diff --git a/CREDITS b/CREDITS
index 2346b09..17899e2 100644
--- a/CREDITS
+++ b/CREDITS
@@ -125,6 +125,7 @@ D: Author of pscan that helps to fix lp/parport bugs
 D: Author of lil (Linux Interrupt Latency benchmark)
 D: Fixed the shm swap deallocation at swapoff time (try_to_unuse message)
 D: VM hacker
+D: NUMA task placement
 D: Various other kernel hacks
 S: Imola 40026
 S: Italy
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index ceb1ff7..8afe64f 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -136,8 +136,6 @@ fault-injection/
 	- dir with docs about the fault injection capabilities infrastructure.
 fb/
 	- directory with info on the frame buffer graphics abstraction layer.
-feature-removal-schedule.txt
-	- list of files and features that are going to be removed.
 filesystems/
 	- info on the vfs and the various filesystems that Linux supports.
 firmware_class/
diff --git a/Documentation/ABI/README b/Documentation/ABI/README
index 9feaf16..1006982 100644
--- a/Documentation/ABI/README
+++ b/Documentation/ABI/README
@@ -36,9 +36,6 @@ The different levels of stability are:
 	the kernel, but are marked to be removed at some later point in
 	time.  The description of the interface will document the reason
 	why it is obsolete and when it can be expected to be removed.
-	The file Documentation/feature-removal-schedule.txt may describe
-	some of these interfaces, giving a schedule for when they will
-	be removed.
 
   removed/
 	This directory contains a list of the old interfaces that have
diff --git a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus
index c2a270b..833fd59 100644
--- a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus
+++ b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus
@@ -8,3 +8,41 @@ Description:	The integer value of this attribute ranges from 0-4.
 		When written, this file sets the number of the startup profile
 		and the mouse activates this profile immediately.
 		Please use actual_profile, it does the same thing.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/firmware_version
+Date:		October 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When read, this file returns the raw integer version number of the
+		firmware reported by the mouse. Using the integer value eases
+		further usage in other programs. To receive the real version
+		number the decimal point has to be shifted 2 positions to the
+		left. E.g. a returned value of 121 means 1.21
+		This file is readonly.
+		Please read binary attribute info which contains firmware version.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_buttons
+Date:		August 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. A profile is split in settings and buttons.
+		profile_buttons holds information about button layout.
+		When read, these files return the respective profile buttons.
+		The returned data is 77 bytes in size.
+		This file is readonly.
+		Write control to select profile and read profile_buttons instead.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_settings
+Date:		August 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. A profile is split in settings and buttons.
+		profile_settings holds information like resolution, sensitivity
+		and light effects.
+		When read, these files return the respective profile settings.
+		The returned data is 43 bytes in size.
+		This file is readonly.
+		Write control to select profile and read profile_settings instead.
+Users:		http://roccat.sourceforge.net
\ No newline at end of file
diff --git a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus
new file mode 100644
index 0000000..4a98e02
--- /dev/null
+++ b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus
@@ -0,0 +1,66 @@
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_cpi
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The integer value of this attribute ranges from 1-4.
+		When read, this attribute returns the number of the active
+		cpi level.
+		This file is readonly.
+		Has never been used. If bookkeeping is done, it's done in userland tools.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_x
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The integer value of this attribute ranges from 1-10.
+		When read, this attribute returns the number of the actual
+		sensitivity in x direction.
+		This file is readonly.
+		Has never been used. If bookkeeping is done, it's done in userland tools.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_y
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The integer value of this attribute ranges from 1-10.
+		When read, this attribute returns the number of the actual
+		sensitivity in y direction.
+		This file is readonly.
+		Has never been used. If bookkeeping is done, it's done in userland tools.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/firmware_version
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When read, this file returns the raw integer version number of the
+		firmware reported by the mouse. Using the integer value eases
+		further usage in other programs. To receive the real version
+		number the decimal point has to be shifted 2 positions to the
+		left. E.g. a returned value of 121 means 1.21
+		This file is readonly.
+		Obsoleted by binary sysfs attribute "info".
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_buttons
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. A profile is split in settings and buttons.
+		profile_buttons holds information about button layout.
+		When read, these files return the respective profile buttons.
+		The returned data is 23 bytes in size.
+		This file is readonly.
+		Write control to select profile and read profile_buttons instead.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_settings
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. A profile is split in settings and buttons.
+		profile_settings holds information like resolution, sensitivity
+		and light effects.
+		When read, these files return the respective profile settings.
+		The returned data is 16 bytes in size.
+		This file is readonly.
+		Write control to select profile and read profile_settings instead.
+Users:		http://roccat.sourceforge.net
diff --git a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra
new file mode 100644
index 0000000..87ac87e
--- /dev/null
+++ b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra
@@ -0,0 +1,73 @@
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_cpi
+Date:		August 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	It is possible to switch the cpi setting of the mouse with the
+		press of a button.
+		When read, this file returns the raw number of the actual cpi
+		setting reported by the mouse. This number has to be further
+		processed to receive the real dpi value.
+
+		VALUE DPI
+		1     400
+		2     800
+		4     1600
+
+		This file is readonly.
+		Has never been used. If bookkeeping is done, it's done in userland tools.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_profile
+Date:		August 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When read, this file returns the number of the actual profile in
+		range 0-4.
+		This file is readonly.
+		Please use binary attribute "settings" which provides this information.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/firmware_version
+Date:		August 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When read, this file returns the raw integer version number of the
+		firmware reported by the mouse. Using the integer value eases
+		further usage in other programs. To receive the real version
+		number the decimal point has to be shifted 2 positions to the
+		left. E.g. a returned value of 138 means 1.38
+		This file is readonly.
+		Please use binary attribute "info" which provides this information.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_buttons
+Date:		August 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. A profile is split in settings and buttons.
+		profile_buttons holds information about button layout.
+		When read, these files return the respective profile buttons.
+		The returned data is 19 bytes in size.
+		This file is readonly.
+		Write control to select profile and read profile_buttons instead.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_settings
+Date:		August 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. A profile is split in settings and buttons.
+		profile_settings holds information like resolution, sensitivity
+		and light effects.
+		When read, these files return the respective profile settings.
+		The returned data is 13 bytes in size.
+		This file is readonly.
+		Write control to select profile and read profile_settings instead.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/startup_profile
+Date:		August 2010
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The integer value of this attribute ranges from 0-4.
+                When read, this attribute returns the number of the profile
+                that's active when the mouse is powered on.
+		This file is readonly.
+		Please use binary attribute "settings" which provides this information.
+Users:		http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/dev-kmsg b/Documentation/ABI/testing/dev-kmsg
index 7e7e07a..bb820be 100644
--- a/Documentation/ABI/testing/dev-kmsg
+++ b/Documentation/ABI/testing/dev-kmsg
@@ -92,7 +92,7 @@ Description:	The /dev/kmsg character device node provides userspace access
 		The flags field carries '-' by default. A 'c' indicates a
 		fragment of a line. All following fragments are flagged with
 		'+'. Note, that these hints about continuation lines are not
-		neccessarily correct, and the stream could be interleaved with
+		necessarily correct, and the stream could be interleaved with
 		unrelated messages, but merging the lines in the output
 		usually produces better human readable results. A similar
 		logic is used internally when messages are printed to the
diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
index 9869466..ec0a38e 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -23,7 +23,7 @@ Description:
 			lsm:	[[subj_user=] [subj_role=] [subj_type=]
 				 [obj_user=] [obj_role=] [obj_type=]]
 
-		base: 	func:= [BPRM_CHECK][FILE_MMAP][FILE_CHECK]
+		base: 	func:= [BPRM_CHECK][FILE_MMAP][FILE_CHECK][MODULE_CHECK]
 			mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
 			fsmagic:= hex value
 			uid:= decimal value
@@ -53,6 +53,7 @@ Description:
 			measure func=BPRM_CHECK
 			measure func=FILE_MMAP mask=MAY_EXEC
 			measure func=FILE_CHECK mask=MAY_READ uid=0
+			measure func=MODULE_CHECK uid=0
 			appraise fowner=0
 
 		The default policy measures all executables in bprm_check,
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index 2f06d40..2e33dc6 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -189,6 +189,14 @@ Description:
 		A computed peak value based on the sum squared magnitude of
 		the underlying value in the specified directions.
 
+What:		/sys/bus/iio/devices/iio:deviceX/in_pressureY_raw
+What:		/sys/bus/iio/devices/iio:deviceX/in_pressure_raw
+KernelVersion:	3.8
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Raw pressure measurement from channel Y. Units after
+		application of scale and offset are kilopascal.
+
 What:		/sys/bus/iio/devices/iio:deviceX/in_accel_offset
 What:		/sys/bus/iio/devices/iio:deviceX/in_accel_x_offset
 What:		/sys/bus/iio/devices/iio:deviceX/in_accel_y_offset
@@ -197,6 +205,8 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_voltageY_offset
 What:		/sys/bus/iio/devices/iio:deviceX/in_voltage_offset
 What:		/sys/bus/iio/devices/iio:deviceX/in_tempY_offset
 What:		/sys/bus/iio/devices/iio:deviceX/in_temp_offset
+What:		/sys/bus/iio/devices/iio:deviceX/in_pressureY_offset
+What:		/sys/bus/iio/devices/iio:deviceX/in_pressure_offset
 KernelVersion:	2.6.35
 Contact:	linux-iio@vger.kernel.org
 Description:
@@ -226,6 +236,8 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_magn_scale
 What:		/sys/bus/iio/devices/iio:deviceX/in_magn_x_scale
 What:		/sys/bus/iio/devices/iio:deviceX/in_magn_y_scale
 What:		/sys/bus/iio/devices/iio:deviceX/in_magn_z_scale
+What:		/sys/bus/iio/devices/iio:deviceX/in_pressureY_scale
+What:		/sys/bus/iio/devices/iio:deviceX/in_pressure_scale
 KernelVersion:	2.6.35
 Contact:	linux-iio@vger.kernel.org
 Description:
@@ -245,6 +257,8 @@ What:		/sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias
 What:		/sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias
 What:		/sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibbias
 What:		/sys/bus/iio/devices/iio:deviceX/in_proximity0_calibbias
+What:		/sys/bus/iio/devices/iio:deviceX/in_pressureY_calibbias
+What:		/sys/bus/iio/devices/iio:deviceX/in_pressure_calibbias
 KernelVersion:	2.6.35
 Contact:	linux-iio@vger.kernel.org
 Description:
@@ -262,6 +276,8 @@ What		/sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibscale
 What		/sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibscale
 what		/sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibscale
 what		/sys/bus/iio/devices/iio:deviceX/in_proximity0_calibscale
+What:		/sys/bus/iio/devices/iio:deviceX/in_pressureY_calibscale
+What:		/sys/bus/iio/devices/iio:deviceX/in_pressure_calibscale
 KernelVersion:	2.6.35
 Contact:	linux-iio@vger.kernel.org
 Description:
@@ -275,6 +291,8 @@ What:		/sys/.../iio:deviceX/in_voltage-voltage_scale_available
 What:		/sys/.../iio:deviceX/out_voltageX_scale_available
 What:		/sys/.../iio:deviceX/out_altvoltageX_scale_available
 What:		/sys/.../iio:deviceX/in_capacitance_scale_available
+What:		/sys/.../iio:deviceX/in_pressure_scale_available
+What:		/sys/.../iio:deviceX/in_pressureY_scale_available
 KernelVersion:	2.6.35
 Contact:	linux-iio@vger.kernel.org
 Description:
@@ -694,6 +712,8 @@ What:		/sys/.../buffer/scan_elements/in_voltageY_en
 What:		/sys/.../buffer/scan_elements/in_voltageY-voltageZ_en
 What:		/sys/.../buffer/scan_elements/in_incli_x_en
 What:		/sys/.../buffer/scan_elements/in_incli_y_en
+What:		/sys/.../buffer/scan_elements/in_pressureY_en
+What:		/sys/.../buffer/scan_elements/in_pressure_en
 KernelVersion:	2.6.37
 Contact:	linux-iio@vger.kernel.org
 Description:
@@ -707,6 +727,8 @@ What:		/sys/.../buffer/scan_elements/in_voltageY_type
 What:		/sys/.../buffer/scan_elements/in_voltage_type
 What:		/sys/.../buffer/scan_elements/in_voltageY_supply_type
 What:		/sys/.../buffer/scan_elements/in_timestamp_type
+What:		/sys/.../buffer/scan_elements/in_pressureY_type
+What:		/sys/.../buffer/scan_elements/in_pressure_type
 KernelVersion:	2.6.37
 Contact:	linux-iio@vger.kernel.org
 Description:
@@ -751,6 +773,8 @@ What:		/sys/.../buffer/scan_elements/in_magn_z_index
 What:		/sys/.../buffer/scan_elements/in_incli_x_index
 What:		/sys/.../buffer/scan_elements/in_incli_y_index
 What:		/sys/.../buffer/scan_elements/in_timestamp_index
+What:		/sys/.../buffer/scan_elements/in_pressureY_index
+What:		/sys/.../buffer/scan_elements/in_pressure_index
 KernelVersion:	2.6.37
 Contact:	linux-iio@vger.kernel.org
 Description:
diff --git a/Documentation/ABI/testing/sysfs-bus-mdio b/Documentation/ABI/testing/sysfs-bus-mdio
new file mode 100644
index 0000000..6349749
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-mdio
@@ -0,0 +1,9 @@
+What:		/sys/bus/mdio_bus/devices/.../phy_id
+Date:		November 2012
+KernelVersion:	3.8
+Contact:	netdev@vger.kernel.org
+Description:
+		This attribute contains the 32-bit PHY Identifier as reported
+		by the device during bus enumeration, encoded in hexadecimal.
+		This ID is used to match the device with the appropriate
+		driver.
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index dff1f48..1ce5ae3 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -222,3 +222,37 @@ Description:
 		satisfied too.  Reading this attribute will show the current
 		value of d3cold_allowed bit.  Writing this attribute will set
 		the value of d3cold_allowed bit.
+
+What:		/sys/bus/pci/devices/.../sriov_totalvfs
+Date:		November 2012
+Contact:	Donald Dutile <ddutile@redhat.com>
+Description:
+		This file appears when a physical PCIe device supports SR-IOV.
+		Userspace applications can read this file to determine the
+		maximum number of Virtual Functions (VFs) a PCIe physical
+		function (PF) can support. Typically, this is the value reported
+		in the PF's SR-IOV extended capability structure's TotalVFs
+		element.  Drivers have the ability at probe time to reduce the
+		value read from this file via the pci_sriov_set_totalvfs()
+		function.
+
+What:		/sys/bus/pci/devices/.../sriov_numvfs
+Date:		November 2012
+Contact:	Donald Dutile <ddutile@redhat.com>
+Description:
+		This file appears when a physical PCIe device supports SR-IOV.
+		Userspace applications can read and write to this file to
+		determine and control the enablement or disablement of Virtual
+		Functions (VFs) on the physical function (PF). A read of this
+		file will return the number of VFs that are enabled on this PF.
+		A number written to this file will enable the specified
+		number of VFs. A userspace application would typically read the
+		file and check that the value is zero, and then write the number
+		of VFs that should be enabled on the PF; the value written
+		should be less than or equal to the value in the sriov_totalvfs
+		file. A userspace application wanting to disable the VFs would
+		write a zero to this file. The core ensures that valid values
+		are written to this file, and returns errors when values are not
+		valid.  For example, writing a 2 to this file when sriov_numvfs
+		is not 0 and not 2 already will return an error. Writing a 10
+		when the value of sriov_totalvfs is 8 will return an error.
diff --git a/Documentation/ABI/testing/sysfs-class-net-batman-adv b/Documentation/ABI/testing/sysfs-class-net-batman-adv
index 38dd762..bdc0070 100644
--- a/Documentation/ABI/testing/sysfs-class-net-batman-adv
+++ b/Documentation/ABI/testing/sysfs-class-net-batman-adv
@@ -1,4 +1,10 @@
 
+What:           /sys/class/net/<iface>/batman-adv/iface_status
+Date:           May 2010
+Contact:        Marek Lindner <lindner_marek@yahoo.de>
+Description:
+                Indicates the status of <iface> as it is seen by batman.
+
 What:           /sys/class/net/<iface>/batman-adv/mesh_iface
 Date:           May 2010
 Contact:        Marek Lindner <lindner_marek@yahoo.de>
@@ -7,8 +13,3 @@ Description:
                 displays the batman mesh interface this <iface>
                 currently is associated with.
 
-What:           /sys/class/net/<iface>/batman-adv/iface_status
-Date:           May 2010
-Contact:        Marek Lindner <lindner_marek@yahoo.de>
-Description:
-                Indicates the status of <iface> as it is seen by batman.
diff --git a/Documentation/ABI/testing/sysfs-class-net-grcan b/Documentation/ABI/testing/sysfs-class-net-grcan
new file mode 100644
index 0000000..f418c92
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-net-grcan
@@ -0,0 +1,35 @@
+
+What:		/sys/class/net/<iface>/grcan/enable0
+Date:		October 2012
+KernelVersion:	3.8
+Contact:	Andreas Larsson <andreas@gaisler.com>
+Description:
+		Hardware configuration of physical interface 0. This file reads
+		and writes the "Enable 0" bit of the configuration register.
+		Possible values: 0 or 1. See the GRCAN chapter of the GRLIB IP
+		core library documentation for details. The default value is 0
+		or set by the module parameter grcan.enable0 and can be read at
+		/sys/module/grcan/parameters/enable0.
+
+What:		/sys/class/net/<iface>/grcan/enable1
+Date:		October 2012
+KernelVersion:	3.8
+Contact:	Andreas Larsson <andreas@gaisler.com>
+Description:
+		Hardware configuration of physical interface 1. This file reads
+		and writes the "Enable 1" bit of the configuration register.
+		Possible values: 0 or 1. See the GRCAN chapter of the GRLIB IP
+		core library documentation for details. The default value is 0
+		or set by the module parameter grcan.enable1 and can be read at
+		/sys/module/grcan/parameters/enable1.
+
+What:		/sys/class/net/<iface>/grcan/select
+Date:		October 2012
+KernelVersion:	3.8
+Contact:	Andreas Larsson <andreas@gaisler.com>
+Description:
+		Configuration of which physical interface to be used. Possible
+		values: 0 or 1. See the GRCAN chapter of the GRLIB IP core
+		library documentation for details. The default value is 0 or is
+		set by the module parameter grcan.select and can be read at
+		/sys/module/grcan/parameters/select.
diff --git a/Documentation/ABI/testing/sysfs-class-net-mesh b/Documentation/ABI/testing/sysfs-class-net-mesh
index c81fe89..bc41da6 100644
--- a/Documentation/ABI/testing/sysfs-class-net-mesh
+++ b/Documentation/ABI/testing/sysfs-class-net-mesh
@@ -6,6 +6,14 @@ Description:
                 Indicates whether the batman protocol messages of the
                 mesh <mesh_iface> shall be aggregated or not.
 
+What:           /sys/class/net/<mesh_iface>/mesh/ap_isolation
+Date:           May 2011
+Contact:        Antonio Quartulli <ordex@autistici.org>
+Description:
+                Indicates whether the data traffic going from a
+                wireless client to another wireless client will be
+                silently dropped.
+
 What:           /sys/class/net/<mesh_iface>/mesh/bonding
 Date:           June 2010
 Contact:        Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
@@ -31,14 +39,6 @@ Description:
                 mesh will be fragmented or silently discarded if the
                 packet size exceeds the outgoing interface MTU.
 
-What:		/sys/class/net/<mesh_iface>/mesh/ap_isolation
-Date:		May 2011
-Contact:	Antonio Quartulli <ordex@autistici.org>
-Description:
-		Indicates whether the data traffic going from a
-		wireless client to another wireless client will be
-		silently dropped.
-
 What:           /sys/class/net/<mesh_iface>/mesh/gw_bandwidth
 Date:           October 2010
 Contact:        Marek Lindner <lindner_marek@yahoo.de>
@@ -60,6 +60,13 @@ Description:
                 Defines the selection criteria this node will use
                 to choose a gateway if gw_mode was set to 'client'.
 
+What:           /sys/class/net/<mesh_iface>/mesh/hop_penalty
+Date:           Oct 2010
+Contact:        Linus Lüssing <linus.luessing@web.de>
+Description:
+                Defines the penalty which will be applied to an
+                originator message's tq-field on every hop.
+
 What:           /sys/class/net/<mesh_iface>/mesh/orig_interval
 Date:           May 2010
 Contact:        Marek Lindner <lindner_marek@yahoo.de>
@@ -67,19 +74,12 @@ Description:
                 Defines the interval in milliseconds in which batman
                 sends its protocol messages.
 
-What:           /sys/class/net/<mesh_iface>/mesh/hop_penalty
-Date:           Oct 2010
-Contact:        Linus Lüssing <linus.luessing@web.de>
-Description:
-		Defines the penalty which will be applied to an
-		originator message's tq-field on every hop.
-
-What:		/sys/class/net/<mesh_iface>/mesh/routing_algo
-Date:		Dec 2011
-Contact:	Marek Lindner <lindner_marek@yahoo.de>
+What:           /sys/class/net/<mesh_iface>/mesh/routing_algo
+Date:           Dec 2011
+Contact:        Marek Lindner <lindner_marek@yahoo.de>
 Description:
-		Defines the routing procotol this mesh instance
-		uses to find the optimal paths through the mesh.
+                Defines the routing procotol this mesh instance
+                uses to find the optimal paths through the mesh.
 
 What:           /sys/class/net/<mesh_iface>/mesh/vis_mode
 Date:           May 2010
diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power
index 45000f0..9d43e76 100644
--- a/Documentation/ABI/testing/sysfs-devices-power
+++ b/Documentation/ABI/testing/sysfs-devices-power
@@ -164,7 +164,7 @@ Contact:	Rafael J. Wysocki <rjw@sisk.pl>
 Description:
 		The /sys/devices/.../wakeup_prevent_sleep_time_ms attribute
 		contains the total time the device has been preventing
-		opportunistic transitions to sleep states from occuring.
+		opportunistic transitions to sleep states from occurring.
 		This attribute is read-only.  If the device is not enabled to
 		wake up the system from sleep states, this attribute is not
 		present.
@@ -204,3 +204,34 @@ Description:
 
 		This attribute has no effect on system-wide suspend/resume and
 		hibernation.
+
+What:		/sys/devices/.../power/pm_qos_no_power_off
+Date:		September 2012
+Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+		The /sys/devices/.../power/pm_qos_no_power_off attribute
+		is used for manipulating the PM QoS "no power off" flag.  If
+		set, this flag indicates to the kernel that power should not
+		be removed entirely from the device.
+
+		Not all drivers support this attribute.  If it isn't supported,
+		it is not present.
+
+		This attribute has no effect on system-wide suspend/resume and
+		hibernation.
+
+What:		/sys/devices/.../power/pm_qos_remote_wakeup
+Date:		September 2012
+Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+		The /sys/devices/.../power/pm_qos_remote_wakeup attribute
+		is used for manipulating the PM QoS "remote wakeup required"
+		flag.  If set, this flag indicates to the kernel that the
+		device is a source of user events that have to be signaled from
+		its low-power states.
+
+		Not all drivers support this attribute.  If it isn't supported,
+		it is not present.
+
+		This attribute has no effect on system-wide suspend/resume and
+		hibernation.
diff --git a/Documentation/ABI/testing/sysfs-devices-sun b/Documentation/ABI/testing/sysfs-devices-sun
new file mode 100644
index 0000000..86be984
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-sun
@@ -0,0 +1,14 @@
+Whatt:		/sys/devices/.../sun
+Date:		October 2012
+Contact:	Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
+Description:
+		The file contains a Slot-unique ID which provided by the _SUN
+		method in the ACPI namespace. The value is written in Advanced
+		Configuration and Power Interface Specification as follows:
+
+		"The _SUN value is required to be unique among the slots of
+		the same type. It is also recommended that this number match
+		the slot number printed on the physical slot whenever possible."
+
+		So reading the sysfs file, we can identify a physical position
+		of the slot in the system.
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku b/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku
index 189dc43..9eca5a1 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku
@@ -117,6 +117,14 @@ Description:	When written, this file lets one store macros with max 500
 		which profile and key to read.
 Users:		http://roccat.sourceforge.net
 
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/reset
+Date:		November 2012
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When written, this file lets one reset the device.
+		The data has to be 3 bytes long.
+		This file is writeonly.
+Users:		http://roccat.sourceforge.net
+
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/control
 Date:		June 2011
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
index 65e6e5d..7bd776f 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
@@ -9,15 +9,12 @@ Description:	The integer value of this attribute ranges from 0-4.
 		and the mouse activates this profile immediately.
 Users:		http://roccat.sourceforge.net
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/firmware_version
-Date:		October 2010
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/info
+Date:		November 2012
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:	When read, this file returns the raw integer version number of the
-		firmware reported by the mouse. Using the integer value eases
-		further usage in other programs. To receive the real version
-		number the decimal point has to be shifted 2 positions to the
-		left. E.g. a returned value of 121 means 1.21
-		This file is readonly.
+Description:	When read, this file returns general data like firmware version.
+		When written, the device can be reset.
+		The data is 8 bytes long.
 Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/macro
@@ -42,18 +39,8 @@ Description:	The mouse can store 5 profiles which can be switched by the
 		The mouse will reject invalid data.
 		Which profile to write is determined by the profile number
 		contained in the data.
-		This file is writeonly.
-Users:		http://roccat.sourceforge.net
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_buttons
-Date:		August 2010
-Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:	The mouse can store 5 profiles which can be switched by the
-		press of a button. A profile is split in settings and buttons.
-		profile_buttons holds information about button layout.
-		When read, these files return the respective profile buttons.
-		The returned data is 77 bytes in size.
-		This file is readonly.
+		Before reading this file, control has to be written to select
+		which profile to read.
 Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_settings
@@ -68,19 +55,8 @@ Description:	The mouse can store 5 profiles which can be switched by the
 		The mouse will reject invalid data.
 		Which profile to write is determined by the profile number
 		contained in the data.
-		This file is writeonly.
-Users:		http://roccat.sourceforge.net
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_settings
-Date:		August 2010
-Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:	The mouse can store 5 profiles which can be switched by the
-		press of a button. A profile is split in settings and buttons.
-		profile_settings holds information like resolution, sensitivity
-		and light effects.
-		When read, these files return the respective profile settings.
-		The returned data is 43 bytes in size.
-		This file is readonly.
+		Before reading this file, control has to be written to select
+		which profile to read.
 Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/sensor
@@ -104,9 +80,9 @@ What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-
 Date:		October 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	When written a calibration process for the tracking control unit
-		can be initiated/cancelled.
-		The data has to be 3 bytes long.
-		This file is writeonly.
+		can be initiated/cancelled. Also lets one read/write sensor
+		registers.
+		The data has to be 4 bytes long.
 Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu_image
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus
index 20f937c..a10404f 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus
@@ -1,12 +1,3 @@
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_cpi
-Date:		January 2011
-Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:	The integer value of this attribute ranges from 1-4.
-		When read, this attribute returns the number of the active
-		cpi level.
-		This file is readonly.
-Users:		http://roccat.sourceforge.net
-
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_profile
 Date:		January 2011
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
@@ -18,33 +9,12 @@ Description:	The integer value of this attribute ranges from 0-4.
 		active when the mouse is powered on.
 Users:		http://roccat.sourceforge.net
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_x
-Date:		January 2011
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/info
+Date:		November 2012
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:	The integer value of this attribute ranges from 1-10.
-		When read, this attribute returns the number of the actual
-		sensitivity in x direction.
-		This file is readonly.
-Users:		http://roccat.sourceforge.net
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_y
-Date:		January 2011
-Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:	The integer value of this attribute ranges from 1-10.
-		When read, this attribute returns the number of the actual
-		sensitivity in y direction.
-		This file is readonly.
-Users:		http://roccat.sourceforge.net
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/firmware_version
-Date:		January 2011
-Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:	When read, this file returns the raw integer version number of the
-		firmware reported by the mouse. Using the integer value eases
-		further usage in other programs. To receive the real version
-		number the decimal point has to be shifted 2 positions to the
-		left. E.g. a returned value of 121 means 1.21
-		This file is readonly.
+Description:	When read, this file returns general data like firmware version.
+		When written, the device can be reset.
+		The data is 6 bytes long.
 Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_buttons
@@ -58,18 +28,8 @@ Description:	The mouse can store 5 profiles which can be switched by the
 		The mouse will reject invalid data.
 		Which profile to write is determined by the profile number
 		contained in the data.
-		This file is writeonly.
-Users:		http://roccat.sourceforge.net
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_buttons
-Date:		January 2011
-Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:	The mouse can store 5 profiles which can be switched by the
-		press of a button. A profile is split in settings and buttons.
-		profile_buttons holds information about button layout.
-		When read, these files return the respective profile buttons.
-		The returned data is 23 bytes in size.
-		This file is readonly.
+		Before reading this file, control has to be written to select
+		which profile to read.
 Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_settings
@@ -84,17 +44,6 @@ Description:	The mouse can store 5 profiles which can be switched by the
 		The mouse will reject invalid data.
 		Which profile to write is determined by the profile number
 		contained in the data.
-		This file is writeonly.
-Users:		http://roccat.sourceforge.net
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_settings
-Date:		January 2011
-Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:	The mouse can store 5 profiles which can be switched by the
-		press of a button. A profile is split in settings and buttons.
-		profile_settings holds information like resolution, sensitivity
-		and light effects.
-		When read, these files return the respective profile settings.
-		The returned data is 16 bytes in size.
-		This file is readonly.
+		Before reading this file, control has to be written to select
+		which profile to read.
 Users:		http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-lua b/Documentation/ABI/testing/sysfs-driver-hid-roccat-lua
new file mode 100644
index 0000000..31c6c4c
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-lua
@@ -0,0 +1,7 @@
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/control
+Date:		October 2012
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When written, cpi, button and light settings can be configured.
+		When read, actual cpi setting and sensor data are returned.
+		The data has to be 8 bytes long.
+Users:		http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra b/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
index 3f8de50..9fa9de3 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
@@ -1,37 +1,9 @@
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_cpi
-Date:		August 2010
-Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:	It is possible to switch the cpi setting of the mouse with the
-		press of a button.
-		When read, this file returns the raw number of the actual cpi
-		setting reported by the mouse. This number has to be further
-		processed to receive the real dpi value.
-
-		VALUE DPI
-		1     400
-		2     800
-		4     1600
-
-		This file is readonly.
-Users:		http://roccat.sourceforge.net
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_profile
-Date:		August 2010
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/info
+Date:		November 2012
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:	When read, this file returns the number of the actual profile in
-		range 0-4.
-		This file is readonly.
-Users:		http://roccat.sourceforge.net
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/firmware_version
-Date:		August 2010
-Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:	When read, this file returns the raw integer version number of the
-		firmware reported by the mouse. Using the integer value eases
-		further usage in other programs. To receive the real version
-		number the decimal point has to be shifted 2 positions to the
-		left. E.g. a returned value of 138 means 1.38
-		This file is readonly.
+Description:	When read, this file returns general data like firmware version.
+		When written, the device can be reset.
+		The data is 6 bytes long.
 Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_settings
@@ -46,19 +18,8 @@ Description:	The mouse can store 5 profiles which can be switched by the
 		The mouse will reject invalid data.
 		Which profile to write is determined by the profile number
 		contained in the data.
-		This file is writeonly.
-Users:		http://roccat.sourceforge.net
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_settings
-Date:		August 2010
-Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:	The mouse can store 5 profiles which can be switched by the
-		press of a button. A profile is split in settings and buttons.
-		profile_settings holds information like resolution, sensitivity
-		and light effects.
-		When read, these files return the respective profile settings.
-		The returned data is 13 bytes in size.
-		This file is readonly.
+		Before reading this file, control has to be written to select
+		which profile to read.
 Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_buttons
@@ -72,27 +33,8 @@ Description:	The mouse can store 5 profiles which can be switched by the
 		The mouse will reject invalid data.
 		Which profile to write is determined by the profile number
 		contained in the data.
-		This file is writeonly.
-Users:		http://roccat.sourceforge.net
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_buttons
-Date:		August 2010
-Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:	The mouse can store 5 profiles which can be switched by the
-		press of a button. A profile is split in settings and buttons.
-		profile_buttons holds information about button layout.
-		When read, these files return the respective profile buttons.
-		The returned data is 19 bytes in size.
-		This file is readonly.
-Users:		http://roccat.sourceforge.net
-
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/startup_profile
-Date:		August 2010
-Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:	The integer value of this attribute ranges from 0-4.
-                When read, this attribute returns the number of the profile
-                that's active when the mouse is powered on.
-		This file is readonly.
+		Before reading this file, control has to be written to select
+		which profile to read.
 Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/settings
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu b/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu
index b42922c..f1e02a9 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu
@@ -40,8 +40,8 @@ What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-
 Date:		Mai 2012
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	When read, this file returns general data like firmware version.
+		When written, the device can be reset.
 		The data is 8 bytes long.
-		This file is readonly.
 Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/macro
@@ -74,4 +74,3 @@ Description:	The mouse has a Avago ADNS-3090 sensor.
 		This file allows reading and writing of the mouse sensors registers.
 		The data has to be 4 bytes long.
 Users:		http://roccat.sourceforge.net
-
diff --git a/Documentation/ABI/testing/sysfs-driver-ppi b/Documentation/ABI/testing/sysfs-driver-ppi
index 97a003e..7d1435b 100644
--- a/Documentation/ABI/testing/sysfs-driver-ppi
+++ b/Documentation/ABI/testing/sysfs-driver-ppi
@@ -5,7 +5,7 @@ Contact:	xiaoyan.zhang@intel.com
 Description:
 		This folder includes the attributes related with PPI (Physical
 		Presence Interface). Only if TPM is supported by BIOS, this
-		folder makes sence. The folder path can be got by command
+		folder makes sense. The folder path can be got by command
 		'find /sys/ -name 'pcrs''. For the detail information of PPI,
 		please refer to the PPI specification from
 		http://www.trustedcomputinggroup.org/
diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty
index 0c43015..ad22fb0 100644
--- a/Documentation/ABI/testing/sysfs-tty
+++ b/Documentation/ABI/testing/sysfs-tty
@@ -26,3 +26,115 @@ Description:
 		 UART port in serial_core, that is bound to TTY like ttyS0.
 		 uartclk = 16 * baud_base
 
+		 These sysfs values expose the TIOCGSERIAL interface via
+		 sysfs rather than via ioctls.
+
+What:		/sys/class/tty/ttyS0/type
+Date:		October 2012
+Contact:	Alan Cox <alan@linux.intel.com>
+Description:
+		 Shows the current tty type for this port.
+
+		 These sysfs values expose the TIOCGSERIAL interface via
+		 sysfs rather than via ioctls.
+
+What:		/sys/class/tty/ttyS0/line
+Date:		October 2012
+Contact:	Alan Cox <alan@linux.intel.com>
+Description:
+		 Shows the current tty line number for this port.
+
+		 These sysfs values expose the TIOCGSERIAL interface via
+		 sysfs rather than via ioctls.
+
+What:		/sys/class/tty/ttyS0/port
+Date:		October 2012
+Contact:	Alan Cox <alan@linux.intel.com>
+Description:
+		 Shows the current tty port I/O address for this port.
+
+		 These sysfs values expose the TIOCGSERIAL interface via
+		 sysfs rather than via ioctls.
+
+What:		/sys/class/tty/ttyS0/irq
+Date:		October 2012
+Contact:	Alan Cox <alan@linux.intel.com>
+Description:
+		 Shows the current primary interrupt for this port.
+
+		 These sysfs values expose the TIOCGSERIAL interface via
+		 sysfs rather than via ioctls.
+
+What:		/sys/class/tty/ttyS0/flags
+Date:		October 2012
+Contact:	Alan Cox <alan@linux.intel.com>
+Description:
+		 Show the tty port status flags for this port.
+
+		 These sysfs values expose the TIOCGSERIAL interface via
+		 sysfs rather than via ioctls.
+
+What:		/sys/class/tty/ttyS0/xmit_fifo_size
+Date:		October 2012
+Contact:	Alan Cox <alan@linux.intel.com>
+Description:
+		 Show the transmit FIFO size for this port.
+
+		 These sysfs values expose the TIOCGSERIAL interface via
+		 sysfs rather than via ioctls.
+
+What:		/sys/class/tty/ttyS0/close_delay
+Date:		October 2012
+Contact:	Alan Cox <alan@linux.intel.com>
+Description:
+		 Show the closing delay time for this port in ms.
+
+		 These sysfs values expose the TIOCGSERIAL interface via
+		 sysfs rather than via ioctls.
+
+What:		/sys/class/tty/ttyS0/closing_wait
+Date:		October 2012
+Contact:	Alan Cox <alan@linux.intel.com>
+Description:
+		 Show the close wait time for this port in ms.
+
+		 These sysfs values expose the TIOCGSERIAL interface via
+		 sysfs rather than via ioctls.
+
+What:		/sys/class/tty/ttyS0/custom_divisor
+Date:		October 2012
+Contact:	Alan Cox <alan@linux.intel.com>
+Description:
+		 Show the custom divisor if any that is set on this port.
+
+		 These sysfs values expose the TIOCGSERIAL interface via
+		 sysfs rather than via ioctls.
+
+What:		/sys/class/tty/ttyS0/io_type
+Date:		October 2012
+Contact:	Alan Cox <alan@linux.intel.com>
+Description:
+		 Show the I/O type that is to be used with the iomem base
+		 address.
+
+		 These sysfs values expose the TIOCGSERIAL interface via
+		 sysfs rather than via ioctls.
+
+What:		/sys/class/tty/ttyS0/iomem_base
+Date:		October 2012
+Contact:	Alan Cox <alan@linux.intel.com>
+Description:
+		 The I/O memory base for this port.
+
+		 These sysfs values expose the TIOCGSERIAL interface via
+		 sysfs rather than via ioctls.
+
+What:		/sys/class/tty/ttyS0/iomem_reg_shift
+Date:		October 2012
+Contact:	Alan Cox <alan@linux.intel.com>
+Description:
+		 Show the register shift indicating the spacing to be used
+		 for accesses on this iomem address.
+
+		 These sysfs values expose the TIOCGSERIAL interface via
+		 sysfs rather than via ioctls.
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index 495e5ba..e00b8f0 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -546,15 +546,7 @@ config AUDIT
 	  logging of avc messages output).  Does not do system-call
 	  auditing without CONFIG_AUDITSYSCALL.
 
-Features that might still be considered unstable should be defined as
-dependent on "EXPERIMENTAL":
-
-config SLUB
-	depends on EXPERIMENTAL && !ARCH_USES_SLAB_PAGE_STRUCT
-	bool "SLUB (Unqueued Allocator)"
-	...
-
-while seriously dangerous features (such as write support for certain
+Seriously dangerous features (such as write support for certain
 filesystems) should advertise this prominently in their prompt string:
 
 config ADFS_FS_RW
diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt
index a0b6250..14129f1 100644
--- a/Documentation/DMA-API-HOWTO.txt
+++ b/Documentation/DMA-API-HOWTO.txt
@@ -468,11 +468,47 @@ To map a single region, you do:
 	size_t size = buffer->len;
 
 	dma_handle = dma_map_single(dev, addr, size, direction);
+	if (dma_mapping_error(dma_handle)) {
+		/*
+		 * reduce current DMA mapping usage,
+		 * delay and try again later or
+		 * reset driver.
+		 */
+		goto map_error_handling;
+	}
 
 and to unmap it:
 
 	dma_unmap_single(dev, dma_handle, size, direction);
 
+You should call dma_mapping_error() as dma_map_single() could fail and return
+error. Not all dma implementations support dma_mapping_error() interface.
+However, it is a good practice to call dma_mapping_error() interface, which
+will invoke the generic mapping error check interface. Doing so will ensure
+that the mapping code will work correctly on all dma implementations without
+any dependency on the specifics of the underlying implementation. Using the
+returned address without checking for errors could result in failures ranging
+from panics to silent data corruption. A couple of examples of incorrect ways
+to check for errors that make assumptions about the underlying dma
+implementation are as follows and these are applicable to dma_map_page() as
+well.
+
+Incorrect example 1:
+	dma_addr_t dma_handle;
+
+	dma_handle = dma_map_single(dev, addr, size, direction);
+	if ((dma_handle & 0xffff != 0) || (dma_handle >= 0x1000000)) {
+		goto map_error;
+	}
+
+Incorrect example 2:
+	dma_addr_t dma_handle;
+
+	dma_handle = dma_map_single(dev, addr, size, direction);
+	if (dma_handle == DMA_ERROR_CODE) {
+		goto map_error;
+	}
+
 You should call dma_unmap_single when the DMA activity is finished, e.g.
 from the interrupt which told you that the DMA transfer is done.
 
@@ -489,6 +525,14 @@ Specifically:
 	size_t size = buffer->len;
 
 	dma_handle = dma_map_page(dev, page, offset, size, direction);
+	if (dma_mapping_error(dma_handle)) {
+		/*
+		 * reduce current DMA mapping usage,
+		 * delay and try again later or
+		 * reset driver.
+		 */
+		goto map_error_handling;
+	}
 
 	...
 
@@ -496,6 +540,12 @@ Specifically:
 
 Here, "offset" means byte offset within the given page.
 
+You should call dma_mapping_error() as dma_map_page() could fail and return
+error as outlined under the dma_map_single() discussion.
+
+You should call dma_unmap_page when the DMA activity is finished, e.g.
+from the interrupt which told you that the DMA transfer is done.
+
 With scatterlists, you map a region gathered from several regions by:
 
 	int i, count = dma_map_sg(dev, sglist, nents, direction);
@@ -578,6 +628,14 @@ to use the dma_sync_*() interfaces.
 		dma_addr_t mapping;
 
 		mapping = dma_map_single(cp->dev, buffer, len, DMA_FROM_DEVICE);
+		if (dma_mapping_error(dma_handle)) {
+			/*
+			 * reduce current DMA mapping usage,
+			 * delay and try again later or
+			 * reset driver.
+			 */
+			goto map_error_handling;
+		}
 
 		cp->rx_buf = buffer;
 		cp->rx_len = len;
@@ -658,6 +716,75 @@ failure can be determined by:
 		 * delay and try again later or
 		 * reset driver.
 		 */
+		goto map_error_handling;
+	}
+
+- unmap pages that are already mapped, when mapping error occurs in the middle
+  of a multiple page mapping attempt. These example are applicable to
+  dma_map_page() as well.
+
+Example 1:
+	dma_addr_t dma_handle1;
+	dma_addr_t dma_handle2;
+
+	dma_handle1 = dma_map_single(dev, addr, size, direction);
+	if (dma_mapping_error(dev, dma_handle1)) {
+		/*
+		 * reduce current DMA mapping usage,
+		 * delay and try again later or
+		 * reset driver.
+		 */
+		goto map_error_handling1;
+	}
+	dma_handle2 = dma_map_single(dev, addr, size, direction);
+	if (dma_mapping_error(dev, dma_handle2)) {
+		/*
+		 * reduce current DMA mapping usage,
+		 * delay and try again later or
+		 * reset driver.
+		 */
+		goto map_error_handling2;
+	}
+
+	...
+
+	map_error_handling2:
+		dma_unmap_single(dma_handle1);
+	map_error_handling1:
+
+Example 2: (if buffers are allocated in a loop, unmap all mapped buffers when
+	    mapping error is detected in the middle)
+
+	dma_addr_t dma_addr;
+	dma_addr_t array[DMA_BUFFERS];
+	int save_index = 0;
+
+	for (i = 0; i < DMA_BUFFERS; i++) {
+
+		...
+
+		dma_addr = dma_map_single(dev, addr, size, direction);
+		if (dma_mapping_error(dev, dma_addr)) {
+			/*
+			 * reduce current DMA mapping usage,
+			 * delay and try again later or
+			 * reset driver.
+			 */
+			goto map_error_handling;
+		}
+		array[i].dma_addr = dma_addr;
+		save_index++;
+	}
+
+	...
+
+	map_error_handling:
+
+	for (i = 0; i < save_index; i++) {
+
+		...
+
+		dma_unmap_single(array[i].dma_addr);
 	}
 
 Networking drivers must call dev_kfree_skb to free the socket buffer
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 66bd97a..78a6c56 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -678,3 +678,15 @@ out of dma_debug_entries. These entries are preallocated at boot. The number
 of preallocated entries is defined per architecture. If it is too low for you
 boot with 'dma_debug_entries=<your_desired_number>' to overwrite the
 architectural default.
+
+void debug_dmap_mapping_error(struct device *dev, dma_addr_t dma_addr);
+
+dma-debug interface debug_dma_mapping_error() to debug drivers that fail
+to check dma mapping errors on addresses returned by dma_map_single() and
+dma_map_page() interfaces. This interface clears a flag set by
+debug_dma_map_page() to indicate that dma_mapping_error() has been called by
+the driver. When driver does unmap, debug_dma_unmap() checks the flag and if
+this flag is still set, prints warning message that includes call trace that
+leads up to the unmap. This interface can be called from dma_mapping_error()
+routines to enable dma mapping error check debugging.
+
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index b030052..4ee2304 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -1141,23 +1141,13 @@ int max_width, max_height;</synopsis>
             the <methodname>page_flip</methodname> operation will be called with a
             non-NULL <parameter>event</parameter> argument pointing to a
             <structname>drm_pending_vblank_event</structname> instance. Upon page
-            flip completion the driver must fill the
-            <parameter>event</parameter>::<structfield>event</structfield>
-            <structfield>sequence</structfield>, <structfield>tv_sec</structfield>
-            and <structfield>tv_usec</structfield> fields with the associated
-            vertical blanking count and timestamp, add the event to the
-            <parameter>drm_file</parameter> list of events to be signaled, and wake
-            up any waiting process. This can be performed with
+            flip completion the driver must call <methodname>drm_send_vblank_event</methodname>
+            to fill in the event and send to wake up any waiting processes.
+            This can be performed with
             <programlisting><![CDATA[
-            struct timeval now;
-
-            event->event.sequence = drm_vblank_count_and_time(..., &now);
-            event->event.tv_sec = now.tv_sec;
-            event->event.tv_usec = now.tv_usec;
-
             spin_lock_irqsave(&dev->event_lock, flags);
-            list_add_tail(&event->base.link, &event->base.file_priv->event_list);
-            wake_up_interruptible(&event->base.file_priv->event_wait);
+            ...
+            drm_send_vblank_event(dev, pipe, event);
             spin_unlock_irqrestore(&dev->event_lock, flags);
             ]]></programlisting>
           </para>
@@ -1621,10 +1611,10 @@ void intel_crt_init(struct drm_device *dev)
     </sect2>
   </sect1>
 
-  <!-- Internals: mid-layer helper functions -->
+  <!-- Internals: kms helper functions -->
 
   <sect1>
-    <title>Mid-layer Helper Functions</title>
+    <title>Mode Setting Helper Functions</title>
     <para>
       The CRTC, encoder and connector functions provided by the drivers
       implement the DRM API. They're called by the DRM core and ioctl handlers
@@ -2106,6 +2096,21 @@ void intel_crt_init(struct drm_device *dev)
         </listitem>
       </itemizedlist>
     </sect2>
+    <sect2>
+      <title>Modeset Helper Functions Reference</title>
+!Edrivers/gpu/drm/drm_crtc_helper.c
+    </sect2>
+    <sect2>
+      <title>fbdev Helper Functions Reference</title>
+!Pdrivers/gpu/drm/drm_fb_helper.c fbdev helpers
+!Edrivers/gpu/drm/drm_fb_helper.c
+    </sect2>
+    <sect2>
+      <title>Display Port Helper Functions Reference</title>
+!Pdrivers/gpu/drm/drm_dp_helper.c dp helpers
+!Iinclude/drm/drm_dp_helper.h
+!Edrivers/gpu/drm/drm_dp_helper.c
+    </sect2>
   </sect1>
 
   <!-- Internals: vertical blanking -->
diff --git a/Documentation/DocBook/gadget.tmpl b/Documentation/DocBook/gadget.tmpl
index 6ef2f00..4017f14 100644
--- a/Documentation/DocBook/gadget.tmpl
+++ b/Documentation/DocBook/gadget.tmpl
@@ -671,7 +671,7 @@ than a kernel driver.
 <para>There's a USB Mass Storage class driver, which provides
 a different solution for interoperability with systems such
 as MS-Windows and MacOS.
-That <emphasis>File-backed Storage</emphasis> driver uses a
+That <emphasis>Mass Storage</emphasis> driver uses a
 file or block device as backing store for a drive,
 like the <filename>loop</filename> driver.
 The USB host uses the BBB, CB, or CBI versions of the mass
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 00687ee..f75ab4c 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -58,6 +58,9 @@
 
      <sect1><title>String Conversions</title>
 !Elib/vsprintf.c
+!Finclude/linux/kernel.h kstrtol
+!Finclude/linux/kernel.h kstrtoul
+!Elib/kstrtox.c
      </sect1>
      <sect1><title>String Manipulation</title>
 <!-- All functions are exported at now
diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl
index eee7142..22e0bd1 100644
--- a/Documentation/DocBook/kernel-hacking.tmpl
+++ b/Documentation/DocBook/kernel-hacking.tmpl
@@ -1185,13 +1185,6 @@ static struct block_device_operations opt_fops = {
     </para>
 
     <para>
-     You may well want to make your CONFIG option only visible if
-     <symbol>CONFIG_EXPERIMENTAL</symbol> is enabled: this serves as a
-     warning to users.  There many other fancy things you can do: see
-     the various <filename>Kconfig</filename> files for ideas.
-    </para>
-
-    <para>
      In your description of the option, make sure you address both the
      expert user and the user who knows nothing about your feature.  Mention
      incompatibilities and issues here.  <emphasis> Definitely
diff --git a/Documentation/DocBook/kgdb.tmpl b/Documentation/DocBook/kgdb.tmpl
index 4ee4ba3..f77358f 100644
--- a/Documentation/DocBook/kgdb.tmpl
+++ b/Documentation/DocBook/kgdb.tmpl
@@ -94,10 +94,8 @@
   <sect1 id="CompileKGDB">
     <title>Kernel config options for kgdb</title>
     <para>
-    To enable <symbol>CONFIG_KGDB</symbol> you should first turn on
-    "Prompt for development and/or incomplete code/drivers"
-    (CONFIG_EXPERIMENTAL) in  "General setup", then under the
-    "Kernel debugging" select "KGDB: kernel debugger".
+    To enable <symbol>CONFIG_KGDB</symbol> you should look under
+    "Kernel debugging" and select "KGDB: kernel debugger".
     </para>
     <para>
     While it is not a hard requirement that you have symbols in your
diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml
index 4fdf6b5..3dd9e78 100644
--- a/Documentation/DocBook/media/v4l/compat.xml
+++ b/Documentation/DocBook/media/v4l/compat.xml
@@ -2586,6 +2586,13 @@ ioctls.</para>
 	  <para>Vendor and device specific media bus pixel formats.
 	    <xref linkend="v4l2-mbus-vendor-spec-fmts" />.</para>
         </listitem>
+        <listitem>
+	  <para>Importing DMABUF file descriptors as a new IO method described
+	  in <xref linkend="dmabuf" />.</para>
+        </listitem>
+        <listitem>
+	  <para>Exporting DMABUF files using &VIDIOC-EXPBUF; ioctl.</para>
+        </listitem>
       </itemizedlist>
     </section>
 
diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
index b5d1cbd..388a340 100644
--- a/Documentation/DocBook/media/v4l/io.xml
+++ b/Documentation/DocBook/media/v4l/io.xml
@@ -331,7 +331,7 @@ application until one or more buffers can be dequeued. By default
 outgoing queue. When the <constant>O_NONBLOCK</constant> flag was
 given to the &func-open; function, <constant>VIDIOC_DQBUF</constant>
 returns immediately with an &EAGAIN; when no buffer is available. The
-&func-select; or &func-poll; function are always available.</para>
+&func-select; or &func-poll; functions are always available.</para>
 
     <para>To start and stop capturing or output applications call the
 &VIDIOC-STREAMON; and &VIDIOC-STREAMOFF; ioctl. Note
@@ -472,6 +472,165 @@ rest should be evident.</para>
       </footnote></para>
   </section>
 
+  <section id="dmabuf">
+    <title>Streaming I/O (DMA buffer importing)</title>
+
+    <note>
+      <title>Experimental</title>
+      <para>This is an <link linkend="experimental"> experimental </link>
+      interface and may change in the future.</para>
+    </note>
+
+<para>The DMABUF framework provides a generic method for sharing buffers
+between multiple devices. Device drivers that support DMABUF can export a DMA
+buffer to userspace as a file descriptor (known as the exporter role), import a
+DMA buffer from userspace using a file descriptor previously exported for a
+different or the same device (known as the importer role), or both. This
+section describes the DMABUF importer role API in V4L2.</para>
+
+    <para>Refer to <link linked="vidioc-expbuf"> DMABUF exporting </link> for
+details about exporting V4L2 buffers as DMABUF file descriptors.</para>
+
+<para>Input and output devices support the streaming I/O method when the
+<constant>V4L2_CAP_STREAMING</constant> flag in the
+<structfield>capabilities</structfield> field of &v4l2-capability; returned by
+the &VIDIOC-QUERYCAP; ioctl is set. Whether importing DMA buffers through
+DMABUF file descriptors is supported is determined by calling the
+&VIDIOC-REQBUFS; ioctl with the memory type set to
+<constant>V4L2_MEMORY_DMABUF</constant>.</para>
+
+    <para>This I/O method is dedicated to sharing DMA buffers between different
+devices, which may be V4L devices or other video-related devices (e.g. DRM).
+Buffers (planes) are allocated by a driver on behalf of an application. Next,
+these buffers are exported to the application as file descriptors using an API
+which is specific for an allocator driver.  Only such file descriptor are
+exchanged. The descriptors and meta-information are passed in &v4l2-buffer; (or
+in &v4l2-plane; in the multi-planar API case).  The driver must be switched
+into DMABUF I/O mode by calling the &VIDIOC-REQBUFS; with the desired buffer
+type.</para>
+
+    <example>
+      <title>Initiating streaming I/O with DMABUF file descriptors</title>
+
+      <programlisting>
+&v4l2-requestbuffers; reqbuf;
+
+memset(&amp;reqbuf, 0, sizeof (reqbuf));
+reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+reqbuf.memory = V4L2_MEMORY_DMABUF;
+reqbuf.count = 1;
+
+if (ioctl(fd, &VIDIOC-REQBUFS;, &amp;reqbuf) == -1) {
+	if (errno == EINVAL)
+		printf("Video capturing or DMABUF streaming is not supported\n");
+	else
+		perror("VIDIOC_REQBUFS");
+
+	exit(EXIT_FAILURE);
+}
+      </programlisting>
+    </example>
+
+    <para>The buffer (plane) file descriptor is passed on the fly with the
+&VIDIOC-QBUF; ioctl. In case of multiplanar buffers, every plane can be
+associated with a different DMABUF descriptor. Although buffers are commonly
+cycled, applications can pass a different DMABUF descriptor at each
+<constant>VIDIOC_QBUF</constant> call.</para>
+
+    <example>
+      <title>Queueing DMABUF using single plane API</title>
+
+      <programlisting>
+int buffer_queue(int v4lfd, int index, int dmafd)
+{
+	&v4l2-buffer; buf;
+
+	memset(&amp;buf, 0, sizeof buf);
+	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	buf.memory = V4L2_MEMORY_DMABUF;
+	buf.index = index;
+	buf.m.fd = dmafd;
+
+	if (ioctl(v4lfd, &VIDIOC-QBUF;, &amp;buf) == -1) {
+		perror("VIDIOC_QBUF");
+		return -1;
+	}
+
+	return 0;
+}
+      </programlisting>
+    </example>
+
+    <example>
+      <title>Queueing DMABUF using multi plane API</title>
+
+      <programlisting>
+int buffer_queue_mp(int v4lfd, int index, int dmafd[], int n_planes)
+{
+	&v4l2-buffer; buf;
+	&v4l2-plane; planes[VIDEO_MAX_PLANES];
+	int i;
+
+	memset(&amp;buf, 0, sizeof buf);
+	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	buf.memory = V4L2_MEMORY_DMABUF;
+	buf.index = index;
+	buf.m.planes = planes;
+	buf.length = n_planes;
+
+	memset(&amp;planes, 0, sizeof planes);
+
+	for (i = 0; i &lt; n_planes; ++i)
+		buf.m.planes[i].m.fd = dmafd[i];
+
+	if (ioctl(v4lfd, &VIDIOC-QBUF;, &amp;buf) == -1) {
+		perror("VIDIOC_QBUF");
+		return -1;
+	}
+
+	return 0;
+}
+      </programlisting>
+    </example>
+
+    <para>Captured or displayed buffers are dequeued with the
+&VIDIOC-DQBUF; ioctl. The driver can unlock the buffer at any
+time between the completion of the DMA and this ioctl. The memory is
+also unlocked when &VIDIOC-STREAMOFF; is called, &VIDIOC-REQBUFS;, or
+when the device is closed.</para>
+
+    <para>For capturing applications it is customary to enqueue a
+number of empty buffers, to start capturing and enter the read loop.
+Here the application waits until a filled buffer can be dequeued, and
+re-enqueues the buffer when the data is no longer needed. Output
+applications fill and enqueue buffers, when enough buffers are stacked
+up output is started. In the write loop, when the application
+runs out of free buffers it must wait until an empty buffer can be
+dequeued and reused. Two methods exist to suspend execution of the
+application until one or more buffers can be dequeued. By default
+<constant>VIDIOC_DQBUF</constant> blocks when no buffer is in the
+outgoing queue. When the <constant>O_NONBLOCK</constant> flag was
+given to the &func-open; function, <constant>VIDIOC_DQBUF</constant>
+returns immediately with an &EAGAIN; when no buffer is available. The
+&func-select; and &func-poll; functions are always available.</para>
+
+    <para>To start and stop capturing or displaying applications call the
+&VIDIOC-STREAMON; and &VIDIOC-STREAMOFF; ioctls. Note that
+<constant>VIDIOC_STREAMOFF</constant> removes all buffers from both queues and
+unlocks all buffers as a side effect. Since there is no notion of doing
+anything "now" on a multitasking system, if an application needs to synchronize
+with another event it should examine the &v4l2-buffer;
+<structfield>timestamp</structfield> of captured buffers, or set the field
+before enqueuing buffers for output.</para>
+
+    <para>Drivers implementing DMABUF importing I/O must support the
+<constant>VIDIOC_REQBUFS</constant>, <constant>VIDIOC_QBUF</constant>,
+<constant>VIDIOC_DQBUF</constant>, <constant>VIDIOC_STREAMON</constant> and
+<constant>VIDIOC_STREAMOFF</constant> ioctls, and the
+<function>select()</function> and <function>poll()</function> functions.</para>
+
+  </section>
+
   <section id="async">
     <title>Asynchronous I/O</title>
 
@@ -673,6 +832,14 @@ memory, set by the application. See <xref linkend="userp" /> for details.
 	    <structname>v4l2_buffer</structname> structure.</entry>
 	  </row>
 	  <row>
+	    <entry></entry>
+	    <entry>int</entry>
+	    <entry><structfield>fd</structfield></entry>
+	    <entry>For the single-plane API and when
+<structfield>memory</structfield> is <constant>V4L2_MEMORY_DMABUF</constant> this
+is the file descriptor associated with a DMABUF buffer.</entry>
+	  </row>
+	  <row>
 	    <entry>__u32</entry>
 	    <entry><structfield>length</structfield></entry>
 	    <entry></entry>
@@ -744,6 +911,15 @@ should set this to 0.</entry>
 	      </entry>
 	  </row>
 	  <row>
+	    <entry></entry>
+	    <entry>int</entry>
+	    <entry><structfield>fd</structfield></entry>
+	    <entry>When the memory type in the containing &v4l2-buffer; is
+		<constant>V4L2_MEMORY_DMABUF</constant>, this is a file
+		descriptor associated with a DMABUF buffer, similar to the
+		<structfield>fd</structfield> field in &v4l2-buffer;.</entry>
+	  </row>
+	  <row>
 	    <entry>__u32</entry>
 	    <entry><structfield>data_offset</structfield></entry>
 	    <entry></entry>
@@ -923,7 +1099,7 @@ application. Drivers set or clear this flag when the
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant></entry>
-	    <entry>0x0400</entry>
+	    <entry>0x0800</entry>
 	    <entry>Caches do not have to be invalidated for this buffer.
 Typically applications shall use this flag if the data captured in the buffer
 is not going to be touched by the CPU, instead the buffer will, probably, be
@@ -932,7 +1108,7 @@ passed on to a DMA-capable hardware unit for further processing or output.
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant></entry>
-	    <entry>0x0800</entry>
+	    <entry>0x1000</entry>
 	    <entry>Caches do not have to be cleaned for this buffer.
 Typically applications shall use this flag for output buffers if the data
 in this buffer has not been created by the CPU but by some DMA-capable unit,
@@ -964,6 +1140,12 @@ pointer</link> I/O.</entry>
 	    <entry>3</entry>
 	    <entry>[to do]</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_MEMORY_DMABUF</constant></entry>
+	    <entry>4</entry>
+	    <entry>The buffer is used for <link linkend="dmabuf">DMA shared
+buffer</link> I/O.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml
index 10ccde9..4d110b1 100644
--- a/Documentation/DocBook/media/v4l/v4l2.xml
+++ b/Documentation/DocBook/media/v4l/v4l2.xml
@@ -543,6 +543,7 @@ and discussions on the V4L mailing list.</revremark>
     &sub-enuminput;
     &sub-enumoutput;
     &sub-enumstd;
+    &sub-expbuf;
     &sub-g-audio;
     &sub-g-audioout;
     &sub-g-crop;
diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
index a8cda1a..cd99436 100644
--- a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
@@ -6,7 +6,8 @@
 
   <refnamediv>
     <refname>VIDIOC_CREATE_BUFS</refname>
-    <refpurpose>Create buffers for Memory Mapped or User Pointer I/O</refpurpose>
+    <refpurpose>Create buffers for Memory Mapped or User Pointer or DMA Buffer
+    I/O</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
@@ -55,11 +56,11 @@
     </note>
 
     <para>This ioctl is used to create buffers for <link linkend="mmap">memory
-mapped</link> or <link linkend="userp">user pointer</link>
-I/O. It can be used as an alternative or in addition to the
-<constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter control over buffers
-is required. This ioctl can be called multiple times to create buffers of
-different sizes.</para>
+mapped</link> or <link linkend="userp">user pointer</link> or <link
+linkend="dmabuf">DMA buffer</link> I/O. It can be used as an alternative or in
+addition to the <constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter
+control over buffers is required. This ioctl can be called multiple times to
+create buffers of different sizes.</para>
 
     <para>To allocate device buffers applications initialize relevant fields of
 the <structname>v4l2_create_buffers</structname> structure. They set the
@@ -109,7 +110,8 @@ information.</para>
 	    <entry>__u32</entry>
 	    <entry><structfield>memory</structfield></entry>
 	    <entry>Applications set this field to
-<constant>V4L2_MEMORY_MMAP</constant> or
+<constant>V4L2_MEMORY_MMAP</constant>,
+<constant>V4L2_MEMORY_DMABUF</constant> or
 <constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory"
 /></entry>
 	  </row>
diff --git a/Documentation/DocBook/media/v4l/vidioc-expbuf.xml b/Documentation/DocBook/media/v4l/vidioc-expbuf.xml
new file mode 100644
index 0000000..72dfbd2
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/vidioc-expbuf.xml
@@ -0,0 +1,212 @@
+<refentry id="vidioc-expbuf">
+
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_EXPBUF</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_EXPBUF</refname>
+    <refpurpose>Export a buffer as a DMABUF file descriptor.</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_exportbuffer *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_EXPBUF</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <note>
+      <title>Experimental</title>
+      <para>This is an <link linkend="experimental"> experimental </link>
+      interface and may change in the future.</para>
+    </note>
+
+<para>This ioctl is an extension to the <link linkend="mmap">memory
+mapping</link> I/O method, therefore it is available only for
+<constant>V4L2_MEMORY_MMAP</constant> buffers.  It can be used to export a
+buffer as a DMABUF file at any time after buffers have been allocated with the
+&VIDIOC-REQBUFS; ioctl.</para>
+
+<para> To export a buffer, applications fill &v4l2-exportbuffer;.  The
+<structfield> type </structfield> field is set to the same buffer type as was
+previously used with  &v4l2-requestbuffers;<structfield> type </structfield>.
+Applications must also set the <structfield> index </structfield> field. Valid
+index numbers range from zero to the number of buffers allocated with
+&VIDIOC-REQBUFS; (&v4l2-requestbuffers;<structfield> count </structfield>)
+minus one.  For the multi-planar API, applications set the <structfield> plane
+</structfield> field to the index of the plane to be exported. Valid planes
+range from zero to the maximal number of valid planes for the currently active
+format. For the single-planar API, applications must set <structfield> plane
+</structfield> to zero.  Additional flags may be posted in the <structfield>
+flags </structfield> field.  Refer to a manual for open() for details.
+Currently only O_CLOEXEC is supported.  All other fields must be set to zero.
+In the case of multi-planar API, every plane is exported separately using
+multiple <constant> VIDIOC_EXPBUF </constant> calls. </para>
+
+<para> After calling <constant>VIDIOC_EXPBUF</constant> the <structfield> fd
+</structfield> field will be set by a driver.  This is a DMABUF file
+descriptor. The application may pass it to other DMABUF-aware devices. Refer to
+<link linkend="dmabuf">DMABUF importing</link> for details about importing
+DMABUF files into V4L2 nodes. It is recommended to close a DMABUF file when it
+is no longer used to allow the associated memory to be reclaimed. </para>
+
+  </refsect1>
+  <refsect1>
+   <section>
+      <title>Examples</title>
+
+      <example>
+	<title>Exporting a buffer.</title>
+	<programlisting>
+int buffer_export(int v4lfd, &v4l2-buf-type; bt, int index, int *dmafd)
+{
+	&v4l2-exportbuffer; expbuf;
+
+	memset(&amp;expbuf, 0, sizeof(expbuf));
+	expbuf.type = bt;
+	expbuf.index = index;
+	if (ioctl(v4lfd, &VIDIOC-EXPBUF;, &amp;expbuf) == -1) {
+		perror("VIDIOC_EXPBUF");
+		return -1;
+	}
+
+	*dmafd = expbuf.fd;
+
+	return 0;
+}
+        </programlisting>
+      </example>
+
+      <example>
+	<title>Exporting a buffer using the multi-planar API.</title>
+	<programlisting>
+int buffer_export_mp(int v4lfd, &v4l2-buf-type; bt, int index,
+	int dmafd[], int n_planes)
+{
+	int i;
+
+	for (i = 0; i &lt; n_planes; ++i) {
+		&v4l2-exportbuffer; expbuf;
+
+		memset(&amp;expbuf, 0, sizeof(expbuf));
+		expbuf.type = bt;
+		expbuf.index = index;
+		expbuf.plane = i;
+		if (ioctl(v4lfd, &VIDIOC-EXPBUF;, &amp;expbuf) == -1) {
+			perror("VIDIOC_EXPBUF");
+			while (i)
+				close(dmafd[--i]);
+			return -1;
+		}
+		dmafd[i] = expbuf.fd;
+	}
+
+	return 0;
+}
+        </programlisting>
+      </example>
+   </section>
+  </refsect1>
+
+  <refsect1>
+    <table pgwide="1" frame="none" id="v4l2-exportbuffer">
+      <title>struct <structname>v4l2_exportbuffer</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>type</structfield></entry>
+	    <entry>Type of the buffer, same as &v4l2-format;
+<structfield>type</structfield> or &v4l2-requestbuffers;
+<structfield>type</structfield>, set by the application. See <xref
+linkend="v4l2-buf-type" /></entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>index</structfield></entry>
+	    <entry>Number of the buffer, set by the application. This field is
+only used for <link linkend="mmap">memory mapping</link> I/O and can range from
+zero to the number of buffers allocated with the &VIDIOC-REQBUFS; and/or
+&VIDIOC-CREATE-BUFS; ioctls. </entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>plane</structfield></entry>
+	    <entry>Index of the plane to be exported when using the
+multi-planar API. Otherwise this value must be set to zero. </entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>flags</structfield></entry>
+	    <entry>Flags for the newly created file, currently only <constant>
+O_CLOEXEC </constant> is supported, refer to the manual of open() for more
+details.</entry>
+	  </row>
+	  <row>
+	    <entry>__s32</entry>
+	    <entry><structfield>fd</structfield></entry>
+	    <entry>The DMABUF file descriptor associated with a buffer. Set by
+		the driver.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved[11]</structfield></entry>
+	    <entry>Reserved field for future use. Must be set to zero.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>A queue is not in MMAP mode or DMABUF exporting is not
+supported or <structfield> flags </structfield> or <structfield> type
+</structfield> or <structfield> index </structfield> or <structfield> plane
+</structfield> fields are invalid.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
index 2d37abe..3504a7f 100644
--- a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
@@ -109,6 +109,23 @@ they cannot be swapped out to disk. Buffers remain locked until
 dequeued, until the &VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is
 called, or until the device is closed.</para>
 
+    <para>To enqueue a <link linkend="dmabuf">DMABUF</link> buffer applications
+set the <structfield>memory</structfield> field to
+<constant>V4L2_MEMORY_DMABUF</constant> and the <structfield>m.fd</structfield>
+field to a file descriptor associated with a DMABUF buffer. When the
+multi-planar API is used the <structfield>m.fd</structfield> fields of the
+passed array of &v4l2-plane; have to be used instead. When
+<constant>VIDIOC_QBUF</constant> is called with a pointer to this structure the
+driver sets the <constant>V4L2_BUF_FLAG_QUEUED</constant> flag and clears the
+<constant>V4L2_BUF_FLAG_MAPPED</constant> and
+<constant>V4L2_BUF_FLAG_DONE</constant> flags in the
+<structfield>flags</structfield> field, or it returns an error code.  This
+ioctl locks the buffer. Locking a buffer means passing it to a driver for a
+hardware access (usually DMA).  If an application accesses (reads/writes) a
+locked buffer then the result is undefined.  Buffers remain locked until
+dequeued, until the &VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is called, or
+until the device is closed.</para>
+
     <para>Applications call the <constant>VIDIOC_DQBUF</constant>
 ioctl to dequeue a filled (capturing) or displayed (output) buffer
 from the driver's outgoing queue. They just set the
diff --git a/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml b/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
index 2b50ef2..78a06a9 100644
--- a/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
@@ -48,28 +48,30 @@
   <refsect1>
     <title>Description</title>
 
-    <para>This ioctl is used to initiate <link linkend="mmap">memory
-mapped</link> or <link linkend="userp">user pointer</link>
-I/O. Memory mapped buffers are located in device memory and must be
-allocated with this ioctl before they can be mapped into the
-application's address space. User buffers are allocated by
-applications themselves, and this ioctl is merely used to switch the
-driver into user pointer I/O mode and to setup some internal structures.</para>
+<para>This ioctl is used to initiate <link linkend="mmap">memory mapped</link>,
+<link linkend="userp">user pointer</link> or <link
+linkend="dmabuf">DMABUF</link> based I/O.  Memory mapped buffers are located in
+device memory and must be allocated with this ioctl before they can be mapped
+into the application's address space. User buffers are allocated by
+applications themselves, and this ioctl is merely used to switch the driver
+into user pointer I/O mode and to setup some internal structures.
+Similarly, DMABUF buffers are allocated by applications through a device
+driver, and this ioctl only configures the driver into DMABUF I/O mode without
+performing any direct allocation.</para>
 
-    <para>To allocate device buffers applications initialize all
-fields of the <structname>v4l2_requestbuffers</structname> structure.
-They set the <structfield>type</structfield> field to the respective
-stream or buffer type, the <structfield>count</structfield> field to
-the desired number of buffers, <structfield>memory</structfield>
-must be set to the requested I/O method and the <structfield>reserved</structfield> array
-must be zeroed. When the ioctl
-is called with a pointer to this structure the driver will attempt to allocate
-the requested number of buffers and it stores the actual number
-allocated in the <structfield>count</structfield> field. It can be
-smaller than the number requested, even zero, when the driver runs out
-of free memory. A larger number is also possible when the driver requires
-more buffers to function correctly. For example video output requires at least two buffers,
-one displayed and one filled by the application.</para>
+    <para>To allocate device buffers applications initialize all fields of the
+<structname>v4l2_requestbuffers</structname> structure.  They set the
+<structfield>type</structfield> field to the respective stream or buffer type,
+the <structfield>count</structfield> field to the desired number of buffers,
+<structfield>memory</structfield> must be set to the requested I/O method and
+the <structfield>reserved</structfield> array must be zeroed. When the ioctl is
+called with a pointer to this structure the driver will attempt to allocate the
+requested number of buffers and it stores the actual number allocated in the
+<structfield>count</structfield> field. It can be smaller than the number
+requested, even zero, when the driver runs out of free memory. A larger number
+is also possible when the driver requires more buffers to function correctly.
+For example video output requires at least two buffers, one displayed and one
+filled by the application.</para>
     <para>When the I/O method is not supported the ioctl
 returns an &EINVAL;.</para>
 
@@ -102,7 +104,8 @@ as the &v4l2-format; <structfield>type</structfield> field. See <xref
 	    <entry>__u32</entry>
 	    <entry><structfield>memory</structfield></entry>
 	    <entry>Applications set this field to
-<constant>V4L2_MEMORY_MMAP</constant> or
+<constant>V4L2_MEMORY_MMAP</constant>,
+<constant>V4L2_MEMORY_DMABUF</constant> or
 <constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory"
 />.</entry>
 	  </row>
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl
index ac3d001..ddb05e9 100644
--- a/Documentation/DocBook/uio-howto.tmpl
+++ b/Documentation/DocBook/uio-howto.tmpl
@@ -719,6 +719,62 @@ framework to set up sysfs files for this region. Simply leave it alone.
 	</para>
 </sect1>
 
+<sect1 id="using uio_dmem_genirq">
+<title>Using uio_dmem_genirq for platform devices</title>
+	<para>
+	In addition to statically allocated memory ranges, they may also be
+	a desire to use dynamically allocated regions in a user space driver.
+	In particular, being able to access memory made available through the
+	dma-mapping API, may be particularly useful.  The
+	<varname>uio_dmem_genirq</varname> driver provides a way to accomplish
+	this.
+	</para>
+	<para>
+	This driver is used in a similar manner to the
+	<varname>"uio_pdrv_genirq"</varname> driver with respect to interrupt
+	configuration and handling.
+	</para>
+	<para>
+	Set the <varname>.name</varname> element of
+	<varname>struct platform_device</varname> to
+	<varname>"uio_dmem_genirq"</varname> to use this driver.
+	</para>
+	<para>
+	When using this driver, fill in the <varname>.platform_data</varname>
+	element of <varname>struct platform_device</varname>, which is of type
+	<varname>struct uio_dmem_genirq_pdata</varname> and which contains the
+	following elements:
+	</para>
+	<itemizedlist>
+	<listitem><varname>struct uio_info uioinfo</varname>: The same
+	structure used as the  <varname>uio_pdrv_genirq</varname> platform
+	data</listitem>
+	<listitem><varname>unsigned int *dynamic_region_sizes</varname>:
+	Pointer to list of sizes of dynamic memory regions to be mapped into
+	user space.
+	</listitem>
+	<listitem><varname>unsigned int num_dynamic_regions</varname>:
+	Number of elements in <varname>dynamic_region_sizes</varname> array.
+	</listitem>
+	</itemizedlist>
+	<para>
+	The dynamic regions defined in the platform data will be appended to
+	the <varname> mem[] </varname> array after the platform device
+	resources, which implies that the total number of static and dynamic
+	memory regions cannot exceed <varname>MAX_UIO_MAPS</varname>.
+	</para>
+	<para>
+	The dynamic memory regions will be allocated when the UIO device file,
+	<varname>/dev/uioX</varname> is opened.
+	Simiar to static memory resources, the memory region information for
+	dynamic regions is then visible via sysfs at
+	<varname>/sys/class/uio/uioX/maps/mapY/*</varname>.
+	The dynmaic memory regions will be freed when the UIO device file is
+	closed. When no processes are holding the device file open, the address
+	returned to userspace is ~0.
+	</para>
+</sect1>
+
 </chapter>
 
 <chapter id="userspace_driver" xreflabel="Writing a driver in user space">
diff --git a/Documentation/PCI/pci-iov-howto.txt b/Documentation/PCI/pci-iov-howto.txt
index fc73ef5..cfaca7e 100644
--- a/Documentation/PCI/pci-iov-howto.txt
+++ b/Documentation/PCI/pci-iov-howto.txt
@@ -2,6 +2,9 @@
 		Copyright (C) 2009 Intel Corporation
 		    Yu Zhao <yu.zhao@intel.com>
 
+		Update: November 2012
+			-- sysfs-based SRIOV enable-/disable-ment
+		Donald Dutile <ddutile@redhat.com>
 
 1. Overview
 
@@ -24,10 +27,21 @@ real existing PCI device.
 
 2.1 How can I enable SR-IOV capability
 
-The device driver (PF driver) will control the enabling and disabling
-of the capability via API provided by SR-IOV core. If the hardware
-has SR-IOV capability, loading its PF driver would enable it and all
-VFs associated with the PF.
+Multiple methods are available for SR-IOV enablement.
+In the first method, the device driver (PF driver) will control the
+enabling and disabling of the capability via API provided by SR-IOV core.
+If the hardware has SR-IOV capability, loading its PF driver would
+enable it and all VFs associated with the PF.  Some PF drivers require
+a module parameter to be set to determine the number of VFs to enable.
+In the second method, a write to the sysfs file sriov_numvfs will
+enable and disable the VFs associated with a PCIe PF.  This method
+enables per-PF, VF enable/disable values versus the first method,
+which applies to all PFs of the same device.  Additionally, the
+PCI SRIOV core support ensures that enable/disable operations are
+valid to reduce duplication in multiple drivers for the same
+checks, e.g., check numvfs == 0 if enabling VFs, ensure
+numvfs <= totalvfs.
+The second method is the recommended method for new/future VF devices.
 
 2.2 How can I use the Virtual Functions
 
@@ -40,13 +54,22 @@ requires device driver that is same as a normal PCI device's.
 3.1 SR-IOV API
 
 To enable SR-IOV capability:
+(a) For the first method, in the driver:
 	int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
 	'nr_virtfn' is number of VFs to be enabled.
+(b) For the second method, from sysfs:
+	echo 'nr_virtfn' > \
+        /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
 
 To disable SR-IOV capability:
+(a) For the first method, in the driver:
 	void pci_disable_sriov(struct pci_dev *dev);
+(b) For the second method, from sysfs:
+	echo  0 > \
+        /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
 
 To notify SR-IOV core of Virtual Function Migration:
+(a) In the driver:
 	irqreturn_t pci_sriov_migration(struct pci_dev *dev);
 
 3.2 Usage example
@@ -88,6 +111,22 @@ static void dev_shutdown(struct pci_dev *dev)
 	...
 }
 
+static int dev_sriov_configure(struct pci_dev *dev, int numvfs)
+{
+	if (numvfs > 0) {
+		...
+		pci_enable_sriov(dev, numvfs);
+		...
+		return numvfs;
+	}
+	if (numvfs == 0) {
+		....
+		pci_disable_sriov(dev);
+		...
+		return 0;
+	}
+}
+
 static struct pci_driver dev_driver = {
 	.name =		"SR-IOV Physical Function driver",
 	.id_table =	dev_id_table,
@@ -96,4 +135,5 @@ static struct pci_driver dev_driver = {
 	.suspend =	dev_suspend,
 	.resume =	dev_resume,
 	.shutdown =	dev_shutdown,
+	.sriov_configure = dev_sriov_configure,
 };
diff --git a/Documentation/RCU/RTFP.txt b/Documentation/RCU/RTFP.txt
index 7c1dfb1..7f40c72 100644
--- a/Documentation/RCU/RTFP.txt
+++ b/Documentation/RCU/RTFP.txt
@@ -186,7 +186,7 @@ Bibtex Entries
 
 @article{Kung80
 ,author="H. T. Kung and Q. Lehman"
-,title="Concurrent Maintenance of Binary Search Trees"
+,title="Concurrent Manipulation of Binary Search Trees"
 ,Year="1980"
 ,Month="September"
 ,journal="ACM Transactions on Database Systems"
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index cdb20d4..31ef8fe 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -271,15 +271,14 @@ over a rather long period of time, but improvements are always welcome!
 	The same cautions apply to call_rcu_bh() and call_rcu_sched().
 
 9.	All RCU list-traversal primitives, which include
-	rcu_dereference(), list_for_each_entry_rcu(),
-	list_for_each_continue_rcu(), and list_for_each_safe_rcu(),
-	must be either within an RCU read-side critical section or
-	must be protected by appropriate update-side locks.  RCU
-	read-side critical sections are delimited by rcu_read_lock()
-	and rcu_read_unlock(), or by similar primitives such as
-	rcu_read_lock_bh() and rcu_read_unlock_bh(), in which case
-	the matching rcu_dereference() primitive must be used in order
-	to keep lockdep happy, in this case, rcu_dereference_bh().
+	rcu_dereference(), list_for_each_entry_rcu(), and
+	list_for_each_safe_rcu(), must be either within an RCU read-side
+	critical section or must be protected by appropriate update-side
+	locks.	RCU read-side critical sections are delimited by
+	rcu_read_lock() and rcu_read_unlock(), or by similar primitives
+	such as rcu_read_lock_bh() and rcu_read_unlock_bh(), in which
+	case the matching rcu_dereference() primitive must be used in
+	order to keep lockdep happy, in this case, rcu_dereference_bh().
 
 	The reason that it is permissible to use RCU list-traversal
 	primitives when the update-side lock is held is that doing so
diff --git a/Documentation/RCU/listRCU.txt b/Documentation/RCU/listRCU.txt
index 4349c14..adb5a37 100644
--- a/Documentation/RCU/listRCU.txt
+++ b/Documentation/RCU/listRCU.txt
@@ -205,7 +205,7 @@ RCU ("read-copy update") its name.  The RCU code is as follows:
 				audit_copy_rule(&ne->rule, &e->rule);
 				ne->rule.action = newaction;
 				ne->rule.file_count = newfield_count;
-				list_replace_rcu(e, ne);
+				list_replace_rcu(&e->list, &ne->list);
 				call_rcu(&e->rcu, audit_free_rule);
 				return 0;
 			}
diff --git a/Documentation/RCU/rcuref.txt b/Documentation/RCU/rcuref.txt
index 4202ad0..141d531 100644
--- a/Documentation/RCU/rcuref.txt
+++ b/Documentation/RCU/rcuref.txt
@@ -20,7 +20,7 @@ release_referenced()			delete()
 {					{
     ...					    write_lock(&list_lock);
     atomic_dec(&el->rc, relfunc)	    ...
-    ...					    delete_element
+    ...					    remove_element
 }					    write_unlock(&list_lock);
  					    ...
 					    if (atomic_dec_and_test(&el->rc))
@@ -52,7 +52,7 @@ release_referenced()			delete()
 {					{
     ...					    spin_lock(&list_lock);
     if (atomic_dec_and_test(&el->rc))       ...
-        call_rcu(&el->head, el_free);       delete_element
+        call_rcu(&el->head, el_free);       remove_element
     ...                                     spin_unlock(&list_lock);
 } 					    ...
 					    if (atomic_dec_and_test(&el->rc))
@@ -64,3 +64,60 @@ Sometimes, a reference to the element needs to be obtained in the
 update (write) stream.  In such cases, atomic_inc_not_zero() might be
 overkill, since we hold the update-side spinlock.  One might instead
 use atomic_inc() in such cases.
+
+It is not always convenient to deal with "FAIL" in the
+search_and_reference() code path.  In such cases, the
+atomic_dec_and_test() may be moved from delete() to el_free()
+as follows:
+
+1.					2.
+add()					search_and_reference()
+{					{
+    alloc_object			    rcu_read_lock();
+    ...					    search_for_element
+    atomic_set(&el->rc, 1);		    atomic_inc(&el->rc);
+    spin_lock(&list_lock);		    ...
+
+    add_element				    rcu_read_unlock();
+    ...					}
+    spin_unlock(&list_lock);		4.
+}					delete()
+3.					{
+release_referenced()			    spin_lock(&list_lock);
+{					    ...
+    ...					    remove_element
+    if (atomic_dec_and_test(&el->rc))       spin_unlock(&list_lock);
+        kfree(el);			    ...
+    ...                                     call_rcu(&el->head, el_free);
+} 					    ...
+5.					}
+void el_free(struct rcu_head *rhp)
+{
+    release_referenced();
+}
+
+The key point is that the initial reference added by add() is not removed
+until after a grace period has elapsed following removal.  This means that
+search_and_reference() cannot find this element, which means that the value
+of el->rc cannot increase.  Thus, once it reaches zero, there are no
+readers that can or ever will be able to reference the element.  The
+element can therefore safely be freed.  This in turn guarantees that if
+any reader finds the element, that reader may safely acquire a reference
+without checking the value of the reference counter.
+
+In cases where delete() can sleep, synchronize_rcu() can be called from
+delete(), so that el_free() can be subsumed into delete as follows:
+
+4.
+delete()
+{
+    spin_lock(&list_lock);
+    ...
+    remove_element
+    spin_unlock(&list_lock);
+    ...
+    synchronize_rcu();
+    if (atomic_dec_and_test(&el->rc))
+    	kfree(el);
+    ...
+}
diff --git a/Documentation/RCU/trace.txt b/Documentation/RCU/trace.txt
index 672d190..c776968 100644
--- a/Documentation/RCU/trace.txt
+++ b/Documentation/RCU/trace.txt
@@ -10,51 +10,63 @@ for rcutree and next for rcutiny.
 
 CONFIG_TREE_RCU and CONFIG_TREE_PREEMPT_RCU debugfs Files and Formats
 
-These implementations of RCU provides several debugfs files under the
+These implementations of RCU provide several debugfs directories under the
 top-level directory "rcu":
 
-rcu/rcudata:
+rcu/rcu_bh
+rcu/rcu_preempt
+rcu/rcu_sched
+
+Each directory contains files for the corresponding flavor of RCU.
+Note that rcu/rcu_preempt is only present for CONFIG_TREE_PREEMPT_RCU.
+For CONFIG_TREE_RCU, the RCU flavor maps onto the RCU-sched flavor,
+so that activity for both appears in rcu/rcu_sched.
+
+In addition, the following file appears in the top-level directory:
+rcu/rcutorture.  This file displays rcutorture test progress.  The output
+of "cat rcu/rcutorture" looks as follows:
+
+rcutorture test sequence: 0 (test in progress)
+rcutorture update version number: 615
+
+The first line shows the number of rcutorture tests that have completed
+since boot.  If a test is currently running, the "(test in progress)"
+string will appear as shown above.  The second line shows the number of
+update cycles that the current test has started, or zero if there is
+no test in progress.
+
+
+Within each flavor directory (rcu/rcu_bh, rcu/rcu_sched, and possibly
+also rcu/rcu_preempt) the following files will be present:
+
+rcudata:
 	Displays fields in struct rcu_data.
-rcu/rcudata.csv:
-	Comma-separated values spreadsheet version of rcudata.
-rcu/rcugp:
+rcuexp:
+	Displays statistics for expedited grace periods.
+rcugp:
 	Displays grace-period counters.
-rcu/rcuhier:
+rcuhier:
 	Displays the struct rcu_node hierarchy.
-rcu/rcu_pending:
+rcu_pending:
 	Displays counts of the reasons rcu_pending() decided that RCU had
 	work to do.
-rcu/rcutorture:
-	Displays rcutorture test progress.
-rcu/rcuboost:
+rcuboost:
 	Displays RCU boosting statistics.  Only present if
 	CONFIG_RCU_BOOST=y.
 
-The output of "cat rcu/rcudata" looks as follows:
-
-rcu_sched:
-  0 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=545/1/0 df=50 of=0 ql=163 qs=NRW. kt=0/W/0 ktl=ebc3 b=10 ci=153737 co=0 ca=0
-  1 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=967/1/0 df=58 of=0 ql=634 qs=NRW. kt=0/W/1 ktl=58c b=10 ci=191037 co=0 ca=0
-  2 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=1081/1/0 df=175 of=0 ql=74 qs=N.W. kt=0/W/2 ktl=da94 b=10 ci=75991 co=0 ca=0
-  3 c=20942 g=20943 pq=1 pgp=20942 qp=1 dt=1846/0/0 df=404 of=0 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=72261 co=0 ca=0
-  4 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=369/1/0 df=83 of=0 ql=48 qs=N.W. kt=0/W/4 ktl=e0e7 b=10 ci=128365 co=0 ca=0
-  5 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=381/1/0 df=64 of=0 ql=169 qs=NRW. kt=0/W/5 ktl=fb2f b=10 ci=164360 co=0 ca=0
-  6 c=20972 g=20973 pq=1 pgp=20973 qp=0 dt=1037/1/0 df=183 of=0 ql=62 qs=N.W. kt=0/W/6 ktl=d2ad b=10 ci=65663 co=0 ca=0
-  7 c=20897 g=20897 pq=1 pgp=20896 qp=0 dt=1572/0/0 df=382 of=0 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=75006 co=0 ca=0
-rcu_bh:
-  0 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=545/1/0 df=6 of=0 ql=0 qs=.... kt=0/W/0 ktl=ebc3 b=10 ci=0 co=0 ca=0
-  1 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=967/1/0 df=3 of=0 ql=0 qs=.... kt=0/W/1 ktl=58c b=10 ci=151 co=0 ca=0
-  2 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=1081/1/0 df=6 of=0 ql=0 qs=.... kt=0/W/2 ktl=da94 b=10 ci=0 co=0 ca=0
-  3 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=1846/0/0 df=8 of=0 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=0 co=0 ca=0
-  4 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=369/1/0 df=6 of=0 ql=0 qs=.... kt=0/W/4 ktl=e0e7 b=10 ci=0 co=0 ca=0
-  5 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=381/1/0 df=4 of=0 ql=0 qs=.... kt=0/W/5 ktl=fb2f b=10 ci=0 co=0 ca=0
-  6 c=1480 g=1480 pq=1 pgp=1480 qp=0 dt=1037/1/0 df=6 of=0 ql=0 qs=.... kt=0/W/6 ktl=d2ad b=10 ci=0 co=0 ca=0
-  7 c=1474 g=1474 pq=1 pgp=1473 qp=0 dt=1572/0/0 df=8 of=0 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=0 co=0 ca=0
-
-The first section lists the rcu_data structures for rcu_sched, the second
-for rcu_bh.  Note that CONFIG_TREE_PREEMPT_RCU kernels will have an
-additional section for rcu_preempt.  Each section has one line per CPU,
-or eight for this 8-CPU system.  The fields are as follows:
+The output of "cat rcu/rcu_preempt/rcudata" looks as follows:
+
+  0!c=30455 g=30456 pq=1 qp=1 dt=126535/140000000000000/0 df=2002 of=4 ql=0/0 qs=N... b=10 ci=74572 nci=0 co=1131 ca=716
+  1!c=30719 g=30720 pq=1 qp=0 dt=132007/140000000000000/0 df=1874 of=10 ql=0/0 qs=N... b=10 ci=123209 nci=0 co=685 ca=982
+  2!c=30150 g=30151 pq=1 qp=1 dt=138537/140000000000000/0 df=1707 of=8 ql=0/0 qs=N... b=10 ci=80132 nci=0 co=1328 ca=1458
+  3 c=31249 g=31250 pq=1 qp=0 dt=107255/140000000000000/0 df=1749 of=6 ql=0/450 qs=NRW. b=10 ci=151700 nci=0 co=509 ca=622
+  4!c=29502 g=29503 pq=1 qp=1 dt=83647/140000000000000/0 df=965 of=5 ql=0/0 qs=N... b=10 ci=65643 nci=0 co=1373 ca=1521
+  5 c=31201 g=31202 pq=1 qp=1 dt=70422/0/0 df=535 of=7 ql=0/0 qs=.... b=10 ci=58500 nci=0 co=764 ca=698
+  6!c=30253 g=30254 pq=1 qp=1 dt=95363/140000000000000/0 df=780 of=5 ql=0/0 qs=N... b=10 ci=100607 nci=0 co=1414 ca=1353
+  7 c=31178 g=31178 pq=1 qp=0 dt=91536/0/0 df=547 of=4 ql=0/0 qs=.... b=10 ci=109819 nci=0 co=1115 ca=969
+
+This file has one line per CPU, or eight for this 8-CPU system.
+The fields are as follows:
 
 o	The number at the beginning of each line is the CPU number.
 	CPUs numbers followed by an exclamation mark are offline,
@@ -64,11 +76,13 @@ o	The number at the beginning of each line is the CPU number.
 	substantially larger than the number of actual CPUs.
 
 o	"c" is the count of grace periods that this CPU believes have
-	completed.  Offlined CPUs and CPUs in dynticks idle mode may
-	lag quite a ways behind, for example, CPU 6 under "rcu_sched"
-	above, which has been offline through not quite 40,000 RCU grace
-	periods.  It is not unusual to see CPUs lagging by thousands of
-	grace periods.
+	completed.  Offlined CPUs and CPUs in dynticks idle mode may lag
+	quite a ways behind, for example, CPU 4 under "rcu_sched" above,
+	which has been offline through 16 RCU grace periods.  It is not
+	unusual to see offline CPUs lagging by thousands of grace periods.
+	Note that although the grace-period number is an unsigned long,
+	it is printed out as a signed long to allow more human-friendly
+	representation near boot time.
 
 o	"g" is the count of grace periods that this CPU believes have
 	started.  Again, offlined CPUs and CPUs in dynticks idle mode
@@ -84,30 +98,25 @@ o	"pq" indicates that this CPU has passed through a quiescent state
 	CPU has not yet reported that fact, (2) some other CPU has not
 	yet reported for this grace period, or (3) both.
 
-o	"pgp" indicates which grace period the last-observed quiescent
-	state for this CPU corresponds to.  This is important for handling
-	the race between CPU 0 reporting an extended dynticks-idle
-	quiescent state for CPU 1 and CPU 1 suddenly waking up and
-	reporting its own quiescent state.  If CPU 1 was the last CPU
-	for the current grace period, then the CPU that loses this race
-	will attempt to incorrectly mark CPU 1 as having checked in for
-	the next grace period!
-
 o	"qp" indicates that RCU still expects a quiescent state from
 	this CPU.  Offlined CPUs and CPUs in dyntick idle mode might
 	well have qp=1, which is OK: RCU is still ignoring them.
 
 o	"dt" is the current value of the dyntick counter that is incremented
-	when entering or leaving dynticks idle state, either by the
-	scheduler or by irq.  This number is even if the CPU is in
-	dyntick idle mode and odd otherwise.  The number after the first
-	"/" is the interrupt nesting depth when in dyntick-idle state,
-	or one greater than the interrupt-nesting depth otherwise.
-	The number after the second "/" is the NMI nesting depth.
+	when entering or leaving idle, either due to a context switch or
+	due to an interrupt.  This number is even if the CPU is in idle
+	from RCU's viewpoint and odd otherwise.  The number after the
+	first "/" is the interrupt nesting depth when in idle state,
+	or a large number added to the interrupt-nesting depth when
+	running a non-idle task.  Some architectures do not accurately
+	count interrupt nesting when running in non-idle kernel context,
+	which can result in interesting anomalies such as negative
+	interrupt-nesting levels.  The number after the second "/"
+	is the NMI nesting depth.
 
 o	"df" is the number of times that some other CPU has forced a
 	quiescent state on behalf of this CPU due to this CPU being in
-	dynticks-idle state.
+	idle state.
 
 o	"of" is the number of times that some other CPU has forced a
 	quiescent state on behalf of this CPU due to this CPU being
@@ -120,9 +129,13 @@ o	"of" is the number of times that some other CPU has forced a
 	error, so it makes sense to err conservatively.
 
 o	"ql" is the number of RCU callbacks currently residing on
-	this CPU.  This is the total number of callbacks, regardless
-	of what state they are in (new, waiting for grace period to
-	start, waiting for grace period to end, ready to invoke).
+	this CPU.  The first number is the number of "lazy" callbacks
+	that are known to RCU to only be freeing memory, and the number
+	after the "/" is the total number of callbacks, lazy or not.
+	These counters count callbacks regardless of what phase of
+	grace-period processing that they are in (new, waiting for
+	grace period to start, waiting for grace period to end, ready
+	to invoke).
 
 o	"qs" gives an indication of the state of the callback queue
 	with four characters:
@@ -150,6 +163,43 @@ o	"qs" gives an indication of the state of the callback queue
 	If there are no callbacks in a given one of the above states,
 	the corresponding character is replaced by ".".
 
+o	"b" is the batch limit for this CPU.  If more than this number
+	of RCU callbacks is ready to invoke, then the remainder will
+	be deferred.
+
+o	"ci" is the number of RCU callbacks that have been invoked for
+	this CPU.  Note that ci+nci+ql is the number of callbacks that have
+	been registered in absence of CPU-hotplug activity.
+
+o	"nci" is the number of RCU callbacks that have been offloaded from
+	this CPU.  This will always be zero unless the kernel was built
+	with CONFIG_RCU_NOCB_CPU=y and the "rcu_nocbs=" kernel boot
+	parameter was specified.
+
+o	"co" is the number of RCU callbacks that have been orphaned due to
+	this CPU going offline.  These orphaned callbacks have been moved
+	to an arbitrarily chosen online CPU.
+
+o	"ca" is the number of RCU callbacks that have been adopted by this
+	CPU due to other CPUs going offline.  Note that ci+co-ca+ql is
+	the number of RCU callbacks registered on this CPU.
+
+
+Kernels compiled with CONFIG_RCU_BOOST=y display the following from
+/debug/rcu/rcu_preempt/rcudata:
+
+  0!c=12865 g=12866 pq=1 qp=1 dt=83113/140000000000000/0 df=288 of=11 ql=0/0 qs=N... kt=0/O ktl=944 b=10 ci=60709 nci=0 co=748 ca=871
+  1 c=14407 g=14408 pq=1 qp=0 dt=100679/140000000000000/0 df=378 of=7 ql=0/119 qs=NRW. kt=0/W ktl=9b6 b=10 ci=109740 nci=0 co=589 ca=485
+  2 c=14407 g=14408 pq=1 qp=0 dt=105486/0/0 df=90 of=9 ql=0/89 qs=NRW. kt=0/W ktl=c0c b=10 ci=83113 nci=0 co=533 ca=490
+  3 c=14407 g=14408 pq=1 qp=0 dt=107138/0/0 df=142 of=8 ql=0/188 qs=NRW. kt=0/W ktl=b96 b=10 ci=121114 nci=0 co=426 ca=290
+  4 c=14405 g=14406 pq=1 qp=1 dt=50238/0/0 df=706 of=7 ql=0/0 qs=.... kt=0/W ktl=812 b=10 ci=34929 nci=0 co=643 ca=114
+  5!c=14168 g=14169 pq=1 qp=0 dt=45465/140000000000000/0 df=161 of=11 ql=0/0 qs=N... kt=0/O ktl=b4d b=10 ci=47712 nci=0 co=677 ca=722
+  6 c=14404 g=14405 pq=1 qp=0 dt=59454/0/0 df=94 of=6 ql=0/0 qs=.... kt=0/W ktl=e57 b=10 ci=55597 nci=0 co=701 ca=811
+  7 c=14407 g=14408 pq=1 qp=1 dt=68850/0/0 df=31 of=8 ql=0/0 qs=.... kt=0/W ktl=14bd b=10 ci=77475 nci=0 co=508 ca=1042
+
+This is similar to the output discussed above, but contains the following
+additional fields:
+
 o	"kt" is the per-CPU kernel-thread state.  The digit preceding
 	the first slash is zero if there is no work pending and 1
 	otherwise.  The character between the first pair of slashes is
@@ -184,35 +234,51 @@ o	"ktl" is the low-order 16 bits (in hexadecimal) of the count of
 
 	This field is displayed only for CONFIG_RCU_BOOST kernels.
 
-o	"b" is the batch limit for this CPU.  If more than this number
-	of RCU callbacks is ready to invoke, then the remainder will
-	be deferred.
 
-o	"ci" is the number of RCU callbacks that have been invoked for
-	this CPU.  Note that ci+ql is the number of callbacks that have
-	been registered in absence of CPU-hotplug activity.
+The output of "cat rcu/rcu_preempt/rcuexp" looks as follows:
 
-o	"co" is the number of RCU callbacks that have been orphaned due to
-	this CPU going offline.  These orphaned callbacks have been moved
-	to an arbitrarily chosen online CPU.
+s=21872 d=21872 w=0 tf=0 wd1=0 wd2=0 n=0 sc=21872 dt=21872 dl=0 dx=21872
+
+These fields are as follows:
+
+o	"s" is the starting sequence number.
 
-o	"ca" is the number of RCU callbacks that have been adopted due to
-	other CPUs going offline.  Note that ci+co-ca+ql is the number of
-	RCU callbacks registered on this CPU.
+o	"d" is the ending sequence number.  When the starting and ending
+	numbers differ, there is an expedited grace period in progress.
 
-There is also an rcu/rcudata.csv file with the same information in
-comma-separated-variable spreadsheet format.
+o	"w" is the number of times that the sequence numbers have been
+	in danger of wrapping.
 
+o	"tf" is the number of times that contention has resulted in a
+	failure to begin an expedited grace period.
 
-The output of "cat rcu/rcugp" looks as follows:
+o	"wd1" and "wd2" are the number of times that an attempt to
+	start an expedited grace period found that someone else had
+	completed an expedited grace period that satisfies the
+	attempted request.  "Our work is done."
 
-rcu_sched: completed=33062  gpnum=33063
-rcu_bh: completed=464  gpnum=464
+o	"n" is number of times that contention was so great that
+	the request was demoted from an expedited grace period to
+	a normal grace period.
+
+o	"sc" is the number of times that the attempt to start a
+	new expedited grace period succeeded.
+
+o	"dt" is the number of times that we attempted to update
+	the "d" counter.
+
+o	"dl" is the number of times that we failed to update the "d"
+	counter.
+
+o	"dx" is the number of times that we succeeded in updating
+	the "d" counter.
 
-Again, this output is for both "rcu_sched" and "rcu_bh".  Note that
-kernels built with CONFIG_TREE_PREEMPT_RCU will have an additional
-"rcu_preempt" line.  The fields are taken from the rcu_state structure,
-and are as follows:
+
+The output of "cat rcu/rcu_preempt/rcugp" looks as follows:
+
+completed=31249  gpnum=31250  age=1  max=18
+
+These fields are taken from the rcu_state structure, and are as follows:
 
 o	"completed" is the number of grace periods that have completed.
 	It is comparable to the "c" field from rcu/rcudata in that a
@@ -220,44 +286,42 @@ o	"completed" is the number of grace periods that have completed.
 	that the corresponding RCU grace period has completed.
 
 o	"gpnum" is the number of grace periods that have started.  It is
-	comparable to the "g" field from rcu/rcudata in that a CPU
-	whose "g" field matches the value of "gpnum" is aware that the
-	corresponding RCU grace period has started.
+	similarly comparable to the "g" field from rcu/rcudata in that
+	a CPU whose "g" field matches the value of "gpnum" is aware that
+	the corresponding RCU grace period has started.
+
+	If these two fields are equal, then there is no grace period
+	in progress, in other words, RCU is idle.  On the other hand,
+	if the two fields differ (as they are above), then an RCU grace
+	period is in progress.
 
-	If these two fields are equal (as they are for "rcu_bh" above),
-	then there is no grace period in progress, in other words, RCU
-	is idle.  On the other hand, if the two fields differ (as they
-	do for "rcu_sched" above), then an RCU grace period is in progress.
+o	"age" is the number of jiffies that the current grace period
+	has extended for, or zero if there is no grace period currently
+	in effect.
 
+o	"max" is the age in jiffies of the longest-duration grace period
+	thus far.
 
-The output of "cat rcu/rcuhier" looks as follows, with very long lines:
+The output of "cat rcu/rcu_preempt/rcuhier" looks as follows:
 
-c=6902 g=6903 s=2 jfq=3 j=72c7 nfqs=13142/nfqsng=0(13142) fqlh=6
-1/1 ..>. 0:127 ^0
-3/3 ..>. 0:35 ^0    0/0 ..>. 36:71 ^1    0/0 ..>. 72:107 ^2    0/0 ..>. 108:127 ^3
-3/3f ..>. 0:5 ^0    2/3 ..>. 6:11 ^1    0/0 ..>. 12:17 ^2    0/0 ..>. 18:23 ^3    0/0 ..>. 24:29 ^4    0/0 ..>. 30:35 ^5    0/0 ..>. 36:41 ^0    0/0 ..>. 42:47 ^1    0/0 ..>. 48:53 ^2    0/0 ..>. 54:59 ^3    0/0 ..>. 60:65 ^4    0/0 ..>. 66:71 ^5    0/0 ..>. 72:77 ^0    0/0 ..>. 78:83 ^1    0/0 ..>. 84:89 ^2    0/0 ..>. 90:95 ^3    0/0 ..>. 96:101 ^4    0/0 ..>. 102:107 ^5    0/0 ..>. 108:113 ^0    0/0 ..>. 114:119 ^1    0/0 ..>. 120:125 ^2    0/0 ..>. 126:127 ^3
-rcu_bh:
-c=-226 g=-226 s=1 jfq=-5701 j=72c7 nfqs=88/nfqsng=0(88) fqlh=0
-0/1 ..>. 0:127 ^0
-0/3 ..>. 0:35 ^0    0/0 ..>. 36:71 ^1    0/0 ..>. 72:107 ^2    0/0 ..>. 108:127 ^3
-0/3f ..>. 0:5 ^0    0/3 ..>. 6:11 ^1    0/0 ..>. 12:17 ^2    0/0 ..>. 18:23 ^3    0/0 ..>. 24:29 ^4    0/0 ..>. 30:35 ^5    0/0 ..>. 36:41 ^0    0/0 ..>. 42:47 ^1    0/0 ..>. 48:53 ^2    0/0 ..>. 54:59 ^3    0/0 ..>. 60:65 ^4    0/0 ..>. 66:71 ^5    0/0 ..>. 72:77 ^0    0/0 ..>. 78:83 ^1    0/0 ..>. 84:89 ^2    0/0 ..>. 90:95 ^3    0/0 ..>. 96:101 ^4    0/0 ..>. 102:107 ^5    0/0 ..>. 108:113 ^0    0/0 ..>. 114:119 ^1    0/0 ..>. 120:125 ^2    0/0 ..>. 126:127 ^3
+c=14407 g=14408 s=0 jfq=2 j=c863 nfqs=12040/nfqsng=0(12040) fqlh=1051 oqlen=0/0
+3/3 ..>. 0:7 ^0
+e/e ..>. 0:3 ^0    d/d ..>. 4:7 ^1
 
-This is once again split into "rcu_sched" and "rcu_bh" portions,
-and CONFIG_TREE_PREEMPT_RCU kernels will again have an additional
-"rcu_preempt" section.  The fields are as follows:
+The fields are as follows:
 
-o	"c" is exactly the same as "completed" under rcu/rcugp.
+o	"c" is exactly the same as "completed" under rcu/rcu_preempt/rcugp.
 
-o	"g" is exactly the same as "gpnum" under rcu/rcugp.
+o	"g" is exactly the same as "gpnum" under rcu/rcu_preempt/rcugp.
 
-o	"s" is the "signaled" state that drives force_quiescent_state()'s
+o	"s" is the current state of the force_quiescent_state()
 	state machine.
 
 o	"jfq" is the number of jiffies remaining for this grace period
 	before force_quiescent_state() is invoked to help push things
-	along.  Note that CPUs in dyntick-idle mode throughout the grace
-	period will not report on their own, but rather must be check by
-	some other CPU via force_quiescent_state().
+	along.	Note that CPUs in idle mode throughout the grace period
+	will not report on their own, but rather must be check by some
+	other CPU via force_quiescent_state().
 
 o	"j" is the low-order four hex digits of the jiffies counter.
 	Yes, Paul did run into a number of problems that turned out to
@@ -268,7 +332,8 @@ o	"nfqs" is the number of calls to force_quiescent_state() since
 
 o	"nfqsng" is the number of useless calls to force_quiescent_state(),
 	where there wasn't actually a grace period active.  This can
-	happen due to races.  The number in parentheses is the difference
+	no longer happen due to grace-period processing being pushed
+	into a kthread.  The number in parentheses is the difference
 	between "nfqs" and "nfqsng", or the number of times that
 	force_quiescent_state() actually did some real work.
 
@@ -276,28 +341,27 @@ o	"fqlh" is the number of calls to force_quiescent_state() that
 	exited immediately (without even being counted in nfqs above)
 	due to contention on ->fqslock.
 
-o	Each element of the form "1/1 0:127 ^0" represents one struct
-	rcu_node.  Each line represents one level of the hierarchy, from
-	root to leaves.  It is best to think of the rcu_data structures
-	as forming yet another level after the leaves.  Note that there
-	might be either one, two, or three levels of rcu_node structures,
-	depending on the relationship between CONFIG_RCU_FANOUT and
-	CONFIG_NR_CPUS.
+o	Each element of the form "3/3 ..>. 0:7 ^0" represents one rcu_node
+	structure.  Each line represents one level of the hierarchy,
+	from root to leaves.  It is best to think of the rcu_data
+	structures as forming yet another level after the leaves.
+	Note that there might be either one, two, three, or even four
+	levels of rcu_node structures, depending on the relationship
+	between CONFIG_RCU_FANOUT, CONFIG_RCU_FANOUT_LEAF (possibly
+	adjusted using the rcu_fanout_leaf kernel boot parameter), and
+	CONFIG_NR_CPUS (possibly adjusted using the nr_cpu_ids count of
+	possible CPUs for the booting hardware).
 
 	o	The numbers separated by the "/" are the qsmask followed
 		by the qsmaskinit.  The qsmask will have one bit
-		set for each entity in the next lower level that
-		has not yet checked in for the current grace period.
+		set for each entity in the next lower level that has
+		not yet checked in for the current grace period ("e"
+		indicating CPUs 5, 6, and 7 in the example above).
 		The qsmaskinit will have one bit for each entity that is
 		currently expected to check in during each grace period.
 		The value of qsmaskinit is assigned to that of qsmask
 		at the beginning of each grace period.
 
-		For example, for "rcu_sched", the qsmask of the first
-		entry of the lowest level is 0x14, meaning that we
-		are still waiting for CPUs 2 and 4 to check in for the
-		current grace period.
-
 	o	The characters separated by the ">" indicate the state
 		of the blocked-tasks lists.  A "G" preceding the ">"
 		indicates that at least one task blocked in an RCU
@@ -312,48 +376,39 @@ o	Each element of the form "1/1 0:127 ^0" represents one struct
 		A "." character appears if the corresponding condition
 		does not hold, so that "..>." indicates that no tasks
 		are blocked.  In contrast, "GE>T" indicates maximal
-		inconvenience from blocked tasks.
+		inconvenience from blocked tasks.  CONFIG_TREE_RCU
+		builds of the kernel will always show "..>.".
 
 	o	The numbers separated by the ":" are the range of CPUs
 		served by this struct rcu_node.  This can be helpful
 		in working out how the hierarchy is wired together.
 
-		For example, the first entry at the lowest level shows
-		"0:5", indicating that it covers CPUs 0 through 5.
+		For example, the example rcu_node structure shown above
+		has "0:7", indicating that it covers CPUs 0 through 7.
 
 	o	The number after the "^" indicates the bit in the
-		next higher level rcu_node structure that this
-		rcu_node structure corresponds to.
-
-		For example, the first entry at the lowest level shows
-		"^0", indicating that it corresponds to bit zero in
-		the first entry at the middle level.
-
-
-The output of "cat rcu/rcu_pending" looks as follows:
-
-rcu_sched:
-  0 np=255892 qsp=53936 rpq=85 cbr=0 cng=14417 gpc=10033 gps=24320 nn=146741
-  1 np=261224 qsp=54638 rpq=33 cbr=0 cng=25723 gpc=16310 gps=2849 nn=155792
-  2 np=237496 qsp=49664 rpq=23 cbr=0 cng=2762 gpc=45478 gps=1762 nn=136629
-  3 np=236249 qsp=48766 rpq=98 cbr=0 cng=286 gpc=48049 gps=1218 nn=137723
-  4 np=221310 qsp=46850 rpq=7 cbr=0 cng=26 gpc=43161 gps=4634 nn=123110
-  5 np=237332 qsp=48449 rpq=9 cbr=0 cng=54 gpc=47920 gps=3252 nn=137456
-  6 np=219995 qsp=46718 rpq=12 cbr=0 cng=50 gpc=42098 gps=6093 nn=120834
-  7 np=249893 qsp=49390 rpq=42 cbr=0 cng=72 gpc=38400 gps=17102 nn=144888
-rcu_bh:
-  0 np=146741 qsp=1419 rpq=6 cbr=0 cng=6 gpc=0 gps=0 nn=145314
-  1 np=155792 qsp=12597 rpq=3 cbr=0 cng=0 gpc=4 gps=8 nn=143180
-  2 np=136629 qsp=18680 rpq=1 cbr=0 cng=0 gpc=7 gps=6 nn=117936
-  3 np=137723 qsp=2843 rpq=0 cbr=0 cng=0 gpc=10 gps=7 nn=134863
-  4 np=123110 qsp=12433 rpq=0 cbr=0 cng=0 gpc=4 gps=2 nn=110671
-  5 np=137456 qsp=4210 rpq=1 cbr=0 cng=0 gpc=6 gps=5 nn=133235
-  6 np=120834 qsp=9902 rpq=2 cbr=0 cng=0 gpc=6 gps=3 nn=110921
-  7 np=144888 qsp=26336 rpq=0 cbr=0 cng=0 gpc=8 gps=2 nn=118542
-
-As always, this is once again split into "rcu_sched" and "rcu_bh"
-portions, with CONFIG_TREE_PREEMPT_RCU kernels having an additional
-"rcu_preempt" section.  The fields are as follows:
+		next higher level rcu_node structure that this rcu_node
+		structure corresponds to.  For example, the "d/d ..>. 4:7
+		^1" has a "1" in this position, indicating that it
+		corresponds to the "1" bit in the "3" shown in the
+		"3/3 ..>. 0:7 ^0" entry on the next level up.
+
+
+The output of "cat rcu/rcu_sched/rcu_pending" looks as follows:
+
+  0!np=26111 qsp=29 rpq=5386 cbr=1 cng=570 gpc=3674 gps=577 nn=15903
+  1!np=28913 qsp=35 rpq=6097 cbr=1 cng=448 gpc=3700 gps=554 nn=18113
+  2!np=32740 qsp=37 rpq=6202 cbr=0 cng=476 gpc=4627 gps=546 nn=20889
+  3 np=23679 qsp=22 rpq=5044 cbr=1 cng=415 gpc=3403 gps=347 nn=14469
+  4!np=30714 qsp=4 rpq=5574 cbr=0 cng=528 gpc=3931 gps=639 nn=20042
+  5 np=28910 qsp=2 rpq=5246 cbr=0 cng=428 gpc=4105 gps=709 nn=18422
+  6!np=38648 qsp=5 rpq=7076 cbr=0 cng=840 gpc=4072 gps=961 nn=25699
+  7 np=37275 qsp=2 rpq=6873 cbr=0 cng=868 gpc=3416 gps=971 nn=25147
+
+The fields are as follows:
+
+o	The leading number is the CPU number, with "!" indicating
+	an offline CPU.
 
 o	"np" is the number of times that __rcu_pending() has been invoked
 	for the corresponding flavor of RCU.
@@ -377,38 +432,23 @@ o	"gpc" is the number of times that an old grace period had
 o	"gps" is the number of times that a new grace period had started,
 	but this CPU was not yet aware of it.
 
-o	"nn" is the number of times that this CPU needed nothing.  Alert
-	readers will note that the rcu "nn" number for a given CPU very
-	closely matches the rcu_bh "np" number for that same CPU.  This
-	is due to short-circuit evaluation in rcu_pending().
-
-
-The output of "cat rcu/rcutorture" looks as follows:
-
-rcutorture test sequence: 0 (test in progress)
-rcutorture update version number: 615
-
-The first line shows the number of rcutorture tests that have completed
-since boot.  If a test is currently running, the "(test in progress)"
-string will appear as shown above.  The second line shows the number of
-update cycles that the current test has started, or zero if there is
-no test in progress.
+o	"nn" is the number of times that this CPU needed nothing.
 
 
 The output of "cat rcu/rcuboost" looks as follows:
 
-0:5 tasks=.... kt=W ntb=0 neb=0 nnb=0 j=2f95 bt=300f
-     balk: nt=0 egt=989 bt=0 nb=0 ny=0 nos=16
-6:7 tasks=.... kt=W ntb=0 neb=0 nnb=0 j=2f95 bt=300f
-     balk: nt=0 egt=225 bt=0 nb=0 ny=0 nos=6
+0:3 tasks=.... kt=W ntb=0 neb=0 nnb=0 j=c864 bt=c894
+    balk: nt=0 egt=4695 bt=0 nb=0 ny=56 nos=0
+4:7 tasks=.... kt=W ntb=0 neb=0 nnb=0 j=c864 bt=c894
+    balk: nt=0 egt=6541 bt=0 nb=0 ny=126 nos=0
 
 This information is output only for rcu_preempt.  Each two-line entry
 corresponds to a leaf rcu_node strcuture.  The fields are as follows:
 
 o	"n:m" is the CPU-number range for the corresponding two-line
 	entry.  In the sample output above, the first entry covers
-	CPUs zero through five and the second entry covers CPUs 6
-	and 7.
+	CPUs zero through three and the second entry covers CPUs four
+	through seven.
 
 o	"tasks=TNEB" gives the state of the various segments of the
 	rnp->blocked_tasks list:
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt
index bf0f6de..0cc7820 100644
--- a/Documentation/RCU/whatisRCU.txt
+++ b/Documentation/RCU/whatisRCU.txt
@@ -499,6 +499,8 @@ The foo_reclaim() function might appear as follows:
 	{
 		struct foo *fp = container_of(rp, struct foo, rcu);
 
+		foo_cleanup(fp->a);
+
 		kfree(fp);
 	}
 
@@ -521,6 +523,12 @@ o	Use call_rcu() -after- removing a data element from an
 	read-side critical sections that might be referencing that
 	data item.
 
+If the callback for call_rcu() is not doing anything more than calling
+kfree() on the structure, you can use kfree_rcu() instead of call_rcu()
+to avoid having to write your own callback:
+
+	kfree_rcu(old_fp, rcu);
+
 Again, see checklist.txt for additional rules governing the use of RCU.
 
 
@@ -773,8 +781,8 @@ a single atomic update, converting to RCU will require special care.
 
 Also, the presence of synchronize_rcu() means that the RCU version of
 delete() can now block.  If this is a problem, there is a callback-based
-mechanism that never blocks, namely call_rcu(), that can be used in
-place of synchronize_rcu().
+mechanism that never blocks, namely call_rcu() or kfree_rcu(), that can
+be used in place of synchronize_rcu().
 
 
 7.  FULL LIST OF RCU APIs
@@ -789,9 +797,7 @@ RCU list traversal:
 	list_for_each_entry_rcu
 	hlist_for_each_entry_rcu
 	hlist_nulls_for_each_entry_rcu
-
-	list_for_each_continue_rcu	(to be deprecated in favor of new
-					 list_for_each_entry_continue_rcu)
+	list_for_each_entry_continue_rcu
 
 RCU pointer/list update:
 
@@ -813,6 +819,7 @@ RCU:	Critical sections	Grace period		Barrier
 	rcu_read_unlock		synchronize_rcu
 	rcu_dereference		synchronize_rcu_expedited
 				call_rcu
+				kfree_rcu
 
 
 bh:	Critical sections	Grace period		Barrier
diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c
index 6f706ac..f8ebcde 100644
--- a/Documentation/accounting/getdelays.c
+++ b/Documentation/accounting/getdelays.c
@@ -51,7 +51,6 @@ int dbg;
 int print_delays;
 int print_io_accounting;
 int print_task_context_switch_counts;
-__u64 stime, utime;
 
 #define PRINTF(fmt, arg...) {			\
 	    if (dbg) {				\
diff --git a/Documentation/acpi/initrd_table_override.txt b/Documentation/acpi/initrd_table_override.txt
new file mode 100644
index 0000000..35c3f54
--- /dev/null
+++ b/Documentation/acpi/initrd_table_override.txt
@@ -0,0 +1,94 @@
+Overriding ACPI tables via initrd
+=================================
+
+1) Introduction (What is this about)
+2) What is this for
+3) How does it work
+4) References (Where to retrieve userspace tools)
+
+1) What is this about
+---------------------
+
+If the ACPI_INITRD_TABLE_OVERRIDE compile option is true, it is possible to
+override nearly any ACPI table provided by the BIOS with an instrumented,
+modified one.
+
+For a full list of ACPI tables that can be overridden, take a look at
+the char *table_sigs[MAX_ACPI_SIGNATURE]; definition in drivers/acpi/osl.c
+All ACPI tables iasl (Intel's ACPI compiler and disassembler) knows should
+be overridable, except:
+   - ACPI_SIG_RSDP (has a signature of 6 bytes)
+   - ACPI_SIG_FACS (does not have an ordinary ACPI table header)
+Both could get implemented as well.
+
+
+2) What is this for
+-------------------
+
+Please keep in mind that this is a debug option.
+ACPI tables should not get overridden for productive use.
+If BIOS ACPI tables are overridden the kernel will get tainted with the
+TAINT_OVERRIDDEN_ACPI_TABLE flag.
+Complain to your platform/BIOS vendor if you find a bug which is so sever
+that a workaround is not accepted in the Linux kernel.
+
+Still, it can and should be enabled in any kernel, because:
+  - There is no functional change with not instrumented initrds
+  - It provides a powerful feature to easily debug and test ACPI BIOS table
+    compatibility with the Linux kernel.
+
+
+3) How does it work
+-------------------
+
+# Extract the machine's ACPI tables:
+cd /tmp
+acpidump >acpidump
+acpixtract -a acpidump
+# Disassemble, modify and recompile them:
+iasl -d *.dat
+# For example add this statement into a _PRT (PCI Routing Table) function
+# of the DSDT:
+Store("HELLO WORLD", debug)
+iasl -sa dsdt.dsl
+# Add the raw ACPI tables to an uncompressed cpio archive.
+# They must be put into a /kernel/firmware/acpi directory inside the
+# cpio archive.
+# The uncompressed cpio archive must be the first.
+# Other, typically compressed cpio archives, must be
+# concatenated on top of the uncompressed one.
+mkdir -p kernel/firmware/acpi
+cp dsdt.aml kernel/firmware/acpi
+# A maximum of: #define ACPI_OVERRIDE_TABLES 10
+# tables are  currently allowed (see osl.c):
+iasl -sa facp.dsl
+iasl -sa ssdt1.dsl
+cp facp.aml kernel/firmware/acpi
+cp ssdt1.aml kernel/firmware/acpi
+# Create the uncompressed cpio archive and concatenate the original initrd
+# on top:
+find kernel | cpio -H newc --create > /boot/instrumented_initrd
+cat /boot/initrd >>/boot/instrumented_initrd
+# reboot with increased acpi debug level, e.g. boot params:
+acpi.debug_level=0x2 acpi.debug_layer=0xFFFFFFFF
+# and check your syslog:
+[    1.268089] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0._PRT]
+[    1.272091] [ACPI Debug]  String [0x0B] "HELLO WORLD"
+
+iasl is able to disassemble and recompile quite a lot different,
+also static ACPI tables.
+
+
+4) Where to retrieve userspace tools
+------------------------------------
+
+iasl and acpixtract are part of Intel's ACPICA project:
+http://acpica.org/
+and should be packaged by distributions (for example in the acpica package
+on SUSE).
+
+acpidump can be found in Len Browns pmtools:
+ftp://kernel.org/pub/linux/kernel/people/lenb/acpi/utils/pmtools/acpidump
+This tool is also part of the acpica package on SUSE.
+Alternatively, used ACPI tables can be retrieved via sysfs in latest kernels:
+/sys/firmware/acpi/tables
diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
index a564cee..4484e02 100644
--- a/Documentation/arm/OMAP/DSS
+++ b/Documentation/arm/OMAP/DSS
@@ -285,7 +285,10 @@ FB0 +-- GFX  ---- LCD ---- LCD
 Misc notes
 ----------
 
-OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator.
+OMAP FB allocates the framebuffer memory using the standard dma allocator. You
+can enable Contiguous Memory Allocator (CONFIG_CMA) to improve the dma
+allocator, and if CMA is enabled, you use "cma=" kernel parameter to increase
+the global memory area for CMA.
 
 Using DSI DPLL to generate pixel clock it is possible produce the pixel clock
 of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI.
@@ -301,11 +304,6 @@ framebuffer parameters.
 Kernel boot arguments
 ---------------------
 
-vram=<size>[,<physaddr>]
-	- Amount of total VRAM to preallocate and optionally a physical start
-	  memory address. For example, "10M". omapfb allocates memory for
-	  framebuffers from VRAM.
-
 omapfb.mode=<display>:<mode>[,...]
 	- Default video mode for specified displays. For example,
 	  "dvi:800x400MR-24@60".  See drivers/video/modedb.c.
diff --git a/Documentation/arm/sunxi/README b/Documentation/arm/sunxi/README
new file mode 100644
index 0000000..87a1e8f
--- /dev/null
+++ b/Documentation/arm/sunxi/README
@@ -0,0 +1,19 @@
+ARM Allwinner SoCs
+==================
+
+This document lists all the ARM Allwinner SoCs that are currently
+supported in mainline by the Linux kernel. This document will also
+provide links to documentation and or datasheet for these SoCs.
+
+SunXi family
+------------
+
+  Flavors:
+        Allwinner A10 (sun4i)
+                Datasheet       : http://dl.linux-sunxi.org/A10/A10%20Datasheet%20-%20v1.21%20%282012-04-06%29.pdf
+
+        Allwinner A13 (sun5i)
+                Datasheet       : http://dl.linux-sunxi.org/A13/A13%20Datasheet%20-%20v1.12%20%282012-03-29%29.pdf
+
+  Core: Cortex A8
+  Linux kernel mach directory: arch/arm/mach-sunxi
\ No newline at end of file
diff --git a/Documentation/backlight/lp855x-driver.txt b/Documentation/backlight/lp855x-driver.txt
index f5e4caa..1529394 100644
--- a/Documentation/backlight/lp855x-driver.txt
+++ b/Documentation/backlight/lp855x-driver.txt
@@ -35,11 +35,8 @@ For supporting platform specific data, the lp855x platform data can be used.
 * mode : Brightness control mode. PWM or register based.
 * device_control : Value of DEVICE CONTROL register.
 * initial_brightness : Initial value of backlight brightness.
-* pwm_data : Platform specific pwm generation functions.
+* period_ns : Platform specific PWM period value. unit is nano.
 	     Only valid when brightness is pwm input mode.
-	     Functions should be implemented by PWM driver.
-	     - pwm_set_intensity() : set duty of PWM
-	     - pwm_get_intensity() : get current duty of PWM
 * load_new_rom_data :
 	0 : use default configuration data
 	1 : update values of eeprom or eprom registers on loading driver
@@ -71,8 +68,5 @@ static struct lp855x_platform_data lp8556_pdata = {
 	.mode = PWM_BASED,
 	.device_control = PWM_CONFIG(LP8556),
 	.initial_brightness = INITIAL_BRT,
-	.pwm_data = {
-		     .pwm_set_intensity = platform_pwm_set_intensity,
-		     .pwm_get_intensity = platform_pwm_get_intensity,
-		     },
+	.period_ns = 1000000,
 };
diff --git a/Documentation/bus-devices/ti-gpmc.txt b/Documentation/bus-devices/ti-gpmc.txt
new file mode 100644
index 0000000..cc9ce57
--- /dev/null
+++ b/Documentation/bus-devices/ti-gpmc.txt
@@ -0,0 +1,122 @@
+GPMC (General Purpose Memory Controller):
+=========================================
+
+GPMC is an unified memory controller dedicated to interfacing external
+memory devices like
+ * Asynchronous SRAM like memories and application specific integrated
+   circuit devices.
+ * Asynchronous, synchronous, and page mode burst NOR flash devices
+   NAND flash
+ * Pseudo-SRAM devices
+
+GPMC is found on Texas Instruments SoC's (OMAP based)
+IP details: http://www.ti.com/lit/pdf/spruh73 section 7.1
+
+
+GPMC generic timing calculation:
+================================
+
+GPMC has certain timings that has to be programmed for proper
+functioning of the peripheral, while peripheral has another set of
+timings. To have peripheral work with gpmc, peripheral timings has to
+be translated to the form gpmc can understand. The way it has to be
+translated depends on the connected peripheral. Also there is a
+dependency for certain gpmc timings on gpmc clock frequency. Hence a
+generic timing routine was developed to achieve above requirements.
+
+Generic routine provides a generic method to calculate gpmc timings
+from gpmc peripheral timings. struct gpmc_device_timings fields has to
+be updated with timings from the datasheet of the peripheral that is
+connected to gpmc. A few of the peripheral timings can be fed either
+in time or in cycles, provision to handle this scenario has been
+provided (refer struct gpmc_device_timings definition). It may so
+happen that timing as specified by peripheral datasheet is not present
+in timing structure, in this scenario, try to correlate peripheral
+timing to the one available. If that doesn't work, try to add a new
+field as required by peripheral, educate generic timing routine to
+handle it, make sure that it does not break any of the existing.
+Then there may be cases where peripheral datasheet doesn't mention
+certain fields of struct gpmc_device_timings, zero those entries.
+
+Generic timing routine has been verified to work properly on
+multiple onenand's and tusb6010 peripherals.
+
+A word of caution: generic timing routine has been developed based
+on understanding of gpmc timings, peripheral timings, available
+custom timing routines, a kind of reverse engineering without
+most of the datasheets & hardware (to be exact none of those supported
+in mainline having custom timing routine) and by simulation.
+
+gpmc timing dependency on peripheral timings:
+[<gpmc_timing>: <peripheral timing1>, <peripheral timing2> ...]
+
+1. common
+cs_on: t_ceasu
+adv_on: t_avdasu, t_ceavd
+
+2. sync common
+sync_clk: clk
+page_burst_access: t_bacc
+clk_activation: t_ces, t_avds
+
+3. read async muxed
+adv_rd_off: t_avdp_r
+oe_on: t_oeasu, t_aavdh
+access: t_iaa, t_oe, t_ce, t_aa
+rd_cycle: t_rd_cycle, t_cez_r, t_oez
+
+4. read async non-muxed
+adv_rd_off: t_avdp_r
+oe_on: t_oeasu
+access: t_iaa, t_oe, t_ce, t_aa
+rd_cycle: t_rd_cycle, t_cez_r, t_oez
+
+5. read sync muxed
+adv_rd_off: t_avdp_r, t_avdh
+oe_on: t_oeasu, t_ach, cyc_aavdh_oe
+access: t_iaa, cyc_iaa, cyc_oe
+rd_cycle: t_cez_r, t_oez, t_ce_rdyz
+
+6. read sync non-muxed
+adv_rd_off: t_avdp_r
+oe_on: t_oeasu
+access: t_iaa, cyc_iaa, cyc_oe
+rd_cycle: t_cez_r, t_oez, t_ce_rdyz
+
+7. write async muxed
+adv_wr_off: t_avdp_w
+we_on, wr_data_mux_bus: t_weasu, t_aavdh, cyc_aavhd_we
+we_off: t_wpl
+cs_wr_off: t_wph
+wr_cycle: t_cez_w, t_wr_cycle
+
+8. write async non-muxed
+adv_wr_off: t_avdp_w
+we_on, wr_data_mux_bus: t_weasu
+we_off: t_wpl
+cs_wr_off: t_wph
+wr_cycle: t_cez_w, t_wr_cycle
+
+9. write sync muxed
+adv_wr_off: t_avdp_w, t_avdh
+we_on, wr_data_mux_bus: t_weasu, t_rdyo, t_aavdh, cyc_aavhd_we
+we_off: t_wpl, cyc_wpl
+cs_wr_off: t_wph
+wr_cycle: t_cez_w, t_ce_rdyz
+
+10. write sync non-muxed
+adv_wr_off: t_avdp_w
+we_on, wr_data_mux_bus: t_weasu, t_rdyo
+we_off: t_wpl, cyc_wpl
+cs_wr_off: t_wph
+wr_cycle: t_cez_w, t_ce_rdyz
+
+
+Note: Many of gpmc timings are dependent on other gpmc timings (a few
+gpmc timings purely dependent on other gpmc timings, a reason that
+some of the gpmc timings are missing above), and it will result in
+indirect dependency of peripheral timings to gpmc timings other than
+mentioned above, refer timing routine for more details. To know what
+these peripheral timings correspond to, please see explanations in
+struct gpmc_device_timings definition. And for gpmc timings refer
+IP details (link above).
diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
index 9e04196..bcf1a00 100644
--- a/Documentation/cgroups/cgroups.txt
+++ b/Documentation/cgroups/cgroups.txt
@@ -299,11 +299,9 @@ a cgroup hierarchy's release_agent path is empty.
 1.5 What does clone_children do ?
 ---------------------------------
 
-If the clone_children flag is enabled (1) in a cgroup, then all
-cgroups created beneath will call the post_clone callbacks for each
-subsystem of the newly created cgroup. Usually when this callback is
-implemented for a subsystem, it copies the values of the parent
-subsystem, this is the case for the cpuset.
+This flag only affects the cpuset controller. If the clone_children
+flag is enabled (1) in a cgroup, a new cpuset cgroup will copy its
+configuration from the parent during initialization.
 
 1.6 How do I use cgroups ?
 --------------------------
@@ -553,16 +551,16 @@ call to cgroup_unload_subsys(). It should also set its_subsys.module =
 THIS_MODULE in its .c file.
 
 Each subsystem may export the following methods. The only mandatory
-methods are create/destroy. Any others that are null are presumed to
+methods are css_alloc/free. Any others that are null are presumed to
 be successful no-ops.
 
-struct cgroup_subsys_state *create(struct cgroup *cgrp)
+struct cgroup_subsys_state *css_alloc(struct cgroup *cgrp)
 (cgroup_mutex held by caller)
 
-Called to create a subsystem state object for a cgroup. The
+Called to allocate a subsystem state object for a cgroup. The
 subsystem should allocate its subsystem state object for the passed
 cgroup, returning a pointer to the new object on success or a
-negative error code. On success, the subsystem pointer should point to
+ERR_PTR() value. On success, the subsystem pointer should point to
 a structure of type cgroup_subsys_state (typically embedded in a
 larger subsystem-specific object), which will be initialized by the
 cgroup system. Note that this will be called at initialization to
@@ -571,24 +569,33 @@ identified by the passed cgroup object having a NULL parent (since
 it's the root of the hierarchy) and may be an appropriate place for
 initialization code.
 
-void destroy(struct cgroup *cgrp)
+int css_online(struct cgroup *cgrp)
 (cgroup_mutex held by caller)
 
-The cgroup system is about to destroy the passed cgroup; the subsystem
-should do any necessary cleanup and free its subsystem state
-object. By the time this method is called, the cgroup has already been
-unlinked from the file system and from the child list of its parent;
-cgroup->parent is still valid. (Note - can also be called for a
-newly-created cgroup if an error occurs after this subsystem's
-create() method has been called for the new cgroup).
+Called after @cgrp successfully completed all allocations and made
+visible to cgroup_for_each_child/descendant_*() iterators. The
+subsystem may choose to fail creation by returning -errno. This
+callback can be used to implement reliable state sharing and
+propagation along the hierarchy. See the comment on
+cgroup_for_each_descendant_pre() for details.
 
-int pre_destroy(struct cgroup *cgrp);
+void css_offline(struct cgroup *cgrp);
 
-Called before checking the reference count on each subsystem. This may
-be useful for subsystems which have some extra references even if
-there are not tasks in the cgroup. If pre_destroy() returns error code,
-rmdir() will fail with it. From this behavior, pre_destroy() can be
-called multiple times against a cgroup.
+This is the counterpart of css_online() and called iff css_online()
+has succeeded on @cgrp. This signifies the beginning of the end of
+@cgrp. @cgrp is being removed and the subsystem should start dropping
+all references it's holding on @cgrp. When all references are dropped,
+cgroup removal will proceed to the next step - css_free(). After this
+callback, @cgrp should be considered dead to the subsystem.
+
+void css_free(struct cgroup *cgrp)
+(cgroup_mutex held by caller)
+
+The cgroup system is about to free @cgrp; the subsystem should free
+its subsystem state object. By the time this method is called, @cgrp
+is completely unused; @cgrp->parent is still valid. (Note - can also
+be called for a newly-created cgroup if an error occurs after this
+subsystem's create() method has been called for the new cgroup).
 
 int can_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
 (cgroup_mutex held by caller)
@@ -635,14 +642,6 @@ void exit(struct task_struct *task)
 
 Called during task exit.
 
-void post_clone(struct cgroup *cgrp)
-(cgroup_mutex held by caller)
-
-Called during cgroup_create() to do any parameter
-initialization which might be required before a task could attach.  For
-example, in cpusets, no task may attach before 'cpus' and 'mems' are set
-up.
-
 void bind(struct cgroup *root)
 (cgroup_mutex held by caller)
 
diff --git a/Documentation/cgroups/cpusets.txt b/Documentation/cgroups/cpusets.txt
index cefd3d8..12e01d4 100644
--- a/Documentation/cgroups/cpusets.txt
+++ b/Documentation/cgroups/cpusets.txt
@@ -218,7 +218,7 @@ and name space for cpusets, with a minimum of additional kernel code.
 The cpus and mems files in the root (top_cpuset) cpuset are
 read-only.  The cpus file automatically tracks the value of
 cpu_online_mask using a CPU hotplug notifier, and the mems file
-automatically tracks the value of node_states[N_HIGH_MEMORY]--i.e.,
+automatically tracks the value of node_states[N_MEMORY]--i.e.,
 nodes with memory--using the cpuset_track_online_nodes() hook.
 
 
diff --git a/Documentation/cgroups/freezer-subsystem.txt b/Documentation/cgroups/freezer-subsystem.txt
index 7e62de1..c96a72c 100644
--- a/Documentation/cgroups/freezer-subsystem.txt
+++ b/Documentation/cgroups/freezer-subsystem.txt
@@ -49,13 +49,49 @@ prevent the freeze/unfreeze cycle from becoming visible to the tasks
 being frozen. This allows the bash example above and gdb to run as
 expected.
 
-The freezer subsystem in the container filesystem defines a file named
-freezer.state. Writing "FROZEN" to the state file will freeze all tasks in the
-cgroup. Subsequently writing "THAWED" will unfreeze the tasks in the cgroup.
-Reading will return the current state.
+The cgroup freezer is hierarchical. Freezing a cgroup freezes all
+tasks beloning to the cgroup and all its descendant cgroups. Each
+cgroup has its own state (self-state) and the state inherited from the
+parent (parent-state). Iff both states are THAWED, the cgroup is
+THAWED.
 
-Note freezer.state doesn't exist in root cgroup, which means root cgroup
-is non-freezable.
+The following cgroupfs files are created by cgroup freezer.
+
+* freezer.state: Read-write.
+
+  When read, returns the effective state of the cgroup - "THAWED",
+  "FREEZING" or "FROZEN". This is the combined self and parent-states.
+  If any is freezing, the cgroup is freezing (FREEZING or FROZEN).
+
+  FREEZING cgroup transitions into FROZEN state when all tasks
+  belonging to the cgroup and its descendants become frozen. Note that
+  a cgroup reverts to FREEZING from FROZEN after a new task is added
+  to the cgroup or one of its descendant cgroups until the new task is
+  frozen.
+
+  When written, sets the self-state of the cgroup. Two values are
+  allowed - "FROZEN" and "THAWED". If FROZEN is written, the cgroup,
+  if not already freezing, enters FREEZING state along with all its
+  descendant cgroups.
+
+  If THAWED is written, the self-state of the cgroup is changed to
+  THAWED.  Note that the effective state may not change to THAWED if
+  the parent-state is still freezing. If a cgroup's effective state
+  becomes THAWED, all its descendants which are freezing because of
+  the cgroup also leave the freezing state.
+
+* freezer.self_freezing: Read only.
+
+  Shows the self-state. 0 if the self-state is THAWED; otherwise, 1.
+  This value is 1 iff the last write to freezer.state was "FROZEN".
+
+* freezer.parent_freezing: Read only.
+
+  Shows the parent-state.  0 if none of the cgroup's ancestors is
+  frozen; otherwise, 1.
+
+The root cgroup is non-freezable and the above interface files don't
+exist.
 
 * Examples of usage :
 
@@ -85,18 +121,3 @@ to unfreeze all tasks in the container :
 
 This is the basic mechanism which should do the right thing for user space task
 in a simple scenario.
-
-It's important to note that freezing can be incomplete. In that case we return
-EBUSY. This means that some tasks in the cgroup are busy doing something that
-prevents us from completely freezing the cgroup at this time. After EBUSY,
-the cgroup will remain partially frozen -- reflected by freezer.state reporting
-"FREEZING" when read. The state will remain "FREEZING" until one of these
-things happens:
-
-	1) Userspace cancels the freezing operation by writing "THAWED" to
-		the freezer.state file
-	2) Userspace retries the freezing operation by writing "FROZEN" to
-		the freezer.state file (writing "FREEZING" is not legal
-		and returns EINVAL)
-	3) The tasks that blocked the cgroup from entering the "FROZEN"
-		state disappear from the cgroup's set of tasks.
diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
index 71c4da4..8b8c28b 100644
--- a/Documentation/cgroups/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -71,6 +71,11 @@ Brief summary of control files.
  memory.oom_control		 # set/show oom controls.
  memory.numa_stat		 # show the number of memory usage per numa node
 
+ memory.kmem.limit_in_bytes      # set/show hard limit for kernel memory
+ memory.kmem.usage_in_bytes      # show current kernel memory allocation
+ memory.kmem.failcnt             # show the number of kernel memory usage hits limits
+ memory.kmem.max_usage_in_bytes  # show max kernel memory usage recorded
+
  memory.kmem.tcp.limit_in_bytes  # set/show hard limit for tcp buf memory
  memory.kmem.tcp.usage_in_bytes  # show current tcp buf memory allocation
  memory.kmem.tcp.failcnt            # show the number of tcp buf memory usage hits limits
@@ -144,9 +149,9 @@ Figure 1 shows the important aspects of the controller
 3. Each page has a pointer to the page_cgroup, which in turn knows the
    cgroup it belongs to
 
-The accounting is done as follows: mem_cgroup_charge() is invoked to set up
-the necessary data structures and check if the cgroup that is being charged
-is over its limit. If it is, then reclaim is invoked on the cgroup.
+The accounting is done as follows: mem_cgroup_charge_common() is invoked to
+set up the necessary data structures and check if the cgroup that is being
+charged is over its limit. If it is, then reclaim is invoked on the cgroup.
 More details can be found in the reclaim section of this document.
 If everything goes well, a page meta-data-structure called page_cgroup is
 updated. page_cgroup has its own LRU on cgroup.
@@ -268,20 +273,73 @@ the amount of kernel memory used by the system. Kernel memory is fundamentally
 different than user memory, since it can't be swapped out, which makes it
 possible to DoS the system by consuming too much of this precious resource.
 
+Kernel memory won't be accounted at all until limit on a group is set. This
+allows for existing setups to continue working without disruption.  The limit
+cannot be set if the cgroup have children, or if there are already tasks in the
+cgroup. Attempting to set the limit under those conditions will return -EBUSY.
+When use_hierarchy == 1 and a group is accounted, its children will
+automatically be accounted regardless of their limit value.
+
+After a group is first limited, it will be kept being accounted until it
+is removed. The memory limitation itself, can of course be removed by writing
+-1 to memory.kmem.limit_in_bytes. In this case, kmem will be accounted, but not
+limited.
+
 Kernel memory limits are not imposed for the root cgroup. Usage for the root
-cgroup may or may not be accounted.
+cgroup may or may not be accounted. The memory used is accumulated into
+memory.kmem.usage_in_bytes, or in a separate counter when it makes sense.
+(currently only for tcp).
+The main "kmem" counter is fed into the main counter, so kmem charges will
+also be visible from the user counter.
 
 Currently no soft limit is implemented for kernel memory. It is future work
 to trigger slab reclaim when those limits are reached.
 
 2.7.1 Current Kernel Memory resources accounted
 
+* stack pages: every process consumes some stack pages. By accounting into
+kernel memory, we prevent new processes from being created when the kernel
+memory usage is too high.
+
+* slab pages: pages allocated by the SLAB or SLUB allocator are tracked. A copy
+of each kmem_cache is created everytime the cache is touched by the first time
+from inside the memcg. The creation is done lazily, so some objects can still be
+skipped while the cache is being created. All objects in a slab page should
+belong to the same memcg. This only fails to hold when a task is migrated to a
+different memcg during the page allocation by the cache.
+
 * sockets memory pressure: some sockets protocols have memory pressure
 thresholds. The Memory Controller allows them to be controlled individually
 per cgroup, instead of globally.
 
 * tcp memory pressure: sockets memory pressure for the tcp protocol.
 
+2.7.3 Common use cases
+
+Because the "kmem" counter is fed to the main user counter, kernel memory can
+never be limited completely independently of user memory. Say "U" is the user
+limit, and "K" the kernel limit. There are three possible ways limits can be
+set:
+
+    U != 0, K = unlimited:
+    This is the standard memcg limitation mechanism already present before kmem
+    accounting. Kernel memory is completely ignored.
+
+    U != 0, K < U:
+    Kernel memory is a subset of the user memory. This setup is useful in
+    deployments where the total amount of memory per-cgroup is overcommited.
+    Overcommiting kernel memory limits is definitely not recommended, since the
+    box can still run out of non-reclaimable memory.
+    In this case, the admin could set up K so that the sum of all groups is
+    never greater than the total memory, and freely set U at the cost of his
+    QoS.
+
+    U != 0, K >= U:
+    Since kmem charges will also be fed to the user counter and reclaim will be
+    triggered for the cgroup for both kinds of memory. This setup gives the
+    admin a unified view of memory, and it is also useful for people who just
+    want to track kernel memory usage.
+
 3. User Interface
 
 0. Configuration
@@ -290,6 +348,7 @@ a. Enable CONFIG_CGROUPS
 b. Enable CONFIG_RESOURCE_COUNTERS
 c. Enable CONFIG_MEMCG
 d. Enable CONFIG_MEMCG_SWAP (to use swap extension)
+d. Enable CONFIG_MEMCG_KMEM (to use kmem extension)
 
 1. Prepare the cgroups (see cgroups.txt, Why are cgroups needed?)
 # mount -t tmpfs none /sys/fs/cgroup
@@ -406,6 +465,11 @@ About use_hierarchy, see Section 6.
   Because rmdir() moves all pages to parent, some out-of-use page caches can be
   moved to the parent. If you want to avoid that, force_empty will be useful.
 
+  Also, note that when memory.kmem.limit_in_bytes is set the charges due to
+  kernel pages will still be seen. This is not considered a failure and the
+  write will still return success. In this case, it is expected that
+  memory.kmem.usage_in_bytes == memory.usage_in_bytes.
+
   About use_hierarchy, see Section 6.
 
 5.2 stat file
diff --git a/Documentation/cgroups/net_prio.txt b/Documentation/cgroups/net_prio.txt
index 01b3226..a82cbd2 100644
--- a/Documentation/cgroups/net_prio.txt
+++ b/Documentation/cgroups/net_prio.txt
@@ -51,3 +51,5 @@ One usage for the net_prio cgroup is with mqprio qdisc allowing application
 traffic to be steered to hardware/driver based traffic classes. These mappings
 can then be managed by administrators or other networking protocols such as
 DCBX.
+
+A new net_prio cgroup inherits the parent's configuration.
diff --git a/Documentation/cgroups/resource_counter.txt b/Documentation/cgroups/resource_counter.txt
index 0c4a344..c4d99ed 100644
--- a/Documentation/cgroups/resource_counter.txt
+++ b/Documentation/cgroups/resource_counter.txt
@@ -83,16 +83,17 @@ to work with it.
 	res_counter->lock internally (it must be called with res_counter->lock
 	held). The force parameter indicates whether we can bypass the limit.
 
- e. void res_counter_uncharge[_locked]
+ e. u64 res_counter_uncharge[_locked]
 			(struct res_counter *rc, unsigned long val)
 
 	When a resource is released (freed) it should be de-accounted
 	from the resource counter it was accounted to.  This is called
-	"uncharging".
+	"uncharging". The return value of this function indicate the amount
+	of charges still present in the counter.
 
 	The _locked routines imply that the res_counter->lock is taken.
 
- f. void res_counter_uncharge_until
+ f. u64 res_counter_uncharge_until
 		(struct res_counter *rc, struct res_counter *top,
 		 unsinged long val)
 
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index b6251cc..08f01e7 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -2561,9 +2561,6 @@ Your cooperation is appreciated.
 		192 = /dev/usb/yurex1	First USB Yurex device
 		   ...
 		209 = /dev/usb/yurex16	16th USB Yurex device
-		240 = /dev/usb/dabusb0	First daubusb device
-		    ...
-		243 = /dev/usb/dabusb3	Fourth dabusb device
 
 180 block	USB block devices
 		  0 = /dev/uba		First USB block device
diff --git a/Documentation/devicetree/bindings/arm/altera/socfpga-reset.txt b/Documentation/devicetree/bindings/arm/altera/socfpga-reset.txt
new file mode 100644
index 0000000..ecdb57d
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/altera/socfpga-reset.txt
@@ -0,0 +1,11 @@
+Altera SOCFPGA Reset Manager
+
+Required properties:
+- compatible : "altr,rst-mgr"
+- reg : Should contain 1 register ranges(address and length)
+
+Example:
+	 rstmgr@ffd05000 {
+		compatible = "altr,rst-mgr";
+		reg = <0xffd05000 0x1000>;
+	};
diff --git a/Documentation/devicetree/bindings/arm/altera/socfpga-system.txt b/Documentation/devicetree/bindings/arm/altera/socfpga-system.txt
new file mode 100644
index 0000000..07c65e3
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/altera/socfpga-system.txt
@@ -0,0 +1,11 @@
+Altera SOCFPGA System Manager
+
+Required properties:
+- compatible : "altr,sys-mgr"
+- reg : Should contain 1 register ranges(address and length)
+
+Example:
+	 sysmgr@ffd08000 {
+		compatible = "altr,sys-mgr";
+		reg = <0xffd08000 0x1000>;
+	};
diff --git a/Documentation/devicetree/bindings/arm/arm-boards b/Documentation/devicetree/bindings/arm/arm-boards
index fc81a7d..db5858e 100644
--- a/Documentation/devicetree/bindings/arm/arm-boards
+++ b/Documentation/devicetree/bindings/arm/arm-boards
@@ -9,6 +9,10 @@ Required properties (in root node):
 
 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.
+
 
 ARM Versatile Application and Platform Baseboards
 -------------------------------------------------
diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt
index d187e9f..1196290 100644
--- a/Documentation/devicetree/bindings/arm/atmel-at91.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt
@@ -7,6 +7,12 @@ PIT Timer required properties:
 - interrupts: Should contain interrupt for the PIT which is the IRQ line
   shared across all System Controller members.
 
+System Timer (ST) required properties:
+- compatible: Should be "atmel,at91rm9200-st"
+- reg: Should contain registers location and length
+- interrupts: Should contain interrupt for the ST which is the IRQ line
+  shared across all System Controller members.
+
 TC/TCLIB Timer required properties:
 - compatible: Should be "atmel,<chip>-tcb".
   <chip> can be "at91rm9200" or "at91sam9x5"
diff --git a/Documentation/devicetree/bindings/arm/bcm/bcm11351.txt b/Documentation/devicetree/bindings/arm/bcm/bcm11351.txt
new file mode 100644
index 0000000..fb7b5cd
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/bcm/bcm11351.txt
@@ -0,0 +1,9 @@
+Broadcom BCM11351 device tree bindings
+-------------------------------------------
+
+Boards with the bcm281xx SoC family (which includes bcm11130, bcm11140,
+bcm11351, bcm28145, bcm28155 SoCs) shall have the following properties:
+
+Required root node property:
+
+compatible = "bcm,bcm11351";
diff --git a/Documentation/devicetree/bindings/arm/calxeda.txt b/Documentation/devicetree/bindings/arm/calxeda.txt
index 4755caa..25fcf96 100644
--- a/Documentation/devicetree/bindings/arm/calxeda.txt
+++ b/Documentation/devicetree/bindings/arm/calxeda.txt
@@ -1,8 +1,15 @@
-Calxeda Highbank Platforms Device Tree Bindings
+Calxeda Platforms Device Tree Bindings
 -----------------------------------------------
 
-Boards with Calxeda Cortex-A9 based Highbank SOC shall have the following
-properties.
+Boards with Calxeda Cortex-A9 based ECX-1000 (Highbank) SOC shall have the
+following properties.
 
 Required root node properties:
     - compatible = "calxeda,highbank";
+
+
+Boards with Calxeda Cortex-A15 based ECX-2000 SOC shall have the following
+properties.
+
+Required root node properties:
+    - compatible = "calxeda,ecx-2000";
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
new file mode 100644
index 0000000..f32494d
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -0,0 +1,77 @@
+* ARM CPUs binding description
+
+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:
+
+http://devicetree.org
+
+For the ARM architecture every CPU node must contain the following properties:
+
+- 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"
+
+Example:
+
+	cpus {
+		#size-cells = <0>;
+		#address-cells = <1>;
+
+		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@100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x100>;
+		};
+
+		CPU3: cpu@101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x101>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/arm/davinci.txt b/Documentation/devicetree/bindings/arm/davinci.txt
new file mode 100644
index 0000000..cfaeda4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/davinci.txt
@@ -0,0 +1,17 @@
+Texas Instruments DaVinci Platforms Device Tree Bindings
+--------------------------------------------------------
+
+DA850/OMAP-L138/AM18x Evaluation Module (EVM) board
+Required root node properties:
+    - compatible = "ti,da850-evm", "ti,da850";
+
+EnBW AM1808 based CMC board
+Required root node properties:
+    - compatible = "enbw,cmc", "ti,da850;
+
+Generic DaVinci Boards
+----------------------
+
+DA850/OMAP-L138/AM18x generic board
+Required root node properties:
+    - compatible = "ti,da850";
diff --git a/Documentation/devicetree/bindings/arm/davinci/nand.txt b/Documentation/devicetree/bindings/arm/davinci/nand.txt
index e37241f..4746452 100644
--- a/Documentation/devicetree/bindings/arm/davinci/nand.txt
+++ b/Documentation/devicetree/bindings/arm/davinci/nand.txt
@@ -23,6 +23,9 @@ Recommended properties :
 - ti,davinci-nand-buswidth: buswidth 8 or 16
 - ti,davinci-nand-use-bbt: use flash based bad block table support.
 
+nand device bindings may contain additional sub-nodes describing
+partitions of the address space. See partition.txt for more detail.
+
 Example (enbw_cmc board):
 aemif@60000000 {
 	compatible = "ti,davinci-aemif";
@@ -47,5 +50,10 @@ aemif@60000000 {
 		ti,davinci-ecc-mode = "hw";
 		ti,davinci-ecc-bits = <4>;
 		ti,davinci-nand-use-bbt;
+
+		partition@180000 {
+			label = "ubifs";
+			reg = <0x180000 0x7e80000>;
+		};
 	};
 };
diff --git a/Documentation/devicetree/bindings/arm/exynos/power_domain.txt b/Documentation/devicetree/bindings/arm/exynos/power_domain.txt
index 6528e21..5216b41 100644
--- a/Documentation/devicetree/bindings/arm/exynos/power_domain.txt
+++ b/Documentation/devicetree/bindings/arm/exynos/power_domain.txt
@@ -4,14 +4,13 @@ Exynos processors include support for multiple power domains which are used
 to gate power to one or more peripherals on the processor.
 
 Required Properties:
-- compatiable: should be one of the following.
+- compatible: should be one of the following.
     * samsung,exynos4210-pd - for exynos4210 type power domain.
 - reg: physical base address of the controller and length of memory mapped
     region.
 
-Optional Properties:
-- samsung,exynos4210-pd-off: Specifies that the power domain is in turned-off
-    state during boot and remains to be turned-off until explicitly turned-on.
+Node of a device using power domains must have a samsung,power-domain property
+defined with a phandle to respective power domain.
 
 Example:
 
@@ -19,3 +18,11 @@ Example:
 		compatible = "samsung,exynos4210-pd";
 		reg = <0x10023C00 0x10>;
 	};
+
+Example of the node using power domain:
+
+	node {
+		/* ... */
+		samsung,power-domain = <&lcd0>;
+		/* ... */
+	};
diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt
index ac9e751..f798187 100644
--- a/Documentation/devicetree/bindings/arm/fsl.txt
+++ b/Documentation/devicetree/bindings/arm/fsl.txt
@@ -41,6 +41,10 @@ i.MX6 Quad SABRE Smart Device Board
 Required root node properties:
     - compatible = "fsl,imx6q-sabresd", "fsl,imx6q";
 
+i.MX6 Quad SABRE Automotive Board
+Required root node properties:
+    - compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
+
 Generic i.MX boards
 -------------------
 
diff --git a/Documentation/devicetree/bindings/arm/l2cc.txt b/Documentation/devicetree/bindings/arm/l2cc.txt
index 7ca5216..7c3ee3a 100644
--- a/Documentation/devicetree/bindings/arm/l2cc.txt
+++ b/Documentation/devicetree/bindings/arm/l2cc.txt
@@ -37,7 +37,7 @@ L2: cache-controller {
         reg = <0xfff12000 0x1000>;
         arm,data-latency = <1 1 1>;
         arm,tag-latency = <2 2 2>;
-        arm,filter-latency = <0x80000000 0x8000000>;
+        arm,filter-ranges = <0x80000000 0x8000000>;
         cache-unified;
         cache-level = <2>;
 	interrupts = <45>;
diff --git a/Documentation/devicetree/bindings/arm/omap/counter.txt b/Documentation/devicetree/bindings/arm/omap/counter.txt
new file mode 100644
index 0000000..5bd8aa0
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/counter.txt
@@ -0,0 +1,15 @@
+OMAP Counter-32K bindings
+
+Required properties:
+- compatible:	Must be "ti,omap-counter32k" for OMAP controllers
+- reg:		Contains timer register address range (base address and length)
+- ti,hwmods:	Name of the hwmod associated to the counter, which is typically
+		"counter_32k"
+
+Example:
+
+counter32k: counter@4a304000 {
+	compatible = "ti,omap-counter32k";
+	reg = <0x4a304000 0x20>;
+	ti,hwmods = "counter_32k";
+};
diff --git a/Documentation/devicetree/bindings/arm/omap/timer.txt b/Documentation/devicetree/bindings/arm/omap/timer.txt
new file mode 100644
index 0000000..8732d4d
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/timer.txt
@@ -0,0 +1,31 @@
+OMAP Timer bindings
+
+Required properties:
+- compatible:		Must be "ti,omap2-timer" for OMAP2+ controllers.
+- reg:			Contains timer register address range (base address and
+			length).
+- interrupts: 		Contains the interrupt information for the timer. The
+			format is being dependent on which interrupt controller
+			the OMAP device uses.
+- ti,hwmods:		Name of the hwmod associated to the timer, "timer<X>",
+			where <X> is the instance number of the timer from the
+			HW spec.
+
+Optional properties:
+- ti,timer-alwon:	Indicates the timer is in an alway-on power domain.
+- ti,timer-dsp:		Indicates the timer can interrupt the on-chip DSP in
+			addition to the ARM CPU.
+- ti,timer-pwm: 	Indicates the timer can generate a PWM output.
+- ti,timer-secure: 	Indicates the timer is reserved on a secure OMAP device
+			and therefore cannot be used by the kernel.
+
+Example:
+
+timer12: timer@48304000 {
+	compatible = "ti,omap2-timer";
+	reg = <0x48304000 0x400>;
+	interrupts = <95>;
+	ti,hwmods = "timer12"
+	ti,timer-alwon;
+	ti,timer-secure;
+};
diff --git a/Documentation/devicetree/bindings/arm/spear/shirq.txt b/Documentation/devicetree/bindings/arm/spear/shirq.txt
new file mode 100644
index 0000000..13fbb88
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/spear/shirq.txt
@@ -0,0 +1,48 @@
+* SPEAr Shared IRQ layer (shirq)
+
+SPEAr3xx architecture includes shared/multiplexed irqs for certain set
+of devices. The multiplexor provides a single interrupt to parent
+interrupt controller (VIC) on behalf of a group of devices.
+
+There can be multiple groups available on SPEAr3xx variants but not
+exceeding 4. The number of devices in a group can differ, further they
+may share same set of status/mask registers spanning across different
+bit masks. Also in some cases the group may not have enable or other
+registers. This makes software little complex.
+
+A single node in the device tree is used to describe the shared
+interrupt multiplexor (one node for all groups). A group in the
+interrupt controller shares config/control registers with other groups.
+For example, a 32-bit interrupt enable/disable config register can
+accommodate upto 4 interrupt groups.
+
+Required properties:
+  - compatible: should be, either of
+     - "st,spear300-shirq"
+     - "st,spear310-shirq"
+     - "st,spear320-shirq"
+  - interrupt-controller: Identifies the node as an interrupt controller.
+  - #interrupt-cells: should be <1> which basically contains the offset
+    (starting from 0) of interrupts for all the groups.
+  - reg: Base address and size of shirq registers.
+  - interrupts: The list of interrupts generated by the groups which are
+    then connected to a parent interrupt controller. Each group is
+    associated with one of the interrupts, hence number of interrupts (to
+    parent) is equal to number of groups. The format of the interrupt
+    specifier depends in the interrupt parent controller.
+
+  Optional properties:
+  - interrupt-parent: pHandle of the parent interrupt controller, if not
+    inherited from the parent node.
+
+Example:
+
+The following is an example from the SPEAr320 SoC dtsi file.
+
+shirq: interrupt-controller@0xb3000000 {
+	compatible = "st,spear320-shirq";
+	reg = <0xb3000000 0x1000>;
+	interrupts = <28 29 30 1>;
+	#interrupt-cells = <1>;
+	interrupt-controller;
+};
diff --git a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
new file mode 100644
index 0000000..9cf3f25
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
@@ -0,0 +1,50 @@
+ARM Versatile Express system registers
+--------------------------------------
+
+This is a system control registers block, providing multiple low level
+platform functions like board detection and identification, software
+interrupt generation, MMC and NOR Flash control etc.
+
+Required node properties:
+- compatible value : = "arm,vexpress,sysreg";
+- reg : physical base address and the size of the registers window
+- gpio-controller : specifies that the node is a GPIO controller
+- #gpio-cells : size of the GPIO specifier, should be 2:
+  - first cell is the pseudo-GPIO line number:
+    0 - MMC CARDIN
+    1 - MMC WPROT
+    2 - NOR FLASH WPn
+  - second cell can take standard GPIO flags (currently ignored).
+
+Example:
+	v2m_sysreg: sysreg@10000000 {
+ 		compatible = "arm,vexpress-sysreg";
+ 		reg = <0x10000000 0x1000>;
+		gpio-controller;
+		#gpio-cells = <2>;
+ 	};
+
+This block also can also act a bridge to the platform's configuration
+bus via "system control" interface, addressing devices with site number,
+position in the board stack, config controller, function and device
+numbers - see motherboard's TRM for more details.
+
+The node describing a config device must refer to the sysreg node via
+"arm,vexpress,config-bridge" phandle (can be also defined in the node's
+parent) and relies on the board topology properties - see main vexpress
+node documentation for more details. It must must also define the
+following property:
+- arm,vexpress-sysreg,func : must contain two cells:
+  - first cell defines function number (eg. 1 for clock generator,
+    2 for voltage regulators etc.)
+  - device number (eg. osc 0, osc 1 etc.)
+
+Example:
+	mcc {
+		arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+		osc@0 {
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 0>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/arm/vexpress.txt b/Documentation/devicetree/bindings/arm/vexpress.txt
index ec8b50c..ae49161 100644
--- a/Documentation/devicetree/bindings/arm/vexpress.txt
+++ b/Documentation/devicetree/bindings/arm/vexpress.txt
@@ -11,6 +11,10 @@ the motherboard file using a /include/ directive. As the motherboard
 can be initialized in one of two different configurations ("memory
 maps"), care must be taken to include the correct one.
 
+
+Root node
+---------
+
 Required properties in the root node:
 - compatible value:
 	compatible = "arm,vexpress,<model>", "arm,vexpress";
@@ -45,6 +49,10 @@ Optional properties in the root node:
   - Coretile Express A9x4 (V2P-CA9) HBI-0225:
 	arm,hbi = <0x225>;
 
+
+CPU nodes
+---------
+
 Top-level standard "cpus" node is required. It must contain a node
 with device_type = "cpu" property for every available core, eg.:
 
@@ -59,6 +67,52 @@ with device_type = "cpu" property for every available core, eg.:
 		};
 	};
 
+
+Configuration infrastructure
+----------------------------
+
+The platform has an elaborated configuration system, consisting of
+microcontrollers residing on the mother- and daughterboards known
+as Motherboard/Daughterboard Configuration Controller (MCC and DCC).
+The controllers are responsible for the platform initialization
+(reset generation, flash programming, FPGA bitfiles loading etc.)
+but also control clock generators, voltage regulators, gather
+environmental data like temperature, power consumption etc. Even
+the video output switch (FPGA) is controlled that way.
+
+Nodes describing devices controlled by this infrastructure should
+point at the bridge device node:
+- bridge phandle:
+	arm,vexpress,config-bridge = <phandle>;
+This property can be also defined in a parent node (eg. for a DCC)
+and is effective for all children.
+
+
+Platform topology
+-----------------
+
+As Versatile Express can be configured in number of physically
+different setups, the device tree should describe platform topology.
+Root node and main motherboard node must define the following
+property, describing physical location of the children nodes:
+- site number:
+	arm,vexpress,site = <number>;
+  where 0 means motherboard, 1 or 2 are daugtherboard sites,
+  0xf means "master" site (site containing main CPU tile)
+- when daughterboards are stacked on one site, their position
+  in the stack be be described with:
+	arm,vexpress,position = <number>;
+- when describing tiles consisting more than one DCC, its number
+  can be described with:
+	arm,vexpress,dcc = <number>;
+
+Any of the numbers above defaults to zero if not defined in
+the node or any of its parent.
+
+
+Motherboard
+-----------
+
 The motherboard description file provides a single "motherboard" node
 using 2 address cells corresponding to the Static Memory Bus used
 between the motherboard and the tile. The first cell defines the Chip
@@ -87,22 +141,30 @@ can be used to obtain required phandle in the tile's "aliases" node:
 - SP804 timers:
 	v2m_timer01 and v2m_timer23
 
-Current Linux implementation requires a "arm,v2m_timer" alias
-pointing at one of the motherboard's SP804 timers, if it is to be
-used as the system timer. This alias should be defined in the
-motherboard files.
+The tile description should define a "smb" node, describing the
+Static Memory Bus between the tile and motherboard. It must define
+the following properties:
+- "simple-bus" compatible value (to ensure creation of the children)
+	compatible = "simple-bus";
+- mapping of the SMB CS/offset addresses into main address space:
+	#address-cells = <2>;
+	#size-cells = <1>;
+	ranges = <...>;
+- interrupts mapping:
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0 0 63>;
+	interrupt-map = <...>;
 
-The tile description must define "ranges", "interrupt-map-mask" and
-"interrupt-map" properties to translate the motherboard's address
-and interrupt space into one used by the tile's processor.
 
-Abbreviated example:
+Example of a VE tile description (simplified)
+---------------------------------------------
 
 /dts-v1/;
 
 / {
 	model = "V2P-CA5s";
 	arm,hbi = <0x225>;
+	arm,vexpress,site = <0xf>;
 	compatible = "arm,vexpress-v2p-ca5s", "arm,vexpress";
 	interrupt-parent = <&gic>;
 	#address-cells = <1>;
@@ -134,13 +196,29 @@ Abbreviated example:
 		      <0x2c000100 0x100>;
 	};
 
-	motherboard {
+	dcc {
+		compatible = "simple-bus";
+		arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+		osc@0 {
+			compatible = "arm,vexpress-osc";
+		};
+	};
+
+	smb {
+		compatible = "simple-bus";
+
+		#address-cells = <2>;
+		#size-cells = <1>;
 		/* CS0 is visible at 0x08000000 */
 		ranges = <0 0 0x08000000 0x04000000>;
+
+		#interrupt-cells = <1>;
 		interrupt-map-mask = <0 0 63>;
 		/* Active high IRQ 0 is connected to GIC's SPI0 */
 		interrupt-map = <0 0 0 &gic 0 0 4>;
+
+		/include/ "vexpress-v2m-rs1.dtsi"
 	};
 };
 
-/include/ "vexpress-v2m-rs1.dtsi"
diff --git a/Documentation/devicetree/bindings/ata/exynos-sata-phy.txt b/Documentation/devicetree/bindings/ata/exynos-sata-phy.txt
new file mode 100644
index 0000000..37824fa
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/exynos-sata-phy.txt
@@ -0,0 +1,14 @@
+* Samsung SATA PHY Controller
+
+SATA PHY nodes are defined to describe on-chip SATA Physical layer controllers.
+Each SATA PHY controller should have its own node.
+
+Required properties:
+- compatible        : compatible list, contains "samsung,exynos5-sata-phy"
+- reg               : <registers mapping>
+
+Example:
+        sata@ffe07000 {
+                compatible = "samsung,exynos5-sata-phy";
+                reg = <0xffe07000 0x1000>;
+        };
diff --git a/Documentation/devicetree/bindings/ata/exynos-sata.txt b/Documentation/devicetree/bindings/ata/exynos-sata.txt
new file mode 100644
index 0000000..0849f10
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/exynos-sata.txt
@@ -0,0 +1,17 @@
+* Samsung AHCI SATA Controller
+
+SATA nodes are defined to describe on-chip Serial ATA controllers.
+Each SATA controller should have its own node.
+
+Required properties:
+- compatible        : compatible list, contains "samsung,exynos5-sata"
+- interrupts        : <interrupt mapping for SATA IRQ>
+- reg               : <registers mapping>
+- samsung,sata-freq : <frequency in MHz>
+
+Example:
+        sata@ffe08000 {
+                compatible = "samsung,exynos5-sata";
+                reg = <0xffe08000 0x1000>;
+                interrupts = <115>;
+        };
diff --git a/Documentation/devicetree/bindings/bus/omap-ocp2scp.txt b/Documentation/devicetree/bindings/bus/omap-ocp2scp.txt
index d2fe064..63dd805 100644
--- a/Documentation/devicetree/bindings/bus/omap-ocp2scp.txt
+++ b/Documentation/devicetree/bindings/bus/omap-ocp2scp.txt
@@ -2,9 +2,27 @@
 
 properties:
 - compatible : Should be "ti,omap-ocp2scp"
+- reg : Address and length of the register set for the device
 - #address-cells, #size-cells : Must be present if the device has sub-nodes
 - ranges : the child address space are mapped 1:1 onto the parent address space
 - ti,hwmods : must be "ocp2scp_usb_phy"
 
 Sub-nodes:
 All the devices connected to ocp2scp are described using sub-node to ocp2scp
+
+ocp2scp@4a0ad000 {
+	compatible = "ti,omap-ocp2scp";
+	reg = <0x4a0ad000 0x1f>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+	ti,hwmods = "ocp2scp_usb_phy";
+
+	subnode1 {
+	...
+	};
+
+	subnode2 {
+	...
+	};
+};
diff --git a/Documentation/devicetree/bindings/clock/imx23-clock.txt b/Documentation/devicetree/bindings/clock/imx23-clock.txt
index a0b867e..baadbb1 100644
--- a/Documentation/devicetree/bindings/clock/imx23-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx23-clock.txt
@@ -52,7 +52,7 @@ clocks and IDs.
 	lcdif		38
 	etm		39
 	usb		40
-	usb_pwr		41
+	usb_phy		41
 
 Examples:
 
diff --git a/Documentation/devicetree/bindings/clock/imx25-clock.txt b/Documentation/devicetree/bindings/clock/imx25-clock.txt
new file mode 100644
index 0000000..c2a3525
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx25-clock.txt
@@ -0,0 +1,162 @@
+* Clock bindings for Freescale i.MX25
+
+Required properties:
+- compatible: Should be "fsl,imx25-ccm"
+- reg: Address and length of the register set
+- interrupts: Should contain CCM interrupt
+- #clock-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  The following is a full list of i.MX25
+clocks and IDs.
+
+	Clock			ID
+	---------------------------
+	dummy			0
+	osc			1
+	mpll			2
+	upll			3
+	mpll_cpu_3_4		4
+	cpu_sel			5
+	cpu			6
+	ahb			7
+	usb_div			8
+	ipg			9
+	per0_sel		10
+	per1_sel		11
+	per2_sel		12
+	per3_sel		13
+	per4_sel		14
+	per5_sel		15
+	per6_sel		16
+	per7_sel		17
+	per8_sel		18
+	per9_sel		19
+	per10_sel		20
+	per11_sel		21
+	per12_sel		22
+	per13_sel		23
+	per14_sel		24
+	per15_sel		25
+	per0			26
+	per1			27
+	per2			28
+	per3			29
+	per4			30
+	per5			31
+	per6			32
+	per7			33
+	per8			34
+	per9			35
+	per10			36
+	per11			37
+	per12			38
+	per13			39
+	per14			40
+	per15			41
+	csi_ipg_per		42
+	epit_ipg_per		43
+	esai_ipg_per		44
+	esdhc1_ipg_per		45
+	esdhc2_ipg_per		46
+	gpt_ipg_per		47
+	i2c_ipg_per		48
+	lcdc_ipg_per		49
+	nfc_ipg_per		50
+	owire_ipg_per		51
+	pwm_ipg_per		52
+	sim1_ipg_per		53
+	sim2_ipg_per		54
+	ssi1_ipg_per		55
+	ssi2_ipg_per		56
+	uart_ipg_per		57
+	ata_ahb			58
+	reserved		59
+	csi_ahb			60
+	emi_ahb			61
+	esai_ahb		62
+	esdhc1_ahb		63
+	esdhc2_ahb		64
+	fec_ahb			65
+	lcdc_ahb		66
+	rtic_ahb		67
+	sdma_ahb		68
+	slcdc_ahb		69
+	usbotg_ahb		70
+	reserved		71
+	reserved		72
+	reserved		73
+	reserved		74
+	can1_ipg		75
+	can2_ipg		76
+	csi_ipg			77
+	cspi1_ipg		78
+	cspi2_ipg		79
+	cspi3_ipg		80
+	dryice_ipg		81
+	ect_ipg			82
+	epit1_ipg		83
+	epit2_ipg		84
+	reserved		85
+	esdhc1_ipg		86
+	esdhc2_ipg		87
+	fec_ipg			88
+	reserved		89
+	reserved		90
+	reserved		91
+	gpt1_ipg		92
+	gpt2_ipg		93
+	gpt3_ipg		94
+	gpt4_ipg		95
+	reserved		96
+	reserved		97
+	reserved		98
+	iim_ipg			99
+	reserved		100
+	reserved		101
+	kpp_ipg			102
+	lcdc_ipg		103
+	reserved		104
+	pwm1_ipg		105
+	pwm2_ipg		106
+	pwm3_ipg		107
+	pwm4_ipg		108
+	rngb_ipg		109
+	reserved		110
+	scc_ipg			111
+	sdma_ipg		112
+	sim1_ipg		113
+	sim2_ipg		114
+	slcdc_ipg		115
+	spba_ipg		116
+	ssi1_ipg		117
+	ssi2_ipg		118
+	tsc_ipg			119
+	uart1_ipg		120
+	uart2_ipg		121
+	uart3_ipg		122
+	uart4_ipg		123
+	uart5_ipg		124
+	reserved		125
+	wdt_ipg			126
+
+Examples:
+
+clks: ccm@53f80000 {
+	compatible = "fsl,imx25-ccm";
+	reg = <0x53f80000 0x4000>;
+	interrupts = <31>;
+	clock-output-names = ...
+			"uart_ipg",
+			"uart_serial",
+			...;
+};
+
+uart1: serial@43f90000 {
+	compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+	reg = <0x43f90000 0x4000>;
+	interrupts = <45>;
+	clocks = <&clks 79>, <&clks 50>;
+	clock-names = "ipg", "per";
+	status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/clock/imx28-clock.txt b/Documentation/devicetree/bindings/clock/imx28-clock.txt
index aa2af28..52a49a4 100644
--- a/Documentation/devicetree/bindings/clock/imx28-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx28-clock.txt
@@ -73,8 +73,8 @@ clocks and IDs.
 	can1		59
 	usb0		60
 	usb1		61
-	usb0_pwr	62
-	usb1_pwr	63
+	usb0_phy	62
+	usb1_phy	63
 	enet_out	64
 
 Examples:
diff --git a/Documentation/devicetree/bindings/clock/imx5-clock.txt b/Documentation/devicetree/bindings/clock/imx5-clock.txt
new file mode 100644
index 0000000..04ad478
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx5-clock.txt
@@ -0,0 +1,191 @@
+* Clock bindings for Freescale i.MX5
+
+Required properties:
+- compatible: Should be "fsl,<soc>-ccm" , where <soc> can be imx51 or imx53
+- reg: Address and length of the register set
+- interrupts: Should contain CCM interrupt
+- #clock-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  The following is a full list of i.MX5
+clocks and IDs.
+
+	Clock			ID
+	---------------------------
+	dummy			0
+	ckil			1
+	osc			2
+	ckih1			3
+	ckih2			4
+	ahb			5
+	ipg			6
+	axi_a			7
+	axi_b			8
+	uart_pred		9
+	uart_root		10
+	esdhc_a_pred		11
+	esdhc_b_pred		12
+	esdhc_c_s		13
+	esdhc_d_s		14
+	emi_sel			15
+	emi_slow_podf		16
+	nfc_podf		17
+	ecspi_pred		18
+	ecspi_podf		19
+	usboh3_pred		20
+	usboh3_podf		21
+	usb_phy_pred		22
+	usb_phy_podf		23
+	cpu_podf		24
+	di_pred			25
+	tve_di			26
+	tve_s			27
+	uart1_ipg_gate		28
+	uart1_per_gate		29
+	uart2_ipg_gate		30
+	uart2_per_gate		31
+	uart3_ipg_gate		32
+	uart3_per_gate		33
+	i2c1_gate		34
+	i2c2_gate		35
+	gpt_ipg_gate		36
+	pwm1_ipg_gate		37
+	pwm1_hf_gate		38
+	pwm2_ipg_gate		39
+	pwm2_hf_gate		40
+	gpt_hf_gate		41
+	fec_gate		42
+	usboh3_per_gate		43
+	esdhc1_ipg_gate		44
+	esdhc2_ipg_gate		45
+	esdhc3_ipg_gate		46
+	esdhc4_ipg_gate		47
+	ssi1_ipg_gate		48
+	ssi2_ipg_gate		49
+	ssi3_ipg_gate		50
+	ecspi1_ipg_gate		51
+	ecspi1_per_gate		52
+	ecspi2_ipg_gate		53
+	ecspi2_per_gate		54
+	cspi_ipg_gate		55
+	sdma_gate		56
+	emi_slow_gate		57
+	ipu_s			58
+	ipu_gate		59
+	nfc_gate		60
+	ipu_di1_gate		61
+	vpu_s			62
+	vpu_gate		63
+	vpu_reference_gate	64
+	uart4_ipg_gate		65
+	uart4_per_gate		66
+	uart5_ipg_gate		67
+	uart5_per_gate		68
+	tve_gate		69
+	tve_pred		70
+	esdhc1_per_gate		71
+	esdhc2_per_gate		72
+	esdhc3_per_gate		73
+	esdhc4_per_gate		74
+	usb_phy_gate		75
+	hsi2c_gate		76
+	mipi_hsc1_gate		77
+	mipi_hsc2_gate		78
+	mipi_esc_gate		79
+	mipi_hsp_gate		80
+	ldb_di1_div_3_5		81
+	ldb_di1_div		82
+	ldb_di0_div_3_5		83
+	ldb_di0_div		84
+	ldb_di1_gate		85
+	can2_serial_gate	86
+	can2_ipg_gate		87
+	i2c3_gate		88
+	lp_apm			89
+	periph_apm		90
+	main_bus		91
+	ahb_max			92
+	aips_tz1		93
+	aips_tz2		94
+	tmax1			95
+	tmax2			96
+	tmax3			97
+	spba			98
+	uart_sel		99
+	esdhc_a_sel		100
+	esdhc_b_sel		101
+	esdhc_a_podf		102
+	esdhc_b_podf		103
+	ecspi_sel		104
+	usboh3_sel		105
+	usb_phy_sel		106
+	iim_gate		107
+	usboh3_gate		108
+	emi_fast_gate		109
+	ipu_di0_gate		110
+	gpc_dvfs		111
+	pll1_sw			112
+	pll2_sw			113
+	pll3_sw			114
+	ipu_di0_sel		115
+	ipu_di1_sel		116
+	tve_ext_sel		117
+	mx51_mipi		118
+	pll4_sw			119
+	ldb_di1_sel		120
+	di_pll4_podf		121
+	ldb_di0_sel		122
+	ldb_di0_gate		123
+	usb_phy1_gate		124
+	usb_phy2_gate		125
+	per_lp_apm		126
+	per_pred1		127
+	per_pred2		128
+	per_podf		129
+	per_root		130
+	ssi_apm			131
+	ssi1_root_sel		132
+	ssi2_root_sel		133
+	ssi3_root_sel		134
+	ssi_ext1_sel		135
+	ssi_ext2_sel		136
+	ssi_ext1_com_sel	137
+	ssi_ext2_com_sel	138
+	ssi1_root_pred		139
+	ssi1_root_podf		140
+	ssi2_root_pred		141
+	ssi2_root_podf		142
+	ssi_ext1_pred		143
+	ssi_ext1_podf		144
+	ssi_ext2_pred		145
+	ssi_ext2_podf		146
+	ssi1_root_gate		147
+	ssi2_root_gate		148
+	ssi3_root_gate		149
+	ssi_ext1_gate		150
+	ssi_ext2_gate		151
+	epit1_ipg_gate		152
+	epit1_hf_gate		153
+	epit2_ipg_gate		154
+	epit2_hf_gate		155
+	can_sel			156
+	can1_serial_gate	157
+	can1_ipg_gate		158
+
+Examples (for mx53):
+
+clks: ccm@53fd4000{
+	compatible = "fsl,imx53-ccm";
+	reg = <0x53fd4000 0x4000>;
+	interrupts = <0 71 0x04 0 72 0x04>;
+	#clock-cells = <1>;
+};
+
+can1: can@53fc8000 {
+	compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
+	reg = <0x53fc8000 0x4000>;
+	interrupts = <82>;
+	clocks = <&clks 158>, <&clks 157>;
+	clock-names = "ipg", "per";
+	status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/clock/imx6q-clock.txt b/Documentation/devicetree/bindings/clock/imx6q-clock.txt
index 492bd99..d77b4e6 100644
--- a/Documentation/devicetree/bindings/clock/imx6q-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx6q-clock.txt
@@ -187,9 +187,9 @@ clocks and IDs.
 	pll3_usb_otg		172
 	pll4_audio		173
 	pll5_video		174
-	pll6_mlb		175
+	pll8_mlb		175
 	pll7_usb_host		176
-	pll8_enet		177
+	pll6_enet		177
 	ssi1_ipg		178
 	ssi2_ipg		179
 	ssi3_ipg		180
@@ -198,6 +198,11 @@ clocks and IDs.
 	usbphy2			183
 	ldb_di0_div_3_5		184
 	ldb_di1_div_3_5		185
+	sata_ref		186
+	sata_ref_100m		187
+	pcie_ref		188
+	pcie_ref_125m		189
+	enet_ref		190
 
 Examples:
 
diff --git a/Documentation/devicetree/bindings/clock/zynq-7000.txt b/Documentation/devicetree/bindings/clock/zynq-7000.txt
new file mode 100644
index 0000000..23ae1db
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/zynq-7000.txt
@@ -0,0 +1,55 @@
+Device Tree Clock bindings for the Zynq 7000 EPP
+
+The Zynq EPP has several different clk providers, each with there own bindings.
+The purpose of this document is to document their usage.
+
+See clock_bindings.txt for more information on the generic clock bindings.
+See Chapter 25 of Zynq TRM for more information about Zynq clocks.
+
+== PLLs ==
+
+Used to describe the ARM_PLL, DDR_PLL, and IO_PLL.
+
+Required properties:
+- #clock-cells : shall be 0 (only one clock is output from this node)
+- compatible : "xlnx,zynq-pll"
+- reg : pair of u32 values, which are the address offsets within the SLCR
+        of the relevant PLL_CTRL register and PLL_CFG register respectively
+- clocks : phandle for parent clock.  should be the phandle for ps_clk
+
+Optional properties:
+- clock-output-names : name of the output clock
+
+Example:
+	armpll: armpll {
+		#clock-cells = <0>;
+		compatible = "xlnx,zynq-pll";
+		clocks = <&ps_clk>;
+		reg = <0x100 0x110>;
+		clock-output-names = "armpll";
+	};
+
+== Peripheral clocks ==
+
+Describes clock node for the SDIO, SMC, SPI, QSPI, and UART clocks.
+
+Required properties:
+- #clock-cells : shall be 1
+- compatible : "xlnx,zynq-periph-clock"
+- reg : a single u32 value, describing the offset within the SLCR where
+        the CLK_CTRL register is found for this peripheral
+- clocks : phandle for parent clocks.  should hold phandles for
+           the IO_PLL, ARM_PLL, and DDR_PLL in order
+- clock-output-names : names of the output clock(s).  For peripherals that have
+                       two output clocks (for example, the UART), two clocks
+                       should be listed.
+
+Example:
+	uart_clk: uart_clk {
+		#clock-cells = <1>;
+		compatible = "xlnx,zynq-periph-clock";
+		clocks = <&iopll &armpll &ddrpll>;
+		reg = <0x154>;
+		clock-output-names = "uart0_ref_clk",
+				     "uart1_ref_clk";
+	};
diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-spear.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-spear.txt
new file mode 100644
index 0000000..f3d44984
--- /dev/null
+++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-spear.txt
@@ -0,0 +1,42 @@
+SPEAr cpufreq driver
+-------------------
+
+SPEAr SoC cpufreq driver for CPU frequency scaling.
+It supports both uniprocessor (UP) and symmetric multiprocessor (SMP) systems
+which share clock across all CPUs.
+
+Required properties:
+- cpufreq_tbl: Table of frequencies CPU could be transitioned into, in the
+  increasing order.
+
+Optional properties:
+- clock-latency: Specify the possible maximum transition latency for clock, in
+  unit of nanoseconds.
+
+Both required and optional properties listed above must be defined under node
+/cpus/cpu@0.
+
+Examples:
+--------
+cpus {
+
+	<...>
+
+	cpu@0 {
+		compatible = "arm,cortex-a9";
+		reg = <0>;
+
+		<...>
+
+		cpufreq_tbl = < 166000
+				200000
+				250000
+				300000
+				400000
+				500000
+				600000 >;
+	};
+
+	<...>
+
+};
diff --git a/Documentation/devicetree/bindings/dma/dma.txt b/Documentation/devicetree/bindings/dma/dma.txt
new file mode 100644
index 0000000..8f504e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/dma.txt
@@ -0,0 +1,81 @@
+* Generic DMA Controller and DMA request bindings
+
+Generic binding to provide a way for a driver using DMA Engine to retrieve the
+DMA request or channel information that goes from a hardware device to a DMA
+controller.
+
+
+* DMA controller
+
+Required property:
+- #dma-cells: 		Must be at least 1. Used to provide DMA controller
+			specific information. See DMA client binding below for
+			more details.
+
+Optional properties:
+- dma-channels: 	Number of DMA channels supported by the controller.
+- dma-requests: 	Number of DMA requests signals supported by the
+			controller.
+
+Example:
+
+	dma: dma@48000000 {
+		compatible = "ti,omap-sdma";
+		reg = <0x48000000 0x1000>;
+		interrupts = <0 12 0x4
+			      0 13 0x4
+			      0 14 0x4
+			      0 15 0x4>;
+		#dma-cells = <1>;
+		dma-channels = <32>;
+		dma-requests = <127>;
+	};
+
+
+* DMA client
+
+Client drivers should specify the DMA property using a phandle to the controller
+followed by DMA controller specific data.
+
+Required property:
+- dmas:			List of one or more DMA specifiers, each consisting of
+			- A phandle pointing to DMA controller node
+			- A number of integer cells, as determined by the
+			  #dma-cells property in the node referenced by phandle
+			  containing DMA controller specific information. This
+			  typically contains a DMA request line number or a
+			  channel number, but can contain any data that is used
+			  required for configuring a channel.
+- dma-names: 		Contains one identifier string for each DMA specifier in
+			the dmas property. The specific strings that can be used
+			are defined in the binding of the DMA client device.
+			Multiple DMA specifiers can be used to represent
+			alternatives and in this case the dma-names for those
+			DMA specifiers must be identical (see examples).
+
+Examples:
+
+1. A device with one DMA read channel, one DMA write channel:
+
+	i2c1: i2c@1 {
+		...
+		dmas = <&dma 2		/* read channel */
+			&dma 3>;	/* write channel */
+		dma-names = "rx", "tx";
+		...
+	};
+
+2. A single read-write channel with three alternative DMA controllers:
+
+	dmas = <&dma1 5
+		&dma2 7
+		&dma3 2>;
+	dma-names = "rx-tx", "rx-tx", "rx-tx";
+
+3. A device with three channels, one of which has two alternatives:
+
+	dmas = <&dma1 2			/* read channel */
+		&dma1 3			/* write channel */
+		&dma2 0			/* error read */
+		&dma3 0>;		/* alternative error read */
+	dma-names = "rx", "tx", "error", "error";
diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
index c0d85db..5bb3dfb 100644
--- a/Documentation/devicetree/bindings/dma/snps-dma.txt
+++ b/Documentation/devicetree/bindings/dma/snps-dma.txt
@@ -6,6 +6,26 @@ Required properties:
 - interrupt-parent: Should be the phandle for the interrupt controller
   that services interrupts for this device
 - interrupt: Should contain the DMAC interrupt number
+- nr_channels: Number of channels supported by hardware
+- is_private: The device channels should be marked as private and not for by the
+  general purpose DMA channel allocator. False if not passed.
+- chan_allocation_order: order of allocation of channel, 0 (default): ascending,
+  1: descending
+- chan_priority: priority of channels. 0 (default): increase from chan 0->n, 1:
+  increase from chan n->0
+- block_size: Maximum block size supported by the controller
+- nr_masters: Number of AHB masters supported by the controller
+- data_width: Maximum data width supported by hardware per AHB master
+  (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
+- slave_info:
+	- bus_id: name of this device channel, not just a device name since
+	  devices may have more than one channel e.g. "foo_tx". For using the
+	  dw_generic_filter(), slave drivers must pass exactly this string as
+	  param to filter function.
+	- cfg_hi: Platform-specific initializer for the CFG_HI register
+	- cfg_lo: Platform-specific initializer for the CFG_LO register
+	- src_master: src master for transfers on allocated channel.
+	- dst_master: dest master for transfers on allocated channel.
 
 Example:
 
@@ -14,4 +34,28 @@ Example:
 		reg = <0xfc000000 0x1000>;
 		interrupt-parent = <&vic1>;
 		interrupts = <12>;
+
+		nr_channels = <8>;
+		chan_allocation_order = <1>;
+		chan_priority = <1>;
+		block_size = <0xfff>;
+		nr_masters = <2>;
+		data_width = <3 3 0 0>;
+
+		slave_info {
+			uart0-tx {
+				bus_id = "uart0-tx";
+				cfg_hi = <0x4000>;	/* 0x8 << 11 */
+				cfg_lo = <0>;
+				src_master = <0>;
+				dst_master = <1>;
+			};
+			spi0-tx {
+				bus_id = "spi0-tx";
+				cfg_hi = <0x2000>;	/* 0x4 << 11 */
+				cfg_lo = <0>;
+				src_master = <0>;
+				dst_master = <0>;
+			};
+		};
 	};
diff --git a/Documentation/devicetree/bindings/drm/exynos/hdmi.txt b/Documentation/devicetree/bindings/drm/exynos/hdmi.txt
new file mode 100644
index 0000000..589edee
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/exynos/hdmi.txt
@@ -0,0 +1,22 @@
+Device-Tree bindings for drm hdmi driver
+
+Required properties:
+- compatible: value should be "samsung,exynos5-hdmi".
+- reg: physical base address of the hdmi and length of memory mapped
+	region.
+- interrupts: interrupt number to the cpu.
+- hpd-gpio: following information about the hotplug gpio pin.
+	a) phandle of the gpio controller node.
+	b) pin number within the gpio controller.
+	c) pin function mode.
+	d) optional flags and pull up/down.
+	e) drive strength.
+
+Example:
+
+	hdmi {
+		compatible = "samsung,exynos5-hdmi";
+		reg = <0x14530000 0x100000>;
+		interrupts = <0 95 0>;
+		hpd-gpio = <&gpx3 7 0xf 1 3>;
+	};
diff --git a/Documentation/devicetree/bindings/drm/exynos/hdmiddc.txt b/Documentation/devicetree/bindings/drm/exynos/hdmiddc.txt
new file mode 100644
index 0000000..fa166d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/exynos/hdmiddc.txt
@@ -0,0 +1,12 @@
+Device-Tree bindings for hdmiddc driver
+
+Required properties:
+- compatible: value should be "samsung,exynos5-hdmiddc".
+- reg: I2C address of the hdmiddc device.
+
+Example:
+
+	hdmiddc {
+		compatible = "samsung,exynos5-hdmiddc";
+		reg = <0x50>;
+	};
diff --git a/Documentation/devicetree/bindings/drm/exynos/hdmiphy.txt b/Documentation/devicetree/bindings/drm/exynos/hdmiphy.txt
new file mode 100644
index 0000000..858f4f9
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/exynos/hdmiphy.txt
@@ -0,0 +1,12 @@
+Device-Tree bindings for hdmiphy driver
+
+Required properties:
+- compatible: value should be "samsung,exynos5-hdmiphy".
+- reg: I2C address of the hdmiphy device.
+
+Example:
+
+	hdmiphy {
+		compatible = "samsung,exynos5-hdmiphy";
+		reg = <0x38>;
+	};
diff --git a/Documentation/devicetree/bindings/drm/exynos/mixer.txt b/Documentation/devicetree/bindings/drm/exynos/mixer.txt
new file mode 100644
index 0000000..9b2ea03
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/exynos/mixer.txt
@@ -0,0 +1,15 @@
+Device-Tree bindings for mixer driver
+
+Required properties:
+- compatible: value should be "samsung,exynos5-mixer".
+- reg: physical base address of the mixer and length of memory mapped
+	region.
+- interrupts: interrupt number to the cpu.
+
+Example:
+
+	mixer {
+		compatible = "samsung,exynos5-mixer";
+		reg = <0x14450000 0x10000>;
+		interrupts = <0 94 0>;
+	};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt b/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
new file mode 100644
index 0000000..558cdf3
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
@@ -0,0 +1,22 @@
+GPIO line that should be set high/low to power off a device
+
+Required properties:
+- compatible : should be "gpio-poweroff".
+- gpios : The GPIO to set high/low, see "gpios property" in
+  Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be
+  low to power down the board set it to "Active Low", otherwise set
+  gpio to "Active High".
+
+Optional properties:
+- input : Initially configure the GPIO line as an input. Only reconfigure
+  it to an output when the pm_power_off function is called. If this optional
+  property is not specified, the GPIO is initialized as an output in its
+  inactive state.
+
+
+Examples:
+
+gpio-poweroff {
+	compatible = "gpio-poweroff";
+	gpios = <&gpio 4 0>; /* GPIO 4 Active Low */
+};
diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt
index 4e16ba4..a336287 100644
--- a/Documentation/devicetree/bindings/gpio/gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio.txt
@@ -75,4 +75,40 @@ Example of two SOC GPIO banks defined as gpio-controller nodes:
 		gpio-controller;
 	};
 
+2.1) gpio-controller and pinctrl subsystem
+------------------------------------------
 
+gpio-controller on a SOC might be tightly coupled with the pinctrl
+subsystem, in the sense that the pins can be used by other functions
+together with optional gpio feature.
+
+While the pin allocation is totally managed by the pin ctrl subsystem,
+gpio (under gpiolib) is still maintained by gpio drivers. It may happen
+that different pin ranges in a SoC is managed by different gpio drivers.
+
+This makes it logical to let gpio drivers announce their pin ranges to
+the pin ctrl subsystem and call 'pinctrl_request_gpio' in order to
+request the corresponding pin before any gpio usage.
+
+For this, the gpio controller can use a pinctrl phandle and pins to
+announce the pinrange to the pin ctrl subsystem. For example,
+
+	qe_pio_e: gpio-controller@1460 {
+		#gpio-cells = <2>;
+		compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
+		reg = <0x1460 0x18>;
+		gpio-controller;
+		gpio-ranges = <&pinctrl1 20 10>, <&pinctrl2 50 20>;
+
+    }
+
+where,
+   &pinctrl1 and &pinctrl2 is the phandle to the pinctrl DT node.
+
+   Next values specify the base pin and number of pins for the range
+   handled by 'qe_pio_e' gpio. In the given example from base pin 20 to
+   pin 29 under pinctrl1 and pin 50 to pin 69 under pinctrl2 is handled
+   by this gpio controller.
+
+The pinctrl node must have "#gpio-range-cells" property to show number of
+arguments to pass with phandle from gpio controllers node.
diff --git a/Documentation/devicetree/bindings/gpio/gpio_atmel.txt b/Documentation/devicetree/bindings/gpio/gpio_atmel.txt
index 66efc80..85f8c0d 100644
--- a/Documentation/devicetree/bindings/gpio/gpio_atmel.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio_atmel.txt
@@ -9,6 +9,10 @@ Required properties:
   unused).
 - gpio-controller: Marks the device node as a GPIO controller.
 
+optional properties:
+- #gpio-lines: Number of gpio if absent 32.
+
+
 Example:
 	pioA: gpio@fffff200 {
 		compatible = "atmel,at91rm9200-gpio";
@@ -16,5 +20,6 @@ Example:
 		interrupts = <2 4>;
 		#gpio-cells = <2>;
 		gpio-controller;
+		#gpio-lines = <19>;
 	};
 
diff --git a/Documentation/devicetree/bindings/gpio/led.txt b/Documentation/devicetree/bindings/gpio/led.txt
index edc83c1..df1b308 100644
--- a/Documentation/devicetree/bindings/gpio/led.txt
+++ b/Documentation/devicetree/bindings/gpio/led.txt
@@ -10,16 +10,10 @@ LED sub-node properties:
 - gpios :  Should specify the LED's GPIO, see "gpios property" in
   Documentation/devicetree/bindings/gpio/gpio.txt.  Active low LEDs should be
   indicated using flags in the GPIO specifier.
-- label :  (optional) The label for this LED.  If omitted, the label is
-  taken from the node name (excluding the unit address).
-- linux,default-trigger :  (optional) This parameter, if present, is a
-  string defining the trigger assigned to the LED.  Current triggers are:
-    "backlight" - LED will act as a back-light, controlled by the framebuffer
-		  system
-    "default-on" - LED will turn on, but see "default-state" below
-    "heartbeat" - LED "double" flashes at a load average based rate
-    "ide-disk" - LED indicates disk activity
-    "timer" - LED flashes at a fixed, configurable rate
+- label :  (optional)
+  see Documentation/devicetree/bindings/leds/common.txt
+- linux,default-trigger :  (optional)
+  see Documentation/devicetree/bindings/leds/common.txt
 - default-state:  (optional) The initial state of the LED.  Valid
   values are "on", "off", and "keep".  If the LED is already on or off
   and the default-state property is set the to same value, then no
diff --git a/Documentation/devicetree/bindings/gpio/leds-ns2.txt b/Documentation/devicetree/bindings/gpio/leds-ns2.txt
new file mode 100644
index 0000000..aef3aca
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/leds-ns2.txt
@@ -0,0 +1,26 @@
+Binding for dual-GPIO LED found on Network Space v2 (and parents).
+
+Required properties:
+- compatible: "lacie,ns2-leds".
+
+Each LED is represented as a sub-node of the ns2-leds device.
+
+Required sub-node properties:
+- cmd-gpio: Command LED GPIO. See OF device-tree GPIO specification.
+- slow-gpio: Slow LED GPIO. See OF device-tree GPIO specification.
+
+Optional sub-node properties:
+- label: Name for this LED. If omitted, the label is taken from the node name.
+- linux,default-trigger: Trigger assigned to the LED.
+
+Example:
+
+ns2-leds {
+	compatible = "lacie,ns2-leds";
+
+	blue-sata {
+		label = "ns2:blue:sata";
+		slow-gpio = <&gpio0 29 0>;
+		cmd-gpio = <&gpio0 30 0>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/gpio/spear_spics.txt b/Documentation/devicetree/bindings/gpio/spear_spics.txt
new file mode 100644
index 0000000..96c37eb
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/spear_spics.txt
@@ -0,0 +1,50 @@
+=== ST Microelectronics SPEAr SPI CS Driver ===
+
+SPEAr platform provides a provision to control chipselects of ARM PL022 Prime
+Cell spi controller through its system registers, which otherwise remains under
+PL022 control. If chipselect remain under PL022 control then they would be
+released as soon as transfer is over and TxFIFO becomes empty. This is not
+desired by some of the device protocols above spi which expect (multiple)
+transfers without releasing their chipselects.
+
+Chipselects can be controlled by software by turning them as GPIOs. SPEAr
+provides another interface through system registers through which software can
+directly control each PL022 chipselect. Hence, it is natural for SPEAr to export
+the control of this interface as gpio.
+
+Required properties:
+
+  * compatible: should be defined as "st,spear-spics-gpio"
+  * reg: mentioning address range of spics controller
+  * st-spics,peripcfg-reg: peripheral configuration register offset
+  * st-spics,sw-enable-bit: bit offset to enable sw control
+  * st-spics,cs-value-bit: bit offset to drive chipselect low or high
+  * st-spics,cs-enable-mask: chip select number bit mask
+  * st-spics,cs-enable-shift: chip select number program offset
+  * gpio-controller: Marks the device node as gpio controller
+  * #gpio-cells: should be 1 and will mention chip select number
+
+All the above bit offsets are within peripcfg register.
+
+Example:
+-------
+spics: spics@e0700000{
+        compatible = "st,spear-spics-gpio";
+        reg = <0xe0700000 0x1000>;
+        st-spics,peripcfg-reg = <0x3b0>;
+        st-spics,sw-enable-bit = <12>;
+        st-spics,cs-value-bit = <11>;
+        st-spics,cs-enable-mask = <3>;
+        st-spics,cs-enable-shift = <8>;
+        gpio-controller;
+        #gpio-cells = <2>;
+};
+
+
+spi0: spi@e0100000 {
+        status = "okay";
+        num-cs = <3>;
+        cs-gpios = <&gpio1 7 0>, <&spics 0>,
+                   <&spics 1>;
+	...
+}
diff --git a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
new file mode 100644
index 0000000..b4fa934
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
@@ -0,0 +1,191 @@
+NVIDIA Tegra host1x
+
+Required properties:
+- compatible: "nvidia,tegra<chip>-host1x"
+- reg: Physical base address and length of the controller's registers.
+- interrupts: The interrupt outputs from the controller.
+- #address-cells: The number of cells used to represent physical base addresses
+  in the host1x address space. Should be 1.
+- #size-cells: The number of cells used to represent the size of an address
+  range in the host1x address space. Should be 1.
+- ranges: The mapping of the host1x address space to the CPU address space.
+
+The host1x top-level node defines a number of children, each representing one
+of the following host1x client modules:
+
+- mpe: video encoder
+
+  Required properties:
+  - compatible: "nvidia,tegra<chip>-mpe"
+  - reg: Physical base address and length of the controller's registers.
+  - interrupts: The interrupt outputs from the controller.
+
+- vi: video input
+
+  Required properties:
+  - compatible: "nvidia,tegra<chip>-vi"
+  - reg: Physical base address and length of the controller's registers.
+  - interrupts: The interrupt outputs from the controller.
+
+- epp: encoder pre-processor
+
+  Required properties:
+  - compatible: "nvidia,tegra<chip>-epp"
+  - reg: Physical base address and length of the controller's registers.
+  - interrupts: The interrupt outputs from the controller.
+
+- isp: image signal processor
+
+  Required properties:
+  - compatible: "nvidia,tegra<chip>-isp"
+  - reg: Physical base address and length of the controller's registers.
+  - interrupts: The interrupt outputs from the controller.
+
+- gr2d: 2D graphics engine
+
+  Required properties:
+  - compatible: "nvidia,tegra<chip>-gr2d"
+  - reg: Physical base address and length of the controller's registers.
+  - interrupts: The interrupt outputs from the controller.
+
+- gr3d: 3D graphics engine
+
+  Required properties:
+  - compatible: "nvidia,tegra<chip>-gr3d"
+  - reg: Physical base address and length of the controller's registers.
+
+- dc: display controller
+
+  Required properties:
+  - compatible: "nvidia,tegra<chip>-dc"
+  - reg: Physical base address and length of the controller's registers.
+  - interrupts: The interrupt outputs from the controller.
+
+  Each display controller node has a child node, named "rgb", that represents
+  the RGB output associated with the controller. It can take the following
+  optional properties:
+  - nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
+  - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
+  - nvidia,edid: supplies a binary EDID blob
+
+- hdmi: High Definition Multimedia Interface
+
+  Required properties:
+  - compatible: "nvidia,tegra<chip>-hdmi"
+  - reg: Physical base address and length of the controller's registers.
+  - interrupts: The interrupt outputs from the controller.
+  - vdd-supply: regulator for supply voltage
+  - pll-supply: regulator for PLL
+
+  Optional properties:
+  - nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
+  - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
+  - nvidia,edid: supplies a binary EDID blob
+
+- tvo: TV encoder output
+
+  Required properties:
+  - compatible: "nvidia,tegra<chip>-tvo"
+  - reg: Physical base address and length of the controller's registers.
+  - interrupts: The interrupt outputs from the controller.
+
+- dsi: display serial interface
+
+  Required properties:
+  - compatible: "nvidia,tegra<chip>-dsi"
+  - reg: Physical base address and length of the controller's registers.
+
+Example:
+
+/ {
+	...
+
+	host1x {
+		compatible = "nvidia,tegra20-host1x", "simple-bus";
+		reg = <0x50000000 0x00024000>;
+		interrupts = <0 65 0x04   /* mpcore syncpt */
+			      0 67 0x04>; /* mpcore general */
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		ranges = <0x54000000 0x54000000 0x04000000>;
+
+		mpe {
+			compatible = "nvidia,tegra20-mpe";
+			reg = <0x54040000 0x00040000>;
+			interrupts = <0 68 0x04>;
+		};
+
+		vi {
+			compatible = "nvidia,tegra20-vi";
+			reg = <0x54080000 0x00040000>;
+			interrupts = <0 69 0x04>;
+		};
+
+		epp {
+			compatible = "nvidia,tegra20-epp";
+			reg = <0x540c0000 0x00040000>;
+			interrupts = <0 70 0x04>;
+		};
+
+		isp {
+			compatible = "nvidia,tegra20-isp";
+			reg = <0x54100000 0x00040000>;
+			interrupts = <0 71 0x04>;
+		};
+
+		gr2d {
+			compatible = "nvidia,tegra20-gr2d";
+			reg = <0x54140000 0x00040000>;
+			interrupts = <0 72 0x04>;
+		};
+
+		gr3d {
+			compatible = "nvidia,tegra20-gr3d";
+			reg = <0x54180000 0x00040000>;
+		};
+
+		dc@54200000 {
+			compatible = "nvidia,tegra20-dc";
+			reg = <0x54200000 0x00040000>;
+			interrupts = <0 73 0x04>;
+
+			rgb {
+				status = "disabled";
+			};
+		};
+
+		dc@54240000 {
+			compatible = "nvidia,tegra20-dc";
+			reg = <0x54240000 0x00040000>;
+			interrupts = <0 74 0x04>;
+
+			rgb {
+				status = "disabled";
+			};
+		};
+
+		hdmi {
+			compatible = "nvidia,tegra20-hdmi";
+			reg = <0x54280000 0x00040000>;
+			interrupts = <0 75 0x04>;
+			status = "disabled";
+		};
+
+		tvo {
+			compatible = "nvidia,tegra20-tvo";
+			reg = <0x542c0000 0x00040000>;
+			interrupts = <0 76 0x04>;
+			status = "disabled";
+		};
+
+		dsi {
+			compatible = "nvidia,tegra20-dsi";
+			reg = <0x54300000 0x00040000>;
+			status = "disabled";
+		};
+	};
+
+	...
+};
diff --git a/Documentation/devicetree/bindings/hwmon/vexpress.txt b/Documentation/devicetree/bindings/hwmon/vexpress.txt
new file mode 100644
index 0000000..9c27ed6
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/vexpress.txt
@@ -0,0 +1,23 @@
+Versatile Express hwmon sensors
+-------------------------------
+
+Requires node properties:
+- "compatible" value : one of
+	"arm,vexpress-volt"
+	"arm,vexpress-amp"
+	"arm,vexpress-temp"
+	"arm,vexpress-power"
+	"arm,vexpress-energy"
+- "arm,vexpress-sysreg,func" when controlled via vexpress-sysreg
+  (see Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
+  for more details)
+
+Optional node properties:
+- label : string describing the monitored value
+
+Example:
+	energy@0 {
+		compatible = "arm,vexpress-energy";
+		arm,vexpress-sysreg,func = <13 0>;
+		label = "A15 Jcore";
+	};
diff --git a/Documentation/devicetree/bindings/i2c/arm-versatile.txt b/Documentation/devicetree/bindings/i2c/arm-versatile.txt
deleted file mode 100644
index 361d31c..0000000
--- a/Documentation/devicetree/bindings/i2c/arm-versatile.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-i2c Controller on ARM Versatile platform:
-
-Required properties:
-- compatible : Must be "arm,versatile-i2c";
-- reg
-- #address-cells = <1>;
-- #size-cells = <0>;
-
-Optional properties:
-- Child nodes conforming to i2c bus binding
diff --git a/Documentation/devicetree/bindings/i2c/atmel-i2c.txt b/Documentation/devicetree/bindings/i2c/atmel-i2c.txt
deleted file mode 100644
index b689a0d..0000000
--- a/Documentation/devicetree/bindings/i2c/atmel-i2c.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-I2C for Atmel platforms
-
-Required properties :
-- compatible : Must be "atmel,at91rm9200-i2c", "atmel,at91sam9261-i2c",
-     "atmel,at91sam9260-i2c", "atmel,at91sam9g20-i2c", "atmel,at91sam9g10-i2c"
-     or "atmel,at91sam9x5-i2c"
-- reg: physical base address of the controller and length of memory mapped
-     region.
-- interrupts: interrupt number to the cpu.
-- #address-cells = <1>;
-- #size-cells = <0>;
-
-Optional properties:
-- Child nodes conforming to i2c bus binding
-
-Examples :
-
-i2c0: i2c@fff84000 {
-	compatible = "atmel,at91sam9g20-i2c";
-	reg = <0xfff84000 0x100>;
-	interrupts = <12 4 6>;
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	24c512@50 {
-		compatible = "24c512";
-		reg = <0x50>;
-		pagesize = <128>;
-	}
-}
diff --git a/Documentation/devicetree/bindings/i2c/cavium-i2c.txt b/Documentation/devicetree/bindings/i2c/cavium-i2c.txt
deleted file mode 100644
index dced82e..0000000
--- a/Documentation/devicetree/bindings/i2c/cavium-i2c.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-* Two Wire Serial Interface (TWSI) / I2C
-
-- compatible: "cavium,octeon-3860-twsi"
-
-  Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
-
-- reg: The base address of the TWSI/I2C bus controller register bank.
-
-- #address-cells: Must be <1>.
-
-- #size-cells: Must be <0>.  I2C addresses have no size component.
-
-- interrupts: A single interrupt specifier.
-
-- clock-frequency: The I2C bus clock rate in Hz.
-
-Example:
-	twsi0: i2c@1180000001000 {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		compatible = "cavium,octeon-3860-twsi";
-		reg = <0x11800 0x00001000 0x0 0x200>;
-		interrupts = <0 45>;
-		clock-frequency = <100000>;
-
-		rtc@68 {
-			compatible = "dallas,ds1337";
-			reg = <0x68>;
-		};
-		tmp@4c {
-			compatible = "ti,tmp421";
-			reg = <0x4c>;
-		};
-	};
diff --git a/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt b/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt
deleted file mode 100644
index 569b162..0000000
--- a/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt
+++ /dev/null
@@ -1,93 +0,0 @@
-CE4100 I2C
-----------
-
-CE4100 has one PCI device which is described as the I2C-Controller. This
-PCI device has three PCI-bars, each bar contains a complete I2C
-controller. So we have a total of three independent I2C-Controllers
-which share only an interrupt line.
-The driver is probed via the PCI-ID and is gathering the information of
-attached devices from the devices tree.
-Grant Likely recommended to use the ranges property to map the PCI-Bar
-number to its physical address and to use this to find the child nodes
-of the specific I2C controller. This were his exact words:
-
-       Here's where the magic happens.  Each entry in
-       ranges describes how the parent pci address space
-       (middle group of 3) is translated to the local
-       address space (first group of 2) and the size of
-       each range (last cell).  In this particular case,
-       the first cell of the local address is chosen to be
-       1:1 mapped to the BARs, and the second is the
-       offset from be base of the BAR (which would be
-       non-zero if you had 2 or more devices mapped off
-       the same BAR)
-
-       ranges allows the address mapping to be described
-       in a way that the OS can interpret without
-       requiring custom device driver code.
-
-This is an example which is used on FalconFalls:
-------------------------------------------------
-	i2c-controller@b,2 {
-		#address-cells = <2>;
-		#size-cells = <1>;
-		compatible = "pci8086,2e68.2",
-				"pci8086,2e68",
-				"pciclass,ff0000",
-				"pciclass,ff00";
-
-		reg = <0x15a00 0x0 0x0 0x0 0x0>;
-		interrupts = <16 1>;
-
-		/* as described by Grant, the first number in the group of
-		* three is the bar number followed by the 64bit bar address
-		* followed by size of the mapping. The bar address
-		* requires also a valid translation in parents ranges
-		* property.
-		*/
-		ranges = <0 0   0x02000000 0 0xdffe0500 0x100
-			  1 0   0x02000000 0 0xdffe0600 0x100
-			  2 0   0x02000000 0 0xdffe0700 0x100>;
-
-		i2c@0 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "intel,ce4100-i2c-controller";
-
-			/* The first number in the reg property is the
-			* number of the bar
-			*/
-			reg = <0 0 0x100>;
-
-			/* This I2C controller has no devices */
-		};
-
-		i2c@1 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "intel,ce4100-i2c-controller";
-			reg = <1 0 0x100>;
-
-			/* This I2C controller has one gpio controller */
-			gpio@26 {
-				#gpio-cells = <2>;
-				compatible = "ti,pcf8575";
-				reg = <0x26>;
-				gpio-controller;
-			};
-		};
-
-		i2c@2 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "intel,ce4100-i2c-controller";
-			reg = <2 0 0x100>;
-
-			gpio@26 {
-				#gpio-cells = <2>;
-				compatible = "ti,pcf8575";
-				reg = <0x26>;
-				gpio-controller;
-			};
-		};
-	};
diff --git a/Documentation/devicetree/bindings/i2c/davinci.txt b/Documentation/devicetree/bindings/i2c/davinci.txt
deleted file mode 100644
index 2dc935b..0000000
--- a/Documentation/devicetree/bindings/i2c/davinci.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-* Texas Instruments Davinci I2C
-
-This file provides information, what the device node for the
-davinci i2c interface contain.
-
-Required properties:
-- compatible: "ti,davinci-i2c";
-- reg : Offset and length of the register set for the device
-
-Recommended properties :
-- interrupts : standard interrupt property.
-- clock-frequency : desired I2C bus clock frequency in Hz.
-
-Example (enbw_cmc board):
-	i2c@1c22000 {
-		compatible = "ti,davinci-i2c";
-		reg = <0x22000 0x1000>;
-		clock-frequency = <100000>;
-		interrupts = <15>;
-		interrupt-parent = <&intc>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		dtt@48 {
-			compatible = "national,lm75";
-			reg = <0x48>;
-		};
-	};
diff --git a/Documentation/devicetree/bindings/i2c/fsl-i2c.txt b/Documentation/devicetree/bindings/i2c/fsl-i2c.txt
deleted file mode 100644
index 1eacd6b..0000000
--- a/Documentation/devicetree/bindings/i2c/fsl-i2c.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-* I2C
-
-Required properties :
-
- - reg : Offset and length of the register set for the device
- - compatible : should be "fsl,CHIP-i2c" where CHIP is the name of a
-   compatible processor, e.g. mpc8313, mpc8543, mpc8544, mpc5121,
-   mpc5200 or mpc5200b. For the mpc5121, an additional node
-   "fsl,mpc5121-i2c-ctrl" is required as shown in the example below.
-
-Recommended properties :
-
- - interrupts : <a b> where a is the interrupt number and b is a
-   field that represents an encoding of the sense and level
-   information for the interrupt.  This should be encoded based on
-   the information in section 2) depending on the type of interrupt
-   controller you have.
- - interrupt-parent : the phandle for the interrupt controller that
-   services interrupts for this device.
- - fsl,preserve-clocking : boolean; if defined, the clock settings
-   from the bootloader are preserved (not touched).
- - clock-frequency : desired I2C bus clock frequency in Hz.
- - fsl,timeout : I2C bus timeout in microseconds.
-
-Examples :
-
-	/* MPC5121 based board */
-	i2c@1740 {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		compatible = "fsl,mpc5121-i2c", "fsl-i2c";
-		reg = <0x1740 0x20>;
-		interrupts = <11 0x8>;
-		interrupt-parent = <&ipic>;
-		clock-frequency = <100000>;
-	};
-
-	i2ccontrol@1760 {
-		compatible = "fsl,mpc5121-i2c-ctrl";
-		reg = <0x1760 0x8>;
-	};
-
-	/* MPC5200B based board */
-	i2c@3d00 {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-		reg = <0x3d00 0x40>;
-		interrupts = <2 15 0>;
-		interrupt-parent = <&mpc5200_pic>;
-		fsl,preserve-clocking;
-	};
-
-	/* MPC8544 base board */
-	i2c@3100 {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		compatible = "fsl,mpc8544-i2c", "fsl-i2c";
-		reg = <0x3100 0x100>;
-		interrupts = <43 2>;
-		interrupt-parent = <&mpic>;
-		clock-frequency = <400000>;
-		fsl,timeout = <10000>;
-	};
diff --git a/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt b/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt
deleted file mode 100644
index f3cf43b..0000000
--- a/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-* Freescale Inter IC (I2C) and High Speed Inter IC (HS-I2C) for i.MX
-
-Required properties:
-- compatible : Should be "fsl,<chip>-i2c"
-- reg : Should contain I2C/HS-I2C registers location and length
-- interrupts : Should contain I2C/HS-I2C interrupt
-
-Optional properties:
-- clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz.
-  The absence of the propoerty indicates the default frequency 100 kHz.
-
-Examples:
-
-i2c@83fc4000 { /* I2C2 on i.MX51 */
-	compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
-	reg = <0x83fc4000 0x4000>;
-	interrupts = <63>;
-};
-
-i2c@70038000 { /* HS-I2C on i.MX51 */
-	compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
-	reg = <0x70038000 0x4000>;
-	interrupts = <64>;
-	clock-frequency = <400000>;
-};
diff --git a/Documentation/devicetree/bindings/i2c/gpio-i2c.txt b/Documentation/devicetree/bindings/i2c/gpio-i2c.txt
deleted file mode 100644
index 4f8ec94..0000000
--- a/Documentation/devicetree/bindings/i2c/gpio-i2c.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-Device-Tree bindings for i2c gpio driver
-
-Required properties:
-	- compatible = "i2c-gpio";
-	- gpios: sda and scl gpio
-
-
-Optional properties:
-	- i2c-gpio,sda-open-drain: sda as open drain
-	- i2c-gpio,scl-open-drain: scl as open drain
-	- i2c-gpio,scl-output-only: scl as output only
-	- i2c-gpio,delay-us: delay between GPIO operations (may depend on each platform)
-	- i2c-gpio,timeout-ms: timeout to get data
-
-Example nodes:
-
-i2c@0 {
-	compatible = "i2c-gpio";
-	gpios = <&pioA 23 0 /* sda */
-		 &pioA 24 0 /* scl */
-		>;
-	i2c-gpio,sda-open-drain;
-	i2c-gpio,scl-open-drain;
-	i2c-gpio,delay-us = <2>;	/* ~100 kHz */
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	rv3029c2@56 {
-		compatible = "rv3029c2";
-		reg = <0x56>;
-	};
-};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-at91.txt b/Documentation/devicetree/bindings/i2c/i2c-at91.txt
new file mode 100644
index 0000000..b689a0d
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-at91.txt
@@ -0,0 +1,30 @@
+I2C for Atmel platforms
+
+Required properties :
+- compatible : Must be "atmel,at91rm9200-i2c", "atmel,at91sam9261-i2c",
+     "atmel,at91sam9260-i2c", "atmel,at91sam9g20-i2c", "atmel,at91sam9g10-i2c"
+     or "atmel,at91sam9x5-i2c"
+- reg: physical base address of the controller and length of memory mapped
+     region.
+- interrupts: interrupt number to the cpu.
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties:
+- Child nodes conforming to i2c bus binding
+
+Examples :
+
+i2c0: i2c@fff84000 {
+	compatible = "atmel,at91sam9g20-i2c";
+	reg = <0xfff84000 0x100>;
+	interrupts = <12 4 6>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	24c512@50 {
+		compatible = "24c512";
+		reg = <0x50>;
+		pagesize = <128>;
+	}
+}
diff --git a/Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt b/Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt
new file mode 100644
index 0000000..8ce9cd2
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt
@@ -0,0 +1,27 @@
+Device tree bindings for i2c-cbus-gpio driver
+
+Required properties:
+	- compatible = "i2c-cbus-gpio";
+	- gpios: clk, dat, sel
+	- #address-cells = <1>;
+	- #size-cells = <0>;
+
+Optional properties:
+	- child nodes conforming to i2c bus binding
+
+Example:
+
+i2c@0 {
+	compatible = "i2c-cbus-gpio";
+	gpios = <&gpio 66 0 /* clk */
+		 &gpio 65 0 /* dat */
+		 &gpio 64 0 /* sel */
+		>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	retu-mfd: retu@1 {
+		compatible = "retu-mfd";
+		reg = <0x1>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-davinci.txt b/Documentation/devicetree/bindings/i2c/i2c-davinci.txt
new file mode 100644
index 0000000..2dc935b
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-davinci.txt
@@ -0,0 +1,28 @@
+* Texas Instruments Davinci I2C
+
+This file provides information, what the device node for the
+davinci i2c interface contain.
+
+Required properties:
+- compatible: "ti,davinci-i2c";
+- reg : Offset and length of the register set for the device
+
+Recommended properties :
+- interrupts : standard interrupt property.
+- clock-frequency : desired I2C bus clock frequency in Hz.
+
+Example (enbw_cmc board):
+	i2c@1c22000 {
+		compatible = "ti,davinci-i2c";
+		reg = <0x22000 0x1000>;
+		clock-frequency = <100000>;
+		interrupts = <15>;
+		interrupt-parent = <&intc>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		dtt@48 {
+			compatible = "national,lm75";
+			reg = <0x48>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-gpio.txt b/Documentation/devicetree/bindings/i2c/i2c-gpio.txt
new file mode 100644
index 0000000..4f8ec94
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-gpio.txt
@@ -0,0 +1,32 @@
+Device-Tree bindings for i2c gpio driver
+
+Required properties:
+	- compatible = "i2c-gpio";
+	- gpios: sda and scl gpio
+
+
+Optional properties:
+	- i2c-gpio,sda-open-drain: sda as open drain
+	- i2c-gpio,scl-open-drain: scl as open drain
+	- i2c-gpio,scl-output-only: scl as output only
+	- i2c-gpio,delay-us: delay between GPIO operations (may depend on each platform)
+	- i2c-gpio,timeout-ms: timeout to get data
+
+Example nodes:
+
+i2c@0 {
+	compatible = "i2c-gpio";
+	gpios = <&pioA 23 0 /* sda */
+		 &pioA 24 0 /* scl */
+		>;
+	i2c-gpio,sda-open-drain;
+	i2c-gpio,scl-open-drain;
+	i2c-gpio,delay-us = <2>;	/* ~100 kHz */
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	rv3029c2@56 {
+		compatible = "rv3029c2";
+		reg = <0x56>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx.txt b/Documentation/devicetree/bindings/i2c/i2c-imx.txt
new file mode 100644
index 0000000..3614242
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-imx.txt
@@ -0,0 +1,25 @@
+* Freescale Inter IC (I2C) and High Speed Inter IC (HS-I2C) for i.MX
+
+Required properties:
+- compatible : Should be "fsl,<chip>-i2c"
+- reg : Should contain I2C/HS-I2C registers location and length
+- interrupts : Should contain I2C/HS-I2C interrupt
+
+Optional properties:
+- clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz.
+  The absence of the propoerty indicates the default frequency 100 kHz.
+
+Examples:
+
+i2c@83fc4000 { /* I2C2 on i.MX51 */
+	compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
+	reg = <0x83fc4000 0x4000>;
+	interrupts = <63>;
+};
+
+i2c@70038000 { /* HS-I2C on i.MX51 */
+	compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
+	reg = <0x70038000 0x4000>;
+	interrupts = <64>;
+	clock-frequency = <400000>;
+};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mpc.txt b/Documentation/devicetree/bindings/i2c/i2c-mpc.txt
new file mode 100644
index 0000000..1eacd6b
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mpc.txt
@@ -0,0 +1,64 @@
+* I2C
+
+Required properties :
+
+ - reg : Offset and length of the register set for the device
+ - compatible : should be "fsl,CHIP-i2c" where CHIP is the name of a
+   compatible processor, e.g. mpc8313, mpc8543, mpc8544, mpc5121,
+   mpc5200 or mpc5200b. For the mpc5121, an additional node
+   "fsl,mpc5121-i2c-ctrl" is required as shown in the example below.
+
+Recommended properties :
+
+ - interrupts : <a b> where a is the interrupt number and b is a
+   field that represents an encoding of the sense and level
+   information for the interrupt.  This should be encoded based on
+   the information in section 2) depending on the type of interrupt
+   controller you have.
+ - interrupt-parent : the phandle for the interrupt controller that
+   services interrupts for this device.
+ - fsl,preserve-clocking : boolean; if defined, the clock settings
+   from the bootloader are preserved (not touched).
+ - clock-frequency : desired I2C bus clock frequency in Hz.
+ - fsl,timeout : I2C bus timeout in microseconds.
+
+Examples :
+
+	/* MPC5121 based board */
+	i2c@1740 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,mpc5121-i2c", "fsl-i2c";
+		reg = <0x1740 0x20>;
+		interrupts = <11 0x8>;
+		interrupt-parent = <&ipic>;
+		clock-frequency = <100000>;
+	};
+
+	i2ccontrol@1760 {
+		compatible = "fsl,mpc5121-i2c-ctrl";
+		reg = <0x1760 0x8>;
+	};
+
+	/* MPC5200B based board */
+	i2c@3d00 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
+		reg = <0x3d00 0x40>;
+		interrupts = <2 15 0>;
+		interrupt-parent = <&mpc5200_pic>;
+		fsl,preserve-clocking;
+	};
+
+	/* MPC8544 base board */
+	i2c@3100 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,mpc8544-i2c", "fsl-i2c";
+		reg = <0x3100 0x100>;
+		interrupts = <43 2>;
+		interrupt-parent = <&mpic>;
+		clock-frequency = <400000>;
+		fsl,timeout = <10000>;
+	};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt
new file mode 100644
index 0000000..66709a8
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt
@@ -0,0 +1,81 @@
+GPIO-based I2C Bus Mux
+
+This binding describes an I2C bus multiplexer that uses GPIOs to
+route the I2C signals.
+
+                                  +-----+  +-----+
+                                  | dev |  | dev |
+    +------------+                +-----+  +-----+
+    | SoC        |                   |        |
+    |            |          /--------+--------+
+    |   +------+ |  +------+    child bus A, on GPIO value set to 0
+    |   | I2C  |-|--| Mux  |
+    |   +------+ |  +--+---+    child bus B, on GPIO value set to 1
+    |            |     |    \----------+--------+--------+
+    |   +------+ |     |               |        |        |
+    |   | GPIO |-|-----+            +-----+  +-----+  +-----+
+    |   +------+ |                  | dev |  | dev |  | dev |
+    +------------+                  +-----+  +-----+  +-----+
+
+Required properties:
+- compatible: i2c-mux-gpio
+- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
+  port is connected to.
+- mux-gpios: list of gpios used to control the muxer
+* Standard I2C mux properties. See mux.txt in this directory.
+* I2C child bus nodes. See mux.txt in this directory.
+
+Optional properties:
+- idle-state: value to set the muxer to when idle. When no value is
+  given, it defaults to the last value used.
+
+For each i2c child node, an I2C child bus will be created. They will
+be numbered based on their order in the device tree.
+
+Whenever an access is made to a device on a child bus, the value set
+in the revelant node's reg property will be output using the list of
+GPIOs, the first in the list holding the least-significant value.
+
+If an idle state is defined, using the idle-state (optional) property,
+whenever an access is not being made to a device on a child bus, the
+GPIOs will be set according to the idle value.
+
+If an idle state is not defined, the most recently used value will be
+left programmed into hardware whenever no access is being made to a
+device on a child bus.
+
+Example:
+	i2cmux {
+		compatible = "i2c-mux-gpio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		mux-gpios = <&gpio1 22 0 &gpio1 23 0>;
+		i2c-parent = <&i2c1>;
+
+		i2c@1 {
+			reg = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			ssd1307: oled@3c {
+				compatible = "solomon,ssd1307fb-i2c";
+				reg = <0x3c>;
+				pwms = <&pwm 4 3000>;
+				reset-gpios = <&gpio2 7 1>;
+				reset-active-low;
+			};
+		};
+
+		i2c@3 {
+			reg = <3>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			pca9555: pca9555@20 {
+				compatible = "nxp,pca9555";
+				gpio-controller;
+				#gpio-cells = <2>;
+				reg = <0x20>;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux.txt b/Documentation/devicetree/bindings/i2c/i2c-mux.txt
new file mode 100644
index 0000000..af84cce
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mux.txt
@@ -0,0 +1,60 @@
+Common i2c bus multiplexer/switch properties.
+
+An i2c bus multiplexer/switch will have several child busses that are
+numbered uniquely in a device dependent manner.  The nodes for an i2c bus
+multiplexer/switch will have one child node for each child
+bus.
+
+Required properties:
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Required properties for child nodes:
+- #address-cells = <1>;
+- #size-cells = <0>;
+- reg : The sub-bus number.
+
+Optional properties for child nodes:
+- Other properties specific to the multiplexer/switch hardware.
+- Child nodes conforming to i2c bus binding
+
+
+Example :
+
+	/*
+	   An NXP pca9548 8 channel I2C multiplexer at address 0x70
+	   with two NXP pca8574 GPIO expanders attached, one each to
+	   ports 3 and 4.
+	 */
+
+	mux@70 {
+		compatible = "nxp,pca9548";
+		reg = <0x70>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+
+			gpio1: gpio@38 {
+				compatible = "nxp,pca8574";
+				reg = <0x38>;
+				#gpio-cells = <2>;
+				gpio-controller;
+			};
+		};
+		i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+
+			gpio2: gpio@38 {
+				compatible = "nxp,pca8574";
+				reg = <0x38>;
+				#gpio-cells = <2>;
+				gpio-controller;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt b/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
new file mode 100644
index 0000000..f46d928
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
@@ -0,0 +1,18 @@
+
+* Marvell MV64XXX I2C controller
+
+Required properties :
+
+ - reg             : Offset and length of the register set for the device
+ - compatible      : Should be "marvell,mv64xxx-i2c"
+ - interrupts      : The interrupt number
+ - clock-frequency : Desired I2C bus clock frequency in Hz.
+
+Examples:
+
+	i2c@11000 {
+		compatible = "marvell,mv64xxx-i2c";
+		reg = <0x11000 0x20>;
+		interrupts = <29>;
+		clock-frequency = <100000>;
+	};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-nomadik.txt b/Documentation/devicetree/bindings/i2c/i2c-nomadik.txt
new file mode 100644
index 0000000..72065b0
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-nomadik.txt
@@ -0,0 +1,23 @@
+I2C for Nomadik based systems
+
+Required (non-standard) properties:
+ - Nil
+
+Recommended (non-standard) properties:
+ - clock-frequency : Maximum bus clock frequency for the device
+
+Optional (non-standard) properties:
+ - Nil
+
+Example :
+
+i2c@80004000 {
+        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c";
+        reg = <0x80004000 0x1000>;
+        interrupts = <0 21 0x4>;
+        #address-cells = <1>;
+        #size-cells = <0>;
+        v-i2c-supply = <&db8500_vape_reg>;
+
+        clock-frequency = <400000>;
+};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt
index c15781f..1637c29 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt
@@ -1,7 +1,7 @@
 Device tree configuration for i2c-ocores
 
 Required properties:
-- compatible      : "opencores,i2c-ocores"
+- compatible      : "opencores,i2c-ocores" or "aeroflexgaisler,i2cmst"
 - reg             : bus address start and address range size of device
 - interrupts      : interrupt number
 - clock-frequency : frequency of bus clock in Hz
diff --git a/Documentation/devicetree/bindings/i2c/i2c-octeon.txt b/Documentation/devicetree/bindings/i2c/i2c-octeon.txt
new file mode 100644
index 0000000..dced82e
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-octeon.txt
@@ -0,0 +1,34 @@
+* Two Wire Serial Interface (TWSI) / I2C
+
+- compatible: "cavium,octeon-3860-twsi"
+
+  Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
+
+- reg: The base address of the TWSI/I2C bus controller register bank.
+
+- #address-cells: Must be <1>.
+
+- #size-cells: Must be <0>.  I2C addresses have no size component.
+
+- interrupts: A single interrupt specifier.
+
+- clock-frequency: The I2C bus clock rate in Hz.
+
+Example:
+	twsi0: i2c@1180000001000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "cavium,octeon-3860-twsi";
+		reg = <0x11800 0x00001000 0x0 0x200>;
+		interrupts = <0 45>;
+		clock-frequency = <100000>;
+
+		rtc@68 {
+			compatible = "dallas,ds1337";
+			reg = <0x68>;
+		};
+		tmp@4c {
+			compatible = "ti,tmp421";
+			reg = <0x4c>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-omap.txt b/Documentation/devicetree/bindings/i2c/i2c-omap.txt
new file mode 100644
index 0000000..56564aa
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-omap.txt
@@ -0,0 +1,30 @@
+I2C for OMAP platforms
+
+Required properties :
+- compatible : Must be "ti,omap3-i2c" or "ti,omap4-i2c"
+- ti,hwmods : Must be "i2c<n>", n being the instance number (1-based)
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Recommended properties :
+- clock-frequency : Desired I2C bus clock frequency in Hz. Otherwise
+  the default 100 kHz frequency will be used.
+
+Optional properties:
+- Child nodes conforming to i2c bus binding
+
+Note: Current implementation will fetch base address, irq and dma
+from omap hwmod data base during device registration.
+Future plan is to migrate hwmod data base contents into device tree
+blob so that, all the required data will be used from device tree dts
+file.
+
+Examples :
+
+i2c1: i2c@0 {
+    compatible = "ti,omap3-i2c";
+    #address-cells = <1>;
+    #size-cells = <0>;
+    ti,hwmods = "i2c1";
+    clock-frequency = <400000>;
+};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-pnx.txt b/Documentation/devicetree/bindings/i2c/i2c-pnx.txt
new file mode 100644
index 0000000..fe98ada
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-pnx.txt
@@ -0,0 +1,36 @@
+* NXP PNX I2C Controller
+
+Required properties:
+
+ - reg: Offset and length of the register set for the device
+ - compatible: should be "nxp,pnx-i2c"
+ - interrupts: configure one interrupt line
+ - #address-cells: always 1 (for i2c addresses)
+ - #size-cells: always 0
+ - interrupt-parent: the phandle for the interrupt controller that
+   services interrupts for this device.
+
+Optional properties:
+
+ - clock-frequency: desired I2C bus clock frequency in Hz, Default: 100000 Hz
+
+Examples:
+
+	i2c1: i2c@400a0000 {
+		compatible = "nxp,pnx-i2c";
+		reg = <0x400a0000 0x100>;
+		interrupt-parent = <&mic>;
+		interrupts = <51 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	i2c2: i2c@400a8000 {
+		compatible = "nxp,pnx-i2c";
+		reg = <0x400a8000 0x100>;
+		interrupt-parent = <&mic>;
+		interrupts = <50 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-frequency = <100000>;
+	};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-pxa-pci-ce4100.txt b/Documentation/devicetree/bindings/i2c/i2c-pxa-pci-ce4100.txt
new file mode 100644
index 0000000..569b162
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-pxa-pci-ce4100.txt
@@ -0,0 +1,93 @@
+CE4100 I2C
+----------
+
+CE4100 has one PCI device which is described as the I2C-Controller. This
+PCI device has three PCI-bars, each bar contains a complete I2C
+controller. So we have a total of three independent I2C-Controllers
+which share only an interrupt line.
+The driver is probed via the PCI-ID and is gathering the information of
+attached devices from the devices tree.
+Grant Likely recommended to use the ranges property to map the PCI-Bar
+number to its physical address and to use this to find the child nodes
+of the specific I2C controller. This were his exact words:
+
+       Here's where the magic happens.  Each entry in
+       ranges describes how the parent pci address space
+       (middle group of 3) is translated to the local
+       address space (first group of 2) and the size of
+       each range (last cell).  In this particular case,
+       the first cell of the local address is chosen to be
+       1:1 mapped to the BARs, and the second is the
+       offset from be base of the BAR (which would be
+       non-zero if you had 2 or more devices mapped off
+       the same BAR)
+
+       ranges allows the address mapping to be described
+       in a way that the OS can interpret without
+       requiring custom device driver code.
+
+This is an example which is used on FalconFalls:
+------------------------------------------------
+	i2c-controller@b,2 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "pci8086,2e68.2",
+				"pci8086,2e68",
+				"pciclass,ff0000",
+				"pciclass,ff00";
+
+		reg = <0x15a00 0x0 0x0 0x0 0x0>;
+		interrupts = <16 1>;
+
+		/* as described by Grant, the first number in the group of
+		* three is the bar number followed by the 64bit bar address
+		* followed by size of the mapping. The bar address
+		* requires also a valid translation in parents ranges
+		* property.
+		*/
+		ranges = <0 0   0x02000000 0 0xdffe0500 0x100
+			  1 0   0x02000000 0 0xdffe0600 0x100
+			  2 0   0x02000000 0 0xdffe0700 0x100>;
+
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "intel,ce4100-i2c-controller";
+
+			/* The first number in the reg property is the
+			* number of the bar
+			*/
+			reg = <0 0 0x100>;
+
+			/* This I2C controller has no devices */
+		};
+
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "intel,ce4100-i2c-controller";
+			reg = <1 0 0x100>;
+
+			/* This I2C controller has one gpio controller */
+			gpio@26 {
+				#gpio-cells = <2>;
+				compatible = "ti,pcf8575";
+				reg = <0x26>;
+				gpio-controller;
+			};
+		};
+
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "intel,ce4100-i2c-controller";
+			reg = <2 0 0x100>;
+
+			gpio@26 {
+				#gpio-cells = <2>;
+				compatible = "ti,pcf8575";
+				reg = <0x26>;
+				gpio-controller;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-pxa.txt b/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
new file mode 100644
index 0000000..12b78ac
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
@@ -0,0 +1,33 @@
+* Marvell MMP I2C controller
+
+Required properties :
+
+ - reg : Offset and length of the register set for the device
+ - compatible : should be "mrvl,mmp-twsi" where mmp is the name of a
+   compatible processor, e.g. pxa168, pxa910, mmp2, mmp3.
+   For the pxa2xx/pxa3xx, an additional node "mrvl,pxa-i2c" is required
+   as shown in the example below.
+
+Recommended properties :
+
+ - interrupts : the interrupt number
+ - interrupt-parent : the phandle for the interrupt controller that
+   services interrupts for this device. If the parent is the default
+   interrupt controller in device tree, it could be ignored.
+ - mrvl,i2c-polling : Disable interrupt of i2c controller. Polling
+   status register of i2c controller instead.
+ - mrvl,i2c-fast-mode : Enable fast mode of i2c controller.
+
+Examples:
+	twsi1: i2c@d4011000 {
+		compatible = "mrvl,mmp-twsi";
+		reg = <0xd4011000 0x1000>;
+		interrupts = <7>;
+		mrvl,i2c-fast-mode;
+	};
+	
+	twsi2: i2c@d4025000 {
+		compatible = "mrvl,mmp-twsi";
+		reg = <0xd4025000 0x1000>;
+		interrupts = <58>;
+	};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt b/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
new file mode 100644
index 0000000..e9611ac
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
@@ -0,0 +1,55 @@
+* Samsung's I2C controller
+
+The Samsung's I2C controller is used to interface with I2C devices.
+
+Required properties:
+  - compatible: value should be either of the following.
+      (a) "samsung, s3c2410-i2c", for i2c compatible with s3c2410 i2c.
+      (b) "samsung, s3c2440-i2c", for i2c compatible with s3c2440 i2c.
+      (c) "samsung, s3c2440-hdmiphy-i2c", for s3c2440-like i2c used
+          inside HDMIPHY block found on several samsung SoCs
+  - reg: physical base address of the controller and length of memory mapped
+    region.
+  - interrupts: interrupt number to the cpu.
+  - samsung,i2c-sda-delay: Delay (in ns) applied to data line (SDA) edges.
+
+Required for all cases except "samsung,s3c2440-hdmiphy-i2c":
+  - Samsung GPIO variant (deprecated):
+    - gpios: The order of the gpios should be the following: <SDA, SCL>.
+      The gpio specifier depends on the gpio controller. Required in all
+      cases except for "samsung,s3c2440-hdmiphy-i2c" whose input/output
+      lines are permanently wired to the respective clienta
+  - Pinctrl variant (preferred, if available):
+    - pinctrl-0: Pin control group to be used for this controller.
+    - pinctrl-names: Should contain only one value - "default".
+
+Optional properties:
+  - samsung,i2c-slave-addr: Slave address in multi-master enviroment. If not
+    specified, default value is 0.
+  - samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not
+    specified, the default value in Hz is 100000.
+
+Example:
+
+	i2c@13870000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x13870000 0x100>;
+		interrupts = <345>;
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <100000>;
+		/* Samsung GPIO variant begins here */
+		gpios = <&gpd1 2 0 /* SDA */
+			 &gpd1 3 0 /* SCL */>;
+		/* Samsung GPIO variant ends here */
+		/* Pinctrl variant begins here */
+		pinctrl-0 = <&i2c3_bus>;
+		pinctrl-names = "default";
+		/* Pinctrl variant ends here */
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		wm8994@1a {
+			compatible = "wlf,wm8994";
+			reg = <0x1a>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-sirf.txt b/Documentation/devicetree/bindings/i2c/i2c-sirf.txt
new file mode 100644
index 0000000..7baf9e1
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-sirf.txt
@@ -0,0 +1,19 @@
+I2C for SiRFprimaII platforms
+
+Required properties :
+- compatible : Must be "sirf,prima2-i2c"
+- reg: physical base address of the controller and length of memory mapped
+     region.
+- interrupts: interrupt number to the cpu.
+
+Optional properties:
+- clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz.
+  The absence of the propoerty indicates the default frequency 100 kHz.
+
+Examples :
+
+i2c0: i2c@b00e0000 {
+    compatible = "sirf,prima2-i2c";
+    reg = <0xb00e0000 0x10000>;
+    interrupts = <24>;
+};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-versatile.txt b/Documentation/devicetree/bindings/i2c/i2c-versatile.txt
new file mode 100644
index 0000000..361d31c
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-versatile.txt
@@ -0,0 +1,10 @@
+i2c Controller on ARM Versatile platform:
+
+Required properties:
+- compatible : Must be "arm,versatile-i2c";
+- reg
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties:
+- Child nodes conforming to i2c bus binding
diff --git a/Documentation/devicetree/bindings/i2c/i2c-xiic.txt b/Documentation/devicetree/bindings/i2c/i2c-xiic.txt
new file mode 100644
index 0000000..ceabbe9
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-xiic.txt
@@ -0,0 +1,22 @@
+Xilinx IIC controller:
+
+Required properties:
+- compatible : Must be "xlnx,xps-iic-2.00.a"
+- reg : IIC register location and length
+- interrupts : IIC controller unterrupt
+- #address-cells = <1>
+- #size-cells = <0>
+
+Optional properties:
+- Child nodes conforming to i2c bus binding
+
+Example:
+
+	axi_iic_0: i2c@40800000 {
+		compatible = "xlnx,xps-iic-2.00.a";
+		interrupts = < 1 2 >;
+		reg = < 0x40800000 0x10000 >;
+
+		#size-cells = <0>;
+		#address-cells = <1>;
+	};
diff --git a/Documentation/devicetree/bindings/i2c/mrvl-i2c.txt b/Documentation/devicetree/bindings/i2c/mrvl-i2c.txt
deleted file mode 100644
index 0f79450..0000000
--- a/Documentation/devicetree/bindings/i2c/mrvl-i2c.txt
+++ /dev/null
@@ -1,51 +0,0 @@
-* Marvell MMP I2C controller
-
-Required properties :
-
- - reg : Offset and length of the register set for the device
- - compatible : should be "mrvl,mmp-twsi" where mmp is the name of a
-   compatible processor, e.g. pxa168, pxa910, mmp2, mmp3.
-   For the pxa2xx/pxa3xx, an additional node "mrvl,pxa-i2c" is required
-   as shown in the example below.
-
-Recommended properties :
-
- - interrupts : the interrupt number
- - interrupt-parent : the phandle for the interrupt controller that
-   services interrupts for this device. If the parent is the default
-   interrupt controller in device tree, it could be ignored.
- - mrvl,i2c-polling : Disable interrupt of i2c controller. Polling
-   status register of i2c controller instead.
- - mrvl,i2c-fast-mode : Enable fast mode of i2c controller.
-
-Examples:
-	twsi1: i2c@d4011000 {
-		compatible = "mrvl,mmp-twsi";
-		reg = <0xd4011000 0x1000>;
-		interrupts = <7>;
-		mrvl,i2c-fast-mode;
-	};
-	
-	twsi2: i2c@d4025000 {
-		compatible = "mrvl,mmp-twsi";
-		reg = <0xd4025000 0x1000>;
-		interrupts = <58>;
-	};
-
-* Marvell MV64XXX I2C controller
-
-Required properties :
-
- - reg             : Offset and length of the register set for the device
- - compatible      : Should be "marvell,mv64xxx-i2c"
- - interrupts      : The interrupt number
- - clock-frequency : Desired I2C bus clock frequency in Hz.
-
-Examples:
-
-	i2c@11000 {
-		compatible = "marvell,mv64xxx-i2c";
-		reg = <0x11000 0x20>;
-		interrupts = <29>;
-		clock-frequency = <100000>;
-	};
diff --git a/Documentation/devicetree/bindings/i2c/mux.txt b/Documentation/devicetree/bindings/i2c/mux.txt
deleted file mode 100644
index af84cce..0000000
--- a/Documentation/devicetree/bindings/i2c/mux.txt
+++ /dev/null
@@ -1,60 +0,0 @@
-Common i2c bus multiplexer/switch properties.
-
-An i2c bus multiplexer/switch will have several child busses that are
-numbered uniquely in a device dependent manner.  The nodes for an i2c bus
-multiplexer/switch will have one child node for each child
-bus.
-
-Required properties:
-- #address-cells = <1>;
-- #size-cells = <0>;
-
-Required properties for child nodes:
-- #address-cells = <1>;
-- #size-cells = <0>;
-- reg : The sub-bus number.
-
-Optional properties for child nodes:
-- Other properties specific to the multiplexer/switch hardware.
-- Child nodes conforming to i2c bus binding
-
-
-Example :
-
-	/*
-	   An NXP pca9548 8 channel I2C multiplexer at address 0x70
-	   with two NXP pca8574 GPIO expanders attached, one each to
-	   ports 3 and 4.
-	 */
-
-	mux@70 {
-		compatible = "nxp,pca9548";
-		reg = <0x70>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		i2c@3 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			reg = <3>;
-
-			gpio1: gpio@38 {
-				compatible = "nxp,pca8574";
-				reg = <0x38>;
-				#gpio-cells = <2>;
-				gpio-controller;
-			};
-		};
-		i2c@4 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			reg = <4>;
-
-			gpio2: gpio@38 {
-				compatible = "nxp,pca8574";
-				reg = <0x38>;
-				#gpio-cells = <2>;
-				gpio-controller;
-			};
-		};
-	};
diff --git a/Documentation/devicetree/bindings/i2c/nomadik.txt b/Documentation/devicetree/bindings/i2c/nomadik.txt
deleted file mode 100644
index 72065b0..0000000
--- a/Documentation/devicetree/bindings/i2c/nomadik.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-I2C for Nomadik based systems
-
-Required (non-standard) properties:
- - Nil
-
-Recommended (non-standard) properties:
- - clock-frequency : Maximum bus clock frequency for the device
-
-Optional (non-standard) properties:
- - Nil
-
-Example :
-
-i2c@80004000 {
-        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c";
-        reg = <0x80004000 0x1000>;
-        interrupts = <0 21 0x4>;
-        #address-cells = <1>;
-        #size-cells = <0>;
-        v-i2c-supply = <&db8500_vape_reg>;
-
-        clock-frequency = <400000>;
-};
diff --git a/Documentation/devicetree/bindings/i2c/omap-i2c.txt b/Documentation/devicetree/bindings/i2c/omap-i2c.txt
deleted file mode 100644
index 56564aa..0000000
--- a/Documentation/devicetree/bindings/i2c/omap-i2c.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-I2C for OMAP platforms
-
-Required properties :
-- compatible : Must be "ti,omap3-i2c" or "ti,omap4-i2c"
-- ti,hwmods : Must be "i2c<n>", n being the instance number (1-based)
-- #address-cells = <1>;
-- #size-cells = <0>;
-
-Recommended properties :
-- clock-frequency : Desired I2C bus clock frequency in Hz. Otherwise
-  the default 100 kHz frequency will be used.
-
-Optional properties:
-- Child nodes conforming to i2c bus binding
-
-Note: Current implementation will fetch base address, irq and dma
-from omap hwmod data base during device registration.
-Future plan is to migrate hwmod data base contents into device tree
-blob so that, all the required data will be used from device tree dts
-file.
-
-Examples :
-
-i2c1: i2c@0 {
-    compatible = "ti,omap3-i2c";
-    #address-cells = <1>;
-    #size-cells = <0>;
-    ti,hwmods = "i2c1";
-    clock-frequency = <400000>;
-};
diff --git a/Documentation/devicetree/bindings/i2c/pnx.txt b/Documentation/devicetree/bindings/i2c/pnx.txt
deleted file mode 100644
index fe98ada..0000000
--- a/Documentation/devicetree/bindings/i2c/pnx.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-* NXP PNX I2C Controller
-
-Required properties:
-
- - reg: Offset and length of the register set for the device
- - compatible: should be "nxp,pnx-i2c"
- - interrupts: configure one interrupt line
- - #address-cells: always 1 (for i2c addresses)
- - #size-cells: always 0
- - interrupt-parent: the phandle for the interrupt controller that
-   services interrupts for this device.
-
-Optional properties:
-
- - clock-frequency: desired I2C bus clock frequency in Hz, Default: 100000 Hz
-
-Examples:
-
-	i2c1: i2c@400a0000 {
-		compatible = "nxp,pnx-i2c";
-		reg = <0x400a0000 0x100>;
-		interrupt-parent = <&mic>;
-		interrupts = <51 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-	};
-
-	i2c2: i2c@400a8000 {
-		compatible = "nxp,pnx-i2c";
-		reg = <0x400a8000 0x100>;
-		interrupt-parent = <&mic>;
-		interrupts = <50 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clock-frequency = <100000>;
-	};
diff --git a/Documentation/devicetree/bindings/i2c/samsung-i2c.txt b/Documentation/devicetree/bindings/i2c/samsung-i2c.txt
deleted file mode 100644
index b6cb5a1..0000000
--- a/Documentation/devicetree/bindings/i2c/samsung-i2c.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-* Samsung's I2C controller
-
-The Samsung's I2C controller is used to interface with I2C devices.
-
-Required properties:
-  - compatible: value should be either of the following.
-      (a) "samsung, s3c2410-i2c", for i2c compatible with s3c2410 i2c.
-      (b) "samsung, s3c2440-i2c", for i2c compatible with s3c2440 i2c.
-      (c) "samsung, s3c2440-hdmiphy-i2c", for s3c2440-like i2c used
-          inside HDMIPHY block found on several samsung SoCs
-  - reg: physical base address of the controller and length of memory mapped
-    region.
-  - interrupts: interrupt number to the cpu.
-  - samsung,i2c-sda-delay: Delay (in ns) applied to data line (SDA) edges.
-
-Optional properties:
-  - gpios: The order of the gpios should be the following: <SDA, SCL>.
-    The gpio specifier depends on the gpio controller. Required in all
-    cases except for "samsung,s3c2440-hdmiphy-i2c" whose input/output
-    lines are permanently wired to the respective client
-  - samsung,i2c-slave-addr: Slave address in multi-master enviroment. If not
-    specified, default value is 0.
-  - samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not
-    specified, the default value in Hz is 100000.
-
-Example:
-
-	i2c@13870000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x13870000 0x100>;
-		interrupts = <345>;
-		samsung,i2c-sda-delay = <100>;
-		samsung,i2c-max-bus-freq = <100000>;
-		gpios = <&gpd1 2 0 /* SDA */
-			 &gpd1 3 0 /* SCL */>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		wm8994@1a {
-			compatible = "wlf,wm8994";
-			reg = <0x1a>;
-		};
-	};
diff --git a/Documentation/devicetree/bindings/i2c/sirf-i2c.txt b/Documentation/devicetree/bindings/i2c/sirf-i2c.txt
deleted file mode 100644
index 7baf9e1..0000000
--- a/Documentation/devicetree/bindings/i2c/sirf-i2c.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-I2C for SiRFprimaII platforms
-
-Required properties :
-- compatible : Must be "sirf,prima2-i2c"
-- reg: physical base address of the controller and length of memory mapped
-     region.
-- interrupts: interrupt number to the cpu.
-
-Optional properties:
-- clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz.
-  The absence of the propoerty indicates the default frequency 100 kHz.
-
-Examples :
-
-i2c0: i2c@b00e0000 {
-    compatible = "sirf,prima2-i2c";
-    reg = <0xb00e0000 0x10000>;
-    interrupts = <24>;
-};
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index 2f5322b..446859f 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -55,5 +55,7 @@ st-micro,24c256		i2c serial eeprom  (24cxx)
 stm,m41t00		Serial Access TIMEKEEPER
 stm,m41t62		Serial real-time clock (RTC) with alarm
 stm,m41t80		M41T80 - SERIAL ACCESS RTC WITH ALARMS
+taos,tsl2550		Ambient Light Sensor with SMBUS/Two Wire Serial Interface
 ti,tsc2003		I2C Touch-Screen Controller
 ti,tmp102		Low Power Digital Temperature Sensor with SMBUS/Two Wire Serial Interface
+ti,tmp275		Digital Temperature Sensor
diff --git a/Documentation/devicetree/bindings/i2c/xiic.txt b/Documentation/devicetree/bindings/i2c/xiic.txt
deleted file mode 100644
index ceabbe9..0000000
--- a/Documentation/devicetree/bindings/i2c/xiic.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-Xilinx IIC controller:
-
-Required properties:
-- compatible : Must be "xlnx,xps-iic-2.00.a"
-- reg : IIC register location and length
-- interrupts : IIC controller unterrupt
-- #address-cells = <1>
-- #size-cells = <0>
-
-Optional properties:
-- Child nodes conforming to i2c bus binding
-
-Example:
-
-	axi_iic_0: i2c@40800000 {
-		compatible = "xlnx,xps-iic-2.00.a";
-		interrupts = < 1 2 >;
-		reg = < 0x40800000 0x10000 >;
-
-		#size-cells = <0>;
-		#address-cells = <1>;
-	};
diff --git a/Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt b/Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt
new file mode 100644
index 0000000..ead641c
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt
@@ -0,0 +1,46 @@
+* GPIO driven matrix keypad device tree bindings
+
+GPIO driven matrix keypad is used to interface a SoC with a matrix keypad.
+The matrix keypad supports multiple row and column lines, a key can be
+placed at each intersection of a unique row and a unique column. The matrix
+keypad can sense a key-press and key-release by means of GPIO lines and
+report the event using GPIO interrupts to the cpu.
+
+Required Properties:
+- compatible:		Should be "gpio-matrix-keypad"
+- row-gpios:		List of gpios used as row lines. The gpio specifier
+			for this property depends on the gpio controller to
+			which these row lines are connected.
+- col-gpios:		List of gpios used as column lines. The gpio specifier
+			for this property depends on the gpio controller to
+			which these column lines are connected.
+- linux,keymap:		The definition can be found at
+			bindings/input/matrix-keymap.txt
+
+Optional Properties:
+- linux,no-autorepeat:	do no enable autorepeat feature.
+- linux,wakeup:		use any event on keypad as wakeup event.
+- debounce-delay-ms:	debounce interval in milliseconds
+- col-scan-delay-us:	delay, measured in microseconds, that is needed
+			before we can scan keypad after activating column gpio
+
+Example:
+	matrix-keypad {
+		compatible = "gpio-matrix-keypad";
+		debounce-delay-ms = <5>;
+		col-scan-delay-us = <2>;
+
+		row-gpios = <&gpio2 25 0
+			     &gpio2 26 0
+			     &gpio2 27 0>;
+
+		col-gpios = <&gpio2 21 0
+			     &gpio2 22 0>;
+
+		linux,keymap = <0x0000008B
+				0x0100009E
+				0x02000069
+				0x0001006A
+				0x0101001C
+				0x0201006C>;
+	};
diff --git a/Documentation/devicetree/bindings/input/pwm-beeper.txt b/Documentation/devicetree/bindings/input/pwm-beeper.txt
new file mode 100644
index 0000000..be332ae
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/pwm-beeper.txt
@@ -0,0 +1,7 @@
+* PWM beeper device tree bindings
+
+Registers a PWM device as beeper.
+
+Required properties:
+- compatible: should be "pwm-beeper"
+- pwms: phandle to the physical PWM device
diff --git a/Documentation/devicetree/bindings/input/stmpe-keypad.txt b/Documentation/devicetree/bindings/input/stmpe-keypad.txt
new file mode 100644
index 0000000..1b97222
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/stmpe-keypad.txt
@@ -0,0 +1,39 @@
+* STMPE Keypad
+
+Required properties:
+ - compatible               : "st,stmpe-keypad"
+ - linux,keymap             : See ./matrix-keymap.txt
+
+Optional properties:
+ - debounce-interval        : Debouncing interval time in milliseconds
+ - st,scan-count            : Scanning cycles elapsed before key data is updated
+ - st,no-autorepeat         : If specified device will not autorepeat
+
+Example:
+
+	stmpe_keypad {
+		compatible = "st,stmpe-keypad";
+
+		debounce-interval = <64>;
+		st,scan-count = <8>;
+		st,no-autorepeat;
+
+		linux,keymap = <0x205006b
+				0x4010074
+				0x3050072
+				0x1030004
+				0x502006a
+				0x500000a
+				0x5008b
+				0x706001c
+				0x405000b
+				0x6070003
+				0x3040067
+				0x303006c
+				0x60400e7
+				0x602009e
+				0x4020073
+				0x5050002
+				0x4030069
+				0x3020008>;
+	};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt b/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt
new file mode 100644
index 0000000..ca5a2c8
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt
@@ -0,0 +1,28 @@
+* Rohm BU21013 Touch Screen
+
+Required properties:
+ - compatible              : "rohm,bu21013_tp"
+ - reg                     :  I2C device address
+
+Optional properties:
+ - touch-gpio              : GPIO pin registering a touch event
+ - <supply_name>-supply    : Phandle to a regulator supply
+ - rohm,touch-max-x        : Maximum outward permitted limit in the X axis
+ - rohm,touch-max-y        : Maximum outward permitted limit in the Y axis
+ - rohm,flip-x             : Flip touch coordinates on the X axis
+ - rohm,flip-y             : Flip touch coordinates on the Y axis
+
+Example:
+
+	i2c@80110000 {
+		bu21013_tp@0x5c {
+			compatible = "rohm,bu21013_tp";
+			reg = <0x5c>;
+			touch-gpio = <&gpio2 20 0x4>;
+			avdd-supply = <&ab8500_ldo_aux1_reg>;
+
+			rohm,touch-max-x = <384>;
+			rohm,touch-max-y = <704>;
+			rohm,flip-y;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/mms114.txt b/Documentation/devicetree/bindings/input/touchscreen/mms114.txt
new file mode 100644
index 0000000..89d4c56
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/mms114.txt
@@ -0,0 +1,34 @@
+* MELFAS MMS114 touchscreen controller
+
+Required properties:
+- compatible: must be "melfas,mms114"
+- reg: I2C address of the chip
+- interrupts: interrupt to which the chip is connected
+- x-size: horizontal resolution of touchscreen
+- y-size: vertical resolution of touchscreen
+
+Optional properties:
+- contact-threshold:
+- moving-threshold:
+- x-invert: invert X axis
+- y-invert: invert Y axis
+
+Example:
+
+	i2c@00000000 {
+		/* ... */
+
+		touchscreen@48 {
+			compatible = "melfas,mms114";
+			reg = <0x48>;
+			interrupts = <39 0>;
+			x-size = <720>;
+			y-size = <1280>;
+			contact-threshold = <10>;
+			moving-threshold = <10>;
+			x-invert;
+			y-invert;
+		};
+
+		/* ... */
+	};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/stmpe.txt b/Documentation/devicetree/bindings/input/touchscreen/stmpe.txt
new file mode 100644
index 0000000..127baa3
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/stmpe.txt
@@ -0,0 +1,43 @@
+STMPE Touchscreen
+----------------
+
+Required properties:
+ - compatible: "st,stmpe-ts"
+
+Optional properties:
+- st,sample-time: ADC converstion time in number of clock.  (0 -> 36 clocks, 1 ->
+  44 clocks, 2 -> 56 clocks, 3 -> 64 clocks, 4 -> 80 clocks, 5 -> 96 clocks, 6
+  -> 144 clocks), recommended is 4.
+- st,mod-12b: ADC Bit mode (0 -> 10bit ADC, 1 -> 12bit ADC)
+- st,ref-sel: ADC reference source (0 -> internal reference, 1 -> external
+  reference)
+- st,adc-freq: ADC Clock speed (0 -> 1.625 MHz, 1 -> 3.25 MHz, 2 || 3 -> 6.5 MHz)
+- st,ave-ctrl: Sample average control (0 -> 1 sample, 1 -> 2 samples, 2 -> 4
+  samples, 3 -> 8 samples)
+- st,touch-det-delay: Touch detect interrupt delay (0 -> 10 us, 1 -> 50 us, 2 ->
+  100 us, 3 -> 500 us, 4-> 1 ms, 5 -> 5 ms, 6 -> 10 ms, 7 -> 50 ms) recommended
+  is 3
+- st,settling: Panel driver settling time (0 -> 10 us, 1 -> 100 us, 2 -> 500 us, 3
+  -> 1 ms, 4 -> 5 ms, 5 -> 10 ms, 6 for 50 ms, 7 -> 100 ms) recommended is 2
+- st,fraction-z: Length of the fractional part in z (fraction-z ([0..7]) = Count of
+  the fractional part) recommended is 7
+- st,i-drive: current limit value of the touchscreen drivers (0 -> 20 mA typical 35
+  mA max, 1 -> 50 mA typical 80 mA max)
+
+Node name must be stmpe_touchscreen and should be child node of stmpe node to
+which it belongs.
+
+Example:
+
+	stmpe_touchscreen {
+		compatible = "st,stmpe-ts";
+		st,sample-time = <4>;
+		st,mod-12b = <1>;
+		st,ref-sel = <0>;
+		st,adc-freq = <1>;
+		st,ave-ctrl = <1>;
+		st,touch-det-delay = <2>;
+		st,settling = <2>;
+		st,fraction-z = <7>;
+		st,i-drive = <1>;
+	};
diff --git a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sunxi-ic.txt b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sunxi-ic.txt
new file mode 100644
index 0000000..7f9fb85
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sunxi-ic.txt
@@ -0,0 +1,104 @@
+Allwinner Sunxi Interrupt Controller
+
+Required properties:
+
+- compatible : should be "allwinner,sunxi-ic"
+- reg : Specifies base physical address and size of the registers.
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 1.
+
+The interrupt sources are as follows:
+
+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: SDMC0
+33: SDMC1
+34: SDMC2
+35: SDMC3
+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
+
+Example:
+
+intc: interrupt-controller {
+	compatible = "allwinner,sunxi-ic";
+	reg = <0x01c20400 0x400>;
+	interrupt-controller;
+	#interrupt-cells = <2>;
+};
diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt
new file mode 100644
index 0000000..2d88816
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/common.txt
@@ -0,0 +1,23 @@
+Common leds properties.
+
+Optional properties for child nodes:
+- label : The label for this LED.  If omitted, the label is
+  taken from the node name (excluding the unit address).
+
+- linux,default-trigger :  This parameter, if present, is a
+    string defining the trigger assigned to the LED.  Current triggers are:
+     "backlight" - LED will act as a back-light, controlled by the framebuffer
+		   system
+     "default-on" - LED will turn on (but for leds-gpio see "default-state"
+		    property in Documentation/devicetree/bindings/gpio/led.txt)
+     "heartbeat" - LED "double" flashes at a load average based rate
+     "ide-disk" - LED indicates disk activity
+     "timer" - LED flashes at a fixed, configurable rate
+
+Examples:
+
+system-status {
+	label = "Status";
+	linux,default-trigger = "heartbeat";
+	...
+};
diff --git a/Documentation/devicetree/bindings/media/s5p-mfc.txt b/Documentation/devicetree/bindings/media/s5p-mfc.txt
new file mode 100644
index 0000000..67ec3d4
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/s5p-mfc.txt
@@ -0,0 +1,23 @@
+* Samsung Multi Format Codec (MFC)
+
+Multi Format Codec (MFC) is the IP present in Samsung SoCs which
+supports high resolution decoding and encoding functionalities.
+The MFC device driver is a v4l2 driver which can encode/decode
+video raw/elementary streams and has support for all popular
+video codecs.
+
+Required properties:
+  - compatible : value should be either one among the following
+	(a) "samsung,mfc-v5" for MFC v5 present in Exynos4 SoCs
+	(b) "samsung,mfc-v6" for MFC v6 present in Exynos5 SoCs
+
+  - reg : Physical base address of the IP registers and length of memory
+	  mapped region.
+
+  - interrupts : MFC interrupt number to the CPU.
+
+  - samsung,mfc-r : Base address of the first memory bank used by MFC
+		    for DMA contiguous memory allocation and its size.
+
+  - samsung,mfc-l : Base address of the second memory bank used by MFC
+		    for DMA contiguous memory allocation and its size.
diff --git a/Documentation/devicetree/bindings/mfd/ab8500.txt b/Documentation/devicetree/bindings/mfd/ab8500.txt
index ce83c8d..13b707b 100644
--- a/Documentation/devicetree/bindings/mfd/ab8500.txt
+++ b/Documentation/devicetree/bindings/mfd/ab8500.txt
@@ -24,7 +24,32 @@ ab8500-bm                :                      :              : Battery Manager
 ab8500-btemp             :                      :              : Battery Temperature
 ab8500-charger           :                      :              : Battery Charger
 ab8500-codec             :                      :              : Audio Codec
-ab8500-fg                :                      :              : Fuel Gauge
+ab8500-fg                : 			: vddadc       : Fuel Gauge
+			 : NCONV_ACCU           :	       : Accumulate N Sample Conversion
+			 : BATT_OVV		:	       : Battery Over Voltage
+			 : LOW_BAT_F		:	       : LOW threshold battery voltage
+			 : CC_INT_CALIB		:	       : Coulomb Counter Internal Calibration
+			 : CCEOC		:	       : Coulomb Counter End of Conversion
+ab8500-btemp		 :			: vtvout       : Battery Temperature
+			 : BAT_CTRL_INDB        :              : Battery Removal Indicator
+			 : BTEMP_LOW            :              : Btemp < BtempLow, if battery temperature is lower than -10°C
+			 : BTEMP_LOW_MEDIUM     :              : BtempLow < Btemp < BtempMedium,if battery temperature is between -10 and 0°C
+			 : BTEMP_MEDIUM_HIGH    :	       : BtempMedium < Btemp < BtempHigh,if battery temperature is between 0°C and“MaxTemp
+			 : BTEMP_HIGH           :              : Btemp > BtempHigh, if battery temperature is higher than “MaxTemp
+ab8500-charger		 :			: vddadc       : Charger interface
+			 : MAIN_CH_UNPLUG_DET	:	       : main charger unplug detection management (not in 8505)
+			 : MAIN_CHARGE_PLUG_DET	:	       : main charger plug detection management (not in 8505)
+			 : MAIN_EXT_CH_NOT_OK	:	       : main charger not OK
+			 : MAIN_CH_TH_PROT_R	:	       : Die temp is above main charger
+			 : MAIN_CH_TH_PROT_F	:	       : Die temp is below main charger
+			 : VBUS_DET_F		:	       : VBUS falling detected
+			 : VBUS_DET_R		:	       : VBUS rising detected
+			 : USB_LINK_STATUS	:	       : USB link status has changed
+			 : USB_CH_TH_PROT_R	:	       : Die temp is above usb charger
+			 : USB_CH_TH_PROT_F	:	       : Die temp is below usb charger
+			 : USB_CHARGER_NOT_OKR	:	       : allowed USB charger not ok detection
+			 : VBUS_OVV		:	       : Overvoltage on Vbus ball detected (USB charge is stopped)
+			 : CH_WD_EXP		:	       : Charger watchdog detected
 ab8500-gpadc             : HW_CONV_END          : vddadc       : Analogue to Digital Converter
                            SW_CONV_END          :              :
 ab8500-gpio              :                      :              : GPIO Controller
diff --git a/Documentation/devicetree/bindings/mfd/stmpe.txt b/Documentation/devicetree/bindings/mfd/stmpe.txt
new file mode 100644
index 0000000..c984508
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/stmpe.txt
@@ -0,0 +1,25 @@
+* STMPE Multi-Functional Device
+
+Required properties:
+ - compatible                   : "st,stmpe[811|1601|2401|2403]"
+ - reg                          : I2C address of the device
+
+Optional properties:
+ - interrupts                   : The interrupt outputs from the controller
+ - interrupt-controller         : Marks the device node as an interrupt controller
+ - interrupt-parent             : Specifies which IRQ controller we're connected to
+ - wakeup-source                : Marks the input device as wakable
+ - st,autosleep-timeout         : Valid entries (ms); 4, 16, 32, 64, 128, 256, 512 and 1024
+
+Example:
+
+	stmpe1601: stmpe1601@40 {
+		compatible = "st,stmpe1601";
+		reg = <0x40>;
+		interrupts = <26 0x4>;
+		interrupt-parent = <&gpio6>;
+		interrupt-controller;
+
+		wakeup-source;
+		st,autosleep-timeout = <1024>;
+	};
diff --git a/Documentation/devicetree/bindings/misc/atmel-ssc.txt b/Documentation/devicetree/bindings/misc/atmel-ssc.txt
new file mode 100644
index 0000000..38e51ad
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/atmel-ssc.txt
@@ -0,0 +1,15 @@
+* Atmel SSC driver.
+
+Required properties:
+- compatible: "atmel,at91rm9200-ssc" or "atmel,at91sam9g45-ssc"
+	- atmel,at91rm9200-ssc: support pdc transfer
+	- atmel,at91sam9g45-ssc: support dma transfer
+- reg: Should contain SSC registers location and length
+- interrupts: Should contain SSC interrupt
+
+Example:
+ssc0: ssc@fffbc000 {
+	compatible = "atmel,at91rm9200-ssc";
+	reg = <0xfffbc000 0x4000>;
+	interrupts = <14 4 5>;
+};
diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt
index 8e2e0ba..b96e510 100644
--- a/Documentation/devicetree/bindings/mmc/mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/mmc.txt
@@ -22,6 +22,10 @@ Optional properties:
 - wp-inverted: when present, polarity on the wp gpio line is inverted
 - max-frequency: maximum operating clock frequency
 
+Optional SDIO properties:
+- keep-power-in-suspend: Preserves card power during a suspend/resume cycle
+- enable-sdio-wakeup: Enables wake up of host system on SDIO IRQ assertion
+
 Example:
 
 sdhci@ab000000 {
@@ -33,4 +37,6 @@ sdhci@ab000000 {
 	cd-inverted;
 	wp-gpios = <&gpio 70 0>;
 	max-frequency = <50000000>;
+	keep-power-in-suspend;
+	enable-sdio-wakeup;
 }
diff --git a/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt b/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
index 630a7d7..97e9e31 100644
--- a/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
@@ -12,10 +12,6 @@ is used. The Samsung's SDHCI controller bindings extends this as listed below.
 [A] The property "samsung,cd-pinmux-gpio" can be used as stated in the
     "Optional Board Specific Properties" section below.
 
-[B] If core card-detect bindings and "samsung,cd-pinmux-gpio" property
-    is not specified, it is assumed that there is no card detection
-    mechanism used.
-
 Required SoC Specific Properties:
 - compatible: should be one of the following
   - "samsung,s3c6410-sdhci": For controllers compatible with s3c6410 sdhci
@@ -24,14 +20,18 @@ Required SoC Specific Properties:
     controller.
 
 Required Board Specific Properties:
-- gpios: Should specify the gpios used for clock, command and data lines. The
-  gpio specifier format depends on the gpio controller.
+- Samsung GPIO variant (will be completely replaced by pinctrl):
+  - gpios: Should specify the gpios used for clock, command and data lines. The
+    gpio specifier format depends on the gpio controller.
+- Pinctrl variant (preferred if available):
+  - pinctrl-0: Should specify pin control groups used for this controller.
+  - pinctrl-names: Should contain only one value - "default".
 
 Optional Board Specific Properties:
 - samsung,cd-pinmux-gpio: Specifies the card detect line that is routed
   through a pinmux to the card-detect pin of the card slot. This property
   should be used only if none of the mmc core card-detect properties are
-  used.
+  used. Only for Samsung GPIO variant.
 
 Example:
 	sdhci@12530000 {
@@ -40,12 +40,18 @@ Example:
 		interrupts = <0 75 0>;
 		bus-width = <4>;
 		cd-gpios = <&gpk2 2 2 3 3>;
+
+		/* Samsung GPIO variant */
 		gpios = <&gpk2 0 2 0 3>,  /* clock line */
 			<&gpk2 1 2 0 3>,  /* command line */
 			<&gpk2 3 2 3 3>,  /* data line 0 */
 			<&gpk2 4 2 3 3>,  /* data line 1 */
 			<&gpk2 5 2 3 3>,  /* data line 2 */
 			<&gpk2 6 2 3 3>;  /* data line 3 */
+
+		/* Pinctrl variant */
+		pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4>;
+		pinctrl-names = "default";
 	};
 
 	Note: This example shows both SoC specific and board specific properties
diff --git a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt
new file mode 100644
index 0000000..06cd32d08
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt
@@ -0,0 +1,79 @@
+* Synopsis Designware Mobile Storage Host Controller
+
+The Synopsis designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core mmc properties described by mmc.txt and the
+properties used by the Synopsis Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be
+	- snps,dw-mshc: for controllers compliant with synopsis dw-mshc.
+* #address-cells: should be 1.
+* #size-cells: should be 0.
+
+# Slots: The slot specific information are contained within child-nodes with
+  each child-node representing a supported slot. There should be atleast one
+  child node representing a card slot. The name of the child node representing
+  the slot is recommended to be slot@n where n is the unique number of the slot
+  connnected to the controller. The following are optional properties which
+  can be included in the slot child node.
+
+	* reg: specifies the physical slot number. The valid values of this
+	  property is 0 to (num-slots -1), where num-slots is the value
+	  specified by the num-slots property.
+
+	* bus-width: as documented in mmc core bindings.
+
+	* wp-gpios: specifies the write protect gpio line. The format of the
+	  gpio specifier depends on the gpio controller. If the write-protect
+	  line is not available, this property is optional.
+
+Optional properties:
+
+* num-slots: specifies the number of slots supported by the controller.
+  The number of physical slots actually used could be equal or less than the
+  value specified by num-slots. If this property is not specified, the value
+  of num-slot property is assumed to be 1.
+
+* fifo-depth: The maximum size of the tx/rx fifo's. If this property is not
+  specified, the default value of the fifo size is determined from the
+  controller registers.
+
+* card-detect-delay: Delay in milli-seconds before detecting card after card
+  insert event. The default value is 0.
+
+* supports-highspeed: Enables support for high speed cards (upto 50MHz)
+
+* broken-cd: as documented in mmc core bindings.
+
+Aliases:
+
+- All the MSHC controller nodes should be represented in the aliases node using
+  the following format 'mshc{n}' where n is a unique number for the alias.
+
+Example:
+
+The MSHC controller node can be split into two portions, SoC specific and
+board specific portions as listed below.
+
+	dwmmc0@12200000 {
+		compatible = "snps,dw-mshc";
+		reg = <0x12200000 0x1000>;
+		interrupts = <0 75 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	dwmmc0@12200000 {
+		num-slots = <1>;
+		supports-highspeed;
+		broken-cd;
+		fifo-depth = <0x80>;
+		card-detect-delay = <200>;
+
+		slot@0 {
+			reg = <0>;
+			bus-width = <8>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt
deleted file mode 100644
index 06cd32d08..0000000
--- a/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt
+++ /dev/null
@@ -1,79 +0,0 @@
-* Synopsis Designware Mobile Storage Host Controller
-
-The Synopsis designware mobile storage host controller is used to interface
-a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
-differences between the core mmc properties described by mmc.txt and the
-properties used by the Synopsis Designware Mobile Storage Host Controller.
-
-Required Properties:
-
-* compatible: should be
-	- snps,dw-mshc: for controllers compliant with synopsis dw-mshc.
-* #address-cells: should be 1.
-* #size-cells: should be 0.
-
-# Slots: The slot specific information are contained within child-nodes with
-  each child-node representing a supported slot. There should be atleast one
-  child node representing a card slot. The name of the child node representing
-  the slot is recommended to be slot@n where n is the unique number of the slot
-  connnected to the controller. The following are optional properties which
-  can be included in the slot child node.
-
-	* reg: specifies the physical slot number. The valid values of this
-	  property is 0 to (num-slots -1), where num-slots is the value
-	  specified by the num-slots property.
-
-	* bus-width: as documented in mmc core bindings.
-
-	* wp-gpios: specifies the write protect gpio line. The format of the
-	  gpio specifier depends on the gpio controller. If the write-protect
-	  line is not available, this property is optional.
-
-Optional properties:
-
-* num-slots: specifies the number of slots supported by the controller.
-  The number of physical slots actually used could be equal or less than the
-  value specified by num-slots. If this property is not specified, the value
-  of num-slot property is assumed to be 1.
-
-* fifo-depth: The maximum size of the tx/rx fifo's. If this property is not
-  specified, the default value of the fifo size is determined from the
-  controller registers.
-
-* card-detect-delay: Delay in milli-seconds before detecting card after card
-  insert event. The default value is 0.
-
-* supports-highspeed: Enables support for high speed cards (upto 50MHz)
-
-* broken-cd: as documented in mmc core bindings.
-
-Aliases:
-
-- All the MSHC controller nodes should be represented in the aliases node using
-  the following format 'mshc{n}' where n is a unique number for the alias.
-
-Example:
-
-The MSHC controller node can be split into two portions, SoC specific and
-board specific portions as listed below.
-
-	dwmmc0@12200000 {
-		compatible = "snps,dw-mshc";
-		reg = <0x12200000 0x1000>;
-		interrupts = <0 75 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-	};
-
-	dwmmc0@12200000 {
-		num-slots = <1>;
-		supports-highspeed;
-		broken-cd;
-		fifo-depth = <0x80>;
-		card-detect-delay = <200>;
-
-		slot@0 {
-			reg = <0>;
-			bus-width = <8>;
-		};
-	};
diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
index be76a23..ed271fc 100644
--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
@@ -19,6 +19,7 @@ ti,dual-volt: boolean, supports dual voltage cards
 "supply-name" examples are "vmmc", "vmmc_aux" etc
 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
 
 Example:
 	mmc1: mmc@0x4809c000 {
diff --git a/Documentation/devicetree/bindings/mmc/vt8500-sdmmc.txt b/Documentation/devicetree/bindings/mmc/vt8500-sdmmc.txt
new file mode 100644
index 0000000..d7fb6ab
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/vt8500-sdmmc.txt
@@ -0,0 +1,23 @@
+* Wondermedia WM8505/WM8650 SD/MMC Host Controller
+
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the wmt-sdmmc driver.
+
+Required properties:
+- compatible: Should be "wm,wm8505-sdhc".
+- interrupts: Two interrupts are required - regular irq and dma irq.
+
+Optional properties:
+- sdon-inverted: SD_ON bit is inverted on the controller
+
+Examples:
+
+sdhc@d800a000 {
+	compatible = "wm,wm8505-sdhc";
+	reg = <0xd800a000 0x1000>;
+	interrupts = <20 21>;
+	clocks = <&sdhc>;
+	bus-width = <4>;
+	sdon-inverted;
+};
+
diff --git a/Documentation/devicetree/bindings/mtd/denali-nand.txt b/Documentation/devicetree/bindings/mtd/denali-nand.txt
new file mode 100644
index 0000000..b04d03a
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/denali-nand.txt
@@ -0,0 +1,23 @@
+* Denali NAND controller
+
+Required properties:
+  - compatible : should be "denali,denali-nand-dt"
+  - reg : should contain registers location and length for data and reg.
+  - reg-names: Should contain the reg names "nand_data" and "denali_reg"
+  - interrupts : The interrupt number.
+  - dm-mask : DMA bit mask
+
+The device tree may optionally contain sub-nodes describing partitions of the
+address space. See partition.txt for more detail.
+
+Examples:
+
+nand: nand@ff900000 {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "denali,denali-nand-dt";
+	reg = <0xff900000 0x100000>, <0xffb80000 0x10000>;
+	reg-names = "nand_data", "denali_reg";
+	interrupts = <0 144 4>;
+	dma-mask = <0xffffffff>;
+};
diff --git a/Documentation/devicetree/bindings/mtd/flctl-nand.txt b/Documentation/devicetree/bindings/mtd/flctl-nand.txt
new file mode 100644
index 0000000..427f46d
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/flctl-nand.txt
@@ -0,0 +1,49 @@
+FLCTL NAND controller
+
+Required properties:
+- compatible : "renesas,shmobile-flctl-sh7372"
+- reg : Address range of the FLCTL
+- interrupts : flste IRQ number
+- nand-bus-width : bus width to NAND chip
+
+Optional properties:
+- dmas: DMA specifier(s)
+- dma-names: name for each DMA specifier. Valid names are
+	     "data_tx", "data_rx", "ecc_tx", "ecc_rx"
+
+The DMA fields are not used yet in the driver but are listed here for
+completing the bindings.
+
+The device tree may optionally contain sub-nodes describing partitions of the
+address space. See partition.txt for more detail.
+
+Example:
+
+	flctl@e6a30000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "renesas,shmobile-flctl-sh7372";
+		reg = <0xe6a30000 0x100>;
+		interrupts = <0x0d80>;
+
+		nand-bus-width = <16>;
+
+		dmas = <&dmac 1 /* data_tx */
+			&dmac 2;> /* data_rx */
+		dma-names = "data_tx", "data_rx";
+
+		system@0 {
+			label = "system";
+			reg = <0x0 0x8000000>;
+		};
+
+		userdata@8000000 {
+			label = "userdata";
+			reg = <0x8000000 0x10000000>;
+		};
+
+		cache@18000000 {
+			label = "cache";
+			reg = <0x18000000 0x8000000>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/mtd/fsmc-nand.txt b/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
index e2c663b..e3ea32e 100644
--- a/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
@@ -3,9 +3,7 @@
 Required properties:
 - compatible : "st,spear600-fsmc-nand"
 - reg : Address range of the mtd chip
-- reg-names: Should contain the reg names "fsmc_regs" and "nand_data"
-- st,ale-off : Chip specific offset to ALE
-- st,cle-off : Chip specific offset to CLE
+- reg-names: Should contain the reg names "fsmc_regs", "nand_data", "nand_addr" and "nand_cmd"
 
 Optional properties:
 - bank-width : Width (in bytes) of the device.  If not present, the width
@@ -19,10 +17,10 @@ Example:
 		#address-cells = <1>;
 		#size-cells = <1>;
 		reg = <0xd1800000 0x1000	/* FSMC Register */
-		       0xd2000000 0x4000>;	/* NAND Base */
-		reg-names = "fsmc_regs", "nand_data";
-		st,ale-off = <0x20000>;
-		st,cle-off = <0x10000>;
+		       0xd2000000 0x0010	/* NAND Base DATA */
+		       0xd2020000 0x0010	/* NAND Base ADDR */
+		       0xd2010000 0x0010>;	/* NAND Base CMD */
+		reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
 
 		bank-width = <1>;
 		nand-skip-bbtscan;
diff --git a/Documentation/devicetree/bindings/mtd/m25p80.txt b/Documentation/devicetree/bindings/mtd/m25p80.txt
new file mode 100644
index 0000000..6d3d576
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/m25p80.txt
@@ -0,0 +1,29 @@
+* MTD SPI driver for ST M25Pxx (and similar) serial flash chips
+
+Required properties:
+- #address-cells, #size-cells : Must be present if the device has sub-nodes
+  representing partitions.
+- compatible : Should be the manufacturer and the name of the chip. Bear in mind
+               the DT binding is not Linux-only, but in case of Linux, see the
+               "m25p_ids" table in drivers/mtd/devices/m25p80.c for the list of
+               supported chips.
+- reg : Chip-Select number
+- spi-max-frequency : Maximum frequency of the SPI bus the chip can operate at
+
+Optional properties:
+- m25p,fast-read : Use the "fast read" opcode to read data from the chip instead
+                   of the usual "read" opcode. This opcode is not supported by
+                   all chips and support for it can not be detected at runtime.
+                   Refer to your chips' datasheet to check if this is supported
+                   by your chip.
+
+Example:
+
+	flash: m25p80@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spansion,m25p80";
+		reg = <0>;
+		spi-max-frequency = <40000000>;
+		m25p,fast-read;
+	};
diff --git a/Documentation/devicetree/bindings/mtd/mtd-physmap.txt b/Documentation/devicetree/bindings/mtd/mtd-physmap.txt
index 94de19b..dab7847 100644
--- a/Documentation/devicetree/bindings/mtd/mtd-physmap.txt
+++ b/Documentation/devicetree/bindings/mtd/mtd-physmap.txt
@@ -23,6 +23,9 @@ file systems on embedded devices.
    unaligned accesses as implemented in the JFFS2 code via memcpy().
    By defining "no-unaligned-direct-access", the flash will not be
    exposed directly to the MTD users (e.g. JFFS2) any more.
+ - linux,mtd-name: allow to specify the mtd name for retro capability with
+   physmap-flash drivers as boot loader pass the mtd partition via the old
+   device name physmap-flash.
 
 For JEDEC compatible devices, the following additional properties
 are defined:
diff --git a/Documentation/devicetree/bindings/net/can/grcan.txt b/Documentation/devicetree/bindings/net/can/grcan.txt
new file mode 100644
index 0000000..34ef349
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/grcan.txt
@@ -0,0 +1,28 @@
+Aeroflex Gaisler GRCAN and GRHCAN CAN controllers.
+
+The GRCAN and CRHCAN CAN controllers are available in the GRLIB VHDL IP core
+library.
+
+Note: These properties are built from the AMBA plug&play in a Leon SPARC system
+(the ordinary environment for GRCAN and GRHCAN). There are no dts files for
+sparc.
+
+Required properties:
+
+- name : Should be "GAISLER_GRCAN", "01_03d", "GAISLER_GRHCAN" or "01_034"
+
+- reg : Address and length of the register set for the device
+
+- freq : Frequency of the external oscillator clock in Hz (the frequency of
+	the amba bus in the ordinary case)
+
+- interrupts : Interrupt number for this device
+
+Optional properties:
+
+- systemid : If not present or if the value of the least significant 16 bits
+	of this 32-bit property is smaller than GRCAN_TXBUG_SAFE_GRLIB_VERSION
+	a bug workaround is activated.
+
+For further information look in the documentation for the GLIB IP core library:
+http://www.gaisler.com/products/grlib/grip.pdf
diff --git a/Documentation/devicetree/bindings/net/cdns-emac.txt b/Documentation/devicetree/bindings/net/cdns-emac.txt
new file mode 100644
index 0000000..09055c2
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/cdns-emac.txt
@@ -0,0 +1,23 @@
+* Cadence EMAC Ethernet controller
+
+Required properties:
+- compatible: Should be "cdns,[<chip>-]{emac}"
+  Use "cdns,at91rm9200-emac" Atmel at91rm9200 SoC.
+  or the generic form: "cdns,emac".
+- reg: Address and length of the register set for the device
+- interrupts: Should contain macb interrupt
+- phy-mode: String, operation mode of the PHY interface.
+  Supported values are: "mii", "rmii".
+
+Optional properties:
+- local-mac-address: 6 bytes, mac address
+
+Examples:
+
+	macb0: ethernet@fffc4000 {
+		compatible = "cdns,at91rm9200-emac";
+		reg = <0xfffc4000 0x4000>;
+		interrupts = <21>;
+		phy-mode = "rmii";
+		local-mac-address = [3a 0e 03 04 05 06];
+	};
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index dcaabe9..6ddd028 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -9,21 +9,15 @@ Required properties:
 			  number
 - interrupt-parent	: The parent interrupt controller
 - cpdma_channels 	: Specifies number of channels in CPDMA
-- host_port_no		: Specifies host port shift
-- cpdma_reg_ofs		: Specifies CPDMA submodule register offset
-- cpdma_sram_ofs	: Specifies CPDMA SRAM offset
-- ale_reg_ofs		: Specifies ALE submodule register offset
 - ale_entries		: Specifies No of entries ALE can hold
-- host_port_reg_ofs	: Specifies host port register offset
-- hw_stats_reg_ofs	: Specifies hardware statistics register offset
-- bd_ram_ofs		: Specifies internal desciptor RAM offset
 - bd_ram_size		: Specifies internal descriptor RAM size
 - rx_descs		: Specifies number of Rx descriptors
 - mac_control		: Specifies Default MAC control register content
 			  for the specific platform
 - slaves		: Specifies number for slaves
-- slave_reg_ofs		: Specifies slave register offset
-- sliver_reg_ofs	: Specifies slave sliver register offset
+- cpts_active_slave	: Specifies the slave to use for time stamping
+- cpts_clock_mult	: Numerator to convert input clock ticks into nanoseconds
+- cpts_clock_shift	: Denominator to convert input clock ticks into nanoseconds
 - phy_id		: Specifies slave phy id
 - mac-address		: Specifies slave MAC address
 
@@ -45,30 +39,22 @@ Examples:
 		interrupts = <55 0x4>;
 		interrupt-parent = <&intc>;
 		cpdma_channels = <8>;
-		host_port_no = <0>;
-		cpdma_reg_ofs = <0x800>;
-		cpdma_sram_ofs = <0xa00>;
-		ale_reg_ofs = <0xd00>;
 		ale_entries = <1024>;
-		host_port_reg_ofs = <0x108>;
-		hw_stats_reg_ofs = <0x900>;
-		bd_ram_ofs = <0x2000>;
 		bd_ram_size = <0x2000>;
 		no_bd_ram = <0>;
 		rx_descs = <64>;
 		mac_control = <0x20>;
 		slaves = <2>;
+		cpts_active_slave = <0>;
+		cpts_clock_mult = <0x80000000>;
+		cpts_clock_shift = <29>;
 		cpsw_emac0: slave@0 {
-			slave_reg_ofs = <0x208>;
-			sliver_reg_ofs = <0xd80>;
-			phy_id = "davinci_mdio.16:00";
+			phy_id = <&davinci_mdio>, <0>;
 			/* Filled in by U-Boot */
 			mac-address = [ 00 00 00 00 00 00 ];
 		};
 		cpsw_emac1: slave@1 {
-			slave_reg_ofs = <0x308>;
-			sliver_reg_ofs = <0xdc0>;
-			phy_id = "davinci_mdio.16:01";
+			phy_id = <&davinci_mdio>, <1>;
 			/* Filled in by U-Boot */
 			mac-address = [ 00 00 00 00 00 00 ];
 		};
@@ -79,30 +65,22 @@ Examples:
 		compatible = "ti,cpsw";
 		ti,hwmods = "cpgmac0";
 		cpdma_channels = <8>;
-		host_port_no = <0>;
-		cpdma_reg_ofs = <0x800>;
-		cpdma_sram_ofs = <0xa00>;
-		ale_reg_ofs = <0xd00>;
 		ale_entries = <1024>;
-		host_port_reg_ofs = <0x108>;
-		hw_stats_reg_ofs = <0x900>;
-		bd_ram_ofs = <0x2000>;
 		bd_ram_size = <0x2000>;
 		no_bd_ram = <0>;
 		rx_descs = <64>;
 		mac_control = <0x20>;
 		slaves = <2>;
+		cpts_active_slave = <0>;
+		cpts_clock_mult = <0x80000000>;
+		cpts_clock_shift = <29>;
 		cpsw_emac0: slave@0 {
-			slave_reg_ofs = <0x208>;
-			sliver_reg_ofs = <0xd80>;
-			phy_id = "davinci_mdio.16:00";
+			phy_id = <&davinci_mdio>, <0>;
 			/* Filled in by U-Boot */
 			mac-address = [ 00 00 00 00 00 00 ];
 		};
 		cpsw_emac1: slave@1 {
-			slave_reg_ofs = <0x308>;
-			sliver_reg_ofs = <0xdc0>;
-			phy_id = "davinci_mdio.16:01";
+			phy_id = <&davinci_mdio>, <1>;
 			/* Filled in by U-Boot */
 			mac-address = [ 00 00 00 00 00 00 ];
 		};
diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
new file mode 100644
index 0000000..3a26812
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
@@ -0,0 +1,141 @@
+* Atmel AT91 Pinmux Controller
+
+The AT91 Pinmux Controler, enables the IC
+to share one PAD to several functional blocks. The sharing is done by
+multiplexing the PAD input/output signals. For each PAD there are up to
+8 muxing options (called periph modes). Since different modules require
+different PAD settings (like pull up, keeper, etc) the contoller controls
+also the PAD settings parameters.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+Atmel AT91 pin configuration node is a node of a group of pins which can be
+used for a specific device or function. This node represents both mux and config
+of the pins in that group. The 'pins' selects the function mode(also named pin
+mode) this pin can work on and the 'config' configures various pad settings
+such as pull-up, multi drive, etc.
+
+Required properties for iomux controller:
+- compatible: "atmel,at91rm9200-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.
+
+How to create such array:
+
+Each column will represent the possible peripheral of the pinctrl
+Each line will represent a pio bank
+
+Take an example on the 9260
+Peripheral: 2 ( A and B)
+Bank: 3 (A, B and C)
+=>
+
+  /*    A         B     */
+  0xffffffff 0xffc00c3b  /* pioA */
+  0xffffffff 0x7fff3ccf  /* pioB */
+  0xffffffff 0x007fffff  /* pioC */
+
+For each peripheral/bank we will descibe in a u32 if a pin can can be
+configured in it by putting 1 to the pin bit (1 << pin)
+
+Let's take the pioA on peripheral B
+From the datasheet Table 10-2.
+Peripheral B
+PA0	MCDB0
+PA1	MCCDB
+PA2
+PA3	MCDB3
+PA4	MCDB2
+PA5	MCDB1
+PA6
+PA7
+PA8
+PA9
+PA10	ETX2
+PA11	ETX3
+PA12
+PA13
+PA14
+PA15
+PA16
+PA17
+PA18
+PA19
+PA20
+PA21
+PA22	ETXER
+PA23	ETX2
+PA24	ETX3
+PA25	ERX2
+PA26	ERX3
+PA27	ERXCK
+PA28	ECRS
+PA29	ECOL
+PA30	RXD4
+PA31	TXD4
+
+=> 0xffc00c3b
+
+Required properties for pin configuration node:
+- atmel,pins: 4 integers array, represents a group of pins mux and config
+  setting. The format is atmel,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>.
+  The PERIPH 0 means gpio.
+
+Bits used for CONFIG:
+PULL_UP		(1 << 0): indicate this pin need a pull up.
+MULTIDRIVE	(1 << 1): indicate this pin need to be configured as multidrive.
+DEGLITCH	(1 << 2): indicate this pin need deglitch.
+PULL_DOWN	(1 << 3): indicate this pin need a pull down.
+DIS_SCHMIT	(1 << 4): indicate this pin need to disable schmit trigger.
+DEBOUNCE	(1 << 16): indicate this pin need debounce.
+DEBOUNCE_VAL	(0x3fff << 17): debounce val.
+
+NOTE:
+Some requirements for using atmel,at91rm9200-pinctrl binding:
+1. We have pin function node defined under at91 controller node to represent
+   what pinmux functions this SoC supports.
+2. The driver can use the function node's name and pin configuration node's
+   name describe the pin function and group hierarchy.
+   For example, Linux at91 pinctrl driver takes the function node's name
+   as the function name and pin configuration node's name as group name to
+   create the map table.
+3. Each pin configuration node should have a phandle, devices can set pins
+   configurations by referring to the phandle of that pin configuration node.
+4. The gpio controller must be describe in the pinctrl simple-bus.
+
+Examples:
+
+pinctrl@fffff400 {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+	compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
+	reg = <0xfffff400 0x600>;
+
+	atmel,mux-mask = <
+	      /*    A         B     */
+	       0xffffffff 0xffc00c3b  /* pioA */
+	       0xffffffff 0x7fff3ccf  /* pioB */
+	       0xffffffff 0x007fffff  /* pioC */
+	      >;
+
+	/* shared pinctrl settings */
+	dbgu {
+		pinctrl_dbgu: dbgu-0 {
+			atmel,pins =
+				<1 14 0x1 0x0	/* PB14 periph A */
+				 1 15 0x1 0x1>;	/* PB15 periph with pullup */
+		};
+	};
+};
+
+dbgu: serial@fffff200 {
+	compatible = "atmel,at91sam9260-usart";
+	reg = <0xfffff200 0x200>;
+	interrupts = <1 4 7>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_dbgu>;
+	status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
index 361bccb..95daf63 100644
--- a/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
@@ -7,8 +7,10 @@ Required properties:
 - compatible: "marvell,88f6180-pinctrl",
               "marvell,88f6190-pinctrl", "marvell,88f6192-pinctrl",
               "marvell,88f6281-pinctrl", "marvell,88f6282-pinctrl"
+              "marvell,98dx4122-pinctrl"
 
 This driver supports all kirkwood variants, i.e. 88f6180, 88f619x, and 88f628x.
+It also support the 88f6281-based variant in the 98dx412x Bobcat SoCs.
 
 Available mpp pins/groups and functions:
 Note: brackets (x) are not part of the mpp name for marvell,function and given
@@ -277,3 +279,40 @@ mpp46         46       gpio, ts(mp10), tdm(fs), lcd(hsync)
 mpp47         47       gpio, ts(mp11), tdm(drx), lcd(vsync)
 mpp48         48       gpio, ts(mp12), tdm(dtx), lcd(d16)
 mpp49         49       gpo, tdm(rx0ql), pex(clkreq), lcd(d17)
+
+* Marvell Bobcat 98dx4122
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, nand(io2), spi(cs)
+mpp1          1        gpo, nand(io3), spi(mosi)
+mpp2          2        gpo, nand(io4), spi(sck)
+mpp3          3        gpo, nand(io5), spi(miso)
+mpp4          4        gpio, nand(io6), uart0(rxd)
+mpp5          5        gpo, nand(io7), uart0(txd)
+mpp6          6        sysrst(out), spi(mosi)
+mpp7          7        gpo, pex(rsto), spi(cs)
+mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts)
+mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts)
+mpp10         10       gpo, spi(sck), uart0(txd)
+mpp11         11       gpio, spi(miso), uart0(rxd)
+mpp13         13       gpio, uart1(txd)
+mpp14         14       gpio, uart1(rxd)
+mpp15         15       gpio, uart0(rts)
+mpp16         16       gpio, uart0(cts)
+mpp18         18       gpo, nand(io0)
+mpp19         19       gpo, nand(io1)
+mpp34         34       gpio
+mpp35         35       gpio
+mpp36         36       gpio
+mpp37         37       gpio
+mpp38         38       gpio
+mpp39         39       gpio
+mpp40         40       gpio
+mpp41         41       gpio
+mpp42         42       gpio
+mpp43         43       gpio
+mpp44         44       gpio
+mpp45         45       gpio
+mpp49         49       gpio
+
diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
index 03dee50..e97a278 100644
--- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
@@ -8,13 +8,20 @@ on-chip controllers onto these pads.
 Required Properties:
 - compatible: should be one of the following.
   - "samsung,pinctrl-exynos4210": for Exynos4210 compatible pin-controller.
+  - "samsung,pinctrl-exynos4x12": for Exynos4x12 compatible pin-controller.
   - "samsung,pinctrl-exynos5250": for Exynos5250 compatible pin-controller.
 
 - reg: Base address of the pin controller hardware module and length of
   the address space it occupies.
 
-- interrupts: interrupt specifier for the controller. The format and value of
-  the interrupt specifier depends on the interrupt parent for the controller.
+- Pin banks as child nodes: Pin banks of the controller are represented by child
+  nodes of the controller node. Bank name is taken from name of the node. Each
+  bank node must contain following properties:
+
+  - gpio-controller: identifies the node as a gpio controller and pin bank.
+  - #gpio-cells: number of cells in GPIO specifier. Since the generic GPIO
+    binding is used, the amount of cells must be specified as 2. See generic
+    GPIO binding documentation for description of particular cells.
 
 - Pin mux/config groups as child nodes: The pin mux (selecting pin function
   mode) and pin config (pull up/down, driver strength) settings are represented
@@ -72,16 +79,24 @@ used as system wakeup events.
 A. External GPIO Interrupts: For supporting external gpio interrupts, the
    following properties should be specified in the pin-controller device node.
 
-- interrupt-controller: identifies the controller node as interrupt-parent.
-- #interrupt-cells: the value of this property should be 2.
-  - First Cell: represents the external gpio interrupt number local to the
-    external gpio interrupt space of the controller.
-  - Second Cell: flags to identify the type of the interrupt
-    - 1 = rising edge triggered
-    - 2 = falling edge triggered
-    - 3 = rising and falling edge triggered
-    - 4 = high level triggered
-    - 8 = low level triggered
+   - interrupt-parent: phandle of the interrupt parent to which the external
+     GPIO interrupts are forwarded to.
+   - interrupts: interrupt specifier for the controller. The format and value of
+     the interrupt specifier depends on the interrupt parent for the controller.
+
+   In addition, following properties must be present in node of every bank
+   of pins supporting GPIO interrupts:
+
+   - interrupt-controller: identifies the controller node as interrupt-parent.
+   - #interrupt-cells: the value of this property should be 2.
+     - First Cell: represents the external gpio interrupt number local to the
+       external gpio interrupt space of the controller.
+     - Second Cell: flags to identify the type of the interrupt
+       - 1 = rising edge triggered
+       - 2 = falling edge triggered
+       - 3 = rising and falling edge triggered
+       - 4 = high level triggered
+       - 8 = low level triggered
 
 B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
    child node representing the external wakeup interrupt controller should be
@@ -94,6 +109,11 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
        found on Samsung Exynos4210 SoC.
    - interrupt-parent: phandle of the interrupt parent to which the external
      wakeup interrupts are forwarded to.
+   - interrupts: interrupt used by multiplexed wakeup interrupts.
+
+   In addition, following properties must be present in node of every bank
+   of pins supporting wake-up interrupts:
+
    - interrupt-controller: identifies the node as interrupt-parent.
    - #interrupt-cells: the value of this property should be 2
      - First Cell: represents the external wakeup interrupt number local to
@@ -105,11 +125,63 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
        - 4 = high level triggered
        - 8 = low level triggered
 
+   Node of every bank of pins supporting direct wake-up interrupts (without
+   multiplexing) must contain following properties:
+
+   - interrupt-parent: phandle of the interrupt parent to which the external
+     wakeup interrupts are forwarded to.
+   - interrupts: interrupts of the interrupt parent which are used for external
+     wakeup interrupts from pins of the bank, must contain interrupts for all
+     pins of the bank.
+
 Aliases:
 
 All the pin controller nodes should be represented in the aliases node using
 the following format 'pinctrl{n}' where n is a unique number for the alias.
 
+Example: A pin-controller node with pin banks:
+
+	pinctrl_0: pinctrl@11400000 {
+		compatible = "samsung,pinctrl-exynos4210";
+		reg = <0x11400000 0x1000>;
+		interrupts = <0 47 0>;
+
+		/* ... */
+
+		/* Pin bank without external interrupts */
+		gpy0: gpy0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		/* ... */
+
+		/* Pin bank with external GPIO or muxed wake-up interrupts */
+		gpj0: gpj0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		/* ... */
+
+		/* Pin bank with external direct wake-up interrupts */
+		gpx0: gpx0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			interrupt-parent = <&gic>;
+			interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+				     <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
+			#interrupt-cells = <2>;
+		};
+
+		/* ... */
+	};
+
 Example 1: A pin-controller node with pin groups.
 
 	pinctrl_0: pinctrl@11400000 {
@@ -117,6 +189,8 @@ Example 1: A pin-controller node with pin groups.
 		reg = <0x11400000 0x1000>;
 		interrupts = <0 47 0>;
 
+		/* ... */
+
 		uart0_data: uart0-data {
 			samsung,pins = "gpa0-0", "gpa0-1";
 			samsung,pin-function = <2>;
@@ -158,20 +232,14 @@ Example 2: A pin-controller node with external wakeup interrupt controller node.
 	pinctrl_1: pinctrl@11000000 {
 		compatible = "samsung,pinctrl-exynos4210";
 		reg = <0x11000000 0x1000>;
-		interrupts = <0 46 0>;
-		interrupt-controller;
-		#interrupt-cells = <2>;
+		interrupts = <0 46 0>
 
-		wakup_eint: wakeup-interrupt-controller {
+		/* ... */
+
+		wakeup-interrupt-controller {
 			compatible = "samsung,exynos4210-wakeup-eint";
 			interrupt-parent = <&gic>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
-					<0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
-					<0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
-					<0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>,
-					<0 32 0>;
+			interrupts = <0 32 0>;
 		};
 	};
 
@@ -190,7 +258,8 @@ Example 4: Set up the default pin state for uart controller.
 
 	static int s3c24xx_serial_probe(struct platform_device *pdev) {
 		struct pinctrl *pinctrl;
-		...
-		...
+
+		/* ... */
+
 		pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
 	}
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt b/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt
new file mode 100644
index 0000000..0ba1bcc
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt
@@ -0,0 +1,16 @@
+=== AB8500 Battery Temperature Monitor Driver ===
+
+The properties below describes the node for btemp driver.
+
+Required Properties:
+- compatible = Shall be: "stericsson,ab8500-btemp"
+- battery = Shall be battery specific information
+
+	Example:
+	ab8500_btemp {
+		compatible = "stericsson,ab8500-btemp";
+		battery	   = <&ab8500_battery>;
+	};
+
+For information on battery specific node, Ref:
+Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/chargalg.txt b/Documentation/devicetree/bindings/power_supply/ab8500/chargalg.txt
new file mode 100644
index 0000000..ef53283
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/ab8500/chargalg.txt
@@ -0,0 +1,16 @@
+=== AB8500 Charging Algorithm Driver ===
+
+The properties below describes the node for chargalg driver.
+
+Required Properties:
+- compatible = Shall be: "stericsson,ab8500-chargalg"
+- battery = Shall be battery specific information
+
+Example:
+ab8500_chargalg {
+	compatible = "stericsson,ab8500-chargalg";
+	battery	   = <&ab8500_battery>;
+};
+
+For information on battery specific node, Ref:
+Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/charger.txt b/Documentation/devicetree/bindings/power_supply/ab8500/charger.txt
new file mode 100644
index 0000000..6bdbb08
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/ab8500/charger.txt
@@ -0,0 +1,25 @@
+=== AB8500 Charger Driver ===
+
+Required Properties:
+- compatible = Shall be "stericsson,ab8500-charger"
+- battery = Shall be battery specific information
+	Example:
+	ab8500_charger {
+		compatible = "stericsson,ab8500-charger";
+		battery	   = <&ab8500_battery>;
+	};
+
+- vddadc-supply: Supply for USB and Main charger
+	Example:
+	ab8500-charger {
+		vddadc-supply	= <&ab8500_ldo_tvout_reg>;
+	}
+- autopower_cfg:
+	Boolean value depicting the presence of 'automatic poweron after powerloss'
+	Example:
+	ab8500-charger {
+		autopower_cfg;
+	};
+
+For information on battery specific node, Ref:
+Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
new file mode 100644
index 0000000..ccafcb9
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
@@ -0,0 +1,58 @@
+=== AB8500 Fuel Gauge Driver ===
+
+AB8500 is a mixed signal multimedia and power management
+device comprising: power and energy-management-module,
+wall-charger, usb-charger, audio codec, general purpose adc,
+tvout, clock management and sim card interface.
+
+Fuelgauge support is part of energy-management-modules, other
+components of this module are:
+main-charger, usb-combo-charger and battery-temperature-monitoring.
+
+The properties below describes the node for fuelgauge driver.
+
+Required Properties:
+- compatible = This shall be: "stericsson,ab8500-fg"
+- battery = Shall be battery specific information
+	Example:
+	ab8500_fg {
+		compatible = "stericsson,ab8500-fg";
+		battery	   = <&ab8500_battery>;
+	};
+
+dependent node:
+	ab8500_battery: ab8500_battery {
+	};
+	This node will provide information on 'thermistor interface' and
+	'battery technology type' used.
+
+Properties of this node are:
+thermistor-on-batctrl:
+	A boolean value indicating thermistor interface	to battery
+
+	Note:
+	'btemp' and 'batctrl' are the pins interfaced for battery temperature
+	measurement, 'btemp' signal is used when NTC(negative temperature
+	coefficient) resister is interfaced external to battery whereas
+	'batctrl' pin is used when NTC resister is internal to battery.
+
+	Example:
+	ab8500_battery: ab8500_battery {
+		thermistor-on-batctrl;
+	};
+	indicates: NTC resister is internal to battery, 'batctrl' is used
+		for thermal measurement.
+
+	The absence of property 'thermal-on-batctrl' indicates
+	NTC resister is external to battery and  'btemp' signal is used
+	for thermal measurement.
+
+battery-type:
+	This shall be the battery manufacturing technology type,
+	allowed types are:
+		"UNKNOWN" "NiMH" "LION" "LIPO" "LiFe" "NiCd" "LiMn"
+	Example:
+	ab8500_battery: ab8500_battery {
+		stericsson,battery-type = "LIPO";
+	}
+
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/raideng.txt b/Documentation/devicetree/bindings/powerpc/fsl/raideng.txt
new file mode 100644
index 0000000..4ad29b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/powerpc/fsl/raideng.txt
@@ -0,0 +1,81 @@
+* Freescale 85xx RAID Engine nodes
+
+RAID Engine nodes are defined to describe on-chip RAID accelerators.  Each RAID
+Engine should have a separate node.
+
+Supported chips:
+P5020, P5040
+
+Required properties:
+
+- compatible:	Should contain "fsl,raideng-v1.0" as the value
+		This identifies RAID Engine block. 1 in 1.0 represents
+		major number whereas 0 represents minor number. The
+		version matches the hardware IP version.
+- reg:		offset and length of the register set for the device
+- ranges:	standard ranges property specifying the translation
+		between child address space and parent address space
+
+Example:
+	/* P5020 */
+	raideng: raideng@320000 {
+		compatible = "fsl,raideng-v1.0";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg	= <0x320000 0x10000>;
+		ranges	= <0 0x320000 0x10000>;
+	};
+
+
+There must be a sub-node for each job queue present in RAID Engine
+This node must be a sub-node of the main RAID Engine node
+
+- compatible:	Should contain "fsl,raideng-v1.0-job-queue" as the value
+		This identifies the job queue interface
+- reg:		offset and length of the register set for job queue
+- ranges:	standard ranges property specifying the translation
+		between child address space and parent address space
+
+Example:
+	/* P5020 */
+	raideng_jq0@1000 {
+		compatible = "fsl,raideng-v1.0-job-queue";
+		reg	   = <0x1000 0x1000>;
+		ranges	   = <0x0 0x1000 0x1000>;
+	};
+
+
+There must be a sub-node for each job ring present in RAID Engine
+This node must be a sub-node of job queue node
+
+- compatible:	Must contain "fsl,raideng-v1.0-job-ring" as the value
+		This identifies job ring. Should contain either
+		"fsl,raideng-v1.0-hp-ring" or "fsl,raideng-v1.0-lp-ring"
+		depending upon whether ring has high or low priority
+- reg:		offset and length of the register set for job ring
+- interrupts:	interrupt mapping for job ring IRQ
+
+Optional property:
+
+- fsl,liodn:	Specifies the LIODN to be used for Job Ring. This
+		property is normally set by firmware. Value
+		is of 12-bits which is the LIODN number for this JR.
+		This property is used by the IOMMU (PAMU) to distinquish
+		transactions from this JR and than be able to do address
+		translation & protection accordingly.
+
+Example:
+	/* P5020 */
+	raideng_jq0@1000 {
+		compatible = "fsl,raideng-v1.0-job-queue";
+		reg	   = <0x1000 0x1000>;
+		ranges	   = <0x0 0x1000 0x1000>;
+
+		raideng_jr0: jr@0 {
+			compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-hp-ring";
+			reg	   = <0x0 0x400>;
+			interrupts = <139 2 0 0>;
+			interrupt-parent = <&mpic>;
+			fsl,liodn = <0x41>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
new file mode 100644
index 0000000..131e8c1
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
@@ -0,0 +1,23 @@
+TI SOC ECAP based APWM controller
+
+Required properties:
+- compatible: Must be "ti,am33xx-ecap"
+- #pwm-cells: Should be 3. Number of cells being used to specify PWM property.
+  First cell specifies the per-chip index of the PWM to use, the second
+  cell is the period in nanoseconds and bit 0 in the third cell is used to
+  encode the polarity of PWM output. Set bit 0 of the third in PWM specifier
+  to 1 for inverse polarity & set to 0 for normal polarity.
+- reg: physical base address and size of the registers map.
+
+Optional properties:
+- ti,hwmods: Name of the hwmod associated to the ECAP:
+  "ecap<x>", <x> being the 0-based instance number from the HW spec
+
+Example:
+
+ecap0: ecap@0 {
+	compatible = "ti,am33xx-ecap";
+	#pwm-cells = <3>;
+	reg = <0x48300100 0x80>;
+	ti,hwmods = "ecap0";
+};
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
new file mode 100644
index 0000000..4fc7079
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
@@ -0,0 +1,23 @@
+TI SOC EHRPWM based PWM controller
+
+Required properties:
+- compatible : Must be "ti,am33xx-ehrpwm"
+- #pwm-cells: Should be 3. Number of cells being used to specify PWM property.
+  First cell specifies the per-chip index of the PWM to use, the second
+  cell is the period in nanoseconds and bit 0 in the third cell is used to
+  encode the polarity of PWM output. Set bit 0 of the third in PWM specifier
+  to 1 for inverse polarity & set to 0 for normal polarity.
+- reg: physical base address and size of the registers map.
+
+Optional properties:
+- ti,hwmods: Name of the hwmod associated to the EHRPWM:
+  "ehrpwm<x>", <x> being the 0-based instance number from the HW spec
+
+Example:
+
+ehrpwm0: ehrpwm@0 {
+	compatible = "ti,am33xx-ehrpwm";
+	#pwm-cells = <3>;
+	reg = <0x48300200 0x100>;
+	ti,hwmods = "ehrpwm0";
+};
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tipwmss.txt b/Documentation/devicetree/bindings/pwm/pwm-tipwmss.txt
new file mode 100644
index 0000000..f7eae77
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-tipwmss.txt
@@ -0,0 +1,31 @@
+TI SOC based PWM Subsystem
+
+Required properties:
+- compatible: Must be "ti,am33xx-pwmss";
+- reg: physical base address and size of the registers map.
+- address-cells: Specify the number of u32 entries needed in child nodes.
+		  Should set to 1.
+- size-cells: specify number of u32 entries needed to specify child nodes size
+		in reg property. Should set to 1.
+- ranges: describes the address mapping of a memory-mapped bus. Should set to
+	   physical address map of child's base address, physical address within
+	   parent's address  space and length of the address map. For am33xx,
+	   3 set of child register maps present, ECAP register space, EQEP
+	   register space, EHRPWM register space.
+
+Also child nodes should also populated under PWMSS DT node.
+
+Example:
+pwmss0: pwmss@48300000 {
+	compatible = "ti,am33xx-pwmss";
+	reg = <0x48300000 0x10>;
+	ti,hwmods = "epwmss0";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	status = "disabled";
+	ranges = <0x48300100 0x48300100 0x80   /* ECAP */
+		  0x48300180 0x48300180 0x80   /* EQEP */
+		  0x48300200 0x48300200 0x80>; /* EHRPWM */
+
+	/* child nodes go here */
+};
diff --git a/Documentation/devicetree/bindings/pwm/pwm.txt b/Documentation/devicetree/bindings/pwm/pwm.txt
index 73ec962..06e6724 100644
--- a/Documentation/devicetree/bindings/pwm/pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm.txt
@@ -37,10 +37,21 @@ device:
 		pwm-names = "backlight";
 	};
 
+Note that in the example above, specifying the "pwm-names" is redundant
+because the name "backlight" would be used as fallback anyway.
+
 pwm-specifier typically encodes the chip-relative PWM number and the PWM
-period in nanoseconds. Note that in the example above, specifying the
-"pwm-names" is redundant because the name "backlight" would be used as
-fallback anyway.
+period in nanoseconds.
+
+Optionally, the pwm-specifier can encode a number of flags in a third cell:
+- bit 0: PWM signal polarity (0: normal polarity, 1: inverse polarity)
+
+Example with optional PWM specifier for inverse polarity
+
+	bl: backlight {
+		pwms = <&pwm 0 5000000 1>;
+		pwm-names = "backlight";
+	};
 
 2) PWM controller nodes
 -----------------------
diff --git a/Documentation/devicetree/bindings/pwm/spear-pwm.txt b/Documentation/devicetree/bindings/pwm/spear-pwm.txt
new file mode 100644
index 0000000..3ac779d
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/spear-pwm.txt
@@ -0,0 +1,18 @@
+== ST SPEAr SoC PWM controller ==
+
+Required properties:
+- compatible: should be one of:
+  - "st,spear320-pwm"
+  - "st,spear1340-pwm"
+- reg: physical base address and length of the controller's registers
+- #pwm-cells: number of cells used to specify PWM which is fixed to 2 on
+  SPEAr. The first cell specifies the per-chip index of the PWM to use and
+  the second cell is the period in nanoseconds.
+
+Example:
+
+        pwm: pwm@a8000000 {
+            compatible ="st,spear320-pwm";
+            reg = <0xa8000000 0x1000>;
+            #pwm-cells = <2>;
+        };
diff --git a/Documentation/devicetree/bindings/pwm/ti,twl-pwm.txt b/Documentation/devicetree/bindings/pwm/ti,twl-pwm.txt
new file mode 100644
index 0000000..2943ee5
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/ti,twl-pwm.txt
@@ -0,0 +1,17 @@
+Texas Instruments TWL series PWM drivers
+
+Supported PWMs:
+On TWL4030 series: PWM1 and PWM2
+On TWL6030 series: PWM0 and PWM1
+
+Required properties:
+- compatible: "ti,twl4030-pwm" or "ti,twl6030-pwm"
+- #pwm-cells: should be 2.  The first cell specifies the per-chip index
+  of the PWM to use and the second cell is the period in nanoseconds.
+
+Example:
+
+twl_pwm: pwm {
+	compatible = "ti,twl6030-pwm";
+	#pwm-cells = <2>;
+};
diff --git a/Documentation/devicetree/bindings/pwm/ti,twl-pwmled.txt b/Documentation/devicetree/bindings/pwm/ti,twl-pwmled.txt
new file mode 100644
index 0000000..cb64f3a
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/ti,twl-pwmled.txt
@@ -0,0 +1,17 @@
+Texas Instruments TWL series PWM drivers connected to LED terminals
+
+Supported PWMs:
+On TWL4030 series: PWMA and PWMB (connected to LEDA and LEDB terminals)
+On TWL6030 series: LED PWM (mainly used as charging indicator LED)
+
+Required properties:
+- compatible: "ti,twl4030-pwmled" or "ti,twl6030-pwmled"
+- #pwm-cells: should be 2.  The first cell specifies the per-chip index
+  of the PWM to use and the second cell is the period in nanoseconds.
+
+Example:
+
+twl_pwmled: pwmled {
+	compatible = "ti,twl6030-pwmled";
+	#pwm-cells = <2>;
+};
diff --git a/Documentation/devicetree/bindings/pwm/vt8500-pwm.txt b/Documentation/devicetree/bindings/pwm/vt8500-pwm.txt
new file mode 100644
index 0000000..bcc6367
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/vt8500-pwm.txt
@@ -0,0 +1,17 @@
+VIA/Wondermedia VT8500/WM8xxx series SoC PWM controller
+
+Required properties:
+- compatible: should be "via,vt8500-pwm"
+- reg: physical base address and length of the controller's registers
+- #pwm-cells: should be 2.  The first cell specifies the per-chip index
+  of the PWM to use and the second cell is the period in nanoseconds.
+- clocks: phandle to the PWM source clock
+
+Example:
+
+pwm1: pwm@d8220000 {
+	#pwm-cells = <2>;
+	compatible = "via,vt8500-pwm";
+	reg = <0xd8220000 0x1000>;
+	clocks = <&clkpwm>;
+};
diff --git a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt
new file mode 100644
index 0000000..63c6598
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt
@@ -0,0 +1,37 @@
+GPIO controlled regulators
+
+Required properties:
+- compatible		: Must be "regulator-gpio".
+- states		: Selection of available voltages and GPIO configs.
+                          if there are no states, then use a fixed regulator
+
+Optional properties:
+- enable-gpio		: GPIO to use to enable/disable the regulator.
+- gpios			: GPIO group used to control voltage.
+- startup-delay-us	: Startup time in microseconds.
+- enable-active-high	: Polarity of GPIO is active high (default is low).
+
+Any property defined as part of the core regulator binding defined in
+regulator.txt can also be used.
+
+Example:
+
+	mmciv: gpio-regulator {
+		compatible = "regulator-gpio";
+
+		regulator-name = "mmci-gpio-supply";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <2600000>;
+		regulator-boot-on;
+
+		enable-gpio = <&gpio0 23 0x4>;
+		gpios = <&gpio0 24 0x4
+			 &gpio0 25 0x4>;
+		states = <1800000 0x3
+			  2200000 0x2
+			  2600000 0x1
+			  2900000 0x0>;
+
+		startup-delay-us = <100000>;
+		enable-active-high;
+	};
diff --git a/Documentation/devicetree/bindings/regulator/max8925-regulator.txt b/Documentation/devicetree/bindings/regulator/max8925-regulator.txt
new file mode 100644
index 0000000..0057695
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/max8925-regulator.txt
@@ -0,0 +1,40 @@
+Max8925 Voltage regulators
+
+Required nodes:
+-nodes:
+  - SDV1 for SDV SDV1
+  - SDV2 for SDV SDV2
+  - SDV3 for SDV SDV3
+  - LDO1 for LDO LDO1
+  - LDO2 for LDO LDO2
+  - LDO3 for LDO LDO3
+  - LDO4 for LDO LDO4
+  - LDO5 for LDO LDO5
+  - LDO6 for LDO LDO6
+  - LDO7 for LDO LDO7
+  - LDO8 for LDO LDO8
+  - LDO9 for LDO LDO9
+  - LDO10 for LDO LDO10
+  - LDO11 for LDO LDO11
+  - LDO12 for LDO LDO12
+  - LDO13 for LDO LDO13
+  - LDO14 for LDO LDO14
+  - LDO15 for LDO LDO15
+  - LDO16 for LDO LDO16
+  - LDO17 for LDO LDO17
+  - LDO18 for LDO LDO18
+  - LDO19 for LDO LDO19
+  - LDO20 for LDO LDO20
+
+Optional properties:
+- Any optional property defined in bindings/regulator/regulator.txt
+
+Example:
+
+	SDV1 {
+		regulator-min-microvolt = <637500>;
+		regulator-max-microvolt = <1425000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
diff --git a/Documentation/devicetree/bindings/regulator/max8997-regulator.txt b/Documentation/devicetree/bindings/regulator/max8997-regulator.txt
new file mode 100644
index 0000000..9fd69a1
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/max8997-regulator.txt
@@ -0,0 +1,146 @@
+* Maxim MAX8997 Voltage and Current Regulator
+
+The Maxim MAX8997 is a multi-function device which includes volatage and
+current regulators, rtc, charger controller and other sub-blocks. It is
+interfaced to the host controller using a i2c interface. Each sub-block is
+addressed by the host system using different i2c slave address. This document
+describes the bindings for 'pmic' sub-block of max8997.
+
+Required properties:
+- compatible: Should be "maxim,max8997-pmic".
+- reg: Specifies the i2c slave address of the pmic block. It should be 0x66.
+
+- max8997,pmic-buck1-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
+  units for buck1 when changing voltage using gpio dvs. Refer to [1] below
+  for additional information.
+
+- max8997,pmic-buck2-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
+  units for buck2 when changing voltage using gpio dvs. Refer to [1] below
+  for additional information.
+
+- max8997,pmic-buck5-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
+  units for buck5 when changing voltage using gpio dvs. Refer to [1] below
+  for additional information.
+
+[1] If none of the 'max8997,pmic-buck[1/2/5]-uses-gpio-dvs' optional
+    property is specified, the 'max8997,pmic-buck[1/2/5]-dvs-voltage'
+    property should specify atleast one voltage level (which would be a
+    safe operating voltage).
+
+    If either of the 'max8997,pmic-buck[1/2/5]-uses-gpio-dvs' optional
+    property is specified, then all the eigth voltage values for the
+    'max8997,pmic-buck[1/2/5]-dvs-voltage' should be specified.
+
+Optional properties:
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+  the interrupts from max8997 are delivered to.
+- interrupts: Interrupt specifiers for two interrupt sources.
+  - First interrupt specifier is for 'irq1' interrupt.
+  - Second interrupt specifier is for 'alert' interrupt.
+- max8997,pmic-buck1-uses-gpio-dvs: 'buck1' can be controlled by gpio dvs.
+- max8997,pmic-buck2-uses-gpio-dvs: 'buck2' can be controlled by gpio dvs.
+- max8997,pmic-buck5-uses-gpio-dvs: 'buck5' can be controlled by gpio dvs.
+
+Additional properties required if either of the optional properties are used:
+- max8997,pmic-ignore-gpiodvs-side-effect: When GPIO-DVS mode is used for
+  multiple bucks, changing the voltage value of one of the bucks may affect
+  that of another buck, which is the side effect of the change (set_voltage).
+  Use this property to ignore such side effects and change the voltage.
+
+- max8997,pmic-buck125-default-dvs-idx: Default voltage setting selected from
+  the possible 8 options selectable by the dvs gpios. The value of this
+  property should be between 0 and 7. If not specified or if out of range, the
+  default value of this property is set to 0.
+
+- max8997,pmic-buck125-dvs-gpios: GPIO specifiers for three host gpio's used
+  for dvs. The format of the gpio specifier depends in the gpio controller.
+
+Regulators: The regulators of max8997 that have to be instantiated should be
+included in a sub-node named 'regulators'. Regulator nodes included in this
+sub-node should be of the format as listed below.
+
+	regulator_name {
+		standard regulator bindings here
+	};
+
+The following are the names of the regulators that the max8997 pmic block
+supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
+as per the datasheet of max8997.
+
+	- LDOn
+		  - valid values for n are 1 to 18 and 21
+		  - Example: LDO0, LD01, LDO2, LDO21
+	- BUCKn
+		  - valid values for n are 1 to 7.
+		  - Example: BUCK1, BUCK2, BUCK3, BUCK7
+
+	- ENVICHG: Battery Charging Current Monitor Output. This is a fixed
+		   voltage type regulator
+
+	- ESAFEOUT1: (ldo19)
+	- ESAFEOUT2: (ld020)
+
+	- CHARGER_CV: main battery charger voltage control
+	- CHARGER: main battery charger current control
+	- CHARGER_TOPOFF: end of charge current threshold level
+
+The bindings inside the regulator nodes use the standard regulator bindings
+which are documented elsewhere.
+
+Example:
+
+	max8997_pmic@66 {
+		compatible = "maxim,max8997-pmic";
+		interrupt-parent = <&wakeup_eint>;
+		reg = <0x66>;
+		interrupts = <4 0>, <3 0>;
+
+		max8997,pmic-buck1-uses-gpio-dvs;
+		max8997,pmic-buck2-uses-gpio-dvs;
+		max8997,pmic-buck5-uses-gpio-dvs;
+
+		max8997,pmic-ignore-gpiodvs-side-effect;
+		max8997,pmic-buck125-default-dvs-idx = <0>;
+
+		max8997,pmic-buck125-dvs-gpios = <&gpx0 0 1 0 0>, /* SET1 */
+						 <&gpx0 1 1 0 0>, /* SET2 */
+						 <&gpx0 2 1 0 0>; /* SET3 */
+
+		max8997,pmic-buck1-dvs-voltage = <1350000>, <1300000>,
+						 <1250000>, <1200000>,
+						 <1150000>, <1100000>,
+						 <1000000>, <950000>;
+
+		max8997,pmic-buck2-dvs-voltage = <1100000>, <1100000>,
+						 <1100000>, <1100000>,
+						 <1000000>, <1000000>,
+						 <1000000>, <1000000>;
+
+		max8997,pmic-buck5-dvs-voltage = <1200000>, <1200000>,
+						 <1200000>, <1200000>,
+						 <1200000>, <1200000>,
+						 <1200000>, <1200000>;
+
+		regulators {
+			ldo1_reg: LDO1 {
+				regulator-name = "VDD_ABB_3.3V";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			ldo2_reg: LDO2 {
+				regulator-name = "VDD_ALIVE_1.1V";
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-always-on;
+			};
+
+			buck1_reg: BUCK1 {
+				regulator-name = "VDD_ARM_1.2V";
+				regulator-min-microvolt = <950000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/regulator/tps65217.txt b/Documentation/devicetree/bindings/regulator/tps65217.txt
index d316fb8..4f05d20 100644
--- a/Documentation/devicetree/bindings/regulator/tps65217.txt
+++ b/Documentation/devicetree/bindings/regulator/tps65217.txt
@@ -11,6 +11,9 @@ Required properties:
   using the standard binding for regulators found at
   Documentation/devicetree/bindings/regulator/regulator.txt.
 
+Optional properties:
+- ti,pmic-shutdown-controller: Telling the PMIC to shutdown on PWR_EN toggle.
+
   The valid names for regulators are:
   tps65217: dcdc1, dcdc2, dcdc3, ldo1, ldo2, ldo3 and ldo4
 
@@ -20,6 +23,7 @@ Example:
 
 	tps: tps@24 {
 		compatible = "ti,tps65217";
+		ti,pmic-shutdown-controller;
 
 		regulators {
 			dcdc1_reg: dcdc1 {
diff --git a/Documentation/devicetree/bindings/regulator/vexpress.txt b/Documentation/devicetree/bindings/regulator/vexpress.txt
new file mode 100644
index 0000000..d775f72
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/vexpress.txt
@@ -0,0 +1,32 @@
+Versatile Express voltage regulators
+------------------------------------
+
+Requires node properties:
+- "compatible" value: "arm,vexpress-volt"
+- "arm,vexpress-sysreg,func" when controlled via vexpress-sysreg
+  (see Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
+  for more details)
+
+Required regulator properties:
+- "regulator-name"
+- "regulator-always-on"
+
+Optional regulator properties:
+- "regulator-min-microvolt"
+- "regulator-max-microvolt"
+
+See Documentation/devicetree/bindings/regulator/regulator.txt
+for more details about the regulator properties.
+
+When no "regulator-[min|max]-microvolt" properties are defined,
+the device is treated as fixed (or rather "read-only") regulator.
+
+Example:
+	volt@0 {
+		compatible = "arm,vexpress-volt";
+		arm,vexpress-sysreg,func = <2 0>;
+		regulator-name = "Cores";
+		regulator-min-microvolt = <800000>;
+		regulator-max-microvolt = <1050000>;
+		regulator-always-on;
+	};
diff --git a/Documentation/devicetree/bindings/rtc/imxdi-rtc.txt b/Documentation/devicetree/bindings/rtc/imxdi-rtc.txt
new file mode 100644
index 0000000..c9d80d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/imxdi-rtc.txt
@@ -0,0 +1,17 @@
+* i.MX25 Real Time Clock controller
+
+This binding supports the following chips: i.MX25, i.MX53
+
+Required properties:
+- compatible: should be: "fsl,imx25-rtc"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- interrupts: rtc alarm interrupt
+
+Example:
+
+rtc@80056000 {
+	compatible = "fsl,imx53-rtc", "fsl,imx25-rtc";
+	reg = <0x80056000 2000>;
+	interrupts = <29>;
+};
diff --git a/Documentation/devicetree/bindings/rtc/nvidia,tegra20-rtc.txt b/Documentation/devicetree/bindings/rtc/nvidia,tegra20-rtc.txt
new file mode 100644
index 0000000..93f45e9
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/nvidia,tegra20-rtc.txt
@@ -0,0 +1,19 @@
+NVIDIA Tegra20 real-time clock
+
+The Tegra RTC maintains seconds and milliseconds counters, and five alarm
+registers. The alarms and other interrupts may wake the system from low-power
+state.
+
+Required properties:
+
+- compatible : should be "nvidia,tegra20-rtc".
+- reg : Specifies base physical address and size of the registers.
+- interrupts : A single interrupt specifier.
+
+Example:
+
+timer {
+	compatible = "nvidia,tegra20-rtc";
+	reg = <0x7000e000 0x100>;
+	interrupts = <0 2 0x04>;
+};
diff --git a/Documentation/devicetree/bindings/rtc/rtc-omap.txt b/Documentation/devicetree/bindings/rtc/rtc-omap.txt
new file mode 100644
index 0000000..b47aa41
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-omap.txt
@@ -0,0 +1,17 @@
+TI Real Time Clock
+
+Required properties:
+- compatible: "ti,da830-rtc"
+- reg: Address range of rtc register set
+- interrupts: rtc timer, alarm interrupts in order
+- interrupt-parent: phandle for the interrupt controller
+
+Example:
+
+rtc@1c23000 {
+	compatible = "ti,da830-rtc";
+	reg = <0x23000 0x1000>;
+	interrupts = <19
+		      19>;
+	interrupt-parent = <&intc>;
+};
diff --git a/Documentation/devicetree/bindings/sound/ak4104.txt b/Documentation/devicetree/bindings/sound/ak4104.txt
new file mode 100644
index 0000000..b902ee3
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/ak4104.txt
@@ -0,0 +1,22 @@
+AK4104 S/PDIF transmitter
+
+This device supports SPI mode only.
+
+Required properties:
+
+  - compatible : "asahi-kasei,ak4104"
+
+  - reg : The chip select number on the SPI bus
+
+Optional properties:
+
+  - reset-gpio : a GPIO spec for the reset pin. If specified, it will be
+		 deasserted before communication to the device starts.
+
+Example:
+
+spdif: ak4104@0 {
+	compatible = "asahi-kasei,ak4104";
+	reg = <0>;
+	spi-max-frequency = <5000000>;
+};
diff --git a/Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt b/Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt
new file mode 100644
index 0000000..9c5a994
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt
@@ -0,0 +1,26 @@
+* Atmel at91sam9g20ek wm8731 audio complex
+
+Required properties:
+  - compatible: "atmel,at91sam9g20ek-wm8731-audio"
+  - atmel,model: The user-visible name of this sound complex.
+  - atmel,audio-routing: A list of the connections between audio components.
+  - atmel,ssc-controller: The phandle of the SSC controller
+  - atmel,audio-codec: The phandle of the WM8731 audio codec
+Optional properties:
+  - pinctrl-names, pinctrl-0: Please refer to pinctrl-bindings.txt
+
+Example:
+sound {
+	compatible = "atmel,at91sam9g20ek-wm8731-audio";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pck0_as_mck>;
+
+	atmel,model = "wm8731 @ AT91SAMG20EK";
+
+	atmel,audio-routing =
+		"Ext Spk", "LHPOUT",
+		"Int MIC", "MICIN";
+
+	atmel,ssc-controller = <&ssc0>;
+	atmel,audio-codec = <&wm8731>;
+};
diff --git a/Documentation/devicetree/bindings/sound/cs4271.txt b/Documentation/devicetree/bindings/sound/cs4271.txt
index c81b5fd..a850fb9 100644
--- a/Documentation/devicetree/bindings/sound/cs4271.txt
+++ b/Documentation/devicetree/bindings/sound/cs4271.txt
@@ -18,6 +18,8 @@ Optional properties:
 
  - reset-gpio: 	a GPIO spec to define which pin is connected to the chip's
 		!RESET pin
+ - cirrus,amuteb-eq-bmutec:	When given, the Codec's AMUTEB=BMUTEC flag
+				is enabled.
 
 Examples:
 
diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra20-sflash.txt b/Documentation/devicetree/bindings/spi/nvidia,tegra20-sflash.txt
new file mode 100644
index 0000000..8cf24f6
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/nvidia,tegra20-sflash.txt
@@ -0,0 +1,26 @@
+NVIDIA Tegra20 SFLASH controller.
+
+Required properties:
+- compatible : should be "nvidia,tegra20-sflash".
+- reg: Should contain SFLASH registers location and length.
+- interrupts: Should contain SFLASH interrupts.
+- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
+  request selector for this SFLASH controller.
+
+Recommended properties:
+- spi-max-frequency: Definition as per
+                     Documentation/devicetree/bindings/spi/spi-bus.txt
+
+Example:
+
+spi@7000d600 {
+	compatible = "nvidia,tegra20-sflash";
+	reg = <0x7000c380 0x80>;
+	interrupts = <0 39 0x04>;
+	nvidia,dma-request-selector = <&apbdma 16>;
+	spi-max-frequency = <25000000>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "disabled";
+};
+
diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra20-slink.txt b/Documentation/devicetree/bindings/spi/nvidia,tegra20-slink.txt
new file mode 100644
index 0000000..f5b1ad1
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/nvidia,tegra20-slink.txt
@@ -0,0 +1,26 @@
+NVIDIA Tegra20/Tegra30 SLINK controller.
+
+Required properties:
+- compatible : should be "nvidia,tegra20-slink", "nvidia,tegra30-slink".
+- reg: Should contain SLINK registers location and length.
+- interrupts: Should contain SLINK interrupts.
+- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
+  request selector for this SLINK controller.
+
+Recommended properties:
+- spi-max-frequency: Definition as per
+                     Documentation/devicetree/bindings/spi/spi-bus.txt
+
+Example:
+
+slink@7000d600 {
+	compatible = "nvidia,tegra20-slink";
+	reg = <0x7000d600 0x200>;
+	interrupts = <0 82 0x04>;
+	nvidia,dma-request-selector = <&apbdma 16>;
+	spi-max-frequency = <25000000>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "disabled";
+};
+
diff --git a/Documentation/devicetree/bindings/spi/omap-spi.txt b/Documentation/devicetree/bindings/spi/omap-spi.txt
index 81df374..938809c 100644
--- a/Documentation/devicetree/bindings/spi/omap-spi.txt
+++ b/Documentation/devicetree/bindings/spi/omap-spi.txt
@@ -6,7 +6,9 @@ Required properties:
   - "ti,omap4-spi" for OMAP4+.
 - ti,spi-num-cs : Number of chipselect supported  by the instance.
 - ti,hwmods: Name of the hwmod associated to the McSPI
-
+- ti,pindir-d0-out-d1-in: Select the D0 pin as output and D1 as
+			  input. The default is D0 as input and
+			  D1 as output.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/spi/spi-bus.txt b/Documentation/devicetree/bindings/spi/spi-bus.txt
index d2c33d0..77a8b0d 100644
--- a/Documentation/devicetree/bindings/spi/spi-bus.txt
+++ b/Documentation/devicetree/bindings/spi/spi-bus.txt
@@ -12,6 +12,7 @@ The SPI master node requires the following properties:
 - #size-cells     - should be zero.
 - compatible      - name of SPI bus controller following generic names
     		recommended practice.
+- cs-gpios	  - (optional) gpios chip select.
 No other properties are required in the SPI bus node.  It is assumed
 that a driver for an SPI bus device will understand that it is an SPI bus.
 However, the binding does not attempt to define the specific method for
@@ -24,6 +25,22 @@ support describing the chip select layout.
 Optional property:
 - num-cs : total number of chipselects
 
+If cs-gpios is used the number of chip select will automatically increased
+with max(cs-gpios > hw cs)
+
+So if for example the controller has 2 CS lines, and the cs-gpios
+property looks like this:
+
+cs-gpios = <&gpio1 0 0> <0> <&gpio1 1 0> <&gpio1 2 0>;
+
+Then it should be configured so that num_chipselect = 4 with the
+following mapping:
+
+cs0 : &gpio1 0 0
+cs1 : native
+cs2 : &gpio1 1 0
+cs3 : &gpio1 2 0
+
 SPI slave nodes must be children of the SPI master node and can
 contain the following properties.
 - reg             - (required) chip select address of device.
@@ -37,6 +54,9 @@ contain the following properties.
 - spi-cs-high     - (optional) Empty property indicating device requires
     		chip select active high
 
+If a gpio chipselect is used for the SPI slave the gpio number will be passed
+via the cs_gpio
+
 SPI example for an MPC5200 SPI bus:
 	spi@f00 {
 		#address-cells = <1>;
diff --git a/Documentation/devicetree/bindings/thermal/db8500-thermal.txt b/Documentation/devicetree/bindings/thermal/db8500-thermal.txt
new file mode 100644
index 0000000..2e1c06f
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/db8500-thermal.txt
@@ -0,0 +1,44 @@
+* ST-Ericsson DB8500 Thermal
+
+** Thermal node properties:
+
+- compatible : "stericsson,db8500-thermal";
+- reg : address range of the thermal sensor registers;
+- interrupts : interrupts generated from PRCMU;
+- interrupt-names : "IRQ_HOTMON_LOW" and "IRQ_HOTMON_HIGH";
+- num-trips : number of total trip points, this is required, set it 0 if none,
+  if greater than 0, the following properties must be defined;
+- tripN-temp : temperature of trip point N, should be in ascending order;
+- tripN-type : type of trip point N, should be one of "active" "passive" "hot"
+  "critical";
+- tripN-cdev-num : number of the cooling devices which can be bound to trip
+  point N, this is required if trip point N is defined, set it 0 if none,
+  otherwise the following cooling device names must be defined;
+- tripN-cdev-nameM : name of the No. M cooling device of trip point N;
+
+Usually the num-trips and tripN-*** are separated in board related dts files.
+
+Example:
+thermal@801573c0 {
+	compatible = "stericsson,db8500-thermal";
+	reg = <0x801573c0 0x40>;
+	interrupts = <21 0x4>, <22 0x4>;
+	interrupt-names = "IRQ_HOTMON_LOW", "IRQ_HOTMON_HIGH";
+
+	num-trips = <3>;
+
+	trip0-temp = <75000>;
+	trip0-type = "active";
+	trip0-cdev-num = <1>;
+	trip0-cdev-name0 = "thermal-cpufreq-0";
+
+	trip1-temp = <80000>;
+	trip1-type = "active";
+	trip1-cdev-num = <2>;
+	trip1-cdev-name0 = "thermal-cpufreq-0";
+	trip1-cdev-name1 = "thermal-fan";
+
+	trip2-temp = <85000>;
+	trip2-type = "critical";
+	trip2-cdev-num = <0>;
+}
diff --git a/Documentation/devicetree/bindings/timer/allwinner,sunxi-timer.txt b/Documentation/devicetree/bindings/timer/allwinner,sunxi-timer.txt
new file mode 100644
index 0000000..0c7b64e
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/allwinner,sunxi-timer.txt
@@ -0,0 +1,17 @@
+Allwinner A1X SoCs Timer Controller
+
+Required properties:
+
+- compatible : should be "allwinner,sunxi-timer"
+- reg : Specifies base physical address and size of the registers.
+- interrupts : The interrupt of the first timer
+- clocks: phandle to the source clock (usually a 24 MHz fixed clock)
+
+Example:
+
+timer {
+	compatible = "allwinner,sunxi-timer";
+	reg = <0x01c20c00 0x400>;
+	interrupts = <22>;
+	clocks = <&osc>;
+};
diff --git a/Documentation/devicetree/bindings/timer/nvidia,tegra20-timer.txt b/Documentation/devicetree/bindings/timer/nvidia,tegra20-timer.txt
new file mode 100644
index 0000000..e019fdc
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/nvidia,tegra20-timer.txt
@@ -0,0 +1,21 @@
+NVIDIA Tegra20 timer
+
+The Tegra20 timer provides four 29-bit timer channels and a single 32-bit free
+running counter. The first two channels may also trigger a watchdog reset.
+
+Required properties:
+
+- compatible : should be "nvidia,tegra20-timer".
+- reg : Specifies base physical address and size of the registers.
+- interrupts : A list of 4 interrupts; one per timer channel.
+
+Example:
+
+timer {
+	compatible = "nvidia,tegra20-timer";
+	reg = <0x60005000 0x60>;
+	interrupts = <0 0 0x04
+			0 1 0x04
+			0 41 0x04
+			0 42 0x04>;
+};
diff --git a/Documentation/devicetree/bindings/timer/nvidia,tegra30-timer.txt b/Documentation/devicetree/bindings/timer/nvidia,tegra30-timer.txt
new file mode 100644
index 0000000..906109d
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/nvidia,tegra30-timer.txt
@@ -0,0 +1,23 @@
+NVIDIA Tegra30 timer
+
+The Tegra30 timer provides ten 29-bit timer channels, a single 32-bit free
+running counter, and 5 watchdog modules. The first two channels may also
+trigger a legacy watchdog reset.
+
+Required properties:
+
+- compatible : should be "nvidia,tegra30-timer", "nvidia,tegra20-timer".
+- reg : Specifies base physical address and size of the registers.
+- interrupts : A list of 6 interrupts; one per each of timer channels 1
+    through 5, and one for the shared interrupt for the remaining channels.
+
+timer {
+	compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
+	reg = <0x60005000 0x400>;
+	interrupts = <0 0 0x04
+		      0 1 0x04
+		      0 41 0x04
+		      0 42 0x04
+		      0 121 0x04
+		      0 122 0x04>;
+};
diff --git a/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt b/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt
index 2ee903f..273a8d5 100644
--- a/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt
+++ b/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt
@@ -6,11 +6,19 @@ Required properties:
 - reg : Address and length of the register set for the device
 - interrupts : Should contain the auart interrupt numbers
 
+Optional properties:
+- fsl,auart-dma-channel : The DMA channels, the first is for RX, the other
+		is for TX. If you add this property, it also means that you
+		will enable the DMA support for the auart.
+		Note: due to the hardware bug in imx23(see errata : 2836),
+		only the imx28 can enable the DMA support for the auart.
+
 Example:
 auart0: serial@8006a000 {
 	compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 	reg = <0x8006a000 0x2000>;
 	interrupts = <112 70 71>;
+	fsl,auart-dma-channel = <8 9>;
 };
 
 Note: Each auart port should have an alias correctly numbered in "aliases"
diff --git a/Documentation/devicetree/bindings/tty/serial/of-serial.txt b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
index ba385f2..1e1145c 100644
--- a/Documentation/devicetree/bindings/tty/serial/of-serial.txt
+++ b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
@@ -14,7 +14,10 @@ Required properties:
 	- "serial" if the port type is unknown.
 - reg : offset and length of the register set for the device.
 - interrupts : should contain uart interrupt.
-- clock-frequency : the input clock frequency for the UART.
+- clock-frequency : the input clock frequency for the UART
+	 or
+  clocks phandle to refer to the clk used as per Documentation/devicetree
+  /bindings/clock/clock-bindings.txt
 
 Optional properties:
 - current-speed : the current active speed of the UART.
diff --git a/Documentation/devicetree/bindings/usb/am33xx-usb.txt b/Documentation/devicetree/bindings/usb/am33xx-usb.txt
index ca8fa56..ea840f7 100644
--- a/Documentation/devicetree/bindings/usb/am33xx-usb.txt
+++ b/Documentation/devicetree/bindings/usb/am33xx-usb.txt
@@ -1,14 +1,35 @@
 AM33XX MUSB GLUE
  - compatible : Should be "ti,musb-am33xx"
+ - reg : offset and length of register sets, first usbss, then for musb instances
+ - interrupts : usbss, musb instance interrupts in order
  - ti,hwmods : must be "usb_otg_hs"
  - 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
+ - num-eps : Specifies the number of endpoints. This is also a
    MUSB configuration-specific setting. Should be set to "16"
- - ram_bits : Specifies the ram address size. Should be set to "12"
- - port0_mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
+ - ram-bits : Specifies the ram address size. Should be set to "12"
+ - port0-mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
    represents PERIPHERAL.
- - port1_mode : Should be "1" to represent HOST. "3" signifies OTG and "2"
+ - port1-mode : Should be "1" to represent HOST. "3" signifies OTG and "2"
    represents PERIPHERAL.
  - power : Should be "250". This signifies the controller can supply upto
    500mA when operating in host mode.
+
+Example:
+
+usb@47400000  {
+	compatible = "ti,musb-am33xx";
+	reg = <0x47400000 0x1000	/* usbss */
+	       0x47401000 0x800		/* musb instance 0 */
+	       0x47401800 0x800>;	/* musb instance 1 */
+	interrupts = <17		/* usbss */
+		      18		/* musb instance 0 */
+		      19>;		/* musb instance 1 */
+	multipoint = <1>;
+	num-eps = <16>;
+	ram-bits = <12>;
+	port0-mode = <3>;
+	port1-mode = <3>;
+	power = <250>;
+	ti,hwmods = "usb_otg_hs";
+};
diff --git a/Documentation/devicetree/bindings/usb/ehci-orion.txt b/Documentation/devicetree/bindings/usb/ehci-orion.txt
new file mode 100644
index 0000000..6bc09ec
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ehci-orion.txt
@@ -0,0 +1,15 @@
+* EHCI controller, Orion Marvell variants
+
+Required properties:
+- compatible: must be "marvell,orion-ehci"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- interrupts: The EHCI interrupt
+
+Example:
+
+	ehci@50000 {
+		compatible = "marvell,orion-ehci";
+		reg = <0x50000 0x1000>;
+		interrupts = <19>;
+	};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 9de2b9f..42820be 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -5,6 +5,7 @@ using them to avoid name-space collisions.
 
 ad	Avionic Design GmbH
 adi	Analog Devices, Inc.
+ak	Asahi Kasei Corp.
 amcc	Applied Micro Circuits Corporation (APM, formally AMCC)
 apm	Applied Micro Circuits Corporation (APM)
 arm	ARM Ltd.
@@ -34,6 +35,7 @@ national	National Semiconductor
 nintendo	Nintendo
 nvidia	NVIDIA
 nxp	NXP Semiconductors
+onnn	ON Semiconductor Corp.
 picochip	Picochip Ltd
 powervr	Imagination Technologies
 qcom	Qualcomm, Inc.
@@ -45,10 +47,12 @@ schindler	Schindler
 sil	Silicon Image
 simtek
 sirf	SiRF Technology, Inc.
+snps 	Synopsys, Inc.
 st	STMicroelectronics
 stericsson	ST-Ericsson
 ti	Texas Instruments
 via	VIA Technologies, Inc.
 wlf	Wolfson Microelectronics
 wm	Wondermedia Technologies, Inc.
+winbond Winbond Electronics corp.
 xlnx	Xilinx
diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
new file mode 100644
index 0000000..3d0060c
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
@@ -0,0 +1,24 @@
+* Solomon SSD1307 Framebuffer Driver
+
+Required properties:
+  - compatible: Should be "solomon,ssd1307fb-<bus>". The only supported bus for
+    now is i2c.
+  - reg: Should contain address of the controller on the I2C bus. Most likely
+         0x3c or 0x3d
+  - pwm: Should contain the pwm to use according to the OF device tree PWM
+         specification [0]
+  - reset-gpios: Should contain the GPIO used to reset the OLED display
+
+Optional properties:
+  - reset-active-low: Is the reset gpio is active on physical low?
+
+[0]: Documentation/devicetree/bindings/pwm/pwm.txt
+
+Examples:
+ssd1307: oled@3c {
+        compatible = "solomon,ssd1307fb-i2c";
+        reg = <0x3c>;
+        pwms = <&pwm 4 3000>;
+        reset-gpios = <&gpio2 7>;
+        reset-active-low;
+};
diff --git a/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt b/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt
new file mode 100644
index 0000000..2957ebb
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt
@@ -0,0 +1,15 @@
+* Atmel Watchdog Timers
+
+** at91sam9-wdt
+
+Required properties:
+- compatible: must be "atmel,at91sam9260-wdt".
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+Example:
+
+	watchdog@fffffd40 {
+		compatible = "atmel,at91sam9260-wdt";
+		reg = <0xfffffd40 0x10>;
+	};
diff --git a/Documentation/devicetree/bindings/watchdog/brcm,bcm2835-pm-wdog.txt b/Documentation/devicetree/bindings/watchdog/brcm,bcm2835-pm-wdog.txt
new file mode 100644
index 0000000..d209366
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/brcm,bcm2835-pm-wdog.txt
@@ -0,0 +1,13 @@
+BCM2835 Watchdog timer
+
+Required properties:
+
+- compatible : should be "brcm,bcm2835-pm-wdt"
+- reg : Specifies base physical address and size of the registers.
+
+Example:
+
+watchdog {
+	compatible = "brcm,bcm2835-pm-wdt";
+	reg = <0x7e100000 0x28>;
+};
diff --git a/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt b/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt
new file mode 100644
index 0000000..0b27177
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt
@@ -0,0 +1,13 @@
+Allwinner sunXi Watchdog timer
+
+Required properties:
+
+- compatible : should be "allwinner,sunxi-wdt"
+- reg : Specifies base physical address and size of the registers.
+
+Example:
+
+wdt: watchdog@01c20c90 {
+	compatible = "allwinner,sunxi-wdt";
+	reg = <0x01c20c90 0x10>;
+};
diff --git a/Documentation/devicetree/usage-model.txt b/Documentation/devicetree/usage-model.txt
index dca90fe..ef9d06c 100644
--- a/Documentation/devicetree/usage-model.txt
+++ b/Documentation/devicetree/usage-model.txt
@@ -347,7 +347,7 @@ later), which will happily live at the base of the Linux /sys/devices
 tree.  Therefore, if a DT node is at the root of the tree, then it
 really probably is best registered as a platform_device.
 
-Linux board support code calls of_platform_populate(NULL, NULL, NULL)
+Linux board support code calls of_platform_populate(NULL, NULL, NULL, NULL)
 to kick off discovery of devices at the root of the tree.  The
 parameters are all NULL because when starting from the root of the
 tree, there is no need to provide a starting node (the first NULL), a
diff --git a/Documentation/dma-buf-sharing.txt b/Documentation/dma-buf-sharing.txt
index ad86fb8..0188903 100644
--- a/Documentation/dma-buf-sharing.txt
+++ b/Documentation/dma-buf-sharing.txt
@@ -376,7 +376,7 @@ Being able to mmap an export dma-buf buffer object has 2 main use-cases:
    leaving the cpu domain and flushing caches at fault time. Note that all the
    dma_buf files share the same anon inode, hence the exporter needs to replace
    the dma_buf file stored in vma->vm_file with it's own if pte shootdown is
-   requred. This is because the kernel uses the underlying inode's address_space
+   required. This is because the kernel uses the underlying inode's address_space
    for vma tracking (and hence pte tracking at shootdown time with
    unmap_mapping_range).
 
@@ -388,7 +388,7 @@ Being able to mmap an export dma-buf buffer object has 2 main use-cases:
    Exporters that shoot down mappings (for any reasons) shall not do any
    synchronization at fault time with outstanding device operations.
    Synchronization is an orthogonal issue to sharing the backing storage of a
-   buffer and hence should not be handled by dma-buf itself. This is explictly
+   buffer and hence should not be handled by dma-buf itself. This is explicitly
    mentioned here because many people seem to want something like this, but if
    different exporters handle this differently, buffer sharing can fail in
    interesting ways depending upong the exporter (if userspace starts depending
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index 74c25c8..b89a739 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -181,7 +181,6 @@ modversions.h*
 nconf
 ncscope.*
 offset.h
-offsets.h
 oui.c*
 page-types
 parse.c
diff --git a/Documentation/fault-injection/notifier-error-inject.txt b/Documentation/fault-injection/notifier-error-inject.txt
index c83526c..09adabe 100644
--- a/Documentation/fault-injection/notifier-error-inject.txt
+++ b/Documentation/fault-injection/notifier-error-inject.txt
@@ -1,7 +1,7 @@
 Notifier error injection
 ========================
 
-Notifier error injection provides the ability to inject artifical errors to
+Notifier error injection provides the ability to inject artificial errors to
 specified notifier chain callbacks. It is useful to test the error handling of
 notifier call chain failures which is rarely executed.  There are kernel
 modules that can be used to test the following notifiers.
@@ -14,7 +14,7 @@ modules that can be used to test the following notifiers.
 CPU notifier error injection module
 -----------------------------------
 This feature can be used to test the error handling of the CPU notifiers by
-injecting artifical errors to CPU notifier chain callbacks.
+injecting artificial errors to CPU notifier chain callbacks.
 
 If the notifier call chain should be failed with some events notified, write
 the error code to debugfs interface
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
index 8c624a1..ce5fd46 100644
--- a/Documentation/filesystems/00-INDEX
+++ b/Documentation/filesystems/00-INDEX
@@ -48,6 +48,8 @@ ext4.txt
 	- info, mount options and specifications for the Ext4 filesystem.
 files.txt
 	- info on file management in the Linux kernel.
+f2fs.txt
+	- info and mount options for the F2FS filesystem.
 fuse.txt
 	- info on the Filesystem in User SpacE including mount options.
 gfs2.txt
diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt
new file mode 100644
index 0000000..dee3960
--- /dev/null
+++ b/Documentation/filesystems/f2fs.txt
@@ -0,0 +1,421 @@
+================================================================================
+WHAT IS Flash-Friendly File System (F2FS)?
+================================================================================
+
+NAND flash memory-based storage devices, such as SSD, eMMC, and SD cards, have
+been equipped on a variety systems ranging from mobile to server systems. Since
+they are known to have different characteristics from the conventional rotating
+disks, a file system, an upper layer to the storage device, should adapt to the
+changes from the sketch in the design level.
+
+F2FS is a file system exploiting NAND flash memory-based storage devices, which
+is based on Log-structured File System (LFS). The design has been focused on
+addressing the fundamental issues in LFS, which are snowball effect of wandering
+tree and high cleaning overhead.
+
+Since a NAND flash memory-based storage device shows different characteristic
+according to its internal geometry or flash memory management scheme, namely FTL,
+F2FS and its tools support various parameters not only for configuring on-disk
+layout, but also for selecting allocation and cleaning algorithms.
+
+The file system formatting tool, "mkfs.f2fs", is available from the following
+git tree:
+>> git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git
+
+For reporting bugs and sending patches, please use the following mailing list:
+>> linux-f2fs-devel@lists.sourceforge.net
+
+================================================================================
+BACKGROUND AND DESIGN ISSUES
+================================================================================
+
+Log-structured File System (LFS)
+--------------------------------
+"A log-structured file system writes all modifications to disk sequentially in
+a log-like structure, thereby speeding up  both file writing and crash recovery.
+The log is the only structure on disk; it contains indexing information so that
+files can be read back from the log efficiently. In order to maintain large free
+areas on disk for fast writing, we divide  the log into segments and use a
+segment cleaner to compress the live information from heavily fragmented
+segments." from Rosenblum, M. and Ousterhout, J. K., 1992, "The design and
+implementation of a log-structured file system", ACM Trans. Computer Systems
+10, 1, 26–52.
+
+Wandering Tree Problem
+----------------------
+In LFS, when a file data is updated and written to the end of log, its direct
+pointer block is updated due to the changed location. Then the indirect pointer
+block is also updated due to the direct pointer block update. In this manner,
+the upper index structures such as inode, inode map, and checkpoint block are
+also updated recursively. This problem is called as wandering tree problem [1],
+and in order to enhance the performance, it should eliminate or relax the update
+propagation as much as possible.
+
+[1] Bityutskiy, A. 2005. JFFS3 design issues. http://www.linux-mtd.infradead.org/
+
+Cleaning Overhead
+-----------------
+Since LFS is based on out-of-place writes, it produces so many obsolete blocks
+scattered across the whole storage. In order to serve new empty log space, it
+needs to reclaim these obsolete blocks seamlessly to users. This job is called
+as a cleaning process.
+
+The process consists of three operations as follows.
+1. A victim segment is selected through referencing segment usage table.
+2. It loads parent index structures of all the data in the victim identified by
+   segment summary blocks.
+3. It checks the cross-reference between the data and its parent index structure.
+4. It moves valid data selectively.
+
+This cleaning job may cause unexpected long delays, so the most important goal
+is to hide the latencies to users. And also definitely, it should reduce the
+amount of valid data to be moved, and move them quickly as well.
+
+================================================================================
+KEY FEATURES
+================================================================================
+
+Flash Awareness
+---------------
+- Enlarge the random write area for better performance, but provide the high
+  spatial locality
+- Align FS data structures to the operational units in FTL as best efforts
+
+Wandering Tree Problem
+----------------------
+- Use a term, “node”, that represents inodes as well as various pointer blocks
+- Introduce Node Address Table (NAT) containing the locations of all the “node”
+  blocks; this will cut off the update propagation.
+
+Cleaning Overhead
+-----------------
+- Support a background cleaning process
+- Support greedy and cost-benefit algorithms for victim selection policies
+- Support multi-head logs for static/dynamic hot and cold data separation
+- Introduce adaptive logging for efficient block allocation
+
+================================================================================
+MOUNT OPTIONS
+================================================================================
+
+background_gc_off      Turn off cleaning operations, namely garbage collection,
+		       triggered in background when I/O subsystem is idle.
+disable_roll_forward   Disable the roll-forward recovery routine
+discard                Issue discard/TRIM commands when a segment is cleaned.
+no_heap                Disable heap-style segment allocation which finds free
+                       segments for data from the beginning of main area, while
+		       for node from the end of main area.
+nouser_xattr           Disable Extended User Attributes. Note: xattr is enabled
+                       by default if CONFIG_F2FS_FS_XATTR is selected.
+noacl                  Disable POSIX Access Control List. Note: acl is enabled
+                       by default if CONFIG_F2FS_FS_POSIX_ACL is selected.
+active_logs=%u         Support configuring the number of active logs. In the
+                       current design, f2fs supports only 2, 4, and 6 logs.
+                       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.
+
+================================================================================
+DEBUGFS ENTRIES
+================================================================================
+
+/sys/kernel/debug/f2fs/ contains information about all the partitions mounted as
+f2fs. Each file shows the whole f2fs information.
+
+/sys/kernel/debug/f2fs/status includes:
+ - major file system information managed by f2fs currently
+ - average SIT information about whole segments
+ - current memory footprint consumed by f2fs.
+
+================================================================================
+USAGE
+================================================================================
+
+1. Download userland tools and compile them.
+
+2. Skip, if f2fs was compiled statically inside kernel.
+   Otherwise, insert the f2fs.ko module.
+ # insmod f2fs.ko
+
+3. Create a directory trying to mount
+ # mkdir /mnt/f2fs
+
+4. Format the block device, and then mount as f2fs
+ # mkfs.f2fs -l label /dev/block_device
+ # mount -t f2fs /dev/block_device /mnt/f2fs
+
+Format options
+--------------
+-l [label]   : Give a volume label, up to 256 unicode name.
+-a [0 or 1]  : Split start location of each area for heap-based allocation.
+               1 is set by default, which performs this.
+-o [int]     : Set overprovision ratio in percent over volume size.
+               5 is set by default.
+-s [int]     : Set the number of segments per section.
+               1 is set by default.
+-z [int]     : Set the number of sections per zone.
+               1 is set by default.
+-e [str]     : Set basic extension list. e.g. "mp3,gif,mov"
+
+================================================================================
+DESIGN
+================================================================================
+
+On-disk Layout
+--------------
+
+F2FS divides the whole volume into a number of segments, each of which is fixed
+to 2MB in size. A section is composed of consecutive segments, and a zone
+consists of a set of sections. By default, section and zone sizes are set to one
+segment size identically, but users can easily modify the sizes by mkfs.
+
+F2FS splits the entire volume into six areas, and all the areas except superblock
+consists of multiple segments as described below.
+
+                                            align with the zone size <-|
+                 |-> align with the segment size
+     _________________________________________________________________________
+    |            |            |    Node     |   Segment   |   Segment  |      |
+    | Superblock | Checkpoint |   Address   |    Info.    |   Summary  | Main |
+    |    (SB)    |   (CP)     | Table (NAT) | Table (SIT) | Area (SSA) |      |
+    |____________|_____2______|______N______|______N______|______N_____|__N___|
+                                                                       .      .
+                                                             .                .
+                                                 .                            .
+                                    ._________________________________________.
+                                    |_Segment_|_..._|_Segment_|_..._|_Segment_|
+                                    .           .
+                                    ._________._________
+                                    |_section_|__...__|_
+                                    .            .
+		                    .________.
+	                            |__zone__|
+
+- Superblock (SB)
+ : It is located at the beginning of the partition, and there exist two copies
+   to avoid file system crash. It contains basic partition information and some
+   default parameters of f2fs.
+
+- Checkpoint (CP)
+ : It contains file system information, bitmaps for valid NAT/SIT sets, orphan
+   inode lists, and summary entries of current active segments.
+
+- Node Address Table (NAT)
+ : It is composed of a block address table for all the node blocks stored in
+   Main area.
+
+- Segment Information Table (SIT)
+ : It contains segment information such as valid block count and bitmap for the
+   validity of all the blocks.
+
+- Segment Summary Area (SSA)
+ : It contains summary entries which contains the owner information of all the
+   data and node blocks stored in Main area.
+
+- Main Area
+ : It contains file and directory data including their indices.
+
+In order to avoid misalignment between file system and flash-based storage, F2FS
+aligns the start block address of CP with the segment size. Also, it aligns the
+start block address of Main area with the zone size by reserving some segments
+in SSA area.
+
+Reference the following survey for additional technical details.
+https://wiki.linaro.org/WorkingGroups/Kernel/Projects/FlashCardSurvey
+
+File System Metadata Structure
+------------------------------
+
+F2FS adopts the checkpointing scheme to maintain file system consistency. At
+mount time, F2FS first tries to find the last valid checkpoint data by scanning
+CP area. In order to reduce the scanning time, F2FS uses only two copies of CP.
+One of them always indicates the last valid data, which is called as shadow copy
+mechanism. In addition to CP, NAT and SIT also adopt the shadow copy mechanism.
+
+For file system consistency, each CP points to which NAT and SIT copies are
+valid, as shown as below.
+
+  +--------+----------+---------+
+  |   CP   |    NAT   |   SIT   |
+  +--------+----------+---------+
+  .         .          .          .
+  .            .              .              .
+  .               .                 .                 .
+  +-------+-------+--------+--------+--------+--------+
+  | CP #0 | CP #1 | NAT #0 | NAT #1 | SIT #0 | SIT #1 |
+  +-------+-------+--------+--------+--------+--------+
+     |             ^                          ^
+     |             |                          |
+     `----------------------------------------'
+
+Index Structure
+---------------
+
+The key data structure to manage the data locations is a "node". Similar to
+traditional file structures, F2FS has three types of node: inode, direct node,
+indirect node. F2FS assigns 4KB to an inode block which contains 929 data block
+indices, two direct node pointers, two indirect node pointers, and one double
+indirect node pointer as described below. One direct node block contains 1018
+data blocks, and one indirect node block contains also 1018 node blocks. Thus,
+one inode block (i.e., a file) covers:
+
+  4KB * (923 + 2 * 1018 + 2 * 1018 * 1018 + 1018 * 1018 * 1018) := 3.94TB.
+
+   Inode block (4KB)
+     |- data (923)
+     |- direct node (2)
+     |          `- data (1018)
+     |- indirect node (2)
+     |            `- direct node (1018)
+     |                       `- data (1018)
+     `- double indirect node (1)
+                         `- indirect node (1018)
+			              `- direct node (1018)
+	                                         `- data (1018)
+
+Note that, all the node blocks are mapped by NAT which means the location of
+each node is translated by the NAT table. In the consideration of the wandering
+tree problem, F2FS is able to cut off the propagation of node updates caused by
+leaf data writes.
+
+Directory Structure
+-------------------
+
+A directory entry occupies 11 bytes, which consists of the following attributes.
+
+- hash		hash value of the file name
+- ino		inode number
+- len		the length of file name
+- type		file type such as directory, symlink, etc
+
+A dentry block consists of 214 dentry slots and file names. Therein a bitmap is
+used to represent whether each dentry is valid or not. A dentry block occupies
+4KB with the following composition.
+
+  Dentry Block(4 K) = bitmap (27 bytes) + reserved (3 bytes) +
+	              dentries(11 * 214 bytes) + file name (8 * 214 bytes)
+
+                         [Bucket]
+             +--------------------------------+
+             |dentry block 1 | dentry block 2 |
+             +--------------------------------+
+             .               .
+       .                             .
+  .       [Dentry Block Structure: 4KB]       .
+  +--------+----------+----------+------------+
+  | bitmap | reserved | dentries | file names |
+  +--------+----------+----------+------------+
+  [Dentry Block: 4KB] .   .
+		 .               .
+            .                          .
+            +------+------+-----+------+
+            | hash | ino  | len | type |
+            +------+------+-----+------+
+            [Dentry Structure: 11 bytes]
+
+F2FS implements multi-level hash tables for directory structure. Each level has
+a hash table with dedicated number of hash buckets as shown below. Note that
+"A(2B)" means a bucket includes 2 data blocks.
+
+----------------------
+A : bucket
+B : block
+N : MAX_DIR_HASH_DEPTH
+----------------------
+
+level #0   | A(2B)
+           |
+level #1   | A(2B) - A(2B)
+           |
+level #2   | A(2B) - A(2B) - A(2B) - A(2B)
+     .     |   .       .       .       .
+level #N/2 | A(2B) - A(2B) - A(2B) - A(2B) - A(2B) - ... - A(2B)
+     .     |   .       .       .       .
+level #N   | A(4B) - A(4B) - A(4B) - A(4B) - A(4B) - ... - A(4B)
+
+The number of blocks and buckets are determined by,
+
+                            ,- 2, if n < MAX_DIR_HASH_DEPTH / 2,
+  # of blocks in level #n = |
+                            `- 4, Otherwise
+
+                             ,- 2^n, if n < MAX_DIR_HASH_DEPTH / 2,
+  # of buckets in level #n = |
+                             `- 2^((MAX_DIR_HASH_DEPTH / 2) - 1), Otherwise
+
+When F2FS finds a file name in a directory, at first a hash value of the file
+name is calculated. Then, F2FS scans the hash table in level #0 to find the
+dentry consisting of the file name and its inode number. If not found, F2FS
+scans the next hash table in level #1. In this way, F2FS scans hash tables in
+each levels incrementally from 1 to N. In each levels F2FS needs to scan only
+one bucket determined by the following equation, which shows O(log(# of files))
+complexity.
+
+  bucket number to scan in level #n = (hash value) % (# of buckets in level #n)
+
+In the case of file creation, F2FS finds empty consecutive slots that cover the
+file name. F2FS searches the empty slots in the hash tables of whole levels from
+1 to N in the same way as the lookup operation.
+
+The following figure shows an example of two cases holding children.
+       --------------> Dir <--------------
+       |                                 |
+    child                             child
+
+    child - child                     [hole] - child
+
+    child - child - child             [hole] - [hole] - child
+
+   Case 1:                           Case 2:
+   Number of children = 6,           Number of children = 3,
+   File size = 7                     File size = 7
+
+Default Block Allocation
+------------------------
+
+At runtime, F2FS manages six active logs inside "Main" area: Hot/Warm/Cold node
+and Hot/Warm/Cold data.
+
+- Hot node	contains direct node blocks of directories.
+- Warm node	contains direct node blocks except hot node blocks.
+- Cold node	contains indirect node blocks
+- Hot data	contains dentry blocks
+- Warm data	contains data blocks except hot and cold data blocks
+- Cold data	contains multimedia data or migrated data blocks
+
+LFS has two schemes for free space management: threaded log and copy-and-compac-
+tion. The copy-and-compaction scheme which is known as cleaning, is well-suited
+for devices showing very good sequential write performance, since free segments
+are served all the time for writing new data. However, it suffers from cleaning
+overhead under high utilization. Contrarily, the threaded log scheme suffers
+from random writes, but no cleaning process is needed. F2FS adopts a hybrid
+scheme where the copy-and-compaction scheme is adopted by default, but the
+policy is dynamically changed to the threaded log scheme according to the file
+system status.
+
+In order to align F2FS with underlying flash-based storage, F2FS allocates a
+segment in a unit of section. F2FS expects that the section size would be the
+same as the unit size of garbage collection in FTL. Furthermore, with respect
+to the mapping granularity in FTL, F2FS allocates each section of the active
+logs from different zones as much as possible, since FTL can write the data in
+the active logs into one allocation unit according to its mapping granularity.
+
+Cleaning process
+----------------
+
+F2FS does cleaning both on demand and in the background. On-demand cleaning is
+triggered when there are not enough free segments to serve VFS calls. Background
+cleaner is operated by a kernel thread, and triggers the cleaning job when the
+system is idle.
+
+F2FS supports two victim selection policies: greedy and cost-benefit algorithms.
+In the greedy algorithm, F2FS selects a victim segment having the smallest number
+of valid blocks. In the cost-benefit algorithm, F2FS selects a victim segment
+according to the segment age and the number of valid blocks in order to address
+log block thrashing problem in the greedy algorithm. F2FS adopts the greedy
+algorithm for on-demand cleaner, while background cleaner adopts cost-benefit
+algorithm.
+
+In order to identify whether the data in the victim segment are valid or not,
+F2FS manages a bitmap. Each bit represents the validity of a block, and the
+bitmap is composed of a bit stream covering whole blocks in main area.
diff --git a/Documentation/filesystems/nfs/nfs41-server.txt b/Documentation/filesystems/nfs/nfs41-server.txt
index 092fad9..01c2db7 100644
--- a/Documentation/filesystems/nfs/nfs41-server.txt
+++ b/Documentation/filesystems/nfs/nfs41-server.txt
@@ -39,21 +39,10 @@ interoperability problems with future clients.  Known issues:
 	  from a linux client are possible, but we aren't really
 	  conformant with the spec (for example, we don't use kerberos
 	  on the backchannel correctly).
-	- Incomplete backchannel support: incomplete backchannel gss
-	  support and no support for BACKCHANNEL_CTL mean that
-	  callbacks (hence delegations and layouts) may not be
-	  available and clients confused by the incomplete
-	  implementation may fail.
 	- We do not support SSV, which provides security for shared
 	  client-server state (thus preventing unauthorized tampering
 	  with locks and opens, for example).  It is mandatory for
 	  servers to support this, though no clients use it yet.
-	- Mandatory operations which we do not support, such as
-	  DESTROY_CLIENTID, are not currently used by clients, but will be
-	  (and the spec recommends their uses in common cases), and
-	  clients should not be expected to know how to recover from the
-	  case where they are not supported.  This will eventually cause
-	  interoperability failures.
 
 In addition, some limitations are inherited from the current NFSv4
 implementation:
@@ -89,7 +78,7 @@ Operations
    |                      | MNI        | or OPT)      |                |
    +----------------------+------------+--------------+----------------+
    | ACCESS               | REQ        |              | Section 18.1   |
-NS | BACKCHANNEL_CTL      | REQ        |              | Section 18.33  |
+I  | BACKCHANNEL_CTL      | REQ        |              | Section 18.33  |
 I  | BIND_CONN_TO_SESSION | REQ        |              | Section 18.34  |
    | CLOSE                | REQ        |              | Section 18.2   |
    | COMMIT               | REQ        |              | Section 18.3   |
@@ -99,7 +88,7 @@ NS*| DELEGPURGE           | OPT        | FDELG (REQ)  | Section 18.5   |
    | DELEGRETURN          | OPT        | FDELG,       | Section 18.6   |
    |                      |            | DDELG, pNFS  |                |
    |                      |            | (REQ)        |                |
-NS | DESTROY_CLIENTID     | REQ        |              | Section 18.50  |
+I  | DESTROY_CLIENTID     | REQ        |              | Section 18.50  |
 I  | DESTROY_SESSION      | REQ        |              | Section 18.37  |
 I  | EXCHANGE_ID          | REQ        |              | Section 18.35  |
 I  | FREE_STATEID         | REQ        |              | Section 18.38  |
@@ -192,7 +181,6 @@ EXCHANGE_ID:
 
 CREATE_SESSION:
 * backchannel attributes are ignored
-* backchannel security parameters are ignored
 
 SEQUENCE:
 * no support for dynamic slot table renegotiation (optional)
@@ -202,7 +190,7 @@ Nonstandard compound limitations:
   ca_maxrequestsize request and a ca_maxresponsesize reply, so we may
   fail to live up to the promise we made in CREATE_SESSION fore channel
   negotiation.
-* No more than one IO operation (read, write, readdir) allowed per
-  compound.
+* No more than one read-like operation allowed per compound; encoding
+  replies that cross page boundaries (except for read data) not handled.
 
 See also http://wiki.linux-nfs.org/wiki/index.php/Server_4.0_and_4.1_issues.
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 3844d21..bcc27c9 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -41,6 +41,7 @@ Table of Contents
   3.5	/proc/<pid>/mountinfo - Information about mounts
   3.6	/proc/<pid>/comm  & /proc/<pid>/task/<tid>/comm
   3.7   /proc/<pid>/task/<tid>/children - Information about task children
+  3.8   /proc/<pid>/fdinfo/<fd> - Information about opened file
 
   4	Configuring procfs
   4.1	Mount options
@@ -142,7 +143,7 @@ Table 1-1: Process specific entries in /proc
  pagemap	Page table
  stack		Report full stack trace, enable via CONFIG_STACKTRACE
  smaps		a extension based on maps, showing the memory consumption of
-		each mapping
+		each mapping and flags associated with it
 ..............................................................................
 
 For example, to get the status information of a process, all you have to do is
@@ -181,6 +182,7 @@ read the file /proc/PID/status:
   CapPrm: 0000000000000000
   CapEff: 0000000000000000
   CapBnd: ffffffffffffffff
+  Seccomp:        0
   voluntary_ctxt_switches:        0
   nonvoluntary_ctxt_switches:     1
 
@@ -237,6 +239,7 @@ Table 1-2: Contents of the status files (as of 2.6.30-rc7)
  CapPrm                      bitmap of permitted capabilities
  CapEff                      bitmap of effective capabilities
  CapBnd                      bitmap of capabilities bounding set
+ Seccomp                     seccomp mode, like prctl(PR_GET_SECCOMP, ...)
  Cpus_allowed                mask of CPUs on which this process may run
  Cpus_allowed_list           Same as previous, but in "list format"
  Mems_allowed                mask of memory nodes allowed to this process
@@ -415,8 +418,9 @@ Swap:                  0 kB
 KernelPageSize:        4 kB
 MMUPageSize:           4 kB
 Locked:              374 kB
+VmFlags: rd ex mr mw me de
 
-The first of these lines shows the same information as is displayed for the
+the first of these lines shows the same information as is displayed for the
 mapping in /proc/PID/maps.  The remaining lines show the size of the mapping
 (size), the amount of the mapping that is currently resident in RAM (RSS), the
 process' proportional share of this mapping (PSS), the number of clean and
@@ -430,6 +434,41 @@ and a page is modified, the file page is replaced by a private anonymous copy.
 "Swap" shows how much would-be-anonymous memory is also used, but out on
 swap.
 
+"VmFlags" field deserves a separate description. This member represents the kernel
+flags associated with the particular virtual memory area in two letter encoded
+manner. The codes are the following:
+    rd  - readable
+    wr  - writeable
+    ex  - executable
+    sh  - shared
+    mr  - may read
+    mw  - may write
+    me  - may execute
+    ms  - may share
+    gd  - stack segment growns down
+    pf  - pure PFN range
+    dw  - disabled write to the mapped file
+    lo  - pages are locked in memory
+    io  - memory mapped I/O area
+    sr  - sequential read advise provided
+    rr  - random read advise provided
+    dc  - do not copy area on fork
+    de  - do not expand area on remapping
+    ac  - area is accountable
+    nr  - swap space is not reserved for the area
+    ht  - area uses huge tlb pages
+    nl  - non-linear mapping
+    ar  - architecture specific flag
+    dd  - do not include area into core dump
+    mm  - mixed map area
+    hg  - huge page advise flag
+    nh  - no-huge page advise flag
+    mg  - mergable advise flag
+
+Note that there is no guarantee that every flag and associated mnemonic will
+be present in all further kernel releases. Things get changed, the flags may
+be vanished or the reverse -- new added.
+
 This file is only present if the CONFIG_MMU kernel configuration option is
 enabled.
 
@@ -1595,6 +1634,87 @@ pids, so one need to either stop or freeze processes being inspected
 if precise results are needed.
 
 
+3.7	/proc/<pid>/fdinfo/<fd> - Information about opened file
+---------------------------------------------------------------
+This file provides information associated with an opened file. The regular
+files have at least two fields -- 'pos' and 'flags'. The 'pos' represents
+the current offset of the opened file in decimal form [see lseek(2) for
+details] and 'flags' denotes the octal O_xxx mask the file has been
+created with [see open(2) for details].
+
+A typical output is
+
+	pos:	0
+	flags:	0100002
+
+The files such as eventfd, fsnotify, signalfd, epoll among the regular pos/flags
+pair provide additional information particular to the objects they represent.
+
+	Eventfd files
+	~~~~~~~~~~~~~
+	pos:	0
+	flags:	04002
+	eventfd-count:	5a
+
+	where 'eventfd-count' is hex value of a counter.
+
+	Signalfd files
+	~~~~~~~~~~~~~~
+	pos:	0
+	flags:	04002
+	sigmask:	0000000000000200
+
+	where 'sigmask' is hex value of the signal mask associated
+	with a file.
+
+	Epoll files
+	~~~~~~~~~~~
+	pos:	0
+	flags:	02
+	tfd:        5 events:       1d data: ffffffffffffffff
+
+	where 'tfd' is a target file descriptor number in decimal form,
+	'events' is events mask being watched and the 'data' is data
+	associated with a target [see epoll(7) for more details].
+
+	Fsnotify files
+	~~~~~~~~~~~~~~
+	For inotify files the format is the following
+
+	pos:	0
+	flags:	02000000
+	inotify wd:3 ino:9e7e sdev:800013 mask:800afce ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:7e9e0000640d1b6d
+
+	where 'wd' is a watch descriptor in decimal form, ie a target file
+	descriptor number, 'ino' and 'sdev' are inode and device where the
+	target file resides and the 'mask' is the mask of events, all in hex
+	form [see inotify(7) for more details].
+
+	If the kernel was built with exportfs support, the path to the target
+	file is encoded as a file handle.  The file handle is provided by three
+	fields 'fhandle-bytes', 'fhandle-type' and 'f_handle', all in hex
+	format.
+
+	If the kernel is built without exportfs support the file handle won't be
+	printed out.
+
+	For fanotify files the format is
+
+	pos:	0
+	flags:	02
+	fanotify ino:2 sdev:800013 mask:1 ignored_mask:40000000 fhandle-bytes:8 fhandle-type:1 f_handle:0200000000000000
+
+	or
+
+	pos:	0
+	flags:	02
+	fanotify mnt_id:13 mask:1 ignored_mask:40000000
+
+	where 'ino', 'sdev' are target inode and device, 'mnt_id' is the mount
+	point identifier, 'mask' is the events mask used and 'ignored_mask' is
+	the mask of events which are to be ignored. All in hex format.
+
+
 ------------------------------------------------------------------------------
 Configuring procfs
 ------------------------------------------------------------------------------
diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt
index de1e6c4..d230dd9 100644
--- a/Documentation/filesystems/vfat.txt
+++ b/Documentation/filesystems/vfat.txt
@@ -111,6 +111,15 @@ tz=UTC        -- Interpret timestamps as UTC rather than local time.
                  useful when mounting devices (like digital cameras)
                  that are set to UTC in order to avoid the pitfalls of
                  local time.
+time_offset=minutes
+	      -- Set offset for conversion of timestamps from local time
+		 used by FAT to UTC. I.e. <minutes> minutes will be subtracted
+		 from each timestamp to convert it to UTC used internally by
+		 Linux. This is useful when time zone set in sys_tz is
+		 not the time zone used by the filesystem. Note that this
+		 option still does not provide correct time stamps in all
+		 cases in presence of DST - time stamps in a different DST
+		 setting will be off by one hour.
 
 showexec      -- If set, the execute permission bits of the file will be
 		 allowed only if the extension part of the name is .EXE,
diff --git a/Documentation/filesystems/xfs.txt b/Documentation/filesystems/xfs.txt
index 3fc0c31..3e4b3dd 100644
--- a/Documentation/filesystems/xfs.txt
+++ b/Documentation/filesystems/xfs.txt
@@ -43,7 +43,7 @@ When mounting an XFS filesystem, the following options are accepted.
 	Issue command to let the block device reclaim space freed by the
 	filesystem.  This is useful for SSD devices, thinly provisioned
 	LUNs and virtual machine images, but may have a performance
-	impact.  This option is incompatible with the nodelaylog option.
+	impact.
 
   dmapi
 	Enable the DMAPI (Data Management API) event callouts.
@@ -72,8 +72,15 @@ When mounting an XFS filesystem, the following options are accepted.
 	Indicates that XFS is allowed to create inodes at any location
 	in the filesystem, including those which will result in inode
 	numbers occupying more than 32 bits of significance.  This is
-	provided for backwards compatibility, but causes problems for
-	backup applications that cannot handle large inode numbers.
+	the default allocation option. Applications which do not handle
+	inode numbers bigger than 32 bits, should use inode32 option.
+
+  inode32
+	Indicates that XFS is limited to create inodes at locations which
+	will not result in inode numbers with more than 32 bits of
+	significance. This is provided for backwards compatibility, since
+	64 bits inode numbers might cause problems for some applications
+	that cannot handle large inode numbers.
 
   largeio/nolargeio
 	If "nolargeio" is specified, the optimal I/O reported in
diff --git a/Documentation/firmware_class/README b/Documentation/firmware_class/README
index 815b711..43fada9 100644
--- a/Documentation/firmware_class/README
+++ b/Documentation/firmware_class/README
@@ -22,12 +22,17 @@
 	- calls request_firmware(&fw_entry, $FIRMWARE, device)
 	- kernel searchs the fimware image with name $FIRMWARE directly
 	in the below search path of root filesystem:
+		User customized search path by module parameter 'path'[1]
 		"/lib/firmware/updates/" UTS_RELEASE,
 		"/lib/firmware/updates",
 		"/lib/firmware/" UTS_RELEASE,
 		"/lib/firmware"
 	- If found, goto 7), else goto 2)
 
+	[1], the 'path' is a string parameter which length should be less
+	than 256, user should pass 'firmware_class.path=$CUSTOMIZED_PATH'
+	if firmware_class is built in kernel(the general situation)
+
  2), userspace:
  	- /sys/class/firmware/xxx/{loading,data} appear.
 	- hotplug gets called with a firmware identifier in $FIRMWARE
@@ -114,3 +119,10 @@
    on the setup, so I think that the choice on what firmware to make
    persistent should be left to userspace.
 
+ about firmware cache:
+ --------------------
+ After firmware cache mechanism is introduced during system sleep,
+ request_firmware can be called safely inside device's suspend and
+ resume callback, and callers need't cache the firmware by
+ themselves any more for dealing with firmware loss during system
+ resume.
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
index e08a883..77a1d11 100644
--- a/Documentation/gpio.txt
+++ b/Documentation/gpio.txt
@@ -439,6 +439,48 @@ slower clock delays the rising edge of SCK, and the I2C master adjusts its
 signaling rate accordingly.
 
 
+GPIO controllers and the pinctrl subsystem
+------------------------------------------
+
+A GPIO controller on a SOC might be tightly coupled with the pinctrl
+subsystem, in the sense that the pins can be used by other functions
+together with an optional gpio feature. We have already covered the
+case where e.g. a GPIO controller need to reserve a pin or set the
+direction of a pin by calling any of:
+
+pinctrl_request_gpio()
+pinctrl_free_gpio()
+pinctrl_gpio_direction_input()
+pinctrl_gpio_direction_output()
+
+But how does the pin control subsystem cross-correlate the GPIO
+numbers (which are a global business) to a certain pin on a certain
+pin controller?
+
+This is done by registering "ranges" of pins, which are essentially
+cross-reference tables. These are described in
+Documentation/pinctrl.txt
+
+While the pin allocation is totally managed by the pinctrl subsystem,
+gpio (under gpiolib) is still maintained by gpio drivers. It may happen
+that different pin ranges in a SoC is managed by different gpio drivers.
+
+This makes it logical to let gpio drivers announce their pin ranges to
+the pin ctrl subsystem before it will call 'pinctrl_request_gpio' in order
+to request the corresponding pin to be prepared by the pinctrl subsystem
+before any gpio usage.
+
+For this, the gpio controller can register its pin range with pinctrl
+subsystem. There are two ways of doing it currently: with or without DT.
+
+For with DT support refer to Documentation/devicetree/bindings/gpio/gpio.txt.
+
+For non-DT support, user can call gpiochip_add_pin_range() with appropriate
+parameters to register a range of gpio pins with a pinctrl driver. For this
+exact name string of pinctrl device has to be passed as one of the
+argument to this routine.
+
+
 What do these conventions omit?
 ===============================
 One of the biggest things these conventions omit is pin multiplexing, since
diff --git a/Documentation/hid/uhid.txt b/Documentation/hid/uhid.txt
index 4627c42..3c74121 100644
--- a/Documentation/hid/uhid.txt
+++ b/Documentation/hid/uhid.txt
@@ -108,7 +108,7 @@ the request was handled successfully.
   UHID_FEATURE_ANSWER:
   If you receive a UHID_FEATURE request you must answer with this request. You
   must copy the "id" field from the request into the answer. Set the "err" field
-  to 0 if no error occured or to EIO if an I/O error occurred.
+  to 0 if no error occurred or to EIO if an I/O error occurred.
   If "err" is 0 then you should fill the buffer of the answer with the results
   of the feature request and set "size" correspondingly.
 
diff --git a/Documentation/hwmon/ads7828 b/Documentation/hwmon/ads7828
index 2bbebe6..f6e263e 100644
--- a/Documentation/hwmon/ads7828
+++ b/Documentation/hwmon/ads7828
@@ -4,29 +4,47 @@ Kernel driver ads7828
 Supported chips:
   * Texas Instruments/Burr-Brown ADS7828
     Prefix: 'ads7828'
-    Addresses scanned: I2C 0x48, 0x49, 0x4a, 0x4b
-    Datasheet: Publicly available at the Texas Instruments website :
+    Datasheet: Publicly available at the Texas Instruments website:
                http://focus.ti.com/lit/ds/symlink/ads7828.pdf
 
+  * Texas Instruments ADS7830
+    Prefix: 'ads7830'
+    Datasheet: Publicly available at the Texas Instruments website:
+               http://focus.ti.com/lit/ds/symlink/ads7830.pdf
+
 Authors:
         Steve Hardy <shardy@redhat.com>
+        Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+        Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
+
+Platform data
+-------------
+
+The ads7828 driver accepts an optional ads7828_platform_data structure (defined
+in include/linux/platform_data/ads7828.h). The structure fields are:
 
-Module Parameters
------------------
+* diff_input: (bool) Differential operation
+  set to true for differential mode, false for default single ended mode.
 
-* se_input: bool (default Y)
-  Single ended operation - set to N for differential mode
-* int_vref: bool (default Y)
-  Operate with the internal 2.5V reference - set to N for external reference
-* vref_mv: int (default 2500)
-  If using an external reference, set this to the reference voltage in mV
+* ext_vref: (bool) External reference
+  set to true if it operates with an external reference, false for default
+  internal reference.
+
+* vref_mv: (unsigned int) Voltage reference
+  if using an external reference, set this to the reference voltage in mV,
+  otherwise it will default to the internal value (2500mV). This value will be
+  bounded with limits accepted by the chip, described in the datasheet.
+
+ If no structure is provided, the configuration defaults to single ended
+ operation and internal voltage reference (2.5V).
 
 Description
 -----------
 
-This driver implements support for the Texas Instruments ADS7828.
+This driver implements support for the Texas Instruments ADS7828 and ADS7830.
 
-This device is a 12-bit 8-channel A-D converter.
+The ADS7828 device is a 12-bit 8-channel A/D converter, while the ADS7830 does
+8-bit sampling.
 
 It can operate in single ended mode (8 +ve inputs) or in differential mode,
 where 4 differential pairs can be measured.
@@ -34,3 +52,7 @@ where 4 differential pairs can be measured.
 The chip also has the facility to use an external voltage reference.  This
 may be required if your hardware supplies the ADS7828 from a 5V supply, see
 the datasheet for more details.
+
+There is no reliable way to identify this chip, so the driver will not scan
+some addresses to try to auto-detect it. That means that you will have to
+statically declare the device in the platform support code.
diff --git a/Documentation/hwmon/coretemp b/Documentation/hwmon/coretemp
index f17256f..3374c08 100644
--- a/Documentation/hwmon/coretemp
+++ b/Documentation/hwmon/coretemp
@@ -98,8 +98,10 @@ Process		Processor					TjMax(C)
 
 45nm		Atom Processors
 		D525/510/425/410				100
+		Z670/650					90
 		Z560/550/540/530P/530/520PT/520/515/510PT/510P	90
 		Z510/500					90
+		N570/550					100
 		N475/470/455/450				100
 		N280/270					90
 		330/230						125
diff --git a/Documentation/hwmon/da9055 b/Documentation/hwmon/da9055
new file mode 100644
index 0000000..855c3f5
--- /dev/null
+++ b/Documentation/hwmon/da9055
@@ -0,0 +1,47 @@
+Supported chips:
+  * Dialog Semiconductors DA9055 PMIC
+    Prefix: 'da9055'
+    Datasheet: Datasheet is not publicly available.
+
+Authors: David Dajun Chen <dchen@diasemi.com>
+
+Description
+-----------
+
+The DA9055 provides an Analogue to Digital Converter (ADC) with 10 bits
+resolution and track and hold circuitry combined with an analogue input
+multiplexer. The analogue input multiplexer will allow conversion of up to 5
+different inputs. The track and hold circuit ensures stable input voltages at
+the input of the ADC during the conversion.
+
+The ADC is used to measure the following inputs:
+Channel 0: VDDOUT - measurement of the system voltage
+Channel 1: ADC_IN1 - high impedance input (0 - 2.5V)
+Channel 2: ADC_IN2 - high impedance input (0 - 2.5V)
+Channel 3: ADC_IN3 - high impedance input (0 - 2.5V)
+Channel 4: Internal Tjunc. - sense (internal temp. sensor)
+
+By using sysfs attributes we can measure the system voltage VDDOUT,
+chip junction temperature and auxiliary channels voltages.
+
+Voltage Monitoring
+------------------
+
+Voltages are sampled in a AUTO mode it can be manually sampled too and results
+are stored in a 10 bit ADC.
+
+The system voltage is calculated as:
+	Milli volt = ((ADC value * 1000) / 85) + 2500
+
+The voltages on ADC channels 1, 2 and 3 are calculated as:
+	Milli volt = (ADC value * 1000) / 102
+
+Temperature Monitoring
+----------------------
+
+Temperatures are sampled by a 10 bit ADC.  Junction temperatures
+are monitored by the ADC channels.
+
+The junction temperature is calculated:
+	Degrees celsius = -0.4084 * (ADC_RES - T_OFFSET) + 307.6332
+The junction temperature attribute is supported by the driver.
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index 87850d8..8386aad 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -209,3 +209,13 @@ doesn't use CPU cycles.
 Trip points must be set properly before switching to automatic fan speed
 control mode. The driver will perform basic integrity checks before
 actually switching to automatic control mode.
+
+
+Temperature offset attributes
+-----------------------------
+
+The driver supports temp[1-3]_offset sysfs attributes to adjust the reported
+temperature for thermal diodes or diode-connected thermal transistors.
+If a temperature sensor is configured for thermistors, the attribute values
+are ignored. If the thermal sensor type is Intel PECI, the temperature offset
+must be programmed to the critical CPU temperature.
diff --git a/Documentation/hwmon/pmbus b/Documentation/hwmon/pmbus
index f90f999..3d3a0f9 100644
--- a/Documentation/hwmon/pmbus
+++ b/Documentation/hwmon/pmbus
@@ -138,7 +138,7 @@ Sysfs entries
 
 When probing the chip, the driver identifies which PMBus registers are
 supported, and determines available sensors from this information.
-Attribute files only exist if respective sensors are suported by the chip.
+Attribute files only exist if respective sensors are supported by the chip.
 Labels are provided to inform the user about the sensor associated with
 a given sysfs entry.
 
diff --git a/Documentation/hwmon/vexpress b/Documentation/hwmon/vexpress
new file mode 100644
index 0000000..557d6d5
--- /dev/null
+++ b/Documentation/hwmon/vexpress
@@ -0,0 +1,34 @@
+Kernel driver vexpress
+======================
+
+Supported systems:
+  * ARM Ltd. Versatile Express platform
+    Prefix: 'vexpress'
+    Datasheets:
+      * "Hardware Description" sections of the Technical Reference Manuals
+        for the Versatile Express boards:
+        http://infocenter.arm.com/help/topic/com.arm.doc.subset.boards.express/index.html
+      * Section "4.4.14. System Configuration registers" of the V2M-P1 TRM:
+        http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0447-/index.html
+
+Author: Pawel Moll
+
+Description
+-----------
+
+Versatile Express platform (http://www.arm.com/versatileexpress/) is a
+reference & prototyping system for ARM Ltd. processors. It can be set up
+from a wide range of boards, each of them containing (apart of the main
+chip/FPGA) a number of microcontrollers responsible for platform
+configuration and control. Theses microcontrollers can also monitor the
+board and its environment by a number of internal and external sensors,
+providing information about power lines voltages and currents, board
+temperature and power usage. Some of them also calculate consumed energy
+and provide a cumulative use counter.
+
+The configuration devices are _not_ memory mapped and must be accessed
+via a custom interface, abstracted by the "vexpress_config" API.
+
+As these devices are non-discoverable, they must be described in a Device
+Tree passed to the kernel. Details of the DT binding for them can be found
+in Documentation/devicetree/bindings/hwmon/vexpress.txt.
diff --git a/Documentation/i2c/smbus-protocol b/Documentation/i2c/smbus-protocol
index 49f5b68..d1f2261 100644
--- a/Documentation/i2c/smbus-protocol
+++ b/Documentation/i2c/smbus-protocol
@@ -23,6 +23,12 @@ don't match these function names.  For some of the operations which pass a
 single data byte, the functions using SMBus protocol operation names execute
 a different protocol operation entirely.
 
+Each transaction type corresponds to a functionality flag. Before calling a
+transaction function, a device driver should always check (just once) for
+the corresponding functionality flag to ensure that the underlying I2C
+adapter supports the transaction in question. See
+<file:Documentation/i2c/functionality> for the details.
+
 
 Key to symbols
 ==============
@@ -49,6 +55,8 @@ This sends a single bit to the device, at the place of the Rd/Wr bit.
 
 A Addr Rd/Wr [A] P
 
+Functionality flag: I2C_FUNC_SMBUS_QUICK
+
 
 SMBus Receive Byte:  i2c_smbus_read_byte()
 ==========================================
@@ -60,6 +68,8 @@ the previous SMBus command.
 
 S Addr Rd [A] [Data] NA P
 
+Functionality flag: I2C_FUNC_SMBUS_READ_BYTE
+
 
 SMBus Send Byte:  i2c_smbus_write_byte()
 ========================================
@@ -69,6 +79,8 @@ to a device.  See Receive Byte for more information.
 
 S Addr Wr [A] Data [A] P
 
+Functionality flag: I2C_FUNC_SMBUS_WRITE_BYTE
+
 
 SMBus Read Byte:  i2c_smbus_read_byte_data()
 ============================================
@@ -78,6 +90,8 @@ The register is specified through the Comm byte.
 
 S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P
 
+Functionality flag: I2C_FUNC_SMBUS_READ_BYTE_DATA
+
 
 SMBus Read Word:  i2c_smbus_read_word_data()
 ============================================
@@ -88,6 +102,8 @@ byte. But this time, the data is a complete word (16 bits).
 
 S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
 
+Functionality flag: I2C_FUNC_SMBUS_READ_WORD_DATA
+
 Note the convenience function i2c_smbus_read_word_swapped is
 available for reads where the two data bytes are the other way
 around (not SMBus compliant, but very popular.)
@@ -102,6 +118,8 @@ the Read Byte operation.
 
 S Addr Wr [A] Comm [A] Data [A] P
 
+Functionality flag: I2C_FUNC_SMBUS_WRITE_BYTE_DATA
+
 
 SMBus Write Word:  i2c_smbus_write_word_data()
 ==============================================
@@ -112,6 +130,8 @@ specified through the Comm byte.
 
 S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P
 
+Functionality flag: I2C_FUNC_SMBUS_WRITE_WORD_DATA
+
 Note the convenience function i2c_smbus_write_word_swapped is
 available for writes where the two data bytes are the other way
 around (not SMBus compliant, but very popular.)
@@ -126,6 +146,8 @@ This command selects a device register (through the Comm byte), sends
 S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] 
                              S Addr Rd [A] [DataLow] A [DataHigh] NA P
 
+Functionality flag: I2C_FUNC_SMBUS_PROC_CALL
+
 
 SMBus Block Read:  i2c_smbus_read_block_data()
 ==============================================
@@ -137,6 +159,8 @@ of data is specified by the device in the Count byte.
 S Addr Wr [A] Comm [A] 
            S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P
 
+Functionality flag: I2C_FUNC_SMBUS_READ_BLOCK_DATA
+
 
 SMBus Block Write:  i2c_smbus_write_block_data()
 ================================================
@@ -147,6 +171,8 @@ Comm byte. The amount of data is specified in the Count byte.
 
 S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P
 
+Functionality flag: I2C_FUNC_SMBUS_WRITE_BLOCK_DATA
+
 
 SMBus Block Write - Block Read Process Call
 ===========================================
@@ -160,6 +186,8 @@ This command selects a device register (through the Comm byte), sends
 S Addr Wr [A] Comm [A] Count [A] Data [A] ...
                              S Addr Rd [A] [Count] A [Data] ... A P
 
+Functionality flag: I2C_FUNC_SMBUS_BLOCK_PROC_CALL
+
 
 SMBus Host Notify
 =================
@@ -229,15 +257,7 @@ designated register that is specified through the Comm byte.
 S Addr Wr [A] Comm [A] 
            S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P
 
-
-I2C Block Read (2 Comm bytes)
-=============================
-
-This command reads a block of bytes from a device, from a 
-designated register that is specified through the two Comm bytes.
-
-S Addr Wr [A] Comm1 [A] Comm2 [A] 
-           S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P
+Functionality flag: I2C_FUNC_SMBUS_READ_I2C_BLOCK
 
 
 I2C Block Write:  i2c_smbus_write_i2c_block_data()
@@ -249,3 +269,5 @@ Comm byte. Note that command lengths of 0, 2, or more bytes are
 supported as they are indistinguishable from data.
 
 S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P
+
+Functionality flag: I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt
index ae8ba9a..3262b6e 100644
--- a/Documentation/input/alps.txt
+++ b/Documentation/input/alps.txt
@@ -133,7 +133,7 @@ number of contacts (f1 and f0 in the table below).
 
 This packet only appears after a position packet with the mt bit set, and
 usually only appears when there are two or more contacts (although
-occassionally it's seen with only a single contact).
+occasionally it's seen with only a single contact).
 
 The final v3 packet type is the trackstick packet.
 
diff --git a/Documentation/input/event-codes.txt b/Documentation/input/event-codes.txt
index 53305bd..f1ea2c6 100644
--- a/Documentation/input/event-codes.txt
+++ b/Documentation/input/event-codes.txt
@@ -196,6 +196,17 @@ EV_MSC:
 EV_MSC events are used for input and output events that do not fall under other
 categories.
 
+A few EV_MSC codes have special meaning:
+
+* MSC_TIMESTAMP:
+  - Used to report the number of microseconds since the last reset. This event
+    should be coded as an uint32 value, which is allowed to wrap around with
+    no special consequence. It is assumed that the time difference between two
+    consecutive events is reliable on a reasonable time scale (hours).
+    A reset to zero can happen, in which case the time since the last event is
+    unknown.  If the device does not provide this information, the driver must
+    not provide it to user space.
+
 EV_LED:
 ----------
 EV_LED events are used for input and output to set and query the state of
diff --git a/Documentation/intel_txt.txt b/Documentation/intel_txt.txt
index 849de1a..91d89c5 100644
--- a/Documentation/intel_txt.txt
+++ b/Documentation/intel_txt.txt
@@ -192,7 +192,7 @@ grub.conf needs to be modified as follows:
 
 The kernel option for enabling Intel TXT support is found under the
 Security top-level menu and is called "Enable Intel(R) Trusted
-Execution Technology (TXT)".  It is marked as EXPERIMENTAL and
+Execution Technology (TXT)".  It is considered EXPERIMENTAL and
 depends on the generic x86 support (to allow maximum flexibility in
 kernel build options), since the tboot code will detect whether the
 platform actually supports Intel TXT and thus whether any of the
diff --git a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt
index 3fb39e0..69372fb 100644
--- a/Documentation/kbuild/modules.txt
+++ b/Documentation/kbuild/modules.txt
@@ -470,7 +470,7 @@ build.
 
 	Sometimes, an external module uses exported symbols from
 	another external module. kbuild needs to have full knowledge of
-	all symbols to avoid spitting out warnings about undefined
+	all symbols to avoid spliitting out warnings about undefined
 	symbols. Three solutions exist for this situation.
 
 	NOTE: The method with a top-level kbuild file is recommended
diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt
index 3d8a977..99b57ab 100644
--- a/Documentation/kernel-doc-nano-HOWTO.txt
+++ b/Documentation/kernel-doc-nano-HOWTO.txt
@@ -64,6 +64,8 @@ Example kernel-doc function comment:
  * comment lines.
  *
  * The longer description can have multiple paragraphs.
+ *
+ * Return: Describe the return value of foobar.
  */
 
 The short description following the subject can span multiple lines
@@ -78,6 +80,8 @@ If a function parameter is "..." (varargs), it should be listed in
 kernel-doc notation as:
  * @...: description
 
+The return value, if any, should be described in a dedicated section
+named "Return".
 
 Example kernel-doc data structure comment.
 
@@ -222,6 +226,9 @@ only a "*").
 "section header:" names must be unique per function (or struct,
 union, typedef, enum).
 
+Use the section header "Return" for sections describing the return value
+of a function.
+
 Avoid putting a spurious blank line after the function name, or else the
 description will be repeated!
 
@@ -237,21 +244,21 @@ patterns, which are highlighted appropriately.
 NOTE 1:  The multi-line descriptive text you provide does *not* recognize
 line breaks, so if you try to format some text nicely, as in:
 
-  Return codes
+  Return:
     0 - cool
     1 - invalid arg
     2 - out of memory
 
 this will all run together and produce:
 
-  Return codes 0 - cool 1 - invalid arg 2 - out of memory
+  Return: 0 - cool 1 - invalid arg 2 - out of memory
 
 NOTE 2:  If the descriptive text you provide has lines that begin with
 some phrase followed by a colon, each of those phrases will be taken as
 a new section heading, which means you should similarly try to avoid text
 like:
 
-  Return codes:
+  Return:
     0: cool
     1: invalid arg
     2: out of memory
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 9776f06..d1d690c 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -905,6 +905,24 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	gpt		[EFI] Forces disk with valid GPT signature but
 			invalid Protective MBR to be treated as GPT.
 
+	grcan.enable0=	[HW] Configuration of physical interface 0. Determines
+			the "Enable 0" bit of the configuration register.
+			Format: 0 | 1
+			Default: 0
+	grcan.enable1=	[HW] Configuration of physical interface 1. Determines
+			the "Enable 0" bit of the configuration register.
+			Format: 0 | 1
+			Default: 0
+	grcan.select=	[HW] Select which physical interface to use.
+			Format: 0 | 1
+			Default: 0
+	grcan.txsize=	[HW] Sets the size of the tx buffer.
+			Format: <unsigned int> such that (txsize & ~0x1fffc0) == 0.
+			Default: 1024
+	grcan.rxsize=	[HW] Sets the size of the rx buffer.
+			Format: <unsigned int> such that (rxsize & ~0x1fffc0) == 0.
+			Default: 1024
+
 	hashdist=	[KNL,NUMA] Large hashes allocated during boot
 			are distributed across NUMA nodes.  Defaults on
 			for 64-bit NUMA, off otherwise.
@@ -1304,6 +1322,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	lapic		[X86-32,APIC] Enable the local APIC even if BIOS
 			disabled it.
 
+	lapic=		[x86,APIC] "notscdeadline" Do not use TSC deadline
+			value for LAPIC timer one-shot implementation. Default
+			back to the programmable timer unit in the LAPIC.
+
 	lapic_timer_c2_ok	[X86,APIC] trust the local apic timer
 			in C2 power state.
 
@@ -1481,9 +1503,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	mem=nn[KMG]	[KNL,BOOT] Force usage of a specific amount of memory
 			Amount of memory to be used when the kernel is not able
 			to see the whole system memory or for test.
-			[X86-32] Use together with memmap= to avoid physical
-			address space collisions. Without memmap= PCI devices
-			could be placed at addresses belonging to unused RAM.
+			[X86] Work as limiting max address. Use together
+			with memmap= to avoid physical address space collisions.
+			Without memmap= PCI devices could be placed at addresses
+			belonging to unused RAM.
 
 	mem=nopentium	[BUGS=X86-32] Disable usage of 4MB pages for kernel
 			memory.
@@ -2394,6 +2417,27 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	ramdisk_size=	[RAM] Sizes of RAM disks in kilobytes
 			See Documentation/blockdev/ramdisk.txt.
 
+	rcu_nocbs=	[KNL,BOOT]
+			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
+			be offloaded to "rcuoN" kthreads created for
+			that purpose.  This reduces OS jitter on the
+			offloaded CPUs, which can be useful for HPC and
+			real-time workloads.  It can also improve energy
+			efficiency for asymmetric multiprocessors.
+
+	rcu_nocbs_poll	[KNL,BOOT]
+			Rather than requiring that offloaded CPUs
+			(specified by rcu_nocbs= above) explicitly
+			awaken the corresponding "rcuoN" kthreads,
+			make these kthreads poll for callbacks.
+			This improves the real-time response for the
+			offloaded CPUs by relieving them of the need to
+			wake up the corresponding kthread, but degrades
+			energy efficiency by requiring that the kthreads
+			periodically wake up to do the polling.
+
 	rcutree.blimit=	[KNL,BOOT]
 			Set maximum number of finished RCU callbacks to process
 			in one batch.
@@ -2859,6 +2903,22 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			to facilitate early boot debugging.
 			See also Documentation/trace/events.txt
 
+	trace_options=[option-list]
+			[FTRACE] Enable or disable tracer options at boot.
+			The option-list is a comma delimited list of options
+			that can be enabled or disabled just as if you were
+			to echo the option name into
+
+			    /sys/kernel/debug/tracing/trace_options
+
+			For example, to enable stacktrace option (to dump the
+			stack trace of each event), add to the command line:
+
+			      trace_options=stacktrace
+
+			See also Documentation/trace/ftrace.txt "trace options"
+			section.
+
 	transparent_hugepage=
 			[KNL]
 			Format: [always|madvise|never]
diff --git a/Documentation/kref.txt b/Documentation/kref.txt
index 48ba715..ddf85a5 100644
--- a/Documentation/kref.txt
+++ b/Documentation/kref.txt
@@ -213,3 +213,91 @@ presentation on krefs, which can be found at:
 and:
   http://www.kroah.com/linux/talks/ols_2004_kref_talk/
 
+
+The above example could also be optimized using kref_get_unless_zero() in
+the following way:
+
+static struct my_data *get_entry()
+{
+	struct my_data *entry = NULL;
+	mutex_lock(&mutex);
+	if (!list_empty(&q)) {
+		entry = container_of(q.next, struct my_data, link);
+		if (!kref_get_unless_zero(&entry->refcount))
+			entry = NULL;
+	}
+	mutex_unlock(&mutex);
+	return entry;
+}
+
+static void release_entry(struct kref *ref)
+{
+	struct my_data *entry = container_of(ref, struct my_data, refcount);
+
+	mutex_lock(&mutex);
+	list_del(&entry->link);
+	mutex_unlock(&mutex);
+	kfree(entry);
+}
+
+static void put_entry(struct my_data *entry)
+{
+	kref_put(&entry->refcount, release_entry);
+}
+
+Which is useful to remove the mutex lock around kref_put() in put_entry(), but
+it's important that kref_get_unless_zero is enclosed in the same critical
+section that finds the entry in the lookup table,
+otherwise kref_get_unless_zero may reference already freed memory.
+Note that it is illegal to use kref_get_unless_zero without checking its
+return value. If you are sure (by already having a valid pointer) that
+kref_get_unless_zero() will return true, then use kref_get() instead.
+
+The function kref_get_unless_zero also makes it possible to use rcu
+locking for lookups in the above example:
+
+struct my_data
+{
+	struct rcu_head rhead;
+	.
+	struct kref refcount;
+	.
+	.
+};
+
+static struct my_data *get_entry_rcu()
+{
+	struct my_data *entry = NULL;
+	rcu_read_lock();
+	if (!list_empty(&q)) {
+		entry = container_of(q.next, struct my_data, link);
+		if (!kref_get_unless_zero(&entry->refcount))
+			entry = NULL;
+	}
+	rcu_read_unlock();
+	return entry;
+}
+
+static void release_entry_rcu(struct kref *ref)
+{
+	struct my_data *entry = container_of(ref, struct my_data, refcount);
+
+	mutex_lock(&mutex);
+	list_del_rcu(&entry->link);
+	mutex_unlock(&mutex);
+	kfree_rcu(entry, rhead);
+}
+
+static void put_entry(struct my_data *entry)
+{
+	kref_put(&entry->refcount, release_entry_rcu);
+}
+
+But note that the struct kref member needs to remain in valid memory for a
+rcu grace period after release_entry_rcu was called. That can be accomplished
+by using kfree_rcu(entry, rhead) as done above, or by calling synchronize_rcu()
+before using kfree, but note that synchronize_rcu() may sleep for a
+substantial amount of time.
+
+
+Thomas Hellstrom <thellstrom@vmware.com>
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 2759f7c..3c4e1b3 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -251,12 +251,13 @@ And there are a number of things that _must_ or _must_not_ be assumed:
 
      And for:
 
-	*A = X; Y = *A;
+	*A = X; *(A + 4) = Y;
 
-     we may get either of:
+     we may get any of:
 
-	STORE *A = X; Y = LOAD *A;
-	STORE *A = Y = X;
+	STORE *A = X; STORE *(A + 4) = Y;
+	STORE *(A + 4) = Y; STORE *A = X;
+	STORE {*A, *(A + 4) } = {X, Y};
 
 
 =========================
diff --git a/Documentation/memory-hotplug.txt b/Documentation/memory-hotplug.txt
index 6d0c251..8e5eacb 100644
--- a/Documentation/memory-hotplug.txt
+++ b/Documentation/memory-hotplug.txt
@@ -161,7 +161,8 @@ a recent addition and not present on older kernels.
 		    in the memory block.
 'state'           : read-write
                     at read:  contains online/offline state of memory.
-                    at write: user can specify "online", "offline" command
+                    at write: user can specify "online_kernel",
+                    "online_movable", "online", "offline" command
                     which will be performed on al sections in the block.
 'phys_device'     : read-only: designed to show the name of physical memory
                     device.  This is not well implemented now.
@@ -255,6 +256,17 @@ For onlining, you have to write "online" to the section's state file as:
 
 % echo online > /sys/devices/system/memory/memoryXXX/state
 
+This onlining will not change the ZONE type of the target memory section,
+If the memory section is in ZONE_NORMAL, you can change it to ZONE_MOVABLE:
+
+% echo online_movable > /sys/devices/system/memory/memoryXXX/state
+(NOTE: current limit: this memory section must be adjacent to ZONE_MOVABLE)
+
+And if the memory section is in ZONE_MOVABLE, you can change it to ZONE_NORMAL:
+
+% echo online_kernel > /sys/devices/system/memory/memoryXXX/state
+(NOTE: current limit: this memory section must be adjacent to ZONE_NORMAL)
+
 After this, section memoryXXX's state will be 'online' and the amount of
 available memory will be increased.
 
@@ -377,15 +389,21 @@ The third argument is passed by pointer of struct memory_notify.
 struct memory_notify {
        unsigned long start_pfn;
        unsigned long nr_pages;
+       int status_change_nid_normal;
+       int status_change_nid_high;
        int status_change_nid;
 }
 
 start_pfn is start_pfn of online/offline memory.
 nr_pages is # of pages of online/offline memory.
-status_change_nid is set node id when N_HIGH_MEMORY of nodemask is (will be)
+status_change_nid_normal is set node id when N_NORMAL_MEMORY of nodemask
+is (will be) set/clear, if this is -1, then nodemask status is not changed.
+status_change_nid_high is set node id when N_HIGH_MEMORY of nodemask
+is (will be) set/clear, if this is -1, then nodemask status is not changed.
+status_change_nid is set node id when N_MEMORY of nodemask is (will be)
 set/clear. It means a new(memoryless) node gets new memory by online and a
 node loses all memory. If this is -1, then nodemask status is not changed.
-If status_changed_nid >= 0, callback should create/discard structures for the
+If status_changed_nid* >= 0, callback should create/discard structures for the
 node if necessary.
 
 --------------
diff --git a/Documentation/misc-devices/mei/mei-amt-version.c b/Documentation/misc-devices/mei/mei-amt-version.c
index 01804f2..49e4f77 100644
--- a/Documentation/misc-devices/mei/mei-amt-version.c
+++ b/Documentation/misc-devices/mei/mei-amt-version.c
@@ -214,7 +214,7 @@ out:
 }
 
 /***************************************************************************
- * Intel Advanced Management Technolgy ME Client
+ * Intel Advanced Management Technology ME Client
  ***************************************************************************/
 
 #define AMT_MAJOR_VERSION 1
@@ -256,7 +256,7 @@ struct amt_code_versions {
 } __attribute__((packed));
 
 /***************************************************************************
- * Intel Advanced Management Technolgy Host Interface
+ * Intel Advanced Management Technology Host Interface
  ***************************************************************************/
 
 struct amt_host_if_msg_header {
diff --git a/Documentation/mmc/mmc-dev-attrs.txt b/Documentation/mmc/mmc-dev-attrs.txt
index 22ae844..0d98fac 100644
--- a/Documentation/mmc/mmc-dev-attrs.txt
+++ b/Documentation/mmc/mmc-dev-attrs.txt
@@ -25,6 +25,8 @@ All attributes are read-only.
 	serial			Product Serial Number (from CID Register)
 	erase_size		Erase group size
 	preferred_erase_size	Preferred erase size
+	raw_rpmb_size_mult	RPMB partition size
+	rel_sectors		Reliable write sector count
 
 Note on Erase Size and Preferred Erase Size:
 
@@ -65,6 +67,11 @@ Note on Erase Size and Preferred Erase Size:
 
 	"preferred_erase_size" is in bytes.
 
+Note on raw_rpmb_size_mult:
+	"raw_rpmb_size_mult" is a mutliple of 128kB block.
+	RPMB size in byte is calculated by using the following equation:
+	RPMB partition size = 128kB x raw_rpmb_size_mult
+
 SD/MMC/SDIO Clock Gating Attribute
 ==================================
 
diff --git a/Documentation/networking/batman-adv.txt b/Documentation/networking/batman-adv.txt
index a173d2a..c1d8204 100644
--- a/Documentation/networking/batman-adv.txt
+++ b/Documentation/networking/batman-adv.txt
@@ -203,7 +203,8 @@ abled  during run time. Following log_levels are defined:
 2 - Enable messages related to route added / changed / deleted
 4 - Enable messages related to translation table operations
 8 - Enable messages related to bridge loop avoidance
-15 - enable all messages
+16 - Enable messaged related to DAT, ARP snooping and parsing
+31 - Enable all messages
 
 The debug output can be changed at runtime  using  the  file
 /sys/class/net/bat0/mesh/log_level. e.g.
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index c7fc107..98ac0d7 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1514,6 +1514,20 @@ cookie_preserve_enable - BOOLEAN
 
 	Default: 1
 
+cookie_hmac_alg - STRING
+	Select the hmac algorithm used when generating the cookie value sent by
+	a listening sctp socket to a connecting client in the INIT-ACK chunk.
+	Valid values are:
+	* md5
+	* sha1
+	* none
+	Ability to assign md5 or sha1 as the selected alg is predicated on the
+	configuarion of those algorithms at build time (CONFIG_CRYPTO_MD5 and
+	CONFIG_CRYPTO_SHA1).
+
+	Default: Dependent on configuration.  MD5 if available, else SHA1 if
+	available, else none.
+
 rcvbuf_policy - INTEGER
 	Determines if the receive buffer is attributed to the socket or to
 	association.   SCTP supports the capability to create multiple
diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt
index 1c08a4b..94444b1 100644
--- a/Documentation/networking/packet_mmap.txt
+++ b/Documentation/networking/packet_mmap.txt
@@ -3,9 +3,9 @@
 --------------------------------------------------------------------------------
 
 This file documents the mmap() facility available with the PACKET
-socket interface on 2.4 and 2.6 kernels. This type of sockets is used for 
-capture network traffic with utilities like tcpdump or any other that needs
-raw access to network interface.
+socket interface on 2.4/2.6/3.x kernels. This type of sockets is used for
+i) capture network traffic with utilities like tcpdump, ii) transmit network
+traffic, or any other that needs raw access to network interface.
 
 You can find the latest version of this document at:
     http://wiki.ipxwarzone.com/index.php5?title=Linux_packet_mmap
@@ -21,19 +21,18 @@ Please send your comments to
 + Why use PACKET_MMAP
 --------------------------------------------------------------------------------
 
-In Linux 2.4/2.6 if PACKET_MMAP is not enabled, the capture process is very
-inefficient. It uses very limited buffers and requires one system call
-to capture each packet, it requires two if you want to get packet's 
-timestamp (like libpcap always does).
+In Linux 2.4/2.6/3.x if PACKET_MMAP is not enabled, the capture process is very
+inefficient. It uses very limited buffers and requires one system call to
+capture each packet, it requires two if you want to get packet's timestamp
+(like libpcap always does).
 
 In the other hand PACKET_MMAP is very efficient. PACKET_MMAP provides a size 
 configurable circular buffer mapped in user space that can be used to either
 send or receive packets. This way reading packets just needs to wait for them,
 most of the time there is no need to issue a single system call. Concerning
 transmission, multiple packets can be sent through one system call to get the
-highest bandwidth.
-By using a shared buffer between the kernel and the user also has the benefit
-of minimizing packet copies.
+highest bandwidth. By using a shared buffer between the kernel and the user
+also has the benefit of minimizing packet copies.
 
 It's fine to use PACKET_MMAP to improve the performance of the capture and
 transmission process, but it isn't everything. At least, if you are capturing
@@ -41,7 +40,8 @@ at high speeds (this is relative to the cpu speed), you should check if the
 device driver of your network interface card supports some sort of interrupt
 load mitigation or (even better) if it supports NAPI, also make sure it is
 enabled. For transmission, check the MTU (Maximum Transmission Unit) used and
-supported by devices of your network.
+supported by devices of your network. CPU IRQ pinning of your network interface
+card can also be an advantage.
 
 --------------------------------------------------------------------------------
 + How to use mmap() to improve capture process
@@ -87,9 +87,7 @@ the following process:
 socket creation and destruction is straight forward, and is done 
 the same way with or without PACKET_MMAP:
 
-int fd;
-
-fd= socket(PF_PACKET, mode, htons(ETH_P_ALL))
+ int fd = socket(PF_PACKET, mode, htons(ETH_P_ALL));
 
 where mode is SOCK_RAW for the raw interface were link level
 information can be captured or SOCK_DGRAM for the cooked
@@ -163,11 +161,23 @@ As capture, each frame contains two parts:
 
  A complete tutorial is available at: http://wiki.gnu-log.net/
 
+By default, the user should put data at :
+ frame base + TPACKET_HDRLEN - sizeof(struct sockaddr_ll)
+
+So, whatever you choose for the socket mode (SOCK_DGRAM or SOCK_RAW),
+the beginning of the user data will be at :
+ frame base + TPACKET_ALIGN(sizeof(struct tpacket_hdr))
+
+If you wish to put user data at a custom offset from the beginning of
+the frame (for payload alignment with SOCK_RAW mode for instance) you
+can set tp_net (with SOCK_DGRAM) or tp_mac (with SOCK_RAW). In order
+to make this work it must be enabled previously with setsockopt()
+and the PACKET_TX_HAS_OFF option.
+
 --------------------------------------------------------------------------------
 + PACKET_MMAP settings
 --------------------------------------------------------------------------------
 
-
 To setup PACKET_MMAP from user level code is done with a call like
 
  - Capture process
@@ -201,7 +211,6 @@ indeed, packet_set_ring checks that the following condition is true
 
     frames_per_block * tp_block_nr == tp_frame_nr
 
-
 Lets see an example, with the following values:
 
      tp_block_size= 4096
@@ -227,7 +236,6 @@ be spawned across two blocks, so there are some details you have to take into
 account when choosing the frame_size. See "Mapping and use of the circular 
 buffer (ring)".
 
-
 --------------------------------------------------------------------------------
 + PACKET_MMAP setting constraints
 --------------------------------------------------------------------------------
@@ -264,7 +272,6 @@ User space programs can include /usr/include/sys/user.h and
 The pagesize can also be determined dynamically with the getpagesize (2) 
 system call. 
 
-
  Block number limit
 --------------------
 
@@ -284,7 +291,6 @@ called pg_vec, its size limits the number of blocks that can be allocated.
       v  block #2
      block #1
 
-
 kmalloc allocates any number of bytes of physically contiguous memory from 
 a pool of pre-determined sizes. This pool of memory is maintained by the slab 
 allocator which is at the end the responsible for doing the allocation and 
@@ -299,7 +305,6 @@ pointers to blocks is
 
      131072/4 = 32768 blocks
 
-
  PACKET_MMAP buffer size calculator
 ------------------------------------
 
@@ -340,7 +345,6 @@ and a value for <frame size> of 2048 bytes. These parameters will yield
 and hence the buffer will have a 262144 MiB size. So it can hold 
 262144 MiB / 2048 bytes = 134217728 frames
 
-
 Actually, this buffer size is not possible with an i386 architecture. 
 Remember that the memory is allocated in kernel space, in the case of 
 an i386 kernel's memory size is limited to 1GiB.
@@ -372,7 +376,6 @@ the following (from include/linux/if_packet.h):
    - Start+tp_net: Packet data, aligned to TPACKET_ALIGNMENT=16.
    - Pad to align to TPACKET_ALIGNMENT=16
  */
-           
  
  The following are conditions that are checked in packet_set_ring
 
@@ -413,7 +416,6 @@ and the following flags apply:
      #define TP_STATUS_LOSING        4 
      #define TP_STATUS_CSUMNOTREADY  8 
 
-
 TP_STATUS_COPY        : This flag indicates that the frame (and associated
                         meta information) has been truncated because it's 
                         larger than tp_frame_size. This packet can be 
@@ -462,7 +464,6 @@ packets are in the ring:
 It doesn't incur in a race condition to first check the status value and 
 then poll for frames.
 
-
 ++ Transmission process
 Those defines are also used for transmission:
 
@@ -494,6 +495,196 @@ The user can also use poll() to check if a buffer is available:
     retval = poll(&pfd, 1, timeout);
 
 -------------------------------------------------------------------------------
++ What TPACKET versions are available and when to use them?
+-------------------------------------------------------------------------------
+
+ int val = tpacket_version;
+ setsockopt(fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
+ getsockopt(fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
+
+where 'tpacket_version' can be TPACKET_V1 (default), TPACKET_V2, TPACKET_V3.
+
+TPACKET_V1:
+	- Default if not otherwise specified by setsockopt(2)
+	- RX_RING, TX_RING available
+	- VLAN metadata information available for packets
+	  (TP_STATUS_VLAN_VALID)
+
+TPACKET_V1 --> TPACKET_V2:
+	- Made 64 bit clean due to unsigned long usage in TPACKET_V1
+	  structures, thus this also works on 64 bit kernel with 32 bit
+	  userspace and the like
+	- Timestamp resolution in nanoseconds instead of microseconds
+	- RX_RING, TX_RING available
+	- How to switch to TPACKET_V2:
+		1. Replace struct tpacket_hdr by struct tpacket2_hdr
+		2. Query header len and save
+		3. Set protocol version to 2, set up ring as usual
+		4. For getting the sockaddr_ll,
+		   use (void *)hdr + TPACKET_ALIGN(hdrlen) instead of
+		   (void *)hdr + TPACKET_ALIGN(sizeof(struct tpacket_hdr))
+
+TPACKET_V2 --> TPACKET_V3:
+	- Flexible buffer implementation:
+		1. Blocks can be configured with non-static frame-size
+		2. Read/poll is at a block-level (as opposed to packet-level)
+		3. Added poll timeout to avoid indefinite user-space wait
+		   on idle links
+		4. Added user-configurable knobs:
+			4.1 block::timeout
+			4.2 tpkt_hdr::sk_rxhash
+	- RX Hash data available in user space
+	- Currently only RX_RING available
+
+-------------------------------------------------------------------------------
++ AF_PACKET fanout mode
+-------------------------------------------------------------------------------
+
+In the AF_PACKET fanout mode, packet reception can be load balanced among
+processes. This also works in combination with mmap(2) on packet sockets.
+
+Minimal example code by David S. Miller (try things like "./test eth0 hash",
+"./test eth0 lb", etc.):
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <unistd.h>
+
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+
+#include <net/if.h>
+
+static const char *device_name;
+static int fanout_type;
+static int fanout_id;
+
+#ifndef PACKET_FANOUT
+# define PACKET_FANOUT			18
+# define PACKET_FANOUT_HASH		0
+# define PACKET_FANOUT_LB		1
+#endif
+
+static int setup_socket(void)
+{
+	int err, fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP));
+	struct sockaddr_ll ll;
+	struct ifreq ifr;
+	int fanout_arg;
+
+	if (fd < 0) {
+		perror("socket");
+		return EXIT_FAILURE;
+	}
+
+	memset(&ifr, 0, sizeof(ifr));
+	strcpy(ifr.ifr_name, device_name);
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		perror("SIOCGIFINDEX");
+		return EXIT_FAILURE;
+	}
+
+	memset(&ll, 0, sizeof(ll));
+	ll.sll_family = AF_PACKET;
+	ll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *) &ll, sizeof(ll));
+	if (err < 0) {
+		perror("bind");
+		return EXIT_FAILURE;
+	}
+
+	fanout_arg = (fanout_id | (fanout_type << 16));
+	err = setsockopt(fd, SOL_PACKET, PACKET_FANOUT,
+			 &fanout_arg, sizeof(fanout_arg));
+	if (err) {
+		perror("setsockopt");
+		return EXIT_FAILURE;
+	}
+
+	return fd;
+}
+
+static void fanout_thread(void)
+{
+	int fd = setup_socket();
+	int limit = 10000;
+
+	if (fd < 0)
+		exit(fd);
+
+	while (limit-- > 0) {
+		char buf[1600];
+		int err;
+
+		err = read(fd, buf, sizeof(buf));
+		if (err < 0) {
+			perror("read");
+			exit(EXIT_FAILURE);
+		}
+		if ((limit % 10) == 0)
+			fprintf(stdout, "(%d) \n", getpid());
+	}
+
+	fprintf(stdout, "%d: Received 10000 packets\n", getpid());
+
+	close(fd);
+	exit(0);
+}
+
+int main(int argc, char **argp)
+{
+	int fd, err;
+	int i;
+
+	if (argc != 3) {
+		fprintf(stderr, "Usage: %s INTERFACE {hash|lb}\n", argp[0]);
+		return EXIT_FAILURE;
+	}
+
+	if (!strcmp(argp[2], "hash"))
+		fanout_type = PACKET_FANOUT_HASH;
+	else if (!strcmp(argp[2], "lb"))
+		fanout_type = PACKET_FANOUT_LB;
+	else {
+		fprintf(stderr, "Unknown fanout type [%s]\n", argp[2]);
+		exit(EXIT_FAILURE);
+	}
+
+	device_name = argp[1];
+	fanout_id = getpid() & 0xffff;
+
+	for (i = 0; i < 4; i++) {
+		pid_t pid = fork();
+
+		switch (pid) {
+		case 0:
+			fanout_thread();
+
+		case -1:
+			perror("fork");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	for (i = 0; i < 4; i++) {
+		int status;
+
+		wait(&status);
+	}
+
+	return 0;
+}
+
+-------------------------------------------------------------------------------
 + PACKET_TIMESTAMP
 -------------------------------------------------------------------------------
 
@@ -519,6 +710,13 @@ the networking stack is used (the behavior before this setting was added).
 See include/linux/net_tstamp.h and Documentation/networking/timestamping
 for more information on hardware timestamps.
 
+-------------------------------------------------------------------------------
++ Miscellaneous bits
+-------------------------------------------------------------------------------
+
+- Packet sockets work well together with Linux socket filters, thus you also
+  might want to have a look at Documentation/networking/filter.txt
+
 --------------------------------------------------------------------------------
 + THANKS
 --------------------------------------------------------------------------------
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index ef9ee71..f9fa6db 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -29,11 +29,9 @@ The kernel configuration option is STMMAC_ETH:
 	dma_txsize: DMA tx ring size;
 	buf_sz: DMA buffer size;
 	tc: control the HW FIFO threshold;
-	tx_coe: Enable/Disable Tx Checksum Offload engine;
 	watchdog: transmit timeout (in milliseconds);
 	flow_ctrl: Flow control ability [on/off];
 	pause: Flow Control Pause Time;
-	tmrate: timer period (only if timer optimisation is configured).
 
 3) Command line options
 Driver parameters can be also passed in command line by using:
@@ -60,17 +58,19 @@ Then the poll method will be scheduled at some future point.
 The incoming packets are stored, by the DMA, in a list of pre-allocated socket
 buffers in order to avoid the memcpy (Zero-copy).
 
-4.3) Timer-Driver Interrupt
-Instead of having the device that asynchronously notifies the frame receptions,
-the driver configures a timer to generate an interrupt at regular intervals.
-Based on the granularity of the timer, the frames that are received by the
-device will experience different levels of latency. Some NICs have dedicated
-timer device to perform this task. STMMAC can use either the RTC device or the
-TMU channel 2  on STLinux platforms.
-The timers frequency can be passed to the driver as parameter; when change it,
-take care of both hardware capability and network stability/performance impact.
-Several performance tests on STM platforms showed this optimisation allows to
-spare the CPU while having the maximum throughput.
+4.3) Interrupt Mitigation
+The driver is able to mitigate the number of its DMA interrupts
+using NAPI for the reception on chips older than the 3.50.
+New chips have an HW RX-Watchdog used for this mitigation.
+
+On Tx-side, the mitigation schema is based on a SW timer that calls the
+tx function (stmmac_tx) to reclaim the resource after transmitting the
+frames.
+Also there is another parameter (like a threshold) used to program
+the descriptors avoiding to set the interrupt on completion bit in
+when the frame is sent (xmit).
+
+Mitigation parameters can be tuned by ethtool.
 
 4.4) WOL
 Wake up on Lan feature through Magic and Unicast frames are supported for the
@@ -121,6 +121,7 @@ struct plat_stmmacenet_data {
 	int bugged_jumbo;
 	int pmt;
 	int force_sf_dma_mode;
+	int riwt_off;
 	void (*fix_mac_speed)(void *priv, unsigned int speed);
 	void (*bus_setup)(void __iomem *ioaddr);
 	int (*init)(struct platform_device *pdev);
@@ -156,6 +157,7 @@ Where:
  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 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
 		 (on ST SoCs) according to the link speed negotiated by the
 		 physical layer .
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index 3b4ee53..da40efb 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -364,6 +364,9 @@ will get an pin number into its handled number range. Further it is also passed
 the range ID value, so that the pin controller knows which range it should
 deal with.
 
+Calling pinctrl_add_gpio_range from pinctrl driver is DEPRECATED. Please see
+section 2.1 of Documentation/devicetree/bindings/gpio/gpio.txt on how to bind
+pinctrl and gpio drivers.
 
 PINMUX interfaces
 =================
@@ -1193,4 +1196,6 @@ foo_switch()
 	...
 }
 
-The above has to be done from process context.
+The above has to be done from process context. The reservation of the pins
+will be done when the state is activated, so in effect one specific pin
+can be used by different functions at different times on a running system.
diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt
index 17e130a..79a2a58 100644
--- a/Documentation/power/pm_qos_interface.txt
+++ b/Documentation/power/pm_qos_interface.txt
@@ -99,7 +99,7 @@ reading the aggregated value does not require any locking mechanism.
 
 From kernel mode the use of this interface is the following:
 
-int dev_pm_qos_add_request(device, handle, value):
+int dev_pm_qos_add_request(device, handle, type, value):
 Will insert an element into the list for that identified device with the
 target value.  Upon change to this list the new target is recomputed and any
 registered notifiers are called only if the target value is now different.
diff --git a/Documentation/power/power_supply_class.txt b/Documentation/power/power_supply_class.txt
index 9c647bd..3f10b39 100644
--- a/Documentation/power/power_supply_class.txt
+++ b/Documentation/power/power_supply_class.txt
@@ -123,6 +123,9 @@ CONSTANT_CHARGE_VOLTAGE - constant charge voltage programmed by charger.
 CONSTANT_CHARGE_VOLTAGE_MAX - maximum charge voltage supported by the
 power supply object.
 
+CHARGE_CONTROL_LIMIT - current charge control limit setting
+CHARGE_CONTROL_LIMIT_MAX - maximum charge control limit setting
+
 ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
 
 CAPACITY - capacity in percents.
diff --git a/Documentation/powerpc/ptrace.txt b/Documentation/powerpc/ptrace.txt
index f4a5499..f2a7a39 100644
--- a/Documentation/powerpc/ptrace.txt
+++ b/Documentation/powerpc/ptrace.txt
@@ -127,6 +127,22 @@ Some examples of using the structure to:
   p.addr2           = (uint64_t) end_range;
   p.condition_value = 0;
 
+- set a watchpoint in server processors (BookS)
+
+  p.version         = 1;
+  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_RW;
+  p.addr_mode       = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
+  or
+  p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
+
+  p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
+  p.addr            = (uint64_t) begin_range;
+  /* For PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE addr2 needs to be specified, where
+   * addr2 - addr <= 8 Bytes.
+   */
+  p.addr2           = (uint64_t) end_range;
+  p.condition_value = 0;
+
 3. PTRACE_DELHWDEBUG
 
 Takes an integer which identifies an existing breakpoint or watchpoint
diff --git a/Documentation/prctl/seccomp_filter.txt b/Documentation/prctl/seccomp_filter.txt
index 597c3c5..1e469ef 100644
--- a/Documentation/prctl/seccomp_filter.txt
+++ b/Documentation/prctl/seccomp_filter.txt
@@ -95,12 +95,15 @@ SECCOMP_RET_KILL:
 
 SECCOMP_RET_TRAP:
 	Results in the kernel sending a SIGSYS signal to the triggering
-	task without executing the system call.  The kernel will
-	rollback the register state to just before the system call
-	entry such that a signal handler in the task will be able to
-	inspect the ucontext_t->uc_mcontext registers and emulate
-	system call success or failure upon return from the signal
-	handler.
+	task without executing the system call.  siginfo->si_call_addr
+	will show the address of the system call instruction, and
+	siginfo->si_syscall and siginfo->si_arch will indicate which
+	syscall was attempted.  The program counter will be as though
+	the syscall happened (i.e. it will not point to the syscall
+	instruction).  The return value register will contain an arch-
+	dependent value -- if resuming execution, set it to something
+	sensible.  (The architecture dependency is because replacing
+	it with -ENOSYS could overwrite some useful information.)
 
 	The SECCOMP_RET_DATA portion of the return value will be passed
 	as si_errno.
@@ -123,6 +126,18 @@ SECCOMP_RET_TRACE:
 	the BPF program return value will be available to the tracer
 	via PTRACE_GETEVENTMSG.
 
+	The tracer can skip the system call by changing the syscall number
+	to -1.  Alternatively, the tracer can change the system call
+	requested by changing the system call to a valid syscall number.  If
+	the tracer asks to skip the system call, then the system call will
+	appear to return the value that the tracer puts in the return value
+	register.
+
+	The seccomp check will not be run again after the tracer is
+	notified.  (This means that seccomp-based sandboxes MUST NOT
+	allow use of ptrace, even of other sandboxed processes, without
+	extreme care; ptracers can use this mechanism to escape.)
+
 SECCOMP_RET_ALLOW:
 	Results in the system call being executed.
 
@@ -161,3 +176,50 @@ architecture supports both ptrace_event and seccomp, it will be able to
 support seccomp filter with minor fixup: SIGSYS support and seccomp return
 value checking.  Then it must just add CONFIG_HAVE_ARCH_SECCOMP_FILTER
 to its arch-specific Kconfig.
+
+
+
+Caveats
+-------
+
+The vDSO can cause some system calls to run entirely in userspace,
+leading to surprises when you run programs on different machines that
+fall back to real syscalls.  To minimize these surprises on x86, make
+sure you test with
+/sys/devices/system/clocksource/clocksource0/current_clocksource set to
+something like acpi_pm.
+
+On x86-64, vsyscall emulation is enabled by default.  (vsyscalls are
+legacy variants on vDSO calls.)  Currently, emulated vsyscalls will honor seccomp, with a few oddities:
+
+- A return value of SECCOMP_RET_TRAP will set a si_call_addr pointing to
+  the vsyscall entry for the given call and not the address after the
+  'syscall' instruction.  Any code which wants to restart the call
+  should be aware that (a) a ret instruction has been emulated and (b)
+  trying to resume the syscall will again trigger the standard vsyscall
+  emulation security checks, making resuming the syscall mostly
+  pointless.
+
+- A return value of SECCOMP_RET_TRACE will signal the tracer as usual,
+  but the syscall may not be changed to another system call using the
+  orig_rax register. It may only be changed to -1 order to skip the
+  currently emulated call. Any other change MAY terminate the process.
+  The rip value seen by the tracer will be the syscall entry address;
+  this is different from normal behavior.  The tracer MUST NOT modify
+  rip or rsp.  (Do not rely on other changes terminating the process.
+  They might work.  For example, on some kernels, choosing a syscall
+  that only exists in future kernels will be correctly emulated (by
+  returning -ENOSYS).
+
+To detect this quirky behavior, check for addr & ~0x0C00 ==
+0xFFFFFFFFFF600000.  (For SECCOMP_RET_TRACE, use rip.  For
+SECCOMP_RET_TRAP, use siginfo->si_call_addr.)  Do not check any other
+condition: future kernels may improve vsyscall emulation and current
+kernels in vsyscall=native mode will behave differently, but the
+instructions at 0xF...F600{0,4,8,C}00 will not be system calls in these
+cases.
+
+Note that modern systems are unlikely to use vsyscalls at all -- they
+are a legacy feature and they are considerably slower than standard
+syscalls.  New code will use the vDSO, and vDSO-issued system calls
+are indistinguishable from normal system calls.
diff --git a/Documentation/scheduler/numa-problem.txt b/Documentation/scheduler/numa-problem.txt
new file mode 100644
index 0000000..7f133e3
--- /dev/null
+++ b/Documentation/scheduler/numa-problem.txt
@@ -0,0 +1,236 @@
+
+
+Effective NUMA scheduling problem statement, described formally:
+
+ * minimize interconnect traffic
+
+For each task 't_i' we have memory, this memory can be spread over multiple
+physical nodes, let us denote this as: 'p_i,k', the memory task 't_i' has on
+node 'k' in [pages].  
+
+If a task shares memory with another task let us denote this as:
+'s_i,k', the memory shared between tasks including 't_i' residing on node
+'k'.
+
+Let 'M' be the distribution that governs all 'p' and 's', ie. the page placement.
+
+Similarly, lets define 'fp_i,k' and 'fs_i,k' resp. as the (average) usage
+frequency over those memory regions [1/s] such that the product gives an
+(average) bandwidth 'bp' and 'bs' in [pages/s].
+
+(note: multiple tasks sharing memory naturally avoid duplicat accounting
+       because each task will have its own access frequency 'fs')
+
+(pjt: I think this frequency is more numerically consistent if you explicitly 
+      restrict p/s above to be the working-set. (It also makes explicit the 
+      requirement for <C0,M0> to change about a change in the working set.)
+
+      Doing this does have the nice property that it lets you use your frequency
+      measurement as a weak-ordering for the benefit a task would receive when
+      we can't fit everything.
+
+      e.g. task1 has working set 10mb, f=90%
+           task2 has working set 90mb, f=10%
+
+      Both are using 9mb/s of bandwidth, but we'd expect a much larger benefit
+      from task1 being on the right node than task2. )
+
+Let 'C' map every task 't_i' to a cpu 'c_i' and its corresponding node 'n_i':
+
+  C: t_i -> {c_i, n_i}
+
+This gives us the total interconnect traffic between nodes 'k' and 'l',
+'T_k,l', as:
+
+  T_k,l = \Sum_i bp_i,l + bs_i,l + \Sum bp_j,k + bs_j,k where n_i == k, n_j == l
+
+And our goal is to obtain C0 and M0 such that:
+
+  T_k,l(C0, M0) =< T_k,l(C, M) for all C, M where k != l
+
+(note: we could introduce 'nc(k,l)' as the cost function of accessing memory
+       on node 'l' from node 'k', this would be useful for bigger NUMA systems
+
+ pjt: I agree nice to have, but intuition suggests diminishing returns on more
+      usual systems given factors like things like Haswell's enormous 35mb l3
+      cache and QPI being able to do a direct fetch.)
+
+(note: do we need a limit on the total memory per node?)
+
+
+ * fairness
+
+For each task 't_i' we have a weight 'w_i' (related to nice), and each cpu
+'c_n' has a compute capacity 'P_n', again, using our map 'C' we can formulate a
+load 'L_n':
+
+  L_n = 1/P_n * \Sum_i w_i for all c_i = n
+
+using that we can formulate a load difference between CPUs
+
+  L_n,m = | L_n - L_m |
+
+Which allows us to state the fairness goal like:
+
+  L_n,m(C0) =< L_n,m(C) for all C, n != m
+
+(pjt: It can also be usefully stated that, having converged at C0:
+
+   | L_n(C0) - L_m(C0) | <= 4/3 * | G_n( U(t_i, t_j) ) - G_m( U(t_i, t_j) ) |
+
+      Where G_n,m is the greedy partition of tasks between L_n and L_m. This is
+      the "worst" partition we should accept; but having it gives us a useful 
+      bound on how much we can reasonably adjust L_n/L_m at a Pareto point to 
+      favor T_n,m. )
+
+Together they give us the complete multi-objective optimization problem:
+
+  min_C,M [ L_n,m(C), T_k,l(C,M) ]
+
+
+
+Notes:
+
+ - the memory bandwidth problem is very much an inter-process problem, in
+   particular there is no such concept as a process in the above problem.
+
+ - the naive solution would completely prefer fairness over interconnect
+   traffic, the more complicated solution could pick another Pareto point using
+   an aggregate objective function such that we balance the loss of work
+   efficiency against the gain of running, we'd want to more or less suggest
+   there to be a fixed bound on the error from the Pareto line for any
+   such solution.
+
+References:
+
+  http://en.wikipedia.org/wiki/Mathematical_optimization
+  http://en.wikipedia.org/wiki/Multi-objective_optimization
+
+
+* warning, significant hand-waving ahead, improvements welcome *
+
+
+Partial solutions / approximations:
+
+ 1) have task node placement be a pure preference from the 'fairness' pov.
+
+This means we always prefer fairness over interconnect bandwidth. This reduces
+the problem to:
+
+  min_C,M [ T_k,l(C,M) ]
+
+ 2a) migrate memory towards 'n_i' (the task's node).
+
+This creates memory movement such that 'p_i,k for k != n_i' becomes 0 -- 
+provided 'n_i' stays stable enough and there's sufficient memory (looks like
+we might need memory limits for this).
+
+This does however not provide us with any 's_i' (shared) information. It does
+however remove 'M' since it defines memory placement in terms of task
+placement.
+
+XXX properties of this M vs a potential optimal
+
+ 2b) migrate memory towards 'n_i' using 2 samples.
+
+XXX include the statistical babble on double sampling somewhere near
+
+This separates pages into those that will migrate and those that will not due
+to the two samples not matching. We could consider the first to be of 'p_i'
+(private) and the second to be of 's_i' (shared).
+
+This interpretation can be motivated by the previously observed property that
+'p_i,k for k != n_i' should become 0 under sufficient memory, leaving only
+'s_i' (shared). (here we loose the need for memory limits again, since it
+becomes indistinguishable from shared).
+
+ 2c) use cpu samples instead of node samples
+
+The problem with sampling on node granularity is that one looses 's_i' for
+the local node, since one cannot distinguish between two accesses from the
+same node.
+
+By increasing the granularity to per-cpu we gain the ability to have both an
+'s_i' and 'p_i' per node. Since we do all task placement per-cpu as well this
+seems like a natural match. The line where we overcommit cpus is where we loose
+granularity again, but when we loose overcommit we naturally spread tasks.
+Therefore it should work out nicely.
+
+This reduces the problem further; we loose 'M' as per 2a, it further reduces
+the 'T_k,l' (interconnect traffic) term to only include shared (since per the
+above all private will be local):
+
+  T_k,l = \Sum_i bs_i,l for every n_i = k, l != k
+
+Motivated by the form of 'T_k,l', try and obtain each term of the sum, so we
+can evaluate it;
+
+ 3a) add per-task per node counters
+
+At fault time, count the number of pages the task faults on for each node.
+This should give an approximation of 'p_i' for the local node and 's_i,k' for
+all remote nodes.
+
+While these numbers provide pages per scan, and so have the unit [pages/s] they
+don't count repeat access and thus aren't actually representable for our
+bandwidth numberes.
+
+ 3b) additional frequency term
+
+Additionally (or instead if it turns out we don't need the raw 'p' and 's' 
+numbers) we can approximate the repeat accesses by using the time since marking
+the pages as indication of the access frequency.
+
+Let 'I' be the interval of marking pages and 'e' the elapsed time since the
+last marking, then we could estimate the number of accesses 'a' as 'a = I / e'.
+If we then increment the node counters using 'a' instead of 1 we might get
+a better estimate of bandwidth terms.
+
+ 3c) additional averaging; can be applied on top of either a/b.
+
+[ Rik argues that decaying averages on 3a might be sufficient for bandwidth since
+  the decaying avg includes the old accesses and therefore has a measure of repeat
+  accesses.
+
+  Rik also argued that the sample frequency is too low to get accurate access
+  frequency measurements, I'm not entirely convinced, event at low sample 
+  frequencies the avg elapsed time 'e' over multiple samples should still
+  give us a fair approximation of the avg access frequency 'a'.
+
+  So doing both b&c has a fair chance of working and allowing us to distinguish
+  between important and less important memory accesses.
+
+  Experimentation has shown no benefit from the added frequency term so far. ]
+
+This will give us 'bp_i' and 'bs_i,k' so that we can approximately compute
+'T_k,l' Our optimization problem now reads:
+
+  min_C [ \Sum_i bs_i,l for every n_i = k, l != k ]
+
+And includes only shared terms, this makes sense since all task private memory
+will become local as per 2.
+
+This suggests that if there is significant shared memory, we should try and
+move towards it.
+
+ 4) move towards where 'most' memory is
+
+The simplest significance test is comparing the biggest shared 's_i,k' against
+the private 'p_i'. If we have more shared than private, move towards it.
+
+This effectively makes us move towards where most our memory is and forms a
+feed-back loop with 2. We migrate memory towards us and we migrate towards
+where 'most' memory is.
+
+(Note: even if there were two tasks fully trashing the same shared memory, it
+       is very rare for there to be an 50/50 split in memory, lacking a perfect
+       split, the small will move towards the larger. In case of the perfect
+       split, we'll tie-break towards the lower node number.)
+
+ 5) 'throttle' 4's node placement
+
+Since per 2b our 's_i,k' and 'p_i' require at least two scans to 'stabilize'
+and show representative numbers, we should limit node-migration to not be
+faster than this.
+
+ n) poke holes in previous that require more stuff and describe it.
diff --git a/Documentation/scsi/hptiop.txt b/Documentation/scsi/hptiop.txt
index 9605179..4a4f47e 100644
--- a/Documentation/scsi/hptiop.txt
+++ b/Documentation/scsi/hptiop.txt
@@ -37,7 +37,7 @@ For Intel IOP based adapters, the controller IOP is accessed via PCI BAR0:
             0x40    Inbound Queue Port
             0x44    Outbound Queue Port
 
-For Marvell IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1:
+For Marvell not Frey IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1:
 
      BAR0 offset    Register
          0x20400    Inbound Doorbell Register
@@ -55,9 +55,31 @@ For Marvell IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1:
      0x40-0x1040    Inbound Queue
    0x1040-0x2040    Outbound Queue
 
+For Marvell Frey IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1:
 
-I/O Request Workflow
-----------------------
+     BAR0 offset    Register
+             0x0    IOP configuration information.
+
+     BAR1 offset    Register
+          0x4000    Inbound List Base Address Low
+          0x4004    Inbound List Base Address High
+          0x4018    Inbound List Write Pointer
+          0x402C    Inbound List Configuration and Control
+          0x4050    Outbound List Base Address Low
+          0x4054    Outbound List Base Address High
+          0x4058    Outbound List Copy Pointer Shadow Base Address Low
+          0x405C    Outbound List Copy Pointer Shadow Base Address High
+          0x4088    Outbound List Interrupt Cause
+          0x408C    Outbound List Interrupt Enable
+         0x1020C    PCIe Function 0 Interrupt Enable
+         0x10400    PCIe Function 0 to CPU Message A
+         0x10420    CPU to PCIe Function 0 Message A
+         0x10480    CPU to PCIe Function 0 Doorbell
+         0x10484    CPU to PCIe Function 0 Doorbell Enable
+
+
+I/O Request Workflow of Not Marvell Frey
+------------------------------------------
 
 All queued requests are handled via inbound/outbound queue port.
 A request packet can be allocated in either IOP or host memory.
@@ -101,6 +123,45 @@ register 0. An outbound message with the same value indicates the completion
 of an inbound message.
 
 
+I/O Request Workflow of Marvell Frey
+--------------------------------------
+
+All queued requests are handled via inbound/outbound list.
+
+To send a request to the controller:
+
+    - Allocate a free request in host DMA coherent memory.
+
+      Requests allocated in host memory must be aligned on 32-bytes boundary.
+
+    - Fill the request with index of the request in the flag.
+
+      Fill a free inbound list unit with the physical address and the size of
+      the request.
+
+      Set up the inbound list write pointer with the index of previous unit,
+      round to 0 if the index reaches the supported count of requests.
+
+    - Post the inbound list writer pointer to IOP.
+
+    - The IOP process the request. When the request is completed, the flag of
+      the request with or-ed IOPMU_QUEUE_MASK_HOST_BITS will be put into a
+      free outbound list unit and the index of the outbound list unit will be
+      put into the copy pointer shadow register. An outbound interrupt will be
+      generated.
+
+    - The host read the outbound list copy pointer shadow register and compare
+      with previous saved read ponter N. If they are different, the host will
+      read the (N+1)th outbound list unit.
+
+      The host get the index of the request from the (N+1)th outbound list
+      unit and complete the request.
+
+Non-queued requests (reset communication/reset/flush etc) can be sent via PCIe
+Function 0 to CPU Message A register. The CPU to PCIe Function 0 Message register
+with the same value indicates the completion of message.
+
+
 User-level Interface
 ---------------------
 
@@ -112,7 +173,7 @@ The driver exposes following sysfs attributes:
 
 
 -----------------------------------------------------------------------------
-Copyright (C) 2006-2009 HighPoint Technologies, Inc. All Rights Reserved.
+Copyright (C) 2006-2012 HighPoint Technologies, Inc. All Rights Reserved.
 
   This file is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/Documentation/security/00-INDEX b/Documentation/security/00-INDEX
index eeed1de..414235c 100644
--- a/Documentation/security/00-INDEX
+++ b/Documentation/security/00-INDEX
@@ -12,6 +12,8 @@ apparmor.txt
 	- documentation on the AppArmor security extension.
 credentials.txt
 	- documentation about credentials in Linux.
+keys-ecryptfs.txt
+	- description of the encryption keys for the ecryptfs filesystem.
 keys-request-key.txt
 	- description of the kernel key request service.
 keys-trusted-encrypted.txt
diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
index 7d9ca92..7b4145d 100644
--- a/Documentation/security/keys.txt
+++ b/Documentation/security/keys.txt
@@ -994,6 +994,23 @@ payload contents" for more information.
     reference pointer if successful.
 
 
+(*) A keyring can be created by:
+
+	struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
+				  const struct cred *cred,
+				  key_perm_t perm,
+				  unsigned long flags,
+				  struct key *dest);
+
+    This creates a keyring with the given attributes and returns it.  If dest
+    is not NULL, the new keyring will be linked into the keyring to which it
+    points.  No permission checks are made upon the destination keyring.
+
+    Error EDQUOT can be returned if the keyring would overload the quota (pass
+    KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted
+    towards the user's quota).  Error ENOMEM can also be returned.
+
+
 (*) To check the validity of a key, this function can be called:
 
 	int validate_key(struct key *key);
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index d90d8ec..b9cfd33 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -1905,7 +1905,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     vid             - Vendor ID for the device (optional)
     pid             - Product ID for the device (optional)
     nrpacks	    - Max. number of packets per URB (default: 8)
-    async_unlink    - Use async unlink mode (default: yes)
     device_setup    - Device specific magic number (optional)
                     - Influence depends on the device
                     - Default: 0x0000 
@@ -1917,8 +1916,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     NB: nrpacks parameter can be modified dynamically via sysfs.
         Don't put the value over 20.  Changing via sysfs has no sanity
 	check.
-    NB: async_unlink=0 would cause Oops.  It remains just for
-        debugging purpose (if any).
     NB: ignore_ctl_error=1 may help when you get an error at accessing
         the mixer element such as URB error -22.  This happens on some
         buggy USB device or the controller.
diff --git a/Documentation/sparse.txt b/Documentation/sparse.txt
index 4909d41..eceab13 100644
--- a/Documentation/sparse.txt
+++ b/Documentation/sparse.txt
@@ -49,6 +49,24 @@ be generated without __CHECK_ENDIAN__.
 __bitwise - noisy stuff; in particular, __le*/__be* are that.  We really
 don't want to drown in noise unless we'd explicitly asked for it.
 
+Using sparse for lock checking
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following macros are undefined for gcc and defined during a sparse
+run to use the "context" tracking feature of sparse, applied to
+locking.  These annotations tell sparse when a lock is held, with
+regard to the annotated function's entry and exit.
+
+__must_hold - The specified lock is held on function entry and exit.
+
+__acquires - The specified lock is held on function exit, but not entry.
+
+__releases - The specified lock is held on function entry, but not exit.
+
+If the function enters and exits without the lock held, acquiring and
+releasing the lock inside the function in a balanced way, no
+annotation is needed.  The tree annotations above are for cases where
+sparse would otherwise report a context imbalance.
 
 Getting sparse
 ~~~~~~~~~~~~~~
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 2907ba6..ccd4258 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -38,6 +38,7 @@ show up in /proc/sys/kernel:
 - l2cr                        [ PPC only ]
 - modprobe                    ==> Documentation/debugging-modules.txt
 - modules_disabled
+- msg_next_id		      [ sysv ipc ]
 - msgmax
 - msgmnb
 - msgmni
@@ -62,7 +63,9 @@ show up in /proc/sys/kernel:
 - rtsig-max
 - rtsig-nr
 - sem
+- sem_next_id		      [ sysv ipc ]
 - sg-big-buff                 [ generic SCSI device (sg) ]
+- shm_next_id		      [ sysv ipc ]
 - shm_rmid_forced
 - shmall
 - shmmax                      [ sysv ipc ]
@@ -320,6 +323,22 @@ to false.
 
 ==============================================================
 
+msg_next_id, sem_next_id, and shm_next_id:
+
+These three toggles allows to specify desired id for next allocated IPC
+object: message, semaphore or shared memory respectively.
+
+By default they are equal to -1, which means generic allocation logic.
+Possible values to set are in range {0..INT_MAX}.
+
+Notes:
+1) kernel doesn't guarantee, that new object will have desired id. So,
+it's up to userspace, how to handle an object with "wrong" id.
+2) Toggle with non-default value will be set back to -1 by kernel after
+successful IPC object allocation.
+
+==============================================================
+
 nmi_watchdog:
 
 Enables/Disables the NMI watchdog on x86 systems. When the value is
@@ -542,6 +561,19 @@ are doing anyway :)
 
 ==============================================================
 
+shmall:
+
+This parameter sets the total amount of shared memory pages that
+can be used system wide. Hence, SHMALL should always be at least
+ceil(shmmax/PAGE_SIZE).
+
+If you are not sure what the default PAGE_SIZE is on your Linux
+system, you can run the following command:
+
+# getconf PAGE_SIZE
+
+==============================================================
+
 shmmax:
 
 This value can be used to query and set the run time limit
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 078701f..21ad181 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -138,18 +138,39 @@ Setting this to zero disables periodic writeback altogether.
 
 drop_caches
 
-Writing to this will cause the kernel to drop clean caches, dentries and
-inodes from memory, causing that memory to become free.
+Writing to this will cause the kernel to drop clean caches, as well as
+reclaimable slab objects like dentries and inodes.  Once dropped, their
+memory becomes free.
 
 To free pagecache:
 	echo 1 > /proc/sys/vm/drop_caches
-To free dentries and inodes:
+To free reclaimable slab objects (includes dentries and inodes):
 	echo 2 > /proc/sys/vm/drop_caches
-To free pagecache, dentries and inodes:
+To free slab objects and pagecache:
 	echo 3 > /proc/sys/vm/drop_caches
 
-As this is a non-destructive operation and dirty objects are not freeable, the
-user should run `sync' first.
+This is a non-destructive operation and will not free any dirty objects.
+To increase the number of objects freed by this operation, the user may run
+`sync' prior to writing to /proc/sys/vm/drop_caches.  This will minimize the
+number of dirty objects on the system and create more candidates to be
+dropped.
+
+This file is not a means to control the growth of the various kernel caches
+(inodes, dentries, pagecache, etc...)  These objects are automatically
+reclaimed by the kernel when memory is needed elsewhere on the system.
+
+Use of this file can cause performance problems.  Since it discards cached
+objects, it may cost a significant amount of I/O and CPU to recreate the
+dropped objects, especially if they were under heavy use.  Because of this,
+use outside of a testing or debugging environment is not recommended.
+
+You may see informational messages in your kernel log when this file is
+used:
+
+	cat (1234): dropped kernel caches: 3
+
+These are informational only.  They do not mean that anything is wrong
+with your system.
 
 ==============================================================
 
diff --git a/Documentation/telephony/00-INDEX b/Documentation/telephony/00-INDEX
deleted file mode 100644
index 4ffe0ed..0000000
--- a/Documentation/telephony/00-INDEX
+++ /dev/null
@@ -1,4 +0,0 @@
-00-INDEX
-	- this file.
-ixj.txt
-	- document describing the Quicknet drivers.
diff --git a/Documentation/telephony/ixj.txt b/Documentation/telephony/ixj.txt
deleted file mode 100644
index db94fb6..0000000
--- a/Documentation/telephony/ixj.txt
+++ /dev/null
@@ -1,394 +0,0 @@
-Linux Quicknet-Drivers-Howto
-Quicknet Technologies, Inc. (www.quicknet.net)
-Version 0.3.4  December 18, 1999
-
-1.0  Introduction
-
-This document describes the first GPL release version of the Linux
-driver for the Quicknet Internet PhoneJACK and Internet LineJACK
-cards.  More information about these cards is available at
-www.quicknet.net.  The driver version discussed in this document is
-0.3.4.
-
-These cards offer nice telco style interfaces to use your standard
-telephone/key system/PBX as the user interface for VoIP applications.
-The Internet LineJACK also offers PSTN connectivity for a single line
-Internet to PSTN gateway.  Of course, you can add more than one card
-to a system to obtain multi-line functionality.  At this time, the
-driver supports the POTS port on both the Internet PhoneJACK and the
-Internet LineJACK, but the PSTN port on the latter card is not yet
-supported.
-
-This document, and the drivers for the cards, are intended for a
-limited audience that includes technically capable programmers who
-would like to experiment with Quicknet cards.  The drivers are
-considered in ALPHA status and are not yet considered stable enough
-for general, widespread use in an unlimited audience.
-
-That's worth saying again:
-
-THE LINUX DRIVERS FOR QUICKNET CARDS ARE PRESENTLY IN A ALPHA STATE
-AND SHOULD NOT BE CONSIDERED AS READY FOR NORMAL WIDESPREAD USE.
-
-They are released early in the spirit of Internet development and to
-make this technology available to innovators who would benefit from
-early exposure.
-
-When we promote the device driver to "beta" level it will be
-considered ready for non-programmer, non-technical users.  Until then,
-please be aware that these drivers may not be stable and may affect
-the performance of your system.
-
-
-1.1 Latest Additions/Improvements
-
-The 0.3.4 version of the driver is the first GPL release.  Several
-features had to be removed from the prior binary only module, mostly
-for reasons of Intellectual Property rights.  We can't release
-information that is not ours - so certain aspects of the driver had to
-be removed to protect the rights of others.  
-
-Specifically, very old Internet PhoneJACK cards have non-standard
-G.723.1 codecs (due to the early nature of the DSPs in those days).
-The auto-conversion code to bring those cards into compliance with
-today's standards is available as a binary only module to those people
-needing it.  If you bought your card after 1997 or so, you are OK -
-it's only the very old cards that are affected.
-
-Also, the code to download G.728/G.729/G.729a codecs to the DSP is
-available as a binary only module as well.  This IP is not ours to
-release.  
-
-Hooks are built into the GPL driver to allow it to work with other
-companion modules that are completely separate from this module.
-
-1.2 Copyright, Trademarks, Disclaimer, & Credits 
-
-Copyright
-
-Copyright (c) 1999 Quicknet Technologies, Inc.  Permission is granted
-to freely copy and distribute this document provided you preserve it
-in its original form. For corrections and minor changes contact the
-maintainer at linux@quicknet.net.
-
-Trademarks
-
-Internet PhoneJACK and Internet LineJACK are registered trademarks of
-Quicknet Technologies, Inc.
-
-Disclaimer
-
-Much of the info in this HOWTO is early information released by
-Quicknet Technologies, Inc. for the express purpose of allowing early
-testing and use of the Linux drivers developed for their products.
-While every attempt has been made to be thorough, complete and
-accurate, the information contained here may be unreliable and there
-are likely a number of errors in this document. Please let the
-maintainer know about them. Since this is free documentation, it
-should be obvious that neither I nor previous authors can be held
-legally responsible for any errors.
-
-Credits
-
-This HOWTO was written by:
-
-	Greg Herlein <gherlein@quicknet.net>
-	Ed Okerson <eokerson@quicknet.net> 
-
-1.3  Future Plans: You Can Help 
-
-Please let the maintainer know of any errors in facts, opinions,
-logic, spelling, grammar, clarity, links, etc.  But first, if the date
-is over a month old, check to see that you have the latest
-version. Please send any info that you think belongs in this document.
-
-You can also contribute code and/or bug-fixes for the sample
-applications.
-
-
-1.4  Where to get things
-
-Info on latest versions of the driver are here:
-
-http://web.archive.org/web/*/http://www.quicknet.net/develop.htm
-
-1.5  Mailing List
-
-Quicknet operates a mailing list to provide a public forum on using
-these drivers.
-
-To subscribe to the linux-sdk mailing list, send an email to:
-
-   majordomo@linux.quicknet.net
-
-In the body of the email, type:
-
-   subscribe linux-sdk <your-email-address>
-
-Please delete any signature block that you would normally add to the
-bottom of your email - it tends to confuse majordomo.
-
-To send mail to the list, address your mail to 
-
-   linux-sdk@linux.quicknet.net
-
-Your message will go out to everyone on the list.
-
-To unsubscribe to the linux-sdk mailing list, send an email to:
-
-   majordomo@linux.quicknet.net
-
-In the body of the email, type:
-
-   unsubscribe linux-sdk <your-email-address>
-
-
-
-2.0  Requirements
-
-2.1  Quicknet Card(s)
-
-You will need at least one Internet PhoneJACK or Internet LineJACK
-cards.  These are ISA or PCI bus devices that use Plug-n-Play for
-configuration, and use no IRQs.  The driver will support up to 16
-cards in any one system, of any mix between the two types.
-
-Note that you will need two cards to do any useful testing alone, since
-you will need a card on both ends of the connection.  Of course, if
-you are doing collaborative work, perhaps your friends or coworkers
-have cards too.  If not, we'll gladly sell them some!
-
-
-2.2  ISAPNP
-
-Since the Quicknet cards are Plug-n-Play devices, you will need the
-isapnp tools package to configure the cards, or you can use the isapnp
-module to autoconfigure them.  The former package probably came with
-your Linux distribution.  Documentation on this package is available
-online at:
-
-http://mailer.wiwi.uni-marburg.de/linux/LDP/HOWTO/Plug-and-Play-HOWTO.html
-
-The isapnp autoconfiguration is available on the Quicknet website at:
-
-    http://www.quicknet.net/develop.htm
-
-though it may be in the kernel by the time you read this.
-
-
-3.0  Card Configuration 
-
-If you did not get your drivers as part of the linux kernel, do the
-following to install them:
-
-   a.  untar the distribution file.  We use the following command:
-        tar -xvzf ixj-0.x.x.tgz
-
-This creates a subdirectory holding all the necessary files.  Go to that
-subdirectory.
-
-   b.  run the "ixj_dev_create" script to remove any stray device
-files left in the /dev directory, and to create the new officially
-designated device files.  Note that the old devices were called 
-/dev/ixj, and the new method uses /dev/phone.  
-
-   c.  type "make;make install" - this will compile and install the
-module.
-
-   d.  type "depmod -av" to rebuild all your kernel version dependencies.
-
-   e.  if you are using the isapnp module to configure the cards
-       automatically, then skip to step f.  Otherwise, ensure that you
-       have run the isapnp configuration utility to properly configure
-       the cards.
-
-       e1. The Internet PhoneJACK has one configuration register that
-           requires 16 IO ports.  The Internet LineJACK card has two
-           configuration registers and isapnp reports that IO 0
-           requires 16 IO ports and IO 1 requires 8.  The Quicknet
-           driver assumes that these registers are configured to be
-           contiguous, i.e. if IO 0 is set to 0x340 then IO 1 should
-           be set to 0x350.
-
-           Make sure that none of the cards overlap if you have
-           multiple cards in the system.
-
-           If you are new to the isapnp tools, you can jumpstart
-           yourself by doing the following:
-
-      e2.  go to the /etc directory and run pnpdump to get a blank
-           isapnp.conf file.
-
-	   	pnpdump > /etc/isapnp.conf
-
-      e3.  edit the /etc/isapnp.conf file to set the IO warnings and
-           the register IO addresses. The IO warnings means that you
-           should find the line in the file that looks like this:
-
-	   (CONFLICT (IO FATAL)(IRQ FATAL)(DMA FATAL)(MEM FATAL)) # or WARNING
-
-	   and you should edit the line to look like this:
-
-	   (CONFLICT (IO WARNING)(IRQ FATAL)(DMA FATAL)(MEM FATAL)) #
-	   or WARNING
-
-           The next step is to set the IO port addresses.  The issue
-           here is that isapnp does not identify all of the ports out
-           there.  Specifically any device that does not have a driver
-           or module loaded by Linux will not be registered.  This
-           includes older sound cards and network cards.  We have
-           found that the IO port 0x300 is often used even though
-           isapnp claims that no-one is using those ports.  We
-           recommend that for a single card installation that port
-           0x340 (and 0x350) be used.  The IO port line should change
-           from this:
-
-	   (IO 0 (SIZE 16) (BASE 0x0300) (CHECK))
-
-	   to this:
-
-	   (IO 0 (SIZE 16) (BASE 0x0340) )
-
-       e4.  if you have multiple Quicknet cards, make sure that you do
-            not have any overlaps.  Be especially careful if you are
-            mixing Internet PhoneJACK and Internet LineJACK cards in
-            the same system.  In these cases we recommend moving the
-            IO port addresses to the 0x400 block.  Please note that on
-            a few machines the 0x400 series are used.  Feel free to
-            experiment with other addresses.  Our cards have been
-            proven to work using IO addresses of up to 0xFF0.
-
-       e5.  the last step is to uncomment the activation line so the
-            drivers will be associated with the port.  This means the
-            line (immediately below) the IO line should go from this:
-
-            # (ACT Y)
-
-            to this:
-
-	    (ACT Y)
-
-            Once you have finished editing the isapnp.conf file you
-            must submit it into the pnp driverconfigure the cards.
-            This is done using the following command:
-
-	    isapnp isapnp.conf
-
-	    If this works you should see a line that identifies the
-            Quicknet device, the IO port(s) chosen, and a message
-            "Enabled OK".
-
-   f.  if you are loading the module by hand, use insmod.  An example
-of this would look like this:
-
-	insmod phonedev
-	insmod ixj dspio=0x320,0x310 xio=0,0x330
-
-Then verify the module loaded by running lsmod. If you are not using a
-module that matches your kernel version, you may need to "force" the
-load using the -f option in the insmod command.
-
-	insmod phonedev
-	insmod -f ixj dspio=0x320,0x310 xio=0,0x330
-
-
-If you are using isapnp to autoconfigure your card, then you do NOT
-need any of the above, though you need to use depmod to load the
-driver, like this:
-
-	depmod ixj
-
-which will result in the needed drivers getting loaded automatically.
-
-   g.  if you are planning on having the kernel automatically request
-the module for you, then you need to edit /etc/conf.modules and add the
-following lines:
-
-	options ixj dspio=0x340 xio=0x330 ixjdebug=0
-
-If you do this, then when you execute an application that uses the
-module the kernel will request that it is loaded.
-
-  h.  if you want non-root users to be able to read and write to the 
-ixj devices (this is a good idea!) you should do the following:
-
-     - decide upon a group name to use and create that group if 
-       needed.  Add the user names to that group that you wish to 
-       have access to the device.  For example, we typically will
-       create a group named "ixj" in /etc/group and add all users
-       to that group that we want to run software that can use the 
-       ixjX devices.
-
-     - change the permissions on the device files, like this:
-	
-       chgrp ixj /dev/ixj*	
-       chmod 660 /dev/ixj*
-	
-Once this is done, then non-root users should be able to use the
-devices.  If you have enabled autoloading of modules, then the user
-should be able to open the device and have the module loaded
-automatically for them.
-
-
-4.0 Driver Installation problems.
-
-We have tested these drivers on the 2.2.9, 2.2.10, 2.2.12, and 2.2.13 kernels
-and in all cases have eventually been able to get the drivers to load and 
-run.  We have found four types of problems that prevent this from happening.
-The problems and solutions are:
-
-  a. A step was missed in the installation.  Go back and use section 3
-as a checklist.  Many people miss running the ixj_dev_create script and thus
-never load the device names into the filesystem.
-
-  b. The kernel is inconsistently linked.  We have found this problem in
-the Out Of the Box installation of several distributions.  The symptoms 
-are that neither driver will load, and that the unknown symbols include "jiffy"
-and "kmalloc".  The solution is to recompile both the kernel and the
-modules.  The command string for the final compile looks like this:
-
-    In the kernel directory:
-    1.  cp .config /tmp
-    2.  make mrproper
-    3.  cp /tmp/.config .
-    4.	make clean;make bzImage;make modules;make modules_install
-
-This rebuilds both the kernel and all the modules and makes sure they all 
-have the same linkages.  This generally solves the problem once the new 
-kernel is installed and the system rebooted.
-
-  c. The kernel has been patched, then unpatched.  This happens when
-someone decides to use an earlier kernel after they load a later kernel.
-The symptoms are proceeding through all three above steps and still not
-being able to load the driver.  What has happened is that the generated
-header files are out of sync with the kernel itself.  The solution is
-to recompile (again) using "make mrproper".  This will remove and then
-regenerate all the necessary header files.  Once this is done, then you 
-need to install and reboot the kernel.  We have not seen any problem
-loading one of our drivers after this treatment.
-
-5.0  Known Limitations
-
-We cannot currently play "dial-tone" and listen for DTMF digits at the
-same time using the ISA PhoneJACK.  This is a bug in the 8020 DSP chip
-used on that product.  All other Quicknet products function normally
-in this regard.  We have a work-around, but it's not done yet.  Until
-then, if you want dial-tone, you can always play a recorded dial-tone
-sound into the audio until you have gathered the DTMF digits.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index ca1a1a3..88c0233 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -112,6 +112,29 @@ temperature) and throttle appropriate devices.
     trip: indicates which trip point the cooling devices is associated with
 	  in this thermal zone.
 
+1.4 Thermal Zone Parameters
+1.4.1 struct thermal_bind_params
+    This structure defines the following parameters that are used to bind
+    a zone with a cooling device for a particular trip point.
+    .cdev: The cooling device pointer
+    .weight: The 'influence' of a particular cooling device on this zone.
+             This is on a percentage scale. The sum of all these weights
+             (for a particular zone) cannot exceed 100.
+    .trip_mask:This is a bit mask that gives the binding relation between
+               this thermal zone and cdev, for a particular trip point.
+               If nth bit is set, then the cdev and thermal zone are bound
+               for trip point n.
+    .match: This call back returns success(0) if the 'tz and cdev' need to
+	    be bound, as per platform data.
+1.4.2 struct thermal_zone_params
+    This structure defines the platform level parameters for a thermal zone.
+    This data, for each thermal zone should come from the platform layer.
+    This is an optional feature where some platforms can choose not to
+    provide this data.
+    .governor_name: Name of the thermal governor used for this zone
+    .num_tbps: Number of thermal_bind_params entries for this zone
+    .tbp: thermal_bind_params entries
+
 2. sysfs attributes structure
 
 RO	read only value
@@ -126,6 +149,7 @@ Thermal zone device sys I/F, created once it's registered:
     |---type:			Type of the thermal zone
     |---temp:			Current temperature
     |---mode:			Working mode of the thermal zone
+    |---policy:			Thermal governor used for this zone
     |---trip_point_[0-*]_temp:	Trip point temperature
     |---trip_point_[0-*]_type:	Trip point type
     |---trip_point_[0-*]_hyst:	Hysteresis value for this trip point
@@ -187,6 +211,10 @@ mode
 			  charge of the thermal management.
 	RW, Optional
 
+policy
+	One of the various thermal governors used for a particular zone.
+	RW, Required
+
 trip_point_[0-*]_temp
 	The temperature above which trip point will be fired.
 	Unit: millidegree Celsius
@@ -264,6 +292,7 @@ method, the sys I/F structure will be built like this:
     |---type:			acpitz
     |---temp:			37000
     |---mode:			enabled
+    |---policy:			step_wise
     |---trip_point_0_temp:	100000
     |---trip_point_0_type:	critical
     |---trip_point_1_temp:	80000
@@ -305,3 +334,38 @@ to a thermal_zone_device when it registers itself with the framework. The
 event will be one of:{THERMAL_AUX0, THERMAL_AUX1, THERMAL_CRITICAL,
 THERMAL_DEV_FAULT}. Notification can be sent when the current temperature
 crosses any of the configured thresholds.
+
+5. Export Symbol APIs:
+
+5.1: get_tz_trend:
+This function returns the trend of a thermal zone, i.e the rate of change
+of temperature of the thermal zone. Ideally, the thermal sensor drivers
+are supposed to implement the callback. If they don't, the thermal
+framework calculated the trend by comparing the previous and the current
+temperature values.
+
+5.2:get_thermal_instance:
+This function returns the thermal_instance corresponding to a given
+{thermal_zone, cooling_device, trip_point} combination. Returns NULL
+if such an instance does not exist.
+
+5.3:notify_thermal_framework:
+This function handles the trip events from sensor drivers. It starts
+throttling the cooling devices according to the policy configured.
+For CRITICAL and HOT trip points, this notifies the respective drivers,
+and does actual throttling for other trip points i.e ACTIVE and PASSIVE.
+The throttling policy is based on the configured platform data; if no
+platform data is provided, this uses the step_wise throttling policy.
+
+5.4:thermal_cdev_update:
+This function serves as an arbitrator to set the state of a cooling
+device. It sets the cooling device to the deepest cooling state if
+possible.
+
+5.5:thermal_register_governor:
+This function lets the various thermal governors to register themselves
+with the Thermal framework. At run time, depending on a zone's platform
+data, a particular governor is used for throttling.
+
+5.6:thermal_unregister_governor:
+This function unregisters a governor from the thermal framework.
diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt
index b3f606b..9c3eb84 100644
--- a/Documentation/usb/error-codes.txt
+++ b/Documentation/usb/error-codes.txt
@@ -21,6 +21,8 @@ Non-USB-specific:
 
 USB-specific:
 
+-EBUSY		The URB is already active.
+
 -ENODEV		specified USB-device or bus doesn't exist
 
 -ENOENT		specified interface or endpoint does not exist or
@@ -35,9 +37,8 @@ USB-specific:
 		d) ISO: number_of_packets is < 0
 		e) various other cases
 
--EAGAIN		a) specified ISO start frame too early
-		b) (using ISO-ASAP) too much scheduled for the future
-		   wait some time and try again.
+-EXDEV		ISO: URB_ISO_ASAP wasn't specified and all the frames
+		the URB would be scheduled in have already expired.
 
 -EFBIG		Host controller driver can't schedule that many ISO frames.
 
diff --git a/Documentation/usb/mass-storage.txt b/Documentation/usb/mass-storage.txt
index e9b9334..59063ad 100644
--- a/Documentation/usb/mass-storage.txt
+++ b/Documentation/usb/mass-storage.txt
@@ -20,9 +20,9 @@
 
   This document describes how to use the gadget from user space, its
   relation to mass storage function (or MSF) and different gadgets
-  using it, and how it differs from File Storage Gadget (or FSG).  It
-  will talk only briefly about how to use MSF within composite
-  gadgets.
+  using it, and how it differs from File Storage Gadget (or FSG)
+  (which is no longer included in Linux).  It will talk only briefly
+  about how to use MSF within composite gadgets.
 
 * Module parameters
 
@@ -198,16 +198,15 @@
   The Mass Storage Function and thus the Mass Storage Gadget has been
   based on the File Storage Gadget.  The difference between the two is
   that MSG is a composite gadget (ie. uses the composite framework)
-  while file storage gadget is a traditional gadget.  From userspace
+  while file storage gadget was a traditional gadget.  From userspace
   point of view this distinction does not really matter, but from
   kernel hacker's point of view, this means that (i) MSG does not
   duplicate code needed for handling basic USB protocol commands and
   (ii) MSF can be used in any other composite gadget.
 
-  Because of that, File Storage Gadget has been deprecated and
-  scheduled to be removed in Linux 3.8.  All users need to transition
-  to the Mass Storage Gadget by that time.  The two gadgets behave
-  mostly the same from the outside except:
+  Because of that, File Storage Gadget has been removed in Linux 3.8.
+  All users need to transition to the Mass Storage Gadget.  The two
+  gadgets behave mostly the same from the outside except:
 
   1. In FSG the “removable” and “cdrom” module parameters set the flag
      for all logical units whereas in MSG they accept a list of y/n
diff --git a/Documentation/video4linux/bttv/Cards b/Documentation/video4linux/bttv/Cards
index db833ce..a8fb6e2 100644
--- a/Documentation/video4linux/bttv/Cards
+++ b/Documentation/video4linux/bttv/Cards
@@ -43,7 +43,7 @@ Very nice card if you only have satellite TV but several tuners connected
 to the card via composite.
 
 Many thanks to Matrix-Vision for giving us 2 cards for free which made
-Bt848a/Bt849 single crytal operation support possible!!!
+Bt848a/Bt849 single crystal operation support possible!!!
 
 
 
diff --git a/Documentation/video4linux/bttv/Sound-FAQ b/Documentation/video4linux/bttv/Sound-FAQ
index 395f6c6..d3f1d77 100644
--- a/Documentation/video4linux/bttv/Sound-FAQ
+++ b/Documentation/video4linux/bttv/Sound-FAQ
@@ -82,7 +82,7 @@ card installed, you might to check out if you can read these registers
 values used by the windows driver.  A tool to do this is available
 from ftp://telepresence.dmem.strath.ac.uk/pub/bt848/winutil, but it
 does'nt work with bt878 boards according to some reports I received.
-Another one with bt878 suport is available from
+Another one with bt878 support is available from
 http://btwincap.sourceforge.net/Files/btspy2.00.zip
 
 You might also dig around in the *.ini files of the Windows applications.
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index f6ec3a9..a5607c5 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1194,12 +1194,15 @@ struct kvm_ppc_pvinfo {
 This ioctl fetches PV specific information that need to be passed to the guest
 using the device tree or other means from vm context.
 
-For now the only implemented piece of information distributed here is an array
-of 4 instructions that make up a hypercall.
+The hcall array defines 4 instructions that make up a hypercall.
 
 If any additional field gets added to this structure later on, a bit for that
 additional piece of information will be set in the flags bitmap.
 
+The flags bitmap is defined as:
+
+   /* the host supports the ePAPR idle hcall
+   #define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
 
 4.48 KVM_ASSIGN_PCI_DEVICE
 
@@ -1731,7 +1734,45 @@ registers, find a list below:
   Arch  |       Register        | Width (bits)
         |                       |
   PPC   | KVM_REG_PPC_HIOR      | 64
-
+  PPC   | KVM_REG_PPC_IAC1      | 64
+  PPC   | KVM_REG_PPC_IAC2      | 64
+  PPC   | KVM_REG_PPC_IAC3      | 64
+  PPC   | KVM_REG_PPC_IAC4      | 64
+  PPC   | KVM_REG_PPC_DAC1      | 64
+  PPC   | KVM_REG_PPC_DAC2      | 64
+  PPC   | KVM_REG_PPC_DABR      | 64
+  PPC   | KVM_REG_PPC_DSCR      | 64
+  PPC   | KVM_REG_PPC_PURR      | 64
+  PPC   | KVM_REG_PPC_SPURR     | 64
+  PPC   | KVM_REG_PPC_DAR       | 64
+  PPC   | KVM_REG_PPC_DSISR     | 32
+  PPC   | KVM_REG_PPC_AMR       | 64
+  PPC   | KVM_REG_PPC_UAMOR     | 64
+  PPC   | KVM_REG_PPC_MMCR0     | 64
+  PPC   | KVM_REG_PPC_MMCR1     | 64
+  PPC   | KVM_REG_PPC_MMCRA     | 64
+  PPC   | KVM_REG_PPC_PMC1      | 32
+  PPC   | KVM_REG_PPC_PMC2      | 32
+  PPC   | KVM_REG_PPC_PMC3      | 32
+  PPC   | KVM_REG_PPC_PMC4      | 32
+  PPC   | KVM_REG_PPC_PMC5      | 32
+  PPC   | KVM_REG_PPC_PMC6      | 32
+  PPC   | KVM_REG_PPC_PMC7      | 32
+  PPC   | KVM_REG_PPC_PMC8      | 32
+  PPC   | KVM_REG_PPC_FPR0      | 64
+          ...
+  PPC   | KVM_REG_PPC_FPR31     | 64
+  PPC   | KVM_REG_PPC_VR0       | 128
+          ...
+  PPC   | KVM_REG_PPC_VR31      | 128
+  PPC   | KVM_REG_PPC_VSR0      | 128
+          ...
+  PPC   | KVM_REG_PPC_VSR31     | 128
+  PPC   | KVM_REG_PPC_FPSCR     | 64
+  PPC   | KVM_REG_PPC_VSCR      | 32
+  PPC   | KVM_REG_PPC_VPA_ADDR  | 64
+  PPC   | KVM_REG_PPC_VPA_SLB   | 128
+  PPC   | KVM_REG_PPC_VPA_DTL   | 128
 
 4.69 KVM_GET_ONE_REG
 
@@ -1747,7 +1788,7 @@ kvm_one_reg struct passed in. On success, the register value can be found
 at the memory location pointed to by "addr".
 
 The list of registers accessible using this interface is identical to the
-list in 4.64.
+list in 4.68.
 
 
 4.70 KVM_KVMCLOCK_CTRL
@@ -1997,6 +2038,93 @@ return the hash table order in the parameter.  (If the guest is using
 the virtualized real-mode area (VRMA) facility, the kernel will
 re-create the VMRA HPTEs on the next KVM_RUN of any vcpu.)
 
+4.77 KVM_S390_INTERRUPT
+
+Capability: basic
+Architectures: s390
+Type: vm ioctl, vcpu ioctl
+Parameters: struct kvm_s390_interrupt (in)
+Returns: 0 on success, -1 on error
+
+Allows to inject an interrupt to the guest. Interrupts can be floating
+(vm ioctl) or per cpu (vcpu ioctl), depending on the interrupt type.
+
+Interrupt parameters are passed via kvm_s390_interrupt:
+
+struct kvm_s390_interrupt {
+	__u32 type;
+	__u32 parm;
+	__u64 parm64;
+};
+
+type can be one of the following:
+
+KVM_S390_SIGP_STOP (vcpu) - sigp restart
+KVM_S390_PROGRAM_INT (vcpu) - program check; code in parm
+KVM_S390_SIGP_SET_PREFIX (vcpu) - sigp set prefix; prefix address in parm
+KVM_S390_RESTART (vcpu) - restart
+KVM_S390_INT_VIRTIO (vm) - virtio external interrupt; external interrupt
+			   parameters in parm and parm64
+KVM_S390_INT_SERVICE (vm) - sclp external interrupt; sclp parameter in parm
+KVM_S390_INT_EMERGENCY (vcpu) - sigp emergency; source cpu in parm
+KVM_S390_INT_EXTERNAL_CALL (vcpu) - sigp external call; source cpu in parm
+
+Note that the vcpu ioctl is asynchronous to vcpu execution.
+
+4.78 KVM_PPC_GET_HTAB_FD
+
+Capability: KVM_CAP_PPC_HTAB_FD
+Architectures: powerpc
+Type: vm ioctl
+Parameters: Pointer to struct kvm_get_htab_fd (in)
+Returns: file descriptor number (>= 0) on success, -1 on error
+
+This returns a file descriptor that can be used either to read out the
+entries in the guest's hashed page table (HPT), or to write entries to
+initialize the HPT.  The returned fd can only be written to if the
+KVM_GET_HTAB_WRITE bit is set in the flags field of the argument, and
+can only be read if that bit is clear.  The argument struct looks like
+this:
+
+/* For KVM_PPC_GET_HTAB_FD */
+struct kvm_get_htab_fd {
+	__u64	flags;
+	__u64	start_index;
+	__u64	reserved[2];
+};
+
+/* Values for kvm_get_htab_fd.flags */
+#define KVM_GET_HTAB_BOLTED_ONLY	((__u64)0x1)
+#define KVM_GET_HTAB_WRITE		((__u64)0x2)
+
+The `start_index' field gives the index in the HPT of the entry at
+which to start reading.  It is ignored when writing.
+
+Reads on the fd will initially supply information about all
+"interesting" HPT entries.  Interesting entries are those with the
+bolted bit set, if the KVM_GET_HTAB_BOLTED_ONLY bit is set, otherwise
+all entries.  When the end of the HPT is reached, the read() will
+return.  If read() is called again on the fd, it will start again from
+the beginning of the HPT, but will only return HPT entries that have
+changed since they were last read.
+
+Data read or written is structured as a header (8 bytes) followed by a
+series of valid HPT entries (16 bytes) each.  The header indicates how
+many valid HPT entries there are and how many invalid entries follow
+the valid entries.  The invalid entries are not represented explicitly
+in the stream.  The header format is:
+
+struct kvm_get_htab_header {
+	__u32	index;
+	__u16	n_valid;
+	__u16	n_invalid;
+};
+
+Writes to the fd create HPT entries starting at the index given in the
+header; first `n_valid' valid entries with contents from the data
+written, then `n_invalid' invalid entries, invalidating any previously
+valid entries found.
+
 
 5. The kvm_run structure
 ------------------------
@@ -2109,7 +2237,8 @@ executed a memory-mapped I/O instruction which could not be satisfied
 by kvm.  The 'data' member contains the written data if 'is_write' is
 true, and should be filled by application code otherwise.
 
-NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO and KVM_EXIT_OSI, the corresponding
+NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_DCR
+      and KVM_EXIT_PAPR the corresponding
 operations are complete (and guest state is consistent) only after userspace
 has re-entered the kernel with KVM_RUN.  The kernel side will first finish
 incomplete operations and then check for pending signals.  Userspace
diff --git a/Documentation/vm/frontswap.txt b/Documentation/vm/frontswap.txt
index 5ef2d13..c71a019 100644
--- a/Documentation/vm/frontswap.txt
+++ b/Documentation/vm/frontswap.txt
@@ -193,7 +193,7 @@ faster.
    or maybe swap-over-nbd/NFS)?
 
 No.  First, the existing swap subsystem doesn't allow for any kind of
-swap hierarchy.  Perhaps it could be rewritten to accomodate a hierarchy,
+swap hierarchy.  Perhaps it could be rewritten to accommodate a hierarchy,
 but this would require fairly drastic changes.  Even if it were
 rewritten, the existing swap subsystem uses the block I/O layer which
 assumes a swap device is fixed size and any page in it is linearly
diff --git a/Documentation/vm/transhuge.txt b/Documentation/vm/transhuge.txt
index f734bb2..8785fb8 100644
--- a/Documentation/vm/transhuge.txt
+++ b/Documentation/vm/transhuge.txt
@@ -116,6 +116,13 @@ echo always >/sys/kernel/mm/transparent_hugepage/defrag
 echo madvise >/sys/kernel/mm/transparent_hugepage/defrag
 echo never >/sys/kernel/mm/transparent_hugepage/defrag
 
+By default kernel tries to use huge zero page on read page fault.
+It's possible to disable huge zero page by writing 0 or enable it
+back by writing 1:
+
+echo 0 >/sys/kernel/mm/transparent_hugepage/khugepaged/use_zero_page
+echo 1 >/sys/kernel/mm/transparent_hugepage/khugepaged/use_zero_page
+
 khugepaged will be automatically started when
 transparent_hugepage/enabled is set to "always" or "madvise, and it'll
 be automatically shutdown if it's set to "never".
@@ -197,6 +204,14 @@ thp_split is incremented every time a huge page is split into base
 	pages. This can happen for a variety of reasons but a common
 	reason is that a huge page is old and is being reclaimed.
 
+thp_zero_page_alloc is incremented every time a huge zero page is
+	successfully allocated. It includes allocations which where
+	dropped due race with other allocation. Note, it doesn't count
+	every map of the huge zero page, only its allocation.
+
+thp_zero_page_alloc_failed is incremented if kernel fails to allocate
+	huge zero page and falls back to using small pages.
+
 As the system ages, allocating huge pages may be expensive as the
 system uses memory compaction to copy data around memory to free a
 huge page for use. There are some counters in /proc/vmstat to help
@@ -276,7 +291,7 @@ unaffected. libhugetlbfs will also work fine as usual.
 == Graceful fallback ==
 
 Code walking pagetables but unware about huge pmds can simply call
-split_huge_page_pmd(mm, pmd) where the pmd is the one returned by
+split_huge_page_pmd(vma, addr, pmd) where the pmd is the one returned by
 pmd_offset. It's trivial to make the code transparent hugepage aware
 by just grepping for "pmd_offset" and adding split_huge_page_pmd where
 missing after pmd_offset returns the pmd. Thanks to the graceful
@@ -299,7 +314,7 @@ diff --git a/mm/mremap.c b/mm/mremap.c
 		return NULL;
 
 	pmd = pmd_offset(pud, addr);
-+	split_huge_page_pmd(mm, pmd);
++	split_huge_page_pmd(vma, addr, pmd);
 	if (pmd_none_or_clear_bad(pmd))
 		return NULL;
 
diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt
index 9efceff..f15cb74 100644
--- a/Documentation/x86/boot.txt
+++ b/Documentation/x86/boot.txt
@@ -1013,7 +1013,7 @@ boot_params as that of 16-bit boot protocol, the boot loader should
 also fill the additional fields of the struct boot_params as that
 described in zero-page.txt.
 
-After setupping the struct boot_params, the boot loader can load the
+After setting up the struct boot_params, the boot loader can load the
 32/64-bit kernel in the same way as that of 16-bit boot protocol.
 
 In 32-bit boot protocol, the kernel is started by jumping to the
@@ -1023,7 +1023,7 @@ In 32-bit boot protocol, the kernel is started by jumping to the
 At entry, the CPU must be in 32-bit protected mode with paging
 disabled; a GDT must be loaded with the descriptors for selectors
 __BOOT_CS(0x10) and __BOOT_DS(0x18); both descriptors must be 4G flat
-segment; __BOOS_CS must have execute/read permission, and __BOOT_DS
+segment; __BOOT_CS must have execute/read permission, and __BOOT_DS
 must have read/write permission; CS must be __BOOT_CS and DS, ES, SS
 must be __BOOT_DS; interrupt must be disabled; %esi must hold the base
 address of the struct boot_params; %ebp, %edi and %ebx must be zero.
diff --git a/Documentation/xtensa/atomctl.txt b/Documentation/xtensa/atomctl.txt
new file mode 100644
index 0000000..10a8d1f
--- /dev/null
+++ b/Documentation/xtensa/atomctl.txt
@@ -0,0 +1,44 @@
+We Have Atomic Operation Control (ATOMCTL) Register.
+This register determines the effect of using a S32C1I instruction
+with various combinations of:
+
+     1. With and without an Coherent Cache Controller which
+        can do Atomic Transactions to the memory internally.
+
+     2. With and without An Intelligent Memory Controller which
+        can do Atomic Transactions itself.
+
+The Core comes up with a default value of for the three types of cache ops:
+
+      0x28: (WB: Internal, WT: Internal, BY:Exception)
+
+On the FPGA Cards we typically simulate an Intelligent Memory controller
+which can implement  RCW transactions. For FPGA cards with an External
+Memory controller we let it to the atomic operations internally while
+doing a Cached (WB) transaction and use the Memory RCW for un-cached
+operations.
+
+For systems without an coherent cache controller, non-MX, we always
+use the memory controllers RCW, thought non-MX controlers likely
+support the Internal Operation.
+
+CUSTOMER-WARNING:
+   Virtually all customers buy their memory controllers from vendors that
+   don't support atomic RCW memory transactions and will likely want to
+   configure this register to not use RCW.
+
+Developers might find using RCW in Bypass mode convenient when testing
+with the cache being bypassed; for example studying cache alias problems.
+
+See Section 4.3.12.4 of ISA; Bits:
+
+                             WB     WT      BY
+                           5   4 | 3   2 | 1   0
+  2 Bit
+  Field
+  Values     WB - Write Back         WT - Write Thru         BY - Bypass
+---------    ---------------         -----------------     ----------------
+    0        Exception               Exception               Exception
+    1        RCW Transaction         RCW Transaction         RCW Transaction
+    2        Internal Operation      Exception               Reserved
+    3        Reserved                Reserved                Reserved
diff --git a/Documentation/zh_CN/CodingStyle b/Documentation/zh_CN/CodingStyle
index ecd9307..654afd7 100644
--- a/Documentation/zh_CN/CodingStyle
+++ b/Documentation/zh_CN/CodingStyle
@@ -462,13 +462,6 @@ config AUDIT
 	  logging of avc messages output).  Does not do system-call
 	  auditing without CONFIG_AUDITSYSCALL.
 
-仍然被认为不够稳定的功能应该被定义为依赖于“EXPERIMENTAL”：
-
-config SLUB
-	depends on EXPERIMENTAL && !ARCH_USES_SLAB_PAGE_STRUCT
-	bool "SLUB (Unqueued Allocator)"
-	...
-
 而那些危险的功能（比如某些文件系统的写支持）应该在它们的提示字符串里显著的声明这
 一点：
 
diff --git a/Documentation/zh_CN/arm/kernel_user_helpers.txt b/Documentation/zh_CN/arm/kernel_user_helpers.txt
new file mode 100644
index 0000000..cd7fc8f
--- /dev/null
+++ b/Documentation/zh_CN/arm/kernel_user_helpers.txt
@@ -0,0 +1,284 @@
+Chinese translated version of Documentation/arm/kernel_user_helpers.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Nicolas Pitre <nicolas.pitre@linaro.org>
+		Dave Martin <dave.martin@linaro.org>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/arm/kernel_user_helpers.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+英文版维护者： Nicolas Pitre <nicolas.pitre@linaro.org>
+		Dave Martin <dave.martin@linaro.org>
+中文版维护者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版校译者： 宋冬生 Dongsheng Song <dongshneg.song@gmail.com>
+		傅炜 Fu Wei <tekkamanninja@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+内核提供的用户空间辅助代码
+=========================
+
+在内核内存空间的固定地址处，有一个由内核提供并可从用户空间访问的代码
+段。它用于向用户空间提供因在许多 ARM CPU 中未实现的特性和/或指令而需
+内核提供帮助的某些操作。这些代码直接在用户模式下执行的想法是为了获得
+最佳效率，但那些与内核计数器联系过于紧密的部分，则被留给了用户库实现。
+事实上，此代码甚至可能因不同的 CPU 而异，这取决于其可用的指令集或它
+是否为 SMP 系统。换句话说，内核保留在不作出警告的情况下根据需要更改
+这些代码的权利。只有本文档描述的入口及其结果是保证稳定的。
+
+这与完全成熟的 VDSO 实现不同（但两者并不冲突），尽管如此，VDSO 可阻止
+某些通过常量高效跳转到那些代码段的汇编技巧。且由于那些代码段在返回用户
+代码前仅使用少量的代码周期，则一个 VDSO 间接远程调用将会在这些简单的
+操作上增加一个可测量的开销。
+
+在对那些拥有原生支持的新型处理器进行代码优化时，仅在已为其他操作使用
+了类似的新增指令，而导致二进制结果已与早期 ARM 处理器不兼容的情况下，
+用户空间才应绕过这些辅助代码，并在内联函数中实现这些操作（无论是通过
+编译器在代码中直接放置，还是作为库函数调用实现的一部分）。也就是说，
+如果你编译的代码不会为了其他目的使用新指令，则不要仅为了避免使用这些
+内核辅助代码，导致二进制程序无法在早期处理器上运行。
+
+新的辅助代码可能随着时间的推移而增加，所以新内核中的某些辅助代码在旧
+内核中可能不存在。因此，程序必须在对任何辅助代码调用假设是安全之前，
+检测 __kuser_helper_version 的值（见下文）。理想情况下，这种检测应该
+只在进程启动时执行一次；如果内核版本不支持所需辅助代码，则该进程可尽早
+中止执行。
+
+kuser_helper_version
+--------------------
+
+位置:	0xffff0ffc
+
+参考声明:
+
+  extern int32_t __kuser_helper_version;
+
+定义:
+
+  这个区域包含了当前运行内核实现的辅助代码版本号。用户空间可以通过读
+  取此版本号以确定特定的辅助代码是否存在。
+
+使用范例:
+
+#define __kuser_helper_version (*(int32_t *)0xffff0ffc)
+
+void check_kuser_version(void)
+{
+	if (__kuser_helper_version < 2) {
+		fprintf(stderr, "can't do atomic operations, kernel too old\n");
+		abort();
+	}
+}
+
+注意:
+
+  用户空间可以假设这个域的值不会在任何单个进程的生存期内改变。也就
+  是说，这个域可以仅在库的初始化阶段或进程启动阶段读取一次。
+
+kuser_get_tls
+-------------
+
+位置:	0xffff0fe0
+
+参考原型:
+
+  void * __kuser_get_tls(void);
+
+输入:
+
+  lr = 返回地址
+
+输出:
+
+  r0 = TLS 值
+
+被篡改的寄存器:
+
+  无
+
+定义:
+
+  获取之前通过 __ARM_NR_set_tls 系统调用设置的 TLS 值。
+
+使用范例:
+
+typedef void * (__kuser_get_tls_t)(void);
+#define __kuser_get_tls (*(__kuser_get_tls_t *)0xffff0fe0)
+
+void foo()
+{
+	void *tls = __kuser_get_tls();
+	printf("TLS = %p\n", tls);
+}
+
+注意:
+
+  - 仅在 __kuser_helper_version >= 1 时，此辅助代码存在
+    （从内核版本 2.6.12 开始）。
+
+kuser_cmpxchg
+-------------
+
+位置:	0xffff0fc0
+
+参考原型:
+
+  int __kuser_cmpxchg(int32_t oldval, int32_t newval, volatile int32_t *ptr);
+
+输入:
+
+  r0 = oldval
+  r1 = newval
+  r2 = ptr
+  lr = 返回地址
+
+输出:
+
+  r0 = 成功代码 (零或非零)
+  C flag = 如果 r0 == 0 则置 1，如果 r0 != 0 则清零。
+
+被篡改的寄存器:
+
+  r3, ip, flags
+
+定义:
+
+  仅在 *ptr 为 oldval 时原子保存 newval 于 *ptr 中。
+  如果 *ptr 被改变，则返回值为零，否则为非零值。
+  如果 *ptr 被改变，则 C flag 也会被置 1，以实现调用代码中的汇编
+  优化。
+
+使用范例:
+
+typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
+#define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0)
+
+int atomic_add(volatile int *ptr, int val)
+{
+	int old, new;
+
+	do {
+		old = *ptr;
+		new = old + val;
+	} while(__kuser_cmpxchg(old, new, ptr));
+
+	return new;
+}
+
+注意:
+
+  - 这个例程已根据需要包含了内存屏障。
+
+  - 仅在 __kuser_helper_version >= 2 时，此辅助代码存在
+    （从内核版本 2.6.12 开始）。
+
+kuser_memory_barrier
+--------------------
+
+位置:	0xffff0fa0
+
+参考原型:
+
+  void __kuser_memory_barrier(void);
+
+输入:
+
+  lr = 返回地址
+
+输出:
+
+  无
+
+被篡改的寄存器:
+
+  无
+
+定义:
+
+  应用于任何需要内存屏障以防止手动数据修改带来的一致性问题，以及
+  __kuser_cmpxchg 中。
+
+使用范例:
+
+typedef void (__kuser_dmb_t)(void);
+#define __kuser_dmb (*(__kuser_dmb_t *)0xffff0fa0)
+
+注意:
+
+  - 仅在 __kuser_helper_version >= 3 时，此辅助代码存在
+    （从内核版本 2.6.15 开始）。
+
+kuser_cmpxchg64
+---------------
+
+位置:	0xffff0f60
+
+参考原型:
+
+  int __kuser_cmpxchg64(const int64_t *oldval,
+                        const int64_t *newval,
+                        volatile int64_t *ptr);
+
+输入:
+
+  r0 = 指向 oldval
+  r1 = 指向 newval
+  r2 = 指向目标值
+  lr = 返回地址
+
+输出:
+
+  r0 = 成功代码 (零或非零)
+  C flag = 如果 r0 == 0 则置 1，如果 r0 != 0 则清零。
+
+被篡改的寄存器:
+
+  r3, lr, flags
+
+定义:
+
+  仅在 *ptr 等于 *oldval 指向的 64 位值时，原子保存 *newval
+  指向的 64 位值于 *ptr 中。如果 *ptr 被改变，则返回值为零，
+  否则为非零值。
+
+  如果 *ptr 被改变，则 C flag 也会被置 1，以实现调用代码中的汇编
+  优化。
+
+使用范例:
+
+typedef int (__kuser_cmpxchg64_t)(const int64_t *oldval,
+                                  const int64_t *newval,
+                                  volatile int64_t *ptr);
+#define __kuser_cmpxchg64 (*(__kuser_cmpxchg64_t *)0xffff0f60)
+
+int64_t atomic_add64(volatile int64_t *ptr, int64_t val)
+{
+	int64_t old, new;
+
+	do {
+		old = *ptr;
+		new = old + val;
+	} while(__kuser_cmpxchg64(&old, &new, ptr));
+
+	return new;
+}
+
+注意:
+
+  - 这个例程已根据需要包含了内存屏障。
+
+  - 由于这个过程的代码长度（此辅助代码跨越 2 个常规的 kuser “槽”），
+    因此 0xffff0f80 不被作为有效的入口点。
+
+  - 仅在 __kuser_helper_version >= 5 时，此辅助代码存在
+    （从内核版本 3.1 开始）。
diff --git a/Documentation/zh_CN/arm64/memory.txt b/Documentation/zh_CN/arm64/memory.txt
index 83b5193..a5f6283 100644
--- a/Documentation/zh_CN/arm64/memory.txt
+++ b/Documentation/zh_CN/arm64/memory.txt
@@ -47,21 +47,21 @@ AArch64 Linux 内存布局：
 -----------------------------------------------------------------------
 0000000000000000	0000007fffffffff	 512GB		用户空间
 
-ffffff8000000000	ffffffbbfffcffff	~240GB		vmalloc
+ffffff8000000000	ffffffbbfffeffff	~240GB		vmalloc
 
-ffffffbbfffd0000	ffffffbcfffdffff	  64KB		[防护页]
+ffffffbbffff0000	ffffffbbffffffff	  64KB		[防护页]
 
-ffffffbbfffe0000	ffffffbcfffeffff	  64KB		PCI I/O 空间
+ffffffbc00000000	ffffffbdffffffff	   8GB		vmemmap
 
-ffffffbbffff0000	ffffffbcffffffff	  64KB		[防护页]
+ffffffbe00000000	ffffffbffbbfffff	  ~8GB		[防护页，未来用于 vmmemap]
 
-ffffffbc00000000	ffffffbdffffffff	   8GB		vmemmap
+ffffffbffbe00000	ffffffbffbe0ffff	  64KB		PCI I/O 空间
 
-ffffffbe00000000	ffffffbffbffffff	  ~8GB		[防护页，未来用于 vmmemap]
+ffffffbbffff0000	ffffffbcffffffff	  ~2MB		[防护页]
 
 ffffffbffc000000	ffffffbfffffffff	  64MB		模块
 
-ffffffc000000000	ffffffffffffffff	 256GB		内存空间
+ffffffc000000000	ffffffffffffffff	 256GB		内核逻辑内存映射
 
 
 4KB 页大小的转换表查找：
diff --git a/MAINTAINERS b/MAINTAINERS
index 9386a63..3be4fa9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -337,6 +337,13 @@ W:	http://wireless.kernel.org/
 S:	Orphan
 F:	drivers/net/wireless/adm8211.*
 
+ADP1653 FLASH CONTROLLER DRIVER
+M:	Sakari Ailus <sakari.ailus@iki.fi>
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	drivers/media/i2c/adp1653.c
+F:	include/media/adp1653.h
+
 ADP5520 BACKLIGHT DRIVER WITH IO EXPANDER (ADP5520/ADP5501)
 M:	Michael Hennerich <michael.hennerich@analog.com>
 L:	device-drivers-devel@blackfin.uclinux.org
@@ -685,6 +692,12 @@ M:	Lennert Buytenhek <kernel@wantstofly.org>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 
+ARM/Allwinner A1X SoC support
+M:	Maxime Ripard <maxime.ripard@free-electrons.com>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	arch/arm/mach-sunxi/
+
 ARM/ATMEL AT91RM9200 AND AT91SAM ARM ARCHITECTURES
 M:	Andrew Victor <linux@maxim.org.za>
 M:	Nicolas Ferre <nicolas.ferre@atmel.com>
@@ -707,6 +720,12 @@ S:	Maintained
 F:	arch/arm/mach-cns3xxx/
 T:	git git://git.infradead.org/users/cbou/linux-cns3xxx.git
 
+ARM/CIRRUS LOGIC CLPS711X ARM ARCHITECTURE
+M:	Alexander Shiyan <shc_work@mail.ru>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:	Odd Fixes
+F:	arch/arm/mach-clps711x/
+
 ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE
 M:	Hartley Sweeten <hsweeten@visionengravers.com>
 M:	Ryan Mallon <rmallon@gmail.com>
@@ -797,7 +816,6 @@ L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 T:	git git://git.pengutronix.de/git/imx/linux-2.6.git
 F:	arch/arm/mach-imx/
-F:	arch/arm/plat-mxc/
 F:	arch/arm/configs/imx*_defconfig
 
 ARM/FREESCALE IMX6
@@ -1130,12 +1148,12 @@ S:	Maintained
 F:	drivers/media/platform/s5p-tv/
 
 ARM/SHMOBILE ARM ARCHITECTURE
-M:	Paul Mundt <lethal@linux-sh.org>
+M:	Simon Horman <horms@verge.net.au>
 M:	Magnus Damm <magnus.damm@gmail.com>
 L:	linux-sh@vger.kernel.org
 W:	http://oss.renesas.com
 Q:	http://patchwork.kernel.org/project/linux-sh/list/
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git rmobile-latest
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git next
 S:	Supported
 F:	arch/arm/mach-shmobile/
 F:	drivers/sh/
@@ -1237,6 +1255,7 @@ F:	drivers/video/wm8505fb*
 F:	drivers/video/wmt_ge_rops.*
 F:	drivers/tty/serial/vt8500_serial.c
 F:	drivers/rtc/rtc-vt8500-c
+F:	drivers/mmc/host/wmt-sdmmc.c
 
 ARM/ZIPIT Z2 SUPPORT
 M:	Marek Vasut <marek.vasut@gmail.com>
@@ -1368,14 +1387,6 @@ S:	Maintained
 F:	drivers/atm/
 F:	include/linux/atm*
 
-ATMEL AT91 MCI DRIVER
-M:	Ludovic Desroches <ludovic.desroches@atmel.com>
-L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-W:	http://www.atmel.com/products/AT91/
-W:	http://www.at91.com/
-S:	Maintained
-F:	drivers/mmc/host/at91_mci.c
-
 ATMEL AT91 / AT32 MCI DRIVER
 M:	Ludovic Desroches <ludovic.desroches@atmel.com>
 S:	Maintained
@@ -1488,6 +1499,14 @@ F:	include/linux/ax25.h
 F:	include/net/ax25.h
 F:	net/ax25/
 
+AZ6007 DVB DRIVER
+M:	Mauro Carvalho Chehab <mchehab@redhat.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Maintained
+F:	drivers/media/usb/dvb-usb-v2/az6007.c
+
 B43 WIRELESS DRIVER
 M:	Stefano Brivio <stefano.brivio@polimi.it>
 L:	linux-wireless@vger.kernel.org
@@ -1740,11 +1759,11 @@ F:	Documentation/filesystems/btrfs.txt
 F:	fs/btrfs/
 
 BTTV VIDEO4LINUX DRIVER
-M:	Mauro Carvalho Chehab <mchehab@infradead.org>
+M:	Mauro Carvalho Chehab <mchehab@redhat.com>
 L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
-S:	Maintained
+T:	git git://linuxtv.org/media_tree.git
+S:	Odd fixes
 F:	Documentation/video4linux/bttv/
 F:	drivers/media/pci/bt8xx/bttv*
 
@@ -1773,7 +1792,7 @@ F:	fs/cachefiles/
 CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER
 M:	Jonathan Corbet <corbet@lwn.net>
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
 F:	Documentation/video4linux/cafe_ccic
 F:	drivers/media/platform/marvell-ccic/
@@ -1909,7 +1928,7 @@ F:	scripts/checkpatch.pl
 
 CHINESE DOCUMENTATION
 M:	Harry Wei <harryxiyou@gmail.com>
-L:	xiyoulinuxkernelgroup@googlegroups.com
+L:	xiyoulinuxkernelgroup@googlegroups.com (subscribers-only)
 L:	linux-kernel@zh-kernel.org (moderated for non-subscribers)
 S:	Maintained
 F:	Documentation/zh_CN/
@@ -2160,12 +2179,22 @@ CX18 VIDEO4LINUX DRIVER
 M:	Andy Walls <awalls@md.metrocast.net>
 L:	ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 W:	http://linuxtv.org
 W:	http://www.ivtvdriver.org/index.php/Cx18
 S:	Maintained
 F:	Documentation/video4linux/cx18.txt
 F:	drivers/media/pci/cx18/
+F:	include/uapi/linux/ivtv*
+
+CX88 VIDEO4LINUX DRIVER
+M:	Mauro Carvalho Chehab <mchehab@redhat.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Odd fixes
+F:	Documentation/video4linux/cx88/
+F:	drivers/media/pci/cx88/
 
 CXD2820R MEDIA DRIVER
 M:	Antti Palosaari <crope@iki.fi>
@@ -2722,6 +2751,15 @@ W:	bluesmoke.sourceforge.net
 S:	Maintained
 F:	drivers/edac/amd64_edac*
 
+EDAC-CAVIUM
+M:	Ralf Baechle <ralf@linux-mips.org>
+M:	David Daney <david.daney@cavium.com>
+L:	linux-edac@vger.kernel.org
+L:	linux-mips@linux-mips.org
+W:	bluesmoke.sourceforge.net
+S:	Supported
+F:	drivers/edac/octeon_edac*
+
 EDAC-E752X
 M:	Mark Gross <mark.gross@intel.com>
 M:	Doug Thompson <dougthompson@xmission.com>
@@ -2852,6 +2890,14 @@ L:	netdev@vger.kernel.org
 S:	Maintained
 F:	drivers/net/ethernet/ibm/ehea/
 
+EM28XX VIDEO4LINUX DRIVER
+M:	Mauro Carvalho Chehab <mchehab@redhat.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Maintained
+F:	drivers/media/usb/em28xx/
+
 EMBEDDED LINUX
 M:	Paul Gortmaker <paul.gortmaker@windriver.com>
 M:	Matt Mackall <mpm@selenic.com>
@@ -2927,7 +2973,6 @@ L:	linux-ext4@vger.kernel.org
 S:	Maintained
 F:	Documentation/filesystems/ext3.txt
 F:	fs/ext3/
-F:	include/linux/ext3*
 
 EXT4 FILE SYSTEM
 M:	"Theodore Ts'o" <tytso@mit.edu>
@@ -3050,6 +3095,14 @@ T:	git git://git.alsa-project.org/alsa-kernel.git
 S:	Maintained
 F:	sound/firewire/
 
+FIREWIRE MEDIA DRIVERS (firedtv)
+M:	Stefan Richter <stefanr@s5r6.in-berlin.de>
+L:	linux-media@vger.kernel.org
+L:	linux1394-devel@lists.sourceforge.net
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+S:	Maintained
+F:	drivers/media/firewire/
+
 FIREWIRE SBP-2 TARGET
 M:	Chris Boot <bootc@bootc.net>
 L:	linux-scsi@vger.kernel.org
@@ -3336,56 +3389,56 @@ F:	drivers/net/ethernet/aeroflex/
 GSPCA FINEPIX SUBDRIVER
 M:	Frank Zago <frank@zago.net>
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
 F:	drivers/media/usb/gspca/finepix.c
 
 GSPCA GL860 SUBDRIVER
 M:	Olivier Lorin <o.lorin@laposte.net>
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
 F:	drivers/media/usb/gspca/gl860/
 
 GSPCA M5602 SUBDRIVER
 M:	Erik Andren <erik.andren@gmail.com>
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
 F:	drivers/media/usb/gspca/m5602/
 
 GSPCA PAC207 SONIXB SUBDRIVER
 M:	Hans de Goede <hdegoede@redhat.com>
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
 F:	drivers/media/usb/gspca/pac207.c
 
 GSPCA SN9C20X SUBDRIVER
 M:	Brian Johnson <brijohn@gmail.com>
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
 F:	drivers/media/usb/gspca/sn9c20x.c
 
 GSPCA T613 SUBDRIVER
 M:	Leandro Costantino <lcostantino@gmail.com>
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
 F:	drivers/media/usb/gspca/t613.c
 
 GSPCA USB WEBCAM DRIVER
 M:	Hans de Goede <hdegoede@redhat.com>
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
 F:	drivers/media/usb/gspca/
 
 STK1160 USB VIDEO CAPTURE DRIVER
 M:	Ezequiel Garcia <elezegarcia@gmail.com>
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
 F:	drivers/media/usb/stk1160/
 
@@ -3604,7 +3657,6 @@ S:	Maintained
 F:	drivers/hv/
 F:	drivers/hid/hid-hyperv.c
 F:	drivers/net/hyperv/
-F:	drivers/staging/hv/
 
 I2C OVER PARALLEL PORT
 M:	Jean Delvare <khali@linux-fr.org>
@@ -3653,7 +3705,7 @@ I2C/SMBUS STUB DRIVER
 M:	"Mark M. Hoffman" <mhoffman@lightlink.com>
 L:	linux-i2c@vger.kernel.org
 S:	Maintained
-F:	drivers/i2c/busses/i2c-stub.c
+F:	drivers/i2c/i2c-stub.c
 
 I2C SUBSYSTEM
 M:	Wolfram Sang <w.sang@pengutronix.de>
@@ -3784,6 +3836,12 @@ F:	net/ieee802154/
 F:	net/mac802154/
 F:	drivers/ieee802154/
 
+IGUANAWORKS USB IR TRANSCEIVER
+M:	Sean Young <sean@mess.org>
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	drivers/media/rc/iguanair.c
+
 IIO SUBSYSTEM AND DRIVERS
 M:	Jonathan Cameron <jic23@cam.ac.uk>
 L:	linux-iio@vger.kernel.org
@@ -3797,6 +3855,15 @@ M:	Stanislaw Gruszka <stf_xl@wp.pl>
 S:	Maintained
 F:	drivers/usb/atm/ueagle-atm.c
 
+INDUSTRY PACK SUBSYSTEM (IPACK)
+M:	Samuel Iglesias Gonsalvez <siglesias@igalia.com>
+M:	Jens Taprogge <jens.taprogge@taprogge.org>
+M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+L:	industrypack-devel@lists.sourceforge.net
+W:	http://industrypack.sourceforge.net
+S:	Maintained
+F:	drivers/ipack/
+
 INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
 M:	Mimi Zohar <zohar@us.ibm.com>
 S:	Supported
@@ -3936,7 +4003,9 @@ M:	Greg Rose <gregory.v.rose@intel.com>
 M:	Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
 M:	Alex Duyck <alexander.h.duyck@intel.com>
 M:	John Ronciak <john.ronciak@intel.com>
+M:	Tushar Dave <tushar.n.dave@intel.com>
 L:	e1000-devel@lists.sourceforge.net
+W:	http://www.intel.com/support/feedback.htm
 W:	http://e1000.sourceforge.net/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net.git
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next.git
@@ -4158,17 +4227,41 @@ S:	Maintained
 F:	Documentation/hwmon/it87
 F:	drivers/hwmon/it87.c
 
+IT913X MEDIA DRIVER
+M:	Malcolm Priestley <tvboxspy@gmail.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org/
+Q:	http://patchwork.linuxtv.org/project/linux-media/list/
+S:	Maintained
+F:	drivers/media/usb/dvb-usb-v2/it913x*
+
+IT913X FE MEDIA DRIVER
+M:	Malcolm Priestley <tvboxspy@gmail.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org/
+Q:	http://patchwork.linuxtv.org/project/linux-media/list/
+S:	Maintained
+F:	drivers/media/dvb-frontends/it913x-fe*
+
 IVTV VIDEO4LINUX DRIVER
 M:	Andy Walls <awalls@md.metrocast.net>
 L:	ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 W:	http://www.ivtvdriver.org
 S:	Maintained
 F:	Documentation/video4linux/*.ivtv
 F:	drivers/media/pci/ivtv/
 F:	include/linux/ivtv*
 
+IX2505V MEDIA DRIVER
+M:	Malcolm Priestley <tvboxspy@gmail.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org/
+Q:	http://patchwork.linuxtv.org/project/linux-media/list/
+S:	Maintained
+F:	drivers/media/dvb-frontends/ix2505v*
+
 JC42.4 TEMPERATURE SENSOR DRIVER
 M:	Guenter Roeck <linux@roeck-us.net>
 L:	lm-sensors@lm-sensors.org
@@ -4205,7 +4298,6 @@ M:	Jan Kara <jack@suse.cz>
 L:	linux-ext4@vger.kernel.org
 S:	Maintained
 F:	fs/jbd/
-F:	include/linux/ext3_jbd.h
 F:	include/linux/jbd.h
 
 JOURNALLING LAYER FOR BLOCK DEVICES (JBD2)
@@ -4300,10 +4392,10 @@ F:	include/linux/kvm*
 F:	virt/kvm/
 
 KERNEL VIRTUAL MACHINE (KVM) FOR AMD-V
-M:	Joerg Roedel <joerg.roedel@amd.com>
+M:	Joerg Roedel <joro@8bytes.org>
 L:	kvm@vger.kernel.org
 W:	http://kvm.qumranet.com
-S:	Supported
+S:	Maintained
 F:	arch/x86/include/asm/svm.h
 F:	arch/x86/kvm/svm.c
 
@@ -4311,6 +4403,7 @@ KERNEL VIRTUAL MACHINE (KVM) FOR POWERPC
 M:	Alexander Graf <agraf@suse.de>
 L:	kvm-ppc@vger.kernel.org
 W:	http://kvm.qumranet.com
+T:	git git://github.com/agraf/linux-2.6.git
 S:	Supported
 F:	arch/powerpc/include/asm/kvm*
 F:	arch/powerpc/kvm/
@@ -4613,6 +4706,14 @@ S:	Maintained
 F:	Documentation/hwmon/lm90
 F:	drivers/hwmon/lm90.c
 
+LME2510 MEDIA DRIVER
+M:	Malcolm Priestley <tvboxspy@gmail.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org/
+Q:	http://patchwork.linuxtv.org/project/linux-media/list/
+S:	Maintained
+F:	drivers/media/usb/dvb-usb-v2/lmedm04*
+
 LOCKDEP AND LOCKSTAT
 M:	Peter Zijlstra <peterz@infradead.org>
 M:	Ingo Molnar <mingo@redhat.com>
@@ -4640,13 +4741,16 @@ S:	Maintained
 F:	fs/logfs/
 
 LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
-M:	Eric Moore <Eric.Moore@lsi.com>
+M:	Nagalakshmi Nandigama <Nagalakshmi.Nandigama@lsi.com>
+M:	Sreekanth Reddy <Sreekanth.Reddy@lsi.com>
 M:	support@lsi.com
 L:	DL-MPTFusionLinux@lsi.com
 L:	linux-scsi@vger.kernel.org
 W:	http://www.lsilogic.com/support
 S:	Supported
 F:	drivers/message/fusion/
+F:	drivers/scsi/mpt2sas/
+F:	drivers/scsi/mpt3sas/
 
 LSILOGIC/SYMBIOS/NCR 53C8XX and 53C1010 PCI-SCSI drivers
 M:	Matthew Wilcox <matthew@wil.cx>
@@ -4703,6 +4807,14 @@ W:	http://www.tazenda.demon.co.uk/phil/linux-hp
 S:	Maintained
 F:	arch/m68k/hp300/
 
+M88RS2000 MEDIA DRIVER
+M:	Malcolm Priestley <tvboxspy@gmail.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org/
+Q:	http://patchwork.linuxtv.org/project/linux-media/list/
+S:	Maintained
+F:	drivers/media/dvb-frontends/m88rs2000*
+
 MAC80211
 M:	Johannes Berg <johannes@sipsolutions.net>
 L:	linux-wireless@vger.kernel.org
@@ -4795,12 +4907,12 @@ F:	Documentation/hwmon/max6650
 F:	drivers/hwmon/max6650.c
 
 MEDIA INPUT INFRASTRUCTURE (V4L/DVB)
-M:	Mauro Carvalho Chehab <mchehab@infradead.org>
+M:	Mauro Carvalho Chehab <mchehab@redhat.com>
 P:	LinuxTV.org Project
 L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org
 Q:	http://patchwork.kernel.org/project/linux-media/list/
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
 F:	Documentation/dvb/
 F:	Documentation/video4linux/
@@ -4808,8 +4920,13 @@ F:	Documentation/DocBook/media/
 F:	drivers/media/
 F:	drivers/staging/media/
 F:	include/media/
-F:	include/linux/dvb/
-F:	include/linux/videodev*.h
+F:	include/uapi/linux/dvb/
+F:	include/uapi/linux/videodev2.h
+F:	include/uapi/linux/media.h
+F:	include/uapi/linux/v4l2-*
+F:	include/uapi/linux/meye.h
+F:	include/uapi/linux/ivtv*
+F:	include/uapi/linux/uvcvideo.h
 
 MEGARAID SCSI DRIVERS
 M:	Neela Syam Kolli <megaraidlinux@lsi.com>
@@ -4883,7 +5000,7 @@ W:	http://popies.net/meye/
 S:	Orphan
 F:	Documentation/video4linux/meye.txt
 F:	drivers/media/pci/meye/
-F:	include/linux/meye.h
+F:	include/uapi/linux/meye.h
 
 MOTOROLA IMX MMC/SD HOST CONTROLLER INTERFACE DRIVER
 M:	Pavel Pisa <ppisa@pikron.com>
@@ -4897,6 +5014,13 @@ S:	Maintained
 F:	Documentation/serial/moxa-smartio
 F:	drivers/tty/mxser.*
 
+MR800 AVERMEDIA USB FM RADIO DRIVER
+M:	Alexey Klimov <klimov.linux@gmail.com>
+L:	linux-media@vger.kernel.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Maintained
+F:	drivers/media/radio/radio-mr800.c
+
 MSI LAPTOP SUPPORT
 M:	"Lee, Chun-Yi" <jlee@novell.com>
 L:	platform-driver-x86@vger.kernel.org
@@ -4974,6 +5098,14 @@ L:	alsa-devel@alsa-project.org
 W:	http://www.native-instruments.com
 F:	sound/usb/caiaq/
 
+NATIVE LINUX KVM TOOL
+M:	Pekka Enberg <penberg@kernel.org>
+M:	Sasha Levin <levinsasha928@gmail.com>
+M:	Asias He <asias.hejun@gmail.com>
+L:	kvm@vger.kernel.org
+S:	Maintained
+F:	tools/kvm/
+
 NCP FILESYSTEM
 M:	Petr Vandrovec <petr@vandrovec.name>
 S:	Odd Fixes
@@ -5062,7 +5194,7 @@ NETWORKING [GENERAL]
 M:	"David S. Miller" <davem@davemloft.net>
 L:	netdev@vger.kernel.org
 W:	http://www.linuxfoundation.org/en/Net
-W:	http://patchwork.ozlabs.org/project/netdev/list/
+Q:	http://patchwork.ozlabs.org/project/netdev/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
 S:	Maintained
@@ -5122,6 +5254,7 @@ F:	drivers/net/wireless/
 NETWORKING DRIVERS
 L:	netdev@vger.kernel.org
 W:	http://www.linuxfoundation.org/en/Net
+Q:	http://patchwork.ozlabs.org/project/netdev/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
 S:	Odd Fixes
@@ -5154,6 +5287,7 @@ F:	net/nfc/
 F:	include/linux/nfc.h
 F:	include/net/nfc/
 F:	drivers/nfc/
+F:	include/linux/platform_data/pn544.h
 
 NFS, SUNRPC, AND LOCKD CLIENTS
 M:	Trond Myklebust <Trond.Myklebust@netapp.com>
@@ -5357,7 +5491,7 @@ F:	drivers/char/pcmcia/cm4040_cs.*
 OMNIVISION OV7670 SENSOR DRIVER
 M:	Jonathan Corbet <corbet@lwn.net>
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
 F:	drivers/media/i2c/ov7670.c
 
@@ -5696,6 +5830,12 @@ S:	Maintained
 F:	drivers/pinctrl/
 F:	include/linux/pinctrl/
 
+PIN CONTROLLER - ATMEL AT91
+M:	Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	drivers/pinctrl/pinctrl-at91.c
+
 PIN CONTROLLER - ST SPEAR
 M:	Viresh Kumar <viresh.linux@gmail.com>
 L:	spear-devel@list.st.com
@@ -5900,11 +6040,18 @@ M:	Mike Isely <isely@pobox.com>
 L:	pvrusb2@isely.net	(subscribers-only)
 L:	linux-media@vger.kernel.org
 W:	http://www.isely.net/pvrusb2/
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
 F:	Documentation/video4linux/README.pvrusb2
 F:	drivers/media/usb/pvrusb2/
 
+PWC WEBCAM DRIVER
+M:	Hans de Goede <hdegoede@redhat.com>
+L:	linux-media@vger.kernel.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Maintained
+F:	drivers/media/usb/pwc/*
+
 PWM SUBSYSTEM
 M:	Thierry Reding <thierry.reding@avionic-design.de>
 L:	linux-kernel@vger.kernel.org
@@ -6047,6 +6194,21 @@ S:	Maintained
 F:	drivers/video/aty/radeon*
 F:	include/linux/radeonfb.h
 
+RADIOSHARK RADIO DRIVER
+M:	Hans de Goede <hdegoede@redhat.com>
+L:	linux-media@vger.kernel.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Maintained
+F:	drivers/media/radio/radio-shark.c
+
+RADIOSHARK2 RADIO DRIVER
+M:	Hans de Goede <hdegoede@redhat.com>
+L:	linux-media@vger.kernel.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Maintained
+F:	drivers/media/radio/radio-shark2.c
+F:	drivers/media/radio/radio-tea5777.c
+
 RAGE128 FRAMEBUFFER DISPLAY DRIVER
 M:	Paul Mackerras <paulus@samba.org>
 L:	linux-fbdev@vger.kernel.org
@@ -6287,10 +6449,19 @@ L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Supported
 F:	drivers/mmc/host/s3cmci.*
 
+SAA7134 VIDEO4LINUX DRIVER
+M:	Mauro Carvalho Chehab <mchehab@redhat.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Odd fixes
+F:	Documentation/video4linux/saa7134/
+F:	drivers/media/pci/saa7134/
+
 SAA7146 VIDEO4LINUX-2 DRIVER
 M:	Michael Hunold <michael@mihu.de>
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 W:	http://www.mihu.de/linux/saa7146
 S:	Maintained
 F:	drivers/media/common/saa7146/
@@ -6325,6 +6496,14 @@ F:	drivers/regulator/s5m*.c
 F:	drivers/rtc/rtc-sec.c
 F:	include/linux/mfd/samsung/
 
+SAMSUNG S3C24XX/S3C64XX SOC SERIES CAMIF DRIVER
+M:	Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
+L:	linux-media@vger.kernel.org
+L:	linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
+S:	Maintained
+F:	drivers/media/platform/s3c-camif/
+F:	include/media/s3c_camif.h
+
 SERIAL DRIVERS
 M:	Alan Cox <alan@linux.intel.com>
 L:	linux-serial@vger.kernel.org
@@ -6423,6 +6602,7 @@ F:	drivers/scsi/st*
 SCTP PROTOCOL
 M:	Vlad Yasevich <vyasevich@gmail.com>
 M:	Sridhar Samudrala <sri@us.ibm.com>
+M:	Neil Horman <nhorman@tuxdriver.com>
 L:	linux-sctp@vger.kernel.org
 W:	http://lksctp.sourceforge.net
 S:	Maintained
@@ -6618,6 +6798,18 @@ S:	Supported
 F:	arch/arm/mach-davinci
 F:	drivers/i2c/busses/i2c-davinci.c
 
+TI DAVINCI SERIES MEDIA DRIVER
+M:	Manjunath Hadli <manjunath.hadli@ti.com>
+M:	Prabhakar Lad <prabhakar.lad@ti.com>
+L:	linux-media@vger.kernel.org
+L:	davinci-linux-open-source@linux.davincidsp.com (moderated for non-subscribers)
+W:	http://linuxtv.org/
+Q:	http://patchwork.linuxtv.org/project/linux-media/list/
+T:	git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
+S:	Supported
+F:	drivers/media/platform/davinci/
+F:	include/media/davinci/
+
 SIS 190 ETHERNET DRIVER
 M:	Francois Romieu <romieu@fr.zoreil.com>
 L:	netdev@vger.kernel.org
@@ -6684,6 +6876,15 @@ M:	Nicolas Pitre <nico@fluxnic.net>
 S:	Odd Fixes
 F:	drivers/net/ethernet/smsc/smc91x.*
 
+SMIA AND SMIA++ IMAGE SENSOR DRIVER
+M:	Sakari Ailus <sakari.ailus@iki.fi>
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	drivers/media/i2c/smiapp
+F:	include/media/smiapp.h
+F:	drivers/media/i2c/smiapp-pll.c
+F:	drivers/media/i2c/smiapp-pll.h
+
 SMM665 HARDWARE MONITOR DRIVER
 M:	Guenter Roeck <linux@roeck-us.net>
 L:	lm-sensors@lm-sensors.org
@@ -6742,7 +6943,7 @@ F:	arch/ia64/sn/
 SOC-CAMERA V4L2 SUBSYSTEM
 M:	Guennadi Liakhovetski <g.liakhovetski@gmx.de>
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
 F:	include/media/soc*
 F:	drivers/media/i2c/soc_camera/
@@ -7232,6 +7433,22 @@ T:	git git://linuxtv.org/mkrufky/tuners.git
 S:	Maintained
 F:	drivers/media/tuners/tda8290.*
 
+TEA5761 TUNER DRIVER
+M:	Mauro Carvalho Chehab <mchehab@redhat.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Odd fixes
+F:	drivers/media/tuners/tea5761.*
+
+TEA5767 TUNER DRIVER
+M:	Mauro Carvalho Chehab <mchehab@redhat.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Maintained
+F:	drivers/media/tuners/tea5767.*
+
 TEAM DRIVER
 M:	Jiri Pirko <jpirko@redhat.com>
 L:	netdev@vger.kernel.org
@@ -7239,6 +7456,12 @@ S:	Supported
 F:	drivers/net/team/
 F:	include/linux/if_team.h
 
+TECHNOTREND USB IR RECEIVER
+M:	Sean Young <sean@mess.org>
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	drivers/media/rc/ttusbir.c
+
 TEGRA SUPPORT
 M:	Stephen Warren <swarren@wwwdotorg.org>
 L:	linux-tegra@vger.kernel.org
@@ -7391,6 +7614,14 @@ S:	Maintained
 F:	include/linux/shmem_fs.h
 F:	mm/shmem.c
 
+TM6000 VIDEO4LINUX DRIVER
+M:	Mauro Carvalho Chehab <mchehab@redhat.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Odd fixes
+F:	drivers/media/usb/tm6000/
+
 TPM DEVICE DRIVER
 M:	Kent Yoder <key@linux.vnet.ibm.com>
 M:	Rajiv Andrade <mail@srajiv.net>
@@ -7424,6 +7655,7 @@ K:	^Subject:.*(?i)trivial
 
 TTY LAYER
 M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+M:	Jiri Slaby <jslaby@suse.cz>
 S:	Supported
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
 F:	drivers/tty/
@@ -7572,6 +7804,12 @@ S:	Maintained
 F:	Documentation/usb/acm.txt
 F:	drivers/usb/class/cdc-acm.*
 
+USB AR5523 WIRELESS DRIVER
+M:	Pontus Fuchs <pontus.fuchs@gmail.com>
+L:	linux-wireless@vger.kernel.org
+S:	Maintained
+F:	drivers/net/wireless/ath/ar5523/
+
 USB ATTACHED SCSI
 M:	Matthew Wilcox <willy@linux.intel.com>
 M:	Sarah Sharp <sarah.a.sharp@linux.intel.com>
@@ -7580,12 +7818,6 @@ L:	linux-scsi@vger.kernel.org
 S:	Supported
 F:	drivers/usb/storage/uas.c
 
-USB BLOCK DRIVER (UB ub)
-M:	Pete Zaitcev <zaitcev@redhat.com>
-L:	linux-usb@vger.kernel.org
-S:	Supported
-F:	drivers/block/ub.c
-
 USB CDC ETHERNET DRIVER
 M:	Oliver Neukum <oliver@neukum.org>
 L:	linux-usb@vger.kernel.org
@@ -7785,7 +8017,7 @@ USB SN9C1xx DRIVER
 M:	Luca Risolia <luca.risolia@studio.unibo.it>
 L:	linux-usb@vger.kernel.org
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 W:	http://www.linux-projects.org
 S:	Maintained
 F:	Documentation/video4linux/sn9c102.txt
@@ -7821,10 +8053,11 @@ USB VIDEO CLASS
 M:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 L:	linux-uvc-devel@lists.sourceforge.net (subscribers-only)
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 W:	http://www.ideasonboard.org/uvc/
 S:	Maintained
 F:	drivers/media/usb/uvc/
+F:	include/uapi/linux/uvcvideo.h
 
 USB WEBCAM GADGET
 M:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
@@ -7856,7 +8089,7 @@ USB ZR364XX DRIVER
 M:	Antoine Jacquet <royale@zerezo.com>
 L:	linux-usb@vger.kernel.org
 L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+T:	git git://linuxtv.org/media_tree.git
 W:	http://royale.zerezo.com/zr364xx/
 S:	Maintained
 F:	Documentation/video4linux/zr364xx.txt
@@ -8211,6 +8444,14 @@ L:	linux-edac@vger.kernel.org
 S:	Maintained
 F:	arch/x86/kernel/cpu/mcheck/*
 
+XC2028/3028 TUNER DRIVER
+M:	Mauro Carvalho Chehab <mchehab@redhat.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Maintained
+F:	drivers/media/tuners/tuner-xc2028.*
+
 XEN HYPERVISOR INTERFACE
 M:	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
 M:	Jeremy Fitzhardinge <jeremy@goop.org>
diff --git a/Makefile b/Makefile
index 3d2fc46..9e5fcac 100644
--- a/Makefile
+++ b/Makefile
@@ -124,7 +124,7 @@ $(if $(KBUILD_OUTPUT),, \
 PHONY += $(MAKECMDGOALS) sub-make
 
 $(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
-	$(Q)@:
+	@:
 
 sub-make: FORCE
 	$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
@@ -981,6 +981,12 @@ _modinst_post: _modinst_
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst
 	$(call cmd,depmod)
 
+ifeq ($(CONFIG_MODULE_SIG), y)
+PHONY += modules_sign
+modules_sign:
+	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modsign
+endif
+
 else # CONFIG_MODULES
 
 # Modules not configured
diff --git a/Next/SHA1s b/Next/SHA1s
new file mode 100644
index 0000000..5c09056
--- /dev/null
+++ b/Next/SHA1s
@@ -0,0 +1,213 @@
+Name		SHA1
+----		----
+origin		e23739b4ade80a3a7f87198f008f6c44a7cbc9fd
+fixes		12250d843e8489ee00b5b7726da855e51694e792
+kbuild-current	bad9955db1b73d7286f74a8136a0628a9b1ac017
+arm-current	5010192d5ae589002c4453d6c6e662e5e9acae59
+m68k-current	34fa78b59c52d1db3513db4c1a999db26b2e9ac2
+powerpc-merge	e716e014384688d1a50d1aa5213ee74748c6d4e0
+sparc		194d9831f0419b5125dc94ec0ece4434d8ef74f0
+net		3ed7147189d2fbe8ac6da95db2fd9d6d52f53ce9
+sound-current	d846b17475d52f037437d125cd19c28f1d36e4f0
+pci-current	ff8e59bc4ec3f31789a47dce9b6fe44bd7bc5fcc
+wireless	6bdd253f635f7b2ef027d116933a6c9ec148b87f
+driver-core.current	77b67063bb6bce6d475e910d3b886a606d0d91f7
+tty.current	b1a925f44a3a21c538144e30b08f966cad7adb63
+usb.current	f4a75d2eb7b1e2206094b901be09adb31ba63681
+staging.current	f4a75d2eb7b1e2206094b901be09adb31ba63681
+char-misc.current	f4a75d2eb7b1e2206094b901be09adb31ba63681
+input-current	0a0d62857366d8a6531e7fed1c3ccdd9a2b5b40b
+md-current	874807a83139abc094f939e93623c5623573d543
+audit-current	c158a35c8a681cf68d36f22f058f9f5466386c71
+crypto-current	9efade1b3e981f5064f9db9ca971b4dc7557ae42
+ide		9974e43d900af7979e0a571b8e0c9674c7399b79
+dwmw2		244dc4e54b73567fae7f8fd9ba56584be9375442
+sh-current	44033109e99cf584d6285226ed521098f5ef7250
+irqdomain-current	a0d271cbfed1dd50278c6b06bead3d00ba0a88f9
+devicetree-current	0e622d39197f0b64b9e043fe75ac3634bf9f3a05
+spi-current	a0d271cbfed1dd50278c6b06bead3d00ba0a88f9
+gpio-current	96b70641b937e99c1579cb6ebbcdb7b0af98cdd0
+rr-fixes	b251f0f399e275b027d6541cfbac1d2a3206b44a
+asm-generic	9b04ebd1584766229c58fedaa8fe4dfff575ac3a
+arm		6b9c9f6e6bb7093ff9c6563b990cd30c760a8efd
+arm-perf	3d70f8c617a436c7146ecb81df2265b4626dfe89
+davinci		fe0d42203cb5616eeff68b14576a0f7e2dd56625
+xilinx		74cad6042156c30fe64d3226e041c77139ae8bcf
+arm64		8f3bfa584ed05e9e7d290707c48eee026fb94ece
+blackfin	9d8460173f6f6089cb001066f92c889832da8fab
+c6x		93bbd0c087eb299e0fe11c59d340932180c082b5
+cris		eacb25c79aa10bccd17854df664694bc9ee79184
+hexagon		e1858b2a21cd84a855945a4747fb2db41b250c22
+ia64		7843ae0ec641fe3acd02f966d45909f3e42e3e63
+m68k		5fec45a20db3656ce36fac24639aac76c6641215
+m68knommu	5a1b2a15cc95d93767b5ceaf490685ab1a9caaa5
+microblaze	f229605441030bcd315c21d97b25889d63ed0130
+mips		46845cf7280edff8151b654e6420d4a11e96b1df
+openrisc	634bd40a894d64df09ba36c12bb6e70787989ba9
+parisc		949a05d03490e39e773e8652ccab9157e6f595b4
+powerpc		3991782ea3e41412f8a665cd6ce66943d76aff8a
+4xx		2074b1d9d53ae696dd3f49482bad43254f40f01d
+mpc5xxx		451815bc42b8b6b8d7e02b16d5ba333a93ce0c1a
+galak		1723d90915d4689fa2e8cd4151d45ea38c96cb99
+s390		683c3dcef439f969b2c7fd09b60144cb4e2155a5
+sh		0dd4d5cbe4c38165dc9b3ad329ebb23f24d74fdb
+sparc-next	43c422eda99b894f18d1cca17bcd2401efaf7bd0
+tile		ddffeb8c4d0331609ef2581d84de4d763607bd37
+unicore32	c284464658acab50c67ff65ff3dc9215a0231ad2
+xtensa		518129b24e46c34a8d2b4c7aa046c41fac765f33
+btrfs		c37b2b6269ee4637fb7cdb5da0d1e47215d57ce2
+ceph		35152979e6181b1fbb4b61c3ff641c14df53ad66
+cifs		0670be919505f2d003977b636d846dd4062bf9a8
+configfs	b930c26416c4ea6855726fd977145ccea9afbdda
+ecryptfs	e4bc6522d53b7b8eb02cfac35fd18275fd86269d
+ext3		55eede29d55a97fce2f9b5c21d4804f4a2b59158
+ext4		f3b59291a69d0b734be1fc8be489fef2dd846d3d
+f2fs		660a59509fbf2081bda4a824f54c541eddc9995a
+fuse		23ab0c76c0855eca2beffcdc9ed4a5a41043fb69
+gfs2		1e2d9d44f3ceb7dac7cb14d2476d0a8128c8e169
+jfs		4e7a4b01222343481d8ff084dbef9b80f7089a19
+logfs		339466142b3f58fe0ee4dea7e8c5f3d33099e89c
+nfs		f937b66ad1af768617e0fb0b1f517450019cddb4
+nfsd		f3c7521fe53a7892d8c8c4715f7c0f4add7b2e19
+ocfs2		4538df64655dcfe17b33080b219dc783161a262e
+omfs		976d167615b64e14bc1491ca51d424e2ba9a5e84
+squashfs	4b0180a49f08dd1c681cdc99edc9e0cec0a833fa
+v9fs		552aad02a283ee88406b102b4d6455eef7127196
+ubifs		a28ad42a4a0c6f302f488f26488b8b37c9b30024
+xfs		7c4cebe8e02dd0b0e655605442bbe9268db9ed4f
+vfs		a736427fa1103158338839813139b20763c7b13e
+pci		053f328c93a3fc9713abfa7060454438407e94a7
+hid		aad2d4622ebfc70d03439a7e801f7305d6a54096
+i2c		c1ec1ae179f67f6a3acc2fbb2e7a35c2e220753f
+i2c-embedded	60937b2cdbf948ddb84cbf5d728012519ff4b321
+jdelvare-hwmon	d2d9cf34496831c002e470517a0273bcb05da2cd
+hwmon-staging	8b59397f37b4712df0712e8a289283a309020342
+v4l-dvb		5a79780728421ccee54c6d032178368d0e442022
+kbuild		a5ce08dcd7ab248b78f51d9a60e04761ca7fbba4
+kconfig		4eae518d4b01b0cbf2f0d8edb5a6f3d6245ee8fb
+libata		a52f514c911978dee418f19d1d0103e3bc25fa62
+infiniband	d0951d2133f260e216dbaa8dadcc73d3d5237809
+pstore		b042e47491ba5f487601b5141a3f1d8582304170
+acpi		32cc109cbbeac76d7a772e2dd4d6f9480313528c
+cpuidle		3cf7997a389de59498c966c529456696ce8bc1a7
+cpupowerutils	f16603386b38c28979f4df1cafdc2fe73fa87d37
+thermal		d12250ef8dc1bbc811d505776be053e358ba82f5
+ieee1394	790198f74c9d1b46b6a89504361b1a844670d050
+ubi		6a059abdbae7b6b35ddc69f6336f7afc1ce79bac
+dlm		da8c66638ae684c99abcb30e89d2803402e7ca20
+swiotlb		af51a9f1848ff50079a10def56a2c064f326af22
+scsi		a3667aaed5698b84bad2f1b3f71adc86499f4bc6
+target-updates	3e4f574857eebce60bb56d7524f3f9eaa2a126d0
+target-merge	6f0c0580b70c89094b3422ba81118c7b959c7556
+ibft		935a9fee51c945b8942be2d7b4bae069167b4886
+isci		6734092e66011def7875bd67beef889d0fee1cc9
+slave-dma	f9744dde1fb0259fba4623749b194dc622156988
+dmaengine	a2bd1140a264b561e38d99e656cd843c2d840e86
+net-next	f4e0b4c5e1c3eac9b7376ce73fb63de436057db1
+wireless-next	0751f8654602e4255f0b9c17784d8100d5896010
+bluetooth	a0110f4ca6ef3410597adb8ce7f09fbe0ec919a1
+mtd		35f95d228e55eebdc87b5c0dbdecc46884f476a6
+l2-mtd		0f722de047e3e041d33446b570f8c960ad188965
+crypto		a465348ff5d3e564ae0bcde63d5ef2066c079aad
+drm		28164fdad85ec806f30c76fe98ed0e3abc91d2d7
+sound		361dab3ec2c59044f420cdf232523cd4af4e833e
+sound-asoc	77286406ee871243f7601852f6e552292af076d6
+modules		56713a28675b966e027a824a0130b80dffab209f
+virtio		b15a62a51cbf27fd36fc3cd63962ae67b45e07ef
+input		852d20aed8a029ea8496e85052493b275f19d22b
+input-mt	6f0c0580b70c89094b3422ba81118c7b959c7556
+cgroup		9718ceb3431acdeee9bdec5c18e18266333970aa
+block		95678efc1e9aa7bbc4add2dd374721c5c66e0dcf
+device-mapper	cee3685bb2d9a7ce21520f810d27030472f1077b
+embedded	4744b43431e8613f920c5cba88346756f53c5165
+firmware	6e03a201bbe8137487f340d26aa662110e324b20
+pcmcia		80af9e6d7ae633309cc5bca96aee6a45117e7c98
+mmc		2656109070eddd02d771c926e5648f0787918b19
+kgdb		58bcdf6847831913b41e9dfee1cbc579f939ef8b
+slab		f1d58d715a1d8b937eb8f89c593e55fa7534eb6a
+uclinux		ddffeb8c4d0331609ef2581d84de4d763607bd37
+md		fb07ccebfd75d8a84910c670f255b76c76579d7a
+mfd		64cdfe256aae6d43d472331ba03bd4ccbfcb1abb
+battery		eba3b670a9166a91be5a11fe33290dca6b9457a2
+fbdev		cd9d6f10d07f26dd8a70e519c22b6b4f8a9e3e7a
+viafb		838ac785d521e091bd8b5f6a2b545166f5f32b77
+omap_dss2	474ff6b8a79093aea966b6246d5b8000de124da9
+regulator	47366619fae316329f48c5ad51deec966930ad16
+security	c91c1bf2f53482c7d8111aa347abdcba148e5668
+selinux		c2d7b247f0c028d325a5da5b9611b60ba160f237
+lblnet		7e27d6e778cd87b6f2415515d7127eba53fe5d02
+watchdog	58ddfed79a60ba5d5eb4dce2767aa592947e1586
+dwmw2-iommu	c3b92c8787367a8bb53d57d9789b558f1295cc96
+iommu		f6cffc1f283e11f623a9b7c36fd9cd32b77ccb1c
+vfio		74d8627792be5ac767780d0f1c8baea9271934b8
+osd		b6755ffb0c03c2e763cc56f72cc2ceaba8ea2805
+jc_docs		5c050fb96380a87a85aad9084b68fdcd2b84c193
+trivial		8fdbb340ef0683437e791360d63726d5725add66
+audit		dcd6c92267155e70a94b3927bce681ce74b80d1f
+pm		6e35af9b955be43d980e6181cc703476419ed62d
+apm		fb9d78aca709b7a6389c79d6211fb384c69bb79f
+fsnotify	1aec9c0d718693553543349e92138033b0bcea4c
+edac		5e75cbbc849a5dab7c3446e15a2fe5237414cb24
+edac-amd	a8373ecc0c26d8afafd0d2e88f96756e26b7f3ee
+devicetree	155dd0c2f7c24c1531a90229f1c749cebf3f21f7
+dt-rh		bd0ba3759fb0655ad619a74b2fe75092636fb1e9
+spi		743179849015dc71bb2ea63d8cd4bfa7fdfb4bc6
+spi-mb		170c2d0a87922adb43a8e8ca47cba3e30407d4d6
+tip		a07005cbd84724600e46a709a6a10ed0350f241a
+ftrace		bf3071f5a054db9e5bab873355d27a7330ce5187
+rcu		98dbec158343a1220d2905adb0e338c2a77c2e77
+cputime		c3e0ef9a298e028a82ada28101ccd5cf64d209ee
+uprobes		0326f5a94ddea33fa331b2519f4172f4fb387baa
+kvm		807f12e57c9783458b8c07f63eff3c3e1df8ab5d
+kvm-ppc		a2ef34ac04527d794df0c59d0c78ff7bf3f493a3
+oprofile	44009105081b51417f311f4c3be0061870b6b8ed
+xen		af3a3ab2966112c0d0a44df7eeb1e95fe32d4495
+xen-two		ca63454c05deabcfcd44b5dde7b9344b811061a8
+xen-pvhvm	b056b6a0144de90707cd22cf7b4f60bf69c86d59
+percpu		b4916cb17c261a6043bcb2a98d0d6512497a7cf8
+workqueues	d8318e5e51f42001b11f2b7bed968bad4eecf432
+drivers-x86	455f38ccba672b33cda0a96cf9089be312ba95de
+hwpoison	46e387bbd82d438b9131e237e6e2cb55a825da49
+sysctl		4e474a00d7ff746ed177ddae14fa8b2d4bad7a00
+regmap		51b6d983b23ea28fbd8a445142505f019bcaf7da
+hsi		43139a61fc68f4b0af7327a0e63f340a7c81c69a
+leds		09f5fe756329fd7fb6ccb94563960d6a22eaaab2
+driver-core	da095fd3d5063f2dd03468d71f7df39a0430d86f
+tty		218cbbd82132d48c6f4e042e31beb6019f92db01
+usb		fb37ef98015f864d22be223a0e0d93547cd1d4ef
+staging		8b7a13c3f404cbd26b495fa9c34339cb9b7b8164
+char-misc	962b686c450493adb8596e813bdfd0e1613482e6
+tmem		8f0d8163b50e01f398b14bcd4dc039ac5ab18d64
+writeback	2f60d628ffd042e65e0b1d3431fb3e38d6f7c1be
+arm-dt		ede338f4ce2fb5ee99d18751df32fbd3b10df268
+hwspinlock	8b37fcfc9b3400b647748783a2cafff67793e0ad
+pinctrl		e7125b5249455146b8e260ecc261e65b8ae6b68e
+vhost		e0953c8b85baaa38d77ebd5dc4051bc3837c1191
+memblock	7bd0b0f0da3b1ec11cbcc798eb0ef747a1184077
+remoteproc	6f0c0580b70c89094b3422ba81118c7b959c7556
+irqdomain	a0d271cbfed1dd50278c6b06bead3d00ba0a88f9
+gpio		b53bc2819a71099ecfc3d61ba0796b3dcc6be321
+gpio-lw		12fff48d7fbab64ff4164a09864a28e2f45f5ded
+arm-soc		659b19ca3a77e2ac32fe84d95242653c75dd07c7
+bcm2835		d7f292ea1d34383a0f2181d8bbe85f272bf86cb5
+cortex		77a3018e38b901f565b36f16924a3f86ad3e7328
+ep93xx		fab1f7446a5baac4bf2f90e151a879677c0de916
+ixp4xx		b94740b3b38fd8e37fcd3bb06a18ec2796061c7d
+msm		a0d271cbfed1dd50278c6b06bead3d00ba0a88f9
+renesas		6cee927094f4813151bee91ddc45556c5ca8f77e
+samsung		d1a8169e923d749477935a5984c2dc204a0824c4
+tegra		3c8d1fc07405e749b019372df1c971a884926592
+kvmtool		6f09dabf84e68ae16c815791939c3de93102f6d2
+dma-mapping	2b8836a7fcae3bf2afe80f62cceafc3ad7d85632
+pwm		9685ac4bff68d44816235915fcceca9b2728c1b9
+dma-buf		ba4205121f8199c32658b03c2660b1a9f9ff217c
+userns		98f842e675f96ffac96e6c50315790912b2812be
+ktest		95f57838418358e93212e9dddd60d3502c7f8e2e
+signal		9c581db8bae71af613015ee6e53d325eefaff857
+clk		1f61e5f143b578606389887887af549bc5554353
+random		ec8f02da9ea500474417d1d31fa3d46a562ab366
+lzo-update	ba32bf9f4149eeab14bb97ca2edd2f8d1619dfd8
+drop-experimental	f4255699ca46f969566b1bb051ce72e148c4afa6
+scsi-post-merge	65112dccf8a113737684366349d7f9ec373ddc47
+akpm-current	064904e0d5055892ea494e2fadcef3b706b53732
+akpm		dc9e38273c2dad3414c61fa2a625d1a69d74f176
diff --git a/Next/Trees b/Next/Trees
new file mode 100644
index 0000000..799360f
--- /dev/null
+++ b/Next/Trees
@@ -0,0 +1,215 @@
+Trees included into this release:
+
+Name		Type	URL
+----		----	---
+origin		git	git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git#master
+fixes		git	git://git.kernel.org/pub/scm/linux/kernel/git/sfr/next-fixes.git#master
+kbuild-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild.git#rc-fixes
+arm-current	git	git://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-arm.git#fixes
+m68k-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git#for-linus
+powerpc-merge	git	git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git#merge
+sparc		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc.git#master
+net		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git#master
+sound-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git#for-linus
+pci-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git#for-linus
+wireless	git	git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git#master
+driver-core.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git#driver-core-linus
+tty.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git#tty-linus
+usb.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git#usb-linus
+staging.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git#staging-linus
+char-misc.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git#char-misc-linus
+input-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git#for-linus
+md-current	git	git://neil.brown.name/md#for-linus
+audit-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit.git#for-linus
+crypto-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git#master
+ide		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide.git#master
+dwmw2		git	git://git.infradead.org/users/dwmw2/random-2.6.git#master
+sh-current	git	git://github.com/pmundt/linux-sh.git#sh-fixes-for-linus
+irqdomain-current	git	git://git.secretlab.ca/git/linux-2.6.git#irqdomain/merge
+devicetree-current	git	git://git.secretlab.ca/git/linux-2.6#devicetree/merge
+spi-current	git	git://git.secretlab.ca/git/linux-2.6#spi/merge
+gpio-current	git	git://git.secretlab.ca/git/linux-2.6#gpio/merge
+rr-fixes	git	git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux.git#fixes
+asm-generic	git	git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic.git#master
+arm		git	git://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-arm.git#for-next
+arm-perf	git	git://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git#for-next/perf
+davinci		git	git://gitorious.org/linux-davinci/linux-davinci.git#davinci-next
+xilinx		git	git://git.xilinx.com/linux-2.6-xlnx.git#arm-next
+arm64		git	git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux-aarch64.git#upstream
+blackfin	git	git://git.kernel.org/pub/scm/linux/kernel/git/lliubbo/blackfin.git#for-linus
+c6x		git	git://linux-c6x.org/git/projects/linux-c6x-upstreaming.git#for-linux-next
+cris		git	git://www.jni.nu/cris.git#for-next
+hexagon		git	git://git.kernel.org/pub/scm/linux/kernel/git/rkuo/linux-hexagon-kernel.git#linux-next
+ia64		git	git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux.git#next
+m68k		git	git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git#for-next
+m68knommu	git	git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu.git#for-next
+microblaze	git	git://git.monstr.eu/linux-2.6-microblaze.git#next
+mips		git	git://git.linux-mips.org/pub/scm/ralf/upstream-sfr.git#mips-for-linux-next
+openrisc	git	git://openrisc.net/jonas/linux#for-upstream
+parisc		git	git://git.kernel.org/pub/scm/linux/kernel/git/jejb/parisc-2.6.git#for-next
+powerpc		git	git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git#next
+4xx		git	git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc-4xx.git#next
+mpc5xxx		git	git://git.denx.de/linux-2.6-agust.git#next
+galak		git	git://git.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git#next
+s390		git	git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git#features
+sh		git	git://github.com/pmundt/linux-sh.git#sh-latest
+sparc-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next.git#master
+tile		git	git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile.git#master
+unicore32	git	git://github.com/gxt/linux.git#unicore32
+xtensa		git	git://github.com/czankel/xtensa-linux.git#for_next
+btrfs		git	git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs.git#next
+ceph		git	git://github.com/ceph/ceph-client.git#master
+cifs		git	git://git.samba.org/sfrench/cifs-2.6.git#for-next
+configfs	git	git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/configfs.git#linux-next
+ecryptfs	git	git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs.git#next
+ext3		git	git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs.git#for_next
+ext4		git	git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git#dev
+f2fs		git	git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git#dev
+fuse		git	git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git#for-next
+gfs2		git	git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw.git#master
+jfs		git	git://github.com/kleikamp/linux-shaggy.git#jfs-next
+logfs		git	git://github.com/prasad-joshi/logfs_upstream.git#master
+nfs		git	git://git.linux-nfs.org/projects/trondmy/nfs-2.6.git#linux-next
+nfsd		git	git://git.linux-nfs.org/~bfields/linux.git#nfsd-next
+ocfs2		git	git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2.git#linux-next
+omfs		git	git://github.com/bcopeland/omfs.git#for-next
+squashfs	git	git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-next.git#master
+v9fs		git	git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs.git#for-next
+ubifs		git	git://git.infradead.org/ubifs-2.6.git#linux-next
+xfs		git	git://oss.sgi.com/xfs/xfs.git#for-next
+vfs		git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6.git#for-next
+pci		git	git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git#next
+hid		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git#for-next
+i2c		quilt	http://khali.linux-fr.org/devel/linux-3/jdelvare-i2c/
+i2c-embedded	git	git://git.pengutronix.de/git/wsa/linux.git#i2c-embedded/for-next
+jdelvare-hwmon	quilt	http://khali.linux-fr.org/devel/linux-3/jdelvare-hwmon/
+hwmon-staging	git	git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git#hwmon-next
+v4l-dvb		git	git://linuxtv.org/mchehab/media-next.git#master
+kbuild		git	git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild.git#for-next
+kconfig		git	git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-kconfig.git#for-next
+libata		git	git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git#NEXT
+infiniband	git	git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git#for-next
+pstore		git	git://git.infradead.org/users/cbou/linux-pstore.git#master
+acpi		git	git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git#next
+cpuidle		git	git://git.linaro.org/people/dlezcano/cpuidle-next.git#cpuidle-next
+cpupowerutils	git	git://git.kernel.org/pub/scm/linux/kernel/git/brodo/cpupowerutils.git#master
+thermal		git	git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git#next
+ieee1394	git	git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394.git#for-next
+ubi		git	git://git.infradead.org/ubi-2.6.git#linux-next
+dlm		git	git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm.git#next
+swiotlb		git	git://git.kernel.org/pub/scm/linux/kernel/git/konrad/swiotlb.git#linux-next
+scsi		git	git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git#for-next
+target-updates	git	git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git#for-next
+target-merge	git	git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git#for-next-merge
+ibft		git	git://git.kernel.org/pub/scm/linux/kernel/git/konrad/ibft.git#linux-next
+isci		git	git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git#all
+slave-dma	git	git://git.infradead.org/users/vkoul/slave-dma.git#next
+dmaengine	git	git://git.kernel.org/pub/scm/linux/kernel/git/djbw/dmaengine.git#next
+net-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git#master
+wireless-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next.git#master
+bluetooth	git	git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git#master
+mtd		git	git://git.infradead.org/mtd-2.6.git#master
+l2-mtd		git	git://git.infradead.org/users/dedekind/l2-mtd-2.6.git#master
+crypto		git	git://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git#master
+drm		git	git://people.freedesktop.org/~airlied/linux.git#drm-next
+sound		git	git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git#for-next
+sound-asoc	git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git#for-next
+modules		git	git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux.git#modules-next
+virtio		git	git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux.git#virtio-next
+input		git	git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git#next
+input-mt	git	git://github.com/rydberg/linux.git#for-next
+cgroup		git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git#for-next
+block		git	git://git.kernel.dk/linux-block.git#for-next
+device-mapper	quilt	http://people.redhat.com/agk/patches/linux/editing/
+embedded	git	git://git.infradead.org/embedded-2.6.git#master
+firmware	git	git://git.infradead.org/users/dwmw2/firmware-2.6.git#master
+pcmcia		git	git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia.git#master
+mmc		git	git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git#mmc-next
+kgdb		git	git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb.git#kgdb-next
+slab		git	git://github.com/penberg/linux.git#for-next
+uclinux		git	git://git.kernel.org/pub/scm/linux/kernel/git/gerg/uclinux.git#for-next
+md		git	git://neil.brown.name/md#for-next
+mfd		git	git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6.git#for-next
+battery		git	git://git.infradead.org/battery-2.6.git#master
+fbdev		git	git://github.com/schandinat/linux-2.6.git#fbdev-next
+viafb		git	git://github.com/schandinat/linux-2.6.git#viafb-next
+omap_dss2	git	git://gitorious.org/linux-omap-dss2/linux.git#for-next
+regulator	git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git#for-next
+security	git	git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git#next
+selinux		git	git://git.infradead.org/users/eparis/selinux.git#master
+lblnet		git	git://git.infradead.org/users/pcmoore/lblnet-2.6_next#master
+watchdog	git	git://www.linux-watchdog.org/linux-watchdog-next.git#master
+dwmw2-iommu	git	git://git.infradead.org/iommu-2.6.git#master
+iommu		git	git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git#next
+vfio		git	git://github.com/awilliam/linux-vfio.git#next
+osd		git	git://git.open-osd.org/linux-open-osd.git#linux-next
+jc_docs		git	git://git.lwn.net/linux-2.6.git#docs-next
+trivial		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial.git#for-next
+audit		git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit.git#for-next
+pm		git	git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git#linux-next
+apm		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/apm.git#for-next
+fsnotify	git	git://git.infradead.org/users/eparis/notify.git#for-next
+edac		git	git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac.git#linux_next
+edac-amd	git	git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git#for-next
+devicetree	git	git://git.secretlab.ca/git/linux-2.6#devicetree/next
+dt-rh		git	git://sources.calxeda.com/kernel/linux.git#for-next
+spi		git	git://git.secretlab.ca/git/linux-2.6#spi/next
+spi-mb		git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/misc.git#spi-next
+tip		git	git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git#auto-latest
+ftrace		git	git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git#for-next
+rcu		git	git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git#rcu/next
+cputime		git	git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git#cputime
+uprobes		git	git://github.com/srikard/linux.git#for-next
+kvm		git	git://git.kernel.org/pub/scm/virt/kvm/kvm.git#linux-next
+kvm-ppc		git	git://github.com/agraf/linux-2.6.git#kvm-ppc-next
+oprofile	git	git://git.kernel.org/pub/scm/linux/kernel/git/rric/oprofile.git#for-next
+xen		git	git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git#upstream/xen
+xen-two		git	git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen.git#linux-next
+xen-pvhvm	git	git://xenbits.xen.org/people/sstabellini/linux-pvhvm.git#linux-next
+percpu		git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu.git#for-next
+workqueues	git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git#for-next
+drivers-x86	git	git://cavan.codon.org.uk/platform-drivers-x86.git#linux-next
+hwpoison	git	git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6.git#hwpoison
+sysctl		git	git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/sysctl.git#master
+regmap		git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git#for-next
+hsi		git	git://gitorious.org/kernel-hsi/kernel-hsi.git#for-next
+leds		git	git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git#for-next
+driver-core	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git#driver-core-next
+tty		git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git#tty-next
+usb		git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git#usb-next
+staging		git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git#staging-next
+char-misc	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git#char-misc-next
+tmem		git	git://git.kernel.org/pub/scm/linux/kernel/git/konrad/mm.git#linux-next
+writeback	git	git://git.kernel.org/pub/scm/linux/kernel/git/wfg/linux.git#writeback-for-next
+arm-dt		git	git://git.secretlab.ca/git/linux-2.6#devicetree/arm-next
+hwspinlock	git	git://github.com/ohadbc/hwspinlock-next.git#linux-next
+pinctrl		git	git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git#for-next
+vhost		git	git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git#linux-next
+memblock	git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git#memblock-kill-early_node_map
+remoteproc	git	git://git.kernel.org/pub/scm/linux/kernel/git/ohad/remoteproc.git#for-next
+irqdomain	git	git://git.secretlab.ca/git/linux-2.6.git#irqdomain/next
+gpio		git	git://git.secretlab.ca/git/linux-2.6#gpio/next
+gpio-lw		git	git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git#for-next
+arm-soc		git	git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git#for-next
+bcm2835		git	git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git#for-next
+cortex		git	git://git.pengutronix.de/git/ukl/linux-2.6.git#for-next
+ep93xx		git	git://github.com/RyanMallon/linux-ep93xx.git#ep93xx-for-next
+ixp4xx		git	git://git.kernel.org/pub/scm/linux/kernel/git/chris/linux.git#next
+msm		git	git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git#for-next
+renesas		git	git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git#next
+samsung		git	git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git#for-next
+tegra		git	git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git#for-next
+kvmtool		git	git://github.com/penberg/linux-kvm.git#master
+dma-mapping	git	git://git.linaro.org/people/mszyprowski/linux-dma-mapping.git#dma-mapping-next
+pwm		git	git://gitorious.org/linux-pwm/linux-pwm.git#for-next
+dma-buf		git	git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git#for-next
+userns		git	git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git#for-next
+ktest		git	git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-ktest.git#for-next
+signal		git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal.git#for-next
+clk		git	git://git.linaro.org/people/mturquette/linux.git#clk-next
+random		git	git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random.git#dev
+lzo-update	git	git://github.com/markus-oberhumer/linux.git#lzo-update
+drop-experimental	git	git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git#linux-next
+scsi-post-merge	git	git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-post-merge-2.6.git#master
+akpm-current	mmotm	http://www.ozlabs.org/~akpm/mmotm/
+akpm		mmotm	http://www.ozlabs.org/~akpm/mmotm/
diff --git a/Next/merge.log b/Next/merge.log
new file mode 100644
index 0000000..dfbd9a6
--- /dev/null
+++ b/Next/merge.log
@@ -0,0 +1,13435 @@
+$ date
+Thursday 29 November  09:06:18 EST 2012
+$ git checkout master
+Already on 'master'
+$ git reset --hard stable
+HEAD is now at e23739b Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
+Merging origin/master (e23739b Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media)
+$ git merge origin/master
+Already up-to-date.
+Merging fixes/master (12250d8 Merge branch 'i2c-embedded/for-next' of git://git.pengutronix.de/git/wsa/linux)
+$ git merge fixes/master
+Already up-to-date.
+Merging kbuild-current/rc-fixes (bad9955 menuconfig: Replace CIRCLEQ by list_head-style lists.)
+$ git merge kbuild-current/rc-fixes
+Already up-to-date.
+Merging arm-current/fixes (5010192 ARM: 7583/1: decompressor: Enable unaligned memory access for v6 and above)
+$ git merge arm-current/fixes
+Already up-to-date.
+Merging m68k-current/for-linus (34fa78b m68k: fix sigset_t accessor functions)
+$ git merge m68k-current/for-linus
+Already up-to-date.
+Merging powerpc-merge/merge (e716e01 powerpc/eeh: Do not invalidate PE properly)
+$ git merge powerpc-merge/merge
+Already up-to-date.
+Merging sparc/master (194d983 Merge tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound)
+$ git merge sparc/master
+Already up-to-date.
+Merging net/master (3ed7147 team: fix hw_features setup)
+$ git merge net/master
+Merge made by the 'recursive' strategy.
+ drivers/atm/ambassador.c                       |    1 +
+ drivers/net/can/usb/peak_usb/pcan_usb.c        |    8 ++++++--
+ drivers/net/can/usb/peak_usb/pcan_usb_pro.c    |    8 ++++++--
+ drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c |    2 +-
+ drivers/net/team/team.c                        |    4 +++-
+ drivers/net/usb/qmi_wwan.c                     |    1 +
+ drivers/vhost/vhost.c                          |    2 +-
+ net/can/bcm.c                                  |    3 +++
+ net/ipv4/icmp.c                                |    3 ++-
+ net/ipv4/ipmr.c                                |    4 ++++
+ net/irda/irttp.c                               |    1 +
+ net/netfilter/ipset/ip_set_hash_netiface.c     |    2 +-
+ net/sctp/chunk.c                               |   20 ++++++++++++++------
+ net/sctp/socket.c                              |    4 ++--
+ net/sctp/transport.c                           |    2 +-
+ 15 files changed, 47 insertions(+), 18 deletions(-)
+Merging sound-current/for-linus (d846b17 ALSA: hda - Fix build without CONFIG_PM)
+$ git merge sound-current/for-linus
+Already up-to-date.
+Merging pci-current/for-linus (ff8e59b PCI/portdrv: Don't create hotplug slots unless port supports hotplug)
+$ git merge pci-current/for-linus
+Already up-to-date.
+Merging wireless/master (6bdd253 mac80211: fix remain-on-channel (non-)cancelling)
+$ git merge wireless/master
+Merge made by the 'recursive' strategy.
+ drivers/net/wireless/iwlwifi/dvm/rxon.c |   12 ++++++------
+ net/mac80211/offchannel.c               |    2 --
+ 2 files changed, 6 insertions(+), 8 deletions(-)
+Merging driver-core.current/driver-core-linus (77b6706 Linux 3.7-rc5)
+$ git merge driver-core.current/driver-core-linus
+Already up-to-date.
+Merging tty.current/tty-linus (b1a925f tty vt: Fix a regression in command line edition)
+$ git merge tty.current/tty-linus
+Already up-to-date.
+Merging usb.current/usb-linus (f4a75d2e Linux 3.7-rc6)
+$ git merge usb.current/usb-linus
+Already up-to-date.
+Merging staging.current/staging-linus (f4a75d2e Linux 3.7-rc6)
+$ git merge staging.current/staging-linus
+Already up-to-date.
+Merging char-misc.current/char-misc-linus (f4a75d2e Linux 3.7-rc6)
+$ git merge char-misc.current/char-misc-linus
+Already up-to-date.
+Merging input-current/for-linus (0a0d628 ARM - OMAP: ads7846: fix pendown debounce setting)
+$ git merge input-current/for-linus
+Already up-to-date.
+Merging md-current/for-linus (874807a md/raid1{,0}: fix deadlock in bitmap_unplug.)
+$ git merge md-current/for-linus
+Merge made by the 'recursive' strategy.
+ drivers/md/raid1.c  |    2 +-
+ drivers/md/raid10.c |    2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+Merging audit-current/for-linus (c158a35 audit: no leading space in audit_log_d_path prefix)
+$ git merge audit-current/for-linus
+Already up-to-date.
+Merging crypto-current/master (9efade1 crypto: cryptd - disable softirqs in cryptd_queue_worker to prevent data corruption)
+$ git merge crypto-current/master
+Already up-to-date.
+Merging ide/master (9974e43 ide: fix generic_ide_suspend/resume Oops)
+$ git merge ide/master
+Already up-to-date.
+Merging dwmw2/master (244dc4e Merge git://git.infradead.org/users/dwmw2/random-2.6)
+$ git merge dwmw2/master
+Already up-to-date.
+Merging sh-current/sh-fixes-for-linus (4403310 SH: Convert out[bwl] macros to inline functions)
+$ git merge sh-current/sh-fixes-for-linus
+Already up-to-date.
+Merging irqdomain-current/irqdomain/merge (a0d271c Linux 3.6)
+$ git merge irqdomain-current/irqdomain/merge
+Already up-to-date.
+Merging devicetree-current/devicetree/merge (0e622d3 of/address: sparc: Declare of_iomap as an extern function for sparc again)
+$ git merge devicetree-current/devicetree/merge
+Already up-to-date.
+Merging spi-current/spi/merge (a0d271c Linux 3.6)
+$ git merge spi-current/spi/merge
+Already up-to-date.
+Merging gpio-current/gpio/merge (96b7064 gpio/tca6424: merge I2C transactions, remove cast)
+$ git merge gpio-current/gpio/merge
+Already up-to-date.
+Merging rr-fixes/fixes (b251f0f Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net)
+$ git merge rr-fixes/fixes
+Already up-to-date.
+Merging asm-generic/master (9b04ebd asm-generic/io.h: remove asm/cacheflush.h include)
+$ git merge asm-generic/master
+Merge made by the 'recursive' strategy.
+ arch/openrisc/include/asm/io.h |    1 +
+ include/asm-generic/io.h       |    1 -
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+Merging arm/for-next (6b9c9f6 Merge branch 'devel-stable' into for-next)
+$ git merge arm/for-next
+Auto-merging include/linux/platform_data/sa11x0-serial.h
+Auto-merging include/linux/platform_data/pxa2xx_udc.h
+Removing arch/avr32/include/asm/mach/serial_at91.h
+Removing arch/arm/include/asm/mach/serial_at91.h
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/arm/cpus.txt     |   77 ++++++
+ arch/arm/Kconfig                                   |    2 +
+ arch/arm/common/gic.c                              |   45 +++-
+ arch/arm/common/vic.c                              |   19 +-
+ arch/arm/include/asm/cpu.h                         |    1 +
+ arch/arm/include/asm/cputype.h                     |   13 +
+ arch/arm/include/asm/cti.h                         |   20 +-
+ arch/arm/include/asm/hardware/cache-l2x0.h         |    5 +
+ arch/arm/include/asm/hardware/vic.h                |    2 +-
+ arch/arm/include/asm/hw_breakpoint.h               |    8 +-
+ arch/arm/include/asm/mach/serial_at91.h            |   33 ---
+ arch/arm/include/asm/mmu.h                         |   11 +-
+ arch/arm/include/asm/mmu_context.h                 |   82 +-----
+ arch/arm/include/asm/perf_event.h                  |    7 +
+ arch/arm/include/asm/pgtable-2level.h              |    2 +
+ arch/arm/include/asm/pgtable-3level.h              |    4 +-
+ arch/arm/include/asm/pgtable.h                     |   10 +-
+ arch/arm/include/asm/pmu.h                         |   28 +-
+ arch/arm/include/asm/prom.h                        |    2 +
+ arch/arm/include/asm/smp.h                         |    1 +
+ arch/arm/include/asm/smp_plat.h                    |   17 ++
+ arch/arm/include/asm/syscall.h                     |    9 +
+ arch/arm/include/asm/thread_info.h                 |    7 +-
+ arch/arm/kernel/devtree.c                          |  104 ++++++++
+ arch/arm/kernel/entry-common.S                     |   15 +-
+ arch/arm/kernel/hw_breakpoint.c                    |  154 ++++++-----
+ arch/arm/kernel/perf_event.c                       |   85 ++++--
+ arch/arm/kernel/perf_event_cpu.c                   |   74 ++++--
+ arch/arm/kernel/perf_event_v6.c                    |  126 ++++-----
+ arch/arm/kernel/perf_event_v7.c                    |  246 ++++++++---------
+ arch/arm/kernel/perf_event_xscale.c                |  157 +++++------
+ arch/arm/kernel/process.c                          |    4 +-
+ arch/arm/kernel/ptrace.c                           |   29 +-
+ arch/arm/kernel/setup.c                            |   78 +++---
+ arch/arm/kernel/smp.c                              |    6 +
+ arch/arm/kernel/smp_twd.c                          |   54 ++--
+ arch/arm/kernel/topology.c                         |   42 +--
+ arch/arm/kernel/vmlinux.lds.S                      |   19 +-
+ arch/arm/mach-ixp4xx/include/mach/udc.h            |    2 +-
+ arch/arm/mach-omap2/pmu.c                          |    2 -
+ arch/arm/mach-pxa/include/mach/udc.h               |    2 +-
+ arch/arm/mach-sa1100/assabet.c                     |    2 +-
+ arch/arm/mach-sa1100/badge4.c                      |    2 +-
+ arch/arm/mach-sa1100/cerf.c                        |    2 +-
+ arch/arm/mach-sa1100/collie.c                      |    2 +-
+ arch/arm/mach-sa1100/h3xxx.c                       |    2 +-
+ arch/arm/mach-sa1100/hackkit.c                     |    2 +-
+ arch/arm/mach-sa1100/jornada720.c                  |    2 +-
+ arch/arm/mach-sa1100/lart.c                        |    2 +-
+ arch/arm/mach-sa1100/nanoengine.c                  |    2 +-
+ arch/arm/mach-sa1100/neponset.c                    |    2 +-
+ arch/arm/mach-sa1100/pleb.c                        |    2 +-
+ arch/arm/mach-sa1100/shannon.c                     |    2 +-
+ arch/arm/mach-sa1100/simpad.c                      |    2 +-
+ arch/arm/mm/cache-aurora-l2.h                      |   55 ++++
+ arch/arm/mm/cache-l2x0.c                           |  278 ++++++++++++++++++--
+ arch/arm/mm/context.c                              |  207 ++++++++-------
+ arch/arm/mm/idmap.c                                |   14 +-
+ arch/arm/mm/mmu.c                                  |    2 +-
+ arch/arm/mm/proc-macros.S                          |    4 +
+ arch/arm/mm/proc-v7-2level.S                       |   10 +-
+ arch/arm/mm/proc-v7-3level.S                       |    5 +-
+ arch/arm/mm/proc-v7.S                              |    2 +-
+ arch/arm/plat-omap/include/plat/omap-serial.h      |   55 ----
+ arch/avr32/include/asm/mach/serial_at91.h          |   33 ---
+ drivers/mmc/host/mmci.c                            |   58 ++--
+ drivers/mmc/host/mmci.h                            |    4 +
+ drivers/tty/serial/atmel_serial.c                  |   18 --
+ drivers/tty/serial/omap-serial.c                   |  235 +++++++++++------
+ drivers/tty/serial/sa1100.c                        |    2 +-
+ drivers/tty/serial/serial_core.c                   |   71 ++++-
+ drivers/usb/gadget/pxa25x_udc.c                    |    4 +-
+ drivers/watchdog/sp805_wdt.c                       |    6 +-
+ .../linux/platform_data/pxa2xx_udc.h               |    5 +-
+ .../linux/platform_data/sa11x0-serial.h            |    6 +-
+ include/linux/serial_core.h                        |    6 +
+ scripts/sortextable.c                              |    1 +
+ 77 files changed, 1623 insertions(+), 1088 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/arm/cpus.txt
+ delete mode 100644 arch/arm/include/asm/mach/serial_at91.h
+ create mode 100644 arch/arm/mm/cache-aurora-l2.h
+ delete mode 100644 arch/avr32/include/asm/mach/serial_at91.h
+ rename arch/arm/include/asm/mach/udc_pxa2xx.h => include/linux/platform_data/pxa2xx_udc.h (94%)
+ rename arch/arm/include/asm/mach/serial_sa1100.h => include/linux/platform_data/sa11x0-serial.h (93%)
+Merging arm-perf/for-next/perf (3d70f8c Linux 3.7-rc4)
+$ git merge arm-perf/for-next/perf
+Already up-to-date.
+Merging davinci/davinci-next (fe0d422 Linux 3.0-rc6)
+$ git merge davinci/davinci-next
+Already up-to-date.
+Merging xilinx/arm-next (74cad60 serial: xilinx_uartps: get clock rate info from dts)
+$ git merge xilinx/arm-next
+Auto-merging arch/arm/mm/mmu.c
+Removing arch/arm/mach-zynq/include/mach/zynq_soc.h
+Removing arch/arm/mach-zynq/include/mach/uncompress.h
+Removing arch/arm/mach-zynq/include/mach/uart.h
+Removing arch/arm/mach-zynq/include/mach/clkdev.h
+Auto-merging arch/arm/include/debug/zynq.S
+Removing arch/arm/boot/dts/zynq-ep107.dts
+Auto-merging arch/arm/Kconfig
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/clock/zynq-7000.txt        |   55 +++
+ arch/arm/Kconfig                                   |   14 +-
+ arch/arm/Kconfig.debug                             |   18 +
+ arch/arm/Makefile                                  |    1 -
+ arch/arm/boot/dts/Makefile                         |    1 +
+ arch/arm/boot/dts/zynq-7000.dtsi                   |  166 +++++++++
+ arch/arm/boot/dts/zynq-ep107.dts                   |   52 ---
+ arch/arm/boot/dts/zynq-zc702.dts                   |   44 +++
+ arch/arm/include/asm/mach/map.h                    |    7 +
+ .../mach/debug-macro.S => include/debug/zynq.S}    |   23 +-
+ arch/arm/kernel/debug.S                            |   14 +
+ arch/arm/mach-zynq/Kconfig                         |   13 +
+ arch/arm/mach-zynq/common.c                        |   80 ++--
+ arch/arm/mach-zynq/common.h                        |    4 +-
+ arch/arm/mach-zynq/include/mach/clkdev.h           |   32 --
+ arch/arm/mach-zynq/include/mach/uart.h             |   25 --
+ arch/arm/mach-zynq/include/mach/uncompress.h       |   51 ---
+ arch/arm/mach-zynq/include/mach/zynq_soc.h         |   48 ---
+ arch/arm/mach-zynq/timer.c                         |  298 ++++++++-------
+ arch/arm/mm/mmu.c                                  |   16 +
+ drivers/clk/Makefile                               |    1 +
+ drivers/clk/clk-zynq.c                             |  383 ++++++++++++++++++++
+ drivers/tty/serial/Kconfig                         |    1 +
+ drivers/tty/serial/xilinx_uartps.c                 |   39 +-
+ include/linux/clk/zynq.h                           |   24 ++
+ 25 files changed, 991 insertions(+), 419 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/clock/zynq-7000.txt
+ create mode 100644 arch/arm/boot/dts/zynq-7000.dtsi
+ delete mode 100644 arch/arm/boot/dts/zynq-ep107.dts
+ create mode 100644 arch/arm/boot/dts/zynq-zc702.dts
+ rename arch/arm/{mach-zynq/include/mach/debug-macro.S => include/debug/zynq.S} (61%)
+ create mode 100644 arch/arm/mach-zynq/Kconfig
+ delete mode 100644 arch/arm/mach-zynq/include/mach/clkdev.h
+ delete mode 100644 arch/arm/mach-zynq/include/mach/uart.h
+ delete mode 100644 arch/arm/mach-zynq/include/mach/uncompress.h
+ delete mode 100644 arch/arm/mach-zynq/include/mach/zynq_soc.h
+ create mode 100644 drivers/clk/clk-zynq.c
+ create mode 100644 include/linux/clk/zynq.h
+Merging arm64/upstream (8f3bfa5 arm64: Convert empty flush_cache_{mm,page} functions to static inline)
+$ git merge arm64/upstream
+Merge made by the 'recursive' strategy.
+ arch/arm64/Kconfig                  |    3 ++
+ arch/arm64/include/asm/Kbuild       |    1 +
+ arch/arm64/include/asm/cacheflush.h |   11 ++++-
+ arch/arm64/include/asm/processor.h  |    5 ---
+ arch/arm64/include/asm/syscalls.h   |   14 +++---
+ arch/arm64/include/asm/unistd.h     |    1 +
+ arch/arm64/include/asm/unistd32.h   |    8 ++--
+ arch/arm64/kernel/entry.S           |   17 +++----
+ arch/arm64/kernel/process.c         |   83 +++++++++++++----------------------
+ arch/arm64/kernel/signal.c          |   49 ++++++++++-----------
+ arch/arm64/kernel/signal32.c        |   20 ++++-----
+ arch/arm64/kernel/sys.c             |   76 ++------------------------------
+ arch/arm64/kernel/sys32.S           |   19 --------
+ arch/arm64/kernel/sys_compat.c      |   38 +++-------------
+ arch/arm64/mm/fault.c               |   13 +++++-
+ arch/arm64/mm/flush.c               |    9 ----
+ arch/arm64/mm/init.c                |    4 +-
+ 17 files changed, 110 insertions(+), 261 deletions(-)
+Merging blackfin/for-linus (9d84601 Blackfin: dpmc: use module_platform_driver macro)
+$ git merge blackfin/for-linus
+Removing arch/blackfin/include/asm/kvm_para.h
+Merge made by the 'recursive' strategy.
+ arch/blackfin/include/asm/Kbuild                   |    6 +-
+ arch/blackfin/include/asm/bfin_sport.h             |  128 +-----
+ arch/blackfin/include/asm/bfin_twi.h               |    2 +-
+ arch/blackfin/include/asm/fixed_code.h             |   30 +-
+ arch/blackfin/include/asm/kvm_para.h               |    1 -
+ arch/blackfin/include/asm/pgtable.h                |    2 -
+ arch/blackfin/include/asm/ptrace.h                 |  161 +-------
+ arch/blackfin/include/asm/uaccess.h                |   41 +-
+ arch/blackfin/include/asm/unistd.h                 |  430 +------------------
+ arch/blackfin/include/uapi/asm/Kbuild              |   16 +
+ arch/blackfin/include/uapi/asm/bfin_sport.h        |  136 ++++++
+ arch/blackfin/include/{ => uapi}/asm/byteorder.h   |    0
+ arch/blackfin/include/{ => uapi}/asm/cachectl.h    |    0
+ arch/blackfin/include/{ => uapi}/asm/fcntl.h       |    0
+ arch/blackfin/include/uapi/asm/fixed_code.h        |   38 ++
+ arch/blackfin/include/{ => uapi}/asm/ioctls.h      |    0
+ arch/blackfin/include/{ => uapi}/asm/poll.h        |    0
+ arch/blackfin/include/{ => uapi}/asm/posix_types.h |    0
+ arch/blackfin/include/uapi/asm/ptrace.h            |  170 ++++++++
+ arch/blackfin/include/{ => uapi}/asm/sigcontext.h  |    0
+ arch/blackfin/include/{ => uapi}/asm/siginfo.h     |    0
+ arch/blackfin/include/{ => uapi}/asm/signal.h      |    0
+ arch/blackfin/include/{ => uapi}/asm/stat.h        |    0
+ arch/blackfin/include/{ => uapi}/asm/swab.h        |    0
+ arch/blackfin/include/uapi/asm/unistd.h            |  437 ++++++++++++++++++++
+ arch/blackfin/mach-common/dpmc.c                   |   19 +-
+ 26 files changed, 817 insertions(+), 800 deletions(-)
+ delete mode 100644 arch/blackfin/include/asm/kvm_para.h
+ create mode 100644 arch/blackfin/include/uapi/asm/bfin_sport.h
+ rename arch/blackfin/include/{ => uapi}/asm/byteorder.h (100%)
+ rename arch/blackfin/include/{ => uapi}/asm/cachectl.h (100%)
+ rename arch/blackfin/include/{ => uapi}/asm/fcntl.h (100%)
+ create mode 100644 arch/blackfin/include/uapi/asm/fixed_code.h
+ rename arch/blackfin/include/{ => uapi}/asm/ioctls.h (100%)
+ rename arch/blackfin/include/{ => uapi}/asm/poll.h (100%)
+ rename arch/blackfin/include/{ => uapi}/asm/posix_types.h (100%)
+ create mode 100644 arch/blackfin/include/uapi/asm/ptrace.h
+ rename arch/blackfin/include/{ => uapi}/asm/sigcontext.h (100%)
+ rename arch/blackfin/include/{ => uapi}/asm/siginfo.h (100%)
+ rename arch/blackfin/include/{ => uapi}/asm/signal.h (100%)
+ rename arch/blackfin/include/{ => uapi}/asm/stat.h (100%)
+ rename arch/blackfin/include/{ => uapi}/asm/swab.h (100%)
+ create mode 100644 arch/blackfin/include/uapi/asm/unistd.h
+Merging c6x/for-linux-next (93bbd0c c6x: use generic kvm_para.h)
+$ git merge c6x/for-linux-next
+Removing arch/c6x/include/uapi/asm/kvm_para.h
+Merge made by the 'recursive' strategy.
+ arch/c6x/include/asm/setup.h         |   33 +++++++++++++++++++++++++++++++++
+ arch/c6x/include/uapi/asm/Kbuild     |    2 ++
+ arch/c6x/include/uapi/asm/kvm_para.h |    1 -
+ arch/c6x/include/uapi/asm/setup.h    |   33 +++------------------------------
+ arch/c6x/kernel/entry.S              |    5 +++--
+ 5 files changed, 41 insertions(+), 33 deletions(-)
+ create mode 100644 arch/c6x/include/asm/setup.h
+ delete mode 100644 arch/c6x/include/uapi/asm/kvm_para.h
+Merging cris/for-next (eacb25c UAPI: Fix up empty files in arch/cris/)
+$ git merge cris/for-next
+Auto-merging arch/cris/include/asm/Kbuild
+Merge made by the 'recursive' strategy.
+ arch/cris/include/arch-v10/arch/Kbuild             |    5 +-
+ arch/cris/include/arch-v32/arch/Kbuild             |    3 +-
+ arch/cris/include/arch-v32/arch/cryptocop.h        |  116 +------
+ arch/cris/include/arch-v32/arch/spinlock.h         |    2 +-
+ arch/cris/include/asm/Kbuild                       |    5 -
+ arch/cris/include/asm/ptrace.h                     |    5 +-
+ arch/cris/include/asm/signal.h                     |  122 +------
+ arch/cris/include/asm/swab.h                       |    3 +-
+ arch/cris/include/asm/termios.h                    |   43 +--
+ arch/cris/include/asm/types.h                      |    5 +-
+ arch/cris/include/asm/unistd.h                     |  342 +------------------
+ arch/cris/include/uapi/arch-v10/arch/Kbuild        |    4 +
+ .../include/{ => uapi}/arch-v10/arch/sv_addr.agh   |    0
+ .../include/{ => uapi}/arch-v10/arch/sv_addr_ag.h  |    0
+ .../cris/include/{ => uapi}/arch-v10/arch/svinto.h |    0
+ arch/cris/include/{ => uapi}/arch-v10/arch/user.h  |    0
+ arch/cris/include/uapi/arch-v32/arch/Kbuild        |    2 +
+ arch/cris/include/uapi/arch-v32/arch/cryptocop.h   |  122 +++++++
+ arch/cris/include/{ => uapi}/arch-v32/arch/user.h  |    0
+ arch/cris/include/uapi/asm/Kbuild                  |   34 ++
+ arch/cris/include/{ => uapi}/asm/auxvec.h          |    0
+ arch/cris/include/{ => uapi}/asm/bitsperlong.h     |    0
+ arch/cris/include/{ => uapi}/asm/byteorder.h       |    0
+ arch/cris/include/{ => uapi}/asm/errno.h           |    0
+ arch/cris/include/{ => uapi}/asm/ethernet.h        |    0
+ arch/cris/include/{ => uapi}/asm/etraxgpio.h       |    0
+ arch/cris/include/{ => uapi}/asm/fcntl.h           |    0
+ arch/cris/include/{ => uapi}/asm/ioctl.h           |    0
+ arch/cris/include/{ => uapi}/asm/ioctls.h          |    0
+ arch/cris/include/{ => uapi}/asm/ipcbuf.h          |    0
+ arch/cris/include/{ => uapi}/asm/mman.h            |    0
+ arch/cris/include/{ => uapi}/asm/msgbuf.h          |    0
+ arch/cris/include/{ => uapi}/asm/param.h           |    0
+ arch/cris/include/{ => uapi}/asm/poll.h            |    0
+ arch/cris/include/{ => uapi}/asm/posix_types.h     |    0
+ arch/cris/include/uapi/asm/ptrace.h                |    1 +
+ arch/cris/include/{ => uapi}/asm/resource.h        |    0
+ arch/cris/include/{ => uapi}/asm/rs485.h           |    0
+ arch/cris/include/{ => uapi}/asm/sembuf.h          |    0
+ arch/cris/include/{ => uapi}/asm/setup.h           |    0
+ arch/cris/include/{ => uapi}/asm/shmbuf.h          |    0
+ arch/cris/include/{ => uapi}/asm/sigcontext.h      |    0
+ arch/cris/include/{ => uapi}/asm/siginfo.h         |    0
+ arch/cris/include/uapi/asm/signal.h                |  122 +++++++
+ arch/cris/include/{ => uapi}/asm/socket.h          |    0
+ arch/cris/include/{ => uapi}/asm/sockios.h         |    0
+ arch/cris/include/{ => uapi}/asm/stat.h            |    0
+ arch/cris/include/{ => uapi}/asm/statfs.h          |    0
+ arch/cris/include/uapi/asm/swab.h                  |    3 +
+ arch/cris/include/{ => uapi}/asm/sync_serial.h     |    0
+ arch/cris/include/{ => uapi}/asm/termbits.h        |    0
+ arch/cris/include/uapi/asm/termios.h               |   45 +++
+ arch/cris/include/uapi/asm/types.h                 |    1 +
+ arch/cris/include/uapi/asm/unistd.h                |  344 ++++++++++++++++++++
+ arch/cris/kernel/asm-offsets.c                     |    6 +-
+ 55 files changed, 689 insertions(+), 646 deletions(-)
+ rename arch/cris/include/{ => uapi}/arch-v10/arch/sv_addr.agh (100%)
+ rename arch/cris/include/{ => uapi}/arch-v10/arch/sv_addr_ag.h (100%)
+ rename arch/cris/include/{ => uapi}/arch-v10/arch/svinto.h (100%)
+ rename arch/cris/include/{ => uapi}/arch-v10/arch/user.h (100%)
+ create mode 100644 arch/cris/include/uapi/arch-v32/arch/cryptocop.h
+ rename arch/cris/include/{ => uapi}/arch-v32/arch/user.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/auxvec.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/bitsperlong.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/byteorder.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/errno.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/ethernet.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/etraxgpio.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/fcntl.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/ioctl.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/ioctls.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/ipcbuf.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/mman.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/msgbuf.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/param.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/poll.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/posix_types.h (100%)
+ create mode 100644 arch/cris/include/uapi/asm/ptrace.h
+ rename arch/cris/include/{ => uapi}/asm/resource.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/rs485.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/sembuf.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/setup.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/shmbuf.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/sigcontext.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/siginfo.h (100%)
+ create mode 100644 arch/cris/include/uapi/asm/signal.h
+ rename arch/cris/include/{ => uapi}/asm/socket.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/sockios.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/stat.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/statfs.h (100%)
+ create mode 100644 arch/cris/include/uapi/asm/swab.h
+ rename arch/cris/include/{ => uapi}/asm/sync_serial.h (100%)
+ rename arch/cris/include/{ => uapi}/asm/termbits.h (100%)
+ create mode 100644 arch/cris/include/uapi/asm/termios.h
+ create mode 100644 arch/cris/include/uapi/asm/types.h
+ create mode 100644 arch/cris/include/uapi/asm/unistd.h
+Merging hexagon/linux-next (e1858b2 Hexagon: Copyright marking changes)
+$ git merge hexagon/linux-next
+Already up-to-date.
+Merging ia64/next (7843ae0 Merge branch 'pstore_mevent' into next)
+$ git merge ia64/next
+Merge made by the 'recursive' strategy.
+ arch/ia64/kernel/topology.c |    4 +-
+ drivers/acpi/apei/erst.c    |   16 ++---
+ drivers/firmware/efivars.c  |  163 ++++++++++++++++++++++++++++++-------------
+ fs/pstore/inode.c           |    7 +-
+ fs/pstore/internal.h        |    2 +-
+ fs/pstore/platform.c        |   13 ++--
+ fs/pstore/ram.c             |    9 ++-
+ include/linux/efi.h         |    1 +
+ include/linux/pstore.h      |    6 +-
+ 9 files changed, 146 insertions(+), 75 deletions(-)
+Merging m68k/for-next (5fec45a m68k/sun3: Fix instruction faults)
+$ git merge m68k/for-next
+Removing arch/m68k/mm/init_no.c
+Removing arch/m68k/mm/init_mm.c
+Removing arch/m68k/include/uapi/asm/termios.h
+Removing arch/m68k/include/uapi/asm/termbits.h
+Removing arch/m68k/include/uapi/asm/sockios.h
+Removing arch/m68k/include/uapi/asm/socket.h
+Removing arch/m68k/include/uapi/asm/shmbuf.h
+Removing arch/m68k/include/uapi/asm/sembuf.h
+Removing arch/m68k/include/uapi/asm/msgbuf.h
+Removing arch/m68k/include/uapi/asm/auxvec.h
+Removing arch/m68k/include/asm/termios.h
+Removing arch/m68k/include/asm/spinlock.h
+Removing arch/m68k/include/asm/shmparam.h
+Removing arch/m68k/include/asm/hw_irq.h
+Merge made by the 'recursive' strategy.
+ arch/m68k/Kconfig.bus                 |    4 +-
+ arch/m68k/Kconfig.cpu                 |    3 +-
+ arch/m68k/Kconfig.debug               |    2 +-
+ arch/m68k/Kconfig.devices             |    6 +-
+ arch/m68k/include/asm/Kbuild          |    4 +
+ arch/m68k/include/asm/hw_irq.h        |    6 -
+ arch/m68k/include/asm/shmparam.h      |    6 -
+ arch/m68k/include/asm/spinlock.h      |    6 -
+ arch/m68k/include/asm/termios.h       |   50 --------
+ arch/m68k/include/uapi/asm/Kbuild     |   17 +--
+ arch/m68k/include/uapi/asm/auxvec.h   |    4 -
+ arch/m68k/include/uapi/asm/msgbuf.h   |   31 -----
+ arch/m68k/include/uapi/asm/sembuf.h   |   25 ----
+ arch/m68k/include/uapi/asm/shmbuf.h   |   42 -------
+ arch/m68k/include/uapi/asm/socket.h   |   72 -----------
+ arch/m68k/include/uapi/asm/sockios.h  |   13 --
+ arch/m68k/include/uapi/asm/termbits.h |  201 -----------------------------
+ arch/m68k/include/uapi/asm/termios.h  |   44 -------
+ arch/m68k/kernel/traps.c              |    2 +-
+ arch/m68k/mm/init.c                   |  224 ++++++++++++++++++++++++++++++++-
+ arch/m68k/mm/init_mm.c                |  176 --------------------------
+ arch/m68k/mm/init_no.c                |  145 ---------------------
+ arch/m68k/mm/mcfmmu.c                 |    4 -
+ arch/m68k/mm/motorola.c               |   14 ---
+ arch/m68k/mm/sun3mmu.c                |    4 -
+ arch/m68k/sun3/sun3ints.c             |   29 +----
+ 26 files changed, 247 insertions(+), 887 deletions(-)
+ delete mode 100644 arch/m68k/include/asm/hw_irq.h
+ delete mode 100644 arch/m68k/include/asm/shmparam.h
+ delete mode 100644 arch/m68k/include/asm/spinlock.h
+ delete mode 100644 arch/m68k/include/asm/termios.h
+ delete mode 100644 arch/m68k/include/uapi/asm/auxvec.h
+ delete mode 100644 arch/m68k/include/uapi/asm/msgbuf.h
+ delete mode 100644 arch/m68k/include/uapi/asm/sembuf.h
+ delete mode 100644 arch/m68k/include/uapi/asm/shmbuf.h
+ delete mode 100644 arch/m68k/include/uapi/asm/socket.h
+ delete mode 100644 arch/m68k/include/uapi/asm/sockios.h
+ delete mode 100644 arch/m68k/include/uapi/asm/termbits.h
+ delete mode 100644 arch/m68k/include/uapi/asm/termios.h
+ delete mode 100644 arch/m68k/mm/init_mm.c
+ delete mode 100644 arch/m68k/mm/init_no.c
+Merging m68knommu/for-next (5a1b2a1 m68knommu: modify clock code so it can be used by all ColdFire CPU types)
+$ git merge m68knommu/for-next
+Removing arch/m68k/include/asm/m5249sim.h
+Auto-merging arch/m68k/Kconfig.cpu
+Merge made by the 'recursive' strategy.
+ arch/m68k/Kconfig.cpu                   |    3 +-
+ arch/m68k/include/asm/m5249sim.h        |  269 -------------------------------
+ arch/m68k/include/asm/m525xsim.h        |  116 ++++++++++++-
+ arch/m68k/include/asm/mcfclk.h          |    9 +-
+ arch/m68k/include/asm/mcfsim.h          |    5 +-
+ arch/m68k/include/asm/page_no.h         |    2 +-
+ arch/m68k/lib/memcpy.c                  |    3 +-
+ arch/m68k/platform/coldfire/clk.c       |  100 +++++-------
+ arch/m68k/platform/coldfire/intc-5249.c |    8 +-
+ arch/m68k/platform/coldfire/m5206.c     |   20 +++
+ arch/m68k/platform/coldfire/m523x.c     |   28 ++++
+ arch/m68k/platform/coldfire/m5249.c     |   28 +++-
+ arch/m68k/platform/coldfire/m525x.c     |   20 +++
+ arch/m68k/platform/coldfire/m5272.c     |   26 +++
+ arch/m68k/platform/coldfire/m527x.c     |   30 ++++
+ arch/m68k/platform/coldfire/m528x.c     |   28 ++++
+ arch/m68k/platform/coldfire/m5307.c     |   20 +++
+ arch/m68k/platform/coldfire/m5407.c     |   20 +++
+ arch/m68k/platform/coldfire/m54xx.c     |   26 +++
+ 19 files changed, 413 insertions(+), 348 deletions(-)
+ delete mode 100644 arch/m68k/include/asm/m5249sim.h
+Merging microblaze/next (f229605 microblaze: dma-mapping: Support debug_dma_mapping_error)
+$ git merge microblaze/next
+Merge made by the 'recursive' strategy.
+ arch/microblaze/include/asm/Kbuild                 |    2 -
+ arch/microblaze/include/asm/dma-mapping.h          |    2 +
+ arch/microblaze/include/asm/elf.h                  |   97 +----
+ arch/microblaze/include/asm/ptrace.h               |   62 +--
+ arch/microblaze/include/asm/setup.h                |    6 +-
+ arch/microblaze/include/asm/uaccess.h              |    3 +-
+ arch/microblaze/include/asm/unistd.h               |  390 +------------------
+ arch/microblaze/include/uapi/asm/Kbuild            |   32 ++
+ arch/microblaze/include/{ => uapi}/asm/auxvec.h    |    0
+ .../include/{ => uapi}/asm/bitsperlong.h           |    0
+ arch/microblaze/include/{ => uapi}/asm/byteorder.h |    0
+ arch/microblaze/include/uapi/asm/elf.h             |  121 ++++++
+ arch/microblaze/include/{ => uapi}/asm/errno.h     |    0
+ arch/microblaze/include/{ => uapi}/asm/fcntl.h     |    0
+ arch/microblaze/include/{ => uapi}/asm/ioctl.h     |    0
+ arch/microblaze/include/{ => uapi}/asm/ioctls.h    |    0
+ arch/microblaze/include/{ => uapi}/asm/ipcbuf.h    |    0
+ arch/microblaze/include/{ => uapi}/asm/kvm_para.h  |    0
+ arch/microblaze/include/{ => uapi}/asm/mman.h      |    0
+ arch/microblaze/include/{ => uapi}/asm/msgbuf.h    |    0
+ arch/microblaze/include/{ => uapi}/asm/param.h     |    0
+ arch/microblaze/include/{ => uapi}/asm/poll.h      |    0
+ .../include/{ => uapi}/asm/posix_types.h           |    0
+ arch/microblaze/include/uapi/asm/ptrace.h          |   72 ++++
+ arch/microblaze/include/{ => uapi}/asm/resource.h  |    0
+ arch/microblaze/include/{ => uapi}/asm/sembuf.h    |    0
+ arch/microblaze/include/uapi/asm/setup.h           |   19 +
+ arch/microblaze/include/{ => uapi}/asm/shmbuf.h    |    0
+ .../microblaze/include/{ => uapi}/asm/sigcontext.h |    0
+ arch/microblaze/include/{ => uapi}/asm/siginfo.h   |    0
+ arch/microblaze/include/{ => uapi}/asm/signal.h    |    0
+ arch/microblaze/include/{ => uapi}/asm/socket.h    |    0
+ arch/microblaze/include/{ => uapi}/asm/sockios.h   |    0
+ arch/microblaze/include/{ => uapi}/asm/stat.h      |    0
+ arch/microblaze/include/{ => uapi}/asm/statfs.h    |    0
+ arch/microblaze/include/{ => uapi}/asm/swab.h      |    0
+ arch/microblaze/include/{ => uapi}/asm/termbits.h  |    0
+ arch/microblaze/include/{ => uapi}/asm/termios.h   |    0
+ arch/microblaze/include/{ => uapi}/asm/types.h     |    0
+ arch/microblaze/include/uapi/asm/unistd.h          |  400 ++++++++++++++++++++
+ arch/microblaze/kernel/entry-nommu.S               |    1 -
+ arch/microblaze/kernel/entry.S                     |    2 +-
+ arch/microblaze/kernel/process.c                   |    1 -
+ 43 files changed, 653 insertions(+), 557 deletions(-)
+ rename arch/microblaze/include/{ => uapi}/asm/auxvec.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/bitsperlong.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/byteorder.h (100%)
+ create mode 100644 arch/microblaze/include/uapi/asm/elf.h
+ rename arch/microblaze/include/{ => uapi}/asm/errno.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/fcntl.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/ioctl.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/ioctls.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/ipcbuf.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/kvm_para.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/mman.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/msgbuf.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/param.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/poll.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/posix_types.h (100%)
+ create mode 100644 arch/microblaze/include/uapi/asm/ptrace.h
+ rename arch/microblaze/include/{ => uapi}/asm/resource.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/sembuf.h (100%)
+ create mode 100644 arch/microblaze/include/uapi/asm/setup.h
+ rename arch/microblaze/include/{ => uapi}/asm/shmbuf.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/sigcontext.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/siginfo.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/signal.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/socket.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/sockios.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/stat.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/statfs.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/swab.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/termbits.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/termios.h (100%)
+ rename arch/microblaze/include/{ => uapi}/asm/types.h (100%)
+ create mode 100644 arch/microblaze/include/uapi/asm/unistd.h
+Merging mips/mips-for-linux-next (46845cf Merge branch 'mips-next' of http://dev.phrozen.org/githttp/mips-next into mips-for-linux-next)
+$ git merge mips/mips-for-linux-next
+Removing arch/mips/bcm47xx/gpio.c
+Merge made by the 'recursive' strategy.
+ MAINTAINERS                                        |    9 +
+ arch/mips/Kconfig                                  |   85 ++-
+ arch/mips/Makefile                                 |    6 +-
+ arch/mips/ar7/platform.c                           |    3 +
+ arch/mips/bcm47xx/Kconfig                          |    2 +
+ arch/mips/bcm47xx/Makefile                         |    2 +-
+ arch/mips/bcm47xx/gpio.c                           |  102 ---
+ arch/mips/bcm47xx/prom.c                           |   20 +-
+ arch/mips/bcm47xx/setup.c                          |   11 +-
+ arch/mips/bcm47xx/sprom.c                          |  780 +++++++++++---------
+ arch/mips/bcm63xx/Makefile                         |    7 +-
+ arch/mips/bcm63xx/boards/board_bcm963xx.c          |   71 +-
+ arch/mips/bcm63xx/clk.c                            |   34 +-
+ arch/mips/bcm63xx/nvram.c                          |  107 +++
+ arch/mips/bcm63xx/reset.c                          |  223 ++++++
+ arch/mips/cavium-octeon/flash_setup.c              |    3 +-
+ arch/mips/cavium-octeon/octeon-memcpy.S            |   27 -
+ arch/mips/cavium-octeon/setup.c                    |   40 +-
+ arch/mips/configs/ath79_defconfig                  |  111 +++
+ arch/mips/configs/cavium_octeon_defconfig          |   98 ++-
+ arch/mips/fw/sni/Makefile                          |    2 +-
+ arch/mips/include/asm/cpu.h                        |    6 +-
+ arch/mips/include/asm/fw/arc/types.h               |    8 +-
+ arch/mips/include/asm/kexec.h                      |   27 +-
+ arch/mips/include/asm/mach-bcm47xx/bcm47xx.h       |    4 +-
+ arch/mips/include/asm/mach-bcm47xx/gpio.h          |  154 +---
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h |   35 +
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h  |   29 +-
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h |   21 +
+ .../mips/include/asm/mach-bcm63xx/board_bcm963xx.h |   17 -
+ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |    3 +
+ arch/mips/include/asm/mach-loongson1/platform.h    |    3 +-
+ arch/mips/include/asm/mach-loongson1/regs-clk.h    |    7 +-
+ arch/mips/include/asm/mach-netlogic/irq.h          |    4 +-
+ arch/mips/include/asm/mach-netlogic/multi-node.h   |   54 ++
+ arch/mips/include/asm/mipsregs.h                   |    2 +-
+ arch/mips/include/asm/netlogic/common.h            |   51 +-
+ arch/mips/include/asm/netlogic/interrupt.h         |    2 +-
+ arch/mips/include/asm/netlogic/mips-extns.h        |  142 ++++
+ arch/mips/include/asm/netlogic/xlp-hal/pic.h       |   44 +-
+ arch/mips/include/asm/netlogic/xlp-hal/sys.h       |    1 -
+ arch/mips/include/asm/netlogic/xlr/fmn.h           |  363 +++++++++
+ arch/mips/include/asm/netlogic/xlr/pic.h           |    2 -
+ arch/mips/include/asm/netlogic/xlr/xlr.h           |    6 +-
+ arch/mips/include/asm/page.h                       |    8 +-
+ arch/mips/include/asm/pgtable-64.h                 |    2 +-
+ arch/mips/include/asm/pgtable-bits.h               |   13 +-
+ arch/mips/include/asm/pgtable.h                    |  168 ++++-
+ arch/mips/include/asm/processor.h                  |    4 -
+ arch/mips/include/asm/sgiarcs.h                    |    8 +-
+ arch/mips/include/asm/smp.h                        |    7 +
+ arch/mips/include/asm/sparsemem.h                  |    2 +-
+ arch/mips/include/asm/tlbdebug.h                   |    1 +
+ arch/mips/kernel/Makefile                          |    3 +-
+ arch/mips/kernel/asm-offsets.c                     |    4 -
+ arch/mips/kernel/crash.c                           |   71 ++
+ arch/mips/kernel/crash_dump.c                      |   77 ++
+ arch/mips/kernel/machine_kexec.c                   |   33 +-
+ arch/mips/kernel/mips_ksyms.c                      |    2 +-
+ arch/mips/kernel/perf_event_mipsxx.c               |  124 ++++
+ arch/mips/kernel/relocate_kernel.S                 |   88 ++-
+ arch/mips/kernel/scall64-n32.S                     |    6 -
+ arch/mips/kernel/setup.c                           |   56 ++
+ arch/mips/kernel/signal.c                          |   13 +-
+ arch/mips/kernel/smp.c                             |   17 +
+ arch/mips/kernel/traps.c                           |    4 +
+ arch/mips/lantiq/Kconfig                           |    4 +
+ arch/mips/lantiq/prom.c                            |    5 +-
+ arch/mips/lantiq/xway/Makefile                     |    2 +
+ arch/mips/lantiq/xway/dma.c                        |   15 +-
+ arch/mips/lantiq/xway/reset.c                      |   58 +-
+ arch/mips/lantiq/xway/sysctrl.c                    |    4 +
+ arch/mips/lantiq/xway/xrx200_phy_fw.c              |   97 +++
+ arch/mips/lib/dump_tlb.c                           |   47 ++
+ arch/mips/loongson1/Kconfig                        |    2 +-
+ arch/mips/loongson1/common/clock.c                 |  159 +---
+ arch/mips/loongson1/common/platform.c              |   10 +-
+ arch/mips/loongson1/ls1b/board.c                   |    5 +-
+ arch/mips/mm/c-octeon.c                            |   46 +-
+ arch/mips/mm/c-r4k.c                               |    8 +-
+ arch/mips/mm/pgtable-64.c                          |   31 +
+ arch/mips/mm/tlb-r4k.c                             |   22 +-
+ arch/mips/mm/tlbex.c                               |  101 ++-
+ arch/mips/netlogic/Kconfig                         |   28 +
+ arch/mips/netlogic/common/irq.c                    |  165 +++--
+ arch/mips/netlogic/common/smp.c                    |   89 ++-
+ arch/mips/netlogic/common/smpboot.S                |    6 +-
+ arch/mips/netlogic/xlp/nlm_hal.c                   |   67 +-
+ arch/mips/netlogic/xlp/setup.c                     |   50 +-
+ arch/mips/netlogic/xlp/wakeup.c                    |   83 ++-
+ arch/mips/netlogic/xlr/Makefile                    |    4 +-
+ arch/mips/netlogic/xlr/fmn-config.c                |  290 ++++++++
+ arch/mips/netlogic/xlr/fmn.c                       |  204 +++++
+ arch/mips/netlogic/xlr/setup.c                     |   37 +-
+ arch/mips/netlogic/xlr/wakeup.c                    |   23 +-
+ arch/mips/oprofile/Makefile                        |    1 +
+ arch/mips/oprofile/common.c                        |    1 +
+ arch/mips/oprofile/op_model_mipsxx.c               |   29 +
+ arch/mips/pci/pci-bcm63xx.c                        |   34 +-
+ arch/mips/pci/pci-octeon.c                         |    4 +
+ arch/mips/pci/pci-xlr.c                            |   69 +-
+ arch/mips/sibyte/Kconfig                           |    2 +-
+ arch/mips/sni/setup.c                              |    8 +-
+ drivers/bcma/Kconfig                               |    9 +
+ drivers/bcma/Makefile                              |    1 +
+ drivers/bcma/bcma_private.h                        |   10 +
+ drivers/bcma/driver_chipcommon.c                   |   81 +-
+ drivers/bcma/driver_gpio.c                         |   98 +++
+ drivers/bcma/main.c                                |    5 +
+ drivers/edac/Kconfig                               |   33 +-
+ drivers/edac/Makefile                              |    5 +
+ drivers/edac/octeon_edac-l2c.c                     |  118 +++
+ drivers/edac/octeon_edac-lmc.c                     |  150 ++++
+ drivers/edac/octeon_edac-lmc.h                     |   78 ++
+ drivers/edac/octeon_edac-pc.c                      |  140 ++++
+ drivers/edac/octeon_edac-pci.c                     |  135 ++++
+ drivers/ssb/Kconfig                                |    9 +
+ drivers/ssb/Makefile                               |    1 +
+ drivers/ssb/driver_chipcommon.c                    |   78 +-
+ drivers/ssb/driver_extif.c                         |   43 +-
+ drivers/ssb/driver_gpio.c                          |  176 +++++
+ drivers/ssb/main.c                                 |    7 +
+ drivers/ssb/ssb_private.h                          |   17 +
+ include/linux/bcma/bcma_driver_chipcommon.h        |   10 +
+ include/linux/ssb/ssb.h                            |    4 +
+ include/linux/ssb/ssb_driver_chipcommon.h          |    3 +
+ include/linux/ssb/ssb_driver_extif.h               |    1 +
+ 127 files changed, 5050 insertions(+), 1411 deletions(-)
+ delete mode 100644 arch/mips/bcm47xx/gpio.c
+ create mode 100644 arch/mips/bcm63xx/nvram.c
+ create mode 100644 arch/mips/bcm63xx/reset.c
+ create mode 100644 arch/mips/configs/ath79_defconfig
+ create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
+ create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h
+ create mode 100644 arch/mips/include/asm/mach-netlogic/multi-node.h
+ create mode 100644 arch/mips/include/asm/netlogic/xlr/fmn.h
+ create mode 100644 arch/mips/kernel/crash.c
+ create mode 100644 arch/mips/kernel/crash_dump.c
+ create mode 100644 arch/mips/lantiq/xway/xrx200_phy_fw.c
+ create mode 100644 arch/mips/netlogic/xlr/fmn-config.c
+ create mode 100644 arch/mips/netlogic/xlr/fmn.c
+ create mode 100644 drivers/bcma/driver_gpio.c
+ create mode 100644 drivers/edac/octeon_edac-l2c.c
+ create mode 100644 drivers/edac/octeon_edac-lmc.c
+ create mode 100644 drivers/edac/octeon_edac-lmc.h
+ create mode 100644 drivers/edac/octeon_edac-pc.c
+ create mode 100644 drivers/edac/octeon_edac-pci.c
+ create mode 100644 drivers/ssb/driver_gpio.c
+Merging openrisc/for-upstream (634bd40 openrisc: use kbuild.h instead of defining macros in asm-offset.c)
+$ git merge openrisc/for-upstream
+Removing arch/openrisc/include/uapi/asm/kvm_para.h
+Merge made by the 'recursive' strategy.
+ arch/openrisc/include/asm/Kbuild          |    1 +
+ arch/openrisc/include/uapi/asm/kvm_para.h |    1 -
+ arch/openrisc/kernel/asm-offsets.c        |    6 +-----
+ 3 files changed, 2 insertions(+), 6 deletions(-)
+ delete mode 100644 arch/openrisc/include/uapi/asm/kvm_para.h
+Merging parisc/for-next (949a05d [PARISC] fix virtual aliasing issue in get_shared_area())
+$ git merge parisc/for-next
+Already up-to-date.
+Merging powerpc/next (3991782 Merge remote-tracking branch 'kumar/next' into next)
+$ git merge powerpc/next
+Removing arch/powerpc/xmon/start.c
+Auto-merging arch/powerpc/kernel/cpu_setup_power.S
+Removing arch/powerpc/include/asm/pSeries_reconfig.h
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/powerpc/fsl/raideng.txt    |   81 +++++
+ Documentation/powerpc/ptrace.txt                   |   16 +
+ arch/arm/mach-mxs/mach-mxs.c                       |    2 +-
+ arch/powerpc/Makefile                              |    2 +-
+ arch/powerpc/boot/dts/fsl/p5020si-post.dtsi        |    1 +
+ arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi         |    6 +
+ arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi     |   85 ++++++
+ arch/powerpc/configs/pseries_defconfig             |    2 +-
+ arch/powerpc/include/asm/bitops.h                  |   75 +----
+ arch/powerpc/include/asm/cputable.h                |   12 +-
+ arch/powerpc/include/asm/dbell.h                   |    2 +-
+ arch/powerpc/include/asm/exception-64s.h           |   97 +++++-
+ arch/powerpc/include/asm/firmware.h                |    4 +-
+ arch/powerpc/include/asm/fsl_gtm.h                 |    2 +-
+ arch/powerpc/include/asm/fsl_guts.h                |    4 +-
+ arch/powerpc/include/asm/hvcall.h                  |   23 +-
+ arch/powerpc/include/asm/immap_qe.h                |    2 +-
+ arch/powerpc/include/asm/machdep.h                 |    3 -
+ arch/powerpc/include/asm/mmu.h                     |    1 +
+ arch/powerpc/include/asm/pSeries_reconfig.h        |   47 ---
+ arch/powerpc/include/asm/ppc-opcode.h              |    6 +-
+ arch/powerpc/include/asm/prom.h                    |   16 +
+ arch/powerpc/include/asm/qe.h                      |    2 +-
+ arch/powerpc/include/asm/qe_ic.h                   |    2 +-
+ arch/powerpc/include/asm/reg.h                     |    3 +
+ arch/powerpc/include/asm/rtas.h                    |    5 +
+ arch/powerpc/include/asm/setup.h                   |   29 ++
+ arch/powerpc/include/asm/ucc.h                     |    2 +-
+ arch/powerpc/include/asm/ucc_fast.h                |    2 +-
+ arch/powerpc/include/asm/ucc_slow.h                |    2 +-
+ arch/powerpc/include/asm/udbg.h                    |    1 -
+ arch/powerpc/include/uapi/asm/setup.h              |   31 --
+ arch/powerpc/kernel/Makefile                       |    2 +-
+ .../{cpu_setup_power7.S => cpu_setup_power.S}      |   32 +-
+ arch/powerpc/kernel/cputable.c                     |   38 +++
+ arch/powerpc/kernel/entry_64.S                     |    2 +
+ arch/powerpc/kernel/exceptions-64s.S               |  308 ++++++++++++++++----
+ arch/powerpc/kernel/head_64.S                      |    6 +-
+ arch/powerpc/kernel/idle.c                         |    3 -
+ arch/powerpc/kernel/iommu.c                        |   16 +-
+ arch/powerpc/kernel/machine_kexec.c                |   14 +-
+ arch/powerpc/kernel/machine_kexec_64.c             |    8 +-
+ arch/powerpc/kernel/pci_32.c                       |    2 +-
+ arch/powerpc/kernel/prom.c                         |    7 +-
+ arch/powerpc/kernel/prom_init.c                    |   11 +-
+ arch/powerpc/kernel/ptrace.c                       |   90 +++++-
+ arch/powerpc/kernel/rtas.c                         |    1 -
+ arch/powerpc/kernel/rtas_flash.c                   |    4 +-
+ arch/powerpc/kernel/setup_64.c                     |    5 +
+ arch/powerpc/kernel/udbg.c                         |   23 --
+ arch/powerpc/mm/numa.c                             |   12 -
+ arch/powerpc/mm/tlb_nohash_low.S                   |   15 +-
+ arch/powerpc/perf/power7-pmu.c                     |   17 +-
+ arch/powerpc/platforms/52xx/lite5200.c             |    2 +-
+ arch/powerpc/platforms/82xx/pq2ads-pci-pic.c       |    8 +-
+ arch/powerpc/platforms/83xx/mpc832x_mds.c          |    2 +-
+ arch/powerpc/platforms/83xx/mpc836x_mds.c          |    2 +-
+ arch/powerpc/platforms/83xx/mpc836x_rdk.c          |    2 +-
+ arch/powerpc/platforms/83xx/mpc837x_rdb.c          |    2 +-
+ arch/powerpc/platforms/85xx/mpc85xx_mds.c          |    2 +-
+ arch/powerpc/platforms/85xx/p1022_ds.c             |    8 +-
+ arch/powerpc/platforms/85xx/smp.c                  |   49 +++-
+ arch/powerpc/platforms/86xx/mpc8610_hpcd.c         |    2 +
+ arch/powerpc/platforms/powermac/cpufreq_32.c       |    5 +-
+ arch/powerpc/platforms/powernv/pci-ioda.c          |   25 +-
+ arch/powerpc/platforms/ps3/os-area.c               |    6 +-
+ arch/powerpc/platforms/pseries/dlpar.c             |   34 +--
+ arch/powerpc/platforms/pseries/firmware.c          |    1 +
+ arch/powerpc/platforms/pseries/hotplug-cpu.c       |    8 +-
+ arch/powerpc/platforms/pseries/hotplug-memory.c    |   60 ++--
+ arch/powerpc/platforms/pseries/iommu.c             |   10 +-
+ arch/powerpc/platforms/pseries/mobility.c          |    4 +-
+ arch/powerpc/platforms/pseries/plpar_wrappers.h    |   31 ++
+ arch/powerpc/platforms/pseries/reconfig.c          |  119 +-------
+ arch/powerpc/platforms/pseries/setup.c             |   77 ++++-
+ arch/powerpc/platforms/pseries/smp.c               |    1 -
+ arch/powerpc/sysdev/fsl_gtm.c                      |    2 +-
+ arch/powerpc/sysdev/fsl_pci.c                      |   37 ++-
+ arch/powerpc/sysdev/pmi.c                          |   13 +-
+ arch/powerpc/sysdev/qe_lib/qe.c                    |    2 +-
+ arch/powerpc/sysdev/qe_lib/qe_ic.c                 |    2 +-
+ arch/powerpc/sysdev/qe_lib/qe_ic.h                 |    2 +-
+ arch/powerpc/sysdev/qe_lib/qe_io.c                 |    2 +-
+ arch/powerpc/sysdev/qe_lib/ucc.c                   |    2 +-
+ arch/powerpc/sysdev/qe_lib/ucc_fast.c              |    2 +-
+ arch/powerpc/sysdev/qe_lib/ucc_slow.c              |    2 +-
+ arch/powerpc/sysdev/qe_lib/usb.c                   |    2 +-
+ arch/powerpc/xmon/Makefile                         |    2 +-
+ arch/powerpc/xmon/nonstdio.c                       |   53 ++--
+ arch/powerpc/xmon/nonstdio.h                       |    6 -
+ arch/powerpc/xmon/start.c                          |   34 ---
+ arch/powerpc/xmon/xmon.c                           |   26 +-
+ drivers/crypto/nx/nx-842.c                         |   20 +-
+ drivers/crypto/nx/nx.c                             |    1 -
+ drivers/infiniband/hw/ehca/hcp_if.c                |   20 --
+ drivers/macintosh/smu.c                            |    2 +-
+ drivers/macintosh/windfarm_fcu_controls.c          |   14 +-
+ drivers/macintosh/windfarm_lm75_sensor.c           |   14 +-
+ drivers/macintosh/windfarm_max6690_sensor.c        |   13 +-
+ drivers/macintosh/windfarm_smu_sat.c               |   13 +-
+ drivers/net/ethernet/ibm/ehea/ehea_phyp.h          |   20 --
+ drivers/of/base.c                                  |  140 ++++++++-
+ drivers/video/Kconfig                              |    8 +-
+ drivers/video/gxt4500.c                            |   15 +-
+ drivers/virt/fsl_hypervisor.c                      |    3 -
+ include/linux/of.h                                 |   29 +-
+ tools/perf/perf.h                                  |    2 +-
+ 107 files changed, 1364 insertions(+), 783 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/powerpc/fsl/raideng.txt
+ create mode 100644 arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi
+ delete mode 100644 arch/powerpc/include/asm/pSeries_reconfig.h
+ create mode 100644 arch/powerpc/include/asm/setup.h
+ rename arch/powerpc/kernel/{cpu_setup_power7.S => cpu_setup_power.S} (80%)
+ delete mode 100644 arch/powerpc/xmon/start.c
+$ git am -3 ../patches/0001-lib-disable-PSERIES_RECONFIG_NOTIFIER_ERROR_INJECT.patch
+Applying: lib: disable PSERIES_RECONFIG_NOTIFIER_ERROR_INJECT
+$ git reset HEAD^
+Unstaged changes after reset:
+M	lib/Kconfig.debug
+$ git add -A .
+$ git commit -v -a --amend
+[master cfb34cb] Merge remote-tracking branch 'powerpc/next'
+Merging 4xx/next (2074b1d powerpc: Fix irq distribution)
+$ git merge 4xx/next
+Already up-to-date.
+Merging mpc5xxx/next (451815b powerpc: mpc5200: Add a3m071 board support)
+$ git merge mpc5xxx/next
+Merge made by the 'recursive' strategy.
+ arch/powerpc/boot/dts/a3m071.dts              |  153 +++++++++++++++++++++++++
+ arch/powerpc/platforms/512x/Kconfig           |    1 -
+ arch/powerpc/platforms/512x/mpc5121_ads.c     |    3 +
+ arch/powerpc/platforms/512x/mpc512x.h         |   11 +-
+ arch/powerpc/platforms/512x/mpc512x_shared.c  |   25 +---
+ arch/powerpc/platforms/52xx/mpc5200_simple.c  |    1 +
+ arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c |   16 +--
+ 7 files changed, 171 insertions(+), 39 deletions(-)
+ create mode 100644 arch/powerpc/boot/dts/a3m071.dts
+Merging galak/next (1723d90 powerpc/dma/raidengine: add raidengine device)
+$ git merge galak/next
+Already up-to-date.
+Merging s390/features (683c3dc s390/ccwgroup: allow drivers to call set_{on,off}line)
+$ git merge s390/features
+Merge made by the 'recursive' strategy.
+ arch/s390/Kconfig                      |   11 +
+ arch/s390/Makefile                     |    1 +
+ arch/s390/crypto/aes_s390.c            |   18 +-
+ arch/s390/crypto/des_s390.c            |   12 +-
+ arch/s390/crypto/ghash_s390.c          |   21 +-
+ arch/s390/crypto/sha_common.c          |    9 +-
+ arch/s390/include/asm/ccwdev.h         |    6 +-
+ arch/s390/include/asm/ccwgroup.h       |    3 +
+ arch/s390/include/asm/page.h           |    2 +
+ arch/s390/include/asm/pgtable.h        |   11 +-
+ arch/s390/include/asm/topology.h       |   34 +-
+ arch/s390/kernel/Makefile              |    2 +-
+ arch/s390/kernel/dis.c                 |  563 +++++++++++++++++++++-----------
+ arch/s390/kernel/entry.S               |    7 +-
+ arch/s390/kernel/entry.h               |   21 +-
+ arch/s390/kernel/entry64.S             |   36 +-
+ arch/s390/kernel/head.S                |   74 +++--
+ arch/s390/kernel/pgm_check.S           |  152 +++++++++
+ arch/s390/kernel/setup.c               |   39 +--
+ arch/s390/kernel/signal.c              |    2 +
+ arch/s390/kernel/topology.c            |  113 +++----
+ arch/s390/kernel/traps.c               |   52 +--
+ arch/s390/mm/Makefile                  |   12 +-
+ arch/s390/mm/dump_pagetables.c         |    7 +-
+ arch/s390/mm/fault.c                   |   31 +-
+ arch/s390/mm/init.c                    |   29 --
+ arch/s390/mm/pageattr.c                |   82 ++++-
+ arch/s390/mm/pgtable.c                 |   16 -
+ arch/s390/mm/vmem.c                    |   46 ++-
+ drivers/s390/block/dasd_eckd.c         |   76 +++--
+ drivers/s390/block/dasd_fba.c          |   23 +-
+ drivers/s390/block/dasd_ioctl.c        |   11 +-
+ drivers/s390/char/sclp_cmd.c           |   17 +-
+ drivers/s390/cio/ccwgroup.c            |   26 +-
+ drivers/s390/cio/device.c              |   11 -
+ drivers/s390/cio/device.h              |    2 -
+ drivers/s390/cio/device_ops.c          |   17 +-
+ drivers/s390/cio/qdio_main.c           |   52 +--
+ drivers/s390/cio/qdio_setup.c          |    7 +-
+ drivers/s390/cio/qdio_thinint.c        |    2 -
+ drivers/s390/crypto/zcrypt_msgtype50.c |   68 ++--
+ drivers/s390/crypto/zcrypt_msgtype50.h |    2 +
+ 42 files changed, 1061 insertions(+), 665 deletions(-)
+ create mode 100644 arch/s390/kernel/pgm_check.S
+Merging sh/sh-latest (0dd4d5c sh: Fix up more fallout from pointless ARM __iomem churn.)
+$ git merge sh/sh-latest
+Already up-to-date.
+Merging sparc-next/master (43c422e apparmor: fix apparmor OOPS in audit_log_untrustedstring+0x1c/0x40)
+$ git merge sparc-next/master
+Already up-to-date.
+Merging tile/master (ddffeb8 Linux 3.7-rc1)
+$ git merge tile/master
+Already up-to-date.
+Merging unicore32/unicore32 (c284464 arch/unicore32: remove CONFIG_EXPERIMENTAL)
+$ git merge unicore32/unicore32
+Already up-to-date.
+Merging xtensa/for_next (518129b xtensa: add XTFPGA DTS)
+$ git merge xtensa/for_next
+Merge made by the 'recursive' strategy.
+ Documentation/xtensa/atomctl.txt                   |   44 ++++
+ arch/xtensa/Kconfig                                |   21 ++
+ arch/xtensa/Kconfig.debug                          |   22 +-
+ arch/xtensa/Makefile                               |   12 +
+ arch/xtensa/boot/Makefile                          |   25 +-
+ arch/xtensa/boot/boot-elf/Makefile                 |   26 +-
+ arch/xtensa/boot/boot-redboot/Makefile             |   26 +-
+ arch/xtensa/boot/boot-uboot/Makefile               |   14 +
+ arch/xtensa/boot/dts/lx60.dts                      |   11 +
+ arch/xtensa/boot/dts/ml605.dts                     |   11 +
+ arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi         |   26 ++
+ arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi          |   18 ++
+ arch/xtensa/boot/dts/xtfpga.dtsi                   |   56 ++++
+ arch/xtensa/include/asm/atomic.h                   |  271 +++++++++++++------
+ arch/xtensa/include/asm/barrier.h                  |    6 +-
+ arch/xtensa/include/asm/bitops.h                   |  127 ++++++++-
+ arch/xtensa/include/asm/bootparam.h                |    1 +
+ arch/xtensa/include/asm/cmpxchg.h                  |   71 +++--
+ arch/xtensa/include/asm/dma-mapping.h              |    2 +
+ arch/xtensa/include/asm/initialize_mmu.h           |   55 ++++
+ arch/xtensa/include/asm/prom.h                     |    6 +
+ arch/xtensa/include/asm/ptrace.h                   |    2 +-
+ arch/xtensa/include/asm/regs.h                     |    4 +
+ arch/xtensa/include/asm/spinlock.h                 |  188 +++++++++++++-
+ arch/xtensa/include/asm/traps.h                    |   23 ++
+ arch/xtensa/kernel/align.S                         |    1 +
+ arch/xtensa/kernel/asm-offsets.c                   |    1 +
+ arch/xtensa/kernel/coprocessor.S                   |   22 ++
+ arch/xtensa/kernel/entry.S                         |   43 +++-
+ arch/xtensa/kernel/head.S                          |   17 +-
+ arch/xtensa/kernel/irq.c                           |  132 +++++++---
+ arch/xtensa/kernel/setup.c                         |  272 ++++++++++++++++++--
+ arch/xtensa/kernel/time.c                          |    7 +-
+ arch/xtensa/kernel/traps.c                         |   11 +
+ arch/xtensa/kernel/vectors.S                       |   65 +++--
+ arch/xtensa/lib/checksum.S                         |    5 +-
+ arch/xtensa/mm/misc.S                              |   49 ++++
+ arch/xtensa/mm/tlb.c                               |    2 +-
+ .../xtensa/platforms/iss/include/platform/serial.h |   15 ++
+ .../platforms/iss/include/platform/simcall.h       |    7 +-
+ arch/xtensa/platforms/xtfpga/Makefile              |    9 +
+ .../platforms/xtfpga/include/platform/hardware.h   |   69 +++++
+ .../xtensa/platforms/xtfpga/include/platform/lcd.h |   20 ++
+ .../platforms/xtfpga/include/platform/serial.h     |   18 ++
+ arch/xtensa/platforms/xtfpga/lcd.c                 |   76 ++++++
+ arch/xtensa/platforms/xtfpga/setup.c               |  269 +++++++++++++++++++
+ arch/xtensa/variants/s6000/gpio.c                  |    4 +-
+ 47 files changed, 1938 insertions(+), 244 deletions(-)
+ create mode 100644 Documentation/xtensa/atomctl.txt
+ create mode 100644 arch/xtensa/boot/boot-uboot/Makefile
+ create mode 100644 arch/xtensa/boot/dts/lx60.dts
+ create mode 100644 arch/xtensa/boot/dts/ml605.dts
+ create mode 100644 arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
+ create mode 100644 arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
+ create mode 100644 arch/xtensa/boot/dts/xtfpga.dtsi
+ create mode 100644 arch/xtensa/include/asm/initialize_mmu.h
+ create mode 100644 arch/xtensa/include/asm/prom.h
+ create mode 100644 arch/xtensa/include/asm/traps.h
+ create mode 100644 arch/xtensa/platforms/xtfpga/Makefile
+ create mode 100644 arch/xtensa/platforms/xtfpga/include/platform/hardware.h
+ create mode 100644 arch/xtensa/platforms/xtfpga/include/platform/lcd.h
+ create mode 100644 arch/xtensa/platforms/xtfpga/include/platform/serial.h
+ create mode 100644 arch/xtensa/platforms/xtfpga/lcd.c
+ create mode 100644 arch/xtensa/platforms/xtfpga/setup.c
+Merging btrfs/next (c37b2b6 Btrfs: do not bug when we fail to commit the transaction)
+$ git merge btrfs/next
+Already up-to-date.
+Merging ceph/master (3515297 rbd: activate v2 image support)
+$ git merge ceph/master
+Auto-merging net/ceph/messenger.c
+Merge made by the 'recursive' strategy.
+ drivers/block/rbd.c  |  100 +++++++++++++++++++++++++++++++++++++++-----------
+ net/ceph/messenger.c |   58 +++++++++++++----------------
+ 2 files changed, 104 insertions(+), 54 deletions(-)
+Merging cifs/for-next (0670be9 CIFS: Fix wrong buffer pointer usage in smb_set_file_info)
+$ git merge cifs/for-next
+Merge made by the 'recursive' strategy.
+ fs/cifs/cifsacl.c  |  190 ++++++++++++++++++++++++++--------------------------
+ fs/cifs/cifsacl.h  |   31 ++++++---
+ fs/cifs/cifsfs.c   |   11 ++-
+ fs/cifs/cifsglob.h |    2 +-
+ fs/cifs/connect.c  |   29 ++------
+ fs/cifs/file.c     |    6 +-
+ fs/cifs/inode.c    |    7 +-
+ fs/cifs/smb1ops.c  |    3 +-
+ 8 files changed, 135 insertions(+), 144 deletions(-)
+Merging configfs/linux-next (b930c26 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs)
+$ git merge configfs/linux-next
+Already up-to-date.
+Merging ecryptfs/next (e4bc652 eCryptfs: Avoid unnecessary disk read and data decryption during writing)
+$ git merge ecryptfs/next
+Merge made by the 'recursive' strategy.
+ fs/ecryptfs/mmap.c |   12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+Merging ext3/for_next (55eede2 quota: Use the pre-processor to compile out quotactl_cmd_write when !CONFIG_BLOCK)
+$ git merge ext3/for_next
+Auto-merging fs/quota/quota.c
+Auto-merging fs/ext3/super.c
+Merge made by the 'recursive' strategy.
+ fs/ext3/inode.c  |    3 +--
+ fs/ext3/super.c  |    3 ---
+ fs/quota/quota.c |    4 ++++
+ fs/udf/inode.c   |   14 +++++++++-----
+ 4 files changed, 14 insertions(+), 10 deletions(-)
+Merging ext4/dev (f3b5929 ext4: remove calls to ext4_jbd2_file_inode() from delalloc write path)
+$ git merge ext4/dev
+Merge made by the 'recursive' strategy.
+ fs/ext4/Makefile            |    2 +-
+ fs/ext4/acl.c               |    6 +-
+ fs/ext4/ext4.h              |   10 +-
+ fs/ext4/ext4_extents.h      |    3 +-
+ fs/ext4/ext4_jbd2.h         |    7 -
+ fs/ext4/extents.c           |  319 +++++----------------------
+ fs/ext4/extents_status.c    |  500 +++++++++++++++++++++++++++++++++++++++++++
+ fs/ext4/extents_status.h    |   45 ++++
+ fs/ext4/file.c              |  334 ++++++++++++++++++++++++++++-
+ fs/ext4/indirect.c          |    4 +-
+ fs/ext4/inode.c             |  175 ++++++---------
+ fs/ext4/mballoc.c           |   60 ++++--
+ fs/ext4/namei.c             |   35 ++-
+ fs/ext4/page-io.c           |    2 +-
+ fs/ext4/resize.c            |   17 +-
+ fs/ext4/super.c             |   43 ++--
+ fs/ext4/xattr.c             |    1 -
+ fs/jbd2/journal.c           |    1 -
+ fs/jbd2/transaction.c       |   11 -
+ include/linux/jbd2.h        |    9 +-
+ include/trace/events/ext4.h |  136 ++++++++++--
+ 21 files changed, 1232 insertions(+), 488 deletions(-)
+ create mode 100644 fs/ext4/extents_status.c
+ create mode 100644 fs/ext4/extents_status.h
+Merging f2fs/dev (660a595 f2fs: remove unneeded version.h header file from f2fs.h)
+$ git merge f2fs/dev
+Merge made by the 'recursive' strategy.
+ Documentation/filesystems/00-INDEX |    2 +
+ Documentation/filesystems/f2fs.txt |  421 +++++++++
+ fs/Kconfig                         |    1 +
+ fs/Makefile                        |    1 +
+ fs/f2fs/Kconfig                    |   52 ++
+ fs/f2fs/Makefile                   |    7 +
+ fs/f2fs/acl.c                      |  465 ++++++++++
+ fs/f2fs/acl.h                      |   57 ++
+ fs/f2fs/checkpoint.c               |  792 ++++++++++++++++
+ fs/f2fs/data.c                     |  701 ++++++++++++++
+ fs/f2fs/debug.c                    |  361 ++++++++
+ fs/f2fs/dir.c                      |  672 ++++++++++++++
+ fs/f2fs/f2fs.h                     | 1061 +++++++++++++++++++++
+ fs/f2fs/file.c                     |  637 +++++++++++++
+ fs/f2fs/gc.c                       |  742 +++++++++++++++
+ fs/f2fs/gc.h                       |  117 +++
+ fs/f2fs/hash.c                     |   98 ++
+ fs/f2fs/inode.c                    |  266 ++++++
+ fs/f2fs/namei.c                    |  504 ++++++++++
+ fs/f2fs/node.c                     | 1763 +++++++++++++++++++++++++++++++++++
+ fs/f2fs/node.h                     |  353 +++++++
+ fs/f2fs/recovery.c                 |  375 ++++++++
+ fs/f2fs/segment.c                  | 1798 ++++++++++++++++++++++++++++++++++++
+ fs/f2fs/segment.h                  |  615 ++++++++++++
+ fs/f2fs/super.c                    |  656 +++++++++++++
+ fs/f2fs/xattr.c                    |  389 ++++++++
+ fs/f2fs/xattr.h                    |  145 +++
+ include/linux/f2fs_fs.h            |  410 ++++++++
+ include/uapi/linux/magic.h         |    1 +
+ 29 files changed, 13462 insertions(+)
+ create mode 100644 Documentation/filesystems/f2fs.txt
+ create mode 100644 fs/f2fs/Kconfig
+ create mode 100644 fs/f2fs/Makefile
+ create mode 100644 fs/f2fs/acl.c
+ create mode 100644 fs/f2fs/acl.h
+ create mode 100644 fs/f2fs/checkpoint.c
+ create mode 100644 fs/f2fs/data.c
+ create mode 100644 fs/f2fs/debug.c
+ create mode 100644 fs/f2fs/dir.c
+ create mode 100644 fs/f2fs/f2fs.h
+ create mode 100644 fs/f2fs/file.c
+ create mode 100644 fs/f2fs/gc.c
+ create mode 100644 fs/f2fs/gc.h
+ create mode 100644 fs/f2fs/hash.c
+ create mode 100644 fs/f2fs/inode.c
+ create mode 100644 fs/f2fs/namei.c
+ create mode 100644 fs/f2fs/node.c
+ create mode 100644 fs/f2fs/node.h
+ create mode 100644 fs/f2fs/recovery.c
+ create mode 100644 fs/f2fs/segment.c
+ create mode 100644 fs/f2fs/segment.h
+ create mode 100644 fs/f2fs/super.c
+ create mode 100644 fs/f2fs/xattr.c
+ create mode 100644 fs/f2fs/xattr.h
+ create mode 100644 include/linux/f2fs_fs.h
+Merging fuse/for-next (23ab0c7 cuse: do not register multiple devices with identical names)
+$ git merge fuse/for-next
+Auto-merging fs/Kconfig
+Merge made by the 'recursive' strategy.
+ fs/Kconfig                |   10 --
+ fs/fuse/Kconfig           |   16 ++-
+ fs/fuse/cuse.c            |   44 ++++++---
+ fs/fuse/dev.c             |  122 ++++++++++++++++-------
+ fs/fuse/dir.c             |  199 ++++++++++++++++++++++++++++++++-----
+ fs/fuse/file.c            |  240 +++++++++++++++++++++++++++++----------------
+ fs/fuse/fuse_i.h          |   58 ++++++++---
+ fs/fuse/inode.c           |   11 ++-
+ include/linux/fs.h        |    2 +-
+ include/uapi/linux/fuse.h |   12 +++
+ mm/filemap.c              |    2 +-
+ 11 files changed, 527 insertions(+), 189 deletions(-)
+Merging gfs2/master (1e2d9d4 GFS2: Set gl_object during inode create)
+$ git merge gfs2/master
+Merge made by the 'recursive' strategy.
+ fs/gfs2/aops.c       |    2 +-
+ fs/gfs2/bmap.c       |   54 ++++++++++++-
+ fs/gfs2/dir.c        |    7 +-
+ fs/gfs2/file.c       |    4 +-
+ fs/gfs2/glock.c      |   40 ++++++----
+ fs/gfs2/glock.h      |   54 ++++++-------
+ fs/gfs2/glops.c      |   19 ++---
+ fs/gfs2/incore.h     |    6 +-
+ fs/gfs2/inode.c      |  209 ++++++++++++++++++++++++++------------------------
+ fs/gfs2/lock_dlm.c   |   20 +++--
+ fs/gfs2/ops_fstype.c |    3 +
+ fs/gfs2/quota.c      |   10 +--
+ fs/gfs2/rgrp.c       |  139 +++++++++++++++++++++++++++++----
+ fs/gfs2/rgrp.h       |    3 +-
+ fs/gfs2/trace_gfs2.h |    2 +-
+ fs/gfs2/xattr.c      |    2 +-
+ 16 files changed, 380 insertions(+), 194 deletions(-)
+Merging jfs/jfs-next (4e7a4b0 jfs: Fix FITRIM argument handling)
+$ git merge jfs/jfs-next
+Already up-to-date.
+Merging logfs/master (3394661 Fix the call to BUG() caused by no free segment found)
+$ git merge logfs/master
+Merge made by the 'recursive' strategy.
+ fs/logfs/dev_mtd.c |    2 +-
+ fs/logfs/super.c   |    6 +++---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+Merging nfs/linux-next (f937b66 Merge branch 'bugfixes' into linux-next)
+$ git merge nfs/linux-next
+Merge made by the 'recursive' strategy.
+ fs/lockd/clnt4xdr.c              |    8 -
+ fs/lockd/clntproc.c              |    3 +-
+ fs/lockd/clntxdr.c               |    9 +-
+ fs/lockd/host.c                  |   15 +-
+ fs/lockd/mon.c                   |    4 +-
+ fs/nfs/Makefile                  |    2 +-
+ fs/nfs/blocklayout/blocklayout.c |    1 +
+ fs/nfs/cache_lib.c               |    1 -
+ fs/nfs/callback.h                |    4 +-
+ fs/nfs/callback_proc.c           |   17 +-
+ fs/nfs/callback_xdr.c            |    5 +-
+ fs/nfs/client.c                  |    7 +-
+ fs/nfs/inode.c                   |    4 +-
+ fs/nfs/internal.h                |   35 --
+ fs/nfs/mount_clnt.c              |    8 +-
+ fs/nfs/nfs2xdr.c                 |    4 +-
+ fs/nfs/nfs3client.c              |    2 +
+ fs/nfs/nfs3xdr.c                 |    7 +-
+ fs/nfs/nfs4_fs.h                 |   29 +-
+ fs/nfs/nfs4client.c              |    5 +-
+ fs/nfs/nfs4file.c                |    1 -
+ fs/nfs/nfs4filelayout.c          |   44 +--
+ fs/nfs/nfs4filelayoutdev.c       |    3 +-
+ fs/nfs/nfs4proc.c                |  728 +++++++++-----------------------------
+ fs/nfs/nfs4session.c             |  436 +++++++++++++++++++++++
+ fs/nfs/nfs4session.h             |  136 +++++++
+ fs/nfs/nfs4state.c               |  119 ++++---
+ fs/nfs/nfs4xdr.c                 |   52 +--
+ fs/nfs/objlayout/objlayout.c     |   11 -
+ fs/nfs/pnfs.c                    |   17 +-
+ fs/nfs/super.c                   |    1 +
+ fs/nfs/write.c                   |   28 +-
+ fs/nfsd/nfs4callback.c           |    1 +
+ include/linux/nfs_fs_sb.h        |   47 ---
+ include/linux/nfs_xdr.h          |   16 +-
+ include/linux/sunrpc/clnt.h      |    1 +
+ net/sunrpc/backchannel_rqst.c    |    9 +-
+ net/sunrpc/bc_svc.c              |    2 +-
+ net/sunrpc/cache.c               |    4 +-
+ net/sunrpc/clnt.c                |   45 ++-
+ net/sunrpc/rpc_pipe.c            |   12 +-
+ net/sunrpc/rpcb_clnt.c           |    5 +-
+ net/sunrpc/sched.c               |   27 +-
+ net/sunrpc/svc.c                 |   12 +-
+ net/sunrpc/svc_xprt.c            |   11 +-
+ net/sunrpc/svcsock.c             |    6 +-
+ net/sunrpc/xdr.c                 |    5 +-
+ net/sunrpc/xprtsock.c            |   13 +-
+ 48 files changed, 1023 insertions(+), 939 deletions(-)
+ create mode 100644 fs/nfs/nfs4session.c
+ create mode 100644 fs/nfs/nfs4session.h
+Merging nfsd/nfsd-next (f3c7521 NFSD: Fold fault_inject.h into state.h)
+$ git merge nfsd/nfsd-next
+Auto-merging net/sunrpc/svc.c
+Auto-merging fs/nfsd/nfs4callback.c
+Removing fs/nfsd/fault_inject.h
+Merge made by the 'recursive' strategy.
+ Documentation/filesystems/nfs/nfs41-server.txt |   20 +-
+ fs/exportfs/expfs.c                            |    4 +-
+ fs/fhandle.c                                   |    2 +-
+ fs/nfsd/fault_inject.c                         |    1 -
+ fs/nfsd/fault_inject.h                         |   28 -
+ fs/nfsd/netns.h                                |   52 ++
+ fs/nfsd/nfs4callback.c                         |   69 ++-
+ fs/nfsd/nfs4proc.c                             |   43 +-
+ fs/nfsd/nfs4recover.c                          |  529 +++++++++++++---
+ fs/nfsd/nfs4state.c                            |  774 ++++++++++++++----------
+ fs/nfsd/nfs4xdr.c                              |  278 +++++----
+ fs/nfsd/nfsctl.c                               |   14 +-
+ fs/nfsd/nfsd.h                                 |    7 +-
+ fs/nfsd/nfsfh.c                                |    4 +-
+ fs/nfsd/nfssvc.c                               |   17 +-
+ fs/nfsd/state.h                                |   56 +-
+ fs/nfsd/vfs.c                                  |   26 +-
+ fs/nfsd/xdr4.h                                 |    7 +-
+ include/linux/exportfs.h                       |    5 +
+ include/linux/sunrpc/cache.h                   |    6 +-
+ net/sunrpc/svc.c                               |    5 +-
+ 21 files changed, 1266 insertions(+), 681 deletions(-)
+ delete mode 100644 fs/nfsd/fault_inject.h
+Merging ocfs2/linux-next (4538df6 ocfs2: Don't spam on -EDQUOT.)
+$ git merge ocfs2/linux-next
+Auto-merging fs/ocfs2/cluster/heartbeat.c
+Merge made by the 'recursive' strategy.
+ fs/ocfs2/cluster/heartbeat.c |   40 +++++++++-------------------------------
+ fs/ocfs2/cluster/masklog.h   |    3 ++-
+ fs/ocfs2/dlm/dlmmaster.c     |   10 ++++++++--
+ fs/ocfs2/dlm/dlmrecovery.c   |    7 +++++++
+ fs/ocfs2/symlink.c           |    2 +-
+ 5 files changed, 27 insertions(+), 35 deletions(-)
+Merging omfs/for-next (976d167 Linux 3.1-rc9)
+$ git merge omfs/for-next
+Already up-to-date.
+Merging squashfs/master (4b0180a Squashfs: add mount time sanity check for block_size and block_log match)
+$ git merge squashfs/master
+Already up-to-date.
+Merging v9fs/for-next (552aad0 9P: Fix race between p9_write_work() and p9_fd_request())
+$ git merge v9fs/for-next
+Merge made by the 'recursive' strategy.
+Merging ubifs/linux-next (a28ad42 UBIFS: fix mounting problems after power cuts)
+$ git merge ubifs/linux-next
+Already up-to-date.
+Merging xfs/for-next (7c4cebe xfs: inode allocation should use unmapped buffers.)
+$ git merge xfs/for-next
+Resolved 'fs/xfs/xfs_fsops.c' using previous resolution.
+Auto-merging fs/xfs/xfs_log_recover.c
+Auto-merging fs/xfs/xfs_log.c
+Auto-merging fs/xfs/xfs_iomap.c
+Auto-merging fs/xfs/xfs_ioctl.c
+Auto-merging fs/xfs/xfs_inode.c
+Removing fs/xfs/xfs_iget.c
+Auto-merging fs/xfs/xfs_icache.h
+Auto-merging fs/xfs/xfs_icache.c
+Auto-merging fs/xfs/xfs_ialloc.c
+Auto-merging fs/xfs/xfs_fsops.c
+CONFLICT (content): Merge conflict in fs/xfs/xfs_fsops.c
+Removing fs/xfs/xfs_fs_subr.c
+Auto-merging fs/xfs/xfs_buf.c
+Auto-merging fs/xfs/xfs_bmap.c
+Auto-merging fs/xfs/xfs_attr_leaf.c
+Auto-merging fs/xfs/xfs_aops.c
+Auto-merging fs/xfs/xfs_alloc_btree.c
+Auto-merging fs/xfs/xfs_alloc.h
+Auto-merging fs/xfs/xfs_alloc.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 2e76020] Merge remote-tracking branch 'xfs/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/filesystems/xfs.txt   |   13 +-
+ fs/xfs/Kconfig                      |    1 +
+ fs/xfs/Makefile                     |    4 +-
+ fs/xfs/uuid.h                       |    6 +
+ fs/xfs/xfs_ag.h                     |    5 +
+ fs/xfs/xfs_alloc.c                  |  140 ++++--
+ fs/xfs/xfs_alloc.h                  |    3 +
+ fs/xfs/xfs_alloc_btree.c            |   77 +++
+ fs/xfs/xfs_alloc_btree.h            |    2 +
+ fs/xfs/xfs_aops.c                   |    2 +-
+ fs/xfs/xfs_attr.c                   |  103 ++--
+ fs/xfs/xfs_attr_leaf.c              |  143 +++---
+ fs/xfs/xfs_attr_leaf.h              |    6 +
+ fs/xfs/xfs_bmap.c                   |   64 ++-
+ fs/xfs/xfs_bmap_btree.c             |   63 +++
+ fs/xfs/xfs_bmap_btree.h             |    1 +
+ fs/xfs/xfs_btree.c                  |  111 +++--
+ fs/xfs/xfs_btree.h                  |   22 +-
+ fs/xfs/xfs_buf.c                    |   59 ++-
+ fs/xfs/xfs_buf.h                    |   27 +-
+ fs/xfs/xfs_cksum.h                  |   63 +++
+ fs/xfs/xfs_da_btree.c               |  141 +++++-
+ fs/xfs/xfs_da_btree.h               |   10 +-
+ fs/xfs/xfs_dfrag.c                  |   13 +-
+ fs/xfs/xfs_dir2_block.c             |  436 ++++++++++-------
+ fs/xfs/xfs_dir2_data.c              |  170 +++++--
+ fs/xfs/xfs_dir2_leaf.c              |  172 +++++--
+ fs/xfs/xfs_dir2_node.c              |  288 +++++++----
+ fs/xfs/xfs_dir2_priv.h              |   19 +-
+ fs/xfs/xfs_dquot.c                  |  134 ++++-
+ fs/xfs/xfs_dquot.h                  |    2 +
+ fs/xfs/xfs_export.c                 |    1 +
+ fs/xfs/xfs_file.c                   |   40 +-
+ fs/xfs/xfs_fs.h                     |   33 +-
+ fs/xfs/xfs_fs_subr.c                |   96 ----
+ fs/xfs/xfs_fsops.c                  |  141 ++++--
+ fs/xfs/xfs_globals.c                |    4 +-
+ fs/xfs/xfs_ialloc.c                 |   83 +++-
+ fs/xfs/xfs_ialloc.h                 |    4 +-
+ fs/xfs/xfs_ialloc_btree.c           |   55 +++
+ fs/xfs/xfs_ialloc_btree.h           |    2 +
+ fs/xfs/{xfs_sync.c => xfs_icache.c} |  914 ++++++++++++++++++++++++-----------
+ fs/xfs/{xfs_sync.h => xfs_icache.h} |   28 +-
+ fs/xfs/xfs_iget.c                   |  705 ---------------------------
+ fs/xfs/xfs_inode.c                  |  437 ++++++++++++++---
+ fs/xfs/xfs_inode.h                  |   12 +-
+ fs/xfs/xfs_ioctl.c                  |   21 +
+ fs/xfs/xfs_iomap.c                  |   31 +-
+ fs/xfs/xfs_iops.c                   |    8 +-
+ fs/xfs/xfs_itable.c                 |    4 +-
+ fs/xfs/xfs_linux.h                  |    2 +
+ fs/xfs/xfs_log.c                    |  238 +++++++--
+ fs/xfs/xfs_log.h                    |    4 +
+ fs/xfs/xfs_log_priv.h               |   12 +-
+ fs/xfs/xfs_log_recover.c            |  146 +++---
+ fs/xfs/xfs_mount.c                  |  163 ++++---
+ fs/xfs/xfs_mount.h                  |   13 +-
+ fs/xfs/xfs_qm.c                     |    7 +-
+ fs/xfs/xfs_qm_syscalls.c            |    6 +-
+ fs/xfs/xfs_rtalloc.c                |   16 +-
+ fs/xfs/xfs_sb.h                     |    7 +
+ fs/xfs/xfs_super.c                  |  148 ++++--
+ fs/xfs/xfs_super.h                  |    1 +
+ fs/xfs/xfs_sysctl.c                 |    9 +
+ fs/xfs/xfs_sysctl.h                 |    1 +
+ fs/xfs/xfs_trace.h                  |   60 ++-
+ fs/xfs/xfs_trans.h                  |   19 +-
+ fs/xfs/xfs_trans_buf.c              |    9 +-
+ fs/xfs/xfs_vnodeops.c               |   80 +--
+ fs/xfs/xfs_vnodeops.h               |    8 +-
+ 70 files changed, 3636 insertions(+), 2232 deletions(-)
+ create mode 100644 fs/xfs/xfs_cksum.h
+ delete mode 100644 fs/xfs/xfs_fs_subr.c
+ rename fs/xfs/{xfs_sync.c => xfs_icache.c} (55%)
+ rename fs/xfs/{xfs_sync.h => xfs_icache.h} (64%)
+ delete mode 100644 fs/xfs/xfs_iget.c
+Merging vfs/for-next (a736427 missing const in alpha callers of do_mount())
+$ git merge vfs/for-next
+Already up-to-date.
+Merging pci/next (053f328 Merge branch 'pci/don-sriov' into next)
+$ git merge pci/next
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-bus-pci |   34 ++++++
+ Documentation/PCI/pci-iov-howto.txt     |   48 ++++++++-
+ arch/x86/pci/acpi.c                     |   46 ++++++++-
+ arch/x86/pci/common.c                   |    2 +-
+ drivers/acpi/pci_bind.c                 |   12 ++-
+ drivers/acpi/pci_irq.c                  |   17 ++-
+ drivers/acpi/pci_root.c                 |  165 ++++++++++++++++-------------
+ drivers/pci/ioapic.c                    |    2 +
+ drivers/pci/iov.c                       |   87 ++++++++++++----
+ drivers/pci/irq.c                       |   10 +-
+ drivers/pci/pci-driver.c                |    6 +-
+ drivers/pci/pci-stub.c                  |    2 +-
+ drivers/pci/pci-sysfs.c                 |  172 +++++++++++++++++++++++++++++--
+ drivers/pci/pci.c                       |   33 +++---
+ drivers/pci/pci.h                       |    8 +-
+ drivers/pci/pcie/aer/aerdrv.h           |    5 +-
+ drivers/pci/pcie/aer/aerdrv_core.c      |   22 +++-
+ drivers/pci/pcie/aspm.c                 |    7 +-
+ drivers/pci/probe.c                     |   23 +++++
+ drivers/pci/quirks.c                    |   39 +++++++
+ drivers/pci/remove.c                    |   36 +++++++
+ drivers/pci/setup-bus.c                 |   22 +---
+ include/acpi/acpi_drivers.h             |    4 +-
+ include/linux/pci.h                     |   19 +++-
+ include/uapi/linux/pci_regs.h           |    6 +-
+ 25 files changed, 641 insertions(+), 186 deletions(-)
+Merging hid/for-next (aad2d46 Merge branch 'for-3.8/hidraw' into for-next)
+$ git merge hid/for-next
+Auto-merging drivers/input/input-mt.c
+Merge made by the 'recursive' strategy.
+ .../ABI/obsolete/sysfs-driver-hid-roccat-koneplus  |   38 +
+ .../ABI/obsolete/sysfs-driver-hid-roccat-kovaplus  |   66 ++
+ .../ABI/obsolete/sysfs-driver-hid-roccat-pyra      |   73 ++
+ .../ABI/testing/sysfs-driver-hid-roccat-isku       |    8 +
+ .../ABI/testing/sysfs-driver-hid-roccat-koneplus   |   48 +-
+ .../ABI/testing/sysfs-driver-hid-roccat-kovaplus   |   69 +-
+ .../ABI/testing/sysfs-driver-hid-roccat-lua        |    7 +
+ .../ABI/testing/sysfs-driver-hid-roccat-pyra       |   76 +-
+ .../ABI/testing/sysfs-driver-hid-roccat-savu       |    3 +-
+ Documentation/input/event-codes.txt                |   11 +
+ drivers/hid/Kconfig                                |   11 +
+ drivers/hid/Makefile                               |    6 +-
+ drivers/hid/hid-apple.c                            |    3 +-
+ drivers/hid/hid-core.c                             |   33 +-
+ drivers/hid/hid-icade.c                            |  259 ++++++
+ drivers/hid/hid-ids.h                              |   12 +
+ drivers/hid/hid-input.c                            |   36 +-
+ drivers/hid/hid-multitouch.c                       |  109 ++-
+ drivers/hid/hid-roccat-isku.c                      |   44 +-
+ drivers/hid/hid-roccat-isku.h                      |   78 +-
+ drivers/hid/hid-roccat-koneplus.c                  |  348 ++-----
+ drivers/hid/hid-roccat-koneplus.h                  |  101 +-
+ drivers/hid/hid-roccat-kovaplus.c                  |  237 +++--
+ drivers/hid/hid-roccat-kovaplus.h                  |   16 +-
+ drivers/hid/hid-roccat-lua.c                       |  227 +++++
+ drivers/hid/hid-roccat-lua.h                       |   29 +
+ drivers/hid/hid-roccat-pyra.c                      |  342 +++----
+ drivers/hid/hid-roccat-pyra.h                      |   24 +-
+ drivers/hid/hid-roccat-savu.c                      |    4 +-
+ drivers/hid/hid-sensor-hub.c                       |    4 -
+ drivers/hid/hidraw.c                               |   16 +-
+ drivers/hid/i2c-hid/Kconfig                        |   21 +
+ drivers/hid/i2c-hid/Makefile                       |    5 +
+ drivers/hid/i2c-hid/i2c-hid.c                      |  975 ++++++++++++++++++++
+ drivers/hid/usbhid/hid-quirks.c                    |    2 +
+ drivers/hid/usbhid/hiddev.c                        |   10 +-
+ drivers/input/input-mt.c                           |    2 +-
+ include/linux/hid.h                                |    3 +
+ include/linux/i2c/i2c-hid.h                        |   35 +
+ include/linux/input/mt.h                           |    6 +
+ include/uapi/linux/input.h                         |    1 +
+ 41 files changed, 2423 insertions(+), 975 deletions(-)
+ create mode 100644 Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus
+ create mode 100644 Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra
+ create mode 100644 Documentation/ABI/testing/sysfs-driver-hid-roccat-lua
+ create mode 100644 drivers/hid/hid-icade.c
+ create mode 100644 drivers/hid/hid-roccat-lua.c
+ create mode 100644 drivers/hid/hid-roccat-lua.h
+ create mode 100644 drivers/hid/i2c-hid/Kconfig
+ create mode 100644 drivers/hid/i2c-hid/Makefile
+ create mode 100644 drivers/hid/i2c-hid/i2c-hid.c
+ create mode 100644 include/linux/i2c/i2c-hid.h
+Merging i2c/master (c1ec1ae i2c: Mention functionality flags in SMBus protocol documentation)
+$ git merge i2c/master
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/i2c/smbus-protocol |   40 +++++++++++++++++++++++++++++---------
+ MAINTAINERS                      |    2 +-
+ drivers/i2c/busses/i2c-i801.c    |   13 +++----------
+ drivers/i2c/busses/i2c-piix4.c   |    5 ++---
+ 4 files changed, 37 insertions(+), 23 deletions(-)
+Merging i2c-embedded/i2c-embedded/for-next (60937b2 i2c: at91: add dma support)
+$ git merge i2c-embedded/i2c-embedded/for-next
+Resolved 'drivers/i2c/busses/i2c-omap.c' using previous resolution.
+Auto-merging include/linux/i2c-omap.h
+Auto-merging drivers/i2c/busses/i2c-s3c2410.c
+Auto-merging drivers/i2c/busses/i2c-omap.c
+CONFLICT (content): Merge conflict in drivers/i2c/busses/i2c-omap.c
+Auto-merging drivers/i2c/busses/i2c-mxs.c
+Auto-merging drivers/i2c/busses/i2c-at91.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master bac27b8] Merge remote-tracking branch 'i2c-embedded/i2c-embedded/for-next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/i2c/i2c-cbus-gpio.txt      |   27 ++
+ .../devicetree/bindings/i2c/i2c-mux-gpio.txt       |   81 +++++
+ .../devicetree/bindings/i2c/i2c-ocores.txt         |    2 +-
+ .../devicetree/bindings/i2c/samsung-i2c.txt        |   20 +-
+ arch/arm/boot/dts/imx28-cfa10049.dts               |   24 ++
+ arch/arm/mach-omap2/board-n8x0.c                   |   42 +++
+ arch/arm/mach-omap2/omap_hwmod_2430_data.c         |    3 +-
+ arch/arm/mach-omap2/omap_hwmod_3xxx_data.c         |    9 +-
+ drivers/i2c/busses/Kconfig                         |   10 +
+ drivers/i2c/busses/Makefile                        |    1 +
+ drivers/i2c/busses/i2c-at91.c                      |  338 ++++++++++++++++++--
+ drivers/i2c/busses/i2c-cbus-gpio.c                 |  300 +++++++++++++++++
+ drivers/i2c/busses/i2c-gpio.c                      |    6 +-
+ drivers/i2c/busses/i2c-mxs.c                       |    2 +-
+ drivers/i2c/busses/i2c-nomadik.c                   |   14 -
+ drivers/i2c/busses/i2c-ocores.c                    |  164 ++++++++--
+ drivers/i2c/busses/i2c-omap.c                      |  225 +++++++------
+ drivers/i2c/busses/i2c-rcar.c                      |    6 +-
+ drivers/i2c/busses/i2c-s3c2410.c                   |  211 +++++++-----
+ drivers/i2c/busses/i2c-sh_mobile.c                 |  150 ++++++---
+ drivers/i2c/muxes/i2c-mux-gpio.c                   |  145 +++++++--
+ include/linux/i2c-omap.h                           |    1 -
+ include/linux/i2c/i2c-sh_mobile.h                  |    1 +
+ include/linux/platform_data/i2c-cbus-gpio.h        |   27 ++
+ 24 files changed, 1459 insertions(+), 350 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt
+ create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt
+ create mode 100644 drivers/i2c/busses/i2c-cbus-gpio.c
+ create mode 100644 include/linux/platform_data/i2c-cbus-gpio.h
+Merging jdelvare-hwmon/master (d2d9cf3 hwmon: (it87) Support PECI for additional chips)
+$ git merge jdelvare-hwmon/master
+Merge made by the 'recursive' strategy.
+ Documentation/hwmon/it87  |   10 +
+ drivers/hwmon/hwmon.c     |   26 +-
+ drivers/hwmon/it87.c      |  918 +++++++++++++++++++++++----------------------
+ drivers/hwmon/w83627ehf.c |   99 ++++-
+ drivers/hwmon/w83627hf.c  |   81 +++-
+ 5 files changed, 679 insertions(+), 455 deletions(-)
+Merging hwmon-staging/hwmon-next (8b59397 hwmon: (da9055) Fix chan_mux[DA9055_ADC_ADCIN3] setting)
+$ git merge hwmon-staging/hwmon-next
+Merge made by the 'recursive' strategy.
+ Documentation/hwmon/ads7828           |   46 +++--
+ Documentation/hwmon/coretemp          |    2 +
+ Documentation/hwmon/da9055            |   47 +++++
+ drivers/hwmon/Kconfig                 |   19 +-
+ drivers/hwmon/Makefile                |    1 +
+ drivers/hwmon/ads7828.c               |  247 ++++++++++--------------
+ drivers/hwmon/coretemp.c              |   60 +++---
+ drivers/hwmon/da9052-hwmon.c          |   27 +--
+ drivers/hwmon/da9055-hwmon.c          |  336 +++++++++++++++++++++++++++++++++
+ drivers/hwmon/ina2xx.c                |   13 +-
+ include/linux/platform_data/ads7828.h |   29 +++
+ 11 files changed, 603 insertions(+), 224 deletions(-)
+ create mode 100644 Documentation/hwmon/da9055
+ create mode 100644 drivers/hwmon/da9055-hwmon.c
+ create mode 100644 include/linux/platform_data/ads7828.h
+Merging v4l-dvb/master (5a79780 Merge /home/v4l/v4l/patchwork)
+$ git merge v4l-dvb/master
+Removing include/linux/dvb/video.h
+Removing include/linux/dvb/dmx.h
+Removing include/linux/dvb/Kbuild
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/DocBook/media/v4l/compat.xml         |    7 +
+ Documentation/DocBook/media/v4l/io.xml             |  188 +++++-
+ Documentation/DocBook/media/v4l/v4l2.xml           |    1 +
+ .../DocBook/media/v4l/vidioc-create-bufs.xml       |   16 +-
+ Documentation/DocBook/media/v4l/vidioc-expbuf.xml  |  212 ++++++
+ Documentation/DocBook/media/v4l/vidioc-qbuf.xml    |   17 +
+ Documentation/DocBook/media/v4l/vidioc-reqbufs.xml |   47 +-
+ MAINTAINERS                                        |  250 ++++++-
+ arch/arm/mach-pxa/pcm990-baseboard.c               |    6 +
+ drivers/hid/hid-picolcd_cir.c                      |    2 +-
+ drivers/media/common/Kconfig                       |    7 +
+ drivers/media/common/b2c2/Kconfig                  |    5 -
+ drivers/media/common/siano/Kconfig                 |   18 +-
+ drivers/media/common/siano/Makefile                |    6 +-
+ drivers/media/common/siano/smscoreapi.c            |    2 +-
+ drivers/media/common/siano/smsir.c                 |    2 +-
+ drivers/media/common/siano/smsir.h                 |    9 +
+ drivers/media/dvb-core/dmxdev.c                    |    2 +-
+ drivers/media/dvb-core/dmxdev.h                    |    1 +
+ drivers/media/dvb-core/dvb_frontend.c              |   10 -
+ drivers/media/dvb-frontends/cx22700.c              |    4 +-
+ drivers/media/dvb-frontends/cx24123.c              |    2 +-
+ drivers/media/dvb-frontends/dib9000.h              |    2 +-
+ drivers/media/dvb-frontends/drxd_hard.c            |    8 +-
+ drivers/media/dvb-frontends/drxk_hard.c            |   24 +-
+ drivers/media/dvb-frontends/drxk_hard.h            |    6 +-
+ drivers/media/dvb-frontends/ds3000.c               |   15 +-
+ drivers/media/dvb-frontends/l64781.c               |    4 +-
+ drivers/media/dvb-frontends/mt312.c                |    4 +-
+ drivers/media/dvb-frontends/rtl2830.c              |    6 +-
+ drivers/media/dvb-frontends/rtl2832.c              |    6 +-
+ drivers/media/dvb-frontends/stb0899_drv.c          |    2 +-
+ drivers/media/dvb-frontends/stv0367.c              |   19 +-
+ drivers/media/dvb-frontends/tda10071.c             |    6 +-
+ drivers/media/dvb-frontends/tda18271c2dd.c         |    1 +
+ drivers/media/firewire/firedtv.h                   |    1 +
+ drivers/media/i2c/adp1653.c                        |    4 +-
+ drivers/media/i2c/adv7183.c                        |   13 +-
+ drivers/media/i2c/adv7604.c                        |   16 +-
+ drivers/media/i2c/cx25840/cx25840-core.c           |    2 +-
+ drivers/media/i2c/ir-kbd-i2c.c                     |   14 +-
+ drivers/media/i2c/s5k4ecgx.c                       |    2 +-
+ drivers/media/i2c/smiapp-pll.c                     |  219 +++---
+ drivers/media/i2c/smiapp-pll.h                     |   61 +-
+ drivers/media/i2c/smiapp/smiapp-core.c             |   74 +-
+ drivers/media/i2c/smiapp/smiapp-limits.c           |    2 +-
+ drivers/media/i2c/smiapp/smiapp-limits.h           |    2 +-
+ drivers/media/i2c/smiapp/smiapp-quirk.c            |    2 +-
+ drivers/media/i2c/smiapp/smiapp-quirk.h            |    2 +-
+ drivers/media/i2c/smiapp/smiapp-reg-defs.h         |    2 +-
+ drivers/media/i2c/smiapp/smiapp-reg.h              |    2 +-
+ drivers/media/i2c/smiapp/smiapp-regs.c             |    2 +-
+ drivers/media/i2c/smiapp/smiapp-regs.h             |    2 +-
+ drivers/media/i2c/smiapp/smiapp.h                  |    2 +-
+ drivers/media/i2c/soc_camera/mt9v022.c             |   88 ++-
+ drivers/media/i2c/soc_camera/ov2640.c              |   55 +-
+ drivers/media/i2c/vs6624.c                         |   13 +-
+ drivers/media/mmc/siano/Kconfig                    |    3 +-
+ drivers/media/pci/bt8xx/bttv-driver.c              |    7 +-
+ drivers/media/pci/cx18/cx18-alsa-main.c            |    2 +-
+ drivers/media/pci/cx18/cx18-alsa-pcm.c             |    1 +
+ drivers/media/pci/cx18/cx18-i2c.c                  |    2 +-
+ drivers/media/pci/cx18/cx18-streams.c              |    2 +-
+ drivers/media/pci/cx23885/altera-ci.c              |   45 +-
+ drivers/media/pci/cx23885/cimax2.c                 |   17 +-
+ drivers/media/pci/cx23885/cx23885-alsa.c           |    6 +-
+ drivers/media/pci/cx23885/cx23885-av.c             |    1 +
+ drivers/media/pci/cx23885/cx23885-cards.c          |    2 +-
+ drivers/media/pci/cx23885/cx23885-core.c           |    8 +-
+ drivers/media/pci/cx23885/cx23885-dvb.c            |    2 +-
+ drivers/media/pci/cx23885/cx23885-f300.c           |    1 +
+ drivers/media/pci/cx23885/cx23885-input.c          |    7 +-
+ drivers/media/pci/cx23885/cx23885-input.h          |    2 +-
+ drivers/media/pci/cx23885/cx23885-ioctl.c          |    2 +
+ drivers/media/pci/cx23885/cx23885-ir.c             |    1 +
+ drivers/media/pci/cx23885/cx23888-ir.c             |    1 +
+ drivers/media/pci/cx23885/netup-init.c             |    1 +
+ drivers/media/pci/cx25821/cx25821-audio-upstream.c |   44 +-
+ drivers/media/pci/cx25821/cx25821-biffuncs.h       |    6 +-
+ drivers/media/pci/cx25821/cx25821-i2c.c            |    4 +-
+ .../media/pci/cx25821/cx25821-video-upstream-ch2.c |   54 +-
+ drivers/media/pci/cx25821/cx25821-video-upstream.c |   47 +-
+ drivers/media/pci/cx25821/cx25821-video.c          |    8 +-
+ drivers/media/pci/cx88/cx88-alsa.c                 |   14 +-
+ drivers/media/pci/cx88/cx88-blackbird.c            |    7 +-
+ drivers/media/pci/cx88/cx88-core.c                 |   12 +-
+ drivers/media/pci/cx88/cx88-input.c                |    8 +-
+ drivers/media/pci/cx88/cx88-mpeg.c                 |   18 +-
+ drivers/media/pci/cx88/cx88.h                      |    4 +-
+ drivers/media/pci/dm1105/dm1105.c                  |    8 +-
+ drivers/media/pci/ivtv/ivtv-alsa-main.c            |    2 +-
+ drivers/media/pci/ivtv/ivtv-alsa-pcm.c             |    6 +-
+ drivers/media/pci/ivtv/ivtv-alsa-pcm.h             |    4 -
+ drivers/media/pci/ivtv/ivtv-firmware.c             |    2 +-
+ drivers/media/pci/ivtv/ivtv-i2c.c                  |    8 +-
+ drivers/media/pci/ivtv/ivtv-ioctl.c                |    4 +-
+ drivers/media/pci/mantis/mantis_input.c            |    5 +-
+ drivers/media/pci/mantis/mantis_uart.c             |    2 +-
+ drivers/media/pci/mantis/mantis_vp1033.c           |    6 +-
+ drivers/media/pci/meye/meye.c                      |    2 +-
+ drivers/media/pci/ngene/ngene-cards.c              |    4 +-
+ drivers/media/pci/ngene/ngene-core.c               |    7 +-
+ drivers/media/pci/saa7134/saa7134-core.c           |    3 +-
+ drivers/media/pci/saa7134/saa7134-input.c          |    2 +-
+ drivers/media/pci/saa7134/saa7134-video.c          |    2 +-
+ drivers/media/pci/saa7164/saa7164-api.c            |   26 +-
+ drivers/media/pci/saa7164/saa7164-bus.c            |    6 +-
+ drivers/media/pci/saa7164/saa7164-cmd.c            |   16 +-
+ drivers/media/pci/saa7164/saa7164-core.c           |    4 +-
+ drivers/media/pci/saa7164/saa7164-encoder.c        |   15 +-
+ drivers/media/pci/saa7164/saa7164-fw.c             |    8 +-
+ drivers/media/pci/saa7164/saa7164-vbi.c            |    6 +-
+ drivers/media/pci/ttpci/av7110.h                   |    1 +
+ drivers/media/pci/ttpci/budget-av.c                |    4 +-
+ drivers/media/platform/blackfin/bfin_capture.c     |   14 +-
+ drivers/media/platform/coda.c                      |    4 +-
+ drivers/media/platform/davinci/Kconfig             |    2 +-
+ drivers/media/platform/davinci/dm355_ccdc.c        |    8 +-
+ drivers/media/platform/davinci/dm644x_ccdc.c       |   16 +-
+ drivers/media/platform/davinci/isif.c              |    5 +-
+ drivers/media/platform/davinci/vpbe.c              |   10 +-
+ drivers/media/platform/davinci/vpbe_display.c      |  303 +++++----
+ drivers/media/platform/davinci/vpbe_osd.c          |    9 +-
+ drivers/media/platform/davinci/vpif.c              |    8 +-
+ drivers/media/platform/davinci/vpif_capture.c      |   34 +-
+ drivers/media/platform/davinci/vpif_display.c      |   28 +-
+ drivers/media/platform/exynos-gsc/gsc-core.c       |    2 +-
+ drivers/media/platform/exynos-gsc/gsc-m2m.c        |    2 +-
+ drivers/media/platform/fsl-viu.c                   |    6 +-
+ drivers/media/platform/m2m-deinterlace.c           |   24 +-
+ drivers/media/platform/mem2mem_testdev.c           |    4 +-
+ drivers/media/platform/mx2_emmaprp.c               |   14 +-
+ drivers/media/platform/omap/omap_vout.c            |   36 +-
+ drivers/media/platform/s5p-fimc/fimc-capture.c     |   11 +-
+ drivers/media/platform/s5p-fimc/fimc-m2m.c         |   16 +-
+ drivers/media/platform/s5p-fimc/fimc-mdevice.c     |    4 +-
+ drivers/media/platform/s5p-mfc/s5p_mfc_dec.c       |   14 +
+ drivers/media/platform/s5p-mfc/s5p_mfc_enc.c       |   16 +-
+ drivers/media/platform/s5p-mfc/s5p_mfc_pm.c        |    2 +-
+ drivers/media/platform/s5p-tv/mixer_video.c        |   13 +-
+ drivers/media/platform/soc_camera/Kconfig          |    1 +
+ drivers/media/platform/soc_camera/soc_camera.c     |   14 +-
+ drivers/media/platform/vivi.c                      |    8 +-
+ drivers/media/radio/radio-aimslab.c                |    2 +-
+ drivers/media/radio/radio-cadet.c                  |    3 +-
+ drivers/media/radio/radio-isa.c                    |   10 +-
+ drivers/media/radio/radio-sf16fmi.c                |    2 +-
+ drivers/media/radio/radio-tea5764.c                |    4 +-
+ drivers/media/radio/si4713-i2c.c                   |    2 +-
+ drivers/media/radio/wl128x/fmdrv.h                 |    2 +-
+ drivers/media/radio/wl128x/fmdrv_common.c          |    2 +-
+ drivers/media/radio/wl128x/fmdrv_rx.c              |    2 +-
+ drivers/media/rc/ati_remote.c                      |    2 +-
+ drivers/media/rc/ene_ir.c                          |   33 +-
+ drivers/media/rc/fintek-cir.c                      |    6 +-
+ drivers/media/rc/gpio-ir-recv.c                    |    2 +-
+ drivers/media/rc/iguanair.c                        |    2 +-
+ drivers/media/rc/imon.c                            |   40 +-
+ drivers/media/rc/ir-jvc-decoder.c                  |    4 +-
+ drivers/media/rc/ir-lirc-codec.c                   |    4 +-
+ drivers/media/rc/ir-mce_kbd-decoder.c              |    4 +-
+ drivers/media/rc/ir-nec-decoder.c                  |    4 +-
+ drivers/media/rc/ir-rc5-decoder.c                  |   14 +-
+ drivers/media/rc/ir-rc5-sz-decoder.c               |    6 +-
+ drivers/media/rc/ir-rc6-decoder.c                  |    8 +-
+ drivers/media/rc/ir-rx51.c                         |   13 +-
+ drivers/media/rc/ir-sanyo-decoder.c                |    4 +-
+ drivers/media/rc/ir-sony-decoder.c                 |   17 +-
+ drivers/media/rc/ite-cir.c                         |    6 +-
+ drivers/media/rc/keymaps/rc-imon-mce.c             |    2 +-
+ drivers/media/rc/keymaps/rc-rc6-mce.c              |    2 +-
+ drivers/media/rc/mceusb.c                          |    2 +-
+ drivers/media/rc/nuvoton-cir.c                     |   13 +-
+ drivers/media/rc/nuvoton-cir.h                     |    1 -
+ drivers/media/rc/rc-loopback.c                     |    2 +-
+ drivers/media/rc/rc-main.c                         |   73 +-
+ drivers/media/rc/redrat3.c                         |    2 +-
+ drivers/media/rc/streamzap.c                       |    2 +-
+ drivers/media/rc/ttusbir.c                         |    2 +-
+ drivers/media/rc/winbond-cir.c                     |  113 +++-
+ drivers/media/tuners/max2165.c                     |    2 +-
+ drivers/media/tuners/tua9001.c                     |    2 +-
+ drivers/media/tuners/xc4000.c                      |    2 +-
+ drivers/media/usb/au0828/au0828-cards.c            |    2 +-
+ drivers/media/usb/au0828/au0828-dvb.c              |    5 +-
+ drivers/media/usb/au0828/au0828-video.c            |   16 +-
+ drivers/media/usb/cx231xx/cx231xx-avcore.c         |    9 +-
+ drivers/media/usb/cx231xx/cx231xx-cards.c          |    8 +-
+ drivers/media/usb/cx231xx/cx231xx-i2c.c            |    4 +-
+ drivers/media/usb/cx231xx/cx231xx-input.c          |    2 +-
+ drivers/media/usb/dvb-usb-v2/af9015.c              |    2 +-
+ drivers/media/usb/dvb-usb-v2/af9035.c              |    4 +-
+ drivers/media/usb/dvb-usb-v2/anysee.c              |    4 +-
+ drivers/media/usb/dvb-usb-v2/az6007.c              |    2 +-
+ drivers/media/usb/dvb-usb-v2/dvb_usb.h             |    2 +-
+ drivers/media/usb/dvb-usb-v2/dvb_usb_core.c        |   14 +-
+ drivers/media/usb/dvb-usb-v2/it913x.c              |   12 +-
+ drivers/media/usb/dvb-usb-v2/lmedm04.c             |    4 +-
+ drivers/media/usb/dvb-usb-v2/rtl28xxu.c            |    4 +-
+ drivers/media/usb/dvb-usb-v2/usb_urb.c             |    8 +-
+ drivers/media/usb/dvb-usb/az6027.c                 |   11 +-
+ drivers/media/usb/dvb-usb/dib0700.h                |    2 +-
+ drivers/media/usb/dvb-usb/dib0700_core.c           |   16 +-
+ drivers/media/usb/dvb-usb/dib0700_devices.c        |  146 ++--
+ drivers/media/usb/dvb-usb/dvb-usb.h                |    2 +-
+ drivers/media/usb/dvb-usb/pctv452e.c               |    4 +-
+ drivers/media/usb/dvb-usb/technisat-usb2.c         |    2 +-
+ drivers/media/usb/dvb-usb/ttusb2.c                 |    2 +-
+ drivers/media/usb/dvb-usb/vp702x.c                 |    8 +-
+ drivers/media/usb/em28xx/em28xx-cards.c            |   15 +-
+ drivers/media/usb/em28xx/em28xx-dvb.c              |   84 ++-
+ drivers/media/usb/em28xx/em28xx-input.c            |   16 +-
+ drivers/media/usb/em28xx/em28xx.h                  |    1 +
+ drivers/media/usb/gspca/gspca.c                    |    3 +-
+ drivers/media/usb/gspca/gspca.h                    |    2 +-
+ drivers/media/usb/gspca/jeilinj.c                  |    6 +-
+ drivers/media/usb/gspca/m5602/m5602_s5k4aa.c       |    6 +
+ drivers/media/usb/gspca/pac7302.c                  |   62 +-
+ drivers/media/usb/gspca/sonixb.c                   |    1 +
+ drivers/media/usb/hdpvr/hdpvr-core.c               |    2 +
+ drivers/media/usb/hdpvr/hdpvr-i2c.c                |    2 +-
+ drivers/media/usb/pvrusb2/pvrusb2-hdw.c            |    6 +-
+ drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c       |    4 +-
+ drivers/media/usb/pvrusb2/pvrusb2-v4l2.c           |    4 +-
+ drivers/media/usb/pwc/pwc-ctrl.c                   |    2 +
+ drivers/media/usb/pwc/pwc-if.c                     |    8 +-
+ drivers/media/usb/s2255/s2255drv.c                 |    2 +-
+ drivers/media/usb/siano/Kconfig                    |    3 +-
+ drivers/media/usb/sn9c102/sn9c102_core.c           |    2 +
+ drivers/media/usb/stk1160/stk1160-i2c.c            |    2 +-
+ drivers/media/usb/stk1160/stk1160-video.c          |   23 +-
+ drivers/media/usb/stk1160/stk1160.h                |    5 +-
+ drivers/media/usb/stkwebcam/stk-webcam.c           |    5 +-
+ drivers/media/usb/tlg2300/pd-dvb.c                 |    1 +
+ drivers/media/usb/tlg2300/pd-video.c               |    4 +-
+ drivers/media/usb/tm6000/tm6000-input.c            |   20 +-
+ drivers/media/usb/tm6000/tm6000-video.c            |    1 +
+ drivers/media/usb/usbvision/usbvision.h            |    2 +-
+ drivers/media/usb/uvc/uvc_queue.c                  |    2 +-
+ drivers/media/usb/zr364xx/zr364xx.c                |    3 +-
+ drivers/media/v4l2-core/Kconfig                    |    3 +
+ drivers/media/v4l2-core/v4l2-common.c              |    3 +-
+ drivers/media/v4l2-core/v4l2-compat-ioctl32.c      |   19 +
+ drivers/media/v4l2-core/v4l2-dev.c                 |    1 +
+ drivers/media/v4l2-core/v4l2-event.c               |    2 +-
+ drivers/media/v4l2-core/v4l2-fh.c                  |    2 +-
+ drivers/media/v4l2-core/v4l2-ioctl.c               |   11 +
+ drivers/media/v4l2-core/v4l2-mem2mem.c             |   19 +-
+ drivers/media/v4l2-core/v4l2-subdev.c              |   22 +-
+ drivers/media/v4l2-core/videobuf-core.c            |    4 +
+ drivers/media/v4l2-core/videobuf2-core.c           |  300 ++++++++-
+ drivers/media/v4l2-core/videobuf2-dma-contig.c     |  706 ++++++++++++++++++--
+ drivers/media/v4l2-core/videobuf2-memops.c         |   40 --
+ drivers/media/v4l2-core/videobuf2-vmalloc.c        |   56 ++
+ drivers/staging/media/dt3155v4l/dt3155v4l.c        |    4 +-
+ drivers/staging/media/go7007/go7007-fw.c           |   42 +-
+ drivers/staging/media/go7007/go7007-v4l2.c         |    2 +-
+ drivers/staging/media/go7007/s2250-board.c         |   13 +-
+ drivers/staging/media/go7007/wis-ov7640.c          |   20 +-
+ drivers/staging/media/go7007/wis-saa7113.c         |   20 +-
+ drivers/staging/media/go7007/wis-saa7115.c         |   20 +-
+ drivers/staging/media/go7007/wis-sony-tuner.c      |   13 +-
+ drivers/staging/media/go7007/wis-tw2804.c          |   13 +-
+ drivers/staging/media/go7007/wis-tw9903.c          |   13 +-
+ drivers/staging/media/go7007/wis-uda1342.c         |   13 +-
+ drivers/staging/media/lirc/lirc_serial.c           |    6 +-
+ include/linux/dvb/dmx.h                            |   29 -
+ include/linux/dvb/video.h                          |   29 -
+ include/media/adp1653.h                            |    4 +-
+ include/media/davinci/vpbe_display.h               |   15 +-
+ include/media/davinci/vpbe_osd.h                   |    2 +-
+ include/media/ir-kbd-i2c.h                         |    2 +-
+ include/media/mt9v022.h                            |   16 +
+ include/media/rc-core.h                            |    4 +-
+ include/media/rc-map.h                             |   64 +-
+ include/media/smiapp.h                             |    2 +-
+ include/media/v4l2-event.h                         |    2 +-
+ include/media/v4l2-fh.h                            |    2 +-
+ include/media/v4l2-ioctl.h                         |    2 +
+ include/media/v4l2-mem2mem.h                       |    3 +
+ include/media/videobuf2-core.h                     |   38 ++
+ include/media/videobuf2-memops.h                   |    5 -
+ include/uapi/linux/videodev2.h                     |   37 +-
+ 283 files changed, 3651 insertions(+), 1601 deletions(-)
+ create mode 100644 Documentation/DocBook/media/v4l/vidioc-expbuf.xml
+ delete mode 100644 include/linux/dvb/Kbuild
+ delete mode 100644 include/linux/dvb/dmx.h
+ delete mode 100644 include/linux/dvb/video.h
+ create mode 100644 include/media/mt9v022.h
+Merging kbuild/for-next (a5ce08d Merge branches 'kbuild/kbuild' and 'kbuild/kconfig' into kbuild/for-next)
+$ git merge kbuild/for-next
+Auto-merging Makefile
+Merge made by the 'recursive' strategy.
+ Makefile                                   |    2 +-
+ scripts/kconfig/expr.c                     |   10 +++++-----
+ scripts/kconfig/gconf.c                    |    2 +-
+ scripts/kconfig/lkc.h                      |    8 ++++++++
+ scripts/kconfig/lxdialog/check-lxdialog.sh |    1 +
+ scripts/kconfig/mconf.c                    |   10 ++++++++--
+ scripts/kconfig/menu.c                     |    4 ++--
+ scripts/kconfig/nconf.c                    |   12 ++++++++++--
+ scripts/kconfig/symbol.c                   |   12 ++++++------
+ scripts/kconfig/util.c                     |   23 +++++++++++++++++++++--
+ scripts/kconfig/zconf.l                    |    8 ++++----
+ scripts/kconfig/zconf.lex.c_shipped        |    8 ++++----
+ scripts/pnmtologo.c                        |    7 +++++++
+ 13 files changed, 78 insertions(+), 29 deletions(-)
+Merging kconfig/for-next (4eae518 localmodconfig: Fix localyesconfig to set to 'y' not 'm')
+$ git merge kconfig/for-next
+Already up-to-date.
+Merging libata/NEXT (a52f514 ata: Convert dev_printk(KERN_<LEVEL> to dev_<level>()
+$ git merge libata/NEXT
+Merge made by the 'recursive' strategy.
+ drivers/ata/ata_piix.c       |   25 ++++++++++++++++++++++---
+ drivers/ata/pata_arasan_cf.c |    7 +++++--
+ drivers/ata/pata_cmd64x.c    |    6 +++---
+ drivers/ata/pata_cs5536.c    |   32 +++++++++++++++++++++++++++++++-
+ drivers/ata/pata_rdc.c       |    3 ---
+ drivers/ata/sata_highbank.c  |    2 +-
+ drivers/ata/sata_inic162x.c  |    2 --
+ drivers/ata/sata_promise.c   |   15 +++++++++++++--
+ drivers/ata/sata_sil24.c     |    4 ----
+ drivers/ata/sata_sx4.c       |   14 ++++++--------
+ 10 files changed, 81 insertions(+), 29 deletions(-)
+Merging infiniband/for-next (d0951d2 Merge branches 'cxgb4', 'misc', 'mlx4', 'nes' and 'uapi' into for-next)
+$ git merge infiniband/for-next
+Merge made by the 'recursive' strategy.
+ drivers/infiniband/hw/amso1100/c2_ae.c         |    1 +
+ drivers/infiniband/hw/cxgb3/iwch_cm.c          |    6 ++--
+ drivers/infiniband/hw/cxgb4/cm.c               |    6 ++--
+ drivers/infiniband/hw/ipath/ipath_init_chip.c  |   10 ------
+ drivers/infiniband/hw/mlx4/cq.c                |   34 ++++++++++++++-----
+ drivers/infiniband/hw/mlx4/main.c              |   27 ++++++++++++---
+ drivers/infiniband/hw/mlx4/mlx4_ib.h           |    1 +
+ drivers/infiniband/hw/mlx4/user.h              |   12 ++++++-
+ drivers/infiniband/hw/nes/nes_cm.c             |    8 ++---
+ drivers/infiniband/hw/nes/nes_mgt.c            |   42 +++++++++++-------------
+ drivers/infiniband/hw/nes/nes_nic.c            |   13 ++++----
+ drivers/net/ethernet/mellanox/mlx4/cmd.c       |    2 +-
+ drivers/net/ethernet/mellanox/mlx4/en_cq.c     |    2 +-
+ drivers/net/ethernet/mellanox/mlx4/en_netdev.c |    1 +
+ drivers/net/ethernet/mellanox/mlx4/en_rx.c     |    5 +--
+ drivers/net/ethernet/mellanox/mlx4/en_tx.c     |    5 +--
+ drivers/net/ethernet/mellanox/mlx4/eq.c        |   26 ++++++++++-----
+ drivers/net/ethernet/mellanox/mlx4/fw.c        |   30 ++++++++++++++++-
+ drivers/net/ethernet/mellanox/mlx4/fw.h        |    1 +
+ drivers/net/ethernet/mellanox/mlx4/main.c      |   38 ++++++++++++++++++++-
+ drivers/net/ethernet/mellanox/mlx4/mlx4_en.h   |    1 +
+ include/linux/mlx4/device.h                    |   21 ++++++++++++
+ include/rdma/Kbuild                            |    6 ----
+ include/rdma/rdma_netlink.h                    |   36 +-------------------
+ include/uapi/rdma/Kbuild                       |    6 ++++
+ include/{ => uapi}/rdma/ib_user_cm.h           |    0
+ include/{ => uapi}/rdma/ib_user_mad.h          |    0
+ include/{ => uapi}/rdma/ib_user_sa.h           |    0
+ include/{ => uapi}/rdma/ib_user_verbs.h        |    0
+ include/uapi/rdma/rdma_netlink.h               |   37 +++++++++++++++++++++
+ include/{ => uapi}/rdma/rdma_user_cm.h         |    0
+ 31 files changed, 254 insertions(+), 123 deletions(-)
+ rename include/{ => uapi}/rdma/ib_user_cm.h (100%)
+ rename include/{ => uapi}/rdma/ib_user_mad.h (100%)
+ rename include/{ => uapi}/rdma/ib_user_sa.h (100%)
+ rename include/{ => uapi}/rdma/ib_user_verbs.h (100%)
+ create mode 100644 include/uapi/rdma/rdma_netlink.h
+ rename include/{ => uapi}/rdma/rdma_user_cm.h (100%)
+Merging pstore/master (b042e47 pstore/ram: Fix undefined usage of rounddown_pow_of_two(0))
+$ git merge pstore/master
+Auto-merging fs/pstore/ram.c
+Merge made by the 'recursive' strategy.
+ fs/pstore/ram.c |   24 +++++++++++++++---------
+ 1 file changed, 15 insertions(+), 9 deletions(-)
+Merging acpi/next (32cc109 tools/power turbostat: v3.0: monitor Watts and Temperature)
+$ git merge acpi/next
+Merge made by the 'recursive' strategy.
+ arch/x86/include/asm/msr-index.h                |   37 ++
+ tools/power/x86/turbostat/Makefile              |    7 +-
+ tools/power/x86/turbostat/turbostat.8           |  103 ++--
+ tools/power/x86/turbostat/turbostat.c           |  676 +++++++++++++++++++++--
+ tools/power/x86/x86_energy_perf_policy/Makefile |    6 +-
+ 5 files changed, 751 insertions(+), 78 deletions(-)
+Merging cpuidle/cpuidle-next (3cf7997 acpi: intel_idle : break dependency between modules)
+$ git merge cpuidle/cpuidle-next
+Resolved 'drivers/cpuidle/coupled.c' using previous resolution.
+Resolved 'include/linux/cpuidle.h' using previous resolution.
+Auto-merging include/linux/cpuidle.h
+CONFLICT (content): Merge conflict in include/linux/cpuidle.h
+Auto-merging drivers/cpuidle/coupled.c
+CONFLICT (add/add): Merge conflict in drivers/cpuidle/coupled.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 9073c7e] Merge remote-tracking branch 'cpuidle/cpuidle-next'
+$ git diff -M --stat --summary HEAD^..
+Merging cpupowerutils/master (f166033 cpupower tools: add install target to the debug tools' makefiles)
+$ git merge cpupowerutils/master
+Already up-to-date.
+Merging thermal/next (d12250e thermal: rcar: add rcar_zone_to_priv() macro)
+$ git merge thermal/next
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/thermal/db8500-thermal.txt |   44 ++
+ Documentation/thermal/sysfs-api.txt                |   64 ++
+ arch/arm/boot/dts/dbx5x0.dtsi                      |   14 +
+ arch/arm/boot/dts/snowball.dts                     |   31 +
+ arch/arm/configs/u8500_defconfig                   |    2 +
+ arch/arm/mach-ux500/board-mop500.c                 |   64 ++
+ drivers/acpi/thermal.c                             |    6 +-
+ drivers/platform/x86/acerhdf.c                     |    2 +-
+ drivers/platform/x86/intel_mid_thermal.c           |    2 +-
+ drivers/power/power_supply_core.c                  |    2 +-
+ drivers/staging/omap-thermal/omap-thermal-common.c |    2 +-
+ drivers/thermal/Kconfig                            |   82 ++-
+ drivers/thermal/Makefile                           |   17 +-
+ drivers/thermal/cpu_cooling.c                      |  107 +--
+ drivers/thermal/db8500_cpufreq_cooling.c           |  108 +++
+ drivers/thermal/db8500_thermal.c                   |  531 +++++++++++++++
+ drivers/thermal/exynos_thermal.c                   |    2 +-
+ drivers/thermal/fair_share.c                       |  133 ++++
+ drivers/thermal/rcar_thermal.c                     |   27 +-
+ drivers/thermal/spear_thermal.c                    |    2 +-
+ drivers/thermal/step_wise.c                        |  194 ++++++
+ drivers/thermal/thermal_core.h                     |   53 ++
+ drivers/thermal/thermal_sys.c                      |  700 +++++++++++++-------
+ drivers/thermal/user_space.c                       |   68 ++
+ include/linux/cpu_cooling.h                        |    6 +-
+ include/linux/platform_data/db8500_thermal.h       |   38 ++
+ include/linux/thermal.h                            |  128 +++-
+ 27 files changed, 2031 insertions(+), 398 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/thermal/db8500-thermal.txt
+ create mode 100644 drivers/thermal/db8500_cpufreq_cooling.c
+ create mode 100644 drivers/thermal/db8500_thermal.c
+ create mode 100644 drivers/thermal/fair_share.c
+ create mode 100644 drivers/thermal/step_wise.c
+ create mode 100644 drivers/thermal/thermal_core.h
+ create mode 100644 drivers/thermal/user_space.c
+ create mode 100644 include/linux/platform_data/db8500_thermal.h
+Merging ieee1394/for-next (790198f firewire: cdev: fix user memory corruption (i386 userland on amd64 kernel))
+$ git merge ieee1394/for-next
+Already up-to-date.
+Merging ubi/linux-next (6a059ab UBI: use list_move_tail instead of list_del/list_add_tail)
+$ git merge ubi/linux-next
+Merge made by the 'recursive' strategy.
+ drivers/mtd/ubi/fastmap.c |    6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+Merging dlm/next (da8c666 dlm: fix lvb invalidation conditions)
+$ git merge dlm/next
+Merge made by the 'recursive' strategy.
+ fs/dlm/Kconfig        |    2 +-
+ fs/dlm/dlm_internal.h |    1 +
+ fs/dlm/lock.c         |   16 +++++++++++++---
+ fs/dlm/lowcomms.c     |    5 ++---
+ fs/dlm/recover.c      |   37 ++++++++++++++++++++++++++++++-------
+ 5 files changed, 47 insertions(+), 14 deletions(-)
+Merging swiotlb/linux-next (af51a9f swiotlb: Do not export swiotlb_bounce since there are no external consumers)
+$ git merge swiotlb/linux-next
+Merge made by the 'recursive' strategy.
+ drivers/xen/swiotlb-xen.c |   25 ++---
+ include/linux/swiotlb.h   |   20 ++--
+ lib/swiotlb.c             |  269 +++++++++++++++++++++++----------------------
+ 3 files changed, 163 insertions(+), 151 deletions(-)
+Merging scsi/for-next (a3667aa [SCSI] csiostor: Chelsio FCoE offload driver)
+$ git merge scsi/for-next
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/scsi/hptiop.txt                   |   69 +-
+ MAINTAINERS                                     |    5 +-
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c |   10 +-
+ drivers/net/ethernet/chelsio/cxgb4/sge.c        |    6 +-
+ drivers/net/ethernet/chelsio/cxgb4/t4_hw.c      |   20 +-
+ drivers/net/ethernet/chelsio/cxgb4/t4_msg.h     |    1 +
+ drivers/net/ethernet/chelsio/cxgb4/t4_regs.h    |   36 +-
+ drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h   |   41 +-
+ drivers/net/ethernet/chelsio/cxgb4vf/sge.c      |    8 +-
+ drivers/scsi/Kconfig                            |    1 +
+ drivers/scsi/Makefile                           |    1 +
+ drivers/scsi/aacraid/aachba.c                   |   87 +-
+ drivers/scsi/aacraid/aacraid.h                  |    2 +-
+ drivers/scsi/be2iscsi/be.h                      |    7 +-
+ drivers/scsi/be2iscsi/be_cmds.c                 |  236 +-
+ drivers/scsi/be2iscsi/be_cmds.h                 |   93 +-
+ drivers/scsi/be2iscsi/be_iscsi.c                |  124 +-
+ drivers/scsi/be2iscsi/be_iscsi.h                |    2 +-
+ drivers/scsi/be2iscsi/be_main.c                 | 1059 ++++--
+ drivers/scsi/be2iscsi/be_main.h                 |  152 +-
+ drivers/scsi/be2iscsi/be_mgmt.c                 |  424 ++-
+ drivers/scsi/be2iscsi/be_mgmt.h                 |   23 +-
+ drivers/scsi/bnx2i/bnx2i.h                      |    2 +-
+ drivers/scsi/bnx2i/bnx2i_init.c                 |   43 +-
+ drivers/scsi/bnx2i/bnx2i_iscsi.c                |    2 +-
+ drivers/scsi/csiostor/Kconfig                   |   19 +
+ drivers/scsi/csiostor/Makefile                  |   11 +
+ drivers/scsi/csiostor/csio_attr.c               |  796 ++++
+ drivers/scsi/csiostor/csio_defs.h               |  121 +
+ drivers/scsi/csiostor/csio_hw.c                 | 4395 +++++++++++++++++++++++
+ drivers/scsi/csiostor/csio_hw.h                 |  667 ++++
+ drivers/scsi/csiostor/csio_init.c               | 1274 +++++++
+ drivers/scsi/csiostor/csio_init.h               |  158 +
+ drivers/scsi/csiostor/csio_isr.c                |  624 ++++
+ drivers/scsi/csiostor/csio_lnode.c              | 2133 +++++++++++
+ drivers/scsi/csiostor/csio_lnode.h              |  255 ++
+ drivers/scsi/csiostor/csio_mb.c                 | 1770 +++++++++
+ drivers/scsi/csiostor/csio_mb.h                 |  278 ++
+ drivers/scsi/csiostor/csio_rnode.c              |  912 +++++
+ drivers/scsi/csiostor/csio_rnode.h              |  141 +
+ drivers/scsi/csiostor/csio_scsi.c               | 2555 +++++++++++++
+ drivers/scsi/csiostor/csio_scsi.h               |  342 ++
+ drivers/scsi/csiostor/csio_wr.c                 | 1632 +++++++++
+ drivers/scsi/csiostor/csio_wr.h                 |  512 +++
+ drivers/scsi/csiostor/t4fw_api_stor.h           |  578 +++
+ drivers/scsi/hptiop.c                           |  413 ++-
+ drivers/scsi/hptiop.h                           |   72 +-
+ drivers/scsi/lpfc/lpfc.h                        |    2 +
+ drivers/scsi/lpfc/lpfc_attr.c                   |   85 +
+ drivers/scsi/lpfc/lpfc_crtn.h                   |    1 +
+ drivers/scsi/lpfc/lpfc_ct.c                     |    2 +-
+ drivers/scsi/lpfc/lpfc_els.c                    |    8 +-
+ drivers/scsi/lpfc/lpfc_hw4.h                    |    3 +
+ drivers/scsi/lpfc/lpfc_init.c                   |   57 +-
+ drivers/scsi/lpfc/lpfc_scsi.c                   |   19 +-
+ drivers/scsi/lpfc/lpfc_sli.c                    |   16 +-
+ drivers/scsi/lpfc/lpfc_sli.h                    |    4 +-
+ drivers/scsi/lpfc/lpfc_sli4.h                   |    3 +
+ drivers/scsi/lpfc/lpfc_version.h                |    2 +-
+ drivers/scsi/osd/osd_uld.c                      |   28 +
+ drivers/scsi/sd.c                               |   17 +-
+ drivers/scsi/virtio_scsi.c                      |    2 +
+ include/scsi/scsi_device.h                      |    1 +
+ 63 files changed, 21648 insertions(+), 714 deletions(-)
+ create mode 100644 drivers/scsi/csiostor/Kconfig
+ create mode 100644 drivers/scsi/csiostor/Makefile
+ create mode 100644 drivers/scsi/csiostor/csio_attr.c
+ create mode 100644 drivers/scsi/csiostor/csio_defs.h
+ create mode 100644 drivers/scsi/csiostor/csio_hw.c
+ create mode 100644 drivers/scsi/csiostor/csio_hw.h
+ create mode 100644 drivers/scsi/csiostor/csio_init.c
+ create mode 100644 drivers/scsi/csiostor/csio_init.h
+ create mode 100644 drivers/scsi/csiostor/csio_isr.c
+ create mode 100644 drivers/scsi/csiostor/csio_lnode.c
+ create mode 100644 drivers/scsi/csiostor/csio_lnode.h
+ create mode 100644 drivers/scsi/csiostor/csio_mb.c
+ create mode 100644 drivers/scsi/csiostor/csio_mb.h
+ create mode 100644 drivers/scsi/csiostor/csio_rnode.c
+ create mode 100644 drivers/scsi/csiostor/csio_rnode.h
+ create mode 100644 drivers/scsi/csiostor/csio_scsi.c
+ create mode 100644 drivers/scsi/csiostor/csio_scsi.h
+ create mode 100644 drivers/scsi/csiostor/csio_wr.c
+ create mode 100644 drivers/scsi/csiostor/csio_wr.h
+ create mode 100644 drivers/scsi/csiostor/t4fw_api_stor.h
+Merging target-updates/for-next (3e4f574 ib_srpt: Convert TMR path to target_submit_tmr)
+$ git merge target-updates/for-next
+Merge made by the 'recursive' strategy.
+ drivers/infiniband/ulp/srpt/ib_srpt.c        |  178 ++--
+ drivers/infiniband/ulp/srpt/ib_srpt.h        |    1 -
+ drivers/scsi/qla2xxx/qla_target.c            |   21 +-
+ drivers/scsi/qla2xxx/tcm_qla2xxx.c           |    4 +-
+ drivers/target/iscsi/iscsi_target.c          |   84 +-
+ drivers/target/iscsi/iscsi_target_configfs.c |    4 +-
+ drivers/target/iscsi/iscsi_target_core.h     |    2 +-
+ drivers/target/iscsi/iscsi_target_erl1.c     |   11 +-
+ drivers/target/iscsi/iscsi_target_erl2.c     |    2 +-
+ drivers/target/iscsi/iscsi_target_login.c    |   18 +-
+ drivers/target/iscsi/iscsi_target_nego.c     |   10 +-
+ drivers/target/iscsi/iscsi_target_tmr.c      |    4 +-
+ drivers/target/iscsi/iscsi_target_tq.c       |    3 +-
+ drivers/target/iscsi/iscsi_target_util.c     |    8 +-
+ drivers/target/loopback/tcm_loop.h           |    1 -
+ drivers/target/sbp/Kconfig                   |    2 +-
+ drivers/target/target_core_alua.c            |  346 +++-----
+ drivers/target/target_core_alua.h            |    9 +-
+ drivers/target/target_core_configfs.c        |  705 +++++----------
+ drivers/target/target_core_device.c          |  709 +++++++--------
+ drivers/target/target_core_fabric_configfs.c |   25 +-
+ drivers/target/target_core_fabric_lib.c      |    3 +-
+ drivers/target/target_core_file.c            |  190 ++--
+ drivers/target/target_core_file.h            |    2 +
+ drivers/target/target_core_hba.c             |    9 +-
+ drivers/target/target_core_iblock.c          |  501 ++++++-----
+ drivers/target/target_core_iblock.h          |    1 +
+ drivers/target/target_core_internal.h        |   16 +-
+ drivers/target/target_core_pr.c              | 1225 +++++++++++---------------
+ drivers/target/target_core_pr.h              |   10 +-
+ drivers/target/target_core_pscsi.c           |  349 +++-----
+ drivers/target/target_core_pscsi.h           |    2 +-
+ drivers/target/target_core_rd.c              |  126 +--
+ drivers/target/target_core_rd.h              |    1 +
+ drivers/target/target_core_sbc.c             |  185 ++--
+ drivers/target/target_core_spc.c             |  572 ++++++++----
+ drivers/target/target_core_stat.c            |  312 ++-----
+ drivers/target/target_core_tmr.c             |    9 +-
+ drivers/target/target_core_tpg.c             |    5 +-
+ drivers/target/target_core_transport.c       |  673 ++++----------
+ drivers/target/target_core_ua.c              |   20 +-
+ drivers/target/target_core_ua.h              |    2 +-
+ drivers/vhost/tcm_vhost.c                    |    4 -
+ include/target/target_core_backend.h         |   49 +-
+ include/target/target_core_base.h            |  206 ++---
+ include/target/target_core_fabric.h          |   13 +-
+ 46 files changed, 2724 insertions(+), 3908 deletions(-)
+Merging target-merge/for-next-merge (6f0c058 Linux 3.7-rc2)
+$ git merge target-merge/for-next-merge
+Already up-to-date.
+Merging ibft/linux-next (935a9fe ibft: Fix finding IBFT ACPI table on UEFI)
+$ git merge ibft/linux-next
+Already up-to-date.
+Merging isci/all (6734092 isci: add a couple __iomem annotations)
+$ git merge isci/all
+Already up-to-date.
+Merging slave-dma/next (f9744dd Merge branch 'topic/dmaengine_dt' into next)
+$ git merge slave-dma/next
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/dma/dma.txt      |   81 ++++++
+ Documentation/devicetree/bindings/dma/snps-dma.txt |   44 ++++
+ arch/arm/boot/dts/spear1340.dtsi                   |   19 ++
+ arch/arm/boot/dts/spear13xx.dtsi                   |   38 +++
+ arch/arm/mach-spear13xx/include/mach/spear.h       |    2 -
+ arch/arm/mach-spear13xx/spear1310.c                |    4 +-
+ arch/arm/mach-spear13xx/spear1340.c                |   27 +-
+ arch/arm/mach-spear13xx/spear13xx.c                |   54 +---
+ crypto/async_tx/async_xor.c                        |    4 +-
+ drivers/dma/Kconfig                                |    3 +-
+ drivers/dma/amba-pl08x.c                           |    8 +-
+ drivers/dma/at_hdmac_regs.h                        |    8 +-
+ drivers/dma/dmaengine.c                            |   16 ++
+ drivers/dma/dmatest.c                              |   16 +-
+ drivers/dma/dw_dmac.c                              |  167 +++++++++++--
+ drivers/dma/dw_dmac_regs.h                         |    6 +
+ drivers/dma/iop-adma.c                             |   45 ++--
+ drivers/dma/mv_xor.c                               |   62 ++---
+ drivers/dma/pch_dma.c                              |   13 +-
+ drivers/of/Makefile                                |    2 +-
+ drivers/of/dma.c                                   |  264 ++++++++++++++++++++
+ include/linux/dmaengine.h                          |   24 +-
+ include/linux/dw_dmac.h                            |   45 ++--
+ include/linux/of_dma.h                             |   73 ++++++
+ 24 files changed, 803 insertions(+), 222 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/dma/dma.txt
+ create mode 100644 drivers/of/dma.c
+ create mode 100644 include/linux/of_dma.h
+Merging dmaengine/next (a2bd114 netdma: adding alignment check for NETDMA ops)
+$ git merge dmaengine/next
+Already up-to-date.
+Merging net-next/master (f4e0b4c ip6tnl/sit: drop packet if ECN present with not-ECT)
+$ git merge net-next/master
+Resolved 'drivers/net/ethernet/mellanox/mlx4/en_rx.c' using previous resolution.
+Auto-merging net/sctp/socket.c
+Auto-merging net/mac80211/offchannel.c
+Auto-merging net/ipv4/ipmr.c
+Removing kernel/time/timecompare.c
+Auto-merging include/uapi/linux/hdlc/ioctl.h
+Removing include/linux/timecompare.h
+Auto-merging include/linux/pci.h
+Auto-merging include/linux/bcma/bcma_driver_chipcommon.h
+Auto-merging drivers/vhost/vhost.c
+Auto-merging drivers/vhost/tcm_vhost.c
+Auto-merging drivers/nfc/pn544/pn544.c
+Removing drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h
+Removing drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c
+Auto-merging drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+Auto-merging drivers/net/ethernet/mellanox/mlx4/en_rx.c
+CONFLICT (content): Merge conflict in drivers/net/ethernet/mellanox/mlx4/en_rx.c
+Auto-merging drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+Removing drivers/net/ethernet/cadence/at91_ether.h
+Auto-merging drivers/bcma/main.c
+Auto-merging drivers/bcma/driver_chipcommon.c
+Auto-merging arch/powerpc/include/asm/ppc-opcode.h
+CONFLICT (modify/delete): arch/m68k/include/uapi/asm/socket.h deleted in HEAD and modified in net-next/master. Version net-next/master of arch/m68k/include/uapi/asm/socket.h left in tree.
+Auto-merging arch/cris/include/uapi/asm/socket.h
+Removing arch/arm/mach-at91/include/mach/at91rm9200_emac.h
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git rm -f arch/m68k/include/uapi/asm/socket.h
+arch/m68k/include/uapi/asm/socket.h: needs merge
+rm 'arch/m68k/include/uapi/asm/socket.h'
+$ git commit -v -a
+[master 790776b5] Merge remote-tracking branch 'net-next/master'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/ABI/testing/sysfs-bus-mdio           |    9 +
+ .../ABI/testing/sysfs-class-net-batman-adv         |   11 +-
+ Documentation/ABI/testing/sysfs-class-net-grcan    |   35 +
+ Documentation/ABI/testing/sysfs-class-net-mesh     |   40 +-
+ .../devicetree/bindings/net/can/grcan.txt          |   28 +
+ .../devicetree/bindings/net/cdns-emac.txt          |   23 +
+ Documentation/devicetree/bindings/net/cpsw.txt     |   48 +-
+ Documentation/kernel-parameters.txt                |   18 +
+ Documentation/networking/batman-adv.txt            |    3 +-
+ Documentation/networking/ip-sysctl.txt             |   14 +
+ Documentation/networking/packet_mmap.txt           |  246 ++-
+ Documentation/networking/stmmac.txt                |   28 +-
+ MAINTAINERS                                        |   12 +-
+ arch/alpha/include/asm/socket.h                    |    1 +
+ arch/arm/boot/dts/am335x-bone.dts                  |    8 +
+ arch/arm/boot/dts/am335x-evm.dts                   |    8 +
+ arch/arm/boot/dts/am33xx.dtsi                      |   48 +
+ arch/arm/boot/dts/imx6q.dtsi                       |    5 +-
+ arch/arm/configs/omap2plus_defconfig               |    3 +
+ arch/arm/mach-at91/Kconfig                         |    4 -
+ arch/arm/mach-at91/board-csb337.c                  |    2 +
+ arch/arm/mach-at91/include/mach/at91rm9200_emac.h  |  138 --
+ arch/arm/mach-imx/mach-imx6q.c                     |   12 +
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c         |   31 +
+ arch/arm/net/bpf_jit_32.c                          |   29 +-
+ arch/arm/net/bpf_jit_32.h                          |    2 +
+ arch/avr32/Kconfig                                 |    1 -
+ arch/avr32/include/uapi/asm/socket.h               |    1 +
+ arch/cris/include/uapi/asm/socket.h                |    1 +
+ arch/frv/include/uapi/asm/socket.h                 |    1 +
+ arch/h8300/include/asm/socket.h                    |    1 +
+ arch/ia64/include/uapi/asm/socket.h                |    1 +
+ arch/m32r/include/asm/socket.h                     |    1 +
+ arch/mips/bcm47xx/nvram.c                          |    4 +-
+ arch/mips/bcm47xx/wgt634u.c                        |    8 +-
+ arch/mips/include/uapi/asm/socket.h                |    1 +
+ arch/mn10300/include/uapi/asm/socket.h             |    1 +
+ arch/parisc/include/uapi/asm/socket.h              |    1 +
+ arch/powerpc/include/asm/ppc-opcode.h              |    3 +
+ arch/powerpc/include/uapi/asm/socket.h             |    1 +
+ arch/powerpc/net/bpf_jit.h                         |    6 +
+ arch/powerpc/net/bpf_jit_comp.c                    |   25 +
+ arch/s390/include/uapi/asm/socket.h                |    1 +
+ arch/sparc/include/uapi/asm/socket.h               |    1 +
+ arch/sparc/net/bpf_jit_comp.c                      |   19 +
+ arch/x86/net/bpf_jit_comp.c                        |   21 +
+ arch/xtensa/include/uapi/asm/socket.h              |    1 +
+ drivers/bcma/driver_chipcommon.c                   |   23 +-
+ drivers/bcma/driver_chipcommon_nflash.c            |    3 +
+ drivers/bcma/driver_chipcommon_pmu.c               |    5 +-
+ drivers/bcma/driver_chipcommon_sflash.c            |   35 +-
+ drivers/bcma/driver_mips.c                         |   48 +-
+ drivers/bcma/driver_pci_host.c                     |   14 +-
+ drivers/bcma/host_pci.c                            |    6 +-
+ drivers/bcma/main.c                                |   54 +-
+ drivers/bcma/sprom.c                               |    5 +-
+ drivers/bluetooth/btmrvl_sdio.c                    |   28 +-
+ drivers/dma/ioat/dca.c                             |   23 +
+ drivers/isdn/hardware/mISDN/hfcpci.c               |    2 +-
+ drivers/isdn/hardware/mISDN/mISDNisar.c            |    2 +-
+ drivers/isdn/hisax/callc.c                         |    2 +-
+ drivers/isdn/hisax/hfc_pci.c                       |    2 +-
+ drivers/isdn/hisax/hfc_sx.c                        |    2 +-
+ drivers/isdn/mISDN/l1oip_core.c                    |    5 +-
+ drivers/isdn/pcbit/layer2.c                        |    2 +-
+ drivers/net/bonding/bond_main.c                    |    2 +-
+ drivers/net/can/Kconfig                            |    9 +
+ drivers/net/can/Makefile                           |    1 +
+ drivers/net/can/at91_can.c                         |    1 +
+ drivers/net/can/bfin_can.c                         |    1 +
+ drivers/net/can/c_can/c_can.c                      |   12 +
+ drivers/net/can/c_can/c_can.h                      |    3 +
+ drivers/net/can/c_can/c_can_platform.c             |   30 +-
+ drivers/net/can/cc770/cc770_platform.c             |    2 +
+ drivers/net/can/flexcan.c                          |    2 +
+ drivers/net/can/grcan.c                            | 1756 +++++++++++++++
+ drivers/net/can/janz-ican3.c                       |    4 +-
+ drivers/net/can/mscan/mpc5xxx_can.c                |    1 +
+ drivers/net/can/sja1000/Kconfig                    |    3 +-
+ drivers/net/can/sja1000/plx_pci.c                  |   19 +
+ drivers/net/can/sja1000/sja1000_of_platform.c      |    6 +-
+ drivers/net/can/sja1000/sja1000_platform.c         |    1 +
+ drivers/net/can/ti_hecc.c                          |    1 +
+ drivers/net/can/usb/Kconfig                        |   29 +
+ drivers/net/can/usb/Makefile                       |    1 +
+ drivers/net/can/usb/esd_usb2.c                     |   35 +-
+ drivers/net/can/usb/kvaser_usb.c                   | 1627 ++++++++++++++
+ drivers/net/dsa/Kconfig                            |    5 +-
+ drivers/net/ethernet/8390/etherh.c                 |    6 -
+ drivers/net/ethernet/adi/Kconfig                   |    2 +-
+ drivers/net/ethernet/adi/bfin_mac.c                |  259 ++-
+ drivers/net/ethernet/adi/bfin_mac.h                |   13 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x.h        |  134 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c    |  469 ++--
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h    |   87 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c    |    8 +-
+ .../net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c    |   11 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h    |   34 +-
+ .../net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h   |   29 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c   |  985 ++++++---
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h   |   17 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c   |  871 +++++---
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h    |   45 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c     |   59 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h     |   12 +
+ drivers/net/ethernet/broadcom/tg3.c                |  276 ++-
+ drivers/net/ethernet/broadcom/tg3.h                |    8 +
+ drivers/net/ethernet/cadence/Kconfig               |    9 +-
+ drivers/net/ethernet/cadence/at91_ether.c          | 1279 +++--------
+ drivers/net/ethernet/cadence/at91_ether.h          |  112 -
+ drivers/net/ethernet/cadence/macb.c                |  556 +++--
+ drivers/net/ethernet/cadence/macb.h                |   67 +-
+ drivers/net/ethernet/calxeda/xgmac.c               |   59 +-
+ drivers/net/ethernet/chelsio/Kconfig               |    4 +-
+ drivers/net/ethernet/chelsio/cxgb3/common.h        |    7 +-
+ drivers/net/ethernet/cisco/Kconfig                 |    2 +-
+ drivers/net/ethernet/cisco/enic/Kconfig            |    2 +-
+ drivers/net/ethernet/dec/ewrk3.c                   |    3 +-
+ drivers/net/ethernet/dlink/dl2k.c                  |   16 +-
+ drivers/net/ethernet/dnet.c                        |    3 -
+ drivers/net/ethernet/emulex/Kconfig                |    2 +-
+ drivers/net/ethernet/emulex/benet/Kconfig          |    2 +-
+ drivers/net/ethernet/emulex/benet/be.h             |   51 +-
+ drivers/net/ethernet/emulex/benet/be_cmds.c        |  409 +++-
+ drivers/net/ethernet/emulex/benet/be_cmds.h        |  177 +-
+ drivers/net/ethernet/emulex/benet/be_ethtool.c     |   80 +-
+ drivers/net/ethernet/emulex/benet/be_hw.h          |   20 +-
+ drivers/net/ethernet/emulex/benet/be_main.c        |  844 ++++---
+ drivers/net/ethernet/emulex/benet/be_roce.c        |    5 +-
+ drivers/net/ethernet/freescale/Kconfig             |    9 +
+ drivers/net/ethernet/freescale/Makefile            |    1 +
+ drivers/net/ethernet/freescale/fec.c               |  161 +-
+ drivers/net/ethernet/freescale/fec.h               |  119 +
+ drivers/net/ethernet/freescale/fec_ptp.c           |  383 ++++
+ drivers/net/ethernet/freescale/gianfar.c           |   14 +-
+ drivers/net/ethernet/i825xx/ether1.c               |    6 -
+ drivers/net/ethernet/ibm/Kconfig                   |    5 +-
+ drivers/net/ethernet/ibm/ehea/ehea_main.c          |    2 +-
+ drivers/net/ethernet/ibm/emac/mal.c                |    6 +-
+ drivers/net/ethernet/intel/Kconfig                 |   30 +-
+ drivers/net/ethernet/intel/e1000/e1000_hw.c        |   17 +-
+ drivers/net/ethernet/intel/e1000e/netdev.c         |   11 +
+ drivers/net/ethernet/intel/igb/Makefile            |    4 +-
+ drivers/net/ethernet/intel/igb/e1000_82575.c       |   28 +-
+ drivers/net/ethernet/intel/igb/e1000_82575.h       |    3 +
+ drivers/net/ethernet/intel/igb/e1000_defines.h     |   15 +
+ drivers/net/ethernet/intel/igb/e1000_i210.c        |   94 +
+ drivers/net/ethernet/intel/igb/e1000_i210.h        |   11 +
+ drivers/net/ethernet/intel/igb/e1000_mac.c         |    4 +
+ drivers/net/ethernet/intel/igb/e1000_mac.h         |    1 +
+ drivers/net/ethernet/intel/igb/e1000_nvm.c         |   71 +
+ drivers/net/ethernet/intel/igb/e1000_nvm.h         |   16 +
+ drivers/net/ethernet/intel/igb/e1000_phy.c         |   49 +-
+ drivers/net/ethernet/intel/igb/e1000_phy.h         |    1 +
+ drivers/net/ethernet/intel/igb/igb.h               |  110 +-
+ drivers/net/ethernet/intel/igb/igb_ethtool.c       |  392 +++-
+ drivers/net/ethernet/intel/igb/igb_main.c          | 1512 ++++++++-----
+ drivers/net/ethernet/intel/igb/igb_ptp.c           |  102 +-
+ drivers/net/ethernet/intel/igbvf/defines.h         |    1 +
+ drivers/net/ethernet/intel/igbvf/igbvf.h           |    2 +-
+ drivers/net/ethernet/intel/igbvf/netdev.c          |   30 +-
+ drivers/net/ethernet/intel/ixgbe/Makefile          |    3 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe.h           |   15 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c     |  158 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_common.c    |   76 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_common.h    |    2 +
+ drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c   |   32 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c   |  109 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c      |    4 +
+ drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c       |   22 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_main.c      |  393 ++--
+ drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h       |   31 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c       |  164 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c     |  470 ++--
+ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h      |    1 +
+ drivers/net/ethernet/intel/ixgbevf/defines.h       |    7 +-
+ drivers/net/ethernet/intel/ixgbevf/ixgbevf.h       |   16 +-
+ drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c  |  394 ++--
+ drivers/net/ethernet/intel/ixgbevf/mbx.h           |   10 +
+ drivers/net/ethernet/intel/ixgbevf/vf.c            |   61 +
+ drivers/net/ethernet/intel/ixgbevf/vf.h            |    2 +
+ drivers/net/ethernet/marvell/pxa168_eth.c          |    7 +-
+ drivers/net/ethernet/mellanox/Kconfig              |    2 +-
+ drivers/net/ethernet/mellanox/mlx4/Kconfig         |    3 +-
+ drivers/net/ethernet/mellanox/mlx4/en_netdev.c     |    2 +-
+ drivers/net/ethernet/mellanox/mlx4/en_rx.c         |    9 +-
+ drivers/net/ethernet/mellanox/mlx4/mlx4_en.h       |   19 +-
+ drivers/net/ethernet/micrel/ks8695net.c            |    3 -
+ drivers/net/ethernet/micrel/ksz884x.c              |   13 +-
+ drivers/net/ethernet/neterion/Kconfig              |    2 +-
+ drivers/net/ethernet/neterion/s2io.c               |    3 +-
+ drivers/net/ethernet/nxp/lpc_eth.c                 |    4 +-
+ drivers/net/ethernet/oki-semi/pch_gbe/Kconfig      |   17 +-
+ drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h    |    2 -
+ .../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c   |   14 -
+ .../ethernet/qlogic/netxen/netxen_nic_ethtool.c    |   93 +-
+ drivers/net/ethernet/qlogic/qla3xxx.c              |   16 +-
+ drivers/net/ethernet/qlogic/qlcnic/Makefile        |    3 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic.h        |  416 ++--
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c    |   48 +-
+ .../net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c    |    3 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h    |   16 -
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c     |  472 +---
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c   |  826 +------
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c     | 1309 +++++++++++
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c   | 1663 +-------------
+ .../net/ethernet/qlogic/qlcnic/qlcnic_minidump.c   |  629 ++++++
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c  |  962 ++++++++
+ drivers/net/ethernet/qlogic/qlge/qlge_dbg.c        |   16 +-
+ drivers/net/ethernet/realtek/8139cp.c              |   52 +-
+ drivers/net/ethernet/realtek/atp.c                 |   58 +-
+ drivers/net/ethernet/realtek/atp.h                 |    2 -
+ drivers/net/ethernet/realtek/r8169.c               |  110 +-
+ drivers/net/ethernet/renesas/sh_eth.c              |    2 +-
+ drivers/net/ethernet/seeq/ether3.c                 |    6 -
+ drivers/net/ethernet/sfc/Kconfig                   |   10 +-
+ drivers/net/ethernet/sfc/Makefile                  |    3 +-
+ drivers/net/ethernet/sfc/net_driver.h              |    2 -
+ drivers/net/ethernet/sfc/nic.h                     |   26 -
+ drivers/net/ethernet/smsc/smc911x.c                |   10 -
+ drivers/net/ethernet/smsc/smc91x.c                 |   10 -
+ drivers/net/ethernet/smsc/smsc911x.c               |    5 -
+ drivers/net/ethernet/stmicro/stmmac/Kconfig        |   25 -
+ drivers/net/ethernet/stmicro/stmmac/Makefile       |    1 -
+ drivers/net/ethernet/stmicro/stmmac/common.h       |   39 +-
+ drivers/net/ethernet/stmicro/stmmac/dwmac1000.h    |    3 -
+ .../net/ethernet/stmicro/stmmac/dwmac1000_dma.c    |    6 +
+ drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h    |    5 +-
+ drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c    |   20 +-
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h       |   14 +-
+ .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c   |  100 +-
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  261 +--
+ drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c |  134 --
+ drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h |   46 -
+ drivers/net/ethernet/ti/Kconfig                    |    9 +
+ drivers/net/ethernet/ti/Makefile                   |    2 +-
+ drivers/net/ethernet/ti/cpsw.c                     |  630 ++++--
+ drivers/net/ethernet/ti/cpsw_ale.c                 |   31 +-
+ drivers/net/ethernet/ti/cpsw_ale.h                 |    1 +
+ drivers/net/ethernet/ti/cpts.c                     |  427 ++++
+ drivers/net/ethernet/ti/cpts.h                     |  146 ++
+ drivers/net/ethernet/ti/davinci_mdio.c             |    2 +-
+ drivers/net/ethernet/toshiba/ps3_gelic_wireless.c  |    4 +-
+ drivers/net/ethernet/wiznet/w5100.c                |    2 -
+ drivers/net/ethernet/wiznet/w5300.c                |    2 -
+ drivers/net/hyperv/rndis_filter.c                  |    5 -
+ drivers/net/irda/sh_irda.c                         |    4 -
+ drivers/net/netconsole.c                           |    6 +
+ drivers/net/phy/davicom.c                          |    6 +
+ drivers/net/phy/mdio_bus.c                         |   14 +
+ drivers/net/phy/micrel.c                           |   44 +
+ drivers/net/phy/smsc.c                             |   69 +-
+ drivers/net/ppp/ppp_generic.c                      |    2 +-
+ drivers/net/tun.c                                  |  852 ++++++--
+ drivers/net/usb/Kconfig                            |   22 +
+ drivers/net/usb/Makefile                           |    1 +
+ drivers/net/usb/asix_common.c                      |  117 +-
+ drivers/net/usb/asix_devices.c                     |   19 +-
+ drivers/net/usb/cdc_mbim.c                         |  412 ++++
+ drivers/net/usb/cdc_ncm.c                          |  645 +++---
+ drivers/net/usb/dm9601.c                           |  107 +-
+ drivers/net/usb/int51x1.c                          |   52 +-
+ drivers/net/usb/mcs7830.c                          |   85 +-
+ drivers/net/usb/net1080.c                          |  110 +-
+ drivers/net/usb/plusb.c                            |   11 +-
+ drivers/net/usb/sierra_net.c                       |   47 +-
+ drivers/net/usb/smsc75xx.c                         |  957 +++++---
+ drivers/net/usb/smsc95xx.c                         |  706 ++++--
+ drivers/net/usb/smsc95xx.h                         |   25 +
+ drivers/net/usb/usbnet.c                           |  196 ++
+ drivers/net/veth.c                                 |    1 +
+ drivers/net/virtio_net.c                           |   12 +-
+ drivers/net/vmxnet3/vmxnet3_drv.c                  |   36 +-
+ drivers/net/vxlan.c                                |  262 ++-
+ drivers/net/wan/Makefile                           |    4 +-
+ drivers/net/wan/wanxlfw.S                          |    1 +
+ drivers/net/wireless/airo.c                        |    2 +-
+ drivers/net/wireless/ath/Kconfig                   |    1 +
+ drivers/net/wireless/ath/Makefile                  |    1 +
+ drivers/net/wireless/ath/ar5523/Kconfig            |    7 +
+ drivers/net/wireless/ath/ar5523/Makefile           |    1 +
+ drivers/net/wireless/ath/ar5523/ar5523.c           | 1806 +++++++++++++++
+ drivers/net/wireless/ath/ar5523/ar5523.h           |  152 ++
+ drivers/net/wireless/ath/ar5523/ar5523_hw.h        |  431 ++++
+ drivers/net/wireless/ath/ath6kl/cfg80211.c         |    4 +-
+ drivers/net/wireless/ath/ath9k/ar9003_calib.c      |    5 +
+ drivers/net/wireless/ath/ath9k/ar9003_eeprom.c     |   22 +-
+ drivers/net/wireless/ath/ath9k/ar9003_hw.c         |    8 +-
+ drivers/net/wireless/ath/ath9k/ar9003_mci.c        |   70 +-
+ drivers/net/wireless/ath/ath9k/ar9003_mci.h        |    8 +-
+ drivers/net/wireless/ath/ath9k/ar9003_phy.h        |    1 +
+ .../net/wireless/ath/ath9k/ar9565_1p0_initvals.h   |    4 +-
+ drivers/net/wireless/ath/ath9k/ath9k.h             |    9 +
+ drivers/net/wireless/ath/ath9k/btcoex.c            |   62 +-
+ drivers/net/wireless/ath/ath9k/btcoex.h            |    7 +
+ drivers/net/wireless/ath/ath9k/calib.c             |    1 +
+ drivers/net/wireless/ath/ath9k/debug.c             |   34 +-
+ drivers/net/wireless/ath/ath9k/gpio.c              |  110 +-
+ drivers/net/wireless/ath/ath9k/htc_drv_init.c      |   17 +
+ drivers/net/wireless/ath/ath9k/htc_drv_main.c      |   20 -
+ drivers/net/wireless/ath/ath9k/hw.c                |    6 +-
+ drivers/net/wireless/ath/ath9k/hw.h                |    2 +
+ drivers/net/wireless/ath/ath9k/init.c              |    1 +
+ drivers/net/wireless/ath/ath9k/link.c              |   12 +-
+ drivers/net/wireless/ath/ath9k/main.c              |   12 +-
+ drivers/net/wireless/ath/ath9k/mci.c               |  171 +-
+ drivers/net/wireless/ath/ath9k/mci.h               |   36 +
+ drivers/net/wireless/ath/ath9k/recv.c              |    5 +-
+ drivers/net/wireless/ath/ath9k/reg.h               |   13 +-
+ drivers/net/wireless/ath/ath9k/wow.c               |    2 +-
+ drivers/net/wireless/ath/carl9170/mac.c            |   21 +-
+ drivers/net/wireless/ath/carl9170/rx.c             |   51 +-
+ drivers/net/wireless/ath/carl9170/usb.c            |    7 +
+ drivers/net/wireless/ath/hw.c                      |   20 +-
+ drivers/net/wireless/b43/main.c                    |    2 +-
+ drivers/net/wireless/brcm80211/brcmfmac/Makefile   |    1 +
+ drivers/net/wireless/brcm80211/brcmfmac/dhd.h      |   73 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h  |    3 -
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c  |   29 -
+ .../net/wireless/brcm80211/brcmfmac/dhd_common.c   |  453 ++--
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c  |    2 +
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h  |    3 +
+ .../net/wireless/brcm80211/brcmfmac/dhd_linux.c    |  198 +-
+ .../net/wireless/brcm80211/brcmfmac/dhd_proto.h    |    8 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |  174 +-
+ drivers/net/wireless/brcm80211/brcmfmac/fwil.c     |  336 +++
+ drivers/net/wireless/brcm80211/brcmfmac/fwil.h     |   39 +
+ drivers/net/wireless/brcm80211/brcmfmac/usb.c      |   41 +-
+ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  | 1218 +++++------
+ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.h  |  145 +-
+ drivers/net/wireless/brcm80211/brcmsmac/aiutils.c  |    4 +-
+ drivers/net/wireless/brcm80211/brcmsmac/main.c     |    2 +-
+ drivers/net/wireless/hostap/hostap_80211_rx.c      |    2 +-
+ drivers/net/wireless/ipw2x00/libipw_rx.c           |    6 +-
+ drivers/net/wireless/iwlwifi/dvm/main.c            |    9 +-
+ drivers/net/wireless/iwlwifi/iwl-devtrace.h        |   95 +-
+ drivers/net/wireless/iwlwifi/iwl-io.c              |    4 +-
+ drivers/net/wireless/iwlwifi/iwl-io.h              |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-prph.h            |    3 +
+ drivers/net/wireless/iwlwifi/iwl-trans.h           |    8 +
+ drivers/net/wireless/iwlwifi/pcie/rx.c             |    3 +-
+ drivers/net/wireless/iwlwifi/pcie/trans.c          |    9 +-
+ drivers/net/wireless/iwlwifi/pcie/tx.c             |   12 +-
+ drivers/net/wireless/libertas/mesh.c               |    2 +-
+ drivers/net/wireless/mwifiex/11n_rxreorder.c       |    8 +-
+ drivers/net/wireless/mwifiex/cfg80211.c            |   20 +-
+ drivers/net/wireless/mwifiex/cmdevt.c              |   21 +-
+ drivers/net/wireless/mwifiex/init.c                |   19 +-
+ drivers/net/wireless/mwifiex/main.c                |    8 +
+ drivers/net/wireless/mwifiex/main.h                |   13 +-
+ drivers/net/wireless/mwifiex/scan.c                |   55 +-
+ drivers/net/wireless/mwifiex/sta_cmdresp.c         |    4 -
+ drivers/net/wireless/mwifiex/sta_ioctl.c           |    4 +-
+ drivers/net/wireless/mwifiex/sta_rx.c              |   26 +-
+ drivers/net/wireless/mwifiex/txrx.c                |   10 +-
+ drivers/net/wireless/mwifiex/uap_cmd.c             |   11 +-
+ drivers/net/wireless/mwifiex/uap_txrx.c            |   17 +-
+ drivers/net/wireless/mwifiex/util.c                |   19 +-
+ drivers/net/wireless/orinoco/main.h                |    2 +-
+ drivers/net/wireless/orinoco/orinoco_usb.c         |    9 +-
+ drivers/net/wireless/rt2x00/rt2800lib.c            |  100 +-
+ drivers/net/wireless/rtlwifi/cam.c                 |    7 +-
+ drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c  |  227 +-
+ drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c |   88 +-
+ drivers/net/wireless/rtlwifi/rtl8192ce/def.h       |    3 +
+ drivers/net/wireless/rtlwifi/rtl8192ce/dm.c        |   30 +-
+ drivers/net/wireless/rtlwifi/rtl8192ce/hw.c        |   93 +-
+ drivers/net/wireless/rtlwifi/rtl8192ce/phy.c       |    2 +
+ drivers/net/wireless/rtlwifi/rtl8192ce/rf.c        |   23 +-
+ drivers/net/wireless/rtlwifi/rtl8192ce/sw.c        |    6 +-
+ drivers/net/wireless/rtlwifi/rtl8192ce/trx.c       |   46 +-
+ drivers/net/wireless/rtlwifi/rtl8192cu/dm.c        |   30 +-
+ drivers/net/wireless/rtlwifi/rtl8192cu/hw.c        |   16 +-
+ drivers/net/wireless/rtlwifi/rtl8192cu/mac.c       |   25 +-
+ drivers/net/wireless/rtlwifi/rtl8192cu/rf.c        |   22 +-
+ drivers/net/wireless/rtlwifi/rtl8192de/dm.c        |   95 +-
+ drivers/net/wireless/rtlwifi/rtl8192de/phy.c       |   65 +-
+ drivers/net/wireless/rtlwifi/rtl8192de/rf.c        |   18 +-
+ drivers/net/wireless/rtlwifi/rtl8192de/trx.c       |   39 +-
+ drivers/net/wireless/rtlwifi/rtl8192se/dm.c        |   89 +-
+ drivers/net/wireless/rtlwifi/rtl8192se/hw.c        |    6 +-
+ drivers/net/wireless/rtlwifi/rtl8192se/phy.c       |   64 +-
+ drivers/net/wireless/rtlwifi/rtl8192se/rf.c        |   11 +-
+ drivers/net/wireless/rtlwifi/rtl8192se/trx.c       |   21 +-
+ drivers/net/wireless/rtlwifi/wifi.h                |   53 +-
+ drivers/nfc/Makefile                               |    2 +-
+ drivers/nfc/pn533.c                                |   18 +-
+ drivers/nfc/pn544/Makefile                         |    7 +
+ drivers/nfc/pn544/i2c.c                            |  500 +++++
+ drivers/nfc/{pn544_hci.c => pn544/pn544.c}         |  679 +++---
+ drivers/nfc/pn544/pn544.h                          |   32 +
+ drivers/pps/Kconfig                                |    1 -
+ drivers/ptp/Kconfig                                |   19 +-
+ drivers/ptp/ptp_chardev.c                          |   61 +-
+ drivers/s390/net/claw.c                            |    2 -
+ drivers/s390/net/ctcm_main.c                       |    2 -
+ drivers/s390/net/ctcm_mpc.c                        |    3 -
+ drivers/s390/net/qeth_core.h                       |    1 +
+ drivers/s390/net/qeth_core_main.c                  |   49 +-
+ drivers/s390/net/qeth_l2_main.c                    |    4 +-
+ drivers/s390/net/qeth_l3_main.c                    |    8 +-
+ drivers/ssb/b43_pci_bridge.c                       |    1 +
+ drivers/ssb/driver_chipcommon_pmu.c                |    3 +
+ drivers/ssb/driver_mipscore.c                      |   16 +-
+ drivers/vhost/net.c                                |  111 +-
+ drivers/vhost/tcm_vhost.c                          |    2 +-
+ drivers/vhost/vhost.c                              |   52 +-
+ drivers/vhost/vhost.h                              |   11 +-
+ fs/proc/proc_sysctl.c                              |    9 +-
+ include/linux/bcma/bcma.h                          |    2 +-
+ include/linux/bcma/bcma_driver_chipcommon.h        |    5 +
+ include/linux/bcma/bcma_driver_mips.h              |    3 +
+ include/linux/bcma/bcma_regs.h                     |    5 +-
+ include/linux/etherdevice.h                        |   20 +
+ include/linux/filter.h                             |    3 +
+ include/linux/hdlc/Kbuild                          |    1 -
+ include/linux/ieee80211.h                          |   47 +-
+ include/linux/if_tunnel.h                          |   17 +
+ include/linux/ipv6.h                               |    1 +
+ include/linux/ktime.h                              |   19 +
+ include/linux/micrel_phy.h                         |    1 +
+ include/linux/netdevice.h                          |   32 +-
+ include/linux/pci.h                                |   14 +
+ include/linux/platform_data/cpsw.h                 |   23 +-
+ include/linux/platform_data/macb.h                 |    1 +
+ include/linux/rtnetlink.h                          |    3 +
+ include/linux/skbuff.h                             |    7 +-
+ include/linux/ssb/ssb_driver_mips.h                |   10 +-
+ include/linux/stmmac.h                             |    1 +
+ include/linux/sysctl.h                             |    3 +-
+ include/linux/timecompare.h                        |  125 --
+ include/linux/usb/cdc_ncm.h                        |  134 ++
+ include/linux/usb/usbnet.h                         |   10 +
+ include/net/af_unix.h                              |    1 -
+ include/net/bluetooth/a2mp.h                       |   24 +-
+ include/net/bluetooth/amp.h                        |   50 +
+ include/net/bluetooth/bluetooth.h                  |    1 -
+ include/net/bluetooth/hci.h                        |   40 +-
+ include/net/bluetooth/hci_core.h                   |   48 +-
+ include/net/bluetooth/l2cap.h                      |   14 +-
+ include/net/cfg80211.h                             |   14 +
+ include/net/cls_cgroup.h                           |    6 +-
+ include/net/ip6_checksum.h                         |   35 +
+ include/net/ip6_fib.h                              |   20 +-
+ include/net/ip6_route.h                            |    3 -
+ include/net/ip_vs.h                                |  195 +-
+ include/net/ipip.h                                 |   40 +-
+ include/net/mac80211.h                             |  114 +-
+ include/net/net_namespace.h                        |   24 +-
+ include/net/netns/sctp.h                           |    3 +
+ include/net/nfc/hci.h                              |   18 +-
+ include/net/nfc/nfc.h                              |    2 +-
+ include/net/protocol.h                             |   31 +-
+ include/net/request_sock.h                         |   12 +-
+ include/net/route.h                                |    9 +-
+ include/net/sctp/command.h                         |   38 +-
+ include/net/sctp/constants.h                       |    8 -
+ include/net/sctp/sm.h                              |    2 +
+ include/net/sctp/structs.h                         |    1 +
+ include/net/sctp/ulpqueue.h                        |    2 +-
+ include/net/tcp.h                                  |    1 -
+ include/uapi/asm-generic/socket.h                  |    1 +
+ include/uapi/linux/filter.h                        |    4 +-
+ include/uapi/linux/hdlc/Kbuild                     |    1 +
+ include/{ => uapi}/linux/hdlc/ioctl.h              |    7 +-
+ include/uapi/linux/if_bridge.h                     |   18 +
+ include/uapi/linux/if_ether.h                      |    1 +
+ include/uapi/linux/if_link.h                       |   21 +
+ include/uapi/linux/if_packet.h                     |    1 +
+ include/uapi/linux/if_tun.h                        |    5 +
+ include/uapi/linux/if_tunnel.h                     |   20 +
+ include/uapi/linux/in6.h                           |    1 +
+ include/uapi/linux/inet_diag.h                     |    3 +-
+ include/uapi/linux/ipv6.h                          |    1 +
+ include/uapi/linux/ipv6_route.h                    |    3 +
+ include/uapi/linux/netconf.h                       |   23 +
+ include/uapi/linux/netfilter_ipv6/ip6_tables.h     |    3 +
+ include/uapi/linux/nfc.h                           |   15 +
+ include/uapi/linux/nl80211.h                       |   48 +
+ include/uapi/linux/ptp_clock.h                     |   14 +
+ include/uapi/linux/rtnetlink.h                     |    9 +
+ include/uapi/linux/unix_diag.h                     |    1 +
+ include/uapi/linux/usb/cdc.h                       |   23 +
+ kernel/nsproxy.c                                   |    2 +-
+ kernel/time/Makefile                               |    2 +-
+ kernel/time/timecompare.c                          |  193 --
+ net/8021q/vlan.c                                   |   14 +-
+ net/8021q/vlan_dev.c                               |   12 +-
+ net/atm/br2684.c                                   |   36 +-
+ net/batman-adv/Kconfig                             |   11 +
+ net/batman-adv/Makefile                            |    1 +
+ net/batman-adv/bat_iv_ogm.c                        |   51 +-
+ net/batman-adv/bitarray.c                          |   23 +-
+ net/batman-adv/bridge_loop_avoidance.c             |  131 +-
+ net/batman-adv/bridge_loop_avoidance.h             |    6 +-
+ net/batman-adv/debugfs.c                           |   60 +-
+ net/batman-adv/distributed-arp-table.c             | 1066 +++++++++
+ net/batman-adv/distributed-arp-table.h             |  167 ++
+ net/batman-adv/gateway_client.c                    |   19 +-
+ net/batman-adv/hard-interface.c                    |   48 +-
+ net/batman-adv/hash.h                              |   22 +
+ net/batman-adv/icmp_socket.c                       |   16 +-
+ net/batman-adv/main.c                              |   89 +-
+ net/batman-adv/main.h                              |   36 +-
+ net/batman-adv/originator.c                        |   22 +-
+ net/batman-adv/packet.h                            |   84 +-
+ net/batman-adv/routing.c                           |  315 +--
+ net/batman-adv/send.c                              |   37 +
+ net/batman-adv/send.h                              |    3 +
+ net/batman-adv/soft-interface.c                    |   85 +-
+ net/batman-adv/sysfs.c                             |   58 +-
+ net/batman-adv/translation-table.c                 |  526 +++--
+ net/batman-adv/translation-table.h                 |    8 +-
+ net/batman-adv/types.h                             |  102 +-
+ net/batman-adv/unicast.c                           |  143 +-
+ net/batman-adv/unicast.h                           |   36 +-
+ net/batman-adv/vis.c                               |   44 +-
+ net/bluetooth/Kconfig                              |    1 +
+ net/bluetooth/Makefile                             |    2 +-
+ net/bluetooth/a2mp.c                               |  459 +++-
+ net/bluetooth/af_bluetooth.c                       |   10 +-
+ net/bluetooth/amp.c                                |  374 ++++
+ net/bluetooth/bnep/core.c                          |    3 +-
+ net/bluetooth/cmtp/core.c                          |    2 +-
+ net/bluetooth/hci_conn.c                           |   70 +-
+ net/bluetooth/hci_core.c                           |   65 +-
+ net/bluetooth/hci_event.c                          |  167 +-
+ net/bluetooth/hci_sysfs.c                          |   10 +-
+ net/bluetooth/hidp/core.c                          |    8 +-
+ net/bluetooth/l2cap_core.c                         |  503 +++--
+ net/bluetooth/l2cap_sock.c                         |   89 +-
+ net/bluetooth/lib.c                                |   14 -
+ net/bluetooth/mgmt.c                               |    5 +-
+ net/bluetooth/rfcomm/core.c                        |   19 +-
+ net/bluetooth/rfcomm/sock.c                        |    9 +-
+ net/bluetooth/rfcomm/tty.c                         |    6 +-
+ net/bluetooth/sco.c                                |   12 +-
+ net/bluetooth/smp.c                                |    2 +-
+ net/bridge/br_device.c                             |    4 +-
+ net/bridge/br_input.c                              |   17 +-
+ net/bridge/br_ioctl.c                              |   25 +-
+ net/bridge/br_netlink.c                            |  247 ++-
+ net/bridge/br_private.h                            |   18 +-
+ net/bridge/br_stp.c                                |   22 +-
+ net/bridge/br_stp_bpdu.c                           |    7 +
+ net/bridge/br_sysfs_br.c                           |   22 +-
+ net/bridge/br_sysfs_if.c                           |   44 +-
+ net/caif/cfctrl.c                                  |    3 +-
+ net/can/gw.c                                       |    6 +
+ net/core/dev.c                                     |  152 +-
+ net/core/ethtool.c                                 |    2 +-
+ net/core/filter.c                                  |  139 ++
+ net/core/flow.c                                    |    4 +-
+ net/core/neighbour.c                               |    4 +
+ net/core/net-sysfs.c                               |   17 +-
+ net/core/net_namespace.c                           |   23 +-
+ net/core/netprio_cgroup.c                          |    2 +-
+ net/core/pktgen.c                                  |   47 +-
+ net/core/rtnetlink.c                               |  226 +-
+ net/core/scm.c                                     |    6 +-
+ net/core/skbuff.c                                  |   24 +-
+ net/core/sock.c                                    |   84 +-
+ net/core/sysctl_net_core.c                         |    5 +
+ net/dcb/dcbnl.c                                    |    3 +
+ net/dccp/minisocks.c                               |    3 +-
+ net/decnet/dn_dev.c                                |    6 +
+ net/decnet/dn_fib.c                                |    6 +
+ net/dsa/Kconfig                                    |   18 +-
+ net/ipv4/af_inet.c                                 |   93 +-
+ net/ipv4/arp.c                                     |    2 +-
+ net/ipv4/devinet.c                                 |  192 +-
+ net/ipv4/fib_frontend.c                            |    2 +-
+ net/ipv4/fib_semantics.c                           |    2 +-
+ net/ipv4/inet_connection_sock.c                    |   25 +-
+ net/ipv4/inet_diag.c                               |    5 +-
+ net/ipv4/ip_fragment.c                             |    4 +
+ net/ipv4/ip_gre.c                                  |   32 +-
+ net/ipv4/ip_options.c                              |    6 +-
+ net/ipv4/ip_sockglue.c                             |    5 +-
+ net/ipv4/ip_vti.c                                  |   26 +-
+ net/ipv4/ipconfig.c                                |    6 +-
+ net/ipv4/ipip.c                                    |  271 ++-
+ net/ipv4/ipmr.c                                    |   30 +-
+ net/ipv4/netfilter/arp_tables.c                    |    8 +-
+ net/ipv4/netfilter/ip_tables.c                     |    8 +-
+ net/ipv4/netfilter/iptable_nat.c                   |    4 +-
+ net/ipv4/protocol.c                                |   21 +
+ net/ipv4/route.c                                   |    4 +
+ net/ipv4/syncookies.c                              |    2 +-
+ net/ipv4/sysctl_net_ipv4.c                         |    3 +
+ net/ipv4/tcp.c                                     |    7 +-
+ net/ipv4/tcp_cong.c                                |    3 +-
+ net/ipv4/tcp_input.c                               |   45 +-
+ net/ipv4/tcp_ipv4.c                                |   38 +-
+ net/ipv4/tcp_minisocks.c                           |    8 +-
+ net/ipv4/tcp_output.c                              |    5 +
+ net/ipv4/tcp_timer.c                               |    8 +-
+ net/ipv6/Makefile                                  |    5 +-
+ net/ipv6/addrconf.c                                |  189 +-
+ net/ipv6/af_inet6.c                                |  245 +--
+ net/ipv6/ah6.c                                     |   10 +-
+ net/ipv6/anycast.c                                 |    4 +-
+ net/ipv6/datagram.c                                |    8 +-
+ net/ipv6/exthdrs.c                                 |   70 +-
+ net/ipv6/exthdrs_core.c                            |   44 +
+ net/ipv6/exthdrs_offload.c                         |   41 +
+ net/ipv6/fib6_rules.c                              |    2 +-
+ net/ipv6/icmp.c                                    |    2 +-
+ net/ipv6/ip6_fib.c                                 |   57 +
+ net/ipv6/ip6_flowlabel.c                           |    3 +-
+ net/ipv6/ip6_gre.c                                 |   29 +-
+ net/ipv6/ip6_offload.c                             |  282 +++
+ net/ipv6/ip6_offload.h                             |   18 +
+ net/ipv6/ip6_output.c                              |   72 +-
+ net/ipv6/ip6_tunnel.c                              |  288 ++-
+ net/ipv6/ip6mr.c                                   |   14 +-
+ net/ipv6/ipv6_sockglue.c                           |    9 +-
+ net/ipv6/mcast.c                                   |    4 +-
+ net/ipv6/ndisc.c                                   |   19 +-
+ net/ipv6/netfilter/ip6_tables.c                    |   14 +-
+ net/ipv6/netfilter/ip6t_rpfilter.c                 |    2 +-
+ net/ipv6/netfilter/ip6table_nat.c                  |    4 +-
+ net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c     |   70 +-
+ net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c     |    4 +-
+ net/ipv6/netfilter/nf_defrag_ipv6_hooks.c          |    6 +-
+ net/ipv6/netfilter/nf_nat_proto_icmpv6.c           |    2 +-
+ net/ipv6/output_core.c                             |   76 +
+ net/ipv6/protocol.c                                |   25 +
+ net/ipv6/raw.c                                     |    6 +-
+ net/ipv6/reassembly.c                              |    4 +
+ net/ipv6/route.c                                   |  186 +-
+ net/ipv6/sit.c                                     |  459 +++-
+ net/ipv6/syncookies.c                              |    2 +-
+ net/ipv6/tcp_ipv6.c                                |  124 +-
+ net/ipv6/tcpv6_offload.c                           |   95 +
+ net/ipv6/udp.c                                     |   94 -
+ net/ipv6/udp_offload.c                             |  120 +
+ net/ipv6/xfrm6_policy.c                            |   21 +-
+ net/ipv6/xfrm6_state.c                             |    4 +-
+ net/key/af_key.c                                   |    2 +-
+ net/l2tp/l2tp_netlink.c                            |    2 +-
+ net/llc/af_llc.c                                   |    2 +-
+ net/mac80211/Kconfig                               |    2 +-
+ net/mac80211/Makefile                              |    1 +
+ net/mac80211/aes_cmac.c                            |   17 +
+ net/mac80211/cfg.c                                 |  284 +--
+ net/mac80211/chan.c                                |  455 +++-
+ net/mac80211/debugfs.h                             |    6 +-
+ net/mac80211/debugfs_netdev.c                      |   10 +-
+ net/mac80211/driver-ops.h                          |   65 +
+ net/mac80211/ibss.c                                |   88 +-
+ net/mac80211/ieee80211_i.h                         |  171 +-
+ net/mac80211/iface.c                               |   44 +-
+ net/mac80211/main.c                                |  105 +-
+ net/mac80211/mesh.c                                |   52 +-
+ net/mac80211/mesh.h                                |    4 +-
+ net/mac80211/mesh_plink.c                          |   14 +-
+ net/mac80211/mesh_sync.c                           |   55 +-
+ net/mac80211/mlme.c                                |  228 +-
+ net/mac80211/offchannel.c                          |    9 +-
+ net/mac80211/pm.c                                  |    2 +
+ net/mac80211/rate.h                                |   12 +-
+ net/mac80211/rx.c                                  |   32 +-
+ net/mac80211/scan.c                                |   29 +-
+ net/mac80211/sta_info.c                            |   59 +-
+ net/mac80211/status.c                              |   15 +-
+ net/mac80211/trace.h                               |  146 +-
+ net/mac80211/tx.c                                  |  281 ++-
+ net/mac80211/util.c                                |  145 +-
+ net/mac80211/vht.c                                 |   35 +
+ net/netfilter/ipset/ip_set_core.c                  |    2 +-
+ net/netfilter/ipvs/Kconfig                         |    7 +-
+ net/netfilter/ipvs/ip_vs_conn.c                    |   15 +-
+ net/netfilter/ipvs/ip_vs_core.c                    |  404 ++--
+ net/netfilter/ipvs/ip_vs_ctl.c                     |    8 +-
+ net/netfilter/ipvs/ip_vs_dh.c                      |    2 +-
+ net/netfilter/ipvs/ip_vs_lblc.c                    |    7 +-
+ net/netfilter/ipvs/ip_vs_lblcr.c                   |    6 +-
+ net/netfilter/ipvs/ip_vs_nfct.c                    |    2 +-
+ net/netfilter/ipvs/ip_vs_pe_sip.c                  |   18 +-
+ net/netfilter/ipvs/ip_vs_proto.c                   |    6 +-
+ net/netfilter/ipvs/ip_vs_proto_ah_esp.c            |    9 +-
+ net/netfilter/ipvs/ip_vs_proto_sctp.c              |   42 +-
+ net/netfilter/ipvs/ip_vs_proto_tcp.c               |   40 +-
+ net/netfilter/ipvs/ip_vs_proto_udp.c               |   41 +-
+ net/netfilter/ipvs/ip_vs_sched.c                   |    2 +-
+ net/netfilter/ipvs/ip_vs_sh.c                      |    2 +-
+ net/netfilter/ipvs/ip_vs_xmit.c                    |   81 +-
+ net/netfilter/nf_conntrack_acct.c                  |    4 +
+ net/netfilter/nf_conntrack_ecache.c                |    4 +
+ net/netfilter/nf_conntrack_helper.c                |    4 +
+ net/netfilter/nf_conntrack_proto_dccp.c            |    8 +-
+ net/netfilter/nf_conntrack_standalone.c            |    4 +
+ net/netfilter/nf_conntrack_timestamp.c             |    4 +
+ net/netfilter/nfnetlink.c                          |    2 +-
+ net/netfilter/xt_ipvs.c                            |    4 +-
+ net/netlink/af_netlink.c                           |    2 +-
+ net/nfc/Kconfig                                    |    4 +-
+ net/nfc/core.c                                     |   33 +-
+ net/nfc/hci/command.c                              |   24 +-
+ net/nfc/hci/core.c                                 |   71 +-
+ net/nfc/hci/llc.c                                  |    2 +-
+ net/nfc/hci/llc_shdlc.c                            |    7 +-
+ net/nfc/llcp/Kconfig                               |    4 +-
+ net/nfc/llcp/commands.c                            |  120 +-
+ net/nfc/llcp/llcp.c                                |  226 +-
+ net/nfc/llcp/llcp.h                                |   13 +
+ net/nfc/llcp/sock.c                                |   42 +-
+ net/nfc/nci/Kconfig                                |    4 +-
+ net/nfc/nci/core.c                                 |   29 +-
+ net/nfc/netlink.c                                  |  157 +-
+ net/nfc/nfc.h                                      |    6 +
+ net/nfc/rawsock.c                                  |    1 -
+ net/packet/af_packet.c                             |   50 +-
+ net/packet/internal.h                              |    1 +
+ net/phonet/pn_netlink.c                            |    6 +
+ net/rds/ib.h                                       |    2 +-
+ net/rds/ib_recv.c                                  |   24 +-
+ net/sched/Kconfig                                  |    2 +-
+ net/sched/act_api.c                                |    3 +
+ net/sched/cls_api.c                                |    2 +
+ net/sched/cls_cgroup.c                             |   24 +
+ net/sched/sch_api.c                                |   18 +-
+ net/sched/sch_cbq.c                                |    3 +-
+ net/sched/sch_htb.c                                |  139 +-
+ net/sched/sch_qfq.c                                |  830 ++++---
+ net/sctp/Kconfig                                   |   39 +-
+ net/sctp/protocol.c                                |    9 +
+ net/sctp/sm_make_chunk.c                           |   19 +
+ net/sctp/sm_sideeffect.c                           |   54 +-
+ net/sctp/socket.c                                  |   19 +-
+ net/sctp/sysctl.c                                  |   59 +
+ net/sctp/tsnmap.c                                  |    8 +-
+ net/sctp/ulpqueue.c                                |    3 +-
+ net/socket.c                                       |    8 -
+ net/sysctl_net.c                                   |   15 +-
+ net/tipc/Kconfig                                   |   13 +-
+ net/tipc/bcast.c                                   |   27 +-
+ net/tipc/bearer.c                                  |  110 +-
+ net/tipc/bearer.h                                  |   24 +-
+ net/tipc/core.c                                    |    5 -
+ net/tipc/discover.c                                |    2 +-
+ net/tipc/link.c                                    |  188 +-
+ net/tipc/link.h                                    |    4 -
+ net/tipc/name_distr.c                              |    2 +-
+ net/tipc/node.c                                    |   15 +-
+ net/tipc/node.h                                    |    6 +-
+ net/tipc/socket.c                                  |   58 +-
+ net/unix/diag.c                                    |    3 +
+ net/unix/sysctl_net_unix.c                         |    4 +
+ net/wireless/Makefile                              |    4 +-
+ net/wireless/ap.c                                  |    3 +-
+ net/wireless/chan.c                                |   16 +-
+ net/wireless/core.c                                |   16 +-
+ net/wireless/core.h                                |    6 +-
+ net/wireless/ethtool.c                             |   15 +-
+ net/wireless/ibss.c                                |    9 +-
+ net/wireless/mesh.c                                |   11 +-
+ net/wireless/mlme.c                                |   92 +-
+ net/wireless/nl80211.c                             |  259 ++-
+ net/wireless/rdev-ops.h                            |  879 ++++++++
+ net/wireless/scan.c                                |  138 +-
+ net/wireless/sme.c                                 |   12 +-
+ net/wireless/sysfs.c                               |    5 +-
+ net/wireless/trace.c                               |    7 +
+ net/wireless/trace.h                               | 2296 ++++++++++++++++++++
+ net/wireless/util.c                                |   14 +-
+ net/wireless/wext-compat.c                         |   48 +-
+ net/xfrm/xfrm_ipcomp.c                             |    8 +-
+ net/xfrm/xfrm_replay.c                             |   13 +-
+ net/xfrm/xfrm_sysctl.c                             |    4 +
+ net/xfrm/xfrm_user.c                               |    2 +-
+ 772 files changed, 42257 insertions(+), 18377 deletions(-)
+ create mode 100644 Documentation/ABI/testing/sysfs-bus-mdio
+ create mode 100644 Documentation/ABI/testing/sysfs-class-net-grcan
+ create mode 100644 Documentation/devicetree/bindings/net/can/grcan.txt
+ create mode 100644 Documentation/devicetree/bindings/net/cdns-emac.txt
+ delete mode 100644 arch/arm/mach-at91/include/mach/at91rm9200_emac.h
+ create mode 100644 drivers/net/can/grcan.c
+ create mode 100644 drivers/net/can/usb/kvaser_usb.c
+ delete mode 100644 drivers/net/ethernet/cadence/at91_ether.h
+ create mode 100644 drivers/net/ethernet/freescale/fec_ptp.c
+ create mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
+ create mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
+ create mode 100644 drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
+ delete mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c
+ delete mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h
+ create mode 100644 drivers/net/ethernet/ti/cpts.c
+ create mode 100644 drivers/net/ethernet/ti/cpts.h
+ create mode 100644 drivers/net/usb/cdc_mbim.c
+ create mode 100644 drivers/net/wireless/ath/ar5523/Kconfig
+ create mode 100644 drivers/net/wireless/ath/ar5523/Makefile
+ create mode 100644 drivers/net/wireless/ath/ar5523/ar5523.c
+ create mode 100644 drivers/net/wireless/ath/ar5523/ar5523.h
+ create mode 100644 drivers/net/wireless/ath/ar5523/ar5523_hw.h
+ create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/fwil.c
+ create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/fwil.h
+ create mode 100644 drivers/nfc/pn544/Makefile
+ create mode 100644 drivers/nfc/pn544/i2c.c
+ rename drivers/nfc/{pn544_hci.c => pn544/pn544.c} (58%)
+ create mode 100644 drivers/nfc/pn544/pn544.h
+ delete mode 100644 include/linux/timecompare.h
+ create mode 100644 include/linux/usb/cdc_ncm.h
+ create mode 100644 include/net/bluetooth/amp.h
+ rename include/{ => uapi}/linux/hdlc/ioctl.h (96%)
+ create mode 100644 include/uapi/linux/netconf.h
+ delete mode 100644 kernel/time/timecompare.c
+ create mode 100644 net/batman-adv/distributed-arp-table.c
+ create mode 100644 net/batman-adv/distributed-arp-table.h
+ create mode 100644 net/bluetooth/amp.c
+ create mode 100644 net/ipv6/exthdrs_offload.c
+ create mode 100644 net/ipv6/ip6_offload.c
+ create mode 100644 net/ipv6/ip6_offload.h
+ create mode 100644 net/ipv6/output_core.c
+ create mode 100644 net/ipv6/tcpv6_offload.c
+ create mode 100644 net/ipv6/udp_offload.c
+ create mode 100644 net/mac80211/vht.c
+ create mode 100644 net/wireless/rdev-ops.h
+ create mode 100644 net/wireless/trace.c
+ create mode 100644 net/wireless/trace.h
+Merging wireless-next/master (0751f86 bcma: add more package IDs)
+$ git merge wireless-next/master
+Resolved 'drivers/net/wireless/iwlwifi/pcie/tx.c' using previous resolution.
+Auto-merging net/mac80211/offchannel.c
+Removing include/linux/nfc/pn544.h
+Auto-merging drivers/net/wireless/iwlwifi/pcie/tx.c
+CONFLICT (content): Merge conflict in drivers/net/wireless/iwlwifi/pcie/tx.c
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 968deab] Merge remote-tracking branch 'wireless-next/master'
+$ git diff -M --stat --summary HEAD^..
+ MAINTAINERS                                        |    1 +
+ drivers/bluetooth/btusb.c                          |    1 +
+ drivers/net/wireless/at76c50x-usb.c                |   85 +-
+ drivers/net/wireless/ath/ar5523/ar5523.c           |   60 +-
+ drivers/net/wireless/ath/ar5523/ar5523_hw.h        |    2 +-
+ drivers/net/wireless/ath/ath5k/ahb.c               |   15 +-
+ drivers/net/wireless/ath/ath5k/base.c              |   12 +-
+ drivers/net/wireless/ath/ath5k/mac80211-ops.c      |    5 +-
+ drivers/net/wireless/ath/ath5k/reset.c             |    6 +-
+ drivers/net/wireless/ath/ath6kl/Kconfig            |    9 +
+ drivers/net/wireless/ath/ath6kl/Makefile           |    1 +
+ drivers/net/wireless/ath/ath6kl/cfg80211.c         |  406 ++--
+ drivers/net/wireless/ath/ath6kl/cfg80211.h         |    1 -
+ drivers/net/wireless/ath/ath6kl/core.c             |   21 +
+ drivers/net/wireless/ath/ath6kl/core.h             |   69 +-
+ drivers/net/wireless/ath/ath6kl/debug.h            |    1 +
+ drivers/net/wireless/ath/ath6kl/hif.c              |   12 +-
+ drivers/net/wireless/ath/ath6kl/htc_mbox.c         |   13 +-
+ drivers/net/wireless/ath/ath6kl/htc_pipe.c         |   14 +-
+ drivers/net/wireless/ath/ath6kl/init.c             |   92 +-
+ drivers/net/wireless/ath/ath6kl/main.c             |   55 +-
+ drivers/net/wireless/ath/ath6kl/recovery.c         |  160 ++
+ drivers/net/wireless/ath/ath6kl/sdio.c             |   27 +-
+ drivers/net/wireless/ath/ath6kl/txrx.c             |   47 +-
+ drivers/net/wireless/ath/ath6kl/usb.c              |   32 +-
+ drivers/net/wireless/ath/ath6kl/wmi.c              |  284 ++-
+ drivers/net/wireless/ath/ath6kl/wmi.h              |   78 +-
+ drivers/net/wireless/ath/ath9k/ar9003_calib.c      |   76 +
+ drivers/net/wireless/ath/ath9k/ar9003_hw.c         |   22 +-
+ drivers/net/wireless/ath/ath9k/ar9003_mci.c        |    1 -
+ drivers/net/wireless/ath/ath9k/ar9003_phy.c        |    2 +-
+ drivers/net/wireless/ath/ath9k/ar9003_phy.h        |   46 +-
+ .../net/wireless/ath/ath9k/ar9462_2p0_initvals.h   |    2 +-
+ drivers/net/wireless/ath/ath9k/ar9485_initvals.h   |  338 ++-
+ drivers/net/wireless/ath/ath9k/ath9k.h             |   34 +-
+ drivers/net/wireless/ath/ath9k/beacon.c            |    2 +-
+ drivers/net/wireless/ath/ath9k/btcoex.c            |    1 +
+ drivers/net/wireless/ath/ath9k/btcoex.h            |    1 +
+ drivers/net/wireless/ath/ath9k/common.h            |    7 -
+ drivers/net/wireless/ath/ath9k/debug.c             |  198 +-
+ drivers/net/wireless/ath/ath9k/debug.h             |   18 +-
+ .../net/wireless/ath/ath9k/dfs_pattern_detector.c  |   12 +-
+ .../net/wireless/ath/ath9k/dfs_pattern_detector.h  |    4 +-
+ drivers/net/wireless/ath/ath9k/gpio.c              |   58 +-
+ drivers/net/wireless/ath/ath9k/htc.h               |    4 +-
+ drivers/net/wireless/ath/ath9k/htc_drv_beacon.c    |    8 +-
+ drivers/net/wireless/ath/ath9k/htc_drv_debug.c     |    8 +-
+ drivers/net/wireless/ath/ath9k/htc_drv_gpio.c      |    2 +-
+ drivers/net/wireless/ath/ath9k/htc_drv_init.c      |    8 +-
+ drivers/net/wireless/ath/ath9k/htc_drv_main.c      |   24 +-
+ drivers/net/wireless/ath/ath9k/htc_drv_txrx.c      |   28 +-
+ drivers/net/wireless/ath/ath9k/hw.c                |    5 -
+ drivers/net/wireless/ath/ath9k/hw.h                |    4 -
+ drivers/net/wireless/ath/ath9k/init.c              |    6 +-
+ drivers/net/wireless/ath/ath9k/link.c              |    5 +-
+ drivers/net/wireless/ath/ath9k/main.c              |   78 +-
+ drivers/net/wireless/ath/ath9k/mci.c               |   39 +-
+ drivers/net/wireless/ath/ath9k/pci.c               |   12 -
+ drivers/net/wireless/ath/ath9k/rc.c                |   53 +-
+ drivers/net/wireless/ath/ath9k/rc.h                |   16 +
+ drivers/net/wireless/ath/ath9k/recv.c              |    2 +-
+ drivers/net/wireless/ath/ath9k/xmit.c              |   12 +-
+ drivers/net/wireless/ath/carl9170/fw.c             |    5 -
+ drivers/net/wireless/b43/xmit.c                    |    2 +-
+ drivers/net/wireless/b43legacy/xmit.c              |    2 +-
+ drivers/net/wireless/brcm80211/Kconfig             |   15 +-
+ drivers/net/wireless/brcm80211/brcmfmac/Makefile   |    1 +
+ drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c   |   43 +-
+ .../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c |  140 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd.h      |  186 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h  |    3 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c  |   72 -
+ .../net/wireless/brcm80211/brcmfmac/dhd_common.c   |  452 +---
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c  |    6 -
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h  |   10 +-
+ .../net/wireless/brcm80211/brcmfmac/dhd_linux.c    |  509 ++---
+ .../net/wireless/brcm80211/brcmfmac/dhd_proto.h    |    7 -
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |  252 ++-
+ drivers/net/wireless/brcm80211/brcmfmac/fweh.c     |  509 +++++
+ drivers/net/wireless/brcm80211/brcmfmac/fweh.h     |  207 ++
+ drivers/net/wireless/brcm80211/brcmfmac/fwil.c     |   26 +-
+ drivers/net/wireless/brcm80211/brcmfmac/usb.c      |  278 +--
+ drivers/net/wireless/brcm80211/brcmfmac/usb.h      |   18 +-
+ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  | 1010 ++-------
+ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.h  |  120 +-
+ drivers/net/wireless/brcm80211/brcmsmac/Makefile   |    3 +-
+ drivers/net/wireless/brcm80211/brcmsmac/ampdu.c    |  723 +++---
+ drivers/net/wireless/brcm80211/brcmsmac/ampdu.h    |   29 +-
+ drivers/net/wireless/brcm80211/brcmsmac/antsel.c   |    4 +-
+ .../brcm80211/brcmsmac/brcms_trace_events.h        |  175 +-
+ drivers/net/wireless/brcm80211/brcmsmac/channel.c  |   10 +-
+ drivers/net/wireless/brcm80211/brcmsmac/debug.c    |   44 +
+ drivers/net/wireless/brcm80211/brcmsmac/debug.h    |   52 +
+ drivers/net/wireless/brcm80211/brcmsmac/dma.c      |  343 ++-
+ drivers/net/wireless/brcm80211/brcmsmac/dma.h      |   11 +-
+ .../net/wireless/brcm80211/brcmsmac/mac80211_if.c  |  123 +-
+ drivers/net/wireless/brcm80211/brcmsmac/main.c     | 1195 +++-------
+ drivers/net/wireless/brcm80211/brcmsmac/main.h     |   48 +-
+ drivers/net/wireless/brcm80211/brcmsmac/pub.h      |   37 -
+ drivers/net/wireless/brcm80211/brcmsmac/stf.c      |    8 +-
+ drivers/net/wireless/brcm80211/brcmsmac/types.h    |    3 +-
+ drivers/net/wireless/brcm80211/include/defs.h      |   11 +-
+ drivers/net/wireless/ipw2x00/ipw2100.c             |    5 +-
+ drivers/net/wireless/ipw2x00/ipw2200.c             |   40 +-
+ drivers/net/wireless/ipw2x00/libipw.h              |    2 +-
+ drivers/net/wireless/ipw2x00/libipw_geo.c          |    3 +-
+ drivers/net/wireless/iwlegacy/3945.c               |    2 +-
+ drivers/net/wireless/iwlegacy/4965-mac.c           |    4 +-
+ drivers/net/wireless/iwlegacy/common.h             |    5 +-
+ drivers/net/wireless/iwlwifi/Kconfig               |    9 -
+ drivers/net/wireless/iwlwifi/dvm/agn.h             |    4 +-
+ drivers/net/wireless/iwlwifi/dvm/commands.h        |    7 +-
+ drivers/net/wireless/iwlwifi/dvm/debugfs.c         |    2 +-
+ drivers/net/wireless/iwlwifi/dvm/dev.h             |    1 -
+ drivers/net/wireless/iwlwifi/dvm/lib.c             |   37 +-
+ drivers/net/wireless/iwlwifi/dvm/mac80211.c        |   16 +-
+ drivers/net/wireless/iwlwifi/dvm/main.c            |   20 +-
+ drivers/net/wireless/iwlwifi/dvm/rx.c              |    6 +-
+ drivers/net/wireless/iwlwifi/dvm/tx.c              |    9 +-
+ drivers/net/wireless/iwlwifi/dvm/ucode.c           |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-config.h          |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-devtrace.h        |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c    |    4 +-
+ drivers/net/wireless/iwlwifi/iwl-fh.h              |    2 +-
+ drivers/net/wireless/iwlwifi/iwl-trans.h           |   27 +-
+ drivers/net/wireless/iwlwifi/pcie/drv.c            |    1 -
+ drivers/net/wireless/iwlwifi/pcie/internal.h       |  117 +-
+ drivers/net/wireless/iwlwifi/pcie/rx.c             |  396 +++-
+ drivers/net/wireless/iwlwifi/pcie/trans.c          | 1047 +--------
+ drivers/net/wireless/iwlwifi/pcie/tx.c             | 1263 ++++++++---
+ drivers/net/wireless/libertas/cfg.c                |   24 +-
+ drivers/net/wireless/libertas/if_sdio.c            |   39 +-
+ drivers/net/wireless/mac80211_hwsim.c              |  580 ++++-
+ drivers/net/wireless/mwifiex/11n_aggr.c            |    8 +-
+ drivers/net/wireless/mwifiex/Kconfig               |    1 -
+ drivers/net/wireless/mwifiex/cfg80211.c            |   54 +-
+ drivers/net/wireless/mwifiex/cmdevt.c              |    3 +
+ drivers/net/wireless/mwifiex/debugfs.c             |   10 +-
+ drivers/net/wireless/mwifiex/init.c                |   20 +-
+ drivers/net/wireless/mwifiex/join.c                |    6 +-
+ drivers/net/wireless/mwifiex/main.c                |   86 +-
+ drivers/net/wireless/mwifiex/main.h                |    6 +-
+ drivers/net/wireless/mwifiex/sdio.c                |   39 +-
+ drivers/net/wireless/mwifiex/sdio.h                |    1 +
+ drivers/net/wireless/mwifiex/sta_event.c           |   10 +-
+ drivers/net/wireless/mwifiex/sta_ioctl.c           |    9 +-
+ drivers/net/wireless/mwifiex/txrx.c                |   28 +-
+ drivers/net/wireless/mwifiex/uap_event.c           |    7 +
+ drivers/net/wireless/mwifiex/usb.c                 |    2 +-
+ drivers/net/wireless/mwifiex/wmm.c                 |   12 +-
+ drivers/net/wireless/mwifiex/wmm.h                 |    2 +
+ drivers/net/wireless/mwl8k.c                       |   57 +-
+ drivers/net/wireless/orinoco/cfg.c                 |   11 +-
+ drivers/net/wireless/p54/txrx.c                    |    6 +-
+ drivers/net/wireless/rndis_wlan.c                  |   12 +-
+ drivers/net/wireless/rt2x00/rt2800usb.c            |    1 +
+ drivers/net/wireless/rt2x00/rt2x00dev.c            |   19 +-
+ drivers/net/wireless/rt2x00/rt2x00mac.c            |    6 +-
+ drivers/net/wireless/rtl818x/rtl8180/dev.c         |    2 +-
+ drivers/net/wireless/rtl818x/rtl8187/dev.c         |    2 +-
+ drivers/net/wireless/rtlwifi/Kconfig               |   11 +
+ drivers/net/wireless/rtlwifi/Makefile              |    4 +-
+ drivers/net/wireless/rtlwifi/base.c                |   24 +
+ drivers/net/wireless/rtlwifi/base.h                |    2 +
+ drivers/net/wireless/rtlwifi/cam.c                 |    2 +-
+ drivers/net/wireless/rtlwifi/core.c                |    5 +-
+ drivers/net/wireless/rtlwifi/debug.h               |    2 +
+ drivers/net/wireless/rtlwifi/pci.c                 |   20 +-
+ drivers/net/wireless/rtlwifi/pci.h                 |    2 +
+ drivers/net/wireless/rtlwifi/rc.c                  |    3 +-
+ drivers/net/wireless/rtlwifi/rtl8192ce/trx.c       |    2 +-
+ drivers/net/wireless/rtlwifi/rtl8192cu/trx.c       |    2 +-
+ drivers/net/wireless/rtlwifi/rtl8192de/trx.c       |    2 +-
+ drivers/net/wireless/rtlwifi/rtl8192se/trx.c       |    2 +-
+ drivers/net/wireless/rtlwifi/rtl8723ae/Makefile    |   22 +
+ drivers/net/wireless/rtlwifi/rtl8723ae/btc.h       |   41 +
+ drivers/net/wireless/rtlwifi/rtl8723ae/def.h       |  163 ++
+ drivers/net/wireless/rtlwifi/rtl8723ae/dm.c        |  920 ++++++++
+ drivers/net/wireless/rtlwifi/rtl8723ae/dm.h        |  149 ++
+ drivers/net/wireless/rtlwifi/rtl8723ae/fw.c        |  745 ++++++
+ drivers/net/wireless/rtlwifi/rtl8723ae/fw.h        |  101 +
+ .../wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c    |  542 +++++
+ .../wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h    |  160 ++
+ drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c   | 1786 +++++++++++++++
+ drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h   |  151 ++
+ drivers/net/wireless/rtlwifi/rtl8723ae/hw.c        | 2380 ++++++++++++++++++++
+ drivers/net/wireless/rtlwifi/rtl8723ae/hw.h        |   73 +
+ drivers/net/wireless/rtlwifi/rtl8723ae/led.c       |  151 ++
+ drivers/net/wireless/rtlwifi/rtl8723ae/led.h       |   39 +
+ drivers/net/wireless/rtlwifi/rtl8723ae/phy.c       | 2044 +++++++++++++++++
+ drivers/net/wireless/rtlwifi/rtl8723ae/phy.h       |  224 ++
+ drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c    |  109 +
+ drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h    |  322 +++
+ drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.c |  129 ++
+ drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.h |   98 +
+ drivers/net/wireless/rtlwifi/rtl8723ae/reg.h       | 2097 +++++++++++++++++
+ drivers/net/wireless/rtlwifi/rtl8723ae/rf.c        |  505 +++++
+ drivers/net/wireless/rtlwifi/rtl8723ae/rf.h        |   43 +
+ drivers/net/wireless/rtlwifi/rtl8723ae/sw.c        |  387 ++++
+ drivers/net/wireless/rtlwifi/rtl8723ae/sw.h        |   37 +
+ drivers/net/wireless/rtlwifi/rtl8723ae/table.c     |  738 ++++++
+ drivers/net/wireless/rtlwifi/rtl8723ae/table.h     |   50 +
+ drivers/net/wireless/rtlwifi/rtl8723ae/trx.c       |  670 ++++++
+ drivers/net/wireless/rtlwifi/rtl8723ae/trx.h       |  725 ++++++
+ drivers/net/wireless/rtlwifi/stats.c               |  268 +++
+ drivers/net/wireless/rtlwifi/stats.h               |   46 +
+ drivers/net/wireless/rtlwifi/wifi.h                |  108 +-
+ drivers/net/wireless/ti/wl1251/rx.c                |    2 +-
+ drivers/net/wireless/ti/wlcore/main.c              |   11 +-
+ drivers/nfc/pn544/i2c.c                            |    2 +-
+ include/linux/bcma/bcma.h                          |    5 +
+ include/linux/ieee80211.h                          |   72 +
+ include/linux/nfc/pn544.h                          |  104 -
+ include/linux/platform_data/pn544.h                |   44 +
+ include/linux/ssb/ssb_regs.h                       |    2 +-
+ include/net/bluetooth/amp.h                        |    4 +
+ include/net/bluetooth/hci.h                        |   29 +-
+ include/net/bluetooth/hci_core.h                   |   48 +-
+ include/net/bluetooth/l2cap.h                      |   38 +-
+ include/net/cfg80211.h                             |  223 +-
+ include/net/mac80211.h                             |  158 +-
+ include/net/nfc/hci.h                              |    3 +
+ include/uapi/linux/nl80211.h                       |  113 +-
+ net/bluetooth/Kconfig                              |    1 -
+ net/bluetooth/a2mp.c                               |    4 +-
+ net/bluetooth/amp.c                                |   97 +
+ net/bluetooth/bnep/netdev.c                        |    1 -
+ net/bluetooth/cmtp/capi.c                          |    2 +-
+ net/bluetooth/cmtp/sock.c                          |    2 +-
+ net/bluetooth/hci_conn.c                           |    6 +
+ net/bluetooth/hci_core.c                           |  163 +-
+ net/bluetooth/hci_event.c                          |  351 ++-
+ net/bluetooth/l2cap_core.c                         | 1010 ++++++++-
+ net/bluetooth/l2cap_sock.c                         |    5 +
+ net/bluetooth/mgmt.c                               |  100 +-
+ net/mac80211/aes_cmac.c                            |    1 +
+ net/mac80211/agg-rx.c                              |    2 +-
+ net/mac80211/agg-tx.c                              |   12 +-
+ net/mac80211/cfg.c                                 |  258 ++-
+ net/mac80211/chan.c                                |  130 +-
+ net/mac80211/debugfs_key.c                         |    6 +-
+ net/mac80211/debugfs_netdev.c                      |   68 +-
+ net/mac80211/debugfs_sta.c                         |   19 +-
+ net/mac80211/driver-ops.h                          |   75 +-
+ net/mac80211/ht.c                                  |    4 +-
+ net/mac80211/ibss.c                                |   75 +-
+ net/mac80211/ieee80211_i.h                         |   50 +-
+ net/mac80211/iface.c                               |   60 +-
+ net/mac80211/key.c                                 |   15 +-
+ net/mac80211/key.h                                 |    8 +-
+ net/mac80211/main.c                                |   50 +-
+ net/mac80211/mesh.c                                |   36 +-
+ net/mac80211/mesh.h                                |   14 -
+ net/mac80211/mesh_plink.c                          |   47 +-
+ net/mac80211/mesh_sync.c                           |   46 +-
+ net/mac80211/mlme.c                                |  198 +-
+ net/mac80211/offchannel.c                          |   13 +-
+ net/mac80211/pm.c                                  |   48 +-
+ net/mac80211/rate.c                                |    5 +-
+ net/mac80211/rate.h                                |    2 +-
+ net/mac80211/rx.c                                  |  169 +-
+ net/mac80211/scan.c                                |    9 +-
+ net/mac80211/sta_info.c                            |   12 +-
+ net/mac80211/sta_info.h                            |   27 +-
+ net/mac80211/status.c                              |  145 +-
+ net/mac80211/trace.h                               |  116 +-
+ net/mac80211/tx.c                                  |   21 +-
+ net/mac80211/util.c                                |  194 +-
+ net/mac80211/wme.c                                 |   40 +-
+ net/nfc/hci/command.c                              |    4 +-
+ net/nfc/hci/core.c                                 |   25 +-
+ net/nfc/llcp/commands.c                            |   32 +-
+ net/nfc/llcp/llcp.c                                |   17 +-
+ net/wireless/Kconfig                               |    5 +-
+ net/wireless/ap.c                                  |    1 +
+ net/wireless/chan.c                                |  280 ++-
+ net/wireless/core.c                                |    7 +
+ net/wireless/core.h                                |   30 +-
+ net/wireless/ibss.c                                |   27 +-
+ net/wireless/mesh.c                                |   49 +-
+ net/wireless/mlme.c                                |   36 +-
+ net/wireless/nl80211.c                             |  590 +++--
+ net/wireless/nl80211.h                             |    8 +-
+ net/wireless/rdev-ops.h                            |   53 +-
+ net/wireless/scan.c                                |   45 +-
+ net/wireless/trace.h                               |  338 +--
+ net/wireless/util.c                                |  174 +-
+ net/wireless/wext-compat.c                         |   32 +-
+ net/wireless/wext-sme.c                            |   11 +-
+ 289 files changed, 27506 insertions(+), 8374 deletions(-)
+ create mode 100644 drivers/net/wireless/ath/ath6kl/recovery.c
+ create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+ create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/fweh.h
+ create mode 100644 drivers/net/wireless/brcm80211/brcmsmac/debug.c
+ create mode 100644 drivers/net/wireless/brcm80211/brcmsmac/debug.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/Makefile
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/btc.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/def.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/dm.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/dm.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/fw.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/fw.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/hw.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/led.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/led.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/phy.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/phy.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/reg.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/rf.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/rf.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/sw.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/sw.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/table.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/table.h
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
+ create mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/trx.h
+ create mode 100644 drivers/net/wireless/rtlwifi/stats.c
+ create mode 100644 drivers/net/wireless/rtlwifi/stats.h
+ delete mode 100644 include/linux/nfc/pn544.h
+ create mode 100644 include/linux/platform_data/pn544.h
+Merging bluetooth/master (a0110f4 Bluetooth: Move double negation to macros)
+$ git merge bluetooth/master
+Auto-merging net/bluetooth/mgmt.c
+Auto-merging net/bluetooth/hci_core.c
+Merge made by the 'recursive' strategy.
+ include/net/bluetooth/hci_core.h |   15 +++++----
+ net/bluetooth/hci_core.c         |    2 ++
+ net/bluetooth/hci_event.c        |   56 +++++++++++++++++++++++++++----
+ net/bluetooth/mgmt.c             |   10 +++---
+ net/bluetooth/rfcomm/sock.c      |    2 +-
+ net/bluetooth/sco.c              |   67 ++++++++++++++++++++++++++++++++++++--
+ 6 files changed, 131 insertions(+), 21 deletions(-)
+Merging mtd/master (35f95d2 Merge tag 'for-linus-20121123' of git://git.infradead.org/mtd-2.6)
+$ git merge mtd/master
+Already up-to-date.
+Merging l2-mtd/master (0f722de mtd: m25p80: modify info for Micron N25Q128)
+$ git merge l2-mtd/master
+Removing include/linux/platform_data/mtd-nomadik-nand.h
+Removing include/linux/mtd/gpmi-nand.h
+Auto-merging include/linux/bcma/bcma.h
+Auto-merging drivers/mtd/ofpart.c
+Removing drivers/mtd/nand/nomadik_nand.c
+Removing drivers/mtd/maps/fortunet.c
+Auto-merging drivers/bcma/driver_chipcommon_pmu.c
+Removing arch/arm/mach-nomadik/include/mach/fsmc.h
+Auto-merging arch/arm/boot/dts/spear13xx.dtsi
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/arm/davinci/nand.txt       |    8 +
+ .../devicetree/bindings/mtd/denali-nand.txt        |   23 ++
+ .../devicetree/bindings/mtd/flctl-nand.txt         |   49 +++
+ .../devicetree/bindings/mtd/fsmc-nand.txt          |   12 +-
+ Documentation/devicetree/bindings/mtd/m25p80.txt   |   29 ++
+ .../devicetree/bindings/mtd/mtd-physmap.txt        |    3 +
+ arch/arm/boot/dts/spear13xx.dtsi                   |   10 +-
+ arch/arm/boot/dts/spear300.dtsi                    |    8 +-
+ arch/arm/boot/dts/spear310.dtsi                    |    8 +-
+ arch/arm/boot/dts/spear320.dtsi                    |    8 +-
+ arch/arm/boot/dts/spear600.dtsi                    |    8 +-
+ arch/arm/configs/nhk8815_defconfig                 |    2 +-
+ arch/arm/mach-nomadik/board-nhk8815.c              |   73 ++---
+ arch/arm/mach-nomadik/include/mach/fsmc.h          |   29 --
+ arch/arm/mach-u300/core.c                          |   14 +-
+ drivers/bcma/driver_chipcommon_pmu.c               |    3 +-
+ drivers/clk/clk-nomadik.c                          |    1 +
+ drivers/mtd/ar7part.c                              |    7 +-
+ drivers/mtd/bcm63xxpart.c                          |   32 +-
+ drivers/mtd/cmdlinepart.c                          |   91 +++---
+ drivers/mtd/devices/bcm47xxsflash.c                |    4 +-
+ drivers/mtd/devices/block2mtd.c                    |    2 +-
+ drivers/mtd/devices/docprobe.c                     |    2 -
+ drivers/mtd/devices/m25p80.c                       |   48 +--
+ drivers/mtd/devices/mtd_dataflash.c                |   14 +-
+ drivers/mtd/devices/spear_smi.c                    |   23 +-
+ drivers/mtd/devices/sst25l.c                       |   10 +-
+ drivers/mtd/maps/Kconfig                           |    7 -
+ drivers/mtd/maps/Makefile                          |    1 -
+ drivers/mtd/maps/amd76xrom.c                       |    7 +-
+ drivers/mtd/maps/autcpu12-nvram.c                  |    6 +-
+ drivers/mtd/maps/bfin-async-flash.c                |    9 +-
+ drivers/mtd/maps/ck804xrom.c                       |    6 +-
+ drivers/mtd/maps/esb2rom.c                         |    6 +-
+ drivers/mtd/maps/fortunet.c                        |  277 -----------------
+ drivers/mtd/maps/gpio-addr-flash.c                 |   12 +-
+ drivers/mtd/maps/ichxrom.c                         |    8 +-
+ drivers/mtd/maps/intel_vr_nor.c                    |   18 +-
+ drivers/mtd/maps/lantiq-flash.c                    |    8 +-
+ drivers/mtd/maps/latch-addr-flash.c                |    4 +-
+ drivers/mtd/maps/pci.c                             |    6 +-
+ drivers/mtd/maps/physmap_of.c                      |   13 +-
+ drivers/mtd/maps/pismo.c                           |   18 +-
+ drivers/mtd/maps/pxa2xx-flash.c                    |    6 +-
+ drivers/mtd/maps/sa1100-flash.c                    |    6 +-
+ drivers/mtd/maps/scb2_flash.c                      |    8 +-
+ drivers/mtd/maps/sun_uflash.c                      |    6 +-
+ drivers/mtd/maps/vmu-flash.c                       |   10 +-
+ drivers/mtd/mtd_blkdevs.c                          |   51 ++--
+ drivers/mtd/mtdoops.c                              |   15 +-
+ drivers/mtd/nand/Kconfig                           |   35 ++-
+ drivers/mtd/nand/Makefile                          |    4 +-
+ drivers/mtd/nand/ams-delta.c                       |    6 +-
+ drivers/mtd/nand/atmel_nand.c                      |   12 +-
+ drivers/mtd/nand/au1550nd.c                        |    8 +-
+ drivers/mtd/nand/bcm47xxnflash/Makefile            |    4 +
+ drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h     |   22 ++
+ drivers/mtd/nand/bcm47xxnflash/main.c              |  108 +++++++
+ drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c       |  316 ++++++++++++++++++++
+ drivers/mtd/nand/bf5xx_nand.c                      |    8 +-
+ drivers/mtd/nand/cafe_nand.c                       |   12 +-
+ drivers/mtd/nand/cs553x_nand.c                     |    3 +-
+ drivers/mtd/nand/davinci_nand.c                    |   13 +-
+ drivers/mtd/nand/denali.c                          |  162 ++--------
+ drivers/mtd/nand/denali.h                          |    5 +
+ drivers/mtd/nand/denali_dt.c                       |  167 +++++++++++
+ drivers/mtd/nand/denali_pci.c                      |  144 +++++++++
+ drivers/mtd/nand/diskonchip.c                      |    2 -
+ drivers/mtd/nand/fsl_elbc_nand.c                   |   17 +-
+ drivers/mtd/nand/fsl_ifc_nand.c                    |    6 +-
+ drivers/mtd/nand/fsl_upm.c                         |    8 +-
+ drivers/mtd/nand/fsmc_nand.c                       |  106 +++----
+ drivers/mtd/nand/gpio.c                            |   26 +-
+ drivers/mtd/nand/gpmi-nand/gpmi-lib.c              |    1 -
+ drivers/mtd/nand/gpmi-nand/gpmi-nand.c             |   41 +--
+ drivers/mtd/nand/gpmi-nand/gpmi-nand.h             |    1 -
+ drivers/mtd/nand/jz4740_nand.c                     |   14 +-
+ drivers/mtd/nand/lpc32xx_mlc.c                     |    6 +-
+ drivers/mtd/nand/lpc32xx_slc.c                     |    6 +-
+ drivers/mtd/nand/mpc5121_nfc.c                     |    8 +-
+ drivers/mtd/nand/mxc_nand.c                        |    6 +-
+ drivers/mtd/nand/nand_base.c                       |   18 +-
+ drivers/mtd/nand/ndfc.c                            |    6 +-
+ drivers/mtd/nand/nomadik_nand.c                    |  235 ---------------
+ drivers/mtd/nand/nuc900_nand.c                     |    6 +-
+ drivers/mtd/nand/omap2.c                           |    2 +-
+ drivers/mtd/nand/orion_nand.c                      |    4 +-
+ drivers/mtd/nand/pasemi_nand.c                     |    4 +-
+ drivers/mtd/nand/plat_nand.c                       |    6 +-
+ drivers/mtd/nand/s3c2410.c                         |    7 +-
+ drivers/mtd/nand/sh_flctl.c                        |  306 +++++++++++++++++--
+ drivers/mtd/nand/sharpsl.c                         |    6 +-
+ drivers/mtd/nand/socrates_nand.c                   |    6 +-
+ drivers/mtd/ofpart.c                               |    5 +-
+ drivers/mtd/onenand/generic.c                      |    6 +-
+ drivers/mtd/onenand/omap2.c                        |    6 +-
+ drivers/mtd/onenand/samsung.c                      |    4 +-
+ drivers/mtd/tests/mtd_nandbiterrs.c                |   73 ++---
+ drivers/mtd/tests/mtd_nandecctest.c                |    6 +-
+ drivers/mtd/tests/mtd_oobtest.c                    |  171 ++++++-----
+ drivers/mtd/tests/mtd_pagetest.c                   |  152 +++++-----
+ drivers/mtd/tests/mtd_readtest.c                   |   42 +--
+ drivers/mtd/tests/mtd_speedtest.c                  |   88 +++---
+ drivers/mtd/tests/mtd_stresstest.c                 |   44 +--
+ drivers/mtd/tests/mtd_subpagetest.c                |  124 ++++----
+ drivers/mtd/tests/mtd_torturetest.c                |   73 ++---
+ fs/jffs2/nodemgmt.c                                |    6 +-
+ include/linux/bcma/bcma.h                          |    1 +
+ include/linux/mtd/blktrans.h                       |    4 +-
+ include/linux/mtd/doc2000.h                        |   22 +-
+ include/linux/mtd/fsmc.h                           |    3 -
+ include/linux/mtd/gpmi-nand.h                      |   68 -----
+ include/linux/mtd/map.h                            |    4 +-
+ include/linux/mtd/mtd.h                            |    2 +-
+ include/linux/mtd/nand.h                           |    4 +-
+ include/linux/mtd/sh_flctl.h                       |   14 +-
+ include/linux/platform_data/mtd-nomadik-nand.h     |   16 -
+ 117 files changed, 2141 insertions(+), 1709 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/mtd/denali-nand.txt
+ create mode 100644 Documentation/devicetree/bindings/mtd/flctl-nand.txt
+ create mode 100644 Documentation/devicetree/bindings/mtd/m25p80.txt
+ delete mode 100644 arch/arm/mach-nomadik/include/mach/fsmc.h
+ delete mode 100644 drivers/mtd/maps/fortunet.c
+ create mode 100644 drivers/mtd/nand/bcm47xxnflash/Makefile
+ create mode 100644 drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
+ create mode 100644 drivers/mtd/nand/bcm47xxnflash/main.c
+ create mode 100644 drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
+ create mode 100644 drivers/mtd/nand/denali_dt.c
+ create mode 100644 drivers/mtd/nand/denali_pci.c
+ delete mode 100644 drivers/mtd/nand/nomadik_nand.c
+ delete mode 100644 include/linux/mtd/gpmi-nand.h
+ delete mode 100644 include/linux/platform_data/mtd-nomadik-nand.h
+Merging crypto/master (a465348 crypto: s5p-sss - Fix compilation error)
+$ git merge crypto/master
+Auto-merging arch/x86/crypto/crc32c-intel_glue.c
+Merge made by the 'recursive' strategy.
+ arch/x86/crypto/Makefile                           |    5 +
+ arch/x86/crypto/camellia-aesni-avx-asm_64.S        | 1102 ++++
+ arch/x86/crypto/camellia_aesni_avx_glue.c          |  558 ++
+ arch/x86/crypto/camellia_glue.c                    |   92 +-
+ arch/x86/crypto/cast5-avx-x86_64-asm_64.S          |  332 +-
+ arch/x86/crypto/cast5_avx_glue.c                   |   79 +-
+ arch/x86/crypto/cast6-avx-x86_64-asm_64.S          |  190 +-
+ arch/x86/crypto/cast6_avx_glue.c                   |   77 +-
+ .../crypto/{crc32c-intel.c => crc32c-intel_glue.c} |   81 +
+ arch/x86/crypto/crc32c-pcl-intel-asm_64.S          |  460 ++
+ arch/x86/crypto/glue_helper-asm-avx.S              |   91 +
+ arch/x86/crypto/glue_helper.c                      |   12 +-
+ arch/x86/crypto/serpent-avx-x86_64-asm_64.S        |  166 +-
+ arch/x86/crypto/serpent_avx_glue.c                 |   49 +-
+ arch/x86/crypto/serpent_sse2_glue.c                |   12 +-
+ arch/x86/crypto/twofish-avx-x86_64-asm_64.S        |  208 +-
+ arch/x86/crypto/twofish_avx_glue.c                 |   73 +-
+ arch/x86/crypto/twofish_glue_3way.c                |   20 +-
+ arch/x86/include/asm/crypto/camellia.h             |   82 +
+ arch/x86/include/asm/crypto/glue_helper.h          |   28 +-
+ arch/x86/include/asm/crypto/serpent-avx.h          |   27 +-
+ arch/x86/include/asm/crypto/twofish.h              |    4 +-
+ crypto/Kconfig                                     |   32 +
+ crypto/tcrypt.c                                    |   29 +
+ crypto/testmgr.c                                   |   92 +
+ crypto/testmgr.h                                   | 5641 +++++++++++++++++++-
+ crypto/vmac.c                                      |   47 +-
+ drivers/crypto/Kconfig                             |    1 +
+ drivers/crypto/picoxcell_crypto.c                  |    1 +
+ drivers/crypto/s5p-sss.c                           |    2 +-
+ drivers/crypto/talitos.c                           |    3 +-
+ drivers/crypto/tegra-aes.c                         |   10 +-
+ include/crypto/vmac.h                              |    2 +
+ 33 files changed, 8833 insertions(+), 775 deletions(-)
+ create mode 100644 arch/x86/crypto/camellia-aesni-avx-asm_64.S
+ create mode 100644 arch/x86/crypto/camellia_aesni_avx_glue.c
+ rename arch/x86/crypto/{crc32c-intel.c => crc32c-intel_glue.c} (69%)
+ create mode 100644 arch/x86/crypto/crc32c-pcl-intel-asm_64.S
+ create mode 100644 arch/x86/crypto/glue_helper-asm-avx.S
+ create mode 100644 arch/x86/include/asm/crypto/camellia.h
+Merging drm/drm-next (28164fd drm/doc: add new dp helpers into drm DocBook)
+$ git merge drm/drm-next
+Auto-merging drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+Auto-merging drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+Auto-merging drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
+Auto-merging drivers/gpu/drm/nouveau/nouveau_drm.c
+Auto-merging drivers/gpu/drm/i915/intel_sdvo.c
+Auto-merging drivers/gpu/drm/i915/intel_display.c
+Auto-merging drivers/gpu/drm/i915/intel_crt.c
+Auto-merging drivers/gpu/drm/drm_dp_helper.c
+Merge made by the 'recursive' strategy.
+ Documentation/DocBook/drm.tmpl                     |   39 +-
+ .../bindings/gpu/nvidia,tegra20-host1x.txt         |  191 ++
+ Documentation/kref.txt                             |   88 +
+ drivers/char/agp/intel-agp.h                       |   91 -
+ drivers/char/agp/intel-gtt.c                       |  320 +--
+ drivers/gpu/drm/Kconfig                            |    2 +
+ drivers/gpu/drm/Makefile                           |    6 +-
+ drivers/gpu/drm/ast/ast_ttm.c                      |    2 +-
+ drivers/gpu/drm/cirrus/cirrus_drv.c                |   13 +-
+ drivers/gpu/drm/cirrus/cirrus_ttm.c                |    2 +-
+ drivers/gpu/drm/drm_crtc.c                         |   32 +-
+ drivers/gpu/drm/drm_crtc_helper.c                  |  161 +-
+ .../drm/{drm_dp_i2c_helper.c => drm_dp_helper.c}   |  146 +-
+ drivers/gpu/drm/drm_edid.c                         |   29 +-
+ drivers/gpu/drm/drm_fb_helper.c                    |   74 +-
+ drivers/gpu/drm/drm_hashtab.c                      |   38 +-
+ drivers/gpu/drm/drm_ioctl.c                        |    3 +
+ drivers/gpu/drm/drm_irq.c                          |  117 +-
+ drivers/gpu/drm/drm_modes.c                        |    8 +-
+ drivers/gpu/drm/drm_stub.c                         |   37 +-
+ drivers/gpu/drm/gma500/mdfld_dsi_output.c          |    2 +-
+ drivers/gpu/drm/gma500/oaktrail.h                  |    6 +
+ drivers/gpu/drm/gma500/oaktrail_crtc.c             |    8 +
+ drivers/gpu/drm/gma500/oaktrail_device.c           |    2 +-
+ drivers/gpu/drm/gma500/oaktrail_hdmi.c             |  365 +++-
+ drivers/gpu/drm/i915/i915_debugfs.c                |   52 +-
+ drivers/gpu/drm/i915/i915_dma.c                    |   86 +-
+ drivers/gpu/drm/i915/i915_drv.c                    |  105 +-
+ drivers/gpu/drm/i915/i915_drv.h                    |  443 ++--
+ drivers/gpu/drm/i915/i915_gem.c                    |   94 +-
+ drivers/gpu/drm/i915/i915_gem_context.c            |    2 +-
+ drivers/gpu/drm/i915/i915_gem_execbuffer.c         |   27 +-
+ drivers/gpu/drm/i915/i915_gem_gtt.c                |  418 +++-
+ drivers/gpu/drm/i915/i915_irq.c                    |   80 +-
+ drivers/gpu/drm/i915/i915_reg.h                    |  293 ++-
+ drivers/gpu/drm/i915/i915_suspend.c                |  763 +++----
+ drivers/gpu/drm/i915/i915_sysfs.c                  |   43 +-
+ drivers/gpu/drm/i915/i915_trace.h                  |   10 +-
+ drivers/gpu/drm/i915/intel_crt.c                   |   47 +-
+ drivers/gpu/drm/i915/intel_ddi.c                   | 1063 ++++++++--
+ drivers/gpu/drm/i915/intel_display.c               | 1592 +++++++++++----
+ drivers/gpu/drm/i915/intel_dp.c                    |  959 +++++----
+ drivers/gpu/drm/i915/intel_drv.h                   |  113 +-
+ drivers/gpu/drm/i915/intel_hdmi.c                  |  131 +-
+ drivers/gpu/drm/i915/intel_i2c.c                   |    9 +-
+ drivers/gpu/drm/i915/intel_lvds.c                  |  215 +-
+ drivers/gpu/drm/i915/intel_modes.c                 |    7 +-
+ drivers/gpu/drm/i915/intel_opregion.c              |    2 +
+ drivers/gpu/drm/i915/intel_panel.c                 |   52 +-
+ drivers/gpu/drm/i915/intel_pm.c                    |  464 +++--
+ drivers/gpu/drm/i915/intel_ringbuffer.c            |  119 +-
+ drivers/gpu/drm/i915/intel_ringbuffer.h            |    6 +-
+ drivers/gpu/drm/i915/intel_sdvo.c                  |   33 +-
+ drivers/gpu/drm/i915/intel_sprite.c                |  101 +-
+ drivers/gpu/drm/i915/intel_tv.c                    |    7 +-
+ drivers/gpu/drm/mgag200/mgag200_main.c             |    4 +-
+ drivers/gpu/drm/mgag200/mgag200_ttm.c              |    2 +-
+ drivers/gpu/drm/nouveau/nouveau_bo.c               |   10 +-
+ drivers/gpu/drm/nouveau/nouveau_drm.c              |    1 +
+ drivers/gpu/drm/radeon/atombios_dp.c               |  149 +-
+ drivers/gpu/drm/radeon/r600.c                      |    8 +-
+ drivers/gpu/drm/radeon/r600_cp.c                   |    7 +-
+ drivers/gpu/drm/radeon/radeon_drv.c                |   13 +-
+ drivers/gpu/drm/radeon/radeon_gart.c               |    2 +-
+ drivers/gpu/drm/radeon/radeon_mode.h               |    2 +-
+ drivers/gpu/drm/radeon/radeon_object.c             |    8 +-
+ drivers/gpu/drm/radeon/radeon_object.h             |    2 +-
+ drivers/gpu/drm/radeon/radeon_ttm.c                |    9 +-
+ drivers/gpu/drm/tegra/Kconfig                      |   23 +
+ drivers/gpu/drm/tegra/Makefile                     |    7 +
+ drivers/gpu/drm/tegra/dc.c                         |  834 ++++++++
+ drivers/gpu/drm/tegra/dc.h                         |  388 ++++
+ drivers/gpu/drm/tegra/drm.c                        |  115 ++
+ drivers/gpu/drm/tegra/drm.h                        |  234 +++
+ drivers/gpu/drm/tegra/fb.c                         |   56 +
+ drivers/gpu/drm/tegra/hdmi.c                       | 1334 +++++++++++++
+ drivers/gpu/drm/tegra/hdmi.h                       |  575 ++++++
+ drivers/gpu/drm/tegra/host1x.c                     |  325 +++
+ drivers/gpu/drm/tegra/output.c                     |  272 +++
+ drivers/gpu/drm/tegra/rgb.c                        |  228 +++
+ drivers/gpu/drm/ttm/ttm_bo.c                       |   55 +-
+ drivers/gpu/drm/ttm/ttm_bo_util.c                  |    2 -
+ drivers/gpu/drm/ttm/ttm_bo_vm.c                    |    4 +-
+ drivers/gpu/drm/ttm/ttm_execbuf_util.c             |    6 +-
+ drivers/gpu/drm/ttm/ttm_memory.c                   |    1 -
+ drivers/gpu/drm/ttm/ttm_object.c                   |   51 +-
+ drivers/gpu/drm/udl/udl_connector.c                |   12 +-
+ drivers/gpu/drm/vmwgfx/Makefile                    |    3 +-
+ drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h        |  909 +++++++++
+ drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c             |   23 +-
+ drivers/gpu/drm/vmwgfx/vmwgfx_context.c            |  274 +++
+ drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c             |    9 +-
+ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c                |   92 +-
+ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h                |  153 +-
+ drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c            |  913 ++++++---
+ drivers/gpu/drm/vmwgfx/vmwgfx_fence.c              |    2 +-
+ drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c              |    7 +-
+ drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c            |   21 +-
+ drivers/gpu/drm/vmwgfx/vmwgfx_resource.c           | 2111 +++++++-------------
+ drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h      |   84 +
+ drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c               |    2 +-
+ drivers/gpu/drm/vmwgfx/vmwgfx_surface.c            |  893 +++++++++
+ drivers/gpu/vga/vga_switcheroo.c                   |    6 -
+ include/drm/drmP.h                                 |    3 +
+ include/drm/drm_crtc.h                             |   10 +-
+ include/drm/drm_crtc_helper.h                      |    3 +
+ include/drm/drm_dp_helper.h                        |   39 +
+ include/drm/drm_hashtab.h                          |   14 +
+ include/drm/intel-gtt.h                            |    7 +-
+ include/drm/ttm/ttm_bo_api.h                       |   30 +-
+ include/drm/ttm/ttm_bo_driver.h                    |   26 +-
+ include/drm/ttm/ttm_execbuf_util.h                 |    3 -
+ include/drm/ttm/ttm_memory.h                       |    2 -
+ include/drm/ttm/ttm_object.h                       |    4 +
+ include/linux/kref.h                               |   21 +
+ include/uapi/drm/drm.h                             |    1 +
+ include/uapi/drm/i915_drm.h                        |    6 +
+ 117 files changed, 14414 insertions(+), 5114 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
+ rename drivers/gpu/drm/{drm_dp_i2c_helper.c => drm_dp_helper.c} (58%)
+ create mode 100644 drivers/gpu/drm/tegra/Kconfig
+ create mode 100644 drivers/gpu/drm/tegra/Makefile
+ create mode 100644 drivers/gpu/drm/tegra/dc.c
+ create mode 100644 drivers/gpu/drm/tegra/dc.h
+ create mode 100644 drivers/gpu/drm/tegra/drm.c
+ create mode 100644 drivers/gpu/drm/tegra/drm.h
+ create mode 100644 drivers/gpu/drm/tegra/fb.c
+ create mode 100644 drivers/gpu/drm/tegra/hdmi.c
+ create mode 100644 drivers/gpu/drm/tegra/hdmi.h
+ create mode 100644 drivers/gpu/drm/tegra/host1x.c
+ create mode 100644 drivers/gpu/drm/tegra/output.c
+ create mode 100644 drivers/gpu/drm/tegra/rgb.c
+ create mode 100644 drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h
+ create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_context.c
+ create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h
+ create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+Merging sound/for-next (361dab3 ALSA: hda - Call snd_array_init() early and only once)
+$ git merge sound/for-next
+Auto-merging sound/pci/hda/hda_codec.c
+Merge made by the 'recursive' strategy.
+ Documentation/sound/alsa/ALSA-Configuration.txt |    3 -
+ include/sound/Kbuild                            |   10 -
+ include/sound/asequencer.h                      |  594 +-------------
+ include/sound/asound.h                          |  935 +---------------------
+ include/sound/emu10k1.h                         |  359 +--------
+ include/sound/pcm.h                             |    3 +
+ include/sound/sb16_csp.h                        |  104 +--
+ include/sound/vx_core.h                         |    6 -
+ include/uapi/sound/Kbuild                       |   10 +
+ include/uapi/sound/asequencer.h                 |  614 ++++++++++++++
+ include/uapi/sound/asound.h                     |  971 +++++++++++++++++++++++
+ include/{ => uapi}/sound/asound_fm.h            |    0
+ include/{ => uapi}/sound/compress_offload.h     |    0
+ include/{ => uapi}/sound/compress_params.h      |    0
+ include/uapi/sound/emu10k1.h                    |  373 +++++++++
+ include/{ => uapi}/sound/hdsp.h                 |    0
+ include/{ => uapi}/sound/hdspm.h                |    0
+ include/uapi/sound/sb16_csp.h                   |  122 +++
+ include/{ => uapi}/sound/sfnt_info.h            |    0
+ sound/core/oss/pcm_plugin.c                     |    6 +-
+ sound/core/pcm.c                                |    3 +-
+ sound/core/pcm_compat.c                         |   20 +-
+ sound/core/pcm_lib.c                            |   57 +-
+ sound/core/pcm_native.c                         |    4 +-
+ sound/drivers/Kconfig                           |    2 +-
+ sound/drivers/aloop.c                           |   36 +-
+ sound/drivers/dummy.c                           |   73 +-
+ sound/drivers/vx/vx_hwdep.c                     |  139 ----
+ sound/firewire/Kconfig                          |   13 +
+ sound/firewire/Makefile                         |    2 +
+ sound/firewire/scs1x.c                          |  527 ++++++++++++
+ sound/isa/Kconfig                               |    4 +-
+ sound/oss/sb_audio.c                            |    3 +-
+ sound/pci/Kconfig                               |    5 +-
+ sound/pci/asihpi/hpidspcd.c                     |   22 +-
+ sound/pci/asihpi/hpioctl.c                      |   17 +-
+ sound/pci/au88x0/au88x0_core.c                  |    7 +-
+ sound/pci/emu10k1/emu10k1.c                     |    4 +
+ sound/pci/emu10k1/emu10k1_main.c                |   92 +--
+ sound/pci/hda/Kconfig                           |    5 +-
+ sound/pci/hda/Makefile                          |    1 +
+ sound/pci/hda/hda_codec.c                       |  176 ++--
+ sound/pci/hda/hda_codec.h                       |    6 +
+ sound/pci/hda/hda_intel.c                       |  130 ++-
+ sound/pci/hda/hda_intel_trace.h                 |   62 ++
+ sound/pci/hda/hda_jack.c                        |   93 ++-
+ sound/pci/hda/hda_jack.h                        |    6 +
+ sound/pci/hda/hda_local.h                       |    8 +-
+ sound/pci/hda/patch_analog.c                    |   73 +-
+ sound/pci/hda/patch_cirrus.c                    |   47 +-
+ sound/pci/hda/patch_conexant.c                  |   77 +-
+ sound/pci/hda/patch_hdmi.c                      |   22 +-
+ sound/pci/hda/patch_realtek.c                   |   45 +-
+ sound/pci/hda/patch_sigmatel.c                  |  150 ++--
+ sound/pci/hda/patch_via.c                       |   14 +-
+ sound/pci/ice1712/Makefile                      |    2 +-
+ sound/pci/ice1712/amp.c                         |    1 -
+ sound/pci/ice1712/aureon.c                      |    4 +-
+ sound/pci/ice1712/delta.c                       |    1 -
+ sound/pci/ice1712/ews.c                         |    5 +-
+ sound/pci/ice1712/hoontech.c                    |    1 -
+ sound/pci/ice1712/ice1712.c                     |    9 +-
+ sound/pci/ice1712/ice1712.h                     |   12 +-
+ sound/pci/ice1712/ice1724.c                     |   23 +-
+ sound/pci/ice1712/juli.c                        |    4 +-
+ sound/pci/ice1712/maya44.c                      |    5 +-
+ sound/pci/ice1712/phase.c                       |    3 +-
+ sound/pci/ice1712/pontis.c                      |    1 -
+ sound/pci/ice1712/prodigy192.c                  |    5 +-
+ sound/pci/ice1712/prodigy_hifi.c                |    1 -
+ sound/pci/ice1712/psc724.c                      |  464 +++++++++++
+ sound/pci/ice1712/psc724.h                      |   13 +
+ sound/pci/ice1712/quartet.c                     |   10 +-
+ sound/pci/ice1712/revo.c                        |    1 -
+ sound/pci/ice1712/se.c                          |   11 +-
+ sound/pci/ice1712/vt1720_mobo.c                 |    1 -
+ sound/pci/ice1712/wm8766.c                      |  361 +++++++++
+ sound/pci/ice1712/wm8766.h                      |  163 ++++
+ sound/pci/ice1712/wm8776.c                      |  633 +++++++++++++++
+ sound/pci/ice1712/wm8776.h                      |  226 ++++++
+ sound/pci/ice1712/wtm.c                         |    1 -
+ sound/pci/mixart/mixart_hwdep.c                 |   76 --
+ sound/pci/oxygen/virtuoso.c                     |    1 +
+ sound/pci/oxygen/xonar_wm87x6.c                 |    6 +-
+ sound/pci/pcxhr/pcxhr_hwdep.c                   |   86 --
+ sound/pci/rme9652/hdsp.c                        |   63 +-
+ sound/pci/ymfpci/ymfpci_main.c                  |    6 +-
+ sound/usb/6fire/comm.c                          |    3 +-
+ sound/usb/Kconfig                               |    2 +-
+ sound/usb/card.c                                |    7 -
+ sound/usb/card.h                                |    2 +
+ sound/usb/endpoint.c                            |   44 +-
+ sound/usb/endpoint.h                            |    5 +-
+ sound/usb/format.c                              |   10 +-
+ sound/usb/pcm.c                                 |   54 +-
+ sound/usb/quirks-table.h                        |  127 +++
+ sound/usb/stream.c                              |  230 +++++-
+ sound/usb/usbaudio.h                            |    1 -
+ 98 files changed, 5930 insertions(+), 2809 deletions(-)
+ create mode 100644 include/uapi/sound/asequencer.h
+ create mode 100644 include/uapi/sound/asound.h
+ rename include/{ => uapi}/sound/asound_fm.h (100%)
+ rename include/{ => uapi}/sound/compress_offload.h (100%)
+ rename include/{ => uapi}/sound/compress_params.h (100%)
+ create mode 100644 include/uapi/sound/emu10k1.h
+ rename include/{ => uapi}/sound/hdsp.h (100%)
+ rename include/{ => uapi}/sound/hdspm.h (100%)
+ create mode 100644 include/uapi/sound/sb16_csp.h
+ rename include/{ => uapi}/sound/sfnt_info.h (100%)
+ create mode 100644 sound/firewire/scs1x.c
+ create mode 100644 sound/pci/hda/hda_intel_trace.h
+ create mode 100644 sound/pci/ice1712/psc724.c
+ create mode 100644 sound/pci/ice1712/psc724.h
+ create mode 100644 sound/pci/ice1712/wm8766.c
+ create mode 100644 sound/pci/ice1712/wm8766.h
+ create mode 100644 sound/pci/ice1712/wm8776.c
+ create mode 100644 sound/pci/ice1712/wm8776.h
+Merging sound-asoc/for-next (7728640 Merge branches 'fix/fsl', 'topic/ab8500', 'topic/ak4104', 'topic/ak4535', 'topic/ak4642', 'topic/arizona', 'topic/atmel', 'topic/cs4271', 'topic/da7210', 'topic/da9055', 'topic/davinci', 'topic/dmaengine', 'topic/fsi', 'topic/fsl', 'topic/hotplug', 'topic/jack', 'topic/jz4740', 'topic/kirkwood', 'topic/lm49453', 'topic/log', 'topic/max98090', 'topic/omap', 'topic/rt5631', 'topic/samsung', 'topic/si476x', 'topic/tlv320aic32x4', 'topic/ux500', 'topic/wm0010', 'topic/wm2000', 'topic/wm2200', 'topic/wm8350', 'topic/wm8400', 'topic/wm8510', 'topic/wm8741', 'topic/wm8750', 'topic/wm8753', 'topic/wm8770', 'topic/wm8804', 'topic/wm8962', 'topic/wm8971', 'topic/wm8978', 'topic/wm8985', 'topic/wm8988', 'topic/wm8993', 'topic/wm8994' and 'topic/wm8995' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-next)
+$ git merge sound-asoc/for-next
+Auto-merging drivers/mfd/arizona-core.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/misc/atmel-ssc.txt         |   15 +
+ Documentation/devicetree/bindings/sound/ak4104.txt |   22 +
+ .../sound/atmel-at91sam9g20ek-wm8731-audio.txt     |   26 +
+ Documentation/devicetree/bindings/sound/cs4271.txt |    2 +
+ arch/arm/boot/dts/at91sam9260.dtsi                 |    8 +
+ arch/arm/boot/dts/at91sam9263.dtsi                 |   16 +
+ arch/arm/boot/dts/at91sam9g20ek_common.dtsi        |   32 +-
+ arch/arm/boot/dts/at91sam9g45.dtsi                 |   16 +
+ arch/arm/boot/dts/at91sam9x5.dtsi                  |    8 +
+ arch/arm/mach-at91/at91rm9200.c                    |    9 +-
+ arch/arm/mach-at91/at91rm9200_devices.c            |    6 +-
+ arch/arm/mach-at91/at91sam9260.c                   |    3 +-
+ arch/arm/mach-at91/at91sam9260_devices.c           |    2 +-
+ arch/arm/mach-at91/at91sam9261.c                   |    9 +-
+ arch/arm/mach-at91/at91sam9261_devices.c           |    6 +-
+ arch/arm/mach-at91/at91sam9263.c                   |    6 +-
+ arch/arm/mach-at91/at91sam9263_devices.c           |    4 +-
+ arch/arm/mach-at91/at91sam9g45.c                   |    6 +-
+ arch/arm/mach-at91/at91sam9g45_devices.c           |    4 +-
+ arch/arm/mach-at91/at91sam9rl.c                    |    6 +-
+ arch/arm/mach-at91/at91sam9rl_devices.c            |    4 +-
+ arch/arm/mach-at91/at91sam9x5.c                    |    1 +
+ arch/arm/mach-at91/board-sam9g20ek.c               |   11 +
+ arch/arm/mach-davinci/board-da850-evm.c            |   24 +-
+ drivers/base/regmap/internal.h                     |    2 +
+ drivers/base/regmap/regmap-debugfs.c               |   50 +-
+ drivers/base/regmap/regmap.c                       |  154 +++--
+ drivers/input/misc/Kconfig                         |   10 +
+ drivers/input/misc/Makefile                        |    1 +
+ drivers/input/misc/arizona-haptics.c               |  255 ++++++++
+ drivers/mfd/arizona-core.c                         |    2 +
+ drivers/mfd/wm8994-core.c                          |   35 +-
+ drivers/misc/atmel-ssc.c                           |  135 ++--
+ include/linux/atmel-ssc.h                          |    6 +
+ include/linux/mfd/arizona/core.h                   |    4 +
+ include/linux/mfd/arizona/pdata.h                  |    6 +
+ include/linux/mfd/wm8994/core.h                    |    4 +
+ include/linux/mfd/wm8994/pdata.h                   |    5 +
+ include/linux/platform_data/davinci_asp.h          |    3 +
+ include/linux/regmap.h                             |    6 +-
+ include/sound/cs4271.h                             |    1 +
+ include/sound/sh_fsi.h                             |    6 +
+ include/sound/tlv320aic32x4.h                      |    1 +
+ sound/soc/atmel/Kconfig                            |    3 +-
+ sound/soc/atmel/atmel-pcm.c                        |   23 +-
+ sound/soc/atmel/atmel-pcm.h                        |    3 +
+ sound/soc/atmel/atmel_ssc_dai.c                    |  157 ++---
+ sound/soc/atmel/atmel_ssc_dai.h                    |    3 +-
+ sound/soc/atmel/sam9g20_wm8731.c                   |  116 +++-
+ sound/soc/codecs/Kconfig                           |   16 +
+ sound/soc/codecs/Makefile                          |    6 +
+ sound/soc/codecs/ab8500-codec.c                    |    2 +-
+ sound/soc/codecs/ak4104.c                          |   65 +-
+ sound/soc/codecs/ak4535.c                          |    7 +-
+ sound/soc/codecs/ak4642.c                          |   23 +-
+ sound/soc/codecs/arizona.c                         |   21 +
+ sound/soc/codecs/arizona.h                         |   65 +-
+ sound/soc/codecs/cs4271.c                          |   21 +-
+ sound/soc/codecs/da7210.c                          |   13 +-
+ sound/soc/codecs/da9055.c                          |   43 +-
+ sound/soc/codecs/jz4740.c                          |  142 ++---
+ sound/soc/codecs/lm49453.c                         |   10 +-
+ sound/soc/codecs/max98088.c                        |   14 +-
+ sound/soc/codecs/max98090.c                        |  577 +++++++++++++++++
+ sound/soc/codecs/rt5631.c                          |    2 +-
+ sound/soc/codecs/si476x.c                          |  255 ++++++++
+ sound/soc/codecs/tlv320aic32x4.c                   |   24 +
+ sound/soc/codecs/tlv320aic32x4.h                   |    3 +
+ sound/soc/codecs/wm0010.c                          |  419 +++++++-----
+ sound/soc/codecs/wm2000.c                          |    2 +-
+ sound/soc/codecs/wm2200.c                          |  260 +++++++-
+ sound/soc/codecs/wm5100.c                          |    2 +-
+ sound/soc/codecs/wm5102.c                          |  120 ++--
+ sound/soc/codecs/wm5110.c                          |   49 +-
+ sound/soc/codecs/wm8350.c                          |    4 +-
+ sound/soc/codecs/wm8400.c                          |   14 +-
+ sound/soc/codecs/wm8510.c                          |    3 -
+ sound/soc/codecs/wm8741.c                          |    4 +-
+ sound/soc/codecs/wm8750.c                          |   86 ++-
+ sound/soc/codecs/wm8753.c                          |   33 +-
+ sound/soc/codecs/wm8770.c                          |  217 ++++---
+ sound/soc/codecs/wm8804.c                          |   17 +-
+ sound/soc/codecs/wm8958-dsp2.c                     |   79 +--
+ sound/soc/codecs/wm8962.c                          |    7 +-
+ sound/soc/codecs/wm8971.c                          |   80 ++-
+ sound/soc/codecs/wm8978.c                          |    3 -
+ sound/soc/codecs/wm8985.c                          |   30 +-
+ sound/soc/codecs/wm8988.c                          |   14 +-
+ sound/soc/codecs/wm8993.c                          |    7 +-
+ sound/soc/codecs/wm8994.c                          |  184 +++---
+ sound/soc/codecs/wm8994.h                          |    1 -
+ sound/soc/codecs/wm8995.c                          |   40 +-
+ sound/soc/codecs/wm_adsp.c                         |  664 ++++++++++++++++++++
+ sound/soc/codecs/wm_adsp.h                         |   59 ++
+ sound/soc/codecs/wmfw.h                            |  128 ++++
+ sound/soc/davinci/davinci-evm.c                    |    5 +
+ sound/soc/davinci/davinci-mcasp.c                  |   93 ++-
+ sound/soc/davinci/davinci-mcasp.h                  |    2 +-
+ sound/soc/davinci/davinci-pcm.c                    |   53 +-
+ sound/soc/davinci/davinci-pcm.h                    |    2 +
+ sound/soc/fsl/Kconfig                              |   20 +-
+ sound/soc/fsl/Makefile                             |   14 +-
+ sound/soc/fsl/imx-pcm.c                            |    4 +
+ sound/soc/fsl/imx-sgtl5000.c                       |    1 +
+ sound/soc/fsl/p1022_rdk.c                          |  392 ++++++++++++
+ sound/soc/fsl/pcm030-audio-fabric.c                |    4 +-
+ sound/soc/kirkwood/kirkwood-dma.c                  |   16 +-
+ sound/soc/kirkwood/kirkwood-i2s.c                  |  235 ++++---
+ sound/soc/kirkwood/kirkwood.h                      |   11 +-
+ sound/soc/mxs/mxs-saif.c                           |    2 +
+ sound/soc/omap/mcbsp.c                             |    4 +-
+ sound/soc/omap/mcbsp.h                             |    6 +
+ sound/soc/omap/omap-mcbsp.c                        |    5 +-
+ sound/soc/samsung/ac97.c                           |    6 +-
+ sound/soc/samsung/bells.c                          |  222 +++++--
+ sound/soc/samsung/i2s.c                            |    8 +-
+ sound/soc/samsung/pcm.c                            |   12 +-
+ sound/soc/samsung/spdif.c                          |   12 +-
+ sound/soc/sh/fsi.c                                 |  550 ++++++++++++++--
+ sound/soc/soc-cache.c                              |   10 +-
+ sound/soc/soc-core.c                               |  243 +++----
+ sound/soc/soc-dapm.c                               |  134 ++--
+ sound/soc/soc-dmaengine-pcm.c                      |    2 +
+ sound/soc/soc-jack.c                               |   16 +-
+ sound/soc/soc-pcm.c                                |  195 +++---
+ sound/soc/tegra/tegra20_das.c                      |    2 +-
+ sound/soc/tegra/tegra20_i2s.c                      |    4 +-
+ sound/soc/tegra/tegra20_spdif.c                    |    2 +-
+ sound/soc/tegra/tegra30_ahub.c                     |    6 +-
+ sound/soc/tegra/tegra30_i2s.c                      |    4 +-
+ sound/soc/tegra/tegra_alc5632.c                    |    2 +-
+ sound/soc/tegra/tegra_wm8753.c                     |    2 +-
+ sound/soc/tegra/tegra_wm8903.c                     |    2 +-
+ sound/soc/tegra/trimslice.c                        |    2 +-
+ sound/soc/ux500/mop500.c                           |    4 +-
+ sound/soc/ux500/ux500_msp_dai.c                    |   55 +-
+ sound/soc/ux500/ux500_msp_dai.h                    |    1 +
+ sound/soc/ux500/ux500_pcm.c                        |   19 +-
+ sound/soc/ux500/ux500_pcm.h                        |    3 +
+ 139 files changed, 5685 insertions(+), 1774 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/misc/atmel-ssc.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/ak4104.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt
+ create mode 100644 drivers/input/misc/arizona-haptics.c
+ create mode 100644 sound/soc/codecs/max98090.c
+ create mode 100644 sound/soc/codecs/si476x.c
+ create mode 100644 sound/soc/codecs/wm_adsp.c
+ create mode 100644 sound/soc/codecs/wm_adsp.h
+ create mode 100644 sound/soc/codecs/wmfw.h
+ create mode 100644 sound/soc/fsl/p1022_rdk.c
+Merging modules/modules-next (58876af moduleparam: use __UNIQUE_ID())
+$ git merge modules/modules-next
+Auto-merging kernel/module.c
+Auto-merging Makefile
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/ima_policy   |    3 +-
+ Makefile                               |    6 +
+ arch/arm/include/uapi/asm/unistd.h     |    1 +
+ arch/arm/kernel/calls.S                |    1 +
+ arch/powerpc/include/asm/systbl.h      |    1 +
+ arch/powerpc/include/asm/unistd.h      |    2 +-
+ arch/powerpc/include/uapi/asm/unistd.h |    1 +
+ arch/x86/syscalls/syscall_32.tbl       |    1 +
+ arch/x86/syscalls/syscall_64.tbl       |    1 +
+ include/linux/compiler-gcc4.h          |    2 +
+ include/linux/compiler.h               |    9 +
+ include/linux/ima.h                    |    6 +
+ include/linux/moduleparam.h            |    6 +-
+ include/linux/security.h               |   13 ++
+ include/linux/syscalls.h               |    1 +
+ include/uapi/asm-generic/unistd.h      |    4 +-
+ include/uapi/linux/module.h            |    8 +
+ kernel/module.c                        |  402 ++++++++++++++++++++------------
+ kernel/sys_ni.c                        |    1 +
+ scripts/Makefile.modsign               |   32 +++
+ security/capability.c                  |    6 +
+ security/integrity/ima/ima.h           |    2 +-
+ security/integrity/ima/ima_api.c       |    4 +-
+ security/integrity/ima/ima_main.c      |   21 ++
+ security/integrity/ima/ima_policy.c    |    3 +
+ security/security.c                    |   10 +
+ 26 files changed, 383 insertions(+), 164 deletions(-)
+ create mode 100644 include/uapi/linux/module.h
+ create mode 100644 scripts/Makefile.modsign
+$ git reset --hard HEAD^
+HEAD is now at 5c9cc5e Merge remote-tracking branch 'sound-asoc/for-next'
+Merging refs/next/20121115/modules
+$ git merge refs/next/20121115/modules
+Auto-merging kernel/module.c
+Auto-merging Makefile
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/ima_policy   |    3 +-
+ Makefile                               |    6 +
+ arch/arm/include/uapi/asm/unistd.h     |    1 +
+ arch/arm/kernel/calls.S                |    1 +
+ arch/powerpc/include/asm/systbl.h      |    1 +
+ arch/powerpc/include/asm/unistd.h      |    2 +-
+ arch/powerpc/include/uapi/asm/unistd.h |    1 +
+ arch/x86/syscalls/syscall_32.tbl       |    1 +
+ arch/x86/syscalls/syscall_64.tbl       |    1 +
+ include/linux/ima.h                    |    6 +
+ include/linux/security.h               |   13 ++
+ include/linux/syscalls.h               |    1 +
+ include/uapi/asm-generic/unistd.h      |    4 +-
+ include/uapi/linux/module.h            |    8 +
+ kernel/module.c                        |  402 ++++++++++++++++++++------------
+ kernel/sys_ni.c                        |    1 +
+ scripts/Makefile.modsign               |   32 +++
+ security/capability.c                  |    6 +
+ security/integrity/ima/ima.h           |    2 +-
+ security/integrity/ima/ima_api.c       |    4 +-
+ security/integrity/ima/ima_main.c      |   21 ++
+ security/integrity/ima/ima_policy.c    |    3 +
+ security/security.c                    |   10 +
+ 23 files changed, 370 insertions(+), 160 deletions(-)
+ create mode 100644 include/uapi/linux/module.h
+ create mode 100644 scripts/Makefile.modsign
+Merging virtio/virtio-next (b15a62a virtio-mmio: Fix irq parsing in command line parameter)
+$ git merge virtio/virtio-next
+Auto-merging mm/highmem.c
+Auto-merging drivers/scsi/virtio_scsi.c
+Auto-merging drivers/net/virtio_net.c
+Merge made by the 'recursive' strategy.
+ drivers/char/virtio_console.c    |   18 +++++---
+ drivers/lguest/core.c            |    2 +-
+ drivers/net/virtio_net.c         |   48 +++++++++-------------
+ drivers/rpmsg/virtio_rpmsg_bus.c |    6 +--
+ drivers/scsi/virtio_scsi.c       |   24 ++++++-----
+ drivers/virtio/virtio_balloon.c  |    7 ++--
+ drivers/virtio/virtio_mmio.c     |   30 +++++++++-----
+ drivers/virtio/virtio_pci.c      |   20 ++-------
+ drivers/virtio/virtio_ring.c     |   46 +++++++++------------
+ include/linux/virtio.h           |   10 ++++-
+ include/linux/virtio_scsi.h      |   28 ++++++++++++-
+ mm/highmem.c                     |    1 +
+ net/9p/trans_virtio.c            |    3 +-
+ tools/lguest/lguest.c            |   84 ++++++++++++++++----------------------
+ tools/virtio/virtio_test.c       |    4 +-
+ 15 files changed, 166 insertions(+), 165 deletions(-)
+Merging input/next (852d20a Input: remove Compaq iPAQ H3600 (Bitsy) touchscreen driver)
+$ git merge input/next
+Removing drivers/input/touchscreen/h3600_ts_input.c
+Auto-merging drivers/input/misc/Makefile
+Auto-merging drivers/input/misc/Kconfig
+Auto-merging drivers/input/input-mt.c
+Merge made by the 'recursive' strategy.
+ .../bindings/input/gpio-matrix-keypad.txt          |   46 ++
+ .../devicetree/bindings/input/pwm-beeper.txt       |    7 +
+ .../devicetree/bindings/input/stmpe-keypad.txt     |   39 ++
+ .../bindings/input/touchscreen/mms114.txt          |   34 ++
+ .../bindings/input/touchscreen/stmpe.txt           |   43 ++
+ arch/arm/mach-omap1/board-nokia770.c               |   14 +-
+ arch/arm/mach-ux500/board-mop500-stuib.c           |   93 +---
+ drivers/input/gameport/emu10k1-gp.c                |    6 +-
+ drivers/input/gameport/fm801-gp.c                  |    6 +-
+ drivers/input/input-mt.c                           |    2 +-
+ drivers/input/input.c                              |  181 ++++++--
+ drivers/input/joystick/as5011.c                    |   29 +-
+ drivers/input/joystick/maplecontrol.c              |    6 +-
+ drivers/input/keyboard/Kconfig                     |    2 +-
+ drivers/input/keyboard/adp5520-keys.c              |    6 +-
+ drivers/input/keyboard/adp5588-keys.c              |   18 +-
+ drivers/input/keyboard/adp5589-keys.c              |   21 +-
+ drivers/input/keyboard/bf54x-keys.c                |    6 +-
+ drivers/input/keyboard/davinci_keyscan.c           |    4 +-
+ drivers/input/keyboard/ep93xx_keypad.c             |    6 +-
+ drivers/input/keyboard/gpio_keys.c                 |   80 +++-
+ drivers/input/keyboard/gpio_keys_polled.c          |    9 +-
+ drivers/input/keyboard/hilkbd.c                    |   10 +-
+ drivers/input/keyboard/imx_keypad.c                |    9 +-
+ drivers/input/keyboard/jornada680_kbd.c            |    6 +-
+ drivers/input/keyboard/jornada720_kbd.c            |    6 +-
+ drivers/input/keyboard/lm8323.c                    |    6 +-
+ drivers/input/keyboard/lm8333.c                    |    6 +-
+ drivers/input/keyboard/locomokbd.c                 |    8 +-
+ drivers/input/keyboard/lpc32xx-keys.c              |    8 +-
+ drivers/input/keyboard/matrix_keypad.c             |  129 ++++--
+ drivers/input/keyboard/max7359_keypad.c            |    6 +-
+ drivers/input/keyboard/mcs_touchkey.c              |    6 +-
+ drivers/input/keyboard/mpr121_touchkey.c           |   12 +-
+ drivers/input/keyboard/nomadik-ske-keypad.c        |   38 +-
+ drivers/input/keyboard/omap-keypad.c               |    6 +-
+ drivers/input/keyboard/omap4-keypad.c              |   10 +-
+ drivers/input/keyboard/opencores-kbd.c             |    6 +-
+ drivers/input/keyboard/pmic8xxx-keypad.c           |   10 +-
+ drivers/input/keyboard/pxa27x_keypad.c             |    6 +-
+ drivers/input/keyboard/pxa930_rotary.c             |    6 +-
+ drivers/input/keyboard/qt1070.c                    |    8 +-
+ drivers/input/keyboard/qt2160.c                    |   31 +-
+ drivers/input/keyboard/samsung-keypad.c            |  109 ++---
+ drivers/input/keyboard/sh_keysc.c                  |    6 +-
+ drivers/input/keyboard/spear-keyboard.c            |   98 ++--
+ drivers/input/keyboard/stmpe-keypad.c              |  142 +++---
+ drivers/input/keyboard/tc3589x-keypad.c            |    6 +-
+ drivers/input/keyboard/tca6416-keypad.c            |    8 +-
+ drivers/input/keyboard/tca8418_keypad.c            |    8 +-
+ drivers/input/keyboard/tegra-kbc.c                 |   16 +-
+ drivers/input/keyboard/tnetv107x-keypad.c          |    6 +-
+ drivers/input/keyboard/twl4030_keypad.c            |    8 +-
+ drivers/input/keyboard/w90p910_keypad.c            |    6 +-
+ drivers/input/matrix-keymap.c                      |   23 +-
+ drivers/input/misc/88pm80x_onkey.c                 |    6 +-
+ drivers/input/misc/88pm860x_onkey.c                |    6 +-
+ drivers/input/misc/Kconfig                         |   29 +-
+ drivers/input/misc/Makefile                        |    2 +
+ drivers/input/misc/ab8500-ponkey.c                 |    6 +-
+ drivers/input/misc/ad714x-i2c.c                    |    6 +-
+ drivers/input/misc/ad714x-spi.c                    |    6 +-
+ drivers/input/misc/adxl34x-i2c.c                   |    6 +-
+ drivers/input/misc/adxl34x-spi.c                   |    6 +-
+ drivers/input/misc/bfin_rotary.c                   |    6 +-
+ drivers/input/misc/bma150.c                        |   28 +-
+ drivers/input/misc/cma3000_d0x_i2c.c               |    6 +-
+ drivers/input/misc/cobalt_btns.c                   |    6 +-
+ drivers/input/misc/da9052_onkey.c                  |    6 +-
+ drivers/input/misc/da9055_onkey.c                  |  171 +++++++
+ drivers/input/misc/dm355evm_keys.c                 |    6 +-
+ drivers/input/misc/gp2ap002a00f.c                  |    8 +-
+ drivers/input/misc/gpio_tilt_polled.c              |    6 +-
+ drivers/input/misc/ixp4xx-beeper.c                 |    6 +-
+ drivers/input/misc/kxtj9.c                         |   16 +-
+ drivers/input/misc/m68kspkr.c                      |    6 +-
+ drivers/input/misc/max8925_onkey.c                 |    6 +-
+ drivers/input/misc/max8997_haptic.c                |    6 +-
+ drivers/input/misc/mc13783-pwrbutton.c             |    6 +-
+ drivers/input/misc/mma8450.c                       |    6 +-
+ drivers/input/misc/mpu3050.c                       |    8 +-
+ drivers/input/misc/pcap_keys.c                     |    6 +-
+ drivers/input/misc/pcf50633-input.c                |    6 +-
+ drivers/input/misc/pcf8574_keypad.c                |    6 +-
+ drivers/input/misc/pcspkr.c                        |    6 +-
+ drivers/input/misc/pm8xxx-vibrator.c               |    6 +-
+ drivers/input/misc/pmic8xxx-pwrkey.c               |    6 +-
+ drivers/input/misc/pwm-beeper.c                    |   20 +-
+ drivers/input/misc/rb532_button.c                  |    6 +-
+ drivers/input/misc/retu-pwrbutton.c                |   99 ++++
+ drivers/input/misc/rotary_encoder.c                |    9 +-
+ drivers/input/misc/sgi_btns.c                      |    6 +-
+ drivers/input/misc/sparcspkr.c                     |   14 +-
+ drivers/input/misc/twl4030-pwrbutton.c             |    3 +-
+ drivers/input/misc/twl4030-vibra.c                 |    6 +-
+ drivers/input/misc/twl6040-vibra.c                 |    6 +-
+ drivers/input/misc/wistron_btns.c                  |   20 +-
+ drivers/input/misc/wm831x-on.c                     |   11 +-
+ drivers/input/misc/xen-kbdfront.c                  |    2 +-
+ drivers/input/mouse/alps.c                         |   10 +-
+ drivers/input/mouse/gpio_mouse.c                   |    6 +-
+ drivers/input/mouse/maplemouse.c                   |    6 +-
+ drivers/input/mouse/navpoint.c                     |    6 +-
+ drivers/input/mouse/pxa930_trkball.c               |    6 +-
+ drivers/input/mouse/synaptics_i2c.c                |    6 +-
+ drivers/input/serio/Kconfig                        |    9 +
+ drivers/input/serio/Makefile                       |    1 +
+ drivers/input/serio/altera_ps2.c                   |    6 +-
+ drivers/input/serio/ambakmi.c                      |    6 +-
+ drivers/input/serio/arc_ps2.c                      |  274 +++++++++++
+ drivers/input/serio/ct82c710.c                     |    6 +-
+ drivers/input/serio/gscps2.c                       |    6 +-
+ drivers/input/serio/hil_mlc.c                      |   13 +-
+ drivers/input/serio/i8042-io.h                     |    2 +-
+ drivers/input/serio/i8042-sparcio.h                |    6 +-
+ drivers/input/serio/i8042.c                        |    6 +-
+ drivers/input/serio/maceps2.c                      |    8 +-
+ drivers/input/serio/pcips2.c                       |    6 +-
+ drivers/input/serio/q40kbd.c                       |    6 +-
+ drivers/input/serio/rpckbd.c                       |    6 +-
+ drivers/input/serio/sa1111ps2.c                    |   12 +-
+ drivers/input/serio/serio.c                        |   11 -
+ drivers/input/serio/xilinx_ps2.c                   |    8 +-
+ drivers/input/tablet/wacom_sys.c                   |   58 ++-
+ drivers/input/tablet/wacom_wac.c                   |   29 +-
+ drivers/input/tablet/wacom_wac.h                   |    2 +
+ drivers/input/touchscreen/88pm860x-ts.c            |    8 +-
+ drivers/input/touchscreen/Kconfig                  |   12 -
+ drivers/input/touchscreen/Makefile                 |    1 -
+ drivers/input/touchscreen/ad7877.c                 |    6 +-
+ drivers/input/touchscreen/ad7879-i2c.c             |    6 +-
+ drivers/input/touchscreen/ad7879-spi.c             |    6 +-
+ drivers/input/touchscreen/ads7846.c                |   10 +-
+ drivers/input/touchscreen/atmel_mxt_ts.c           |    6 +-
+ drivers/input/touchscreen/atmel_tsadcc.c           |    6 +-
+ drivers/input/touchscreen/auo-pixcir-ts.c          |    8 +-
+ drivers/input/touchscreen/bu21013_ts.c             |  125 +++--
+ drivers/input/touchscreen/cy8ctmg110_ts.c          |   19 +-
+ drivers/input/touchscreen/cyttsp_i2c.c             |    6 +-
+ drivers/input/touchscreen/cyttsp_spi.c             |    6 +-
+ drivers/input/touchscreen/da9034-ts.c              |    6 +-
+ drivers/input/touchscreen/da9052_tsi.c             |   10 +-
+ drivers/input/touchscreen/edt-ft5x06.c             |   28 +-
+ drivers/input/touchscreen/eeti_ts.c                |    6 +-
+ drivers/input/touchscreen/egalax_ts.c              |    8 +-
+ drivers/input/touchscreen/h3600_ts_input.c         |  479 --------------------
+ drivers/input/touchscreen/htcpen.c                 |    6 +-
+ drivers/input/touchscreen/ili210x.c                |    6 +-
+ drivers/input/touchscreen/intel-mid-touch.c        |   14 +-
+ drivers/input/touchscreen/jornada720_ts.c          |    6 +-
+ drivers/input/touchscreen/lpc32xx_ts.c             |    6 +-
+ drivers/input/touchscreen/max11801_ts.c            |    8 +-
+ drivers/input/touchscreen/mc13783_ts.c             |    4 +-
+ drivers/input/touchscreen/mcs5000_ts.c             |    6 +-
+ drivers/input/touchscreen/mms114.c                 |   68 ++-
+ drivers/input/touchscreen/pcap_ts.c                |    6 +-
+ drivers/input/touchscreen/pixcir_i2c_ts.c          |    6 +-
+ drivers/input/touchscreen/s3c2410_ts.c             |    6 +-
+ drivers/input/touchscreen/st1232.c                 |    8 +-
+ drivers/input/touchscreen/stmpe-ts.c               |  133 +++---
+ drivers/input/touchscreen/ti_tscadc.c              |    2 +-
+ drivers/input/touchscreen/tnetv107x-ts.c           |    6 +-
+ drivers/input/touchscreen/tps6507x-ts.c            |    4 +-
+ drivers/input/touchscreen/tsc2005.c                |    8 +-
+ drivers/input/touchscreen/tsc2007.c                |    6 +-
+ drivers/input/touchscreen/ucb1400_ts.c             |    8 +-
+ drivers/input/touchscreen/w90p910_ts.c             |    6 +-
+ drivers/input/touchscreen/wacom_i2c.c              |    6 +-
+ drivers/input/touchscreen/wm831x-ts.c              |   12 +-
+ drivers/mfd/stmpe.c                                |    2 +
+ include/linux/input.h                              |   10 +-
+ include/linux/input/bu21013.h                      |   10 +-
+ 172 files changed, 2135 insertions(+), 1552 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt
+ create mode 100644 Documentation/devicetree/bindings/input/pwm-beeper.txt
+ create mode 100644 Documentation/devicetree/bindings/input/stmpe-keypad.txt
+ create mode 100644 Documentation/devicetree/bindings/input/touchscreen/mms114.txt
+ create mode 100644 Documentation/devicetree/bindings/input/touchscreen/stmpe.txt
+ create mode 100644 drivers/input/misc/da9055_onkey.c
+ create mode 100644 drivers/input/misc/retu-pwrbutton.c
+ create mode 100644 drivers/input/serio/arc_ps2.c
+ delete mode 100644 drivers/input/touchscreen/h3600_ts_input.c
+Merging input-mt/for-next (6f0c058 Linux 3.7-rc2)
+$ git merge input-mt/for-next
+Already up-to-date.
+Merging cgroup/for-next (9718ceb cgroup: list_del_init() on removed events)
+$ git merge cgroup/for-next
+Resolved 'mm/memcontrol.c' using previous resolution.
+Resolved 'net/sched/cls_cgroup.c' using previous resolution.
+Auto-merging net/sched/cls_cgroup.c
+CONFLICT (content): Merge conflict in net/sched/cls_cgroup.c
+Auto-merging net/core/netprio_cgroup.c
+Auto-merging mm/memcontrol.c
+CONFLICT (content): Merge conflict in mm/memcontrol.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 90f99c0] Merge remote-tracking branch 'cgroup/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/cgroups/cgroups.txt           |   61 ++-
+ Documentation/cgroups/freezer-subsystem.txt |   63 ++-
+ Documentation/cgroups/net_prio.txt          |    2 +
+ block/blk-cgroup.c                          |   15 +-
+ include/linux/cgroup.h                      |  167 +++++--
+ include/linux/freezer.h                     |   57 ++-
+ include/net/netprio_cgroup.h                |   11 +-
+ kernel/cgroup.c                             |  717 ++++++++++++++-------------
+ kernel/cgroup_freezer.c                     |  514 +++++++++++--------
+ kernel/cpuset.c                             |   90 ++--
+ kernel/events/core.c                        |    8 +-
+ kernel/fork.c                               |    9 +-
+ kernel/freezer.c                            |   11 +-
+ kernel/power/process.c                      |   13 +-
+ kernel/sched/core.c                         |   16 +-
+ kernel/signal.c                             |   20 +-
+ mm/hugetlb_cgroup.c                         |   23 +-
+ mm/memcontrol.c                             |  191 +++----
+ net/core/netprio_cgroup.c                   |  260 +++++-----
+ net/sched/cls_cgroup.c                      |   28 +-
+ security/device_cgroup.c                    |   20 +-
+ 21 files changed, 1224 insertions(+), 1072 deletions(-)
+Merging block/for-next (95678ef Merge branch 'for-3.8/core' into for-next)
+$ git merge block/for-next
+Removing include/linux/drbd_tag_magic.h
+Removing include/linux/drbd_nl.h
+Merge made by the 'recursive' strategy.
+ block/blk-core.c                   |    4 +-
+ block/cfq-iosched.c                |    3 +-
+ block/elevator.c                   |   16 +-
+ block/genhd.c                      |   10 +-
+ block/partitions/efi.c             |    7 +-
+ block/partitions/msdos.c           |   21 +-
+ drivers/block/cciss.c              |   21 +-
+ drivers/block/drbd/Makefile        |    2 +
+ drivers/block/drbd/drbd_actlog.c   |  702 +++----
+ drivers/block/drbd/drbd_bitmap.c   |  249 +--
+ drivers/block/drbd/drbd_int.h      | 1392 ++++++-------
+ drivers/block/drbd/drbd_interval.c |  207 ++
+ drivers/block/drbd/drbd_interval.h |   40 +
+ drivers/block/drbd/drbd_main.c     | 3861 ++++++++++++++---------------------
+ drivers/block/drbd/drbd_nl.c       | 3334 +++++++++++++++++-------------
+ drivers/block/drbd/drbd_nla.c      |   55 +
+ drivers/block/drbd/drbd_nla.h      |    8 +
+ drivers/block/drbd/drbd_proc.c     |   41 +-
+ drivers/block/drbd/drbd_receiver.c | 3894 +++++++++++++++++++++---------------
+ drivers/block/drbd/drbd_req.c      | 1574 +++++++--------
+ drivers/block/drbd/drbd_req.h      |  187 +-
+ drivers/block/drbd/drbd_state.c    | 1857 +++++++++++++++++
+ drivers/block/drbd/drbd_state.h    |  161 ++
+ drivers/block/drbd/drbd_strings.c  |    1 +
+ drivers/block/drbd/drbd_worker.c   | 1237 +++++++-----
+ drivers/block/drbd/drbd_wrappers.h |   11 +-
+ include/linux/drbd.h               |   81 +-
+ include/linux/drbd_genl.h          |  378 ++++
+ include/linux/drbd_genl_api.h      |   55 +
+ include/linux/drbd_limits.h        |   90 +-
+ include/linux/drbd_nl.h            |  163 --
+ include/linux/drbd_tag_magic.h     |   84 -
+ include/linux/genhd.h              |    8 +-
+ include/linux/genl_magic_func.h    |  422 ++++
+ include/linux/genl_magic_struct.h  |  277 +++
+ include/linux/idr.h                |   11 +
+ include/linux/lru_cache.h          |   67 +-
+ init/do_mounts.c                   |   61 +-
+ lib/lru_cache.c                    |  359 ++--
+ 39 files changed, 12339 insertions(+), 8612 deletions(-)
+ create mode 100644 drivers/block/drbd/drbd_interval.c
+ create mode 100644 drivers/block/drbd/drbd_interval.h
+ create mode 100644 drivers/block/drbd/drbd_nla.c
+ create mode 100644 drivers/block/drbd/drbd_nla.h
+ create mode 100644 drivers/block/drbd/drbd_state.c
+ create mode 100644 drivers/block/drbd/drbd_state.h
+ create mode 100644 include/linux/drbd_genl.h
+ create mode 100644 include/linux/drbd_genl_api.h
+ delete mode 100644 include/linux/drbd_nl.h
+ delete mode 100644 include/linux/drbd_tag_magic.h
+ create mode 100644 include/linux/genl_magic_func.h
+ create mode 100644 include/linux/genl_magic_struct.h
+Merging device-mapper/master (cee3685 track_chunk is always called with interrupts enabled. Consequently, we do not need to save and restore interrupt state in "flags" variable. This patch changes spin_lock_irqsave to spin_lock_irq and spin_unlock_irqrestore to spin_unlock_irq.)
+$ git merge device-mapper/master
+Merge made by the 'recursive' strategy.
+ drivers/md/dm-raid1.c                          |   10 ++---
+ drivers/md/dm-snap.c                           |    5 +--
+ drivers/md/persistent-data/dm-btree-internal.h |   16 ++++----
+ drivers/md/persistent-data/dm-btree-remove.c   |   50 ++++++++++++------------
+ drivers/md/persistent-data/dm-btree-spine.c    |    6 +--
+ drivers/md/persistent-data/dm-btree.c          |   22 +++++------
+ 6 files changed, 53 insertions(+), 56 deletions(-)
+Merging embedded/master (4744b43 embedded: fix vc_translate operator precedence)
+$ git merge embedded/master
+Already up-to-date.
+Merging firmware/master (6e03a20 firmware: speed up request_firmware(), v3)
+$ git merge firmware/master
+Already up-to-date.
+Merging pcmcia/master (80af9e6 pcmcia at91_cf: fix raw gpio number usage)
+$ git merge pcmcia/master
+Already up-to-date.
+Merging mmc/mmc-next (2656109 mmc: sdhci-spear: Don't call clk_{un}prepare() in suspend/resume)
+$ git merge mmc/mmc-next
+Removing include/linux/mmc/mxs-mmc.h
+Removing drivers/mmc/host/at91_mci.h
+Removing drivers/mmc/host/at91_mci.c
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/mmc/mmc.txt      |    6 +
+ .../devicetree/bindings/mmc/samsung-sdhci.txt      |   20 +-
+ .../{synposis-dw-mshc.txt => synopsis-dw-mshc.txt} |    0
+ .../devicetree/bindings/mmc/ti-omap-hsmmc.txt      |    1 +
+ .../devicetree/bindings/mmc/vt8500-sdmmc.txt       |   23 +
+ Documentation/mmc/mmc-dev-attrs.txt                |    7 +
+ MAINTAINERS                                        |    9 +-
+ arch/arm/mach-at91/include/mach/board.h            |   10 -
+ arch/arm/plat-omap/include/plat/mmc.h              |    1 +
+ drivers/mmc/card/block.c                           |   81 ++
+ drivers/mmc/card/queue.c                           |   17 +-
+ drivers/mmc/core/core.c                            |   32 +-
+ drivers/mmc/core/debugfs.c                         |   16 +
+ drivers/mmc/core/mmc.c                             |   17 +-
+ drivers/mmc/core/mmc_ops.c                         |   11 +
+ drivers/mmc/core/sdio_io.c                         |   10 +-
+ drivers/mmc/core/sdio_ops.c                        |   32 +-
+ drivers/mmc/host/Kconfig                           |   34 +-
+ drivers/mmc/host/Makefile                          |    2 +-
+ drivers/mmc/host/at91_mci.c                        | 1219 --------------------
+ drivers/mmc/host/at91_mci.h                        |  115 --
+ drivers/mmc/host/dw_mmc-pci.c                      |    2 +-
+ drivers/mmc/host/dw_mmc-pltfm.c                    |   16 +-
+ drivers/mmc/host/dw_mmc.c                          |   30 +-
+ drivers/mmc/host/mxcmmc.c                          |    2 +-
+ drivers/mmc/host/mxs-mmc.c                         |   31 +-
+ drivers/mmc/host/omap_hsmmc.c                      |  177 ++-
+ drivers/mmc/host/sdhci-dove.c                      |    1 -
+ drivers/mmc/host/sdhci-of-esdhc.c                  |    3 +
+ drivers/mmc/host/sdhci-pltfm.c                     |    6 +
+ drivers/mmc/host/sdhci-pxav3.c                     |   13 +-
+ drivers/mmc/host/sdhci-s3c.c                       |   63 +-
+ drivers/mmc/host/sdhci-spear.c                     |    9 +-
+ drivers/mmc/host/sdhci.c                           |   31 +-
+ drivers/mmc/host/wmt-sdmmc.c                       | 1029 +++++++++++++++++
+ include/linux/mmc/card.h                           |    2 +
+ include/linux/mmc/core.h                           |    2 +
+ include/linux/mmc/dw_mmc.h                         |    5 +-
+ include/linux/mmc/host.h                           |   16 +-
+ include/linux/mmc/mmc.h                            |    2 +
+ include/linux/mmc/mxs-mmc.h                        |   19 -
+ include/linux/mmc/sdhci.h                          |    4 +-
+ include/linux/platform_data/pxa_sdhci.h            |    6 +-
+ 43 files changed, 1538 insertions(+), 1594 deletions(-)
+ rename Documentation/devicetree/bindings/mmc/{synposis-dw-mshc.txt => synopsis-dw-mshc.txt} (100%)
+ create mode 100644 Documentation/devicetree/bindings/mmc/vt8500-sdmmc.txt
+ delete mode 100644 drivers/mmc/host/at91_mci.c
+ delete mode 100644 drivers/mmc/host/at91_mci.h
+ create mode 100644 drivers/mmc/host/wmt-sdmmc.c
+ delete mode 100644 include/linux/mmc/mxs-mmc.h
+Merging kgdb/kgdb-next (58bcdf6 tty/console: fix warnings in drivers/tty/serial/kgdboc.c)
+$ git merge kgdb/kgdb-next
+Merge made by the 'recursive' strategy.
+Merging slab/for-next (f1d58d7 Merge branch 'slab/next' into for-next)
+$ git merge slab/for-next
+Resolved 'mm/slob.c' using previous resolution.
+Auto-merging mm/slob.c
+CONFLICT (content): Merge conflict in mm/slob.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 6367b9d] Merge remote-tracking branch 'slab/for-next'
+$ git diff -M --stat --summary HEAD^..
+ include/linux/mm_types.h |    7 +--
+ include/linux/slab.h     |    9 ++-
+ mm/slab.c                |  151 +++++++++-------------------------------------
+ mm/slab.h                |   45 ++++++++++++++
+ mm/slab_common.c         |  116 +++++++++++++++++++++++++++++++++++
+ mm/slob.c                |   36 ++++-------
+ mm/slub.c                |  147 ++++++++++++--------------------------------
+ 7 files changed, 248 insertions(+), 263 deletions(-)
+Merging uclinux/for-next (ddffeb8 Linux 3.7-rc1)
+$ git merge uclinux/for-next
+Already up-to-date.
+Merging md/for-next (fb07cce md/raid5: use async_tx_quiesce() instead of open-coding it.)
+$ git merge md/for-next
+Auto-merging block/blk-core.c
+Auto-merging arch/x86/Makefile
+Merge made by the 'recursive' strategy.
+ arch/x86/Makefile       |    5 +-
+ block/blk-core.c        |    1 +
+ drivers/md/md.c         |   26 ++-
+ drivers/md/md.h         |   10 ++
+ drivers/md/raid5.c      |  451 ++++++++++++++++++++++++++++++++++++++++++++---
+ drivers/md/raid5.h      |   19 ++
+ include/linux/raid/pq.h |    1 +
+ lib/raid6/Makefile      |    2 +-
+ lib/raid6/algos.c       |    3 +
+ lib/raid6/recov_avx2.c  |  327 ++++++++++++++++++++++++++++++++++
+ lib/raid6/test/Makefile |    2 +-
+ lib/raid6/x86.h         |   14 +-
+ 12 files changed, 819 insertions(+), 42 deletions(-)
+ create mode 100644 lib/raid6/recov_avx2.c
+Merging mfd/for-next (64cdfe2 mfd: tps65090: MFD_TPS65090 needs to select REGMAP_IRQ)
+$ git merge mfd/for-next
+Resolved 'drivers/mfd/twl-core.c' using previous resolution.
+Resolved 'drivers/mmc/host/Kconfig' using previous resolution.
+Auto-merging include/linux/regmap.h
+Removing include/linux/input/ti_tscadc.h
+Auto-merging drivers/mmc/host/Makefile
+Auto-merging drivers/mmc/host/Kconfig
+CONFLICT (content): Merge conflict in drivers/mmc/host/Kconfig
+Auto-merging drivers/mfd/wm8994-core.c
+Auto-merging drivers/mfd/wm5102-tables.c
+Auto-merging drivers/mfd/twl6040.c
+Removing drivers/mfd/twl6040-irq.c
+Auto-merging drivers/mfd/twl4030-irq.c
+Auto-merging drivers/mfd/twl-core.c
+CONFLICT (content): Merge conflict in drivers/mfd/twl-core.c
+Removing drivers/mfd/tps65910-irq.c
+Auto-merging drivers/mfd/stmpe.c
+CONFLICT (modify/delete): drivers/input/touchscreen/ti_tscadc.c deleted in mfd/for-next and modified in HEAD. Version HEAD of drivers/input/touchscreen/ti_tscadc.c left in tree.
+Auto-merging drivers/input/touchscreen/da9052_tsi.c
+Auto-merging drivers/input/touchscreen/Makefile
+Auto-merging drivers/input/touchscreen/Kconfig
+Auto-merging drivers/input/misc/da9052_onkey.c
+Auto-merging drivers/i2c/busses/Makefile
+Auto-merging drivers/i2c/busses/Kconfig
+Auto-merging drivers/gpio/Kconfig
+Auto-merging drivers/base/regmap/regmap.c
+Auto-merging drivers/base/regmap/internal.h
+Automatic merge failed; fix conflicts and then commit the result.
+$ git rm -f drivers/input/touchscreen/ti_tscadc.c
+drivers/input/touchscreen/ti_tscadc.c: needs merge
+rm 'drivers/input/touchscreen/ti_tscadc.c'
+$ git commit -v -a
+[master 0decee3] Merge remote-tracking branch 'mfd/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/devicetree/bindings/mfd/stmpe.txt    |   25 +
+ .../devicetree/bindings/regulator/tps65217.txt     |    4 +
+ drivers/base/regmap/internal.h                     |    4 +-
+ drivers/base/regmap/regmap-irq.c                   |   19 +
+ drivers/base/regmap/regmap.c                       |   65 +-
+ drivers/gpio/Kconfig                               |   13 +
+ drivers/gpio/Makefile                              |    1 +
+ drivers/gpio/gpio-da9052.c                         |    6 +-
+ drivers/gpio/gpio-tps6586x.c                       |    9 +
+ drivers/gpio/gpio-twl4030.c                        |   12 +-
+ drivers/gpio/gpio-viperboard.c                     |  517 ++++++++
+ drivers/i2c/busses/Kconfig                         |   10 +
+ drivers/i2c/busses/Makefile                        |    1 +
+ drivers/i2c/busses/i2c-viperboard.c                |  480 +++++++
+ drivers/iio/adc/Kconfig                            |   14 +
+ drivers/iio/adc/Makefile                           |    2 +
+ drivers/iio/adc/ti_am335x_adc.c                    |  260 ++++
+ drivers/iio/adc/viperboard_adc.c                   |  181 +++
+ drivers/input/misc/da9052_onkey.c                  |   22 +-
+ drivers/input/touchscreen/Kconfig                  |    6 +-
+ drivers/input/touchscreen/Makefile                 |    2 +-
+ drivers/input/touchscreen/da9052_tsi.c             |   59 +-
+ drivers/input/touchscreen/ti_am335x_tsc.c          |  398 ++++++
+ drivers/input/touchscreen/ti_tscadc.c              |  486 -------
+ drivers/memstick/host/Kconfig                      |   10 +
+ drivers/memstick/host/Makefile                     |    1 +
+ drivers/memstick/host/rtsx_pci_ms.c                |  641 ++++++++++
+ drivers/mfd/Kconfig                                |   73 +-
+ drivers/mfd/Makefile                               |   13 +-
+ drivers/mfd/ab8500-core.c                          |  102 +-
+ drivers/mfd/as3711.c                               |  217 ++++
+ drivers/mfd/da9052-core.c                          |  273 +---
+ drivers/mfd/da9052-irq.c                           |  288 +++++
+ drivers/mfd/db8500-prcmu.c                         |    8 +-
+ drivers/mfd/jz4740-adc.c                           |   20 +-
+ drivers/mfd/lpc_ich.c                              |   16 +-
+ drivers/mfd/mc13xxx-core.c                         |   94 +-
+ drivers/mfd/mc13xxx-i2c.c                          |   22 +-
+ drivers/mfd/mc13xxx-spi.c                          |   29 +-
+ drivers/mfd/mc13xxx.h                              |   18 +-
+ drivers/mfd/mfd-core.c                             |   15 +-
+ drivers/mfd/rc5t583-irq.c                          |    2 +-
+ drivers/mfd/retu-mfd.c                             |  264 ++++
+ drivers/mfd/rtl8411.c                              |  251 ++++
+ drivers/mfd/rts5209.c                              |  223 ++++
+ drivers/mfd/rts5229.c                              |  205 +++
+ drivers/mfd/rtsx_pcr.c                             | 1252 ++++++++++++++++++
+ drivers/mfd/rtsx_pcr.h                             |   32 +
+ drivers/mfd/sec-irq.c                              |  102 +-
+ drivers/mfd/sta2x11-mfd.c                          |  532 +++++---
+ drivers/mfd/stmpe-i2c.c                            |    8 +-
+ drivers/mfd/stmpe.c                                |  190 +--
+ drivers/mfd/ti_am335x_tscadc.c                     |  274 ++++
+ drivers/mfd/tps65090.c                             |  312 ++---
+ drivers/mfd/tps65217.c                             |   12 +
+ drivers/mfd/tps6586x.c                             |  103 +-
+ drivers/mfd/tps65910-irq.c                         |  260 ----
+ drivers/mfd/tps65910.c                             |  233 +++-
+ drivers/mfd/tps80031.c                             |  573 +++++++++
+ drivers/mfd/twl-core.c                             |  227 ++--
+ drivers/mfd/twl4030-irq.c                          |   10 +-
+ drivers/mfd/twl4030-madc.c                         |   14 +-
+ drivers/mfd/twl4030-power.c                        |  124 +-
+ drivers/mfd/twl6030-irq.c                          |    4 +-
+ drivers/mfd/twl6040-irq.c                          |  205 ---
+ drivers/mfd/{twl6040-core.c => twl6040.c}          |  138 +-
+ drivers/mfd/viperboard.c                           |  137 ++
+ drivers/mfd/wm5102-tables.c                        |   13 +-
+ drivers/mfd/wm8994-core.c                          |    1 +
+ drivers/mmc/host/Kconfig                           |    7 +
+ drivers/mmc/host/Makefile                          |    2 +
+ drivers/mmc/host/rtsx_pci_sdmmc.c                  | 1348 ++++++++++++++++++++
+ drivers/power/da9052-battery.c                     |   44 +-
+ drivers/rtc/rtc-twl.c                              |   32 +-
+ include/linux/i2c/twl.h                            |   73 +-
+ include/linux/input/ti_am335x_tsc.h                |   23 +
+ include/linux/input/ti_tscadc.h                    |   17 -
+ include/linux/mfd/as3711.h                         |  126 ++
+ include/linux/mfd/da9052/da9052.h                  |   10 +
+ include/linux/mfd/da9055/core.h                    |    2 +-
+ include/linux/mfd/da9055/pdata.h                   |    2 +-
+ include/linux/mfd/da9055/reg.h                     |    2 +-
+ include/linux/mfd/rc5t583.h                        |    3 +-
+ include/linux/mfd/retu.h                           |   22 +
+ include/linux/mfd/rtsx_common.h                    |   48 +
+ include/linux/mfd/rtsx_pci.h                       |  794 ++++++++++++
+ include/linux/mfd/sta2x11-mfd.h                    |  198 ++-
+ include/linux/mfd/stmpe.h                          |    2 +
+ include/linux/mfd/ti_am335x_tscadc.h               |  152 +++
+ include/linux/mfd/tps65090.h                       |   73 +-
+ include/linux/mfd/tps6586x.h                       |    1 +
+ include/linux/mfd/tps65910.h                       |  143 ++-
+ include/linux/mfd/tps80031.h                       |  637 +++++++++
+ include/linux/mfd/twl6040.h                        |   10 +-
+ include/linux/mfd/viperboard.h                     |  110 ++
+ include/linux/platform_data/ti_am335x_adc.h        |   14 +
+ include/linux/regmap.h                             |   18 +-
+ 97 files changed, 11620 insertions(+), 2430 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/mfd/stmpe.txt
+ create mode 100644 drivers/gpio/gpio-viperboard.c
+ create mode 100644 drivers/i2c/busses/i2c-viperboard.c
+ create mode 100644 drivers/iio/adc/ti_am335x_adc.c
+ create mode 100644 drivers/iio/adc/viperboard_adc.c
+ create mode 100644 drivers/input/touchscreen/ti_am335x_tsc.c
+ delete mode 100644 drivers/input/touchscreen/ti_tscadc.c
+ create mode 100644 drivers/memstick/host/rtsx_pci_ms.c
+ create mode 100644 drivers/mfd/as3711.c
+ create mode 100644 drivers/mfd/da9052-irq.c
+ create mode 100644 drivers/mfd/retu-mfd.c
+ create mode 100644 drivers/mfd/rtl8411.c
+ create mode 100644 drivers/mfd/rts5209.c
+ create mode 100644 drivers/mfd/rts5229.c
+ create mode 100644 drivers/mfd/rtsx_pcr.c
+ create mode 100644 drivers/mfd/rtsx_pcr.h
+ create mode 100644 drivers/mfd/ti_am335x_tscadc.c
+ delete mode 100644 drivers/mfd/tps65910-irq.c
+ create mode 100644 drivers/mfd/tps80031.c
+ delete mode 100644 drivers/mfd/twl6040-irq.c
+ rename drivers/mfd/{twl6040-core.c => twl6040.c} (84%)
+ create mode 100644 drivers/mfd/viperboard.c
+ create mode 100644 drivers/mmc/host/rtsx_pci_sdmmc.c
+ create mode 100644 include/linux/input/ti_am335x_tsc.h
+ delete mode 100644 include/linux/input/ti_tscadc.h
+ create mode 100644 include/linux/mfd/as3711.h
+ create mode 100644 include/linux/mfd/retu.h
+ create mode 100644 include/linux/mfd/rtsx_common.h
+ create mode 100644 include/linux/mfd/rtsx_pci.h
+ create mode 100644 include/linux/mfd/ti_am335x_tscadc.h
+ create mode 100644 include/linux/mfd/tps80031.h
+ create mode 100644 include/linux/mfd/viperboard.h
+ create mode 100644 include/linux/platform_data/ti_am335x_adc.h
+Merging battery/master (eba3b67 max8925_power: Add support for device-tree initialization)
+$ git merge battery/master
+Auto-merging drivers/power/power_supply_core.c
+Auto-merging drivers/mfd/ab8500-core.c
+Auto-merging arch/arm/boot/dts/dbx5x0.dtsi
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/mfd/ab8500.txt   |   27 +-
+ .../bindings/power_supply/ab8500/btemp.txt         |   16 +
+ .../bindings/power_supply/ab8500/chargalg.txt      |   16 +
+ .../bindings/power_supply/ab8500/charger.txt       |   25 +
+ .../devicetree/bindings/power_supply/ab8500/fg.txt |   58 +
+ Documentation/power/power_supply_class.txt         |    3 +
+ arch/arm/boot/dts/dbx5x0.dtsi                      |   28 +-
+ drivers/mfd/ab8500-core.c                          |   20 +
+ drivers/power/Kconfig                              |   23 +-
+ drivers/power/Makefile                             |    4 +-
+ drivers/power/ab8500_bmdata.c                      |  521 ++++++
+ drivers/power/ab8500_btemp.c                       |   77 +-
+ drivers/power/ab8500_charger.c                     |   84 +-
+ drivers/power/ab8500_fg.c                          |   82 +-
+ drivers/power/abx500_chargalg.c                    |   56 +-
+ drivers/power/bq2415x_charger.c                    | 1670 ++++++++++++++++++++
+ drivers/power/bq27x00_battery.c                    |    8 +
+ drivers/power/ds2782_battery.c                     |    4 +-
+ drivers/power/generic-adc-battery.c                |    5 +-
+ drivers/power/jz4740-battery.c                     |   45 +-
+ drivers/power/lp8788-charger.c                     |   75 +-
+ drivers/power/max17042_battery.c                   |    3 +-
+ drivers/power/max8925_power.c                      |   51 +-
+ drivers/power/power_supply_core.c                  |   96 ++
+ drivers/power/power_supply_sysfs.c                 |    2 +
+ drivers/power/rx51_battery.c                       |  251 +++
+ drivers/power/twl4030_charger.c                    |   12 +-
+ include/linux/mfd/abx500.h                         |   34 +-
+ include/linux/mfd/lp8788.h                         |    8 +-
+ include/linux/power/bq2415x_charger.h              |   95 ++
+ include/linux/power_supply.h                       |    3 +
+ 31 files changed, 3123 insertions(+), 279 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt
+ create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/chargalg.txt
+ create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/charger.txt
+ create mode 100644 Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
+ create mode 100644 drivers/power/ab8500_bmdata.c
+ create mode 100644 drivers/power/bq2415x_charger.c
+ create mode 100644 drivers/power/rx51_battery.c
+ create mode 100644 include/linux/power/bq2415x_charger.h
+Merging fbdev/fbdev-next (cd9d6f1 gbefb: fix compile error)
+$ git merge fbdev/fbdev-next
+Already up-to-date.
+Merging viafb/viafb-next (838ac78 viafb: avoid refresh and mode lookup in set_par)
+$ git merge viafb/viafb-next
+Already up-to-date.
+Merging omap_dss2/for-next (474ff6b Merge tag 'omapdss-for-3.7-rc' of git://gitorious.org/linux-omap-dss2/linux)
+$ git merge omap_dss2/for-next
+Auto-merging include/video/omapvrfb.h
+Removing drivers/video/omap2/vram.c
+Auto-merging drivers/media/platform/omap/omap_vout.c
+Removing arch/arm/plat-omap/include/plat/vram.h
+Merge made by the 'recursive' strategy.
+ Documentation/arm/OMAP/DSS                         |   10 +-
+ arch/arm/mach-omap2/board-rx51-video.c             |   14 -
+ arch/arm/mach-omap2/board-rx51.c                   |    3 -
+ arch/arm/mach-omap2/display.c                      |   53 +-
+ arch/arm/mach-omap2/sdrc.c                         |   16 -
+ arch/arm/plat-omap/common.c                        |    2 -
+ arch/arm/plat-omap/fb.c                            |   66 ++-
+ arch/arm/plat-omap/include/plat/sdrc.h             |    7 -
+ arch/arm/plat-omap/include/plat/vram.h             |   43 --
+ drivers/media/platform/omap/omap_vout.c            |    2 +-
+ drivers/media/platform/omap/omap_vout_vrfb.c       |    2 +-
+ drivers/media/platform/omap/omap_voutdef.h         |    2 +-
+ drivers/video/omap2/Kconfig                        |    3 -
+ drivers/video/omap2/Makefile                       |    1 -
+ drivers/video/omap2/displays/panel-acx565akm.c     |   23 -
+ drivers/video/omap2/displays/panel-generic-dpi.c   |   36 --
+ .../omap2/displays/panel-lgphilips-lb035q02.c      |   34 --
+ drivers/video/omap2/displays/panel-n8x0.c          |   89 +---
+ .../omap2/displays/panel-nec-nl8048hl11-01b.c      |   24 -
+ drivers/video/omap2/displays/panel-picodlp.c       |   44 --
+ .../video/omap2/displays/panel-sharp-ls037v7dw01.c |   17 -
+ drivers/video/omap2/displays/panel-taal.c          |   72 ---
+ drivers/video/omap2/displays/panel-tfp410.c        |   33 --
+ .../video/omap2/displays/panel-tpo-td043mtea1.c    |   20 -
+ drivers/video/omap2/dss/Kconfig                    |   35 +-
+ drivers/video/omap2/dss/Makefile                   |    1 +
+ drivers/video/omap2/dss/apply.c                    |   85 ++-
+ drivers/video/omap2/dss/core.c                     |   37 +-
+ drivers/video/omap2/dss/dispc.c                    |  555 ++++++++++++--------
+ drivers/video/omap2/dss/display.c                  |   93 +---
+ drivers/video/omap2/dss/dpi.c                      |  101 ++--
+ drivers/video/omap2/dss/dsi.c                      |  211 ++++----
+ drivers/video/omap2/dss/dss.c                      |  111 +++-
+ drivers/video/omap2/dss/dss.h                      |   73 +--
+ drivers/video/omap2/dss/dss_features.c             |   73 ++-
+ drivers/video/omap2/dss/dss_features.h             |    7 +-
+ drivers/video/omap2/dss/hdmi.c                     |  149 ++++--
+ drivers/video/omap2/dss/hdmi_panel.c               |   82 +--
+ drivers/video/omap2/dss/rfbi.c                     |    2 +-
+ drivers/video/omap2/dss/sdi.c                      |    2 +-
+ drivers/video/omap2/dss/ti_hdmi.h                  |    3 +
+ drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c          |   11 +-
+ drivers/video/omap2/dss/venc.c                     |    2 +-
+ drivers/video/omap2/dss/venc_panel.c               |   19 -
+ drivers/video/omap2/omapfb/Kconfig                 |    1 -
+ drivers/video/omap2/omapfb/omapfb-ioctl.c          |   17 +-
+ drivers/video/omap2/omapfb/omapfb-main.c           |  182 ++++---
+ drivers/video/omap2/omapfb/omapfb-sysfs.c          |    2 +-
+ drivers/video/omap2/omapfb/omapfb.h                |    5 +
+ drivers/video/omap2/vram.c                         |  514 ------------------
+ drivers/video/omap2/vrfb.c                         |  142 ++++-
+ include/video/omapdss.h                            |   24 +-
+ .../plat/vrfb.h => include/video/omapvrfb.h        |    2 +
+ 53 files changed, 1302 insertions(+), 1855 deletions(-)
+ delete mode 100644 arch/arm/plat-omap/include/plat/vram.h
+ delete mode 100644 drivers/video/omap2/vram.c
+ rename arch/arm/plat-omap/include/plat/vrfb.h => include/video/omapvrfb.h (95%)
+Merging regulator/for-next (4736661 Merge remote-tracking branches 'regulator/fix/wm831x', 'regulator/topic/arizona', 'regulator/topic/as3711', 'regulator/topic/da9052', 'regulator/topic/da9055', 'regulator/topic/log', 'regulator/topic/lp8788', 'regulator/topic/max77686', 'regulator/topic/max8973', 'regulator/topic/max8997', 'regulator/topic/min', 'regulator/topic/s2mps11', 'regulator/topic/stub', 'regulator/topic/tol', 'regulator/topic/tps65090', 'regulator/topic/tps6586x', 'regulator/topic/tps65910' and 'regulator/topic/tps80031' into regulator-next)
+$ git merge regulator/for-next
+Resolved 'include/linux/mfd/tps65090.h' using previous resolution.
+Removing include/linux/regulator/tps65090-regulator.h
+Auto-merging include/linux/mfd/tps6586x.h
+Auto-merging include/linux/mfd/tps65090.h
+CONFLICT (content): Merge conflict in include/linux/mfd/tps65090.h
+Auto-merging include/linux/mfd/da9055/pdata.h
+Auto-merging drivers/mfd/wm5102-tables.c
+Auto-merging drivers/mfd/tps6586x.c
+Auto-merging drivers/mfd/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 12f8635] Merge remote-tracking branch 'regulator/for-next'
+$ git diff -M --stat --summary HEAD^..
+ .../bindings/regulator/gpio-regulator.txt          |   37 +
+ .../bindings/regulator/max8925-regulator.txt       |   40 +
+ .../bindings/regulator/max8997-regulator.txt       |  146 ++++
+ .../devicetree/bindings/regulator/vexpress.txt     |   32 +
+ drivers/mfd/Kconfig                                |    1 -
+ drivers/mfd/max8997.c                              |   73 +-
+ drivers/mfd/tps6586x.c                             |   76 +-
+ drivers/mfd/wm5102-tables.c                        |    3 +
+ drivers/regulator/88pm8607.c                       |    6 +-
+ drivers/regulator/Kconfig                          |   54 ++
+ drivers/regulator/Makefile                         |    6 +
+ drivers/regulator/aat2870-regulator.c              |    4 +-
+ drivers/regulator/ab3100.c                         |    6 +-
+ drivers/regulator/ab8500.c                         |   12 +-
+ drivers/regulator/ad5398.c                         |    6 +-
+ drivers/regulator/anatop-regulator.c               |    6 +-
+ drivers/regulator/arizona-ldo1.c                   |  136 +++-
+ drivers/regulator/arizona-micsupp.c                |    8 +-
+ drivers/regulator/as3711-regulator.c               |  369 +++++++++
+ drivers/regulator/core.c                           |   20 +-
+ drivers/regulator/da903x.c                         |    6 +-
+ drivers/regulator/da9052-regulator.c               |   16 +-
+ drivers/regulator/da9055-regulator.c               |  641 ++++++++++++++++
+ drivers/regulator/db8500-prcmu.c                   |    6 +-
+ drivers/regulator/dbx500-prcmu.c                   |    4 +-
+ drivers/regulator/dummy.c                          |    2 +-
+ drivers/regulator/fan53555.c                       |    6 +-
+ drivers/regulator/fixed.c                          |    6 +-
+ drivers/regulator/gpio-regulator.c                 |  106 ++-
+ drivers/regulator/isl6271a-regulator.c             |    6 +-
+ drivers/regulator/lp3971.c                         |    8 +-
+ drivers/regulator/lp3972.c                         |    8 +-
+ drivers/regulator/lp872x.c                         |    4 +-
+ drivers/regulator/lp8788-buck.c                    |    6 +-
+ drivers/regulator/lp8788-ldo.c                     |   14 +-
+ drivers/regulator/max1586.c                        |    6 +-
+ drivers/regulator/max77686.c                       |  170 ++++-
+ drivers/regulator/max8649.c                        |    6 +-
+ drivers/regulator/max8660.c                        |    6 +-
+ drivers/regulator/max8907-regulator.c              |    6 +-
+ drivers/regulator/max8925-regulator.c              |   78 +-
+ drivers/regulator/max8952.c                        |    6 +-
+ drivers/regulator/max8973-regulator.c              |  505 +++++++++++++
+ drivers/regulator/max8997.c                        |  187 ++++-
+ drivers/regulator/max8998.c                        |    6 +-
+ drivers/regulator/mc13783-regulator.c              |    6 +-
+ drivers/regulator/mc13892-regulator.c              |    6 +-
+ drivers/regulator/mc13xxx-regulator-core.c         |    4 +-
+ drivers/regulator/palmas-regulator.c               |   45 +-
+ drivers/regulator/pcap-regulator.c                 |    6 +-
+ drivers/regulator/pcf50633-regulator.c             |  182 +----
+ drivers/regulator/rc5t583-regulator.c              |    6 +-
+ drivers/regulator/s2mps11.c                        |   16 +-
+ drivers/regulator/s5m8767.c                        |    6 +-
+ drivers/regulator/tps51632-regulator.c             |  327 ++++++++
+ drivers/regulator/tps6105x-regulator.c             |    6 +-
+ drivers/regulator/tps62360-regulator.c             |    8 +-
+ drivers/regulator/tps65023-regulator.c             |    6 +-
+ drivers/regulator/tps6507x-regulator.c             |    6 +-
+ drivers/regulator/tps65090-regulator.c             |  254 +++++--
+ drivers/regulator/tps65217-regulator.c             |    6 +-
+ drivers/regulator/tps6524x-regulator.c             |    4 +-
+ drivers/regulator/tps6586x-regulator.c             |  189 ++++-
+ drivers/regulator/tps65910-regulator.c             |   13 +-
+ drivers/regulator/tps65912-regulator.c             |    6 +-
+ drivers/regulator/tps80031-regulator.c             |  795 ++++++++++++++++++++
+ drivers/regulator/twl-regulator.c                  |    6 +-
+ drivers/regulator/vexpress.c                       |  147 ++++
+ drivers/regulator/virtual.c                        |    6 +-
+ drivers/regulator/wm831x-dcdc.c                    |   28 +-
+ drivers/regulator/wm831x-isink.c                   |    6 +-
+ drivers/regulator/wm831x-ldo.c                     |   18 +-
+ drivers/regulator/wm8400-regulator.c               |    6 +-
+ drivers/regulator/wm8994-regulator.c               |    6 +-
+ include/linux/mfd/arizona/registers.h              |   16 +
+ include/linux/mfd/da9055/pdata.h                   |   27 +-
+ include/linux/mfd/max8997-private.h                |    1 +
+ include/linux/mfd/max8997.h                        |    1 +
+ include/linux/mfd/tps65090.h                       |   35 +
+ include/linux/mfd/tps6586x.h                       |    3 +
+ include/linux/regulator/consumer.h                 |   12 +
+ include/linux/regulator/driver.h                   |    5 +
+ include/linux/regulator/max8973-regulator.h        |   72 ++
+ include/linux/regulator/tps51632-regulator.h       |   47 ++
+ include/linux/regulator/tps65090-regulator.h       |   50 --
+ 85 files changed, 4616 insertions(+), 629 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/regulator/gpio-regulator.txt
+ create mode 100644 Documentation/devicetree/bindings/regulator/max8925-regulator.txt
+ create mode 100644 Documentation/devicetree/bindings/regulator/max8997-regulator.txt
+ create mode 100644 Documentation/devicetree/bindings/regulator/vexpress.txt
+ create mode 100644 drivers/regulator/as3711-regulator.c
+ create mode 100644 drivers/regulator/da9055-regulator.c
+ create mode 100644 drivers/regulator/max8973-regulator.c
+ create mode 100644 drivers/regulator/tps51632-regulator.c
+ create mode 100644 drivers/regulator/tps80031-regulator.c
+ create mode 100644 drivers/regulator/vexpress.c
+ create mode 100644 include/linux/regulator/max8973-regulator.h
+ create mode 100644 include/linux/regulator/tps51632-regulator.h
+ delete mode 100644 include/linux/regulator/tps65090-regulator.h
+Merging security/next (c91c1bf Smack: create a sysfs mount point for smackfs)
+$ git merge security/next
+Resolved 'net/dns_resolver/dns_key.c' using previous resolution.
+Resolved 'security/keys/keyctl.c' using previous resolution.
+Resolved 'security/keys/keyring.c' using previous resolution.
+Resolved 'security/keys/process_keys.c' using previous resolution.
+Auto-merging security/keys/request_key.c
+Auto-merging security/keys/process_keys.c
+CONFLICT (content): Merge conflict in security/keys/process_keys.c
+Auto-merging security/keys/keyring.c
+CONFLICT (content): Merge conflict in security/keys/keyring.c
+Auto-merging security/keys/keyctl.c
+CONFLICT (content): Merge conflict in security/keys/keyctl.c
+Auto-merging security/keys/key.c
+Auto-merging net/dns_resolver/dns_key.c
+CONFLICT (content): Merge conflict in net/dns_resolver/dns_key.c
+Auto-merging kernel/cred.c
+Auto-merging include/linux/key.h
+Auto-merging fs/nfs/idmap.c
+Auto-merging fs/cifs/cifsacl.c
+Auto-merging arch/x86/kernel/vsyscall_64.c
+Auto-merging Documentation/security/keys.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 12524c1] Merge remote-tracking branch 'security/next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/prctl/seccomp_filter.txt |   74 +++++++++++++++++--
+ Documentation/security/keys.txt        |   17 +++++
+ arch/x86/kernel/vsyscall_64.c          |  110 ++++++++++++++-------------
+ drivers/char/tpm/tpm_ibmvtpm.c         |   81 +++++++-------------
+ drivers/char/tpm/tpm_ibmvtpm.h         |    5 +-
+ fs/cifs/cifsacl.c                      |   12 +--
+ fs/nfs/idmap.c                         |   12 +--
+ include/linux/cred.h                   |   17 +----
+ include/linux/key.h                    |    1 +
+ kernel/cred.c                          |  127 ++++----------------------------
+ kernel/seccomp.c                       |   13 +++-
+ net/dns_resolver/dns_key.c             |    9 +--
+ security/keys/key.c                    |    6 +-
+ security/keys/keyctl.c                 |   15 ++--
+ security/keys/keyring.c                |   10 +--
+ security/keys/process_keys.c           |   94 ++++++++++-------------
+ security/keys/request_key.c            |   21 ++++--
+ security/smack/Kconfig                 |    5 +-
+ security/smack/smackfs.c               |   17 +++++
+ security/yama/yama_lsm.c               |   88 +++++++++++++++-------
+ 20 files changed, 365 insertions(+), 369 deletions(-)
+Merging selinux/master (c2d7b24 Merge tag 'v3.4' into 20120409)
+$ git merge selinux/master
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging lblnet/master (7e27d6e Linux 2.6.35-rc3)
+$ git merge lblnet/master
+Already up-to-date.
+Merging watchdog/master (58ddfed Merge branch 'master' of ../linux-watchdog)
+$ git merge watchdog/master
+Merge made by the 'recursive' strategy.
+ drivers/watchdog/davinci_wdt.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+Merging dwmw2-iommu/master (c3b92c8 Linux 3.1)
+$ git merge dwmw2-iommu/master
+Already up-to-date.
+Merging iommu/next (f6cffc1 Merge branches 'iommu/fixes', 'dma-debug', 'x86/amd', 'arm/exynos', 'x86/vt-d' and 'arm/tegra' into next)
+$ git merge iommu/next
+Merge made by the 'recursive' strategy.
+ Documentation/DMA-API-HOWTO.txt        |  126 ++++++++++++++++++++++
+ Documentation/DMA-API.txt              |   12 +++
+ arch/arm64/include/asm/dma-mapping.h   |    1 +
+ arch/c6x/include/asm/dma-mapping.h     |    1 +
+ arch/ia64/include/asm/dma-mapping.h    |    1 +
+ arch/mips/include/asm/dma-mapping.h    |    2 +
+ arch/powerpc/include/asm/dma-mapping.h |    1 +
+ arch/sh/include/asm/dma-mapping.h      |    1 +
+ arch/sparc/include/asm/dma-mapping.h   |    1 +
+ arch/tile/include/asm/dma-mapping.h    |    1 +
+ arch/x86/include/asm/dma-mapping.h     |    1 +
+ drivers/iommu/Kconfig                  |    2 +-
+ drivers/iommu/amd_iommu.c              |  184 ++++++++++++++++++++++++--------
+ drivers/iommu/amd_iommu_types.h        |    1 +
+ drivers/iommu/exynos-iommu.c           |   29 ++++-
+ drivers/iommu/intel-iommu.c            |   31 ++++++
+ drivers/iommu/tegra-gart.c             |    2 +-
+ drivers/iommu/tegra-smmu.c             |    6 +-
+ include/linux/dma-debug.h              |    7 ++
+ lib/dma-debug.c                        |   66 ++++++++++--
+ 20 files changed, 415 insertions(+), 61 deletions(-)
+Merging vfio/next (74d8627 vfio-pci: Enable device before attempting reset)
+$ git merge vfio/next
+Merge made by the 'recursive' strategy.
+ drivers/vfio/pci/vfio_pci.c |   83 ++++++++++++++++++++++++-------------------
+ drivers/vfio/vfio.c         |   34 +++++++++---------
+ 2 files changed, 64 insertions(+), 53 deletions(-)
+Merging osd/linux-next (b6755ff osduld: Add osdname & systemid sysfs at scsi_osd class)
+$ git merge osd/linux-next
+Merge made by the 'recursive' strategy.
+Merging jc_docs/docs-next (5c050fb docs: update the development process document)
+$ git merge jc_docs/docs-next
+Already up-to-date.
+Merging trivial/for-next (8fdbb34 messages: i2o: Fix typo in messages/i2o)
+$ git merge trivial/for-next
+Auto-merging sound/pci/ice1712/delta.c
+Auto-merging sound/pci/es1968.c
+Auto-merging net/mac80211/driver-ops.h
+Auto-merging net/ipv4/tcp_cong.c
+Auto-merging mm/memory_hotplug.c
+Auto-merging include/linux/stmmac.h
+Auto-merging include/linux/netdevice.h
+Auto-merging include/linux/lru_cache.h
+Auto-merging fs/jbd2/transaction.c
+Auto-merging fs/jbd/transaction.c
+Auto-merging fs/fhandle.c
+Auto-merging fs/ext4/ext4.h
+Auto-merging drivers/vhost/tcm_vhost.c
+Auto-merging drivers/target/iscsi/iscsi_target_util.c
+Auto-merging drivers/target/iscsi/iscsi_target_configfs.c
+Auto-merging drivers/scsi/qla2xxx/tcm_qla2xxx.c
+Auto-merging drivers/scsi/qla2xxx/qla_target.c
+Auto-merging drivers/regulator/palmas-regulator.c
+Auto-merging drivers/net/ethernet/micrel/ksz884x.c
+Auto-merging drivers/net/ethernet/mellanox/mlx4/eq.c
+Auto-merging drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
+Auto-merging drivers/mtd/nand/s3c2410.c
+Auto-merging drivers/md/raid5.c
+Auto-merging drivers/md/md.c
+Auto-merging drivers/i2c/busses/i2c-s3c2410.c
+Auto-merging drivers/gpu/drm/radeon/si.c
+Auto-merging drivers/gpu/drm/radeon/evergreen.c
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/dev-kmsg                 |    2 +-
+ Documentation/ABI/testing/sysfs-devices-power      |    2 +-
+ Documentation/ABI/testing/sysfs-driver-ppi         |    2 +-
+ Documentation/accounting/getdelays.c               |    1 -
+ Documentation/dma-buf-sharing.txt                  |    4 +--
+ Documentation/dontdiff                             |    1 -
+ .../fault-injection/notifier-error-inject.txt      |    4 +--
+ Documentation/hid/uhid.txt                         |    2 +-
+ Documentation/hwmon/pmbus                          |    2 +-
+ Documentation/input/alps.txt                       |    2 +-
+ Documentation/kbuild/modules.txt                   |    2 +-
+ Documentation/kernel-doc-nano-HOWTO.txt            |   13 ++++++--
+ Documentation/misc-devices/mei/mei-amt-version.c   |    4 +--
+ Documentation/video4linux/bttv/Cards               |    2 +-
+ Documentation/video4linux/bttv/Sound-FAQ           |    2 +-
+ Documentation/vm/frontswap.txt                     |    2 +-
+ README                                             |    4 +++
+ arch/alpha/kernel/pci_iommu.c                      |   12 +++----
+ arch/arm/kernel/kprobes-test.c                     |    2 +-
+ arch/arm/mach-s3c24xx/include/mach/bast-map.h      |    2 +-
+ arch/arm/mach-s3c24xx/include/mach/dma.h           |    2 +-
+ arch/arm/mach-s3c24xx/include/mach/vr1000-map.h    |    2 +-
+ arch/arm/mach-s3c24xx/pm.c                         |    2 +-
+ arch/arm/plat-s3c24xx/dma.c                        |    2 +-
+ arch/blackfin/mm/sram-alloc.c                      |    2 +-
+ arch/cris/include/arch-v10/arch/irq.h              |    2 +-
+ arch/cris/include/arch-v32/arch/irq.h              |    2 +-
+ arch/ia64/kvm/kvm-ia64.c                           |    2 +-
+ arch/m68k/math-emu/fp_log.c                        |    2 +-
+ arch/mips/txx9/generic/pci.c                       |    2 +-
+ arch/powerpc/include/asm/oprofile_impl.h           |    2 +-
+ arch/powerpc/include/asm/pte-hash64-64k.h          |    2 +-
+ arch/powerpc/include/asm/smu.h                     |    4 +--
+ arch/powerpc/kernel/legacy_serial.c                |    2 +-
+ arch/powerpc/kernel/of_platform.c                  |    2 +-
+ arch/powerpc/kernel/signal_64.c                    |    2 +-
+ arch/powerpc/mm/slice.c                            |    2 +-
+ arch/powerpc/platforms/52xx/mpc52xx_gpt.c          |    2 +-
+ arch/powerpc/platforms/cell/iommu.c                |    2 +-
+ arch/powerpc/platforms/cell/spider-pic.c           |    6 ++--
+ arch/powerpc/platforms/powermac/pic.c              |    2 +-
+ arch/sh/boards/board-espt.c                        |    2 +-
+ arch/x86/boot/.gitignore                           |    1 -
+ drivers/acpi/acpica/dsopcode.c                     |    2 +-
+ drivers/base/firmware_class.c                      |    2 +-
+ drivers/char/ipmi/ipmi_msghandler.c                |    2 +-
+ drivers/char/ipmi/ipmi_si_intf.c                   |    2 +-
+ drivers/char/ppdev.c                               |    6 +---
+ drivers/eisa/eisa.ids                              |    4 +--
+ drivers/firewire/init_ohci1394_dma.c               |    4 +--
+ drivers/firewire/ohci.c                            |    2 +-
+ drivers/gpu/drm/radeon/evergreen.c                 |    2 +-
+ drivers/gpu/drm/radeon/ni.c                        |    4 +--
+ drivers/gpu/drm/radeon/radeon_ring.c               |    4 +--
+ drivers/gpu/drm/radeon/si.c                        |    6 ++--
+ drivers/i2c/busses/i2c-nuc900.c                    |    2 +-
+ drivers/i2c/busses/i2c-s3c2410.c                   |    4 +--
+ drivers/isdn/hisax/amd7930_fn.c                    |    2 +-
+ drivers/isdn/hisax/isar.c                          |    2 +-
+ drivers/md/md.c                                    |    2 +-
+ drivers/md/persistent-data/dm-block-manager.c      |    4 +--
+ drivers/md/persistent-data/dm-btree.h              |    2 +-
+ drivers/md/raid5.c                                 |    2 +-
+ drivers/message/i2o/README.ioctl                   |   12 +++----
+ drivers/message/i2o/i2o_block.c                    |    2 +-
+ drivers/message/i2o/i2o_config.c                   |    2 +-
+ drivers/mtd/maps/plat-ram.c                        |    2 +-
+ drivers/mtd/nand/s3c2410.c                         |    2 +-
+ drivers/net/bonding/bonding.h                      |    2 +-
+ drivers/net/ethernet/8390/ax88796.c                |    2 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c     |    2 +-
+ drivers/net/ethernet/intel/e1000/e1000_ethtool.c   |    2 +-
+ drivers/net/ethernet/mellanox/mlx4/eq.c            |    2 +-
+ drivers/net/ethernet/micrel/ksz884x.c              |    2 +-
+ .../myricom/myri10ge/myri10ge_mcp_gen_header.h     |    2 +-
+ drivers/net/sungem_phy.c                           |    8 ++---
+ drivers/net/wimax/i2400m/debugfs.c                 |    1 +
+ drivers/net/wireless/atmel.c                       |    2 +-
+ drivers/net/wireless/ipw2x00/ipw2100.h             |    2 +-
+ drivers/net/wireless/zd1211rw/zd_chip.c            |    2 +-
+ drivers/regulator/palmas-regulator.c               |    2 +-
+ drivers/rtc/rtc-isl1208.c                          |    2 +-
+ drivers/rtc/rtc-s3c.c                              |    2 +-
+ drivers/s390/block/dasd_devmap.c                   |    2 +-
+ drivers/scsi/bnx2fc/bnx2fc_hwi.c                   |    2 +-
+ drivers/scsi/libsas/sas_expander.c                 |    2 +-
+ drivers/scsi/qla2xxx/qla_isr.c                     |    4 +--
+ drivers/scsi/qla2xxx/qla_nx.c                      |    4 +--
+ drivers/scsi/qla2xxx/qla_target.c                  |   12 +++----
+ drivers/scsi/qla2xxx/tcm_qla2xxx.c                 |    2 +-
+ drivers/staging/comedi/drivers/usbdux.c            |    2 +-
+ drivers/staging/csr/netdev.c                       |    2 +-
+ drivers/staging/tidspbridge/rmgr/node.c            |    2 +-
+ drivers/target/iscsi/iscsi_target_configfs.c       |    2 +-
+ drivers/target/iscsi/iscsi_target_erl0.c           |    6 ++--
+ drivers/target/iscsi/iscsi_target_parameters.c     |    1 +
+ drivers/target/iscsi/iscsi_target_util.c           |    2 +-
+ drivers/tty/hvc/hvc_opal.c                         |    2 +-
+ drivers/tty/hvc/hvc_vio.c                          |    2 +-
+ drivers/tty/ipwireless/setup_protocol.h            |    2 +-
+ drivers/tty/serial/8250/Kconfig                    |    2 +-
+ drivers/tty/serial/bfin_uart.c                     |    2 +-
+ drivers/tty/serial/icom.c                          |    2 +-
+ drivers/usb/core/driver.c                          |    2 +-
+ drivers/usb/gadget/at91_udc.c                      |    2 +-
+ drivers/usb/gadget/tcm_usb_gadget.c                |    2 +-
+ drivers/usb/storage/realtek_cr.c                   |    2 +-
+ drivers/vhost/tcm_vhost.c                          |    2 +-
+ drivers/watchdog/booke_wdt.c                       |    2 +-
+ drivers/xen/xen-pciback/pci_stub.c                 |    2 +-
+ fs/btrfs/ctree.h                                   |    2 +-
+ fs/btrfs/extent-tree.c                             |    2 +-
+ fs/btrfs/extent_map.c                              |    3 +-
+ fs/btrfs/ordered-data.h                            |    2 +-
+ fs/btrfs/volumes.c                                 |    2 +-
+ fs/cifs/README                                     |    2 +-
+ fs/ext4/ext4.h                                     |    2 +-
+ fs/fhandle.c                                       |    4 +--
+ fs/jbd/transaction.c                               |    2 +-
+ fs/jbd2/transaction.c                              |    2 +-
+ fs/logfs/inode.c                                   |    2 +-
+ fs/notify/fanotify/Kconfig                         |    2 +-
+ fs/notify/notification.c                           |    2 +-
+ include/linux/dlm.h                                |    2 +-
+ include/linux/ipmi_smi.h                           |    2 +-
+ include/linux/lru_cache.h                          |    4 +--
+ include/linux/netdevice.h                          |    2 +-
+ include/linux/stmmac.h                             |    2 +-
+ include/linux/vgaarb.h                             |    4 +--
+ include/linux/watchdog.h                           |    2 +-
+ include/net/irda/irlmp.h                           |    2 +-
+ include/net/sock.h                                 |    2 +-
+ mm/memory_hotplug.c                                |    6 ++--
+ mm/util.c                                          |    2 +-
+ net/can/proc.c                                     |    2 +-
+ net/ipv4/tcp_cong.c                                |    2 +-
+ net/mac80211/driver-ops.h                          |    2 +-
+ net/netfilter/nf_log.c                             |    2 +-
+ net/rfkill/core.c                                  |    4 +--
+ net/sctp/endpointola.c                             |    2 +-
+ net/sctp/sm_statefuns.c                            |    2 +-
+ scripts/kernel-doc                                 |   34 ++++++++++++++++++++
+ sound/core/seq/seq_device.c                        |    2 +-
+ sound/pci/emu10k1/emu10k1_patch.c                  |    2 +-
+ sound/pci/es1968.c                                 |    2 +-
+ sound/pci/ice1712/delta.c                          |    2 +-
+ sound/pci/sis7019.c                                |    2 +-
+ sound/usb/quirks.c                                 |    2 +-
+ usr/gen_init_cpio.c                                |    1 -
+ 149 files changed, 230 insertions(+), 196 deletions(-)
+Merging audit/for-next (dcd6c92 Linux 3.3-rc1)
+$ git merge audit/for-next
+Already up-to-date.
+Merging pm/linux-next (6e35af9 Merge branch 'pm-tools-next' into linux-next)
+$ git merge pm/linux-next
+Auto-merging include/linux/freezer.h
+Auto-merging drivers/mtd/nand/sh_flctl.c
+Auto-merging drivers/mmc/host/Makefile
+Auto-merging drivers/mmc/host/Kconfig
+Auto-merging drivers/gpio/Makefile
+Auto-merging drivers/gpio/Kconfig
+Auto-merging drivers/acpi/thermal.c
+Auto-merging drivers/acpi/pci_irq.c
+Auto-merging drivers/acpi/acpica/dsopcode.c
+Auto-merging arch/arm/Kconfig
+Auto-merging Documentation/ABI/testing/sysfs-devices-power
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-devices-power      |   31 +
+ Documentation/ABI/testing/sysfs-devices-sun        |   14 +
+ .../devicetree/bindings/cpufreq/cpufreq-spear.txt  |   42 ++
+ Documentation/power/pm_qos_interface.txt           |    2 +-
+ arch/arm/Kconfig                                   |    1 +
+ arch/ia64/include/asm/device.h                     |    3 -
+ arch/ia64/kernel/acpi.c                            |    2 +
+ arch/powerpc/platforms/pseries/processor_idle.c    |    4 +-
+ arch/x86/include/asm/device.h                      |    3 -
+ arch/x86/kernel/acpi/boot.c                        |    6 +
+ arch/x86/kernel/acpi/sleep.c                       |    2 +
+ drivers/acpi/Kconfig                               |    6 +
+ drivers/acpi/Makefile                              |    6 +-
+ drivers/acpi/acpi_i2c.c                            |  103 +++
+ drivers/acpi/acpi_memhotplug.c                     |  193 +++--
+ drivers/acpi/acpi_pad.c                            |    8 +-
+ drivers/acpi/acpi_platform.c                       |  104 +++
+ drivers/acpi/acpica/Makefile                       |    3 +
+ drivers/acpi/acpica/acdebug.h                      |   94 ++-
+ drivers/acpi/acpica/acdispat.h                     |   11 +-
+ drivers/acpi/acpica/acevents.h                     |    6 +-
+ drivers/acpi/acpica/acglobal.h                     |   73 +-
+ drivers/acpi/acpica/aclocal.h                      |   16 +-
+ drivers/acpi/acpica/acmacros.h                     |  163 ++---
+ drivers/acpi/acpica/acobject.h                     |    7 +-
+ drivers/acpi/acpica/acopcode.h                     |    6 +-
+ drivers/acpi/acpica/acparser.h                     |    3 +-
+ drivers/acpi/acpica/acpredef.h                     |   11 +-
+ drivers/acpi/acpica/acstruct.h                     |    2 +-
+ drivers/acpi/acpica/acutils.h                      |   58 +-
+ drivers/acpi/acpica/amlresrc.h                     |    1 -
+ drivers/acpi/acpica/dscontrol.c                    |    2 +-
+ drivers/acpi/acpica/dsfield.c                      |    2 +-
+ drivers/acpi/acpica/dsmethod.c                     |    6 +-
+ drivers/acpi/acpica/dsmthdat.c                     |   14 +-
+ drivers/acpi/acpica/dsobject.c                     |    6 +-
+ drivers/acpi/acpica/dsopcode.c                     |    3 +-
+ drivers/acpi/acpica/dsutils.c                      |   33 +-
+ drivers/acpi/acpica/dswexec.c                      |   10 +-
+ drivers/acpi/acpica/dswload2.c                     |    4 +-
+ drivers/acpi/acpica/dswstate.c                     |   26 +-
+ drivers/acpi/acpica/evgpe.c                        |   20 +-
+ drivers/acpi/acpica/evgpeblk.c                     |    3 +-
+ drivers/acpi/acpica/evgpeutil.c                    |    3 +-
+ drivers/acpi/acpica/evrgnini.c                     |    7 +-
+ drivers/acpi/acpica/evxface.c                      |    2 +-
+ drivers/acpi/acpica/evxfgpe.c                      |   13 +-
+ drivers/acpi/acpica/exconvrt.c                     |    4 +-
+ drivers/acpi/acpica/excreate.c                     |    9 +-
+ drivers/acpi/acpica/exdebug.c                      |   10 +-
+ drivers/acpi/acpica/exdump.c                       |   20 +-
+ drivers/acpi/acpica/exfield.c                      |    4 +-
+ drivers/acpi/acpica/exfldio.c                      |   15 +-
+ drivers/acpi/acpica/exmisc.c                       |    5 +-
+ drivers/acpi/acpica/exmutex.c                      |    9 +-
+ drivers/acpi/acpica/exnames.c                      |    9 +-
+ drivers/acpi/acpica/exoparg1.c                     |   11 +-
+ drivers/acpi/acpica/exoparg2.c                     |    2 +-
+ drivers/acpi/acpica/exoparg3.c                     |    3 +-
+ drivers/acpi/acpica/exoparg6.c                     |    5 +-
+ drivers/acpi/acpica/exprep.c                       |   13 +-
+ drivers/acpi/acpica/exregion.c                     |    3 +-
+ drivers/acpi/acpica/exresnte.c                     |    9 +-
+ drivers/acpi/acpica/exresolv.c                     |    3 +-
+ drivers/acpi/acpica/exresop.c                      |    8 +-
+ drivers/acpi/acpica/exstore.c                      |    4 +-
+ drivers/acpi/acpica/exstoren.c                     |   11 +-
+ drivers/acpi/acpica/exstorob.c                     |    5 +-
+ drivers/acpi/acpica/exsystem.c                     |    9 +-
+ drivers/acpi/acpica/exutils.c                      |    5 +-
+ drivers/acpi/acpica/hwacpi.c                       |    3 +-
+ drivers/acpi/acpica/hwgpe.c                        |    4 +-
+ drivers/acpi/acpica/hwpci.c                        |    4 +-
+ drivers/acpi/acpica/hwregs.c                       |    1 -
+ drivers/acpi/acpica/hwtimer.c                      |    6 +-
+ drivers/acpi/acpica/hwvalid.c                      |    1 -
+ drivers/acpi/acpica/hwxface.c                      |    1 -
+ drivers/acpi/acpica/hwxfsleep.c                    |   12 +-
+ drivers/acpi/acpica/nsaccess.c                     |    7 +-
+ drivers/acpi/acpica/nsalloc.c                      |    4 +-
+ drivers/acpi/acpica/nsdump.c                       |   10 +-
+ drivers/acpi/acpica/nsinit.c                       |    4 +-
+ drivers/acpi/acpica/nsload.c                       |   10 +-
+ drivers/acpi/acpica/nsnames.c                      |    2 +-
+ drivers/acpi/acpica/nsobject.c                     |    8 +-
+ drivers/acpi/acpica/nsparse.c                      |    8 +-
+ drivers/acpi/acpica/nssearch.c                     |   17 +-
+ drivers/acpi/acpica/nsutils.c                      |   18 +-
+ drivers/acpi/acpica/nswalk.c                       |   10 +-
+ drivers/acpi/acpica/nsxfeval.c                     |   20 +-
+ drivers/acpi/acpica/nsxfname.c                     |   66 +-
+ drivers/acpi/acpica/nsxfobj.c                      |    4 +-
+ drivers/acpi/acpica/psargs.c                       |    8 +-
+ drivers/acpi/acpica/psloop.c                       |   61 +-
+ drivers/acpi/acpica/psopcode.c                     |   29 +-
+ drivers/acpi/acpica/psparse.c                      |   13 +-
+ drivers/acpi/acpica/psutils.c                      |    4 +-
+ drivers/acpi/acpica/rscalc.c                       |   14 +-
+ drivers/acpi/acpica/rslist.c                       |    4 +-
+ drivers/acpi/acpica/tbfind.c                       |    2 +-
+ drivers/acpi/acpica/tbinstal.c                     |    2 +
+ drivers/acpi/acpica/tbutils.c                      |    2 +-
+ drivers/acpi/acpica/tbxface.c                      |    4 +-
+ drivers/acpi/acpica/tbxfload.c                     |    2 +-
+ drivers/acpi/acpica/tbxfroot.c                     |    3 +-
+ drivers/acpi/acpica/utcache.c                      |  323 +++++++++
+ drivers/acpi/acpica/utclib.c                       |  749 ++++++++++++++++++++
+ drivers/acpi/acpica/utdebug.c                      |   37 +-
+ drivers/acpi/acpica/utids.c                        |  104 ++-
+ drivers/acpi/acpica/utmath.c                       |    2 +-
+ drivers/acpi/acpica/utmisc.c                       |  150 +++-
+ drivers/acpi/acpica/utmutex.c                      |   14 +-
+ drivers/acpi/acpica/utobject.c                     |    8 +-
+ drivers/acpi/acpica/utstate.c                      |    2 +-
+ drivers/acpi/acpica/uttrack.c                      |  692 ++++++++++++++++++
+ drivers/acpi/acpica/utxface.c                      |    5 +-
+ drivers/acpi/acpica/utxferror.c                    |    2 +-
+ drivers/acpi/apei/ghes.c                           |    2 +-
+ drivers/acpi/battery.c                             |   77 ++
+ drivers/acpi/bus.c                                 |   21 +-
+ drivers/acpi/container.c                           |   27 +-
+ drivers/acpi/device_pm.c                           |  668 +++++++++++++++++
+ drivers/acpi/dock.c                                |   56 +-
+ drivers/acpi/ec.c                                  |   97 +--
+ drivers/acpi/glue.c                                |   56 +-
+ drivers/acpi/hed.c                                 |    2 +-
+ drivers/acpi/internal.h                            |   11 +-
+ drivers/acpi/osl.c                                 |   22 +-
+ drivers/acpi/pci_irq.c                             |   15 +-
+ drivers/acpi/power.c                               |    2 +-
+ drivers/acpi/proc.c                                |   11 +-
+ drivers/acpi/processor_driver.c                    |   74 +-
+ drivers/acpi/processor_idle.c                      |   57 +-
+ drivers/acpi/resource.c                            |  526 ++++++++++++++
+ drivers/acpi/scan.c                                |  137 +++-
+ drivers/acpi/sleep.c                               |  203 +-----
+ drivers/acpi/sysfs.c                               |    4 +-
+ drivers/acpi/thermal.c                             |   34 +
+ drivers/acpi/utils.c                               |   38 +
+ drivers/base/core.c                                |    2 +-
+ drivers/base/platform.c                            |   26 +-
+ drivers/base/power/clock_ops.c                     |    6 +-
+ drivers/base/power/domain.c                        |   11 +-
+ drivers/base/power/opp.c                           |   44 +-
+ drivers/base/power/power.h                         |    6 +-
+ drivers/base/power/qos.c                           |  321 +++++++--
+ drivers/base/power/sysfs.c                         |   94 ++-
+ drivers/cpufreq/Kconfig.arm                        |    7 +
+ drivers/cpufreq/Makefile                           |    5 +-
+ drivers/cpufreq/cpufreq-cpu0.c                     |    2 +-
+ drivers/cpufreq/cpufreq.c                          |   37 +-
+ drivers/cpufreq/cpufreq_conservative.c             |  558 ++++-----------
+ drivers/cpufreq/cpufreq_governor.c                 |  318 +++++++++
+ drivers/cpufreq/cpufreq_governor.h                 |  176 +++++
+ drivers/cpufreq/cpufreq_ondemand.c                 |  731 ++++++-------------
+ drivers/cpufreq/cpufreq_performance.c              |    2 +
+ drivers/cpufreq/cpufreq_powersave.c                |    2 +
+ drivers/cpufreq/cpufreq_stats.c                    |    4 +-
+ drivers/cpufreq/cpufreq_userspace.c                |    2 +
+ drivers/cpufreq/exynos-cpufreq.c                   |   11 +-
+ drivers/cpufreq/freq_table.c                       |    2 +
+ drivers/cpufreq/longhaul.c                         |    4 +-
+ drivers/cpufreq/powernow-k8.c                      |    4 +-
+ drivers/cpufreq/spear-cpufreq.c                    |  291 ++++++++
+ drivers/cpuidle/Kconfig                            |    9 +
+ drivers/cpuidle/cpuidle.c                          |   55 +-
+ drivers/cpuidle/cpuidle.h                          |   13 +-
+ drivers/cpuidle/driver.c                           |  209 +++++-
+ drivers/cpuidle/governors/menu.c                   |  168 ++++-
+ drivers/cpuidle/sysfs.c                            |  201 +++++-
+ drivers/devfreq/devfreq.c                          |    4 +-
+ drivers/gpio/Kconfig                               |    4 +
+ drivers/gpio/Makefile                              |    1 +
+ drivers/gpio/gpiolib-acpi.c                        |   54 ++
+ drivers/i2c/i2c-core.c                             |    6 +
+ drivers/idle/intel_idle.c                          |   14 +-
+ drivers/mmc/host/Kconfig                           |   12 +
+ drivers/mmc/host/Makefile                          |    1 +
+ drivers/mmc/host/sdhci-acpi.c                      |  304 ++++++++
+ drivers/mtd/nand/sh_flctl.c                        |    4 +-
+ drivers/pci/pci-acpi.c                             |   79 +--
+ drivers/pnp/base.h                                 |    2 +
+ drivers/pnp/pnpacpi/core.c                         |    4 +
+ drivers/pnp/pnpacpi/rsparser.c                     |  296 +-------
+ drivers/pnp/resource.c                             |   16 +
+ drivers/spi/spi.c                                  |  103 ++-
+ include/acpi/acconfig.h                            |    1 +
+ include/acpi/acexcep.h                             |    2 +-
+ include/acpi/acnames.h                             |    1 +
+ include/acpi/acpi_bus.h                            |   78 +-
+ include/acpi/acpiosxf.h                            |    3 +-
+ include/acpi/acpixf.h                              |   18 +-
+ include/acpi/actbl3.h                              |   22 +-
+ include/acpi/actypes.h                             |   42 +-
+ include/linux/acpi.h                               |  135 +++-
+ include/linux/acpi_gpio.h                          |   19 +
+ include/linux/cpufreq.h                            |    5 +-
+ include/linux/cpuidle.h                            |   15 +-
+ include/linux/device.h                             |   18 +
+ include/linux/freezer.h                            |    1 +
+ include/linux/i2c.h                                |    9 +
+ include/linux/platform_device.h                    |    1 +
+ include/linux/pm.h                                 |    3 +-
+ include/linux/pm_qos.h                             |   77 +-
+ include/linux/tick.h                               |    6 +
+ kernel/cpu.c                                       |    8 +-
+ kernel/power/main.c                                |    2 +-
+ kernel/power/qos.c                                 |   65 +-
+ kernel/power/swap.c                                |    2 +-
+ kernel/time/tick-sched.c                           |    4 +
+ tools/power/cpupower/.gitignore                    |    7 +
+ tools/power/cpupower/Makefile                      |    3 +-
+ tools/power/cpupower/debug/i386/Makefile           |    5 +-
+ tools/power/cpupower/man/cpupower-monitor.1        |   15 +-
+ tools/power/cpupower/utils/helpers/cpuid.c         |    2 +
+ tools/power/cpupower/utils/helpers/helpers.h       |   18 +-
+ tools/power/cpupower/utils/helpers/sysfs.c         |   19 -
+ tools/power/cpupower/utils/helpers/topology.c      |   53 +-
+ .../cpupower/utils/idle_monitor/cpupower-monitor.c |   21 +-
+ .../cpupower/utils/idle_monitor/cpupower-monitor.h |   17 +
+ tools/power/cpupower/utils/idle_monitor/snb_idle.c |   10 +-
+ 221 files changed, 8082 insertions(+), 2760 deletions(-)
+ create mode 100644 Documentation/ABI/testing/sysfs-devices-sun
+ create mode 100644 Documentation/devicetree/bindings/cpufreq/cpufreq-spear.txt
+ create mode 100644 drivers/acpi/acpi_i2c.c
+ create mode 100644 drivers/acpi/acpi_platform.c
+ create mode 100644 drivers/acpi/acpica/utcache.c
+ create mode 100644 drivers/acpi/acpica/utclib.c
+ create mode 100644 drivers/acpi/acpica/uttrack.c
+ create mode 100644 drivers/acpi/device_pm.c
+ create mode 100644 drivers/acpi/resource.c
+ create mode 100644 drivers/cpufreq/cpufreq_governor.c
+ create mode 100644 drivers/cpufreq/cpufreq_governor.h
+ create mode 100644 drivers/cpufreq/spear-cpufreq.c
+ create mode 100644 drivers/gpio/gpiolib-acpi.c
+ create mode 100644 drivers/mmc/host/sdhci-acpi.c
+ create mode 100644 include/linux/acpi_gpio.h
+Merging apm/for-next (fb9d78a Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/apm)
+$ git merge apm/for-next
+Already up-to-date.
+Merging fsnotify/for-next (1aec9c0 inotify: automatically restart syscalls)
+$ git merge fsnotify/for-next
+Resolved 'kernel/audit_tree.c' using previous resolution.
+Auto-merging kernel/audit_watch.c
+Auto-merging kernel/audit_tree.c
+CONFLICT (content): Merge conflict in kernel/audit_tree.c
+Auto-merging include/linux/fsnotify_backend.h
+Auto-merging fs/notify/notification.c
+Auto-merging fs/notify/inotify/inotify_user.c
+Auto-merging fs/notify/fanotify/fanotify_user.c
+Auto-merging fs/notify/fanotify/fanotify.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 2bce47f] Merge remote-tracking branch 'fsnotify/for-next'
+$ git diff -M --stat --summary HEAD^..
+ fs/notify/dnotify/dnotify.c          |    4 +-
+ fs/notify/fanotify/fanotify.c        |    6 +++
+ fs/notify/fanotify/fanotify_user.c   |   37 +++++++++-----
+ fs/notify/group.c                    |   47 ++++++++++--------
+ fs/notify/inode_mark.c               |   14 ++++--
+ fs/notify/inotify/inotify_fsnotify.c |    4 +-
+ fs/notify/inotify/inotify_user.c     |   34 ++++++-------
+ fs/notify/mark.c                     |   91 +++++++++++++++++++---------------
+ fs/notify/notification.c             |    1 +
+ fs/notify/vfsmount_mark.c            |   14 ++++--
+ include/linux/fsnotify_backend.h     |   31 ++++++++----
+ kernel/audit_tree.c                  |   10 ++--
+ kernel/audit_watch.c                 |    4 +-
+ 13 files changed, 178 insertions(+), 119 deletions(-)
+Merging edac/linux_next (5e75cbb Merge branch 'devel' into next)
+$ git merge edac/linux_next
+Auto-merging drivers/edac/edac_mc.c
+Merge made by the 'recursive' strategy.
+ drivers/edac/edac_mc.c      |   21 +-
+ drivers/edac/i7300_edac.c   |    8 +-
+ drivers/edac/i82975x_edac.c |  457 +++++++++++++++++++++++++------------------
+ drivers/edac/sb_edac.c      |    2 +-
+ include/linux/edac.h        |    1 -
+ 5 files changed, 288 insertions(+), 201 deletions(-)
+Merging edac-amd/for-next (a8373ec EDAC: Handle error path in edac_mc_sysfs_init() properly)
+$ git merge edac-amd/for-next
+Auto-merging include/linux/edac.h
+Auto-merging drivers/edac/edac_mc.c
+Auto-merging drivers/edac/amd64_edac.h
+Auto-merging drivers/edac/Kconfig
+Merge made by the 'recursive' strategy.
+ drivers/edac/Kconfig            |    8 +-
+ drivers/edac/amd64_edac.c       |  297 +++++++++++++++------------------------
+ drivers/edac/amd64_edac.h       |   59 ++++++--
+ drivers/edac/amd64_edac_inj.c   |  128 +++++++++--------
+ drivers/edac/edac_mc.c          |   57 ++++----
+ drivers/edac/edac_mc_sysfs.c    |   39 +++--
+ drivers/edac/edac_module.c      |   27 +++-
+ drivers/edac/edac_pci.c         |    3 +-
+ drivers/edac/highbank_mc_edac.c |    8 +-
+ drivers/edac/mce_amd.c          |  254 +++++++++++++++++----------------
+ drivers/edac/mce_amd.h          |   11 +-
+ include/linux/edac.h            |    3 +
+ 12 files changed, 456 insertions(+), 438 deletions(-)
+Merging devicetree/devicetree/next (155dd0c Documentation: correct of_platform_populate() argument list)
+$ git merge devicetree/devicetree/next
+Auto-merging include/linux/of.h
+Auto-merging drivers/of/base.c
+Auto-merging drivers/i2c/busses/i2c-ocores.c
+Auto-merging arch/powerpc/sysdev/fsl_pci.c
+Auto-merging arch/powerpc/platforms/pseries/reconfig.c
+Auto-merging arch/arm/include/asm/prom.h
+Auto-merging Documentation/devicetree/bindings/i2c/i2c-pxa.txt
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/arm/l2cc.txt     |    2 +-
+ Documentation/devicetree/bindings/gpio/led.txt     |   14 +---
+ .../bindings/i2c/{atmel-i2c.txt => i2c-at91.txt}   |    0
+ .../bindings/i2c/{davinci.txt => i2c-davinci.txt}  |    0
+ .../bindings/i2c/{gpio-i2c.txt => i2c-gpio.txt}    |    0
+ .../bindings/i2c/{fsl-imx-i2c.txt => i2c-imx.txt}  |    0
+ .../bindings/i2c/{fsl-i2c.txt => i2c-mpc.txt}      |    0
+ .../bindings/i2c/{mux.txt => i2c-mux.txt}          |    0
+ .../devicetree/bindings/i2c/i2c-mv64xxx.txt        |   18 +++++
+ .../bindings/i2c/{nomadik.txt => i2c-nomadik.txt}  |    0
+ .../i2c/{cavium-i2c.txt => i2c-octeon.txt}         |    0
+ .../bindings/i2c/{omap-i2c.txt => i2c-omap.txt}    |    0
+ .../bindings/i2c/{pnx.txt => i2c-pnx.txt}          |    0
+ .../i2c/{ce4100-i2c.txt => i2c-pxa-pci-ce4100.txt} |    0
+ .../bindings/i2c/{mrvl-i2c.txt => i2c-pxa.txt}     |   18 -----
+ .../i2c/{samsung-i2c.txt => i2c-s3c2410.txt}       |    0
+ .../bindings/i2c/{sirf-i2c.txt => i2c-sirf.txt}    |    0
+ .../i2c/{arm-versatile.txt => i2c-versatile.txt}   |    0
+ .../bindings/i2c/{xiic.txt => i2c-xiic.txt}        |    0
+ Documentation/devicetree/bindings/leds/common.txt  |   23 ++++++
+ .../devicetree/bindings/vendor-prefixes.txt        |    3 +
+ Documentation/devicetree/usage-model.txt           |    2 +-
+ arch/arm/boot/dts/tegra20-seaboard.dts             |    4 +-
+ arch/arm/include/asm/prom.h                        |    2 +
+ arch/powerpc/platforms/powermac/pfunc_core.c       |    2 +-
+ arch/powerpc/platforms/pseries/reconfig.c          |    3 +-
+ arch/powerpc/sysdev/fsl_pci.c                      |    2 +-
+ arch/sparc/kernel/pci_impl.h                       |    2 +-
+ drivers/i2c/busses/i2c-ocores.c                    |    4 -
+ drivers/of/base.c                                  |   77 ++++++++++++++++++++
+ drivers/of/fdt.c                                   |   16 ++--
+ include/linux/of.h                                 |   34 ++++++++-
+ scripts/dtc/Makefile                               |    2 +
+ 33 files changed, 178 insertions(+), 50 deletions(-)
+ rename Documentation/devicetree/bindings/i2c/{atmel-i2c.txt => i2c-at91.txt} (100%)
+ rename Documentation/devicetree/bindings/i2c/{davinci.txt => i2c-davinci.txt} (100%)
+ rename Documentation/devicetree/bindings/i2c/{gpio-i2c.txt => i2c-gpio.txt} (100%)
+ rename Documentation/devicetree/bindings/i2c/{fsl-imx-i2c.txt => i2c-imx.txt} (100%)
+ rename Documentation/devicetree/bindings/i2c/{fsl-i2c.txt => i2c-mpc.txt} (100%)
+ rename Documentation/devicetree/bindings/i2c/{mux.txt => i2c-mux.txt} (100%)
+ create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
+ rename Documentation/devicetree/bindings/i2c/{nomadik.txt => i2c-nomadik.txt} (100%)
+ rename Documentation/devicetree/bindings/i2c/{cavium-i2c.txt => i2c-octeon.txt} (100%)
+ rename Documentation/devicetree/bindings/i2c/{omap-i2c.txt => i2c-omap.txt} (100%)
+ rename Documentation/devicetree/bindings/i2c/{pnx.txt => i2c-pnx.txt} (100%)
+ rename Documentation/devicetree/bindings/i2c/{ce4100-i2c.txt => i2c-pxa-pci-ce4100.txt} (100%)
+ rename Documentation/devicetree/bindings/i2c/{mrvl-i2c.txt => i2c-pxa.txt} (70%)
+ rename Documentation/devicetree/bindings/i2c/{samsung-i2c.txt => i2c-s3c2410.txt} (100%)
+ rename Documentation/devicetree/bindings/i2c/{sirf-i2c.txt => i2c-sirf.txt} (100%)
+ rename Documentation/devicetree/bindings/i2c/{arm-versatile.txt => i2c-versatile.txt} (100%)
+ rename Documentation/devicetree/bindings/i2c/{xiic.txt => i2c-xiic.txt} (100%)
+ create mode 100644 Documentation/devicetree/bindings/leds/common.txt
+Merging dt-rh/for-next (bd0ba37 of/i2c: check status property for i2c client)
+$ git merge dt-rh/for-next
+Auto-merging include/linux/of.h
+Auto-merging drivers/of/base.c
+Merge made by the 'recursive' strategy.
+ drivers/of/base.c   |   18 +++++++++++++-----
+ drivers/of/of_i2c.c |    3 +++
+ include/linux/of.h  |   15 +++++++++++++--
+ 3 files changed, 29 insertions(+), 7 deletions(-)
+Merging spi/spi/next (7431798 of_spi: add generic binding support to specify cs gpio)
+$ git merge spi/spi/next
+Auto-merging drivers/spi/spi.c
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/spi/spi-bus.txt |   20 ++++++++
+ drivers/spi/spi-bitbang.c                         |   27 +++++------
+ drivers/spi/spi-omap2-mcspi.c                     |    1 -
+ drivers/spi/spi.c                                 |   54 +++++++++++++++++++--
+ include/linux/spi/spi.h                           |    3 ++
+ 5 files changed, 85 insertions(+), 20 deletions(-)
+Merging spi-mb/spi-next (170c2d0 Merge branch 'spi-mcspi' into spi-next)
+$ git merge spi-mb/spi-next
+Auto-merging drivers/spi/spi.c
+Auto-merging drivers/spi/spi-omap2-mcspi.c
+Merge made by the 'recursive' strategy.
+ .../bindings/spi/nvidia,tegra20-sflash.txt         |   26 +
+ .../bindings/spi/nvidia,tegra20-slink.txt          |   26 +
+ Documentation/devicetree/bindings/spi/omap-spi.txt |    4 +-
+ drivers/spi/Kconfig                                |   14 +
+ drivers/spi/Makefile                               |    3 +-
+ drivers/spi/spi-bcm63xx.c                          |   16 +-
+ drivers/spi/spi-omap2-mcspi.c                      |   64 +-
+ drivers/spi/spi-pl022.c                            |   52 +-
+ drivers/spi/spi-s3c64xx.c                          |   34 +-
+ drivers/spi/spi-tegra20-sflash.c                   |  665 ++++++++++
+ drivers/spi/spi-tegra20-slink.c                    | 1358 ++++++++++++++++++++
+ drivers/spi/spi.c                                  |   16 +-
+ drivers/spi/spidev.c                               |   10 +
+ include/linux/platform_data/spi-omap2-mcspi.h      |    4 +
+ include/linux/spi/spi-tegra.h                      |   40 +
+ 15 files changed, 2257 insertions(+), 75 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/spi/nvidia,tegra20-sflash.txt
+ create mode 100644 Documentation/devicetree/bindings/spi/nvidia,tegra20-slink.txt
+ create mode 100644 drivers/spi/spi-tegra20-sflash.c
+ create mode 100644 drivers/spi/spi-tegra20-slink.c
+ create mode 100644 include/linux/spi/spi-tegra.h
+Merging tip/auto-latest (a07005c Merge branch 'x86/mm')
+$ git merge tip/auto-latest
+Auto-merging tools/perf/tests/parse-events.c
+Auto-merging tools/perf/tests/dso-data.c
+Auto-merging tools/perf/tests/builtin-test.c
+Auto-merging tools/perf/perf.h
+Auto-merging mm/memcontrol.c
+Auto-merging kernel/time/tick-sched.c
+Auto-merging kernel/sched/core.c
+Auto-merging include/linux/mm_types.h
+Auto-merging include/linux/device.h
+Auto-merging include/linux/acpi.h
+Auto-merging fs/proc/base.c
+Auto-merging drivers/base/core.c
+Auto-merging drivers/acpi/osl.c
+Auto-merging drivers/acpi/Kconfig
+Auto-merging arch/x86/kernel/ptrace.c
+Auto-merging arch/x86/kernel/entry_64.S
+Auto-merging arch/x86/kernel/acpi/sleep.c
+Auto-merging arch/x86/kernel/acpi/boot.c
+Auto-merging arch/x86/include/asm/msr-index.h
+Auto-merging MAINTAINERS
+Auto-merging Documentation/kernel-parameters.txt
+Auto-merging CREDITS
+Merge made by the 'recursive' strategy.
+ CREDITS                                            |    1 +
+ Documentation/acpi/initrd_table_override.txt       |   94 +
+ Documentation/kernel-parameters.txt                |   20 +
+ Documentation/scheduler/numa-problem.txt           |  236 +++
+ Documentation/x86/boot.txt                         |    4 +-
+ MAINTAINERS                                        |    8 +
+ arch/ia64/kernel/time.c                            |    8 +-
+ arch/powerpc/kernel/time.c                         |    4 +-
+ arch/s390/kernel/vtime.c                           |    4 +
+ arch/s390/kvm/kvm-s390.c                           |    4 -
+ arch/sh/mm/Kconfig                                 |    1 +
+ arch/x86/Kconfig                                   |   35 +-
+ arch/x86/include/asm/cpufeature.h                  |    1 +
+ arch/x86/include/asm/mce.h                         |   21 +-
+ arch/x86/include/asm/msr-index.h                   |    2 +
+ arch/x86/include/asm/page.h                        |    3 +-
+ arch/x86/include/asm/page_32.h                     |    1 +
+ arch/x86/include/asm/page_64.h                     |   36 +
+ arch/x86/include/asm/page_64_types.h               |   22 -
+ arch/x86/include/asm/pgtable.h                     |    6 +
+ arch/x86/include/asm/pgtable_64.h                  |    5 +
+ arch/x86/include/asm/processor.h                   |    2 +-
+ arch/x86/kernel/Makefile                           |    1 -
+ arch/x86/kernel/acpi/boot.c                        |    6 +
+ arch/x86/kernel/acpi/sleep.c                       |    2 +-
+ arch/x86/kernel/apic/apic.c                        |   73 +-
+ arch/x86/kernel/apic/apic_numachip.c               |    1 +
+ arch/x86/kernel/apic/io_apic.c                     |    5 +-
+ arch/x86/kernel/cpu/amd.c                          |    9 +-
+ arch/x86/kernel/cpu/intel.c                        |    2 +-
+ arch/x86/kernel/cpu/intel_cacheinfo.c              |   75 +-
+ arch/x86/kernel/cpu/mcheck/mce-internal.h          |    2 -
+ arch/x86/kernel/cpu/mcheck/mce-severity.c          |    4 +-
+ arch/x86/kernel/cpu/mcheck/mce.c                   |  209 +-
+ arch/x86/kernel/cpu/mcheck/mce_intel.c             |    8 +-
+ arch/x86/kernel/cpu/perf_event.c                   |  121 ++
+ arch/x86/kernel/cpu/perf_event.h                   |    5 +
+ arch/x86/kernel/cpu/perf_event_amd.c               |    9 +
+ arch/x86/kernel/cpu/perf_event_intel.c             |    9 +
+ arch/x86/kernel/cpu/perf_event_p6.c                |    2 +
+ arch/x86/kernel/entry_64.S                         |   41 +-
+ arch/x86/kernel/ftrace.c                           |    4 +-
+ arch/x86/kernel/head32.c                           |    4 +-
+ arch/x86/kernel/head64.c                           |    4 +-
+ arch/x86/kernel/hpet.c                             |    4 +-
+ arch/x86/kernel/process.c                          |   39 +-
+ arch/x86/kernel/ptrace.c                           |    7 +
+ arch/x86/kernel/rtc.c                              |    6 -
+ arch/x86/kernel/setup.c                            |   20 +-
+ arch/x86/kernel/smpboot.c                          |    2 +-
+ arch/x86/kernel/tsc.c                              |    6 +
+ arch/x86/kernel/x8664_ksyms_64.c                   |    3 +
+ arch/x86/lguest/boot.c                             |    2 +-
+ arch/x86/lib/copy_page_64.S                        |  120 +-
+ arch/x86/mm/gup.c                                  |   23 +-
+ arch/x86/mm/init_64.c                              |   18 +-
+ arch/x86/mm/pageattr.c                             |    8 +-
+ arch/x86/mm/pgtable.c                              |    8 +-
+ arch/x86/mm/physaddr.c                             |   51 +-
+ arch/x86/platform/efi/efi.c                        |    4 +-
+ arch/x86/realmode/init.c                           |    8 +-
+ drivers/acpi/Kconfig                               |    9 +
+ drivers/acpi/osl.c                                 |  202 +-
+ drivers/base/core.c                                |   21 +
+ fs/proc/base.c                                     |   78 -
+ include/asm-generic/pgtable.h                      |   59 +
+ include/linux/acpi.h                               |   16 +
+ include/linux/device.h                             |    7 +
+ include/linux/earlycpio.h                          |   17 +
+ include/linux/ftrace_event.h                       |   14 +-
+ include/linux/hardirq.h                            |   15 +-
+ include/linux/huge_mm.h                            |   12 +
+ include/linux/hugetlb.h                            |    8 +-
+ include/linux/init_task.h                          |    8 +
+ include/linux/irq.h                                |    9 +
+ include/linux/irqdesc.h                            |    3 +
+ include/linux/kernel.h                             |    7 +-
+ include/linux/kernel_stat.h                        |    9 +-
+ include/linux/kvm_host.h                           |   12 +-
+ include/linux/mempolicy.h                          |    8 +
+ include/linux/migrate.h                            |    7 +
+ include/linux/mm.h                                 |   99 +-
+ include/linux/mm_types.h                           |   10 +
+ include/linux/mmzone.h                             |   14 +-
+ include/linux/page-flags-layout.h                  |   83 +
+ include/linux/ring_buffer.h                        |    3 +-
+ include/linux/sched.h                              |   74 +-
+ include/linux/vtime.h                              |   47 +
+ include/trace/ftrace.h                             |    3 +-
+ include/trace/syscall.h                            |   23 -
+ init/Kconfig                                       |   81 +
+ kernel/bounds.c                                    |    4 +
+ kernel/events/hw_breakpoint.c                      |   12 +-
+ kernel/irq/chip.c                                  |    1 +
+ kernel/irq/manage.c                                |   41 +-
+ kernel/irq/resend.c                                |    8 +
+ kernel/lockdep_proc.c                              |    2 +-
+ kernel/sched/auto_group.c                          |   68 +-
+ kernel/sched/auto_group.h                          |    9 +-
+ kernel/sched/core.c                                |   90 +-
+ kernel/sched/cputime.c                             |   20 +-
+ kernel/sched/debug.c                               |   36 +-
+ kernel/sched/fair.c                                | 2135 ++++++++++++++++----
+ kernel/sched/features.h                            |   15 +
+ kernel/sched/sched.h                               |   98 +-
+ kernel/softirq.c                                   |    6 +-
+ kernel/sysctl.c                                    |   51 +-
+ kernel/time/tick-sched.c                           |  113 +-
+ kernel/trace/Kconfig                               |    1 +
+ kernel/trace/ftrace.c                              |    6 +-
+ kernel/trace/ring_buffer.c                         |   51 +-
+ kernel/trace/trace.c                               |  372 ++--
+ kernel/trace/trace.h                               |   14 +-
+ kernel/trace/trace_branch.c                        |    4 +-
+ kernel/trace/trace_events.c                        |   51 +-
+ kernel/trace/trace_events_filter.c                 |    4 +-
+ kernel/trace/trace_functions.c                     |    5 +-
+ kernel/trace/trace_functions_graph.c               |    6 +-
+ kernel/trace/trace_irqsoff.c                       |   14 +-
+ kernel/trace/trace_kprobe.c                        |   10 +-
+ kernel/trace/trace_probe.c                         |   14 +-
+ kernel/trace/trace_sched_switch.c                  |    4 +-
+ kernel/trace/trace_sched_wakeup.c                  |   10 +-
+ kernel/trace/trace_selftest.c                      |   13 +-
+ kernel/trace/trace_syscalls.c                      |   61 +-
+ kernel/trace/trace_uprobe.c                        |    2 +-
+ lib/Makefile                                       |    2 +-
+ lib/earlycpio.c                                    |  145 ++
+ mm/Makefile                                        |    1 +
+ mm/huge_memory.c                                   |  166 +-
+ mm/hugetlb.c                                       |   10 +-
+ mm/internal.h                                      |    5 +-
+ mm/memcontrol.c                                    |    7 +-
+ mm/memory.c                                        |  110 +-
+ mm/mempolicy.c                                     |  185 +-
+ mm/migrate.c                                       |  106 +-
+ mm/mprotect.c                                      |   69 +-
+ mm/numa.c                                          |   73 +
+ mm/pgtable-generic.c                               |    9 +-
+ scripts/kconfig/Makefile                           |    7 +-
+ tools/kvm/.gitignore                               |   12 +
+ tools/kvm/CREDITS-Git                              |   30 +
+ tools/kvm/Documentation/kernel-debugging.txt       |   15 +
+ tools/kvm/Documentation/kvm-balloon.txt            |   24 +
+ tools/kvm/Documentation/kvm-debug.txt              |   16 +
+ tools/kvm/Documentation/kvm-list.txt               |   16 +
+ tools/kvm/Documentation/kvm-pause.txt              |   16 +
+ tools/kvm/Documentation/kvm-resume.txt             |   16 +
+ tools/kvm/Documentation/kvm-run.txt                |   62 +
+ tools/kvm/Documentation/kvm-sandbox.txt            |   16 +
+ tools/kvm/Documentation/kvm-setup.txt              |   15 +
+ tools/kvm/Documentation/kvm-stat.txt               |   19 +
+ tools/kvm/Documentation/kvm-stop.txt               |   16 +
+ tools/kvm/Documentation/kvm-version.txt            |   21 +
+ tools/kvm/Documentation/virtio-console.txt         |   41 +
+ tools/kvm/Makefile                                 |  457 +++++
+ tools/kvm/README                                   |  112 +
+ tools/kvm/builtin-balloon.c                        |   80 +
+ tools/kvm/builtin-debug.c                          |  110 +
+ tools/kvm/builtin-help.c                           |   63 +
+ tools/kvm/builtin-list.c                           |  149 ++
+ tools/kvm/builtin-pause.c                          |   88 +
+ tools/kvm/builtin-resume.c                         |   88 +
+ tools/kvm/builtin-run.c                            |  697 +++++++
+ tools/kvm/builtin-sandbox.c                        |    9 +
+ tools/kvm/builtin-setup.c                          |  262 +++
+ tools/kvm/builtin-stat.c                           |  127 ++
+ tools/kvm/builtin-stop.c                           |   70 +
+ tools/kvm/builtin-version.c                        |   15 +
+ tools/kvm/code16gcc.h                              |   15 +
+ tools/kvm/command-list.txt                         |   15 +
+ tools/kvm/config/feature-tests.mak                 |  177 ++
+ tools/kvm/config/utilities.mak                     |  196 ++
+ tools/kvm/disk/blk.c                               |   76 +
+ tools/kvm/disk/core.c                              |  354 ++++
+ tools/kvm/disk/qcow.c                              | 1529 ++++++++++++++
+ tools/kvm/disk/raw.c                               |  141 ++
+ tools/kvm/framebuffer.c                            |   80 +
+ tools/kvm/guest/init.c                             |   72 +
+ tools/kvm/guest_compat.c                           |   99 +
+ tools/kvm/hw/i8042.c                               |  355 ++++
+ tools/kvm/hw/pci-shmem.c                           |  405 ++++
+ tools/kvm/hw/rtc.c                                 |  149 ++
+ tools/kvm/hw/serial.c                              |  452 +++++
+ tools/kvm/hw/vesa.c                                |   89 +
+ tools/kvm/include/asm/hweight.h                    |    8 +
+ tools/kvm/include/bios/memcpy.h                    |    9 +
+ tools/kvm/include/kvm/8250-serial.h                |   11 +
+ tools/kvm/include/kvm/apic.h                       |   17 +
+ tools/kvm/include/kvm/brlock.h                     |   41 +
+ tools/kvm/include/kvm/builtin-balloon.h            |    9 +
+ tools/kvm/include/kvm/builtin-debug.h              |   20 +
+ tools/kvm/include/kvm/builtin-help.h               |    6 +
+ tools/kvm/include/kvm/builtin-list.h               |   10 +
+ tools/kvm/include/kvm/builtin-pause.h              |    9 +
+ tools/kvm/include/kvm/builtin-resume.h             |    9 +
+ tools/kvm/include/kvm/builtin-run.h                |   11 +
+ tools/kvm/include/kvm/builtin-sandbox.h            |    6 +
+ tools/kvm/include/kvm/builtin-setup.h              |   11 +
+ tools/kvm/include/kvm/builtin-stat.h               |    9 +
+ tools/kvm/include/kvm/builtin-stop.h               |    9 +
+ tools/kvm/include/kvm/builtin-version.h            |    6 +
+ tools/kvm/include/kvm/compiler.h                   |   10 +
+ tools/kvm/include/kvm/disk-image.h                 |   96 +
+ tools/kvm/include/kvm/e820.h                       |   13 +
+ tools/kvm/include/kvm/framebuffer.h                |   36 +
+ tools/kvm/include/kvm/guest_compat.h               |    9 +
+ tools/kvm/include/kvm/i8042.h                      |   12 +
+ tools/kvm/include/kvm/ioeventfd.h                  |   28 +
+ tools/kvm/include/kvm/ioport.h                     |   70 +
+ tools/kvm/include/kvm/irq.h                        |   33 +
+ tools/kvm/include/kvm/kvm-cmd.h                    |   17 +
+ tools/kvm/include/kvm/kvm-config.h                 |   60 +
+ tools/kvm/include/kvm/kvm-cpu.h                    |   26 +
+ tools/kvm/include/kvm/kvm-ipc.h                    |   26 +
+ tools/kvm/include/kvm/kvm.h                        |  121 ++
+ tools/kvm/include/kvm/msi.h                        |   10 +
+ tools/kvm/include/kvm/mutex.h                      |   33 +
+ tools/kvm/include/kvm/parse-options.h              |  218 ++
+ tools/kvm/include/kvm/pci-shmem.h                  |   32 +
+ tools/kvm/include/kvm/pci.h                        |   95 +
+ tools/kvm/include/kvm/qcow.h                       |  133 ++
+ tools/kvm/include/kvm/rbtree-interval.h            |   28 +
+ tools/kvm/include/kvm/read-write.h                 |   43 +
+ tools/kvm/include/kvm/rtc.h                        |    9 +
+ tools/kvm/include/kvm/rwsem.h                      |   39 +
+ tools/kvm/include/kvm/sdl.h                        |   28 +
+ tools/kvm/include/kvm/segment.h                    |   21 +
+ tools/kvm/include/kvm/strbuf.h                     |   20 +
+ tools/kvm/include/kvm/symbol.h                     |   30 +
+ tools/kvm/include/kvm/term.h                       |   24 +
+ tools/kvm/include/kvm/threadpool.h                 |   38 +
+ tools/kvm/include/kvm/types.h                      |    7 +
+ tools/kvm/include/kvm/uip.h                        |  360 ++++
+ tools/kvm/include/kvm/util-init.h                  |   51 +
+ tools/kvm/include/kvm/util.h                       |   97 +
+ tools/kvm/include/kvm/vesa.h                       |   18 +
+ tools/kvm/include/kvm/virtio-9p.h                  |   76 +
+ tools/kvm/include/kvm/virtio-balloon.h             |    9 +
+ tools/kvm/include/kvm/virtio-blk.h                 |   12 +
+ tools/kvm/include/kvm/virtio-console.h             |   10 +
+ tools/kvm/include/kvm/virtio-mmio.h                |   58 +
+ tools/kvm/include/kvm/virtio-net.h                 |   30 +
+ tools/kvm/include/kvm/virtio-pci-dev.h             |   38 +
+ tools/kvm/include/kvm/virtio-pci.h                 |   49 +
+ tools/kvm/include/kvm/virtio-rng.h                 |    9 +
+ tools/kvm/include/kvm/virtio-scsi.h                |   26 +
+ tools/kvm/include/kvm/virtio.h                     |  102 +
+ tools/kvm/include/kvm/vnc.h                        |   22 +
+ tools/kvm/include/linux/bitops.h                   |   33 +
+ tools/kvm/include/linux/byteorder.h                |    7 +
+ tools/kvm/include/linux/compiler.h                 |   20 +
+ tools/kvm/include/linux/kernel.h                   |   41 +
+ tools/kvm/include/linux/module.h                   |    6 +
+ tools/kvm/include/linux/prefetch.h                 |    6 +
+ tools/kvm/include/linux/stddef.h                   |   16 +
+ tools/kvm/include/linux/types.h                    |   51 +
+ tools/kvm/ioeventfd.c                              |  216 ++
+ tools/kvm/ioport.c                                 |  198 ++
+ tools/kvm/kvm-cmd.c                                |   91 +
+ tools/kvm/kvm-cpu.c                                |  242 +++
+ tools/kvm/kvm-ipc.c                                |  498 +++++
+ tools/kvm/kvm.c                                    |  458 +++++
+ tools/kvm/main.c                                   |   19 +
+ tools/kvm/mmio.c                                   |  139 ++
+ tools/kvm/net/uip/arp.c                            |   30 +
+ tools/kvm/net/uip/buf.c                            |  114 ++
+ tools/kvm/net/uip/core.c                           |  190 ++
+ tools/kvm/net/uip/csum.c                           |   92 +
+ tools/kvm/net/uip/dhcp.c                           |  202 ++
+ tools/kvm/net/uip/icmp.c                           |   29 +
+ tools/kvm/net/uip/ipv4.c                           |   29 +
+ tools/kvm/net/uip/tcp.c                            |  345 ++++
+ tools/kvm/net/uip/udp.c                            |  236 +++
+ tools/kvm/pci.c                                    |  215 ++
+ tools/kvm/powerpc/boot.c                           |    8 +
+ tools/kvm/powerpc/cpu_info.c                       |  195 ++
+ tools/kvm/powerpc/cpu_info.h                       |   42 +
+ tools/kvm/powerpc/include/kvm/barrier.h            |    6 +
+ tools/kvm/powerpc/include/kvm/kvm-arch.h           |   68 +
+ tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h       |   76 +
+ tools/kvm/powerpc/ioport.c                         |   18 +
+ tools/kvm/powerpc/irq.c                            |   56 +
+ tools/kvm/powerpc/kvm-cpu.c                        |  290 +++
+ tools/kvm/powerpc/kvm.c                            |  529 +++++
+ tools/kvm/powerpc/spapr.h                          |   93 +
+ tools/kvm/powerpc/spapr_hcall.c                    |  134 ++
+ tools/kvm/powerpc/spapr_hvcons.c                   |  108 +
+ tools/kvm/powerpc/spapr_hvcons.h                   |   19 +
+ tools/kvm/powerpc/spapr_pci.c                      |  423 ++++
+ tools/kvm/powerpc/spapr_pci.h                      |   57 +
+ tools/kvm/powerpc/spapr_rtas.c                     |  233 +++
+ tools/kvm/powerpc/xics.c                           |  522 +++++
+ tools/kvm/powerpc/xics.h                           |   18 +
+ tools/kvm/symbol.c                                 |  133 ++
+ tools/kvm/term.c                                   |  171 ++
+ tools/kvm/tests/Makefile                           |   19 +
+ tools/kvm/tests/boot/Makefile                      |   13 +
+ tools/kvm/tests/boot/init.c                        |   11 +
+ tools/kvm/tests/kernel/.gitignore                  |    2 +
+ tools/kvm/tests/kernel/Makefile                    |   20 +
+ tools/kvm/tests/kernel/README                      |   16 +
+ tools/kvm/tests/kernel/kernel.S                    |    8 +
+ tools/kvm/tests/pit/.gitignore                     |    2 +
+ tools/kvm/tests/pit/Makefile                       |   20 +
+ tools/kvm/tests/pit/README                         |   16 +
+ tools/kvm/tests/pit/tick.S                         |  101 +
+ tools/kvm/ui/sdl.c                                 |  321 +++
+ tools/kvm/ui/vnc.c                                 |  248 +++
+ tools/kvm/util/KVMTOOLS-VERSION-GEN                |   40 +
+ tools/kvm/util/generate-cmdlist.sh                 |   23 +
+ tools/kvm/util/init.c                              |   69 +
+ tools/kvm/util/kvm-ifup-vbr0                       |    6 +
+ tools/kvm/util/parse-options.c                     |  577 ++++++
+ tools/kvm/util/rbtree-interval.c                   |  118 ++
+ tools/kvm/util/read-write.c                        |  354 ++++
+ tools/kvm/util/set_private_br.sh                   |   51 +
+ tools/kvm/util/strbuf.c                            |   62 +
+ tools/kvm/util/threadpool.c                        |  173 ++
+ tools/kvm/util/util.c                              |  133 ++
+ tools/kvm/virtio/9p-pdu.c                          |  287 +++
+ tools/kvm/virtio/9p.c                              | 1432 +++++++++++++
+ tools/kvm/virtio/balloon.c                         |  270 +++
+ tools/kvm/virtio/blk.c                             |  315 +++
+ tools/kvm/virtio/console.c                         |  203 ++
+ tools/kvm/virtio/core.c                            |  233 +++
+ tools/kvm/virtio/mmio.c                            |  264 +++
+ tools/kvm/virtio/net.c                             |  670 ++++++
+ tools/kvm/virtio/pci.c                             |  398 ++++
+ tools/kvm/virtio/rng.c                             |  193 ++
+ tools/kvm/virtio/scsi.c                            |  309 +++
+ tools/kvm/x86/bios.c                               |  174 ++
+ tools/kvm/x86/bios/.gitignore                      |    3 +
+ tools/kvm/x86/bios/bios-rom.S                      |   12 +
+ tools/kvm/x86/bios/e820.c                          |   72 +
+ tools/kvm/x86/bios/entry.S                         |   92 +
+ tools/kvm/x86/bios/gen-offsets.sh                  |   14 +
+ tools/kvm/x86/bios/int10.c                         |  110 +
+ tools/kvm/x86/bios/int15.c                         |   18 +
+ tools/kvm/x86/bios/local.S                         |    7 +
+ tools/kvm/x86/bios/macro.S                         |   25 +
+ tools/kvm/x86/bios/memcpy.c                        |   23 +
+ tools/kvm/x86/bios/rom.ld.S                        |   16 +
+ tools/kvm/x86/boot.c                               |   41 +
+ tools/kvm/x86/cpuid.c                              |   60 +
+ tools/kvm/x86/include/kvm/assembly.h               |   24 +
+ tools/kvm/x86/include/kvm/barrier.h                |   20 +
+ tools/kvm/x86/include/kvm/bios-export.h            |   13 +
+ tools/kvm/x86/include/kvm/bios.h                   |   93 +
+ tools/kvm/x86/include/kvm/boot-protocol.h          |   16 +
+ tools/kvm/x86/include/kvm/cpufeature.h             |   41 +
+ tools/kvm/x86/include/kvm/interrupt.h              |   26 +
+ tools/kvm/x86/include/kvm/kvm-arch.h               |   43 +
+ tools/kvm/x86/include/kvm/kvm-cpu-arch.h           |   49 +
+ tools/kvm/x86/include/kvm/mptable.h                |    9 +
+ tools/kvm/x86/interrupt.c                          |   28 +
+ tools/kvm/x86/ioport.c                             |   77 +
+ tools/kvm/x86/irq.c                                |  224 ++
+ tools/kvm/x86/kvm-cpu.c                            |  425 ++++
+ tools/kvm/x86/kvm.c                                |  362 ++++
+ tools/kvm/x86/mptable.c                            |  289 +++
+ tools/lib/traceevent/Makefile                      |    2 +-
+ tools/lib/traceevent/event-parse.c                 |   22 +-
+ tools/perf/Documentation/Makefile                  |   31 +-
+ tools/perf/Documentation/android.txt               |   78 +
+ tools/perf/Documentation/perf-diff.txt             |   60 +
+ tools/perf/Documentation/perf-inject.txt           |   11 +
+ tools/perf/Documentation/perf-stat.txt             |    5 +
+ tools/perf/Documentation/perf-trace.txt            |    6 +
+ tools/perf/Makefile                                |  157 +-
+ tools/perf/arch/common.c                           |  211 ++
+ tools/perf/arch/common.h                           |   10 +
+ tools/perf/builtin-annotate.c                      |   17 +-
+ tools/perf/builtin-buildid-cache.c                 |    1 +
+ tools/perf/builtin-buildid-list.c                  |    6 +-
+ tools/perf/builtin-diff.c                          |  437 +++-
+ tools/perf/builtin-evlist.c                        |    5 +-
+ tools/perf/builtin-inject.c                        |  195 +-
+ tools/perf/builtin-kmem.c                          |    5 +-
+ tools/perf/builtin-kvm.c                           |   35 +-
+ tools/perf/builtin-lock.c                          |    2 -
+ tools/perf/builtin-record.c                        |   40 +-
+ tools/perf/builtin-report.c                        |   23 +-
+ tools/perf/builtin-sched.c                         |    8 +-
+ tools/perf/builtin-script.c                        |   87 +-
+ tools/perf/builtin-stat.c                          |   42 +-
+ tools/perf/builtin-timechart.c                     |    5 +-
+ tools/perf/builtin-top.c                           |   17 +-
+ tools/perf/builtin-trace.c                         |  403 +++-
+ tools/perf/config/feature-tests.mak                |   25 +-
+ tools/perf/config/utilities.mak                    |   10 +-
+ tools/perf/perf.c                                  |    5 +
+ tools/perf/perf.h                                  |   18 +-
+ tools/perf/tests/attr.c                            |  174 ++
+ tools/perf/tests/attr.py                           |  322 +++
+ tools/perf/tests/attr/README                       |   64 +
+ tools/perf/tests/attr/base-record                  |   39 +
+ tools/perf/tests/attr/base-stat                    |   39 +
+ tools/perf/tests/attr/test-record-basic            |    5 +
+ tools/perf/tests/attr/test-record-branch-any       |    8 +
+ .../perf/tests/attr/test-record-branch-filter-any  |    8 +
+ .../tests/attr/test-record-branch-filter-any_call  |    8 +
+ .../tests/attr/test-record-branch-filter-any_ret   |    8 +
+ tools/perf/tests/attr/test-record-branch-filter-hv |    8 +
+ .../tests/attr/test-record-branch-filter-ind_call  |    8 +
+ tools/perf/tests/attr/test-record-branch-filter-k  |    8 +
+ tools/perf/tests/attr/test-record-branch-filter-u  |    8 +
+ tools/perf/tests/attr/test-record-count            |    8 +
+ tools/perf/tests/attr/test-record-data             |    8 +
+ tools/perf/tests/attr/test-record-freq             |    6 +
+ tools/perf/tests/attr/test-record-graph-default    |    6 +
+ tools/perf/tests/attr/test-record-graph-dwarf      |   10 +
+ tools/perf/tests/attr/test-record-graph-fp         |    6 +
+ tools/perf/tests/attr/test-record-group            |   17 +
+ tools/perf/tests/attr/test-record-group1           |   20 +
+ tools/perf/tests/attr/test-record-no-delay         |    9 +
+ tools/perf/tests/attr/test-record-no-inherit       |    7 +
+ tools/perf/tests/attr/test-record-no-samples       |    6 +
+ tools/perf/tests/attr/test-record-period           |    7 +
+ tools/perf/tests/attr/test-record-raw              |    7 +
+ tools/perf/tests/attr/test-stat-basic              |    6 +
+ tools/perf/tests/attr/test-stat-default            |   64 +
+ tools/perf/tests/attr/test-stat-detailed-1         |  101 +
+ tools/perf/tests/attr/test-stat-detailed-2         |  155 ++
+ tools/perf/tests/attr/test-stat-detailed-3         |  173 ++
+ tools/perf/tests/attr/test-stat-group              |   15 +
+ tools/perf/tests/attr/test-stat-group1             |   17 +
+ tools/perf/tests/attr/test-stat-no-inherit         |    7 +
+ tools/perf/{ => tests}/builtin-test.c              |   69 +-
+ .../{util/dso-test-data.c => tests/dso-data.c}     |    1 +
+ .../parse-events-test.c => tests/parse-events.c}   |   68 +
+ tools/perf/ui/browsers/annotate.c                  |   45 +-
+ tools/perf/ui/browsers/hists.c                     |   97 +-
+ tools/perf/ui/browsers/scripts.c                   |  189 ++
+ tools/perf/ui/gtk/browser.c                        |    4 +-
+ tools/perf/ui/hist.c                               |  138 +-
+ tools/perf/ui/stdio/hist.c                         |    2 +-
+ tools/perf/util/PERF-VERSION-GEN                   |   14 +-
+ tools/perf/util/annotate.c                         |   72 +-
+ tools/perf/util/annotate.h                         |   10 +-
+ tools/perf/util/build-id.c                         |   27 +-
+ tools/perf/util/build-id.h                         |   11 +-
+ tools/perf/util/dso.c                              |  595 ++++++
+ tools/perf/util/dso.h                              |  148 ++
+ tools/perf/util/event.c                            |  228 +--
+ tools/perf/util/event.h                            |    9 +-
+ tools/perf/util/evlist.c                           |    3 -
+ tools/perf/util/header.c                           |   13 +
+ tools/perf/util/header.h                           |    1 +
+ tools/perf/util/hist.c                             |  100 +
+ tools/perf/util/hist.h                             |   49 +-
+ tools/perf/util/machine.c                          |  464 +++++
+ tools/perf/util/machine.h                          |  148 ++
+ tools/perf/util/map.c                              |  182 +-
+ tools/perf/util/map.h                              |   93 -
+ tools/perf/util/parse-events.c                     |   30 +-
+ tools/perf/util/parse-events.h                     |    2 +
+ tools/perf/util/parse-events.l                     |    2 +
+ tools/perf/util/parse-events.y                     |   18 +
+ tools/perf/util/pmu.c                              |    7 +-
+ tools/perf/util/python.c                           |    2 +
+ tools/perf/util/rblist.c                           |    4 +-
+ .../util/scripting-engines/trace-event-python.c    |    1 -
+ tools/perf/util/session.c                          |    4 +-
+ tools/perf/util/session.h                          |    5 +-
+ tools/perf/util/sort.h                             |   45 +-
+ tools/perf/util/strbuf.c                           |    8 +-
+ tools/perf/util/string.c                           |   18 +
+ tools/perf/util/symbol.c                           |  658 +-----
+ tools/perf/util/symbol.h                           |  161 +-
+ tools/perf/util/thread.c                           |   41 +-
+ tools/perf/util/thread.h                           |    2 +
+ tools/perf/util/trace-event-read.c                 |    2 -
+ tools/perf/util/util.c                             |   35 +
+ tools/perf/util/util.h                             |    8 +
+ 475 files changed, 36118 insertions(+), 3207 deletions(-)
+ create mode 100644 Documentation/acpi/initrd_table_override.txt
+ create mode 100644 Documentation/scheduler/numa-problem.txt
+ create mode 100644 include/linux/earlycpio.h
+ create mode 100644 include/linux/page-flags-layout.h
+ create mode 100644 include/linux/vtime.h
+ create mode 100644 lib/earlycpio.c
+ create mode 100644 mm/numa.c
+ create mode 100644 tools/kvm/.gitignore
+ create mode 100644 tools/kvm/CREDITS-Git
+ create mode 100644 tools/kvm/Documentation/kernel-debugging.txt
+ create mode 100644 tools/kvm/Documentation/kvm-balloon.txt
+ create mode 100644 tools/kvm/Documentation/kvm-debug.txt
+ create mode 100644 tools/kvm/Documentation/kvm-list.txt
+ create mode 100644 tools/kvm/Documentation/kvm-pause.txt
+ create mode 100644 tools/kvm/Documentation/kvm-resume.txt
+ create mode 100644 tools/kvm/Documentation/kvm-run.txt
+ create mode 100644 tools/kvm/Documentation/kvm-sandbox.txt
+ create mode 100644 tools/kvm/Documentation/kvm-setup.txt
+ create mode 100644 tools/kvm/Documentation/kvm-stat.txt
+ create mode 100644 tools/kvm/Documentation/kvm-stop.txt
+ create mode 100644 tools/kvm/Documentation/kvm-version.txt
+ create mode 100644 tools/kvm/Documentation/virtio-console.txt
+ create mode 100644 tools/kvm/Makefile
+ create mode 100644 tools/kvm/README
+ create mode 100644 tools/kvm/builtin-balloon.c
+ create mode 100644 tools/kvm/builtin-debug.c
+ create mode 100644 tools/kvm/builtin-help.c
+ create mode 100644 tools/kvm/builtin-list.c
+ create mode 100644 tools/kvm/builtin-pause.c
+ create mode 100644 tools/kvm/builtin-resume.c
+ create mode 100644 tools/kvm/builtin-run.c
+ create mode 100644 tools/kvm/builtin-sandbox.c
+ create mode 100644 tools/kvm/builtin-setup.c
+ create mode 100644 tools/kvm/builtin-stat.c
+ create mode 100644 tools/kvm/builtin-stop.c
+ create mode 100644 tools/kvm/builtin-version.c
+ create mode 100644 tools/kvm/code16gcc.h
+ create mode 100644 tools/kvm/command-list.txt
+ create mode 100644 tools/kvm/config/feature-tests.mak
+ create mode 100644 tools/kvm/config/utilities.mak
+ create mode 100644 tools/kvm/disk/blk.c
+ create mode 100644 tools/kvm/disk/core.c
+ create mode 100644 tools/kvm/disk/qcow.c
+ create mode 100644 tools/kvm/disk/raw.c
+ create mode 100644 tools/kvm/framebuffer.c
+ create mode 100644 tools/kvm/guest/init.c
+ create mode 100644 tools/kvm/guest_compat.c
+ create mode 100644 tools/kvm/hw/i8042.c
+ create mode 100644 tools/kvm/hw/pci-shmem.c
+ create mode 100644 tools/kvm/hw/rtc.c
+ create mode 100644 tools/kvm/hw/serial.c
+ create mode 100644 tools/kvm/hw/vesa.c
+ create mode 100644 tools/kvm/include/asm/hweight.h
+ create mode 100644 tools/kvm/include/bios/memcpy.h
+ create mode 100644 tools/kvm/include/kvm/8250-serial.h
+ create mode 100644 tools/kvm/include/kvm/apic.h
+ create mode 100644 tools/kvm/include/kvm/brlock.h
+ create mode 100644 tools/kvm/include/kvm/builtin-balloon.h
+ create mode 100644 tools/kvm/include/kvm/builtin-debug.h
+ create mode 100644 tools/kvm/include/kvm/builtin-help.h
+ create mode 100644 tools/kvm/include/kvm/builtin-list.h
+ create mode 100644 tools/kvm/include/kvm/builtin-pause.h
+ create mode 100644 tools/kvm/include/kvm/builtin-resume.h
+ create mode 100644 tools/kvm/include/kvm/builtin-run.h
+ create mode 100644 tools/kvm/include/kvm/builtin-sandbox.h
+ create mode 100644 tools/kvm/include/kvm/builtin-setup.h
+ create mode 100644 tools/kvm/include/kvm/builtin-stat.h
+ create mode 100644 tools/kvm/include/kvm/builtin-stop.h
+ create mode 100644 tools/kvm/include/kvm/builtin-version.h
+ create mode 100644 tools/kvm/include/kvm/compiler.h
+ create mode 100644 tools/kvm/include/kvm/disk-image.h
+ create mode 100644 tools/kvm/include/kvm/e820.h
+ create mode 100644 tools/kvm/include/kvm/framebuffer.h
+ create mode 100644 tools/kvm/include/kvm/guest_compat.h
+ create mode 100644 tools/kvm/include/kvm/i8042.h
+ create mode 100644 tools/kvm/include/kvm/ioeventfd.h
+ create mode 100644 tools/kvm/include/kvm/ioport.h
+ create mode 100644 tools/kvm/include/kvm/irq.h
+ create mode 100644 tools/kvm/include/kvm/kvm-cmd.h
+ create mode 100644 tools/kvm/include/kvm/kvm-config.h
+ create mode 100644 tools/kvm/include/kvm/kvm-cpu.h
+ create mode 100644 tools/kvm/include/kvm/kvm-ipc.h
+ create mode 100644 tools/kvm/include/kvm/kvm.h
+ create mode 100644 tools/kvm/include/kvm/msi.h
+ create mode 100644 tools/kvm/include/kvm/mutex.h
+ create mode 100644 tools/kvm/include/kvm/parse-options.h
+ create mode 100644 tools/kvm/include/kvm/pci-shmem.h
+ create mode 100644 tools/kvm/include/kvm/pci.h
+ create mode 100644 tools/kvm/include/kvm/qcow.h
+ create mode 100644 tools/kvm/include/kvm/rbtree-interval.h
+ create mode 100644 tools/kvm/include/kvm/read-write.h
+ create mode 100644 tools/kvm/include/kvm/rtc.h
+ create mode 100644 tools/kvm/include/kvm/rwsem.h
+ create mode 100644 tools/kvm/include/kvm/sdl.h
+ create mode 100644 tools/kvm/include/kvm/segment.h
+ create mode 100644 tools/kvm/include/kvm/strbuf.h
+ create mode 100644 tools/kvm/include/kvm/symbol.h
+ create mode 100644 tools/kvm/include/kvm/term.h
+ create mode 100644 tools/kvm/include/kvm/threadpool.h
+ create mode 100644 tools/kvm/include/kvm/types.h
+ create mode 100644 tools/kvm/include/kvm/uip.h
+ create mode 100644 tools/kvm/include/kvm/util-init.h
+ create mode 100644 tools/kvm/include/kvm/util.h
+ create mode 100644 tools/kvm/include/kvm/vesa.h
+ create mode 100644 tools/kvm/include/kvm/virtio-9p.h
+ create mode 100644 tools/kvm/include/kvm/virtio-balloon.h
+ create mode 100644 tools/kvm/include/kvm/virtio-blk.h
+ create mode 100644 tools/kvm/include/kvm/virtio-console.h
+ create mode 100644 tools/kvm/include/kvm/virtio-mmio.h
+ create mode 100644 tools/kvm/include/kvm/virtio-net.h
+ create mode 100644 tools/kvm/include/kvm/virtio-pci-dev.h
+ create mode 100644 tools/kvm/include/kvm/virtio-pci.h
+ create mode 100644 tools/kvm/include/kvm/virtio-rng.h
+ create mode 100644 tools/kvm/include/kvm/virtio-scsi.h
+ create mode 100644 tools/kvm/include/kvm/virtio.h
+ create mode 100644 tools/kvm/include/kvm/vnc.h
+ create mode 100644 tools/kvm/include/linux/bitops.h
+ create mode 100644 tools/kvm/include/linux/byteorder.h
+ create mode 100644 tools/kvm/include/linux/compiler.h
+ create mode 100644 tools/kvm/include/linux/kernel.h
+ create mode 100644 tools/kvm/include/linux/module.h
+ create mode 100644 tools/kvm/include/linux/prefetch.h
+ create mode 100644 tools/kvm/include/linux/stddef.h
+ create mode 100644 tools/kvm/include/linux/types.h
+ create mode 100644 tools/kvm/ioeventfd.c
+ create mode 100644 tools/kvm/ioport.c
+ create mode 100644 tools/kvm/kvm-cmd.c
+ create mode 100644 tools/kvm/kvm-cpu.c
+ create mode 100644 tools/kvm/kvm-ipc.c
+ create mode 100644 tools/kvm/kvm.c
+ create mode 100644 tools/kvm/main.c
+ create mode 100644 tools/kvm/mmio.c
+ create mode 100644 tools/kvm/net/uip/arp.c
+ create mode 100644 tools/kvm/net/uip/buf.c
+ create mode 100644 tools/kvm/net/uip/core.c
+ create mode 100644 tools/kvm/net/uip/csum.c
+ create mode 100644 tools/kvm/net/uip/dhcp.c
+ create mode 100644 tools/kvm/net/uip/icmp.c
+ create mode 100644 tools/kvm/net/uip/ipv4.c
+ create mode 100644 tools/kvm/net/uip/tcp.c
+ create mode 100644 tools/kvm/net/uip/udp.c
+ create mode 100644 tools/kvm/pci.c
+ create mode 100644 tools/kvm/powerpc/boot.c
+ create mode 100644 tools/kvm/powerpc/cpu_info.c
+ create mode 100644 tools/kvm/powerpc/cpu_info.h
+ create mode 100644 tools/kvm/powerpc/include/kvm/barrier.h
+ create mode 100644 tools/kvm/powerpc/include/kvm/kvm-arch.h
+ create mode 100644 tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h
+ create mode 100644 tools/kvm/powerpc/ioport.c
+ create mode 100644 tools/kvm/powerpc/irq.c
+ create mode 100644 tools/kvm/powerpc/kvm-cpu.c
+ create mode 100644 tools/kvm/powerpc/kvm.c
+ create mode 100644 tools/kvm/powerpc/spapr.h
+ create mode 100644 tools/kvm/powerpc/spapr_hcall.c
+ create mode 100644 tools/kvm/powerpc/spapr_hvcons.c
+ create mode 100644 tools/kvm/powerpc/spapr_hvcons.h
+ create mode 100644 tools/kvm/powerpc/spapr_pci.c
+ create mode 100644 tools/kvm/powerpc/spapr_pci.h
+ create mode 100644 tools/kvm/powerpc/spapr_rtas.c
+ create mode 100644 tools/kvm/powerpc/xics.c
+ create mode 100644 tools/kvm/powerpc/xics.h
+ create mode 100644 tools/kvm/symbol.c
+ create mode 100644 tools/kvm/term.c
+ create mode 100644 tools/kvm/tests/Makefile
+ create mode 100644 tools/kvm/tests/boot/Makefile
+ create mode 100644 tools/kvm/tests/boot/init.c
+ create mode 100644 tools/kvm/tests/kernel/.gitignore
+ create mode 100644 tools/kvm/tests/kernel/Makefile
+ create mode 100644 tools/kvm/tests/kernel/README
+ create mode 100644 tools/kvm/tests/kernel/kernel.S
+ create mode 100644 tools/kvm/tests/pit/.gitignore
+ create mode 100644 tools/kvm/tests/pit/Makefile
+ create mode 100644 tools/kvm/tests/pit/README
+ create mode 100644 tools/kvm/tests/pit/tick.S
+ create mode 100644 tools/kvm/ui/sdl.c
+ create mode 100644 tools/kvm/ui/vnc.c
+ create mode 100755 tools/kvm/util/KVMTOOLS-VERSION-GEN
+ create mode 100755 tools/kvm/util/generate-cmdlist.sh
+ create mode 100644 tools/kvm/util/init.c
+ create mode 100755 tools/kvm/util/kvm-ifup-vbr0
+ create mode 100644 tools/kvm/util/parse-options.c
+ create mode 100644 tools/kvm/util/rbtree-interval.c
+ create mode 100644 tools/kvm/util/read-write.c
+ create mode 100755 tools/kvm/util/set_private_br.sh
+ create mode 100644 tools/kvm/util/strbuf.c
+ create mode 100644 tools/kvm/util/threadpool.c
+ create mode 100644 tools/kvm/util/util.c
+ create mode 100644 tools/kvm/virtio/9p-pdu.c
+ create mode 100644 tools/kvm/virtio/9p.c
+ create mode 100644 tools/kvm/virtio/balloon.c
+ create mode 100644 tools/kvm/virtio/blk.c
+ create mode 100644 tools/kvm/virtio/console.c
+ create mode 100644 tools/kvm/virtio/core.c
+ create mode 100644 tools/kvm/virtio/mmio.c
+ create mode 100644 tools/kvm/virtio/net.c
+ create mode 100644 tools/kvm/virtio/pci.c
+ create mode 100644 tools/kvm/virtio/rng.c
+ create mode 100644 tools/kvm/virtio/scsi.c
+ create mode 100644 tools/kvm/x86/bios.c
+ create mode 100644 tools/kvm/x86/bios/.gitignore
+ create mode 100644 tools/kvm/x86/bios/bios-rom.S
+ create mode 100644 tools/kvm/x86/bios/e820.c
+ create mode 100644 tools/kvm/x86/bios/entry.S
+ create mode 100644 tools/kvm/x86/bios/gen-offsets.sh
+ create mode 100644 tools/kvm/x86/bios/int10.c
+ create mode 100644 tools/kvm/x86/bios/int15.c
+ create mode 100644 tools/kvm/x86/bios/local.S
+ create mode 100644 tools/kvm/x86/bios/macro.S
+ create mode 100644 tools/kvm/x86/bios/memcpy.c
+ create mode 100644 tools/kvm/x86/bios/rom.ld.S
+ create mode 100644 tools/kvm/x86/boot.c
+ create mode 100644 tools/kvm/x86/cpuid.c
+ create mode 100644 tools/kvm/x86/include/kvm/assembly.h
+ create mode 100644 tools/kvm/x86/include/kvm/barrier.h
+ create mode 100644 tools/kvm/x86/include/kvm/bios-export.h
+ create mode 100644 tools/kvm/x86/include/kvm/bios.h
+ create mode 100644 tools/kvm/x86/include/kvm/boot-protocol.h
+ create mode 100644 tools/kvm/x86/include/kvm/cpufeature.h
+ create mode 100644 tools/kvm/x86/include/kvm/interrupt.h
+ create mode 100644 tools/kvm/x86/include/kvm/kvm-arch.h
+ create mode 100644 tools/kvm/x86/include/kvm/kvm-cpu-arch.h
+ create mode 100644 tools/kvm/x86/include/kvm/mptable.h
+ create mode 100644 tools/kvm/x86/interrupt.c
+ create mode 100644 tools/kvm/x86/ioport.c
+ create mode 100644 tools/kvm/x86/irq.c
+ create mode 100644 tools/kvm/x86/kvm-cpu.c
+ create mode 100644 tools/kvm/x86/kvm.c
+ create mode 100644 tools/kvm/x86/mptable.c
+ create mode 100644 tools/perf/Documentation/android.txt
+ create mode 100644 tools/perf/arch/common.c
+ create mode 100644 tools/perf/arch/common.h
+ create mode 100644 tools/perf/tests/attr.c
+ create mode 100644 tools/perf/tests/attr.py
+ create mode 100644 tools/perf/tests/attr/README
+ create mode 100644 tools/perf/tests/attr/base-record
+ create mode 100644 tools/perf/tests/attr/base-stat
+ create mode 100644 tools/perf/tests/attr/test-record-basic
+ create mode 100644 tools/perf/tests/attr/test-record-branch-any
+ create mode 100644 tools/perf/tests/attr/test-record-branch-filter-any
+ create mode 100644 tools/perf/tests/attr/test-record-branch-filter-any_call
+ create mode 100644 tools/perf/tests/attr/test-record-branch-filter-any_ret
+ create mode 100644 tools/perf/tests/attr/test-record-branch-filter-hv
+ create mode 100644 tools/perf/tests/attr/test-record-branch-filter-ind_call
+ create mode 100644 tools/perf/tests/attr/test-record-branch-filter-k
+ create mode 100644 tools/perf/tests/attr/test-record-branch-filter-u
+ create mode 100644 tools/perf/tests/attr/test-record-count
+ create mode 100644 tools/perf/tests/attr/test-record-data
+ create mode 100644 tools/perf/tests/attr/test-record-freq
+ create mode 100644 tools/perf/tests/attr/test-record-graph-default
+ create mode 100644 tools/perf/tests/attr/test-record-graph-dwarf
+ create mode 100644 tools/perf/tests/attr/test-record-graph-fp
+ create mode 100644 tools/perf/tests/attr/test-record-group
+ create mode 100644 tools/perf/tests/attr/test-record-group1
+ create mode 100644 tools/perf/tests/attr/test-record-no-delay
+ create mode 100644 tools/perf/tests/attr/test-record-no-inherit
+ create mode 100644 tools/perf/tests/attr/test-record-no-samples
+ create mode 100644 tools/perf/tests/attr/test-record-period
+ create mode 100644 tools/perf/tests/attr/test-record-raw
+ create mode 100644 tools/perf/tests/attr/test-stat-basic
+ create mode 100644 tools/perf/tests/attr/test-stat-default
+ create mode 100644 tools/perf/tests/attr/test-stat-detailed-1
+ create mode 100644 tools/perf/tests/attr/test-stat-detailed-2
+ create mode 100644 tools/perf/tests/attr/test-stat-detailed-3
+ create mode 100644 tools/perf/tests/attr/test-stat-group
+ create mode 100644 tools/perf/tests/attr/test-stat-group1
+ create mode 100644 tools/perf/tests/attr/test-stat-no-inherit
+ rename tools/perf/{ => tests}/builtin-test.c (97%)
+ rename tools/perf/{util/dso-test-data.c => tests/dso-data.c} (99%)
+ rename tools/perf/{util/parse-events-test.c => tests/parse-events.c} (96%)
+ create mode 100644 tools/perf/ui/browsers/scripts.c
+ create mode 100644 tools/perf/util/dso.c
+ create mode 100644 tools/perf/util/dso.h
+ create mode 100644 tools/perf/util/machine.c
+ create mode 100644 tools/perf/util/machine.h
+Merging ftrace/for-next (bf3071f tracing: Remove unnecessary WARN_ONCE's from tracing_buffers_splice_read)
+$ git merge ftrace/for-next
+Auto-merging arch/unicore32/include/asm/Kbuild
+Auto-merging arch/openrisc/include/asm/Kbuild
+Auto-merging arch/microblaze/include/asm/Kbuild
+Auto-merging arch/m68k/include/asm/Kbuild
+Auto-merging arch/cris/include/asm/Kbuild
+Auto-merging arch/blackfin/include/asm/Kbuild
+Auto-merging arch/arm64/include/asm/Kbuild
+Merge made by the 'recursive' strategy.
+ arch/alpha/include/asm/Kbuild      |    1 +
+ arch/arm/include/asm/Kbuild        |    1 +
+ arch/arm64/include/asm/Kbuild      |    1 +
+ arch/avr32/include/asm/Kbuild      |    1 +
+ arch/blackfin/include/asm/Kbuild   |    1 +
+ arch/c6x/include/asm/Kbuild        |    1 +
+ arch/cris/include/asm/Kbuild       |    1 +
+ arch/frv/include/asm/Kbuild        |    1 +
+ arch/h8300/include/asm/Kbuild      |    1 +
+ arch/hexagon/include/asm/Kbuild    |    1 +
+ arch/ia64/include/asm/Kbuild       |    1 +
+ arch/m32r/include/asm/Kbuild       |    1 +
+ arch/m68k/include/asm/Kbuild       |    1 +
+ arch/microblaze/include/asm/Kbuild |    1 +
+ arch/mips/include/asm/Kbuild       |    1 +
+ arch/mn10300/include/asm/Kbuild    |    1 +
+ arch/openrisc/include/asm/Kbuild   |    1 +
+ arch/parisc/include/asm/Kbuild     |    1 +
+ arch/powerpc/include/asm/Kbuild    |    1 +
+ arch/s390/include/asm/Kbuild       |    1 +
+ arch/score/include/asm/Kbuild      |    1 +
+ arch/sh/include/asm/Kbuild         |    1 +
+ arch/sparc/include/asm/Kbuild      |    1 +
+ arch/tile/include/asm/Kbuild       |    1 +
+ arch/um/include/asm/Kbuild         |    1 +
+ arch/unicore32/include/asm/Kbuild  |    1 +
+ arch/x86/include/asm/trace_clock.h |   20 ++++++++
+ arch/x86/kernel/Makefile           |    1 +
+ arch/x86/kernel/trace_clock.c      |   21 ++++++++
+ arch/xtensa/include/asm/Kbuild     |    1 +
+ include/asm-generic/trace_clock.h  |   16 ++++++
+ include/linux/ftrace_event.h       |    6 +++
+ include/linux/trace_clock.h        |    2 +
+ include/trace/ftrace.h             |   73 --------------------------
+ kernel/trace/trace.c               |   99 ++++++++++++++++++++++--------------
+ kernel/trace/trace.h               |    4 --
+ kernel/trace/trace_output.c        |   78 +++++++++++++++++++---------
+ kernel/trace/trace_stack.c         |    4 --
+ 38 files changed, 207 insertions(+), 144 deletions(-)
+ create mode 100644 arch/x86/include/asm/trace_clock.h
+ create mode 100644 arch/x86/kernel/trace_clock.c
+ create mode 100644 include/asm-generic/trace_clock.h
+Merging rcu/rcu/next (98dbec1 context_tracking: New context tracking susbsystem)
+$ git merge rcu/rcu/next
+Recorded preimage for 'arch/x86/kernel/ptrace.c'
+Auto-merging lib/Kconfig.debug
+Auto-merging kernel/sched/core.c
+Auto-merging kernel/Makefile
+Auto-merging init/Kconfig
+Auto-merging include/linux/sched.h
+Auto-merging arch/x86/kernel/signal.c
+Auto-merging arch/x86/kernel/ptrace.c
+CONFLICT (content): Merge conflict in arch/x86/kernel/ptrace.c
+Auto-merging arch/x86/kernel/entry_64.S
+Auto-merging arch/x86/include/asm/context_tracking.h
+Auto-merging arch/x86/Kconfig
+Auto-merging Documentation/kernel-parameters.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+Recorded resolution for 'arch/x86/kernel/ptrace.c'.
+[master f6e07d8] Merge remote-tracking branch 'rcu/rcu/next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/RCU/RTFP.txt                         |    2 +-
+ Documentation/RCU/checklist.txt                    |   17 +-
+ Documentation/RCU/listRCU.txt                      |    2 +-
+ Documentation/RCU/rcuref.txt                       |   61 ++-
+ Documentation/RCU/trace.txt                        |  396 ++++++++++---------
+ Documentation/RCU/whatisRCU.txt                    |   17 +-
+ Documentation/kernel-parameters.txt                |   21 +
+ Documentation/memory-barriers.txt                  |    9 +-
+ arch/Kconfig                                       |   15 +-
+ arch/um/drivers/mconsole_kern.c                    |    2 +-
+ arch/x86/Kconfig                                   |    2 +-
+ arch/x86/include/asm/{rcu.h => context_tracking.h} |   15 +-
+ arch/x86/kernel/entry_64.S                         |    2 +-
+ arch/x86/kernel/ptrace.c                           |    8 +-
+ arch/x86/kernel/signal.c                           |    5 +-
+ arch/x86/kernel/traps.c                            |    2 +-
+ arch/x86/mm/fault.c                                |    2 +-
+ include/linux/context_tracking.h                   |   18 +
+ include/linux/rculist.h                            |   17 -
+ include/linux/rcupdate.h                           |   29 +-
+ include/linux/sched.h                              |   10 +-
+ include/linux/srcu.h                               |   34 ++
+ include/trace/events/rcu.h                         |    1 +
+ init/Kconfig                                       |   67 ++--
+ kernel/Makefile                                    |    1 +
+ kernel/context_tracking.c                          |   83 ++++
+ kernel/ksysfs.c                                    |   18 +
+ kernel/rcu.h                                       |    2 +
+ kernel/rcupdate.c                                  |    3 +
+ kernel/rcutiny.c                                   |    2 +-
+ kernel/rcutiny_plugin.h                            |    5 +-
+ kernel/rcutorture.c                                |   54 +--
+ kernel/rcutree.c                                   |  347 ++++++++++------
+ kernel/rcutree.h                                   |   67 +++-
+ kernel/rcutree_plugin.h                            |  415 +++++++++++++++++++-
+ kernel/rcutree_trace.c                             |  330 ++++++++--------
+ kernel/sched/core.c                                |   23 +-
+ kernel/srcu.c                                      |   16 +-
+ lib/Kconfig.debug                                  |    2 +-
+ 39 files changed, 1493 insertions(+), 629 deletions(-)
+ rename arch/x86/include/asm/{rcu.h => context_tracking.h} (63%)
+ create mode 100644 include/linux/context_tracking.h
+ create mode 100644 kernel/context_tracking.c
+Merging cputime/cputime (c3e0ef9 [S390] fix cputime overflow in uptime_proc_show)
+$ git merge cputime/cputime
+Already up-to-date.
+Merging uprobes/for-next (0326f5a uprobes/core: Handle breakpoint and singlestep exceptions)
+$ git merge uprobes/for-next
+Already up-to-date.
+Merging kvm/linux-next (807f12e KVM: remove unnecessary return value check)
+$ git merge kvm/linux-next
+Auto-merging include/linux/kvm_host.h
+Auto-merging arch/x86/kvm/x86.c
+Auto-merging arch/x86/kvm/vmx.c
+Auto-merging arch/s390/kvm/kvm-s390.c
+Auto-merging arch/powerpc/include/asm/Kbuild
+Auto-merging arch/ia64/kvm/kvm-ia64.c
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/virtual/kvm/api.txt            |   85 +++-
+ MAINTAINERS                                  |    4 +-
+ arch/ia64/kvm/kvm-ia64.c                     |    2 -
+ arch/powerpc/include/asm/Kbuild              |    1 -
+ arch/powerpc/include/asm/epapr_hcalls.h      |   83 +---
+ arch/powerpc/include/asm/fsl_hcalls.h        |   36 +-
+ arch/powerpc/include/asm/kvm_asm.h           |    1 +
+ arch/powerpc/include/asm/kvm_book3s.h        |    2 +-
+ arch/powerpc/include/asm/kvm_book3s_64.h     |    2 +-
+ arch/powerpc/include/asm/kvm_booke_hv_asm.h  |    4 +-
+ arch/powerpc/include/asm/kvm_host.h          |   55 ++-
+ arch/powerpc/include/asm/kvm_para.h          |   15 +-
+ arch/powerpc/include/asm/kvm_ppc.h           |   64 ++-
+ arch/powerpc/include/asm/reg_booke.h         |    7 +
+ arch/powerpc/include/asm/smp.h               |    8 +
+ arch/powerpc/include/uapi/asm/Kbuild         |    1 +
+ arch/powerpc/include/uapi/asm/epapr_hcalls.h |   98 ++++
+ arch/powerpc/include/uapi/asm/kvm.h          |   59 +++
+ arch/powerpc/include/uapi/asm/kvm_para.h     |    7 +-
+ arch/powerpc/kernel/epapr_hcalls.S           |   28 ++
+ arch/powerpc/kernel/epapr_paravirt.c         |   11 +-
+ arch/powerpc/kernel/kvm.c                    |    2 +-
+ arch/powerpc/kernel/ppc_ksyms.c              |    5 +
+ arch/powerpc/kernel/smp.c                    |   46 ++
+ arch/powerpc/kvm/44x.c                       |    1 +
+ arch/powerpc/kvm/44x_emulate.c               |  112 +++--
+ arch/powerpc/kvm/Kconfig                     |    3 +
+ arch/powerpc/kvm/book3s.c                    |  125 +++++
+ arch/powerpc/kvm/book3s_32_mmu_host.c        |    3 +-
+ arch/powerpc/kvm/book3s_64_mmu_host.c        |    3 +-
+ arch/powerpc/kvm/book3s_64_mmu_hv.c          |   67 ++-
+ arch/powerpc/kvm/book3s_hv.c                 |  633 +++++++++++++++++++-------
+ arch/powerpc/kvm/book3s_hv_builtin.c         |    4 +-
+ arch/powerpc/kvm/book3s_hv_rm_mmu.c          |    6 +-
+ arch/powerpc/kvm/book3s_hv_rmhandlers.S      |   11 +-
+ arch/powerpc/kvm/book3s_mmu_hpte.c           |    5 -
+ arch/powerpc/kvm/book3s_pr.c                 |  180 ++++++--
+ arch/powerpc/kvm/book3s_rmhandlers.S         |   15 +-
+ arch/powerpc/kvm/booke.c                     |  310 +++++++++++--
+ arch/powerpc/kvm/booke_emulate.c             |   22 +-
+ arch/powerpc/kvm/e500.h                      |    3 +-
+ arch/powerpc/kvm/e500_tlb.c                  |   94 +++-
+ arch/powerpc/kvm/emulate.c                   |  221 +++++----
+ arch/powerpc/kvm/powerpc.c                   |  150 +++++-
+ arch/powerpc/kvm/trace.h                     |  200 ++++++--
+ arch/powerpc/platforms/Kconfig               |    1 +
+ arch/powerpc/sysdev/fsl_msi.c                |    9 +-
+ arch/powerpc/sysdev/fsl_soc.c                |    2 +
+ arch/s390/kvm/interrupt.c                    |   19 +-
+ arch/s390/kvm/kvm-s390.c                     |    2 +-
+ arch/x86/kvm/mmu.c                           |   49 +-
+ arch/x86/kvm/paging_tmpl.h                   |  115 ++---
+ arch/x86/kvm/svm.c                           |    7 +-
+ arch/x86/kvm/vmx.c                           |   45 +-
+ arch/x86/kvm/x86.c                           |   69 +--
+ drivers/tty/Kconfig                          |    1 +
+ drivers/virt/Kconfig                         |    1 +
+ include/linux/kvm_host.h                     |   36 +-
+ include/uapi/linux/kvm.h                     |   18 +-
+ virt/kvm/iommu.c                             |   10 +-
+ virt/kvm/kvm_main.c                          |   38 +-
+ 61 files changed, 2356 insertions(+), 860 deletions(-)
+ create mode 100644 arch/powerpc/include/uapi/asm/epapr_hcalls.h
+Merging kvm-ppc/kvm-ppc-next (a2ef34a KVM: PPC: Book3S HV: Handle guest-caused machine checks on POWER7 without panicking)
+$ git merge kvm-ppc/kvm-ppc-next
+Auto-merging include/linux/kvm_host.h
+Auto-merging arch/powerpc/include/asm/reg.h
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/virtual/kvm/api.txt        |   54 ++++
+ MAINTAINERS                              |    1 +
+ arch/powerpc/include/asm/kvm_book3s.h    |   10 +-
+ arch/powerpc/include/asm/kvm_book3s_64.h |   31 +++
+ arch/powerpc/include/asm/kvm_host.h      |    6 +-
+ arch/powerpc/include/asm/kvm_ppc.h       |    2 +
+ arch/powerpc/include/asm/mmu-hash64.h    |   10 +
+ arch/powerpc/include/asm/reg.h           |    1 +
+ arch/powerpc/include/uapi/asm/kvm.h      |   25 ++
+ arch/powerpc/kernel/asm-offsets.c        |    4 +-
+ arch/powerpc/kvm/Kconfig                 |    1 +
+ arch/powerpc/kvm/Makefile                |    5 +-
+ arch/powerpc/kvm/book3s_64_mmu_hv.c      |  407 +++++++++++++++++++++++++++++-
+ arch/powerpc/kvm/book3s_emulate.c        |   16 +-
+ arch/powerpc/kvm/book3s_exports.c        |    3 -
+ arch/powerpc/kvm/book3s_hv.c             |   32 ++-
+ arch/powerpc/kvm/book3s_hv_ras.c         |  144 +++++++++++
+ arch/powerpc/kvm/book3s_hv_rm_mmu.c      |  139 ++++++++--
+ arch/powerpc/kvm/book3s_hv_rmhandlers.S  |  131 +++++-----
+ arch/powerpc/kvm/book3s_pr.c             |  114 +++++----
+ arch/powerpc/kvm/book3s_rmhandlers.S     |    3 -
+ arch/powerpc/kvm/powerpc.c               |   34 ++-
+ include/linux/kvm_host.h                 |   12 +-
+ include/uapi/linux/kvm.h                 |    3 +
+ virt/kvm/eventfd.c                       |    6 +
+ 25 files changed, 1013 insertions(+), 181 deletions(-)
+ create mode 100644 arch/powerpc/kvm/book3s_hv_ras.c
+Merging oprofile/for-next (4400910 oprofile, x86: Fix wrapping bug in op_x86_get_ctrl())
+$ git merge oprofile/for-next
+Already up-to-date.
+Merging xen/upstream/xen (af3a3ab Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes)
+$ git merge xen/upstream/xen
+Already up-to-date.
+Merging xen-two/linux-next (ca63454 Merge branch 'stable/pvh.v6.1' into linux-next)
+$ git merge xen-two/linux-next
+Auto-merging drivers/xen/xen-pciback/pci_stub.c
+Merge made by the 'recursive' strategy.
+ arch/arm/include/asm/xen/interface.h |    1 +
+ arch/arm/xen/enlighten.c             |  125 +++++++++++++++++++----
+ arch/x86/include/asm/xen/interface.h |   12 ++-
+ arch/x86/include/asm/xen/page.h      |    3 +
+ arch/x86/xen/Kconfig                 |   11 ++
+ arch/x86/xen/enlighten.c             |  174 +++++++++++++++++++++++--------
+ arch/x86/xen/irq.c                   |    5 +-
+ arch/x86/xen/mmu.c                   |  187 +++++++++++++++++++++++++++++++---
+ arch/x86/xen/mmu.h                   |    2 +
+ arch/x86/xen/p2m.c                   |    2 +-
+ arch/x86/xen/setup.c                 |   64 +++++++++---
+ arch/x86/xen/smp.c                   |   75 +++++++++-----
+ arch/x86/xen/suspend.c               |    2 +-
+ arch/x86/xen/xen-head.S              |   11 +-
+ arch/x86/xen/xen-ops.h               |    2 +-
+ drivers/net/xen-netback/netback.c    |   11 +-
+ drivers/xen/Kconfig                  |    3 +
+ drivers/xen/Makefile                 |    7 +-
+ drivers/xen/balloon.c                |   19 ++--
+ drivers/xen/cpu_hotplug.c            |    4 +-
+ drivers/xen/events.c                 |    9 +-
+ drivers/xen/gntdev.c                 |    3 +-
+ drivers/xen/grant-table.c            |   78 ++++----------
+ drivers/xen/privcmd.c                |   72 ++++++++++++-
+ drivers/xen/xen-acpi-pad.c           |  182 +++++++++++++++++++++++++++++++++
+ drivers/xen/xen-pciback/pci_stub.c   |  118 +++++++++++----------
+ drivers/xen/xenbus/xenbus_client.c   |    9 +-
+ drivers/xen/xenbus/xenbus_xs.c       |    1 -
+ include/xen/grant_table.h            |   12 ---
+ include/xen/interface/memory.h       |   44 +++++++-
+ include/xen/interface/physdev.h      |   10 ++
+ include/xen/interface/platform.h     |   17 ++++
+ include/xen/xen-ops.h                |    9 +-
+ 33 files changed, 1012 insertions(+), 272 deletions(-)
+ create mode 100644 drivers/xen/xen-acpi-pad.c
+Merging xen-pvhvm/linux-next (b056b6a xen: suspend: remove xen_hvm_suspend)
+$ git merge xen-pvhvm/linux-next
+Already up-to-date.
+Merging percpu/for-next (b4916cb percpu: make pcpu_free_chunk() use pcpu_mem_free() instead of kfree())
+$ git merge percpu/for-next
+Merge made by the 'recursive' strategy.
+ mm/percpu.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+Merging workqueues/for-next (d8318e5 Merge branch 'for-3.8' into for-next)
+$ git merge workqueues/for-next
+Merge made by the 'recursive' strategy.
+ kernel/workqueue.c |   16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+Merging drivers-x86/linux-next (455f38c eeepc-laptop: fix device reference count leakage in eeepc_rfkill_hotplug())
+$ git merge drivers-x86/linux-next
+Auto-merging drivers/platform/x86/asus-wmi.c
+Merge made by the 'recursive' strategy.
+ drivers/platform/x86/asus-wmi.c |   76 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 76 insertions(+)
+Merging hwpoison/hwpoison (46e387b Merge branch 'hwpoison-hugepages' into hwpoison)
+$ git merge hwpoison/hwpoison
+Already up-to-date.
+Merging sysctl/master (4e474a0 sysctl: protect poll() in entries that may go away)
+$ git merge sysctl/master
+Already up-to-date.
+Merging regmap/for-next (51b6d98 Merge remote-tracking branches 'regmap/topic/domain', 'regmap/topic/table' and 'regmap/topic/type' into regmap-next)
+$ git merge regmap/for-next
+Merge made by the 'recursive' strategy.
+ drivers/base/regmap/internal.h |    4 ++
+ drivers/base/regmap/regmap.c   |   52 +++++++++++++++++++++++--
+ include/linux/regmap.h         |   83 ++++++++++++++++++++++++++++++++++------
+ 3 files changed, 125 insertions(+), 14 deletions(-)
+Merging hsi/for-next (43139a6 HSI: hsi_char: Update ioctl-number.txt)
+$ git merge hsi/for-next
+Already up-to-date.
+Merging leds/for-next (09f5fe7 leds: led-triggers: Fix checkpatch warnings)
+$ git merge leds/for-next
+Merge made by the 'recursive' strategy.
+ drivers/leds/led-class.c         |    2 +-
+ drivers/leds/led-triggers.c      |   25 +++++++++++++++++++------
+ drivers/leds/leds-88pm860x.c     |    9 ++-------
+ drivers/leds/leds-adp5520.c      |    4 ++--
+ drivers/leds/leds-bd2802.c       |   10 +++++-----
+ drivers/leds/leds-cobalt-qube.c  |   11 ++++-------
+ drivers/leds/leds-cobalt-raq.c   |   11 ++++-------
+ drivers/leds/leds-da903x.c       |   10 +++++-----
+ drivers/leds/leds-fsg.c          |   15 +++++----------
+ drivers/leds/leds-gpio.c         |   37 ++++++++++++++++++-------------------
+ drivers/leds/leds-lm355x.c       |    4 ++--
+ drivers/leds/leds-lm3642.c       |   12 ++++++------
+ drivers/leds/leds-lp3944.c       |    2 +-
+ drivers/leds/leds-lp5521.c       |    4 ++--
+ drivers/leds/leds-lp5523.c       |   24 +++++++++++++++++++-----
+ drivers/leds/leds-lt3593.c       |   20 ++++++--------------
+ drivers/leds/leds-net48xx.c      |    2 +-
+ drivers/leds/leds-netxbig.c      |    2 +-
+ drivers/leds/leds-ns2.c          |   36 +++++++++++-------------------------
+ drivers/leds/leds-pca955x.c      |    2 +-
+ drivers/leds/leds-pwm.c          |    2 +-
+ drivers/leds/leds-renesas-tpu.c  |   25 ++++++++++---------------
+ drivers/leds/leds-ss4200.c       |    2 +-
+ drivers/leds/leds-wm8350.c       |    4 ++--
+ drivers/leds/leds-wrap.c         |    2 +-
+ drivers/leds/ledtrig-backlight.c |    4 ++--
+ drivers/leds/ledtrig-gpio.c      |    2 +-
+ include/linux/leds.h             |   17 +++++++++++++++++
+ 28 files changed, 150 insertions(+), 150 deletions(-)
+Merging driver-core/driver-core-next (da095fd acpi: remove use of __devinit)
+$ git merge driver-core/driver-core-next
+Auto-merging lib/Makefile
+CONFLICT (content): Merge conflict in lib/Makefile
+Auto-merging kernel/sysctl.c
+Auto-merging kernel/ksysfs.c
+Auto-merging include/linux/pci.h
+Auto-merging drivers/watchdog/sp805_wdt.c
+Auto-merging drivers/watchdog/davinci_wdt.c
+Auto-merging drivers/rapidio/rio.c
+Auto-merging drivers/power/max8925_power.c
+CONFLICT (content): Merge conflict in drivers/power/max8925_power.c
+Auto-merging drivers/power/max17042_battery.c
+Auto-merging drivers/power/lp8788-charger.c
+Auto-merging drivers/power/jz4740-battery.c
+Auto-merging drivers/power/generic-adc-battery.c
+Auto-merging drivers/power/da9052-battery.c
+CONFLICT (content): Merge conflict in drivers/power/da9052-battery.c
+Auto-merging drivers/power/bq27x00_battery.c
+Auto-merging drivers/power/abx500_chargalg.c
+CONFLICT (content): Merge conflict in drivers/power/abx500_chargalg.c
+Auto-merging drivers/power/ab8500_fg.c
+CONFLICT (content): Merge conflict in drivers/power/ab8500_fg.c
+Auto-merging drivers/power/ab8500_charger.c
+CONFLICT (content): Merge conflict in drivers/power/ab8500_charger.c
+Auto-merging drivers/power/ab8500_btemp.c
+CONFLICT (content): Merge conflict in drivers/power/ab8500_btemp.c
+Auto-merging drivers/pci/quirks.c
+CONFLICT (content): Merge conflict in drivers/pci/quirks.c
+Auto-merging drivers/pci/probe.c
+Auto-merging drivers/pci/pci.h
+CONFLICT (content): Merge conflict in drivers/pci/pci.h
+Auto-merging drivers/pci/pci.c
+Auto-merging drivers/pci/pci-sysfs.c
+Auto-merging drivers/pci/pci-driver.c
+Auto-merging drivers/pci/ioapic.c
+Removing drivers/pci/hotplug.c
+Auto-merging drivers/mmc/host/sdhci-spear.c
+Auto-merging drivers/mmc/host/sdhci-s3c.c
+Auto-merging drivers/mmc/host/sdhci-pxav3.c
+Auto-merging drivers/mmc/host/sdhci-of-esdhc.c
+Auto-merging drivers/mmc/host/sdhci-dove.c
+Auto-merging drivers/mmc/host/omap_hsmmc.c
+Auto-merging drivers/mmc/host/mmci.c
+Auto-merging drivers/mmc/host/dw_mmc-pltfm.c
+Auto-merging drivers/mmc/host/dw_mmc-pci.c
+Auto-merging drivers/mfd/wm8994-core.c
+Auto-merging drivers/mfd/twl4030-power.c
+Auto-merging drivers/mfd/twl4030-madc.c
+Auto-merging drivers/mfd/twl-core.c
+Auto-merging drivers/mfd/tps65910.c
+Auto-merging drivers/mfd/tps6586x.c
+Auto-merging drivers/mfd/tps65217.c
+Auto-merging drivers/mfd/tps65090.c
+CONFLICT (content): Merge conflict in drivers/mfd/tps65090.c
+Auto-merging drivers/mfd/stmpe-i2c.c
+Auto-merging drivers/mfd/sta2x11-mfd.c
+CONFLICT (content): Merge conflict in drivers/mfd/sta2x11-mfd.c
+Auto-merging drivers/mfd/mc13xxx-spi.c
+Auto-merging drivers/mfd/mc13xxx-i2c.c
+Auto-merging drivers/mfd/lpc_ich.c
+Auto-merging drivers/mfd/jz4740-adc.c
+Auto-merging drivers/mfd/db8500-prcmu.c
+Auto-merging drivers/mfd/da9052-core.c
+CONFLICT (content): Merge conflict in drivers/mfd/da9052-core.c
+Auto-merging drivers/mfd/arizona-core.c
+Auto-merging drivers/mfd/ab8500-core.c
+CONFLICT (content): Merge conflict in drivers/mfd/ab8500-core.c
+Auto-merging drivers/leds/leds-ss4200.c
+Auto-merging drivers/leds/leds-renesas-tpu.c
+Auto-merging drivers/leds/leds-pwm.c
+Auto-merging drivers/leds/leds-pca955x.c
+Auto-merging drivers/leds/leds-ns2.c
+Auto-merging drivers/leds/leds-netxbig.c
+Auto-merging drivers/leds/leds-lt3593.c
+Auto-merging drivers/leds/leds-lp5523.c
+Auto-merging drivers/leds/leds-lp5521.c
+Auto-merging drivers/leds/leds-lp3944.c
+Auto-merging drivers/leds/leds-lm3642.c
+Auto-merging drivers/leds/leds-lm355x.c
+Auto-merging drivers/leds/leds-gpio.c
+Auto-merging drivers/leds/leds-da903x.c
+Auto-merging drivers/leds/leds-cobalt-raq.c
+Auto-merging drivers/leds/leds-cobalt-qube.c
+Auto-merging drivers/leds/leds-bd2802.c
+Auto-merging drivers/leds/leds-adp5520.c
+Auto-merging drivers/hwmon/w83627hf.c
+Auto-merging drivers/hwmon/w83627ehf.c
+Auto-merging drivers/hwmon/it87.c
+Auto-merging drivers/hwmon/da9052-hwmon.c
+Auto-merging drivers/hwmon/coretemp.c
+Auto-merging drivers/gpio/gpio-twl4030.c
+Auto-merging drivers/gpio/gpio-tps6586x.c
+CONFLICT (content): Merge conflict in drivers/gpio/gpio-tps6586x.c
+Auto-merging drivers/gpio/gpio-mvebu.c
+Auto-merging drivers/gpio/gpio-mcp23s08.c
+Auto-merging drivers/gpio/gpio-da9052.c
+Auto-merging dRecorded preimage for 'drivers/dma/dw_dmac.c'
+Recorded preimage for 'drivers/gpio/gpio-tps6586x.c'
+Recorded preimage for 'drivers/mfd/ab8500-core.c'
+Recorded preimage for 'drivers/mfd/da9052-core.c'
+Recorded preimage for 'drivers/mfd/sta2x11-mfd.c'
+Recorded preimage for 'drivers/mfd/tps65090.c'
+Recorded preimage for 'drivers/pci/pci.h'
+Recorded preimage for 'drivers/pci/quirks.c'
+Recorded preimage for 'drivers/power/ab8500_btemp.c'
+Recorded preimage for 'drivers/power/ab8500_charger.c'
+Recorded preimage for 'drivers/power/ab8500_fg.c'
+Recorded preimage for 'drivers/power/abx500_chargalg.c'
+Recorded preimage for 'drivers/power/da9052-battery.c'
+Recorded preimage for 'drivers/power/max8925_power.c'
+Recorded preimage for 'lib/Makefile'
+rivers/firewire/ohci.c
+Auto-merging drivers/dma/pch_dma.c
+Auto-merging drivers/dma/mv_xor.c
+Auto-merging drivers/dma/iop-adma.c
+Auto-merging drivers/dma/dw_dmac.c
+CONFLICT (content): Merge conflict in drivers/dma/dw_dmac.c
+Auto-merging drivers/char/tpm/tpm_ibmvtpm.c
+Auto-merging drivers/base/platform.c
+Auto-merging drivers/base/firmware_class.c
+Auto-merging drivers/base/core.c
+Auto-merging drivers/acpi/pci_root.c
+Auto-merging drivers/acpi/hed.c
+Auto-merging drivers/acpi/apei/ghes.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+Recorded resolution for 'drivers/dma/dw_dmac.c'.
+Recorded resolution for 'drivers/gpio/gpio-tps6586x.c'.
+Recorded resolution for 'drivers/mfd/ab8500-core.c'.
+Recorded resolution for 'drivers/mfd/da9052-core.c'.
+Recorded resolution for 'drivers/mfd/sta2x11-mfd.c'.
+Recorded resolution for 'drivers/mfd/tps65090.c'.
+Recorded resolution for 'drivers/pci/pci.h'.
+Recorded resolution for 'drivers/pci/quirks.c'.
+Recorded resolution for 'drivers/power/ab8500_btemp.c'.
+Recorded resolution for 'drivers/power/ab8500_charger.c'.
+Recorded resolution for 'drivers/power/ab8500_fg.c'.
+Recorded resolution for 'drivers/power/abx500_chargalg.c'.
+Recorded resolution for 'drivers/power/da9052-battery.c'.
+Recorded resolution for 'drivers/power/max8925_power.c'.
+Recorded resolution for 'lib/Makefile'.
+[master 02cc691] Merge remote-tracking branch 'driver-core/driver-core-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/firmware_class/README             |   12 +
+ Documentation/zh_CN/arm/kernel_user_helpers.txt |  284 +++++++++++++++++++++++
+ Documentation/zh_CN/arm64/memory.txt            |   14 +-
+ arch/microblaze/pci/pci-common.c                |    4 -
+ arch/mips/pci/pci.c                             |    2 -
+ arch/powerpc/kernel/pci-common.c                |    4 -
+ arch/powerpc/kernel/pci_64.c                    |    4 -
+ arch/sh/drivers/pci/pci.c                       |    2 -
+ arch/unicore32/kernel/pci.c                     |    2 -
+ drivers/acpi/apei/ghes.c                        |    2 +-
+ drivers/acpi/hed.c                              |    2 +-
+ drivers/acpi/pci_root.c                         |    2 +-
+ drivers/base/Kconfig                            |    7 +-
+ drivers/base/attribute_container.c              |    2 +-
+ drivers/base/bus.c                              |   14 --
+ drivers/base/core.c                             |    8 +-
+ drivers/base/devres.c                           |    4 +-
+ drivers/base/firmware_class.c                   |   50 +++-
+ drivers/base/platform.c                         |    4 +-
+ drivers/char/tpm/tpm_i2c_infineon.c             |    4 +-
+ drivers/char/tpm/tpm_ibmvtpm.c                  |    2 +-
+ drivers/char/tpm/tpm_infineon.c                 |    4 +-
+ drivers/char/tpm/tpm_tis.c                      |    2 +-
+ drivers/clk/clk-max77686.c                      |    6 +-
+ drivers/clk/clk-wm831x.c                        |    6 +-
+ drivers/dma/dw_dmac.c                           |    4 +-
+ drivers/dma/edma.c                              |    4 +-
+ drivers/dma/fsldma.c                            |    4 +-
+ drivers/dma/intel_mid_dma.c                     |    4 +-
+ drivers/dma/ioat/pci.c                          |    2 +-
+ drivers/dma/iop-adma.c                          |   10 +-
+ drivers/dma/mmp_pdma.c                          |    6 +-
+ drivers/dma/mmp_tdma.c                          |    6 +-
+ drivers/dma/mpc512x_dma.c                       |    4 +-
+ drivers/dma/mv_xor.c                            |    8 +-
+ drivers/dma/pch_dma.c                           |    4 +-
+ drivers/dma/pl330.c                             |    2 +-
+ drivers/dma/ppc4xx/adma.c                       |    4 +-
+ drivers/dma/sa11x0-dma.c                        |    6 +-
+ drivers/dma/sh/shdma.c                          |    6 +-
+ drivers/dma/sirf-dma.c                          |    4 +-
+ drivers/dma/tegra20-apb-dma.c                   |    4 +-
+ drivers/dma/timb_dma.c                          |    2 +-
+ drivers/firewire/nosy.c                         |    4 +-
+ drivers/firewire/ohci.c                         |    2 +-
+ drivers/gpio/gpio-74x164.c                      |    6 +-
+ drivers/gpio/gpio-ab8500.c                      |    6 +-
+ drivers/gpio/gpio-adnp.c                        |   10 +-
+ drivers/gpio/gpio-adp5520.c                     |    6 +-
+ drivers/gpio/gpio-adp5588.c                     |    6 +-
+ drivers/gpio/gpio-arizona.c                     |    6 +-
+ drivers/gpio/gpio-cs5535.c                      |    6 +-
+ drivers/gpio/gpio-da9052.c                      |    8 +-
+ drivers/gpio/gpio-em.c                          |    6 +-
+ drivers/gpio/gpio-ep93xx.c                      |    2 +-
+ drivers/gpio/gpio-generic.c                     |    6 +-
+ drivers/gpio/gpio-ich.c                         |   10 +-
+ drivers/gpio/gpio-janz-ttl.c                    |   10 +-
+ drivers/gpio/gpio-langwell.c                    |    8 +-
+ drivers/gpio/gpio-lpc32xx.c                     |    4 +-
+ drivers/gpio/gpio-max7300.c                     |    6 +-
+ drivers/gpio/gpio-max7301.c                     |    6 +-
+ drivers/gpio/gpio-max730x.c                     |    4 +-
+ drivers/gpio/gpio-max732x.c                     |    8 +-
+ drivers/gpio/gpio-mc33880.c                     |    6 +-
+ drivers/gpio/gpio-mcp23s08.c                    |    6 +-
+ drivers/gpio/gpio-ml-ioh.c                      |    8 +-
+ drivers/gpio/gpio-mpc5200.c                     |    4 +-
+ drivers/gpio/gpio-msic.c                        |    2 +-
+ drivers/gpio/gpio-msm-v2.c                      |    6 +-
+ drivers/gpio/gpio-mvebu.c                       |    4 +-
+ drivers/gpio/gpio-mxc.c                         |    4 +-
+ drivers/gpio/gpio-mxs.c                         |    2 +-
+ drivers/gpio/gpio-omap.c                        |    6 +-
+ drivers/gpio/gpio-pca953x.c                     |    6 +-
+ drivers/gpio/gpio-pch.c                         |    8 +-
+ drivers/gpio/gpio-pxa.c                         |    6 +-
+ drivers/gpio/gpio-rc5t583.c                     |    6 +-
+ drivers/gpio/gpio-rdc321x.c                     |    6 +-
+ drivers/gpio/gpio-sch.c                         |    6 +-
+ drivers/gpio/gpio-sodaville.c                   |    4 +-
+ drivers/gpio/gpio-sta2x11.c                     |    4 +-
+ drivers/gpio/gpio-stmpe.c                       |    8 +-
+ drivers/gpio/gpio-stp-xway.c                    |    2 +-
+ drivers/gpio/gpio-sx150x.c                      |    6 +-
+ drivers/gpio/gpio-tc3589x.c                     |    6 +-
+ drivers/gpio/gpio-tegra.c                       |    4 +-
+ drivers/gpio/gpio-timberdale.c                  |    4 +-
+ drivers/gpio/gpio-tps6586x.c                    |    6 +-
+ drivers/gpio/gpio-tps65910.c                    |    6 +-
+ drivers/gpio/gpio-tps65912.c                    |    6 +-
+ drivers/gpio/gpio-twl4030.c                     |    8 +-
+ drivers/gpio/gpio-twl6040.c                     |    4 +-
+ drivers/gpio/gpio-vr41xx.c                      |    6 +-
+ drivers/gpio/gpio-vt8500.c                      |    2 +-
+ drivers/gpio/gpio-vx855.c                       |    6 +-
+ drivers/gpio/gpio-wm831x.c                      |    6 +-
+ drivers/gpio/gpio-wm8350.c                      |    6 +-
+ drivers/gpio/gpio-wm8994.c                      |    6 +-
+ drivers/gpio/gpio-xilinx.c                      |    4 +-
+ drivers/hwmon/abituguru.c                       |   12 +-
+ drivers/hwmon/abituguru3.c                      |    6 +-
+ drivers/hwmon/ad7314.c                          |    6 +-
+ drivers/hwmon/ad7414.c                          |    4 +-
+ drivers/hwmon/adcxx.c                           |    6 +-
+ drivers/hwmon/ads7871.c                         |    6 +-
+ drivers/hwmon/adt7411.c                         |    6 +-
+ drivers/hwmon/coretemp.c                        |    8 +-
+ drivers/hwmon/da9052-hwmon.c                    |    6 +-
+ drivers/hwmon/dme1737.c                         |    6 +-
+ drivers/hwmon/f71805f.c                         |    8 +-
+ drivers/hwmon/f71882fg.c                        |    8 +-
+ drivers/hwmon/fam15h_power.c                    |   10 +-
+ drivers/hwmon/gpio-fan.c                        |    8 +-
+ drivers/hwmon/hih6130.c                         |    6 +-
+ drivers/hwmon/i5k_amb.c                         |   18 +-
+ drivers/hwmon/it87.c                            |   12 +-
+ drivers/hwmon/jz4740-hwmon.c                    |    6 +-
+ drivers/hwmon/k10temp.c                         |    8 +-
+ drivers/hwmon/k8temp.c                          |    8 +-
+ drivers/hwmon/lm70.c                            |    6 +-
+ drivers/hwmon/lm78.c                            |    6 +-
+ drivers/hwmon/max1111.c                         |    8 +-
+ drivers/hwmon/max197.c                          |    6 +-
+ drivers/hwmon/mc13783-adc.c                     |    4 +-
+ drivers/hwmon/ntc_thermistor.c                  |    6 +-
+ drivers/hwmon/pc87360.c                         |    8 +-
+ drivers/hwmon/pc87427.c                         |   10 +-
+ drivers/hwmon/s3c-hwmon.c                       |    6 +-
+ drivers/hwmon/sch5627.c                         |    4 +-
+ drivers/hwmon/sch5636.c                         |    2 +-
+ drivers/hwmon/sht15.c                           |    6 +-
+ drivers/hwmon/sht21.c                           |    6 +-
+ drivers/hwmon/sis5595.c                         |   16 +-
+ drivers/hwmon/smsc47b397.c                      |    6 +-
+ drivers/hwmon/tmp102.c                          |    6 +-
+ drivers/hwmon/twl4030-madc-hwmon.c              |    4 +-
+ drivers/hwmon/ultra45_env.c                     |    6 +-
+ drivers/hwmon/via-cputemp.c                     |    6 +-
+ drivers/hwmon/via686a.c                         |   14 +-
+ drivers/hwmon/vt1211.c                          |    8 +-
+ drivers/hwmon/vt8231.c                          |   12 +-
+ drivers/hwmon/w83627ehf.c                       |   12 +-
+ drivers/hwmon/w83627hf.c                        |   14 +-
+ drivers/hwmon/w83781d.c                         |    6 +-
+ drivers/hwmon/wm831x-hwmon.c                    |    6 +-
+ drivers/hwmon/wm8350-hwmon.c                    |    6 +-
+ drivers/hwspinlock/omap_hwspinlock.c            |    6 +-
+ drivers/hwspinlock/u8500_hsem.c                 |    6 +-
+ drivers/leds/leds-adp5520.c                     |    8 +-
+ drivers/leds/leds-asic3.c                       |    6 +-
+ drivers/leds/leds-atmel-pwm.c                   |    2 +-
+ drivers/leds/leds-bd2802.c                      |    2 +-
+ drivers/leds/leds-blinkm.c                      |    6 +-
+ drivers/leds/leds-clevo-mail.c                  |    2 +-
+ drivers/leds/leds-cobalt-qube.c                 |    6 +-
+ drivers/leds/leds-cobalt-raq.c                  |    6 +-
+ drivers/leds/leds-da903x.c                      |    6 +-
+ drivers/leds/leds-da9052.c                      |    6 +-
+ drivers/leds/leds-gpio.c                        |   12 +-
+ drivers/leds/leds-lm3530.c                      |    6 +-
+ drivers/leds/leds-lm3533.c                      |    8 +-
+ drivers/leds/leds-lm355x.c                      |    8 +-
+ drivers/leds/leds-lm3642.c                      |    8 +-
+ drivers/leds/leds-lp3944.c                      |    6 +-
+ drivers/leds/leds-lp5521.c                      |    8 +-
+ drivers/leds/leds-lp5523.c                      |    4 +-
+ drivers/leds/leds-lp8788.c                      |    6 +-
+ drivers/leds/leds-lt3593.c                      |    8 +-
+ drivers/leds/leds-max8997.c                     |    6 +-
+ drivers/leds/leds-mc13783.c                     |   10 +-
+ drivers/leds/leds-netxbig.c                     |   10 +-
+ drivers/leds/leds-ns2.c                         |    8 +-
+ drivers/leds/leds-ot200.c                       |    6 +-
+ drivers/leds/leds-pca955x.c                     |    6 +-
+ drivers/leds/leds-pca9633.c                     |    6 +-
+ drivers/leds/leds-pwm.c                         |    4 +-
+ drivers/leds/leds-rb532.c                       |    6 +-
+ drivers/leds/leds-regulator.c                   |    6 +-
+ drivers/leds/leds-renesas-tpu.c                 |    6 +-
+ drivers/leds/leds-ss4200.c                      |    4 +-
+ drivers/leds/leds-sunfire.c                     |   12 +-
+ drivers/leds/leds-tca6507.c                     |    6 +-
+ drivers/mfd/88pm800.c                           |   12 +-
+ drivers/mfd/88pm805.c                           |   10 +-
+ drivers/mfd/88pm80x.c                           |    2 +-
+ drivers/mfd/88pm860x-core.c                     |  104 ++++-----
+ drivers/mfd/ab3100-core.c                       |   13 +-
+ drivers/mfd/ab8500-core.c                       |   40 ++--
+ drivers/mfd/ab8500-debugfs.c                    |    6 +-
+ drivers/mfd/ab8500-gpadc.c                      |    6 +-
+ drivers/mfd/ab8500-sysctrl.c                    |    6 +-
+ drivers/mfd/adp5520.c                           |    6 +-
+ drivers/mfd/arizona-core.c                      |    4 +-
+ drivers/mfd/arizona-i2c.c                       |    6 +-
+ drivers/mfd/arizona-spi.c                       |    6 +-
+ drivers/mfd/asic3.c                             |    4 +-
+ drivers/mfd/cs5535-mfd.c                        |   12 +-
+ drivers/mfd/da903x.c                            |   10 +-
+ drivers/mfd/da9052-core.c                       |    4 +-
+ drivers/mfd/da9052-i2c.c                        |    6 +-
+ drivers/mfd/da9052-spi.c                        |    6 +-
+ drivers/mfd/da9055-core.c                       |    4 +-
+ drivers/mfd/da9055-i2c.c                        |    6 +-
+ drivers/mfd/davinci_voicecodec.c                |    4 +-
+ drivers/mfd/db8500-prcmu.c                      |    2 +-
+ drivers/mfd/ezx-pcap.c                          |    8 +-
+ drivers/mfd/htc-i2cpld.c                        |   12 +-
+ drivers/mfd/intel_msic.c                        |   10 +-
+ drivers/mfd/janz-cmodio.c                       |   10 +-
+ drivers/mfd/jz4740-adc.c                        |    6 +-
+ drivers/mfd/lm3533-core.c                       |   18 +-
+ drivers/mfd/lp8788.c                            |    4 +-
+ drivers/mfd/lpc_ich.c                           |   20 +-
+ drivers/mfd/lpc_sch.c                           |    6 +-
+ drivers/mfd/max77686.c                          |    2 +-
+ drivers/mfd/max8907.c                           |    4 +-
+ drivers/mfd/max8925-core.c                      |   58 ++---
+ drivers/mfd/max8925-i2c.c                       |    6 +-
+ drivers/mfd/mc13xxx-i2c.c                       |    4 +-
+ drivers/mfd/mc13xxx-spi.c                       |    4 +-
+ drivers/mfd/omap-usb-host.c                     |    4 +-
+ drivers/mfd/omap-usb-tll.c                      |    6 +-
+ drivers/mfd/palmas.c                            |    6 +-
+ drivers/mfd/pcf50633-adc.c                      |    6 +-
+ drivers/mfd/pcf50633-core.c                     |    6 +-
+ drivers/mfd/pm8921-core.c                       |    8 +-
+ drivers/mfd/pm8xxx-irq.c                        |    4 +-
+ drivers/mfd/rc5t583.c                           |    6 +-
+ drivers/mfd/rdc321x-southbridge.c               |    6 +-
+ drivers/mfd/sm501.c                             |   16 +-
+ drivers/mfd/sta2x11-mfd.c                       |   30 +--
+ drivers/mfd/stmpe-i2c.c                         |    6 +-
+ drivers/mfd/stmpe-spi.c                         |    6 +-
+ drivers/mfd/syscon.c                            |    6 +-
+ drivers/mfd/tc3589x.c                           |    8 +-
+ drivers/mfd/tc6387xb.c                          |    6 +-
+ drivers/mfd/tc6393xb.c                          |   12 +-
+ drivers/mfd/ti-ssp.c                            |    6 +-
+ drivers/mfd/timberdale.c                        |   64 ++---
+ drivers/mfd/tps6105x.c                          |    8 +-
+ drivers/mfd/tps65090.c                          |    6 +-
+ drivers/mfd/tps65217.c                          |    6 +-
+ drivers/mfd/tps6586x.c                          |   10 +-
+ drivers/mfd/tps65910.c                          |   10 +-
+ drivers/mfd/tps65911-comparator.c               |    6 +-
+ drivers/mfd/tps65912-spi.c                      |    6 +-
+ drivers/mfd/twl-core.c                          |    2 +-
+ drivers/mfd/twl4030-audio.c                     |    6 +-
+ drivers/mfd/twl4030-madc.c                      |    4 +-
+ drivers/mfd/twl4030-power.c                     |   20 +-
+ drivers/mfd/vx855.c                             |    6 +-
+ drivers/mfd/wl1273-core.c                       |    4 +-
+ drivers/mfd/wm831x-spi.c                        |    6 +-
+ drivers/mfd/wm8994-core.c                       |   16 +-
+ drivers/mmc/host/atmel-mci.c                    |    2 +-
+ drivers/mmc/host/au1xmmc.c                      |    4 +-
+ drivers/mmc/host/bfin_sdh.c                     |    6 +-
+ drivers/mmc/host/cb710-mmc.c                    |    6 +-
+ drivers/mmc/host/dw_mmc-pci.c                   |    4 +-
+ drivers/mmc/host/dw_mmc-pltfm.c                 |    4 +-
+ drivers/mmc/host/dw_mmc-pltfm.h                 |    2 +-
+ drivers/mmc/host/jz4740_mmc.c                   |   12 +-
+ drivers/mmc/host/mmc_spi.c                      |    6 +-
+ drivers/mmc/host/mmci.c                         |   10 +-
+ drivers/mmc/host/omap.c                         |    8 +-
+ drivers/mmc/host/omap_hsmmc.c                   |    6 +-
+ drivers/mmc/host/pxamci.c                       |    4 +-
+ drivers/mmc/host/s3cmci.c                       |    6 +-
+ drivers/mmc/host/sdhci-cns3xxx.c                |    6 +-
+ drivers/mmc/host/sdhci-dove.c                   |    8 +-
+ drivers/mmc/host/sdhci-esdhc-imx.c              |    8 +-
+ drivers/mmc/host/sdhci-of-esdhc.c               |    6 +-
+ drivers/mmc/host/sdhci-of-hlwd.c                |    6 +-
+ drivers/mmc/host/sdhci-pci.c                    |   14 +-
+ drivers/mmc/host/sdhci-pxav2.c                  |    6 +-
+ drivers/mmc/host/sdhci-pxav3.c                  |    6 +-
+ drivers/mmc/host/sdhci-s3c.c                    |   10 +-
+ drivers/mmc/host/sdhci-spear.c                  |   12 +-
+ drivers/mmc/host/sdhci-tegra.c                  |   10 +-
+ drivers/mmc/host/sh_mmcif.c                     |    4 +-
+ drivers/mmc/host/sh_mobile_sdhi.c               |    4 +-
+ drivers/mmc/host/tmio_mmc.c                     |    6 +-
+ drivers/mmc/host/tmio_mmc_pio.c                 |    2 +-
+ drivers/mmc/host/via-sdmmc.c                    |    6 +-
+ drivers/mmc/host/wbsd.c                         |   28 +--
+ drivers/pci/Makefile                            |    7 +-
+ drivers/pci/hotplug.c                           |   37 ---
+ drivers/pci/hotplug/cpcihp_zt5550.c             |    4 +-
+ drivers/pci/ioapic.c                            |    6 +-
+ drivers/pci/pci-driver.c                        |   42 +++-
+ drivers/pci/pci-sysfs.c                         |    7 -
+ drivers/pci/pci.c                               |    4 +-
+ drivers/pci/pci.h                               |    5 -
+ drivers/pci/pcie/aer/aerdrv.c                   |    4 +-
+ drivers/pci/pcie/portdrv_pci.c                  |    2 +-
+ drivers/pci/probe.c                             |   20 +-
+ drivers/pci/quirks.c                            |  134 +++++------
+ drivers/pci/xen-pcifront.c                      |   10 +-
+ drivers/pcmcia/bcm63xx_pcmcia.c                 |   12 +-
+ drivers/pcmcia/bfin_cf_pcmcia.c                 |    6 +-
+ drivers/pcmcia/db1xxx_ss.c                      |    6 +-
+ drivers/pcmcia/ds.c                             |   13 +-
+ drivers/pcmcia/electra_cf.c                     |    4 +-
+ drivers/pcmcia/i82092.c                         |    6 +-
+ drivers/pcmcia/pd6729.c                         |    8 +-
+ drivers/pcmcia/pxa2xx_sharpsl.c                 |    2 +-
+ drivers/pcmcia/rsrc_nonstatic.c                 |    6 +-
+ drivers/pcmcia/sa1100_assabet.c                 |    2 +-
+ drivers/pcmcia/sa1100_cerf.c                    |    2 +-
+ drivers/pcmcia/sa1100_generic.c                 |    4 +-
+ drivers/pcmcia/sa1100_h3600.c                   |    2 +-
+ drivers/pcmcia/sa1100_shannon.c                 |    2 +-
+ drivers/pcmcia/sa1100_simpad.c                  |    2 +-
+ drivers/pcmcia/sa1111_generic.c                 |    4 +-
+ drivers/pcmcia/sa1111_jornada720.c              |    2 +-
+ drivers/pcmcia/vrc4171_card.c                   |    8 +-
+ drivers/pcmcia/vrc4173_cardu.c                  |    8 +-
+ drivers/pcmcia/xxs1500_ss.c                     |    6 +-
+ drivers/pcmcia/yenta_socket.c                   |    6 +-
+ drivers/pinctrl/pinctrl-bcm2835.c               |    8 +-
+ drivers/pinctrl/pinctrl-imx.c                   |    2 +-
+ drivers/pinctrl/pinctrl-imx23.c                 |    4 +-
+ drivers/pinctrl/pinctrl-imx28.c                 |    4 +-
+ drivers/pinctrl/pinctrl-imx35.c                 |    4 +-
+ drivers/pinctrl/pinctrl-imx51.c                 |    4 +-
+ drivers/pinctrl/pinctrl-imx53.c                 |    4 +-
+ drivers/pinctrl/pinctrl-imx6q.c                 |    4 +-
+ drivers/pinctrl/pinctrl-mmp2.c                  |    4 +-
+ drivers/pinctrl/pinctrl-mxs.c                   |    2 +-
+ drivers/pinctrl/pinctrl-pxa168.c                |    4 +-
+ drivers/pinctrl/pinctrl-pxa910.c                |    4 +-
+ drivers/pinctrl/pinctrl-single.c                |    6 +-
+ drivers/pinctrl/pinctrl-sirf.c                  |    2 +-
+ drivers/pinctrl/pinctrl-tegra.c                 |    2 +-
+ drivers/pinctrl/pinctrl-tegra20.c               |    4 +-
+ drivers/pinctrl/pinctrl-tegra30.c               |    4 +-
+ drivers/pinctrl/pinctrl-u300.c                  |    4 +-
+ drivers/pinctrl/spear/pinctrl-spear.c           |    2 +-
+ drivers/pinctrl/spear/pinctrl-spear.h           |    2 +-
+ drivers/pinctrl/spear/pinctrl-spear1310.c       |    6 +-
+ drivers/pinctrl/spear/pinctrl-spear1340.c       |    6 +-
+ drivers/pinctrl/spear/pinctrl-spear300.c        |    6 +-
+ drivers/pinctrl/spear/pinctrl-spear310.c        |    6 +-
+ drivers/pinctrl/spear/pinctrl-spear320.c        |    6 +-
+ drivers/pnp/pnpbios/core.c                      |   20 +-
+ drivers/power/88pm860x_battery.c                |    6 +-
+ drivers/power/88pm860x_charger.c                |    6 +-
+ drivers/power/ab8500_btemp.c                    |    6 +-
+ drivers/power/ab8500_charger.c                  |    6 +-
+ drivers/power/ab8500_fg.c                       |    6 +-
+ drivers/power/abx500_chargalg.c                 |    6 +-
+ drivers/power/avs/smartreflex.c                 |    8 +-
+ drivers/power/bq27x00_battery.c                 |    6 +-
+ drivers/power/charger-manager.c                 |    4 +-
+ drivers/power/collie_battery.c                  |    6 +-
+ drivers/power/da9052-battery.c                  |    6 +-
+ drivers/power/ds2780_battery.c                  |    6 +-
+ drivers/power/ds2781_battery.c                  |    6 +-
+ drivers/power/generic-adc-battery.c             |    6 +-
+ drivers/power/gpio-charger.c                    |    6 +-
+ drivers/power/intel_mid_battery.c               |    8 +-
+ drivers/power/isp1704_charger.c                 |    6 +-
+ drivers/power/jz4740-battery.c                  |    6 +-
+ drivers/power/lp8727_charger.c                  |    4 +-
+ drivers/power/lp8788-charger.c                  |    6 +-
+ drivers/power/max17040_battery.c                |    6 +-
+ drivers/power/max17042_battery.c                |    6 +-
+ drivers/power/max8903_charger.c                 |    6 +-
+ drivers/power/max8925_power.c                   |   10 +-
+ drivers/power/max8997_charger.c                 |    6 +-
+ drivers/power/max8998_charger.c                 |    6 +-
+ drivers/power/olpc_battery.c                    |    6 +-
+ drivers/power/pcf50633-charger.c                |    6 +-
+ drivers/power/s3c_adc_battery.c                 |    2 +-
+ drivers/power/sbs-battery.c                     |    6 +-
+ drivers/power/smb347-charger.c                  |    2 +-
+ drivers/power/tosa_battery.c                    |    6 +-
+ drivers/power/wm831x_backup.c                   |    6 +-
+ drivers/power/wm831x_power.c                    |    6 +-
+ drivers/power/wm8350_power.c                    |    6 +-
+ drivers/power/wm97xx_battery.c                  |    6 +-
+ drivers/power/z2_battery.c                      |    6 +-
+ drivers/ptp/ptp_pch.c                           |    4 +-
+ drivers/pwm/pwm-ab8500.c                        |    6 +-
+ drivers/pwm/pwm-bfin.c                          |    4 +-
+ drivers/pwm/pwm-imx.c                           |    6 +-
+ drivers/pwm/pwm-jz4740.c                        |    6 +-
+ drivers/pwm/pwm-lpc32xx.c                       |    4 +-
+ drivers/pwm/pwm-mxs.c                           |    4 +-
+ drivers/pwm/pwm-puv3.c                          |    6 +-
+ drivers/pwm/pwm-pxa.c                           |    6 +-
+ drivers/pwm/pwm-samsung.c                       |    4 +-
+ drivers/pwm/pwm-tegra.c                         |    4 +-
+ drivers/pwm/pwm-tiecap.c                        |    6 +-
+ drivers/pwm/pwm-tiehrpwm.c                      |    6 +-
+ drivers/pwm/pwm-twl6030.c                       |    2 +-
+ drivers/rapidio/devices/tsi721.c                |    4 +-
+ drivers/rapidio/devices/tsi721.h                |    2 +-
+ drivers/rapidio/devices/tsi721_dma.c            |    2 +-
+ drivers/rapidio/rio-scan.c                      |   14 +-
+ drivers/rapidio/rio.c                           |    6 +-
+ drivers/video/backlight/adp5520_bl.c            |    6 +-
+ drivers/video/backlight/adp8860_bl.c            |   14 +-
+ drivers/video/backlight/adp8870_bl.c            |   14 +-
+ drivers/video/backlight/ams369fg06.c            |    6 +-
+ drivers/video/backlight/apple_bl.c              |    4 +-
+ drivers/video/backlight/corgi_lcd.c             |    6 +-
+ drivers/video/backlight/ep93xx_bl.c             |    2 +-
+ drivers/video/backlight/hp680_bl.c              |    2 +-
+ drivers/video/backlight/ili9320.c               |    4 +-
+ drivers/video/backlight/l4f00242t03.c           |    6 +-
+ drivers/video/backlight/ld9040.c                |    4 +-
+ drivers/video/backlight/lm3533_bl.c             |    8 +-
+ drivers/video/backlight/lm3630_bl.c             |    8 +-
+ drivers/video/backlight/lm3639_bl.c             |    8 +-
+ drivers/video/backlight/lms283gf05.c            |    6 +-
+ drivers/video/backlight/lp855x_bl.c             |    4 +-
+ drivers/video/backlight/ltv350qv.c              |    6 +-
+ drivers/video/backlight/max8925_bl.c            |    6 +-
+ drivers/video/backlight/pcf50633-backlight.c    |    6 +-
+ drivers/video/backlight/platform_lcd.c          |    6 +-
+ drivers/video/backlight/s6e63m0.c               |    6 +-
+ drivers/video/backlight/tdo24m.c                |    6 +-
+ drivers/video/backlight/tosa_bl.c               |    6 +-
+ drivers/video/backlight/tosa_lcd.c              |    6 +-
+ drivers/video/backlight/vgg2432a4.c             |    6 +-
+ drivers/watchdog/acquirewdt.c                   |    6 +-
+ drivers/watchdog/advantechwdt.c                 |    6 +-
+ drivers/watchdog/ar7_wdt.c                      |    6 +-
+ drivers/watchdog/at91rm9200_wdt.c               |    6 +-
+ drivers/watchdog/ath79_wdt.c                    |    6 +-
+ drivers/watchdog/bcm63xx_wdt.c                  |    6 +-
+ drivers/watchdog/bfin_wdt.c                     |    6 +-
+ drivers/watchdog/cpu5wdt.c                      |    8 +-
+ drivers/watchdog/cpwd.c                         |    6 +-
+ drivers/watchdog/da9052_wdt.c                   |    6 +-
+ drivers/watchdog/davinci_wdt.c                  |    6 +-
+ drivers/watchdog/dw_wdt.c                       |    6 +-
+ drivers/watchdog/ep93xx_wdt.c                   |    6 +-
+ drivers/watchdog/gef_wdt.c                      |    4 +-
+ drivers/watchdog/geodewdt.c                     |    6 +-
+ drivers/watchdog/hpwdt.c                        |   30 +--
+ drivers/watchdog/i6300esb.c                     |   10 +-
+ drivers/watchdog/iTCO_wdt.c                     |    8 +-
+ drivers/watchdog/ib700wdt.c                     |    6 +-
+ drivers/watchdog/ie6xx_wdt.c                    |   10 +-
+ drivers/watchdog/jz4740_wdt.c                   |    6 +-
+ drivers/watchdog/ks8695_wdt.c                   |    6 +-
+ drivers/watchdog/lantiq_wdt.c                   |    6 +-
+ drivers/watchdog/max63xx_wdt.c                  |    6 +-
+ drivers/watchdog/mixcomwd.c                     |    2 +-
+ drivers/watchdog/mpc8xxx_wdt.c                  |    6 +-
+ drivers/watchdog/mpcore_wdt.c                   |    6 +-
+ drivers/watchdog/mtx-1_wdt.c                    |    6 +-
+ drivers/watchdog/mv64x60_wdt.c                  |    6 +-
+ drivers/watchdog/nuc900_wdt.c                   |    6 +-
+ drivers/watchdog/nv_tco.c                       |   10 +-
+ drivers/watchdog/of_xilinx_wdt.c                |    8 +-
+ drivers/watchdog/omap_wdt.c                     |    6 +-
+ drivers/watchdog/orion_wdt.c                    |    8 +-
+ drivers/watchdog/pcwd.c                         |    8 +-
+ drivers/watchdog/pcwd_pci.c                     |    6 +-
+ drivers/watchdog/pnx4008_wdt.c                  |    6 +-
+ drivers/watchdog/rc32434_wdt.c                  |    6 +-
+ drivers/watchdog/rdc321x_wdt.c                  |    6 +-
+ drivers/watchdog/riowd.c                        |    6 +-
+ drivers/watchdog/s3c2410_wdt.c                  |    6 +-
+ drivers/watchdog/sch311x_wdt.c                  |    6 +-
+ drivers/watchdog/shwdt.c                        |    6 +-
+ drivers/watchdog/sp5100_tco.c                   |   10 +-
+ drivers/watchdog/sp805_wdt.c                    |    6 +-
+ drivers/watchdog/stmp3xxx_wdt.c                 |    6 +-
+ drivers/watchdog/ts72xx_wdt.c                   |    6 +-
+ drivers/watchdog/twl4030_wdt.c                  |    6 +-
+ drivers/watchdog/via_wdt.c                      |    6 +-
+ drivers/watchdog/wdt_pci.c                      |    6 +-
+ drivers/watchdog/wm831x_wdt.c                   |    6 +-
+ drivers/watchdog/wm8350_wdt.c                   |    6 +-
+ drivers/watchdog/xen_wdt.c                      |    6 +-
+ fs/debugfs/inode.c                              |    1 -
+ fs/sysfs/file.c                                 |    4 +-
+ include/linux/kobject.h                         |   18 --
+ include/linux/mfd/88pm80x.h                     |    2 +-
+ include/linux/mfd/abx500/ab8500.h               |    4 +-
+ include/linux/mfd/pm8xxx/irq.h                  |    8 +-
+ include/linux/pci.h                             |    8 +-
+ kernel/ksysfs.c                                 |    5 +-
+ kernel/sysctl.c                                 |    4 +-
+ lib/Makefile                                    |    3 +-
+ 490 files changed, 2029 insertions(+), 1819 deletions(-)
+ create mode 100644 Documentation/zh_CN/arm/kernel_user_helpers.txt
+ delete mode 100644 drivers/pci/hotplug.c
+Merging tty/tty-next (218cbbd staging/fwserial: Remove superfluous free)
+$ git merge tty/tty-next
+Resolved 'drivers/tty/serial/omap-serial.c' using previous resolution.
+Resolved 'drivers/tty/serial/xilinx_uartps.c' using previous resolution.
+Auto-merging drivers/tty/vt/vt.c
+Auto-merging drivers/tty/serial/xilinx_uartps.c
+CONFLICT (content): Merge conflict in drivers/tty/serial/xilinx_uartps.c
+Auto-merging drivers/tty/serial/serial_core.c
+Auto-merging drivers/tty/serial/sa1100.c
+Auto-merging drivers/tty/serial/omap-serial.c
+CONFLICT (content): Merge conflict in drivers/tty/serial/omap-serial.c
+Auto-merging drivers/tty/serial/icom.c
+Auto-merging drivers/tty/serial/bfin_uart.c
+Auto-merging drivers/tty/serial/atmel_serial.c
+Auto-merging drivers/tty/serial/Kconfig
+Auto-merging drivers/tty/hvc/hvc_vio.c
+Auto-merging drivers/tty/hvc/hvc_opal.c
+Auto-merging arch/x86/platform/ce4100/ce4100.c
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master f757e6a] Merge remote-tracking branch 'tty/tty-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/ABI/testing/sysfs-tty                |  112 +
+ .../bindings/tty/serial/fsl-mxs-auart.txt          |    8 +
+ .../devicetree/bindings/tty/serial/of-serial.txt   |    5 +-
+ MAINTAINERS                                        |    1 +
+ arch/alpha/include/asm/ioctls.h                    |    3 +
+ arch/alpha/kernel/srmcons.c                        |    5 +-
+ arch/arm/boot/dts/imx28.dtsi                       |    1 +
+ arch/arm/plat-omap/include/plat/serial.h           |    9 -
+ arch/ia64/hp/sim/simserial.c                       |    1 +
+ arch/m68k/emu/nfcon.c                              |    6 +-
+ arch/mips/include/uapi/asm/ioctls.h                |    3 +
+ arch/parisc/include/uapi/asm/ioctls.h              |    3 +
+ arch/parisc/kernel/pdc_cons.c                      |    5 +-
+ arch/powerpc/include/uapi/asm/ioctls.h             |    3 +
+ arch/sh/include/uapi/asm/ioctls.h                  |    3 +
+ arch/sparc/include/uapi/asm/ioctls.h               |    3 +
+ arch/um/drivers/chan_kern.c                        |   17 +-
+ arch/um/drivers/line.c                             |    2 +
+ arch/x86/platform/ce4100/ce4100.c                  |    3 +
+ arch/xtensa/include/uapi/asm/ioctls.h              |    3 +
+ arch/xtensa/platforms/iss/console.c                |    1 +
+ drivers/bluetooth/hci_ldisc.c                      |    7 +-
+ drivers/char/pcmcia/synclink_cs.c                  |    5 +-
+ drivers/char/ttyprintk.c                           |    4 +-
+ drivers/isdn/capi/capi.c                           |   36 +-
+ drivers/isdn/gigaset/common.c                      |    1 +
+ drivers/isdn/i4l/isdn_tty.c                        |    4 +
+ drivers/misc/pti.c                                 |    7 +-
+ drivers/mmc/card/sdio_uart.c                       |   24 +-
+ drivers/net/usb/hso.c                              |    5 +-
+ drivers/s390/char/con3215.c                        |    1 +
+ drivers/s390/char/sclp_tty.c                       |    4 +-
+ drivers/s390/char/sclp_vt220.c                     |    2 +
+ drivers/s390/char/tty3270.c                        |    2 +
+ drivers/staging/Kconfig                            |    4 +
+ drivers/staging/Makefile                           |    2 +
+ drivers/staging/ccg/u_serial.c                     |    5 +-
+ drivers/staging/dgrp/dgrp_common.h                 |    1 -
+ drivers/staging/dgrp/dgrp_driver.c                 |    4 -
+ drivers/staging/dgrp/dgrp_net_ops.c                |   73 +-
+ drivers/staging/dgrp/dgrp_specproc.c               |    4 +-
+ drivers/staging/dgrp/dgrp_sysfs.c                  |   18 -
+ drivers/staging/dgrp/dgrp_tty.c                    |   39 +-
+ drivers/staging/fwserial/Kconfig                   |    9 +
+ drivers/staging/fwserial/Makefile                  |    2 +
+ drivers/staging/fwserial/TODO                      |   37 +
+ drivers/staging/fwserial/dma_fifo.c                |  307 ++
+ drivers/staging/fwserial/dma_fifo.h                |  130 +
+ drivers/staging/fwserial/fwserial.c                | 2943 ++++++++++++++++++
+ drivers/staging/fwserial/fwserial.h                |  387 +++
+ drivers/staging/ipack/devices/ipoctal.c            |    2 +
+ drivers/staging/sb105x/Kconfig                     |    9 +
+ drivers/staging/sb105x/Makefile                    |    3 +
+ drivers/staging/sb105x/sb_mp_register.h            |  295 ++
+ drivers/staging/sb105x/sb_pci_mp.c                 | 3195 ++++++++++++++++++++
+ drivers/staging/sb105x/sb_pci_mp.h                 |  293 ++
+ drivers/staging/sb105x/sb_ser_core.h               |  368 +++
+ drivers/tty/amiserial.c                            |    2 +
+ drivers/tty/bfin_jtag_comm.c                       |    6 +-
+ drivers/tty/cyclades.c                             |   28 +-
+ drivers/tty/ehv_bytechan.c                         |    4 +-
+ drivers/tty/hvc/hvc_opal.c                         |    8 +-
+ drivers/tty/hvc/hvc_vio.c                          |    6 +-
+ drivers/tty/hvc/hvc_xen.c                          |    2 +-
+ drivers/tty/hvc/hvcs.c                             |   20 +-
+ drivers/tty/hvc/hvsi.c                             |    1 +
+ drivers/tty/ipwireless/network.c                   |    5 +-
+ drivers/tty/ipwireless/tty.c                       |    1 +
+ drivers/tty/isicom.c                               |   35 +-
+ drivers/tty/moxa.c                                 |   12 +-
+ drivers/tty/mxser.c                                |   35 +-
+ drivers/tty/n_gsm.c                                |   11 +-
+ drivers/tty/n_tty.c                                |  752 ++---
+ drivers/tty/nozomi.c                               |   23 +-
+ drivers/tty/pty.c                                  |   81 +-
+ drivers/tty/rocket.c                               |    4 +-
+ drivers/tty/serial/68328serial.c                   |    2 +
+ drivers/tty/serial/8250/8250.c                     |   98 +-
+ drivers/tty/serial/8250/8250.h                     |   36 +
+ drivers/tty/serial/8250/8250_acorn.c               |    6 +-
+ drivers/tty/serial/8250/8250_dw.c                  |   31 +-
+ drivers/tty/serial/8250/8250_early.c               |   46 +-
+ drivers/tty/serial/8250/8250_em.c                  |    8 +-
+ drivers/tty/serial/8250/8250_hp300.c               |   10 +-
+ drivers/tty/serial/8250/8250_pci.c                 |  352 ++-
+ drivers/tty/serial/8250/8250_pnp.c                 |   14 +-
+ drivers/tty/serial/Kconfig                         |   47 +-
+ drivers/tty/serial/Makefile                        |    1 +
+ drivers/tty/serial/altera_jtaguart.c               |    6 +-
+ drivers/tty/serial/altera_uart.c                   |    6 +-
+ drivers/tty/serial/amba-pl011.c                    |   25 +-
+ drivers/tty/serial/apbuart.c                       |    2 +-
+ drivers/tty/serial/ar933x_uart.c                   |   96 +-
+ drivers/tty/serial/arc_uart.c                      |  746 +++++
+ drivers/tty/serial/atmel_serial.c                  |   10 +-
+ drivers/tty/serial/bcm63xx_uart.c                  |    6 +-
+ drivers/tty/serial/bfin_sport_uart.c               |    6 +-
+ drivers/tty/serial/bfin_uart.c                     |   20 +-
+ drivers/tty/serial/clps711x.c                      |  595 ++--
+ drivers/tty/serial/cpm_uart/cpm_uart_core.c        |    4 +-
+ drivers/tty/serial/efm32-uart.c                    |    6 +-
+ drivers/tty/serial/icom.c                          |   14 +-
+ drivers/tty/serial/ifx6x60.c                       |  168 +-
+ drivers/tty/serial/ifx6x60.h                       |    2 +
+ drivers/tty/serial/ioc3_serial.c                   |    2 +-
+ drivers/tty/serial/jsm/jsm.h                       |    8 +-
+ drivers/tty/serial/jsm/jsm_driver.c                |    9 +-
+ drivers/tty/serial/jsm/jsm_neo.c                   |  116 +-
+ drivers/tty/serial/jsm/jsm_tty.c                   |  104 +-
+ drivers/tty/serial/kgdb_nmi.c                      |    2 +
+ drivers/tty/serial/lpc32xx_hs.c                    |    6 +-
+ drivers/tty/serial/max3100.c                       |    6 +-
+ drivers/tty/serial/max310x.c                       |   11 +-
+ drivers/tty/serial/mcf.c                           |    6 +-
+ drivers/tty/serial/mfd.c                           |    7 +-
+ drivers/tty/serial/mpc52xx_uart.c                  |    2 +-
+ drivers/tty/serial/mrst_max3110.c                  |    6 +-
+ drivers/tty/serial/msm_serial.c                    |    2 +-
+ drivers/tty/serial/msm_serial_hs.c                 |    8 +-
+ drivers/tty/serial/mux.c                           |    6 +-
+ drivers/tty/serial/mxs-auart.c                     |  376 ++-
+ drivers/tty/serial/of_serial.c                     |   38 +-
+ drivers/tty/serial/omap-serial.c                   |   24 +-
+ drivers/tty/serial/pch_uart.c                      |    4 +-
+ drivers/tty/serial/pxa.c                           |   55 +
+ drivers/tty/serial/sa1100.c                        |    2 +-
+ drivers/tty/serial/samsung.c                       |   46 +-
+ drivers/tty/serial/sc26xx.c                        |    6 +-
+ drivers/tty/serial/sccnxp.c                        |    6 +-
+ drivers/tty/serial/serial_core.c                   |  186 +-
+ drivers/tty/serial/serial_txx9.c                   |   16 +-
+ drivers/tty/serial/sh-sci.c                        |  154 +-
+ drivers/tty/serial/sirfsoc_uart.c                  |    4 +-
+ drivers/tty/serial/sunhv.c                         |    6 +-
+ drivers/tty/serial/sunsab.c                        |    8 +-
+ drivers/tty/serial/sunsu.c                         |   10 +-
+ drivers/tty/serial/sunzilog.c                      |   14 +-
+ drivers/tty/serial/timbuart.c                      |    6 +-
+ drivers/tty/serial/uartlite.c                      |   14 +-
+ drivers/tty/serial/vr41xx_siu.c                    |    8 +-
+ drivers/tty/serial/vt8500_serial.c                 |   14 +-
+ drivers/tty/serial/xilinx_uartps.c                 |    6 +-
+ drivers/tty/synclink.c                             |    7 +-
+ drivers/tty/synclink_gt.c                          |   11 +-
+ drivers/tty/synclinkmp.c                           |   11 +-
+ drivers/tty/sysrq.c                                |    3 +-
+ drivers/tty/tty_audit.c                            |   15 +-
+ drivers/tty/tty_buffer.c                           |  228 +-
+ drivers/tty/tty_io.c                               |   24 +-
+ drivers/tty/tty_ioctl.c                            |   21 -
+ drivers/tty/tty_ldisc.c                            |   47 +-
+ drivers/tty/tty_mutex.c                            |    4 +-
+ drivers/tty/tty_port.c                             |   18 +-
+ drivers/tty/vt/consolemap.c                        |    6 +-
+ drivers/tty/vt/selection.c                         |    9 +-
+ drivers/tty/vt/vt.c                                |    5 +-
+ drivers/tty/vt/vt_ioctl.c                          |    1 +
+ drivers/usb/gadget/u_serial.c                      |    5 +-
+ drivers/usb/serial/usb-serial.c                    |    1 +
+ fs/compat_ioctl.c                                  |    3 +
+ fs/devpts/inode.c                                  |   61 +-
+ include/linux/devpts_fs.h                          |   20 +-
+ include/linux/pci_ids.h                            |    5 +
+ include/linux/serial_8250.h                        |    2 +
+ include/linux/tty.h                                |   45 +-
+ include/linux/tty_flip.h                           |    2 +-
+ include/uapi/asm-generic/ioctls.h                  |    3 +
+ include/uapi/linux/serial_core.h                   |    5 +-
+ include/uapi/linux/serial_reg.h                    |   18 +
+ kernel/auditsc.c                                   |    2 +-
+ kernel/printk.c                                    |   12 +-
+ net/irda/ircomm/ircomm_tty.c                       |    1 +
+ 172 files changed, 11956 insertions(+), 1771 deletions(-)
+ create mode 100644 drivers/staging/fwserial/Kconfig
+ create mode 100644 drivers/staging/fwserial/Makefile
+ create mode 100644 drivers/staging/fwserial/TODO
+ create mode 100644 drivers/staging/fwserial/dma_fifo.c
+ create mode 100644 drivers/staging/fwserial/dma_fifo.h
+ create mode 100644 drivers/staging/fwserial/fwserial.c
+ create mode 100644 drivers/staging/fwserial/fwserial.h
+ create mode 100644 drivers/staging/sb105x/Kconfig
+ create mode 100644 drivers/staging/sb105x/Makefile
+ create mode 100644 drivers/staging/sb105x/sb_mp_register.h
+ create mode 100644 drivers/staging/sb105x/sb_pci_mp.c
+ create mode 100644 drivers/staging/sb105x/sb_pci_mp.h
+ create mode 100644 drivers/staging/sb105x/sb_ser_core.h
+ create mode 100644 drivers/tty/serial/arc_uart.c
+$ git am -3 ../patches/0001-disable-the-SB105X-driver.patch
+Applying: disable the SB105X driver
+$ git reset HEAD^
+Unstaged changes after reset:
+M	drivers/staging/sb105x/Kconfig
+$ git add -A .
+$ git commit -v -a --amend
+[master 5261f3c] Merge remote-tracking branch 'tty/tty-next'
+Merging usb/usb-next (fb37ef9 USB: mark uas driver as BROKEN)
+$ git merge usb/usb-next
+Removing firmware/dabusb/firmware.HEX
+Removing firmware/dabusb/bitstream.bin.ihex
+Auto-merging drivers/usb/storage/realtek_cr.c
+Removing drivers/usb/host/ohci-xls.c
+Removing drivers/usb/host/ohci-sh.c
+Removing drivers/usb/host/ohci-ppc-soc.c
+Removing drivers/usb/host/ohci-pnx8550.c
+Removing drivers/usb/host/ohci-cns3xxx.c
+Removing drivers/usb/host/ohci-au1xxx.c
+Removing drivers/usb/host/ehci-xls.c
+Removing drivers/usb/host/ehci-ls1x.c
+Removing drivers/usb/host/ehci-lpm.c
+Removing drivers/usb/host/ehci-ixp4xx.c
+Removing drivers/usb/host/ehci-cns3xxx.c
+Removing drivers/usb/host/ehci-au1xxx.c
+Auto-merging drivers/usb/gadget/tcm_usb_gadget.c
+Removing drivers/usb/gadget/file_storage.c
+Auto-merging drivers/usb/gadget/at91_udc.c
+Auto-merging drivers/usb/core/driver.c
+Auto-merging arch/mips/loongson1/common/platform.c
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/DocBook/gadget.tmpl                  |    2 +-
+ Documentation/devices.txt                          |    3 -
+ .../devicetree/bindings/usb/am33xx-usb.txt         |    8 +-
+ Documentation/usb/error-codes.txt                  |    7 +-
+ Documentation/usb/mass-storage.txt                 |   15 +-
+ MAINTAINERS                                        |    6 -
+ arch/arm/configs/afeb9260_defconfig                |    2 +-
+ arch/arm/configs/at91sam9260_defconfig             |    2 +-
+ arch/arm/configs/at91sam9261_defconfig             |    2 +-
+ arch/arm/configs/at91sam9263_defconfig             |    2 +-
+ arch/arm/configs/at91sam9g20_defconfig             |    2 +-
+ arch/arm/configs/corgi_defconfig                   |    2 +-
+ arch/arm/configs/davinci_all_defconfig             |    2 +-
+ arch/arm/configs/h7202_defconfig                   |    3 +-
+ arch/arm/configs/magician_defconfig                |    2 +-
+ arch/arm/configs/mini2440_defconfig                |    2 +-
+ arch/arm/configs/omap1_defconfig                   |    3 +-
+ arch/arm/configs/prima2_defconfig                  |    1 -
+ arch/arm/configs/spitz_defconfig                   |    2 +-
+ arch/arm/configs/stamp9g20_defconfig               |    2 +-
+ arch/arm/configs/viper_defconfig                   |    2 +-
+ arch/arm/configs/zeus_defconfig                    |    2 +-
+ arch/arm/mach-cns3xxx/cns3420vb.c                  |   53 +-
+ arch/avr32/configs/atngw100_defconfig              |    2 +-
+ arch/avr32/configs/atngw100_evklcd100_defconfig    |    2 +-
+ arch/avr32/configs/atngw100_evklcd101_defconfig    |    2 +-
+ arch/avr32/configs/atngw100_mrmt_defconfig         |    2 +-
+ arch/avr32/configs/atngw100mkii_defconfig          |    2 +-
+ .../avr32/configs/atngw100mkii_evklcd100_defconfig |    2 +-
+ .../avr32/configs/atngw100mkii_evklcd101_defconfig |    2 +-
+ arch/avr32/configs/atstk1002_defconfig             |    2 +-
+ arch/avr32/configs/atstk1003_defconfig             |    2 +-
+ arch/avr32/configs/atstk1004_defconfig             |    2 +-
+ arch/avr32/configs/atstk1006_defconfig             |    2 +-
+ arch/avr32/configs/favr-32_defconfig               |    2 +-
+ arch/avr32/configs/hammerhead_defconfig            |    2 +-
+ arch/blackfin/configs/CM-BF527_defconfig           |    2 +-
+ arch/blackfin/configs/CM-BF548_defconfig           |    2 +-
+ arch/blackfin/configs/CM-BF561_defconfig           |    2 +-
+ arch/mips/alchemy/common/Makefile                  |    2 +-
+ arch/mips/alchemy/common/platform.c                |   58 +-
+ .../mips/alchemy/common/usb.c                      |    0
+ arch/mips/ath79/dev-usb.c                          |    2 -
+ arch/mips/configs/bcm47xx_defconfig                |    2 +-
+ arch/mips/configs/db1000_defconfig                 |    1 +
+ arch/mips/configs/db1235_defconfig                 |    2 +
+ arch/mips/configs/gpr_defconfig                    |    1 +
+ arch/mips/configs/ls1b_defconfig                   |    1 +
+ arch/mips/configs/mtx1_defconfig                   |    3 +-
+ arch/mips/loongson1/common/platform.c              |    7 +-
+ arch/mips/netlogic/xlr/platform.c                  |   17 +-
+ arch/mips/pnx8550/common/platform.c                |   31 +-
+ arch/sh/configs/ecovec24_defconfig                 |    2 +-
+ arch/sh/configs/se7724_defconfig                   |    2 +-
+ arch/sh/kernel/cpu/sh3/setup-sh7720.c              |    6 +-
+ arch/sh/kernel/cpu/sh4a/setup-sh7757.c             |    6 +-
+ arch/sh/kernel/cpu/sh4a/setup-sh7763.c             |    6 +-
+ arch/sh/kernel/cpu/sh4a/setup-sh7786.c             |    6 +-
+ drivers/usb/c67x00/c67x00-drv.c                    |    6 +-
+ drivers/usb/chipidea/Kconfig                       |    1 +
+ drivers/usb/chipidea/ci13xxx_imx.c                 |    8 +-
+ drivers/usb/chipidea/ci13xxx_msm.c                 |    6 +-
+ drivers/usb/chipidea/ci13xxx_pci.c                 |    6 +-
+ drivers/usb/chipidea/core.c                        |    9 +-
+ drivers/usb/chipidea/debug.c                       |    3 -
+ drivers/usb/chipidea/host.c                        |   67 +-
+ drivers/usb/chipidea/usbmisc_imx6q.c               |    6 +-
+ drivers/usb/class/cdc-acm.c                        |   38 +
+ drivers/usb/core/devices.c                         |   18 +-
+ drivers/usb/core/driver.c                          |   25 -
+ drivers/usb/core/generic.c                         |    7 +-
+ drivers/usb/core/hcd.c                             |   19 +-
+ drivers/usb/core/hub.c                             |   97 +-
+ drivers/usb/core/message.c                         |   66 +-
+ drivers/usb/core/urb.c                             |   29 +-
+ drivers/usb/core/usb.c                             |   13 +-
+ drivers/usb/dwc3/Makefile                          |   14 +-
+ drivers/usb/dwc3/core.c                            |   96 +-
+ drivers/usb/dwc3/core.h                            |    3 -
+ drivers/usb/dwc3/debugfs.c                         |    4 +-
+ drivers/usb/dwc3/dwc3-exynos.c                     |   57 +-
+ drivers/usb/dwc3/dwc3-omap.c                       |   24 +-
+ drivers/usb/dwc3/dwc3-pci.c                        |   24 +-
+ drivers/usb/dwc3/gadget.c                          |    4 +-
+ drivers/usb/early/ehci-dbgp.c                      |    4 +-
+ drivers/usb/gadget/Kconfig                         |   29 +-
+ drivers/usb/gadget/Makefile                        |    2 -
+ drivers/usb/gadget/at91_udc.c                      |    4 +-
+ drivers/usb/gadget/bcm63xx_udc.c                   |    6 +-
+ drivers/usb/gadget/composite.c                     |    8 +-
+ drivers/usb/gadget/config.c                        |   39 +-
+ drivers/usb/gadget/dummy_hcd.c                     |  170 +-
+ drivers/usb/gadget/f_acm.c                         |   79 +-
+ drivers/usb/gadget/f_ecm.c                         |  112 +-
+ drivers/usb/gadget/f_eem.c                         |   51 +-
+ drivers/usb/gadget/f_fs.c                          |    4 +-
+ drivers/usb/gadget/f_hid.c                         |   30 +-
+ drivers/usb/gadget/f_loopback.c                    |   28 +-
+ drivers/usb/gadget/f_mass_storage.c                |   63 +-
+ drivers/usb/gadget/f_midi.c                        |   14 +-
+ drivers/usb/gadget/f_ncm.c                         |   94 +-
+ drivers/usb/gadget/f_obex.c                        |   42 +-
+ drivers/usb/gadget/f_phonet.c                      |   21 +-
+ drivers/usb/gadget/f_rndis.c                       |   94 +-
+ drivers/usb/gadget/f_serial.c                      |   38 +-
+ drivers/usb/gadget/f_sourcesink.c                  |  104 +-
+ drivers/usb/gadget/f_subset.c                      |   75 +-
+ drivers/usb/gadget/f_uac1.c                        |   23 +-
+ drivers/usb/gadget/f_uac2.c                        |  222 +-
+ drivers/usb/gadget/f_uvc.c                         |  138 +-
+ drivers/usb/gadget/file_storage.c                  | 3656 --------------------
+ drivers/usb/gadget/fsl_qe_udc.c                    |   14 +-
+ drivers/usb/gadget/fsl_udc_core.c                  |    2 +-
+ drivers/usb/gadget/hid.c                           |    4 +-
+ drivers/usb/gadget/inode.c                         |    3 -
+ drivers/usb/gadget/lpc32xx_udc.c                   |    6 +-
+ drivers/usb/gadget/mv_u3d_core.c                   |    2 +-
+ drivers/usb/gadget/mv_udc_core.c                   |    4 +-
+ drivers/usb/gadget/net2272.c                       |   29 +-
+ drivers/usb/gadget/net2280.c                       |    2 +-
+ drivers/usb/gadget/omap_udc.c                      |   10 +-
+ drivers/usb/gadget/printer.c                       |   12 +-
+ drivers/usb/gadget/pxa27x_udc.h                    |    2 +-
+ drivers/usb/gadget/s3c-hsotg.c                     |   12 +-
+ drivers/usb/gadget/s3c-hsudc.c                     |    2 +-
+ drivers/usb/gadget/storage_common.c                |  165 +-
+ drivers/usb/gadget/tcm_usb_gadget.c                |   11 +-
+ drivers/usb/gadget/udc-core.c                      |   11 -
+ drivers/usb/host/Kconfig                           |   35 +-
+ drivers/usb/host/Makefile                          |    4 +-
+ drivers/usb/host/bcma-hcd.c                        |   15 +-
+ drivers/usb/host/ehci-atmel.c                      |   15 +-
+ drivers/usb/host/ehci-au1xxx.c                     |  184 -
+ drivers/usb/host/ehci-cns3xxx.c                    |  155 -
+ drivers/usb/host/ehci-dbg.c                        |  112 -
+ drivers/usb/host/ehci-fsl.c                        |    1 -
+ drivers/usb/host/ehci-grlib.c                      |   20 +-
+ drivers/usb/host/ehci-hcd.c                        |  204 +-
+ drivers/usb/host/ehci-hub.c                        |   47 +-
+ drivers/usb/host/ehci-ixp4xx.c                     |  139 -
+ drivers/usb/host/ehci-lpm.c                        |   84 -
+ drivers/usb/host/ehci-ls1x.c                       |  147 -
+ drivers/usb/host/ehci-msm.c                        |    5 +-
+ drivers/usb/host/ehci-mxc.c                        |   10 +-
+ drivers/usb/host/ehci-octeon.c                     |    3 -
+ drivers/usb/host/ehci-omap.c                       |    3 -
+ drivers/usb/host/ehci-orion.c                      |   20 +-
+ drivers/usb/host/ehci-pci.c                        |  132 +-
+ drivers/usb/host/ehci-platform.c                   |  102 +-
+ drivers/usb/host/ehci-pmcmsp.c                     |    1 -
+ drivers/usb/host/ehci-ppc-of.c                     |    4 +-
+ drivers/usb/host/ehci-ps3.c                        |    2 +-
+ drivers/usb/host/ehci-q.c                          |   12 +-
+ drivers/usb/host/ehci-s5p.c                        |   16 +-
+ drivers/usb/host/ehci-sched.c                      |  136 +-
+ drivers/usb/host/ehci-sh.c                         |    9 +-
+ drivers/usb/host/ehci-spear.c                      |   59 +-
+ drivers/usb/host/ehci-tegra.c                      |   18 +-
+ drivers/usb/host/ehci-vt8500.c                     |   21 -
+ drivers/usb/host/ehci-w90x900.c                    |   10 +-
+ drivers/usb/host/ehci-xilinx-of.c                  |    2 +-
+ drivers/usb/host/ehci-xls.c                        |  142 -
+ drivers/usb/host/ehci.h                            |   45 +-
+ drivers/usb/host/fhci-hcd.c                        |    8 +-
+ drivers/usb/host/fsl-mph-dr-of.c                   |   16 +-
+ drivers/usb/host/imx21-hcd.c                       |    2 +-
+ drivers/usb/host/isp116x-hcd.c                     |    2 +-
+ drivers/usb/host/isp1362-hcd.c                     |    6 +-
+ drivers/usb/host/isp1760-if.c                      |   15 +-
+ drivers/usb/host/ohci-at91.c                       |   22 +-
+ drivers/usb/host/ohci-au1xxx.c                     |  234 --
+ drivers/usb/host/ohci-cns3xxx.c                    |  166 -
+ drivers/usb/host/ohci-ep93xx.c                     |    4 +-
+ drivers/usb/host/ohci-exynos.c                     |   38 +-
+ drivers/usb/host/ohci-hcd.c                        |  139 +-
+ drivers/usb/host/ohci-hub.c                        |   42 -
+ drivers/usb/host/ohci-jz4740.c                     |    6 +-
+ drivers/usb/host/ohci-nxp.c                        |    4 +-
+ drivers/usb/host/ohci-octeon.c                     |    2 +-
+ drivers/usb/host/ohci-omap.c                       |    2 +-
+ drivers/usb/host/ohci-omap3.c                      |    6 +-
+ drivers/usb/host/ohci-pci.c                        |   49 +-
+ drivers/usb/host/ohci-platform.c                   |   34 +-
+ drivers/usb/host/ohci-pnx8550.c                    |  243 --
+ drivers/usb/host/ohci-ppc-of.c                     |    4 +-
+ drivers/usb/host/ohci-ppc-soc.c                    |  216 --
+ drivers/usb/host/ohci-ps3.c                        |    4 +-
+ drivers/usb/host/ohci-pxa27x.c                     |    8 +-
+ drivers/usb/host/ohci-q.c                          |   23 +-
+ drivers/usb/host/ohci-s3c2410.c                    |   41 +-
+ drivers/usb/host/ohci-sa1111.c                     |    2 +-
+ drivers/usb/host/ohci-sh.c                         |  141 -
+ drivers/usb/host/ohci-sm501.c                      |    2 +-
+ drivers/usb/host/ohci-spear.c                      |   50 +-
+ drivers/usb/host/ohci-tmio.c                       |    8 +-
+ drivers/usb/host/ohci-xls.c                        |  152 -
+ drivers/usb/host/pci-quirks.c                      |   20 +-
+ drivers/usb/host/r8a66597-hcd.c                    |   12 +-
+ drivers/usb/host/sl811-hcd.c                       |    6 +-
+ drivers/usb/host/ssb-hcd.c                         |   19 +-
+ drivers/usb/host/u132-hcd.c                        |    6 +-
+ drivers/usb/host/uhci-grlib.c                      |    2 +-
+ drivers/usb/host/uhci-platform.c                   |    2 +-
+ drivers/usb/host/uhci-q.c                          |   73 +-
+ drivers/usb/host/xhci-mem.c                        |    9 +-
+ drivers/usb/host/xhci-pci.c                        |   16 +-
+ drivers/usb/host/xhci-ring.c                       |   34 +-
+ drivers/usb/host/xhci.c                            |   32 +-
+ drivers/usb/host/xhci.h                            |    2 +-
+ drivers/usb/misc/Kconfig                           |    1 +
+ drivers/usb/misc/ezusb.c                           |   38 +-
+ drivers/usb/misc/usbtest.c                         |    4 +
+ drivers/usb/musb/am35x.c                           |   40 +-
+ drivers/usb/musb/blackfin.c                        |   38 +-
+ drivers/usb/musb/cppi_dma.c                        |    4 +-
+ drivers/usb/musb/da8xx.c                           |   40 +-
+ drivers/usb/musb/davinci.c                         |   40 +-
+ drivers/usb/musb/musb_core.c                       |  137 +-
+ drivers/usb/musb/musb_core.h                       |    5 +-
+ drivers/usb/musb/musb_debugfs.c                    |    2 +-
+ drivers/usb/musb/musb_dma.h                        |    3 +-
+ drivers/usb/musb/musb_dsps.c                       |  141 +-
+ drivers/usb/musb/musb_gadget.c                     |   36 +-
+ drivers/usb/musb/musb_gadget_ep0.c                 |    6 +-
+ drivers/usb/musb/musb_host.c                       |    2 +-
+ drivers/usb/musb/musbhsdma.c                       |    3 +-
+ drivers/usb/musb/musbhsdma.h                       |    4 -
+ drivers/usb/musb/omap2430.c                        |   52 +-
+ drivers/usb/musb/tusb6010.c                        |   40 +-
+ drivers/usb/musb/tusb6010_omap.c                   |    3 +-
+ drivers/usb/musb/ux500.c                           |   62 +-
+ drivers/usb/musb/ux500_dma.c                       |    3 +-
+ drivers/usb/otg/ab8500-usb.c                       |    6 +-
+ drivers/usb/otg/fsl_otg.c                          |    6 +-
+ drivers/usb/otg/isp1301_omap.c                     |    2 +-
+ drivers/usb/otg/msm_otg.c                          |    4 +-
+ drivers/usb/otg/mv_otg.c                           |   14 +-
+ drivers/usb/otg/mxs-phy.c                          |   59 +-
+ drivers/usb/otg/nop-usb-xceiv.c                    |    6 +-
+ drivers/usb/otg/twl4030-usb.c                      |   48 +-
+ drivers/usb/otg/twl6030-usb.c                      |    2 +-
+ drivers/usb/phy/Kconfig                            |   12 +
+ drivers/usb/phy/Makefile                           |    1 +
+ drivers/usb/phy/mv_u3d_phy.c                       |    4 +-
+ drivers/usb/phy/omap-usb2.c                        |    6 +-
+ drivers/usb/phy/rcar-phy.c                         |  220 ++
+ drivers/usb/phy/tegra_usb_phy.c                    |    4 +-
+ drivers/usb/renesas_usbhs/common.c                 |    9 +-
+ drivers/usb/renesas_usbhs/common.h                 |    1 +
+ drivers/usb/renesas_usbhs/fifo.c                   |   14 +-
+ drivers/usb/renesas_usbhs/mod.c                    |    3 +-
+ drivers/usb/renesas_usbhs/mod_gadget.c             |   11 +
+ drivers/usb/renesas_usbhs/mod_host.c               |   45 +-
+ drivers/usb/renesas_usbhs/pipe.c                   |  101 +
+ drivers/usb/renesas_usbhs/pipe.h                   |    1 +
+ drivers/usb/serial/aircable.c                      |    5 -
+ drivers/usb/serial/ark3116.c                       |    5 -
+ drivers/usb/serial/belkin_sa.c                     |    5 -
+ drivers/usb/serial/bus.c                           |   10 -
+ drivers/usb/serial/cp210x.c                        |   37 +-
+ drivers/usb/serial/cyberjack.c                     |    5 -
+ drivers/usb/serial/cypress_m8.c                    |    5 -
+ drivers/usb/serial/digi_acceleport.c               |    4 -
+ drivers/usb/serial/empeg.c                         |    4 -
+ drivers/usb/serial/ftdi_sio.c                      |   82 +-
+ drivers/usb/serial/ftdi_sio_ids.h                  |    6 +
+ drivers/usb/serial/generic.c                       |    1 +
+ drivers/usb/serial/hp4x.c                          |    5 -
+ drivers/usb/serial/io_edgeport.c                   |    4 -
+ drivers/usb/serial/io_ti.c                         |    4 -
+ drivers/usb/serial/ipaq.c                          |    5 -
+ drivers/usb/serial/ipw.c                           |    4 -
+ drivers/usb/serial/iuu_phoenix.c                   |    8 +-
+ drivers/usb/serial/keyspan.c                       |    4 -
+ drivers/usb/serial/keyspan_pda.c                   |    4 -
+ drivers/usb/serial/kl5kusb105.c                    |    4 -
+ drivers/usb/serial/kobil_sct.c                     |    2 -
+ drivers/usb/serial/mct_u232.c                      |    4 -
+ drivers/usb/serial/metro-usb.c                     |    2 -
+ drivers/usb/serial/mos7720.c                       |    4 -
+ drivers/usb/serial/mos7840.c                       |    4 -
+ drivers/usb/serial/omninet.c                       |    4 -
+ drivers/usb/serial/opticon.c                       |  351 +-
+ drivers/usb/serial/option.c                        |  113 +-
+ drivers/usb/serial/oti6858.c                       |    2 -
+ drivers/usb/serial/quatech2.c                      |    2 -
+ drivers/usb/serial/siemens_mpi.c                   |    2 -
+ drivers/usb/serial/sierra.c                        |    3 +-
+ drivers/usb/serial/spcp8x5.c                       |    4 -
+ drivers/usb/serial/ssu100.c                        |    2 -
+ drivers/usb/serial/usb_wwan.c                      |    2 -
+ drivers/usb/serial/vivopay-serial.c                |    3 -
+ drivers/usb/storage/Kconfig                        |    2 +-
+ drivers/usb/storage/realtek_cr.c                   |    2 +-
+ drivers/usb/storage/usb.c                          |    1 -
+ drivers/usb/usb-skeleton.c                         |   13 +-
+ drivers/usb/wusbcore/devconnect.c                  |   13 -
+ drivers/uwb/Kconfig                                |    3 +-
+ drivers/uwb/reset.c                                |    1 +
+ drivers/uwb/umc-bus.c                              |    2 +-
+ firmware/Makefile                                  |    1 -
+ firmware/dabusb/bitstream.bin.ihex                 |  761 ----
+ firmware/dabusb/firmware.HEX                       |  649 ----
+ include/linux/usb.h                                |   50 +-
+ include/linux/usb/composite.h                      |    4 +-
+ include/linux/usb/ehci_pdriver.h                   |    5 +-
+ include/linux/usb/ezusb.h                          |    8 -
+ include/linux/usb/gadget.h                         |    7 +
+ include/linux/usb/ohci_pdriver.h                   |    2 +
+ include/linux/usb/phy.h                            |   15 +-
+ 310 files changed, 3027 insertions(+), 10753 deletions(-)
+ rename drivers/usb/host/alchemy-common.c => arch/mips/alchemy/common/usb.c (100%)
+ delete mode 100644 drivers/usb/gadget/file_storage.c
+ delete mode 100644 drivers/usb/host/ehci-au1xxx.c
+ delete mode 100644 drivers/usb/host/ehci-cns3xxx.c
+ delete mode 100644 drivers/usb/host/ehci-ixp4xx.c
+ delete mode 100644 drivers/usb/host/ehci-lpm.c
+ delete mode 100644 drivers/usb/host/ehci-ls1x.c
+ delete mode 100644 drivers/usb/host/ehci-xls.c
+ delete mode 100644 drivers/usb/host/ohci-au1xxx.c
+ delete mode 100644 drivers/usb/host/ohci-cns3xxx.c
+ delete mode 100644 drivers/usb/host/ohci-pnx8550.c
+ delete mode 100644 drivers/usb/host/ohci-ppc-soc.c
+ delete mode 100644 drivers/usb/host/ohci-sh.c
+ delete mode 100644 drivers/usb/host/ohci-xls.c
+ create mode 100644 drivers/usb/phy/rcar-phy.c
+ delete mode 100644 firmware/dabusb/bitstream.bin.ihex
+ delete mode 100644 firmware/dabusb/firmware.HEX
+Merging staging/staging-next (8b7a13c staging: r8712u: Fix possible buffer overrun)
+$ git merge staging/staging-next
+Auto-merging include/linux/ipack.h
+Removing drivers/staging/vt6656/upc.h
+Removing drivers/staging/vt6656/ioctl.h
+Removing drivers/staging/vt6656/ioctl.c
+Removing drivers/staging/telephony/phonedev.c
+Removing drivers/staging/telephony/ixj_pcmcia.c
+Removing drivers/staging/telephony/ixj.h
+Removing drivers/staging/telephony/ixj.c
+Removing drivers/staging/telephony/ixj-ver.h
+Removing drivers/staging/telephony/TODO
+Removing drivers/staging/telephony/Makefile
+Removing drivers/staging/telephony/Kconfig
+Removing drivers/staging/rts_pstor/xd.h
+Removing drivers/staging/rts_pstor/xd.c
+Removing drivers/staging/rts_pstor/trace.h
+Removing drivers/staging/rts_pstor/spi.h
+Removing drivers/staging/rts_pstor/spi.c
+Removing drivers/staging/rts_pstor/sd.h
+Removing drivers/staging/rts_pstor/sd.c
+Removing drivers/staging/rts_pstor/rtsx_transport.h
+Removing drivers/staging/rts_pstor/rtsx_transport.c
+Removing drivers/staging/rts_pstor/rtsx_sys.h
+Removing drivers/staging/rts_pstor/rtsx_scsi.h
+Removing drivers/staging/rts_pstor/rtsx_scsi.c
+Removing drivers/staging/rts_pstor/rtsx_chip.h
+Removing drivers/staging/rts_pstor/rtsx_chip.c
+Removing drivers/staging/rts_pstor/rtsx_card.h
+Removing drivers/staging/rts_pstor/rtsx_card.c
+Removing drivers/staging/rts_pstor/rtsx.h
+Removing drivers/staging/rts_pstor/rtsx.c
+Removing drivers/staging/rts_pstor/ms.h
+Removing drivers/staging/rts_pstor/ms.c
+Removing drivers/staging/rts_pstor/general.h
+Removing drivers/staging/rts_pstor/general.c
+Removing drivers/staging/rts_pstor/debug.h
+Removing drivers/staging/rts_pstor/TODO
+Removing drivers/staging/rts_pstor/Makefile
+Removing drivers/staging/rts_pstor/Kconfig
+Auto-merging drivers/staging/omap-thermal/omap-thermal-common.c
+Auto-merging drivers/staging/media/lirc/lirc_serial.c
+Auto-merging drivers/staging/media/dt3155v4l/dt3155v4l.c
+Removing drivers/staging/line6/dumprequest.h
+Removing drivers/staging/line6/dumprequest.c
+Removing drivers/staging/line6/control.h
+Removing drivers/staging/line6/control.c
+Removing drivers/staging/ipack/ipack_ids.h
+Removing drivers/staging/ipack/bridges/Kconfig
+Removing drivers/staging/ipack/TODO
+Removing drivers/staging/ipack/Kconfig
+Removing drivers/staging/iio/gyro/adis16260_trigger.c
+Removing drivers/staging/iio/gyro/adis16260_ring.c
+Removing drivers/staging/iio/adc/max1363_ring.c
+Removing drivers/staging/iio/adc/max1363.h
+Removing drivers/staging/iio/adc/adt7310.c
+Removing drivers/staging/iio/adc/ad7887_ring.c
+Removing drivers/staging/iio/adc/ad7887.h
+Removing drivers/staging/iio/adc/ad7298_ring.c
+Removing drivers/staging/iio/adc/ad7298.h
+Removing drivers/staging/iio/accel/adis16240_trigger.c
+Removing drivers/staging/iio/accel/adis16240_ring.c
+Removing drivers/staging/iio/accel/adis16209_trigger.c
+Removing drivers/staging/iio/accel/adis16209_ring.c
+Removing drivers/staging/iio/accel/adis16204_trigger.c
+Removing drivers/staging/iio/accel/adis16204_ring.c
+Removing drivers/staging/iio/accel/adis16203_trigger.c
+Removing drivers/staging/iio/accel/adis16203_ring.c
+Removing drivers/staging/iio/accel/adis16201_trigger.c
+Removing drivers/staging/iio/accel/adis16201_ring.c
+Auto-merging drivers/staging/fwserial/fwserial.c
+CONFLICT (add/add): Merge conflict in drivers/staging/fwserial/fwserial.c
+Auto-merging drivers/staging/dgrp/dgrp_tty.c
+CONFLICT (content): Merge conflict in drivers/staging/dgrp/dgrp_tty.c
+Auto-merging drivers/staging/dgrp/dgrp_sysfs.c
+Auto-merging drivers/staging/dgrp/dgrp_net_ops.c
+Auto-merging drivers/staging/csr/netdev.c
+Removing drivers/staging/csr/csr_panic.h
+Removing drivers/staging/csr/csr_panic.c
+Removing drivers/staging/csr/csr_lib.h
+Auto-merging drivers/staging/comedi/drivers/usbdux.c
+Removing drivers/staging/comedi/drivers/mpc8260cpm.c
+Removing drivers/staging/comedi/drivers/addi_apci_3300.c
+Removing drivers/staging/comedi/drivers/addi_apci_3001.c
+Removing drivers/staging/comedi/drivers/addi_apci_2016.c
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+Removing driverRecorded preimage for 'drivers/staging/Kconfig'
+Recorded preimage for 'drivers/staging/Makefile'
+Recorded preimage for 'drivers/staging/fwserial/fwserial.c'
+Resolved 'drivers/iio/adc/Kconfig' using previous resolution.
+Resolved 'drivers/iio/adc/Makefile' using previous resolution.
+Resolved 'drivers/staging/dgrp/dgrp_tty.c' using previous resolution.
+s/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+Removing drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h
+Removing drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+Removing drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+Auto-merging drivers/staging/Makefile
+CONFLICT (content): Merge conflict in drivers/staging/Makefile
+Auto-merging drivers/staging/Kconfig
+CONFLICT (content): Merge conflict in drivers/staging/Kconfig
+Auto-merging drivers/ipack/ipack.c
+Auto-merging drivers/ipack/devices/scc2698.h
+Auto-merging drivers/ipack/devices/ipoctal.h
+Auto-merging drivers/ipack/devices/ipoctal.c
+Auto-merging drivers/ipack/devices/Kconfig
+Auto-merging drivers/ipack/carriers/tpci200.h
+Auto-merging drivers/ipack/carriers/tpci200.c
+Auto-merging drivers/ipack/Makefile
+Auto-merging drivers/iio/adc/max1363.c
+Auto-merging drivers/iio/adc/ad7887.c
+Auto-merging drivers/iio/adc/ad7298.c
+Auto-merging drivers/iio/adc/Makefile
+CONFLICT (content): Merge conflict in drivers/iio/adc/Makefile
+Auto-merging drivers/iio/adc/Kconfig
+CONFLICT (content): Merge conflict in drivers/iio/adc/Kconfig
+Auto-merging MAINTAINERS
+Removing Documentation/telephony/ixj.txt
+Removing Documentation/telephony/00-INDEX
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+Recorded resolution for 'drivers/staging/Kconfig'.
+Recorded resolution for 'drivers/staging/Makefile'.
+Recorded resolution for 'drivers/staging/fwserial/fwserial.c'.
+[master 28b7963] Merge remote-tracking branch 'staging/staging-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/ABI/testing/sysfs-bus-iio            |   24 +
+ Documentation/telephony/00-INDEX                   |    4 -
+ Documentation/telephony/ixj.txt                    |  394 -
+ MAINTAINERS                                        |    9 +
+ arch/arm/mach-omap2/board-overo.c                  |    1 -
+ arch/arm/mach-omap2/drm.c                          |    7 +
+ drivers/Kconfig                                    |    2 +
+ drivers/Makefile                                   |    1 +
+ drivers/iio/Kconfig                                |   13 +-
+ drivers/iio/Makefile                               |    8 +-
+ drivers/iio/accel/Kconfig                          |    2 +-
+ drivers/iio/accel/hid-sensor-accel-3d.c            |   21 +-
+ drivers/iio/adc/Kconfig                            |   43 +
+ drivers/iio/adc/Makefile                           |    5 +-
+ drivers/iio/adc/ad7266.c                           |    3 +-
+ .../iio/adc/ad7298_core.c => iio/adc/ad7298.c}     |  201 +-
+ drivers/iio/adc/ad7476.c                           |    2 +-
+ .../iio/adc/ad7887_core.c => iio/adc/ad7887.c}     |  217 +-
+ drivers/iio/adc/ad_sigma_delta.c                   |    2 +-
+ drivers/iio/adc/at91_adc.c                         |    6 +-
+ .../iio/adc/max1363_core.c => iio/adc/max1363.c}   |  330 +-
+ drivers/iio/buffer_cb.c                            |  113 +
+ drivers/iio/common/hid-sensors/Kconfig             |    2 +-
+ .../iio/common/hid-sensors/hid-sensor-trigger.c    |    6 +-
+ drivers/iio/dac/Kconfig                            |   12 +-
+ drivers/iio/dac/Makefile                           |    1 +
+ drivers/iio/dac/ad5449.c                           |  376 +
+ drivers/iio/dac/ad5686.c                           |    2 +-
+ drivers/iio/gyro/Kconfig                           |    9 +
+ drivers/iio/gyro/Makefile                          |    1 +
+ drivers/iio/gyro/adis16136.c                       |  581 ++
+ drivers/iio/gyro/hid-sensor-gyro-3d.c              |   21 +-
+ drivers/iio/imu/Kconfig                            |   27 +
+ drivers/iio/imu/Makefile                           |   10 +
+ drivers/iio/imu/adis.c                             |  440 +
+ drivers/iio/imu/adis16480.c                        |  925 ++
+ drivers/iio/imu/adis_buffer.c                      |  176 +
+ drivers/iio/imu/adis_trigger.c                     |   89 +
+ drivers/iio/industrialio-buffer.c                  |  386 +-
+ drivers/iio/industrialio-core.c                    |  105 +-
+ drivers/iio/industrialio-event.c                   |   11 +-
+ drivers/iio/inkern.c                               |    6 +-
+ drivers/iio/light/adjd_s311.c                      |    3 +-
+ drivers/iio/light/hid-sensor-als.c                 |   20 +-
+ drivers/iio/magnetometer/hid-sensor-magn-3d.c      |   21 +-
+ drivers/ipack/Kconfig                              |   24 +
+ drivers/{staging => }/ipack/Makefile               |    2 +-
+ drivers/ipack/carriers/Kconfig                     |    7 +
+ .../ipack/bridges => ipack/carriers}/Makefile      |    0
+ .../ipack/bridges => ipack/carriers}/tpci200.c     |  321 +-
+ .../ipack/bridges => ipack/carriers}/tpci200.h     |   33 +-
+ drivers/{staging => }/ipack/devices/Kconfig        |    1 -
+ drivers/{staging => }/ipack/devices/Makefile       |    0
+ drivers/{staging => }/ipack/devices/ipoctal.c      |  127 +-
+ drivers/{staging => }/ipack/devices/ipoctal.h      |    7 +-
+ drivers/{staging => }/ipack/devices/scc2698.h      |    7 +-
+ drivers/{staging => }/ipack/ipack.c                |   64 +-
+ drivers/staging/Kconfig                            |    6 -
+ drivers/staging/Makefile                           |    3 -
+ drivers/staging/android/Makefile                   |    2 +
+ drivers/staging/android/binder.c                   |  471 +-
+ drivers/staging/android/binder_trace.h             |  327 +
+ drivers/staging/android/logger.c                   |   21 +
+ drivers/staging/bcm/Adapter.h                      |    8 +-
+ drivers/staging/bcm/Bcmchar.c                      |  149 +-
+ drivers/staging/bcm/Bcmnet.c                       |    6 +-
+ drivers/staging/bcm/CmHost.c                       |   90 +-
+ drivers/staging/bcm/CmHost.h                       |  189 +-
+ drivers/staging/bcm/HandleControlPacket.c          |    2 +-
+ drivers/staging/bcm/HostMIBSInterface.h            |  384 +-
+ drivers/staging/bcm/InterfaceAdapter.h             |  142 +-
+ drivers/staging/bcm/InterfaceDld.c                 |    4 +-
+ drivers/staging/bcm/InterfaceIdleMode.c            |    2 +-
+ drivers/staging/bcm/InterfaceIdleMode.h            |    5 +-
+ drivers/staging/bcm/InterfaceInit.c                |   25 +-
+ drivers/staging/bcm/InterfaceInit.h                |    4 +-
+ drivers/staging/bcm/InterfaceIsr.c                 |    6 +-
+ drivers/staging/bcm/InterfaceIsr.h                 |    4 +-
+ drivers/staging/bcm/InterfaceMisc.c                |  124 +-
+ drivers/staging/bcm/InterfaceMisc.h                |    6 +-
+ drivers/staging/bcm/InterfaceRx.c                  |   16 +-
+ drivers/staging/bcm/InterfaceRx.h                  |    2 +-
+ drivers/staging/bcm/InterfaceTx.c                  |   14 +-
+ drivers/staging/bcm/Ioctl.h                        |  482 +-
+ drivers/staging/bcm/LeakyBucket.c                  |    6 +-
+ drivers/staging/bcm/Misc.c                         |  236 +-
+ drivers/staging/bcm/Prototypes.h                   |   36 +-
+ drivers/staging/bcm/Transmit.c                     |    2 +-
+ drivers/staging/bcm/cntrl_SignalingInterface.h     |  256 +-
+ drivers/staging/bcm/hostmibs.c                     |   12 +-
+ drivers/staging/bcm/nvm.c                          |   94 +-
+ drivers/staging/bcm/vendorspecificextn.c           |    6 +-
+ drivers/staging/bcm/vendorspecificextn.h           |    6 +-
+ drivers/staging/ccg/ccg.c                          |    8 +-
+ drivers/staging/ced1401/ced_ioc.c                  |   37 +-
+ drivers/staging/ced1401/usb1401.c                  |   36 +-
+ drivers/staging/ced1401/usb1401.h                  |    2 +-
+ drivers/staging/ced1401/userspace/use1401.c        |    8 +-
+ drivers/staging/comedi/Kconfig                     |   45 +-
+ drivers/staging/comedi/comedi.h                    |   65 +-
+ drivers/staging/comedi/comedi_compat32.c           |    1 -
+ drivers/staging/comedi/comedi_fops.c               |    5 +-
+ drivers/staging/comedi/comedidev.h                 |   70 +-
+ drivers/staging/comedi/drivers.c                   |  144 +-
+ drivers/staging/comedi/drivers/8255.c              |   27 +-
+ drivers/staging/comedi/drivers/8255_pci.c          |   26 +-
+ drivers/staging/comedi/drivers/Makefile            |    2 -
+ .../comedi/drivers/addi-data/APCI1710_82x54.c      |  205 +-
+ .../comedi/drivers/addi-data/APCI1710_82x54.h      |   73 -
+ .../comedi/drivers/addi-data/APCI1710_Chrono.c     |  245 +-
+ .../comedi/drivers/addi-data/APCI1710_Chrono.h     |   74 -
+ .../comedi/drivers/addi-data/APCI1710_Dig_io.c     |   44 +-
+ .../comedi/drivers/addi-data/APCI1710_Dig_io.h     |   46 -
+ .../comedi/drivers/addi-data/APCI1710_INCCPT.c     |  886 +-
+ .../comedi/drivers/addi-data/APCI1710_INCCPT.h     |  271 -
+ .../comedi/drivers/addi-data/APCI1710_Inp_cpt.c    |   39 +-
+ .../comedi/drivers/addi-data/APCI1710_Inp_cpt.h    |   47 -
+ .../comedi/drivers/addi-data/APCI1710_Pwm.c        |  278 +-
+ .../comedi/drivers/addi-data/APCI1710_Pwm.h        |   76 -
+ .../comedi/drivers/addi-data/APCI1710_Ssi.c        |   41 +-
+ .../comedi/drivers/addi-data/APCI1710_Ssi.h        |   43 -
+ .../comedi/drivers/addi-data/APCI1710_Tor.c        |   50 +-
+ .../comedi/drivers/addi-data/APCI1710_Tor.h        |   57 -
+ .../comedi/drivers/addi-data/APCI1710_Ttl.c        |   38 +-
+ .../comedi/drivers/addi-data/APCI1710_Ttl.h        |   44 -
+ .../comedi/drivers/addi-data/addi_amcc_s5933.h     |  469 -
+ .../staging/comedi/drivers/addi-data/addi_common.c | 2036 +---
+ .../staging/comedi/drivers/addi-data/addi_common.h |   32 -
+ .../staging/comedi/drivers/addi-data/addi_eeprom.c | 1367 +--
+ .../comedi/drivers/addi-data/hwdrv_APCI1710.c      |   69 +-
+ .../comedi/drivers/addi-data/hwdrv_APCI1710.h      |   71 -
+ .../comedi/drivers/addi-data/hwdrv_apci035.c       |  116 +-
+ .../comedi/drivers/addi-data/hwdrv_apci035.h       |  109 -
+ .../comedi/drivers/addi-data/hwdrv_apci1032.c      |  287 -
+ .../comedi/drivers/addi-data/hwdrv_apci1032.h      |   64 -
+ .../comedi/drivers/addi-data/hwdrv_apci1500.c      |  197 +-
+ .../comedi/drivers/addi-data/hwdrv_apci1500.h      |  165 -
+ .../comedi/drivers/addi-data/hwdrv_apci1516.c      |  542 -
+ .../comedi/drivers/addi-data/hwdrv_apci1516.h      |   65 -
+ .../comedi/drivers/addi-data/hwdrv_apci1564.c      |  469 +-
+ .../comedi/drivers/addi-data/hwdrv_apci1564.h      |  121 -
+ .../comedi/drivers/addi-data/hwdrv_apci16xx.c      |   57 +-
+ .../comedi/drivers/addi-data/hwdrv_apci16xx.h      |   79 -
+ .../comedi/drivers/addi-data/hwdrv_apci2016.c      |  460 -
+ .../comedi/drivers/addi-data/hwdrv_apci2016.h      |   72 -
+ .../comedi/drivers/addi-data/hwdrv_apci2032.c      |  333 +-
+ .../comedi/drivers/addi-data/hwdrv_apci2032.h      |   83 -
+ .../comedi/drivers/addi-data/hwdrv_apci2200.c      |  392 +-
+ .../comedi/drivers/addi-data/hwdrv_apci2200.h      |   61 -
+ .../comedi/drivers/addi-data/hwdrv_apci3120.c      | 1768 ++--
+ .../comedi/drivers/addi-data/hwdrv_apci3120.h      |  249 -
+ .../comedi/drivers/addi-data/hwdrv_apci3200.c      | 3417 +++----
+ .../comedi/drivers/addi-data/hwdrv_apci3200.h      |  191 -
+ .../comedi/drivers/addi-data/hwdrv_apci3501.c      |  320 +-
+ .../comedi/drivers/addi-data/hwdrv_apci3501.h      |   98 -
+ .../comedi/drivers/addi-data/hwdrv_apci3xxx.c      |  414 +-
+ .../comedi/drivers/addi-data/hwdrv_apci3xxx.h      |   48 -
+ drivers/staging/comedi/drivers/addi_apci_035.c     |   72 +-
+ drivers/staging/comedi/drivers/addi_apci_1032.c    |  396 +-
+ drivers/staging/comedi/drivers/addi_apci_1500.c    |   72 +-
+ drivers/staging/comedi/drivers/addi_apci_1516.c    |  348 +-
+ drivers/staging/comedi/drivers/addi_apci_1564.c    |   69 +-
+ drivers/staging/comedi/drivers/addi_apci_16xx.c    |   72 +-
+ drivers/staging/comedi/drivers/addi_apci_1710.c    |  153 +-
+ drivers/staging/comedi/drivers/addi_apci_2016.c    |    9 -
+ drivers/staging/comedi/drivers/addi_apci_2032.c    |   66 +-
+ drivers/staging/comedi/drivers/addi_apci_2200.c    |   64 +-
+ drivers/staging/comedi/drivers/addi_apci_3001.c    |    9 -
+ drivers/staging/comedi/drivers/addi_apci_3120.c    |  273 +-
+ drivers/staging/comedi/drivers/addi_apci_3200.c    |  119 +-
+ drivers/staging/comedi/drivers/addi_apci_3300.c    |    5 -
+ drivers/staging/comedi/drivers/addi_apci_3501.c    |   70 +-
+ drivers/staging/comedi/drivers/addi_apci_3xxx.c    |  794 +-
+ drivers/staging/comedi/drivers/adl_pci6208.c       |   23 +-
+ drivers/staging/comedi/drivers/adl_pci7x3x.c       |   15 +-
+ drivers/staging/comedi/drivers/adl_pci8164.c       |   27 +-
+ drivers/staging/comedi/drivers/adl_pci9111.c       |   81 +-
+ drivers/staging/comedi/drivers/adl_pci9118.c       |  494 +-
+ drivers/staging/comedi/drivers/adq12b.c            |   46 +-
+ drivers/staging/comedi/drivers/adv_pci1710.c       |   73 +-
+ drivers/staging/comedi/drivers/adv_pci1723.c       |   24 +-
+ drivers/staging/comedi/drivers/adv_pci_dio.c       |   25 +-
+ drivers/staging/comedi/drivers/aio_aio12_8.c       |    8 +-
+ drivers/staging/comedi/drivers/aio_iiro_16.c       |   19 +-
+ drivers/staging/comedi/drivers/amplc_dio200.c      | 1468 ++-
+ drivers/staging/comedi/drivers/amplc_pc236.c       |   72 +-
+ drivers/staging/comedi/drivers/amplc_pc263.c       |   23 +-
+ drivers/staging/comedi/drivers/amplc_pci224.c      |   93 +-
+ drivers/staging/comedi/drivers/amplc_pci230.c      |  157 +-
+ drivers/staging/comedi/drivers/cb_das16_cs.c       |   69 +-
+ drivers/staging/comedi/drivers/cb_pcidas.c         |  106 +-
+ drivers/staging/comedi/drivers/cb_pcidas64.c       | 3041 +++---
+ drivers/staging/comedi/drivers/cb_pcidda.c         |  681 +-
+ drivers/staging/comedi/drivers/cb_pcimdas.c        |  121 +-
+ drivers/staging/comedi/drivers/cb_pcimdda.c        |   25 +-
+ drivers/staging/comedi/drivers/comedi_bond.c       |    8 +-
+ drivers/staging/comedi/drivers/comedi_fc.c         |    2 +-
+ drivers/staging/comedi/drivers/comedi_fc.h         |   44 +
+ drivers/staging/comedi/drivers/comedi_parport.c    |   35 +-
+ drivers/staging/comedi/drivers/comedi_test.c       |   71 +-
+ drivers/staging/comedi/drivers/contec_pci_dio.c    |   15 +-
+ drivers/staging/comedi/drivers/daqboard2000.c      |   23 +-
+ drivers/staging/comedi/drivers/das08.c             |   39 +-
+ drivers/staging/comedi/drivers/das08_cs.c          |    9 +-
+ drivers/staging/comedi/drivers/das16.c             |   78 +-
+ drivers/staging/comedi/drivers/das16m1.c           |   80 +-
+ drivers/staging/comedi/drivers/das1800.c           |   66 +-
+ drivers/staging/comedi/drivers/das6402.c           |   16 +-
+ drivers/staging/comedi/drivers/das800.c            |   79 +-
+ drivers/staging/comedi/drivers/dmm32at.c           |   80 +-
+ drivers/staging/comedi/drivers/dt2801.c            |   14 +-
+ drivers/staging/comedi/drivers/dt2811.c            |   13 +-
+ drivers/staging/comedi/drivers/dt2814.c            |   54 +-
+ drivers/staging/comedi/drivers/dt2815.c            |    9 +-
+ drivers/staging/comedi/drivers/dt282x.c            |  115 +-
+ drivers/staging/comedi/drivers/dt3000.c            |  620 +-
+ drivers/staging/comedi/drivers/dt9812.c            |   27 +-
+ drivers/staging/comedi/drivers/dyna_pci10xx.c      |   27 +-
+ drivers/staging/comedi/drivers/fl512.c             |   10 +-
+ drivers/staging/comedi/drivers/gsc_hpdi.c          |  515 +-
+ drivers/staging/comedi/drivers/icp_multi.c         |   22 +-
+ drivers/staging/comedi/drivers/ii_pci20kc.c        |   51 +-
+ drivers/staging/comedi/drivers/jr3_pci.c           |  658 +-
+ drivers/staging/comedi/drivers/jr3_pci.h           |   12 +-
+ drivers/staging/comedi/drivers/ke_counter.c        |   60 +-
+ drivers/staging/comedi/drivers/me4000.c            |   42 +-
+ drivers/staging/comedi/drivers/me_daq.c            |  595 +-
+ drivers/staging/comedi/drivers/mpc624.c            |   10 +-
+ drivers/staging/comedi/drivers/mpc8260cpm.c        |  164 -
+ drivers/staging/comedi/drivers/multiq3.c           |   11 +-
+ drivers/staging/comedi/drivers/ni_6527.c           |   64 +-
+ drivers/staging/comedi/drivers/ni_65xx.c           |  164 +-
+ drivers/staging/comedi/drivers/ni_660x.c           |  586 +-
+ drivers/staging/comedi/drivers/ni_670x.c           |   24 +-
+ drivers/staging/comedi/drivers/ni_at_a2150.c       |   64 +-
+ drivers/staging/comedi/drivers/ni_at_ao.c          |   13 +-
+ drivers/staging/comedi/drivers/ni_atmio.c          |   11 +-
+ drivers/staging/comedi/drivers/ni_atmio16d.c       |   58 +-
+ drivers/staging/comedi/drivers/ni_daq_dio24.c      |   14 +-
+ drivers/staging/comedi/drivers/ni_labpc.c          |  114 +-
+ drivers/staging/comedi/drivers/ni_labpc_cs.c       |    6 +-
+ drivers/staging/comedi/drivers/ni_mio_common.c     |  336 +-
+ drivers/staging/comedi/drivers/ni_mio_cs.c         |   29 +-
+ drivers/staging/comedi/drivers/ni_pcidio.c         |   85 +-
+ drivers/staging/comedi/drivers/ni_pcimio.c         |   62 +-
+ drivers/staging/comedi/drivers/ni_tio.h            |    4 +-
+ drivers/staging/comedi/drivers/ni_tiocmd.c         |   60 +-
+ drivers/staging/comedi/drivers/pcl711.c            |   51 +-
+ drivers/staging/comedi/drivers/pcl726.c            |   10 +-
+ drivers/staging/comedi/drivers/pcl812.c            |   85 +-
+ drivers/staging/comedi/drivers/pcl816.c            |   71 +-
+ drivers/staging/comedi/drivers/pcl818.c            |   80 +-
+ drivers/staging/comedi/drivers/pcm3724.c           |   44 +-
+ drivers/staging/comedi/drivers/pcm_common.c        |   34 +-
+ drivers/staging/comedi/drivers/pcmad.c             |   10 +-
+ drivers/staging/comedi/drivers/pcmda12.c           |   34 +-
+ drivers/staging/comedi/drivers/pcmmio.c            |  124 +-
+ drivers/staging/comedi/drivers/pcmuio.c            |   25 +-
+ drivers/staging/comedi/drivers/poc.c               |   15 +-
+ drivers/staging/comedi/drivers/quatech_daqp_cs.c   |   95 +-
+ drivers/staging/comedi/drivers/rtd520.c            |  950 +-
+ drivers/staging/comedi/drivers/rtd520.h            |  267 +-
+ drivers/staging/comedi/drivers/rti800.c            |   13 +-
+ drivers/staging/comedi/drivers/rti802.c            |    9 +-
+ drivers/staging/comedi/drivers/s526.c              |    8 +-
+ drivers/staging/comedi/drivers/s626.c              |  129 +-
+ drivers/staging/comedi/drivers/serial2002.c        |   44 +-
+ drivers/staging/comedi/drivers/skel.c              |  610 +-
+ drivers/staging/comedi/drivers/ssv_dnp.c           |   26 +-
+ drivers/staging/comedi/drivers/unioxx5.c           |   44 +-
+ drivers/staging/comedi/drivers/usbdux.c            |  125 +-
+ drivers/staging/comedi/drivers/usbduxfast.c        |  211 +-
+ drivers/staging/comedi/drivers/usbduxsigma.c       |  116 +-
+ drivers/staging/comedi/drivers/vmk80xx.c           |   20 +-
+ .../staging/comedi/kcomedilib/kcomedilib_main.c    |    6 +-
+ drivers/staging/comedi/proc.c                      |    1 -
+ drivers/staging/crystalhd/crystalhd_cmds.c         |    8 +-
+ drivers/staging/crystalhd/crystalhd_lnx.c          |   14 +-
+ drivers/staging/crystalhd/crystalhd_misc.c         |    2 +-
+ drivers/staging/csr/Makefile                       |    3 +-
+ drivers/staging/csr/bh.c                           |   19 +-
+ drivers/staging/csr/csr_framework_ext.c            |   97 -
+ drivers/staging/csr/csr_framework_ext.h            |  213 -
+ drivers/staging/csr/csr_framework_ext_types.h      |   41 +-
+ drivers/staging/csr/csr_lib.h                      |  188 -
+ drivers/staging/csr/csr_log.h                      |  172 +-
+ drivers/staging/csr/csr_log_configure.h            |  105 +-
+ drivers/staging/csr/csr_log_text.h                 |    8 -
+ drivers/staging/csr/csr_macro.h                    |   75 -
+ drivers/staging/csr/csr_msg_transport.h            |    8 -
+ drivers/staging/csr/csr_msgconv.c                  |    1 -
+ drivers/staging/csr/csr_msgconv.h                  |    9 -
+ drivers/staging/csr/csr_panic.c                    |   20 -
+ drivers/staging/csr/csr_panic.h                    |   53 -
+ drivers/staging/csr/csr_prim_defs.h                |    7 -
+ drivers/staging/csr/csr_result.h                   |    8 -
+ drivers/staging/csr/csr_sched.h                    |  215 +-
+ drivers/staging/csr/csr_sdio.h                     |    8 -
+ .../staging/csr/csr_serialize_primitive_types.c    |    1 -
+ drivers/staging/csr/csr_time.c                     |    9 +-
+ drivers/staging/csr/csr_time.h                     |   82 +-
+ drivers/staging/csr/csr_wifi_common.h              |    8 -
+ drivers/staging/csr/csr_wifi_fsm.h                 |    8 -
+ drivers/staging/csr/csr_wifi_fsm_event.h           |    8 -
+ drivers/staging/csr/csr_wifi_fsm_types.h           |   10 -
+ drivers/staging/csr/csr_wifi_hip_card.h            |    9 -
+ drivers/staging/csr/csr_wifi_hip_card_sdio.c       |  162 -
+ drivers/staging/csr/csr_wifi_hip_card_sdio.h       |    8 -
+ drivers/staging/csr/csr_wifi_hip_chiphelper.h      |   64 -
+ .../staging/csr/csr_wifi_hip_chiphelper_private.h  |    8 -
+ drivers/staging/csr/csr_wifi_hip_conversions.h     |    8 -
+ drivers/staging/csr/csr_wifi_hip_download.c        |   18 -
+ drivers/staging/csr/csr_wifi_hip_dump.c            |   32 +-
+ drivers/staging/csr/csr_wifi_hip_send.c            |    2 -
+ drivers/staging/csr/csr_wifi_hip_signals.h         |   17 +-
+ drivers/staging/csr/csr_wifi_hip_sigs.h            |    8 -
+ drivers/staging/csr/csr_wifi_hip_ta_sampling.h     |    9 -
+ drivers/staging/csr/csr_wifi_hip_unifi.h           |   10 +-
+ .../staging/csr/csr_wifi_hip_unifi_signal_names.c  |   45 +-
+ drivers/staging/csr/csr_wifi_hip_unifi_udi.h       |    9 -
+ drivers/staging/csr/csr_wifi_hip_unifihw.h         |    8 -
+ drivers/staging/csr/csr_wifi_hip_unifiversion.h    |    8 -
+ drivers/staging/csr/csr_wifi_hip_xbv.c             |    2 +-
+ drivers/staging/csr/csr_wifi_hip_xbv.h             |    8 -
+ drivers/staging/csr/csr_wifi_hostio_prim.h         |    9 -
+ drivers/staging/csr/csr_wifi_lib.h                 |    9 -
+ drivers/staging/csr/csr_wifi_msgconv.h             |    9 -
+ .../staging/csr/csr_wifi_nme_ap_converter_init.h   |    8 -
+ drivers/staging/csr/csr_wifi_nme_ap_lib.h          |   28 -
+ drivers/staging/csr/csr_wifi_nme_ap_prim.h         |    9 -
+ drivers/staging/csr/csr_wifi_nme_ap_sef.h          |   10 -
+ drivers/staging/csr/csr_wifi_nme_ap_serialize.h    |    9 -
+ drivers/staging/csr/csr_wifi_nme_converter_init.h  |    8 -
+ drivers/staging/csr/csr_wifi_nme_lib.h             |   63 -
+ drivers/staging/csr/csr_wifi_nme_prim.h            |    9 -
+ drivers/staging/csr/csr_wifi_nme_serialize.h       |    8 -
+ drivers/staging/csr/csr_wifi_nme_task.h            |   11 -
+ drivers/staging/csr/csr_wifi_private_common.h      |    8 -
+ drivers/staging/csr/csr_wifi_result.h              |    8 -
+ .../staging/csr/csr_wifi_router_converter_init.h   |    8 -
+ .../csr/csr_wifi_router_ctrl_converter_init.h      |    8 -
+ drivers/staging/csr/csr_wifi_router_ctrl_lib.h     |   10 -
+ drivers/staging/csr/csr_wifi_router_ctrl_prim.h    |    9 -
+ drivers/staging/csr/csr_wifi_router_ctrl_sef.c     |   67 +-
+ drivers/staging/csr/csr_wifi_router_ctrl_sef.h     |    7 -
+ .../staging/csr/csr_wifi_router_ctrl_serialize.h   |    8 -
+ .../csr/csr_wifi_router_free_upstream_contents.c   |   46 +-
+ drivers/staging/csr/csr_wifi_router_lib.h          |   10 -
+ drivers/staging/csr/csr_wifi_router_prim.h         |    9 -
+ drivers/staging/csr/csr_wifi_router_sef.h          |    8 -
+ drivers/staging/csr/csr_wifi_router_serialize.h    |    8 -
+ drivers/staging/csr/csr_wifi_router_task.h         |    8 -
+ drivers/staging/csr/csr_wifi_sme_ap_lib.h          |    9 -
+ drivers/staging/csr/csr_wifi_sme_ap_prim.h         |    8 -
+ drivers/staging/csr/csr_wifi_sme_converter_init.h  |    8 -
+ drivers/staging/csr/csr_wifi_sme_lib.h             |   10 -
+ drivers/staging/csr/csr_wifi_sme_prim.h            |    9 -
+ drivers/staging/csr/csr_wifi_sme_sef.h             |  213 +-
+ drivers/staging/csr/csr_wifi_sme_serialize.h       |  336 +-
+ drivers/staging/csr/csr_wifi_sme_task.h            |   16 +-
+ drivers/staging/csr/csr_wifi_vif_utils.h           |   81 -
+ drivers/staging/csr/data_tx.c                      |   45 +-
+ drivers/staging/csr/drv.c                          |  101 +-
+ drivers/staging/csr/firmware.c                     |   15 -
+ drivers/staging/csr/inet.c                         |   10 +-
+ drivers/staging/csr/io.c                           |  102 +-
+ drivers/staging/csr/mlme.c                         |    3 -
+ drivers/staging/csr/monitor.c                      |   10 -
+ drivers/staging/csr/netdev.c                       |   88 +-
+ drivers/staging/csr/os.c                           |   18 +-
+ drivers/staging/csr/sdio_mmc.c                     |   28 -
+ drivers/staging/csr/sme_blocking.c                 |  307 +-
+ drivers/staging/csr/sme_native.c                   |   21 -
+ drivers/staging/csr/sme_sys.c                      |   17 +-
+ drivers/staging/csr/sme_userspace.h                |    2 +-
+ drivers/staging/csr/sme_wext.c                     |   49 -
+ drivers/staging/csr/ul_int.c                       |    1 -
+ drivers/staging/csr/unifi_event.c                  |    8 -
+ drivers/staging/csr/unifi_os.h                     |   23 -
+ drivers/staging/csr/unifi_pdu_processing.c         |   39 +-
+ drivers/staging/csr/unifi_priv.h                   |    7 +-
+ drivers/staging/csr/unifi_sme.c                    |   15 -
+ drivers/staging/csr/unifi_wext.h                   |    1 -
+ drivers/staging/cxt1e1/musycc.c                    | 2162 ++--
+ drivers/staging/cxt1e1/musycc.h                    |  236 +-
+ drivers/staging/cxt1e1/sbecrc.c                    |  105 +-
+ drivers/staging/dgrp/dgrp_dpa_ops.c                |    2 +-
+ drivers/staging/dgrp/dgrp_net_ops.c                |    5 +-
+ drivers/staging/dgrp/dgrp_sysfs.c                  |    3 +-
+ drivers/staging/dgrp/dgrp_tty.c                    |    4 -
+ drivers/staging/et131x/README                      |    2 +-
+ drivers/staging/et131x/et131x.c                    | 1323 +--
+ drivers/staging/et131x/et131x.h                    |    4 -
+ drivers/staging/ft1000/ft1000-usb/ft1000_proc.c    |    4 +-
+ drivers/staging/gdm72xx/gdm_qos.c                  |   33 +-
+ drivers/staging/gdm72xx/gdm_sdio.c                 |   29 +-
+ drivers/staging/gdm72xx/gdm_usb.c                  |   63 +-
+ drivers/staging/gdm72xx/gdm_wimax.c                |   70 +-
+ drivers/staging/gdm72xx/netlink_k.c                |   23 +-
+ drivers/staging/gdm72xx/sdio_boot.c                |  100 +-
+ drivers/staging/gdm72xx/usb_boot.c                 |   49 +-
+ drivers/staging/iio/accel/Kconfig                  |   21 +-
+ drivers/staging/iio/accel/Makefile                 |    5 -
+ drivers/staging/iio/accel/adis16201.h              |   89 +-
+ drivers/staging/iio/accel/adis16201_core.c         |  476 +-
+ drivers/staging/iio/accel/adis16201_ring.c         |  136 -
+ drivers/staging/iio/accel/adis16201_trigger.c      |   71 -
+ drivers/staging/iio/accel/adis16203.h              |   80 +-
+ drivers/staging/iio/accel/adis16203_core.c         |  432 +-
+ drivers/staging/iio/accel/adis16203_ring.c         |  136 -
+ drivers/staging/iio/accel/adis16203_trigger.c      |   73 -
+ drivers/staging/iio/accel/adis16204.h              |   79 +-
+ drivers/staging/iio/accel/adis16204_core.c         |  462 +-
+ drivers/staging/iio/accel/adis16204_ring.c         |  134 -
+ drivers/staging/iio/accel/adis16204_trigger.c      |   73 -
+ drivers/staging/iio/accel/adis16209.h              |   77 +-
+ drivers/staging/iio/accel/adis16209_core.c         |  496 +-
+ drivers/staging/iio/accel/adis16209_ring.c         |  134 -
+ drivers/staging/iio/accel/adis16209_trigger.c      |   81 -
+ drivers/staging/iio/accel/adis16220.h              |   20 +-
+ drivers/staging/iio/accel/adis16220_core.c         |  288 +-
+ drivers/staging/iio/accel/adis16240.h              |   85 +-
+ drivers/staging/iio/accel/adis16240_core.c         |  481 +-
+ drivers/staging/iio/accel/adis16240_ring.c         |  132 -
+ drivers/staging/iio/accel/adis16240_trigger.c      |   82 -
+ drivers/staging/iio/accel/kxsd9.c                  |   10 +-
+ drivers/staging/iio/accel/lis3l02dq.h              |    1 +
+ drivers/staging/iio/accel/lis3l02dq_core.c         |   16 +-
+ drivers/staging/iio/accel/lis3l02dq_ring.c         |    6 +-
+ drivers/staging/iio/accel/sca3000_core.c           |    6 +-
+ drivers/staging/iio/adc/Kconfig                    |   61 +-
+ drivers/staging/iio/adc/Makefile                   |   14 -
+ drivers/staging/iio/adc/ad7192.c                   |    6 +-
+ drivers/staging/iio/adc/ad7280a.c                  |    8 +-
+ drivers/staging/iio/adc/ad7291.c                   |    6 +-
+ drivers/staging/iio/adc/ad7298.h                   |   75 -
+ drivers/staging/iio/adc/ad7298_ring.c              |  113 -
+ drivers/staging/iio/adc/ad7606_par.c               |    6 +-
+ drivers/staging/iio/adc/ad7606_ring.c              |    2 +-
+ drivers/staging/iio/adc/ad7606_spi.c               |    6 +-
+ drivers/staging/iio/adc/ad7780.c                   |    6 +-
+ drivers/staging/iio/adc/ad7793.c                   |    6 +-
+ drivers/staging/iio/adc/ad7816.c                   |    6 +-
+ drivers/staging/iio/adc/ad7887.h                   |   99 -
+ drivers/staging/iio/adc/ad7887_ring.c              |  122 -
+ drivers/staging/iio/adc/ad799x_core.c              |    6 +-
+ drivers/staging/iio/adc/ad799x_ring.c              |    2 +-
+ drivers/staging/iio/adc/adt7310.c                  |  881 --
+ drivers/staging/iio/adc/adt7410.c                  |  460 +-
+ drivers/staging/iio/adc/lpc32xx_adc.c              |    8 +-
+ drivers/staging/iio/adc/max1363.h                  |  177 -
+ drivers/staging/iio/adc/max1363_ring.c             |  139 -
+ drivers/staging/iio/adc/mxs-lradc.c                |   11 +-
+ drivers/staging/iio/adc/spear_adc.c                |    6 +-
+ drivers/staging/iio/addac/adt7316-i2c.c            |    6 +-
+ drivers/staging/iio/addac/adt7316-spi.c            |    6 +-
+ drivers/staging/iio/addac/adt7316.c                |    4 +-
+ drivers/staging/iio/cdc/ad7150.c                   |   18 +-
+ drivers/staging/iio/cdc/ad7152.c                   |    8 +-
+ drivers/staging/iio/cdc/ad7746.c                   |    8 +-
+ drivers/staging/iio/frequency/ad5930.c             |    6 +-
+ drivers/staging/iio/frequency/ad9832.c             |    6 +-
+ drivers/staging/iio/frequency/ad9834.c             |    6 +-
+ drivers/staging/iio/frequency/ad9850.c             |    6 +-
+ drivers/staging/iio/frequency/ad9852.c             |    6 +-
+ drivers/staging/iio/frequency/ad9910.c             |    6 +-
+ drivers/staging/iio/frequency/ad9951.c             |    6 +-
+ drivers/staging/iio/gyro/Makefile                  |    1 -
+ drivers/staging/iio/gyro/adis16060_core.c          |   12 +-
+ drivers/staging/iio/gyro/adis16080_core.c          |    6 +-
+ drivers/staging/iio/gyro/adis16130_core.c          |    6 +-
+ drivers/staging/iio/gyro/adis16260.h               |   84 +-
+ drivers/staging/iio/gyro/adis16260_core.c          |  496 +-
+ drivers/staging/iio/gyro/adis16260_ring.c          |  136 -
+ drivers/staging/iio/gyro/adis16260_trigger.c       |   75 -
+ drivers/staging/iio/gyro/adxrs450_core.c           |    6 +-
+ drivers/staging/iio/iio_dummy_evgen.c              |    2 +-
+ drivers/staging/iio/iio_hwmon.c                    |    6 +-
+ drivers/staging/iio/iio_simple_dummy.c             |    2 +-
+ drivers/staging/iio/iio_simple_dummy_buffer.c      |    5 +-
+ drivers/staging/iio/impedance-analyzer/ad5933.c    |   10 +-
+ drivers/staging/iio/imu/adis16400.h                |   12 +-
+ drivers/staging/iio/imu/adis16400_core.c           |  161 +-
+ drivers/staging/iio/imu/adis16400_ring.c           |    5 +-
+ drivers/staging/iio/light/isl29018.c               |   53 +-
+ drivers/staging/iio/light/isl29028.c               |    6 +-
+ drivers/staging/iio/light/tsl2563.c                |   10 +-
+ drivers/staging/iio/light/tsl2583.c                |    6 +-
+ drivers/staging/iio/light/tsl2x7x_core.c           |    6 +-
+ drivers/staging/iio/magnetometer/ak8975.c          |    6 +-
+ drivers/staging/iio/magnetometer/hmc5843.c         |    8 +-
+ drivers/staging/iio/meter/ade7753.c                |    6 +-
+ drivers/staging/iio/meter/ade7753.h                |    2 -
+ drivers/staging/iio/meter/ade7754.c                |    6 +-
+ drivers/staging/iio/meter/ade7754.h                |    2 -
+ drivers/staging/iio/meter/ade7758.h                |    3 -
+ drivers/staging/iio/meter/ade7758_core.c           |    6 +-
+ drivers/staging/iio/meter/ade7758_ring.c           |    2 +-
+ drivers/staging/iio/meter/ade7759.c                |    6 +-
+ drivers/staging/iio/meter/ade7759.h                |    2 -
+ drivers/staging/iio/meter/ade7854-i2c.c            |    6 +-
+ drivers/staging/iio/meter/ade7854-spi.c            |    6 +-
+ drivers/staging/iio/meter/ade7854.h                |    2 -
+ drivers/staging/iio/resolver/ad2s1200.c            |    6 +-
+ drivers/staging/iio/resolver/ad2s1210.c            |    8 +-
+ drivers/staging/iio/resolver/ad2s90.c              |    6 +-
+ drivers/staging/iio/trigger/iio-trig-bfin-timer.c  |    6 +-
+ drivers/staging/iio/trigger/iio-trig-gpio.c        |    6 +-
+ .../staging/iio/trigger/iio-trig-periodic-rtc.c    |    6 +-
+ drivers/staging/imx-drm/Kconfig                    |    2 +-
+ drivers/staging/imx-drm/imx-drm-core.c             |    2 +-
+ drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h        |    2 +-
+ drivers/staging/imx-drm/ipu-v3/ipu-common.c        |   67 +-
+ drivers/staging/imx-drm/ipuv3-crtc.c               |    8 +-
+ drivers/staging/imx-drm/parallel-display.c         |   16 +-
+ drivers/staging/ipack/Kconfig                      |   21 -
+ drivers/staging/ipack/TODO                         |   22 -
+ drivers/staging/ipack/bridges/Kconfig              |    8 -
+ drivers/staging/ipack/ipack_ids.h                  |   32 -
+ drivers/staging/line6/Kconfig                      |   37 -
+ drivers/staging/line6/Makefile                     |    2 -
+ drivers/staging/line6/audio.c                      |    8 +-
+ drivers/staging/line6/capture.c                    |   13 +-
+ drivers/staging/line6/control.c                    |  995 --
+ drivers/staging/line6/control.h                    |  195 -
+ drivers/staging/line6/driver.c                     |   85 +-
+ drivers/staging/line6/driver.h                     |   10 +-
+ drivers/staging/line6/dumprequest.c                |  135 -
+ drivers/staging/line6/dumprequest.h                |   76 -
+ drivers/staging/line6/midi.c                       |  126 -
+ drivers/staging/line6/midi.h                       |   10 -
+ drivers/staging/line6/midibuf.c                    |    6 +-
+ drivers/staging/line6/pcm.c                        |    4 +-
+ drivers/staging/line6/pcm.h                        |    2 +-
+ drivers/staging/line6/playback.c                   |   17 +-
+ drivers/staging/line6/pod.c                        |  879 +-
+ drivers/staging/line6/pod.h                        |  105 +-
+ drivers/staging/line6/toneport.c                   |    8 +-
+ drivers/staging/line6/usbdefs.h                    |   10 +-
+ drivers/staging/line6/variax.c                     |  484 +-
+ drivers/staging/line6/variax.h                     |   60 -
+ drivers/staging/media/dt3155v4l/dt3155v4l.c        |   12 +-
+ drivers/staging/media/lirc/lirc_parallel.c         |    6 +-
+ drivers/staging/media/lirc/lirc_serial.c           |    6 +-
+ drivers/staging/media/lirc/lirc_sir.c              |    6 +-
+ drivers/staging/media/solo6x10/core.c              |    4 +-
+ drivers/staging/net/pc300_drv.c                    |    6 +-
+ drivers/staging/nvec/Kconfig                       |    1 +
+ drivers/staging/nvec/nvec.c                        |    8 +-
+ drivers/staging/nvec/nvec_kbd.c                    |    6 +-
+ drivers/staging/nvec/nvec_paz00.c                  |    6 +-
+ drivers/staging/nvec/nvec_power.c                  |    6 +-
+ drivers/staging/nvec/nvec_ps2.c                    |    6 +-
+ drivers/staging/octeon/ethernet.c                  |   12 +-
+ drivers/staging/olpc_dcon/olpc_dcon.c              |   85 +-
+ drivers/staging/olpc_dcon/olpc_dcon.h              |    2 +-
+ drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c       |   30 -
+ drivers/staging/omap-thermal/omap-bandgap.c        |   67 +-
+ drivers/staging/omap-thermal/omap-bandgap.h        |    9 -
+ drivers/staging/omap-thermal/omap-thermal-common.c |   69 +-
+ drivers/staging/omapdrm/Kconfig                    |    2 +-
+ drivers/staging/omapdrm/omap_connector.c           |    8 +-
+ drivers/staging/omapdrm/omap_crtc.c                |    8 +-
+ drivers/staging/omapdrm/omap_dmm_priv.h            |    9 +-
+ drivers/staging/omapdrm/omap_dmm_tiler.c           |  108 +-
+ drivers/staging/omapdrm/omap_dmm_tiler.h           |    8 +-
+ drivers/staging/omapdrm/omap_drv.c                 |   73 +-
+ drivers/staging/omapdrm/omap_drv.h                 |   14 +-
+ drivers/staging/omapdrm/omap_encoder.c             |    7 +-
+ drivers/staging/omapdrm/omap_fb.c                  |   25 +-
+ drivers/staging/omapdrm/omap_gem.c                 |   46 +-
+ drivers/staging/omapdrm/omap_gem_dmabuf.c          |    4 +-
+ drivers/staging/omapdrm/omap_gem_helpers.c         |    6 +-
+ drivers/staging/omapdrm/omap_plane.c               |   42 +-
+ drivers/staging/ozwpan/ozevent.c                   |    2 +-
+ drivers/staging/ozwpan/ozhcd.c                     |    7 +-
+ drivers/staging/ozwpan/ozpd.c                      |    6 +-
+ drivers/staging/ozwpan/ozproto.c                   |    3 +-
+ drivers/staging/rtl8187se/ieee80211/ieee80211.h    |    6 +-
+ .../staging/rtl8187se/ieee80211/ieee80211_crypt.c  |   24 +-
+ .../staging/rtl8187se/ieee80211/ieee80211_crypt.h  |    2 +-
+ .../rtl8187se/ieee80211/ieee80211_crypt_ccmp.c     |   38 +-
+ .../rtl8187se/ieee80211/ieee80211_crypt_wep.c      |   18 +-
+ .../staging/rtl8187se/ieee80211/ieee80211_module.c |   23 +-
+ drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c |  321 +-
+ .../rtl8187se/ieee80211/ieee80211_softmac_wx.c     |  121 +-
+ drivers/staging/rtl8187se/r8180.h                  |   28 -
+ drivers/staging/rtl8187se/r8180_core.c             |  496 +-
+ drivers/staging/rtl8187se/r8180_dm.h               |    4 +-
+ drivers/staging/rtl8187se/r8180_rtl8225.h          |    4 +-
+ drivers/staging/rtl8187se/r8180_rtl8225z2.c        |  229 +-
+ drivers/staging/rtl8187se/r8180_wx.c               |    2 -
+ drivers/staging/rtl8187se/r8185b_init.c            |  239 +-
+ drivers/staging/rtl8192e/rtl8192e/rtl_core.c       |   15 +-
+ drivers/staging/rtl8192e/rtllib.h                  |    6 +-
+ drivers/staging/rtl8192e/rtllib_tx.c               |    2 +-
+ drivers/staging/rtl8192u/ieee80211/ieee80211.h     |    5 +-
+ drivers/staging/rtl8192u/r8192U_core.c             |    8 +-
+ drivers/staging/rtl8712/mlme_linux.c               |    2 +-
+ drivers/staging/rtl8712/rtl871x_cmd.c              |    4 +-
+ drivers/staging/rtl8712/rtl871x_ioctl_linux.c      |    4 +-
+ drivers/staging/rts5139/Makefile                   |   22 +-
+ drivers/staging/rts5139/ms.c                       |   96 +-
+ drivers/staging/rts5139/ms.h                       |   18 +-
+ drivers/staging/rts5139/ms_mg.c                    |  104 +-
+ drivers/staging/rts5139/ms_mg.h                    |   14 +-
+ drivers/staging/rts5139/rts51x.c                   |   10 +-
+ drivers/staging/rts5139/rts51x_card.c              |   80 +-
+ drivers/staging/rts5139/rts51x_card.h              |   30 +-
+ drivers/staging/rts5139/rts51x_chip.c              |   24 +-
+ drivers/staging/rts5139/rts51x_chip.h              |   16 +-
+ drivers/staging/rts5139/rts51x_fop.c               |    6 +-
+ drivers/staging/rts5139/rts51x_scsi.c              |  238 +-
+ drivers/staging/rts5139/rts51x_scsi.h              |    6 +-
+ drivers/staging/rts5139/sd.c                       |   36 +-
+ drivers/staging/rts5139/sd.h                       |   12 +-
+ drivers/staging/rts5139/sd_cprm.c                  |  124 +-
+ drivers/staging/rts5139/sd_cprm.h                  |   18 +-
+ drivers/staging/rts5139/xd.c                       |   58 +-
+ drivers/staging/rts5139/xd.h                       |   10 +-
+ drivers/staging/rts_pstor/Kconfig                  |   16 -
+ drivers/staging/rts_pstor/Makefile                 |   16 -
+ drivers/staging/rts_pstor/TODO                     |    9 -
+ drivers/staging/rts_pstor/debug.h                  |   43 -
+ drivers/staging/rts_pstor/general.c                |   35 -
+ drivers/staging/rts_pstor/general.h                |   31 -
+ drivers/staging/rts_pstor/ms.c                     | 4051 --------
+ drivers/staging/rts_pstor/ms.h                     |  225 -
+ drivers/staging/rts_pstor/rtsx.c                   | 1105 --
+ drivers/staging/rts_pstor/rtsx.h                   |  186 -
+ drivers/staging/rts_pstor/rtsx_card.c              | 1233 ---
+ drivers/staging/rts_pstor/rtsx_card.h              | 1093 --
+ drivers/staging/rts_pstor/rtsx_chip.c              | 2264 -----
+ drivers/staging/rts_pstor/rtsx_chip.h              |  989 --
+ drivers/staging/rts_pstor/rtsx_scsi.c              | 3137 ------
+ drivers/staging/rts_pstor/rtsx_scsi.h              |  142 -
+ drivers/staging/rts_pstor/rtsx_sys.h               |   50 -
+ drivers/staging/rts_pstor/rtsx_transport.c         |  769 --
+ drivers/staging/rts_pstor/rtsx_transport.h         |   66 -
+ drivers/staging/rts_pstor/sd.c                     | 4570 ---------
+ drivers/staging/rts_pstor/sd.h                     |  300 -
+ drivers/staging/rts_pstor/spi.c                    |  812 --
+ drivers/staging/rts_pstor/spi.h                    |   65 -
+ drivers/staging/rts_pstor/trace.h                  |   93 -
+ drivers/staging/rts_pstor/xd.c                     | 2052 ----
+ drivers/staging/rts_pstor/xd.h                     |  188 -
+ drivers/staging/sbe-2t3e3/cpld.c                   |    2 +-
+ drivers/staging/sbe-2t3e3/main.c                   |    7 +-
+ drivers/staging/sbe-2t3e3/module.c                 |   19 +-
+ drivers/staging/sbe-2t3e3/netdev.c                 |    5 +-
+ drivers/staging/sep/sep_main.c                     |    6 +-
+ drivers/staging/serqt_usb2/serqt_usb2.c            |  287 +-
+ drivers/staging/silicom/bp_mod.c                   |  219 +-
+ drivers/staging/silicom/bp_proc.c                  |   85 +-
+ drivers/staging/silicom/bypasslib/bplibk.h         |    9 -
+ drivers/staging/silicom/bypasslib/bypass.c         |    1 -
+ drivers/staging/slicoss/slicoss.c                  |  166 +-
+ drivers/staging/sm7xxfb/sm7xxfb.c                  |    6 +-
+ drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c      |  106 +-
+ drivers/staging/telephony/Kconfig                  |   47 -
+ drivers/staging/telephony/Makefile                 |    7 -
+ drivers/staging/telephony/TODO                     |   10 -
+ drivers/staging/telephony/ixj-ver.h                |    4 -
+ drivers/staging/telephony/ixj.c                    |10571 --------------------
+ drivers/staging/telephony/ixj.h                    | 1322 ---
+ drivers/staging/telephony/ixj_pcmcia.c             |  187 -
+ drivers/staging/telephony/phonedev.c               |  166 -
+ .../staging/tidspbridge/dynload/dload_internal.h   |    8 +-
+ drivers/staging/tidspbridge/dynload/reloc.c        |    6 +-
+ drivers/staging/tidspbridge/rmgr/drv_interface.c   |    6 +-
+ drivers/staging/usbip/stub_dev.c                   |   15 +-
+ drivers/staging/usbip/stub_rx.c                    |    5 +-
+ drivers/staging/usbip/stub_tx.c                    |    3 +-
+ drivers/staging/usbip/usbip_common.c               |   40 +-
+ drivers/staging/usbip/usbip_common.h               |    4 +-
+ drivers/staging/usbip/userspace/src/usbip_detach.c |    9 +
+ drivers/staging/usbip/vhci.h                       |    1 -
+ drivers/staging/usbip/vhci_hcd.c                   |   51 +-
+ drivers/staging/usbip/vhci_rx.c                    |    2 +-
+ drivers/staging/usbip/vhci_sysfs.c                 |    6 +-
+ drivers/staging/usbip/vhci_tx.c                    |    2 +-
+ drivers/staging/vme/devices/vme_pio2.h             |    2 +-
+ drivers/staging/vme/devices/vme_pio2_core.c        |   10 +-
+ drivers/staging/vme/devices/vme_pio2_gpio.c        |    2 +-
+ drivers/staging/vme/devices/vme_user.c             |   83 +-
+ drivers/staging/vt6655/device_main.c               |    6 +-
+ drivers/staging/vt6655/hostap.c                    |    6 +-
+ drivers/staging/vt6655/rxtx.c                      |    2 +-
+ drivers/staging/vt6655/wcmd.c                      |    1 +
+ drivers/staging/vt6656/80211mgr.c                  |    2 +-
+ drivers/staging/vt6656/Makefile                    |    1 -
+ drivers/staging/vt6656/bssdb.c                     |   43 -
+ drivers/staging/vt6656/desc.h                      |   28 +-
+ drivers/staging/vt6656/device.h                    |   48 +-
+ drivers/staging/vt6656/dpc.c                       |   64 +-
+ drivers/staging/vt6656/firmware.c                  |   22 +-
+ drivers/staging/vt6656/hostap.c                    |    6 +-
+ drivers/staging/vt6656/int.h                       |    4 +-
+ drivers/staging/vt6656/ioctl.c                     |  648 --
+ drivers/staging/vt6656/ioctl.h                     |   54 -
+ drivers/staging/vt6656/iwctl.c                     |  510 +-
+ drivers/staging/vt6656/iwctl.h                     |   79 +-
+ drivers/staging/vt6656/key.c                       |   55 +-
+ drivers/staging/vt6656/key.h                       |    8 +-
+ drivers/staging/vt6656/mac.c                       |    6 +-
+ drivers/staging/vt6656/main_usb.c                  |  552 +-
+ drivers/staging/vt6656/mib.c                       |    1 -
+ drivers/staging/vt6656/mib.h                       |    1 -
+ drivers/staging/vt6656/rf.c                        |    3 +
+ drivers/staging/vt6656/rxtx.c                      |   36 +-
+ drivers/staging/vt6656/rxtx.h                      |    8 +-
+ drivers/staging/vt6656/tkip.c                      |   40 +-
+ drivers/staging/vt6656/ttype.h                     |   16 +-
+ drivers/staging/vt6656/upc.h                       |  162 -
+ drivers/staging/vt6656/usbpipe.c                   |    4 +-
+ drivers/staging/vt6656/wcmd.c                      |   44 +-
+ drivers/staging/vt6656/wmgr.c                      |   66 -
+ drivers/staging/vt6656/wmgr.h                      |   42 +-
+ drivers/staging/vt6656/wpa2.c                      |    2 +-
+ drivers/staging/vt6656/wpa2.h                      |    4 +-
+ drivers/staging/vt6656/wpactl.c                    |  664 +-
+ drivers/staging/vt6656/wpactl.h                    |   12 +-
+ drivers/staging/winbond/mds.c                      |    7 +-
+ drivers/staging/winbond/wb35rx_f.h                 |   12 +-
+ drivers/staging/winbond/wb35rx_s.h                 |   62 +-
+ drivers/staging/winbond/wbhal.h                    |    4 +-
+ drivers/staging/winbond/wbusb.c                    |   14 -
+ drivers/staging/wlags49_h2/ap_h2.c                 |   16 +-
+ drivers/staging/wlags49_h2/man/wlags49.4           |    2 +-
+ drivers/staging/wlags49_h2/wl_if.h                 |  133 +-
+ drivers/staging/wlags49_h2/wl_pci.c                |   25 +-
+ drivers/staging/wlan-ng/hfa384x_usb.c              |    6 +-
+ drivers/staging/xgifb/TODO                         |    2 +-
+ drivers/staging/xgifb/XGI_main_26.c                |   60 +-
+ drivers/staging/xgifb/vb_def.h                     |    9 +-
+ drivers/staging/xgifb/vb_init.c                    |   47 +-
+ drivers/staging/xgifb/vb_init.h                    |    1 -
+ drivers/staging/xgifb/vb_setmode.c                 |  898 +-
+ drivers/staging/xgifb/vb_struct.h                  |   36 +-
+ drivers/staging/xgifb/vb_table.h                   |  504 +-
+ drivers/staging/zram/zram_drv.c                    |  113 +-
+ drivers/staging/zram/zram_drv.h                    |    4 +-
+ drivers/staging/zram/zram_sysfs.c                  |    8 +-
+ drivers/vme/boards/vme_vmivme7805.c                |   15 +-
+ drivers/vme/bridges/vme_ca91cx42.c                 |   15 +-
+ drivers/vme/bridges/vme_tsi148.c                   |   15 +-
+ include/linux/iio/buffer.h                         |   26 +-
+ include/linux/iio/consumer.h                       |   50 +
+ include/linux/iio/iio.h                            |    5 +
+ include/linux/iio/imu/adis.h                       |  280 +
+ include/linux/iio/machine.h                        |    2 +
+ include/linux/iio/types.h                          |    2 +
+ {drivers/staging/ipack => include/linux}/ipack.h   |  100 +-
+ include/linux/platform_data/ad5449.h               |   40 +
+ include/linux/platform_data/ad7298.h               |   20 +
+ include/linux/platform_data/ad7887.h               |   26 +
+ include/linux/platform_data/omap_drm.h             |    1 +
+ 757 files changed, 27181 insertions(+), 81662 deletions(-)
+ delete mode 100644 Documentation/telephony/00-INDEX
+ delete mode 100644 Documentation/telephony/ixj.txt
+ rename drivers/{staging/iio/adc/ad7298_core.c => iio/adc/ad7298.c} (55%)
+ rename drivers/{staging/iio/adc/ad7887_core.c => iio/adc/ad7887.c} (50%)
+ rename drivers/{staging/iio/adc/max1363_core.c => iio/adc/max1363.c} (81%)
+ create mode 100644 drivers/iio/buffer_cb.c
+ create mode 100644 drivers/iio/dac/ad5449.c
+ create mode 100644 drivers/iio/gyro/adis16136.c
+ create mode 100644 drivers/iio/imu/Kconfig
+ create mode 100644 drivers/iio/imu/Makefile
+ create mode 100644 drivers/iio/imu/adis.c
+ create mode 100644 drivers/iio/imu/adis16480.c
+ create mode 100644 drivers/iio/imu/adis_buffer.c
+ create mode 100644 drivers/iio/imu/adis_trigger.c
+ create mode 100644 drivers/ipack/Kconfig
+ rename drivers/{staging => }/ipack/Makefile (83%)
+ create mode 100644 drivers/ipack/carriers/Kconfig
+ rename drivers/{staging/ipack/bridges => ipack/carriers}/Makefile (100%)
+ rename drivers/{staging/ipack/bridges => ipack/carriers}/tpci200.c (66%)
+ rename drivers/{staging/ipack/bridges => ipack/carriers}/tpci200.h (85%)
+ rename drivers/{staging => }/ipack/devices/Kconfig (99%)
+ rename drivers/{staging => }/ipack/devices/Makefile (100%)
+ rename drivers/{staging => }/ipack/devices/ipoctal.c (86%)
+ rename drivers/{staging => }/ipack/devices/ipoctal.h (82%)
+ rename drivers/{staging => }/ipack/devices/scc2698.h (97%)
+ rename drivers/{staging => }/ipack/ipack.c (90%)
+ create mode 100644 drivers/staging/android/binder_trace.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi_apci_2016.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi_apci_3001.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi_apci_3300.c
+ delete mode 100644 drivers/staging/comedi/drivers/mpc8260cpm.c
+ delete mode 100644 drivers/staging/csr/csr_lib.h
+ delete mode 100644 drivers/staging/csr/csr_panic.c
+ delete mode 100644 drivers/staging/csr/csr_panic.h
+ delete mode 100644 drivers/staging/iio/accel/adis16201_ring.c
+ delete mode 100644 drivers/staging/iio/accel/adis16201_trigger.c
+ delete mode 100644 drivers/staging/iio/accel/adis16203_ring.c
+ delete mode 100644 drivers/staging/iio/accel/adis16203_trigger.c
+ delete mode 100644 drivers/staging/iio/accel/adis16204_ring.c
+ delete mode 100644 drivers/staging/iio/accel/adis16204_trigger.c
+ delete mode 100644 drivers/staging/iio/accel/adis16209_ring.c
+ delete mode 100644 drivers/staging/iio/accel/adis16209_trigger.c
+ delete mode 100644 drivers/staging/iio/accel/adis16240_ring.c
+ delete mode 100644 drivers/staging/iio/accel/adis16240_trigger.c
+ delete mode 100644 drivers/staging/iio/adc/ad7298.h
+ delete mode 100644 drivers/staging/iio/adc/ad7298_ring.c
+ delete mode 100644 drivers/staging/iio/adc/ad7887.h
+ delete mode 100644 drivers/staging/iio/adc/ad7887_ring.c
+ delete mode 100644 drivers/staging/iio/adc/adt7310.c
+ delete mode 100644 drivers/staging/iio/adc/max1363.h
+ delete mode 100644 drivers/staging/iio/adc/max1363_ring.c
+ delete mode 100644 drivers/staging/iio/gyro/adis16260_ring.c
+ delete mode 100644 drivers/staging/iio/gyro/adis16260_trigger.c
+ delete mode 100644 drivers/staging/ipack/Kconfig
+ delete mode 100644 drivers/staging/ipack/TODO
+ delete mode 100644 drivers/staging/ipack/bridges/Kconfig
+ delete mode 100644 drivers/staging/ipack/ipack_ids.h
+ delete mode 100644 drivers/staging/line6/control.c
+ delete mode 100644 drivers/staging/line6/control.h
+ delete mode 100644 drivers/staging/line6/dumprequest.c
+ delete mode 100644 drivers/staging/line6/dumprequest.h
+ delete mode 100644 drivers/staging/rts_pstor/Kconfig
+ delete mode 100644 drivers/staging/rts_pstor/Makefile
+ delete mode 100644 drivers/staging/rts_pstor/TODO
+ delete mode 100644 drivers/staging/rts_pstor/debug.h
+ delete mode 100644 drivers/staging/rts_pstor/general.c
+ delete mode 100644 drivers/staging/rts_pstor/general.h
+ delete mode 100644 drivers/staging/rts_pstor/ms.c
+ delete mode 100644 drivers/staging/rts_pstor/ms.h
+ delete mode 100644 drivers/staging/rts_pstor/rtsx.c
+ delete mode 100644 drivers/staging/rts_pstor/rtsx.h
+ delete mode 100644 drivers/staging/rts_pstor/rtsx_card.c
+ delete mode 100644 drivers/staging/rts_pstor/rtsx_card.h
+ delete mode 100644 drivers/staging/rts_pstor/rtsx_chip.c
+ delete mode 100644 drivers/staging/rts_pstor/rtsx_chip.h
+ delete mode 100644 drivers/staging/rts_pstor/rtsx_scsi.c
+ delete mode 100644 drivers/staging/rts_pstor/rtsx_scsi.h
+ delete mode 100644 drivers/staging/rts_pstor/rtsx_sys.h
+ delete mode 100644 drivers/staging/rts_pstor/rtsx_transport.c
+ delete mode 100644 drivers/staging/rts_pstor/rtsx_transport.h
+ delete mode 100644 drivers/staging/rts_pstor/sd.c
+ delete mode 100644 drivers/staging/rts_pstor/sd.h
+ delete mode 100644 drivers/staging/rts_pstor/spi.c
+ delete mode 100644 drivers/staging/rts_pstor/spi.h
+ delete mode 100644 drivers/staging/rts_pstor/trace.h
+ delete mode 100644 drivers/staging/rts_pstor/xd.c
+ delete mode 100644 drivers/staging/rts_pstor/xd.h
+ delete mode 100644 drivers/staging/telephony/Kconfig
+ delete mode 100644 drivers/staging/telephony/Makefile
+ delete mode 100644 drivers/staging/telephony/TODO
+ delete mode 100644 drivers/staging/telephony/ixj-ver.h
+ delete mode 100644 drivers/staging/telephony/ixj.c
+ delete mode 100644 drivers/staging/telephony/ixj.h
+ delete mode 100644 drivers/staging/telephony/ixj_pcmcia.c
+ delete mode 100644 drivers/staging/telephony/phonedev.c
+ delete mode 100644 drivers/staging/vt6656/ioctl.c
+ delete mode 100644 drivers/staging/vt6656/ioctl.h
+ delete mode 100644 drivers/staging/vt6656/upc.h
+ create mode 100644 include/linux/iio/imu/adis.h
+ rename {drivers/staging/ipack => include/linux}/ipack.h (66%)
+ create mode 100644 include/linux/platform_data/ad5449.h
+ create mode 100644 include/linux/platform_data/ad7298.h
+ create mode 100644 include/linux/platform_data/ad7887.h
+Merging char-misc/char-misc-next (962b686 Merge tag 'pull_req_20121122' of git://git.kernel.org/pub/scm/linux/kernel/git/mzx/extcon into char-misc-next)
+$ git merge char-misc/char-misc-next
+Resolved 'drivers/mfd/rtsx_pcr.c' using previous resolution.
+Resolved 'drivers/misc/atmel-ssc.c' using previous resolution.
+Resolved 'drivers/mmc/host/Kconfig' using previous resolution.
+Resolved 'drivers/mmc/host/rtsx_pci_sdmmc.c' using previous resolution.
+Auto-merging drivers/mmc/host/rtsx_pci_sdmmc.c
+CONFLICT (add/add): Merge conflict in drivers/mmc/host/rtsx_pci_sdmmc.c
+Auto-merging drivers/mmc/host/Makefile
+Auto-merging drivers/mmc/host/Kconfig
+CONFLICT (content): Merge conflict in drivers/mmc/host/Kconfig
+Auto-merging drivers/misc/pti.c
+Auto-merging drivers/misc/atmel-ssc.c
+CONFLICT (content): Merge conflict in drivers/misc/atmel-ssc.c
+Auto-merging drivers/mfd/rtsx_pcr.c
+CONFLICT (add/add): Merge conflict in drivers/mfd/rtsx_pcr.c
+Auto-merging drivers/char/virtio_console.c
+Auto-merging drivers/char/tpm/tpm_tis.c
+Auto-merging drivers/char/tpm/tpm_infineon.c
+Auto-merging drivers/char/tpm/tpm_ibmvtpm.c
+Auto-merging drivers/char/tpm/tpm_i2c_infineon.c
+Auto-merging drivers/char/ipmi/ipmi_si_intf.c
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 24341ab] Merge remote-tracking branch 'char-misc/char-misc-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/DocBook/uio-howto.tmpl          |   56 ++
+ MAINTAINERS                                   |    1 -
+ arch/arm/include/asm/io.h                     |    2 +-
+ arch/arm/mm/mmap.c                            |    2 +-
+ arch/ia64/include/asm/io.h                    |    2 +-
+ arch/ia64/kernel/efi.c                        |    2 +-
+ arch/sh/include/asm/io.h                      |    2 +-
+ arch/sh/mm/mmap.c                             |    2 +-
+ drivers/char/agp/ali-agp.c                    |    4 +-
+ drivers/char/agp/amd-k7-agp.c                 |    4 +-
+ drivers/char/agp/amd64-agp.c                  |    2 +-
+ drivers/char/agp/ati-agp.c                    |    4 +-
+ drivers/char/agp/efficeon-agp.c               |    2 +-
+ drivers/char/agp/i460-agp.c                   |    2 +-
+ drivers/char/agp/intel-agp.c                  |    2 +-
+ drivers/char/agp/nvidia-agp.c                 |    2 +-
+ drivers/char/agp/sgi-agp.c                    |    2 +-
+ drivers/char/agp/sis-agp.c                    |    8 +-
+ drivers/char/agp/sworks-agp.c                 |    2 +-
+ drivers/char/agp/uninorth-agp.c               |    4 +-
+ drivers/char/agp/via-agp.c                    |    4 +-
+ drivers/char/hpet.c                           |    5 +-
+ drivers/char/hw_random/atmel-rng.c            |    2 +-
+ drivers/char/hw_random/bcm63xx-rng.c          |    2 +-
+ drivers/char/hw_random/exynos-rng.c           |    2 +-
+ drivers/char/hw_random/n2-drv.c               |    4 +-
+ drivers/char/hw_random/pasemi-rng.c           |    2 +-
+ drivers/char/hw_random/picoxcell-rng.c        |    2 +-
+ drivers/char/hw_random/ppc4xx-rng.c           |    2 +-
+ drivers/char/hw_random/timeriomem-rng.c       |    2 +-
+ drivers/char/hw_random/virtio-rng.c           |    2 +-
+ drivers/char/ipmi/ipmi_si_intf.c              |   32 +-
+ drivers/char/mbcs.c                           |    2 +-
+ drivers/char/mem.c                            |   10 +-
+ drivers/char/pc8736x_gpio.c                   |    3 +-
+ drivers/char/ps3flash.c                       |    2 +-
+ drivers/char/sonypi.c                         |   14 +-
+ drivers/char/tb0219.c                         |    6 +-
+ drivers/char/tpm/tpm_i2c_infineon.c           |    2 +-
+ drivers/char/tpm/tpm_ibmvtpm.c                |    4 +-
+ drivers/char/tpm/tpm_infineon.c               |    2 +-
+ drivers/char/tpm/tpm_tis.c                    |    4 +-
+ drivers/char/virtio_console.c                 |    2 +-
+ drivers/char/xilinx_hwicap/xilinx_hwicap.c    |   14 +-
+ drivers/extcon/extcon-adc-jack.c              |    6 +-
+ drivers/extcon/extcon-arizona.c               |    7 +-
+ drivers/extcon/extcon-class.c                 |    2 +-
+ drivers/extcon/extcon-gpio.c                  |    6 +-
+ drivers/extcon/extcon-max77693.c              |   42 +-
+ drivers/extcon/extcon-max8997.c               |   34 +-
+ drivers/hv/Kconfig                            |    6 +
+ drivers/hv/Makefile                           |    1 +
+ drivers/hv/channel.c                          |    8 -
+ drivers/hv/channel_mgmt.c                     |    8 -
+ drivers/hv/hv_balloon.c                       | 1041 +++++++++++++++++++++++++
+ drivers/misc/ad525x_dpot-i2c.c                |    6 +-
+ drivers/misc/ad525x_dpot-spi.c                |    6 +-
+ drivers/misc/ad525x_dpot.c                    |    4 +-
+ drivers/misc/apds9802als.c                    |    6 +-
+ drivers/misc/apds990x.c                       |    6 +-
+ drivers/misc/atmel-ssc.c                      |    4 +-
+ drivers/misc/bh1770glc.c                      |    6 +-
+ drivers/misc/bh1780gli.c                      |    6 +-
+ drivers/misc/bmp085-i2c.c                     |    4 +-
+ drivers/misc/bmp085-spi.c                     |    4 +-
+ drivers/misc/bmp085.c                         |    2 +-
+ drivers/misc/cb710/core.c                     |   10 +-
+ drivers/misc/cs5535-mfgpt.c                   |    6 +-
+ drivers/misc/eeprom/at24.c                    |    4 +-
+ drivers/misc/eeprom/at25.c                    |    4 +-
+ drivers/misc/eeprom/eeprom_93xx46.c           |    6 +-
+ drivers/misc/fsa9480.c                        |    6 +-
+ drivers/misc/hpilo.c                          |   21 +-
+ drivers/misc/ibmasm/module.c                  |    6 +-
+ drivers/misc/ioc4.c                           |   10 +-
+ drivers/misc/isl29003.c                       |    6 +-
+ drivers/misc/lis3lv02d/lis3lv02d_i2c.c        |    6 +-
+ drivers/misc/lis3lv02d/lis3lv02d_spi.c        |    6 +-
+ drivers/misc/mei/Makefile                     |    1 +
+ drivers/misc/mei/amthif.c                     |  722 +++++++++++++++++
+ drivers/misc/mei/hw.h                         |   36 +-
+ drivers/misc/mei/init.c                       |  368 ++++-----
+ drivers/misc/mei/interface.c                  |   91 +--
+ drivers/misc/mei/interrupt.c                  |  760 ++++++------------
+ drivers/misc/mei/iorw.c                       |  455 +++--------
+ drivers/misc/mei/main.c                       |  462 ++++-------
+ drivers/misc/mei/mei_dev.h                    |  155 +++-
+ drivers/misc/mei/wd.c                         |   15 +-
+ drivers/misc/pch_phub.c                       |    6 +-
+ drivers/misc/phantom.c                        |   10 +-
+ drivers/misc/pti.c                            |    8 +-
+ drivers/misc/spear13xx_pcie_gadget.c          |    4 +-
+ drivers/misc/ti-st/st_core.c                  |    1 -
+ drivers/misc/ti-st/st_kim.c                   |   30 +-
+ drivers/misc/ti_dac7512.c                     |    6 +-
+ drivers/misc/tsl2550.c                        |    6 +-
+ drivers/mmc/host/Makefile                     |    2 +
+ drivers/parport/Kconfig                       |   16 +-
+ drivers/uio/Kconfig                           |   16 +
+ drivers/uio/Makefile                          |    1 +
+ drivers/uio/uio_aec.c                         |    2 +-
+ drivers/uio/uio_cif.c                         |    4 +-
+ drivers/uio/uio_dmem_genirq.c                 |  359 +++++++++
+ drivers/uio/uio_netx.c                        |    2 +-
+ drivers/uio/uio_pci_generic.c                 |    2 +-
+ drivers/uio/uio_pdrv.c                        |    1 +
+ drivers/uio/uio_pdrv_genirq.c                 |    3 +-
+ drivers/uio/uio_pruss.c                       |    6 +-
+ drivers/uio/uio_sercos3.c                     |    4 +-
+ drivers/w1/masters/Kconfig                    |    2 +-
+ drivers/w1/masters/ds2482.c                   |   13 +-
+ drivers/w1/masters/matrox_w1.c                |   10 +-
+ drivers/w1/masters/mxc_w1.c                   |   28 +-
+ drivers/w1/masters/omap_hdq.c                 |   10 +-
+ drivers/w1/masters/w1-gpio.c                  |   65 +-
+ drivers/w1/w1.c                               |    7 -
+ drivers/xen/xen-selfballoon.c                 |    2 +-
+ include/linux/extcon.h                        |   50 +-
+ include/linux/mman.h                          |    2 +
+ include/linux/platform_data/uio_dmem_genirq.h |   26 +
+ mm/mmap.c                                     |   14 +
+ mm/nommu.c                                    |   15 +
+ tools/hv/hv_kvp_daemon.c                      |   40 +-
+ 123 files changed, 3449 insertions(+), 1928 deletions(-)
+ create mode 100644 drivers/hv/hv_balloon.c
+ create mode 100644 drivers/misc/mei/amthif.c
+ create mode 100644 drivers/uio/uio_dmem_genirq.c
+ create mode 100644 include/linux/platform_data/uio_dmem_genirq.h
+Merging tmem/linux-next (8f0d816 Linux 3.7-rc3)
+$ git merge tmem/linux-next
+Already up-to-date.
+Merging writeback/writeback-for-next (2f60d62 CPU hotplug, writeback: Don't call writeback_set_ratelimit() too often during hotplug)
+$ git merge writeback/writeback-for-next
+Already up-to-date.
+Merging arm-dt/devicetree/arm-next (ede338f dt: add documentation of ARM dt boot interface)
+$ git merge arm-dt/devicetree/arm-next
+Already up-to-date.
+Merging hwspinlock/linux-next (8b37fcf hwspinlock: add MAINTAINERS entries)
+$ git merge hwspinlock/linux-next
+Already up-to-date.
+Merging pinctrl/for-next (e7125b5 Merge branch 'devel' into for-next)
+$ git merge pinctrl/for-next
+Resolved 'arch/arm/boot/dts/at91sam9260.dtsi' using previous resolution.
+Resolved 'arch/arm/boot/dts/at91sam9g20ek_common.dtsi' using previous resolution.
+Resolved 'arch/arm/boot/dts/spear1340.dtsi' using previous resolution.
+Auto-merging include/linux/platform_data/pinctrl-nomadik.h
+Auto-merging drivers/tty/serial/atmel_serial.c
+Auto-merging drivers/pinctrl/spear/pinctrl-spear320.c
+Auto-merging drivers/pinctrl/spear/pinctrl-spear310.c
+Auto-merging drivers/pinctrl/spear/pinctrl-spear300.c
+Auto-merging drivers/pinctrl/spear/pinctrl-spear1340.c
+Auto-merging drivers/pinctrl/spear/pinctrl-spear1310.c
+Auto-merging drivers/pinctrl/spear/pinctrl-spear.h
+Auto-merging drivers/pinctrl/spear/pinctrl-spear.c
+Auto-merging drivers/pinctrl/pinctrl-u300.c
+Auto-merging drivers/pinctrl/pinctrl-tegra.c
+Auto-merging drivers/pinctrl/pinctrl-sirf.c
+Auto-merging drivers/pinctrl/pinctrl-single.c
+Auto-merging drivers/pinctrl/pinctrl-mxs.c
+Auto-merging drivers/pinctrl/pinctrl-imx.c
+Auto-merging drivers/pinctrl/pinctrl-bcm2835.c
+Auto-merging drivers/pinctrl/mvebu/pinctrl-mvebu.c
+Auto-merging drivers/mtd/nand/atmel_nand.c
+Removing arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
+Auto-merging arch/arm/mach-ux500/board-mop500.c
+Auto-merging arch/arm/mach-u300/core.c
+Auto-merging arch/arm/mach-nomadik/board-nhk8815.c
+Auto-merging arch/arm/mach-at91/at91sam9x5.c
+Auto-merging arch/arm/mach-at91/at91sam9rl.c
+Auto-merging arch/arm/mach-at91/at91sam9g45.c
+Auto-merging arch/arm/mach-at91/at91sam9263.c
+Auto-merging arch/arm/mach-at91/at91sam9261.c
+Auto-merging arch/arm/mach-at91/at91sam9260.c
+Auto-merging arch/arm/mach-at91/at91rm9200.c
+Auto-merging arch/arm/mach-at91/Kconfig
+Auto-merging arch/arm/boot/dts/spear320.dtsi
+Auto-merging arch/arm/boot/dts/spear310.dtsi
+Auto-merging arch/arm/boot/dts/spear1340.dtsi
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/spear1340.dtsi
+Auto-merging arch/arm/boot/dts/at91sam9x5.dtsi
+Auto-merging arch/arm/boot/dts/at91sam9g45.dtsi
+Auto-merging arch/arm/boot/dts/at91sam9g20ek_common.dtsi
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/at91sam9g20ek_common.dtsi
+Auto-merging arch/arm/boot/dts/at91sam9263.dtsi
+Auto-merging arch/arm/boot/dts/at91sam9260.dtsi
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/at91sam9260.dtsi
+Auto-merging arch/arm/boot/dts/Makefile
+Auto-merging arch/arm/Kconfig
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 9d6a8e9] Merge remote-tracking branch 'pinctrl/for-next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/arm/atmel-at91.txt         |    6 +
+ Documentation/devicetree/bindings/gpio/gpio.txt    |   36 +
+ .../devicetree/bindings/gpio/gpio_atmel.txt        |    5 +
+ .../bindings/pinctrl/atmel,at91-pinctrl.txt        |  141 ++
+ Documentation/gpio.txt                             |   42 +
+ Documentation/pinctrl.txt                          |    7 +-
+ MAINTAINERS                                        |    6 +
+ arch/arm/Kconfig                                   |    2 +
+ arch/arm/boot/dts/Makefile                         |   48 +-
+ arch/arm/boot/dts/animeo_ip.dts                    |  178 +++
+ arch/arm/boot/dts/at91rm9200.dtsi                  |  349 +++++
+ arch/arm/boot/dts/at91rm9200ek.dts                 |   79 +
+ arch/arm/boot/dts/at91sam9260.dtsi                 |  295 +++-
+ arch/arm/boot/dts/at91sam9263.dtsi                 |  299 +++-
+ arch/arm/boot/dts/at91sam9263ek.dts                |   29 +
+ arch/arm/boot/dts/at91sam9g15.dtsi                 |   28 +
+ arch/arm/boot/dts/at91sam9g15ek.dts                |   16 +
+ arch/arm/boot/dts/at91sam9g20ek_2mmc.dts           |   26 +
+ arch/arm/boot/dts/at91sam9g20ek_common.dtsi        |   30 +
+ arch/arm/boot/dts/at91sam9g25.dtsi                 |   28 +
+ arch/arm/boot/dts/at91sam9g25ek.dts                |   49 +-
+ arch/arm/boot/dts/at91sam9g35.dtsi                 |   28 +
+ arch/arm/boot/dts/at91sam9g35ek.dts                |   16 +
+ arch/arm/boot/dts/at91sam9g45.dtsi                 |  301 +++-
+ arch/arm/boot/dts/at91sam9m10g45ek.dts             |   48 +
+ arch/arm/boot/dts/at91sam9n12.dtsi                 |  225 ++-
+ arch/arm/boot/dts/at91sam9n12ek.dts                |   22 +
+ arch/arm/boot/dts/at91sam9x25.dtsi                 |   49 +
+ arch/arm/boot/dts/at91sam9x25ek.dts                |   16 +
+ arch/arm/boot/dts/at91sam9x35.dtsi                 |   28 +
+ arch/arm/boot/dts/at91sam9x35ek.dts                |   16 +
+ arch/arm/boot/dts/at91sam9x5.dtsi                  |  270 +++-
+ arch/arm/boot/dts/at91sam9x5ek.dtsi                |  101 ++
+ arch/arm/boot/dts/pm9g45.dts                       |  165 ++
+ arch/arm/boot/dts/spear1310-evb.dts                |    4 +
+ arch/arm/boot/dts/spear1310.dtsi                   |   27 +
+ arch/arm/boot/dts/spear1340-evb.dts                |    4 +
+ arch/arm/boot/dts/spear1340.dtsi                   |   26 +
+ arch/arm/boot/dts/spear310.dtsi                    |   22 +-
+ arch/arm/boot/dts/spear320-evb.dts                 |    4 +
+ arch/arm/boot/dts/spear320.dtsi                    |   23 +-
+ arch/arm/configs/at91_dt_defconfig                 |    1 +
+ arch/arm/mach-at91/Kconfig                         |    9 +
+ arch/arm/mach-at91/Makefile                        |    1 +
+ arch/arm/mach-at91/at91rm9200.c                    |   22 +-
+ arch/arm/mach-at91/at91rm9200_time.c               |   63 +-
+ arch/arm/mach-at91/at91sam9260.c                   |    8 +-
+ arch/arm/mach-at91/at91sam9261.c                   |    4 +-
+ arch/arm/mach-at91/at91sam9263.c                   |   11 +-
+ arch/arm/mach-at91/at91sam9g45.c                   |   12 +-
+ arch/arm/mach-at91/at91sam9n12.c                   |   16 +-
+ arch/arm/mach-at91/at91sam9rl.c                    |    4 +-
+ arch/arm/mach-at91/at91sam9x5.c                    |   21 +-
+ arch/arm/mach-at91/board-dt.c                      |    2 -
+ arch/arm/mach-at91/board-rm9200-dt.c               |   57 +
+ arch/arm/mach-at91/generic.h                       |    1 +
+ arch/arm/mach-at91/gpio.c                          |  190 +--
+ arch/arm/mach-at91/setup.c                         |   20 +-
+ arch/arm/mach-at91/soc.h                           |   12 +-
+ arch/arm/mach-nomadik/board-nhk8815.c              |    3 +-
+ arch/arm/mach-nomadik/cpu-8815.c                   |    2 +-
+ arch/arm/mach-nomadik/i2c-8815nhk.c                |    3 +-
+ arch/arm/mach-u300/core.c                          |    5 +-
+ arch/arm/mach-u300/include/mach/irqs.h             |  126 +-
+ arch/arm/mach-ux500/board-mop500-audio.c           |    3 +-
+ arch/arm/mach-ux500/board-mop500-pins.c            |    3 +-
+ arch/arm/mach-ux500/board-mop500.c                 |    2 +-
+ arch/arm/mach-ux500/cpu-db8500.c                   |    6 +-
+ arch/arm/mach-ux500/devices-common.c               |    3 +-
+ arch/arm/mach-ux500/devices-common.h               |    8 +-
+ arch/arm/plat-nomadik/include/plat/gpio-nomadik.h  |  102 --
+ drivers/gpio/gpiolib-of.c                          |   52 +
+ drivers/gpio/gpiolib.c                             |   76 +
+ drivers/mtd/nand/atmel_nand.c                      |    9 +
+ drivers/pinctrl/Kconfig                            |   47 +-
+ drivers/pinctrl/Makefile                           |    7 +-
+ drivers/pinctrl/core.c                             |   58 +
+ drivers/pinctrl/core.h                             |    2 +
+ drivers/pinctrl/devicetree.c                       |   11 +
+ drivers/pinctrl/mvebu/Kconfig                      |   24 +
+ drivers/pinctrl/mvebu/Makefile                     |    5 +
+ drivers/pinctrl/{ => mvebu}/pinctrl-armada-370.c   |    0
+ drivers/pinctrl/{ => mvebu}/pinctrl-armada-xp.c    |    0
+ drivers/pinctrl/{ => mvebu}/pinctrl-dove.c         |    0
+ drivers/pinctrl/{ => mvebu}/pinctrl-kirkwood.c     |    0
+ drivers/pinctrl/{ => mvebu}/pinctrl-mvebu.c        |    1 -
+ drivers/pinctrl/{ => mvebu}/pinctrl-mvebu.h        |    0
+ drivers/pinctrl/pinconf-generic.c                  |    1 +
+ drivers/pinctrl/pinctrl-at91.c                     | 1634 ++++++++++++++++++++
+ drivers/pinctrl/pinctrl-bcm2835.c                  |    2 +-
+ drivers/pinctrl/pinctrl-coh901.c                   |  175 ++-
+ drivers/pinctrl/pinctrl-exynos.c                   |    1 +
+ drivers/pinctrl/pinctrl-falcon.c                   |    2 +-
+ drivers/pinctrl/pinctrl-imx.c                      |    4 +-
+ drivers/pinctrl/pinctrl-lantiq.c                   |   23 +-
+ drivers/pinctrl/pinctrl-mxs.c                      |    2 +-
+ drivers/pinctrl/pinctrl-nomadik-db8500.c           |  125 +-
+ drivers/pinctrl/pinctrl-nomadik-db8540.c           |   16 +-
+ drivers/pinctrl/pinctrl-nomadik.c                  |  152 +-
+ drivers/pinctrl/pinctrl-nomadik.h                  |    2 +-
+ drivers/pinctrl/pinctrl-pxa3xx.c                   |   12 +-
+ drivers/pinctrl/pinctrl-pxa3xx.h                   |    2 -
+ drivers/pinctrl/pinctrl-single.c                   |   88 +-
+ drivers/pinctrl/pinctrl-sirf.c                     |   52 +-
+ drivers/pinctrl/pinctrl-tegra.c                    |   24 +-
+ drivers/pinctrl/pinctrl-u300.c                     |   97 +-
+ drivers/pinctrl/pinctrl-xway.c                     |    2 +-
+ drivers/pinctrl/pinmux.c                           |   85 +-
+ drivers/pinctrl/spear/Kconfig                      |   11 +
+ drivers/pinctrl/spear/Makefile                     |    1 +
+ drivers/pinctrl/spear/pinctrl-plgpio.c             |  758 +++++++++
+ drivers/pinctrl/spear/pinctrl-spear.c              |  131 +-
+ drivers/pinctrl/spear/pinctrl-spear.h              |   60 +
+ drivers/pinctrl/spear/pinctrl-spear1310.c          |  264 ++++
+ drivers/pinctrl/spear/pinctrl-spear1340.c          |   27 +
+ drivers/pinctrl/spear/pinctrl-spear300.c           |    2 +
+ drivers/pinctrl/spear/pinctrl-spear310.c           |    2 +
+ drivers/pinctrl/spear/pinctrl-spear320.c           |    2 +
+ drivers/pinctrl/spear/pinctrl-spear3xx.c           |   37 +
+ drivers/tty/serial/atmel_serial.c                  |    8 +
+ include/asm-generic/gpio.h                         |   47 +
+ include/linux/gpio.h                               |   21 +-
+ include/linux/pinctrl/pinconf-generic.h            |    5 +-
+ include/linux/pinctrl/pinctrl.h                    |   19 +
+ include/linux/platform_data/pinctrl-coh901.h       |    4 -
+ .../linux/platform_data/pinctrl-nomadik.h          |  111 +-
+ 126 files changed, 7063 insertions(+), 1054 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
+ create mode 100644 arch/arm/boot/dts/animeo_ip.dts
+ create mode 100644 arch/arm/boot/dts/at91rm9200.dtsi
+ create mode 100644 arch/arm/boot/dts/at91rm9200ek.dts
+ create mode 100644 arch/arm/boot/dts/at91sam9g15.dtsi
+ create mode 100644 arch/arm/boot/dts/at91sam9g15ek.dts
+ create mode 100644 arch/arm/boot/dts/at91sam9g25.dtsi
+ create mode 100644 arch/arm/boot/dts/at91sam9g35.dtsi
+ create mode 100644 arch/arm/boot/dts/at91sam9g35ek.dts
+ create mode 100644 arch/arm/boot/dts/at91sam9x25.dtsi
+ create mode 100644 arch/arm/boot/dts/at91sam9x25ek.dts
+ create mode 100644 arch/arm/boot/dts/at91sam9x35.dtsi
+ create mode 100644 arch/arm/boot/dts/at91sam9x35ek.dts
+ create mode 100644 arch/arm/boot/dts/at91sam9x5ek.dtsi
+ create mode 100644 arch/arm/boot/dts/pm9g45.dts
+ create mode 100644 arch/arm/mach-at91/board-rm9200-dt.c
+ delete mode 100644 arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
+ create mode 100644 drivers/pinctrl/mvebu/Kconfig
+ create mode 100644 drivers/pinctrl/mvebu/Makefile
+ rename drivers/pinctrl/{ => mvebu}/pinctrl-armada-370.c (100%)
+ rename drivers/pinctrl/{ => mvebu}/pinctrl-armada-xp.c (100%)
+ rename drivers/pinctrl/{ => mvebu}/pinctrl-dove.c (100%)
+ rename drivers/pinctrl/{ => mvebu}/pinctrl-kirkwood.c (100%)
+ rename drivers/pinctrl/{ => mvebu}/pinctrl-mvebu.c (99%)
+ rename drivers/pinctrl/{ => mvebu}/pinctrl-mvebu.h (100%)
+ create mode 100644 drivers/pinctrl/pinctrl-at91.c
+ create mode 100644 drivers/pinctrl/spear/pinctrl-plgpio.c
+ rename arch/arm/plat-nomadik/include/plat/pincfg.h => include/linux/platform_data/pinctrl-nomadik.h (66%)
+Merging vhost/linux-next (e0953c8 tun: experimental zero copy tx support)
+$ git merge vhost/linux-next
+Resolved 'drivers/net/tun.c' using previous resolution.
+Auto-merging drivers/net/tun.c
+CONFLICT (content): Merge conflict in drivers/net/tun.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 1491dfa] Merge remote-tracking branch 'vhost/linux-next'
+$ git diff -M --stat --summary HEAD^..
+Merging memblock/memblock-kill-early_node_map (7bd0b0f memblock: Reimplement memblock allocation using reverse free area iterator)
+$ git merge memblock/memblock-kill-early_node_map
+Already up-to-date.
+Merging remoteproc/for-next (6f0c058 Linux 3.7-rc2)
+$ git merge remoteproc/for-next
+Already up-to-date.
+Merging irqdomain/irqdomain/next (a0d271c Linux 3.6)
+$ git merge irqdomain/irqdomain/next
+Already up-to-date.
+Merging gpio/gpio/next (b53bc28 gpio: SPEAr: add spi chipselect control driver)
+$ git merge gpio/gpio/next
+Recorded preimage for 'drivers/gpio/gpio-em.c'
+Auto-merging include/asm-generic/gpio.h
+Auto-merging drivers/gpio/gpiolib.c
+Auto-merging drivers/gpio/gpio-vt8500.c
+Auto-merging drivers/gpio/gpio-twl4030.c
+Auto-merging drivers/gpio/gpio-tegra.c
+Auto-merging drivers/gpio/gpio-tc3589x.c
+Auto-merging drivers/gpio/gpio-pch.c
+Auto-merging drivers/gpio/gpio-pca953x.c
+Auto-merging drivers/gpio/gpio-omap.c
+Auto-merging drivers/gpio/gpio-mvebu.c
+Auto-merging drivers/gpio/gpio-max730x.c
+Auto-merging drivers/gpio/gpio-em.c
+CONFLICT (content): Merge conflict in drivers/gpio/gpio-em.c
+Auto-merging drivers/gpio/Makefile
+Auto-merging drivers/gpio/Kconfig
+Auto-merging arch/arm/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+Recorded resolution for 'drivers/gpio/gpio-em.c'.
+[master 99565ba] Merge remote-tracking branch 'gpio/gpio/next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/gpio/spear_spics.txt       |   50 +++++
+ arch/arm/Kconfig                                   |    1 +
+ arch/arm/plat-spear/Kconfig                        |    1 +
+ drivers/gpio/Kconfig                               |   22 ++
+ drivers/gpio/Makefile                              |    3 +
+ drivers/gpio/gpio-clps711x.c                       |  199 ++++++++++++++++++
+ drivers/gpio/gpio-da9055.c                         |  204 ++++++++++++++++++
+ drivers/gpio/gpio-em.c                             |   48 +----
+ drivers/gpio/gpio-max730x.c                        |   12 +-
+ drivers/gpio/gpio-mvebu.c                          |    9 +-
+ drivers/gpio/gpio-omap.c                           |    2 +-
+ drivers/gpio/gpio-pca953x.c                        |   55 ++++-
+ drivers/gpio/gpio-pch.c                            |    1 +
+ drivers/gpio/gpio-pl061.c                          |   59 ++----
+ drivers/gpio/gpio-spear-spics.c                    |  217 ++++++++++++++++++++
+ drivers/gpio/gpio-tc3589x.c                        |   20 +-
+ drivers/gpio/gpio-tegra.c                          |   43 ++--
+ drivers/gpio/gpio-twl4030.c                        |   35 ++--
+ drivers/gpio/gpio-vt8500.c                         |    2 +
+ drivers/gpio/gpiolib.c                             |  124 +++++++----
+ include/asm-generic/gpio.h                         |    5 +-
+ 21 files changed, 931 insertions(+), 181 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/gpio/spear_spics.txt
+ create mode 100644 drivers/gpio/gpio-clps711x.c
+ create mode 100644 drivers/gpio/gpio-da9055.c
+ create mode 100644 drivers/gpio/gpio-spear-spics.c
+Merging gpio-lw/for-next (12fff48 Merge branch 'devel' into for-next)
+$ git merge gpio-lw/for-next
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging arm-soc/for-next (659b19c Merge branch 'next/soc' into for-next)
+$ git merge arm-soc/for-next
+Auto-merging sound/soc/ux500/ux500_pcm.c
+Auto-merging sound/soc/tegra/tegra30_ahub.c
+Auto-merging include/linux/tegra-ahb.h
+Auto-merging include/linux/platform_data/mmc-omap.h
+CONFLICT (content): Merge conflict in include/linux/platform_data/mmc-omap.h
+Auto-merging include/linux/platform_data/leds-omap.h
+Auto-merging include/linux/platform_data/clocksource-nomadik-mtu.h
+Auto-merging include/linux/mfd/menelaus.h
+Auto-merging include/linux/irqchip/spear-shirq.h
+Auto-merging include/linux/dma/ipu-dma.h
+Auto-merging include/linux/clk/sunxi.h
+Auto-merging drivers/watchdog/omap_wdt.c
+Auto-merging drivers/usb/musb/tusb6010_omap.c
+Auto-merging drivers/usb/musb/musb_dsps.c
+Auto-merging drivers/usb/musb/am35x.c
+Auto-merging drivers/usb/host/ohci-omap3.c
+Auto-merging drivers/usb/host/ohci-omap.c
+Auto-merging drivers/usb/host/ohci-at91.c
+Auto-merging drivers/usb/host/ehci-orion.c
+CONFLICT (content): Merge conflict in drivers/usb/host/ehci-orion.c
+Auto-merging drivers/usb/host/ehci-omap.c
+Auto-merging drivers/usb/host/ehci-mxc.c
+Auto-merging drivers/usb/gadget/omap_udc.c
+Auto-merging drivers/usb/gadget/at91_udc.c
+Auto-merging drivers/uio/uio_pruss.c
+Auto-merging drivers/uio/Kconfig
+Auto-merging drivers/tty/serial/samsung.c
+Auto-merging drivers/tty/serial/atmel_serial.c
+CONFLICT (content): Merge conflict in drivers/tty/serial/atmel_serial.c
+Auto-merging drivers/staging/nvec/nvec.c
+Auto-merging drivers/power/avs/smartreflex.c
+Auto-merging drivers/power/Makefile
+Auto-merging drivers/power/Kconfig
+CONFLICT (content): Merge conflict in drivers/power/Kconfig
+Auto-merging drivers/pinctrl/pinctrl-nomadik.c
+CONFLICT (content): Merge conflict in drivers/pinctrl/pinctrl-nomadik.c
+Auto-merging drivers/pinctrl/Makefile
+Auto-merging drivers/pinctrl/Kconfig
+Auto-merging drivers/net/ethernet/cadence/at91_ether.c
+CONFLICT (content): Merge conflict in drivers/net/ethernet/cadence/at91_ether.c
+Auto-merging drivers/net/can/at91_can.c
+Auto-merging drivers/mtd/onenand/omap2.c
+Removing drivers/mtd/nand/spia.c
+Auto-merging drivers/mtd/nand/omap2.c
+Auto-merging drivers/mtd/nand/mxc_nand.c
+CONFLICT (content): Merge conflict in drivers/mtd/nand/mxc_nand.c
+Removing drivers/mtd/nand/autcpu12.c
+Auto-merging drivers/mtd/nand/Makefile
+Auto-merging drivers/mtd/nand/Kconfig
+Removing drivers/mtd/maps/cdb89712.c
+Auto-merging drivers/mtd/maps/Makefile
+Auto-merging drivers/mtd/maps/Kconfig
+Auto-merging drivers/mmc/host/omap_hsmmc.c
+Auto-merging drivers/mmc/host/omap.c
+Auto-merging drivers/mmc/host/mxcmmc.c
+Auto-merging drivers/mmc/host/atmel-mci.c
+Auto-merging drivers/mfd/omap-usb-tll.c
+Auto-merging drivers/mfd/omap-usb-host.c
+Auto-merging drivers/mfd/db8500-prcmu.c
+Auto-merging drivers/mfd/ab8500-core.c
+Auto-merging drivers/mfd/Makefile
+CONFLICT (content): Merge conflict in drivers/mfd/Makefile
+Auto-merging drivers/mfd/Kconfig
+Auto-merging drivers/media/rc/ir-rx51.c
+Auto-merging drivers/media/platform/soc_camera/omap1_camera.c
+Auto-merging drivers/media/platform/soc_camera/mx3_camera.c
+Auto-merging drivers/media/platform/soc_camera/mx2_camera.c
+Auto-merging drivers/media/platform/omap3isp/ispvideo.c
+Auto-merging drivers/media/platform/omap3isp/ispstat.h
+Auto-merging drivers/media/platform/omap/omap_vout.c
+Auto-merging drivers/leds/leds-ns2.c
+CONFLICT (content): Merge conflict in drivers/leds/leds-ns2.c
+Auto-merging drivers/irqchip/irq-versatile-fpga.c
+Auto-merging drivers/iommu/tegra-smmu.c
+Auto-merging drivers/input/touchscreen/atmel_tsadcc.c
+Auto-merging drivers/input/keyboard/Kconfig
+Auto-merging drivers/hwmon/Makefile
+Auto-merging drivers/hwmon/Kconfig
+Auto-merging drivers/gpio/gpio-pxa.c
+Auto-merging drivers/gpio/Kconfig
+Auto-merging drivers/crypto/tegra-aes.c
+Auto-merging drivers/cpuidle/Kconfig
+Auto-merging drivers/clocksource/nomadik-mtu.c
+Removing arch/arm/plat-spear/shirq.c
+Removing arch/arm/plat-omap/sram.h
+Removing arch/arm/plat-omap/include/plat/usb.h
+Removing arch/arm/plat-omap/include/plat/uncompress.h
+Removing arch/arm/plat-omap/include/plat/sdrc.h
+Removing arch/arm/plat-omap/include/plat/prcm.h
+Removing arch/arm/plat-omap/include/plat/omap-secure.h
+Removing arch/arm/plat-omap/include/plat/multi.h
+Removing arch/arm/plat-omap/include/plat/fpga.h
+Removing arch/arm/plat-omap/include/plat/dma-44xx.h
+Auto-merging arch/arm/plat-omap/include/plat/debug-devices.h
+Removing arch/arm/plat-omap/include/plat/common.h
+Removing arch/arm/plat-omap/include/plat/clock.h
+Removing arch/arm/plat-omap/include/plat/clkdev_omap.h
+Auto-merging arch/arm/plat-omap/include/plat-omap/dma-omap.h
+Auto-merging arch/arm/plat-omap/fb.c
+CONFLICT (modify/delete): arch/arm/plat-omap/common.c deleted in arm-soc/for-next and modified in HEAD. Version HEAD of arch/arm/plat-omap/common.c left in tree.
+Removing arch/arm/plat-omap/clock.c
+Removing arch/arm/plat-nomadik/Makefile
+Removing arch/arm/plat-nomadik/Kconfig
+Removing arch/arm/plat-mxc/include/mach/uncompress.h
+Removing arch/arm/plat-mxc/include/mach/irqs.h
+Removing arch/arm/plat-mxc/include/mach/debug-macro.S
+Removing arch/arm/plat-mxc/Makefile
+Removing arch/arm/plat-mxc/Kconfig
+Removing arch/arm/mach-zynq/include/mach/timex.h
+Removing arch/arm/mach-zynq/include/mach/irqs.h
+Removing arch/arm/mach-zynq/include/mach/hardware.h
+Removing arch/arm/mach-vt8500/include/mach/restart.h
+Removing arch/arm/mach-vt8500/include/mach/i8042.h
+Removing arch/arm/mach-vt8500/include/mach/hardware.h
+Removing arch/arm/mach-vt8500/include/mach/entry-macro.S
+Auto-merging arch/arm/mach-ux500/devices-common.c
+Auto-merging arch/arm/mach-ux500/cpu-db8500.c
+CONFLICT (content): Merge conflict in arch/arm/mach-ux500/cpu-db8500.c
+Auto-merging arch/arm/mach-ux500/board-mop500.c
+CONFLICT (content): Merge conflict in arch/arm/mach-ux500/board-mop500.c
+Auto-merging arch/arm/mach-ux500/board-mop500-stuib.c
+CONFLICT (content): Merge conflict in arch/arm/mach-ux500/board-mop500-stuib.c
+Auto-merging arch/arm/mach-ux500/board-mop500-pins.c
+Auto-merging arch/arm/mach-ux500/board-mop500-audio.c
+CONFLICT (content): Merge conflict in arch/arm/mach-ux500/board-mop500-audio.c
+Auto-merging arch/arm/mach-u300/core.c
+Auto-merging arch/arm/mach-tegra/sleep-tegra30.S
+Auto-merging arch/arm/mach-tegra/sleep-tegra20.S
+Auto-merging arch/arm/mach-tegra/irammap.h
+Auto-merging arch/arm/mach-tegra/iomap.h
+Removing arch/arm/mach-tegra/include/mach/irqs.h
+Removing arch/arm/mach-tegra/include/mach/dma.h
+Removing arch/arm/mach-tegra/include/mach/debug-macro.S
+Auto-merging arch/arm/mach-spear13xx/spear13xx.c
+CONFLICT (content): Merge conflict in arch/arm/mach-spear13xx/spear13xx.c
+Auto-merging arch/arm/mach-spear13xx/spear1310.c
+CONFLICT (content): Merge conflict in arch/arm/mach-spear13xx/spear1310.c
+Auto-merging arch/arm/mach-spear13xx/include/mach/spear.h
+Auto-merging arch/arm/mach-socfpga/core.h
+Removing arch/arm/mach-shmobile/setup-sh7377.c
+Removing arch/arm/mach-shmobile/setup-sh7367.c
+Removing arch/arm/mach-shmobile/pfc-sh7377.c
+Removing arch/arm/mach-shmobile/pfc-sh7367.c
+Removing arch/arm/mach-shmobile/intc-sh7377.c
+Removing arch/arm/mach-shmobile/intc-sh7367.c
+Removing arch/arm/mach-shmobile/include/mach/sh7377.h
+Removing arch/arm/mach-shmobile/include/mach/sh7367.h
+Removing arch/arm/mach-shmobile/clock-sh7377.c
+Removing arch/arm/mach-shmobile/clock-sh7367.c
+Removing arch/arm/mach-shmobile/board-g4evm.c
+Removing arch/arm/mach-shmobile/board-g3evm.c
+Removing arch/arm/mach-pxa/tavorevb3.c
+Removing arch/arm/mach-pxa/saarb.c
+Removing arch/arm/mach-pxa/pxa95x.c
+Removing arch/arm/mach-pxa/include/mach/pxa95x.h
+Removing arch/arm/mach-omap2/prcm.c
+Removing arch/arm/mach-omap2/powerdomain44xx.c
+Removing arch/arm/mach-omap2/powerdomain33xx.c
+Removing arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
+Auto-merging arch/arm/mach-omap2/pmu.c
+Auto-merging arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+Auto-merging arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+Auto-merging arch/arm/mach-omap2/omap_hwmod_2430_data.c
+Auto-merging arch/arm/mach-omap2/omap_hwmod.h
+Auto-merging arch/arm/mach-omap2/omap_device.h
+Auto-merging arch/arm/mach-omap2/omap_device.c
+Auto-merging arch/arm/mach-omap2/omap-pm-noop.c
+Auto-merging arch/arm/mach-omap2/include/mach/serial.h
+Removing arch/arm/mach-omap2/include/mach/gpio.h
+Auto-merging arch/arm/mach-omap2/gpmc.h
+Auto-merging arch/arm/mach-omap2/drm.c
+CONFLICT (content): Merge conflict in arch/arm/mach-omap2/drm.c
+Auto-merging arch/arm/mach-omap2/display.c
+Auto-merging arch/arm/mach-omap2/cm3xxx.c
+Removing arch/arm/mach-omap2/clockdomain44xx.c
+Removing arch/arm/mach-omap2/clockdomain33xx.c
+Removing arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
+Removing arch/arm/mach-omap2/clock44xx_data.c
+Removing arch/arm/mach-omap2/clock3xxx_data.c
+Removing arch/arm/mach-omap2/clock33xx_data.c
+Removing arch/arm/mach-omap2/clock2430_data.c
+Removing arch/arm/mach-omap2/clock2420_data.c
+Auto-merging arch/arm/mach-omap2/board-rx51.c
+Auto-merging arch/arm/mach-omap2/board-overo.c
+Auto-merging arch/arm/mach-omap2/board-n8x0.c
+Removing arch/arm/mach-omap1/include/mach/gpio.h
+Auto-merging arch/arm/mach-omap1/board-nokia770.c
+Auto-merging arch/arm/mach-nomadik/board-nhk8815.c
+CONFLICT (content): Merge conflict in arch/arm/mach-nomadik/board-nhk8815.c
+Auto-merging arch/arm/mach-mxs/mach-mxs.c
+Auto-merging arch/arm/mach-imx/ulpi.c
+Auto-merging arch/arm/mach-imx/tzic.c
+Auto-merging arch/arm/mach-imx/time.c
+Auto-merging arch/arm/mach-imx/system.c
+Auto-merging arch/arm/mach-imx/mx6q.h
+Auto-merging arch/arm/mach-imx/mach-imx6q.c
+Auto-merging arch/arm/mach-imx/irq-common.h
+Auto-merging arch/arm/mach-imx/iram_alloc.c
+Auto-merging arch/arm/mach-imx/iomux-v3.c
+Auto-merging arch/arm/mach-imx/iomux-v1.c
+Auto-merging arch/arm/mach-imx/iomux-mx51.h
+Auto-merging arch/arm/mach-imx/iomux-mx50.h
+Auto-merging arch/arm/mach-imx/iomux-mx35.h
+Auto-merging arch/arm/mach-imx/iomux-mx27.h
+Auto-merging arch/arm/mach-imx/iomux-mx25.h
+Auto-merging arch/arm/mach-imx/iomux-mx21.h
+Auto-merging arch/arm/mach-imx/iomux-mx1.h
+Removing arch/arm/mach-imx/include/mach/dma-mx1-mx2.h
+Auto-merging arch/arm/mach-imx/hardware.h
+Auto-merging arch/arm/mach-imx/epit.c
+Auto-merging arch/arm/mach-imx/devices/platform-spi_imx.c
+Auto-merging arch/arm/mach-imx/devices/platform-sdhci-esdhc-imx.c
+Auto-merging arch/arm/mach-imx/devices/platform-pata_imx.c
+Auto-merging arch/arm/mach-imx/devices/platform-mxc_w1.c
+Auto-merging arch/arm/mach-imx/devices/platform-mxc_rtc.c
+Auto-merging arch/arm/mach-imx/devices/platform-mxc_rnga.c
+Auto-merging arch/arm/mach-imx/devices/platform-mxc_pwm.c
+Auto-merging arch/arm/mach-imx/devices/platform-mxc_nand.c
+Auto-merging arch/arm/mach-imx/devices/platform-mxc-mmc.c
+Auto-merging arch/arm/mach-imx/devices/platform-mxc-ehci.c
+Auto-merging arch/arm/mach-imx/devices/platform-mx2-camera.c
+Auto-merging arch/arm/mach-imx/devices/platform-mx1-camera.c
+Auto-merging arch/arm/mach-imx/devices/platform-ipu-core.c
+Auto-merging arch/arm/mach-imx/devices/platform-imxdi_rtc.c
+Auto-merging arch/arm/mach-imx/devices/platform-imx_udc.c
+Auto-merging arch/arm/mach-imx/devices/platform-imx27-coda.c
+Auto-merging arch/arm/mach-imx/devices/platform-imx21-hcd.c
+Auto-merging arch/arm/mach-imx/devices/platform-imx2-wdt.c
+Auto-merging arch/arm/mach-imx/devices/platform-imx-uart.c
+Auto-merging arch/arm/mach-imx/devices/platform-imx-ssi.c
+Auto-merging arch/arm/mach-imx/devices/platform-imx-keypad.c
+Auto-merging arch/arm/mach-imx/devices/platform-imx-i2c.c
+Auto-merging arch/arm/mach-imx/devices/platform-imx-fb.c
+Auto-merging arch/arm/mach-imx/devices/platform-imx-dma.c
+Auto-merging arch/arm/mach-imx/devices/platform-gpio_keys.c
+Auto-merging arch/arm/mach-imx/devices/platform-gpio-mxc.c
+Auto-merging arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c
+Auto-merging arch/arm/mach-imx/devices/platform-flexcan.c
+Auto-merging arch/arm/mach-imx/devices/platform-fec.c
+Auto-merging arch/arm/mach-imx/devices/platform-ahci-imx.c
+Auto-merging arch/arm/mach-imx/devices/devices.c
+Auto-merging arch/arm/mach-imx/devices/devices-common.h
+Auto-merging arch/arm/mach-imx/devices/Makefile
+Auto-merging arch/arm/mach-imx/devices/Kconfig
+Auto-merging arch/arm/mach-imx/cpufreq.c
+Auto-merging arch/arm/mach-imx/cpu.c
+Auto-merging arch/arm/mach-imx/common.h
+Auto-merging arch/arm/mach-imx/avic.c
+Auto-merging arch/arm/mach-imx/3ds_debugboard.c
+Removing arch/arm/mach-highbank/lluart.c
+Removing arch/arm/mach-exynos/dev-drm.c
+Auto-merging arch/arm/mach-davinci/board-da850-evm.c
+Removing arch/arm/mach-clps711x/p720t.c
+Removing arch/arm/mach-clps711x/include/mach/irqs.h
+Removing arch/arm/mach-clps711x/include/mach/entry-macro.S
+Removing arch/arm/mach-clps711x/edb7211-mm.c
+Removing arch/arm/mach-clps711x/edb7211-arch.c
+Removing arch/arm/mach-clps711x/cdb89712.c
+Auto-merging arch/arm/mach-clps711x/board-fortunet.c
+Auto-merging arch/arm/mach-clps711x/board-clep7312.c
+Removing arch/arm/mach-clps711x/autcpu12.c
+Auto-merging arch/arm/mach-at91/setup.c
+Removing arch/arm/mach-at91/include/mach/at91_pit.h
+Auto-merging arch/arm/mach-at91/board.h
+Auto-merging arch/arm/mach-at91/board-sam9g20ek.c
+Auto-merging arch/arm/mach-at91/board-dt.c
+Auto-merging arch/arm/mach-at91/board-csb337.c
+Auto-merging arch/arm/mach-at91/at91sam9x5.c
+Auto-merging arch/arm/mach-at91/at91sam9rl_devices.c
+Auto-merging arch/arm/mach-at91/at91sam9rl.c
+Auto-merging arch/arm/mach-at91/at91sam9n12.c
+Auto-merging arch/arm/mach-at91/at91sam9g45_devices.c
+Auto-merging arch/arm/mach-at91/at91sam9g45.c
+Auto-merging arch/arm/mach-at91/at91sam9263_devices.c
+Auto-merging arch/arm/mach-at91/at91sam9263.c
+Auto-merging arch/arm/mach-at91/at91sam9261_devices.c
+Auto-merging arch/arm/mach-at91/at91sam9261.c
+Auto-merging arch/arm/mach-at91/at91sam9260_devices.c
+Auto-merging arch/arm/mach-at91/at91sam9260.c
+Auto-merging arch/arm/mach-at91/at91rm9200_devices.c
+Auto-merging arch/arm/mach-at91/at91rm9200.c
+Auto-merging arch/arm/kernel/smp_twd.c
+Removing arch/arm/configs/usb-a9260_defconfig
+Auto-merging arch/arm/configs/u8500_defconfig
+CONFLICT (modify/delete): arch/arm/configs/stamp9g20_defconfig deleted in arm-soc/for-next and modified in HEAD. Version HEAD of arch/arm/configs/stamp9g20_defconfig left in tree.
+Removing arch/arm/configs/sam9_l9260_defconfig
+Removing arch/arm/configs/qil-a9260_defconfig
+Removing arch/arm/configs/g4evm_defconfig
+Removing arch/arm/configs/g3evm_defconfig
+Removing arch/arm/configs/fortunet_defconfig
+Removing arch/arm/configs/edb7211_defconfig
+Removing arch/arm/configs/cpu9g20_defconfig
+Removing arch/arm/configs/cpu9260_defconfig
+Removing arch/arm/configs/cam60_defconfig
+CONFLICT (modify/delete): arch/arm/configs/afeb9260_defconfig deleted in arm-soc/for-next and modified in HEAD. Version HEAD of arch/arm/configs/afeb9260_defconfig left in tree.
+Auto-merging arch/arm/boot/dts/tegra20-seaboard.dts
+Auto-merging arch/arm/boot/dts/spear600.dtsi
+Auto-merging arch/arm/boot/dts/spear320.dtsi
+Auto-merging arch/arm/boot/dts/spear310.dtsi
+Auto-merging arch/arm/boot/dts/spear300.dtsi
+Auto-merging arch/arm/boot/dts/spear13xx.dtsi
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/spear13xx.dtsi
+Auto-merging arch/arm/boot/dts/spear1340.dtsi
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/spear1340.dtsi
+Auto-merging arch/arm/boot/dts/snowball.dts
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/snowball.dts
+Auto-merging arch/arm/boot/dts/sh7372-mackerel.dts
+Auto-merging arch/arm/boot/dts/omap4-panda-es.dts
+Auto-merging arch/arm/boot/dts/imx6q.dtsi
+Auto-merging arch/arm/boot/dts/imx28.dtsi
+Auto-merging arch/arm/boot/dts/imx28-cfa10049.dts
+Auto-merging arch/arm/boot/dts/dbx5x0.dtsi
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/dbx5x0.dtsi
+Auto-merging arch/arm/boot/dts/at91sam9g45.dtsi
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/at91sam9g45.dtsi
+Auto-merging arch/arm/boot/dts/at91sam9263.dtsi
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/at91sam9263.dtsi
+Auto-merging arch/arm/boot/dts/at91sam9260.dtsi
+Auto-merging arch/arm/boot/dts/am33xx.dtsi
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/am33xx.dtsi
+Auto-merging arch/arm/boot/dts/am335x-evm.dts
+Auto-merging arch/arm/boot/dts/am335x-bone.dts
+Auto-merging arch/arm/boot/dts/Makefile
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/Makefile
+Removing arch/arm/boot/compressed/head-vt8500.S
+Auto-merging arch/arm/Kconfig.debug
+CONFLICT (content): Merge conflict in arch/arm/Kconfig.debug
+Auto-merging arch/arm/Kconfig
+Auto-merging MAINTAINERS
+Auto-merging Documentation/devicetree/bindings/vendoRecorded preimage for 'arch/arm/mach-ux500/board-mop500-stuib.c'
+Recorded preimage for 'drivers/leds/leds-ns2.c'
+Resolved 'arch/arm/Kconfig.debug' using previous resolution.
+Resolved 'arch/arm/boot/dts/Makefile' using previous resolution.
+Resolved 'arch/arm/boot/dts/am33xx.dtsi' using previous resolution.
+Resolved 'arch/arm/boot/dts/at91sam9263.dtsi' using previous resolution.
+Resolved 'arch/arm/boot/dts/at91sam9g45.dtsi' using previous resolution.
+Resolved 'arch/arm/boot/dts/dbx5x0.dtsi' using previous resolution.
+Resolved 'arch/arm/boot/dts/snowball.dts' using previous resolution.
+Resolved 'arch/arm/boot/dts/spear1340.dtsi' using previous resolution.
+Resolved 'arch/arm/boot/dts/spear13xx.dtsi' using previous resolution.
+Resolved 'arch/arm/mach-nomadik/board-nhk8815.c' using previous resolution.
+Resolved 'arch/arm/mach-omap2/drm.c' using previous resolution.
+Resolved 'arch/arm/mach-spear13xx/spear1310.c' using previous resolution.
+Resolved 'arch/arm/mach-spear13xx/spear13xx.c' using previous resolution.
+Resolved 'arch/arm/mach-ux500/board-mop500-audio.c' using previous resolution.
+Resolved 'arch/arm/mach-ux500/board-mop500.c' using previous resolution.
+Resolved 'arch/arm/mach-ux500/cpu-db8500.c' using previous resolution.
+Resolved 'drivers/mfd/Makefile' using previous resolution.
+Resolved 'drivers/mtd/nand/mxc_nand.c' using previous resolution.
+Resolved 'drivers/net/ethernet/cadence/at91_ether.c' using previous resolution.
+Resolved 'drivers/pinctrl/pinctrl-nomadik.c' using previous resolution.
+Resolved 'drivers/power/Kconfig' using previous resolution.
+Resolved 'drivers/tty/serial/atmel_serial.c' using previous resolution.
+Resolved 'drivers/usb/host/ehci-orion.c' using previous resolution.
+Resolved 'include/linux/platform_data/mmc-omap.h' using previous resolution.
+r-prefixes.txt
+Auto-merging Documentation/devicetree/bindings/usb/am33xx-usb.txt
+Auto-merging Documentation/devicetree/bindings/i2c/i2c-imx.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git rm -f arch/arm/configs/afeb9260_defconfig arch/arm/configs/stamp9g20_defconfig arch/arm/plat-omap/common.c
+arch/arm/configs/afeb9260_defconfig: needs merge
+arch/arm/configs/stamp9g20_defconfig: needs merge
+arch/arm/plat-omap/common.c: needs merge
+rm 'arch/arm/configs/afeb9260_defconfig'
+rm 'arch/arm/configs/stamp9g20_defconfig'
+rm 'arch/arm/plat-omap/common.c'
+$ git commit -v -a
+Recorded resolution for 'arch/arm/mach-ux500/board-mop500-stuib.c'.
+Recorded resolution for 'drivers/leds/leds-ns2.c'.
+[master d51f25e] Merge remote-tracking branch 'arm-soc/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/arm/sunxi/README                     |   19 +
+ Documentation/bus-devices/ti-gpmc.txt              |  122 +
+ .../bindings/arm/altera/socfpga-reset.txt          |   11 +
+ .../bindings/arm/altera/socfpga-system.txt         |   11 +
+ Documentation/devicetree/bindings/arm/arm-boards   |    4 +
+ .../devicetree/bindings/arm/bcm/bcm11351.txt       |    9 +
+ Documentation/devicetree/bindings/arm/calxeda.txt  |   13 +-
+ Documentation/devicetree/bindings/arm/davinci.txt  |   17 +
+ .../bindings/arm/exynos/power_domain.txt           |   15 +-
+ Documentation/devicetree/bindings/arm/fsl.txt      |    4 +
+ .../devicetree/bindings/arm/omap/counter.txt       |   15 +
+ .../devicetree/bindings/arm/omap/timer.txt         |   31 +
+ .../devicetree/bindings/arm/spear/shirq.txt        |   48 +
+ .../devicetree/bindings/arm/vexpress-sysreg.txt    |   50 +
+ Documentation/devicetree/bindings/arm/vexpress.txt |   98 +-
+ .../devicetree/bindings/ata/exynos-sata-phy.txt    |   14 +
+ .../devicetree/bindings/ata/exynos-sata.txt        |   17 +
+ .../devicetree/bindings/bus/omap-ocp2scp.txt       |   18 +
+ .../devicetree/bindings/clock/imx25-clock.txt      |  162 +
+ .../devicetree/bindings/clock/imx5-clock.txt       |  191 ++
+ .../devicetree/bindings/clock/imx6q-clock.txt      |    9 +-
+ .../devicetree/bindings/drm/exynos/hdmi.txt        |   22 +
+ .../devicetree/bindings/drm/exynos/hdmiddc.txt     |   12 +
+ .../devicetree/bindings/drm/exynos/hdmiphy.txt     |   12 +
+ .../devicetree/bindings/drm/exynos/mixer.txt       |   15 +
+ .../devicetree/bindings/gpio/gpio-poweroff.txt     |   22 +
+ .../devicetree/bindings/gpio/leds-ns2.txt          |   26 +
+ .../devicetree/bindings/hwmon/vexpress.txt         |   23 +
+ Documentation/devicetree/bindings/i2c/i2c-imx.txt  |    4 +-
+ .../devicetree/bindings/i2c/trivial-devices.txt    |    2 +
+ .../bindings/input/touchscreen/bu21013.txt         |   28 +
+ .../interrupt-controller/allwinner,sunxi-ic.txt    |  104 +
+ .../devicetree/bindings/media/s5p-mfc.txt          |   23 +
+ .../bindings/pinctrl/marvell,kirkwood-pinctrl.txt  |   39 +
+ .../bindings/pinctrl/samsung-pinctrl.txt           |  119 +-
+ .../devicetree/bindings/rtc/nvidia,tegra20-rtc.txt |   19 +
+ .../bindings/timer/allwinner,sunxi-timer.txt       |   17 +
+ .../bindings/timer/nvidia,tegra20-timer.txt        |   21 +
+ .../bindings/timer/nvidia,tegra30-timer.txt        |   23 +
+ .../devicetree/bindings/usb/am33xx-usb.txt         |   21 +
+ .../devicetree/bindings/usb/ehci-orion.txt         |   15 +
+ .../devicetree/bindings/vendor-prefixes.txt        |    1 +
+ .../devicetree/bindings/watchdog/atmel-wdt.txt     |   15 +
+ .../bindings/watchdog/brcm,bcm2835-pm-wdog.txt     |   13 +
+ .../devicetree/bindings/watchdog/sunxi-wdt.txt     |   13 +
+ Documentation/hwmon/vexpress                       |   34 +
+ MAINTAINERS                                        |   13 +-
+ arch/arm/Kconfig                                   |   51 +-
+ arch/arm/Kconfig.debug                             |   83 +-
+ arch/arm/Makefile                                  |    4 +-
+ arch/arm/arm-soc-for-next-contents.txt             |  168 +
+ arch/arm/boot/compressed/Makefile                  |    9 -
+ arch/arm/boot/compressed/head-vt8500.S             |   46 -
+ arch/arm/boot/dts/Makefile                         |   46 +-
+ arch/arm/boot/dts/am335x-bone.dts                  |   50 +
+ arch/arm/boot/dts/am335x-evm.dts                   |  118 +
+ arch/arm/boot/dts/am335x-evmsk.dts                 |  250 ++
+ arch/arm/boot/dts/am33xx.dtsi                      |  157 +-
+ arch/arm/boot/dts/at91sam9260.dtsi                 |    6 +
+ arch/arm/boot/dts/at91sam9263.dtsi                 |    6 +
+ arch/arm/boot/dts/at91sam9g45.dtsi                 |    6 +
+ arch/arm/boot/dts/bcm11351-brt.dts                 |   30 +
+ arch/arm/boot/dts/bcm11351.dtsi                    |   50 +
+ arch/arm/boot/dts/bcm2835-rpi-b.dts                |   15 +
+ arch/arm/boot/dts/bcm2835.dtsi                     |   28 +
+ arch/arm/boot/dts/ccu9540.dts                      |   72 +
+ arch/arm/boot/dts/cros5250-common.dtsi             |  184 +
+ arch/arm/boot/dts/da850-enbw-cmc.dts               |   30 +
+ arch/arm/boot/dts/da850-evm.dts                    |   28 +
+ arch/arm/boot/dts/da850.dtsi                       |   60 +
+ arch/arm/boot/dts/dbx5x0.dtsi                      |   56 +-
+ arch/arm/boot/dts/dove-cubox.dts                   |   10 +
+ arch/arm/boot/dts/dove.dtsi                        |   19 +-
+ arch/arm/boot/dts/ecx-2000.dts                     |  104 +
+ arch/arm/boot/dts/ecx-common.dtsi                  |  237 ++
+ arch/arm/boot/dts/evk-pro3.dts                     |   12 +
+ arch/arm/boot/dts/exynos4.dtsi                     |   54 +-
+ arch/arm/boot/dts/exynos4210-origen.dts            |   70 +-
+ arch/arm/boot/dts/exynos4210-pinctrl.dtsi          |  334 +-
+ arch/arm/boot/dts/exynos4210-smdkv310.dts          |   16 +
+ arch/arm/boot/dts/exynos4210-trats.dts             |   87 +-
+ arch/arm/boot/dts/exynos4210.dtsi                  |  249 +-
+ arch/arm/boot/dts/exynos4212.dtsi                  |   28 +
+ arch/arm/boot/dts/exynos4412-smdk4412.dts          |   45 +
+ arch/arm/boot/dts/exynos4412.dtsi                  |   28 +
+ arch/arm/boot/dts/exynos4x12-pinctrl.dtsi          |  965 ++++++
+ arch/arm/boot/dts/exynos4x12.dtsi                  |   69 +
+ arch/arm/boot/dts/exynos5250-smdk5250.dts          |   56 +-
+ arch/arm/boot/dts/exynos5250-snow.dts              |   43 +
+ arch/arm/boot/dts/exynos5250.dtsi                  |   87 +-
+ arch/arm/boot/dts/exynos5440-ssdk5440.dts          |   46 +
+ arch/arm/boot/dts/exynos5440.dtsi                  |  159 +
+ arch/arm/boot/dts/highbank.dts                     |  212 +-
+ arch/arm/boot/dts/href.dtsi                        |  273 ++
+ arch/arm/boot/dts/hrefprev60.dts                   |   48 +
+ arch/arm/boot/dts/hrefv60plus.dts                  |  217 +-
+ arch/arm/boot/dts/imx23-olinuxino.dts              |   23 +-
+ arch/arm/boot/dts/imx23.dtsi                       |   13 +
+ arch/arm/boot/dts/imx25-karo-tx25.dts              |   44 +
+ arch/arm/boot/dts/imx25.dtsi                       |  515 +++
+ arch/arm/boot/dts/imx27-3ds.dts                    |    4 -
+ arch/arm/boot/dts/imx27-apf27.dts                  |   89 +
+ arch/arm/boot/dts/imx27.dtsi                       |    9 +-
+ arch/arm/boot/dts/imx28-apf28.dts                  |   85 +
+ arch/arm/boot/dts/imx28-apf28dev.dts               |  154 +
+ arch/arm/boot/dts/imx28-cfa10036.dts               |   46 +
+ arch/arm/boot/dts/imx28-cfa10049.dts               |   33 +
+ arch/arm/boot/dts/imx28-evk.dts                    |   13 +-
+ arch/arm/boot/dts/imx28-sps1.dts                   |  169 +
+ arch/arm/boot/dts/imx28.dtsi                       |   35 +
+ arch/arm/boot/dts/imx51-babbage.dts                |   16 +
+ arch/arm/boot/dts/imx51.dtsi                       |  171 +-
+ arch/arm/boot/dts/imx53-qsb.dts                    |   62 +-
+ arch/arm/boot/dts/imx53.dtsi                       |  171 +-
+ arch/arm/boot/dts/imx6q-sabreauto.dts              |   64 +
+ arch/arm/boot/dts/imx6q-sabresd.dts                |   18 +
+ arch/arm/boot/dts/imx6q.dtsi                       |  154 +-
+ arch/arm/boot/dts/integratorap.dts                 |    5 +
+ arch/arm/boot/dts/integratorcp.dts                 |    5 +
+ arch/arm/boot/dts/kirkwood-6281.dtsi               |   44 +
+ arch/arm/boot/dts/kirkwood-6282.dtsi               |   45 +
+ arch/arm/boot/dts/kirkwood-98dx4122.dtsi           |   31 +
+ arch/arm/boot/dts/kirkwood-dnskw.dtsi              |  140 +
+ arch/arm/boot/dts/kirkwood-dockstar.dts            |   37 +
+ arch/arm/boot/dts/kirkwood-dreamplug.dts           |   21 +
+ arch/arm/boot/dts/kirkwood-goflexnet.dts           |   73 +
+ arch/arm/boot/dts/kirkwood-ib62x0.dts              |   40 +
+ arch/arm/boot/dts/kirkwood-iconnect.dts            |   51 +
+ arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts      |   89 +
+ arch/arm/boot/dts/kirkwood-is2.dts                 |   30 +
+ arch/arm/boot/dts/kirkwood-km_kirkwood.dts         |   17 +
+ arch/arm/boot/dts/kirkwood-lsxl.dtsi               |  106 +
+ arch/arm/boot/dts/kirkwood-mplcec4.dts             |  178 +
+ arch/arm/boot/dts/kirkwood-ns2-common.dtsi         |   63 +
+ arch/arm/boot/dts/kirkwood-ns2.dts                 |   30 +
+ arch/arm/boot/dts/kirkwood-ns2lite.dts             |   30 +
+ arch/arm/boot/dts/kirkwood-ns2max.dts              |   49 +
+ arch/arm/boot/dts/kirkwood-ns2mini.dts             |   49 +
+ arch/arm/boot/dts/kirkwood-nsa310.dts              |  144 +
+ arch/arm/boot/dts/kirkwood-openblocks_a6.dts       |   98 +
+ arch/arm/boot/dts/kirkwood-topkick.dts             |   85 +
+ arch/arm/boot/dts/kirkwood-ts219-6281.dts          |   31 +
+ arch/arm/boot/dts/kirkwood-ts219-6282.dts          |   31 +
+ arch/arm/boot/dts/kirkwood.dtsi                    |   17 +-
+ arch/arm/boot/dts/lpc32xx.dtsi                     |    7 +
+ arch/arm/boot/dts/omap2.dtsi                       |   86 +
+ arch/arm/boot/dts/omap2420.dtsi                    |   16 +-
+ arch/arm/boot/dts/omap2430.dtsi                    |   19 +-
+ arch/arm/boot/dts/omap3-beagle-xm.dts              |    6 -
+ arch/arm/boot/dts/omap3-beagle.dts                 |   67 +
+ arch/arm/boot/dts/omap3.dtsi                       |  107 +-
+ arch/arm/boot/dts/omap4-panda-a4.dts               |   17 +
+ .../dts/{omap4-pandaES.dts => omap4-panda-es.dts}  |    9 +
+ arch/arm/boot/dts/omap4-panda.dts                  |   22 +
+ arch/arm/boot/dts/omap4-sdp-es23plus.dts           |   17 +
+ arch/arm/boot/dts/omap4-sdp.dts                    |   22 +
+ .../dts/{omap4-var_som.dts => omap4-var-som.dts}   |    0
+ arch/arm/boot/dts/omap4.dtsi                       |  105 +-
+ arch/arm/boot/dts/omap5-evm.dts                    |   13 +-
+ arch/arm/boot/dts/omap5.dtsi                       |  178 +-
+ .../dts/orion5x-lacie-ethernet-disk-mini-v2.dts    |   55 +
+ arch/arm/boot/dts/orion5x.dtsi                     |   98 +
+ arch/arm/boot/dts/samsung_k3pe0e000b.dtsi          |   67 +
+ .../boot/dts/{sh7377.dtsi => sh7372-mackerel.dts}  |   13 +-
+ arch/arm/boot/dts/snowball.dts                     |  140 +-
+ arch/arm/boot/dts/socfpga.dtsi                     |   10 +
+ arch/arm/boot/dts/spear1310-evb.dts                |  165 +-
+ arch/arm/boot/dts/spear1310.dtsi                   |   32 +-
+ arch/arm/boot/dts/spear1340-evb.dts                |  253 +-
+ arch/arm/boot/dts/spear1340.dtsi                   |   61 +
+ arch/arm/boot/dts/spear13xx.dtsi                   |   72 +-
+ arch/arm/boot/dts/spear300-evb.dts                 |   20 +-
+ arch/arm/boot/dts/spear300.dtsi                    |   14 +-
+ arch/arm/boot/dts/spear310-evb.dts                 |   30 +-
+ arch/arm/boot/dts/spear310.dtsi                    |   18 +
+ arch/arm/boot/dts/spear320-evb.dts                 |   35 +-
+ arch/arm/boot/dts/spear320-hmi.dts                 |  305 ++
+ arch/arm/boot/dts/spear320.dtsi                    |   39 +-
+ arch/arm/boot/dts/spear3xx.dtsi                    |    5 +-
+ arch/arm/boot/dts/spear600-evb.dts                 |   46 +-
+ arch/arm/boot/dts/spear600.dtsi                    |   16 +
+ arch/arm/boot/dts/stuib.dtsi                       |   78 +
+ arch/arm/boot/dts/sun4i-cubieboard.dts             |   38 +
+ arch/arm/boot/dts/sun4i.dtsi                       |   19 +
+ arch/arm/boot/dts/sun5i-olinuxino.dts              |   30 +
+ arch/arm/boot/dts/sun5i.dtsi                       |   20 +
+ arch/arm/boot/dts/sunxi.dtsi                       |   80 +
+ arch/arm/boot/dts/tegra20-harmony.dts              |   84 +-
+ arch/arm/boot/dts/tegra20-paz00.dts                |   59 +-
+ arch/arm/boot/dts/tegra20-plutux.dts               |    6 +
+ arch/arm/boot/dts/tegra20-seaboard.dts             |   65 +-
+ arch/arm/boot/dts/tegra20-tamonten.dtsi            |  147 +-
+ arch/arm/boot/dts/tegra20-tec.dts                  |    9 +-
+ arch/arm/boot/dts/tegra20-trimslice.dts            |   54 +-
+ arch/arm/boot/dts/tegra20-ventana.dts              |  149 +-
+ arch/arm/boot/dts/tegra20-whistler.dts             |  136 +-
+ arch/arm/boot/dts/tegra20.dtsi                     |  167 +
+ arch/arm/boot/dts/tegra30-cardhu-a02.dts           |    6 +
+ arch/arm/boot/dts/tegra30-cardhu-a04.dts           |    6 +
+ arch/arm/boot/dts/tegra30-cardhu.dtsi              |   84 +-
+ arch/arm/boot/dts/tegra30.dtsi                     |  179 +
+ arch/arm/boot/dts/twl4030.dtsi                     |   27 +
+ arch/arm/boot/dts/twl6030.dtsi                     |    5 +
+ arch/arm/boot/dts/u9540.dts                        |   72 +
+ arch/arm/boot/dts/vexpress-v2m-rs1.dtsi            |  146 +-
+ arch/arm/boot/dts/vexpress-v2m.dtsi                |  146 +-
+ arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts        |  121 +-
+ arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts         |  186 +-
+ arch/arm/boot/dts/vexpress-v2p-ca5s.dts            |   84 +-
+ arch/arm/boot/dts/vexpress-v2p-ca9.dts             |  136 +-
+ arch/arm/configs/afeb9260_defconfig                |  106 -
+ arch/arm/configs/ap4evb_defconfig                  |    1 -
+ arch/arm/configs/armadillo800eva_defconfig         |    3 +-
+ arch/arm/configs/bcm2835_defconfig                 |    2 -
+ arch/arm/configs/bcm_defconfig                     |  114 +
+ arch/arm/configs/cam60_defconfig                   |  173 -
+ arch/arm/configs/clps711x_defconfig                |   90 +
+ arch/arm/configs/cpu9260_defconfig                 |  116 -
+ arch/arm/configs/cpu9g20_defconfig                 |  116 -
+ arch/arm/configs/da8xx_omapl_defconfig             |    3 +
+ arch/arm/configs/dove_defconfig                    |   24 +
+ arch/arm/configs/edb7211_defconfig                 |   27 -
+ arch/arm/configs/fortunet_defconfig                |   28 -
+ arch/arm/configs/g3evm_defconfig                   |   57 -
+ arch/arm/configs/g4evm_defconfig                   |   57 -
+ arch/arm/configs/imx_v4_v5_defconfig               |    5 +-
+ arch/arm/configs/imx_v6_v7_defconfig               |    5 +
+ arch/arm/configs/kirkwood_defconfig                |    9 +
+ arch/arm/configs/kota2_defconfig                   |    1 -
+ arch/arm/configs/kzm9g_defconfig                   |    5 +-
+ arch/arm/configs/mackerel_defconfig                |   19 +-
+ arch/arm/configs/marzen_defconfig                  |   18 +-
+ arch/arm/configs/mxs_defconfig                     |    6 +
+ arch/arm/configs/orion5x_defconfig                 |   36 +-
+ arch/arm/configs/qil-a9260_defconfig               |  114 -
+ arch/arm/configs/sam9_l9260_defconfig              |  148 -
+ arch/arm/configs/socfpga_defconfig                 |    5 +-
+ arch/arm/configs/stamp9g20_defconfig               |  128 -
+ arch/arm/configs/tegra_defconfig                   |   21 +-
+ arch/arm/configs/u8500_defconfig                   |    1 +
+ arch/arm/configs/usb-a9260_defconfig               |  105 -
+ arch/arm/include/asm/dma-mapping.h                 |    7 -
+ arch/arm/include/asm/hardware/sp810.h              |    6 +-
+ arch/arm/include/debug/imx.S                       |   74 +
+ arch/arm/include/debug/sunxi.S                     |   27 +
+ arch/arm/include/debug/tegra.S                     |  223 ++
+ arch/arm/include/debug/vexpress.S                  |   11 +-
+ arch/arm/kernel/smp_twd.c                          |    6 +-
+ arch/arm/mach-at91/{include/mach => }/at91_aic.h   |    0
+ arch/arm/mach-at91/{include/mach => }/at91_rstc.h  |    0
+ arch/arm/mach-at91/{include/mach => }/at91_shdwc.h |    0
+ arch/arm/mach-at91/{include/mach => }/at91_tc.h    |    0
+ arch/arm/mach-at91/at91rm9200.c                    |    2 +-
+ arch/arm/mach-at91/at91rm9200_devices.c            |    2 +-
+ arch/arm/mach-at91/at91sam9260.c                   |    4 +-
+ arch/arm/mach-at91/at91sam9260_devices.c           |    2 +-
+ arch/arm/mach-at91/at91sam9261.c                   |    4 +-
+ arch/arm/mach-at91/at91sam9261_devices.c           |    2 +-
+ arch/arm/mach-at91/at91sam9263.c                   |    4 +-
+ arch/arm/mach-at91/at91sam9263_devices.c           |    2 +-
+ arch/arm/mach-at91/at91sam926x_time.c              |   14 +-
+ arch/arm/mach-at91/at91sam9_alt_reset.S            |    2 +-
+ arch/arm/mach-at91/at91sam9g45.c                   |    3 +-
+ arch/arm/mach-at91/at91sam9g45_devices.c           |    2 +-
+ arch/arm/mach-at91/at91sam9g45_reset.S             |    3 +-
+ arch/arm/mach-at91/at91sam9n12.c                   |    2 +-
+ arch/arm/mach-at91/at91sam9rl.c                    |    4 +-
+ arch/arm/mach-at91/at91sam9rl_devices.c            |    2 +-
+ arch/arm/mach-at91/at91sam9x5.c                    |    2 +-
+ arch/arm/mach-at91/at91x40.c                       |    3 +-
+ arch/arm/mach-at91/at91x40_time.c                  |    3 +-
+ arch/arm/mach-at91/board-1arm.c                    |    4 +-
+ arch/arm/mach-at91/board-afeb-9260v1.c             |    5 +-
+ arch/arm/mach-at91/board-cam60.c                   |    4 +-
+ arch/arm/mach-at91/board-carmeva.c                 |    4 +-
+ arch/arm/mach-at91/board-cpu9krea.c                |    4 +-
+ arch/arm/mach-at91/board-cpuat91.c                 |    4 +-
+ arch/arm/mach-at91/board-csb337.c                  |    4 +-
+ arch/arm/mach-at91/board-csb637.c                  |    4 +-
+ arch/arm/mach-at91/board-dt.c                      |    5 +-
+ arch/arm/mach-at91/board-eb01.c                    |    5 +-
+ arch/arm/mach-at91/board-eb9200.c                  |    5 +-
+ arch/arm/mach-at91/board-ecbat91.c                 |    4 +-
+ arch/arm/mach-at91/board-eco920.c                  |    4 +-
+ arch/arm/mach-at91/board-flexibity.c               |    4 +-
+ arch/arm/mach-at91/board-foxg20.c                  |    4 +-
+ arch/arm/mach-at91/board-gsia18s.c                 |    8 +-
+ arch/arm/mach-at91/board-kafa.c                    |    4 +-
+ arch/arm/mach-at91/board-kb9202.c                  |    4 +-
+ arch/arm/mach-at91/board-neocore926.c              |    4 +-
+ arch/arm/mach-at91/board-pcontrol-g20.c            |    6 +-
+ arch/arm/mach-at91/board-picotux200.c              |    4 +-
+ arch/arm/mach-at91/board-qil-a9260.c               |    6 +-
+ arch/arm/mach-at91/board-rm9200dk.c                |    4 +-
+ arch/arm/mach-at91/board-rm9200ek.c                |    4 +-
+ arch/arm/mach-at91/board-rsi-ews.c                 |    4 +-
+ arch/arm/mach-at91/board-sam9-l9260.c              |    4 +-
+ arch/arm/mach-at91/board-sam9260ek.c               |    6 +-
+ arch/arm/mach-at91/board-sam9261ek.c               |    6 +-
+ arch/arm/mach-at91/board-sam9263ek.c               |    6 +-
+ arch/arm/mach-at91/board-sam9g20ek.c               |    4 +-
+ arch/arm/mach-at91/board-sam9m10g45ek.c            |    6 +-
+ arch/arm/mach-at91/board-sam9rlek.c                |    7 +-
+ arch/arm/mach-at91/board-snapper9260.c             |    4 +-
+ arch/arm/mach-at91/board-stamp9g20.c               |    4 +-
+ arch/arm/mach-at91/board-usb-a926x.c               |    6 +-
+ arch/arm/mach-at91/board-yl-9200.c                 |    4 +-
+ arch/arm/mach-at91/{include/mach => }/board.h      |   55 -
+ arch/arm/mach-at91/{include/mach => }/gsia18s.h    |    0
+ arch/arm/mach-at91/include/mach/at91_pit.h         |   32 -
+ arch/arm/mach-at91/include/mach/atmel-mci.h        |    7 -
+ arch/arm/mach-at91/include/mach/hardware.h         |    3 -
+ arch/arm/mach-at91/irq.c                           |    2 +-
+ arch/arm/mach-at91/leds.c                          |    2 +-
+ arch/arm/mach-at91/pm.c                            |    6 +-
+ arch/arm/mach-at91/setup.c                         |    2 +-
+ arch/arm/mach-at91/{include/mach => }/stamp9g20.h  |    0
+ arch/arm/mach-bcm/Kconfig                          |   19 +
+ arch/arm/mach-bcm/Makefile                         |   13 +
+ arch/arm/mach-bcm/board_bcm.c                      |   57 +
+ arch/arm/mach-bcm2835/Makefile.boot                |    4 +-
+ arch/arm/mach-bcm2835/bcm2835.c                    |   50 +-
+ arch/arm/mach-bcm2835/include/mach/gpio.h          |    1 +
+ arch/arm/mach-clps711x/Kconfig                     |    2 -
+ arch/arm/mach-clps711x/Makefile                    |   12 +-
+ arch/arm/mach-clps711x/Makefile.boot               |    1 -
+ arch/arm/mach-clps711x/autcpu12.c                  |   92 -
+ arch/arm/mach-clps711x/board-autcpu12.c            |  179 +
+ arch/arm/mach-clps711x/board-cdb89712.c            |  147 +
+ .../mach-clps711x/{clep7312.c => board-clep7312.c} |    4 +-
+ arch/arm/mach-clps711x/board-edb7211.c             |  180 +
+ .../mach-clps711x/{fortunet.c => board-fortunet.c} |    2 +
+ arch/arm/mach-clps711x/board-p720t.c               |  232 ++
+ arch/arm/mach-clps711x/cdb89712.c                  |   63 -
+ arch/arm/mach-clps711x/common.c                    |  181 +-
+ arch/arm/mach-clps711x/common.h                    |    7 +-
+ arch/arm/mach-clps711x/edb7211-arch.c              |   66 -
+ arch/arm/mach-clps711x/edb7211-mm.c                |   82 -
+ arch/arm/mach-clps711x/include/mach/autcpu12.h     |   23 +-
+ arch/arm/mach-clps711x/include/mach/clps711x.h     |   27 +
+ arch/arm/mach-clps711x/include/mach/entry-macro.S  |   51 -
+ arch/arm/mach-clps711x/include/mach/hardware.h     |   67 +-
+ arch/arm/mach-clps711x/include/mach/irqs.h         |   50 -
+ arch/arm/mach-clps711x/include/mach/syspld.h       |    9 +-
+ arch/arm/mach-clps711x/p720t.c                     |  181 -
+ arch/arm/mach-cns3xxx/Kconfig                      |    1 -
+ arch/arm/mach-davinci/Kconfig                      |    8 +
+ arch/arm/mach-davinci/Makefile                     |    1 +
+ arch/arm/mach-davinci/board-da850-evm.c            |   34 +-
+ arch/arm/mach-davinci/board-dm355-evm.c            |    2 +-
+ arch/arm/mach-davinci/board-dm355-leopard.c        |    2 +-
+ arch/arm/mach-davinci/board-dm365-evm.c            |    4 +-
+ arch/arm/mach-davinci/board-dm644x-evm.c           |    7 +-
+ arch/arm/mach-davinci/board-dm646x-evm.c           |    2 +-
+ arch/arm/mach-davinci/board-neuros-osd2.c          |    2 +-
+ arch/arm/mach-davinci/common.c                     |    2 -
+ arch/arm/mach-davinci/da850.c                      |   17 +-
+ arch/arm/mach-davinci/da8xx-dt.c                   |   66 +
+ arch/arm/mach-davinci/devices-da8xx.c              |   77 +-
+ arch/arm/mach-davinci/devices-tnetv107x.c          |    2 +-
+ arch/arm/mach-davinci/dm355.c                      |    6 -
+ arch/arm/mach-davinci/dm365.c                      |    6 -
+ arch/arm/mach-davinci/dm644x.c                     |    6 -
+ arch/arm/mach-davinci/dm646x.c                     |    6 -
+ arch/arm/mach-davinci/include/mach/common.h        |    2 -
+ arch/arm/mach-davinci/include/mach/da8xx.h         |    3 +
+ arch/arm/mach-davinci/include/mach/serial.h        |    3 +-
+ arch/arm/mach-davinci/include/mach/sram.h          |    3 +
+ arch/arm/mach-davinci/include/mach/uncompress.h    |    6 +
+ arch/arm/mach-davinci/serial.c                     |   39 +-
+ arch/arm/mach-davinci/sram.c                       |   23 +-
+ arch/arm/mach-davinci/time.c                       |    4 +-
+ arch/arm/mach-davinci/usb.c                        |    6 -
+ arch/arm/mach-dove/include/mach/pm.h               |    2 +-
+ arch/arm/mach-dove/irq.c                           |   14 +-
+ arch/arm/mach-exynos/Kconfig                       |   12 +-
+ arch/arm/mach-exynos/Makefile                      |    3 +-
+ arch/arm/mach-exynos/clock-exynos4.c               |    9 +-
+ arch/arm/mach-exynos/clock-exynos5.c               |   67 +-
+ arch/arm/mach-exynos/common.c                      |  134 +-
+ arch/arm/mach-exynos/cpuidle.c                     |   36 +
+ arch/arm/mach-exynos/dev-audio.c                   |    2 +-
+ arch/arm/mach-exynos/dev-drm.c                     |   29 -
+ arch/arm/mach-exynos/dev-ohci.c                    |    2 +-
+ arch/arm/mach-exynos/dev-uart.c                    |   24 -
+ arch/arm/mach-exynos/include/mach/irqs.h           |   13 +-
+ arch/arm/mach-exynos/include/mach/map.h            |    8 +-
+ arch/arm/mach-exynos/include/mach/regs-clock.h     |   19 +
+ arch/arm/mach-exynos/include/mach/regs-pmu.h       |    4 +-
+ arch/arm/mach-exynos/mach-exynos4-dt.c             |    4 +
+ arch/arm/mach-exynos/mach-exynos5-dt.c             |   99 +-
+ arch/arm/mach-exynos/mach-nuri.c                   |   10 +-
+ arch/arm/mach-exynos/mach-origen.c                 |   11 +-
+ arch/arm/mach-exynos/mach-smdk4x12.c               |    5 +-
+ arch/arm/mach-exynos/mach-smdkv310.c               |    9 +-
+ arch/arm/mach-exynos/mach-universal_c210.c         |    8 +-
+ arch/arm/mach-exynos/mct.c                         |   11 +-
+ arch/arm/mach-exynos/pm.c                          |    9 +
+ arch/arm/mach-exynos/pm_domains.c                  |   93 +-
+ arch/arm/mach-exynos/setup-i2c0.c                  |    2 +-
+ arch/arm/mach-highbank/Kconfig                     |    2 +-
+ arch/arm/mach-highbank/Makefile                    |    1 -
+ arch/arm/mach-highbank/core.h                      |   10 +-
+ arch/arm/mach-highbank/highbank.c                  |   33 +-
+ arch/arm/mach-highbank/hotplug.c                   |    6 +-
+ arch/arm/mach-highbank/lluart.c                    |   34 -
+ arch/arm/mach-highbank/platsmp.c                   |    7 +-
+ arch/arm/mach-highbank/pm.c                        |    3 -
+ arch/arm/mach-highbank/sysregs.h                   |   19 +
+ arch/arm/mach-highbank/system.c                    |    2 -
+ arch/arm/{plat-mxc => mach-imx}/3ds_debugboard.c   |    2 +-
+ .../include/mach => mach-imx}/3ds_debugboard.h     |    0
+ arch/arm/mach-imx/Kconfig                          |  110 +-
+ arch/arm/mach-imx/Makefile                         |   23 +
+ arch/arm/{plat-mxc => mach-imx}/avic.c             |    5 +-
+ .../include/mach => mach-imx}/board-mx31lilly.h    |    0
+ .../include/mach => mach-imx}/board-mx31lite.h     |    0
+ .../include/mach => mach-imx}/board-mx31moboard.h  |    0
+ .../include/mach => mach-imx}/board-pcm038.h       |    0
+ arch/arm/mach-imx/clk-imx1.c                       |   17 +-
+ arch/arm/mach-imx/clk-imx21.c                      |   18 +-
+ arch/arm/mach-imx/clk-imx25.c                      |  145 +-
+ arch/arm/mach-imx/clk-imx27.c                      |   58 +-
+ arch/arm/mach-imx/clk-imx31.c                      |   21 +-
+ arch/arm/mach-imx/clk-imx35.c                      |   13 +-
+ arch/arm/mach-imx/clk-imx51-imx53.c                |   59 +-
+ arch/arm/mach-imx/clk-imx6q.c                      |   46 +-
+ arch/arm/mach-imx/clk-pllv1.c                      |    4 +-
+ arch/arm/mach-imx/clk-pllv3.c                      |   72 +-
+ arch/arm/mach-imx/clk.h                            |    3 +-
+ .../{plat-mxc/include/mach => mach-imx}/common.h   |    2 +
+ arch/arm/mach-imx/cpu-imx25.c                      |    5 +-
+ arch/arm/mach-imx/cpu-imx27.c                      |    2 +-
+ arch/arm/mach-imx/cpu-imx31.c                      |    7 +-
+ arch/arm/mach-imx/cpu-imx35.c                      |    5 +-
+ arch/arm/mach-imx/cpu-imx5.c                       |    3 +-
+ arch/arm/{plat-mxc => mach-imx}/cpu.c              |    3 +-
+ arch/arm/mach-imx/cpu_op-mx51.c                    |    3 +-
+ arch/arm/{plat-mxc => mach-imx}/cpufreq.c          |    3 +-
+ arch/arm/{plat-mxc => mach-imx}/cpuidle.c          |    0
+ .../{plat-mxc/include/mach => mach-imx}/cpuidle.h  |    0
+ arch/arm/mach-imx/devices-imx1.h                   |    3 +-
+ arch/arm/mach-imx/devices-imx21.h                  |    3 +-
+ arch/arm/mach-imx/devices-imx25.h                  |    3 +-
+ arch/arm/mach-imx/devices-imx27.h                  |    7 +-
+ arch/arm/mach-imx/devices-imx31.h                  |    3 +-
+ arch/arm/mach-imx/devices-imx35.h                  |    3 +-
+ arch/arm/mach-imx/devices-imx50.h                  |    3 +-
+ arch/arm/mach-imx/devices-imx51.h                  |    3 +-
+ arch/arm/{plat-mxc => mach-imx}/devices/Kconfig    |    3 +
+ arch/arm/{plat-mxc => mach-imx}/devices/Makefile   |    3 +
+ .../mach => mach-imx/devices}/devices-common.h     |   18 +-
+ arch/arm/{plat-mxc => mach-imx/devices}/devices.c  |    4 +-
+ .../devices/platform-ahci-imx.c                    |    5 +-
+ .../{plat-mxc => mach-imx}/devices/platform-fec.c  |    5 +-
+ .../devices/platform-flexcan.c                     |    4 +-
+ .../devices/platform-fsl-usb2-udc.c                |    5 +-
+ .../devices/platform-gpio-mxc.c                    |    2 +-
+ .../devices/platform-gpio_keys.c                   |    5 +-
+ .../devices/platform-imx-dma.c                     |   23 +-
+ .../devices/platform-imx-fb.c                      |   16 +-
+ .../devices/platform-imx-i2c.c                     |   32 +-
+ .../devices/platform-imx-keypad.c                  |    4 +-
+ .../devices/platform-imx-ssi.c                     |    4 +-
+ .../devices/platform-imx-uart.c                    |    4 +-
+ .../devices/platform-imx2-wdt.c                    |    5 +-
+ .../devices/platform-imx21-hcd.c                   |    4 +-
+ .../devices/platform-imx27-coda.c                  |    4 +-
+ .../devices/platform-imx_udc.c                     |    4 +-
+ .../devices/platform-imxdi_rtc.c                   |    5 +-
+ .../devices/platform-ipu-core.c                    |    5 +-
+ .../devices/platform-mx1-camera.c                  |    4 +-
+ .../devices/platform-mx2-camera.c                  |   33 +-
+ .../devices/platform-mxc-ehci.c                    |    5 +-
+ .../devices/platform-mxc-mmc.c                     |   20 +-
+ .../devices/platform-mxc_nand.c                    |   25 +-
+ .../devices/platform-mxc_pwm.c                     |    4 +-
+ .../devices/platform-mxc_rnga.c                    |    4 +-
+ .../devices/platform-mxc_rtc.c                     |   13 +-
+ .../devices/platform-mxc_w1.c                      |    4 +-
+ .../devices/platform-pata_imx.c                    |    4 +-
+ .../devices/platform-sdhci-esdhc-imx.c             |    5 +-
+ .../devices/platform-spi_imx.c                     |    4 +-
+ arch/arm/mach-imx/ehci-imx25.c                     |    4 +-
+ arch/arm/mach-imx/ehci-imx27.c                     |    4 +-
+ arch/arm/mach-imx/ehci-imx31.c                     |    4 +-
+ arch/arm/mach-imx/ehci-imx35.c                     |    4 +-
+ arch/arm/mach-imx/ehci-imx5.c                      |    4 +-
+ arch/arm/{plat-mxc => mach-imx}/epit.c             |    6 +-
+ .../include/mach => mach-imx}/eukrea-baseboards.h  |    0
+ arch/arm/mach-imx/eukrea_mbimx27-baseboard.c       |    7 +-
+ arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c     |    8 +-
+ arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c     |    7 +-
+ arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c     |    7 +-
+ .../{plat-mxc/include/mach => mach-imx}/hardware.h |   26 +-
+ arch/arm/mach-imx/hotplug.c                        |    3 +-
+ arch/arm/{plat-mxc/include/mach => mach-imx}/iim.h |    0
+ arch/arm/mach-imx/imx25-dt.c                       |   48 +
+ arch/arm/mach-imx/imx27-dt.c                       |   11 +-
+ arch/arm/mach-imx/imx31-dt.c                       |    5 +-
+ arch/arm/mach-imx/imx51-dt.c                       |   31 +-
+ arch/arm/mach-imx/include/mach/dma-mx1-mx2.h       |   10 -
+ arch/arm/mach-imx/iomux-imx31.c                    |    5 +-
+ .../include/mach => mach-imx}/iomux-mx1.h          |    2 +-
+ .../include/mach => mach-imx}/iomux-mx21.h         |    4 +-
+ .../include/mach => mach-imx}/iomux-mx25.h         |    2 +-
+ .../include/mach => mach-imx}/iomux-mx27.h         |    4 +-
+ .../include/mach => mach-imx}/iomux-mx2x.h         |    0
+ .../include/mach => mach-imx}/iomux-mx3.h          |    0
+ .../include/mach => mach-imx}/iomux-mx35.h         |    2 +-
+ .../include/mach => mach-imx}/iomux-mx50.h         |    2 +-
+ .../include/mach => mach-imx}/iomux-mx51.h         |    2 +-
+ arch/arm/{plat-mxc => mach-imx}/iomux-v1.c         |    5 +-
+ .../{plat-mxc/include/mach => mach-imx}/iomux-v1.h |    0
+ arch/arm/{plat-mxc => mach-imx}/iomux-v3.c         |    5 +-
+ .../{plat-mxc/include/mach => mach-imx}/iomux-v3.h |    0
+ .../arm/{plat-mxc/include/mach => mach-imx}/iram.h |    0
+ arch/arm/{plat-mxc => mach-imx}/iram_alloc.c       |    3 +-
+ arch/arm/{plat-mxc => mach-imx}/irq-common.c       |    0
+ arch/arm/{plat-mxc => mach-imx}/irq-common.h       |    3 +
+ arch/arm/mach-imx/lluart.c                         |   31 +-
+ arch/arm/mach-imx/mach-apf9328.c                   |    7 +-
+ arch/arm/mach-imx/mach-armadillo5x0.c              |    9 +-
+ arch/arm/mach-imx/mach-bug.c                       |    7 +-
+ arch/arm/mach-imx/mach-cpuimx27.c                  |   11 +-
+ arch/arm/mach-imx/mach-cpuimx35.c                  |    9 +-
+ arch/arm/mach-imx/mach-cpuimx51sd.c                |    9 +-
+ arch/arm/mach-imx/mach-eukrea_cpuimx25.c           |   10 +-
+ arch/arm/mach-imx/mach-imx27_visstrim_m10.c        |   58 +-
+ arch/arm/mach-imx/mach-imx27ipcam.c                |    6 +-
+ arch/arm/mach-imx/mach-imx27lite.c                 |    6 +-
+ arch/arm/mach-imx/mach-imx53.c                     |   34 +-
+ arch/arm/mach-imx/mach-imx6q.c                     |   41 +-
+ arch/arm/mach-imx/mach-kzm_arm11_01.c              |    7 +-
+ arch/arm/mach-imx/mach-mx1ads.c                    |    7 +-
+ arch/arm/mach-imx/mach-mx21ads.c                   |    6 +-
+ arch/arm/mach-imx/mach-mx25_3ds.c                  |    8 +-
+ arch/arm/mach-imx/mach-mx27_3ds.c                  |   10 +-
+ arch/arm/mach-imx/mach-mx27ads.c                   |    6 +-
+ arch/arm/mach-imx/mach-mx31_3ds.c                  |   12 +-
+ arch/arm/mach-imx/mach-mx31ads.c                   |    5 +-
+ arch/arm/mach-imx/mach-mx31lilly.c                 |   11 +-
+ arch/arm/mach-imx/mach-mx31lite.c                  |   11 +-
+ arch/arm/mach-imx/mach-mx31moboard.c               |   14 +-
+ arch/arm/mach-imx/mach-mx35_3ds.c                  |    8 +-
+ arch/arm/mach-imx/mach-mx50_rdp.c                  |    7 +-
+ arch/arm/mach-imx/mach-mx51_3ds.c                  |    9 +-
+ arch/arm/mach-imx/mach-mx51_babbage.c              |    7 +-
+ arch/arm/mach-imx/mach-mxt_td60.c                  |    6 +-
+ arch/arm/mach-imx/mach-pca100.c                    |    8 +-
+ arch/arm/mach-imx/mach-pcm037.c                    |    8 +-
+ arch/arm/mach-imx/mach-pcm037_eet.c                |    5 +-
+ arch/arm/mach-imx/mach-pcm038.c                    |   13 +-
+ arch/arm/mach-imx/mach-pcm043.c                    |    9 +-
+ arch/arm/mach-imx/mach-qong.c                      |    6 +-
+ arch/arm/mach-imx/mach-scb9328.c                   |    7 +-
+ arch/arm/mach-imx/mach-vpr200.c                    |    7 +-
+ arch/arm/mach-imx/mm-imx1.c                        |    9 +-
+ arch/arm/mach-imx/mm-imx21.c                       |   14 +-
+ arch/arm/mach-imx/mm-imx25.c                       |   12 +-
+ arch/arm/mach-imx/mm-imx27.c                       |   14 +-
+ arch/arm/mach-imx/mm-imx3.c                        |   13 +-
+ arch/arm/mach-imx/mm-imx5.c                        |   32 +-
+ arch/arm/{plat-mxc/include/mach => mach-imx}/mx1.h |    0
+ .../arm/{plat-mxc/include/mach => mach-imx}/mx21.h |    0
+ .../arm/{plat-mxc/include/mach => mach-imx}/mx25.h |    0
+ .../arm/{plat-mxc/include/mach => mach-imx}/mx27.h |    0
+ .../arm/{plat-mxc/include/mach => mach-imx}/mx2x.h |    0
+ .../arm/{plat-mxc/include/mach => mach-imx}/mx31.h |    0
+ arch/arm/mach-imx/mx31lilly-db.c                   |    9 +-
+ arch/arm/mach-imx/mx31lite-db.c                    |    9 +-
+ arch/arm/mach-imx/mx31moboard-devboard.c           |    9 +-
+ arch/arm/mach-imx/mx31moboard-marxbot.c            |    9 +-
+ arch/arm/mach-imx/mx31moboard-smartbot.c           |   11 +-
+ .../arm/{plat-mxc/include/mach => mach-imx}/mx35.h |    0
+ .../arm/{plat-mxc/include/mach => mach-imx}/mx3x.h |    0
+ .../arm/{plat-mxc/include/mach => mach-imx}/mx50.h |    0
+ .../arm/{plat-mxc/include/mach => mach-imx}/mx51.h |    0
+ .../arm/{plat-mxc/include/mach => mach-imx}/mx53.h |    0
+ .../arm/{plat-mxc/include/mach => mach-imx}/mx6q.h |    4 -
+ arch/arm/{plat-mxc/include/mach => mach-imx}/mxc.h |    0
+ arch/arm/mach-imx/pcm970-baseboard.c               |    7 +-
+ arch/arm/mach-imx/platsmp.c                        |    5 +-
+ arch/arm/mach-imx/pm-imx27.c                       |    3 +-
+ arch/arm/mach-imx/pm-imx3.c                        |    7 +-
+ arch/arm/mach-imx/pm-imx5.c                        |    7 +-
+ arch/arm/mach-imx/pm-imx6q.c                       |    5 +-
+ arch/arm/{plat-mxc => mach-imx}/ssi-fiq-ksym.c     |    0
+ arch/arm/{plat-mxc => mach-imx}/ssi-fiq.S          |    0
+ arch/arm/{plat-mxc => mach-imx}/system.c           |    5 +-
+ arch/arm/{plat-mxc => mach-imx}/time.c             |    5 +-
+ arch/arm/{plat-mxc => mach-imx}/tzic.c             |    6 +-
+ arch/arm/{plat-mxc => mach-imx}/ulpi.c             |    2 +-
+ .../arm/{plat-mxc/include/mach => mach-imx}/ulpi.h |    0
+ arch/arm/mach-integrator/Kconfig                   |    2 +
+ arch/arm/mach-integrator/common.h                  |    8 +-
+ arch/arm/mach-integrator/core.c                    |  141 +-
+ arch/arm/mach-integrator/include/mach/irqs.h       |  109 +-
+ arch/arm/mach-integrator/include/mach/platform.h   |    1 -
+ arch/arm/mach-integrator/integrator_ap.c           |  163 +-
+ arch/arm/mach-integrator/integrator_cp.c           |  121 +-
+ arch/arm/mach-integrator/pci_v3.c                  |   32 +-
+ arch/arm/mach-kirkwood/Kconfig                     |   70 +
+ arch/arm/mach-kirkwood/Makefile                    |    9 +
+ arch/arm/mach-kirkwood/board-dnskw.c               |   54 -
+ arch/arm/mach-kirkwood/board-dockstar.c            |   29 -
+ arch/arm/mach-kirkwood/board-dreamplug.c           |   30 -
+ arch/arm/mach-kirkwood/board-dt.c                  |   34 +-
+ arch/arm/mach-kirkwood/board-goflexnet.c           |   37 -
+ arch/arm/mach-kirkwood/board-ib62x0.c              |   41 -
+ arch/arm/mach-kirkwood/board-iconnect.c            |   26 -
+ arch/arm/mach-kirkwood/board-iomega_ix2_200.c      |   28 -
+ arch/arm/mach-kirkwood/board-km_kirkwood.c         |   13 -
+ arch/arm/mach-kirkwood/board-lsxl.c                |   83 -
+ arch/arm/mach-kirkwood/board-mplcec4.c             |   44 +
+ arch/arm/mach-kirkwood/board-ns2.c                 |   86 +
+ arch/arm/mach-kirkwood/board-nsa310.c              |  101 +
+ arch/arm/mach-kirkwood/board-openblocks_a6.c       |   70 +
+ arch/arm/mach-kirkwood/board-ts219.c               |   29 -
+ arch/arm/mach-kirkwood/board-usi_topkick.c         |   81 +
+ arch/arm/mach-kirkwood/common.c                    |   12 +-
+ arch/arm/mach-kirkwood/common.h                    |   37 +-
+ arch/arm/mach-kirkwood/cpuidle.c                   |    2 +-
+ arch/arm/mach-kirkwood/dockstar-setup.c            |    2 +-
+ arch/arm/mach-kirkwood/irq.c                       |    1 +
+ arch/arm/mach-kirkwood/lacie_v2-common.c           |    1 +
+ arch/arm/mach-kirkwood/mpp.c                       |    4 +-
+ arch/arm/mach-kirkwood/netspace_v2-setup.c         |    4 +-
+ arch/arm/mach-kirkwood/openrd-setup.c              |   14 +-
+ arch/arm/mach-kirkwood/pcie.c                      |   42 +-
+ arch/arm/mach-kirkwood/sheevaplug-setup.c          |    2 +-
+ arch/arm/mach-kirkwood/t5325-setup.c               |    6 +-
+ arch/arm/mach-kirkwood/ts41x-setup.c               |    3 +-
+ arch/arm/mach-kirkwood/tsx1x-common.c              |    7 +-
+ arch/arm/mach-lpc32xx/clock.c                      |    8 +
+ arch/arm/mach-lpc32xx/include/mach/platform.h      |    1 +
+ arch/arm/mach-lpc32xx/irq.c                        |   23 +-
+ arch/arm/mach-mmp/Kconfig                          |    4 +
+ arch/arm/mach-mxs/mach-mxs.c                       |   56 +
+ arch/arm/mach-mxs/timer.c                          |   10 +-
+ arch/arm/mach-nomadik/Kconfig                      |    2 +-
+ arch/arm/mach-nomadik/board-nhk8815.c              |    7 +-
+ arch/arm/mach-nomadik/include/mach/irqs.h          |    2 +-
+ arch/arm/mach-omap1/Makefile                       |    3 +-
+ arch/arm/mach-omap1/board-ams-delta.c              |    1 -
+ arch/arm/mach-omap1/board-fsample.c                |   12 +-
+ arch/arm/mach-omap1/board-generic.c                |    1 -
+ arch/arm/mach-omap1/board-h2-mmc.c                 |    5 +-
+ arch/arm/mach-omap1/board-h2.c                     |    9 +-
+ arch/arm/mach-omap1/board-h3-mmc.c                 |    3 +-
+ arch/arm/mach-omap1/board-h3.c                     |    8 +-
+ arch/arm/mach-omap1/board-htcherald.c              |    3 +-
+ arch/arm/mach-omap1/board-innovator.c              |   30 +-
+ arch/arm/mach-omap1/board-nokia770.c               |    5 +-
+ arch/arm/mach-omap1/board-osk.c                    |    3 +-
+ arch/arm/mach-omap1/board-palmte.c                 |    6 +-
+ arch/arm/mach-omap1/board-palmtt.c                 |    8 +-
+ arch/arm/mach-omap1/board-palmz71.c                |    6 +-
+ arch/arm/mach-omap1/board-perseus2.c               |   12 +-
+ arch/arm/mach-omap1/board-sx1-mmc.c                |    3 +-
+ arch/arm/mach-omap1/board-sx1.c                    |    6 +-
+ arch/arm/mach-omap1/board-voiceblue.c              |    3 +-
+ arch/arm/mach-omap1/clock.c                        |  507 ++-
+ arch/arm/mach-omap1/clock.h                        |  178 +-
+ arch/arm/mach-omap1/clock_data.c                   |   16 +-
+ arch/arm/mach-omap1/common.h                       |    7 +-
+ arch/arm/mach-omap1/devices.c                      |   35 +-
+ arch/arm/mach-omap1/dma.c                          |    9 +-
+ arch/arm/mach-omap1/dma.h                          |   83 +
+ arch/arm/mach-omap1/flash.c                        |    2 +-
+ arch/arm/mach-omap1/fpga.c                         |    4 +-
+ arch/arm/mach-omap1/fpga.h                         |   52 +
+ arch/arm/mach-omap1/gpio15xx.c                     |    2 +
+ arch/arm/mach-omap1/gpio16xx.c                     |    2 +
+ arch/arm/mach-omap1/gpio7xx.c                      |    2 +
+ arch/arm/mach-omap1/i2c.c                          |   64 +-
+ arch/arm/mach-omap1/id.c                           |    2 +-
+ arch/arm/mach-omap1/include/mach/debug-macro.S     |    2 +-
+ arch/arm/mach-omap1/include/mach/entry-macro.S     |    2 -
+ arch/arm/mach-omap1/include/mach/gpio.h            |    3 -
+ arch/arm/mach-omap1/include/mach/hardware.h        |    9 +-
+ arch/arm/mach-omap1/include/mach/memory.h          |    2 +-
+ arch/arm/mach-omap1/include/mach/omap1510.h        |  113 +
+ arch/arm/mach-omap1/include/mach/serial.h          |   53 +
+ arch/arm/mach-omap1/include/mach/soc.h             |  229 ++
+ .../include/plat => mach-omap1/include/mach}/tc.h  |    0
+ arch/arm/mach-omap1/include/mach/uncompress.h      |  121 +-
+ arch/arm/mach-omap1/io.c                           |    5 +-
+ arch/arm/mach-omap1/iomap.h                        |    3 -
+ arch/arm/mach-omap1/irq.c                          |    2 +-
+ arch/arm/mach-omap1/lcd_dma.c                      |    4 +-
+ arch/arm/mach-omap1/mcbsp.c                        |    5 +-
+ arch/arm/mach-omap1/mmc.h                          |   18 +
+ arch/arm/mach-omap1/opp_data.c                     |    2 +-
+ arch/arm/mach-omap1/pm.c                           |   10 +-
+ arch/arm/mach-omap1/pm_bus.c                       |    3 +-
+ arch/arm/mach-omap1/reset.c                        |   41 +-
+ arch/arm/mach-omap1/serial.c                       |    1 -
+ arch/arm/mach-omap1/sleep.S                        |    2 +
+ arch/arm/mach-omap1/soc.h                          |    4 +
+ arch/arm/mach-omap1/sram-init.c                    |   76 +
+ arch/arm/mach-omap1/sram.h                         |    7 +
+ arch/arm/mach-omap1/timer32k.c                     |    1 +
+ arch/arm/mach-omap1/usb.c                          |    6 +-
+ arch/arm/mach-omap2/Kconfig                        |    9 +-
+ arch/arm/mach-omap2/Makefile                       |  130 +-
+ arch/arm/mach-omap2/am33xx.h                       |    1 +
+ arch/arm/mach-omap2/am35xx-emac.c                  |    2 +-
+ arch/arm/mach-omap2/board-2430sdp.c                |    6 +-
+ arch/arm/mach-omap2/board-3430sdp.c                |    8 +-
+ arch/arm/mach-omap2/board-3630sdp.c                |    5 +-
+ arch/arm/mach-omap2/board-4430sdp.c                |  163 +-
+ arch/arm/mach-omap2/board-am3517crane.c            |    3 +-
+ arch/arm/mach-omap2/board-am3517evm.c              |    4 +-
+ arch/arm/mach-omap2/board-apollon.c                |    6 +-
+ arch/arm/mach-omap2/board-cm-t35.c                 |   28 +-
+ arch/arm/mach-omap2/board-cm-t3517.c               |    8 +-
+ arch/arm/mach-omap2/board-devkit8000.c             |   13 +-
+ arch/arm/mach-omap2/board-flash.c                  |   52 +-
+ arch/arm/mach-omap2/board-flash.h                  |    8 +-
+ arch/arm/mach-omap2/board-generic.c                |   37 +-
+ arch/arm/mach-omap2/board-h4.c                     |   10 +-
+ arch/arm/mach-omap2/board-igep0020.c               |   13 +-
+ arch/arm/mach-omap2/board-ldp.c                    |   11 +-
+ arch/arm/mach-omap2/board-n8x0.c                   |   11 +-
+ arch/arm/mach-omap2/board-omap3beagle.c            |   18 +-
+ arch/arm/mach-omap2/board-omap3evm.c               |   13 +-
+ arch/arm/mach-omap2/board-omap3logic.c             |   11 +-
+ arch/arm/mach-omap2/board-omap3pandora.c           |    6 +-
+ arch/arm/mach-omap2/board-omap3stalker.c           |    5 +-
+ arch/arm/mach-omap2/board-omap3touchbook.c         |   13 +-
+ arch/arm/mach-omap2/board-omap4panda.c             |   75 +-
+ arch/arm/mach-omap2/board-overo.c                  |   13 +-
+ arch/arm/mach-omap2/board-rm680.c                  |   15 +-
+ arch/arm/mach-omap2/board-rx51-peripherals.c       |    7 +-
+ arch/arm/mach-omap2/board-rx51.c                   |   12 +-
+ arch/arm/mach-omap2/board-ti8168evm.c              |    7 +-
+ arch/arm/mach-omap2/board-zoom-debugboard.c        |    4 +-
+ arch/arm/mach-omap2/board-zoom-display.c           |    3 +-
+ arch/arm/mach-omap2/board-zoom-peripherals.c       |    3 +-
+ arch/arm/mach-omap2/board-zoom.c                   |   12 +-
+ .../arm/mach-omap2/{include/mach => }/board-zoom.h |    0
+ arch/arm/mach-omap2/cclock2420_data.c              | 1950 +++++++++++
+ arch/arm/mach-omap2/cclock2430_data.c              | 2065 +++++++++++
+ arch/arm/mach-omap2/cclock33xx_data.c              |  961 ++++++
+ arch/arm/mach-omap2/cclock3xxx_data.c              | 3595 +++++++++++++++++++
+ arch/arm/mach-omap2/cclock44xx_data.c              | 1987 +++++++++++
+ arch/arm/mach-omap2/clkt2xxx_apll.c                |   92 +-
+ arch/arm/mach-omap2/clkt2xxx_dpll.c                |   12 +-
+ arch/arm/mach-omap2/clkt2xxx_dpllcore.c            |   49 +-
+ arch/arm/mach-omap2/clkt2xxx_osc.c                 |   15 +-
+ arch/arm/mach-omap2/clkt2xxx_sys.c                 |    9 +-
+ arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c       |   85 +-
+ arch/arm/mach-omap2/clkt34xx_dpll3m2.c             |   13 +-
+ arch/arm/mach-omap2/clkt_clksel.c                  |  196 +-
+ arch/arm/mach-omap2/clkt_dpll.c                    |   30 +-
+ arch/arm/mach-omap2/clkt_iclk.c                    |   32 +-
+ arch/arm/mach-omap2/clock.c                        |  470 ++-
+ arch/arm/mach-omap2/clock.h                        |  452 ++-
+ arch/arm/mach-omap2/clock2420_data.c               | 1990 -----------
+ arch/arm/mach-omap2/clock2430.c                    |   12 +-
+ arch/arm/mach-omap2/clock2430_data.c               | 2089 -----------
+ arch/arm/mach-omap2/clock2xxx.c                    |   19 +-
+ arch/arm/mach-omap2/clock2xxx.h                    |   48 +-
+ arch/arm/mach-omap2/clock33xx_data.c               | 1112 ------
+ arch/arm/mach-omap2/clock34xx.c                    |   55 +-
+ arch/arm/mach-omap2/clock3517.c                    |   28 +-
+ arch/arm/mach-omap2/clock36xx.c                    |   24 +-
+ arch/arm/mach-omap2/clock36xx.h                    |    2 +-
+ arch/arm/mach-omap2/clock3xxx.c                    |    8 +-
+ arch/arm/mach-omap2/clock3xxx.h                    |    6 +-
+ arch/arm/mach-omap2/clock3xxx_data.c               | 3617 --------------------
+ arch/arm/mach-omap2/clock44xx_data.c               | 3402 ------------------
+ arch/arm/mach-omap2/clock_common_data.c            |   22 +-
+ arch/arm/mach-omap2/clockdomain.c                  |   92 +-
+ arch/arm/mach-omap2/clockdomain.h                  |    5 +-
+ arch/arm/mach-omap2/clockdomain2xxx_3xxx.c         |  339 --
+ arch/arm/mach-omap2/clockdomain33xx.c              |   74 -
+ arch/arm/mach-omap2/clockdomain44xx.c              |  151 -
+ arch/arm/mach-omap2/clockdomains2420_data.c        |    1 +
+ arch/arm/mach-omap2/clockdomains2430_data.c        |    1 +
+ arch/arm/mach-omap2/clockdomains3xxx_data.c        |    1 +
+ arch/arm/mach-omap2/cm-regbits-24xx.h              |    7 +
+ arch/arm/mach-omap2/cm-regbits-34xx.h              |   31 +
+ arch/arm/mach-omap2/cm.h                           |   30 +-
+ arch/arm/mach-omap2/cm2xxx.c                       |  381 +++
+ arch/arm/mach-omap2/cm2xxx.h                       |   70 +
+ arch/arm/mach-omap2/cm2xxx_3xxx.h                  |  126 +-
+ arch/arm/mach-omap2/cm33xx.c                       |   58 +-
+ arch/arm/mach-omap2/{cm2xxx_3xxx.c => cm3xxx.c}    |  371 +-
+ arch/arm/mach-omap2/cm3xxx.h                       |   91 +
+ arch/arm/mach-omap2/cm_common.c                    |  140 +
+ arch/arm/mach-omap2/cminst44xx.c                   |  142 +-
+ arch/arm/mach-omap2/cminst44xx.h                   |    2 +
+ arch/arm/mach-omap2/common-board-devices.c         |   46 -
+ arch/arm/mach-omap2/common-board-devices.h         |    1 -
+ arch/arm/mach-omap2/common.c                       |  187 +-
+ arch/arm/mach-omap2/common.h                       |  150 +-
+ arch/arm/mach-omap2/control.c                      |   18 +-
+ arch/arm/mach-omap2/control.h                      |    3 +
+ arch/arm/mach-omap2/cpuidle34xx.c                  |    1 -
+ arch/arm/mach-omap2/devices.c                      |   34 +-
+ arch/arm/mach-omap2/display.c                      |    9 +-
+ arch/arm/mach-omap2/dma.c                          |   11 +-
+ arch/arm/mach-omap2/dma.h                          |  131 +
+ arch/arm/mach-omap2/dpll3xxx.c                     |  185 +-
+ arch/arm/mach-omap2/dpll44xx.c                     |   23 +-
+ arch/arm/mach-omap2/drm.c                          |    4 +-
+ arch/arm/mach-omap2/dsp.c                          |    2 +-
+ arch/arm/mach-omap2/dss-common.c                   |  276 ++
+ arch/arm/mach-omap2/dss-common.h                   |   14 +
+ arch/arm/mach-omap2/gpio.c                         |    6 +-
+ arch/arm/mach-omap2/gpmc-nand.c                    |   85 +-
+ arch/arm/mach-omap2/gpmc-nand.h                    |   27 +
+ arch/arm/mach-omap2/gpmc-onenand.c                 |  343 +-
+ arch/arm/mach-omap2/gpmc-onenand.h                 |   24 +
+ arch/arm/mach-omap2/gpmc-smc91x.c                  |   45 +-
+ arch/arm/mach-omap2/gpmc-smsc911x.c                |    2 +-
+ arch/arm/mach-omap2/gpmc.c                         |  837 +++--
+ .../{plat-omap/include/plat => mach-omap2}/gpmc.h  |  168 +-
+ arch/arm/mach-omap2/hdq1w.c                        |    8 +-
+ arch/arm/mach-omap2/hdq1w.h                        |    2 +-
+ arch/arm/mach-omap2/hsmmc.c                        |    8 +-
+ arch/arm/mach-omap2/hwspinlock.c                   |    4 +-
+ arch/arm/mach-omap2/i2c.c                          |   73 +-
+ arch/arm/mach-omap2/i2c.h                          |   42 +
+ arch/arm/mach-omap2/id.c                           |   32 +-
+ arch/arm/mach-omap2/include/mach/debug-macro.S     |    2 +-
+ arch/arm/mach-omap2/include/mach/gpio.h            |    3 -
+ .../plat => mach-omap2/include/mach}/serial.h      |   20 -
+ arch/arm/mach-omap2/include/mach/uncompress.h      |  175 +-
+ arch/arm/mach-omap2/io.c                           |  119 +-
+ arch/arm/mach-omap2/mcbsp.c                        |    9 +-
+ arch/arm/mach-omap2/mmc.h                          |   23 +
+ arch/arm/mach-omap2/msdi.c                         |   11 +-
+ arch/arm/mach-omap2/mux.c                          |    3 +-
+ arch/arm/mach-omap2/omap-headsmp.S                 |   38 +
+ arch/arm/mach-omap2/omap-mpuss-lowpower.c          |   10 +-
+ arch/arm/{plat-omap => mach-omap2}/omap-pm-noop.c  |    5 +-
+ .../include/plat => mach-omap2}/omap-pm.h          |    0
+ arch/arm/mach-omap2/omap-secure.c                  |    1 -
+ arch/arm/mach-omap2/omap-secure.h                  |    7 +
+ arch/arm/mach-omap2/omap-smp.c                     |   41 +-
+ arch/arm/mach-omap2/omap2-restart.c                |   65 +
+ arch/arm/mach-omap2/omap3-restart.c                |   36 +
+ arch/arm/mach-omap2/omap4-common.c                 |   69 +-
+ arch/arm/{plat-omap => mach-omap2}/omap_device.c   |    5 +-
+ .../include/plat => mach-omap2}/omap_device.h      |    2 +-
+ arch/arm/mach-omap2/omap_hwmod.c                   |  126 +-
+ .../include/plat => mach-omap2}/omap_hwmod.h       |    1 -
+ arch/arm/mach-omap2/omap_hwmod_2420_data.c         |   13 +-
+ arch/arm/mach-omap2/omap_hwmod_2430_data.c         |   12 +-
+ .../omap_hwmod_2xxx_3xxx_interconnect_data.c       |    3 +-
+ .../mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c |    9 +-
+ .../mach-omap2/omap_hwmod_2xxx_interconnect_data.c |    4 +-
+ arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c |   21 +-
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c         |   10 +-
+ arch/arm/mach-omap2/omap_hwmod_3xxx_data.c         |   55 +-
+ arch/arm/mach-omap2/omap_hwmod_44xx_data.c         |   16 +-
+ arch/arm/mach-omap2/omap_hwmod_common_data.c       |    2 +-
+ arch/arm/mach-omap2/omap_hwmod_common_data.h       |    2 +-
+ arch/arm/mach-omap2/omap_opp_data.h                |   11 +-
+ arch/arm/mach-omap2/omap_phy_internal.c            |   36 +-
+ arch/arm/mach-omap2/omap_twl.c                     |   74 +-
+ arch/arm/mach-omap2/opp.c                          |    2 +-
+ arch/arm/mach-omap2/opp3xxx_data.c                 |    1 +
+ arch/arm/mach-omap2/opp4xxx_data.c                 |   98 +-
+ arch/arm/mach-omap2/pm-debug.c                     |    5 +-
+ arch/arm/mach-omap2/pm.c                           |   37 +-
+ arch/arm/mach-omap2/pm.h                           |   19 +
+ arch/arm/mach-omap2/pm24xx.c                       |   17 +-
+ arch/arm/mach-omap2/pm34xx.c                       |   15 +-
+ arch/arm/mach-omap2/pm44xx.c                       |    8 +-
+ arch/arm/mach-omap2/pmu.c                          |    5 +-
+ arch/arm/mach-omap2/powerdomain.c                  |    2 -
+ arch/arm/mach-omap2/powerdomain.h                  |    2 -
+ arch/arm/mach-omap2/powerdomain2xxx_3xxx.c         |  242 --
+ arch/arm/mach-omap2/powerdomain33xx.c              |  229 --
+ arch/arm/mach-omap2/powerdomain44xx.c              |  285 --
+ arch/arm/mach-omap2/powerdomains2xxx_data.c        |    1 +
+ arch/arm/mach-omap2/prcm-common.h                  |   22 -
+ arch/arm/mach-omap2/prcm.c                         |  188 -
+ arch/arm/mach-omap2/prcm_mpu44xx.c                 |   17 +
+ arch/arm/mach-omap2/prcm_mpu44xx.h                 |    9 +-
+ arch/arm/mach-omap2/prm-regbits-24xx.h             |    8 +-
+ arch/arm/mach-omap2/prm-regbits-34xx.h             |   13 +-
+ arch/arm/mach-omap2/prm.h                          |   77 +-
+ arch/arm/mach-omap2/prm2xxx.c                      |  139 +
+ arch/arm/mach-omap2/prm2xxx.h                      |  134 +
+ arch/arm/mach-omap2/prm2xxx_3xxx.c                 |  332 +-
+ arch/arm/mach-omap2/prm2xxx_3xxx.h                 |  285 +-
+ arch/arm/mach-omap2/prm33xx.c                      |  204 +-
+ arch/arm/mach-omap2/prm3xxx.c                      |  417 +++
+ arch/arm/mach-omap2/prm3xxx.h                      |  162 +
+ arch/arm/mach-omap2/prm44xx.c                      |  356 +-
+ arch/arm/mach-omap2/prm44xx.h                      |    2 +
+ arch/arm/mach-omap2/prm_common.c                   |  118 +-
+ arch/arm/mach-omap2/prminst44xx.h                  |    2 +
+ arch/arm/mach-omap2/scrm44xx.h                     |    2 +
+ arch/arm/mach-omap2/sdram-hynix-h8mbx00u0mer-0em.h |    2 +-
+ arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h  |    2 +-
+ arch/arm/mach-omap2/sdram-nokia.c                  |    4 +-
+ arch/arm/mach-omap2/sdram-numonyx-m65kxxxxam.h     |    2 +-
+ .../mach-omap2/sdram-qimonda-hyb18m512160af-6.h    |    2 +-
+ arch/arm/mach-omap2/sdrc.c                         |   13 +-
+ arch/arm/mach-omap2/sdrc.h                         |  148 +-
+ arch/arm/mach-omap2/sdrc2xxx.c                     |    7 +-
+ arch/arm/mach-omap2/serial.c                       |   13 +-
+ arch/arm/mach-omap2/serial.h                       |    1 +
+ arch/arm/mach-omap2/sleep34xx.S                    |    7 +-
+ arch/arm/mach-omap2/soc.h                          |  464 ++-
+ arch/arm/mach-omap2/sr_device.c                    |   17 +-
+ arch/arm/mach-omap2/sram.c                         |  305 ++
+ arch/arm/mach-omap2/sram.h                         |   83 +
+ arch/arm/mach-omap2/sram242x.S                     |    4 +-
+ arch/arm/mach-omap2/sram243x.S                     |    4 +-
+ arch/arm/mach-omap2/sram34xx.S                     |    2 +-
+ arch/arm/mach-omap2/ti81xx.h                       |    9 +
+ arch/arm/mach-omap2/timer.c                        |  272 +-
+ arch/arm/mach-omap2/twl-common.c                   |    3 -
+ arch/arm/mach-omap2/usb-host.c                     |    6 +-
+ arch/arm/mach-omap2/usb-musb.c                     |    8 +-
+ arch/arm/mach-omap2/usb-tusb6010.c                 |  184 +-
+ arch/arm/mach-omap2/usb.h                          |   82 +
+ arch/arm/mach-omap2/vc.c                           |  453 ++-
+ arch/arm/mach-omap2/vc.h                           |    8 +-
+ arch/arm/mach-omap2/vc3xxx_data.c                  |   22 +
+ arch/arm/mach-omap2/vc44xx_data.c                  |   28 +
+ arch/arm/mach-omap2/voltage.h                      |   44 +-
+ arch/arm/mach-omap2/voltagedomains3xxx_data.c      |    5 +
+ arch/arm/mach-omap2/voltagedomains44xx_data.c      |   25 +-
+ arch/arm/mach-omap2/vp.c                           |   19 +-
+ arch/arm/mach-omap2/vp.h                           |    7 +
+ arch/arm/mach-omap2/vp3xxx_data.c                  |   10 +
+ arch/arm/mach-omap2/vp44xx_data.c                  |   15 +
+ arch/arm/mach-omap2/wd_timer.c                     |   40 +-
+ arch/arm/mach-omap2/wd_timer.h                     |    2 +-
+ arch/arm/mach-orion5x/Kconfig                      |   14 +-
+ arch/arm/mach-orion5x/Makefile                     |    4 +-
+ arch/arm/mach-orion5x/board-dt.c                   |   79 +
+ arch/arm/mach-orion5x/common.c                     |    4 +-
+ arch/arm/mach-orion5x/common.h                     |    9 +
+ arch/arm/mach-orion5x/edmini_v2-setup.c            |   88 +-
+ arch/arm/mach-pxa/Kconfig                          |   34 -
+ arch/arm/mach-pxa/Makefile                         |    3 -
+ arch/arm/mach-pxa/clock.h                          |    2 +-
+ arch/arm/mach-pxa/devices.c                        |    8 +-
+ arch/arm/mach-pxa/include/mach/hardware.h          |   28 -
+ arch/arm/mach-pxa/include/mach/irqs.h              |    1 -
+ arch/arm/mach-pxa/include/mach/pxa3xx.h            |    1 -
+ arch/arm/mach-pxa/include/mach/pxa95x.h            |    7 -
+ arch/arm/mach-pxa/pxa25x.c                         |    6 +
+ arch/arm/mach-pxa/pxa3xx-ulpi.c                    |   13 +-
+ arch/arm/mach-pxa/pxa95x.c                         |  295 --
+ arch/arm/mach-pxa/saarb.c                          |  115 -
+ arch/arm/mach-pxa/tavorevb3.c                      |  136 -
+ arch/arm/mach-s3c24xx/Kconfig                      |    2 +-
+ arch/arm/mach-s3c24xx/clock-s3c2443.c              |    6 -
+ arch/arm/mach-s3c64xx/Kconfig                      |    2 +
+ arch/arm/mach-s3c64xx/clock.c                      |   20 +-
+ arch/arm/mach-s3c64xx/common.c                     |    1 -
+ arch/arm/mach-s3c64xx/mach-crag6410-module.c       |  141 +-
+ arch/arm/mach-s3c64xx/mach-crag6410.c              |   29 +-
+ arch/arm/mach-s5p64x0/common.c                     |    2 -
+ arch/arm/mach-s5pv210/common.c                     |    2 -
+ arch/arm/mach-s5pv210/mach-goni.c                  |    1 -
+ arch/arm/mach-shmobile/Kconfig                     |   31 +-
+ arch/arm/mach-shmobile/Makefile                    |    8 -
+ arch/arm/mach-shmobile/board-ap4evb.c              |  139 +-
+ arch/arm/mach-shmobile/board-armadillo800eva.c     |   46 +-
+ arch/arm/mach-shmobile/board-g3evm.c               |  343 --
+ arch/arm/mach-shmobile/board-g4evm.c               |  384 ---
+ arch/arm/mach-shmobile/board-kzm9g.c               |   14 +-
+ arch/arm/mach-shmobile/board-mackerel.c            |   88 +-
+ arch/arm/mach-shmobile/board-marzen.c              |  211 +-
+ arch/arm/mach-shmobile/clock-r8a7740.c             |   34 +
+ arch/arm/mach-shmobile/clock-r8a7779.c             |   23 +-
+ arch/arm/mach-shmobile/clock-sh7367.c              |  355 --
+ arch/arm/mach-shmobile/clock-sh7372.c              |  106 +-
+ arch/arm/mach-shmobile/clock-sh7377.c              |  366 --
+ arch/arm/mach-shmobile/include/mach/common.h       |   18 -
+ arch/arm/mach-shmobile/include/mach/r8a7779.h      |    2 +-
+ arch/arm/mach-shmobile/include/mach/sh7367.h       |  332 --
+ arch/arm/mach-shmobile/include/mach/sh7372.h       |    8 +-
+ arch/arm/mach-shmobile/include/mach/sh7377.h       |  360 --
+ arch/arm/mach-shmobile/intc-sh7367.c               |  413 ---
+ arch/arm/mach-shmobile/intc-sh7377.c               |  592 ----
+ arch/arm/mach-shmobile/pfc-r8a7779.c               |   16 +-
+ arch/arm/mach-shmobile/pfc-sh7367.c                | 1727 ----------
+ arch/arm/mach-shmobile/pfc-sh7377.c                | 1688 ---------
+ arch/arm/mach-shmobile/setup-r8a7740.c             |   24 +-
+ arch/arm/mach-shmobile/setup-r8a7779.c             |   77 +
+ arch/arm/mach-shmobile/setup-sh7367.c              |  481 ---
+ arch/arm/mach-shmobile/setup-sh7372.c              |   26 +-
+ arch/arm/mach-shmobile/setup-sh7377.c              |  549 ---
+ arch/arm/mach-socfpga/Kconfig                      |    1 +
+ arch/arm/mach-socfpga/Makefile                     |    1 +
+ .../include/mach/irqs.h => mach-socfpga/core.h}    |   22 +-
+ arch/arm/mach-socfpga/headsmp.S                    |   25 +
+ arch/arm/mach-socfpga/platsmp.c                    |  116 +
+ arch/arm/mach-socfpga/socfpga.c                    |   54 +-
+ arch/arm/mach-spear13xx/include/mach/spear.h       |    8 -
+ arch/arm/mach-spear13xx/spear1310.c                |   16 +-
+ arch/arm/mach-spear13xx/spear13xx.c                |    2 -
+ arch/arm/mach-spear3xx/include/mach/irqs.h         |   10 +-
+ arch/arm/mach-spear3xx/spear300.c                  |  103 -
+ arch/arm/mach-spear3xx/spear310.c                  |  202 --
+ arch/arm/mach-spear3xx/spear320.c                  |  205 +-
+ arch/arm/mach-spear3xx/spear3xx.c                  |    4 +
+ arch/arm/mach-sunxi/Kconfig                        |    9 +
+ arch/arm/mach-sunxi/Makefile                       |    1 +
+ arch/arm/mach-sunxi/Makefile.boot                  |    1 +
+ arch/arm/mach-sunxi/sunxi.c                        |   95 +
+ arch/arm/mach-sunxi/sunxi.h                        |   20 +
+ arch/arm/mach-tegra/Kconfig                        |   51 -
+ arch/arm/mach-tegra/Makefile                       |   13 +-
+ arch/arm/mach-tegra/apbio.c                        |    5 +-
+ arch/arm/mach-tegra/board-dt-tegra20.c             |   27 +-
+ arch/arm/mach-tegra/board-dt-tegra30.c             |   28 +-
+ arch/arm/mach-tegra/clock.c                        |    2 -
+ arch/arm/mach-tegra/common.c                       |   33 +-
+ arch/arm/mach-tegra/cpu-tegra.c                    |    3 -
+ arch/arm/mach-tegra/cpuidle-tegra20.c              |   66 +
+ arch/arm/mach-tegra/cpuidle-tegra30.c              |  188 +
+ arch/arm/mach-tegra/cpuidle.c                      |   85 +-
+ arch/arm/mach-tegra/cpuidle.h                      |   32 +
+ arch/arm/mach-tegra/flowctrl.c                     |   50 +-
+ arch/arm/mach-tegra/flowctrl.h                     |    8 +
+ arch/arm/mach-tegra/fuse.c                         |   52 +-
+ arch/arm/mach-tegra/fuse.h                         |   16 +
+ arch/arm/mach-tegra/headsmp.S                      |   74 +-
+ arch/arm/mach-tegra/include/mach/debug-macro.S     |  100 -
+ arch/arm/mach-tegra/include/mach/dma.h             |   54 -
+ arch/arm/mach-tegra/include/mach/irqs.h            |  182 -
+ arch/arm/mach-tegra/include/mach/powergate.h       |    2 +
+ arch/arm/mach-tegra/include/mach/uncompress.h      |   67 +-
+ arch/arm/mach-tegra/io.c                           |    3 +-
+ arch/arm/mach-tegra/{include/mach => }/iomap.h     |   16 -
+ arch/arm/mach-tegra/{include/mach => }/irammap.h   |    9 -
+ arch/arm/mach-tegra/irq.c                          |    3 +-
+ arch/arm/mach-tegra/pcie.c                         |    5 +-
+ arch/arm/mach-tegra/platsmp.c                      |    3 +-
+ arch/arm/mach-tegra/pm.c                           |  216 ++
+ arch/arm/mach-tegra/pm.h                           |   35 +
+ arch/arm/mach-tegra/pmc.c                          |    2 +-
+ arch/arm/mach-tegra/powergate.c                    |    2 +-
+ arch/arm/mach-tegra/reset.c                        |   11 +-
+ arch/arm/mach-tegra/reset.h                        |    9 +
+ .../mach-tegra/{sleep-t20.S => sleep-tegra20.S}    |    2 -
+ .../mach-tegra/{sleep-t30.S => sleep-tegra30.S}    |   68 +-
+ arch/arm/mach-tegra/sleep.S                        |   80 +-
+ arch/arm/mach-tegra/sleep.h                        |   39 +-
+ arch/arm/mach-tegra/tegra20_clocks.c               |    3 +-
+ arch/arm/mach-tegra/tegra20_clocks_data.c          |   13 +-
+ arch/arm/mach-tegra/tegra20_speedo.c               |  109 +
+ arch/arm/mach-tegra/tegra2_emc.c                   |    2 -
+ arch/arm/mach-tegra/tegra30_clocks.c               |  215 +-
+ arch/arm/mach-tegra/tegra30_clocks.h               |    1 +
+ arch/arm/mach-tegra/tegra30_clocks_data.c          |   51 +-
+ arch/arm/mach-tegra/tegra30_speedo.c               |  292 ++
+ arch/arm/mach-tegra/tegra_cpu_car.h                |   37 +
+ arch/arm/mach-tegra/timer.c                        |   78 +-
+ arch/arm/mach-u300/core.c                          |    2 -
+ arch/arm/mach-ux500/Kconfig                        |    2 +-
+ arch/arm/mach-ux500/board-mop500-audio.c           |   19 +-
+ arch/arm/mach-ux500/board-mop500-pins.c            |  425 ++-
+ arch/arm/mach-ux500/board-mop500-sdi.c             |    2 +-
+ arch/arm/mach-ux500/board-mop500.c                 |  156 +-
+ arch/arm/mach-ux500/board-mop500.h                 |   10 +-
+ arch/arm/mach-ux500/cpu-db8500.c                   |  116 +-
+ arch/arm/mach-ux500/cpu.c                          |    3 +
+ arch/arm/mach-ux500/devices-common.c               |    1 +
+ arch/arm/mach-ux500/devices-db8500.c               |    4 +-
+ arch/arm/mach-ux500/devices-db8500.h               |    1 +
+ arch/arm/mach-ux500/include/mach/irqs.h            |    2 +-
+ arch/arm/mach-ux500/include/mach/msp.h             |    2 +-
+ arch/arm/mach-ux500/timer.c                        |    5 +-
+ arch/arm/mach-ux500/usb.c                          |    4 +-
+ arch/arm/mach-versatile/core.c                     |    2 +-
+ arch/arm/mach-vexpress/Kconfig                     |    4 +-
+ arch/arm/mach-vexpress/Makefile                    |    2 +-
+ arch/arm/mach-vexpress/ct-ca9x4.c                  |   41 +-
+ arch/arm/mach-vexpress/include/mach/motherboard.h  |   81 -
+ arch/arm/mach-vexpress/platsmp.c                   |    3 +-
+ arch/arm/mach-vexpress/reset.c                     |  141 +
+ arch/arm/mach-vexpress/v2m.c                       |  349 +-
+ arch/arm/mach-vt8500/Kconfig                       |   12 +
+ arch/arm/mach-vt8500/common.h                      |    3 +
+ arch/arm/mach-vt8500/include/mach/entry-macro.S    |   26 -
+ arch/arm/mach-vt8500/include/mach/hardware.h       |   12 -
+ arch/arm/mach-vt8500/include/mach/i8042.h          |   18 -
+ arch/arm/mach-vt8500/include/mach/restart.h        |   17 -
+ arch/arm/mach-vt8500/irq.c                         |  108 +-
+ arch/arm/mach-vt8500/timer.c                       |    2 +-
+ arch/arm/mach-vt8500/vt8500.c                      |    3 +-
+ arch/arm/mach-zynq/include/mach/hardware.h         |   18 -
+ arch/arm/mach-zynq/include/mach/irqs.h             |   21 -
+ arch/arm/mach-zynq/include/mach/timex.h            |   23 -
+ arch/arm/plat-mxc/Kconfig                          |   89 -
+ arch/arm/plat-mxc/Makefile                         |   24 -
+ arch/arm/plat-mxc/devices/platform-mx2-emma.c      |   40 +
+ arch/arm/plat-mxc/include/mach/debug-macro.S       |   51 -
+ arch/arm/plat-mxc/include/mach/irqs.h              |   21 -
+ arch/arm/plat-mxc/include/mach/uncompress.h        |  132 -
+ arch/arm/plat-nomadik/Kconfig                      |   29 -
+ arch/arm/plat-nomadik/Makefile                     |    5 -
+ arch/arm/plat-omap/Makefile                        |    4 +-
+ arch/arm/plat-omap/clock.c                         |  544 ---
+ arch/arm/plat-omap/common.c                        |   46 -
+ arch/arm/plat-omap/counter_32k.c                   |    3 -
+ arch/arm/plat-omap/debug-devices.c                 |    3 +-
+ arch/arm/plat-omap/debug-leds.c                    |   25 +-
+ arch/arm/plat-omap/dma.c                           |  132 +-
+ arch/arm/plat-omap/dmtimer.c                       |  190 +-
+ arch/arm/plat-omap/fb.c                            |    1 -
+ arch/arm/plat-omap/i2c.c                           |  174 +-
+ .../include/{plat/dma.h => plat-omap/dma-omap.h}   |  201 +-
+ arch/arm/plat-omap/include/plat/clkdev_omap.h      |   51 -
+ arch/arm/plat-omap/include/plat/clock.h            |  309 --
+ arch/arm/plat-omap/include/plat/common.h           |   42 -
+ arch/arm/plat-omap/include/plat/counter-32k.h      |    1 +
+ arch/arm/plat-omap/include/plat/cpu.h              |  468 +--
+ .../include/plat}/debug-devices.h                  |    7 -
+ arch/arm/plat-omap/include/plat/dma-44xx.h         |  147 -
+ arch/arm/plat-omap/include/plat/dmtimer.h          |   75 +-
+ arch/arm/plat-omap/include/plat/fpga.h             |  193 --
+ arch/arm/plat-omap/include/plat/i2c.h              |   30 +-
+ arch/arm/plat-omap/include/plat/multi.h            |  120 -
+ arch/arm/plat-omap/include/plat/omap-secure.h      |   14 -
+ arch/arm/plat-omap/include/plat/prcm.h             |   37 -
+ arch/arm/plat-omap/include/plat/sdrc.h             |  157 -
+ arch/arm/plat-omap/include/plat/sram.h             |   97 +-
+ arch/arm/plat-omap/include/plat/uncompress.h       |  204 --
+ arch/arm/plat-omap/include/plat/usb.h              |  179 -
+ arch/arm/plat-omap/sram.c                          |  366 +-
+ arch/arm/plat-omap/sram.h                          |    6 -
+ arch/arm/plat-orion/irq.c                          |    6 +-
+ arch/arm/plat-pxa/Makefile                         |    1 -
+ arch/arm/plat-pxa/include/plat/mfp.h               |    4 +-
+ arch/arm/plat-samsung/adc.c                        |   48 +-
+ arch/arm/plat-samsung/clock.c                      |   75 +-
+ arch/arm/plat-samsung/devs.c                       |    5 +-
+ arch/arm/plat-samsung/include/plat/cpu.h           |    8 +
+ arch/arm/plat-samsung/include/plat/devs.h          |    2 -
+ arch/arm/plat-samsung/include/plat/gpio-core.h     |    2 +
+ arch/arm/plat-samsung/include/plat/mfc.h           |   11 +
+ arch/arm/plat-samsung/s5p-dev-mfc.c                |   34 +
+ arch/arm/plat-samsung/s5p-irq-gpioint.c            |    8 +-
+ arch/arm/plat-spear/Makefile                       |    2 +-
+ arch/arm/plat-spear/shirq.c                        |  118 -
+ arch/arm/plat-versatile/Kconfig                    |   11 +-
+ arch/arm/plat-versatile/Makefile                   |    1 -
+ arch/avr32/mach-at32ap/include/mach/board.h        |    8 -
+ drivers/amba/tegra-ahb.c                           |    1 +
+ drivers/ata/pata_at91.c                            |    2 +-
+ drivers/char/hw_random/Kconfig                     |    2 +-
+ drivers/char/hw_random/omap-rng.c                  |    2 -
+ drivers/clk/Kconfig                                |   16 +-
+ drivers/clk/Makefile                               |    2 +
+ drivers/clk/clk-bcm2835.c                          |    2 +-
+ drivers/clk/clk-fixed-rate.c                       |    2 +-
+ drivers/clk/clk-prima2.c                           |   84 +-
+ drivers/clk/clk-sunxi.c                            |   30 +
+ drivers/clk/clk-twl6040.c                          |  126 +
+ drivers/clk/clk.c                                  |   20 +-
+ drivers/clk/spear/clk-vco-pll.c                    |    2 +-
+ drivers/clk/spear/spear1310_clock.c                |    1 +
+ drivers/clk/ux500/clk-prcmu.c                      |   55 +
+ drivers/clk/ux500/clk.h                            |    6 +
+ drivers/clk/ux500/u8500_clk.c                      |   16 +-
+ drivers/clk/versatile/Makefile                     |    2 +
+ drivers/clk/versatile/clk-vexpress-osc.c           |  146 +
+ drivers/clk/versatile/clk-vexpress.c               |  142 +
+ drivers/clocksource/Kconfig                        |   20 +-
+ drivers/clocksource/Makefile                       |    2 +
+ .../timer.c => drivers/clocksource/nomadik-mtu.c   |   19 +-
+ drivers/clocksource/sunxi_timer.c                  |  170 +
+ drivers/cpuidle/Kconfig                            |   10 +
+ drivers/cpuidle/Makefile                           |    2 +
+ drivers/cpuidle/cpuidle-calxeda.c                  |  161 +
+ drivers/crypto/omap-aes.c                          |    8 +-
+ drivers/crypto/omap-sham.c                         |   10 +-
+ drivers/crypto/tegra-aes.c                         |    2 -
+ drivers/crypto/ux500/cryp/cryp_core.c              |    3 +-
+ drivers/dma/imx-dma.c                              |  137 +-
+ drivers/dma/imx-sdma.c                             |    1 -
+ drivers/dma/ipu/ipu_idmac.c                        |    3 +-
+ drivers/dma/ipu/ipu_irq.c                          |    3 +-
+ drivers/dma/omap-dma.c                             |    5 +-
+ drivers/dma/ste_dma40.c                            |    3 +-
+ drivers/dma/ste_dma40_ll.c                         |    2 +-
+ drivers/gpio/Kconfig                               |    2 +-
+ drivers/gpio/gpio-pxa.c                            |    2 +-
+ drivers/gpio/gpio-samsung.c                        |   68 +-
+ drivers/hwmon/Kconfig                              |    8 +
+ drivers/hwmon/Makefile                             |    1 +
+ drivers/hwmon/vexpress.c                           |  229 ++
+ drivers/i2c/busses/i2c-imx.c                       |   40 +-
+ drivers/input/keyboard/Kconfig                     |    2 +-
+ drivers/input/touchscreen/atmel_tsadcc.c           |    2 +-
+ drivers/iommu/tegra-smmu.c                         |    4 +-
+ drivers/irqchip/Kconfig                            |    9 +-
+ drivers/irqchip/Makefile                           |    5 +-
+ drivers/irqchip/irq-sunxi.c                        |  150 +
+ .../irqchip/irq-versatile-fpga.c                   |   54 +-
+ drivers/irqchip/spear-shirq.c                      |  316 ++
+ drivers/leds/Kconfig                               |    4 +-
+ drivers/leds/leds-ns2.c                            |   78 +-
+ drivers/media/platform/omap/omap_vout.c            |    2 +-
+ drivers/media/platform/omap/omap_vout_vrfb.c       |    4 +-
+ drivers/media/platform/omap3isp/isphist.c          |    2 +
+ drivers/media/platform/omap3isp/ispstat.h          |    2 +-
+ drivers/media/platform/omap3isp/ispvideo.c         |    1 -
+ drivers/media/platform/soc_camera/mx2_camera.c     |  134 +-
+ drivers/media/platform/soc_camera/mx3_camera.c     |    2 +-
+ drivers/media/platform/soc_camera/omap1_camera.c   |    3 +-
+ drivers/media/rc/ir-rx51.c                         |    1 -
+ drivers/mfd/Kconfig                                |    6 +
+ drivers/mfd/Makefile                               |    1 +
+ drivers/mfd/ab8500-core.c                          |   13 +-
+ drivers/mfd/db8500-prcmu.c                         |   16 +-
+ drivers/mfd/menelaus.c                             |    2 +-
+ drivers/mfd/omap-usb-host.c                        |    5 +-
+ drivers/mfd/omap-usb-tll.c                         |    2 +-
+ drivers/mfd/omap-usb.h                             |    2 +
+ drivers/mfd/vexpress-config.c                      |  277 ++
+ drivers/mfd/vexpress-sysreg.c                      |  552 +++
+ drivers/mmc/host/atmel-mci.c                       |    2 +-
+ drivers/mmc/host/mxcmmc.c                          |   31 +-
+ drivers/mmc/host/omap.c                            |   35 +-
+ drivers/mmc/host/omap_hsmmc.c                      |    4 +-
+ drivers/mtd/maps/Kconfig                           |    7 -
+ drivers/mtd/maps/Makefile                          |    1 -
+ drivers/mtd/maps/cdb89712.c                        |  278 --
+ drivers/mtd/nand/Kconfig                           |   15 +-
+ drivers/mtd/nand/Makefile                          |    2 -
+ drivers/mtd/nand/autcpu12.c                        |  237 --
+ drivers/mtd/nand/mxc_nand.c                        |   96 +-
+ drivers/mtd/nand/omap2.c                           |  129 +-
+ drivers/mtd/nand/spia.c                            |  176 -
+ drivers/mtd/onenand/omap2.c                        |   47 +-
+ drivers/net/can/at91_can.c                         |    3 +-
+ drivers/pcmcia/at91_cf.c                           |    2 +-
+ drivers/pcmcia/omap_cf.c                           |    2 +-
+ drivers/pinctrl/Kconfig                            |    5 +
+ drivers/pinctrl/Makefile                           |    1 +
+ drivers/pinctrl/mvebu/pinctrl-dove.c               |   22 +-
+ drivers/pinctrl/mvebu/pinctrl-kirkwood.c           |  568 +--
+ drivers/pinctrl/pinctrl-exynos.c                   |  477 ++-
+ drivers/pinctrl/pinctrl-exynos.h                   |  170 +-
+ drivers/pinctrl/pinctrl-exynos5440.c               |  919 +++++
+ drivers/pinctrl/pinctrl-nomadik.c                  |    3 +-
+ drivers/pinctrl/pinctrl-samsung.c                  |  207 +-
+ drivers/pinctrl/pinctrl-samsung.h                  |   30 +-
+ drivers/power/Kconfig                              |    2 +
+ drivers/power/Makefile                             |    1 +
+ drivers/power/avs/smartreflex.c                    |   54 +-
+ drivers/power/reset/Kconfig                        |   15 +
+ drivers/power/reset/Makefile                       |    1 +
+ drivers/power/reset/gpio-poweroff.c                |  129 +
+ drivers/rtc/rtc-at91rm9200.c                       |    2 +-
+ .../at91_rtc.h => drivers/rtc/rtc-at91rm9200.h     |    0
+ drivers/rtc/rtc-at91sam9.c                         |    2 +-
+ drivers/rtc/rtc-mxc.c                              |   34 +-
+ drivers/sh/clk/cpg.c                               |   85 +
+ drivers/spi/spi-atmel.c                            |    2 +-
+ drivers/staging/nvec/nvec.c                        |    1 -
+ .../tidspbridge/include/dspbridge/host_os.h        |    1 -
+ drivers/tty/serial/atmel_serial.c                  |    3 +-
+ drivers/tty/serial/samsung.c                       |    3 +-
+ drivers/uio/Kconfig                                |    1 +
+ drivers/uio/uio_pruss.c                            |   24 +-
+ drivers/usb/gadget/at91_udc.c                      |    2 +-
+ drivers/usb/gadget/atmel_usba_udc.c                |    2 +-
+ drivers/usb/gadget/omap_udc.c                      |    4 +-
+ drivers/usb/host/ehci-mxc.c                        |    1 -
+ drivers/usb/host/ehci-omap.c                       |    3 +-
+ drivers/usb/host/ehci-orion.c                      |   38 +-
+ drivers/usb/host/ohci-at91.c                       |    2 +-
+ drivers/usb/host/ohci-omap.c                       |    5 +-
+ drivers/usb/host/ohci-omap3.c                      |    1 -
+ drivers/usb/musb/am35x.c                           |    3 +-
+ drivers/usb/musb/musb_dsps.c                       |    3 +-
+ drivers/usb/musb/omap2430.h                        |    2 +-
+ drivers/usb/musb/tusb6010_omap.c                   |    9 +-
+ drivers/video/atmel_lcdfb.c                        |    2 +-
+ drivers/video/clps711xfb.c                         |  156 +-
+ drivers/video/imxfb.c                              |   38 +-
+ drivers/video/mx3fb.c                              |    3 +-
+ drivers/video/omap/lcd_inn1510.c                   |    7 +-
+ drivers/video/omap/lcdc.c                          |    2 +-
+ drivers/video/omap/omapfb_main.c                   |    2 +-
+ drivers/video/omap/sossi.c                         |    2 +-
+ drivers/watchdog/at91sam9_wdt.c                    |   11 +
+ drivers/watchdog/imx2_wdt.c                        |    1 -
+ drivers/watchdog/omap_wdt.c                        |   26 +-
+ include/linux/clk-provider.h                       |   16 +-
+ .../mach/timex.h => include/linux/clk/sunxi.h      |   14 +-
+ .../mach/ipu.h => include/linux/dma/ipu-dma.h      |    6 +-
+ .../shirq.h => include/linux/irqchip/spear-shirq.h |   49 +-
+ include/linux/irqchip/sunxi.h                      |   27 +
+ .../linux/irqchip/versatile-fpga.h                 |    0
+ include/linux/mfd/db8500-prcmu.h                   |    4 +-
+ include/linux/mfd/dbx500-prcmu.h                   |   10 +
+ .../include/plat => include/linux/mfd}/menelaus.h  |    2 -
+ include/linux/platform_data/asoc-imx-ssi.h         |    2 +
+ include/linux/platform_data/atmel.h                |   73 +
+ .../linux/platform_data/clocksource-nomadik-mtu.h  |    2 +-
+ include/linux/platform_data/crypto-ux500.h         |    2 +-
+ include/linux/platform_data/dma-imx.h              |    4 +-
+ .../linux/platform_data/dma-ste-dma40.h            |    0
+ include/linux/platform_data/gpio-omap.h            |    1 -
+ .../linux/platform_data/leds-omap.h                |    2 -
+ .../linux/platform_data/mmc-omap.h                 |   48 +-
+ include/linux/platform_data/mtd-nand-omap2.h       |   46 +-
+ include/linux/platform_data/mtd-onenand-omap2.h    |   28 +-
+ include/linux/platform_data/omap-wd-timer.h        |   38 +
+ include/linux/platform_data/uio_pruss.h            |    3 +-
+ include/linux/platform_data/usb-omap.h             |   80 +
+ include/linux/power/smartreflex.h                  |   14 +-
+ include/linux/sh_clk.h                             |    9 +
+ include/linux/sunxi_timer.h                        |   24 +
+ .../include/mach => include/linux}/tegra-ahb.h     |    6 +-
+ include/linux/vexpress.h                           |  121 +
+ sound/soc/fsl/imx-pcm-fiq.c                        |    1 -
+ sound/soc/fsl/imx-ssi.c                            |    1 -
+ sound/soc/omap/am3517evm.c                         |    2 -
+ sound/soc/omap/n810.c                              |    1 -
+ sound/soc/omap/omap-pcm.c                          |    9 +-
+ sound/soc/omap/osk5912.c                           |    1 -
+ sound/soc/omap/sdp3430.c                           |    2 -
+ sound/soc/tegra/tegra30_ahub.c                     |    1 -
+ sound/soc/tegra/tegra_pcm.h                        |    2 -
+ sound/soc/ux500/ux500_pcm.c                        |    3 +-
+ 1334 files changed, 48975 insertions(+), 39983 deletions(-)
+ create mode 100644 Documentation/arm/sunxi/README
+ create mode 100644 Documentation/bus-devices/ti-gpmc.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/altera/socfpga-reset.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/altera/socfpga-system.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/bcm/bcm11351.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/davinci.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/omap/counter.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/omap/timer.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/spear/shirq.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
+ create mode 100644 Documentation/devicetree/bindings/ata/exynos-sata-phy.txt
+ create mode 100644 Documentation/devicetree/bindings/ata/exynos-sata.txt
+ create mode 100644 Documentation/devicetree/bindings/clock/imx25-clock.txt
+ create mode 100644 Documentation/devicetree/bindings/clock/imx5-clock.txt
+ create mode 100644 Documentation/devicetree/bindings/drm/exynos/hdmi.txt
+ create mode 100644 Documentation/devicetree/bindings/drm/exynos/hdmiddc.txt
+ create mode 100644 Documentation/devicetree/bindings/drm/exynos/hdmiphy.txt
+ create mode 100644 Documentation/devicetree/bindings/drm/exynos/mixer.txt
+ create mode 100644 Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
+ create mode 100644 Documentation/devicetree/bindings/gpio/leds-ns2.txt
+ create mode 100644 Documentation/devicetree/bindings/hwmon/vexpress.txt
+ create mode 100644 Documentation/devicetree/bindings/input/touchscreen/bu21013.txt
+ create mode 100644 Documentation/devicetree/bindings/interrupt-controller/allwinner,sunxi-ic.txt
+ create mode 100644 Documentation/devicetree/bindings/media/s5p-mfc.txt
+ create mode 100644 Documentation/devicetree/bindings/rtc/nvidia,tegra20-rtc.txt
+ create mode 100644 Documentation/devicetree/bindings/timer/allwinner,sunxi-timer.txt
+ create mode 100644 Documentation/devicetree/bindings/timer/nvidia,tegra20-timer.txt
+ create mode 100644 Documentation/devicetree/bindings/timer/nvidia,tegra30-timer.txt
+ create mode 100644 Documentation/devicetree/bindings/usb/ehci-orion.txt
+ create mode 100644 Documentation/devicetree/bindings/watchdog/atmel-wdt.txt
+ create mode 100644 Documentation/devicetree/bindings/watchdog/brcm,bcm2835-pm-wdog.txt
+ create mode 100644 Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt
+ create mode 100644 Documentation/hwmon/vexpress
+ create mode 100644 arch/arm/arm-soc-for-next-contents.txt
+ delete mode 100644 arch/arm/boot/compressed/head-vt8500.S
+ create mode 100644 arch/arm/boot/dts/am335x-evmsk.dts
+ create mode 100644 arch/arm/boot/dts/bcm11351-brt.dts
+ create mode 100644 arch/arm/boot/dts/bcm11351.dtsi
+ create mode 100644 arch/arm/boot/dts/ccu9540.dts
+ create mode 100644 arch/arm/boot/dts/cros5250-common.dtsi
+ create mode 100644 arch/arm/boot/dts/da850-enbw-cmc.dts
+ create mode 100644 arch/arm/boot/dts/da850-evm.dts
+ create mode 100644 arch/arm/boot/dts/da850.dtsi
+ create mode 100644 arch/arm/boot/dts/ecx-2000.dts
+ create mode 100644 arch/arm/boot/dts/ecx-common.dtsi
+ create mode 100644 arch/arm/boot/dts/exynos4212.dtsi
+ create mode 100644 arch/arm/boot/dts/exynos4412-smdk4412.dts
+ create mode 100644 arch/arm/boot/dts/exynos4412.dtsi
+ create mode 100644 arch/arm/boot/dts/exynos4x12-pinctrl.dtsi
+ create mode 100644 arch/arm/boot/dts/exynos4x12.dtsi
+ create mode 100644 arch/arm/boot/dts/exynos5250-snow.dts
+ create mode 100644 arch/arm/boot/dts/exynos5440-ssdk5440.dts
+ create mode 100644 arch/arm/boot/dts/exynos5440.dtsi
+ create mode 100644 arch/arm/boot/dts/href.dtsi
+ create mode 100644 arch/arm/boot/dts/hrefprev60.dts
+ create mode 100644 arch/arm/boot/dts/imx25-karo-tx25.dts
+ create mode 100644 arch/arm/boot/dts/imx25.dtsi
+ create mode 100644 arch/arm/boot/dts/imx27-apf27.dts
+ create mode 100644 arch/arm/boot/dts/imx28-apf28.dts
+ create mode 100644 arch/arm/boot/dts/imx28-apf28dev.dts
+ create mode 100644 arch/arm/boot/dts/imx28-sps1.dts
+ create mode 100644 arch/arm/boot/dts/imx6q-sabreauto.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-6281.dtsi
+ create mode 100644 arch/arm/boot/dts/kirkwood-6282.dtsi
+ create mode 100644 arch/arm/boot/dts/kirkwood-98dx4122.dtsi
+ create mode 100644 arch/arm/boot/dts/kirkwood-is2.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-mplcec4.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ns2-common.dtsi
+ create mode 100644 arch/arm/boot/dts/kirkwood-ns2.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ns2lite.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ns2max.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-ns2mini.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-nsa310.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-openblocks_a6.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-topkick.dts
+ create mode 100644 arch/arm/boot/dts/omap3-beagle.dts
+ create mode 100644 arch/arm/boot/dts/omap4-panda-a4.dts
+ rename arch/arm/boot/dts/{omap4-pandaES.dts => omap4-panda-es.dts} (70%)
+ create mode 100644 arch/arm/boot/dts/omap4-sdp-es23plus.dts
+ rename arch/arm/boot/dts/{omap4-var_som.dts => omap4-var-som.dts} (100%)
+ create mode 100644 arch/arm/boot/dts/orion5x-lacie-ethernet-disk-mini-v2.dts
+ create mode 100644 arch/arm/boot/dts/orion5x.dtsi
+ create mode 100644 arch/arm/boot/dts/samsung_k3pe0e000b.dtsi
+ rename arch/arm/boot/dts/{sh7377.dtsi => sh7372-mackerel.dts} (59%)
+ create mode 100644 arch/arm/boot/dts/spear320-hmi.dts
+ create mode 100644 arch/arm/boot/dts/stuib.dtsi
+ create mode 100644 arch/arm/boot/dts/sun4i-cubieboard.dts
+ create mode 100644 arch/arm/boot/dts/sun4i.dtsi
+ create mode 100644 arch/arm/boot/dts/sun5i-olinuxino.dts
+ create mode 100644 arch/arm/boot/dts/sun5i.dtsi
+ create mode 100644 arch/arm/boot/dts/sunxi.dtsi
+ create mode 100644 arch/arm/boot/dts/u9540.dts
+ delete mode 100644 arch/arm/configs/afeb9260_defconfig
+ create mode 100644 arch/arm/configs/bcm_defconfig
+ delete mode 100644 arch/arm/configs/cam60_defconfig
+ create mode 100644 arch/arm/configs/clps711x_defconfig
+ delete mode 100644 arch/arm/configs/cpu9260_defconfig
+ delete mode 100644 arch/arm/configs/cpu9g20_defconfig
+ delete mode 100644 arch/arm/configs/edb7211_defconfig
+ delete mode 100644 arch/arm/configs/fortunet_defconfig
+ delete mode 100644 arch/arm/configs/g3evm_defconfig
+ delete mode 100644 arch/arm/configs/g4evm_defconfig
+ delete mode 100644 arch/arm/configs/qil-a9260_defconfig
+ delete mode 100644 arch/arm/configs/sam9_l9260_defconfig
+ delete mode 100644 arch/arm/configs/stamp9g20_defconfig
+ delete mode 100644 arch/arm/configs/usb-a9260_defconfig
+ create mode 100644 arch/arm/include/debug/imx.S
+ create mode 100644 arch/arm/include/debug/sunxi.S
+ create mode 100644 arch/arm/include/debug/tegra.S
+ rename arch/arm/mach-at91/{include/mach => }/at91_aic.h (100%)
+ rename arch/arm/mach-at91/{include/mach => }/at91_rstc.h (100%)
+ rename arch/arm/mach-at91/{include/mach => }/at91_shdwc.h (100%)
+ rename arch/arm/mach-at91/{include/mach => }/at91_tc.h (100%)
+ rename arch/arm/mach-at91/{include/mach => }/board.h (69%)
+ rename arch/arm/mach-at91/{include/mach => }/gsia18s.h (100%)
+ delete mode 100644 arch/arm/mach-at91/include/mach/at91_pit.h
+ rename arch/arm/mach-at91/{include/mach => }/stamp9g20.h (100%)
+ create mode 100644 arch/arm/mach-bcm/Kconfig
+ create mode 100644 arch/arm/mach-bcm/Makefile
+ create mode 100644 arch/arm/mach-bcm/board_bcm.c
+ create mode 100644 arch/arm/mach-bcm2835/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-clps711x/autcpu12.c
+ create mode 100644 arch/arm/mach-clps711x/board-autcpu12.c
+ create mode 100644 arch/arm/mach-clps711x/board-cdb89712.c
+ rename arch/arm/mach-clps711x/{clep7312.c => board-clep7312.c} (95%)
+ create mode 100644 arch/arm/mach-clps711x/board-edb7211.c
+ rename arch/arm/mach-clps711x/{fortunet.c => board-fortunet.c} (96%)
+ create mode 100644 arch/arm/mach-clps711x/board-p720t.c
+ delete mode 100644 arch/arm/mach-clps711x/cdb89712.c
+ delete mode 100644 arch/arm/mach-clps711x/edb7211-arch.c
+ delete mode 100644 arch/arm/mach-clps711x/edb7211-mm.c
+ delete mode 100644 arch/arm/mach-clps711x/include/mach/entry-macro.S
+ delete mode 100644 arch/arm/mach-clps711x/include/mach/irqs.h
+ delete mode 100644 arch/arm/mach-clps711x/p720t.c
+ create mode 100644 arch/arm/mach-davinci/da8xx-dt.c
+ delete mode 100644 arch/arm/mach-exynos/dev-drm.c
+ delete mode 100644 arch/arm/mach-highbank/lluart.c
+ rename arch/arm/{plat-mxc => mach-imx}/3ds_debugboard.c (99%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/3ds_debugboard.h (100%)
+ rename arch/arm/{plat-mxc => mach-imx}/avic.c (98%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/board-mx31lilly.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/board-mx31lite.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/board-mx31moboard.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/board-pcm038.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/common.h (98%)
+ rename arch/arm/{plat-mxc => mach-imx}/cpu.c (97%)
+ rename arch/arm/{plat-mxc => mach-imx}/cpufreq.c (99%)
+ rename arch/arm/{plat-mxc => mach-imx}/cpuidle.c (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/cpuidle.h (100%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/Kconfig (97%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/Makefile (95%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx/devices}/devices-common.h (96%)
+ rename arch/arm/{plat-mxc => mach-imx/devices}/devices.c (92%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-ahci-imx.c (98%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-fec.c (97%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-flexcan.c (96%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-fsl-usb2-udc.c (96%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-gpio-mxc.c (96%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-gpio_keys.c (94%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx-dma.c (63%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx-fb.c (79%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx-i2c.c (76%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx-keypad.c (97%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx-ssi.c (98%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx-uart.c (98%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx2-wdt.c (97%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx21-hcd.c (94%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx27-coda.c (93%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx_udc.c (96%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imxdi_rtc.c (94%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-ipu-core.c (98%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mx1-camera.c (94%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mx2-camera.c (67%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mxc-ehci.c (97%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mxc-mmc.c (76%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mxc_nand.c (74%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mxc_pwm.c (97%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mxc_rnga.c (95%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mxc_rtc.c (77%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mxc_w1.c (95%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-pata_imx.c (96%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-sdhci-esdhc-imx.c (98%)
+ rename arch/arm/{plat-mxc => mach-imx}/devices/platform-spi_imx.c (98%)
+ rename arch/arm/{plat-mxc => mach-imx}/epit.c (99%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/eukrea-baseboards.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/hardware.h (94%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/iim.h (100%)
+ create mode 100644 arch/arm/mach-imx/imx25-dt.c
+ delete mode 100644 arch/arm/mach-imx/include/mach/dma-mx1-mx2.h
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx1.h (99%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx21.h (99%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx25.h (99%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx27.h (99%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx2x.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx3.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx35.h (99%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx50.h (99%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx51.h (99%)
+ rename arch/arm/{plat-mxc => mach-imx}/iomux-v1.c (98%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-v1.h (100%)
+ rename arch/arm/{plat-mxc => mach-imx}/iomux-v3.c (97%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-v3.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/iram.h (100%)
+ rename arch/arm/{plat-mxc => mach-imx}/iram_alloc.c (98%)
+ rename arch/arm/{plat-mxc => mach-imx}/irq-common.c (100%)
+ rename arch/arm/{plat-mxc => mach-imx}/irq-common.h (94%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx1.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx21.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx25.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx27.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx2x.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx31.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx35.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx3x.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx50.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx51.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx53.h (100%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx6q.h (86%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/mxc.h (100%)
+ rename arch/arm/{plat-mxc => mach-imx}/ssi-fiq-ksym.c (100%)
+ rename arch/arm/{plat-mxc => mach-imx}/ssi-fiq.S (100%)
+ rename arch/arm/{plat-mxc => mach-imx}/system.c (97%)
+ rename arch/arm/{plat-mxc => mach-imx}/time.c (99%)
+ rename arch/arm/{plat-mxc => mach-imx}/tzic.c (98%)
+ rename arch/arm/{plat-mxc => mach-imx}/ulpi.c (99%)
+ rename arch/arm/{plat-mxc/include/mach => mach-imx}/ulpi.h (100%)
+ create mode 100644 arch/arm/mach-kirkwood/board-mplcec4.c
+ create mode 100644 arch/arm/mach-kirkwood/board-ns2.c
+ create mode 100644 arch/arm/mach-kirkwood/board-nsa310.c
+ create mode 100644 arch/arm/mach-kirkwood/board-openblocks_a6.c
+ create mode 100644 arch/arm/mach-kirkwood/board-usi_topkick.c
+ create mode 100644 arch/arm/mach-omap1/dma.h
+ create mode 100644 arch/arm/mach-omap1/fpga.h
+ delete mode 100644 arch/arm/mach-omap1/include/mach/gpio.h
+ create mode 100644 arch/arm/mach-omap1/include/mach/serial.h
+ create mode 100644 arch/arm/mach-omap1/include/mach/soc.h
+ rename arch/arm/{plat-omap/include/plat => mach-omap1/include/mach}/tc.h (100%)
+ create mode 100644 arch/arm/mach-omap1/mmc.h
+ create mode 100644 arch/arm/mach-omap1/soc.h
+ create mode 100644 arch/arm/mach-omap1/sram-init.c
+ create mode 100644 arch/arm/mach-omap1/sram.h
+ rename arch/arm/mach-omap2/{include/mach => }/board-zoom.h (100%)
+ create mode 100644 arch/arm/mach-omap2/cclock2420_data.c
+ create mode 100644 arch/arm/mach-omap2/cclock2430_data.c
+ create mode 100644 arch/arm/mach-omap2/cclock33xx_data.c
+ create mode 100644 arch/arm/mach-omap2/cclock3xxx_data.c
+ create mode 100644 arch/arm/mach-omap2/cclock44xx_data.c
+ delete mode 100644 arch/arm/mach-omap2/clock2420_data.c
+ delete mode 100644 arch/arm/mach-omap2/clock2430_data.c
+ delete mode 100644 arch/arm/mach-omap2/clock33xx_data.c
+ delete mode 100644 arch/arm/mach-omap2/clock3xxx_data.c
+ delete mode 100644 arch/arm/mach-omap2/clock44xx_data.c
+ delete mode 100644 arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
+ delete mode 100644 arch/arm/mach-omap2/clockdomain33xx.c
+ delete mode 100644 arch/arm/mach-omap2/clockdomain44xx.c
+ create mode 100644 arch/arm/mach-omap2/cm2xxx.c
+ create mode 100644 arch/arm/mach-omap2/cm2xxx.h
+ rename arch/arm/mach-omap2/{cm2xxx_3xxx.c => cm3xxx.c} (67%)
+ create mode 100644 arch/arm/mach-omap2/cm3xxx.h
+ create mode 100644 arch/arm/mach-omap2/cm_common.c
+ create mode 100644 arch/arm/mach-omap2/dma.h
+ create mode 100644 arch/arm/mach-omap2/dss-common.c
+ create mode 100644 arch/arm/mach-omap2/dss-common.h
+ create mode 100644 arch/arm/mach-omap2/gpmc-nand.h
+ create mode 100644 arch/arm/mach-omap2/gpmc-onenand.h
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/gpmc.h (56%)
+ create mode 100644 arch/arm/mach-omap2/i2c.h
+ delete mode 100644 arch/arm/mach-omap2/include/mach/gpio.h
+ rename arch/arm/{plat-omap/include/plat => mach-omap2/include/mach}/serial.h (87%)
+ create mode 100644 arch/arm/mach-omap2/mmc.h
+ rename arch/arm/{plat-omap => mach-omap2}/omap-pm-noop.c (98%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/omap-pm.h (100%)
+ create mode 100644 arch/arm/mach-omap2/omap2-restart.c
+ create mode 100644 arch/arm/mach-omap2/omap3-restart.c
+ rename arch/arm/{plat-omap => mach-omap2}/omap_device.c (99%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/omap_device.h (99%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/omap_hwmod.h (99%)
+ delete mode 100644 arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
+ delete mode 100644 arch/arm/mach-omap2/powerdomain33xx.c
+ delete mode 100644 arch/arm/mach-omap2/powerdomain44xx.c
+ delete mode 100644 arch/arm/mach-omap2/prcm.c
+ create mode 100644 arch/arm/mach-omap2/prm2xxx.c
+ create mode 100644 arch/arm/mach-omap2/prm2xxx.h
+ create mode 100644 arch/arm/mach-omap2/prm3xxx.c
+ create mode 100644 arch/arm/mach-omap2/prm3xxx.h
+ create mode 100644 arch/arm/mach-omap2/serial.h
+ create mode 100644 arch/arm/mach-omap2/sram.c
+ create mode 100644 arch/arm/mach-omap2/sram.h
+ create mode 100644 arch/arm/mach-omap2/usb.h
+ create mode 100644 arch/arm/mach-orion5x/board-dt.c
+ delete mode 100644 arch/arm/mach-pxa/include/mach/pxa95x.h
+ delete mode 100644 arch/arm/mach-pxa/pxa95x.c
+ delete mode 100644 arch/arm/mach-pxa/saarb.c
+ delete mode 100644 arch/arm/mach-pxa/tavorevb3.c
+ delete mode 100644 arch/arm/mach-shmobile/board-g3evm.c
+ delete mode 100644 arch/arm/mach-shmobile/board-g4evm.c
+ delete mode 100644 arch/arm/mach-shmobile/clock-sh7367.c
+ delete mode 100644 arch/arm/mach-shmobile/clock-sh7377.c
+ delete mode 100644 arch/arm/mach-shmobile/include/mach/sh7367.h
+ delete mode 100644 arch/arm/mach-shmobile/include/mach/sh7377.h
+ delete mode 100644 arch/arm/mach-shmobile/intc-sh7367.c
+ delete mode 100644 arch/arm/mach-shmobile/intc-sh7377.c
+ delete mode 100644 arch/arm/mach-shmobile/pfc-sh7367.c
+ delete mode 100644 arch/arm/mach-shmobile/pfc-sh7377.c
+ delete mode 100644 arch/arm/mach-shmobile/setup-sh7367.c
+ delete mode 100644 arch/arm/mach-shmobile/setup-sh7377.c
+ rename arch/arm/{mach-vt8500/include/mach/irqs.h => mach-socfpga/core.h} (61%)
+ create mode 100644 arch/arm/mach-socfpga/headsmp.S
+ create mode 100644 arch/arm/mach-socfpga/platsmp.c
+ create mode 100644 arch/arm/mach-sunxi/Kconfig
+ create mode 100644 arch/arm/mach-sunxi/Makefile
+ create mode 100644 arch/arm/mach-sunxi/Makefile.boot
+ create mode 100644 arch/arm/mach-sunxi/sunxi.c
+ create mode 100644 arch/arm/mach-sunxi/sunxi.h
+ create mode 100644 arch/arm/mach-tegra/cpuidle-tegra20.c
+ create mode 100644 arch/arm/mach-tegra/cpuidle-tegra30.c
+ create mode 100644 arch/arm/mach-tegra/cpuidle.h
+ delete mode 100644 arch/arm/mach-tegra/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-tegra/include/mach/dma.h
+ delete mode 100644 arch/arm/mach-tegra/include/mach/irqs.h
+ rename arch/arm/mach-tegra/{include/mach => }/iomap.h (93%)
+ rename arch/arm/mach-tegra/{include/mach => }/irammap.h (73%)
+ create mode 100644 arch/arm/mach-tegra/pm.c
+ create mode 100644 arch/arm/mach-tegra/pm.h
+ rename arch/arm/mach-tegra/{sleep-t20.S => sleep-tegra20.S} (98%)
+ rename arch/arm/mach-tegra/{sleep-t30.S => sleep-tegra30.S} (63%)
+ create mode 100644 arch/arm/mach-tegra/tegra20_speedo.c
+ create mode 100644 arch/arm/mach-tegra/tegra30_speedo.c
+ create mode 100644 arch/arm/mach-vexpress/reset.c
+ create mode 100644 arch/arm/mach-vt8500/Kconfig
+ delete mode 100644 arch/arm/mach-vt8500/include/mach/entry-macro.S
+ delete mode 100644 arch/arm/mach-vt8500/include/mach/hardware.h
+ delete mode 100644 arch/arm/mach-vt8500/include/mach/i8042.h
+ delete mode 100644 arch/arm/mach-vt8500/include/mach/restart.h
+ delete mode 100644 arch/arm/mach-zynq/include/mach/hardware.h
+ delete mode 100644 arch/arm/mach-zynq/include/mach/irqs.h
+ delete mode 100644 arch/arm/mach-zynq/include/mach/timex.h
+ delete mode 100644 arch/arm/plat-mxc/Kconfig
+ delete mode 100644 arch/arm/plat-mxc/Makefile
+ create mode 100644 arch/arm/plat-mxc/devices/platform-mx2-emma.c
+ delete mode 100644 arch/arm/plat-mxc/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/plat-mxc/include/mach/irqs.h
+ delete mode 100644 arch/arm/plat-mxc/include/mach/uncompress.h
+ delete mode 100644 arch/arm/plat-nomadik/Kconfig
+ delete mode 100644 arch/arm/plat-nomadik/Makefile
+ delete mode 100644 arch/arm/plat-omap/clock.c
+ delete mode 100644 arch/arm/plat-omap/common.c
+ rename arch/arm/plat-omap/include/{plat/dma.h => plat-omap/dma-omap.h} (60%)
+ delete mode 100644 arch/arm/plat-omap/include/plat/clkdev_omap.h
+ delete mode 100644 arch/arm/plat-omap/include/plat/clock.h
+ delete mode 100644 arch/arm/plat-omap/include/plat/common.h
+ create mode 100644 arch/arm/plat-omap/include/plat/counter-32k.h
+ rename arch/arm/{mach-omap2 => plat-omap/include/plat}/debug-devices.h (54%)
+ delete mode 100644 arch/arm/plat-omap/include/plat/dma-44xx.h
+ delete mode 100644 arch/arm/plat-omap/include/plat/fpga.h
+ delete mode 100644 arch/arm/plat-omap/include/plat/multi.h
+ delete mode 100644 arch/arm/plat-omap/include/plat/omap-secure.h
+ delete mode 100644 arch/arm/plat-omap/include/plat/prcm.h
+ delete mode 100644 arch/arm/plat-omap/include/plat/sdrc.h
+ delete mode 100644 arch/arm/plat-omap/include/plat/uncompress.h
+ delete mode 100644 arch/arm/plat-omap/include/plat/usb.h
+ delete mode 100644 arch/arm/plat-omap/sram.h
+ delete mode 100644 arch/arm/plat-spear/shirq.c
+ create mode 100644 drivers/clk/clk-sunxi.c
+ create mode 100644 drivers/clk/clk-twl6040.c
+ create mode 100644 drivers/clk/versatile/clk-vexpress-osc.c
+ create mode 100644 drivers/clk/versatile/clk-vexpress.c
+ rename arch/arm/plat-nomadik/timer.c => drivers/clocksource/nomadik-mtu.c (93%)
+ create mode 100644 drivers/clocksource/sunxi_timer.c
+ create mode 100644 drivers/cpuidle/cpuidle-calxeda.c
+ create mode 100644 drivers/hwmon/vexpress.c
+ create mode 100644 drivers/irqchip/irq-sunxi.c
+ rename arch/arm/plat-versatile/fpga-irq.c => drivers/irqchip/irq-versatile-fpga.c (83%)
+ create mode 100644 drivers/irqchip/spear-shirq.c
+ create mode 100644 drivers/mfd/omap-usb.h
+ create mode 100644 drivers/mfd/vexpress-config.c
+ create mode 100644 drivers/mfd/vexpress-sysreg.c
+ delete mode 100644 drivers/mtd/maps/cdb89712.c
+ delete mode 100644 drivers/mtd/nand/autcpu12.c
+ delete mode 100644 drivers/mtd/nand/spia.c
+ create mode 100644 drivers/pinctrl/pinctrl-exynos5440.c
+ create mode 100644 drivers/power/reset/Kconfig
+ create mode 100644 drivers/power/reset/Makefile
+ create mode 100644 drivers/power/reset/gpio-poweroff.c
+ rename arch/arm/mach-at91/include/mach/at91_rtc.h => drivers/rtc/rtc-at91rm9200.h (100%)
+ rename arch/arm/plat-mxc/include/mach/timex.h => include/linux/clk/sunxi.h (65%)
+ rename arch/arm/plat-mxc/include/mach/ipu.h => include/linux/dma/ipu-dma.h (97%)
+ rename arch/arm/plat-spear/include/plat/shirq.h => include/linux/irqchip/spear-shirq.h (60%)
+ create mode 100644 include/linux/irqchip/sunxi.h
+ rename arch/arm/plat-versatile/include/plat/fpga-irq.h => include/linux/irqchip/versatile-fpga.h (100%)
+ rename {arch/arm/plat-omap/include/plat => include/linux/mfd}/menelaus.h (96%)
+ rename arch/arm/plat-nomadik/include/plat/mtu.h => include/linux/platform_data/clocksource-nomadik-mtu.h (71%)
+ rename arch/arm/plat-nomadik/include/plat/ste_dma40.h => include/linux/platform_data/dma-ste-dma40.h (100%)
+ rename arch/arm/plat-omap/include/plat/led.h => include/linux/platform_data/leds-omap.h (91%)
+ rename arch/arm/plat-omap/include/plat/mmc.h => include/linux/platform_data/mmc-omap.h (80%)
+ create mode 100644 include/linux/platform_data/omap-wd-timer.h
+ create mode 100644 include/linux/platform_data/usb-omap.h
+ create mode 100644 include/linux/sunxi_timer.h
+ rename {arch/arm/mach-tegra/include/mach => include/linux}/tegra-ahb.h (86%)
+ create mode 100644 include/linux/vexpress.h
+$ git am -3 ../patches/0001-OMAP-common.c-remove-init-call-to-vram-fixup.patch
+Applying: OMAP: common.c: remove init call to vram fixup
+$ git reset HEAD^
+Unstaged changes after reset:
+M	arch/arm/mach-omap2/common.c
+$ git add -A .
+$ git commit -v -a --amend
+[master aea87af] Merge remote-tracking branch 'arm-soc/for-next'
+Merging bcm2835/for-next (d7f292e Merge branch 'for-3.8/defconfig' into for-next)
+$ git merge bcm2835/for-next
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging cortex/for-next (77a3018 Cortex-M3: Add support for exception handling)
+$ git merge cortex/for-next
+Auto-merging arch/arm/mm/mmu.c
+Auto-merging arch/arm/mm/alignment.c
+Auto-merging arch/arm/kernel/setup.c
+Auto-merging arch/arm/kernel/ptrace.c
+Auto-merging arch/arm/kernel/process.c
+Auto-merging arch/arm/kernel/entry-common.S
+Auto-merging arch/arm/include/asm/cputype.h
+Merge made by the 'recursive' strategy.
+ arch/arm/include/asm/assembler.h   |   13 ++-
+ arch/arm/include/asm/cp15.h        |   11 ++-
+ arch/arm/include/asm/cputype.h     |    3 +
+ arch/arm/include/asm/glue-cache.h  |   25 ++++++
+ arch/arm/include/asm/glue-df.h     |    8 ++
+ arch/arm/include/asm/glue-proc.h   |    9 ++
+ arch/arm/include/asm/irqflags.h    |   22 +++--
+ arch/arm/include/asm/processor.h   |    7 ++
+ arch/arm/include/asm/ptrace.h      |    8 ++
+ arch/arm/include/asm/system_info.h |    1 +
+ arch/arm/include/uapi/asm/ptrace.h |   36 ++++++--
+ arch/arm/kernel/asm-offsets.c      |    3 +
+ arch/arm/kernel/entry-common.S     |    4 +
+ arch/arm/kernel/entry-header.S     |  148 +++++++++++++++++++++++++++++++++
+ arch/arm/kernel/entry-v7m.S        |  134 ++++++++++++++++++++++++++++++
+ arch/arm/kernel/head-common.S      |    9 +-
+ arch/arm/kernel/head-nommu.S       |    9 +-
+ arch/arm/kernel/process.c          |    4 +
+ arch/arm/kernel/ptrace.c           |    3 +
+ arch/arm/kernel/setup.c            |   13 ++-
+ arch/arm/kernel/traps.c            |    2 +
+ arch/arm/mm/alignment.c            |    2 +
+ arch/arm/mm/mmu.c                  |   17 ++++
+ arch/arm/mm/nommu.c                |    2 +
+ arch/arm/mm/proc-v7m.S             |  161 ++++++++++++++++++++++++++++++++++++
+ 25 files changed, 632 insertions(+), 22 deletions(-)
+ create mode 100644 arch/arm/kernel/entry-v7m.S
+ create mode 100644 arch/arm/mm/proc-v7m.S
+Merging ep93xx/ep93xx-for-next (fab1f74 Merge branch 'ep93xx-fixes' into ep93xx-for-next)
+$ git merge ep93xx/ep93xx-for-next
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging ixp4xx/next (b94740b IXP4xx: use __iomem for MMIO)
+$ git merge ixp4xx/next
+Auto-merging drivers/net/wan/ixp4xx_hss.c
+Auto-merging drivers/crypto/Kconfig
+Auto-merging drivers/char/hw_random/Kconfig
+Merge made by the 'recursive' strategy.
+ arch/arm/mach-ixp4xx/common-pci.c               |    1 +
+ arch/arm/mach-ixp4xx/common.c                   |   13 +++----
+ arch/arm/mach-ixp4xx/goramo_mlr.c               |    3 +-
+ arch/arm/mach-ixp4xx/include/mach/debug-macro.S |    4 +-
+ arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h |   46 ++++++++++-------------
+ arch/arm/mach-ixp4xx/include/mach/qmgr.h        |   12 +++---
+ arch/arm/mach-ixp4xx/ixp4xx_npe.c               |    9 ++++-
+ arch/arm/mach-ixp4xx/ixp4xx_qmgr.c              |   12 +-----
+ drivers/char/hw_random/Kconfig                  |    6 +--
+ drivers/char/hw_random/ixp4xx-rng.c             |    5 ++-
+ drivers/crypto/Kconfig                          |    2 +-
+ drivers/crypto/ixp4xx_crypto.c                  |   12 +++---
+ drivers/net/wan/ixp4xx_hss.c                    |    2 +-
+ 13 files changed, 59 insertions(+), 68 deletions(-)
+Merging msm/for-next (a0d271c Linux 3.6)
+$ git merge msm/for-next
+Already up-to-date.
+Merging renesas/next (6cee927 Merge branches 'heads/fixes', 'heads/defconfig', 'heads/boards3', 'heads/soc4' and 'heads/maintainers'; commit 'ab6f6d85210c4d0265cf48e9958c04e08595055a' into next)
+$ git merge renesas/next
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ MAINTAINERS |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+Merging samsung/for-next (d1a8169 Merge branch 'next/cleanup-samsung-3' into for-next)
+$ git merge samsung/for-next
+Resolved 'arch/arm/boot/dts/Makefile' using previous resolution.
+Resolved 'arch/arm/boot/dts/exynos5250-smdk5250.dts' using previous resolution.
+Resolved 'arch/arm/boot/dts/exynos5250.dtsi' using previous resolution.
+Resolved 'arch/arm/mach-exynos/mach-exynos5-dt.c' using previous resolution.
+Auto-merging arch/arm/plat-s3c24xx/dma.c
+Auto-merging arch/arm/mach-s3c24xx/Kconfig
+Auto-merging arch/arm/mach-exynos/mach-exynos5-dt.c
+CONFLICT (content): Merge conflict in arch/arm/mach-exynos/mach-exynos5-dt.c
+Removing arch/arm/mach-exynos/include/mach/regs-mem.h
+Removing arch/arm/mach-exynos/include/mach/dwmci.h
+Removing arch/arm/mach-exynos/dev-dwmci.c
+Auto-merging arch/arm/mach-exynos/common.c
+Auto-merging arch/arm/boot/dts/exynos5250.dtsi
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/exynos5250.dtsi
+Auto-merging arch/arm/boot/dts/exynos5250-smdk5250.dts
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/exynos5250-smdk5250.dts
+Auto-merging arch/arm/boot/dts/Makefile
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/Makefile
+Auto-merging arch/arm/Kconfig.debug
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 253ac47] Merge remote-tracking branch 'samsung/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/arm/Kconfig.debug                         |   11 +++
+ arch/arm/boot/dts/exynos4.dtsi                 |    6 ++
+ arch/arm/boot/dts/exynos5250-smdk5250.dts      |   14 +++
+ arch/arm/boot/dts/exynos5250.dtsi              |   32 +++++-
+ arch/arm/mach-exynos/Kconfig                   |    5 -
+ arch/arm/mach-exynos/Makefile                  |    1 -
+ arch/arm/mach-exynos/clock-exynos5.c           |  117 ++++++++++++++++++++++
+ arch/arm/mach-exynos/common.c                  |    7 ++
+ arch/arm/mach-exynos/cpuidle.c                 |    3 +-
+ arch/arm/mach-exynos/dev-audio.c               |   12 ---
+ arch/arm/mach-exynos/dev-dwmci.c               |   75 --------------
+ arch/arm/mach-exynos/hotplug.c                 |   45 ++++++++-
+ arch/arm/mach-exynos/include/mach/dwmci.h      |   20 ----
+ arch/arm/mach-exynos/include/mach/map.h        |    2 +
+ arch/arm/mach-exynos/include/mach/regs-audss.h |    7 +-
+ arch/arm/mach-exynos/include/mach/regs-mem.h   |   23 -----
+ arch/arm/mach-exynos/mach-exynos4-dt.c         |    1 +
+ arch/arm/mach-exynos/mach-exynos5-dt.c         |    6 ++
+ arch/arm/mach-exynos/platsmp.c                 |   30 ++++--
+ arch/arm/mach-exynos/pm.c                      |    7 ++
+ arch/arm/mach-s3c24xx/Kconfig                  |    1 +
+ arch/arm/mach-s3c24xx/clock-s3c2440.c          |    1 +
+ arch/arm/mach-s3c64xx/clock.c                  |  126 +++++++++++++++---------
+ arch/arm/mach-s3c64xx/dev-audio.c              |   11 ---
+ arch/arm/mach-s3c64xx/mach-crag6410.c          |   20 +++-
+ arch/arm/mach-s5p64x0/clock-s5p6440.c          |   49 ++++++---
+ arch/arm/mach-s5p64x0/clock-s5p6450.c          |   61 ++++++++----
+ arch/arm/mach-s5p64x0/dev-audio.c              |   12 ---
+ arch/arm/mach-s5pc100/clock.c                  |   48 +++++----
+ arch/arm/mach-s5pc100/dev-audio.c              |   16 ---
+ arch/arm/mach-s5pv210/dev-audio.c              |   16 ---
+ arch/arm/plat-s3c24xx/dma.c                    |    9 +-
+ arch/arm/plat-samsung/Kconfig                  |    6 ++
+ arch/arm/plat-samsung/Makefile                 |    1 +
+ arch/arm/plat-samsung/include/plat/devs.h      |    1 -
+ arch/arm/plat-samsung/include/plat/map-s5p.h   |    2 +
+ arch/arm/plat-samsung/include/plat/pm.h        |    2 +
+ arch/arm/plat-samsung/setup-camif.c            |   70 +++++++++++++
+ drivers/pinctrl/pinctrl-samsung.c              |    2 +-
+ 39 files changed, 565 insertions(+), 313 deletions(-)
+ delete mode 100644 arch/arm/mach-exynos/dev-dwmci.c
+ delete mode 100644 arch/arm/mach-exynos/include/mach/dwmci.h
+ delete mode 100644 arch/arm/mach-exynos/include/mach/regs-mem.h
+ create mode 100644 arch/arm/plat-samsung/setup-camif.c
+Merging tegra/for-next (3c8d1fc Merge branch 'for-3.8/fixes-for-rc1' into for-next)
+$ git merge tegra/for-next
+Auto-merging drivers/amba/tegra-ahb.c
+Auto-merging arch/arm/mach-tegra/tegra30_clocks.c
+Auto-merging arch/arm/mach-tegra/common.c
+Merge made by the 'recursive' strategy.
+ arch/arm/mach-tegra/common.c         |    2 +-
+ arch/arm/mach-tegra/tegra30_clocks.c |    4 +---
+ drivers/amba/tegra-ahb.c             |    2 ++
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+Merging kvmtool/master (6f09dab kvm tools: add support for ARMv7 processors)
+$ git merge kvmtool/master
+Merge made by the 'recursive' strategy.
+ tools/kvm/Makefile                           |   45 ++++-
+ tools/kvm/arm/aarch32/cortex-a15.c           |   98 ++++++++++
+ tools/kvm/arm/aarch32/include/kvm/barrier.h  |   10 +
+ tools/kvm/arm/aarch32/include/kvm/kvm-arch.h |   30 +++
+ tools/kvm/arm/aarch32/kvm-cpu.c              |  111 +++++++++++
+ tools/kvm/arm/aarch32/smp-pen.S              |   35 ++++
+ tools/kvm/arm/fdt.c                          |  266 ++++++++++++++++++++++++++
+ tools/kvm/arm/gic.c                          |   92 +++++++++
+ tools/kvm/arm/include/arm-common/gic.h       |   34 ++++
+ tools/kvm/arm/include/arm-common/kvm-arch.h  |   34 ++++
+ tools/kvm/arm/include/kvm/kvm-cpu-arch.h     |   46 +++++
+ tools/kvm/arm/ioport.c                       |    5 +
+ tools/kvm/arm/irq.c                          |   17 ++
+ tools/kvm/arm/kvm-cpu.c                      |  107 +++++++++++
+ tools/kvm/arm/kvm.c                          |   69 +++++++
+ tools/kvm/arm/smp.c                          |   21 ++
+ tools/kvm/builtin-balloon.c                  |    4 +-
+ tools/kvm/builtin-run.c                      |   20 +-
+ tools/kvm/builtin-setup.c                    |    4 -
+ tools/kvm/devices.c                          |   86 +++++++++
+ tools/kvm/disk/core.c                        |    2 +
+ tools/kvm/hw/pci-shmem.c                     |   12 +-
+ tools/kvm/hw/rtc.c                           |   30 +--
+ tools/kvm/hw/serial.c                        |   10 +-
+ tools/kvm/hw/vesa.c                          |   12 +-
+ tools/kvm/include/kvm/devices.h              |   27 +++
+ tools/kvm/include/kvm/fdt.h                  |   26 +++
+ tools/kvm/include/kvm/irq.h                  |    2 +-
+ tools/kvm/include/kvm/kvm.h                  |   20 +-
+ tools/kvm/include/kvm/mutex.h                |   20 +-
+ tools/kvm/include/kvm/parse-options.h        |   22 +--
+ tools/kvm/include/kvm/pci.h                  |    2 -
+ tools/kvm/include/kvm/qcow.h                 |    2 +-
+ tools/kvm/include/kvm/rbtree-interval.h      |    3 +-
+ tools/kvm/include/kvm/threadpool.h           |    4 +-
+ tools/kvm/include/kvm/uip.h                  |   10 +-
+ tools/kvm/include/kvm/virtio-mmio.h          |    1 +
+ tools/kvm/include/kvm/virtio-pci.h           |    2 +
+ tools/kvm/include/linux/stddef.h             |    6 -
+ tools/kvm/ioeventfd.c                        |    2 +
+ tools/kvm/kvm-ipc.c                          |    2 +
+ tools/kvm/kvm.c                              |   56 +++++-
+ tools/kvm/net/uip/buf.c                      |    4 +-
+ tools/kvm/net/uip/core.c                     |    6 +-
+ tools/kvm/net/uip/tcp.c                      |    9 +-
+ tools/kvm/net/uip/udp.c                      |    5 +-
+ tools/kvm/pci.c                              |   43 ++---
+ tools/kvm/powerpc/include/kvm/kvm-arch.h     |   13 +-
+ tools/kvm/powerpc/irq.c                      |   10 +-
+ tools/kvm/powerpc/kvm.c                      |    2 +-
+ tools/kvm/powerpc/spapr_pci.c                |    4 +-
+ tools/kvm/ui/sdl.c                           |    2 +
+ tools/kvm/ui/vnc.c                           |    2 +
+ tools/kvm/util/rbtree-interval.c             |    6 +-
+ tools/kvm/util/threadpool.c                  |   10 +-
+ tools/kvm/virtio/9p.c                        |   10 +-
+ tools/kvm/virtio/balloon.c                   |   10 +-
+ tools/kvm/virtio/blk.c                       |    9 +-
+ tools/kvm/virtio/console.c                   |   14 +-
+ tools/kvm/virtio/mmio.c                      |   13 +-
+ tools/kvm/virtio/net.c                       |   18 +-
+ tools/kvm/virtio/pci.c                       |   22 ++-
+ tools/kvm/virtio/rng.c                       |   16 +-
+ tools/kvm/virtio/scsi.c                      |    3 +-
+ tools/kvm/x86/include/kvm/kvm-arch.h         |   11 +-
+ tools/kvm/x86/ioport.c                       |   22 +++
+ tools/kvm/x86/irq.c                          |    4 +-
+ tools/kvm/x86/kvm.c                          |    7 +
+ 68 files changed, 1494 insertions(+), 188 deletions(-)
+ create mode 100644 tools/kvm/arm/aarch32/cortex-a15.c
+ create mode 100644 tools/kvm/arm/aarch32/include/kvm/barrier.h
+ create mode 100644 tools/kvm/arm/aarch32/include/kvm/kvm-arch.h
+ create mode 100644 tools/kvm/arm/aarch32/kvm-cpu.c
+ create mode 100644 tools/kvm/arm/aarch32/smp-pen.S
+ create mode 100644 tools/kvm/arm/fdt.c
+ create mode 100644 tools/kvm/arm/gic.c
+ create mode 100644 tools/kvm/arm/include/arm-common/gic.h
+ create mode 100644 tools/kvm/arm/include/arm-common/kvm-arch.h
+ create mode 100644 tools/kvm/arm/include/kvm/kvm-cpu-arch.h
+ create mode 100644 tools/kvm/arm/ioport.c
+ create mode 100644 tools/kvm/arm/irq.c
+ create mode 100644 tools/kvm/arm/kvm-cpu.c
+ create mode 100644 tools/kvm/arm/kvm.c
+ create mode 100644 tools/kvm/arm/smp.c
+ create mode 100644 tools/kvm/devices.c
+ create mode 100644 tools/kvm/include/kvm/devices.h
+ create mode 100644 tools/kvm/include/kvm/fdt.h
+Merging dma-mapping/dma-mapping-next (2b8836a Merge branch 'dma-fixes-for-v3.7' into HEAD)
+$ git merge dma-mapping/dma-mapping-next
+Auto-merging arch/arm/include/asm/dma-mapping.h
+Merge made by the 'recursive' strategy.
+ arch/arm/include/asm/dma-mapping.h |    1 +
+ drivers/base/dma-mapping.c         |    4 ++--
+ mm/dmapool.c                       |   31 +++++++------------------------
+ 3 files changed, 10 insertions(+), 26 deletions(-)
+Merging pwm/for-next (9685ac4 pwm: Export of_pwm_xlate_with_flags())
+$ git merge pwm/for-next
+Recorded preimage for 'drivers/pwm/pwm-tiecap.c'
+Recorded preimage for 'drivers/pwm/pwm-tiehrpwm.c'
+CONFLICT (modify/delete): drivers/pwm/pwm-twl6030.c deleted in pwm/for-next and modified in HEAD. Version HEAD of drivers/pwm/pwm-twl6030.c left in tree.
+Auto-merging drivers/pwm/pwm-tiehrpwm.c
+CONFLICT (content): Merge conflict in drivers/pwm/pwm-tiehrpwm.c
+Auto-merging drivers/pwm/pwm-tiecap.c
+CONFLICT (content): Merge conflict in drivers/pwm/pwm-tiecap.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git rm -f drivers/pwm/pwm-twl6030.c
+drivers/pwm/pwm-twl6030.c: needs merge
+rm 'drivers/pwm/pwm-twl6030.c'
+$ git commit -v -a
+Recorded resolution for 'drivers/pwm/pwm-tiecap.c'.
+Recorded resolution for 'drivers/pwm/pwm-tiehrpwm.c'.
+[master 902601d] Merge remote-tracking branch 'pwm/for-next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/pwm/pwm-tiecap.txt         |   23 ++
+ .../devicetree/bindings/pwm/pwm-tiehrpwm.txt       |   23 ++
+ .../devicetree/bindings/pwm/pwm-tipwmss.txt        |   31 ++
+ Documentation/devicetree/bindings/pwm/pwm.txt      |   17 +-
+ .../devicetree/bindings/pwm/spear-pwm.txt          |   18 +
+ .../devicetree/bindings/pwm/ti,twl-pwm.txt         |   17 +
+ .../devicetree/bindings/pwm/ti,twl-pwmled.txt      |   17 +
+ .../devicetree/bindings/pwm/vt8500-pwm.txt         |   17 +
+ drivers/pwm/Kconfig                                |   39 ++-
+ drivers/pwm/Makefile                               |    5 +-
+ drivers/pwm/core.c                                 |   29 ++
+ drivers/pwm/pwm-spear.c                            |  276 +++++++++++++++
+ drivers/pwm/pwm-tiecap.c                           |   48 ++-
+ drivers/pwm/pwm-tiehrpwm.c                         |   62 +++-
+ drivers/pwm/pwm-tipwmss.c                          |  139 ++++++++
+ drivers/pwm/pwm-tipwmss.h                          |   39 +++
+ drivers/pwm/pwm-twl-led.c                          |  344 +++++++++++++++++++
+ drivers/pwm/pwm-twl.c                              |  359 ++++++++++++++++++++
+ drivers/pwm/pwm-twl6030.c                          |  184 ----------
+ drivers/pwm/pwm-vt8500.c                           |   98 ++++--
+ include/linux/pwm.h                                |    3 +
+ 21 files changed, 1570 insertions(+), 218 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
+ create mode 100644 Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
+ create mode 100644 Documentation/devicetree/bindings/pwm/pwm-tipwmss.txt
+ create mode 100644 Documentation/devicetree/bindings/pwm/spear-pwm.txt
+ create mode 100644 Documentation/devicetree/bindings/pwm/ti,twl-pwm.txt
+ create mode 100644 Documentation/devicetree/bindings/pwm/ti,twl-pwmled.txt
+ create mode 100644 Documentation/devicetree/bindings/pwm/vt8500-pwm.txt
+ create mode 100644 drivers/pwm/pwm-spear.c
+ create mode 100644 drivers/pwm/pwm-tipwmss.c
+ create mode 100644 drivers/pwm/pwm-tipwmss.h
+ create mode 100644 drivers/pwm/pwm-twl-led.c
+ create mode 100644 drivers/pwm/pwm-twl.c
+ delete mode 100644 drivers/pwm/pwm-twl6030.c
+Merging dma-buf/for-next (ba42051 dma-buf: might_sleep() in dma_buf_unmap_attachment())
+$ git merge dma-buf/for-next
+Auto-merging drivers/base/dma-buf.c
+Merge made by the 'recursive' strategy.
+ drivers/base/dma-buf.c |    2 ++
+ 1 file changed, 2 insertions(+)
+Merging userns/for-next (98f842e proc: Usable inode numbers for the namespace file descriptors.)
+$ git merge userns/for-next
+Resolved 'include/net/net_namespace.h' using previous resolution.
+Resolved 'kernel/nsproxy.c' using previous resolution.
+Auto-merging security/yama/yama_lsm.c
+Auto-merging net/core/net_namespace.c
+Auto-merging kernel/signal.c
+Auto-merging kernel/sched/core.c
+Auto-merging kernel/nsproxy.c
+CONFLICT (content): Merge conflict in kernel/nsproxy.c
+Auto-merging kernel/fork.c
+Auto-merging kernel/events/core.c
+Auto-merging kernel/cgroup.c
+Auto-merging init/main.c
+Auto-merging init/Kconfig
+Auto-merging include/net/net_namespace.h
+CONFLICT (content): Merge conflict in include/net/net_namespace.h
+Auto-merging include/linux/fs.h
+Auto-merging include/linux/cred.h
+Auto-merging fs/proc/base.c
+Auto-merging fs/fuse/inode.c
+Auto-merging fs/fuse/fuse_i.h
+Auto-merging fs/fuse/dir.c
+Auto-merging fs/fuse/dev.c
+Auto-merging drivers/staging/android/binder.c
+Auto-merging arch/um/drivers/mconsole_kern.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 6b16702] Merge remote-tracking branch 'userns/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/mips/kernel/mips-mt-fpaff.c          |    4 +-
+ arch/powerpc/platforms/cell/spufs/sched.c |    2 +-
+ arch/um/drivers/mconsole_kern.c           |    2 +-
+ drivers/staging/android/binder.c          |    3 +-
+ fs/attr.c                                 |   11 +-
+ fs/autofs4/autofs_i.h                     |    8 +-
+ fs/autofs4/dev-ioctl.c                    |    4 +-
+ fs/autofs4/inode.c                        |   24 ++--
+ fs/autofs4/waitq.c                        |    5 +-
+ fs/exec.c                                 |    9 +-
+ fs/fuse/dev.c                             |    4 +-
+ fs/fuse/dir.c                             |   20 +--
+ fs/fuse/fuse_i.h                          |    4 +-
+ fs/fuse/inode.c                           |   23 ++--
+ fs/hppfs/hppfs.c                          |    2 +-
+ fs/mount.h                                |    3 +
+ fs/namespace.c                            |  211 ++++++++++++++++++++++++-----
+ fs/open.c                                 |    2 +-
+ fs/pnode.h                                |    1 +
+ fs/proc/Makefile                          |    1 +
+ fs/proc/array.c                           |    2 +-
+ fs/proc/base.c                            |  169 +----------------------
+ fs/proc/generic.c                         |   26 ++--
+ fs/proc/inode.c                           |    6 +-
+ fs/proc/internal.h                        |    1 +
+ fs/proc/namespaces.c                      |  185 ++++++++++++++++++++++---
+ fs/proc/root.c                            |   17 +--
+ fs/proc/self.c                            |   59 ++++++++
+ fs/sysfs/mount.c                          |    1 +
+ include/linux/cred.h                      |    2 -
+ include/linux/fs.h                        |    2 +
+ include/linux/ipc_namespace.h             |    9 +-
+ include/linux/mnt_namespace.h             |    3 +-
+ include/linux/nsproxy.h                   |    2 +-
+ include/linux/pid_namespace.h             |   11 +-
+ include/linux/proc_fs.h                   |   26 +++-
+ include/linux/user_namespace.h            |   10 ++
+ include/linux/utsname.h                   |    7 +-
+ include/net/net_namespace.h               |    2 +
+ init/Kconfig                              |    2 -
+ init/main.c                               |    1 -
+ init/version.c                            |    2 +
+ ipc/msgutil.c                             |    2 +
+ ipc/namespace.c                           |   32 ++++-
+ kernel/cgroup.c                           |    2 +-
+ kernel/events/core.c                      |    2 +-
+ kernel/exit.c                             |   12 --
+ kernel/fork.c                             |   69 +++++++---
+ kernel/nsproxy.c                          |   36 ++---
+ kernel/pid.c                              |   47 +++++--
+ kernel/pid_namespace.c                    |  112 +++++++++++----
+ kernel/ptrace.c                           |   10 +-
+ kernel/sched/core.c                       |   10 +-
+ kernel/signal.c                           |    2 +-
+ kernel/sysctl_binary.c                    |    2 +-
+ kernel/user.c                             |    2 +
+ kernel/user_namespace.c                   |  147 +++++++++++++++++---
+ kernel/utsname.c                          |   33 ++++-
+ net/core/net_namespace.c                  |   31 ++++-
+ security/yama/yama_lsm.c                  |   12 +-
+ 60 files changed, 998 insertions(+), 453 deletions(-)
+ create mode 100644 fs/proc/self.c
+Merging ktest/for-next (95f5783 ktest: Fix ELSE IF statements)
+$ git merge ktest/for-next
+Already up-to-date.
+Merging signal/for-next (9c581db do_coredump(): get rid of pt_regs argument)
+$ git merge signal/for-next
+Resolved 'arch/arm/kernel/process.c' using previous resolution.
+Resolved 'arch/cris/include/asm/signal.h' using previous resolution.
+Resolved 'arch/powerpc/kernel/entry_64.S' using previous resolution.
+Resolved 'arch/xtensa/Kconfig' using previous resolution.
+Auto-merging kernel/signal.c
+Auto-merging kernel/fork.c
+Auto-merging kernel/exit.c
+Auto-merging kernel/auditsc.c
+Auto-merging include/linux/syscalls.h
+Auto-merging include/linux/sched.h
+Auto-merging fs/file.c
+Auto-merging fs/exec.c
+Auto-merging drivers/staging/gdm72xx/gdm_usb.c
+Auto-merging arch/xtensa/Kconfig
+CONFLICT (content): Merge conflict in arch/xtensa/Kconfig
+Auto-merging arch/x86/syscalls/syscall_32.tbl
+Auto-merging arch/x86/kernel/process.c
+Auto-merging arch/x86/kernel/entry_64.S
+Auto-merging arch/x86/include/asm/processor.h
+Auto-merging arch/x86/Kconfig
+Removing arch/sh/kernel/sys_sh64.c
+Auto-merging arch/s390/kernel/entry64.S
+Auto-merging arch/s390/kernel/entry.S
+Auto-merging arch/s390/Kconfig
+Auto-merging arch/powerpc/kernel/entry_64.S
+CONFLICT (content): Merge conflict in arch/powerpc/kernel/entry_64.S
+Auto-merging arch/powerpc/include/asm/unistd.h
+Removing arch/openrisc/kernel/sys_or32.c
+Auto-merging arch/mips/kernel/scall64-n32.S
+Auto-merging arch/mips/kernel/mips_ksyms.c
+Auto-merging arch/mips/include/asm/processor.h
+Auto-merging arch/mips/Kconfig
+Auto-merging arch/microblaze/kernel/process.c
+Auto-merging arch/microblaze/kernel/entry.S
+Auto-merging arch/microblaze/kernel/entry-nommu.S
+Auto-merging arch/microblaze/include/asm/unistd.h
+Auto-merging arch/m68k/include/asm/signal.h
+Removing arch/hexagon/kernel/syscall.c
+Auto-merging arch/cris/include/asm/unistd.h
+Auto-merging arch/cris/include/asm/signal.h
+CONFLICT (content): Merge conflict in arch/cris/include/asm/signal.h
+Auto-merging arch/c6x/kernel/entry.S
+Auto-merging arch/blackfin/include/asm/unistd.h
+Removing arch/avr32/kernel/sys_avr32.c
+Auto-merging arch/avr32/Kconfig
+Auto-merging arch/arm64/Kconfig
+Auto-merging arch/arm/kernel/process.c
+CONFLICT (content): Merge conflict in arch/arm/kernel/process.c
+Auto-merging arch/arm/kernel/entry-common.S
+Auto-merging arch/arm/kernel/calls.S
+Auto-merging arch/arm/Kconfig
+Auto-merging arch/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 49b7260] Merge remote-tracking branch 'signal/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/Kconfig                             |   11 ++
+ arch/alpha/include/asm/ptrace.h          |    1 +
+ arch/alpha/include/asm/signal.h          |    3 -
+ arch/alpha/include/asm/unistd.h          |    3 +
+ arch/alpha/kernel/binfmt_loader.c        |    4 +-
+ arch/alpha/kernel/entry.S                |   51 ++-----
+ arch/alpha/kernel/process.c              |   62 ++------
+ arch/alpha/kernel/signal.c               |   16 +-
+ arch/alpha/kernel/systbls.S              |    6 +-
+ arch/arm/Kconfig                         |    1 +
+ arch/arm/include/asm/signal.h            |    1 -
+ arch/arm/include/asm/unistd.h            |    3 +
+ arch/arm/kernel/calls.S                  |    6 +-
+ arch/arm/kernel/entry-common.S           |   16 --
+ arch/arm/kernel/process.c                |   11 +-
+ arch/arm/kernel/sys_arm.c                |   31 ----
+ arch/arm64/Kconfig                       |    1 +
+ arch/arm64/include/asm/unistd.h          |    3 +
+ arch/arm64/include/asm/unistd32.h        |    4 +-
+ arch/arm64/kernel/process.c              |    9 +-
+ arch/arm64/kernel/sys.c                  |   11 --
+ arch/arm64/kernel/sys_compat.c           |   11 --
+ arch/avr32/Kconfig                       |    2 +
+ arch/avr32/include/asm/processor.h       |    3 -
+ arch/avr32/include/asm/signal.h          |    2 -
+ arch/avr32/include/asm/unistd.h          |    4 +
+ arch/avr32/kernel/Makefile               |    2 +-
+ arch/avr32/kernel/entry-avr32b.S         |   14 +-
+ arch/avr32/kernel/process.c              |  115 +++-----------
+ arch/avr32/kernel/sys_avr32.c            |   24 ---
+ arch/avr32/kernel/syscall-stubs.S        |   24 ---
+ arch/avr32/kernel/syscall_table.S        |    8 +-
+ arch/blackfin/Kconfig                    |    2 +
+ arch/blackfin/include/asm/processor.h    |    2 -
+ arch/blackfin/include/asm/unistd.h       |    1 +
+ arch/blackfin/kernel/entry.S             |   22 +--
+ arch/blackfin/kernel/process.c           |   81 +++-------
+ arch/blackfin/mach-common/entry.S        |   55 -------
+ arch/c6x/Kconfig                         |    1 +
+ arch/c6x/include/asm/syscalls.h          |    2 -
+ arch/c6x/include/uapi/asm/unistd.h       |    2 +-
+ arch/c6x/kernel/entry.S                  |   24 +--
+ arch/c6x/kernel/process.c                |   25 +---
+ arch/cris/Kconfig                        |    3 +
+ arch/cris/arch-v10/kernel/entry.S        |   17 ++-
+ arch/cris/arch-v10/kernel/process.c      |  121 +++------------
+ arch/cris/arch-v32/kernel/entry.S        |   22 +--
+ arch/cris/arch-v32/kernel/process.c      |  118 +++------------
+ arch/cris/include/asm/processor.h        |    2 -
+ arch/cris/include/asm/signal.h           |    5 -
+ arch/cris/include/asm/unistd.h           |    4 +
+ arch/cris/kernel/crisksyms.c             |    1 -
+ arch/frv/include/asm/unistd.h            |    3 +
+ arch/frv/kernel/process.c                |   45 +-----
+ arch/h8300/Kconfig                       |    2 +
+ arch/h8300/include/asm/processor.h       |    2 -
+ arch/h8300/include/asm/ptrace.h          |    3 +
+ arch/h8300/include/asm/signal.h          |    2 -
+ arch/h8300/include/asm/unistd.h          |    4 +
+ arch/h8300/kernel/entry.S                |    9 ++
+ arch/h8300/kernel/h8300_ksyms.c          |    1 -
+ arch/h8300/kernel/process.c              |  100 ++-----------
+ arch/h8300/kernel/sys_h8300.c            |   26 ----
+ arch/h8300/kernel/syscalls.S             |    9 --
+ arch/hexagon/Kconfig                     |    2 +
+ arch/hexagon/include/asm/processor.h     |    1 -
+ arch/hexagon/include/asm/syscall.h       |    3 -
+ arch/hexagon/include/uapi/asm/ptrace.h   |    4 +
+ arch/hexagon/include/uapi/asm/unistd.h   |    2 +
+ arch/hexagon/kernel/Makefile             |    3 +-
+ arch/hexagon/kernel/process.c            |  100 ++++---------
+ arch/hexagon/kernel/signal.c             |    4 +-
+ arch/hexagon/kernel/syscall.c            |   89 -----------
+ arch/hexagon/kernel/vm_entry.S           |    4 +
+ arch/ia64/Kconfig                        |    2 +
+ arch/ia64/include/asm/processor.h        |   16 --
+ arch/ia64/include/asm/signal.h           |    2 -
+ arch/ia64/include/asm/unistd.h           |    1 +
+ arch/ia64/kernel/entry.S                 |   53 ++++---
+ arch/ia64/kernel/head.S                  |   13 --
+ arch/ia64/kernel/process.c               |  161 ++++++++------------
+ arch/ia64/kernel/smpboot.c               |    5 -
+ arch/m32r/Kconfig                        |    2 +
+ arch/m32r/include/asm/processor.h        |    5 -
+ arch/m32r/include/asm/ptrace.h           |    2 +
+ arch/m32r/include/asm/signal.h           |    4 -
+ arch/m32r/include/asm/unistd.h           |    4 +
+ arch/m32r/kernel/entry.S                 |    9 ++
+ arch/m32r/kernel/m32r_ksyms.c            |    1 -
+ arch/m32r/kernel/process.c               |  126 +++-------------
+ arch/m32r/kernel/sys_m32r.c              |   21 ---
+ arch/m68k/Kconfig                        |    1 +
+ arch/m68k/include/asm/signal.h           |    8 +-
+ arch/m68k/include/asm/unistd.h           |    3 +-
+ arch/m68k/kernel/entry.S                 |   30 ++--
+ arch/m68k/kernel/process.c               |   87 ++++-------
+ arch/m68k/kernel/signal.c                |    3 +-
+ arch/m68k/kernel/syscalltable.S          |    6 +-
+ arch/microblaze/Kconfig                  |    3 +
+ arch/microblaze/include/asm/processor.h  |    8 +-
+ arch/microblaze/include/asm/unistd.h     |    6 +
+ arch/microblaze/kernel/entry-nommu.S     |   20 +--
+ arch/microblaze/kernel/entry.S           |   55 +------
+ arch/microblaze/kernel/process.c         |   75 +++-------
+ arch/microblaze/kernel/sys_microblaze.c  |   53 -------
+ arch/microblaze/kernel/syscall_table.S   |    6 +-
+ arch/mips/Kconfig                        |    2 +
+ arch/mips/include/asm/processor.h        |    2 -
+ arch/mips/include/asm/ptrace.h           |    6 +
+ arch/mips/include/asm/signal.h           |    2 -
+ arch/mips/include/asm/unistd.h           |    1 +
+ arch/mips/kernel/entry.S                 |    6 +
+ arch/mips/kernel/linux32.c               |   23 +--
+ arch/mips/kernel/mips_ksyms.c            |    2 -
+ arch/mips/kernel/process.c               |   64 +++-----
+ arch/mips/kernel/scall64-n32.S           |    2 +-
+ arch/mips/kernel/scall64-o32.S           |    2 +-
+ arch/mips/kernel/syscall.c               |   57 +------
+ arch/mn10300/Kconfig                     |    1 +
+ arch/mn10300/include/asm/signal.h        |    4 -
+ arch/mn10300/include/asm/unistd.h        |    4 +-
+ arch/mn10300/kernel/entry.S              |    7 +-
+ arch/mn10300/kernel/process.c            |   33 +---
+ arch/openrisc/Kconfig                    |    2 +
+ arch/openrisc/include/asm/processor.h    |    2 -
+ arch/openrisc/include/asm/syscalls.h     |    7 +
+ arch/openrisc/include/uapi/asm/unistd.h  |    4 +
+ arch/openrisc/kernel/Makefile            |    2 +-
+ arch/openrisc/kernel/entry.S             |   55 +++----
+ arch/openrisc/kernel/process.c           |  164 +++++++-------------
+ arch/openrisc/kernel/sys_or32.c          |   57 -------
+ arch/parisc/Kconfig                      |    3 +
+ arch/parisc/include/asm/processor.h      |    1 -
+ arch/parisc/include/asm/signal.h         |    2 -
+ arch/parisc/include/asm/unistd.h         |    4 +
+ arch/parisc/kernel/entry.S               |  241 +++---------------------------
+ arch/parisc/kernel/process.c             |  142 +++---------------
+ arch/parisc/kernel/sys_parisc32.c        |   22 ---
+ arch/parisc/kernel/syscall_table.S       |    2 +-
+ arch/powerpc/Kconfig                     |    2 +
+ arch/powerpc/include/asm/signal.h        |    2 -
+ arch/powerpc/include/asm/syscalls.h      |    9 --
+ arch/powerpc/include/asm/unistd.h        |    4 +-
+ arch/powerpc/kernel/entry_32.S           |    5 -
+ arch/powerpc/kernel/entry_64.S           |    8 +-
+ arch/powerpc/kernel/process.c            |   64 ++------
+ arch/s390/Kconfig                        |    2 +
+ arch/s390/include/asm/signal.h           |    2 -
+ arch/s390/include/asm/unistd.h           |    4 +-
+ arch/s390/kernel/entry.S                 |   32 +---
+ arch/s390/kernel/entry64.S               |   26 +---
+ arch/s390/kernel/process.c               |   53 ++-----
+ arch/score/Kconfig                       |    3 +
+ arch/score/include/asm/processor.h       |    1 -
+ arch/score/include/asm/syscalls.h        |    1 -
+ arch/score/include/asm/unistd.h          |    4 +
+ arch/score/kernel/entry.S                |   30 +---
+ arch/score/kernel/process.c              |   57 ++-----
+ arch/score/kernel/sys_score.c            |   89 -----------
+ arch/sh/Kconfig                          |    2 +
+ arch/sh/include/asm/processor_32.h       |    5 -
+ arch/sh/include/asm/processor_64.h       |    5 -
+ arch/sh/include/asm/syscalls_32.h        |   14 --
+ arch/sh/include/asm/syscalls_64.h        |   17 ---
+ arch/sh/include/asm/unistd.h             |    4 +
+ arch/sh/kernel/Makefile                  |    3 +-
+ arch/sh/kernel/cpu/sh5/entry.S           |   19 +++
+ arch/sh/kernel/entry-common.S            |   13 ++
+ arch/sh/kernel/process_32.c              |  134 +++--------------
+ arch/sh/kernel/process_64.c              |  127 +++-------------
+ arch/sh/kernel/sys_sh32.c                |   24 ---
+ arch/sh/kernel/sys_sh64.c                |   50 -------
+ arch/sparc/Kconfig                       |    2 +
+ arch/sparc/include/asm/processor_32.h    |    1 -
+ arch/sparc/include/asm/processor_64.h    |   11 +-
+ arch/sparc/include/asm/ptrace.h          |   10 +-
+ arch/sparc/include/asm/signal.h          |    2 -
+ arch/sparc/include/asm/switch_to_64.h    |    2 +-
+ arch/sparc/include/asm/syscalls.h        |    2 -
+ arch/sparc/include/asm/thread_info_64.h  |   25 ++--
+ arch/sparc/include/asm/uaccess_64.h      |    4 +-
+ arch/sparc/include/asm/unistd.h          |    1 +
+ arch/sparc/kernel/entry.S                |   51 +++----
+ arch/sparc/kernel/etrap_64.S             |    8 +-
+ arch/sparc/kernel/process_32.c           |  158 ++++++--------------
+ arch/sparc/kernel/process_64.c           |  148 ++++--------------
+ arch/sparc/kernel/sys_sparc32.c          |   36 -----
+ arch/sparc/kernel/sys_sparc_32.c         |   24 ---
+ arch/sparc/kernel/sys_sparc_64.c         |   22 ---
+ arch/sparc/kernel/syscalls.S             |   30 ++--
+ arch/sparc/kernel/systbls_64.S           |    2 +-
+ arch/sparc/kernel/traps_64.c             |    4 +-
+ arch/sparc/mm/init_64.c                  |    2 +-
+ arch/tile/Kconfig                        |    2 +
+ arch/tile/include/asm/compat.h           |   15 +-
+ arch/tile/include/asm/elf.h              |    1 +
+ arch/tile/include/asm/processor.h        |    6 +-
+ arch/tile/include/asm/switch_to.h        |    5 +-
+ arch/tile/include/asm/syscalls.h         |   16 +-
+ arch/tile/include/asm/unistd.h           |    2 +
+ arch/tile/kernel/compat.c                |    5 +-
+ arch/tile/kernel/compat_signal.c         |   10 +-
+ arch/tile/kernel/entry.S                 |   11 --
+ arch/tile/kernel/intvec_32.S             |   29 ++--
+ arch/tile/kernel/intvec_64.S             |   30 ++--
+ arch/tile/kernel/process.c               |  171 ++++++---------------
+ arch/tile/kernel/signal.c                |    9 +-
+ arch/tile/kernel/sys.c                   |    9 +-
+ arch/tile/mm/fault.c                     |    5 +-
+ arch/um/kernel/process.c                 |    5 +-
+ arch/um/kernel/syscall.c                 |   23 ---
+ arch/unicore32/include/uapi/asm/unistd.h |    1 +
+ arch/unicore32/kernel/entry.S            |    6 -
+ arch/unicore32/kernel/process.c          |   11 +-
+ arch/unicore32/kernel/sys.c              |   14 --
+ arch/x86/Kconfig                         |    1 +
+ arch/x86/ia32/ia32_aout.c                |    5 +-
+ arch/x86/ia32/ia32entry.S                |    7 +-
+ arch/x86/ia32/sys_ia32.c                 |   11 --
+ arch/x86/include/asm/processor.h         |    2 -
+ arch/x86/include/asm/signal.h            |    2 -
+ arch/x86/include/asm/sys_ia32.h          |    2 -
+ arch/x86/include/asm/syscalls.h          |   14 +-
+ arch/x86/include/asm/unistd.h            |    3 +
+ arch/x86/kernel/cpu/common.c             |    9 --
+ arch/x86/kernel/entry_32.S               |   18 ---
+ arch/x86/kernel/entry_64.S               |   22 ++-
+ arch/x86/kernel/process.c                |   30 ----
+ arch/x86/kernel/process_32.c             |   12 +-
+ arch/x86/kernel/process_64.c             |   10 +-
+ arch/x86/syscalls/syscall_32.tbl         |    6 +-
+ arch/x86/um/Kconfig                      |    1 +
+ arch/x86/um/sys_call_table_32.c          |    3 -
+ arch/x86/um/syscalls_32.c                |   15 --
+ arch/xtensa/Kconfig                      |    1 +
+ arch/xtensa/include/asm/signal.h         |    1 -
+ arch/xtensa/include/asm/syscall.h        |    2 -
+ arch/xtensa/include/asm/unistd.h         |    1 +
+ arch/xtensa/include/uapi/asm/unistd.h    |    2 +-
+ arch/xtensa/kernel/process.c             |   12 +-
+ drivers/staging/gdm72xx/gdm_usb.c        |    4 +-
+ fs/binfmt_aout.c                         |    5 +-
+ fs/binfmt_elf.c                          |    5 +-
+ fs/binfmt_elf_fdpic.c                    |    6 +-
+ fs/binfmt_em86.c                         |    4 +-
+ fs/binfmt_flat.c                         |    5 +-
+ fs/binfmt_misc.c                         |    4 +-
+ fs/binfmt_script.c                       |    4 +-
+ fs/binfmt_som.c                          |    5 +-
+ fs/coredump.c                            |    4 +-
+ fs/exec.c                                |   37 ++---
+ fs/file.c                                |    6 -
+ fs/fs_struct.c                           |   24 ---
+ include/asm-generic/signal.h             |    2 -
+ include/asm-generic/syscalls.h           |   14 +-
+ include/linux/binfmts.h                  |    4 +-
+ include/linux/compat.h                   |    4 -
+ include/linux/coredump.h                 |    4 +-
+ include/linux/fdtable.h                  |    1 -
+ include/linux/fs_struct.h                |    1 -
+ include/linux/ptrace.h                   |   13 ++
+ include/linux/sched.h                    |    7 +-
+ include/linux/syscalls.h                 |    6 +-
+ kernel/auditsc.c                         |  102 +++----------
+ kernel/exit.c                            |   92 ------------
+ kernel/fork.c                            |   64 ++++++--
+ kernel/signal.c                          |   15 +-
+ 267 files changed, 1371 insertions(+), 4119 deletions(-)
+ delete mode 100644 arch/avr32/kernel/sys_avr32.c
+ delete mode 100644 arch/hexagon/kernel/syscall.c
+ delete mode 100644 arch/openrisc/kernel/sys_or32.c
+ delete mode 100644 arch/sh/kernel/sys_sh64.c
+Merging clk/clk-next (1f61e5f clk: clock multiplexers may register out of order)
+$ git merge clk/clk-next
+Resolved 'arch/arm/mach-ux500/cpu-db8500.c' using previous resolution.
+Auto-merging include/linux/clk-provider.h
+Auto-merging drivers/mfd/db8500-prcmu.c
+Auto-merging drivers/clk/ux500/u8500_clk.c
+Auto-merging drivers/clk/spear/spear1310_clock.c
+Auto-merging drivers/clk/clk-wm831x.c
+Auto-merging drivers/clk/clk-bcm2835.c
+Auto-merging arch/arm/mach-ux500/cpu-db8500.c
+CONFLICT (content): Merge conflict in arch/arm/mach-ux500/cpu-db8500.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 99e0846] Merge remote-tracking branch 'clk/clk-next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/clock/imx23-clock.txt      |    2 +-
+ .../devicetree/bindings/clock/imx28-clock.txt      |    4 +-
+ arch/arm/mach-integrator/impd1.c                   |   69 +-----
+ arch/arm/mach-ux500/cpu-db8500.c                   |    6 -
+ drivers/clk/clk-bcm2835.c                          |    8 +-
+ drivers/clk/clk-twl6040.c                          |    4 +-
+ drivers/clk/clk-vt8500.c                           |   18 ++
+ drivers/clk/clk-wm831x.c                           |   34 +--
+ drivers/clk/clk.c                                  |  121 ++++++++--
+ drivers/clk/mxs/clk-imx23.c                        |    6 +-
+ drivers/clk/mxs/clk-imx28.c                        |   10 +-
+ drivers/clk/spear/clk-aux-synth.c                  |    3 +-
+ drivers/clk/spear/clk.c                            |    3 +
+ drivers/clk/spear/spear1310_clock.c                |  106 +++++----
+ drivers/clk/spear/spear1340_clock.c                |  237 ++++++++++++--------
+ drivers/clk/spear/spear3xx_clock.c                 |  154 ++++++++-----
+ drivers/clk/spear/spear6xx_clock.c                 |   13 +-
+ drivers/clk/ux500/Makefile                         |    3 +
+ drivers/clk/ux500/abx500-clk.c                     |   73 ++++++
+ drivers/clk/ux500/clk-prcmu.c                      |   17 ++
+ drivers/clk/ux500/clk.h                            |    6 +
+ drivers/clk/ux500/u8500_clk.c                      |   21 +-
+ drivers/clk/versatile/Makefile                     |    1 +
+ drivers/clk/versatile/clk-icst.c                   |   66 +++++-
+ drivers/clk/versatile/clk-icst.h                   |   14 +-
+ drivers/clk/versatile/clk-impd1.c                  |   97 ++++++++
+ drivers/clk/versatile/clk-integrator.c             |   55 ++---
+ drivers/clk/versatile/clk-realview.c               |   65 ++----
+ drivers/cpufreq/db8500-cpufreq.c                   |  101 +++++----
+ drivers/mfd/db8500-prcmu.c                         |   82 +++++--
+ include/linux/clk-provider.h                       |    2 +
+ include/linux/platform_data/clk-integrator.h       |    2 +
+ 32 files changed, 901 insertions(+), 502 deletions(-)
+ create mode 100644 drivers/clk/ux500/abx500-clk.c
+ create mode 100644 drivers/clk/versatile/clk-impd1.c
+Merging random/dev (ec8f02da random: prime last_data value per fips requirements)
+$ git merge random/dev
+Merge made by the 'recursive' strategy.
+ drivers/char/random.c |   40 +++++++++++++++++++++++++++-------------
+ 1 file changed, 27 insertions(+), 13 deletions(-)
+Merging lzo-update/lzo-update (ba32bf9 lib/lzo: Do not leak implementation details in lzo1x_1_compress())
+$ git merge lzo-update/lzo-update
+Removing lib/lzo/lzo1x_decompress.c
+Auto-merging crypto/testmgr.h
+Merge made by the 'recursive' strategy.
+ crypto/testmgr.h                |   38 ++---
+ include/linux/lzo.h             |   15 +-
+ lib/decompress_unlzo.c          |    2 +-
+ lib/lzo/Makefile                |    2 +-
+ lib/lzo/lzo1x_compress.c        |  335 +++++++++++++++++++++++----------------
+ lib/lzo/lzo1x_decompress.c      |  255 -----------------------------
+ lib/lzo/lzo1x_decompress_safe.c |  237 +++++++++++++++++++++++++++
+ lib/lzo/lzodefs.h               |   34 +++-
+ 8 files changed, 488 insertions(+), 430 deletions(-)
+ delete mode 100644 lib/lzo/lzo1x_decompress.c
+ create mode 100644 lib/lzo/lzo1x_decompress_safe.c
+Merging drop-experimental/linux-next (f425569 tools/lguest: remove depends on CONFIG_EXPERIMENTAL)
+$ git merge drop-experimental/linux-next
+Resolved 'drivers/net/ethernet/intel/Kconfig' using previous resolution.
+Resolved 'drivers/ptp/Kconfig' using previous resolution.
+Resolved 'net/dsa/Kconfig' using previous resolution.
+Auto-merging net/tipc/Kconfig
+Auto-merging net/sctp/Kconfig
+Auto-merging net/mac80211/Kconfig
+Auto-merging net/dsa/Kconfig
+CONFLICT (content): Merge conflict in net/dsa/Kconfig
+Auto-merging init/Kconfig
+Auto-merging fs/xfs/Kconfig
+Auto-merging drivers/ptp/Kconfig
+CONFLICT (content): Merge conflict in drivers/ptp/Kconfig
+Auto-merging drivers/net/usb/Kconfig
+Auto-merging drivers/net/ethernet/ti/Kconfig
+Auto-merging drivers/net/ethernet/intel/Kconfig
+CONFLICT (content): Merge conflict in drivers/net/ethernet/intel/Kconfig
+Auto-merging drivers/mtd/nand/Kconfig
+Auto-merging drivers/mmc/host/Kconfig
+Auto-merging drivers/cpufreq/Kconfig.arm
+Auto-merging crypto/Kconfig
+Auto-merging arch/x86/um/Kconfig
+Auto-merging arch/x86/Kconfig
+Auto-merging arch/s390/Kconfig
+Auto-merging arch/ia64/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master dee3d81] Merge remote-tracking branch 'drop-experimental/linux-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/CodingStyle                  |   10 +-----
+ Documentation/DocBook/kernel-hacking.tmpl  |    7 ----
+ Documentation/DocBook/kgdb.tmpl            |    6 ++--
+ Documentation/intel_txt.txt                |    2 +-
+ Documentation/zh_CN/CodingStyle            |    7 ----
+ arch/alpha/Kconfig                         |    3 +-
+ arch/cris/arch-v32/drivers/Kconfig         |    4 +--
+ arch/ia64/Kconfig                          |    8 ++---
+ arch/ia64/kvm/Kconfig                      |    2 +-
+ arch/ia64/xen/Kconfig                      |    2 +-
+ arch/powerpc/platforms/ps3/Kconfig         |    2 +-
+ arch/s390/Kconfig                          |    4 +--
+ arch/s390/kvm/Kconfig                      |    2 +-
+ arch/um/Kconfig.net                        |    2 +-
+ arch/um/Kconfig.um                         |    8 ++---
+ arch/x86/Kconfig                           |   22 ++++++------
+ arch/x86/um/Kconfig                        |    3 +-
+ crypto/Kconfig                             |   15 +++-----
+ drivers/cpufreq/Kconfig.arm                |    4 +--
+ drivers/cpufreq/Kconfig.x86                |    6 ++--
+ drivers/gpu/drm/udl/Kconfig                |    2 +-
+ drivers/i2c/muxes/Kconfig                  |    2 --
+ drivers/ide/Kconfig                        |    8 ++---
+ drivers/lguest/Kconfig                     |    2 +-
+ drivers/media/Kconfig                      |    7 ++--
+ drivers/media/pci/cx25821/Kconfig          |    2 +-
+ drivers/media/platform/s5p-fimc/Kconfig    |    1 -
+ drivers/media/platform/s5p-tv/Kconfig      |    3 +-
+ drivers/media/usb/pvrusb2/Kconfig          |    8 ++---
+ drivers/mmc/core/Kconfig                   |    3 +-
+ drivers/mmc/host/Kconfig                   |   20 +++++------
+ drivers/mtd/Kconfig                        |    2 +-
+ drivers/mtd/chips/Kconfig                  |    2 +-
+ drivers/mtd/devices/Kconfig                |    4 +--
+ drivers/mtd/nand/Kconfig                   |    7 ++--
+ drivers/net/Kconfig                        |    9 +++--
+ drivers/net/ethernet/8390/Kconfig          |   21 +++++------
+ drivers/net/ethernet/atheros/Kconfig       |    8 ++---
+ drivers/net/ethernet/dec/tulip/Kconfig     |    4 +--
+ drivers/net/ethernet/i825xx/Kconfig        |   12 +++----
+ drivers/net/ethernet/intel/Kconfig         |    5 ---
+ drivers/net/ethernet/natsemi/Kconfig       |    3 --
+ drivers/net/ethernet/packetengines/Kconfig |    4 +--
+ drivers/net/ethernet/realtek/Kconfig       |    4 +--
+ drivers/net/ethernet/silan/Kconfig         |    6 ++--
+ drivers/net/ethernet/ti/Kconfig            |    4 +--
+ drivers/net/team/Kconfig                   |    3 +-
+ drivers/net/usb/Kconfig                    |   16 ++++-----
+ drivers/net/wan/Kconfig                    |    8 ++---
+ drivers/pcmcia/Kconfig                     |    4 +--
+ drivers/rpmsg/Kconfig                      |    3 +-
+ drivers/sbus/char/Kconfig                  |    7 ++--
+ drivers/virtio/Kconfig                     |    8 ++---
+ fs/ceph/Kconfig                            |    4 +--
+ fs/ecryptfs/Kconfig                        |    4 +--
+ fs/nilfs2/Kconfig                          |    3 +-
+ fs/xfs/Kconfig                             |    4 +--
+ init/Kconfig                               |   54 +++++++---------------------
+ kernel/gcov/Kconfig                        |    2 +-
+ net/9p/Kconfig                             |    2 +-
+ net/Kconfig                                |    5 ++-
+ net/ceph/Kconfig                           |    4 +--
+ net/dccp/Kconfig                           |    4 +--
+ net/dccp/ccids/Kconfig                     |    5 ++-
+ net/decnet/Kconfig                         |    4 +--
+ net/decnet/netfilter/Kconfig               |    2 +-
+ net/ieee802154/Kconfig                     |    3 +-
+ net/ipv4/Kconfig                           |   11 +-----
+ net/ipv4/netfilter/Kconfig                 |    4 +--
+ net/ipv6/Kconfig                           |   24 ++++++-------
+ net/l2tp/Kconfig                           |    4 +--
+ net/lapb/Kconfig                           |    3 +-
+ net/mac80211/Kconfig                       |    2 +-
+ net/mac802154/Kconfig                      |    2 +-
+ net/netfilter/Kconfig                      |   24 +++++--------
+ net/rds/Kconfig                            |    4 +--
+ net/rxrpc/Kconfig                          |    2 +-
+ net/sctp/Kconfig                           |    4 +--
+ net/sunrpc/Kconfig                         |    2 +-
+ net/tipc/Kconfig                           |    4 +--
+ net/wanrouter/Kconfig                      |    1 -
+ net/x25/Kconfig                            |    3 +-
+ net/xfrm/Kconfig                           |   16 ++++-----
+ tools/lguest/lguest.txt                    |    8 ++---
+ 84 files changed, 206 insertions(+), 333 deletions(-)
+Merging scsi-post-merge/merge-base:master ()
+Merging akpm-current/current (064904e drivers/rtc/rtc-tps65910.c: fix invalid pointer access on _remove())
+$ git merge akpm-current/current
+Merge made by the 'recursive' strategy.
+ drivers/mtd/mtdcore.c           |    6 ++----
+ drivers/rtc/rtc-tps65910.c      |    6 +++---
+ include/linux/gfp.h             |   13 +++++--------
+ include/trace/events/gfpflags.h |    1 -
+ mm/memory-failure.c             |    8 ++++++++
+ mm/page_alloc.c                 |   40 +++++++++++++++++++++++++++------------
+ mm/sparse.c                     |   10 ++++------
+ mm/vmscan.c                     |   27 +++++++++++++++++---------
+ 8 files changed, 68 insertions(+), 43 deletions(-)
+$ git clone -s -l -n -q . ../rebase-tmp
+$ cd ../rebase-tmp
+$ git fetch --no-tags ../next refs/heads/akpm/master:akpm
+From ../next
+ * [new branch]      akpm/master -> akpm
+$ git fetch --no-tags ../next refs/heads/akpm/master-base:akpm-base
+From ../next
+ * [new branch]      akpm/master-base -> akpm-base
+$ git checkout akpm
+Switched to branch 'akpm'
+$ git rebase --onto master akpm-base
+First, rewinding head to replay your work on top of it...
+Applying: thp: fix update_mmu_cache_pmd() calls
+Applying: CRIS: Fix I/O macros
+Applying: vfs: d_obtain_alias() needs to use "/" as default name.
+Applying: fs/block_dev.c: page cache wrongly left invalidated after revalidate_disk()
+Applying: arch/x86/platform/iris/iris.c: register a platform device and a platform driver
+Applying: x86 numa: don't check if node is NUMA_NO_NODE
+Applying: arch/x86/tools/insn_sanity.c: identify source of messages
+Applying: arch/x86/platform/uv: fix incorrect tlb flush all issue
+Applying: olpc: fix olpc-xo1-sci.c build errors
+Applying: x86: convert update_mmu_cache() and update_mmu_cache_pmd() to functions
+Applying: x86: fix the argument passed to sync_global_pgds()
+Applying: x86: make 'mem=' option to work for efi platform
+Applying: audit: create explicit AUDIT_SECCOMP event type
+Applying: audit: catch possible NULL audit buffers
+Applying: ceph: fix dentry reference leak in ceph_encode_fh()
+Applying: pcmcia: move unbind/rebind into dev_pm_ops.complete
+Applying: drm/i915: optimize DIV_ROUND_CLOSEST() call
+Applying: drivers/video: add support for the Solomon SSD1307 OLED Controller
+Applying: drivers-video-add-support-for-the-solomon-ssd1307-oled-controller-checkpatch-fixes
+Applying: drivers/video/console/softcursor.c: remove redundant NULL check before kfree()
+Applying: irq: tsk->comm is an array
+Applying: timeconst.pl: remove deprecated defined(@array)
+Applying: time: don't inline EXPORT_SYMBOL functions
+Applying: Coccinelle: Add api/d_find_alias.cocci.
+Applying: h8300: select generic atomic64_t support
+Applying: drivers/message/fusion/mptscsih.c: missing break
+Applying: wait: add wait_event_lock_irq() interface
+Applying: loop: limit the number of requests in the bio list
+Applying: vfs: increment iversion when a file is truncated
+Applying: fs: change return values from -EACCES to -EPERM
+Applying: fs/block_dev.c: no need to check inode->i_bdev in bd_forget()
+Applying: watchdog: trigger all-cpu backtrace when locked up and going to panic
+Applying: mm/page_alloc.c: remove duplicate check
+Applying: writeback: remove nr_pages_dirtied arg from balance_dirty_pages_ratelimited_nr()
+Applying: mm: show migration types in show_mem
+Applying: mm, memcg: make mem_cgroup_out_of_memory() static
+Applying: mm: use IS_ENABLED(CONFIG_NUMA) instead of NUMA_BUILD
+Applying: mm: use IS_ENABLED(CONFIG_COMPACTION) instead of COMPACTION_BUILD
+Applying: mm-use-is_enabledconfig_compaction-instead-of-compaction_build-fix
+Applying: thp: clean up __collapse_huge_page_isolate
+Applying: thp-clean-up-__collapse_huge_page_isolate v2
+Applying: mm: introduce mm_find_pmd()
+Applying: mm-introduce-mm_find_pmd-fix
+Applying: thp: introduce hugepage_vma_check()
+Applying: thp: cleanup: introduce mk_huge_pmd()
+Applying: memory hotplug: suppress "Device memoryX does not have a release() function" warning
+Applying: memory-hotplug: skip HWPoisoned page when offlining pages
+Applying: memory-hotplug: update mce_bad_pages when removing the memory
+Applying: memory-hotplug-update-mce_bad_pages-when-removing-the-memory-fix
+Applying: memory-hotplug: auto offline page_cgroup when onlining memory block failed
+Applying: memory-hotplug: fix NR_FREE_PAGES mismatch
+Applying: memory-hotplug: fix NR_FREE_PAGES mismatch's fix
+Applying: numa: convert static memory to dynamically allocated memory for per node device
+Applying: memory-hotplug: suppress "Device nodeX does not have a release() function" warning
+Applying: memory-hotplug, mm/sparse.c: clear the memory to store struct page
+Applying: memory-hotplug: allocate zone's pcp before onlining pages
+Applying: mm: make zone_pcp_reset independent of MEMORY_HOTREMOVE
+Applying: memory-hotplug: build zonelist if a zone is populated after onlining pages
+Applying: memory_hotplug: fix possible incorrect node_states[N_NORMAL_MEMORY]
+Applying: slub, hotplug: ignore unrelated node's hot-adding and hot-removing
+Applying: mm/memory_hotplug.c: update start_pfn in zone and pg_data when spanned_pages == 0.
+Applying: mm: add comment on storage key dirty bit semantics
+Applying: mm,vmscan: only evict file pages when we have plenty
+Applying: mmvmscan-only-evict-file-pages-when-we-have-plenty-fix
+Applying: mm: refactor reinsert of swap_info in sys_swapoff()
+Applying: mm: do not call frontswap_init() during swapoff
+Applying: mm, highmem: use PKMAP_NR() to calculate an index of pkmap
+Applying: mm, highmem: remove useless pool_lock
+Applying: mm, highmem: remove page_address_pool list
+Applying: mm-highmem-remove-page_address_pool-list-v2
+Applying: mm, highmem: get virtual address of the page using PKMAP_ADDR()
+Applying: mm: thp: set the accessed flag for old pages on access fault
+Applying: mm: memmap_init_zone() performance improvement
+Applying: Documentation/cgroups/memory.txt: s/mem_cgroup_charge/mem_cgroup_change_common/
+Applying: mm, oom: allow exiting threads to have access to memory reserves
+Applying: memcg: make it possible to use the stock for more than one page
+Applying: memcg: reclaim when more than one page needed
+Applying: memcg: change defines to an enum
+Applying: memcg: kmem accounting basic infrastructure
+Applying: mm: add a __GFP_KMEMCG flag
+Applying: memcg: kmem controller infrastructure
+Applying: memcg: replace __always_inline with plain inline
+Applying: mm: allocate kernel pages to the right memcg
+Applying: res_counter: return amount of charges after res_counter_uncharge()
+Applying: memcg: kmem accounting lifecycle management
+Applying: memcg: use static branches when code not in use
+Applying: memcg: allow a memcg with kmem charges to be destructed
+Applying: memcg: execute the whole memcg freeing in free_worker()
+Applying: fork: protect architectures where THREAD_SIZE >= PAGE_SIZE against fork bombs
+Applying: memcg: add documentation about the kmem controller
+Applying: slab/slub: struct memcg_params
+Applying: slab: annotate on-slab caches nodelist locks
+Applying: slab/slub: consider a memcg parameter in kmem_create_cache
+Applying: memcg: allocate memory for memcg caches whenever a new memcg appears
+Applying: memcg: simplify ida initialization
+Applying: memcg: infrastructure to match an allocation to the right cache
+Applying: memcg: skip memcg kmem allocations in specified code regions
+Applying: memcg: remove test for current->mm in memcg_stop/resume_kmem_account
+Applying: sl[au]b: always get the cache from its page in kmem_cache_free()
+Applying: sl[au]b: allocate objects from memcg cache
+Applying: memcg: destroy memcg caches
+Applying: move include of workqueue.h to top of slab.h file
+Applying: memcg/sl[au]b: track all the memcg children of a kmem_cache
+Applying: memcg/sl[au]b: shrink dead caches
+Applying: memcg: get rid of once-per-second cache shrinking for dead memcgs
+Applying: memcg: aggregate memcg cache values in slabinfo
+Applying: slab: propagate tunable values
+Applying: slub: slub-specific propagation changes
+Applying: slub-slub-specific-propagation-changes-fix
+Applying: kmem: add slab-specific documentation about the kmem controller
+Applying: memcg: add comments clarifying aspects of cache attribute propagation
+Applying: slub: drop mutex before deleting sysfs entry
+Applying: dmapool: make DMAPOOL_DEBUG detect corruption of free marker
+Applying: dmapool-make-dmapool_debug-detect-corruption-of-free-marker-fix
+Applying: mm: hwpoison: fix action_result() to print out dirty/clean
+Applying: mm: print out information of file affected by memory error
+Applying: mm: support more pagesizes for MAP_HUGETLB/SHM_HUGETLB
+Applying: mm-support-more-pagesizes-for-map_hugetlb-shm_hugetlb-v7-fix
+Applying: mm-support-more-pagesizes-for-map_hugetlb-shm_hugetlb-v7-fix-fix
+Applying: MM: Support more pagesizes for MAP_HUGETLB/SHM_HUGETLB v7 fix fix fix
+Applying: MM: Support more pagesizes for MAP_HUGETLB/SHM_HUGETLB v7 fix fix fix fix
+Applying: mm-support-more-pagesizes-for-map_hugetlb-shm_hugetlb-v7-fix-fix-fix-fix-checkpatch-fixes
+Applying: selftests: add a test program for variable huge page sizes in mmap/shmget
+Applying: mm: augment vma rbtree with rb_subtree_gap
+Applying: mm: ensure safe rb_subtree_gap update when inserting new VMA
+Applying: mm: ensure safe rb_subtree_gap update when removing VMA
+Applying: mm: debug code to verify rb_subtree_gap updates are safe
+Applying: mm-augment-vma-rbtree-with-rb_subtree_gap-fix
+Applying: mm: check rb_subtree_gap correctness
+Applying: mm-check-rb_subtree_gap-correctness-fix
+Applying: mm: rearrange vm_area_struct for fewer cache misses
+Applying: mm-rearrange-vm_area_struct-for-fewer-cache-misses-checkpatch-fixes
+Applying: mm: vm_unmapped_area() lookup function
+Applying: mm-vm_unmapped_area-lookup-function-checkpatch-fixes
+Applying: mm: use vm_unmapped_area() on x86_64 architecture
+Applying: mm: fix cache coloring on x86_64 architecture
+Applying: mm: use vm_unmapped_area() in hugetlbfs
+Applying: mm: use vm_unmapped_area() in hugetlbfs on i386 architecture
+Applying: mm-use-vm_unmapped_area-in-hugetlbfs-on-i386-architecture-fix
+Applying: mm: use vm_unmapped_area() on mips architecture
+Applying: mm-use-vm_unmapped_area-on-mips-architecture-fix
+Applying: mm: use vm_unmapped_area() on arm architecture
+Applying: mm-use-vm_unmapped_area-on-arm-architecture-fix
+Applying: mm-use-vm_unmapped_area-on-arm-architecture-fix-fix
+Applying: mm: use vm_unmapped_area() on sh architecture
+Applying: mm-use-vm_unmapped_area-on-sh-architecture-fix
+Applying: mm-use-vm_unmapped_area-on-sh-architecture-fix2
+Applying: mm: use vm_unmapped_area() on sparc32 architecture
+Applying: mm-use-vm_unmapped_area-on-sparc32-architecture-fix
+Applying: mm-use-vm_unmapped_area-on-sparc32-architecture-fix-fix
+Applying: mm: use vm_unmapped_area() in hugetlbfs on tile architecture
+Applying: mm-use-vm_unmapped_area-in-hugetlbfs-on-tile-architecture-fix
+Applying: mm: use vm_unmapped_area() on sparc64 architecture
+Applying: mm-use-vm_unmapped_area-on-sparc64-architecture-fix
+Applying: linux-next: build warning after merge of the final tree (akpm tree related)
+Applying: mm: use vm_unmapped_area() in hugetlbfs on sparc64 architecture
+Applying: mm-use-vm_unmapped_area-in-hugetlbfs-on-sparc64-architecture-fix
+Applying: arch/sparc/kernel/sys_sparc_64.c: s/COLOUR/COLOR/
+Applying: mm: adjust address_space_operations.migratepage() return code
+Applying: mm: redefine address_space.assoc_mapping
+Applying: mm: introduce a common interface for balloon pages mobility
+Applying: mm: fix balloon_page_movable() page->flags check
+Applying: mm: introduce a common interface for balloon pages mobility fix
+Applying: mm: introduce compaction and migration for ballooned pages
+Applying: virtio_balloon: introduce migration primitives to balloon pages
+Applying: virtio: balloon: fix missing unlock on error in fill_balloon()
+Applying: virtio_balloon-introduce-migration-primitives-to-balloon-pages-fix-fix
+Applying: virtio_balloon-introduce-migration-primitives-to-balloon-pages-fix-fix-fix
+Applying: mm: introduce putback_movable_pages()
+Applying: mm: add vm event counters for balloon pages compaction
+Applying: mm/vmscan.c: try_to_freeze() returns boolean
+Applying: mm, mempolicy: remove duplicate code
+Applying: mm: cleanup register_node()
+Applying: mm, oom: change type of oom_score_adj to short
+Applying: mm, oom: fix race when specifying a thread as the oom origin
+Applying: mm: cma: skip watermarks check for already isolated blocks in split_free_page()
+Applying: mm: cma: skip watermarks check for already isolated blocks in split_free_page() fix
+Applying: mm-cma-skip-watermarks-check-for-already-isolated-blocks-in-split_free_page-fix-fix
+Applying: mm: cma: remove watermark hacks
+Applying: mm: cma: remove watermark hacks (fix)
+Applying: bootmem: remove not implemented function call, bootmem_arch_preferred_node()
+Applying: avr32, kconfig: remove HAVE_ARCH_BOOTMEM
+Applying: bootmem: remove alloc_arch_preferred_bootmem()
+Applying: bootmem: fix wrong call parameter for free_bootmem()
+Applying: bootmem-fix-wrong-call-parameter-for-free_bootmem-fix
+Applying: mm: cma: WARN if freed memory is still in use
+Applying: drivers/base/node.c: cleanup node_state_attr[]
+Applying: mm, memory-hotplug: dynamic configure movable memory and portion memory
+Applying: mm-memory-hotplug-dynamic-configure-movable-memory-and-portion-memory-fix
+Applying: memory_hotplug: handle empty zone when online_movable/online_kernel
+Applying: memory_hotplug: ensure every online node has NORMAL memory
+Applying: thp: huge zero page: basic preparation
+Applying: thp-huge-zero-page-basic-preparation-v6
+Applying: thp: zap_huge_pmd(): zap huge zero pmd
+Applying: thp: copy_huge_pmd(): copy huge zero page
+Applying: thp-copy_huge_pmd-copy-huge-zero-page-v6
+Applying: thp: copy_huge_pmd(): copy huge zero page v6 fix
+Applying: thp: do_huge_pmd_wp_page(): handle huge zero page
+Applying: thp-do_huge_pmd_wp_page-handle-huge-zero-page-v6
+Applying: thp: change_huge_pmd(): keep huge zero page write-protected
+Applying: thp: change split_huge_page_pmd() interface
+Applying: thp-change-split_huge_page_pmd-interface-v6
+Applying: thp: implement splitting pmd for huge zero page
+Applying: thp-implement-splitting-pmd-for-huge-zero-page-fix
+Applying: thp-implement-splitting-pmd-for-huge-zero-page-v6
+Applying: thp: setup huge zero page on non-write page fault
+Applying: thp-setup-huge-zero-page-on-non-write-page-fault-fix
+Applying: thp: lazy huge zero page allocation
+Applying: thp: implement refcounting for huge zero page
+Applying: thp, vmstat: implement HZP_ALLOC and HZP_ALLOC_FAILED events
+Applying: thp, vmstat: implement HZP_ALLOC and HZP_ALLOC_FAILED events
+Applying: thp: introduce sysfs knob to disable huge zero page
+Applying: mm: compaction: Fix compiler warning
+Applying: mm: use migrate_prep() instead of migrate_prep_local()
+Applying: mm: node_states: introduce N_MEMORY
+Applying: cpuset: use N_MEMORY instead N_HIGH_MEMORY
+Applying: procfs: use N_MEMORY instead N_HIGH_MEMORY
+Applying: memcontrol: use N_MEMORY instead N_HIGH_MEMORY
+Applying: oom: use N_MEMORY instead N_HIGH_MEMORY
+Applying: mm,migrate: use N_MEMORY instead N_HIGH_MEMORY
+Applying: mempolicy: use N_MEMORY instead N_HIGH_MEMORY
+Applying: hugetlb: use N_MEMORY instead N_HIGH_MEMORY
+Applying: vmstat: use N_MEMORY instead N_HIGH_MEMORY
+Applying: kthread: use N_MEMORY instead N_HIGH_MEMORY
+Applying: init: use N_MEMORY instead N_HIGH_MEMORY
+Applying: vmscan: use N_MEMORY instead N_HIGH_MEMORY
+Applying: page_alloc: use N_MEMORY instead N_HIGH_MEMORY change the node_states initialization
+Applying: hotplug: update nodemasks management
+Applying: res_counter: delete res_counter_write()
+Applying: mm: WARN_ON_ONCE if f_op->mmap() change vma's start address
+Applying: mm: add a reminder comment for __GFP_BITS_SHIFT
+Applying: mm, memcg: avoid unnecessary function call when memcg is disabled
+Applying: numa: add CONFIG_MOVABLE_NODE for movable-dedicated node
+Applying: numa-add-config_movable_node-for-movable-dedicated-node-fix
+Applying: memory_hotplug: allow online/offline memory to result movable node
+Applying: mm, oom: cleanup pagefault oom handler
+Applying: mm, oom: remove redundant sleep in pagefault oom handler
+Applying: mm, oom: remove statically defined arch functions of same name
+Applying: mm: introduce new field "managed_pages" to struct zone
+Applying: mm-introduce-new-field-managed_pages-to-struct-zone-fix
+Applying: mm: trace filemap add and del
+Applying: writeback: fix a typo in comment
+Applying: fs/buffer.c: do not inline exported function
+Applying: fs/buffer.c: remove redundant initialization in alloc_page_buffers()
+Applying: mm: provide more accurate estimation of pages occupied by memmap
+Applying: mm-provide-more-accurate-estimation-of-pages-occupied-by-memmap-fix
+Applying: drop_caches: add some documentation and info message
+Applying: drop_caches-add-some-documentation-and-info-messsge-checkpatch-fixes
+Applying: swap: add a simple detector for inappropriate swapin readahead
+Applying: swap-add-a-simple-detector-for-inappropriate-swapin-readahead-fix
+Applying: mm/memblock: reduce overhead in binary search
+Applying: drivers/usb/gadget/amd5536udc.c: avoid calling dma_pool_create() with NULL dev
+Applying: mm/dmapool.c: fix null dev in dma_pool_create()
+Applying: scripts-pnmtologo-fix-for-plain-pbm-checkpatch-fixes
+Applying: Documentation/kernel-parameters.txt: update mem= option's spec according to its implementation
+Applying: include/linux/init.h: use the stringify operator for the __define_initcall macro
+Applying: scripts/tags.sh: add magic for declarations of popular kernel type
+Applying: Documentation: remove reference to feature-removal-schedule.txt
+Applying: kernel: remove reference to feature-removal-schedule.txt
+Applying: sound: remove reference to feature-removal-schedule.txt
+Applying: drivers: remove reference to feature-removal-schedule.txt
+Applying: Kconfig: centralise CONFIG_ARCH_NO_VIRT_TO_BUS
+Applying: printk: boot_delay should only affect output
+Applying: MAINTAINERS: CHINESE MAINTAINERS mailing list is subscribers only
+Applying: MAINTAINERS: remove include/linux/ext3*
+Applying: backlight: da903x_bl: use dev_get_drvdata() instead of platform_get_drvdata()
+Applying: backlight: 88pm860x_bl: fix checkpatch warning
+Applying: backlight: atmel-pwm-bl: fix checkpatch warning
+Applying: backlight: corgi_lcd: fix checkpatch error and warning
+Applying: backlight: da903x_bl: fix checkpatch warning
+Applying: backlight: generic_bl: fix checkpatch warning
+Applying: backlight: hp680_bl: fix checkpatch error and warning
+Applying: backlight: ili9320: fix checkpatch error and warning
+Applying: backlight: jornada720: fix checkpatch error and warning
+Applying: backlight: l4f00242t03: fix checkpatch warning
+Applying: backlight: lm3630: fix checkpatch warning
+Applying: backlight: locomolcd: fix checkpatch error and warning
+Applying: backlight: omap1: fix checkpatch warning
+Applying: backlight: pcf50633: fix checkpatch warning
+Applying: backlight: platform_lcd: fix checkpatch error
+Applying: backlight: tdo24m: fix checkpatch warning
+Applying: backlight: tosa: fix checkpatch error and warning
+Applying: backlight: vgg2432a4: fix checkpatch warning
+Applying: backlight: lms283gf05: use devm_gpio_request_one
+Applying: backlight: tosa: use devm_gpio_request_one
+Applying: drivers/video/backlight/lp855x_bl.c: use generic PWM functions
+Applying: drivers-video-backlight-lp855x_blc-use-generic-pwm-functions-fix
+Applying: drivers/video/backlight/lp855x_bl.c: remove unnecessary mutex code
+Applying: drivers/video/backlight/da9052_bl.c: add missing const
+Applying: drivers/video/backlight/lms283gf05.c: add missing const
+Applying: drivers/video/backlight/tdo24m.c: add missing const
+Applying: drivers/video/backlight/vgg2432a4.c: add missing const
+Applying: drivers/video/backlight/s6e63m0.c: remove unnecessary cast of void pointer
+Applying: drivers/video/backlight/88pm860x_bl.c: drop devm_kfree of devm_kzalloc'd data
+Applying: drivers/video/backlight/max8925_bl.c: drop devm_kfree of devm_kzalloc'd data
+Applying: drivers/video/backlight/lm3639_bl.c: fix up world writable sysfs file
+Applying: drivers/video/backlight/ep93xx_bl.c: fix section mismatch
+Applying: drivers/video/backlight/hp680_bl.c: add missing __devexit macros for remove
+Applying: drivers/video/backlight/ili9320.c: add missing __devexit macros for remove
+Applying: backlight: add of_find_backlight_by_node()
+Applying: backlight-add-of_find_backlight_by_node-function-fix
+Applying: backlight-add-of_find_backlight_by_node-function-fix-2
+Applying: drivers/video/backlight/pandora_bl.c: change TWL4030_MODULE_PWM0 to TWL_MODULE_PWM
+Applying: backlight: 88pm860x_bl: remove an unnecessary line continuation
+Applying: backlight-88pm860x_bl-remove-an-unnecessary-line-continuation-fix
+Applying: drivers/video/backlight/lcd.c: return ENXIO when ops functions cannot be called
+Applying: drivers/video/backlight/lms283gf05.c: use GPIOF_INIT flags when using devm_gpio_request_one()
+Applying: string: introduce helper to get base file name from given path
+Applying: lib: dynamic_debug: use kbasename()
+Applying: mm: use kbasename()
+Applying: procfs: use kbasename()
+Applying: proc_devtree: remove duplicated include from proc_devtree.c
+Applying: trace: use kbasename()
+Applying: drivers/of/fdt.c: re-use kernel's kbasename()
+Applying: sscanf: don't ignore field widths for numeric conversions
+Applying: percpu_rw_semaphore: reimplement to not block the readers unnecessarily
+Using index info to reconstruct a base tree...
+M	lib/Makefile
+Falling back to patching base and 3-way merge...
+Auto-merging lib/Makefile
+CONFLICT (content): Merge conflict in lib/Makefile
+Failed to merge in the changes.
+Patch failed at 0317 percpu_rw_semaphore: reimplement to not block the readers unnecessarily
+
+When you have resolved this problem run "git rebase --continue".
+If you would prefer to skip this patch, instead run "git rebase --skip".
+To check out the original branch and stop rebasing run "git rebase --abort".
+
+$ git rebase --continue
+Applying: percpu_rw_semaphore-reimplement-to-not-block-the-readers-unnecessari-lyfix
+Applying: percpu_rw_semaphore: kill ->writer_mutex, add ->write_ctr
+Applying: percpu_rw_semaphore: add lockdep annotations
+Applying: percpu_rw_semaphore: introduce CONFIG_PERCPU_RWSEM
+Using index info to reconstruct a base tree...
+M	arch/Kconfig
+M	lib/Makefile
+Falling back to patching base and 3-way merge...
+Auto-merging lib/Makefile
+CONFLICT (content): Merge conflict in lib/Makefile
+Auto-merging arch/Kconfig
+Failed to merge in the changes.
+Patch failed at 0321 percpu_rw_semaphore: introduce CONFIG_PERCPU_RWSEM
+
+When you have resolved this problem run "git rebase --continue".
+If you would prefer to skip this patch, instead run "git rebase --skip".
+To check out the original branch and stop rebasing run "git rebase --abort".
+
+$ git rebase --continue
+Applying: compat: generic compat_sys_sched_rr_get_interval() implementation
+Applying: drivers/firmware/dmi_scan.c: check dmi version when get system uuid
+Applying: drivers-firmware-dmi_scanc-check-dmi-version-when-get-system-uuid-fix
+Applying: drivers/firmware/dmi_scan.c: fetch dmi version from SMBIOS if it exists
+Applying: drivers-firmware-dmi_scanc-fetch-dmi-version-from-smbios-if-it-exists-checkpatch-fixes
+Applying: checkpatch: warn on unnecessary line continuations
+Applying: checkpatch: warn about using CONFIG_EXPERIMENTAL
+Applying: checkpatch: remove reference to feature-removal-schedule.txt
+Applying: checkpatch: consolidate if (foo) bar(foo) checks and add debugfs_remove
+Applying: checkpatch: allow control over line length warning, default remains 80
+Applying: checkpatch: extend line continuation test
+Applying: checkpatch: Add --strict messages for blank lines around braces
+Applying: epoll: support for disabling items, and a self-test app
+Applying: binfmt_elf: fix corner case kfree of uninitialized data
+Applying: binfmt_elf-fix-corner-case-kfree-of-uninitialized-data-checkpatch-fixes
+Applying: binfmt_elf.c: use get_random_int() to fix entropy depleting
+Applying: rtc: omap: kicker mechanism support
+Applying: ARM: davinci: remove rtc kicker release
+Applying: rtc: omap: dt support
+Applying: rtc: omap: depend on am33xx
+Applying: rtc: omap: add runtime pm support
+Applying: drivers/rtc/rtc-imxdi: support for i.MX53
+Applying: drivers/rtc/rtc-imxdi.c: add devicetree support
+Applying: drivers/rtc/rtc-vt8500.c: convert to use devm_kzalloc
+Applying: drivers/rtc/rtc-test.c: avoid calling platform_device_put() twice
+Applying: rtc-avoid-calling-platform_device_put-twice-in-test_init-fix
+Applying: rtc: rtc-spear: use devm_*() routines
+Applying: rtc-rtc-spear-use-devm_-routines-fix
+Applying: rtc: rtc-spear: Add clk_{un}prepare() support
+Applying: rtc: rtc-spear: Provide flag for no support of UIE mode
+Applying: drivers/rtc/rtc-tps65910.c: rename irq to match device
+Applying: rtc: rtc-davinci: return correct error code if rtc_device_register() fails
+Applying: rtc: rtc-davinci: use devm_kzalloc()
+Applying: rtc: add NXP PCF8523 support
+Applying: rtc-add-nxp-pcf8523-support-v2
+Applying: drivers/rtc/rtc-s3c.c: remove unnecessary err_nores label
+Applying: drivers/rtc/rtc-s3c.c: convert to use devm_* API
+Applying: drivers/rtc/rtc-dev.c: remove unused code from rtc-dev.c
+Applying: hfsplus: avoid crash on failed block map free
+Applying: hfsplus: add osx.* prefix for handling namespace of Mac OS X extended attributes
+Applying: hfsplus-add-osx-prefix-for-handling-namespace-of-mac-os-x-extended-attributes-checkpatch-fixes
+Applying: hfsplus: add on-disk layout declarations related to attributes tree
+Applying: hfsplus: add functionality of manipulating by records in attributes tree
+Applying: hfsplus: rework functionality of getting, setting and deleting of extended attributes
+Applying: hfsplus-rework-functionality-of-getting-setting-and-deleting-of-extended-attributes-fix
+Applying: hfsplus: add support of manipulation by attributes file
+Applying: hfsplus: rework processing errors in hfsplus_free_extents()
+Applying: fat: notify when discard is not supported
+Applying: fat: provide option for setting timezone offset
+Applying: fat: ix mount option parsing
+Applying: fs/fat: strip "cp" prefix from codepage in display
+Applying: Documentation/DMA-API-HOWTO.txt: minor grammar corrections
+Applying: Documentation: fix Documentation/security/00-INDEX
+Applying: kstrto*: add documentation
+Applying: simple_strto*: annotate function as obsolete
+Applying: ptrace: introduce PTRACE_O_EXITKILL
+Applying: proc: don't show nonexistent capabilities
+Applying: procfs: add VmFlags field in smaps output
+Applying: procfs-add-vmflags-field-in-smaps-output-v4-fix
+Applying: /proc/pid/status: add "Seccomp" field
+Applying: proc: pid/status: show all supplementary groups
+Applying: fork: unshare: remove dead code
+Applying: exec: do not leave bprm->interp on stack
+Applying: exec: use -ELOOP for max recursion depth
+Applying: ipc: remove forced assignment of selected message
+Applying: ipc: add sysctl to specify desired next object id
+Applying: ipc-add-sysctl-to-specify-desired-next-object-id-checkpatch-fixes
+Applying: ipc: wrap new sysctls for CRIU inside CONFIG_CHECKPOINT_RESTORE
+Applying: Documentation: update sysctl/kernel.txt
+Applying: ipc: message queue receive cleanup
+Applying: ipc-message-queue-receive-cleanup-checkpatch-fixes
+Applying: ipc: introduce message queue copy feature
+Applying: ipc: remove redundant MSG_COPY check
+Applying: ipc: cleanup do_msgrcv() around MSG_COPY feature
+Applying: selftests: IPC message queue copy feature test
+Applying: test: IPC message queue copy feature test update
+Applying: ipc: simplify free_copy() call
+Applying: ipc: convert prepare_copy() from macro to function
+Applying: ipc-convert-prepare_copy-from-macro-to-function-fix
+Applying: ipc: simplify message copying
+Applying: ipc: add more comments to message copying related code
+Applying: Documentation/sysctl/kernel.txt: document /proc/sys/shmall
+Applying: ipc/sem.c: alternatives to preempt_disable()
+Applying: pidns: remove unused is_container_init()
+Applying: linux/compiler.h: add __must_hold macro for functions called with a lock held
+Applying: Documentation/sparse.txt: document context annotations for lock checking
+Applying: aoe: describe the behavior of the "err" character device
+Applying: aoe: print warning regarding a common reason for dropped transmits
+Applying: aoe-print-warning-regarding-a-common-reason-for-dropped-transmits-v2
+Applying: aoe: avoid using skb member after dev_queue_xmit
+Applying: aoe: update cap on outstanding commands based on config query response
+Applying: aoe: support the forgetting (flushing) of a user-specified AoE target
+Applying: aoe: support larger I/O requests via aoe_maxsectors module param
+Applying: aoe: "payload" sysfs file exports per-AoE-command data transfer size
+Applying: aoe: cleanup: remove unused ata_scnt function
+Applying: aoe: whitespace cleanup
+Applying: aoe: update driver-internal version number to 60
+Applying: aoe: provide ATA identify device content to user on request
+Applying: aoe: improve network congestion handling
+Applying: aoe: err device: include MAC addresses for unexpected responses
+Applying: aoe: manipulate aoedev network stats under lock
+Applying: aoe: use high-resolution RTTs with fallback to low-res
+Applying: aoe: commands in retransmit queue use new destination on failure
+Applying: aoe: update driver-internal version to 64+
+Applying: aoe: copy fallback timing information on destination failover
+Applying: aoe: remove vestigial request queue allocation
+Applying: aoe: increase default cap on outstanding AoE commands in the network
+Applying: aoe: cleanup: correct comment for aoetgt nout
+Applying: aoe: remove call to request handler from I/O completion
+Applying: aoe: make error messages more specific in static minor allocation
+Applying: aoe: initialize sysminor to avoid compiler warning
+Applying: aoe: return real minor number for static minors
+Applying: random32: rename random32 to prandom
+Applying: prandom: introduce prandom_bytes() and prandom_bytes_state()
+Applying: bnx2x: use prandom_bytes()
+Applying: mtd: nandsim: use prandom_bytes
+Applying: ubifs: use prandom_bytes
+Applying: mtd: mtd_nandecctest: use prandom_bytes instead of get_random_bytes()
+Applying: mtd: mtd_oobtest: convert to use prandom library
+Applying: mtd: mtd_pagetest: convert to use prandom library
+Applying: mtd: mtd_speedtest: use prandom_bytes
+Applying: mtd: mtd_subpagetest: convert to use prandom library
+Applying: mtd: mtd_stresstest: use prandom_bytes()
+Applying: Documentation/DMA-API-HOWTO.txt: fix typo
+Applying: vm selftests: print failure status instead of cause make error
+Applying: mqueue selftests: print failure status instead of cause make error
+Applying: cpu-hotplug selftests: print failure status instead of cause make error
+Applying: mem-hotplug selftests: print failure status instead of cause make error
+Applying: kcmp selftests: make run_tests fix
+Applying: kcmp selftests: print fail status instead of cause make error
+Applying: breakpoint selftests: print failure status instead of cause make error
+Applying: tools/testing/selftests/kcmp/kcmp_test.c: print reason for failure in kcmp_test
+Applying: procfs: add ability to plug in auxiliary fdinfo providers
+Applying: fs, eventfd: add procfs fdinfo helper
+Applying: fs, epoll: add procfs fdinfo helper
+Applying: fs, epoll: drop enabled field from fdinfo output
+Applying: fdinfo: show sigmask for signalfd fd
+Applying: fs, exportfs: escape nil dereference if no s_export_op present
+Applying: fs, exportfs: add exportfs_encode_inode_fh() helper
+Applying: fs, notify: add procfs fdinfo helper
+Applying: fs, notify: Move bare fdinfo helpers to a header
+Applying: fs, notify: add missing space after prefix
+Applying: fs, notify: don't forget to provide fhandle for inode fanotify
+Applying: docs: add documentation about /proc/<pid>/fdinfo/<fd> output
+Applying: docs-add-documentation-about-proc-pid-fdinfo-fd-output-fix
+Applying: fs-notify-add-procfs-fdinfo-helper-v7-fix
+Applying: scatterlist: don't BUG when we can trivially return a proper error.
+Applying: scatterlist-dont-bug-when-we-can-trivially-return-a-proper-error-fix
+$ cd ../next
+$ git fetch -f ../rebase-tmp akpm:akpm/master
+From ../rebase-tmp
+ + e917406...dc9e382 akpm       -> akpm/master  (forced update)
+$ rm -rf ../rebase-tmp
+Merging akpm/master (dc9e382 scatterlist-dont-bug-when-we-can-trivially-return-a-proper-error-fix)
+$ git merge --no-ff akpm/master
+Merge made by the 'recursive' strategy.
+ Documentation/00-INDEX                             |    2 -
+ Documentation/ABI/README                           |    3 -
+ Documentation/DMA-API-HOWTO.txt                    |    9 +-
+ Documentation/DocBook/kernel-api.tmpl              |    3 +
+ Documentation/backlight/lp855x-driver.txt          |   10 +-
+ Documentation/cgroups/cpusets.txt                  |    2 +-
+ Documentation/cgroups/memory.txt                   |   72 +-
+ Documentation/cgroups/resource_counter.txt         |    7 +-
+ .../devicetree/bindings/rtc/imxdi-rtc.txt          |   17 +
+ Documentation/devicetree/bindings/rtc/rtc-omap.txt |   17 +
+ .../devicetree/bindings/video/ssd1307fb.txt        |   24 +
+ Documentation/filesystems/proc.txt                 |  124 +-
+ Documentation/filesystems/vfat.txt                 |    9 +
+ Documentation/kernel-parameters.txt                |    7 +-
+ Documentation/memory-hotplug.txt                   |   24 +-
+ Documentation/security/00-INDEX                    |    2 +
+ Documentation/sparse.txt                           |   18 +
+ Documentation/sysctl/kernel.txt                    |   32 +
+ Documentation/sysctl/vm.txt                        |   33 +-
+ Documentation/vm/transhuge.txt                     |   19 +-
+ MAINTAINERS                                        |    4 +-
+ arch/Kconfig                                       |    8 +
+ arch/alpha/include/asm/mman.h                      |   11 +
+ arch/arm/mach-davinci/devices-da8xx.c              |   13 +-
+ arch/arm/mm/mmap.c                                 |  132 +-
+ arch/arm64/include/asm/unistd.h                    |    1 +
+ arch/arm64/kernel/sys_compat.c                     |   15 -
+ arch/avr32/Kconfig                                 |    3 -
+ arch/cris/include/asm/io.h                         |   39 +-
+ arch/h8300/Kconfig                                 |    1 +
+ arch/mips/include/uapi/asm/mman.h                  |   11 +
+ arch/mips/mm/mmap.c                                |  111 +-
+ arch/parisc/include/uapi/asm/mman.h                |   11 +
+ arch/powerpc/Kconfig                               |    4 +-
+ arch/powerpc/include/asm/machdep.h                 |   36 +-
+ arch/powerpc/include/asm/systbl.h                  |    2 +-
+ arch/powerpc/include/asm/unistd.h                  |    1 +
+ arch/powerpc/kernel/sys_ppc32.c                    |   17 +-
+ arch/powerpc/kernel/sysfs.c                        |    4 +-
+ arch/powerpc/mm/fault.c                            |   27 +-
+ arch/powerpc/platforms/cell/celleb_pci.c           |    4 +-
+ arch/s390/include/asm/page.h                       |    3 +
+ arch/sh/Kconfig                                    |    4 +-
+ arch/sh/mm/fault.c                                 |   19 +-
+ arch/sh/mm/mmap.c                                  |  137 +-
+ arch/sparc/Kconfig                                 |    4 +-
+ arch/sparc/include/asm/unistd.h                    |    1 +
+ arch/sparc/kernel/sys_sparc32.c                    |   14 -
+ arch/sparc/kernel/sys_sparc_32.c                   |   27 +-
+ arch/sparc/kernel/sys_sparc_64.c                   |  150 +-
+ arch/sparc/mm/hugetlbpage.c                        |  124 +-
+ arch/tile/include/asm/compat.h                     |    2 -
+ arch/tile/include/asm/unistd.h                     |    1 +
+ arch/tile/kernel/compat.c                          |   18 -
+ arch/tile/mm/hugetlbpage.c                         |  139 +-
+ arch/x86/Kconfig                                   |    1 +
+ arch/x86/include/asm/e820.h                        |    2 +
+ arch/x86/include/asm/elf.h                         |    6 +-
+ arch/x86/include/asm/mman.h                        |    3 +
+ arch/x86/include/asm/pgtable.h                     |   12 +
+ arch/x86/include/asm/pgtable_32.h                  |    7 -
+ arch/x86/include/asm/pgtable_64.h                  |    3 -
+ arch/x86/include/asm/uv/uv.h                       |    2 +-
+ arch/x86/kernel/e820.c                             |   72 +-
+ arch/x86/kernel/sys_x86_64.c                       |  151 +-
+ arch/x86/kernel/vm86_32.c                          |    2 +-
+ arch/x86/mm/fault.c                                |   23 +-
+ arch/x86/mm/hugetlbpage.c                          |  130 +-
+ arch/x86/mm/init_64.c                              |    8 +-
+ arch/x86/mm/numa.c                                 |    3 +-
+ arch/x86/platform/efi/efi.c                        |   15 +-
+ arch/x86/platform/iris/iris.c                      |   67 +-
+ arch/x86/platform/uv/tlb_uv.c                      |   10 +-
+ arch/x86/tools/insn_sanity.c                       |   10 +-
+ arch/x86/vdso/vma.c                                |    2 +-
+ arch/xtensa/include/uapi/asm/mman.h                |   11 +
+ block/Kconfig                                      |    1 +
+ drivers/base/memory.c                              |   42 +-
+ drivers/base/node.c                                |   86 +-
+ drivers/block/aoe/aoe.h                            |   32 +-
+ drivers/block/aoe/aoeblk.c                         |   66 +-
+ drivers/block/aoe/aoechr.c                         |    7 +-
+ drivers/block/aoe/aoecmd.c                         |  334 +++--
+ drivers/block/aoe/aoedev.c                         |  117 +-
+ drivers/block/aoe/aoemain.c                        |    2 +-
+ drivers/block/aoe/aoenet.c                         |   13 +-
+ drivers/block/loop.c                               |   10 +
+ drivers/firmware/dmi_scan.c                        |   78 +-
+ drivers/gpu/drm/i915/intel_pm.c                    |    3 +-
+ drivers/macintosh/smu.c                            |    2 +-
+ drivers/md/md.c                                    |    2 +-
+ drivers/md/md.h                                    |   26 -
+ drivers/md/raid1.c                                 |   15 +-
+ drivers/md/raid10.c                                |   15 +-
+ drivers/md/raid5.c                                 |   12 +-
+ drivers/message/fusion/mptscsih.c                  |    1 +
+ drivers/mtd/nand/nandsim.c                         |    5 +-
+ drivers/mtd/tests/mtd_nandecctest.c                |    2 +-
+ drivers/mtd/tests/mtd_oobtest.c                    |   49 +-
+ drivers/mtd/tests/mtd_pagetest.c                   |   43 +-
+ drivers/mtd/tests/mtd_speedtest.c                  |    9 +-
+ drivers/mtd/tests/mtd_stresstest.c                 |    3 +-
+ drivers/mtd/tests/mtd_subpagetest.c                |   42 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c    |    5 +-
+ drivers/net/wireless/Kconfig                       |    6 +-
+ drivers/of/fdt.c                                   |   10 +-
+ drivers/pcmcia/cs.c                                |   37 +-
+ drivers/rtc/Kconfig                                |   21 +-
+ drivers/rtc/Makefile                               |    1 +
+ drivers/rtc/rtc-davinci.c                          |   21 +-
+ drivers/rtc/rtc-dev.c                              |   19 -
+ drivers/rtc/rtc-imxdi.c                            |   11 +
+ drivers/rtc/rtc-omap.c                             |   80 +-
+ drivers/rtc/rtc-pcf8523.c                          |  326 +++++
+ drivers/rtc/rtc-s3c.c                              |   48 +-
+ drivers/rtc/rtc-spear.c                            |   91 +-
+ drivers/rtc/rtc-test.c                             |   14 +-
+ drivers/rtc/rtc-tps65910.c                         |    2 +-
+ drivers/rtc/rtc-vt8500.c                           |   15 +-
+ drivers/scsi/fcoe/fcoe_ctlr.c                      |    4 +-
+ drivers/staging/android/lowmemorykiller.c          |   16 +-
+ drivers/usb/gadget/amd5536udc.c                    |   16 +-
+ drivers/video/Kconfig                              |   15 +
+ drivers/video/Makefile                             |    1 +
+ drivers/video/backlight/88pm860x_bl.c              |   18 +-
+ drivers/video/backlight/atmel-pwm-bl.c             |    7 +-
+ drivers/video/backlight/backlight.c                |   29 +
+ drivers/video/backlight/corgi_lcd.c                |   16 +-
+ drivers/video/backlight/da903x_bl.c                |   15 +-
+ drivers/video/backlight/da9052_bl.c                |    2 +-
+ drivers/video/backlight/ep93xx_bl.c                |    4 +-
+ drivers/video/backlight/generic_bl.c               |    4 +-
+ drivers/video/backlight/hp680_bl.c                 |    8 +-
+ drivers/video/backlight/ili9320.c                  |   16 +-
+ drivers/video/backlight/ili9320.h                  |    2 +-
+ drivers/video/backlight/jornada720_bl.c            |   34 +-
+ drivers/video/backlight/jornada720_lcd.c           |    3 +-
+ drivers/video/backlight/l4f00242t03.c              |    3 +-
+ drivers/video/backlight/lcd.c                      |    8 +-
+ drivers/video/backlight/lm3630_bl.c                |    2 +-
+ drivers/video/backlight/lm3639_bl.c                |    2 +-
+ drivers/video/backlight/lms283gf05.c               |   17 +-
+ drivers/video/backlight/locomolcd.c                |   65 +-
+ drivers/video/backlight/lp855x_bl.c                |   51 +-
+ drivers/video/backlight/max8925_bl.c               |   11 +-
+ drivers/video/backlight/omap1_bl.c                 |    4 +-
+ drivers/video/backlight/pandora_bl.c               |    8 +-
+ drivers/video/backlight/pcf50633-backlight.c       |    8 +-
+ drivers/video/backlight/platform_lcd.c             |    2 +-
+ drivers/video/backlight/s6e63m0.c                  |    2 +-
+ drivers/video/backlight/tdo24m.c                   |   33 +-
+ drivers/video/backlight/tosa_bl.c                  |   10 +-
+ drivers/video/backlight/tosa_lcd.c                 |   24 +-
+ drivers/video/backlight/vgg2432a4.c                |   10 +-
+ drivers/video/console/softcursor.c                 |    3 +-
+ drivers/video/ssd1307fb.c                          |  396 +++++
+ drivers/virtio/virtio_balloon.c                    |  151 +-
+ fs/attr.c                                          |    5 +
+ fs/autofs4/root.c                                  |    2 +-
+ fs/binfmt_elf.c                                    |   25 +-
+ fs/binfmt_em86.c                                   |    1 -
+ fs/binfmt_misc.c                                   |   11 +-
+ fs/binfmt_script.c                                 |    8 +-
+ fs/block_dev.c                                     |    9 +-
+ fs/btrfs/disk-io.c                                 |    8 +-
+ fs/btrfs/file.c                                    |    3 +-
+ fs/btrfs/ioctl.c                                   |    2 +-
+ fs/buffer.c                                        |   18 +-
+ fs/ceph/export.c                                   |    4 +-
+ fs/dcache.c                                        |    2 +-
+ fs/dlm/config.c                                    |    2 +-
+ fs/drop_caches.c                                   |    2 +
+ fs/eventfd.c                                       |   20 +
+ fs/eventpoll.c                                     |   68 +-
+ fs/exec.c                                          |   25 +-
+ fs/exportfs/expfs.c                                |   19 +-
+ fs/fat/fat.h                                       |    3 +-
+ fs/fat/inode.c                                     |   55 +-
+ fs/fat/misc.c                                      |    9 +-
+ fs/fs-writeback.c                                  |    2 +-
+ fs/gfs2/glock.c                                    |    2 +-
+ fs/gfs2/sys.c                                      |   18 +-
+ fs/hfsplus/Makefile                                |    4 +-
+ fs/hfsplus/attributes.c                            |  399 +++++
+ fs/hfsplus/bfind.c                                 |   93 +-
+ fs/hfsplus/bitmap.c                                |   13 +-
+ fs/hfsplus/bnode.c                                 |    6 +-
+ fs/hfsplus/brec.c                                  |   23 +-
+ fs/hfsplus/btree.c                                 |    8 +
+ fs/hfsplus/catalog.c                               |   36 +-
+ fs/hfsplus/dir.c                                   |   55 +-
+ fs/hfsplus/extents.c                               |   28 +-
+ fs/hfsplus/hfsplus_fs.h                            |   52 +-
+ fs/hfsplus/hfsplus_raw.h                           |   68 +-
+ fs/hfsplus/inode.c                                 |   18 +-
+ fs/hfsplus/ioctl.c                                 |  108 --
+ fs/hfsplus/super.c                                 |   56 +-
+ fs/hfsplus/unicode.c                               |    7 +-
+ fs/hfsplus/xattr.c                                 |  709 +++++++++
+ fs/hfsplus/xattr.h                                 |   60 +
+ fs/hfsplus/xattr_security.c                        |  104 ++
+ fs/hfsplus/xattr_trusted.c                         |   63 +
+ fs/hfsplus/xattr_user.c                            |   63 +
+ fs/hugetlbfs/inode.c                               |  109 +-
+ fs/inode.c                                         |    2 +-
+ fs/ncpfs/ioctl.c                                   |    2 +-
+ fs/nilfs2/page.c                                   |    2 +-
+ fs/notify/Makefile                                 |    2 +-
+ fs/notify/fanotify/fanotify_user.c                 |    2 +
+ fs/notify/fdinfo.c                                 |  150 ++
+ fs/notify/fdinfo.h                                 |   27 +
+ fs/notify/inotify/inotify_user.c                   |    2 +
+ fs/ocfs2/file.c                                    |    5 +-
+ fs/proc/array.c                                    |   21 +-
+ fs/proc/base.c                                     |   16 +-
+ fs/proc/fd.c                                       |    2 +
+ fs/proc/kcore.c                                    |    2 +-
+ fs/proc/proc_devtree.c                             |    6 +-
+ fs/proc/task_mmu.c                                 |   59 +-
+ fs/signalfd.c                                      |   18 +
+ fs/splice.c                                        |    5 +-
+ fs/ubifs/debug.c                                   |    8 +-
+ fs/udf/file.c                                      |    2 +-
+ include/linux/audit.h                              |    3 +-
+ include/linux/backlight.h                          |   10 +
+ include/linux/balloon_compaction.h                 |  280 ++++
+ include/linux/binfmts.h                            |    3 +-
+ include/linux/bootmem.h                            |    4 +-
+ include/linux/compat.h                             |    3 +
+ include/linux/compiler.h                           |    2 +
+ include/linux/cpuset.h                             |    2 +-
+ include/linux/exportfs.h                           |    2 +
+ include/linux/fs.h                                 |    6 +-
+ include/linux/gfp.h                                |   11 +-
+ include/linux/huge_mm.h                            |   22 +-
+ include/linux/hugetlb.h                            |    7 +-
+ include/linux/init.h                               |   40 +-
+ include/linux/ipc_namespace.h                      |    1 +
+ include/linux/kernel.h                             |   47 +-
+ include/linux/loop.h                               |    3 +
+ include/linux/memcontrol.h                         |  218 ++-
+ include/linux/memory.h                             |    2 +
+ include/linux/memory_hotplug.h                     |   13 +-
+ include/linux/migrate.h                            |   19 +
+ include/linux/mm.h                                 |   39 +
+ include/linux/mm_types.h                           |   19 +-
+ include/linux/mmzone.h                             |   50 +-
+ include/linux/msg.h                                |    6 +-
+ include/linux/node.h                               |    3 +-
+ include/linux/nodemask.h                           |    5 +
+ include/linux/oom.h                                |   21 +-
+ include/linux/page-isolation.h                     |   10 +-
+ include/linux/pagemap.h                            |   16 +
+ include/linux/percpu-rwsem.h                       |   91 +-
+ include/linux/platform_data/lp855x.h               |    9 +-
+ include/linux/proc_fs.h                            |    3 +
+ include/linux/ptrace.h                             |    2 +
+ include/linux/random.h                             |   19 +-
+ include/linux/res_counter.h                        |   17 +-
+ include/linux/rmap.h                               |    3 +
+ include/linux/sched.h                              |   14 +-
+ include/linux/shm.h                                |   15 +
+ include/linux/slab.h                               |   48 +
+ include/linux/slab_def.h                           |    3 +
+ include/linux/slub_def.h                           |    9 +-
+ include/linux/string.h                             |   11 +
+ include/linux/thread_info.h                        |    2 +
+ include/linux/types.h                              |    1 +
+ include/linux/vm_event_item.h                      |    9 +-
+ include/linux/wait.h                               |  166 +++
+ include/linux/writeback.h                          |    9 +-
+ include/trace/events/filemap.h                     |   79 +
+ include/trace/events/gfpflags.h                    |    1 +
+ include/trace/events/oom.h                         |    4 +-
+ include/trace/events/task.h                        |    8 +-
+ include/uapi/asm-generic/mman-common.h             |   11 +
+ include/uapi/asm-generic/mman.h                    |    2 +
+ include/uapi/linux/audit.h                         |    1 +
+ include/uapi/linux/eventpoll.h                     |    1 +
+ include/uapi/linux/msg.h                           |    1 +
+ include/uapi/linux/ptrace.h                        |    5 +-
+ include/uapi/linux/xattr.h                         |   13 +-
+ init/Kconfig                                       |    3 +-
+ init/main.c                                        |    2 +-
+ ipc/compat.c                                       |   46 +-
+ ipc/ipc_sysctl.c                                   |   32 +
+ ipc/msg.c                                          |  123 +-
+ ipc/msgutil.c                                      |   43 +
+ ipc/sem.c                                          |  250 +++-
+ ipc/shm.c                                          |    3 +-
+ ipc/util.c                                         |   16 +-
+ ipc/util.h                                         |    2 +
+ kernel/audit.c                                     |    4 +
+ kernel/audit_tree.c                                |   26 +-
+ kernel/audit_watch.c                               |    2 +
+ kernel/auditsc.c                                   |   20 +-
+ kernel/cgroup.c                                    |    1 -
+ kernel/compat.c                                    |   17 +
+ kernel/cpuset.c                                    |   32 +-
+ kernel/fork.c                                      |   11 +-
+ kernel/irq/manage.c                                |    2 +-
+ kernel/kthread.c                                   |    2 +-
+ kernel/module.c                                    |    3 -
+ kernel/pid.c                                       |   15 -
+ kernel/printk.c                                    |   40 +-
+ kernel/ptrace.c                                    |    3 +
+ kernel/res_counter.c                               |   42 +-
+ kernel/time.c                                      |    4 +-
+ kernel/timeconst.pl                                |    2 +-
+ kernel/trace/trace_uprobe.c                        |    8 +-
+ kernel/watchdog.c                                  |   10 +-
+ lib/Kconfig                                        |    3 +
+ lib/Makefile                                       |    1 +
+ lib/cpumask.c                                      |    2 +-
+ lib/dynamic_debug.c                                |    9 +-
+ lib/interval_tree_test_main.c                      |    7 +-
+ lib/kstrtox.c                                      |   64 +
+ lib/percpu-rwsem.c                                 |  165 +++
+ lib/random32.c                                     |   97 +-
+ lib/rbtree_test.c                                  |    6 +-
+ lib/scatterlist.c                                  |    3 +-
+ lib/vsprintf.c                                     |  104 +-
+ mm/Kconfig                                         |   23 +
+ mm/Makefile                                        |    3 +-
+ mm/balloon_compaction.c                            |  304 ++++
+ mm/bootmem.c                                       |   73 +-
+ mm/compaction.c                                    |  135 +-
+ mm/dmapool.c                                       |   29 +-
+ mm/filemap.c                                       |    5 +
+ mm/highmem.c                                       |   29 +-
+ mm/huge_memory.c                                   |  518 +++++--
+ mm/hugetlb.c                                       |   28 +-
+ mm/internal.h                                      |   53 +
+ mm/ksm.c                                           |   21 +-
+ mm/memblock.c                                      |    5 +
+ mm/memcontrol.c                                    | 1547 +++++++++++++++++---
+ mm/memory-failure.c                                |   28 +-
+ mm/memory.c                                        |   29 +-
+ mm/memory_hotplug.c                                |  415 +++++-
+ mm/mempolicy.c                                     |   35 +-
+ mm/migrate.c                                       |  102 +-
+ mm/mmap.c                                          |  517 +++++--
+ mm/mprotect.c                                      |    2 +-
+ mm/mremap.c                                        |    2 +-
+ mm/nobootmem.c                                     |   22 +
+ mm/oom_kill.c                                      |  138 +-
+ mm/page-writeback.c                                |   11 +-
+ mm/page_alloc.c                                    |  343 +++--
+ mm/page_cgroup.c                                   |    5 +-
+ mm/page_isolation.c                                |   27 +-
+ mm/pagewalk.c                                      |    2 +-
+ mm/rmap.c                                          |   59 +-
+ mm/shmem.c                                         |    1 +
+ mm/slab.c                                          |   94 +-
+ mm/slab.h                                          |  137 +-
+ mm/slab_common.c                                   |  118 +-
+ mm/slob.c                                          |    2 +-
+ mm/slub.c                                          |  154 +-
+ mm/sparse.c                                        |   25 +-
+ mm/swap_state.c                                    |    6 +
+ mm/swapfile.c                                      |   31 +-
+ mm/truncate.c                                      |    8 +-
+ mm/vmalloc.c                                       |    4 +-
+ mm/vmscan.c                                        |   32 +-
+ mm/vmstat.c                                        |   21 +-
+ scripts/checkpatch.pl                              |   94 +-
+ scripts/coccinelle/api/d_find_alias.cocci          |   80 +
+ scripts/pnmtologo.c                                |    8 +-
+ scripts/tags.sh                                    |   41 +-
+ sound/Kconfig                                      |    3 -
+ sound/sound_core.c                                 |    3 +-
+ tools/testing/selftests/Makefile                   |    2 +-
+ tools/testing/selftests/breakpoints/Makefile       |    2 +-
+ tools/testing/selftests/cpu-hotplug/Makefile       |    2 +-
+ tools/testing/selftests/epoll/Makefile             |   11 +
+ tools/testing/selftests/epoll/test_epoll.c         |  364 +++++
+ tools/testing/selftests/ipc/Makefile               |   25 +
+ tools/testing/selftests/ipc/msgque.c               |  246 ++++
+ tools/testing/selftests/kcmp/Makefile              |    6 +-
+ tools/testing/selftests/kcmp/kcmp_test.c           |    6 +-
+ tools/testing/selftests/memory-hotplug/Makefile    |    2 +-
+ tools/testing/selftests/mqueue/Makefile            |    4 +-
+ tools/testing/selftests/vm/Makefile                |    6 +-
+ tools/testing/selftests/vm/thuge-gen.c             |  254 ++++
+ 384 files changed, 12496 insertions(+), 4009 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/rtc/imxdi-rtc.txt
+ create mode 100644 Documentation/devicetree/bindings/rtc/rtc-omap.txt
+ create mode 100644 Documentation/devicetree/bindings/video/ssd1307fb.txt
+ create mode 100644 drivers/rtc/rtc-pcf8523.c
+ create mode 100644 drivers/video/ssd1307fb.c
+ create mode 100644 fs/hfsplus/attributes.c
+ create mode 100644 fs/hfsplus/xattr.c
+ create mode 100644 fs/hfsplus/xattr.h
+ create mode 100644 fs/hfsplus/xattr_security.c
+ create mode 100644 fs/hfsplus/xattr_trusted.c
+ create mode 100644 fs/hfsplus/xattr_user.c
+ create mode 100644 fs/notify/fdinfo.c
+ create mode 100644 fs/notify/fdinfo.h
+ create mode 100644 include/linux/balloon_compaction.h
+ create mode 100644 include/trace/events/filemap.h
+ create mode 100644 lib/percpu-rwsem.c
+ create mode 100644 mm/balloon_compaction.c
+ create mode 100644 scripts/coccinelle/api/d_find_alias.cocci
+ create mode 100644 tools/testing/selftests/epoll/Makefile
+ create mode 100644 tools/testing/selftests/epoll/test_epoll.c
+ create mode 100644 tools/testing/selftests/ipc/Makefile
+ create mode 100644 tools/testing/selftests/ipc/msgque.c
+ create mode 100644 tools/testing/selftests/vm/thuge-gen.c
diff --git a/Next/quilt-import.log b/Next/quilt-import.log
new file mode 100644
index 0000000..a4f16dc
--- /dev/null
+++ b/Next/quilt-import.log
@@ -0,0 +1,6 @@
+Importing i2c based on 2844a48706e54ddda4a04269dba4250b42f449de
+Unchanged quilt series i2c
+Importing jdelvare-hwmon based on 2844a48706e54ddda4a04269dba4250b42f449de
+Unchanged quilt series jdelvare-hwmon
+Importing device-mapper based on v3.7-rc1
+Unchanged quilt series device-mapper
diff --git a/README b/README
index f32710a..a24ec89 100644
--- a/README
+++ b/README
@@ -180,6 +180,10 @@ CONFIGURING the kernel:
                         with questions already answered.
                         Additionally updates the dependencies.
 
+     "make olddefconfig"
+                        Like above, but sets new symbols to their default
+                        values without prompting.
+
      "make defconfig"   Create a ./.config file by using the default
                         symbol values from either arch/$ARCH/defconfig
                         or arch/$ARCH/configs/${PLATFORM}_defconfig,
diff --git a/arch/Kconfig b/arch/Kconfig
index 366ec06..28998a2 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -80,6 +80,7 @@ config UPROBES
 	bool "Transparent user-space probes (EXPERIMENTAL)"
 	depends on UPROBE_EVENT && PERF_EVENTS
 	default n
+	select PERCPU_RWSEM
 	help
 	  Uprobes is the user-space counterpart to kprobes: they
 	  enable instrumentation applications (such as 'perf probe')
@@ -271,6 +272,13 @@ config ARCH_WANT_OLD_COMPAT_IPC
 	select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
 	bool
 
+config ARCH_NO_VIRT_TO_BUS
+	bool
+	help
+	  An architecture should select this if it cannot (or will not)
+	  implement virt_to_bus().  All new architectures should probably
+	  select this.
+
 config GENERIC_KERNEL_THREAD
 	bool
 
@@ -300,15 +308,16 @@ config SECCOMP_FILTER
 
 	  See Documentation/prctl/seccomp_filter.txt for details.
 
-config HAVE_RCU_USER_QS
+config HAVE_CONTEXT_TRACKING
 	bool
 	help
-	  Provide kernel entry/exit hooks necessary for userspace
-	  RCU extended quiescent state. Syscalls need to be wrapped inside
-	  rcu_user_exit()-rcu_user_enter() through the slow path using
-	  TIF_NOHZ flag. Exceptions handlers must be wrapped as well. Irqs
-	  are already protected inside rcu_irq_enter/rcu_irq_exit() but
-	  preemption or signal handling on irq exit still need to be protected.
+	  Provide kernel/user boundaries probes necessary for subsystems
+	  that need it, such as userspace RCU extended quiescent state.
+	  Syscalls need to be wrapped inside user_exit()-user_enter() through
+	  the slow path using TIF_NOHZ flag. Exceptions handlers must be
+	  wrapped as well. Irqs are already protected inside
+	  rcu_irq_enter/rcu_irq_exit() but preemption or signal handling on
+	  irq exit still need to be protected.
 
 config HAVE_VIRT_CPU_ACCOUNTING
 	bool
@@ -341,4 +350,15 @@ config MODULES_USE_ELF_REL
 	  Modules only use ELF REL relocations.  Modules with ELF RELA
 	  relocations will give an error.
 
+config CLONE_BACKWARDS
+	bool
+	help
+	  Architecture has tls passed as the 4th argument of clone(2),
+	  not the 5th one.
+
+config CLONE_BACKWARDS2
+	bool
+	help
+	  Architecture has the first two arguments of clone(2) swapped.
+
 source "kernel/gcov/Kconfig"
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 5dd7f5d..65ec1c8 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -557,8 +557,7 @@ config NR_CPUS
           with working support have a maximum of 4 CPUs.
 
 config ARCH_DISCONTIGMEM_ENABLE
-	bool "Discontiguous Memory Support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	bool "Discontiguous Memory Support"
 	help
 	  Say Y to support efficient handling of discontiguous physical memory,
 	  for architectures which are either NUMA (Non-Uniform Memory Access)
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 64ffc9e..dcfabb9 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -11,3 +11,4 @@ header-y += reg.h
 header-y += regdef.h
 header-y += sysinfo.h
 generic-y += exec.h
+generic-y += trace_clock.h
diff --git a/arch/alpha/include/asm/ioctls.h b/arch/alpha/include/asm/ioctls.h
index 80e1cee..92c557b 100644
--- a/arch/alpha/include/asm/ioctls.h
+++ b/arch/alpha/include/asm/ioctls.h
@@ -95,6 +95,9 @@
 #define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
 #define TIOCVHANGUP	0x5437
+#define TIOCGPKT	_IOR('T', 0x38, int) /* Get packet mode state */
+#define TIOCGPTLCK	_IOR('T', 0x39, int) /* Get Pty lock state */
+#define TIOCGEXCL	_IOR('T', 0x40, int) /* Get exclusive mode state */
 
 #define TIOCSERCONFIG	0x5453
 #define TIOCSERGWILD	0x5454
diff --git a/arch/alpha/include/asm/mman.h b/arch/alpha/include/asm/mman.h
index cbeb361..0086b47 100644
--- a/arch/alpha/include/asm/mman.h
+++ b/arch/alpha/include/asm/mman.h
@@ -63,4 +63,15 @@
 /* compatibility flags */
 #define MAP_FILE	0
 
+/*
+ * When MAP_HUGETLB is set bits [26:31] encode the log2 of the huge page size.
+ * This gives us 6 bits, which is enough until someone invents 128 bit address
+ * spaces.
+ *
+ * Assume these are all power of twos.
+ * When 0 use the default page size.
+ */
+#define MAP_HUGE_SHIFT	26
+#define MAP_HUGE_MASK	0x3f
+
 #endif /* __ALPHA_MMAN_H__ */
diff --git a/arch/alpha/include/asm/ptrace.h b/arch/alpha/include/asm/ptrace.h
index b87755a..b4c5b2f 100644
--- a/arch/alpha/include/asm/ptrace.h
+++ b/arch/alpha/include/asm/ptrace.h
@@ -78,6 +78,7 @@ struct switch_stack {
 
 #define current_pt_regs() \
   ((struct pt_regs *) ((char *)current_thread_info() + 2*PAGE_SIZE) - 1)
+#define signal_pt_regs current_pt_regs
 
 #define force_successful_syscall_return() (current_pt_regs()->r0 = 0)
 
diff --git a/arch/alpha/include/asm/signal.h b/arch/alpha/include/asm/signal.h
index a938830..4555286 100644
--- a/arch/alpha/include/asm/signal.h
+++ b/arch/alpha/include/asm/signal.h
@@ -164,9 +164,6 @@ struct sigstack {
 
 #ifdef __KERNEL__
 #include <asm/sigcontext.h>
-
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
 #endif
 
 #endif
diff --git a/arch/alpha/include/asm/socket.h b/arch/alpha/include/asm/socket.h
index 7d2f75b..0087d05 100644
--- a/arch/alpha/include/asm/socket.h
+++ b/arch/alpha/include/asm/socket.h
@@ -47,6 +47,7 @@
 /* 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
diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h
index 7826e22..eb3a466 100644
--- a/arch/alpha/include/asm/unistd.h
+++ b/arch/alpha/include/asm/unistd.h
@@ -482,6 +482,9 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_CLONE
 
 /* "Conditional" syscalls.  What we want is
 
diff --git a/arch/alpha/kernel/binfmt_loader.c b/arch/alpha/kernel/binfmt_loader.c
index d1f474d..9525660 100644
--- a/arch/alpha/kernel/binfmt_loader.c
+++ b/arch/alpha/kernel/binfmt_loader.c
@@ -5,7 +5,7 @@
 #include <linux/binfmts.h>
 #include <linux/a.out.h>
 
-static int load_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+static int load_binary(struct linux_binprm *bprm)
 {
 	struct exec *eh = (struct exec *)bprm->buf;
 	unsigned long loader;
@@ -37,7 +37,7 @@ static int load_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 	retval = prepare_binprm(bprm);
 	if (retval < 0)
 		return retval;
-	return search_binary_handler(bprm,regs);
+	return search_binary_handler(bprm);
 }
 
 static struct linux_binfmt loader_format = {
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index a760783..f62a994 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -612,47 +612,24 @@ ret_from_kernel_thread:
  * Special system calls.  Most of these are special in that they either
  * have to play switch_stack games or in some way use the pt_regs struct.
  */
-	.align	4
-	.globl	sys_fork
-	.ent	sys_fork
-sys_fork:
-	.prologue 0
-	mov	$sp, $21
-	bsr	$1, do_switch_stack
-	bis	$31, SIGCHLD, $16
-	mov	$31, $17
-	mov	$31, $18
-	mov	$31, $19
-	mov	$31, $20
-	jsr	$26, alpha_clone
-	bsr	$1, undo_switch_stack
-	ret
-.end sys_fork
 
+.macro	fork_like name
 	.align	4
-	.globl	sys_clone
-	.ent	sys_clone
-sys_clone:
+	.globl	alpha_\name
+	.ent	alpha_\name
+alpha_\name:
 	.prologue 0
-	mov	$sp, $21
 	bsr	$1, do_switch_stack
-	/* $16, $17, $18, $19, $20 come from the user.  */
-	jsr	$26, alpha_clone
-	bsr	$1, undo_switch_stack
+	jsr	$26, sys_\name
+	ldq	$26, 56($sp)
+	lda	$sp, SWITCH_STACK_SIZE($sp)
 	ret
-.end sys_clone
+.end	alpha_\name
+.endm
 
-	.align	4
-	.globl	sys_vfork
-	.ent	sys_vfork
-sys_vfork:
-	.prologue 0
-	mov	$sp, $16
-	bsr	$1, do_switch_stack
-	jsr	$26, alpha_vfork
-	bsr	$1, undo_switch_stack
-	ret
-.end sys_vfork
+fork_like fork
+fork_like vfork
+fork_like clone
 
 	.align	4
 	.globl	sys_sigreturn
@@ -661,8 +638,6 @@ sys_sigreturn:
 	.prologue 0
 	lda	$9, ret_from_straced
 	cmpult	$26, $9, $9
-	mov	$sp, $17
-	lda	$18, -SWITCH_STACK_SIZE($sp)
 	lda	$sp, -SWITCH_STACK_SIZE($sp)
 	jsr	$26, do_sigreturn
 	bne	$9, 1f
@@ -678,8 +653,6 @@ sys_rt_sigreturn:
 	.prologue 0
 	lda	$9, ret_from_straced
 	cmpult	$26, $9, $9
-	mov	$sp, $17
-	lda	$18, -SWITCH_STACK_SIZE($sp)
 	lda	$sp, -SWITCH_STACK_SIZE($sp)
 	jsr	$26, do_rt_sigreturn
 	bne	$9, 1f
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 3f844d2..a21d0ab 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -354,8 +354,7 @@ static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page,
 	struct pci_dev *pdev = alpha_gendev_to_pci(dev);
 	int dac_allowed;
 
-	if (dir == PCI_DMA_NONE)
-		BUG();
+	BUG_ON(dir == PCI_DMA_NONE);
 
 	dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0; 
 	return pci_map_single_1(pdev, (char *)page_address(page) + offset, 
@@ -378,8 +377,7 @@ static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr,
 	struct pci_iommu_arena *arena;
 	long dma_ofs, npages;
 
-	if (dir == PCI_DMA_NONE)
-		BUG();
+	BUG_ON(dir == PCI_DMA_NONE);
 
 	if (dma_addr >= __direct_map_base
 	    && dma_addr < __direct_map_base + __direct_map_size) {
@@ -662,8 +660,7 @@ static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
 	dma_addr_t max_dma;
 	int dac_allowed;
 
-	if (dir == PCI_DMA_NONE)
-		BUG();
+	BUG_ON(dir == PCI_DMA_NONE);
 
 	dac_allowed = dev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
 
@@ -742,8 +739,7 @@ static void alpha_pci_unmap_sg(struct device *dev, struct scatterlist *sg,
 	dma_addr_t max_dma;
 	dma_addr_t fbeg, fend;
 
-	if (dir == PCI_DMA_NONE)
-		BUG();
+	BUG_ON(dir == PCI_DMA_NONE);
 
 	if (! alpha_mv.mv_pci_tbi)
 		return;
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 51987dc..b5d0d09 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -235,51 +235,28 @@ release_thread(struct task_struct *dead_task)
 }
 
 /*
- * "alpha_clone()".. By the time we get here, the
- * non-volatile registers have also been saved on the
- * stack. We do some ugly pointer stuff here.. (see
- * also copy_thread)
- *
- * Notice that "fork()" is implemented in terms of clone,
- * with parameters (SIGCHLD, 0).
- */
-int
-alpha_clone(unsigned long clone_flags, unsigned long usp,
-	    int __user *parent_tid, int __user *child_tid,
-	    unsigned long tls_value, struct pt_regs *regs)
-{
-	if (!usp)
-		usp = rdusp();
-
-	return do_fork(clone_flags, usp, regs, 0, parent_tid, child_tid);
-}
-
-int
-alpha_vfork(struct pt_regs *regs)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(),
-		       regs, 0, NULL, NULL);
-}
-
-/*
  * Copy an alpha thread..
  */
 
 int
 copy_thread(unsigned long clone_flags, unsigned long usp,
 	    unsigned long arg,
-	    struct task_struct * p, struct pt_regs * regs)
+	    struct task_struct *p)
 {
 	extern void ret_from_fork(void);
 	extern void ret_from_kernel_thread(void);
 
 	struct thread_info *childti = task_thread_info(p);
 	struct pt_regs *childregs = task_pt_regs(p);
+	struct pt_regs *regs = current_pt_regs();
 	struct switch_stack *childstack, *stack;
 	unsigned long settls;
 
 	childstack = ((struct switch_stack *) childregs) - 1;
-	if (unlikely(!regs)) {
+	childti->pcb.ksp = (unsigned long) childstack;
+	childti->pcb.flags = 1;	/* set FEN, clear everything else */
+
+	if (unlikely(p->flags & PF_KTHREAD)) {
 		/* kernel thread */
 		memset(childstack, 0,
 			sizeof(struct switch_stack) + sizeof(struct pt_regs));
@@ -288,12 +265,17 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
 		childstack->r10 = arg;
 		childregs->hae = alpha_mv.hae_cache,
 		childti->pcb.usp = 0;
-		childti->pcb.ksp = (unsigned long) childstack;
-		childti->pcb.flags = 1;	/* set FEN, clear everything else */
 		return 0;
 	}
+	/* Note: if CLONE_SETTLS is not set, then we must inherit the
+	   value from the parent, which will have been set by the block
+	   copy in dup_task_struct.  This is non-intuitive, but is
+	   required for proper operation in the case of a threaded
+	   application calling fork.  */
+	if (clone_flags & CLONE_SETTLS)
+		childti->pcb.unique = regs->r20;
+	childti->pcb.usp = usp ?: rdusp();
 	*childregs = *regs;
-	settls = regs->r20;
 	childregs->r0 = 0;
 	childregs->r19 = 0;
 	childregs->r20 = 1;	/* OSF/1 has some strange fork() semantics.  */
@@ -301,22 +283,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
 	stack = ((struct switch_stack *) regs) - 1;
 	*childstack = *stack;
 	childstack->r26 = (unsigned long) ret_from_fork;
-	childti->pcb.usp = usp;
-	childti->pcb.ksp = (unsigned long) childstack;
-	childti->pcb.flags = 1;	/* set FEN, clear everything else */
-
-	/* Set a new TLS for the child thread?  Peek back into the
-	   syscall arguments that we saved on syscall entry.  Oops,
-	   except we'd have clobbered it with the parent/child set
-	   of r20.  Read the saved copy.  */
-	/* Note: if CLONE_SETTLS is not set, then we must inherit the
-	   value from the parent, which will have been set by the block
-	   copy in dup_task_struct.  This is non-intuitive, but is
-	   required for proper operation in the case of a threaded
-	   application calling fork.  */
-	if (clone_flags & CLONE_SETTLS)
-		childti->pcb.unique = settls;
-
 	return 0;
 }
 
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 32575f8..336393c 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -160,10 +160,10 @@ extern char compile_time_assert
 #define INSN_CALLSYS		0x00000083
 
 static long
-restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
-		   struct switch_stack *sw)
+restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
 {
 	unsigned long usp;
+	struct switch_stack *sw = (struct switch_stack *)regs - 1;
 	long i, err = __get_user(regs->pc, &sc->sc_pc);
 
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
@@ -215,9 +215,9 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
    registers and transfer control from userland.  */
 
 asmlinkage void
-do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
-	     struct switch_stack *sw)
+do_sigreturn(struct sigcontext __user *sc)
 {
+	struct pt_regs *regs = current_pt_regs();
 	sigset_t set;
 
 	/* Verify that it's a good sigcontext before using it */
@@ -228,7 +228,7 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
 
 	set_current_blocked(&set);
 
-	if (restore_sigcontext(sc, regs, sw))
+	if (restore_sigcontext(sc, regs))
 		goto give_sigsegv;
 
 	/* Send SIGTRAP if we're single-stepping: */
@@ -249,9 +249,9 @@ give_sigsegv:
 }
 
 asmlinkage void
-do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,
-		struct switch_stack *sw)
+do_rt_sigreturn(struct rt_sigframe __user *frame)
 {
+	struct pt_regs *regs = current_pt_regs();
 	sigset_t set;
 
 	/* Verify that it's a good ucontext_t before using it */
@@ -262,7 +262,7 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,
 
 	set_current_blocked(&set);
 
-	if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
+	if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
 		goto give_sigsegv;
 
 	/* Send SIGTRAP if we're single-stepping: */
diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c
index 5d58652..59b7bba 100644
--- a/arch/alpha/kernel/srmcons.c
+++ b/arch/alpha/kernel/srmcons.c
@@ -205,7 +205,6 @@ static const struct tty_operations srmcons_ops = {
 static int __init
 srmcons_init(void)
 {
-	tty_port_init(&srmcons_singleton.port);
 	setup_timer(&srmcons_singleton.timer, srmcons_receive_chars,
 			(unsigned long)&srmcons_singleton);
 	if (srm_is_registered_console) {
@@ -215,6 +214,9 @@ srmcons_init(void)
 		driver = alloc_tty_driver(MAX_SRM_CONSOLE_DEVICES);
 		if (!driver)
 			return -ENOMEM;
+
+		tty_port_init(&srmcons_singleton.port);
+
 		driver->driver_name = "srm";
 		driver->name = "srm";
 		driver->major = 0; 	/* dynamic */
@@ -227,6 +229,7 @@ srmcons_init(void)
 		err = tty_register_driver(driver);
 		if (err) {
 			put_tty_driver(driver);
+			tty_port_destroy(&srmcons_singleton.port);
 			return err;
 		}
 		srmcons_driver = driver;
diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
index 2ac6b45..4284ec7 100644
--- a/arch/alpha/kernel/systbls.S
+++ b/arch/alpha/kernel/systbls.S
@@ -12,7 +12,7 @@
 sys_call_table:
 	.quad alpha_ni_syscall			/* 0 */
 	.quad sys_exit
-	.quad sys_fork
+	.quad alpha_fork
 	.quad sys_read
 	.quad sys_write
 	.quad alpha_ni_syscall			/* 5 */
@@ -76,7 +76,7 @@ sys_call_table:
 	.quad sys_getpgrp
 	.quad sys_getpagesize
 	.quad alpha_ni_syscall			/* 65 */
-	.quad sys_vfork
+	.quad alpha_vfork
 	.quad sys_newstat
 	.quad sys_newlstat
 	.quad alpha_ni_syscall
@@ -330,7 +330,7 @@ sys_call_table:
 	.quad sys_ni_syscall			/* 309: old get_kernel_syms */
 	.quad sys_syslog			/* 310 */
 	.quad sys_reboot
-	.quad sys_clone
+	.quad alpha_clone
 	.quad sys_uselib
 	.quad sys_mlock
 	.quad sys_munlock			/* 315 */
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ade7e92..1fd4208 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -5,6 +5,7 @@ config ARM
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select ARCH_HAVE_CUSTOM_GPIO_H
 	select ARCH_WANT_IPC_PARSE_VERSION
+	select BUILDTIME_EXTABLE_SORT if MMU
 	select CPU_PM if (SUSPEND || CPU_IDLE)
 	select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && !CPU_BIG_ENDIAN
 	select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI)
@@ -21,6 +22,7 @@ config ARM
 	select HAVE_AOUT
 	select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
 	select HAVE_ARCH_KGDB
+	select HAVE_ARCH_SECCOMP_FILTER
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_BPF_JIT
 	select HAVE_C_RECORDMCOUNT
@@ -55,6 +57,7 @@ config ARM
 	select SYS_SUPPORTS_APM_EMULATION
 	select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND
 	select MODULES_USE_ELF_REL
+	select CLONE_BACKWARDS
 	help
 	  The ARM series is a line of low-power-consumption RISC chip designs
 	  licensed by ARM Ltd and targeted at embedded applications and
@@ -284,8 +287,8 @@ config ARCH_INTEGRATOR
 	select MULTI_IRQ_HANDLER
 	select NEED_MACH_MEMORY_H
 	select PLAT_VERSATILE
-	select PLAT_VERSATILE_FPGA_IRQ
 	select SPARSE_IRQ
+	select VERSATILE_FPGA_IRQ
 	help
 	  Support for ARM's Integrator platform.
 
@@ -318,7 +321,7 @@ config ARCH_VERSATILE
 	select PLAT_VERSATILE
 	select PLAT_VERSATILE_CLCD
 	select PLAT_VERSATILE_CLOCK
-	select PLAT_VERSATILE_FPGA_IRQ
+	select VERSATILE_FPGA_IRQ
 	help
 	  This enables support for ARM Ltd Versatile board.
 
@@ -330,13 +333,15 @@ config ARCH_AT91
 	select IRQ_DOMAIN
 	select NEED_MACH_GPIO_H
 	select NEED_MACH_IO_H if PCCARD
+	select PINCTRL
+	select PINCTRL_AT91 if USE_OF
 	help
 	  This enables support for systems based on Atmel
 	  AT91RM9200 and AT91SAM9* processors.
 
 config ARCH_BCM2835
 	bool "Broadcom BCM2835 family"
-	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select ARCH_REQUIRE_GPIOLIB
 	select ARM_AMBA
 	select ARM_ERRATA_411920
 	select ARM_TIMER_SP804
@@ -344,7 +349,10 @@ config ARCH_BCM2835
 	select COMMON_CLK
 	select CPU_V6
 	select GENERIC_CLOCKEVENTS
+	select GENERIC_GPIO
 	select MULTI_IRQ_HANDLER
+	select PINCTRL
+	select PINCTRL_BCM2835
 	select SPARSE_IRQ
 	select USE_OF
 	help
@@ -364,11 +372,16 @@ config ARCH_CNS3XXX
 
 config ARCH_CLPS711X
 	bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
+	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_USES_GETTIMEOFFSET
+	select AUTO_ZRELADDR
 	select CLKDEV_LOOKUP
 	select COMMON_CLK
 	select CPU_ARM720T
+	select GENERIC_CLOCKEVENTS
+	select MULTI_IRQ_HANDLER
 	select NEED_MACH_MEMORY_H
+	select SPARSE_IRQ
 	help
 	  Support for Cirrus Logic 711x/721x/731x based boards.
 
@@ -433,19 +446,6 @@ config ARCH_FOOTBRIDGE
 	  Support for systems based on the DC21285 companion chip
 	  ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
 
-config ARCH_MXC
-	bool "Freescale MXC/iMX-based"
-	select ARCH_REQUIRE_GPIOLIB
-	select CLKDEV_LOOKUP
-	select CLKSRC_MMIO
-	select GENERIC_CLOCKEVENTS
-	select GENERIC_IRQ_CHIP
-	select MULTI_IRQ_HANDLER
-	select SPARSE_IRQ
-	select USE_OF
-	help
-	  Support for Freescale MXC/iMX-based family of processors
-
 config ARCH_MXS
 	bool "Freescale MXS-based"
 	select ARCH_REQUIRE_GPIOLIB
@@ -536,6 +536,8 @@ config ARCH_DOVE
 	select CPU_V7
 	select GENERIC_CLOCKEVENTS
 	select MIGHT_HAVE_PCI
+	select PINCTRL
+	select PINCTRL_DOVE
 	select PLAT_ORION_LEGACY
 	select USB_ARCH_HAS_EHCI
 	help
@@ -547,6 +549,9 @@ config ARCH_KIRKWOOD
 	select CPU_FEROCEON
 	select GENERIC_CLOCKEVENTS
 	select PCI
+	select PCI_QUIRKS
+	select PINCTRL
+	select PINCTRL_KIRKWOOD
 	select PLAT_ORION_LEGACY
 	help
 	  Support for the following Marvell Kirkwood series SoCs:
@@ -644,6 +649,7 @@ config ARCH_TEGRA
 	select HAVE_CLK
 	select HAVE_SMP
 	select MIGHT_HAVE_CACHE_L2X0
+	select SPARSE_IRQ
 	select USE_OF
 	help
 	  This enables support for NVIDIA Tegra based systems (Tegra APX,
@@ -885,6 +891,7 @@ config ARCH_U8500
 	select GENERIC_CLOCKEVENTS
 	select HAVE_SMP
 	select MIGHT_HAVE_CACHE_L2X0
+	select SPARSE_IRQ
 	help
 	  Support for ST-Ericsson's Ux500 architecture
 
@@ -899,11 +906,13 @@ config ARCH_NOMADIK
 	select MIGHT_HAVE_CACHE_L2X0
 	select PINCTRL
 	select PINCTRL_STN8815
+	select SPARSE_IRQ
 	help
 	  Support for the Nomadik platform by ST-Ericsson
 
 config PLAT_SPEAR
 	bool "ST SPEAr"
+	select ARCH_HAS_CPUFREQ
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_AMBA
 	select CLKDEV_LOOKUP
@@ -924,6 +933,7 @@ config ARCH_DAVINCI
 	select GENERIC_IRQ_CHIP
 	select HAVE_IDE
 	select NEED_MACH_GPIO_H
+	select USE_OF
 	select ZONE_DMA
 	help
 	  Support for TI's DaVinci platform.
@@ -937,11 +947,10 @@ config ARCH_OMAP
 	select CLKSRC_MMIO
 	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
-	select NEED_MACH_GPIO_H
 	help
 	  Support for TI's OMAP platform (OMAP1/2/3/4).
 
-config ARCH_VT8500
+config ARCH_VT8500_SINGLE
 	bool "VIA/WonderMedia 85xx"
 	select ARCH_HAS_CPUFREQ
 	select ARCH_REQUIRE_GPIOLIB
@@ -951,22 +960,12 @@ config ARCH_VT8500
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_GPIO
 	select HAVE_CLK
+	select MULTI_IRQ_HANDLER
+	select SPARSE_IRQ
 	select USE_OF
 	help
 	  Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
 
-config ARCH_ZYNQ
-	bool "Xilinx Zynq ARM Cortex A9 Platform"
-	select ARM_AMBA
-	select ARM_GIC
-	select CLKDEV_LOOKUP
-	select CPU_V7
-	select GENERIC_CLOCKEVENTS
-	select ICST
-	select MIGHT_HAVE_CACHE_L2X0
-	select USE_OF
-	help
-	  Support for Xilinx Zynq ARM Cortex A9 Platform
 endchoice
 
 menu "Multiple platform selection"
@@ -1022,6 +1021,8 @@ source "arch/arm/mach-mvebu/Kconfig"
 
 source "arch/arm/mach-at91/Kconfig"
 
+source "arch/arm/mach-bcm/Kconfig"
+
 source "arch/arm/mach-clps711x/Kconfig"
 
 source "arch/arm/mach-cns3xxx/Kconfig"
@@ -1058,14 +1059,13 @@ source "arch/arm/mach-msm/Kconfig"
 
 source "arch/arm/mach-mv78xx0/Kconfig"
 
-source "arch/arm/plat-mxc/Kconfig"
+source "arch/arm/mach-imx/Kconfig"
 
 source "arch/arm/mach-mxs/Kconfig"
 
 source "arch/arm/mach-netx/Kconfig"
 
 source "arch/arm/mach-nomadik/Kconfig"
-source "arch/arm/plat-nomadik/Kconfig"
 
 source "arch/arm/plat-omap/Kconfig"
 
@@ -1113,6 +1113,8 @@ source "arch/arm/mach-exynos/Kconfig"
 
 source "arch/arm/mach-shmobile/Kconfig"
 
+source "arch/arm/mach-sunxi/Kconfig"
+
 source "arch/arm/mach-prima2/Kconfig"
 
 source "arch/arm/mach-tegra/Kconfig"
@@ -1126,8 +1128,12 @@ source "arch/arm/mach-versatile/Kconfig"
 source "arch/arm/mach-vexpress/Kconfig"
 source "arch/arm/plat-versatile/Kconfig"
 
+source "arch/arm/mach-vt8500/Kconfig"
+
 source "arch/arm/mach-w90x900/Kconfig"
 
+source "arch/arm/mach-zynq/Kconfig"
+
 # Definitions to make life easier
 config ARCH_ACORN
 	bool
@@ -1168,7 +1174,7 @@ config ARM_NR_BANKS
 config IWMMXT
 	bool "Enable iWMMXt support"
 	depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4
-	default y if PXA27x || PXA3xx || PXA95x || ARCH_MMP
+	default y if PXA27x || PXA3xx || ARCH_MMP
 	help
 	  Enable support for iWMMXt context switching at run time if
 	  running on a CPU that supports it.
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index b0f3857..661030d 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -132,6 +132,23 @@ choice
 		  their output to UART1 serial port on DaVinci TNETV107X
 		  devices.
 
+	config DEBUG_ZYNQ_UART0
+		bool "Kernel low-level debugging on Xilinx Zynq using UART0"
+		depends on ARCH_ZYNQ
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to UART0 on the Zynq platform.
+
+	config DEBUG_ZYNQ_UART1
+		bool "Kernel low-level debugging on Xilinx Zynq using UART1"
+		depends on ARCH_ZYNQ
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to UART1 on the Zynq platform.
+
+		  If you have a ZC702 board and want early boot messages to
+		  appear on the USB serial adaptor, select this option.
+
 	config DEBUG_DC21285_PORT
 		bool "Kernel low-level debugging messages via footbridge serial port"
 		depends on FOOTBRIDGE
@@ -209,20 +226,12 @@ choice
 		  Say Y here if you want kernel low-level debugging support
 		  on i.MX50 or i.MX53.
 
-	config DEBUG_IMX6Q_UART2
-		bool "i.MX6Q Debug UART2"
-		depends on SOC_IMX6Q
-		help
-		  Say Y here if you want kernel low-level debugging support
-		  on i.MX6Q UART2. This is correct for e.g. the SabreLite
-                  board.
-
-	config DEBUG_IMX6Q_UART4
-		bool "i.MX6Q Debug UART4"
+	config DEBUG_IMX6Q_UART
+		bool "i.MX6Q Debug UART"
 		depends on SOC_IMX6Q
 		help
 		  Say Y here if you want kernel low-level debugging support
-		  on i.MX6Q UART4.
+		  on i.MX6Q.
 
 	config DEBUG_MMP_UART2
 		bool "Kernel low-level debugging message via MMP UART2"
@@ -338,6 +347,17 @@ choice
 		  The uncompressor code port configuration is now handled
 		  by CONFIG_S3C_LOWLEVEL_UART_PORT.
 
+	config DEBUG_S3C_UART3
+		depends on PLAT_SAMSUNG && ARCH_EXYNOS
+		bool "Use S3C UART 3 for low-level debug"
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to UART 3. The port must have been initialised
+		  by the boot-loader before use.
+
+		  The uncompressor code port configuration is now handled
+		  by CONFIG_S3C_LOWLEVEL_UART_PORT.
+
 	config DEBUG_SOCFPGA_UART
 		depends on ARCH_SOCFPGA
 		bool "Use SOCFPGA UART for low-level debug"
@@ -345,6 +365,27 @@ choice
 		  Say Y here if you want kernel low-level debugging support
 		  on SOCFPGA based platforms.
 
+	config DEBUG_SUNXI_UART0
+		bool "Kernel low-level debugging messages via sunXi UART0"
+		depends on ARCH_SUNXI
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Allwinner A1X based platforms on the UART0.
+
+	config DEBUG_SUNXI_UART1
+		bool "Kernel low-level debugging messages via sunXi UART1"
+		depends on ARCH_SUNXI
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Allwinner A1X based platforms on the UART1.
+
+	config DEBUG_TEGRA_UART
+		depends on ARCH_TEGRA
+		bool "Use Tegra UART for low-level debug"
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Tegra based platforms.
+
 	config DEBUG_VEXPRESS_UART0_DETECT
 		bool "Autodetect UART0 on Versatile Express Cortex-A core tiles"
 		depends on ARCH_VEXPRESS && CPU_CP15_MMU
@@ -409,15 +450,64 @@ choice
 
 endchoice
 
+config DEBUG_IMX6Q_UART_PORT
+	int "i.MX6Q Debug UART Port (1-5)" if DEBUG_IMX6Q_UART
+	range 1 5
+	default 1
+	depends on SOC_IMX6Q
+	help
+	  Choose UART port on which kernel low-level debug messages
+	  should be output.
+
+choice
+	prompt "Low-level debug console UART"
+	depends on DEBUG_LL && DEBUG_TEGRA_UART
+
+	config TEGRA_DEBUG_UART_AUTO_ODMDATA
+	bool "Via ODMDATA"
+	help
+	  Automatically determines which UART to use for low-level debug based
+	  on the ODMDATA value. This value is part of the BCT, and is written
+	  to the boot memory device using nvflash, or other flashing tool.
+	  When bits 19:18 are 3, then bits 17:15 indicate which UART to use;
+	  0/1/2/3/4 are UART A/B/C/D/E.
+
+	config TEGRA_DEBUG_UARTA
+		bool "UART A"
+
+	config TEGRA_DEBUG_UARTB
+		bool "UART B"
+
+	config TEGRA_DEBUG_UARTC
+		bool "UART C"
+
+	config TEGRA_DEBUG_UARTD
+		bool "UART D"
+
+	config TEGRA_DEBUG_UARTE
+		bool "UART E"
+
+endchoice
+
 config DEBUG_LL_INCLUDE
 	string
 	default "debug/icedcc.S" if DEBUG_ICEDCC
+	default "debug/imx.S" if DEBUG_IMX1_UART || \
+				 DEBUG_IMX25_UART || \
+				 DEBUG_IMX21_IMX27_UART || \
+				 DEBUG_IMX31_IMX35_UART || \
+				 DEBUG_IMX51_UART || \
+				 DEBUG_IMX50_IMX53_UART ||\
+				 DEBUG_IMX6Q_UART
 	default "debug/highbank.S" if DEBUG_HIGHBANK_UART
 	default "debug/mvebu.S" if DEBUG_MVEBU_UART
 	default "debug/picoxcell.S" if DEBUG_PICOXCELL_UART
 	default "debug/socfpga.S" if DEBUG_SOCFPGA_UART
+	default "debug/sunxi.S" if DEBUG_SUNXI_UART0 || DEBUG_SUNXI_UART1
 	default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT || \
 		DEBUG_VEXPRESS_UART0_CA9 || DEBUG_VEXPRESS_UART0_RS1
+	default "debug/tegra.S" if DEBUG_TEGRA_UART
+	default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
 	default "mach/debug-macro.S"
 
 config EARLY_PRINTK
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 5f914fc..1ec5f67 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -137,6 +137,7 @@ textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000
 # Machine directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
 machine-$(CONFIG_ARCH_AT91)		+= at91
+machine-$(CONFIG_ARCH_BCM)		+= bcm
 machine-$(CONFIG_ARCH_BCM2835)		+= bcm2835
 machine-$(CONFIG_ARCH_CLPS711X)		+= clps711x
 machine-$(CONFIG_ARCH_CNS3XXX)		+= cns3xxx
@@ -193,15 +194,13 @@ machine-$(CONFIG_ARCH_SPEAR13XX)	+= spear13xx
 machine-$(CONFIG_ARCH_SPEAR3XX)		+= spear3xx
 machine-$(CONFIG_MACH_SPEAR600)		+= spear6xx
 machine-$(CONFIG_ARCH_ZYNQ)		+= zynq
+machine-$(CONFIG_ARCH_SUNXI)		+= sunxi
 
 # Platform directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
-plat-$(CONFIG_ARCH_MXC)		+= mxc
 plat-$(CONFIG_ARCH_OMAP)	+= omap
 plat-$(CONFIG_ARCH_S3C64XX)	+= samsung
-plat-$(CONFIG_ARCH_ZYNQ)	+= versatile
 plat-$(CONFIG_PLAT_IOP)		+= iop
-plat-$(CONFIG_PLAT_NOMADIK)	+= nomadik
 plat-$(CONFIG_PLAT_ORION)	+= orion
 plat-$(CONFIG_PLAT_PXA)		+= pxa
 plat-$(CONFIG_PLAT_S3C24XX)	+= s3c24xx samsung
diff --git a/arch/arm/arm-soc-for-next-contents.txt b/arch/arm/arm-soc-for-next-contents.txt
new file mode 100644
index 0000000..2237dda
--- /dev/null
+++ b/arch/arm/arm-soc-for-next-contents.txt
@@ -0,0 +1,168 @@
+arm-soc for-next contents for 3.8:
+
+External dependencies:
+depends/tty             gregkh's tty tree @54ec52b6dd3b0ba4bc4eb97e7e1b2534705b326c
+depends/omap-cleanup-headers-usb        git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap omap-for-v3.8/cleanup-headers-usb
+depends/omap-cleanup-headers-menelaus   git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap omap-for-v3.8/cleanup-headers-menelaus
+depends/clk:		common clock tree
+depends/asoc		renesas bits of the asoc tree
+depends/gpio-devel	gpio/devel branch @tag  gpio-for-grant-v3.8 (b53bc2819a71099ecfc3d61ba0796b3dcc6be321)
+depends/pinctrl-devel	pinctrl/devel branch @06763c741b0a1
+depends/pinctrl-devel2  pinctrl/devel branch @4ddb1c2
+
+next/fixes-non-critical:
+vexpress/fixes		git://git.linaro.org/people/pawelmoll/linux.git vexpress-fixes
+davinci/fixes		git://gitorious.org/linux-davinci/linux-davinci.git tags/davinci-for-v3.8/fixes
++patch <201211081405.23202.arnd@arndb.de>
+omap/fixes		git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.8/fixes-non-critical-v4-signed
+pxa/fixes		git://github.com/hzhuang1/linux.git armsoc/fix
+				refetched @ d90cb69
++patch <1353855220-5238-1-git-send-email-shc_work@mail.ru>
+
+next/headers:
+omap/headers		git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap omap-for-v3.8/cleanup-headers-signed
+omap/cleanup-headers-3  git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.8/cleanup-headers-part3-signed
+			depends on depends/tty and depends/omap-cleanup*
+omap/cleanup-prcm	git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.8/cleanup-prcm-part1-take2-signed
+at91/header		git://github.com/at91linux/linux-at91.git tags/for-3.8-at91_header_clean
+			+ re-pull from git://github.com/at91linux/linux-at91.git tags/at91-header
+omap/cleanup-headers-4  git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.8/cleanup-headers-prepare-multiplatform-v3-signed
++patch <1352970366-7154-1-git-send-email-haojian.zhuang@gmail.com>
+
+
+next/cleanup:
+imx/multiplatform	git://git.linaro.org/people/shawnguo/linux-2.6.git imx/multi-platform
+			(pulled twice)
+vt8500/cleanup		git://server.prisktech.co.nz/git/linuxwmt.git/ tags/cleanup-for-3.8
++ cherry-pick of "ARM: pxa: use module_platform_driver macro"
+zynq/cleanup		git://git.xilinx.com/linux-xlnx.git arm-next
+cleanups/dma		<1352360783-17523-1-git-send-email-m.szyprowski@samsung.com>
+omap/cleanup-fixes	git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.8/cleanup-fixes-signed
+				depends on omap/headers4
+omap/cleanup-prcm-part2	  git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.8/cleanup-prcm-part2-signed
+				depends on omap/headers4
+omap/cleanup-fixes-2	git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.8/cleanup-fixes-part2-v2-signed
+				depends on omap/cleanup-fixes
+at91/cleanup		git://github.com/at91linux/linux-at91.git tags/at91-for-next-cleanup
+tegra/cleanup		git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.8-cleanup
+bcm2835/cleanup		git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git bcm2835-for-3.8-cleanup
+samsung/cleanup		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/cleanup-samsung-2
+orion/cleanup		git://git.infradead.org/users/jcooper/linux.git tags/orion_cleanup_for_3.8
+integrator/cleanup	git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git tags/integrator-for-arm-soc
+
+next/soc:
+ux500/core		git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git ux500-core
+clps711x/soc           patches from Alexander Shiyan <shc_work@mail.ru>
+renesas/soc		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas soc
+calxeda/ecx-2000	git://sources.calxeda.com/kernel/linux.git tags/calxeda-ecx-2000
+integrator/irq		git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git tags/integrator-irq
++ patch "ARM: highbank: add ifdef guards to core.h"
++ patch <201211062208.47390.arnd@arndb.de>
+lpc32xx/soc		git://git.antcom.de/linux-2.6.git lpc32xx/core
+renesas/soc2		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git soc
+imx/soc			git://git.pengutronix.de/git/imx/linux-2.6.git tags/imx-soc
+				depends on imx/multiplatform
+davinci/soc		git://gitorious.org/linux-davinci/linux-davinci.git tags/davinci-for-v3.8/soc
++patch <1353347170-10257-1-git-send-email-csd@broadcom.com> "[PATCH V6] Add support for generic BCM SoC chipsets"
+sunxi/soc		git://github.com/mripard/linux.git tags/tags/sunxi-support-for-3.8
+tegra/soc		git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.8-soc
+tegra/cpuidle		git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.8-cpuidle
+tegra/defconfig		git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.8-defconfig
+bcm2835/soc		git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git bcm2835-for-3.8-soc
+bcm2835/defconfig	git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git bcm2835-for-3.8-defconfig
+vexpress/soc		git://git.linaro.org/people/pawelmoll/linux.git vexpress-clk-soc
+				depends on depends/clk
+				+patch
+calxeda/debug_ll	git://sources.calxeda.com/kernel/linux.git tags/highbank-debugll-cleanup
+calxeda/cpuidle		git://sources.calxeda.com/kernel/linux.git tags/highbank-cpuidle
+clps711x/soc2		Patch series from email <1353160644-22446-1-git-send-email-shc_work@mail.ru>
+samsung/pinctrl		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/pinctrl-samsung
+sunxi/soc2		git://github.com/mripard/linux.git tags/tags/sun4i-support-for-3.8
+imx/soc2		git://git.pengutronix.de/git/imx/linux-2.6.git tags/imx-soc-1
+sansung/exynos5440	git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/soc-exynos5440
++patch "ARM: EXYNOS: Avoid early use of of_machine_is_compatible()"
+
+next/boards:
+renesas/boards		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git boards
+renesas/defconfig	git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git defconfig
+omap/board		git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.8/board-v2-signed
+davinci/board		git://gitorious.org/linux-davinci/linux-davinci.git tags/davinci-for-v3.8/board
+				depends on davinci/soc
+davinci/defconfig	git://gitorious.org/linux-davinci/linux-davinci.git tags/davinci-for-v3.8/defconfig
+pxa/board		git://github.com/hzhuang1/linux.git armsoc/board
+samsung/boards		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/board-samsung
+imx/board		git://git.pengutronix.de/git/imx/linux-2.6.git tags/imx-board
+imx/defconfig		git://git.pengutronix.de/git/imx/linux-2.6.git tags/imx-defconfig
+orion/boards		git://git.infradead.org/users/jcooper/linux.git tags/orion_boards_for_3.8
+
+next/dt:
+ux500/dt		git://git.linaro.org/people/ljones/linux-3.0-ux500.git ste-dt-for-next
+				(pulled three times)
+omap/dt			git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.8/dt-signed
+                                depends on omap/headers4 and omap/cleanup-prcm
+imx/dt			git://git.pengutronix.de/git/imx/linux-2.6.git tags/imx-dt
+zynq/dt			git://git.xilinx.com/linux-xlnx.git arm-next
+				depends on zynq/cleanup
+mxs/dt			git://git.linaro.org/people/shawnguo/linux-2.6.git tags/mxs-dt-3.8
+				repulled at tags/mxs-dt-3.8-2
+imx/dt2			git://git.linaro.org/people/shawnguo/linux-2.6.git tags/imx-dt-3.8
+davinci/dt		git://gitorious.org/linux-davinci/linux-davinci.git tags/davinci-for-v3.8/dt
+				depends on davinci/soc
+				+ local patch to move dtb targets
+at91/dt			git://github.com/at91linux/linux-at91.git tags/at91-for-next-dt
+tegra/dt		git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.8-dt
+lpc32xx/dt		git://git.antcom.de/linux-2.6.git tags/lpc32xx-dts-for-3.7
+samsung/hdmi		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/hdmi-samsung
+samsung/dt		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/dt-samsung
+samsung/dt2		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/dt-samsung-2
+orion/dt		git://git.infradead.org/users/jcooper/linux.git tags/orion_dt_for_3.8
+
+next/multiplatform:
+vt8500/multiplatform	git://server.prisktech.co.nz/git/linuxwmt.git/ tags/armsoc-for-3.8
+devel/debug_ll_init     patch <1350927774-14020-1-git-send-email-swarren@wwwdotorg.org>
+nomadik/plat-removal	git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git tags/kill-plat-sparse-irq
+ux500/mtu-clk		git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git tags/mtu-clk-for-arm-soc
+tegra/single-zimage	git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.8-single-zimage
+zynq/multiplatform	git://git.monstr.eu/linux-2.6-microblaze.git zynq/multiplatform
+
+next/pm:
+omap/pm			git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.8/pm-signed
+omap/pm2		git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.8/pm-part2-v3-signed
+
+next/clock:
+omap/clock		git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.8/clock-signed
+				depends on omap/pm
+
+next/smp:
+socfpga/smp		patch from Dinh Nguyen <dinguyen@altera.com>
++ patch <1351183299-17346-1-git-send-email-dinguyen@altera.com>
++ patch <20121029002724.GA27891@elf.ucw.cz>
++ patch <201211062219.43459.arnd@arndb.de>
+
+next/drivers:
+vexpress/drivers	git://git.linaro.org/people/pawelmoll/linux vexpress/drivers
+ux500/pins		http://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git tags/ux500-pins-for-arm-soc
++ patch <1352976439-24133-1-git-send-email-linus.walleij@stericsson.com>
+omap/gpmc		git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.8/gpmc-signed
+				depends on omap/headers4
+omap/timer		git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.8/timer-signed
+				depends on omap/dt
+samsung/gpio		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/gpio-samsung
+
+next/boards2:
+renesas/boards2		depends on renesas/soc, renesas/soc2, renesas/boards and depends/asoc
+renesas/boards3		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git boards3
+
+next/soc2:
+vexpress/soc		git://git.linaro.org/people/pawelmoll/linux vexpress-soc
+				depends on depends/clk
+renesas/soc3		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git soc2
+				depends on renesas/boards2
++patch <1352333341-9249-1-git-send-email-robherring2@gmail.com>
+			depends on calxeda/ecx-2000 and devel/debug_ll_init
+renesas/soc4		git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git soc4
+samsung/devel		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/devel-samsung
+
+next/dt2:
+spear/dt2:		git://git.linaro.org/people/vireshk/linux.git spear-for-3.8
+				depends on depends/pinctrl2
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index a517153..5cad8a6 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -45,19 +45,10 @@ ifeq ($(CONFIG_ARCH_SHARK),y)
 OBJS		+= head-shark.o ofw-shark.o
 endif
 
-ifeq ($(CONFIG_ARCH_P720T),y)
-# Borrow this code from SA1100
-OBJS		+= head-sa1100.o
-endif
-
 ifeq ($(CONFIG_ARCH_SA1100),y)
 OBJS		+= head-sa1100.o
 endif
 
-ifeq ($(CONFIG_ARCH_VT8500),y)
-OBJS		+= head-vt8500.o
-endif
-
 ifeq ($(CONFIG_CPU_XSCALE),y)
 OBJS		+= head-xscale.o
 endif
diff --git a/arch/arm/boot/compressed/head-vt8500.S b/arch/arm/boot/compressed/head-vt8500.S
deleted file mode 100644
index 1dc1e21..0000000
--- a/arch/arm/boot/compressed/head-vt8500.S
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * linux/arch/arm/boot/compressed/head-vt8500.S
- *
- * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * VIA VT8500 specific tweaks. This is merged into head.S by the linker.
- *
- */
-
-#include <linux/linkage.h>
-#include <asm/mach-types.h>
-
-		.section        ".start", "ax"
-
-__VT8500_start:
-	@ Compare the SCC ID register against a list of known values
-	ldr	r1, .SCCID
-	ldr	r3, [r1]
-
-	@ VT8500 override
-	ldr	r4, .VT8500SCC
-	cmp	r3, r4
-	ldreq	r7, .ID_BV07
-	beq	.Lendvt8500
-
-	@ WM8505 override
-	ldr	r4, .WM8505SCC
-	cmp	r3, r4
-	ldreq	r7, .ID_8505
-	beq	.Lendvt8500
-
-	@ Otherwise, leave the bootloader's machine id untouched
-
-.SCCID:
-	.word	0xd8120000
-.VT8500SCC:
-	.word	0x34000102
-.WM8505SCC:
-	.word	0x34260103
-
-.ID_BV07:
-	.word	MACH_TYPE_BV07
-.ID_8505:
-	.word	MACH_TYPE_WM8505_7IN_NETBOOK
-
-.Lendvt8500:
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 90275f0..49ca86e 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -652,6 +652,15 @@ __setup_mmu:	sub	r3, r4, #16384		@ Page directory size
 		mov	pc, lr
 ENDPROC(__setup_mmu)
 
+@ Enable unaligned access on v6, to allow better code generation
+@ for the decompressor C code:
+__armv6_mmu_cache_on:
+		mrc	p15, 0, r0, c1, c0, 0	@ read SCTLR
+		bic	r0, r0, #2		@ A (no unaligned access fault)
+		orr	r0, r0, #1 << 22	@ U (v6 unaligned access model)
+		mcr	p15, 0, r0, c1, c0, 0	@ write SCTLR
+		b	__armv4_mmu_cache_on
+
 __arm926ejs_mmu_cache_on:
 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 		mov	r0, #4			@ put dcache in WT mode
@@ -694,6 +703,9 @@ __armv7_mmu_cache_on:
 		bic	r0, r0, #1 << 28	@ clear SCTLR.TRE
 		orr	r0, r0, #0x5000		@ I-cache enable, RR cache replacement
 		orr	r0, r0, #0x003c		@ write buffer
+		bic	r0, r0, #2		@ A (no unaligned access fault)
+		orr	r0, r0, #1 << 22	@ U (v6 unaligned access model)
+						@ (needed for ARM1176)
 #ifdef CONFIG_MMU
 #ifdef CONFIG_CPU_ENDIAN_BE8
 		orr	r0, r0, #1 << 25	@ big-endian page tables
@@ -914,7 +926,7 @@ proc_types:
 
 		.word	0x0007b000		@ ARMv6
 		.word	0x000ff000
-		W(b)	__armv4_mmu_cache_on
+		W(b)	__armv6_mmu_cache_on
 		W(b)	__armv4_mmu_cache_off
 		W(b)	__armv6_mmu_cache_flush
 
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index f37cf9f..81b26f5 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -1,30 +1,53 @@
 ifeq ($(CONFIG_OF),y)
 
-dtb-$(CONFIG_ARCH_AT91) += aks-cdu.dtb \
-	at91sam9263ek.dtb \
-	at91sam9g20ek_2mmc.dtb \
-	at91sam9g20ek.dtb \
-	at91sam9g25ek.dtb \
-	at91sam9m10g45ek.dtb \
-	at91sam9n12ek.dtb \
-	ethernut5.dtb \
-	evk-pro3.dtb \
-	kizbox.dtb \
-	tny_a9260.dtb \
-	tny_a9263.dtb \
-	tny_a9g20.dtb \
-	usb_a9260.dtb \
-	usb_a9263.dtb \
-	usb_a9g20.dtb
+# Keep at91 dtb files sorted alphabetically for each SoC
+# rm9200
+dtb-$(CONFIG_ARCH_AT91) += at91rm9200ek.dtb
+# sam9260
+dtb-$(CONFIG_ARCH_AT91) += animeo_ip.dtb
+dtb-$(CONFIG_ARCH_AT91) += aks-cdu.dtb
+dtb-$(CONFIG_ARCH_AT91) += ethernut5.dtb
+dtb-$(CONFIG_ARCH_AT91) += evk-pro3.dtb
+dtb-$(CONFIG_ARCH_AT91) += tny_a9260.dtb
+dtb-$(CONFIG_ARCH_AT91) += usb_a9260.dtb
+# sam9263
+dtb-$(CONFIG_ARCH_AT91) += at91sam9263ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += tny_a9263.dtb
+dtb-$(CONFIG_ARCH_AT91) += usb_a9263.dtb
+# sam9g20
+dtb-$(CONFIG_ARCH_AT91) += at91sam9g20ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += at91sam9g20ek_2mmc.dtb
+dtb-$(CONFIG_ARCH_AT91) += kizbox.dtb
+dtb-$(CONFIG_ARCH_AT91) += tny_a9g20.dtb
+dtb-$(CONFIG_ARCH_AT91) += usb_a9g20.dtb
+# sam9g45
+dtb-$(CONFIG_ARCH_AT91) += at91sam9m10g45ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += pm9g45.dtb
+# sam9n12
+dtb-$(CONFIG_ARCH_AT91) += at91sam9n12ek.dtb
+# sam9x5
+dtb-$(CONFIG_ARCH_AT91) += at91sam9g15ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += at91sam9g25ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += at91sam9g35ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += at91sam9x25ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += at91sam9x35ek.dtb
+
+dtb-$(CONFIG_ARCH_BCM) += bcm11351-brt.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-dove-db.dtb
 dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
 	exynos4210-smdkv310.dtb \
 	exynos4210-trats.dtb \
-	exynos5250-smdk5250.dtb
-dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb
+	exynos4412-smdk4412.dtb \
+	exynos5250-smdk5250.dtb \
+	exynos5250-snow.dtb \
+	exynos5440-ssdk5440.dtb
+dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \
+	ecx-2000.dtb
 dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \
 	integratorcp.dtb
 dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
@@ -36,11 +59,20 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-dns320.dtb \
 	kirkwood-ib62x0.dtb \
 	kirkwood-iconnect.dtb \
 	kirkwood-iomega_ix2_200.dtb \
+	kirkwood-is2.dtb \
 	kirkwood-km_kirkwood.dtb \
 	kirkwood-lschlv2.dtb \
 	kirkwood-lsxhl.dtb \
+	kirkwood-mplcec4.dtb \
+	kirkwood-ns2.dtb \
+	kirkwood-ns2lite.dtb \
+	kirkwood-ns2max.dtb \
+	kirkwood-ns2mini.dtb \
+	kirkwood-nsa310.dtb \
+	kirkwood-topkick.dtb \
 	kirkwood-ts219-6281.dtb \
-	kirkwood-ts219-6282.dtb
+	kirkwood-ts219-6282.dtb \
+	kirkwood-openblocks_a6.dtb
 dtb-$(CONFIG_ARCH_MSM) += msm8660-surf.dtb \
 	msm8960-cdp.dtb
 dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \
@@ -51,39 +83,53 @@ dtb-$(CONFIG_ARCH_MXC) += imx51-babbage.dtb \
 	imx53-qsb.dtb \
 	imx53-smd.dtb \
 	imx6q-arm2.dtb \
+	imx6q-sabreauto.dtb \
 	imx6q-sabrelite.dtb \
 	imx6q-sabresd.dtb
 dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \
 	imx23-olinuxino.dtb \
 	imx23-stmp378x_devb.dtb \
+	imx28-apf28.dtb \
+	imx28-apf28dev.dtb \
 	imx28-apx4devkit.dtb \
 	imx28-cfa10036.dtb \
 	imx28-cfa10049.dtb \
 	imx28-evk.dtb \
 	imx28-m28evk.dtb \
+	imx28-sps1.dtb \
 	imx28-tx28.dtb
 dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
+	omap3-beagle.dtb \
 	omap3-beagle-xm.dtb \
 	omap3-evm.dtb \
 	omap3-tobi.dtb \
 	omap4-panda.dtb \
-	omap4-pandaES.dtb \
-	omap4-var_som.dtb \
+	omap4-panda-es.dtb \
+	omap4-var-som.dtb \
 	omap4-sdp.dtb \
 	omap5-evm.dtb \
 	am335x-evm.dtb \
+	am335x-evmsk.dtb \
 	am335x-bone.dtb
+dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
-dtb-$(CONFIG_ARCH_U8500) += snowball.dtb
+dtb-$(CONFIG_ARCH_U8500) += snowball.dtb \
+	hrefprev60.dtb \
+	hrefv60plus.dtb \
+	ccu9540.dtb
 dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
 	r8a7740-armadillo800eva.dtb \
-	sh73a0-kzm9g.dtb
+	sh73a0-kzm9g.dtb \
+	sh7372-mackerel.dtb
 dtb-$(CONFIG_ARCH_SPEAR13XX) += spear1310-evb.dtb \
 	spear1340-evb.dtb
 dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \
 	spear310-evb.dtb \
-	spear320-evb.dtb
+	spear320-evb.dtb \
+	spear320-hmi.dtb
 dtb-$(CONFIG_ARCH_SPEAR6XX)+= spear600-evb.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun4i-cubieboard.dtb \
+	sun5i-olinuxino.dtb
 dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
 	tegra20-medcom-wide.dtb \
 	tegra20-paz00.dtb \
@@ -103,5 +149,6 @@ dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \
 dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \
 	wm8505-ref.dtb \
 	wm8650-mid.dtb
+dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb
 
 endif
diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
index c634f87..11b240c 100644
--- a/arch/arm/boot/dts/am335x-bone.dts
+++ b/arch/arm/boot/dts/am335x-bone.dts
@@ -13,11 +13,31 @@
 	model = "TI AM335x BeagleBone";
 	compatible = "ti,am335x-bone", "ti,am33xx";
 
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&dcdc2_reg>;
+		};
+	};
+
 	memory {
 		device_type = "memory";
 		reg = <0x80000000 0x10000000>; /* 256 MB */
 	};
 
+	am33xx_pinmux: pinmux@44e10800 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&user_leds_s0>;
+
+		user_leds_s0: user_leds_s0 {
+			pinctrl-single,pins = <
+				0x54 0x7	/* gpmc_a5.gpio1_21, OUTPUT | MODE7 */
+				0x58 0x17	/* gpmc_a6.gpio1_22, OUTPUT_PULLUP | MODE7 */
+				0x5c 0x7	/* gpmc_a7.gpio1_23, OUTPUT | MODE7 */
+				0x60 0x17	/* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
+			>;
+		};
+	};
+
 	ocp {
 		uart1: serial@44e09000 {
 			status = "okay";
@@ -33,6 +53,36 @@
 
 		};
 	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led@2 {
+			label = "beaglebone:green:heartbeat";
+			gpios = <&gpio2 21 0>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+
+		led@3 {
+			label = "beaglebone:green:mmc0";
+			gpios = <&gpio2 22 0>;
+			linux,default-trigger = "mmc0";
+			default-state = "off";
+		};
+
+		led@4 {
+			label = "beaglebone:green:usr2";
+			gpios = <&gpio2 23 0>;
+			default-state = "off";
+		};
+
+		led@5 {
+			label = "beaglebone:green:usr3";
+			gpios = <&gpio2 24 0>;
+			default-state = "off";
+		};
+	};
 };
 
 /include/ "tps65217.dtsi"
@@ -78,3 +128,11 @@
 		};
 	};
 };
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+};
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index 185d632..d649644 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -13,11 +13,39 @@
 	model = "TI AM335x EVM";
 	compatible = "ti,am335x-evm", "ti,am33xx";
 
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vdd1_reg>;
+		};
+	};
+
 	memory {
 		device_type = "memory";
 		reg = <0x80000000 0x10000000>; /* 256 MB */
 	};
 
+	am33xx_pinmux: pinmux@44e10800 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&matrix_keypad_s0 &volume_keys_s0>;
+
+		matrix_keypad_s0: matrix_keypad_s0 {
+			pinctrl-single,pins = <
+				0x54 0x7	/* gpmc_a5.gpio1_21, OUTPUT | MODE7 */
+				0x58 0x7	/* gpmc_a6.gpio1_22, OUTPUT | MODE7 */
+				0x64 0x27	/* gpmc_a9.gpio1_25, INPUT | MODE7 */
+				0x68 0x27	/* gpmc_a10.gpio1_26, INPUT | MODE7 */
+				0x6c 0x27	/* gpmc_a11.gpio1_27, INPUT | MODE7 */
+			>;
+		};
+
+		volume_keys_s0: volume_keys_s0 {
+			pinctrl-single,pins = <
+				0x150 0x27	/* spi0_sclk.gpio0_2, INPUT | MODE7 */
+				0x154 0x27	/* spi0_d0.gpio0_3, INPUT | MODE7 */
+			>;
+		};
+	};
+
 	ocp {
 		uart1: serial@44e09000 {
 			status = "okay";
@@ -31,6 +59,49 @@
 				reg = <0x2d>;
 			};
 		};
+
+		i2c2: i2c@4802a000 {
+			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>;
+			};
+		};
 	};
 
 	vbat: fixedregulator@0 {
@@ -40,6 +111,53 @@
 		regulator-max-microvolt = <5000000>;
 		regulator-boot-on;
 	};
+
+	lis3_reg: fixedregulator@1 {
+		compatible = "regulator-fixed";
+		regulator-name = "lis3_reg";
+		regulator-boot-on;
+	};
+
+	matrix_keypad: matrix_keypad@0 {
+		compatible = "gpio-matrix-keypad";
+		debounce-delay-ms = <5>;
+		col-scan-delay-us = <2>;
+
+		row-gpios = <&gpio2 25 0	/* Bank1, pin25 */
+			     &gpio2 26 0	/* Bank1, pin26 */
+			     &gpio2 27 0>;	/* Bank1, pin27 */
+
+		col-gpios = <&gpio2 21 0	/* Bank1, pin21 */
+			     &gpio2 22 0>;	/* Bank1, pin22 */
+
+		linux,keymap = <0x0000008b	/* MENU */
+				0x0100009e	/* BACK */
+				0x02000069	/* LEFT */
+				0x0001006a	/* RIGHT */
+				0x0101001c	/* ENTER */
+				0x0201006c>;	/* DOWN */
+	};
+
+	gpio_keys: volume_keys@0 {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		autorepeat;
+
+		switch@9 {
+			label = "volume-up";
+			linux,code = <115>;
+			gpios = <&gpio1 2 1>;
+			gpio-key,wakeup;
+		};
+
+		switch@10 {
+			label = "volume-down";
+			linux,code = <114>;
+			gpios = <&gpio1 3 1>;
+			gpio-key,wakeup;
+		};
+	};
 };
 
 /include/ "tps65910.dtsi"
@@ -118,3 +236,11 @@
 		};
 	};
 };
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+};
diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
new file mode 100644
index 0000000..f5a6162
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-evmsk.dts
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/*
+ * AM335x Starter Kit
+ * http://www.ti.com/tool/tmdssk3358
+ */
+
+/dts-v1/;
+
+/include/ "am33xx.dtsi"
+
+/ {
+	model = "TI AM335x EVM-SK";
+	compatible = "ti,am335x-evmsk", "ti,am33xx";
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vdd1_reg>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	am33xx_pinmux: pinmux@44e10800 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&user_leds_s0 &gpio_keys_s0>;
+
+		user_leds_s0: user_leds_s0 {
+			pinctrl-single,pins = <
+				0x10 0x7	/* gpmc_ad4.gpio1_4, OUTPUT | MODE7 */
+				0x14 0x7	/* gpmc_ad5.gpio1_5, OUTPUT | MODE7 */
+				0x18 0x7	/* gpmc_ad6.gpio1_6, OUTPUT | MODE7 */
+				0x1c 0x7	/* gpmc_ad7.gpio1_7, OUTPUT | MODE7 */
+			>;
+		};
+
+		gpio_keys_s0: gpio_keys_s0 {
+			pinctrl-single,pins = <
+				0x94 0x27	/* gpmc_oen_ren.gpio2_3, INPUT | MODE7 */
+				0x90 0x27	/* gpmc_advn_ale.gpio2_2, INPUT | MODE7 */
+				0x70 0x27	/* gpmc_wait0.gpio0_30, INPUT | MODE7 */
+				0x9c 0x27	/* gpmc_ben0_cle.gpio2_5, INPUT | MODE7 */
+			>;
+		};
+	};
+
+	ocp {
+		uart1: serial@44e09000 {
+			status = "okay";
+		};
+
+		i2c1: i2c@44e0b000 {
+			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>;
+			};
+		};
+	};
+
+	vbat: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+	};
+
+	lis3_reg: fixedregulator@1 {
+		compatible = "regulator-fixed";
+		regulator-name = "lis3_reg";
+		regulator-boot-on;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led@1 {
+			label = "evmsk:green:usr0";
+			gpios = <&gpio2 4 0>;
+			default-state = "off";
+		};
+
+		led@2 {
+			label = "evmsk:green:usr1";
+			gpios = <&gpio2 5 0>;
+			default-state = "off";
+		};
+
+		led@3 {
+			label = "evmsk:green:mmc0";
+			gpios = <&gpio2 6 0>;
+			linux,default-trigger = "mmc0";
+			default-state = "off";
+		};
+
+		led@4 {
+			label = "evmsk:green:heartbeat";
+			gpios = <&gpio2 7 0>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+	};
+
+	gpio_buttons: gpio_buttons@0 {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		switch@1 {
+			label = "button0";
+			linux,code = <0x100>;
+			gpios = <&gpio3 3 0>;
+		};
+
+		switch@2 {
+			label = "button1";
+			linux,code = <0x101>;
+			gpios = <&gpio3 2 0>;
+		};
+
+		switch@3 {
+			label = "button2";
+			linux,code = <0x102>;
+			gpios = <&gpio1 30 0>;
+			gpio-key,wakeup;
+		};
+
+		switch@4 {
+			label = "button3";
+			linux,code = <0x103>;
+			gpios = <&gpio3 5 0>;
+		};
+	};
+};
+
+/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/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index bb31bff..73ea69c 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -12,6 +12,7 @@
 
 / {
 	compatible = "ti,am33xx";
+	interrupt-parent = <&intc>;
 
 	aliases {
 		serial0 = &uart1;
@@ -25,6 +26,21 @@
 	cpus {
 		cpu@0 {
 			compatible = "arm,cortex-a8";
+
+			/*
+			 * To consider voltage drop between PMIC and SoC,
+			 * tolerance value is reduced to 2% from 4% and
+			 * voltage value is increased as a precaution.
+			 */
+			operating-points = <
+				/* kHz    uV */
+				720000  1285000
+				600000  1225000
+				500000  1125000
+				275000  1125000
+			>;
+			voltage-tolerance = <2>; /* 2 percentage */
+			clock-latency = <300000>; /* From omap-cpufreq driver */
 		};
 	};
 
@@ -40,6 +56,15 @@
 		};
 	};
 
+	am33xx_pinmux: pinmux@44e10800 {
+		compatible = "pinctrl-single";
+		reg = <0x44e10800 0x0238>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0x7f>;
+	};
+
 	/*
 	 * XXX: Use a flat representation of the AM33XX interconnect.
 	 * The real AM33XX interconnect network is quite complex.Since
@@ -70,7 +95,6 @@
 			interrupt-controller;
 			#interrupt-cells = <1>;
 			reg = <0x44e07000 0x1000>;
-			interrupt-parent = <&intc>;
 			interrupts = <96>;
 		};
 
@@ -82,7 +106,6 @@
 			interrupt-controller;
 			#interrupt-cells = <1>;
 			reg = <0x4804c000 0x1000>;
-			interrupt-parent = <&intc>;
 			interrupts = <98>;
 		};
 
@@ -94,7 +117,6 @@
 			interrupt-controller;
 			#interrupt-cells = <1>;
 			reg = <0x481ac000 0x1000>;
-			interrupt-parent = <&intc>;
 			interrupts = <32>;
 		};
 
@@ -106,7 +128,6 @@
 			interrupt-controller;
 			#interrupt-cells = <1>;
 			reg = <0x481ae000 0x1000>;
-			interrupt-parent = <&intc>;
 			interrupts = <62>;
 		};
 
@@ -115,7 +136,6 @@
 			ti,hwmods = "uart1";
 			clock-frequency = <48000000>;
 			reg = <0x44e09000 0x2000>;
-			interrupt-parent = <&intc>;
 			interrupts = <72>;
 			status = "disabled";
 		};
@@ -125,7 +145,6 @@
 			ti,hwmods = "uart2";
 			clock-frequency = <48000000>;
 			reg = <0x48022000 0x2000>;
-			interrupt-parent = <&intc>;
 			interrupts = <73>;
 			status = "disabled";
 		};
@@ -135,7 +154,6 @@
 			ti,hwmods = "uart3";
 			clock-frequency = <48000000>;
 			reg = <0x48024000 0x2000>;
-			interrupt-parent = <&intc>;
 			interrupts = <74>;
 			status = "disabled";
 		};
@@ -145,7 +163,6 @@
 			ti,hwmods = "uart4";
 			clock-frequency = <48000000>;
 			reg = <0x481a6000 0x2000>;
-			interrupt-parent = <&intc>;
 			interrupts = <44>;
 			status = "disabled";
 		};
@@ -155,7 +172,6 @@
 			ti,hwmods = "uart5";
 			clock-frequency = <48000000>;
 			reg = <0x481a8000 0x2000>;
-			interrupt-parent = <&intc>;
 			interrupts = <45>;
 			status = "disabled";
 		};
@@ -165,7 +181,6 @@
 			ti,hwmods = "uart6";
 			clock-frequency = <48000000>;
 			reg = <0x481aa000 0x2000>;
-			interrupt-parent = <&intc>;
 			interrupts = <46>;
 			status = "disabled";
 		};
@@ -176,7 +191,6 @@
 			#size-cells = <0>;
 			ti,hwmods = "i2c1";
 			reg = <0x44e0b000 0x1000>;
-			interrupt-parent = <&intc>;
 			interrupts = <70>;
 			status = "disabled";
 		};
@@ -187,7 +201,6 @@
 			#size-cells = <0>;
 			ti,hwmods = "i2c2";
 			reg = <0x4802a000 0x1000>;
-			interrupt-parent = <&intc>;
 			interrupts = <71>;
 			status = "disabled";
 		};
@@ -198,7 +211,6 @@
 			#size-cells = <0>;
 			ti,hwmods = "i2c3";
 			reg = <0x4819c000 0x1000>;
-			interrupt-parent = <&intc>;
 			interrupts = <30>;
 			status = "disabled";
 		};
@@ -207,8 +219,171 @@
 			compatible = "ti,omap3-wdt";
 			ti,hwmods = "wd_timer2";
 			reg = <0x44e35000 0x1000>;
-			interrupt-parent = <&intc>;
 			interrupts = <91>;
 		};
+
+		mac: ethernet@4a100000 {
+			compatible = "ti,cpsw";
+			ti,hwmods = "cpgmac0";
+			cpdma_channels = <8>;
+			ale_entries = <1024>;
+			bd_ram_size = <0x2000>;
+			no_bd_ram = <0>;
+			rx_descs = <64>;
+			mac_control = <0x20>;
+			slaves = <2>;
+			cpts_active_slave = <0>;
+			cpts_clock_mult = <0x80000000>;
+			cpts_clock_shift = <29>;
+			reg = <0x4a100000 0x800
+			       0x4a101200 0x100>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			/*
+			 * c0_rx_thresh_pend
+			 * c0_rx_pend
+			 * c0_tx_pend
+			 * c0_misc_pend
+			 */
+			interrupts = <40 41 42 43>;
+			ranges;
+
+			davinci_mdio: mdio@4a101000 {
+				compatible = "ti,davinci_mdio";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				ti,hwmods = "davinci_mdio";
+				bus_freq = <1000000>;
+				reg = <0x4a101000 0x100>;
+			};
+
+			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 ];
+			};
+
+		};
+
+		dcan0: d_can@481cc000 {
+			compatible = "bosch,d_can";
+			ti,hwmods = "d_can0";
+			reg = <0x481cc000 0x2000>;
+			interrupts = <52>;
+			status = "disabled";
+		};
+
+		dcan1: d_can@481d0000 {
+			compatible = "bosch,d_can";
+			ti,hwmods = "d_can1";
+			reg = <0x481d0000 0x2000>;
+			interrupts = <55>;
+			status = "disabled";
+		};
+
+		timer1: timer@44e31000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x44e31000 0x400>;
+			interrupts = <67>;
+			ti,hwmods = "timer1";
+			ti,timer-alwon;
+		};
+
+		timer2: timer@48040000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48040000 0x400>;
+			interrupts = <68>;
+			ti,hwmods = "timer2";
+		};
+
+		timer3: timer@48042000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48042000 0x400>;
+			interrupts = <69>;
+			ti,hwmods = "timer3";
+		};
+
+		timer4: timer@48044000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48044000 0x400>;
+			interrupts = <92>;
+			ti,hwmods = "timer4";
+			ti,timer-pwm;
+		};
+
+		timer5: timer@48046000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48046000 0x400>;
+			interrupts = <93>;
+			ti,hwmods = "timer5";
+			ti,timer-pwm;
+		};
+
+		timer6: timer@48048000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48048000 0x400>;
+			interrupts = <94>;
+			ti,hwmods = "timer6";
+			ti,timer-pwm;
+		};
+
+		timer7: timer@4804a000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4804a000 0x400>;
+			interrupts = <95>;
+			ti,hwmods = "timer7";
+			ti,timer-pwm;
+		};
+
+		rtc@44e3e000 {
+			compatible = "ti,da830-rtc";
+			reg = <0x44e3e000 0x1000>;
+			interrupts = <75
+				      76>;
+			ti,hwmods = "rtc";
+		};
+
+		spi0: spi@48030000 {
+			compatible = "ti,omap4-mcspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x48030000 0x400>;
+			interrupt = <65>;
+			ti,spi-num-cs = <2>;
+			ti,hwmods = "spi0";
+			status = "disabled";
+		};
+
+		spi1: spi@481a0000 {
+			compatible = "ti,omap4-mcspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x481a0000 0x400>;
+			interrupt = <125>;
+			ti,spi-num-cs = <2>;
+			ti,hwmods = "spi1";
+			status = "disabled";
+		};
+
+		usb@47400000 {
+			compatible = "ti,musb-am33xx";
+			reg = <0x47400000 0x1000	/* usbss */
+			       0x47401000 0x800		/* musb instance 0 */
+			       0x47401800 0x800>;	/* musb instance 1 */
+			interrupts = <17		/* usbss */
+				      18		/* musb instance 0 */
+				      19>;		/* musb instance 1 */
+			multipoint = <1>;
+			num-eps = <16>;
+			ram-bits = <12>;
+			port0-mode = <3>;
+			port1-mode = <3>;
+			power = <250>;
+			ti,hwmods = "usb_otg_hs";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/animeo_ip.dts b/arch/arm/boot/dts/animeo_ip.dts
new file mode 100644
index 0000000..74d92cd
--- /dev/null
+++ b/arch/arm/boot/dts/animeo_ip.dts
@@ -0,0 +1,178 @@
+/*
+ * animeo_ip.dts - Device Tree file for Somfy Animeo IP Boards
+ *
+ *  Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 only.
+ */
+
+/dts-v1/;
+/include/ "at91sam9260.dtsi"
+
+/ {
+	model = "Somfy Animeo IP";
+	compatible = "somfy,animeo-ip", "atmel,at91sam9260", "atmel,at91sam9";
+
+	aliases {
+		serial0 = &usart1;
+		serial1 = &usart2;
+		serial2 = &usart0;
+		serial3 = &dbgu;
+		serial4 = &usart3;
+		serial5 = &uart0;
+		serial6 = &uart1;
+	};
+
+	chosen {
+		linux,stdout-path = &usart2;
+	};
+
+	memory {
+		reg = <0x20000000 0x4000000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		main_clock: clock@0 {
+			compatible = "atmel,osc", "fixed-clock";
+			clock-frequency = <18432000>;
+		};
+	};
+
+	ahb {
+		apb {
+			usart0: serial@fffb0000 {
+				pinctrl-0 = <&pinctrl_usart0 &pinctrl_usart0_rts>;
+				linux,rs485-enabled-at-boot-time;
+				status = "okay";
+			};
+
+			usart1: serial@fffb4000 {
+				pinctrl-0 = <&pinctrl_usart1 &pinctrl_usart1_rts>;
+				linux,rs485-enabled-at-boot-time;
+				status = "okay";
+			};
+
+			usart2: serial@fffb8000 {
+				pinctrl-0 = <&pinctrl_usart2>;
+				status = "okay";
+			};
+
+			macb0: ethernet@fffc4000 {
+				pinctrl-0 = <&pinctrl_macb_rmii &pinctrl_macb_rmii_mii>;
+				phy-mode = "mii";
+				status = "okay";
+			};
+
+			mmc0: mmc@fffa8000 {
+				pinctrl-0 = <&pinctrl_mmc0_clk
+					     &pinctrl_mmc0_slot1_cmd_dat0
+					     &pinctrl_mmc0_slot1_dat1_3>;
+				status = "okay";
+
+				slot@1 {
+					reg = <1>;
+					bus-width = <4>;
+				};
+			};
+		};
+
+		nand0: nand@40000000 {
+			nand-bus-width = <8>;
+			nand-ecc-mode = "soft";
+			nand-on-flash-bbt;
+			status = "okay";
+
+			at91bootstrap@0 {
+				label = "at91bootstrap";
+				reg = <0x0 0x8000>;
+			};
+
+			barebox@8000 {
+				label = "barebox";
+				reg = <0x8000 0x40000>;
+			};
+
+			bareboxenv@48000 {
+				label = "bareboxenv";
+				reg = <0x48000 0x8000>;
+			};
+
+			user_block@0x50000 {
+				label = "user_block";
+				reg = <0x50000 0xb0000>;
+			};
+
+			kernel@100000 {
+				label = "kernel";
+				reg = <0x100000 0x1b0000>;
+			};
+
+			root@2b0000 {
+				label = "root";
+				reg = <0x2b0000 0x1D50000>;
+			};
+		};
+
+		usb0: ohci@00500000 {
+			num-ports = <2>;
+			atmel,vbus-gpio = <&pioB 15 1>;
+			status = "okay";
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		power_green {
+			label = "power_green";
+			gpios = <&pioC 17 0>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		power_red {
+			label = "power_red";
+			gpios = <&pioA 2 0>;
+		};
+
+		tx_green {
+			label = "tx_green";
+			gpios = <&pioC 19 0>;
+		};
+
+		tx_red {
+			label = "tx_red";
+			gpios = <&pioC 18 0>;
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		keyswitch_in {
+			label = "keyswitch_in";
+			gpios = <&pioB 1 0>;
+			linux,code = <28>;
+			gpio-key,wakeup;
+		};
+
+		error_in {
+			label = "error_in";
+			gpios = <&pioB 2 0>;
+			linux,code = <29>;
+			gpio-key,wakeup;
+		};
+
+		btn {
+			label = "btn";
+			gpios = <&pioC 23 0>;
+			linux,code = <31>;
+			gpio-key,wakeup;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/at91rm9200.dtsi b/arch/arm/boot/dts/at91rm9200.dtsi
new file mode 100644
index 0000000..e154f24
--- /dev/null
+++ b/arch/arm/boot/dts/at91rm9200.dtsi
@@ -0,0 +1,349 @@
+/*
+ * at91rm9200.dtsi - Device Tree Include file for AT91RM9200 family SoC
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>,
+ *                2012 Joachim Eastwood <manabian@gmail.com>
+ *
+ * Based on at91sam9260.dtsi
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Atmel AT91RM9200 family SoC";
+	compatible = "atmel,at91rm9200";
+	interrupt-parent = <&aic>;
+
+	aliases {
+		serial0 = &dbgu;
+		serial1 = &usart0;
+		serial2 = &usart1;
+		serial3 = &usart2;
+		serial4 = &usart3;
+		gpio0 = &pioA;
+		gpio1 = &pioB;
+		gpio2 = &pioC;
+		gpio3 = &pioD;
+		tcb0 = &tcb0;
+		tcb1 = &tcb1;
+	};
+	cpus {
+		cpu@0 {
+			compatible = "arm,arm920t";
+		};
+	};
+
+	memory {
+		reg = <0x20000000 0x04000000>;
+	};
+
+	ahb {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			aic: interrupt-controller@fffff000 {
+				#interrupt-cells = <3>;
+				compatible = "atmel,at91rm9200-aic";
+				interrupt-controller;
+				reg = <0xfffff000 0x200>;
+				atmel,external-irqs = <25 26 27 28 29 30 31>;
+			};
+
+			ramc0: ramc@ffffff00 {
+				compatible = "atmel,at91rm9200-sdramc";
+				reg = <0xffffff00 0x100>;
+			};
+
+			pmc: pmc@fffffc00 {
+				compatible = "atmel,at91rm9200-pmc";
+				reg = <0xfffffc00 0x100>;
+			};
+
+			st: timer@fffffd00 {
+				compatible = "atmel,at91rm9200-st";
+				reg = <0xfffffd00 0x100>;
+				interrupts = <1 4 7>;
+			};
+
+			tcb0: timer@fffa0000 {
+				compatible = "atmel,at91rm9200-tcb";
+				reg = <0xfffa0000 0x100>;
+				interrupts = <17 4 0 18 4 0 19 4 0>;
+			};
+
+			tcb1: timer@fffa4000 {
+				compatible = "atmel,at91rm9200-tcb";
+				reg = <0xfffa4000 0x100>;
+				interrupts = <20 4 0 21 4 0 22 4 0>;
+			};
+
+			pinctrl@fffff400 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
+				ranges = <0xfffff400 0xfffff400 0x800>;
+
+				atmel,mux-mask = <
+					/*    A         B     */
+					 0xffffffff 0xffffffff  /* pioA */
+					 0xffffffff 0x083fffff  /* pioB */
+					 0xffff3fff 0x00000000  /* pioC */
+					 0x03ff87ff 0x0fffff80  /* pioD */
+					>;
+
+				/* shared pinctrl settings */
+				dbgu {
+					pinctrl_dbgu: dbgu-0 {
+						atmel,pins =
+							<0 30 0x1 0x0	/* PA30 periph A */
+							 0 31 0x1 0x1>;	/* PA31 periph with pullup */
+					};
+				};
+
+				uart0 {
+					pinctrl_uart0: uart0-0 {
+						atmel,pins =
+							<0 17 0x1 0x0	/* PA17 periph A */
+							 0 18 0x1 0x0>;	/* PA18 periph A */
+					};
+
+					pinctrl_uart0_rts: uart0_rts-0 {
+						atmel,pins =
+							<0 20 0x1 0x0>;	/* PA20 periph A */
+					};
+
+					pinctrl_uart0_cts: uart0_cts-0 {
+						atmel,pins =
+							<0 21 0x1 0x0>;	/* PA21 periph A */
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1: uart1-0 {
+						atmel,pins =
+							<1 20 0x1 0x1	/* PB20 periph A with pullup */
+							 1 21 0x1 0x0>;	/* PB21 periph A */
+					};
+
+					pinctrl_uart1_rts: uart1_rts-0 {
+						atmel,pins =
+							<1 24 0x1 0x0>;	/* PB24 periph A */
+					};
+
+					pinctrl_uart1_cts: uart1_cts-0 {
+						atmel,pins =
+							<1 26 0x1 0x0>;	/* PB26 periph A */
+					};
+
+					pinctrl_uart1_dtr_dsr: uart1_dtr_dsr-0 {
+						atmel,pins =
+							<1 19 0x1 0x0	/* PB19 periph A */
+							 1 25 0x1 0x0>;	/* PB25 periph A */
+					};
+
+					pinctrl_uart1_dcd: uart1_dcd-0 {
+						atmel,pins =
+							<1 23 0x1 0x0>;	/* PB23 periph A */
+					};
+
+					pinctrl_uart1_ri: uart1_ri-0 {
+						atmel,pins =
+							<1 18 0x1 0x0>;	/* PB18 periph A */
+					};
+				};
+
+				uart2 {
+					pinctrl_uart2: uart2-0 {
+						atmel,pins =
+							<0 22 0x1 0x0	/* PA22 periph A */
+							 0 23 0x1 0x1>;	/* PA23 periph A with pullup */
+					};
+
+					pinctrl_uart2_rts: uart2_rts-0 {
+						atmel,pins =
+							<0 30 0x2 0x0>;	/* PA30 periph B */
+					};
+
+					pinctrl_uart2_cts: uart2_cts-0 {
+						atmel,pins =
+							<0 31 0x2 0x0>;	/* PA31 periph B */
+					};
+				};
+
+				uart3 {
+					pinctrl_uart3: uart3-0 {
+						atmel,pins =
+							<0 5 0x2 0x1	/* PA5 periph B with pullup */
+							 0 6 0x2 0x0>;	/* PA6 periph B */
+					};
+
+					pinctrl_uart3_rts: uart3_rts-0 {
+						atmel,pins =
+							<1 0 0x2 0x0>;	/* PB0 periph B */
+					};
+
+					pinctrl_uart3_cts: uart3_cts-0 {
+						atmel,pins =
+							<1 1 0x2 0x0>;	/* PB1 periph B */
+					};
+				};
+
+				nand {
+					pinctrl_nand: nand-0 {
+						atmel,pins =
+							<2 2 0x0 0x1	/* PC2 gpio RDY pin pull_up */
+							 1 1 0x0 0x1>;	/* PB1 gpio CD pin pull_up */
+					};
+				};
+
+				pioA: gpio@fffff400 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffff400 0x200>;
+					interrupts = <2 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioB: gpio@fffff600 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffff600 0x200>;
+					interrupts = <3 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioC: gpio@fffff800 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffff800 0x200>;
+					interrupts = <4 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioD: gpio@fffffa00 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffffa00 0x200>;
+					interrupts = <5 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+			};
+
+			dbgu: serial@fffff200 {
+				compatible = "atmel,at91rm9200-usart";
+				reg = <0xfffff200 0x200>;
+				interrupts = <1 4 7>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_dbgu>;
+				status = "disabled";
+			};
+
+			usart0: serial@fffc0000 {
+				compatible = "atmel,at91rm9200-usart";
+				reg = <0xfffc0000 0x200>;
+				interrupts = <6 4 5>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart0>;
+				status = "disabled";
+			};
+
+			usart1: serial@fffc4000 {
+				compatible = "atmel,at91rm9200-usart";
+				reg = <0xfffc4000 0x200>;
+				interrupts = <7 4 5>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart1>;
+				status = "disabled";
+			};
+
+			usart2: serial@fffc8000 {
+				compatible = "atmel,at91rm9200-usart";
+				reg = <0xfffc8000 0x200>;
+				interrupts = <8 4 5>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart2>;
+				status = "disabled";
+			};
+
+			usart3: serial@fffcc000 {
+				compatible = "atmel,at91rm9200-usart";
+				reg = <0xfffcc000 0x200>;
+				interrupts = <23 4 5>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart3>;
+				status = "disabled";
+			};
+
+			usb1: gadget@fffb0000 {
+				compatible = "atmel,at91rm9200-udc";
+				reg = <0xfffb0000 0x4000>;
+				interrupts = <11 4 2>;
+				status = "disabled";
+			};
+		};
+
+		nand0: nand@40000000 {
+			compatible = "atmel,at91rm9200-nand";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x40000000 0x10000000>;
+			atmel,nand-addr-offset = <21>;
+			atmel,nand-cmd-offset = <22>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_nand>;
+			nand-ecc-mode = "soft";
+			gpios = <&pioC 2 0
+				 0
+				 &pioB 1 0
+				>;
+			status = "disabled";
+		};
+
+		usb0: ohci@00300000 {
+			compatible = "atmel,at91rm9200-ohci", "usb-ohci";
+			reg = <0x00300000 0x100000>;
+			interrupts = <23 4 2>;
+			status = "disabled";
+		};
+	};
+
+	i2c@0 {
+		compatible = "i2c-gpio";
+		gpios = <&pioA 23 0 /* sda */
+			 &pioA 24 0 /* scl */
+			>;
+		i2c-gpio,sda-open-drain;
+		i2c-gpio,scl-open-drain;
+		i2c-gpio,delay-us = <2>;	/* ~100 kHz */
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+};
diff --git a/arch/arm/boot/dts/at91rm9200ek.dts b/arch/arm/boot/dts/at91rm9200ek.dts
new file mode 100644
index 0000000..8aa4893
--- /dev/null
+++ b/arch/arm/boot/dts/at91rm9200ek.dts
@@ -0,0 +1,79 @@
+/*
+ * at91rm9200ek.dts - Device Tree file for Atmel AT91RM9200 evaluation kit
+ *
+ *  Copyright (C) 2012 Joachim Eastwood <manabian@gmail.com>
+ *
+ * Licensed under GPLv2 only
+ */
+/dts-v1/;
+/include/ "at91rm9200.dtsi"
+
+/ {
+	model = "Atmel AT91RM9200 evaluation kit";
+	compatible = "atmel,at91rm9200ek", "atmel,at91rm9200";
+
+	memory {
+		reg = <0x20000000 0x4000000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		main_clock: clock@0 {
+			compatible = "atmel,osc", "fixed-clock";
+			clock-frequency = <18432000>;
+		};
+	};
+
+	ahb {
+		apb {
+			dbgu: serial@fffff200 {
+				status = "okay";
+			};
+
+			usart1: serial@fffc4000 {
+				pinctrl-0 =
+						<&pinctrl_uart1
+						 &pinctrl_uart1_rts
+						 &pinctrl_uart1_cts
+						 &pinctrl_uart1_dtr_dsr
+						 &pinctrl_uart1_dcd
+						 &pinctrl_uart1_ri>;
+				status = "okay";
+			};
+
+			usb1: gadget@fffb0000 {
+				atmel,vbus-gpio = <&pioD 4 0>;
+				status = "okay";
+			};
+		};
+
+		usb0: ohci@00300000 {
+			num-ports = <2>;
+			status = "okay";
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		ds2 {
+			label = "green";
+			gpios = <&pioB 0 0x1>;
+			linux,default-trigger = "mmc0";
+		};
+
+		ds4 {
+			label = "yellow";
+			gpios = <&pioB 1 0x1>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		ds6 {
+			label = "red";
+			gpios = <&pioB 2 0x1>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
index d410581..ed0209b 100644
--- a/arch/arm/boot/dts/at91sam9260.dtsi
+++ b/arch/arm/boot/dts/at91sam9260.dtsi
@@ -21,14 +21,15 @@
 		serial2 = &usart1;
 		serial3 = &usart2;
 		serial4 = &usart3;
-		serial5 = &usart4;
-		serial6 = &usart5;
+		serial5 = &uart0;
+		serial6 = &uart1;
 		gpio0 = &pioA;
 		gpio1 = &pioB;
 		gpio2 = &pioC;
 		tcb0 = &tcb0;
 		tcb1 = &tcb1;
 		i2c0 = &i2c0;
+		ssc0 = &ssc0;
 	};
 	cpus {
 		cpu@0 {
@@ -98,40 +99,250 @@
 				interrupts = <26 4 0 27 4 0 28 4 0>;
 			};
 
-			pioA: gpio@fffff400 {
-				compatible = "atmel,at91rm9200-gpio";
-				reg = <0xfffff400 0x100>;
-				interrupts = <2 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+			pinctrl@fffff400 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
+				ranges = <0xfffff400 0xfffff400 0x600>;
+
+				atmel,mux-mask = <
+				      /*    A         B     */
+				       0xffffffff 0xffc00c3b  /* pioA */
+				       0xffffffff 0x7fff3ccf  /* pioB */
+				       0xffffffff 0x007fffff  /* pioC */
+				      >;
+
+				/* shared pinctrl settings */
+				dbgu {
+					pinctrl_dbgu: dbgu-0 {
+						atmel,pins =
+							<1 14 0x1 0x0	/* PB14 periph A */
+							 1 15 0x1 0x1>;	/* PB15 periph with pullup */
+					};
+				};
 
-			pioB: gpio@fffff600 {
-				compatible = "atmel,at91rm9200-gpio";
-				reg = <0xfffff600 0x100>;
-				interrupts = <3 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+				usart0 {
+					pinctrl_usart0: usart0-0 {
+						atmel,pins =
+							<1 4 0x1 0x0	/* PB4 periph A */
+							 1 5 0x1 0x0>;	/* PB5 periph A */
+					};
+
+					pinctrl_usart0_rts: usart0_rts-0 {
+						atmel,pins =
+							<1 26 0x1 0x0>;	/* PB26 periph A */
+					};
+
+					pinctrl_usart0_cts: usart0_cts-0 {
+						atmel,pins =
+							<1 27 0x1 0x0>;	/* PB27 periph A */
+					};
+
+					pinctrl_usart0_dtr_dsr: usart0_dtr_dsr-0 {
+						atmel,pins =
+							<1 24 0x1 0x0	/* PB24 periph A */
+							 1 22 0x1 0x0>;	/* PB22 periph A */
+					};
+
+					pinctrl_usart0_dcd: usart0_dcd-0 {
+						atmel,pins =
+							<1 23 0x1 0x0>;	/* PB23 periph A */
+					};
+
+					pinctrl_usart0_ri: usart0_ri-0 {
+						atmel,pins =
+							<1 25 0x1 0x0>;	/* PB25 periph A */
+					};
+				};
 
-			pioC: gpio@fffff800 {
-				compatible = "atmel,at91rm9200-gpio";
-				reg = <0xfffff800 0x100>;
-				interrupts = <4 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
+				usart1 {
+					pinctrl_usart1: usart1-0 {
+						atmel,pins =
+							<2 6 0x1 0x1	/* PB6 periph A with pullup */
+							 2 7 0x1 0x0>;	/* PB7 periph A */
+					};
+
+					pinctrl_usart1_rts: usart1_rts-0 {
+						atmel,pins =
+							<1 28 0x1 0x0>;	/* PB28 periph A */
+					};
+
+					pinctrl_usart1_cts: usart1_cts-0 {
+						atmel,pins =
+							<1 29 0x1 0x0>;	/* PB29 periph A */
+					};
+				};
+
+				usart2 {
+					pinctrl_usart2: usart2-0 {
+						atmel,pins =
+							<1 8 0x1 0x1	/* PB8 periph A with pullup */
+							 1 9 0x1 0x0>;	/* PB9 periph A */
+					};
+
+					pinctrl_usart2_rts: usart2_rts-0 {
+						atmel,pins =
+							<0 4 0x1 0x0>;	/* PA4 periph A */
+					};
+
+					pinctrl_usart2_cts: usart2_cts-0 {
+						atmel,pins =
+							<0 5 0x1 0x0>;	/* PA5 periph A */
+					};
+				};
+
+				usart3 {
+					pinctrl_usart3: usart3-0 {
+						atmel,pins =
+							<2 10 0x1 0x1	/* PB10 periph A with pullup */
+							 2 11 0x1 0x0>;	/* PB11 periph A */
+					};
+
+					pinctrl_usart3_rts: usart3_rts-0 {
+						atmel,pins =
+							<3 8 0x2 0x0>;	/* PB8 periph B */
+					};
+
+					pinctrl_usart3_cts: usart3_cts-0 {
+						atmel,pins =
+							<3 10 0x2 0x0>;	/* PB10 periph B */
+					};
+				};
+
+				uart0 {
+					pinctrl_uart0: uart0-0 {
+						atmel,pins =
+							<0 31 0x2 0x1	/* PA31 periph B with pullup */
+							 0 30 0x2 0x0>;	/* PA30 periph B */
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1: uart1-0 {
+						atmel,pins =
+							<2 12 0x1 0x1	/* PB12 periph A with pullup */
+							 2 13 0x1 0x0>;	/* PB13 periph A */
+					};
+				};
+
+				nand {
+					pinctrl_nand: nand-0 {
+						atmel,pins =
+							<2 13 0x0 0x1	/* PC13 gpio RDY pin pull_up */
+							 2 14 0x0 0x1>;	/* PC14 gpio enable pin pull_up */
+					};
+				};
+
+				macb {
+					pinctrl_macb_rmii: macb_rmii-0 {
+						atmel,pins =
+							<0 12 0x1 0x0	/* PA12 periph A */
+							 0 13 0x1 0x0	/* PA13 periph A */
+							 0 14 0x1 0x0	/* PA14 periph A */
+							 0 15 0x1 0x0	/* PA15 periph A */
+							 0 16 0x1 0x0	/* PA16 periph A */
+							 0 17 0x1 0x0	/* PA17 periph A */
+							 0 18 0x1 0x0	/* PA18 periph A */
+							 0 19 0x1 0x0	/* PA19 periph A */
+							 0 20 0x1 0x0	/* PA20 periph A */
+							 0 21 0x1 0x0>;	/* PA21 periph A */
+					};
+
+					pinctrl_macb_rmii_mii: macb_rmii_mii-0 {
+						atmel,pins =
+							<0 22 0x2 0x0	/* PA22 periph B */
+							 0 23 0x2 0x0	/* PA23 periph B */
+							 0 24 0x2 0x0	/* PA24 periph B */
+							 0 25 0x2 0x0	/* PA25 periph B */
+							 0 26 0x2 0x0	/* PA26 periph B */
+							 0 27 0x2 0x0	/* PA27 periph B */
+							 0 28 0x2 0x0	/* PA28 periph B */
+							 0 29 0x2 0x0>;	/* PA29 periph B */
+					};
+
+					pinctrl_macb_rmii_mii_alt: macb_rmii_mii-1 {
+						atmel,pins =
+							<0 10 0x2 0x0	/* PA10 periph B */
+							 0 11 0x2 0x0	/* PA11 periph B */
+							 0 24 0x2 0x0	/* PA24 periph B */
+							 0 25 0x2 0x0	/* PA25 periph B */
+							 0 26 0x2 0x0	/* PA26 periph B */
+							 0 27 0x2 0x0	/* PA27 periph B */
+							 0 28 0x2 0x0	/* PA28 periph B */
+							 0 29 0x2 0x0>;	/* PA29 periph B */
+					};
+				};
+
+				mmc0 {
+					pinctrl_mmc0_clk: mmc0_clk-0 {
+						atmel,pins =
+							<0 8 0x1 0x0>;	/* PA8 periph A */
+					};
+
+					pinctrl_mmc0_slot0_cmd_dat0: mmc0_slot0_cmd_dat0-0 {
+						atmel,pins =
+							<0 7 0x1 0x1	/* PA7 periph A with pullup */
+							 0 6 0x1 0x1>;	/* PA6 periph A with pullup */
+					};
+
+					pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 {
+						atmel,pins =
+							<0 9 0x1 0x1	/* PA9 periph A with pullup */
+							 0 10 0x1 0x1	/* PA10 periph A with pullup */
+							 0 11 0x1 0x1>;	/* PA11 periph A with pullup */
+					};
+
+					pinctrl_mmc0_slot1_cmd_dat0: mmc0_slot1_cmd_dat0-0 {
+						atmel,pins =
+							<0 1 0x2 0x1	/* PA1 periph B with pullup */
+							 0 0 0x2 0x1>;	/* PA0 periph B with pullup */
+					};
+
+					pinctrl_mmc0_slot1_dat1_3: mmc0_slot1_dat1_3-0 {
+						atmel,pins =
+							<0 5 0x2 0x1	/* PA5 periph B with pullup */
+							 0 4 0x2 0x1	/* PA4 periph B with pullup */
+							 0 3 0x2 0x1>;	/* PA3 periph B with pullup */
+					};
+				};
+
+				pioA: gpio@fffff400 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffff400 0x200>;
+					interrupts = <2 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioB: gpio@fffff600 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffff600 0x200>;
+					interrupts = <3 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioC: gpio@fffff800 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffff800 0x200>;
+					interrupts = <4 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
 			};
 
 			dbgu: serial@fffff200 {
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xfffff200 0x200>;
 				interrupts = <1 4 7>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_dbgu>;
 				status = "disabled";
 			};
 
@@ -141,6 +352,8 @@
 				interrupts = <6 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart0>;
 				status = "disabled";
 			};
 
@@ -150,6 +363,8 @@
 				interrupts = <7 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart1>;
 				status = "disabled";
 			};
 
@@ -159,6 +374,8 @@
 				interrupts = <8 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart2>;
 				status = "disabled";
 			};
 
@@ -168,24 +385,30 @@
 				interrupts = <23 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart3>;
 				status = "disabled";
 			};
 
-			usart4: serial@fffd4000 {
+			uart0: serial@fffd4000 {
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xfffd4000 0x200>;
 				interrupts = <24 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart0>;
 				status = "disabled";
 			};
 
-			usart5: serial@fffd8000 {
+			uart1: serial@fffd8000 {
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xfffd8000 0x200>;
 				interrupts = <25 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart1>;
 				status = "disabled";
 			};
 
@@ -193,6 +416,8 @@
 				compatible = "cdns,at32ap7000-macb", "cdns,macb";
 				reg = <0xfffc4000 0x100>;
 				interrupts = <21 4 3>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_macb_rmii>;
 				status = "disabled";
 			};
 
@@ -212,6 +437,22 @@
 				status = "disabled";
 			};
 
+			mmc0: mmc@fffa8000 {
+				compatible = "atmel,hsmci";
+				reg = <0xfffa8000 0x600>;
+				interrupts = <9 4 0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			ssc0: ssc@fffbc000 {
+				compatible = "atmel,at91rm9200-ssc";
+				reg = <0xfffbc000 0x4000>;
+				interrupts = <14 4 5>;
+				status = "disable";
+			};
+
 			adc0: adc@fffe0000 {
 				compatible = "atmel,at91sam9260-adc";
 				reg = <0xfffe0000 0x100>;
@@ -246,6 +487,12 @@
 					trigger-external;
 				};
 			};
+
+			watchdog@fffffd40 {
+				compatible = "atmel,at91sam9260-wdt";
+				reg = <0xfffffd40 0x10>;
+				status = "disabled";
+			};
 		};
 
 		nand0: nand@40000000 {
@@ -257,6 +504,8 @@
 			      >;
 			atmel,nand-addr-offset = <21>;
 			atmel,nand-cmd-offset = <22>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_nand>;
 			gpios = <&pioC 13 0
 				 &pioC 14 0
 				 0
diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
index 3e6e5c1..8e6251f 100644
--- a/arch/arm/boot/dts/at91sam9263.dtsi
+++ b/arch/arm/boot/dts/at91sam9263.dtsi
@@ -25,6 +25,8 @@
 		gpio4 = &pioE;
 		tcb0 = &tcb0;
 		i2c0 = &i2c0;
+		ssc0 = &ssc0;
+		ssc1 = &ssc1;
 	};
 	cpus {
 		cpu@0 {
@@ -89,60 +91,243 @@
 				reg = <0xfffffd10 0x10>;
 			};
 
-			pioA: gpio@fffff200 {
-				compatible = "atmel,at91rm9200-gpio";
-				reg = <0xfffff200 0x100>;
-				interrupts = <2 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+			pinctrl@fffff200 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
+				ranges = <0xfffff200 0xfffff200 0xa00>;
 
-			pioB: gpio@fffff400 {
-				compatible = "atmel,at91rm9200-gpio";
-				reg = <0xfffff400 0x100>;
-				interrupts = <3 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+				atmel,mux-mask = <
+				      /*    A         B     */
+				       0xfffffffb 0xffffe07f  /* pioA */
+				       0x0007ffff 0x39072fff  /* pioB */
+				       0xffffffff 0x3ffffff8  /* pioC */
+				       0xfffffbff 0xffffffff  /* pioD */
+				       0xffe00fff 0xfbfcff00  /* pioE */
+				      >;
 
-			pioC: gpio@fffff600 {
-				compatible = "atmel,at91rm9200-gpio";
-				reg = <0xfffff600 0x100>;
-				interrupts = <4 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+				/* shared pinctrl settings */
+				dbgu {
+					pinctrl_dbgu: dbgu-0 {
+						atmel,pins =
+							<2 30 0x1 0x0	/* PC30 periph A */
+							 2 31 0x1 0x1>;	/* PC31 periph with pullup */
+					};
+				};
 
-			pioD: gpio@fffff800 {
-				compatible = "atmel,at91rm9200-gpio";
-				reg = <0xfffff800 0x100>;
-				interrupts = <4 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+				usart0 {
+					pinctrl_usart0: usart0-0 {
+						atmel,pins =
+							<0 26 0x1 0x1	/* PA26 periph A with pullup */
+							 0 27 0x1 0x0>;	/* PA27 periph A */
+					};
 
-			pioE: gpio@fffffa00 {
-				compatible = "atmel,at91rm9200-gpio";
-				reg = <0xfffffa00 0x100>;
-				interrupts = <4 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
+					pinctrl_usart0_rts: usart0_rts-0 {
+						atmel,pins =
+							<0 28 0x1 0x0>;	/* PA28 periph A */
+					};
+
+					pinctrl_usart0_cts: usart0_cts-0 {
+						atmel,pins =
+							<0 29 0x1 0x0>;	/* PA29 periph A */
+					};
+				};
+
+				usart1 {
+					pinctrl_usart1: usart1-0 {
+						atmel,pins =
+							<3 0 0x1 0x1	/* PD0 periph A with pullup */
+							 3 1 0x1 0x0>;	/* PD1 periph A */
+					};
+
+					pinctrl_usart1_rts: usart1_rts-0 {
+						atmel,pins =
+							<3 7 0x2 0x0>;	/* PD7 periph B */
+					};
+
+					pinctrl_usart1_cts: usart1_cts-0 {
+						atmel,pins =
+							<3 8 0x2 0x0>;	/* PD8 periph B */
+					};
+				};
+
+				usart2 {
+					pinctrl_usart2: usart2-0 {
+						atmel,pins =
+							<3 2 0x1 0x1	/* PD2 periph A with pullup */
+							 3 3 0x1 0x0>;	/* PD3 periph A */
+					};
+
+					pinctrl_usart2_rts: usart2_rts-0 {
+						atmel,pins =
+							<3 5 0x2 0x0>;	/* PD5 periph B */
+					};
+
+					pinctrl_usart2_cts: usart2_cts-0 {
+						atmel,pins =
+							<4 6 0x2 0x0>;	/* PD6 periph B */
+					};
+				};
+
+				nand {
+					pinctrl_nand: nand-0 {
+						atmel,pins =
+							<0 22 0x0 0x1	/* PA22 gpio RDY pin pull_up*/
+							 3 15 0x0 0x1>;	/* PD15 gpio enable pin pull_up */
+					};
+				};
+
+				macb {
+					pinctrl_macb_rmii: macb_rmii-0 {
+						atmel,pins =
+							<2 25 0x2 0x0	/* PC25 periph B */
+							 4 21 0x1 0x0	/* PE21 periph A */
+							 4 23 0x1 0x0	/* PE23 periph A */
+							 4 24 0x1 0x0	/* PE24 periph A */
+							 4 25 0x1 0x0	/* PE25 periph A */
+							 4 26 0x1 0x0	/* PE26 periph A */
+							 4 27 0x1 0x0	/* PE27 periph A */
+							 4 28 0x1 0x0	/* PE28 periph A */
+							 4 29 0x1 0x0	/* PE29 periph A */
+							 4 30 0x1 0x0>;	/* PE30 periph A */
+					};
+
+					pinctrl_macb_rmii_mii: macb_rmii_mii-0 {
+						atmel,pins =
+							<2 20 0x2 0x0	/* PC20 periph B */
+							 2 21 0x2 0x0	/* PC21 periph B */
+							 2 22 0x2 0x0	/* PC22 periph B */
+							 2 23 0x2 0x0	/* PC23 periph B */
+							 2 24 0x2 0x0	/* PC24 periph B */
+							 2 25 0x2 0x0	/* PC25 periph B */
+							 2 27 0x2 0x0	/* PC27 periph B */
+							 4 22 0x2 0x0>;	/* PE22 periph B */
+					};
+				};
+
+				mmc0 {
+					pinctrl_mmc0_clk: mmc0_clk-0 {
+						atmel,pins =
+							<0 12 0x1 0x0>;	/* PA12 periph A */
+					};
+
+					pinctrl_mmc0_slot0_cmd_dat0: mmc0_slot0_cmd_dat0-0 {
+						atmel,pins =
+							<0 1 0x1 0x1	/* PA1 periph A with pullup */
+							 0 0 0x1 0x1>;	/* PA0 periph A with pullup */
+					};
+
+					pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 {
+						atmel,pins =
+							<0 3 0x1 0x1	/* PA3 periph A with pullup */
+							 0 4 0x1 0x1	/* PA4 periph A with pullup */
+							 0 5 0x1 0x1>;	/* PA5 periph A with pullup */
+					};
+
+					pinctrl_mmc0_slot1_cmd_dat0: mmc0_slot1_cmd_dat0-0 {
+						atmel,pins =
+							<0 16 0x1 0x1	/* PA16 periph A with pullup */
+							 0 17 0x1 0x1>;	/* PA17 periph A with pullup */
+					};
+
+					pinctrl_mmc0_slot1_dat1_3: mmc0_slot1_dat1_3-0 {
+						atmel,pins =
+							<0 18 0x1 0x1	/* PA18 periph A with pullup */
+							 0 19 0x1 0x1	/* PA19 periph A with pullup */
+							 0 20 0x1 0x1>;	/* PA20 periph A with pullup */
+					};
+				};
+
+				mmc1 {
+					pinctrl_mmc1_clk: mmc1_clk-0 {
+						atmel,pins =
+							<0 6 0x1 0x0>;	/* PA6 periph A */
+					};
+
+					pinctrl_mmc1_slot0_cmd_dat0: mmc1_slot0_cmd_dat0-0 {
+						atmel,pins =
+							<0 7 0x1 0x1	/* PA7 periph A with pullup */
+							 0 8 0x1 0x1>;	/* PA8 periph A with pullup */
+					};
+
+					pinctrl_mmc1_slot0_dat1_3: mmc1_slot0_dat1_3-0 {
+						atmel,pins =
+							<0 9 0x1 0x1	/* PA9 periph A with pullup */
+							 0 10 0x1 0x1	/* PA10 periph A with pullup */
+							 0 11 0x1 0x1>;	/* PA11 periph A with pullup */
+					};
+
+					pinctrl_mmc1_slot1_cmd_dat0: mmc1_slot1_cmd_dat0-0 {
+						atmel,pins =
+							<0 21 0x1 0x1	/* PA21 periph A with pullup */
+							 0 22 0x1 0x1>;	/* PA22 periph A with pullup */
+					};
+
+					pinctrl_mmc1_slot1_dat1_3: mmc1_slot1_dat1_3-0 {
+						atmel,pins =
+							<0 23 0x1 0x1	/* PA23 periph A with pullup */
+							 0 24 0x1 0x1	/* PA24 periph A with pullup */
+							 0 25 0x1 0x1>;	/* PA25 periph A with pullup */
+					};
+				};
+
+				pioA: gpio@fffff200 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffff200 0x200>;
+					interrupts = <2 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioB: gpio@fffff400 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffff400 0x200>;
+					interrupts = <3 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioC: gpio@fffff600 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffff600 0x200>;
+					interrupts = <4 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioD: gpio@fffff800 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffff800 0x200>;
+					interrupts = <4 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioE: gpio@fffffa00 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffffa00 0x200>;
+					interrupts = <4 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
 			};
 
 			dbgu: serial@ffffee00 {
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xffffee00 0x200>;
 				interrupts = <1 4 7>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_dbgu>;
 				status = "disabled";
 			};
 
@@ -152,6 +337,8 @@
 				interrupts = <7 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart0>;
 				status = "disabled";
 			};
 
@@ -161,6 +348,8 @@
 				interrupts = <8 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart1>;
 				status = "disabled";
 			};
 
@@ -170,13 +359,31 @@
 				interrupts = <9 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart2>;
 				status = "disabled";
 			};
 
+			ssc0: ssc@fff98000 {
+				compatible = "atmel,at91rm9200-ssc";
+				reg = <0xfff98000 0x4000>;
+				interrupts = <16 4 5>;
+				status = "disable";
+			};
+
+			ssc1: ssc@fff9c000 {
+				compatible = "atmel,at91rm9200-ssc";
+				reg = <0xfff9c000 0x4000>;
+				interrupts = <17 4 5>;
+				status = "disable";
+			};
+
 			macb0: ethernet@fffbc000 {
 				compatible = "cdns,at32ap7000-macb", "cdns,macb";
 				reg = <0xfffbc000 0x100>;
 				interrupts = <21 4 3>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_macb_rmii>;
 				status = "disabled";
 			};
 
@@ -195,6 +402,30 @@
 				#size-cells = <0>;
 				status = "disabled";
 			};
+
+			mmc0: mmc@fff80000 {
+				compatible = "atmel,hsmci";
+				reg = <0xfff80000 0x600>;
+				interrupts = <10 4 0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			mmc1: mmc@fff84000 {
+				compatible = "atmel,hsmci";
+				reg = <0xfff84000 0x600>;
+				interrupts = <11 4 0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			watchdog@fffffd40 {
+				compatible = "atmel,at91sam9260-wdt";
+				reg = <0xfffffd40 0x10>;
+				status = "disabled";
+			};
 		};
 
 		nand0: nand@40000000 {
@@ -206,6 +437,8 @@
 			      >;
 			atmel,nand-addr-offset = <21>;
 			atmel,nand-cmd-offset = <22>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_nand>;
 			gpios = <&pioA 22 0
 				 &pioD 15 0
 				 0
diff --git a/arch/arm/boot/dts/at91sam9263ek.dts b/arch/arm/boot/dts/at91sam9263ek.dts
index f86ac4b..1eb0872 100644
--- a/arch/arm/boot/dts/at91sam9263ek.dts
+++ b/arch/arm/boot/dts/at91sam9263ek.dts
@@ -38,6 +38,10 @@
 			};
 
 			usart0: serial@fff8c000 {
+				pinctrl-0 = <
+					&pinctrl_usart0
+					&pinctrl_usart0_rts
+					&pinctrl_usart0_cts>;
 				status = "okay";
 			};
 
@@ -50,6 +54,31 @@
 				atmel,vbus-gpio = <&pioA 25 0>;
 				status = "okay";
 			};
+
+			mmc0: mmc@fff80000 {
+				pinctrl-0 = <
+					&pinctrl_board_mmc0
+					&pinctrl_mmc0_clk
+					&pinctrl_mmc0_slot0_cmd_dat0
+					&pinctrl_mmc0_slot0_dat1_3>;
+				status = "okay";
+				slot@0 {
+					reg = <0>;
+					bus-width = <4>;
+					cd-gpios = <&pioE 18 0>;
+					wp-gpios = <&pioE 19 0>;
+				};
+			};
+
+			pinctrl@fffff200 {
+				mmc0 {
+					pinctrl_board_mmc0: mmc0-board {
+						atmel,pins =
+							<5 18 0x0 0x5	/* PE18 gpio CD pin pull up and deglitch */
+							 5 19 0x0 0x1>;	/* PE19 gpio WP pin pull up */
+					};
+				};
+			};
 		};
 
 		nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9g15.dtsi b/arch/arm/boot/dts/at91sam9g15.dtsi
new file mode 100644
index 0000000..fbe7a70
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g15.dtsi
@@ -0,0 +1,28 @@
+/*
+ * at91sam9g15.dtsi - Device Tree Include file for AT91SAM9G15 SoC
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/include/ "at91sam9x5.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9G15 SoC";
+	compatible = "atmel, at91sam9g15, atmel,at91sam9x5";
+
+	ahb {
+		apb {
+			pinctrl@fffff400 {
+				atmel,mux-mask = <
+				      /*    A         B          C     */
+				       0xffffffff 0xffe0399f 0x00000000  /* pioA */
+				       0x00040000 0x00047e3f 0x00000000  /* pioB */
+				       0xfdffffff 0x00000000 0xb83fffff  /* pioC */
+				       0x003fffff 0x003f8000 0x00000000  /* pioD */
+				      >;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/at91sam9g15ek.dts b/arch/arm/boot/dts/at91sam9g15ek.dts
new file mode 100644
index 0000000..86dd3f6
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g15ek.dts
@@ -0,0 +1,16 @@
+/*
+ * at91sam9g15ek.dts - Device Tree file for AT91SAM9G15-EK board
+ *
+ *  Copyright (C) 2012 Atmel,
+ *                2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9g15.dtsi"
+/include/ "at91sam9x5ek.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9G25-EK";
+	compatible = "atmel,at91sam9g15ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+};
diff --git a/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts b/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts
index f1b2e14..66467b1 100644
--- a/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts
+++ b/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts
@@ -12,6 +12,32 @@
 	model = "Atmel at91sam9g20ek 2 mmc";
 	compatible = "atmel,at91sam9g20ek_2mmc", "atmel,at91sam9g20", "atmel,at91sam9";
 
+	ahb {
+		apb{
+			mmc0: mmc@fffa8000 {
+				/* clk already mux wuth slot0 */
+				pinctrl-0 = <
+					&pinctrl_board_mmc0_slot0
+					&pinctrl_mmc0_slot0_cmd_dat0
+					&pinctrl_mmc0_slot0_dat1_3>;
+				slot@0 {
+					reg = <0>;
+					bus-width = <4>;
+					cd-gpios = <&pioC 2 0>;
+				};
+			};
+
+			pinctrl@fffff400 {
+				mmc0_slot0 {
+					pinctrl_board_mmc0_slot0: mmc0_slot0-board {
+						atmel,pins =
+							<2 2 0x0 0x5>;	/* PC2 gpio CD pin pull up and deglitch */
+					};
+				};
+			};
+		};
+	};
+
 	leds {
 		compatible = "gpio-leds";
 
diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
index e6391a4..832b8f0 100644
--- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
@@ -30,11 +30,28 @@
 
 	ahb {
 		apb {
+			pinctrl@fffff400 {
+				board {
+					pinctrl_pck0_as_mck: pck0_as_mck {
+						atmel,pins =
+							<2 1 0x2 0x0>;	/* PC1 periph B */
+					};
+
+				};
+			};
+
 			dbgu: serial@fffff200 {
 				status = "okay";
 			};
 
 			usart0: serial@fffb0000 {
+				pinctrl-0 =
+					<&pinctrl_usart0
+					 &pinctrl_usart0_rts
+					 &pinctrl_usart0_cts
+					 &pinctrl_usart0_dtr_dsr
+					 &pinctrl_usart0_dcd
+					 &pinctrl_usart0_ri>;
 				status = "okay";
 			};
 
@@ -51,6 +68,34 @@
 				atmel,vbus-gpio = <&pioC 5 0>;
 				status = "okay";
 			};
+
+			mmc0: mmc@fffa8000 {
+				pinctrl-0 = <
+					&pinctrl_board_mmc0_slot1
+					&pinctrl_mmc0_clk
+					&pinctrl_mmc0_slot1_cmd_dat0
+					&pinctrl_mmc0_slot1_dat1_3>;
+				status = "okay";
+				slot@1 {
+					reg = <1>;
+					bus-width = <4>;
+					cd-gpios = <&pioC 9 0>;
+				};
+			};
+
+			ssc0: ssc@fffbc000 {
+				status = "okay";
+				pinctrl-0 = <&pinctrl_ssc0_tx>;
+			};
+
+			pinctrl@fffff400 {
+				mmc0_slot1 {
+					pinctrl_board_mmc0_slot1: mmc0_slot1-board {
+						atmel,pins =
+							<2 9 0x0 0x5>;	/* PC9 gpio CD pin pull up and deglitch */
+					};
+				};
+			};
 		};
 
 		nand0: nand@40000000 {
@@ -114,7 +159,7 @@
 			reg = <0x50>;
 		};
 
-		wm8731@1b {
+		wm8731: wm8731@1b {
 			compatible = "wm8731";
 			reg = <0x1b>;
 		};
@@ -139,4 +184,19 @@
 			gpio-key,wakeup;
 		};
 	};
+
+	sound {
+		compatible = "atmel,at91sam9g20ek-wm8731-audio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pck0_as_mck>;
+
+		atmel,model = "wm8731 @ AT91SAMG20EK";
+
+		atmel,audio-routing =
+			"Ext Spk", "LHPOUT",
+			"Int Mic", "MICIN";
+
+		atmel,ssc-controller = <&ssc0>;
+		atmel,audio-codec = <&wm8731>;
+	};
 };
diff --git a/arch/arm/boot/dts/at91sam9g25.dtsi b/arch/arm/boot/dts/at91sam9g25.dtsi
new file mode 100644
index 0000000..05a718f
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g25.dtsi
@@ -0,0 +1,28 @@
+/*
+ * at91sam9g25.dtsi - Device Tree Include file for AT91SAM9G25 SoC
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/include/ "at91sam9x5.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9G25 SoC";
+	compatible = "atmel, at91sam9g25, atmel,at91sam9x5";
+
+	ahb {
+		apb {
+			pinctrl@fffff400 {
+				atmel,mux-mask = <
+				      /*    A         B          C     */
+				       0xffffffff 0xffe0399f 0xc000001c  /* pioA */
+				       0x0007ffff 0x8000fe3f 0x00000000  /* pioB */
+				       0x80000000 0x07c0ffff 0xb83fffff  /* pioC */
+				       0x003fffff 0x003f8000 0x00000000  /* pioD */
+				      >;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts
index 877c08f..c5ab16f 100644
--- a/arch/arm/boot/dts/at91sam9g25ek.dts
+++ b/arch/arm/boot/dts/at91sam9g25ek.dts
@@ -7,55 +7,10 @@
  * Licensed under GPLv2 or later.
  */
 /dts-v1/;
-/include/ "at91sam9x5.dtsi"
-/include/ "at91sam9x5cm.dtsi"
+/include/ "at91sam9g25.dtsi"
+/include/ "at91sam9x5ek.dtsi"
 
 / {
 	model = "Atmel AT91SAM9G25-EK";
 	compatible = "atmel,at91sam9g25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
-
-	chosen {
-		bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
-	};
-
-	ahb {
-		apb {
-			dbgu: serial@fffff200 {
-				status = "okay";
-			};
-
-			usart0: serial@f801c000 {
-				status = "okay";
-			};
-
-			macb0: ethernet@f802c000 {
-				phy-mode = "rmii";
-				status = "okay";
-			};
-
-			i2c0: i2c@f8010000 {
-				status = "okay";
-			};
-
-			i2c1: i2c@f8014000 {
-				status = "okay";
-			};
-
-			i2c2: i2c@f8018000 {
-				status = "okay";
-			};
-		};
-
-		usb0: ohci@00600000 {
-			status = "okay";
-			num-ports = <2>;
-			atmel,vbus-gpio = <&pioD 19 1
-					   &pioD 20 1
-					  >;
-		};
-
-		usb1: ehci@00700000 {
-			status = "okay";
-		};
-	};
 };
diff --git a/arch/arm/boot/dts/at91sam9g35.dtsi b/arch/arm/boot/dts/at91sam9g35.dtsi
new file mode 100644
index 0000000..f9d14a7
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g35.dtsi
@@ -0,0 +1,28 @@
+/*
+ * at91sam9g35.dtsi - Device Tree Include file for AT91SAM9G35 SoC
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/include/ "at91sam9x5.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9G35 SoC";
+	compatible = "atmel, at91sam9g35, atmel,at91sam9x5";
+
+	ahb {
+		apb {
+			pinctrl@fffff400 {
+				atmel,mux-mask = <
+				      /*    A         B          C     */
+				       0xffffffff 0xffe0399f 0xc000000c  /* pioA */
+				       0x000406ff 0x00047e3f 0x00000000  /* pioB */
+				       0xfdffffff 0x00000000 0xb83fffff  /* pioC */
+				       0x003fffff 0x003f8000 0x00000000  /* pioD */
+				      >;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/at91sam9g35ek.dts b/arch/arm/boot/dts/at91sam9g35ek.dts
new file mode 100644
index 0000000..95944bd
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g35ek.dts
@@ -0,0 +1,16 @@
+/*
+ * at91sam9g35ek.dts - Device Tree file for AT91SAM9G35-EK board
+ *
+ *  Copyright (C) 2012 Atmel,
+ *                2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9g35.dtsi"
+/include/ "at91sam9x5ek.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9G35-EK";
+	compatible = "atmel,at91sam9g35ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+};
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index 3add030..fa1ae0c 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -31,6 +31,8 @@
 		tcb1 = &tcb1;
 		i2c0 = &i2c0;
 		i2c1 = &i2c1;
+		ssc0 = &ssc0;
+		ssc1 = &ssc1;
 	};
 	cpus {
 		cpu@0 {
@@ -108,60 +110,243 @@
 				interrupts = <21 4 0>;
 			};
 
-			pioA: gpio@fffff200 {
-				compatible = "atmel,at91rm9200-gpio";
-				reg = <0xfffff200 0x100>;
-				interrupts = <2 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+			pinctrl@fffff200 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
+				ranges = <0xfffff200 0xfffff200 0xa00>;
+
+				atmel,mux-mask = <
+				      /*    A         B     */
+				       0xffffffff 0xffc003ff  /* pioA */
+				       0xffffffff 0x800f8f00  /* pioB */
+				       0xffffffff 0x00000e00  /* pioC */
+				       0xffffffff 0xff0c1381  /* pioD */
+				       0xffffffff 0x81ffff81  /* pioE */
+				      >;
+
+				/* shared pinctrl settings */
+				dbgu {
+					pinctrl_dbgu: dbgu-0 {
+						atmel,pins =
+							<1 12 0x1 0x0	/* PB12 periph A */
+							 1 13 0x1 0x0>;	/* PB13 periph A */
+					};
+				};
 
-			pioB: gpio@fffff400 {
-				compatible = "atmel,at91rm9200-gpio";
-				reg = <0xfffff400 0x100>;
-				interrupts = <3 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+				usart0 {
+					pinctrl_usart0: usart0-0 {
+						atmel,pins =
+							<1 19 0x1 0x1	/* PB19 periph A with pullup */
+							 1 18 0x1 0x0>;	/* PB18 periph A */
+					};
+
+					pinctrl_usart0_rts: usart0_rts-0 {
+						atmel,pins =
+							<1 17 0x2 0x0>;	/* PB17 periph B */
+					};
+
+					pinctrl_usart0_cts: usart0_cts-0 {
+						atmel,pins =
+							<1 15 0x2 0x0>;	/* PB15 periph B */
+					};
+				};
 
-			pioC: gpio@fffff600 {
-				compatible = "atmel,at91rm9200-gpio";
-				reg = <0xfffff600 0x100>;
-				interrupts = <4 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+				uart1 {
+					pinctrl_usart1: usart1-0 {
+						atmel,pins =
+							<1 4 0x1 0x1	/* PB4 periph A with pullup */
+							 1 5 0x1 0x0>;	/* PB5 periph A */
+					};
+
+					pinctrl_usart1_rts: usart1_rts-0 {
+						atmel,pins =
+							<3 16 0x1 0x0>;	/* PD16 periph A */
+					};
+
+					pinctrl_usart1_cts: usart1_cts-0 {
+						atmel,pins =
+							<3 17 0x1 0x0>;	/* PD17 periph A */
+					};
+				};
 
-			pioD: gpio@fffff800 {
-				compatible = "atmel,at91rm9200-gpio";
-				reg = <0xfffff800 0x100>;
-				interrupts = <5 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+				usart2 {
+					pinctrl_usart2: usart2-0 {
+						atmel,pins =
+							<1 6 0x1 0x1	/* PB6 periph A with pullup */
+							 1 7 0x1 0x0>;	/* PB7 periph A */
+					};
+
+					pinctrl_usart2_rts: usart2_rts-0 {
+						atmel,pins =
+							<2 9 0x2 0x0>;	/* PC9 periph B */
+					};
+
+					pinctrl_usart2_cts: usart2_cts-0 {
+						atmel,pins =
+							<2 11 0x2 0x0>;	/* PC11 periph B */
+					};
+				};
 
-			pioE: gpio@fffffa00 {
-				compatible = "atmel,at91rm9200-gpio";
-				reg = <0xfffffa00 0x100>;
-				interrupts = <5 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
+				usart3 {
+					pinctrl_usart3: usart3-0 {
+						atmel,pins =
+							<1 8 0x1 0x1	/* PB9 periph A with pullup */
+							 1 9 0x1 0x0>;	/* PB8 periph A */
+					};
+
+					pinctrl_usart3_rts: usart3_rts-0 {
+						atmel,pins =
+							<0 23 0x2 0x0>;	/* PA23 periph B */
+					};
+
+					pinctrl_usart3_cts: usart3_cts-0 {
+						atmel,pins =
+							<0 24 0x2 0x0>;	/* PA24 periph B */
+					};
+				};
+
+				nand {
+					pinctrl_nand: nand-0 {
+						atmel,pins =
+							<2 8 0x0 0x1	/* PC8 gpio RDY pin pull_up*/
+							 2 14 0x0 0x1>;	/* PC14 gpio enable pin pull_up */
+					};
+				};
+
+				macb {
+					pinctrl_macb_rmii: macb_rmii-0 {
+						atmel,pins =
+							<0 10 0x1 0x0	/* PA10 periph A */
+							 0 11 0x1 0x0	/* PA11 periph A */
+							 0 12 0x1 0x0	/* PA12 periph A */
+							 0 13 0x1 0x0	/* PA13 periph A */
+							 0 14 0x1 0x0	/* PA14 periph A */
+							 0 15 0x1 0x0	/* PA15 periph A */
+							 0 16 0x1 0x0	/* PA16 periph A */
+							 0 17 0x1 0x0	/* PA17 periph A */
+							 0 18 0x1 0x0	/* PA18 periph A */
+							 0 19 0x1 0x0>;	/* PA19 periph A */
+					};
+
+					pinctrl_macb_rmii_mii: macb_rmii_mii-0 {
+						atmel,pins =
+							<0 6 0x2 0x0	/* PA6 periph B */
+							 0 7 0x2 0x0	/* PA7 periph B */
+							 0 8 0x2 0x0	/* PA8 periph B */
+							 0 9 0x2 0x0	/* PA9 periph B */
+							 0 27 0x2 0x0	/* PA27 periph B */
+							 0 28 0x2 0x0	/* PA28 periph B */
+							 0 29 0x2 0x0	/* PA29 periph B */
+							 0 30 0x2 0x0>;	/* PA30 periph B */
+					};
+				};
+
+				mmc0 {
+					pinctrl_mmc0_slot0_clk_cmd_dat0: mmc0_slot0_clk_cmd_dat0-0 {
+						atmel,pins =
+							<0 0 0x1 0x0	/* PA0 periph A */
+							 0 1 0x1 0x1	/* PA1 periph A with pullup */
+							 0 2 0x1 0x1>;	/* PA2 periph A with pullup */
+					};
+
+					pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 {
+						atmel,pins =
+							<0 3 0x1 0x1	/* PA3 periph A with pullup */
+							 0 4 0x1 0x1	/* PA4 periph A with pullup */
+							 0 5 0x1 0x1>;	/* PA5 periph A with pullup */
+					};
+
+					pinctrl_mmc0_slot0_dat4_7: mmc0_slot0_dat4_7-0 {
+						atmel,pins =
+							<0 6 0x1 0x1	/* PA6 periph A with pullup */
+							 0 7 0x1 0x1	/* PA7 periph A with pullup */
+							 0 8 0x1 0x1	/* PA8 periph A with pullup */
+							 0 9 0x1 0x1>;	/* PA9 periph A with pullup */
+					};
+				};
+
+				mmc1 {
+					pinctrl_mmc1_slot0_clk_cmd_dat0: mmc1_slot0_clk_cmd_dat0-0 {
+						atmel,pins =
+							<0 31 0x1 0x0	/* PA31 periph A */
+							 0 22 0x1 0x1	/* PA22 periph A with pullup */
+							 0 23 0x1 0x1>;	/* PA23 periph A with pullup */
+					};
+
+					pinctrl_mmc1_slot0_dat1_3: mmc1_slot0_dat1_3-0 {
+						atmel,pins =
+							<0 24 0x1 0x1	/* PA24 periph A with pullup */
+							 0 25 0x1 0x1	/* PA25 periph A with pullup */
+							 0 26 0x1 0x1>;	/* PA26 periph A with pullup */
+					};
+
+					pinctrl_mmc1_slot0_dat4_7: mmc1_slot0_dat4_7-0 {
+						atmel,pins =
+							<0 27 0x1 0x1	/* PA27 periph A with pullup */
+							 0 28 0x1 0x1	/* PA28 periph A with pullup */
+							 0 29 0x1 0x1	/* PA29 periph A with pullup */
+							 0 20 0x1 0x1>;	/* PA30 periph A with pullup */
+					};
+				};
+
+				pioA: gpio@fffff200 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffff200 0x200>;
+					interrupts = <2 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioB: gpio@fffff400 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffff400 0x200>;
+					interrupts = <3 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioC: gpio@fffff600 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffff600 0x200>;
+					interrupts = <4 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioD: gpio@fffff800 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffff800 0x200>;
+					interrupts = <5 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioE: gpio@fffffa00 {
+					compatible = "atmel,at91rm9200-gpio";
+					reg = <0xfffffa00 0x200>;
+					interrupts = <5 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
 			};
 
 			dbgu: serial@ffffee00 {
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xffffee00 0x200>;
 				interrupts = <1 4 7>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_dbgu>;
 				status = "disabled";
 			};
 
@@ -171,6 +356,8 @@
 				interrupts = <7 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart0>;
 				status = "disabled";
 			};
 
@@ -180,6 +367,8 @@
 				interrupts = <8 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart1>;
 				status = "disabled";
 			};
 
@@ -189,6 +378,8 @@
 				interrupts = <9 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart2>;
 				status = "disabled";
 			};
 
@@ -198,6 +389,8 @@
 				interrupts = <10 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart3>;
 				status = "disabled";
 			};
 
@@ -205,6 +398,8 @@
 				compatible = "cdns,at32ap7000-macb", "cdns,macb";
 				reg = <0xfffbc000 0x100>;
 				interrupts = <25 4 3>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_macb_rmii>;
 				status = "disabled";
 			};
 
@@ -226,6 +421,20 @@
 				status = "disabled";
 			};
 
+			ssc0: ssc@fff9c000 {
+				compatible = "atmel,at91sam9g45-ssc";
+				reg = <0xfff9c000 0x4000>;
+				interrupts = <16 4 5>;
+				status = "disable";
+			};
+
+			ssc1: ssc@fffa0000 {
+				compatible = "atmel,at91sam9g45-ssc";
+				reg = <0xfffa0000 0x4000>;
+				interrupts = <17 4 5>;
+				status = "disable";
+			};
+
 			adc0: adc@fffb0000 {
 				compatible = "atmel,at91sam9260-adc";
 				reg = <0xfffb0000 0x100>;
@@ -262,6 +471,30 @@
 					trigger-value = <0x6>;
 				};
 			};
+
+			mmc0: mmc@fff80000 {
+				compatible = "atmel,hsmci";
+				reg = <0xfff80000 0x600>;
+				interrupts = <11 4 0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			mmc1: mmc@fffd0000 {
+				compatible = "atmel,hsmci";
+				reg = <0xfffd0000 0x600>;
+				interrupts = <29 4 0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			watchdog@fffffd40 {
+				compatible = "atmel,at91sam9260-wdt";
+				reg = <0xfffffd40 0x10>;
+				status = "disabled";
+			};
 		};
 
 		nand0: nand@40000000 {
@@ -273,6 +506,8 @@
 			      >;
 			atmel,nand-addr-offset = <21>;
 			atmel,nand-cmd-offset = <22>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_nand>;
 			gpios = <&pioC 8 0
 				 &pioC 14 0
 				 0
diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts
index 15e1dd4..20c3191 100644
--- a/arch/arm/boot/dts/at91sam9m10g45ek.dts
+++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts
@@ -39,6 +39,10 @@
 			};
 
 			usart1: serial@fff90000 {
+				pinctrl-0 =
+					<&pinctrl_usart1
+					 &pinctrl_usart1_rts
+					 &pinctrl_usart1_cts>;
 				status = "okay";
 			};
 
@@ -54,6 +58,50 @@
 			i2c1: i2c@fff88000 {
 				status = "okay";
 			};
+
+			mmc0: mmc@fff80000 {
+				pinctrl-0 = <
+					&pinctrl_board_mmc0
+					&pinctrl_mmc0_slot0_clk_cmd_dat0
+					&pinctrl_mmc0_slot0_dat1_3>;
+				status = "okay";
+				slot@0 {
+					reg = <0>;
+					bus-width = <4>;
+					cd-gpios = <&pioD 10 0>;
+				};
+			};
+
+			mmc1: mmc@fffd0000 {
+				pinctrl-0 = <
+					&pinctrl_board_mmc1
+					&pinctrl_mmc1_slot0_clk_cmd_dat0
+					&pinctrl_mmc1_slot0_dat1_3>;
+				status = "okay";
+				slot@0 {
+					reg = <0>;
+					bus-width = <4>;
+					cd-gpios = <&pioD 11 0>;
+					wp-gpios = <&pioD 29 0>;
+				};
+			};
+
+			pinctrl@fffff200 {
+				mmc0 {
+					pinctrl_board_mmc0: mmc0-board {
+						atmel,pins =
+							<3 10 0x0 0x5>;	/* PD10 gpio CD pin pull up and deglitch */
+					};
+				};
+
+				mmc1 {
+					pinctrl_board_mmc1: mmc1-board {
+						atmel,pins =
+							<3 11 0x0 0x5	/* PD11 gpio CD pin pull up and deglitch */
+							 3 29 0x0 0x1>;	/* PD29 gpio WP pin pull up */
+					};
+				};
+			};
 		};
 
 		nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
index 82508d6..e9efb34 100644
--- a/arch/arm/boot/dts/at91sam9n12.dtsi
+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
@@ -84,6 +84,15 @@
 				reg = <0xfffffe10 0x10>;
 			};
 
+			mmc0: mmc@f0008000 {
+				compatible = "atmel,hsmci";
+				reg = <0xf0008000 0x600>;
+				interrupts = <12 4 0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
 			tcb0: timer@f8008000 {
 				compatible = "atmel,at91sam9x5-tcb";
 				reg = <0xf8008000 0x100>;
@@ -102,50 +111,186 @@
 				interrupts = <20 4 0>;
 			};
 
-			pioA: gpio@fffff400 {
-				compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-				reg = <0xfffff400 0x100>;
-				interrupts = <2 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+			pinctrl@fffff400 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus";
+				ranges = <0xfffff400 0xfffff400 0x800>;
 
-			pioB: gpio@fffff600 {
-				compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-				reg = <0xfffff600 0x100>;
-				interrupts = <2 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+				atmel,mux-mask = <
+				      /*    A         B          C     */
+				       0xffffffff 0xffe07983 0x00000000  /* pioA */
+				       0x00040000 0x00047e0f 0x00000000  /* pioB */
+				       0xfdffffff 0x07c00000 0xb83fffff  /* pioC */
+				       0x003fffff 0x003f8000 0x00000000  /* pioD */
+				      >;
 
-			pioC: gpio@fffff800 {
-				compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-				reg = <0xfffff800 0x100>;
-				interrupts = <3 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+				/* shared pinctrl settings */
+				dbgu {
+					pinctrl_dbgu: dbgu-0 {
+						atmel,pins =
+							<0 9 0x1 0x0	/* PA9 periph A */
+							 0 10 0x1 0x1>;	/* PA10 periph with pullup */
+					};
+				};
 
-			pioD: gpio@fffffa00 {
-				compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-				reg = <0xfffffa00 0x100>;
-				interrupts = <3 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
+				usart0 {
+					pinctrl_usart0: usart0-0 {
+						atmel,pins =
+							<0 1 0x1 0x1	/* PA1 periph A with pullup */
+							 0 0 0x1 0x0>;	/* PA0 periph A */
+					};
+
+					pinctrl_usart0_rts: usart0_rts-0 {
+						atmel,pins =
+							<0 2 0x1 0x0>;	/* PA2 periph A */
+					};
+
+					pinctrl_usart0_cts: usart0_cts-0 {
+						atmel,pins =
+							<0 3 0x1 0x0>;	/* PA3 periph A */
+					};
+				};
+
+				usart1 {
+					pinctrl_usart1: usart1-0 {
+						atmel,pins =
+							<0 6 0x1 0x1	/* PA6 periph A with pullup */
+							 0 5 0x1 0x0>;	/* PA5 periph A */
+					};
+				};
+
+				usart2 {
+					pinctrl_usart2: usart2-0 {
+						atmel,pins =
+							<0 8 0x1 0x1	/* PA8 periph A with pullup */
+							 0 7 0x1 0x0>;	/* PA7 periph A */
+					};
+
+					pinctrl_usart2_rts: usart2_rts-0 {
+						atmel,pins =
+							<1 0 0x2 0x0>;	/* PB0 periph B */
+					};
+
+					pinctrl_usart2_cts: usart2_cts-0 {
+						atmel,pins =
+							<1 1 0x2 0x0>;	/* PB1 periph B */
+					};
+				};
+
+				usart3 {
+					pinctrl_usart3: usart3-0 {
+						atmel,pins =
+							<2 23 0x2 0x1	/* PC23 periph B with pullup */
+							 2 22 0x2 0x0>;	/* PC22 periph B */
+					};
+
+					pinctrl_usart3_rts: usart3_rts-0 {
+						atmel,pins =
+							<2 24 0x2 0x0>;	/* PC24 periph B */
+					};
+
+					pinctrl_usart3_cts: usart3_cts-0 {
+						atmel,pins =
+							<2 25 0x2 0x0>;	/* PC25 periph B */
+					};
+				};
+
+				uart0 {
+					pinctrl_uart0: uart0-0 {
+						atmel,pins =
+							<2 9 0x3 0x1	/* PC9 periph C with pullup */
+							 2 8 0x3 0x0>;	/* PC8 periph C */
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1: uart1-0 {
+						atmel,pins =
+							<2 16 0x3 0x1	/* PC17 periph C with pullup */
+							 2 17 0x3 0x0>;	/* PC16 periph C */
+					};
+				};
+
+				nand {
+					pinctrl_nand: nand-0 {
+						atmel,pins =
+							<3 5 0x0 0x1	/* PD5 gpio RDY pin pull_up*/
+							 3 4 0x0 0x1>;	/* PD4 gpio enable pin pull_up */
+					};
+				};
+
+				mmc0 {
+					pinctrl_mmc0_slot0_clk_cmd_dat0: mmc0_slot0_clk_cmd_dat0-0 {
+						atmel,pins =
+							<0 17 0x1 0x0	/* PA17 periph A */
+							 0 16 0x1 0x1	/* PA16 periph A with pullup */
+							 0 15 0x1 0x1>;	/* PA15 periph A with pullup */
+					};
+
+					pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 {
+						atmel,pins =
+							<0 18 0x1 0x1	/* PA18 periph A with pullup */
+							 0 19 0x1 0x1	/* PA19 periph A with pullup */
+							 0 20 0x1 0x1>;	/* PA20 periph A with pullup */
+					};
+
+					pinctrl_mmc0_slot0_dat4_7: mmc0_slot0_dat4_7-0 {
+						atmel,pins =
+							<0 11 0x2 0x1	/* PA11 periph B with pullup */
+							 0 12 0x2 0x1	/* PA12 periph B with pullup */
+							 0 13 0x2 0x1	/* PA13 periph B with pullup */
+							 0 14 0x2 0x1>;	/* PA14 periph B with pullup */
+					};
+				};
+
+				pioA: gpio@fffff400 {
+					compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+					reg = <0xfffff400 0x200>;
+					interrupts = <2 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioB: gpio@fffff600 {
+					compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+					reg = <0xfffff600 0x200>;
+					interrupts = <2 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioC: gpio@fffff800 {
+					compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+					reg = <0xfffff800 0x200>;
+					interrupts = <3 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioD: gpio@fffffa00 {
+					compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+					reg = <0xfffffa00 0x200>;
+					interrupts = <3 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
 			};
 
 			dbgu: serial@fffff200 {
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xfffff200 0x200>;
 				interrupts = <1 4 7>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_dbgu>;
 				status = "disabled";
 			};
 
@@ -155,6 +300,8 @@
 				interrupts = <5 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart0>;
 				status = "disabled";
 			};
 
@@ -164,6 +311,8 @@
 				interrupts = <6 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart1>;
 				status = "disabled";
 			};
 
@@ -173,6 +322,8 @@
 				interrupts = <7 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart2>;
 				status = "disabled";
 			};
 
@@ -182,6 +333,8 @@
 				interrupts = <8 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart3>;
 				status = "disabled";
 			};
 
@@ -215,6 +368,8 @@
 			       >;
 			atmel,nand-addr-offset = <21>;
 			atmel,nand-cmd-offset = <22>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_nand>;
 			gpios = <&pioD 5 0
 				 &pioD 4 0
 				 0
diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts
index 912b2c2..0376bf4 100644
--- a/arch/arm/boot/dts/at91sam9n12ek.dts
+++ b/arch/arm/boot/dts/at91sam9n12ek.dts
@@ -45,6 +45,28 @@
 			i2c1: i2c@f8014000 {
 				status = "okay";
 			};
+
+			mmc0: mmc@f0008000 {
+				pinctrl-0 = <
+					&pinctrl_board_mmc0
+					&pinctrl_mmc0_slot0_clk_cmd_dat0
+					&pinctrl_mmc0_slot0_dat1_3>;
+				status = "okay";
+				slot@0 {
+					reg = <0>;
+					bus-width = <4>;
+					cd-gpios = <&pioA 7 0>;
+				};
+			};
+
+			pinctrl@fffff400 {
+				mmc0 {
+					pinctrl_board_mmc0: mmc0-board {
+						atmel,pins =
+							<0 7 0x0 0x5>;	/* PA7 gpio CD pin pull up and deglitch */
+					};
+				};
+			};
 		};
 
 		nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9x25.dtsi b/arch/arm/boot/dts/at91sam9x25.dtsi
new file mode 100644
index 0000000..54eb33b
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9x25.dtsi
@@ -0,0 +1,49 @@
+/*
+ * at91sam9x25.dtsi - Device Tree Include file for AT91SAM9X25 SoC
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/include/ "at91sam9x5.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9X25 SoC";
+	compatible = "atmel, at91sam9x25, atmel,at91sam9x5";
+
+	ahb {
+		apb {
+			pinctrl@fffff400 {
+				atmel,mux-mask = <
+				      /*    A         B          C     */
+				       0xffffffff 0xffe03fff 0xc000001c  /* pioA */
+				       0x0007ffff 0x00047e3f 0x00000000  /* pioB */
+				       0x80000000 0xfffd0000 0xb83fffff  /* pioC */
+				       0x003fffff 0x003f8000 0x00000000  /* pioD */
+				      >;
+
+				macb1 {
+					pinctrl_macb1_rmii: macb1_rmii-0 {
+						atmel,pins =
+							<2 16 0x2 0x0	/* PC16 periph B */
+							 2 18 0x2 0x0	/* PC18 periph B */
+							 2 19 0x2 0x0	/* PC19 periph B */
+							 2 20 0x2 0x0	/* PC20 periph B */
+							 2 21 0x2 0x0	/* PC21 periph B */
+							 2 27 0x2 0x0	/* PC27 periph B */
+							 2 28 0x2 0x0	/* PC28 periph B */
+							 2 29 0x2 0x0	/* PC29 periph B */
+							 2 30 0x2 0x0	/* PC30 periph B */
+							 2 31 0x2 0x0>;	/* PC31 periph B */
+					};
+				};
+			};
+
+			macb1: ethernet@f8030000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_macb1_rmii>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/at91sam9x25ek.dts b/arch/arm/boot/dts/at91sam9x25ek.dts
new file mode 100644
index 0000000..af907ea
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9x25ek.dts
@@ -0,0 +1,16 @@
+/*
+ * at91sam9x25ek.dts - Device Tree file for AT91SAM9X25-EK board
+ *
+ *  Copyright (C) 2012 Atmel,
+ *                2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9x25.dtsi"
+/include/ "at91sam9x5ek.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9G25-EK";
+	compatible = "atmel,at91sam9x25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+};
diff --git a/arch/arm/boot/dts/at91sam9x35.dtsi b/arch/arm/boot/dts/at91sam9x35.dtsi
new file mode 100644
index 0000000..fb102d6
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9x35.dtsi
@@ -0,0 +1,28 @@
+/*
+ * at91sam9x35.dtsi - Device Tree Include file for AT91SAM9X35 SoC
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/include/ "at91sam9x5.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9X35 SoC";
+	compatible = "atmel, at91sam9x35, atmel,at91sam9x5";
+
+	ahb {
+		apb {
+			pinctrl@fffff400 {
+				atmel,mux-mask = <
+				      /*    A         B          C     */
+				       0xffffffff 0xffe03fff 0xc000000c  /* pioA */
+				       0x000406ff 0x00047e3f 0x00000000  /* pioB */
+				       0xfdffffff 0x00000000 0xb83fffff  /* pioC */
+				       0x003fffff 0x003f8000 0x00000000  /* pioD */
+				      >;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/at91sam9x35ek.dts b/arch/arm/boot/dts/at91sam9x35ek.dts
new file mode 100644
index 0000000..5ccb607
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9x35ek.dts
@@ -0,0 +1,16 @@
+/*
+ * at91sam9x35ek.dts - Device Tree file for AT91SAM9X35-EK board
+ *
+ *  Copyright (C) 2012 Atmel,
+ *                2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9x35.dtsi"
+/include/ "at91sam9x5ek.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9X35-EK";
+	compatible = "atmel,at91sam9x35ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+};
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index 03fc136..617ede5 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -30,6 +30,7 @@
 		i2c0 = &i2c0;
 		i2c1 = &i2c1;
 		i2c2 = &i2c2;
+		ssc0 = &ssc0;
 	};
 	cpus {
 		cpu@0 {
@@ -87,6 +88,13 @@
 				interrupts = <1 4 7>;
 			};
 
+			ssc0: ssc@f0010000 {
+				compatible = "atmel,at91sam9g45-ssc";
+				reg = <0xf0010000 0x4000>;
+				interrupts = <28 4 5>;
+				status = "disable";
+			};
+
 			tcb0: timer@f8008000 {
 				compatible = "atmel,at91sam9x5-tcb";
 				reg = <0xf8008000 0x100>;
@@ -111,50 +119,244 @@
 				interrupts = <21 4 0>;
 			};
 
-			pioA: gpio@fffff400 {
-				compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-				reg = <0xfffff400 0x100>;
-				interrupts = <2 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-			};
+			pinctrl@fffff400 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus";
+				ranges = <0xfffff400 0xfffff400 0x800>;
+
+				/* shared pinctrl settings */
+				dbgu {
+					pinctrl_dbgu: dbgu-0 {
+						atmel,pins =
+							<0 9 0x1 0x0	/* PA9 periph A */
+							 0 10 0x1 0x1>;	/* PA10 periph A with pullup */
+					};
+				};
 
-			pioB: gpio@fffff600 {
-				compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-				reg = <0xfffff600 0x100>;
-				interrupts = <2 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
+				usart0 {
+					pinctrl_usart0: usart0-0 {
+						atmel,pins =
+							<0 0 0x1 0x1	/* PA0 periph A with pullup */
+							 0 1 0x1 0x0>;	/* PA1 periph A */
+					};
+
+					pinctrl_usart0_rts: usart0_rts-0 {
+						atmel,pins =
+							<0 2 0x1 0x0>;	/* PA2 periph A */
+					};
+
+					pinctrl_usart0_cts: usart0_cts-0 {
+						atmel,pins =
+							<0 3 0x1 0x0>;	/* PA3 periph A */
+					};
+				};
+
+				usart1 {
+					pinctrl_usart1: usart1-0 {
+						atmel,pins =
+							<0 5 0x1 0x1	/* PA5 periph A with pullup */
+							 0 6 0x1 0x0>;	/* PA6 periph A */
+					};
+
+					pinctrl_usart1_rts: usart1_rts-0 {
+						atmel,pins =
+							<3 27 0x3 0x0>;	/* PC27 periph C */
+					};
+
+					pinctrl_usart1_cts: usart1_cts-0 {
+						atmel,pins =
+							<3 28 0x3 0x0>;	/* PC28 periph C */
+					};
+				};
+
+				usart2 {
+					pinctrl_usart2: usart2-0 {
+						atmel,pins =
+							<0 7 0x1 0x1	/* PA7 periph A with pullup */
+							 0 8 0x1 0x0>;	/* PA8 periph A */
+					};
+
+					pinctrl_uart2_rts: uart2_rts-0 {
+						atmel,pins =
+							<0 0 0x2 0x0>;	/* PB0 periph B */
+					};
+
+					pinctrl_uart2_cts: uart2_cts-0 {
+						atmel,pins =
+							<0 1 0x2 0x0>;	/* PB1 periph B */
+					};
+				};
+
+				usart3 {
+					pinctrl_uart3: usart3-0 {
+						atmel,pins =
+							<3 23 0x2 0x1	/* PC22 periph B with pullup */
+							 3 23 0x2 0x0>;	/* PC23 periph B */
+					};
+
+					pinctrl_usart3_rts: usart3_rts-0 {
+						atmel,pins =
+							<3 24 0x2 0x0>;	/* PC24 periph B */
+					};
+
+					pinctrl_usart3_cts: usart3_cts-0 {
+						atmel,pins =
+							<3 25 0x2 0x0>;	/* PC25 periph B */
+					};
+				};
+
+				uart0 {
+					pinctrl_uart0: uart0-0 {
+						atmel,pins =
+							<3 8 0x3 0x0	/* PC8 periph C */
+							 3 9 0x3 0x1>;	/* PC9 periph C with pullup */
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1: uart1-0 {
+						atmel,pins =
+							<3 16 0x3 0x0	/* PC16 periph C */
+							 3 17 0x3 0x1>;	/* PC17 periph C with pullup */
+					};
+				};
+
+				nand {
+					pinctrl_nand: nand-0 {
+						atmel,pins =
+							<3 4 0x0 0x1	/* PD5 gpio RDY pin pull_up */
+							 3 5 0x0 0x1>;	/* PD4 gpio enable pin pull_up */
+					};
+				};
+
+				macb0 {
+					pinctrl_macb0_rmii: macb0_rmii-0 {
+						atmel,pins =
+							<1 0 0x1 0x0	/* PB0 periph A */
+							 1 1 0x1 0x0	/* PB1 periph A */
+							 1 2 0x1 0x0	/* PB2 periph A */
+							 1 3 0x1 0x0	/* PB3 periph A */
+							 1 4 0x1 0x0	/* PB4 periph A */
+							 1 5 0x1 0x0	/* PB5 periph A */
+							 1 6 0x1 0x0	/* PB6 periph A */
+							 1 7 0x1 0x0	/* PB7 periph A */
+							 1 9 0x1 0x0	/* PB9 periph A */
+							 1 10 0x1 0x0>;	/* PB10 periph A */
+					};
+
+					pinctrl_macb0_rmii_mii: macb0_rmii_mii-0 {
+						atmel,pins =
+							<1 8 0x1 0x0	/* PA8 periph A */
+							 1 11 0x1 0x0	/* PA11 periph A */
+							 1 12 0x1 0x0	/* PA12 periph A */
+							 1 13 0x1 0x0	/* PA13 periph A */
+							 1 14 0x1 0x0	/* PA14 periph A */
+							 1 15 0x1 0x0	/* PA15 periph A */
+							 1 16 0x1 0x0	/* PA16 periph A */
+							 1 17 0x1 0x0>;	/* PA17 periph A */
+					};
+				};
+
+				mmc0 {
+					pinctrl_mmc0_slot0_clk_cmd_dat0: mmc0_slot0_clk_cmd_dat0-0 {
+						atmel,pins =
+							<0 17 0x1 0x0	/* PA17 periph A */
+							 0 16 0x1 0x1	/* PA16 periph A with pullup */
+							 0 15 0x1 0x1>;	/* PA15 periph A with pullup */
+					};
+
+					pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 {
+						atmel,pins =
+							<0 18 0x1 0x1	/* PA18 periph A with pullup */
+							 0 19 0x1 0x1	/* PA19 periph A with pullup */
+							 0 20 0x1 0x1>;	/* PA20 periph A with pullup */
+					};
+				};
+
+				mmc1 {
+					pinctrl_mmc1_slot0_clk_cmd_dat0: mmc1_slot0_clk_cmd_dat0-0 {
+						atmel,pins =
+							<0 13 0x2 0x0	/* PA13 periph B */
+							 0 12 0x2 0x1	/* PA12 periph B with pullup */
+							 0 11 0x2 0x1>;	/* PA11 periph B with pullup */
+					};
+
+					pinctrl_mmc1_slot0_dat1_3: mmc1_slot0_dat1_3-0 {
+						atmel,pins =
+							<0 2 0x2 0x1	/* PA2 periph B with pullup */
+							 0 3 0x2 0x1	/* PA3 periph B with pullup */
+							 0 4 0x2 0x1>;	/* PA4 periph B with pullup */
+					};
+				};
+
+				pioA: gpio@fffff400 {
+					compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+					reg = <0xfffff400 0x200>;
+					interrupts = <2 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioB: gpio@fffff600 {
+					compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+					reg = <0xfffff600 0x200>;
+					interrupts = <2 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					#gpio-lines = <19>;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioC: gpio@fffff800 {
+					compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+					reg = <0xfffff800 0x200>;
+					interrupts = <3 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
+
+				pioD: gpio@fffffa00 {
+					compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+					reg = <0xfffffa00 0x200>;
+					interrupts = <3 4 1>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					#gpio-lines = <22>;
+					interrupt-controller;
+					#interrupt-cells = <2>;
+				};
 			};
 
-			pioC: gpio@fffff800 {
-				compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-				reg = <0xfffff800 0x100>;
-				interrupts = <3 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
+			mmc0: mmc@f0008000 {
+				compatible = "atmel,hsmci";
+				reg = <0xf0008000 0x600>;
+				interrupts = <12 4 0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
 			};
 
-			pioD: gpio@fffffa00 {
-				compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
-				reg = <0xfffffa00 0x100>;
-				interrupts = <3 4 1>;
-				#gpio-cells = <2>;
-				gpio-controller;
-				interrupt-controller;
-				#interrupt-cells = <2>;
+			mmc1: mmc@f000c000 {
+				compatible = "atmel,hsmci";
+				reg = <0xf000c000 0x600>;
+				interrupts = <26 4 0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
 			};
 
 			dbgu: serial@fffff200 {
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xfffff200 0x200>;
 				interrupts = <1 4 7>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_dbgu>;
 				status = "disabled";
 			};
 
@@ -164,6 +366,8 @@
 				interrupts = <5 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart0>;
 				status = "disabled";
 			};
 
@@ -173,6 +377,8 @@
 				interrupts = <6 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart1>;
 				status = "disabled";
 			};
 
@@ -182,6 +388,8 @@
 				interrupts = <7 4 5>;
 				atmel,use-dma-rx;
 				atmel,use-dma-tx;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart2>;
 				status = "disabled";
 			};
 
@@ -189,6 +397,8 @@
 				compatible = "cdns,at32ap7000-macb", "cdns,macb";
 				reg = <0xf802c000 0x100>;
 				interrupts = <24 4 3>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_macb0_rmii>;
 				status = "disabled";
 			};
 
@@ -273,6 +483,8 @@
 			      >;
 			atmel,nand-addr-offset = <21>;
 			atmel,nand-cmd-offset = <22>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_nand>;
 			gpios = <&pioD 5 0
 				 &pioD 4 0
 				 0
diff --git a/arch/arm/boot/dts/at91sam9x5ek.dtsi b/arch/arm/boot/dts/at91sam9x5ek.dtsi
new file mode 100644
index 0000000..8a7cf1d
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9x5ek.dtsi
@@ -0,0 +1,101 @@
+/*
+ * at91sam9x5ek.dtsi - Device Tree file for AT91SAM9x5CM Base board
+ *
+ *  Copyright (C) 2012 Atmel,
+ *                2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/include/ "at91sam9x5cm.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9X5-EK";
+	compatible = "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+
+	chosen {
+		bootargs = "128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
+	};
+
+	ahb {
+		apb {
+			mmc0: mmc@f0008000 {
+				pinctrl-0 = <
+					&pinctrl_board_mmc0
+					&pinctrl_mmc0_slot0_clk_cmd_dat0
+					&pinctrl_mmc0_slot0_dat1_3>;
+				status = "okay";
+				slot@0 {
+					reg = <0>;
+					bus-width = <4>;
+					cd-gpios = <&pioD 15 0>;
+				};
+			};
+
+			mmc1: mmc@f000c000 {
+				pinctrl-0 = <
+					&pinctrl_board_mmc1
+					&pinctrl_mmc1_slot0_clk_cmd_dat0
+					&pinctrl_mmc1_slot0_dat1_3>;
+				status = "okay";
+				slot@0 {
+					reg = <0>;
+					bus-width = <4>;
+					cd-gpios = <&pioD 14 0>;
+				};
+			};
+
+			dbgu: serial@fffff200 {
+				status = "okay";
+			};
+
+			usart0: serial@f801c000 {
+				status = "okay";
+			};
+
+			macb0: ethernet@f802c000 {
+				phy-mode = "rmii";
+				status = "okay";
+			};
+
+			i2c0: i2c@f8010000 {
+				status = "okay";
+			};
+
+			i2c1: i2c@f8014000 {
+				status = "okay";
+			};
+
+			i2c2: i2c@f8018000 {
+				status = "okay";
+			};
+
+			pinctrl@fffff400 {
+				mmc0 {
+					pinctrl_board_mmc0: mmc0-board {
+						atmel,pins =
+							<3 15 0x0 0x5>;	/* PD15 gpio CD pin pull up and deglitch */
+					};
+				};
+
+				mmc1 {
+					pinctrl_board_mmc1: mmc1-board {
+						atmel,pins =
+							<3 14 0x0 0x5>;	/* PD14 gpio CD pin pull up and deglitch */
+					};
+				};
+			};
+		};
+
+		usb0: ohci@00600000 {
+			status = "okay";
+			num-ports = <2>;
+			atmel,vbus-gpio = <&pioD 19 1
+					   &pioD 20 1
+					  >;
+		};
+
+		usb1: ehci@00700000 {
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/bcm11351-brt.dts b/arch/arm/boot/dts/bcm11351-brt.dts
new file mode 100644
index 0000000..248067c
--- /dev/null
+++ b/arch/arm/boot/dts/bcm11351-brt.dts
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/dts-v1/;
+
+/include/ "bcm11351.dtsi"
+
+/ {
+	model = "BCM11351 BRT board";
+	compatible = "bcm,bcm11351-brt", "bcm,bcm11351";
+
+	memory {
+		reg = <0x80000000 0x40000000>; /* 1 GB */
+	};
+
+	uart@3e000000 {
+		status = "okay";
+	};
+
+};
diff --git a/arch/arm/boot/dts/bcm11351.dtsi b/arch/arm/boot/dts/bcm11351.dtsi
new file mode 100644
index 0000000..ad13588
--- /dev/null
+++ b/arch/arm/boot/dts/bcm11351.dtsi
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 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/ "skeleton.dtsi"
+
+/ {
+	model = "BCM11351 SoC";
+	compatible = "bcm,bcm11351";
+	interrupt-parent = <&gic>;
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	gic: interrupt-controller@3ff00100 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+		interrupt-controller;
+		reg = <0x3ff01000 0x1000>,
+		      <0x3ff00100 0x100>;
+	};
+
+	uart@3e000000 {
+		compatible = "bcm,bcm11351-dw-apb-uart", "snps,dw-apb-uart";
+		status = "disabled";
+		reg = <0x3e000000 0x1000>;
+		clock-frequency = <13000000>;
+		interrupts = <0x0 67 0x4>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+	};
+
+	L2: l2-cache {
+		    compatible = "arm,pl310-cache";
+		    reg = <0x3ff20000 0x1000>;
+		    cache-unified;
+		    cache-level = <2>;
+	};
+};
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts
index 7dd860f..9b72054 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts
@@ -10,3 +10,18 @@
 		reg = <0 0x10000000>;
 	};
 };
+
+&gpio {
+	pinctrl-names = "default";
+	pinctrl-0 = <&alt0 &alt3>;
+
+	alt0: alt0 {
+		brcm,pins = <0 1 2 3 4 5 6 7 8 9 10 11 14 15 40 45>;
+		brcm,function = <4>; /* alt0 */
+	};
+
+	alt3: alt3 {
+		brcm,pins = <48 49 50 51 52 53>;
+		brcm,function = <7>; /* alt3 */
+	};
+};
diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
index 0b61939..8917550 100644
--- a/arch/arm/boot/dts/bcm2835.dtsi
+++ b/arch/arm/boot/dts/bcm2835.dtsi
@@ -29,11 +29,39 @@
 			#interrupt-cells = <2>;
 		};
 
+		watchdog {
+			compatible = "brcm,bcm2835-pm-wdt";
+			reg = <0x7e100000 0x28>;
+		};
+
 		uart@20201000 {
 			compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
 			reg = <0x7e201000 0x1000>;
 			interrupts = <2 25>;
 			clock-frequency = <3000000>;
 		};
+
+		gpio: gpio {
+			compatible = "brcm,bcm2835-gpio";
+			reg = <0x7e200000 0xb4>;
+			/*
+			 * The GPIO IP block is designed for 3 banks of GPIOs.
+			 * Each bank has a GPIO interrupt for itself.
+			 * There is an overall "any bank" interrupt.
+			 * In order, these are GIC interrupts 17, 18, 19, 20.
+			 * Since the BCM2835 only has 2 banks, the 2nd bank
+			 * interrupt output appears to be mirrored onto the
+			 * 3rd bank's interrupt signal.
+			 * So, a bank0 interrupt shows up on 17, 20, and
+			 * a bank1 interrupt shows up on 18, 19, 20!
+			 */
+			interrupts = <2 17>, <2 18>, <2 19>, <2 20>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/ccu9540.dts b/arch/arm/boot/dts/ccu9540.dts
new file mode 100644
index 0000000..0430546
--- /dev/null
+++ b/arch/arm/boot/dts/ccu9540.dts
@@ -0,0 +1,72 @@
+/*
+ * 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/ "dbx5x0.dtsi"
+
+/ {
+	model = "ST-Ericsson CCU9540 platform with Device Tree";
+	compatible = "st-ericsson,ccu9540", "st-ericsson,u9540";
+
+	memory {
+		reg = <0x00000000 0x20000000>;
+	};
+
+	soc-u9500 {
+		uart@80120000 {
+			status = "okay";
+		};
+
+		uart@80121000 {
+			status = "okay";
+		};
+
+		uart@80007000 {
+			status = "okay";
+		};
+
+		// 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  = <&gpio7 6 0x4>; // 230
+			cd-inverted;
+
+			status = "okay";
+		};
+
+
+		// WLAN SDIO channel
+		sdi1_per2@80118000 {
+			arm,primecell-periphid = <0x10480180>;
+			max-frequency = <50000000>;
+			bus-width = <4>;
+
+			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/cros5250-common.dtsi b/arch/arm/boot/dts/cros5250-common.dtsi
new file mode 100644
index 0000000..fddd174
--- /dev/null
+++ b/arch/arm/boot/dts/cros5250-common.dtsi
@@ -0,0 +1,184 @@
+/*
+ * Common device tree include for all Exynos 5250 boards based off of Daisy.
+ *
+ * Copyright (c) 2012 Google, 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.
+*/
+
+/ {
+	aliases {
+	};
+
+	memory {
+		reg = <0x40000000 0x80000000>;
+	};
+
+	chosen {
+	};
+
+	i2c@12C60000 {
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <378000>;
+		gpios = <&gpb3 0 2 3 0>,
+			<&gpb3 1 2 3 0>;
+	};
+
+	i2c@12C70000 {
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <378000>;
+		gpios = <&gpb3 2 2 3 0>,
+			<&gpb3 3 2 3 0>;
+	};
+
+	i2c@12C80000 {
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <66000>;
+
+		/*
+		 * Disabled pullups since external part has its own pullups and
+		 * double-pulling gets us out of spec in some cases.
+		 */
+		gpios = <&gpa0 6 3 0 0>,
+			<&gpa0 7 3 0 0>;
+
+		hdmiddc@50 {
+			compatible = "samsung,exynos5-hdmiddc";
+			reg = <0x50>;
+		};
+	};
+
+	i2c@12C90000 {
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <66000>;
+		gpios = <&gpa1 2 3 3 0>,
+			<&gpa1 3 3 3 0>;
+	};
+
+	i2c@12CA0000 {
+		status = "disabled";
+	};
+
+	i2c@12CB0000 {
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <66000>;
+		gpios = <&gpa2 2 3 3 0>,
+			<&gpa2 3 3 3 0>;
+	};
+
+	i2c@12CC0000 {
+		status = "disabled";
+	};
+
+	i2c@12CD0000 {
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <66000>;
+		gpios = <&gpb2 2 3 3 0>,
+			<&gpb2 3 3 3 0>;
+	};
+
+	i2c@12CE0000 {
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <378000>;
+
+		hdmiphy@38 {
+			compatible = "samsung,exynos5-hdmiphy";
+			reg = <0x38>;
+		};
+	};
+
+	dwmmc0@12200000 {
+		num-slots = <1>;
+		supports-highspeed;
+		broken-cd;
+		fifo-depth = <0x80>;
+		card-detect-delay = <200>;
+		samsung,dw-mshc-ciu-div = <3>;
+		samsung,dw-mshc-sdr-timing = <2 3 3>;
+		samsung,dw-mshc-ddr-timing = <1 2 3>;
+
+		slot@0 {
+			reg = <0>;
+			bus-width = <8>;
+			gpios = <&gpc0 0 2 0 3>, <&gpc0 1 2 0 3>,
+				<&gpc1 0 2 3 3>, <&gpc1 1 2 3 3>,
+				<&gpc1 2 2 3 3>, <&gpc1 3 2 3 3>,
+				<&gpc0 3 2 3 3>, <&gpc0 4 2 3 3>,
+				<&gpc0 5 2 3 3>, <&gpc0 6 2 3 3>;
+		};
+	};
+
+	dwmmc1@12210000 {
+		status = "disabled";
+	};
+
+	dwmmc2@12220000 {
+		num-slots = <1>;
+		supports-highspeed;
+		fifo-depth = <0x80>;
+		card-detect-delay = <200>;
+		samsung,dw-mshc-ciu-div = <3>;
+		samsung,dw-mshc-sdr-timing = <2 3 3>;
+		samsung,dw-mshc-ddr-timing = <1 2 3>;
+
+		slot@0 {
+			reg = <0>;
+			bus-width = <4>;
+			samsung,cd-pinmux-gpio = <&gpc3 2 2 3 3>;
+			wp-gpios = <&gpc2 1 0 0 3>;
+			gpios = <&gpc3 0 2 0 3>, <&gpc3 1 2 0 3>,
+				<&gpc3 3 2 3 3>, <&gpc3 4 2 3 3>,
+				<&gpc3 5 2 3 3>, <&gpc3 6 2 3 3>;
+		};
+	};
+
+	dwmmc3@12230000 {
+		num-slots = <1>;
+		supports-highspeed;
+		broken-cd;
+		fifo-depth = <0x80>;
+		card-detect-delay = <200>;
+		samsung,dw-mshc-ciu-div = <3>;
+		samsung,dw-mshc-sdr-timing = <2 3 3>;
+		samsung,dw-mshc-ddr-timing = <1 2 3>;
+
+		slot@0 {
+			reg = <0>;
+			bus-width = <4>;
+			/* See board-specific dts files for GPIOs */
+		};
+	};
+
+	spi_0: spi@12d20000 {
+		status = "disabled";
+	};
+
+	spi_1: spi@12d30000 {
+		gpios = <&gpa2 4 2 3 0>,
+			<&gpa2 6 2 3 0>,
+			<&gpa2 7 2 3 0>;
+		samsung,spi-src-clk = <0>;
+		num-cs = <1>;
+	};
+
+	spi_2: spi@12d40000 {
+		status = "disabled";
+	};
+
+	hdmi {
+		hpd-gpio = <&gpx3 7 0xf 1 3>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power {
+			label = "Power";
+			gpios = <&gpx1 3 0 0x10000 0>;
+			linux,code = <116>; /* KEY_POWER */
+			gpio-key,wakeup;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/da850-enbw-cmc.dts b/arch/arm/boot/dts/da850-enbw-cmc.dts
new file mode 100644
index 0000000..422fdb3
--- /dev/null
+++ b/arch/arm/boot/dts/da850-enbw-cmc.dts
@@ -0,0 +1,30 @@
+/*
+ * Device Tree for AM1808 EnBW CMC board
+ *
+ * Copyright 2012 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.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.
+ */
+/dts-v1/;
+/include/ "da850.dtsi"
+
+/ {
+	compatible = "enbw,cmc", "ti,da850";
+	model = "EnBW CMC";
+
+	soc {
+		serial0: serial@1c42000 {
+			status = "okay";
+		};
+		serial1: serial@1d0c000 {
+			status = "okay";
+		};
+		serial2: serial@1d0d000 {
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.dts
new file mode 100644
index 0000000..37dc5a3
--- /dev/null
+++ b/arch/arm/boot/dts/da850-evm.dts
@@ -0,0 +1,28 @@
+/*
+ * Device Tree for DA850 EVM board
+ *
+ * Copyright (C) 2012 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.
+ */
+/dts-v1/;
+/include/ "da850.dtsi"
+
+/ {
+	compatible = "ti,da850-evm", "ti,da850";
+	model = "DA850/AM1808/OMAP-L138 EVM";
+
+	soc {
+		serial0: serial@1c42000 {
+			status = "okay";
+		};
+		serial1: serial@1d0c000 {
+			status = "okay";
+		};
+		serial2: serial@1d0d000 {
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
new file mode 100644
index 0000000..640ab75
--- /dev/null
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.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/ "skeleton.dtsi"
+
+/ {
+	arm {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		intc: interrupt-controller {
+			compatible = "ti,cp-intc";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			ti,intc-size = <100>;
+			reg = <0xfffee000 0x2000>;
+		};
+	};
+	soc {
+		compatible = "simple-bus";
+		model = "da850";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x0 0x01c00000 0x400000>;
+
+		serial0: serial@1c42000 {
+			compatible = "ns16550a";
+			reg = <0x42000 0x100>;
+			clock-frequency = <150000000>;
+			reg-shift = <2>;
+			interrupts = <25>;
+			interrupt-parent = <&intc>;
+			status = "disabled";
+		};
+		serial1: serial@1d0c000 {
+			compatible = "ns16550a";
+			reg = <0x10c000 0x100>;
+			clock-frequency = <150000000>;
+			reg-shift = <2>;
+			interrupts = <53>;
+			interrupt-parent = <&intc>;
+			status = "disabled";
+		};
+		serial2: serial@1d0d000 {
+			compatible = "ns16550a";
+			reg = <0x10d000 0x100>;
+			clock-frequency = <150000000>;
+			reg-shift = <2>;
+			interrupts = <61>;
+			interrupt-parent = <&intc>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi
index 4b0e0ca..2efd9c8 100644
--- a/arch/arm/boot/dts/dbx5x0.dtsi
+++ b/arch/arm/boot/dts/dbx5x0.dtsi
@@ -203,129 +203,117 @@
 				reg = <0x80157450 0xC>;
 			};
 
+			thermal@801573c0 {
+				compatible = "stericsson,db8500-thermal";
+				reg = <0x801573c0 0x40>;
+				interrupts = <21 0x4>, <22 0x4>;
+				interrupt-names = "IRQ_HOTMON_LOW", "IRQ_HOTMON_HIGH";
+				status = "disabled";
+			 };
+
 			db8500-prcmu-regulators {
 				compatible = "stericsson,db8500-prcmu-regulator";
 
 				// DB8500_REGULATOR_VAPE
 				db8500_vape_reg: db8500_vape {
 					regulator-compatible = "db8500_vape";
-					regulator-name = "db8500-vape";
 					regulator-always-on;
 				};
 
 				// DB8500_REGULATOR_VARM
 				db8500_varm_reg: db8500_varm {
 					regulator-compatible = "db8500_varm";
-					regulator-name = "db8500-varm";
 				};
 
 				// DB8500_REGULATOR_VMODEM
 				db8500_vmodem_reg: db8500_vmodem {
 					regulator-compatible = "db8500_vmodem";
-					regulator-name = "db8500-vmodem";
 				};
 
 				// DB8500_REGULATOR_VPLL
 				db8500_vpll_reg: db8500_vpll {
 					regulator-compatible = "db8500_vpll";
-					regulator-name = "db8500-vpll";
 				};
 
 				// DB8500_REGULATOR_VSMPS1
 				db8500_vsmps1_reg: db8500_vsmps1 {
 					regulator-compatible = "db8500_vsmps1";
-					regulator-name = "db8500-vsmps1";
 				};
 
 				// DB8500_REGULATOR_VSMPS2
 				db8500_vsmps2_reg: db8500_vsmps2 {
 					regulator-compatible = "db8500_vsmps2";
-					regulator-name = "db8500-vsmps2";
 				};
 
 				// DB8500_REGULATOR_VSMPS3
 				db8500_vsmps3_reg: db8500_vsmps3 {
 					regulator-compatible = "db8500_vsmps3";
-					regulator-name = "db8500-vsmps3";
 				};
 
 				// DB8500_REGULATOR_VRF1
 				db8500_vrf1_reg: db8500_vrf1 {
 					regulator-compatible = "db8500_vrf1";
-					regulator-name = "db8500-vrf1";
 				};
 
 				// DB8500_REGULATOR_SWITCH_SVAMMDSP
 				db8500_sva_mmdsp_reg: db8500_sva_mmdsp {
 					regulator-compatible = "db8500_sva_mmdsp";
-					regulator-name = "db8500-sva-mmdsp";
 				};
 
 				// DB8500_REGULATOR_SWITCH_SVAMMDSPRET
 				db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret {
 					regulator-compatible = "db8500_sva_mmdsp_ret";
-					regulator-name = "db8500-sva-mmdsp-ret";
 				};
 
 				// DB8500_REGULATOR_SWITCH_SVAPIPE
 				db8500_sva_pipe_reg: db8500_sva_pipe {
 					regulator-compatible = "db8500_sva_pipe";
-					regulator-name = "db8500_sva_pipe";
 				};
 
 				// DB8500_REGULATOR_SWITCH_SIAMMDSP
 				db8500_sia_mmdsp_reg: db8500_sia_mmdsp {
 					regulator-compatible = "db8500_sia_mmdsp";
-					regulator-name = "db8500_sia_mmdsp";
 				};
 
 				// DB8500_REGULATOR_SWITCH_SIAMMDSPRET
 				db8500_sia_mmdsp_ret_reg: db8500_sia_mmdsp_ret {
-					regulator-name = "db8500-sia-mmdsp-ret";
 				};
 
 				// DB8500_REGULATOR_SWITCH_SIAPIPE
 				db8500_sia_pipe_reg: db8500_sia_pipe {
 					regulator-compatible = "db8500_sia_pipe";
-					regulator-name = "db8500-sia-pipe";
 				};
 
 				// DB8500_REGULATOR_SWITCH_SGA
 				db8500_sga_reg: db8500_sga {
 					regulator-compatible = "db8500_sga";
-					regulator-name = "db8500-sga";
 					vin-supply = <&db8500_vape_reg>;
 				};
 
 				// DB8500_REGULATOR_SWITCH_B2R2_MCDE
 				db8500_b2r2_mcde_reg: db8500_b2r2_mcde {
 					regulator-compatible = "db8500_b2r2_mcde";
-					regulator-name = "db8500-b2r2-mcde";
 					vin-supply = <&db8500_vape_reg>;
 				};
 
 				// DB8500_REGULATOR_SWITCH_ESRAM12
 				db8500_esram12_reg: db8500_esram12 {
 					regulator-compatible = "db8500_esram12";
-					regulator-name = "db8500-esram12";
 				};
 
 				// DB8500_REGULATOR_SWITCH_ESRAM12RET
 				db8500_esram12_ret_reg: db8500_esram12_ret {
 					regulator-compatible = "db8500_esram12_ret";
-					regulator-name = "db8500-esram12-ret";
 				};
 
 				// DB8500_REGULATOR_SWITCH_ESRAM34
 				db8500_esram34_reg: db8500_esram34 {
 					regulator-compatible = "db8500_esram34";
-					regulator-name = "db8500-esram34";
 				};
 
 				// DB8500_REGULATOR_SWITCH_ESRAM34RET
 				db8500_esram34_ret_reg: db8500_esram34_ret {
 					regulator-compatible = "db8500_esram34_ret";
-					regulator-name = "db8500-esram34-ret";
 				};
 			};
 
@@ -352,7 +340,33 @@
 					vddadc-supply = <&ab8500_ldo_tvout_reg>;
 				};
 
-				ab8500-usb {
+				ab8500_battery: ab8500_battery {
+					stericsson,battery-type = "LIPO";
+					thermistor-on-batctrl;
+				};
+
+				ab8500_fg {
+					compatible = "stericsson,ab8500-fg";
+					battery	   = <&ab8500_battery>;
+				};
+
+				ab8500_btemp {
+					compatible = "stericsson,ab8500-btemp";
+					battery	   = <&ab8500_battery>;
+				};
+
+				ab8500_charger {
+					compatible	= "stericsson,ab8500-charger";
+					battery		= <&ab8500_battery>;
+					vddadc-supply	= <&ab8500_ldo_tvout_reg>;
+				};
+
+				ab8500_chargalg {
+					compatible	= "stericsson,ab8500-chargalg";
+					battery		= <&ab8500_battery>;
+				};
+
+				ab8500_usb {
 					compatible = "stericsson,ab8500-usb";
 					interrupts = < 90 0x4
 						       96 0x4
@@ -404,7 +418,6 @@
 					// supplies to the display/camera
 					ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
 						regulator-compatible = "ab8500_ldo_aux1";
-						regulator-name = "V-DISPLAY";
 						regulator-min-microvolt = <2500000>;
 						regulator-max-microvolt = <2900000>;
 						regulator-boot-on;
@@ -415,7 +428,6 @@
 					// supplies to the on-board eMMC
 					ab8500_ldo_aux2_reg: ab8500_ldo_aux2 {
 						regulator-compatible = "ab8500_ldo_aux2";
-						regulator-name = "V-eMMC1";
 						regulator-min-microvolt = <1100000>;
 						regulator-max-microvolt = <3300000>;
 					};
@@ -423,7 +435,6 @@
 					// supply for VAUX3; SDcard slots
 					ab8500_ldo_aux3_reg: ab8500_ldo_aux3 {
 						regulator-compatible = "ab8500_ldo_aux3";
-						regulator-name = "V-MMC-SD";
 						regulator-min-microvolt = <1100000>;
 						regulator-max-microvolt = <3300000>;
 					};
@@ -431,49 +442,41 @@
 					// supply for v-intcore12; VINTCORE12 LDO
 					ab8500_ldo_initcore_reg: ab8500_ldo_initcore {
 						regulator-compatible = "ab8500_ldo_initcore";
-						regulator-name = "V-INTCORE";
 					};
 
 					// supply for tvout; gpadc; TVOUT LDO
 					ab8500_ldo_tvout_reg: ab8500_ldo_tvout {
 						regulator-compatible = "ab8500_ldo_tvout";
-						regulator-name = "V-TVOUT";
 					};
 
 					// supply for ab8500-usb; USB LDO
 					ab8500_ldo_usb_reg: ab8500_ldo_usb {
 						regulator-compatible = "ab8500_ldo_usb";
-						regulator-name = "dummy";
 					};
 
 					// supply for ab8500-vaudio; VAUDIO LDO
 					ab8500_ldo_audio_reg: ab8500_ldo_audio {
 						regulator-compatible = "ab8500_ldo_audio";
-						regulator-name = "V-AUD";
 					};
 
 					// supply for v-anamic1 VAMic1-LDO
 					ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 {
 						regulator-compatible = "ab8500_ldo_anamic1";
-						regulator-name = "V-AMIC1";
 					};
 
 					// supply for v-amic2; VAMIC2 LDO; reuse constants for AMIC1
 					ab8500_ldo_amamic2_reg: ab8500_ldo_amamic2 {
 						regulator-compatible = "ab8500_ldo_amamic2";
-						regulator-name = "V-AMIC2";
 					};
 
 					// supply for v-dmic; VDMIC LDO
 					ab8500_ldo_dmic_reg: ab8500_ldo_dmic {
 						regulator-compatible = "ab8500_ldo_dmic";
-						regulator-name = "V-DMIC";
 					};
 
 					// supply for U8500 CSI/DSI; VANA LDO
 					ab8500_ldo_ana_reg: ab8500_ldo_ana {
 						regulator-compatible = "ab8500_ldo_ana";
-						regulator-name = "V-CSI/DSI";
 					};
 				};
 			};
@@ -577,42 +580,42 @@
 			status = "disabled";
 		};
 
-		sdi@80126000 {
+		sdi0_per1@80126000 {
 			compatible = "arm,pl18x", "arm,primecell";
 			reg = <0x80126000 0x1000>;
 			interrupts = <0 60 0x4>;
 			status = "disabled";
 		};
 
-		sdi@80118000 {
+		sdi1_per2@80118000 {
 			compatible = "arm,pl18x", "arm,primecell";
 			reg = <0x80118000 0x1000>;
 			interrupts = <0 50 0x4>;
 			status = "disabled";
 		};
 
-		sdi@80005000 {
+		sdi2_per3@80005000 {
 			compatible = "arm,pl18x", "arm,primecell";
 			reg = <0x80005000 0x1000>;
 			interrupts = <0 41 0x4>;
 			status = "disabled";
 		};
 
-		sdi@80119000 {
+		sdi3_per2@80119000 {
 			compatible = "arm,pl18x", "arm,primecell";
 			reg = <0x80119000 0x1000>;
 			interrupts = <0 59 0x4>;
 			status = "disabled";
 		};
 
-		sdi@80114000 {
+		sdi4_per2@80114000 {
 			compatible = "arm,pl18x", "arm,primecell";
 			reg = <0x80114000 0x1000>;
 			interrupts = <0 99 0x4>;
 			status = "disabled";
 		};
 
-		sdi@80008000 {
+		sdi5_per3@80008000 {
 			compatible = "arm,pl18x", "arm,primecell";
 			reg = <0x80008000 0x1000>;
 			interrupts = <0 100 0x4>;
@@ -660,5 +663,24 @@
 			ranges = <0 0x50000000 0x4000000>;
 			status = "disabled";
 		};
+
+		cpufreq-cooling {
+			compatible = "stericsson,db8500-cpufreq-cooling";
+			status = "disabled";
+		 };
+
+		vmmci: regulator-gpio {
+			compatible = "regulator-gpio";
+
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2600000>;
+			regulator-name = "mmci-reg";
+			regulator-type = "voltage";
+
+			states = <1800000 0x1
+				  2900000 0x0>;
+
+			status = "disabled";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/dove-cubox.dts b/arch/arm/boot/dts/dove-cubox.dts
index 0adbd5a..fed7d3f 100644
--- a/arch/arm/boot/dts/dove-cubox.dts
+++ b/arch/arm/boot/dts/dove-cubox.dts
@@ -40,3 +40,13 @@
 		reg = <0>;
 	};
 };
+
+&pinctrl {
+	pinctrl-0 = <&pmx_gpio_18>;
+	pinctrl-names = "default";
+
+	pmx_gpio_18: pmx-gpio-18 {
+		marvell,pins = "mpp18";
+		marvell,function = "gpio";
+	};
+};
diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
index 5a00022..61f3914 100644
--- a/arch/arm/boot/dts/dove.dtsi
+++ b/arch/arm/boot/dts/dove.dtsi
@@ -4,6 +4,12 @@
 	compatible = "marvell,dove";
 	model = "Marvell Armada 88AP510 SoC";
 
+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+		gpio2 = &gpio2;
+	};
+
 	soc@f1000000 {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -72,7 +78,8 @@
 			#gpio-cells = <2>;
 			gpio-controller;
 			reg = <0xd0400 0x20>;
-			ngpio = <32>;
+			ngpios = <32>;
+			interrupt-controller;
 			interrupts = <12>, <13>, <14>, <60>;
 		};
 
@@ -81,7 +88,8 @@
 			#gpio-cells = <2>;
 			gpio-controller;
 			reg = <0xd0420 0x20>;
-			ngpio = <32>;
+			ngpios = <32>;
+			interrupt-controller;
 			interrupts = <61>;
 		};
 
@@ -90,7 +98,12 @@
 			#gpio-cells = <2>;
 			gpio-controller;
 			reg = <0xe8400 0x0c>;
-			ngpio = <8>;
+			ngpios = <8>;
+		};
+
+		pinctrl: pinctrl@d0200 {
+			compatible = "marvell,dove-pinctrl";
+			reg = <0xd0200 0x10>;
 		};
 
 		spi0: spi@10600 {
diff --git a/arch/arm/boot/dts/ecx-2000.dts b/arch/arm/boot/dts/ecx-2000.dts
new file mode 100644
index 0000000..46477ac
--- /dev/null
+++ b/arch/arm/boot/dts/ecx-2000.dts
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2011-2012 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/dts-v1/;
+
+/* First 4KB has pen for secondary cores. */
+/memreserve/ 0x00000000 0x0001000;
+
+/ {
+	model = "Calxeda ECX-2000";
+	compatible = "calxeda,ecx-2000";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	clock-ranges;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a15";
+			reg = <0>;
+			clocks = <&a9pll>;
+			clock-names = "cpu";
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a15";
+			reg = <1>;
+			clocks = <&a9pll>;
+			clock-names = "cpu";
+		};
+
+		cpu@2 {
+			compatible = "arm,cortex-a15";
+			reg = <2>;
+			clocks = <&a9pll>;
+			clock-names = "cpu";
+		};
+
+		cpu@3 {
+			compatible = "arm,cortex-a15";
+			reg = <3>;
+			clocks = <&a9pll>;
+			clock-names = "cpu";
+		};
+	};
+
+	memory@0 {
+		name = "memory";
+		device_type = "memory";
+		reg = <0x00000000 0x00000000 0x00000000 0xff800000>;
+	};
+
+	memory@200000000 {
+		name = "memory";
+		device_type = "memory";
+		reg = <0x00000002 0x00000000 0x00000003 0x00000000>;
+	};
+
+	soc {
+		ranges = <0x00000000 0x00000000 0x00000000 0xffffffff>;
+
+		timer {
+			compatible = "arm,cortex-a15-timer", "arm,armv7-timer"; 			interrupts = <1 13 0xf08>,
+				<1 14 0xf08>,
+				<1 11 0xf08>,
+				<1 10 0xf08>;
+		};
+
+		intc: interrupt-controller@fff11000 {
+			compatible = "arm,cortex-a15-gic";
+			#interrupt-cells = <3>;
+			#size-cells = <0>;
+			#address-cells = <1>;
+			interrupt-controller;
+			interrupts = <1 9 0xf04>;
+			reg = <0xfff11000 0x1000>,
+			      <0xfff12000 0x1000>,
+			      <0xfff14000 0x2000>,
+			      <0xfff16000 0x2000>;
+		};
+
+		pmu {
+			compatible = "arm,cortex-a9-pmu";
+			interrupts = <0 76 4  0 75 4  0 74 4  0 73 4>;
+		};
+	};
+};
+
+/include/ "ecx-common.dtsi"
diff --git a/arch/arm/boot/dts/ecx-common.dtsi b/arch/arm/boot/dts/ecx-common.dtsi
new file mode 100644
index 0000000..d61b535
--- /dev/null
+++ b/arch/arm/boot/dts/ecx-common.dtsi
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2011-2012 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/>.
+ */
+
+/ {
+	chosen {
+		bootargs = "console=ttyAMA0";
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&intc>;
+
+		sata@ffe08000 {
+			compatible = "calxeda,hb-ahci";
+			reg = <0xffe08000 0x10000>;
+			interrupts = <0 83 4>;
+			dma-coherent;
+			calxeda,port-phys = <&combophy5 0 &combophy0 0
+					     &combophy0 1 &combophy0 2
+					     &combophy0 3>;
+		};
+
+		sdhci@ffe0e000 {
+			compatible = "calxeda,hb-sdhci";
+			reg = <0xffe0e000 0x1000>;
+			interrupts = <0 90 4>;
+			clocks = <&eclk>;
+			status = "disabled";
+		};
+
+		memory-controller@fff00000 {
+			compatible = "calxeda,hb-ddr-ctrl";
+			reg = <0xfff00000 0x1000>;
+			interrupts = <0 91 4>;
+		};
+
+		ipc@fff20000 {
+			compatible = "arm,pl320", "arm,primecell";
+			reg = <0xfff20000 0x1000>;
+			interrupts = <0 7 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+		};
+
+		gpioe: gpio@fff30000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0xfff30000 0x1000>;
+			interrupts = <0 14 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		gpiof: gpio@fff31000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0xfff31000 0x1000>;
+			interrupts = <0 15 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		gpiog: gpio@fff32000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0xfff32000 0x1000>;
+			interrupts = <0 16 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		gpioh: gpio@fff33000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0xfff33000 0x1000>;
+			interrupts = <0 17 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		timer@fff34000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0xfff34000 0x1000>;
+			interrupts = <0 18 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+		};
+
+		rtc@fff35000 {
+			compatible = "arm,pl031", "arm,primecell";
+			reg = <0xfff35000 0x1000>;
+			interrupts = <0 19 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+		};
+
+		serial@fff36000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0xfff36000 0x1000>;
+			interrupts = <0 20 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+		};
+
+		smic@fff3a000 {
+			compatible = "ipmi-smic";
+			device_type = "ipmi";
+			reg = <0xfff3a000 0x1000>;
+			interrupts = <0 24 4>;
+			reg-size = <4>;
+			reg-spacing = <4>;
+		};
+
+		sregs@fff3c000 {
+			compatible = "calxeda,hb-sregs";
+			reg = <0xfff3c000 0x1000>;
+
+			clocks {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				osc: oscillator {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+					clock-frequency = <33333000>;
+				};
+
+				ddrpll: ddrpll {
+					#clock-cells = <0>;
+					compatible = "calxeda,hb-pll-clock";
+					clocks = <&osc>;
+					reg = <0x108>;
+				};
+
+				a9pll: a9pll {
+					#clock-cells = <0>;
+					compatible = "calxeda,hb-pll-clock";
+					clocks = <&osc>;
+					reg = <0x100>;
+				};
+
+				a9periphclk: a9periphclk {
+					#clock-cells = <0>;
+					compatible = "calxeda,hb-a9periph-clock";
+					clocks = <&a9pll>;
+					reg = <0x104>;
+				};
+
+				a9bclk: a9bclk {
+					#clock-cells = <0>;
+					compatible = "calxeda,hb-a9bus-clock";
+					clocks = <&a9pll>;
+					reg = <0x104>;
+				};
+
+				emmcpll: emmcpll {
+					#clock-cells = <0>;
+					compatible = "calxeda,hb-pll-clock";
+					clocks = <&osc>;
+					reg = <0x10C>;
+				};
+
+				eclk: eclk {
+					#clock-cells = <0>;
+					compatible = "calxeda,hb-emmc-clock";
+					clocks = <&emmcpll>;
+					reg = <0x114>;
+				};
+
+				pclk: pclk {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+					clock-frequency = <150000000>;
+				};
+			};
+		};
+
+		dma@fff3d000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0xfff3d000 0x1000>;
+			interrupts = <0 92 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+		};
+
+		ethernet@fff50000 {
+			compatible = "calxeda,hb-xgmac";
+			reg = <0xfff50000 0x1000>;
+			interrupts = <0 77 4  0 78 4  0 79 4>;
+			dma-coherent;
+		};
+
+		ethernet@fff51000 {
+			compatible = "calxeda,hb-xgmac";
+			reg = <0xfff51000 0x1000>;
+			interrupts = <0 80 4  0 81 4  0 82 4>;
+			dma-coherent;
+		};
+
+		combophy0: combo-phy@fff58000 {
+			compatible = "calxeda,hb-combophy";
+			#phy-cells = <1>;
+			reg = <0xfff58000 0x1000>;
+			phydev = <5>;
+		};
+
+		combophy5: combo-phy@fff5d000 {
+			compatible = "calxeda,hb-combophy";
+			#phy-cells = <1>;
+			reg = <0xfff5d000 0x1000>;
+			phydev = <31>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/evk-pro3.dts b/arch/arm/boot/dts/evk-pro3.dts
index b7354e6..96e50f5 100644
--- a/arch/arm/boot/dts/evk-pro3.dts
+++ b/arch/arm/boot/dts/evk-pro3.dts
@@ -22,10 +22,22 @@
 				status = "okay";
 			};
 
+			usart0: serial@fffb0000 {
+				status = "okay";
+			};
+
+			usart2: serial@fffb8000 {
+				status = "okay";
+			};
+
 			usb1: gadget@fffa4000 {
 				atmel,vbus-gpio = <&pioC 5 0>;
 				status = "okay";
 			};
+
+			watchdog@fffffd40 {
+				status = "okay";
+			};
 		};
 
 		usb0: ohci@00500000 {
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index a26c3dd..e1347fc 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -28,6 +28,44 @@
 		spi0 = &spi_0;
 		spi1 = &spi_1;
 		spi2 = &spi_2;
+		i2c0 = &i2c_0;
+		i2c1 = &i2c_1;
+		i2c2 = &i2c_2;
+		i2c3 = &i2c_3;
+		i2c4 = &i2c_4;
+		i2c5 = &i2c_5;
+		i2c6 = &i2c_6;
+		i2c7 = &i2c_7;
+	};
+
+	pd_mfc: mfc-power-domain@10023C40 {
+		compatible = "samsung,exynos4210-pd";
+		reg = <0x10023C40 0x20>;
+	};
+
+	pd_g3d: g3d-power-domain@10023C60 {
+		compatible = "samsung,exynos4210-pd";
+		reg = <0x10023C60 0x20>;
+	};
+
+	pd_lcd0: lcd0-power-domain@10023C80 {
+		compatible = "samsung,exynos4210-pd";
+		reg = <0x10023C80 0x20>;
+	};
+
+	pd_tv: tv-power-domain@10023C20 {
+		compatible = "samsung,exynos4210-pd";
+		reg = <0x10023C20 0x20>;
+	};
+
+	pd_cam: cam-power-domain@10023C00 {
+		compatible = "samsung,exynos4210-pd";
+		reg = <0x10023C00 0x20>;
+	};
+
+	pd_gps: gps-power-domain@10023CE0 {
+		compatible = "samsung,exynos4210-pd";
+		reg = <0x10023CE0 0x20>;
 	};
 
 	gic:interrupt-controller@10490000 {
@@ -121,7 +159,7 @@
 		status = "disabled";
 	};
 
-	i2c@13860000 {
+	i2c_0: i2c@13860000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
@@ -130,7 +168,7 @@
 		status = "disabled";
 	};
 
-	i2c@13870000 {
+	i2c_1: i2c@13870000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
@@ -139,7 +177,7 @@
 		status = "disabled";
 	};
 
-	i2c@13880000 {
+	i2c_2: i2c@13880000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
@@ -148,7 +186,7 @@
 		status = "disabled";
 	};
 
-	i2c@13890000 {
+	i2c_3: i2c@13890000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
@@ -157,7 +195,7 @@
 		status = "disabled";
 	};
 
-	i2c@138A0000 {
+	i2c_4: i2c@138A0000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
@@ -166,7 +204,7 @@
 		status = "disabled";
 	};
 
-	i2c@138B0000 {
+	i2c_5: i2c@138B0000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
@@ -175,7 +213,7 @@
 		status = "disabled";
 	};
 
-	i2c@138C0000 {
+	i2c_6: i2c@138C0000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
@@ -184,7 +222,7 @@
 		status = "disabled";
 	};
 
-	i2c@138D0000 {
+	i2c_7: i2c@138D0000 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
@@ -244,5 +282,11 @@
 			reg = <0x12690000 0x1000>;
 			interrupts = <0 36 0>;
 		};
+
+		mdma1: mdma@12850000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x12850000 0x1000>;
+			interrupts = <0 34 0>;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts
index 3e68f52..f271001 100644
--- a/arch/arm/boot/dts/exynos4210-origen.dts
+++ b/arch/arm/boot/dts/exynos4210-origen.dts
@@ -22,38 +22,54 @@
 	compatible = "insignal,origen", "samsung,exynos4210";
 
 	memory {
-		reg = <0x40000000 0x40000000>;
+		reg = <0x40000000 0x10000000
+		       0x50000000 0x10000000
+		       0x60000000 0x10000000
+		       0x70000000 0x10000000>;
 	};
 
 	chosen {
 		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;
+	};
+
 	sdhci@12530000 {
-		samsung,sdhci-bus-width = <4>;
-		linux,mmc_cap_4_bit_data;
-		samsung,sdhci-cd-internal;
-		gpio-cd = <&gpk2 2 2 3 3>;
-		gpios = <&gpk2 0 2 0 3>,
-			<&gpk2 1 2 0 3>,
-			<&gpk2 3 2 3 3>,
-			<&gpk2 4 2 3 3>,
-			<&gpk2 5 2 3 3>,
-			<&gpk2 6 2 3 3>;
+		bus-width = <4>;
+		pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &sd2_cd>;
+		pinctrl-names = "default";
+		vmmc-supply = <&mmc_reg>;
 		status = "okay";
 	};
 
 	sdhci@12510000 {
-		samsung,sdhci-bus-width = <4>;
-		linux,mmc_cap_4_bit_data;
-		samsung,sdhci-cd-internal;
-		gpio-cd = <&gpk0 2 2 3 3>;
-		gpios = <&gpk0 0 2 0 3>,
-			<&gpk0 1 2 0 3>,
-			<&gpk0 3 2 3 3>,
-			<&gpk0 4 2 3 3>,
-			<&gpk0 5 2 3 3>,
-			<&gpk0 6 2 3 3>;
+		bus-width = <4>;
+		pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_cd>;
+		pinctrl-names = "default";
+		vmmc-supply = <&mmc_reg>;
+		status = "okay";
+	};
+
+	serial@13800000 {
+		status = "okay";
+	};
+
+	serial@13810000 {
+		status = "okay";
+	};
+
+	serial@13820000 {
+		status = "okay";
+	};
+
+	serial@13830000 {
 		status = "okay";
 	};
 
@@ -64,35 +80,35 @@
 
 		up {
 			label = "Up";
-			gpios = <&gpx2 0 0 0x10000 2>;
+			gpios = <&gpx2 0 1>;
 			linux,code = <103>;
 			gpio-key,wakeup;
 		};
 
 		down {
 			label = "Down";
-			gpios = <&gpx2 1 0 0x10000 2>;
+			gpios = <&gpx2 1 1>;
 			linux,code = <108>;
 			gpio-key,wakeup;
 		};
 
 		back {
 			label = "Back";
-			gpios = <&gpx1 7 0 0x10000 2>;
+			gpios = <&gpx1 7 1>;
 			linux,code = <158>;
 			gpio-key,wakeup;
 		};
 
 		home {
 			label = "Home";
-			gpios = <&gpx1 6 0 0x10000 2>;
+			gpios = <&gpx1 6 1>;
 			linux,code = <102>;
 			gpio-key,wakeup;
 		};
 
 		menu {
 			label = "Menu";
-			gpios = <&gpx1 5 0 0x10000 2>;
+			gpios = <&gpx1 5 1>;
 			linux,code = <139>;
 			gpio-key,wakeup;
 		};
@@ -101,7 +117,7 @@
 	leds {
 		compatible = "gpio-leds";
 		status {
-			gpios = <&gpx1 3 0 0x10000 2>;
+			gpios = <&gpx1 3 1>;
 			linux,default-trigger = "heartbeat";
 		};
 	};
diff --git a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
index b12cf27..55a2efb 100644
--- a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
@@ -16,6 +16,134 @@
 
 / {
 	pinctrl@11400000 {
+		gpa0: gpa0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpa1: gpa1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpb: gpb {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpc0: gpc0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpc1: gpc1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpd0: gpd0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpd1: gpd1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpe0: gpe0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpe1: gpe1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpe2: gpe2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpe3: gpe3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpe4: gpe4 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpf0: gpf0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpf1: gpf1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpf2: gpf2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpf3: gpf3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
 		uart0_data: uart0-data {
 			samsung,pins = "gpa0-0", "gpa0-1";
 			samsung,pin-function = <0x2>;
@@ -205,200 +333,345 @@
 	};
 
 	pinctrl@11000000 {
+		gpj0: gpj0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpj1: gpj1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpk0: gpk0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpk1: gpk1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpk2: gpk2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpk3: gpk3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpl0: gpl0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpl1: gpl1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpl2: gpl2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpy0: gpy0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy1: gpy1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy2: gpy2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy3: gpy3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy4: gpy4 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy5: gpy5 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy6: gpy6 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpx0: gpx0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			interrupt-parent = <&gic>;
+			interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+				     <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
+			#interrupt-cells = <2>;
+		};
+
+		gpx1: gpx1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			interrupt-parent = <&gic>;
+			interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+				     <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
+			#interrupt-cells = <2>;
+		};
+
+		gpx2: gpx2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpx3: gpx3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
 		sd0_clk: sd0-clk {
 			samsung,pins = "gpk0-0";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <0>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd0_cmd: sd0-cmd {
 			samsung,pins = "gpk0-1";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <0>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd0_cd: sd0-cd {
 			samsung,pins = "gpk0-2";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd0_bus1: sd0-bus-width1 {
 			samsung,pins = "gpk0-3";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd0_bus4: sd0-bus-width4 {
 			samsung,pins = "gpk0-3", "gpk0-4", "gpk0-5", "gpk0-6";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd0_bus8: sd0-bus-width8 {
 			samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
 			samsung,pin-function = <3>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd4_clk: sd4-clk {
 			samsung,pins = "gpk0-0";
 			samsung,pin-function = <3>;
 			samsung,pin-pud = <0>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd4_cmd: sd4-cmd {
 			samsung,pins = "gpk0-1";
 			samsung,pin-function = <3>;
 			samsung,pin-pud = <0>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd4_cd: sd4-cd {
 			samsung,pins = "gpk0-2";
 			samsung,pin-function = <3>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd4_bus1: sd4-bus-width1 {
 			samsung,pins = "gpk0-3";
 			samsung,pin-function = <3>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd4_bus4: sd4-bus-width4 {
 			samsung,pins = "gpk0-3", "gpk0-4", "gpk0-5", "gpk0-6";
 			samsung,pin-function = <3>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd4_bus8: sd4-bus-width8 {
 			samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
 			samsung,pin-function = <3>;
 			samsung,pin-pud = <4>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd1_clk: sd1-clk {
 			samsung,pins = "gpk1-0";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <0>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd1_cmd: sd1-cmd {
 			samsung,pins = "gpk1-1";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <0>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd1_cd: sd1-cd {
 			samsung,pins = "gpk1-2";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd1_bus1: sd1-bus-width1 {
 			samsung,pins = "gpk1-3";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd1_bus4: sd1-bus-width4 {
 			samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd2_clk: sd2-clk {
 			samsung,pins = "gpk2-0";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <0>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd2_cmd: sd2-cmd {
 			samsung,pins = "gpk2-1";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <0>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd2_cd: sd2-cd {
 			samsung,pins = "gpk2-2";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd2_bus1: sd2-bus-width1 {
 			samsung,pins = "gpk2-3";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd2_bus4: sd2-bus-width4 {
 			samsung,pins = "gpk2-3", "gpk2-4", "gpk2-5", "gpk2-6";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd2_bus8: sd2-bus-width8 {
 			samsung,pins = "gpk3-3", "gpk3-4", "gpk3-5", "gpk3-6";
 			samsung,pin-function = <3>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd3_clk: sd3-clk {
 			samsung,pins = "gpk3-0";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <0>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd3_cmd: sd3-cmd {
 			samsung,pins = "gpk3-1";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <0>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd3_cd: sd3-cd {
 			samsung,pins = "gpk3-2";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd3_bus1: sd3-bus-width1 {
 			samsung,pins = "gpk3-3";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		sd3_bus4: sd3-bus-width4 {
 			samsung,pins = "gpk3-3", "gpk3-4", "gpk3-5", "gpk3-6";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <3>;
-			samsung,pin-drv = <0>;
+			samsung,pin-drv = <3>;
 		};
 
 		eint0: ext-int0 {
@@ -438,6 +711,11 @@
 	};
 
 	pinctrl@03860000 {
+		gpz: gpz {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
 		i2s0_bus: i2s0-bus {
 			samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
 					"gpz-4", "gpz-5", "gpz-6";
diff --git a/arch/arm/boot/dts/exynos4210-smdkv310.dts b/arch/arm/boot/dts/exynos4210-smdkv310.dts
index 63610c3..9b23a82 100644
--- a/arch/arm/boot/dts/exynos4210-smdkv310.dts
+++ b/arch/arm/boot/dts/exynos4210-smdkv310.dts
@@ -43,6 +43,22 @@
 		status = "okay";
 	};
 
+	serial@13800000 {
+		status = "okay";
+	};
+
+	serial@13810000 {
+		status = "okay";
+	};
+
+	serial@13820000 {
+		status = "okay";
+	};
+
+	serial@13830000 {
+		status = "okay";
+	};
+
 	keypad@100A0000 {
 		samsung,keypad-num-rows = <2>;
 		samsung,keypad-num-columns = <8>;
diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts
index a21511c..c346b64 100644
--- a/arch/arm/boot/dts/exynos4210-trats.dts
+++ b/arch/arm/boot/dts/exynos4210-trats.dts
@@ -35,24 +35,15 @@
 		regulator-name = "VMEM_VDD_2.8V";
 		regulator-min-microvolt = <2800000>;
 		regulator-max-microvolt = <2800000>;
-		gpio = <&gpk0 2 1 0 0>;
+		gpio = <&gpk0 2 0>;
 		enable-active-high;
 	};
 
 	sdhci_emmc: sdhci@12510000 {
 		bus-width = <8>;
 		non-removable;
-		broken-voltage;
-		gpios = <&gpk0 0 2 0 3>,
-			<&gpk0 1 2 0 3>,
-			<&gpk0 3 2 2 3>,
-			<&gpk0 4 2 2 3>,
-			<&gpk0 5 2 2 3>,
-			<&gpk0 6 2 2 3>,
-			<&gpk1 3 3 3 3>,
-			<&gpk1 4 3 3 3>,
-			<&gpk1 5 3 3 3>,
-			<&gpk1 6 3 3 3>;
+		pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus8>;
+		pinctrl-names = "default";
 		vmmc-supply = <&vemmc_reg>;
 		status = "okay";
 	};
@@ -73,12 +64,74 @@
 		status = "okay";
 	};
 
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		vol-down-key {
+			gpios = <&gpx2 1 1>;
+			linux,code = <114>;
+			label = "volume down";
+			debounce-interval = <10>;
+		};
+
+		vol-up-key {
+			gpios = <&gpx2 0 1>;
+			linux,code = <115>;
+			label = "volume up";
+			debounce-interval = <10>;
+		};
+
+		power-key {
+			gpios = <&gpx2 7 1>;
+			linux,code = <116>;
+			label = "power";
+			debounce-interval = <10>;
+			gpio-key,wakeup;
+		};
+
+		ok-key {
+			gpios = <&gpx3 5 1>;
+			linux,code = <352>;
+			label = "ok";
+			debounce-interval = <10>;
+		};
+	};
+
+	tsp_reg: voltage-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "TSP_FIXED_VOLTAGES";
+		regulator-min-microvolt = <2800000>;
+		regulator-max-microvolt = <2800000>;
+		gpio = <&gpl0 3 0>;
+		enable-active-high;
+	};
+
+	i2c@13890000 {
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-slave-addr = <0x10>;
+		samsung,i2c-max-bus-freq = <400000>;
+		pinctrl-0 = <&i2c3_bus>;
+		pinctrl-names = "default";
+		status = "okay";
+
+		mms114-touchscreen@48 {
+			compatible = "melfas,mms114";
+			reg = <0x48>;
+			interrupt-parent = <&gpx0>;
+			interrupts = <4 2>;
+			x-size = <720>;
+			y-size = <1280>;
+			avdd-supply = <&tsp_reg>;
+			vdd-supply = <&tsp_reg>;
+		};
+	};
+
 	i2c@138B0000 {
 		samsung,i2c-sda-delay = <100>;
 		samsung,i2c-slave-addr = <0x10>;
 		samsung,i2c-max-bus-freq = <100000>;
-		gpios = <&gpb 6 3 3 0>,
-			<&gpb 7 3 3 0>;
+		pinctrl-0 = <&i2c5_bus>;
+		pinctrl-names = "default";
 		status = "okay";
 
 		max8997_pmic@66 {
@@ -93,9 +146,9 @@
 			max8997,pmic-ignore-gpiodvs-side-effect;
 			max8997,pmic-buck125-default-dvs-idx = <0>;
 
-			max8997,pmic-buck125-dvs-gpios = <&gpx0 5 1 0 0>,
-						         <&gpx0 6 1 0 0>,
-							 <&gpl0 0 1 0 0>;
+			max8997,pmic-buck125-dvs-gpios = <&gpx0 5 0>,
+						         <&gpx0 6 0>,
+							 <&gpl0 0 0>;
 
 			max8997,pmic-buck1-dvs-voltage = <1350000>, <1300000>,
 							 <1250000>, <1200000>,
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index 214c557..e31bfc4 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -31,6 +31,11 @@
 		pinctrl2 = &pinctrl_2;
 	};
 
+	pd_lcd1: lcd1-power-domain@10023CA0 {
+		compatible = "samsung,exynos4210-pd";
+		reg = <0x10023CA0 0x20>;
+	};
+
 	gic:interrupt-controller@10490000 {
 		cpu-offset = <0x8000>;
 	};
@@ -46,27 +51,17 @@
 		compatible = "samsung,pinctrl-exynos4210";
 		reg = <0x11400000 0x1000>;
 		interrupts = <0 47 0>;
-		interrupt-controller;
-		#interrupt-cells = <2>;
 	};
 
 	pinctrl_1: pinctrl@11000000 {
 		compatible = "samsung,pinctrl-exynos4210";
 		reg = <0x11000000 0x1000>;
 		interrupts = <0 46 0>;
-		interrupt-controller;
-		#interrupt-cells = <2>;
 
 		wakup_eint: wakeup-interrupt-controller {
 			compatible = "samsung,exynos4210-wakeup-eint";
 			interrupt-parent = <&gic>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
-				     <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
-				     <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
-				     <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>,
-				     <0 32 0>;
+			interrupts = <0 32 0>;
 		};
 	};
 
@@ -75,232 +70,10 @@
 		reg = <0x03860000 0x1000>;
 	};
 
-	gpio-controllers {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		gpio-controller;
-		ranges;
-
-		gpa0: gpio-controller@11400000 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400000 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpa1: gpio-controller@11400020 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400020 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpb: gpio-controller@11400040 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400040 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpc0: gpio-controller@11400060 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400060 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpc1: gpio-controller@11400080 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400080 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpd0: gpio-controller@114000A0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x114000A0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpd1: gpio-controller@114000C0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x114000C0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpe0: gpio-controller@114000E0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x114000E0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpe1: gpio-controller@11400100 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400100 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpe2: gpio-controller@11400120 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400120 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpe3: gpio-controller@11400140 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400140 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpe4: gpio-controller@11400160 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400160 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpf0: gpio-controller@11400180 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11400180 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpf1: gpio-controller@114001A0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x114001A0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpf2: gpio-controller@114001C0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x114001C0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpf3: gpio-controller@114001E0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x114001E0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpj0: gpio-controller@11000000 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11000000 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpj1: gpio-controller@11000020 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11000020 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpk0: gpio-controller@11000040 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11000040 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpk1: gpio-controller@11000060 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11000060 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpk2: gpio-controller@11000080 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11000080 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpk3: gpio-controller@110000A0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x110000A0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpl0: gpio-controller@110000C0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x110000C0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpl1: gpio-controller@110000E0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x110000E0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpl2: gpio-controller@11000100 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11000100 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpy0: gpio-controller@11000120 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11000120 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpy1: gpio-controller@11000140 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11000140 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpy2: gpio-controller@11000160 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11000160 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpy3: gpio-controller@11000180 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11000180 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpy4: gpio-controller@110001A0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x110001A0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpy5: gpio-controller@110001C0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x110001C0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpy6: gpio-controller@110001E0 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x110001E0 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpx0: gpio-controller@11000C00 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11000C00 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpx1: gpio-controller@11000C20 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11000C20 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpx2: gpio-controller@11000C40 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11000C40 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpx3: gpio-controller@11000C60 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x11000C60 0x20>;
-			#gpio-cells = <4>;
-		};
-
-		gpz: gpio-controller@03860000 {
-			compatible = "samsung,exynos4-gpio";
-			reg = <0x03860000 0x20>;
-			#gpio-cells = <4>;
-		};
+	tmu@100C0000 {
+		compatible = "samsung,exynos4210-tmu";
+		interrupt-parent = <&combiner>;
+		reg = <0x100C0000 0x100>;
+		interrupts = <2 4>;
 	};
 };
diff --git a/arch/arm/boot/dts/exynos4212.dtsi b/arch/arm/boot/dts/exynos4212.dtsi
new file mode 100644
index 0000000..c6ae200
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4212.dtsi
@@ -0,0 +1,28 @@
+/*
+ * Samsung's Exynos4212 SoC device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung's Exynos4212 SoC device nodes are listed in this file. Exynos4212
+ * 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
+ * Exynos4212 SoC. As device tree coverage for Exynos4212 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/ "exynos4x12.dtsi"
+
+/ {
+	compatible = "samsung,exynos4212";
+
+	gic:interrupt-controller@10490000 {
+		cpu-offset = <0x8000>;
+	};
+};
diff --git a/arch/arm/boot/dts/exynos4412-smdk4412.dts b/arch/arm/boot/dts/exynos4412-smdk4412.dts
new file mode 100644
index 0000000..f05bf57
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4412-smdk4412.dts
@@ -0,0 +1,45 @@
+/*
+ * Samsung's Exynos4412 based SMDK board device tree source
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Device tree source file for Samsung's SMDK4412 board which is based on
+ * Samsung's Exynos4412 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/ "exynos4412.dtsi"
+
+/ {
+	model = "Samsung SMDK evaluation board based on Exynos4412";
+	compatible = "samsung,smdk4412", "samsung,exynos4412";
+
+	memory {
+		reg = <0x40000000 0x40000000>;
+	};
+
+	chosen {
+		bootargs ="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc";
+	};
+
+	serial@13800000 {
+		status = "okay";
+	};
+
+	serial@13810000 {
+		status = "okay";
+	};
+
+	serial@13820000 {
+		status = "okay";
+	};
+
+	serial@13830000 {
+		status = "okay";
+	};
+};
diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
new file mode 100644
index 0000000..d7dfe31
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4412.dtsi
@@ -0,0 +1,28 @@
+/*
+ * Samsung's Exynos4412 SoC device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung's Exynos4412 SoC device nodes are listed in this file. Exynos4412
+ * 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
+ * Exynos4412 SoC. As device tree coverage for Exynos4412 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/ "exynos4x12.dtsi"
+
+/ {
+	compatible = "samsung,exynos4412";
+
+	gic:interrupt-controller@10490000 {
+		cpu-offset = <0x4000>;
+	};
+};
diff --git a/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi b/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi
new file mode 100644
index 0000000..8e6115a
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi
@@ -0,0 +1,965 @@
+/*
+ * Samsung's Exynos4x12 SoCs pin-mux and pin-config device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung's Exynos4x12 SoCs pin-mux and pin-config optiosn are listed as device
+ * tree nodes are listed 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.
+*/
+
+/ {
+	pinctrl@11400000 {
+		gpa0: gpa0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpa1: gpa1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpb: gpb {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpc0: gpc0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpc1: gpc1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpd0: gpd0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpd1: gpd1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpf0: gpf0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpf1: gpf1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpf2: gpf2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpf3: gpf3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpj0: gpj0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpj1: gpj1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		uart0_data: uart0-data {
+			samsung,pins = "gpa0-0", "gpa0-1";
+			samsung,pin-function = <0x2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart0_fctl: uart0-fctl {
+			samsung,pins = "gpa0-2", "gpa0-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart1_data: uart1-data {
+			samsung,pins = "gpa0-4", "gpa0-5";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart1_fctl: uart1-fctl {
+			samsung,pins = "gpa0-6", "gpa0-7";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c2_bus: i2c2-bus {
+			samsung,pins = "gpa0-6", "gpa0-7";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart2_data: uart2-data {
+			samsung,pins = "gpa1-0", "gpa1-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart2_fctl: uart2-fctl {
+			samsung,pins = "gpa1-2", "gpa1-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart_audio_a: uart-audio-a {
+			samsung,pins = "gpa1-0", "gpa1-1";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c3_bus: i2c3-bus {
+			samsung,pins = "gpa1-2", "gpa1-3";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart3_data: uart3-data {
+			samsung,pins = "gpa1-4", "gpa1-5";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart_audio_b: uart-audio-b {
+			samsung,pins = "gpa1-4", "gpa1-5";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		spi0_bus: spi0-bus {
+			samsung,pins = "gpb-0", "gpb-2", "gpb-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c4_bus: i2c4-bus {
+			samsung,pins = "gpb-0", "gpb-1";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		spi1_bus: spi1-bus {
+			samsung,pins = "gpb-4", "gpb-6", "gpb-7";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c5_bus: i2c5-bus {
+			samsung,pins = "gpb-2", "gpb-3";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2s1_bus: i2s1-bus {
+			samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
+					"gpc0-4";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		pcm1_bus: pcm1-bus {
+			samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
+					"gpc0-4";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		ac97_bus: ac97-bus {
+			samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
+					"gpc0-4";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2s2_bus: i2s2-bus {
+			samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
+					"gpc1-4";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		pcm2_bus: pcm2-bus {
+			samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
+					"gpc1-4";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		spdif_bus: spdif-bus {
+			samsung,pins = "gpc1-0", "gpc1-1";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c6_bus: i2c6-bus {
+			samsung,pins = "gpc1-3", "gpc1-4";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		spi2_bus: spi2-bus {
+			samsung,pins = "gpc1-1", "gpc1-3", "gpc1-4";
+			samsung,pin-function = <5>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		pwm0_out: pwm0-out {
+			samsung,pins = "gpd0-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		pwm1_out: pwm1-out {
+			samsung,pins = "gpd0-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		lcd_ctrl: lcd-ctrl {
+			samsung,pins = "gpd0-0", "gpd0-1";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c7_bus: i2c7-bus {
+			samsung,pins = "gpd0-2", "gpd0-3";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		pwm2_out: pwm2-out {
+			samsung,pins = "gpd0-2";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		pwm3_out: pwm3-out {
+			samsung,pins = "gpd0-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c0_bus: i2c0-bus {
+			samsung,pins = "gpd1-0", "gpd1-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		mipi0_clk: mipi0-clk {
+			samsung,pins = "gpd1-0", "gpd1-1";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c1_bus: i2c1-bus {
+			samsung,pins = "gpd1-2", "gpd1-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		mipi1_clk: mipi1-clk {
+			samsung,pins = "gpd1-2", "gpd1-3";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		lcd_clk: lcd-clk {
+			samsung,pins = "gpf0-0", "gpf0-1", "gpf0-2", "gpf0-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		lcd_data16: lcd-data-width16 {
+			samsung,pins = "gpf0-7", "gpf1-0", "gpf1-1", "gpf1-2",
+					"gpf1-3", "gpf1-6", "gpf1-7", "gpf2-0",
+					"gpf2-1", "gpf2-2", "gpf2-3", "gpf2-7",
+					"gpf3-0", "gpf3-1", "gpf3-2", "gpf3-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		lcd_data18: lcd-data-width18 {
+			samsung,pins = "gpf0-6", "gpf0-7", "gpf1-0", "gpf1-1",
+					"gpf1-2", "gpf1-3", "gpf1-6", "gpf1-7",
+					"gpf2-0", "gpf2-1", "gpf2-2", "gpf2-3",
+					"gpf2-6", "gpf2-7", "gpf3-0", "gpf3-1",
+					"gpf3-2", "gpf3-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		lcd_data24: lcd-data-width24 {
+			samsung,pins = "gpf0-4", "gpf0-5", "gpf0-6", "gpf0-7",
+					"gpf1-0", "gpf1-1", "gpf1-2", "gpf1-3",
+					"gpf1-4", "gpf1-5", "gpf1-6", "gpf1-7",
+					"gpf2-0", "gpf2-1", "gpf2-2", "gpf2-3",
+					"gpf2-4", "gpf2-5", "gpf2-6", "gpf2-7",
+					"gpf3-0", "gpf3-1", "gpf3-2", "gpf3-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		lcd_ldi: lcd-ldi {
+			samsung,pins = "gpf3-4";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		cam_port_a: cam-port-a {
+			samsung,pins = "gpj0-0", "gpj0-1", "gpj0-2", "gpj0-3",
+					"gpj0-4", "gpj0-5", "gpj0-6", "gpj0-7",
+					"gpj1-0", "gpj1-1", "gpj1-2", "gpj1-3",
+					"gpj1-4";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+	};
+
+	pinctrl@11000000 {
+		gpk0: gpk0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpk1: gpk1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpk2: gpk2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpk3: gpk3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpl0: gpl0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpl1: gpl1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpl2: gpl2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpm0: gpm0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpm1: gpm1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpm2: gpm2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpm3: gpm3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpm4: gpm4 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpy0: gpy0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy1: gpy1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy2: gpy2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy3: gpy3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy4: gpy4 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy5: gpy5 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpy6: gpy6 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpx0: gpx0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			interrupt-parent = <&gic>;
+			interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+				     <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
+			#interrupt-cells = <2>;
+		};
+
+		gpx1: gpx1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			interrupt-parent = <&gic>;
+			interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+				     <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
+			#interrupt-cells = <2>;
+		};
+
+		gpx2: gpx2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpx3: gpx3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		sd0_clk: sd0-clk {
+			samsung,pins = "gpk0-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd0_cmd: sd0-cmd {
+			samsung,pins = "gpk0-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd0_cd: sd0-cd {
+			samsung,pins = "gpk0-2";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd0_bus1: sd0-bus-width1 {
+			samsung,pins = "gpk0-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd0_bus4: sd0-bus-width4 {
+			samsung,pins = "gpk0-3", "gpk0-4", "gpk0-5", "gpk0-6";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd0_bus8: sd0-bus-width8 {
+			samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd4_clk: sd4-clk {
+			samsung,pins = "gpk0-0";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd4_cmd: sd4-cmd {
+			samsung,pins = "gpk0-1";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd4_cd: sd4-cd {
+			samsung,pins = "gpk0-2";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd4_bus1: sd4-bus-width1 {
+			samsung,pins = "gpk0-3";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd4_bus4: sd4-bus-width4 {
+			samsung,pins = "gpk0-3", "gpk0-4", "gpk0-5", "gpk0-6";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd4_bus8: sd4-bus-width8 {
+			samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <4>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd1_clk: sd1-clk {
+			samsung,pins = "gpk1-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd1_cmd: sd1-cmd {
+			samsung,pins = "gpk1-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd1_cd: sd1-cd {
+			samsung,pins = "gpk1-2";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd1_bus1: sd1-bus-width1 {
+			samsung,pins = "gpk1-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd1_bus4: sd1-bus-width4 {
+			samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd2_clk: sd2-clk {
+			samsung,pins = "gpk2-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd2_cmd: sd2-cmd {
+			samsung,pins = "gpk2-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd2_cd: sd2-cd {
+			samsung,pins = "gpk2-2";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd2_bus1: sd2-bus-width1 {
+			samsung,pins = "gpk2-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd2_bus4: sd2-bus-width4 {
+			samsung,pins = "gpk2-3", "gpk2-4", "gpk2-5", "gpk2-6";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd2_bus8: sd2-bus-width8 {
+			samsung,pins = "gpk3-3", "gpk3-4", "gpk3-5", "gpk3-6";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd3_clk: sd3-clk {
+			samsung,pins = "gpk3-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd3_cmd: sd3-cmd {
+			samsung,pins = "gpk3-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd3_cd: sd3-cd {
+			samsung,pins = "gpk3-2";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd3_bus1: sd3-bus-width1 {
+			samsung,pins = "gpk3-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd3_bus4: sd3-bus-width4 {
+			samsung,pins = "gpk3-3", "gpk3-4", "gpk3-5", "gpk3-6";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <3>;
+		};
+
+		keypad_col0: keypad-col0 {
+			samsung,pins = "gpl2-0";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		keypad_col1: keypad-col1 {
+			samsung,pins = "gpl2-1";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		keypad_col2: keypad-col2 {
+			samsung,pins = "gpl2-2";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		keypad_col3: keypad-col3 {
+			samsung,pins = "gpl2-3";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		keypad_col4: keypad-col4 {
+			samsung,pins = "gpl2-4";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		keypad_col5: keypad-col5 {
+			samsung,pins = "gpl2-5";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		keypad_col6: keypad-col6 {
+			samsung,pins = "gpl2-6";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		keypad_col7: keypad-col7 {
+			samsung,pins = "gpl2-7";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		cam_port_b: cam-port-b {
+			samsung,pins = "gpm0-0", "gpm0-1", "gpm0-2", "gpm0-3",
+					"gpm0-4", "gpm0-5", "gpm0-6", "gpm0-7",
+					"gpm1-0", "gpm1-1", "gpm2-0", "gpm2-1",
+					"gpm2-2";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		eint0: ext-int0 {
+			samsung,pins = "gpx0-0";
+			samsung,pin-function = <0xf>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		eint8: ext-int8 {
+			samsung,pins = "gpx1-0";
+			samsung,pin-function = <0xf>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		eint15: ext-int15 {
+			samsung,pins = "gpx1-7";
+			samsung,pin-function = <0xf>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		eint16: ext-int16 {
+			samsung,pins = "gpx2-0";
+			samsung,pin-function = <0xf>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		eint31: ext-int31 {
+			samsung,pins = "gpx3-7";
+			samsung,pin-function = <0xf>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+	};
+
+	pinctrl@03860000 {
+		gpz: gpz {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		i2s0_bus: i2s0-bus {
+			samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
+					"gpz-4", "gpz-5", "gpz-6";
+			samsung,pin-function = <0x2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		pcm0_bus: pcm0-bus {
+			samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
+					"gpz-4";
+			samsung,pin-function = <0x3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+	};
+
+	pinctrl@106E0000 {
+		gpv0: gpv0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpv1: gpv1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpv2: gpv2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpv3: gpv3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpv4: gpv4 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		c2c_bus: c2c-bus {
+			samsung,pins = "gpv0-0", "gpv0-1", "gpv0-2", "gpv0-3",
+					"gpv0-4", "gpv0-5", "gpv0-6", "gpv0-7",
+					"gpv1-0", "gpv1-1", "gpv1-2", "gpv1-3",
+					"gpv1-4", "gpv1-5", "gpv1-6", "gpv1-7",
+					"gpv2-0", "gpv2-1", "gpv2-2", "gpv2-3",
+					"gpv2-4", "gpv2-5", "gpv2-6", "gpv2-7",
+					"gpv3-0", "gpv3-1", "gpv3-2", "gpv3-3",
+					"gpv3-4", "gpv3-5", "gpv3-6", "gpv3-7",
+					"gpv4-0", "gpv4-1";
+			samsung,pin-function = <0x2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi
new file mode 100644
index 0000000..179a62e
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4x12.dtsi
@@ -0,0 +1,69 @@
+/*
+ * Samsung's Exynos4x12 SoCs device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung's Exynos4x12 SoCs device nodes are listed in this file. Exynos4x12
+ * 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
+ * Exynos4x12 SoC. As device tree coverage for Exynos4x12 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/ "exynos4.dtsi"
+/include/ "exynos4x12-pinctrl.dtsi"
+
+/ {
+	aliases {
+		pinctrl0 = &pinctrl_0;
+		pinctrl1 = &pinctrl_1;
+		pinctrl2 = &pinctrl_2;
+		pinctrl3 = &pinctrl_3;
+	};
+
+	combiner:interrupt-controller@10440000 {
+		interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
+			     <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
+			     <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
+			     <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
+			     <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>;
+	};
+
+	pinctrl_0: pinctrl@11400000 {
+		compatible = "samsung,pinctrl-exynos4x12";
+		reg = <0x11400000 0x1000>;
+		interrupts = <0 47 0>;
+	};
+
+	pinctrl_1: pinctrl@11000000 {
+		compatible = "samsung,pinctrl-exynos4x12";
+		reg = <0x11000000 0x1000>;
+		interrupts = <0 46 0>;
+
+		wakup_eint: wakeup-interrupt-controller {
+			compatible = "samsung,exynos4210-wakeup-eint";
+			interrupt-parent = <&gic>;
+			interrupts = <0 32 0>;
+		};
+	};
+
+	pinctrl_2: pinctrl@03860000 {
+		compatible = "samsung,pinctrl-exynos4x12";
+		reg = <0x03860000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <10 0>;
+	};
+
+	pinctrl_3: pinctrl@106E0000 {
+		compatible = "samsung,pinctrl-exynos4x12";
+		reg = <0x106E0000 0x1000>;
+		interrupts = <0 72 0>;
+	};
+};
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index a352df4..f30ca18 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -17,10 +17,6 @@
 	compatible = "samsung,smdk5250", "samsung,exynos5250";
 
 	aliases {
-		mshc0 = &dwmmc_0;
-		mshc1 = &dwmmc_1;
-		mshc2 = &dwmmc_2;
-		mshc3 = &dwmmc_3;
 	};
 
 	memory {
@@ -55,8 +51,31 @@
 		};
 	};
 
+	i2c@121D0000 {
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <40000>;
+		samsung,i2c-slave-addr = <0x38>;
+
+		sata-phy {
+			compatible = "samsung,sata-phy";
+			reg = <0x38>;
+		};
+	};
+
+	sata@122F0000 {
+		samsung,sata-freq = <66>;
+	};
+
 	i2c@12C80000 {
-		status = "disabled";
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <66000>;
+		gpios = <&gpa0 6 3 3 0>,
+			<&gpa0 7 3 3 0>;
+
+		hdmiddc@50 {
+			compatible = "samsung,exynos5-hdmiddc";
+			reg = <0x50>;
+		};
 	};
 
 	i2c@12C90000 {
@@ -79,7 +98,17 @@
 		status = "disabled";
 	};
 
-	dwmmc_0: dwmmc0@12200000 {
+	i2c@12CE0000 {
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <66000>;
+
+		hdmiphy@38 {
+			compatible = "samsung,exynos5-hdmiphy";
+			reg = <0x38>;
+		};
+	};
+
+	dwmmc0@12200000 {
 		num-slots = <1>;
 		supports-highspeed;
 		broken-cd;
@@ -100,11 +129,11 @@
 		};
 	};
 
-	dwmmc_1: dwmmc1@12210000 {
+	dwmmc1@12210000 {
 		status = "disabled";
 	};
 
-	dwmmc_2: dwmmc2@12220000 {
+	dwmmc2@12220000 {
 		num-slots = <1>;
 		supports-highspeed;
 		fifo-depth = <0x80>;
@@ -125,7 +154,7 @@
 		};
 	};
 
-	dwmmc_3: dwmmc3@12230000 {
+	dwmmc3@12230000 {
 		status = "disabled";
 	};
 
@@ -166,4 +195,27 @@
 	spi_2: spi@12d40000 {
 		status = "disabled";
 	};
+
+	hdmi {
+		hpd-gpio = <&gpx3 7 0xf 1 3>;
+	};
+
+	codec@11000000 {
+		samsung,mfc-r = <0x43000000 0x800000>;
+		samsung,mfc-l = <0x51000000 0x800000>;
+	};
+
+	i2s_0: i2s@03830000 {
+		gpios = <&gpz 0 2 0 0>, <&gpz 1 2 0 0>, <&gpz 2 2 0 0>,
+			<&gpz 3 2 0 0>, <&gpz 4 2 0 0>, <&gpz 5 2 0 0>,
+			<&gpz 6 2 0 0>;
+	};
+
+	i2s_1: i2s@12D60000 {
+		status = "disabled";
+	};
+
+	i2s_2: i2s@12D70000 {
+		status = "disabled";
+	};
 };
diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts
new file mode 100644
index 0000000..17dd951
--- /dev/null
+++ b/arch/arm/boot/dts/exynos5250-snow.dts
@@ -0,0 +1,43 @@
+/*
+ * Google Snow board device tree source
+ *
+ * Copyright (c) 2012 Google, 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.
+*/
+
+/dts-v1/;
+/include/ "exynos5250.dtsi"
+/include/ "cros5250-common.dtsi"
+
+/ {
+	model = "Google Snow";
+	compatible = "google,snow", "samsung,exynos5250";
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		lid-switch {
+			label = "Lid";
+			gpios = <&gpx3 5 0 0x10000 0>;
+			linux,input-type = <5>; /* EV_SW */
+			linux,code = <0>; /* SW_LID */
+			debounce-interval = <1>;
+			gpio-key,wakeup;
+		};
+	};
+
+	/*
+	 * On Snow we've got SIP WiFi and so can keep drive strengths low to
+	 * reduce EMI.
+	 */
+	dwmmc3@12230000 {
+		slot@0 {
+			gpios = <&gpc4 0 2 0 0>, <&gpc4 1 2 3 0>,
+				<&gpc4 3 2 3 0>, <&gpc4 4 2 3 0>,
+				<&gpc4 5 2 3 0>, <&gpc4 6 2 3 0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index dddfd6e..581e57a 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -31,6 +31,23 @@
 		gsc1 = &gsc_1;
 		gsc2 = &gsc_2;
 		gsc3 = &gsc_3;
+		i2c0 = &i2c_0;
+		i2c1 = &i2c_1;
+		i2c2 = &i2c_2;
+		i2c3 = &i2c_3;
+		i2c4 = &i2c_4;
+		i2c5 = &i2c_5;
+		i2c6 = &i2c_6;
+		i2c7 = &i2c_7;
+		i2c8 = &i2c_8;
+		i2c9 = &i2c_9;
+		i2s0 = &i2s_0;
+		i2s1 = &i2s_1;
+		i2s2 = &i2s_2;
+		mshc0 = &dwmmc_0;
+		mshc1 = &dwmmc_1;
+		mshc2 = &dwmmc_2;
+		mshc3 = &dwmmc_3;
 	};
 
 	gic:interrupt-controller@10481000 {
@@ -62,12 +79,24 @@
 		interrupts = <0 42 0>;
 	};
 
+	codec@11000000 {
+		compatible = "samsung,mfc-v6";
+		reg = <0x11000000 0x10000>;
+		interrupts = <0 96 0>;
+	};
+
 	rtc {
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x101E0000 0x100>;
 		interrupts = <0 43 0>, <0 44 0>;
 	};
 
+	tmu@10060000 {
+		compatible = "samsung,exynos5250-tmu";
+		reg = <0x10060000 0x100>;
+		interrupts = <0 65 0>;
+	};
+
 	serial@12C00000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C00000 0x100>;
@@ -92,7 +121,18 @@
 		interrupts = <0 54 0>;
 	};
 
-	i2c@12C60000 {
+	sata@122F0000 {
+		compatible = "samsung,exynos5-sata-ahci";
+		reg = <0x122F0000 0x1ff>;
+		interrupts = <0 115 0>;
+	};
+
+	sata-phy@12170000 {
+		compatible = "samsung,exynos5-sata-phy";
+		reg = <0x12170000 0x1ff>;
+	};
+
+	i2c_0: i2c@12C60000 {
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x12C60000 0x100>;
 		interrupts = <0 56 0>;
@@ -100,7 +140,7 @@
 		#size-cells = <0>;
 	};
 
-	i2c@12C70000 {
+	i2c_1: i2c@12C70000 {
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x12C70000 0x100>;
 		interrupts = <0 57 0>;
@@ -108,7 +148,7 @@
 		#size-cells = <0>;
 	};
 
-	i2c@12C80000 {
+	i2c_2: i2c@12C80000 {
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x12C80000 0x100>;
 		interrupts = <0 58 0>;
@@ -116,7 +156,7 @@
 		#size-cells = <0>;
 	};
 
-	i2c@12C90000 {
+	i2c_3: i2c@12C90000 {
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x12C90000 0x100>;
 		interrupts = <0 59 0>;
@@ -124,7 +164,7 @@
 		#size-cells = <0>;
 	};
 
-	i2c@12CA0000 {
+	i2c_4: i2c@12CA0000 {
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x12CA0000 0x100>;
 		interrupts = <0 60 0>;
@@ -132,7 +172,7 @@
 		#size-cells = <0>;
 	};
 
-	i2c@12CB0000 {
+	i2c_5: i2c@12CB0000 {
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x12CB0000 0x100>;
 		interrupts = <0 61 0>;
@@ -140,7 +180,7 @@
 		#size-cells = <0>;
 	};
 
-	i2c@12CC0000 {
+	i2c_6: i2c@12CC0000 {
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x12CC0000 0x100>;
 		interrupts = <0 62 0>;
@@ -148,7 +188,7 @@
 		#size-cells = <0>;
 	};
 
-	i2c@12CD0000 {
+	i2c_7: i2c@12CD0000 {
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x12CD0000 0x100>;
 		interrupts = <0 63 0>;
@@ -156,6 +196,21 @@
 		#size-cells = <0>;
 	};
 
+	i2c_8: i2c@12CE0000 {
+		compatible = "samsung,s3c2440-hdmiphy-i2c";
+		reg = <0x12CE0000 0x1000>;
+		interrupts = <0 64 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	i2c_9: i2c@121D0000 {
+                compatible = "samsung,exynos5-sata-phy-i2c";
+                reg = <0x121D0000 0x100>;
+                #address-cells = <1>;
+                #size-cells = <0>;
+	};
+
 	spi_0: spi@12d20000 {
 		compatible = "samsung,exynos4210-spi";
 		reg = <0x12d20000 0x100>;
@@ -186,7 +241,7 @@
 		#size-cells = <0>;
 	};
 
-	dwmmc0@12200000 {
+	dwmmc_0: dwmmc0@12200000 {
 		compatible = "samsung,exynos5250-dw-mshc";
 		reg = <0x12200000 0x1000>;
 		interrupts = <0 75 0>;
@@ -194,7 +249,7 @@
 		#size-cells = <0>;
 	};
 
-	dwmmc1@12210000 {
+	dwmmc_1: dwmmc1@12210000 {
 		compatible = "samsung,exynos5250-dw-mshc";
 		reg = <0x12210000 0x1000>;
 		interrupts = <0 76 0>;
@@ -202,7 +257,7 @@
 		#size-cells = <0>;
 	};
 
-	dwmmc2@12220000 {
+	dwmmc_2: dwmmc2@12220000 {
 		compatible = "samsung,exynos5250-dw-mshc";
 		reg = <0x12220000 0x1000>;
 		interrupts = <0 77 0>;
@@ -210,7 +265,7 @@
 		#size-cells = <0>;
 	};
 
-	dwmmc3@12230000 {
+	dwmmc_3: dwmmc3@12230000 {
 		compatible = "samsung,exynos5250-dw-mshc";
 		reg = <0x12230000 0x1000>;
 		interrupts = <0 78 0>;
@@ -218,6 +273,32 @@
 		#size-cells = <0>;
 	};
 
+	i2s_0: i2s@03830000 {
+		compatible = "samsung,samsung-i2s";
+		reg = <0x03830000 0x100>;
+		tx-dma-channel-secondary = <&pdma0 8>; /* preliminary */
+		tx-dma-channel = <&pdma0 10>; /* preliminary */
+		rx-dma-channel = <&pdma0 9>; /* preliminary */
+		samsung,supports-6ch;
+		samsung,supports-rstclr;
+		samsung,supports-secdai;
+		samsung,idma-addr = <0x03000000>;
+	};
+
+	i2s_1: i2s@12D60000 {
+		compatible = "samsung,samsung-i2s";
+		reg = <0x12D60000 0x100>;
+		tx-dma-channel = <&pdma1 12>; /* preliminary */
+		rx-dma-channel = <&pdma1 11>; /* preliminary */
+	};
+
+	i2s_2: i2s@12D70000 {
+		compatible = "samsung,samsung-i2s";
+		reg = <0x12D70000 0x100>;
+		tx-dma-channel = <&pdma0 12>; /* preliminary */
+		rx-dma-channel = <&pdma0 11>; /* preliminary */
+	};
+
 	amba {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -520,4 +601,16 @@
 		reg = <0x13e30000 0x1000>;
 		interrupts = <0 88 0>;
 	};
+
+	hdmi {
+		compatible = "samsung,exynos5-hdmi";
+		reg = <0x14530000 0x100000>;
+		interrupts = <0 95 0>;
+	};
+
+	mixer {
+		compatible = "samsung,exynos5-mixer";
+		reg = <0x14450000 0x10000>;
+		interrupts = <0 94 0>;
+	};
 };
diff --git a/arch/arm/boot/dts/exynos5440-ssdk5440.dts b/arch/arm/boot/dts/exynos5440-ssdk5440.dts
new file mode 100644
index 0000000..921c83c
--- /dev/null
+++ b/arch/arm/boot/dts/exynos5440-ssdk5440.dts
@@ -0,0 +1,46 @@
+/*
+ * SAMSUNG SSDK5440 board device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/dts-v1/;
+/include/ "exynos5440.dtsi"
+
+/ {
+	model = "SAMSUNG SSDK5440 board based on EXYNOS5440";
+	compatible = "samsung,ssdk5440", "samsung,exynos5440";
+
+	memory {
+		reg = <0x80000000 0x80000000>;
+	};
+
+	chosen {
+		bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x81000000,8M console=ttySAC2,115200 init=/linuxrc";
+	};
+
+	spi {
+		status = "disabled";
+	};
+
+	i2c@F0000 {
+		status = "disabled";
+	};
+
+	i2c@100000 {
+		status = "disabled";
+	};
+
+	watchdog {
+		status = "disabled";
+	};
+
+	rtc {
+		status = "disabled";
+	};
+};
diff --git a/arch/arm/boot/dts/exynos5440.dtsi b/arch/arm/boot/dts/exynos5440.dtsi
new file mode 100644
index 0000000..024269d
--- /dev/null
+++ b/arch/arm/boot/dts/exynos5440.dtsi
@@ -0,0 +1,159 @@
+/*
+ * SAMSUNG EXYNOS5440 SoC device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "samsung,exynos5440";
+
+	interrupt-parent = <&gic>;
+
+	gic:interrupt-controller@2E0000 {
+		compatible = "arm,cortex-a15-gic";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0x2E1000 0x1000>, <0x2E2000 0x1000>;
+	};
+
+	cpus {
+		cpu@0 {
+			compatible = "arm,cortex-a15";
+			timer {
+				compatible = "arm,armv7-timer";
+				interrupts = <1 13 0xf08>;
+				clock-frequency = <1000000>;
+			};
+		};
+		cpu@1 {
+			compatible = "arm,cortex-a15";
+			timer {
+				compatible = "arm,armv7-timer";
+				interrupts = <1 14 0xf08>;
+				clock-frequency = <1000000>;
+			};
+		};
+		cpu@2 {
+			compatible = "arm,cortex-a15";
+			timer {
+				compatible = "arm,armv7-timer";
+				interrupts = <1 14 0xf08>;
+				clock-frequency = <1000000>;
+			};
+		};
+		cpu@3 {
+			compatible = "arm,cortex-a15";
+			timer {
+				compatible = "arm,armv7-timer";
+				interrupts = <1 14 0xf08>;
+				clock-frequency = <1000000>;
+			};
+		};
+	};
+
+	common {
+		compatible = "samsung,exynos5440";
+
+	};
+
+	serial@B0000 {
+		compatible = "samsung,exynos4210-uart";
+		reg = <0xB0000 0x1000>;
+		interrupts = <0 2 0>;
+	};
+
+	serial@C0000 {
+		compatible = "samsung,exynos4210-uart";
+		reg = <0xC0000 0x1000>;
+		interrupts = <0 3 0>;
+	};
+
+	spi {
+		compatible = "samsung,exynos4210-spi";
+		reg = <0xD0000 0x1000>;
+		interrupts = <0 4 0>;
+		tx-dma-channel = <&pdma0 5>; /* preliminary */
+		rx-dma-channel = <&pdma0 4>; /* preliminary */
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	pinctrl {
+		compatible = "samsung,pinctrl-exynos5440";
+		reg = <0xE0000 0x1000>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		#gpio-cells = <2>;
+
+		fan: fan {
+			samsung,exynos5440-pin-function = <1>;
+		};
+
+		hdd_led0: hdd_led0 {
+			samsung,exynos5440-pin-function = <2>;
+		};
+
+		hdd_led1: hdd_led1 {
+			samsung,exynos5440-pin-function = <3>;
+		};
+
+		uart1: uart1 {
+			samsung,exynos5440-pin-function = <4>;
+		};
+	};
+
+	i2c@F0000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0xF0000 0x1000>;
+		interrupts = <0 5 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	i2c@100000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x100000 0x1000>;
+		interrupts = <0 6 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	watchdog {
+		compatible = "samsung,s3c2410-wdt";
+		reg = <0x110000 0x1000>;
+		interrupts = <0 1 0>;
+	};
+
+	amba {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "arm,amba-bus";
+		interrupt-parent = <&gic>;
+		ranges;
+
+		pdma0: pdma@121A0000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x120000 0x1000>;
+			interrupts = <0 34 0>;
+		};
+
+		pdma1: pdma@121B0000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x121000 0x1000>;
+			interrupts = <0 35 0>;
+		};
+	};
+
+	rtc {
+		compatible = "samsung,s3c6410-rtc";
+		reg = <0x130000 0x1000>;
+		interrupts = <0 16 0>, <0 17 0>;
+	};
+};
diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/highbank.dts
index 0c6fc34..a9ae5d3 100644
--- a/arch/arm/boot/dts/highbank.dts
+++ b/arch/arm/boot/dts/highbank.dts
@@ -69,16 +69,8 @@
 		reg = <0x00000000 0xff900000>;
 	};
 
-	chosen {
-		bootargs = "console=ttyAMA0";
-	};
-
 	soc {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "simple-bus";
-		interrupt-parent = <&intc>;
-		ranges;
+		ranges = <0x00000000 0x00000000 0xffffffff>;
 
 		timer@fff10600 {
 			compatible = "arm,cortex-a9-twd-timer";
@@ -117,173 +109,6 @@
 			interrupts = <0 76 4  0 75 4  0 74 4  0 73 4>;
 		};
 
-		sata@ffe08000 {
-			compatible = "calxeda,hb-ahci";
-			reg = <0xffe08000 0x10000>;
-			interrupts = <0 83 4>;
-			calxeda,port-phys = <&combophy5 0 &combophy0 0
-					     &combophy0 1 &combophy0 2
-					     &combophy0 3>;
-			dma-coherent;
-		};
-
-		sdhci@ffe0e000 {
-			compatible = "calxeda,hb-sdhci";
-			reg = <0xffe0e000 0x1000>;
-			interrupts = <0 90 4>;
-			clocks = <&eclk>;
-		};
-
-		memory-controller@fff00000 {
-			compatible = "calxeda,hb-ddr-ctrl";
-			reg = <0xfff00000 0x1000>;
-			interrupts = <0 91 4>;
-		};
-
-		ipc@fff20000 {
-			compatible = "arm,pl320", "arm,primecell";
-			reg = <0xfff20000 0x1000>;
-			interrupts = <0 7 4>;
-			clocks = <&pclk>;
-			clock-names = "apb_pclk";
-		};
-
-		gpioe: gpio@fff30000 {
-			#gpio-cells = <2>;
-			compatible = "arm,pl061", "arm,primecell";
-			gpio-controller;
-			reg = <0xfff30000 0x1000>;
-			interrupts = <0 14 4>;
-			clocks = <&pclk>;
-			clock-names = "apb_pclk";
-		};
-
-		gpiof: gpio@fff31000 {
-			#gpio-cells = <2>;
-			compatible = "arm,pl061", "arm,primecell";
-			gpio-controller;
-			reg = <0xfff31000 0x1000>;
-			interrupts = <0 15 4>;
-			clocks = <&pclk>;
-			clock-names = "apb_pclk";
-		};
-
-		gpiog: gpio@fff32000 {
-			#gpio-cells = <2>;
-			compatible = "arm,pl061", "arm,primecell";
-			gpio-controller;
-			reg = <0xfff32000 0x1000>;
-			interrupts = <0 16 4>;
-			clocks = <&pclk>;
-			clock-names = "apb_pclk";
-		};
-
-		gpioh: gpio@fff33000 {
-			#gpio-cells = <2>;
-			compatible = "arm,pl061", "arm,primecell";
-			gpio-controller;
-			reg = <0xfff33000 0x1000>;
-			interrupts = <0 17 4>;
-			clocks = <&pclk>;
-			clock-names = "apb_pclk";
-		};
-
-		timer {
-			compatible = "arm,sp804", "arm,primecell";
-			reg = <0xfff34000 0x1000>;
-			interrupts = <0 18 4>;
-			clocks = <&pclk>;
-			clock-names = "apb_pclk";
-		};
-
-		rtc@fff35000 {
-			compatible = "arm,pl031", "arm,primecell";
-			reg = <0xfff35000 0x1000>;
-			interrupts = <0 19 4>;
-			clocks = <&pclk>;
-			clock-names = "apb_pclk";
-		};
-
-		serial@fff36000 {
-			compatible = "arm,pl011", "arm,primecell";
-			reg = <0xfff36000 0x1000>;
-			interrupts = <0 20 4>;
-			clocks = <&pclk>;
-			clock-names = "apb_pclk";
-		};
-
-		smic@fff3a000 {
-			compatible = "ipmi-smic";
-			device_type = "ipmi";
-			reg = <0xfff3a000 0x1000>;
-			interrupts = <0 24 4>;
-			reg-size = <4>;
-			reg-spacing = <4>;
-		};
-
-		sregs@fff3c000 {
-			compatible = "calxeda,hb-sregs";
-			reg = <0xfff3c000 0x1000>;
-
-			clocks {
-				#address-cells = <1>;
-				#size-cells = <0>;
-
-				osc: oscillator {
-					#clock-cells = <0>;
-					compatible = "fixed-clock";
-					clock-frequency = <33333000>;
-				};
-
-				ddrpll: ddrpll {
-					#clock-cells = <0>;
-					compatible = "calxeda,hb-pll-clock";
-					clocks = <&osc>;
-					reg = <0x108>;
-				};
-
-				a9pll: a9pll {
-					#clock-cells = <0>;
-					compatible = "calxeda,hb-pll-clock";
-					clocks = <&osc>;
-					reg = <0x100>;
-				};
-
-				a9periphclk: a9periphclk {
-					#clock-cells = <0>;
-					compatible = "calxeda,hb-a9periph-clock";
-					clocks = <&a9pll>;
-					reg = <0x104>;
-				};
-
-				a9bclk: a9bclk {
-					#clock-cells = <0>;
-					compatible = "calxeda,hb-a9bus-clock";
-					clocks = <&a9pll>;
-					reg = <0x104>;
-				};
-
-				emmcpll: emmcpll {
-					#clock-cells = <0>;
-					compatible = "calxeda,hb-pll-clock";
-					clocks = <&osc>;
-					reg = <0x10C>;
-				};
-
-				eclk: eclk {
-					#clock-cells = <0>;
-					compatible = "calxeda,hb-emmc-clock";
-					clocks = <&emmcpll>;
-					reg = <0x114>;
-				};
-
-				pclk: pclk {
-					#clock-cells = <0>;
-					compatible = "fixed-clock";
-					clock-frequency = <150000000>;
-				};
-			};
-		};
 
 		sregs@fff3c200 {
 			compatible = "calxeda,hb-sregs-l2-ecc";
@@ -291,38 +116,7 @@
 			interrupts = <0 71 4  0 72 4>;
 		};
 
-		dma@fff3d000 {
-			compatible = "arm,pl330", "arm,primecell";
-			reg = <0xfff3d000 0x1000>;
-			interrupts = <0 92 4>;
-			clocks = <&pclk>;
-			clock-names = "apb_pclk";
-		};
-
-		ethernet@fff50000 {
-			compatible = "calxeda,hb-xgmac";
-			reg = <0xfff50000 0x1000>;
-			interrupts = <0 77 4  0 78 4  0 79 4>;
-		};
-
-		ethernet@fff51000 {
-			compatible = "calxeda,hb-xgmac";
-			reg = <0xfff51000 0x1000>;
-			interrupts = <0 80 4  0 81 4  0 82 4>;
-		};
-
-		combophy0: combo-phy@fff58000 {
-			compatible = "calxeda,hb-combophy";
-			#phy-cells = <1>;
-			reg = <0xfff58000 0x1000>;
-			phydev = <5>;
-		};
-
-		combophy5: combo-phy@fff5d000 {
-			compatible = "calxeda,hb-combophy";
-			#phy-cells = <1>;
-			reg = <0xfff5d000 0x1000>;
-			phydev = <31>;
-		};
 	};
 };
+
+/include/ "ecx-common.dtsi"
diff --git a/arch/arm/boot/dts/href.dtsi b/arch/arm/boot/dts/href.dtsi
new file mode 100644
index 0000000..592fb9d
--- /dev/null
+++ b/arch/arm/boot/dts/href.dtsi
@@ -0,0 +1,273 @@
+/*
+ * 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/ "dbx5x0.dtsi"
+
+/ {
+	memory {
+		reg = <0x00000000 0x20000000>;
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		button@1 {
+			linux,code = <11>;
+			label = "SFH7741 Proximity Sensor";
+		};
+	};
+
+	soc-u9500 {
+		uart@80120000 {
+			status = "okay";
+		};
+
+		uart@80121000 {
+			status = "okay";
+		};
+
+		uart@80007000 {
+			status = "okay";
+		};
+
+		i2c@80004000 {
+			tc3589x@42 {
+				compatible = "tc3589x";
+				reg = <0x42>;
+				interrupt-parent = <&gpio6>;
+				interrupts = <25 0x1>;
+
+				interrupt-controller;
+				#interrupt-cells = <2>;
+
+				tc3589x_gpio: tc3589x_gpio {
+					compatible = "tc3589x-gpio";
+					interrupts = <0 0x1>;
+
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+			};
+		};
+
+		i2c@80128000 {
+			lp5521@0x33 {
+				compatible = "lp5521";
+				reg = <0x33>;
+			};
+
+			lp5521@0x34 {
+				compatible = "lp5521";
+				reg = <0x34>;
+			};
+
+			bh1780@0x29 {
+				compatible = "rohm,bh1780gli";
+				reg = <0x33>;
+			};
+		};
+
+		// External Micro SD slot
+		sdi0_per1@80126000 {
+			arm,primecell-periphid = <0x10480180>;
+			max-frequency = <50000000>;
+			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 = <50000000>;
+			bus-width = <4>;
+
+			status = "okay";
+		};
+
+		// PoP:ed eMMC
+		sdi2_per3@80005000 {
+			arm,primecell-periphid = <0x10480180>;
+			max-frequency = <50000000>;
+			bus-width = <8>;
+			mmc-cap-mmc-highspeed;
+
+			status = "okay";
+		};
+
+		// On-board eMMC
+		sdi4_per2@80114000 {
+			arm,primecell-periphid = <0x10480180>;
+		        max-frequency = <50000000>;
+			bus-width = <8>;
+			mmc-cap-mmc-highspeed;
+			vmmc-supply = <&ab8500_ldo_aux2_reg>;
+
+			status = "okay";
+		};
+
+		sound {
+			compatible = "stericsson,snd-soc-mop500";
+
+			stericsson,cpu-dai = <&msp1 &msp3>;
+			stericsson,audio-codec = <&codec>;
+		};
+
+		msp1: msp@80124000 {
+			status = "okay";
+		};
+
+		msp3: msp@80125000 {
+			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@5 {
+				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_initcore_reg: ab8500_ldo_initcore {
+						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_amamic2_reg: ab8500_ldo_amamic2 {
+						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/hrefprev60.dts b/arch/arm/boot/dts/hrefprev60.dts
new file mode 100644
index 0000000..eec29c4
--- /dev/null
+++ b/arch/arm/boot/dts/hrefprev60.dts
@@ -0,0 +1,48 @@
+/*
+ * 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/ "dbx5x0.dtsi"
+/include/ "href.dtsi"
+/include/ "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>;
+		};
+	};
+
+	soc-u9500 {
+		i2c@80004000 {
+			tps61052@33 {
+				compatible = "tps61052";
+				reg = <0x33>;
+			};
+		};
+
+		i2c@80110000 {
+			bu21013_tp@0x5c {
+				reset-gpio = <&tc3589x_gpio 13 0x4>;
+			};
+		};
+
+		vmmci: regulator-gpio {
+			gpios = <&tc3589x_gpio 18 0x4>;
+			gpio-enable = <&tc3589x_gpio 17 0x4>;
+
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/hrefv60plus.dts b/arch/arm/boot/dts/hrefv60plus.dts
index 2131d77..55f4191 100644
--- a/arch/arm/boot/dts/hrefv60plus.dts
+++ b/arch/arm/boot/dts/hrefv60plus.dts
@@ -11,85 +11,200 @@
 
 /dts-v1/;
 /include/ "dbx5x0.dtsi"
+/include/ "href.dtsi"
+/include/ "stuib.dtsi"
 
 / {
-	model = "ST-Ericsson HREF platform with Device Tree";
-	compatible = "st-ericsson,hrefv60+";
+	model = "ST-Ericsson HREF (v60+) platform with Device Tree";
+	compatible = "st-ericsson,hrefv60+", "st-ericsson,u8500";
 
-	memory {
-		reg = <0x00000000 0x20000000>;
+	gpio_keys {
+		button@1 {
+			gpios = <&gpio6 25 0x4>;
+		};
 	};
 
 	soc-u9500 {
-		uart@80120000 {
+		i2c@80110000 {
+			bu21013_tp@0x5c {
+				reset-gpio = <&gpio4 15 0x4>;
+			};
+		};
+
+		// External Micro SD slot
+		sdi0_per1@80126000 {
+			arm,primecell-periphid = <0x10480180>;
+			max-frequency = <50000000>;
+			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";
 		};
 
-		uart@80121000 {
+		// WLAN SDIO channel
+		sdi1_per2@80118000 {
+			arm,primecell-periphid = <0x10480180>;
+			max-frequency = <50000000>;
+			bus-width = <4>;
+
 			status = "okay";
 		};
 
-		uart@80007000 {
+		// PoP:ed eMMC
+		sdi2_per3@80005000 {
+			arm,primecell-periphid = <0x10480180>;
+			max-frequency = <50000000>;
+			bus-width = <8>;
+			mmc-cap-mmc-highspeed;
+
 			status = "okay";
 		};
 
-		i2c@80004000 {
-			tc3589x@42 {
-				compatible = "tc3589x";
-				reg = <0x42>;
-				interrupt-parent = <&gpio6>;
-				interrupts = <25 0x1>;
+		// On-board eMMC
+		sdi4_per2@80114000 {
+			arm,primecell-periphid = <0x10480180>;
+		        max-frequency = <50000000>;
+			bus-width = <8>;
+			mmc-cap-mmc-highspeed;
+			vmmc-supply = <&ab8500_ldo_aux2_reg>;
 
-				interrupt-controller;
-				#interrupt-cells = <2>;
+			status = "okay";
+		};
 
-				tc3589x_gpio: tc3589x_gpio {
-					compatible = "tc3589x-gpio";
-					interrupts = <0 0x1>;
+		prcmu@80157000 {
+			db8500-prcmu-regulators {
+				db8500_vape_reg: db8500_vape {
+					regulator-name = "db8500-vape";
+				};
 
-					interrupt-controller;
-					#interrupt-cells = <2>;
-					gpio-controller;
-					#gpio-cells = <2>;
+				db8500_varm_reg: db8500_varm {
+					regulator-name = "db8500-varm";
 				};
-			};
 
-			tps61052@33 {
-				compatible = "tps61052";
-				reg = <0x33>;
-			};
-		};
+				db8500_vmodem_reg: db8500_vmodem {
+					regulator-name = "db8500-vmodem";
+				};
 
-		i2c@80128000 {
-			lp5521@0x33 {
-				compatible = "lp5521";
-				reg = <0x33>;
-			};
+				db8500_vpll_reg: db8500_vpll {
+					regulator-name = "db8500-vpll";
+				};
 
-			lp5521@0x34 {
-				compatible = "lp5521";
-				reg = <0x34>;
-			};
+				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";
+				};
 
-			bh1780@0x29 {
-				compatible = "rohm,bh1780gli";
-				reg = <0x33>;
+				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";
+				};
 			};
-		};
 
-		sound {
-			compatible = "stericsson,snd-soc-mop500";
+			ab8500@5 {
+				ab8500-regulators {
+					ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
+						regulator-name = "V-DISPLAY";
+					};
 
-			stericsson,cpu-dai = <&msp1 &msp3>;
-			stericsson,audio-codec = <&codec>;
-		};
+					ab8500_ldo_aux2_reg: ab8500_ldo_aux2 {
+						regulator-name = "V-eMMC1";
+					};
 
-		msp1: msp@80124000 {
-			status = "okay";
-		};
+					ab8500_ldo_aux3_reg: ab8500_ldo_aux3 {
+						regulator-name = "V-MMC-SD";
+					};
 
-		msp3: msp@80125000 {
-			status = "okay";
+					ab8500_ldo_initcore_reg: ab8500_ldo_initcore {
+						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_amamic2_reg: ab8500_ldo_amamic2 {
+						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/imx23-olinuxino.dts b/arch/arm/boot/dts/imx23-olinuxino.dts
index 384d8b6..7c43b8e 100644
--- a/arch/arm/boot/dts/imx23-olinuxino.dts
+++ b/arch/arm/boot/dts/imx23-olinuxino.dts
@@ -40,6 +40,15 @@
 					reg = <0>;
 					fsl,pinmux-ids = <
 						0x2013 /* MX23_PAD_SSP1_DETECT__GPIO_2_1 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
+				led_pin_gpio0_17: led_gpio0_17@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
 						0x0113 /* MX23_PAD_GPMI_ALE__GPIO_0_17 */
 					>;
 					fsl,drive-strength = <0>;
@@ -47,6 +56,15 @@
 					fsl,pull-up = <0>;
 				};
 			};
+
+			ssp1: ssp@80034000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx23-spi";
+				pinctrl-names = "default";
+				pinctrl-0 = <&spi2_pins_a>;
+				status = "okay";
+			};
 		};
 
 		apbx@80040000 {
@@ -91,11 +109,12 @@
 
 	leds {
 		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pin_gpio0_17>;
 
 		user {
 			label = "green";
-			gpios = <&gpio2 1 0>;
-			linux,default-trigger = "default-on";
+			gpios = <&gpio2 1 1>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi
index 6d31aa3..65415c5 100644
--- a/arch/arm/boot/dts/imx23.dtsi
+++ b/arch/arm/boot/dts/imx23.dtsi
@@ -279,6 +279,19 @@
 					fsl,voltage = <1>;
 					fsl,pull-up = <0>;
 				};
+
+				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 */
+					>;
+					fsl,drive-strength = <1>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <1>;
+				};
 			};
 
 			digctl@8001c000 {
diff --git a/arch/arm/boot/dts/imx25-karo-tx25.dts b/arch/arm/boot/dts/imx25-karo-tx25.dts
new file mode 100644
index 0000000..d81f8a0
--- /dev/null
+++ b/arch/arm/boot/dts/imx25-karo-tx25.dts
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2012 Sascha Hauer, Pengutronix
+ *
+ * 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/ "imx25.dtsi"
+
+/ {
+	model = "Ka-Ro TX25";
+	compatible = "karo,imx25-tx25", "fsl,imx25";
+
+	memory {
+		reg = <0x80000000 0x02000000 0x90000000 0x02000000>;
+	};
+
+	soc {
+		aips@43f00000 {
+			uart1: serial@43f90000 {
+				status = "okay";
+			};
+		};
+
+		spba@50000000 {
+			fec: ethernet@50038000 {
+				status = "okay";
+				phy-mode = "rmii";
+			};
+		};
+
+		emi@80000000 {
+			nand@bb000000 {
+				nand-on-flash-bbt;
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi
new file mode 100644
index 0000000..e1b13eb
--- /dev/null
+++ b/arch/arm/boot/dts/imx25.dtsi
@@ -0,0 +1,515 @@
+/*
+ * Copyright 2012 Sascha Hauer, Pengutronix <s.hauer@pengutronix.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
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		serial3 = &uart4;
+		serial4 = &uart5;
+		gpio0 = &gpio1;
+		gpio1 = &gpio2;
+		gpio2 = &gpio3;
+		gpio3 = &gpio4;
+		usb0 = &usbotg;
+		usb1 = &usbhost1;
+	};
+
+	asic: asic-interrupt-controller@68000000 {
+		compatible = "fsl,imx25-asic", "fsl,avic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0x68000000 0x8000000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc {
+			compatible = "fsl,imx-osc", "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&asic>;
+		ranges;
+
+		aips@43f00000 { /* AIPS1 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x43f00000 0x100000>;
+			ranges;
+
+			i2c1: i2c@43f80000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx25-i2c", "fsl,imx21-i2c";
+				reg = <0x43f80000 0x4000>;
+				clocks = <&clks 48>;
+				clock-names = "";
+				interrupts = <3>;
+				status = "disabled";
+			};
+
+			i2c3: i2c@43f84000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx25-i2c", "fsl,imx21-i2c";
+				reg = <0x43f84000 0x4000>;
+				clocks = <&clks 48>;
+				clock-names = "";
+				interrupts = <10>;
+				status = "disabled";
+			};
+
+			can1: can@43f88000 {
+				compatible = "fsl,imx25-flexcan", "fsl,p1010-flexcan";
+				reg = <0x43f88000 0x4000>;
+				interrupts = <43>;
+				clocks = <&clks 75>, <&clks 75>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			can2: can@43f8c000 {
+				compatible = "fsl,imx25-flexcan", "fsl,p1010-flexcan";
+				reg = <0x43f8c000 0x4000>;
+				interrupts = <44>;
+				clocks = <&clks 76>, <&clks 76>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart1: serial@43f90000 {
+				compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+				reg = <0x43f90000 0x4000>;
+				interrupts = <45>;
+				clocks = <&clks 120>, <&clks 57>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart2: serial@43f94000 {
+				compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+				reg = <0x43f94000 0x4000>;
+				interrupts = <32>;
+				clocks = <&clks 121>, <&clks 57>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			i2c2: i2c@43f98000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx25-i2c", "fsl,imx21-i2c";
+				reg = <0x43f98000 0x4000>;
+				clocks = <&clks 48>;
+				clock-names = "";
+				interrupts = <4>;
+				status = "disabled";
+			};
+
+			owire@43f9c000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x43f9c000 0x4000>;
+				clocks = <&clks 51>;
+				clock-names = "";
+				interrupts = <2>;
+				status = "disabled";
+			};
+
+			spi1: cspi@43fa4000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx25-cspi", "fsl,imx35-cspi";
+				reg = <0x43fa4000 0x4000>;
+				clocks = <&clks 62>;
+				clock-names = "ipg";
+				interrupts = <14>;
+				status = "disabled";
+			};
+
+			kpp@43fa8000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x43fa8000 0x4000>;
+				clocks = <&clks 102>;
+				clock-names = "";
+				interrupts = <24>;
+				status = "disabled";
+			};
+
+			iomuxc@43fac000{
+				compatible = "fsl,imx25-iomuxc";
+				reg = <0x43fac000 0x4000>;
+			};
+
+			audmux@43fb0000 {
+				compatible = "fsl,imx25-audmux", "fsl,imx31-audmux";
+				reg = <0x43fb0000 0x4000>;
+				status = "disabled";
+			};
+		};
+
+		spba@50000000 {
+			compatible = "fsl,spba-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x50000000 0x40000>;
+			ranges;
+
+			spi3: cspi@50004000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx25-cspi", "fsl,imx35-cspi";
+				reg = <0x50004000 0x4000>;
+				interrupts = <0>;
+				clocks = <&clks 80>;
+				clock-names = "ipg";
+				status = "disabled";
+			};
+
+			uart4: serial@50008000 {
+				compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+				reg = <0x50008000 0x4000>;
+				interrupts = <5>;
+				clocks = <&clks 123>, <&clks 57>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			uart3: serial@5000c000 {
+				compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+				reg = <0x5000c000 0x4000>;
+				interrupts = <18>;
+				clocks = <&clks 122>, <&clks 57>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			spi2: cspi@50010000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx25-cspi", "fsl,imx35-cspi";
+				reg = <0x50010000 0x4000>;
+				clocks = <&clks 79>;
+				clock-names = "ipg";
+				interrupts = <13>;
+				status = "disabled";
+			};
+
+			ssi2: ssi@50014000 {
+				compatible = "fsl,imx25-ssi", "fsl,imx21-ssi";
+				reg = <0x50014000 0x4000>;
+				interrupts = <11>;
+				status = "disabled";
+			};
+
+			esai@50018000 {
+				reg = <0x50018000 0x4000>;
+				interrupts = <7>;
+			};
+
+			uart5: serial@5002c000 {
+				compatible = "fsl,imx25-uart", "fsl,imx21-uart";
+				reg = <0x5002c000 0x4000>;
+				interrupts = <40>;
+				clocks = <&clks 124>, <&clks 57>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			tsc: tsc@50030000 {
+				compatible = "fsl,imx25-adc", "fsl,imx21-tsc";
+				reg = <0x50030000 0x4000>;
+				interrupts = <46>;
+				clocks = <&clks 119>;
+				clock-names = "ipg";
+				status = "disabled";
+			};
+
+			ssi1: ssi@50034000 {
+				compatible = "fsl,imx25-ssi", "fsl,imx21-ssi";
+				reg = <0x50034000 0x4000>;
+				interrupts = <12>;
+				status = "disabled";
+			};
+
+			fec: ethernet@50038000 {
+				compatible = "fsl,imx25-fec";
+				reg = <0x50038000 0x4000>;
+				interrupts = <57>;
+				clocks = <&clks 88>, <&clks 65>;
+				clock-names = "ipg", "ahb";
+				status = "disabled";
+			};
+		};
+
+		aips@53f00000 { /* AIPS2 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x53f00000 0x100000>;
+			ranges;
+
+			clks: ccm@53f80000 {
+				compatible = "fsl,imx25-ccm";
+				reg = <0x53f80000 0x4000>;
+				interrupts = <31>;
+				#clock-cells = <1>;
+			};
+
+			gpt4: timer@53f84000 {
+				compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
+				reg = <0x53f84000 0x4000>;
+				clocks = <&clks 9>, <&clks 45>;
+				clock-names = "ipg", "per";
+				interrupts = <1>;
+			};
+
+			gpt3: timer@53f88000 {
+				compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
+				reg = <0x53f88000 0x4000>;
+				clocks = <&clks 9>, <&clks 47>;
+				clock-names = "ipg", "per";
+				interrupts = <29>;
+			};
+
+			gpt2: timer@53f8c000 {
+				compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
+				reg = <0x53f8c000 0x4000>;
+				clocks = <&clks 9>, <&clks 47>;
+				clock-names = "ipg", "per";
+				interrupts = <53>;
+			};
+
+			gpt1: timer@53f90000 {
+				compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
+				reg = <0x53f90000 0x4000>;
+				clocks = <&clks 9>, <&clks 47>;
+				clock-names = "ipg", "per";
+				interrupts = <54>;
+			};
+
+			epit1: timer@53f94000 {
+				compatible = "fsl,imx25-epit";
+				reg = <0x53f94000 0x4000>;
+				interrupts = <28>;
+			};
+
+			epit2: timer@53f98000 {
+				compatible = "fsl,imx25-epit";
+				reg = <0x53f98000 0x4000>;
+				interrupts = <27>;
+			};
+
+			gpio4: gpio@53f9c000 {
+				compatible = "fsl,imx25-gpio", "fsl,imx35-gpio";
+				reg = <0x53f9c000 0x4000>;
+				interrupts = <23>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			pwm2: pwm@53fa0000 {
+				compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
+				#pwm-cells = <2>;
+				reg = <0x53fa0000 0x4000>;
+				clocks = <&clks 106>, <&clks 36>;
+				clock-names = "ipg", "per";
+				interrupts = <36>;
+			};
+
+			gpio3: gpio@53fa4000 {
+				compatible = "fsl,imx25-gpio", "fsl,imx35-gpio";
+				reg = <0x53fa4000 0x4000>;
+				interrupts = <16>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			pwm3: pwm@53fa8000 {
+				compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
+				#pwm-cells = <2>;
+				reg = <0x53fa8000 0x4000>;
+				clocks = <&clks 107>, <&clks 36>;
+				clock-names = "ipg", "per";
+				interrupts = <41>;
+			};
+
+			esdhc1: esdhc@53fb4000 {
+				compatible = "fsl,imx25-esdhc";
+				reg = <0x53fb4000 0x4000>;
+				interrupts = <9>;
+				clocks = <&clks 86>, <&clks 63>, <&clks 45>;
+				clock-names = "ipg", "ahb", "per";
+				status = "disabled";
+			};
+
+			esdhc2: esdhc@53fb8000 {
+				compatible = "fsl,imx25-esdhc";
+				reg = <0x53fb8000 0x4000>;
+				interrupts = <8>;
+				clocks = <&clks 87>, <&clks 64>, <&clks 46>;
+				clock-names = "ipg", "ahb", "per";
+				status = "disabled";
+			};
+
+			lcdc@53fbc000 {
+				reg = <0x53fbc000 0x4000>;
+				interrupts = <39>;
+				clocks = <&clks 103>, <&clks 66>, <&clks 49>;
+				clock-names = "ipg", "ahb", "per";
+				status = "disabled";
+			};
+
+			slcdc@53fc0000 {
+				reg = <0x53fc0000 0x4000>;
+				interrupts = <38>;
+				status = "disabled";
+			};
+
+			pwm4: pwm@53fc8000 {
+				compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
+				reg = <0x53fc8000 0x4000>;
+				clocks = <&clks 108>, <&clks 36>;
+				clock-names = "ipg", "per";
+				interrupts = <42>;
+			};
+
+			gpio1: gpio@53fcc000 {
+				compatible = "fsl,imx25-gpio", "fsl,imx35-gpio";
+				reg = <0x53fcc000 0x4000>;
+				interrupts = <52>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio2: gpio@53fd0000 {
+				compatible = "fsl,imx25-gpio", "fsl,imx35-gpio";
+				reg = <0x53fd0000 0x4000>;
+				interrupts = <51>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			sdma@53fd4000 {
+				compatible = "fsl,imx25-sdma", "fsl,imx35-sdma";
+				reg = <0x53fd4000 0x4000>;
+				clocks = <&clks 112>, <&clks 68>;
+				clock-names = "ipg", "ahb";
+				interrupts = <34>;
+			};
+
+			wdog@53fdc000 {
+				compatible = "fsl,imx25-wdt", "fsl,imx21-wdt";
+				reg = <0x53fdc000 0x4000>;
+				clocks = <&clks 126>;
+				clock-names = "";
+				interrupts = <55>;
+			};
+
+			pwm1: pwm@53fe0000 {
+				compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
+				#pwm-cells = <2>;
+				reg = <0x53fe0000 0x4000>;
+				clocks = <&clks 105>, <&clks 36>;
+				clock-names = "ipg", "per";
+				interrupts = <26>;
+			};
+
+			usbphy1: usbphy@1 {
+				compatible = "nop-usbphy";
+				status = "disabled";
+			};
+
+			usbphy2: usbphy@2 {
+				compatible = "nop-usbphy";
+				status = "disabled";
+			};
+
+			usbotg: usb@53ff4000 {
+				compatible = "fsl,imx25-usb", "fsl,imx27-usb";
+				reg = <0x53ff4000 0x0200>;
+				interrupts = <37>;
+				clocks = <&clks 9>, <&clks 70>, <&clks 8>;
+				clock-names = "ipg", "ahb", "per";
+				fsl,usbmisc = <&usbmisc 0>;
+				status = "disabled";
+			};
+
+			usbhost1: usb@53ff4400 {
+				compatible = "fsl,imx25-usb", "fsl,imx27-usb";
+				reg = <0x53ff4400 0x0200>;
+				interrupts = <35>;
+				clocks = <&clks 9>, <&clks 70>, <&clks 8>;
+				clock-names = "ipg", "ahb", "per";
+				fsl,usbmisc = <&usbmisc 1>;
+				status = "disabled";
+			};
+
+			usbmisc: usbmisc@53ff4600 {
+				#index-cells = <1>;
+				compatible = "fsl,imx25-usbmisc";
+				clocks = <&clks 9>, <&clks 70>, <&clks 8>;
+				clock-names = "ipg", "ahb", "per";
+				reg = <0x53ff4600 0x00f>;
+				status = "disabled";
+			};
+
+			dryice@53ffc000 {
+				compatible = "fsl,imx25-dryice", "fsl,imx25-rtc";
+				reg = <0x53ffc000 0x4000>;
+				clocks = <&clks 81>;
+				clock-names = "ipg";
+				interrupts = <25>;
+			};
+		};
+
+		emi@80000000 {
+			compatible = "fsl,emi-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x80000000 0x3b002000>;
+			ranges;
+
+			nand@bb000000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+
+				compatible = "fsl,imx25-nand";
+				reg = <0xbb000000 0x2000>;
+				clocks = <&clks 50>;
+				clock-names = "";
+				interrupts = <33>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx27-3ds.dts b/arch/arm/boot/dts/imx27-3ds.dts
index 0a8978a..b01c0d7 100644
--- a/arch/arm/boot/dts/imx27-3ds.dts
+++ b/arch/arm/boot/dts/imx27-3ds.dts
@@ -23,10 +23,6 @@
 	soc {
 		aipi@10000000 { /* aipi */
 
-			wdog@10002000 {
-				status = "okay";
-			};
-
 			uart1: serial@1000a000 {
 				fsl,uart-has-rtscts;
 				status = "okay";
diff --git a/arch/arm/boot/dts/imx27-apf27.dts b/arch/arm/boot/dts/imx27-apf27.dts
new file mode 100644
index 0000000..c0327c0
--- /dev/null
+++ b/arch/arm/boot/dts/imx27-apf27.dts
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2012 Philippe Reynes <tremyfr@yahoo.fr>
+ * Copyright 2012 Armadeus Systems <support@armadeus.com>
+ *
+ * Based on code which is: Copyright 2012 Sascha Hauer, Pengutronix
+ *
+ * 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/ "imx27.dtsi"
+
+/ {
+	model = "Armadeus Systems APF27 module";
+	compatible = "armadeus,imx27-apf27", "fsl,imx27";
+
+	memory {
+		reg = <0xa0000000 0x04000000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc26m {
+			compatible = "fsl,imx-osc26m", "fixed-clock";
+			clock-frequency = <0>;
+		};
+	};
+
+	soc {
+		aipi@10000000 {
+			serial@1000a000 {
+				status = "okay";
+			};
+
+			ethernet@1002b000 {
+				status = "okay";
+			};
+		};
+
+		nand@d8000000 {
+			status = "okay";
+			nand-bus-width = <16>;
+			nand-ecc-mode = "hw";
+			nand-on-flash-bbt;
+
+			partition@0 {
+				label = "u-boot";
+				reg = <0x0 0x100000>;
+			};
+
+			partition@100000 {
+				label = "env";
+				reg = <0x100000 0x80000>;
+			};
+
+			partition@180000 {
+				label = "env2";
+				reg = <0x180000 0x80000>;
+			};
+
+			partition@200000 {
+				label = "firmware";
+				reg = <0x200000 0x80000>;
+			};
+
+			partition@280000 {
+				label = "dtb";
+				reg = <0x280000 0x80000>;
+			};
+
+			partition@300000 {
+				label = "kernel";
+				reg = <0x300000 0x500000>;
+			};
+
+			partition@800000 {
+				label = "rootfs";
+				reg = <0x800000 0xf800000>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi
index 3e54f14..b8d3905 100644
--- a/arch/arm/boot/dts/imx27.dtsi
+++ b/arch/arm/boot/dts/imx27.dtsi
@@ -58,7 +58,7 @@
 			reg = <0x10000000 0x10000000>;
 			ranges;
 
-			wdog@10002000 {
+			wdog: wdog@10002000 {
 				compatible = "fsl,imx27-wdt", "fsl,imx21-wdt";
 				reg = <0x10002000 0x4000>;
 				interrupts = <27>;
@@ -113,7 +113,7 @@
 			i2c1: i2c@10012000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
-				compatible = "fsl,imx27-i2c", "fsl,imx1-i2c";
+				compatible = "fsl,imx27-i2c", "fsl,imx21-i2c";
 				reg = <0x10012000 0x1000>;
 				interrupts = <12>;
 				status = "disabled";
@@ -205,7 +205,7 @@
 			i2c2: i2c@1001d000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
-				compatible = "fsl,imx27-i2c", "fsl,imx1-i2c";
+				compatible = "fsl,imx27-i2c", "fsl,imx21-i2c";
 				reg = <0x1001d000 0x1000>;
 				interrupts = <1>;
 				status = "disabled";
@@ -218,7 +218,8 @@
 				status = "disabled";
 			};
 		};
-		nand@d8000000 {
+
+		nfc: nand@d8000000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
 
diff --git a/arch/arm/boot/dts/imx28-apf28.dts b/arch/arm/boot/dts/imx28-apf28.dts
new file mode 100644
index 0000000..7eb0758
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-apf28.dts
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012 Armadeus Systems - <support@armadeus.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx28.dtsi"
+
+/ {
+	model = "Armadeus Systems APF28 module";
+	compatible = "armadeus,imx28-apf28", "fsl,imx28";
+
+	memory {
+		reg = <0x40000000 0x08000000>;
+	};
+
+	apb@80000000 {
+		apbh@80000000 {
+			gpmi-nand@8000c000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg>;
+				status = "okay";
+
+				partition@0 {
+					label = "u-boot";
+					reg = <0x0 0x300000>;
+				};
+
+				partition@300000 {
+					label = "env";
+					reg = <0x300000 0x80000>;
+				};
+
+				partition@380000 {
+					label = "env2";
+					reg = <0x380000 0x80000>;
+				};
+
+				partition@400000 {
+					label = "dtb";
+					reg = <0x400000 0x80000>;
+				};
+
+				partition@480000 {
+					label = "splash";
+					reg = <0x480000 0x80000>;
+				};
+
+				partition@500000 {
+					label = "kernel";
+					reg = <0x500000 0x800000>;
+				};
+
+				partition@d00000 {
+					label = "rootfs";
+					reg = <0xd00000 0xf300000>;
+				};
+			};
+		};
+
+		apbx@80040000 {
+			duart: serial@80074000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&duart_pins_a>;
+				status = "okay";
+			};
+		};
+	};
+
+	ahb@80080000 {
+		mac0: ethernet@800f0000 {
+			phy-mode = "rmii";
+			pinctrl-names = "default";
+			pinctrl-0 = <&mac0_pins_a>;
+			phy-reset-gpios = <&gpio4 13 0>;
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx28-apf28dev.dts b/arch/arm/boot/dts/imx28-apf28dev.dts
new file mode 100644
index 0000000..6d8865b
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-apf28dev.dts
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2012 Armadeus Systems - <support@armadeus.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/* APF28Dev is a docking board for the APF28 SOM */
+/include/ "imx28-apf28.dts"
+
+/ {
+	model = "Armadeus Systems APF28Dev docking/development board";
+	compatible = "armadeus,imx28-apf28dev", "armadeus,imx28-apf28", "fsl,imx28";
+
+	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";
+			};
+
+			ssp2: ssp@80014000 {
+				compatible = "fsl,imx28-spi";
+				pinctrl-names = "default";
+				pinctrl-0 = <&spi2_pins_a>;
+				status = "okay";
+			};
+
+			pinctrl@80018000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&hog_pins_apf28dev>;
+
+				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 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
+				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 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+			};
+
+			lcdif@80030000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&lcdif_16bit_pins_a
+						&lcdif_pins_apf28dev>;
+				status = "okay";
+			};
+		};
+
+		apbx@80040000 {
+			lradc@80050000 {
+				status = "okay";
+			};
+
+			i2c0: i2c@80058000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&i2c0_pins_a>;
+				status = "okay";
+			};
+
+			pwm: pwm@80064000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pwm3_pins_a &pwm4_pins_a>;
+				status = "okay";
+			};
+
+			usbphy0: usbphy@8007c000 {
+				status = "okay";
+			};
+
+			usbphy1: usbphy@8007e000 {
+				status = "okay";
+			};
+		};
+	};
+
+	ahb@80080000 {
+		usb0: usb@80080000 {
+			vbus-supply = <&reg_usb0_vbus>;
+			status = "okay";
+		};
+
+		usb1: usb@80090000 {
+			status = "okay";
+		};
+
+		mac1: ethernet@800f4000 {
+			phy-mode = "rmii";
+			pinctrl-names = "default";
+			pinctrl-0 = <&mac1_pins_a>;
+			phy-reset-gpios = <&gpio0 23 0>;
+			status = "okay";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_usb0_vbus: usb0_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb0_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio1 23 1>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		user {
+			label = "Heartbeat";
+			gpios = <&gpio0 21 0>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+
+		pwms = <&pwm 3 191000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
index c03a577..1594694 100644
--- a/arch/arm/boot/dts/imx28-cfa10036.dts
+++ b/arch/arm/boot/dts/imx28-cfa10036.dts
@@ -22,6 +22,31 @@
 
 	apb@80000000 {
 		apbh@80000000 {
+			pinctrl@80018000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&hog_pins_cfa10036>;
+
+				hog_pins_cfa10036: hog-10036@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x2073 /* MX28_PAD_SSP0_D7__GPIO_2_7 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
+				led_pins_cfa10036: leds-10036@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x3043 /* MX28_PAD_AUART1_RX__GPIO_3_4 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+			};
+
 			ssp0: ssp@80010000 {
 				compatible = "fsl,imx28-mmc";
 				pinctrl-names = "default";
@@ -33,16 +58,37 @@
 		};
 
 		apbx@80040000 {
+			pwm: pwm@80064000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pwm4_pins_a>;
+				status = "okay";
+			};
+
 			duart: serial@80074000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&duart_pins_b>;
 				status = "okay";
 			};
+
+			i2c0: i2c@80058000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&i2c0_pins_b>;
+				status = "okay";
+
+				ssd1307: oled@3c {
+					compatible = "solomon,ssd1307fb-i2c";
+					reg = <0x3c>;
+					pwms = <&pwm 4 3000>;
+					reset-gpios = <&gpio2 7 0>;
+				};
+			};
 		};
 	};
 
 	leds {
 		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pins_cfa10036>;
 
 		power {
 			gpios = <&gpio3 4 1>;
diff --git a/arch/arm/boot/dts/imx28-cfa10049.dts b/arch/arm/boot/dts/imx28-cfa10049.dts
index 05c892e..bdc80a4 100644
--- a/arch/arm/boot/dts/imx28-cfa10049.dts
+++ b/arch/arm/boot/dts/imx28-cfa10049.dts
@@ -22,6 +22,22 @@
 	apb@80000000 {
 		apbh@80000000 {
 			pinctrl@80018000 {
+				pinctrl-names = "default", "default";
+				pinctrl-1 = <&hog_pins_cfa10049>;
+
+				hog_pins_cfa10049: hog-10049@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */
+						0x1163 /* MX28_PAD_LCD_D22__GPIO_1_22 */
+						0x1173 /* MX28_PAD_LCD_D22__GPIO_1_23 */
+						0x2153 /* MX28_PAD_SSP2_D5__GPIO_2_21 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
 				spi3_pins_cfa10049: spi3-cfa10049@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
@@ -29,6 +45,7 @@
 						0x01c1 /* MX28_PAD_GPMI_RESETN__SSP3_CMD */
 						0x0111 /* MX28_PAD_GPMI_CE1N__SSP3_D3 */
 						0x01a2 /* MX28_PAD_GPMI_ALE__SSP3_D4 */
+						0x01b2 /* MX28_PAD_GPMI_CLE__SSP3_D5 */
 					>;
 					fsl,drive-strength = <1>;
 					fsl,voltage = <1>;
@@ -60,6 +77,11 @@
 					spi-max-frequency = <100000>;
 				};
 
+				dac0: dh2228@2 {
+					compatible = "rohm,dh2228fv";
+					reg = <2>;
+					spi-max-frequency = <100000>;
+				};
 			};
 		};
 
@@ -70,6 +92,30 @@
 				status = "okay";
 			};
 
+			i2cmux {
+				compatible = "i2c-mux-gpio";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				mux-gpios = <&gpio1 22 0 &gpio1 23 0>;
+				i2c-parent = <&i2c1>;
+
+				i2c@0 {
+					reg = <0>;
+				};
+
+				i2c@1 {
+					reg = <1>;
+				};
+
+				i2c@2 {
+					reg = <2>;
+				};
+
+				i2c@3 {
+					reg = <3>;
+				};
+			};
+
 			usbphy1: usbphy@8007e000 {
 				status = "okay";
 			};
@@ -96,4 +142,15 @@
 			gpio = <&gpio0 7 1>;
 		};
 	};
+
+	ahb@80080000 {
+		mac0: ethernet@800f0000 {
+			phy-mode = "rmii";
+			pinctrl-names = "default";
+			pinctrl-0 = <&mac0_pins_a>;
+			phy-reset-gpios = <&gpio2 21 0>;
+			phy-reset-duration = <100>;
+			status = "okay";
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts
index a0ad71c..2da316e 100644
--- a/arch/arm/boot/dts/imx28-evk.dts
+++ b/arch/arm/boot/dts/imx28-evk.dts
@@ -76,7 +76,6 @@
 						0x20c3 /* MX28_PAD_SSP1_SCK__GPIO_2_12 */
 						0x31c3 /* MX28_PAD_PWM3__GPIO_3_28 */
 						0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
-						0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
 						0x3083 /* MX28_PAD_AUART2_RX__GPIO_3_8 */
 						0x3093 /* MX28_PAD_AUART2_TX__GPIO_3_9 */
 					>;
@@ -85,6 +84,16 @@
 					fsl,pull-up = <0>;
 				};
 
+				led_pin_gpio3_5: led_gpio3_5@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
 				gpmi_pins_evk: gpmi-nand-evk@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
@@ -288,6 +297,8 @@
 
 	leds {
 		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pin_gpio3_5>;
 
 		user {
 			label = "Heartbeat";
diff --git a/arch/arm/boot/dts/imx28-sps1.dts b/arch/arm/boot/dts/imx28-sps1.dts
new file mode 100644
index 0000000..e6cde8a
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-sps1.dts
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2012 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 = "SchulerControl GmbH, SC SPS 1";
+	compatible = "schulercontrol,imx28-sps1", "fsl,imx28";
+
+	memory {
+		reg = <0x40000000 0x08000000>;
+	};
+
+	apb@80000000 {
+		apbh@80000000 {
+			pinctrl@80018000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&hog_pins_a>;
+
+				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 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
+			};
+
+			ssp0: ssp@80010000 {
+				compatible = "fsl,imx28-mmc";
+				pinctrl-names = "default";
+				pinctrl-0 = <&mmc0_4bit_pins_a>;
+				bus-width = <4>;
+				status = "okay";
+			};
+
+			ssp2: ssp@80014000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx28-spi";
+				pinctrl-names = "default";
+				pinctrl-0 = <&spi2_pins_a>;
+				status = "okay";
+
+				flash: m25p80@0 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "everspin,mr25h256", "mr25h256";
+					spi-max-frequency = <40000000>;
+					reg = <0>;
+				};
+			};
+		};
+
+		apbx@80040000 {
+			i2c0: i2c@80058000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&i2c0_pins_a>;
+				clock-frequency = <400000>;
+				status = "okay";
+
+				rtc: rtc@51 {
+					compatible = "nxp,pcf8563";
+					reg = <0x51>;
+				};
+
+				eeprom: eeprom@52 {
+					compatible = "atmel,24c64";
+					reg = <0x52>;
+					pagesize = <32>;
+				};
+			};
+
+			duart: serial@80074000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&duart_pins_a>;
+				status = "okay";
+			};
+
+			usbphy0: usbphy@8007c000 {
+				status = "okay";
+			};
+
+			auart0: serial@8006a000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&auart0_pins_a>;
+				status = "okay";
+			};
+		};
+	};
+
+	ahb@80080000 {
+		usb0: usb@80080000 {
+			vbus-supply = <&reg_usb0_vbus>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&usbphy0_pins_b>;
+			status = "okay";
+		};
+
+		mac0: ethernet@800f0000 {
+			phy-mode = "rmii";
+			pinctrl-names = "default";
+			pinctrl-0 = <&mac0_pins_a>;
+			status = "okay";
+		};
+
+		mac1: ethernet@800f4000 {
+			phy-mode = "rmii";
+			pinctrl-names = "default";
+			pinctrl-0 = <&mac1_pins_a>;
+			status = "okay";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_usb0_vbus: usb0_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb0_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 9 0>;
+		};
+	};
+
+	leds {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "gpio-leds";
+		status = "okay";
+
+		led@1 {
+			label = "sps1-1:yellow:user";
+			gpios = <&gpio0 6 0>;
+			linux,default-trigger = "heartbeat";
+			reg = <0>;
+		};
+
+		led@2 {
+			label = "sps1-2:red:user";
+			gpios = <&gpio0 3 0>;
+			linux,default-trigger = "heartbeat";
+			reg = <1>;
+		};
+
+		led@3 {
+			label = "sps1-3:red:user";
+			gpios = <&gpio0 0 0>;
+			default-trigger = "heartbeat";
+			reg = <2>;
+		};
+
+	};
+};
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 55c57ea..13b7053 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -492,6 +492,16 @@
 					fsl,pull-up = <0>;
 				};
 
+				pwm3_pins_a: pwm3@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x31c0 /* MX28_PAD_PWM3__PWM_3 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
 				pwm4_pins_a: pwm4@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
@@ -535,6 +545,31 @@
 					fsl,pull-up = <0>;
 				};
 
+				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 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
 				can0_pins_a: can0@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
@@ -799,6 +834,7 @@
 				compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 				reg = <0x8006a000 0x2000>;
 				interrupts = <112 70 71>;
+				fsl,auart-dma-channel = <8 9>;
 				clocks = <&clks 45>;
 				status = "disabled";
 			};
diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
index cbd2b1c..567e7ee 100644
--- a/arch/arm/boot/dts/imx51-babbage.dts
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -22,6 +22,22 @@
 	};
 
 	soc {
+		display@di0 {
+			compatible = "fsl,imx-parallel-display";
+			crtcs = <&ipu 0>;
+			interface-pix-fmt = "rgb24";
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_ipu_disp1_1>;
+		};
+
+		display@di1 {
+			compatible = "fsl,imx-parallel-display";
+			crtcs = <&ipu 1>;
+			interface-pix-fmt = "rgb565";
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_ipu_disp2_1>;
+		};
+
 		aips@70000000 { /* aips-1 */
 			spba@70000000 {
 				esdhc@70004000 { /* ESDHC1 */
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
index 75d069f..d4dad0d 100644
--- a/arch/arm/boot/dts/imx51.dtsi
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -62,6 +62,13 @@
 		interrupt-parent = <&tzic>;
 		ranges;
 
+		ipu: ipu@40000000 {
+			#crtc-cells = <1>;
+			compatible = "fsl,imx51-ipu";
+			reg = <0x40000000 0x20000000>;
+			interrupts = <11 10>;
+		};
+
 		aips@70000000 { /* AIPS1 */
 			compatible = "fsl,aips-bus", "simple-bus";
 			#address-cells = <1>;
@@ -76,17 +83,22 @@
 				reg = <0x70000000 0x40000>;
 				ranges;
 
-				esdhc@70004000 { /* ESDHC1 */
+				esdhc1: esdhc@70004000 {
 					compatible = "fsl,imx51-esdhc";
 					reg = <0x70004000 0x4000>;
 					interrupts = <1>;
+					clocks = <&clks 44>, <&clks 0>, <&clks 71>;
+					clock-names = "ipg", "ahb", "per";
 					status = "disabled";
 				};
 
-				esdhc@70008000 { /* ESDHC2 */
+				esdhc2: esdhc@70008000 {
 					compatible = "fsl,imx51-esdhc";
 					reg = <0x70008000 0x4000>;
 					interrupts = <2>;
+					bus-width = <4>;
+					clocks = <&clks 45>, <&clks 0>, <&clks 72>;
+					clock-names = "ipg", "ahb", "per";
 					status = "disabled";
 				};
 
@@ -94,15 +106,19 @@
 					compatible = "fsl,imx51-uart", "fsl,imx21-uart";
 					reg = <0x7000c000 0x4000>;
 					interrupts = <33>;
+					clocks = <&clks 32>, <&clks 33>;
+					clock-names = "ipg", "per";
 					status = "disabled";
 				};
 
-				ecspi@70010000 { /* ECSPI1 */
+				ecspi1: ecspi@70010000 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					compatible = "fsl,imx51-ecspi";
 					reg = <0x70010000 0x4000>;
 					interrupts = <36>;
+					clocks = <&clks 51>, <&clks 52>;
+					clock-names = "ipg", "per";
 					status = "disabled";
 				};
 
@@ -110,48 +126,55 @@
 					compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
 					reg = <0x70014000 0x4000>;
 					interrupts = <30>;
+					clocks = <&clks 49>;
 					fsl,fifo-depth = <15>;
 					fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
 					status = "disabled";
 				};
 
-				esdhc@70020000 { /* ESDHC3 */
+				esdhc3: esdhc@70020000 {
 					compatible = "fsl,imx51-esdhc";
 					reg = <0x70020000 0x4000>;
 					interrupts = <3>;
+					bus-width = <4>;
+					clocks = <&clks 46>, <&clks 0>, <&clks 73>;
+					clock-names = "ipg", "ahb", "per";
 					status = "disabled";
 				};
 
-				esdhc@70024000 { /* ESDHC4 */
+				esdhc4: esdhc@70024000 {
 					compatible = "fsl,imx51-esdhc";
 					reg = <0x70024000 0x4000>;
 					interrupts = <4>;
+					bus-width = <4>;
+					clocks = <&clks 47>, <&clks 0>, <&clks 74>;
+					clock-names = "ipg", "ahb", "per";
 					status = "disabled";
 				};
 			};
 
-			usb@73f80000 {
+			usbotg: usb@73f80000 {
 				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
 				reg = <0x73f80000 0x0200>;
 				interrupts = <18>;
 				status = "disabled";
 			};
 
-			usb@73f80200 {
+			usbh1: usb@73f80200 {
 				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
 				reg = <0x73f80200 0x0200>;
 				interrupts = <14>;
 				status = "disabled";
 			};
 
-			usb@73f80400 {
+			usbh2: usb@73f80400 {
 				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
 				reg = <0x73f80400 0x0200>;
 				interrupts = <16>;
 				status = "disabled";
 			};
 
-			usb@73f80600 {
+			usbh3: usb@73f80600 {
 				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
 				reg = <0x73f80600 0x0200>;
 				interrupts = <17>;
@@ -198,20 +221,22 @@
 				#interrupt-cells = <2>;
 			};
 
-			wdog@73f98000 { /* WDOG1 */
+			wdog1: wdog@73f98000 {
 				compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
 				reg = <0x73f98000 0x4000>;
 				interrupts = <58>;
+				clocks = <&clks 0>;
 			};
 
-			wdog@73f9c000 { /* WDOG2 */
+			wdog2: wdog@73f9c000 {
 				compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
 				reg = <0x73f9c000 0x4000>;
 				interrupts = <59>;
+				clocks = <&clks 0>;
 				status = "disabled";
 			};
 
-			iomuxc@73fa8000 {
+			iomuxc: iomuxc@73fa8000 {
 				compatible = "fsl,imx51-iomuxc";
 				reg = <0x73fa8000 0x4000>;
 
@@ -295,6 +320,66 @@
 					};
 				};
 
+				ipu_disp1 {
+					pinctrl_ipu_disp1_1: ipudisp1grp-1 {
+						fsl,pins = <
+							528 0x5 /* MX51_PAD_DISP1_DAT0__DISP1_DAT0 */
+							529 0x5 /* MX51_PAD_DISP1_DAT1__DISP1_DAT1 */
+							530 0x5 /* MX51_PAD_DISP1_DAT2__DISP1_DAT2 */
+							531 0x5 /* MX51_PAD_DISP1_DAT3__DISP1_DAT3 */
+							532 0x5 /* MX51_PAD_DISP1_DAT4__DISP1_DAT4 */
+							533 0x5 /* MX51_PAD_DISP1_DAT5__DISP1_DAT5 */
+							535 0x5 /* MX51_PAD_DISP1_DAT6__DISP1_DAT6 */
+							537 0x5 /* MX51_PAD_DISP1_DAT7__DISP1_DAT7 */
+							539 0x5 /* MX51_PAD_DISP1_DAT8__DISP1_DAT8 */
+							541 0x5 /* MX51_PAD_DISP1_DAT9__DISP1_DAT9 */
+							543 0x5 /* MX51_PAD_DISP1_DAT10__DISP1_DAT10 */
+							545 0x5 /* MX51_PAD_DISP1_DAT11__DISP1_DAT11 */
+							547 0x5 /* MX51_PAD_DISP1_DAT12__DISP1_DAT12 */
+							549 0x5 /* MX51_PAD_DISP1_DAT13__DISP1_DAT13 */
+							551 0x5 /* MX51_PAD_DISP1_DAT14__DISP1_DAT14 */
+							553 0x5 /* MX51_PAD_DISP1_DAT15__DISP1_DAT15 */
+							555 0x5 /* MX51_PAD_DISP1_DAT16__DISP1_DAT16 */
+							557 0x5 /* MX51_PAD_DISP1_DAT17__DISP1_DAT17 */
+							559 0x5 /* MX51_PAD_DISP1_DAT18__DISP1_DAT18 */
+							563 0x5 /* MX51_PAD_DISP1_DAT19__DISP1_DAT19 */
+							567 0x5 /* MX51_PAD_DISP1_DAT20__DISP1_DAT20 */
+							571 0x5 /* MX51_PAD_DISP1_DAT21__DISP1_DAT21 */
+							575 0x5 /* MX51_PAD_DISP1_DAT22__DISP1_DAT22 */
+							579 0x5 /* MX51_PAD_DISP1_DAT23__DISP1_DAT23 */
+							584 0x5 /* MX51_PAD_DI1_PIN2__DI1_PIN2 (hsync) */
+							583 0x5 /* MX51_PAD_DI1_PIN3__DI1_PIN3 (vsync) */
+						>;
+					};
+				};
+
+				ipu_disp2 {
+					pinctrl_ipu_disp2_1: ipudisp2grp-1 {
+						fsl,pins = <
+							603 0x5 /* MX51_PAD_DISP2_DAT0__DISP2_DAT0 */
+							608 0x5 /* MX51_PAD_DISP2_DAT1__DISP2_DAT1 */
+							613 0x5 /* MX51_PAD_DISP2_DAT2__DISP2_DAT2 */
+							614 0x5 /* MX51_PAD_DISP2_DAT3__DISP2_DAT3 */
+							615 0x5 /* MX51_PAD_DISP2_DAT4__DISP2_DAT4 */
+							616 0x5 /* MX51_PAD_DISP2_DAT5__DISP2_DAT5 */
+							617 0x5 /* MX51_PAD_DISP2_DAT6__DISP2_DAT6 */
+							622 0x5 /* MX51_PAD_DISP2_DAT7__DISP2_DAT7 */
+							627 0x5 /* MX51_PAD_DISP2_DAT8__DISP2_DAT8 */
+							633 0x5 /* MX51_PAD_DISP2_DAT9__DISP2_DAT9 */
+							637 0x5 /* MX51_PAD_DISP2_DAT10__DISP2_DAT10 */
+							643 0x5 /* MX51_PAD_DISP2_DAT11__DISP2_DAT11 */
+							648 0x5 /* MX51_PAD_DISP2_DAT12__DISP2_DAT12 */
+							652 0x5 /* MX51_PAD_DISP2_DAT13__DISP2_DAT13 */
+							656 0x5 /* MX51_PAD_DISP2_DAT14__DISP2_DAT14 */
+							661 0x5 /* MX51_PAD_DISP2_DAT15__DISP2_DAT15 */
+							593 0x5 /* MX51_PAD_DI2_PIN2__DI2_PIN2 (hsync) */
+							595 0x5 /* MX51_PAD_DI2_PIN3__DI2_PIN3 (vsync) */
+							597 0x5 /* MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK */
+							599 0x5 /* MX51_PAD_DI_GP4__DI2_PIN15 */
+						>;
+					};
+				};
+
 				uart1 {
 					pinctrl_uart1_1: uart1grp-1 {
 						fsl,pins = <
@@ -327,10 +412,30 @@
 				};
 			};
 
+			pwm1: pwm@73fb4000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx51-pwm", "fsl,imx27-pwm";
+				reg = <0x73fb4000 0x4000>;
+				clocks = <&clks 37>, <&clks 38>;
+				clock-names = "ipg", "per";
+				interrupts = <61>;
+			};
+
+			pwm2: pwm@73fb8000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx51-pwm", "fsl,imx27-pwm";
+				reg = <0x73fb8000 0x4000>;
+				clocks = <&clks 39>, <&clks 40>;
+				clock-names = "ipg", "per";
+				interrupts = <94>;
+			};
+
 			uart1: serial@73fbc000 {
 				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
 				reg = <0x73fbc000 0x4000>;
 				interrupts = <31>;
+				clocks = <&clks 28>, <&clks 29>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
@@ -338,8 +443,17 @@
 				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
 				reg = <0x73fc0000 0x4000>;
 				interrupts = <32>;
+				clocks = <&clks 30>, <&clks 31>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
+
+			clks: ccm@73fd4000{
+				compatible = "fsl,imx51-ccm";
+				reg = <0x73fd4000 0x4000>;
+				interrupts = <0 71 0x04 0 72 0x04>;
+				#clock-cells = <1>;
+			};
 		};
 
 		aips@80000000 {	/* AIPS2 */
@@ -349,46 +463,54 @@
 			reg = <0x80000000 0x10000000>;
 			ranges;
 
-			ecspi@83fac000 { /* ECSPI2 */
+			ecspi2: ecspi@83fac000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				compatible = "fsl,imx51-ecspi";
 				reg = <0x83fac000 0x4000>;
 				interrupts = <37>;
+				clocks = <&clks 53>, <&clks 54>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
-			sdma@83fb0000 {
+			sdma: sdma@83fb0000 {
 				compatible = "fsl,imx51-sdma", "fsl,imx35-sdma";
 				reg = <0x83fb0000 0x4000>;
 				interrupts = <6>;
+				clocks = <&clks 56>, <&clks 56>;
+				clock-names = "ipg", "ahb";
 				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx51.bin";
 			};
 
-			cspi@83fc0000 {
+			cspi: cspi@83fc0000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				compatible = "fsl,imx51-cspi", "fsl,imx35-cspi";
 				reg = <0x83fc0000 0x4000>;
 				interrupts = <38>;
+				clocks = <&clks 55>, <&clks 0>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
-			i2c@83fc4000 { /* I2C2 */
+			i2c2: i2c@83fc4000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
-				compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+				compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
 				reg = <0x83fc4000 0x4000>;
 				interrupts = <63>;
+				clocks = <&clks 35>;
 				status = "disabled";
 			};
 
-			i2c@83fc8000 { /* I2C1 */
+			i2c1: i2c@83fc8000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
-				compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+				compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
 				reg = <0x83fc8000 0x4000>;
 				interrupts = <62>;
+				clocks = <&clks 34>;
 				status = "disabled";
 			};
 
@@ -396,21 +518,23 @@
 				compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
 				reg = <0x83fcc000 0x4000>;
 				interrupts = <29>;
+				clocks = <&clks 48>;
 				fsl,fifo-depth = <15>;
 				fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */
 				status = "disabled";
 			};
 
-			audmux@83fd0000 {
+			audmux: audmux@83fd0000 {
 				compatible = "fsl,imx51-audmux", "fsl,imx31-audmux";
 				reg = <0x83fd0000 0x4000>;
 				status = "disabled";
 			};
 
-			nand@83fdb000 {
+			nfc: nand@83fdb000 {
 				compatible = "fsl,imx51-nand";
 				reg = <0x83fdb000 0x1000 0xcfff0000 0x10000>;
 				interrupts = <8>;
+				clocks = <&clks 60>;
 				status = "disabled";
 			};
 
@@ -418,15 +542,18 @@
 				compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
 				reg = <0x83fe8000 0x4000>;
 				interrupts = <96>;
+				clocks = <&clks 50>;
 				fsl,fifo-depth = <15>;
 				fsl,ssi-dma-events = <47 46 37 35>; /* TX0 RX0 TX1 RX1 */
 				status = "disabled";
 			};
 
-			ethernet@83fec000 {
+			fec: ethernet@83fec000 {
 				compatible = "fsl,imx51-fec", "fsl,imx27-fec";
 				reg = <0x83fec000 0x4000>;
 				interrupts = <87>;
+				clocks = <&clks 42>, <&clks 42>, <&clks 42>;
+				clock-names = "ipg", "ahb", "ptp";
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/boot/dts/imx53-qsb.dts b/arch/arm/boot/dts/imx53-qsb.dts
index 08948af..b007553 100644
--- a/arch/arm/boot/dts/imx53-qsb.dts
+++ b/arch/arm/boot/dts/imx53-qsb.dts
@@ -60,10 +60,17 @@
 							697  0x80000000	/* MX53_PAD_EIM_DA12__GPIO3_12 */
 							701  0x80000000	/* MX53_PAD_EIM_DA13__GPIO3_13 */
 							868  0x80000000	/* MX53_PAD_PATA_DA_0__GPIO7_6 */
+							1149 0x80000000 /* MX53_PAD_GPIO_16__GPIO7_11 */
+						>;
+					};
+
+					led_pin_gpio7_7: led_gpio7_7@0 {
+						fsl,pins = <
 							873  0x80000000	/* MX53_PAD_PATA_DA_1__GPIO7_7 */
 						>;
 					};
 				};
+
 			};
 
 			uart1: serial@53fbc000 {
@@ -100,76 +107,93 @@
 				pmic: dialog@48 {
 					compatible = "dlg,da9053-aa", "dlg,da9052";
 					reg = <0x48>;
+					interrupt-parent = <&gpio7>;
+					interrupts = <11 0x8>; /* low-level active IRQ at GPIO7_11 */
 
 					regulators {
-						buck0 {
+						buck1_reg: buck1 {
 							regulator-min-microvolt = <500000>;
 							regulator-max-microvolt = <2075000>;
+							regulator-always-on;
 						};
 
-						buck1 {
+						buck2_reg: buck2 {
 							regulator-min-microvolt = <500000>;
 							regulator-max-microvolt = <2075000>;
+							regulator-always-on;
 						};
 
-						buck2 {
+						buck3_reg: buck3 {
 							regulator-min-microvolt = <925000>;
 					                regulator-max-microvolt = <2500000>;
+							regulator-always-on;
 						};
 
-						buck3 {
+						buck4_reg: buck4 {
 							regulator-min-microvolt = <925000>;
 					                regulator-max-microvolt = <2500000>;
+							regulator-always-on;
 						};
 
-						ldo4 {
+						ldo1_reg: ldo1 {
 							regulator-min-microvolt = <600000>;
 							regulator-max-microvolt = <1800000>;
+							regulator-boot-on;
+							regulator-always-on;
 						};
 
-						ldo5 {
+						ldo2_reg: ldo2 {
+							regulator-min-microvolt = <600000>;
+							regulator-max-microvolt = <1800000>;
+							regulator-always-on;
+						};
+
+						ldo3_reg: ldo3 {
 							regulator-min-microvolt = <600000>;
 					                regulator-max-microvolt = <1800000>;
+							regulator-always-on;
 						};
 
-						ldo6 {
+						ldo4_reg: ldo4 {
 							regulator-min-microvolt = <1725000>;
 					                regulator-max-microvolt = <3300000>;
+							regulator-always-on;
 						};
 
-						ldo7 {
+						ldo5_reg: ldo5 {
 							regulator-min-microvolt = <1725000>;
 					                regulator-max-microvolt = <3300000>;
+							regulator-always-on;
 						};
 
-						ldo8 {
+						ldo6_reg: ldo6 {
 							regulator-min-microvolt = <1200000>;
 					                regulator-max-microvolt = <3600000>;
+							regulator-always-on;
 						};
 
-						ldo9 {
+						ldo7_reg: ldo7 {
 							regulator-min-microvolt = <1200000>;
 					                regulator-max-microvolt = <3600000>;
+							regulator-always-on;
 						};
 
-						ldo10 {
+						ldo8_reg: ldo8 {
 							regulator-min-microvolt = <1200000>;
 					                regulator-max-microvolt = <3600000>;
+							regulator-always-on;
 						};
 
-						ldo11 {
+						ldo9_reg: ldo9 {
 							regulator-min-microvolt = <1200000>;
 					                regulator-max-microvolt = <3600000>;
+							regulator-always-on;
 						};
 
-						ldo12 {
+						ldo10_reg: ldo10 {
 							regulator-min-microvolt = <1250000>;
 					                regulator-max-microvolt = <3650000>;
-						};
-
-						ldo13 {
-							regulator-min-microvolt = <1200000>;
-					                regulator-max-microvolt = <3600000>;
+							regulator-always-on;
 						};
 					};
 				};
@@ -216,6 +240,8 @@
 
 	leds {
 		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pin_gpio7_7>;
 
 		user {
 			label = "Heartbeat";
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
index 76ebb1a..e315cfc 100644
--- a/arch/arm/boot/dts/imx53.dtsi
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -67,6 +67,13 @@
 		interrupt-parent = <&tzic>;
 		ranges;
 
+		ipu: ipu@18000000 {
+			#crtc-cells = <1>;
+			compatible = "fsl,imx53-ipu";
+			reg = <0x18000000 0x080000000>;
+			interrupts = <11 10>;
+		};
+
 		aips@50000000 { /* AIPS1 */
 			compatible = "fsl,aips-bus", "simple-bus";
 			#address-cells = <1>;
@@ -81,17 +88,23 @@
 				reg = <0x50000000 0x40000>;
 				ranges;
 
-				esdhc@50004000 { /* ESDHC1 */
+				esdhc1: esdhc@50004000 {
 					compatible = "fsl,imx53-esdhc";
 					reg = <0x50004000 0x4000>;
 					interrupts = <1>;
+					bus-width = <4>;
+					clocks = <&clks 44>, <&clks 0>, <&clks 71>;
+					clock-names = "ipg", "ahb", "per";
 					status = "disabled";
 				};
 
-				esdhc@50008000 { /* ESDHC2 */
+				esdhc2: esdhc@50008000 {
 					compatible = "fsl,imx53-esdhc";
 					reg = <0x50008000 0x4000>;
 					interrupts = <2>;
+					bus-width = <4>;
+					clocks = <&clks 45>, <&clks 0>, <&clks 72>;
+					clock-names = "ipg", "ahb", "per";
 					status = "disabled";
 				};
 
@@ -99,15 +112,19 @@
 					compatible = "fsl,imx53-uart", "fsl,imx21-uart";
 					reg = <0x5000c000 0x4000>;
 					interrupts = <33>;
+					clocks = <&clks 32>, <&clks 33>;
+					clock-names = "ipg", "per";
 					status = "disabled";
 				};
 
-				ecspi@50010000 { /* ECSPI1 */
+				ecspi1: ecspi@50010000 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
 					reg = <0x50010000 0x4000>;
 					interrupts = <36>;
+					clocks = <&clks 51>, <&clks 52>;
+					clock-names = "ipg", "per";
 					status = "disabled";
 				};
 
@@ -115,48 +132,55 @@
 					compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
 					reg = <0x50014000 0x4000>;
 					interrupts = <30>;
+					clocks = <&clks 49>;
 					fsl,fifo-depth = <15>;
 					fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
 					status = "disabled";
 				};
 
-				esdhc@50020000 { /* ESDHC3 */
+				esdhc3: esdhc@50020000 {
 					compatible = "fsl,imx53-esdhc";
 					reg = <0x50020000 0x4000>;
 					interrupts = <3>;
+					bus-width = <4>;
+					clocks = <&clks 46>, <&clks 0>, <&clks 73>;
+					clock-names = "ipg", "ahb", "per";
 					status = "disabled";
 				};
 
-				esdhc@50024000 { /* ESDHC4 */
+				esdhc4: esdhc@50024000 {
 					compatible = "fsl,imx53-esdhc";
 					reg = <0x50024000 0x4000>;
 					interrupts = <4>;
+					bus-width = <4>;
+					clocks = <&clks 47>, <&clks 0>, <&clks 74>;
+					clock-names = "ipg", "ahb", "per";
 					status = "disabled";
 				};
 			};
 
-			usb@53f80000 {
+			usbotg: usb@53f80000 {
 				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
 				reg = <0x53f80000 0x0200>;
 				interrupts = <18>;
 				status = "disabled";
 			};
 
-			usb@53f80200 {
+			usbh1: usb@53f80200 {
 				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
 				reg = <0x53f80200 0x0200>;
 				interrupts = <14>;
 				status = "disabled";
 			};
 
-			usb@53f80400 {
+			usbh2: usb@53f80400 {
 				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
 				reg = <0x53f80400 0x0200>;
 				interrupts = <16>;
 				status = "disabled";
 			};
 
-			usb@53f80600 {
+			usbh3: usb@53f80600 {
 				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
 				reg = <0x53f80600 0x0200>;
 				interrupts = <17>;
@@ -203,20 +227,22 @@
 				#interrupt-cells = <2>;
 			};
 
-			wdog@53f98000 { /* WDOG1 */
+			wdog1: wdog@53f98000 {
 				compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
 				reg = <0x53f98000 0x4000>;
 				interrupts = <58>;
+				clocks = <&clks 0>;
 			};
 
-			wdog@53f9c000 { /* WDOG2 */
+			wdog2: wdog@53f9c000 {
 				compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
 				reg = <0x53f9c000 0x4000>;
 				interrupts = <59>;
+				clocks = <&clks 0>;
 				status = "disabled";
 			};
 
-			iomuxc@53fa8000 {
+			iomuxc: iomuxc@53fa8000 {
 				compatible = "fsl,imx53-iomuxc";
 				reg = <0x53fa8000 0x4000>;
 
@@ -316,6 +342,24 @@
 					};
 				};
 
+				can1 {
+					pinctrl_can1_1: can1grp-1 {
+						fsl,pins = <
+							847 0x80000000  /* MX53_PAD_PATA_INTRQ__CAN1_TXCAN */
+							853 0x80000000  /* MX53_PAD_PATA_DIOR__CAN1_RXCAN */
+						>;
+					};
+				};
+
+				can2 {
+					pinctrl_can2_1: can2grp-1 {
+						fsl,pins = <
+							67  0x80000000  /* MX53_PAD_KEY_COL4__CAN2_TXCAN */
+							74  0x80000000  /* MX53_PAD_KEY_ROW4__CAN2_RXCAN */
+						>;
+					};
+				};
+
 				i2c1 {
 					pinctrl_i2c1_1: i2c1grp-1 {
 						fsl,pins = <
@@ -334,6 +378,15 @@
 					};
 				};
 
+				i2c3 {
+					pinctrl_i2c3_1: i2c3grp-1 {
+						fsl,pins = <
+							1102 0xc0000000	/* MX53_PAD_GPIO_6__I2C3_SDA */
+							1130 0xc0000000	/* MX53_PAD_GPIO_5__I2C3_SCL */
+						>;
+					};
+				};
+
 				uart1 {
 					pinctrl_uart1_1: uart1grp-1 {
 						fsl,pins = <
@@ -369,12 +422,51 @@
 						>;
 					};
 				};
+
+				uart4 {
+					pinctrl_uart4_1: uart4grp-1 {
+						fsl,pins = <
+							11 0x1c5	/* MX53_PAD_KEY_COL0__UART4_TXD_MUX */
+							18 0x1c5	/* MX53_PAD_KEY_ROW0__UART4_RXD_MUX */
+						>;
+					};
+				};
+
+				uart5 {
+					pinctrl_uart5_1: uart5grp-1 {
+						fsl,pins = <
+							24 0x1c5	/* MX53_PAD_KEY_COL1__UART5_TXD_MUX */
+							31 0x1c5	/* MX53_PAD_KEY_ROW1__UART5_RXD_MUX */
+						>;
+					};
+				};
+
+			};
+
+			pwm1: pwm@53fb4000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
+				reg = <0x53fb4000 0x4000>;
+				clocks = <&clks 37>, <&clks 38>;
+				clock-names = "ipg", "per";
+				interrupts = <61>;
+			};
+
+			pwm2: pwm@53fb8000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
+				reg = <0x53fb8000 0x4000>;
+				clocks = <&clks 39>, <&clks 40>;
+				clock-names = "ipg", "per";
+				interrupts = <94>;
 			};
 
 			uart1: serial@53fbc000 {
 				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
 				reg = <0x53fbc000 0x4000>;
 				interrupts = <31>;
+				clocks = <&clks 28>, <&clks 29>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
@@ -382,6 +474,8 @@
 				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
 				reg = <0x53fc0000 0x4000>;
 				interrupts = <32>;
+				clocks = <&clks 30>, <&clks 31>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
@@ -389,6 +483,8 @@
 				compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
 				reg = <0x53fc8000 0x4000>;
 				interrupts = <82>;
+				clocks = <&clks 158>, <&clks 157>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
@@ -396,9 +492,18 @@
 				compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
 				reg = <0x53fcc000 0x4000>;
 				interrupts = <83>;
+				clocks = <&clks 158>, <&clks 157>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
+			clks: ccm@53fd4000{
+				compatible = "fsl,imx53-ccm";
+				reg = <0x53fd4000 0x4000>;
+				interrupts = <0 71 0x04 0 72 0x04>;
+				#clock-cells = <1>;
+			};
+
 			gpio5: gpio@53fdc000 {
 				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
 				reg = <0x53fdc000 0x4000>;
@@ -429,12 +534,13 @@
 				#interrupt-cells = <2>;
 			};
 
-			i2c@53fec000 { /* I2C3 */
+			i2c3: i2c@53fec000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
-				compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+				compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
 				reg = <0x53fec000 0x4000>;
 				interrupts = <64>;
+				clocks = <&clks 88>;
 				status = "disabled";
 			};
 
@@ -442,6 +548,8 @@
 				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
 				reg = <0x53ff0000 0x4000>;
 				interrupts = <13>;
+				clocks = <&clks 65>, <&clks 66>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 		};
@@ -457,49 +565,59 @@
 				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
 				reg = <0x63f90000 0x4000>;
 				interrupts = <86>;
+				clocks = <&clks 67>, <&clks 68>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
-			ecspi@63fac000 { /* ECSPI2 */
+			ecspi2: ecspi@63fac000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
 				reg = <0x63fac000 0x4000>;
 				interrupts = <37>;
+				clocks = <&clks 53>, <&clks 54>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
-			sdma@63fb0000 {
+			sdma: sdma@63fb0000 {
 				compatible = "fsl,imx53-sdma", "fsl,imx35-sdma";
 				reg = <0x63fb0000 0x4000>;
 				interrupts = <6>;
+				clocks = <&clks 56>, <&clks 56>;
+				clock-names = "ipg", "ahb";
 				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
 			};
 
-			cspi@63fc0000 {
+			cspi: cspi@63fc0000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				compatible = "fsl,imx53-cspi", "fsl,imx35-cspi";
 				reg = <0x63fc0000 0x4000>;
 				interrupts = <38>;
+				clocks = <&clks 55>, <&clks 0>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
-			i2c@63fc4000 { /* I2C2 */
+			i2c2: i2c@63fc4000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
-				compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+				compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
 				reg = <0x63fc4000 0x4000>;
 				interrupts = <63>;
+				clocks = <&clks 35>;
 				status = "disabled";
 			};
 
-			i2c@63fc8000 { /* I2C1 */
+			i2c1: i2c@63fc8000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
-				compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+				compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
 				reg = <0x63fc8000 0x4000>;
 				interrupts = <62>;
+				clocks = <&clks 34>;
 				status = "disabled";
 			};
 
@@ -507,21 +625,23 @@
 				compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
 				reg = <0x63fcc000 0x4000>;
 				interrupts = <29>;
+				clocks = <&clks 48>;
 				fsl,fifo-depth = <15>;
 				fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */
 				status = "disabled";
 			};
 
-			audmux@63fd0000 {
+			audmux: audmux@63fd0000 {
 				compatible = "fsl,imx53-audmux", "fsl,imx31-audmux";
 				reg = <0x63fd0000 0x4000>;
 				status = "disabled";
 			};
 
-			nand@63fdb000 {
+			nfc: nand@63fdb000 {
 				compatible = "fsl,imx53-nand";
 				reg = <0x63fdb000 0x1000 0xf7ff0000 0x10000>;
 				interrupts = <8>;
+				clocks = <&clks 60>;
 				status = "disabled";
 			};
 
@@ -529,15 +649,18 @@
 				compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
 				reg = <0x63fe8000 0x4000>;
 				interrupts = <96>;
+				clocks = <&clks 50>;
 				fsl,fifo-depth = <15>;
 				fsl,ssi-dma-events = <47 46 45 44>; /* TX0 RX0 TX1 RX1 */
 				status = "disabled";
 			};
 
-			ethernet@63fec000 {
+			fec: ethernet@63fec000 {
 				compatible = "fsl,imx53-fec", "fsl,imx25-fec";
 				reg = <0x63fec000 0x4000>;
 				interrupts = <87>;
+				clocks = <&clks 42>, <&clks 42>, <&clks 42>;
+				clock-names = "ipg", "ahb", "ptp";
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/boot/dts/imx6q-sabreauto.dts b/arch/arm/boot/dts/imx6q-sabreauto.dts
new file mode 100644
index 0000000..826e4ad
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabreauto.dts
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx6q.dtsi"
+
+/ {
+	model = "Freescale i.MX6 Quad SABRE Automotive Board";
+	compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
+
+	memory {
+		reg = <0x10000000 0x80000000>;
+	};
+
+	soc {
+		aips-bus@02000000 { /* AIPS1 */
+			iomuxc@020e0000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_hog>;
+
+				hog {
+					pinctrl_hog: hoggrp {
+						fsl,pins = <
+							1376 0x80000000	/* MX6Q_PAD_NANDF_CS2__GPIO_6_15 */
+							13   0x80000000	/* MX6Q_PAD_SD2_DAT2__GPIO_1_13 */
+						>;
+					};
+				};
+			};
+		};
+
+		aips-bus@02100000 { /* AIPS2 */
+			uart4: serial@021f0000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart4_1>;
+				status = "okay";
+			};
+
+			ethernet@02188000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_enet_2>;
+				phy-mode = "rgmii";
+				status = "okay";
+			};
+
+			usdhc@02198000 { /* uSDHC3 */
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usdhc3_1>;
+				cd-gpios = <&gpio6 15 0>;
+				wp-gpios = <&gpio1 13 0>;
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx6q-sabresd.dts b/arch/arm/boot/dts/imx6q-sabresd.dts
index e596c28c..a424025 100644
--- a/arch/arm/boot/dts/imx6q-sabresd.dts
+++ b/arch/arm/boot/dts/imx6q-sabresd.dts
@@ -38,6 +38,8 @@
 				hog {
 					pinctrl_hog: hoggrp {
 						fsl,pins = <
+							1004 0x80000000 /* MX6Q_PAD_GPIO_4__GPIO_1_4 */
+							1012 0x80000000 /* MX6Q_PAD_GPIO_5__GPIO_1_5 */
 							1402 0x80000000	/* MX6Q_PAD_NANDF_D0__GPIO_2_0 */
 							1410 0x80000000	/* MX6Q_PAD_NANDF_D1__GPIO_2_1 */
 							1418 0x80000000	/* MX6Q_PAD_NANDF_D2__GPIO_2_2 */
@@ -73,4 +75,20 @@
 			};
 		};
 	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio1 4 0>;
+			linux,code = <115>; /* KEY_VOLUMEUP */
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio1 5 0>;
+			linux,code = <114>; /* KEY_VOLUMEDOWN */
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index f3990b0..d6265ca 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -36,6 +36,14 @@
 			compatible = "arm,cortex-a9";
 			reg = <0>;
 			next-level-cache = <&L2>;
+			operating-points = <
+				/* kHz    uV */
+				792000  1100000
+				396000  950000
+				198000  850000
+			>;
+			clock-latency = <61036>; /* two CLK32 periods */
+			cpu0-supply = <&reg_cpu>;
 		};
 
 		cpu@1 {
@@ -100,7 +108,7 @@
 			clocks = <&clks 106>;
 		};
 
-		gpmi-nand@00112000 {
+		nfc: gpmi-nand@00112000 {
 			compatible = "fsl,imx6q-gpmi-nand";
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -144,12 +152,12 @@
 				reg = <0x02000000 0x40000>;
 				ranges;
 
-				spdif@02004000 {
+				spdif: spdif@02004000 {
 					reg = <0x02004000 0x4000>;
 					interrupts = <0 52 0x04>;
 				};
 
-				ecspi@02008000 { /* eCSPI1 */
+				ecspi1: ecspi@02008000 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
@@ -160,7 +168,7 @@
 					status = "disabled";
 				};
 
-				ecspi@0200c000 { /* eCSPI2 */
+				ecspi2: ecspi@0200c000 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
@@ -171,7 +179,7 @@
 					status = "disabled";
 				};
 
-				ecspi@02010000 { /* eCSPI3 */
+				ecspi3: ecspi@02010000 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
@@ -182,7 +190,7 @@
 					status = "disabled";
 				};
 
-				ecspi@02014000 { /* eCSPI4 */
+				ecspi4: ecspi@02014000 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
@@ -193,7 +201,7 @@
 					status = "disabled";
 				};
 
-				ecspi@02018000 { /* eCSPI5 */
+				ecspi5: ecspi@02018000 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
@@ -213,7 +221,7 @@
 					status = "disabled";
 				};
 
-				esai@02024000 {
+				esai: esai@02024000 {
 					reg = <0x02024000 0x4000>;
 					interrupts = <0 51 0x04>;
 				};
@@ -248,7 +256,7 @@
 					status = "disabled";
 				};
 
-				asrc@02034000 {
+				asrc: asrc@02034000 {
 					reg = <0x02034000 0x4000>;
 					interrupts = <0 50 0x04>;
 				};
@@ -258,7 +266,7 @@
 				};
 			};
 
-			vpu@02040000 {
+			vpu: vpu@02040000 {
 				reg = <0x02040000 0x3c000>;
 				interrupts = <0 3 0x04 0 12 0x04>;
 			};
@@ -267,37 +275,53 @@
 				reg = <0x0207c000 0x4000>;
 			};
 
-			pwm@02080000 { /* PWM1 */
+			pwm1: pwm@02080000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
 				reg = <0x02080000 0x4000>;
 				interrupts = <0 83 0x04>;
+				clocks = <&clks 62>, <&clks 145>;
+				clock-names = "ipg", "per";
 			};
 
-			pwm@02084000 { /* PWM2 */
+			pwm2: pwm@02084000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
 				reg = <0x02084000 0x4000>;
 				interrupts = <0 84 0x04>;
+				clocks = <&clks 62>, <&clks 146>;
+				clock-names = "ipg", "per";
 			};
 
-			pwm@02088000 { /* PWM3 */
+			pwm3: pwm@02088000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
 				reg = <0x02088000 0x4000>;
 				interrupts = <0 85 0x04>;
+				clocks = <&clks 62>, <&clks 147>;
+				clock-names = "ipg", "per";
 			};
 
-			pwm@0208c000 { /* PWM4 */
+			pwm4: pwm@0208c000 {
+				#pwm-cells = <2>;
+				compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
 				reg = <0x0208c000 0x4000>;
 				interrupts = <0 86 0x04>;
+				clocks = <&clks 62>, <&clks 148>;
+				clock-names = "ipg", "per";
 			};
 
-			flexcan@02090000 { /* CAN1 */
+			can1: flexcan@02090000 {
 				reg = <0x02090000 0x4000>;
 				interrupts = <0 110 0x04>;
 			};
 
-			flexcan@02094000 { /* CAN2 */
+			can2: flexcan@02094000 {
 				reg = <0x02094000 0x4000>;
 				interrupts = <0 111 0x04>;
 			};
 
-			gpt@02098000 {
+			gpt: gpt@02098000 {
 				compatible = "fsl,imx6q-gpt";
 				reg = <0x02098000 0x4000>;
 				interrupts = <0 55 0x04>;
@@ -373,19 +397,19 @@
 				#interrupt-cells = <2>;
 			};
 
-			kpp@020b8000 {
+			kpp: kpp@020b8000 {
 				reg = <0x020b8000 0x4000>;
 				interrupts = <0 82 0x04>;
 			};
 
-			wdog@020bc000 { /* WDOG1 */
+			wdog1: wdog@020bc000 {
 				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
 				reg = <0x020bc000 0x4000>;
 				interrupts = <0 80 0x04>;
 				clocks = <&clks 0>;
 			};
 
-			wdog@020c0000 { /* WDOG2 */
+			wdog2: wdog@020c0000 {
 				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
 				reg = <0x020c0000 0x4000>;
 				interrupts = <0 81 0x04>;
@@ -447,7 +471,7 @@
 					anatop-max-voltage = <2750000>;
 				};
 
-				regulator-vddcore@140 {
+				reg_cpu: regulator-vddcore@140 {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "cpu";
 					regulator-min-microvolt = <725000>;
@@ -505,27 +529,35 @@
 			};
 
 			snvs@020cc000 {
-				reg = <0x020cc000 0x4000>;
-				interrupts = <0 19 0x04 0 20 0x04>;
+				compatible = "fsl,sec-v4.0-mon", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x020cc000 0x4000>;
+
+				snvs-rtc-lp@34 {
+					compatible = "fsl,sec-v4.0-mon-rtc-lp";
+					reg = <0x34 0x58>;
+					interrupts = <0 19 0x04 0 20 0x04>;
+				};
 			};
 
-			epit@020d0000 { /* EPIT1 */
+			epit1: epit@020d0000 { /* EPIT1 */
 				reg = <0x020d0000 0x4000>;
 				interrupts = <0 56 0x04>;
 			};
 
-			epit@020d4000 { /* EPIT2 */
+			epit2: epit@020d4000 { /* EPIT2 */
 				reg = <0x020d4000 0x4000>;
 				interrupts = <0 57 0x04>;
 			};
 
-			src@020d8000 {
+			src: src@020d8000 {
 				compatible = "fsl,imx6q-src";
 				reg = <0x020d8000 0x4000>;
 				interrupts = <0 91 0x04 0 96 0x04>;
 			};
 
-			gpc@020dc000 {
+			gpc: gpc@020dc000 {
 				compatible = "fsl,imx6q-gpc";
 				reg = <0x020dc000 0x4000>;
 				interrupts = <0 89 0x04 0 90 0x04>;
@@ -536,7 +568,7 @@
 				reg = <0x020e0000 0x38>;
 			};
 
-			iomuxc@020e0000 {
+			iomuxc: iomuxc@020e0000 {
 				compatible = "fsl,imx6q-iomuxc";
 				reg = <0x020e0000 0x4000>;
 
@@ -580,6 +612,7 @@
 							66  0x1b0b0	/* MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2 */
 							70  0x1b0b0	/* MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3 */
 							48  0x1b0b0	/* MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL */
+							1033 0x4001b0a8	/* MX6Q_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT*/
 						>;
 					};
 
@@ -748,17 +781,17 @@
 				};
 			};
 
-			dcic@020e4000 { /* DCIC1 */
+			dcic1: dcic@020e4000 {
 				reg = <0x020e4000 0x4000>;
 				interrupts = <0 124 0x04>;
 			};
 
-			dcic@020e8000 { /* DCIC2 */
+			dcic2: dcic@020e8000 {
 				reg = <0x020e8000 0x4000>;
 				interrupts = <0 125 0x04>;
 			};
 
-			sdma@020ec000 {
+			sdma: sdma@020ec000 {
 				compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
 				reg = <0x020ec000 0x4000>;
 				interrupts = <0 2 0x04>;
@@ -784,7 +817,7 @@
 				reg = <0x0217c000 0x4000>;
 			};
 
-			usb@02184000 { /* USB OTG */
+			usbotg: usb@02184000 {
 				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
 				reg = <0x02184000 0x200>;
 				interrupts = <0 43 0x04>;
@@ -794,7 +827,7 @@
 				status = "disabled";
 			};
 
-			usb@02184200 { /* USB1 */
+			usbh1: usb@02184200 {
 				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
 				reg = <0x02184200 0x200>;
 				interrupts = <0 40 0x04>;
@@ -804,7 +837,7 @@
 				status = "disabled";
 			};
 
-			usb@02184400 { /* USB2 */
+			usbh2: usb@02184400 {
 				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
 				reg = <0x02184400 0x200>;
 				interrupts = <0 41 0x04>;
@@ -813,7 +846,7 @@
 				status = "disabled";
 			};
 
-			usb@02184600 { /* USB3 */
+			usbh3: usb@02184600 {
 				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
 				reg = <0x02184600 0x200>;
 				interrupts = <0 42 0x04>;
@@ -822,19 +855,19 @@
 				status = "disabled";
 			};
 
-			usbmisc: usbmisc@02184800 {
+			usbmisc: usbmisc: usbmisc@02184800 {
 				#index-cells = <1>;
 				compatible = "fsl,imx6q-usbmisc";
 				reg = <0x02184800 0x200>;
 				clocks = <&clks 162>;
 			};
 
-			ethernet@02188000 {
+			fec: ethernet@02188000 {
 				compatible = "fsl,imx6q-fec";
 				reg = <0x02188000 0x4000>;
 				interrupts = <0 118 0x04 0 119 0x04>;
-				clocks = <&clks 117>, <&clks 117>;
-				clock-names = "ipg", "ahb";
+				clocks = <&clks 117>, <&clks 117>, <&clks 177>;
+				clock-names = "ipg", "ahb", "ptp";
 				status = "disabled";
 			};
 
@@ -843,66 +876,70 @@
 				interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>;
 			};
 
-			usdhc@02190000 { /* uSDHC1 */
+			usdhc1: usdhc@02190000 {
 				compatible = "fsl,imx6q-usdhc";
 				reg = <0x02190000 0x4000>;
 				interrupts = <0 22 0x04>;
 				clocks = <&clks 163>, <&clks 163>, <&clks 163>;
 				clock-names = "ipg", "ahb", "per";
+				bus-width = <4>;
 				status = "disabled";
 			};
 
-			usdhc@02194000 { /* uSDHC2 */
+			usdhc2: usdhc@02194000 {
 				compatible = "fsl,imx6q-usdhc";
 				reg = <0x02194000 0x4000>;
 				interrupts = <0 23 0x04>;
 				clocks = <&clks 164>, <&clks 164>, <&clks 164>;
 				clock-names = "ipg", "ahb", "per";
+				bus-width = <4>;
 				status = "disabled";
 			};
 
-			usdhc@02198000 { /* uSDHC3 */
+			usdhc3: usdhc@02198000 {
 				compatible = "fsl,imx6q-usdhc";
 				reg = <0x02198000 0x4000>;
 				interrupts = <0 24 0x04>;
 				clocks = <&clks 165>, <&clks 165>, <&clks 165>;
 				clock-names = "ipg", "ahb", "per";
+				bus-width = <4>;
 				status = "disabled";
 			};
 
-			usdhc@0219c000 { /* uSDHC4 */
+			usdhc4: usdhc@0219c000 {
 				compatible = "fsl,imx6q-usdhc";
 				reg = <0x0219c000 0x4000>;
 				interrupts = <0 25 0x04>;
 				clocks = <&clks 166>, <&clks 166>, <&clks 166>;
 				clock-names = "ipg", "ahb", "per";
+				bus-width = <4>;
 				status = "disabled";
 			};
 
-			i2c@021a0000 { /* I2C1 */
+			i2c1: i2c@021a0000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
-				compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+				compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
 				reg = <0x021a0000 0x4000>;
 				interrupts = <0 36 0x04>;
 				clocks = <&clks 125>;
 				status = "disabled";
 			};
 
-			i2c@021a4000 { /* I2C2 */
+			i2c2: i2c@021a4000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
-				compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+				compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
 				reg = <0x021a4000 0x4000>;
 				interrupts = <0 37 0x04>;
 				clocks = <&clks 126>;
 				status = "disabled";
 			};
 
-			i2c@021a8000 { /* I2C3 */
+			i2c3: i2c@021a8000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
-				compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+				compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
 				reg = <0x021a8000 0x4000>;
 				interrupts = <0 38 0x04>;
 				clocks = <&clks 127>;
@@ -913,12 +950,12 @@
 				reg = <0x021ac000 0x4000>;
 			};
 
-			mmdc@021b0000 { /* MMDC0 */
+			mmdc0: mmdc@021b0000 { /* MMDC0 */
 				compatible = "fsl,imx6q-mmdc";
 				reg = <0x021b0000 0x4000>;
 			};
 
-			mmdc@021b4000 { /* MMDC1 */
+			mmdc1: mmdc@021b4000 { /* MMDC1 */
 				reg = <0x021b4000 0x4000>;
 			};
 
@@ -946,7 +983,7 @@
 				interrupts = <0 109 0x04>;
 			};
 
-			audmux@021d8000 {
+			audmux: audmux@021d8000 {
 				compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux";
 				reg = <0x021d8000 0x4000>;
 				status = "disabled";
@@ -1001,5 +1038,23 @@
 				status = "disabled";
 			};
 		};
+
+		ipu1: ipu@02400000 {
+			#crtc-cells = <1>;
+			compatible = "fsl,imx6q-ipu";
+			reg = <0x02400000 0x400000>;
+			interrupts = <0 6 0x4 0 5 0x4>;
+			clocks = <&clks 130>, <&clks 131>, <&clks 132>;
+			clock-names = "bus", "di0", "di1";
+		};
+
+		ipu2: ipu@02800000 {
+			#crtc-cells = <1>;
+			compatible = "fsl,imx6q-ipu";
+			reg = <0x02800000 0x400000>;
+			interrupts = <0 8 0x4 0 7 0x4>;
+			clocks = <&clks 133>, <&clks 134>, <&clks 137>;
+			clock-names = "bus", "di0", "di1";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/integratorap.dts b/arch/arm/boot/dts/integratorap.dts
index 6176775..c9c3fa3 100644
--- a/arch/arm/boot/dts/integratorap.dts
+++ b/arch/arm/boot/dts/integratorap.dts
@@ -18,6 +18,11 @@
 		bootargs = "root=/dev/ram0 console=ttyAM0,38400n8 earlyprintk";
 	};
 
+	syscon {
+		/* AP system controller registers */
+		reg = <0x11000000 0x100>;
+	};
+
 	timer0: timer@13000000 {
 		compatible = "arm,integrator-timer";
 	};
diff --git a/arch/arm/boot/dts/integratorcp.dts b/arch/arm/boot/dts/integratorcp.dts
index 2dd5e4e..8b11939 100644
--- a/arch/arm/boot/dts/integratorcp.dts
+++ b/arch/arm/boot/dts/integratorcp.dts
@@ -18,6 +18,11 @@
 		bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk";
 	};
 
+	cpcon {
+		/* CP controller registers */
+		reg = <0xcb000000 0x100>;
+	};
+
 	timer0: timer@13000000 {
 		compatible = "arm,sp804", "arm,primecell";
 	};
diff --git a/arch/arm/boot/dts/kirkwood-6281.dtsi b/arch/arm/boot/dts/kirkwood-6281.dtsi
new file mode 100644
index 0000000..d6c9d65
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-6281.dtsi
@@ -0,0 +1,44 @@
+/ {
+	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+			compatible = "marvell,88f6281-pinctrl";
+			reg = <0x10000 0x20>;
+
+			pmx_nand: pmx-nand {
+				marvell,pins = "mpp0", "mpp1", "mpp2", "mpp3",
+					       "mpp4", "mpp5", "mpp18",
+					       "mpp19";
+				marvell,function = "nand";
+			};
+			pmx_sata0: pmx-sata0 {
+				marvell,pins = "mpp5", "mpp21", "mpp23";
+				marvell,function = "sata0";
+			};
+			pmx_sata1: pmx-sata1 {
+				marvell,pins = "mpp4", "mpp20", "mpp22";
+				marvell,function = "sata1";
+			};
+			pmx_spi: pmx-spi {
+				marvell,pins = "mpp0", "mpp1", "mpp2", "mpp3";
+				marvell,function = "spi";
+			};
+			pmx_twsi0: pmx-twsi0 {
+				marvell,pins = "mpp8", "mpp9";
+				marvell,function = "twsi0";
+			};
+			pmx_uart0: pmx-uart0 {
+				marvell,pins = "mpp10", "mpp11";
+				marvell,function = "uart0";
+			};
+			pmx_uart1: pmx-uart1 {
+				marvell,pins = "mpp13", "mpp14";
+				marvell,function = "uart1";
+			};
+			pmx_sdio: pmx-sdio {
+				marvell,pins = "mpp12", "mpp13", "mpp14",
+					       "mpp15", "mpp16", "mpp17";
+				marvell,function = "sdio";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-6282.dtsi b/arch/arm/boot/dts/kirkwood-6282.dtsi
new file mode 100644
index 0000000..9ae2004
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-6282.dtsi
@@ -0,0 +1,45 @@
+/ {
+	ocp@f1000000 {
+
+		pinctrl: pinctrl@10000 {
+			compatible = "marvell,88f6282-pinctrl";
+			reg = <0x10000 0x20>;
+
+			pmx_sata0: pmx-sata0 {
+				marvell,pins = "mpp5", "mpp21", "mpp23";
+				marvell,function = "sata0";
+			};
+			pmx_sata1: pmx-sata1 {
+				marvell,pins = "mpp4", "mpp20", "mpp22";
+				marvell,function = "sata1";
+			};
+			pmx_spi: pmx-spi {
+				marvell,pins = "mpp0", "mpp1", "mpp2", "mpp3";
+				marvell,function = "spi";
+			};
+			pmx_twsi0: pmx-twsi0 {
+				marvell,pins = "mpp8", "mpp9";
+				marvell,function = "twsi0";
+			};
+			pmx_uart0: pmx-uart0 {
+				marvell,pins = "mpp10", "mpp11";
+				marvell,function = "uart0";
+			};
+
+			pmx_uart1: pmx-uart1 {
+				marvell,pins = "mpp13", "mpp14";
+				marvell,function = "uart1";
+			};
+		};
+
+		i2c@11100 {
+			compatible = "marvell,mv64xxx-i2c";
+			reg = <0x11100 0x20>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <32>;
+			clock-frequency = <100000>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-98dx4122.dtsi b/arch/arm/boot/dts/kirkwood-98dx4122.dtsi
new file mode 100644
index 0000000..3271e4c
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-98dx4122.dtsi
@@ -0,0 +1,31 @@
+/ {
+	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+			compatible = "marvell,98dx4122-pinctrl";
+			reg = <0x10000 0x20>;
+
+			pmx_nand: pmx-nand {
+				marvell,pins = "mpp0", "mpp1", "mpp2", "mpp3",
+					       "mpp4", "mpp5", "mpp18",
+					       "mpp19";
+				marvell,function = "nand";
+			};
+			pmx_spi: pmx-spi {
+				marvell,pins = "mpp0", "mpp1", "mpp2", "mpp3";
+				marvell,function = "spi";
+			};
+			pmx_twsi0: pmx-twsi0 {
+				marvell,pins = "mpp8", "mpp9";
+				marvell,function = "twsi0";
+			};
+			pmx_uart0: pmx-uart0 {
+				marvell,pins = "mpp10", "mpp11";
+				marvell,function = "uart0";
+			};
+			pmx_uart1: pmx-uart1 {
+				marvell,pins = "mpp13", "mpp14";
+				marvell,function = "uart1";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-dnskw.dtsi b/arch/arm/boot/dts/kirkwood-dnskw.dtsi
index 9b32d02..6875ac0 100644
--- a/arch/arm/boot/dts/kirkwood-dnskw.dtsi
+++ b/arch/arm/boot/dts/kirkwood-dnskw.dtsi
@@ -1,4 +1,5 @@
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
 	model = "D-Link DNS NASes (kirkwood-based)";
@@ -35,7 +36,116 @@
 				      6000 2>;
 	};
 
+	gpio_poweroff {
+		compatible = "gpio-poweroff";
+		gpios = <&gpio1 4 0>;
+	};
+
 	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+
+			pinctrl-0 = < &pmx_nand &pmx_uart1
+				      &pmx_sata0 &pmx_sata1
+				      &pmx_led_power
+				      &pmx_led_red_right_hdd
+				      &pmx_led_red_left_hdd
+				      &pmx_led_red_usb_325
+				      &pmx_button_power
+				      &pmx_led_red_usb_320
+				      &pmx_power_off &pmx_power_back_on
+				      &pmx_power_sata0 &pmx_power_sata1
+				      &pmx_present_sata0 &pmx_present_sata1
+				      &pmx_led_white_usb &pmx_fan_tacho
+				      &pmx_fan_high_speed &pmx_fan_low_speed
+				      &pmx_button_unmount &pmx_button_reset
+				      &pmx_temp_alarm >;
+			pinctrl-names = "default";
+
+			pmx_sata0: pmx-sata0 {
+				marvell,pins = "mpp20";
+				marvell,function = "sata1";
+			};
+			pmx_sata1: pmx-sata1 {
+				marvell,pins = "mpp21";
+				marvell,function = "sata0";
+			};
+			pmx_led_power: pmx-led-power {
+				marvell,pins = "mpp26";
+				marvell,function = "gpio";
+			};
+			pmx_led_red_right_hdd: pmx-led-red-right-hdd {
+				marvell,pins = "mpp27";
+				marvell,function = "gpio";
+			};
+			pmx_led_red_left_hdd: pmx-led-red-left-hdd {
+				marvell,pins = "mpp28";
+				marvell,function = "gpio";
+			};
+			pmx_led_red_usb_325: pmx-led-red-usb-325 {
+				marvell,pins = "mpp29";
+				marvell,function = "gpio";
+			};
+			pmx_button_power: pmx-button-power {
+				marvell,pins = "mpp34";
+				marvell,function = "gpio";
+			};
+			pmx_led_red_usb_320: pmx-led-red-usb-320 {
+				marvell,pins = "mpp35";
+				marvell,function = "gpio";
+			};
+			pmx_power_off: pmx-power-off {
+				marvell,pins = "mpp36";
+				marvell,function = "gpio";
+			};
+			pmx_power_back_on: pmx-power-back-on {
+				marvell,pins = "mpp37";
+				marvell,function = "gpio";
+			};
+			pmx_power_sata0: pmx-power-sata0 {
+				marvell,pins = "mpp39";
+				marvell,function = "gpio";
+			};
+			pmx_power_sata1: pmx-power-sata1 {
+				marvell,pins = "mpp40";
+				marvell,function = "gpio";
+			};
+			pmx_present_sata0: pmx-present-sata0 {
+				marvell,pins = "mpp41";
+				marvell,function = "gpio";
+			};
+			pmx_present_sata1: pmx-present-sata1 {
+				marvell,pins = "mpp42";
+				marvell,function = "gpio";
+			};
+			pmx_led_white_usb: pmx-led-white-usb {
+				marvell,pins = "mpp43";
+				marvell,function = "gpio";
+			};
+			pmx_fan_tacho: pmx-fan-tacho {
+				marvell,pins = "mpp44";
+				marvell,function = "gpio";
+			};
+			pmx_fan_high_speed: pmx-fan-high-speed {
+				marvell,pins = "mpp45";
+				marvell,function = "gpio";
+			};
+			pmx_fan_low_speed: pmx-fan-low-speed {
+				marvell,pins = "mpp46";
+				marvell,function = "gpio";
+			};
+			pmx_button_unmount: pmx-button-unmount {
+				marvell,pins = "mpp47";
+				marvell,function = "gpio";
+			};
+			pmx_button_reset: pmx-button-reset {
+				marvell,pins = "mpp48";
+				marvell,function = "gpio";
+			};
+			pmx_temp_alarm: pmx-temp-alarm {
+				marvell,pins = "mpp49";
+				marvell,function = "gpio";
+			};
+		};
 		sata@80000 {
 			status = "okay";
 			nr-ports = <2>;
@@ -43,6 +153,7 @@
 
 		nand@3000000 {
 			status = "okay";
+			chip-delay = <35>;
 
 			partition@0 {
 				label = "u-boot";
@@ -76,4 +187,33 @@
 			};
 		};
 	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		sata0_power: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "SATA0 Power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&gpio1 7 0>;
+		};
+		sata1_power: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "SATA1 Power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&gpio1 8 0>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/kirkwood-dockstar.dts b/arch/arm/boot/dts/kirkwood-dockstar.dts
index 08a5824..2e3dd34 100644
--- a/arch/arm/boot/dts/kirkwood-dockstar.dts
+++ b/arch/arm/boot/dts/kirkwood-dockstar.dts
@@ -1,6 +1,7 @@
 /dts-v1/;
 
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
 	model = "Seagate FreeAgent Dockstar";
@@ -16,6 +17,25 @@
 	};
 
 	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+
+			pinctrl-0 = < &pmx_usb_power_enable
+				      &pmx_led_green &pmx_led_orange >;
+			pinctrl-names = "default";
+
+			pmx_usb_power_enable: pmx-usb-power-enable {
+				marvell,pins = "mpp29";
+				marvell,function = "gpio";
+			};
+			pmx_led_green: pmx-led-green {
+				marvell,pins = "mpp46";
+				marvell,function = "gpio";
+			};
+			pmx_led_orange: pmx-led-orange {
+				marvell,pins = "mpp47";
+				marvell,function = "gpio";
+			};
+		};
 		serial@12000 {
 			clock-frequency = <200000000>;
 			status = "ok";
@@ -54,4 +74,21 @@
 			gpios = <&gpio1 15 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 29 0>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/kirkwood-dreamplug.dts b/arch/arm/boot/dts/kirkwood-dreamplug.dts
index 26e281f..f2d386c 100644
--- a/arch/arm/boot/dts/kirkwood-dreamplug.dts
+++ b/arch/arm/boot/dts/kirkwood-dreamplug.dts
@@ -1,6 +1,7 @@
 /dts-v1/;
 
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
 	model = "Globalscale Technologies Dreamplug";
@@ -16,6 +17,26 @@
 	};
 
 	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+
+			pinctrl-0 = < &pmx_spi
+				      &pmx_led_bluetooth &pmx_led_wifi
+				      &pmx_led_wifi_ap >;
+			pinctrl-names = "default";
+
+			pmx_led_bluetooth: pmx-led-bluetooth {
+				marvell,pins = "mpp47";
+				marvell,function = "gpio";
+			};
+			pmx_led_wifi: pmx-led-wifi {
+				marvell,pins = "mpp48";
+				marvell,function = "gpio";
+			};
+			pmx_led_wifi_ap: pmx-led-wifi-ap {
+				marvell,pins = "mpp49";
+				marvell,function = "gpio";
+			};
+		};
 		serial@12000 {
 			clock-frequency = <200000000>;
 			status = "ok";
diff --git a/arch/arm/boot/dts/kirkwood-goflexnet.dts b/arch/arm/boot/dts/kirkwood-goflexnet.dts
index 7c8238f..1b133e0 100644
--- a/arch/arm/boot/dts/kirkwood-goflexnet.dts
+++ b/arch/arm/boot/dts/kirkwood-goflexnet.dts
@@ -1,6 +1,7 @@
 /dts-v1/;
 
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
 	model = "Seagate GoFlex Net";
@@ -16,6 +17,61 @@
 	};
 
 	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+
+			pinctrl-0 = < &pmx_usb_power_enable &pmx_led_orange
+				      &pmx_led_left_cap_0 &pmx_led_left_cap_1
+				      &pmx_led_left_cap_2 &pmx_led_left_cap_3
+				      &pmx_led_right_cap_0 &pmx_led_right_cap_1
+				      &pmx_led_right_cap_2 &pmx_led_right_cap_3
+				    >;
+			pinctrl-names = "default";
+
+			pmx_usb_power_enable: pmx-usb-power-enable {
+				marvell,pins = "mpp29";
+				marvell,function = "gpio";
+			};
+			pmx_led_right_cap_0: pmx-led_right_cap_0 {
+				marvell,pins = "mpp38";
+				marvell,function = "gpio";
+			};
+			pmx_led_right_cap_1: pmx-led_right_cap_1 {
+				marvell,pins = "mpp39";
+				marvell,function = "gpio";
+			};
+			pmx_led_right_cap_2: pmx-led_right_cap_2 {
+				marvell,pins = "mpp40";
+				marvell,function = "gpio";
+			};
+			pmx_led_right_cap_3: pmx-led_right_cap_3 {
+				marvell,pins = "mpp41";
+				marvell,function = "gpio";
+			};
+			pmx_led_left_cap_0: pmx-led_left_cap_0 {
+				marvell,pins = "mpp42";
+				marvell,function = "gpio";
+			};
+			pmx_led_left_cap_1: pmx-led_left_cap_1 {
+				marvell,pins = "mpp43";
+				marvell,function = "gpio";
+			};
+			pmx_led_left_cap_2: pmx-led_left_cap_2 {
+				marvell,pins = "mpp44";
+				marvell,function = "gpio";
+			};
+			pmx_led_left_cap_3: pmx-led_left_cap_3 {
+				marvell,pins = "mpp45";
+				marvell,function = "gpio";
+			};
+			pmx_led_green: pmx-led_green {
+				marvell,pins = "mpp46";
+				marvell,function = "gpio";
+			};
+			pmx_led_orange: pmx-led_orange {
+				marvell,pins = "mpp47";
+				marvell,function = "gpio";
+			};
+		};
 		serial@12000 {
 			clock-frequency = <200000000>;
 			status = "ok";
@@ -96,4 +152,21 @@
 			gpios = <&gpio1 9 0>;
 		};
 	};
+	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 29 0>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/kirkwood-ib62x0.dts b/arch/arm/boot/dts/kirkwood-ib62x0.dts
index 66794ed..71902da 100644
--- a/arch/arm/boot/dts/kirkwood-ib62x0.dts
+++ b/arch/arm/boot/dts/kirkwood-ib62x0.dts
@@ -1,6 +1,7 @@
 /dts-v1/;
 
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
 	model = "RaidSonic ICY BOX IB-NAS62x0 (Rev B)";
@@ -16,6 +17,39 @@
 	};
 
 	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+
+			pinctrl-0 = < &pmx_nand
+				      &pmx_led_os_red &pmx_power_off
+				      &pmx_led_os_green &pmx_led_usb_transfer
+				      &pmx_button_reset &pmx_button_usb_copy >;
+			pinctrl-names = "default";
+
+			pmx_led_os_red: pmx-led-os-red {
+				marvell,pins = "mpp22";
+				marvell,function = "gpio";
+			};
+			pmx_power_off: pmx-power-off {
+				marvell,pins = "mpp24";
+				marvell,function = "gpio";
+			};
+			pmx_led_os_green: pmx-led-os-green {
+				marvell,pins = "mpp25";
+				marvell,function = "gpio";
+			};
+			pmx_led_usb_transfer: pmx-led-usb-transfer {
+				marvell,pins = "mpp27";
+				marvell,function = "gpio";
+			};
+			pmx_button_reset: pmx-button-reset {
+				marvell,pins = "mpp28";
+				marvell,function = "gpio";
+			};
+			pmx_button_usb_copy: pmx-button-usb-copy {
+				marvell,pins = "mpp29";
+				marvell,function = "gpio";
+			};
+		};
 		serial@12000 {
 			clock-frequency = <200000000>;
 			status = "okay";
@@ -79,4 +113,10 @@
 			gpios = <&gpio0 27 0>;
 		};
 	};
+	gpio_poweroff {
+		compatible = "gpio-poweroff";
+		gpios = <&gpio0 24 0>;
+	};
+
+
 };
diff --git a/arch/arm/boot/dts/kirkwood-iconnect.dts b/arch/arm/boot/dts/kirkwood-iconnect.dts
index d97cd9d..504f16b 100644
--- a/arch/arm/boot/dts/kirkwood-iconnect.dts
+++ b/arch/arm/boot/dts/kirkwood-iconnect.dts
@@ -1,6 +1,7 @@
 /dts-v1/;
 
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
 	model = "Iomega Iconnect";
@@ -18,6 +19,56 @@
 	};
 
 	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+
+			pinctrl-0 = < &pmx_gpio_12 &pmx_gpio_35
+				      &pmx_gpio_41 &pmx_gpio_42
+				      &pmx_gpio_43 &pmx_gpio_44
+				      &pmx_gpio_45 &pmx_gpio_46
+				      &pmx_gpio_47 &pmx_gpio_48 >;
+			pinctrl-names = "default";
+
+			pmx_gpio_12: pmx-gpio-12 {
+				marvell,pins = "mpp12";
+				marvell,function = "gpio";
+			};
+			pmx_gpio_35: pmx-gpio-35 {
+				marvell,pins = "mpp35";
+				marvell,function = "gpio";
+			};
+			pmx_gpio_41: pmx-gpio-41 {
+				marvell,pins = "mpp41";
+				marvell,function = "gpio";
+			};
+			pmx_gpio_42: pmx-gpio-42 {
+				marvell,pins = "mpp42";
+				marvell,function = "gpio";
+			};
+			pmx_gpio_43: pmx-gpio-43 {
+				marvell,pins = "mpp43";
+				marvell,function = "gpio";
+			};
+			pmx_gpio_44: pmx-gpio-44 {
+				marvell,pins = "mpp44";
+				marvell,function = "gpio";
+			};
+			pmx_gpio_45: pmx-gpio-45 {
+				marvell,pins = "mpp45";
+				marvell,function = "gpio";
+			};
+			pmx_gpio_46: pmx-gpio-46 {
+				marvell,pins = "mpp46";
+				marvell,function = "gpio";
+			};
+			pmx_gpio_47: pmx-gpio-47 {
+				marvell,pins = "mpp47";
+				marvell,function = "gpio";
+			};
+			pmx_gpio_48: pmx-gpio-48 {
+				marvell,pins = "mpp48";
+				marvell,function = "gpio";
+			};
+		};
 		i2c@11000 {
 			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 865aeec..6cae459 100644
--- a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
+++ b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
@@ -1,6 +1,7 @@
 /dts-v1/;
 
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
 	model = "Iomega StorCenter ix2-200";
@@ -16,6 +17,94 @@
 	};
 
 	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+
+			pinctrl-0 = < &pmx_button_reset &pmx_button_power
+				      &pmx_led_backup &pmx_led_power
+				      &pmx_button_otb &pmx_led_rebuild
+				      &pmx_led_health
+				      &pmx_led_sata_brt_ctrl_1
+				      &pmx_led_sata_brt_ctrl_2
+				      &pmx_led_backup_brt_ctrl_1
+				      &pmx_led_backup_brt_ctrl_2
+				      &pmx_led_power_brt_ctrl_1
+				      &pmx_led_power_brt_ctrl_2
+				      &pmx_led_health_brt_ctrl_1
+				      &pmx_led_health_brt_ctrl_2
+				      &pmx_led_rebuild_brt_ctrl_1
+				      &pmx_led_rebuild_brt_ctrl_2 >;
+			pinctrl-names = "default";
+
+			pmx_button_reset: pmx-button-reset {
+				marvell,pins = "mpp12";
+				marvell,function = "gpio";
+			};
+			pmx_button_power: pmx-button-power {
+				marvell,pins = "mpp14";
+				marvell,function = "gpio";
+			};
+			pmx_led_backup: pmx-led-backup {
+				marvell,pins = "mpp15";
+				marvell,function = "gpio";
+			};
+			pmx_led_power: pmx-led-power {
+				marvell,pins = "mpp16";
+				marvell,function = "gpio";
+			};
+			pmx_button_otb: pmx-button-otb {
+				marvell,pins = "mpp35";
+				marvell,function = "gpio";
+			};
+			pmx_led_rebuild: pmx-led-rebuild {
+				marvell,pins = "mpp36";
+				marvell,function = "gpio";
+			};
+			pmx_led_health: pmx-led_health {
+				marvell,pins = "mpp37";
+				marvell,function = "gpio";
+			};
+			pmx_led_sata_brt_ctrl_1: pmx-led-sata-brt-ctrl-1 {
+				marvell,pins = "mpp38";
+				marvell,function = "gpio";
+			};
+			pmx_led_sata_brt_ctrl_2: pmx-led-sata-brt-ctrl-2 {
+				marvell,pins = "mpp39";
+				marvell,function = "gpio";
+			};
+			pmx_led_backup_brt_ctrl_1: pmx-led-backup-brt-ctrl-1 {
+				marvell,pins = "mpp40";
+				marvell,function = "gpio";
+			};
+			pmx_led_backup_brt_ctrl_2: pmx-led-backup-brt-ctrl-2 {
+				marvell,pins = "mpp41";
+				marvell,function = "gpio";
+			};
+			pmx_led_power_brt_ctrl_1: pmx-led-power-brt-ctrl-1 {
+				marvell,pins = "mpp42";
+				marvell,function = "gpio";
+			};
+			pmx_led_power_brt_ctrl_2: pmx-led-power-brt-ctrl-2 {
+				marvell,pins = "mpp43";
+				marvell,function = "gpio";
+			};
+			pmx_led_health_brt_ctrl_1: pmx-led-health-brt-ctrl-1 {
+				marvell,pins = "mpp44";
+				marvell,function = "gpio";
+			};
+			pmx_led_health_brt_ctrl_2: pmx-led-health-brt-ctrl-2 {
+				marvell,pins = "mpp45";
+				marvell,function = "gpio";
+			};
+			pmx_led_rebuild_brt_ctrl_1: pmx-led-rebuild-brt-ctrl-1 {
+				marvell,pins = "mpp44";
+				marvell,function = "gpio";
+			};
+			pmx_led_rebuild_brt_ctrl_2: pmx-led-rebuild-brt-ctrl-2 {
+				marvell,pins = "mpp45";
+				marvell,function = "gpio";
+			};
+
+		};
 		i2c@11000 {
 			status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-is2.dts b/arch/arm/boot/dts/kirkwood-is2.dts
new file mode 100644
index 0000000..0bdce0a
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-is2.dts
@@ -0,0 +1,30 @@
+/dts-v1/;
+
+/include/ "kirkwood-ns2-common.dtsi"
+
+/ {
+	model = "LaCie Internet Space v2";
+	compatible = "lacie,inetspace_v2", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	ocp@f1000000 {
+		sata@80000 {
+			status = "okay";
+			nr-ports = <1>;
+		};
+	};
+
+	ns2-leds {
+		compatible = "lacie,ns2-leds";
+
+		blue-sata {
+			label = "ns2:blue:sata";
+			slow-gpio = <&gpio0 29 0>;
+			cmd-gpio = <&gpio0 30 0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-km_kirkwood.dts b/arch/arm/boot/dts/kirkwood-km_kirkwood.dts
index 75bdb93..8db3123 100644
--- a/arch/arm/boot/dts/kirkwood-km_kirkwood.dts
+++ b/arch/arm/boot/dts/kirkwood-km_kirkwood.dts
@@ -1,6 +1,7 @@
 /dts-v1/;
 
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-98dx4122.dtsi"
 
 / {
 	model = "Keymile Kirkwood Reference Design";
@@ -16,6 +17,22 @@
 	};
 
 	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+
+			pinctrl-0 = < &pmx_nand &pmx_i2c_gpio_sda
+				&pmx_i2c_gpio_scl >;
+			pinctrl-names = "default";
+
+			pmx_i2c_gpio_sda: pmx-gpio-sda {
+				marvell,pins = "mpp8";
+				marvell,function = "gpio";
+			};
+			pmx_i2c_gpio_scl: pmx-gpio-scl {
+				marvell,pins = "mpp9";
+				marvell,function = "gpio";
+			};
+		};
+
 		serial@12000 {
 			clock-frequency = <200000000>;
 			status = "ok";
diff --git a/arch/arm/boot/dts/kirkwood-lsxl.dtsi b/arch/arm/boot/dts/kirkwood-lsxl.dtsi
index 8fea375..37d45c4 100644
--- a/arch/arm/boot/dts/kirkwood-lsxl.dtsi
+++ b/arch/arm/boot/dts/kirkwood-lsxl.dtsi
@@ -1,4 +1,5 @@
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
 	chosen {
@@ -6,6 +7,71 @@
 	};
 
 	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+
+			pinctrl-0 = < &pmx_power_hdd &pmx_usb_vbus
+				      &pmx_fan_low &pmx_fan_high
+				      &pmx_led_function_red &pmx_led_alarm
+				      &pmx_led_info &pmx_led_power
+				      &pmx_fan_lock &pmx_button_function
+				      &pmx_power_switch &pmx_power_auto_switch
+				      &pmx_led_function_blue >;
+			pinctrl-names = "default";
+
+			pmx_power_hdd: pmx-power-hdd {
+				marvell,pins = "mpp10";
+				marvell,function = "gpo";
+			};
+			pmx_usb_vbus: pmx-usb-vbus {
+				marvell,pins = "mpp11";
+				marvell,function = "gpio";
+			};
+			pmx_fan_high: pmx-fan-high {
+				marvell,pins = "mpp18";
+				marvell,function = "gpo";
+			};
+			pmx_fan_low: pmx-fan-low {
+				marvell,pins = "mpp19";
+				marvell,function = "gpo";
+			};
+			pmx_led_function_blue: pmx-led-function-blue {
+				marvell,pins = "mpp36";
+				marvell,function = "gpio";
+			};
+			pmx_led_alarm: pmx-led-alarm {
+				marvell,pins = "mpp37";
+				marvell,function = "gpio";
+			};
+			pmx_led_info: pmx-led-info {
+				marvell,pins = "mpp38";
+				marvell,function = "gpio";
+			};
+			pmx_led_power: pmx-led-power {
+				marvell,pins = "mpp39";
+				marvell,function = "gpio";
+			};
+			pmx_fan_lock: pmx-fan-lock {
+				marvell,pins = "mpp40";
+				marvell,function = "gpio";
+			};
+			pmx_button_function: pmx-button-function {
+				marvell,pins = "mpp41";
+				marvell,function = "gpio";
+			};
+			pmx_power_switch: pmx-power-switch {
+				marvell,pins = "mpp42";
+				marvell,function = "gpio";
+			};
+			pmx_power_auto_switch: pmx-power-auto-switch {
+				marvell,pins = "mpp43";
+				marvell,function = "gpio";
+			};
+			pmx_led_function_red: pmx-led-function_red {
+				marvell,pins = "mpp48";
+				marvell,function = "gpio";
+			};
+
+		};
 		sata@80000 {
 			status = "okay";
 			nr-ports = <1>;
@@ -94,4 +160,44 @@
 			gpios = <&gpio1 16 1>;
 		};
 	};
+
+	gpio_fan {
+		compatible = "gpio-fan";
+		gpios = <&gpio0 19 1
+		         &gpio0 18 1>;
+		gpio-fan,speed-map = <0    3
+		                      1500 2
+		                      3250 1
+		                      5000 0>;
+		alarm-gpios = <&gpio1 8 0>;
+	};
+
+	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 11 0>;
+		};
+		hdd_power: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "HDD Power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&gpio0 10 0>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/kirkwood-mplcec4.dts b/arch/arm/boot/dts/kirkwood-mplcec4.dts
new file mode 100644
index 0000000..262c654
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-mplcec4.dts
@@ -0,0 +1,178 @@
+/dts-v1/;
+
+/include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
+
+/ {
+	model = "MPL CEC4";
+	compatible = "mpl,cec4-10", "mpl,cec4", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+        memory {
+                device_type = "memory";
+                reg = <0x00000000 0x20000000>;
+        };
+
+        chosen {
+                bootargs = "console=ttyS0,115200n8 earlyprintk";
+        };
+
+	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+
+			pinctrl-0 = < &pmx_nand &pmx_uart0
+				      &pmx_led_health &pmx_sdio
+				      &pmx_sata0 &pmx_sata1
+				      &pmx_led_user1o
+				      &pmx_led_user1g &pmx_led_user0o
+				      &pmx_led_user0g &pmx_led_misc
+				      &pmx_sdio_cd
+				    >;
+			pinctrl-names = "default";
+
+			pmx_led_health: pmx-led-health {
+				marvell,pins = "mpp7";
+				marvell,function = "gpo";
+			};
+
+			pmx_sata1: pmx-sata1 {
+				marvell,pins = "mpp34";
+				marvell,function = "sata1";
+			};
+
+			pmx_sata0: pmx-sata0 {
+				marvell,pins = "mpp35";
+				marvell,function = "sata0";
+			};
+
+			pmx_led_user1o: pmx-led-user1o {
+				marvell,pins = "mpp40";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_user1g: pmx-led-user1g {
+				marvell,pins = "mpp41";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_user0o: pmx-led-user0o {
+				marvell,pins = "mpp44";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_user0g: pmx-led-user0g {
+				marvell,pins = "mpp45";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_misc: pmx-led-misc {
+				marvell,pins = "mpp46";
+				marvell,function = "gpio";
+			};
+
+			pmx_sdio_cd: pmx-sdio-cd {
+				marvell,pins = "mpp47";
+				marvell,function = "gpio";
+			};
+		};
+
+                i2c@11000 {
+                        status = "okay";
+
+			rtc@51 {
+				compatible = "nxp,pcf8563";
+				reg = <0x51>;
+			};
+
+			eeprom@57 {
+				compatible = "atmel,24c02";
+				reg = <0x57>;
+			};
+
+                };
+
+                serial@12000 {
+                        clock-frequency = <200000000>;
+                        status = "ok";
+                };
+
+                nand@3000000 {
+                        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";
+		};
+
+		sata@80000 {
+			nr-ports = <2>;
+			status = "okay";
+
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		health {
+			label = "status:green:health";
+			gpios = <&gpio0 7 1>;
+		};
+
+		user1o {
+			label = "user1:orange";
+			gpios = <&gpio1 8 1>;
+			default-state = "on";
+		};
+
+		user1g {
+			label = "user1:green";
+			gpios = <&gpio1 9 1>;
+			default-state = "on";
+		};
+
+		user0o {
+			label = "user0:orange";
+			gpios = <&gpio1 12 1>;
+			default-state = "on";
+		};
+
+		user0g {
+			label = "user0:green";
+			gpios = <&gpio1 13 1>;
+			default-state = "on";
+		};
+
+		misc {
+			label = "status:orange:misc";
+			gpios = <&gpio1 14 1>;
+			default-state = "on";
+		};
+
+	};
+};
+
diff --git a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
new file mode 100644
index 0000000..9bc6785
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
@@ -0,0 +1,63 @@
+/include/ "kirkwood.dtsi"
+
+/ {
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	ocp@f1000000 {
+		serial@12000 {
+			clock-frequency = <166666667>;
+			status = "okay";
+		};
+
+		spi@10600 {
+			status = "okay";
+
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "mx25l4005a";
+				reg = <0>;
+				spi-max-frequency = <20000000>;
+				mode = <0>;
+
+				partition@0 {
+					reg = <0x0 0x80000>;
+					label = "u-boot";
+				};
+			};
+		};
+
+		i2c@11000 {
+			status = "okay";
+
+			eeprom@50 {
+				compatible = "at,24c04";
+				pagesize = <16>;
+				reg = <0x50>;
+			};
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		button@1 {
+			label = "Power push button";
+			linux,code = <116>;
+			gpios = <&gpio1 0 0>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		red-fail {
+			label = "ns2:red:fail";
+			gpios = <&gpio0 12 0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-ns2.dts b/arch/arm/boot/dts/kirkwood-ns2.dts
new file mode 100644
index 0000000..f2d36ecf
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ns2.dts
@@ -0,0 +1,30 @@
+/dts-v1/;
+
+/include/ "kirkwood-ns2-common.dtsi"
+
+/ {
+	model = "LaCie Network Space v2";
+	compatible = "lacie,netspace_v2", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>;
+	};
+
+	ocp@f1000000 {
+		sata@80000 {
+			status = "okay";
+			nr-ports = <1>;
+		};
+	};
+
+	ns2-leds {
+		compatible = "lacie,ns2-leds";
+
+		blue-sata {
+			label = "ns2:blue:sata";
+			slow-gpio = <&gpio0 29 0>;
+			cmd-gpio = <&gpio0 30 0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-ns2lite.dts b/arch/arm/boot/dts/kirkwood-ns2lite.dts
new file mode 100644
index 0000000..b02eb4e
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ns2lite.dts
@@ -0,0 +1,30 @@
+/dts-v1/;
+
+/include/ "kirkwood-ns2-common.dtsi"
+
+/ {
+	model = "LaCie Network Space Lite v2";
+	compatible = "lacie,netspace_lite_v2", "marvell,kirkwood-88f6192", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	ocp@f1000000 {
+		sata@80000 {
+			status = "okay";
+			nr-ports = <1>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		blue-sata {
+			label = "ns2:blue:sata";
+			gpios = <&gpio0 30 1>;
+			linux,default-trigger = "default-on";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-ns2max.dts b/arch/arm/boot/dts/kirkwood-ns2max.dts
new file mode 100644
index 0000000..bcec4d6
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ns2max.dts
@@ -0,0 +1,49 @@
+/dts-v1/;
+
+/include/ "kirkwood-ns2-common.dtsi"
+
+/ {
+	model = "LaCie Network Space Max v2";
+	compatible = "lacie,netspace_max_v2", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>;
+	};
+
+	ocp@f1000000 {
+		sata@80000 {
+			status = "okay";
+			nr-ports = <2>;
+		};
+	};
+
+	gpio_fan {
+		compatible = "gpio-fan";
+		gpios = <&gpio0 22 1
+			 &gpio0  7 1
+			 &gpio1  1 1
+			 &gpio0 23 1>;
+		gpio-fan,speed-map =
+			<   0  0
+			 1500 15
+			 1700 14
+			 1800 13
+			 2100 12
+			 3100 11
+			 3300 10
+			 4300  9
+			 5500  8>;
+		alarm-gpios = <&gpio0 25 1>;
+	};
+
+	ns2-leds {
+		compatible = "lacie,ns2-leds";
+
+		blue-sata {
+			label = "ns2:blue:sata";
+			slow-gpio = <&gpio0 29 0>;
+			cmd-gpio = <&gpio0 30 0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-ns2mini.dts b/arch/arm/boot/dts/kirkwood-ns2mini.dts
new file mode 100644
index 0000000..b79f5eb
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-ns2mini.dts
@@ -0,0 +1,49 @@
+/dts-v1/;
+
+/include/ "kirkwood-ns2-common.dtsi"
+
+/ {
+	model = "LaCie Network Space Mini v2";
+	compatible = "lacie,netspace_mini_v2", "marvell,kirkwood-88f6192", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	ocp@f1000000 {
+		sata@80000 {
+			status = "okay";
+			nr-ports = <1>;
+		};
+	};
+
+	gpio_fan {
+		compatible = "gpio-fan";
+		gpios = <&gpio0 22 1
+			 &gpio0  7 1
+			 &gpio1  1 1
+			 &gpio0 23 1>;
+		gpio-fan,speed-map =
+			<   0  0
+			 3000 15
+			 3180 14
+			 4140 13
+			 4570 12
+			 6760 11
+			 7140 10
+			 7980  9
+			 9200  8>;
+		alarm-gpios = <&gpio0 25 1>;
+	};
+
+	ns2-leds {
+		compatible = "lacie,ns2-leds";
+
+		blue-sata {
+			label = "ns2:blue:sata";
+			slow-gpio = <&gpio0 29 0>;
+			cmd-gpio = <&gpio0 30 0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-nsa310.dts b/arch/arm/boot/dts/kirkwood-nsa310.dts
new file mode 100644
index 0000000..5509f96
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-nsa310.dts
@@ -0,0 +1,144 @@
+/dts-v1/;
+
+/include/ "kirkwood.dtsi"
+
+/ {
+	model = "ZyXEL NSA310";
+	compatible = "zyxel,nsa310", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200";
+	};
+
+	ocp@f1000000 {
+
+		serial@12000 {
+			clock-frequency = <200000000>;
+			status = "ok";
+		};
+
+		sata@80000 {
+			status = "okay";
+			nr-ports = <2>;
+		};
+
+		i2c@11000 {
+			status = "okay";
+		};
+
+		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>;
+			};
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		button@1 {
+			label = "Power Button";
+			linux,code = <116>;
+			gpios = <&gpio1 14 0>;
+		};
+		button@2 {
+			label = "Copy Button";
+			linux,code = <133>;
+			gpios = <&gpio1 5 1>;
+		};
+		button@3 {
+			label = "Reset Button";
+			linux,code = <0x198>;
+			gpios = <&gpio1 4 1>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		green-sys {
+			label = "nsa310:green:sys";
+			gpios = <&gpio0 28 0>;
+		};
+		red-sys {
+			label = "nsa310:red:sys";
+			gpios = <&gpio0 29 0>;
+		};
+		green-hdd {
+			label = "nsa310:green:hdd";
+			gpios = <&gpio1 9 0>;
+		};
+		red-hdd {
+			label = "nsa310:red:hdd";
+			gpios = <&gpio1 10 0>;
+		};
+		green-esata {
+			label = "nsa310:green:esata";
+			gpios = <&gpio0 12 0>;
+		};
+		red-esata {
+			label = "nsa310:red:esata";
+			gpios = <&gpio0 13 0>;
+		};
+		green-usb {
+			label = "nsa310:green:usb";
+			gpios = <&gpio0 15 0>;
+		};
+		red-usb {
+			label = "nsa310:red:usb";
+			gpios = <&gpio0 16 0>;
+		};
+		green-copy {
+			label = "nsa310:green:copy";
+			gpios = <&gpio1 7 0>;
+		};
+		red-copy {
+			label = "nsa310:red:copy";
+			gpios = <&gpio1 8 0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-openblocks_a6.dts b/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
new file mode 100644
index 0000000..49d3d74
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
@@ -0,0 +1,98 @@
+/dts-v1/;
+
+/include/ "kirkwood.dtsi"
+/include/ "kirkwood-6282.dtsi"
+
+/ {
+	model = "Plat'Home OpenBlocksA6";
+	compatible = "plathome,openblocks-a6", "marvell,kirkwood-88f6283", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x20000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 earlyprintk";
+	};
+
+	ocp@f1000000 {
+		serial@12000 {
+			clock-frequency = <200000000>;
+			status = "ok";
+		};
+
+		serial@12100 {
+			clock-frequency = <200000000>;
+			status = "ok";
+		};
+
+		nand@3000000 {
+			chip-delay = <25>;
+			status = "okay";
+
+			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";
+		};
+
+		i2c@11100 {
+			status = "okay";
+
+			s35390a: s35390a@30 {
+				compatible = "s35390a";
+				reg = <0x30>;
+			};
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		led-red {
+			label = "obsa6:red:stat";
+			gpios = <&gpio1 9 1>;
+		};
+
+		led-green {
+			label = "obsa6:green:stat";
+			gpios = <&gpio1 10 1>;
+		};
+
+		led-yellow {
+			label = "obsa6:yellow:stat";
+			gpios = <&gpio1 11 1>;
+		};
+        };
+};
diff --git a/arch/arm/boot/dts/kirkwood-topkick.dts b/arch/arm/boot/dts/kirkwood-topkick.dts
new file mode 100644
index 0000000..c0de5a7
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-topkick.dts
@@ -0,0 +1,85 @@
+/dts-v1/;
+
+/include/ "kirkwood.dtsi"
+
+/ {
+	model = "Univeral Scientific Industrial Co. Topkick-1281P2";
+	compatible = "usi,topkick-1281P2", "usi,topkick", "marvell,kirkwood-88f6282", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 earlyprintk";
+	};
+
+	ocp@f1000000 {
+		serial@12000 {
+			clock-frequency = <200000000>;
+			status = "ok";
+		};
+
+		nand@3000000 {
+			status = "okay";
+
+			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>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		disk {
+			label = "topkick:yellow:disk";
+			gpios = <&gpio0 21 1>;
+			linux,default-trigger = "ide-disk";
+		};
+		system2 {
+			label = "topkick:red:system";
+			gpios = <&gpio1 5 1>;
+		};
+		system {
+			label = "topkick:blue:system";
+			gpios = <&gpio1 6 1>;
+			default-state = "on";
+		};
+		wifi {
+			label = "topkick:green:wifi";
+			gpios = <&gpio1 7 1>;
+		};
+		wifi2 {
+			label = "topkick:yellow:wifi";
+			gpios = <&gpio1 16 1>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-ts219-6281.dts b/arch/arm/boot/dts/kirkwood-ts219-6281.dts
index ccbf327..8295c83 100644
--- a/arch/arm/boot/dts/kirkwood-ts219-6281.dts
+++ b/arch/arm/boot/dts/kirkwood-ts219-6281.dts
@@ -1,8 +1,39 @@
 /dts-v1/;
 
 /include/ "kirkwood-ts219.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
+	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+
+			pinctrl-0 = < &pmx_uart0 &pmx_uart1 &pmx_spi
+				      &pmx_twsi0 &pmx_sata0 &pmx_sata1
+				      &pmx_ram_size &pmx_reset_button
+				      &pmx_USB_copy_button &pmx_board_id>;
+			pinctrl-names = "default";
+
+			pmx_ram_size: pmx-ram-size {
+				/* RAM: 0: 256 MB, 1: 512 MB */
+				marvell,pins = "mpp36";
+				marvell,function = "gpio";
+			};
+			pmx_USB_copy_button: pmx-USB-copy-button {
+				marvell,pins = "mpp15";
+				marvell,function = "gpio";
+			};
+			pmx_reset_button: pmx-reset-button {
+				marvell,pins = "mpp16";
+				marvell,function = "gpio";
+			};
+			pmx_board_id: pmx-board-id {
+				/* 0: TS-11x, 1: TS-21x */
+				marvell,pins = "mpp44";
+				marvell,function = "gpio";
+			};
+		};
+	};
+
 	gpio_keys {
 		compatible = "gpio-keys";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/kirkwood-ts219-6282.dts b/arch/arm/boot/dts/kirkwood-ts219-6282.dts
index fbe9932..df3f95d 100644
--- a/arch/arm/boot/dts/kirkwood-ts219-6282.dts
+++ b/arch/arm/boot/dts/kirkwood-ts219-6282.dts
@@ -1,8 +1,39 @@
 /dts-v1/;
 
 /include/ "kirkwood-ts219.dtsi"
+/include/ "kirkwood-6282.dtsi"
 
 / {
+	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+
+			pinctrl-0 = < &pmx_uart0 &pmx_uart1 &pmx_spi
+				      &pmx_twsi0 &pmx_sata0 &pmx_sata1
+				      &pmx_ram_size &pmx_reset_button
+				      &pmx_USB_copy_button &pmx_board_id>;
+			pinctrl-names = "default";
+
+			pmx_ram_size: pmx-ram-size {
+				/* RAM: 0: 256 MB, 1: 512 MB */
+				marvell,pins = "mpp36";
+				marvell,function = "gpio";
+			};
+			pmx_reset_button: pmx-reset-button {
+				marvell,pins = "mpp37";
+				marvell,function = "gpio";
+			};
+			pmx_USB_copy_button: pmx-USB-copy-button {
+				marvell,pins = "mpp43";
+				marvell,function = "gpio";
+			};
+			pmx_board_id: pmx-board-id {
+				/* 0: TS-11x, 1: TS-21x */
+				marvell,pins = "mpp44";
+				marvell,function = "gpio";
+			};
+		};
+	};
+
 	gpio_keys {
 		compatible = "gpio-keys";
 		#address-cells = <1>;
diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi
index 4e5b815..a990c30 100644
--- a/arch/arm/boot/dts/kirkwood.dtsi
+++ b/arch/arm/boot/dts/kirkwood.dtsi
@@ -4,6 +4,10 @@
 	compatible = "marvell,kirkwood";
 	interrupt-parent = <&intc>;
 
+	aliases {
+	       gpio0 = &gpio0;
+	       gpio1 = &gpio1;
+	};
 	intc: interrupt-controller {
 		compatible = "marvell,orion-intc", "marvell,intc";
 		interrupt-controller;
@@ -24,7 +28,8 @@
 			#gpio-cells = <2>;
 			gpio-controller;
 			reg = <0x10100 0x40>;
-			ngpio = <32>;
+			ngpios = <32>;
+			interrupt-controller;
 			interrupts = <35>, <36>, <37>, <38>;
 		};
 
@@ -33,7 +38,8 @@
 			#gpio-cells = <2>;
 			gpio-controller;
 			reg = <0x10140 0x40>;
-			ngpio = <18>;
+			ngpios = <18>;
+			interrupt-controller;
 			interrupts = <39>, <40>, <41>;
 		};
 
@@ -77,6 +83,13 @@
 			status = "okay";
 		};
 
+		ehci@50000 {
+			compatible = "marvell,orion-ehci";
+			reg = <0x50000 0x1000>;
+			interrupts = <19>;
+			status = "okay";
+		};
+
 		sata@80000 {
 			compatible = "marvell,orion-sata";
 			reg = <0x80000 0x5000>;
diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi
index e5ffe96..1582f48 100644
--- a/arch/arm/boot/dts/lpc32xx.dtsi
+++ b/arch/arm/boot/dts/lpc32xx.dtsi
@@ -182,6 +182,13 @@
 				pnx,timeout = <0x64>;
 			};
 
+			mpwm: mpwm@400E8000 {
+				compatible = "nxp,lpc3220-motor-pwm";
+				reg = <0x400E8000 0x78>;
+				status = "disabled";
+				#pwm-cells = <2>;
+			};
+
 			i2cusb: i2c@31020300 {
 				compatible = "nxp,pnx-i2c";
 				reg = <0x31020300 0x100>;
diff --git a/arch/arm/boot/dts/omap2.dtsi b/arch/arm/boot/dts/omap2.dtsi
index 581cb08..761c4b6 100644
--- a/arch/arm/boot/dts/omap2.dtsi
+++ b/arch/arm/boot/dts/omap2.dtsi
@@ -12,6 +12,7 @@
 
 / {
 	compatible = "ti,omap2430", "ti,omap2420", "ti,omap2";
+	interrupt-parent = <&intc>;
 
 	aliases {
 		serial0 = &uart1;
@@ -65,5 +66,90 @@
 			ti,hwmods = "uart3";
 			clock-frequency = <48000000>;
 		};
+
+		timer2: timer@4802a000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4802a000 0x400>;
+			interrupts = <38>;
+			ti,hwmods = "timer2";
+		};
+
+		timer3: timer@48078000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48078000 0x400>;
+			interrupts = <39>;
+			ti,hwmods = "timer3";
+		};
+
+		timer4: timer@4807a000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4807a000 0x400>;
+			interrupts = <40>;
+			ti,hwmods = "timer4";
+		};
+
+		timer5: timer@4807c000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4807c000 0x400>;
+			interrupts = <41>;
+			ti,hwmods = "timer5";
+			ti,timer-dsp;
+		};
+
+		timer6: timer@4807e000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4807e000 0x400>;
+			interrupts = <42>;
+			ti,hwmods = "timer6";
+			ti,timer-dsp;
+		};
+
+		timer7: timer@48080000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48080000 0x400>;
+			interrupts = <43>;
+			ti,hwmods = "timer7";
+			ti,timer-dsp;
+		};
+
+		timer8: timer@48082000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48082000 0x400>;
+			interrupts = <44>;
+			ti,hwmods = "timer8";
+			ti,timer-dsp;
+		};
+
+		timer9: timer@48084000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48084000 0x400>;
+			interrupts = <45>;
+			ti,hwmods = "timer9";
+			ti,timer-pwm;
+		};
+
+		timer10: timer@48086000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48086000 0x400>;
+			interrupts = <46>;
+			ti,hwmods = "timer10";
+			ti,timer-pwm;
+		};
+
+		timer11: timer@48088000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48088000 0x400>;
+			interrupts = <47>;
+			ti,hwmods = "timer11";
+			ti,timer-pwm;
+		};
+
+		timer12: timer@4808a000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4808a000 0x400>;
+			interrupts = <48>;
+			ti,hwmods = "timer12";
+			ti,timer-pwm;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/omap2420.dtsi b/arch/arm/boot/dts/omap2420.dtsi
index bfd76b4..af65609 100644
--- a/arch/arm/boot/dts/omap2420.dtsi
+++ b/arch/arm/boot/dts/omap2420.dtsi
@@ -14,6 +14,12 @@
 	compatible = "ti,omap2420", "ti,omap2";
 
 	ocp {
+		counter32k: counter@48004000 {
+			compatible = "ti,omap-counter32k";
+			reg = <0x48004000 0x20>;
+			ti,hwmods = "counter_32k";
+		};
+
 		omap2420_pmx: pinmux@48000030 {
 			compatible = "ti,omap2420-padconf", "pinctrl-single";
 			reg = <0x48000030 0x0113>;
@@ -30,7 +36,6 @@
 			interrupts = <59>, /* TX interrupt */
 				     <60>; /* RX interrupt */
 			interrupt-names = "tx", "rx";
-			interrupt-parent = <&intc>;
 			ti,hwmods = "mcbsp1";
 		};
 
@@ -41,8 +46,15 @@
 			interrupts = <62>, /* TX interrupt */
 				     <63>; /* RX interrupt */
 			interrupt-names = "tx", "rx";
-			interrupt-parent = <&intc>;
 			ti,hwmods = "mcbsp2";
 		};
+
+		timer1: timer@48028000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48028000 0x400>;
+			interrupts = <37>;
+			ti,hwmods = "timer1";
+			ti,timer-alwon;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/omap2430.dtsi b/arch/arm/boot/dts/omap2430.dtsi
index 4565d97..c392445 100644
--- a/arch/arm/boot/dts/omap2430.dtsi
+++ b/arch/arm/boot/dts/omap2430.dtsi
@@ -14,6 +14,12 @@
 	compatible = "ti,omap2430", "ti,omap2";
 
 	ocp {
+		counter32k: counter@49020000 {
+			compatible = "ti,omap-counter32k";
+			reg = <0x49020000 0x20>;
+			ti,hwmods = "counter_32k";
+		};
+
 		omap2430_pmx: pinmux@49002030 {
 			compatible = "ti,omap2430-padconf", "pinctrl-single";
 			reg = <0x49002030 0x0154>;
@@ -32,7 +38,6 @@
 				     <60>, /* RX interrupt */
 				     <61>; /* RX overflow interrupt */
 			interrupt-names = "common", "tx", "rx", "rx_overflow";
-			interrupt-parent = <&intc>;
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp1";
 		};
@@ -45,7 +50,6 @@
 				     <62>, /* TX interrupt */
 				     <63>; /* RX interrupt */
 			interrupt-names = "common", "tx", "rx";
-			interrupt-parent = <&intc>;
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp2";
 		};
@@ -58,7 +62,6 @@
 				     <89>, /* TX interrupt */
 				     <90>; /* RX interrupt */
 			interrupt-names = "common", "tx", "rx";
-			interrupt-parent = <&intc>;
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp3";
 		};
@@ -71,7 +74,6 @@
 				     <54>, /* TX interrupt */
 				     <55>; /* RX interrupt */
 			interrupt-names = "common", "tx", "rx";
-			interrupt-parent = <&intc>;
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp4";
 		};
@@ -84,9 +86,16 @@
 				     <81>, /* TX interrupt */
 				     <82>; /* RX interrupt */
 			interrupt-names = "common", "tx", "rx";
-			interrupt-parent = <&intc>;
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp5";
 		};
+
+		timer1: timer@49018000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x49018000 0x400>;
+			interrupts = <37>;
+			ti,hwmods = "timer1";
+			ti,timer-alwon;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/omap3-beagle-xm.dts b/arch/arm/boot/dts/omap3-beagle-xm.dts
index c38cf76..3705a81 100644
--- a/arch/arm/boot/dts/omap3-beagle-xm.dts
+++ b/arch/arm/boot/dts/omap3-beagle-xm.dts
@@ -55,12 +55,6 @@
 		interrupts = <7>; /* SYS_NIRQ cascaded to intc */
 		interrupt-parent = <&intc>;
 
-		vsim: regulator-vsim {
-			compatible = "ti,twl4030-vsim";
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <3000000>;
-		};
-
 		twl_audio: audio {
 			compatible = "ti,twl4030-audio";
 			codec {
diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts
new file mode 100644
index 0000000..f624dc8
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-beagle.dts
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap3.dtsi"
+
+/ {
+	model = "TI OMAP3 BeagleBoard";
+	compatible = "ti,omap3-beagle", "ti,omap3";
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pmu_stat {
+			label = "beagleboard::pmu_stat";
+			gpios = <&twl_gpio 19 0>; /* LEDB */
+		};
+
+		heartbeat {
+			label = "beagleboard::usr0";
+			gpios = <&gpio5 22 0>; /* 150 -> D6 LED */
+			linux,default-trigger = "heartbeat";
+		};
+
+		mmc {
+			label = "beagleboard::usr1";
+			gpios = <&gpio5 21 0>; /* 149 -> D7 LED */
+			linux,default-trigger = "mmc0";
+		};
+	};
+
+};
+
+&i2c1 {
+	clock-frequency = <2600000>;
+
+	twl: twl@48 {
+		reg = <0x48>;
+		interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+		interrupt-parent = <&intc>;
+	};
+};
+
+/include/ "twl4030.dtsi"
+
+&mmc1 {
+	vmmc-supply = <&vmmc1>;
+	vmmc_aux-supply = <&vsim>;
+	bus-width = <8>;
+};
+
+&mmc2 {
+	status = "disabled";
+};
+
+&mmc3 {
+	status = "disabled";
+};
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 696e929..1acc261 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -12,6 +12,7 @@
 
 / {
 	compatible = "ti,omap3430", "ti,omap3";
+	interrupt-parent = <&intc>;
 
 	aliases {
 		serial0 = &uart1;
@@ -60,6 +61,12 @@
 		ranges;
 		ti,hwmods = "l3_main";
 
+		counter32k: counter@48320000 {
+			compatible = "ti,omap-counter32k";
+			reg = <0x48320000 0x20>;
+			ti,hwmods = "counter_32k";
+		};
+
 		intc: interrupt-controller@48200000 {
 			compatible = "ti,omap2-intc";
 			interrupt-controller;
@@ -240,7 +247,6 @@
 				     <59>, /* TX interrupt */
 				     <60>; /* RX interrupt */
 			interrupt-names = "common", "tx", "rx";
-			interrupt-parent = <&intc>;
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp1";
 		};
@@ -255,7 +261,6 @@
 				     <63>, /* RX interrupt */
 				     <4>;  /* Sidetone */
 			interrupt-names = "common", "tx", "rx", "sidetone";
-			interrupt-parent = <&intc>;
 			ti,buffer-size = <1280>;
 			ti,hwmods = "mcbsp2", "mcbsp2_sidetone";
 		};
@@ -270,7 +275,6 @@
 				     <90>, /* RX interrupt */
 				     <5>;  /* Sidetone */
 			interrupt-names = "common", "tx", "rx", "sidetone";
-			interrupt-parent = <&intc>;
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp3", "mcbsp3_sidetone";
 		};
@@ -283,7 +287,6 @@
 				     <54>, /* TX interrupt */
 				     <55>; /* RX interrupt */
 			interrupt-names = "common", "tx", "rx";
-			interrupt-parent = <&intc>;
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp4";
 		};
@@ -296,9 +299,103 @@
 				     <81>, /* TX interrupt */
 				     <82>; /* RX interrupt */
 			interrupt-names = "common", "tx", "rx";
-			interrupt-parent = <&intc>;
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp5";
 		};
+
+		timer1: timer@48318000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48318000 0x400>;
+			interrupts = <37>;
+			ti,hwmods = "timer1";
+			ti,timer-alwon;
+		};
+
+		timer2: timer@49032000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x49032000 0x400>;
+			interrupts = <38>;
+			ti,hwmods = "timer2";
+		};
+
+		timer3: timer@49034000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x49034000 0x400>;
+			interrupts = <39>;
+			ti,hwmods = "timer3";
+		};
+
+		timer4: timer@49036000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x49036000 0x400>;
+			interrupts = <40>;
+			ti,hwmods = "timer4";
+		};
+
+		timer5: timer@49038000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x49038000 0x400>;
+			interrupts = <41>;
+			ti,hwmods = "timer5";
+			ti,timer-dsp;
+		};
+
+		timer6: timer@4903a000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4903a000 0x400>;
+			interrupts = <42>;
+			ti,hwmods = "timer6";
+			ti,timer-dsp;
+		};
+
+		timer7: timer@4903c000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4903c000 0x400>;
+			interrupts = <43>;
+			ti,hwmods = "timer7";
+			ti,timer-dsp;
+		};
+
+		timer8: timer@4903e000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4903e000 0x400>;
+			interrupts = <44>;
+			ti,hwmods = "timer8";
+			ti,timer-pwm;
+			ti,timer-dsp;
+		};
+
+		timer9: timer@49040000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x49040000 0x400>;
+			interrupts = <45>;
+			ti,hwmods = "timer9";
+			ti,timer-pwm;
+		};
+
+		timer10: timer@48086000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48086000 0x400>;
+			interrupts = <46>;
+			ti,hwmods = "timer10";
+			ti,timer-pwm;
+		};
+
+		timer11: timer@48088000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48088000 0x400>;
+			interrupts = <47>;
+			ti,hwmods = "timer11";
+			ti,timer-pwm;
+		};
+
+		timer12: timer@48304000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48304000 0x400>;
+			interrupts = <95>;
+			ti,hwmods = "timer12";
+			ti,timer-alwon;
+			ti,timer-secure;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/omap4-panda-a4.dts b/arch/arm/boot/dts/omap4-panda-a4.dts
new file mode 100644
index 0000000..75466d2
--- /dev/null
+++ b/arch/arm/boot/dts/omap4-panda-a4.dts
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+/include/ "omap4-panda.dts"
+
+/* Pandaboard Rev A4+ have external pullups on SCL & SDA */
+&dss_hdmi_pins {
+	pinctrl-single,pins = <
+		0x5a 0x118	/* hdmi_cec.hdmi_cec INPUT PULLUP | MODE 0 */
+		0x5c 0x100	/* hdmi_scl.hdmi_scl INPUT | MODE 0 */
+		0x5e 0x100	/* hdmi_sda.hdmi_sda INPUT | MODE 0 */
+		>;
+};
diff --git a/arch/arm/boot/dts/omap4-panda-es.dts b/arch/arm/boot/dts/omap4-panda-es.dts
new file mode 100644
index 0000000..73bc1a6
--- /dev/null
+++ b/arch/arm/boot/dts/omap4-panda-es.dts
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+/include/ "omap4-panda.dts"
+
+/* Audio routing is differnet between PandaBoard4430 and PandaBoardES */
+&sound {
+	ti,model = "PandaBoardES";
+
+	/* Audio routing */
+	ti,audio-routing =
+		"Headset Stereophone", "HSOL",
+		"Headset Stereophone", "HSOR",
+		"Ext Spk", "HFL",
+		"Ext Spk", "HFR",
+		"Line Out", "AUXL",
+		"Line Out", "AUXR",
+		"AFML", "Line In",
+		"AFMR", "Line In";
+};
+
+/* PandaboardES has external pullups on SCL & SDA */
+&dss_hdmi_pins {
+	pinctrl-single,pins = <
+		0x5a 0x118	/* hdmi_cec.hdmi_cec INPUT PULLUP | MODE 0 */
+		0x5c 0x100	/* hdmi_scl.hdmi_scl INPUT | MODE 0 */
+		0x5e 0x100	/* hdmi_sda.hdmi_sda INPUT | MODE 0 */
+		>;
+};
diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts
index e8f927c..4122efe 100644
--- a/arch/arm/boot/dts/omap4-panda.dts
+++ b/arch/arm/boot/dts/omap4-panda.dts
@@ -65,6 +65,8 @@
 			&twl6040_pins
 			&mcpdm_pins
 			&mcbsp1_pins
+			&dss_hdmi_pins
+			&tpd12s015_pins
 	>;
 
 	twl6040_pins: pinmux_twl6040_pins {
@@ -92,6 +94,22 @@
 			0xc4 0x100	/* abe_mcbsp1_fsx.abe_mcbsp1_fsx INPUT | MODE0 */
 		>;
 	};
+
+	dss_hdmi_pins: pinmux_dss_hdmi_pins {
+		pinctrl-single,pins = <
+			0x5a 0x118	/* hdmi_cec.hdmi_cec INPUT PULLUP | MODE 0 */
+			0x5c 0x118	/* hdmi_scl.hdmi_scl INPUT PULLUP | MODE 0 */
+			0x5e 0x118	/* hdmi_sda.hdmi_sda INPUT PULLUP | MODE 0 */
+		>;
+	};
+
+	tpd12s015_pins: pinmux_tpd12s015_pins {
+		pinctrl-single,pins = <
+			0x22 0x3	/* gpmc_a17.gpio_41 OUTPUT | MODE3 */
+			0x48 0x3	/* gpmc_nbe1.gpio_60 OUTPUT | MODE3 */
+			0x58 0x10b	/* hdmi_hpd.gpio_63 INPUT PULLDOWN | MODE3 */
+		>;
+	};
 };
 
 &i2c1 {
@@ -184,3 +202,7 @@
 &dmic {
 	status = "disabled";
 };
+
+&twl_usb_comparator {
+	usb-supply = <&vusb>;
+};
diff --git a/arch/arm/boot/dts/omap4-pandaES.dts b/arch/arm/boot/dts/omap4-pandaES.dts
deleted file mode 100644
index d4ba43a..0000000
--- a/arch/arm/boot/dts/omap4-pandaES.dts
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-/include/ "omap4-panda.dts"
-
-/* Audio routing is differnet between PandaBoard4430 and PandaBoardES */
-&sound {
-	ti,model = "PandaBoardES";
-
-	/* Audio routing */
-	ti,audio-routing =
-		"Headset Stereophone", "HSOL",
-		"Headset Stereophone", "HSOR",
-		"Ext Spk", "HFL",
-		"Ext Spk", "HFR",
-		"Line Out", "AUXL",
-		"Line Out", "AUXR",
-		"AFML", "Line In",
-		"AFMR", "Line In";
-};
diff --git a/arch/arm/boot/dts/omap4-sdp-es23plus.dts b/arch/arm/boot/dts/omap4-sdp-es23plus.dts
new file mode 100644
index 0000000..b4a40ff
--- /dev/null
+++ b/arch/arm/boot/dts/omap4-sdp-es23plus.dts
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+/include/ "omap4-sdp.dts"
+
+/* SDP boards with 4430 ES2.3+ or 4460 have external pullups on SCL & SDA */
+&dss_hdmi_pins {
+	pinctrl-single,pins = <
+		0x5a 0x118	/* hdmi_cec.hdmi_cec INPUT PULLUP | MODE 0 */
+		0x5c 0x100	/* hdmi_scl.hdmi_scl INPUT | MODE 0 */
+		0x5e 0x100	/* hdmi_sda.hdmi_sda INPUT | MODE 0 */
+		>;
+};
diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
index 5b7e04f..43e5258 100644
--- a/arch/arm/boot/dts/omap4-sdp.dts
+++ b/arch/arm/boot/dts/omap4-sdp.dts
@@ -124,6 +124,8 @@
 			&dmic_pins
 			&mcbsp1_pins
 			&mcbsp2_pins
+			&dss_hdmi_pins
+			&tpd12s015_pins
 	>;
 
 	uart2_pins: pinmux_uart2_pins {
@@ -194,6 +196,22 @@
 			0xbc 0x100	/* abe_mcbsp2_fsx.abe_mcbsp2_fsx INPUT | MODE0 */
 		>;
 	};
+
+	dss_hdmi_pins: pinmux_dss_hdmi_pins {
+		pinctrl-single,pins = <
+			0x5a 0x118	/* hdmi_cec.hdmi_cec INPUT PULLUP | MODE 0 */
+			0x5c 0x118	/* hdmi_scl.hdmi_scl INPUT PULLUP | MODE 0 */
+			0x5e 0x118	/* hdmi_sda.hdmi_sda INPUT PULLUP | MODE 0 */
+		>;
+	};
+
+	tpd12s015_pins: pinmux_tpd12s015_pins {
+		pinctrl-single,pins = <
+			0x22 0x3	/* gpmc_a17.gpio_41 OUTPUT | MODE3 */
+			0x48 0x3	/* gpmc_nbe1.gpio_60 OUTPUT | MODE3 */
+			0x58 0x10b	/* hdmi_hpd.gpio_63 INPUT PULLDOWN | MODE3 */
+		>;
+	};
 };
 
 &i2c1 {
@@ -406,3 +424,7 @@
 &mcbsp3 {
 	status = "disabled";
 };
+
+&twl_usb_comparator {
+	usb-supply = <&vusb>;
+};
diff --git a/arch/arm/boot/dts/omap4-var-som.dts b/arch/arm/boot/dts/omap4-var-som.dts
new file mode 100644
index 0000000..6601e6a
--- /dev/null
+++ b/arch/arm/boot/dts/omap4-var-som.dts
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 Variscite Ltd. - http://www.variscite.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap4.dtsi"
+
+/ {
+	model = "Variscite OMAP4 SOM";
+	compatible = "var,omap4-var_som", "ti,omap4430", "ti,omap4";
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x40000000>; /* 1 GB */
+	};
+
+	vdd_eth: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "VDD_ETH";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		enable-active-high;
+		regulator-boot-on;
+	};
+};
+
+&i2c1 {
+	clock-frequency = <400000>;
+
+	twl: twl@48 {
+		reg = <0x48>;
+		/* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */
+		interrupts = <0 7 4>; /* IRQ_SYS_1N cascaded to gic */
+		interrupt-parent = <&gic>;
+	};
+};
+
+/include/ "twl6030.dtsi"
+
+&i2c2 {
+	clock-frequency = <400000>;
+};
+
+&i2c3 {
+	clock-frequency = <400000>;
+
+	/*
+	 * Temperature Sensor
+	 * http://www.ti.com/lit/ds/symlink/tmp105.pdf
+	 */
+	tmp105@49 {
+		compatible = "ti,tmp105";
+		reg = <0x49>;
+	};
+};
+
+&i2c4 {
+	clock-frequency = <400000>;
+};
+
+&mcspi1 {
+	eth@0 {
+		compatible = "ks8851";
+		spi-max-frequency = <24000000>;
+		reg = <0>;
+		interrupt-parent = <&gpio6>;
+		interrupts = <11>; /* gpio line 171 */
+		vdd-supply = <&vdd_eth>;
+	};
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmc>;
+	ti,bus-width = <8>;
+	ti,non-removable;
+};
+
+&mmc2 {
+	status = "disabled";
+};
+
+&mmc3 {
+	status = "disabled";
+};
+
+&mmc4 {
+	status = "disabled";
+};
+
+&mmc5 {
+	ti,bus-width = <4>;
+};
diff --git a/arch/arm/boot/dts/omap4-var_som.dts b/arch/arm/boot/dts/omap4-var_som.dts
deleted file mode 100644
index 6601e6a..0000000
--- a/arch/arm/boot/dts/omap4-var_som.dts
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2012 Variscite Ltd. - http://www.variscite.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-/dts-v1/;
-
-/include/ "omap4.dtsi"
-
-/ {
-	model = "Variscite OMAP4 SOM";
-	compatible = "var,omap4-var_som", "ti,omap4430", "ti,omap4";
-
-	memory {
-		device_type = "memory";
-		reg = <0x80000000 0x40000000>; /* 1 GB */
-	};
-
-	vdd_eth: fixedregulator@0 {
-		compatible = "regulator-fixed";
-		regulator-name = "VDD_ETH";
-		regulator-min-microvolt = <3300000>;
-		regulator-max-microvolt = <3300000>;
-		enable-active-high;
-		regulator-boot-on;
-	};
-};
-
-&i2c1 {
-	clock-frequency = <400000>;
-
-	twl: twl@48 {
-		reg = <0x48>;
-		/* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */
-		interrupts = <0 7 4>; /* IRQ_SYS_1N cascaded to gic */
-		interrupt-parent = <&gic>;
-	};
-};
-
-/include/ "twl6030.dtsi"
-
-&i2c2 {
-	clock-frequency = <400000>;
-};
-
-&i2c3 {
-	clock-frequency = <400000>;
-
-	/*
-	 * Temperature Sensor
-	 * http://www.ti.com/lit/ds/symlink/tmp105.pdf
-	 */
-	tmp105@49 {
-		compatible = "ti,tmp105";
-		reg = <0x49>;
-	};
-};
-
-&i2c4 {
-	clock-frequency = <400000>;
-};
-
-&mcspi1 {
-	eth@0 {
-		compatible = "ks8851";
-		spi-max-frequency = <24000000>;
-		reg = <0>;
-		interrupt-parent = <&gpio6>;
-		interrupts = <11>; /* gpio line 171 */
-		vdd-supply = <&vdd_eth>;
-	};
-};
-
-&mmc1 {
-	vmmc-supply = <&vmmc>;
-	ti,bus-width = <8>;
-	ti,non-removable;
-};
-
-&mmc2 {
-	status = "disabled";
-};
-
-&mmc3 {
-	status = "disabled";
-};
-
-&mmc4 {
-	status = "disabled";
-};
-
-&mmc5 {
-	ti,bus-width = <4>;
-};
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 3883f94..739bb79 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -95,6 +95,12 @@
 		ranges;
 		ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3";
 
+		counter32k: counter@4a304000 {
+			compatible = "ti,omap-counter32k";
+			reg = <0x4a304000 0x20>;
+			ti,hwmods = "counter_32k";
+		};
+
 		omap4_pmx_core: pinmux@4a100040 {
 			compatible = "ti,omap4-padconf", "pinctrl-single";
 			reg = <0x4a100040 0x0196>;
@@ -340,7 +346,6 @@
 			      <0x49032000 0x7f>; /* L3 Interconnect */
 			reg-names = "mpu", "dma";
 			interrupts = <0 112 0x4>;
-			interrupt-parent = <&gic>;
 			ti,hwmods = "mcpdm";
 		};
 
@@ -350,7 +355,6 @@
 			      <0x4902e000 0x7f>; /* L3 Interconnect */
 			reg-names = "mpu", "dma";
 			interrupts = <0 114 0x4>;
-			interrupt-parent = <&gic>;
 			ti,hwmods = "dmic";
 		};
 
@@ -361,7 +365,6 @@
 			reg-names = "mpu", "dma";
 			interrupts = <0 17 0x4>;
 			interrupt-names = "common";
-			interrupt-parent = <&gic>;
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp1";
 		};
@@ -373,7 +376,6 @@
 			reg-names = "mpu", "dma";
 			interrupts = <0 22 0x4>;
 			interrupt-names = "common";
-			interrupt-parent = <&gic>;
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp2";
 		};
@@ -385,7 +387,6 @@
 			reg-names = "mpu", "dma";
 			interrupts = <0 23 0x4>;
 			interrupt-names = "common";
-			interrupt-parent = <&gic>;
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp3";
 		};
@@ -396,7 +397,6 @@
 			reg-names = "mpu";
 			interrupts = <0 16 0x4>;
 			interrupt-names = "common";
-			interrupt-parent = <&gic>;
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp4";
 		};
@@ -431,12 +431,103 @@
 			hw-caps-temp-alert;
 		};
 
-		ocp2scp {
+		ocp2scp@4a0ad000 {
 			compatible = "ti,omap-ocp2scp";
+			reg = <0x4a0ad000 0x1f>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges;
 			ti,hwmods = "ocp2scp_usb_phy";
 		};
+
+		timer1: timer@4a318000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4a318000 0x80>;
+			interrupts = <0 37 0x4>;
+			ti,hwmods = "timer1";
+			ti,timer-alwon;
+		};
+
+		timer2: timer@48032000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48032000 0x80>;
+			interrupts = <0 38 0x4>;
+			ti,hwmods = "timer2";
+		};
+
+		timer3: timer@48034000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48034000 0x80>;
+			interrupts = <0 39 0x4>;
+			ti,hwmods = "timer3";
+		};
+
+		timer4: timer@48036000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48036000 0x80>;
+			interrupts = <0 40 0x4>;
+			ti,hwmods = "timer4";
+		};
+
+		timer5: timer@40138000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x40138000 0x80>,
+			      <0x49038000 0x80>;
+			interrupts = <0 41 0x4>;
+			ti,hwmods = "timer5";
+			ti,timer-dsp;
+		};
+
+		timer6: timer@4013a000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4013a000 0x80>,
+			      <0x4903a000 0x80>;
+			interrupts = <0 42 0x4>;
+			ti,hwmods = "timer6";
+			ti,timer-dsp;
+		};
+
+		timer7: timer@4013c000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4013c000 0x80>,
+			      <0x4903c000 0x80>;
+			interrupts = <0 43 0x4>;
+			ti,hwmods = "timer7";
+			ti,timer-dsp;
+		};
+
+		timer8: timer@4013e000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4013e000 0x80>,
+			      <0x4903e000 0x80>;
+			interrupts = <0 44 0x4>;
+			ti,hwmods = "timer8";
+			ti,timer-pwm;
+			ti,timer-dsp;
+		};
+
+		timer9: timer@4803e000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4803e000 0x80>;
+			interrupts = <0 45 0x4>;
+			ti,hwmods = "timer9";
+			ti,timer-pwm;
+		};
+
+		timer10: timer@48086000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48086000 0x80>;
+			interrupts = <0 46 0x4>;
+			ti,hwmods = "timer10";
+			ti,timer-pwm;
+		};
+
+		timer11: timer@48088000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48088000 0x80>;
+			interrupts = <0 47 0x4>;
+			ti,hwmods = "timer11";
+			ti,timer-pwm;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/omap5-evm.dts b/arch/arm/boot/dts/omap5-evm.dts
index c663eba..8722c15 100644
--- a/arch/arm/boot/dts/omap5-evm.dts
+++ b/arch/arm/boot/dts/omap5-evm.dts
@@ -8,6 +8,7 @@
 /dts-v1/;
 
 /include/ "omap5.dtsi"
+/include/ "samsung_k3pe0e000b.dtsi"
 
 / {
 	model = "TI OMAP5 EVM board";
@@ -15,7 +16,7 @@
 
 	memory {
 		device_type = "memory";
-		reg = <0x80000000 0x40000000>; /* 1 GB */
+		reg = <0x80000000 0x80000000>; /* 2 GB */
 	};
 
 	vmmcsd_fixed: fixedregulator-mmcsd {
@@ -140,3 +141,13 @@
 &mcbsp3 {
 	status = "disabled";
 };
+
+&emif1 {
+	cs1-used;
+	device-handle = <&samsung_K3PE0E000B>;
+};
+
+&emif2 {
+	cs1-used;
+	device-handle = <&samsung_K3PE0E000B>;
+};
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 42c78be..790bb2a 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -77,6 +77,12 @@
 		ranges;
 		ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3";
 
+		counter32k: counter@4ae04000 {
+			compatible = "ti,omap-counter32k";
+			reg = <0x4ae04000 0x40>;
+			ti,hwmods = "counter_32k";
+		};
+
 		omap5_pmx_core: pinmux@4a002840 {
 			compatible = "ti,omap4-padconf", "pinctrl-single";
 			reg = <0x4a002840 0x01b6>;
@@ -104,6 +110,8 @@
 
 		gpio1: gpio@4ae10000 {
 			compatible = "ti,omap4-gpio";
+			reg = <0x4ae10000 0x200>;
+			interrupts = <0 29 0x4>;
 			ti,hwmods = "gpio1";
 			gpio-controller;
 			#gpio-cells = <2>;
@@ -113,6 +121,8 @@
 
 		gpio2: gpio@48055000 {
 			compatible = "ti,omap4-gpio";
+			reg = <0x48055000 0x200>;
+			interrupts = <0 30 0x4>;
 			ti,hwmods = "gpio2";
 			gpio-controller;
 			#gpio-cells = <2>;
@@ -122,6 +132,8 @@
 
 		gpio3: gpio@48057000 {
 			compatible = "ti,omap4-gpio";
+			reg = <0x48057000 0x200>;
+			interrupts = <0 31 0x4>;
 			ti,hwmods = "gpio3";
 			gpio-controller;
 			#gpio-cells = <2>;
@@ -131,6 +143,8 @@
 
 		gpio4: gpio@48059000 {
 			compatible = "ti,omap4-gpio";
+			reg = <0x48059000 0x200>;
+			interrupts = <0 32 0x4>;
 			ti,hwmods = "gpio4";
 			gpio-controller;
 			#gpio-cells = <2>;
@@ -140,6 +154,8 @@
 
 		gpio5: gpio@4805b000 {
 			compatible = "ti,omap4-gpio";
+			reg = <0x4805b000 0x200>;
+			interrupts = <0 33 0x4>;
 			ti,hwmods = "gpio5";
 			gpio-controller;
 			#gpio-cells = <2>;
@@ -149,6 +165,8 @@
 
 		gpio6: gpio@4805d000 {
 			compatible = "ti,omap4-gpio";
+			reg = <0x4805d000 0x200>;
+			interrupts = <0 34 0x4>;
 			ti,hwmods = "gpio6";
 			gpio-controller;
 			#gpio-cells = <2>;
@@ -158,6 +176,8 @@
 
 		gpio7: gpio@48051000 {
 			compatible = "ti,omap4-gpio";
+			reg = <0x48051000 0x200>;
+			interrupts = <0 35 0x4>;
 			ti,hwmods = "gpio7";
 			gpio-controller;
 			#gpio-cells = <2>;
@@ -167,6 +187,8 @@
 
 		gpio8: gpio@48053000 {
 			compatible = "ti,omap4-gpio";
+			reg = <0x48053000 0x200>;
+			interrupts = <0 121 0x4>;
 			ti,hwmods = "gpio8";
 			gpio-controller;
 			#gpio-cells = <2>;
@@ -176,6 +198,8 @@
 
 		i2c1: i2c@48070000 {
 			compatible = "ti,omap4-i2c";
+			reg = <0x48070000 0x100>;
+			interrupts = <0 56 0x4>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c1";
@@ -183,6 +207,8 @@
 
 		i2c2: i2c@48072000 {
 			compatible = "ti,omap4-i2c";
+			reg = <0x48072000 0x100>;
+			interrupts = <0 57 0x4>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c2";
@@ -190,20 +216,26 @@
 
 		i2c3: i2c@48060000 {
 			compatible = "ti,omap4-i2c";
+			reg = <0x48060000 0x100>;
+			interrupts = <0 61 0x4>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c3";
 		};
 
-		i2c4: i2c@4807A000 {
+		i2c4: i2c@4807a000 {
 			compatible = "ti,omap4-i2c";
+			reg = <0x4807a000 0x100>;
+			interrupts = <0 62 0x4>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c4";
 		};
 
-		i2c5: i2c@4807C000 {
+		i2c5: i2c@4807c000 {
 			compatible = "ti,omap4-i2c";
+			reg = <0x4807c000 0x100>;
+			interrupts = <0 60 0x4>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c5";
@@ -211,42 +243,56 @@
 
 		uart1: serial@4806a000 {
 			compatible = "ti,omap4-uart";
+			reg = <0x4806a000 0x100>;
+			interrupts = <0 72 0x4>;
 			ti,hwmods = "uart1";
 			clock-frequency = <48000000>;
 		};
 
 		uart2: serial@4806c000 {
 			compatible = "ti,omap4-uart";
+			reg = <0x4806c000 0x100>;
+			interrupts = <0 73 0x4>;
 			ti,hwmods = "uart2";
 			clock-frequency = <48000000>;
 		};
 
 		uart3: serial@48020000 {
 			compatible = "ti,omap4-uart";
+			reg = <0x48020000 0x100>;
+			interrupts = <0 74 0x4>;
 			ti,hwmods = "uart3";
 			clock-frequency = <48000000>;
 		};
 
 		uart4: serial@4806e000 {
 			compatible = "ti,omap4-uart";
+			reg = <0x4806e000 0x100>;
+			interrupts = <0 70 0x4>;
 			ti,hwmods = "uart4";
 			clock-frequency = <48000000>;
 		};
 
 		uart5: serial@48066000 {
-			compatible = "ti,omap5-uart";
+			compatible = "ti,omap4-uart";
+			reg = <0x48066000 0x100>;
+			interrupts = <0 105 0x4>;
 			ti,hwmods = "uart5";
 			clock-frequency = <48000000>;
 		};
 
 		uart6: serial@48068000 {
-			compatible = "ti,omap6-uart";
+			compatible = "ti,omap4-uart";
+			reg = <0x48068000 0x100>;
+			interrupts = <0 106 0x4>;
 			ti,hwmods = "uart6";
 			clock-frequency = <48000000>;
 		};
 
 		mmc1: mmc@4809c000 {
 			compatible = "ti,omap4-hsmmc";
+			reg = <0x4809c000 0x400>;
+			interrupts = <0 83 0x4>;
 			ti,hwmods = "mmc1";
 			ti,dual-volt;
 			ti,needs-special-reset;
@@ -254,24 +300,32 @@
 
 		mmc2: mmc@480b4000 {
 			compatible = "ti,omap4-hsmmc";
+			reg = <0x480b4000 0x400>;
+			interrupts = <0 86 0x4>;
 			ti,hwmods = "mmc2";
 			ti,needs-special-reset;
 		};
 
 		mmc3: mmc@480ad000 {
 			compatible = "ti,omap4-hsmmc";
+			reg = <0x480ad000 0x400>;
+			interrupts = <0 94 0x4>;
 			ti,hwmods = "mmc3";
 			ti,needs-special-reset;
 		};
 
 		mmc4: mmc@480d1000 {
 			compatible = "ti,omap4-hsmmc";
+			reg = <0x480d1000 0x400>;
+			interrupts = <0 96 0x4>;
 			ti,hwmods = "mmc4";
 			ti,needs-special-reset;
 		};
 
 		mmc5: mmc@480d5000 {
 			compatible = "ti,omap4-hsmmc";
+			reg = <0x480d5000 0x400>;
+			interrupts = <0 59 0x4>;
 			ti,hwmods = "mmc5";
 			ti,needs-special-reset;
 		};
@@ -287,7 +341,6 @@
 			      <0x49032000 0x7f>; /* L3 Interconnect */
 			reg-names = "mpu", "dma";
 			interrupts = <0 112 0x4>;
-			interrupt-parent = <&gic>;
 			ti,hwmods = "mcpdm";
 		};
 
@@ -297,7 +350,6 @@
 			      <0x4902e000 0x7f>; /* L3 Interconnect */
 			reg-names = "mpu", "dma";
 			interrupts = <0 114 0x4>;
-			interrupt-parent = <&gic>;
 			ti,hwmods = "dmic";
 		};
 
@@ -308,7 +360,6 @@
 			reg-names = "mpu", "dma";
 			interrupts = <0 17 0x4>;
 			interrupt-names = "common";
-			interrupt-parent = <&gic>;
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp1";
 		};
@@ -320,7 +371,6 @@
 			reg-names = "mpu", "dma";
 			interrupts = <0 22 0x4>;
 			interrupt-names = "common";
-			interrupt-parent = <&gic>;
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp2";
 		};
@@ -332,9 +382,119 @@
 			reg-names = "mpu", "dma";
 			interrupts = <0 23 0x4>;
 			interrupt-names = "common";
-			interrupt-parent = <&gic>;
 			ti,buffer-size = <128>;
 			ti,hwmods = "mcbsp3";
 		};
+
+		timer1: timer@4ae18000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4ae18000 0x80>;
+			interrupts = <0 37 0x4>;
+			ti,hwmods = "timer1";
+			ti,timer-alwon;
+		};
+
+		timer2: timer@48032000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48032000 0x80>;
+			interrupts = <0 38 0x4>;
+			ti,hwmods = "timer2";
+		};
+
+		timer3: timer@48034000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48034000 0x80>;
+			interrupts = <0 39 0x4>;
+			ti,hwmods = "timer3";
+		};
+
+		timer4: timer@48036000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48036000 0x80>;
+			interrupts = <0 40 0x4>;
+			ti,hwmods = "timer4";
+		};
+
+		timer5: timer@40138000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x40138000 0x80>,
+			      <0x49038000 0x80>;
+			interrupts = <0 41 0x4>;
+			ti,hwmods = "timer5";
+			ti,timer-dsp;
+		};
+
+		timer6: timer@4013a000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4013a000 0x80>,
+			      <0x4903a000 0x80>;
+			interrupts = <0 42 0x4>;
+			ti,hwmods = "timer6";
+			ti,timer-dsp;
+			ti,timer-pwm;
+		};
+
+		timer7: timer@4013c000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4013c000 0x80>,
+			      <0x4903c000 0x80>;
+			interrupts = <0 43 0x4>;
+			ti,hwmods = "timer7";
+			ti,timer-dsp;
+		};
+
+		timer8: timer@4013e000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4013e000 0x80>,
+			      <0x4903e000 0x80>;
+			interrupts = <0 44 0x4>;
+			ti,hwmods = "timer8";
+			ti,timer-dsp;
+			ti,timer-pwm;
+		};
+
+		timer9: timer@4803e000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x4803e000 0x80>;
+			interrupts = <0 45 0x4>;
+			ti,hwmods = "timer9";
+		};
+
+		timer10: timer@48086000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48086000 0x80>;
+			interrupts = <0 46 0x4>;
+			ti,hwmods = "timer10";
+		};
+
+		timer11: timer@48088000 {
+			compatible = "ti,omap2-timer";
+			reg = <0x48088000 0x80>;
+			interrupts = <0 47 0x4>;
+			ti,hwmods = "timer11";
+			ti,timer-pwm;
+		};
+
+		emif1: emif@0x4c000000 {
+			compatible	= "ti,emif-4d5";
+			ti,hwmods	= "emif1";
+			phy-type	= <2>; /* DDR PHY type: Intelli PHY */
+			reg = <0x4c000000 0x400>;
+			interrupts = <0 110 0x4>;
+			hw-caps-read-idle-ctrl;
+			hw-caps-ll-interface;
+			hw-caps-temp-alert;
+		};
+
+		emif2: emif@0x4d000000 {
+			compatible	= "ti,emif-4d5";
+			ti,hwmods	= "emif2";
+			phy-type	= <2>; /* DDR PHY type: Intelli PHY */
+			reg = <0x4d000000 0x400>;
+			interrupts = <0 111 0x4>;
+			hw-caps-read-idle-ctrl;
+			hw-caps-ll-interface;
+			hw-caps-temp-alert;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/orion5x-lacie-ethernet-disk-mini-v2.dts b/arch/arm/boot/dts/orion5x-lacie-ethernet-disk-mini-v2.dts
new file mode 100644
index 0000000..5a3a58b
--- /dev/null
+++ b/arch/arm/boot/dts/orion5x-lacie-ethernet-disk-mini-v2.dts
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 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/ "orion5x.dtsi"
+
+/ {
+	model = "LaCie Ethernet Disk mini V2";
+	compatible = "lacie,ethernet-disk-mini-v2", "marvell-orion5x-88f5182", "marvell,orion5x";
+
+	memory {
+		reg = <0x00000000 0x4000000>; /* 64 MB */
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 earlyprintk";
+	};
+
+	ocp@f1000000 {
+		serial@12000 {
+			clock-frequency = <166666667>;
+			status = "okay";
+		};
+
+		sata@80000 {
+			status = "okay";
+			nr-ports = <2>;
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		button@1 {
+			label = "Power-on Switch";
+			linux,code = <116>; /* KEY_POWER */
+			gpios = <&gpio0 18 0>;
+		};
+	};
+
+	gpio_leds {
+		compatible = "gpio-leds";
+
+		led@1 {
+			label = "power:blue";
+			gpios = <&gpio0 16 1>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/orion5x.dtsi b/arch/arm/boot/dts/orion5x.dtsi
new file mode 100644
index 0000000..8aad00f
--- /dev/null
+++ b/arch/arm/boot/dts/orion5x.dtsi
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Marvell Orion5x SoC";
+	compatible = "marvell,orion5x";
+	interrupt-parent = <&intc>;
+
+	intc: interrupt-controller {
+		compatible = "marvell,orion-intc", "marvell,intc";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0xf1020204 0x04>;
+	};
+
+	ocp@f1000000 {
+		compatible = "simple-bus";
+		ranges = <0x00000000 0xf1000000 0x4000000
+		          0xf2200000 0xf2200000 0x0000800>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		gpio0: gpio@10100 {
+			compatible = "marvell,orion-gpio";
+			#gpio-cells = <2>;
+			gpio-controller;
+			reg = <0x10100 0x40>;
+			ngpio = <32>;
+			interrupts = <6>, <7>, <8>, <9>;
+		};
+
+		serial@12000 {
+			compatible = "ns16550a";
+			reg = <0x12000 0x100>;
+			reg-shift = <2>;
+			interrupts = <3>;
+			/* set clock-frequency in board dts */
+			status = "disabled";
+		};
+
+		serial@12100 {
+			compatible = "ns16550a";
+			reg = <0x12100 0x100>;
+			reg-shift = <2>;
+			interrupts = <4>;
+			/* set clock-frequency in board dts */
+			status = "disabled";
+		};
+
+		spi@10600 {
+			compatible = "marvell,orion-spi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			reg = <0x10600 0x28>;
+			status = "disabled";
+		};
+
+		wdt@20300 {
+			compatible = "marvell,orion-wdt";
+			reg = <0x20300 0x28>;
+			status = "okay";
+		};
+
+		sata@80000 {
+			compatible = "marvell,orion-sata";
+			reg = <0x80000 0x5000>;
+			interrupts = <29>;
+			status = "disabled";
+		};
+
+		i2c@11000 {
+			compatible = "marvell,mv64xxx-i2c";
+			reg = <0x11000 0x20>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <5>;
+			clock-frequency = <100000>;
+			status = "disabled";
+		};
+
+		crypto@90000 {
+			compatible = "marvell,orion-crypto";
+			reg = <0x90000 0x10000>,
+			      <0xf2200000 0x800>;
+			reg-names = "regs", "sram";
+			interrupts = <22>;
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pm9g45.dts b/arch/arm/boot/dts/pm9g45.dts
new file mode 100644
index 0000000..387fedb
--- /dev/null
+++ b/arch/arm/boot/dts/pm9g45.dts
@@ -0,0 +1,165 @@
+/*
+ * pm9g45.dts - Device Tree file for Ronetix pm9g45 board
+ *
+ *  Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+/dts-v1/;
+/include/ "at91sam9g45.dtsi"
+
+/ {
+	model = "Ronetix pm9g45";
+	compatible = "ronetix,pm9g45", "atmel,at91sam9g45", "atmel,at91sam9";
+
+	chosen {
+		bootargs = "console=ttyS0,115200";
+	};
+
+	memory {
+		reg = <0x70000000 0x8000000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		main_clock: clock@0 {
+			compatible = "atmel,osc", "fixed-clock";
+			clock-frequency = <12000000>;
+		};
+	};
+
+	ahb {
+		apb {
+			dbgu: serial@ffffee00 {
+				status = "okay";
+			};
+
+			pinctrl@fffff200 {
+
+				board {
+					pinctrl_board_nand: nand0-board {
+						atmel,pins =
+							<3 3 0x0 0x1	/* PD3 gpio RDY pin pull_up*/
+							 2 14 0x0 0x1>;	/* PC14 gpio enable pin pull_up */
+					};
+				};
+
+				mmc {
+					pinctrl_board_mmc: mmc0-board {
+						atmel,pins =
+							<3 6 0x0 0x5>;	/* PD6 gpio CD pin pull_up and deglitch */
+					};
+				};
+			};
+
+			mmc0: mmc@fff80000 {
+				pinctrl-0 = <
+					&pinctrl_board_mmc
+					&pinctrl_mmc0_slot0_clk_cmd_dat0
+					&pinctrl_mmc0_slot0_dat1_3>;
+				status = "okay";
+				slot@0 {
+					reg = <0>;
+					bus-width = <4>;
+					cd-gpios = <&pioD 6 0>;
+				};
+			};
+
+			macb0: ethernet@fffbc000 {
+				phy-mode = "rmii";
+				status = "okay";
+			};
+
+		};
+
+		nand0: nand@40000000 {
+			nand-bus-width = <8>;
+			nand-ecc-mode = "soft";
+			nand-on-flash-bbt;
+			pinctrl-0 = <&pinctrl_board_nand>;
+
+			gpios = <&pioD 3 0
+				 &pioC 14 0
+				 0
+				>;
+
+			status = "okay";
+
+			at91bootstrap@0 {
+				label = "at91bootstrap";
+				reg = <0x0 0x20000>;
+			};
+
+			barebox@20000 {
+				label = "barebox";
+				reg = <0x20000 0x40000>;
+			};
+
+			bareboxenv@60000 {
+				label = "bareboxenv";
+				reg = <0x60000 0x1A0000>;
+			};
+
+			kernel@200000 {
+				label = "bareboxenv2";
+				reg = <0x200000 0x300000>;
+			};
+
+			kernel@500000 {
+				label = "root";
+				reg = <0x500000 0x400000>;
+			};
+
+			data@900000 {
+				label = "data";
+				reg = <0x900000 0x8340000>;
+			};
+		};
+
+		usb0: ohci@00700000 {
+			status = "okay";
+			num-ports = <2>;
+		};
+
+		usb1: ehci@00800000 {
+			status = "okay";
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led0 {
+			label = "led0";
+			gpios = <&pioD 0 1>;
+			linux,default-trigger = "nand-disk";
+		};
+
+		led1 {
+			label = "led1";
+			gpios = <&pioD 31 0>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		right {
+			label = "SW4";
+			gpios = <&pioE 7 1>;
+			linux,code = <106>;
+		};
+
+		up {
+			label = "SW3";
+			gpios = <&pioE 8 1>;
+			linux,code = <103>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/samsung_k3pe0e000b.dtsi b/arch/arm/boot/dts/samsung_k3pe0e000b.dtsi
new file mode 100644
index 0000000..9657a5c
--- /dev/null
+++ b/arch/arm/boot/dts/samsung_k3pe0e000b.dtsi
@@ -0,0 +1,67 @@
+/*
+ * Timings and Geometry for Samsung K3PE0E000B memory part
+ */
+
+/ {
+	samsung_K3PE0E000B: lpddr2 {
+		compatible	= "Samsung,K3PE0E000B","jedec,lpddr2-s4";
+		density		= <4096>;
+		io-width	= <32>;
+
+		tRPab-min-tck	= <3>;
+		tRCD-min-tck	= <3>;
+		tWR-min-tck	= <3>;
+		tRASmin-min-tck	= <3>;
+		tRRD-min-tck	= <2>;
+		tWTR-min-tck	= <2>;
+		tXP-min-tck	= <2>;
+		tRTP-min-tck	= <2>;
+		tCKE-min-tck	= <3>;
+		tCKESR-min-tck	= <3>;
+		tFAW-min-tck	= <8>;
+
+		timings_samsung_K3PE0E000B_533MHz: lpddr2-timings@0 {
+			compatible	= "jedec,lpddr2-timings";
+			min-freq	= <10000000>;
+			max-freq	= <533333333>;
+			tRPab		= <21000>;
+			tRCD		= <18000>;
+			tWR		= <15000>;
+			tRAS-min	= <42000>;
+			tRRD		= <10000>;
+			tWTR		= <7500>;
+			tXP		= <7500>;
+			tRTP		= <7500>;
+			tCKESR		= <15000>;
+			tDQSCK-max	= <5500>;
+			tFAW		= <50000>;
+			tZQCS		= <90000>;
+			tZQCL		= <360000>;
+			tZQinit		= <1000000>;
+			tRAS-max-ns	= <70000>;
+			tDQSCK-max-derated = <6000>;
+		};
+
+		timings_samsung_K3PE0E000B_266MHz: lpddr2-timings@1 {
+			compatible	= "jedec,lpddr2-timings";
+			min-freq	= <10000000>;
+			max-freq	= <266666666>;
+			tRPab		= <21000>;
+			tRCD		= <18000>;
+			tWR		= <15000>;
+			tRAS-min	= <42000>;
+			tRRD		= <10000>;
+			tWTR		= <7500>;
+			tXP		= <7500>;
+			tRTP		= <7500>;
+			tCKESR		= <15000>;
+			tDQSCK-max	= <5500>;
+			tFAW		= <50000>;
+			tZQCS		= <90000>;
+			tZQCL		= <360000>;
+			tZQinit		= <1000000>;
+			tRAS-max-ns	= <70000>;
+			tDQSCK-max-derated = <6000>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sh7372-mackerel.dts b/arch/arm/boot/dts/sh7372-mackerel.dts
new file mode 100644
index 0000000..286f0ca
--- /dev/null
+++ b/arch/arm/boot/dts/sh7372-mackerel.dts
@@ -0,0 +1,22 @@
+/*
+ * Device Tree Source for the mackerel board
+ *
+ * Copyright (C) 2012 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/ "skeleton.dtsi"
+
+/ {
+	model = "Mackerel (AP4 EVM 2nd)";
+	compatible = "renesas,mackerel";
+
+	memory {
+		device_type = "memory";
+		reg = <0x40000000 0x10000000>;
+	};
+};
diff --git a/arch/arm/boot/dts/sh7377.dtsi b/arch/arm/boot/dts/sh7377.dtsi
deleted file mode 100644
index 767ee07..0000000
--- a/arch/arm/boot/dts/sh7377.dtsi
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Device Tree Source for the sh7377 SoC
- *
- * Copyright (C) 2012 Renesas Solutions Corp.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-/include/ "skeleton.dtsi"
-
-/ {
-	compatible = "renesas,sh7377";
-
-	cpus {
-		cpu@0 {
-			compatible = "arm,cortex-a8";
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/snowball.dts b/arch/arm/boot/dts/snowball.dts
index 702c0ba..27f31a5 100644
--- a/arch/arm/boot/dts/snowball.dts
+++ b/arch/arm/boot/dts/snowball.dts
@@ -14,7 +14,7 @@
 
 / {
 	model = "Calao Systems Snowball platform with device tree";
-	compatible = "calaosystems,snowball-a9500";
+	compatible = "calaosystems,snowball-a9500", "st-ericsson,u9500";
 
 	memory {
 		reg = <0x00000000 0x20000000>;
@@ -99,6 +99,33 @@
 			status = "okay";
 		};
 
+		prcmu@80157000 {
+			thermal@801573c0 {
+				num-trips = <4>;
+
+				trip0-temp = <70000>;
+				trip0-type = "active";
+				trip0-cdev-num = <1>;
+				trip0-cdev-name0 = "thermal-cpufreq-0";
+
+				trip1-temp = <75000>;
+				trip1-type = "active";
+				trip1-cdev-num = <1>;
+				trip1-cdev-name0 = "thermal-cpufreq-0";
+
+				trip2-temp = <80000>;
+				trip2-type = "active";
+				trip2-cdev-num = <1>;
+				trip2-cdev-name0 = "thermal-cpufreq-0";
+
+				trip3-temp = <85000>;
+				trip3-type = "critical";
+				trip3-cdev-num = <0>;
+
+				status = "okay";
+			 };
+		};
+
 		external-bus@50000000 {
 			status = "okay";
 
@@ -120,10 +147,10 @@
 		};
 
 		// External Micro SD slot
-		sdi@80126000 {
+		sdi0_per1@80126000 {
 			arm,primecell-periphid = <0x10480180>;
 			max-frequency = <50000000>;
-			bus-width = <8>;
+			bus-width = <4>;
 			mmc-cap-mmc-highspeed;
 			vmmc-supply = <&ab8500_ldo_aux3_reg>;
 
@@ -134,7 +161,7 @@
 		};
 
 		// On-board eMMC
-		sdi@80114000 {
+		sdi4_per2@80114000 {
 			arm,primecell-periphid = <0x10480180>;
 		        max-frequency = <50000000>;
 			bus-width = <8>;
@@ -183,5 +210,141 @@
 				reg = <0x33>;
 			};
 		};
+
+		cpufreq-cooling {
+			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@5 {
+				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_initcore_reg: ab8500_ldo_initcore {
+						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_amamic2_reg: ab8500_ldo_amamic2 {
+						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/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
index 0772f57..19aec42 100644
--- a/arch/arm/boot/dts/socfpga.dtsi
+++ b/arch/arm/boot/dts/socfpga.dtsi
@@ -143,5 +143,15 @@
 			reg-shift = <2>;
 			reg-io-width = <4>;
 		};
+
+		rstmgr@ffd05000 {
+				compatible = "altr,rst-mgr";
+				reg = <0xffd05000 0x1000>;
+			};
+
+		sysmgr@ffd08000 {
+				compatible = "altr,sys-mgr";
+				reg = <0xffd08000 0x4000>;
+			};
 	};
 };
diff --git a/arch/arm/boot/dts/spear1310-evb.dts b/arch/arm/boot/dts/spear1310-evb.dts
index dd4358b..b56a801 100644
--- a/arch/arm/boot/dts/spear1310-evb.dts
+++ b/arch/arm/boot/dts/spear1310-evb.dts
@@ -30,10 +30,14 @@
 			pinctrl-0 = <&state_default>;
 
 			state_default: pinmux {
-				i2c0-pmx {
+				i2c0 {
 					st,pins = "i2c0_grp";
 					st,function = "i2c0";
 				};
+				i2s0 {
+					st,pins = "i2s0_grp";
+					st,function = "i2s0";
+				};
 				i2s1 {
 					st,pins = "i2s1_grp";
 					st,function = "i2s1";
@@ -42,6 +46,10 @@
 					st,pins = "arm_gpio_grp";
 					st,function = "arm_gpio";
 				};
+				clcd {
+					st,pins = "clcd_grp" , "clcd_high_res";
+					st,function = "clcd";
+				};
 				eth {
 					st,pins = "gmii_grp";
 					st,function = "gmii";
@@ -74,11 +82,6 @@
 					st,pins = "i2c_1_2_grp";
 					st,function = "i2c_1_2";
 				};
-				pci {
-					st,pins = "pcie0_grp","pcie1_grp",
-						"pcie2_grp";
-					st,function = "pci";
-				};
 				smii {
 					st,pins = "smii_0_1_2_grp";
 					st,function = "smii_0_1_2";
@@ -88,6 +91,14 @@
 						"nand_16bit_grp";
 					st,function = "nand";
 				};
+				sata {
+					st,pins = "sata0_grp";
+					st,function = "sata";
+				};
+				pcie {
+					st,pins = "pcie1_grp", "pcie2_grp";
+					st,function = "pci_express";
+				};
 			};
 		};
 
@@ -109,9 +120,49 @@
 
 		fsmc: flash@b0000000 {
 			status = "okay";
+
+			partition@0 {
+				label = "xloader";
+				reg = <0x0 0x80000>;
+			};
+			partition@80000 {
+				label = "u-boot";
+				reg = <0x80000 0x140000>;
+			};
+			partition@1C0000 {
+				label = "environment";
+				reg = <0x1C0000 0x40000>;
+			};
+			partition@200000 {
+				label = "dtb";
+				reg = <0x200000 0x40000>;
+			};
+			partition@240000 {
+				label = "linux";
+				reg = <0x240000 0xC00000>;
+			};
+			partition@E40000 {
+				label = "rootfs";
+				reg = <0xE40000 0x0>;
+			};
+		};
+
+		gpio_keys {
+			compatible = "gpio-keys";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			button@1 {
+				label = "wakeup";
+				linux,code = <0x100>;
+				gpios = <&gpio0 7 0x4>;
+				debounce-interval = <20>;
+				gpio-key,wakeup = <1>;
+			};
 		};
 
 		gmac0: eth@e2000000 {
+			phy-mode = "gmii";
 			status = "okay";
 		};
 
@@ -135,23 +186,27 @@
 				};
 				partition@10000 {
 					label = "u-boot";
-					reg = <0x10000 0x40000>;
+					reg = <0x10000 0x50000>;
+				};
+				partition@60000 {
+					label = "environment";
+					reg = <0x60000 0x10000>;
 				};
-				partition@50000 {
+				partition@70000 {
+					label = "dtb";
+					reg = <0x70000 0x10000>;
+				};
+				partition@80000 {
 					label = "linux";
-					reg = <0x50000 0x2c0000>;
+					reg = <0x80000 0x310000>;
 				};
-				partition@310000 {
+				partition@390000 {
 					label = "rootfs";
-					reg = <0x310000 0x4f0000>;
+					reg = <0x390000 0x0>;
 				};
 			};
 		};
 
-		spi0: spi@e0100000 {
-			status = "okay";
-		};
-
 		ehci@e4800000 {
 			status = "okay";
 		};
@@ -181,11 +236,11 @@
 			       status = "okay";
 			};
 
-			i2c0: i2c@e0280000 {
+			gpio@d8400000 {
 			       status = "okay";
 			};
 
-			i2c1: i2c@5cd00000 {
+			i2c0: i2c@e0280000 {
 			       status = "okay";
 			};
 
@@ -273,6 +328,7 @@
 						 0x08080052 >;
 			       autorepeat;
 			       st,mode = <0>;
+			       suspended_rate = <2000000>;
 			       status = "okay";
 			};
 
@@ -282,6 +338,81 @@
 
 			serial@e0000000 {
 			       status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
+			};
+
+			spi0: spi@e0100000 {
+				status = "okay";
+				num-cs = <3>;
+				cs-gpios = <&gpio1 7 0>, <&spics 0>, <&spics 1>;
+
+				stmpe610@0 {
+					compatible = "st,stmpe610";
+					reg = <0>;
+					#address-cells = <1>;
+					#size-cells = <0>;
+					spi-max-frequency = <1000000>;
+					spi-cpha;
+					pl022,hierarchy = <0>;
+					pl022,interface = <0>;
+					pl022,slave-tx-disable;
+					pl022,com-mode = <0>;
+					pl022,rx-level-trig = <0>;
+					pl022,tx-level-trig = <0>;
+					pl022,ctrl-len = <0x7>;
+					pl022,wait-state = <0>;
+					pl022,duplex = <0>;
+					interrupts = <6 0x4>;
+					interrupt-parent = <&gpio1>;
+					irq-trigger = <0x2>;
+
+					stmpe_touchscreen {
+						compatible = "st,stmpe-ts";
+						ts,sample-time = <4>;
+						ts,mod-12b = <1>;
+						ts,ref-sel = <0>;
+						ts,adc-freq = <1>;
+						ts,ave-ctrl = <1>;
+						ts,touch-det-delay = <2>;
+						ts,settling = <2>;
+						ts,fraction-z = <7>;
+						ts,i-drive = <1>;
+					};
+				};
+
+				m25p80@1 {
+					compatible = "st,m25p80";
+					reg = <1>;
+					spi-max-frequency = <12000000>;
+					spi-cpol;
+					spi-cpha;
+					pl022,hierarchy = <0>;
+					pl022,interface = <0>;
+					pl022,slave-tx-disable;
+					pl022,com-mode = <0x2>;
+					pl022,rx-level-trig = <0>;
+					pl022,tx-level-trig = <0>;
+					pl022,ctrl-len = <0x11>;
+					pl022,wait-state = <0>;
+					pl022,duplex = <0>;
+				};
+
+				spidev@2 {
+					compatible = "spidev";
+					reg = <2>;
+					spi-max-frequency = <25000000>;
+					spi-cpha;
+					pl022,hierarchy = <0>;
+					pl022,interface = <0>;
+					pl022,slave-tx-disable;
+					pl022,com-mode = <0x2>;
+					pl022,rx-level-trig = <0>;
+					pl022,tx-level-trig = <0>;
+					pl022,ctrl-len = <0x11>;
+					pl022,wait-state = <0>;
+					pl022,duplex = <0>;
+				};
 			};
 
 			wdt@ec800620 {
diff --git a/arch/arm/boot/dts/spear1310.dtsi b/arch/arm/boot/dts/spear1310.dtsi
index 419ea74..1513c19 100644
--- a/arch/arm/boot/dts/spear1310.dtsi
+++ b/arch/arm/boot/dts/spear1310.dtsi
@@ -17,6 +17,18 @@
 	compatible = "st,spear1310";
 
 	ahb {
+		spics: spics@e0700000{
+			compatible = "st,spear-spics-gpio";
+			reg = <0xe0700000 0x1000>;
+			st-spics,peripcfg-reg = <0x3b0>;
+			st-spics,sw-enable-bit = <12>;
+			st-spics,cs-value-bit = <11>;
+			st-spics,cs-enable-mask = <3>;
+			st-spics,cs-enable-shift = <8>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
 		ahci@b1000000 {
 			compatible = "snps,spear-ahci";
 			reg = <0xb1000000 0x10000>;
@@ -43,6 +55,7 @@
 			reg = <0x5c400000 0x8000>;
 			interrupts = <0 95 0x4>;
 			interrupt-names = "macirq";
+			phy-mode = "mii";
 			status = "disabled";
 		};
 
@@ -51,6 +64,7 @@
 			reg = <0x5c500000 0x8000>;
 			interrupts = <0 96 0x4>;
 			interrupt-names = "macirq";
+			phy-mode = "mii";
 			status = "disabled";
 		};
 
@@ -59,6 +73,7 @@
 			reg = <0x5c600000 0x8000>;
 			interrupts = <0 97 0x4>;
 			interrupt-names = "macirq";
+			phy-mode = "rmii";
 			status = "disabled";
 		};
 
@@ -67,14 +82,14 @@
 			reg = <0x5c700000 0x8000>;
 			interrupts = <0 98 0x4>;
 			interrupt-names = "macirq";
+			phy-mode = "rgmii";
 			status = "disabled";
 		};
 
-		spi1: spi@5d400000 {
-			compatible = "arm,pl022", "arm,primecell";
-			reg = <0x5d400000 0x1000>;
-			interrupts = <0 99 0x4>;
-			status = "disabled";
+		pinmux: pinmux@e0700000 {
+			compatible = "st,spear1310-pinmux";
+			reg = <0xe0700000 0x1000>;
+			#gpio-range-cells = <2>;
 		};
 
 		apb {
@@ -141,6 +156,15 @@
 				status = "disabled";
 			};
 
+			spi1: spi@5d400000 {
+				compatible = "arm,pl022", "arm,primecell";
+				reg = <0x5d400000 0x1000>;
+				interrupts = <0 99 0x4>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
 			serial@5c800000 {
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0x5c800000 0x1000>;
@@ -179,6 +203,27 @@
 			thermal@e07008c4 {
 				st,thermal-flags = <0x7000>;
 			};
+
+			gpiopinctrl: gpio@d8400000 {
+				compatible = "st,spear-plgpio";
+				reg = <0xd8400000 0x1000>;
+				interrupts = <0 100 0x4>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				gpio-controller;
+				#gpio-cells = <2>;
+				gpio-ranges = <&pinmux 0 246>;
+				status = "disabled";
+
+				st-plgpio,ngpio = <246>;
+				st-plgpio,enb-reg = <0xd0>;
+				st-plgpio,wdata-reg = <0x90>;
+				st-plgpio,dir-reg = <0xb0>;
+				st-plgpio,ie-reg = <0x30>;
+				st-plgpio,rdata-reg = <0x70>;
+				st-plgpio,mis-reg = <0x10>;
+				st-plgpio,eit-reg = <0x50>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/spear1340-evb.dts b/arch/arm/boot/dts/spear1340-evb.dts
index c9a54e0..d6c30ae 100644
--- a/arch/arm/boot/dts/spear1340-evb.dts
+++ b/arch/arm/boot/dts/spear1340-evb.dts
@@ -38,20 +38,15 @@
 					st,pins = "fsmc_8bit_grp";
 					st,function = "fsmc";
 				};
-				kbd {
-					st,pins = "keyboard_row_col_grp",
-						"keyboard_col5_grp";
-					st,function = "keyboard";
-				};
 				uart0 {
-					st,pins = "uart0_grp", "uart0_enh_grp";
+					st,pins = "uart0_grp";
 					st,function = "uart0";
 				};
-				i2c0-pmx {
+				i2c0 {
 					st,pins = "i2c0_grp";
 					st,function = "i2c0";
 				};
-				i2c1-pmx {
+				i2c1 {
 					st,pins = "i2c1_grp";
 					st,function = "i2c1";
 				};
@@ -64,14 +59,9 @@
 					st,function = "spdif_out";
 				};
 				ssp0 {
-					st,pins = "ssp0_grp", "ssp0_cs1_grp",
-						"ssp0_cs3_grp";
+					st,pins = "ssp0_grp", "ssp0_cs1_grp", "ssp0_cs2_grp", "ssp0_cs3_grp";
 					st,function = "ssp0";
 				};
-				pwm {
-					st,pins = "pwm2_grp", "pwm3_grp";
-					st,function = "pwm";
-				};
 				smi-pmx {
 					st,pins = "smi_grp";
 					st,function = "smi";
@@ -84,6 +74,18 @@
 					st,pins = "gmii_grp", "rgmii_grp";
 					st,function = "gmac";
 				};
+				cam0 {
+					st,pins = "cam0_grp";
+					st,function = "cam0";
+				};
+				cam1 {
+					st,pins = "cam1_grp";
+					st,function = "cam1";
+				};
+				cam2 {
+					st,pins = "cam2_grp";
+					st,function = "cam2";
+				};
 				cam3 {
 					st,pins = "cam3_grp";
 					st,function = "cam3";
@@ -108,9 +110,18 @@
 					st,pins = "sata_grp";
 					st,function = "sata";
 				};
+				pcie {
+					st,pins = "pcie_grp";
+					st,function = "pcie";
+				};
+
 			};
 		};
 
+		ahci@b1000000 {
+			status = "okay";
+		};
+
 		dma@ea800000 {
 			status = "okay";
 		};
@@ -121,9 +132,35 @@
 
 		fsmc: flash@b0000000 {
 			status = "okay";
+
+			partition@0 {
+				label = "xloader";
+				reg = <0x0 0x200000>;
+			};
+			partition@200000 {
+				label = "u-boot";
+				reg = <0x200000 0x200000>;
+			};
+			partition@400000 {
+				label = "environment";
+				reg = <0x400000 0x100000>;
+			};
+			partition@500000 {
+				label = "dtb";
+				reg = <0x500000 0x100000>;
+			};
+			partition@600000 {
+				label = "linux";
+				reg = <0x600000 0xC00000>;
+			};
+			partition@1200000 {
+				label = "rootfs";
+				reg = <0x1200000 0x0>;
+			};
 		};
 
 		gmac0: eth@e2000000 {
+			phy-mode = "rgmii";
 			status = "okay";
 		};
 
@@ -147,31 +184,62 @@
 				};
 				partition@10000 {
 					label = "u-boot";
-					reg = <0x10000 0x40000>;
+					reg = <0x10000 0x50000>;
+				};
+				partition@60000 {
+					label = "environment";
+					reg = <0x60000 0x10000>;
+				};
+				partition@70000 {
+					label = "dtb";
+					reg = <0x70000 0x10000>;
 				};
-				partition@50000 {
+				partition@80000 {
 					label = "linux";
-					reg = <0x50000 0x2c0000>;
+					reg = <0x80000 0x310000>;
 				};
-				partition@310000 {
+				partition@390000 {
 					label = "rootfs";
-					reg = <0x310000 0x4f0000>;
+					reg = <0x390000 0x0>;
 				};
 			};
 		};
 
-		spi0: spi@e0100000 {
+		ehci@e4800000 {
 			status = "okay";
 		};
 
-		ehci@e4800000 {
-			status = "okay";
+		gpio_keys {
+			compatible = "gpio-keys";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			button@1 {
+				label = "wakeup";
+				linux,code = <0x100>;
+				gpios = <&gpio1 1 0x4>;
+				debounce-interval = <20>;
+				gpio-key,wakeup = <1>;
+			};
 		};
 
 		ehci@e5800000 {
 			status = "okay";
 		};
 
+		i2s0: i2s-play@b2400000 {
+			status = "okay";
+		};
+
+		i2s1: i2s-rec@b2000000 {
+			status = "okay";
+		};
+
+		incodec: dir-hifi {
+			compatible = "dummy,dir-hifi";
+			status = "okay";
+		};
+
 		ohci@e4000000 {
 			status = "okay";
 		};
@@ -180,11 +248,43 @@
 			status = "okay";
 		};
 
+		outcodec: dit-hifi {
+			compatible = "dummy,dit-hifi";
+			status = "okay";
+		};
+
+		sound {
+			compatible = "spear,spear-evb";
+			audio-controllers = <&spdif0 &spdif1 &i2s0 &i2s1>;
+			audio-codecs = <&incodec &outcodec &sta529 &sta529>;
+			codec_dai_name = "dir-hifi", "dit-hifi", "sta529-audio", "sta529-audio";
+			stream_name = "spdif-cap", "spdif-play", "i2s-play", "i2s-cap";
+			dai_name = "spdifin-pcm", "spdifout-pcm", "i2s0-pcm", "i2s1-pcm";
+			nr_controllers = <4>;
+		        status = "okay";
+		};
+
+		spdif0: spdif-in@d0100000 {
+			status = "okay";
+		};
+
+		spdif1: spdif-out@d0000000 {
+			status = "okay";
+		};
+
 		apb {
 			adc@e0080000 {
 				status = "okay";
 			};
 
+			i2s-play@b2400000 {
+				status = "okay";
+			};
+
+			i2s-rec@b2000000 {
+				status = "okay";
+			};
+
 			gpio0: gpio@e0600000 {
 			       status = "okay";
 			};
@@ -193,12 +293,42 @@
 			       status = "okay";
 			};
 
+			gpio@e2800000 {
+			       status = "okay";
+			};
+
 			i2c0: i2c@e0280000 {
 			       status = "okay";
+
+				sta529: sta529@1a {
+					compatible = "st,sta529";
+					reg = <0x1a>;
+				};
 			};
 
 			i2c1: i2c@b4000000 {
 			       status = "okay";
+
+				eeprom0@56 {
+					compatible = "st,eeprom";
+					reg = <0x56>;
+				};
+
+				stmpe801@41 {
+					compatible = "st,stmpe801";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0x41>;
+					interrupts = <4 0x4>;
+					interrupt-parent = <&gpio0>;
+					irq-trigger = <0x2>;
+
+					stmpegpio: stmpe_gpio {
+						compatible = "st,stmpe-gpio";
+						gpio-controller;
+						#gpio-cells = <2>;
+					};
+				};
 			};
 
 			kbd@e0300000 {
@@ -285,6 +415,7 @@
 						 0x08080052 >;
 			       autorepeat;
 			       st,mode = <0>;
+			       suspended_rate = <2000000>;
 			       status = "okay";
 			};
 
@@ -294,10 +425,92 @@
 
 			serial@e0000000 {
 			       status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
 			};
 
 			serial@b4100000 {
 			       status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
+			};
+
+			spi0: spi@e0100000 {
+				status = "okay";
+				num-cs = <3>;
+				cs-gpios = <&gpiopinctrl 80 0>, <&gpiopinctrl 24 0>,
+					   <&gpiopinctrl 85 0>;
+
+				m25p80@0 {
+					compatible = "m25p80";
+					reg = <0>;
+					spi-max-frequency = <12000000>;
+					spi-cpol;
+					spi-cpha;
+					pl022,hierarchy = <0>;
+					pl022,interface = <0>;
+					pl022,slave-tx-disable;
+					pl022,com-mode = <0x2>;
+					pl022,rx-level-trig = <0>;
+					pl022,tx-level-trig = <0>;
+					pl022,ctrl-len = <0x11>;
+					pl022,wait-state = <0>;
+					pl022,duplex = <0>;
+				};
+
+				stmpe610@1 {
+					compatible = "st,stmpe610";
+					spi-max-frequency = <1000000>;
+					spi-cpha;
+					reg = <1>;
+					pl022,hierarchy = <0>;
+					pl022,interface = <0>;
+					pl022,slave-tx-disable;
+					pl022,com-mode = <0>;
+					pl022,rx-level-trig = <0>;
+					pl022,tx-level-trig = <0>;
+					pl022,ctrl-len = <0x7>;
+					pl022,wait-state = <0>;
+					pl022,duplex = <0>;
+					interrupts = <100 0>;
+					interrupt-parent = <&gpiopinctrl>;
+					irq-trigger = <0x2>;
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					stmpe_touchscreen {
+						compatible = "st,stmpe-ts";
+						ts,sample-time = <4>;
+						ts,mod-12b = <1>;
+						ts,ref-sel = <0>;
+						ts,adc-freq = <1>;
+						ts,ave-ctrl = <1>;
+						ts,touch-det-delay = <2>;
+						ts,settling = <2>;
+						ts,fraction-z = <7>;
+						ts,i-drive = <1>;
+					};
+				};
+
+				spidev@2 {
+					compatible = "spidev";
+					reg = <2>;
+					spi-max-frequency = <25000000>;
+					spi-cpha;
+					pl022,hierarchy = <0>;
+					pl022,interface = <0>;
+					pl022,slave-tx-disable;
+					pl022,com-mode = <0x2>;
+					pl022,rx-level-trig = <0>;
+					pl022,tx-level-trig = <0>;
+					pl022,ctrl-len = <0x11>;
+					pl022,wait-state = <0>;
+					pl022,duplex = <0>;
+				};
+			};
+
+			timer@ec800600 {
+				status = "okay";
 			};
 
 			wdt@ec800620 {
diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/spear1340.dtsi
index d71fe2a..afa7dd7 100644
--- a/arch/arm/boot/dts/spear1340.dtsi
+++ b/arch/arm/boot/dts/spear1340.dtsi
@@ -17,6 +17,20 @@
 	compatible = "st,spear1340";
 
 	ahb {
+
+		spics: spics@e0700000{
+			compatible = "st,spear-spics-gpio";
+			reg = <0xe0700000 0x1000>;
+			st-spics,peripcfg-reg = <0x42c>;
+			st-spics,sw-enable-bit = <21>;
+			st-spics,cs-value-bit = <20>;
+			st-spics,cs-enable-mask = <3>;
+			st-spics,cs-enable-shift = <18>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			status = "disabled";
+		};
+
 		ahci@b1000000 {
 			compatible = "snps,spear-ahci";
 			reg = <0xb1000000 0x10000>;
@@ -24,9 +38,80 @@
 			status = "disabled";
 		};
 
+		dma@ea800000 {
+			slave_info {
+				uart1_tx {
+					bus_id = "uart1_tx";
+					cfg_hi = <0x6000>;	/* 0xC << 11 */
+					cfg_lo = <0>;
+					src_master = <0>;
+					dst_master = <1>;
+				};
+				uart1_tx {
+					bus_id = "uart1_tx";
+					cfg_hi = <0x680>;	/* 0xD << 7 */
+					cfg_lo = <0>;
+					src_master = <1>;
+					dst_master = <0>;
+				};
+			};
+		};
+
+		i2s-play@b2400000 {
+			compatible = "snps,designware-i2s";
+			reg = <0xb2400000 0x10000>;
+			interrupt-names = "play_irq";
+			interrupts = <0 98 0x4
+				      0 99 0x4>;
+			play;
+			channel = <8>;
+			status = "disabled";
+		};
+
+		i2s-rec@b2000000 {
+			compatible = "snps,designware-i2s";
+			reg = <0xb2000000 0x10000>;
+			interrupt-names = "record_irq";
+			interrupts = <0 100  0x4
+				      0 101 0x4>;
+			record;
+			channel = <8>;
+			status = "disabled";
+		};
+
+		pinmux: pinmux@e0700000 {
+			compatible = "st,spear1340-pinmux";
+			reg = <0xe0700000 0x1000>;
+			#gpio-range-cells = <2>;
+		};
+
+		pwm: pwm@e0180000 {
+			compatible ="st,spear13xx-pwm";
+			reg = <0xe0180000 0x1000>;
+			#pwm-cells = <2>;
+			status = "disabled";
+		};
+
+		spdif-in@d0100000 {
+			compatible = "st,spdif-in";
+			reg = < 0xd0100000 0x20000
+				0xd0110000 0x10000 >;
+			interrupts = <0 84 0x4>;
+			status = "disabled";
+		};
+
+		spdif-out@d0000000 {
+			compatible = "st,spdif-out";
+			reg = <0xd0000000 0x20000>;
+			interrupts = <0 85 0x4>;
+			status = "disabled";
+		};
+
 		spi1: spi@5d400000 {
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0x5d400000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
 			interrupts = <0 99 0x4>;
 			status = "disabled";
 		};
@@ -38,6 +123,7 @@
 				compatible = "snps,designware-i2c";
 				reg = <0xb4000000 0x1000>;
 				interrupts = <0 104 0x4>;
+				write-16bit;
 				status = "disabled";
 			};
 
@@ -51,6 +137,26 @@
 			thermal@e07008c4 {
 				st,thermal-flags = <0x2a00>;
 			};
+
+			gpiopinctrl: gpio@e2800000 {
+				compatible = "st,spear-plgpio";
+				reg = <0xe2800000 0x1000>;
+				interrupts = <0 107 0x4>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				gpio-controller;
+				#gpio-cells = <2>;
+				gpio-ranges = <&pinmux 0 252>;
+				status = "disabled";
+
+				st-plgpio,ngpio = <250>;
+				st-plgpio,wdata-reg = <0x40>;
+				st-plgpio,dir-reg = <0x00>;
+				st-plgpio,ie-reg = <0x80>;
+				st-plgpio,rdata-reg = <0x20>;
+				st-plgpio,mis-reg = <0xa0>;
+				st-plgpio,eit-reg = <0x60>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi
index f7b84ac..eaae1e0 100644
--- a/arch/arm/boot/dts/spear13xx.dtsi
+++ b/arch/arm/boot/dts/spear13xx.dtsi
@@ -64,12 +64,26 @@
 		bootargs = "console=ttyAMA0,115200";
 	};
 
+	cpufreq {
+		compatible = "st,cpufreq-spear";
+		cpufreq_tbl = < 166000
+				200000
+				250000
+				300000
+				400000
+				500000
+				600000 >;
+		status = "disable";
+	};
+
 	ahb {
 		#address-cells = <1>;
 		#size-cells = <1>;
 		compatible = "simple-bus";
 		ranges = <0x50000000 0x50000000 0x10000000
 			  0xb0000000 0xb0000000 0x10000000
+			  0xd0000000 0xd0000000 0x02000000
+			  0xd8000000 0xd8000000 0x01000000
 			  0xe0000000 0xe0000000 0x10000000>;
 
 		sdhci@b3000000 {
@@ -81,7 +95,7 @@
 
 		cf@b2800000 {
 			compatible = "arasan,cf-spear1340";
-			reg = <0xb2800000 0x100>;
+			reg = <0xb2800000 0x1000>;
 			interrupts = <0 29 0x4>;
 			status = "disabled";
 		};
@@ -91,6 +105,37 @@
 			reg = <0xea800000 0x1000>;
 			interrupts = <0 19 0x4>;
 			status = "disabled";
+
+			nr_channels = <8>;
+			chan_allocation_order = <1>;
+			chan_priority = <1>;
+			block_size = <0xfff>;
+			nr_masters = <2>;
+			data_width = <3 3 0 0>;
+
+			slave_info {
+				ssp0_tx {
+					bus_id = "ssp0_tx";
+					cfg_hi = <0x2000>;	/* 0x4 << 11 */
+					cfg_lo = <0>;
+					src_master = <0>;
+					dst_master = <0>;
+				};
+				ssp0_rx {
+					bus_id = "ssp0_rx";
+					cfg_hi = <0x280>;	/* 0x5 << 7 */
+					cfg_lo = <0>;
+					src_master = <0>;
+					dst_master = <0>;
+				};
+				cf {
+					bus_id = "cf";
+					cfg_hi = <0>;
+					cfg_lo = <0>;
+					src_master = <0>;
+					dst_master = <0>;
+				};
+			};
 		};
 
 		dma@eb000000 {
@@ -98,21 +143,29 @@
 			reg = <0xeb000000 0x1000>;
 			interrupts = <0 59 0x4>;
 			status = "disabled";
+
+			nr_channels = <8>;
+			chan_allocation_order = <1>;
+			chan_priority = <1>;
+			block_size = <0xfff>;
+			nr_masters = <2>;
+			data_width = <3 3 0 0>;
 		};
 
 		fsmc: flash@b0000000 {
 			compatible = "st,spear600-fsmc-nand";
 			#address-cells = <1>;
 			#size-cells = <1>;
-			reg = <0xb0000000 0x1000	/* FSMC Register */
-			       0xb0800000 0x0010>;	/* NAND Base */
-			reg-names = "fsmc_regs", "nand_data";
+			reg = <0xb0000000 0x1000	/* FSMC Register*/
+			       0xb0800000 0x0010	/* NAND Base DATA */
+			       0xb0820000 0x0010	/* NAND Base ADDR */
+			       0xb0810000 0x0010>;	/* NAND Base CMD */
+			reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
 			interrupts = <0 20 0x4
 				      0 21 0x4
 				      0 22 0x4
 				      0 23 0x4>;
-			st,ale-off = <0x20000>;
-			st,cle-off = <0x10000>;
+			st,mode = <2>;
 			status = "disabled";
 		};
 
@@ -125,6 +178,13 @@
 			status = "disabled";
 		};
 
+		pcm {
+			compatible = "st,pcm-audio";
+			#address-cells = <0>;
+			#size-cells = <0>;
+			status = "disable";
+		};
+
 		smi: flash@ea000000 {
 			compatible = "st,spear600-smi";
 			#address-cells = <1>;
@@ -134,17 +194,11 @@
 			status = "disabled";
 		};
 
-		spi0: spi@e0100000 {
-			compatible = "arm,pl022", "arm,primecell";
-			reg = <0xe0100000 0x1000>;
-			interrupts = <0 31 0x4>;
-			status = "disabled";
-		};
-
 		ehci@e4800000 {
 			compatible = "st,spear600-ehci", "usb-ehci";
 			reg = <0xe4800000 0x1000>;
 			interrupts = <0 64 0x4>;
+			usbh0_id = <0>;
 			status = "disabled";
 		};
 
@@ -152,6 +206,7 @@
 			compatible = "st,spear600-ehci", "usb-ehci";
 			reg = <0xe5800000 0x1000>;
 			interrupts = <0 66 0x4>;
+			usbh1_id = <1>;
 			status = "disabled";
 		};
 
@@ -159,6 +214,7 @@
 			compatible = "st,spear600-ohci", "usb-ohci";
 			reg = <0xe4000000 0x1000>;
 			interrupts = <0 65 0x4>;
+			usbh0_id = <0>;
 			status = "disabled";
 		};
 
@@ -166,6 +222,7 @@
 			compatible = "st,spear600-ohci", "usb-ohci";
 			reg = <0xe5000000 0x1000>;
 			interrupts = <0 67 0x4>;
+			usbh1_id = <1>;
 			status = "disabled";
 		};
 
@@ -175,6 +232,8 @@
 			compatible = "simple-bus";
 			ranges = <0x50000000 0x50000000 0x10000000
 				  0xb0000000 0xb0000000 0x10000000
+				  0xd0000000 0xd0000000 0x02000000
+				  0xd8000000 0xd8000000 0x01000000
 				  0xe0000000 0xe0000000 0x10000000>;
 
 			gpio0: gpio@e0600000 {
@@ -215,8 +274,35 @@
 				status = "disabled";
 			};
 
+			i2s@e0180000 {
+				compatible = "st,designware-i2s";
+				reg = <0xe0180000 0x1000>;
+				interrupt-names = "play_irq", "record_irq";
+				interrupts = <0 10 0x4
+					      0 11 0x4 >;
+				status = "disabled";
+			};
+
+			i2s@e0200000 {
+				compatible = "st,designware-i2s";
+				reg = <0xe0200000 0x1000>;
+				interrupt-names = "play_irq", "record_irq";
+				interrupts = <0 26 0x4
+					      0 53 0x4>;
+				status = "disabled";
+			};
+
+			spi0: spi@e0100000 {
+				compatible = "arm,pl022", "arm,primecell";
+				reg = <0xe0100000 0x1000>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <0 31 0x4>;
+				status = "disabled";
+			};
+
 			rtc@e0580000 {
-				compatible = "st,spear-rtc";
+				compatible = "st,spear600-rtc";
 				reg = <0xe0580000 0x1000>;
 				interrupts = <0 36 0x4>;
 				status = "disabled";
@@ -232,7 +318,7 @@
 			adc@e0080000 {
 				compatible = "st,spear600-adc";
 				reg = <0xe0080000 0x1000>;
-				interrupts = <0 44 0x4>;
+				interrupts = <0 12 0x4>;
 				status = "disabled";
 			};
 
@@ -245,7 +331,8 @@
 			timer@ec800600 {
 				compatible = "arm,cortex-a9-twd-timer";
 				reg = <0xec800600 0x20>;
-				interrupts = <1 13 0x301>;
+				interrupts = <1 13 0x4>;
+				status = "disabled";
 			};
 
 			wdt@ec800620 {
@@ -257,6 +344,7 @@
 			thermal@e07008c4 {
 				compatible = "st,thermal-spear1340";
 				reg = <0xe07008c4 0x4>;
+				thermal_flags = <0x7000>;
 			};
 		};
 	};
diff --git a/arch/arm/boot/dts/spear300-evb.dts b/arch/arm/boot/dts/spear300-evb.dts
index 1e7c7a8..5de1431 100644
--- a/arch/arm/boot/dts/spear300-evb.dts
+++ b/arch/arm/boot/dts/spear300-evb.dts
@@ -100,15 +100,23 @@
 				};
 				partition@10000 {
 					label = "u-boot";
-					reg = <0x10000 0x40000>;
+					reg = <0x10000 0x50000>;
 				};
-				partition@50000 {
+				partition@60000 {
+					label = "environment";
+					reg = <0x60000 0x10000>;
+				};
+				partition@70000 {
+					label = "dtb";
+					reg = <0x70000 0x10000>;
+				};
+				partition@80000 {
 					label = "linux";
-					reg = <0x50000 0x2c0000>;
+					reg = <0x80000 0x310000>;
 				};
-				partition@310000 {
+				partition@390000 {
 					label = "rootfs";
-					reg = <0x310000 0x4f0000>;
+					reg = <0x390000 0x0>;
 				};
 			};
 		};
@@ -235,6 +243,8 @@
 
 			serial@d0000000 {
 			       status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
 			};
 
 			wdt@fc880000 {
diff --git a/arch/arm/boot/dts/spear300.dtsi b/arch/arm/boot/dts/spear300.dtsi
index ed3627c..f79b3df 100644
--- a/arch/arm/boot/dts/spear300.dtsi
+++ b/arch/arm/boot/dts/spear300.dtsi
@@ -27,7 +27,7 @@
 		};
 
 		clcd@60000000 {
-			compatible = "arm,clcd-pl110", "arm,primecell";
+			compatible = "arm,pl110", "arm,primecell";
 			reg = <0x60000000 0x1000>;
 			interrupts = <30>;
 			status = "disabled";
@@ -38,10 +38,10 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			reg = <0x94000000 0x1000	/* FSMC Register */
-			       0x80000000 0x0010>;	/* NAND Base */
-			reg-names = "fsmc_regs", "nand_data";
-			st,ale-off = <0x20000>;
-			st,cle-off = <0x10000>;
+			       0x80000000 0x0010	/* NAND Base DATA */
+			       0x80020000 0x0010	/* NAND Base ADDR */
+			       0x80010000 0x0010>;	/* NAND Base CMD */
+			reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
 			status = "disabled";
 		};
 
@@ -52,6 +52,14 @@
 			status = "disabled";
 		};
 
+		shirq: interrupt-controller@0x50000000 {
+			compatible = "st,spear300-shirq";
+			reg = <0x50000000 0x1000>;
+			interrupts = <28>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
+		};
+
 		apb {
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -64,12 +72,16 @@
 				compatible = "arm,pl061", "arm,primecell";
 				gpio-controller;
 				reg = <0xa9000000 0x1000>;
+				interrupts = <8>;
+				interrupt-parent = <&shirq>;
 				status = "disabled";
 			};
 
 			kbd@a0000000 {
 				compatible = "st,spear300-kbd";
 				reg = <0xa0000000 0x1000>;
+				interrupts = <7>;
+				interrupt-parent = <&shirq>;
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/boot/dts/spear310-evb.dts b/arch/arm/boot/dts/spear310-evb.dts
index b00544e..b096329 100644
--- a/arch/arm/boot/dts/spear310-evb.dts
+++ b/arch/arm/boot/dts/spear310-evb.dts
@@ -114,15 +114,23 @@
 				};
 				partition@10000 {
 					label = "u-boot";
-					reg = <0x10000 0x40000>;
+					reg = <0x10000 0x50000>;
 				};
-				partition@50000 {
+				partition@60000 {
+					label = "environment";
+					reg = <0x60000 0x10000>;
+				};
+				partition@70000 {
+					label = "dtb";
+					reg = <0x70000 0x10000>;
+				};
+				partition@80000 {
 					label = "linux";
-					reg = <0x50000 0x2c0000>;
+					reg = <0x80000 0x310000>;
 				};
-				partition@310000 {
+				partition@390000 {
 					label = "rootfs";
-					reg = <0x310000 0x4f0000>;
+					reg = <0x390000 0x0>;
 				};
 			};
 		};
@@ -158,26 +166,38 @@
 
 			serial@d0000000 {
 			       status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
 			};
 
 			serial@b2000000 {
 			       status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
 			};
 
 			serial@b2080000 {
 			       status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
 			};
 
 			serial@b2100000 {
 			       status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
 			};
 
 			serial@b2180000 {
 			       status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
 			};
 
 			serial@b2200000 {
 			       status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
 			};
 
 			wdt@fc880000 {
diff --git a/arch/arm/boot/dts/spear310.dtsi b/arch/arm/boot/dts/spear310.dtsi
index 62fc4fb..ab45b8c 100644
--- a/arch/arm/boot/dts/spear310.dtsi
+++ b/arch/arm/boot/dts/spear310.dtsi
@@ -22,9 +22,10 @@
 			  0xb0000000 0xb0000000 0x10000000
 			  0xd0000000 0xd0000000 0x30000000>;
 
-		pinmux@b4000000 {
+		pinmux: pinmux@b4000000 {
 			compatible = "st,spear310-pinmux";
 			reg = <0xb4000000 0x1000>;
+			#gpio-range-cells = <2>;
 		};
 
 		fsmc: flash@44000000 {
@@ -32,13 +33,21 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			reg = <0x44000000 0x1000	/* FSMC Register */
-			       0x40000000 0x0010>;	/* NAND Base */
-			reg-names = "fsmc_regs", "nand_data";
-			st,ale-off = <0x10000>;
-			st,cle-off = <0x20000>;
+			       0x40000000 0x0010	/* NAND Base DATA */
+			       0x40020000 0x0010	/* NAND Base ADDR */
+			       0x40010000 0x0010>;	/* NAND Base CMD */
+			reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
 			status = "disabled";
 		};
 
+		shirq: interrupt-controller@0xb4000000 {
+			compatible = "st,spear310-shirq";
+			reg = <0xb4000000 0x1000>;
+			interrupts = <28 29 30 1>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
+		};
+
 		apb {
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -49,32 +58,61 @@
 			serial@b2000000 {
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0xb2000000 0x1000>;
+				interrupts = <8>;
+				interrupt-parent = <&shirq>;
 				status = "disabled";
 			};
 
 			serial@b2080000 {
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0xb2080000 0x1000>;
+				interrupts = <9>;
+				interrupt-parent = <&shirq>;
 				status = "disabled";
 			};
 
 			serial@b2100000 {
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0xb2100000 0x1000>;
+				interrupts = <10>;
+				interrupt-parent = <&shirq>;
 				status = "disabled";
 			};
 
 			serial@b2180000 {
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0xb2180000 0x1000>;
+				interrupts = <11>;
+				interrupt-parent = <&shirq>;
 				status = "disabled";
 			};
 
 			serial@b2200000 {
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0xb2200000 0x1000>;
+				interrupts = <12>;
+				interrupt-parent = <&shirq>;
 				status = "disabled";
 			};
+
+			gpiopinctrl: gpio@b4000000 {
+				compatible = "st,spear-plgpio";
+				reg = <0xb4000000 0x1000>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				gpio-controller;
+				#gpio-cells = <2>;
+				gpio-ranges = <&pinmux 0 102>;
+				status = "disabled";
+
+				st-plgpio,ngpio = <102>;
+				st-plgpio,enb-reg = <0x10>;
+				st-plgpio,wdata-reg = <0x20>;
+				st-plgpio,dir-reg = <0x30>;
+				st-plgpio,ie-reg = <0x50>;
+				st-plgpio,rdata-reg = <0x40>;
+				st-plgpio,mis-reg = <0x60>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/spear320-evb.dts b/arch/arm/boot/dts/spear320-evb.dts
index 082328b..fdedbb5 100644
--- a/arch/arm/boot/dts/spear320-evb.dts
+++ b/arch/arm/boot/dts/spear320-evb.dts
@@ -76,20 +76,12 @@
 					st,function = "mii2";
 				};
 				pwm0_1 {
-					st,pins = "pwm0_1_pin_14_15_grp";
+					st,pins = "pwm0_1_pin_37_38_grp";
 					st,function = "pwm0_1";
 				};
-				pwm2 {
-					st,pins = "pwm2_pin_13_grp";
-					st,function = "pwm2";
-				};
 			};
 		};
 
-		clcd@90000000 {
-			status = "okay";
-		};
-
 		dma@fc400000 {
 			status = "okay";
 		};
@@ -103,6 +95,7 @@
 		};
 
 		sdhci@70000000 {
+			power-gpio = <&gpiopinctrl 61 1>;
 			status = "okay";
 		};
 
@@ -122,15 +115,23 @@
 				};
 				partition@10000 {
 					label = "u-boot";
-					reg = <0x10000 0x40000>;
+					reg = <0x10000 0x50000>;
+				};
+				partition@60000 {
+					label = "environment";
+					reg = <0x60000 0x10000>;
 				};
-				partition@50000 {
+				partition@70000 {
+					label = "dtb";
+					reg = <0x70000 0x10000>;
+				};
+				partition@80000 {
 					label = "linux";
-					reg = <0x50000 0x2c0000>;
+					reg = <0x80000 0x310000>;
 				};
-				partition@310000 {
+				partition@390000 {
 					label = "rootfs";
-					reg = <0x310000 0x4f0000>;
+					reg = <0x390000 0x0>;
 				};
 			};
 		};
@@ -164,6 +165,10 @@
 			       status = "okay";
 			};
 
+			gpio@b3000000 {
+			       status = "okay";
+			};
+
 			i2c0: i2c@d0180000 {
 			       status = "okay";
 			};
@@ -178,14 +183,20 @@
 
 			serial@d0000000 {
 			       status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
 			};
 
 			serial@a3000000 {
 			       status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
 			};
 
 			serial@a4000000 {
 			       status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
 			};
 
 			wdt@fc880000 {
diff --git a/arch/arm/boot/dts/spear320-hmi.dts b/arch/arm/boot/dts/spear320-hmi.dts
new file mode 100644
index 0000000..3075d2d
--- /dev/null
+++ b/arch/arm/boot/dts/spear320-hmi.dts
@@ -0,0 +1,305 @@
+/*
+ * DTS file for SPEAr320 Evaluation Baord
+ *
+ * Copyright 2012 Shiraz Hashim <shiraz.hashim@st.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "spear320.dtsi"
+
+/ {
+	model = "ST SPEAr320 HMI Board";
+	compatible = "st,spear320-hmi", "st,spear320";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	memory {
+		reg = <0 0x40000000>;
+	};
+
+	ahb {
+		pinmux@b3000000 {
+			st,pinmux-mode = <4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&state_default>;
+
+			state_default: pinmux {
+				i2c0 {
+					st,pins = "i2c0_grp";
+					st,function = "i2c0";
+				};
+				ssp0 {
+					st,pins = "ssp0_grp";
+					st,function = "ssp0";
+				};
+				uart0 {
+					st,pins = "uart0_grp";
+					st,function = "uart0";
+				};
+				clcd {
+					st,pins = "clcd_grp";
+					st,function = "clcd";
+				};
+				fsmc {
+					st,pins = "fsmc_8bit_grp";
+					st,function = "fsmc";
+				};
+				sdhci {
+					st,pins = "sdhci_cd_12_grp";
+					st,function = "sdhci";
+				};
+				i2s {
+					st,pins = "i2s_grp";
+					st,function = "i2s";
+				};
+				uart1 {
+					st,pins = "uart1_grp";
+					st,function = "uart1";
+				};
+				uart2 {
+					st,pins = "uart2_grp";
+					st,function = "uart2";
+				};
+				can0 {
+					st,pins = "can0_grp";
+					st,function = "can0";
+				};
+				can1 {
+					st,pins = "can1_grp";
+					st,function = "can1";
+				};
+				mii0_1 {
+					st,pins = "rmii0_1_grp";
+					st,function = "mii0_1";
+				};
+				pwm0_1 {
+					st,pins = "pwm0_1_pin_37_38_grp";
+					st,function = "pwm0_1";
+				};
+				pwm2 {
+					st,pins = "pwm2_pin_34_grp";
+					st,function = "pwm2";
+				};
+			};
+		};
+
+		clcd@90000000 {
+			status = "okay";
+		};
+
+		dma@fc400000 {
+			status = "okay";
+		};
+
+		ehci@e1800000 {
+			status = "okay";
+		};
+
+		fsmc: flash@4c000000 {
+			status = "okay";
+
+			partition@0 {
+				label = "xloader";
+				reg = <0x0 0x80000>;
+			};
+			partition@80000 {
+				label = "u-boot";
+				reg = <0x80000 0x140000>;
+			};
+			partition@1C0000 {
+				label = "environment";
+				reg = <0x1C0000 0x40000>;
+			};
+			partition@200000 {
+				label = "dtb";
+				reg = <0x200000 0x40000>;
+			};
+			partition@240000 {
+				label = "linux";
+				reg = <0x240000 0xC00000>;
+			};
+			partition@E40000 {
+				label = "rootfs";
+				reg = <0xE40000 0x0>;
+			};
+		};
+
+		gpio_keys {
+			compatible = "gpio-keys";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			button@1 {
+				label = "user button 1";
+				linux,code = <0x100>;
+				gpios = <&stmpegpio 3 0x4>;
+				debounce-interval = <20>;
+				gpio-key,wakeup = <1>;
+			};
+
+			button@2 {
+				label = "user button 2";
+				linux,code = <0x200>;
+				gpios = <&stmpegpio 2 0x4>;
+				debounce-interval = <20>;
+				gpio-key,wakeup = <1>;
+			};
+		};
+
+		ohci@e1900000 {
+			status = "okay";
+		};
+
+		ohci@e2100000 {
+			status = "okay";
+		};
+
+		pwm: pwm@a8000000 {
+			status = "okay";
+		};
+
+		sdhci@70000000 {
+			power-gpio = <&gpiopinctrl 50 1>;
+			power_always_enb;
+			status = "okay";
+		};
+
+		smi: flash@fc000000 {
+			status = "okay";
+			clock-rate=<50000000>;
+
+			flash@f8000000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0xf8000000 0x800000>;
+				st,smi-fast-mode;
+
+				partition@0 {
+					label = "xloader";
+					reg = <0x0 0x10000>;
+				};
+				partition@10000 {
+					label = "u-boot";
+					reg = <0x10000 0x50000>;
+				};
+				partition@60000 {
+					label = "environment";
+					reg = <0x60000 0x10000>;
+				};
+				partition@70000 {
+					label = "dtb";
+					reg = <0x70000 0x10000>;
+				};
+				partition@80000 {
+					label = "linux";
+					reg = <0x80000 0x310000>;
+				};
+				partition@390000 {
+					label = "rootfs";
+					reg = <0x390000 0x0>;
+				};
+			};
+		};
+
+		spi0: spi@d0100000 {
+			status = "okay";
+		};
+
+		spi1: spi@a5000000 {
+			status = "okay";
+		};
+
+		spi2: spi@a6000000 {
+			status = "okay";
+		};
+
+		usbd@e1100000 {
+			status = "okay";
+		};
+
+		apb {
+			gpio0: gpio@fc980000 {
+			       status = "okay";
+			};
+
+			gpio@b3000000 {
+				status = "okay";
+			};
+
+			i2c0: i2c@d0180000 {
+				status = "okay";
+
+				stmpe811@41 {
+					compatible = "st,stmpe811";
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0x41>;
+					irq-over-gpio;
+					irq-gpios = <&gpiopinctrl 29 0x4>;
+					id = <0>;
+					blocks = <0x5>;
+					irq-trigger = <0x1>;
+
+					stmpegpio: stmpe-gpio {
+						compatible = "stmpe,gpio";
+						reg = <0>;
+						gpio-controller;
+						#gpio-cells = <2>;
+						gpio,norequest-mask = <0xF3>;
+					};
+
+					stmpe610-ts {
+						compatible = "stmpe,ts";
+						reg = <0>;
+						ts,sample-time = <4>;
+						ts,mod-12b = <1>;
+						ts,ref-sel = <0>;
+						ts,adc-freq = <1>;
+						ts,ave-ctrl = <1>;
+						ts,touch-det-delay = <3>;
+						ts,settling = <4>;
+						ts,fraction-z = <7>;
+						ts,i-drive = <1>;
+					};
+				};
+			};
+
+			i2c1: i2c@a7000000 {
+			       status = "okay";
+			};
+
+			rtc@fc900000 {
+			       status = "okay";
+			};
+
+			serial@d0000000 {
+			       status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
+			};
+
+			serial@a3000000 {
+			       status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
+			};
+
+			serial@a4000000 {
+			       status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
+			};
+
+			wdt@fc880000 {
+			       status = "okay";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/spear320.dtsi b/arch/arm/boot/dts/spear320.dtsi
index 1f49d69..caa5520 100644
--- a/arch/arm/boot/dts/spear320.dtsi
+++ b/arch/arm/boot/dts/spear320.dtsi
@@ -21,15 +21,17 @@
 		ranges = <0x40000000 0x40000000 0x80000000
 			  0xd0000000 0xd0000000 0x30000000>;
 
-		pinmux@b3000000 {
+		pinmux: pinmux@b3000000 {
 			compatible = "st,spear320-pinmux";
 			reg = <0xb3000000 0x1000>;
+			#gpio-range-cells = <2>;
 		};
 
 		clcd@90000000 {
-			compatible = "arm,clcd-pl110", "arm,primecell";
+			compatible = "arm,pl110", "arm,primecell";
 			reg = <0x90000000 0x1000>;
-			interrupts = <33>;
+			interrupts = <8>;
+			interrupt-parent = <&shirq>;
 			status = "disabled";
 		};
 
@@ -38,37 +40,61 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			reg = <0x4c000000 0x1000	/* FSMC Register */
-			       0x50000000 0x0010>;	/* NAND Base */
-			reg-names = "fsmc_regs", "nand_data";
-			st,ale-off = <0x20000>;
-			st,cle-off = <0x10000>;
+			       0x50000000 0x0010	/* NAND Base DATA */
+			       0x50020000 0x0010	/* NAND Base ADDR */
+			       0x50010000 0x0010>;	/* NAND Base CMD */
+			reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
 			status = "disabled";
 		};
 
 		sdhci@70000000 {
 			compatible = "st,sdhci-spear";
 			reg = <0x70000000 0x100>;
-			interrupts = <29>;
+			interrupts = <10>;
+			interrupt-parent = <&shirq>;
 			status = "disabled";
 		};
 
+		shirq: interrupt-controller@0xb3000000 {
+			compatible = "st,spear320-shirq";
+			reg = <0xb3000000 0x1000>;
+			interrupts = <30 28 29 1>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
+		};
+
 		spi1: spi@a5000000 {
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0xa5000000 0x1000>;
+			interrupts = <15>;
+			interrupt-parent = <&shirq>;
+			#address-cells = <1>;
+			#size-cells = <0>;
 			status = "disabled";
 		};
 
 		spi2: spi@a6000000 {
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0xa6000000 0x1000>;
+			interrupts = <16>;
+			interrupt-parent = <&shirq>;
+			#address-cells = <1>;
+			#size-cells = <0>;
 			status = "disabled";
 		};
 
+		pwm: pwm@a8000000 {
+			compatible ="st,spear-pwm";
+			reg = <0xa8000000 0x1000>;
+			#pwm-cells = <2>;
+			status = "disabled";
+                };
+
 		apb {
 			#address-cells = <1>;
 			#size-cells = <1>;
 			compatible = "simple-bus";
-			ranges = <0xa0000000 0xa0000000 0x10000000
+			ranges = <0xa0000000 0xa0000000 0x20000000
 				  0xd0000000 0xd0000000 0x30000000>;
 
 			i2c1: i2c@a7000000 {
@@ -76,20 +102,46 @@
 				#size-cells = <0>;
 				compatible = "snps,designware-i2c";
 				reg = <0xa7000000 0x1000>;
+				interrupts = <21>;
+				interrupt-parent = <&shirq>;
 				status = "disabled";
 			};
 
 			serial@a3000000 {
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0xa3000000 0x1000>;
+				interrupts = <13>;
+				interrupt-parent = <&shirq>;
 				status = "disabled";
 			};
 
 			serial@a4000000 {
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0xa4000000 0x1000>;
+				interrupts = <14>;
+				interrupt-parent = <&shirq>;
 				status = "disabled";
 			};
+
+			gpiopinctrl: gpio@b3000000 {
+				compatible = "st,spear-plgpio";
+				reg = <0xb3000000 0x1000>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				gpio-controller;
+				#gpio-cells = <2>;
+				gpio-ranges = <&pinmux 0 102>;
+				status = "disabled";
+
+				st-plgpio,ngpio = <102>;
+				st-plgpio,enb-reg = <0x24>;
+				st-plgpio,wdata-reg = <0x34>;
+				st-plgpio,dir-reg = <0x44>;
+				st-plgpio,ie-reg = <0x64>;
+				st-plgpio,rdata-reg = <0x54>;
+				st-plgpio,mis-reg = <0x84>;
+				st-plgpio,eit-reg = <0x94>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/spear3xx.dtsi b/arch/arm/boot/dts/spear3xx.dtsi
index 3a8bb57..c2a852d 100644
--- a/arch/arm/boot/dts/spear3xx.dtsi
+++ b/arch/arm/boot/dts/spear3xx.dtsi
@@ -53,6 +53,7 @@
 			reg = <0xe0800000 0x8000>;
 			interrupts = <23 22>;
 			interrupt-names = "macirq", "eth_wake_irq";
+			phy-mode = "mii";
 			status = "disabled";
 		};
 
@@ -69,6 +70,8 @@
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0xd0100000 0x1000>;
 			interrupts = <20>;
+			#address-cells = <1>;
+			#size-cells = <0>;
 			status = "disabled";
 		};
 
@@ -120,7 +123,7 @@
 			};
 
 			rtc@fc900000 {
-				compatible = "st,spear-rtc";
+				compatible = "st,spear600-rtc";
 				reg = <0xfc900000 0x1000>;
 				interrupts = <10>;
 				status = "disabled";
diff --git a/arch/arm/boot/dts/spear600-evb.dts b/arch/arm/boot/dts/spear600-evb.dts
index 1119c22..d865a89 100644
--- a/arch/arm/boot/dts/spear600-evb.dts
+++ b/arch/arm/boot/dts/spear600-evb.dts
@@ -24,15 +24,35 @@
 	};
 
 	ahb {
+		clcd@fc200000 {
+			status = "okay";
+		};
+
 		dma@fc400000 {
 			status = "okay";
 		};
 
+		ehci@e1800000 {
+			status = "okay";
+		};
+
+		ehci@e2000000 {
+			status = "okay";
+		};
+
 		gmac: ethernet@e0800000 {
 			phy-mode = "gmii";
 			status = "okay";
 		};
 
+		ohci@e1900000 {
+			status = "okay";
+		};
+
+		ohci@e2100000 {
+			status = "okay";
+		};
+
 		smi: flash@fc000000 {
 			status = "okay";
 			clock-rate=<50000000>;
@@ -49,15 +69,23 @@
 				};
 				partition@10000 {
 					label = "u-boot";
-					reg = <0x10000 0x40000>;
+					reg = <0x10000 0x50000>;
 				};
-				partition@50000 {
+				partition@60000 {
+					label = "environment";
+					reg = <0x60000 0x10000>;
+				};
+				partition@70000 {
+					label = "dtb";
+					reg = <0x70000 0x10000>;
+				};
+				partition@80000 {
 					label = "linux";
-					reg = <0x50000 0x2c0000>;
+					reg = <0x80000 0x310000>;
 				};
-				partition@310000 {
+				partition@390000 {
 					label = "rootfs";
-					reg = <0x310000 0x4f0000>;
+					reg = <0x390000 0x0>;
 				};
 			};
 		};
@@ -65,10 +93,18 @@
 		apb {
 			serial@d0000000 {
 				status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
 			};
 
 			serial@d0080000 {
 				status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <>;
+			};
+
+			rtc@fc900000 {
+			       status = "okay";
 			};
 
 			i2c@d0200000 {
diff --git a/arch/arm/boot/dts/spear600.dtsi b/arch/arm/boot/dts/spear600.dtsi
index a3c36e4..19f99dc 100644
--- a/arch/arm/boot/dts/spear600.dtsi
+++ b/arch/arm/boot/dts/spear600.dtsi
@@ -45,6 +45,14 @@
 			#interrupt-cells = <1>;
 		};
 
+		clcd@fc200000 {
+			compatible = "arm,pl110", "arm,primecell";
+			reg = <0xfc200000 0x1000>;
+			interrupt-parent = <&vic1>;
+			interrupts = <12>;
+			status = "disabled";
+		};
+
 		dma@fc400000 {
 			compatible = "arm,pl080", "arm,primecell";
 			reg = <0xfc400000 0x1000>;
@@ -59,6 +67,7 @@
 			interrupt-parent = <&vic1>;
 			interrupts = <24 23>;
 			interrupt-names = "macirq", "eth_wake_irq";
+			phy-mode = "gmii";
 			status = "disabled";
 		};
 
@@ -67,10 +76,10 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			reg = <0xd1800000 0x1000	/* FSMC Register */
-			       0xd2000000 0x4000>;	/* NAND Base */
-			reg-names = "fsmc_regs", "nand_data";
-			st,ale-off = <0x20000>;
-			st,cle-off = <0x10000>;
+			       0xd2000000 0x0010	/* NAND Base DATA */
+			       0xd2020000 0x0010	/* NAND Base ADDR */
+			       0xd2010000 0x0010>;	/* NAND Base CMD */
+			reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
 			status = "disabled";
 		};
 
@@ -178,6 +187,13 @@
 				status = "disabled";
 			};
 
+			rtc@fc900000 {
+				compatible = "st,spear600-rtc";
+				reg = <0xfc900000 0x1000>;
+				interrupts = <10>;
+				status = "disabled";
+			};
+
 			timer@f0000000 {
 				compatible = "st,spear-timer";
 				reg = <0xf0000000 0x400>;
diff --git a/arch/arm/boot/dts/stuib.dtsi b/arch/arm/boot/dts/stuib.dtsi
new file mode 100644
index 0000000..39446a2
--- /dev/null
+++ b/arch/arm/boot/dts/stuib.dtsi
@@ -0,0 +1,78 @@
+/*
+ * 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
+ */
+
+/ {
+	soc-u9500 {
+		i2c@80004000 {
+			stmpe1601: stmpe1601@40 {
+				compatible = "st,stmpe1601";
+				reg = <0x40>;
+				interrupts = <26 0x1>;
+				interrupt-parent = <&gpio6>;
+				interrupt-controller;
+
+				wakeup-source;
+				st,autosleep-timeout = <1024>;
+
+				stmpe_keypad {
+					compatible = "st,stmpe-keypad";
+
+					debounce-interval = <64>;
+					st,scan-count = <8>;
+					st,no-autorepeat;
+
+					linux,keymap = <0x205006b
+							0x4010074
+							0x3050072
+							0x1030004
+							0x502006a
+							0x500000a
+							0x5008b
+							0x706001c
+							0x405000b
+							0x6070003
+							0x3040067
+							0x303006c
+							0x60400e7
+							0x602009e
+							0x4020073
+							0x5050002
+							0x4030069
+							0x3020008>;
+				};
+			};
+		};
+
+		i2c@80110000 {
+			bu21013_tp@0x5c {
+				compatible = "rhom,bu21013_tp";
+				reg = <0x5c>;
+				touch-gpio = <&gpio2 20 0x4>;
+				avdd-supply = <&ab8500_ldo_aux1_reg>;
+
+				rhom,touch-max-x = <384>;
+				rhom,touch-max-y = <704>;
+				rhom,flip-y;
+			};
+
+			bu21013_tp@0x5d {
+				compatible = "rhom,bu21013_tp";
+				reg = <0x5d>;
+				touch-gpio = <&gpio2 20 0x4>;
+				avdd-supply = <&ab8500_ldo_aux1_reg>;
+
+				rhom,touch-max-x = <384>;
+				rhom,touch-max-y = <704>;
+				rhom,flip-y;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sun4i-cubieboard.dts b/arch/arm/boot/dts/sun4i-cubieboard.dts
new file mode 100644
index 0000000..f4ca126
--- /dev/null
+++ b/arch/arm/boot/dts/sun4i-cubieboard.dts
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012 Stefan Roese
+ * Stefan Roese <sr@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/ "sun4i.dtsi"
+
+/ {
+	model = "Cubietech Cubieboard";
+	compatible = "cubietech,cubieboard", "allwinner,sun4i";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+	};
+
+	chosen {
+		bootargs = "earlyprintk console=ttyS0,115200";
+	};
+
+	soc {
+		uart0: uart@01c28000 {
+			status = "okay";
+		};
+
+		uart1: uart@01c28400 {
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sun4i.dtsi b/arch/arm/boot/dts/sun4i.dtsi
new file mode 100644
index 0000000..e61fdd4
--- /dev/null
+++ b/arch/arm/boot/dts/sun4i.dtsi
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2012 Stefan Roese
+ * Stefan Roese <sr@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
+ */
+
+/include/ "sunxi.dtsi"
+
+/ {
+	memory {
+		reg = <0x40000000 0x80000000>;
+	};
+};
diff --git a/arch/arm/boot/dts/sun5i-olinuxino.dts b/arch/arm/boot/dts/sun5i-olinuxino.dts
new file mode 100644
index 0000000..d6ff889
--- /dev/null
+++ b/arch/arm/boot/dts/sun5i-olinuxino.dts
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2012 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "sun5i.dtsi"
+
+/ {
+	model = "Olimex A13-Olinuxino";
+	compatible = "olimex,a13-olinuxino", "allwinner,sun5i";
+
+	chosen {
+		bootargs = "earlyprintk console=ttyS0,115200";
+	};
+
+	soc {
+		uart1: uart@01c28400 {
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi
new file mode 100644
index 0000000..59a2d26
--- /dev/null
+++ b/arch/arm/boot/dts/sun5i.dtsi
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "sunxi.dtsi"
+
+/ {
+	memory {
+		reg = <0x40000000 0x20000000>;
+	};
+};
diff --git a/arch/arm/boot/dts/sunxi.dtsi b/arch/arm/boot/dts/sunxi.dtsi
new file mode 100644
index 0000000..8bbc2bf
--- /dev/null
+++ b/arch/arm/boot/dts/sunxi.dtsi
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	interrupt-parent = <&intc>;
+
+	cpus {
+		cpu@0 {
+			compatible = "arm,cortex-a8";
+		};
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc: oscillator {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x01c20000 0x300000>;
+		ranges;
+
+		timer@01c20c00 {
+			compatible = "allwinner,sunxi-timer";
+			reg = <0x01c20c00 0x90>;
+			interrupts = <22>;
+			clocks = <&osc>;
+		};
+
+		wdt: watchdog@01c20c90 {
+			compatible = "allwinner,sunxi-wdt";
+			reg = <0x01c20c90 0x10>;
+		};
+
+		intc: interrupt-controller@01c20400 {
+			compatible = "allwinner,sunxi-ic";
+			reg = <0x01c20400 0x400>;
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+
+		uart0: uart@01c28000 {
+			compatible = "ns8250";
+			reg = <0x01c28000 0x400>;
+			interrupts = <1>;
+			reg-shift = <2>;
+			clock-frequency = <24000000>;
+			status = "disabled";
+		};
+
+		uart1: uart@01c28400 {
+			compatible = "ns8250";
+			reg = <0x01c28400 0x400>;
+			interrupts = <2>;
+			reg-shift = <2>;
+			clock-frequency = <24000000>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts
index c3ef1ad..43eb72a 100644
--- a/arch/arm/boot/dts/tegra20-harmony.dts
+++ b/arch/arm/boot/dts/tegra20-harmony.dts
@@ -10,6 +10,18 @@
 		reg = <0x00000000 0x40000000>;
 	};
 
+	host1x {
+		hdmi {
+			status = "okay";
+
+			vdd-supply = <&hdmi_vdd_reg>;
+			pll-supply = <&hdmi_pll_reg>;
+
+			nvidia,ddc-i2c-bus = <&hdmi_ddc>;
+			nvidia,hpd-gpio = <&gpio 111 0>; /* PN7 */
+		};
+	};
+
 	pinmux {
 		pinctrl-names = "default";
 		pinctrl-0 = <&state_default>;
@@ -262,9 +274,9 @@
 		};
 	};
 
-	i2c@7000c400 {
+	hdmi_ddc: i2c@7000c400 {
 		status = "okay";
-		clock-frequency = <400000>;
+		clock-frequency = <100000>;
 	};
 
 	i2c@7000c500 {
@@ -297,131 +309,98 @@
 			vinldo9-supply = <&sm2_reg>;
 
 			regulators {
-				#address-cells = <1>;
-				#size-cells = <0>;
-
-				sys_reg: regulator@0 {
-					reg = <0>;
-					regulator-compatible = "sys";
+				sys_reg: sys {
 					regulator-name = "vdd_sys";
 					regulator-always-on;
 				};
 
-				regulator@1 {
-					reg = <1>;
-					regulator-compatible = "sm0";
+				sm0 {
 					regulator-name = "vdd_sm0,vdd_core";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 					regulator-always-on;
 				};
 
-				regulator@2 {
-					reg = <2>;
-					regulator-compatible = "sm1";
+				sm1 {
 					regulator-name = "vdd_sm1,vdd_cpu";
 					regulator-min-microvolt = <1000000>;
 					regulator-max-microvolt = <1000000>;
 					regulator-always-on;
 				};
 
-				sm2_reg: regulator@3 {
-					reg = <3>;
-					regulator-compatible = "sm2";
+				sm2_reg: sm2 {
 					regulator-name = "vdd_sm2,vin_ldo*";
 					regulator-min-microvolt = <3700000>;
 					regulator-max-microvolt = <3700000>;
 					regulator-always-on;
 				};
 
-				regulator@4 {
-					reg = <4>;
-					regulator-compatible = "ldo0";
+				ldo0 {
 					regulator-name = "vdd_ldo0,vddio_pex_clk";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 				};
 
-				regulator@5 {
-					reg = <5>;
-					regulator-compatible = "ldo1";
+				ldo1 {
 					regulator-name = "vdd_ldo1,avdd_pll*";
 					regulator-min-microvolt = <1100000>;
 					regulator-max-microvolt = <1100000>;
 					regulator-always-on;
 				};
 
-				regulator@6 {
-					reg = <6>;
-					regulator-compatible = "ldo2";
+				ldo2 {
 					regulator-name = "vdd_ldo2,vdd_rtc";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 				};
 
-				regulator@7 {
-					reg = <7>;
-					regulator-compatible = "ldo3";
+				ldo3 {
 					regulator-name = "vdd_ldo3,avdd_usb*";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 					regulator-always-on;
 				};
 
-				regulator@8 {
-					reg = <8>;
-					regulator-compatible = "ldo4";
+				ldo4 {
 					regulator-name = "vdd_ldo4,avdd_osc,vddio_sys";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 					regulator-always-on;
 				};
 
-				regulator@9 {
-					reg = <9>;
-					regulator-compatible = "ldo5";
+				ldo5 {
 					regulator-name = "vdd_ldo5,vcore_mmc";
 					regulator-min-microvolt = <2850000>;
 					regulator-max-microvolt = <2850000>;
 					regulator-always-on;
 				};
 
-				regulator@10 {
-					reg = <10>;
-					regulator-compatible = "ldo6";
+				ldo6 {
 					regulator-name = "vdd_ldo6,avdd_vdac";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 				};
 
-				regulator@11 {
-					reg = <11>;
-					regulator-compatible = "ldo7";
+				hdmi_vdd_reg: ldo7 {
 					regulator-name = "vdd_ldo7,avdd_hdmi";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 				};
 
-				regulator@12 {
-					reg = <12>;
-					regulator-compatible = "ldo8";
+				hdmi_pll_reg: ldo8 {
 					regulator-name = "vdd_ldo8,avdd_hdmi_pll";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 				};
 
-				regulator@13 {
-					reg = <13>;
-					regulator-compatible = "ldo9";
+				ldo9 {
 					regulator-name = "vdd_ldo9,avdd_2v85,vdd_ddr_rx";
 					regulator-min-microvolt = <2850000>;
 					regulator-max-microvolt = <2850000>;
 					regulator-always-on;
 				};
 
-				regulator@14 {
-					reg = <14>;
-					regulator-compatible = "ldo_rtc";
+				ldo_rtc {
 					regulator-name = "vdd_rtc_out,vdd_cell";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
@@ -429,6 +408,11 @@
 				};
 			};
 		};
+
+		temperature-sensor@4c {
+			compatible = "adi,adt7461";
+			reg = <0x4c>;
+		};
 	};
 
 	pmc {
diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts
index ddf287f..6a93d14 100644
--- a/arch/arm/boot/dts/tegra20-paz00.dts
+++ b/arch/arm/boot/dts/tegra20-paz00.dts
@@ -291,37 +291,26 @@
 			vinldo9-supply = <&sm2_reg>;
 
 			regulators {
-				#address-cells = <1>;
-				#size-cells = <0>;
-
-				sys_reg: regulator@0 {
-					reg = <0>;
-					regulator-compatible = "sys";
+				sys_reg: sys {
 					regulator-name = "vdd_sys";
 					regulator-always-on;
 				};
 
-				regulator@1 {
-					reg = <1>;
-					regulator-compatible = "sm0";
+				sm0 {
 					regulator-name = "+1.2vs_sm0,vdd_core";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 					regulator-always-on;
 				};
 
-				regulator@2 {
-					reg = <2>;
-					regulator-compatible = "sm1";
+				sm1 {
 					regulator-name = "+1.0vs_sm1,vdd_cpu";
 					regulator-min-microvolt = <1000000>;
 					regulator-max-microvolt = <1000000>;
 					regulator-always-on;
 				};
 
-				sm2_reg: regulator@3 {
-					reg = <3>;
-					regulator-compatible = "sm2";
+				sm2_reg: sm2 {
 					regulator-name = "+3.7vs_sm2,vin_ldo*";
 					regulator-min-microvolt = <3700000>;
 					regulator-max-microvolt = <3700000>;
@@ -330,53 +319,41 @@
 
 				/* LDO0 is not connected to anything */
 
-				regulator@5 {
-					reg = <5>;
-					regulator-compatible = "ldo1";
+				ldo1 {
 					regulator-name = "+1.1vs_ldo1,avdd_pll*";
 					regulator-min-microvolt = <1100000>;
 					regulator-max-microvolt = <1100000>;
 					regulator-always-on;
 				};
 
-				regulator@6 {
-					reg = <6>;
-					regulator-compatible = "ldo2";
+				ldo2 {
 					regulator-name = "+1.2vs_ldo2,vdd_rtc";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 				};
 
-				regulator@7 {
-					reg = <7>;
-					regulator-compatible = "ldo3";
+				ldo3 {
 					regulator-name = "+3.3vs_ldo3,avdd_usb*";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 					regulator-always-on;
 				};
 
-				regulator@8 {
-					reg = <8>;
-					regulator-compatible = "ldo4";
+				ldo4 {
 					regulator-name = "+1.8vs_ldo4,avdd_osc,vddio_sys";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 					regulator-always-on;
 				};
 
-				regulator@9 {
-					reg = <9>;
-					regulator-compatible = "ldo5";
+				ldo5 {
 					regulator-name = "+2.85vs_ldo5,vcore_mmc";
 					regulator-min-microvolt = <2850000>;
 					regulator-max-microvolt = <2850000>;
 					regulator-always-on;
 				};
 
-				regulator@10 {
-					reg = <10>;
-					regulator-compatible = "ldo6";
+				ldo6 {
 					/*
 					 * Research indicates this should be
 					 * 1.8v; other boards that use this
@@ -390,34 +367,26 @@
 					regulator-max-microvolt = <1800000>;
 				};
 
-				regulator@11 {
-					reg = <11>;
-					regulator-compatible = "ldo7";
+				ldo7 {
 					regulator-name = "+3.3vs_ldo7,avdd_hdmi";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 				};
 
-				regulator@12 {
-					reg = <12>;
-					regulator-compatible = "ldo8";
+				ldo8 {
 					regulator-name = "+1.8vs_ldo8,avdd_hdmi_pll";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 				};
 
-				regulator@13 {
-					reg = <13>;
-					regulator-compatible = "ldo9";
+				ldo9 {
 					regulator-name = "+2.85vs_ldo9,vdd_ddr_rx";
 					regulator-min-microvolt = <2850000>;
 					regulator-max-microvolt = <2850000>;
 					regulator-always-on;
 				};
 
-				regulator@14 {
-					reg = <14>;
-					regulator-compatible = "ldo_rtc";
+				ldo_rtc {
 					regulator-name = "+3.3vs_rtc";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
diff --git a/arch/arm/boot/dts/tegra20-plutux.dts b/arch/arm/boot/dts/tegra20-plutux.dts
index 331a3ef..2894800 100644
--- a/arch/arm/boot/dts/tegra20-plutux.dts
+++ b/arch/arm/boot/dts/tegra20-plutux.dts
@@ -6,6 +6,12 @@
 	model = "Avionic Design Plutux board";
 	compatible = "ad,plutux", "ad,tamonten", "nvidia,tegra20";
 
+	host1x {
+		hdmi {
+			status = "okay";
+		};
+	};
+
 	i2c@7000c000 {
 		wm8903: wm8903@1a {
 			compatible = "wlf,wm8903";
diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts
index f0ba901..4204598 100644
--- a/arch/arm/boot/dts/tegra20-seaboard.dts
+++ b/arch/arm/boot/dts/tegra20-seaboard.dts
@@ -395,37 +395,26 @@
 			vinldo9-supply = <&sm2_reg>;
 
 			regulators {
-				#address-cells = <1>;
-				#size-cells = <0>;
-
-				sys_reg: regulator@0 {
-					reg = <0>;
-					regulator-compatible = "sys";
+				sys_reg: sys {
 					regulator-name = "vdd_sys";
 					regulator-always-on;
 				};
 
-				regulator@1 {
-					reg = <1>;
-					regulator-compatible = "sm0";
+				sm0 {
 					regulator-name = "vdd_sm0,vdd_core";
 					regulator-min-microvolt = <1300000>;
 					regulator-max-microvolt = <1300000>;
 					regulator-always-on;
 				};
 
-				regulator@2 {
-					reg = <2>;
-					regulator-compatible = "sm1";
+				sm1 {
 					regulator-name = "vdd_sm1,vdd_cpu";
 					regulator-min-microvolt = <1125000>;
 					regulator-max-microvolt = <1125000>;
 					regulator-always-on;
 				};
 
-				sm2_reg: regulator@3 {
-					reg = <3>;
-					regulator-compatible = "sm2";
+				sm2_reg: sm2 {
 					regulator-name = "vdd_sm2,vin_ldo*";
 					regulator-min-microvolt = <3700000>;
 					regulator-max-microvolt = <3700000>;
@@ -434,86 +423,66 @@
 
 				/* LDO0 is not connected to anything */
 
-				regulator@5 {
-					reg = <5>;
-					regulator-compatible = "ldo1";
+				ldo1 {
 					regulator-name = "vdd_ldo1,avdd_pll*";
 					regulator-min-microvolt = <1100000>;
 					regulator-max-microvolt = <1100000>;
 					regulator-always-on;
 				};
 
-				regulator@6 {
-					reg = <6>;
-					regulator-compatible = "ldo2";
+				ldo2 {
 					regulator-name = "vdd_ldo2,vdd_rtc";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 				};
 
-				regulator@7 {
-					reg = <7>;
-					regulator-compatible = "ldo3";
+				ldo3 {
 					regulator-name = "vdd_ldo3,avdd_usb*";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 					regulator-always-on;
 				};
 
-				regulator@8 {
-					reg = <8>;
-					regulator-compatible = "ldo4";
+				ldo4 {
 					regulator-name = "vdd_ldo4,avdd_osc,vddio_sys";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 					regulator-always-on;
 				};
 
-				regulator@9 {
-					reg = <9>;
-					regulator-compatible = "ldo5";
+				ldo5 {
 					regulator-name = "vdd_ldo5,vcore_mmc";
 					regulator-min-microvolt = <2850000>;
 					regulator-max-microvolt = <2850000>;
 					regulator-always-on;
 				};
 
-				regulator@10 {
-					reg = <10>;
-					regulator-compatible = "ldo6";
+				ldo6 {
 					regulator-name = "vdd_ldo6,avdd_vdac,vddio_vi,vddio_cam";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 				};
 
-				regulator@11 {
-					reg = <11>;
-					regulator-compatible = "ldo7";
+				ldo7 {
 					regulator-name = "vdd_ldo7,avdd_hdmi,vdd_fuse";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 				};
 
-				regulator@12 {
-					reg = <12>;
-					regulator-compatible = "ldo8";
+				ldo8 {
 					regulator-name = "vdd_ldo8,avdd_hdmi_pll";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 				};
 
-				regulator@13 {
-					reg = <13>;
-					regulator-compatible = "ldo9";
+				ldo9 {
 					regulator-name = "vdd_ldo9,avdd_2v85,vdd_ddr_rx";
 					regulator-min-microvolt = <2850000>;
 					regulator-max-microvolt = <2850000>;
 					regulator-always-on;
 				};
 
-				regulator@14 {
-					reg = <14>;
-					regulator-compatible = "ldo_rtc";
+				ldo_rtc {
 					regulator-name = "vdd_rtc_out,vdd_cell";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
@@ -523,12 +492,12 @@
 		};
 
 		temperature-sensor@4c {
-			compatible = "nct1008";
+			compatible = "onnn,nct1008";
 			reg = <0x4c>;
 		};
 
 		magnetometer@c {
-			compatible = "ak8975";
+			compatible = "ak,ak8975";
 			reg = <0xc>;
 			interrupt-parent = <&gpio>;
 			interrupts = <109 0x04>; /* gpio PN5 */
@@ -592,6 +561,12 @@
 		status = "okay";
 	};
 
+	sdhci@c8000000 {
+		status = "okay";
+		power-gpios = <&gpio 86 0>; /* gpio PK6 */
+		bus-width = <4>;
+	};
+
 	sdhci@c8000400 {
 		status = "okay";
 		cd-gpios = <&gpio 69 0>; /* gpio PI5 */
diff --git a/arch/arm/boot/dts/tegra20-tamonten.dtsi b/arch/arm/boot/dts/tegra20-tamonten.dtsi
index f18cec9..a239ccd 100644
--- a/arch/arm/boot/dts/tegra20-tamonten.dtsi
+++ b/arch/arm/boot/dts/tegra20-tamonten.dtsi
@@ -8,6 +8,16 @@
 		reg = <0x00000000 0x20000000>;
 	};
 
+	host1x {
+		hdmi {
+			vdd-supply = <&hdmi_vdd_reg>;
+			pll-supply = <&hdmi_pll_reg>;
+
+			nvidia,ddc-i2c-bus = <&hdmi_ddc>;
+			nvidia,hpd-gpio = <&gpio 111 0>; /* PN7 */
+		};
+	};
+
 	pinmux {
 		pinctrl-names = "default";
 		pinctrl-0 = <&state_default>;
@@ -62,10 +72,6 @@
 				nvidia,pins = "dap4";
 				nvidia,function = "dap4";
 			};
-			ddc {
-				nvidia,pins = "ddc";
-				nvidia,function = "i2c2";
-			};
 			dta {
 				nvidia,pins = "dta", "dtd";
 				nvidia,function = "sdio2";
@@ -91,7 +97,7 @@
 				nvidia,function = "pcie";
 			};
 			hdint {
-				nvidia,pins = "hdint", "pta";
+				nvidia,pins = "hdint";
 				nvidia,function = "hdmi";
 			};
 			i2cp {
@@ -230,6 +236,39 @@
 				nvidia,pull = <1>;
 			};
 		};
+
+		state_i2cmux_ddc: pinmux_i2cmux_ddc {
+			ddc {
+				nvidia,pins = "ddc";
+				nvidia,function = "i2c2";
+			};
+			pta {
+				nvidia,pins = "pta";
+				nvidia,function = "rsvd4";
+			};
+		};
+
+		state_i2cmux_pta: pinmux_i2cmux_pta {
+			ddc {
+				nvidia,pins = "ddc";
+				nvidia,function = "rsvd4";
+			};
+			pta {
+				nvidia,pins = "pta";
+				nvidia,function = "i2c2";
+			};
+		};
+
+		state_i2cmux_idle: pinmux_i2cmux_idle {
+			ddc {
+				nvidia,pins = "ddc";
+				nvidia,function = "rsvd4";
+			};
+			pta {
+				nvidia,pins = "pta";
+				nvidia,function = "rsvd4";
+			};
+		};
 	};
 
 	i2s@70002800 {
@@ -246,6 +285,36 @@
 		status = "okay";
 	};
 
+	i2c@7000c400 {
+		clock-frequency = <100000>;
+		status = "okay";
+	};
+
+	i2cmux {
+		compatible = "i2c-mux-pinctrl";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		i2c-parent = <&{/i2c@7000c400}>;
+
+		pinctrl-names = "ddc", "pta", "idle";
+		pinctrl-0 = <&state_i2cmux_ddc>;
+		pinctrl-1 = <&state_i2cmux_pta>;
+		pinctrl-2 = <&state_i2cmux_idle>;
+
+		hdmi_ddc: i2c@0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c@1 {
+			reg = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
 	i2c@7000d000 {
 		clock-frequency = <400000>;
 		status = "okay";
@@ -271,97 +340,72 @@
 			vinldo9-supply = <&sm2_reg>;
 
 			regulators {
-				#address-cells = <1>;
-				#size-cells = <0>;
-
-				sys_reg: regulator@0 {
-					reg = <0>;
-					regulator-compatible = "sys";
+				sys_reg: sys {
 					regulator-name = "vdd_sys";
 					regulator-always-on;
 				};
 
-				regulator@1 {
-					reg = <1>;
-					regulator-compatible = "sm0";
+				sm0 {
 					regulator-name = "vdd_sys_sm0,vdd_core";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 					regulator-always-on;
 				};
 
-				regulator@2 {
-					reg = <2>;
-					regulator-compatible = "sm1";
+				sm1 {
 					regulator-name = "vdd_sys_sm1,vdd_cpu";
 					regulator-min-microvolt = <1000000>;
 					regulator-max-microvolt = <1000000>;
 					regulator-always-on;
 				};
 
-				sm2_reg: regulator@3 {
-					reg = <3>;
-					regulator-compatible = "sm2";
+				sm2_reg: sm2 {
 					regulator-name = "vdd_sys_sm2,vin_ldo*";
 					regulator-min-microvolt = <3700000>;
 					regulator-max-microvolt = <3700000>;
 					regulator-always-on;
 				};
 
-				regulator@4 {
-					reg = <4>;
-					regulator-compatible = "ldo0";
+				ldo0 {
 					regulator-name = "vdd_ldo0,vddio_pex_clk";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 				};
 
-				regulator@5 {
-					reg = <5>;
-					regulator-compatible = "ldo1";
+				ldo1 {
 					regulator-name = "vdd_ldo1,avdd_pll*";
 					regulator-min-microvolt = <1100000>;
 					regulator-max-microvolt = <1100000>;
 					regulator-always-on;
 				};
 
-				regulator@6 {
-					reg = <6>;
-					regulator-compatible = "ldo2";
+				ldo2 {
 					regulator-name = "vdd_ldo2,vdd_rtc";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 				};
 
-				regulator@7 {
-					reg = <7>;
-					regulator-compatible = "ldo3";
+				ldo3 {
 					regulator-name = "vdd_ldo3,avdd_usb*";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 					regulator-always-on;
 				};
 
-				regulator@8 {
-					reg = <8>;
-					regulator-compatible = "ldo4";
+				ldo4 {
 					regulator-name = "vdd_ldo4,avdd_osc,vddio_sys";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 					regulator-always-on;
 				};
 
-				regulator@9 {
-					reg = <9>;
-					regulator-compatible = "ldo5";
+				ldo5 {
 					regulator-name = "vdd_ldo5,vcore_mmc";
 					regulator-min-microvolt = <2850000>;
 					regulator-max-microvolt = <2850000>;
 				};
 
-				regulator@10 {
-					reg = <10>;
-					regulator-compatible = "ldo6";
+				ldo6 {
 					regulator-name = "vdd_ldo6,avdd_vdac";
 					/*
 					 * According to the Tegra 2 Automotive
@@ -373,25 +417,19 @@
 					regulator-max-microvolt = <2850000>;
 				};
 
-				regulator@11 {
-					reg = <11>;
-					regulator-compatible = "ldo7";
+				hdmi_vdd_reg: ldo7 {
 					regulator-name = "vdd_ldo7,avdd_hdmi";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 				};
 
-				regulator@12 {
-					reg = <12>;
-					regulator-compatible = "ldo8";
+				hdmi_pll_reg: ldo8 {
 					regulator-name = "vdd_ldo8,avdd_hdmi_pll";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 				};
 
-				regulator@13 {
-					reg = <13>;
-					regulator-compatible = "ldo9";
+				ldo9 {
 					regulator-name = "vdd_ldo9,vdd_ddr_rx,avdd_cam";
 					/*
 					 * According to the Tegra 2 Automotive
@@ -404,9 +442,7 @@
 					regulator-always-on;
 				};
 
-				regulator@14 {
-					reg = <14>;
-					regulator-compatible = "ldo_rtc";
+				ldo_rtc {
 					regulator-name = "vdd_rtc_out";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
@@ -414,6 +450,11 @@
 				};
 			};
 		};
+
+		temperature-sensor@4c {
+			compatible = "onnn,nct1008";
+			reg = <0x4c>;
+		};
 	};
 
 	pmc {
diff --git a/arch/arm/boot/dts/tegra20-tec.dts b/arch/arm/boot/dts/tegra20-tec.dts
index 9aff31b..402b210 100644
--- a/arch/arm/boot/dts/tegra20-tec.dts
+++ b/arch/arm/boot/dts/tegra20-tec.dts
@@ -6,10 +6,13 @@
 	model = "Avionic Design Tamonten Evaluation Carrier";
 	compatible = "ad,tec", "ad,tamonten", "nvidia,tegra20";
 
-	i2c@7000c000 {
-		clock-frequency = <400000>;
-		status = "okay";
+	host1x {
+		hdmi {
+			status = "okay";
+		};
+	};
 
+	i2c@7000c000 {
 		wm8903: wm8903@1a {
 			compatible = "wlf,wm8903";
 			reg = <0x1a>;
diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts
index 27fb8a6..b70b4cb 100644
--- a/arch/arm/boot/dts/tegra20-trimslice.dts
+++ b/arch/arm/boot/dts/tegra20-trimslice.dts
@@ -10,6 +10,18 @@
 		reg = <0x00000000 0x40000000>;
 	};
 
+	host1x {
+		hdmi {
+			status = "okay";
+
+			vdd-supply = <&hdmi_vdd_reg>;
+			pll-supply = <&hdmi_pll_reg>;
+
+			nvidia,ddc-i2c-bus = <&hdmi_ddc>;
+			nvidia,hpd-gpio = <&gpio 111 0>; /* PN7 */
+		};
+	};
+
 	pinmux {
 		pinctrl-names = "default";
 		pinctrl-0 = <&state_default>;
@@ -249,14 +261,24 @@
 		clock-frequency = <216000000>;
 	};
 
-	i2c@7000c000 {
+	dvi_ddc: i2c@7000c000 {
 		status = "okay";
-		clock-frequency = <400000>;
+		clock-frequency = <100000>;
 	};
 
-	i2c@7000c400 {
+	spi@7000c380 {
 		status = "okay";
-		clock-frequency = <400000>;
+		spi-max-frequency = <48000000>;
+		spi-flash@0 {
+			compatible = "winbond,w25q80bl";
+			reg = <0>;
+			spi-max-frequency = <48000000>;
+		};
+	};
+
+	hdmi_ddc: i2c@7000c400 {
+		status = "okay";
+		clock-frequency = <100000>;
 	};
 
 	i2c@7000c500 {
@@ -300,6 +322,30 @@
 		bus-width = <4>;
 	};
 
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		hdmi_vdd_reg: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "avdd_hdmi";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		hdmi_pll_reg: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "avdd_hdmi_pll";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			regulator-always-on;
+		};
+	};
+
 	sound {
 		compatible = "nvidia,tegra-audio-trimslice";
 		nvidia,i2s-controller = <&tegra_i2s1>;
diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts
index 3e5952f..adc4754 100644
--- a/arch/arm/boot/dts/tegra20-ventana.dts
+++ b/arch/arm/boot/dts/tegra20-ventana.dts
@@ -64,11 +64,6 @@
 				nvidia,pins = "dap4";
 				nvidia,function = "dap4";
 			};
-			ddc {
-				nvidia,pins = "ddc", "owc", "spdi", "spdo",
-					"uac";
-				nvidia,function = "rsvd2";
-			};
 			dta {
 				nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte";
 				nvidia,function = "vi";
@@ -98,7 +93,7 @@
 				nvidia,function = "pcie";
 			};
 			hdint {
-				nvidia,pins = "hdint", "pta";
+				nvidia,pins = "hdint";
 				nvidia,function = "hdmi";
 			};
 			i2cp {
@@ -129,6 +124,10 @@
 					"lspi", "lvp1", "lvs";
 				nvidia,function = "displaya";
 			};
+			owc {
+				nvidia,pins = "owc", "spdi", "spdo", "uac";
+				nvidia,function = "rsvd2";
+			};
 			pmc {
 				nvidia,pins = "pmc";
 				nvidia,function = "pwr_on";
@@ -237,6 +236,49 @@
 					"ld23_22";
 				nvidia,pull = <1>;
 			};
+			drive_sdio1 {
+				nvidia,pins = "drive_sdio1";
+				nvidia,high-speed-mode = <0>;
+				nvidia,schmitt = <1>;
+				nvidia,low-power-mode = <3>;
+				nvidia,pull-down-strength = <31>;
+				nvidia,pull-up-strength = <31>;
+				nvidia,slew-rate-rising = <3>;
+				nvidia,slew-rate-falling = <3>;
+			};
+		};
+
+		state_i2cmux_ddc: pinmux_i2cmux_ddc {
+			ddc {
+				nvidia,pins = "ddc";
+				nvidia,function = "i2c2";
+			};
+			pta {
+				nvidia,pins = "pta";
+				nvidia,function = "rsvd4";
+			};
+		};
+
+		state_i2cmux_pta: pinmux_i2cmux_pta {
+			ddc {
+				nvidia,pins = "ddc";
+				nvidia,function = "rsvd4";
+			};
+			pta {
+				nvidia,pins = "pta";
+				nvidia,function = "i2c2";
+			};
+		};
+
+		state_i2cmux_idle: pinmux_i2cmux_idle {
+			ddc {
+				nvidia,pins = "ddc";
+				nvidia,function = "rsvd4";
+			};
+			pta {
+				nvidia,pins = "pta";
+				nvidia,function = "rsvd4";
+			};
 		};
 	};
 
@@ -281,6 +323,31 @@
 		clock-frequency = <400000>;
 	};
 
+	i2cmux {
+		compatible = "i2c-mux-pinctrl";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		i2c-parent = <&{/i2c@7000c400}>;
+
+		pinctrl-names = "ddc", "pta", "idle";
+		pinctrl-0 = <&state_i2cmux_ddc>;
+		pinctrl-1 = <&state_i2cmux_pta>;
+		pinctrl-2 = <&state_i2cmux_idle>;
+
+		i2c@0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c@1 {
+			reg = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
 	i2c@7000c500 {
 		status = "okay";
 		clock-frequency = <400000>;
@@ -311,37 +378,26 @@
 			vinldo9-supply = <&sm2_reg>;
 
 			regulators {
-				#address-cells = <1>;
-				#size-cells = <0>;
-
-				sys_reg: regulator@0 {
-					reg = <0>;
-					regulator-compatible = "sys";
+				sys_reg: sys {
 					regulator-name = "vdd_sys";
 					regulator-always-on;
 				};
 
-				regulator@1 {
-					reg = <1>;
-					regulator-compatible = "sm0";
+				sm0 {
 					regulator-name = "vdd_sm0,vdd_core";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 					regulator-always-on;
 				};
 
-				regulator@2 {
-					reg = <2>;
-					regulator-compatible = "sm1";
+				sm1 {
 					regulator-name = "vdd_sm1,vdd_cpu";
 					regulator-min-microvolt = <1000000>;
 					regulator-max-microvolt = <1000000>;
 					regulator-always-on;
 				};
 
-				sm2_reg: regulator@3 {
-					reg = <3>;
-					regulator-compatible = "sm2";
+				sm2_reg: sm2 {
 					regulator-name = "vdd_sm2,vin_ldo*";
 					regulator-min-microvolt = <3700000>;
 					regulator-max-microvolt = <3700000>;
@@ -350,86 +406,66 @@
 
 				/* LDO0 is not connected to anything */
 
-				regulator@5 {
-					reg = <5>;
-					regulator-compatible = "ldo1";
+				ldo1 {
 					regulator-name = "vdd_ldo1,avdd_pll*";
 					regulator-min-microvolt = <1100000>;
 					regulator-max-microvolt = <1100000>;
 					regulator-always-on;
 				};
 
-				regulator@6 {
-					reg = <6>;
-					regulator-compatible = "ldo2";
+				ldo2 {
 					regulator-name = "vdd_ldo2,vdd_rtc";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 				};
 
-				regulator@7 {
-					reg = <7>;
-					regulator-compatible = "ldo3";
+				ldo3 {
 					regulator-name = "vdd_ldo3,avdd_usb*";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 					regulator-always-on;
 				};
 
-				regulator@8 {
-					reg = <8>;
-					regulator-compatible = "ldo4";
+				ldo4 {
 					regulator-name = "vdd_ldo4,avdd_osc,vddio_sys";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 					regulator-always-on;
 				};
 
-				regulator@9 {
-					reg = <9>;
-					regulator-compatible = "ldo5";
+				ldo5 {
 					regulator-name = "vdd_ldo5,vcore_mmc";
 					regulator-min-microvolt = <2850000>;
 					regulator-max-microvolt = <2850000>;
 					regulator-always-on;
 				};
 
-				regulator@10 {
-					reg = <10>;
-					regulator-compatible = "ldo6";
+				ldo6 {
 					regulator-name = "vdd_ldo6,avdd_vdac";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 				};
 
-				regulator@11 {
-					reg = <11>;
-					regulator-compatible = "ldo7";
+				ldo7 {
 					regulator-name = "vdd_ldo7,avdd_hdmi,vdd_fuse";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 				};
 
-				regulator@12 {
-					reg = <12>;
-					regulator-compatible = "ldo8";
+				ldo8 {
 					regulator-name = "vdd_ldo8,avdd_hdmi_pll";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 				};
 
-				regulator@13 {
-					reg = <13>;
-					regulator-compatible = "ldo9";
+				ldo9 {
 					regulator-name = "vdd_ldo9,avdd_2v85,vdd_ddr_rx";
 					regulator-min-microvolt = <2850000>;
 					regulator-max-microvolt = <2850000>;
 					regulator-always-on;
 				};
 
-				regulator@14 {
-					reg = <14>;
-					regulator-compatible = "ldo_rtc";
+				ldo_rtc {
 					regulator-name = "vdd_rtc_out,vdd_cell";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
@@ -437,6 +473,11 @@
 				};
 			};
 		};
+
+		temperature-sensor@4c {
+			compatible = "onnn,nct1008";
+			reg = <0x4c>;
+		};
 	};
 
 	pmc {
@@ -456,6 +497,12 @@
 		status = "okay";
 	};
 
+	sdhci@c8000000 {
+		status = "okay";
+		power-gpios = <&gpio 86 0>; /* gpio PK6 */
+		bus-width = <4>;
+	};
+
 	sdhci@c8000400 {
 		status = "okay";
 		cd-gpios = <&gpio 69 0>; /* gpio PI5 */
diff --git a/arch/arm/boot/dts/tegra20-whistler.dts b/arch/arm/boot/dts/tegra20-whistler.dts
index c636d00..20d576e 100644
--- a/arch/arm/boot/dts/tegra20-whistler.dts
+++ b/arch/arm/boot/dts/tegra20-whistler.dts
@@ -10,6 +10,18 @@
 		reg = <0x00000000 0x20000000>;
 	};
 
+	host1x {
+		hdmi {
+			status = "okay";
+
+			vdd-supply = <&hdmi_vdd_reg>;
+			pll-supply = <&hdmi_pll_reg>;
+
+			nvidia,ddc-i2c-bus = <&hdmi_ddc>;
+			nvidia,hpd-gpio = <&gpio 111 0>; /* PN7 */
+		};
+	};
+
 	pinmux {
 		pinctrl-names = "default";
 		pinctrl-0 = <&state_default>;
@@ -246,6 +258,11 @@
 		clock-frequency = <216000000>;
 	};
 
+	hdmi_ddc: i2c@7000c400 {
+		status = "okay";
+		clock-frequency = <100000>;
+	};
+
 	i2c@7000d000 {
 		status = "okay";
 		clock-frequency = <100000>;
@@ -295,243 +312,182 @@
 			in20-supply = <&mbatt_reg>;
 
 			regulators {
-				#address-cells = <1>;
-				#size-cells = <0>;
-
-				mbatt_reg: regulator@0 {
-					reg = <0>;
-					regulator-compatible = "mbatt";
+				mbatt_reg: mbatt {
 					regulator-name = "vbat_pmu";
 					regulator-always-on;
 				};
 
-				regulator@1 {
-					reg = <1>;
-					regulator-compatible = "sd1";
+				sd1 {
 					regulator-name = "nvvdd_sv1,vdd_cpu_pmu";
 					regulator-min-microvolt = <1000000>;
 					regulator-max-microvolt = <1000000>;
 					regulator-always-on;
 				};
 
-				regulator@2 {
-					reg = <2>;
-					regulator-compatible = "sd2";
+				sd2 {
 					regulator-name = "nvvdd_sv2,vdd_core";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 					regulator-always-on;
 				};
 
-				nvvdd_sv3_reg: regulator@3 {
-					reg = <3>;
-					regulator-compatible = "sd3";
+				nvvdd_sv3_reg: sd3 {
 					regulator-name = "nvvdd_sv3";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 					regulator-always-on;
 				};
 
-				regulator@4 {
-					reg = <4>;
-					regulator-compatible = "ldo1";
+				ldo1 {
 					regulator-name = "nvvdd_ldo1,vddio_rx_ddr,vcore_acc";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 					regulator-always-on;
 				};
 
-				regulator@5 {
-					reg = <5>;
-					regulator-compatible = "ldo2";
+				ldo2 {
 					regulator-name = "nvvdd_ldo2,avdd_pll*";
 					regulator-min-microvolt = <1100000>;
 					regulator-max-microvolt = <1100000>;
 					regulator-always-on;
 				};
 
-				regulator@6 {
-					reg = <6>;
-					regulator-compatible = "ldo3";
+				ldo3 {
 					regulator-name = "nvvdd_ldo3,vcom_1v8b";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 					regulator-always-on;
 				};
 
-				regulator@7 {
-					reg = <7>;
-					regulator-compatible = "ldo4";
+				ldo4 {
 					regulator-name = "nvvdd_ldo4,avdd_usb*";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 					regulator-always-on;
 				};
 
-				regulator@8 {
-					reg = <8>;
-					regulator-compatible = "ldo5";
+				ldo5 {
 					regulator-name = "nvvdd_ldo5,vcore_mmc,avdd_lcd1,vddio_1wire";
 					regulator-min-microvolt = <2800000>;
 					regulator-max-microvolt = <2800000>;
 					regulator-always-on;
 				};
 
-				regulator@9 {
-					reg = <9>;
-					regulator-compatible = "ldo6";
+				hdmi_pll_reg: ldo6 {
 					regulator-name = "nvvdd_ldo6,avdd_hdmi_pll";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 				};
 
-				regulator@10 {
-					reg = <10>;
-					regulator-compatible = "ldo7";
+				ldo7 {
 					regulator-name = "nvvdd_ldo7,avddio_audio";
 					regulator-min-microvolt = <2800000>;
 					regulator-max-microvolt = <2800000>;
 					regulator-always-on;
 				};
 
-				regulator@11 {
-					reg = <11>;
-					regulator-compatible = "ldo8";
+				ldo8 {
 					regulator-name = "nvvdd_ldo8,vcom_3v0,vcore_cmps";
 					regulator-min-microvolt = <3000000>;
 					regulator-max-microvolt = <3000000>;
 				};
 
-				regulator@12 {
-					reg = <12>;
-					regulator-compatible = "ldo9";
+				ldo9 {
 					regulator-name = "nvvdd_ldo9,avdd_cam*";
 					regulator-min-microvolt = <2800000>;
 					regulator-max-microvolt = <2800000>;
 				};
 
-				regulator@13 {
-					reg = <13>;
-					regulator-compatible = "ldo10";
+				ldo10 {
 					regulator-name = "nvvdd_ldo10,avdd_usb_ic_3v0";
 					regulator-min-microvolt = <3000000>;
 					regulator-max-microvolt = <3000000>;
 					regulator-always-on;
 				};
 
-				regulator@14 {
-					reg = <14>;
-					regulator-compatible = "ldo11";
+				hdmi_vdd_reg: ldo11 {
 					regulator-name = "nvvdd_ldo11,vddio_pex_clk,vcom_33,avdd_hdmi";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 				};
 
-				regulator@15 {
-					reg = <15>;
-					regulator-compatible = "ldo12";
+				ldo12 {
 					regulator-name = "nvvdd_ldo12,vddio_sdio";
 					regulator-min-microvolt = <2800000>;
 					regulator-max-microvolt = <2800000>;
 					regulator-always-on;
 				};
 
-				regulator@16 {
-					reg = <16>;
-					regulator-compatible = "ldo13";
+				ldo13 {
 					regulator-name = "nvvdd_ldo13,vcore_phtn,vdd_af";
 					regulator-min-microvolt = <2800000>;
 					regulator-max-microvolt = <2800000>;
 				};
 
-				regulator@17 {
-					reg = <17>;
-					regulator-compatible = "ldo14";
+				ldo14 {
 					regulator-name = "nvvdd_ldo14,avdd_vdac";
 					regulator-min-microvolt = <2800000>;
 					regulator-max-microvolt = <2800000>;
 				};
 
-				regulator@18 {
-					reg = <18>;
-					regulator-compatible = "ldo15";
+				ldo15 {
 					regulator-name = "nvvdd_ldo15,vcore_temp,vddio_hdcp";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 				};
 
-				regulator@19 {
-					reg = <19>;
-					regulator-compatible = "ldo16";
+				ldo16 {
 					regulator-name = "nvvdd_ldo16,vdd_dbrtr";
 					regulator-min-microvolt = <1300000>;
 					regulator-max-microvolt = <1300000>;
 				};
 
-				regulator@20 {
-					reg = <20>;
-					regulator-compatible = "ldo17";
+				ldo17 {
 					regulator-name = "nvvdd_ldo17,vddio_mipi";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 				};
 
-				regulator@21 {
-					reg = <21>;
-					regulator-compatible = "ldo18";
+				ldo18 {
 					regulator-name = "nvvdd_ldo18,vddio_vi,vcore_cam*";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 				};
 
-				regulator@22 {
-					reg = <22>;
-					regulator-compatible = "ldo19";
+				ldo19 {
 					regulator-name = "nvvdd_ldo19,avdd_lcd2,vddio_lx";
 					regulator-min-microvolt = <2800000>;
 					regulator-max-microvolt = <2800000>;
 				};
 
-				regulator@23 {
-					reg = <23>;
-					regulator-compatible = "ldo20";
+				ldo20 {
 					regulator-name = "nvvdd_ldo20,vddio_ddr_1v2,vddio_hsic,vcom_1v2";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 					regulator-always-on;
 				};
 
-				regulator@24 {
-					reg = <24>;
-					regulator-compatible = "out5v";
+				out5v {
 					regulator-name = "usb0_vbus_reg";
 				};
 
-				regulator@25 {
-					reg = <25>;
-					regulator-compatible = "out33v";
+				out33v {
 					regulator-name = "pmu_out3v3";
 				};
 
-				regulator@26 {
-					reg = <26>;
-					regulator-compatible = "bbat";
+				bbat {
 					regulator-name = "pmu_bbat";
 					regulator-min-microvolt = <2400000>;
 					regulator-max-microvolt = <2400000>;
 					regulator-always-on;
 				};
 
-				regulator@27 {
-					reg = <27>;
-					regulator-compatible = "sdby";
+				sdby {
 					regulator-name = "vdd_aon";
 					regulator-always-on;
 				};
 
-				regulator@28 {
-					reg = <28>;
-					regulator-compatible = "vrtc";
+				vrtc {
 					regulator-name = "vrtc,pmu_vccadc";
 					regulator-always-on;
 				};
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index f3a09d0..b8effa1 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -4,6 +4,108 @@
 	compatible = "nvidia,tegra20";
 	interrupt-parent = <&intc>;
 
+	host1x {
+		compatible = "nvidia,tegra20-host1x", "simple-bus";
+		reg = <0x50000000 0x00024000>;
+		interrupts = <0 65 0x04   /* mpcore syncpt */
+			      0 67 0x04>; /* mpcore general */
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		ranges = <0x54000000 0x54000000 0x04000000>;
+
+		mpe {
+			compatible = "nvidia,tegra20-mpe";
+			reg = <0x54040000 0x00040000>;
+			interrupts = <0 68 0x04>;
+		};
+
+		vi {
+			compatible = "nvidia,tegra20-vi";
+			reg = <0x54080000 0x00040000>;
+			interrupts = <0 69 0x04>;
+		};
+
+		epp {
+			compatible = "nvidia,tegra20-epp";
+			reg = <0x540c0000 0x00040000>;
+			interrupts = <0 70 0x04>;
+		};
+
+		isp {
+			compatible = "nvidia,tegra20-isp";
+			reg = <0x54100000 0x00040000>;
+			interrupts = <0 71 0x04>;
+		};
+
+		gr2d {
+			compatible = "nvidia,tegra20-gr2d";
+			reg = <0x54140000 0x00040000>;
+			interrupts = <0 72 0x04>;
+		};
+
+		gr3d {
+			compatible = "nvidia,tegra20-gr3d";
+			reg = <0x54180000 0x00040000>;
+		};
+
+		dc@54200000 {
+			compatible = "nvidia,tegra20-dc";
+			reg = <0x54200000 0x00040000>;
+			interrupts = <0 73 0x04>;
+
+			rgb {
+				status = "disabled";
+			};
+		};
+
+		dc@54240000 {
+			compatible = "nvidia,tegra20-dc";
+			reg = <0x54240000 0x00040000>;
+			interrupts = <0 74 0x04>;
+
+			rgb {
+				status = "disabled";
+			};
+		};
+
+		hdmi {
+			compatible = "nvidia,tegra20-hdmi";
+			reg = <0x54280000 0x00040000>;
+			interrupts = <0 75 0x04>;
+			status = "disabled";
+		};
+
+		tvo {
+			compatible = "nvidia,tegra20-tvo";
+			reg = <0x542c0000 0x00040000>;
+			interrupts = <0 76 0x04>;
+			status = "disabled";
+		};
+
+		dsi {
+			compatible = "nvidia,tegra20-dsi";
+			reg = <0x54300000 0x00040000>;
+			status = "disabled";
+		};
+	};
+
+	timer@50004600 {
+		compatible = "arm,cortex-a9-twd-timer";
+		reg = <0x50040600 0x20>;
+		interrupts = <1 13 0x304>;
+	};
+
+	cache-controller@50043000 {
+		compatible = "arm,pl310-cache";
+		reg = <0x50043000 0x1000>;
+		arm,data-latency = <5 5 2>;
+		arm,tag-latency = <4 4 2>;
+		cache-unified;
+		cache-level = <2>;
+	};
+
 	intc: interrupt-controller {
 		compatible = "arm,cortex-a9-gic";
 		reg = <0x50041000 0x1000
@@ -12,6 +114,15 @@
 		#interrupt-cells = <3>;
 	};
 
+	timer@60005000 {
+		compatible = "nvidia,tegra20-timer";
+		reg = <0x60005000 0x60>;
+		interrupts = <0 0 0x04
+			      0 1 0x04
+			      0 41 0x04
+			      0 42 0x04>;
+	};
+
 	apbdma: dma {
 		compatible = "nvidia,tegra20-apbdma";
 		reg = <0x6000a000 0x1200>;
@@ -129,6 +240,12 @@
 		#pwm-cells = <2>;
 	};
 
+	rtc {
+		compatible = "nvidia,tegra20-rtc";
+		reg = <0x7000e000 0x100>;
+		interrupts = <0 2 0x04>;
+	};
+
 	i2c@7000c000 {
 		compatible = "nvidia,tegra20-i2c";
 		reg = <0x7000c000 0x100>;
@@ -138,6 +255,16 @@
 		status = "disabled";
 	};
 
+	spi@7000c380 {
+		compatible = "nvidia,tegra20-sflash";
+		reg = <0x7000c380 0x80>;
+		interrupts = <0 39 0x04>;
+		nvidia,dma-request-selector = <&apbdma 11>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
 	i2c@7000c400 {
 		compatible = "nvidia,tegra20-i2c";
 		reg = <0x7000c400 0x100>;
@@ -165,6 +292,46 @@
 		status = "disabled";
 	};
 
+	spi@7000d400 {
+		compatible = "nvidia,tegra20-slink";
+		reg = <0x7000d400 0x200>;
+		interrupts = <0 59 0x04>;
+		nvidia,dma-request-selector = <&apbdma 15>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi@7000d600 {
+		compatible = "nvidia,tegra20-slink";
+		reg = <0x7000d600 0x200>;
+		interrupts = <0 82 0x04>;
+		nvidia,dma-request-selector = <&apbdma 16>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi@7000d800 {
+		compatible = "nvidia,tegra20-slink";
+		reg = <0x7000d480 0x200>;
+		interrupts = <0 83 0x04>;
+		nvidia,dma-request-selector = <&apbdma 17>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi@7000da00 {
+		compatible = "nvidia,tegra20-slink";
+		reg = <0x7000da00 0x200>;
+		interrupts = <0 93 0x04>;
+		nvidia,dma-request-selector = <&apbdma 18>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
 	pmc {
 		compatible = "nvidia,tegra20-pmc";
 		reg = <0x7000e400 0x400>;
diff --git a/arch/arm/boot/dts/tegra30-cardhu-a02.dts b/arch/arm/boot/dts/tegra30-cardhu-a02.dts
index dd4222f..adc88aa 100644
--- a/arch/arm/boot/dts/tegra30-cardhu-a02.dts
+++ b/arch/arm/boot/dts/tegra30-cardhu-a02.dts
@@ -83,5 +83,11 @@
 			gpio = <&gpio 83 0>; /* GPIO PK3 */
 		};
 	};
+
+	sdhci@78000400 {
+		status = "okay";
+		power-gpios = <&gpio 28 0>; /* gpio PD4 */
+		bus-width = <4>;
+	};
 };
 
diff --git a/arch/arm/boot/dts/tegra30-cardhu-a04.dts b/arch/arm/boot/dts/tegra30-cardhu-a04.dts
index 0828f09..08163e1 100644
--- a/arch/arm/boot/dts/tegra30-cardhu-a04.dts
+++ b/arch/arm/boot/dts/tegra30-cardhu-a04.dts
@@ -95,4 +95,10 @@
 			gpio = <&gpio 232 0>; /* GPIO PDD0 */
 		};
 	};
+
+	sdhci@78000400 {
+		status = "okay";
+		power-gpios = <&gpio 27 0>; /* gpio PD3 */
+		bus-width = <4>;
+	};
 };
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi
index d10c9c5..bdb2a66 100644
--- a/arch/arm/boot/dts/tegra30-cardhu.dtsi
+++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
@@ -52,6 +52,22 @@
 				nvidia,pull = <2>;
 				nvidia,tristate = <0>;
 			};
+			sdmmc3_clk_pa6 {
+				nvidia,pins = "sdmmc3_clk_pa6";
+				nvidia,function = "sdmmc3";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+			};
+			sdmmc3_cmd_pa7 {
+				nvidia,pins =	"sdmmc3_cmd_pa7",
+						"sdmmc3_dat0_pb7",
+						"sdmmc3_dat1_pb6",
+						"sdmmc3_dat2_pb5",
+						"sdmmc3_dat3_pb4";
+				nvidia,function = "sdmmc3";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+			};
 			sdmmc4_clk_pcc4 {
 				nvidia,pins =	"sdmmc4_clk_pcc4",
 						"sdmmc4_rst_n_pcc3";
@@ -81,6 +97,15 @@
 				nvidia,pull = <0>;
 				nvidia,tristate = <0>;
 			};
+			sdio3 {
+				nvidia,pins = "drive_sdio3";
+				nvidia,high-speed-mode = <0>;
+				nvidia,schmitt = <0>;
+				nvidia,pull-down-strength = <46>;
+				nvidia,pull-up-strength = <42>;
+				nvidia,slew-rate-rising = <1>;
+				nvidia,slew-rate-falling = <1>;
+			};
 		};
 	};
 
@@ -171,56 +196,41 @@
 			vccio-supply = <&vdd_ac_bat_reg>;
 
 			regulators {
-				#address-cells = <1>;
-				#size-cells = <0>;
-
-				vdd1_reg: regulator@0 {
-					reg = <0>;
-					regulator-compatible = "vdd1";
+				vdd1_reg: vdd1 {
 					regulator-name = "vddio_ddr_1v2";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 					regulator-always-on;
 				};
 
-				vdd2_reg: regulator@1 {
-					reg = <1>;
-					regulator-compatible = "vdd2";
+				vdd2_reg: vdd2 {
 					regulator-name = "vdd_1v5_gen";
 					regulator-min-microvolt = <1500000>;
 					regulator-max-microvolt = <1500000>;
 					regulator-always-on;
 				};
 
-				vddctrl_reg: regulator@2 {
-					reg = <2>;
-					regulator-compatible = "vddctrl";
+				vddctrl_reg: vddctrl {
 					regulator-name = "vdd_cpu,vdd_sys";
 					regulator-min-microvolt = <1000000>;
 					regulator-max-microvolt = <1000000>;
 					regulator-always-on;
 				};
 
-				vio_reg: regulator@3 {
-					reg = <3>;
-					regulator-compatible = "vio";
+				vio_reg: vio {
 					regulator-name = "vdd_1v8_gen";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 					regulator-always-on;
 				};
 
-				ldo1_reg: regulator@4 {
-					reg = <4>;
-					regulator-compatible = "ldo1";
+				ldo1_reg: ldo1 {
 					regulator-name = "vdd_pexa,vdd_pexb";
 					regulator-min-microvolt = <1050000>;
 					regulator-max-microvolt = <1050000>;
 				};
 
-				ldo2_reg: regulator@5 {
-					reg = <5>;
-					regulator-compatible = "ldo2";
+				ldo2_reg: ldo2 {
 					regulator-name = "vdd_sata,avdd_plle";
 					regulator-min-microvolt = <1050000>;
 					regulator-max-microvolt = <1050000>;
@@ -228,44 +238,34 @@
 
 				/* LDO3 is not connected to anything */
 
-				ldo4_reg: regulator@7 {
-					reg = <7>;
-					regulator-compatible = "ldo4";
+				ldo4_reg: ldo4 {
 					regulator-name = "vdd_rtc";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 					regulator-always-on;
 				};
 
-				ldo5_reg: regulator@8 {
-					reg = <8>;
-					regulator-compatible = "ldo5";
+				ldo5_reg: ldo5 {
 					regulator-name = "vddio_sdmmc,avdd_vdac";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
 					regulator-always-on;
 				};
 
-				ldo6_reg: regulator@9 {
-					reg = <9>;
-					regulator-compatible = "ldo6";
+				ldo6_reg: ldo6 {
 					regulator-name = "avdd_dsi_csi,pwrdet_mipi";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 				};
 
-				ldo7_reg: regulator@10 {
-					reg = <10>;
-					regulator-compatible = "ldo7";
+				ldo7_reg: ldo7 {
 					regulator-name = "vdd_pllm,x,u,a_p_c_s";
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 					regulator-always-on;
 				};
 
-				ldo8_reg: regulator@11 {
-					reg = <11>;
-					regulator-compatible = "ldo8";
+				ldo8_reg: ldo8 {
 					regulator-name = "vdd_ddr_hs";
 					regulator-min-microvolt = <1000000>;
 					regulator-max-microvolt = <1000000>;
@@ -275,6 +275,16 @@
 		};
 	};
 
+	spi@7000da00 {
+		status = "okay";
+		spi-max-frequency = <25000000>;
+		spi-flash@1 {
+			compatible = "winbond,w25q32";
+			reg = <1>;
+			spi-max-frequency = <20000000>;
+		};
+	};
+
 	ahub {
 		i2s@70080400 {
 			status = "okay";
@@ -409,6 +419,8 @@
 			regulator-name = "vdd_com";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
 			enable-active-high;
 			gpio = <&gpio 24 0>; /* gpio PD0 */
 			vin-supply = <&sys_3v3_reg>;
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index df7f227..529fdb8 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -4,6 +4,108 @@
 	compatible = "nvidia,tegra30";
 	interrupt-parent = <&intc>;
 
+	host1x {
+		compatible = "nvidia,tegra30-host1x", "simple-bus";
+		reg = <0x50000000 0x00024000>;
+		interrupts = <0 65 0x04   /* mpcore syncpt */
+			      0 67 0x04>; /* mpcore general */
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		ranges = <0x54000000 0x54000000 0x04000000>;
+
+		mpe {
+			compatible = "nvidia,tegra30-mpe";
+			reg = <0x54040000 0x00040000>;
+			interrupts = <0 68 0x04>;
+		};
+
+		vi {
+			compatible = "nvidia,tegra30-vi";
+			reg = <0x54080000 0x00040000>;
+			interrupts = <0 69 0x04>;
+		};
+
+		epp {
+			compatible = "nvidia,tegra30-epp";
+			reg = <0x540c0000 0x00040000>;
+			interrupts = <0 70 0x04>;
+		};
+
+		isp {
+			compatible = "nvidia,tegra30-isp";
+			reg = <0x54100000 0x00040000>;
+			interrupts = <0 71 0x04>;
+		};
+
+		gr2d {
+			compatible = "nvidia,tegra30-gr2d";
+			reg = <0x54140000 0x00040000>;
+			interrupts = <0 72 0x04>;
+		};
+
+		gr3d {
+			compatible = "nvidia,tegra30-gr3d";
+			reg = <0x54180000 0x00040000>;
+		};
+
+		dc@54200000 {
+			compatible = "nvidia,tegra30-dc";
+			reg = <0x54200000 0x00040000>;
+			interrupts = <0 73 0x04>;
+
+			rgb {
+				status = "disabled";
+			};
+		};
+
+		dc@54240000 {
+			compatible = "nvidia,tegra30-dc";
+			reg = <0x54240000 0x00040000>;
+			interrupts = <0 74 0x04>;
+
+			rgb {
+				status = "disabled";
+			};
+		};
+
+		hdmi {
+			compatible = "nvidia,tegra30-hdmi";
+			reg = <0x54280000 0x00040000>;
+			interrupts = <0 75 0x04>;
+			status = "disabled";
+		};
+
+		tvo {
+			compatible = "nvidia,tegra30-tvo";
+			reg = <0x542c0000 0x00040000>;
+			interrupts = <0 76 0x04>;
+			status = "disabled";
+		};
+
+		dsi {
+			compatible = "nvidia,tegra30-dsi";
+			reg = <0x54300000 0x00040000>;
+			status = "disabled";
+		};
+	};
+
+	timer@50004600 {
+		compatible = "arm,cortex-a9-twd-timer";
+		reg = <0x50040600 0x20>;
+		interrupts = <1 13 0xf04>;
+	};
+
+	cache-controller@50043000 {
+		compatible = "arm,pl310-cache";
+		reg = <0x50043000 0x1000>;
+		arm,data-latency = <6 6 2>;
+		arm,tag-latency = <5 5 2>;
+		cache-unified;
+		cache-level = <2>;
+	};
+
 	intc: interrupt-controller {
 		compatible = "arm,cortex-a9-gic";
 		reg = <0x50041000 0x1000
@@ -12,6 +114,17 @@
 		#interrupt-cells = <3>;
 	};
 
+	timer@60005000 {
+		compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
+		reg = <0x60005000 0x400>;
+		interrupts = <0 0 0x04
+			      0 1 0x04
+			      0 41 0x04
+			      0 42 0x04
+			      0 121 0x04
+			      0 122 0x04>;
+	};
+
 	apbdma: dma {
 		compatible = "nvidia,tegra30-apbdma", "nvidia,tegra20-apbdma";
 		reg = <0x6000a000 0x1400>;
@@ -123,6 +236,12 @@
 		#pwm-cells = <2>;
 	};
 
+	rtc {
+		compatible = "nvidia,tegra30-rtc", "nvidia,tegra20-rtc";
+		reg = <0x7000e000 0x100>;
+		interrupts = <0 2 0x04>;
+	};
+
 	i2c@7000c000 {
 		compatible =  "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
 		reg = <0x7000c000 0x100>;
@@ -168,6 +287,66 @@
 		status = "disabled";
 	};
 
+	spi@7000d400 {
+		compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+		reg = <0x7000d400 0x200>;
+		interrupts = <0 59 0x04>;
+		nvidia,dma-request-selector = <&apbdma 15>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi@7000d600 {
+		compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+		reg = <0x7000d600 0x200>;
+		interrupts = <0 82 0x04>;
+		nvidia,dma-request-selector = <&apbdma 16>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi@7000d800 {
+		compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+		reg = <0x7000d480 0x200>;
+		interrupts = <0 83 0x04>;
+		nvidia,dma-request-selector = <&apbdma 17>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi@7000da00 {
+		compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+		reg = <0x7000da00 0x200>;
+		interrupts = <0 93 0x04>;
+		nvidia,dma-request-selector = <&apbdma 18>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi@7000dc00 {
+		compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+		reg = <0x7000dc00 0x200>;
+		interrupts = <0 94 0x04>;
+		nvidia,dma-request-selector = <&apbdma 27>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi@7000de00 {
+		compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
+		reg = <0x7000de00 0x200>;
+		interrupts = <0 79 0x04>;
+		nvidia,dma-request-selector = <&apbdma 28>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
 	pmc {
 		compatible = "nvidia,tegra20-pmc", "nvidia,tegra30-pmc";
 		reg = <0x7000e400 0x400>;
diff --git a/arch/arm/boot/dts/twl4030.dtsi b/arch/arm/boot/dts/twl4030.dtsi
index ff00017..63411b0 100644
--- a/arch/arm/boot/dts/twl4030.dtsi
+++ b/arch/arm/boot/dts/twl4030.dtsi
@@ -37,6 +37,24 @@
 		regulator-max-microvolt = <3150000>;
 	};
 
+	vusb1v5: regulator-vusb1v5 {
+		compatible = "ti,twl4030-vusb1v5";
+	};
+
+	vusb1v8: regulator-vusb1v8 {
+		compatible = "ti,twl4030-vusb1v8";
+	};
+
+	vusb3v1: regulator-vusb3v1 {
+		compatible = "ti,twl4030-vusb3v1";
+	};
+
+	vsim: regulator-vsim {
+		compatible = "ti,twl4030-vsim";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3000000>;
+	};
+
 	twl_gpio: gpio {
 		compatible = "ti,twl4030-gpio";
 		gpio-controller;
@@ -44,4 +62,13 @@
 		interrupt-controller;
 		#interrupt-cells = <1>;
 	};
+
+	twl4030-usb {
+		compatible = "ti,twl4030-usb";
+		interrupts = <10>, <4>;
+		usb1v5-supply = <&vusb1v5>;
+		usb1v8-supply = <&vusb1v8>;
+		usb3v1-supply = <&vusb3v1>;
+		usb_mode = <1>;
+	};
 };
diff --git a/arch/arm/boot/dts/twl6030.dtsi b/arch/arm/boot/dts/twl6030.dtsi
index 123e2c4..9996cfc 100644
--- a/arch/arm/boot/dts/twl6030.dtsi
+++ b/arch/arm/boot/dts/twl6030.dtsi
@@ -86,4 +86,9 @@
 	clk32kg: regulator-clk32kg {
 		compatible = "ti,twl6030-clk32kg";
 	};
+
+	twl_usb_comparator: usb-comparator {
+		compatible = "ti,twl6030-usb";
+		interrupts = <4>, <10>;
+	};
 };
diff --git a/arch/arm/boot/dts/u9540.dts b/arch/arm/boot/dts/u9540.dts
new file mode 100644
index 0000000..95892ec
--- /dev/null
+++ b/arch/arm/boot/dts/u9540.dts
@@ -0,0 +1,72 @@
+/*
+ * 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/ "dbx5x0.dtsi"
+
+/ {
+	model = "ST-Ericsson U9540 platform with Device Tree";
+	compatible = "st-ericsson,u9540";
+
+	memory {
+		reg = <0x00000000 0x20000000>;
+	};
+
+	soc-u9500 {
+		uart@80120000 {
+			status = "okay";
+		};
+
+		uart@80121000 {
+			status = "okay";
+		};
+
+		uart@80007000 {
+			status = "okay";
+		};
+
+		// 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  = <&gpio7 6 0x4>; // 230
+			cd-inverted;
+
+			status = "okay";
+		};
+
+
+		// WLAN SDIO channel
+		sdi1_per2@80118000 {
+			arm,primecell-periphid = <0x10480180>;
+			max-frequency = <50000000>;
+			bus-width = <4>;
+
+			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/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
index d8a827b..ac870fb 100644
--- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
+++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
@@ -17,17 +17,16 @@
  * CHANGES TO vexpress-v2m.dtsi!
  */
 
-/ {
-	aliases {
-		arm,v2m_timer = &v2m_timer01;
-	};
-
 	motherboard {
-		compatible = "simple-bus";
+		model = "V2M-P1";
+		arm,hbi = <0x190>;
+		arm,vexpress,site = <0>;
 		arm,v2m-memory-map = "rs1";
+		compatible = "arm,vexpress,v2m-p1", "simple-bus";
 		#address-cells = <2>; /* SMB chipselect number and offset */
 		#size-cells = <1>;
 		#interrupt-cells = <1>;
+		ranges;
 
 		flash@0,00000000 {
 			compatible = "arm,vexpress-flash", "cfi-flash";
@@ -72,14 +71,20 @@
 			#size-cells = <1>;
 			ranges = <0 3 0 0x200000>;
 
-			sysreg@010000 {
+			v2m_sysreg: sysreg@010000 {
 				compatible = "arm,vexpress-sysreg";
 				reg = <0x010000 0x1000>;
+				gpio-controller;
+				#gpio-cells = <2>;
 			};
 
-			sysctl@020000 {
+			v2m_sysctl: sysctl@020000 {
 				compatible = "arm,sp810", "arm,primecell";
 				reg = <0x020000 0x1000>;
+				clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>;
+				clock-names = "refclk", "timclk", "apb_pclk";
+				#clock-cells = <1>;
+				clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
 			};
 
 			/* PCI-E I2C bus */
@@ -100,66 +105,92 @@
 				compatible = "arm,pl041", "arm,primecell";
 				reg = <0x040000 0x1000>;
 				interrupts = <11>;
+				clocks = <&smbclk>;
+				clock-names = "apb_pclk";
 			};
 
 			mmci@050000 {
 				compatible = "arm,pl180", "arm,primecell";
 				reg = <0x050000 0x1000>;
 				interrupts = <9 10>;
+				cd-gpios = <&v2m_sysreg 0 0>;
+				wp-gpios = <&v2m_sysreg 1 0>;
+				max-frequency = <12000000>;
+				vmmc-supply = <&v2m_fixed_3v3>;
+				clocks = <&v2m_clk24mhz>, <&smbclk>;
+				clock-names = "mclk", "apb_pclk";
 			};
 
 			kmi@060000 {
 				compatible = "arm,pl050", "arm,primecell";
 				reg = <0x060000 0x1000>;
 				interrupts = <12>;
+				clocks = <&v2m_clk24mhz>, <&smbclk>;
+				clock-names = "KMIREFCLK", "apb_pclk";
 			};
 
 			kmi@070000 {
 				compatible = "arm,pl050", "arm,primecell";
 				reg = <0x070000 0x1000>;
 				interrupts = <13>;
+				clocks = <&v2m_clk24mhz>, <&smbclk>;
+				clock-names = "KMIREFCLK", "apb_pclk";
 			};
 
 			v2m_serial0: uart@090000 {
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0x090000 0x1000>;
 				interrupts = <5>;
+				clocks = <&v2m_oscclk2>, <&smbclk>;
+				clock-names = "uartclk", "apb_pclk";
 			};
 
 			v2m_serial1: uart@0a0000 {
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0x0a0000 0x1000>;
 				interrupts = <6>;
+				clocks = <&v2m_oscclk2>, <&smbclk>;
+				clock-names = "uartclk", "apb_pclk";
 			};
 
 			v2m_serial2: uart@0b0000 {
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0x0b0000 0x1000>;
 				interrupts = <7>;
+				clocks = <&v2m_oscclk2>, <&smbclk>;
+				clock-names = "uartclk", "apb_pclk";
 			};
 
 			v2m_serial3: uart@0c0000 {
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0x0c0000 0x1000>;
 				interrupts = <8>;
+				clocks = <&v2m_oscclk2>, <&smbclk>;
+				clock-names = "uartclk", "apb_pclk";
 			};
 
 			wdt@0f0000 {
 				compatible = "arm,sp805", "arm,primecell";
 				reg = <0x0f0000 0x1000>;
 				interrupts = <0>;
+				clocks = <&v2m_refclk32khz>, <&smbclk>;
+				clock-names = "wdogclk", "apb_pclk";
 			};
 
 			v2m_timer01: timer@110000 {
 				compatible = "arm,sp804", "arm,primecell";
 				reg = <0x110000 0x1000>;
 				interrupts = <2>;
+				clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&smbclk>;
+				clock-names = "timclken1", "timclken2", "apb_pclk";
 			};
 
 			v2m_timer23: timer@120000 {
 				compatible = "arm,sp804", "arm,primecell";
 				reg = <0x120000 0x1000>;
 				interrupts = <3>;
+				clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&smbclk>;
+				clock-names = "timclken1", "timclken2", "apb_pclk";
 			};
 
 			/* DVI I2C bus */
@@ -185,6 +216,8 @@
 				compatible = "arm,pl031", "arm,primecell";
 				reg = <0x170000 0x1000>;
 				interrupts = <4>;
+				clocks = <&smbclk>;
+				clock-names = "apb_pclk";
 			};
 
 			compact-flash@1a0000 {
@@ -198,6 +231,8 @@
 				compatible = "arm,pl111", "arm,primecell";
 				reg = <0x1f0000 0x1000>;
 				interrupts = <14>;
+				clocks = <&v2m_oscclk1>, <&smbclk>;
+				clock-names = "clcdclk", "apb_pclk";
 			};
 		};
 
@@ -208,5 +243,98 @@
 			regulator-max-microvolt = <3300000>;
 			regulator-always-on;
 		};
+
+		v2m_clk24mhz: clk24mhz {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <24000000>;
+			clock-output-names = "v2m:clk24mhz";
+		};
+
+		v2m_refclk1mhz: refclk1mhz {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <1000000>;
+			clock-output-names = "v2m:refclk1mhz";
+		};
+
+		v2m_refclk32khz: refclk32khz {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+			clock-output-names = "v2m:refclk32khz";
+		};
+
+		mcc {
+			compatible = "arm,vexpress,config-bus";
+			arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+			osc@0 {
+				/* MCC static memory clock */
+				compatible = "arm,vexpress-osc";
+				arm,vexpress-sysreg,func = <1 0>;
+				freq-range = <25000000 60000000>;
+				#clock-cells = <0>;
+				clock-output-names = "v2m:oscclk0";
+			};
+
+			v2m_oscclk1: osc@1 {
+				/* CLCD clock */
+				compatible = "arm,vexpress-osc";
+				arm,vexpress-sysreg,func = <1 1>;
+				freq-range = <23750000 63500000>;
+				#clock-cells = <0>;
+				clock-output-names = "v2m:oscclk1";
+			};
+
+			v2m_oscclk2: osc@2 {
+				/* IO FPGA peripheral clock */
+				compatible = "arm,vexpress-osc";
+				arm,vexpress-sysreg,func = <1 2>;
+				freq-range = <24000000 24000000>;
+				#clock-cells = <0>;
+				clock-output-names = "v2m:oscclk2";
+			};
+
+			volt@0 {
+				/* Logic level voltage */
+				compatible = "arm,vexpress-volt";
+				arm,vexpress-sysreg,func = <2 0>;
+				regulator-name = "VIO";
+				regulator-always-on;
+				label = "VIO";
+			};
+
+			temp@0 {
+				/* MCC internal operating temperature */
+				compatible = "arm,vexpress-temp";
+				arm,vexpress-sysreg,func = <4 0>;
+				label = "MCC";
+			};
+
+			reset@0 {
+				compatible = "arm,vexpress-reset";
+				arm,vexpress-sysreg,func = <5 0>;
+			};
+
+			muxfpga@0 {
+				compatible = "arm,vexpress-muxfpga";
+				arm,vexpress-sysreg,func = <7 0>;
+			};
+
+			shutdown@0 {
+				compatible = "arm,vexpress-shutdown";
+				arm,vexpress-sysreg,func = <8 0>;
+			};
+
+			reboot@0 {
+				compatible = "arm,vexpress-reboot";
+				arm,vexpress-sysreg,func = <9 0>;
+			};
+
+			dvimode@0 {
+				compatible = "arm,vexpress-dvimode";
+				arm,vexpress-sysreg,func = <11 0>;
+			};
+		};
 	};
-};
diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/vexpress-v2m.dtsi
index dba53fd..f142036 100644
--- a/arch/arm/boot/dts/vexpress-v2m.dtsi
+++ b/arch/arm/boot/dts/vexpress-v2m.dtsi
@@ -17,16 +17,15 @@
  * CHANGES TO vexpress-v2m-rs1.dtsi!
  */
 
-/ {
-	aliases {
-		arm,v2m_timer = &v2m_timer01;
-	};
-
 	motherboard {
-		compatible = "simple-bus";
+		model = "V2M-P1";
+		arm,hbi = <0x190>;
+		arm,vexpress,site = <0>;
+		compatible = "arm,vexpress,v2m-p1", "simple-bus";
 		#address-cells = <2>; /* SMB chipselect number and offset */
 		#size-cells = <1>;
 		#interrupt-cells = <1>;
+		ranges;
 
 		flash@0,00000000 {
 			compatible = "arm,vexpress-flash", "cfi-flash";
@@ -71,14 +70,20 @@
 			#size-cells = <1>;
 			ranges = <0 7 0 0x20000>;
 
-			sysreg@00000 {
+			v2m_sysreg: sysreg@00000 {
 				compatible = "arm,vexpress-sysreg";
 				reg = <0x00000 0x1000>;
+				gpio-controller;
+				#gpio-cells = <2>;
 			};
 
-			sysctl@01000 {
+			v2m_sysctl: sysctl@01000 {
 				compatible = "arm,sp810", "arm,primecell";
 				reg = <0x01000 0x1000>;
+				clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>;
+				clock-names = "refclk", "timclk", "apb_pclk";
+				#clock-cells = <1>;
+				clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
 			};
 
 			/* PCI-E I2C bus */
@@ -99,66 +104,92 @@
 				compatible = "arm,pl041", "arm,primecell";
 				reg = <0x04000 0x1000>;
 				interrupts = <11>;
+				clocks = <&smbclk>;
+				clock-names = "apb_pclk";
 			};
 
 			mmci@05000 {
 				compatible = "arm,pl180", "arm,primecell";
 				reg = <0x05000 0x1000>;
 				interrupts = <9 10>;
+				cd-gpios = <&v2m_sysreg 0 0>;
+				wp-gpios = <&v2m_sysreg 1 0>;
+				max-frequency = <12000000>;
+				vmmc-supply = <&v2m_fixed_3v3>;
+				clocks = <&v2m_clk24mhz>, <&smbclk>;
+				clock-names = "mclk", "apb_pclk";
 			};
 
 			kmi@06000 {
 				compatible = "arm,pl050", "arm,primecell";
 				reg = <0x06000 0x1000>;
 				interrupts = <12>;
+				clocks = <&v2m_clk24mhz>, <&smbclk>;
+				clock-names = "KMIREFCLK", "apb_pclk";
 			};
 
 			kmi@07000 {
 				compatible = "arm,pl050", "arm,primecell";
 				reg = <0x07000 0x1000>;
 				interrupts = <13>;
+				clocks = <&v2m_clk24mhz>, <&smbclk>;
+				clock-names = "KMIREFCLK", "apb_pclk";
 			};
 
 			v2m_serial0: uart@09000 {
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0x09000 0x1000>;
 				interrupts = <5>;
+				clocks = <&v2m_oscclk2>, <&smbclk>;
+				clock-names = "uartclk", "apb_pclk";
 			};
 
 			v2m_serial1: uart@0a000 {
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0x0a000 0x1000>;
 				interrupts = <6>;
+				clocks = <&v2m_oscclk2>, <&smbclk>;
+				clock-names = "uartclk", "apb_pclk";
 			};
 
 			v2m_serial2: uart@0b000 {
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0x0b000 0x1000>;
 				interrupts = <7>;
+				clocks = <&v2m_oscclk2>, <&smbclk>;
+				clock-names = "uartclk", "apb_pclk";
 			};
 
 			v2m_serial3: uart@0c000 {
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0x0c000 0x1000>;
 				interrupts = <8>;
+				clocks = <&v2m_oscclk2>, <&smbclk>;
+				clock-names = "uartclk", "apb_pclk";
 			};
 
 			wdt@0f000 {
 				compatible = "arm,sp805", "arm,primecell";
 				reg = <0x0f000 0x1000>;
 				interrupts = <0>;
+				clocks = <&v2m_refclk32khz>, <&smbclk>;
+				clock-names = "wdogclk", "apb_pclk";
 			};
 
 			v2m_timer01: timer@11000 {
 				compatible = "arm,sp804", "arm,primecell";
 				reg = <0x11000 0x1000>;
 				interrupts = <2>;
+				clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&smbclk>;
+				clock-names = "timclken1", "timclken2", "apb_pclk";
 			};
 
 			v2m_timer23: timer@12000 {
 				compatible = "arm,sp804", "arm,primecell";
 				reg = <0x12000 0x1000>;
 				interrupts = <3>;
+				clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&smbclk>;
+				clock-names = "timclken1", "timclken2", "apb_pclk";
 			};
 
 			/* DVI I2C bus */
@@ -184,6 +215,8 @@
 				compatible = "arm,pl031", "arm,primecell";
 				reg = <0x17000 0x1000>;
 				interrupts = <4>;
+				clocks = <&smbclk>;
+				clock-names = "apb_pclk";
 			};
 
 			compact-flash@1a000 {
@@ -197,6 +230,8 @@
 				compatible = "arm,pl111", "arm,primecell";
 				reg = <0x1f000 0x1000>;
 				interrupts = <14>;
+				clocks = <&v2m_oscclk1>, <&smbclk>;
+				clock-names = "clcdclk", "apb_pclk";
 			};
 		};
 
@@ -207,5 +242,98 @@
 			regulator-max-microvolt = <3300000>;
 			regulator-always-on;
 		};
+
+		v2m_clk24mhz: clk24mhz {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <24000000>;
+			clock-output-names = "v2m:clk24mhz";
+		};
+
+		v2m_refclk1mhz: refclk1mhz {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <1000000>;
+			clock-output-names = "v2m:refclk1mhz";
+		};
+
+		v2m_refclk32khz: refclk32khz {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+			clock-output-names = "v2m:refclk32khz";
+		};
+
+		mcc {
+			compatible = "arm,vexpress,config-bus";
+			arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+			osc@0 {
+				/* MCC static memory clock */
+				compatible = "arm,vexpress-osc";
+				arm,vexpress-sysreg,func = <1 0>;
+				freq-range = <25000000 60000000>;
+				#clock-cells = <0>;
+				clock-output-names = "v2m:oscclk0";
+			};
+
+			v2m_oscclk1: osc@1 {
+				/* CLCD clock */
+				compatible = "arm,vexpress-osc";
+				arm,vexpress-sysreg,func = <1 1>;
+				freq-range = <23750000 63500000>;
+				#clock-cells = <0>;
+				clock-output-names = "v2m:oscclk1";
+			};
+
+			v2m_oscclk2: osc@2 {
+				/* IO FPGA peripheral clock */
+				compatible = "arm,vexpress-osc";
+				arm,vexpress-sysreg,func = <1 2>;
+				freq-range = <24000000 24000000>;
+				#clock-cells = <0>;
+				clock-output-names = "v2m:oscclk2";
+			};
+
+			volt@0 {
+				/* Logic level voltage */
+				compatible = "arm,vexpress-volt";
+				arm,vexpress-sysreg,func = <2 0>;
+				regulator-name = "VIO";
+				regulator-always-on;
+				label = "VIO";
+			};
+
+			temp@0 {
+				/* MCC internal operating temperature */
+				compatible = "arm,vexpress-temp";
+				arm,vexpress-sysreg,func = <4 0>;
+				label = "MCC";
+			};
+
+			reset@0 {
+				compatible = "arm,vexpress-reset";
+				arm,vexpress-sysreg,func = <5 0>;
+			};
+
+			muxfpga@0 {
+				compatible = "arm,vexpress-muxfpga";
+				arm,vexpress-sysreg,func = <7 0>;
+			};
+
+			shutdown@0 {
+				compatible = "arm,vexpress-shutdown";
+				arm,vexpress-sysreg,func = <8 0>;
+			};
+
+			reboot@0 {
+				compatible = "arm,vexpress-reboot";
+				arm,vexpress-sysreg,func = <9 0>;
+			};
+
+			dvimode@0 {
+				compatible = "arm,vexpress-dvimode";
+				arm,vexpress-sysreg,func = <11 0>;
+			};
+		};
 	};
-};
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
index d12b34c..a3d37ec 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
@@ -12,6 +12,7 @@
 / {
 	model = "V2P-CA15";
 	arm,hbi = <0x237>;
+	arm,vexpress,site = <0xf>;
 	compatible = "arm,vexpress,v2p-ca15,tc1", "arm,vexpress,v2p-ca15", "arm,vexpress";
 	interrupt-parent = <&gic>;
 	#address-cells = <2>;
@@ -54,17 +55,24 @@
 		compatible = "arm,hdlcd";
 		reg = <0 0x2b000000 0 0x1000>;
 		interrupts = <0 85 4>;
+		clocks = <&oscclk5>;
+		clock-names = "pxlclk";
 	};
 
 	memory-controller@2b0a0000 {
 		compatible = "arm,pl341", "arm,primecell";
 		reg = <0 0x2b0a0000 0 0x1000>;
+		clocks = <&oscclk7>;
+		clock-names = "apb_pclk";
 	};
 
 	wdt@2b060000 {
 		compatible = "arm,sp805", "arm,primecell";
+		status = "disabled";
 		reg = <0 0x2b060000 0 0x1000>;
 		interrupts = <98>;
+		clocks = <&oscclk7>;
+		clock-names = "apb_pclk";
 	};
 
 	gic: interrupt-controller@2c001000 {
@@ -84,6 +92,8 @@
 		reg = <0 0x7ffd0000 0 0x1000>;
 		interrupts = <0 86 4>,
 			     <0 87 4>;
+		clocks = <&oscclk7>;
+		clock-names = "apb_pclk";
 	};
 
 	dma@7ffb0000 {
@@ -94,6 +104,8 @@
 			     <0 89 4>,
 			     <0 90 4>,
 			     <0 91 4>;
+		clocks = <&oscclk7>;
+		clock-names = "apb_pclk";
 	};
 
 	timer {
@@ -110,7 +122,109 @@
 			     <0 69 4>;
 	};
 
-	motherboard {
+	dcc {
+		compatible = "arm,vexpress,config-bus";
+		arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+		osc@0 {
+			/* CPU PLL reference clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 0>;
+			freq-range = <50000000 60000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk0";
+		};
+
+		osc@4 {
+			/* Multiplexed AXI master clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 4>;
+			freq-range = <20000000 40000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk4";
+		};
+
+		oscclk5: osc@5 {
+			/* HDLCD PLL reference clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 5>;
+			freq-range = <23750000 165000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk5";
+		};
+
+		smbclk: osc@6 {
+			/* SMB clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 6>;
+			freq-range = <20000000 50000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk6";
+		};
+
+		oscclk7: osc@7 {
+			/* SYS PLL reference clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 7>;
+			freq-range = <20000000 60000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk7";
+		};
+
+		osc@8 {
+			/* DDR2 PLL reference clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 8>;
+			freq-range = <40000000 40000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk8";
+		};
+
+		volt@0 {
+			/* CPU core voltage */
+			compatible = "arm,vexpress-volt";
+			arm,vexpress-sysreg,func = <2 0>;
+			regulator-name = "Cores";
+			regulator-min-microvolt = <800000>;
+			regulator-max-microvolt = <1050000>;
+			regulator-always-on;
+			label = "Cores";
+		};
+
+		amp@0 {
+			/* Total current for the two cores */
+			compatible = "arm,vexpress-amp";
+			arm,vexpress-sysreg,func = <3 0>;
+			label = "Cores";
+		};
+
+		temp@0 {
+			/* DCC internal temperature */
+			compatible = "arm,vexpress-temp";
+			arm,vexpress-sysreg,func = <4 0>;
+			label = "DCC";
+		};
+
+		power@0 {
+			/* Total power */
+			compatible = "arm,vexpress-power";
+			arm,vexpress-sysreg,func = <12 0>;
+			label = "Cores";
+		};
+
+		energy@0 {
+			/* Total energy */
+			compatible = "arm,vexpress-energy";
+			arm,vexpress-sysreg,func = <13 0>;
+			label = "Cores";
+		};
+	};
+
+	smb {
+		compatible = "simple-bus";
+
+		#address-cells = <2>;
+		#size-cells = <1>;
 		ranges = <0 0 0 0x08000000 0x04000000>,
 			 <1 0 0 0x14000000 0x04000000>,
 			 <2 0 0 0x18000000 0x04000000>,
@@ -118,6 +232,7 @@
 			 <4 0 0 0x0c000000 0x04000000>,
 			 <5 0 0 0x10000000 0x04000000>;
 
+		#interrupt-cells = <1>;
 		interrupt-map-mask = <0 0 63>;
 		interrupt-map = <0 0  0 &gic 0  0 4>,
 				<0 0  1 &gic 0  1 4>,
@@ -162,7 +277,7 @@
 				<0 0 40 &gic 0 40 4>,
 				<0 0 41 &gic 0 41 4>,
 				<0 0 42 &gic 0 42 4>;
+
+		/include/ "vexpress-v2m-rs1.dtsi"
 	};
 };
-
-/include/ "vexpress-v2m-rs1.dtsi"
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
index 4890a81..1fc405a 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
@@ -12,6 +12,7 @@
 / {
 	model = "V2P-CA15_CA7";
 	arm,hbi = <0x249>;
+	arm,vexpress,site = <0xf>;
 	compatible = "arm,vexpress,v2p-ca15_a7", "arm,vexpress";
 	interrupt-parent = <&gic>;
 	#address-cells = <2>;
@@ -74,17 +75,23 @@
 		compatible = "arm,sp805", "arm,primecell";
 		reg = <0 0x2a490000 0 0x1000>;
 		interrupts = <98>;
+		clocks = <&oscclk6a>, <&oscclk6a>;
+		clock-names = "wdogclk", "apb_pclk";
 	};
 
 	hdlcd@2b000000 {
 		compatible = "arm,hdlcd";
 		reg = <0 0x2b000000 0 0x1000>;
 		interrupts = <0 85 4>;
+		clocks = <&oscclk5>;
+		clock-names = "pxlclk";
 	};
 
 	memory-controller@2b0a0000 {
 		compatible = "arm,pl341", "arm,primecell";
 		reg = <0 0x2b0a0000 0 0x1000>;
+		clocks = <&oscclk6a>;
+		clock-names = "apb_pclk";
 	};
 
 	gic: interrupt-controller@2c001000 {
@@ -104,6 +111,8 @@
 		reg = <0 0x7ffd0000 0 0x1000>;
 		interrupts = <0 86 4>,
 			     <0 87 4>;
+		clocks = <&oscclk6a>;
+		clock-names = "apb_pclk";
 	};
 
 	dma@7ff00000 {
@@ -114,6 +123,8 @@
 			     <0 89 4>,
 			     <0 90 4>,
 			     <0 91 4>;
+		clocks = <&oscclk6a>;
+		clock-names = "apb_pclk";
 	};
 
 	timer {
@@ -130,7 +141,175 @@
 			     <0 69 4>;
 	};
 
-	motherboard {
+	oscclk6a: oscclk6a {
+		/* Reference 24MHz clock */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+		clock-output-names = "oscclk6a";
+	};
+
+	dcc {
+		compatible = "arm,vexpress,config-bus";
+		arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+		osc@0 {
+			/* A15 PLL 0 reference clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 0>;
+			freq-range = <17000000 50000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk0";
+		};
+
+		osc@1 {
+			/* A15 PLL 1 reference clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 1>;
+			freq-range = <17000000 50000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk1";
+		};
+
+		osc@2 {
+			/* A7 PLL 0 reference clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 2>;
+			freq-range = <17000000 50000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk2";
+		};
+
+		osc@3 {
+			/* A7 PLL 1 reference clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 3>;
+			freq-range = <17000000 50000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk3";
+		};
+
+		osc@4 {
+			/* External AXI master clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 4>;
+			freq-range = <20000000 40000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk4";
+		};
+
+		oscclk5: osc@5 {
+			/* HDLCD PLL reference clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 5>;
+			freq-range = <23750000 165000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk5";
+		};
+
+		smbclk: osc@6 {
+			/* Static memory controller clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 6>;
+			freq-range = <20000000 40000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk6";
+		};
+
+		osc@7 {
+			/* SYS PLL reference clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 7>;
+			freq-range = <17000000 50000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk7";
+		};
+
+		osc@8 {
+			/* DDR2 PLL reference clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 8>;
+			freq-range = <20000000 50000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk8";
+		};
+
+		volt@0 {
+			/* A15 CPU core voltage */
+			compatible = "arm,vexpress-volt";
+			arm,vexpress-sysreg,func = <2 0>;
+			regulator-name = "A15 Vcore";
+			regulator-min-microvolt = <800000>;
+			regulator-max-microvolt = <1050000>;
+			regulator-always-on;
+			label = "A15 Vcore";
+		};
+
+		volt@1 {
+			/* A7 CPU core voltage */
+			compatible = "arm,vexpress-volt";
+			arm,vexpress-sysreg,func = <2 1>;
+			regulator-name = "A7 Vcore";
+			regulator-min-microvolt = <800000>;
+			regulator-max-microvolt = <1050000>;
+			regulator-always-on;
+			label = "A7 Vcore";
+		};
+
+		amp@0 {
+			/* Total current for the two A15 cores */
+			compatible = "arm,vexpress-amp";
+			arm,vexpress-sysreg,func = <3 0>;
+			label = "A15 Icore";
+		};
+
+		amp@1 {
+			/* Total current for the three A7 cores */
+			compatible = "arm,vexpress-amp";
+			arm,vexpress-sysreg,func = <3 1>;
+			label = "A7 Icore";
+		};
+
+		temp@0 {
+			/* DCC internal temperature */
+			compatible = "arm,vexpress-temp";
+			arm,vexpress-sysreg,func = <4 0>;
+			label = "DCC";
+		};
+
+		power@0 {
+			/* Total power for the two A15 cores */
+			compatible = "arm,vexpress-power";
+			arm,vexpress-sysreg,func = <12 0>;
+			label = "A15 Pcore";
+		};
+		power@1 {
+			/* Total power for the three A7 cores */
+			compatible = "arm,vexpress-power";
+			arm,vexpress-sysreg,func = <12 1>;
+			label = "A7 Pcore";
+		};
+
+		energy@0 {
+			/* Total energy for the two A15 cores */
+			compatible = "arm,vexpress-energy";
+			arm,vexpress-sysreg,func = <13 0>;
+			label = "A15 Jcore";
+		};
+
+		energy@2 {
+			/* Total energy for the three A7 cores */
+			compatible = "arm,vexpress-energy";
+			arm,vexpress-sysreg,func = <13 2>;
+			label = "A7 Jcore";
+		};
+	};
+
+	smb {
+		compatible = "simple-bus";
+
+		#address-cells = <2>;
+		#size-cells = <1>;
 		ranges = <0 0 0 0x08000000 0x04000000>,
 			 <1 0 0 0x14000000 0x04000000>,
 			 <2 0 0 0x18000000 0x04000000>,
@@ -138,6 +317,7 @@
 			 <4 0 0 0x0c000000 0x04000000>,
 			 <5 0 0 0x10000000 0x04000000>;
 
+		#interrupt-cells = <1>;
 		interrupt-map-mask = <0 0 63>;
 		interrupt-map = <0 0  0 &gic 0  0 4>,
 				<0 0  1 &gic 0  1 4>,
@@ -182,7 +362,7 @@
 				<0 0 40 &gic 0 40 4>,
 				<0 0 41 &gic 0 41 4>,
 				<0 0 42 &gic 0 42 4>;
+
+		/include/ "vexpress-v2m-rs1.dtsi"
 	};
 };
-
-/include/ "vexpress-v2m-rs1.dtsi"
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts
index 18917a0..6328cbc 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts
@@ -12,6 +12,7 @@
 / {
 	model = "V2P-CA5s";
 	arm,hbi = <0x225>;
+	arm,vexpress,site = <0xf>;
 	compatible = "arm,vexpress,v2p-ca5s", "arm,vexpress";
 	interrupt-parent = <&gic>;
 	#address-cells = <1>;
@@ -56,11 +57,15 @@
 		compatible = "arm,hdlcd";
 		reg = <0x2a110000 0x1000>;
 		interrupts = <0 85 4>;
+		clocks = <&oscclk3>;
+		clock-names = "pxlclk";
 	};
 
 	memory-controller@2a150000 {
 		compatible = "arm,pl341", "arm,primecell";
 		reg = <0x2a150000 0x1000>;
+		clocks = <&oscclk1>;
+		clock-names = "apb_pclk";
 	};
 
 	memory-controller@2a190000 {
@@ -68,6 +73,8 @@
 		reg = <0x2a190000 0x1000>;
 		interrupts = <0 86 4>,
 			     <0 87 4>;
+		clocks = <&oscclk1>;
+		clock-names = "apb_pclk";
 	};
 
 	scu@2c000000 {
@@ -109,7 +116,77 @@
 			     <0 69 4>;
 	};
 
-	motherboard {
+	dcc {
+		compatible = "arm,vexpress,config-bus";
+		arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+		osc@0 {
+			/* CPU and internal AXI reference clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 0>;
+			freq-range = <50000000 100000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk0";
+		};
+
+		oscclk1: osc@1 {
+			/* Multiplexed AXI master clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 1>;
+			freq-range = <5000000 50000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk1";
+		};
+
+		osc@2 {
+			/* DDR2 */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 2>;
+			freq-range = <80000000 120000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk2";
+		};
+
+		oscclk3: osc@3 {
+			/* HDLCD */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 3>;
+			freq-range = <23750000 165000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk3";
+		};
+
+		osc@4 {
+			/* Test chip gate configuration */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 4>;
+			freq-range = <80000000 80000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk4";
+		};
+
+		smbclk: osc@5 {
+			/* SMB clock */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 5>;
+			freq-range = <25000000 60000000>;
+			#clock-cells = <0>;
+			clock-output-names = "oscclk5";
+		};
+
+		temp@0 {
+			/* DCC internal operating temperature */
+			compatible = "arm,vexpress-temp";
+			arm,vexpress-sysreg,func = <4 0>;
+			label = "DCC";
+		};
+	};
+
+	smb {
+		compatible = "simple-bus";
+
+		#address-cells = <2>;
+		#size-cells = <1>;
 		ranges = <0 0 0x08000000 0x04000000>,
 			 <1 0 0x14000000 0x04000000>,
 			 <2 0 0x18000000 0x04000000>,
@@ -117,6 +194,7 @@
 			 <4 0 0x0c000000 0x04000000>,
 			 <5 0 0x10000000 0x04000000>;
 
+		#interrupt-cells = <1>;
 		interrupt-map-mask = <0 0 63>;
 		interrupt-map = <0 0  0 &gic 0  0 4>,
 				<0 0  1 &gic 0  1 4>,
@@ -161,7 +239,7 @@
 				<0 0 40 &gic 0 40 4>,
 				<0 0 41 &gic 0 41 4>,
 				<0 0 42 &gic 0 42 4>;
+
+		/include/ "vexpress-v2m-rs1.dtsi"
 	};
 };
-
-/include/ "vexpress-v2m-rs1.dtsi"
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca9.dts b/arch/arm/boot/dts/vexpress-v2p-ca9.dts
index 3f0c736..1420bb1 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca9.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca9.dts
@@ -12,6 +12,7 @@
 / {
 	model = "V2P-CA9";
 	arm,hbi = <0x191>;
+	arm,vexpress,site = <0xf>;
 	compatible = "arm,vexpress,v2p-ca9", "arm,vexpress";
 	interrupt-parent = <&gic>;
 	#address-cells = <1>;
@@ -70,11 +71,15 @@
 		compatible = "arm,pl111", "arm,primecell";
 		reg = <0x10020000 0x1000>;
 		interrupts = <0 44 4>;
+		clocks = <&oscclk1>, <&oscclk2>;
+		clock-names = "clcdclk", "apb_pclk";
 	};
 
 	memory-controller@100e0000 {
 		compatible = "arm,pl341", "arm,primecell";
 		reg = <0x100e0000 0x1000>;
+		clocks = <&oscclk2>;
+		clock-names = "apb_pclk";
 	};
 
 	memory-controller@100e1000 {
@@ -82,6 +87,8 @@
 		reg = <0x100e1000 0x1000>;
 		interrupts = <0 45 4>,
 			     <0 46 4>;
+		clocks = <&oscclk2>;
+		clock-names = "apb_pclk";
 	};
 
 	timer@100e4000 {
@@ -89,12 +96,16 @@
 		reg = <0x100e4000 0x1000>;
 		interrupts = <0 48 4>,
 			     <0 49 4>;
+		clocks = <&oscclk2>, <&oscclk2>;
+		clock-names = "timclk", "apb_pclk";
 	};
 
 	watchdog@100e5000 {
 		compatible = "arm,sp805", "arm,primecell";
 		reg = <0x100e5000 0x1000>;
 		interrupts = <0 51 4>;
+		clocks = <&oscclk2>, <&oscclk2>;
+		clock-names = "wdogclk", "apb_pclk";
 	};
 
 	scu@1e000000 {
@@ -140,13 +151,132 @@
 			     <0 63 4>;
 	};
 
-	motherboard {
+	dcc {
+		compatible = "arm,vexpress,config-bus";
+		arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+		osc@0 {
+			/* ACLK clock to the AXI master port on the test chip */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 0>;
+			freq-range = <30000000 50000000>;
+			#clock-cells = <0>;
+			clock-output-names = "extsaxiclk";
+		};
+
+		oscclk1: osc@1 {
+			/* Reference clock for the CLCD */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 1>;
+			freq-range = <10000000 80000000>;
+			#clock-cells = <0>;
+			clock-output-names = "clcdclk";
+		};
+
+		smbclk: oscclk2: osc@2 {
+			/* Reference clock for the test chip internal PLLs */
+			compatible = "arm,vexpress-osc";
+			arm,vexpress-sysreg,func = <1 2>;
+			freq-range = <33000000 100000000>;
+			#clock-cells = <0>;
+			clock-output-names = "tcrefclk";
+		};
+
+		volt@0 {
+			/* Test Chip internal logic voltage */
+			compatible = "arm,vexpress-volt";
+			arm,vexpress-sysreg,func = <2 0>;
+			regulator-name = "VD10";
+			regulator-always-on;
+			label = "VD10";
+		};
+
+		volt@1 {
+			/* PL310, L2 cache, RAM cell supply (not PL310 logic) */
+			compatible = "arm,vexpress-volt";
+			arm,vexpress-sysreg,func = <2 1>;
+			regulator-name = "VD10_S2";
+			regulator-always-on;
+			label = "VD10_S2";
+		};
+
+		volt@2 {
+			/* Cortex-A9 system supply, Cores, MPEs, SCU and PL310 logic */
+			compatible = "arm,vexpress-volt";
+			arm,vexpress-sysreg,func = <2 2>;
+			regulator-name = "VD10_S3";
+			regulator-always-on;
+			label = "VD10_S3";
+		};
+
+		volt@3 {
+			/* DDR2 SDRAM and Test Chip DDR2 I/O supply */
+			compatible = "arm,vexpress-volt";
+			arm,vexpress-sysreg,func = <2 3>;
+			regulator-name = "VCC1V8";
+			regulator-always-on;
+			label = "VCC1V8";
+		};
+
+		volt@4 {
+			/* DDR2 SDRAM VTT termination voltage */
+			compatible = "arm,vexpress-volt";
+			arm,vexpress-sysreg,func = <2 4>;
+			regulator-name = "DDR2VTT";
+			regulator-always-on;
+			label = "DDR2VTT";
+		};
+
+		volt@5 {
+			/* Local board supply for miscellaneous logic external to the Test Chip */
+			arm,vexpress-sysreg,func = <2 5>;
+			compatible = "arm,vexpress-volt";
+			regulator-name = "VCC3V3";
+			regulator-always-on;
+			label = "VCC3V3";
+		};
+
+		amp@0 {
+			/* PL310, L2 cache, RAM cell supply (not PL310 logic) */
+			compatible = "arm,vexpress-amp";
+			arm,vexpress-sysreg,func = <3 0>;
+			label = "VD10_S2";
+		};
+
+		amp@1 {
+			/* Cortex-A9 system supply, Cores, MPEs, SCU and PL310 logic */
+			compatible = "arm,vexpress-amp";
+			arm,vexpress-sysreg,func = <3 1>;
+			label = "VD10_S3";
+		};
+
+		power@0 {
+			/* PL310, L2 cache, RAM cell supply (not PL310 logic) */
+			compatible = "arm,vexpress-power";
+			arm,vexpress-sysreg,func = <12 0>;
+			label = "PVD10_S2";
+		};
+
+		power@1 {
+			/* Cortex-A9 system supply, Cores, MPEs, SCU and PL310 logic */
+			compatible = "arm,vexpress-power";
+			arm,vexpress-sysreg,func = <12 1>;
+			label = "PVD10_S3";
+		};
+	};
+
+	smb {
+		compatible = "simple-bus";
+
+		#address-cells = <2>;
+		#size-cells = <1>;
 		ranges = <0 0 0x40000000 0x04000000>,
 			 <1 0 0x44000000 0x04000000>,
 			 <2 0 0x48000000 0x04000000>,
 			 <3 0 0x4c000000 0x04000000>,
 			 <7 0 0x10000000 0x00020000>;
 
+		#interrupt-cells = <1>;
 		interrupt-map-mask = <0 0 63>;
 		interrupt-map = <0 0  0 &gic 0  0 4>,
 				<0 0  1 &gic 0  1 4>,
@@ -191,7 +321,7 @@
 				<0 0 40 &gic 0 40 4>,
 				<0 0 41 &gic 0 41 4>,
 				<0 0 42 &gic 0 42 4>;
+
+		/include/ "vexpress-v2m.dtsi"
 	};
 };
-
-/include/ "vexpress-v2m.dtsi"
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
new file mode 100644
index 0000000..5914b56
--- /dev/null
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -0,0 +1,166 @@
+/*
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "xlnx,zynq-7000";
+
+	amba {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		interrupt-parent = <&intc>;
+		ranges;
+
+		intc: interrupt-controller@f8f01000 {
+			compatible = "arm,cortex-a9-gic";
+			#interrupt-cells = <3>;
+			#address-cells = <1>;
+			interrupt-controller;
+			reg = <0xF8F01000 0x1000>,
+			      <0xF8F00100 0x100>;
+		};
+
+		L2: cache-controller {
+			compatible = "arm,pl310-cache";
+			reg = <0xF8F02000 0x1000>;
+			arm,data-latency = <2 3 2>;
+			arm,tag-latency = <2 3 2>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		uart0: uart@e0000000 {
+			compatible = "xlnx,xuartps";
+			reg = <0xE0000000 0x1000>;
+			interrupts = <0 27 4>;
+			clocks = <&uart_clk 0>;
+		};
+
+		uart1: uart@e0001000 {
+			compatible = "xlnx,xuartps";
+			reg = <0xE0001000 0x1000>;
+			interrupts = <0 50 4>;
+			clocks = <&uart_clk 1>;
+		};
+
+		slcr: slcr@f8000000 {
+			compatible = "xlnx,zynq-slcr";
+			reg = <0xF8000000 0x1000>;
+
+			clocks {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				ps_clk: ps_clk {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+					/* clock-frequency set in board-specific file */
+					clock-output-names = "ps_clk";
+				};
+				armpll: armpll {
+					#clock-cells = <0>;
+					compatible = "xlnx,zynq-pll";
+					clocks = <&ps_clk>;
+					reg = <0x100 0x110>;
+					clock-output-names = "armpll";
+				};
+				ddrpll: ddrpll {
+					#clock-cells = <0>;
+					compatible = "xlnx,zynq-pll";
+					clocks = <&ps_clk>;
+					reg = <0x104 0x114>;
+					clock-output-names = "ddrpll";
+				};
+				iopll: iopll {
+					#clock-cells = <0>;
+					compatible = "xlnx,zynq-pll";
+					clocks = <&ps_clk>;
+					reg = <0x108 0x118>;
+					clock-output-names = "iopll";
+				};
+				uart_clk: uart_clk {
+					#clock-cells = <1>;
+					compatible = "xlnx,zynq-periph-clock";
+					clocks = <&iopll &armpll &ddrpll>;
+					reg = <0x154>;
+					clock-output-names = "uart0_ref_clk",
+							     "uart1_ref_clk";
+				};
+				cpu_clk: cpu_clk {
+					#clock-cells = <1>;
+					compatible = "xlnx,zynq-cpu-clock";
+					clocks = <&iopll &armpll &ddrpll>;
+					reg = <0x120 0x1C4>;
+					clock-output-names = "cpu_6x4x",
+							     "cpu_3x2x",
+							     "cpu_2x",
+							     "cpu_1x";
+				};
+			};
+		};
+
+		ttc0: ttc0@f8001000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "xlnx,ttc";
+			reg = <0xF8001000 0x1000>;
+			clocks = <&cpu_clk 3>;
+			clock-names = "cpu_1x";
+			clock-ranges;
+
+			ttc0_0: ttc0.0 {
+				status = "disabled";
+				reg = <0>;
+				interrupts = <0 10 4>;
+			};
+			ttc0_1: ttc0.1 {
+				status = "disabled";
+				reg = <1>;
+				interrupts = <0 11 4>;
+			};
+			ttc0_2: ttc0.2 {
+				status = "disabled";
+				reg = <2>;
+				interrupts = <0 12 4>;
+			};
+		};
+
+		ttc1: ttc1@f8002000 {
+			#interrupt-parent = <&intc>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "xlnx,ttc";
+			reg = <0xF8002000 0x1000>;
+			clocks = <&cpu_clk 3>;
+			clock-names = "cpu_1x";
+			clock-ranges;
+
+			ttc1_0: ttc1.0 {
+				status = "disabled";
+				reg = <0>;
+				interrupts = <0 37 4>;
+			};
+			ttc1_1: ttc1.1 {
+				status = "disabled";
+				reg = <1>;
+				interrupts = <0 38 4>;
+			};
+			ttc1_2: ttc1.2 {
+				status = "disabled";
+				reg = <2>;
+				interrupts = <0 39 4>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/zynq-ep107.dts b/arch/arm/boot/dts/zynq-ep107.dts
deleted file mode 100644
index 37ca192..0000000
--- a/arch/arm/boot/dts/zynq-ep107.dts
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *  Copyright (C) 2011 Xilinx
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-/dts-v1/;
-/ {
-	model = "Xilinx Zynq EP107";
-	compatible = "xlnx,zynq-ep107";
-	#address-cells = <1>;
-	#size-cells = <1>;
-	interrupt-parent = <&intc>;
-
-	memory {
-		device_type = "memory";
-		reg = <0x0 0x10000000>;
-	};
-
-	chosen {
-		bootargs = "console=ttyPS0,9600 root=/dev/ram rw initrd=0x800000,8M earlyprintk";
-		linux,stdout-path = &uart0;
-	};
-
-	amba {
-		compatible = "simple-bus";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-
-		intc: interrupt-controller@f8f01000 {
-			interrupt-controller;
-			compatible = "arm,gic";
-			reg = <0xF8F01000 0x1000>;
-			#interrupt-cells = <2>;
-		};
-
-		uart0: uart@e0000000 {
-			compatible = "xlnx,xuartps";
-			reg = <0xE0000000 0x1000>;
-			interrupts = <59 0>;
-			clock = <50000000>;
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/zynq-zc702.dts b/arch/arm/boot/dts/zynq-zc702.dts
new file mode 100644
index 0000000..c772942
--- /dev/null
+++ b/arch/arm/boot/dts/zynq-zc702.dts
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (C) 2011 Xilinx
+ *  Copyright (C) 2012 National Instruments Corp.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+/dts-v1/;
+/include/ "zynq-7000.dtsi"
+
+/ {
+	model = "Zynq ZC702 Development Board";
+	compatible = "xlnx,zynq-zc702", "xlnx,zynq-7000";
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x40000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyPS1,115200 earlyprintk";
+	};
+
+};
+
+&ps_clk {
+	clock-frequency = <33333330>;
+};
+
+&ttc0_0 {
+	status = "ok";
+	compatible = "xlnx,ttc-counter-clocksource";
+};
+
+&ttc0_1 {
+	status = "ok";
+	compatible = "xlnx,ttc-counter-clockevent";
+};
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index aa52699..36ae03a 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -70,6 +70,14 @@ struct gic_chip_data {
 static DEFINE_RAW_SPINLOCK(irq_controller_lock);
 
 /*
+ * The GIC mapping of CPU interfaces does not necessarily match
+ * the logical CPU numbering.  Let's use a mapping as returned
+ * by the GIC itself.
+ */
+#define NR_GIC_CPU_IF 8
+static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly;
+
+/*
  * Supported arch specific GIC irq extension.
  * Default make them NULL.
  */
@@ -238,11 +246,11 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
 	u32 val, mask, bit;
 
-	if (cpu >= 8 || cpu >= nr_cpu_ids)
+	if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
 		return -EINVAL;
 
 	mask = 0xff << shift;
-	bit = 1 << (cpu_logical_map(cpu) + shift);
+	bit = gic_cpu_map[cpu] << shift;
 
 	raw_spin_lock(&irq_controller_lock);
 	val = readl_relaxed(reg) & ~mask;
@@ -349,11 +357,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
 	u32 cpumask;
 	unsigned int gic_irqs = gic->gic_irqs;
 	void __iomem *base = gic_data_dist_base(gic);
-	u32 cpu = cpu_logical_map(smp_processor_id());
-
-	cpumask = 1 << cpu;
-	cpumask |= cpumask << 8;
-	cpumask |= cpumask << 16;
 
 	writel_relaxed(0, base + GIC_DIST_CTRL);
 
@@ -366,6 +369,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
 	/*
 	 * Set all global interrupts to this CPU only.
 	 */
+	cpumask = readl_relaxed(base + GIC_DIST_TARGET + 0);
 	for (i = 32; i < gic_irqs; i += 4)
 		writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
 
@@ -389,9 +393,25 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
 {
 	void __iomem *dist_base = gic_data_dist_base(gic);
 	void __iomem *base = gic_data_cpu_base(gic);
+	unsigned int cpu_mask, cpu = smp_processor_id();
 	int i;
 
 	/*
+	 * Get what the GIC says our CPU mask is.
+	 */
+	BUG_ON(cpu >= NR_GIC_CPU_IF);
+	cpu_mask = readl_relaxed(dist_base + GIC_DIST_TARGET + 0);
+	gic_cpu_map[cpu] = cpu_mask;
+
+	/*
+	 * Clear our mask from the other map entries in case they're
+	 * still undefined.
+	 */
+	for (i = 0; i < NR_GIC_CPU_IF; i++)
+		if (i != cpu)
+			gic_cpu_map[i] &= ~cpu_mask;
+
+	/*
 	 * Deal with the banked PPI and SGI interrupts - disable all
 	 * PPI interrupts, ensure all SGI interrupts are enabled.
 	 */
@@ -646,7 +666,7 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 {
 	irq_hw_number_t hwirq_base;
 	struct gic_chip_data *gic;
-	int gic_irqs, irq_base;
+	int gic_irqs, irq_base, i;
 
 	BUG_ON(gic_nr >= MAX_GIC_NR);
 
@@ -683,6 +703,13 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 	}
 
 	/*
+	 * Initialize the CPU interface map to all CPUs.
+	 * It will be refined as each CPU probes its ID.
+	 */
+	for (i = 0; i < NR_GIC_CPU_IF; i++)
+		gic_cpu_map[i] = 0xff;
+
+	/*
 	 * For primary GICs, skip over SGIs.
 	 * For secondary GICs, skip over PPIs, too.
 	 */
@@ -737,7 +764,7 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 
 	/* Convert our logical CPU mask into a physical one. */
 	for_each_cpu(cpu, mask)
-		map |= 1 << cpu_logical_map(cpu);
+		map |= gic_cpu_map[cpu];
 
 	/*
 	 * Ensure that stores to Normal memory are visible to the
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index e0d5388..e4df17c 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -218,7 +218,7 @@ static void __init vic_register(void __iomem *base, unsigned int irq,
 	v->resume_sources = resume_sources;
 	v->irq = irq;
 	vic_id++;
-	v->domain = irq_domain_add_legacy(node, fls(valid_sources), irq, 0,
+	v->domain = irq_domain_add_simple(node, fls(valid_sources), irq,
 					  &vic_irqdomain_ops, v);
 }
 
@@ -350,7 +350,7 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
 	vic_register(base, irq_start, vic_sources, 0, node);
 }
 
-void __init __vic_init(void __iomem *base, unsigned int irq_start,
+void __init __vic_init(void __iomem *base, int irq_start,
 			      u32 vic_sources, u32 resume_sources,
 			      struct device_node *node)
 {
@@ -407,7 +407,6 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
 int __init vic_of_init(struct device_node *node, struct device_node *parent)
 {
 	void __iomem *regs;
-	int irq_base;
 
 	if (WARN(parent, "non-root VICs are not supported"))
 		return -EINVAL;
@@ -416,18 +415,12 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)
 	if (WARN_ON(!regs))
 		return -EIO;
 
-	irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id());
-	if (WARN_ON(irq_base < 0))
-		goto out_unmap;
-
-	__vic_init(regs, irq_base, ~0, ~0, node);
+	/*
+	 * Passing -1 as first IRQ makes the simple domain allocate descriptors
+	 */
+	__vic_init(regs, -1, ~0, ~0, node);
 
 	return 0;
-
- out_unmap:
-	iounmap(regs);
-
-	return -EIO;
 }
 #endif /* CONFIG OF */
 
diff --git a/arch/arm/configs/afeb9260_defconfig b/arch/arm/configs/afeb9260_defconfig
deleted file mode 100644
index c285a9d..0000000
--- a/arch/arm/configs/afeb9260_defconfig
+++ /dev/null
@@ -1,106 +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_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9260=y
-CONFIG_MACH_AFEB9260=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_SSC=y
-CONFIG_EEPROM_AT24=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# 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_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_SPI=y
-CONFIG_SPI_DEBUG=y
-CONFIG_SPI_ATMEL=y
-CONFIG_SPI_SPIDEV=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ZERO=m
-CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DEBUG=y
-CONFIG_RTC_DRV_FM3130=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_INOTIFY=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_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_FTRACE is not set
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
-CONFIG_CRC_T10DIF=y
diff --git a/arch/arm/configs/ap4evb_defconfig b/arch/arm/configs/ap4evb_defconfig
index 2eef85e..66894f7 100644
--- a/arch/arm/configs/ap4evb_defconfig
+++ b/arch/arm/configs/ap4evb_defconfig
@@ -46,7 +46,6 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
 # CONFIG_DNOTIFY is not set
-# CONFIG_INOTIFY_USER is not set
 CONFIG_TMPFS=y
 # CONFIG_MISC_FILESYSTEMS is not set
 CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
index f78d259..2e1a825 100644
--- a/arch/arm/configs/armadillo800eva_defconfig
+++ b/arch/arm/configs/armadillo800eva_defconfig
@@ -7,6 +7,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_IPC_NS is not set
 # CONFIG_PID_NS is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_PERF_EVENTS=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -20,7 +21,7 @@ CONFIG_MACH_ARMADILLO800EVA=y
 # CONFIG_SH_TIMER_TMU is not set
 CONFIG_ARM_THUMB=y
 CONFIG_CPU_BPREDICT_DISABLE=y
-# CONFIG_CACHE_L2X0 is not set
+CONFIG_CACHE_L2X0=y
 CONFIG_ARM_ERRATA_430973=y
 CONFIG_ARM_ERRATA_458693=y
 CONFIG_ARM_ERRATA_460075=y
diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig
index 67bc571..b175577 100644
--- a/arch/arm/configs/at91_dt_defconfig
+++ b/arch/arm/configs/at91_dt_defconfig
@@ -111,6 +111,7 @@ CONFIG_I2C=y
 CONFIG_I2C_GPIO=y
 CONFIG_SPI=y
 CONFIG_SPI_ATMEL=y
+CONFIG_PINCTRL_AT91=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_AT91SAM9X_WATCHDOG=y
diff --git a/arch/arm/configs/at91sam9260_defconfig b/arch/arm/configs/at91sam9260_defconfig
index 505b376..0ea5d2c 100644
--- a/arch/arm/configs/at91sam9260_defconfig
+++ b/arch/arm/configs/at91sam9260_defconfig
@@ -75,7 +75,7 @@ CONFIG_USB_STORAGE_DEBUG=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AT91SAM9=y
diff --git a/arch/arm/configs/at91sam9261_defconfig b/arch/arm/configs/at91sam9261_defconfig
index 1e8712e..c87beb9 100644
--- a/arch/arm/configs/at91sam9261_defconfig
+++ b/arch/arm/configs/at91sam9261_defconfig
@@ -125,7 +125,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 CONFIG_MMC_ATMELMCI=m
diff --git a/arch/arm/configs/at91sam9263_defconfig b/arch/arm/configs/at91sam9263_defconfig
index d2050ca..c5212f4 100644
--- a/arch/arm/configs/at91sam9263_defconfig
+++ b/arch/arm/configs/at91sam9263_defconfig
@@ -133,7 +133,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 CONFIG_SDIO_UART=m
diff --git a/arch/arm/configs/at91sam9g20_defconfig b/arch/arm/configs/at91sam9g20_defconfig
index e1b0e80..3b18810 100644
--- a/arch/arm/configs/at91sam9g20_defconfig
+++ b/arch/arm/configs/at91sam9g20_defconfig
@@ -96,7 +96,7 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 CONFIG_MMC_ATMELMCI=m
diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index 7aea702..74e27f0 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -66,8 +66,6 @@ CONFIG_TTY_PRINTK=y
 # CONFIG_FILE_LOCKING is not set
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY_USER is not set
-# CONFIG_PROC_FS is not set
-# CONFIG_SYSFS is not set
 # CONFIG_MISC_FILESYSTEMS is not set
 CONFIG_PRINTK_TIME=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig
new file mode 100644
index 0000000..e3bf2d6
--- /dev/null
+++ b/arch/arm/configs/bcm_defconfig
@@ -0,0 +1,114 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=19
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_BLK_CGROUP=y
+CONFIG_NAMESPACES=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
+CONFIG_ARCH_BCM=y
+CONFIG_ARM_THUMBEE=y
+CONFIG_ARM_ERRATA_743622=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_COMPACTION is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_CMDLINE="console=ttyS0,115200n8 mem=128M"
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_BLK_DEV is not set
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_INPUT_FF_MEMLESS=y
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_HWMON is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_USB_SUPPORT is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=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_DEBUG_LL=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC7=y
+CONFIG_XZ_DEC=y
+CONFIG_AVERAGE=y
diff --git a/arch/arm/configs/cam60_defconfig b/arch/arm/configs/cam60_defconfig
deleted file mode 100644
index 1457971..0000000
--- a/arch/arm/configs/cam60_defconfig
+++ /dev/null
@@ -1,173 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# 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_AUDIT=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_KALLSYMS_ALL=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9260=y
-CONFIG_MACH_CAM60=y
-CONFIG_ZBOOT_ROM_BSS=0x20004000
-CONFIG_CMDLINE="console=ttyS0,115200 noinitrd root=/dev/mtdblock0 rootfstype=jffs2 mem=64M"
-CONFIG_FPE_NWFPE=y
-CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_MISC=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETWORK_SECMARK=y
-CONFIG_CFG80211=m
-CONFIG_MAC80211=m
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-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_COMPLEX_MAPPINGS=y
-CONFIG_MTD_PLATRAM=m
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_SCSI=y
-CONFIG_SCSI_TGT=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_CHR_DEV_SCH=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-CONFIG_SCSI_SPI_ATTRS=m
-CONFIG_SCSI_FC_ATTRS=m
-CONFIG_SCSI_ISCSI_ATTRS=m
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_NETDEVICES=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_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-CONFIG_INPUT_EVDEV=y
-CONFIG_KEYBOARD_LKKBD=m
-CONFIG_KEYBOARD_NEWTON=m
-CONFIG_KEYBOARD_STOWAWAY=m
-CONFIG_KEYBOARD_SUNKBD=m
-CONFIG_KEYBOARD_XTKBD=m
-CONFIG_MOUSE_SERIAL=m
-CONFIG_MOUSE_APPLETOUCH=m
-CONFIG_MOUSE_VSXXXAA=m
-# CONFIG_SERIO_SERPORT is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
-CONFIG_SERIAL_NONSTANDARD=y
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_LIBUSUAL=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_INTF_DEV_UIE_EMUL=y
-CONFIG_RTC_DRV_TEST=m
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT3_FS=y
-CONFIG_INOTIFY=y
-CONFIG_QUOTA=y
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_DEFAULT="cp437"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_UTF8=y
-CONFIG_PRINTK_TIME=y
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_UNUSED_SYMBOLS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_DEBUG_LL=y
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_CRYPTD=m
-CONFIG_CRYPTO_TEST=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-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_DES=y
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_DEFLATE=m
-# CONFIG_CRYPTO_HW is not set
-CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
diff --git a/arch/arm/configs/clps711x_defconfig b/arch/arm/configs/clps711x_defconfig
new file mode 100644
index 0000000..1cd94c3
--- /dev/null
+++ b/arch/arm/configs/clps711x_defconfig
@@ -0,0 +1,90 @@
+CONFIG_KERNEL_LZMA=y
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_LZMA=y
+CONFIG_EMBEDDED=y
+CONFIG_SLOB=y
+CONFIG_JUMP_LABEL=y
+# CONFIG_LBDAF is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_CLPS711X=y
+CONFIG_ARCH_AUTCPU12=y
+CONFIG_ARCH_CDB89712=y
+CONFIG_ARCH_CLEP7312=y
+CONFIG_ARCH_EDB7211=y
+CONFIG_ARCH_P720T=y
+CONFIG_ARCH_FORTUNET=y
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_COREDUMP is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IPV6 is not set
+CONFIG_IRDA=y
+CONFIG_IRTTY_SIR=y
+CONFIG_EP7211_DONGLE=y
+# CONFIG_WIRELESS is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_AUTCPU12=y
+CONFIG_MTD_PLATRAM=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_GPIO=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+CONFIG_CS89x0=y
+CONFIG_CS89x0_PLATFORM=y
+# 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_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+CONFIG_SERIAL_CLPS711X_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_SPI=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FB_CLPS711X=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_PLATFORM=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_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_MINIX_FS=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_CRC32 is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 4b8a25d..1fd1d1d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -218,7 +218,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 CONFIG_MMC_PXA=y
diff --git a/arch/arm/configs/cpu9260_defconfig b/arch/arm/configs/cpu9260_defconfig
deleted file mode 100644
index 921480c..0000000
--- a/arch/arm/configs/cpu9260_defconfig
+++ /dev/null
@@ -1,116 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9260=y
-CONFIG_MACH_CPU9260=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PLATRAM=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_NETDEVICES=y
-CONFIG_SMSC_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-CONFIG_PPP=y
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=32
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91SAM9X_WATCHDOG=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=y
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ETH=m
-CONFIG_MMC=y
-CONFIG_MMC_ATMELMCI=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_GPIO=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-CONFIG_RTC_CLASS=y
-# CONFIG_RTC_HCTOSYS is not set
-CONFIG_RTC_DRV_DS1307=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_INOTIFY=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_CRAMFS=y
-CONFIG_MINIX_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_NLS_UTF8=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
diff --git a/arch/arm/configs/cpu9g20_defconfig b/arch/arm/configs/cpu9g20_defconfig
deleted file mode 100644
index ea116cb..0000000
--- a/arch/arm/configs/cpu9g20_defconfig
+++ /dev/null
@@ -1,116 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9G20=y
-CONFIG_MACH_CPU9G20=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PLATRAM=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_NETDEVICES=y
-CONFIG_SMSC_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-CONFIG_PPP=y
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=32
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91SAM9X_WATCHDOG=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=y
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ETH=m
-CONFIG_MMC=y
-CONFIG_MMC_ATMELMCI=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_GPIO=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-CONFIG_RTC_CLASS=y
-# CONFIG_RTC_HCTOSYS is not set
-CONFIG_RTC_DRV_DS1307=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_INOTIFY=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_CRAMFS=y
-CONFIG_MINIX_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_NLS_UTF8=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig
index 88ccde0..f292239 100644
--- a/arch/arm/configs/da8xx_omapl_defconfig
+++ b/arch/arm/configs/da8xx_omapl_defconfig
@@ -17,6 +17,7 @@ CONFIG_MODVERSIONS=y
 CONFIG_ARCH_DAVINCI=y
 CONFIG_ARCH_DAVINCI_DA830=y
 CONFIG_ARCH_DAVINCI_DA850=y
+CONFIG_MACH_DA8XX_DT=y
 CONFIG_MACH_MITYOMAPL138=y
 CONFIG_MACH_OMAPL138_HAWKBOARD=y
 CONFIG_DAVINCI_RESET_CLOCKS=y
@@ -26,6 +27,7 @@ CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 # CONFIG_OABI_COMPAT is not set
 CONFIG_LEDS=y
+CONFIG_USE_OF=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CPU_FREQ=y
@@ -75,6 +77,7 @@ CONFIG_SERIO_LIBPS2=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=3
+CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_DAVINCI=y
diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig
index 67b5abb6..4ea7c95 100644
--- a/arch/arm/configs/davinci_all_defconfig
+++ b/arch/arm/configs/davinci_all_defconfig
@@ -144,7 +144,7 @@ CONFIG_USB_GADGET_DEBUG_FS=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_USB_CDC_COMPOSITE=m
diff --git a/arch/arm/configs/dove_defconfig b/arch/arm/configs/dove_defconfig
index 40db34c..0b7ee92 100644
--- a/arch/arm/configs/dove_defconfig
+++ b/arch/arm/configs/dove_defconfig
@@ -8,11 +8,19 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_ARCH_DOVE=y
 CONFIG_MACH_DOVE_DB=y
+CONFIG_MACH_CM_A510=y
+CONFIG_MACH_DOVE_DT=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_HIGHMEM=y
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
 CONFIG_VFP=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -62,6 +70,9 @@ CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_SERIAL_8250_PCI is not set
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -74,6 +85,18 @@ CONFIG_USB_DEVICEFS=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_IO_ACCESSORS=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_DOVE=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_MV=y
 CONFIG_DMADEVICES=y
@@ -122,6 +145,7 @@ CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRYPTO_LZO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DEV_MV_CESA=y
 CONFIG_CRC_CCITT=y
 CONFIG_CRC16=y
 CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/edb7211_defconfig b/arch/arm/configs/edb7211_defconfig
deleted file mode 100644
index d52ded35..0000000
--- a/arch/arm/configs/edb7211_defconfig
+++ /dev/null
@@ -1,27 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
-# CONFIG_HOTPLUG is not set
-CONFIG_ARCH_CLPS711X=y
-CONFIG_ARCH_EDB7211=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_IPV6 is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_NETDEVICES=y
-# CONFIG_INPUT is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_VT is not set
-CONFIG_SERIAL_CLPS711X=y
-CONFIG_SERIAL_CLPS711X_CONSOLE=y
-CONFIG_EXT2_FS=y
-CONFIG_MINIX_FS=y
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_MSDOS_PARTITION is not set
-CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/fortunet_defconfig b/arch/arm/configs/fortunet_defconfig
deleted file mode 100644
index 840fced..0000000
--- a/arch/arm/configs/fortunet_defconfig
+++ /dev/null
@@ -1,28 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
-# CONFIG_HOTPLUG is not set
-CONFIG_ARCH_CLPS711X=y
-CONFIG_ARCH_FORTUNET=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_FASTFPE=y
-CONFIG_BINFMT_AOUT=y
-CONFIG_NET=y
-CONFIG_UNIX=y
-CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_CLPS711X=y
-CONFIG_SERIAL_CLPS711X_CONSOLE=y
-CONFIG_EXT2_FS=y
-CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/g3evm_defconfig b/arch/arm/configs/g3evm_defconfig
deleted file mode 100644
index 4a336ab..0000000
--- a/arch/arm/configs/g3evm_defconfig
+++ /dev/null
@@ -1,57 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_SHMOBILE=y
-CONFIG_ARCH_SH7367=y
-CONFIG_MACH_G3EVM=y
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttySC1,115200 earlyprintk=sh-sci.1,115200"
-CONFIG_KEXEC=y
-CONFIG_PM=y
-# CONFIG_SUSPEND is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_FIRMWARE_IN_KERNEL is not set
-CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_NAND=y
-# CONFIG_BLK_DEV is not set
-# CONFIG_MISC_DEVICES is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_SH_SCI=y
-CONFIG_SERIAL_SH_SCI_NR_UARTS=8
-CONFIG_SERIAL_SH_SCI_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_INOTIFY_USER is not set
-CONFIG_TMPFS=y
-# CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DETECT_SOFTLOCKUP is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_FTRACE is not set
-# CONFIG_CRC32 is not set
diff --git a/arch/arm/configs/g4evm_defconfig b/arch/arm/configs/g4evm_defconfig
deleted file mode 100644
index 21c6d03..0000000
--- a/arch/arm/configs/g4evm_defconfig
+++ /dev/null
@@ -1,57 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_SHMOBILE=y
-CONFIG_ARCH_SH7377=y
-CONFIG_MACH_G4EVM=y
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttySC4,115200 earlyprintk=sh-sci.4,115200"
-CONFIG_KEXEC=y
-CONFIG_PM=y
-# CONFIG_SUSPEND is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_FIRMWARE_IN_KERNEL is not set
-CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_NAND=y
-# CONFIG_BLK_DEV is not set
-# CONFIG_MISC_DEVICES is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_SH_SCI=y
-CONFIG_SERIAL_SH_SCI_NR_UARTS=8
-CONFIG_SERIAL_SH_SCI_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_INOTIFY_USER is not set
-CONFIG_TMPFS=y
-# CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DETECT_SOFTLOCKUP is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_FTRACE is not set
-# CONFIG_CRC32 is not set
diff --git a/arch/arm/configs/h7202_defconfig b/arch/arm/configs/h7202_defconfig
index 69405a7..e16d3f3 100644
--- a/arch/arm/configs/h7202_defconfig
+++ b/arch/arm/configs/h7202_defconfig
@@ -34,8 +34,7 @@ CONFIG_FB_MODE_HELPERS=y
 CONFIG_USB_GADGET=m
 CONFIG_USB_ZERO=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_EXT2_FS=y
 CONFIG_TMPFS=y
diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig
index 78ed575..ebbfb27 100644
--- a/arch/arm/configs/imx_v4_v5_defconfig
+++ b/arch/arm/configs/imx_v4_v5_defconfig
@@ -18,7 +18,9 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARCH_MXC=y
-CONFIG_ARCH_IMX_V4_V5=y
+CONFIG_ARCH_MULTI_V4T=y
+CONFIG_ARCH_MULTI_V5=y
+# CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_ARCH_MX1ADS=y
 CONFIG_MACH_SCB9328=y
 CONFIG_MACH_APF9328=y
@@ -121,6 +123,7 @@ CONFIG_REGULATOR_MC13892=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
 CONFIG_SOC_CAMERA=y
 CONFIG_SOC_CAMERA_OV2640=y
 CONFIG_VIDEO_MX2=y
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index 394ded6..6966713 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -17,6 +17,8 @@ CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_ARCH_MXC=y
+CONFIG_ARCH_MULTI_V6=y
+CONFIG_ARCH_MULTI_V7=y
 CONFIG_MACH_MX31LILLY=y
 CONFIG_MACH_MX31LITE=y
 CONFIG_MACH_PCM037=y
@@ -143,15 +145,18 @@ CONFIG_GPIO_MC9S08DZ60=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_IMX2_WDT=y
+CONFIG_MFD_DA9052_I2C=y
 CONFIG_MFD_MC13XXX_SPI=y
 CONFIG_MFD_MC13XXX_I2C=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_DA9052=y
 CONFIG_REGULATOR_MC13783=y
 CONFIG_REGULATOR_MC13892=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
 CONFIG_SOC_CAMERA=y
 CONFIG_SOC_CAMERA_OV2640=y
 CONFIG_VIDEO_MX3=y
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
index 74eee0c..93f3794 100644
--- a/arch/arm/configs/kirkwood_defconfig
+++ b/arch/arm/configs/kirkwood_defconfig
@@ -27,6 +27,14 @@ CONFIG_MACH_GOFLEXNET_DT=y
 CONFIG_MACH_LSXL_DT=y
 CONFIG_MACH_IOMEGA_IX2_200_DT=y
 CONFIG_MACH_KM_KIRKWOOD_DT=y
+CONFIG_MACH_INETSPACE_V2_DT=y
+CONFIG_MACH_MPLCEC4_DT=y
+CONFIG_MACH_NETSPACE_V2_DT=y
+CONFIG_MACH_NETSPACE_MAX_V2_DT=y
+CONFIG_MACH_NETSPACE_LITE_V2_DT=y
+CONFIG_MACH_NETSPACE_MINI_V2_DT=y
+CONFIG_MACH_OPENBLOCKS_A6_DT=y
+CONFIG_MACH_TOPKICK_DT=y
 CONFIG_MACH_TS219=y
 CONFIG_MACH_TS41X=y
 CONFIG_MACH_DOCKSTAR=y
@@ -40,6 +48,7 @@ CONFIG_MACH_D2NET_V2=y
 CONFIG_MACH_NET2BIG_V2=y
 CONFIG_MACH_NET5BIG_V2=y
 CONFIG_MACH_T5325=y
+CONFIG_MACH_NSA310_DT=y
 # CONFIG_CPU_FEROCEON_OLD_ID is not set
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
diff --git a/arch/arm/configs/kota2_defconfig b/arch/arm/configs/kota2_defconfig
index b7735d6..fa83db1 100644
--- a/arch/arm/configs/kota2_defconfig
+++ b/arch/arm/configs/kota2_defconfig
@@ -112,7 +112,6 @@ CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_RENESAS_TPU=y
 CONFIG_LEDS_TRIGGERS=y
 # CONFIG_DNOTIFY is not set
-# CONFIG_INOTIFY_USER is not set
 CONFIG_TMPFS=y
 # CONFIG_MISC_FILESYSTEMS is not set
 CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig
index c88b578..afbae28 100644
--- a/arch/arm/configs/kzm9g_defconfig
+++ b/arch/arm/configs/kzm9g_defconfig
@@ -74,6 +74,8 @@ CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ST1232=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_ADXL34X=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=9
@@ -119,8 +121,9 @@ CONFIG_DMADEVICES=y
 CONFIG_SH_DMAE=y
 CONFIG_ASYNC_TX_DMA=y
 CONFIG_STAGING=y
+CONFIG_SENSORS_AK8975=y
+CONFIG_IIO=y
 # CONFIG_DNOTIFY is not set
-CONFIG_INOTIFY_USER=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 # CONFIG_MISC_FILESYSTEMS is not set
diff --git a/arch/arm/configs/mackerel_defconfig b/arch/arm/configs/mackerel_defconfig
index 306a2e2..2098ce1 100644
--- a/arch/arm/configs/mackerel_defconfig
+++ b/arch/arm/configs/mackerel_defconfig
@@ -70,17 +70,31 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=8
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_SH_MOBILE=y
 # CONFIG_HWMON is not set
 # CONFIG_MFD_SUPPORT is not set
 CONFIG_FB=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_SH_MOBILE_LCDC=y
+CONFIG_FB_SH_MOBILE_HDMI=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SOC_SH4_FSI=y
+CONFIG_USB=y
+CONFIG_USB_RENESAS_USBHS_HCD=y
+CONFIG_USB_RENESAS_USBHS=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_RENESAS_USBHS_UDC=y
+CONFIG_DMADEVICES=y
+CONFIG_SH_DMAE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
@@ -91,7 +105,6 @@ CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
 # CONFIG_DNOTIFY is not set
-# CONFIG_INOTIFY_USER is not set
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
diff --git a/arch/arm/configs/magician_defconfig b/arch/arm/configs/magician_defconfig
index a691ef4..557dd29 100644
--- a/arch/arm/configs/magician_defconfig
+++ b/arch/arm/configs/magician_defconfig
@@ -136,7 +136,7 @@ CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_USB_GPIO_VBUS=y
diff --git a/arch/arm/configs/marzen_defconfig b/arch/arm/configs/marzen_defconfig
index 53382b6..728a43c 100644
--- a/arch/arm/configs/marzen_defconfig
+++ b/arch/arm/configs/marzen_defconfig
@@ -47,6 +47,8 @@ CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_FARADAY is not set
@@ -59,9 +61,8 @@ CONFIG_SMSC911X=y
 # CONFIG_NET_VENDOR_STMICRO is not set
 # CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
 # CONFIG_VT is not set
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
@@ -69,14 +70,25 @@ CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=6
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_RCAR=y
+CONFIG_SPI=y
+CONFIG_SPI_SH_HSPI=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 CONFIG_THERMAL=y
 CONFIG_RCAR_THERMAL=y
 CONFIG_SSB=y
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB=y
+CONFIG_USB_RCAR_PHY=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHI=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
 CONFIG_UIO=y
 CONFIG_UIO_PDRV_GENIRQ=y
 # CONFIG_IOMMU_SUPPORT is not set
diff --git a/arch/arm/configs/mini2440_defconfig b/arch/arm/configs/mini2440_defconfig
index 00630e6..a07948a 100644
--- a/arch/arm/configs/mini2440_defconfig
+++ b/arch/arm/configs/mini2440_defconfig
@@ -240,7 +240,7 @@ CONFIG_USB_GADGET_S3C2410=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig
index 048aaca..7bf5351 100644
--- a/arch/arm/configs/mxs_defconfig
+++ b/arch/arm/configs/mxs_defconfig
@@ -61,6 +61,8 @@ CONFIG_MTD_NAND_GPMI_NAND=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_ENC28J60=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC95XX=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_WLAN is not set
@@ -158,6 +160,10 @@ CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=y
 CONFIG_PRINTK_TIME=y
 CONFIG_FRAME_WARN=2048
 CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/arm/configs/nhk8815_defconfig b/arch/arm/configs/nhk8815_defconfig
index 240b25e..86cfd29 100644
--- a/arch/arm/configs/nhk8815_defconfig
+++ b/arch/arm/configs/nhk8815_defconfig
@@ -57,7 +57,7 @@ CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_ECC_SMC=y
-CONFIG_MTD_NAND_NOMADIK=y
+CONFIG_MTD_NAND_FSMC=y
 CONFIG_MTD_ONENAND=y
 CONFIG_MTD_ONENAND_VERIFY_WRITE=y
 CONFIG_MTD_ONENAND_GENERIC=y
diff --git a/arch/arm/configs/omap1_defconfig b/arch/arm/configs/omap1_defconfig
index dde2a1a..42eab9a 100644
--- a/arch/arm/configs/omap1_defconfig
+++ b/arch/arm/configs/omap1_defconfig
@@ -214,8 +214,7 @@ CONFIG_USB_TEST=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index 6230304..a1dc5c0 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -240,3 +240,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
diff --git a/arch/arm/configs/orion5x_defconfig b/arch/arm/configs/orion5x_defconfig
index cd5e6ba..952430d 100644
--- a/arch/arm/configs/orion5x_defconfig
+++ b/arch/arm/configs/orion5x_defconfig
@@ -1,7 +1,8 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_EXPERT=y
 # CONFIG_SLUB_DEBUG is not set
 CONFIG_PROFILING=y
@@ -10,6 +11,8 @@ CONFIG_KPROBES=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_BSD_DISKLABEL=y
 CONFIG_ARCH_ORION5X=y
 CONFIG_MACH_DB88F5281=y
 CONFIG_MACH_RD88F5182=y
@@ -24,7 +27,7 @@ CONFIG_MACH_TS409=y
 CONFIG_MACH_WRT350N_V2=y
 CONFIG_MACH_TS78XX=y
 CONFIG_MACH_MV2120=y
-CONFIG_MACH_EDMINI_V2=y
+CONFIG_MACH_EDMINI_V2_DT=y
 CONFIG_MACH_D2NET=y
 CONFIG_MACH_BIGDISK=y
 CONFIG_MACH_NET2BIG=y
@@ -33,17 +36,13 @@ CONFIG_MACH_WNR854T=y
 CONFIG_MACH_RD88F5181L_GE=y
 CONFIG_MACH_RD88F5181L_FXO=y
 CONFIG_MACH_RD88F6183AP_GE=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
 CONFIG_FPE_NWFPE=y
 CONFIG_VFP=y
-# CONFIG_SUSPEND is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -54,13 +53,10 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IPV6 is not set
 CONFIG_NET_DSA=y
-CONFIG_NET_DSA_MV88E6131=y
-CONFIG_NET_DSA_MV88E6123_61_65=y
 CONFIG_NET_PKTGEN=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
@@ -82,12 +78,11 @@ CONFIG_CHR_DEV_SG=m
 CONFIG_ATA=y
 CONFIG_SATA_MV=y
 CONFIG_NETDEVICES=y
-CONFIG_MARVELL_PHY=y
-CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-CONFIG_NET_PCI=y
+CONFIG_NET_DSA_MV88E6131=y
+CONFIG_NET_DSA_MV88E6123_61_65=y
 CONFIG_MV643XX_ETH=y
-# CONFIG_NETDEV_10000 is not set
+CONFIG_MARVELL_PHY=y
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
@@ -95,11 +90,12 @@ CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
+CONFIG_LEGACY_PTY_COUNT=16
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_SERIAL_8250_PCI is not set
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_LEGACY_PTY_COUNT=16
+CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_HW_RANDOM_TIMERIOMEM=m
 CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
@@ -109,10 +105,8 @@ CONFIG_GPIO_SYSFS=y
 CONFIG_SENSORS_LM75=y
 # CONFIG_VGA_ARB is not set
 CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
-CONFIG_USB_EHCI_TT_NEWSCHED=y
 CONFIG_USB_PRINTER=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DATAFAB=y
@@ -140,7 +134,6 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=m
-CONFIG_INOTIFY=y
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_UDF_FS=m
@@ -150,25 +143,18 @@ CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_CRAMFS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_BSD_DISKLABEL=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_850=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_2=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_LATENCYTOP=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 # CONFIG_FTRACE is not set
 CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 CONFIG_CRYPTO_CBC=m
 CONFIG_CRYPTO_ECB=m
diff --git a/arch/arm/configs/prima2_defconfig b/arch/arm/configs/prima2_defconfig
index 807d4e2..6a936c7 100644
--- a/arch/arm/configs/prima2_defconfig
+++ b/arch/arm/configs/prima2_defconfig
@@ -37,7 +37,6 @@ CONFIG_SPI_SIRF=y
 CONFIG_SPI_SPIDEV=y
 # CONFIG_HWMON is not set
 CONFIG_USB_GADGET=y
-CONFIG_USB_FILE_STORAGE=m
 CONFIG_USB_MASS_STORAGE=m
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
diff --git a/arch/arm/configs/qil-a9260_defconfig b/arch/arm/configs/qil-a9260_defconfig
deleted file mode 100644
index 42d5db1..0000000
--- a/arch/arm/configs/qil-a9260_defconfig
+++ /dev/null
@@ -1,114 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9260=y
-CONFIG_MACH_QIL_A9260=y
-CONFIG_AT91_SLOW_CLOCK=y
-CONFIG_AT91_EARLY_USART0=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS1,115200"
-CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_EVBUG=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ETH=m
-CONFIG_MMC=y
-CONFIG_MMC_ATMELMCI=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_M41T94=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_FUSE_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
-# CONFIG_CRYPTO_HW is not set
diff --git a/arch/arm/configs/sam9_l9260_defconfig b/arch/arm/configs/sam9_l9260_defconfig
deleted file mode 100644
index b4384af..0000000
--- a/arch/arm/configs/sam9_l9260_defconfig
+++ /dev/null
@@ -1,148 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# 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_AUDIT=y
-CONFIG_LOG_BUF_SHIFT=15
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9260=y
-CONFIG_MACH_SAM9_L9260=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
-CONFIG_PREEMPT=y
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,115200 mem=64M initrd=0x21100000,4194304 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_BLOCK2MTD=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_MTD_NAND_PLATFORM=y
-CONFIG_MTD_UBI=y
-CONFIG_MTD_UBI_BEB_LIMIT=25
-CONFIG_MTD_UBI_GLUEBI=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_MISC_DEVICES is not set
-CONFIG_RAID_ATTRS=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# 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_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=16
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_LIBUSUAL=y
-CONFIG_USB_GADGET=y
-CONFIG_MMC=y
-CONFIG_MMC_DEBUG=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_DS1553=y
-CONFIG_RTC_DRV_DS1742=y
-CONFIG_RTC_DRV_M48T86=y
-CONFIG_RTC_DRV_V3020=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_INOTIFY=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_737=y
-CONFIG_NLS_CODEPAGE_775=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_CODEPAGE_852=y
-CONFIG_NLS_CODEPAGE_855=y
-CONFIG_NLS_CODEPAGE_857=y
-CONFIG_NLS_CODEPAGE_860=y
-CONFIG_NLS_CODEPAGE_861=y
-CONFIG_NLS_CODEPAGE_862=y
-CONFIG_NLS_CODEPAGE_863=y
-CONFIG_NLS_CODEPAGE_864=y
-CONFIG_NLS_CODEPAGE_865=y
-CONFIG_NLS_CODEPAGE_866=y
-CONFIG_NLS_CODEPAGE_869=y
-CONFIG_NLS_CODEPAGE_936=y
-CONFIG_NLS_CODEPAGE_950=y
-CONFIG_NLS_CODEPAGE_932=y
-CONFIG_NLS_CODEPAGE_949=y
-CONFIG_NLS_CODEPAGE_874=y
-CONFIG_NLS_ISO8859_8=y
-CONFIG_NLS_CODEPAGE_1250=y
-CONFIG_NLS_CODEPAGE_1251=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=y
-CONFIG_NLS_ISO8859_3=y
-CONFIG_NLS_ISO8859_4=y
-CONFIG_NLS_ISO8859_5=y
-CONFIG_NLS_ISO8859_6=y
-CONFIG_NLS_ISO8859_7=y
-CONFIG_NLS_ISO8859_9=y
-CONFIG_NLS_ISO8859_13=y
-CONFIG_NLS_ISO8859_14=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_KOI8_R=y
-CONFIG_NLS_KOI8_U=y
-CONFIG_NLS_UTF8=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_UNUSED_SYMBOLS=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
index 0ac1293..2307285 100644
--- a/arch/arm/configs/socfpga_defconfig
+++ b/arch/arm/configs/socfpga_defconfig
@@ -1,5 +1,5 @@
 CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -18,9 +18,10 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_SOCFPGA=y
 CONFIG_MACH_SOCFPGA_CYCLONE5=y
 CONFIG_ARM_THUMBEE=y
+# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
 # CONFIG_CACHE_L2X0 is not set
 CONFIG_HIGH_RES_TIMERS=y
-CONFIG_VMSPLIT_2G=y
+CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index df77931..2e0419d 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -214,7 +214,7 @@ CONFIG_USB_GADGET_DUMMY_HCD=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 CONFIG_MMC_PXA=y
diff --git a/arch/arm/configs/stamp9g20_defconfig b/arch/arm/configs/stamp9g20_defconfig
deleted file mode 100644
index 52f1488..0000000
--- a/arch/arm/configs/stamp9g20_defconfig
+++ /dev/null
@@ -1,128 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_LBDAF is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9G20=y
-CONFIG_MACH_PORTUXG20=y
-CONFIG_MACH_STAMP9G20=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-CONFIG_AT91_SLOW_CLOCK=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
-CONFIG_KEXEC=y
-CONFIG_CPU_IDLE=y
-CONFIG_PM=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-# CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-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_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_MISC_DEVICES is not set
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MACB=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_WLAN is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-CONFIG_SPI_SPIDEV=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_W1=y
-CONFIG_W1_MASTER_GPIO=y
-CONFIG_W1_SLAVE_THERM=y
-CONFIG_W1_SLAVE_DS2431=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_AT91SAM9X_WATCHDOG=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=m
-CONFIG_USB_ZERO=m
-CONFIG_USB_ETH=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_MMC=y
-CONFIG_MMC_ATMELMCI=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_INOTIFY=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_ARM_UNWIND is not set
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index e2184f6..a7827fd 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -80,6 +80,10 @@ CONFIG_RFKILL_GPIO=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_CMA=y
+CONFIG_MTD=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_M25P80=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_AD525X_DPOT=y
@@ -98,12 +102,12 @@ CONFIG_USB_PEGASUS=y
 CONFIG_USB_USBNET=y
 CONFIG_USB_NET_SMSC75XX=y
 CONFIG_USB_NET_SMSC95XX=y
+CONFIG_BRCMFMAC=m
 CONFIG_RT2X00=y
 CONFIG_RT2800USB=m
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MPU3050=y
-# CONFIG_VT is not set
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_8250=y
@@ -116,7 +120,8 @@ CONFIG_I2C_MUX=y
 CONFIG_I2C_MUX_PINCTRL=y
 CONFIG_I2C_TEGRA=y
 CONFIG_SPI=y
-CONFIG_SPI_TEGRA=y
+CONFIG_SPI_TEGRA20_SFLASH=y
+CONFIG_SPI_TEGRA20_SLINK=y
 CONFIG_GPIO_PCA953X_IRQ=y
 CONFIG_GPIO_TPS6586X=y
 CONFIG_GPIO_TPS65910=y
@@ -138,6 +143,15 @@ CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_CAMERA_SUPPORT=y
 CONFIG_MEDIA_USB_SUPPORT=y
 CONFIG_USB_VIDEO_CLASS=m
+CONFIG_DRM=y
+CONFIG_DRM_TEGRA=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 # CONFIG_SND_SUPPORT_OLD_API is not set
@@ -205,6 +219,9 @@ CONFIG_EXT4_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
 CONFIG_NFS_FS=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig
index da68454..231dca6 100644
--- a/arch/arm/configs/u8500_defconfig
+++ b/arch/arm/configs/u8500_defconfig
@@ -69,6 +69,8 @@ CONFIG_GPIO_TC3589X=y
 CONFIG_POWER_SUPPLY=y
 CONFIG_AB8500_BM=y
 CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL=y
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
 CONFIG_MFD_STMPE=y
 CONFIG_MFD_TC3589X=y
 CONFIG_AB5500_CORE=y
@@ -76,6 +78,7 @@ CONFIG_AB8500_CORE=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_AB8500=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_GPIO=y
 # CONFIG_HID_SUPPORT is not set
 CONFIG_USB_GADGET=y
 CONFIG_AB8500_USB=y
diff --git a/arch/arm/configs/usb-a9260_defconfig b/arch/arm/configs/usb-a9260_defconfig
deleted file mode 100644
index a1501e1..0000000
--- a/arch/arm/configs/usb-a9260_defconfig
+++ /dev/null
@@ -1,105 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9260=y
-CONFIG_MACH_USB_A9260=y
-CONFIG_AT91_SLOW_CLOCK=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200"
-CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_EVBUG=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ETH=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_FUSE_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
-# CONFIG_CRYPTO_HW is not set
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index 1d01ddd..d36e0d3 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -139,7 +139,7 @@ CONFIG_USB_SERIAL_MCT_U232=m
 CONFIG_USB_GADGET=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_RTC_CLASS=y
diff --git a/arch/arm/configs/zeus_defconfig b/arch/arm/configs/zeus_defconfig
index 547a3c1..731d4f9 100644
--- a/arch/arm/configs/zeus_defconfig
+++ b/arch/arm/configs/zeus_defconfig
@@ -143,7 +143,7 @@ CONFIG_USB_GADGET=m
 CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_MMC=y
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index f70ae17..514e398 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -31,5 +31,6 @@ generic-y += sockios.h
 generic-y += termbits.h
 generic-y += termios.h
 generic-y += timex.h
+generic-y += trace_clock.h
 generic-y += types.h
 generic-y += unaligned.h
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 2ef9581..ab7c02c 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -136,7 +136,11 @@
  * assumes FIQs are enabled, and that the processor is in SVC mode.
  */
 	.macro	save_and_disable_irqs, oldcpsr
+#ifdef CONFIG_CPU_V7M
+	mrs	\oldcpsr, primask
+#else
 	mrs	\oldcpsr, cpsr
+#endif
 	disable_irq
 	.endm
 
@@ -150,7 +154,11 @@
  * guarantee that this will preserve the flags.
  */
 	.macro	restore_irqs_notrace, oldcpsr
+#ifdef CONFIG_CPU_V7M
+	msr	primask, \oldcpsr
+#else
 	msr	cpsr_c, \oldcpsr
+#endif
 	.endm
 
 	.macro restore_irqs, oldcpsr
@@ -229,7 +237,10 @@
 #endif
 	.endm
 
-#ifdef CONFIG_THUMB2_KERNEL
+#if defined(CONFIG_CPU_V7M)
+	.macro	setmode, mode, reg
+	.endm
+#elif defined(CONFIG_THUMB2_KERNEL)
 	.macro	setmode, mode, reg
 	mov	\reg, #\mode
 	msr	cpsr_c, \reg
diff --git a/arch/arm/include/asm/cp15.h b/arch/arm/include/asm/cp15.h
index 5ef4d80..d814435 100644
--- a/arch/arm/include/asm/cp15.h
+++ b/arch/arm/include/asm/cp15.h
@@ -42,6 +42,8 @@
 #define vectors_high()	(0)
 #endif
 
+#ifdef CONFIG_CPU_CP15
+
 extern unsigned long cr_no_alignment;	/* defined in entry-armv.S */
 extern unsigned long cr_alignment;	/* defined in entry-armv.S */
 
@@ -82,6 +84,13 @@ static inline void set_copro_access(unsigned int val)
 	isb();
 }
 
-#endif
+#else /* ifdef CONFIG_CPU_CP15 */
+
+#define cr_no_alignment	UL(0)
+#define cr_alignment	UL(0)
+
+#endif /* ifdef CONFIG_CPU_CP15 / else */
+
+#endif /* ifndef __ASSEMBLY__ */
 
 #endif
diff --git a/arch/arm/include/asm/cpu.h b/arch/arm/include/asm/cpu.h
index d797223..2744f06 100644
--- a/arch/arm/include/asm/cpu.h
+++ b/arch/arm/include/asm/cpu.h
@@ -15,6 +15,7 @@
 
 struct cpuinfo_arm {
 	struct cpu	cpu;
+	u32		cpuid;
 #ifdef CONFIG_SMP
 	unsigned int	loops_per_jiffy;
 #endif
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index cb47d28..b33a6dc 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -25,6 +25,19 @@
 #define CPUID_EXT_ISAR4	"c2, 4"
 #define CPUID_EXT_ISAR5	"c2, 5"
 
+#define MPIDR_SMP_BITMASK (0x3 << 30)
+#define MPIDR_SMP_VALUE (0x2 << 30)
+
+#define MPIDR_MT_BITMASK (0x1 << 24)
+
+#define MPIDR_HWID_BITMASK 0xFFFFFF
+
+#define MPIDR_LEVEL_BITS 8
+#define MPIDR_LEVEL_MASK ((1 << MPIDR_LEVEL_BITS) - 1)
+
+#define MPIDR_AFFINITY_LEVEL(mpidr, level) \
+	((mpidr >> (MPIDR_LEVEL_BITS * level)) & MPIDR_LEVEL_MASK)
+
 extern unsigned int processor_id;
 
 #ifdef CONFIG_CPU_CP15
@@ -46,6 +59,9 @@ extern unsigned int processor_id;
 		    : "cc");						\
 		__val;							\
 	})
+#elif defined(CONFIG_CPU_V7M)
+#define read_cpuid(reg) (*(unsigned int *)0xe000ed00)
+#define read_cpuid_ext(reg) 0
 #else
 #define read_cpuid(reg) (processor_id)
 #define read_cpuid_ext(reg) 0
diff --git a/arch/arm/include/asm/cti.h b/arch/arm/include/asm/cti.h
index a0ada3e..f2e5cad 100644
--- a/arch/arm/include/asm/cti.h
+++ b/arch/arm/include/asm/cti.h
@@ -146,15 +146,7 @@ static inline void cti_irq_ack(struct cti *cti)
  */
 static inline void cti_unlock(struct cti *cti)
 {
-	void __iomem *base = cti->base;
-	unsigned long val;
-
-	val = __raw_readl(base + LOCKSTATUS);
-
-	if (val & 1) {
-		val = LOCKCODE;
-		__raw_writel(val, base + LOCKACCESS);
-	}
+	__raw_writel(LOCKCODE, cti->base + LOCKACCESS);
 }
 
 /**
@@ -166,14 +158,6 @@ static inline void cti_unlock(struct cti *cti)
  */
 static inline void cti_lock(struct cti *cti)
 {
-	void __iomem *base = cti->base;
-	unsigned long val;
-
-	val = __raw_readl(base + LOCKSTATUS);
-
-	if (!(val & 1)) {
-		val = ~LOCKCODE;
-		__raw_writel(val, base + LOCKACCESS);
-	}
+	__raw_writel(~LOCKCODE, cti->base + LOCKACCESS);
 }
 #endif
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 2300484..5f07086 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -91,6 +91,7 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
  */
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
+	debug_dma_mapping_error(dev, dma_addr);
 	return dma_addr == DMA_ERROR_CODE;
 }
 
@@ -211,13 +212,6 @@ static inline void dma_free_writecombine(struct device *dev, size_t size,
 extern void __init init_dma_coherent_pool_size(unsigned long size);
 
 /*
- * This can be called during boot to increase the size of the consistent
- * DMA region above it's default value of 2MB. It must be called before the
- * memory allocator is initialised, i.e. before any core_initcall.
- */
-static inline void init_consistent_dma_size(unsigned long size) { }
-
-/*
  * For SA-1111, IXP425, and ADI systems  the dma-mapping functions are "magic"
  * and utilize bounce buffers as needed to work around limited DMA windows.
  *
diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h
index cca9f15..ea98658 100644
--- a/arch/arm/include/asm/glue-cache.h
+++ b/arch/arm/include/asm/glue-cache.h
@@ -125,10 +125,35 @@
 # endif
 #endif
 
+#if defined(CONFIG_CPU_V7M)
+# ifdef _CACHE
+#  error "Multi-cache not supported on ARMv7-M"
+# else
+#  define _CACHE nop
+# endif
+#endif
+
 #if !defined(_CACHE) && !defined(MULTI_CACHE)
 #error Unknown cache maintenance model
 #endif
 
+#ifndef __ASSEMBLER__
+static inline void nop_flush_icache_all(void) { }
+static inline void nop_flush_kern_cache_all(void) { }
+static inline void nop_flush_kern_cache_louis(void) { }
+static inline void nop_flush_user_cache_all(void) { }
+static inline void nop_flush_user_cache_range(unsigned long a, unsigned long b, unsigned int c) { }
+
+static inline void nop_coherent_kern_range(unsigned long a, unsigned long b) { }
+static inline int nop_coherent_user_range(unsigned long a, unsigned long b) { return 0; }
+static inline void nop_flush_kern_dcache_area(void *a, size_t s) { }
+
+static inline void nop_dma_flush_range(const void *a, const void *b) { }
+
+static inline void nop_dma_map_area(const void *s, size_t l, int f) { }
+static inline void nop_dma_unmap_area(const void *s, size_t l, int f) { }
+#endif
+
 #ifndef MULTI_CACHE
 #define __cpuc_flush_icache_all		__glue(_CACHE,_flush_icache_all)
 #define __cpuc_flush_kern_all		__glue(_CACHE,_flush_kern_cache_all)
diff --git a/arch/arm/include/asm/glue-df.h b/arch/arm/include/asm/glue-df.h
index 8cacbcd..1f2339c 100644
--- a/arch/arm/include/asm/glue-df.h
+++ b/arch/arm/include/asm/glue-df.h
@@ -95,6 +95,14 @@
 # endif
 #endif
 
+#ifdef CONFIG_CPU_ABRT_NOMMU
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER nommu_early_abort
+# endif
+#endif
+
 #ifndef CPU_DABORT_HANDLER
 #error Unknown data abort handler type
 #endif
diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h
index ac1dd54..f2f39bc 100644
--- a/arch/arm/include/asm/glue-proc.h
+++ b/arch/arm/include/asm/glue-proc.h
@@ -230,6 +230,15 @@
 # endif
 #endif
 
+#ifdef CONFIG_CPU_V7M
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_v7m
+# endif
+#endif
+
 #ifndef MULTI_CPU
 #define cpu_proc_init			__glue(CPU_NAME,_proc_init)
 #define cpu_proc_fin			__glue(CPU_NAME,_proc_fin)
diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h
index c4c87bc..3b2c40b 100644
--- a/arch/arm/include/asm/hardware/cache-l2x0.h
+++ b/arch/arm/include/asm/hardware/cache-l2x0.h
@@ -102,6 +102,10 @@
 
 #define L2X0_ADDR_FILTER_EN		1
 
+#define L2X0_CTRL_EN			1
+
+#define L2X0_WAY_SIZE_SHIFT		3
+
 #ifndef __ASSEMBLY__
 extern void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask);
 #if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_OF)
@@ -126,6 +130,7 @@ struct l2x0_regs {
 	unsigned long filter_end;
 	unsigned long prefetch_ctrl;
 	unsigned long pwr_ctrl;
+	unsigned long ctrl;
 };
 
 extern struct l2x0_regs l2x0_saved_regs;
diff --git a/arch/arm/include/asm/hardware/sp810.h b/arch/arm/include/asm/hardware/sp810.h
index 6b9b077..6636430 100644
--- a/arch/arm/include/asm/hardware/sp810.h
+++ b/arch/arm/include/asm/hardware/sp810.h
@@ -50,11 +50,7 @@
 #define SCPCELLID2		0xFF8
 #define SCPCELLID3		0xFFC
 
-#define SCCTRL_TIMEREN0SEL_REFCLK	(0 << 15)
-#define SCCTRL_TIMEREN0SEL_TIMCLK	(1 << 15)
-
-#define SCCTRL_TIMEREN1SEL_REFCLK	(0 << 17)
-#define SCCTRL_TIMEREN1SEL_TIMCLK	(1 << 17)
+#define SCCTRL_TIMERENnSEL_SHIFT(n)	(15 + ((n) * 2))
 
 static inline void sysctl_soft_reset(void __iomem *base)
 {
diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h
index e14af1a..2bebad3 100644
--- a/arch/arm/include/asm/hardware/vic.h
+++ b/arch/arm/include/asm/hardware/vic.h
@@ -47,7 +47,7 @@
 struct device_node;
 struct pt_regs;
 
-void __vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources,
+void __vic_init(void __iomem *base, int irq_start, u32 vic_sources,
 		u32 resume_sources, struct device_node *node);
 void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
 int vic_of_init(struct device_node *node, struct device_node *parent);
diff --git a/arch/arm/include/asm/hw_breakpoint.h b/arch/arm/include/asm/hw_breakpoint.h
index c190bc9..01169dd 100644
--- a/arch/arm/include/asm/hw_breakpoint.h
+++ b/arch/arm/include/asm/hw_breakpoint.h
@@ -98,12 +98,12 @@ static inline void decode_ctrl_reg(u32 reg,
 #define ARM_BASE_WCR		112
 
 /* Accessor macros for the debug registers. */
-#define ARM_DBG_READ(M, OP2, VAL) do {\
-	asm volatile("mrc p14, 0, %0, c0," #M ", " #OP2 : "=r" (VAL));\
+#define ARM_DBG_READ(N, M, OP2, VAL) do {\
+	asm volatile("mrc p14, 0, %0, " #N "," #M ", " #OP2 : "=r" (VAL));\
 } while (0)
 
-#define ARM_DBG_WRITE(M, OP2, VAL) do {\
-	asm volatile("mcr p14, 0, %0, c0," #M ", " #OP2 : : "r" (VAL));\
+#define ARM_DBG_WRITE(N, M, OP2, VAL) do {\
+	asm volatile("mcr p14, 0, %0, " #N "," #M ", " #OP2 : : "r" (VAL));\
 } while (0)
 
 struct notifier_block;
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 42f042e..652b560 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -374,7 +374,7 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
 
 #ifdef CONFIG_MMU
 #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
-extern int valid_phys_addr_range(unsigned long addr, size_t size);
+extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
 extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
 extern int devmem_is_allowed(unsigned long pfn);
 #endif
diff --git a/arch/arm/include/asm/irqflags.h b/arch/arm/include/asm/irqflags.h
index 1e6cca5..3b763d6 100644
--- a/arch/arm/include/asm/irqflags.h
+++ b/arch/arm/include/asm/irqflags.h
@@ -8,6 +8,16 @@
 /*
  * CPU interrupt mask handling.
  */
+#ifdef CONFIG_CPU_V7M
+#define IRQMASK_REG_NAME_R "primask"
+#define IRQMASK_REG_NAME_W "primask"
+#define IRQMASK_I_BIT	1
+#else
+#define IRQMASK_REG_NAME_R "cpsr"
+#define IRQMASK_REG_NAME_W "cpsr_c"
+#define IRQMASK_I_BIT	PSR_I_BIT
+#endif
+
 #if __LINUX_ARM_ARCH__ >= 6
 
 static inline unsigned long arch_local_irq_save(void)
@@ -15,7 +25,7 @@ static inline unsigned long arch_local_irq_save(void)
 	unsigned long flags;
 
 	asm volatile(
-		"	mrs	%0, cpsr	@ arch_local_irq_save\n"
+		"	mrs	%0, " IRQMASK_REG_NAME_R "	@ arch_local_irq_save\n"
 		"	cpsid	i"
 		: "=r" (flags) : : "memory", "cc");
 	return flags;
@@ -129,7 +139,7 @@ static inline unsigned long arch_local_save_flags(void)
 {
 	unsigned long flags;
 	asm volatile(
-		"	mrs	%0, cpsr	@ local_save_flags"
+		"	mrs	%0, " IRQMASK_REG_NAME_R "	@ local_save_flags"
 		: "=r" (flags) : : "memory", "cc");
 	return flags;
 }
@@ -140,7 +150,7 @@ static inline unsigned long arch_local_save_flags(void)
 static inline void arch_local_irq_restore(unsigned long flags)
 {
 	asm volatile(
-		"	msr	cpsr_c, %0	@ local_irq_restore"
+		"	msr	" IRQMASK_REG_NAME_W ", %0	@ local_irq_restore"
 		:
 		: "r" (flags)
 		: "memory", "cc");
@@ -148,8 +158,8 @@ static inline void arch_local_irq_restore(unsigned long flags)
 
 static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
-	return flags & PSR_I_BIT;
+	return flags & IRQMASK_I_BIT;
 }
 
-#endif
-#endif
+#endif /* ifdef __KERNEL__ */
+#endif /* ifndef __ASM_ARM_IRQFLAGS_H */
diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h
index 195ac2f..2fe141f 100644
--- a/arch/arm/include/asm/mach/map.h
+++ b/arch/arm/include/asm/mach/map.h
@@ -40,6 +40,13 @@ extern void iotable_init(struct map_desc *, int);
 extern void vm_reserve_area_early(unsigned long addr, unsigned long size,
 				  void *caller);
 
+#ifdef CONFIG_DEBUG_LL
+extern void debug_ll_addr(unsigned long *paddr, unsigned long *vaddr);
+extern void debug_ll_io_init(void);
+#else
+static inline void debug_ll_io_init(void) {}
+#endif
+
 struct mem_type;
 extern const struct mem_type *get_mem_type(unsigned int type);
 /*
diff --git a/arch/arm/include/asm/mach/serial_at91.h b/arch/arm/include/asm/mach/serial_at91.h
deleted file mode 100644
index ea6d063..0000000
--- a/arch/arm/include/asm/mach/serial_at91.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *  arch/arm/include/asm/mach/serial_at91.h
- *
- *  Based on serial_sa1100.h  by Nicolas Pitre
- *
- *  Copyright (C) 2002 ATMEL Rousset
- *
- *  Low level machine dependent UART functions.
- */
-
-struct uart_port;
-
-/*
- * This is a temporary structure for registering these
- * functions; it is intended to be discarded after boot.
- */
-struct atmel_port_fns {
-	void	(*set_mctrl)(struct uart_port *, u_int);
-	u_int	(*get_mctrl)(struct uart_port *);
-	void	(*enable_ms)(struct uart_port *);
-	void	(*pm)(struct uart_port *, u_int, u_int);
-	int	(*set_wake)(struct uart_port *, u_int);
-	int	(*open)(struct uart_port *);
-	void	(*close)(struct uart_port *);
-};
-
-#if defined(CONFIG_SERIAL_ATMEL)
-void atmel_register_uart_fns(struct atmel_port_fns *fns);
-#else
-#define atmel_register_uart_fns(fns) do { } while (0)
-#endif
-
-
diff --git a/arch/arm/include/asm/mach/serial_sa1100.h b/arch/arm/include/asm/mach/serial_sa1100.h
deleted file mode 100644
index d09064b..0000000
--- a/arch/arm/include/asm/mach/serial_sa1100.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  arch/arm/include/asm/mach/serial_sa1100.h
- *
- *  Author: Nicolas Pitre
- *
- * Moved and changed lots, Russell King
- *
- * Low level machine dependent UART functions.
- */
-
-struct uart_port;
-struct uart_info;
-
-/*
- * This is a temporary structure for registering these
- * functions; it is intended to be discarded after boot.
- */
-struct sa1100_port_fns {
-	void	(*set_mctrl)(struct uart_port *, u_int);
-	u_int	(*get_mctrl)(struct uart_port *);
-	void	(*pm)(struct uart_port *, u_int, u_int);
-	int	(*set_wake)(struct uart_port *, u_int);
-};
-
-#ifdef CONFIG_SERIAL_SA1100
-void sa1100_register_uart_fns(struct sa1100_port_fns *fns);
-void sa1100_register_uart(int idx, int port);
-#else
-#define sa1100_register_uart_fns(fns) do { } while (0)
-#define sa1100_register_uart(idx,port) do { } while (0)
-#endif
diff --git a/arch/arm/include/asm/mach/udc_pxa2xx.h b/arch/arm/include/asm/mach/udc_pxa2xx.h
deleted file mode 100644
index ea297ac..0000000
--- a/arch/arm/include/asm/mach/udc_pxa2xx.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * arch/arm/include/asm/mach/udc_pxa2xx.h
- *
- * This supports machine-specific differences in how the PXA2xx
- * USB Device Controller (UDC) is wired.
- *
- * It is set in linux/arch/arm/mach-pxa/<machine>.c or in
- * linux/arch/mach-ixp4xx/<machine>.c and used in
- * the probe routine of linux/drivers/usb/gadget/pxa2xx_udc.c
- */
-
-struct pxa2xx_udc_mach_info {
-        int  (*udc_is_connected)(void);		/* do we see host? */
-        void (*udc_command)(int cmd);
-#define	PXA2XX_UDC_CMD_CONNECT		0	/* let host see us */
-#define	PXA2XX_UDC_CMD_DISCONNECT	1	/* so host won't see us */
-
-	/* Boards following the design guidelines in the developer's manual,
-	 * with on-chip GPIOs not Lubbock's weird hardware, can have a sane
-	 * VBUS IRQ and omit the methods above.  Store the GPIO number
-	 * here.  Note that sometimes the signals go through inverters...
-	 */
-	bool	gpio_pullup_inverted;
-	int	gpio_pullup;			/* high == pullup activated */
-};
-
diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h
index 1496565..5b53b53 100644
--- a/arch/arm/include/asm/mmu.h
+++ b/arch/arm/include/asm/mmu.h
@@ -5,18 +5,15 @@
 
 typedef struct {
 #ifdef CONFIG_CPU_HAS_ASID
-	unsigned int id;
-	raw_spinlock_t id_lock;
+	u64 id;
 #endif
 	unsigned int kvm_seq;
 } mm_context_t;
 
 #ifdef CONFIG_CPU_HAS_ASID
-#define ASID(mm)	((mm)->context.id & 255)
-
-/* init_mm.context.id_lock should be initialized. */
-#define INIT_MM_CONTEXT(name)                                                 \
-	.context.id_lock    = __RAW_SPIN_LOCK_UNLOCKED(name.context.id_lock),
+#define ASID_BITS	8
+#define ASID_MASK	((~0ULL) << ASID_BITS)
+#define ASID(mm)	((mm)->context.id & ~ASID_MASK)
 #else
 #define ASID(mm)	(0)
 #endif
diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h
index 0306bc6..a64f61c 100644
--- a/arch/arm/include/asm/mmu_context.h
+++ b/arch/arm/include/asm/mmu_context.h
@@ -24,84 +24,8 @@ void __check_kvm_seq(struct mm_struct *mm);
 
 #ifdef CONFIG_CPU_HAS_ASID
 
-/*
- * On ARMv6, we have the following structure in the Context ID:
- *
- * 31                         7          0
- * +-------------------------+-----------+
- * |      process ID         |   ASID    |
- * +-------------------------+-----------+
- * |              context ID             |
- * +-------------------------------------+
- *
- * The ASID is used to tag entries in the CPU caches and TLBs.
- * The context ID is used by debuggers and trace logic, and
- * should be unique within all running processes.
- */
-#define ASID_BITS		8
-#define ASID_MASK		((~0) << ASID_BITS)
-#define ASID_FIRST_VERSION	(1 << ASID_BITS)
-
-extern unsigned int cpu_last_asid;
-
-void __init_new_context(struct task_struct *tsk, struct mm_struct *mm);
-void __new_context(struct mm_struct *mm);
-void cpu_set_reserved_ttbr0(void);
-
-static inline void switch_new_context(struct mm_struct *mm)
-{
-	unsigned long flags;
-
-	__new_context(mm);
-
-	local_irq_save(flags);
-	cpu_switch_mm(mm->pgd, mm);
-	local_irq_restore(flags);
-}
-
-static inline void check_and_switch_context(struct mm_struct *mm,
-					    struct task_struct *tsk)
-{
-	if (unlikely(mm->context.kvm_seq != init_mm.context.kvm_seq))
-		__check_kvm_seq(mm);
-
-	/*
-	 * Required during context switch to avoid speculative page table
-	 * walking with the wrong TTBR.
-	 */
-	cpu_set_reserved_ttbr0();
-
-	if (!((mm->context.id ^ cpu_last_asid) >> ASID_BITS))
-		/*
-		 * The ASID is from the current generation, just switch to the
-		 * new pgd. This condition is only true for calls from
-		 * context_switch() and interrupts are already disabled.
-		 */
-		cpu_switch_mm(mm->pgd, mm);
-	else if (irqs_disabled())
-		/*
-		 * Defer the new ASID allocation until after the context
-		 * switch critical region since __new_context() cannot be
-		 * called with interrupts disabled (it sends IPIs).
-		 */
-		set_ti_thread_flag(task_thread_info(tsk), TIF_SWITCH_MM);
-	else
-		/*
-		 * That is a direct call to switch_mm() or activate_mm() with
-		 * interrupts enabled and a new context.
-		 */
-		switch_new_context(mm);
-}
-
-#define init_new_context(tsk,mm)	(__init_new_context(tsk,mm),0)
-
-#define finish_arch_post_lock_switch \
-	finish_arch_post_lock_switch
-static inline void finish_arch_post_lock_switch(void)
-{
-	if (test_and_clear_thread_flag(TIF_SWITCH_MM))
-		switch_new_context(current->mm);
-}
+void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk);
+#define init_new_context(tsk,mm)	({ mm->context.id = 0; })
 
 #else	/* !CONFIG_CPU_HAS_ASID */
 
@@ -143,6 +67,7 @@ static inline void finish_arch_post_lock_switch(void)
 #endif	/* CONFIG_CPU_HAS_ASID */
 
 #define destroy_context(mm)		do { } while(0)
+#define activate_mm(prev,next)		switch_mm(prev, next, NULL)
 
 /*
  * This is called when "tsk" is about to enter lazy TLB mode.
@@ -186,6 +111,5 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
 }
 
 #define deactivate_mm(tsk,mm)	do { } while (0)
-#define activate_mm(prev,next)	switch_mm(prev, next, NULL)
 
 #endif
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h
index 625cd62..7558775 100644
--- a/arch/arm/include/asm/perf_event.h
+++ b/arch/arm/include/asm/perf_event.h
@@ -21,4 +21,11 @@
 #define C(_x)				PERF_COUNT_HW_CACHE_##_x
 #define CACHE_OP_UNSUPPORTED		0xFFFF
 
+#ifdef CONFIG_HW_PERF_EVENTS
+struct pt_regs;
+extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
+extern unsigned long perf_misc_flags(struct pt_regs *regs);
+#define perf_misc_flags(regs)	perf_misc_flags(regs)
+#endif
+
 #endif /* __ARM_PERF_EVENT_H__ */
diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h
index 2317a71..f97ee02 100644
--- a/arch/arm/include/asm/pgtable-2level.h
+++ b/arch/arm/include/asm/pgtable-2level.h
@@ -115,6 +115,7 @@
  * The PTE table pointer refers to the hardware entries; the "Linux"
  * entries are stored 1024 bytes below.
  */
+#define L_PTE_VALID		(_AT(pteval_t, 1) << 0)		/* Valid */
 #define L_PTE_PRESENT		(_AT(pteval_t, 1) << 0)
 #define L_PTE_YOUNG		(_AT(pteval_t, 1) << 1)
 #define L_PTE_FILE		(_AT(pteval_t, 1) << 2)	/* only when !PRESENT */
@@ -123,6 +124,7 @@
 #define L_PTE_USER		(_AT(pteval_t, 1) << 8)
 #define L_PTE_XN		(_AT(pteval_t, 1) << 9)
 #define L_PTE_SHARED		(_AT(pteval_t, 1) << 10)	/* shared(v6), coherent(xsc3) */
+#define L_PTE_NONE		(_AT(pteval_t, 1) << 11)
 
 /*
  * These are the memory types, defined to be compatible with
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index b249035..a3f3792 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -67,7 +67,8 @@
  * These bits overlap with the hardware bits but the naming is preserved for
  * consistency with the classic page table format.
  */
-#define L_PTE_PRESENT		(_AT(pteval_t, 3) << 0)		/* Valid */
+#define L_PTE_VALID		(_AT(pteval_t, 1) << 0)		/* Valid */
+#define L_PTE_PRESENT		(_AT(pteval_t, 3) << 0)		/* Present */
 #define L_PTE_FILE		(_AT(pteval_t, 1) << 2)		/* only when !PRESENT */
 #define L_PTE_USER		(_AT(pteval_t, 1) << 6)		/* AP[1] */
 #define L_PTE_RDONLY		(_AT(pteval_t, 1) << 7)		/* AP[2] */
@@ -76,6 +77,7 @@
 #define L_PTE_XN		(_AT(pteval_t, 1) << 54)	/* XN */
 #define L_PTE_DIRTY		(_AT(pteval_t, 1) << 55)	/* unused */
 #define L_PTE_SPECIAL		(_AT(pteval_t, 1) << 56)	/* unused */
+#define L_PTE_NONE		(_AT(pteval_t, 1) << 57)	/* PROT_NONE */
 
 /*
  * To be used in assembly code with the upper page attributes.
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 08c1231..9c82f98 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -73,7 +73,7 @@ extern pgprot_t		pgprot_kernel;
 
 #define _MOD_PROT(p, b)	__pgprot(pgprot_val(p) | (b))
 
-#define PAGE_NONE		_MOD_PROT(pgprot_user, L_PTE_XN | L_PTE_RDONLY)
+#define PAGE_NONE		_MOD_PROT(pgprot_user, L_PTE_XN | L_PTE_RDONLY | L_PTE_NONE)
 #define PAGE_SHARED		_MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_XN)
 #define PAGE_SHARED_EXEC	_MOD_PROT(pgprot_user, L_PTE_USER)
 #define PAGE_COPY		_MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY | L_PTE_XN)
@@ -83,7 +83,7 @@ extern pgprot_t		pgprot_kernel;
 #define PAGE_KERNEL		_MOD_PROT(pgprot_kernel, L_PTE_XN)
 #define PAGE_KERNEL_EXEC	pgprot_kernel
 
-#define __PAGE_NONE		__pgprot(_L_PTE_DEFAULT | L_PTE_RDONLY | L_PTE_XN)
+#define __PAGE_NONE		__pgprot(_L_PTE_DEFAULT | L_PTE_RDONLY | L_PTE_XN | L_PTE_NONE)
 #define __PAGE_SHARED		__pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_XN)
 #define __PAGE_SHARED_EXEC	__pgprot(_L_PTE_DEFAULT | L_PTE_USER)
 #define __PAGE_COPY		__pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY | L_PTE_XN)
@@ -203,9 +203,7 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
 #define pte_exec(pte)		(!(pte_val(pte) & L_PTE_XN))
 #define pte_special(pte)	(0)
 
-#define pte_present_user(pte) \
-	((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \
-	 (L_PTE_PRESENT | L_PTE_USER))
+#define pte_present_user(pte)  (pte_present(pte) && (pte_val(pte) & L_PTE_USER))
 
 #if __LINUX_ARM_ARCH__ < 6
 static inline void __sync_icache_dcache(pte_t pteval)
@@ -242,7 +240,7 @@ static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
-	const pteval_t mask = L_PTE_XN | L_PTE_RDONLY | L_PTE_USER;
+	const pteval_t mask = L_PTE_XN | L_PTE_RDONLY | L_PTE_USER | L_PTE_NONE;
 	pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
 	return pte;
 }
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index a26170d..f24edad 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -67,19 +67,19 @@ struct arm_pmu {
 	cpumask_t	active_irqs;
 	char		*name;
 	irqreturn_t	(*handle_irq)(int irq_num, void *dev);
-	void		(*enable)(struct hw_perf_event *evt, int idx);
-	void		(*disable)(struct hw_perf_event *evt, int idx);
+	void		(*enable)(struct perf_event *event);
+	void		(*disable)(struct perf_event *event);
 	int		(*get_event_idx)(struct pmu_hw_events *hw_events,
-					 struct hw_perf_event *hwc);
+					 struct perf_event *event);
 	int		(*set_event_filter)(struct hw_perf_event *evt,
 					    struct perf_event_attr *attr);
-	u32		(*read_counter)(int idx);
-	void		(*write_counter)(int idx, u32 val);
-	void		(*start)(void);
-	void		(*stop)(void);
+	u32		(*read_counter)(struct perf_event *event);
+	void		(*write_counter)(struct perf_event *event, u32 val);
+	void		(*start)(struct arm_pmu *);
+	void		(*stop)(struct arm_pmu *);
 	void		(*reset)(void *);
-	int		(*request_irq)(irq_handler_t handler);
-	void		(*free_irq)(void);
+	int		(*request_irq)(struct arm_pmu *, irq_handler_t handler);
+	void		(*free_irq)(struct arm_pmu *);
 	int		(*map_event)(struct perf_event *event);
 	int		num_events;
 	atomic_t	active_events;
@@ -93,15 +93,11 @@ struct arm_pmu {
 
 extern const struct dev_pm_ops armpmu_dev_pm_ops;
 
-int armpmu_register(struct arm_pmu *armpmu, char *name, int type);
+int armpmu_register(struct arm_pmu *armpmu, int type);
 
-u64 armpmu_event_update(struct perf_event *event,
-			struct hw_perf_event *hwc,
-			int idx);
+u64 armpmu_event_update(struct perf_event *event);
 
-int armpmu_event_set_period(struct perf_event *event,
-			    struct hw_perf_event *hwc,
-			    int idx);
+int armpmu_event_set_period(struct perf_event *event);
 
 int armpmu_map_event(struct perf_event *event,
 		     const unsigned (*event_map)[PERF_COUNT_HW_MAX],
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index 06e7d50..5e61b88 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -49,7 +49,14 @@ struct thread_struct {
 #ifdef CONFIG_MMU
 #define nommu_start_thread(regs) do { } while (0)
 #else
+#ifndef CONFIG_CPU_V7M
 #define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data
+#else
+#define nommu_start_thread(regs) do {					\
+	regs->ARM_r10 = current->mm->start_data;			\
+	regs->ARM_EXC_RET = 0xfffffffdL;				\
+} while (0)
+#endif
 #endif
 
 #define start_thread(regs,pc,sp)					\
diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h
index aeae9c6..a219227 100644
--- a/arch/arm/include/asm/prom.h
+++ b/arch/arm/include/asm/prom.h
@@ -11,10 +11,13 @@
 #ifndef __ASMARM_PROM_H
 #define __ASMARM_PROM_H
 
+#define HAVE_ARCH_DEVTREE_FIXUPS
+
 #ifdef CONFIG_OF
 
 extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
 extern void arm_dt_memblock_reserve(void);
+extern void __init arm_dt_init_cpu_maps(void);
 
 #else /* CONFIG_OF */
 
@@ -24,6 +27,7 @@ static inline struct machine_desc *setup_machine_fdt(unsigned int dt_phys)
 }
 
 static inline void arm_dt_memblock_reserve(void) { }
+static inline void arm_dt_init_cpu_maps(void) { }
 
 #endif /* CONFIG_OF */
 #endif /* ASMARM_PROM_H */
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 3d52ee1..67661e8 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -14,7 +14,11 @@
 
 #ifndef __ASSEMBLY__
 struct pt_regs {
+#ifdef CONFIG_CPU_V7M
+	unsigned long uregs[20];
+#else
 	unsigned long uregs[18];
+#endif
 };
 
 #define user_mode(regs)	\
@@ -45,6 +49,7 @@ struct pt_regs {
  */
 static inline int valid_user_regs(struct pt_regs *regs)
 {
+#ifndef CONFIG_CPU_V7M
 	unsigned long mode = regs->ARM_cpsr & MODE_MASK;
 
 	/*
@@ -67,6 +72,9 @@ static inline int valid_user_regs(struct pt_regs *regs)
 		regs->ARM_cpsr |= USR_MODE;
 
 	return 0;
+#else /* ifndef CONFIG_CPU_V7M */
+	return 1;
+#endif
 }
 
 static inline long regs_return_value(struct pt_regs *regs)
diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
index 5a7963d..9a0ea6a 100644
--- a/arch/arm/include/asm/signal.h
+++ b/arch/arm/include/asm/signal.h
@@ -35,5 +35,4 @@ struct k_sigaction {
 };
 
 #include <asm/sigcontext.h>
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
 #endif
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index 2e3be16..d3a22be 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -79,6 +79,7 @@ extern void cpu_die(void);
 
 extern void arch_send_call_function_single_ipi(int cpu);
 extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
+extern void arch_send_wakeup_ipi_mask(const struct cpumask *mask);
 
 struct smp_operations {
 #ifdef CONFIG_SMP
diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h
index 558d6c8..aaa61b6 100644
--- a/arch/arm/include/asm/smp_plat.h
+++ b/arch/arm/include/asm/smp_plat.h
@@ -5,6 +5,9 @@
 #ifndef __ASMARM_SMP_PLAT_H
 #define __ASMARM_SMP_PLAT_H
 
+#include <linux/cpumask.h>
+#include <linux/err.h>
+
 #include <asm/cputype.h>
 
 /*
@@ -48,5 +51,19 @@ static inline int cache_ops_need_broadcast(void)
  */
 extern int __cpu_logical_map[];
 #define cpu_logical_map(cpu)	__cpu_logical_map[cpu]
+/*
+ * Retrieve logical cpu index corresponding to a given MPIDR[23:0]
+ *  - mpidr: MPIDR[23:0] to be used for the look-up
+ *
+ * Returns the cpu logical index or -EINVAL on look-up error
+ */
+static inline int get_logical_index(u32 mpidr)
+{
+	int cpu;
+	for (cpu = 0; cpu < nr_cpu_ids; cpu++)
+		if (cpu_logical_map(cpu) == mpidr)
+			return cpu;
+	return -EINVAL;
+}
 
 #endif
diff --git a/arch/arm/include/asm/syscall.h b/arch/arm/include/asm/syscall.h
index 9fdded6..f1d96d4 100644
--- a/arch/arm/include/asm/syscall.h
+++ b/arch/arm/include/asm/syscall.h
@@ -7,6 +7,8 @@
 #ifndef _ASM_ARM_SYSCALL_H
 #define _ASM_ARM_SYSCALL_H
 
+#include <linux/audit.h> /* for AUDIT_ARCH_* */
+#include <linux/elf.h> /* for ELF_EM */
 #include <linux/err.h>
 #include <linux/sched.h>
 
@@ -95,4 +97,11 @@ static inline void syscall_set_arguments(struct task_struct *task,
 	memcpy(&regs->ARM_r0 + i, args, n * sizeof(args[0]));
 }
 
+static inline int syscall_get_arch(struct task_struct *task,
+				   struct pt_regs *regs)
+{
+	/* ARM tasks don't change audit architectures on the fly. */
+	return AUDIT_ARCH_ARM;
+}
+
 #endif /* _ASM_ARM_SYSCALL_H */
diff --git a/arch/arm/include/asm/system_info.h b/arch/arm/include/asm/system_info.h
index dfd386d..720ea03 100644
--- a/arch/arm/include/asm/system_info.h
+++ b/arch/arm/include/asm/system_info.h
@@ -11,6 +11,7 @@
 #define CPU_ARCH_ARMv5TEJ	7
 #define CPU_ARCH_ARMv6		8
 #define CPU_ARCH_ARMv7		9
+#define CPU_ARCH_ARMv7M		10
 
 #ifndef __ASSEMBLY__
 
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 8477b4c..cddda1f 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -151,10 +151,10 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
 #define TIF_SYSCALL_TRACE	8
 #define TIF_SYSCALL_AUDIT	9
 #define TIF_SYSCALL_TRACEPOINT	10
+#define TIF_SECCOMP		11	/* seccomp syscall filtering active */
 #define TIF_USING_IWMMXT	17
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK	20
-#define TIF_SECCOMP		21
 #define TIF_SWITCH_MM		22	/* deferred switch_mm */
 
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
@@ -163,11 +163,12 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
-#define _TIF_USING_IWMMXT	(1 << TIF_USING_IWMMXT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
+#define _TIF_USING_IWMMXT	(1 << TIF_USING_IWMMXT)
 
 /* Checks for any syscall work in entry-common.S */
-#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT)
+#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
+			   _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP)
 
 /*
  * Change these and you break ASM code in entry-common.S
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
index 8f60b6e..7cd13cc 100644
--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -42,6 +42,9 @@
 #define __ARCH_WANT_SYS_SOCKETCALL
 #endif
 #define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_CLONE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/arm/include/asm/xen/interface.h b/arch/arm/include/asm/xen/interface.h
index 5000397..1151188 100644
--- a/arch/arm/include/asm/xen/interface.h
+++ b/arch/arm/include/asm/xen/interface.h
@@ -49,6 +49,7 @@ DEFINE_GUEST_HANDLE(void);
 DEFINE_GUEST_HANDLE(uint64_t);
 DEFINE_GUEST_HANDLE(uint32_t);
 DEFINE_GUEST_HANDLE(xen_pfn_t);
+DEFINE_GUEST_HANDLE(xen_ulong_t);
 
 /* Maximum number of virtual CPUs in multi-processor guests. */
 #define MAX_VIRT_CPUS 1
diff --git a/arch/arm/include/debug/imx.S b/arch/arm/include/debug/imx.S
new file mode 100644
index 0000000..0c4e17d
--- /dev/null
+++ b/arch/arm/include/debug/imx.S
@@ -0,0 +1,74 @@
+/* arch/arm/mach-imx/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.
+ *
+ */
+#define IMX6Q_UART1_BASE_ADDR	0x02020000
+#define IMX6Q_UART2_BASE_ADDR	0x021e8000
+#define IMX6Q_UART3_BASE_ADDR	0x021ec000
+#define IMX6Q_UART4_BASE_ADDR	0x021f0000
+#define IMX6Q_UART5_BASE_ADDR	0x021f4000
+
+/*
+ * IMX6Q_UART_BASE_ADDR is put in the middle to force the expansion
+ * of IMX6Q_UART##n##_BASE_ADDR.
+ */
+#define IMX6Q_UART_BASE_ADDR(n)	IMX6Q_UART##n##_BASE_ADDR
+#define IMX6Q_UART_BASE(n)	IMX6Q_UART_BASE_ADDR(n)
+#define IMX6Q_DEBUG_UART_BASE	IMX6Q_UART_BASE(CONFIG_DEBUG_IMX6Q_UART_PORT)
+
+#ifdef CONFIG_DEBUG_IMX1_UART
+#define UART_PADDR	0x00206000
+#elif defined (CONFIG_DEBUG_IMX25_UART)
+#define UART_PADDR	0x43f90000
+#elif defined (CONFIG_DEBUG_IMX21_IMX27_UART)
+#define UART_PADDR	0x1000a000
+#elif defined (CONFIG_DEBUG_IMX31_IMX35_UART)
+#define UART_PADDR	0x43f90000
+#elif defined (CONFIG_DEBUG_IMX51_UART)
+#define UART_PADDR	0x73fbc000
+#elif defined (CONFIG_DEBUG_IMX50_IMX53_UART)
+#define UART_PADDR	0x53fbc000
+#elif defined (CONFIG_DEBUG_IMX6Q_UART)
+#define UART_PADDR	IMX6Q_DEBUG_UART_BASE
+#endif
+
+/*
+ * FIXME: This is a copy of IMX_IO_P2V in hardware.h, and needs to
+ * stay sync with that.  It's hard to maintain, and should be fixed
+ * globally for multi-platform build to use a fixed virtual address
+ * for low-level debug uart port across platforms.
+ */
+#define IMX_IO_P2V(x)	(						\
+			(((x) & 0x80000000) >> 7) |			\
+			(0xf4000000 +					\
+			(((x) & 0x50000000) >> 6) +			\
+			(((x) & 0x0b000000) >> 4) +			\
+			(((x) & 0x000fffff))))
+
+#define UART_VADDR	IMX_IO_P2V(UART_PADDR)
+
+		.macro	addruart, rp, rv, tmp
+		ldr	\rp, =UART_PADDR	@ physical
+		ldr	\rv, =UART_VADDR	@ virtual
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #0x40]	@ TXDATA
+		.endm
+
+		.macro	waituart,rd,rx
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldr	\rd, [\rx, #0x98]	@ SR2
+		tst	\rd, #1 << 3		@ TXDC
+		beq	1002b			@ wait until transmit done
+		.endm
diff --git a/arch/arm/include/debug/sunxi.S b/arch/arm/include/debug/sunxi.S
new file mode 100644
index 0000000..04eb56d
--- /dev/null
+++ b/arch/arm/include/debug/sunxi.S
@@ -0,0 +1,27 @@
+/*
+ * Early serial output macro for Allwinner A1X SoCs
+ *
+ * Copyright (C) 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 version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#if defined(CONFIG_DEBUG_SUNXI_UART0)
+#define SUNXI_UART_DEBUG_PHYS_BASE 0x01c28000
+#define SUNXI_UART_DEBUG_VIRT_BASE 0xf1c28000
+#elif defined(CONFIG_DEBUG_SUNXI_UART1)
+#define SUNXI_UART_DEBUG_PHYS_BASE 0x01c28400
+#define SUNXI_UART_DEBUG_VIRT_BASE 0xf1c28400
+#endif
+
+	.macro	addruart, rp, rv, tmp
+	ldr	\rp, =SUNXI_UART_DEBUG_PHYS_BASE
+	ldr	\rv, =SUNXI_UART_DEBUG_VIRT_BASE
+	.endm
+
+#define UART_SHIFT	2
+#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/include/debug/tegra.S b/arch/arm/include/debug/tegra.S
new file mode 100644
index 0000000..883d7c2
--- /dev/null
+++ b/arch/arm/include/debug/tegra.S
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2010,2011 Google, Inc.
+ * Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *	Erik Gilling <konkers@google.com>
+ *	Doug Anderson <dianders@chromium.org>
+ *	Stephen Warren <swarren@nvidia.com>
+ *
+ * Portions based on mach-omap2's debug-macro.S
+ * Copyright (C) 1994-1999 Russell King
+ *
+ * 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/serial_reg.h>
+
+#define UART_SHIFT 2
+
+/* Physical addresses */
+#define TEGRA_CLK_RESET_BASE		0x60006000
+#define TEGRA_APB_MISC_BASE		0x70000000
+#define TEGRA_UARTA_BASE		0x70006000
+#define TEGRA_UARTB_BASE		0x70006040
+#define TEGRA_UARTC_BASE		0x70006200
+#define TEGRA_UARTD_BASE		0x70006300
+#define TEGRA_UARTE_BASE		0x70006400
+#define TEGRA_PMC_BASE			0x7000e400
+
+#define TEGRA_CLK_RST_DEVICES_L		(TEGRA_CLK_RESET_BASE + 0x04)
+#define TEGRA_CLK_RST_DEVICES_H		(TEGRA_CLK_RESET_BASE + 0x08)
+#define TEGRA_CLK_RST_DEVICES_U		(TEGRA_CLK_RESET_BASE + 0x0c)
+#define TEGRA_CLK_OUT_ENB_L		(TEGRA_CLK_RESET_BASE + 0x10)
+#define TEGRA_CLK_OUT_ENB_H		(TEGRA_CLK_RESET_BASE + 0x14)
+#define TEGRA_CLK_OUT_ENB_U		(TEGRA_CLK_RESET_BASE + 0x18)
+#define TEGRA_PMC_SCRATCH20		(TEGRA_PMC_BASE + 0xa0)
+#define TEGRA_APB_MISC_GP_HIDREV	(TEGRA_APB_MISC_BASE + 0x804)
+
+/*
+ * Must be 1MB-aligned since a 1MB mapping is used early on.
+ * Must not overlap with regions in mach-tegra/io.c:tegra_io_desc[].
+ */
+#define UART_VIRTUAL_BASE		0xfe100000
+
+#define checkuart(rp, rv, lhu, bit, uart) \
+		/* Load address of CLK_RST register */ \
+		movw	rp, #TEGRA_CLK_RST_DEVICES_##lhu & 0xffff ; \
+		movt	rp, #TEGRA_CLK_RST_DEVICES_##lhu >> 16 ; \
+		/* Load value from CLK_RST register */ \
+		ldr	rp, [rp, #0] ; \
+		/* Test UART's reset bit */ \
+		tst	rp, #(1 << bit) ; \
+		/* If set, can't use UART; jump to save no UART */ \
+		bne	90f ; \
+		/* Load address of CLK_OUT_ENB register */ \
+		movw	rp, #TEGRA_CLK_OUT_ENB_##lhu & 0xffff ; \
+		movt	rp, #TEGRA_CLK_OUT_ENB_##lhu >> 16 ; \
+		/* Load value from CLK_OUT_ENB register */ \
+		ldr	rp, [rp, #0] ; \
+		/* Test UART's clock enable bit */ \
+		tst	rp, #(1 << bit) ; \
+		/* If clear, can't use UART; jump to save no UART */ \
+		beq	90f ; \
+		/* Passed all tests, load address of UART registers */ \
+		movw	rp, #TEGRA_UART##uart##_BASE & 0xffff ; \
+		movt	rp, #TEGRA_UART##uart##_BASE >> 16 ; \
+		/* Jump to save UART address */ \
+		b 91f
+
+		.macro  addruart, rp, rv, tmp
+		adr	\rp, 99f		@ actual addr of 99f
+		ldr	\rv, [\rp]		@ linked addr is stored there
+		sub	\rv, \rv, \rp		@ offset between the two
+		ldr	\rp, [\rp, #4]		@ linked tegra_uart_config
+		sub	\tmp, \rp, \rv		@ actual tegra_uart_config
+		ldr	\rp, [\tmp]		@ Load tegra_uart_config
+		cmp	\rp, #1			@ needs initialization?
+		bne	100f			@ no; go load the addresses
+		mov	\rv, #0			@ yes; record init is done
+		str	\rv, [\tmp]
+
+#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA
+		/* Check ODMDATA */
+10:		movw	\rp, #TEGRA_PMC_SCRATCH20 & 0xffff
+		movt	\rp, #TEGRA_PMC_SCRATCH20 >> 16
+		ldr	\rp, [\rp, #0]		@ Load PMC_SCRATCH20
+		ubfx	\rv, \rp, #18, #2	@ 19:18 are console type
+		cmp	\rv, #2			@ 2 and 3 mean DCC, UART
+		beq	11f			@ some boards swap the meaning
+		cmp	\rv, #3			@ so accept either
+		bne	90f
+11:		ubfx	\rv, \rp, #15, #3	@ 17:15 are UART ID
+		cmp	\rv, #0			@ UART 0?
+		beq	20f
+		cmp	\rv, #1			@ UART 1?
+		beq	21f
+		cmp	\rv, #2			@ UART 2?
+		beq	22f
+		cmp	\rv, #3			@ UART 3?
+		beq	23f
+		cmp	\rv, #4			@ UART 4?
+		beq	24f
+		b	90f			@ invalid
+#endif
+
+#if defined(CONFIG_TEGRA_DEBUG_UARTA) || \
+    defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
+		/* Check UART A validity */
+20:		checkuart(\rp, \rv, L, 6, A)
+#endif
+
+#if defined(CONFIG_TEGRA_DEBUG_UARTB) || \
+    defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
+		/* Check UART B validity */
+21:		checkuart(\rp, \rv, L, 7, B)
+#endif
+
+#if defined(CONFIG_TEGRA_DEBUG_UARTC) || \
+    defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
+		/* Check UART C validity */
+22:		checkuart(\rp, \rv, H, 23, C)
+#endif
+
+#if defined(CONFIG_TEGRA_DEBUG_UARTD) || \
+    defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
+		/* Check UART D validity */
+23:		checkuart(\rp, \rv, U, 1, D)
+#endif
+
+#if defined(CONFIG_TEGRA_DEBUG_UARTE) || \
+    defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
+		/* Check UART E validity */
+24:
+		checkuart(\rp, \rv, U, 2, E)
+#endif
+
+		/* No valid UART found */
+90:		mov	\rp, #0
+		/* fall through */
+
+		/* Record whichever UART we chose */
+91:		str	\rp, [\tmp, #4]		@ Store in tegra_uart_phys
+		cmp	\rp, #0			@ Valid UART address?
+		bne	92f			@ Yes, go process it
+		str	\rp, [\tmp, #8]		@ Store 0 in tegra_uart_virt
+		b	100f			@ Done
+92:		and	\rv, \rp, #0xffffff	@ offset within 1MB section
+		add	\rv, \rv, #UART_VIRTUAL_BASE
+		str	\rv, [\tmp, #8]		@ Store in tegra_uart_virt
+		movw	\rv, #TEGRA_APB_MISC_GP_HIDREV & 0xffff
+		movt	\rv, #TEGRA_APB_MISC_GP_HIDREV >> 16
+		ldr	\rv, [\rv, #0]		@ Load HIDREV
+		ubfx	\rv, \rv, #8, #8	@ 15:8 are SoC version
+		cmp	\rv, #0x20		@ Tegra20?
+		moveq	\rv, #0x75		@ Tegra20 divisor
+		movne	\rv, #0xdd		@ Tegra30 divisor
+		str	\rv, [\tmp, #12]	@ Save divisor to scratch
+		/* uart[UART_LCR] = UART_LCR_WLEN8 | UART_LCR_DLAB; */
+		mov	\rv, #UART_LCR_WLEN8 | UART_LCR_DLAB
+		str	\rv, [\rp, #UART_LCR << UART_SHIFT]
+		/* uart[UART_DLL] = div & 0xff; */
+		ldr	\rv, [\tmp, #12]
+		and	\rv, \rv, #0xff
+		str	\rv, [\rp, #UART_DLL << UART_SHIFT]
+		/* uart[UART_DLM] = div >> 8; */
+		ldr	\rv, [\tmp, #12]
+		lsr	\rv, \rv, #8
+		str	\rv, [\rp, #UART_DLM << UART_SHIFT]
+		/* uart[UART_LCR] = UART_LCR_WLEN8; */
+		mov	\rv, #UART_LCR_WLEN8
+		str	\rv, [\rp, #UART_LCR << UART_SHIFT]
+		b	100f
+
+		.align
+99:		.word	.
+		.word	tegra_uart_config
+		.ltorg
+
+		/* Load previously selected UART address */
+100:		ldr	\rp, [\tmp, #4]		@ Load tegra_uart_phys
+		ldr	\rv, [\tmp, #8]		@ Load tegra_uart_virt
+		.endm
+
+/*
+ * Code below is swiped from <asm/hardware/debug-8250.S>, but add an extra
+ * check to make sure that the UART address is actually valid.
+ */
+
+		.macro	senduart, rd, rx
+		cmp	\rx, #0
+		strneb	\rd, [\rx, #UART_TX << UART_SHIFT]
+1001:
+		.endm
+
+		.macro	busyuart, rd, rx
+		cmp	\rx, #0
+		beq	1002f
+1001:		ldrb	\rd, [\rx, #UART_LSR << UART_SHIFT]
+		and	\rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
+		teq	\rd, #UART_LSR_TEMT | UART_LSR_THRE
+		bne	1001b
+1002:
+		.endm
+
+		.macro	waituart, rd, rx
+#ifdef FLOW_CONTROL
+		cmp	\rx, #0
+		beq	1002f
+1001:		ldrb	\rd, [\rx, #UART_MSR << UART_SHIFT]
+		tst	\rd, #UART_MSR_CTS
+		beq	1001b
+1002:
+#endif
+		.endm
diff --git a/arch/arm/include/debug/vexpress.S b/arch/arm/include/debug/vexpress.S
index 9f509f5..dc8e882 100644
--- a/arch/arm/include/debug/vexpress.S
+++ b/arch/arm/include/debug/vexpress.S
@@ -21,14 +21,17 @@
 #if defined(CONFIG_DEBUG_VEXPRESS_UART0_DETECT)
 
 		.macro	addruart,rp,rv,tmp
+		.arch   armv7-a
 
 		@ Make an educated guess regarding the memory map:
-		@ - the original A9 core tile, which has MPCore peripherals
-		@   located at 0x1e000000, should use UART at 0x10009000
+		@ - the original A9 core tile (based on ARM Cortex-A9 r0p1)
+		@   should use UART at 0x10009000
 		@ - all other (RS1 complaint) tiles use UART mapped
 		@   at 0x1c090000
-		mrc	p15, 4, \tmp, c15, c0, 0
-		cmp	\tmp, #0x1e000000
+		mrc	p15, 0, \rp, c0, c0, 0
+		movw	\rv, #0xc091
+		movt	\rv, #0x410f
+		cmp	\rp, \rv
 
 		@ Original memory map
 		moveq	\rp, #DEBUG_LL_UART_OFFSET
diff --git a/arch/arm/include/debug/zynq.S b/arch/arm/include/debug/zynq.S
new file mode 100644
index 0000000..f9aa974
--- /dev/null
+++ b/arch/arm/include/debug/zynq.S
@@ -0,0 +1,51 @@
+/*
+ * Debugging macro include header
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * 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.
+ */
+#define UART_CR_OFFSET		0x00  /* Control Register [8:0] */
+#define UART_SR_OFFSET		0x2C  /* Channel Status [11:0] */
+#define UART_FIFO_OFFSET	0x30  /* FIFO [15:0] or [7:0] */
+
+#define UART_SR_TXFULL		0x00000010	/* TX FIFO full */
+#define UART_SR_TXEMPTY		0x00000008	/* TX FIFO empty */
+
+#define UART0_PHYS		0xE0000000
+#define UART1_PHYS		0xE0001000
+#define UART_SIZE		SZ_4K
+#define UART_VIRT		0xF0001000
+
+#if IS_ENABLED(CONFIG_DEBUG_ZYNQ_UART1)
+# define LL_UART_PADDR		UART1_PHYS
+#else
+# define LL_UART_PADDR		UART0_PHYS
+#endif
+
+#define LL_UART_VADDR		UART_VIRT
+
+		.macro	addruart, rp, rv, tmp
+		ldr	\rp, =LL_UART_PADDR	@ physical
+		ldr	\rv, =LL_UART_VADDR	@ virtual
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #UART_FIFO_OFFSET]	@ TXDATA
+		.endm
+
+		.macro	waituart,rd,rx
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldr	\rd, [\rx, #UART_SR_OFFSET]	@ get status register
+		tst	\rd, #UART_SR_TXFULL		@
+		bne	1002b			@ wait if FIFO is full
+		.endm
diff --git a/arch/arm/include/uapi/asm/ptrace.h b/arch/arm/include/uapi/asm/ptrace.h
index 96ee092..2ae7d1b 100644
--- a/arch/arm/include/uapi/asm/ptrace.h
+++ b/arch/arm/include/uapi/asm/ptrace.h
@@ -34,28 +34,47 @@
 
 /*
  * PSR bits
+ * Note on V7M there is no mode contained in the PSR
  */
 #define USR26_MODE	0x00000000
 #define FIQ26_MODE	0x00000001
 #define IRQ26_MODE	0x00000002
 #define SVC26_MODE	0x00000003
+#if defined(__KERNEL__) && defined(CONFIG_CPU_V7M)
+/*
+ * Use 0 here to get code right that creates a userspace
+ * or kernel space thread.
+ */
+#define USR_MODE	0x00000000
+#define SVC_MODE	0x00000000
+#else
 #define USR_MODE	0x00000010
+#define SVC_MODE	0x00000013
+#endif
 #define FIQ_MODE	0x00000011
 #define IRQ_MODE	0x00000012
-#define SVC_MODE	0x00000013
 #define ABT_MODE	0x00000017
 #define HYP_MODE	0x0000001a
 #define UND_MODE	0x0000001b
 #define SYSTEM_MODE	0x0000001f
 #define MODE32_BIT	0x00000010
 #define MODE_MASK	0x0000001f
-#define PSR_T_BIT	0x00000020
-#define PSR_F_BIT	0x00000040
-#define PSR_I_BIT	0x00000080
-#define PSR_A_BIT	0x00000100
-#define PSR_E_BIT	0x00000200
-#define PSR_J_BIT	0x01000000
-#define PSR_Q_BIT	0x08000000
+
+#define V4_PSR_T_BIT	0x00000020	/* >= V4T, but not V7M */
+#define V7M_PSR_T_BIT	0x01000000
+#if defined(__KERNEL__) && defined(CONFIG_CPU_V7M)
+#define PSR_T_BIT	V7M_PSR_T_BIT
+#else
+/* for compatibility */
+#define PSR_T_BIT	V4_PSR_T_BIT
+#endif
+
+#define PSR_F_BIT	0x00000040	/* >= V4, but not V7M */
+#define PSR_I_BIT	0x00000080	/* >= V4, but not V7M */
+#define PSR_A_BIT	0x00000100	/* >= V6, but not V7M */
+#define PSR_E_BIT	0x00000200	/* >= V6, but not V7M */
+#define PSR_J_BIT	0x01000000	/* >= V5J, but not V7M */
+#define PSR_Q_BIT	0x08000000	/* >= V5E, including V7M */
 #define PSR_V_BIT	0x10000000
 #define PSR_C_BIT	0x20000000
 #define PSR_Z_BIT	0x40000000
@@ -125,6 +144,7 @@ struct pt_regs {
 #define ARM_r1		uregs[1]
 #define ARM_r0		uregs[0]
 #define ARM_ORIG_r0	uregs[17]
+#define ARM_EXC_RET    uregs[18]
 
 /*
  * The size of the user-visible VFP state as seen by PTRACE_GET/SETVFPREGS
diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h
index ac03bdb..4da7cde 100644
--- a/arch/arm/include/uapi/asm/unistd.h
+++ b/arch/arm/include/uapi/asm/unistd.h
@@ -405,6 +405,7 @@
 #define __NR_process_vm_readv		(__NR_SYSCALL_BASE+376)
 #define __NR_process_vm_writev		(__NR_SYSCALL_BASE+377)
 					/* 378 for kcmp */
+#define __NR_finit_module		(__NR_SYSCALL_BASE+379)
 
 /*
  * This may need to be greater than __NR_last_syscall+1 in order to
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index c985b48..5fe9ace 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -93,6 +93,9 @@ int main(void)
   DEFINE(S_PC,			offsetof(struct pt_regs, ARM_pc));
   DEFINE(S_PSR,			offsetof(struct pt_regs, ARM_cpsr));
   DEFINE(S_OLD_R0,		offsetof(struct pt_regs, ARM_ORIG_r0));
+#ifdef CONFIG_CPU_V7M
+  DEFINE(S_EXC_RET,		offsetof(struct pt_regs, ARM_EXC_RET));
+#endif
   DEFINE(S_FRAME_SIZE,		sizeof(struct pt_regs));
   BLANK();
 #ifdef CONFIG_CACHE_L2X0
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 831cd38..a4fda4e 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -11,7 +11,7 @@
  */
 /* 0 */		CALL(sys_restart_syscall)
 		CALL(sys_exit)
-		CALL(sys_fork_wrapper)
+		CALL(sys_fork)
 		CALL(sys_read)
 		CALL(sys_write)
 /* 5 */		CALL(sys_open)
@@ -129,7 +129,7 @@
 		CALL(OBSOLETE(ABI(sys_ipc, sys_oabi_ipc)))
 		CALL(sys_fsync)
 		CALL(sys_sigreturn_wrapper)
-/* 120 */	CALL(sys_clone_wrapper)
+/* 120 */	CALL(sys_clone)
 		CALL(sys_setdomainname)
 		CALL(sys_newuname)
 		CALL(sys_ni_syscall)		/* modify_ldt */
@@ -199,7 +199,7 @@
 		CALL(sys_sendfile)
 		CALL(sys_ni_syscall)		/* getpmsg */
 		CALL(sys_ni_syscall)		/* putpmsg */
-/* 190 */	CALL(sys_vfork_wrapper)
+/* 190 */	CALL(sys_vfork)
 		CALL(sys_getrlimit)
 		CALL(sys_mmap2)
 		CALL(ABI(sys_truncate64, sys_oabi_truncate64))
@@ -388,6 +388,7 @@
 		CALL(sys_process_vm_readv)
 		CALL(sys_process_vm_writev)
 		CALL(sys_ni_syscall)	/* reserved for sys_kcmp */
+		CALL(sys_finit_module)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index 66f711b..6809200 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -100,6 +100,13 @@ ENTRY(printch)
 		b	1b
 ENDPROC(printch)
 
+ENTRY(debug_ll_addr)
+		addruart r2, r3, ip
+		str	r2, [r0]
+		str	r3, [r1]
+		mov	pc, lr
+ENDPROC(debug_ll_addr)
+
 #else
 
 ENTRY(printascii)
@@ -119,4 +126,11 @@ ENTRY(printch)
 		mov	pc, lr
 ENDPROC(printch)
 
+ENTRY(debug_ll_addr)
+		mov	r2, #0
+		str	r2, [r0]
+		str	r2, [r1]
+		mov	pc, lr
+ENDPROC(debug_ll_addr)
+
 #endif
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index bee7f9d..70f1bde 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -19,8 +19,10 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
+#include <asm/cputype.h>
 #include <asm/setup.h>
 #include <asm/page.h>
+#include <asm/smp_plat.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
@@ -61,6 +63,108 @@ void __init arm_dt_memblock_reserve(void)
 	}
 }
 
+/*
+ * arm_dt_init_cpu_maps - Function retrieves cpu nodes from the device tree
+ * and builds the cpu logical map array containing MPIDR values related to
+ * logical cpus
+ *
+ * Updates the cpu possible mask with the number of parsed cpu nodes
+ */
+void __init arm_dt_init_cpu_maps(void)
+{
+	/*
+	 * Temp logical map is initialized with UINT_MAX values that are
+	 * considered invalid logical map entries since the logical map must
+	 * contain a list of MPIDR[23:0] values where MPIDR[31:24] must
+	 * read as 0.
+	 */
+	struct device_node *cpu, *cpus;
+	u32 i, j, cpuidx = 1;
+	u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0;
+
+	u32 tmp_map[NR_CPUS] = { [0 ... NR_CPUS-1] = UINT_MAX };
+	bool bootcpu_valid = false;
+	cpus = of_find_node_by_path("/cpus");
+
+	if (!cpus)
+		return;
+
+	for_each_child_of_node(cpus, cpu) {
+		u32 hwid;
+
+		pr_debug(" * %s...\n", cpu->full_name);
+		/*
+		 * A device tree containing CPU nodes with missing "reg"
+		 * properties is considered invalid to build the
+		 * cpu_logical_map.
+		 */
+		if (of_property_read_u32(cpu, "reg", &hwid)) {
+			pr_debug(" * %s missing reg property\n",
+				     cpu->full_name);
+			return;
+		}
+
+		/*
+		 * 8 MSBs must be set to 0 in the DT since the reg property
+		 * defines the MPIDR[23:0].
+		 */
+		if (hwid & ~MPIDR_HWID_BITMASK)
+			return;
+
+		/*
+		 * Duplicate MPIDRs are a recipe for disaster.
+		 * Scan all initialized entries and check for
+		 * duplicates. If any is found just bail out.
+		 * temp values were initialized to UINT_MAX
+		 * to avoid matching valid MPIDR[23:0] values.
+		 */
+		for (j = 0; j < cpuidx; j++)
+			if (WARN(tmp_map[j] == hwid, "Duplicate /cpu reg "
+						     "properties in the DT\n"))
+				return;
+
+		/*
+		 * Build a stashed array of MPIDR values. Numbering scheme
+		 * requires that if detected the boot CPU must be assigned
+		 * logical id 0. Other CPUs get sequential indexes starting
+		 * from 1. If a CPU node with a reg property matching the
+		 * boot CPU MPIDR is detected, this is recorded so that the
+		 * logical map built from DT is validated and can be used
+		 * to override the map created in smp_setup_processor_id().
+		 */
+		if (hwid == mpidr) {
+			i = 0;
+			bootcpu_valid = true;
+		} else {
+			i = cpuidx++;
+		}
+
+		if (WARN(cpuidx > nr_cpu_ids, "DT /cpu %u nodes greater than "
+					       "max cores %u, capping them\n",
+					       cpuidx, nr_cpu_ids)) {
+			cpuidx = nr_cpu_ids;
+			break;
+		}
+
+		tmp_map[i] = hwid;
+	}
+
+	if (WARN(!bootcpu_valid, "DT missing boot CPU MPIDR[23:0], "
+				 "fall back to default cpu_logical_map\n"))
+		return;
+
+	/*
+	 * Since the boot CPU node contains proper data, and all nodes have
+	 * a reg property, the DT CPU list can be considered valid and the
+	 * logical map created in smp_setup_processor_id() can be overridden
+	 */
+	for (i = 0; i < cpuidx; i++) {
+		set_cpu_possible(i, true);
+		cpu_logical_map(i) = tmp_map[i];
+		pr_debug("cpu logical map 0x%x\n", cpu_logical_map(i));
+	}
+}
+
 /**
  * setup_machine_fdt - Machine setup when an dtb was passed to the kernel
  * @dt_phys: physical address of dt blob
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 3471175..7fc4872 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -339,6 +339,9 @@ ENDPROC(ftrace_stub)
 
 	.align	5
 ENTRY(vector_swi)
+#ifdef CONFIG_CPU_V7M
+	v7m_exception_entry
+#else
 	sub	sp, sp, #S_FRAME_SIZE
 	stmia	sp, {r0 - r12}			@ Calling r0 - r12
  ARM(	add	r8, sp, #S_PC		)
@@ -349,6 +352,7 @@ ENTRY(vector_swi)
 	str	lr, [sp, #S_PC]			@ Save calling PC
 	str	r8, [sp, #S_PSR]		@ Save CPSR
 	str	r0, [sp, #S_OLD_R0]		@ Save OLD_R0
+#endif
 	zero_fp
 
 	/*
@@ -417,16 +421,6 @@ local_restart:
 	ldr	r10, [tsk, #TI_FLAGS]		@ check for syscall tracing
 	stmdb	sp!, {r4, r5}			@ push fifth and sixth args
 
-#ifdef CONFIG_SECCOMP
-	tst	r10, #_TIF_SECCOMP
-	beq	1f
-	mov	r0, scno
-	bl	__secure_computing	
-	add	r0, sp, #S_R0 + S_OFF		@ pointer to regs
-	ldmia	r0, {r0 - r3}			@ have to reload r0 - r3
-1:
-#endif
-
 	tst	r10, #_TIF_SYSCALL_WORK		@ are we tracing syscalls?
 	bne	__sys_trace
 
@@ -458,7 +452,10 @@ __sys_trace:
 	ldmccia	r1, {r0 - r6}			@ have to reload r0 - r6
 	stmccia	sp, {r4, r5}			@ and update the stack args
 	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine
-	b	2b
+	cmp	scno, #-1			@ skip the syscall?
+	bne	2b
+	add	sp, sp, #S_OFF			@ restore stack
+	b	ret_slow_syscall
 
 __sys_trace_return:
 	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
@@ -510,22 +507,6 @@ sys_syscall:
 		b	sys_ni_syscall
 ENDPROC(sys_syscall)
 
-sys_fork_wrapper:
-		add	r0, sp, #S_OFF
-		b	sys_fork
-ENDPROC(sys_fork_wrapper)
-
-sys_vfork_wrapper:
-		add	r0, sp, #S_OFF
-		b	sys_vfork
-ENDPROC(sys_vfork_wrapper)
-
-sys_clone_wrapper:
-		add	ip, sp, #S_OFF
-		str	ip, [sp, #4]
-		b	sys_clone
-ENDPROC(sys_clone_wrapper)
-
 sys_sigreturn_wrapper:
 		add	r0, sp, #S_OFF
 		mov	why, #0		@ prevent syscall restart handling
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 9a8531e..33d9900 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -44,6 +44,145 @@
 #endif
 	.endm
 
+#ifdef CONFIG_CPU_V7M
+/*
+ * ARMv7-M exception entry/exit macros.
+ *
+ * xPSR, ReturnAddress(), LR (R14), R12, R3, R2, R1, and R0 are
+ * automatically saved on the current stack (32 words) before
+ * switching to the exception stack (SP_main).
+ *
+ * If exception is taken while in user mode, SP_main is
+ * empty. Otherwise, SP_main is aligned to 64 bit automatically
+ * (CCR.STKALIGN set).
+ *
+ * Linux assumes that the interrupts are disabled when entering an
+ * exception handler and it may BUG if this is not the case. Interrupts
+ * are disabled during entry and reenabled in the exit macro.
+ *
+ * v7m_exception_fast_exit is used when returning from interrupts.
+ *
+ * v7m_exception_slow_exit is used when returning from SVC or PendSV.
+ * When returning to kernel mode, we don't return from exception.
+ */
+	.macro	v7m_exception_entry
+	@ determine the location of the registers saved by the core during
+	@ exception entry. Depending on the mode the cpu was in when the
+	@ exception happend that is either on the main or the process stack.
+	@ Bit 2 of EXC_RETURN stored in the lr register specifies which stack
+	@ was used.
+	tst	lr, #0x4
+	mrsne	r12, psp
+	moveq	r12, sp
+
+	@ we cannot rely on r0-r3 and r12 matching the value saved in the
+	@ exception frame because of tail-chaining. So these have to be
+	@ reloaded.
+	ldmia	r12!, {r0-r3}
+
+	@ Linux expects to have irqs off. Do it here before taking stack space
+	cpsid	i
+
+	sub	sp, #S_FRAME_SIZE-S_IP
+	stmdb	sp!, {r0-r11}
+
+	@ load saved r12, lr, return address and xPSR.
+	@ r0-r7 are used for signals and never touched from now on. Clobbering
+	@ r8-r12 is OK.
+	mov	r9, r12
+	ldmia	r9!, {r8, r10-r12}
+
+	@ calculate the original stack pointer value.
+	@ r9 currently points to the memory location just above the auto saved
+	@ xPSR. If the FP extension is implemented and bit 4 of EXC_RETURN is 0
+	@ then space was allocated for FP state. That is space for 18 32-bit
+	@ values. (If FP extension is unimplemented, bit 4 is 1.)
+	@ Additionally the cpu might automatically 8-byte align the stack. Bit 9
+	@ of the saved xPSR specifies if stack aligning took place. In this case
+	@ another 32-bit value is included in the stack.
+
+	tst	lr, #0x10
+	addeq	r9, r9, #576
+
+	tst	r12, 0x100
+	addne	r9, r9, #4
+
+	@ store saved r12 using str to have a register to hold the base for stm
+	str	r8, [sp, #S_IP]
+	add	r8, sp, #S_SP
+	@ store r13-r15, xPSR
+	stmia	r8!, {r9-r12}
+	@ store r0 once more and EXC_RETURN
+	stmia	r8, {r0, lr}
+	.endm
+
+	.macro	v7m_exception_fast_exit
+	@ registers r0-r3 and r12 are automatically restored on exception
+	@ return. r4-r7 were not clobbered in v7m_exception_entry so for
+	@ correctness they don't need to be restored. So only r8-r11 must be
+	@ restored here. The easiest way to do so is to restore r0-r7, too.
+	ldmia	sp!, {r0-r11}
+	add	sp, #S_FRAME_SIZE-S_IP
+	cpsie	i
+	bx	lr
+	.endm
+
+	.macro	v7m_exception_slow_exit ret_r0
+	cpsid	i
+	ldr	lr, [sp, #S_EXC_RET]	@ read exception LR
+	tst     lr, #0x8
+	bne	1f			@ go to thread mode using exception return
+
+	/*
+	 * return to kernel thread
+	 * sp is already set up (and might be unset in pt_regs), so only
+	 * restore r0-r12 and pc
+	 */
+	ldmia	sp, {r0-r12}
+	ldr	lr, [sp, #S_PC]
+	add	sp, sp, #S_FRAME_SIZE
+	cpsie	i
+	bx	lr
+
+1:	/*
+	 * return to userspace
+	 */
+
+	@ read original r12, sp, lr, pc and xPSR
+	add	r12, sp, #S_IP
+	ldmia	r12, {r1-r5}
+
+	@ handle stack aligning
+	tst	r5, #0x100
+	subne	r2, r2, #4
+
+	@ skip over stack space for fp saving
+	tst	lr, #0x10
+	subeq	r2, r2, #576
+
+	@ write basic exception frame
+	stmdb	r2!, {r1, r3-r5}
+	ldmia	sp, {r1, r3-r5}
+	.if	\ret_r0
+	stmdb	r2!, {r0, r3-r5}
+	.else
+	stmdb	r2!, {r1, r3-r5}
+	.endif
+
+	@ restore process sp
+	msr	psp, r2
+
+	@ restore original r4-r11
+	ldmia	sp!, {r0-r11}
+
+	@ restore main sp
+	add	sp, sp, #S_FRAME_SIZE-S_IP
+
+	cpsie	i
+	bx	lr
+	.endm
+#endif	/* CONFIG_CPU_V7M */
+
 	@
 	@ Store/load the USER SP and LR registers by switching to the SYS
 	@ mode. Useful in Thumb-2 mode where "stm/ldm rd, {sp, lr}^" is not
@@ -131,6 +270,14 @@
 	rfeia	sp!
 	.endm
 
+#ifdef CONFIG_CPU_V7M
+	.macro	restore_user_regs, fast = 0, offset = 0
+	.if	\offset
+	add	sp, #\offset
+	.endif
+	v7m_exception_slow_exit ret_r0 = \fast
+	.endm
+#else	/* !CONFIG_CPU_V7M */
 	.macro	restore_user_regs, fast = 0, offset = 0
 	clrex					@ clear the exclusive monitor
 	mov	r2, sp
@@ -147,6 +294,7 @@
 	add	sp, sp, #S_FRAME_SIZE - S_SP
 	movs	pc, lr				@ return & move spsr_svc into cpsr
 	.endm
+#endif	/* CONFIG_CPU_V7M */
 
 	.macro	get_thread_info, rd
 	mov	\rd, sp
diff --git a/arch/arm/kernel/entry-v7m.S b/arch/arm/kernel/entry-v7m.S
new file mode 100644
index 0000000..a0991dc
--- /dev/null
+++ b/arch/arm/kernel/entry-v7m.S
@@ -0,0 +1,134 @@
+/*
+ * linux/arch/arm/kernel/entry-v7m.S
+ *
+ * Copyright (C) 2008 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.
+ *
+ * Low-level vector interface routines for the ARMv7-M architecture
+ */
+#include <asm/memory.h>
+#include <asm/glue.h>
+#include <asm/thread_notify.h>
+
+#include <mach/entry-macro.S>
+
+#include "entry-header.S"
+
+#ifdef CONFIG_PREEMPT
+#error "CONFIG_PREEMPT not supported on the current ARMv7M implementation"
+#endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+#error "CONFIG_TRACE_IRQFLAGS not supported on the current ARMv7M implementation"
+#endif
+
+__invalid_entry:
+	v7m_exception_entry
+	adr	r0, strerr
+	mrs	r1, ipsr
+	mov	r2, lr
+	bl	printk
+	mov	r0, sp
+	bl	show_regs
+1:	b	1b
+ENDPROC(__invalid_entry)
+
+strerr:	.asciz	"\nUnhandled exception: IPSR = %08lx LR = %08lx\n"
+
+	.align	2
+__irq_entry:
+	v7m_exception_entry
+
+	@
+	@ Invoke the IRQ handler
+	@
+	mrs	r0, ipsr
+	and	r0, #0xff
+	sub	r0, #16			@ IRQ number
+	mov	r1, sp
+	@ routine called with r0 = irq number, r1 = struct pt_regs *
+	bl	asm_do_IRQ
+
+	@
+	@ Check for any pending work if returning to user
+	@
+	ldr	lr, [sp, #S_EXC_RET]
+	tst	lr, #0x8		@ check the return stack
+	beq	2f			@ returning to handler mode
+	get_thread_info tsk
+	ldr	r1, [tsk, #TI_FLAGS]
+	tst	r1, #_TIF_WORK_MASK
+	beq	2f			@ no work pending
+	ldr	r1, =0xe000ed04		@ ICSR
+	mov	r0, #1 << 28		@ ICSR.PENDSVSET
+	str	r0, [r1]		@ raise PendSV
+
+2:
+	v7m_exception_fast_exit
+ENDPROC(__irq_entry)
+
+__pendsv_entry:
+	v7m_exception_entry
+
+	ldr	r1, =0xe000ed04		@ ICSR
+	mov	r0, #1 << 27		@ ICSR.PENDSVCLR
+	str	r0, [r1]		@ clear PendSV
+
+	@ execute the pending work, including reschedule
+	get_thread_info tsk
+	mov	why, #0
+	b	ret_to_user
+ENDPROC(__pendsv_entry)
+
+/*
+ * Register switch for ARMv7-M processors.
+ * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
+ * previous and next are guaranteed not to be the same.
+ */
+ENTRY(__switch_to)
+	.fnstart
+	.cantunwind
+	add	ip, r1, #TI_CPU_SAVE
+	stmia	ip!, {r4 - r11}		@ Store most regs on stack
+	str	sp, [ip], #4
+	str	lr, [ip], #4
+	mov	r5, r0
+	add	r4, r2, #TI_CPU_SAVE
+	ldr	r0, =thread_notify_head
+	mov	r1, #THREAD_NOTIFY_SWITCH
+	bl	atomic_notifier_call_chain
+	mov	ip, r4
+	mov	r0, r5
+	ldmia	ip!, {r4 - r11}		@ Load all regs saved previously
+	ldr	sp, [ip], #4
+	ldr	pc, [ip]
+	.fnend
+ENDPROC(__switch_to)
+
+	.data
+	.align	8
+/*
+ * Vector table (64 words => 256 bytes natural alignment)
+ */
+ENTRY(vector_table)
+	.long	0			@ 0 - Reset stack pointer
+	.long	__invalid_entry		@ 1 - Reset
+	.long	__invalid_entry		@ 2 - NMI
+	.long	__invalid_entry		@ 3 - HardFault
+	.long	__invalid_entry		@ 4 - MemManage
+	.long	__invalid_entry		@ 5 - BusFault
+	.long	__invalid_entry		@ 6 - UsageFault
+	.long	__invalid_entry		@ 7 - Reserved
+	.long	__invalid_entry		@ 8 - Reserved
+	.long	__invalid_entry		@ 9 - Reserved
+	.long	__invalid_entry		@ 10 - Reserved
+	.long	vector_swi		@ 11 - SVCall
+	.long	__invalid_entry		@ 12 - Debug Monitor
+	.long	__invalid_entry		@ 13 - Reserved
+	.long	__pendsv_entry		@ 14 - PendSV
+	.long	__invalid_entry		@ 15 - SysTick
+	.rept	64 - 16
+	.long	__irq_entry		@ 16..64 - External Interrupts
+	.endr
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 854bd22..2f560c5 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -98,8 +98,9 @@ __mmap_switched:
 	str	r9, [r4]			@ Save processor ID
 	str	r1, [r5]			@ Save machine type
 	str	r2, [r6]			@ Save atags pointer
-	bic	r4, r0, #CR_A			@ Clear 'A' bit
-	stmia	r7, {r0, r4}			@ Save control register values
+	cmp	r7, #0
+	bicne	r4, r0, #CR_A			@ Clear 'A' bit
+	stmneia	r7, {r0, r4}			@ Save control register values
 	b	start_kernel
 ENDPROC(__mmap_switched)
 
@@ -113,7 +114,11 @@ __mmap_switched_data:
 	.long	processor_id			@ r4
 	.long	__machine_arch_type		@ r5
 	.long	__atags_pointer			@ r6
+#ifdef CONFIG_CPU_CP15
 	.long	cr_alignment			@ r7
+#else
+	.long	0
+#endif
 	.long	init_thread_union + THREAD_START_SP @ sp
 	.size	__mmap_switched_data, . - __mmap_switched_data
 
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 278cfc1..c391c05 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -44,10 +44,13 @@ ENTRY(stext)
 
 	setmode	PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
 						@ and irqs disabled
-#ifndef CONFIG_CPU_CP15
-	ldr	r9, =CONFIG_PROCESSOR_ID
-#else
+#if defined(CONFIG_CPU_CP15)
 	mrc	p15, 0, r9, c0, c0		@ get processor id
+#elif defined(CONFIG_CPU_V7M)
+	ldr	r9, =0xe000ed00			@ CPUID register address
+	ldr	r9, [r9]
+#else
+	ldr	r9, =CONFIG_PROCESSOR_ID
 #endif
 	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
 	movs	r10, r5				@ invalid processor (r5=0)?
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 281bf33..5ff2e77 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -52,14 +52,14 @@ static u8 debug_arch;
 /* Maximum supported watchpoint length. */
 static u8 max_watchpoint_len;
 
-#define READ_WB_REG_CASE(OP2, M, VAL)		\
-	case ((OP2 << 4) + M):			\
-		ARM_DBG_READ(c ## M, OP2, VAL); \
+#define READ_WB_REG_CASE(OP2, M, VAL)			\
+	case ((OP2 << 4) + M):				\
+		ARM_DBG_READ(c0, c ## M, OP2, VAL);	\
 		break
 
-#define WRITE_WB_REG_CASE(OP2, M, VAL)		\
-	case ((OP2 << 4) + M):			\
-		ARM_DBG_WRITE(c ## M, OP2, VAL);\
+#define WRITE_WB_REG_CASE(OP2, M, VAL)			\
+	case ((OP2 << 4) + M):				\
+		ARM_DBG_WRITE(c0, c ## M, OP2, VAL);	\
 		break
 
 #define GEN_READ_WB_REG_CASES(OP2, VAL)		\
@@ -136,12 +136,12 @@ static u8 get_debug_arch(void)
 
 	/* Do we implement the extended CPUID interface? */
 	if (((read_cpuid_id() >> 16) & 0xf) != 0xf) {
-		pr_warning("CPUID feature registers not supported. "
-			   "Assuming v6 debug is present.\n");
+		pr_warn_once("CPUID feature registers not supported. "
+			     "Assuming v6 debug is present.\n");
 		return ARM_DEBUG_ARCH_V6;
 	}
 
-	ARM_DBG_READ(c0, 0, didr);
+	ARM_DBG_READ(c0, c0, 0, didr);
 	return (didr >> 16) & 0xf;
 }
 
@@ -169,7 +169,7 @@ static int debug_exception_updates_fsr(void)
 static int get_num_wrp_resources(void)
 {
 	u32 didr;
-	ARM_DBG_READ(c0, 0, didr);
+	ARM_DBG_READ(c0, c0, 0, didr);
 	return ((didr >> 28) & 0xf) + 1;
 }
 
@@ -177,7 +177,7 @@ static int get_num_wrp_resources(void)
 static int get_num_brp_resources(void)
 {
 	u32 didr;
-	ARM_DBG_READ(c0, 0, didr);
+	ARM_DBG_READ(c0, c0, 0, didr);
 	return ((didr >> 24) & 0xf) + 1;
 }
 
@@ -228,19 +228,17 @@ static int get_num_brps(void)
  * be put into halting debug mode at any time by an external debugger
  * but there is nothing we can do to prevent that.
  */
-static int enable_monitor_mode(void)
+static int monitor_mode_enabled(void)
 {
 	u32 dscr;
-	int ret = 0;
-
-	ARM_DBG_READ(c1, 0, dscr);
+	ARM_DBG_READ(c0, c1, 0, dscr);
+	return !!(dscr & ARM_DSCR_MDBGEN);
+}
 
-	/* Ensure that halting mode is disabled. */
-	if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN,
-		"halting debug mode enabled. Unable to access hardware resources.\n")) {
-		ret = -EPERM;
-		goto out;
-	}
+static int enable_monitor_mode(void)
+{
+	u32 dscr;
+	ARM_DBG_READ(c0, c1, 0, dscr);
 
 	/* If monitor mode is already enabled, just return. */
 	if (dscr & ARM_DSCR_MDBGEN)
@@ -250,24 +248,27 @@ static int enable_monitor_mode(void)
 	switch (get_debug_arch()) {
 	case ARM_DEBUG_ARCH_V6:
 	case ARM_DEBUG_ARCH_V6_1:
-		ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN));
+		ARM_DBG_WRITE(c0, c1, 0, (dscr | ARM_DSCR_MDBGEN));
 		break;
 	case ARM_DEBUG_ARCH_V7_ECP14:
 	case ARM_DEBUG_ARCH_V7_1:
-		ARM_DBG_WRITE(c2, 2, (dscr | ARM_DSCR_MDBGEN));
+		ARM_DBG_WRITE(c0, c2, 2, (dscr | ARM_DSCR_MDBGEN));
+		isb();
 		break;
 	default:
-		ret = -ENODEV;
-		goto out;
+		return -ENODEV;
 	}
 
 	/* Check that the write made it through. */
-	ARM_DBG_READ(c1, 0, dscr);
-	if (!(dscr & ARM_DSCR_MDBGEN))
-		ret = -EPERM;
+	ARM_DBG_READ(c0, c1, 0, dscr);
+	if (!(dscr & ARM_DSCR_MDBGEN)) {
+		pr_warn_once("Failed to enable monitor mode on CPU %d.\n",
+				smp_processor_id());
+		return -EPERM;
+	}
 
 out:
-	return ret;
+	return 0;
 }
 
 int hw_breakpoint_slots(int type)
@@ -328,14 +329,9 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
 {
 	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
 	struct perf_event **slot, **slots;
-	int i, max_slots, ctrl_base, val_base, ret = 0;
+	int i, max_slots, ctrl_base, val_base;
 	u32 addr, ctrl;
 
-	/* Ensure that we are in monitor mode and halting mode is disabled. */
-	ret = enable_monitor_mode();
-	if (ret)
-		goto out;
-
 	addr = info->address;
 	ctrl = encode_ctrl_reg(info->ctrl) | 0x1;
 
@@ -362,9 +358,9 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
 		}
 	}
 
-	if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) {
-		ret = -EBUSY;
-		goto out;
+	if (i == max_slots) {
+		pr_warning("Can't find any breakpoint slot\n");
+		return -EBUSY;
 	}
 
 	/* Override the breakpoint data with the step data. */
@@ -383,9 +379,7 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
 
 	/* Setup the control register. */
 	write_wb_reg(ctrl_base + i, ctrl);
-
-out:
-	return ret;
+	return 0;
 }
 
 void arch_uninstall_hw_breakpoint(struct perf_event *bp)
@@ -416,8 +410,10 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp)
 		}
 	}
 
-	if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n"))
+	if (i == max_slots) {
+		pr_warning("Can't find any breakpoint slot\n");
 		return;
+	}
 
 	/* Ensure that we disable the mismatch breakpoint. */
 	if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE &&
@@ -596,6 +592,10 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
 	int ret = 0;
 	u32 offset, alignment_mask = 0x3;
 
+	/* Ensure that we are in monitor debug mode. */
+	if (!monitor_mode_enabled())
+		return -ENODEV;
+
 	/* Build the arch_hw_breakpoint. */
 	ret = arch_build_bp_info(bp);
 	if (ret)
@@ -858,7 +858,7 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
 		local_irq_enable();
 
 	/* We only handle watchpoints and hardware breakpoints. */
-	ARM_DBG_READ(c1, 0, dscr);
+	ARM_DBG_READ(c0, c1, 0, dscr);
 
 	/* Perform perf callbacks. */
 	switch (ARM_DSCR_MOE(dscr)) {
@@ -906,7 +906,7 @@ static struct undef_hook debug_reg_hook = {
 static void reset_ctrl_regs(void *unused)
 {
 	int i, raw_num_brps, err = 0, cpu = smp_processor_id();
-	u32 dbg_power;
+	u32 val;
 
 	/*
 	 * v7 debug contains save and restore registers so that debug state
@@ -919,23 +919,30 @@ static void reset_ctrl_regs(void *unused)
 	switch (debug_arch) {
 	case ARM_DEBUG_ARCH_V6:
 	case ARM_DEBUG_ARCH_V6_1:
-		/* ARMv6 cores just need to reset the registers. */
-		goto reset_regs;
+		/* ARMv6 cores clear the registers out of reset. */
+		goto out_mdbgen;
 	case ARM_DEBUG_ARCH_V7_ECP14:
 		/*
 		 * Ensure sticky power-down is clear (i.e. debug logic is
 		 * powered up).
 		 */
-		asm volatile("mrc p14, 0, %0, c1, c5, 4" : "=r" (dbg_power));
-		if ((dbg_power & 0x1) == 0)
+		ARM_DBG_READ(c1, c5, 4, val);
+		if ((val & 0x1) == 0)
 			err = -EPERM;
+
+		/*
+		 * Check whether we implement OS save and restore.
+		 */
+		ARM_DBG_READ(c1, c1, 4, val);
+		if ((val & 0x9) == 0)
+			goto clear_vcr;
 		break;
 	case ARM_DEBUG_ARCH_V7_1:
 		/*
 		 * Ensure the OS double lock is clear.
 		 */
-		asm volatile("mrc p14, 0, %0, c1, c3, 4" : "=r" (dbg_power));
-		if ((dbg_power & 0x1) == 1)
+		ARM_DBG_READ(c1, c3, 4, val);
+		if ((val & 0x1) == 1)
 			err = -EPERM;
 		break;
 	}
@@ -947,24 +954,29 @@ static void reset_ctrl_regs(void *unused)
 	}
 
 	/*
-	 * Unconditionally clear the lock by writing a value
+	 * Unconditionally clear the OS lock by writing a value
 	 * other than 0xC5ACCE55 to the access register.
 	 */
-	asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));
+	ARM_DBG_WRITE(c1, c0, 4, 0);
 	isb();
 
 	/*
 	 * Clear any configured vector-catch events before
 	 * enabling monitor mode.
 	 */
-	asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0));
+clear_vcr:
+	ARM_DBG_WRITE(c0, c7, 0, 0);
 	isb();
 
-reset_regs:
-	if (enable_monitor_mode())
+	if (cpumask_intersects(&debug_err_mask, cpumask_of(cpu))) {
+		pr_warning("CPU %d failed to disable vector catch\n", cpu);
 		return;
+	}
 
-	/* We must also reset any reserved registers. */
+	/*
+	 * The control/value register pairs are UNKNOWN out of reset so
+	 * clear them to avoid spurious debug events.
+	 */
 	raw_num_brps = get_num_brp_resources();
 	for (i = 0; i < raw_num_brps; ++i) {
 		write_wb_reg(ARM_BASE_BCR + i, 0UL);
@@ -975,6 +987,19 @@ reset_regs:
 		write_wb_reg(ARM_BASE_WCR + i, 0UL);
 		write_wb_reg(ARM_BASE_WVR + i, 0UL);
 	}
+
+	if (cpumask_intersects(&debug_err_mask, cpumask_of(cpu))) {
+		pr_warning("CPU %d failed to clear debug register pairs\n", cpu);
+		return;
+	}
+
+	/*
+	 * Have a crack at enabling monitor mode. We don't actually need
+	 * it yet, but reporting an error early is useful if it fails.
+	 */
+out_mdbgen:
+	if (enable_monitor_mode())
+		cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu));
 }
 
 static int __cpuinit dbg_reset_notify(struct notifier_block *self,
@@ -992,8 +1017,6 @@ static struct notifier_block __cpuinitdata dbg_reset_nb = {
 
 static int __init arch_hw_breakpoint_init(void)
 {
-	u32 dscr;
-
 	debug_arch = get_debug_arch();
 
 	if (!debug_arch_supported()) {
@@ -1028,17 +1051,10 @@ static int __init arch_hw_breakpoint_init(void)
 		core_num_brps, core_has_mismatch_brps() ? "(+1 reserved) " :
 		"", core_num_wrps);
 
-	ARM_DBG_READ(c1, 0, dscr);
-	if (dscr & ARM_DSCR_HDBGEN) {
-		max_watchpoint_len = 4;
-		pr_warning("halting debug mode enabled. Assuming maximum watchpoint size of %u bytes.\n",
-			   max_watchpoint_len);
-	} else {
-		/* Work out the maximum supported watchpoint length. */
-		max_watchpoint_len = get_max_wp_len();
-		pr_info("maximum watchpoint size is %u bytes.\n",
-				max_watchpoint_len);
-	}
+	/* Work out the maximum supported watchpoint length. */
+	max_watchpoint_len = get_max_wp_len();
+	pr_info("maximum watchpoint size is %u bytes.\n",
+			max_watchpoint_len);
 
 	/* Register debug fault handler. */
 	hook_fault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP,
diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c
index 1862d8f..0cd63d0 100644
--- a/arch/arm/kernel/kprobes-test.c
+++ b/arch/arm/kernel/kprobes-test.c
@@ -1598,7 +1598,7 @@ static int __init run_all_tests(void)
 {
 	int ret = 0;
 
-	pr_info("Begining kprobe tests...\n");
+	pr_info("Beginning kprobe tests...\n");
 
 #ifndef CONFIG_THUMB2_KERNEL
 
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 53c0304..f9e8657 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -86,12 +86,10 @@ armpmu_map_event(struct perf_event *event,
 	return -ENOENT;
 }
 
-int
-armpmu_event_set_period(struct perf_event *event,
-			struct hw_perf_event *hwc,
-			int idx)
+int armpmu_event_set_period(struct perf_event *event)
 {
 	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
 	s64 left = local64_read(&hwc->period_left);
 	s64 period = hwc->sample_period;
 	int ret = 0;
@@ -119,24 +117,22 @@ armpmu_event_set_period(struct perf_event *event,
 
 	local64_set(&hwc->prev_count, (u64)-left);
 
-	armpmu->write_counter(idx, (u64)(-left) & 0xffffffff);
+	armpmu->write_counter(event, (u64)(-left) & 0xffffffff);
 
 	perf_event_update_userpage(event);
 
 	return ret;
 }
 
-u64
-armpmu_event_update(struct perf_event *event,
-		    struct hw_perf_event *hwc,
-		    int idx)
+u64 armpmu_event_update(struct perf_event *event)
 {
 	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
 	u64 delta, prev_raw_count, new_raw_count;
 
 again:
 	prev_raw_count = local64_read(&hwc->prev_count);
-	new_raw_count = armpmu->read_counter(idx);
+	new_raw_count = armpmu->read_counter(event);
 
 	if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
 			     new_raw_count) != prev_raw_count)
@@ -159,7 +155,7 @@ armpmu_read(struct perf_event *event)
 	if (hwc->idx < 0)
 		return;
 
-	armpmu_event_update(event, hwc, hwc->idx);
+	armpmu_event_update(event);
 }
 
 static void
@@ -173,14 +169,13 @@ armpmu_stop(struct perf_event *event, int flags)
 	 * PERF_EF_UPDATE, see comments in armpmu_start().
 	 */
 	if (!(hwc->state & PERF_HES_STOPPED)) {
-		armpmu->disable(hwc, hwc->idx);
-		armpmu_event_update(event, hwc, hwc->idx);
+		armpmu->disable(event);
+		armpmu_event_update(event);
 		hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
 	}
 }
 
-static void
-armpmu_start(struct perf_event *event, int flags)
+static void armpmu_start(struct perf_event *event, int flags)
 {
 	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	struct hw_perf_event *hwc = &event->hw;
@@ -200,8 +195,8 @@ armpmu_start(struct perf_event *event, int flags)
 	 * get an interrupt too soon or *way* too late if the overflow has
 	 * happened since disabling.
 	 */
-	armpmu_event_set_period(event, hwc, hwc->idx);
-	armpmu->enable(hwc, hwc->idx);
+	armpmu_event_set_period(event);
+	armpmu->enable(event);
 }
 
 static void
@@ -233,7 +228,7 @@ armpmu_add(struct perf_event *event, int flags)
 	perf_pmu_disable(event->pmu);
 
 	/* If we don't have a space for the counter then finish early. */
-	idx = armpmu->get_event_idx(hw_events, hwc);
+	idx = armpmu->get_event_idx(hw_events, event);
 	if (idx < 0) {
 		err = idx;
 		goto out;
@@ -244,7 +239,7 @@ armpmu_add(struct perf_event *event, int flags)
 	 * sure it is disabled.
 	 */
 	event->hw.idx = idx;
-	armpmu->disable(hwc, idx);
+	armpmu->disable(event);
 	hw_events->events[idx] = event;
 
 	hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
@@ -264,13 +259,12 @@ validate_event(struct pmu_hw_events *hw_events,
 	       struct perf_event *event)
 {
 	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
-	struct hw_perf_event fake_event = event->hw;
 	struct pmu *leader_pmu = event->group_leader->pmu;
 
 	if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
 		return 1;
 
-	return armpmu->get_event_idx(hw_events, &fake_event) >= 0;
+	return armpmu->get_event_idx(hw_events, event) >= 0;
 }
 
 static int
@@ -316,7 +310,7 @@ static irqreturn_t armpmu_dispatch_irq(int irq, void *dev)
 static void
 armpmu_release_hardware(struct arm_pmu *armpmu)
 {
-	armpmu->free_irq();
+	armpmu->free_irq(armpmu);
 	pm_runtime_put_sync(&armpmu->plat_device->dev);
 }
 
@@ -330,7 +324,7 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)
 		return -ENODEV;
 
 	pm_runtime_get_sync(&pmu_device->dev);
-	err = armpmu->request_irq(armpmu_dispatch_irq);
+	err = armpmu->request_irq(armpmu, armpmu_dispatch_irq);
 	if (err) {
 		armpmu_release_hardware(armpmu);
 		return err;
@@ -465,13 +459,13 @@ static void armpmu_enable(struct pmu *pmu)
 	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
 
 	if (enabled)
-		armpmu->start();
+		armpmu->start(armpmu);
 }
 
 static void armpmu_disable(struct pmu *pmu)
 {
 	struct arm_pmu *armpmu = to_arm_pmu(pmu);
-	armpmu->stop();
+	armpmu->stop(armpmu);
 }
 
 #ifdef CONFIG_PM_RUNTIME
@@ -517,12 +511,13 @@ static void __init armpmu_init(struct arm_pmu *armpmu)
 	};
 }
 
-int armpmu_register(struct arm_pmu *armpmu, char *name, int type)
+int armpmu_register(struct arm_pmu *armpmu, int type)
 {
 	armpmu_init(armpmu);
+	pm_runtime_enable(&armpmu->plat_device->dev);
 	pr_info("enabled with %s PMU driver, %d counters available\n",
 			armpmu->name, armpmu->num_events);
-	return perf_pmu_register(&armpmu->pmu, name, type);
+	return perf_pmu_register(&armpmu->pmu, armpmu->name, type);
 }
 
 /*
@@ -576,6 +571,10 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
 	struct frame_tail __user *tail;
 
+	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+		/* We don't support guest os callchain now */
+		return;
+	}
 
 	tail = (struct frame_tail __user *)regs->ARM_fp - 1;
 
@@ -603,9 +602,41 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
 	struct stackframe fr;
 
+	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+		/* We don't support guest os callchain now */
+		return;
+	}
+
 	fr.fp = regs->ARM_fp;
 	fr.sp = regs->ARM_sp;
 	fr.lr = regs->ARM_lr;
 	fr.pc = regs->ARM_pc;
 	walk_stackframe(&fr, callchain_trace, entry);
 }
+
+unsigned long perf_instruction_pointer(struct pt_regs *regs)
+{
+	if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
+		return perf_guest_cbs->get_guest_ip();
+
+	return instruction_pointer(regs);
+}
+
+unsigned long perf_misc_flags(struct pt_regs *regs)
+{
+	int misc = 0;
+
+	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+		if (perf_guest_cbs->is_user_mode())
+			misc |= PERF_RECORD_MISC_GUEST_USER;
+		else
+			misc |= PERF_RECORD_MISC_GUEST_KERNEL;
+	} else {
+		if (user_mode(regs))
+			misc |= PERF_RECORD_MISC_USER;
+		else
+			misc |= PERF_RECORD_MISC_KERNEL;
+	}
+
+	return misc;
+}
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c
index 8d7d8d4..9a4f630 100644
--- a/arch/arm/kernel/perf_event_cpu.c
+++ b/arch/arm/kernel/perf_event_cpu.c
@@ -23,6 +23,7 @@
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 
 #include <asm/cputype.h>
@@ -45,7 +46,7 @@ const char *perf_pmu_name(void)
 	if (!cpu_pmu)
 		return NULL;
 
-	return cpu_pmu->pmu.name;
+	return cpu_pmu->name;
 }
 EXPORT_SYMBOL_GPL(perf_pmu_name);
 
@@ -70,7 +71,7 @@ static struct pmu_hw_events *cpu_pmu_get_cpu_events(void)
 	return &__get_cpu_var(cpu_hw_events);
 }
 
-static void cpu_pmu_free_irq(void)
+static void cpu_pmu_free_irq(struct arm_pmu *cpu_pmu)
 {
 	int i, irq, irqs;
 	struct platform_device *pmu_device = cpu_pmu->plat_device;
@@ -86,7 +87,7 @@ static void cpu_pmu_free_irq(void)
 	}
 }
 
-static int cpu_pmu_request_irq(irq_handler_t handler)
+static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
 {
 	int i, err, irq, irqs;
 	struct platform_device *pmu_device = cpu_pmu->plat_device;
@@ -147,7 +148,7 @@ static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu)
 
 	/* Ensure the PMU has sane values out of reset. */
 	if (cpu_pmu && cpu_pmu->reset)
-		on_each_cpu(cpu_pmu->reset, NULL, 1);
+		on_each_cpu(cpu_pmu->reset, cpu_pmu, 1);
 }
 
 /*
@@ -163,7 +164,9 @@ static int __cpuinit cpu_pmu_notify(struct notifier_block *b,
 		return NOTIFY_DONE;
 
 	if (cpu_pmu && cpu_pmu->reset)
-		cpu_pmu->reset(NULL);
+		cpu_pmu->reset(cpu_pmu);
+	else
+		return NOTIFY_DONE;
 
 	return NOTIFY_OK;
 }
@@ -195,13 +198,13 @@ static struct platform_device_id __devinitdata cpu_pmu_plat_device_ids[] = {
 /*
  * CPU PMU identification and probing.
  */
-static struct arm_pmu *__devinit probe_current_pmu(void)
+static int __devinit probe_current_pmu(struct arm_pmu *pmu)
 {
-	struct arm_pmu *pmu = NULL;
 	int cpu = get_cpu();
 	unsigned long cpuid = read_cpuid_id();
 	unsigned long implementor = (cpuid & 0xFF000000) >> 24;
 	unsigned long part_number = (cpuid & 0xFFF0);
+	int ret = -ENODEV;
 
 	pr_info("probing PMU on CPU %d\n", cpu);
 
@@ -211,25 +214,25 @@ static struct arm_pmu *__devinit probe_current_pmu(void)
 		case 0xB360:	/* ARM1136 */
 		case 0xB560:	/* ARM1156 */
 		case 0xB760:	/* ARM1176 */
-			pmu = armv6pmu_init();
+			ret = armv6pmu_init(pmu);
 			break;
 		case 0xB020:	/* ARM11mpcore */
-			pmu = armv6mpcore_pmu_init();
+			ret = armv6mpcore_pmu_init(pmu);
 			break;
 		case 0xC080:	/* Cortex-A8 */
-			pmu = armv7_a8_pmu_init();
+			ret = armv7_a8_pmu_init(pmu);
 			break;
 		case 0xC090:	/* Cortex-A9 */
-			pmu = armv7_a9_pmu_init();
+			ret = armv7_a9_pmu_init(pmu);
 			break;
 		case 0xC050:	/* Cortex-A5 */
-			pmu = armv7_a5_pmu_init();
+			ret = armv7_a5_pmu_init(pmu);
 			break;
 		case 0xC0F0:	/* Cortex-A15 */
-			pmu = armv7_a15_pmu_init();
+			ret = armv7_a15_pmu_init(pmu);
 			break;
 		case 0xC070:	/* Cortex-A7 */
-			pmu = armv7_a7_pmu_init();
+			ret = armv7_a7_pmu_init(pmu);
 			break;
 		}
 	/* Intel CPUs [xscale]. */
@@ -237,43 +240,54 @@ static struct arm_pmu *__devinit probe_current_pmu(void)
 		part_number = (cpuid >> 13) & 0x7;
 		switch (part_number) {
 		case 1:
-			pmu = xscale1pmu_init();
+			ret = xscale1pmu_init(pmu);
 			break;
 		case 2:
-			pmu = xscale2pmu_init();
+			ret = xscale2pmu_init(pmu);
 			break;
 		}
 	}
 
 	put_cpu();
-	return pmu;
+	return ret;
 }
 
 static int __devinit cpu_pmu_device_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id;
-	struct arm_pmu *(*init_fn)(void);
+	int (*init_fn)(struct arm_pmu *);
 	struct device_node *node = pdev->dev.of_node;
+	struct arm_pmu *pmu;
+	int ret = -ENODEV;
 
 	if (cpu_pmu) {
 		pr_info("attempt to register multiple PMU devices!");
 		return -ENOSPC;
 	}
 
+	pmu = kzalloc(sizeof(struct arm_pmu), GFP_KERNEL);
+	if (!pmu) {
+		pr_info("failed to allocate PMU device!");
+		return -ENOMEM;
+	}
+
 	if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) {
 		init_fn = of_id->data;
-		cpu_pmu = init_fn();
+		ret = init_fn(pmu);
 	} else {
-		cpu_pmu = probe_current_pmu();
+		ret = probe_current_pmu(pmu);
 	}
 
-	if (!cpu_pmu)
-		return -ENODEV;
+	if (ret) {
+		pr_info("failed to register PMU devices!");
+		kfree(pmu);
+		return ret;
+	}
 
+	cpu_pmu = pmu;
 	cpu_pmu->plat_device = pdev;
 	cpu_pmu_init(cpu_pmu);
-	register_cpu_notifier(&cpu_pmu_hotplug_notifier);
-	armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW);
+	armpmu_register(cpu_pmu, PERF_TYPE_RAW);
 
 	return 0;
 }
@@ -290,6 +304,16 @@ static struct platform_driver cpu_pmu_driver = {
 
 static int __init register_pmu_driver(void)
 {
-	return platform_driver_register(&cpu_pmu_driver);
+	int err;
+
+	err = register_cpu_notifier(&cpu_pmu_hotplug_notifier);
+	if (err)
+		return err;
+
+	err = platform_driver_register(&cpu_pmu_driver);
+	if (err)
+		unregister_cpu_notifier(&cpu_pmu_hotplug_notifier);
+
+	return err;
 }
 device_initcall(register_pmu_driver);
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index 6ccc079..f3e22ff 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -401,9 +401,10 @@ armv6_pmcr_counter_has_overflowed(unsigned long pmcr,
 	return ret;
 }
 
-static inline u32
-armv6pmu_read_counter(int counter)
+static inline u32 armv6pmu_read_counter(struct perf_event *event)
 {
+	struct hw_perf_event *hwc = &event->hw;
+	int counter = hwc->idx;
 	unsigned long value = 0;
 
 	if (ARMV6_CYCLE_COUNTER == counter)
@@ -418,10 +419,11 @@ armv6pmu_read_counter(int counter)
 	return value;
 }
 
-static inline void
-armv6pmu_write_counter(int counter,
-		       u32 value)
+static inline void armv6pmu_write_counter(struct perf_event *event, u32 value)
 {
+	struct hw_perf_event *hwc = &event->hw;
+	int counter = hwc->idx;
+
 	if (ARMV6_CYCLE_COUNTER == counter)
 		asm volatile("mcr   p15, 0, %0, c15, c12, 1" : : "r"(value));
 	else if (ARMV6_COUNTER0 == counter)
@@ -432,12 +434,13 @@ armv6pmu_write_counter(int counter,
 		WARN_ONCE(1, "invalid counter number (%d)\n", counter);
 }
 
-static void
-armv6pmu_enable_event(struct hw_perf_event *hwc,
-		      int idx)
+static void armv6pmu_enable_event(struct perf_event *event)
 {
 	unsigned long val, mask, evt, flags;
+	struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+	int idx = hwc->idx;
 
 	if (ARMV6_CYCLE_COUNTER == idx) {
 		mask	= 0;
@@ -473,7 +476,8 @@ armv6pmu_handle_irq(int irq_num,
 {
 	unsigned long pmcr = armv6_pmcr_read();
 	struct perf_sample_data data;
-	struct pmu_hw_events *cpuc;
+	struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
+	struct pmu_hw_events *cpuc = cpu_pmu->get_hw_events();
 	struct pt_regs *regs;
 	int idx;
 
@@ -489,7 +493,6 @@ armv6pmu_handle_irq(int irq_num,
 	 */
 	armv6_pmcr_write(pmcr);
 
-	cpuc = &__get_cpu_var(cpu_hw_events);
 	for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
 		struct perf_event *event = cpuc->events[idx];
 		struct hw_perf_event *hwc;
@@ -506,13 +509,13 @@ armv6pmu_handle_irq(int irq_num,
 			continue;
 
 		hwc = &event->hw;
-		armpmu_event_update(event, hwc, idx);
+		armpmu_event_update(event);
 		perf_sample_data_init(&data, 0, hwc->last_period);
-		if (!armpmu_event_set_period(event, hwc, idx))
+		if (!armpmu_event_set_period(event))
 			continue;
 
 		if (perf_event_overflow(event, &data, regs))
-			cpu_pmu->disable(hwc, idx);
+			cpu_pmu->disable(event);
 	}
 
 	/*
@@ -527,8 +530,7 @@ armv6pmu_handle_irq(int irq_num,
 	return IRQ_HANDLED;
 }
 
-static void
-armv6pmu_start(void)
+static void armv6pmu_start(struct arm_pmu *cpu_pmu)
 {
 	unsigned long flags, val;
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
@@ -540,8 +542,7 @@ armv6pmu_start(void)
 	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void
-armv6pmu_stop(void)
+static void armv6pmu_stop(struct arm_pmu *cpu_pmu)
 {
 	unsigned long flags, val;
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
@@ -555,10 +556,11 @@ armv6pmu_stop(void)
 
 static int
 armv6pmu_get_event_idx(struct pmu_hw_events *cpuc,
-		       struct hw_perf_event *event)
+				struct perf_event *event)
 {
+	struct hw_perf_event *hwc = &event->hw;
 	/* Always place a cycle counter into the cycle counter. */
-	if (ARMV6_PERFCTR_CPU_CYCLES == event->config_base) {
+	if (ARMV6_PERFCTR_CPU_CYCLES == hwc->config_base) {
 		if (test_and_set_bit(ARMV6_CYCLE_COUNTER, cpuc->used_mask))
 			return -EAGAIN;
 
@@ -579,12 +581,13 @@ armv6pmu_get_event_idx(struct pmu_hw_events *cpuc,
 	}
 }
 
-static void
-armv6pmu_disable_event(struct hw_perf_event *hwc,
-		       int idx)
+static void armv6pmu_disable_event(struct perf_event *event)
 {
 	unsigned long val, mask, evt, flags;
+	struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+	int idx = hwc->idx;
 
 	if (ARMV6_CYCLE_COUNTER == idx) {
 		mask	= ARMV6_PMCR_CCOUNT_IEN;
@@ -613,12 +616,13 @@ armv6pmu_disable_event(struct hw_perf_event *hwc,
 	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void
-armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc,
-			      int idx)
+static void armv6mpcore_pmu_disable_event(struct perf_event *event)
 {
 	unsigned long val, mask, flags, evt = 0;
+	struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+	int idx = hwc->idx;
 
 	if (ARMV6_CYCLE_COUNTER == idx) {
 		mask	= ARMV6_PMCR_CCOUNT_IEN;
@@ -649,24 +653,22 @@ static int armv6_map_event(struct perf_event *event)
 				&armv6_perf_cache_map, 0xFF);
 }
 
-static struct arm_pmu armv6pmu = {
-	.name			= "v6",
-	.handle_irq		= armv6pmu_handle_irq,
-	.enable			= armv6pmu_enable_event,
-	.disable		= armv6pmu_disable_event,
-	.read_counter		= armv6pmu_read_counter,
-	.write_counter		= armv6pmu_write_counter,
-	.get_event_idx		= armv6pmu_get_event_idx,
-	.start			= armv6pmu_start,
-	.stop			= armv6pmu_stop,
-	.map_event		= armv6_map_event,
-	.num_events		= 3,
-	.max_period		= (1LLU << 32) - 1,
-};
-
-static struct arm_pmu *__devinit armv6pmu_init(void)
+static int __devinit armv6pmu_init(struct arm_pmu *cpu_pmu)
 {
-	return &armv6pmu;
+	cpu_pmu->name		= "v6";
+	cpu_pmu->handle_irq	= armv6pmu_handle_irq;
+	cpu_pmu->enable		= armv6pmu_enable_event;
+	cpu_pmu->disable	= armv6pmu_disable_event;
+	cpu_pmu->read_counter	= armv6pmu_read_counter;
+	cpu_pmu->write_counter	= armv6pmu_write_counter;
+	cpu_pmu->get_event_idx	= armv6pmu_get_event_idx;
+	cpu_pmu->start		= armv6pmu_start;
+	cpu_pmu->stop		= armv6pmu_stop;
+	cpu_pmu->map_event	= armv6_map_event;
+	cpu_pmu->num_events	= 3;
+	cpu_pmu->max_period	= (1LLU << 32) - 1;
+
+	return 0;
 }
 
 /*
@@ -683,33 +685,31 @@ static int armv6mpcore_map_event(struct perf_event *event)
 				&armv6mpcore_perf_cache_map, 0xFF);
 }
 
-static struct arm_pmu armv6mpcore_pmu = {
-	.name			= "v6mpcore",
-	.handle_irq		= armv6pmu_handle_irq,
-	.enable			= armv6pmu_enable_event,
-	.disable		= armv6mpcore_pmu_disable_event,
-	.read_counter		= armv6pmu_read_counter,
-	.write_counter		= armv6pmu_write_counter,
-	.get_event_idx		= armv6pmu_get_event_idx,
-	.start			= armv6pmu_start,
-	.stop			= armv6pmu_stop,
-	.map_event		= armv6mpcore_map_event,
-	.num_events		= 3,
-	.max_period		= (1LLU << 32) - 1,
-};
-
-static struct arm_pmu *__devinit armv6mpcore_pmu_init(void)
+static int __devinit armv6mpcore_pmu_init(struct arm_pmu *cpu_pmu)
 {
-	return &armv6mpcore_pmu;
+	cpu_pmu->name		= "v6mpcore";
+	cpu_pmu->handle_irq	= armv6pmu_handle_irq;
+	cpu_pmu->enable		= armv6pmu_enable_event;
+	cpu_pmu->disable	= armv6mpcore_pmu_disable_event;
+	cpu_pmu->read_counter	= armv6pmu_read_counter;
+	cpu_pmu->write_counter	= armv6pmu_write_counter;
+	cpu_pmu->get_event_idx	= armv6pmu_get_event_idx;
+	cpu_pmu->start		= armv6pmu_start;
+	cpu_pmu->stop		= armv6pmu_stop;
+	cpu_pmu->map_event	= armv6mpcore_map_event;
+	cpu_pmu->num_events	= 3;
+	cpu_pmu->max_period	= (1LLU << 32) - 1;
+
+	return 0;
 }
 #else
-static struct arm_pmu *__devinit armv6pmu_init(void)
+static int armv6pmu_init(struct arm_pmu *cpu_pmu)
 {
-	return NULL;
+	return -ENODEV;
 }
 
-static struct arm_pmu *__devinit armv6mpcore_pmu_init(void)
+static int armv6mpcore_pmu_init(struct arm_pmu *cpu_pmu)
 {
-	return NULL;
+	return -ENODEV;
 }
 #endif	/* CONFIG_CPU_V6 || CONFIG_CPU_V6K */
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index bd4b090..7d0cce8 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -18,8 +18,6 @@
 
 #ifdef CONFIG_CPU_V7
 
-static struct arm_pmu armv7pmu;
-
 /*
  * Common ARMv7 event types
  *
@@ -738,7 +736,8 @@ static const unsigned armv7_a7_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
  */
 #define	ARMV7_IDX_CYCLE_COUNTER	0
 #define	ARMV7_IDX_COUNTER0	1
-#define	ARMV7_IDX_COUNTER_LAST	(ARMV7_IDX_CYCLE_COUNTER + cpu_pmu->num_events - 1)
+#define	ARMV7_IDX_COUNTER_LAST(cpu_pmu) \
+	(ARMV7_IDX_CYCLE_COUNTER + cpu_pmu->num_events - 1)
 
 #define	ARMV7_MAX_COUNTERS	32
 #define	ARMV7_COUNTER_MASK	(ARMV7_MAX_COUNTERS - 1)
@@ -804,49 +803,34 @@ static inline int armv7_pmnc_has_overflowed(u32 pmnc)
 	return pmnc & ARMV7_OVERFLOWED_MASK;
 }
 
-static inline int armv7_pmnc_counter_valid(int idx)
+static inline int armv7_pmnc_counter_valid(struct arm_pmu *cpu_pmu, int idx)
 {
-	return idx >= ARMV7_IDX_CYCLE_COUNTER && idx <= ARMV7_IDX_COUNTER_LAST;
+	return idx >= ARMV7_IDX_CYCLE_COUNTER &&
+		idx <= ARMV7_IDX_COUNTER_LAST(cpu_pmu);
 }
 
 static inline int armv7_pmnc_counter_has_overflowed(u32 pmnc, int idx)
 {
-	int ret = 0;
-	u32 counter;
-
-	if (!armv7_pmnc_counter_valid(idx)) {
-		pr_err("CPU%u checking wrong counter %d overflow status\n",
-			smp_processor_id(), idx);
-	} else {
-		counter = ARMV7_IDX_TO_COUNTER(idx);
-		ret = pmnc & BIT(counter);
-	}
-
-	return ret;
+	return pmnc & BIT(ARMV7_IDX_TO_COUNTER(idx));
 }
 
 static inline int armv7_pmnc_select_counter(int idx)
 {
-	u32 counter;
-
-	if (!armv7_pmnc_counter_valid(idx)) {
-		pr_err("CPU%u selecting wrong PMNC counter %d\n",
-			smp_processor_id(), idx);
-		return -EINVAL;
-	}
-
-	counter = ARMV7_IDX_TO_COUNTER(idx);
+	u32 counter = ARMV7_IDX_TO_COUNTER(idx);
 	asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (counter));
 	isb();
 
 	return idx;
 }
 
-static inline u32 armv7pmu_read_counter(int idx)
+static inline u32 armv7pmu_read_counter(struct perf_event *event)
 {
+	struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	int idx = hwc->idx;
 	u32 value = 0;
 
-	if (!armv7_pmnc_counter_valid(idx))
+	if (!armv7_pmnc_counter_valid(cpu_pmu, idx))
 		pr_err("CPU%u reading wrong counter %d\n",
 			smp_processor_id(), idx);
 	else if (idx == ARMV7_IDX_CYCLE_COUNTER)
@@ -857,9 +841,13 @@ static inline u32 armv7pmu_read_counter(int idx)
 	return value;
 }
 
-static inline void armv7pmu_write_counter(int idx, u32 value)
+static inline void armv7pmu_write_counter(struct perf_event *event, u32 value)
 {
-	if (!armv7_pmnc_counter_valid(idx))
+	struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	int idx = hwc->idx;
+
+	if (!armv7_pmnc_counter_valid(cpu_pmu, idx))
 		pr_err("CPU%u writing wrong counter %d\n",
 			smp_processor_id(), idx);
 	else if (idx == ARMV7_IDX_CYCLE_COUNTER)
@@ -878,60 +866,28 @@ static inline void armv7_pmnc_write_evtsel(int idx, u32 val)
 
 static inline int armv7_pmnc_enable_counter(int idx)
 {
-	u32 counter;
-
-	if (!armv7_pmnc_counter_valid(idx)) {
-		pr_err("CPU%u enabling wrong PMNC counter %d\n",
-			smp_processor_id(), idx);
-		return -EINVAL;
-	}
-
-	counter = ARMV7_IDX_TO_COUNTER(idx);
+	u32 counter = ARMV7_IDX_TO_COUNTER(idx);
 	asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (BIT(counter)));
 	return idx;
 }
 
 static inline int armv7_pmnc_disable_counter(int idx)
 {
-	u32 counter;
-
-	if (!armv7_pmnc_counter_valid(idx)) {
-		pr_err("CPU%u disabling wrong PMNC counter %d\n",
-			smp_processor_id(), idx);
-		return -EINVAL;
-	}
-
-	counter = ARMV7_IDX_TO_COUNTER(idx);
+	u32 counter = ARMV7_IDX_TO_COUNTER(idx);
 	asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (BIT(counter)));
 	return idx;
 }
 
 static inline int armv7_pmnc_enable_intens(int idx)
 {
-	u32 counter;
-
-	if (!armv7_pmnc_counter_valid(idx)) {
-		pr_err("CPU%u enabling wrong PMNC counter IRQ enable %d\n",
-			smp_processor_id(), idx);
-		return -EINVAL;
-	}
-
-	counter = ARMV7_IDX_TO_COUNTER(idx);
+	u32 counter = ARMV7_IDX_TO_COUNTER(idx);
 	asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (BIT(counter)));
 	return idx;
 }
 
 static inline int armv7_pmnc_disable_intens(int idx)
 {
-	u32 counter;
-
-	if (!armv7_pmnc_counter_valid(idx)) {
-		pr_err("CPU%u disabling wrong PMNC counter IRQ enable %d\n",
-			smp_processor_id(), idx);
-		return -EINVAL;
-	}
-
-	counter = ARMV7_IDX_TO_COUNTER(idx);
+	u32 counter = ARMV7_IDX_TO_COUNTER(idx);
 	asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (BIT(counter)));
 	isb();
 	/* Clear the overflow flag in case an interrupt is pending. */
@@ -956,7 +912,7 @@ static inline u32 armv7_pmnc_getreset_flags(void)
 }
 
 #ifdef DEBUG
-static void armv7_pmnc_dump_regs(void)
+static void armv7_pmnc_dump_regs(struct arm_pmu *cpu_pmu)
 {
 	u32 val;
 	unsigned int cnt;
@@ -981,7 +937,8 @@ static void armv7_pmnc_dump_regs(void)
 	asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
 	printk(KERN_INFO "CCNT  =0x%08x\n", val);
 
-	for (cnt = ARMV7_IDX_COUNTER0; cnt <= ARMV7_IDX_COUNTER_LAST; cnt++) {
+	for (cnt = ARMV7_IDX_COUNTER0;
+			cnt <= ARMV7_IDX_COUNTER_LAST(cpu_pmu); cnt++) {
 		armv7_pmnc_select_counter(cnt);
 		asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
 		printk(KERN_INFO "CNT[%d] count =0x%08x\n",
@@ -993,10 +950,19 @@ static void armv7_pmnc_dump_regs(void)
 }
 #endif
 
-static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
+static void armv7pmu_enable_event(struct perf_event *event)
 {
 	unsigned long flags;
+	struct hw_perf_event *hwc = &event->hw;
+	struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+	int idx = hwc->idx;
+
+	if (!armv7_pmnc_counter_valid(cpu_pmu, idx)) {
+		pr_err("CPU%u enabling wrong PMNC counter IRQ enable %d\n",
+			smp_processor_id(), idx);
+		return;
+	}
 
 	/*
 	 * Enable counter and interrupt, and set the counter to count
@@ -1014,7 +980,7 @@ static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
 	 * We only need to set the event for the cycle counter if we
 	 * have the ability to perform event filtering.
 	 */
-	if (armv7pmu.set_event_filter || idx != ARMV7_IDX_CYCLE_COUNTER)
+	if (cpu_pmu->set_event_filter || idx != ARMV7_IDX_CYCLE_COUNTER)
 		armv7_pmnc_write_evtsel(idx, hwc->config_base);
 
 	/*
@@ -1030,10 +996,19 @@ static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
 	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx)
+static void armv7pmu_disable_event(struct perf_event *event)
 {
 	unsigned long flags;
+	struct hw_perf_event *hwc = &event->hw;
+	struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+	int idx = hwc->idx;
+
+	if (!armv7_pmnc_counter_valid(cpu_pmu, idx)) {
+		pr_err("CPU%u disabling wrong PMNC counter IRQ enable %d\n",
+			smp_processor_id(), idx);
+		return;
+	}
 
 	/*
 	 * Disable counter and interrupt
@@ -1057,7 +1032,8 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
 {
 	u32 pmnc;
 	struct perf_sample_data data;
-	struct pmu_hw_events *cpuc;
+	struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
+	struct pmu_hw_events *cpuc = cpu_pmu->get_hw_events();
 	struct pt_regs *regs;
 	int idx;
 
@@ -1077,7 +1053,6 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
 	 */
 	regs = get_irq_regs();
 
-	cpuc = &__get_cpu_var(cpu_hw_events);
 	for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
 		struct perf_event *event = cpuc->events[idx];
 		struct hw_perf_event *hwc;
@@ -1094,13 +1069,13 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
 			continue;
 
 		hwc = &event->hw;
-		armpmu_event_update(event, hwc, idx);
+		armpmu_event_update(event);
 		perf_sample_data_init(&data, 0, hwc->last_period);
-		if (!armpmu_event_set_period(event, hwc, idx))
+		if (!armpmu_event_set_period(event))
 			continue;
 
 		if (perf_event_overflow(event, &data, regs))
-			cpu_pmu->disable(hwc, idx);
+			cpu_pmu->disable(event);
 	}
 
 	/*
@@ -1115,7 +1090,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
 	return IRQ_HANDLED;
 }
 
-static void armv7pmu_start(void)
+static void armv7pmu_start(struct arm_pmu *cpu_pmu)
 {
 	unsigned long flags;
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
@@ -1126,7 +1101,7 @@ static void armv7pmu_start(void)
 	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void armv7pmu_stop(void)
+static void armv7pmu_stop(struct arm_pmu *cpu_pmu)
 {
 	unsigned long flags;
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
@@ -1138,10 +1113,12 @@ static void armv7pmu_stop(void)
 }
 
 static int armv7pmu_get_event_idx(struct pmu_hw_events *cpuc,
-				  struct hw_perf_event *event)
+				  struct perf_event *event)
 {
 	int idx;
-	unsigned long evtype = event->config_base & ARMV7_EVTYPE_EVENT;
+	struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	unsigned long evtype = hwc->config_base & ARMV7_EVTYPE_EVENT;
 
 	/* Always place a cycle counter into the cycle counter. */
 	if (evtype == ARMV7_PERFCTR_CPU_CYCLES) {
@@ -1192,11 +1169,14 @@ static int armv7pmu_set_event_filter(struct hw_perf_event *event,
 
 static void armv7pmu_reset(void *info)
 {
+	struct arm_pmu *cpu_pmu = (struct arm_pmu *)info;
 	u32 idx, nb_cnt = cpu_pmu->num_events;
 
 	/* The counter and interrupt enable registers are unknown at reset. */
-	for (idx = ARMV7_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx)
-		armv7pmu_disable_event(NULL, idx);
+	for (idx = ARMV7_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx) {
+		armv7_pmnc_disable_counter(idx);
+		armv7_pmnc_disable_intens(idx);
+	}
 
 	/* Initialize & Reset PMNC: C and P bits */
 	armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
@@ -1232,17 +1212,18 @@ static int armv7_a7_map_event(struct perf_event *event)
 				&armv7_a7_perf_cache_map, 0xFF);
 }
 
-static struct arm_pmu armv7pmu = {
-	.handle_irq		= armv7pmu_handle_irq,
-	.enable			= armv7pmu_enable_event,
-	.disable		= armv7pmu_disable_event,
-	.read_counter		= armv7pmu_read_counter,
-	.write_counter		= armv7pmu_write_counter,
-	.get_event_idx		= armv7pmu_get_event_idx,
-	.start			= armv7pmu_start,
-	.stop			= armv7pmu_stop,
-	.reset			= armv7pmu_reset,
-	.max_period		= (1LLU << 32) - 1,
+static void armv7pmu_init(struct arm_pmu *cpu_pmu)
+{
+	cpu_pmu->handle_irq	= armv7pmu_handle_irq;
+	cpu_pmu->enable		= armv7pmu_enable_event;
+	cpu_pmu->disable	= armv7pmu_disable_event;
+	cpu_pmu->read_counter	= armv7pmu_read_counter;
+	cpu_pmu->write_counter	= armv7pmu_write_counter;
+	cpu_pmu->get_event_idx	= armv7pmu_get_event_idx;
+	cpu_pmu->start		= armv7pmu_start;
+	cpu_pmu->stop		= armv7pmu_stop;
+	cpu_pmu->reset		= armv7pmu_reset;
+	cpu_pmu->max_period	= (1LLU << 32) - 1;
 };
 
 static u32 __devinit armv7_read_num_pmnc_events(void)
@@ -1256,70 +1237,75 @@ static u32 __devinit armv7_read_num_pmnc_events(void)
 	return nb_cnt + 1;
 }
 
-static struct arm_pmu *__devinit armv7_a8_pmu_init(void)
+static int __devinit armv7_a8_pmu_init(struct arm_pmu *cpu_pmu)
 {
-	armv7pmu.name		= "ARMv7 Cortex-A8";
-	armv7pmu.map_event	= armv7_a8_map_event;
-	armv7pmu.num_events	= armv7_read_num_pmnc_events();
-	return &armv7pmu;
+	armv7pmu_init(cpu_pmu);
+	cpu_pmu->name		= "ARMv7 Cortex-A8";
+	cpu_pmu->map_event	= armv7_a8_map_event;
+	cpu_pmu->num_events	= armv7_read_num_pmnc_events();
+	return 0;
 }
 
-static struct arm_pmu *__devinit armv7_a9_pmu_init(void)
+static int __devinit armv7_a9_pmu_init(struct arm_pmu *cpu_pmu)
 {
-	armv7pmu.name		= "ARMv7 Cortex-A9";
-	armv7pmu.map_event	= armv7_a9_map_event;
-	armv7pmu.num_events	= armv7_read_num_pmnc_events();
-	return &armv7pmu;
+	armv7pmu_init(cpu_pmu);
+	cpu_pmu->name		= "ARMv7 Cortex-A9";
+	cpu_pmu->map_event	= armv7_a9_map_event;
+	cpu_pmu->num_events	= armv7_read_num_pmnc_events();
+	return 0;
 }
 
-static struct arm_pmu *__devinit armv7_a5_pmu_init(void)
+static int __devinit armv7_a5_pmu_init(struct arm_pmu *cpu_pmu)
 {
-	armv7pmu.name		= "ARMv7 Cortex-A5";
-	armv7pmu.map_event	= armv7_a5_map_event;
-	armv7pmu.num_events	= armv7_read_num_pmnc_events();
-	return &armv7pmu;
+	armv7pmu_init(cpu_pmu);
+	cpu_pmu->name		= "ARMv7 Cortex-A5";
+	cpu_pmu->map_event	= armv7_a5_map_event;
+	cpu_pmu->num_events	= armv7_read_num_pmnc_events();
+	return 0;
 }
 
-static struct arm_pmu *__devinit armv7_a15_pmu_init(void)
+static int __devinit armv7_a15_pmu_init(struct arm_pmu *cpu_pmu)
 {
-	armv7pmu.name		= "ARMv7 Cortex-A15";
-	armv7pmu.map_event	= armv7_a15_map_event;
-	armv7pmu.num_events	= armv7_read_num_pmnc_events();
-	armv7pmu.set_event_filter = armv7pmu_set_event_filter;
-	return &armv7pmu;
+	armv7pmu_init(cpu_pmu);
+	cpu_pmu->name		= "ARMv7 Cortex-A15";
+	cpu_pmu->map_event	= armv7_a15_map_event;
+	cpu_pmu->num_events	= armv7_read_num_pmnc_events();
+	cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
+	return 0;
 }
 
-static struct arm_pmu *__devinit armv7_a7_pmu_init(void)
+static int __devinit armv7_a7_pmu_init(struct arm_pmu *cpu_pmu)
 {
-	armv7pmu.name		= "ARMv7 Cortex-A7";
-	armv7pmu.map_event	= armv7_a7_map_event;
-	armv7pmu.num_events	= armv7_read_num_pmnc_events();
-	armv7pmu.set_event_filter = armv7pmu_set_event_filter;
-	return &armv7pmu;
+	armv7pmu_init(cpu_pmu);
+	cpu_pmu->name		= "ARMv7 Cortex-A7";
+	cpu_pmu->map_event	= armv7_a7_map_event;
+	cpu_pmu->num_events	= armv7_read_num_pmnc_events();
+	cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
+	return 0;
 }
 #else
-static struct arm_pmu *__devinit armv7_a8_pmu_init(void)
+static inline int armv7_a8_pmu_init(struct arm_pmu *cpu_pmu)
 {
-	return NULL;
+	return -ENODEV;
 }
 
-static struct arm_pmu *__devinit armv7_a9_pmu_init(void)
+static inline int armv7_a9_pmu_init(struct arm_pmu *cpu_pmu)
 {
-	return NULL;
+	return -ENODEV;
 }
 
-static struct arm_pmu *__devinit armv7_a5_pmu_init(void)
+static inline int armv7_a5_pmu_init(struct arm_pmu *cpu_pmu)
 {
-	return NULL;
+	return -ENODEV;
 }
 
-static struct arm_pmu *__devinit armv7_a15_pmu_init(void)
+static inline int armv7_a15_pmu_init(struct arm_pmu *cpu_pmu)
 {
-	return NULL;
+	return -ENODEV;
 }
 
-static struct arm_pmu *__devinit armv7_a7_pmu_init(void)
+static inline int armv7_a7_pmu_init(struct arm_pmu *cpu_pmu)
 {
-	return NULL;
+	return -ENODEV;
 }
 #endif	/* CONFIG_CPU_V7 */
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c
index 426e19f..0c8265e 100644
--- a/arch/arm/kernel/perf_event_xscale.c
+++ b/arch/arm/kernel/perf_event_xscale.c
@@ -224,7 +224,8 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
 {
 	unsigned long pmnc;
 	struct perf_sample_data data;
-	struct pmu_hw_events *cpuc;
+	struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
+	struct pmu_hw_events *cpuc = cpu_pmu->get_hw_events();
 	struct pt_regs *regs;
 	int idx;
 
@@ -248,7 +249,6 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
 
 	regs = get_irq_regs();
 
-	cpuc = &__get_cpu_var(cpu_hw_events);
 	for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
 		struct perf_event *event = cpuc->events[idx];
 		struct hw_perf_event *hwc;
@@ -260,13 +260,13 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
 			continue;
 
 		hwc = &event->hw;
-		armpmu_event_update(event, hwc, idx);
+		armpmu_event_update(event);
 		perf_sample_data_init(&data, 0, hwc->last_period);
-		if (!armpmu_event_set_period(event, hwc, idx))
+		if (!armpmu_event_set_period(event))
 			continue;
 
 		if (perf_event_overflow(event, &data, regs))
-			cpu_pmu->disable(hwc, idx);
+			cpu_pmu->disable(event);
 	}
 
 	irq_work_run();
@@ -280,11 +280,13 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
 	return IRQ_HANDLED;
 }
 
-static void
-xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx)
+static void xscale1pmu_enable_event(struct perf_event *event)
 {
 	unsigned long val, mask, evt, flags;
+	struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+	int idx = hwc->idx;
 
 	switch (idx) {
 	case XSCALE_CYCLE_COUNTER:
@@ -314,11 +316,13 @@ xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx)
 	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void
-xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx)
+static void xscale1pmu_disable_event(struct perf_event *event)
 {
 	unsigned long val, mask, evt, flags;
+	struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+	int idx = hwc->idx;
 
 	switch (idx) {
 	case XSCALE_CYCLE_COUNTER:
@@ -348,9 +352,10 @@ xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx)
 
 static int
 xscale1pmu_get_event_idx(struct pmu_hw_events *cpuc,
-			struct hw_perf_event *event)
+				struct perf_event *event)
 {
-	if (XSCALE_PERFCTR_CCNT == event->config_base) {
+	struct hw_perf_event *hwc = &event->hw;
+	if (XSCALE_PERFCTR_CCNT == hwc->config_base) {
 		if (test_and_set_bit(XSCALE_CYCLE_COUNTER, cpuc->used_mask))
 			return -EAGAIN;
 
@@ -366,8 +371,7 @@ xscale1pmu_get_event_idx(struct pmu_hw_events *cpuc,
 	}
 }
 
-static void
-xscale1pmu_start(void)
+static void xscale1pmu_start(struct arm_pmu *cpu_pmu)
 {
 	unsigned long flags, val;
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
@@ -379,8 +383,7 @@ xscale1pmu_start(void)
 	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void
-xscale1pmu_stop(void)
+static void xscale1pmu_stop(struct arm_pmu *cpu_pmu)
 {
 	unsigned long flags, val;
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
@@ -392,9 +395,10 @@ xscale1pmu_stop(void)
 	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static inline u32
-xscale1pmu_read_counter(int counter)
+static inline u32 xscale1pmu_read_counter(struct perf_event *event)
 {
+	struct hw_perf_event *hwc = &event->hw;
+	int counter = hwc->idx;
 	u32 val = 0;
 
 	switch (counter) {
@@ -412,9 +416,11 @@ xscale1pmu_read_counter(int counter)
 	return val;
 }
 
-static inline void
-xscale1pmu_write_counter(int counter, u32 val)
+static inline void xscale1pmu_write_counter(struct perf_event *event, u32 val)
 {
+	struct hw_perf_event *hwc = &event->hw;
+	int counter = hwc->idx;
+
 	switch (counter) {
 	case XSCALE_CYCLE_COUNTER:
 		asm volatile("mcr p14, 0, %0, c1, c0, 0" : : "r" (val));
@@ -434,24 +440,22 @@ static int xscale_map_event(struct perf_event *event)
 				&xscale_perf_cache_map, 0xFF);
 }
 
-static struct arm_pmu xscale1pmu = {
-	.name		= "xscale1",
-	.handle_irq	= xscale1pmu_handle_irq,
-	.enable		= xscale1pmu_enable_event,
-	.disable	= xscale1pmu_disable_event,
-	.read_counter	= xscale1pmu_read_counter,
-	.write_counter	= xscale1pmu_write_counter,
-	.get_event_idx	= xscale1pmu_get_event_idx,
-	.start		= xscale1pmu_start,
-	.stop		= xscale1pmu_stop,
-	.map_event	= xscale_map_event,
-	.num_events	= 3,
-	.max_period	= (1LLU << 32) - 1,
-};
-
-static struct arm_pmu *__devinit xscale1pmu_init(void)
+static int __devinit xscale1pmu_init(struct arm_pmu *cpu_pmu)
 {
-	return &xscale1pmu;
+	cpu_pmu->name		= "xscale1";
+	cpu_pmu->handle_irq	= xscale1pmu_handle_irq;
+	cpu_pmu->enable		= xscale1pmu_enable_event;
+	cpu_pmu->disable	= xscale1pmu_disable_event;
+	cpu_pmu->read_counter	= xscale1pmu_read_counter;
+	cpu_pmu->write_counter	= xscale1pmu_write_counter;
+	cpu_pmu->get_event_idx	= xscale1pmu_get_event_idx;
+	cpu_pmu->start		= xscale1pmu_start;
+	cpu_pmu->stop		= xscale1pmu_stop;
+	cpu_pmu->map_event	= xscale_map_event;
+	cpu_pmu->num_events	= 3;
+	cpu_pmu->max_period	= (1LLU << 32) - 1;
+
+	return 0;
 }
 
 #define XSCALE2_OVERFLOWED_MASK	0x01f
@@ -567,7 +571,8 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
 {
 	unsigned long pmnc, of_flags;
 	struct perf_sample_data data;
-	struct pmu_hw_events *cpuc;
+	struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
+	struct pmu_hw_events *cpuc = cpu_pmu->get_hw_events();
 	struct pt_regs *regs;
 	int idx;
 
@@ -585,7 +590,6 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
 
 	regs = get_irq_regs();
 
-	cpuc = &__get_cpu_var(cpu_hw_events);
 	for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
 		struct perf_event *event = cpuc->events[idx];
 		struct hw_perf_event *hwc;
@@ -597,13 +601,13 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
 			continue;
 
 		hwc = &event->hw;
-		armpmu_event_update(event, hwc, idx);
+		armpmu_event_update(event);
 		perf_sample_data_init(&data, 0, hwc->last_period);
-		if (!armpmu_event_set_period(event, hwc, idx))
+		if (!armpmu_event_set_period(event))
 			continue;
 
 		if (perf_event_overflow(event, &data, regs))
-			cpu_pmu->disable(hwc, idx);
+			cpu_pmu->disable(event);
 	}
 
 	irq_work_run();
@@ -617,11 +621,13 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
 	return IRQ_HANDLED;
 }
 
-static void
-xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)
+static void xscale2pmu_enable_event(struct perf_event *event)
 {
 	unsigned long flags, ien, evtsel;
+	struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+	int idx = hwc->idx;
 
 	ien = xscale2pmu_read_int_enable();
 	evtsel = xscale2pmu_read_event_select();
@@ -661,11 +667,13 @@ xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)
 	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void
-xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)
+static void xscale2pmu_disable_event(struct perf_event *event)
 {
 	unsigned long flags, ien, evtsel, of_flags;
+	struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+	int idx = hwc->idx;
 
 	ien = xscale2pmu_read_int_enable();
 	evtsel = xscale2pmu_read_event_select();
@@ -713,7 +721,7 @@ xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)
 
 static int
 xscale2pmu_get_event_idx(struct pmu_hw_events *cpuc,
-			struct hw_perf_event *event)
+				struct perf_event *event)
 {
 	int idx = xscale1pmu_get_event_idx(cpuc, event);
 	if (idx >= 0)
@@ -727,8 +735,7 @@ out:
 	return idx;
 }
 
-static void
-xscale2pmu_start(void)
+static void xscale2pmu_start(struct arm_pmu *cpu_pmu)
 {
 	unsigned long flags, val;
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
@@ -740,8 +747,7 @@ xscale2pmu_start(void)
 	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static void
-xscale2pmu_stop(void)
+static void xscale2pmu_stop(struct arm_pmu *cpu_pmu)
 {
 	unsigned long flags, val;
 	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
@@ -753,9 +759,10 @@ xscale2pmu_stop(void)
 	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 }
 
-static inline u32
-xscale2pmu_read_counter(int counter)
+static inline u32 xscale2pmu_read_counter(struct perf_event *event)
 {
+	struct hw_perf_event *hwc = &event->hw;
+	int counter = hwc->idx;
 	u32 val = 0;
 
 	switch (counter) {
@@ -779,9 +786,11 @@ xscale2pmu_read_counter(int counter)
 	return val;
 }
 
-static inline void
-xscale2pmu_write_counter(int counter, u32 val)
+static inline void xscale2pmu_write_counter(struct perf_event *event, u32 val)
 {
+	struct hw_perf_event *hwc = &event->hw;
+	int counter = hwc->idx;
+
 	switch (counter) {
 	case XSCALE_CYCLE_COUNTER:
 		asm volatile("mcr p14, 0, %0, c1, c1, 0" : : "r" (val));
@@ -801,33 +810,31 @@ xscale2pmu_write_counter(int counter, u32 val)
 	}
 }
 
-static struct arm_pmu xscale2pmu = {
-	.name		= "xscale2",
-	.handle_irq	= xscale2pmu_handle_irq,
-	.enable		= xscale2pmu_enable_event,
-	.disable	= xscale2pmu_disable_event,
-	.read_counter	= xscale2pmu_read_counter,
-	.write_counter	= xscale2pmu_write_counter,
-	.get_event_idx	= xscale2pmu_get_event_idx,
-	.start		= xscale2pmu_start,
-	.stop		= xscale2pmu_stop,
-	.map_event	= xscale_map_event,
-	.num_events	= 5,
-	.max_period	= (1LLU << 32) - 1,
-};
-
-static struct arm_pmu *__devinit xscale2pmu_init(void)
+static int __devinit xscale2pmu_init(struct arm_pmu *cpu_pmu)
 {
-	return &xscale2pmu;
+	cpu_pmu->name		= "xscale2";
+	cpu_pmu->handle_irq	= xscale2pmu_handle_irq;
+	cpu_pmu->enable		= xscale2pmu_enable_event;
+	cpu_pmu->disable	= xscale2pmu_disable_event;
+	cpu_pmu->read_counter	= xscale2pmu_read_counter;
+	cpu_pmu->write_counter	= xscale2pmu_write_counter;
+	cpu_pmu->get_event_idx	= xscale2pmu_get_event_idx;
+	cpu_pmu->start		= xscale2pmu_start;
+	cpu_pmu->stop		= xscale2pmu_stop;
+	cpu_pmu->map_event	= xscale_map_event;
+	cpu_pmu->num_events	= 5;
+	cpu_pmu->max_period	= (1LLU << 32) - 1;
+
+	return 0;
 }
 #else
-static struct arm_pmu *__devinit xscale1pmu_init(void)
+static inline int xscale1pmu_init(struct arm_pmu *cpu_pmu)
 {
-	return NULL;
+	return -ENODEV;
 }
 
-static struct arm_pmu *__devinit xscale2pmu_init(void)
+static inline int xscale2pmu_init(struct arm_pmu *cpu_pmu)
 {
-	return NULL;
+	return -ENODEV;
 }
 #endif	/* CONFIG_CPU_XSCALE */
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 90084a6..f79dd1e 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -34,6 +34,7 @@
 #include <linux/leds.h>
 
 #include <asm/cacheflush.h>
+#include <asm/idmap.h>
 #include <asm/processor.h>
 #include <asm/thread_notify.h>
 #include <asm/stacktrace.h>
@@ -56,8 +57,6 @@ static const char *isa_modes[] = {
   "ARM" , "Thumb" , "Jazelle", "ThumbEE"
 };
 
-extern void setup_mm_for_reboot(void);
-
 static volatile int hlt_counter;
 
 void disable_hlt(void)
@@ -70,6 +69,7 @@ EXPORT_SYMBOL(disable_hlt);
 void enable_hlt(void)
 {
 	hlt_counter--;
+	BUG_ON(hlt_counter < 0);
 }
 
 EXPORT_SYMBOL(enable_hlt);
@@ -376,17 +376,22 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
 int
 copy_thread(unsigned long clone_flags, unsigned long stack_start,
-	    unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs)
+	    unsigned long stk_sz, struct task_struct *p)
 {
 	struct thread_info *thread = task_thread_info(p);
 	struct pt_regs *childregs = task_pt_regs(p);
 
 	memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
 
-	if (likely(regs)) {
-		*childregs = *regs;
+	if (likely(!(p->flags & PF_KTHREAD))) {
+		*childregs = *current_pt_regs();
 		childregs->ARM_r0 = 0;
-		childregs->ARM_sp = stack_start;
+		if (stack_start)
+			childregs->ARM_sp = stack_start;
+#if defined CONFIG_CPU_V7M
+		/* Return to Thread mode with Process stack */
+		childregs->ARM_EXC_RET = 0xfffffffdUL;
+#endif
 	} else {
 		memset(childregs, 0, sizeof(struct pt_regs));
 		thread->cpu_context.r4 = stk_sz;
@@ -399,7 +404,7 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
 	clear_ptrace_hw_breakpoint(p);
 
 	if (clone_flags & CLONE_SETTLS)
-		thread->tp_value = regs->ARM_r3;
+		thread->tp_value = childregs->ARM_r3;
 
 	thread_notify(THREAD_NOTIFY_COPY, thread);
 
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 739db3a..8725a8b 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -87,6 +87,9 @@ static const struct pt_regs_offset regoffset_table[] = {
 	REG_OFFSET_NAME(pc),
 	REG_OFFSET_NAME(cpsr),
 	REG_OFFSET_NAME(ORIG_r0),
+#ifdef CONFIG_CPU_V7M
+	REG_OFFSET_NAME(EXC_RET),
+#endif
 	REG_OFFSET_END,
 };
 
@@ -916,16 +919,11 @@ enum ptrace_syscall_dir {
 	PTRACE_SYSCALL_EXIT,
 };
 
-static int ptrace_syscall_trace(struct pt_regs *regs, int scno,
-				enum ptrace_syscall_dir dir)
+static int tracehook_report_syscall(struct pt_regs *regs,
+				    enum ptrace_syscall_dir dir)
 {
 	unsigned long ip;
 
-	current_thread_info()->syscall = scno;
-
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		return scno;
-
 	/*
 	 * IP is used to denote syscall entry/exit:
 	 * IP = 0 -> entry, =1 -> exit
@@ -944,19 +942,35 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno,
 
 asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno)
 {
-	scno = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_ENTER);
+	current_thread_info()->syscall = scno;
+
+	/* Do the secure computing check first; failures should be fast. */
+	if (secure_computing(scno) == -1)
+		return -1;
+
+	if (test_thread_flag(TIF_SYSCALL_TRACE))
+		scno = tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
+
 	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
 		trace_sys_enter(regs, scno);
+
 	audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, regs->ARM_r1,
 			    regs->ARM_r2, regs->ARM_r3);
+
 	return scno;
 }
 
 asmlinkage int syscall_trace_exit(struct pt_regs *regs, int scno)
 {
-	scno = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_EXIT);
+	current_thread_info()->syscall = scno;
+
+	if (test_thread_flag(TIF_SYSCALL_TRACE))
+		scno = tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
+
 	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
 		trace_sys_exit(regs, scno);
+
 	audit_syscall_exit(regs);
+
 	return scno;
 }
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index da1d1aa..388214b 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -128,7 +128,9 @@ struct stack {
 	u32 und[3];
 } ____cacheline_aligned;
 
+#ifndef CONFIG_CPU_V7M
 static struct stack stacks[NR_CPUS];
+#endif
 
 char elf_platform[ELF_PLATFORM_SIZE];
 EXPORT_SYMBOL(elf_platform);
@@ -207,7 +209,7 @@ static const char *proc_arch[] = {
 	"5TEJ",
 	"6TEJ",
 	"7",
-	"?(11)",
+	"7M",
 	"?(12)",
 	"?(13)",
 	"?(14)",
@@ -216,6 +218,12 @@ static const char *proc_arch[] = {
 	"?(17)",
 };
 
+#ifdef CONFIG_CPU_V7M
+static int __get_cpu_architecture(void)
+{
+	return CPU_ARCH_ARMv7M;
+}
+#else
 static int __get_cpu_architecture(void)
 {
 	int cpu_arch;
@@ -248,6 +256,7 @@ static int __get_cpu_architecture(void)
 
 	return cpu_arch;
 }
+#endif
 
 int __pure cpu_architecture(void)
 {
@@ -375,6 +384,7 @@ static void __init feat_v6_fixup(void)
  */
 void cpu_init(void)
 {
+#ifndef CONFIG_CPU_V7M
 	unsigned int cpu = smp_processor_id();
 	struct stack *stk = &stacks[cpu];
 
@@ -419,6 +429,7 @@ void cpu_init(void)
 	      "I" (offsetof(struct stack, und[0])),
 	      PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
 	    : "r14");
+#endif
 }
 
 int __cpu_logical_map[NR_CPUS];
@@ -426,13 +437,14 @@ int __cpu_logical_map[NR_CPUS];
 void __init smp_setup_processor_id(void)
 {
 	int i;
-	u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0;
+	u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0;
+	u32 cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
 
 	cpu_logical_map(0) = cpu;
-	for (i = 1; i < NR_CPUS; ++i)
+	for (i = 1; i < nr_cpu_ids; ++i)
 		cpu_logical_map(i) = i == cpu ? 0 : i;
 
-	printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu);
+	printk(KERN_INFO "Booting Linux on physical CPU 0x%x\n", mpidr);
 }
 
 static void __init setup_processor(void)
@@ -758,6 +770,7 @@ void __init setup_arch(char **cmdline_p)
 
 	unflatten_device_tree();
 
+	arm_dt_init_cpu_maps();
 #ifdef CONFIG_SMP
 	if (is_smp()) {
 		smp_set_ops(mdesc->smp);
@@ -841,12 +854,9 @@ static const char *hwcap_str[] = {
 
 static int c_show(struct seq_file *m, void *v)
 {
-	int i;
-
-	seq_printf(m, "Processor\t: %s rev %d (%s)\n",
-		   cpu_name, read_cpuid_id() & 15, elf_platform);
+	int i, j;
+	u32 cpuid;
 
-#if defined(CONFIG_SMP)
 	for_each_online_cpu(i) {
 		/*
 		 * glibc reads /proc/cpuinfo to determine the number of
@@ -854,45 +864,48 @@ static int c_show(struct seq_file *m, void *v)
 		 * "processor".  Give glibc what it expects.
 		 */
 		seq_printf(m, "processor\t: %d\n", i);
-		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
+		cpuid = is_smp() ? per_cpu(cpu_data, i).cpuid : read_cpuid_id();
+		seq_printf(m, "model name\t: %s rev %d (%s)\n",
+			   cpu_name, cpuid & 15, elf_platform);
+
+#if defined(CONFIG_SMP)
+		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
 			   per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
 			   (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
-	}
-#else /* CONFIG_SMP */
-	seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
-		   loops_per_jiffy / (500000/HZ),
-		   (loops_per_jiffy / (5000/HZ)) % 100);
+#else
+		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
+			   loops_per_jiffy / (500000/HZ),
+			   (loops_per_jiffy / (5000/HZ)) % 100);
 #endif
+		/* dump out the processor features */
+		seq_puts(m, "Features\t: ");
 
-	/* dump out the processor features */
-	seq_puts(m, "Features\t: ");
+		for (j = 0; hwcap_str[j]; j++)
+			if (elf_hwcap & (1 << j))
+				seq_printf(m, "%s ", hwcap_str[j]);
 
-	for (i = 0; hwcap_str[i]; i++)
-		if (elf_hwcap & (1 << i))
-			seq_printf(m, "%s ", hwcap_str[i]);
+		seq_printf(m, "\nCPU implementer\t: 0x%02x\n", cpuid >> 24);
+		seq_printf(m, "CPU architecture: %s\n",
+			   proc_arch[cpu_architecture()]);
 
-	seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
-	seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
-
-	if ((read_cpuid_id() & 0x0008f000) == 0x00000000) {
-		/* pre-ARM7 */
-		seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4);
-	} else {
-		if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
-			/* ARM7 */
-			seq_printf(m, "CPU variant\t: 0x%02x\n",
-				   (read_cpuid_id() >> 16) & 127);
+		if ((cpuid & 0x0008f000) == 0x00000000) {
+			/* pre-ARM7 */
+			seq_printf(m, "CPU part\t: %07x\n", cpuid >> 4);
 		} else {
-			/* post-ARM7 */
-			seq_printf(m, "CPU variant\t: 0x%x\n",
-				   (read_cpuid_id() >> 20) & 15);
+			if ((cpuid & 0x0008f000) == 0x00007000) {
+				/* ARM7 */
+				seq_printf(m, "CPU variant\t: 0x%02x\n",
+					   (cpuid >> 16) & 127);
+			} else {
+				/* post-ARM7 */
+				seq_printf(m, "CPU variant\t: 0x%x\n",
+					   (cpuid >> 20) & 15);
+			}
+			seq_printf(m, "CPU part\t: 0x%03x\n",
+				   (cpuid >> 4) & 0xfff);
 		}
-		seq_printf(m, "CPU part\t: 0x%03x\n",
-			   (read_cpuid_id() >> 4) & 0xfff);
+		seq_printf(m, "CPU revision\t: %d\n\n", cpuid & 15);
 	}
-	seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
-
-	seq_puts(m, "\n");
 
 	seq_printf(m, "Hardware\t: %s\n", machine_name);
 	seq_printf(m, "Revision\t: %04x\n", system_rev);
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index fbc8b26..7ece3dd 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -281,6 +281,7 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid)
 	struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);
 
 	cpu_info->loops_per_jiffy = loops_per_jiffy;
+	cpu_info->cpuid = read_cpuid_id();
 
 	store_cpu_topology(cpuid);
 }
@@ -421,6 +422,11 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask)
 	smp_cross_call(mask, IPI_CALL_FUNC);
 }
 
+void arch_send_wakeup_ipi_mask(const struct cpumask *mask)
+{
+	smp_cross_call(mask, IPI_WAKEUP);
+}
+
 void arch_send_call_function_single_ipi(int cpu)
 {
 	smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index b22d700..49f335d 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -31,6 +31,8 @@ static void __iomem *twd_base;
 
 static struct clk *twd_clk;
 static unsigned long twd_timer_rate;
+static bool common_setup_called;
+static DEFINE_PER_CPU(bool, percpu_setup_called);
 
 static struct clock_event_device __percpu **twd_evt;
 static int twd_ppi;
@@ -248,17 +250,9 @@ static struct clk *twd_get_clock(void)
 		return clk;
 	}
 
-	err = clk_prepare(clk);
+	err = clk_prepare_enable(clk);
 	if (err) {
-		pr_err("smp_twd: clock failed to prepare: %d\n", err);
-		clk_put(clk);
-		return ERR_PTR(err);
-	}
-
-	err = clk_enable(clk);
-	if (err) {
-		pr_err("smp_twd: clock failed to enable: %d\n", err);
-		clk_unprepare(clk);
+		pr_err("smp_twd: clock failed to prepare+enable: %d\n", err);
 		clk_put(clk);
 		return ERR_PTR(err);
 	}
@@ -272,15 +266,45 @@ static struct clk *twd_get_clock(void)
 static int __cpuinit twd_timer_setup(struct clock_event_device *clk)
 {
 	struct clock_event_device **this_cpu_clk;
+	int cpu = smp_processor_id();
+
+	/*
+	 * If the basic setup for this CPU has been done before don't
+	 * bother with the below.
+	 */
+	if (per_cpu(percpu_setup_called, cpu)) {
+		__raw_writel(0, twd_base + TWD_TIMER_CONTROL);
+		clockevents_register_device(*__this_cpu_ptr(twd_evt));
+		enable_percpu_irq(clk->irq, 0);
+		return 0;
+	}
+	per_cpu(percpu_setup_called, cpu) = true;
 
-	if (!twd_clk)
+	/*
+	 * This stuff only need to be done once for the entire TWD cluster
+	 * during the runtime of the system.
+	 */
+	if (!common_setup_called) {
 		twd_clk = twd_get_clock();
 
-	if (!IS_ERR_OR_NULL(twd_clk))
-		twd_timer_rate = clk_get_rate(twd_clk);
-	else
-		twd_calibrate_rate();
+		/*
+		 * We use IS_ERR_OR_NULL() here, because if the clock stubs
+		 * are active we will get a valid clk reference which is
+		 * however NULL and will return the rate 0. In that case we
+		 * need to calibrate the rate instead.
+		 */
+		if (!IS_ERR_OR_NULL(twd_clk))
+			twd_timer_rate = clk_get_rate(twd_clk);
+		else
+			twd_calibrate_rate();
+
+		common_setup_called = true;
+	}
 
+	/*
+	 * The following is done once per CPU the first time .setup() is
+	 * called.
+	 */
 	__raw_writel(0, twd_base + TWD_TIMER_CONTROL);
 
 	clk->name = "local_timer";
@@ -366,10 +390,8 @@ void __init twd_local_timer_of_register(void)
 	int err;
 
 	np = of_find_matching_node(NULL, twd_of_match);
-	if (!np) {
-		err = -ENODEV;
-		goto out;
-	}
+	if (!np)
+		return;
 
 	twd_ppi = irq_of_parse_and_map(np, 0);
 	if (!twd_ppi) {
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index c2a898a..3151f56 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -28,37 +28,6 @@
 #include <linux/uaccess.h>
 #include <linux/slab.h>
 
-/* Fork a new task - this creates a new program thread.
- * This is called indirectly via a small wrapper
- */
-asmlinkage int sys_fork(struct pt_regs *regs)
-{
-#ifdef CONFIG_MMU
-	return do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
-#else
-	/* can not support in nommu mode */
-	return(-EINVAL);
-#endif
-}
-
-/* Clone a task - this clones the calling program thread.
- * This is called indirectly via a small wrapper
- */
-asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
-			 int __user *parent_tidptr, int tls_val,
-			 int __user *child_tidptr, struct pt_regs *regs)
-{
-	if (!newsp)
-		newsp = regs->ARM_sp;
-
-	return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
-}
-
-asmlinkage int sys_vfork(struct pt_regs *regs)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
-}
-
 /*
  * Since loff_t is a 64 bit type we avoid a lot of ABI hassle
  * with a different argument ordering.
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index 26c12c6..79282eb 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -196,32 +196,7 @@ static inline void parse_dt_topology(void) {}
 static inline void update_cpu_power(unsigned int cpuid, unsigned int mpidr) {}
 #endif
 
-
-/*
- * cpu topology management
- */
-
-#define MPIDR_SMP_BITMASK (0x3 << 30)
-#define MPIDR_SMP_VALUE (0x2 << 30)
-
-#define MPIDR_MT_BITMASK (0x1 << 24)
-
-/*
- * These masks reflect the current use of the affinity levels.
- * The affinity level can be up to 16 bits according to ARM ARM
- */
-#define MPIDR_HWID_BITMASK 0xFFFFFF
-
-#define MPIDR_LEVEL0_MASK 0x3
-#define MPIDR_LEVEL0_SHIFT 0
-
-#define MPIDR_LEVEL1_MASK 0xF
-#define MPIDR_LEVEL1_SHIFT 8
-
-#define MPIDR_LEVEL2_MASK 0xFF
-#define MPIDR_LEVEL2_SHIFT 16
-
-/*
+ /*
  * cpu topology table
  */
 struct cputopo_arm cpu_topology[NR_CPUS];
@@ -282,19 +257,14 @@ void store_cpu_topology(unsigned int cpuid)
 
 		if (mpidr & MPIDR_MT_BITMASK) {
 			/* core performance interdependency */
-			cpuid_topo->thread_id = (mpidr >> MPIDR_LEVEL0_SHIFT)
-				& MPIDR_LEVEL0_MASK;
-			cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL1_SHIFT)
-				& MPIDR_LEVEL1_MASK;
-			cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL2_SHIFT)
-				& MPIDR_LEVEL2_MASK;
+			cpuid_topo->thread_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+			cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+			cpuid_topo->socket_id = MPIDR_AFFINITY_LEVEL(mpidr, 2);
 		} else {
 			/* largely independent cores */
 			cpuid_topo->thread_id = -1;
-			cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL0_SHIFT)
-				& MPIDR_LEVEL0_MASK;
-			cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL1_SHIFT)
-				& MPIDR_LEVEL1_MASK;
+			cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+			cpuid_topo->socket_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
 		}
 	} else {
 		/*
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index b0179b8..12d976b 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -819,6 +819,7 @@ static void __init kuser_get_tls_init(unsigned long vectors)
 
 void __init early_trap_init(void *vectors_base)
 {
+#ifndef CONFIG_CPU_V7M
 	unsigned long vectors = (unsigned long)vectors_base;
 	extern char __stubs_start[], __stubs_end[];
 	extern char __vectors_start[], __vectors_end[];
@@ -850,4 +851,5 @@ void __init early_trap_init(void *vectors_base)
 
 	flush_icache_range(vectors, vectors + PAGE_SIZE);
 	modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
+#endif
 }
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 36ff15b..b9f38e3 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -114,6 +114,15 @@ SECTIONS
 
 	RO_DATA(PAGE_SIZE)
 
+	. = ALIGN(4);
+	__ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
+		__start___ex_table = .;
+#ifdef CONFIG_MMU
+		*(__ex_table)
+#endif
+		__stop___ex_table = .;
+	}
+
 #ifdef CONFIG_ARM_UNWIND
 	/*
 	 * Stack unwinding tables
@@ -220,16 +229,6 @@ SECTIONS
 		READ_MOSTLY_DATA(L1_CACHE_BYTES)
 
 		/*
-		 * The exception fixup table (might need resorting at runtime)
-		 */
-		. = ALIGN(4);
-		__start___ex_table = .;
-#ifdef CONFIG_MMU
-		*(__ex_table)
-#endif
-		__stop___ex_table = .;
-
-		/*
 		 * and the usual data section
 		 */
 		DATA_DATA
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 0436242..958358c 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -39,7 +39,6 @@ config SOC_AT91RM9200
 config SOC_AT91SAM9260
 	bool "AT91SAM9260, AT91SAM9XE or AT91SAM9G20"
 	select HAVE_AT91_DBGU0
-	select HAVE_NET_MACB
 	select SOC_AT91SAM9
 	help
 	  Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE
@@ -57,7 +56,6 @@ config SOC_AT91SAM9263
 	bool "AT91SAM9263"
 	select HAVE_AT91_DBGU1
 	select HAVE_FB_ATMEL
-	select HAVE_NET_MACB
 	select SOC_AT91SAM9
 
 config SOC_AT91SAM9RL
@@ -70,7 +68,6 @@ config SOC_AT91SAM9G45
 	bool "AT91SAM9G45 or AT91SAM9M10 families"
 	select HAVE_AT91_DBGU1
 	select HAVE_FB_ATMEL
-	select HAVE_NET_MACB
 	select SOC_AT91SAM9
 	help
 	  Select this if you are using one of Atmel's AT91SAM9G45 family SoC.
@@ -80,7 +77,6 @@ config SOC_AT91SAM9X5
 	bool "AT91SAM9x5 family"
 	select HAVE_AT91_DBGU0
 	select HAVE_FB_ATMEL
-	select HAVE_NET_MACB
 	select SOC_AT91SAM9
 	help
 	  Select this if you are using one of Atmel's AT91SAM9x5 family SoC.
@@ -494,8 +490,17 @@ endif
 
 comment "Generic Board Type"
 
+config MACH_AT91RM9200_DT
+	bool "Atmel AT91RM9200 Evaluation Kits with device-tree support"
+	depends on SOC_AT91RM9200
+	select USE_OF
+	help
+	  Select this if you want to experiment device-tree with
+	  an Atmel RM9200 Evaluation Kit.
+
 config MACH_AT91SAM_DT
 	bool "Atmel AT91SAM Evaluation Kits with device-tree support"
+	depends on SOC_AT91SAM9
 	select USE_OF
 	help
 	  Select this if you want to experiment device-tree with
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index 3bb7a51..b38a1dc 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_MACH_SNAPPER_9260)	+= board-snapper9260.o
 obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o
 
 # AT91SAM board with device-tree
+obj-$(CONFIG_MACH_AT91RM9200_DT) += board-rm9200-dt.o
 obj-$(CONFIG_MACH_AT91SAM_DT) += board-dt.o
 
 # AT91X40 board-specific support
diff --git a/arch/arm/mach-at91/at91_aic.h b/arch/arm/mach-at91/at91_aic.h
new file mode 100644
index 0000000..eaea661
--- /dev/null
+++ b/arch/arm/mach-at91/at91_aic.h
@@ -0,0 +1,99 @@
+/*
+ * arch/arm/mach-at91/include/mach/at91_aic.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Advanced Interrupt Controller (AIC) - System peripherals registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 AT91_AIC_H
+#define AT91_AIC_H
+
+#ifndef __ASSEMBLY__
+extern void __iomem *at91_aic_base;
+
+#define at91_aic_read(field) \
+	__raw_readl(at91_aic_base + field)
+
+#define at91_aic_write(field, value) \
+	__raw_writel(value, at91_aic_base + field)
+#else
+.extern at91_aic_base
+#endif
+
+/* Number of irq lines managed by AIC */
+#define NR_AIC_IRQS	32
+#define NR_AIC5_IRQS	128
+
+#define AT91_AIC5_SSR		0x0			/* Source Select Register [AIC5] */
+#define 	AT91_AIC5_INTSEL_MSK	(0x7f << 0)		/* Interrupt Line Selection Mask */
+
+#define AT91_AIC_IRQ_MIN_PRIORITY	0
+#define AT91_AIC_IRQ_MAX_PRIORITY	7
+
+#define AT91_AIC_SMR(n)		((n) * 4)		/* Source Mode Registers 0-31 */
+#define AT91_AIC5_SMR		0x4			/* Source Mode Register [AIC5] */
+#define		AT91_AIC_PRIOR		(7 << 0)		/* Priority Level */
+#define		AT91_AIC_SRCTYPE	(3 << 5)		/* Interrupt Source Type */
+#define			AT91_AIC_SRCTYPE_LOW		(0 << 5)
+#define			AT91_AIC_SRCTYPE_FALLING	(1 << 5)
+#define			AT91_AIC_SRCTYPE_HIGH		(2 << 5)
+#define			AT91_AIC_SRCTYPE_RISING		(3 << 5)
+
+#define AT91_AIC_SVR(n)		(0x80 + ((n) * 4))	/* Source Vector Registers 0-31 */
+#define AT91_AIC5_SVR		0x8			/* Source Vector Register [AIC5] */
+#define AT91_AIC_IVR		0x100			/* Interrupt Vector Register */
+#define AT91_AIC5_IVR		0x10			/* Interrupt Vector Register [AIC5] */
+#define AT91_AIC_FVR		0x104			/* Fast Interrupt Vector Register */
+#define AT91_AIC5_FVR		0x14			/* Fast Interrupt Vector Register [AIC5] */
+#define AT91_AIC_ISR		0x108			/* Interrupt Status Register */
+#define AT91_AIC5_ISR		0x18			/* Interrupt Status Register [AIC5] */
+#define		AT91_AIC_IRQID		(0x1f << 0)		/* Current Interrupt Identifier */
+
+#define AT91_AIC_IPR		0x10c			/* Interrupt Pending Register */
+#define AT91_AIC5_IPR0		0x20			/* Interrupt Pending Register 0 [AIC5] */
+#define AT91_AIC5_IPR1		0x24			/* Interrupt Pending Register 1 [AIC5] */
+#define AT91_AIC5_IPR2		0x28			/* Interrupt Pending Register 2 [AIC5] */
+#define AT91_AIC5_IPR3		0x2c			/* Interrupt Pending Register 3 [AIC5] */
+#define AT91_AIC_IMR		0x110			/* Interrupt Mask Register */
+#define AT91_AIC5_IMR		0x30			/* Interrupt Mask Register [AIC5] */
+#define AT91_AIC_CISR		0x114			/* Core Interrupt Status Register */
+#define AT91_AIC5_CISR		0x34			/* Core Interrupt Status Register [AIC5] */
+#define		AT91_AIC_NFIQ		(1 << 0)		/* nFIQ Status */
+#define		AT91_AIC_NIRQ		(1 << 1)		/* nIRQ Status */
+
+#define AT91_AIC_IECR		0x120			/* Interrupt Enable Command Register */
+#define AT91_AIC5_IECR		0x40			/* Interrupt Enable Command Register [AIC5] */
+#define AT91_AIC_IDCR		0x124			/* Interrupt Disable Command Register */
+#define AT91_AIC5_IDCR		0x44			/* Interrupt Disable Command Register [AIC5] */
+#define AT91_AIC_ICCR		0x128			/* Interrupt Clear Command Register */
+#define AT91_AIC5_ICCR		0x48			/* Interrupt Clear Command Register [AIC5] */
+#define AT91_AIC_ISCR		0x12c			/* Interrupt Set Command Register */
+#define AT91_AIC5_ISCR		0x4c			/* Interrupt Set Command Register [AIC5] */
+#define AT91_AIC_EOICR		0x130			/* End of Interrupt Command Register */
+#define AT91_AIC5_EOICR		0x38			/* End of Interrupt Command Register [AIC5] */
+#define AT91_AIC_SPU		0x134			/* Spurious Interrupt Vector Register */
+#define AT91_AIC5_SPU		0x3c			/* Spurious Interrupt Vector Register [AIC5] */
+#define AT91_AIC_DCR		0x138			/* Debug Control Register */
+#define AT91_AIC5_DCR		0x6c			/* Debug Control Register [AIC5] */
+#define		AT91_AIC_DCR_PROT	(1 << 0)		/* Protection Mode */
+#define		AT91_AIC_DCR_GMSK	(1 << 1)		/* General Mask */
+
+#define AT91_AIC_FFER		0x140			/* Fast Forcing Enable Register [SAM9 only] */
+#define AT91_AIC5_FFER		0x50			/* Fast Forcing Enable Register [AIC5] */
+#define AT91_AIC_FFDR		0x144			/* Fast Forcing Disable Register [SAM9 only] */
+#define AT91_AIC5_FFDR		0x54			/* Fast Forcing Disable Register [AIC5] */
+#define AT91_AIC_FFSR		0x148			/* Fast Forcing Status Register [SAM9 only] */
+#define AT91_AIC5_FFSR		0x58			/* Fast Forcing Status Register [AIC5] */
+
+void at91_aic_handle_irq(struct pt_regs *regs);
+void at91_aic5_handle_irq(struct pt_regs *regs);
+
+#endif
diff --git a/arch/arm/mach-at91/at91_rstc.h b/arch/arm/mach-at91/at91_rstc.h
new file mode 100644
index 0000000..875fa33
--- /dev/null
+++ b/arch/arm/mach-at91/at91_rstc.h
@@ -0,0 +1,53 @@
+/*
+ * arch/arm/mach-at91/include/mach/at91_rstc.h
+ *
+ * Copyright (C) 2007 Andrew Victor
+ * Copyright (C) 2007 Atmel Corporation.
+ *
+ * Reset Controller (RSTC) - System peripherals regsters.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 AT91_RSTC_H
+#define AT91_RSTC_H
+
+#ifndef __ASSEMBLY__
+extern void __iomem *at91_rstc_base;
+
+#define at91_rstc_read(field) \
+	__raw_readl(at91_rstc_base + field)
+
+#define at91_rstc_write(field, value) \
+	__raw_writel(value, at91_rstc_base + field);
+#else
+.extern at91_rstc_base
+#endif
+
+#define AT91_RSTC_CR		0x00			/* Reset Controller Control Register */
+#define		AT91_RSTC_PROCRST	(1 << 0)		/* Processor Reset */
+#define		AT91_RSTC_PERRST	(1 << 2)		/* Peripheral Reset */
+#define		AT91_RSTC_EXTRST	(1 << 3)		/* External Reset */
+#define		AT91_RSTC_KEY		(0xa5 << 24)		/* KEY Password */
+
+#define AT91_RSTC_SR		0x04			/* Reset Controller Status Register */
+#define		AT91_RSTC_URSTS		(1 << 0)		/* User Reset Status */
+#define		AT91_RSTC_RSTTYP	(7 << 8)		/* Reset Type */
+#define			AT91_RSTC_RSTTYP_GENERAL	(0 << 8)
+#define			AT91_RSTC_RSTTYP_WAKEUP		(1 << 8)
+#define			AT91_RSTC_RSTTYP_WATCHDOG	(2 << 8)
+#define			AT91_RSTC_RSTTYP_SOFTWARE	(3 << 8)
+#define			AT91_RSTC_RSTTYP_USER	(4 << 8)
+#define		AT91_RSTC_NRSTL		(1 << 16)		/* NRST Pin Level */
+#define		AT91_RSTC_SRCMP		(1 << 17)		/* Software Reset Command in Progress */
+
+#define AT91_RSTC_MR		0x08			/* Reset Controller Mode Register */
+#define		AT91_RSTC_URSTEN	(1 << 0)		/* User Reset Enable */
+#define		AT91_RSTC_URSTIEN	(1 << 4)		/* User Reset Interrupt Enable */
+#define		AT91_RSTC_ERSTL		(0xf << 8)		/* External Reset Length */
+
+#endif
diff --git a/arch/arm/mach-at91/at91_shdwc.h b/arch/arm/mach-at91/at91_shdwc.h
new file mode 100644
index 0000000..60478ea
--- /dev/null
+++ b/arch/arm/mach-at91/at91_shdwc.h
@@ -0,0 +1,50 @@
+/*
+ * arch/arm/mach-at91/include/mach/at91_shdwc.h
+ *
+ * Copyright (C) 2007 Andrew Victor
+ * Copyright (C) 2007 Atmel Corporation.
+ *
+ * Shutdown Controller (SHDWC) - System peripherals regsters.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 AT91_SHDWC_H
+#define AT91_SHDWC_H
+
+#ifndef __ASSEMBLY__
+extern void __iomem *at91_shdwc_base;
+
+#define at91_shdwc_read(field) \
+	__raw_readl(at91_shdwc_base + field)
+
+#define at91_shdwc_write(field, value) \
+	__raw_writel(value, at91_shdwc_base + field);
+#endif
+
+#define AT91_SHDW_CR		0x00			/* Shut Down Control Register */
+#define		AT91_SHDW_SHDW		(1    << 0)		/* Shut Down command */
+#define		AT91_SHDW_KEY		(0xa5 << 24)		/* KEY Password */
+
+#define AT91_SHDW_MR		0x04			/* Shut Down Mode Register */
+#define		AT91_SHDW_WKMODE0	(3 << 0)		/* Wake-up 0 Mode Selection */
+#define			AT91_SHDW_WKMODE0_NONE		0
+#define			AT91_SHDW_WKMODE0_HIGH		1
+#define			AT91_SHDW_WKMODE0_LOW		2
+#define			AT91_SHDW_WKMODE0_ANYLEVEL	3
+#define		AT91_SHDW_CPTWK0_MAX	0xf			/* Maximum Counter On Wake Up 0 */
+#define		AT91_SHDW_CPTWK0	(AT91_SHDW_CPTWK0_MAX << 4) /* Counter On Wake Up 0 */
+#define			AT91_SHDW_CPTWK0_(x)	((x) << 4)
+#define		AT91_SHDW_RTTWKEN	(1   << 16)		/* Real Time Timer Wake-up Enable */
+#define		AT91_SHDW_RTCWKEN	(1   << 17)		/* Real Time Clock Wake-up Enable */
+
+#define AT91_SHDW_SR		0x08			/* Shut Down Status Register */
+#define		AT91_SHDW_WAKEUP0	(1 <<  0)		/* Wake-up 0 Status */
+#define		AT91_SHDW_RTTWK		(1 << 16)		/* Real-time Timer Wake-up */
+#define		AT91_SHDW_RTCWK		(1 << 17)		/* Real-time Clock Wake-up [SAM9RL] */
+
+#endif
diff --git a/arch/arm/mach-at91/at91_tc.h b/arch/arm/mach-at91/at91_tc.h
new file mode 100644
index 0000000..46a317f
--- /dev/null
+++ b/arch/arm/mach-at91/at91_tc.h
@@ -0,0 +1,146 @@
+/*
+ * arch/arm/mach-at91/include/mach/at91_tc.h
+ *
+ * Copyright (C) SAN People
+ *
+ * Timer/Counter Unit (TC) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 AT91_TC_H
+#define AT91_TC_H
+
+#define AT91_TC_BCR		0xc0		/* TC Block Control Register */
+#define		AT91_TC_SYNC		(1 << 0)	/* Synchro Command */
+
+#define AT91_TC_BMR		0xc4		/* TC Block Mode Register */
+#define		AT91_TC_TC0XC0S		(3 << 0)	/* External Clock Signal 0 Selection */
+#define			AT91_TC_TC0XC0S_TCLK0		(0 << 0)
+#define			AT91_TC_TC0XC0S_NONE		(1 << 0)
+#define			AT91_TC_TC0XC0S_TIOA1		(2 << 0)
+#define			AT91_TC_TC0XC0S_TIOA2		(3 << 0)
+#define		AT91_TC_TC1XC1S		(3 << 2)	/* External Clock Signal 1 Selection */
+#define			AT91_TC_TC1XC1S_TCLK1		(0 << 2)
+#define			AT91_TC_TC1XC1S_NONE		(1 << 2)
+#define			AT91_TC_TC1XC1S_TIOA0		(2 << 2)
+#define			AT91_TC_TC1XC1S_TIOA2		(3 << 2)
+#define		AT91_TC_TC2XC2S		(3 << 4)	/* External Clock Signal 2 Selection */
+#define			AT91_TC_TC2XC2S_TCLK2		(0 << 4)
+#define			AT91_TC_TC2XC2S_NONE		(1 << 4)
+#define			AT91_TC_TC2XC2S_TIOA0		(2 << 4)
+#define			AT91_TC_TC2XC2S_TIOA1		(3 << 4)
+
+
+#define AT91_TC_CCR		0x00		/* Channel Control Register */
+#define		AT91_TC_CLKEN		(1 << 0)	/* Counter Clock Enable Command */
+#define		AT91_TC_CLKDIS		(1 << 1)	/* Counter CLock Disable Command */
+#define		AT91_TC_SWTRG		(1 << 2)	/* Software Trigger Command */
+
+#define AT91_TC_CMR		0x04		/* Channel Mode Register */
+#define		AT91_TC_TCCLKS		(7 << 0)	/* Capture/Waveform Mode: Clock Selection */
+#define			AT91_TC_TIMER_CLOCK1		(0 << 0)
+#define			AT91_TC_TIMER_CLOCK2		(1 << 0)
+#define			AT91_TC_TIMER_CLOCK3		(2 << 0)
+#define			AT91_TC_TIMER_CLOCK4		(3 << 0)
+#define			AT91_TC_TIMER_CLOCK5		(4 << 0)
+#define			AT91_TC_XC0			(5 << 0)
+#define			AT91_TC_XC1			(6 << 0)
+#define			AT91_TC_XC2			(7 << 0)
+#define		AT91_TC_CLKI		(1 << 3)	/* Capture/Waveform Mode: Clock Invert */
+#define		AT91_TC_BURST		(3 << 4)	/* Capture/Waveform Mode: Burst Signal Selection */
+#define		AT91_TC_LDBSTOP		(1 << 6)	/* Capture Mode: Counter Clock Stopped with TB Loading */
+#define		AT91_TC_LDBDIS		(1 << 7)	/* Capture Mode: Counter Clock Disable with RB Loading */
+#define		AT91_TC_ETRGEDG		(3 << 8)	/* Capture Mode: External Trigger Edge Selection */
+#define		AT91_TC_ABETRG		(1 << 10)	/* Capture Mode: TIOA or TIOB External Trigger Selection */
+#define		AT91_TC_CPCTRG		(1 << 14)	/* Capture Mode: RC Compare Trigger Enable */
+#define		AT91_TC_WAVE		(1 << 15)	/* Capture/Waveform mode */
+#define		AT91_TC_LDRA		(3 << 16)	/* Capture Mode: RA Loading Selection */
+#define		AT91_TC_LDRB		(3 << 18)	/* Capture Mode: RB Loading Selection */
+
+#define		AT91_TC_CPCSTOP		(1 <<  6)	/* Waveform Mode: Counter Clock Stopped with RC Compare */
+#define		AT91_TC_CPCDIS		(1 <<  7)	/* Waveform Mode: Counter Clock Disable with RC Compare */
+#define		AT91_TC_EEVTEDG		(3 <<  8)	/* Waveform Mode: External Event Edge Selection */
+#define			AT91_TC_EEVTEDG_NONE		(0 << 8)
+#define			AT91_TC_EEVTEDG_RISING		(1 << 8)
+#define			AT91_TC_EEVTEDG_FALLING		(2 << 8)
+#define			AT91_TC_EEVTEDG_BOTH		(3 << 8)
+#define		AT91_TC_EEVT		(3 << 10)	/* Waveform Mode: External Event Selection */
+#define			AT91_TC_EEVT_TIOB		(0 << 10)
+#define			AT91_TC_EEVT_XC0		(1 << 10)
+#define			AT91_TC_EEVT_XC1		(2 << 10)
+#define			AT91_TC_EEVT_XC2		(3 << 10)
+#define		AT91_TC_ENETRG		(1 << 12)	/* Waveform Mode: External Event Trigger Enable */
+#define		AT91_TC_WAVESEL		(3 << 13)	/* Waveform Mode: Waveform Selection */
+#define			AT91_TC_WAVESEL_UP		(0 << 13)
+#define			AT91_TC_WAVESEL_UP_AUTO		(2 << 13)
+#define			AT91_TC_WAVESEL_UPDOWN		(1 << 13)
+#define			AT91_TC_WAVESEL_UPDOWN_AUTO	(3 << 13)
+#define		AT91_TC_ACPA		(3 << 16)	/* Waveform Mode: RA Compare Effect on TIOA */
+#define			AT91_TC_ACPA_NONE		(0 << 16)
+#define			AT91_TC_ACPA_SET		(1 << 16)
+#define			AT91_TC_ACPA_CLEAR		(2 << 16)
+#define			AT91_TC_ACPA_TOGGLE		(3 << 16)
+#define		AT91_TC_ACPC		(3 << 18)	/* Waveform Mode: RC Compre Effect on TIOA */
+#define			AT91_TC_ACPC_NONE		(0 << 18)
+#define			AT91_TC_ACPC_SET		(1 << 18)
+#define			AT91_TC_ACPC_CLEAR		(2 << 18)
+#define			AT91_TC_ACPC_TOGGLE		(3 << 18)
+#define		AT91_TC_AEEVT		(3 << 20)	/* Waveform Mode: External Event Effect on TIOA */
+#define			AT91_TC_AEEVT_NONE		(0 << 20)
+#define			AT91_TC_AEEVT_SET		(1 << 20)
+#define			AT91_TC_AEEVT_CLEAR		(2 << 20)
+#define			AT91_TC_AEEVT_TOGGLE		(3 << 20)
+#define		AT91_TC_ASWTRG		(3 << 22)	/* Waveform Mode: Software Trigger Effect on TIOA */
+#define			AT91_TC_ASWTRG_NONE		(0 << 22)
+#define			AT91_TC_ASWTRG_SET		(1 << 22)
+#define			AT91_TC_ASWTRG_CLEAR		(2 << 22)
+#define			AT91_TC_ASWTRG_TOGGLE		(3 << 22)
+#define		AT91_TC_BCPB		(3 << 24)	/* Waveform Mode: RB Compare Effect on TIOB */
+#define			AT91_TC_BCPB_NONE		(0 << 24)
+#define			AT91_TC_BCPB_SET		(1 << 24)
+#define			AT91_TC_BCPB_CLEAR		(2 << 24)
+#define			AT91_TC_BCPB_TOGGLE		(3 << 24)
+#define		AT91_TC_BCPC		(3 << 26)	/* Waveform Mode: RC Compare Effect on TIOB */
+#define			AT91_TC_BCPC_NONE		(0 << 26)
+#define			AT91_TC_BCPC_SET		(1 << 26)
+#define			AT91_TC_BCPC_CLEAR		(2 << 26)
+#define			AT91_TC_BCPC_TOGGLE		(3 << 26)
+#define		AT91_TC_BEEVT		(3 << 28)	/* Waveform Mode: External Event Effect on TIOB */
+#define			AT91_TC_BEEVT_NONE		(0 << 28)
+#define			AT91_TC_BEEVT_SET		(1 << 28)
+#define			AT91_TC_BEEVT_CLEAR		(2 << 28)
+#define			AT91_TC_BEEVT_TOGGLE		(3 << 28)
+#define		AT91_TC_BSWTRG		(3 << 30)	/* Waveform Mode: Software Trigger Effect on TIOB */
+#define			AT91_TC_BSWTRG_NONE		(0 << 30)
+#define			AT91_TC_BSWTRG_SET		(1 << 30)
+#define			AT91_TC_BSWTRG_CLEAR		(2 << 30)
+#define			AT91_TC_BSWTRG_TOGGLE		(3 << 30)
+
+#define AT91_TC_CV		0x10		/* Counter Value */
+#define AT91_TC_RA		0x14		/* Register A */
+#define AT91_TC_RB		0x18		/* Register B */
+#define AT91_TC_RC		0x1c		/* Register C */
+
+#define AT91_TC_SR		0x20		/* Status Register */
+#define		AT91_TC_COVFS		(1 <<  0)	/* Counter Overflow Status */
+#define		AT91_TC_LOVRS		(1 <<  1)	/* Load Overrun Status */
+#define		AT91_TC_CPAS		(1 <<  2)	/* RA Compare Status */
+#define		AT91_TC_CPBS		(1 <<  3)	/* RB Compare Status */
+#define		AT91_TC_CPCS		(1 <<  4)	/* RC Compare Status */
+#define		AT91_TC_LDRAS		(1 <<  5)	/* RA Loading Status */
+#define		AT91_TC_LDRBS		(1 <<  6)	/* RB Loading Status */
+#define		AT91_TC_ETRGS		(1 <<  7)	/* External Trigger Status */
+#define		AT91_TC_CLKSTA		(1 << 16)	/* Clock Enabling Status */
+#define		AT91_TC_MTIOA		(1 << 17)	/* TIOA Mirror */
+#define		AT91_TC_MTIOB		(1 << 18)	/* TIOB Mirror */
+
+#define AT91_TC_IER		0x24		/* Interrupt Enable Register */
+#define AT91_TC_IDR		0x28		/* Interrupt Disable Register */
+#define AT91_TC_IMR		0x2c		/* Interrupt Mask Register */
+
+#endif
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index 5269825..7aeb473 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -17,11 +17,11 @@
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
 #include <mach/at91rm9200.h>
-#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_st.h>
 #include <mach/cpu.h>
 
+#include "at91_aic.h"
 #include "soc.h"
 #include "generic.h"
 #include "clock.h"
@@ -184,9 +184,12 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
 	CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
 	CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
-	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
-	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
-	CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
+	CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+	CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+	CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.2", &ssc2_clk),
+	CLKDEV_CON_DEV_ID("pclk", "fffd0000.ssc", &ssc0_clk),
+	CLKDEV_CON_DEV_ID("pclk", "fffd4000.ssc", &ssc1_clk),
+	CLKDEV_CON_DEV_ID("pclk", "fffd8000.ssc", &ssc2_clk),
 	CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200.0", &twi_clk),
 	/* fake hclk clock */
 	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
@@ -194,6 +197,24 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_ID("pioB", &pioB_clk),
 	CLKDEV_CON_ID("pioC", &pioC_clk),
 	CLKDEV_CON_ID("pioD", &pioD_clk),
+	/* usart lookup table for DT entries */
+	CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
+	CLKDEV_CON_DEV_ID("usart", "fffc0000.serial", &usart0_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffc4000.serial", &usart1_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffc8000.serial", &usart2_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffcc000.serial", &usart3_clk),
+	/* tc lookup table for DT entries */
+	CLKDEV_CON_DEV_ID("t0_clk", "fffa0000.timer", &tc0_clk),
+	CLKDEV_CON_DEV_ID("t1_clk", "fffa0000.timer", &tc1_clk),
+	CLKDEV_CON_DEV_ID("t2_clk", "fffa0000.timer", &tc2_clk),
+	CLKDEV_CON_DEV_ID("t0_clk", "fffa4000.timer", &tc3_clk),
+	CLKDEV_CON_DEV_ID("t1_clk", "fffa4000.timer", &tc4_clk),
+	CLKDEV_CON_DEV_ID("t2_clk", "fffa4000.timer", &tc5_clk),
+	CLKDEV_CON_DEV_ID("hclk", "300000.ohci", &ohci_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioA_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioB_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioC_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioD_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
@@ -361,10 +382,10 @@ static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0	/* Advanced Interrupt Controller (IRQ6) */
 };
 
-struct at91_init_soc __initdata at91rm9200_soc = {
+AT91_SOC_START(rm9200)
 	.map_io = at91rm9200_map_io,
 	.default_irq_priority = at91rm9200_default_irq_priority,
 	.ioremap_registers = at91rm9200_ioremap_registers,
 	.register_clocks = at91rm9200_register_clocks,
 	.init = at91rm9200_initialize,
-};
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 3cee0e6..3ebc979 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -18,11 +18,11 @@
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 
-#include <mach/board.h>
 #include <mach/at91rm9200.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 
+#include "board.h"
 #include "generic.h"
 
 
@@ -752,7 +752,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91rm9200_ssc0_device = {
-	.name	= "ssc",
+	.name	= "at91rm9200_ssc",
 	.id	= 0,
 	.dev	= {
 		.dma_mask		= &ssc0_dmamask,
@@ -794,7 +794,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91rm9200_ssc1_device = {
-	.name	= "ssc",
+	.name	= "at91rm9200_ssc",
 	.id	= 1,
 	.dev	= {
 		.dma_mask		= &ssc1_dmamask,
@@ -836,7 +836,7 @@ static struct resource ssc2_resources[] = {
 };
 
 static struct platform_device at91rm9200_ssc2_device = {
-	.name	= "ssc",
+	.name	= "at91rm9200_ssc",
 	.id	= 2,
 	.dev	= {
 		.dma_mask		= &ssc2_dmamask,
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index aaa443b..cafe988 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -24,6 +24,9 @@
 #include <linux/irq.h>
 #include <linux/clockchips.h>
 #include <linux/export.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <asm/mach/time.h>
 
@@ -91,7 +94,8 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
 static struct irqaction at91rm9200_timer_irq = {
 	.name		= "at91_tick",
 	.flags		= IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= at91rm9200_timer_interrupt
+	.handler	= at91rm9200_timer_interrupt,
+	.irq		= NR_IRQS_LEGACY + AT91_ID_SYS,
 };
 
 static cycle_t read_clk32k(struct clocksource *cs)
@@ -179,8 +183,60 @@ static struct clock_event_device clkevt = {
 void __iomem *at91_st_base;
 EXPORT_SYMBOL_GPL(at91_st_base);
 
+#ifdef CONFIG_OF
+static struct of_device_id at91rm9200_st_timer_ids[] = {
+	{ .compatible = "atmel,at91rm9200-st" },
+	{ /* sentinel */ }
+};
+
+static int __init of_at91rm9200_st_init(void)
+{
+	struct device_node *np;
+	int ret;
+
+	np = of_find_matching_node(NULL, at91rm9200_st_timer_ids);
+	if (!np)
+		goto err;
+
+	at91_st_base = of_iomap(np, 0);
+	if (!at91_st_base)
+		goto node_err;
+
+	/* Get the interrupts property */
+	ret = irq_of_parse_and_map(np, 0);
+	if (!ret)
+		goto ioremap_err;
+	at91rm9200_timer_irq.irq = ret;
+
+	of_node_put(np);
+
+	return 0;
+
+ioremap_err:
+	iounmap(at91_st_base);
+node_err:
+	of_node_put(np);
+err:
+	return -EINVAL;
+}
+#else
+static int __init of_at91rm9200_st_init(void)
+{
+	return -EINVAL;
+}
+#endif
+
 void __init at91rm9200_ioremap_st(u32 addr)
 {
+#ifdef CONFIG_OF
+	struct device_node *np;
+
+	np = of_find_matching_node(NULL, at91rm9200_st_timer_ids);
+	if (np) {
+		of_node_put(np);
+		return;
+	}
+#endif
 	at91_st_base = ioremap(addr, 256);
 	if (!at91_st_base)
 		panic("Impossible to ioremap ST\n");
@@ -191,13 +247,16 @@ void __init at91rm9200_ioremap_st(u32 addr)
  */
 void __init at91rm9200_timer_init(void)
 {
+	/* For device tree enabled device: initialize here */
+	of_at91rm9200_st_init();
+
 	/* Disable all timer interrupts, and clear any pending ones */
 	at91_st_write(AT91_ST_IDR,
 		AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
 	at91_st_read(AT91_ST_SR);
 
 	/* Make IRQs happen for the system timer */
-	setup_irq(NR_IRQS_LEGACY + AT91_ID_SYS, &at91rm9200_timer_irq);
+	setup_irq(at91rm9200_timer_irq.irq, &at91rm9200_timer_irq);
 
 	/* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
 	 * directly for the clocksource and all clockevents, after adjusting
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index f820261..b67cd53 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -20,10 +20,10 @@
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
 #include <mach/at91sam9260.h>
-#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
-#include <mach/at91_rstc.h>
 
+#include "at91_aic.h"
+#include "at91_rstc.h"
 #include "soc.h"
 #include "generic.h"
 #include "clock.h"
@@ -210,7 +210,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
 	CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
 	CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
-	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
+	CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc_clk),
+	CLKDEV_CON_DEV_ID("pclk", "fffbc000.ssc", &ssc_clk),
 	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
 	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi_clk),
 	/* more usart lookup table for DT entries */
@@ -230,11 +231,15 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t1_clk", "fffdc000.timer", &tc4_clk),
 	CLKDEV_CON_DEV_ID("t2_clk", "fffdc000.timer", &tc5_clk),
 	CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &ohci_clk),
+	CLKDEV_CON_DEV_ID("mci_clk", "fffa8000.mmc", &mmc_clk),
 	/* fake hclk clock */
 	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 	CLKDEV_CON_ID("pioA", &pioA_clk),
 	CLKDEV_CON_ID("pioB", &pioB_clk),
 	CLKDEV_CON_ID("pioC", &pioC_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioA_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioB_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioC_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
@@ -390,10 +395,10 @@ static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller */
 };
 
-struct at91_init_soc __initdata at91sam9260_soc = {
+AT91_SOC_START(sam9260)
 	.map_io = at91sam9260_map_io,
 	.default_irq_priority = at91sam9260_default_irq_priority,
 	.ioremap_registers = at91sam9260_ioremap_registers,
 	.register_clocks = at91sam9260_register_clocks,
 	.init = at91sam9260_initialize,
-};
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 414bd85..eda8d16 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -19,7 +19,6 @@
 
 #include <linux/platform_data/at91_adc.h>
 
-#include <mach/board.h>
 #include <mach/cpu.h>
 #include <mach/at91sam9260.h>
 #include <mach/at91sam9260_matrix.h>
@@ -27,6 +26,7 @@
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_adc.h>
 
+#include "board.h"
 #include "generic.h"
 
 
@@ -742,7 +742,7 @@ static struct resource ssc_resources[] = {
 };
 
 static struct platform_device at91sam9260_ssc_device = {
-	.name	= "ssc",
+	.name	= "at91rm9200_ssc",
 	.id	= 0,
 	.dev	= {
 		.dma_mask		= &ssc_dmamask,
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 04295c0..2998a08 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -19,10 +19,10 @@
 #include <asm/system_misc.h>
 #include <mach/cpu.h>
 #include <mach/at91sam9261.h>
-#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
-#include <mach/at91_rstc.h>
 
+#include "at91_aic.h"
+#include "at91_rstc.h"
 #include "soc.h"
 #include "generic.h"
 #include "clock.h"
@@ -174,9 +174,12 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
 	CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
 	CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
-	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
-	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
-	CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
+	CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+	CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+	CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.2", &ssc2_clk),
+	CLKDEV_CON_DEV_ID("pclk", "fffbc000.ssc", &ssc0_clk),
+	CLKDEV_CON_DEV_ID("pclk", "fffc0000.ssc", &ssc1_clk),
+	CLKDEV_CON_DEV_ID("pclk", "fffc4000.ssc", &ssc2_clk),
 	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
 	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261.0", &twi_clk),
 	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi_clk),
@@ -334,10 +337,10 @@ static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller */
 };
 
-struct at91_init_soc __initdata at91sam9261_soc = {
+AT91_SOC_START(sam9261)
 	.map_io = at91sam9261_map_io,
 	.default_irq_priority = at91sam9261_default_irq_priority,
 	.ioremap_registers = at91sam9261_ioremap_registers,
 	.register_clocks = at91sam9261_register_clocks,
 	.init = at91sam9261_initialize,
-};
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index cd604aa..92e0f86 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -21,12 +21,12 @@
 #include <linux/fb.h>
 #include <video/atmel_lcdc.h>
 
-#include <mach/board.h>
 #include <mach/at91sam9261.h>
 #include <mach/at91sam9261_matrix.h>
 #include <mach/at91_matrix.h>
 #include <mach/at91sam9_smc.h>
 
+#include "board.h"
 #include "generic.h"
 
 
@@ -706,7 +706,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91sam9261_ssc0_device = {
-	.name	= "ssc",
+	.name	= "at91rm9200_ssc",
 	.id	= 0,
 	.dev	= {
 		.dma_mask		= &ssc0_dmamask,
@@ -748,7 +748,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91sam9261_ssc1_device = {
-	.name	= "ssc",
+	.name	= "at91rm9200_ssc",
 	.id	= 1,
 	.dev	= {
 		.dma_mask		= &ssc1_dmamask,
@@ -790,7 +790,7 @@ static struct resource ssc2_resources[] = {
 };
 
 static struct platform_device at91sam9261_ssc2_device = {
-	.name	= "ssc",
+	.name	= "at91rm9200_ssc",
 	.id	= 2,
 	.dev	= {
 		.dma_mask		= &ssc2_dmamask,
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index d6f9c23..b9fc60d 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -18,10 +18,10 @@
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
 #include <mach/at91sam9263.h>
-#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
-#include <mach/at91_rstc.h>
 
+#include "at91_aic.h"
+#include "at91_rstc.h"
 #include "soc.h"
 #include "generic.h"
 #include "clock.h"
@@ -186,8 +186,10 @@ static struct clk *periph_clocks[] __initdata = {
 static struct clk_lookup periph_clocks_lookups[] = {
 	/* One additional fake clock for macb_hclk */
 	CLKDEV_CON_ID("hclk", &macb_clk),
-	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
-	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+	CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+	CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+	CLKDEV_CON_DEV_ID("pclk", "fff98000.ssc", &ssc0_clk),
+	CLKDEV_CON_DEV_ID("pclk", "fff9c000.ssc", &ssc1_clk),
 	CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.0", &mmc0_clk),
 	CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.1", &mmc1_clk),
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
@@ -211,7 +213,14 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("hclk", "a00000.ohci", &ohci_clk),
 	CLKDEV_CON_DEV_ID("spi_clk", "fffa4000.spi", &spi0_clk),
 	CLKDEV_CON_DEV_ID("spi_clk", "fffa8000.spi", &spi1_clk),
+	CLKDEV_CON_DEV_ID("mci_clk", "fff80000.mmc", &mmc0_clk),
+	CLKDEV_CON_DEV_ID("mci_clk", "fff84000.mmc", &mmc1_clk),
 	CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff200.gpio", &pioA_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioB_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioCDE_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCDE_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCDE_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
@@ -365,10 +374,10 @@ static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller (IRQ1) */
 };
 
-struct at91_init_soc __initdata at91sam9263_soc = {
+AT91_SOC_START(sam9263)
 	.map_io = at91sam9263_map_io,
 	.default_irq_priority = at91sam9263_default_irq_priority,
 	.ioremap_registers = at91sam9263_ioremap_registers,
 	.register_clocks = at91sam9263_register_clocks,
 	.init = at91sam9263_initialize,
-};
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 9c61e59..ed666f5 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -20,12 +20,12 @@
 #include <linux/fb.h>
 #include <video/atmel_lcdc.h>
 
-#include <mach/board.h>
 #include <mach/at91sam9263.h>
 #include <mach/at91sam9263_matrix.h>
 #include <mach/at91_matrix.h>
 #include <mach/at91sam9_smc.h>
 
+#include "board.h"
 #include "generic.h"
 
 
@@ -1199,7 +1199,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91sam9263_ssc0_device = {
-	.name	= "ssc",
+	.name	= "at91rm9200_ssc",
 	.id	= 0,
 	.dev	= {
 		.dma_mask		= &ssc0_dmamask,
@@ -1241,7 +1241,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91sam9263_ssc1_device = {
-	.name	= "ssc",
+	.name	= "at91rm9200_ssc",
 	.id	= 1,
 	.dev	= {
 		.dma_mask		= &ssc1_dmamask,
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
index ffc0957..358412f 100644
--- a/arch/arm/mach-at91/at91sam926x_time.c
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -20,8 +20,18 @@
 
 #include <asm/mach/time.h>
 
-#include <mach/at91_pit.h>
-
+#define AT91_PIT_MR		0x00			/* Mode Register */
+#define		AT91_PIT_PITIEN		(1 << 25)		/* Timer Interrupt Enable */
+#define		AT91_PIT_PITEN		(1 << 24)		/* Timer Enabled */
+#define		AT91_PIT_PIV		(0xfffff)		/* Periodic Interval Value */
+
+#define AT91_PIT_SR		0x04			/* Status Register */
+#define		AT91_PIT_PITS		(1 << 0)		/* Timer Status */
+
+#define AT91_PIT_PIVR		0x08			/* Periodic Interval Value Register */
+#define AT91_PIT_PIIR		0x0c			/* Periodic Interval Image Register */
+#define		AT91_PIT_PICNT		(0xfff << 20)		/* Interval Counter */
+#define		AT91_PIT_CPIV		(0xfffff)		/* Inverval Value */
 
 #define PIT_CPIV(x)	((x) & AT91_PIT_CPIV)
 #define PIT_PICNT(x)	(((x) & AT91_PIT_PICNT) >> 20)
diff --git a/arch/arm/mach-at91/at91sam9_alt_reset.S b/arch/arm/mach-at91/at91sam9_alt_reset.S
index 7af2e10..f039538 100644
--- a/arch/arm/mach-at91/at91sam9_alt_reset.S
+++ b/arch/arm/mach-at91/at91sam9_alt_reset.S
@@ -16,7 +16,7 @@
 #include <linux/linkage.h>
 #include <mach/hardware.h>
 #include <mach/at91_ramc.h>
-#include <mach/at91_rstc.h>
+#include "at91_rstc.h"
 
 			.arm
 
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 84af1b5..d3addee 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -18,10 +18,10 @@
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
 #include <mach/at91sam9g45.h>
-#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/cpu.h>
 
+#include "at91_aic.h"
 #include "soc.h"
 #include "generic.h"
 #include "clock.h"
@@ -239,8 +239,10 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),
 	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi0_clk),
 	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.1", &twi1_clk),
-	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
-	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+	CLKDEV_CON_DEV_ID("pclk", "at91sam9g45_ssc.0", &ssc0_clk),
+	CLKDEV_CON_DEV_ID("pclk", "at91sam9g45_ssc.1", &ssc1_clk),
+	CLKDEV_CON_DEV_ID("pclk", "fff9c000.ssc", &ssc0_clk),
+	CLKDEV_CON_DEV_ID("pclk", "fffa0000.ssc", &ssc1_clk),
 	CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
 	CLKDEV_CON_DEV_ID(NULL, "atmel_sha", &aestdessha_clk),
 	CLKDEV_CON_DEV_ID(NULL, "atmel_tdes", &aestdessha_clk),
@@ -256,10 +258,18 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t0_clk", "fffd4000.timer", &tcb0_clk),
 	CLKDEV_CON_DEV_ID("hclk", "700000.ohci", &uhphs_clk),
 	CLKDEV_CON_DEV_ID("ehci_clk", "800000.ehci", &uhphs_clk),
+	CLKDEV_CON_DEV_ID("mci_clk", "fff80000.mmc", &mmc0_clk),
+	CLKDEV_CON_DEV_ID("mci_clk", "fffd0000.mmc", &mmc1_clk),
 	CLKDEV_CON_DEV_ID(NULL, "fff84000.i2c", &twi0_clk),
 	CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi1_clk),
 	/* fake hclk clock */
 	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff200.gpio", &pioA_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioB_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioC_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioDE_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioDE_clk),
+
 	CLKDEV_CON_ID("pioA", &pioA_clk),
 	CLKDEV_CON_ID("pioB", &pioB_clk),
 	CLKDEV_CON_ID("pioC", &pioC_clk),
@@ -343,7 +353,6 @@ static struct at91_gpio_bank at91sam9g45_gpio[] __initdata = {
 static void __init at91sam9g45_map_io(void)
 {
 	at91_init_sram(0, AT91SAM9G45_SRAM_BASE, AT91SAM9G45_SRAM_SIZE);
-	init_consistent_dma_size(SZ_4M);
 }
 
 static void __init at91sam9g45_ioremap_registers(void)
@@ -409,10 +418,10 @@ static unsigned int at91sam9g45_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller (IRQ0) */
 };
 
-struct at91_init_soc __initdata at91sam9g45_soc = {
+AT91_SOC_START(sam9g45)
 	.map_io = at91sam9g45_map_io,
 	.default_irq_priority = at91sam9g45_default_irq_priority,
 	.ioremap_registers = at91sam9g45_ioremap_registers,
 	.register_clocks = at91sam9g45_register_clocks,
 	.init = at91sam9g45_initialize,
-};
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index fcd233c..827c9f2 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -26,7 +26,6 @@
 #include <video/atmel_lcdc.h>
 
 #include <mach/at91_adc.h>
-#include <mach/board.h>
 #include <mach/at91sam9g45.h>
 #include <mach/at91sam9g45_matrix.h>
 #include <mach/at91_matrix.h>
@@ -36,6 +35,7 @@
 
 #include <media/atmel-isi.h>
 
+#include "board.h"
 #include "generic.h"
 #include "clock.h"
 
@@ -1459,7 +1459,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91sam9g45_ssc0_device = {
-	.name	= "ssc",
+	.name	= "at91sam9g45_ssc",
 	.id	= 0,
 	.dev	= {
 		.dma_mask		= &ssc0_dmamask,
@@ -1501,7 +1501,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91sam9g45_ssc1_device = {
-	.name	= "ssc",
+	.name	= "at91sam9g45_ssc",
 	.id	= 1,
 	.dev	= {
 		.dma_mask		= &ssc1_dmamask,
diff --git a/arch/arm/mach-at91/at91sam9g45_reset.S b/arch/arm/mach-at91/at91sam9g45_reset.S
index 9d45718..721a1a3 100644
--- a/arch/arm/mach-at91/at91sam9g45_reset.S
+++ b/arch/arm/mach-at91/at91sam9g45_reset.S
@@ -13,8 +13,7 @@
 #include <linux/linkage.h>
 #include <mach/hardware.h>
 #include <mach/at91_ramc.h>
-#include <mach/at91_rstc.h>
-
+#include "at91_rstc.h"
 			.arm
 
 			.globl	at91sam9g45_restart
diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c
index 732d3d3..5dfc8fd 100644
--- a/arch/arm/mach-at91/at91sam9n12.c
+++ b/arch/arm/mach-at91/at91sam9n12.c
@@ -15,8 +15,8 @@
 #include <mach/at91sam9n12.h>
 #include <mach/at91_pmc.h>
 #include <mach/cpu.h>
-#include <mach/board.h>
 
+#include "board.h"
 #include "soc.h"
 #include "generic.h"
 #include "clock.h"
@@ -168,13 +168,14 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
 	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("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),
-	CLKDEV_CON_ID("pioA", &pioAB_clk),
-	CLKDEV_CON_ID("pioB", &pioAB_clk),
-	CLKDEV_CON_ID("pioC", &pioCD_clk),
-	CLKDEV_CON_ID("pioD", &pioCD_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioAB_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioAB_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCD_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCD_clk),
 	/* additional fake clock for macb_hclk */
 	CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &uhp_clk),
 	CLKDEV_CON_DEV_ID("ohci_clk", "500000.ohci", &uhp_clk),
@@ -223,13 +224,10 @@ static void __init at91sam9n12_map_io(void)
 void __init at91sam9n12_initialize(void)
 {
 	at91_extern_irq = (1 << AT91SAM9N12_ID_IRQ0);
-
-	/* Register GPIO subsystem (using DT) */
-	at91_gpio_init(NULL, 0);
 }
 
-struct at91_init_soc __initdata at91sam9n12_soc = {
+AT91_SOC_START(sam9n12)
 	.map_io = at91sam9n12_map_io,
 	.register_clocks = at91sam9n12_register_clocks,
 	.init = at91sam9n12_initialize,
-};
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index 72e9084..eb98704 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -19,10 +19,10 @@
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
 #include <mach/at91sam9rl.h>
-#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
-#include <mach/at91_rstc.h>
 
+#include "at91_aic.h"
+#include "at91_rstc.h"
 #include "soc.h"
 #include "generic.h"
 #include "clock.h"
@@ -184,8 +184,10 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
 	CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
 	CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
-	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
-	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+	CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+	CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+	CLKDEV_CON_DEV_ID("pclk", "fffc0000.ssc", &ssc0_clk),
+	CLKDEV_CON_DEV_ID("pclk", "fffc4000.ssc", &ssc1_clk),
 	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi0_clk),
 	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.1", &twi1_clk),
 	CLKDEV_CON_ID("pioA", &pioA_clk),
@@ -338,10 +340,10 @@ static unsigned int at91sam9rl_default_irq_priority[NR_AIC_IRQS] __initdata = {
 	0,	/* Advanced Interrupt Controller */
 };
 
-struct at91_init_soc __initdata at91sam9rl_soc = {
+AT91_SOC_START(sam9rl)
 	.map_io = at91sam9rl_map_io,
 	.default_irq_priority = at91sam9rl_default_irq_priority,
 	.ioremap_registers = at91sam9rl_ioremap_registers,
 	.register_clocks = at91sam9rl_register_clocks,
 	.init = at91sam9rl_initialize,
-};
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 5047bdc..ddf223f 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -17,13 +17,13 @@
 #include <linux/fb.h>
 #include <video/atmel_lcdc.h>
 
-#include <mach/board.h>
 #include <mach/at91sam9rl.h>
 #include <mach/at91sam9rl_matrix.h>
 #include <mach/at91_matrix.h>
 #include <mach/at91sam9_smc.h>
 #include <linux/platform_data/dma-atmel.h>
 
+#include "board.h"
 #include "generic.h"
 
 
@@ -832,7 +832,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91sam9rl_ssc0_device = {
-	.name	= "ssc",
+	.name	= "at91rm9200_ssc",
 	.id	= 0,
 	.dev	= {
 		.dma_mask		= &ssc0_dmamask,
@@ -874,7 +874,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91sam9rl_ssc1_device = {
-	.name	= "ssc",
+	.name	= "at91rm9200_ssc",
 	.id	= 1,
 	.dev	= {
 		.dma_mask		= &ssc1_dmamask,
diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
index e503538..44a9a62 100644
--- a/arch/arm/mach-at91/at91sam9x5.c
+++ b/arch/arm/mach-at91/at91sam9x5.c
@@ -15,8 +15,8 @@
 #include <mach/at91sam9x5.h>
 #include <mach/at91_pmc.h>
 #include <mach/cpu.h>
-#include <mach/board.h>
 
+#include "board.h"
 #include "soc.h"
 #include "generic.h"
 #include "clock.h"
@@ -229,15 +229,18 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
 	CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb0_clk),
 	CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
+	CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc0_clk),
+	CLKDEV_CON_DEV_ID("mci_clk", "f000c000.mmc", &mmc1_clk),
 	CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma0_clk),
 	CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk),
+	CLKDEV_CON_DEV_ID("pclk", "f0010000.ssc", &ssc_clk),
 	CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
 	CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
 	CLKDEV_CON_DEV_ID(NULL, "f8018000.i2c", &twi2_clk),
-	CLKDEV_CON_ID("pioA", &pioAB_clk),
-	CLKDEV_CON_ID("pioB", &pioAB_clk),
-	CLKDEV_CON_ID("pioC", &pioCD_clk),
-	CLKDEV_CON_ID("pioD", &pioCD_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioAB_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioAB_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCD_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCD_clk),
 	/* additional fake clock for macb_hclk */
 	CLKDEV_CON_DEV_ID("hclk", "f802c000.ethernet", &macb0_clk),
 	CLKDEV_CON_DEV_ID("hclk", "f8030000.ethernet", &macb1_clk),
@@ -313,18 +316,11 @@ static void __init at91sam9x5_map_io(void)
 	at91_init_sram(0, AT91SAM9X5_SRAM_BASE, AT91SAM9X5_SRAM_SIZE);
 }
 
-void __init at91sam9x5_initialize(void)
-{
-	/* Register GPIO subsystem (using DT) */
-	at91_gpio_init(NULL, 0);
-}
-
 /* --------------------------------------------------------------------
  *  Interrupt initialization
  * -------------------------------------------------------------------- */
 
-struct at91_init_soc __initdata at91sam9x5_soc = {
+AT91_SOC_START(sam9x5)
 	.map_io = at91sam9x5_map_io,
 	.register_clocks = at91sam9x5_register_clocks,
-	.init = at91sam9x5_initialize,
-};
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91x40.c b/arch/arm/mach-at91/at91x40.c
index bb7f544..19ca793 100644
--- a/arch/arm/mach-at91/at91x40.c
+++ b/arch/arm/mach-at91/at91x40.c
@@ -18,9 +18,10 @@
 #include <asm/system_misc.h>
 #include <asm/mach/arch.h>
 #include <mach/at91x40.h>
-#include <mach/at91_aic.h>
 #include <mach/at91_st.h>
 #include <mach/timex.h>
+
+#include "at91_aic.h"
 #include "generic.h"
 
 /*
diff --git a/arch/arm/mach-at91/at91x40_time.c b/arch/arm/mach-at91/at91x40_time.c
index ee06d7b..0e57e44 100644
--- a/arch/arm/mach-at91/at91x40_time.c
+++ b/arch/arm/mach-at91/at91x40_time.c
@@ -26,7 +26,8 @@
 #include <linux/io.h>
 #include <mach/hardware.h>
 #include <asm/mach/time.h>
-#include <mach/at91_tc.h>
+
+#include "at91_tc.h"
 
 #define at91_tc_read(field) \
 	__raw_readl(AT91_IO_P2V(AT91_TC) + field)
diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
index 22d8856..b99b575 100644
--- a/arch/arm/mach-at91/board-1arm.c
+++ b/arch/arm/mach-at91/board-1arm.c
@@ -34,10 +34,10 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/board.h>
 #include <mach/cpu.h>
-#include <mach/at91_aic.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 
diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
index 93a832f..854b979 100644
--- a/arch/arm/mach-at91/board-afeb-9260v1.c
+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
@@ -43,9 +43,8 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/board.h>
-#include <mach/at91_aic.h>
-
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 
diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
index 477e708..28a18ce 100644
--- a/arch/arm/mach-at91/board-cam60.c
+++ b/arch/arm/mach-at91/board-cam60.c
@@ -38,10 +38,10 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
index 71d8f36..c17bb53 100644
--- a/arch/arm/mach-at91/board-carmeva.c
+++ b/arch/arm/mach-at91/board-carmeva.c
@@ -35,9 +35,9 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 
diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
index e71c473..8474324 100644
--- a/arch/arm/mach-at91/board-cpu9krea.c
+++ b/arch/arm/mach-at91/board-cpu9krea.c
@@ -40,12 +40,12 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91sam9260_matrix.h>
 #include <mach/at91_matrix.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c
index 2cbd1a2..2a7af78 100644
--- a/arch/arm/mach-at91/board-cpuat91.c
+++ b/arch/arm/mach-at91/board-cpuat91.c
@@ -36,12 +36,12 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 #include <mach/cpu.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 static struct gpio_led cpuat91_leds[] = {
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
index 3e37437..48a531e 100644
--- a/arch/arm/mach-at91/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -38,9 +38,9 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 
@@ -53,6 +53,8 @@ static void __init csb337_init_early(void)
 static struct macb_platform_data __initdata csb337_eth_data = {
 	.phy_irq_pin	= AT91_PIN_PC2,
 	.is_rmii	= 0,
+	/* The CSB337 bootloader stores the MAC the wrong-way around */
+	.rev_eth_addr	= 1,
 };
 
 static struct at91_usbh_data __initdata csb337_usbh_data = {
diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
index 872871a..ec0f3ab 100644
--- a/arch/arm/mach-at91/board-csb637.c
+++ b/arch/arm/mach-at91/board-csb637.c
@@ -35,9 +35,9 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 
diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
index e8f45c4..881170c 100644
--- a/arch/arm/mach-at91/board-dt.c
+++ b/arch/arm/mach-at91/board-dt.c
@@ -15,23 +15,20 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
-#include <mach/board.h>
-#include <mach/at91_aic.h>
-
 #include <asm/setup.h>
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 
 static const struct of_device_id irq_of_match[] __initconst = {
 
 	{ .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
-	{ .compatible = "atmel,at91rm9200-gpio", .data = at91_gpio_of_irq_setup },
-	{ .compatible = "atmel,at91sam9x5-gpio", .data = at91_gpio_of_irq_setup },
 	{ /*sentinel*/ }
 };
 
diff --git a/arch/arm/mach-at91/board-eb01.c b/arch/arm/mach-at91/board-eb01.c
index 01f66e9..b489388 100644
--- a/arch/arm/mach-at91/board-eb01.c
+++ b/arch/arm/mach-at91/board-eb01.c
@@ -27,8 +27,9 @@
 #include <mach/hardware.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
+
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 static void __init at91eb01_init_irq(void)
diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
index 0cfac16..9f5e71c 100644
--- a/arch/arm/mach-at91/board-eb9200.c
+++ b/arch/arm/mach-at91/board-eb9200.c
@@ -35,9 +35,8 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/board.h>
-#include <mach/at91_aic.h>
-
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 
diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
index 3d931ff..ef69e0e 100644
--- a/arch/arm/mach-at91/board-ecbat91.c
+++ b/arch/arm/mach-at91/board-ecbat91.c
@@ -37,10 +37,10 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/board.h>
 #include <mach/cpu.h>
-#include <mach/at91_aic.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 
diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c
index d93658a..50f3d37 100644
--- a/arch/arm/mach-at91/board-eco920.c
+++ b/arch/arm/mach-at91/board-eco920.c
@@ -24,12 +24,12 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 #include <mach/cpu.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 static void __init eco920_init_early(void)
diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
index fa98aba..5d44eba 100644
--- a/arch/arm/mach-at91/board-flexibity.c
+++ b/arch/arm/mach-at91/board-flexibity.c
@@ -33,9 +33,9 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 static void __init flexibity_init_early(void)
diff --git a/arch/arm/mach-at91/board-foxg20.c b/arch/arm/mach-at91/board-foxg20.c
index 6e47071..191d37c 100644
--- a/arch/arm/mach-at91/board-foxg20.c
+++ b/arch/arm/mach-at91/board-foxg20.c
@@ -41,10 +41,10 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-at91/board-gsia18s.c b/arch/arm/mach-at91/board-gsia18s.c
index a9d5e78..23a2fa1 100644
--- a/arch/arm/mach-at91/board-gsia18s.c
+++ b/arch/arm/mach-at91/board-gsia18s.c
@@ -30,14 +30,14 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
-#include <mach/gsia18s.h>
-#include <mach/stamp9g20.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
+#include "gsia18s.h"
+#include "stamp9g20.h"
 
 static void __init gsia18s_init_early(void)
 {
diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
index 86050da..9a43d1e 100644
--- a/arch/arm/mach-at91/board-kafa.c
+++ b/arch/arm/mach-at91/board-kafa.c
@@ -34,10 +34,10 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/cpu.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
index abe9fed..f168bec 100644
--- a/arch/arm/mach-at91/board-kb9202.c
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -35,12 +35,12 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/board.h>
 #include <mach/cpu.h>
-#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 
diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
index 6960778..bc7a1c4 100644
--- a/arch/arm/mach-at91/board-neocore926.c
+++ b/arch/arm/mach-at91/board-neocore926.c
@@ -44,10 +44,10 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c
index 9ca3e32..0299554 100644
--- a/arch/arm/mach-at91/board-pcontrol-g20.c
+++ b/arch/arm/mach-at91/board-pcontrol-g20.c
@@ -29,13 +29,13 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
-#include <mach/stamp9g20.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
+#include "stamp9g20.h"
 
 
 static void __init pcontrol_g20_init_early(void)
diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
index f83e1de..4938f1c 100644
--- a/arch/arm/mach-at91/board-picotux200.c
+++ b/arch/arm/mach-at91/board-picotux200.c
@@ -37,11 +37,11 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 
diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c
index 799f214..33b1628 100644
--- a/arch/arm/mach-at91/board-qil-a9260.c
+++ b/arch/arm/mach-at91/board-qil-a9260.c
@@ -40,11 +40,11 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
-#include <mach/at91_shdwc.h>
 
+#include "at91_aic.h"
+#include "at91_shdwc.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-at91/board-rm9200-dt.c b/arch/arm/mach-at91/board-rm9200-dt.c
new file mode 100644
index 0000000..5f9ce3d
--- /dev/null
+++ b/arch/arm/mach-at91/board-rm9200-dt.c
@@ -0,0 +1,57 @@
+/*
+ *  Setup code for AT91RM9200 Evaluation Kits with Device Tree support
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *                2012 Joachim Eastwood <manabian@gmail.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#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>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include "at91_aic.h"
+#include "generic.h"
+
+
+static const struct of_device_id irq_of_match[] __initconst = {
+	{ .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
+	{ /*sentinel*/ }
+};
+
+static void __init at91rm9200_dt_init_irq(void)
+{
+	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
+};
+
+DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200 (Device Tree)")
+	.timer		= &at91rm9200_timer,
+	.map_io		= at91_map_io,
+	.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-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c
index 66338e7..9e5061b 100644
--- a/arch/arm/mach-at91/board-rm9200dk.c
+++ b/arch/arm/mach-at91/board-rm9200dk.c
@@ -39,11 +39,11 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 
diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c
index 5d1b572..58277db 100644
--- a/arch/arm/mach-at91/board-rm9200ek.c
+++ b/arch/arm/mach-at91/board-rm9200ek.c
@@ -39,11 +39,11 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 
diff --git a/arch/arm/mach-at91/board-rsi-ews.c b/arch/arm/mach-at91/board-rsi-ews.c
index a0ecf04..2e8b833 100644
--- a/arch/arm/mach-at91/board-rsi-ews.c
+++ b/arch/arm/mach-at91/board-rsi-ews.c
@@ -25,11 +25,11 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 
 #include <linux/gpio.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 static void __init rsi_ews_init_early(void)
diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
index c5f01ac..b75fbf6 100644
--- a/arch/arm/mach-at91/board-sam9-l9260.c
+++ b/arch/arm/mach-at91/board-sam9-l9260.c
@@ -37,10 +37,10 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index 8cd6e67..f0135cd 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -41,12 +41,12 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
-#include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
 
+#include "at91_aic.h"
+#include "at91_shdwc.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index a9167dd..13ebaa8 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -45,12 +45,12 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
-#include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
 
+#include "at91_aic.h"
+#include "at91_shdwc.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index b87dbe2..89b9608 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -44,12 +44,12 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
-#include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
 
+#include "at91_aic.h"
+#include "at91_shdwc.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index 3ab2b86..1b7dd9f 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -43,11 +43,11 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/system_rev.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
 
@@ -353,6 +353,16 @@ static struct i2c_board_info __initdata ek_i2c_devices[] = {
         },
 };
 
+static struct platform_device sam9g20ek_audio_device = {
+	.name   = "at91sam9g20ek-audio",
+	.id     = -1,
+};
+
+static void __init ek_add_device_audio(void)
+{
+	platform_device_register(&sam9g20ek_audio_device);
+}
+
 
 static void __init ek_board_init(void)
 {
@@ -394,6 +404,7 @@ static void __init ek_board_init(void)
 	at91_set_B_periph(AT91_PIN_PC1, 0);
 	/* SSC (for WM8731) */
 	at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
+	ek_add_device_audio();
 }
 
 MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index 3d48ec1..e4cc375 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -42,12 +42,12 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
-#include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
 
+#include "at91_aic.h"
+#include "at91_shdwc.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index fb89ea9..377a109 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -30,11 +30,12 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
-#include <mach/at91_shdwc.h>
 
+
+#include "at91_aic.h"
+#include "at91_shdwc.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index a4e031a..9877150 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -32,10 +32,10 @@
 #include <asm/mach/arch.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
index c3fb31d..48a962b 100644
--- a/arch/arm/mach-at91/board-stamp9g20.c
+++ b/arch/arm/mach-at91/board-stamp9g20.c
@@ -25,10 +25,10 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-at91/board-usb-a926x.c b/arch/arm/mach-at91/board-usb-a926x.c
index 6ea069b..c1060f9 100644
--- a/arch/arm/mach-at91/board-usb-a926x.c
+++ b/arch/arm/mach-at91/board-usb-a926x.c
@@ -41,11 +41,11 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
-#include <mach/at91_shdwc.h>
 
+#include "at91_aic.h"
+#include "at91_shdwc.h"
+#include "board.h"
 #include "sam9_smc.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
index f162fdf..8673aeb 100644
--- a/arch/arm/mach-at91/board-yl-9200.c
+++ b/arch/arm/mach-at91/board-yl-9200.c
@@ -43,12 +43,12 @@
 #include <asm/mach/irq.h>
 
 #include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 #include <mach/cpu.h>
 
+#include "at91_aic.h"
+#include "board.h"
 #include "generic.h"
 
 
diff --git a/arch/arm/mach-at91/board.h b/arch/arm/mach-at91/board.h
new file mode 100644
index 0000000..4a234fb
--- /dev/null
+++ b/arch/arm/mach-at91/board.h
@@ -0,0 +1,131 @@
+/*
+ * arch/arm/mach-at91/include/mach/board.h
+ *
+ *  Copyright (C) 2005 HP Labs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * These are data structures found in platform_device.dev.platform_data,
+ * and describing board-specific data needed by drivers.  For example,
+ * which pin is used for a given GPIO role.
+ *
+ * In 2.6, drivers should strongly avoid board-specific knowledge so
+ * that supporting new boards normally won't require driver patches.
+ * Most board-specific knowledge should be in arch/.../board-*.c files.
+ */
+
+#ifndef __ASM_ARCH_BOARD_H
+#define __ASM_ARCH_BOARD_H
+
+#include <linux/platform_data/atmel.h>
+
+ /* USB Device */
+extern void __init at91_add_device_udc(struct at91_udc_data *data);
+
+ /* USB High Speed Device */
+extern void __init at91_add_device_usba(struct usba_platform_data *data);
+
+ /* Compact Flash */
+extern void __init at91_add_device_cf(struct at91_cf_data *data);
+
+ /* MMC / SD */
+  /* atmel-mci platform config */
+extern void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data);
+
+extern void __init at91_add_device_eth(struct macb_platform_data *data);
+
+ /* USB Host */
+extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
+extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data);
+extern void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data);
+
+extern void __init at91_add_device_nand(struct atmel_nand_data *data);
+
+ /* I2C*/
+#if defined(CONFIG_ARCH_AT91SAM9G45)
+extern void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices);
+#else
+extern void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices);
+#endif
+
+ /* SPI */
+extern void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices);
+
+ /* Serial */
+#define ATMEL_UART_CTS	0x01
+#define ATMEL_UART_RTS	0x02
+#define ATMEL_UART_DSR	0x04
+#define ATMEL_UART_DTR	0x08
+#define ATMEL_UART_DCD	0x10
+#define ATMEL_UART_RI	0x20
+
+extern void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins);
+
+extern struct platform_device *atmel_default_console_device;
+
+extern void __init at91_add_device_serial(void);
+
+/*
+ * PWM
+ */
+#define AT91_PWM0	0
+#define AT91_PWM1	1
+#define AT91_PWM2	2
+#define AT91_PWM3	3
+
+extern void __init at91_add_device_pwm(u32 mask);
+
+/*
+ * SSC -- accessed through ssc_request(id).  Drivers don't bind to SSC
+ * platform devices.  Their SSC ID is part of their configuration data,
+ * along with information about which SSC signals they should use.
+ */
+#define ATMEL_SSC_TK	0x01
+#define ATMEL_SSC_TF	0x02
+#define ATMEL_SSC_TD	0x04
+#define ATMEL_SSC_TX	(ATMEL_SSC_TK | ATMEL_SSC_TF | ATMEL_SSC_TD)
+
+#define ATMEL_SSC_RK	0x10
+#define ATMEL_SSC_RF	0x20
+#define ATMEL_SSC_RD	0x40
+#define ATMEL_SSC_RX	(ATMEL_SSC_RK | ATMEL_SSC_RF | ATMEL_SSC_RD)
+
+extern void __init at91_add_device_ssc(unsigned id, unsigned pins);
+
+ /* LCD Controller */
+struct atmel_lcdfb_info;
+extern void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data);
+
+ /* AC97 */
+extern void __init at91_add_device_ac97(struct ac97c_platform_data *data);
+
+ /* ISI */
+struct isi_platform_data;
+extern void __init at91_add_device_isi(struct isi_platform_data *data,
+		bool use_pck_as_mck);
+
+ /* Touchscreen Controller */
+extern void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data);
+
+/* CAN */
+extern void __init at91_add_device_can(struct at91_can_data *data);
+
+ /* LEDs */
+extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);
+extern void __init at91_pwm_leds(struct gpio_led *leds, int nr);
+
+#endif
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index b62f560e..fc593d6 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -20,6 +20,7 @@ extern void __init at91_init_sram(int bank, unsigned long base,
 extern void __init at91rm9200_set_type(int type);
 extern void __init at91_initialize(unsigned long main_clock);
 extern void __init at91x40_initialize(unsigned long main_clock);
+extern void __init at91rm9200_dt_initialize(void);
 extern void __init at91_dt_initialize(void);
 
  /* Interrupts */
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
index be42cf0..c5d7e1e 100644
--- a/arch/arm/mach-at91/gpio.c
+++ b/arch/arm/mach-at91/gpio.c
@@ -23,8 +23,6 @@
 #include <linux/io.h>
 #include <linux/irqdomain.h>
 #include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_gpio.h>
 
 #include <asm/mach/irq.h>
 
@@ -33,6 +31,8 @@
 
 #include "generic.h"
 
+#define MAX_NB_GPIO_PER_BANK	32
+
 struct at91_gpio_chip {
 	struct gpio_chip	chip;
 	struct at91_gpio_chip	*next;		/* Bank sharing same clock */
@@ -46,6 +46,7 @@ struct at91_gpio_chip {
 
 #define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip)
 
+static int at91_gpiolib_request(struct gpio_chip *chip, unsigned offset);
 static void at91_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip);
 static void at91_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val);
 static int at91_gpiolib_get(struct gpio_chip *chip, unsigned offset);
@@ -55,26 +56,27 @@ static int at91_gpiolib_direction_input(struct gpio_chip *chip,
 					unsigned offset);
 static int at91_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset);
 
-#define AT91_GPIO_CHIP(name, nr_gpio)					\
+#define AT91_GPIO_CHIP(name)						\
 	{								\
 		.chip = {						\
 			.label		  = name,			\
+			.request	  = at91_gpiolib_request,	\
 			.direction_input  = at91_gpiolib_direction_input, \
 			.direction_output = at91_gpiolib_direction_output, \
 			.get		  = at91_gpiolib_get,		\
 			.set		  = at91_gpiolib_set,		\
 			.dbg_show	  = at91_gpiolib_dbg_show,	\
 			.to_irq		  = at91_gpiolib_to_irq,	\
-			.ngpio		  = nr_gpio,			\
+			.ngpio		  = MAX_NB_GPIO_PER_BANK,	\
 		},							\
 	}
 
 static struct at91_gpio_chip gpio_chip[] = {
-	AT91_GPIO_CHIP("pioA", 32),
-	AT91_GPIO_CHIP("pioB", 32),
-	AT91_GPIO_CHIP("pioC", 32),
-	AT91_GPIO_CHIP("pioD", 32),
-	AT91_GPIO_CHIP("pioE", 32),
+	AT91_GPIO_CHIP("pioA"),
+	AT91_GPIO_CHIP("pioB"),
+	AT91_GPIO_CHIP("pioC"),
+	AT91_GPIO_CHIP("pioD"),
+	AT91_GPIO_CHIP("pioE"),
 };
 
 static int gpio_banks;
@@ -89,7 +91,7 @@ static unsigned long at91_gpio_caps;
 
 static inline void __iomem *pin_to_controller(unsigned pin)
 {
-	pin /= 32;
+	pin /= MAX_NB_GPIO_PER_BANK;
 	if (likely(pin < gpio_banks))
 		return gpio_chip[pin].regbase;
 
@@ -98,7 +100,7 @@ static inline void __iomem *pin_to_controller(unsigned pin)
 
 static inline unsigned pin_to_mask(unsigned pin)
 {
-	return 1 << (pin % 32);
+	return 1 << (pin % MAX_NB_GPIO_PER_BANK);
 }
 
 
@@ -713,80 +715,6 @@ postcore_initcall(at91_gpio_debugfs_init);
  */
 static struct lock_class_key gpio_lock_class;
 
-#if defined(CONFIG_OF)
-static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq,
-							irq_hw_number_t hw)
-{
-	struct at91_gpio_chip	*at91_gpio = h->host_data;
-
-	irq_set_lockdep_class(virq, &gpio_lock_class);
-
-	/*
-	 * Can use the "simple" and not "edge" handler since it's
-	 * shorter, and the AIC handles interrupts sanely.
-	 */
-	irq_set_chip_and_handler(virq, &gpio_irqchip,
-				 handle_simple_irq);
-	set_irq_flags(virq, IRQF_VALID);
-	irq_set_chip_data(virq, at91_gpio);
-
-	return 0;
-}
-
-static struct irq_domain_ops at91_gpio_ops = {
-	.map	= at91_gpio_irq_map,
-	.xlate	= irq_domain_xlate_twocell,
-};
-
-int __init at91_gpio_of_irq_setup(struct device_node *node,
-				     struct device_node *parent)
-{
-	struct at91_gpio_chip	*prev = NULL;
-	int			alias_idx = of_alias_get_id(node, "gpio");
-	struct at91_gpio_chip	*at91_gpio = &gpio_chip[alias_idx];
-
-	/* Setup proper .irq_set_type function */
-	if (has_pio3())
-		gpio_irqchip.irq_set_type = alt_gpio_irq_type;
-	else
-		gpio_irqchip.irq_set_type = gpio_irq_type;
-
-	/* Disable irqs of this PIO controller */
-	__raw_writel(~0, at91_gpio->regbase + PIO_IDR);
-
-	/* Setup irq domain */
-	at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio,
-						&at91_gpio_ops, at91_gpio);
-	if (!at91_gpio->domain)
-		panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n",
-			at91_gpio->pioc_idx);
-
-	/* Setup chained handler */
-	if (at91_gpio->pioc_idx)
-		prev = &gpio_chip[at91_gpio->pioc_idx - 1];
-
-	/* The toplevel 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.
-	 */
-	if (prev && prev->next == at91_gpio)
-		return 0;
-
-	at91_gpio->pioc_virq = irq_create_mapping(irq_find_host(parent),
-							at91_gpio->pioc_hwirq);
-	irq_set_chip_data(at91_gpio->pioc_virq, at91_gpio);
-	irq_set_chained_handler(at91_gpio->pioc_virq, gpio_irq_handler);
-
-	return 0;
-}
-#else
-int __init at91_gpio_of_irq_setup(struct device_node *node,
-				     struct device_node *parent)
-{
-	return -EINVAL;
-}
-#endif
-
 /*
  * irqdomain initialization: pile up irqdomains on top of AIC range
  */
@@ -862,6 +790,16 @@ void __init at91_gpio_irq_setup(void)
 }
 
 /* gpiolib support */
+static int at91_gpiolib_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+	void __iomem *pio = at91_gpio->regbase;
+	unsigned mask = 1 << offset;
+
+	__raw_writel(mask, pio + PIO_PER);
+	return 0;
+}
+
 static int at91_gpiolib_direction_input(struct gpio_chip *chip,
 					unsigned offset)
 {
@@ -975,81 +913,11 @@ err:
 	return -EINVAL;
 }
 
-#ifdef CONFIG_OF_GPIO
-static void __init of_at91_gpio_init_one(struct device_node *np)
-{
-	int alias_idx;
-	struct at91_gpio_chip *at91_gpio;
-
-	if (!np)
-		return;
-
-	alias_idx = of_alias_get_id(np, "gpio");
-	if (alias_idx >= MAX_GPIO_BANKS) {
-		pr_err("at91_gpio, failed alias idx(%d) > MAX_GPIO_BANKS(%d), ignoring.\n",
-						alias_idx, MAX_GPIO_BANKS);
-		return;
-	}
-
-	at91_gpio = &gpio_chip[alias_idx];
-	at91_gpio->chip.base = alias_idx * at91_gpio->chip.ngpio;
-
-	at91_gpio->regbase = of_iomap(np, 0);
-	if (!at91_gpio->regbase) {
-		pr_err("at91_gpio.%d, failed to map registers, ignoring.\n",
-								alias_idx);
-		return;
-	}
-
-	/* Get the interrupts property */
-	if (of_property_read_u32(np, "interrupts", &at91_gpio->pioc_hwirq)) {
-		pr_err("at91_gpio.%d, failed to get interrupts property, ignoring.\n",
-								alias_idx);
-		goto ioremap_err;
-	}
-
-	/* Get capabilities from compatibility property */
-	if (of_device_is_compatible(np, "atmel,at91sam9x5-gpio"))
-		at91_gpio_caps |= AT91_GPIO_CAP_PIO3;
-
-	/* Setup clock */
-	if (at91_gpio_setup_clk(alias_idx))
-		goto ioremap_err;
-
-	at91_gpio->chip.of_node = np;
-	gpio_banks = max(gpio_banks, alias_idx + 1);
-	at91_gpio->pioc_idx = alias_idx;
-	return;
-
-ioremap_err:
-	iounmap(at91_gpio->regbase);
-}
-
-static int __init of_at91_gpio_init(void)
-{
-	struct device_node *np = NULL;
-
-	/*
-	 * This isn't ideal, but it gets things hooked up until this
-	 * driver is converted into a platform_device
-	 */
-	for_each_compatible_node(np, NULL, "atmel,at91rm9200-gpio")
-		of_at91_gpio_init_one(np);
-
-	return gpio_banks > 0 ? 0 : -EINVAL;
-}
-#else
-static int __init of_at91_gpio_init(void)
-{
-	return -EINVAL;
-}
-#endif
-
 static void __init at91_gpio_init_one(int idx, u32 regbase, int pioc_hwirq)
 {
 	struct at91_gpio_chip *at91_gpio = &gpio_chip[idx];
 
-	at91_gpio->chip.base = idx * at91_gpio->chip.ngpio;
+	at91_gpio->chip.base = idx * MAX_NB_GPIO_PER_BANK;
 	at91_gpio->pioc_hwirq = pioc_hwirq;
 	at91_gpio->pioc_idx = idx;
 
@@ -1079,11 +947,11 @@ void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
 
 	BUG_ON(nr_banks > MAX_GPIO_BANKS);
 
-	if (of_at91_gpio_init() < 0) {
-		/* No GPIO controller found in device tree */
-		for (i = 0; i < nr_banks; i++)
-			at91_gpio_init_one(i, data[i].regbase, data[i].id);
-	}
+	if (of_have_populated_dt())
+		return;
+
+	for (i = 0; i < nr_banks; i++)
+		at91_gpio_init_one(i, data[i].regbase, data[i].id);
 
 	for (i = 0; i < gpio_banks; i++) {
 		at91_gpio = &gpio_chip[i];
diff --git a/arch/arm/mach-at91/gsia18s.h b/arch/arm/mach-at91/gsia18s.h
new file mode 100644
index 0000000..307c194
--- /dev/null
+++ b/arch/arm/mach-at91/gsia18s.h
@@ -0,0 +1,33 @@
+/* Buttons */
+#define GPIO_TRIG_NET_IN		AT91_PIN_PB21
+#define GPIO_CARD_UNMOUNT_0		AT91_PIN_PB13
+#define GPIO_CARD_UNMOUNT_1		AT91_PIN_PB12
+#define GPIO_KEY_POWER			AT91_PIN_PA25
+
+/* PCF8574 0x20 GPIO - U1 on the GS_IA18-CB_V3 board */
+#define GS_IA18_S_PCF_GPIO_BASE0	NR_BUILTIN_GPIO
+#define PCF_GPIO_HDC_POWER		(GS_IA18_S_PCF_GPIO_BASE0 + 0)
+#define PCF_GPIO_WIFI_SETUP		(GS_IA18_S_PCF_GPIO_BASE0 + 1)
+#define PCF_GPIO_WIFI_ENABLE		(GS_IA18_S_PCF_GPIO_BASE0 + 2)
+#define PCF_GPIO_WIFI_RESET		(GS_IA18_S_PCF_GPIO_BASE0 + 3)
+#define PCF_GPIO_ETH_DETECT		4 /* this is a GPI */
+#define PCF_GPIO_GPS_SETUP		(GS_IA18_S_PCF_GPIO_BASE0 + 5)
+#define PCF_GPIO_GPS_STANDBY		(GS_IA18_S_PCF_GPIO_BASE0 + 6)
+#define PCF_GPIO_GPS_POWER		(GS_IA18_S_PCF_GPIO_BASE0 + 7)
+
+/* PCF8574 0x22 GPIO - U1 on the GS_2G_OPT1-A_V0 board (Alarm) */
+#define GS_IA18_S_PCF_GPIO_BASE1	(GS_IA18_S_PCF_GPIO_BASE0 + 8)
+#define PCF_GPIO_ALARM1			(GS_IA18_S_PCF_GPIO_BASE1 + 0)
+#define PCF_GPIO_ALARM2			(GS_IA18_S_PCF_GPIO_BASE1 + 1)
+#define PCF_GPIO_ALARM3			(GS_IA18_S_PCF_GPIO_BASE1 + 2)
+#define PCF_GPIO_ALARM4			(GS_IA18_S_PCF_GPIO_BASE1 + 3)
+/* bits 4, 5, 6 not used */
+#define PCF_GPIO_ALARM_V_RELAY_ON	(GS_IA18_S_PCF_GPIO_BASE1 + 7)
+
+/* PCF8574 0x24 GPIO U1 on the GS_2G-OPT23-A_V0 board (Modem) */
+#define GS_IA18_S_PCF_GPIO_BASE2	(GS_IA18_S_PCF_GPIO_BASE1 + 8)
+#define PCF_GPIO_MODEM_POWER		(GS_IA18_S_PCF_GPIO_BASE2 + 0)
+#define PCF_GPIO_MODEM_RESET		(GS_IA18_S_PCF_GPIO_BASE2 + 3)
+/* bits 1, 2, 4, 5 not used */
+#define PCF_GPIO_TRX_RESET		(GS_IA18_S_PCF_GPIO_BASE2 + 6)
+/* bit 7 not used */
diff --git a/arch/arm/mach-at91/include/mach/at91_aic.h b/arch/arm/mach-at91/include/mach/at91_aic.h
deleted file mode 100644
index eaea661..0000000
--- a/arch/arm/mach-at91/include/mach/at91_aic.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_aic.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Advanced Interrupt Controller (AIC) - System peripherals registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91_AIC_H
-#define AT91_AIC_H
-
-#ifndef __ASSEMBLY__
-extern void __iomem *at91_aic_base;
-
-#define at91_aic_read(field) \
-	__raw_readl(at91_aic_base + field)
-
-#define at91_aic_write(field, value) \
-	__raw_writel(value, at91_aic_base + field)
-#else
-.extern at91_aic_base
-#endif
-
-/* Number of irq lines managed by AIC */
-#define NR_AIC_IRQS	32
-#define NR_AIC5_IRQS	128
-
-#define AT91_AIC5_SSR		0x0			/* Source Select Register [AIC5] */
-#define 	AT91_AIC5_INTSEL_MSK	(0x7f << 0)		/* Interrupt Line Selection Mask */
-
-#define AT91_AIC_IRQ_MIN_PRIORITY	0
-#define AT91_AIC_IRQ_MAX_PRIORITY	7
-
-#define AT91_AIC_SMR(n)		((n) * 4)		/* Source Mode Registers 0-31 */
-#define AT91_AIC5_SMR		0x4			/* Source Mode Register [AIC5] */
-#define		AT91_AIC_PRIOR		(7 << 0)		/* Priority Level */
-#define		AT91_AIC_SRCTYPE	(3 << 5)		/* Interrupt Source Type */
-#define			AT91_AIC_SRCTYPE_LOW		(0 << 5)
-#define			AT91_AIC_SRCTYPE_FALLING	(1 << 5)
-#define			AT91_AIC_SRCTYPE_HIGH		(2 << 5)
-#define			AT91_AIC_SRCTYPE_RISING		(3 << 5)
-
-#define AT91_AIC_SVR(n)		(0x80 + ((n) * 4))	/* Source Vector Registers 0-31 */
-#define AT91_AIC5_SVR		0x8			/* Source Vector Register [AIC5] */
-#define AT91_AIC_IVR		0x100			/* Interrupt Vector Register */
-#define AT91_AIC5_IVR		0x10			/* Interrupt Vector Register [AIC5] */
-#define AT91_AIC_FVR		0x104			/* Fast Interrupt Vector Register */
-#define AT91_AIC5_FVR		0x14			/* Fast Interrupt Vector Register [AIC5] */
-#define AT91_AIC_ISR		0x108			/* Interrupt Status Register */
-#define AT91_AIC5_ISR		0x18			/* Interrupt Status Register [AIC5] */
-#define		AT91_AIC_IRQID		(0x1f << 0)		/* Current Interrupt Identifier */
-
-#define AT91_AIC_IPR		0x10c			/* Interrupt Pending Register */
-#define AT91_AIC5_IPR0		0x20			/* Interrupt Pending Register 0 [AIC5] */
-#define AT91_AIC5_IPR1		0x24			/* Interrupt Pending Register 1 [AIC5] */
-#define AT91_AIC5_IPR2		0x28			/* Interrupt Pending Register 2 [AIC5] */
-#define AT91_AIC5_IPR3		0x2c			/* Interrupt Pending Register 3 [AIC5] */
-#define AT91_AIC_IMR		0x110			/* Interrupt Mask Register */
-#define AT91_AIC5_IMR		0x30			/* Interrupt Mask Register [AIC5] */
-#define AT91_AIC_CISR		0x114			/* Core Interrupt Status Register */
-#define AT91_AIC5_CISR		0x34			/* Core Interrupt Status Register [AIC5] */
-#define		AT91_AIC_NFIQ		(1 << 0)		/* nFIQ Status */
-#define		AT91_AIC_NIRQ		(1 << 1)		/* nIRQ Status */
-
-#define AT91_AIC_IECR		0x120			/* Interrupt Enable Command Register */
-#define AT91_AIC5_IECR		0x40			/* Interrupt Enable Command Register [AIC5] */
-#define AT91_AIC_IDCR		0x124			/* Interrupt Disable Command Register */
-#define AT91_AIC5_IDCR		0x44			/* Interrupt Disable Command Register [AIC5] */
-#define AT91_AIC_ICCR		0x128			/* Interrupt Clear Command Register */
-#define AT91_AIC5_ICCR		0x48			/* Interrupt Clear Command Register [AIC5] */
-#define AT91_AIC_ISCR		0x12c			/* Interrupt Set Command Register */
-#define AT91_AIC5_ISCR		0x4c			/* Interrupt Set Command Register [AIC5] */
-#define AT91_AIC_EOICR		0x130			/* End of Interrupt Command Register */
-#define AT91_AIC5_EOICR		0x38			/* End of Interrupt Command Register [AIC5] */
-#define AT91_AIC_SPU		0x134			/* Spurious Interrupt Vector Register */
-#define AT91_AIC5_SPU		0x3c			/* Spurious Interrupt Vector Register [AIC5] */
-#define AT91_AIC_DCR		0x138			/* Debug Control Register */
-#define AT91_AIC5_DCR		0x6c			/* Debug Control Register [AIC5] */
-#define		AT91_AIC_DCR_PROT	(1 << 0)		/* Protection Mode */
-#define		AT91_AIC_DCR_GMSK	(1 << 1)		/* General Mask */
-
-#define AT91_AIC_FFER		0x140			/* Fast Forcing Enable Register [SAM9 only] */
-#define AT91_AIC5_FFER		0x50			/* Fast Forcing Enable Register [AIC5] */
-#define AT91_AIC_FFDR		0x144			/* Fast Forcing Disable Register [SAM9 only] */
-#define AT91_AIC5_FFDR		0x54			/* Fast Forcing Disable Register [AIC5] */
-#define AT91_AIC_FFSR		0x148			/* Fast Forcing Status Register [SAM9 only] */
-#define AT91_AIC5_FFSR		0x58			/* Fast Forcing Status Register [AIC5] */
-
-void at91_aic_handle_irq(struct pt_regs *regs);
-void at91_aic5_handle_irq(struct pt_regs *regs);
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91_pit.h b/arch/arm/mach-at91/include/mach/at91_pit.h
deleted file mode 100644
index d1f80ad..0000000
--- a/arch/arm/mach-at91/include/mach/at91_pit.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_pit.h
- *
- * Copyright (C) 2007 Andrew Victor
- * Copyright (C) 2007 Atmel Corporation.
- *
- * Periodic Interval Timer (PIT) - System peripherals regsters.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91_PIT_H
-#define AT91_PIT_H
-
-#define AT91_PIT_MR		0x00			/* Mode Register */
-#define		AT91_PIT_PITIEN		(1 << 25)		/* Timer Interrupt Enable */
-#define		AT91_PIT_PITEN		(1 << 24)		/* Timer Enabled */
-#define		AT91_PIT_PIV		(0xfffff)		/* Periodic Interval Value */
-
-#define AT91_PIT_SR		0x04			/* Status Register */
-#define		AT91_PIT_PITS		(1 << 0)		/* Timer Status */
-
-#define AT91_PIT_PIVR		0x08			/* Periodic Interval Value Register */
-#define AT91_PIT_PIIR		0x0c			/* Periodic Interval Image Register */
-#define		AT91_PIT_PICNT		(0xfff << 20)		/* Interval Counter */
-#define		AT91_PIT_CPIV		(0xfffff)		/* Inverval Value */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91_rstc.h b/arch/arm/mach-at91/include/mach/at91_rstc.h
deleted file mode 100644
index 875fa33..0000000
--- a/arch/arm/mach-at91/include/mach/at91_rstc.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_rstc.h
- *
- * Copyright (C) 2007 Andrew Victor
- * Copyright (C) 2007 Atmel Corporation.
- *
- * Reset Controller (RSTC) - System peripherals regsters.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91_RSTC_H
-#define AT91_RSTC_H
-
-#ifndef __ASSEMBLY__
-extern void __iomem *at91_rstc_base;
-
-#define at91_rstc_read(field) \
-	__raw_readl(at91_rstc_base + field)
-
-#define at91_rstc_write(field, value) \
-	__raw_writel(value, at91_rstc_base + field);
-#else
-.extern at91_rstc_base
-#endif
-
-#define AT91_RSTC_CR		0x00			/* Reset Controller Control Register */
-#define		AT91_RSTC_PROCRST	(1 << 0)		/* Processor Reset */
-#define		AT91_RSTC_PERRST	(1 << 2)		/* Peripheral Reset */
-#define		AT91_RSTC_EXTRST	(1 << 3)		/* External Reset */
-#define		AT91_RSTC_KEY		(0xa5 << 24)		/* KEY Password */
-
-#define AT91_RSTC_SR		0x04			/* Reset Controller Status Register */
-#define		AT91_RSTC_URSTS		(1 << 0)		/* User Reset Status */
-#define		AT91_RSTC_RSTTYP	(7 << 8)		/* Reset Type */
-#define			AT91_RSTC_RSTTYP_GENERAL	(0 << 8)
-#define			AT91_RSTC_RSTTYP_WAKEUP		(1 << 8)
-#define			AT91_RSTC_RSTTYP_WATCHDOG	(2 << 8)
-#define			AT91_RSTC_RSTTYP_SOFTWARE	(3 << 8)
-#define			AT91_RSTC_RSTTYP_USER	(4 << 8)
-#define		AT91_RSTC_NRSTL		(1 << 16)		/* NRST Pin Level */
-#define		AT91_RSTC_SRCMP		(1 << 17)		/* Software Reset Command in Progress */
-
-#define AT91_RSTC_MR		0x08			/* Reset Controller Mode Register */
-#define		AT91_RSTC_URSTEN	(1 << 0)		/* User Reset Enable */
-#define		AT91_RSTC_URSTIEN	(1 << 4)		/* User Reset Interrupt Enable */
-#define		AT91_RSTC_ERSTL		(0xf << 8)		/* External Reset Length */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91_rtc.h b/arch/arm/mach-at91/include/mach/at91_rtc.h
deleted file mode 100644
index da1945e..0000000
--- a/arch/arm/mach-at91/include/mach/at91_rtc.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_rtc.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Real Time Clock (RTC) - System peripheral registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91_RTC_H
-#define AT91_RTC_H
-
-#define	AT91_RTC_CR		0x00			/* Control Register */
-#define		AT91_RTC_UPDTIM		(1 <<  0)		/* Update Request Time Register */
-#define		AT91_RTC_UPDCAL		(1 <<  1)		/* Update Request Calendar Register */
-#define		AT91_RTC_TIMEVSEL	(3 <<  8)		/* Time Event Selection */
-#define			AT91_RTC_TIMEVSEL_MINUTE	(0 << 8)
-#define			AT91_RTC_TIMEVSEL_HOUR		(1 << 8)
-#define			AT91_RTC_TIMEVSEL_DAY24		(2 << 8)
-#define			AT91_RTC_TIMEVSEL_DAY12		(3 << 8)
-#define		AT91_RTC_CALEVSEL	(3 << 16)		/* Calendar Event Selection */
-#define			AT91_RTC_CALEVSEL_WEEK		(0 << 16)
-#define			AT91_RTC_CALEVSEL_MONTH		(1 << 16)
-#define			AT91_RTC_CALEVSEL_YEAR		(2 << 16)
-
-#define	AT91_RTC_MR		0x04			/* Mode Register */
-#define			AT91_RTC_HRMOD		(1 <<  0)		/* 12/24 Hour Mode */
-
-#define	AT91_RTC_TIMR		0x08			/* Time Register */
-#define		AT91_RTC_SEC		(0x7f <<  0)		/* Current Second */
-#define		AT91_RTC_MIN		(0x7f <<  8)		/* Current Minute */
-#define		AT91_RTC_HOUR		(0x3f << 16)		/* Current Hour */
-#define		AT91_RTC_AMPM		(1    << 22)		/* Ante Meridiem Post Meridiem Indicator */
-
-#define	AT91_RTC_CALR		0x0c			/* Calendar Register */
-#define		AT91_RTC_CENT		(0x7f <<  0)		/* Current Century */
-#define		AT91_RTC_YEAR		(0xff <<  8)		/* Current Year */
-#define		AT91_RTC_MONTH		(0x1f << 16)		/* Current Month */
-#define		AT91_RTC_DAY		(7    << 21)		/* Current Day */
-#define		AT91_RTC_DATE		(0x3f << 24)		/* Current Date */
-
-#define	AT91_RTC_TIMALR		0x10			/* Time Alarm Register */
-#define		AT91_RTC_SECEN		(1 <<  7)		/* Second Alarm Enable */
-#define		AT91_RTC_MINEN		(1 << 15)		/* Minute Alarm Enable */
-#define		AT91_RTC_HOUREN		(1 << 23)		/* Hour Alarm Enable */
-
-#define	AT91_RTC_CALALR		0x14			/* Calendar Alarm Register */
-#define		AT91_RTC_MTHEN		(1 << 23)		/* Month Alarm Enable */
-#define		AT91_RTC_DATEEN		(1 << 31)		/* Date Alarm Enable */
-
-#define	AT91_RTC_SR		0x18			/* Status Register */
-#define		AT91_RTC_ACKUPD		(1 <<  0)		/* Acknowledge for Update */
-#define		AT91_RTC_ALARM		(1 <<  1)		/* Alarm Flag */
-#define		AT91_RTC_SECEV		(1 <<  2)		/* Second Event */
-#define		AT91_RTC_TIMEV		(1 <<  3)		/* Time Event */
-#define		AT91_RTC_CALEV		(1 <<  4)		/* Calendar Event */
-
-#define	AT91_RTC_SCCR		0x1c			/* Status Clear Command Register */
-#define	AT91_RTC_IER		0x20			/* Interrupt Enable Register */
-#define	AT91_RTC_IDR		0x24			/* Interrupt Disable Register */
-#define	AT91_RTC_IMR		0x28			/* Interrupt Mask Register */
-
-#define	AT91_RTC_VER		0x2c			/* Valid Entry Register */
-#define		AT91_RTC_NVTIM		(1 <<  0)		/* Non valid Time */
-#define		AT91_RTC_NVCAL		(1 <<  1)		/* Non valid Calendar */
-#define		AT91_RTC_NVTIMALR	(1 <<  2)		/* Non valid Time Alarm */
-#define		AT91_RTC_NVCALALR	(1 <<  3)		/* Non valid Calendar Alarm */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91_shdwc.h b/arch/arm/mach-at91/include/mach/at91_shdwc.h
deleted file mode 100644
index 60478ea..0000000
--- a/arch/arm/mach-at91/include/mach/at91_shdwc.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_shdwc.h
- *
- * Copyright (C) 2007 Andrew Victor
- * Copyright (C) 2007 Atmel Corporation.
- *
- * Shutdown Controller (SHDWC) - System peripherals regsters.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91_SHDWC_H
-#define AT91_SHDWC_H
-
-#ifndef __ASSEMBLY__
-extern void __iomem *at91_shdwc_base;
-
-#define at91_shdwc_read(field) \
-	__raw_readl(at91_shdwc_base + field)
-
-#define at91_shdwc_write(field, value) \
-	__raw_writel(value, at91_shdwc_base + field);
-#endif
-
-#define AT91_SHDW_CR		0x00			/* Shut Down Control Register */
-#define		AT91_SHDW_SHDW		(1    << 0)		/* Shut Down command */
-#define		AT91_SHDW_KEY		(0xa5 << 24)		/* KEY Password */
-
-#define AT91_SHDW_MR		0x04			/* Shut Down Mode Register */
-#define		AT91_SHDW_WKMODE0	(3 << 0)		/* Wake-up 0 Mode Selection */
-#define			AT91_SHDW_WKMODE0_NONE		0
-#define			AT91_SHDW_WKMODE0_HIGH		1
-#define			AT91_SHDW_WKMODE0_LOW		2
-#define			AT91_SHDW_WKMODE0_ANYLEVEL	3
-#define		AT91_SHDW_CPTWK0_MAX	0xf			/* Maximum Counter On Wake Up 0 */
-#define		AT91_SHDW_CPTWK0	(AT91_SHDW_CPTWK0_MAX << 4) /* Counter On Wake Up 0 */
-#define			AT91_SHDW_CPTWK0_(x)	((x) << 4)
-#define		AT91_SHDW_RTTWKEN	(1   << 16)		/* Real Time Timer Wake-up Enable */
-#define		AT91_SHDW_RTCWKEN	(1   << 17)		/* Real Time Clock Wake-up Enable */
-
-#define AT91_SHDW_SR		0x08			/* Shut Down Status Register */
-#define		AT91_SHDW_WAKEUP0	(1 <<  0)		/* Wake-up 0 Status */
-#define		AT91_SHDW_RTTWK		(1 << 16)		/* Real-time Timer Wake-up */
-#define		AT91_SHDW_RTCWK		(1 << 17)		/* Real-time Clock Wake-up [SAM9RL] */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91_tc.h b/arch/arm/mach-at91/include/mach/at91_tc.h
deleted file mode 100644
index 46a317f..0000000
--- a/arch/arm/mach-at91/include/mach/at91_tc.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_tc.h
- *
- * Copyright (C) SAN People
- *
- * Timer/Counter Unit (TC) registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91_TC_H
-#define AT91_TC_H
-
-#define AT91_TC_BCR		0xc0		/* TC Block Control Register */
-#define		AT91_TC_SYNC		(1 << 0)	/* Synchro Command */
-
-#define AT91_TC_BMR		0xc4		/* TC Block Mode Register */
-#define		AT91_TC_TC0XC0S		(3 << 0)	/* External Clock Signal 0 Selection */
-#define			AT91_TC_TC0XC0S_TCLK0		(0 << 0)
-#define			AT91_TC_TC0XC0S_NONE		(1 << 0)
-#define			AT91_TC_TC0XC0S_TIOA1		(2 << 0)
-#define			AT91_TC_TC0XC0S_TIOA2		(3 << 0)
-#define		AT91_TC_TC1XC1S		(3 << 2)	/* External Clock Signal 1 Selection */
-#define			AT91_TC_TC1XC1S_TCLK1		(0 << 2)
-#define			AT91_TC_TC1XC1S_NONE		(1 << 2)
-#define			AT91_TC_TC1XC1S_TIOA0		(2 << 2)
-#define			AT91_TC_TC1XC1S_TIOA2		(3 << 2)
-#define		AT91_TC_TC2XC2S		(3 << 4)	/* External Clock Signal 2 Selection */
-#define			AT91_TC_TC2XC2S_TCLK2		(0 << 4)
-#define			AT91_TC_TC2XC2S_NONE		(1 << 4)
-#define			AT91_TC_TC2XC2S_TIOA0		(2 << 4)
-#define			AT91_TC_TC2XC2S_TIOA1		(3 << 4)
-
-
-#define AT91_TC_CCR		0x00		/* Channel Control Register */
-#define		AT91_TC_CLKEN		(1 << 0)	/* Counter Clock Enable Command */
-#define		AT91_TC_CLKDIS		(1 << 1)	/* Counter CLock Disable Command */
-#define		AT91_TC_SWTRG		(1 << 2)	/* Software Trigger Command */
-
-#define AT91_TC_CMR		0x04		/* Channel Mode Register */
-#define		AT91_TC_TCCLKS		(7 << 0)	/* Capture/Waveform Mode: Clock Selection */
-#define			AT91_TC_TIMER_CLOCK1		(0 << 0)
-#define			AT91_TC_TIMER_CLOCK2		(1 << 0)
-#define			AT91_TC_TIMER_CLOCK3		(2 << 0)
-#define			AT91_TC_TIMER_CLOCK4		(3 << 0)
-#define			AT91_TC_TIMER_CLOCK5		(4 << 0)
-#define			AT91_TC_XC0			(5 << 0)
-#define			AT91_TC_XC1			(6 << 0)
-#define			AT91_TC_XC2			(7 << 0)
-#define		AT91_TC_CLKI		(1 << 3)	/* Capture/Waveform Mode: Clock Invert */
-#define		AT91_TC_BURST		(3 << 4)	/* Capture/Waveform Mode: Burst Signal Selection */
-#define		AT91_TC_LDBSTOP		(1 << 6)	/* Capture Mode: Counter Clock Stopped with TB Loading */
-#define		AT91_TC_LDBDIS		(1 << 7)	/* Capture Mode: Counter Clock Disable with RB Loading */
-#define		AT91_TC_ETRGEDG		(3 << 8)	/* Capture Mode: External Trigger Edge Selection */
-#define		AT91_TC_ABETRG		(1 << 10)	/* Capture Mode: TIOA or TIOB External Trigger Selection */
-#define		AT91_TC_CPCTRG		(1 << 14)	/* Capture Mode: RC Compare Trigger Enable */
-#define		AT91_TC_WAVE		(1 << 15)	/* Capture/Waveform mode */
-#define		AT91_TC_LDRA		(3 << 16)	/* Capture Mode: RA Loading Selection */
-#define		AT91_TC_LDRB		(3 << 18)	/* Capture Mode: RB Loading Selection */
-
-#define		AT91_TC_CPCSTOP		(1 <<  6)	/* Waveform Mode: Counter Clock Stopped with RC Compare */
-#define		AT91_TC_CPCDIS		(1 <<  7)	/* Waveform Mode: Counter Clock Disable with RC Compare */
-#define		AT91_TC_EEVTEDG		(3 <<  8)	/* Waveform Mode: External Event Edge Selection */
-#define			AT91_TC_EEVTEDG_NONE		(0 << 8)
-#define			AT91_TC_EEVTEDG_RISING		(1 << 8)
-#define			AT91_TC_EEVTEDG_FALLING		(2 << 8)
-#define			AT91_TC_EEVTEDG_BOTH		(3 << 8)
-#define		AT91_TC_EEVT		(3 << 10)	/* Waveform Mode: External Event Selection */
-#define			AT91_TC_EEVT_TIOB		(0 << 10)
-#define			AT91_TC_EEVT_XC0		(1 << 10)
-#define			AT91_TC_EEVT_XC1		(2 << 10)
-#define			AT91_TC_EEVT_XC2		(3 << 10)
-#define		AT91_TC_ENETRG		(1 << 12)	/* Waveform Mode: External Event Trigger Enable */
-#define		AT91_TC_WAVESEL		(3 << 13)	/* Waveform Mode: Waveform Selection */
-#define			AT91_TC_WAVESEL_UP		(0 << 13)
-#define			AT91_TC_WAVESEL_UP_AUTO		(2 << 13)
-#define			AT91_TC_WAVESEL_UPDOWN		(1 << 13)
-#define			AT91_TC_WAVESEL_UPDOWN_AUTO	(3 << 13)
-#define		AT91_TC_ACPA		(3 << 16)	/* Waveform Mode: RA Compare Effect on TIOA */
-#define			AT91_TC_ACPA_NONE		(0 << 16)
-#define			AT91_TC_ACPA_SET		(1 << 16)
-#define			AT91_TC_ACPA_CLEAR		(2 << 16)
-#define			AT91_TC_ACPA_TOGGLE		(3 << 16)
-#define		AT91_TC_ACPC		(3 << 18)	/* Waveform Mode: RC Compre Effect on TIOA */
-#define			AT91_TC_ACPC_NONE		(0 << 18)
-#define			AT91_TC_ACPC_SET		(1 << 18)
-#define			AT91_TC_ACPC_CLEAR		(2 << 18)
-#define			AT91_TC_ACPC_TOGGLE		(3 << 18)
-#define		AT91_TC_AEEVT		(3 << 20)	/* Waveform Mode: External Event Effect on TIOA */
-#define			AT91_TC_AEEVT_NONE		(0 << 20)
-#define			AT91_TC_AEEVT_SET		(1 << 20)
-#define			AT91_TC_AEEVT_CLEAR		(2 << 20)
-#define			AT91_TC_AEEVT_TOGGLE		(3 << 20)
-#define		AT91_TC_ASWTRG		(3 << 22)	/* Waveform Mode: Software Trigger Effect on TIOA */
-#define			AT91_TC_ASWTRG_NONE		(0 << 22)
-#define			AT91_TC_ASWTRG_SET		(1 << 22)
-#define			AT91_TC_ASWTRG_CLEAR		(2 << 22)
-#define			AT91_TC_ASWTRG_TOGGLE		(3 << 22)
-#define		AT91_TC_BCPB		(3 << 24)	/* Waveform Mode: RB Compare Effect on TIOB */
-#define			AT91_TC_BCPB_NONE		(0 << 24)
-#define			AT91_TC_BCPB_SET		(1 << 24)
-#define			AT91_TC_BCPB_CLEAR		(2 << 24)
-#define			AT91_TC_BCPB_TOGGLE		(3 << 24)
-#define		AT91_TC_BCPC		(3 << 26)	/* Waveform Mode: RC Compare Effect on TIOB */
-#define			AT91_TC_BCPC_NONE		(0 << 26)
-#define			AT91_TC_BCPC_SET		(1 << 26)
-#define			AT91_TC_BCPC_CLEAR		(2 << 26)
-#define			AT91_TC_BCPC_TOGGLE		(3 << 26)
-#define		AT91_TC_BEEVT		(3 << 28)	/* Waveform Mode: External Event Effect on TIOB */
-#define			AT91_TC_BEEVT_NONE		(0 << 28)
-#define			AT91_TC_BEEVT_SET		(1 << 28)
-#define			AT91_TC_BEEVT_CLEAR		(2 << 28)
-#define			AT91_TC_BEEVT_TOGGLE		(3 << 28)
-#define		AT91_TC_BSWTRG		(3 << 30)	/* Waveform Mode: Software Trigger Effect on TIOB */
-#define			AT91_TC_BSWTRG_NONE		(0 << 30)
-#define			AT91_TC_BSWTRG_SET		(1 << 30)
-#define			AT91_TC_BSWTRG_CLEAR		(2 << 30)
-#define			AT91_TC_BSWTRG_TOGGLE		(3 << 30)
-
-#define AT91_TC_CV		0x10		/* Counter Value */
-#define AT91_TC_RA		0x14		/* Register A */
-#define AT91_TC_RB		0x18		/* Register B */
-#define AT91_TC_RC		0x1c		/* Register C */
-
-#define AT91_TC_SR		0x20		/* Status Register */
-#define		AT91_TC_COVFS		(1 <<  0)	/* Counter Overflow Status */
-#define		AT91_TC_LOVRS		(1 <<  1)	/* Load Overrun Status */
-#define		AT91_TC_CPAS		(1 <<  2)	/* RA Compare Status */
-#define		AT91_TC_CPBS		(1 <<  3)	/* RB Compare Status */
-#define		AT91_TC_CPCS		(1 <<  4)	/* RC Compare Status */
-#define		AT91_TC_LDRAS		(1 <<  5)	/* RA Loading Status */
-#define		AT91_TC_LDRBS		(1 <<  6)	/* RB Loading Status */
-#define		AT91_TC_ETRGS		(1 <<  7)	/* External Trigger Status */
-#define		AT91_TC_CLKSTA		(1 << 16)	/* Clock Enabling Status */
-#define		AT91_TC_MTIOA		(1 << 17)	/* TIOA Mirror */
-#define		AT91_TC_MTIOB		(1 << 18)	/* TIOB Mirror */
-
-#define AT91_TC_IER		0x24		/* Interrupt Enable Register */
-#define AT91_TC_IDR		0x28		/* Interrupt Disable Register */
-#define AT91_TC_IMR		0x2c		/* Interrupt Mask Register */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91rm9200_emac.h b/arch/arm/mach-at91/include/mach/at91rm9200_emac.h
deleted file mode 100644
index b8260cd..0000000
--- a/arch/arm/mach-at91/include/mach/at91rm9200_emac.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91rm9200_emac.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Ethernet MAC registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91RM9200_EMAC_H
-#define AT91RM9200_EMAC_H
-
-#define	AT91_EMAC_CTL		0x00	/* Control Register */
-#define		AT91_EMAC_LB		(1 <<  0)	/* Loopback */
-#define		AT91_EMAC_LBL		(1 <<  1)	/* Loopback Local */
-#define		AT91_EMAC_RE		(1 <<  2)	/* Receive Enable */
-#define		AT91_EMAC_TE		(1 <<  3)	/* Transmit Enable */
-#define		AT91_EMAC_MPE		(1 <<  4)	/* Management Port Enable */
-#define		AT91_EMAC_CSR		(1 <<  5)	/* Clear Statistics Registers */
-#define		AT91_EMAC_INCSTAT	(1 <<  6)	/* Increment Statistics Registers */
-#define		AT91_EMAC_WES		(1 <<  7)	/* Write Enable for Statistics Registers */
-#define		AT91_EMAC_BP		(1 <<  8)	/* Back Pressure */
-
-#define	AT91_EMAC_CFG		0x04	/* Configuration Register */
-#define		AT91_EMAC_SPD		(1 <<  0)	/* Speed */
-#define		AT91_EMAC_FD		(1 <<  1)	/* Full Duplex */
-#define		AT91_EMAC_BR		(1 <<  2)	/* Bit Rate */
-#define		AT91_EMAC_CAF		(1 <<  4)	/* Copy All Frames */
-#define		AT91_EMAC_NBC		(1 <<  5)	/* No Broadcast */
-#define		AT91_EMAC_MTI		(1 <<  6)	/* Multicast Hash Enable */
-#define		AT91_EMAC_UNI		(1 <<  7)	/* Unicast Hash Enable */
-#define		AT91_EMAC_BIG		(1 <<  8)	/* Receive 1522 Bytes */
-#define		AT91_EMAC_EAE		(1 <<  9)	/* External Address Match Enable */
-#define		AT91_EMAC_CLK		(3 << 10)	/* MDC Clock Divisor */
-#define		AT91_EMAC_CLK_DIV8		(0 << 10)
-#define		AT91_EMAC_CLK_DIV16		(1 << 10)
-#define		AT91_EMAC_CLK_DIV32		(2 << 10)
-#define		AT91_EMAC_CLK_DIV64		(3 << 10)
-#define		AT91_EMAC_RTY		(1 << 12)	/* Retry Test */
-#define		AT91_EMAC_RMII		(1 << 13)	/* Reduce MII (RMII) */
-
-#define	AT91_EMAC_SR		0x08	/* Status Register */
-#define		AT91_EMAC_SR_LINK	(1 <<  0)	/* Link */
-#define		AT91_EMAC_SR_MDIO	(1 <<  1)	/* MDIO pin */
-#define		AT91_EMAC_SR_IDLE	(1 <<  2)	/* PHY idle */
-
-#define	AT91_EMAC_TAR		0x0c	/* Transmit Address Register */
-
-#define	AT91_EMAC_TCR		0x10	/* Transmit Control Register */
-#define		AT91_EMAC_LEN		(0x7ff << 0)	/* Transmit Frame Length */
-#define		AT91_EMAC_NCRC		(1     << 15)	/* No CRC */
-
-#define	AT91_EMAC_TSR		0x14	/* Transmit Status Register */
-#define		AT91_EMAC_TSR_OVR	(1 <<  0)	/* Transmit Buffer Overrun */
-#define		AT91_EMAC_TSR_COL	(1 <<  1)	/* Collision Occurred */
-#define		AT91_EMAC_TSR_RLE	(1 <<  2)	/* Retry Limit Exceeded */
-#define		AT91_EMAC_TSR_IDLE	(1 <<  3)	/* Transmitter Idle */
-#define		AT91_EMAC_TSR_BNQ	(1 <<  4)	/* Transmit Buffer not Queued */
-#define		AT91_EMAC_TSR_COMP	(1 <<  5)	/* Transmit Complete */
-#define		AT91_EMAC_TSR_UND	(1 <<  6)	/* Transmit Underrun */
-
-#define	AT91_EMAC_RBQP		0x18	/* Receive Buffer Queue Pointer */
-
-#define	AT91_EMAC_RSR		0x20	/* Receive Status Register */
-#define		AT91_EMAC_RSR_BNA	(1 <<  0)	/* Buffer Not Available */
-#define		AT91_EMAC_RSR_REC	(1 <<  1)	/* Frame Received */
-#define		AT91_EMAC_RSR_OVR	(1 <<  2)	/* RX Overrun */
-
-#define	AT91_EMAC_ISR		0x24	/* Interrupt Status Register */
-#define		AT91_EMAC_DONE		(1 <<  0)	/* Management Done */
-#define		AT91_EMAC_RCOM		(1 <<  1)	/* Receive Complete */
-#define		AT91_EMAC_RBNA		(1 <<  2)	/* Receive Buffer Not Available */
-#define		AT91_EMAC_TOVR		(1 <<  3)	/* Transmit Buffer Overrun */
-#define		AT91_EMAC_TUND		(1 <<  4)	/* Transmit Buffer Underrun */
-#define		AT91_EMAC_RTRY		(1 <<  5)	/* Retry Limit */
-#define		AT91_EMAC_TBRE		(1 <<  6)	/* Transmit Buffer Register Empty */
-#define		AT91_EMAC_TCOM		(1 <<  7)	/* Transmit Complete */
-#define		AT91_EMAC_TIDLE		(1 <<  8)	/* Transmit Idle */
-#define		AT91_EMAC_LINK		(1 <<  9)	/* Link */
-#define		AT91_EMAC_ROVR		(1 << 10)	/* RX Overrun */
-#define		AT91_EMAC_ABT		(1 << 11)	/* Abort */
-
-#define	AT91_EMAC_IER		0x28	/* Interrupt Enable Register */
-#define	AT91_EMAC_IDR		0x2c	/* Interrupt Disable Register */
-#define	AT91_EMAC_IMR		0x30	/* Interrupt Mask Register */
-
-#define	AT91_EMAC_MAN		0x34	/* PHY Maintenance Register */
-#define		AT91_EMAC_DATA		(0xffff << 0)	/* MDIO Data */
-#define		AT91_EMAC_REGA		(0x1f	<< 18)	/* MDIO Register */
-#define		AT91_EMAC_PHYA		(0x1f	<< 23)	/* MDIO PHY Address */
-#define		AT91_EMAC_RW		(3	<< 28)	/* Read/Write operation */
-#define			AT91_EMAC_RW_W		(1 << 28)
-#define			AT91_EMAC_RW_R		(2 << 28)
-#define		AT91_EMAC_MAN_802_3	0x40020000	/* IEEE 802.3 value */
-
-/*
- * Statistics Registers.
- */
-#define AT91_EMAC_FRA		0x40	/* Frames Transmitted OK */
-#define AT91_EMAC_SCOL		0x44	/* Single Collision Frame */
-#define AT91_EMAC_MCOL		0x48	/* Multiple Collision Frame */
-#define AT91_EMAC_OK		0x4c	/* Frames Received OK */
-#define AT91_EMAC_SEQE		0x50	/* Frame Check Sequence Error */
-#define AT91_EMAC_ALE		0x54	/* Alignmemt Error */
-#define AT91_EMAC_DTE		0x58	/* Deffered Transmission Frame */
-#define AT91_EMAC_LCOL		0x5c	/* Late Collision */
-#define AT91_EMAC_ECOL		0x60	/* Excessive Collision */
-#define AT91_EMAC_TUE		0x64	/* Transmit Underrun Error */
-#define AT91_EMAC_CSE		0x68	/* Carrier Sense Error */
-#define AT91_EMAC_DRFC		0x6c	/* Discard RX Frame */
-#define AT91_EMAC_ROV		0x70	/* Receive Overrun */
-#define AT91_EMAC_CDE		0x74	/* Code Error */
-#define AT91_EMAC_ELR		0x78	/* Excessive Length Error */
-#define AT91_EMAC_RJB		0x7c	/* Receive Jabber */
-#define AT91_EMAC_USF		0x80	/* Undersize Frame */
-#define AT91_EMAC_SQEE		0x84	/* SQE Test Error */
-
-/*
- * Address Registers.
- */
-#define AT91_EMAC_HSL		0x90	/* Hash Address Low [31:0] */
-#define AT91_EMAC_HSH		0x94	/* Hash Address High [63:32] */
-#define AT91_EMAC_SA1L		0x98	/* Specific Address 1 Low, bytes 0-3 */
-#define AT91_EMAC_SA1H		0x9c	/* Specific Address 1 High, bytes 4-5 */
-#define AT91_EMAC_SA2L		0xa0	/* Specific Address 2 Low, bytes 0-3 */
-#define AT91_EMAC_SA2H		0xa4	/* Specific Address 2 High, bytes 4-5 */
-#define AT91_EMAC_SA3L		0xa8	/* Specific Address 3 Low, bytes 0-3 */
-#define AT91_EMAC_SA3H		0xac	/* Specific Address 3 High, bytes 4-5 */
-#define AT91_EMAC_SA4L		0xb0	/* Specific Address 4 Low, bytes 0-3 */
-#define AT91_EMAC_SA4H		0xb4	/* Specific Address 4 High, bytes 4-5 */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/atmel-mci.h b/arch/arm/mach-at91/include/mach/atmel-mci.h
index cd580a1..3069e41 100644
--- a/arch/arm/mach-at91/include/mach/atmel-mci.h
+++ b/arch/arm/mach-at91/include/mach/atmel-mci.h
@@ -14,11 +14,4 @@ struct mci_dma_data {
 #define	slave_data_ptr(s)	(&(s)->sdata)
 #define find_slave_dev(s)	((s)->sdata.dma_dev)
 
-#define	setup_dma_addr(s, t, r)	do {		\
-	if (s) {				\
-		(s)->sdata.tx_reg = (t);	\
-		(s)->sdata.rx_reg = (r);	\
-	}					\
-} while (0)
-
 #endif /* __MACH_ATMEL_MCI_H */
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
deleted file mode 100644
index c55a436..0000000
--- a/arch/arm/mach-at91/include/mach/board.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/board.h
- *
- *  Copyright (C) 2005 HP Labs
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- * These are data structures found in platform_device.dev.platform_data,
- * and describing board-specific data needed by drivers.  For example,
- * which pin is used for a given GPIO role.
- *
- * In 2.6, drivers should strongly avoid board-specific knowledge so
- * that supporting new boards normally won't require driver patches.
- * Most board-specific knowledge should be in arch/.../board-*.c files.
- */
-
-#ifndef __ASM_ARCH_BOARD_H
-#define __ASM_ARCH_BOARD_H
-
-#include <linux/mtd/partitions.h>
-#include <linux/device.h>
-#include <linux/i2c.h>
-#include <linux/leds.h>
-#include <linux/spi/spi.h>
-#include <linux/usb/atmel_usba_udc.h>
-#include <linux/atmel-mci.h>
-#include <sound/atmel-ac97c.h>
-#include <linux/serial.h>
-#include <linux/platform_data/macb.h>
-#include <linux/platform_data/atmel.h>
-
- /* USB Device */
-struct at91_udc_data {
-	int	vbus_pin;		/* high == host powering us */
-	u8	vbus_active_low;	/* vbus polarity */
-	u8	vbus_polled;		/* Use polling, not interrupt */
-	int	pullup_pin;		/* active == D+ pulled up */
-	u8	pullup_active_low;	/* true == pullup_pin is active low */
-};
-extern void __init at91_add_device_udc(struct at91_udc_data *data);
-
- /* USB High Speed Device */
-extern void __init at91_add_device_usba(struct usba_platform_data *data);
-
- /* Compact Flash */
-struct at91_cf_data {
-	int	irq_pin;		/* I/O IRQ */
-	int	det_pin;		/* Card detect */
-	int	vcc_pin;		/* power switching */
-	int	rst_pin;		/* card reset */
-	u8	chipselect;		/* EBI Chip Select number */
-	u8	flags;
-#define AT91_CF_TRUE_IDE	0x01
-#define AT91_IDE_SWAP_A0_A2	0x02
-};
-extern void __init at91_add_device_cf(struct at91_cf_data *data);
-
- /* MMC / SD */
-  /* at91_mci platform config */
-struct at91_mmc_data {
-	int		det_pin;	/* card detect IRQ */
-	unsigned	slot_b:1;	/* uses Slot B */
-	unsigned	wire4:1;	/* (SD) supports DAT0..DAT3 */
-	int		wp_pin;		/* (SD) writeprotect detect */
-	int		vcc_pin;	/* power switching (high == on) */
-};
-extern void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data);
-
-  /* atmel-mci platform config */
-extern void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data);
-
-extern void __init at91_add_device_eth(struct macb_platform_data *data);
-
- /* USB Host */
-#define AT91_MAX_USBH_PORTS	3
-struct at91_usbh_data {
-	int		vbus_pin[AT91_MAX_USBH_PORTS];	/* port power-control pin */
-	int             overcurrent_pin[AT91_MAX_USBH_PORTS];
-	u8		ports;				/* number of ports on root hub */
-	u8              overcurrent_supported;
-	u8              vbus_pin_active_low[AT91_MAX_USBH_PORTS];
-	u8              overcurrent_status[AT91_MAX_USBH_PORTS];
-	u8              overcurrent_changed[AT91_MAX_USBH_PORTS];
-};
-extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
-extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data);
-extern void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data);
-
-extern void __init at91_add_device_nand(struct atmel_nand_data *data);
-
- /* I2C*/
-#if defined(CONFIG_ARCH_AT91SAM9G45)
-extern void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices);
-#else
-extern void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices);
-#endif
-
- /* SPI */
-extern void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices);
-
- /* Serial */
-#define ATMEL_UART_CTS	0x01
-#define ATMEL_UART_RTS	0x02
-#define ATMEL_UART_DSR	0x04
-#define ATMEL_UART_DTR	0x08
-#define ATMEL_UART_DCD	0x10
-#define ATMEL_UART_RI	0x20
-
-extern void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins);
-
-extern struct platform_device *atmel_default_console_device;
-
-struct atmel_uart_data {
-	int			num;		/* port num */
-	short			use_dma_tx;	/* use transmit DMA? */
-	short			use_dma_rx;	/* use receive DMA? */
-	void __iomem		*regs;		/* virt. base address, if any */
-	struct serial_rs485	rs485;		/* rs485 settings */
-};
-extern void __init at91_add_device_serial(void);
-
-/*
- * PWM
- */
-#define AT91_PWM0	0
-#define AT91_PWM1	1
-#define AT91_PWM2	2
-#define AT91_PWM3	3
-
-extern void __init at91_add_device_pwm(u32 mask);
-
-/*
- * SSC -- accessed through ssc_request(id).  Drivers don't bind to SSC
- * platform devices.  Their SSC ID is part of their configuration data,
- * along with information about which SSC signals they should use.
- */
-#define ATMEL_SSC_TK	0x01
-#define ATMEL_SSC_TF	0x02
-#define ATMEL_SSC_TD	0x04
-#define ATMEL_SSC_TX	(ATMEL_SSC_TK | ATMEL_SSC_TF | ATMEL_SSC_TD)
-
-#define ATMEL_SSC_RK	0x10
-#define ATMEL_SSC_RF	0x20
-#define ATMEL_SSC_RD	0x40
-#define ATMEL_SSC_RX	(ATMEL_SSC_RK | ATMEL_SSC_RF | ATMEL_SSC_RD)
-
-extern void __init at91_add_device_ssc(unsigned id, unsigned pins);
-
- /* LCD Controller */
-struct atmel_lcdfb_info;
-extern void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data);
-
- /* AC97 */
-extern void __init at91_add_device_ac97(struct ac97c_platform_data *data);
-
- /* ISI */
-struct isi_platform_data;
-extern void __init at91_add_device_isi(struct isi_platform_data *data,
-		bool use_pck_as_mck);
-
- /* Touchscreen Controller */
-struct at91_tsadcc_data {
-	unsigned int    adc_clock;
-	u8		pendet_debounce;
-	u8		ts_sample_hold_time;
-};
-extern void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data);
-
-/* CAN */
-struct at91_can_data {
-	void (*transceiver_switch)(int on);
-};
-extern void __init at91_add_device_can(struct at91_can_data *data);
-
- /* LEDs */
-extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);
-extern void __init at91_pwm_leds(struct gpio_led *leds, int nr);
-
-/* FIXME: this needs a better location, but gets stuff building again */
-extern int at91_suspend_entering_slow_clock(void);
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/gsia18s.h b/arch/arm/mach-at91/include/mach/gsia18s.h
deleted file mode 100644
index 307c194..0000000
--- a/arch/arm/mach-at91/include/mach/gsia18s.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Buttons */
-#define GPIO_TRIG_NET_IN		AT91_PIN_PB21
-#define GPIO_CARD_UNMOUNT_0		AT91_PIN_PB13
-#define GPIO_CARD_UNMOUNT_1		AT91_PIN_PB12
-#define GPIO_KEY_POWER			AT91_PIN_PA25
-
-/* PCF8574 0x20 GPIO - U1 on the GS_IA18-CB_V3 board */
-#define GS_IA18_S_PCF_GPIO_BASE0	NR_BUILTIN_GPIO
-#define PCF_GPIO_HDC_POWER		(GS_IA18_S_PCF_GPIO_BASE0 + 0)
-#define PCF_GPIO_WIFI_SETUP		(GS_IA18_S_PCF_GPIO_BASE0 + 1)
-#define PCF_GPIO_WIFI_ENABLE		(GS_IA18_S_PCF_GPIO_BASE0 + 2)
-#define PCF_GPIO_WIFI_RESET		(GS_IA18_S_PCF_GPIO_BASE0 + 3)
-#define PCF_GPIO_ETH_DETECT		4 /* this is a GPI */
-#define PCF_GPIO_GPS_SETUP		(GS_IA18_S_PCF_GPIO_BASE0 + 5)
-#define PCF_GPIO_GPS_STANDBY		(GS_IA18_S_PCF_GPIO_BASE0 + 6)
-#define PCF_GPIO_GPS_POWER		(GS_IA18_S_PCF_GPIO_BASE0 + 7)
-
-/* PCF8574 0x22 GPIO - U1 on the GS_2G_OPT1-A_V0 board (Alarm) */
-#define GS_IA18_S_PCF_GPIO_BASE1	(GS_IA18_S_PCF_GPIO_BASE0 + 8)
-#define PCF_GPIO_ALARM1			(GS_IA18_S_PCF_GPIO_BASE1 + 0)
-#define PCF_GPIO_ALARM2			(GS_IA18_S_PCF_GPIO_BASE1 + 1)
-#define PCF_GPIO_ALARM3			(GS_IA18_S_PCF_GPIO_BASE1 + 2)
-#define PCF_GPIO_ALARM4			(GS_IA18_S_PCF_GPIO_BASE1 + 3)
-/* bits 4, 5, 6 not used */
-#define PCF_GPIO_ALARM_V_RELAY_ON	(GS_IA18_S_PCF_GPIO_BASE1 + 7)
-
-/* PCF8574 0x24 GPIO U1 on the GS_2G-OPT23-A_V0 board (Modem) */
-#define GS_IA18_S_PCF_GPIO_BASE2	(GS_IA18_S_PCF_GPIO_BASE1 + 8)
-#define PCF_GPIO_MODEM_POWER		(GS_IA18_S_PCF_GPIO_BASE2 + 0)
-#define PCF_GPIO_MODEM_RESET		(GS_IA18_S_PCF_GPIO_BASE2 + 3)
-/* bits 1, 2, 4, 5 not used */
-#define PCF_GPIO_TRX_RESET		(GS_IA18_S_PCF_GPIO_BASE2 + 6)
-/* bit 7 not used */
diff --git a/arch/arm/mach-at91/include/mach/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h
index 711a789..a832e07 100644
--- a/arch/arm/mach-at91/include/mach/hardware.h
+++ b/arch/arm/mach-at91/include/mach/hardware.h
@@ -90,9 +90,6 @@
 #define AT91_SRAM_MAX		SZ_1M
 #define AT91_VIRT_BASE		(AT91_IO_VIRT_BASE - AT91_SRAM_MAX)
 
-/* Serial ports */
-#define ATMEL_MAX_UART		7		/* 6 USART3's and one DBGU port (SAM9260) */
-
 /* External Memory Map */
 #define AT91_CHIPSELECT_0	0x10000000
 #define AT91_CHIPSELECT_1	0x20000000
diff --git a/arch/arm/mach-at91/include/mach/stamp9g20.h b/arch/arm/mach-at91/include/mach/stamp9g20.h
deleted file mode 100644
index f62c0ab..0000000
--- a/arch/arm/mach-at91/include/mach/stamp9g20.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __MACH_STAMP9G20_H
-#define __MACH_STAMP9G20_H
-
-void stamp9g20_init_early(void);
-void stamp9g20_board_init(void);
-
-#endif
diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
index febc2ee..8e21026 100644
--- a/arch/arm/mach-at91/irq.c
+++ b/arch/arm/mach-at91/irq.c
@@ -42,7 +42,7 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/map.h>
 
-#include <mach/at91_aic.h>
+#include "at91_aic.h"
 
 void __iomem *at91_aic_base;
 static struct irq_domain *at91_aic_domain;
diff --git a/arch/arm/mach-at91/leds.c b/arch/arm/mach-at91/leds.c
index 1b1e62b..3e22978 100644
--- a/arch/arm/mach-at91/leds.c
+++ b/arch/arm/mach-at91/leds.c
@@ -15,7 +15,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
-#include <mach/board.h>
+#include "board.h"
 
 
 /* ------------------------------------------------------------------------- */
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 5315f05..adb6db8 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -25,10 +25,10 @@
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 
-#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/cpu.h>
 
+#include "at91_aic.h"
 #include "generic.h"
 #include "pm.h"
 
@@ -36,8 +36,8 @@
  * Show the reason for the previous system reset.
  */
 
-#include <mach/at91_rstc.h>
-#include <mach/at91_shdwc.h>
+#include "at91_rstc.h"
+#include "at91_shdwc.h"
 
 static void __init show_reset_status(void)
 {
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 0b32c81..9ee866c 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <linux/pm.h>
 #include <linux/of_address.h>
+#include <linux/pinctrl/machine.h>
 
 #include <asm/system_misc.h>
 #include <asm/mach/map.h>
@@ -18,8 +19,8 @@
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
 #include <mach/at91_pmc.h>
-#include <mach/at91_shdwc.h>
 
+#include "at91_shdwc.h"
 #include "soc.h"
 #include "generic.h"
 
@@ -338,6 +339,7 @@ static void at91_dt_rstc(void)
 }
 
 static struct of_device_id ramc_ids[] = {
+	{ .compatible = "atmel,at91rm9200-sdramc" },
 	{ .compatible = "atmel,at91sam9260-sdramc" },
 	{ .compatible = "atmel,at91sam9g45-ddramc" },
 	{ /*sentinel*/ }
@@ -436,6 +438,19 @@ end:
 	of_node_put(np);
 }
 
+void __init at91rm9200_dt_initialize(void)
+{
+	at91_dt_ramc();
+
+	/* Init clock subsystem */
+	at91_dt_clock_init();
+
+	/* Register the processor-specific clocks */
+	at91_boot_soc.register_clocks();
+
+	at91_boot_soc.init();
+}
+
 void __init at91_dt_initialize(void)
 {
 	at91_dt_rstc();
@@ -448,7 +463,8 @@ void __init at91_dt_initialize(void)
 	/* Register the processor-specific clocks */
 	at91_boot_soc.register_clocks();
 
-	at91_boot_soc.init();
+	if (at91_boot_soc.init)
+		at91_boot_soc.init();
 }
 #endif
 
@@ -463,4 +479,6 @@ void __init at91_initialize(unsigned long main_clock)
 	at91_boot_soc.register_clocks();
 
 	at91_boot_soc.init();
+
+	pinctrl_provide_dummies();
 }
diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h
index a9cfeb1..9c6d3d4 100644
--- a/arch/arm/mach-at91/soc.h
+++ b/arch/arm/mach-at91/soc.h
@@ -5,6 +5,7 @@
  */
 
 struct at91_init_soc {
+	int builtin;
 	unsigned int *default_irq_priority;
 	void (*map_io)(void);
 	void (*ioremap_registers)(void);
@@ -22,9 +23,18 @@ extern struct at91_init_soc at91sam9rl_soc;
 extern struct at91_init_soc at91sam9x5_soc;
 extern struct at91_init_soc at91sam9n12_soc;
 
+#define AT91_SOC_START(_name)				\
+struct at91_init_soc __initdata at91##_name##_soc	\
+ __used							\
+						= {	\
+	.builtin	= 1,				\
+
+#define AT91_SOC_END					\
+};
+
 static inline int at91_soc_is_enabled(void)
 {
-	return at91_boot_soc.init != NULL;
+	return at91_boot_soc.builtin;
 }
 
 #if !defined(CONFIG_SOC_AT91RM9200)
diff --git a/arch/arm/mach-at91/stamp9g20.h b/arch/arm/mach-at91/stamp9g20.h
new file mode 100644
index 0000000..f62c0ab
--- /dev/null
+++ b/arch/arm/mach-at91/stamp9g20.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_STAMP9G20_H
+#define __MACH_STAMP9G20_H
+
+void stamp9g20_init_early(void);
+void stamp9g20_board_init(void);
+
+#endif
diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
new file mode 100644
index 0000000..48705c1
--- /dev/null
+++ b/arch/arm/mach-bcm/Kconfig
@@ -0,0 +1,19 @@
+config ARCH_BCM
+	bool "Broadcom SoC" if ARCH_MULTI_V7
+	depends on MMU
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_ERRATA_754322
+	select ARM_ERRATA_764369 if SMP
+	select ARM_GIC
+	select CPU_V7
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_GPIO
+	select GENERIC_TIME
+	select GPIO_BCM
+	select SPARSE_IRQ
+	select TICK_ONESHOT
+	help
+	  This enables support for system based on Broadcom SoCs.
+	  It currently supports the 'BCM281XX' family, which includes
+	  BCM11130, BCM11140, BCM11351, BCM28145 and
+	  BCM28155 variants.
diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile
new file mode 100644
index 0000000..bbf4122
--- /dev/null
+++ b/arch/arm/mach-bcm/Makefile
@@ -0,0 +1,13 @@
+#
+# Copyright (C) 2012 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.
+
+obj-$(CONFIG_ARCH_BCM) := board_bcm.o
diff --git a/arch/arm/mach-bcm/board_bcm.c b/arch/arm/mach-bcm/board_bcm.c
new file mode 100644
index 0000000..3a62f1b
--- /dev/null
+++ b/arch/arm/mach-bcm/board_bcm.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 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/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/hardware/gic.h>
+
+#include <asm/mach/time.h>
+
+static const struct of_device_id irq_match[] = {
+	{.compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+	{}
+};
+
+static void timer_init(void)
+{
+}
+
+static struct sys_timer timer = {
+	.init = timer_init,
+};
+
+static void __init init_irq(void)
+{
+	of_irq_init(irq_match);
+}
+
+static void __init board_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL,
+		&platform_bus);
+}
+
+static const char * const bcm11351_dt_compat[] = { "bcm,bcm11351", NULL, };
+
+DT_MACHINE_START(BCM11351_DT, "Broadcom Application Processor")
+	.init_irq = init_irq,
+	.timer = &timer,
+	.init_machine = board_init,
+	.dt_compat = bcm11351_dt_compat,
+	.handle_irq = gic_handle_irq,
+MACHINE_END
diff --git a/arch/arm/mach-bcm2835/Makefile.boot b/arch/arm/mach-bcm2835/Makefile.boot
index 2d30e17..b327175 100644
--- a/arch/arm/mach-bcm2835/Makefile.boot
+++ b/arch/arm/mach-bcm2835/Makefile.boot
@@ -1,3 +1 @@
-   zreladdr-y := 0x00008000
-params_phys-y := 0x00000100
-initrd_phys-y := 0x00800000
+zreladdr-y := 0x00008000
diff --git a/arch/arm/mach-bcm2835/bcm2835.c b/arch/arm/mach-bcm2835/bcm2835.c
index f6fea49..f0d739f 100644
--- a/arch/arm/mach-bcm2835/bcm2835.c
+++ b/arch/arm/mach-bcm2835/bcm2835.c
@@ -12,8 +12,10 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/irqchip/bcm2835.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/bcm2835_timer.h>
 #include <linux/clk/bcm2835.h>
@@ -23,6 +25,48 @@
 
 #include <mach/bcm2835_soc.h>
 
+#define PM_RSTC				0x1c
+#define PM_WDOG				0x24
+
+#define PM_PASSWORD			0x5a000000
+#define PM_RSTC_WRCFG_MASK		0x00000030
+#define PM_RSTC_WRCFG_FULL_RESET	0x00000020
+
+static void __iomem *wdt_regs;
+
+/*
+ * The machine restart method can be called from an atomic context so we won't
+ * be able to ioremap the regs then.
+ */
+static void bcm2835_setup_restart(void)
+{
+	struct device_node *np = of_find_compatible_node(NULL, NULL,
+						"brcm,bcm2835-pm-wdt");
+	if (WARN(!np, "unable to setup watchdog restart"))
+		return;
+
+	wdt_regs = of_iomap(np, 0);
+	WARN(!wdt_regs, "failed to remap watchdog regs");
+}
+
+static void bcm2835_restart(char mode, const char *cmd)
+{
+	u32 val;
+
+	if (!wdt_regs)
+		return;
+
+	/* use a timeout of 10 ticks (~150us) */
+	writel_relaxed(10 | PM_PASSWORD, wdt_regs + PM_WDOG);
+	val = readl_relaxed(wdt_regs + PM_RSTC);
+	val &= ~PM_RSTC_WRCFG_MASK;
+	val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
+	writel_relaxed(val, wdt_regs + PM_RSTC);
+
+	/* No sleeping, possibly atomic. */
+	mdelay(1);
+}
+
 static struct map_desc io_map __initdata = {
 	.virtual = BCM2835_PERIPH_VIRT,
 	.pfn = __phys_to_pfn(BCM2835_PERIPH_PHYS),
@@ -30,15 +74,16 @@ static struct map_desc io_map __initdata = {
 	.type = MT_DEVICE
 };
 
-void __init bcm2835_map_io(void)
+static void __init bcm2835_map_io(void)
 {
 	iotable_init(&io_map, 1);
 }
 
-void __init bcm2835_init(void)
+static void __init bcm2835_init(void)
 {
 	int ret;
 
+	bcm2835_setup_restart();
 	bcm2835_init_clocks();
 
 	ret = of_platform_populate(NULL, of_default_bus_match_table, NULL,
@@ -60,5 +105,6 @@ DT_MACHINE_START(BCM2835, "BCM2835")
 	.handle_irq = bcm2835_handle_irq,
 	.init_machine = bcm2835_init,
 	.timer = &bcm2835_timer,
+	.restart = bcm2835_restart,
 	.dt_compat = bcm2835_compat
 MACHINE_END
diff --git a/arch/arm/mach-bcm2835/include/mach/gpio.h b/arch/arm/mach-bcm2835/include/mach/gpio.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/arch/arm/mach-bcm2835/include/mach/gpio.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-clps711x/Kconfig b/arch/arm/mach-clps711x/Kconfig
index 263242d..2d00165 100644
--- a/arch/arm/mach-clps711x/Kconfig
+++ b/arch/arm/mach-clps711x/Kconfig
@@ -10,7 +10,6 @@ config ARCH_AUTCPU12
 
 config ARCH_CDB89712
 	bool "CDB89712"
-	select ISA
 	help
 	  This is an evaluation board from Cirrus for the CS89712 processor.
 	  The board includes 2 serial ports, Ethernet, IRDA, and expansion
@@ -25,7 +24,6 @@ config ARCH_EDB7211
 	bool "EDB7211"
 	select ARCH_SELECT_MEMORY_MODEL
 	select ARCH_SPARSEMEM_ENABLE
-	select ISA
 	help
 	  Say Y here if you intend to run this kernel on a Cirrus Logic EDB-7211
 	  evaluation board.
diff --git a/arch/arm/mach-clps711x/Makefile b/arch/arm/mach-clps711x/Makefile
index 6da6940..992995a 100644
--- a/arch/arm/mach-clps711x/Makefile
+++ b/arch/arm/mach-clps711x/Makefile
@@ -9,9 +9,9 @@ obj-m			:=
 obj-n			:=
 obj-			:=
 
-obj-$(CONFIG_ARCH_AUTCPU12) += autcpu12.o
-obj-$(CONFIG_ARCH_CDB89712) += cdb89712.o
-obj-$(CONFIG_ARCH_CLEP7312) += clep7312.o
-obj-$(CONFIG_ARCH_EDB7211)  += edb7211-arch.o edb7211-mm.o
-obj-$(CONFIG_ARCH_FORTUNET) += fortunet.o
-obj-$(CONFIG_ARCH_P720T)    += p720t.o
+obj-$(CONFIG_ARCH_AUTCPU12)	+= board-autcpu12.o
+obj-$(CONFIG_ARCH_CDB89712)	+= board-cdb89712.o
+obj-$(CONFIG_ARCH_CLEP7312)	+= board-clep7312.o
+obj-$(CONFIG_ARCH_EDB7211)	+= board-edb7211.o
+obj-$(CONFIG_ARCH_FORTUNET)	+= board-fortunet.o
+obj-$(CONFIG_ARCH_P720T)	+= board-p720t.o
diff --git a/arch/arm/mach-clps711x/Makefile.boot b/arch/arm/mach-clps711x/Makefile.boot
index 9398e85..eba77d3 100644
--- a/arch/arm/mach-clps711x/Makefile.boot
+++ b/arch/arm/mach-clps711x/Makefile.boot
@@ -1,5 +1,4 @@
 # The standard locations for stuff on CLPS711x type processors
-   zreladdr-y				+= 0xc0028000
 params_phys-y				:= 0xc0000100
 # Should probably have some agreement on these...
 initrd_phys-$(CONFIG_ARCH_P720T)	:= 0xc0400000
diff --git a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c
deleted file mode 100644
index 3287191..0000000
--- a/arch/arm/mach-clps711x/autcpu12.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- *  linux/arch/arm/mach-clps711x/autcpu12.c
- *
- * (c) 2001 Thomas Gleixner, autronix automation <gleixner@autronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-
-#include <mach/hardware.h>
-#include <asm/sizes.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-#include <asm/mach/map.h>
-#include <mach/autcpu12.h>
-
-#include "common.h"
-
-/*
- * The on-chip registers are given a size of 1MB so that a section can
- * be used to map them; this saves a page table.  This is the place to
- * add mappings for ROM, expansion memory, PCMCIA, etc.  (if static
- * mappings are chosen for those areas).
- *
-*/
-
-static struct map_desc autcpu12_io_desc[] __initdata = {
-	/* memory-mapped extra io and CS8900A Ethernet chip */
- 	/* ethernet chip */
- 	{
-		.virtual	= AUTCPU12_VIRT_CS8900A,
-		.pfn		= __phys_to_pfn(AUTCPU12_PHYS_CS8900A),
-		.length		= SZ_1M,
-		.type		= MT_DEVICE
-	}
-};
-
-void __init autcpu12_map_io(void)
-{
-        clps711x_map_io();
-        iotable_init(autcpu12_io_desc, ARRAY_SIZE(autcpu12_io_desc));
-}
-
-static struct resource autcpu12_nvram_resource[] __initdata = {
-	DEFINE_RES_MEM_NAMED(AUTCPU12_PHYS_NVRAM, SZ_128K, "SRAM"),
-};
-
-static struct platform_device autcpu12_nvram_pdev __initdata = {
-	.name		= "autcpu12_nvram",
-	.id		= -1,
-	.resource	= autcpu12_nvram_resource,
-	.num_resources	= ARRAY_SIZE(autcpu12_nvram_resource),
-};
-
-static void __init autcpu12_init(void)
-{
-	platform_device_register(&autcpu12_nvram_pdev);
-}
-
-MACHINE_START(AUTCPU12, "autronix autcpu12")
-	/* Maintainer: Thomas Gleixner */
-	.atag_offset	= 0x20000,
-	.init_machine	= autcpu12_init,
-	.map_io		= autcpu12_map_io,
-	.init_irq	= clps711x_init_irq,
-	.timer		= &clps711x_timer,
-	.restart	= clps711x_restart,
-MACHINE_END
-
diff --git a/arch/arm/mach-clps711x/board-autcpu12.c b/arch/arm/mach-clps711x/board-autcpu12.c
new file mode 100644
index 0000000..3fbf43f
--- /dev/null
+++ b/arch/arm/mach-clps711x/board-autcpu12.c
@@ -0,0 +1,179 @@
+/*
+ *  linux/arch/arm/mach-clps711x/autcpu12.c
+ *
+ * (c) 2001 Thomas Gleixner, autronix automation <gleixner@autronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand-gpio.h>
+#include <linux/platform_device.h>
+#include <linux/basic_mmio_gpio.h>
+
+#include <mach/hardware.h>
+#include <asm/sizes.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+#include <mach/autcpu12.h>
+
+#include "common.h"
+
+#define AUTCPU12_CS8900_BASE	(CS2_PHYS_BASE + 0x300)
+#define AUTCPU12_CS8900_IRQ	(IRQ_EINT3)
+
+#define AUTCPU12_SMC_BASE	(CS1_PHYS_BASE + 0x06000000)
+#define AUTCPU12_SMC_SEL_BASE	(AUTCPU12_SMC_BASE + 0x10)
+
+#define AUTCPU12_MMGPIO_BASE	(CLPS711X_NR_GPIO)
+#define AUTCPU12_SMC_NCE	(AUTCPU12_MMGPIO_BASE + 0) /* Bit 0 */
+#define AUTCPU12_SMC_RDY	CLPS711X_GPIO(1, 2)
+#define AUTCPU12_SMC_ALE	CLPS711X_GPIO(1, 3)
+#define AUTCPU12_SMC_CLE	CLPS711X_GPIO(1, 3)
+
+static struct resource autcpu12_cs8900_resource[] __initdata = {
+	DEFINE_RES_MEM(AUTCPU12_CS8900_BASE, SZ_1K),
+	DEFINE_RES_IRQ(AUTCPU12_CS8900_IRQ),
+};
+
+static struct resource autcpu12_nvram_resource[] __initdata = {
+	DEFINE_RES_MEM_NAMED(AUTCPU12_PHYS_NVRAM, SZ_128K, "SRAM"),
+};
+
+static struct platform_device autcpu12_nvram_pdev __initdata = {
+	.name		= "autcpu12_nvram",
+	.id		= -1,
+	.resource	= autcpu12_nvram_resource,
+	.num_resources	= ARRAY_SIZE(autcpu12_nvram_resource),
+};
+
+static struct resource autcpu12_nand_resource[] __initdata = {
+	DEFINE_RES_MEM(AUTCPU12_SMC_BASE, SZ_16),
+};
+
+static struct mtd_partition autcpu12_nand_parts[] __initdata = {
+	{
+		.name	= "Flash partition 1",
+		.offset	= 0,
+		.size	= SZ_8M,
+	},
+	{
+		.name	= "Flash partition 2",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static void __init autcpu12_adjust_parts(struct gpio_nand_platdata *pdata,
+					 size_t sz)
+{
+	switch (sz) {
+	case SZ_16M:
+	case SZ_32M:
+		break;
+	case SZ_64M:
+	case SZ_128M:
+		pdata->parts[0].size = SZ_16M;
+		break;
+	default:
+		pr_warn("Unsupported SmartMedia device size %u\n", sz);
+		break;
+	}
+}
+
+static struct gpio_nand_platdata autcpu12_nand_pdata __initdata = {
+	.gpio_rdy	= AUTCPU12_SMC_RDY,
+	.gpio_nce	= AUTCPU12_SMC_NCE,
+	.gpio_ale	= AUTCPU12_SMC_ALE,
+	.gpio_cle	= AUTCPU12_SMC_CLE,
+	.gpio_nwp	= -1,
+	.chip_delay	= 20,
+	.parts		= autcpu12_nand_parts,
+	.num_parts	= ARRAY_SIZE(autcpu12_nand_parts),
+	.adjust_parts	= autcpu12_adjust_parts,
+};
+
+static struct platform_device autcpu12_nand_pdev __initdata = {
+	.name		= "gpio-nand",
+	.id		= -1,
+	.resource	= autcpu12_nand_resource,
+	.num_resources	= ARRAY_SIZE(autcpu12_nand_resource),
+	.dev		= {
+		.platform_data = &autcpu12_nand_pdata,
+	},
+};
+
+static struct resource autcpu12_mmgpio_resource[] __initdata = {
+	DEFINE_RES_MEM_NAMED(AUTCPU12_SMC_SEL_BASE, SZ_1, "dat"),
+};
+
+static struct bgpio_pdata autcpu12_mmgpio_pdata __initdata = {
+	.base	= AUTCPU12_MMGPIO_BASE,
+	.ngpio	= 8,
+};
+
+static struct platform_device autcpu12_mmgpio_pdev __initdata = {
+	.name		= "basic-mmio-gpio",
+	.id		= -1,
+	.resource	= autcpu12_mmgpio_resource,
+	.num_resources	= ARRAY_SIZE(autcpu12_mmgpio_resource),
+	.dev		= {
+		.platform_data = &autcpu12_mmgpio_pdata,
+	},
+};
+
+static void __init autcpu12_init(void)
+{
+	platform_device_register_simple("video-clps711x", 0, NULL, 0);
+	platform_device_register_simple("cs89x0", 0, autcpu12_cs8900_resource,
+					ARRAY_SIZE(autcpu12_cs8900_resource));
+	platform_device_register(&autcpu12_mmgpio_pdev);
+	platform_device_register(&autcpu12_nvram_pdev);
+}
+
+static void __init autcpu12_init_late(void)
+{
+	if (IS_ENABLED(MTD_NAND_GPIO) && IS_ENABLED(GPIO_GENERIC_PLATFORM)) {
+		/* We are need both drivers to handle NAND */
+		platform_device_register(&autcpu12_nand_pdev);
+	}
+}
+
+MACHINE_START(AUTCPU12, "autronix autcpu12")
+	/* Maintainer: Thomas Gleixner */
+	.atag_offset	= 0x20000,
+	.nr_irqs	= CLPS711X_NR_IRQS,
+	.map_io		= clps711x_map_io,
+	.init_irq	= clps711x_init_irq,
+	.timer		= &clps711x_timer,
+	.init_machine	= autcpu12_init,
+	.init_late	= autcpu12_init_late,
+	.handle_irq	= clps711x_handle_irq,
+	.restart	= clps711x_restart,
+MACHINE_END
+
diff --git a/arch/arm/mach-clps711x/board-cdb89712.c b/arch/arm/mach-clps711x/board-cdb89712.c
new file mode 100644
index 0000000..60900dd
--- /dev/null
+++ b/arch/arm/mach-clps711x/board-cdb89712.c
@@ -0,0 +1,147 @@
+/*
+ *  linux/arch/arm/mach-clps711x/cdb89712.c
+ *
+ *  Copyright (C) 2000-2001 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/mtd/partitions.h>
+
+#include <mach/hardware.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include "common.h"
+
+#define CDB89712_CS8900_BASE	(CS2_PHYS_BASE + 0x300)
+#define CDB89712_CS8900_IRQ	(IRQ_EINT3)
+
+static struct resource cdb89712_cs8900_resource[] __initdata = {
+	DEFINE_RES_MEM(CDB89712_CS8900_BASE, SZ_1K),
+	DEFINE_RES_IRQ(CDB89712_CS8900_IRQ),
+};
+
+static struct mtd_partition cdb89712_flash_partitions[] __initdata = {
+	{
+		.name	= "Flash",
+		.offset	= 0,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct physmap_flash_data cdb89712_flash_pdata __initdata = {
+	.width		= 4,
+	.probe_type	= "map_rom",
+	.parts		= cdb89712_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(cdb89712_flash_partitions),
+};
+
+static struct resource cdb89712_flash_resources[] __initdata = {
+	DEFINE_RES_MEM(CS0_PHYS_BASE, SZ_8M),
+};
+
+static struct platform_device cdb89712_flash_pdev __initdata = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.resource	= cdb89712_flash_resources,
+	.num_resources	= ARRAY_SIZE(cdb89712_flash_resources),
+	.dev	= {
+		.platform_data	= &cdb89712_flash_pdata,
+	},
+};
+
+static struct mtd_partition cdb89712_bootrom_partitions[] __initdata = {
+	{
+		.name	= "BootROM",
+		.offset	= 0,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct physmap_flash_data cdb89712_bootrom_pdata __initdata = {
+	.width		= 4,
+	.probe_type	= "map_rom",
+	.parts		= cdb89712_bootrom_partitions,
+	.nr_parts	= ARRAY_SIZE(cdb89712_bootrom_partitions),
+};
+
+static struct resource cdb89712_bootrom_resources[] __initdata = {
+	DEFINE_RES_NAMED(CS7_PHYS_BASE, SZ_128, "BOOTROM", IORESOURCE_MEM |
+			 IORESOURCE_CACHEABLE | IORESOURCE_READONLY),
+};
+
+static struct platform_device cdb89712_bootrom_pdev __initdata = {
+	.name		= "physmap-flash",
+	.id		= 1,
+	.resource	= cdb89712_bootrom_resources,
+	.num_resources	= ARRAY_SIZE(cdb89712_bootrom_resources),
+	.dev	= {
+		.platform_data	= &cdb89712_bootrom_pdata,
+	},
+};
+
+static struct platdata_mtd_ram cdb89712_sram_pdata __initdata = {
+	.bankwidth	= 4,
+};
+
+static struct resource cdb89712_sram_resources[] __initdata = {
+	DEFINE_RES_MEM(CLPS711X_SRAM_BASE, CLPS711X_SRAM_SIZE),
+};
+
+static struct platform_device cdb89712_sram_pdev __initdata = {
+	.name		= "mtd-ram",
+	.id		= 0,
+	.resource	= cdb89712_sram_resources,
+	.num_resources	= ARRAY_SIZE(cdb89712_sram_resources),
+	.dev	= {
+		.platform_data	= &cdb89712_sram_pdata,
+	},
+};
+
+static void __init cdb89712_init(void)
+{
+	platform_device_register(&cdb89712_flash_pdev);
+	platform_device_register(&cdb89712_bootrom_pdev);
+	platform_device_register(&cdb89712_sram_pdev);
+	platform_device_register_simple("cs89x0", 0, cdb89712_cs8900_resource,
+					ARRAY_SIZE(cdb89712_cs8900_resource));
+}
+
+MACHINE_START(CDB89712, "Cirrus-CDB89712")
+	/* Maintainer: Ray Lehtiniemi */
+	.atag_offset	= 0x100,
+	.nr_irqs	= CLPS711X_NR_IRQS,
+	.map_io		= clps711x_map_io,
+	.init_irq	= clps711x_init_irq,
+	.timer		= &clps711x_timer,
+	.init_machine	= cdb89712_init,
+	.handle_irq	= clps711x_handle_irq,
+	.restart	= clps711x_restart,
+MACHINE_END
diff --git a/arch/arm/mach-clps711x/board-clep7312.c b/arch/arm/mach-clps711x/board-clep7312.c
new file mode 100644
index 0000000..0b32a48
--- /dev/null
+++ b/arch/arm/mach-clps711x/board-clep7312.c
@@ -0,0 +1,46 @@
+/*
+ *  linux/arch/arm/mach-clps711x/clep7312.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "common.h"
+
+static void __init
+fixup_clep7312(struct tag *tags, char **cmdline, struct meminfo *mi)
+{
+	mi->nr_banks=1;
+	mi->bank[0].start = 0xc0000000;
+	mi->bank[0].size = 0x01000000;
+}
+
+MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312")
+	/* Maintainer: Nobody */
+	.atag_offset	= 0x0100,
+	.nr_irqs	= CLPS711X_NR_IRQS,
+	.fixup		= fixup_clep7312,
+	.map_io		= clps711x_map_io,
+	.init_irq	= clps711x_init_irq,
+	.timer		= &clps711x_timer,
+	.handle_irq	= clps711x_handle_irq,
+	.restart	= clps711x_restart,
+MACHINE_END
diff --git a/arch/arm/mach-clps711x/board-edb7211.c b/arch/arm/mach-clps711x/board-edb7211.c
new file mode 100644
index 0000000..71aa5cf
--- /dev/null
+++ b/arch/arm/mach-clps711x/board-edb7211.c
@@ -0,0 +1,180 @@
+/*
+ *  Copyright (C) 2000, 2001 Blue Mug, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/memblock.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/backlight.h>
+#include <linux/platform_device.h>
+
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/setup.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <video/platform_lcd.h>
+
+#include <mach/hardware.h>
+
+#include "common.h"
+
+#define VIDEORAM_SIZE		SZ_128K
+
+#define EDB7211_LCD_DC_DC_EN	CLPS711X_GPIO(3, 1)
+#define EDB7211_LCDEN		CLPS711X_GPIO(3, 2)
+#define EDB7211_LCDBL		CLPS711X_GPIO(3, 3)
+
+#define EDB7211_FLASH0_BASE	(CS0_PHYS_BASE)
+#define EDB7211_FLASH1_BASE	(CS1_PHYS_BASE)
+#define EDB7211_CS8900_BASE	(CS2_PHYS_BASE + 0x300)
+#define EDB7211_CS8900_IRQ	(IRQ_EINT3)
+
+static struct resource edb7211_cs8900_resource[] __initdata = {
+	DEFINE_RES_MEM(EDB7211_CS8900_BASE, SZ_1K),
+	DEFINE_RES_IRQ(EDB7211_CS8900_IRQ),
+};
+
+static struct mtd_partition edb7211_flash_partitions[] __initdata = {
+	{
+		.name	= "Flash",
+		.offset	= 0,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct physmap_flash_data edb7211_flash_pdata __initdata = {
+	.width		= 4,
+	.parts		= edb7211_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(edb7211_flash_partitions),
+};
+
+static struct resource edb7211_flash_resources[] __initdata = {
+	DEFINE_RES_MEM(EDB7211_FLASH0_BASE, SZ_8M),
+	DEFINE_RES_MEM(EDB7211_FLASH1_BASE, SZ_8M),
+};
+
+static struct platform_device edb7211_flash_pdev __initdata = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.resource	= edb7211_flash_resources,
+	.num_resources	= ARRAY_SIZE(edb7211_flash_resources),
+	.dev	= {
+		.platform_data	= &edb7211_flash_pdata,
+	},
+};
+
+static void edb7211_lcd_power_set(struct plat_lcd_data *pd, unsigned int power)
+{
+	if (power) {
+		gpio_set_value(EDB7211_LCDEN, 1);
+		udelay(100);
+		gpio_set_value(EDB7211_LCD_DC_DC_EN, 1);
+	} else {
+		gpio_set_value(EDB7211_LCD_DC_DC_EN, 0);
+		udelay(100);
+		gpio_set_value(EDB7211_LCDEN, 0);
+	}
+}
+
+static struct plat_lcd_data edb7211_lcd_power_pdata = {
+	.set_power	= edb7211_lcd_power_set,
+};
+
+static void edb7211_lcd_backlight_set_intensity(int intensity)
+{
+	gpio_set_value(EDB7211_LCDBL, intensity);
+}
+
+static struct generic_bl_info edb7211_lcd_backlight_pdata = {
+	.name			= "lcd-backlight.0",
+	.default_intensity	= 0x01,
+	.max_intensity		= 0x01,
+	.set_bl_intensity	= edb7211_lcd_backlight_set_intensity,
+};
+
+static struct gpio edb7211_gpios[] __initconst = {
+	{ EDB7211_LCD_DC_DC_EN,	GPIOF_OUT_INIT_LOW,	"LCD DC-DC" },
+	{ EDB7211_LCDEN,	GPIOF_OUT_INIT_LOW,	"LCD POWER" },
+	{ EDB7211_LCDBL,	GPIOF_OUT_INIT_LOW,	"LCD BACKLIGHT" },
+};
+
+static struct map_desc edb7211_io_desc[] __initdata = {
+	{	/* Memory-mapped extra keyboard row */
+		.virtual	= IO_ADDRESS(EP7211_PHYS_EXTKBD),
+		.pfn		= __phys_to_pfn(EP7211_PHYS_EXTKBD),
+		.length		= SZ_1M,
+		.type		= MT_DEVICE,
+	},
+};
+
+void __init edb7211_map_io(void)
+{
+	clps711x_map_io();
+	iotable_init(edb7211_io_desc, ARRAY_SIZE(edb7211_io_desc));
+}
+
+/* Reserve screen memory region at the start of main system memory. */
+static void __init edb7211_reserve(void)
+{
+	memblock_reserve(PHYS_OFFSET, VIDEORAM_SIZE);
+}
+
+static void __init
+fixup_edb7211(struct tag *tags, char **cmdline, struct meminfo *mi)
+{
+	/*
+	 * Bank start addresses are not present in the information
+	 * passed in from the boot loader.  We could potentially
+	 * detect them, but instead we hard-code them.
+	 *
+	 * Banks sizes _are_ present in the param block, but we're
+	 * not using that information yet.
+	 */
+	mi->bank[0].start = 0xc0000000;
+	mi->bank[0].size = SZ_8M;
+	mi->bank[1].start = 0xc1000000;
+	mi->bank[1].size = SZ_8M;
+	mi->nr_banks = 2;
+}
+
+static void __init edb7211_init(void)
+{
+	gpio_request_array(edb7211_gpios, ARRAY_SIZE(edb7211_gpios));
+
+	platform_device_register(&edb7211_flash_pdev);
+	platform_device_register_data(&platform_bus, "platform-lcd", 0,
+				      &edb7211_lcd_power_pdata,
+				      sizeof(edb7211_lcd_power_pdata));
+	platform_device_register_data(&platform_bus, "generic-bl", 0,
+				      &edb7211_lcd_backlight_pdata,
+				      sizeof(edb7211_lcd_backlight_pdata));
+	platform_device_register_simple("video-clps711x", 0, NULL, 0);
+	platform_device_register_simple("cs89x0", 0, edb7211_cs8900_resource,
+					ARRAY_SIZE(edb7211_cs8900_resource));
+}
+
+MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)")
+	/* Maintainer: Jon McClintock */
+	.atag_offset	= VIDEORAM_SIZE + 0x100,
+	.nr_irqs	= CLPS711X_NR_IRQS,
+	.fixup		= fixup_edb7211,
+	.reserve	= edb7211_reserve,
+	.map_io		= edb7211_map_io,
+	.init_irq	= clps711x_init_irq,
+	.timer		= &clps711x_timer,
+	.init_machine	= edb7211_init,
+	.handle_irq	= clps711x_handle_irq,
+	.restart	= clps711x_restart,
+MACHINE_END
diff --git a/arch/arm/mach-clps711x/board-fortunet.c b/arch/arm/mach-clps711x/board-fortunet.c
new file mode 100644
index 0000000..7d01255
--- /dev/null
+++ b/arch/arm/mach-clps711x/board-fortunet.c
@@ -0,0 +1,84 @@
+/*
+ *  linux/arch/arm/mach-clps711x/fortunet.c
+ *
+ *  Derived from linux/arch/arm/mach-integrator/arch.c
+ *
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/initrd.h>
+
+#include <mach/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+
+#include <asm/memory.h>
+
+#include "common.h"
+
+struct meminfo memmap = {
+	.nr_banks	= 1,
+	.bank		= {
+		{
+			.start	= 0xC0000000,
+			.size	= 0x01000000,
+		},
+	},
+};
+
+typedef struct tag_IMAGE_PARAMS
+{
+	int	ramdisk_ok;
+	int	ramdisk_address;
+	int	ramdisk_size;
+	int	ram_size;
+	int	extra_param_type;
+	int	extra_param_ptr;
+	int	command_line;
+} IMAGE_PARAMS;
+
+#define IMAGE_PARAMS_PHYS	0xC01F0000
+
+static void __init
+fortunet_fixup(struct tag *tags, char **cmdline, struct meminfo *mi)
+{
+	IMAGE_PARAMS *ip = phys_to_virt(IMAGE_PARAMS_PHYS);
+	*cmdline = phys_to_virt(ip->command_line);
+#ifdef CONFIG_BLK_DEV_INITRD
+	if(ip->ramdisk_ok)
+	{
+		initrd_start = __phys_to_virt(ip->ramdisk_address);
+		initrd_end = initrd_start + ip->ramdisk_size;
+	}
+#endif
+	memmap.bank[0].size = ip->ram_size;
+	*mi = memmap;
+}
+
+MACHINE_START(FORTUNET, "ARM-FortuNet")
+	/* Maintainer: FortuNet Inc. */
+	.nr_irqs	= CLPS711X_NR_IRQS,
+	.fixup		= fortunet_fixup,
+	.map_io		= clps711x_map_io,
+	.init_irq	= clps711x_init_irq,
+	.timer		= &clps711x_timer,
+	.handle_irq	= clps711x_handle_irq,
+	.restart	= clps711x_restart,
+MACHINE_END
diff --git a/arch/arm/mach-clps711x/board-p720t.c b/arch/arm/mach-clps711x/board-p720t.c
new file mode 100644
index 0000000..1518fc8
--- /dev/null
+++ b/arch/arm/mach-clps711x/board-p720t.c
@@ -0,0 +1,232 @@
+/*
+ *  linux/arch/arm/mach-clps711x/p720t.c
+ *
+ *  Copyright (C) 2000-2001 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include <linux/sizes.h>
+#include <linux/backlight.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand-gpio.h>
+
+#include <mach/hardware.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/syspld.h>
+
+#include <video/platform_lcd.h>
+
+#include "common.h"
+
+#define P720T_USERLED		CLPS711X_GPIO(3, 0)
+#define P720T_NAND_CLE		CLPS711X_GPIO(4, 0)
+#define P720T_NAND_ALE		CLPS711X_GPIO(4, 1)
+#define P720T_NAND_NCE		CLPS711X_GPIO(4, 2)
+
+#define P720T_NAND_BASE		(CLPS711X_SDRAM1_BASE)
+
+static struct resource p720t_nand_resource[] __initdata = {
+	DEFINE_RES_MEM(P720T_NAND_BASE, SZ_4),
+};
+
+static struct mtd_partition p720t_nand_parts[] __initdata = {
+	{
+		.name	= "Flash partition 1",
+		.offset	= 0,
+		.size	= SZ_2M,
+	},
+	{
+		.name	= "Flash partition 2",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct gpio_nand_platdata p720t_nand_pdata __initdata = {
+	.gpio_rdy	= -1,
+	.gpio_nce	= P720T_NAND_NCE,
+	.gpio_ale	= P720T_NAND_ALE,
+	.gpio_cle	= P720T_NAND_CLE,
+	.gpio_nwp	= -1,
+	.chip_delay	= 15,
+	.parts		= p720t_nand_parts,
+	.num_parts	= ARRAY_SIZE(p720t_nand_parts),
+};
+
+static struct platform_device p720t_nand_pdev __initdata = {
+	.name		= "gpio-nand",
+	.id		= -1,
+	.resource	= p720t_nand_resource,
+	.num_resources	= ARRAY_SIZE(p720t_nand_resource),
+	.dev		= {
+		.platform_data = &p720t_nand_pdata,
+	},
+};
+
+static void p720t_lcd_power_set(struct plat_lcd_data *pd, unsigned int power)
+{
+	if (power) {
+		PLD_LCDEN = PLD_LCDEN_EN;
+		PLD_PWR |= PLD_S4_ON | PLD_S2_ON | PLD_S1_ON;
+	} else {
+		PLD_PWR &= ~(PLD_S4_ON | PLD_S2_ON | PLD_S1_ON);
+		PLD_LCDEN = 0;
+	}
+}
+
+static struct plat_lcd_data p720t_lcd_power_pdata = {
+	.set_power	= p720t_lcd_power_set,
+};
+
+static void p720t_lcd_backlight_set_intensity(int intensity)
+{
+	if (intensity)
+		PLD_PWR |= PLD_S3_ON;
+	else
+		PLD_PWR = 0;
+}
+
+static struct generic_bl_info p720t_lcd_backlight_pdata = {
+	.name			= "lcd-backlight.0",
+	.default_intensity	= 0x01,
+	.max_intensity		= 0x01,
+	.set_bl_intensity	= p720t_lcd_backlight_set_intensity,
+};
+
+/*
+ * Map the P720T system PLD. It occupies two address spaces:
+ * 0x10000000 and 0x10400000. We map both regions as one.
+ */
+static struct map_desc p720t_io_desc[] __initdata = {
+	{
+		.virtual	= SYSPLD_VIRT_BASE,
+		.pfn		= __phys_to_pfn(SYSPLD_PHYS_BASE),
+		.length		= SZ_8M,
+		.type		= MT_DEVICE,
+	},
+};
+
+static void __init
+fixup_p720t(struct tag *tag, char **cmdline, struct meminfo *mi)
+{
+	/*
+	 * Our bootloader doesn't setup any tags (yet).
+	 */
+	if (tag->hdr.tag != ATAG_CORE) {
+		tag->hdr.tag = ATAG_CORE;
+		tag->hdr.size = tag_size(tag_core);
+		tag->u.core.flags = 0;
+		tag->u.core.pagesize = PAGE_SIZE;
+		tag->u.core.rootdev = 0x0100;
+
+		tag = tag_next(tag);
+		tag->hdr.tag = ATAG_MEM;
+		tag->hdr.size = tag_size(tag_mem32);
+		tag->u.mem.size = 4096;
+		tag->u.mem.start = PHYS_OFFSET;
+
+		tag = tag_next(tag);
+		tag->hdr.tag = ATAG_NONE;
+		tag->hdr.size = 0;
+	}
+}
+
+static void __init p720t_map_io(void)
+{
+	clps711x_map_io();
+	iotable_init(p720t_io_desc, ARRAY_SIZE(p720t_io_desc));
+}
+
+static void __init p720t_init_early(void)
+{
+	/*
+	 * Power down as much as possible in case we don't
+	 * have the drivers loaded.
+	 */
+	PLD_LCDEN = 0;
+	PLD_PWR  &= ~(PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
+
+	PLD_KBD   = 0;
+	PLD_IO    = 0;
+	PLD_IRDA  = 0;
+	PLD_CODEC = 0;
+	PLD_TCH   = 0;
+	PLD_SPI   = 0;
+	if (!IS_ENABLED(CONFIG_DEBUG_LL)) {
+		PLD_COM2 = 0;
+		PLD_COM1 = 0;
+	}
+}
+
+static struct gpio_led p720t_gpio_leds[] = {
+	{
+		.name			= "User LED",
+		.default_trigger	= "heartbeat",
+		.gpio			= P720T_USERLED,
+	},
+};
+
+static struct gpio_led_platform_data p720t_gpio_led_pdata __initdata = {
+	.leds		= p720t_gpio_leds,
+	.num_leds	= ARRAY_SIZE(p720t_gpio_leds),
+};
+
+static void __init p720t_init(void)
+{
+	platform_device_register(&p720t_nand_pdev);
+	platform_device_register_data(&platform_bus, "platform-lcd", 0,
+				      &p720t_lcd_power_pdata,
+				      sizeof(p720t_lcd_power_pdata));
+	platform_device_register_data(&platform_bus, "generic-bl", 0,
+				      &p720t_lcd_backlight_pdata,
+				      sizeof(p720t_lcd_backlight_pdata));
+	platform_device_register_simple("video-clps711x", 0, NULL, 0);
+}
+
+static void __init p720t_init_late(void)
+{
+	platform_device_register_data(&platform_bus, "leds-gpio", 0,
+				      &p720t_gpio_led_pdata,
+				      sizeof(p720t_gpio_led_pdata));
+}
+
+MACHINE_START(P720T, "ARM-Prospector720T")
+	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
+	.atag_offset	= 0x100,
+	.nr_irqs	= CLPS711X_NR_IRQS,
+	.fixup		= fixup_p720t,
+	.map_io		= p720t_map_io,
+	.init_early	= p720t_init_early,
+	.init_irq	= clps711x_init_irq,
+	.timer		= &clps711x_timer,
+	.init_machine	= p720t_init,
+	.init_late	= p720t_init_late,
+	.handle_irq	= clps711x_handle_irq,
+	.restart	= clps711x_restart,
+MACHINE_END
diff --git a/arch/arm/mach-clps711x/cdb89712.c b/arch/arm/mach-clps711x/cdb89712.c
deleted file mode 100644
index c314f49..0000000
--- a/arch/arm/mach-clps711x/cdb89712.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- *  linux/arch/arm/mach-clps711x/cdb89712.c
- *
- *  Copyright (C) 2000-2001 Deep Blue Solutions Ltd
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include "common.h"
-
-/*
- * Map the CS89712 Ethernet port.  That should be moved to the
- * ethernet driver, perhaps.
- */
-static struct map_desc cdb89712_io_desc[] __initdata = {
-	{
-		.virtual	= ETHER_BASE,
-		.pfn		=__phys_to_pfn(ETHER_START),
-		.length		= ETHER_SIZE,
-		.type		= MT_DEVICE
-	}
-};
-
-static void __init cdb89712_map_io(void)
-{
-	clps711x_map_io();
-	iotable_init(cdb89712_io_desc, ARRAY_SIZE(cdb89712_io_desc));
-}
-
-MACHINE_START(CDB89712, "Cirrus-CDB89712")
-	/* Maintainer: Ray Lehtiniemi */
-	.atag_offset	= 0x100,
-	.map_io		= cdb89712_map_io,
-	.init_irq	= clps711x_init_irq,
-	.timer		= &clps711x_timer,
-	.restart	= clps711x_restart,
-MACHINE_END
diff --git a/arch/arm/mach-clps711x/clep7312.c b/arch/arm/mach-clps711x/clep7312.c
deleted file mode 100644
index dbc7842..0000000
--- a/arch/arm/mach-clps711x/clep7312.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  linux/arch/arm/mach-clps711x/clep7312.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/string.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include "common.h"
-
-static void __init
-fixup_clep7312(struct tag *tags, char **cmdline, struct meminfo *mi)
-{
-	mi->nr_banks=1;
-	mi->bank[0].start = 0xc0000000;
-	mi->bank[0].size = 0x01000000;
-}
-
-
-MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312")
-	/* Maintainer: Nobody */
-	.atag_offset	= 0x0100,
-	.fixup		= fixup_clep7312,
-	.map_io		= clps711x_map_io,
-	.init_irq	= clps711x_init_irq,
-	.timer		= &clps711x_timer,
-	.restart	= clps711x_restart,
-MACHINE_END
-
diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c
index 509243d..e046439 100644
--- a/arch/arm/mach-clps711x/common.c
+++ b/arch/arm/mach-clps711x/common.c
@@ -21,13 +21,16 @@
  */
 #include <linux/io.h>
 #include <linux/init.h>
+#include <linux/sizes.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/clockchips.h>
 #include <linux/clk-provider.h>
 
-#include <asm/sizes.h>
+#include <asm/exception.h>
+#include <asm/mach/irq.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <asm/system_misc.h>
@@ -36,7 +39,6 @@
 
 static struct clk *clk_pll, *clk_bus, *clk_uart, *clk_timerl, *clk_timerh,
 		  *clk_tint, *clk_spi;
-static unsigned long latch;
 
 /*
  * This maps the generic CLPS711x registers
@@ -45,7 +47,7 @@ static struct map_desc clps711x_io_desc[] __initdata = {
 	{
 		.virtual	= (unsigned long)CLPS711X_VIRT_BASE,
 		.pfn		= __phys_to_pfn(CLPS711X_PHYS_BASE),
-		.length		= SZ_1M,
+		.length		= SZ_64K,
 		.type		= MT_DEVICE
 	}
 };
@@ -64,7 +66,7 @@ static void int1_mask(struct irq_data *d)
 	clps_writel(intmr1, INTMR1);
 }
 
-static void int1_ack(struct irq_data *d)
+static void int1_eoi(struct irq_data *d)
 {
 	switch (d->irq) {
 	case IRQ_CSINT:  clps_writel(0, COEOI);  break;
@@ -86,7 +88,8 @@ static void int1_unmask(struct irq_data *d)
 }
 
 static struct irq_chip int1_chip = {
-	.irq_ack	= int1_ack,
+	.name		= "Interrupt Vector 1",
+	.irq_eoi	= int1_eoi,
 	.irq_mask	= int1_mask,
 	.irq_unmask	= int1_unmask,
 };
@@ -100,7 +103,7 @@ static void int2_mask(struct irq_data *d)
 	clps_writel(intmr2, INTMR2);
 }
 
-static void int2_ack(struct irq_data *d)
+static void int2_eoi(struct irq_data *d)
 {
 	switch (d->irq) {
 	case IRQ_KBDINT: clps_writel(0, KBDEOI); break;
@@ -117,73 +120,160 @@ static void int2_unmask(struct irq_data *d)
 }
 
 static struct irq_chip int2_chip = {
-	.irq_ack	= int2_ack,
+	.name		= "Interrupt Vector 2",
+	.irq_eoi	= int2_eoi,
 	.irq_mask	= int2_mask,
 	.irq_unmask	= int2_unmask,
 };
 
+static void int3_mask(struct irq_data *d)
+{
+	u32 intmr3;
+
+	intmr3 = clps_readl(INTMR3);
+	intmr3 &= ~(1 << (d->irq - 32));
+	clps_writel(intmr3, INTMR3);
+}
+
+static void int3_unmask(struct irq_data *d)
+{
+	u32 intmr3;
+
+	intmr3 = clps_readl(INTMR3);
+	intmr3 |= 1 << (d->irq - 32);
+	clps_writel(intmr3, INTMR3);
+}
+
+static struct irq_chip int3_chip = {
+	.name		= "Interrupt Vector 3",
+	.irq_mask	= int3_mask,
+	.irq_unmask	= int3_unmask,
+};
+
+static struct {
+	int			nr;
+	struct irq_chip		*chip;
+	irq_flow_handler_t	handle;
+} clps711x_irqdescs[] __initdata = {
+	{ IRQ_CSINT,	&int1_chip,	handle_fasteoi_irq,	},
+	{ IRQ_EINT1,	&int1_chip,	handle_level_irq,	},
+	{ IRQ_EINT2,	&int1_chip,	handle_level_irq,	},
+	{ IRQ_EINT3,	&int1_chip,	handle_level_irq,	},
+	{ IRQ_TC1OI,	&int1_chip,	handle_fasteoi_irq,	},
+	{ IRQ_TC2OI,	&int1_chip,	handle_fasteoi_irq,	},
+	{ IRQ_RTCMI,	&int1_chip,	handle_fasteoi_irq,	},
+	{ IRQ_TINT,	&int1_chip,	handle_fasteoi_irq,	},
+	{ IRQ_UTXINT1,	&int1_chip,	handle_level_irq,	},
+	{ IRQ_URXINT1,	&int1_chip,	handle_level_irq,	},
+	{ IRQ_UMSINT,	&int1_chip,	handle_fasteoi_irq,	},
+	{ IRQ_SSEOTI,	&int1_chip,	handle_level_irq,	},
+	{ IRQ_KBDINT,	&int2_chip,	handle_fasteoi_irq,	},
+	{ IRQ_SS2RX,	&int2_chip,	handle_level_irq,	},
+	{ IRQ_SS2TX,	&int2_chip,	handle_level_irq,	},
+	{ IRQ_UTXINT2,	&int2_chip,	handle_level_irq,	},
+	{ IRQ_URXINT2,	&int2_chip,	handle_level_irq,	},
+};
+
 void __init clps711x_init_irq(void)
 {
 	unsigned int i;
 
-	for (i = 0; i < NR_IRQS; i++) {
-	        if (INT1_IRQS & (1 << i)) {
-			irq_set_chip_and_handler(i, &int1_chip,
-						 handle_level_irq);
-			set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-		}
-		if (INT2_IRQS & (1 << i)) {
-			irq_set_chip_and_handler(i, &int2_chip,
-						 handle_level_irq);
-			set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-		}
-	}
-
-	/*
-	 * Disable interrupts
-	 */
+	/* Disable interrupts */
 	clps_writel(0, INTMR1);
 	clps_writel(0, INTMR2);
+	clps_writel(0, INTMR3);
 
-	/*
-	 * Clear down any pending interrupts
-	 */
+	/* Clear down any pending interrupts */
+	clps_writel(0, BLEOI);
+	clps_writel(0, MCEOI);
 	clps_writel(0, COEOI);
 	clps_writel(0, TC1EOI);
 	clps_writel(0, TC2EOI);
 	clps_writel(0, RTCEOI);
 	clps_writel(0, TEOI);
 	clps_writel(0, UMSEOI);
-	clps_writel(0, SYNCIO);
 	clps_writel(0, KBDEOI);
+	clps_writel(0, SRXEOF);
+	clps_writel(0xffffffff, DAISR);
+
+	for (i = 0; i < ARRAY_SIZE(clps711x_irqdescs); i++) {
+		irq_set_chip_and_handler(clps711x_irqdescs[i].nr,
+					 clps711x_irqdescs[i].chip,
+					 clps711x_irqdescs[i].handle);
+		set_irq_flags(clps711x_irqdescs[i].nr,
+			      IRQF_VALID | IRQF_PROBE);
+	}
+
+	if (IS_ENABLED(CONFIG_FIQ)) {
+		init_FIQ(0);
+		irq_set_chip_and_handler(IRQ_DAIINT, &int3_chip,
+					 handle_bad_irq);
+		set_irq_flags(IRQ_DAIINT,
+			      IRQF_VALID | IRQF_PROBE | IRQF_NOAUTOEN);
+	}
 }
 
-/*
- * gettimeoffset() returns time since last timer tick, in usecs.
- *
- * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
- * 'tick' is usecs per jiffy.
- */
-static unsigned long clps711x_gettimeoffset(void)
+inline u32 fls16(u32 x)
 {
-	unsigned long hwticks;
-	hwticks = latch - (clps_readl(TC2D) & 0xffff);
-	return (hwticks * (tick_nsec / 1000)) / latch;
+	u32 r = 15;
+
+	if (!(x & 0xff00)) {
+		x <<= 8;
+		r -= 8;
+	}
+	if (!(x & 0xf000)) {
+		x <<= 4;
+		r -= 4;
+	}
+	if (!(x & 0xc000)) {
+		x <<= 2;
+		r -= 2;
+	}
+	if (!(x & 0x8000))
+		r--;
+
+	return r;
 }
 
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t p720t_timer_interrupt(int irq, void *dev_id)
+asmlinkage void __exception_irq_entry clps711x_handle_irq(struct pt_regs *regs)
 {
-	timer_tick();
+	u32 irqstat;
+	void __iomem *base = CLPS711X_VIRT_BASE;
+
+	irqstat = readl_relaxed(base + INTSR1) & readl_relaxed(base + INTMR1);
+	if (irqstat) {
+		handle_IRQ(fls16(irqstat), regs);
+		return;
+	}
+
+	irqstat = readl_relaxed(base + INTSR2) & readl_relaxed(base + INTMR2);
+	if (likely(irqstat))
+		handle_IRQ(fls16(irqstat) + 16, regs);
+}
+
+static void clps711x_clockevent_set_mode(enum clock_event_mode mode,
+					 struct clock_event_device *evt)
+{
+}
+
+static struct clock_event_device clockevent_clps711x = {
+	.name		= "CLPS711x Clockevents",
+	.rating		= 300,
+	.features	= CLOCK_EVT_FEAT_PERIODIC,
+	.set_mode	= clps711x_clockevent_set_mode,
+};
+
+static irqreturn_t clps711x_timer_interrupt(int irq, void *dev_id)
+{
+	clockevent_clps711x.event_handler(&clockevent_clps711x);
+
 	return IRQ_HANDLED;
 }
 
 static struct irqaction clps711x_timer_irq = {
 	.name		= "CLPS711x Timer Tick",
 	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= p720t_timer_interrupt,
+	.handler	= clps711x_timer_interrupt,
 };
 
 static void add_fixed_clk(struct clk *clk, const char *name, int rate)
@@ -244,20 +334,19 @@ static void __init clps711x_timer_init(void)
 
 	pr_info("CPU frequency set at %i Hz.\n", cpu);
 
-	latch = (timh + HZ / 2) / HZ;
+	clps_writew(DIV_ROUND_CLOSEST(timh, HZ), TC2D);
 
 	tmp = clps_readl(SYSCON1);
 	tmp |= SYSCON1_TC2S | SYSCON1_TC2M;
 	clps_writel(tmp, SYSCON1);
 
-	clps_writel(latch - 1, TC2D);
+	clockevents_config_and_register(&clockevent_clps711x, timh, 1, 0xffff);
 
 	setup_irq(IRQ_TC2OI, &clps711x_timer_irq);
 }
 
 struct sys_timer clps711x_timer = {
 	.init		= clps711x_timer_init,
-	.offset		= clps711x_gettimeoffset,
 };
 
 void clps711x_restart(char mode, const char *cmd)
diff --git a/arch/arm/mach-clps711x/common.h b/arch/arm/mach-clps711x/common.h
index fc0f065..b7c0c75 100644
--- a/arch/arm/mach-clps711x/common.h
+++ b/arch/arm/mach-clps711x/common.h
@@ -4,9 +4,14 @@
  * Common bits.
  */
 
+#define CLPS711X_NR_IRQS	(33)
+#define CLPS711X_NR_GPIO	(4 * 8 + 3)
+#define CLPS711X_GPIO(prt, bit)	((prt) * 8 + (bit))
+
 struct sys_timer;
 
 extern void clps711x_map_io(void);
 extern void clps711x_init_irq(void);
-extern struct sys_timer clps711x_timer;
+extern void clps711x_handle_irq(struct pt_regs *regs);
 extern void clps711x_restart(char mode, const char *cmd);
+extern struct sys_timer clps711x_timer;
diff --git a/arch/arm/mach-clps711x/edb7211-arch.c b/arch/arm/mach-clps711x/edb7211-arch.c
deleted file mode 100644
index 5fad0b4..0000000
--- a/arch/arm/mach-clps711x/edb7211-arch.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- *  linux/arch/arm/mach-clps711x/arch-edb7211.c
- *
- *  Copyright (C) 2000, 2001 Blue Mug, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/init.h>
-#include <linux/memblock.h>
-#include <linux/types.h>
-#include <linux/string.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include "common.h"
-
-extern void edb7211_map_io(void);
-
-/* Reserve screen memory region at the start of main system memory. */
-static void __init edb7211_reserve(void)
-{
-	memblock_reserve(PHYS_OFFSET, 0x00020000);
-}
-
-static void __init
-fixup_edb7211(struct tag *tags, char **cmdline, struct meminfo *mi)
-{
-	/*
-	 * Bank start addresses are not present in the information
-	 * passed in from the boot loader.  We could potentially
-	 * detect them, but instead we hard-code them.
-	 *
-	 * Banks sizes _are_ present in the param block, but we're
-	 * not using that information yet.
-	 */
-	mi->bank[0].start = 0xc0000000;
-	mi->bank[0].size = 8*1024*1024;
-	mi->bank[1].start = 0xc1000000;
-	mi->bank[1].size = 8*1024*1024;
-	mi->nr_banks = 2;
-}
-
-MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)")
-	/* Maintainer: Jon McClintock */
-	.atag_offset	= 0x20100,	/* 0xc0000000 - 0xc001ffff can be video RAM */
-	.fixup		= fixup_edb7211,
-	.map_io		= edb7211_map_io,
-	.reserve	= edb7211_reserve,
-	.init_irq	= clps711x_init_irq,
-	.timer		= &clps711x_timer,
-	.restart	= clps711x_restart,
-MACHINE_END
diff --git a/arch/arm/mach-clps711x/edb7211-mm.c b/arch/arm/mach-clps711x/edb7211-mm.c
deleted file mode 100644
index 4372f06..0000000
--- a/arch/arm/mach-clps711x/edb7211-mm.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- *  linux/arch/arm/mach-clps711x/mm.c
- *
- *  Extra MM routines for the EDB7211 board
- *
- *  Copyright (C) 2000, 2001 Blue Mug, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/bug.h>
-
-#include <mach/hardware.h>
-#include <asm/page.h>
-#include <asm/sizes.h>
- 
-#include <asm/mach/map.h>
-
-extern void clps711x_map_io(void);
-
-/*
- * The on-chip registers are given a size of 1MB so that a section can
- * be used to map them; this saves a page table.  This is the place to
- * add mappings for ROM, expansion memory, PCMCIA, etc.  (if static
- * mappings are chosen for those areas).
- *
- * Here is a physical memory map (to be fleshed out later):
- *
- * Physical Address  Size  Description
- * ----------------- ----- ---------------------------------
- * c0000000-c001ffff 128KB reserved for video RAM [1]
- * c0020000-c0023fff  16KB parameters (see Documentation/arm/Setup)
- * c0024000-c0027fff  16KB swapper_pg_dir (task 0 page directory)
- * c0028000-...            kernel image (TEXTADDR)
- *
- * [1] Unused pages should be given back to the VM; they are not yet.
- *     The parameter block should also be released (not sure if this
- *     happens).
- */
-static struct map_desc edb7211_io_desc[] __initdata = {
- 	{	/* memory-mapped extra keyboard row */
-	 	.virtual 	= EP7211_VIRT_EXTKBD,
-		.pfn		= __phys_to_pfn(EP7211_PHYS_EXTKBD),
-		.length		= SZ_1M,
-		.type		= MT_DEVICE,
-	}, {	/* and CS8900A Ethernet chip */
-		.virtual	= EP7211_VIRT_CS8900A,
-		.pfn		= __phys_to_pfn(EP7211_PHYS_CS8900A),
-		.length		= SZ_1M,
-		.type		= MT_DEVICE,
-	}, { 	/* flash banks */
-		.virtual	= EP7211_VIRT_FLASH1,
-		.pfn		= __phys_to_pfn(EP7211_PHYS_FLASH1),
-		.length		= SZ_8M,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= EP7211_VIRT_FLASH2,
-		.pfn		= __phys_to_pfn(EP7211_PHYS_FLASH2),
-		.length		= SZ_8M,
-		.type		= MT_DEVICE,
-	}
-};
-
-void __init edb7211_map_io(void)
-{
-        clps711x_map_io();
-        iotable_init(edb7211_io_desc, ARRAY_SIZE(edb7211_io_desc));
-}
-
diff --git a/arch/arm/mach-clps711x/fortunet.c b/arch/arm/mach-clps711x/fortunet.c
deleted file mode 100644
index 3a3f0b7..0000000
--- a/arch/arm/mach-clps711x/fortunet.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- *  linux/arch/arm/mach-clps711x/fortunet.c
- *
- *  Derived from linux/arch/arm/mach-integrator/arch.c
- *
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/initrd.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-
-#include <asm/mach/arch.h>
-
-#include <asm/memory.h>
-
-#include "common.h"
-
-struct meminfo memmap = {
-	.nr_banks	= 1,
-	.bank		= {
-		{
-			.start	= 0xC0000000,
-			.size	= 0x01000000,
-		},
-	},
-};
-
-typedef struct tag_IMAGE_PARAMS
-{
-	int	ramdisk_ok;
-	int	ramdisk_address;
-	int	ramdisk_size;
-	int	ram_size;
-	int	extra_param_type;
-	int	extra_param_ptr;
-	int	command_line;
-} IMAGE_PARAMS;
-
-#define IMAGE_PARAMS_PHYS	0xC01F0000
-
-static void __init
-fortunet_fixup(struct tag *tags, char **cmdline, struct meminfo *mi)
-{
-	IMAGE_PARAMS *ip = phys_to_virt(IMAGE_PARAMS_PHYS);
-	*cmdline = phys_to_virt(ip->command_line);
-#ifdef CONFIG_BLK_DEV_INITRD
-	if(ip->ramdisk_ok)
-	{
-		initrd_start = __phys_to_virt(ip->ramdisk_address);
-		initrd_end = initrd_start + ip->ramdisk_size;
-	}
-#endif
-	memmap.bank[0].size = ip->ram_size;
-	*mi = memmap;
-}
-
-MACHINE_START(FORTUNET, "ARM-FortuNet")
-	/* Maintainer: FortuNet Inc. */
-	.fixup		= fortunet_fixup,
-	.map_io		= clps711x_map_io,
-	.init_irq	= clps711x_init_irq,
-	.timer		= &clps711x_timer,
-	.restart	= clps711x_restart,
-MACHINE_END
diff --git a/arch/arm/mach-clps711x/include/mach/autcpu12.h b/arch/arm/mach-clps711x/include/mach/autcpu12.h
index 1588a36..0452f5f 100644
--- a/arch/arm/mach-clps711x/include/mach/autcpu12.h
+++ b/arch/arm/mach-clps711x/include/mach/autcpu12.h
@@ -21,24 +21,15 @@
 #define __ASM_ARCH_AUTCPU12_H
 
 /*
- * The CS8900A ethernet chip has its I/O registers wired to chip select 2
- * (nCS2). This is the mapping for it.
- */
-#define AUTCPU12_PHYS_CS8900A		CS2_PHYS_BASE		/* physical */
-#define AUTCPU12_VIRT_CS8900A		(0xfe000000)		/* virtual */
-
-/*
  * The flash bank is wired to chip select 0
  */
 #define AUTCPU12_PHYS_FLASH		CS0_PHYS_BASE		/* physical */
 
 /* offset for device specific information structure */
 #define AUTCPU12_LCDINFO_OFFS		(0x00010000)	
-/*
-* Videomemory is the internal SRAM (CS 6)	
-*/
+
+/* Videomemory in the internal SRAM (CS 6) */
 #define AUTCPU12_PHYS_VIDEO		CS6_PHYS_BASE
-#define AUTCPU12_VIRT_VIDEO		(0xfd000000)
 
 /*
 * All special IO's are tied to CS1
@@ -49,8 +40,6 @@
 
 #define AUTCPU12_PHYS_CSAUX1           	CS1_PHYS_BASE +0x04000000  /* physical */
 
-#define AUTCPU12_PHYS_SMC              	CS1_PHYS_BASE +0x06000000  /* physical */
-
 #define AUTCPU12_PHYS_CAN              	CS1_PHYS_BASE +0x08000000  /* physical */
 
 #define AUTCPU12_PHYS_TOUCH            	CS1_PHYS_BASE +0x0A000000  /* physical */
@@ -59,14 +48,6 @@
 
 #define AUTCPU12_PHYS_LPT              	CS1_PHYS_BASE +0x0E000000  /* physical */
 
-/* 
-* defines for smartmedia card access 
-*/
-#define AUTCPU12_SMC_RDY		(1<<2)
-#define AUTCPU12_SMC_ALE		(1<<3)
-#define AUTCPU12_SMC_CLE  		(1<<4)
-#define AUTCPU12_SMC_PORT_OFFSET	PBDR
-#define AUTCPU12_SMC_SELECT_OFFSET 	0x10
 /*
 * defines for lcd contrast 
 */
diff --git a/arch/arm/mach-clps711x/include/mach/clps711x.h b/arch/arm/mach-clps711x/include/mach/clps711x.h
index c82e21c..01d1b95 100644
--- a/arch/arm/mach-clps711x/include/mach/clps711x.h
+++ b/arch/arm/mach-clps711x/include/mach/clps711x.h
@@ -257,6 +257,9 @@
 #define MEMCFG_BUS_WIDTH_16	(0)
 #define MEMCFG_BUS_WIDTH_8	(3)
 
+#define MEMCFG_SQAEN		(1 << 6)
+#define MEMCFG_CLKENB		(1 << 7)
+
 #define MEMCFG_WAITSTATE_8_3	(0 << 2)
 #define MEMCFG_WAITSTATE_7_3	(1 << 2)
 #define MEMCFG_WAITSTATE_6_3	(2 << 2)
@@ -274,4 +277,28 @@
 #define MEMCFG_WAITSTATE_2_0	(14 << 2)
 #define MEMCFG_WAITSTATE_1_0	(15 << 2)
 
+/* INTSR1 Interrupts */
+#define IRQ_CSINT		(4)
+#define IRQ_EINT1		(5)
+#define IRQ_EINT2		(6)
+#define IRQ_EINT3		(7)
+#define IRQ_TC1OI		(8)
+#define IRQ_TC2OI		(9)
+#define IRQ_RTCMI		(10)
+#define IRQ_TINT		(11)
+#define IRQ_UTXINT1		(12)
+#define IRQ_URXINT1		(13)
+#define IRQ_UMSINT		(14)
+#define IRQ_SSEOTI		(15)
+
+/* INTSR2 Interrupts */
+#define IRQ_KBDINT		(16 + 0)
+#define IRQ_SS2RX		(16 + 1)
+#define IRQ_SS2TX		(16 + 2)
+#define IRQ_UTXINT2		(16 + 12)
+#define IRQ_URXINT2		(16 + 13)
+
+/* INTSR3 Interrupts */
+#define IRQ_DAIINT		(32 + 0)
+
 #endif /* __MACH_CLPS711X_H */
diff --git a/arch/arm/mach-clps711x/include/mach/entry-macro.S b/arch/arm/mach-clps711x/include/mach/entry-macro.S
deleted file mode 100644
index 56e5c2c..0000000
--- a/arch/arm/mach-clps711x/include/mach/entry-macro.S
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * arch/arm/mach-clps711x/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for CLPS711X-based platforms
- *
- * This file is licensed under  the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-#include <mach/hardware.h>
-
-		.macro	get_irqnr_preamble, base, tmp
-		.endm
-
-#if (INTSR2 - INTSR1) != (INTMR2 - INTMR1)
-#error INTSR stride != INTMR stride
-#endif
-
-		.macro	get_irqnr_and_base, irqnr, stat, base, mask
-		mov	\base, #CLPS711X_VIRT_BASE
-		ldr	\stat, [\base, #INTSR1]
-		ldr	\mask, [\base, #INTMR1]
-		mov	\irqnr, #4
-		mov	\mask, \mask, lsl #16
-		and	\stat, \stat, \mask, lsr #16
-		movs	\stat, \stat, lsr #4
-		bne	1001f
-
-		add	\base, \base, #INTSR2 - INTSR1
-		ldr	\stat, [\base, #INTSR1]
-		ldr	\mask, [\base, #INTMR1]
-		mov	\irqnr, #16
-		mov	\mask, \mask, lsl #16
-		and	\stat, \stat, \mask, lsr #16
-
-1001:		tst	\stat, #255
-		addeq	\irqnr, \irqnr, #8
-		moveq	\stat, \stat, lsr #8
-		tst	\stat, #15
-		addeq	\irqnr, \irqnr, #4
-		moveq	\stat, \stat, lsr #4
-		tst	\stat, #3
-		addeq	\irqnr, \irqnr, #2
-		moveq	\stat, \stat, lsr #2
-		tst	\stat, #1
-		addeq	\irqnr, \irqnr, #1
-		moveq	\stat, \stat, lsr #1
-		tst	\stat, #1			@ bit 0 should be set
-		.endm
-
-
diff --git a/arch/arm/mach-clps711x/include/mach/hardware.h b/arch/arm/mach-clps711x/include/mach/hardware.h
index 8497775..2f23dd5 100644
--- a/arch/arm/mach-clps711x/include/mach/hardware.h
+++ b/arch/arm/mach-clps711x/include/mach/hardware.h
@@ -24,7 +24,10 @@
 
 #include <mach/clps711x.h>
 
-#define CLPS711X_VIRT_BASE	IOMEM(0xff000000)
+#define IO_ADDRESS(x)		(0xdc000000 + (((x) & 0x03ffffff) | \
+				(((x) >> 2) & 0x3c000000)))
+
+#define CLPS711X_VIRT_BASE	IOMEM(IO_ADDRESS(CLPS711X_PHYS_BASE))
 
 #ifndef __ASSEMBLY__
 #define clps_readb(off)		readb(CLPS711X_VIRT_BASE + (off))
@@ -61,67 +64,17 @@
 #define CS7_PHYS_BASE		(0x00000000)
 #endif
 
-#define SYSPLD_VIRT_BASE	0xfe000000
-#define SYSPLD_BASE		SYSPLD_VIRT_BASE
-
-#if defined (CONFIG_ARCH_CDB89712)
-
-#define ETHER_START      0x20000000
-#define ETHER_SIZE       0x1000
-#define ETHER_BASE       0xfe000000
-
-#endif
+#define CLPS711X_SRAM_BASE	CS6_PHYS_BASE
+#define CLPS711X_SRAM_SIZE	(48 * 1024)
 
+#define CLPS711X_SDRAM0_BASE	(0xc0000000)
+#define CLPS711X_SDRAM1_BASE	(0xd0000000)
 
 #if defined (CONFIG_ARCH_EDB7211)
 
-/*
- * The extra 8 lines of the keyboard matrix are wired to chip select 3 (nCS3) 
- * and repeat across it. This is the mapping for it.
- *
- * In jumpered boot mode, nCS3 is mapped to 0x4000000, not 0x3000000. This 
- * was cause for much consternation and headscratching. This should probably
- * be made a compile/run time kernel option.
- */
-#define EP7211_PHYS_EXTKBD		CS3_PHYS_BASE	/* physical */
-
-#define EP7211_VIRT_EXTKBD		(0xfd000000)	/* virtual */
-
-
-/*
- * The CS8900A ethernet chip has its I/O registers wired to chip select 2 
- * (nCS2). This is the mapping for it.
- *
- * In jumpered boot mode, nCS2 is mapped to 0x5000000, not 0x2000000. This 
- * was cause for much consternation and headscratching. This should probably
- * be made a compile/run time kernel option.
- */
-#define EP7211_PHYS_CS8900A		CS2_PHYS_BASE	/* physical */
-
-#define EP7211_VIRT_CS8900A		(0xfc000000)	/* virtual */
-
-
-/*
- * The two flash banks are wired to chip selects 0 and 1. This is the mapping
- * for them.
- *
- * nCS0 and nCS1 are at 0x70000000 and 0x60000000, respectively, when running
- * in jumpered boot mode.
- */
-#define EP7211_PHYS_FLASH1		CS0_PHYS_BASE	/* physical */
-#define EP7211_PHYS_FLASH2		CS1_PHYS_BASE	/* physical */
-
-#define EP7211_VIRT_FLASH1		(0xfa000000)	/* virtual */
-#define EP7211_VIRT_FLASH2		(0xfb000000)	/* virtual */
+/* The extra 8 lines of the keyboard matrix are wired to chip select 3 */
+#define EP7211_PHYS_EXTKBD	CS3_PHYS_BASE
 
 #endif /* CONFIG_ARCH_EDB7211 */
 
-/*
- * Relevant bits in port D, which controls power to the various parts of
- * the LCD on the EDB7211.
- */
-#define EDB_PD1_LCD_DC_DC_EN	(1<<1)
-#define EDB_PD2_LCDEN		(1<<2)
-#define EDB_PD3_LCDBL		(1<<3)
-
 #endif
diff --git a/arch/arm/mach-clps711x/include/mach/irqs.h b/arch/arm/mach-clps711x/include/mach/irqs.h
deleted file mode 100644
index 14d215f..0000000
--- a/arch/arm/mach-clps711x/include/mach/irqs.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  arch/arm/mach-clps711x/include/mach/irqs.h
- *
- *  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
- */
-
-/*
- * Interrupts from INTSR1
- */
-#define IRQ_CSINT			4
-#define IRQ_EINT1			5
-#define IRQ_EINT2			6
-#define IRQ_EINT3			7
-#define IRQ_TC1OI			8
-#define IRQ_TC2OI			9
-#define IRQ_RTCMI			10
-#define IRQ_TINT			11
-#define IRQ_UTXINT1			12
-#define IRQ_URXINT1			13
-#define IRQ_UMSINT			14
-#define IRQ_SSEOTI			15
-
-#define INT1_IRQS			(0x0000fff0)
-
-/*
- * Interrupts from INTSR2
- */
-#define IRQ_KBDINT			(16+0)	/* bit 0 */
-#define IRQ_SS2RX			(16+1)	/* bit 1 */
-#define IRQ_SS2TX			(16+2)	/* bit 2 */
-#define IRQ_UTXINT2			(16+12)	/* bit 12 */
-#define IRQ_URXINT2			(16+13)	/* bit 13 */
-
-#define INT2_IRQS			(0x30070000)
-
-#define NR_IRQS				30
diff --git a/arch/arm/mach-clps711x/include/mach/syspld.h b/arch/arm/mach-clps711x/include/mach/syspld.h
index f7f4c12..9a43315 100644
--- a/arch/arm/mach-clps711x/include/mach/syspld.h
+++ b/arch/arm/mach-clps711x/include/mach/syspld.h
@@ -23,14 +23,9 @@
 #define __ASM_ARCH_SYSPLD_H
 
 #define SYSPLD_PHYS_BASE	(0x10000000)
+#define SYSPLD_VIRT_BASE	IO_ADDRESS(SYSPLD_PHYS_BASE)
 
-#ifndef __ASSEMBLY__
-#include <asm/types.h>
-
-#define SYSPLD_REG(type,off)	(*(volatile type *)(SYSPLD_BASE + off))
-#else
-#define SYSPLD_REG(type,off)	(off)
-#endif
+#define SYSPLD_REG(type, off)	(*(volatile type *)(SYSPLD_VIRT_BASE + (off)))
 
 #define PLD_INT		SYSPLD_REG(u32, 0x000000)
 #define PLD_INT_PENIRQ		(1 << 5)
diff --git a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c
deleted file mode 100644
index b752b58..0000000
--- a/arch/arm/mach-clps711x/p720t.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- *  linux/arch/arm/mach-clps711x/p720t.c
- *
- *  Copyright (C) 2000-2001 Deep Blue Solutions Ltd
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/leds.h>
-
-#include <mach/hardware.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-#include <asm/sizes.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <mach/syspld.h>
-
-#include <asm/hardware/clps7111.h>
-
-#include "common.h"
-
-/*
- * Map the P720T system PLD.  It occupies two address spaces:
- *  SYSPLD_PHYS_BASE and SYSPLD_PHYS_BASE + 0x00400000
- * We map both here.
- */
-static struct map_desc p720t_io_desc[] __initdata = {
-	{
-		.virtual	= SYSPLD_VIRT_BASE,
-		.pfn		= __phys_to_pfn(SYSPLD_PHYS_BASE),
-		.length		= SZ_1M,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= 0xfe400000,
-		.pfn		= __phys_to_pfn(0x10400000),
-		.length		= SZ_1M,
-		.type		= MT_DEVICE
-	}
-};
-
-static void __init
-fixup_p720t(struct tag *tag, char **cmdline, struct meminfo *mi)
-{
-	/*
-	 * Our bootloader doesn't setup any tags (yet).
-	 */
-	if (tag->hdr.tag != ATAG_CORE) {
-		tag->hdr.tag = ATAG_CORE;
-		tag->hdr.size = tag_size(tag_core);
-		tag->u.core.flags = 0;
-		tag->u.core.pagesize = PAGE_SIZE;
-		tag->u.core.rootdev = 0x0100;
-
-		tag = tag_next(tag);
-		tag->hdr.tag = ATAG_MEM;
-		tag->hdr.size = tag_size(tag_mem32);
-		tag->u.mem.size = 4096;
-		tag->u.mem.start = PHYS_OFFSET;
-
-		tag = tag_next(tag);
-		tag->hdr.tag = ATAG_NONE;
-		tag->hdr.size = 0;
-	}
-}
-
-static void __init p720t_map_io(void)
-{
-	clps711x_map_io();
-	iotable_init(p720t_io_desc, ARRAY_SIZE(p720t_io_desc));
-}
-
-static void __init p720t_init_early(void)
-{
-	/*
-	 * Power down as much as possible in case we don't
-	 * have the drivers loaded.
-	 */
-	PLD_LCDEN = 0;
-	PLD_PWR  &= ~(PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
-
-	PLD_KBD   = 0;
-	PLD_IO    = 0;
-	PLD_IRDA  = 0;
-	PLD_CODEC = 0;
-	PLD_TCH   = 0;
-	PLD_SPI   = 0;
-	if (!IS_ENABLED(CONFIG_DEBUG_LL)) {
-		PLD_COM2 = 0;
-		PLD_COM1 = 0;
-	}
-}
-
-/*
- * LED controled by CPLD
- */
-#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
-static void p720t_led_set(struct led_classdev *cdev,
-			      enum led_brightness b)
-{
-	u8 reg = clps_readb(PDDR);
-
-	if (b != LED_OFF)
-		reg |= 0x1;
-	else
-		reg &= ~0x1;
-
-	clps_writeb(reg, PDDR);
-}
-
-static enum led_brightness p720t_led_get(struct led_classdev *cdev)
-{
-	u8 reg = clps_readb(PDDR);
-
-	return (reg & 0x1) ? LED_FULL : LED_OFF;
-}
-
-static int __init p720t_leds_init(void)
-{
-
-	struct led_classdev *cdev;
-	int ret;
-
-	if (!machine_is_p720t())
-		return -ENODEV;
-
-	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
-	if (!cdev)
-		return -ENOMEM;
-
-	cdev->name = "p720t:0";
-	cdev->brightness_set = p720t_led_set;
-	cdev->brightness_get = p720t_led_get;
-	cdev->default_trigger = "heartbeat";
-
-	ret = led_classdev_register(NULL, cdev);
-	if (ret	< 0) {
-		kfree(cdev);
-		return ret;
-	}
-
-	return 0;
-}
-
-/*
- * Since we may have triggers on any subsystem, defer registration
- * until after subsystem_init.
- */
-fs_initcall(p720t_leds_init);
-#endif
-
-MACHINE_START(P720T, "ARM-Prospector720T")
-	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.atag_offset	= 0x100,
-	.fixup		= fixup_p720t,
-	.init_early	= p720t_init_early,
-	.map_io		= p720t_map_io,
-	.init_irq	= clps711x_init_irq,
-	.timer		= &clps711x_timer,
-	.restart	= clps711x_restart,
-MACHINE_END
diff --git a/arch/arm/mach-cns3xxx/Kconfig b/arch/arm/mach-cns3xxx/Kconfig
index 29b13f2..9ebfcc4 100644
--- a/arch/arm/mach-cns3xxx/Kconfig
+++ b/arch/arm/mach-cns3xxx/Kconfig
@@ -3,7 +3,6 @@ menu "CNS3XXX platform type"
 
 config MACH_CNS3420VB
 	bool "Support for CNS3420 Validation Board"
-	select MIGHT_HAVE_PCI
 	help
 	  Include support for the Cavium Networks CNS3420 MPCore Platform
 	  Baseboard.
diff --git a/arch/arm/mach-cns3xxx/cns3420vb.c b/arch/arm/mach-cns3xxx/cns3420vb.c
index 2c5fb4c..ae30539 100644
--- a/arch/arm/mach-cns3xxx/cns3420vb.c
+++ b/arch/arm/mach-cns3xxx/cns3420vb.c
@@ -24,6 +24,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/partitions.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/hardware/gic.h>
@@ -32,6 +34,7 @@
 #include <asm/mach/time.h>
 #include <mach/cns3xxx.h>
 #include <mach/irqs.h>
+#include <mach/pm.h>
 #include "core.h"
 #include "devices.h"
 
@@ -125,13 +128,52 @@ static struct resource cns3xxx_usb_ehci_resources[] = {
 
 static u64 cns3xxx_usb_ehci_dma_mask = DMA_BIT_MASK(32);
 
+static int csn3xxx_usb_power_on(struct platform_device *pdev)
+{
+	/*
+	 * EHCI and OHCI share the same clock and power,
+	 * resetting twice would cause the 1st controller been reset.
+	 * Therefore only do power up  at the first up device, and
+	 * power down at the last down device.
+	 *
+	 * Set USB AHB INCR length to 16
+	 */
+	if (atomic_inc_return(&usb_pwr_ref) == 1) {
+		cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
+		cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+		cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
+		__raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
+			MISC_CHIP_CONFIG_REG);
+	}
+
+	return 0;
+}
+
+static void csn3xxx_usb_power_off(struct platform_device *pdev)
+{
+	/*
+	 * EHCI and OHCI share the same clock and power,
+	 * resetting twice would cause the 1st controller been reset.
+	 * Therefore only do power up  at the first up device, and
+	 * power down at the last down device.
+	 */
+	if (atomic_dec_return(&usb_pwr_ref) == 0)
+		cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+}
+
+static struct usb_ehci_pdata cns3xxx_usb_ehci_pdata = {
+	.power_on	= csn3xxx_usb_power_on,
+	.power_off	= csn3xxx_usb_power_off,
+};
+
 static struct platform_device cns3xxx_usb_ehci_device = {
-	.name          = "cns3xxx-ehci",
+	.name          = "ehci-platform",
 	.num_resources = ARRAY_SIZE(cns3xxx_usb_ehci_resources),
 	.resource      = cns3xxx_usb_ehci_resources,
 	.dev           = {
 		.dma_mask          = &cns3xxx_usb_ehci_dma_mask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data     = &cns3xxx_usb_ehci_pdata,
 	},
 };
 
@@ -149,13 +191,20 @@ static struct resource cns3xxx_usb_ohci_resources[] = {
 
 static u64 cns3xxx_usb_ohci_dma_mask = DMA_BIT_MASK(32);
 
+static struct usb_ohci_pdata cns3xxx_usb_ohci_pdata = {
+	.num_ports	= 1,
+	.power_on	= csn3xxx_usb_power_on,
+	.power_off	= csn3xxx_usb_power_off,
+};
+
 static struct platform_device cns3xxx_usb_ohci_device = {
-	.name          = "cns3xxx-ohci",
+	.name          = "ohci-platform",
 	.num_resources = ARRAY_SIZE(cns3xxx_usb_ohci_resources),
 	.resource      = cns3xxx_usb_ohci_resources,
 	.dev           = {
 		.dma_mask          = &cns3xxx_usb_ohci_dma_mask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data	   = &cns3xxx_usb_ohci_pdata,
 	},
 };
 
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
index f8eecb9..0153950 100644
--- a/arch/arm/mach-davinci/Kconfig
+++ b/arch/arm/mach-davinci/Kconfig
@@ -58,6 +58,14 @@ config ARCH_DAVINCI_TNETV107X
 
 comment "DaVinci Board Type"
 
+config MACH_DA8XX_DT
+	bool "Support DA8XX platforms using device tree"
+	default y
+	depends on ARCH_DAVINCI_DA8XX
+	help
+	  Say y here to include support for TI DaVinci DA850 based using
+	  Flattened Device Tree. More information at Documentation/devicetree
+
 config MACH_DAVINCI_EVM
 	bool "TI DM644x EVM"
 	default ARCH_DAVINCI_DM644x
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index 2227eff..fb5c1aa 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_AINTC)			+= irq.o
 obj-$(CONFIG_CP_INTC)			+= cp_intc.o
 
 # Board specific
+obj-$(CONFIG_MACH_DA8XX_DT)		+= da8xx-dt.o
 obj-$(CONFIG_MACH_DAVINCI_EVM)  	+= board-dm644x-evm.o
 obj-$(CONFIG_MACH_SFFSDR)		+= board-sffsdr.o
 obj-$(CONFIG_MACH_NEUROS_OSD2)		+= board-neuros-osd2.o
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 32ee3f8..7211772 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -11,39 +11,40 @@
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
-#include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/i2c.h>
 #include <linux/i2c/at24.h>
 #include <linux/i2c/pca953x.h>
 #include <linux/input.h>
+#include <linux/input/tps6507x-ts.h>
 #include <linux/mfd/tps6507x.h>
-#include <linux/gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
+#include <linux/platform_device.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/uio_pruss.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/tps6507x.h>
-#include <linux/input/tps6507x-ts.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
-#include <linux/delay.h>
 #include <linux/wl12xx.h>
 
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/system_info.h>
-
 #include <mach/cp_intc.h>
 #include <mach/da8xx.h>
-#include <linux/platform_data/mtd-davinci.h>
 #include <mach/mux.h>
-#include <linux/platform_data/mtd-davinci-aemif.h>
-#include <linux/platform_data/spi-davinci.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/system_info.h>
 
 #include <media/tvp514x.h>
 #include <media/adv7343.h>
@@ -762,16 +763,19 @@ static u8 da850_iis_serializer_direction[] = {
 };
 
 static struct snd_platform_data da850_evm_snd_data = {
-	.tx_dma_offset	= 0x2000,
-	.rx_dma_offset	= 0x2000,
-	.op_mode	= DAVINCI_MCASP_IIS_MODE,
-	.num_serializer	= ARRAY_SIZE(da850_iis_serializer_direction),
-	.tdm_slots	= 2,
-	.serial_dir	= da850_iis_serializer_direction,
-	.asp_chan_q	= EVENTQ_0,
-	.version	= MCASP_VERSION_2,
-	.txnumevt	= 1,
-	.rxnumevt	= 1,
+	.tx_dma_offset		= 0x2000,
+	.rx_dma_offset		= 0x2000,
+	.op_mode		= DAVINCI_MCASP_IIS_MODE,
+	.num_serializer		= ARRAY_SIZE(da850_iis_serializer_direction),
+	.tdm_slots		= 2,
+	.serial_dir		= da850_iis_serializer_direction,
+	.asp_chan_q		= EVENTQ_0,
+	.ram_chan_q		= EVENTQ_1,
+	.version		= MCASP_VERSION_2,
+	.txnumevt		= 1,
+	.rxnumevt		= 1,
+	.sram_size_playback	= SZ_8K,
+	.sram_size_capture	= SZ_8K,
 };
 
 static const short da850_evm_mcasp_pins[] __initconst = {
@@ -1509,6 +1513,7 @@ static __init void da850_evm_init(void)
 		pr_warning("da850_evm_init: mcasp mux setup failed: %d\n",
 				ret);
 
+	da850_evm_snd_data.sram_pool = sram_get_gen_pool();
 	da8xx_register_mcasp(0, &da850_evm_snd_data);
 
 	ret = davinci_cfg_reg_list(da850_lcdcntl_pins);
@@ -1516,6 +1521,11 @@ static __init void da850_evm_init(void)
 		pr_warning("da850_evm_init: lcdcntl mux setup failed: %d\n",
 				ret);
 
+	ret = da8xx_register_uio_pruss();
+	if (ret)
+		pr_warn("da850_evm_init: pruss initialization failed: %d\n",
+				ret);
+
 	/* Handle board specific muxing for LCD here */
 	ret = davinci_cfg_reg_list(da850_evm_lcdc_pins);
 	if (ret)
diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
index 88ebea8..cdf8d07 100644
--- a/arch/arm/mach-davinci/board-dm355-evm.c
+++ b/arch/arm/mach-davinci/board-dm355-evm.c
@@ -324,7 +324,7 @@ static __init void dm355_evm_init(void)
 	if (IS_ERR(aemif))
 		WARN("%s: unable to get AEMIF clock\n", __func__);
 	else
-		clk_enable(aemif);
+		clk_prepare_enable(aemif);
 
 	platform_add_devices(davinci_evm_devices,
 			     ARRAY_SIZE(davinci_evm_devices));
diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c
index 2f88103..d419545 100644
--- a/arch/arm/mach-davinci/board-dm355-leopard.c
+++ b/arch/arm/mach-davinci/board-dm355-leopard.c
@@ -246,7 +246,7 @@ static __init void dm355_leopard_init(void)
 	if (IS_ERR(aemif))
 		WARN("%s: unable to get AEMIF clock\n", __func__);
 	else
-		clk_enable(aemif);
+		clk_prepare_enable(aemif);
 
 	platform_add_devices(davinci_leopard_devices,
 			     ARRAY_SIZE(davinci_leopard_devices));
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 1b4a8ad..5d49c75 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -478,7 +478,7 @@ static void __init evm_init_cpld(void)
 	aemif_clk = clk_get(NULL, "aemif");
 	if (IS_ERR(aemif_clk))
 		return;
-	clk_enable(aemif_clk);
+	clk_prepare_enable(aemif_clk);
 
 	if (request_mem_region(DM365_ASYNC_EMIF_DATA_CE1_BASE, SECTION_SIZE,
 			"cpld") == NULL)
@@ -489,7 +489,7 @@ static void __init evm_init_cpld(void)
 				SECTION_SIZE);
 fail:
 		pr_err("ERROR: can't map CPLD\n");
-		clk_disable(aemif_clk);
+		clk_disable_unprepare(aemif_clk);
 		return;
 	}
 
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index f22572ce..f5e018d 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -519,13 +519,11 @@ static int dm6444evm_msp430_get_pins(void)
 	char buf[4];
 	struct i2c_msg msg[2] = {
 		{
-			.addr = dm6446evm_msp->addr,
 			.flags = 0,
 			.len = 2,
 			.buf = (void __force *)txbuf,
 		},
 		{
-			.addr = dm6446evm_msp->addr,
 			.flags = I2C_M_RD,
 			.len = 4,
 			.buf = buf,
@@ -536,6 +534,9 @@ static int dm6444evm_msp430_get_pins(void)
 	if (!dm6446evm_msp)
 		return -ENXIO;
 
+	msg[0].addr = dm6446evm_msp->addr;
+	msg[1].addr = dm6446evm_msp->addr;
+
 	/* Command 4 == get input state, returns port 2 and port3 data
 	 *   S Addr W [A] len=2 [A] cmd=4 [A]
 	 *   RS Addr R [A] [len=4] A [cmd=4] A [port2] A [port3] N P
@@ -776,7 +777,7 @@ static __init void davinci_evm_init(void)
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 
 	aemif_clk = clk_get(NULL, "aemif");
-	clk_enable(aemif_clk);
+	clk_prepare_enable(aemif_clk);
 
 	if (HAS_ATA) {
 		if (HAS_NAND || HAS_NOR)
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 1dbf85b..9211e88 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -194,7 +194,7 @@ static int evm_led_setup(struct i2c_client *client, int gpio,
 	while (ngpio--) {
 		leds->gpio = gpio++;
 		leds++;
-	};
+	}
 
 	evm_led_dev = platform_device_alloc("leds-gpio", 0);
 	platform_device_add_data(evm_led_dev, &evm_led_data,
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index 144bf31..3e3e3af 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -188,7 +188,7 @@ static __init void davinci_ntosd2_init(void)
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 
 	aemif_clk = clk_get(NULL, "aemif");
-	clk_enable(aemif_clk);
+	clk_prepare_enable(aemif_clk);
 
 	if (HAS_ATA) {
 		if (HAS_NAND)
diff --git a/arch/arm/mach-davinci/common.c b/arch/arm/mach-davinci/common.c
index 64b0f65..a794f6d 100644
--- a/arch/arm/mach-davinci/common.c
+++ b/arch/arm/mach-davinci/common.c
@@ -87,8 +87,6 @@ void __init davinci_common_init(struct davinci_soc_info *soc_info)
 		iotable_init(davinci_soc_info.io_desc,
 				davinci_soc_info.io_desc_num);
 
-	init_consistent_dma_size(14 << 20);
-
 	/*
 	 * Normally devicemaps_init() would flush caches and tlb after
 	 * mdesc->map_io(), but we must also do it here because of the CPU
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index b90c172..68c5fe0 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -212,6 +212,12 @@ static struct clk tptc2_clk = {
 	.flags		= ALWAYS_ENABLED,
 };
 
+static struct clk pruss_clk = {
+	.name		= "pruss",
+	.parent		= &pll0_sysclk2,
+	.lpsc		= DA8XX_LPSC0_PRUSS,
+};
+
 static struct clk uart0_clk = {
 	.name		= "uart0",
 	.parent		= &pll0_sysclk2,
@@ -385,6 +391,7 @@ static struct clk_lookup da850_clks[] = {
 	CLK(NULL,		"tptc1",	&tptc1_clk),
 	CLK(NULL,		"tpcc1",	&tpcc1_clk),
 	CLK(NULL,		"tptc2",	&tptc2_clk),
+	CLK("pruss_uio",	"pruss",	&pruss_clk),
 	CLK(NULL,		"uart0",	&uart0_clk),
 	CLK(NULL,		"uart1",	&uart1_clk),
 	CLK(NULL,		"uart2",	&uart2_clk),
@@ -781,12 +788,6 @@ static struct map_desc da850_io_desc[] = {
 		.length		= DA8XX_CP_INTC_SIZE,
 		.type		= MT_DEVICE
 	},
-	{
-		.virtual	= SRAM_VIRT,
-		.pfn		= __phys_to_pfn(DA8XX_ARM_RAM_BASE),
-		.length		= SZ_8K,
-		.type		= MT_DEVICE
-	},
 };
 
 static u32 da850_psc_bases[] = { DA8XX_PSC0_BASE, DA8XX_PSC1_BASE };
@@ -1239,8 +1240,8 @@ static struct davinci_soc_info davinci_soc_info_da850 = {
 	.gpio_irq		= IRQ_DA8XX_GPIO0,
 	.serial_dev		= &da8xx_serial_device,
 	.emac_pdata		= &da8xx_emac_pdata,
-	.sram_dma		= DA8XX_ARM_RAM_BASE,
-	.sram_len		= SZ_8K,
+	.sram_dma		= DA8XX_SHARED_RAM_BASE,
+	.sram_len		= SZ_128K,
 };
 
 void __init da850_init(void)
diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c
new file mode 100644
index 0000000..37c27af
--- /dev/null
+++ b/arch/arm/mach-davinci/da8xx-dt.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Modified from mach-omap/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/io.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/irqdomain.h>
+
+#include <asm/mach/arch.h>
+
+#include <mach/common.h>
+#include <mach/cp_intc.h>
+#include <mach/da8xx.h>
+
+#define DA8XX_NUM_UARTS	3
+
+void __init da8xx_uart_clk_enable(void)
+{
+	int i;
+	for (i = 0; i < DA8XX_NUM_UARTS; i++)
+		davinci_serial_setup_clk(i, NULL);
+}
+
+static struct of_device_id da8xx_irq_match[] __initdata = {
+	{ .compatible = "ti,cp-intc", .data = cp_intc_of_init, },
+	{ }
+};
+
+static void __init da8xx_init_irq(void)
+{
+	of_irq_init(da8xx_irq_match);
+}
+
+#ifdef CONFIG_ARCH_DAVINCI_DA850
+
+static void __init da850_init_machine(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+	da8xx_uart_clk_enable();
+}
+
+static const char *da850_boards_compat[] __initdata = {
+	"enbw,cmc",
+	"ti,da850-evm",
+	"ti,da850",
+	NULL,
+};
+
+DT_MACHINE_START(DA850_DT, "Generic DA850/OMAP-L138/AM18x")
+	.map_io		= da850_init,
+	.init_irq	= da8xx_init_irq,
+	.timer		= &davinci_timer,
+	.init_machine	= da850_init_machine,
+	.dt_compat	= da850_boards_compat,
+	.init_late	= davinci_init_late,
+	.restart	= da8xx_restart,
+MACHINE_END
+
+#endif
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index bd2f72b..41ccc88 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -22,6 +22,7 @@
 #include <mach/time.h>
 #include <mach/da8xx.h>
 #include <mach/cpuidle.h>
+#include <mach/sram.h>
 
 #include "clock.h"
 #include "asp.h"
@@ -32,6 +33,7 @@
 #define DA8XX_WDOG_BASE			0x01c21000 /* DA8XX_TIMER64P1_BASE */
 #define DA8XX_I2C0_BASE			0x01c22000
 #define DA8XX_RTC_BASE			0x01c23000
+#define DA8XX_PRUSS_MEM_BASE		0x01c30000
 #define DA8XX_MMCSD0_BASE		0x01c40000
 #define DA8XX_SPI0_BASE			0x01c41000
 #define DA830_SPI1_BASE			0x01e12000
@@ -518,6 +520,75 @@ void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata)
 	}
 }
 
+static struct resource da8xx_pruss_resources[] = {
+	{
+		.start	= DA8XX_PRUSS_MEM_BASE,
+		.end	= DA8XX_PRUSS_MEM_BASE + 0xFFFF,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IRQ_DA8XX_EVTOUT0,
+		.end	= IRQ_DA8XX_EVTOUT0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DA8XX_EVTOUT1,
+		.end	= IRQ_DA8XX_EVTOUT1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DA8XX_EVTOUT2,
+		.end	= IRQ_DA8XX_EVTOUT2,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DA8XX_EVTOUT3,
+		.end	= IRQ_DA8XX_EVTOUT3,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DA8XX_EVTOUT4,
+		.end	= IRQ_DA8XX_EVTOUT4,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DA8XX_EVTOUT5,
+		.end	= IRQ_DA8XX_EVTOUT5,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DA8XX_EVTOUT6,
+		.end	= IRQ_DA8XX_EVTOUT6,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DA8XX_EVTOUT7,
+		.end	= IRQ_DA8XX_EVTOUT7,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct uio_pruss_pdata da8xx_uio_pruss_pdata = {
+	.pintc_base	= 0x4000,
+};
+
+static struct platform_device da8xx_uio_pruss_dev = {
+	.name		= "pruss_uio",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(da8xx_pruss_resources),
+	.resource	= da8xx_pruss_resources,
+	.dev		= {
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &da8xx_uio_pruss_pdata,
+	}
+};
+
+int __init da8xx_register_uio_pruss(void)
+{
+	da8xx_uio_pruss_pdata.sram_pool = sram_get_gen_pool();
+	return platform_device_register(&da8xx_uio_pruss_dev);
+}
+
 static const struct display_panel disp_panel = {
 	QVGA,
 	16,
@@ -674,7 +745,7 @@ static struct resource da8xx_rtc_resources[] = {
 };
 
 static struct platform_device da8xx_rtc_device = {
-	.name           = "omap_rtc",
+	.name           = "da830-rtc",
 	.id             = -1,
 	.num_resources	= ARRAY_SIZE(da8xx_rtc_resources),
 	.resource	= da8xx_rtc_resources,
@@ -683,17 +754,6 @@ static struct platform_device da8xx_rtc_device = {
 int da8xx_register_rtc(void)
 {
 	int ret;
-	void __iomem *base;
-
-	base = ioremap(DA8XX_RTC_BASE, SZ_4K);
-	if (WARN_ON(!base))
-		return -ENOMEM;
-
-	/* Unlock the rtc's registers */
-	__raw_writel(0x83e70b13, base + 0x6c);
-	__raw_writel(0x95a4f1e0, base + 0x70);
-
-	iounmap(base);
 
 	ret = platform_device_register(&da8xx_rtc_device);
 	if (!ret)
@@ -900,7 +960,7 @@ static int da850_sata_init(struct device *dev, void __iomem *addr)
 	if (IS_ERR(da850_sata_clk))
 		return PTR_ERR(da850_sata_clk);
 
-	ret = clk_enable(da850_sata_clk);
+	ret = clk_prepare_enable(da850_sata_clk);
 	if (ret)
 		goto err0;
 
@@ -931,7 +991,7 @@ static int da850_sata_init(struct device *dev, void __iomem *addr)
 	return 0;
 
 err1:
-	clk_disable(da850_sata_clk);
+	clk_disable_unprepare(da850_sata_clk);
 err0:
 	clk_put(da850_sata_clk);
 	return ret;
@@ -939,7 +999,7 @@ err0:
 
 static void da850_sata_exit(struct device *dev)
 {
-	clk_disable(da850_sata_clk);
+	clk_disable_unprepare(da850_sata_clk);
 	clk_put(da850_sata_clk);
 }
 
diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c
index 29b17f7..773ab07 100644
--- a/arch/arm/mach-davinci/devices-tnetv107x.c
+++ b/arch/arm/mach-davinci/devices-tnetv107x.c
@@ -374,7 +374,7 @@ void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
 	 * complete sample conversion in time.
 	 */
 	tsc_clk = clk_get(NULL, "sys_tsc_clk");
-	if (tsc_clk) {
+	if (!IS_ERR(tsc_clk)) {
 		error = clk_set_rate(tsc_clk, 5000000);
 		WARN_ON(error < 0);
 		clk_put(tsc_clk);
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index a255434..b49c3b7 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -758,12 +758,6 @@ static struct map_desc dm355_io_desc[] = {
 		.length		= IO_SIZE,
 		.type		= MT_DEVICE
 	},
-	{
-		.virtual	= SRAM_VIRT,
-		.pfn		= __phys_to_pfn(0x00010000),
-		.length		= SZ_32K,
-		.type		= MT_MEMORY_NONCACHED,
-	},
 };
 
 /* Contents of JTAG ID register used to identify exact cpu type */
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index b680c83..6c39805 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -985,12 +985,6 @@ static struct map_desc dm365_io_desc[] = {
 		.length		= IO_SIZE,
 		.type		= MT_DEVICE
 	},
-	{
-		.virtual	= SRAM_VIRT,
-		.pfn		= __phys_to_pfn(0x00010000),
-		.length		= SZ_32K,
-		.type		= MT_MEMORY_NONCACHED,
-	},
 };
 
 static struct resource dm365_ks_resources[] = {
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index 14e9947..11c79a3 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -785,12 +785,6 @@ static struct map_desc dm644x_io_desc[] = {
 		.length		= IO_SIZE,
 		.type		= MT_DEVICE
 	},
-	{
-		.virtual	= SRAM_VIRT,
-		.pfn		= __phys_to_pfn(0x00008000),
-		.length		= SZ_16K,
-		.type		= MT_MEMORY_NONCACHED,
-	},
 };
 
 /* Contents of JTAG ID register used to identify exact cpu type */
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 97c0f8e..ac7b431 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -756,12 +756,6 @@ static struct map_desc dm646x_io_desc[] = {
 		.length		= IO_SIZE,
 		.type		= MT_DEVICE
 	},
-	{
-		.virtual	= SRAM_VIRT,
-		.pfn		= __phys_to_pfn(0x00010000),
-		.length		= SZ_32K,
-		.type		= MT_MEMORY_NONCACHED,
-	},
 };
 
 /* Contents of JTAG ID register used to identify exact cpu type */
diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h
index bdc4aa8..046c723 100644
--- a/arch/arm/mach-davinci/include/mach/common.h
+++ b/arch/arm/mach-davinci/include/mach/common.h
@@ -104,8 +104,6 @@ int davinci_pm_init(void);
 static inline int davinci_pm_init(void) { return 0; }
 #endif
 
-/* standard place to map on-chip SRAMs; they *may* support DMA */
-#define SRAM_VIRT	0xfffe0000
 #define SRAM_SIZE	SZ_128K
 
 #endif /* __ARCH_ARM_MACH_DAVINCI_COMMON_H */
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index aaccdc4..700d311 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -26,6 +26,7 @@
 #include <linux/platform_data/mmc-davinci.h>
 #include <linux/platform_data/usb-davinci.h>
 #include <linux/platform_data/spi-davinci.h>
+#include <linux/platform_data/uio_pruss.h>
 
 #include <media/davinci/vpif_types.h>
 
@@ -72,6 +73,7 @@ extern unsigned int da850_max_speed;
 #define DA8XX_AEMIF_CS2_BASE	0x60000000
 #define DA8XX_AEMIF_CS3_BASE	0x62000000
 #define DA8XX_AEMIF_CTL_BASE	0x68000000
+#define DA8XX_SHARED_RAM_BASE	0x80000000
 #define DA8XX_ARM_RAM_BASE	0xffff0000
 
 void __init da830_init(void);
@@ -86,6 +88,7 @@ int da8xx_register_watchdog(void);
 int da8xx_register_usb20(unsigned mA, unsigned potpgt);
 int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata);
 int da8xx_register_emac(void);
+int da8xx_register_uio_pruss(void);
 int da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata);
 int da8xx_register_mmcsd0(struct davinci_mmc_config *config);
 int da850_register_mmcsd1(struct davinci_mmc_config *config);
diff --git a/arch/arm/mach-davinci/include/mach/serial.h b/arch/arm/mach-davinci/include/mach/serial.h
index 46b3cd1..62ad300 100644
--- a/arch/arm/mach-davinci/include/mach/serial.h
+++ b/arch/arm/mach-davinci/include/mach/serial.h
@@ -38,11 +38,12 @@
 
 #ifndef __ASSEMBLY__
 struct davinci_uart_config {
-	/* Bit field of UARTs present; bit 0 --> UART1 */
+	/* Bit field of UARTs present; bit 0 --> UART0 */
 	unsigned int enabled_uarts;
 };
 
 extern int davinci_serial_init(struct davinci_uart_config *);
+extern int davinci_serial_setup_clk(unsigned instance, unsigned int *rate);
 #endif
 
 #endif /* __ASM_ARCH_SERIAL_H */
diff --git a/arch/arm/mach-davinci/include/mach/sram.h b/arch/arm/mach-davinci/include/mach/sram.h
index 111f7cc..4e5db56 100644
--- a/arch/arm/mach-davinci/include/mach/sram.h
+++ b/arch/arm/mach-davinci/include/mach/sram.h
@@ -24,4 +24,7 @@
 extern void *sram_alloc(size_t len, dma_addr_t *dma);
 extern void sram_free(void *addr, size_t len);
 
+/* Get the struct gen_pool * for use in platform data */
+extern struct gen_pool *sram_get_gen_pool(void);
+
 #endif /* __MACH_SRAM_H */
diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h
index 18cfd49..3a0ff90 100644
--- a/arch/arm/mach-davinci/include/mach/uncompress.h
+++ b/arch/arm/mach-davinci/include/mach/uncompress.h
@@ -32,6 +32,9 @@ u32 *uart;
 /* PORT_16C550A, in polled non-fifo mode */
 static void putc(char c)
 {
+	if (!uart)
+		return;
+
 	while (!(uart[UART_LSR] & UART_LSR_THRE))
 		barrier();
 	uart[UART_TX] = c;
@@ -39,6 +42,9 @@ static void putc(char c)
 
 static inline void flush(void)
 {
+	if (!uart)
+		return;
+
 	while (!(uart[UART_LSR] & UART_LSR_THRE))
 		barrier();
 }
diff --git a/arch/arm/mach-davinci/serial.c b/arch/arm/mach-davinci/serial.c
index 1875740..f262581 100644
--- a/arch/arm/mach-davinci/serial.c
+++ b/arch/arm/mach-davinci/serial.c
@@ -70,11 +70,33 @@ static void __init davinci_serial_reset(struct plat_serial8250_port *p)
 				 UART_DM646X_SCR_TX_WATERMARK);
 }
 
-int __init davinci_serial_init(struct davinci_uart_config *info)
+/* Enable UART clock and obtain its rate */
+int __init davinci_serial_setup_clk(unsigned instance, unsigned int *rate)
 {
-	int i;
 	char name[16];
-	struct clk *uart_clk;
+	struct clk *clk;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+	struct device *dev = &soc_info->serial_dev->dev;
+
+	sprintf(name, "uart%d", instance);
+	clk = clk_get(dev, name);
+	if (IS_ERR(clk)) {
+		pr_err("%s:%d: failed to get UART%d clock\n",
+					__func__, __LINE__, instance);
+		return PTR_ERR(clk);
+	}
+
+	clk_prepare_enable(clk);
+
+	if (rate)
+		*rate = clk_get_rate(clk);
+
+	return 0;
+}
+
+int __init davinci_serial_init(struct davinci_uart_config *info)
+{
+	int i, ret;
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 	struct device *dev = &soc_info->serial_dev->dev;
 	struct plat_serial8250_port *p = dev->platform_data;
@@ -87,16 +109,9 @@ int __init davinci_serial_init(struct davinci_uart_config *info)
 		if (!(info->enabled_uarts & (1 << i)))
 			continue;
 
-		sprintf(name, "uart%d", i);
-		uart_clk = clk_get(dev, name);
-		if (IS_ERR(uart_clk)) {
-			printk(KERN_ERR "%s:%d: failed to get UART%d clock\n",
-					__func__, __LINE__, i);
+		ret = davinci_serial_setup_clk(i, &p->uartclk);
+		if (ret)
 			continue;
-		}
-
-		clk_enable(uart_clk);
-		p->uartclk = clk_get_rate(uart_clk);
 
 		if (!p->membase && p->mapbase) {
 			p->membase = ioremap(p->mapbase, SZ_4K);
diff --git a/arch/arm/mach-davinci/sram.c b/arch/arm/mach-davinci/sram.c
index db0f778..c5f7ee5 100644
--- a/arch/arm/mach-davinci/sram.c
+++ b/arch/arm/mach-davinci/sram.c
@@ -10,6 +10,7 @@
  */
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/genalloc.h>
 
 #include <mach/common.h>
@@ -17,6 +18,11 @@
 
 static struct gen_pool *sram_pool;
 
+struct gen_pool *sram_get_gen_pool(void)
+{
+	return sram_pool;
+}
+
 void *sram_alloc(size_t len, dma_addr_t *dma)
 {
 	unsigned long vaddr;
@@ -32,7 +38,7 @@ void *sram_alloc(size_t len, dma_addr_t *dma)
 		return NULL;
 
 	if (dma)
-		*dma = dma_base + (vaddr - SRAM_VIRT);
+		*dma = gen_pool_virt_to_phys(sram_pool, vaddr);
 	return (void *)vaddr;
 
 }
@@ -53,8 +59,10 @@ EXPORT_SYMBOL(sram_free);
  */
 static int __init sram_init(void)
 {
+	phys_addr_t phys = davinci_soc_info.sram_dma;
 	unsigned len = davinci_soc_info.sram_len;
 	int status = 0;
+	void *addr;
 
 	if (len) {
 		len = min_t(unsigned, len, SRAM_SIZE);
@@ -62,8 +70,17 @@ static int __init sram_init(void)
 		if (!sram_pool)
 			status = -ENOMEM;
 	}
-	if (sram_pool)
-		status = gen_pool_add(sram_pool, SRAM_VIRT, len, -1);
+
+	if (sram_pool) {
+		addr = ioremap(phys, len);
+		if (!addr)
+			return -ENOMEM;
+		status = gen_pool_add_virt(sram_pool, (unsigned)addr,
+					   phys, len, -1);
+		if (status < 0)
+			iounmap(addr);
+	}
+
 	WARN_ON(status < 0);
 	return status;
 }
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c
index 75da315..9847938 100644
--- a/arch/arm/mach-davinci/time.c
+++ b/arch/arm/mach-davinci/time.c
@@ -379,7 +379,7 @@ static void __init davinci_timer_init(void)
 
 	timer_clk = clk_get(NULL, "timer0");
 	BUG_ON(IS_ERR(timer_clk));
-	clk_enable(timer_clk);
+	clk_prepare_enable(timer_clk);
 
 	/* init timer hw */
 	timer_init();
@@ -429,7 +429,7 @@ void davinci_watchdog_reset(struct platform_device *pdev)
 	wd_clk = clk_get(&pdev->dev, NULL);
 	if (WARN_ON(IS_ERR(wd_clk)))
 		return;
-	clk_enable(wd_clk);
+	clk_prepare_enable(wd_clk);
 
 	/* disable, internal clock source */
 	__raw_writel(0, base + TCR);
diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c
index f77b953..34509ff 100644
--- a/arch/arm/mach-davinci/usb.c
+++ b/arch/arm/mach-davinci/usb.c
@@ -42,14 +42,8 @@ static struct musb_hdrc_config musb_config = {
 };
 
 static struct musb_hdrc_platform_data usb_data = {
-#if defined(CONFIG_USB_MUSB_OTG)
 	/* OTG requires a Mini-AB connector */
 	.mode           = MUSB_OTG,
-#elif defined(CONFIG_USB_MUSB_PERIPHERAL)
-	.mode           = MUSB_PERIPHERAL,
-#elif defined(CONFIG_USB_MUSB_HOST)
-	.mode           = MUSB_HOST,
-#endif
 	.clock		= "usb",
 	.config		= &musb_config,
 };
diff --git a/arch/arm/mach-dove/include/mach/pm.h b/arch/arm/mach-dove/include/mach/pm.h
index 7bcd0df..b47f750 100644
--- a/arch/arm/mach-dove/include/mach/pm.h
+++ b/arch/arm/mach-dove/include/mach/pm.h
@@ -63,7 +63,7 @@ static inline int pmu_to_irq(int pin)
 
 static inline int irq_to_pmu(int irq)
 {
-	if (IRQ_DOVE_PMU_START < irq && irq < NR_IRQS)
+	if (IRQ_DOVE_PMU_START <= irq && irq < NR_IRQS)
 		return irq - IRQ_DOVE_PMU_START;
 
 	return -EINVAL;
diff --git a/arch/arm/mach-dove/irq.c b/arch/arm/mach-dove/irq.c
index 0877115..bc4344a 100644
--- a/arch/arm/mach-dove/irq.c
+++ b/arch/arm/mach-dove/irq.c
@@ -46,8 +46,20 @@ static void pmu_irq_ack(struct irq_data *d)
 	int pin = irq_to_pmu(d->irq);
 	u32 u;
 
+	/*
+	 * The PMU mask register is not RW0C: it is RW.  This means that
+	 * the bits take whatever value is written to them; if you write
+	 * a '1', you will set the interrupt.
+	 *
+	 * Unfortunately this means there is NO race free way to clear
+	 * these interrupts.
+	 *
+	 * So, let's structure the code so that the window is as small as
+	 * possible.
+	 */
 	u = ~(1 << (pin & 31));
-	writel(u, PMU_INTERRUPT_CAUSE);
+	u &= readl_relaxed(PMU_INTERRUPT_CAUSE);
+	writel_relaxed(u, PMU_INTERRUPT_CAUSE);
 }
 
 static struct irq_chip pmu_irq_chip = {
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index da55107..91d5b6f 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -63,10 +63,20 @@ config SOC_EXYNOS5250
 	depends on ARCH_EXYNOS5
 	select S5P_PM if PM
 	select S5P_SLEEP if PM
+	select S5P_DEV_MFC
 	select SAMSUNG_DMADEV
 	help
 	  Enable EXYNOS5250 SoC support
 
+config SOC_EXYNOS5440
+	bool "SAMSUNG EXYNOS5440"
+	default y
+	depends on ARCH_EXYNOS5
+	select ARM_ARCH_TIMER
+	select AUTO_ZRELADDR
+	help
+	  Enable EXYNOS5440 SoC support
+
 config EXYNOS4_MCT
 	bool
 	default y
@@ -98,11 +108,6 @@ config EXYNOS_DEV_SYSMMU
 	help
 	  Common setup code for SYSTEM MMU in EXYNOS platforms
 
-config EXYNOS4_DEV_DWMCI
-	bool
-	help
-	  Compile in platform device definitions for DWMCI
-
 config EXYNOS4_DEV_USB_OHCI
 	bool
 	help
@@ -417,9 +422,9 @@ config MACH_EXYNOS4_DT
 
 config MACH_EXYNOS5_DT
 	bool "SAMSUNG EXYNOS5 Machine using device tree"
+	default y
 	depends on ARCH_EXYNOS5
 	select ARM_AMBA
-	select SOC_EXYNOS5250
 	select USE_OF
 	help
 	  Machine support for Samsung EXYNOS5 machine with device tree enabled.
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 9b58024..b189881 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -14,9 +14,9 @@ obj-				:=
 
 obj-$(CONFIG_ARCH_EXYNOS)	+= common.o
 obj-$(CONFIG_ARCH_EXYNOS4)	+= clock-exynos4.o
-obj-$(CONFIG_ARCH_EXYNOS5)	+= clock-exynos5.o
 obj-$(CONFIG_CPU_EXYNOS4210)	+= clock-exynos4210.o
 obj-$(CONFIG_SOC_EXYNOS4212)	+= clock-exynos4212.o
+obj-$(CONFIG_SOC_EXYNOS5250)	+= clock-exynos5.o
 
 obj-$(CONFIG_PM)		+= pm.o
 obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
@@ -50,10 +50,8 @@ obj-$(CONFIG_MACH_EXYNOS5_DT)		+= mach-exynos5-dt.o
 obj-y					+= dev-uart.o
 obj-$(CONFIG_ARCH_EXYNOS4)		+= dev-audio.o
 obj-$(CONFIG_EXYNOS4_DEV_AHCI)		+= dev-ahci.o
-obj-$(CONFIG_EXYNOS4_DEV_DWMCI)		+= dev-dwmci.o
 obj-$(CONFIG_EXYNOS_DEV_DMA)		+= dma.o
 obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI)	+= dev-ohci.o
-obj-$(CONFIG_EXYNOS_DEV_DRM)		+= dev-drm.o
 obj-$(CONFIG_EXYNOS_DEV_SYSMMU)		+= dev-sysmmu.o
 
 obj-$(CONFIG_ARCH_EXYNOS)		+= setup-i2c0.o
diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c
index 6a45c9a..efead60 100644
--- a/arch/arm/mach-exynos/clock-exynos4.c
+++ b/arch/arm/mach-exynos/clock-exynos4.c
@@ -576,6 +576,10 @@ static struct clk exynos4_init_clocks_off[] = {
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 15),
 	}, {
+		.name		= "tmu_apbif",
+		.enable		= exynos4_clk_ip_perir_ctrl,
+		.ctrlbit	= (1 << 17),
+	}, {
 		.name		= "keypad",
 		.enable		= exynos4_clk_ip_perir_ctrl,
 		.ctrlbit	= (1 << 16),
@@ -613,11 +617,6 @@ static struct clk exynos4_init_clocks_off[] = {
 		.ctrlbit	= (1 << 18),
 	}, {
 		.name		= "iis",
-		.devname	= "samsung-i2s.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 19),
-	}, {
-		.name		= "iis",
 		.devname	= "samsung-i2s.1",
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 20),
diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c
index c44ca1e..5c63bc7 100644
--- a/arch/arm/mach-exynos/clock-exynos5.c
+++ b/arch/arm/mach-exynos/clock-exynos5.c
@@ -24,6 +24,7 @@
 
 #include <mach/map.h>
 #include <mach/regs-clock.h>
+#include <mach/regs-audss.h>
 #include <mach/sysmmu.h>
 
 #include "common.h"
@@ -80,6 +81,8 @@ static struct sleep_save exynos5_clock_save[] = {
 	SAVE_ITEM(EXYNOS5_VPLL_CON0),
 	SAVE_ITEM(EXYNOS5_VPLL_CON1),
 	SAVE_ITEM(EXYNOS5_VPLL_CON2),
+	SAVE_ITEM(EXYNOS5_PWR_CTRL1),
+	SAVE_ITEM(EXYNOS5_PWR_CTRL2),
 };
 #endif
 
@@ -166,6 +169,16 @@ static int exynos5_clk_ip_gen_ctrl(struct clk *clk, int enable)
 	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GEN, clk, enable);
 }
 
+static int exynos5_clksrc_mask_maudio_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_MAUDIO, clk, enable);
+}
+
+static int exynos5_clk_audss_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(EXYNOS_CLKGATE_AUDSS, clk, enable);
+}
+
 static int exynos5_clk_ip_mfc_ctrl(struct clk *clk, int enable)
 {
 	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_MFC, clk, enable);
@@ -196,6 +209,11 @@ static int exynos5_clk_ip_isp1_ctrl(struct clk *clk, int enable)
 	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ISP1, clk, enable);
 }
 
+static int exynos5_clk_hdmiphy_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
+}
+
 /* Core list of CMU_CPU side */
 
 static struct clksrc_clk exynos5_clk_mout_apll = {
@@ -292,7 +310,7 @@ static struct clksrc_sources exynos5_clk_src_mpll = {
 	.nr_sources	= ARRAY_SIZE(exynos5_clk_src_mpll_list),
 };
 
-struct clksrc_clk exynos5_clk_mout_mpll = {
+static struct clksrc_clk exynos5_clk_mout_mpll = {
 	.clk = {
 		.name		= "mout_mpll",
 	},
@@ -467,12 +485,12 @@ static struct clksrc_clk exynos5_clk_pclk_acp = {
 
 /* Core list of CMU_TOP side */
 
-struct clk *exynos5_clkset_aclk_top_list[] = {
+static struct clk *exynos5_clkset_aclk_top_list[] = {
 	[0] = &exynos5_clk_mout_mpll_user.clk,
 	[1] = &exynos5_clk_mout_bpll_user.clk,
 };
 
-struct clksrc_sources exynos5_clkset_aclk = {
+static struct clksrc_sources exynos5_clkset_aclk = {
 	.sources	= exynos5_clkset_aclk_top_list,
 	.nr_sources	= ARRAY_SIZE(exynos5_clkset_aclk_top_list),
 };
@@ -486,12 +504,12 @@ static struct clksrc_clk exynos5_clk_aclk_400 = {
 	.reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 24, .size = 3 },
 };
 
-struct clk *exynos5_clkset_aclk_333_166_list[] = {
+static struct clk *exynos5_clkset_aclk_333_166_list[] = {
 	[0] = &exynos5_clk_mout_cpll.clk,
 	[1] = &exynos5_clk_mout_mpll_user.clk,
 };
 
-struct clksrc_sources exynos5_clkset_aclk_333_166 = {
+static struct clksrc_sources exynos5_clkset_aclk_333_166 = {
 	.sources	= exynos5_clkset_aclk_333_166_list,
 	.nr_sources	= ARRAY_SIZE(exynos5_clkset_aclk_333_166_list),
 };
@@ -616,6 +634,11 @@ static struct clk exynos5_init_clocks_off[] = {
 		.enable		= exynos5_clk_ip_peric_ctrl,
 		.ctrlbit	= (1 << 24),
 	}, {
+		.name		= "tmu_apbif",
+		.parent		= &exynos5_clk_aclk_66.clk,
+		.enable		= exynos5_clk_ip_peris_ctrl,
+		.ctrlbit	= (1 << 21),
+	}, {
 		.name		= "rtc",
 		.parent		= &exynos5_clk_aclk_66.clk,
 		.enable		= exynos5_clk_ip_peris_ctrl,
@@ -651,33 +674,48 @@ static struct clk exynos5_init_clocks_off[] = {
 		.ctrlbit	= (1 << 15),
 	}, {
 		.name		= "sata",
-		.devname	= "ahci",
+		.devname	= "exynos5-sata",
+		.parent         = &exynos5_clk_aclk_200.clk,
 		.enable		= exynos5_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 6),
 	}, {
-		.name		= "sata_phy",
+		.name		= "sata-phy",
+		.devname	= "exynos5-sata-phy",
+		.parent         = &exynos5_clk_aclk_200.clk,
 		.enable		= exynos5_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 24),
 	}, {
-		.name		= "sata_phy_i2c",
+		.name		= "i2c",
+		.devname	= "exynos5-sata-phy-i2c",
+		.parent         = &exynos5_clk_aclk_200.clk,
 		.enable		= exynos5_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 25),
 	}, {
 		.name		= "mfc",
-		.devname	= "s5p-mfc",
+		.devname	= "s5p-mfc-v6",
 		.enable		= exynos5_clk_ip_mfc_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
 		.name		= "hdmi",
-		.devname	= "exynos4-hdmi",
+		.devname	= "exynos5-hdmi",
 		.enable		= exynos5_clk_ip_disp1_ctrl,
 		.ctrlbit	= (1 << 6),
 	}, {
+		.name		= "hdmiphy",
+		.devname	= "exynos5-hdmi",
+		.enable		= exynos5_clk_hdmiphy_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
 		.name		= "mixer",
-		.devname	= "s5p-mixer",
+		.devname	= "exynos5-mixer",
 		.enable		= exynos5_clk_ip_disp1_ctrl,
 		.ctrlbit	= (1 << 5),
 	}, {
+		.name		= "dp",
+		.devname	= "exynos-dp",
+		.enable		= exynos5_clk_ip_disp1_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
 		.name		= "jpeg",
 		.enable		= exynos5_clk_ip_gen_ctrl,
 		.ctrlbit	= (1 << 2),
@@ -687,6 +725,11 @@ static struct clk exynos5_init_clocks_off[] = {
 		.ctrlbit	= (1 << 3),
 	}, {
 		.name		= "iis",
+		.devname	= "samsung-i2s.0",
+		.enable		= exynos5_clk_audss_ctrl,
+		.ctrlbit	= (3 << 2),
+	}, {
+		.name		= "iis",
 		.devname	= "samsung-i2s.1",
 		.enable		= exynos5_clk_ip_peric_ctrl,
 		.ctrlbit	= (1 << 20),
@@ -697,6 +740,11 @@ static struct clk exynos5_init_clocks_off[] = {
 		.ctrlbit	= (1 << 21),
 	}, {
 		.name		= "pcm",
+		.devname	= "samsung-pcm.0",
+		.enable		= exynos5_clk_audss_ctrl,
+		.ctrlbit	= (3 << 4),
+	}, {
+		.name		= "pcm",
 		.devname	= "samsung-pcm.1",
 		.enable		= exynos5_clk_ip_peric_ctrl,
 		.ctrlbit	= (1 << 22),
@@ -938,6 +986,95 @@ static struct clk exynos5_init_clocks_on[] = {
 	}
 };
 
+static struct clk *clkset_sclk_audio0_list[] = {
+	[0] = NULL,
+	[1] = &clk_ext_xtal_mux,
+	[2] = &exynos5_clk_sclk_hdmi27m,
+	[3] = &exynos5_clk_sclk_dptxphy,
+	[4] = &exynos5_clk_sclk_usbphy,
+	[5] = &exynos5_clk_sclk_hdmiphy,
+	[6] = &exynos5_clk_mout_mpll.clk,
+	[7] = &exynos5_clk_mout_epll.clk,
+	[8] = &exynos5_clk_sclk_vpll.clk,
+	[9] = &exynos5_clk_mout_cpll.clk,
+};
+
+static struct clksrc_sources exynos5_clkset_sclk_audio0 = {
+	.sources	= clkset_sclk_audio0_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_audio0_list),
+};
+
+static struct clksrc_clk exynos5_clk_sclk_audio0 = {
+	.clk	= {
+		.name		= "sclk-audio0",
+		.enable		= exynos5_clksrc_mask_maudio_ctrl,
+		.ctrlbit	= (1 << 0),
+	},
+	.sources = &exynos5_clkset_sclk_audio0,
+	.reg_src = { .reg = EXYNOS5_CLKSRC_MAUDIO, .shift = 0, .size = 4 },
+	.reg_div = { .reg = EXYNOS5_CLKDIV_MAUDIO, .shift = 0, .size = 4 },
+};
+
+static struct clk *exynos5_clkset_mout_audss_list[] = {
+	&clk_ext_xtal_mux,
+	&clk_fout_epll,
+};
+
+static struct clksrc_sources clkset_mout_audss = {
+	.sources	= exynos5_clkset_mout_audss_list,
+	.nr_sources	= ARRAY_SIZE(exynos5_clkset_mout_audss_list),
+};
+
+static struct clksrc_clk exynos5_clk_mout_audss = {
+	.clk	= {
+		.name		= "mout_audss",
+	},
+	.sources = &clkset_mout_audss,
+	.reg_src = { .reg = EXYNOS_CLKSRC_AUDSS, .shift = 0, .size = 1 },
+};
+
+static struct clk *exynos5_clkset_sclk_i2s_list[] = {
+	[0] = &exynos5_clk_mout_audss.clk,
+	[1] = NULL,
+	[2] = &exynos5_clk_sclk_audio0.clk,
+};
+
+static struct clksrc_sources exynos5_clkset_sclk_i2s = {
+	.sources	= exynos5_clkset_sclk_i2s_list,
+	.nr_sources	= ARRAY_SIZE(exynos5_clkset_sclk_i2s_list),
+};
+
+static struct clksrc_clk exynos5_clk_sclk_i2s = {
+	.clk		= {
+		.name		= "sclk-i2s",
+		.devname	= "samsung-i2s.0",
+		.enable		= exynos5_clk_audss_ctrl,
+		.ctrlbit	= (1 << 3),
+	},
+	.sources = &exynos5_clkset_sclk_i2s,
+	.reg_src = { .reg = EXYNOS_CLKSRC_AUDSS, .shift = 2, .size = 2 },
+	.reg_div = { .reg = EXYNOS_CLKDIV_AUDSS, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk exynos5_clk_dout_srp = {
+	.clk	= {
+		.name		= "dout_srp",
+		.parent		= &exynos5_clk_mout_audss.clk,
+	},
+	.reg_div = { .reg = EXYNOS_CLKDIV_AUDSS, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk exynos5_clk_i2s_bus = {
+	.clk	= {
+		.name		= "i2s-bus",
+		.devname	= "samsung-i2s.0",
+		.parent		= &exynos5_clk_dout_srp.clk,
+		.enable		= exynos5_clk_audss_ctrl,
+		.ctrlbit	= (1 << 2),
+	},
+	.reg_div = { .reg = EXYNOS_CLKDIV_AUDSS, .shift = 4, .size = 4 },
+};
+
 static struct clk exynos5_clk_pdma0 = {
 	.name		= "dma",
 	.devname	= "dma-pl330.0",
@@ -966,7 +1103,7 @@ static struct clk exynos5_clk_fimd1 = {
 	.ctrlbit	= (1 << 0),
 };
 
-struct clk *exynos5_clkset_group_list[] = {
+static struct clk *exynos5_clkset_group_list[] = {
 	[0] = &clk_ext_xtal_mux,
 	[1] = NULL,
 	[2] = &exynos5_clk_sclk_hdmi24m,
@@ -979,7 +1116,7 @@ struct clk *exynos5_clkset_group_list[] = {
 	[9] = &exynos5_clk_mout_cpll.clk,
 };
 
-struct clksrc_sources exynos5_clkset_group = {
+static struct clksrc_sources exynos5_clkset_group = {
 	.sources	= exynos5_clkset_group_list,
 	.nr_sources	= ARRAY_SIZE(exynos5_clkset_group_list),
 };
@@ -1195,7 +1332,7 @@ static struct clksrc_clk exynos5_clk_sclk_spi2 = {
 	.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC2, .shift = 8, .size = 8 },
 };
 
-struct clksrc_clk exynos5_clk_sclk_fimd1 = {
+static struct clksrc_clk exynos5_clk_sclk_fimd1 = {
 	.clk	= {
 		.name		= "sclk_fimd",
 		.devname	= "exynos5-fb.1",
@@ -1226,6 +1363,16 @@ static struct clksrc_clk exynos5_clksrcs[] = {
 		.reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 24, .size = 3 },
 	}, {
 		.clk	= {
+			.name		= "sclk_sata",
+			.devname	= "exynos5-sata",
+			.enable		= exynos5_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 24),
+		},
+		.sources = &exynos5_clkset_aclk,
+		.reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 24, .size = 1 },
+		.reg_div = { .reg = EXYNOS5_CLKDIV_FSYS0, .shift = 20, .size = 4 },
+	}, {
+		.clk	= {
 			.name		= "sclk_gscl_wrap",
 			.devname	= "s5p-mipi-csis.0",
 			.enable		= exynos5_clksrc_mask_gscl_ctrl,
@@ -1314,6 +1461,9 @@ static struct clksrc_clk *exynos5_sysclks[] = {
 	&exynos5_clk_mdout_spi1,
 	&exynos5_clk_mdout_spi2,
 	&exynos5_clk_sclk_fimd1,
+	&exynos5_clk_mout_audss,
+	&exynos5_clk_dout_srp,
+	&exynos5_clk_sclk_audio0,
 };
 
 static struct clk *exynos5_clk_cdev[] = {
@@ -1332,6 +1482,8 @@ static struct clksrc_clk *exynos5_clksrc_cdev[] = {
 	&exynos5_clk_sclk_mmc1,
 	&exynos5_clk_sclk_mmc2,
 	&exynos5_clk_sclk_mmc3,
+	&exynos5_clk_i2s_bus,
+	&exynos5_clk_sclk_i2s,
 };
 
 static struct clk_lookup exynos5_clk_lookup[] = {
@@ -1350,6 +1502,8 @@ static struct clk_lookup exynos5_clk_lookup[] = {
 	CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos5_clk_pdma1),
 	CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos5_clk_mdma1),
 	CLKDEV_INIT("exynos5-fb.1", "lcd", &exynos5_clk_fimd1),
+	CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &exynos5_clk_sclk_i2s.clk),
+	CLKDEV_INIT("samsung-i2s.0", "i2s_opclk1", &exynos5_clk_i2s_bus.clk),
 };
 
 static unsigned long exynos5_epll_get_rate(struct clk *clk)
@@ -1476,7 +1630,7 @@ static void exynos5_clock_resume(void)
 #define exynos5_clock_resume NULL
 #endif
 
-struct syscore_ops exynos5_clock_syscore_ops = {
+static struct syscore_ops exynos5_clock_syscore_ops = {
 	.suspend	= exynos5_clock_suspend,
 	.resume		= exynos5_clock_resume,
 };
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 1947be8..b919f5f 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -18,6 +18,7 @@
 #include <linux/sched.h>
 #include <linux/serial_core.h>
 #include <linux/of.h>
+#include <linux/of_fdt.h>
 #include <linux/of_irq.h>
 #include <linux/export.h>
 #include <linux/irqdomain.h>
@@ -58,12 +59,14 @@ static const char name_exynos4210[] = "EXYNOS4210";
 static const char name_exynos4212[] = "EXYNOS4212";
 static const char name_exynos4412[] = "EXYNOS4412";
 static const char name_exynos5250[] = "EXYNOS5250";
+static const char name_exynos5440[] = "EXYNOS5440";
 
 static void exynos4_map_io(void);
 static void exynos5_map_io(void);
+static void exynos5440_map_io(void);
 static void exynos4_init_clocks(int xtal);
 static void exynos5_init_clocks(int xtal);
-static void exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+static void exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 static int exynos_init(void);
 
 static struct cpu_table cpu_ids[] __initdata = {
@@ -72,7 +75,7 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idmask		= EXYNOS4_CPU_MASK,
 		.map_io		= exynos4_map_io,
 		.init_clocks	= exynos4_init_clocks,
-		.init_uarts	= exynos_init_uarts,
+		.init_uarts	= exynos4_init_uarts,
 		.init		= exynos_init,
 		.name		= name_exynos4210,
 	}, {
@@ -80,7 +83,7 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idmask		= EXYNOS4_CPU_MASK,
 		.map_io		= exynos4_map_io,
 		.init_clocks	= exynos4_init_clocks,
-		.init_uarts	= exynos_init_uarts,
+		.init_uarts	= exynos4_init_uarts,
 		.init		= exynos_init,
 		.name		= name_exynos4212,
 	}, {
@@ -88,7 +91,7 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idmask		= EXYNOS4_CPU_MASK,
 		.map_io		= exynos4_map_io,
 		.init_clocks	= exynos4_init_clocks,
-		.init_uarts	= exynos_init_uarts,
+		.init_uarts	= exynos4_init_uarts,
 		.init		= exynos_init,
 		.name		= name_exynos4412,
 	}, {
@@ -96,9 +99,14 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idmask		= EXYNOS5_SOC_MASK,
 		.map_io		= exynos5_map_io,
 		.init_clocks	= exynos5_init_clocks,
-		.init_uarts	= exynos_init_uarts,
 		.init		= exynos_init,
 		.name		= name_exynos5250,
+	}, {
+		.idcode		= EXYNOS5440_SOC_ID,
+		.idmask		= EXYNOS5_SOC_MASK,
+		.map_io		= exynos5440_map_io,
+		.init		= exynos_init,
+		.name		= name_exynos5440,
 	},
 };
 
@@ -110,6 +118,20 @@ static struct map_desc exynos_iodesc[] __initdata = {
 		.pfn		= __phys_to_pfn(EXYNOS_PA_CHIPID),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_AUDSS,
+		.pfn		= __phys_to_pfn(EXYNOS_PA_AUDSS),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static struct map_desc exynos5440_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_CHIPID,
+		.pfn		= __phys_to_pfn(EXYNOS5440_PA_CHIPID),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
 	},
 };
 
@@ -257,24 +279,18 @@ static struct map_desc exynos5_iodesc[] __initdata = {
 		.length		= SZ_64K,
 		.type		= MT_DEVICE,
 	}, {
-		.virtual	= (unsigned long)S5P_VA_COMBINER_BASE,
-		.pfn		= __phys_to_pfn(EXYNOS5_PA_COMBINER),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
 		.virtual	= (unsigned long)S3C_VA_UART,
 		.pfn		= __phys_to_pfn(EXYNOS5_PA_UART),
 		.length		= SZ_512K,
 		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GIC_CPU,
-		.pfn		= __phys_to_pfn(EXYNOS5_PA_GIC_CPU),
-		.length		= SZ_8K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GIC_DIST,
-		.pfn		= __phys_to_pfn(EXYNOS5_PA_GIC_DIST),
-		.length		= SZ_4K,
+	},
+};
+
+static struct map_desc exynos5440_iodesc0[] __initdata = {
+	{
+		.virtual	= (unsigned long)S3C_VA_UART,
+		.pfn		= __phys_to_pfn(EXYNOS5440_PA_UART0),
+		.length		= SZ_512K,
 		.type		= MT_DEVICE,
 	},
 };
@@ -286,11 +302,29 @@ void exynos4_restart(char mode, const char *cmd)
 
 void exynos5_restart(char mode, const char *cmd)
 {
-	__raw_writel(0x1, EXYNOS_SWRESET);
+	u32 val;
+	void __iomem *addr;
+
+	if (of_machine_is_compatible("samsung,exynos5250")) {
+		val = 0x1;
+		addr = EXYNOS_SWRESET;
+	} else if (of_machine_is_compatible("samsung,exynos5440")) {
+		val = (0x10 << 20) | (0x1 << 16);
+		addr = EXYNOS5440_SWRESET;
+	} else {
+		pr_err("%s: cannot support non-DT\n", __func__);
+		return;
+	}
+
+	__raw_writel(val, addr);
 }
 
 void __init exynos_init_late(void)
 {
+	if (of_machine_is_compatible("samsung,exynos5440"))
+		/* to be supported later */
+		return;
+
 	exynos_pm_late_initcall();
 }
 
@@ -302,8 +336,14 @@ void __init exynos_init_late(void)
 
 void __init exynos_init_io(struct map_desc *mach_desc, int size)
 {
+	unsigned long root = of_get_flat_dt_root();
+
 	/* initialize the io descriptors we need for initialization */
-	iotable_init(exynos_iodesc, ARRAY_SIZE(exynos_iodesc));
+	if (of_flat_dt_is_compatible(root, "samsung,exynos5440"))
+		iotable_init(exynos5440_iodesc, ARRAY_SIZE(exynos5440_iodesc));
+	else
+		iotable_init(exynos_iodesc, ARRAY_SIZE(exynos_iodesc));
+
 	if (mach_desc)
 		iotable_init(mach_desc, size);
 
@@ -354,23 +394,6 @@ static void __init exynos4_map_io(void)
 static void __init exynos5_map_io(void)
 {
 	iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
-
-	s3c_device_i2c0.resource[0].start = EXYNOS5_PA_IIC(0);
-	s3c_device_i2c0.resource[0].end   = EXYNOS5_PA_IIC(0) + SZ_4K - 1;
-	s3c_device_i2c0.resource[1].start = EXYNOS5_IRQ_IIC;
-	s3c_device_i2c0.resource[1].end   = EXYNOS5_IRQ_IIC;
-
-	s3c_sdhci_setname(0, "exynos4-sdhci");
-	s3c_sdhci_setname(1, "exynos4-sdhci");
-	s3c_sdhci_setname(2, "exynos4-sdhci");
-	s3c_sdhci_setname(3, "exynos4-sdhci");
-
-	/* The I2C bus controllers are directly compatible with s3c2440 */
-	s3c_i2c0_setname("s3c2440-i2c");
-	s3c_i2c1_setname("s3c2440-i2c");
-	s3c_i2c2_setname("s3c2440-i2c");
-
-	s3c64xx_spi_setname("exynos4210-spi");
 }
 
 static void __init exynos4_init_clocks(int xtal)
@@ -389,6 +412,11 @@ static void __init exynos4_init_clocks(int xtal)
 	exynos4_setup_clocks();
 }
 
+static void __init exynos5440_map_io(void)
+{
+	iotable_init(exynos5440_iodesc0, ARRAY_SIZE(exynos5440_iodesc0));
+}
+
 static void __init exynos5_init_clocks(int xtal)
 {
 	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
@@ -589,7 +617,8 @@ static void __init combiner_init(void __iomem *combiner_base,
 }
 
 #ifdef CONFIG_OF
-int __init combiner_of_init(struct device_node *np, struct device_node *parent)
+static int __init combiner_of_init(struct device_node *np,
+				   struct device_node *parent)
 {
 	void __iomem *combiner_base;
 
@@ -604,8 +633,9 @@ int __init combiner_of_init(struct device_node *np, struct device_node *parent)
 	return 0;
 }
 
-static const struct of_device_id exynos4_dt_irq_match[] = {
+static const struct of_device_id exynos_dt_irq_match[] = {
 	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+	{ .compatible = "arm,cortex-a15-gic", .data = gic_of_init, },
 	{ .compatible = "samsung,exynos4210-combiner",
 			.data = combiner_of_init, },
 	{},
@@ -622,7 +652,7 @@ void __init exynos4_init_irq(void)
 		gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset, NULL);
 #ifdef CONFIG_OF
 	else
-		of_irq_init(exynos4_dt_irq_match);
+		of_irq_init(exynos_dt_irq_match);
 #endif
 
 	if (!of_have_populated_dt())
@@ -639,7 +669,7 @@ void __init exynos4_init_irq(void)
 void __init exynos5_init_irq(void)
 {
 #ifdef CONFIG_OF
-	of_irq_init(exynos4_dt_irq_match);
+	of_irq_init(exynos_dt_irq_match);
 #endif
 	/*
 	 * The parameters of s5p_init_irq() are for VIC init.
@@ -647,6 +677,8 @@ void __init exynos5_init_irq(void)
 	 * uses GIC instead of VIC.
 	 */
 	s5p_init_irq(NULL, 0);
+
+	gic_arch_extn.irq_set_wake = s3c_irq_wake;
 }
 
 struct bus_type exynos_subsys = {
@@ -669,7 +701,7 @@ static int __init exynos4_l2x0_cache_init(void)
 {
 	int ret;
 
-	if (soc_is_exynos5250())
+	if (soc_is_exynos5250() || soc_is_exynos5440())
 		return 0;
 
 	ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK);
@@ -727,7 +759,7 @@ static int __init exynos_init(void)
 
 /* uart registration process */
 
-static void __init exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+static void __init exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 {
 	struct s3c2410_uartcfg *tcfg = cfg;
 	u32 ucnt;
@@ -735,10 +767,7 @@ static void __init exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 	for (ucnt = 0; ucnt < no; ucnt++, tcfg++)
 		tcfg->has_fracval = 1;
 
-	if (soc_is_exynos5250())
-		s3c24xx_init_uartdevs("exynos4210-uart", exynos5_uart_resources, cfg, no);
-	else
-		s3c24xx_init_uartdevs("exynos4210-uart", exynos4_uart_resources, cfg, no);
+	s3c24xx_init_uartdevs("exynos4210-uart", exynos4_uart_resources, cfg, no);
 }
 
 static void __iomem *exynos_eint_base;
@@ -970,14 +999,7 @@ static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
 	struct irq_chip *chip = irq_get_chip(irq);
 
 	chained_irq_enter(chip, desc);
-	chip->irq_mask(&desc->irq_data);
-
-	if (chip->irq_ack)
-		chip->irq_ack(&desc->irq_data);
-
 	generic_handle_irq(*irq_data);
-
-	chip->irq_unmask(&desc->irq_data);
 	chained_irq_exit(chip, desc);
 }
 
@@ -997,11 +1019,14 @@ static int __init exynos_init_irq_eint(void)
 	 * platforms switch over to using the pinctrl driver, the wakeup
 	 * interrupt support code here can be completely removed.
 	 */
+	static const struct of_device_id exynos_pinctrl_ids[] = {
+		{ .compatible = "samsung,pinctrl-exynos4210", },
+		{ .compatible = "samsung,pinctrl-exynos4x12", },
+	};
 	struct device_node *pctrl_np, *wkup_np;
-	const char *pctrl_compat = "samsung,pinctrl-exynos4210";
 	const char *wkup_compat = "samsung,exynos4210-wakeup-eint";
 
-	for_each_compatible_node(pctrl_np, NULL, pctrl_compat) {
+	for_each_matching_node(pctrl_np, exynos_pinctrl_ids) {
 		if (of_device_is_available(pctrl_np)) {
 			wkup_np = of_find_compatible_node(pctrl_np, NULL,
 							wkup_compat);
@@ -1010,6 +1035,8 @@ static int __init exynos_init_irq_eint(void)
 		}
 	}
 #endif
+	if (soc_is_exynos5440())
+		return 0;
 
 	if (soc_is_exynos5250())
 		exynos_eint_base = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c
index cff0595..0509241 100644
--- a/arch/arm/mach-exynos/cpuidle.c
+++ b/arch/arm/mach-exynos/cpuidle.c
@@ -21,6 +21,7 @@
 #include <asm/suspend.h>
 #include <asm/unified.h>
 #include <asm/cpuidle.h>
+#include <mach/regs-clock.h>
 #include <mach/regs-pmu.h>
 #include <mach/pmu.h>
 
@@ -116,7 +117,8 @@ static int exynos4_enter_core0_aftr(struct cpuidle_device *dev,
 	cpu_suspend(0, idle_finisher);
 
 #ifdef CONFIG_SMP
-	scu_enable(S5P_VA_SCU);
+	if (!soc_is_exynos5250())
+		scu_enable(S5P_VA_SCU);
 #endif
 	cpu_pm_exit();
 
@@ -156,12 +158,47 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev,
 		return exynos4_enter_core0_aftr(dev, drv, new_index);
 }
 
+static void __init exynos5_core_down_clk(void)
+{
+	unsigned int tmp;
+
+	/*
+	 * Enable arm clock down (in idle) and set arm divider
+	 * ratios in WFI/WFE state.
+	 */
+	tmp = PWR_CTRL1_CORE2_DOWN_RATIO | \
+	      PWR_CTRL1_CORE1_DOWN_RATIO | \
+	      PWR_CTRL1_DIV2_DOWN_EN	 | \
+	      PWR_CTRL1_DIV1_DOWN_EN	 | \
+	      PWR_CTRL1_USE_CORE1_WFE	 | \
+	      PWR_CTRL1_USE_CORE0_WFE	 | \
+	      PWR_CTRL1_USE_CORE1_WFI	 | \
+	      PWR_CTRL1_USE_CORE0_WFI;
+	__raw_writel(tmp, EXYNOS5_PWR_CTRL1);
+
+	/*
+	 * Enable arm clock up (on exiting idle). Set arm divider
+	 * ratios when not in idle along with the standby duration
+	 * ratios.
+	 */
+	tmp = PWR_CTRL2_DIV2_UP_EN	 | \
+	      PWR_CTRL2_DIV1_UP_EN	 | \
+	      PWR_CTRL2_DUR_STANDBY2_VAL | \
+	      PWR_CTRL2_DUR_STANDBY1_VAL | \
+	      PWR_CTRL2_CORE2_UP_RATIO	 | \
+	      PWR_CTRL2_CORE1_UP_RATIO;
+	__raw_writel(tmp, EXYNOS5_PWR_CTRL2);
+}
+
 static int __init exynos4_init_cpuidle(void)
 {
 	int i, max_cpuidle_state, cpu_id;
 	struct cpuidle_device *device;
 	struct cpuidle_driver *drv = &exynos4_idle_driver;
 
+	if (soc_is_exynos5250())
+		exynos5_core_down_clk();
+
 	/* Setup cpuidle driver */
 	drv->state_count = (sizeof(exynos4_cpuidle_set) /
 				       sizeof(struct cpuidle_state));
diff --git a/arch/arm/mach-exynos/dev-audio.c b/arch/arm/mach-exynos/dev-audio.c
index ae321c7..9d1a609 100644
--- a/arch/arm/mach-exynos/dev-audio.c
+++ b/arch/arm/mach-exynos/dev-audio.c
@@ -14,20 +14,15 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
+#include <linux/platform_data/asoc-s3c.h>
 
 #include <plat/gpio-cfg.h>
-#include <linux/platform_data/asoc-s3c.h>
 
 #include <mach/map.h>
 #include <mach/dma.h>
 #include <mach/irqs.h>
 #include <mach/regs-audss.h>
 
-static const char *rclksrc[] = {
-	[0] = "busclk",
-	[1] = "i2sclk",
-};
-
 static int exynos4_cfg_i2s(struct platform_device *pdev)
 {
 	/* configure GPIO for i2s port */
@@ -55,7 +50,6 @@ static struct s3c_audio_pdata i2sv5_pdata = {
 		.i2s = {
 			.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
 					 | QUIRK_NEED_RSTCLR,
-			.src_clk = rclksrc,
 			.idma_addr = EXYNOS4_AUDSS_INT_MEM,
 		},
 	},
@@ -78,17 +72,11 @@ struct platform_device exynos4_device_i2s0 = {
 	},
 };
 
-static const char *rclksrc_v3[] = {
-	[0] = "sclk_i2s",
-	[1] = "no_such_clock",
-};
-
 static struct s3c_audio_pdata i2sv3_pdata = {
 	.cfg_gpio = exynos4_cfg_i2s,
 	.type = {
 		.i2s = {
 			.quirks = QUIRK_NO_MUXPSR,
-			.src_clk = rclksrc_v3,
 		},
 	},
 };
diff --git a/arch/arm/mach-exynos/dev-drm.c b/arch/arm/mach-exynos/dev-drm.c
deleted file mode 100644
index 17c9c6e..0000000
--- a/arch/arm/mach-exynos/dev-drm.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * linux/arch/arm/mach-exynos/dev-drm.c
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS - core DRM device
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/dma-mapping.h>
-#include <linux/platform_device.h>
-
-#include <plat/devs.h>
-
-static u64 exynos_drm_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device exynos_device_drm = {
-	.name	= "exynos-drm",
-	.dev	= {
-		.dma_mask		= &exynos_drm_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	}
-};
diff --git a/arch/arm/mach-exynos/dev-dwmci.c b/arch/arm/mach-exynos/dev-dwmci.c
deleted file mode 100644
index 7903501..0000000
--- a/arch/arm/mach-exynos/dev-dwmci.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * linux/arch/arm/mach-exynos4/dev-dwmci.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Platform device for Synopsys DesignWare Mobile Storage IP
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/mmc/dw_mmc.h>
-
-#include <plat/devs.h>
-
-#include <mach/map.h>
-
-static int exynos4_dwmci_get_bus_wd(u32 slot_id)
-{
-	return 4;
-}
-
-static int exynos4_dwmci_init(u32 slot_id, irq_handler_t handler, void *data)
-{
-	return 0;
-}
-
-static struct resource exynos4_dwmci_resource[] = {
-	[0] = DEFINE_RES_MEM(EXYNOS4_PA_DWMCI, SZ_4K),
-	[1] = DEFINE_RES_IRQ(EXYNOS4_IRQ_DWMCI),
-};
-
-static struct dw_mci_board exynos4_dwci_pdata = {
-	.num_slots			= 1,
-	.quirks				= DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
-	.bus_hz				= 80 * 1000 * 1000,
-	.detect_delay_ms	= 200,
-	.init				= exynos4_dwmci_init,
-	.get_bus_wd			= exynos4_dwmci_get_bus_wd,
-};
-
-static u64 exynos4_dwmci_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device exynos4_device_dwmci = {
-	.name		= "dw_mmc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(exynos4_dwmci_resource),
-	.resource	= exynos4_dwmci_resource,
-	.dev		= {
-		.dma_mask		= &exynos4_dwmci_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-		.platform_data	= &exynos4_dwci_pdata,
-	},
-};
-
-void __init exynos4_dwmci_set_platdata(struct dw_mci_board *pd)
-{
-	struct dw_mci_board *npd;
-
-	npd = s3c_set_platdata(pd, sizeof(struct dw_mci_board),
-			&exynos4_device_dwmci);
-
-	if (!npd->init)
-		npd->init = exynos4_dwmci_init;
-	if (!npd->get_bus_wd)
-		npd->get_bus_wd = exynos4_dwmci_get_bus_wd;
-}
diff --git a/arch/arm/mach-exynos/dev-ohci.c b/arch/arm/mach-exynos/dev-ohci.c
index 14ed795..4244d02 100644
--- a/arch/arm/mach-exynos/dev-ohci.c
+++ b/arch/arm/mach-exynos/dev-ohci.c
@@ -12,10 +12,10 @@
 
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
+#include <linux/platform_data/usb-exynos.h>
 
 #include <mach/irqs.h>
 #include <mach/map.h>
-#include <linux/platform_data/usb-exynos.h>
 
 #include <plat/devs.h>
 #include <plat/usb-phy.h>
diff --git a/arch/arm/mach-exynos/dev-uart.c b/arch/arm/mach-exynos/dev-uart.c
index 2e85c02..7c42f4b 100644
--- a/arch/arm/mach-exynos/dev-uart.c
+++ b/arch/arm/mach-exynos/dev-uart.c
@@ -52,27 +52,3 @@ struct s3c24xx_uart_resources exynos4_uart_resources[] __initdata = {
 		.nr_resources	= ARRAY_SIZE(exynos4_uart3_resource),
 	},
 };
-
-EXYNOS_UART_RESOURCE(5, 0)
-EXYNOS_UART_RESOURCE(5, 1)
-EXYNOS_UART_RESOURCE(5, 2)
-EXYNOS_UART_RESOURCE(5, 3)
-
-struct s3c24xx_uart_resources exynos5_uart_resources[] __initdata = {
-	[0] = {
-		.resources	= exynos5_uart0_resource,
-		.nr_resources	= ARRAY_SIZE(exynos5_uart0_resource),
-	},
-	[1] = {
-		.resources	= exynos5_uart1_resource,
-		.nr_resources	= ARRAY_SIZE(exynos5_uart0_resource),
-	},
-	[2] = {
-		.resources	= exynos5_uart2_resource,
-		.nr_resources	= ARRAY_SIZE(exynos5_uart2_resource),
-	},
-	[3] = {
-		.resources	= exynos5_uart3_resource,
-		.nr_resources	= ARRAY_SIZE(exynos5_uart3_resource),
-	},
-};
diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c
index f4d7dd2..c3f825b 100644
--- a/arch/arm/mach-exynos/hotplug.c
+++ b/arch/arm/mach-exynos/hotplug.c
@@ -20,10 +20,11 @@
 #include <asm/smp_plat.h>
 
 #include <mach/regs-pmu.h>
+#include <plat/cpu.h>
 
 #include "common.h"
 
-static inline void cpu_enter_lowpower(void)
+static inline void cpu_enter_lowpower_a9(void)
 {
 	unsigned int v;
 
@@ -45,6 +46,35 @@ static inline void cpu_enter_lowpower(void)
 	  : "cc");
 }
 
+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();
+}
+
 static inline void cpu_leave_lowpower(void)
 {
 	unsigned int v;
@@ -103,11 +133,20 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 void __ref exynos_cpu_die(unsigned int cpu)
 {
 	int spurious = 0;
+	int primary_part = 0;
 
 	/*
-	 * we're ready for shutdown now, so do it
+	 * we're ready for shutdown now, so do it.
+	 * Exynos4 is A9 based while Exynos5 is A15; check the CPU part
+	 * number by reading the Main ID register and then perform the
+	 * appropriate sequence for entering low power.
 	 */
-	cpu_enter_lowpower();
+	asm("mrc p15, 0, %0, c0, c0, 0" : "=r"(primary_part) : : "cc");
+	if ((primary_part & 0xfff0) == 0xc0f0)
+		cpu_enter_lowpower_a15();
+	else
+		cpu_enter_lowpower_a9();
+
 	platform_do_lowpower(cpu, &spurious);
 
 	/*
diff --git a/arch/arm/mach-exynos/include/mach/dwmci.h b/arch/arm/mach-exynos/include/mach/dwmci.h
deleted file mode 100644
index 7ce6574..0000000
--- a/arch/arm/mach-exynos/include/mach/dwmci.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/dwmci.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Synopsys DesignWare Mobile Storage for EXYNOS4210
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARM_ARCH_DWMCI_H
-#define __ASM_ARM_ARCH_DWMCI_H __FILE__
-
-#include <linux/mmc/dw_mmc.h>
-
-extern void exynos4_dwmci_set_platdata(struct dw_mci_board *pd);
-
-#endif /* __ASM_ARM_ARCH_DWMCI_H */
diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h
index 35bced6..1f4dc35 100644
--- a/arch/arm/mach-exynos/include/mach/irqs.h
+++ b/arch/arm/mach-exynos/include/mach/irqs.h
@@ -136,6 +136,9 @@
 #define EXYNOS4_IRQ_TSI			IRQ_SPI(115)
 #define EXYNOS4_IRQ_SATA		IRQ_SPI(116)
 
+#define EXYNOS4_IRQ_TMU_TRIG0		COMBINER_IRQ(2, 4)
+#define EXYNOS4_IRQ_TMU_TRIG1		COMBINER_IRQ(3, 4)
+
 #define EXYNOS4_IRQ_SYSMMU_MDMA0_0	COMBINER_IRQ(4, 0)
 #define EXYNOS4_IRQ_SYSMMU_SSS_0	COMBINER_IRQ(4, 1)
 #define EXYNOS4_IRQ_SYSMMU_FIMC0_0	COMBINER_IRQ(4, 2)
@@ -259,11 +262,6 @@
 #define EXYNOS5_IRQ_IEM_IEC		IRQ_SPI(48)
 #define EXYNOS5_IRQ_IEM_APC		IRQ_SPI(49)
 #define EXYNOS5_IRQ_GPIO_C2C		IRQ_SPI(50)
-#define EXYNOS5_IRQ_UART0		IRQ_SPI(51)
-#define EXYNOS5_IRQ_UART1		IRQ_SPI(52)
-#define EXYNOS5_IRQ_UART2		IRQ_SPI(53)
-#define EXYNOS5_IRQ_UART3		IRQ_SPI(54)
-#define EXYNOS5_IRQ_UART4		IRQ_SPI(55)
 #define EXYNOS5_IRQ_IIC			IRQ_SPI(56)
 #define EXYNOS5_IRQ_IIC1		IRQ_SPI(57)
 #define EXYNOS5_IRQ_IIC2		IRQ_SPI(58)
@@ -333,6 +331,11 @@
 #define EXYNOS5_IRQ_FIMC_LITE1		IRQ_SPI(126)
 #define EXYNOS5_IRQ_RP_TIMER		IRQ_SPI(127)
 
+/* EXYNOS5440 */
+
+#define EXYNOS5440_IRQ_UART0		IRQ_SPI(2)
+#define EXYNOS5440_IRQ_UART1		IRQ_SPI(3)
+
 #define EXYNOS5_IRQ_PMU			COMBINER_IRQ(1, 2)
 
 #define EXYNOS5_IRQ_SYSMMU_GSC0_0	COMBINER_IRQ(2, 0)
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index ed4da45..cbb2852 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -43,6 +43,8 @@
 #define EXYNOS4_PA_I2S1			0xE3100000
 #define EXYNOS4_PA_I2S2			0xE2A00000
 
+#define EXYNOS_PA_AUDSS			0x03810000
+
 #define EXYNOS4_PA_PCM0			0x03840000
 #define EXYNOS4_PA_PCM1			0x13980000
 #define EXYNOS4_PA_PCM2			0x13990000
@@ -53,6 +55,7 @@
 #define EXYNOS4_PA_ONENAND_DMA		0x0C600000
 
 #define EXYNOS_PA_CHIPID		0x10000000
+#define EXYNOS5440_PA_CHIPID		0x00160000
 
 #define EXYNOS4_PA_SYSCON		0x10010000
 #define EXYNOS5_PA_SYSCON		0x10050100
@@ -88,6 +91,8 @@
 #define EXYNOS4_PA_TWD			0x10500600
 #define EXYNOS4_PA_L2CC			0x10502000
 
+#define EXYNOS4_PA_TMU			0x100C0000
+
 #define EXYNOS4_PA_MDMA0		0x10810000
 #define EXYNOS4_PA_MDMA1		0x12850000
 #define EXYNOS4_PA_S_MDMA1		0x12840000
@@ -280,7 +285,10 @@
 #define EXYNOS5_PA_UART1		0x12C10000
 #define EXYNOS5_PA_UART2		0x12C20000
 #define EXYNOS5_PA_UART3		0x12C30000
-#define EXYNOS5_SZ_UART			SZ_256
+
+#define EXYNOS5440_PA_UART0		0x000B0000
+#define EXYNOS5440_PA_UART1		0x000C0000
+#define EXYNOS5440_SZ_UART		SZ_256
 
 #define S3C_VA_UARTx(x)			(S3C_VA_UART + ((x) * S3C_UART_OFFSET))
 
diff --git a/arch/arm/mach-exynos/include/mach/regs-audss.h b/arch/arm/mach-exynos/include/mach/regs-audss.h
index ca5a8b6..3b23b0d 100644
--- a/arch/arm/mach-exynos/include/mach/regs-audss.h
+++ b/arch/arm/mach-exynos/include/mach/regs-audss.h
@@ -3,7 +3,7 @@
  * Copyright (c) 2011 Samsung Electronics
  *		http://www.samsung.com
  *
- * Exynos4 Audio SubSystem clock register definitions
+ * Exynos Audio SubSystem clock register definitions
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,4 +15,9 @@
 
 #define EXYNOS4_AUDSS_INT_MEM	(0x03000000)
 
+#define EXYNOS_AUDSSREG(x)		(S5P_VA_AUDSS + (x))
+
+#define EXYNOS_CLKSRC_AUDSS		EXYNOS_AUDSSREG(0x0)
+#define EXYNOS_CLKDIV_AUDSS		EXYNOS_AUDSSREG(0x4)
+#define EXYNOS_CLKGATE_AUDSS		EXYNOS_AUDSSREG(0x8)
 #endif /* _PLAT_REGS_AUDSS_H */
diff --git a/arch/arm/mach-exynos/include/mach/regs-clock.h b/arch/arm/mach-exynos/include/mach/regs-clock.h
index 8c9b38c..d36ad76 100644
--- a/arch/arm/mach-exynos/include/mach/regs-clock.h
+++ b/arch/arm/mach-exynos/include/mach/regs-clock.h
@@ -267,6 +267,9 @@
 #define EXYNOS5_CLKDIV_STATCPU0			EXYNOS_CLKREG(0x00600)
 #define EXYNOS5_CLKDIV_STATCPU1			EXYNOS_CLKREG(0x00604)
 
+#define EXYNOS5_PWR_CTRL1			EXYNOS_CLKREG(0x01020)
+#define EXYNOS5_PWR_CTRL2			EXYNOS_CLKREG(0x01024)
+
 #define EXYNOS5_MPLL_CON0			EXYNOS_CLKREG(0x04100)
 #define EXYNOS5_CLKSRC_CORE1			EXYNOS_CLKREG(0x04204)
 
@@ -344,6 +347,22 @@
 
 #define EXYNOS5_EPLLCON0_LOCKED_SHIFT		(29)
 
+#define PWR_CTRL1_CORE2_DOWN_RATIO		(7 << 28)
+#define PWR_CTRL1_CORE1_DOWN_RATIO		(7 << 16)
+#define PWR_CTRL1_DIV2_DOWN_EN			(1 << 9)
+#define PWR_CTRL1_DIV1_DOWN_EN			(1 << 8)
+#define PWR_CTRL1_USE_CORE1_WFE			(1 << 5)
+#define PWR_CTRL1_USE_CORE0_WFE			(1 << 4)
+#define PWR_CTRL1_USE_CORE1_WFI			(1 << 1)
+#define PWR_CTRL1_USE_CORE0_WFI			(1 << 0)
+
+#define PWR_CTRL2_DIV2_UP_EN			(1 << 25)
+#define PWR_CTRL2_DIV1_UP_EN			(1 << 24)
+#define PWR_CTRL2_DUR_STANDBY2_VAL		(1 << 16)
+#define PWR_CTRL2_DUR_STANDBY1_VAL		(1 << 8)
+#define PWR_CTRL2_CORE2_UP_RATIO		(1 << 4)
+#define PWR_CTRL2_CORE1_UP_RATIO		(1 << 0)
+
 /* Compatibility defines and inclusion */
 
 #include <mach/regs-pmu.h>
diff --git a/arch/arm/mach-exynos/include/mach/regs-mem.h b/arch/arm/mach-exynos/include/mach/regs-mem.h
deleted file mode 100644
index 0368b5a..0000000
--- a/arch/arm/mach-exynos/include/mach/regs-mem.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/regs-mem.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - SROMC and DMC register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_MEM_H
-#define __ASM_ARCH_REGS_MEM_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_DMC0_MEMCON_OFFSET		0x04
-
-#define S5P_DMC0_MEMTYPE_SHIFT		8
-#define S5P_DMC0_MEMTYPE_MASK		0xF
-
-#endif /* __ASM_ARCH_REGS_MEM_H */
diff --git a/arch/arm/mach-exynos/include/mach/regs-pmu.h b/arch/arm/mach-exynos/include/mach/regs-pmu.h
index d4e392b..3f30aa1 100644
--- a/arch/arm/mach-exynos/include/mach/regs-pmu.h
+++ b/arch/arm/mach-exynos/include/mach/regs-pmu.h
@@ -15,6 +15,7 @@
 #include <mach/map.h>
 
 #define S5P_PMUREG(x)				(S5P_VA_PMU + (x))
+#define S5P_SYSREG(x)				(S3C_VA_SYS + (x))
 
 #define S5P_CENTRAL_SEQ_CONFIGURATION		S5P_PMUREG(0x0200)
 
@@ -31,6 +32,7 @@
 
 #define S5P_SWRESET				S5P_PMUREG(0x0400)
 #define EXYNOS_SWRESET				S5P_PMUREG(0x0400)
+#define EXYNOS5440_SWRESET			S5P_PMUREG(0x00C4)
 
 #define S5P_WAKEUP_STAT				S5P_PMUREG(0x0600)
 #define S5P_EINT_WAKEUP_MASK			S5P_PMUREG(0x0604)
@@ -230,7 +232,7 @@
 
 /* For EXYNOS5 */
 
-#define EXYNOS5_USB_CFG						S5P_PMUREG(0x0230)
+#define EXYNOS5_SYS_I2C_CFG					S5P_SYSREG(0x0234)
 
 #define EXYNOS5_AUTO_WDTRESET_DISABLE				S5P_PMUREG(0x0408)
 #define EXYNOS5_MASK_WDTRESET_REQUEST				S5P_PMUREG(0x040C)
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index eadf4b5..92757ff 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -77,6 +77,9 @@ static const struct of_dev_auxdata exynos4_auxdata_lookup[] __initconst = {
 				"exynos4210-spi.2", NULL),
 	OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA0, "dma-pl330.0", NULL),
 	OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA1, "dma-pl330.1", NULL),
+	OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_MDMA1, "dma-pl330.2", NULL),
+	OF_DEV_AUXDATA("samsung,exynos4210-tmu", EXYNOS4_PA_TMU,
+				"exynos-tmu", NULL),
 	{},
 };
 
@@ -94,6 +97,8 @@ static void __init exynos4_dt_machine_init(void)
 
 static char const *exynos4_dt_compat[] __initdata = {
 	"samsung,exynos4210",
+	"samsung,exynos4212",
+	"samsung,exynos4412",
 	NULL
 };
 
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c
index db1cd8e..7bd4f05 100644
--- a/arch/arm/mach-exynos/mach-exynos5-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos5-dt.c
@@ -11,13 +11,18 @@
 
 #include <linux/of_platform.h>
 #include <linux/serial_core.h>
+#include <linux/io.h>
+#include <linux/memblock.h>
+#include <linux/of_fdt.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
 #include <mach/map.h>
+#include <mach/regs-pmu.h>
 
 #include <plat/cpu.h>
 #include <plat/regs-serial.h>
+#include <plat/mfc.h>
 
 #include "common.h"
 
@@ -47,6 +52,20 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
 				"s3c2440-i2c.0", NULL),
 	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(1),
 				"s3c2440-i2c.1", NULL),
+	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(2),
+				"s3c2440-i2c.2", NULL),
+	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(3),
+				"s3c2440-i2c.3", NULL),
+	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(4),
+				"s3c2440-i2c.4", NULL),
+	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(5),
+				"s3c2440-i2c.5", NULL),
+	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(6),
+				"s3c2440-i2c.6", NULL),
+	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(7),
+				"s3c2440-i2c.7", NULL),
+	OF_DEV_AUXDATA("samsung,s3c2440-hdmiphy-i2c", EXYNOS5_PA_IIC(8),
+				"s3c2440-hdmiphy-i2c", NULL),
 	OF_DEV_AUXDATA("samsung,exynos5250-dw-mshc", EXYNOS5_PA_DWMCI0,
 				"dw_mmc.0", NULL),
 	OF_DEV_AUXDATA("samsung,exynos5250-dw-mshc", EXYNOS5_PA_DWMCI1,
@@ -61,6 +80,12 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
 				"exynos4210-spi.1", NULL),
 	OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS5_PA_SPI2,
 				"exynos4210-spi.2", NULL),
+	OF_DEV_AUXDATA("samsung,exynos5-sata-ahci", 0x122F0000,
+				"exynos5-sata", NULL),
+	OF_DEV_AUXDATA("samsung,exynos5-sata-phy", 0x12170000,
+				"exynos5-sata-phy", NULL),
+	OF_DEV_AUXDATA("samsung,exynos5-sata-phy-i2c", 0x121D0000,
+				"exynos5-sata-phy-i2c", NULL),
 	OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA0, "dma-pl330.0", NULL),
 	OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.1", NULL),
 	OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_MDMA1, "dma-pl330.2", NULL),
@@ -72,35 +97,97 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
 				"exynos-gsc.2", NULL),
 	OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC3,
 				"exynos-gsc.3", NULL),
+	OF_DEV_AUXDATA("samsung,exynos5-hdmi", 0x14530000,
+				"exynos5-hdmi", NULL),
+	OF_DEV_AUXDATA("samsung,exynos5-mixer", 0x14450000,
+				"exynos5-mixer", NULL),
+	OF_DEV_AUXDATA("samsung,mfc-v6", 0x11000000, "s5p-mfc-v6", NULL),
+	OF_DEV_AUXDATA("samsung,exynos5250-tmu", 0x10060000,
+				"exynos-tmu", NULL),
+	OF_DEV_AUXDATA("samsung,samsung-i2s", 0x03830000,
+				"samsung-i2s.0", NULL),
+	OF_DEV_AUXDATA("samsung,samsung-i2s", 0x12D60000,
+				"samsung-i2s.1", NULL),
+	OF_DEV_AUXDATA("samsung,samsung-i2s", 0x12D70000,
+				"samsung-i2s.2", NULL),
 	{},
 };
 
-static void __init exynos5250_dt_map_io(void)
+static const struct of_dev_auxdata exynos5440_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5440_PA_UART0,
+				"exynos4210-uart.0", NULL),
+	{},
+};
+
+static void __init exynos5_dt_map_io(void)
 {
+	unsigned long root = of_get_flat_dt_root();
+
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(24000000);
+
+	if (of_flat_dt_is_compatible(root, "samsung,exynos5250"))
+		s3c24xx_init_clocks(24000000);
 }
 
-static void __init exynos5250_dt_machine_init(void)
+static void __init exynos5_dt_machine_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table,
-				exynos5250_auxdata_lookup, NULL);
+	struct device_node *i2c_np;
+	const char *i2c_compat = "samsung,s3c2440-i2c";
+	unsigned int tmp;
+
+	/*
+	 * Exynos5's legacy i2c controller and new high speed i2c
+	 * controller have muxed interrupt sources. By default the
+	 * interrupts for 4-channel HS-I2C controller are enabled.
+	 * If node for first four channels of legacy i2c controller
+	 * are available then re-configure the interrupts via the
+	 * system register.
+	 */
+	for_each_compatible_node(i2c_np, NULL, i2c_compat) {
+		if (of_device_is_available(i2c_np)) {
+			if (of_alias_get_id(i2c_np, "i2c") < 4) {
+				tmp = readl(EXYNOS5_SYS_I2C_CFG);
+				writel(tmp & ~(0x1 << of_alias_get_id(i2c_np, "i2c")),
+						EXYNOS5_SYS_I2C_CFG);
+			}
+		}
+	}
+
+	if (of_machine_is_compatible("samsung,exynos5250"))
+		of_platform_populate(NULL, of_default_bus_match_table,
+				     exynos5250_auxdata_lookup, NULL);
+	else if (of_machine_is_compatible("samsung,exynos5440"))
+		of_platform_populate(NULL, of_default_bus_match_table,
+				     exynos5440_auxdata_lookup, NULL);
 }
 
-static char const *exynos5250_dt_compat[] __initdata = {
+static char const *exynos5_dt_compat[] __initdata = {
 	"samsung,exynos5250",
+	"samsung,exynos5440",
 	NULL
 };
 
+static void __init exynos5_reserve(void)
+{
+	struct s5p_mfc_dt_meminfo mfc_mem;
+
+	/* Reserve memory for MFC only if it's available */
+	mfc_mem.compatible = "samsung,mfc-v6";
+	if (of_scan_flat_dt(s5p_fdt_find_mfc_mem, &mfc_mem))
+		s5p_mfc_reserve_mem(mfc_mem.roff, mfc_mem.rsize, mfc_mem.loff,
+				mfc_mem.lsize);
+}
+
 DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
 	.init_irq	= exynos5_init_irq,
 	.smp		= smp_ops(exynos_smp_ops),
-	.map_io		= exynos5250_dt_map_io,
+	.map_io		= exynos5_dt_map_io,
 	.handle_irq	= gic_handle_irq,
-	.init_machine	= exynos5250_dt_machine_init,
+	.init_machine	= exynos5_dt_machine_init,
 	.init_late	= exynos_init_late,
 	.timer		= &exynos4_timer,
-	.dt_compat	= exynos5250_dt_compat,
+	.dt_compat	= exynos5_dt_compat,
 	.restart        = exynos5_restart,
+	.reserve	= exynos5_reserve,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index c05d7aa..27d4ed8 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -25,7 +25,10 @@
 #include <linux/mmc/host.h>
 #include <linux/fb.h>
 #include <linux/pwm_backlight.h>
+#include <linux/platform_data/i2c-s3c2410.h>
+#include <linux/platform_data/mipi-csis.h>
 #include <linux/platform_data/s3c-hsotg.h>
+#include <linux/platform_data/usb-ehci-s5p.h>
 #include <drm/exynos_drm.h>
 
 #include <video/platform_lcd.h>
@@ -45,14 +48,11 @@
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/sdhci.h>
-#include <linux/platform_data/usb-ehci-s5p.h>
 #include <plat/clock.h>
 #include <plat/gpio-cfg.h>
-#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/mfc.h>
 #include <plat/fimc-core.h>
 #include <plat/camport.h>
-#include <linux/platform_data/mipi-csis.h>
 
 #include <mach/map.h>
 
@@ -113,7 +113,6 @@ static struct s3c_sdhci_platdata nuri_hsmmc0_data __initdata = {
 	.host_caps		= (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
 				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
 				MMC_CAP_ERASE),
-	.host_caps2		= MMC_CAP2_BROKEN_VOLTAGE,
 	.cd_type		= S3C_SDHCI_CD_PERMANENT,
 };
 
@@ -1327,9 +1326,6 @@ static struct platform_device *nuri_devices[] __initdata = {
 	&cam_vdda_fixed_rdev,
 	&cam_8m_12v_fixed_rdev,
 	&exynos4_bus_devfreq,
-#ifdef CONFIG_DRM_EXYNOS
-	&exynos_device_drm,
-#endif
 };
 
 static void __init nuri_map_io(void)
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 9adf491..e6f4191 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -23,7 +23,10 @@
 #include <linux/mfd/max8997.h>
 #include <linux/lcd.h>
 #include <linux/rfkill-gpio.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <linux/platform_data/s3c-hsotg.h>
+#include <linux/platform_data/usb-ehci-s5p.h>
+#include <linux/platform_data/usb-exynos.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
@@ -36,8 +39,6 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/sdhci.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <linux/platform_data/usb-ehci-s5p.h>
 #include <plat/clock.h>
 #include <plat/gpio-cfg.h>
 #include <plat/backlight.h>
@@ -45,7 +46,6 @@
 #include <plat/mfc.h>
 #include <plat/hdmi.h>
 
-#include <linux/platform_data/usb-exynos.h>
 #include <mach/map.h>
 
 #include <drm/exynos_drm.h>
@@ -100,6 +100,7 @@ static struct regulator_consumer_supply __initdata ldo3_consumer[] = {
 	REGULATOR_SUPPLY("vddcore", "s5p-mipi-csis.0"), /* MIPI */
 	REGULATOR_SUPPLY("vdd", "exynos4-hdmi"), /* HDMI */
 	REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"), /* HDMI */
+	REGULATOR_SUPPLY("vusb_a", "s3c-hsotg"), /* OTG */
 };
 static struct regulator_consumer_supply __initdata ldo6_consumer[] = {
 	REGULATOR_SUPPLY("vddio", "s5p-mipi-csis.0"), /* MIPI */
@@ -110,6 +111,7 @@ static struct regulator_consumer_supply __initdata ldo7_consumer[] = {
 static struct regulator_consumer_supply __initdata ldo8_consumer[] = {
 	REGULATOR_SUPPLY("vdd", "s5p-adc"), /* ADC */
 	REGULATOR_SUPPLY("vdd_osc", "exynos4-hdmi"), /* HDMI */
+	REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"), /* OTG */
 };
 static struct regulator_consumer_supply __initdata ldo9_consumer[] = {
 	REGULATOR_SUPPLY("dvdd", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
@@ -709,9 +711,6 @@ static struct platform_device *origen_devices[] __initdata = {
 	&s5p_device_mfc_l,
 	&s5p_device_mfc_r,
 	&s5p_device_mixer,
-#ifdef CONFIG_DRM_EXYNOS
-	&exynos_device_drm,
-#endif
 	&exynos4_device_ohci,
 	&origen_device_gpiokeys,
 	&origen_lcd_hv070wsa,
diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c
index 730f1ac..a1555a7 100644
--- a/arch/arm/mach-exynos/mach-smdk4x12.c
+++ b/arch/arm/mach-exynos/mach-smdk4x12.c
@@ -21,6 +21,7 @@
 #include <linux/pwm_backlight.h>
 #include <linux/regulator/machine.h>
 #include <linux/serial_core.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <linux/platform_data/s3c-hsotg.h>
 
 #include <asm/mach/arch.h>
@@ -34,7 +35,6 @@
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
-#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/keypad.h>
 #include <plat/mfc.h>
 #include <plat/regs-serial.h>
@@ -317,9 +317,6 @@ static struct platform_device *smdk4x12_devices[] __initdata = {
 	&s5p_device_mfc,
 	&s5p_device_mfc_l,
 	&s5p_device_mfc_r,
-#ifdef CONFIG_DRM_EXYNOS
-	&exynos_device_drm,
-#endif
 	&samsung_device_keypad,
 };
 
diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c
index ee4fb1a..063cb94 100644
--- a/arch/arm/mach-exynos/mach-smdkv310.c
+++ b/arch/arm/mach-exynos/mach-smdkv310.c
@@ -20,7 +20,10 @@
 #include <linux/input.h>
 #include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <linux/platform_data/s3c-hsotg.h>
+#include <linux/platform_data/usb-ehci-s5p.h>
+#include <linux/platform_data/usb-exynos.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
@@ -35,16 +38,13 @@
 #include <plat/fb.h>
 #include <plat/keypad.h>
 #include <plat/sdhci.h>
-#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 #include <plat/backlight.h>
 #include <plat/mfc.h>
-#include <linux/platform_data/usb-ehci-s5p.h>
 #include <plat/clock.h>
 #include <plat/hdmi.h>
 
 #include <mach/map.h>
-#include <linux/platform_data/usb-exynos.h>
 
 #include <drm/exynos_drm.h>
 #include "common.h"
@@ -300,9 +300,6 @@ static struct platform_device *smdkv310_devices[] __initdata = {
 	&s5p_device_fimc_md,
 	&s5p_device_g2d,
 	&s5p_device_jpeg,
-#ifdef CONFIG_DRM_EXYNOS
-	&exynos_device_drm,
-#endif
 	&exynos4_device_ac97,
 	&exynos4_device_i2s0,
 	&exynos4_device_ohci,
diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
index ebc9dd3..9e3340f 100644
--- a/arch/arm/mach-exynos/mach-universal_c210.c
+++ b/arch/arm/mach-exynos/mach-universal_c210.c
@@ -23,6 +23,8 @@
 #include <linux/i2c-gpio.h>
 #include <linux/i2c/mcs.h>
 #include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/platform_data/i2c-s3c2410.h>
+#include <linux/platform_data/mipi-csis.h>
 #include <linux/platform_data/s3c-hsotg.h>
 #include <drm/exynos_drm.h>
 
@@ -35,7 +37,6 @@
 #include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
-#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 #include <plat/fb.h>
 #include <plat/mfc.h>
@@ -43,7 +44,6 @@
 #include <plat/fimc-core.h>
 #include <plat/s5p-time.h>
 #include <plat/camport.h>
-#include <linux/platform_data/mipi-csis.h>
 
 #include <mach/map.h>
 
@@ -754,7 +754,6 @@ static struct s3c_sdhci_platdata universal_hsmmc0_data __initdata = {
 	.max_width		= 8,
 	.host_caps		= (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
 				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-	.host_caps2		= MMC_CAP2_BROKEN_VOLTAGE,
 	.cd_type		= S3C_SDHCI_CD_PERMANENT,
 };
 
@@ -1081,9 +1080,6 @@ static struct platform_device *universal_devices[] __initdata = {
 	&s5p_device_onenand,
 	&s5p_device_fimd0,
 	&s5p_device_jpeg,
-#ifdef CONFIG_DRM_EXYNOS
-	&exynos_device_drm,
-#endif
 	&s3c_device_usb_hsotg,
 	&s5p_device_mfc,
 	&s5p_device_mfc_l,
diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
index b601fb8..57668eb 100644
--- a/arch/arm/mach-exynos/mct.c
+++ b/arch/arm/mach-exynos/mct.c
@@ -19,7 +19,9 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/percpu.h>
+#include <linux/of.h>
 
+#include <asm/arch_timer.h>
 #include <asm/hardware/gic.h>
 #include <asm/localtimer.h>
 
@@ -476,8 +478,13 @@ static void __init exynos4_timer_resources(void)
 #endif /* CONFIG_LOCAL_TIMERS */
 }
 
-static void __init exynos4_timer_init(void)
+static void __init exynos_timer_init(void)
 {
+	if (soc_is_exynos5440()) {
+		arch_timer_of_register();
+		return;
+	}
+
 	if ((soc_is_exynos4210()) || (soc_is_exynos5250()))
 		mct_int_type = MCT_INT_SPI;
 	else
@@ -489,5 +496,5 @@ static void __init exynos4_timer_init(void)
 }
 
 struct sys_timer exynos4_timer = {
-	.init		= exynos4_timer_init,
+	.init		= exynos_timer_init,
 };
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index f93d820..4ca8ff1 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -36,8 +36,22 @@
 
 extern void exynos4_secondary_startup(void);
 
-#define CPU1_BOOT_REG		(samsung_rev() == EXYNOS4210_REV_1_1 ? \
-				S5P_INFORM5 : S5P_VA_SYSRAM)
+static inline void __iomem *cpu_boot_reg_base(void)
+{
+	if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
+		return S5P_INFORM5;
+	return S5P_VA_SYSRAM;
+}
+
+static inline void __iomem *cpu_boot_reg(int cpu)
+{
+	void __iomem *boot_reg;
+
+	boot_reg = cpu_boot_reg_base();
+	if (soc_is_exynos4412())
+		boot_reg += 4*cpu;
+	return boot_reg;
+}
 
 /*
  * Write pen_release in a way that is guaranteed to be visible to all
@@ -84,6 +98,7 @@ static void __cpuinit exynos_secondary_init(unsigned int cpu)
 static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	unsigned long timeout;
+	unsigned long phys_cpu = cpu_logical_map(cpu);
 
 	/*
 	 * Set synchronisation state between this boot processor
@@ -99,7 +114,7 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct
 	 * Note that "pen_release" is the hardware CPU ID, whereas
 	 * "cpu" is Linux's internal ID.
 	 */
-	write_pen_release(cpu_logical_map(cpu));
+	write_pen_release(phys_cpu);
 
 	if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) {
 		__raw_writel(S5P_CORE_LOCAL_PWR_EN,
@@ -133,7 +148,7 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct
 		smp_rmb();
 
 		__raw_writel(virt_to_phys(exynos4_secondary_startup),
-			CPU1_BOOT_REG);
+							cpu_boot_reg(phys_cpu));
 		gic_raise_softirq(cpumask_of(cpu), 0);
 
 		if (pen_release == -1)
@@ -181,6 +196,8 @@ static void __init exynos_smp_init_cpus(void)
 
 static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
 {
+	int i;
+
 	if (!soc_is_exynos5250())
 		scu_enable(scu_base_addr());
 
@@ -190,8 +207,9 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
 	 * until it receives a soft interrupt, and then the
 	 * secondary CPU branches to this address.
 	 */
-	__raw_writel(virt_to_phys(exynos4_secondary_startup),
-			CPU1_BOOT_REG);
+	for (i = 1; i < max_cpus; ++i)
+		__raw_writel(virt_to_phys(exynos4_secondary_startup),
+					cpu_boot_reg(cpu_logical_map(i)));
 }
 
 struct smp_operations exynos_smp_ops __initdata = {
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index c06c992..b9b539c 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -62,6 +62,10 @@ static struct sleep_save exynos4_vpll_save[] = {
 	SAVE_ITEM(EXYNOS4_VPLL_CON1),
 };
 
+static struct sleep_save exynos5_sys_save[] = {
+	SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
+};
+
 static struct sleep_save exynos_core_save[] = {
 	/* SROM side */
 	SAVE_ITEM(S5P_SROM_BW),
@@ -81,6 +85,9 @@ static int exynos_cpu_suspend(unsigned long arg)
 	outer_flush_all();
 #endif
 
+	if (soc_is_exynos5250())
+		flush_cache_all();
+
 	/* issue the standby signal into the pm unit. */
 	cpu_do_idle();
 
@@ -98,6 +105,7 @@ static void exynos_pm_prepare(void)
 		s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
 		s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
 	} else {
+		s3c_pm_do_save(exynos5_sys_save, ARRAY_SIZE(exynos5_sys_save));
 		/* Disable USE_RETENTION of JPEG_MEM_OPTION */
 		tmp = __raw_readl(EXYNOS5_JPEG_MEM_OPTION);
 		tmp &= ~EXYNOS5_OPTION_USE_RETENTION;
@@ -301,6 +309,10 @@ static void exynos_pm_resume(void)
 	__raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
 	__raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
 
+	if (soc_is_exynos5250())
+		s3c_pm_do_restore(exynos5_sys_save,
+			ARRAY_SIZE(exynos5_sys_save));
+
 	s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
 
 	if (!soc_is_exynos5250()) {
@@ -312,6 +324,10 @@ static void exynos_pm_resume(void)
 	}
 
 early_wakeup:
+
+	/* Clear SLEEP mode set in INFORM1 */
+	__raw_writel(0x0, S5P_INFORM1);
+
 	return;
 }
 
diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c
index c0bc83a..9f1351d 100644
--- a/arch/arm/mach-exynos/pm_domains.c
+++ b/arch/arm/mach-exynos/pm_domains.c
@@ -19,6 +19,8 @@
 #include <linux/pm_domain.h>
 #include <linux/delay.h>
 #include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/sched.h>
 
 #include <mach/regs-pmu.h>
 #include <plat/devs.h>
@@ -83,12 +85,88 @@ static struct exynos_pm_domain PD = {			\
 }
 
 #ifdef CONFIG_OF
+static void exynos_add_device_to_domain(struct exynos_pm_domain *pd,
+					 struct device *dev)
+{
+	int ret;
+
+	dev_dbg(dev, "adding to power domain %s\n", pd->pd.name);
+
+	while (1) {
+		ret = pm_genpd_add_device(&pd->pd, dev);
+		if (ret != -EAGAIN)
+			break;
+		cond_resched();
+	}
+
+	pm_genpd_dev_need_restore(dev, true);
+}
+
+static void exynos_remove_device_from_domain(struct device *dev)
+{
+	struct generic_pm_domain *genpd = dev_to_genpd(dev);
+	int ret;
+
+	dev_dbg(dev, "removing from power domain %s\n", genpd->name);
+
+	while (1) {
+		ret = pm_genpd_remove_device(genpd, dev);
+		if (ret != -EAGAIN)
+			break;
+		cond_resched();
+	}
+}
+
+static void exynos_read_domain_from_dt(struct device *dev)
+{
+	struct platform_device *pd_pdev;
+	struct exynos_pm_domain *pd;
+	struct device_node *node;
+
+	node = of_parse_phandle(dev->of_node, "samsung,power-domain", 0);
+	if (!node)
+		return;
+	pd_pdev = of_find_device_by_node(node);
+	if (!pd_pdev)
+		return;
+	pd = platform_get_drvdata(pd_pdev);
+	exynos_add_device_to_domain(pd, dev);
+}
+
+static int exynos_pm_notifier_call(struct notifier_block *nb,
+				    unsigned long event, void *data)
+{
+	struct device *dev = data;
+
+	switch (event) {
+	case BUS_NOTIFY_BIND_DRIVER:
+		if (dev->of_node)
+			exynos_read_domain_from_dt(dev);
+
+		break;
+
+	case BUS_NOTIFY_UNBOUND_DRIVER:
+		exynos_remove_device_from_domain(dev);
+
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block platform_nb = {
+	.notifier_call = exynos_pm_notifier_call,
+};
+
 static __init int exynos_pm_dt_parse_domains(void)
 {
+	struct platform_device *pdev;
 	struct device_node *np;
 
 	for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") {
 		struct exynos_pm_domain *pd;
+		int on;
+
+		pdev = of_find_device_by_node(np);
 
 		pd = kzalloc(sizeof(*pd), GFP_KERNEL);
 		if (!pd) {
@@ -97,15 +175,22 @@ static __init int exynos_pm_dt_parse_domains(void)
 			return -ENOMEM;
 		}
 
-		if (of_get_property(np, "samsung,exynos4210-pd-off", NULL))
-			pd->is_off = true;
-		pd->name = np->name;
+		pd->pd.name = kstrdup(np->name, GFP_KERNEL);
+		pd->name = pd->pd.name;
 		pd->base = of_iomap(np, 0);
 		pd->pd.power_off = exynos_pd_power_off;
 		pd->pd.power_on = exynos_pd_power_on;
 		pd->pd.of_node = np;
-		pm_genpd_init(&pd->pd, NULL, false);
+
+		platform_set_drvdata(pdev, pd);
+
+		on = __raw_readl(pd->base + 0x4) & S5P_INT_LOCAL_PWR_EN;
+
+		pm_genpd_init(&pd->pd, NULL, !on);
 	}
+
+	bus_register_notifier(&platform_bus_type, &platform_nb);
+
 	return 0;
 }
 #else
diff --git a/arch/arm/mach-exynos/setup-i2c0.c b/arch/arm/mach-exynos/setup-i2c0.c
index 5700f23..e2d9dfb 100644
--- a/arch/arm/mach-exynos/setup-i2c0.c
+++ b/arch/arm/mach-exynos/setup-i2c0.c
@@ -20,7 +20,7 @@ struct platform_device; /* don't need the contents */
 
 void s3c_i2c0_cfg_gpio(struct platform_device *dev)
 {
-	if (soc_is_exynos5250())
+	if (soc_is_exynos5250() || soc_is_exynos5440())
 		/* will be implemented with gpio function */
 		return;
 
diff --git a/arch/arm/mach-highbank/Kconfig b/arch/arm/mach-highbank/Kconfig
index 0e1d0a4..551c97e 100644
--- a/arch/arm/mach-highbank/Kconfig
+++ b/arch/arm/mach-highbank/Kconfig
@@ -1,5 +1,5 @@
 config ARCH_HIGHBANK
-	bool "Calxeda ECX-1000 (Highbank)" if ARCH_MULTI_V7
+	bool "Calxeda ECX-1000/2000 (Highbank/Midway)" if ARCH_MULTI_V7
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARM_AMBA
 	select ARM_GIC
diff --git a/arch/arm/mach-highbank/Makefile b/arch/arm/mach-highbank/Makefile
index 3ec8bdd..8a1ef57 100644
--- a/arch/arm/mach-highbank/Makefile
+++ b/arch/arm/mach-highbank/Makefile
@@ -3,7 +3,6 @@ obj-y					:= highbank.o system.o smc.o
 plus_sec := $(call as-instr,.arch_extension sec,+sec)
 AFLAGS_smc.o				:=-Wa,-march=armv7-a$(plus_sec)
 
-obj-$(CONFIG_DEBUG_HIGHBANK_UART)	+= lluart.o
 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 286ec82..80235b4 100644
--- a/arch/arm/mach-highbank/core.h
+++ b/arch/arm/mach-highbank/core.h
@@ -1,12 +1,10 @@
+#ifndef __HIGHBANK_CORE_H
+#define __HIGHBANK_CORE_H
+
 extern void highbank_set_cpu_jump(int cpu, void *jump_addr);
 extern void highbank_clocks_init(void);
 extern void highbank_restart(char, const char *);
 extern void __iomem *scu_base_addr;
-#ifdef CONFIG_DEBUG_HIGHBANK_UART
-extern void highbank_lluart_map_io(void);
-#else
-static inline void highbank_lluart_map_io(void) {}
-#endif
 
 #ifdef CONFIG_PM_SLEEP
 extern void highbank_pm_init(void);
@@ -18,3 +16,5 @@ 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 40e36a5..dc24816 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -26,9 +26,9 @@
 #include <linux/smp.h>
 #include <linux/amba/bus.h>
 
+#include <asm/arch_timer.h>
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
-#include <asm/smp_scu.h>
 #include <asm/smp_twd.h>
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/timer-sp.h>
@@ -42,16 +42,7 @@
 #include "sysregs.h"
 
 void __iomem *sregs_base;
-
-#define HB_SCU_VIRT_BASE	0xfee00000
-void __iomem *scu_base_addr = ((void __iomem *)(HB_SCU_VIRT_BASE));
-
-static struct map_desc scu_io_desc __initdata = {
-	.virtual	= HB_SCU_VIRT_BASE,
-	.pfn		= 0, /* run-time */
-	.length		= SZ_4K,
-	.type		= MT_DEVICE,
-};
+void __iomem *scu_base_addr;
 
 static void __init highbank_scu_map_io(void)
 {
@@ -60,14 +51,7 @@ static void __init highbank_scu_map_io(void)
 	/* Get SCU base */
 	asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
 
-	scu_io_desc.pfn = __phys_to_pfn(base);
-	iotable_init(&scu_io_desc, 1);
-}
-
-static void __init highbank_map_io(void)
-{
-	highbank_scu_map_io();
-	highbank_lluart_map_io();
+	scu_base_addr = ioremap(base, SZ_4K);
 }
 
 #define HB_JUMP_TABLE_PHYS(cpu)		(0x40 + (0x10 * (cpu)))
@@ -83,6 +67,7 @@ void highbank_set_cpu_jump(int cpu, void *jump_addr)
 }
 
 const static struct of_device_id irq_match[] = {
+	{ .compatible = "arm,cortex-a15-gic", .data = gic_of_init, },
 	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
 	{}
 };
@@ -99,6 +84,9 @@ static void __init highbank_init_irq(void)
 {
 	of_irq_init(irq_match);
 
+	if (of_find_compatible_node(NULL, NULL, "arm,cortex-a9"))
+		highbank_scu_map_io();
+
 #ifdef CONFIG_CACHE_L2X0
 	/* Enable PL310 L2 Cache controller */
 	highbank_smc1(0x102, 0x1);
@@ -136,6 +124,9 @@ static void __init highbank_timer_init(void)
 	sp804_clockevents_init(timer_base, irq, "timer0");
 
 	twd_local_timer_of_register();
+
+	arch_timer_of_register();
+	arch_timer_sched_clock_init();
 }
 
 static struct sys_timer highbank_timer = {
@@ -145,7 +136,6 @@ static struct sys_timer highbank_timer = {
 static void highbank_power_off(void)
 {
 	hignbank_set_pwr_shutdown();
-	scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
 
 	while (1)
 		cpu_do_idle();
@@ -211,12 +201,13 @@ static void __init highbank_init(void)
 
 static const char *highbank_match[] __initconst = {
 	"calxeda,highbank",
+	"calxeda,ecx-2000",
 	NULL,
 };
 
 DT_MACHINE_START(HIGHBANK, "Highbank")
 	.smp		= smp_ops(highbank_smp_ops),
-	.map_io		= highbank_map_io,
+	.map_io		= debug_ll_io_init,
 	.init_irq	= highbank_init_irq,
 	.timer		= &highbank_timer,
 	.handle_irq	= gic_handle_irq,
diff --git a/arch/arm/mach-highbank/hotplug.c b/arch/arm/mach-highbank/hotplug.c
index 2c1b8c3..7b60fac 100644
--- a/arch/arm/mach-highbank/hotplug.c
+++ b/arch/arm/mach-highbank/hotplug.c
@@ -14,13 +14,11 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/smp.h>
 
-#include <asm/smp_scu.h>
 #include <asm/cacheflush.h>
 
 #include "core.h"
+#include "sysregs.h"
 
 extern void secondary_startup(void);
 
@@ -33,7 +31,7 @@ void __ref highbank_cpu_die(unsigned int cpu)
 	flush_cache_all();
 
 	highbank_set_cpu_jump(cpu, secondary_startup);
-	scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+	highbank_set_core_pwr();
 
 	cpu_do_idle();
 
diff --git a/arch/arm/mach-highbank/lluart.c b/arch/arm/mach-highbank/lluart.c
deleted file mode 100644
index 3715750..0000000
--- a/arch/arm/mach-highbank/lluart.c
+++ /dev/null
@@ -1,34 +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/init.h>
-#include <asm/page.h>
-#include <asm/sizes.h>
-#include <asm/mach/map.h>
-
-#define HB_DEBUG_LL_PHYS_BASE	0xfff36000
-#define HB_DEBUG_LL_VIRT_BASE	0xfee36000
-
-static struct map_desc lluart_io_desc __initdata = {
-	.virtual	= HB_DEBUG_LL_VIRT_BASE,
-	.pfn		= __phys_to_pfn(HB_DEBUG_LL_PHYS_BASE),
-	.length		= SZ_4K,
-	.type		= MT_DEVICE,
-};
-
-void __init highbank_lluart_map_io(void)
-{
-	iotable_init(&lluart_io_desc, 1);
-}
diff --git a/arch/arm/mach-highbank/platsmp.c b/arch/arm/mach-highbank/platsmp.c
index fa9560e..1129957 100644
--- a/arch/arm/mach-highbank/platsmp.c
+++ b/arch/arm/mach-highbank/platsmp.c
@@ -42,9 +42,7 @@ static int __cpuinit highbank_boot_secondary(unsigned int cpu, struct task_struc
  */
 static void __init highbank_smp_init_cpus(void)
 {
-	unsigned int i, ncores;
-
-	ncores = scu_get_core_count(scu_base_addr);
+	unsigned int i, ncores = 4;
 
 	/* sanity check */
 	if (ncores > NR_CPUS) {
@@ -65,7 +63,8 @@ static void __init highbank_smp_prepare_cpus(unsigned int max_cpus)
 {
 	int i;
 
-	scu_enable(scu_base_addr);
+	if (scu_base_addr)
+		scu_enable(scu_base_addr);
 
 	/*
 	 * Write the address of secondary startup into the jump table
diff --git a/arch/arm/mach-highbank/pm.c b/arch/arm/mach-highbank/pm.c
index de866f2..74aa135 100644
--- a/arch/arm/mach-highbank/pm.c
+++ b/arch/arm/mach-highbank/pm.c
@@ -19,7 +19,6 @@
 #include <linux/suspend.h>
 
 #include <asm/proc-fns.h>
-#include <asm/smp_scu.h>
 #include <asm/suspend.h>
 
 #include "core.h"
@@ -35,8 +34,6 @@ static int highbank_pm_enter(suspend_state_t state)
 {
 	hignbank_set_pwr_suspend();
 	highbank_set_cpu_jump(0, cpu_resume);
-
-	scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
 	cpu_suspend(0, highbank_suspend_finish);
 
 	return 0;
diff --git a/arch/arm/mach-highbank/sysregs.h b/arch/arm/mach-highbank/sysregs.h
index 0e91338..e13e8ea 100644
--- a/arch/arm/mach-highbank/sysregs.h
+++ b/arch/arm/mach-highbank/sysregs.h
@@ -17,6 +17,10 @@
 #define _MACH_HIGHBANK__SYSREGS_H_
 
 #include <linux/io.h>
+#include <linux/smp.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+#include "core.h"
 
 extern void __iomem *sregs_base;
 
@@ -29,24 +33,39 @@ extern void __iomem *sregs_base;
 #define HB_PWR_HARD_RESET		2
 #define HB_PWR_SHUTDOWN			3
 
+#define SREG_CPU_PWR_CTRL(c)		(0x200 + ((c) * 4))
+
+static inline void highbank_set_core_pwr(void)
+{
+	int cpu = cpu_logical_map(smp_processor_id());
+	if (scu_base_addr)
+		scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+	else
+		writel_relaxed(1, sregs_base + SREG_CPU_PWR_CTRL(cpu));
+}
+
 static inline void hignbank_set_pwr_suspend(void)
 {
 	writel(HB_PWR_SUSPEND, sregs_base + HB_SREG_A9_PWR_REQ);
+	highbank_set_core_pwr();
 }
 
 static inline void hignbank_set_pwr_shutdown(void)
 {
 	writel(HB_PWR_SHUTDOWN, sregs_base + HB_SREG_A9_PWR_REQ);
+	highbank_set_core_pwr();
 }
 
 static inline void hignbank_set_pwr_soft_reset(void)
 {
 	writel(HB_PWR_SOFT_RESET, sregs_base + HB_SREG_A9_PWR_REQ);
+	highbank_set_core_pwr();
 }
 
 static inline void hignbank_set_pwr_hard_reset(void)
 {
 	writel(HB_PWR_HARD_RESET, sregs_base + HB_SREG_A9_PWR_REQ);
+	highbank_set_core_pwr();
 }
 
 #endif
diff --git a/arch/arm/mach-highbank/system.c b/arch/arm/mach-highbank/system.c
index 86e37cd..aed96ad 100644
--- a/arch/arm/mach-highbank/system.c
+++ b/arch/arm/mach-highbank/system.c
@@ -14,7 +14,6 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include <linux/io.h>
-#include <asm/smp_scu.h>
 #include <asm/proc-fns.h>
 
 #include "core.h"
@@ -27,7 +26,6 @@ void highbank_restart(char mode, const char *cmd)
 	else
 		hignbank_set_pwr_soft_reset();
 
-	scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
 	while (1)
 		cpu_do_idle();
 }
diff --git a/arch/arm/mach-imx/3ds_debugboard.c b/arch/arm/mach-imx/3ds_debugboard.c
new file mode 100644
index 0000000..1343773
--- /dev/null
+++ b/arch/arm/mach-imx/3ds_debugboard.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2010 Jason Wang <jason77.wang@gmail.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/smsc911x.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+
+#include "hardware.h"
+
+/* LAN9217 ethernet base address */
+#define LAN9217_BASE_ADDR(n)	(n + 0x0)
+/* External UART */
+#define UARTA_BASE_ADDR(n)	(n + 0x8000)
+#define UARTB_BASE_ADDR(n)	(n + 0x10000)
+
+#define BOARD_IO_ADDR(n)	(n + 0x20000)
+/* LED switchs */
+#define LED_SWITCH_REG		0x00
+/* buttons */
+#define SWITCH_BUTTONS_REG	0x08
+/* status, interrupt */
+#define INTR_STATUS_REG	0x10
+#define INTR_MASK_REG		0x38
+#define INTR_RESET_REG		0x20
+/* magic word for debug CPLD */
+#define MAGIC_NUMBER1_REG	0x40
+#define MAGIC_NUMBER2_REG	0x48
+/* CPLD code version */
+#define CPLD_CODE_VER_REG	0x50
+/* magic word for debug CPLD */
+#define MAGIC_NUMBER3_REG	0x58
+/* module reset register*/
+#define MODULE_RESET_REG	0x60
+/* CPU ID and Personality ID */
+#define MCU_BOARD_ID_REG	0x68
+
+#define MXC_MAX_EXP_IO_LINES	16
+
+/* interrupts like external uart , external ethernet etc*/
+#define EXPIO_INT_ENET		0
+#define EXPIO_INT_XUART_A	1
+#define EXPIO_INT_XUART_B	2
+#define EXPIO_INT_BUTTON_A	3
+#define EXPIO_INT_BUTTON_B	4
+
+static void __iomem *brd_io;
+static struct irq_domain *domain;
+
+static struct resource smsc911x_resources[] = {
+	{
+		.flags = IORESOURCE_MEM,
+	} , {
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct smsc911x_platform_config smsc911x_config = {
+	.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.flags = SMSC911X_USE_32BIT | SMSC911X_FORCE_INTERNAL_PHY,
+};
+
+static struct platform_device smsc_lan9217_device = {
+	.name = "smsc911x",
+	.id = -1,
+	.dev = {
+		.platform_data = &smsc911x_config,
+	},
+	.num_resources = ARRAY_SIZE(smsc911x_resources),
+	.resource = smsc911x_resources,
+};
+
+static void mxc_expio_irq_handler(u32 irq, struct irq_desc *desc)
+{
+	u32 imr_val;
+	u32 int_valid;
+	u32 expio_irq;
+
+	/* irq = gpio irq number */
+	desc->irq_data.chip->irq_mask(&desc->irq_data);
+
+	imr_val = __raw_readw(brd_io + INTR_MASK_REG);
+	int_valid = __raw_readw(brd_io + INTR_STATUS_REG) & ~imr_val;
+
+	expio_irq = 0;
+	for (; int_valid != 0; int_valid >>= 1, expio_irq++) {
+		if ((int_valid & 1) == 0)
+			continue;
+		generic_handle_irq(irq_find_mapping(domain, expio_irq));
+	}
+
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
+	desc->irq_data.chip->irq_unmask(&desc->irq_data);
+}
+
+/*
+ * Disable an expio pin's interrupt by setting the bit in the imr.
+ * Irq is an expio virtual irq number
+ */
+static void expio_mask_irq(struct irq_data *d)
+{
+	u16 reg;
+	u32 expio = d->hwirq;
+
+	reg = __raw_readw(brd_io + INTR_MASK_REG);
+	reg |= (1 << expio);
+	__raw_writew(reg, brd_io + INTR_MASK_REG);
+}
+
+static void expio_ack_irq(struct irq_data *d)
+{
+	u32 expio = d->hwirq;
+
+	__raw_writew(1 << expio, brd_io + INTR_RESET_REG);
+	__raw_writew(0, brd_io + INTR_RESET_REG);
+	expio_mask_irq(d);
+}
+
+static void expio_unmask_irq(struct irq_data *d)
+{
+	u16 reg;
+	u32 expio = d->hwirq;
+
+	reg = __raw_readw(brd_io + INTR_MASK_REG);
+	reg &= ~(1 << expio);
+	__raw_writew(reg, brd_io + INTR_MASK_REG);
+}
+
+static struct irq_chip expio_irq_chip = {
+	.irq_ack = expio_ack_irq,
+	.irq_mask = expio_mask_irq,
+	.irq_unmask = expio_unmask_irq,
+};
+
+static struct regulator_consumer_supply dummy_supplies[] = {
+	REGULATOR_SUPPLY("vdd33a", "smsc911x"),
+	REGULATOR_SUPPLY("vddvario", "smsc911x"),
+};
+
+int __init mxc_expio_init(u32 base, u32 intr_gpio)
+{
+	u32 p_irq = gpio_to_irq(intr_gpio);
+	int irq_base;
+	int i;
+
+	brd_io = ioremap(BOARD_IO_ADDR(base), SZ_4K);
+	if (brd_io == NULL)
+		return -ENOMEM;
+
+	if ((__raw_readw(brd_io + MAGIC_NUMBER1_REG) != 0xAAAA) ||
+	    (__raw_readw(brd_io + MAGIC_NUMBER2_REG) != 0x5555) ||
+	    (__raw_readw(brd_io + MAGIC_NUMBER3_REG) != 0xCAFE)) {
+		pr_info("3-Stack Debug board not detected\n");
+		iounmap(brd_io);
+		brd_io = NULL;
+		return -ENODEV;
+	}
+
+	pr_info("3-Stack Debug board detected, rev = 0x%04X\n",
+		readw(brd_io + CPLD_CODE_VER_REG));
+
+	/*
+	 * Configure INT line as GPIO input
+	 */
+	gpio_request(intr_gpio, "expio_pirq");
+	gpio_direction_input(intr_gpio);
+
+	/* disable the interrupt and clear the status */
+	__raw_writew(0, brd_io + INTR_MASK_REG);
+	__raw_writew(0xFFFF, brd_io + INTR_RESET_REG);
+	__raw_writew(0, brd_io + INTR_RESET_REG);
+	__raw_writew(0x1F, brd_io + INTR_MASK_REG);
+
+	irq_base = irq_alloc_descs(-1, 0, MXC_MAX_EXP_IO_LINES, numa_node_id());
+	WARN_ON(irq_base < 0);
+
+	domain = irq_domain_add_legacy(NULL, MXC_MAX_EXP_IO_LINES, irq_base, 0,
+				       &irq_domain_simple_ops, NULL);
+	WARN_ON(!domain);
+
+	for (i = irq_base; i < irq_base + MXC_MAX_EXP_IO_LINES; i++) {
+		irq_set_chip_and_handler(i, &expio_irq_chip, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+	irq_set_irq_type(p_irq, IRQF_TRIGGER_LOW);
+	irq_set_chained_handler(p_irq, mxc_expio_irq_handler);
+
+	/* Register Lan device on the debugboard */
+	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+
+	smsc911x_resources[0].start = LAN9217_BASE_ADDR(base);
+	smsc911x_resources[0].end = LAN9217_BASE_ADDR(base) + 0x100 - 1;
+	smsc911x_resources[1].start = irq_find_mapping(domain, EXPIO_INT_ENET);
+	smsc911x_resources[1].end = irq_find_mapping(domain, EXPIO_INT_ENET);
+	platform_device_register(&smsc_lan9217_device);
+
+	return 0;
+}
diff --git a/arch/arm/mach-imx/3ds_debugboard.h b/arch/arm/mach-imx/3ds_debugboard.h
new file mode 100644
index 0000000..9fd6cb3
--- /dev/null
+++ b/arch/arm/mach-imx/3ds_debugboard.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __ASM_ARCH_MXC_3DS_DB_H__
+#define __ASM_ARCH_MXC_3DS_DB_H__
+
+extern int __init mxc_expio_init(u32 base, u32 intr_gpio);
+
+#endif /* __ASM_ARCH_MXC_3DS_DB_H__ */
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 8d27658..1ad0d76 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -1,3 +1,70 @@
+config ARCH_MXC
+	bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_PATCH_PHYS_VIRT
+	select AUTO_ZRELADDR if !ZBOOT_ROM
+	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_IRQ_CHIP
+	select MULTI_IRQ_HANDLER
+	select SPARSE_IRQ
+	select USE_OF
+	help
+	  Support for Freescale MXC/iMX-based family of processors
+
+menu "Freescale i.MX support"
+	depends on ARCH_MXC
+
+config MXC_IRQ_PRIOR
+	bool "Use IRQ priority"
+	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.
+	  This may be useful in embedded applications, where are strong
+	  requirements for timing.
+	  Say N here, unless you have a specialized requirement.
+
+config MXC_TZIC
+	bool
+
+config MXC_AVIC
+	bool
+
+config MXC_DEBUG_BOARD
+	bool "Enable MXC debug board(for 3-stack)"
+	help
+	  The debug board is an integral part of the MXC 3-stack(PDK)
+	  platforms, it can be attached or removed from the peripheral
+	  board. On debug board, several debug devices(ethernet, UART,
+	  buttons, LEDs and JTAG) are implemented. Between the MCU and
+	  these devices, a CPLD is added as a bridge which performs
+	  data/address de-multiplexing and decode, signal level shift,
+	  interrupt control and various board functions.
+
+config HAVE_EPIT
+	bool
+
+config MXC_USE_EPIT
+	bool "Use EPIT instead of GPT"
+	depends on HAVE_EPIT
+	help
+	  Use EPIT as the system timer on systems that have it. Normally you
+	  don't have a reason to do so as the EPIT has the same features and
+	  uses the same clocks as the GPT. Anyway, on some systems the GPT
+	  may be in use for other purposes.
+
+config MXC_ULPI
+	bool
+
+config ARCH_HAS_RNGA
+	bool
+
+config IRAM_ALLOC
+	bool
+	select GENERIC_ALLOCATOR
+
 config HAVE_IMX_GPC
 	bool
 
@@ -5,6 +72,12 @@ config HAVE_IMX_MMDC
 	bool
 
 config HAVE_IMX_SRC
+	def_bool y if SMP
+
+config IMX_HAVE_IOMUX_V1
+	bool
+
+config ARCH_MXC_IOMUX_V3
 	bool
 
 config ARCH_MX1
@@ -104,7 +177,7 @@ config	SOC_IMX51
 	select PINCTRL_IMX51
 	select SOC_IMX5
 
-if ARCH_IMX_V4_V5
+if ARCH_MULTI_V4T
 
 comment "MX1 platforms:"
 config MACH_MXLADS
@@ -133,6 +206,10 @@ config MACH_APF9328
 	help
 	  Say Yes here if you are using the Armadeus APF9328 development board
 
+endif
+
+if ARCH_MULTI_V5
+
 comment "MX21 platforms:"
 
 config MACH_MX21ADS
@@ -195,6 +272,13 @@ config MACH_EUKREA_MBIMXSD25_BASEBOARD
 
 endchoice
 
+config MACH_IMX25_DT
+	bool "Support i.MX25 platforms from device tree"
+	select SOC_IMX25
+	help
+	  Include support for Freescale i.MX25 based platforms
+	  using the device tree for discovery
+
 comment "MX27 platforms:"
 
 config MACH_MX27ADS
@@ -317,6 +401,7 @@ config MACH_IMX27_VISSTRIM_M10
 	select IMX_HAVE_PLATFORM_IMX_SSI
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_MX2_CAMERA
+	select IMX_HAVE_PLATFORM_MX2_EMMA
 	select IMX_HAVE_PLATFORM_MXC_EHCI
 	select IMX_HAVE_PLATFORM_MXC_MMC
 	select LEDS_GPIO_REGISTER
@@ -384,7 +469,7 @@ config MACH_IMX27_DT
 
 endif
 
-if ARCH_IMX_V6_V7
+if ARCH_MULTI_V6
 
 comment "MX31 platforms:"
 
@@ -649,6 +734,10 @@ config MACH_VPR200
 	  Include support for VPR200 platform. This includes specific
 	  configurations for the board and its peripherals.
 
+endif
+
+if ARCH_MULTI_V7
+
 comment "i.MX5 platforms:"
 
 config MACH_MX50_RDP
@@ -739,6 +828,7 @@ config	SOC_IMX53
 	select ARCH_MX5
 	select ARCH_MX53
 	select HAVE_CAN_FLEXCAN if CAN
+	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select PINCTRL
 	select PINCTRL_IMX53
 	select SOC_IMX5
@@ -748,7 +838,14 @@ config	SOC_IMX53
 
 config SOC_IMX6Q
 	bool "i.MX6 Quad support"
+	select ARCH_HAS_CPUFREQ
+	select ARCH_HAS_OPP
 	select ARM_CPU_SUSPEND if PM
+	select ARM_ERRATA_743622
+	select ARM_ERRATA_751472
+	select ARM_ERRATA_754322
+	select ARM_ERRATA_764369 if SMP
+	select ARM_ERRATA_775420
 	select ARM_GIC
 	select COMMON_CLK
 	select CPU_V7
@@ -756,13 +853,20 @@ config SOC_IMX6Q
 	select HAVE_CAN_FLEXCAN if CAN
 	select HAVE_IMX_GPC
 	select HAVE_IMX_MMDC
-	select HAVE_IMX_SRC
 	select HAVE_SMP
 	select MFD_SYSCON
 	select PINCTRL
 	select PINCTRL_IMX6Q
+	select PL310_ERRATA_588369 if CACHE_PL310
+	select PL310_ERRATA_727915 if CACHE_PL310
+	select PL310_ERRATA_769419 if CACHE_PL310
+	select PM_OPP if PM
 
 	help
 	  This enables support for Freescale i.MX6 Quad processor.
 
 endif
+
+source "arch/arm/mach-imx/devices/Kconfig"
+
+endmenu
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 895754a..0634b31 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -1,3 +1,5 @@
+obj-y := time.o cpu.o system.o irq-common.o
+
 obj-$(CONFIG_SOC_IMX1) += clk-imx1.o mm-imx1.o
 obj-$(CONFIG_SOC_IMX21) += clk-imx21.o mm-imx21.o
 
@@ -15,6 +17,24 @@ obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o $(i
 obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
 			    clk-pfd.o clk-busy.o clk.o
 
+obj-$(CONFIG_IMX_HAVE_IOMUX_V1) += iomux-v1.o
+obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
+
+obj-$(CONFIG_MXC_TZIC) += tzic.o
+obj-$(CONFIG_MXC_AVIC) += avic.o
+
+obj-$(CONFIG_IRAM_ALLOC) += iram_alloc.o
+obj-$(CONFIG_MXC_ULPI) += ulpi.o
+obj-$(CONFIG_MXC_USE_EPIT) += epit.o
+obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
+obj-$(CONFIG_CPU_FREQ_IMX)    += cpufreq.o
+obj-$(CONFIG_CPU_IDLE) += cpuidle.o
+
+ifdef CONFIG_SND_IMX_SOC
+obj-y += ssi-fiq.o
+obj-y += ssi-fiq-ksym.o
+endif
+
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
 
@@ -30,6 +50,7 @@ obj-$(CONFIG_MACH_MX21ADS) += mach-mx21ads.o
 obj-$(CONFIG_MACH_MX25_3DS) += mach-mx25_3ds.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX25SD) += mach-eukrea_cpuimx25.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD25_BASEBOARD) += eukrea_mbimxsd25-baseboard.o
+obj-$(CONFIG_MACH_IMX25_DT) += imx25-dt.o
 
 # i.MX27 based machines
 obj-$(CONFIG_MACH_MX27ADS) += mach-mx27ads.o
@@ -89,3 +110,5 @@ obj-$(CONFIG_MACH_MX50_RDP) += mach-mx50_rdp.o
 
 obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
 obj-$(CONFIG_SOC_IMX53) += mach-imx53.o
+
+obj-y += devices/
diff --git a/arch/arm/mach-imx/avic.c b/arch/arm/mach-imx/avic.c
new file mode 100644
index 0000000..0eff23e
--- /dev/null
+++ b/arch/arm/mach-imx/avic.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <asm/mach/irq.h>
+#include <asm/exception.h>
+
+#include "common.h"
+#include "hardware.h"
+#include "irq-common.h"
+
+#define AVIC_INTCNTL		0x00	/* int control reg */
+#define AVIC_NIMASK		0x04	/* int mask reg */
+#define AVIC_INTENNUM		0x08	/* int enable number reg */
+#define AVIC_INTDISNUM		0x0C	/* int disable number reg */
+#define AVIC_INTENABLEH		0x10	/* int enable reg high */
+#define AVIC_INTENABLEL		0x14	/* int enable reg low */
+#define AVIC_INTTYPEH		0x18	/* int type reg high */
+#define AVIC_INTTYPEL		0x1C	/* int type reg low */
+#define AVIC_NIPRIORITY(x)	(0x20 + 4 * (7 - (x))) /* int priority */
+#define AVIC_NIVECSR		0x40	/* norm int vector/status */
+#define AVIC_FIVECSR		0x44	/* fast int vector/status */
+#define AVIC_INTSRCH		0x48	/* int source reg high */
+#define AVIC_INTSRCL		0x4C	/* int source reg low */
+#define AVIC_INTFRCH		0x50	/* int force reg high */
+#define AVIC_INTFRCL		0x54	/* int force reg low */
+#define AVIC_NIPNDH		0x58	/* norm int pending high */
+#define AVIC_NIPNDL		0x5C	/* norm int pending low */
+#define AVIC_FIPNDH		0x60	/* fast int pending high */
+#define AVIC_FIPNDL		0x64	/* fast int pending low */
+
+#define AVIC_NUM_IRQS 64
+
+void __iomem *avic_base;
+static struct irq_domain *domain;
+
+static u32 avic_saved_mask_reg[2];
+
+#ifdef CONFIG_MXC_IRQ_PRIOR
+static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
+{
+	struct irq_data *d = irq_get_irq_data(irq);
+	unsigned int temp;
+	unsigned int mask = 0x0F << irq % 8 * 4;
+
+	irq = d->hwirq;
+
+	if (irq >= AVIC_NUM_IRQS)
+		return -EINVAL;
+
+	temp = __raw_readl(avic_base + AVIC_NIPRIORITY(irq / 8));
+	temp &= ~mask;
+	temp |= prio & mask;
+
+	__raw_writel(temp, avic_base + AVIC_NIPRIORITY(irq / 8));
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_FIQ
+static int avic_set_irq_fiq(unsigned int irq, unsigned int type)
+{
+	struct irq_data *d = irq_get_irq_data(irq);
+	unsigned int irqt;
+
+	irq = d->hwirq;
+
+	if (irq >= AVIC_NUM_IRQS)
+		return -EINVAL;
+
+	if (irq < AVIC_NUM_IRQS / 2) {
+		irqt = __raw_readl(avic_base + AVIC_INTTYPEL) & ~(1 << irq);
+		__raw_writel(irqt | (!!type << irq), avic_base + AVIC_INTTYPEL);
+	} else {
+		irq -= AVIC_NUM_IRQS / 2;
+		irqt = __raw_readl(avic_base + AVIC_INTTYPEH) & ~(1 << irq);
+		__raw_writel(irqt | (!!type << irq), avic_base + AVIC_INTTYPEH);
+	}
+
+	return 0;
+}
+#endif /* CONFIG_FIQ */
+
+
+static struct mxc_extra_irq avic_extra_irq = {
+#ifdef CONFIG_MXC_IRQ_PRIOR
+	.set_priority = avic_irq_set_priority,
+#endif
+#ifdef CONFIG_FIQ
+	.set_irq_fiq = avic_set_irq_fiq,
+#endif
+};
+
+#ifdef CONFIG_PM
+static void avic_irq_suspend(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct = gc->chip_types;
+	int idx = d->hwirq >> 5;
+
+	avic_saved_mask_reg[idx] = __raw_readl(avic_base + ct->regs.mask);
+	__raw_writel(gc->wake_active, avic_base + ct->regs.mask);
+}
+
+static void avic_irq_resume(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct = gc->chip_types;
+	int idx = d->hwirq >> 5;
+
+	__raw_writel(avic_saved_mask_reg[idx], avic_base + ct->regs.mask);
+}
+
+#else
+#define avic_irq_suspend NULL
+#define avic_irq_resume NULL
+#endif
+
+static __init void avic_init_gc(int idx, unsigned int irq_start)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+
+	gc = irq_alloc_generic_chip("mxc-avic", 1, irq_start, avic_base,
+				    handle_level_irq);
+	gc->private = &avic_extra_irq;
+	gc->wake_enabled = IRQ_MSK(32);
+
+	ct = gc->chip_types;
+	ct->chip.irq_mask = irq_gc_mask_clr_bit;
+	ct->chip.irq_unmask = irq_gc_mask_set_bit;
+	ct->chip.irq_ack = irq_gc_mask_clr_bit;
+	ct->chip.irq_set_wake = irq_gc_set_wake;
+	ct->chip.irq_suspend = avic_irq_suspend;
+	ct->chip.irq_resume = avic_irq_resume;
+	ct->regs.mask = !idx ? AVIC_INTENABLEL : AVIC_INTENABLEH;
+	ct->regs.ack = ct->regs.mask;
+
+	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
+}
+
+asmlinkage void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
+{
+	u32 nivector;
+
+	do {
+		nivector = __raw_readl(avic_base + AVIC_NIVECSR) >> 16;
+		if (nivector == 0xffff)
+			break;
+
+		handle_IRQ(irq_find_mapping(domain, nivector), regs);
+	} while (1);
+}
+
+/*
+ * This function initializes the AVIC hardware and disables all the
+ * interrupts. It registers the interrupt enable and disable functions
+ * to the kernel for each interrupt source.
+ */
+void __init mxc_init_irq(void __iomem *irqbase)
+{
+	struct device_node *np;
+	int irq_base;
+	int i;
+
+	avic_base = irqbase;
+
+	/* put the AVIC into the reset value with
+	 * all interrupts disabled
+	 */
+	__raw_writel(0, avic_base + AVIC_INTCNTL);
+	__raw_writel(0x1f, avic_base + AVIC_NIMASK);
+
+	/* disable all interrupts */
+	__raw_writel(0, avic_base + AVIC_INTENABLEH);
+	__raw_writel(0, avic_base + AVIC_INTENABLEL);
+
+	/* all IRQ no FIQ */
+	__raw_writel(0, avic_base + AVIC_INTTYPEH);
+	__raw_writel(0, avic_base + AVIC_INTTYPEL);
+
+	irq_base = irq_alloc_descs(-1, 0, AVIC_NUM_IRQS, numa_node_id());
+	WARN_ON(irq_base < 0);
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,avic");
+	domain = irq_domain_add_legacy(np, AVIC_NUM_IRQS, irq_base, 0,
+				       &irq_domain_simple_ops, NULL);
+	WARN_ON(!domain);
+
+	for (i = 0; i < AVIC_NUM_IRQS / 32; i++, irq_base += 32)
+		avic_init_gc(i, irq_base);
+
+	/* Set default priority value (0) for all IRQ's */
+	for (i = 0; i < 8; i++)
+		__raw_writel(0, avic_base + AVIC_NIPRIORITY(i));
+
+#ifdef CONFIG_FIQ
+	/* Initialize FIQ */
+	init_FIQ(FIQ_START);
+#endif
+
+	printk(KERN_INFO "MXC IRQ initialized\n");
+}
diff --git a/arch/arm/mach-imx/board-mx31lilly.h b/arch/arm/mach-imx/board-mx31lilly.h
new file mode 100644
index 0000000..0df71bf
--- /dev/null
+++ b/arch/arm/mach-imx/board-mx31lilly.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ * Based on code for mobots boards,
+ *   Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __ASM_ARCH_MXC_BOARD_MX31LILLY_H__
+#define __ASM_ARCH_MXC_BOARD_MX31LILLY_H__
+
+#ifndef __ASSEMBLY__
+
+enum mx31lilly_boards {
+	MX31LILLY_NOBOARD	= 0,
+	MX31LILLY_DB		= 1,
+};
+
+/*
+ * This CPU module needs a baseboard to work. After basic initializing
+ * its own devices, it calls the baseboard's init function.
+ */
+
+extern void mx31lilly_db_init(void);
+
+#endif
+
+#endif /* __ASM_ARCH_MXC_BOARD_MX31LILLY_H__ */
diff --git a/arch/arm/mach-imx/board-mx31lite.h b/arch/arm/mach-imx/board-mx31lite.h
new file mode 100644
index 0000000..c1ad0ae8
--- /dev/null
+++ b/arch/arm/mach-imx/board-mx31lite.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ * Based on code for mobots boards,
+ *   Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __ASM_ARCH_MXC_BOARD_MX31LITE_H__
+#define __ASM_ARCH_MXC_BOARD_MX31LITE_H__
+
+#ifndef __ASSEMBLY__
+
+enum mx31lite_boards {
+	MX31LITE_NOBOARD	= 0,
+	MX31LITE_DB		= 1,
+};
+
+/*
+ * This CPU module needs a baseboard to work. After basic initializing
+ * its own devices, it calls the baseboard's init function.
+ */
+
+extern void mx31lite_db_init(void);
+
+#endif
+
+#endif /* __ASM_ARCH_MXC_BOARD_MX31LITE_H__ */
diff --git a/arch/arm/mach-imx/board-mx31moboard.h b/arch/arm/mach-imx/board-mx31moboard.h
new file mode 100644
index 0000000..de14543
--- /dev/null
+++ b/arch/arm/mach-imx/board-mx31moboard.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __ASM_ARCH_MXC_BOARD_MX31MOBOARD_H__
+#define __ASM_ARCH_MXC_BOARD_MX31MOBOARD_H__
+
+#ifndef __ASSEMBLY__
+
+enum mx31moboard_boards {
+	MX31NOBOARD	= 0,
+	MX31DEVBOARD	= 1,
+	MX31MARXBOT	= 2,
+	MX31SMARTBOT	= 3,
+	MX31EYEBOT	= 4,
+};
+
+/*
+ * This CPU module needs a baseboard to work. After basic initializing
+ * its own devices, it calls the baseboard's init function.
+ */
+
+extern void mx31moboard_devboard_init(void);
+extern void mx31moboard_marxbot_init(void);
+extern void mx31moboard_smartbot_init(int board);
+
+#endif
+
+#endif /* __ASM_ARCH_MXC_BOARD_MX31MOBOARD_H__ */
diff --git a/arch/arm/mach-imx/board-pcm038.h b/arch/arm/mach-imx/board-pcm038.h
new file mode 100644
index 0000000..6f371e3
--- /dev/null
+++ b/arch/arm/mach-imx/board-pcm038.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __ASM_ARCH_MXC_BOARD_PCM038_H__
+#define __ASM_ARCH_MXC_BOARD_PCM038_H__
+
+#ifndef __ASSEMBLY__
+/*
+ * This CPU module needs a baseboard to work. After basic initializing
+ * its own devices, it calls the baseboard's init function.
+ * TODO: Add your own baseboard init function and call it from
+ * inside pcm038_init().
+ *
+ * This example here is for the development board. Refer pcm970-baseboard.c
+ */
+
+extern void pcm970_baseboard_init(void);
+
+#endif
+
+#endif /* __ASM_ARCH_MXC_BOARD_PCM038_H__ */
diff --git a/arch/arm/mach-imx/clk-imx1.c b/arch/arm/mach-imx/clk-imx1.c
index 516ddee..15f9d22 100644
--- a/arch/arm/mach-imx/clk-imx1.c
+++ b/arch/arm/mach-imx/clk-imx1.c
@@ -22,9 +22,9 @@
 #include <linux/clkdev.h>
 #include <linux/err.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
 #include "clk.h"
+#include "common.h"
+#include "hardware.h"
 
 /* CCM register addresses */
 #define IO_ADDR_CCM(off)	(MX1_IO_ADDRESS(MX1_CCM_BASE_ADDR + (off)))
@@ -82,7 +82,8 @@ int __init mx1_clocks_init(unsigned long fref)
 			pr_err("imx1 clk %d: register failed with %ld\n",
 				i, PTR_ERR(clk[i]));
 
-	clk_register_clkdev(clk[dma_gate], "ahb", "imx-dma");
+	clk_register_clkdev(clk[dma_gate], "ahb", "imx1-dma");
+	clk_register_clkdev(clk[hclk], "ipg", "imx1-dma");
 	clk_register_clkdev(clk[csi_gate], NULL, "mx1-camera.0");
 	clk_register_clkdev(clk[mma_gate], "mma", NULL);
 	clk_register_clkdev(clk[usbd_gate], NULL, "imx_udc.0");
@@ -94,18 +95,18 @@ int __init mx1_clocks_init(unsigned long fref)
 	clk_register_clkdev(clk[hclk], "ipg", "imx1-uart.1");
 	clk_register_clkdev(clk[per1], "per", "imx1-uart.2");
 	clk_register_clkdev(clk[hclk], "ipg", "imx1-uart.2");
-	clk_register_clkdev(clk[hclk], NULL, "imx-i2c.0");
+	clk_register_clkdev(clk[hclk], NULL, "imx1-i2c.0");
 	clk_register_clkdev(clk[per2], "per", "imx1-cspi.0");
 	clk_register_clkdev(clk[dummy], "ipg", "imx1-cspi.0");
 	clk_register_clkdev(clk[per2], "per", "imx1-cspi.1");
 	clk_register_clkdev(clk[dummy], "ipg", "imx1-cspi.1");
 	clk_register_clkdev(clk[per2], NULL, "imx-mmc.0");
-	clk_register_clkdev(clk[per2], "per", "imx-fb.0");
-	clk_register_clkdev(clk[dummy], "ipg", "imx-fb.0");
-	clk_register_clkdev(clk[dummy], "ahb", "imx-fb.0");
+	clk_register_clkdev(clk[per2], "per", "imx1-fb.0");
+	clk_register_clkdev(clk[dummy], "ipg", "imx1-fb.0");
+	clk_register_clkdev(clk[dummy], "ahb", "imx1-fb.0");
 	clk_register_clkdev(clk[hclk], "mshc", NULL);
 	clk_register_clkdev(clk[per3], "ssi", NULL);
-	clk_register_clkdev(clk[clk32], NULL, "mxc_rtc.0");
+	clk_register_clkdev(clk[clk32], NULL, "imx1-rtc.0");
 	clk_register_clkdev(clk[clko], "clko", NULL);
 
 	mxc_timer_init(MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR), MX1_TIM1_INT);
diff --git a/arch/arm/mach-imx/clk-imx21.c b/arch/arm/mach-imx/clk-imx21.c
index cf65148..d7ed660 100644
--- a/arch/arm/mach-imx/clk-imx21.c
+++ b/arch/arm/mach-imx/clk-imx21.c
@@ -25,9 +25,9 @@
 #include <linux/module.h>
 #include <linux/err.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
 #include "clk.h"
+#include "common.h"
+#include "hardware.h"
 
 #define IO_ADDR_CCM(off)	(MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off)))
 
@@ -156,16 +156,16 @@ int __init mx21_clocks_init(unsigned long lref, unsigned long href)
 	clk_register_clkdev(clk[cspi2_ipg_gate], "ipg", "imx21-cspi.1");
 	clk_register_clkdev(clk[per2], "per", "imx21-cspi.2");
 	clk_register_clkdev(clk[cspi3_ipg_gate], "ipg", "imx21-cspi.2");
-	clk_register_clkdev(clk[per3], "per", "imx-fb.0");
-	clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx-fb.0");
-	clk_register_clkdev(clk[lcdc_hclk_gate], "ahb", "imx-fb.0");
+	clk_register_clkdev(clk[per3], "per", "imx21-fb.0");
+	clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx21-fb.0");
+	clk_register_clkdev(clk[lcdc_hclk_gate], "ahb", "imx21-fb.0");
 	clk_register_clkdev(clk[usb_gate], "per", "imx21-hcd.0");
 	clk_register_clkdev(clk[usb_hclk_gate], "ahb", "imx21-hcd.0");
-	clk_register_clkdev(clk[nfc_gate], NULL, "mxc_nand.0");
-	clk_register_clkdev(clk[dma_hclk_gate], "ahb", "imx-dma");
-	clk_register_clkdev(clk[dma_gate], "ipg", "imx-dma");
+	clk_register_clkdev(clk[nfc_gate], NULL, "imx21-nand.0");
+	clk_register_clkdev(clk[dma_hclk_gate], "ahb", "imx21-dma");
+	clk_register_clkdev(clk[dma_gate], "ipg", "imx21-dma");
 	clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
-	clk_register_clkdev(clk[i2c_gate], NULL, "imx-i2c.0");
+	clk_register_clkdev(clk[i2c_gate], NULL, "imx21-i2c.0");
 	clk_register_clkdev(clk[kpp_gate], NULL, "mxc-keypad");
 	clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1.0");
 	clk_register_clkdev(clk[brom_gate], "brom", NULL);
diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c
index 01e2f84..b197aa7 100644
--- a/arch/arm/mach-imx/clk-imx25.c
+++ b/arch/arm/mach-imx/clk-imx25.c
@@ -23,11 +23,14 @@
 #include <linux/io.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/mx25.h>
 #include "clk.h"
+#include "common.h"
+#include "hardware.h"
+#include "mx25.h"
 
 #define CRM_BASE	MX25_IO_ADDRESS(MX25_CRM_BASE_ADDR)
 
@@ -55,6 +58,8 @@
 
 #define ccm(x)	(CRM_BASE + (x))
 
+static struct clk_onecell_data clk_data;
+
 static const char *cpu_sel_clks[] = { "mpll", "mpll_cpu_3_4", };
 static const char *per_sel_clks[] = { "ahb", "upll", };
 
@@ -64,24 +69,30 @@ enum mx25_clks {
 	per7_sel, per8_sel, per9_sel, per10_sel, per11_sel, per12_sel,
 	per13_sel, per14_sel, per15_sel, per0, per1, per2, per3, per4, per5,
 	per6, per7, per8, per9, per10, per11, per12, per13, per14, per15,
-	csi_ipg_per, esdhc1_ipg_per, esdhc2_ipg_per, gpt_ipg_per, i2c_ipg_per,
-	lcdc_ipg_per, nfc_ipg_per, ssi1_ipg_per, ssi2_ipg_per, uart_ipg_per,
-	csi_ahb, esdhc1_ahb, esdhc2_ahb, fec_ahb, lcdc_ahb, sdma_ahb,
-	usbotg_ahb, can1_ipg, can2_ipg, csi_ipg, cspi1_ipg, cspi2_ipg,
-	cspi3_ipg, dryice_ipg, esdhc1_ipg, esdhc2_ipg, fec_ipg, iim_ipg,
-	kpp_ipg, lcdc_ipg, pwm1_ipg, pwm2_ipg, pwm3_ipg, pwm4_ipg, sdma_ipg,
-	ssi1_ipg, ssi2_ipg, tsc_ipg, uart1_ipg, uart2_ipg, uart3_ipg,
-	uart4_ipg, uart5_ipg, wdt_ipg, clk_max
+	csi_ipg_per, epit_ipg_per, esai_ipg_per, esdhc1_ipg_per, esdhc2_ipg_per,
+	gpt_ipg_per, i2c_ipg_per, lcdc_ipg_per, nfc_ipg_per, owire_ipg_per,
+	pwm_ipg_per, sim1_ipg_per, sim2_ipg_per, ssi1_ipg_per, ssi2_ipg_per,
+	uart_ipg_per, ata_ahb, reserved1, csi_ahb, emi_ahb, esai_ahb, esdhc1_ahb,
+	esdhc2_ahb, fec_ahb, lcdc_ahb, rtic_ahb, sdma_ahb, slcdc_ahb, usbotg_ahb,
+	reserved2, reserved3, reserved4, reserved5, can1_ipg, can2_ipg,	csi_ipg,
+	cspi1_ipg, cspi2_ipg, cspi3_ipg, dryice_ipg, ect_ipg, epit1_ipg, epit2_ipg,
+	reserved6, esdhc1_ipg, esdhc2_ipg, fec_ipg, reserved7, reserved8, reserved9,
+	gpt1_ipg, gpt2_ipg, gpt3_ipg, gpt4_ipg, reserved10, reserved11, reserved12,
+	iim_ipg, reserved13, reserved14, kpp_ipg, lcdc_ipg, reserved15, pwm1_ipg,
+	pwm2_ipg, pwm3_ipg, pwm4_ipg, rngb_ipg, reserved16, scc_ipg, sdma_ipg,
+	sim1_ipg, sim2_ipg, slcdc_ipg, spba_ipg, ssi1_ipg, ssi2_ipg, tsc_ipg,
+	uart1_ipg, uart2_ipg, uart3_ipg, uart4_ipg, uart5_ipg, reserved17,
+	wdt_ipg, clk_max
 };
 
 static struct clk *clk[clk_max];
 
-int __init mx25_clocks_init(void)
+static int __init __mx25_clocks_init(unsigned long osc_rate)
 {
 	int i;
 
 	clk[dummy] = imx_clk_fixed("dummy", 0);
-	clk[osc] = imx_clk_fixed("osc", 24000000);
+	clk[osc] = imx_clk_fixed("osc", osc_rate);
 	clk[mpll] = imx_clk_pllv1("mpll", "osc", ccm(CCM_MPCTL));
 	clk[upll] = imx_clk_pllv1("upll", "osc", ccm(CCM_UPCTL));
 	clk[mpll_cpu_3_4] = imx_clk_fixed_factor("mpll_cpu_3_4", "mpll", 3, 4);
@@ -123,22 +134,36 @@ int __init mx25_clocks_init(void)
 	clk[per14] = imx_clk_divider("per14", "per14_sel", ccm(CCM_PCDR3), 16, 6);
 	clk[per15] = imx_clk_divider("per15", "per15_sel", ccm(CCM_PCDR3), 24, 6);
 	clk[csi_ipg_per] = imx_clk_gate("csi_ipg_per", "per0", ccm(CCM_CGCR0), 0);
+	clk[epit_ipg_per] = imx_clk_gate("epit_ipg_per", "per1", ccm(CCM_CGCR0),  1);
+	clk[esai_ipg_per] = imx_clk_gate("esai_ipg_per", "per2", ccm(CCM_CGCR0),  2);
 	clk[esdhc1_ipg_per] = imx_clk_gate("esdhc1_ipg_per", "per3", ccm(CCM_CGCR0),  3);
 	clk[esdhc2_ipg_per] = imx_clk_gate("esdhc2_ipg_per", "per4", ccm(CCM_CGCR0),  4);
 	clk[gpt_ipg_per] = imx_clk_gate("gpt_ipg_per", "per5", ccm(CCM_CGCR0),  5);
 	clk[i2c_ipg_per] = imx_clk_gate("i2c_ipg_per", "per6", ccm(CCM_CGCR0),  6);
 	clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per7", ccm(CCM_CGCR0),  7);
 	clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "per8", ccm(CCM_CGCR0),  8);
+	clk[owire_ipg_per] = imx_clk_gate("owire_ipg_per", "per9", ccm(CCM_CGCR0),  9);
+	clk[pwm_ipg_per] = imx_clk_gate("pwm_ipg_per", "per10", ccm(CCM_CGCR0),  10);
+	clk[sim1_ipg_per] = imx_clk_gate("sim1_ipg_per", "per11", ccm(CCM_CGCR0),  11);
+	clk[sim2_ipg_per] = imx_clk_gate("sim2_ipg_per", "per12", ccm(CCM_CGCR0),  12);
 	clk[ssi1_ipg_per] = imx_clk_gate("ssi1_ipg_per", "per13", ccm(CCM_CGCR0), 13);
 	clk[ssi2_ipg_per] = imx_clk_gate("ssi2_ipg_per", "per14", ccm(CCM_CGCR0), 14);
 	clk[uart_ipg_per] = imx_clk_gate("uart_ipg_per", "per15", ccm(CCM_CGCR0), 15);
+	clk[ata_ahb] = imx_clk_gate("ata_ahb", "ahb", ccm(CCM_CGCR0), 16);
+	/* CCM_CGCR0(17): reserved */
 	clk[csi_ahb] = imx_clk_gate("csi_ahb", "ahb", ccm(CCM_CGCR0), 18);
+	clk[emi_ahb] = imx_clk_gate("emi_ahb", "ahb", ccm(CCM_CGCR0), 19);
+	clk[esai_ahb] = imx_clk_gate("esai_ahb", "ahb", ccm(CCM_CGCR0), 20);
 	clk[esdhc1_ahb] = imx_clk_gate("esdhc1_ahb", "ahb", ccm(CCM_CGCR0), 21);
 	clk[esdhc2_ahb] = imx_clk_gate("esdhc2_ahb", "ahb", ccm(CCM_CGCR0), 22);
 	clk[fec_ahb] = imx_clk_gate("fec_ahb", "ahb", ccm(CCM_CGCR0), 23);
 	clk[lcdc_ahb] = imx_clk_gate("lcdc_ahb", "ahb", ccm(CCM_CGCR0), 24);
+	clk[rtic_ahb] = imx_clk_gate("rtic_ahb", "ahb", ccm(CCM_CGCR0), 25);
 	clk[sdma_ahb] = imx_clk_gate("sdma_ahb", "ahb", ccm(CCM_CGCR0), 26);
+	clk[slcdc_ahb] = imx_clk_gate("slcdc_ahb", "ahb", ccm(CCM_CGCR0), 27);
 	clk[usbotg_ahb] = imx_clk_gate("usbotg_ahb", "ahb", ccm(CCM_CGCR0), 28);
+	/* CCM_CGCR0(29-31): reserved */
+	/* CCM_CGCR1(0): reserved in datasheet, used as audmux in FSL kernel */
 	clk[can1_ipg] = imx_clk_gate("can1_ipg", "ipg", ccm(CCM_CGCR1),  2);
 	clk[can2_ipg] = imx_clk_gate("can2_ipg", "ipg", ccm(CCM_CGCR1),  3);
 	clk[csi_ipg] = imx_clk_gate("csi_ipg", "ipg", ccm(CCM_CGCR1),  4);
@@ -146,17 +171,41 @@ int __init mx25_clocks_init(void)
 	clk[cspi2_ipg] = imx_clk_gate("cspi2_ipg", "ipg", ccm(CCM_CGCR1),  6);
 	clk[cspi3_ipg] = imx_clk_gate("cspi3_ipg", "ipg", ccm(CCM_CGCR1),  7);
 	clk[dryice_ipg] = imx_clk_gate("dryice_ipg", "ipg", ccm(CCM_CGCR1),  8);
+	clk[ect_ipg] = imx_clk_gate("ect_ipg", "ipg", ccm(CCM_CGCR1),  9);
+	clk[epit1_ipg] = imx_clk_gate("epit1_ipg", "ipg", ccm(CCM_CGCR1),  10);
+	clk[epit2_ipg] = imx_clk_gate("epit2_ipg", "ipg", ccm(CCM_CGCR1),  11);
+	/* CCM_CGCR1(12): reserved in datasheet, used as esai in FSL kernel */
 	clk[esdhc1_ipg] = imx_clk_gate("esdhc1_ipg", "ipg", ccm(CCM_CGCR1), 13);
 	clk[esdhc2_ipg] = imx_clk_gate("esdhc2_ipg", "ipg", ccm(CCM_CGCR1), 14);
 	clk[fec_ipg] = imx_clk_gate("fec_ipg", "ipg", ccm(CCM_CGCR1), 15);
+	/* CCM_CGCR1(16): reserved in datasheet, used as gpio1 in FSL kernel */
+	/* CCM_CGCR1(17): reserved in datasheet, used as gpio2 in FSL kernel */
+	/* CCM_CGCR1(18): reserved in datasheet, used as gpio3 in FSL kernel */
+	clk[gpt1_ipg] = imx_clk_gate("gpt1_ipg", "ipg", ccm(CCM_CGCR1), 19);
+	clk[gpt2_ipg] = imx_clk_gate("gpt2_ipg", "ipg", ccm(CCM_CGCR1), 20);
+	clk[gpt3_ipg] = imx_clk_gate("gpt3_ipg", "ipg", ccm(CCM_CGCR1), 21);
+	clk[gpt4_ipg] = imx_clk_gate("gpt4_ipg", "ipg", ccm(CCM_CGCR1), 22);
+	/* CCM_CGCR1(23): reserved in datasheet, used as i2c1 in FSL kernel */
+	/* CCM_CGCR1(24): reserved in datasheet, used as i2c2 in FSL kernel */
+	/* CCM_CGCR1(25): reserved in datasheet, used as i2c3 in FSL kernel */
 	clk[iim_ipg] = imx_clk_gate("iim_ipg", "ipg", ccm(CCM_CGCR1), 26);
+	/* CCM_CGCR1(27): reserved in datasheet, used as iomuxc in FSL kernel */
+	/* CCM_CGCR1(28): reserved in datasheet, used as kpp in FSL kernel */
 	clk[kpp_ipg] = imx_clk_gate("kpp_ipg", "ipg", ccm(CCM_CGCR1), 28);
 	clk[lcdc_ipg] = imx_clk_gate("lcdc_ipg", "ipg", ccm(CCM_CGCR1), 29);
+	/* CCM_CGCR1(30): reserved in datasheet, used as owire in FSL kernel */
 	clk[pwm1_ipg] = imx_clk_gate("pwm1_ipg", "ipg", ccm(CCM_CGCR1), 31);
 	clk[pwm2_ipg] = imx_clk_gate("pwm2_ipg", "ipg", ccm(CCM_CGCR2),  0);
 	clk[pwm3_ipg] = imx_clk_gate("pwm3_ipg", "ipg", ccm(CCM_CGCR2),  1);
 	clk[pwm4_ipg] = imx_clk_gate("pwm4_ipg", "ipg", ccm(CCM_CGCR2),  2);
+	clk[rngb_ipg] = imx_clk_gate("rngb_ipg", "ipg", ccm(CCM_CGCR2),  3);
+	/* CCM_CGCR2(4): reserved in datasheet, used as rtic in FSL kernel */
+	clk[scc_ipg] = imx_clk_gate("scc_ipg", "ipg", ccm(CCM_CGCR2),  5);
 	clk[sdma_ipg] = imx_clk_gate("sdma_ipg", "ipg", ccm(CCM_CGCR2),  6);
+	clk[sim1_ipg] = imx_clk_gate("sim1_ipg", "ipg", ccm(CCM_CGCR2),  7);
+	clk[sim2_ipg] = imx_clk_gate("sim2_ipg", "ipg", ccm(CCM_CGCR2),  8);
+	clk[slcdc_ipg] = imx_clk_gate("slcdc_ipg", "ipg", ccm(CCM_CGCR2),  9);
+	clk[spba_ipg] = imx_clk_gate("spba_ipg", "ipg", ccm(CCM_CGCR2),  10);
 	clk[ssi1_ipg] = imx_clk_gate("ssi1_ipg", "ipg", ccm(CCM_CGCR2), 11);
 	clk[ssi2_ipg] = imx_clk_gate("ssi2_ipg", "ipg", ccm(CCM_CGCR2), 12);
 	clk[tsc_ipg] = imx_clk_gate("tsc_ipg", "ipg", ccm(CCM_CGCR2), 13);
@@ -165,6 +214,7 @@ int __init mx25_clocks_init(void)
 	clk[uart3_ipg] = imx_clk_gate("uart3_ipg", "ipg", ccm(CCM_CGCR2), 16);
 	clk[uart4_ipg] = imx_clk_gate("uart4_ipg", "ipg", ccm(CCM_CGCR2), 17);
 	clk[uart5_ipg] = imx_clk_gate("uart5_ipg", "ipg", ccm(CCM_CGCR2), 18);
+	/* CCM_CGCR2(19): reserved in datasheet, but used as wdt in FSL kernel */
 	clk[wdt_ipg] = imx_clk_gate("wdt_ipg", "ipg", ccm(CCM_CGCR2), 19);
 
 	for (i = 0; i < ARRAY_SIZE(clk); i++)
@@ -172,6 +222,18 @@ int __init mx25_clocks_init(void)
 			pr_err("i.MX25 clk %d: register failed with %ld\n",
 				i, PTR_ERR(clk[i]));
 
+	clk_prepare_enable(clk[emi_ahb]);
+
+	clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
+	clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
+
+	return 0;
+}
+
+int __init mx25_clocks_init(void)
+{
+	__mx25_clocks_init(24000000);
+
 	/* i.mx25 has the i.mx21 type uart */
 	clk_register_clkdev(clk[uart1_ipg], "ipg", "imx21-uart.0");
 	clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.0");
@@ -183,8 +245,6 @@ int __init mx25_clocks_init(void)
 	clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.3");
 	clk_register_clkdev(clk[uart5_ipg], "ipg", "imx21-uart.4");
 	clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.4");
-	clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
-	clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
 	clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.0");
 	clk_register_clkdev(clk[usbotg_ahb], "ahb", "mxc-ehci.0");
 	clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.0");
@@ -197,7 +257,7 @@ int __init mx25_clocks_init(void)
 	clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
 	clk_register_clkdev(clk[usbotg_ahb], "ahb", "fsl-usb2-udc");
 	clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");
-	clk_register_clkdev(clk[nfc_ipg_per], NULL, "mxc_nand.0");
+	clk_register_clkdev(clk[nfc_ipg_per], NULL, "imx25-nand.0");
 	/* i.mx25 has the i.mx35 type cspi */
 	clk_register_clkdev(clk[cspi1_ipg], NULL, "imx35-cspi.0");
 	clk_register_clkdev(clk[cspi2_ipg], NULL, "imx35-cspi.1");
@@ -212,15 +272,15 @@ int __init mx25_clocks_init(void)
 	clk_register_clkdev(clk[per10], "per", "mxc_pwm.3");
 	clk_register_clkdev(clk[kpp_ipg], NULL, "imx-keypad");
 	clk_register_clkdev(clk[tsc_ipg], NULL, "mx25-adc");
-	clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx-i2c.0");
-	clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx-i2c.1");
-	clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx-i2c.2");
+	clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx21-i2c.0");
+	clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx21-i2c.1");
+	clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx21-i2c.2");
 	clk_register_clkdev(clk[fec_ipg], "ipg", "imx25-fec.0");
 	clk_register_clkdev(clk[fec_ahb], "ahb", "imx25-fec.0");
 	clk_register_clkdev(clk[dryice_ipg], NULL, "imxdi_rtc.0");
-	clk_register_clkdev(clk[lcdc_ipg_per], "per", "imx-fb.0");
-	clk_register_clkdev(clk[lcdc_ipg], "ipg", "imx-fb.0");
-	clk_register_clkdev(clk[lcdc_ahb], "ahb", "imx-fb.0");
+	clk_register_clkdev(clk[lcdc_ipg_per], "per", "imx21-fb.0");
+	clk_register_clkdev(clk[lcdc_ipg], "ipg", "imx21-fb.0");
+	clk_register_clkdev(clk[lcdc_ahb], "ahb", "imx21-fb.0");
 	clk_register_clkdev(clk[wdt_ipg], NULL, "imx2-wdt.0");
 	clk_register_clkdev(clk[ssi1_ipg], NULL, "imx-ssi.0");
 	clk_register_clkdev(clk[ssi2_ipg], NULL, "imx-ssi.1");
@@ -230,9 +290,9 @@ int __init mx25_clocks_init(void)
 	clk_register_clkdev(clk[esdhc2_ipg_per], "per", "sdhci-esdhc-imx25.1");
 	clk_register_clkdev(clk[esdhc2_ipg], "ipg", "sdhci-esdhc-imx25.1");
 	clk_register_clkdev(clk[esdhc2_ahb], "ahb", "sdhci-esdhc-imx25.1");
-	clk_register_clkdev(clk[csi_ipg_per], "per", "mx2-camera.0");
-	clk_register_clkdev(clk[csi_ipg], "ipg", "mx2-camera.0");
-	clk_register_clkdev(clk[csi_ahb], "ahb", "mx2-camera.0");
+	clk_register_clkdev(clk[csi_ipg_per], "per", "imx25-camera.0");
+	clk_register_clkdev(clk[csi_ipg], "ipg", "imx25-camera.0");
+	clk_register_clkdev(clk[csi_ahb], "ahb", "imx25-camera.0");
 	clk_register_clkdev(clk[dummy], "audmux", NULL);
 	clk_register_clkdev(clk[can1_ipg], NULL, "flexcan.0");
 	clk_register_clkdev(clk[can2_ipg], NULL, "flexcan.1");
@@ -242,5 +302,40 @@ int __init mx25_clocks_init(void)
 	clk_register_clkdev(clk[iim_ipg], "iim", NULL);
 
 	mxc_timer_init(MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), MX25_INT_GPT1);
+
+	return 0;
+}
+
+int __init mx25_clocks_init_dt(void)
+{
+	struct device_node *np;
+	void __iomem *base;
+	int irq;
+	unsigned long osc_rate = 24000000;
+
+	/* retrieve the freqency of fixed clocks from device tree */
+	for_each_compatible_node(np, NULL, "fixed-clock") {
+		u32 rate;
+		if (of_property_read_u32(np, "clock-frequency", &rate))
+			continue;
+
+		if (of_device_is_compatible(np, "fsl,imx-osc"))
+			osc_rate = rate;
+	}
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx25-ccm");
+	clk_data.clks = clk;
+	clk_data.clk_num = ARRAY_SIZE(clk);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+	__mx25_clocks_init(osc_rate);
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx25-gpt");
+	base = of_iomap(np, 0);
+	WARN_ON(!base);
+	irq = irq_of_parse_and_map(np, 0);
+
+	mxc_timer_init(base, irq);
+
 	return 0;
 }
diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c
index 366e5d5..4c1d1e4 100644
--- a/arch/arm/mach-imx/clk-imx27.c
+++ b/arch/arm/mach-imx/clk-imx27.c
@@ -6,9 +6,9 @@
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
 #include "clk.h"
+#include "common.h"
+#include "hardware.h"
 
 #define IO_ADDR_CCM(off)	(MX27_IO_ADDRESS(MX27_CCM_BASE_ADDR + (off)))
 
@@ -51,8 +51,10 @@
 
 static const char *vpu_sel_clks[] = { "spll", "mpll_main2", };
 static const char *cpu_sel_clks[] = { "mpll_main2", "mpll", };
+static const char *mpll_sel_clks[] = { "fpm", "mpll_osc_sel", };
+static const char *mpll_osc_sel_clks[] = { "ckih", "ckih_div1p5", };
 static const char *clko_sel_clks[] = {
-	"ckil", "prem", "ckih", "ckih",
+	"ckil", "fpm", "ckih", "ckih",
 	"ckih", "mpll", "spll", "cpu_div",
 	"ahb", "ipg", "per1_div", "per2_div",
 	"per3_div", "per4_div", "ssi1_div", "ssi2_div",
@@ -79,7 +81,8 @@ enum mx27_clks {
 	vpu_ahb_gate, fec_ahb_gate, emma_ahb_gate, emi_ahb_gate, dma_ahb_gate,
 	csi_ahb_gate, brom_ahb_gate, ata_ahb_gate, wdog_ipg_gate, usb_ipg_gate,
 	uart6_ipg_gate, uart5_ipg_gate, uart4_ipg_gate, uart3_ipg_gate,
-	uart2_ipg_gate, uart1_ipg_gate, clk_max
+	uart2_ipg_gate, uart1_ipg_gate, ckih_div1p5, fpm, mpll_osc_sel,
+	mpll_sel, clk_max
 };
 
 static struct clk *clk[clk_max];
@@ -91,7 +94,15 @@ int __init mx27_clocks_init(unsigned long fref)
 	clk[dummy] = imx_clk_fixed("dummy", 0);
 	clk[ckih] = imx_clk_fixed("ckih", fref);
 	clk[ckil] = imx_clk_fixed("ckil", 32768);
-	clk[mpll] = imx_clk_pllv1("mpll", "ckih", CCM_MPCTL0);
+	clk[fpm] = imx_clk_fixed_factor("fpm", "ckil", 1024, 1);
+	clk[ckih_div1p5] = imx_clk_fixed_factor("ckih_div1p5", "ckih", 2, 3);
+
+	clk[mpll_osc_sel] = imx_clk_mux("mpll_osc_sel", CCM_CSCR, 4, 1,
+			mpll_osc_sel_clks,
+			ARRAY_SIZE(mpll_osc_sel_clks));
+	clk[mpll_sel] = imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks,
+			ARRAY_SIZE(mpll_sel_clks));
+	clk[mpll] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0);
 	clk[spll] = imx_clk_pllv1("spll", "ckih", CCM_SPCTL0);
 	clk[mpll_main2] = imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3);
 
@@ -211,19 +222,20 @@ int __init mx27_clocks_init(unsigned long fref)
 	clk_register_clkdev(clk[gpt6_ipg_gate], "ipg", "imx-gpt.5");
 	clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.5");
 	clk_register_clkdev(clk[pwm_ipg_gate], NULL, "mxc_pwm.0");
-	clk_register_clkdev(clk[per2_gate], "per", "mxc-mmc.0");
-	clk_register_clkdev(clk[sdhc1_ipg_gate], "ipg", "mxc-mmc.0");
-	clk_register_clkdev(clk[per2_gate], "per", "mxc-mmc.1");
-	clk_register_clkdev(clk[sdhc2_ipg_gate], "ipg", "mxc-mmc.1");
-	clk_register_clkdev(clk[per2_gate], "per", "mxc-mmc.2");
-	clk_register_clkdev(clk[sdhc2_ipg_gate], "ipg", "mxc-mmc.2");
+	clk_register_clkdev(clk[per2_gate], "per", "imx21-mmc.0");
+	clk_register_clkdev(clk[sdhc1_ipg_gate], "ipg", "imx21-mmc.0");
+	clk_register_clkdev(clk[per2_gate], "per", "imx21-mmc.1");
+	clk_register_clkdev(clk[sdhc2_ipg_gate], "ipg", "imx21-mmc.1");
+	clk_register_clkdev(clk[per2_gate], "per", "imx21-mmc.2");
+	clk_register_clkdev(clk[sdhc2_ipg_gate], "ipg", "imx21-mmc.2");
 	clk_register_clkdev(clk[cspi1_ipg_gate], NULL, "imx27-cspi.0");
 	clk_register_clkdev(clk[cspi2_ipg_gate], NULL, "imx27-cspi.1");
 	clk_register_clkdev(clk[cspi3_ipg_gate], NULL, "imx27-cspi.2");
-	clk_register_clkdev(clk[per3_gate], "per", "imx-fb.0");
-	clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx-fb.0");
-	clk_register_clkdev(clk[lcdc_ahb_gate], "ahb", "imx-fb.0");
-	clk_register_clkdev(clk[csi_ahb_gate], "ahb", "mx2-camera.0");
+	clk_register_clkdev(clk[per3_gate], "per", "imx21-fb.0");
+	clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx21-fb.0");
+	clk_register_clkdev(clk[lcdc_ahb_gate], "ahb", "imx21-fb.0");
+	clk_register_clkdev(clk[csi_ahb_gate], "ahb", "imx27-camera.0");
+	clk_register_clkdev(clk[per4_gate], "per", "imx27-camera.0");
 	clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");
 	clk_register_clkdev(clk[usb_ipg_gate], "ipg", "fsl-usb2-udc");
 	clk_register_clkdev(clk[usb_ahb_gate], "ahb", "fsl-usb2-udc");
@@ -238,27 +250,27 @@ int __init mx27_clocks_init(unsigned long fref)
 	clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.2");
 	clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0");
 	clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1");
-	clk_register_clkdev(clk[nfc_baud_gate], NULL, "mxc_nand.0");
+	clk_register_clkdev(clk[nfc_baud_gate], NULL, "imx27-nand.0");
 	clk_register_clkdev(clk[vpu_baud_gate], "per", "coda-imx27.0");
 	clk_register_clkdev(clk[vpu_ahb_gate], "ahb", "coda-imx27.0");
-	clk_register_clkdev(clk[dma_ahb_gate], "ahb", "imx-dma");
-	clk_register_clkdev(clk[dma_ipg_gate], "ipg", "imx-dma");
+	clk_register_clkdev(clk[dma_ahb_gate], "ahb", "imx27-dma");
+	clk_register_clkdev(clk[dma_ipg_gate], "ipg", "imx27-dma");
 	clk_register_clkdev(clk[fec_ipg_gate], "ipg", "imx27-fec.0");
 	clk_register_clkdev(clk[fec_ahb_gate], "ahb", "imx27-fec.0");
 	clk_register_clkdev(clk[wdog_ipg_gate], NULL, "imx2-wdt.0");
-	clk_register_clkdev(clk[i2c1_ipg_gate], NULL, "imx-i2c.0");
-	clk_register_clkdev(clk[i2c2_ipg_gate], NULL, "imx-i2c.1");
+	clk_register_clkdev(clk[i2c1_ipg_gate], NULL, "imx21-i2c.0");
+	clk_register_clkdev(clk[i2c2_ipg_gate], NULL, "imx21-i2c.1");
 	clk_register_clkdev(clk[owire_ipg_gate], NULL, "mxc_w1.0");
 	clk_register_clkdev(clk[kpp_ipg_gate], NULL, "imx-keypad");
-	clk_register_clkdev(clk[emma_ahb_gate], "emma-ahb", "mx2-camera.0");
-	clk_register_clkdev(clk[emma_ipg_gate], "emma-ipg", "mx2-camera.0");
+	clk_register_clkdev(clk[emma_ahb_gate], "emma-ahb", "imx27-camera.0");
+	clk_register_clkdev(clk[emma_ipg_gate], "emma-ipg", "imx27-camera.0");
 	clk_register_clkdev(clk[emma_ahb_gate], "ahb", "m2m-emmaprp.0");
 	clk_register_clkdev(clk[emma_ipg_gate], "ipg", "m2m-emmaprp.0");
 	clk_register_clkdev(clk[iim_ipg_gate], "iim", NULL);
 	clk_register_clkdev(clk[gpio_ipg_gate], "gpio", NULL);
 	clk_register_clkdev(clk[brom_ahb_gate], "brom", NULL);
 	clk_register_clkdev(clk[ata_ahb_gate], "ata", NULL);
-	clk_register_clkdev(clk[rtc_ipg_gate], NULL, "mxc_rtc");
+	clk_register_clkdev(clk[rtc_ipg_gate], NULL, "imx21-rtc");
 	clk_register_clkdev(clk[scc_ipg_gate], "scc", NULL);
 	clk_register_clkdev(clk[cpu_div], "cpu", NULL);
 	clk_register_clkdev(clk[emi_ahb_gate], "emi_ahb" , NULL);
diff --git a/arch/arm/mach-imx/clk-imx31.c b/arch/arm/mach-imx/clk-imx31.c
index 1253af2..8be64e0 100644
--- a/arch/arm/mach-imx/clk-imx31.c
+++ b/arch/arm/mach-imx/clk-imx31.c
@@ -22,12 +22,11 @@
 #include <linux/err.h>
 #include <linux/of.h>
 
-#include <mach/hardware.h>
-#include <mach/mx31.h>
-#include <mach/common.h>
-
 #include "clk.h"
+#include "common.h"
 #include "crmregs-imx3.h"
+#include "hardware.h"
+#include "mx31.h"
 
 static const char *mcu_main_sel[] = { "spll", "mpll", };
 static const char *per_sel[] = { "per_div", "ipg", };
@@ -124,10 +123,10 @@ int __init mx31_clocks_init(unsigned long fref)
 	clk_register_clkdev(clk[cspi3_gate], NULL, "imx31-cspi.2");
 	clk_register_clkdev(clk[pwm_gate], "pwm", NULL);
 	clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
-	clk_register_clkdev(clk[rtc_gate], NULL, "mxc_rtc");
+	clk_register_clkdev(clk[rtc_gate], NULL, "imx21-rtc");
 	clk_register_clkdev(clk[epit1_gate], "epit", NULL);
 	clk_register_clkdev(clk[epit2_gate], "epit", NULL);
-	clk_register_clkdev(clk[nfc], NULL, "mxc_nand.0");
+	clk_register_clkdev(clk[nfc], NULL, "imx27-nand.0");
 	clk_register_clkdev(clk[ipu_gate], NULL, "ipu-core");
 	clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb");
 	clk_register_clkdev(clk[kpp_gate], NULL, "imx-keypad");
@@ -155,12 +154,12 @@ int __init mx31_clocks_init(unsigned long fref)
 	clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.3");
 	clk_register_clkdev(clk[uart5_gate], "per", "imx21-uart.4");
 	clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.4");
-	clk_register_clkdev(clk[i2c1_gate], NULL, "imx-i2c.0");
-	clk_register_clkdev(clk[i2c2_gate], NULL, "imx-i2c.1");
-	clk_register_clkdev(clk[i2c3_gate], NULL, "imx-i2c.2");
+	clk_register_clkdev(clk[i2c1_gate], NULL, "imx21-i2c.0");
+	clk_register_clkdev(clk[i2c2_gate], NULL, "imx21-i2c.1");
+	clk_register_clkdev(clk[i2c3_gate], NULL, "imx21-i2c.2");
 	clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1.0");
-	clk_register_clkdev(clk[sdhc1_gate], NULL, "mxc-mmc.0");
-	clk_register_clkdev(clk[sdhc2_gate], NULL, "mxc-mmc.1");
+	clk_register_clkdev(clk[sdhc1_gate], NULL, "imx31-mmc.0");
+	clk_register_clkdev(clk[sdhc2_gate], NULL, "imx31-mmc.1");
 	clk_register_clkdev(clk[ssi1_gate], NULL, "imx-ssi.0");
 	clk_register_clkdev(clk[ssi2_gate], NULL, "imx-ssi.1");
 	clk_register_clkdev(clk[firi_gate], "firi", NULL);
diff --git a/arch/arm/mach-imx/clk-imx35.c b/arch/arm/mach-imx/clk-imx35.c
index 177259b..66f3d65 100644
--- a/arch/arm/mach-imx/clk-imx35.c
+++ b/arch/arm/mach-imx/clk-imx35.c
@@ -14,11 +14,10 @@
 #include <linux/of.h>
 #include <linux/err.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-
 #include "crmregs-imx3.h"
 #include "clk.h"
+#include "common.h"
+#include "hardware.h"
 
 struct arm_ahb_div {
 	unsigned char arm, ahb, sel;
@@ -226,9 +225,9 @@ int __init mx35_clocks_init()
 	clk_register_clkdev(clk[fec_gate], NULL, "imx27-fec.0");
 	clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0");
 	clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
-	clk_register_clkdev(clk[i2c1_gate], NULL, "imx-i2c.0");
-	clk_register_clkdev(clk[i2c2_gate], NULL, "imx-i2c.1");
-	clk_register_clkdev(clk[i2c3_gate], NULL, "imx-i2c.2");
+	clk_register_clkdev(clk[i2c1_gate], NULL, "imx21-i2c.0");
+	clk_register_clkdev(clk[i2c2_gate], NULL, "imx21-i2c.1");
+	clk_register_clkdev(clk[i2c3_gate], NULL, "imx21-i2c.2");
 	clk_register_clkdev(clk[ipu_gate], NULL, "ipu-core");
 	clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb");
 	clk_register_clkdev(clk[kpp_gate], NULL, "imx-keypad");
@@ -256,7 +255,7 @@ int __init mx35_clocks_init()
 	clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
 	clk_register_clkdev(clk[usbotg_gate], "ahb", "fsl-usb2-udc");
 	clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
-	clk_register_clkdev(clk[nfc_div], NULL, "mxc_nand.0");
+	clk_register_clkdev(clk[nfc_div], NULL, "imx25-nand.0");
 	clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
 
 	clk_prepare_enable(clk[spba_gate]);
diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c
index a0bf848..e8c0473 100644
--- a/arch/arm/mach-imx/clk-imx51-imx53.c
+++ b/arch/arm/mach-imx/clk-imx51-imx53.c
@@ -14,11 +14,10 @@
 #include <linux/of.h>
 #include <linux/err.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-
 #include "crm-regs-imx5.h"
 #include "clk.h"
+#include "common.h"
+#include "hardware.h"
 
 /* Low-power Audio Playback Mode clock */
 static const char *lp_apm_sel[] = { "osc", };
@@ -88,6 +87,7 @@ enum imx5_clks {
 };
 
 static struct clk *clk[clk_max];
+static struct clk_onecell_data clk_data;
 
 static void __init mx5_clocks_common_init(unsigned long rate_ckil,
 		unsigned long rate_osc, unsigned long rate_ckih1,
@@ -258,8 +258,8 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
 	clk_register_clkdev(clk[cspi_ipg_gate], NULL, "imx35-cspi.2");
 	clk_register_clkdev(clk[pwm1_ipg_gate], "pwm", "mxc_pwm.0");
 	clk_register_clkdev(clk[pwm2_ipg_gate], "pwm", "mxc_pwm.1");
-	clk_register_clkdev(clk[i2c1_gate], NULL, "imx-i2c.0");
-	clk_register_clkdev(clk[i2c2_gate], NULL, "imx-i2c.1");
+	clk_register_clkdev(clk[i2c1_gate], NULL, "imx21-i2c.0");
+	clk_register_clkdev(clk[i2c2_gate], NULL, "imx21-i2c.1");
 	clk_register_clkdev(clk[usboh3_per_gate], "per", "mxc-ehci.0");
 	clk_register_clkdev(clk[usboh3_gate], "ipg", "mxc-ehci.0");
 	clk_register_clkdev(clk[usboh3_gate], "ahb", "mxc-ehci.0");
@@ -272,7 +272,7 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
 	clk_register_clkdev(clk[usboh3_per_gate], "per", "fsl-usb2-udc");
 	clk_register_clkdev(clk[usboh3_gate], "ipg", "fsl-usb2-udc");
 	clk_register_clkdev(clk[usboh3_gate], "ahb", "fsl-usb2-udc");
-	clk_register_clkdev(clk[nfc_gate], NULL, "mxc_nand");
+	clk_register_clkdev(clk[nfc_gate], NULL, "imx51-nand");
 	clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0");
 	clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1");
 	clk_register_clkdev(clk[ssi3_ipg_gate], NULL, "imx-ssi.2");
@@ -306,6 +306,10 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
 	clk_prepare_enable(clk[spba]);
 	clk_prepare_enable(clk[emi_fast_gate]); /* fec */
 	clk_prepare_enable(clk[emi_slow_gate]); /* eim */
+	clk_prepare_enable(clk[mipi_hsc1_gate]);
+	clk_prepare_enable(clk[mipi_hsc2_gate]);
+	clk_prepare_enable(clk[mipi_esc_gate]);
+	clk_prepare_enable(clk[mipi_hsp_gate]);
 	clk_prepare_enable(clk[tmax1]);
 	clk_prepare_enable(clk[tmax2]); /* esdhc2, fec */
 	clk_prepare_enable(clk[tmax3]); /* esdhc1, esdhc4 */
@@ -315,6 +319,7 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 			unsigned long rate_ckih1, unsigned long rate_ckih2)
 {
 	int i;
+	struct device_node *np;
 
 	clk[pll1_sw] = imx_clk_pllv2("pll1_sw", "osc", MX51_DPLL1_BASE);
 	clk[pll2_sw] = imx_clk_pllv2("pll2_sw", "osc", MX51_DPLL2_BASE);
@@ -343,16 +348,20 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 			pr_err("i.MX51 clk %d: register failed with %ld\n",
 				i, PTR_ERR(clk[i]));
 
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx51-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);
 
-	clk_register_clkdev(clk[hsi2c_gate], NULL, "imx-i2c.2");
+	clk_register_clkdev(clk[hsi2c_gate], NULL, "imx21-i2c.2");
 	clk_register_clkdev(clk[mx51_mipi], "mipi_hsp", NULL);
 	clk_register_clkdev(clk[vpu_gate], NULL, "imx51-vpu.0");
 	clk_register_clkdev(clk[fec_gate], NULL, "imx27-fec.0");
-	clk_register_clkdev(clk[ipu_gate], "bus", "imx51-ipu");
-	clk_register_clkdev(clk[ipu_di0_gate], "di0", "imx51-ipu");
-	clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx51-ipu");
-	clk_register_clkdev(clk[ipu_gate], "hsp", "imx51-ipu");
+	clk_register_clkdev(clk[ipu_gate], "bus", "40000000.ipu");
+	clk_register_clkdev(clk[ipu_di0_gate], "di0", "40000000.ipu");
+	clk_register_clkdev(clk[ipu_di1_gate], "di1", "40000000.ipu");
 	clk_register_clkdev(clk[usb_phy_gate], "phy", "mxc-ehci.0");
 	clk_register_clkdev(clk[esdhc1_ipg_gate], "ipg", "sdhci-esdhc-imx51.0");
 	clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx51.0");
@@ -366,10 +375,6 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 	clk_register_clkdev(clk[esdhc4_ipg_gate], "ipg", "sdhci-esdhc-imx51.3");
 	clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx51.3");
 	clk_register_clkdev(clk[esdhc4_per_gate], "per", "sdhci-esdhc-imx51.3");
-	clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "83fcc000.ssi");
-	clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "70014000.ssi");
-	clk_register_clkdev(clk[ssi3_ipg_gate], NULL, "83fe8000.ssi");
-	clk_register_clkdev(clk[nfc_gate], NULL, "83fdb000.nand");
 
 	/* set the usboh3 parent to pll2_sw */
 	clk_set_parent(clk[usboh3_sel], clk[pll2_sw]);
@@ -393,6 +398,7 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 {
 	int i;
 	unsigned long r;
+	struct device_node *np;
 
 	clk[pll1_sw] = imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE);
 	clk[pll2_sw] = imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE);
@@ -437,15 +443,20 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 			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);
 
 	clk_register_clkdev(clk[vpu_gate], NULL, "imx53-vpu.0");
-	clk_register_clkdev(clk[i2c3_gate], NULL, "imx-i2c.2");
+	clk_register_clkdev(clk[i2c3_gate], NULL, "imx21-i2c.2");
 	clk_register_clkdev(clk[fec_gate], NULL, "imx25-fec.0");
-	clk_register_clkdev(clk[ipu_gate], "bus", "imx53-ipu");
-	clk_register_clkdev(clk[ipu_di0_gate], "di0", "imx53-ipu");
-	clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx53-ipu");
-	clk_register_clkdev(clk[ipu_gate], "hsp", "imx53-ipu");
+	clk_register_clkdev(clk[ipu_gate], "bus", "18000000.ipu");
+	clk_register_clkdev(clk[ipu_di0_gate], "di0", "18000000.ipu");
+	clk_register_clkdev(clk[ipu_di1_gate], "di1", "18000000.ipu");
+	clk_register_clkdev(clk[ipu_gate], "hsp", "18000000.ipu");
 	clk_register_clkdev(clk[usb_phy1_gate], "usb_phy1", "mxc-ehci.0");
 	clk_register_clkdev(clk[esdhc1_ipg_gate], "ipg", "sdhci-esdhc-imx53.0");
 	clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx53.0");
@@ -459,14 +470,6 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 	clk_register_clkdev(clk[esdhc4_ipg_gate], "ipg", "sdhci-esdhc-imx53.3");
 	clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx53.3");
 	clk_register_clkdev(clk[esdhc4_per_gate], "per", "sdhci-esdhc-imx53.3");
-	clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "63fcc000.ssi");
-	clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "50014000.ssi");
-	clk_register_clkdev(clk[ssi3_ipg_gate], NULL, "63fd0000.ssi");
-	clk_register_clkdev(clk[nfc_gate], NULL, "63fdb000.nand");
-	clk_register_clkdev(clk[can1_ipg_gate], "ipg", "53fc8000.can");
-	clk_register_clkdev(clk[can1_serial_gate], "per", "53fc8000.can");
-	clk_register_clkdev(clk[can2_ipg_gate], "ipg", "53fcc000.can");
-	clk_register_clkdev(clk[can2_serial_gate], "per", "53fcc000.can");
 
 	/* set SDHC root clock to 200MHZ*/
 	clk_set_rate(clk[esdhc_a_podf], 200000000);
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 3ec242f..7f2c10c 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -19,8 +19,9 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#include <mach/common.h>
+
 #include "clk.h"
+#include "common.h"
 
 #define CCGR0				0x68
 #define CCGR1				0x6c
@@ -104,7 +105,7 @@ static const char *gpu2d_core_sels[]	= { "axi", "pll3_usb_otg", "pll2_pfd0_352m"
 static const char *gpu3d_core_sels[]	= { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", };
 static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd9_720m", };
 static const char *ipu_sels[]		= { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
-static const char *ldb_di_sels[]	= { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", };
+static const char *ldb_di_sels[]	= { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_pfd1_540m", };
 static const char *ipu_di_pre_sels[]	= { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", };
 static const char *ipu1_di0_sels[]	= { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
 static const char *ipu1_di1_sels[]	= { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
@@ -151,8 +152,9 @@ enum mx6q_clks {
 	gpmi_bch_apb, gpmi_bch, gpmi_io, gpmi_apb, sata, sdma, spba, ssi1,
 	ssi2, ssi3, uart_ipg, uart_serial, usboh3, usdhc1, usdhc2, usdhc3,
 	usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg,
-	pll4_audio, pll5_video, pll6_mlb, pll7_usb_host, pll8_enet, ssi1_ipg,
+	pll4_audio, pll5_video, pll8_mlb, pll7_usb_host, pll6_enet, ssi1_ipg,
 	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,
 	clk_max
 };
 
@@ -163,6 +165,13 @@ static enum mx6q_clks const clks_init_on[] __initconst = {
 	mmdc_ch0_axi, rom,
 };
 
+static struct clk_div_table clk_enet_ref_table[] = {
+	{ .val = 0, .div = 20, },
+	{ .val = 1, .div = 10, },
+	{ .val = 2, .div = 5, },
+	{ .val = 3, .div = 4, },
+};
+
 int __init mx6q_clocks_init(void)
 {
 	struct device_node *np;
@@ -189,19 +198,29 @@ int __init mx6q_clocks_init(void)
 	base = of_iomap(np, 0);
 	WARN_ON(!base);
 
-	/*                   type                               name         parent_name  base     gate_mask div_mask */
-	clk[pll1_sys]      = imx_clk_pllv3(IMX_PLLV3_SYS,	"pll1_sys",	"osc", base,        0x2000,   0x7f);
-	clk[pll2_bus]      = imx_clk_pllv3(IMX_PLLV3_GENERIC,	"pll2_bus",	"osc", base + 0x30, 0x2000,   0x1);
-	clk[pll3_usb_otg]  = imx_clk_pllv3(IMX_PLLV3_USB,	"pll3_usb_otg",	"osc", base + 0x10, 0x2000,   0x3);
-	clk[pll4_audio]    = imx_clk_pllv3(IMX_PLLV3_AV,	"pll4_audio",	"osc", base + 0x70, 0x2000,   0x7f);
-	clk[pll5_video]    = imx_clk_pllv3(IMX_PLLV3_AV,	"pll5_video",	"osc", base + 0xa0, 0x2000,   0x7f);
-	clk[pll6_mlb]      = imx_clk_pllv3(IMX_PLLV3_MLB,	"pll6_mlb",	"osc", base + 0xd0, 0x2000,   0x0);
-	clk[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB,	"pll7_usb_host","osc", base + 0x20, 0x2000,   0x3);
-	clk[pll8_enet]     = imx_clk_pllv3(IMX_PLLV3_ENET,	"pll8_enet",	"osc", base + 0xe0, 0x182000, 0x3);
+	/*                   type                               name         parent_name  base     div_mask */
+	clk[pll1_sys]      = imx_clk_pllv3(IMX_PLLV3_SYS,	"pll1_sys",	"osc", base,        0x7f);
+	clk[pll2_bus]      = imx_clk_pllv3(IMX_PLLV3_GENERIC,	"pll2_bus",	"osc", base + 0x30, 0x1);
+	clk[pll3_usb_otg]  = imx_clk_pllv3(IMX_PLLV3_USB,	"pll3_usb_otg",	"osc", base + 0x10, 0x3);
+	clk[pll4_audio]    = imx_clk_pllv3(IMX_PLLV3_AV,	"pll4_audio",	"osc", base + 0x70, 0x7f);
+	clk[pll5_video]    = imx_clk_pllv3(IMX_PLLV3_AV,	"pll5_video",	"osc", base + 0xa0, 0x7f);
+	clk[pll6_enet]     = imx_clk_pllv3(IMX_PLLV3_ENET,	"pll6_enet",	"osc", base + 0xe0, 0x3);
+	clk[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB,	"pll7_usb_host","osc", base + 0x20, 0x3);
+	clk[pll8_mlb]      = imx_clk_pllv3(IMX_PLLV3_MLB,	"pll8_mlb",	"osc", base + 0xd0, 0x0);
 
 	clk[usbphy1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 6);
 	clk[usbphy2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 6);
 
+	clk[sata_ref] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 5);
+	clk[pcie_ref] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 4);
+
+	clk[sata_ref_100m] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20);
+	clk[pcie_ref_125m] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
+
+	clk[enet_ref] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
+			base + 0xe0, 0, 2, 0, clk_enet_ref_table,
+			&imx_ccm_lock);
+
 	/*                                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);
@@ -357,7 +376,7 @@ int __init mx6q_clocks_init(void)
 	clk[ldb_di1]      = imx_clk_gate2("ldb_di1",       "ldb_di1_podf",      base + 0x74, 14);
 	clk[ipu2_di1]     = imx_clk_gate2("ipu2_di1",      "ipu2_di1_sel",      base + 0x74, 10);
 	clk[hsi_tx]       = imx_clk_gate2("hsi_tx",        "hsi_tx_podf",       base + 0x74, 16);
-	clk[mlb]          = imx_clk_gate2("mlb",           "pll6_mlb",          base + 0x74, 18);
+	clk[mlb]          = imx_clk_gate2("mlb",           "pll8_mlb",          base + 0x74, 18);
 	clk[mmdc_ch0_axi] = imx_clk_gate2("mmdc_ch0_axi",  "mmdc_ch0_axi_podf", base + 0x74, 20);
 	clk[mmdc_ch1_axi] = imx_clk_gate2("mmdc_ch1_axi",  "mmdc_ch1_axi_podf", base + 0x74, 22);
 	clk[ocram]        = imx_clk_gate2("ocram",         "ahb",               base + 0x74, 28);
@@ -405,6 +424,7 @@ int __init mx6q_clocks_init(void)
 	clk_register_clkdev(clk[cko1_sel], "cko1_sel", NULL);
 	clk_register_clkdev(clk[ahb], "ahb", NULL);
 	clk_register_clkdev(clk[cko1], "cko1", NULL);
+	clk_register_clkdev(clk[arm], NULL, "cpu0");
 
 	/*
 	 * The gpmi needs 100MHz frequency in the EDO/Sync mode,
diff --git a/arch/arm/mach-imx/clk-pllv1.c b/arch/arm/mach-imx/clk-pllv1.c
index 02be731..abff350 100644
--- a/arch/arm/mach-imx/clk-pllv1.c
+++ b/arch/arm/mach-imx/clk-pllv1.c
@@ -4,10 +4,10 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/err.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
 
 #include "clk.h"
+#include "common.h"
+#include "hardware.h"
 
 /**
  * pll v1
diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c
index 36aac94..d09bc3d 100644
--- a/arch/arm/mach-imx/clk-pllv3.c
+++ b/arch/arm/mach-imx/clk-pllv3.c
@@ -31,7 +31,6 @@
  * @clk_hw:	 clock source
  * @base:	 base address of PLL registers
  * @powerup_set: set POWER bit to power up the PLL
- * @gate_mask:	 mask of gate bits
  * @div_mask:	 mask of divider bits
  *
  * IMX PLL clock version 3, found on i.MX6 series.  Divider for pllv3
@@ -41,7 +40,6 @@ struct clk_pllv3 {
 	struct clk_hw	hw;
 	void __iomem	*base;
 	bool		powerup_set;
-	u32		gate_mask;
 	u32		div_mask;
 };
 
@@ -89,7 +87,7 @@ static int clk_pllv3_enable(struct clk_hw *hw)
 	u32 val;
 
 	val = readl_relaxed(pll->base);
-	val |= pll->gate_mask;
+	val |= BM_PLL_ENABLE;
 	writel_relaxed(val, pll->base);
 
 	return 0;
@@ -101,7 +99,7 @@ static void clk_pllv3_disable(struct clk_hw *hw)
 	u32 val;
 
 	val = readl_relaxed(pll->base);
-	val &= ~pll->gate_mask;
+	val &= ~BM_PLL_ENABLE;
 	writel_relaxed(val, pll->base);
 }
 
@@ -287,66 +285,7 @@ static const struct clk_ops clk_pllv3_av_ops = {
 static unsigned long clk_pllv3_enet_recalc_rate(struct clk_hw *hw,
 						unsigned long parent_rate)
 {
-	struct clk_pllv3 *pll = to_clk_pllv3(hw);
-	u32 div = readl_relaxed(pll->base) & pll->div_mask;
-
-	switch (div) {
-	case 0:
-		return 25000000;
-	case 1:
-		return 50000000;
-	case 2:
-		return 100000000;
-	case 3:
-		return 125000000;
-	}
-
-	return 0;
-}
-
-static long clk_pllv3_enet_round_rate(struct clk_hw *hw, unsigned long rate,
-				      unsigned long *prate)
-{
-	if (rate >= 125000000)
-		rate = 125000000;
-	else if (rate >= 100000000)
-		rate = 100000000;
-	else if (rate >= 50000000)
-		rate = 50000000;
-	else
-		rate = 25000000;
-	return rate;
-}
-
-static int clk_pllv3_enet_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	struct clk_pllv3 *pll = to_clk_pllv3(hw);
-	u32 val, div;
-
-	switch (rate) {
-	case 25000000:
-		div = 0;
-		break;
-	case 50000000:
-		div = 1;
-		break;
-	case 100000000:
-		div = 2;
-		break;
-	case 125000000:
-		div = 3;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	val = readl_relaxed(pll->base);
-	val &= ~pll->div_mask;
-	val |= div;
-	writel_relaxed(val, pll->base);
-
-	return 0;
+	return 500000000;
 }
 
 static const struct clk_ops clk_pllv3_enet_ops = {
@@ -355,8 +294,6 @@ static const struct clk_ops clk_pllv3_enet_ops = {
 	.enable		= clk_pllv3_enable,
 	.disable	= clk_pllv3_disable,
 	.recalc_rate	= clk_pllv3_enet_recalc_rate,
-	.round_rate	= clk_pllv3_enet_round_rate,
-	.set_rate	= clk_pllv3_enet_set_rate,
 };
 
 static const struct clk_ops clk_pllv3_mlb_ops = {
@@ -368,7 +305,7 @@ static const struct clk_ops clk_pllv3_mlb_ops = {
 
 struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
 			  const char *parent_name, void __iomem *base,
-			  u32 gate_mask, u32 div_mask)
+			  u32 div_mask)
 {
 	struct clk_pllv3 *pll;
 	const struct clk_ops *ops;
@@ -400,7 +337,6 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
 		ops = &clk_pllv3_ops;
 	}
 	pll->base = base;
-	pll->gate_mask = gate_mask;
 	pll->div_mask = div_mask;
 
 	init.name = name;
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index 5f2d8ac..9d1f3b9 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -22,8 +22,7 @@ enum imx_pllv3_type {
 };
 
 struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
-		const char *parent_name, void __iomem *base, u32 gate_mask,
-		u32 div_mask);
+		const char *parent_name, void __iomem *base, u32 div_mask);
 
 struct clk *clk_register_gate2(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
new file mode 100644
index 0000000..7191ab4
--- /dev/null
+++ b/arch/arm/mach-imx/common.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_MXC_COMMON_H__
+#define __ASM_ARCH_MXC_COMMON_H__
+
+struct platform_device;
+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 mx50_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 imx50_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 mx50_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 imx50_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,
+			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 int mx6q_clocks_init(void);
+extern struct platform_device *mxc_register_gpio(char *name, int id,
+	resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);
+extern void mxc_set_cpu_type(unsigned int type);
+extern void mxc_restart(char, const char *);
+extern void mxc_arch_reset_init(void __iomem *);
+extern int mx53_revision(void);
+extern int mx53_display_revision(void);
+extern void imx_set_aips(void __iomem *);
+extern int mxc_device_init(void);
+
+enum mxc_cpu_pwr_mode {
+	WAIT_CLOCKED,		/* wfi only */
+	WAIT_UNCLOCKED,		/* WAIT */
+	WAIT_UNCLOCKED_POWER_OFF,	/* WAIT + SRPG */
+	STOP_POWER_ON,		/* just STOP */
+	STOP_POWER_OFF,		/* STOP + SRPG */
+};
+
+enum mx3_cpu_pwr_mode {
+	MX3_RUN,
+	MX3_WAIT,
+	MX3_DOZE,
+	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 avic_handle_irq(struct pt_regs *);
+void tzic_handle_irq(struct pt_regs *);
+
+#define imx1_handle_irq avic_handle_irq
+#define imx21_handle_irq avic_handle_irq
+#define imx25_handle_irq avic_handle_irq
+#define imx27_handle_irq avic_handle_irq
+#define imx31_handle_irq avic_handle_irq
+#define imx35_handle_irq avic_handle_irq
+#define imx50_handle_irq tzic_handle_irq
+#define imx51_handle_irq tzic_handle_irq
+#define imx53_handle_irq tzic_handle_irq
+#define imx6q_handle_irq gic_handle_irq
+
+extern void imx_enable_cpu(int cpu, bool enable);
+extern void imx_set_cpu_jump(int cpu, void *jump_addr);
+#ifdef CONFIG_DEBUG_LL
+extern void imx_lluart_map_io(void);
+#else
+static inline void imx_lluart_map_io(void) {}
+#endif
+extern void v7_cpu_resume(void);
+extern u32 *pl310_get_save_ptr(void);
+#ifdef CONFIG_SMP
+extern void v7_secondary_startup(void);
+extern void imx_scu_map_io(void);
+extern void imx_smp_prepare(void);
+#else
+static inline void imx_scu_map_io(void) {}
+static inline void imx_smp_prepare(void) {}
+#endif
+extern void imx_enable_cpu(int cpu, bool enable);
+extern void imx_set_cpu_jump(int cpu, void *jump_addr);
+extern void imx_src_init(void);
+extern void imx_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 int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
+extern void imx6q_clock_map_io(void);
+
+extern void imx_cpu_die(unsigned int cpu);
+
+#ifdef CONFIG_PM
+extern void imx6q_pm_init(void);
+extern void imx51_pm_init(void);
+extern void imx53_pm_init(void);
+#else
+static inline void imx6q_pm_init(void) {}
+static inline void imx51_pm_init(void) {}
+static inline void imx53_pm_init(void) {}
+#endif
+
+#ifdef CONFIG_NEON
+extern int mx51_neon_fixup(void);
+#else
+static inline int mx51_neon_fixup(void) { return 0; }
+#endif
+
+extern struct smp_operations imx_smp_ops;
+
+#endif
diff --git a/arch/arm/mach-imx/cpu-imx25.c b/arch/arm/mach-imx/cpu-imx25.c
index 6914bcb..96ec64b 100644
--- a/arch/arm/mach-imx/cpu-imx25.c
+++ b/arch/arm/mach-imx/cpu-imx25.c
@@ -11,8 +11,9 @@
  */
 #include <linux/module.h>
 #include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/iim.h>
+
+#include "iim.h"
+#include "hardware.h"
 
 static int mx25_cpu_rev = -1;
 
diff --git a/arch/arm/mach-imx/cpu-imx27.c b/arch/arm/mach-imx/cpu-imx27.c
index ff38e15..fe8d36f 100644
--- a/arch/arm/mach-imx/cpu-imx27.c
+++ b/arch/arm/mach-imx/cpu-imx27.c
@@ -24,7 +24,7 @@
 #include <linux/io.h>
 #include <linux/module.h>
 
-#include <mach/hardware.h>
+#include "hardware.h"
 
 static int mx27_cpu_rev = -1;
 static int mx27_cpu_partnumber;
diff --git a/arch/arm/mach-imx/cpu-imx31.c b/arch/arm/mach-imx/cpu-imx31.c
index 3f2345f..fde1860 100644
--- a/arch/arm/mach-imx/cpu-imx31.c
+++ b/arch/arm/mach-imx/cpu-imx31.c
@@ -11,9 +11,10 @@
 
 #include <linux/module.h>
 #include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/iim.h>
-#include <mach/common.h>
+
+#include "common.h"
+#include "hardware.h"
+#include "iim.h"
 
 static int mx31_cpu_rev = -1;
 
diff --git a/arch/arm/mach-imx/cpu-imx35.c b/arch/arm/mach-imx/cpu-imx35.c
index 846e46e..ec3aaa0 100644
--- a/arch/arm/mach-imx/cpu-imx35.c
+++ b/arch/arm/mach-imx/cpu-imx35.c
@@ -10,8 +10,9 @@
  */
 #include <linux/module.h>
 #include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/iim.h>
+
+#include "hardware.h"
+#include "iim.h"
 
 static int mx35_cpu_rev = -1;
 
diff --git a/arch/arm/mach-imx/cpu-imx5.c b/arch/arm/mach-imx/cpu-imx5.c
index 8eb15a2..d887600 100644
--- a/arch/arm/mach-imx/cpu-imx5.c
+++ b/arch/arm/mach-imx/cpu-imx5.c
@@ -15,9 +15,10 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <mach/hardware.h>
 #include <linux/io.h>
 
+#include "hardware.h"
+
 static int mx5_cpu_rev = -1;
 
 #define IIM_SREV 0x24
diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c
new file mode 100644
index 0000000..03fcbd0
--- /dev/null
+++ b/arch/arm/mach-imx/cpu.c
@@ -0,0 +1,45 @@
+
+#include <linux/module.h>
+#include <linux/io.h>
+
+#include "hardware.h"
+
+unsigned int __mxc_cpu_type;
+EXPORT_SYMBOL(__mxc_cpu_type);
+
+void mxc_set_cpu_type(unsigned int type)
+{
+	__mxc_cpu_type = type;
+}
+
+void imx_print_silicon_rev(const char *cpu, int srev)
+{
+	if (srev == IMX_CHIP_REVISION_UNKNOWN)
+		pr_info("CPU identified as %s, unknown revision\n", cpu);
+	else
+		pr_info("CPU identified as %s, silicon rev %d.%d\n",
+				cpu, (srev >> 4) & 0xf, srev & 0xf);
+}
+
+void __init imx_set_aips(void __iomem *base)
+{
+	unsigned int reg;
+/*
+ * Set all MPROTx to be non-bufferable, trusted for R/W,
+ * not forced to user-mode.
+ */
+	__raw_writel(0x77777777, base + 0x0);
+	__raw_writel(0x77777777, base + 0x4);
+
+/*
+ * Set all OPACRx to be non-bufferable, to not require
+ * supervisor privilege level for access, allow for
+ * write access and untrusted master access.
+ */
+	__raw_writel(0x0, base + 0x40);
+	__raw_writel(0x0, base + 0x44);
+	__raw_writel(0x0, base + 0x48);
+	__raw_writel(0x0, base + 0x4C);
+	reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
+	__raw_writel(reg, base + 0x50);
+}
diff --git a/arch/arm/mach-imx/cpu_op-mx51.c b/arch/arm/mach-imx/cpu_op-mx51.c
index 7b92cd6..b9ef692 100644
--- a/arch/arm/mach-imx/cpu_op-mx51.c
+++ b/arch/arm/mach-imx/cpu_op-mx51.c
@@ -13,9 +13,10 @@
 
 #include <linux/bug.h>
 #include <linux/types.h>
-#include <mach/hardware.h>
 #include <linux/kernel.h>
 
+#include "hardware.h"
+
 static struct cpu_op mx51_cpu_op[] = {
 	{
 	.cpu_rate = 160000000,},
diff --git a/arch/arm/mach-imx/cpufreq.c b/arch/arm/mach-imx/cpufreq.c
new file mode 100644
index 0000000..36e8b39
--- /dev/null
+++ b/arch/arm/mach-imx/cpufreq.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ * A driver for the Freescale Semiconductor i.MXC CPUfreq module.
+ * The CPUFREQ driver is for controlling CPU frequency. It allows you to change
+ * the CPU clock speed on the fly.
+ */
+
+#include <linux/module.h>
+#include <linux/cpufreq.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include "hardware.h"
+
+#define CLK32_FREQ	32768
+#define NANOSECOND	(1000 * 1000 * 1000)
+
+struct cpu_op *(*get_cpu_op)(int *op);
+
+static int cpu_freq_khz_min;
+static int cpu_freq_khz_max;
+
+static struct clk *cpu_clk;
+static struct cpufreq_frequency_table *imx_freq_table;
+
+static int cpu_op_nr;
+static struct cpu_op *cpu_op_tbl;
+
+static int set_cpu_freq(int freq)
+{
+	int ret = 0;
+	int org_cpu_rate;
+
+	org_cpu_rate = clk_get_rate(cpu_clk);
+	if (org_cpu_rate == freq)
+		return ret;
+
+	ret = clk_set_rate(cpu_clk, freq);
+	if (ret != 0) {
+		printk(KERN_DEBUG "cannot set CPU clock rate\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static int mxc_verify_speed(struct cpufreq_policy *policy)
+{
+	if (policy->cpu != 0)
+		return -EINVAL;
+
+	return cpufreq_frequency_table_verify(policy, imx_freq_table);
+}
+
+static unsigned int mxc_get_speed(unsigned int cpu)
+{
+	if (cpu)
+		return 0;
+
+	return clk_get_rate(cpu_clk) / 1000;
+}
+
+static int mxc_set_target(struct cpufreq_policy *policy,
+			  unsigned int target_freq, unsigned int relation)
+{
+	struct cpufreq_freqs freqs;
+	int freq_Hz;
+	int ret = 0;
+	unsigned int index;
+
+	cpufreq_frequency_table_target(policy, imx_freq_table,
+			target_freq, relation, &index);
+	freq_Hz = imx_freq_table[index].frequency * 1000;
+
+	freqs.old = clk_get_rate(cpu_clk) / 1000;
+	freqs.new = freq_Hz / 1000;
+	freqs.cpu = 0;
+	freqs.flags = 0;
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	ret = set_cpu_freq(freq_Hz);
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	return ret;
+}
+
+static int mxc_cpufreq_init(struct cpufreq_policy *policy)
+{
+	int ret;
+	int i;
+
+	printk(KERN_INFO "i.MXC CPU frequency driver\n");
+
+	if (policy->cpu != 0)
+		return -EINVAL;
+
+	if (!get_cpu_op)
+		return -EINVAL;
+
+	cpu_clk = clk_get(NULL, "cpu_clk");
+	if (IS_ERR(cpu_clk)) {
+		printk(KERN_ERR "%s: failed to get cpu clock\n", __func__);
+		return PTR_ERR(cpu_clk);
+	}
+
+	cpu_op_tbl = get_cpu_op(&cpu_op_nr);
+
+	cpu_freq_khz_min = cpu_op_tbl[0].cpu_rate / 1000;
+	cpu_freq_khz_max = cpu_op_tbl[0].cpu_rate / 1000;
+
+	imx_freq_table = kmalloc(
+		sizeof(struct cpufreq_frequency_table) * (cpu_op_nr + 1),
+			GFP_KERNEL);
+	if (!imx_freq_table) {
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	for (i = 0; i < cpu_op_nr; i++) {
+		imx_freq_table[i].index = i;
+		imx_freq_table[i].frequency = cpu_op_tbl[i].cpu_rate / 1000;
+
+		if ((cpu_op_tbl[i].cpu_rate / 1000) < cpu_freq_khz_min)
+			cpu_freq_khz_min = cpu_op_tbl[i].cpu_rate / 1000;
+
+		if ((cpu_op_tbl[i].cpu_rate / 1000) > cpu_freq_khz_max)
+			cpu_freq_khz_max = cpu_op_tbl[i].cpu_rate / 1000;
+	}
+
+	imx_freq_table[i].index = i;
+	imx_freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+	policy->cur = clk_get_rate(cpu_clk) / 1000;
+	policy->min = policy->cpuinfo.min_freq = cpu_freq_khz_min;
+	policy->max = policy->cpuinfo.max_freq = cpu_freq_khz_max;
+
+	/* Manual states, that PLL stabilizes in two CLK32 periods */
+	policy->cpuinfo.transition_latency = 2 * NANOSECOND / CLK32_FREQ;
+
+	ret = cpufreq_frequency_table_cpuinfo(policy, imx_freq_table);
+
+	if (ret < 0) {
+		printk(KERN_ERR "%s: failed to register i.MXC CPUfreq with error code %d\n",
+		       __func__, ret);
+		goto err;
+	}
+
+	cpufreq_frequency_table_get_attr(imx_freq_table, policy->cpu);
+	return 0;
+err:
+	kfree(imx_freq_table);
+err1:
+	clk_put(cpu_clk);
+	return ret;
+}
+
+static int mxc_cpufreq_exit(struct cpufreq_policy *policy)
+{
+	cpufreq_frequency_table_put_attr(policy->cpu);
+
+	set_cpu_freq(cpu_freq_khz_max * 1000);
+	clk_put(cpu_clk);
+	kfree(imx_freq_table);
+	return 0;
+}
+
+static struct cpufreq_driver mxc_driver = {
+	.flags = CPUFREQ_STICKY,
+	.verify = mxc_verify_speed,
+	.target = mxc_set_target,
+	.get = mxc_get_speed,
+	.init = mxc_cpufreq_init,
+	.exit = mxc_cpufreq_exit,
+	.name = "imx",
+};
+
+static int __devinit mxc_cpufreq_driver_init(void)
+{
+	return cpufreq_register_driver(&mxc_driver);
+}
+
+static void mxc_cpufreq_driver_exit(void)
+{
+	cpufreq_unregister_driver(&mxc_driver);
+}
+
+module_init(mxc_cpufreq_driver_init);
+module_exit(mxc_cpufreq_driver_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor Inc. Yong Shen <yong.shen@linaro.org>");
+MODULE_DESCRIPTION("CPUfreq driver for i.MX");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-imx/cpuidle.c b/arch/arm/mach-imx/cpuidle.c
new file mode 100644
index 0000000..d4cb511
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/cpuidle.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+static struct cpuidle_device __percpu * imx_cpuidle_devices;
+
+static void __init imx_cpuidle_devices_uninit(void)
+{
+	int cpu_id;
+	struct cpuidle_device *dev;
+
+	for_each_possible_cpu(cpu_id) {
+		dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id);
+		cpuidle_unregister_device(dev);
+	}
+
+	free_percpu(imx_cpuidle_devices);
+}
+
+int __init imx_cpuidle_init(struct cpuidle_driver *drv)
+{
+	struct cpuidle_device *dev;
+	int cpu_id, ret;
+
+	if (drv->state_count > CPUIDLE_STATE_MAX) {
+		pr_err("%s: state_count exceeds maximum\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = cpuidle_register_driver(drv);
+	if (ret) {
+		pr_err("%s: Failed to register cpuidle driver with error: %d\n",
+			 __func__, ret);
+		return ret;
+	}
+
+	imx_cpuidle_devices = alloc_percpu(struct cpuidle_device);
+	if (imx_cpuidle_devices == NULL) {
+		ret = -ENOMEM;
+		goto unregister_drv;
+	}
+
+	/* initialize state data for each cpuidle_device */
+	for_each_possible_cpu(cpu_id) {
+		dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id);
+		dev->cpu = cpu_id;
+		dev->state_count = drv->state_count;
+
+		ret = cpuidle_register_device(dev);
+		if (ret) {
+			pr_err("%s: Failed to register cpu %u, error: %d\n",
+				__func__, cpu_id, ret);
+			goto uninit;
+		}
+	}
+
+	return 0;
+
+uninit:
+	imx_cpuidle_devices_uninit();
+
+unregister_drv:
+	cpuidle_unregister_driver(drv);
+	return ret;
+}
diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h
new file mode 100644
index 0000000..bc932d1
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/cpuidle.h>
+
+#ifdef CONFIG_CPU_IDLE
+extern int imx_cpuidle_init(struct cpuidle_driver *drv);
+#else
+static inline int imx_cpuidle_init(struct cpuidle_driver *drv)
+{
+	return -ENODEV;
+}
+#endif
diff --git a/arch/arm/mach-imx/devices-imx1.h b/arch/arm/mach-imx/devices-imx1.h
index 3aad1e7..f9b5afc 100644
--- a/arch/arm/mach-imx/devices-imx1.h
+++ b/arch/arm/mach-imx/devices-imx1.h
@@ -6,8 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/mx1.h>
-#include <mach/devices-common.h>
+#include "devices/devices-common.h"
 
 extern const struct imx_imx_fb_data imx1_imx_fb_data;
 #define imx1_add_imx_fb(pdata) \
diff --git a/arch/arm/mach-imx/devices-imx21.h b/arch/arm/mach-imx/devices-imx21.h
index 93ece55..bd93932 100644
--- a/arch/arm/mach-imx/devices-imx21.h
+++ b/arch/arm/mach-imx/devices-imx21.h
@@ -6,8 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/mx21.h>
-#include <mach/devices-common.h>
+#include "devices/devices-common.h"
 
 extern const struct imx_imx21_hcd_data imx21_imx21_hcd_data;
 #define imx21_add_imx21_hcd(pdata)	\
diff --git a/arch/arm/mach-imx/devices-imx25.h b/arch/arm/mach-imx/devices-imx25.h
index f8e03dd..0d2922b 100644
--- a/arch/arm/mach-imx/devices-imx25.h
+++ b/arch/arm/mach-imx/devices-imx25.h
@@ -6,8 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/mx25.h>
-#include <mach/devices-common.h>
+#include "devices/devices-common.h"
 
 extern const struct imx_fec_data imx25_fec_data;
 #define imx25_add_fec(pdata)	\
diff --git a/arch/arm/mach-imx/devices-imx27.h b/arch/arm/mach-imx/devices-imx27.h
index 0482293..1309625 100644
--- a/arch/arm/mach-imx/devices-imx27.h
+++ b/arch/arm/mach-imx/devices-imx27.h
@@ -6,8 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/mx27.h>
-#include <mach/devices-common.h>
+#include "devices/devices-common.h"
 
 extern const struct imx_fec_data imx27_fec_data;
 #define imx27_add_fec(pdata)	\
@@ -54,8 +53,10 @@ extern const struct imx_imx_uart_1irq_data imx27_imx_uart_data[];
 extern const struct imx_mx2_camera_data imx27_mx2_camera_data;
 #define imx27_add_mx2_camera(pdata)	\
 	imx_add_mx2_camera(&imx27_mx2_camera_data, pdata)
+
+extern const struct imx_mx2_emma_data imx27_mx2_emmaprp_data;
 #define imx27_add_mx2_emmaprp()	\
-	imx_add_mx2_emmaprp(&imx27_mx2_camera_data)
+	imx_add_mx2_emmaprp(&imx27_mx2_emmaprp_data)
 
 extern const struct imx_mxc_ehci_data imx27_mxc_ehci_otg_data;
 #define imx27_add_mxc_ehci_otg(pdata)	\
diff --git a/arch/arm/mach-imx/devices-imx31.h b/arch/arm/mach-imx/devices-imx31.h
index 8b2ceb4..e8d1611 100644
--- a/arch/arm/mach-imx/devices-imx31.h
+++ b/arch/arm/mach-imx/devices-imx31.h
@@ -6,8 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/mx31.h>
-#include <mach/devices-common.h>
+#include "devices/devices-common.h"
 
 extern const struct imx_fsl_usb2_udc_data imx31_fsl_usb2_udc_data;
 #define imx31_add_fsl_usb2_udc(pdata)	\
diff --git a/arch/arm/mach-imx/devices-imx35.h b/arch/arm/mach-imx/devices-imx35.h
index c3e9f20..e2675f1 100644
--- a/arch/arm/mach-imx/devices-imx35.h
+++ b/arch/arm/mach-imx/devices-imx35.h
@@ -6,8 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/mx35.h>
-#include <mach/devices-common.h>
+#include "devices/devices-common.h"
 
 extern const struct imx_fec_data imx35_fec_data;
 #define imx35_add_fec(pdata)	\
diff --git a/arch/arm/mach-imx/devices-imx50.h b/arch/arm/mach-imx/devices-imx50.h
index 7216667..2c29039 100644
--- a/arch/arm/mach-imx/devices-imx50.h
+++ b/arch/arm/mach-imx/devices-imx50.h
@@ -18,8 +18,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include <mach/mx50.h>
-#include <mach/devices-common.h>
+#include "devices/devices-common.h"
 
 extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[];
 #define imx50_add_imx_uart(id, pdata)	\
diff --git a/arch/arm/mach-imx/devices-imx51.h b/arch/arm/mach-imx/devices-imx51.h
index 9f17187..deee5ba 100644
--- a/arch/arm/mach-imx/devices-imx51.h
+++ b/arch/arm/mach-imx/devices-imx51.h
@@ -6,8 +6,7 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <mach/mx51.h>
-#include <mach/devices-common.h>
+#include "devices/devices-common.h"
 
 extern const struct imx_fec_data imx51_fec_data;
 #define imx51_add_fec(pdata)	\
diff --git a/arch/arm/mach-imx/devices/Kconfig b/arch/arm/mach-imx/devices/Kconfig
new file mode 100644
index 0000000..9a8f1ca
--- /dev/null
+++ b/arch/arm/mach-imx/devices/Kconfig
@@ -0,0 +1,92 @@
+config IMX_HAVE_PLATFORM_FEC
+	bool
+	default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX50 || SOC_IMX51 || SOC_IMX53
+
+config IMX_HAVE_PLATFORM_FLEXCAN
+	bool
+	select HAVE_CAN_FLEXCAN if CAN
+
+config IMX_HAVE_PLATFORM_FSL_USB2_UDC
+	bool
+
+config IMX_HAVE_PLATFORM_GPIO_KEYS
+	bool
+	default y if SOC_IMX51
+
+config IMX_HAVE_PLATFORM_IMX21_HCD
+	bool
+
+config IMX_HAVE_PLATFORM_IMX27_CODA
+	bool
+	default y if SOC_IMX27
+
+config IMX_HAVE_PLATFORM_IMX2_WDT
+	bool
+
+config IMX_HAVE_PLATFORM_IMXDI_RTC
+	bool
+
+config IMX_HAVE_PLATFORM_IMX_FB
+	bool
+
+config IMX_HAVE_PLATFORM_IMX_I2C
+	bool
+
+config IMX_HAVE_PLATFORM_IMX_KEYPAD
+	bool
+
+config IMX_HAVE_PLATFORM_PATA_IMX
+	bool
+
+config IMX_HAVE_PLATFORM_IMX_SSI
+	bool
+
+config IMX_HAVE_PLATFORM_IMX_UART
+	bool
+
+config IMX_HAVE_PLATFORM_IMX_UDC
+	bool
+
+config IMX_HAVE_PLATFORM_IPU_CORE
+	bool
+
+config IMX_HAVE_PLATFORM_MX1_CAMERA
+	bool
+
+config IMX_HAVE_PLATFORM_MX2_CAMERA
+	bool
+
+config IMX_HAVE_PLATFORM_MX2_EMMA
+	bool
+
+config IMX_HAVE_PLATFORM_MXC_EHCI
+	bool
+
+config IMX_HAVE_PLATFORM_MXC_MMC
+	bool
+
+config IMX_HAVE_PLATFORM_MXC_NAND
+	bool
+
+config IMX_HAVE_PLATFORM_MXC_PWM
+	bool
+
+config IMX_HAVE_PLATFORM_MXC_RNGA
+	bool
+	select ARCH_HAS_RNGA
+
+config IMX_HAVE_PLATFORM_MXC_RTC
+	bool
+
+config IMX_HAVE_PLATFORM_MXC_W1
+	bool
+
+config IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	bool
+
+config IMX_HAVE_PLATFORM_SPI_IMX
+	bool
+
+config IMX_HAVE_PLATFORM_AHCI
+	bool
+	default y if ARCH_MX53
diff --git a/arch/arm/mach-imx/devices/Makefile b/arch/arm/mach-imx/devices/Makefile
new file mode 100644
index 0000000..6acf37e
--- /dev/null
+++ b/arch/arm/mach-imx/devices/Makefile
@@ -0,0 +1,33 @@
+obj-y := devices.o
+
+obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC) += platform-fsl-usb2-udc.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_GPIO_KEYS) += platform-gpio_keys.o
+obj-y += platform-gpio-mxc.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX21_HCD) += platform-imx21-hcd.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX27_CODA) += platform-imx27-coda.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT) += platform-imx2-wdt.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMXDI_RTC) += platform-imxdi_rtc.o
+obj-y += platform-imx-dma.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_FB) += platform-imx-fb.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_I2C) += platform-imx-i2c.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_KEYPAD) += platform-imx-keypad.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_PATA_IMX) += platform-pata_imx.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_SSI) += platform-imx-ssi.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UART) += platform-imx-uart.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UDC) += platform-imx_udc.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IPU_CORE) += platform-ipu-core.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_MX1_CAMERA) += platform-mx1-camera.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_MX2_CAMERA) += platform-mx2-camera.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_EHCI) += platform-mxc-ehci.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_MMC) += platform-mxc-mmc.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_NAND) += platform-mxc_nand.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_PWM) += platform-mxc_pwm.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_RNGA) += platform-mxc_rnga.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_RTC) += platform-mxc_rtc.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_W1) += platform-mxc_w1.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX) += platform-sdhci-esdhc-imx.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_SPI_IMX) +=  platform-spi_imx.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_AHCI) +=  platform-ahci-imx.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_MX2_EMMA) += platform-mx2-emma.o
diff --git a/arch/arm/mach-imx/devices/devices-common.h b/arch/arm/mach-imx/devices/devices-common.h
new file mode 100644
index 0000000..6277baf
--- /dev/null
+++ b/arch/arm/mach-imx/devices/devices-common.h
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2009-2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/platform_data/dma-imx-sdma.h>
+
+extern struct device mxc_aips_bus;
+extern struct device mxc_ahb_bus;
+
+static inline struct platform_device *imx_add_platform_device_dmamask(
+		const char *name, int id,
+		const struct resource *res, unsigned int num_resources,
+		const void *data, size_t size_data, u64 dmamask)
+{
+	struct platform_device_info pdevinfo = {
+		.name = name,
+		.id = id,
+		.res = res,
+		.num_res = num_resources,
+		.data = data,
+		.size_data = size_data,
+		.dma_mask = dmamask,
+	};
+	return platform_device_register_full(&pdevinfo);
+}
+
+static inline struct platform_device *imx_add_platform_device(
+		const char *name, int id,
+		const struct resource *res, unsigned int num_resources,
+		const void *data, size_t size_data)
+{
+	return imx_add_platform_device_dmamask(
+			name, id, res, num_resources, data, size_data, 0);
+}
+
+#include <linux/fec.h>
+struct imx_fec_data {
+	const char *devid;
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_fec(
+		const struct imx_fec_data *data,
+		const struct fec_platform_data *pdata);
+
+#include <linux/can/platform/flexcan.h>
+struct imx_flexcan_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_flexcan(
+		const struct imx_flexcan_data *data,
+		const struct flexcan_platform_data *pdata);
+
+#include <linux/fsl_devices.h>
+struct imx_fsl_usb2_udc_data {
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_fsl_usb2_udc(
+		const struct imx_fsl_usb2_udc_data *data,
+		const struct fsl_usb2_platform_data *pdata);
+
+#include <linux/gpio_keys.h>
+struct platform_device *__init imx_add_gpio_keys(
+		const struct gpio_keys_platform_data *pdata);
+
+#include <linux/platform_data/usb-mx2.h>
+struct imx_imx21_hcd_data {
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx21_hcd(
+		const struct imx_imx21_hcd_data *data,
+		const struct mx21_usbh_platform_data *pdata);
+
+struct imx_imx27_coda_data {
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx27_coda(
+		const struct imx_imx27_coda_data *data);
+
+struct imx_imx2_wdt_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+};
+struct platform_device *__init imx_add_imx2_wdt(
+		const struct imx_imx2_wdt_data *data);
+
+struct imx_imxdi_rtc_data {
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_imxdi_rtc(
+		const struct imx_imxdi_rtc_data *data);
+
+#include <linux/platform_data/video-imxfb.h>
+struct imx_imx_fb_data {
+	const char *devid;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx_fb(
+		const struct imx_imx_fb_data *data,
+		const struct imx_fb_platform_data *pdata);
+
+#include <linux/platform_data/i2c-imx.h>
+struct imx_imx_i2c_data {
+	const char *devid;
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx_i2c(
+		const struct imx_imx_i2c_data *data,
+		const struct imxi2c_platform_data *pdata);
+
+#include <linux/input/matrix_keypad.h>
+struct imx_imx_keypad_data {
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx_keypad(
+		const struct imx_imx_keypad_data *data,
+		const struct matrix_keymap_data *pdata);
+
+#include <linux/platform_data/asoc-imx-ssi.h>
+struct imx_imx_ssi_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+	resource_size_t dmatx0;
+	resource_size_t dmarx0;
+	resource_size_t dmatx1;
+	resource_size_t dmarx1;
+};
+struct platform_device *__init imx_add_imx_ssi(
+		const struct imx_imx_ssi_data *data,
+		const struct imx_ssi_platform_data *pdata);
+
+#include <linux/platform_data/serial-imx.h>
+struct imx_imx_uart_3irq_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irqrx;
+	resource_size_t irqtx;
+	resource_size_t irqrts;
+};
+struct platform_device *__init imx_add_imx_uart_3irq(
+		const struct imx_imx_uart_3irq_data *data,
+		const struct imxuart_platform_data *pdata);
+
+struct imx_imx_uart_1irq_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx_uart_1irq(
+		const struct imx_imx_uart_1irq_data *data,
+		const struct imxuart_platform_data *pdata);
+
+#include <linux/platform_data/usb-imx_udc.h>
+struct imx_imx_udc_data {
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq0;
+	resource_size_t irq1;
+	resource_size_t irq2;
+	resource_size_t irq3;
+	resource_size_t irq4;
+	resource_size_t irq5;
+	resource_size_t irq6;
+};
+struct platform_device *__init imx_add_imx_udc(
+		const struct imx_imx_udc_data *data,
+		const struct imxusb_platform_data *pdata);
+
+#include <linux/platform_data/video-mx3fb.h>
+#include <linux/platform_data/camera-mx3.h>
+struct imx_ipu_core_data {
+	resource_size_t iobase;
+	resource_size_t synirq;
+	resource_size_t errirq;
+};
+struct platform_device *__init imx_add_ipu_core(
+		const struct imx_ipu_core_data *data);
+struct platform_device *__init imx_alloc_mx3_camera(
+		const struct imx_ipu_core_data *data,
+		const struct mx3_camera_pdata *pdata);
+struct platform_device *__init imx_add_mx3_sdc_fb(
+		const struct imx_ipu_core_data *data,
+		struct mx3fb_platform_data *pdata);
+
+#include <linux/platform_data/camera-mx1.h>
+struct imx_mx1_camera_data {
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_mx1_camera(
+		const struct imx_mx1_camera_data *data,
+		const struct mx1_camera_pdata *pdata);
+
+#include <linux/platform_data/camera-mx2.h>
+struct imx_mx2_camera_data {
+	const char *devid;
+	resource_size_t iobasecsi;
+	resource_size_t iosizecsi;
+	resource_size_t irqcsi;
+	resource_size_t iobaseemmaprp;
+	resource_size_t iosizeemmaprp;
+	resource_size_t irqemmaprp;
+};
+struct platform_device *__init imx_add_mx2_camera(
+		const struct imx_mx2_camera_data *data,
+		const struct mx2_camera_platform_data *pdata);
+
+
+struct imx_mx2_emma_data {
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_mx2_emmaprp(
+		const struct imx_mx2_emma_data *data);
+
+#include <linux/platform_data/usb-ehci-mxc.h>
+struct imx_mxc_ehci_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_mxc_ehci(
+		const struct imx_mxc_ehci_data *data,
+		const struct mxc_usbh_platform_data *pdata);
+
+#include <linux/platform_data/mmc-mxcmmc.h>
+struct imx_mxc_mmc_data {
+	const char *devid;
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+	resource_size_t dmareq;
+};
+struct platform_device *__init imx_add_mxc_mmc(
+		const struct imx_mxc_mmc_data *data,
+		const struct imxmmc_platform_data *pdata);
+
+#include <linux/platform_data/mtd-mxc_nand.h>
+struct imx_mxc_nand_data {
+	const char *devid;
+	/*
+	 * id is traditionally 0, but -1 is more appropriate.  We use -1 for new
+	 * machines but don't change existing devices as the nand device usually
+	 * appears in the kernel command line to pass its partitioning.
+	 */
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t axibase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_mxc_nand(
+		const struct imx_mxc_nand_data *data,
+		const struct mxc_nand_platform_data *pdata);
+
+struct imx_pata_imx_data {
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_pata_imx(
+		const struct imx_pata_imx_data *data);
+
+struct imx_mxc_pwm_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_mxc_pwm(
+		const struct imx_mxc_pwm_data *data);
+
+/* mxc_rtc */
+struct imx_mxc_rtc_data {
+	const char *devid;
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_mxc_rtc(
+		const struct imx_mxc_rtc_data *data);
+
+/* mxc_w1 */
+struct imx_mxc_w1_data {
+	resource_size_t iobase;
+};
+struct platform_device *__init imx_add_mxc_w1(
+		const struct imx_mxc_w1_data *data);
+
+#include <linux/platform_data/mmc-esdhc-imx.h>
+struct imx_sdhci_esdhc_imx_data {
+	const char *devid;
+	int id;
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_sdhci_esdhc_imx(
+		const struct imx_sdhci_esdhc_imx_data *data,
+		const struct esdhc_platform_data *pdata);
+
+#include <linux/platform_data/spi-imx.h>
+struct imx_spi_imx_data {
+	const char *devid;
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	int irq;
+};
+struct platform_device *__init imx_add_spi_imx(
+		const struct imx_spi_imx_data *data,
+		const struct spi_imx_master *pdata);
+
+struct platform_device *imx_add_imx_dma(char *name, resource_size_t iobase,
+					int irq, int irq_err);
+struct platform_device *imx_add_imx_sdma(char *name,
+	resource_size_t iobase, int irq, struct sdma_platform_data *pdata);
+
+#include <linux/ahci_platform.h>
+struct imx_ahci_imx_data {
+	const char *devid;
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_ahci_imx(
+		const struct imx_ahci_imx_data *data,
+		const struct ahci_platform_data *pdata);
diff --git a/arch/arm/mach-imx/devices/devices.c b/arch/arm/mach-imx/devices/devices.c
new file mode 100644
index 0000000..1b37482
--- /dev/null
+++ b/arch/arm/mach-imx/devices/devices.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2008 Sascha Hauer, kernel@pengutronix.de
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+struct device mxc_aips_bus = {
+	.init_name	= "mxc_aips",
+	.parent		= &platform_bus,
+};
+
+struct device mxc_ahb_bus = {
+	.init_name	= "mxc_ahb",
+	.parent		= &platform_bus,
+};
+
+int __init mxc_device_init(void)
+{
+	int ret;
+
+	ret = device_register(&mxc_aips_bus);
+	if (IS_ERR_VALUE(ret))
+		goto done;
+
+	ret = device_register(&mxc_ahb_bus);
+
+done:
+	return ret;
+}
diff --git a/arch/arm/mach-imx/devices/platform-ahci-imx.c b/arch/arm/mach-imx/devices/platform-ahci-imx.c
new file mode 100644
index 0000000..3d87dd9
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-ahci-imx.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <asm/sizes.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_ahci_imx_data_entry_single(soc, _devid)		\
+	{								\
+		.devid = _devid,					\
+		.iobase = soc ## _SATA_BASE_ADDR,			\
+		.irq = soc ## _INT_SATA,				\
+	}
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_ahci_imx_data imx53_ahci_imx_data __initconst =
+	imx_ahci_imx_data_entry_single(MX53, "imx53-ahci");
+#endif
+
+enum {
+	HOST_CAP = 0x00,
+	HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
+	HOST_PORTS_IMPL	= 0x0c,
+	HOST_TIMER1MS = 0xe0, /* Timer 1-ms */
+};
+
+static struct clk *sata_clk, *sata_ref_clk;
+
+/* AHCI module Initialization, if return 0, initialization is successful. */
+static int imx_sata_init(struct device *dev, void __iomem *addr)
+{
+	u32 tmpdata;
+	int ret = 0;
+	struct clk *clk;
+
+	sata_clk = clk_get(dev, "ahci");
+	if (IS_ERR(sata_clk)) {
+		dev_err(dev, "no sata clock.\n");
+		return PTR_ERR(sata_clk);
+	}
+	ret = clk_prepare_enable(sata_clk);
+	if (ret) {
+		dev_err(dev, "can't prepare/enable sata clock.\n");
+		goto put_sata_clk;
+	}
+
+	/* Get the AHCI SATA PHY CLK */
+	sata_ref_clk = clk_get(dev, "ahci_phy");
+	if (IS_ERR(sata_ref_clk)) {
+		dev_err(dev, "no sata ref clock.\n");
+		ret = PTR_ERR(sata_ref_clk);
+		goto release_sata_clk;
+	}
+	ret = clk_prepare_enable(sata_ref_clk);
+	if (ret) {
+		dev_err(dev, "can't prepare/enable sata ref clock.\n");
+		goto put_sata_ref_clk;
+	}
+
+	/* Get the AHB clock rate, and configure the TIMER1MS reg later */
+	clk = clk_get(dev, "ahci_dma");
+	if (IS_ERR(clk)) {
+		dev_err(dev, "no dma clock.\n");
+		ret = PTR_ERR(clk);
+		goto release_sata_ref_clk;
+	}
+	tmpdata = clk_get_rate(clk) / 1000;
+	clk_put(clk);
+
+	writel(tmpdata, addr + HOST_TIMER1MS);
+
+	tmpdata = readl(addr + HOST_CAP);
+	if (!(tmpdata & HOST_CAP_SSS)) {
+		tmpdata |= HOST_CAP_SSS;
+		writel(tmpdata, addr + HOST_CAP);
+	}
+
+	if (!(readl(addr + HOST_PORTS_IMPL) & 0x1))
+		writel((readl(addr + HOST_PORTS_IMPL) | 0x1),
+			addr + HOST_PORTS_IMPL);
+
+	return 0;
+
+release_sata_ref_clk:
+	clk_disable_unprepare(sata_ref_clk);
+put_sata_ref_clk:
+	clk_put(sata_ref_clk);
+release_sata_clk:
+	clk_disable_unprepare(sata_clk);
+put_sata_clk:
+	clk_put(sata_clk);
+
+	return ret;
+}
+
+static void imx_sata_exit(struct device *dev)
+{
+	clk_disable_unprepare(sata_ref_clk);
+	clk_put(sata_ref_clk);
+
+	clk_disable_unprepare(sata_clk);
+	clk_put(sata_clk);
+
+}
+struct platform_device *__init imx_add_ahci_imx(
+		const struct imx_ahci_imx_data *data,
+		const struct ahci_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device_dmamask(data->devid, 0,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata),  DMA_BIT_MASK(32));
+}
+
+struct platform_device *__init imx53_add_ahci_imx(void)
+{
+	struct ahci_platform_data pdata = {
+		.init = imx_sata_init,
+		.exit = imx_sata_exit,
+	};
+
+	return imx_add_ahci_imx(&imx53_ahci_imx_data, &pdata);
+}
diff --git a/arch/arm/mach-imx/devices/platform-fec.c b/arch/arm/mach-imx/devices/platform-fec.c
new file mode 100644
index 0000000..2cb188a
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-fec.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <linux/dma-mapping.h>
+#include <asm/sizes.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_fec_data_entry_single(soc, _devid)				\
+	{								\
+		.devid = _devid,					\
+		.iobase = soc ## _FEC_BASE_ADDR,			\
+		.irq = soc ## _INT_FEC,					\
+	}
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_fec_data imx25_fec_data __initconst =
+	imx_fec_data_entry_single(MX25, "imx25-fec");
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_fec_data imx27_fec_data __initconst =
+	imx_fec_data_entry_single(MX27, "imx27-fec");
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX35
+/* i.mx35 has the i.mx27 type fec */
+const struct imx_fec_data imx35_fec_data __initconst =
+	imx_fec_data_entry_single(MX35, "imx27-fec");
+#endif
+
+#ifdef CONFIG_SOC_IMX50
+/* i.mx50 has the i.mx25 type fec */
+const struct imx_fec_data imx50_fec_data __initconst =
+	imx_fec_data_entry_single(MX50, "imx25-fec");
+#endif
+
+#ifdef CONFIG_SOC_IMX51
+/* i.mx51 has the i.mx27 type fec */
+const struct imx_fec_data imx51_fec_data __initconst =
+	imx_fec_data_entry_single(MX51, "imx27-fec");
+#endif
+
+#ifdef CONFIG_SOC_IMX53
+/* i.mx53 has the i.mx25 type fec */
+const struct imx_fec_data imx53_fec_data __initconst =
+	imx_fec_data_entry_single(MX53, "imx25-fec");
+#endif
+
+struct platform_device *__init imx_add_fec(
+		const struct imx_fec_data *data,
+		const struct fec_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device_dmamask(data->devid, 0,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
diff --git a/arch/arm/mach-imx/devices/platform-flexcan.c b/arch/arm/mach-imx/devices/platform-flexcan.c
new file mode 100644
index 0000000..1078bf0
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-flexcan.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_flexcan_data_entry_single(soc, _id, _hwid, _size)		\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _CAN ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+		.irq = soc ## _INT_CAN ## _hwid,			\
+	}
+
+#define imx_flexcan_data_entry(soc, _id, _hwid, _size)			\
+	[_id] = imx_flexcan_data_entry_single(soc, _id, _hwid, _size)
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_flexcan_data imx25_flexcan_data[] __initconst = {
+#define imx25_flexcan_data_entry(_id, _hwid)				\
+	imx_flexcan_data_entry(MX25, _id, _hwid, SZ_16K)
+	imx25_flexcan_data_entry(0, 1),
+	imx25_flexcan_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_flexcan_data imx35_flexcan_data[] __initconst = {
+#define imx35_flexcan_data_entry(_id, _hwid)				\
+	imx_flexcan_data_entry(MX35, _id, _hwid, SZ_16K)
+	imx35_flexcan_data_entry(0, 1),
+	imx35_flexcan_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+struct platform_device *__init imx_add_flexcan(
+		const struct imx_flexcan_data *data,
+		const struct flexcan_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device("flexcan", data->id,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c b/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c
new file mode 100644
index 0000000..37e4439
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <linux/dma-mapping.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_fsl_usb2_udc_data_entry_single(soc)				\
+	{								\
+		.iobase = soc ## _USB_OTG_BASE_ADDR,			\
+		.irq = soc ## _INT_USB_OTG,				\
+	}
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data __initconst =
+	imx_fsl_usb2_udc_data_entry_single(MX25);
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_fsl_usb2_udc_data imx27_fsl_usb2_udc_data __initconst =
+	imx_fsl_usb2_udc_data_entry_single(MX27);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_fsl_usb2_udc_data imx31_fsl_usb2_udc_data __initconst =
+	imx_fsl_usb2_udc_data_entry_single(MX31);
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_fsl_usb2_udc_data imx35_fsl_usb2_udc_data __initconst =
+	imx_fsl_usb2_udc_data_entry_single(MX35);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data __initconst =
+	imx_fsl_usb2_udc_data_entry_single(MX51);
+#endif
+
+struct platform_device *__init imx_add_fsl_usb2_udc(
+		const struct imx_fsl_usb2_udc_data *data,
+		const struct fsl_usb2_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_512 - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	return imx_add_platform_device_dmamask("fsl-usb2-udc", -1,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
diff --git a/arch/arm/mach-imx/devices/platform-gpio-mxc.c b/arch/arm/mach-imx/devices/platform-gpio-mxc.c
new file mode 100644
index 0000000..26483fa
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-gpio-mxc.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include "devices-common.h"
+
+struct platform_device *__init mxc_register_gpio(char *name, int id,
+	resource_size_t iobase, resource_size_t iosize, int irq, int irq_high)
+{
+	struct resource res[] = {
+		{
+			.start = iobase,
+			.end = iobase + iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = irq,
+			.end = irq,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = irq_high,
+			.end = irq_high,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return platform_device_register_resndata(&mxc_aips_bus,
+			name, id, res, ARRAY_SIZE(res), NULL, 0);
+}
diff --git a/arch/arm/mach-imx/devices/platform-gpio_keys.c b/arch/arm/mach-imx/devices/platform-gpio_keys.c
new file mode 100644
index 0000000..4862825
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-gpio_keys.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+#include <asm/sizes.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
+
+struct platform_device *__init imx_add_gpio_keys(
+		const struct gpio_keys_platform_data *pdata)
+{
+	return imx_add_platform_device("gpio-keys", -1, NULL,
+		 0, pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/mach-imx/devices/platform-imx-dma.c b/arch/arm/mach-imx/devices/platform-imx-dma.c
new file mode 100644
index 0000000..ccdb5dc
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-imx-dma.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include "devices-common.h"
+
+struct platform_device __init __maybe_unused *imx_add_imx_dma(char *name,
+	resource_size_t iobase, int irq, int irq_err)
+{
+	struct resource res[] = {
+		{
+			.start = iobase,
+			.end = iobase + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = irq,
+			.end = irq,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = irq_err,
+			.end = irq_err,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return platform_device_register_resndata(&mxc_ahb_bus,
+			name, -1, res, ARRAY_SIZE(res), NULL, 0);
+}
+
+struct platform_device __init __maybe_unused *imx_add_imx_sdma(char *name,
+	resource_size_t iobase, int irq, struct sdma_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = iobase,
+			.end = iobase + SZ_16K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = irq,
+			.end = irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return platform_device_register_resndata(&mxc_ahb_bus, name,
+			-1, res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/mach-imx/devices/platform-imx-fb.c b/arch/arm/mach-imx/devices/platform-imx-fb.c
new file mode 100644
index 0000000..10b0ed3
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-imx-fb.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <linux/dma-mapping.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_imx_fb_data_entry_single(soc, _devid, _size)		\
+	{								\
+		.devid = _devid,					\
+		.iobase = soc ## _LCDC_BASE_ADDR,			\
+		.iosize = _size,					\
+		.irq = soc ## _INT_LCDC,				\
+	}
+
+#ifdef CONFIG_SOC_IMX1
+const struct imx_imx_fb_data imx1_imx_fb_data __initconst =
+	imx_imx_fb_data_entry_single(MX1, "imx1-fb", SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX1 */
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx_fb_data imx21_imx_fb_data __initconst =
+	imx_imx_fb_data_entry_single(MX21, "imx21-fb", SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_imx_fb_data imx25_imx_fb_data __initconst =
+	imx_imx_fb_data_entry_single(MX25, "imx21-fb", SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx_fb_data imx27_imx_fb_data __initconst =
+	imx_imx_fb_data_entry_single(MX27, "imx21-fb", SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+struct platform_device *__init imx_add_imx_fb(
+		const struct imx_imx_fb_data *data,
+		const struct imx_fb_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	return imx_add_platform_device_dmamask("imx-fb", 0,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
diff --git a/arch/arm/mach-imx/devices/platform-imx-i2c.c b/arch/arm/mach-imx/devices/platform-imx-i2c.c
new file mode 100644
index 0000000..8e30e57
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-imx-i2c.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2009-2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_imx_i2c_data_entry_single(soc, _devid, _id, _hwid, _size)	\
+	{								\
+		.devid = _devid,					\
+		.id = _id,						\
+		.iobase = soc ## _I2C ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+		.irq = soc ## _INT_I2C ## _hwid,			\
+	}
+
+#define imx_imx_i2c_data_entry(soc, _devid, _id, _hwid, _size)		\
+	[_id] = imx_imx_i2c_data_entry_single(soc, _devid, _id, _hwid, _size)
+
+#ifdef CONFIG_SOC_IMX1
+const struct imx_imx_i2c_data imx1_imx_i2c_data __initconst =
+	imx_imx_i2c_data_entry_single(MX1, "imx1-i2c", 0, , SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX1 */
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx_i2c_data imx21_imx_i2c_data __initconst =
+	imx_imx_i2c_data_entry_single(MX21, "imx21-i2c", 0, , SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_imx_i2c_data imx25_imx_i2c_data[] __initconst = {
+#define imx25_imx_i2c_data_entry(_id, _hwid)				\
+	imx_imx_i2c_data_entry(MX25, "imx21-i2c", _id, _hwid, SZ_16K)
+	imx25_imx_i2c_data_entry(0, 1),
+	imx25_imx_i2c_data_entry(1, 2),
+	imx25_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx_i2c_data imx27_imx_i2c_data[] __initconst = {
+#define imx27_imx_i2c_data_entry(_id, _hwid)				\
+	imx_imx_i2c_data_entry(MX27, "imx21-i2c", _id, _hwid, SZ_4K)
+	imx27_imx_i2c_data_entry(0, 1),
+	imx27_imx_i2c_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_imx_i2c_data imx31_imx_i2c_data[] __initconst = {
+#define imx31_imx_i2c_data_entry(_id, _hwid)				\
+	imx_imx_i2c_data_entry(MX31, "imx21-i2c", _id, _hwid, SZ_4K)
+	imx31_imx_i2c_data_entry(0, 1),
+	imx31_imx_i2c_data_entry(1, 2),
+	imx31_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst = {
+#define imx35_imx_i2c_data_entry(_id, _hwid)				\
+	imx_imx_i2c_data_entry(MX35, "imx21-i2c", _id, _hwid, SZ_4K)
+	imx35_imx_i2c_data_entry(0, 1),
+	imx35_imx_i2c_data_entry(1, 2),
+	imx35_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX50
+const struct imx_imx_i2c_data imx50_imx_i2c_data[] __initconst = {
+#define imx50_imx_i2c_data_entry(_id, _hwid)				\
+	imx_imx_i2c_data_entry(MX50, "imx21-i2c", _id, _hwid, SZ_4K)
+	imx50_imx_i2c_data_entry(0, 1),
+	imx50_imx_i2c_data_entry(1, 2),
+	imx50_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = {
+#define imx51_imx_i2c_data_entry(_id, _hwid)				\
+	imx_imx_i2c_data_entry(MX51, "imx21-i2c", _id, _hwid, SZ_4K)
+	imx51_imx_i2c_data_entry(0, 1),
+	imx51_imx_i2c_data_entry(1, 2),
+	{
+		.devid = "imx21-i2c",
+		.id = 2,
+		.iobase = MX51_HSI2C_DMA_BASE_ADDR,
+		.iosize = SZ_16K,
+		.irq = MX51_INT_HS_I2C,
+	},
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_imx_i2c_data imx53_imx_i2c_data[] __initconst = {
+#define imx53_imx_i2c_data_entry(_id, _hwid)				\
+	imx_imx_i2c_data_entry(MX53, "imx21-i2c", _id, _hwid, SZ_4K)
+	imx53_imx_i2c_data_entry(0, 1),
+	imx53_imx_i2c_data_entry(1, 2),
+	imx53_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
+struct platform_device *__init imx_add_imx_i2c(
+		const struct imx_imx_i2c_data *data,
+		const struct imxi2c_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device(data->devid, data->id,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/mach-imx/devices/platform-imx-keypad.c b/arch/arm/mach-imx/devices/platform-imx-keypad.c
new file mode 100644
index 0000000..8f22a4c
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-imx-keypad.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_imx_keypad_data_entry_single(soc, _size)			\
+	{								\
+		.iobase = soc ## _KPP_BASE_ADDR,			\
+		.iosize = _size,					\
+		.irq = soc ## _INT_KPP,					\
+	}
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx_keypad_data imx21_imx_keypad_data __initconst =
+	imx_imx_keypad_data_entry_single(MX21, SZ_16);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_imx_keypad_data imx25_imx_keypad_data __initconst =
+	imx_imx_keypad_data_entry_single(MX25, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx_keypad_data imx27_imx_keypad_data __initconst =
+	imx_imx_keypad_data_entry_single(MX27, SZ_16);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_imx_keypad_data imx31_imx_keypad_data __initconst =
+	imx_imx_keypad_data_entry_single(MX31, SZ_16);
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_imx_keypad_data imx35_imx_keypad_data __initconst =
+	imx_imx_keypad_data_entry_single(MX35, SZ_16);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_imx_keypad_data imx51_imx_keypad_data __initconst =
+	imx_imx_keypad_data_entry_single(MX51, SZ_16);
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_imx_keypad_data imx53_imx_keypad_data __initconst =
+	imx_imx_keypad_data_entry_single(MX53, SZ_16);
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
+struct platform_device *__init imx_add_imx_keypad(
+		const struct imx_imx_keypad_data *data,
+		const struct matrix_keymap_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device("imx-keypad", -1,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/mach-imx/devices/platform-imx-ssi.c b/arch/arm/mach-imx/devices/platform-imx-ssi.c
new file mode 100644
index 0000000..bfcb8f3
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-imx-ssi.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_imx_ssi_data_entry(soc, _id, _hwid, _size)			\
+	[_id] = {							\
+		.id = _id,						\
+		.iobase = soc ## _SSI ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+		.irq = soc ## _INT_SSI ## _hwid,			\
+		.dmatx0 = soc ## _DMA_REQ_SSI ## _hwid ## _TX0,		\
+		.dmarx0 = soc ## _DMA_REQ_SSI ## _hwid ## _RX0,		\
+		.dmatx1 = soc ## _DMA_REQ_SSI ## _hwid ## _TX1,		\
+		.dmarx1 = soc ## _DMA_REQ_SSI ## _hwid ## _RX1,		\
+	}
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx_ssi_data imx21_imx_ssi_data[] __initconst = {
+#define imx21_imx_ssi_data_entry(_id, _hwid)				\
+	imx_imx_ssi_data_entry(MX21, _id, _hwid, SZ_4K)
+	imx21_imx_ssi_data_entry(0, 1),
+	imx21_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_imx_ssi_data imx25_imx_ssi_data[] __initconst = {
+#define imx25_imx_ssi_data_entry(_id, _hwid)				\
+	imx_imx_ssi_data_entry(MX25, _id, _hwid, SZ_4K)
+	imx25_imx_ssi_data_entry(0, 1),
+	imx25_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx_ssi_data imx27_imx_ssi_data[] __initconst = {
+#define imx27_imx_ssi_data_entry(_id, _hwid)				\
+	imx_imx_ssi_data_entry(MX27, _id, _hwid, SZ_4K)
+	imx27_imx_ssi_data_entry(0, 1),
+	imx27_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_imx_ssi_data imx31_imx_ssi_data[] __initconst = {
+#define imx31_imx_ssi_data_entry(_id, _hwid)				\
+	imx_imx_ssi_data_entry(MX31, _id, _hwid, SZ_4K)
+	imx31_imx_ssi_data_entry(0, 1),
+	imx31_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_imx_ssi_data imx35_imx_ssi_data[] __initconst = {
+#define imx35_imx_ssi_data_entry(_id, _hwid)				\
+	imx_imx_ssi_data_entry(MX35, _id, _hwid, SZ_4K)
+	imx35_imx_ssi_data_entry(0, 1),
+	imx35_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_imx_ssi_data imx51_imx_ssi_data[] __initconst = {
+#define imx51_imx_ssi_data_entry(_id, _hwid)				\
+	imx_imx_ssi_data_entry(MX51, _id, _hwid, SZ_16K)
+	imx51_imx_ssi_data_entry(0, 1),
+	imx51_imx_ssi_data_entry(1, 2),
+	imx51_imx_ssi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_imx_ssi_data imx53_imx_ssi_data[] __initconst = {
+#define imx53_imx_ssi_data_entry(_id, _hwid)				\
+	imx_imx_ssi_data_entry(MX53, _id, _hwid, SZ_16K)
+	imx53_imx_ssi_data_entry(0, 1),
+	imx53_imx_ssi_data_entry(1, 2),
+	imx53_imx_ssi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
+struct platform_device *__init imx_add_imx_ssi(
+		const struct imx_imx_ssi_data *data,
+		const struct imx_ssi_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+#define DMARES(_name) {							\
+	.name = #_name,							\
+	.start = data->dma ## _name,					\
+	.end = data->dma ## _name,					\
+	.flags = IORESOURCE_DMA,					\
+}
+		DMARES(tx0),
+		DMARES(rx0),
+		DMARES(tx1),
+		DMARES(rx1),
+	};
+
+	return imx_add_platform_device("imx-ssi", data->id,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/mach-imx/devices/platform-imx-uart.c b/arch/arm/mach-imx/devices/platform-imx-uart.c
new file mode 100644
index 0000000..67bf866
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-imx-uart.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2009-2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_imx_uart_3irq_data_entry(soc, _id, _hwid, _size)		\
+	[_id] = {							\
+		.id = _id,						\
+		.iobase = soc ## _UART ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+		.irqrx = soc ## _INT_UART ## _hwid ## RX,		\
+		.irqtx = soc ## _INT_UART ## _hwid ## TX,		\
+		.irqrts = soc ## _INT_UART ## _hwid ## RTS,		\
+	}
+
+#define imx_imx_uart_1irq_data_entry(soc, _id, _hwid, _size)		\
+	[_id] = {							\
+		.id = _id,						\
+		.iobase = soc ## _UART ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+		.irq = soc ## _INT_UART ## _hwid,			\
+	}
+
+#ifdef CONFIG_SOC_IMX1
+const struct imx_imx_uart_3irq_data imx1_imx_uart_data[] __initconst = {
+#define imx1_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_3irq_data_entry(MX1, _id, _hwid, 0xd0)
+	imx1_imx_uart_data_entry(0, 1),
+	imx1_imx_uart_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX1 */
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx_uart_1irq_data imx21_imx_uart_data[] __initconst = {
+#define imx21_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_1irq_data_entry(MX21, _id, _hwid, SZ_4K)
+	imx21_imx_uart_data_entry(0, 1),
+	imx21_imx_uart_data_entry(1, 2),
+	imx21_imx_uart_data_entry(2, 3),
+	imx21_imx_uart_data_entry(3, 4),
+};
+#endif
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_imx_uart_1irq_data imx25_imx_uart_data[] __initconst = {
+#define imx25_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_1irq_data_entry(MX25, _id, _hwid, SZ_16K)
+	imx25_imx_uart_data_entry(0, 1),
+	imx25_imx_uart_data_entry(1, 2),
+	imx25_imx_uart_data_entry(2, 3),
+	imx25_imx_uart_data_entry(3, 4),
+	imx25_imx_uart_data_entry(4, 5),
+};
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx_uart_1irq_data imx27_imx_uart_data[] __initconst = {
+#define imx27_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_1irq_data_entry(MX27, _id, _hwid, SZ_4K)
+	imx27_imx_uart_data_entry(0, 1),
+	imx27_imx_uart_data_entry(1, 2),
+	imx27_imx_uart_data_entry(2, 3),
+	imx27_imx_uart_data_entry(3, 4),
+	imx27_imx_uart_data_entry(4, 5),
+	imx27_imx_uart_data_entry(5, 6),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_imx_uart_1irq_data imx31_imx_uart_data[] __initconst = {
+#define imx31_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_1irq_data_entry(MX31, _id, _hwid, SZ_4K)
+	imx31_imx_uart_data_entry(0, 1),
+	imx31_imx_uart_data_entry(1, 2),
+	imx31_imx_uart_data_entry(2, 3),
+	imx31_imx_uart_data_entry(3, 4),
+	imx31_imx_uart_data_entry(4, 5),
+};
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_imx_uart_1irq_data imx35_imx_uart_data[] __initconst = {
+#define imx35_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_1irq_data_entry(MX35, _id, _hwid, SZ_16K)
+	imx35_imx_uart_data_entry(0, 1),
+	imx35_imx_uart_data_entry(1, 2),
+	imx35_imx_uart_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX50
+const struct imx_imx_uart_1irq_data imx50_imx_uart_data[] __initconst = {
+#define imx50_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_1irq_data_entry(MX50, _id, _hwid, SZ_4K)
+	imx50_imx_uart_data_entry(0, 1),
+	imx50_imx_uart_data_entry(1, 2),
+	imx50_imx_uart_data_entry(2, 3),
+	imx50_imx_uart_data_entry(3, 4),
+	imx50_imx_uart_data_entry(4, 5),
+};
+#endif /* ifdef CONFIG_SOC_IMX50 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_imx_uart_1irq_data imx51_imx_uart_data[] __initconst = {
+#define imx51_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_1irq_data_entry(MX51, _id, _hwid, SZ_4K)
+	imx51_imx_uart_data_entry(0, 1),
+	imx51_imx_uart_data_entry(1, 2),
+	imx51_imx_uart_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_imx_uart_1irq_data imx53_imx_uart_data[] __initconst = {
+#define imx53_imx_uart_data_entry(_id, _hwid)				\
+	imx_imx_uart_1irq_data_entry(MX53, _id, _hwid, SZ_4K)
+	imx53_imx_uart_data_entry(0, 1),
+	imx53_imx_uart_data_entry(1, 2),
+	imx53_imx_uart_data_entry(2, 3),
+	imx53_imx_uart_data_entry(3, 4),
+	imx53_imx_uart_data_entry(4, 5),
+};
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
+struct platform_device *__init imx_add_imx_uart_3irq(
+		const struct imx_imx_uart_3irq_data *data,
+		const struct imxuart_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irqrx,
+			.end = data->irqrx,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->irqtx,
+			.end = data->irqtx,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->irqrts,
+			.end = data->irqrx,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device("imx1-uart", data->id, res,
+			ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
+
+struct platform_device *__init imx_add_imx_uart_1irq(
+		const struct imx_imx_uart_1irq_data *data,
+		const struct imxuart_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	/* i.mx21 type uart runs on all i.mx except i.mx1 */
+	return imx_add_platform_device("imx21-uart", data->id,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/mach-imx/devices/platform-imx2-wdt.c b/arch/arm/mach-imx/devices/platform-imx2-wdt.c
new file mode 100644
index 0000000..ec75d64
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-imx2-wdt.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <asm/sizes.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_imx2_wdt_data_entry_single(soc, _id, _hwid, _size)		\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _WDOG ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+	}
+#define imx_imx2_wdt_data_entry(soc, _id, _hwid, _size)			\
+	[_id] = imx_imx2_wdt_data_entry_single(soc, _id, _hwid, _size)
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx2_wdt_data imx21_imx2_wdt_data __initconst =
+	imx_imx2_wdt_data_entry_single(MX21, 0, , SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_imx2_wdt_data imx25_imx2_wdt_data __initconst =
+	imx_imx2_wdt_data_entry_single(MX25, 0, , SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx2_wdt_data imx27_imx2_wdt_data __initconst =
+	imx_imx2_wdt_data_entry_single(MX27, 0, , SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_imx2_wdt_data imx31_imx2_wdt_data __initconst =
+	imx_imx2_wdt_data_entry_single(MX31, 0, , SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_imx2_wdt_data imx35_imx2_wdt_data __initconst =
+	imx_imx2_wdt_data_entry_single(MX35, 0, , SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_imx2_wdt_data imx51_imx2_wdt_data[] __initconst = {
+#define imx51_imx2_wdt_data_entry(_id, _hwid)				\
+	imx_imx2_wdt_data_entry(MX51, _id, _hwid, SZ_16K)
+	imx51_imx2_wdt_data_entry(0, 1),
+	imx51_imx2_wdt_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_imx2_wdt_data imx53_imx2_wdt_data[] __initconst = {
+#define imx53_imx2_wdt_data_entry(_id, _hwid)				\
+	imx_imx2_wdt_data_entry(MX53, _id, _hwid, SZ_16K)
+	imx53_imx2_wdt_data_entry(0, 1),
+	imx53_imx2_wdt_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
+struct platform_device *__init imx_add_imx2_wdt(
+		const struct imx_imx2_wdt_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		},
+	};
+	return imx_add_platform_device("imx2-wdt", data->id,
+			res, ARRAY_SIZE(res), NULL, 0);
+}
diff --git a/arch/arm/mach-imx/devices/platform-imx21-hcd.c b/arch/arm/mach-imx/devices/platform-imx21-hcd.c
new file mode 100644
index 0000000..30c8161
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-imx21-hcd.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_imx21_hcd_data_entry_single(soc)				\
+	{								\
+		.iobase = soc ## _USBOTG_BASE_ADDR,			\
+		.irq = soc ## _INT_USBHOST,				\
+	}
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx21_hcd_data imx21_imx21_hcd_data __initconst =
+	imx_imx21_hcd_data_entry_single(MX21);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+struct platform_device *__init imx_add_imx21_hcd(
+		const struct imx_imx21_hcd_data *data,
+		const struct mx21_usbh_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	return imx_add_platform_device_dmamask("imx21-hcd", 0,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
diff --git a/arch/arm/mach-imx/devices/platform-imx27-coda.c b/arch/arm/mach-imx/devices/platform-imx27-coda.c
new file mode 100644
index 0000000..25bebc2
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-imx27-coda.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 Vista Silicon
+ * Javier Martin <javier.martin@vista-silicon.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 "../hardware.h"
+#include "devices-common.h"
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx27_coda_data imx27_coda_data __initconst = {
+	.iobase = MX27_VPU_BASE_ADDR,
+	.iosize = SZ_512,
+	.irq = MX27_INT_VPU,
+};
+#endif
+
+struct platform_device *__init imx_add_imx27_coda(
+		const struct imx_imx27_coda_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	return imx_add_platform_device_dmamask("coda-imx27", 0, res, 2, NULL,
+					0, DMA_BIT_MASK(32));
+}
diff --git a/arch/arm/mach-imx/devices/platform-imx_udc.c b/arch/arm/mach-imx/devices/platform-imx_udc.c
new file mode 100644
index 0000000..5ced7e4
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-imx_udc.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_imx_udc_data_entry_single(soc, _size)			\
+	{								\
+		.iobase = soc ## _USBD_BASE_ADDR,			\
+		.iosize = _size,					\
+		.irq0 = soc ## _INT_USBD0,				\
+		.irq1 = soc ## _INT_USBD1,				\
+		.irq2 = soc ## _INT_USBD2,				\
+		.irq3 = soc ## _INT_USBD3,				\
+		.irq4 = soc ## _INT_USBD4,				\
+		.irq5 = soc ## _INT_USBD5,				\
+		.irq6 = soc ## _INT_USBD6,				\
+	}
+
+#define imx_imx_udc_data_entry(soc, _size)				\
+	[_id] = imx_imx_udc_data_entry_single(soc, _size)
+
+#ifdef CONFIG_SOC_IMX1
+const struct imx_imx_udc_data imx1_imx_udc_data __initconst =
+	imx_imx_udc_data_entry_single(MX1, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX1 */
+
+struct platform_device *__init imx_add_imx_udc(
+		const struct imx_imx_udc_data *data,
+		const struct imxusb_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq0,
+			.end = data->irq0,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->irq1,
+			.end = data->irq1,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->irq2,
+			.end = data->irq2,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->irq3,
+			.end = data->irq3,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->irq4,
+			.end = data->irq4,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->irq5,
+			.end = data->irq5,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->irq6,
+			.end = data->irq6,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device("imx_udc", 0,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/mach-imx/devices/platform-imxdi_rtc.c b/arch/arm/mach-imx/devices/platform-imxdi_rtc.c
new file mode 100644
index 0000000..5bb490d
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-imxdi_rtc.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <asm/sizes.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_imxdi_rtc_data_entry_single(soc)				\
+	{								\
+		.iobase = soc ## _DRYICE_BASE_ADDR,			\
+		.irq = soc ## _INT_DRYICE,				\
+	}
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_imxdi_rtc_data imx25_imxdi_rtc_data __initconst =
+	imx_imxdi_rtc_data_entry_single(MX25);
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+struct platform_device *__init imx_add_imxdi_rtc(
+		const struct imx_imxdi_rtc_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_16K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device("imxdi_rtc", 0,
+			res, ARRAY_SIZE(res), NULL, 0);
+}
diff --git a/arch/arm/mach-imx/devices/platform-ipu-core.c b/arch/arm/mach-imx/devices/platform-ipu-core.c
new file mode 100644
index 0000000..fc4dd7c
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-ipu-core.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2011 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/dma-mapping.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_ipu_core_entry_single(soc)					\
+{									\
+	.iobase = soc ## _IPU_CTRL_BASE_ADDR,				\
+	.synirq = soc ## _INT_IPU_SYN,					\
+	.errirq = soc ## _INT_IPU_ERR,					\
+}
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_ipu_core_data imx31_ipu_core_data __initconst =
+	imx_ipu_core_entry_single(MX31);
+#endif
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_ipu_core_data imx35_ipu_core_data __initconst =
+	imx_ipu_core_entry_single(MX35);
+#endif
+
+static struct platform_device *imx_ipu_coredev __initdata;
+
+struct platform_device *__init imx_add_ipu_core(
+		const struct imx_ipu_core_data *data)
+{
+	/* The resource order is important! */
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + 0x5f,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->iobase + 0x88,
+			.end = data->iobase + 0xb3,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->synirq,
+			.end = data->synirq,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->errirq,
+			.end = data->errirq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_ipu_coredev = imx_add_platform_device("ipu-core", -1,
+			res, ARRAY_SIZE(res), NULL, 0);
+}
+
+struct platform_device *__init imx_alloc_mx3_camera(
+		const struct imx_ipu_core_data *data,
+		const struct mx3_camera_pdata *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase + 0x60,
+			.end = data->iobase + 0x87,
+			.flags = IORESOURCE_MEM,
+		},
+	};
+	int ret = -ENOMEM;
+	struct platform_device *pdev;
+
+	if (IS_ERR_OR_NULL(imx_ipu_coredev))
+		return ERR_PTR(-ENODEV);
+
+	pdev = platform_device_alloc("mx3-camera", 0);
+	if (!pdev)
+		goto err;
+
+	pdev->dev.dma_mask = kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
+	if (!pdev->dev.dma_mask)
+		goto err;
+
+	*pdev->dev.dma_mask = DMA_BIT_MASK(32);
+	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
+	ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
+	if (ret)
+		goto err;
+
+	if (pdata) {
+		struct mx3_camera_pdata *copied_pdata;
+
+		ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+		if (ret) {
+err:
+			kfree(pdev->dev.dma_mask);
+			platform_device_put(pdev);
+			return ERR_PTR(-ENODEV);
+		}
+		copied_pdata = dev_get_platdata(&pdev->dev);
+		copied_pdata->dma_dev = &imx_ipu_coredev->dev;
+	}
+
+	return pdev;
+}
+
+struct platform_device *__init imx_add_mx3_sdc_fb(
+		const struct imx_ipu_core_data *data,
+		struct mx3fb_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase + 0xb4,
+			.end = data->iobase + 0x1bf,
+			.flags = IORESOURCE_MEM,
+		},
+	};
+
+	if (IS_ERR_OR_NULL(imx_ipu_coredev))
+		return ERR_PTR(-ENODEV);
+
+	pdata->dma_dev = &imx_ipu_coredev->dev;
+
+	return imx_add_platform_device_dmamask("mx3_sdc_fb", -1,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata),
+			DMA_BIT_MASK(32));
+}
diff --git a/arch/arm/mach-imx/devices/platform-mx1-camera.c b/arch/arm/mach-imx/devices/platform-mx1-camera.c
new file mode 100644
index 0000000..2c67881
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-mx1-camera.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_mx1_camera_data_entry_single(soc, _size)			\
+	{								\
+		.iobase = soc ## _CSI ## _BASE_ADDR,			\
+		.iosize = _size,					\
+		.irq = soc ## _INT_CSI,					\
+	}
+
+#ifdef CONFIG_SOC_IMX1
+const struct imx_mx1_camera_data imx1_mx1_camera_data __initconst =
+	imx_mx1_camera_data_entry_single(MX1, 10);
+#endif /* ifdef CONFIG_SOC_IMX1 */
+
+struct platform_device *__init imx_add_mx1_camera(
+		const struct imx_mx1_camera_data *data,
+		const struct mx1_camera_pdata *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	return imx_add_platform_device_dmamask("mx1-camera", 0,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
diff --git a/arch/arm/mach-imx/devices/platform-mx2-camera.c b/arch/arm/mach-imx/devices/platform-mx2-camera.c
new file mode 100644
index 0000000..b53e1f3
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-mx2-camera.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_mx2_camera_data_entry_single(soc, _devid)			\
+	{								\
+		.devid = _devid,					\
+		.iobasecsi = soc ## _CSI_BASE_ADDR,			\
+		.iosizecsi = SZ_4K,					\
+		.irqcsi = soc ## _INT_CSI,				\
+	}
+#define imx_mx2_camera_data_entry_single_emma(soc, _devid)		\
+	{								\
+		.devid = _devid,					\
+		.iobasecsi = soc ## _CSI_BASE_ADDR,			\
+		.iosizecsi = SZ_32,					\
+		.irqcsi = soc ## _INT_CSI,				\
+		.iobaseemmaprp = soc ## _EMMAPRP_BASE_ADDR,		\
+		.iosizeemmaprp = SZ_32,					\
+		.irqemmaprp = soc ## _INT_EMMAPRP,			\
+	}
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_mx2_camera_data imx25_mx2_camera_data __initconst =
+	imx_mx2_camera_data_entry_single(MX25, "imx25-camera");
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_mx2_camera_data imx27_mx2_camera_data __initconst =
+	imx_mx2_camera_data_entry_single_emma(MX27, "imx27-camera");
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+struct platform_device *__init imx_add_mx2_camera(
+		const struct imx_mx2_camera_data *data,
+		const struct mx2_camera_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobasecsi,
+			.end = data->iobasecsi + data->iosizecsi - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irqcsi,
+			.end = data->irqcsi,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->iobaseemmaprp,
+			.end = data->iobaseemmaprp + data->iosizeemmaprp - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irqemmaprp,
+			.end = data->irqemmaprp,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	return imx_add_platform_device_dmamask(data->devid, 0,
+			res, data->iobaseemmaprp ? 4 : 2,
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
+
diff --git a/arch/arm/mach-imx/devices/platform-mxc-ehci.c b/arch/arm/mach-imx/devices/platform-mxc-ehci.c
new file mode 100644
index 0000000..5d4bbbf
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-mxc-ehci.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <linux/dma-mapping.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_mxc_ehci_data_entry_single(soc, _id, hs)			\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _USB_ ## hs ## _BASE_ADDR,		\
+		.irq = soc ## _INT_USB_ ## hs,				\
+	}
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_mxc_ehci_data imx25_mxc_ehci_otg_data __initconst =
+	imx_mxc_ehci_data_entry_single(MX25, 0, OTG);
+const struct imx_mxc_ehci_data imx25_mxc_ehci_hs_data __initconst =
+	imx_mxc_ehci_data_entry_single(MX25, 1, HS);
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_mxc_ehci_data imx27_mxc_ehci_otg_data __initconst =
+	imx_mxc_ehci_data_entry_single(MX27, 0, OTG);
+const struct imx_mxc_ehci_data imx27_mxc_ehci_hs_data[] __initconst = {
+	imx_mxc_ehci_data_entry_single(MX27, 1, HS1),
+	imx_mxc_ehci_data_entry_single(MX27, 2, HS2),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_mxc_ehci_data imx31_mxc_ehci_otg_data __initconst =
+	imx_mxc_ehci_data_entry_single(MX31, 0, OTG);
+const struct imx_mxc_ehci_data imx31_mxc_ehci_hs_data[] __initconst = {
+	imx_mxc_ehci_data_entry_single(MX31, 1, HS1),
+	imx_mxc_ehci_data_entry_single(MX31, 2, HS2),
+};
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_mxc_ehci_data imx35_mxc_ehci_otg_data __initconst =
+	imx_mxc_ehci_data_entry_single(MX35, 0, OTG);
+const struct imx_mxc_ehci_data imx35_mxc_ehci_hs_data __initconst =
+	imx_mxc_ehci_data_entry_single(MX35, 1, HS);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data __initconst =
+	imx_mxc_ehci_data_entry_single(MX51, 0, OTG);
+const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[] __initconst = {
+	imx_mxc_ehci_data_entry_single(MX51, 1, HS1),
+	imx_mxc_ehci_data_entry_single(MX51, 2, HS2),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+struct platform_device *__init imx_add_mxc_ehci(
+		const struct imx_mxc_ehci_data *data,
+		const struct mxc_usbh_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_512 - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	return imx_add_platform_device_dmamask("mxc-ehci", data->id,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
diff --git a/arch/arm/mach-imx/devices/platform-mxc-mmc.c b/arch/arm/mach-imx/devices/platform-mxc-mmc.c
new file mode 100644
index 0000000..b8203c7
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-mxc-mmc.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <linux/dma-mapping.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_mxc_mmc_data_entry_single(soc, _devid, _id, _hwid, _size)	\
+	{								\
+		.devid = _devid,					\
+		.id = _id,						\
+		.iobase = soc ## _SDHC ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+		.irq = soc ## _INT_SDHC ## _hwid,			\
+		.dmareq = soc ## _DMA_REQ_SDHC ## _hwid,		\
+	}
+#define imx_mxc_mmc_data_entry(soc, _devid, _id, _hwid, _size)		\
+	[_id] = imx_mxc_mmc_data_entry_single(soc, _devid, _id, _hwid, _size)
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_mxc_mmc_data imx21_mxc_mmc_data[] __initconst = {
+#define imx21_mxc_mmc_data_entry(_id, _hwid)				\
+	imx_mxc_mmc_data_entry(MX21, "imx21-mmc", _id, _hwid, SZ_4K)
+	imx21_mxc_mmc_data_entry(0, 1),
+	imx21_mxc_mmc_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_mxc_mmc_data imx27_mxc_mmc_data[] __initconst = {
+#define imx27_mxc_mmc_data_entry(_id, _hwid)				\
+	imx_mxc_mmc_data_entry(MX27, "imx21-mmc", _id, _hwid, SZ_4K)
+	imx27_mxc_mmc_data_entry(0, 1),
+	imx27_mxc_mmc_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_mxc_mmc_data imx31_mxc_mmc_data[] __initconst = {
+#define imx31_mxc_mmc_data_entry(_id, _hwid)				\
+	imx_mxc_mmc_data_entry(MX31, "imx31-mmc", _id, _hwid, SZ_16K)
+	imx31_mxc_mmc_data_entry(0, 1),
+	imx31_mxc_mmc_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+struct platform_device *__init imx_add_mxc_mmc(
+		const struct imx_mxc_mmc_data *data,
+		const struct imxmmc_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->dmareq,
+			.end = data->dmareq,
+			.flags = IORESOURCE_DMA,
+		},
+	};
+	return imx_add_platform_device_dmamask(data->devid, data->id,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
diff --git a/arch/arm/mach-imx/devices/platform-mxc_nand.c b/arch/arm/mach-imx/devices/platform-mxc_nand.c
new file mode 100644
index 0000000..7af1c53
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-mxc_nand.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2009-2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <asm/sizes.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_mxc_nand_data_entry_single(soc, _devid, _size)		\
+	{								\
+		.devid = _devid,					\
+		.iobase = soc ## _NFC_BASE_ADDR,			\
+		.iosize = _size,					\
+		.irq = soc ## _INT_NFC					\
+	}
+
+#define imx_mxc_nandv3_data_entry_single(soc, _devid, _size)		\
+	{								\
+		.devid = _devid,					\
+		.id = -1,						\
+		.iobase = soc ## _NFC_BASE_ADDR,			\
+		.iosize = _size,					\
+		.axibase = soc ## _NFC_AXI_BASE_ADDR,			\
+		.irq = soc ## _INT_NFC					\
+	}
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_mxc_nand_data imx21_mxc_nand_data __initconst =
+	imx_mxc_nand_data_entry_single(MX21, "imx21-nand", SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_mxc_nand_data imx25_mxc_nand_data __initconst =
+	imx_mxc_nand_data_entry_single(MX25, "imx25-nand", SZ_8K);
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_mxc_nand_data imx27_mxc_nand_data __initconst =
+	imx_mxc_nand_data_entry_single(MX27, "imx27-nand", SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_mxc_nand_data imx31_mxc_nand_data __initconst =
+	imx_mxc_nand_data_entry_single(MX31, "imx27-nand", SZ_4K);
+#endif
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_mxc_nand_data imx35_mxc_nand_data __initconst =
+	imx_mxc_nand_data_entry_single(MX35, "imx25-nand", SZ_8K);
+#endif
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_mxc_nand_data imx51_mxc_nand_data __initconst =
+	imx_mxc_nandv3_data_entry_single(MX51, "imx51-nand", SZ_16K);
+#endif
+
+struct platform_device *__init imx_add_mxc_nand(
+		const struct imx_mxc_nand_data *data,
+		const struct mxc_nand_platform_data *pdata)
+{
+	/* AXI has to come first, that's how the mxc_nand driver expect it */
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->axibase,
+			.end = data->axibase + SZ_16K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+	};
+	return imx_add_platform_device(data->devid, data->id,
+			res, ARRAY_SIZE(res) - !data->axibase,
+			pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/mach-imx/devices/platform-mxc_pwm.c b/arch/arm/mach-imx/devices/platform-mxc_pwm.c
new file mode 100644
index 0000000..dcd2897
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-mxc_pwm.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009-2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_mxc_pwm_data_entry_single(soc, _id, _hwid, _size)		\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _PWM ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+		.irq = soc ## _INT_PWM ## _hwid,			\
+	}
+#define imx_mxc_pwm_data_entry(soc, _id, _hwid, _size)			\
+	[_id] = imx_mxc_pwm_data_entry_single(soc, _id, _hwid, _size)
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_mxc_pwm_data imx21_mxc_pwm_data __initconst =
+	imx_mxc_pwm_data_entry_single(MX21, 0, , SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_mxc_pwm_data imx25_mxc_pwm_data[] __initconst = {
+#define imx25_mxc_pwm_data_entry(_id, _hwid)				\
+	imx_mxc_pwm_data_entry(MX25, _id, _hwid, SZ_16K)
+	imx25_mxc_pwm_data_entry(0, 1),
+	imx25_mxc_pwm_data_entry(1, 2),
+	imx25_mxc_pwm_data_entry(2, 3),
+	imx25_mxc_pwm_data_entry(3, 4),
+};
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_mxc_pwm_data imx27_mxc_pwm_data __initconst =
+	imx_mxc_pwm_data_entry_single(MX27, 0, , SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_mxc_pwm_data imx51_mxc_pwm_data[] __initconst = {
+#define imx51_mxc_pwm_data_entry(_id, _hwid)				\
+	imx_mxc_pwm_data_entry(MX51, _id, _hwid, SZ_16K)
+	imx51_mxc_pwm_data_entry(0, 1),
+	imx51_mxc_pwm_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+struct platform_device *__init imx_add_mxc_pwm(
+		const struct imx_mxc_pwm_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device("mxc_pwm", data->id,
+			res, ARRAY_SIZE(res), NULL, 0);
+}
diff --git a/arch/arm/mach-imx/devices/platform-mxc_rnga.c b/arch/arm/mach-imx/devices/platform-mxc_rnga.c
new file mode 100644
index 0000000..c58404b
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-mxc_rnga.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include "../hardware.h"
+#include "devices-common.h"
+
+struct imx_mxc_rnga_data {
+	resource_size_t iobase;
+};
+
+#define imx_mxc_rnga_data_entry_single(soc)				\
+	{								\
+		.iobase = soc ## _RNGA_BASE_ADDR,			\
+	}
+
+#ifdef CONFIG_SOC_IMX31
+static const struct imx_mxc_rnga_data imx31_mxc_rnga_data __initconst =
+	imx_mxc_rnga_data_entry_single(MX31);
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+static struct platform_device *__init imx_add_mxc_rnga(
+		const struct imx_mxc_rnga_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_16K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+	};
+	return imx_add_platform_device("mxc_rnga", -1,
+			res, ARRAY_SIZE(res), NULL, 0);
+}
+
+static int __init imxXX_add_mxc_rnga(void)
+{
+	struct platform_device *ret;
+
+#if defined(CONFIG_SOC_IMX31)
+	if (cpu_is_mx31())
+		ret = imx_add_mxc_rnga(&imx31_mxc_rnga_data);
+	else
+#endif /* if defined(CONFIG_SOC_IMX31) */
+		ret = ERR_PTR(-ENODEV);
+
+	if (IS_ERR(ret))
+		return PTR_ERR(ret);
+
+	return 0;
+}
+arch_initcall(imxXX_add_mxc_rnga);
diff --git a/arch/arm/mach-imx/devices/platform-mxc_rtc.c b/arch/arm/mach-imx/devices/platform-mxc_rtc.c
new file mode 100644
index 0000000..c7fffaa
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-mxc_rtc.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010-2011 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 "../hardware.h"
+#include "devices-common.h"
+
+#define imx_mxc_rtc_data_entry_single(soc, _devid)			\
+	{								\
+		.devid = _devid,					\
+		.iobase = soc ## _RTC_BASE_ADDR,			\
+		.irq = soc ## _INT_RTC,					\
+	}
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_mxc_rtc_data imx31_mxc_rtc_data __initconst =
+	imx_mxc_rtc_data_entry_single(MX31, "imx21-rtc");
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_mxc_rtc_data imx35_mxc_rtc_data __initconst =
+	imx_mxc_rtc_data_entry_single(MX35, "imx21-rtc");
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+struct platform_device *__init imx_add_mxc_rtc(
+		const struct imx_mxc_rtc_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_16K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device(data->devid, -1,
+			res, ARRAY_SIZE(res), NULL, 0);
+}
diff --git a/arch/arm/mach-imx/devices/platform-mxc_w1.c b/arch/arm/mach-imx/devices/platform-mxc_w1.c
new file mode 100644
index 0000000..88c18b7
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-mxc_w1.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_mxc_w1_data_entry_single(soc)				\
+	{								\
+		.iobase = soc ## _OWIRE_BASE_ADDR,			\
+	}
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_mxc_w1_data imx21_mxc_w1_data __initconst =
+	imx_mxc_w1_data_entry_single(MX21);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_mxc_w1_data imx27_mxc_w1_data __initconst =
+	imx_mxc_w1_data_entry_single(MX27);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_mxc_w1_data imx31_mxc_w1_data __initconst =
+	imx_mxc_w1_data_entry_single(MX31);
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_mxc_w1_data imx35_mxc_w1_data __initconst =
+	imx_mxc_w1_data_entry_single(MX35);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+struct platform_device *__init imx_add_mxc_w1(
+		const struct imx_mxc_w1_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+	};
+
+	return imx_add_platform_device("mxc_w1", 0,
+			res, ARRAY_SIZE(res), NULL, 0);
+}
diff --git a/arch/arm/mach-imx/devices/platform-pata_imx.c b/arch/arm/mach-imx/devices/platform-pata_imx.c
new file mode 100644
index 0000000..e4ec11c
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-pata_imx.c
@@ -0,0 +1,59 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_pata_imx_data_entry_single(soc, _size)			\
+	{								\
+		.iobase = soc ## _ATA_BASE_ADDR,			\
+		.iosize = _size,					\
+		.irq = soc ## _INT_ATA,					\
+	}
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_pata_imx_data imx27_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX27, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_pata_imx_data imx31_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX31, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_pata_imx_data imx35_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX35, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_pata_imx_data imx51_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX51, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_pata_imx_data imx53_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX53, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
+struct platform_device *__init imx_add_pata_imx(
+		const struct imx_pata_imx_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	return imx_add_platform_device("pata_imx", -1,
+			res, ARRAY_SIZE(res), NULL, 0);
+}
+
diff --git a/arch/arm/mach-imx/devices/platform-sdhci-esdhc-imx.c b/arch/arm/mach-imx/devices/platform-sdhci-esdhc-imx.c
new file mode 100644
index 0000000..e66a4e3
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-sdhci-esdhc-imx.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2010 Pengutronix, Wolfram Sang <w.sang@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+
+#include <linux/platform_data/mmc-esdhc-imx.h>
+
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_sdhci_esdhc_imx_data_entry_single(soc, _devid, _id, hwid) \
+	{								\
+		.devid = _devid,					\
+		.id = _id,						\
+		.iobase = soc ## _ESDHC ## hwid ## _BASE_ADDR,	\
+		.irq = soc ## _INT_ESDHC ## hwid,			\
+	}
+
+#define imx_sdhci_esdhc_imx_data_entry(soc, devid, id, hwid)	\
+	[id] = imx_sdhci_esdhc_imx_data_entry_single(soc, devid, id, hwid)
+
+#ifdef CONFIG_SOC_IMX25
+const struct imx_sdhci_esdhc_imx_data
+imx25_sdhci_esdhc_imx_data[] __initconst = {
+#define imx25_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
+	imx_sdhci_esdhc_imx_data_entry(MX25, "sdhci-esdhc-imx25", _id, _hwid)
+	imx25_sdhci_esdhc_imx_data_entry(0, 1),
+	imx25_sdhci_esdhc_imx_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_sdhci_esdhc_imx_data
+imx35_sdhci_esdhc_imx_data[] __initconst = {
+#define imx35_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
+	imx_sdhci_esdhc_imx_data_entry(MX35, "sdhci-esdhc-imx35", _id, _hwid)
+	imx35_sdhci_esdhc_imx_data_entry(0, 1),
+	imx35_sdhci_esdhc_imx_data_entry(1, 2),
+	imx35_sdhci_esdhc_imx_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_sdhci_esdhc_imx_data
+imx51_sdhci_esdhc_imx_data[] __initconst = {
+#define imx51_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
+	imx_sdhci_esdhc_imx_data_entry(MX51, "sdhci-esdhc-imx51", _id, _hwid)
+	imx51_sdhci_esdhc_imx_data_entry(0, 1),
+	imx51_sdhci_esdhc_imx_data_entry(1, 2),
+	imx51_sdhci_esdhc_imx_data_entry(2, 3),
+	imx51_sdhci_esdhc_imx_data_entry(3, 4),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_sdhci_esdhc_imx_data
+imx53_sdhci_esdhc_imx_data[] __initconst = {
+#define imx53_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
+	imx_sdhci_esdhc_imx_data_entry(MX53, "sdhci-esdhc-imx53", _id, _hwid)
+	imx53_sdhci_esdhc_imx_data_entry(0, 1),
+	imx53_sdhci_esdhc_imx_data_entry(1, 2),
+	imx53_sdhci_esdhc_imx_data_entry(2, 3),
+	imx53_sdhci_esdhc_imx_data_entry(3, 4),
+};
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
+static const struct esdhc_platform_data default_esdhc_pdata __initconst = {
+	.wp_type = ESDHC_WP_NONE,
+	.cd_type = ESDHC_CD_NONE,
+};
+
+struct platform_device *__init imx_add_sdhci_esdhc_imx(
+		const struct imx_sdhci_esdhc_imx_data *data,
+		const struct esdhc_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_16K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	/*
+	 * If machine does not provide pdata, use the default one
+	 * which means no WP/CD support
+	 */
+	if (!pdata)
+		pdata = &default_esdhc_pdata;
+
+	return imx_add_platform_device(data->devid, data->id, res,
+			ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/mach-imx/devices/platform-spi_imx.c b/arch/arm/mach-imx/devices/platform-spi_imx.c
new file mode 100644
index 0000000..8880bcb
--- /dev/null
+++ b/arch/arm/mach-imx/devices/platform-spi_imx.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2009-2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include "../hardware.h"
+#include "devices-common.h"
+
+#define imx_spi_imx_data_entry_single(soc, type, _devid, _id, hwid, _size) \
+	{								\
+		.devid = _devid,					\
+		.id = _id,						\
+		.iobase = soc ## _ ## type ## hwid ## _BASE_ADDR,	\
+		.iosize = _size,					\
+		.irq = soc ## _INT_ ## type ## hwid,			\
+	}
+
+#define imx_spi_imx_data_entry(soc, type, devid, id, hwid, size)	\
+	[id] = imx_spi_imx_data_entry_single(soc, type, devid, id, hwid, size)
+
+#ifdef CONFIG_SOC_IMX1
+const struct imx_spi_imx_data imx1_cspi_data[] __initconst = {
+#define imx1_cspi_data_entry(_id, _hwid) \
+	imx_spi_imx_data_entry(MX1, CSPI, "imx1-cspi", _id, _hwid, SZ_4K)
+	imx1_cspi_data_entry(0, 1),
+	imx1_cspi_data_entry(1, 2),
+};
+#endif
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_spi_imx_data imx21_cspi_data[] __initconst = {
+#define imx21_cspi_data_entry(_id, _hwid)                            \
+	imx_spi_imx_data_entry(MX21, CSPI, "imx21-cspi", _id, _hwid, SZ_4K)
+	imx21_cspi_data_entry(0, 1),
+	imx21_cspi_data_entry(1, 2),
+};
+#endif
+
+#ifdef CONFIG_SOC_IMX25
+/* i.mx25 has the i.mx35 type cspi */
+const struct imx_spi_imx_data imx25_cspi_data[] __initconst = {
+#define imx25_cspi_data_entry(_id, _hwid)				\
+	imx_spi_imx_data_entry(MX25, CSPI, "imx35-cspi", _id, _hwid, SZ_16K)
+	imx25_cspi_data_entry(0, 1),
+	imx25_cspi_data_entry(1, 2),
+	imx25_cspi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_spi_imx_data imx27_cspi_data[] __initconst = {
+#define imx27_cspi_data_entry(_id, _hwid)				\
+	imx_spi_imx_data_entry(MX27, CSPI, "imx27-cspi", _id, _hwid, SZ_4K)
+	imx27_cspi_data_entry(0, 1),
+	imx27_cspi_data_entry(1, 2),
+	imx27_cspi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_spi_imx_data imx31_cspi_data[] __initconst = {
+#define imx31_cspi_data_entry(_id, _hwid)				\
+	imx_spi_imx_data_entry(MX31, CSPI, "imx31-cspi", _id, _hwid, SZ_4K)
+	imx31_cspi_data_entry(0, 1),
+	imx31_cspi_data_entry(1, 2),
+	imx31_cspi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_spi_imx_data imx35_cspi_data[] __initconst = {
+#define imx35_cspi_data_entry(_id, _hwid)                           \
+	imx_spi_imx_data_entry(MX35, CSPI, "imx35-cspi", _id, _hwid, SZ_4K)
+	imx35_cspi_data_entry(0, 1),
+	imx35_cspi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX51
+/* i.mx51 has the i.mx35 type cspi */
+const struct imx_spi_imx_data imx51_cspi_data __initconst =
+	imx_spi_imx_data_entry_single(MX51, CSPI, "imx35-cspi", 2, , SZ_4K);
+
+const struct imx_spi_imx_data imx51_ecspi_data[] __initconst = {
+#define imx51_ecspi_data_entry(_id, _hwid)				\
+	imx_spi_imx_data_entry(MX51, ECSPI, "imx51-ecspi", _id, _hwid, SZ_4K)
+	imx51_ecspi_data_entry(0, 1),
+	imx51_ecspi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+/* i.mx53 has the i.mx35 type cspi */
+const struct imx_spi_imx_data imx53_cspi_data __initconst =
+	imx_spi_imx_data_entry_single(MX53, CSPI, "imx35-cspi", 2, , SZ_4K);
+
+/* i.mx53 has the i.mx51 type ecspi */
+const struct imx_spi_imx_data imx53_ecspi_data[] __initconst = {
+#define imx53_ecspi_data_entry(_id, _hwid)				\
+	imx_spi_imx_data_entry(MX53, ECSPI, "imx51-ecspi", _id, _hwid, SZ_4K)
+	imx53_ecspi_data_entry(0, 1),
+	imx53_ecspi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
+struct platform_device *__init imx_add_spi_imx(
+		const struct imx_spi_imx_data *data,
+		const struct spi_imx_master *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device(data->devid, data->id,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/mach-imx/ehci-imx25.c b/arch/arm/mach-imx/ehci-imx25.c
index 576af74..134c190 100644
--- a/arch/arm/mach-imx/ehci-imx25.c
+++ b/arch/arm/mach-imx/ehci-imx25.c
@@ -15,10 +15,10 @@
 
 #include <linux/platform_device.h>
 #include <linux/io.h>
-
-#include <mach/hardware.h>
 #include <linux/platform_data/usb-ehci-mxc.h>
 
+#include "hardware.h"
+
 #define USBCTRL_OTGBASE_OFFSET	0x600
 
 #define MX25_OTG_SIC_SHIFT	29
diff --git a/arch/arm/mach-imx/ehci-imx27.c b/arch/arm/mach-imx/ehci-imx27.c
index cd6e1f8..448d911 100644
--- a/arch/arm/mach-imx/ehci-imx27.c
+++ b/arch/arm/mach-imx/ehci-imx27.c
@@ -15,10 +15,10 @@
 
 #include <linux/platform_device.h>
 #include <linux/io.h>
-
-#include <mach/hardware.h>
 #include <linux/platform_data/usb-ehci-mxc.h>
 
+#include "hardware.h"
+
 #define USBCTRL_OTGBASE_OFFSET	0x600
 
 #define MX27_OTG_SIC_SHIFT	29
diff --git a/arch/arm/mach-imx/ehci-imx31.c b/arch/arm/mach-imx/ehci-imx31.c
index 9a880c7..05de4e1 100644
--- a/arch/arm/mach-imx/ehci-imx31.c
+++ b/arch/arm/mach-imx/ehci-imx31.c
@@ -15,10 +15,10 @@
 
 #include <linux/platform_device.h>
 #include <linux/io.h>
-
-#include <mach/hardware.h>
 #include <linux/platform_data/usb-ehci-mxc.h>
 
+#include "hardware.h"
+
 #define USBCTRL_OTGBASE_OFFSET	0x600
 
 #define MX31_OTG_SIC_SHIFT	29
diff --git a/arch/arm/mach-imx/ehci-imx35.c b/arch/arm/mach-imx/ehci-imx35.c
index 2933978..554e7cc 100644
--- a/arch/arm/mach-imx/ehci-imx35.c
+++ b/arch/arm/mach-imx/ehci-imx35.c
@@ -15,10 +15,10 @@
 
 #include <linux/platform_device.h>
 #include <linux/io.h>
-
-#include <mach/hardware.h>
 #include <linux/platform_data/usb-ehci-mxc.h>
 
+#include "hardware.h"
+
 #define USBCTRL_OTGBASE_OFFSET	0x600
 
 #define MX35_OTG_SIC_SHIFT	29
diff --git a/arch/arm/mach-imx/ehci-imx5.c b/arch/arm/mach-imx/ehci-imx5.c
index cf8d00e..e49710b 100644
--- a/arch/arm/mach-imx/ehci-imx5.c
+++ b/arch/arm/mach-imx/ehci-imx5.c
@@ -15,10 +15,10 @@
 
 #include <linux/platform_device.h>
 #include <linux/io.h>
-
-#include <mach/hardware.h>
 #include <linux/platform_data/usb-ehci-mxc.h>
 
+#include "hardware.h"
+
 #define MXC_OTG_OFFSET			0
 #define MXC_H1_OFFSET			0x200
 #define MXC_H2_OFFSET			0x400
diff --git a/arch/arm/mach-imx/epit.c b/arch/arm/mach-imx/epit.c
new file mode 100644
index 0000000..04a5961
--- /dev/null
+++ b/arch/arm/mach-imx/epit.c
@@ -0,0 +1,234 @@
+/*
+ *  linux/arch/arm/plat-mxc/epit.c
+ *
+ *  Copyright (C) 2010 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#define EPITCR		0x00
+#define EPITSR		0x04
+#define EPITLR		0x08
+#define EPITCMPR	0x0c
+#define EPITCNR		0x10
+
+#define EPITCR_EN			(1 << 0)
+#define EPITCR_ENMOD			(1 << 1)
+#define EPITCR_OCIEN			(1 << 2)
+#define EPITCR_RLD			(1 << 3)
+#define EPITCR_PRESC(x)			(((x) & 0xfff) << 4)
+#define EPITCR_SWR			(1 << 16)
+#define EPITCR_IOVW			(1 << 17)
+#define EPITCR_DBGEN			(1 << 18)
+#define EPITCR_WAITEN			(1 << 19)
+#define EPITCR_RES			(1 << 20)
+#define EPITCR_STOPEN			(1 << 21)
+#define EPITCR_OM_DISCON		(0 << 22)
+#define EPITCR_OM_TOGGLE		(1 << 22)
+#define EPITCR_OM_CLEAR			(2 << 22)
+#define EPITCR_OM_SET			(3 << 22)
+#define EPITCR_CLKSRC_OFF		(0 << 24)
+#define EPITCR_CLKSRC_PERIPHERAL	(1 << 24)
+#define EPITCR_CLKSRC_REF_HIGH		(1 << 24)
+#define EPITCR_CLKSRC_REF_LOW		(3 << 24)
+
+#define EPITSR_OCIF			(1 << 0)
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <asm/mach/time.h>
+
+#include "common.h"
+#include "hardware.h"
+
+static struct clock_event_device clockevent_epit;
+static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
+
+static void __iomem *timer_base;
+
+static inline void epit_irq_disable(void)
+{
+	u32 val;
+
+	val = __raw_readl(timer_base + EPITCR);
+	val &= ~EPITCR_OCIEN;
+	__raw_writel(val, timer_base + EPITCR);
+}
+
+static inline void epit_irq_enable(void)
+{
+	u32 val;
+
+	val = __raw_readl(timer_base + EPITCR);
+	val |= EPITCR_OCIEN;
+	__raw_writel(val, timer_base + EPITCR);
+}
+
+static void epit_irq_acknowledge(void)
+{
+	__raw_writel(EPITSR_OCIF, timer_base + EPITSR);
+}
+
+static int __init epit_clocksource_init(struct clk *timer_clk)
+{
+	unsigned int c = clk_get_rate(timer_clk);
+
+	return clocksource_mmio_init(timer_base + EPITCNR, "epit", c, 200, 32,
+			clocksource_mmio_readl_down);
+}
+
+/* clock event */
+
+static int epit_set_next_event(unsigned long evt,
+			      struct clock_event_device *unused)
+{
+	unsigned long tcmp;
+
+	tcmp = __raw_readl(timer_base + EPITCNR);
+
+	__raw_writel(tcmp - evt, timer_base + EPITCMPR);
+
+	return 0;
+}
+
+static void epit_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *evt)
+{
+	unsigned long flags;
+
+	/*
+	 * The timer interrupt generation is disabled at least
+	 * for enough time to call epit_set_next_event()
+	 */
+	local_irq_save(flags);
+
+	/* Disable interrupt in GPT module */
+	epit_irq_disable();
+
+	if (mode != clockevent_mode) {
+		/* Set event time into far-far future */
+
+		/* Clear pending interrupt */
+		epit_irq_acknowledge();
+	}
+
+	/* Remember timer mode */
+	clockevent_mode = mode;
+	local_irq_restore(flags);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		printk(KERN_ERR "epit_set_mode: Periodic mode is not "
+				"supported for i.MX EPIT\n");
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+	/*
+	 * Do not put overhead of interrupt enable/disable into
+	 * epit_set_next_event(), the core has about 4 minutes
+	 * to call epit_set_next_event() or shutdown clock after
+	 * mode switching
+	 */
+		local_irq_save(flags);
+		epit_irq_enable();
+		local_irq_restore(flags);
+		break;
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_RESUME:
+		/* Left event sources disabled, no more interrupts appear */
+		break;
+	}
+}
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t epit_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = &clockevent_epit;
+
+	epit_irq_acknowledge();
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction epit_timer_irq = {
+	.name		= "i.MX EPIT Timer Tick",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= epit_timer_interrupt,
+};
+
+static struct clock_event_device clockevent_epit = {
+	.name		= "epit",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.shift		= 32,
+	.set_mode	= epit_set_mode,
+	.set_next_event	= epit_set_next_event,
+	.rating		= 200,
+};
+
+static int __init epit_clockevent_init(struct clk *timer_clk)
+{
+	unsigned int c = clk_get_rate(timer_clk);
+
+	clockevent_epit.mult = div_sc(c, NSEC_PER_SEC,
+					clockevent_epit.shift);
+	clockevent_epit.max_delta_ns =
+			clockevent_delta2ns(0xfffffffe, &clockevent_epit);
+	clockevent_epit.min_delta_ns =
+			clockevent_delta2ns(0x800, &clockevent_epit);
+
+	clockevent_epit.cpumask = cpumask_of(0);
+
+	clockevents_register_device(&clockevent_epit);
+
+	return 0;
+}
+
+void __init epit_timer_init(void __iomem *base, int irq)
+{
+	struct clk *timer_clk;
+
+	timer_clk = clk_get_sys("imx-epit.0", NULL);
+	if (IS_ERR(timer_clk)) {
+		pr_err("i.MX epit: unable to get clk\n");
+		return;
+	}
+
+	clk_prepare_enable(timer_clk);
+
+	timer_base = base;
+
+	/*
+	 * Initialise to a known state (all timers off, and timing reset)
+	 */
+	__raw_writel(0x0, timer_base + EPITCR);
+
+	__raw_writel(0xffffffff, timer_base + EPITLR);
+	__raw_writel(EPITCR_EN | EPITCR_CLKSRC_REF_HIGH | EPITCR_WAITEN,
+			timer_base + EPITCR);
+
+	/* init and register the timer to the framework */
+	epit_clocksource_init(timer_clk);
+	epit_clockevent_init(timer_clk);
+
+	/* Make irqs happen */
+	setup_irq(irq, &epit_timer_irq);
+}
diff --git a/arch/arm/mach-imx/eukrea-baseboards.h b/arch/arm/mach-imx/eukrea-baseboards.h
new file mode 100644
index 0000000..a21d331
--- /dev/null
+++ b/arch/arm/mach-imx/eukrea-baseboards.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 Eric Benard - eric@eukrea.com
+ *
+ * Based on board-pcm038.h which is :
+ * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __MACH_EUKREA_BASEBOARDS_H__
+#define __MACH_EUKREA_BASEBOARDS_H__
+
+#ifndef __ASSEMBLY__
+/*
+ * This CPU module needs a baseboard to work. After basic initializing
+ * its own devices, it calls baseboard's init function.
+ * TODO: Add your own baseboard init function and call it from
+ * inside eukrea_cpuimx25_init() eukrea_cpuimx27_init()
+ * eukrea_cpuimx35_init() eukrea_cpuimx51_init()
+ * or eukrea_cpuimx51sd_init().
+ *
+ * This example here is for the development board. Refer
+ * mach-mx25/eukrea_mbimxsd-baseboard.c for cpuimx25
+ * mach-imx/eukrea_mbimx27-baseboard.c for cpuimx27
+ * mach-mx3/eukrea_mbimxsd-baseboard.c for cpuimx35
+ * mach-mx5/eukrea_mbimx51-baseboard.c for cpuimx51
+ * mach-mx5/eukrea_mbimxsd-baseboard.c for cpuimx51sd
+ */
+
+extern void eukrea_mbimxsd25_baseboard_init(void);
+extern void eukrea_mbimx27_baseboard_init(void);
+extern void eukrea_mbimxsd35_baseboard_init(void);
+extern void eukrea_mbimx51_baseboard_init(void);
+extern void eukrea_mbimxsd51_baseboard_init(void);
+
+#endif
+
+#endif /* __MACH_EUKREA_BASEBOARDS_H__ */
diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
index 98aef57..b4c7002 100644
--- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
@@ -29,11 +29,10 @@
 
 #include <asm/mach/arch.h>
 
-#include <mach/common.h>
-#include <mach/iomux-mx27.h>
-#include <mach/hardware.h>
-
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
 
 static const int eukrea_mbimx27_pins[] __initconst = {
 	/* UART2 */
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
index 0b84666..e2b70f4c 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
@@ -26,14 +26,14 @@
 #include <linux/spi/spi.h>
 #include <video/platform_lcd.h>
 
-#include <mach/hardware.h>
-#include <mach/iomux-mx25.h>
-#include <mach/common.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <mach/mx25.h>
 
+#include "common.h"
 #include "devices-imx25.h"
+#include "hardware.h"
+#include "iomux-mx25.h"
+#include "mx25.h"
 
 static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
 	/* LCD */
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
index c6532a0..5a2d5ef 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
@@ -36,11 +36,10 @@
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx35.h>
-
+#include "common.h"
 #include "devices-imx35.h"
+#include "hardware.h"
+#include "iomux-mx35.h"
 
 static const struct fb_videomode fb_modedb[] = {
 	{
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c
index 8b0de30..9be6c1e 100644
--- a/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c
@@ -36,11 +36,10 @@
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx51.h>
-
+#include "common.h"
 #include "devices-imx51.h"
+#include "hardware.h"
+#include "iomux-mx51.h"
 
 static iomux_v3_cfg_t eukrea_mbimxsd51_pads[] = {
 	/* LED */
diff --git a/arch/arm/mach-imx/hardware.h b/arch/arm/mach-imx/hardware.h
new file mode 100644
index 0000000..3ce7fa3
--- /dev/null
+++ b/arch/arm/mach-imx/hardware.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ */
+
+#ifndef __ASM_ARCH_MXC_HARDWARE_H__
+#define __ASM_ARCH_MXC_HARDWARE_H__
+
+#include <asm/sizes.h>
+
+#define addr_in_module(addr, mod) \
+	((unsigned long)(addr) - mod ## _BASE_ADDR < mod ## _SIZE)
+
+#define IMX_IO_P2V_MODULE(addr, module)					\
+	(((addr) - module ## _BASE_ADDR) < module ## _SIZE ?		\
+	 (addr) - (module ## _BASE_ADDR) + (module ## _BASE_ADDR_VIRT) : 0)
+
+/*
+ * This is rather complicated for humans and ugly to verify, but for a machine
+ * it's OK.  Still more as it is usually only applied to constants.  The upsides
+ * on using this approach are:
+ *
+ *  - same mapping on all i.MX machines
+ *  - works for assembler, too
+ *  - no need to nurture #defines for virtual addresses
+ *
+ * The downside it, it's hard to verify (but I have a script for that).
+ *
+ * Obviously this needs to be injective for each SoC.  In general it maps the
+ * whole address space to [0xf4000000, 0xf5ffffff].  So [0xf6000000,0xfeffffff]
+ * is free for per-machine use (e.g. KZM_ARM11_01 uses 64MiB there).
+ *
+ * It applies the following mappings for the different SoCs:
+ *
+ * mx1:
+ *	IO	0x00200000+0x100000	->	0xf4000000+0x100000
+ * mx21:
+ *	AIPI	0x10000000+0x100000	->	0xf4400000+0x100000
+ *	SAHB1	0x80000000+0x100000	->	0xf5000000+0x100000
+ *	X_MEMC	0xdf000000+0x004000	->	0xf5f00000+0x004000
+ * mx25:
+ *	AIPS1	0x43f00000+0x100000	->	0xf5300000+0x100000
+ *	AIPS2	0x53f00000+0x100000	->	0xf5700000+0x100000
+ *	AVIC	0x68000000+0x100000	->	0xf5800000+0x100000
+ * mx27:
+ *	AIPI	0x10000000+0x100000	->	0xf4400000+0x100000
+ *	SAHB1	0x80000000+0x100000	->	0xf5000000+0x100000
+ *	X_MEMC	0xd8000000+0x100000	->	0xf5c00000+0x100000
+ * mx31:
+ *	AIPS1	0x43f00000+0x100000	->	0xf5300000+0x100000
+ *	AIPS2	0x53f00000+0x100000	->	0xf5700000+0x100000
+ *	AVIC	0x68000000+0x100000	->	0xf5800000+0x100000
+ *	X_MEMC	0xb8000000+0x010000	->	0xf5c00000+0x010000
+ *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
+ * mx35:
+ *	AIPS1	0x43f00000+0x100000	->	0xf5300000+0x100000
+ *	AIPS2	0x53f00000+0x100000	->	0xf5700000+0x100000
+ *	AVIC	0x68000000+0x100000	->	0xf5800000+0x100000
+ *	X_MEMC	0xb8000000+0x010000	->	0xf5c00000+0x010000
+ *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
+ * mx50:
+ *	TZIC	0x0fffc000+0x004000	->	0xf4bfc000+0x004000
+ *	AIPS1	0x53f00000+0x100000	->	0xf5700000+0x100000
+ *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
+ *	AIPS2	0x63f00000+0x100000	->	0xf5300000+0x100000
+ * mx51:
+ *	TZIC	0x0fffc000+0x004000	->	0xf4bfc000+0x004000
+ *	IRAM	0x1ffe0000+0x020000	->	0xf4fe0000+0x020000
+ *	DEBUG	0x60000000+0x100000	->	0xf5000000+0x100000
+ *	SPBA0	0x70000000+0x100000	->	0xf5400000+0x100000
+ *	AIPS1	0x73f00000+0x100000	->	0xf5700000+0x100000
+ *	AIPS2	0x83f00000+0x100000	->	0xf5300000+0x100000
+ * mx53:
+ *	TZIC	0x0fffc000+0x004000	->	0xf4bfc000+0x004000
+ *	DEBUG	0x40000000+0x100000	->	0xf5000000+0x100000
+ *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
+ *	AIPS1	0x53f00000+0x100000	->	0xf5700000+0x100000
+ *	AIPS2	0x63f00000+0x100000	->	0xf5300000+0x100000
+ * mx6q:
+ *	SCU	0x00a00000+0x004000	->	0xf4000000+0x004000
+ *	CCM	0x020c4000+0x004000	->	0xf42c4000+0x004000
+ *	ANATOP	0x020c8000+0x004000	->	0xf42c8000+0x004000
+ *	UART4	0x021f0000+0x004000	->	0xf42f0000+0x004000
+ */
+#define IMX_IO_P2V(x)	(						\
+			(((x) & 0x80000000) >> 7) |			\
+			(0xf4000000 +					\
+			(((x) & 0x50000000) >> 6) +			\
+			(((x) & 0x0b000000) >> 4) +			\
+			(((x) & 0x000fffff))))
+
+#define IMX_IO_ADDRESS(x)	IOMEM(IMX_IO_P2V(x))
+
+#include "mxc.h"
+
+#include "mx6q.h"
+#include "mx50.h"
+#include "mx51.h"
+#include "mx53.h"
+#include "mx3x.h"
+#include "mx31.h"
+#include "mx35.h"
+#include "mx2x.h"
+#include "mx21.h"
+#include "mx27.h"
+#include "mx1.h"
+#include "mx25.h"
+
+#define imx_map_entry(soc, name, _type)	{				\
+	.virtual = soc ## _IO_P2V(soc ## _ ## name ## _BASE_ADDR),	\
+	.pfn = __phys_to_pfn(soc ## _ ## name ## _BASE_ADDR),		\
+	.length = soc ## _ ## name ## _SIZE,				\
+	.type = _type,							\
+}
+
+/* There's a off-by-one betweem the gpio bank number and the gpiochip */
+/* range e.g. GPIO_1_5 is gpio 5 under linux */
+#define IMX_GPIO_NR(bank, nr)		(((bank) - 1) * 32 + (nr))
+
+#endif /* __ASM_ARCH_MXC_HARDWARE_H__ */
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
index b07b778..3dec962 100644
--- a/arch/arm/mach-imx/hotplug.c
+++ b/arch/arm/mach-imx/hotplug.c
@@ -13,7 +13,8 @@
 #include <linux/errno.h>
 #include <asm/cacheflush.h>
 #include <asm/cp15.h>
-#include <mach/common.h>
+
+#include "common.h"
 
 static inline void cpu_enter_lowpower(void)
 {
diff --git a/arch/arm/mach-imx/iim.h b/arch/arm/mach-imx/iim.h
new file mode 100644
index 0000000..315bffa
--- /dev/null
+++ b/arch/arm/mach-imx/iim.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ */
+
+#ifndef __ASM_ARCH_MXC_IIM_H__
+#define __ASM_ARCH_MXC_IIM_H__
+
+/* Register offsets */
+#define MXC_IIMSTAT             0x0000
+#define MXC_IIMSTATM            0x0004
+#define MXC_IIMERR              0x0008
+#define MXC_IIMEMASK            0x000C
+#define MXC_IIMFCTL             0x0010
+#define MXC_IIMUA               0x0014
+#define MXC_IIMLA               0x0018
+#define MXC_IIMSDAT             0x001C
+#define MXC_IIMPREV             0x0020
+#define MXC_IIMSREV             0x0024
+#define MXC_IIMPRG_P            0x0028
+#define MXC_IIMSCS0             0x002C
+#define MXC_IIMSCS1             0x0030
+#define MXC_IIMSCS2             0x0034
+#define MXC_IIMSCS3             0x0038
+#define MXC_IIMFBAC0            0x0800
+#define MXC_IIMJAC              0x0804
+#define MXC_IIMHWV1             0x0808
+#define MXC_IIMHWV2             0x080C
+#define MXC_IIMHAB0             0x0810
+#define MXC_IIMHAB1             0x0814
+/* Definitions for i.MX27 TO2 */
+#define MXC_IIMMAC              0x0814
+#define MXC_IIMPREV_FUSE        0x0818
+#define MXC_IIMSREV_FUSE        0x081C
+#define MXC_IIMSJC_CHALL_0      0x0820
+#define MXC_IIMSJC_CHALL_7      0x083C
+#define MXC_IIMFB0UC17          0x0840
+#define MXC_IIMFB0UC255         0x0BFC
+#define MXC_IIMFBAC1            0x0C00
+/* Definitions for i.MX27 TO2 */
+#define MXC_IIMSUID             0x0C04
+#define MXC_IIMKEY0             0x0C04
+#define MXC_IIMKEY20            0x0C54
+#define MXC_IIMSJC_RESP_0       0x0C58
+#define MXC_IIMSJC_RESP_7       0x0C74
+#define MXC_IIMFB1UC30          0x0C78
+#define MXC_IIMFB1UC255         0x0FFC
+
+/* Bit definitions */
+
+#define MXC_IIMHWV1_WLOCK               (0x1 << 7)
+#define MXC_IIMHWV1_MCU_ENDIAN          (0x1 << 6)
+#define MXC_IIMHWV1_DSP_ENDIAN          (0x1 << 5)
+#define MXC_IIMHWV1_BOOT_INT            (0x1 << 4)
+#define MXC_IIMHWV1_SCC_DISABLE         (0x1 << 3)
+#define MXC_IIMHWV1_HANTRO_DISABLE      (0x1 << 2)
+#define MXC_IIMHWV1_MEMSTICK_DIS        (0x1 << 1)
+
+#define MXC_IIMHWV2_WLOCK               (0x1 << 7)
+#define MXC_IIMHWV2_BP_SDMA             (0x1 << 6)
+#define MXC_IIMHWV2_SCM_DCM             (0x1 << 5)
+
+#endif /* __ASM_ARCH_MXC_IIM_H__ */
diff --git a/arch/arm/mach-imx/imx25-dt.c b/arch/arm/mach-imx/imx25-dt.c
new file mode 100644
index 0000000..e17dfbc
--- /dev/null
+++ b/arch/arm/mach-imx/imx25-dt.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2012 Sascha Hauer, Pengutronix
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/irq.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include "common.h"
+#include "mx25.h"
+
+static void __init imx25_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static void __init imx25_timer_init(void)
+{
+	mx25_clocks_init_dt();
+}
+
+static struct sys_timer imx25_timer = {
+	.init = imx25_timer_init,
+};
+
+static const char * const imx25_dt_board_compat[] __initconst = {
+	"fsl,imx25",
+	NULL
+};
+
+DT_MACHINE_START(IMX25_DT, "Freescale i.MX25 (Device Tree Support)")
+	.map_io		= mx25_map_io,
+	.init_early	= imx25_init_early,
+	.init_irq	= mx25_init_irq,
+	.handle_irq	= imx25_handle_irq,
+	.timer		= &imx25_timer,
+	.init_machine	= imx25_dt_init,
+	.dt_compat	= imx25_dt_board_compat,
+	.restart	= mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c
index e80d523..ebfae96 100644
--- a/arch/arm/mach-imx/imx27-dt.c
+++ b/arch/arm/mach-imx/imx27-dt.c
@@ -14,21 +14,22 @@
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
-#include <mach/common.h>
-#include <mach/mx27.h>
+
+#include "common.h"
+#include "mx27.h"
 
 static const struct of_dev_auxdata imx27_auxdata_lookup[] __initconst = {
 	OF_DEV_AUXDATA("fsl,imx27-uart", MX27_UART1_BASE_ADDR, "imx21-uart.0", NULL),
 	OF_DEV_AUXDATA("fsl,imx27-uart", MX27_UART2_BASE_ADDR, "imx21-uart.1", NULL),
 	OF_DEV_AUXDATA("fsl,imx27-uart", MX27_UART3_BASE_ADDR, "imx21-uart.2", NULL),
 	OF_DEV_AUXDATA("fsl,imx27-fec", MX27_FEC_BASE_ADDR, "imx27-fec.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx27-i2c", MX27_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx27-i2c", MX27_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx27-i2c", MX27_I2C1_BASE_ADDR, "imx21-i2c.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx27-i2c", MX27_I2C2_BASE_ADDR, "imx21-i2c.1", NULL),
 	OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI1_BASE_ADDR, "imx27-cspi.0", NULL),
 	OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI2_BASE_ADDR, "imx27-cspi.1", NULL),
 	OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI3_BASE_ADDR, "imx27-cspi.2", NULL),
 	OF_DEV_AUXDATA("fsl,imx27-wdt", MX27_WDOG_BASE_ADDR, "imx2-wdt.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx27-nand", MX27_NFC_BASE_ADDR, "mxc_nand.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx27-nand", MX27_NFC_BASE_ADDR, "imx27-nand.0", NULL),
 	{ /* sentinel */ }
 };
 
diff --git a/arch/arm/mach-imx/imx31-dt.c b/arch/arm/mach-imx/imx31-dt.c
index a68ba20..af476de 100644
--- a/arch/arm/mach-imx/imx31-dt.c
+++ b/arch/arm/mach-imx/imx31-dt.c
@@ -14,8 +14,9 @@
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
-#include <mach/common.h>
-#include <mach/mx31.h>
+
+#include "common.h"
+#include "mx31.h"
 
 static const struct of_dev_auxdata imx31_auxdata_lookup[] __initconst = {
 	OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART1_BASE_ADDR,
diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/imx51-dt.c
index f233b4b..5ffa40c 100644
--- a/arch/arm/mach-imx/imx51-dt.c
+++ b/arch/arm/mach-imx/imx51-dt.c
@@ -15,38 +15,13 @@
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
-#include <mach/common.h>
-#include <mach/mx51.h>
 
-/*
- * Lookup table for attaching a specific name and platform_data pointer to
- * devices as they get created by of_platform_populate().  Ideally this table
- * would not exist, but the current clock implementation depends on some devices
- * having a specific name.
- */
-static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
-	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx21-uart.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx21-uart.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx21-uart.2", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "imx27-fec.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx51.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx51.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx51.2", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx51.3", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-cspi", MX51_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-sdma", MX51_SDMA_BASE_ADDR, "imx35-sdma", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-wdt", MX51_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
-	{ /* sentinel */ }
-};
+#include "common.h"
+#include "mx51.h"
 
 static void __init imx51_dt_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     imx51_auxdata_lookup, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static void __init imx51_timer_init(void)
diff --git a/arch/arm/mach-imx/include/mach/dma-mx1-mx2.h b/arch/arm/mach-imx/include/mach/dma-mx1-mx2.h
deleted file mode 100644
index df5f522..0000000
--- a/arch/arm/mach-imx/include/mach/dma-mx1-mx2.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __MACH_DMA_MX1_MX2_H__
-#define __MACH_DMA_MX1_MX2_H__
-/*
- * Don't use this header in new code, it will go away when all users are
- * converted to mach/dma-v1.h
- */
-
-#include <mach/dma-v1.h>
-
-#endif /* ifndef __MACH_DMA_MX1_MX2_H__ */
diff --git a/arch/arm/mach-imx/iomux-imx31.c b/arch/arm/mach-imx/iomux-imx31.c
index 82bd440..cabefbc 100644
--- a/arch/arm/mach-imx/iomux-imx31.c
+++ b/arch/arm/mach-imx/iomux-imx31.c
@@ -22,8 +22,9 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx3.h>
+
+#include "hardware.h"
+#include "iomux-mx3.h"
 
 /*
  * IOMUX register (base) addresses
diff --git a/arch/arm/mach-imx/iomux-mx1.h b/arch/arm/mach-imx/iomux-mx1.h
new file mode 100644
index 0000000..95f4681
--- /dev/null
+++ b/arch/arm/mach-imx/iomux-mx1.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#ifndef __MACH_IOMUX_MX1_H__
+#define __MACH_IOMUX_MX1_H__
+
+#include "iomux-v1.h"
+
+#define PA0_AIN_SPI2_CLK	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 0)
+#define PA0_AF_ETMTRACESYNC	(GPIO_PORTA | GPIO_AF | 0)
+#define PA1_AOUT_SPI2_RXD	(GPIO_PORTA | GPIO_AOUT | GPIO_IN | 1)
+#define PA1_PF_TIN		(GPIO_PORTA | GPIO_PF | 1)
+#define PA2_PF_PWM0		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 2)
+#define PA3_PF_CSI_MCLK		(GPIO_PORTA | GPIO_PF | 3)
+#define PA4_PF_CSI_D0		(GPIO_PORTA | GPIO_PF | 4)
+#define PA5_PF_CSI_D1		(GPIO_PORTA | GPIO_PF | 5)
+#define PA6_PF_CSI_D2		(GPIO_PORTA | GPIO_PF | 6)
+#define PA7_PF_CSI_D3		(GPIO_PORTA | GPIO_PF | 7)
+#define PA8_PF_CSI_D4		(GPIO_PORTA | GPIO_PF | 8)
+#define PA9_PF_CSI_D5		(GPIO_PORTA | GPIO_PF | 9)
+#define PA10_PF_CSI_D6		(GPIO_PORTA | GPIO_PF | 10)
+#define PA11_PF_CSI_D7		(GPIO_PORTA | GPIO_PF | 11)
+#define PA12_PF_CSI_VSYNC	(GPIO_PORTA | GPIO_PF | 12)
+#define PA13_PF_CSI_HSYNC	(GPIO_PORTA | GPIO_PF | 13)
+#define PA14_PF_CSI_PIXCLK	(GPIO_PORTA | GPIO_PF | 14)
+#define PA15_PF_I2C_SDA		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 15)
+#define PA16_PF_I2C_SCL		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 16)
+#define PA17_AF_ETMTRACEPKT4	(GPIO_PORTA | GPIO_AF | 17)
+#define PA17_AIN_SPI2_SS	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 17)
+#define PA18_AF_ETMTRACEPKT5	(GPIO_PORTA | GPIO_AF | 18)
+#define PA19_AF_ETMTRACEPKT6	(GPIO_PORTA | GPIO_AF | 19)
+#define PA20_AF_ETMTRACEPKT7	(GPIO_PORTA | GPIO_AF | 20)
+#define PA21_PF_A0		(GPIO_PORTA | GPIO_PF | 21)
+#define PA22_PF_CS4		(GPIO_PORTA | GPIO_PF | 22)
+#define PA23_PF_CS5		(GPIO_PORTA | GPIO_PF | 23)
+#define PA24_PF_A16		(GPIO_PORTA | GPIO_PF | 24)
+#define PA24_AF_ETMTRACEPKT0	(GPIO_PORTA | GPIO_AF | 24)
+#define PA25_PF_A17		(GPIO_PORTA | GPIO_PF | 25)
+#define PA25_AF_ETMTRACEPKT1	(GPIO_PORTA | GPIO_AF | 25)
+#define PA26_PF_A18		(GPIO_PORTA | GPIO_PF | 26)
+#define PA26_AF_ETMTRACEPKT2	(GPIO_PORTA | GPIO_AF | 26)
+#define PA27_PF_A19		(GPIO_PORTA | GPIO_PF | 27)
+#define PA27_AF_ETMTRACEPKT3	(GPIO_PORTA | GPIO_AF | 27)
+#define PA28_PF_A20		(GPIO_PORTA | GPIO_PF | 28)
+#define PA28_AF_ETMPIPESTAT0	(GPIO_PORTA | GPIO_AF | 28)
+#define PA29_PF_A21		(GPIO_PORTA | GPIO_PF | 29)
+#define PA29_AF_ETMPIPESTAT1	(GPIO_PORTA | GPIO_AF | 29)
+#define PA30_PF_A22		(GPIO_PORTA | GPIO_PF | 30)
+#define PA30_AF_ETMPIPESTAT2	(GPIO_PORTA | GPIO_AF | 30)
+#define PA31_PF_A23		(GPIO_PORTA | GPIO_PF | 31)
+#define PA31_AF_ETMTRACECLK	(GPIO_PORTA | GPIO_AF | 31)
+#define PB8_PF_SD_DAT0		(GPIO_PORTB | GPIO_PF | GPIO_PUEN | 8)
+#define PB8_AF_MS_PIO		(GPIO_PORTB | GPIO_AF | 8)
+#define PB9_PF_SD_DAT1		(GPIO_PORTB | GPIO_PF | GPIO_PUEN | 9)
+#define PB9_AF_MS_PI1		(GPIO_PORTB | GPIO_AF | 9)
+#define PB10_PF_SD_DAT2		(GPIO_PORTB | GPIO_PF | GPIO_PUEN | 10)
+#define PB10_AF_MS_SCLKI	(GPIO_PORTB | GPIO_AF | 10)
+#define PB11_PF_SD_DAT3		(GPIO_PORTB | GPIO_PF | 11)
+#define PB11_AF_MS_SDIO		(GPIO_PORTB | GPIO_AF | 11)
+#define PB12_PF_SD_CLK		(GPIO_PORTB | GPIO_PF | 12)
+#define PB12_AF_MS_SCLK0	(GPIO_PORTB | GPIO_AF | 12)
+#define PB13_PF_SD_CMD		(GPIO_PORTB | GPIO_PF | GPIO_PUEN | 13)
+#define PB13_AF_MS_BS		(GPIO_PORTB | GPIO_AF | 13)
+#define PB14_AF_SSI_RXFS	(GPIO_PORTB | GPIO_AF | 14)
+#define PB15_AF_SSI_RXCLK	(GPIO_PORTB | GPIO_AF | 15)
+#define PB16_AF_SSI_RXDAT	(GPIO_PORTB | GPIO_AF | GPIO_IN | 16)
+#define PB17_AF_SSI_TXDAT	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 17)
+#define PB18_AF_SSI_TXFS	(GPIO_PORTB | GPIO_AF | 18)
+#define PB19_AF_SSI_TXCLK	(GPIO_PORTB | GPIO_AF | 19)
+#define PB20_PF_USBD_AFE	(GPIO_PORTB | GPIO_PF | 20)
+#define PB21_PF_USBD_OE		(GPIO_PORTB | GPIO_PF | 21)
+#define PB22_PF_USBD_RCV	(GPIO_PORTB | GPIO_PF | 22)
+#define PB23_PF_USBD_SUSPND	(GPIO_PORTB | GPIO_PF | 23)
+#define PB24_PF_USBD_VP		(GPIO_PORTB | GPIO_PF | 24)
+#define PB25_PF_USBD_VM		(GPIO_PORTB | GPIO_PF | 25)
+#define PB26_PF_USBD_VPO	(GPIO_PORTB | GPIO_PF | 26)
+#define PB27_PF_USBD_VMO	(GPIO_PORTB | GPIO_PF | 27)
+#define PB28_PF_UART2_CTS	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 28)
+#define PB29_PF_UART2_RTS	(GPIO_PORTB | GPIO_PF | GPIO_IN | 29)
+#define PB30_PF_UART2_TXD	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 30)
+#define PB31_PF_UART2_RXD	(GPIO_PORTB | GPIO_PF | GPIO_IN | 31)
+#define PC3_PF_SSI_RXFS		(GPIO_PORTC | GPIO_PF | 3)
+#define PC4_PF_SSI_RXCLK	(GPIO_PORTC | GPIO_PF | 4)
+#define PC5_PF_SSI_RXDAT	(GPIO_PORTC | GPIO_PF | GPIO_IN | 5)
+#define PC6_PF_SSI_TXDAT	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 6)
+#define PC7_PF_SSI_TXFS		(GPIO_PORTC | GPIO_PF | 7)
+#define PC8_PF_SSI_TXCLK	(GPIO_PORTC | GPIO_PF | 8)
+#define PC9_PF_UART1_CTS	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 9)
+#define PC10_PF_UART1_RTS	(GPIO_PORTC | GPIO_PF | GPIO_IN | 10)
+#define PC11_PF_UART1_TXD	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 11)
+#define PC12_PF_UART1_RXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 12)
+#define PC13_PF_SPI1_SPI_RDY	(GPIO_PORTC | GPIO_PF | 13)
+#define PC14_PF_SPI1_SCLK	(GPIO_PORTC | GPIO_PF | 14)
+#define PC15_PF_SPI1_SS		(GPIO_PORTC | GPIO_PF | 15)
+#define PC16_PF_SPI1_MISO	(GPIO_PORTC | GPIO_PF | 16)
+#define PC17_PF_SPI1_MOSI	(GPIO_PORTC | GPIO_PF | 17)
+#define PC24_BIN_UART3_RI	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 24)
+#define PC25_BIN_UART3_DSR	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 25)
+#define PC26_AOUT_UART3_DTR	(GPIO_PORTC | GPIO_AOUT | GPIO_IN | 26)
+#define PC27_BIN_UART3_DCD	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 27)
+#define PC28_BIN_UART3_CTS	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 28)
+#define PC29_AOUT_UART3_RTS	(GPIO_PORTC | GPIO_AOUT | GPIO_IN | 29)
+#define PC30_BIN_UART3_TX	(GPIO_PORTC | GPIO_BIN | 30)
+#define PC31_AOUT_UART3_RX	(GPIO_PORTC | GPIO_AOUT | GPIO_IN | 31)
+#define PD6_PF_LSCLK		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 6)
+#define PD7_PF_REV		(GPIO_PORTD | GPIO_PF | 7)
+#define PD7_AF_UART2_DTR	(GPIO_PORTD | GPIO_AF | GPIO_IN | 7)
+#define PD7_AIN_SPI2_SCLK	(GPIO_PORTD | GPIO_AIN | 7)
+#define PD8_PF_CLS		(GPIO_PORTD | GPIO_PF | 8)
+#define PD8_AF_UART2_DCD	(GPIO_PORTD | GPIO_AF | GPIO_OUT | 8)
+#define PD8_AIN_SPI2_SS		(GPIO_PORTD | GPIO_AIN | 8)
+#define PD9_PF_PS		(GPIO_PORTD | GPIO_PF | 9)
+#define PD9_AF_UART2_RI		(GPIO_PORTD | GPIO_AF | GPIO_OUT | 9)
+#define PD9_AOUT_SPI2_RXD	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 9)
+#define PD10_PF_SPL_SPR		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 10)
+#define PD10_AF_UART2_DSR	(GPIO_PORTD | GPIO_AF | GPIO_OUT | 10)
+#define PD10_AIN_SPI2_TXD	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 10)
+#define PD11_PF_CONTRAST	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 11)
+#define PD12_PF_ACD_OE		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 12)
+#define PD13_PF_LP_HSYNC	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 13)
+#define PD14_PF_FLM_VSYNC	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 14)
+#define PD15_PF_LD0		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 15)
+#define PD16_PF_LD1		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 16)
+#define PD17_PF_LD2		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 17)
+#define PD18_PF_LD3		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 18)
+#define PD19_PF_LD4		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 19)
+#define PD20_PF_LD5		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 20)
+#define PD21_PF_LD6		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 21)
+#define PD22_PF_LD7		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 22)
+#define PD23_PF_LD8		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 23)
+#define PD24_PF_LD9		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 24)
+#define PD25_PF_LD10		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 25)
+#define PD26_PF_LD11		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 26)
+#define PD27_PF_LD12		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 27)
+#define PD28_PF_LD13		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 28)
+#define PD29_PF_LD14		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 29)
+#define PD30_PF_LD15		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 30)
+#define PD31_PF_TMR2OUT		(GPIO_PORTD | GPIO_PF | 31)
+#define PD31_BIN_SPI2_TXD	(GPIO_PORTD | GPIO_BIN | 31)
+
+#endif /* ifndef __MACH_IOMUX_MX1_H__ */
diff --git a/arch/arm/mach-imx/iomux-mx21.h b/arch/arm/mach-imx/iomux-mx21.h
new file mode 100644
index 0000000..a70cffc
--- /dev/null
+++ b/arch/arm/mach-imx/iomux-mx21.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#ifndef __MACH_IOMUX_MX21_H__
+#define __MACH_IOMUX_MX21_H__
+
+#include "iomux-mx2x.h"
+#include "iomux-v1.h"
+
+/* Primary GPIO pin functions */
+
+#define PB22_PF_USBH1_BYP	(GPIO_PORTB | GPIO_PF | 22)
+#define PB25_PF_USBH1_ON	(GPIO_PORTB | GPIO_PF | 25)
+#define PC5_PF_USBOTG_SDA	(GPIO_PORTC | GPIO_PF | 5)
+#define PC6_PF_USBOTG_SCL	(GPIO_PORTC | GPIO_PF | 6)
+#define PC7_PF_USBOTG_ON	(GPIO_PORTC | GPIO_PF | 7)
+#define PC8_PF_USBOTG_FS	(GPIO_PORTC | GPIO_PF | 8)
+#define PC9_PF_USBOTG_OE	(GPIO_PORTC | GPIO_PF | 9)
+#define PC10_PF_USBOTG_TXDM	(GPIO_PORTC | GPIO_PF | 10)
+#define PC11_PF_USBOTG_TXDP	(GPIO_PORTC | GPIO_PF | 11)
+#define PC12_PF_USBOTG_RXDM	(GPIO_PORTC | GPIO_PF | 12)
+#define PC13_PF_USBOTG_RXDP	(GPIO_PORTC | GPIO_PF | 13)
+#define PC16_PF_SAP_FS		(GPIO_PORTC | GPIO_PF | 16)
+#define PC17_PF_SAP_RXD		(GPIO_PORTC | GPIO_PF | 17)
+#define PC18_PF_SAP_TXD		(GPIO_PORTC | GPIO_PF | 18)
+#define PC19_PF_SAP_CLK		(GPIO_PORTC | GPIO_PF | 19)
+#define PE0_PF_TEST_WB2		(GPIO_PORTE | GPIO_PF | 0)
+#define PE1_PF_TEST_WB1		(GPIO_PORTE | GPIO_PF | 1)
+#define PE2_PF_TEST_WB0		(GPIO_PORTE | GPIO_PF | 2)
+#define PF1_PF_NFCE		(GPIO_PORTF | GPIO_PF | 1)
+#define PF3_PF_NFCLE		(GPIO_PORTF | GPIO_PF | 3)
+#define PF7_PF_NFIO0		(GPIO_PORTF | GPIO_PF | 7)
+#define PF8_PF_NFIO1		(GPIO_PORTF | GPIO_PF | 8)
+#define PF9_PF_NFIO2		(GPIO_PORTF | GPIO_PF | 9)
+#define PF10_PF_NFIO3		(GPIO_PORTF | GPIO_PF | 10)
+#define PF11_PF_NFIO4		(GPIO_PORTF | GPIO_PF | 11)
+#define PF12_PF_NFIO5		(GPIO_PORTF | GPIO_PF | 12)
+#define PF13_PF_NFIO6		(GPIO_PORTF | GPIO_PF | 13)
+#define PF14_PF_NFIO7		(GPIO_PORTF | GPIO_PF | 14)
+#define PF16_PF_RES		(GPIO_PORTF | GPIO_PF | 16)
+
+/* Alternate GPIO pin functions */
+
+#define PA5_AF_BMI_CLK_CS	(GPIO_PORTA | GPIO_AF | 5)
+#define PA6_AF_BMI_D0		(GPIO_PORTA | GPIO_AF | 6)
+#define PA7_AF_BMI_D1		(GPIO_PORTA | GPIO_AF | 7)
+#define PA8_AF_BMI_D2		(GPIO_PORTA | GPIO_AF | 8)
+#define PA9_AF_BMI_D3		(GPIO_PORTA | GPIO_AF | 9)
+#define PA10_AF_BMI_D4		(GPIO_PORTA | GPIO_AF | 10)
+#define PA11_AF_BMI_D5		(GPIO_PORTA | GPIO_AF | 11)
+#define PA12_AF_BMI_D6		(GPIO_PORTA | GPIO_AF | 12)
+#define PA13_AF_BMI_D7		(GPIO_PORTA | GPIO_AF | 13)
+#define PA14_AF_BMI_D8		(GPIO_PORTA | GPIO_AF | 14)
+#define PA15_AF_BMI_D9		(GPIO_PORTA | GPIO_AF | 15)
+#define PA16_AF_BMI_D10		(GPIO_PORTA | GPIO_AF | 16)
+#define PA17_AF_BMI_D11		(GPIO_PORTA | GPIO_AF | 17)
+#define PA18_AF_BMI_D12		(GPIO_PORTA | GPIO_AF | 18)
+#define PA19_AF_BMI_D13		(GPIO_PORTA | GPIO_AF | 19)
+#define PA20_AF_BMI_D14		(GPIO_PORTA | GPIO_AF | 20)
+#define PA21_AF_BMI_D15		(GPIO_PORTA | GPIO_AF | 21)
+#define PA22_AF_BMI_READ_REQ	(GPIO_PORTA | GPIO_AF | 22)
+#define PA23_AF_BMI_WRITE	(GPIO_PORTA | GPIO_AF | 23)
+#define PA29_AF_BMI_RX_FULL	(GPIO_PORTA | GPIO_AF | 29)
+#define PA30_AF_BMI_READ	(GPIO_PORTA | GPIO_AF | 30)
+
+/* AIN GPIO pin functions */
+
+#define PC14_AIN_SYS_CLK	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 14)
+#define PD21_AIN_USBH2_FS	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 21)
+#define PD22_AIN_USBH2_OE	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 22)
+#define PD23_AIN_USBH2_TXDM	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 23)
+#define PD24_AIN_USBH2_TXDP	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 24)
+#define PE8_AIN_IR_TXD		(GPIO_PORTE | GPIO_AIN | GPIO_OUT | 8)
+#define PF0_AIN_PC_RST		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 0)
+#define PF1_AIN_PC_CE1		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 1)
+#define PF2_AIN_PC_CE2		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 2)
+#define PF3_AIN_PC_POE		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 3)
+#define PF4_AIN_PC_OE		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 4)
+#define PF5_AIN_PC_RW		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 5)
+
+/* BIN GPIO pin functions */
+
+#define PC14_BIN_SYS_CLK	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 14)
+#define PD27_BIN_EXT_DMA_GRANT	(GPIO_PORTD | GPIO_BIN | GPIO_OUT | 27)
+
+/* CIN GPIO pin functions */
+
+#define PB26_CIN_USBH1_RXDAT	(GPIO_PORTB | GPIO_CIN | GPIO_OUT | 26)
+
+/* AOUT GPIO pin functions */
+
+#define PA29_AOUT_BMI_WAIT	(GPIO_PORTA | GPIO_AOUT | GPIO_IN | 29)
+#define PD19_AOUT_USBH2_RXDM	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 19)
+#define PD20_AOUT_USBH2_RXDP	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 20)
+#define PD25_AOUT_EXT_DMAREQ	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 25)
+#define PD26_AOUT_USBOTG_RXDAT	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 26)
+#define PE9_AOUT_IR_RXD		(GPIO_PORTE | GPIO_AOUT | GPIO_IN | 9)
+#define PF6_AOUT_PC_BVD2	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 6)
+#define PF7_AOUT_PC_BVD1	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 7)
+#define PF8_AOUT_PC_VS2		(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 8)
+#define PF9_AOUT_PC_VS1		(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 9)
+#define PF10_AOUT_PC_WP		(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 10)
+#define PF11_AOUT_PC_READY	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 11)
+#define PF12_AOUT_PC_WAIT	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 12)
+#define PF13_AOUT_PC_CD2	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 13)
+#define PF14_AOUT_PC_CD1	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 14)
+
+#endif /* ifndef __MACH_IOMUX_MX21_H__ */
diff --git a/arch/arm/mach-imx/iomux-mx25.h b/arch/arm/mach-imx/iomux-mx25.h
new file mode 100644
index 0000000..be51e83
--- /dev/null
+++ b/arch/arm/mach-imx/iomux-mx25.h
@@ -0,0 +1,524 @@
+/*
+ * arch/arm/plat-mxc/include/mach/iomux-mx25.h
+ *
+ * Copyright (C) 2009 by Lothar Wassmann <LW@KARO-electronics.de>
+ *
+ * based on arch/arm/mach-mx25/mx25_pins.h
+ *    Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * and
+ * arch/arm/plat-mxc/include/mach/iomux-mx35.h
+ *    Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH <armlinux@phytec.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __MACH_IOMUX_MX25_H__
+#define __MACH_IOMUX_MX25_H__
+
+#include "iomux-v3.h"
+
+/*
+ * IOMUX/PAD Bit field definitions
+ */
+
+#define MX25_PAD_A10__A10		IOMUX_PAD(0x000, 0x008, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A10__GPIO_4_0		IOMUX_PAD(0x000, 0x008, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_A13__A13		IOMUX_PAD(0x22C, 0x00c, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A13__GPIO_4_1		IOMUX_PAD(0x22C, 0x00c, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_A14__A14		IOMUX_PAD(0x230, 0x010, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A14__GPIO_2_0		IOMUX_PAD(0x230, 0x010, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_A15__A15		IOMUX_PAD(0x234, 0x014, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A15__GPIO_2_1		IOMUX_PAD(0x234, 0x014, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_A16__A16		IOMUX_PAD(0x000, 0x018, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A16__GPIO_2_2		IOMUX_PAD(0x000, 0x018, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_A17__A17		IOMUX_PAD(0x238, 0x01c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A17__GPIO_2_3		IOMUX_PAD(0x238, 0x01c, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_A18__A18		IOMUX_PAD(0x23c, 0x020, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A18__GPIO_2_4		IOMUX_PAD(0x23c, 0x020, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A18__FEC_COL		IOMUX_PAD(0x23c, 0x020, 0x17, 0x504, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_A19__A19		IOMUX_PAD(0x240, 0x024, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A19__FEC_RX_ER		IOMUX_PAD(0x240, 0x024, 0x17, 0x518, 0, NO_PAD_CTRL)
+#define MX25_PAD_A19__GPIO_2_5		IOMUX_PAD(0x240, 0x024, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_A20__A20		IOMUX_PAD(0x244, 0x028, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A20__GPIO_2_6		IOMUX_PAD(0x244, 0x028, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A20__FEC_RDATA2	IOMUX_PAD(0x244, 0x028, 0x17, 0x50c, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_A21__A21		IOMUX_PAD(0x248, 0x02c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A21__GPIO_2_7		IOMUX_PAD(0x248, 0x02c, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A21__FEC_RDATA3	IOMUX_PAD(0x248, 0x02c, 0x17, 0x510, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_A22__A22		IOMUX_PAD(0x000, 0x030, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A22__GPIO_2_8		IOMUX_PAD(0x000, 0x030, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_A23__A23		IOMUX_PAD(0x24c, 0x034, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A23__GPIO_2_9		IOMUX_PAD(0x24c, 0x034, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_A24__A24		IOMUX_PAD(0x250, 0x038, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A24__GPIO_2_10		IOMUX_PAD(0x250, 0x038, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A24__FEC_RX_CLK	IOMUX_PAD(0x250, 0x038, 0x17, 0x514, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_A25__A25		IOMUX_PAD(0x254, 0x03c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A25__GPIO_2_11		IOMUX_PAD(0x254, 0x03c, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A25__FEC_CRS		IOMUX_PAD(0x254, 0x03c, 0x17, 0x508, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_EB0__EB0		IOMUX_PAD(0x258, 0x040, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_EB0__AUD4_TXD		IOMUX_PAD(0x258, 0x040, 0x14, 0x464, 0, NO_PAD_CTRL)
+#define MX25_PAD_EB0__GPIO_2_12		IOMUX_PAD(0x258, 0x040, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_EB1__EB1		IOMUX_PAD(0x25c, 0x044, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_EB1__AUD4_RXD		IOMUX_PAD(0x25c, 0x044, 0x14, 0x460, 0, NO_PAD_CTRL)
+#define MX25_PAD_EB1__GPIO_2_13		IOMUX_PAD(0x25c, 0x044, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_OE__OE			IOMUX_PAD(0x260, 0x048, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_OE__AUD4_TXC		IOMUX_PAD(0x260, 0x048, 0x14, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_OE__GPIO_2_14		IOMUX_PAD(0x260, 0x048, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CS0__CS0		IOMUX_PAD(0x000, 0x04c, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CS0__GPIO_4_2		IOMUX_PAD(0x000, 0x04c, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CS1__CS1		IOMUX_PAD(0x000, 0x050, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CS1__NF_CE3		IOMUX_PAD(0x000, 0x050, 0x01, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CS1__GPIO_4_3		IOMUX_PAD(0x000, 0x050, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CS4__CS4		IOMUX_PAD(0x264, 0x054, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CS4__NF_CE1		IOMUX_PAD(0x264, 0x054, 0x01, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CS4__UART5_CTS		IOMUX_PAD(0x264, 0x054, 0x13, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CS4__GPIO_3_20		IOMUX_PAD(0x264, 0x054, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CS5__CS5		IOMUX_PAD(0x268, 0x058, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CS5__NF_CE2		IOMUX_PAD(0x268, 0x058, 0x01, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CS5__UART5_RTS		IOMUX_PAD(0x268, 0x058, 0x13, 0x574, 0, NO_PAD_CTRL)
+#define MX25_PAD_CS5__GPIO_3_21		IOMUX_PAD(0x268, 0x058, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_NF_CE0__NF_CE0		IOMUX_PAD(0x26c, 0x05c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_NF_CE0__GPIO_3_22	IOMUX_PAD(0x26c, 0x05c, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_ECB__ECB		IOMUX_PAD(0x270, 0x060, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_ECB__UART5_TXD_MUX	IOMUX_PAD(0x270, 0x060, 0x13, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_ECB__GPIO_3_23		IOMUX_PAD(0x270, 0x060, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_LBA__LBA		IOMUX_PAD(0x274, 0x064, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_LBA__UART5_RXD_MUX	IOMUX_PAD(0x274, 0x064, 0x13, 0x578, 0, NO_PAD_CTRL)
+#define MX25_PAD_LBA__GPIO_3_24		IOMUX_PAD(0x274, 0x064, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_BCLK__BCLK		IOMUX_PAD(0x000, 0x068, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_BCLK__GPIO_4_4		IOMUX_PAD(0x000, 0x068, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_RW__RW			IOMUX_PAD(0x278, 0x06c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_RW__AUD4_TXFS		IOMUX_PAD(0x278, 0x06c, 0x14, 0x474, 0, NO_PAD_CTRL)
+#define MX25_PAD_RW__GPIO_3_25		IOMUX_PAD(0x278, 0x06c, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_NFWE_B__NFWE_B		IOMUX_PAD(0x000, 0x070, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_NFWE_B__GPIO_3_26	IOMUX_PAD(0x000, 0x070, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_NFRE_B__NFRE_B		IOMUX_PAD(0x000, 0x074, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_NFRE_B__GPIO_3_27	IOMUX_PAD(0x000, 0x074, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_NFALE__NFALE		IOMUX_PAD(0x000, 0x078, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_NFALE__GPIO_3_28	IOMUX_PAD(0x000, 0x078, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_NFCLE__NFCLE		IOMUX_PAD(0x000, 0x07c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_NFCLE__GPIO_3_29	IOMUX_PAD(0x000, 0x07c, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_NFWP_B__NFWP_B		IOMUX_PAD(0x000, 0x080, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_NFWP_B__GPIO_3_30	IOMUX_PAD(0x000, 0x080, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_NFRB__NFRB		IOMUX_PAD(0x27c, 0x084, 0x10, 0, 0, PAD_CTL_PKE)
+#define MX25_PAD_NFRB__GPIO_3_31	IOMUX_PAD(0x27c, 0x084, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_D15__D15		IOMUX_PAD(0x280, 0x088, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D15__LD16		IOMUX_PAD(0x280, 0x088, 0x01, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_D15__GPIO_4_5		IOMUX_PAD(0x280, 0x088, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_D14__D14		IOMUX_PAD(0x284, 0x08c, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D14__LD17		IOMUX_PAD(0x284, 0x08c, 0x01, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_D14__GPIO_4_6		IOMUX_PAD(0x284, 0x08c, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_D13__D13		IOMUX_PAD(0x288, 0x090, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D13__LD18		IOMUX_PAD(0x288, 0x090, 0x01, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_D13__GPIO_4_7		IOMUX_PAD(0x288, 0x090, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_D12__D12		IOMUX_PAD(0x28c, 0x094, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D12__GPIO_4_8		IOMUX_PAD(0x28c, 0x094, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_D11__D11		IOMUX_PAD(0x290, 0x098, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D11__GPIO_4_9		IOMUX_PAD(0x290, 0x098, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_D10__D10		IOMUX_PAD(0x294, 0x09c, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D10__GPIO_4_10		IOMUX_PAD(0x294, 0x09c, 0x05, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D10__USBOTG_OC		IOMUX_PAD(0x294, 0x09c, 0x06, 0x57c, 0, PAD_CTL_PUS_100K_UP)
+
+#define MX25_PAD_D9__D9			IOMUX_PAD(0x298, 0x0a0, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D9__GPIO_4_11		IOMUX_PAD(0x298, 0x0a0, 0x05, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D9__USBH2_PWR		IOMUX_PAD(0x298, 0x0a0, 0x06, 0, 0, PAD_CTL_PKE)
+
+#define MX25_PAD_D8__D8			IOMUX_PAD(0x29c, 0x0a4, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D8__GPIO_4_12		IOMUX_PAD(0x29c, 0x0a4, 0x05, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D8__USBH2_OC		IOMUX_PAD(0x29c, 0x0a4, 0x06, 0x580, 0, PAD_CTL_PUS_100K_UP)
+
+#define MX25_PAD_D7__D7			IOMUX_PAD(0x2a0, 0x0a8, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D7__GPIO_4_13		IOMUX_PAD(0x2a0, 0x0a8, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_D6__D6			IOMUX_PAD(0x2a4, 0x0ac, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D6__GPIO_4_14		IOMUX_PAD(0x2a4, 0x0ac, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_D5__D5			IOMUX_PAD(0x2a8, 0x0b0, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D5__GPIO_4_15		IOMUX_PAD(0x2a8, 0x0b0, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_D4__D4			IOMUX_PAD(0x2ac, 0x0b4, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D4__GPIO_4_16		IOMUX_PAD(0x2ac, 0x0b4, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_D3__D3			IOMUX_PAD(0x2b0, 0x0b8, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D3__GPIO_4_17		IOMUX_PAD(0x2b0, 0x0b8, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_D2__D2			IOMUX_PAD(0x2b4, 0x0bc, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D2__GPIO_4_18		IOMUX_PAD(0x2b4, 0x0bc, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_D1__D1			IOMUX_PAD(0x2b8, 0x0c0, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D1__GPIO_4_19		IOMUX_PAD(0x2b8, 0x0c0, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_D0__D0			IOMUX_PAD(0x2bc, 0x0c4, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_D0__GPIO_4_20		IOMUX_PAD(0x2bc, 0x0c4, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_LD0__LD0		IOMUX_PAD(0x2c0, 0x0c8, 0x10, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_LD0__CSI_D0		IOMUX_PAD(0x2c0, 0x0c8, 0x12, 0x488, 0, NO_PAD_CTRL)
+#define MX25_PAD_LD0__GPIO_2_15		IOMUX_PAD(0x2c0, 0x0c8, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_LD1__LD1		IOMUX_PAD(0x2c4, 0x0cc, 0x10, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_LD1__CSI_D1		IOMUX_PAD(0x2c4, 0x0cc, 0x12, 0x48c, 0, NO_PAD_CTRL)
+#define MX25_PAD_LD1__GPIO_2_16		IOMUX_PAD(0x2c4, 0x0cc, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_LD2__LD2		IOMUX_PAD(0x2c8, 0x0d0, 0x10, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_LD2__GPIO_2_17		IOMUX_PAD(0x2c8, 0x0d0, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_LD3__LD3		IOMUX_PAD(0x2cc, 0x0d4, 0x10, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_LD3__GPIO_2_18		IOMUX_PAD(0x2cc, 0x0d4, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_LD4__LD4		IOMUX_PAD(0x2d0, 0x0d8, 0x10, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_LD4__GPIO_2_19		IOMUX_PAD(0x2d0, 0x0d8, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_LD5__LD5		IOMUX_PAD(0x2d4, 0x0dc, 0x10, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_LD5__GPIO_1_19		IOMUX_PAD(0x2d4, 0x0dc, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_LD6__LD6		IOMUX_PAD(0x2d8, 0x0e0, 0x10, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_LD6__GPIO_1_20		IOMUX_PAD(0x2d8, 0x0e0, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_LD7__LD7		IOMUX_PAD(0x2dc, 0x0e4, 0x10, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_LD7__GPIO_1_21		IOMUX_PAD(0x2dc, 0x0e4, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_LD8__LD8		IOMUX_PAD(0x2e0, 0x0e8, 0x10, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_LD8__FEC_TX_ERR	IOMUX_PAD(0x2e0, 0x0e8, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_LD9__LD9		IOMUX_PAD(0x2e4, 0x0ec, 0x10, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_LD9__FEC_COL		IOMUX_PAD(0x2e4, 0x0ec, 0x15, 0x504, 1, NO_PAD_CTRL)
+
+#define MX25_PAD_LD10__LD10		IOMUX_PAD(0x2e8, 0x0f0, 0x10, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_LD10__FEC_RX_ER	IOMUX_PAD(0x2e8, 0x0f0, 0x15, 0x518, 1, NO_PAD_CTRL)
+
+#define MX25_PAD_LD11__LD11		IOMUX_PAD(0x2ec, 0x0f4, 0x10, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_LD11__FEC_RDATA2	IOMUX_PAD(0x2ec, 0x0f4, 0x15, 0x50c, 1, NO_PAD_CTRL)
+
+#define MX25_PAD_LD12__LD12		IOMUX_PAD(0x2f0, 0x0f8, 0x10, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_LD12__FEC_RDATA3	IOMUX_PAD(0x2f0, 0x0f8, 0x15, 0x510, 1, NO_PAD_CTRL)
+
+#define MX25_PAD_LD13__LD13		IOMUX_PAD(0x2f4, 0x0fc, 0x10, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_LD13__FEC_TDATA2	IOMUX_PAD(0x2f4, 0x0fc, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_LD14__LD14		IOMUX_PAD(0x2f8, 0x100, 0x10, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_LD14__FEC_TDATA3	IOMUX_PAD(0x2f8, 0x100, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_LD15__LD15		IOMUX_PAD(0x2fc, 0x104, 0x10, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_LD15__FEC_RX_CLK	IOMUX_PAD(0x2fc, 0x104, 0x15, 0x514, 1, NO_PAD_CTRL)
+
+#define MX25_PAD_HSYNC__HSYNC		IOMUX_PAD(0x300, 0x108, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_HSYNC__GPIO_1_22	IOMUX_PAD(0x300, 0x108, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_VSYNC__VSYNC		IOMUX_PAD(0x304, 0x10c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_VSYNC__GPIO_1_23	IOMUX_PAD(0x304, 0x10c, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_LSCLK__LSCLK		IOMUX_PAD(0x308, 0x110, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_LSCLK__GPIO_1_24	IOMUX_PAD(0x308, 0x110, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_OE_ACD__OE_ACD		IOMUX_PAD(0x30c, 0x114, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_OE_ACD__GPIO_1_25	IOMUX_PAD(0x30c, 0x114, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CONTRAST__CONTRAST	IOMUX_PAD(0x310, 0x118, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CONTRAST__PWM4_PWMO	IOMUX_PAD(0x310, 0x118, 0x14, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CONTRAST__FEC_CRS	IOMUX_PAD(0x310, 0x118, 0x15, 0x508, 1, NO_PAD_CTRL)
+
+#define MX25_PAD_PWM__PWM		IOMUX_PAD(0x314, 0x11c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_PWM__GPIO_1_26		IOMUX_PAD(0x314, 0x11c, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_PWM__USBH2_OC		IOMUX_PAD(0x314, 0x11c, 0x16, 0x580, 1, PAD_CTL_PUS_100K_UP)
+
+#define MX25_PAD_CSI_D2__CSI_D2		IOMUX_PAD(0x318, 0x120, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSI_D2__UART5_RXD_MUX	IOMUX_PAD(0x318, 0x120, 0x11, 0x578, 1, NO_PAD_CTRL)
+#define MX25_PAD_CSI_D2__GPIO_1_27	IOMUX_PAD(0x318, 0x120, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSI_D2__CSPI3_MOSI	IOMUX_PAD(0x318, 0x120, 0x17, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CSI_D3__CSI_D3		IOMUX_PAD(0x31c, 0x124, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSI_D3__GPIO_1_28	IOMUX_PAD(0x31c, 0x124, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSI_D3__CSPI3_MISO	IOMUX_PAD(0x31c, 0x124, 0x17, 0x4b4, 1, NO_PAD_CTRL)
+
+#define MX25_PAD_CSI_D4__CSI_D4		IOMUX_PAD(0x320, 0x128, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSI_D4__UART5_RTS	IOMUX_PAD(0x320, 0x128, 0x11, 0x574, 1, NO_PAD_CTRL)
+#define MX25_PAD_CSI_D4__GPIO_1_29	IOMUX_PAD(0x320, 0x128, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSI_D4__CSPI3_SCLK	IOMUX_PAD(0x320, 0x128, 0x17, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CSI_D5__CSI_D5		IOMUX_PAD(0x324, 0x12c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSI_D5__GPIO_1_30	IOMUX_PAD(0x324, 0x12c, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSI_D5__CSPI3_RDY	IOMUX_PAD(0x324, 0x12c, 0x17, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CSI_D6__CSI_D6		IOMUX_PAD(0x328, 0x130, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSI_D6__GPIO_1_31	IOMUX_PAD(0x328, 0x130, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CSI_D7__CSI_D7		IOMUX_PAD(0x32c, 0x134, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSI_D7__GPIO_1_6	IOMUX_PAD(0x32c, 0x134, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CSI_D8__CSI_D8		IOMUX_PAD(0x330, 0x138, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSI_D8__GPIO_1_7	IOMUX_PAD(0x330, 0x138, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CSI_D9__CSI_D9		IOMUX_PAD(0x334, 0x13c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSI_D9__GPIO_4_21	IOMUX_PAD(0x334, 0x13c, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CSI_MCLK__CSI_MCLK	IOMUX_PAD(0x338, 0x140, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSI_MCLK__GPIO_1_8	IOMUX_PAD(0x338, 0x140, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CSI_VSYNC__CSI_VSYNC	IOMUX_PAD(0x33c, 0x144, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSI_VSYNC__GPIO_1_9	IOMUX_PAD(0x33c, 0x144, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CSI_HSYNC__CSI_HSYNC	IOMUX_PAD(0x340, 0x148, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSI_HSYNC__GPIO_1_10	IOMUX_PAD(0x340, 0x148, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CSI_PIXCLK__CSI_PIXCLK	IOMUX_PAD(0x344, 0x14c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSI_PIXCLK__GPIO_1_11	IOMUX_PAD(0x344, 0x14c, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_I2C1_CLK__I2C1_CLK	IOMUX_PAD(0x348, 0x150, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_I2C1_CLK__GPIO_1_12	IOMUX_PAD(0x348, 0x150, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_I2C1_DAT__I2C1_DAT	IOMUX_PAD(0x34c, 0x154, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_I2C1_DAT__GPIO_1_13	IOMUX_PAD(0x34c, 0x154, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CSPI1_MOSI__CSPI1_MOSI	IOMUX_PAD(0x350, 0x158, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSPI1_MOSI__GPIO_1_14	IOMUX_PAD(0x350, 0x158, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CSPI1_MISO__CSPI1_MISO	IOMUX_PAD(0x354, 0x15c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSPI1_MISO__GPIO_1_15	IOMUX_PAD(0x354, 0x15c, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CSPI1_SS0__CSPI1_SS0	IOMUX_PAD(0x358, 0x160, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSPI1_SS0__GPIO_1_16	IOMUX_PAD(0x358, 0x160, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CSPI1_SS1__CSPI1_SS1	IOMUX_PAD(0x35c, 0x164, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSPI1_SS1__GPIO_1_17	IOMUX_PAD(0x35c, 0x164, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CSPI1_SCLK__CSPI1_SCLK	IOMUX_PAD(0x360, 0x168, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CSPI1_SCLK__GPIO_1_18	IOMUX_PAD(0x360, 0x168, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CSPI1_RDY__CSPI1_RDY	IOMUX_PAD(0x364, 0x16c, 0x10, 0, 0, PAD_CTL_PKE)
+#define MX25_PAD_CSPI1_RDY__GPIO_2_22	IOMUX_PAD(0x364, 0x16c, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_UART1_RXD__UART1_RXD	IOMUX_PAD(0x368, 0x170, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN)
+#define MX25_PAD_UART1_RXD__GPIO_4_22	IOMUX_PAD(0x368, 0x170, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_UART1_TXD__UART1_TXD	IOMUX_PAD(0x36c, 0x174, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_UART1_TXD__GPIO_4_23	IOMUX_PAD(0x36c, 0x174, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_UART1_RTS__UART1_RTS	IOMUX_PAD(0x370, 0x178, 0x10, 0, 0, PAD_CTL_PUS_100K_UP)
+#define MX25_PAD_UART1_RTS__CSI_D0	IOMUX_PAD(0x370, 0x178, 0x11, 0x488, 1, NO_PAD_CTRL)
+#define MX25_PAD_UART1_RTS__GPIO_4_24	IOMUX_PAD(0x370, 0x178, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_UART1_CTS__UART1_CTS	IOMUX_PAD(0x374, 0x17c, 0x10, 0, 0, PAD_CTL_PUS_100K_UP)
+#define MX25_PAD_UART1_CTS__CSI_D1	IOMUX_PAD(0x374, 0x17c, 0x11, 0x48c, 1, NO_PAD_CTRL)
+#define MX25_PAD_UART1_CTS__GPIO_4_25	IOMUX_PAD(0x374, 0x17c, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_UART2_RXD__UART2_RXD	IOMUX_PAD(0x378, 0x180, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_UART2_RXD__GPIO_4_26	IOMUX_PAD(0x378, 0x180, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_UART2_TXD__UART2_TXD	IOMUX_PAD(0x37c, 0x184, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_UART2_TXD__GPIO_4_27	IOMUX_PAD(0x37c, 0x184, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_UART2_RTS__UART2_RTS	IOMUX_PAD(0x380, 0x188, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_UART2_RTS__FEC_COL	IOMUX_PAD(0x380, 0x188, 0x12, 0x504, 2, NO_PAD_CTRL)
+#define MX25_PAD_UART2_RTS__GPIO_4_28	IOMUX_PAD(0x380, 0x188, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_UART2_CTS__FEC_RX_ER	IOMUX_PAD(0x384, 0x18c, 0x12, 0x518, 2, NO_PAD_CTRL)
+#define MX25_PAD_UART2_CTS__UART2_CTS	IOMUX_PAD(0x384, 0x18c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_UART2_CTS__GPIO_4_29	IOMUX_PAD(0x384, 0x18c, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_SD1_CMD__SD1_CMD	IOMUX_PAD(0x388, 0x190, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
+#define MX25_PAD_SD1_CMD__FEC_RDATA2	IOMUX_PAD(0x388, 0x190, 0x12, 0x50c, 2, NO_PAD_CTRL)
+#define MX25_PAD_SD1_CMD__GPIO_2_23	IOMUX_PAD(0x388, 0x190, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_SD1_CLK__SD1_CLK	IOMUX_PAD(0x38c, 0x194, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
+#define MX25_PAD_SD1_CLK__FEC_RDATA3	IOMUX_PAD(0x38c, 0x194, 0x12, 0x510, 2, NO_PAD_CTRL)
+#define MX25_PAD_SD1_CLK__GPIO_2_24	IOMUX_PAD(0x38c, 0x194, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_SD1_DATA0__SD1_DATA0	IOMUX_PAD(0x390, 0x198, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
+#define MX25_PAD_SD1_DATA0__GPIO_2_25	IOMUX_PAD(0x390, 0x198, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_SD1_DATA1__SD1_DATA1	IOMUX_PAD(0x394, 0x19c, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
+#define MX25_PAD_SD1_DATA1__AUD7_RXD	IOMUX_PAD(0x394, 0x19c, 0x13, 0x478, 0, NO_PAD_CTRL)
+#define MX25_PAD_SD1_DATA1__GPIO_2_26	IOMUX_PAD(0x394, 0x19c, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_SD1_DATA2__SD1_DATA2	IOMUX_PAD(0x398, 0x1a0, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
+#define MX25_PAD_SD1_DATA2__FEC_RX_CLK	IOMUX_PAD(0x398, 0x1a0, 0x15, 0x514, 2, NO_PAD_CTRL)
+#define MX25_PAD_SD1_DATA2__GPIO_2_27	IOMUX_PAD(0x398, 0x1a0, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_SD1_DATA3__SD1_DATA3	IOMUX_PAD(0x39c, 0x1a4, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
+#define MX25_PAD_SD1_DATA3__FEC_CRS	IOMUX_PAD(0x39c, 0x1a4, 0x10, 0x508, 2, NO_PAD_CTRL)
+#define MX25_PAD_SD1_DATA3__GPIO_2_28	IOMUX_PAD(0x39c, 0x1a4, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define KPP_CTL_ROW	(PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
+#define KPP_CTL_COL	(PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP | PAD_CTL_ODE)
+
+#define MX25_PAD_KPP_ROW0__KPP_ROW0	IOMUX_PAD(0x3a0, 0x1a8, 0x10, 0, 0, KPP_CTL_ROW)
+#define MX25_PAD_KPP_ROW0__GPIO_2_29	IOMUX_PAD(0x3a0, 0x1a8, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_KPP_ROW1__KPP_ROW1	IOMUX_PAD(0x3a4, 0x1ac, 0x10, 0, 0, KPP_CTL_ROW)
+#define MX25_PAD_KPP_ROW1__GPIO_2_30	IOMUX_PAD(0x3a4, 0x1ac, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_KPP_ROW2__KPP_ROW2	IOMUX_PAD(0x3a8, 0x1b0, 0x10, 0, 0, KPP_CTL_ROW)
+#define MX25_PAD_KPP_ROW2__CSI_D0	IOMUX_PAD(0x3a8, 0x1b0, 0x13, 0x488, 2, NO_PAD_CTRL)
+#define MX25_PAD_KPP_ROW2__GPIO_2_31	IOMUX_PAD(0x3a8, 0x1b0, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_KPP_ROW3__KPP_ROW3	IOMUX_PAD(0x3ac, 0x1b4, 0x10, 0, 0, KPP_CTL_ROW)
+#define MX25_PAD_KPP_ROW3__CSI_LD1	IOMUX_PAD(0x3ac, 0x1b4, 0x13, 0x48c, 2, NO_PAD_CTRL)
+#define MX25_PAD_KPP_ROW3__GPIO_3_0	IOMUX_PAD(0x3ac, 0x1b4, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_KPP_COL0__KPP_COL0	IOMUX_PAD(0x3b0, 0x1b8, 0x10, 0, 0, KPP_CTL_COL)
+#define MX25_PAD_KPP_COL0__UART4_RXD_MUX IOMUX_PAD(0x3b0, 0x1b8, 0x11, 0x570, 1, NO_PAD_CTRL)
+#define MX25_PAD_KPP_COL0__AUD5_TXD	IOMUX_PAD(0x3b0, 0x1b8, 0x12, 0, 0, PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
+#define MX25_PAD_KPP_COL0__GPIO_3_1	IOMUX_PAD(0x3b0, 0x1b8, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_KPP_COL1__KPP_COL1	IOMUX_PAD(0x3b4, 0x1bc, 0x10, 0, 0, KPP_CTL_COL)
+#define MX25_PAD_KPP_COL1__UART4_TXD_MUX IOMUX_PAD(0x3b4, 0x1bc, 0x11, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_KPP_COL1__AUD5_RXD	IOMUX_PAD(0x3b4, 0x1bc, 0x12, 0, 0, PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
+#define MX25_PAD_KPP_COL1__GPIO_3_2	IOMUX_PAD(0x3b4, 0x1bc, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_KPP_COL2__KPP_COL2	IOMUX_PAD(0x3b8, 0x1c0, 0x10, 0, 0, KPP_CTL_COL)
+#define MX25_PAD_KPP_COL2__UART4_RTS	IOMUX_PAD(0x3b8, 0x1c0, 0x11, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_KPP_COL2__AUD5_TXC	IOMUX_PAD(0x3b8, 0x1c0, 0x12, 0, 0, PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
+#define MX25_PAD_KPP_COL2__GPIO_3_3	IOMUX_PAD(0x3b8, 0x1c0, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_KPP_COL3__KPP_COL3	IOMUX_PAD(0x3bc, 0x1c4, 0x10, 0, 0, KPP_CTL_COL)
+#define MX25_PAD_KPP_COL3__UART4_CTS	IOMUX_PAD(0x3bc, 0x1c4, 0x11, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_KPP_COL3__AUD5_TXFS	IOMUX_PAD(0x3bc, 0x1c4, 0x12, 0, 0, PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
+#define MX25_PAD_KPP_COL3__GPIO_3_4	IOMUX_PAD(0x3bc, 0x1c4, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_FEC_MDC__FEC_MDC	IOMUX_PAD(0x3c0, 0x1c8, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_FEC_MDC__AUD4_TXD	IOMUX_PAD(0x3c0, 0x1c8, 0x12, 0x464, 1, NO_PAD_CTRL)
+#define MX25_PAD_FEC_MDC__GPIO_3_5	IOMUX_PAD(0x3c0, 0x1c8, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_FEC_MDIO__FEC_MDIO	IOMUX_PAD(0x3c4, 0x1cc, 0x10, 0, 0, PAD_CTL_HYS | PAD_CTL_PUS_22K_UP)
+#define MX25_PAD_FEC_MDIO__AUD4_RXD	IOMUX_PAD(0x3c4, 0x1cc, 0x12, 0x460, 1, NO_PAD_CTRL)
+#define MX25_PAD_FEC_MDIO__GPIO_3_6	IOMUX_PAD(0x3c4, 0x1cc, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_FEC_TDATA0__FEC_TDATA0	IOMUX_PAD(0x3c8, 0x1d0, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_FEC_TDATA0__GPIO_3_7	IOMUX_PAD(0x3c8, 0x1d0, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_FEC_TDATA1__FEC_TDATA1	IOMUX_PAD(0x3cc, 0x1d4, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_FEC_TDATA1__AUD4_TXFS	IOMUX_PAD(0x3cc, 0x1d4, 0x12, 0x474, 1, NO_PAD_CTRL)
+#define MX25_PAD_FEC_TDATA1__GPIO_3_8	IOMUX_PAD(0x3cc, 0x1d4, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_FEC_TX_EN__FEC_TX_EN	IOMUX_PAD(0x3d0, 0x1d8, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_FEC_TX_EN__GPIO_3_9   	IOMUX_PAD(0x3d0, 0x1d8, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_FEC_RDATA0__FEC_RDATA0	IOMUX_PAD(0x3d4, 0x1dc, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTRL)
+#define MX25_PAD_FEC_RDATA0__GPIO_3_10	IOMUX_PAD(0x3d4, 0x1dc, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_FEC_RDATA1__FEC_RDATA1	IOMUX_PAD(0x3d8, 0x1e0, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTRL)
+#define MX25_PAD_FEC_RDATA1__GPIO_3_11	IOMUX_PAD(0x3d8, 0x1e0, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_FEC_RX_DV__FEC_RX_DV	IOMUX_PAD(0x3dc, 0x1e4, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTRL)
+#define MX25_PAD_FEC_RX_DV__CAN2_RX	IOMUX_PAD(0x3dc, 0x1e4, 0x14, 0x484, 0, PAD_CTL_PUS_22K_UP)
+#define MX25_PAD_FEC_RX_DV__GPIO_3_12	IOMUX_PAD(0x3dc, 0x1e4, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_FEC_TX_CLK__FEC_TX_CLK	IOMUX_PAD(0x3e0, 0x1e8, 0x10, 0, 0, PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN)
+#define MX25_PAD_FEC_TX_CLK__GPIO_3_13	IOMUX_PAD(0x3e0, 0x1e8, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_RTCK__RTCK		IOMUX_PAD(0x3e4, 0x1ec, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_RTCK__OWIRE		IOMUX_PAD(0x3e4, 0x1ec, 0x11, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_RTCK__GPIO_3_14	IOMUX_PAD(0x3e4, 0x1ec, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_DE_B__DE_B		IOMUX_PAD(0x3ec, 0x1f0, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_DE_B__GPIO_2_20	IOMUX_PAD(0x3ec, 0x1f0, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_TDO__TDO		IOMUX_PAD(0x3e8, 0x000, 0x00, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_GPIO_A__GPIO_A		IOMUX_PAD(0x3f0, 0x1f4, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_GPIO_A__CAN1_TX	IOMUX_PAD(0x3f0, 0x1f4, 0x16, 0, 0, PAD_CTL_PUS_22K_UP)
+#define MX25_PAD_GPIO_A__USBOTG_PWR	IOMUX_PAD(0x3f0, 0x1f4, 0x12, 0, 0, PAD_CTL_PKE)
+
+#define MX25_PAD_GPIO_B__GPIO_B		IOMUX_PAD(0x3f4, 0x1f8, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_GPIO_B__CAN1_RX	IOMUX_PAD(0x3f4, 0x1f8, 0x16, 0x480, 1, PAD_CTL_PUS_22K_UP)
+#define MX25_PAD_GPIO_B__USBOTG_OC	IOMUX_PAD(0x3f4, 0x1f8, 0x12, 0x57c, 1, PAD_CTL_PUS_100K_UP)
+
+#define MX25_PAD_GPIO_C__GPIO_C		IOMUX_PAD(0x3f8, 0x1fc, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_GPIO_C__CAN2_TX	IOMUX_PAD(0x3f8, 0x1fc, 0x16, 0, 0, PAD_CTL_PUS_22K_UP)
+
+#define MX25_PAD_GPIO_D__GPIO_D		IOMUX_PAD(0x3fc, 0x200, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_GPIO_E__LD16		IOMUX_PAD(0x400, 0x204, 0x02, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_GPIO_D__CAN2_RX	IOMUX_PAD(0x3fc, 0x200, 0x16, 0x484, 1, PAD_CTL_PUS_22K_UP)
+
+#define MX25_PAD_GPIO_E__GPIO_E		IOMUX_PAD(0x400, 0x204, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_GPIO_F__LD17		IOMUX_PAD(0x404, 0x208, 0x02, 0, 0, PAD_CTL_SRE_FAST)
+#define MX25_PAD_GPIO_E__AUD7_TXD	IOMUX_PAD(0x400, 0x204, 0x14, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_GPIO_F__GPIO_F		IOMUX_PAD(0x404, 0x208, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_GPIO_F__AUD7_TXC	IOMUX_PAD(0x404, 0x208, 0x14, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_EXT_ARMCLK__EXT_ARMCLK	IOMUX_PAD(0x000, 0x20c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_EXT_ARMCLK__GPIO_3_15	IOMUX_PAD(0x000, 0x20c, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_UPLL_BYPCLK__UPLL_BYPCLK IOMUX_PAD(0x000, 0x210, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_UPLL_BYPCLK__GPIO_3_16	IOMUX_PAD(0x000, 0x210, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_VSTBY_REQ__VSTBY_REQ	IOMUX_PAD(0x408, 0x214, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_VSTBY_REQ__AUD7_TXFS	IOMUX_PAD(0x408, 0x214, 0x14, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_VSTBY_REQ__GPIO_3_17	IOMUX_PAD(0x408, 0x214, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_VSTBY_ACK__VSTBY_ACK	IOMUX_PAD(0x40c, 0x218, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_VSTBY_ACK__GPIO_3_18	IOMUX_PAD(0x40c, 0x218, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_POWER_FAIL__POWER_FAIL	IOMUX_PAD(0x410, 0x21c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_POWER_FAIL__AUD7_RXD	IOMUX_PAD(0x410, 0x21c, 0x14, 0x478, 1, NO_PAD_CTRL)
+#define MX25_PAD_POWER_FAIL__GPIO_3_19	IOMUX_PAD(0x410, 0x21c, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CLKO__CLKO		IOMUX_PAD(0x414, 0x220, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CLKO__GPIO_2_21	IOMUX_PAD(0x414, 0x220, 0x15, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_BOOT_MODE0__BOOT_MODE0	IOMUX_PAD(0x000, 0x224, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_BOOT_MODE0__GPIO_4_30	IOMUX_PAD(0x000, 0x224, 0x05, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_BOOT_MODE1__BOOT_MODE1	IOMUX_PAD(0x000, 0x228, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_BOOT_MODE1__GPIO_4_31	IOMUX_PAD(0x000, 0x228, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CTL_GRP_DVS_MISC	IOMUX_PAD(0x418, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_FEC	IOMUX_PAD(0x41c, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DVS_JTAG	IOMUX_PAD(0x420, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_NFC	IOMUX_PAD(0x424, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_CSI	IOMUX_PAD(0x428, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_WEIM	IOMUX_PAD(0x42c, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_DDR	IOMUX_PAD(0x430, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DVS_CRM	IOMUX_PAD(0x434, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_KPP	IOMUX_PAD(0x438, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_SDHC1	IOMUX_PAD(0x43c, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_LCD	IOMUX_PAD(0x440, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_UART	IOMUX_PAD(0x444, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DVS_NFC	IOMUX_PAD(0x448, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DVS_CSI	IOMUX_PAD(0x44c, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_CSPI1	IOMUX_PAD(0x450, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DDRTYPE	IOMUX_PAD(0x454, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DVS_SDHC1	IOMUX_PAD(0x458, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DVS_LCD	IOMUX_PAD(0x45c, 0x000, 0, 0, 0, NO_PAD_CTRL)
+
+#endif /* __MACH_IOMUX_MX25_H__ */
diff --git a/arch/arm/mach-imx/iomux-mx27.h b/arch/arm/mach-imx/iomux-mx27.h
new file mode 100644
index 0000000..218e99e
--- /dev/null
+++ b/arch/arm/mach-imx/iomux-mx27.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#ifndef __MACH_IOMUX_MX27_H__
+#define __MACH_IOMUX_MX27_H__
+
+#include "iomux-mx2x.h"
+#include "iomux-v1.h"
+
+/* Primary GPIO pin functions */
+
+#define PA0_PF_USBH2_CLK	(GPIO_PORTA | GPIO_PF | 0)
+#define PA1_PF_USBH2_DIR	(GPIO_PORTA | GPIO_PF | 1)
+#define PA2_PF_USBH2_DATA7	(GPIO_PORTA | GPIO_PF | 2)
+#define PA3_PF_USBH2_NXT	(GPIO_PORTA | GPIO_PF | 3)
+#define PA4_PF_USBH2_STP	(GPIO_PORTA | GPIO_PF | 4)
+#define PB22_PF_USBH1_SUSP	(GPIO_PORTB | GPIO_PF | 22)
+#define PB25_PF_USBH1_RCV	(GPIO_PORTB | GPIO_PF | 25)
+#define PC5_PF_I2C2_SDA		(GPIO_PORTC | GPIO_PF | GPIO_IN | 5)
+#define PC6_PF_I2C2_SCL		(GPIO_PORTC | GPIO_PF | GPIO_IN | 6)
+#define PC7_PF_USBOTG_DATA5	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 7)
+#define PC8_PF_USBOTG_DATA6	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 8)
+#define PC9_PF_USBOTG_DATA0	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 9)
+#define PC10_PF_USBOTG_DATA2	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 10)
+#define PC11_PF_USBOTG_DATA1	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 11)
+#define PC12_PF_USBOTG_DATA4	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 12)
+#define PC13_PF_USBOTG_DATA3	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 13)
+#define PC16_PF_SSI4_FS		(GPIO_PORTC | GPIO_PF | GPIO_IN | 16)
+#define PC17_PF_SSI4_RXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 17)
+#define PC18_PF_SSI4_TXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 18)
+#define PC19_PF_SSI4_CLK	(GPIO_PORTC | GPIO_PF | GPIO_IN | 19)
+#define PD0_PF_SD3_CMD		(GPIO_PORTD | GPIO_PF | 0)
+#define PD1_PF_SD3_CLK		(GPIO_PORTD | GPIO_PF | 1)
+#define PD2_PF_ATA_DATA0	(GPIO_PORTD | GPIO_PF | 2)
+#define PD3_PF_ATA_DATA1	(GPIO_PORTD | GPIO_PF | 3)
+#define PD4_PF_ATA_DATA2	(GPIO_PORTD | GPIO_PF | 4)
+#define PD5_PF_ATA_DATA3	(GPIO_PORTD | GPIO_PF | 5)
+#define PD6_PF_ATA_DATA4	(GPIO_PORTD | GPIO_PF | 6)
+#define PD7_PF_ATA_DATA5	(GPIO_PORTD | GPIO_PF | 7)
+#define PD8_PF_ATA_DATA6	(GPIO_PORTD | GPIO_PF | 8)
+#define PD9_PF_ATA_DATA7	(GPIO_PORTD | GPIO_PF | 9)
+#define PD10_PF_ATA_DATA8	(GPIO_PORTD | GPIO_PF | 10)
+#define PD11_PF_ATA_DATA9	(GPIO_PORTD | GPIO_PF | 11)
+#define PD12_PF_ATA_DATA10	(GPIO_PORTD | GPIO_PF | 12)
+#define PD13_PF_ATA_DATA11	(GPIO_PORTD | GPIO_PF | 13)
+#define PD14_PF_ATA_DATA12	(GPIO_PORTD | GPIO_PF | 14)
+#define PD15_PF_ATA_DATA13	(GPIO_PORTD | GPIO_PF | 15)
+#define PD16_PF_ATA_DATA14	(GPIO_PORTD | GPIO_PF | 16)
+#define PE0_PF_USBOTG_NXT	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 0)
+#define PE1_PF_USBOTG_STP	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 1)
+#define PE2_PF_USBOTG_DIR	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 2)
+#define PE24_PF_USBOTG_CLK	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 24)
+#define PE25_PF_USBOTG_DATA7	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 25)
+#define PF1_PF_NFCLE		(GPIO_PORTF | GPIO_PF | 1)
+#define PF3_PF_NFCE		(GPIO_PORTF | GPIO_PF | 3)
+#define PF7_PF_PC_POE		(GPIO_PORTF | GPIO_PF | 7)
+#define PF8_PF_PC_RW		(GPIO_PORTF | GPIO_PF | 8)
+#define PF9_PF_PC_IOIS16	(GPIO_PORTF | GPIO_PF | 9)
+#define PF10_PF_PC_RST		(GPIO_PORTF | GPIO_PF | 10)
+#define PF11_PF_PC_BVD2		(GPIO_PORTF | GPIO_PF | 11)
+#define PF12_PF_PC_BVD1		(GPIO_PORTF | GPIO_PF | 12)
+#define PF13_PF_PC_VS2		(GPIO_PORTF | GPIO_PF | 13)
+#define PF14_PF_PC_VS1		(GPIO_PORTF | GPIO_PF | 14)
+#define PF16_PF_PC_PWRON	(GPIO_PORTF | GPIO_PF | 16)
+#define PF17_PF_PC_READY	(GPIO_PORTF | GPIO_PF | 17)
+#define PF18_PF_PC_WAIT		(GPIO_PORTF | GPIO_PF | 18)
+#define PF19_PF_PC_CD2		(GPIO_PORTF | GPIO_PF | 19)
+#define PF20_PF_PC_CD1		(GPIO_PORTF | GPIO_PF | 20)
+#define PF23_PF_ATA_DATA15	(GPIO_PORTF | GPIO_PF | 23)
+
+/* Alternate GPIO pin functions */
+
+#define PB4_AF_MSHC_DATA0	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 4)
+#define PB5_AF_MSHC_DATA1	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 5)
+#define PB6_AF_MSHC_DATA2	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 6)
+#define PB7_AF_MSHC_DATA4	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 7)
+#define PB8_AF_MSHC_BS		(GPIO_PORTB | GPIO_AF | GPIO_OUT | 8)
+#define PB9_AF_MSHC_SCLK	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 9)
+#define PB10_AF_UART6_TXD	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 10)
+#define PB11_AF_UART6_RXD	(GPIO_PORTB | GPIO_AF | GPIO_IN | 11)
+#define PB12_AF_UART6_CTS	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 12)
+#define PB13_AF_UART6_RTS	(GPIO_PORTB | GPIO_AF | GPIO_IN | 13)
+#define PB18_AF_UART5_TXD	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 18)
+#define PB19_AF_UART5_RXD	(GPIO_PORTB | GPIO_AF | GPIO_IN | 19)
+#define PB20_AF_UART5_CTS	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 20)
+#define PB21_AF_UART5_RTS	(GPIO_PORTB | GPIO_AF | GPIO_IN | 21)
+#define PC8_AF_FEC_MDIO		(GPIO_PORTC | GPIO_AF | GPIO_IN | 8)
+#define PC24_AF_GPT5_TOUT	(GPIO_PORTC | GPIO_AF | 24)
+#define PC25_AF_GPT5_TIN	(GPIO_PORTC | GPIO_AF | 25)
+#define PC26_AF_GPT4_TOUT	(GPIO_PORTC | GPIO_AF | 26)
+#define PC27_AF_GPT4_TIN	(GPIO_PORTC | GPIO_AF | 27)
+#define PD1_AF_ETMTRACE_PKT15	(GPIO_PORTD | GPIO_AF | 1)
+#define PD6_AF_ETMTRACE_PKT14	(GPIO_PORTD | GPIO_AF | 6)
+#define PD7_AF_ETMTRACE_PKT13	(GPIO_PORTD | GPIO_AF | 7)
+#define PD9_AF_ETMTRACE_PKT12	(GPIO_PORTD | GPIO_AF | 9)
+#define PD2_AF_SD3_D0		(GPIO_PORTD | GPIO_AF | 2)
+#define PD3_AF_SD3_D1		(GPIO_PORTD | GPIO_AF | 3)
+#define PD4_AF_SD3_D2		(GPIO_PORTD | GPIO_AF | 4)
+#define PD5_AF_SD3_D3		(GPIO_PORTD | GPIO_AF | 5)
+#define PD8_AF_FEC_MDIO		(GPIO_PORTD | GPIO_AF | GPIO_IN | 8)
+#define PD10_AF_ETMTRACE_PKT11	(GPIO_PORTD | GPIO_AF | 10)
+#define PD11_AF_ETMTRACE_PKT10	(GPIO_PORTD | GPIO_AF | 11)
+#define PD12_AF_ETMTRACE_PKT9	(GPIO_PORTD | GPIO_AF | 12)
+#define PD13_AF_ETMTRACE_PKT8	(GPIO_PORTD | GPIO_AF | 13)
+#define PD14_AF_ETMTRACE_PKT7	(GPIO_PORTD | GPIO_AF | 14)
+#define PD15_AF_ETMTRACE_PKT6	(GPIO_PORTD | GPIO_AF | 15)
+#define PD16_AF_ETMTRACE_PKT5	(GPIO_PORTD | GPIO_AF | 16)
+#define PF1_AF_ETMTRACE_PKT0	(GPIO_PORTF | GPIO_AF | 1)
+#define PF3_AF_ETMTRACE_PKT2	(GPIO_PORTF | GPIO_AF | 3)
+#define PF5_AF_ETMPIPESTAT11	(GPIO_PORTF | GPIO_AF | 5)
+#define PF7_AF_ATA_BUFFER_EN	(GPIO_PORTF | GPIO_AF | 7)
+#define PF8_AF_ATA_IORDY	(GPIO_PORTF | GPIO_AF | 8)
+#define PF9_AF_ATA_INTRQ	(GPIO_PORTF | GPIO_AF | 9)
+#define PF10_AF_ATA_RESET	(GPIO_PORTF | GPIO_AF | 10)
+#define PF11_AF_ATA_DMACK	(GPIO_PORTF | GPIO_AF | 11)
+#define PF12_AF_ATA_DMAREQ	(GPIO_PORTF | GPIO_AF | 12)
+#define PF13_AF_ATA_DA0		(GPIO_PORTF | GPIO_AF | 13)
+#define PF14_AF_ATA_DA1		(GPIO_PORTF | GPIO_AF | 14)
+#define PF15_AF_ETMTRACE_SYNC	(GPIO_PORTF | GPIO_AF | 15)
+#define PF16_AF_ATA_DA2		(GPIO_PORTF | GPIO_AF | 16)
+#define PF17_AF_ATA_CS0		(GPIO_PORTF | GPIO_AF | 17)
+#define PF18_AF_ATA_CS1		(GPIO_PORTF | GPIO_AF | 18)
+#define PF19_AF_ATA_DIOW	(GPIO_PORTF | GPIO_AF | 19)
+#define PF20_AF_ATA_DIOR	(GPIO_PORTF | GPIO_AF | 20)
+#define PF22_AF_ETMTRACE_CLK	(GPIO_PORTF | GPIO_AF | 22)
+#define PF23_AF_ETMTRACE_PKT4	(GPIO_PORTF | GPIO_AF | 23)
+
+/* AIN GPIO pin functions */
+
+#define PC14_AIN_SSI1_MCLK	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 14)
+#define PC15_AIN_GPT6_TOUT	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 15)
+#define PD0_AIN_FEC_TXD0	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 0)
+#define PD1_AIN_FEC_TXD1	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 1)
+#define PD2_AIN_FEC_TXD2	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 2)
+#define PD3_AIN_FEC_TXD3	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 3)
+#define PD9_AIN_FEC_MDC		(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 9)
+#define PD16_AIN_FEC_TX_ER	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 16)
+#define PD27_AIN_EXT_DMA_GRANT	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 27)
+#define PF23_AIN_FEC_TX_EN	(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 23)
+
+/* BIN GPIO pin functions */
+
+#define PC14_BIN_SSI2_MCLK	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 14)
+
+/* CIN GPIO pin functions */
+
+#define PD2_CIN_SLCDC1_DAT0	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 2)
+#define PD3_CIN_SLCDC1_DAT1	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 3)
+#define PD4_CIN_SLCDC1_DAT2	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 4)
+#define PD5_CIN_SLCDC1_DAT3	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 5)
+#define PD6_CIN_SLCDC1_DAT4	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 6)
+#define PD7_CIN_SLCDC1_DAT5	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 7)
+#define PD8_CIN_SLCDC1_DAT6	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 8)
+#define PD9_CIN_SLCDC1_DAT7	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 9)
+#define PD10_CIN_SLCDC1_DAT8	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 10)
+#define PD11_CIN_SLCDC1_DAT9	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 11)
+#define PD12_CIN_SLCDC1_DAT10	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 12)
+#define PD13_CIN_SLCDC1_DAT11	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 13)
+#define PD14_CIN_SLCDC1_DAT12	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 14)
+#define PD15_CIN_SLCDC1_DAT13	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 15)
+#define PD16_CIN_SLCDC1_DAT14	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 16)
+#define PD23_CIN_SLCDC1_DAT15	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 23)
+#define PF27_CIN_EXT_DMA_GRANT	(GPIO_PORTF | GPIO_CIN | GPIO_OUT | 27)
+/* LCDC_TESTx on PBxx omitted, because it's not clear what they do */
+
+/* AOUT GPIO pin functions */
+
+#define PC14_AOUT_GPT6_TIN	(GPIO_PORTC | GPIO_AOUT | GPIO_IN | 14)
+#define PD4_AOUT_FEC_RX_ER	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 4)
+#define PD5_AOUT_FEC_RXD1	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 5)
+#define PD6_AOUT_FEC_RXD2	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 6)
+#define PD7_AOUT_FEC_RXD3	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 7)
+#define PD10_AOUT_FEC_CRS	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 10)
+#define PD11_AOUT_FEC_TX_CLK	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 11)
+#define PD12_AOUT_FEC_RXD0	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 12)
+#define PD13_AOUT_FEC_RX_DV	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 13)
+#define PD14_AOUT_FEC_RX_CLK	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 14)
+#define PD15_AOUT_FEC_COL	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 15)
+
+/* BOUT GPIO pin functions */
+
+#define PC17_BOUT_PC_IOIS16	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 17)
+#define PC18_BOUT_PC_BVD2	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 18)
+#define PC19_BOUT_PC_BVD1	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 19)
+#define PC28_BOUT_PC_BVD2	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 28)
+#define PC29_BOUT_PC_VS1	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 29)
+#define PC30_BOUT_PC_READY	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 30)
+#define PC31_BOUT_PC_WAIT	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 31)
+
+#endif /* __MACH_IOMUX_MX27_H__ */
diff --git a/arch/arm/mach-imx/iomux-mx2x.h b/arch/arm/mach-imx/iomux-mx2x.h
new file mode 100644
index 0000000..7a9b20a
--- /dev/null
+++ b/arch/arm/mach-imx/iomux-mx2x.h
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#ifndef __MACH_IOMUX_MX2x_H__
+#define __MACH_IOMUX_MX2x_H__
+
+/* Primary GPIO pin functions */
+
+#define PA5_PF_LSCLK		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 5)
+#define PA6_PF_LD0		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 6)
+#define PA7_PF_LD1		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 7)
+#define PA8_PF_LD2		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 8)
+#define PA9_PF_LD3		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 9)
+#define PA10_PF_LD4		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 10)
+#define PA11_PF_LD5		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 11)
+#define PA12_PF_LD6		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 12)
+#define PA13_PF_LD7		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 13)
+#define PA14_PF_LD8		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 14)
+#define PA15_PF_LD9		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 15)
+#define PA16_PF_LD10		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 16)
+#define PA17_PF_LD11		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 17)
+#define PA18_PF_LD12		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 18)
+#define PA19_PF_LD13		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 19)
+#define PA20_PF_LD14		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 20)
+#define PA21_PF_LD15		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 21)
+#define PA22_PF_LD16		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 22)
+#define PA23_PF_LD17		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 23)
+#define PA24_PF_REV		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 24)
+#define PA25_PF_CLS		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 25)
+#define PA26_PF_PS		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 26)
+#define PA27_PF_SPL_SPR		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 27)
+#define PA28_PF_HSYNC		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 28)
+#define PA29_PF_VSYNC		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 29)
+#define PA30_PF_CONTRAST	(GPIO_PORTA | GPIO_PF | GPIO_OUT | 30)
+#define PA31_PF_OE_ACD		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 31)
+#define PB4_PF_SD2_D0		(GPIO_PORTB | GPIO_PF | 4)
+#define PB5_PF_SD2_D1		(GPIO_PORTB | GPIO_PF | 5)
+#define PB6_PF_SD2_D2		(GPIO_PORTB | GPIO_PF | 6)
+#define PB7_PF_SD2_D3		(GPIO_PORTB | GPIO_PF | 7)
+#define PB8_PF_SD2_CMD		(GPIO_PORTB | GPIO_PF | 8)
+#define PB9_PF_SD2_CLK		(GPIO_PORTB | GPIO_PF | 9)
+#define PB10_PF_CSI_D0		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 10)
+#define PB11_PF_CSI_D1		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 11)
+#define PB12_PF_CSI_D2		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 12)
+#define PB13_PF_CSI_D3		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 13)
+#define PB14_PF_CSI_D4		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 14)
+#define PB15_PF_CSI_MCLK	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 15)
+#define PB16_PF_CSI_PIXCLK	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 16)
+#define PB17_PF_CSI_D5		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 17)
+#define PB18_PF_CSI_D6		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 18)
+#define PB19_PF_CSI_D7		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 19)
+#define PB20_PF_CSI_VSYNC	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 20)
+#define PB21_PF_CSI_HSYNC	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 21)
+#define PB23_PF_USB_PWR		(GPIO_PORTB | GPIO_PF | 23)
+#define PB24_PF_USB_OC		(GPIO_PORTB | GPIO_PF | 24)
+#define PB26_PF_USBH1_FS	(GPIO_PORTB | GPIO_PF | 26)
+#define PB27_PF_USBH1_OE	(GPIO_PORTB | GPIO_PF | 27)
+#define PB28_PF_USBH1_TXDM	(GPIO_PORTB | GPIO_PF | 28)
+#define PB29_PF_USBH1_TXDP	(GPIO_PORTB | GPIO_PF | 29)
+#define PB30_PF_USBH1_RXDM	(GPIO_PORTB | GPIO_PF | 30)
+#define PB31_PF_USBH1_RXDP	(GPIO_PORTB | GPIO_PF | 31)
+#define PC14_PF_TOUT		(GPIO_PORTC | GPIO_PF | 14)
+#define PC15_PF_TIN		(GPIO_PORTC | GPIO_PF | 15)
+#define PC20_PF_SSI1_FS		(GPIO_PORTC | GPIO_PF | GPIO_IN | 20)
+#define PC21_PF_SSI1_RXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 21)
+#define PC22_PF_SSI1_TXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 22)
+#define PC23_PF_SSI1_CLK	(GPIO_PORTC | GPIO_PF | GPIO_IN | 23)
+#define PC24_PF_SSI2_FS		(GPIO_PORTC | GPIO_PF | GPIO_IN | 24)
+#define PC25_PF_SSI2_RXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 25)
+#define PC26_PF_SSI2_TXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 26)
+#define PC27_PF_SSI2_CLK	(GPIO_PORTC | GPIO_PF | GPIO_IN | 27)
+#define PC28_PF_SSI3_FS		(GPIO_PORTC | GPIO_PF | GPIO_IN | 28)
+#define PC29_PF_SSI3_RXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 29)
+#define PC30_PF_SSI3_TXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 30)
+#define PC31_PF_SSI3_CLK	(GPIO_PORTC | GPIO_PF | GPIO_IN | 31)
+#define PD17_PF_I2C_DATA	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 17)
+#define PD18_PF_I2C_CLK		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 18)
+#define PD19_PF_CSPI2_SS2	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 19)
+#define PD20_PF_CSPI2_SS1	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 20)
+#define PD21_PF_CSPI2_SS0	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 21)
+#define PD22_PF_CSPI2_SCLK	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 22)
+#define PD23_PF_CSPI2_MISO	(GPIO_PORTD | GPIO_PF | GPIO_IN | 23)
+#define PD24_PF_CSPI2_MOSI	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 24)
+#define PD25_PF_CSPI1_RDY	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 25)
+#define PD26_PF_CSPI1_SS2	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 26)
+#define PD27_PF_CSPI1_SS1	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 27)
+#define PD28_PF_CSPI1_SS0	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 28)
+#define PD29_PF_CSPI1_SCLK	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 29)
+#define PD30_PF_CSPI1_MISO	(GPIO_PORTD | GPIO_PF | GPIO_IN | 30)
+#define PD31_PF_CSPI1_MOSI	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 31)
+#define PE3_PF_UART2_CTS	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 3)
+#define PE4_PF_UART2_RTS	(GPIO_PORTE | GPIO_PF | GPIO_IN | 4)
+#define PE5_PF_PWMO		(GPIO_PORTE | GPIO_PF | 5)
+#define PE6_PF_UART2_TXD	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 6)
+#define PE7_PF_UART2_RXD	(GPIO_PORTE | GPIO_PF | GPIO_IN | 7)
+#define PE8_PF_UART3_TXD	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 8)
+#define PE9_PF_UART3_RXD	(GPIO_PORTE | GPIO_PF | GPIO_IN | 9)
+#define PE10_PF_UART3_CTS	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 10)
+#define PE11_PF_UART3_RTS	(GPIO_PORTE | GPIO_PF | GPIO_IN | 11)
+#define PE12_PF_UART1_TXD	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 12)
+#define PE13_PF_UART1_RXD	(GPIO_PORTE | GPIO_PF | GPIO_IN | 13)
+#define PE14_PF_UART1_CTS	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 14)
+#define PE15_PF_UART1_RTS	(GPIO_PORTE | GPIO_PF | GPIO_IN | 15)
+#define PE16_PF_RTCK		(GPIO_PORTE | GPIO_PF | GPIO_OUT | 16)
+#define PE17_PF_RESET_OUT	(GPIO_PORTE | GPIO_PF | 17)
+#define PE18_PF_SD1_D0		(GPIO_PORTE | GPIO_PF | 18)
+#define PE19_PF_SD1_D1		(GPIO_PORTE | GPIO_PF | 19)
+#define PE20_PF_SD1_D2		(GPIO_PORTE | GPIO_PF | 20)
+#define PE21_PF_SD1_D3		(GPIO_PORTE | GPIO_PF | 21)
+#define PE22_PF_SD1_CMD		(GPIO_PORTE | GPIO_PF | 22)
+#define PE23_PF_SD1_CLK		(GPIO_PORTE | GPIO_PF | 23)
+#define PF0_PF_NRFB		(GPIO_PORTF | GPIO_PF | 0)
+#define PF2_PF_NFWP		(GPIO_PORTF | GPIO_PF | 2)
+#define PF4_PF_NFALE		(GPIO_PORTF | GPIO_PF | 4)
+#define PF5_PF_NFRE		(GPIO_PORTF | GPIO_PF | 5)
+#define PF6_PF_NFWE		(GPIO_PORTF | GPIO_PF | 6)
+#define PF15_PF_CLKO		(GPIO_PORTF | GPIO_PF | 15)
+#define PF21_PF_CS4		(GPIO_PORTF | GPIO_PF | 21)
+#define PF22_PF_CS5		(GPIO_PORTF | GPIO_PF | 22)
+
+/* Alternate GPIO pin functions */
+
+#define PB26_AF_UART4_RTS	(GPIO_PORTB | GPIO_AF | GPIO_IN | 26)
+#define PB28_AF_UART4_TXD	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 28)
+#define PB29_AF_UART4_CTS	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 29)
+#define PB31_AF_UART4_RXD	(GPIO_PORTB | GPIO_AF | GPIO_IN | 31)
+#define PC28_AF_SLCDC2_D0	(GPIO_PORTC | GPIO_AF | 28)
+#define PC29_AF_SLCDC2_RS	(GPIO_PORTC | GPIO_AF | 29)
+#define PC30_AF_SLCDC2_CS	(GPIO_PORTC | GPIO_AF | 30)
+#define PC31_AF_SLCDC2_CLK	(GPIO_PORTC | GPIO_AF | 31)
+#define PD19_AF_USBH2_DATA4	(GPIO_PORTD | GPIO_AF | 19)
+#define PD20_AF_USBH2_DATA3	(GPIO_PORTD | GPIO_AF | 20)
+#define PD21_AF_USBH2_DATA6	(GPIO_PORTD | GPIO_AF | 21)
+#define PD22_AF_USBH2_DATA0	(GPIO_PORTD | GPIO_AF | 22)
+#define PD23_AF_USBH2_DATA2	(GPIO_PORTD | GPIO_AF | 23)
+#define PD24_AF_USBH2_DATA1	(GPIO_PORTD | GPIO_AF | 24)
+#define PD26_AF_USBH2_DATA5	(GPIO_PORTD | GPIO_AF | 26)
+#define PE0_AF_KP_COL6		(GPIO_PORTE | GPIO_AF | 0)
+#define PE1_AF_KP_ROW6		(GPIO_PORTE | GPIO_AF | 1)
+#define PE2_AF_KP_ROW7		(GPIO_PORTE | GPIO_AF | 2)
+#define PE3_AF_KP_COL7		(GPIO_PORTE | GPIO_AF | 3)
+#define PE4_AF_KP_ROW7		(GPIO_PORTE | GPIO_AF | 4)
+#define PE6_AF_KP_COL6		(GPIO_PORTE | GPIO_AF | 6)
+#define PE7_AF_KP_ROW6		(GPIO_PORTE | GPIO_AF | 7)
+#define PE16_AF_OWIRE		(GPIO_PORTE | GPIO_AF | 16)
+#define PE18_AF_CSPI3_MISO	(GPIO_PORTE | GPIO_AF | GPIO_IN | 18)
+#define PE21_AF_CSPI3_SS	(GPIO_PORTE | GPIO_AF | GPIO_OUT | 21)
+#define PE22_AF_CSPI3_MOSI	(GPIO_PORTE | GPIO_AF | GPIO_OUT | 22)
+#define PE23_AF_CSPI3_SCLK	(GPIO_PORTE | GPIO_AF | GPIO_OUT | 23)
+
+/* AIN GPIO pin functions */
+
+#define PA6_AIN_SLCDC1_DAT0	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 6)
+#define PA7_AIN_SLCDC1_DAT1	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 7)
+#define PA8_AIN_SLCDC1_DAT2	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 8)
+#define PA0_AIN_SLCDC1_DAT3	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 0)
+#define PA11_AIN_SLCDC1_DAT5	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 11)
+#define PA13_AIN_SLCDC1_DAT7	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 13)
+#define PA15_AIN_SLCDC1_DAT9	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 15)
+#define PA17_AIN_SLCDC1_DAT11	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 17)
+#define PA19_AIN_SLCDC1_DAT13	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 19)
+#define PA21_AIN_SLCDC1_DAT15	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 21)
+#define PA22_AIN_EXT_DMAGRANT	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 22)
+#define PA24_AIN_SLCDC1_D0	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 24)
+#define PA25_AIN_SLCDC1_RS	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 25)
+#define PA26_AIN_SLCDC1_CS	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 26)
+#define PA27_AIN_SLCDC1_CLK	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 27)
+#define PB6_AIN_SLCDC1_D0	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 6)
+#define PB7_AIN_SLCDC1_RS	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 7)
+#define PB8_AIN_SLCDC1_CS	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 8)
+#define PB9_AIN_SLCDC1_CLK	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 9)
+#define PB25_AIN_SLCDC1_DAT0	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 25)
+#define PB26_AIN_SLCDC1_DAT1	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 26)
+#define PB27_AIN_SLCDC1_DAT2	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 27)
+#define PB28_AIN_SLCDC1_DAT3	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 28)
+#define PB29_AIN_SLCDC1_DAT4	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 29)
+#define PB30_AIN_SLCDC1_DAT5	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 30)
+#define PB31_AIN_SLCDC1_DAT6	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 31)
+#define PC5_AIN_SLCDC1_DAT7	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 5)
+#define PC6_AIN_SLCDC1_DAT8	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 6)
+#define PC7_AIN_SLCDC1_DAT9	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 7)
+#define PC8_AIN_SLCDC1_DAT10	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 8)
+#define PC9_AIN_SLCDC1_DAT11	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 9)
+#define PC10_AIN_SLCDC1_DAT12	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 10)
+#define PC11_AIN_SLCDC1_DAT13	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 11)
+#define PC12_AIN_SLCDC1_DAT14	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 12)
+#define PC13_AIN_SLCDC1_DAT15	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 13)
+#define PE5_AIN_PC_SPKOUT	(GPIO_PORTE | GPIO_AIN | GPIO_OUT | 5)
+
+/* BIN GPIO pin functions */
+
+#define PE5_BIN_TOUT2		(GPIO_PORTE | GPIO_BIN | GPIO_OUT | 5)
+
+/* CIN GPIO pin functions */
+
+#define PA14_CIN_SLCDC1_DAT0	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 14)
+#define PA15_CIN_SLCDC1_DAT1	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 15)
+#define PA16_CIN_SLCDC1_DAT2	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 16)
+#define PA17_CIN_SLCDC1_DAT3	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 17)
+#define PA18_CIN_SLCDC1_DAT4	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 18)
+#define PA19_CIN_SLCDC1_DAT5	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 19)
+#define PA20_CIN_SLCDC1_DAT6	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 20)
+#define PA21_CIN_SLCDC1_DAT7	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 21)
+#define PB30_CIN_UART4_CTS	(GPIO_PORTB | GPIO_CIN | GPIO_OUT | 30)
+#define PE5_CIN_TOUT3		(GPIO_PORTE | GPIO_CIN | GPIO_OUT | 5)
+
+/* AOUT GPIO pin functions */
+
+#define PB29_AOUT_UART4_RXD	(GPIO_PORTB | GPIO_AOUT | GPIO_IN | 29)
+#define PB31_AOUT_UART4_RTS	(GPIO_PORTB | GPIO_AOUT | GPIO_IN | 31)
+#define PC8_AOUT_USBOTG_TXR_INT (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 8)
+#define PC15_AOUT_WKGD		(GPIO_PORTC | GPIO_AOUT | GPIO_IN | 15)
+#define PF21_AOUT_DTACK		(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 21)
+
+#endif /* ifndef __MACH_IOMUX_MX2x_H__ */
diff --git a/arch/arm/mach-imx/iomux-mx3.h b/arch/arm/mach-imx/iomux-mx3.h
new file mode 100644
index 0000000..f79f78a
--- /dev/null
+++ b/arch/arm/mach-imx/iomux-mx3.h
@@ -0,0 +1,753 @@
+/*
+ * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#ifndef __MACH_IOMUX_MX3_H__
+#define __MACH_IOMUX_MX3_H__
+
+#include <linux/types.h>
+/*
+ * various IOMUX output functions
+ */
+
+#define	IOMUX_OCONFIG_GPIO (0 << 4)	/* used as GPIO */
+#define	IOMUX_OCONFIG_FUNC (1 << 4)	/* used as function */
+#define	IOMUX_OCONFIG_ALT1 (2 << 4)	/* used as alternate function 1 */
+#define	IOMUX_OCONFIG_ALT2 (3 << 4)	/* used as alternate function 2 */
+#define	IOMUX_OCONFIG_ALT3 (4 << 4)	/* used as alternate function 3 */
+#define	IOMUX_OCONFIG_ALT4 (5 << 4)	/* used as alternate function 4 */
+#define	IOMUX_OCONFIG_ALT5 (6 << 4)	/* used as alternate function 5 */
+#define	IOMUX_OCONFIG_ALT6 (7 << 4)	/* used as alternate function 6 */
+#define	IOMUX_ICONFIG_NONE  0		/* not configured for input */
+#define	IOMUX_ICONFIG_GPIO  1		/* used as GPIO */
+#define	IOMUX_ICONFIG_FUNC  2		/* used as function */
+#define	IOMUX_ICONFIG_ALT1  4		/* used as alternate function 1 */
+#define	IOMUX_ICONFIG_ALT2  8		/* used as alternate function 2 */
+
+#define IOMUX_CONFIG_GPIO (IOMUX_OCONFIG_GPIO | IOMUX_ICONFIG_GPIO)
+#define IOMUX_CONFIG_FUNC (IOMUX_OCONFIG_FUNC | IOMUX_ICONFIG_FUNC)
+#define IOMUX_CONFIG_ALT1 (IOMUX_OCONFIG_ALT1 | IOMUX_ICONFIG_ALT1)
+#define IOMUX_CONFIG_ALT2 (IOMUX_OCONFIG_ALT2 | IOMUX_ICONFIG_ALT2)
+
+/*
+ * various IOMUX pad functions
+ */
+enum iomux_pad_config {
+	PAD_CTL_NOLOOPBACK	= 0x0 << 9,
+	PAD_CTL_LOOPBACK	= 0x1 << 9,
+	PAD_CTL_PKE_NONE	= 0x0 << 8,
+	PAD_CTL_PKE_ENABLE	= 0x1 << 8,
+	PAD_CTL_PUE_KEEPER	= 0x0 << 7,
+	PAD_CTL_PUE_PUD		= 0x1 << 7,
+	PAD_CTL_100K_PD		= 0x0 << 5,
+	PAD_CTL_100K_PU		= 0x1 << 5,
+	PAD_CTL_47K_PU		= 0x2 << 5,
+	PAD_CTL_22K_PU		= 0x3 << 5,
+	PAD_CTL_HYS_CMOS	= 0x0 << 4,
+	PAD_CTL_HYS_SCHMITZ	= 0x1 << 4,
+	PAD_CTL_ODE_CMOS	= 0x0 << 3,
+	PAD_CTL_ODE_OpenDrain	= 0x1 << 3,
+	PAD_CTL_DRV_NORMAL	= 0x0 << 1,
+	PAD_CTL_DRV_HIGH	= 0x1 << 1,
+	PAD_CTL_DRV_MAX		= 0x2 << 1,
+	PAD_CTL_SRE_SLOW	= 0x0 << 0,
+	PAD_CTL_SRE_FAST	= 0x1 << 0
+};
+
+/*
+ * various IOMUX general purpose functions
+ */
+enum iomux_gp_func {
+	MUX_PGP_FIRI			= 1 << 0,
+	MUX_DDR_MODE			= 1 << 1,
+	MUX_PGP_CSPI_BB			= 1 << 2,
+	MUX_PGP_ATA_1			= 1 << 3,
+	MUX_PGP_ATA_2			= 1 << 4,
+	MUX_PGP_ATA_3			= 1 << 5,
+	MUX_PGP_ATA_4			= 1 << 6,
+	MUX_PGP_ATA_5			= 1 << 7,
+	MUX_PGP_ATA_6			= 1 << 8,
+	MUX_PGP_ATA_7			= 1 << 9,
+	MUX_PGP_ATA_8			= 1 << 10,
+	MUX_PGP_UH2			= 1 << 11,
+	MUX_SDCTL_CSD0_SEL		= 1 << 12,
+	MUX_SDCTL_CSD1_SEL		= 1 << 13,
+	MUX_CSPI1_UART3			= 1 << 14,
+	MUX_EXTDMAREQ2_MBX_SEL		= 1 << 15,
+	MUX_TAMPER_DETECT_EN		= 1 << 16,
+	MUX_PGP_USB_4WIRE		= 1 << 17,
+	MUX_PGP_USB_COMMON		= 1 << 18,
+	MUX_SDHC_MEMSTICK1		= 1 << 19,
+	MUX_SDHC_MEMSTICK2		= 1 << 20,
+	MUX_PGP_SPLL_BYP		= 1 << 21,
+	MUX_PGP_UPLL_BYP		= 1 << 22,
+	MUX_PGP_MSHC1_CLK_SEL		= 1 << 23,
+	MUX_PGP_MSHC2_CLK_SEL		= 1 << 24,
+	MUX_CSPI3_UART5_SEL		= 1 << 25,
+	MUX_PGP_ATA_9			= 1 << 26,
+	MUX_PGP_USB_SUSPEND		= 1 << 27,
+	MUX_PGP_USB_OTG_LOOPBACK	= 1 << 28,
+	MUX_PGP_USB_HS1_LOOPBACK	= 1 << 29,
+	MUX_PGP_USB_HS2_LOOPBACK	= 1 << 30,
+	MUX_CLKO_DDR_MODE		= 1 << 31,
+};
+
+/*
+ * setups a single pin:
+ * 	- reserves the pin so that it is not claimed by another driver
+ * 	- setups the iomux according to the configuration
+ * 	- if the pin is configured as a GPIO, we claim it through kernel gpiolib
+ */
+int mxc_iomux_alloc_pin(unsigned int pin, const char *label);
+/*
+ * setups mutliple pins
+ * convenient way to call the above function with tables
+ */
+int mxc_iomux_setup_multiple_pins(const unsigned int *pin_list, unsigned count,
+		const char *label);
+
+/*
+ * releases a single pin:
+ * 	- make it available for a future use by another driver
+ * 	- frees the GPIO if the pin was configured as GPIO
+ * 	- DOES NOT reconfigure the IOMUX in its reset state
+ */
+void mxc_iomux_release_pin(unsigned int pin);
+/*
+ * releases multiple pins
+ * convenvient way to call the above function with tables
+ */
+void mxc_iomux_release_multiple_pins(const unsigned int *pin_list, int count);
+
+/*
+ * This function enables/disables the general purpose function for a particular
+ * signal.
+ */
+void mxc_iomux_set_gpr(enum iomux_gp_func, bool en);
+
+/*
+ * This function only configures the iomux hardware.
+ * It is called by the setup functions and should not be called directly anymore.
+ * It is here visible for backward compatibility
+ */
+int mxc_iomux_mode(unsigned int pin_mode);
+
+#define IOMUX_PADNUM_MASK	0x1ff
+#define IOMUX_GPIONUM_SHIFT	9
+#define IOMUX_GPIONUM_MASK	(0xff << IOMUX_GPIONUM_SHIFT)
+#define IOMUX_MODE_SHIFT	17
+#define IOMUX_MODE_MASK	(0xff << IOMUX_MODE_SHIFT)
+
+#define IOMUX_PIN(gpionum, padnum) \
+	(((gpionum << IOMUX_GPIONUM_SHIFT) & IOMUX_GPIONUM_MASK) | \
+	 (padnum & IOMUX_PADNUM_MASK))
+
+#define IOMUX_MODE(pin, mode) (pin | mode << IOMUX_MODE_SHIFT)
+
+#define IOMUX_TO_GPIO(iomux_pin) \
+	((iomux_pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT)
+
+/*
+ * This enumeration is constructed based on the Section
+ * "sw_pad_ctl & sw_mux_ctl details" of the MX31 IC Spec. Each enumerated
+ * value is constructed based on the rules described above.
+ */
+
+enum iomux_pins {
+	MX31_PIN_TTM_PAD	= IOMUX_PIN(0xff,   0),
+	MX31_PIN_CSPI3_SPI_RDY	= IOMUX_PIN(0xff,   1),
+	MX31_PIN_CSPI3_SCLK	= IOMUX_PIN(0xff,   2),
+	MX31_PIN_CSPI3_MISO	= IOMUX_PIN(0xff,   3),
+	MX31_PIN_CSPI3_MOSI	= IOMUX_PIN(0xff,   4),
+	MX31_PIN_CLKSS		= IOMUX_PIN(0xff,   5),
+	MX31_PIN_CE_CONTROL	= IOMUX_PIN(0xff,   6),
+	MX31_PIN_ATA_RESET_B	= IOMUX_PIN(95,     7),
+	MX31_PIN_ATA_DMACK	= IOMUX_PIN(94,     8),
+	MX31_PIN_ATA_DIOW	= IOMUX_PIN(93,     9),
+	MX31_PIN_ATA_DIOR	= IOMUX_PIN(92,    10),
+	MX31_PIN_ATA_CS1	= IOMUX_PIN(91,    11),
+	MX31_PIN_ATA_CS0	= IOMUX_PIN(90,    12),
+	MX31_PIN_SD1_DATA3	= IOMUX_PIN(63,    13),
+	MX31_PIN_SD1_DATA2	= IOMUX_PIN(62,    14),
+	MX31_PIN_SD1_DATA1	= IOMUX_PIN(61,    15),
+	MX31_PIN_SD1_DATA0	= IOMUX_PIN(60,    16),
+	MX31_PIN_SD1_CLK	= IOMUX_PIN(59,    17),
+	MX31_PIN_SD1_CMD	= IOMUX_PIN(58,    18),
+	MX31_PIN_D3_SPL		= IOMUX_PIN(0xff,  19),
+	MX31_PIN_D3_CLS		= IOMUX_PIN(0xff,  20),
+	MX31_PIN_D3_REV		= IOMUX_PIN(0xff,  21),
+	MX31_PIN_CONTRAST	= IOMUX_PIN(0xff,  22),
+	MX31_PIN_VSYNC3		= IOMUX_PIN(0xff,  23),
+	MX31_PIN_READ		= IOMUX_PIN(0xff,  24),
+	MX31_PIN_WRITE		= IOMUX_PIN(0xff,  25),
+	MX31_PIN_PAR_RS		= IOMUX_PIN(0xff,  26),
+	MX31_PIN_SER_RS		= IOMUX_PIN(89,    27),
+	MX31_PIN_LCS1		= IOMUX_PIN(88,    28),
+	MX31_PIN_LCS0		= IOMUX_PIN(87,    29),
+	MX31_PIN_SD_D_CLK	= IOMUX_PIN(86,    30),
+	MX31_PIN_SD_D_IO	= IOMUX_PIN(85,    31),
+	MX31_PIN_SD_D_I		= IOMUX_PIN(84,    32),
+	MX31_PIN_DRDY0		= IOMUX_PIN(0xff,  33),
+	MX31_PIN_FPSHIFT	= IOMUX_PIN(0xff,  34),
+	MX31_PIN_HSYNC		= IOMUX_PIN(0xff,  35),
+	MX31_PIN_VSYNC0		= IOMUX_PIN(0xff,  36),
+	MX31_PIN_LD17		= IOMUX_PIN(0xff,  37),
+	MX31_PIN_LD16		= IOMUX_PIN(0xff,  38),
+	MX31_PIN_LD15		= IOMUX_PIN(0xff,  39),
+	MX31_PIN_LD14		= IOMUX_PIN(0xff,  40),
+	MX31_PIN_LD13		= IOMUX_PIN(0xff,  41),
+	MX31_PIN_LD12		= IOMUX_PIN(0xff,  42),
+	MX31_PIN_LD11		= IOMUX_PIN(0xff,  43),
+	MX31_PIN_LD10		= IOMUX_PIN(0xff,  44),
+	MX31_PIN_LD9		= IOMUX_PIN(0xff,  45),
+	MX31_PIN_LD8		= IOMUX_PIN(0xff,  46),
+	MX31_PIN_LD7		= IOMUX_PIN(0xff,  47),
+	MX31_PIN_LD6		= IOMUX_PIN(0xff,  48),
+	MX31_PIN_LD5		= IOMUX_PIN(0xff,  49),
+	MX31_PIN_LD4		= IOMUX_PIN(0xff,  50),
+	MX31_PIN_LD3		= IOMUX_PIN(0xff,  51),
+	MX31_PIN_LD2		= IOMUX_PIN(0xff,  52),
+	MX31_PIN_LD1		= IOMUX_PIN(0xff,  53),
+	MX31_PIN_LD0		= IOMUX_PIN(0xff,  54),
+	MX31_PIN_USBH2_DATA1	= IOMUX_PIN(0xff,  55),
+	MX31_PIN_USBH2_DATA0	= IOMUX_PIN(0xff,  56),
+	MX31_PIN_USBH2_NXT	= IOMUX_PIN(0xff,  57),
+	MX31_PIN_USBH2_STP	= IOMUX_PIN(0xff,  58),
+	MX31_PIN_USBH2_DIR	= IOMUX_PIN(0xff,  59),
+	MX31_PIN_USBH2_CLK	= IOMUX_PIN(0xff,  60),
+	MX31_PIN_USBOTG_DATA7	= IOMUX_PIN(0xff,  61),
+	MX31_PIN_USBOTG_DATA6	= IOMUX_PIN(0xff,  62),
+	MX31_PIN_USBOTG_DATA5	= IOMUX_PIN(0xff,  63),
+	MX31_PIN_USBOTG_DATA4	= IOMUX_PIN(0xff,  64),
+	MX31_PIN_USBOTG_DATA3	= IOMUX_PIN(0xff,  65),
+	MX31_PIN_USBOTG_DATA2	= IOMUX_PIN(0xff,  66),
+	MX31_PIN_USBOTG_DATA1	= IOMUX_PIN(0xff,  67),
+	MX31_PIN_USBOTG_DATA0	= IOMUX_PIN(0xff,  68),
+	MX31_PIN_USBOTG_NXT	= IOMUX_PIN(0xff,  69),
+	MX31_PIN_USBOTG_STP	= IOMUX_PIN(0xff,  70),
+	MX31_PIN_USBOTG_DIR	= IOMUX_PIN(0xff,  71),
+	MX31_PIN_USBOTG_CLK	= IOMUX_PIN(0xff,  72),
+	MX31_PIN_USB_BYP	= IOMUX_PIN(31,    73),
+	MX31_PIN_USB_OC		= IOMUX_PIN(30,    74),
+	MX31_PIN_USB_PWR	= IOMUX_PIN(29,    75),
+	MX31_PIN_SJC_MOD	= IOMUX_PIN(0xff,  76),
+	MX31_PIN_DE_B		= IOMUX_PIN(0xff,  77),
+	MX31_PIN_TRSTB		= IOMUX_PIN(0xff,  78),
+	MX31_PIN_TDO		= IOMUX_PIN(0xff,  79),
+	MX31_PIN_TDI		= IOMUX_PIN(0xff,  80),
+	MX31_PIN_TMS		= IOMUX_PIN(0xff,  81),
+	MX31_PIN_TCK		= IOMUX_PIN(0xff,  82),
+	MX31_PIN_RTCK		= IOMUX_PIN(0xff,  83),
+	MX31_PIN_KEY_COL7	= IOMUX_PIN(57,    84),
+	MX31_PIN_KEY_COL6	= IOMUX_PIN(56,    85),
+	MX31_PIN_KEY_COL5	= IOMUX_PIN(55,    86),
+	MX31_PIN_KEY_COL4	= IOMUX_PIN(54,    87),
+	MX31_PIN_KEY_COL3	= IOMUX_PIN(0xff,  88),
+	MX31_PIN_KEY_COL2	= IOMUX_PIN(0xff,  89),
+	MX31_PIN_KEY_COL1	= IOMUX_PIN(0xff,  90),
+	MX31_PIN_KEY_COL0	= IOMUX_PIN(0xff,  91),
+	MX31_PIN_KEY_ROW7	= IOMUX_PIN(53,    92),
+	MX31_PIN_KEY_ROW6	= IOMUX_PIN(52,    93),
+	MX31_PIN_KEY_ROW5	= IOMUX_PIN(51,    94),
+	MX31_PIN_KEY_ROW4	= IOMUX_PIN(50,    95),
+	MX31_PIN_KEY_ROW3	= IOMUX_PIN(0xff,  96),
+	MX31_PIN_KEY_ROW2	= IOMUX_PIN(0xff,  97),
+	MX31_PIN_KEY_ROW1	= IOMUX_PIN(0xff,  98),
+	MX31_PIN_KEY_ROW0	= IOMUX_PIN(0xff,  99),
+	MX31_PIN_BATT_LINE	= IOMUX_PIN(49,   100),
+	MX31_PIN_CTS2		= IOMUX_PIN(0xff, 101),
+	MX31_PIN_RTS2		= IOMUX_PIN(0xff, 102),
+	MX31_PIN_TXD2		= IOMUX_PIN(28,   103),
+	MX31_PIN_RXD2		= IOMUX_PIN(27,   104),
+	MX31_PIN_DTR_DCE2	= IOMUX_PIN(48,   105),
+	MX31_PIN_DCD_DTE1	= IOMUX_PIN(47,   106),
+	MX31_PIN_RI_DTE1	= IOMUX_PIN(46,   107),
+	MX31_PIN_DSR_DTE1	= IOMUX_PIN(45,   108),
+	MX31_PIN_DTR_DTE1	= IOMUX_PIN(44,   109),
+	MX31_PIN_DCD_DCE1	= IOMUX_PIN(43,   110),
+	MX31_PIN_RI_DCE1	= IOMUX_PIN(42,   111),
+	MX31_PIN_DSR_DCE1	= IOMUX_PIN(41,   112),
+	MX31_PIN_DTR_DCE1	= IOMUX_PIN(40,   113),
+	MX31_PIN_CTS1		= IOMUX_PIN(39,   114),
+	MX31_PIN_RTS1		= IOMUX_PIN(38,   115),
+	MX31_PIN_TXD1		= IOMUX_PIN(37,   116),
+	MX31_PIN_RXD1		= IOMUX_PIN(36,   117),
+	MX31_PIN_CSPI2_SPI_RDY	= IOMUX_PIN(0xff, 118),
+	MX31_PIN_CSPI2_SCLK	= IOMUX_PIN(0xff, 119),
+	MX31_PIN_CSPI2_SS2	= IOMUX_PIN(0xff, 120),
+	MX31_PIN_CSPI2_SS1	= IOMUX_PIN(0xff, 121),
+	MX31_PIN_CSPI2_SS0	= IOMUX_PIN(0xff, 122),
+	MX31_PIN_CSPI2_MISO	= IOMUX_PIN(0xff, 123),
+	MX31_PIN_CSPI2_MOSI	= IOMUX_PIN(0xff, 124),
+	MX31_PIN_CSPI1_SPI_RDY	= IOMUX_PIN(0xff, 125),
+	MX31_PIN_CSPI1_SCLK	= IOMUX_PIN(0xff, 126),
+	MX31_PIN_CSPI1_SS2	= IOMUX_PIN(0xff, 127),
+	MX31_PIN_CSPI1_SS1	= IOMUX_PIN(0xff, 128),
+	MX31_PIN_CSPI1_SS0	= IOMUX_PIN(0xff, 129),
+	MX31_PIN_CSPI1_MISO	= IOMUX_PIN(0xff, 130),
+	MX31_PIN_CSPI1_MOSI	= IOMUX_PIN(0xff, 131),
+	MX31_PIN_SFS6		= IOMUX_PIN(26,   132),
+	MX31_PIN_SCK6		= IOMUX_PIN(25,   133),
+	MX31_PIN_SRXD6		= IOMUX_PIN(24,   134),
+	MX31_PIN_STXD6		= IOMUX_PIN(23,   135),
+	MX31_PIN_SFS5		= IOMUX_PIN(0xff, 136),
+	MX31_PIN_SCK5		= IOMUX_PIN(0xff, 137),
+	MX31_PIN_SRXD5		= IOMUX_PIN(22,   138),
+	MX31_PIN_STXD5		= IOMUX_PIN(21,   139),
+	MX31_PIN_SFS4		= IOMUX_PIN(0xff, 140),
+	MX31_PIN_SCK4		= IOMUX_PIN(0xff, 141),
+	MX31_PIN_SRXD4		= IOMUX_PIN(20,   142),
+	MX31_PIN_STXD4		= IOMUX_PIN(19,   143),
+	MX31_PIN_SFS3		= IOMUX_PIN(0xff, 144),
+	MX31_PIN_SCK3		= IOMUX_PIN(0xff, 145),
+	MX31_PIN_SRXD3		= IOMUX_PIN(18,   146),
+	MX31_PIN_STXD3		= IOMUX_PIN(17,   147),
+	MX31_PIN_I2C_DAT	= IOMUX_PIN(0xff, 148),
+	MX31_PIN_I2C_CLK	= IOMUX_PIN(0xff, 149),
+	MX31_PIN_CSI_PIXCLK	= IOMUX_PIN(83,   150),
+	MX31_PIN_CSI_HSYNC	= IOMUX_PIN(82,   151),
+	MX31_PIN_CSI_VSYNC	= IOMUX_PIN(81,   152),
+	MX31_PIN_CSI_MCLK	= IOMUX_PIN(80,   153),
+	MX31_PIN_CSI_D15	= IOMUX_PIN(79,   154),
+	MX31_PIN_CSI_D14	= IOMUX_PIN(78,   155),
+	MX31_PIN_CSI_D13	= IOMUX_PIN(77,   156),
+	MX31_PIN_CSI_D12	= IOMUX_PIN(76,   157),
+	MX31_PIN_CSI_D11	= IOMUX_PIN(75,   158),
+	MX31_PIN_CSI_D10	= IOMUX_PIN(74,   159),
+	MX31_PIN_CSI_D9		= IOMUX_PIN(73,   160),
+	MX31_PIN_CSI_D8		= IOMUX_PIN(72,   161),
+	MX31_PIN_CSI_D7		= IOMUX_PIN(71,   162),
+	MX31_PIN_CSI_D6		= IOMUX_PIN(70,   163),
+	MX31_PIN_CSI_D5		= IOMUX_PIN(69,   164),
+	MX31_PIN_CSI_D4		= IOMUX_PIN(68,   165),
+	MX31_PIN_M_GRANT	= IOMUX_PIN(0xff, 166),
+	MX31_PIN_M_REQUEST	= IOMUX_PIN(0xff, 167),
+	MX31_PIN_PC_POE		= IOMUX_PIN(0xff, 168),
+	MX31_PIN_PC_RW_B	= IOMUX_PIN(0xff, 169),
+	MX31_PIN_IOIS16		= IOMUX_PIN(0xff, 170),
+	MX31_PIN_PC_RST		= IOMUX_PIN(0xff, 171),
+	MX31_PIN_PC_BVD2	= IOMUX_PIN(0xff, 172),
+	MX31_PIN_PC_BVD1	= IOMUX_PIN(0xff, 173),
+	MX31_PIN_PC_VS2		= IOMUX_PIN(0xff, 174),
+	MX31_PIN_PC_VS1		= IOMUX_PIN(0xff, 175),
+	MX31_PIN_PC_PWRON	= IOMUX_PIN(0xff, 176),
+	MX31_PIN_PC_READY	= IOMUX_PIN(0xff, 177),
+	MX31_PIN_PC_WAIT_B	= IOMUX_PIN(0xff, 178),
+	MX31_PIN_PC_CD2_B	= IOMUX_PIN(0xff, 179),
+	MX31_PIN_PC_CD1_B	= IOMUX_PIN(0xff, 180),
+	MX31_PIN_D0		= IOMUX_PIN(0xff, 181),
+	MX31_PIN_D1		= IOMUX_PIN(0xff, 182),
+	MX31_PIN_D2		= IOMUX_PIN(0xff, 183),
+	MX31_PIN_D3		= IOMUX_PIN(0xff, 184),
+	MX31_PIN_D4		= IOMUX_PIN(0xff, 185),
+	MX31_PIN_D5		= IOMUX_PIN(0xff, 186),
+	MX31_PIN_D6		= IOMUX_PIN(0xff, 187),
+	MX31_PIN_D7		= IOMUX_PIN(0xff, 188),
+	MX31_PIN_D8		= IOMUX_PIN(0xff, 189),
+	MX31_PIN_D9		= IOMUX_PIN(0xff, 190),
+	MX31_PIN_D10		= IOMUX_PIN(0xff, 191),
+	MX31_PIN_D11		= IOMUX_PIN(0xff, 192),
+	MX31_PIN_D12		= IOMUX_PIN(0xff, 193),
+	MX31_PIN_D13		= IOMUX_PIN(0xff, 194),
+	MX31_PIN_D14		= IOMUX_PIN(0xff, 195),
+	MX31_PIN_D15		= IOMUX_PIN(0xff, 196),
+	MX31_PIN_NFRB		= IOMUX_PIN(16,   197),
+	MX31_PIN_NFCE_B		= IOMUX_PIN(15,   198),
+	MX31_PIN_NFWP_B		= IOMUX_PIN(14,   199),
+	MX31_PIN_NFCLE		= IOMUX_PIN(13,   200),
+	MX31_PIN_NFALE		= IOMUX_PIN(12,   201),
+	MX31_PIN_NFRE_B		= IOMUX_PIN(11,   202),
+	MX31_PIN_NFWE_B		= IOMUX_PIN(10,   203),
+	MX31_PIN_SDQS3		= IOMUX_PIN(0xff, 204),
+	MX31_PIN_SDQS2		= IOMUX_PIN(0xff, 205),
+	MX31_PIN_SDQS1		= IOMUX_PIN(0xff, 206),
+	MX31_PIN_SDQS0		= IOMUX_PIN(0xff, 207),
+	MX31_PIN_SDCLK_B	= IOMUX_PIN(0xff, 208),
+	MX31_PIN_SDCLK		= IOMUX_PIN(0xff, 209),
+	MX31_PIN_SDCKE1		= IOMUX_PIN(0xff, 210),
+	MX31_PIN_SDCKE0		= IOMUX_PIN(0xff, 211),
+	MX31_PIN_SDWE		= IOMUX_PIN(0xff, 212),
+	MX31_PIN_CAS		= IOMUX_PIN(0xff, 213),
+	MX31_PIN_RAS		= IOMUX_PIN(0xff, 214),
+	MX31_PIN_RW		= IOMUX_PIN(0xff, 215),
+	MX31_PIN_BCLK		= IOMUX_PIN(0xff, 216),
+	MX31_PIN_LBA		= IOMUX_PIN(0xff, 217),
+	MX31_PIN_ECB		= IOMUX_PIN(0xff, 218),
+	MX31_PIN_CS5		= IOMUX_PIN(0xff, 219),
+	MX31_PIN_CS4		= IOMUX_PIN(0xff, 220),
+	MX31_PIN_CS3		= IOMUX_PIN(0xff, 221),
+	MX31_PIN_CS2		= IOMUX_PIN(0xff, 222),
+	MX31_PIN_CS1		= IOMUX_PIN(0xff, 223),
+	MX31_PIN_CS0		= IOMUX_PIN(0xff, 224),
+	MX31_PIN_OE		= IOMUX_PIN(0xff, 225),
+	MX31_PIN_EB1		= IOMUX_PIN(0xff, 226),
+	MX31_PIN_EB0		= IOMUX_PIN(0xff, 227),
+	MX31_PIN_DQM3		= IOMUX_PIN(0xff, 228),
+	MX31_PIN_DQM2		= IOMUX_PIN(0xff, 229),
+	MX31_PIN_DQM1		= IOMUX_PIN(0xff, 230),
+	MX31_PIN_DQM0		= IOMUX_PIN(0xff, 231),
+	MX31_PIN_SD31		= IOMUX_PIN(0xff, 232),
+	MX31_PIN_SD30		= IOMUX_PIN(0xff, 233),
+	MX31_PIN_SD29		= IOMUX_PIN(0xff, 234),
+	MX31_PIN_SD28		= IOMUX_PIN(0xff, 235),
+	MX31_PIN_SD27		= IOMUX_PIN(0xff, 236),
+	MX31_PIN_SD26		= IOMUX_PIN(0xff, 237),
+	MX31_PIN_SD25		= IOMUX_PIN(0xff, 238),
+	MX31_PIN_SD24		= IOMUX_PIN(0xff, 239),
+	MX31_PIN_SD23		= IOMUX_PIN(0xff, 240),
+	MX31_PIN_SD22		= IOMUX_PIN(0xff, 241),
+	MX31_PIN_SD21		= IOMUX_PIN(0xff, 242),
+	MX31_PIN_SD20		= IOMUX_PIN(0xff, 243),
+	MX31_PIN_SD19		= IOMUX_PIN(0xff, 244),
+	MX31_PIN_SD18		= IOMUX_PIN(0xff, 245),
+	MX31_PIN_SD17		= IOMUX_PIN(0xff, 246),
+	MX31_PIN_SD16		= IOMUX_PIN(0xff, 247),
+	MX31_PIN_SD15		= IOMUX_PIN(0xff, 248),
+	MX31_PIN_SD14		= IOMUX_PIN(0xff, 249),
+	MX31_PIN_SD13		= IOMUX_PIN(0xff, 250),
+	MX31_PIN_SD12		= IOMUX_PIN(0xff, 251),
+	MX31_PIN_SD11		= IOMUX_PIN(0xff, 252),
+	MX31_PIN_SD10		= IOMUX_PIN(0xff, 253),
+	MX31_PIN_SD9		= IOMUX_PIN(0xff, 254),
+	MX31_PIN_SD8		= IOMUX_PIN(0xff, 255),
+	MX31_PIN_SD7		= IOMUX_PIN(0xff, 256),
+	MX31_PIN_SD6		= IOMUX_PIN(0xff, 257),
+	MX31_PIN_SD5		= IOMUX_PIN(0xff, 258),
+	MX31_PIN_SD4		= IOMUX_PIN(0xff, 259),
+	MX31_PIN_SD3		= IOMUX_PIN(0xff, 260),
+	MX31_PIN_SD2		= IOMUX_PIN(0xff, 261),
+	MX31_PIN_SD1		= IOMUX_PIN(0xff, 262),
+	MX31_PIN_SD0		= IOMUX_PIN(0xff, 263),
+	MX31_PIN_SDBA0		= IOMUX_PIN(0xff, 264),
+	MX31_PIN_SDBA1		= IOMUX_PIN(0xff, 265),
+	MX31_PIN_A25		= IOMUX_PIN(0xff, 266),
+	MX31_PIN_A24		= IOMUX_PIN(0xff, 267),
+	MX31_PIN_A23		= IOMUX_PIN(0xff, 268),
+	MX31_PIN_A22		= IOMUX_PIN(0xff, 269),
+	MX31_PIN_A21		= IOMUX_PIN(0xff, 270),
+	MX31_PIN_A20		= IOMUX_PIN(0xff, 271),
+	MX31_PIN_A19		= IOMUX_PIN(0xff, 272),
+	MX31_PIN_A18		= IOMUX_PIN(0xff, 273),
+	MX31_PIN_A17		= IOMUX_PIN(0xff, 274),
+	MX31_PIN_A16		= IOMUX_PIN(0xff, 275),
+	MX31_PIN_A14		= IOMUX_PIN(0xff, 276),
+	MX31_PIN_A15		= IOMUX_PIN(0xff, 277),
+	MX31_PIN_A13		= IOMUX_PIN(0xff, 278),
+	MX31_PIN_A12		= IOMUX_PIN(0xff, 279),
+	MX31_PIN_A11		= IOMUX_PIN(0xff, 280),
+	MX31_PIN_MA10		= IOMUX_PIN(0xff, 281),
+	MX31_PIN_A10		= IOMUX_PIN(0xff, 282),
+	MX31_PIN_A9		= IOMUX_PIN(0xff, 283),
+	MX31_PIN_A8		= IOMUX_PIN(0xff, 284),
+	MX31_PIN_A7		= IOMUX_PIN(0xff, 285),
+	MX31_PIN_A6		= IOMUX_PIN(0xff, 286),
+	MX31_PIN_A5		= IOMUX_PIN(0xff, 287),
+	MX31_PIN_A4		= IOMUX_PIN(0xff, 288),
+	MX31_PIN_A3		= IOMUX_PIN(0xff, 289),
+	MX31_PIN_A2		= IOMUX_PIN(0xff, 290),
+	MX31_PIN_A1		= IOMUX_PIN(0xff, 291),
+	MX31_PIN_A0		= IOMUX_PIN(0xff, 292),
+	MX31_PIN_VPG1		= IOMUX_PIN(0xff, 293),
+	MX31_PIN_VPG0		= IOMUX_PIN(0xff, 294),
+	MX31_PIN_DVFS1		= IOMUX_PIN(0xff, 295),
+	MX31_PIN_DVFS0		= IOMUX_PIN(0xff, 296),
+	MX31_PIN_VSTBY		= IOMUX_PIN(0xff, 297),
+	MX31_PIN_POWER_FAIL	= IOMUX_PIN(0xff, 298),
+	MX31_PIN_CKIL		= IOMUX_PIN(0xff, 299),
+	MX31_PIN_BOOT_MODE4	= IOMUX_PIN(0xff, 300),
+	MX31_PIN_BOOT_MODE3	= IOMUX_PIN(0xff, 301),
+	MX31_PIN_BOOT_MODE2	= IOMUX_PIN(0xff, 302),
+	MX31_PIN_BOOT_MODE1	= IOMUX_PIN(0xff, 303),
+	MX31_PIN_BOOT_MODE0	= IOMUX_PIN(0xff, 304),
+	MX31_PIN_CLKO		= IOMUX_PIN(0xff, 305),
+	MX31_PIN_POR_B		= IOMUX_PIN(0xff, 306),
+	MX31_PIN_RESET_IN_B	= IOMUX_PIN(0xff, 307),
+	MX31_PIN_CKIH		= IOMUX_PIN(0xff, 308),
+	MX31_PIN_SIMPD0		= IOMUX_PIN(35,   309),
+	MX31_PIN_SRX0		= IOMUX_PIN(34,   310),
+	MX31_PIN_STX0		= IOMUX_PIN(33,   311),
+	MX31_PIN_SVEN0		= IOMUX_PIN(32,   312),
+	MX31_PIN_SRST0		= IOMUX_PIN(67,   313),
+	MX31_PIN_SCLK0		= IOMUX_PIN(66,   314),
+	MX31_PIN_GPIO3_1	= IOMUX_PIN(65,   315),
+	MX31_PIN_GPIO3_0	= IOMUX_PIN(64,   316),
+	MX31_PIN_GPIO1_6	= IOMUX_PIN( 6,   317),
+	MX31_PIN_GPIO1_5	= IOMUX_PIN( 5,   318),
+	MX31_PIN_GPIO1_4	= IOMUX_PIN( 4,   319),
+	MX31_PIN_GPIO1_3	= IOMUX_PIN( 3,   320),
+	MX31_PIN_GPIO1_2	= IOMUX_PIN( 2,   321),
+	MX31_PIN_GPIO1_1	= IOMUX_PIN( 1,   322),
+	MX31_PIN_GPIO1_0	= IOMUX_PIN( 0,   323),
+	MX31_PIN_PWMO		= IOMUX_PIN( 9,   324),
+	MX31_PIN_WATCHDOG_RST	= IOMUX_PIN(0xff, 325),
+	MX31_PIN_COMPARE	= IOMUX_PIN( 8,   326),
+	MX31_PIN_CAPTURE	= IOMUX_PIN( 7,   327),
+};
+
+#define PIN_MAX 327
+#define NB_PORTS 12 /* NB_PINS/32, we chose 32 pins per "PORT" */
+
+/*
+ * Convenience values for use with mxc_iomux_mode()
+ *
+ * Format here is MX31_PIN_(pin name)__(function)
+ */
+#define MX31_PIN_CSPI3_MOSI__RXD3	IOMUX_MODE(MX31_PIN_CSPI3_MOSI, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI3_MISO__TXD3	IOMUX_MODE(MX31_PIN_CSPI3_MISO, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI3_SCLK__RTS3	IOMUX_MODE(MX31_PIN_CSPI3_SCLK, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI3_SPI_RDY__CTS3	IOMUX_MODE(MX31_PIN_CSPI3_SPI_RDY, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CTS1__CTS1		IOMUX_MODE(MX31_PIN_CTS1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_RTS1__RTS1		IOMUX_MODE(MX31_PIN_RTS1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_RTS1__SFS		IOMUX_MODE(MX31_PIN_RTS1, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_TXD1__TXD1		IOMUX_MODE(MX31_PIN_TXD1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_TXD1__SCK		IOMUX_MODE(MX31_PIN_TXD1, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_RXD1__RXD1		IOMUX_MODE(MX31_PIN_RXD1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_RXD1__STXDA		IOMUX_MODE(MX31_PIN_RXD1, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_DCD_DCE1__DCD_DCE1	IOMUX_MODE(MX31_PIN_DCD_DCE1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_RI_DCE1__RI_DCE1	IOMUX_MODE(MX31_PIN_RI_DCE1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_DSR_DCE1__DSR_DCE1	IOMUX_MODE(MX31_PIN_DSR_DCE1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_DTR_DCE1__DTR_DCE1	IOMUX_MODE(MX31_PIN_DTR_DCE1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_DTR_DCE1__SRXDA	IOMUX_MODE(MX31_PIN_DTR_DCE1, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_CTS2__CTS2		IOMUX_MODE(MX31_PIN_CTS2, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_RTS2__RTS2		IOMUX_MODE(MX31_PIN_RTS2, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_TXD2__TXD2		IOMUX_MODE(MX31_PIN_TXD2, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_RXD2__RXD2		IOMUX_MODE(MX31_PIN_RXD2, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_DCD_DTE1__DCD_DTE2	IOMUX_MODE(MX31_PIN_DCD_DTE1, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_RI_DTE1__RI_DTE2	IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_DSR_DTE1__DSR_DTE2	IOMUX_MODE(MX31_PIN_DSR_DTE1, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_DTR_DTE1__DTR_DTE2	IOMUX_MODE(MX31_PIN_DTR_DTE1, IOMUX_OCONFIG_ALT3 | IOMUX_ICONFIG_NONE)
+#define MX31_PIN_PC_RST__CTS5		IOMUX_MODE(MX31_PIN_PC_RST, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_PC_VS2__RTS5		IOMUX_MODE(MX31_PIN_PC_VS2, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_PC_BVD2__TXD5		IOMUX_MODE(MX31_PIN_PC_BVD2, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_PC_BVD1__RXD5		IOMUX_MODE(MX31_PIN_PC_BVD1, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_CSPI1_MOSI__MOSI	IOMUX_MODE(MX31_PIN_CSPI1_MOSI, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI1_MISO__MISO	IOMUX_MODE(MX31_PIN_CSPI1_MISO, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI1_SCLK__SCLK	IOMUX_MODE(MX31_PIN_CSPI1_SCLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI1_SPI_RDY__SPI_RDY	IOMUX_MODE(MX31_PIN_CSPI1_SPI_RDY, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI1_SS0__SS0		IOMUX_MODE(MX31_PIN_CSPI1_SS0, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI1_SS1__SS1		IOMUX_MODE(MX31_PIN_CSPI1_SS1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI1_SS2__SS2		IOMUX_MODE(MX31_PIN_CSPI1_SS2, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI2_MOSI__MOSI	IOMUX_MODE(MX31_PIN_CSPI2_MOSI, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI2_MOSI__SCL	IOMUX_MODE(MX31_PIN_CSPI2_MOSI, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI2_MISO__MISO	IOMUX_MODE(MX31_PIN_CSPI2_MISO, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI2_MISO__SDA	IOMUX_MODE(MX31_PIN_CSPI2_MISO, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI2_SCLK__SCLK	IOMUX_MODE(MX31_PIN_CSPI2_SCLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI2_SPI_RDY__SPI_RDY	IOMUX_MODE(MX31_PIN_CSPI2_SPI_RDY, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI2_SS0__SS0		IOMUX_MODE(MX31_PIN_CSPI2_SS0, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI2_SS1__SS1		IOMUX_MODE(MX31_PIN_CSPI2_SS1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI2_SS2__SS2		IOMUX_MODE(MX31_PIN_CSPI2_SS2, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI3_MOSI__MOSI	IOMUX_MODE(MX31_PIN_CSPI3_MOSI, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI3_MISO__MISO	IOMUX_MODE(MX31_PIN_CSPI3_MISO, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI3_SCLK__SCLK	IOMUX_MODE(MX31_PIN_CSPI3_SCLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI3_SPI_RDY__SPI_RDY	IOMUX_MODE(MX31_PIN_CSPI3_SPI_RDY, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_BATT_LINE__OWIRE	IOMUX_MODE(MX31_PIN_BATT_LINE, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CS4__CS4		IOMUX_MODE(MX31_PIN_CS4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SD1_DATA3__SD1_DATA3	IOMUX_MODE(MX31_PIN_SD1_DATA3, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SD1_DATA2__SD1_DATA2	IOMUX_MODE(MX31_PIN_SD1_DATA2, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SD1_DATA1__SD1_DATA1	IOMUX_MODE(MX31_PIN_SD1_DATA1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SD1_DATA0__SD1_DATA0	IOMUX_MODE(MX31_PIN_SD1_DATA0, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SD1_CLK__SD1_CLK	IOMUX_MODE(MX31_PIN_SD1_CLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SD1_CMD__SD1_CMD	IOMUX_MODE(MX31_PIN_SD1_CMD, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_ATA_CS0__GPIO3_26	IOMUX_MODE(MX31_PIN_ATA_CS0, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_ATA_CS1__GPIO3_27	IOMUX_MODE(MX31_PIN_ATA_CS1, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_PC_PWRON__SD2_DATA3	IOMUX_MODE(MX31_PIN_PC_PWRON, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_VS1__SD2_DATA2	IOMUX_MODE(MX31_PIN_PC_VS1, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_READY__SD2_DATA1	IOMUX_MODE(MX31_PIN_PC_READY, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_WAIT_B__SD2_DATA0	IOMUX_MODE(MX31_PIN_PC_WAIT_B, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_CD2_B__SD2_CLK	IOMUX_MODE(MX31_PIN_PC_CD2_B, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_CD1_B__SD2_CMD	IOMUX_MODE(MX31_PIN_PC_CD1_B, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_ATA_DIOR__GPIO3_28	IOMUX_MODE(MX31_PIN_ATA_DIOR, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_ATA_DIOW__GPIO3_29	IOMUX_MODE(MX31_PIN_ATA_DIOW, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_LD0__LD0		IOMUX_MODE(MX31_PIN_LD0, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD1__LD1		IOMUX_MODE(MX31_PIN_LD1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD2__LD2		IOMUX_MODE(MX31_PIN_LD2, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD3__LD3		IOMUX_MODE(MX31_PIN_LD3, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD4__LD4		IOMUX_MODE(MX31_PIN_LD4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD5__LD5		IOMUX_MODE(MX31_PIN_LD5, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD6__LD6		IOMUX_MODE(MX31_PIN_LD6, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD7__LD7		IOMUX_MODE(MX31_PIN_LD7, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD8__LD8		IOMUX_MODE(MX31_PIN_LD8, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD9__LD9		IOMUX_MODE(MX31_PIN_LD9, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD10__LD10		IOMUX_MODE(MX31_PIN_LD10, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD11__LD11		IOMUX_MODE(MX31_PIN_LD11, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD12__LD12		IOMUX_MODE(MX31_PIN_LD12, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD13__LD13		IOMUX_MODE(MX31_PIN_LD13, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD14__LD14		IOMUX_MODE(MX31_PIN_LD14, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD15__LD15		IOMUX_MODE(MX31_PIN_LD15, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD16__LD16		IOMUX_MODE(MX31_PIN_LD16, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD17__LD17		IOMUX_MODE(MX31_PIN_LD17, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_VSYNC3__VSYNC3		IOMUX_MODE(MX31_PIN_VSYNC3, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_HSYNC__HSYNC		IOMUX_MODE(MX31_PIN_HSYNC, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_FPSHIFT__FPSHIFT	IOMUX_MODE(MX31_PIN_FPSHIFT, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_DRDY0__DRDY0		IOMUX_MODE(MX31_PIN_DRDY0, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_D3_REV__D3_REV		IOMUX_MODE(MX31_PIN_D3_REV, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CONTRAST__CONTRAST	IOMUX_MODE(MX31_PIN_CONTRAST, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_D3_SPL__D3_SPL		IOMUX_MODE(MX31_PIN_D3_SPL, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_D3_CLS__D3_CLS		IOMUX_MODE(MX31_PIN_D3_CLS, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LCS0__GPI03_23		IOMUX_MODE(MX31_PIN_LCS0, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_GPIO1_1__GPIO          IOMUX_MODE(MX31_PIN_GPIO1_1, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_I2C_CLK__SCL		IOMUX_MODE(MX31_PIN_I2C_CLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_I2C_DAT__SDA		IOMUX_MODE(MX31_PIN_I2C_DAT, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_DCD_DTE1__I2C2_SDA	IOMUX_MODE(MX31_PIN_DCD_DTE1, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_RI_DTE1__I2C2_SCL	IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_CSPI2_SS2__I2C3_SDA	IOMUX_MODE(MX31_PIN_CSPI2_SS2, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI2_SCLK__I2C3_SCL	IOMUX_MODE(MX31_PIN_CSPI2_SCLK, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSI_D4__CSI_D4		IOMUX_MODE(MX31_PIN_CSI_D4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D5__CSI_D5		IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D6__CSI_D6		IOMUX_MODE(MX31_PIN_CSI_D6, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D7__CSI_D7		IOMUX_MODE(MX31_PIN_CSI_D7, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D8__CSI_D8		IOMUX_MODE(MX31_PIN_CSI_D8, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D9__CSI_D9		IOMUX_MODE(MX31_PIN_CSI_D9, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D10__CSI_D10	IOMUX_MODE(MX31_PIN_CSI_D10, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D11__CSI_D11	IOMUX_MODE(MX31_PIN_CSI_D11, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D12__CSI_D12	IOMUX_MODE(MX31_PIN_CSI_D12, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D13__CSI_D13	IOMUX_MODE(MX31_PIN_CSI_D13, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D14__CSI_D14	IOMUX_MODE(MX31_PIN_CSI_D14, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D15__CSI_D15	IOMUX_MODE(MX31_PIN_CSI_D15, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_HSYNC__CSI_HSYNC	IOMUX_MODE(MX31_PIN_CSI_HSYNC, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_MCLK__CSI_MCLK	IOMUX_MODE(MX31_PIN_CSI_MCLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_PIXCLK__CSI_PIXCLK	IOMUX_MODE(MX31_PIN_CSI_PIXCLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_VSYNC__CSI_VSYNC	IOMUX_MODE(MX31_PIN_CSI_VSYNC, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_GPIO3_0__GPIO3_0	IOMUX_MODE(MX31_PIN_GPIO3_0, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_GPIO3_1__GPIO3_1	IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_TXD2__GPIO1_28		IOMUX_MODE(MX31_PIN_TXD2, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_CSI_D4__GPIO3_4	IOMUX_MODE(MX31_PIN_CSI_D4, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_CSI_D5__GPIO3_5	IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_USBOTG_DATA0__USBOTG_DATA0	IOMUX_MODE(MX31_PIN_USBOTG_DATA0, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA1__USBOTG_DATA1	IOMUX_MODE(MX31_PIN_USBOTG_DATA1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA2__USBOTG_DATA2	IOMUX_MODE(MX31_PIN_USBOTG_DATA2, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA3__USBOTG_DATA3	IOMUX_MODE(MX31_PIN_USBOTG_DATA3, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA4__USBOTG_DATA4	IOMUX_MODE(MX31_PIN_USBOTG_DATA4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA5__USBOTG_DATA5	IOMUX_MODE(MX31_PIN_USBOTG_DATA5, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA6__USBOTG_DATA6	IOMUX_MODE(MX31_PIN_USBOTG_DATA6, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA7__USBOTG_DATA7	IOMUX_MODE(MX31_PIN_USBOTG_DATA7, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_CLK__USBOTG_CLK		IOMUX_MODE(MX31_PIN_USBOTG_CLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DIR__USBOTG_DIR		IOMUX_MODE(MX31_PIN_USBOTG_DIR, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_NXT__USBOTG_NXT		IOMUX_MODE(MX31_PIN_USBOTG_NXT, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_STP__USBOTG_STP		IOMUX_MODE(MX31_PIN_USBOTG_STP, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI1_MOSI__USBH1_RXDM		IOMUX_MODE(MX31_PIN_CSPI1_MOSI, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI1_MISO__USBH1_RXDP		IOMUX_MODE(MX31_PIN_CSPI1_MISO, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI1_SS0__USBH1_TXDM		IOMUX_MODE(MX31_PIN_CSPI1_SS0, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI1_SS1__USBH1_TXDP		IOMUX_MODE(MX31_PIN_CSPI1_SS1, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI1_SS2__USBH1_RCV		IOMUX_MODE(MX31_PIN_CSPI1_SS2, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI1_SCLK__USBH1_OEB		IOMUX_MODE(MX31_PIN_CSPI1_SCLK, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI1_SPI_RDY__USBH1_FS	IOMUX_MODE(MX31_PIN_CSPI1_SPI_RDY, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_SFS6__USBH1_SUSPEND	IOMUX_MODE(MX31_PIN_SFS6, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_NFRE_B__GPIO1_11	IOMUX_MODE(MX31_PIN_NFRE_B, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_NFALE__GPIO1_12	IOMUX_MODE(MX31_PIN_NFALE, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_USBH2_DATA0__USBH2_DATA0	IOMUX_MODE(MX31_PIN_USBH2_DATA0, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBH2_DATA1__USBH2_DATA1	IOMUX_MODE(MX31_PIN_USBH2_DATA1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_STXD3__USBH2_DATA2	IOMUX_MODE(MX31_PIN_STXD3, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SRXD3__USBH2_DATA3	IOMUX_MODE(MX31_PIN_SRXD3, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SCK3__USBH2_DATA4	IOMUX_MODE(MX31_PIN_SCK3, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SFS3__USBH2_DATA5	IOMUX_MODE(MX31_PIN_SFS3, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_STXD6__USBH2_DATA6	IOMUX_MODE(MX31_PIN_STXD6, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SRXD6__USBH2_DATA7	IOMUX_MODE(MX31_PIN_SRXD6, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBH2_CLK__USBH2_CLK		IOMUX_MODE(MX31_PIN_USBH2_CLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBH2_DIR__USBH2_DIR		IOMUX_MODE(MX31_PIN_USBH2_DIR, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBH2_NXT__USBH2_NXT		IOMUX_MODE(MX31_PIN_USBH2_NXT, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBH2_STP__USBH2_STP		IOMUX_MODE(MX31_PIN_USBH2_STP, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SCK6__GPIO1_25		IOMUX_MODE(MX31_PIN_SCK6, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_USB_OC__GPIO1_30	IOMUX_MODE(MX31_PIN_USB_OC, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_I2C_DAT__I2C1_SDA	IOMUX_MODE(MX31_PIN_I2C_DAT, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_I2C_CLK__I2C1_SCL	IOMUX_MODE(MX31_PIN_I2C_CLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_DCD_DTE1__I2C2_SDA	IOMUX_MODE(MX31_PIN_DCD_DTE1, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_RI_DTE1__I2C2_SCL	IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_ATA_CS0__GPIO3_26	IOMUX_MODE(MX31_PIN_ATA_CS0, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_ATA_CS1__GPIO3_27	IOMUX_MODE(MX31_PIN_ATA_CS1, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_PC_PWRON__SD2_DATA3	IOMUX_MODE(MX31_PIN_PC_PWRON, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_VS1__SD2_DATA2	IOMUX_MODE(MX31_PIN_PC_VS1, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_READY__SD2_DATA1	IOMUX_MODE(MX31_PIN_PC_READY, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_WAIT_B__SD2_DATA0	IOMUX_MODE(MX31_PIN_PC_WAIT_B, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_CD2_B__SD2_CLK	IOMUX_MODE(MX31_PIN_PC_CD2_B, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_CD1_B__SD2_CMD	IOMUX_MODE(MX31_PIN_PC_CD1_B, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_ATA_DIOR__GPIO3_28	IOMUX_MODE(MX31_PIN_ATA_DIOR, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_ATA_DIOW__GPIO3_29	IOMUX_MODE(MX31_PIN_ATA_DIOW, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_CSI_D4__CSI_D4		IOMUX_MODE(MX31_PIN_CSI_D4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D5__CSI_D5		IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D6__CSI_D6		IOMUX_MODE(MX31_PIN_CSI_D6, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D7__CSI_D7		IOMUX_MODE(MX31_PIN_CSI_D7, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D8__CSI_D8		IOMUX_MODE(MX31_PIN_CSI_D8, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D9__CSI_D9		IOMUX_MODE(MX31_PIN_CSI_D9, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D10__CSI_D10	IOMUX_MODE(MX31_PIN_CSI_D10, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D11__CSI_D11	IOMUX_MODE(MX31_PIN_CSI_D11, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D12__CSI_D12	IOMUX_MODE(MX31_PIN_CSI_D12, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D13__CSI_D13	IOMUX_MODE(MX31_PIN_CSI_D13, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D14__CSI_D14	IOMUX_MODE(MX31_PIN_CSI_D14, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D15__CSI_D15	IOMUX_MODE(MX31_PIN_CSI_D15, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_HSYNC__CSI_HSYNC	IOMUX_MODE(MX31_PIN_CSI_HSYNC, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_MCLK__CSI_MCLK	IOMUX_MODE(MX31_PIN_CSI_MCLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_PIXCLK__CSI_PIXCLK	IOMUX_MODE(MX31_PIN_CSI_PIXCLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_VSYNC__CSI_VSYNC	IOMUX_MODE(MX31_PIN_CSI_VSYNC, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_GPIO3_0__GPIO3_0	IOMUX_MODE(MX31_PIN_GPIO3_0, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_GPIO3_1__GPIO3_1	IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_TXD2__GPIO1_28		IOMUX_MODE(MX31_PIN_TXD2, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_GPIO1_0__GPIO1_0	IOMUX_MODE(MX31_PIN_GPIO1_0, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_SVEN0__GPIO2_0		IOMUX_MODE(MX31_PIN_SVEN0, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_STX0__GPIO2_1		IOMUX_MODE(MX31_PIN_STX0, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_SRX0__GPIO2_2		IOMUX_MODE(MX31_PIN_SRX0, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_SIMPD0__GPIO2_3	IOMUX_MODE(MX31_PIN_SIMPD0, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_DTR_DCE1__GPIO2_8	IOMUX_MODE(MX31_PIN_DTR_DCE1, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_DSR_DCE1__GPIO2_9	IOMUX_MODE(MX31_PIN_DSR_DCE1, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_RI_DCE1__GPIO2_10	IOMUX_MODE(MX31_PIN_RI_DCE1, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_DCD_DCE1__GPIO2_11	IOMUX_MODE(MX31_PIN_DCD_DCE1, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_STXD5__GPIO1_21	IOMUX_MODE(MX31_PIN_STXD5, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_SRXD5__GPIO1_22	IOMUX_MODE(MX31_PIN_SRXD5, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_GPIO1_3__GPIO1_3	IOMUX_MODE(MX31_PIN_GPIO1_3, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_CSPI2_SS1__CSPI3_SS1	IOMUX_MODE(MX31_PIN_CSPI2_SS1, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_RTS1__GPIO2_6		IOMUX_MODE(MX31_PIN_RTS1, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_CTS1__GPIO2_7		IOMUX_MODE(MX31_PIN_CTS1, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_LCS0__GPIO3_23		IOMUX_MODE(MX31_PIN_LCS0, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_STXD4__STXD4		IOMUX_MODE(MX31_PIN_STXD4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SRXD4__SRXD4		IOMUX_MODE(MX31_PIN_SRXD4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SCK4__SCK4		IOMUX_MODE(MX31_PIN_SCK4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SFS4__SFS4		IOMUX_MODE(MX31_PIN_SFS4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_STXD5__STXD5		IOMUX_MODE(MX31_PIN_STXD5, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SRXD5__SRXD5		IOMUX_MODE(MX31_PIN_SRXD5, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SCK5__SCK5		IOMUX_MODE(MX31_PIN_SCK5, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_SFS5__SFS5		IOMUX_MODE(MX31_PIN_SFS5, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_ROW0_KEY_ROW0	IOMUX_MODE(MX31_PIN_KEY_ROW0, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_ROW1_KEY_ROW1	IOMUX_MODE(MX31_PIN_KEY_ROW1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_ROW2_KEY_ROW2	IOMUX_MODE(MX31_PIN_KEY_ROW2, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_ROW3_KEY_ROW3	IOMUX_MODE(MX31_PIN_KEY_ROW3, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_ROW4_KEY_ROW4	IOMUX_MODE(MX31_PIN_KEY_ROW4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_ROW4_GPIO		IOMUX_MODE(MX31_PIN_KEY_ROW4, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_KEY_ROW5_KEY_ROW5	IOMUX_MODE(MX31_PIN_KEY_ROW5, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_ROW6_KEY_ROW6	IOMUX_MODE(MX31_PIN_KEY_ROW6, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_ROW7_KEY_ROW7	IOMUX_MODE(MX31_PIN_KEY_ROW7, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_COL0_KEY_COL0	IOMUX_MODE(MX31_PIN_KEY_COL0, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_COL1_KEY_COL1	IOMUX_MODE(MX31_PIN_KEY_COL1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_COL2_KEY_COL2	IOMUX_MODE(MX31_PIN_KEY_COL2, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_COL3_KEY_COL3	IOMUX_MODE(MX31_PIN_KEY_COL3, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_COL4_KEY_COL4	IOMUX_MODE(MX31_PIN_KEY_COL4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_COL5_KEY_COL5	IOMUX_MODE(MX31_PIN_KEY_COL5, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_COL6_KEY_COL6	IOMUX_MODE(MX31_PIN_KEY_COL6, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_COL7_KEY_COL7	IOMUX_MODE(MX31_PIN_KEY_COL7, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_WATCHDOG_RST__WATCHDOG_RST	IOMUX_MODE(MX31_PIN_WATCHDOG_RST, IOMUX_CONFIG_FUNC)
+
+
+/*
+ * XXX: The SS0, SS1, SS2, SS3 lines of spi3 are multiplexed with cspi2_ss0,
+ * cspi2_ss1, cspi1_ss0 cspi1_ss1
+ */
+
+/*
+ * This function configures the pad value for a IOMUX pin.
+ */
+void mxc_iomux_set_pad(enum iomux_pins, u32);
+
+#endif /* ifndef __MACH_IOMUX_MX3_H__ */
diff --git a/arch/arm/mach-imx/iomux-mx35.h b/arch/arm/mach-imx/iomux-mx35.h
new file mode 100644
index 0000000..90bfa6b
--- /dev/null
+++ b/arch/arm/mach-imx/iomux-mx35.h
@@ -0,0 +1,1267 @@
+/*
+ * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH <armlinux@phytec.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option, NO_PAD_CTRL) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __MACH_IOMUX_MX35_H__
+#define __MACH_IOMUX_MX35_H__
+
+#include "iomux-v3.h"
+
+/*
+ * The naming convention for the pad modes is MX35_PAD_<padname>__<padmode>
+ * If <padname> or <padmode> refers to a GPIO, it is named
+ * GPIO_<unit>_<num> see also iomux-v3.h
+ */
+
+/*									  PAD    MUX   ALT INPSE PATH */
+#define MX35_PAD_CAPTURE__GPT_CAPIN1				IOMUX_PAD(0x328, 0x004, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CAPTURE__GPT_CMPOUT2				IOMUX_PAD(0x328, 0x004, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CAPTURE__CSPI2_SS1				IOMUX_PAD(0x328, 0x004, 2, 0x7f4, 0, NO_PAD_CTRL)
+#define MX35_PAD_CAPTURE__EPIT1_EPITO				IOMUX_PAD(0x328, 0x004, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CAPTURE__CCM_CLK32K				IOMUX_PAD(0x328, 0x004, 4, 0x7d0, 0, NO_PAD_CTRL)
+#define MX35_PAD_CAPTURE__GPIO1_4				IOMUX_PAD(0x328, 0x004, 5, 0x850, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_COMPARE__GPT_CMPOUT1				IOMUX_PAD(0x32c, 0x008, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_COMPARE__GPT_CAPIN2				IOMUX_PAD(0x32c, 0x008, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_COMPARE__GPT_CMPOUT3				IOMUX_PAD(0x32c, 0x008, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_COMPARE__EPIT2_EPITO				IOMUX_PAD(0x32c, 0x008, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_COMPARE__GPIO1_5				IOMUX_PAD(0x32c, 0x008, 5, 0x854, 0, NO_PAD_CTRL)
+#define MX35_PAD_COMPARE__SDMA_EXTDMA_2				IOMUX_PAD(0x32c, 0x008, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_WDOG_RST__WDOG_WDOG_B				IOMUX_PAD(0x330, 0x00c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_WDOG_RST__IPU_FLASH_STROBE			IOMUX_PAD(0x330, 0x00c, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_WDOG_RST__GPIO1_6				IOMUX_PAD(0x330, 0x00c, 5, 0x858, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_GPIO1_0__GPIO1_0				IOMUX_PAD(0x334, 0x010, 0, 0x82c, 0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO1_0__CCM_PMIC_RDY				IOMUX_PAD(0x334, 0x010, 1, 0x7d4, 0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO1_0__OWIRE_LINE				IOMUX_PAD(0x334, 0x010, 2, 0x990, 0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO1_0__SDMA_EXTDMA_0				IOMUX_PAD(0x334, 0x010, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_GPIO1_1__GPIO1_1				IOMUX_PAD(0x338, 0x014, 0, 0x838, 0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO1_1__PWM_PWMO				IOMUX_PAD(0x338, 0x014, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO1_1__CSPI1_SS2				IOMUX_PAD(0x338, 0x014, 3, 0x7d8, 0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO1_1__SCC_TAMPER_DETECT			IOMUX_PAD(0x338, 0x014, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO1_1__SDMA_EXTDMA_1				IOMUX_PAD(0x338, 0x014, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_GPIO2_0__GPIO2_0				IOMUX_PAD(0x33c, 0x018, 0, 0x868, 0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO2_0__USB_TOP_USBOTG_CLK			IOMUX_PAD(0x33c, 0x018, 1, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_GPIO3_0__GPIO3_0				IOMUX_PAD(0x340, 0x01c, 0, 0x8e8, 0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO3_0__USB_TOP_USBH2_CLK			IOMUX_PAD(0x340, 0x01c, 1, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_RESET_IN_B__CCM_RESET_IN_B			IOMUX_PAD(0x344, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_POR_B__CCM_POR_B				IOMUX_PAD(0x348, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CLKO__CCM_CLKO					IOMUX_PAD(0x34c, 0x020, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CLKO__GPIO1_8					IOMUX_PAD(0x34c, 0x020, 5, 0x860, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_BOOT_MODE0__CCM_BOOT_MODE_0			IOMUX_PAD(0x350, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_BOOT_MODE1__CCM_BOOT_MODE_1			IOMUX_PAD(0x354, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CLK_MODE0__CCM_CLK_MODE_0			IOMUX_PAD(0x358, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CLK_MODE1__CCM_CLK_MODE_1			IOMUX_PAD(0x35c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_POWER_FAIL__CCM_DSM_WAKEUP_INT_26		IOMUX_PAD(0x360, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_VSTBY__CCM_VSTBY				IOMUX_PAD(0x364, 0x024, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_VSTBY__GPIO1_7					IOMUX_PAD(0x364, 0x024, 5, 0x85c, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_A0__EMI_EIM_DA_L_0				IOMUX_PAD(0x368, 0x028, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A1__EMI_EIM_DA_L_1				IOMUX_PAD(0x36c, 0x02c, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A2__EMI_EIM_DA_L_2				IOMUX_PAD(0x370, 0x030, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A3__EMI_EIM_DA_L_3				IOMUX_PAD(0x374, 0x034, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A4__EMI_EIM_DA_L_4				IOMUX_PAD(0x378, 0x038, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A5__EMI_EIM_DA_L_5				IOMUX_PAD(0x37c, 0x03c, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A6__EMI_EIM_DA_L_6				IOMUX_PAD(0x380, 0x040, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A7__EMI_EIM_DA_L_7				IOMUX_PAD(0x384, 0x044, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A8__EMI_EIM_DA_H_8				IOMUX_PAD(0x388, 0x048, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A9__EMI_EIM_DA_H_9				IOMUX_PAD(0x38c, 0x04c, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A10__EMI_EIM_DA_H_10				IOMUX_PAD(0x390, 0x050, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_MA10__EMI_MA10					IOMUX_PAD(0x394, 0x054, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A11__EMI_EIM_DA_H_11				IOMUX_PAD(0x398, 0x058, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A12__EMI_EIM_DA_H_12				IOMUX_PAD(0x39c, 0x05c, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A13__EMI_EIM_DA_H_13				IOMUX_PAD(0x3a0, 0x060, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A14__EMI_EIM_DA_H2_14				IOMUX_PAD(0x3a4, 0x064, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A15__EMI_EIM_DA_H2_15				IOMUX_PAD(0x3a8, 0x068, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A16__EMI_EIM_A_16				IOMUX_PAD(0x3ac, 0x06c, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A17__EMI_EIM_A_17				IOMUX_PAD(0x3b0, 0x070, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A18__EMI_EIM_A_18				IOMUX_PAD(0x3b4, 0x074, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A19__EMI_EIM_A_19				IOMUX_PAD(0x3b8, 0x078, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A20__EMI_EIM_A_20				IOMUX_PAD(0x3bc, 0x07c, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A21__EMI_EIM_A_21				IOMUX_PAD(0x3c0, 0x080, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A22__EMI_EIM_A_22				IOMUX_PAD(0x3c4, 0x084, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A23__EMI_EIM_A_23				IOMUX_PAD(0x3c8, 0x088, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A24__EMI_EIM_A_24				IOMUX_PAD(0x3cc, 0x08c, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A25__EMI_EIM_A_25				IOMUX_PAD(0x3d0, 0x090, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDBA1__EMI_EIM_SDBA1				IOMUX_PAD(0x3d4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDBA0__EMI_EIM_SDBA0				IOMUX_PAD(0x3d8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD0__EMI_DRAM_D_0				IOMUX_PAD(0x3dc, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD1__EMI_DRAM_D_1				IOMUX_PAD(0x3e0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD2__EMI_DRAM_D_2				IOMUX_PAD(0x3e4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD3__EMI_DRAM_D_3				IOMUX_PAD(0x3e8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD4__EMI_DRAM_D_4				IOMUX_PAD(0x3ec, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD5__EMI_DRAM_D_5				IOMUX_PAD(0x3f0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD6__EMI_DRAM_D_6				IOMUX_PAD(0x3f4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD7__EMI_DRAM_D_7				IOMUX_PAD(0x3f8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD8__EMI_DRAM_D_8				IOMUX_PAD(0x3fc, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD9__EMI_DRAM_D_9				IOMUX_PAD(0x400, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD10__EMI_DRAM_D_10				IOMUX_PAD(0x404, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD11__EMI_DRAM_D_11				IOMUX_PAD(0x408, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD12__EMI_DRAM_D_12				IOMUX_PAD(0x40c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD13__EMI_DRAM_D_13				IOMUX_PAD(0x410, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD14__EMI_DRAM_D_14				IOMUX_PAD(0x414, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD15__EMI_DRAM_D_15				IOMUX_PAD(0x418, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD16__EMI_DRAM_D_16				IOMUX_PAD(0x41c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD17__EMI_DRAM_D_17				IOMUX_PAD(0x420, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD18__EMI_DRAM_D_18				IOMUX_PAD(0x424, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD19__EMI_DRAM_D_19				IOMUX_PAD(0x428, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD20__EMI_DRAM_D_20				IOMUX_PAD(0x42c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD21__EMI_DRAM_D_21				IOMUX_PAD(0x430, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD22__EMI_DRAM_D_22				IOMUX_PAD(0x434, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD23__EMI_DRAM_D_23				IOMUX_PAD(0x438, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD24__EMI_DRAM_D_24				IOMUX_PAD(0x43c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD25__EMI_DRAM_D_25				IOMUX_PAD(0x440, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD26__EMI_DRAM_D_26				IOMUX_PAD(0x444, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD27__EMI_DRAM_D_27				IOMUX_PAD(0x448, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD28__EMI_DRAM_D_28				IOMUX_PAD(0x44c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD29__EMI_DRAM_D_29				IOMUX_PAD(0x450, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD30__EMI_DRAM_D_30				IOMUX_PAD(0x454, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD31__EMI_DRAM_D_31				IOMUX_PAD(0x458, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_DQM0__EMI_DRAM_DQM_0				IOMUX_PAD(0x45c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_DQM1__EMI_DRAM_DQM_1				IOMUX_PAD(0x460, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_DQM2__EMI_DRAM_DQM_2				IOMUX_PAD(0x464, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_DQM3__EMI_DRAM_DQM_3				IOMUX_PAD(0x468, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_EB0__EMI_EIM_EB0_B				IOMUX_PAD(0x46c, 0x094, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_EB1__EMI_EIM_EB1_B				IOMUX_PAD(0x470, 0x098, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_OE__EMI_EIM_OE					IOMUX_PAD(0x474, 0x09c, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CS0__EMI_EIM_CS0				IOMUX_PAD(0x478, 0x0a0, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CS1__EMI_EIM_CS1				IOMUX_PAD(0x47c, 0x0a4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CS1__EMI_NANDF_CE3				IOMUX_PAD(0x47c, 0x0a4, 3, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CS2__EMI_EIM_CS2				IOMUX_PAD(0x480, 0x0a8, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CS3__EMI_EIM_CS3				IOMUX_PAD(0x484, 0x0ac, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CS4__EMI_EIM_CS4				IOMUX_PAD(0x488, 0x0b0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CS4__EMI_DTACK_B				IOMUX_PAD(0x488, 0x0b0, 1, 0x800, 0, NO_PAD_CTRL)
+#define MX35_PAD_CS4__EMI_NANDF_CE1				IOMUX_PAD(0x488, 0x0b0, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CS4__GPIO1_20					IOMUX_PAD(0x488, 0x0b0, 5, 0x83c, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_CS5__EMI_EIM_CS5				IOMUX_PAD(0x48c, 0x0b4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CS5__CSPI2_SS2					IOMUX_PAD(0x48c, 0x0b4, 1, 0x7f8, 0, NO_PAD_CTRL)
+#define MX35_PAD_CS5__CSPI1_SS2					IOMUX_PAD(0x48c, 0x0b4, 2, 0x7d8, 1, NO_PAD_CTRL)
+#define MX35_PAD_CS5__EMI_NANDF_CE2				IOMUX_PAD(0x48c, 0x0b4, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CS5__GPIO1_21					IOMUX_PAD(0x48c, 0x0b4, 5, 0x840, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_NF_CE0__EMI_NANDF_CE0				IOMUX_PAD(0x490, 0x0b8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NF_CE0__GPIO1_22				IOMUX_PAD(0x490, 0x0b8, 5, 0x844, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_ECB__EMI_EIM_ECB				IOMUX_PAD(0x494, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LBA__EMI_EIM_LBA				IOMUX_PAD(0x498, 0x0bc, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_BCLK__EMI_EIM_BCLK				IOMUX_PAD(0x49c, 0x0c0, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_RW__EMI_EIM_RW					IOMUX_PAD(0x4a0, 0x0c4, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_RAS__EMI_DRAM_RAS				IOMUX_PAD(0x4a4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CAS__EMI_DRAM_CAS				IOMUX_PAD(0x4a8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDWE__EMI_DRAM_SDWE				IOMUX_PAD(0x4ac, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDCKE0__EMI_DRAM_SDCKE_0			IOMUX_PAD(0x4b0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDCKE1__EMI_DRAM_SDCKE_1			IOMUX_PAD(0x4b4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDCLK__EMI_DRAM_SDCLK				IOMUX_PAD(0x4b8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDQS0__EMI_DRAM_SDQS_0				IOMUX_PAD(0x4bc, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDQS1__EMI_DRAM_SDQS_1				IOMUX_PAD(0x4c0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDQS2__EMI_DRAM_SDQS_2				IOMUX_PAD(0x4c4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDQS3__EMI_DRAM_SDQS_3				IOMUX_PAD(0x4c8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_NFWE_B__EMI_NANDF_WE_B				IOMUX_PAD(0x4cc, 0x0c8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFWE_B__USB_TOP_USBH2_DATA_3			IOMUX_PAD(0x4cc, 0x0c8, 1, 0x9d8, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFWE_B__IPU_DISPB_D0_VSYNC			IOMUX_PAD(0x4cc, 0x0c8, 2, 0x924, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFWE_B__GPIO2_18				IOMUX_PAD(0x4cc, 0x0c8, 5, 0x88c, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFWE_B__ARM11P_TOP_TRACE_0			IOMUX_PAD(0x4cc, 0x0c8, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_NFRE_B__EMI_NANDF_RE_B				IOMUX_PAD(0x4d0, 0x0cc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFRE_B__USB_TOP_USBH2_DIR			IOMUX_PAD(0x4d0, 0x0cc, 1, 0x9ec, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFRE_B__IPU_DISPB_BCLK				IOMUX_PAD(0x4d0, 0x0cc, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFRE_B__GPIO2_19				IOMUX_PAD(0x4d0, 0x0cc, 5, 0x890, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFRE_B__ARM11P_TOP_TRACE_1			IOMUX_PAD(0x4d0, 0x0cc, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_NFALE__EMI_NANDF_ALE				IOMUX_PAD(0x4d4, 0x0d0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFALE__USB_TOP_USBH2_STP			IOMUX_PAD(0x4d4, 0x0d0, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFALE__IPU_DISPB_CS0				IOMUX_PAD(0x4d4, 0x0d0, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFALE__GPIO2_20				IOMUX_PAD(0x4d4, 0x0d0, 5, 0x898, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFALE__ARM11P_TOP_TRACE_2			IOMUX_PAD(0x4d4, 0x0d0, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_NFCLE__EMI_NANDF_CLE				IOMUX_PAD(0x4d8, 0x0d4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFCLE__USB_TOP_USBH2_NXT			IOMUX_PAD(0x4d8, 0x0d4, 1, 0x9f0, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFCLE__IPU_DISPB_PAR_RS			IOMUX_PAD(0x4d8, 0x0d4, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFCLE__GPIO2_21				IOMUX_PAD(0x4d8, 0x0d4, 5, 0x89c, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFCLE__ARM11P_TOP_TRACE_3			IOMUX_PAD(0x4d8, 0x0d4, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_NFWP_B__EMI_NANDF_WP_B				IOMUX_PAD(0x4dc, 0x0d8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFWP_B__USB_TOP_USBH2_DATA_7			IOMUX_PAD(0x4dc, 0x0d8, 1, 0x9e8, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFWP_B__IPU_DISPB_WR				IOMUX_PAD(0x4dc, 0x0d8, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFWP_B__GPIO2_22				IOMUX_PAD(0x4dc, 0x0d8, 5, 0x8a0, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFWP_B__ARM11P_TOP_TRCTL			IOMUX_PAD(0x4dc, 0x0d8, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_NFRB__EMI_NANDF_RB				IOMUX_PAD(0x4e0, 0x0dc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFRB__IPU_DISPB_RD				IOMUX_PAD(0x4e0, 0x0dc, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFRB__GPIO2_23					IOMUX_PAD(0x4e0, 0x0dc, 5, 0x8a4, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFRB__ARM11P_TOP_TRCLK				IOMUX_PAD(0x4e0, 0x0dc, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D15__EMI_EIM_D_15				IOMUX_PAD(0x4e4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D14__EMI_EIM_D_14				IOMUX_PAD(0x4e8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D13__EMI_EIM_D_13				IOMUX_PAD(0x4ec, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D12__EMI_EIM_D_12				IOMUX_PAD(0x4f0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D11__EMI_EIM_D_11				IOMUX_PAD(0x4f4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D10__EMI_EIM_D_10				IOMUX_PAD(0x4f8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D9__EMI_EIM_D_9				IOMUX_PAD(0x4fc, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D8__EMI_EIM_D_8				IOMUX_PAD(0x500, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D7__EMI_EIM_D_7				IOMUX_PAD(0x504, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D6__EMI_EIM_D_6				IOMUX_PAD(0x508, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D5__EMI_EIM_D_5				IOMUX_PAD(0x50c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D4__EMI_EIM_D_4				IOMUX_PAD(0x510, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D3__EMI_EIM_D_3				IOMUX_PAD(0x514, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D2__EMI_EIM_D_2				IOMUX_PAD(0x518, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D1__EMI_EIM_D_1				IOMUX_PAD(0x51c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D0__EMI_EIM_D_0				IOMUX_PAD(0x520, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_D8__IPU_CSI_D_8				IOMUX_PAD(0x524, 0x0e0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D8__KPP_COL_0				IOMUX_PAD(0x524, 0x0e0, 1, 0x950, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D8__GPIO1_20				IOMUX_PAD(0x524, 0x0e0, 5, 0x83c, 1, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D8__ARM11P_TOP_EVNTBUS_13			IOMUX_PAD(0x524, 0x0e0, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_D9__IPU_CSI_D_9				IOMUX_PAD(0x528, 0x0e4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D9__KPP_COL_1				IOMUX_PAD(0x528, 0x0e4, 1, 0x954, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D9__GPIO1_21				IOMUX_PAD(0x528, 0x0e4, 5, 0x840, 1, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D9__ARM11P_TOP_EVNTBUS_14			IOMUX_PAD(0x528, 0x0e4, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_D10__IPU_CSI_D_10				IOMUX_PAD(0x52c, 0x0e8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D10__KPP_COL_2				IOMUX_PAD(0x52c, 0x0e8, 1, 0x958, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D10__GPIO1_22				IOMUX_PAD(0x52c, 0x0e8, 5, 0x844, 1, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D10__ARM11P_TOP_EVNTBUS_15			IOMUX_PAD(0x52c, 0x0e8, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_D11__IPU_CSI_D_11				IOMUX_PAD(0x530, 0x0ec, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D11__KPP_COL_3				IOMUX_PAD(0x530, 0x0ec, 1, 0x95c, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D11__GPIO1_23				IOMUX_PAD(0x530, 0x0ec, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_D12__IPU_CSI_D_12				IOMUX_PAD(0x534, 0x0f0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D12__KPP_ROW_0				IOMUX_PAD(0x534, 0x0f0, 1, 0x970, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D12__GPIO1_24				IOMUX_PAD(0x534, 0x0f0, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_D13__IPU_CSI_D_13				IOMUX_PAD(0x538, 0x0f4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D13__KPP_ROW_1				IOMUX_PAD(0x538, 0x0f4, 1, 0x974, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D13__GPIO1_25				IOMUX_PAD(0x538, 0x0f4, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_D14__IPU_CSI_D_14				IOMUX_PAD(0x53c, 0x0f8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D14__KPP_ROW_2				IOMUX_PAD(0x53c, 0x0f8, 1, 0x978, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D14__GPIO1_26				IOMUX_PAD(0x53c, 0x0f8, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_D15__IPU_CSI_D_15				IOMUX_PAD(0x540, 0x0fc, 0, 0x97c, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D15__KPP_ROW_3				IOMUX_PAD(0x540, 0x0fc, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D15__GPIO1_27				IOMUX_PAD(0x540, 0x0fc, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_MCLK__IPU_CSI_MCLK				IOMUX_PAD(0x544, 0x100, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_MCLK__GPIO1_28				IOMUX_PAD(0x544, 0x100, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_VSYNC__IPU_CSI_VSYNC			IOMUX_PAD(0x548, 0x104, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_VSYNC__GPIO1_29				IOMUX_PAD(0x548, 0x104, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_HSYNC__IPU_CSI_HSYNC			IOMUX_PAD(0x54c, 0x108, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_HSYNC__GPIO1_30				IOMUX_PAD(0x54c, 0x108, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_PIXCLK__IPU_CSI_PIXCLK			IOMUX_PAD(0x550, 0x10c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_PIXCLK__GPIO1_31				IOMUX_PAD(0x550, 0x10c, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_I2C1_CLK__I2C1_SCL				IOMUX_PAD(0x554, 0x110, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_I2C1_CLK__GPIO2_24				IOMUX_PAD(0x554, 0x110, 5, 0x8a8, 0, NO_PAD_CTRL)
+#define MX35_PAD_I2C1_CLK__CCM_USB_BYP_CLK			IOMUX_PAD(0x554, 0x110, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_I2C1_DAT__I2C1_SDA				IOMUX_PAD(0x558, 0x114, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_I2C1_DAT__GPIO2_25				IOMUX_PAD(0x558, 0x114, 5, 0x8ac, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_I2C2_CLK__I2C2_SCL				IOMUX_PAD(0x55c, 0x118, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_I2C2_CLK__CAN1_TXCAN				IOMUX_PAD(0x55c, 0x118, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_I2C2_CLK__USB_TOP_USBH2_PWR			IOMUX_PAD(0x55c, 0x118, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_I2C2_CLK__GPIO2_26				IOMUX_PAD(0x55c, 0x118, 5, 0x8b0, 0, NO_PAD_CTRL)
+#define MX35_PAD_I2C2_CLK__SDMA_DEBUG_BUS_DEVICE_2		IOMUX_PAD(0x55c, 0x118, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_I2C2_DAT__I2C2_SDA				IOMUX_PAD(0x560, 0x11c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_I2C2_DAT__CAN1_RXCAN				IOMUX_PAD(0x560, 0x11c, 1, 0x7c8, 0, NO_PAD_CTRL)
+#define MX35_PAD_I2C2_DAT__USB_TOP_USBH2_OC			IOMUX_PAD(0x560, 0x11c, 2, 0x9f4, 0, NO_PAD_CTRL)
+#define MX35_PAD_I2C2_DAT__GPIO2_27				IOMUX_PAD(0x560, 0x11c, 5, 0x8b4, 0, NO_PAD_CTRL)
+#define MX35_PAD_I2C2_DAT__SDMA_DEBUG_BUS_DEVICE_3		IOMUX_PAD(0x560, 0x11c, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_STXD4__AUDMUX_AUD4_TXD				IOMUX_PAD(0x564, 0x120, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_STXD4__GPIO2_28				IOMUX_PAD(0x564, 0x120, 5, 0x8b8, 0, NO_PAD_CTRL)
+#define MX35_PAD_STXD4__ARM11P_TOP_ARM_COREASID0		IOMUX_PAD(0x564, 0x120, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SRXD4__AUDMUX_AUD4_RXD				IOMUX_PAD(0x568, 0x124, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SRXD4__GPIO2_29				IOMUX_PAD(0x568, 0x124, 5, 0x8bc, 0, NO_PAD_CTRL)
+#define MX35_PAD_SRXD4__ARM11P_TOP_ARM_COREASID1		IOMUX_PAD(0x568, 0x124, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SCK4__AUDMUX_AUD4_TXC				IOMUX_PAD(0x56c, 0x128, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SCK4__GPIO2_30					IOMUX_PAD(0x56c, 0x128, 5, 0x8c4, 0, NO_PAD_CTRL)
+#define MX35_PAD_SCK4__ARM11P_TOP_ARM_COREASID2			IOMUX_PAD(0x56c, 0x128, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS			IOMUX_PAD(0x570, 0x12c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_STXFS4__GPIO2_31				IOMUX_PAD(0x570, 0x12c, 5, 0x8c8, 0, NO_PAD_CTRL)
+#define MX35_PAD_STXFS4__ARM11P_TOP_ARM_COREASID3		IOMUX_PAD(0x570, 0x12c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_STXD5__AUDMUX_AUD5_TXD				IOMUX_PAD(0x574, 0x130, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_STXD5__SPDIF_SPDIF_OUT1			IOMUX_PAD(0x574, 0x130, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_STXD5__CSPI2_MOSI				IOMUX_PAD(0x574, 0x130, 2, 0x7ec, 0, NO_PAD_CTRL)
+#define MX35_PAD_STXD5__GPIO1_0					IOMUX_PAD(0x574, 0x130, 5, 0x82c, 1, NO_PAD_CTRL)
+#define MX35_PAD_STXD5__ARM11P_TOP_ARM_COREASID4		IOMUX_PAD(0x574, 0x130, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SRXD5__AUDMUX_AUD5_RXD				IOMUX_PAD(0x578, 0x134, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SRXD5__SPDIF_SPDIF_IN1				IOMUX_PAD(0x578, 0x134, 1, 0x998, 0, NO_PAD_CTRL)
+#define MX35_PAD_SRXD5__CSPI2_MISO				IOMUX_PAD(0x578, 0x134, 2, 0x7e8, 0, NO_PAD_CTRL)
+#define MX35_PAD_SRXD5__GPIO1_1					IOMUX_PAD(0x578, 0x134, 5, 0x838, 1, NO_PAD_CTRL)
+#define MX35_PAD_SRXD5__ARM11P_TOP_ARM_COREASID5		IOMUX_PAD(0x578, 0x134, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SCK5__AUDMUX_AUD5_TXC				IOMUX_PAD(0x57c, 0x138, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SCK5__SPDIF_SPDIF_EXTCLK			IOMUX_PAD(0x57c, 0x138, 1, 0x994, 0, NO_PAD_CTRL)
+#define MX35_PAD_SCK5__CSPI2_SCLK				IOMUX_PAD(0x57c, 0x138, 2, 0x7e0, 0, NO_PAD_CTRL)
+#define MX35_PAD_SCK5__GPIO1_2					IOMUX_PAD(0x57c, 0x138, 5, 0x848, 0, NO_PAD_CTRL)
+#define MX35_PAD_SCK5__ARM11P_TOP_ARM_COREASID6			IOMUX_PAD(0x57c, 0x138, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_STXFS5__AUDMUX_AUD5_TXFS			IOMUX_PAD(0x580, 0x13c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_STXFS5__CSPI2_RDY				IOMUX_PAD(0x580, 0x13c, 2, 0x7e4, 0, NO_PAD_CTRL)
+#define MX35_PAD_STXFS5__GPIO1_3				IOMUX_PAD(0x580, 0x13c, 5, 0x84c, 0, NO_PAD_CTRL)
+#define MX35_PAD_STXFS5__ARM11P_TOP_ARM_COREASID7		IOMUX_PAD(0x580, 0x13c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SCKR__ESAI_SCKR				IOMUX_PAD(0x584, 0x140, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SCKR__GPIO1_4					IOMUX_PAD(0x584, 0x140, 5, 0x850, 1, NO_PAD_CTRL)
+#define MX35_PAD_SCKR__ARM11P_TOP_EVNTBUS_10			IOMUX_PAD(0x584, 0x140, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FSR__ESAI_FSR					IOMUX_PAD(0x588, 0x144, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FSR__GPIO1_5					IOMUX_PAD(0x588, 0x144, 5, 0x854, 1, NO_PAD_CTRL)
+#define MX35_PAD_FSR__ARM11P_TOP_EVNTBUS_11			IOMUX_PAD(0x588, 0x144, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_HCKR__ESAI_HCKR				IOMUX_PAD(0x58c, 0x148, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_HCKR__AUDMUX_AUD5_RXFS				IOMUX_PAD(0x58c, 0x148, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_HCKR__CSPI2_SS0				IOMUX_PAD(0x58c, 0x148, 2, 0x7f0, 0, NO_PAD_CTRL)
+#define MX35_PAD_HCKR__IPU_FLASH_STROBE				IOMUX_PAD(0x58c, 0x148, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_HCKR__GPIO1_6					IOMUX_PAD(0x58c, 0x148, 5, 0x858, 1, NO_PAD_CTRL)
+#define MX35_PAD_HCKR__ARM11P_TOP_EVNTBUS_12			IOMUX_PAD(0x58c, 0x148, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SCKT__ESAI_SCKT				IOMUX_PAD(0x590, 0x14c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SCKT__GPIO1_7					IOMUX_PAD(0x590, 0x14c, 5, 0x85c, 1, NO_PAD_CTRL)
+#define MX35_PAD_SCKT__IPU_CSI_D_0				IOMUX_PAD(0x590, 0x14c, 6, 0x930, 0, NO_PAD_CTRL)
+#define MX35_PAD_SCKT__KPP_ROW_2				IOMUX_PAD(0x590, 0x14c, 7, 0x978, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_FST__ESAI_FST					IOMUX_PAD(0x594, 0x150, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FST__GPIO1_8					IOMUX_PAD(0x594, 0x150, 5, 0x860, 1, NO_PAD_CTRL)
+#define MX35_PAD_FST__IPU_CSI_D_1				IOMUX_PAD(0x594, 0x150, 6, 0x934, 0, NO_PAD_CTRL)
+#define MX35_PAD_FST__KPP_ROW_3					IOMUX_PAD(0x594, 0x150, 7, 0x97c, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_HCKT__ESAI_HCKT				IOMUX_PAD(0x598, 0x154, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_HCKT__AUDMUX_AUD5_RXC				IOMUX_PAD(0x598, 0x154, 1, 0x7a8, 0, NO_PAD_CTRL)
+#define MX35_PAD_HCKT__GPIO1_9					IOMUX_PAD(0x598, 0x154, 5, 0x864, 0, NO_PAD_CTRL)
+#define MX35_PAD_HCKT__IPU_CSI_D_2				IOMUX_PAD(0x598, 0x154, 6, 0x938, 0, NO_PAD_CTRL)
+#define MX35_PAD_HCKT__KPP_COL_3				IOMUX_PAD(0x598, 0x154, 7, 0x95c, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_TX5_RX0__ESAI_TX5_RX0				IOMUX_PAD(0x59c, 0x158, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX5_RX0__AUDMUX_AUD4_RXC			IOMUX_PAD(0x59c, 0x158, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX5_RX0__CSPI2_SS2				IOMUX_PAD(0x59c, 0x158, 2, 0x7f8, 1, NO_PAD_CTRL)
+#define MX35_PAD_TX5_RX0__CAN2_TXCAN				IOMUX_PAD(0x59c, 0x158, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX5_RX0__UART2_DTR				IOMUX_PAD(0x59c, 0x158, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX5_RX0__GPIO1_10				IOMUX_PAD(0x59c, 0x158, 5, 0x830, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX5_RX0__EMI_M3IF_CHOSEN_MASTER_0		IOMUX_PAD(0x59c, 0x158, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_TX4_RX1__ESAI_TX4_RX1				IOMUX_PAD(0x5a0, 0x15c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX4_RX1__AUDMUX_AUD4_RXFS			IOMUX_PAD(0x5a0, 0x15c, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX4_RX1__CSPI2_SS3				IOMUX_PAD(0x5a0, 0x15c, 2, 0x7fc, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX4_RX1__CAN2_RXCAN				IOMUX_PAD(0x5a0, 0x15c, 3, 0x7cc, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX4_RX1__UART2_DSR				IOMUX_PAD(0x5a0, 0x15c, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX4_RX1__GPIO1_11				IOMUX_PAD(0x5a0, 0x15c, 5, 0x834, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX4_RX1__IPU_CSI_D_3				IOMUX_PAD(0x5a0, 0x15c, 6, 0x93c, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX4_RX1__KPP_ROW_0				IOMUX_PAD(0x5a0, 0x15c, 7, 0x970, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_TX3_RX2__ESAI_TX3_RX2				IOMUX_PAD(0x5a4, 0x160, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX3_RX2__I2C3_SCL				IOMUX_PAD(0x5a4, 0x160, 1, 0x91c, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX3_RX2__EMI_NANDF_CE1				IOMUX_PAD(0x5a4, 0x160, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX3_RX2__GPIO1_12				IOMUX_PAD(0x5a4, 0x160, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX3_RX2__IPU_CSI_D_4				IOMUX_PAD(0x5a4, 0x160, 6, 0x940, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX3_RX2__KPP_ROW_1				IOMUX_PAD(0x5a4, 0x160, 7, 0x974, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_TX2_RX3__ESAI_TX2_RX3				IOMUX_PAD(0x5a8, 0x164, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX2_RX3__I2C3_SDA				IOMUX_PAD(0x5a8, 0x164, 1, 0x920, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX2_RX3__EMI_NANDF_CE2				IOMUX_PAD(0x5a8, 0x164, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX2_RX3__GPIO1_13				IOMUX_PAD(0x5a8, 0x164, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX2_RX3__IPU_CSI_D_5				IOMUX_PAD(0x5a8, 0x164, 6, 0x944, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX2_RX3__KPP_COL_0				IOMUX_PAD(0x5a8, 0x164, 7, 0x950, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_TX1__ESAI_TX1					IOMUX_PAD(0x5ac, 0x168, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX1__CCM_PMIC_RDY				IOMUX_PAD(0x5ac, 0x168, 1, 0x7d4, 1, NO_PAD_CTRL)
+#define MX35_PAD_TX1__CSPI1_SS2					IOMUX_PAD(0x5ac, 0x168, 2, 0x7d8, 2, NO_PAD_CTRL)
+#define MX35_PAD_TX1__EMI_NANDF_CE3				IOMUX_PAD(0x5ac, 0x168, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX1__UART2_RI					IOMUX_PAD(0x5ac, 0x168, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX1__GPIO1_14					IOMUX_PAD(0x5ac, 0x168, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX1__IPU_CSI_D_6				IOMUX_PAD(0x5ac, 0x168, 6, 0x948, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX1__KPP_COL_1					IOMUX_PAD(0x5ac, 0x168, 7, 0x954, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_TX0__ESAI_TX0					IOMUX_PAD(0x5b0, 0x16c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX0__SPDIF_SPDIF_EXTCLK			IOMUX_PAD(0x5b0, 0x16c, 1, 0x994, 1, NO_PAD_CTRL)
+#define MX35_PAD_TX0__CSPI1_SS3					IOMUX_PAD(0x5b0, 0x16c, 2, 0x7dc, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX0__EMI_DTACK_B				IOMUX_PAD(0x5b0, 0x16c, 3, 0x800, 1, NO_PAD_CTRL)
+#define MX35_PAD_TX0__UART2_DCD					IOMUX_PAD(0x5b0, 0x16c, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX0__GPIO1_15					IOMUX_PAD(0x5b0, 0x16c, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX0__IPU_CSI_D_7				IOMUX_PAD(0x5b0, 0x16c, 6, 0x94c, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX0__KPP_COL_2					IOMUX_PAD(0x5b0, 0x16c, 7, 0x958, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_CSPI1_MOSI__CSPI1_MOSI				IOMUX_PAD(0x5b4, 0x170, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_MOSI__GPIO1_16				IOMUX_PAD(0x5b4, 0x170, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_MOSI__ECT_CTI_TRIG_OUT1_2		IOMUX_PAD(0x5b4, 0x170, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSPI1_MISO__CSPI1_MISO				IOMUX_PAD(0x5b8, 0x174, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_MISO__GPIO1_17				IOMUX_PAD(0x5b8, 0x174, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_MISO__ECT_CTI_TRIG_OUT1_3		IOMUX_PAD(0x5b8, 0x174, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSPI1_SS0__CSPI1_SS0				IOMUX_PAD(0x5bc, 0x178, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS0__OWIRE_LINE				IOMUX_PAD(0x5bc, 0x178, 1, 0x990, 1, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS0__CSPI2_SS3				IOMUX_PAD(0x5bc, 0x178, 2, 0x7fc, 1, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS0__GPIO1_18				IOMUX_PAD(0x5bc, 0x178, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS0__ECT_CTI_TRIG_OUT1_4			IOMUX_PAD(0x5bc, 0x178, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSPI1_SS1__CSPI1_SS1				IOMUX_PAD(0x5c0, 0x17c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS1__PWM_PWMO				IOMUX_PAD(0x5c0, 0x17c, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS1__CCM_CLK32K				IOMUX_PAD(0x5c0, 0x17c, 2, 0x7d0, 1, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS1__GPIO1_19				IOMUX_PAD(0x5c0, 0x17c, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS1__IPU_DIAGB_29			IOMUX_PAD(0x5c0, 0x17c, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS1__ECT_CTI_TRIG_OUT1_5			IOMUX_PAD(0x5c0, 0x17c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSPI1_SCLK__CSPI1_SCLK				IOMUX_PAD(0x5c4, 0x180, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SCLK__GPIO3_4				IOMUX_PAD(0x5c4, 0x180, 5, 0x904, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SCLK__IPU_DIAGB_30			IOMUX_PAD(0x5c4, 0x180, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SCLK__EMI_M3IF_CHOSEN_MASTER_1		IOMUX_PAD(0x5c4, 0x180, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSPI1_SPI_RDY__CSPI1_RDY			IOMUX_PAD(0x5c8, 0x184, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SPI_RDY__GPIO3_5				IOMUX_PAD(0x5c8, 0x184, 5, 0x908, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SPI_RDY__IPU_DIAGB_31			IOMUX_PAD(0x5c8, 0x184, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SPI_RDY__EMI_M3IF_CHOSEN_MASTER_2	IOMUX_PAD(0x5c8, 0x184, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_RXD1__UART1_RXD_MUX				IOMUX_PAD(0x5cc, 0x188, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_RXD1__CSPI2_MOSI				IOMUX_PAD(0x5cc, 0x188, 1, 0x7ec, 1, NO_PAD_CTRL)
+#define MX35_PAD_RXD1__KPP_COL_4				IOMUX_PAD(0x5cc, 0x188, 4, 0x960, 0, NO_PAD_CTRL)
+#define MX35_PAD_RXD1__GPIO3_6					IOMUX_PAD(0x5cc, 0x188, 5, 0x90c, 0, NO_PAD_CTRL)
+#define MX35_PAD_RXD1__ARM11P_TOP_EVNTBUS_16			IOMUX_PAD(0x5cc, 0x188, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_TXD1__UART1_TXD_MUX				IOMUX_PAD(0x5d0, 0x18c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TXD1__CSPI2_MISO				IOMUX_PAD(0x5d0, 0x18c, 1, 0x7e8, 1, NO_PAD_CTRL)
+#define MX35_PAD_TXD1__KPP_COL_5				IOMUX_PAD(0x5d0, 0x18c, 4, 0x964, 0, NO_PAD_CTRL)
+#define MX35_PAD_TXD1__GPIO3_7					IOMUX_PAD(0x5d0, 0x18c, 5, 0x910, 0, NO_PAD_CTRL)
+#define MX35_PAD_TXD1__ARM11P_TOP_EVNTBUS_17			IOMUX_PAD(0x5d0, 0x18c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_RTS1__UART1_RTS				IOMUX_PAD(0x5d4, 0x190, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_RTS1__CSPI2_SCLK				IOMUX_PAD(0x5d4, 0x190, 1, 0x7e0, 1, NO_PAD_CTRL)
+#define MX35_PAD_RTS1__I2C3_SCL					IOMUX_PAD(0x5d4, 0x190, 2, 0x91c, 1, NO_PAD_CTRL)
+#define MX35_PAD_RTS1__IPU_CSI_D_0				IOMUX_PAD(0x5d4, 0x190, 3, 0x930, 1, NO_PAD_CTRL)
+#define MX35_PAD_RTS1__KPP_COL_6				IOMUX_PAD(0x5d4, 0x190, 4, 0x968, 0, NO_PAD_CTRL)
+#define MX35_PAD_RTS1__GPIO3_8					IOMUX_PAD(0x5d4, 0x190, 5, 0x914, 0, NO_PAD_CTRL)
+#define MX35_PAD_RTS1__EMI_NANDF_CE1				IOMUX_PAD(0x5d4, 0x190, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_RTS1__ARM11P_TOP_EVNTBUS_18			IOMUX_PAD(0x5d4, 0x190, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CTS1__UART1_CTS				IOMUX_PAD(0x5d8, 0x194, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CTS1__CSPI2_RDY				IOMUX_PAD(0x5d8, 0x194, 1, 0x7e4, 1, NO_PAD_CTRL)
+#define MX35_PAD_CTS1__I2C3_SDA					IOMUX_PAD(0x5d8, 0x194, 2, 0x920, 1, NO_PAD_CTRL)
+#define MX35_PAD_CTS1__IPU_CSI_D_1				IOMUX_PAD(0x5d8, 0x194, 3, 0x934, 1, NO_PAD_CTRL)
+#define MX35_PAD_CTS1__KPP_COL_7				IOMUX_PAD(0x5d8, 0x194, 4, 0x96c, 0, NO_PAD_CTRL)
+#define MX35_PAD_CTS1__GPIO3_9					IOMUX_PAD(0x5d8, 0x194, 5, 0x918, 0, NO_PAD_CTRL)
+#define MX35_PAD_CTS1__EMI_NANDF_CE2				IOMUX_PAD(0x5d8, 0x194, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CTS1__ARM11P_TOP_EVNTBUS_19			IOMUX_PAD(0x5d8, 0x194, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_RXD2__UART2_RXD_MUX				IOMUX_PAD(0x5dc, 0x198, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_RXD2__KPP_ROW_4				IOMUX_PAD(0x5dc, 0x198, 4, 0x980, 0, NO_PAD_CTRL)
+#define MX35_PAD_RXD2__GPIO3_10					IOMUX_PAD(0x5dc, 0x198, 5, 0x8ec, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_TXD2__UART2_TXD_MUX				IOMUX_PAD(0x5e0, 0x19c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TXD2__SPDIF_SPDIF_EXTCLK			IOMUX_PAD(0x5e0, 0x19c, 1, 0x994, 2, NO_PAD_CTRL)
+#define MX35_PAD_TXD2__KPP_ROW_5				IOMUX_PAD(0x5e0, 0x19c, 4, 0x984, 0, NO_PAD_CTRL)
+#define MX35_PAD_TXD2__GPIO3_11					IOMUX_PAD(0x5e0, 0x19c, 5, 0x8f0, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_RTS2__UART2_RTS				IOMUX_PAD(0x5e4, 0x1a0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_RTS2__SPDIF_SPDIF_IN1				IOMUX_PAD(0x5e4, 0x1a0, 1, 0x998, 1, NO_PAD_CTRL)
+#define MX35_PAD_RTS2__CAN2_RXCAN				IOMUX_PAD(0x5e4, 0x1a0, 2, 0x7cc, 1, NO_PAD_CTRL)
+#define MX35_PAD_RTS2__IPU_CSI_D_2				IOMUX_PAD(0x5e4, 0x1a0, 3, 0x938, 1, NO_PAD_CTRL)
+#define MX35_PAD_RTS2__KPP_ROW_6				IOMUX_PAD(0x5e4, 0x1a0, 4, 0x988, 0, NO_PAD_CTRL)
+#define MX35_PAD_RTS2__GPIO3_12					IOMUX_PAD(0x5e4, 0x1a0, 5, 0x8f4, 0, NO_PAD_CTRL)
+#define MX35_PAD_RTS2__AUDMUX_AUD5_RXC				IOMUX_PAD(0x5e4, 0x1a0, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_RTS2__UART3_RXD_MUX				IOMUX_PAD(0x5e4, 0x1a0, 7, 0x9a0, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_CTS2__UART2_CTS				IOMUX_PAD(0x5e8, 0x1a4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CTS2__SPDIF_SPDIF_OUT1				IOMUX_PAD(0x5e8, 0x1a4, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CTS2__CAN2_TXCAN				IOMUX_PAD(0x5e8, 0x1a4, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CTS2__IPU_CSI_D_3				IOMUX_PAD(0x5e8, 0x1a4, 3, 0x93c, 1, NO_PAD_CTRL)
+#define MX35_PAD_CTS2__KPP_ROW_7				IOMUX_PAD(0x5e8, 0x1a4, 4, 0x98c, 0, NO_PAD_CTRL)
+#define MX35_PAD_CTS2__GPIO3_13					IOMUX_PAD(0x5e8, 0x1a4, 5, 0x8f8, 0, NO_PAD_CTRL)
+#define MX35_PAD_CTS2__AUDMUX_AUD5_RXFS				IOMUX_PAD(0x5e8, 0x1a4, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CTS2__UART3_TXD_MUX				IOMUX_PAD(0x5e8, 0x1a4, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_RTCK__ARM11P_TOP_RTCK				IOMUX_PAD(0x5ec, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_TCK__SJC_TCK					IOMUX_PAD(0x5f0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_TMS__SJC_TMS					IOMUX_PAD(0x5f4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_TDI__SJC_TDI					IOMUX_PAD(0x5f8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_TDO__SJC_TDO					IOMUX_PAD(0x5fc, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_TRSTB__SJC_TRSTB				IOMUX_PAD(0x600, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_DE_B__SJC_DE_B					IOMUX_PAD(0x604, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SJC_MOD__SJC_MOD				IOMUX_PAD(0x608, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_USBOTG_PWR__USB_TOP_USBOTG_PWR			IOMUX_PAD(0x60c, 0x1a8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_USBOTG_PWR__USB_TOP_USBH2_PWR			IOMUX_PAD(0x60c, 0x1a8, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_USBOTG_PWR__GPIO3_14				IOMUX_PAD(0x60c, 0x1a8, 5, 0x8fc, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_USBOTG_OC__USB_TOP_USBOTG_OC			IOMUX_PAD(0x610, 0x1ac, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_USBOTG_OC__USB_TOP_USBH2_OC			IOMUX_PAD(0x610, 0x1ac, 1, 0x9f4, 1, NO_PAD_CTRL)
+#define MX35_PAD_USBOTG_OC__GPIO3_15				IOMUX_PAD(0x610, 0x1ac, 5, 0x900, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD0__IPU_DISPB_DAT_0				IOMUX_PAD(0x614, 0x1b0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD0__GPIO2_0					IOMUX_PAD(0x614, 0x1b0, 5, 0x868, 1, NO_PAD_CTRL)
+#define MX35_PAD_LD0__SDMA_SDMA_DEBUG_PC_0			IOMUX_PAD(0x614, 0x1b0, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD1__IPU_DISPB_DAT_1				IOMUX_PAD(0x618, 0x1b4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD1__GPIO2_1					IOMUX_PAD(0x618, 0x1b4, 5, 0x894, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD1__SDMA_SDMA_DEBUG_PC_1			IOMUX_PAD(0x618, 0x1b4, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD2__IPU_DISPB_DAT_2				IOMUX_PAD(0x61c, 0x1b8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD2__GPIO2_2					IOMUX_PAD(0x61c, 0x1b8, 5, 0x8c0, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD2__SDMA_SDMA_DEBUG_PC_2			IOMUX_PAD(0x61c, 0x1b8, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD3__IPU_DISPB_DAT_3				IOMUX_PAD(0x620, 0x1bc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD3__GPIO2_3					IOMUX_PAD(0x620, 0x1bc, 5, 0x8cc, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD3__SDMA_SDMA_DEBUG_PC_3			IOMUX_PAD(0x620, 0x1bc, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD4__IPU_DISPB_DAT_4				IOMUX_PAD(0x624, 0x1c0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD4__GPIO2_4					IOMUX_PAD(0x624, 0x1c0, 5, 0x8d0, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD4__SDMA_SDMA_DEBUG_PC_4			IOMUX_PAD(0x624, 0x1c0, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD5__IPU_DISPB_DAT_5				IOMUX_PAD(0x628, 0x1c4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD5__GPIO2_5					IOMUX_PAD(0x628, 0x1c4, 5, 0x8d4, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD5__SDMA_SDMA_DEBUG_PC_5			IOMUX_PAD(0x628, 0x1c4, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD6__IPU_DISPB_DAT_6				IOMUX_PAD(0x62c, 0x1c8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD6__GPIO2_6					IOMUX_PAD(0x62c, 0x1c8, 5, 0x8d8, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD6__SDMA_SDMA_DEBUG_PC_6			IOMUX_PAD(0x62c, 0x1c8, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD7__IPU_DISPB_DAT_7				IOMUX_PAD(0x630, 0x1cc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD7__GPIO2_7					IOMUX_PAD(0x630, 0x1cc, 5, 0x8dc, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD7__SDMA_SDMA_DEBUG_PC_7			IOMUX_PAD(0x630, 0x1cc, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD8__IPU_DISPB_DAT_8				IOMUX_PAD(0x634, 0x1d0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD8__GPIO2_8					IOMUX_PAD(0x634, 0x1d0, 5, 0x8e0, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD8__SDMA_SDMA_DEBUG_PC_8			IOMUX_PAD(0x634, 0x1d0, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD9__IPU_DISPB_DAT_9				IOMUX_PAD(0x638, 0x1d4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD9__GPIO2_9					IOMUX_PAD(0x638, 0x1d4, 5, 0x8e4, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD9__SDMA_SDMA_DEBUG_PC_9			IOMUX_PAD(0x638, 0x1d4, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD10__IPU_DISPB_DAT_10				IOMUX_PAD(0x63c, 0x1d8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD10__GPIO2_10					IOMUX_PAD(0x63c, 0x1d8, 5, 0x86c, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD10__SDMA_SDMA_DEBUG_PC_10			IOMUX_PAD(0x63c, 0x1d8, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD11__IPU_DISPB_DAT_11				IOMUX_PAD(0x640, 0x1dc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD11__GPIO2_11					IOMUX_PAD(0x640, 0x1dc, 5, 0x870, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD11__SDMA_SDMA_DEBUG_PC_11			IOMUX_PAD(0x640, 0x1dc, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD11__ARM11P_TOP_TRACE_4			IOMUX_PAD(0x640, 0x1dc, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD12__IPU_DISPB_DAT_12				IOMUX_PAD(0x644, 0x1e0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD12__GPIO2_12					IOMUX_PAD(0x644, 0x1e0, 5, 0x874, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD12__SDMA_SDMA_DEBUG_PC_12			IOMUX_PAD(0x644, 0x1e0, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD12__ARM11P_TOP_TRACE_5			IOMUX_PAD(0x644, 0x1e0, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD13__IPU_DISPB_DAT_13				IOMUX_PAD(0x648, 0x1e4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD13__GPIO2_13					IOMUX_PAD(0x648, 0x1e4, 5, 0x878, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD13__SDMA_SDMA_DEBUG_PC_13			IOMUX_PAD(0x648, 0x1e4, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD13__ARM11P_TOP_TRACE_6			IOMUX_PAD(0x648, 0x1e4, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD14__IPU_DISPB_DAT_14				IOMUX_PAD(0x64c, 0x1e8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD14__GPIO2_14					IOMUX_PAD(0x64c, 0x1e8, 5, 0x87c, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD14__SDMA_SDMA_DEBUG_EVENT_CHANNEL_0		IOMUX_PAD(0x64c, 0x1e8, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD14__ARM11P_TOP_TRACE_7			IOMUX_PAD(0x64c, 0x1e8, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD15__IPU_DISPB_DAT_15				IOMUX_PAD(0x650, 0x1ec, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD15__GPIO2_15					IOMUX_PAD(0x650, 0x1ec, 5, 0x880, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD15__SDMA_SDMA_DEBUG_EVENT_CHANNEL_1		IOMUX_PAD(0x650, 0x1ec, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD15__ARM11P_TOP_TRACE_8			IOMUX_PAD(0x650, 0x1ec, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD16__IPU_DISPB_DAT_16				IOMUX_PAD(0x654, 0x1f0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD16__IPU_DISPB_D12_VSYNC			IOMUX_PAD(0x654, 0x1f0, 2, 0x928, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD16__GPIO2_16					IOMUX_PAD(0x654, 0x1f0, 5, 0x884, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD16__SDMA_SDMA_DEBUG_EVENT_CHANNEL_2		IOMUX_PAD(0x654, 0x1f0, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD16__ARM11P_TOP_TRACE_9			IOMUX_PAD(0x654, 0x1f0, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD17__IPU_DISPB_DAT_17				IOMUX_PAD(0x658, 0x1f4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD17__IPU_DISPB_CS2				IOMUX_PAD(0x658, 0x1f4, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD17__GPIO2_17					IOMUX_PAD(0x658, 0x1f4, 5, 0x888, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD17__SDMA_SDMA_DEBUG_EVENT_CHANNEL_3		IOMUX_PAD(0x658, 0x1f4, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD17__ARM11P_TOP_TRACE_10			IOMUX_PAD(0x658, 0x1f4, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD18__IPU_DISPB_DAT_18				IOMUX_PAD(0x65c, 0x1f8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD18__IPU_DISPB_D0_VSYNC			IOMUX_PAD(0x65c, 0x1f8, 1, 0x924, 1, NO_PAD_CTRL)
+#define MX35_PAD_LD18__IPU_DISPB_D12_VSYNC			IOMUX_PAD(0x65c, 0x1f8, 2, 0x928, 1, NO_PAD_CTRL)
+#define MX35_PAD_LD18__ESDHC3_CMD				IOMUX_PAD(0x65c, 0x1f8, 3, 0x818, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD18__USB_TOP_USBOTG_DATA_3			IOMUX_PAD(0x65c, 0x1f8, 4, 0x9b0, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD18__GPIO3_24					IOMUX_PAD(0x65c, 0x1f8, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD18__SDMA_SDMA_DEBUG_EVENT_CHANNEL_4		IOMUX_PAD(0x65c, 0x1f8, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD18__ARM11P_TOP_TRACE_11			IOMUX_PAD(0x65c, 0x1f8, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD19__IPU_DISPB_DAT_19				IOMUX_PAD(0x660, 0x1fc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD19__IPU_DISPB_BCLK				IOMUX_PAD(0x660, 0x1fc, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD19__IPU_DISPB_CS1				IOMUX_PAD(0x660, 0x1fc, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD19__ESDHC3_CLK				IOMUX_PAD(0x660, 0x1fc, 3, 0x814, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD19__USB_TOP_USBOTG_DIR			IOMUX_PAD(0x660, 0x1fc, 4, 0x9c4, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD19__GPIO3_25					IOMUX_PAD(0x660, 0x1fc, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD19__SDMA_SDMA_DEBUG_EVENT_CHANNEL_5		IOMUX_PAD(0x660, 0x1fc, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD19__ARM11P_TOP_TRACE_12			IOMUX_PAD(0x660, 0x1fc, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD20__IPU_DISPB_DAT_20				IOMUX_PAD(0x664, 0x200, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD20__IPU_DISPB_CS0				IOMUX_PAD(0x664, 0x200, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD20__IPU_DISPB_SD_CLK				IOMUX_PAD(0x664, 0x200, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD20__ESDHC3_DAT0				IOMUX_PAD(0x664, 0x200, 3, 0x81c, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD20__GPIO3_26					IOMUX_PAD(0x664, 0x200, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD20__SDMA_SDMA_DEBUG_CORE_STATUS_3		IOMUX_PAD(0x664, 0x200, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD20__ARM11P_TOP_TRACE_13			IOMUX_PAD(0x664, 0x200, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD21__IPU_DISPB_DAT_21				IOMUX_PAD(0x668, 0x204, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD21__IPU_DISPB_PAR_RS				IOMUX_PAD(0x668, 0x204, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD21__IPU_DISPB_SER_RS				IOMUX_PAD(0x668, 0x204, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD21__ESDHC3_DAT1				IOMUX_PAD(0x668, 0x204, 3, 0x820, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD21__USB_TOP_USBOTG_STP			IOMUX_PAD(0x668, 0x204, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD21__GPIO3_27					IOMUX_PAD(0x668, 0x204, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD21__SDMA_DEBUG_EVENT_CHANNEL_SEL		IOMUX_PAD(0x668, 0x204, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD21__ARM11P_TOP_TRACE_14			IOMUX_PAD(0x668, 0x204, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD22__IPU_DISPB_DAT_22				IOMUX_PAD(0x66c, 0x208, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD22__IPU_DISPB_WR				IOMUX_PAD(0x66c, 0x208, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD22__IPU_DISPB_SD_D_I				IOMUX_PAD(0x66c, 0x208, 2, 0x92c, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD22__ESDHC3_DAT2				IOMUX_PAD(0x66c, 0x208, 3, 0x824, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD22__USB_TOP_USBOTG_NXT			IOMUX_PAD(0x66c, 0x208, 4, 0x9c8, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD22__GPIO3_28					IOMUX_PAD(0x66c, 0x208, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD22__SDMA_DEBUG_BUS_ERROR			IOMUX_PAD(0x66c, 0x208, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD22__ARM11P_TOP_TRCTL				IOMUX_PAD(0x66c, 0x208, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD23__IPU_DISPB_DAT_23				IOMUX_PAD(0x670, 0x20c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD23__IPU_DISPB_RD				IOMUX_PAD(0x670, 0x20c, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD23__IPU_DISPB_SD_D_IO			IOMUX_PAD(0x670, 0x20c, 2, 0x92c, 1, NO_PAD_CTRL)
+#define MX35_PAD_LD23__ESDHC3_DAT3				IOMUX_PAD(0x670, 0x20c, 3, 0x828, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD23__USB_TOP_USBOTG_DATA_7			IOMUX_PAD(0x670, 0x20c, 4, 0x9c0, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD23__GPIO3_29					IOMUX_PAD(0x670, 0x20c, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD23__SDMA_DEBUG_MATCHED_DMBUS			IOMUX_PAD(0x670, 0x20c, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD23__ARM11P_TOP_TRCLK				IOMUX_PAD(0x670, 0x20c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D3_HSYNC__IPU_DISPB_D3_HSYNC			IOMUX_PAD(0x674, 0x210, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_HSYNC__IPU_DISPB_SD_D_IO			IOMUX_PAD(0x674, 0x210, 2, 0x92c, 2, NO_PAD_CTRL)
+#define MX35_PAD_D3_HSYNC__GPIO3_30				IOMUX_PAD(0x674, 0x210, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_HSYNC__SDMA_DEBUG_RTBUFFER_WRITE		IOMUX_PAD(0x674, 0x210, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_HSYNC__ARM11P_TOP_TRACE_15			IOMUX_PAD(0x674, 0x210, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D3_FPSHIFT__IPU_DISPB_D3_CLK			IOMUX_PAD(0x678, 0x214, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_FPSHIFT__IPU_DISPB_SD_CLK			IOMUX_PAD(0x678, 0x214, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_FPSHIFT__GPIO3_31				IOMUX_PAD(0x678, 0x214, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_FPSHIFT__SDMA_SDMA_DEBUG_CORE_STATUS_0	IOMUX_PAD(0x678, 0x214, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_FPSHIFT__ARM11P_TOP_TRACE_16		IOMUX_PAD(0x678, 0x214, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D3_DRDY__IPU_DISPB_D3_DRDY			IOMUX_PAD(0x67c, 0x218, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_DRDY__IPU_DISPB_SD_D_O			IOMUX_PAD(0x67c, 0x218, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_DRDY__GPIO1_0				IOMUX_PAD(0x67c, 0x218, 5, 0x82c, 2, NO_PAD_CTRL)
+#define MX35_PAD_D3_DRDY__SDMA_SDMA_DEBUG_CORE_STATUS_1		IOMUX_PAD(0x67c, 0x218, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_DRDY__ARM11P_TOP_TRACE_17			IOMUX_PAD(0x67c, 0x218, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CONTRAST__IPU_DISPB_CONTR			IOMUX_PAD(0x680, 0x21c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CONTRAST__GPIO1_1				IOMUX_PAD(0x680, 0x21c, 5, 0x838, 2, NO_PAD_CTRL)
+#define MX35_PAD_CONTRAST__SDMA_SDMA_DEBUG_CORE_STATUS_2	IOMUX_PAD(0x680, 0x21c, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CONTRAST__ARM11P_TOP_TRACE_18			IOMUX_PAD(0x680, 0x21c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D3_VSYNC__IPU_DISPB_D3_VSYNC			IOMUX_PAD(0x684, 0x220, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_VSYNC__IPU_DISPB_CS1			IOMUX_PAD(0x684, 0x220, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_VSYNC__GPIO1_2				IOMUX_PAD(0x684, 0x220, 5, 0x848, 1, NO_PAD_CTRL)
+#define MX35_PAD_D3_VSYNC__SDMA_DEBUG_YIELD			IOMUX_PAD(0x684, 0x220, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_VSYNC__ARM11P_TOP_TRACE_19			IOMUX_PAD(0x684, 0x220, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D3_REV__IPU_DISPB_D3_REV			IOMUX_PAD(0x688, 0x224, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_REV__IPU_DISPB_SER_RS			IOMUX_PAD(0x688, 0x224, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_REV__GPIO1_3				IOMUX_PAD(0x688, 0x224, 5, 0x84c, 1, NO_PAD_CTRL)
+#define MX35_PAD_D3_REV__SDMA_DEBUG_BUS_RWB			IOMUX_PAD(0x688, 0x224, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_REV__ARM11P_TOP_TRACE_20			IOMUX_PAD(0x688, 0x224, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D3_CLS__IPU_DISPB_D3_CLS			IOMUX_PAD(0x68c, 0x228, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_CLS__IPU_DISPB_CS2				IOMUX_PAD(0x68c, 0x228, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_CLS__GPIO1_4				IOMUX_PAD(0x68c, 0x228, 5, 0x850, 2, NO_PAD_CTRL)
+#define MX35_PAD_D3_CLS__SDMA_DEBUG_BUS_DEVICE_0		IOMUX_PAD(0x68c, 0x228, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_CLS__ARM11P_TOP_TRACE_21			IOMUX_PAD(0x68c, 0x228, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D3_SPL__IPU_DISPB_D3_SPL			IOMUX_PAD(0x690, 0x22c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_SPL__IPU_DISPB_D12_VSYNC			IOMUX_PAD(0x690, 0x22c, 2, 0x928, 2, NO_PAD_CTRL)
+#define MX35_PAD_D3_SPL__GPIO1_5				IOMUX_PAD(0x690, 0x22c, 5, 0x854, 2, NO_PAD_CTRL)
+#define MX35_PAD_D3_SPL__SDMA_DEBUG_BUS_DEVICE_1		IOMUX_PAD(0x690, 0x22c, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_SPL__ARM11P_TOP_TRACE_22			IOMUX_PAD(0x690, 0x22c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD1_CMD__ESDHC1_CMD				IOMUX_PAD(0x694, 0x230, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CMD__MSHC_SCLK				IOMUX_PAD(0x694, 0x230, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CMD__IPU_DISPB_D0_VSYNC			IOMUX_PAD(0x694, 0x230, 3, 0x924, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CMD__USB_TOP_USBOTG_DATA_4			IOMUX_PAD(0x694, 0x230, 4, 0x9b4, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CMD__GPIO1_6				IOMUX_PAD(0x694, 0x230, 5, 0x858, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CMD__ARM11P_TOP_TRCTL			IOMUX_PAD(0x694, 0x230, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD1_CLK__ESDHC1_CLK				IOMUX_PAD(0x698, 0x234, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CLK__MSHC_BS				IOMUX_PAD(0x698, 0x234, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CLK__IPU_DISPB_BCLK			IOMUX_PAD(0x698, 0x234, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CLK__USB_TOP_USBOTG_DATA_5			IOMUX_PAD(0x698, 0x234, 4, 0x9b8, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CLK__GPIO1_7				IOMUX_PAD(0x698, 0x234, 5, 0x85c, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CLK__ARM11P_TOP_TRCLK			IOMUX_PAD(0x698, 0x234, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD1_DATA0__ESDHC1_DAT0				IOMUX_PAD(0x69c, 0x238, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA0__MSHC_DATA_0				IOMUX_PAD(0x69c, 0x238, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA0__IPU_DISPB_CS0			IOMUX_PAD(0x69c, 0x238, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA0__USB_TOP_USBOTG_DATA_6		IOMUX_PAD(0x69c, 0x238, 4, 0x9bc, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA0__GPIO1_8				IOMUX_PAD(0x69c, 0x238, 5, 0x860, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA0__ARM11P_TOP_TRACE_23			IOMUX_PAD(0x69c, 0x238, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD1_DATA1__ESDHC1_DAT1				IOMUX_PAD(0x6a0, 0x23c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA1__MSHC_DATA_1				IOMUX_PAD(0x6a0, 0x23c, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA1__IPU_DISPB_PAR_RS			IOMUX_PAD(0x6a0, 0x23c, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA1__USB_TOP_USBOTG_DATA_0		IOMUX_PAD(0x6a0, 0x23c, 4, 0x9a4, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA1__GPIO1_9				IOMUX_PAD(0x6a0, 0x23c, 5, 0x864, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA1__ARM11P_TOP_TRACE_24			IOMUX_PAD(0x6a0, 0x23c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD1_DATA2__ESDHC1_DAT2				IOMUX_PAD(0x6a4, 0x240, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA2__MSHC_DATA_2				IOMUX_PAD(0x6a4, 0x240, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA2__IPU_DISPB_WR			IOMUX_PAD(0x6a4, 0x240, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA2__USB_TOP_USBOTG_DATA_1		IOMUX_PAD(0x6a4, 0x240, 4, 0x9a8, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA2__GPIO1_10				IOMUX_PAD(0x6a4, 0x240, 5, 0x830, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA2__ARM11P_TOP_TRACE_25			IOMUX_PAD(0x6a4, 0x240, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD1_DATA3__ESDHC1_DAT3				IOMUX_PAD(0x6a8, 0x244, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA3__MSHC_DATA_3				IOMUX_PAD(0x6a8, 0x244, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA3__IPU_DISPB_RD			IOMUX_PAD(0x6a8, 0x244, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA3__USB_TOP_USBOTG_DATA_2		IOMUX_PAD(0x6a8, 0x244, 4, 0x9ac, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA3__GPIO1_11				IOMUX_PAD(0x6a8, 0x244, 5, 0x834, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA3__ARM11P_TOP_TRACE_26			IOMUX_PAD(0x6a8, 0x244, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD2_CMD__ESDHC2_CMD				IOMUX_PAD(0x6ac, 0x248, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CMD__I2C3_SCL				IOMUX_PAD(0x6ac, 0x248, 1, 0x91c, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CMD__ESDHC1_DAT4				IOMUX_PAD(0x6ac, 0x248, 2, 0x804, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CMD__IPU_CSI_D_2				IOMUX_PAD(0x6ac, 0x248, 3, 0x938, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CMD__USB_TOP_USBH2_DATA_4			IOMUX_PAD(0x6ac, 0x248, 4, 0x9dc, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CMD__GPIO2_0				IOMUX_PAD(0x6ac, 0x248, 5, 0x868, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CMD__SPDIF_SPDIF_OUT1			IOMUX_PAD(0x6ac, 0x248, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CMD__IPU_DISPB_D12_VSYNC			IOMUX_PAD(0x6ac, 0x248, 7, 0x928, 3, NO_PAD_CTRL)
+
+#define MX35_PAD_SD2_CLK__ESDHC2_CLK				IOMUX_PAD(0x6b0, 0x24c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CLK__I2C3_SDA				IOMUX_PAD(0x6b0, 0x24c, 1, 0x920, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CLK__ESDHC1_DAT5				IOMUX_PAD(0x6b0, 0x24c, 2, 0x808, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CLK__IPU_CSI_D_3				IOMUX_PAD(0x6b0, 0x24c, 3, 0x93c, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CLK__USB_TOP_USBH2_DATA_5			IOMUX_PAD(0x6b0, 0x24c, 4, 0x9e0, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CLK__GPIO2_1				IOMUX_PAD(0x6b0, 0x24c, 5, 0x894, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CLK__SPDIF_SPDIF_IN1			IOMUX_PAD(0x6b0, 0x24c, 6, 0x998, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CLK__IPU_DISPB_CS2				IOMUX_PAD(0x6b0, 0x24c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD2_DATA0__ESDHC2_DAT0				IOMUX_PAD(0x6b4, 0x250, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA0__UART3_RXD_MUX			IOMUX_PAD(0x6b4, 0x250, 1, 0x9a0, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA0__ESDHC1_DAT6				IOMUX_PAD(0x6b4, 0x250, 2, 0x80c, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA0__IPU_CSI_D_4				IOMUX_PAD(0x6b4, 0x250, 3, 0x940, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA0__USB_TOP_USBH2_DATA_6		IOMUX_PAD(0x6b4, 0x250, 4, 0x9e4, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA0__GPIO2_2				IOMUX_PAD(0x6b4, 0x250, 5, 0x8c0, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA0__SPDIF_SPDIF_EXTCLK			IOMUX_PAD(0x6b4, 0x250, 6, 0x994, 3, NO_PAD_CTRL)
+
+#define MX35_PAD_SD2_DATA1__ESDHC2_DAT1				IOMUX_PAD(0x6b8, 0x254, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA1__UART3_TXD_MUX			IOMUX_PAD(0x6b8, 0x254, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA1__ESDHC1_DAT7				IOMUX_PAD(0x6b8, 0x254, 2, 0x810, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA1__IPU_CSI_D_5				IOMUX_PAD(0x6b8, 0x254, 3, 0x944, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA1__USB_TOP_USBH2_DATA_0		IOMUX_PAD(0x6b8, 0x254, 4, 0x9cc, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA1__GPIO2_3				IOMUX_PAD(0x6b8, 0x254, 5, 0x8cc, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_SD2_DATA2__ESDHC2_DAT2				IOMUX_PAD(0x6bc, 0x258, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA2__UART3_RTS				IOMUX_PAD(0x6bc, 0x258, 1, 0x99c, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA2__CAN1_RXCAN				IOMUX_PAD(0x6bc, 0x258, 2, 0x7c8, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA2__IPU_CSI_D_6				IOMUX_PAD(0x6bc, 0x258, 3, 0x948, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA2__USB_TOP_USBH2_DATA_1		IOMUX_PAD(0x6bc, 0x258, 4, 0x9d0, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA2__GPIO2_4				IOMUX_PAD(0x6bc, 0x258, 5, 0x8d0, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_SD2_DATA3__ESDHC2_DAT3				IOMUX_PAD(0x6c0, 0x25c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA3__UART3_CTS				IOMUX_PAD(0x6c0, 0x25c, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA3__CAN1_TXCAN				IOMUX_PAD(0x6c0, 0x25c, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA3__IPU_CSI_D_7				IOMUX_PAD(0x6c0, 0x25c, 3, 0x94c, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA3__USB_TOP_USBH2_DATA_2		IOMUX_PAD(0x6c0, 0x25c, 4, 0x9d4, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA3__GPIO2_5				IOMUX_PAD(0x6c0, 0x25c, 5, 0x8d4, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_CS0__ATA_CS0				IOMUX_PAD(0x6c4, 0x260, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS0__CSPI1_SS3				IOMUX_PAD(0x6c4, 0x260, 1, 0x7dc, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS0__IPU_DISPB_CS1				IOMUX_PAD(0x6c4, 0x260, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS0__GPIO2_6				IOMUX_PAD(0x6c4, 0x260, 5, 0x8d8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS0__IPU_DIAGB_0				IOMUX_PAD(0x6c4, 0x260, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS0__ARM11P_TOP_MAX1_HMASTER_0		IOMUX_PAD(0x6c4, 0x260, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_CS1__ATA_CS1				IOMUX_PAD(0x6c8, 0x264, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS1__IPU_DISPB_CS2				IOMUX_PAD(0x6c8, 0x264, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS1__CSPI2_SS0				IOMUX_PAD(0x6c8, 0x264, 4, 0x7f0, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS1__GPIO2_7				IOMUX_PAD(0x6c8, 0x264, 5, 0x8dc, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS1__IPU_DIAGB_1				IOMUX_PAD(0x6c8, 0x264, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS1__ARM11P_TOP_MAX1_HMASTER_1		IOMUX_PAD(0x6c8, 0x264, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DIOR__ATA_DIOR				IOMUX_PAD(0x6cc, 0x268, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOR__ESDHC3_DAT0				IOMUX_PAD(0x6cc, 0x268, 1, 0x81c, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOR__USB_TOP_USBOTG_DIR			IOMUX_PAD(0x6cc, 0x268, 2, 0x9c4, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOR__IPU_DISPB_BE0			IOMUX_PAD(0x6cc, 0x268, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOR__CSPI2_SS1				IOMUX_PAD(0x6cc, 0x268, 4, 0x7f4, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOR__GPIO2_8				IOMUX_PAD(0x6cc, 0x268, 5, 0x8e0, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOR__IPU_DIAGB_2				IOMUX_PAD(0x6cc, 0x268, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOR__ARM11P_TOP_MAX1_HMASTER_2		IOMUX_PAD(0x6cc, 0x268, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DIOW__ATA_DIOW				IOMUX_PAD(0x6d0, 0x26c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOW__ESDHC3_DAT1				IOMUX_PAD(0x6d0, 0x26c, 1, 0x820, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOW__USB_TOP_USBOTG_STP			IOMUX_PAD(0x6d0, 0x26c, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOW__IPU_DISPB_BE1			IOMUX_PAD(0x6d0, 0x26c, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOW__CSPI2_MOSI				IOMUX_PAD(0x6d0, 0x26c, 4, 0x7ec, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOW__GPIO2_9				IOMUX_PAD(0x6d0, 0x26c, 5, 0x8e4, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOW__IPU_DIAGB_3				IOMUX_PAD(0x6d0, 0x26c, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOW__ARM11P_TOP_MAX1_HMASTER_3		IOMUX_PAD(0x6d0, 0x26c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DMACK__ATA_DMACK				IOMUX_PAD(0x6d4, 0x270, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMACK__ESDHC3_DAT2				IOMUX_PAD(0x6d4, 0x270, 1, 0x824, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMACK__USB_TOP_USBOTG_NXT			IOMUX_PAD(0x6d4, 0x270, 2, 0x9c8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMACK__CSPI2_MISO				IOMUX_PAD(0x6d4, 0x270, 4, 0x7e8, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMACK__GPIO2_10				IOMUX_PAD(0x6d4, 0x270, 5, 0x86c, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMACK__IPU_DIAGB_4				IOMUX_PAD(0x6d4, 0x270, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMACK__ARM11P_TOP_MAX0_HMASTER_0		IOMUX_PAD(0x6d4, 0x270, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_RESET_B__ATA_RESET_B			IOMUX_PAD(0x6d8, 0x274, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_RESET_B__ESDHC3_DAT3			IOMUX_PAD(0x6d8, 0x274, 1, 0x828, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_RESET_B__USB_TOP_USBOTG_DATA_0		IOMUX_PAD(0x6d8, 0x274, 2, 0x9a4, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_RESET_B__IPU_DISPB_SD_D_O			IOMUX_PAD(0x6d8, 0x274, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_RESET_B__CSPI2_RDY				IOMUX_PAD(0x6d8, 0x274, 4, 0x7e4, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_RESET_B__GPIO2_11				IOMUX_PAD(0x6d8, 0x274, 5, 0x870, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_RESET_B__IPU_DIAGB_5			IOMUX_PAD(0x6d8, 0x274, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_RESET_B__ARM11P_TOP_MAX0_HMASTER_1		IOMUX_PAD(0x6d8, 0x274, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_IORDY__ATA_IORDY				IOMUX_PAD(0x6dc, 0x278, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_IORDY__ESDHC3_DAT4				IOMUX_PAD(0x6dc, 0x278, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_IORDY__USB_TOP_USBOTG_DATA_1		IOMUX_PAD(0x6dc, 0x278, 2, 0x9a8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_IORDY__IPU_DISPB_SD_D_IO			IOMUX_PAD(0x6dc, 0x278, 3, 0x92c, 3, NO_PAD_CTRL)
+#define MX35_PAD_ATA_IORDY__ESDHC2_DAT4				IOMUX_PAD(0x6dc, 0x278, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_IORDY__GPIO2_12				IOMUX_PAD(0x6dc, 0x278, 5, 0x874, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_IORDY__IPU_DIAGB_6				IOMUX_PAD(0x6dc, 0x278, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_IORDY__ARM11P_TOP_MAX0_HMASTER_2		IOMUX_PAD(0x6dc, 0x278, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA0__ATA_DATA_0				IOMUX_PAD(0x6e0, 0x27c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA0__ESDHC3_DAT5				IOMUX_PAD(0x6e0, 0x27c, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA0__USB_TOP_USBOTG_DATA_2		IOMUX_PAD(0x6e0, 0x27c, 2, 0x9ac, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA0__IPU_DISPB_D12_VSYNC			IOMUX_PAD(0x6e0, 0x27c, 3, 0x928, 4, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA0__ESDHC2_DAT5				IOMUX_PAD(0x6e0, 0x27c, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA0__GPIO2_13				IOMUX_PAD(0x6e0, 0x27c, 5, 0x878, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA0__IPU_DIAGB_7				IOMUX_PAD(0x6e0, 0x27c, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA0__ARM11P_TOP_MAX0_HMASTER_3		IOMUX_PAD(0x6e0, 0x27c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA1__ATA_DATA_1				IOMUX_PAD(0x6e4, 0x280, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA1__ESDHC3_DAT6				IOMUX_PAD(0x6e4, 0x280, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA1__USB_TOP_USBOTG_DATA_3		IOMUX_PAD(0x6e4, 0x280, 2, 0x9b0, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA1__IPU_DISPB_SD_CLK			IOMUX_PAD(0x6e4, 0x280, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA1__ESDHC2_DAT6				IOMUX_PAD(0x6e4, 0x280, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA1__GPIO2_14				IOMUX_PAD(0x6e4, 0x280, 5, 0x87c, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA1__IPU_DIAGB_8				IOMUX_PAD(0x6e4, 0x280, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA1__ARM11P_TOP_TRACE_27			IOMUX_PAD(0x6e4, 0x280, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA2__ATA_DATA_2				IOMUX_PAD(0x6e8, 0x284, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA2__ESDHC3_DAT7				IOMUX_PAD(0x6e8, 0x284, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA2__USB_TOP_USBOTG_DATA_4		IOMUX_PAD(0x6e8, 0x284, 2, 0x9b4, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA2__IPU_DISPB_SER_RS			IOMUX_PAD(0x6e8, 0x284, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA2__ESDHC2_DAT7				IOMUX_PAD(0x6e8, 0x284, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA2__GPIO2_15				IOMUX_PAD(0x6e8, 0x284, 5, 0x880, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA2__IPU_DIAGB_9				IOMUX_PAD(0x6e8, 0x284, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA2__ARM11P_TOP_TRACE_28			IOMUX_PAD(0x6e8, 0x284, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA3__ATA_DATA_3				IOMUX_PAD(0x6ec, 0x288, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__ESDHC3_CLK				IOMUX_PAD(0x6ec, 0x288, 1, 0x814, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__USB_TOP_USBOTG_DATA_5		IOMUX_PAD(0x6ec, 0x288, 2, 0x9b8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__CSPI2_SCLK				IOMUX_PAD(0x6ec, 0x288, 4, 0x7e0, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__GPIO2_16				IOMUX_PAD(0x6ec, 0x288, 5, 0x884, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__IPU_DIAGB_10			IOMUX_PAD(0x6ec, 0x288, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__ARM11P_TOP_TRACE_29			IOMUX_PAD(0x6ec, 0x288, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA4__ATA_DATA_4				IOMUX_PAD(0x6f0, 0x28c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA4__ESDHC3_CMD				IOMUX_PAD(0x6f0, 0x28c, 1, 0x818, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA4__USB_TOP_USBOTG_DATA_6		IOMUX_PAD(0x6f0, 0x28c, 2, 0x9bc, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA4__GPIO2_17				IOMUX_PAD(0x6f0, 0x28c, 5, 0x888, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA4__IPU_DIAGB_11			IOMUX_PAD(0x6f0, 0x28c, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA4__ARM11P_TOP_TRACE_30			IOMUX_PAD(0x6f0, 0x28c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA5__ATA_DATA_5				IOMUX_PAD(0x6f4, 0x290, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA5__USB_TOP_USBOTG_DATA_7		IOMUX_PAD(0x6f4, 0x290, 2, 0x9c0, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA5__GPIO2_18				IOMUX_PAD(0x6f4, 0x290, 5, 0x88c, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA5__IPU_DIAGB_12			IOMUX_PAD(0x6f4, 0x290, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA5__ARM11P_TOP_TRACE_31			IOMUX_PAD(0x6f4, 0x290, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA6__ATA_DATA_6				IOMUX_PAD(0x6f8, 0x294, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA6__CAN1_TXCAN				IOMUX_PAD(0x6f8, 0x294, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA6__UART1_DTR				IOMUX_PAD(0x6f8, 0x294, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA6__AUDMUX_AUD6_TXD			IOMUX_PAD(0x6f8, 0x294, 3, 0x7b4, 0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA6__GPIO2_19				IOMUX_PAD(0x6f8, 0x294, 5, 0x890, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA6__IPU_DIAGB_13			IOMUX_PAD(0x6f8, 0x294, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA7__ATA_DATA_7				IOMUX_PAD(0x6fc, 0x298, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA7__CAN1_RXCAN				IOMUX_PAD(0x6fc, 0x298, 1, 0x7c8, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA7__UART1_DSR				IOMUX_PAD(0x6fc, 0x298, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA7__AUDMUX_AUD6_RXD			IOMUX_PAD(0x6fc, 0x298, 3, 0x7b0, 0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA7__GPIO2_20				IOMUX_PAD(0x6fc, 0x298, 5, 0x898, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA7__IPU_DIAGB_14			IOMUX_PAD(0x6fc, 0x298, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA8__ATA_DATA_8				IOMUX_PAD(0x700, 0x29c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA8__UART3_RTS				IOMUX_PAD(0x700, 0x29c, 1, 0x99c, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA8__UART1_RI				IOMUX_PAD(0x700, 0x29c, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA8__AUDMUX_AUD6_TXC			IOMUX_PAD(0x700, 0x29c, 3, 0x7c0, 0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA8__GPIO2_21				IOMUX_PAD(0x700, 0x29c, 5, 0x89c, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA8__IPU_DIAGB_15			IOMUX_PAD(0x700, 0x29c, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA9__ATA_DATA_9				IOMUX_PAD(0x704, 0x2a0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA9__UART3_CTS				IOMUX_PAD(0x704, 0x2a0, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA9__UART1_DCD				IOMUX_PAD(0x704, 0x2a0, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA9__AUDMUX_AUD6_TXFS			IOMUX_PAD(0x704, 0x2a0, 3, 0x7c4, 0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA9__GPIO2_22				IOMUX_PAD(0x704, 0x2a0, 5, 0x8a0, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA9__IPU_DIAGB_16			IOMUX_PAD(0x704, 0x2a0, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA10__ATA_DATA_10			IOMUX_PAD(0x708, 0x2a4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA10__UART3_RXD_MUX			IOMUX_PAD(0x708, 0x2a4, 1, 0x9a0, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA10__AUDMUX_AUD6_RXC			IOMUX_PAD(0x708, 0x2a4, 3, 0x7b8, 0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA10__GPIO2_23				IOMUX_PAD(0x708, 0x2a4, 5, 0x8a4, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA10__IPU_DIAGB_17			IOMUX_PAD(0x708, 0x2a4, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA11__ATA_DATA_11			IOMUX_PAD(0x70c, 0x2a8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA11__UART3_TXD_MUX			IOMUX_PAD(0x70c, 0x2a8, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA11__AUDMUX_AUD6_RXFS			IOMUX_PAD(0x70c, 0x2a8, 3, 0x7bc, 0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA11__GPIO2_24				IOMUX_PAD(0x70c, 0x2a8, 5, 0x8a8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA11__IPU_DIAGB_18			IOMUX_PAD(0x70c, 0x2a8, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA12__ATA_DATA_12			IOMUX_PAD(0x710, 0x2ac, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA12__I2C3_SCL				IOMUX_PAD(0x710, 0x2ac, 1, 0x91c, 3, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA12__GPIO2_25				IOMUX_PAD(0x710, 0x2ac, 5, 0x8ac, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA12__IPU_DIAGB_19			IOMUX_PAD(0x710, 0x2ac, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA13__ATA_DATA_13			IOMUX_PAD(0x714, 0x2b0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA13__I2C3_SDA				IOMUX_PAD(0x714, 0x2b0, 1, 0x920, 3, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA13__GPIO2_26				IOMUX_PAD(0x714, 0x2b0, 5, 0x8b0, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA13__IPU_DIAGB_20			IOMUX_PAD(0x714, 0x2b0, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA14__ATA_DATA_14			IOMUX_PAD(0x718, 0x2b4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA14__IPU_CSI_D_0			IOMUX_PAD(0x718, 0x2b4, 1, 0x930, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA14__KPP_ROW_0				IOMUX_PAD(0x718, 0x2b4, 3, 0x970, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA14__GPIO2_27				IOMUX_PAD(0x718, 0x2b4, 5, 0x8b4, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA14__IPU_DIAGB_21			IOMUX_PAD(0x718, 0x2b4, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA15__ATA_DATA_15			IOMUX_PAD(0x71c, 0x2b8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA15__IPU_CSI_D_1			IOMUX_PAD(0x71c, 0x2b8, 1, 0x934, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA15__KPP_ROW_1				IOMUX_PAD(0x71c, 0x2b8, 3, 0x974, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA15__GPIO2_28				IOMUX_PAD(0x71c, 0x2b8, 5, 0x8b8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA15__IPU_DIAGB_22			IOMUX_PAD(0x71c, 0x2b8, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_INTRQ__ATA_INTRQ				IOMUX_PAD(0x720, 0x2bc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_INTRQ__IPU_CSI_D_2				IOMUX_PAD(0x720, 0x2bc, 1, 0x938, 3, NO_PAD_CTRL)
+#define MX35_PAD_ATA_INTRQ__KPP_ROW_2				IOMUX_PAD(0x720, 0x2bc, 3, 0x978, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_INTRQ__GPIO2_29				IOMUX_PAD(0x720, 0x2bc, 5, 0x8bc, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_INTRQ__IPU_DIAGB_23			IOMUX_PAD(0x720, 0x2bc, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_BUFF_EN__ATA_BUFFER_EN			IOMUX_PAD(0x724, 0x2c0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_BUFF_EN__IPU_CSI_D_3			IOMUX_PAD(0x724, 0x2c0, 1, 0x93c, 3, NO_PAD_CTRL)
+#define MX35_PAD_ATA_BUFF_EN__KPP_ROW_3				IOMUX_PAD(0x724, 0x2c0, 3, 0x97c, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_BUFF_EN__GPIO2_30				IOMUX_PAD(0x724, 0x2c0, 5, 0x8c4, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_BUFF_EN__IPU_DIAGB_24			IOMUX_PAD(0x724, 0x2c0, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DMARQ__ATA_DMARQ				IOMUX_PAD(0x728, 0x2c4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMARQ__IPU_CSI_D_4				IOMUX_PAD(0x728, 0x2c4, 1, 0x940, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMARQ__KPP_COL_0				IOMUX_PAD(0x728, 0x2c4, 3, 0x950, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMARQ__GPIO2_31				IOMUX_PAD(0x728, 0x2c4, 5, 0x8c8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMARQ__IPU_DIAGB_25			IOMUX_PAD(0x728, 0x2c4, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMARQ__ECT_CTI_TRIG_IN1_4			IOMUX_PAD(0x728, 0x2c4, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DA0__ATA_DA_0				IOMUX_PAD(0x72c, 0x2c8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA0__IPU_CSI_D_5				IOMUX_PAD(0x72c, 0x2c8, 1, 0x944, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA0__KPP_COL_1				IOMUX_PAD(0x72c, 0x2c8, 3, 0x954, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA0__GPIO3_0				IOMUX_PAD(0x72c, 0x2c8, 5, 0x8e8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA0__IPU_DIAGB_26				IOMUX_PAD(0x72c, 0x2c8, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA0__ECT_CTI_TRIG_IN1_5			IOMUX_PAD(0x72c, 0x2c8, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DA1__ATA_DA_1				IOMUX_PAD(0x730, 0x2cc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA1__IPU_CSI_D_6				IOMUX_PAD(0x730, 0x2cc, 1, 0x948, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA1__KPP_COL_2				IOMUX_PAD(0x730, 0x2cc, 3, 0x958, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA1__GPIO3_1				IOMUX_PAD(0x730, 0x2cc, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA1__IPU_DIAGB_27				IOMUX_PAD(0x730, 0x2cc, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA1__ECT_CTI_TRIG_IN1_6			IOMUX_PAD(0x730, 0x2cc, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DA2__ATA_DA_2				IOMUX_PAD(0x734, 0x2d0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA2__IPU_CSI_D_7				IOMUX_PAD(0x734, 0x2d0, 1, 0x94c, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA2__KPP_COL_3				IOMUX_PAD(0x734, 0x2d0, 3, 0x95c, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA2__GPIO3_2				IOMUX_PAD(0x734, 0x2d0, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA2__IPU_DIAGB_28				IOMUX_PAD(0x734, 0x2d0, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA2__ECT_CTI_TRIG_IN1_7			IOMUX_PAD(0x734, 0x2d0, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_MLB_CLK__MLB_MLBCLK				IOMUX_PAD(0x738, 0x2d4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_MLB_CLK__GPIO3_3				IOMUX_PAD(0x738, 0x2d4, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_MLB_DAT__MLB_MLBDAT				IOMUX_PAD(0x73c, 0x2d8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_MLB_DAT__GPIO3_4				IOMUX_PAD(0x73c, 0x2d8, 5, 0x904, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_MLB_SIG__MLB_MLBSIG				IOMUX_PAD(0x740, 0x2dc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_MLB_SIG__GPIO3_5				IOMUX_PAD(0x740, 0x2dc, 5, 0x908, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_TX_CLK__FEC_TX_CLK				IOMUX_PAD(0x744, 0x2e0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_CLK__ESDHC1_DAT4			IOMUX_PAD(0x744, 0x2e0, 1, 0x804, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_CLK__UART3_RXD_MUX			IOMUX_PAD(0x744, 0x2e0, 2, 0x9a0, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_CLK__USB_TOP_USBH2_DIR			IOMUX_PAD(0x744, 0x2e0, 3, 0x9ec, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_CLK__CSPI2_MOSI				IOMUX_PAD(0x744, 0x2e0, 4, 0x7ec, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_CLK__GPIO3_6				IOMUX_PAD(0x744, 0x2e0, 5, 0x90c, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_CLK__IPU_DISPB_D12_VSYNC		IOMUX_PAD(0x744, 0x2e0, 6, 0x928, 5, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_CLK__ARM11P_TOP_EVNTBUS_0		IOMUX_PAD(0x744, 0x2e0, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_RX_CLK__FEC_RX_CLK				IOMUX_PAD(0x748, 0x2e4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_CLK__ESDHC1_DAT5			IOMUX_PAD(0x748, 0x2e4, 1, 0x808, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_CLK__UART3_TXD_MUX			IOMUX_PAD(0x748, 0x2e4, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_CLK__USB_TOP_USBH2_STP			IOMUX_PAD(0x748, 0x2e4, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_CLK__CSPI2_MISO				IOMUX_PAD(0x748, 0x2e4, 4, 0x7e8, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_CLK__GPIO3_7				IOMUX_PAD(0x748, 0x2e4, 5, 0x910, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_CLK__IPU_DISPB_SD_D_I			IOMUX_PAD(0x748, 0x2e4, 6, 0x92c, 4, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_CLK__ARM11P_TOP_EVNTBUS_1		IOMUX_PAD(0x748, 0x2e4, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_RX_DV__FEC_RX_DV				IOMUX_PAD(0x74c, 0x2e8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_DV__ESDHC1_DAT6				IOMUX_PAD(0x74c, 0x2e8, 1, 0x80c, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_DV__UART3_RTS				IOMUX_PAD(0x74c, 0x2e8, 2, 0x99c, 2, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_DV__USB_TOP_USBH2_NXT			IOMUX_PAD(0x74c, 0x2e8, 3, 0x9f0, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_DV__CSPI2_SCLK				IOMUX_PAD(0x74c, 0x2e8, 4, 0x7e0, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_DV__GPIO3_8				IOMUX_PAD(0x74c, 0x2e8, 5, 0x914, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_DV__IPU_DISPB_SD_CLK			IOMUX_PAD(0x74c, 0x2e8, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_DV__ARM11P_TOP_EVNTBUS_2		IOMUX_PAD(0x74c, 0x2e8, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_COL__FEC_COL				IOMUX_PAD(0x750, 0x2ec, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_COL__ESDHC1_DAT7				IOMUX_PAD(0x750, 0x2ec, 1, 0x810, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_COL__UART3_CTS				IOMUX_PAD(0x750, 0x2ec, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_COL__USB_TOP_USBH2_DATA_0			IOMUX_PAD(0x750, 0x2ec, 3, 0x9cc, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_COL__CSPI2_RDY				IOMUX_PAD(0x750, 0x2ec, 4, 0x7e4, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_COL__GPIO3_9				IOMUX_PAD(0x750, 0x2ec, 5, 0x918, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_COL__IPU_DISPB_SER_RS			IOMUX_PAD(0x750, 0x2ec, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_COL__ARM11P_TOP_EVNTBUS_3			IOMUX_PAD(0x750, 0x2ec, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_RDATA0__FEC_RDATA_0			IOMUX_PAD(0x754, 0x2f0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA0__PWM_PWMO				IOMUX_PAD(0x754, 0x2f0, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA0__UART3_DTR				IOMUX_PAD(0x754, 0x2f0, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA0__USB_TOP_USBH2_DATA_1		IOMUX_PAD(0x754, 0x2f0, 3, 0x9d0, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA0__CSPI2_SS0				IOMUX_PAD(0x754, 0x2f0, 4, 0x7f0, 2, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA0__GPIO3_10				IOMUX_PAD(0x754, 0x2f0, 5, 0x8ec, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA0__IPU_DISPB_CS1			IOMUX_PAD(0x754, 0x2f0, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA0__ARM11P_TOP_EVNTBUS_4		IOMUX_PAD(0x754, 0x2f0, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_TDATA0__FEC_TDATA_0			IOMUX_PAD(0x758, 0x2f4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA0__SPDIF_SPDIF_OUT1			IOMUX_PAD(0x758, 0x2f4, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA0__UART3_DSR				IOMUX_PAD(0x758, 0x2f4, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA0__USB_TOP_USBH2_DATA_2		IOMUX_PAD(0x758, 0x2f4, 3, 0x9d4, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA0__CSPI2_SS1				IOMUX_PAD(0x758, 0x2f4, 4, 0x7f4, 2, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA0__GPIO3_11				IOMUX_PAD(0x758, 0x2f4, 5, 0x8f0, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA0__IPU_DISPB_CS0			IOMUX_PAD(0x758, 0x2f4, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA0__ARM11P_TOP_EVNTBUS_5		IOMUX_PAD(0x758, 0x2f4, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_TX_EN__FEC_TX_EN				IOMUX_PAD(0x75c, 0x2f8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_EN__SPDIF_SPDIF_IN1			IOMUX_PAD(0x75c, 0x2f8, 1, 0x998, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_EN__UART3_RI				IOMUX_PAD(0x75c, 0x2f8, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_EN__USB_TOP_USBH2_DATA_3		IOMUX_PAD(0x75c, 0x2f8, 3, 0x9d8, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_EN__GPIO3_12				IOMUX_PAD(0x75c, 0x2f8, 5, 0x8f4, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_EN__IPU_DISPB_PAR_RS			IOMUX_PAD(0x75c, 0x2f8, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_EN__ARM11P_TOP_EVNTBUS_6		IOMUX_PAD(0x75c, 0x2f8, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_MDC__FEC_MDC				IOMUX_PAD(0x760, 0x2fc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDC__CAN2_TXCAN				IOMUX_PAD(0x760, 0x2fc, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDC__UART3_DCD				IOMUX_PAD(0x760, 0x2fc, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDC__USB_TOP_USBH2_DATA_4			IOMUX_PAD(0x760, 0x2fc, 3, 0x9dc, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDC__GPIO3_13				IOMUX_PAD(0x760, 0x2fc, 5, 0x8f8, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDC__IPU_DISPB_WR				IOMUX_PAD(0x760, 0x2fc, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDC__ARM11P_TOP_EVNTBUS_7			IOMUX_PAD(0x760, 0x2fc, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_MDIO__FEC_MDIO				IOMUX_PAD(0x764, 0x300, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDIO__CAN2_RXCAN				IOMUX_PAD(0x764, 0x300, 1, 0x7cc, 2, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDIO__USB_TOP_USBH2_DATA_5			IOMUX_PAD(0x764, 0x300, 3, 0x9e0, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDIO__GPIO3_14				IOMUX_PAD(0x764, 0x300, 5, 0x8fc, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDIO__IPU_DISPB_RD				IOMUX_PAD(0x764, 0x300, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDIO__ARM11P_TOP_EVNTBUS_8			IOMUX_PAD(0x764, 0x300, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_TX_ERR__FEC_TX_ERR				IOMUX_PAD(0x768, 0x304, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_ERR__OWIRE_LINE				IOMUX_PAD(0x768, 0x304, 1, 0x990, 2, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_ERR__SPDIF_SPDIF_EXTCLK			IOMUX_PAD(0x768, 0x304, 2, 0x994, 4, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_ERR__USB_TOP_USBH2_DATA_6		IOMUX_PAD(0x768, 0x304, 3, 0x9e4, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_ERR__GPIO3_15				IOMUX_PAD(0x768, 0x304, 5, 0x900, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_ERR__IPU_DISPB_D0_VSYNC			IOMUX_PAD(0x768, 0x304, 6, 0x924, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_ERR__ARM11P_TOP_EVNTBUS_9		IOMUX_PAD(0x768, 0x304, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_RX_ERR__FEC_RX_ERR				IOMUX_PAD(0x76c, 0x308, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_ERR__IPU_CSI_D_0			IOMUX_PAD(0x76c, 0x308, 1, 0x930, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_ERR__USB_TOP_USBH2_DATA_7		IOMUX_PAD(0x76c, 0x308, 3, 0x9e8, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_ERR__KPP_COL_4				IOMUX_PAD(0x76c, 0x308, 4, 0x960, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_ERR__GPIO3_16				IOMUX_PAD(0x76c, 0x308, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_ERR__IPU_DISPB_SD_D_IO			IOMUX_PAD(0x76c, 0x308, 6, 0x92c, 5, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_CRS__FEC_CRS				IOMUX_PAD(0x770, 0x30c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_CRS__IPU_CSI_D_1				IOMUX_PAD(0x770, 0x30c, 1, 0x934, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_CRS__USB_TOP_USBH2_PWR			IOMUX_PAD(0x770, 0x30c, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_CRS__KPP_COL_5				IOMUX_PAD(0x770, 0x30c, 4, 0x964, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_CRS__GPIO3_17				IOMUX_PAD(0x770, 0x30c, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_CRS__IPU_FLASH_STROBE			IOMUX_PAD(0x770, 0x30c, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_RDATA1__FEC_RDATA_1			IOMUX_PAD(0x774, 0x310, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA1__IPU_CSI_D_2			IOMUX_PAD(0x774, 0x310, 1, 0x938, 4, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA1__AUDMUX_AUD6_RXC			IOMUX_PAD(0x774, 0x310, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA1__USB_TOP_USBH2_OC			IOMUX_PAD(0x774, 0x310, 3, 0x9f4, 2, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA1__KPP_COL_6				IOMUX_PAD(0x774, 0x310, 4, 0x968, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA1__GPIO3_18				IOMUX_PAD(0x774, 0x310, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA1__IPU_DISPB_BE0			IOMUX_PAD(0x774, 0x310, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_TDATA1__FEC_TDATA_1			IOMUX_PAD(0x778, 0x314, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA1__IPU_CSI_D_3			IOMUX_PAD(0x778, 0x314, 1, 0x93c, 4, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA1__AUDMUX_AUD6_RXFS			IOMUX_PAD(0x778, 0x314, 2, 0x7bc, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA1__KPP_COL_7				IOMUX_PAD(0x778, 0x314, 4, 0x96c, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA1__GPIO3_19				IOMUX_PAD(0x778, 0x314, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA1__IPU_DISPB_BE1			IOMUX_PAD(0x778, 0x314, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_RDATA2__FEC_RDATA_2			IOMUX_PAD(0x77c, 0x318, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA2__IPU_CSI_D_4			IOMUX_PAD(0x77c, 0x318, 1, 0x940, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA2__AUDMUX_AUD6_TXD			IOMUX_PAD(0x77c, 0x318, 2, 0x7b4, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA2__KPP_ROW_4				IOMUX_PAD(0x77c, 0x318, 4, 0x980, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA2__GPIO3_20				IOMUX_PAD(0x77c, 0x318, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_TDATA2__FEC_TDATA_2			IOMUX_PAD(0x780, 0x31c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA2__IPU_CSI_D_5			IOMUX_PAD(0x780, 0x31c, 1, 0x944, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA2__AUDMUX_AUD6_RXD			IOMUX_PAD(0x780, 0x31c, 2, 0x7b0, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA2__KPP_ROW_5				IOMUX_PAD(0x780, 0x31c, 4, 0x984, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA2__GPIO3_21				IOMUX_PAD(0x780, 0x31c, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_RDATA3__FEC_RDATA_3			IOMUX_PAD(0x784, 0x320, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA3__IPU_CSI_D_6			IOMUX_PAD(0x784, 0x320, 1, 0x948, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA3__AUDMUX_AUD6_TXC			IOMUX_PAD(0x784, 0x320, 2, 0x7c0, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA3__KPP_ROW_6				IOMUX_PAD(0x784, 0x320, 4, 0x988, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA3__GPIO3_22				IOMUX_PAD(0x784, 0x320, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_TDATA3__FEC_TDATA_3			IOMUX_PAD(0x788, 0x324, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA3__IPU_CSI_D_7			IOMUX_PAD(0x788, 0x324, 1, 0x94c, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA3__AUDMUX_AUD6_TXFS			IOMUX_PAD(0x788, 0x324, 2, 0x7c4, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA3__KPP_ROW_7				IOMUX_PAD(0x788, 0x324, 4, 0x98c, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA3__GPIO3_23				IOMUX_PAD(0x788, 0x324, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_EXT_ARMCLK__CCM_EXT_ARMCLK			IOMUX_PAD(0x78c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_TEST_MODE__TCU_TEST_MODE			IOMUX_PAD(0x790, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+
+#endif /* __MACH_IOMUX_MX35_H__ */
diff --git a/arch/arm/mach-imx/iomux-mx50.h b/arch/arm/mach-imx/iomux-mx50.h
new file mode 100644
index 0000000..00f56e0
--- /dev/null
+++ b/arch/arm/mach-imx/iomux-mx50.h
@@ -0,0 +1,977 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __MACH_IOMUX_MX50_H__
+#define __MACH_IOMUX_MX50_H__
+
+#include "iomux-v3.h"
+
+#define MX50_ELCDIF_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
+
+#define MX50_SD_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
+					PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_HIGH)
+
+#define MX50_UART_PAD_CTRL	(PAD_CTL_DSE_HIGH | PAD_CTL_PKE)
+
+#define MX50_I2C_PAD_CTRL	(PAD_CTL_ODE | PAD_CTL_DSE_HIGH | \
+					PAD_CTL_PUS_100K_UP | PAD_CTL_HYS)
+
+#define MX50_USB_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE | \
+					PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP)
+
+#define MX50_FEC_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
+					PAD_CTL_PUS_22K_UP | PAD_CTL_ODE | \
+					PAD_CTL_DSE_HIGH)
+
+#define MX50_OWIRE_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
+					PAD_CTL_PUS_100K_UP | PAD_CTL_ODE | \
+					PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST)
+
+#define MX50_KEYPAD_CTRL        (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
+					PAD_CTL_PUS_100K_UP | PAD_CTL_DSE_HIGH)
+
+#define MX50_CSPI_SS_PAD	(PAD_CTL_PKE | PAD_CTL_PUE | \
+					PAD_CTL_PUS_22K_UP | PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_KEY_COL0__KEY_COL0	IOMUX_PAD(0x2CC, 0x20, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_COL0__GPIO_4_0	IOMUX_PAD(0x2CC, 0x20, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_COL0__NANDF_CLE	IOMUX_PAD(0x2CC, 0x20, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_KEY_ROW0__KEY_ROW0	IOMUX_PAD(0x2D0, 0x24, 0, 0x0, 0, MX50_KEYPAD_CTRL)
+#define MX50_PAD_KEY_ROW0__GPIO_4_1	IOMUX_PAD(0x2D0, 0x24, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_ROW0__NANDF_ALE	IOMUX_PAD(0x2D0, 0x24, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_KEY_COL1__KEY_COL1	IOMUX_PAD(0x2D4, 0x28, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_COL1__GPIO_4_2	IOMUX_PAD(0x2D4, 0x28, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_COL1__NANDF_CE0	IOMUX_PAD(0x2D4, 0x28, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_KEY_ROW1__KEY_ROW1	IOMUX_PAD(0x2D8, 0x2C, 0, 0x0, 0, MX50_KEYPAD_CTRL)
+#define MX50_PAD_KEY_ROW1__GPIO_4_3	IOMUX_PAD(0x2D8, 0x2C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_ROW1__NANDF_CE1	IOMUX_PAD(0x2D8, 0x2C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_KEY_COL2__KEY_COL2	IOMUX_PAD(0x2DC, 0x30, 0, 0x0, 0, MX50_KEYPAD_CTRL)
+#define MX50_PAD_KEY_COL2__GPIO_4_4	IOMUX_PAD(0x2DC, 0x30, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_COL2__NANDF_CE2	IOMUX_PAD(0x2DC, 0x30, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_KEY_ROW2__KEY_ROW2	IOMUX_PAD(0x2E0, 0x34, 0, 0x0, 0, MX50_KEYPAD_CTRL)
+#define MX50_PAD_KEY_ROW2__GPIO_4_5	IOMUX_PAD(0x2E0, 0x34, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_ROW2__NANDF_CE3	IOMUX_PAD(0x2E0, 0x34, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_KEY_COL3__KEY_COL3	IOMUX_PAD(0x2E4, 0x38, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_COL3__GPIO_4_6	IOMUX_PAD(0x2E4, 0x38, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_COL3__NANDF_READY	IOMUX_PAD(0x2E4, 0x38, 2, 0x7b4, 0, PAD_CTL_PKE | \
+							PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
+#define MX50_PAD_KEY_COL3__SDMA_EXT0	IOMUX_PAD(0x2E4, 0x38, 6, 0x7b8, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_KEY_ROW3__KEY_ROW3	IOMUX_PAD(0x2E8, 0x3C, 0, 0x0, 0, MX50_KEYPAD_CTRL)
+#define MX50_PAD_KEY_ROW3__GPIO_4_7	IOMUX_PAD(0x2E8, 0x3C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_KEY_ROW3__NANDF_DQS	IOMUX_PAD(0x2E8, 0x3C, 2, 0x7b0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_KEY_ROW3__SDMA_EXT1	IOMUX_PAD(0x2E8, 0x3C, 6, 0x7bc, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_I2C1_SCL__I2C1_SCL	IOMUX_PAD(0x2EC, 0x40, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX50_I2C_PAD_CTRL)
+#define MX50_PAD_I2C1_SCL__GPIO_6_18	IOMUX_PAD(0x2EC, 0x40, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C1_SCL__UART2_TXD	IOMUX_PAD(0x2EC, 0x40, 2, 0x0, 0, MX50_UART_PAD_CTRL)
+
+#define MX50_PAD_I2C1_SDA__I2C1_SDA	IOMUX_PAD(0x2F0, 0x44, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX50_I2C_PAD_CTRL)
+#define MX50_PAD_I2C1_SDA__GPIO_6_19	IOMUX_PAD(0x2F0, 0x44, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C1_SDA__UART2_RXD	IOMUX_PAD(0x2F0, 0x44, 2, 0x7cc, 1, MX50_UART_PAD_CTRL)
+
+#define MX50_PAD_I2C2_SCL__I2C2_SCL	IOMUX_PAD(0x2F4, 0x48, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX50_I2C_PAD_CTRL)
+#define MX50_PAD_I2C2_SCL__GPIO_6_20	IOMUX_PAD(0x2F4, 0x48, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C2_SCL__UART2_CTS	IOMUX_PAD(0x2F4, 0x48, 2, 0x0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_I2C2_SCL__DCDC_OK	IOMUX_PAD(0x2F4, 0x48, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_I2C2_SDA__I2C2_SDA	IOMUX_PAD(0x2F8, 0x4C, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX50_I2C_PAD_CTRL)
+#define MX50_PAD_I2C2_SDA__GPIO_6_21	IOMUX_PAD(0x2F8, 0x4C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C2_SDA__UART2_RTS	IOMUX_PAD(0x2F8, 0x4C, 2, 0x7c8, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_I2C2_SDA__PWRSTABLE	IOMUX_PAD(0x2F8, 0x4C, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_I2C3_SCL__I2C3_SCL	IOMUX_PAD(0x2FC, 0x50, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX50_I2C_PAD_CTRL)
+#define MX50_PAD_I2C3_SCL__GPIO_6_22	IOMUX_PAD(0x2FC, 0x50, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C3_SCL__FEC_MDC	IOMUX_PAD(0x2FC, 0x50, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_I2C3_SCL__PMIC_RDY	IOMUX_PAD(0x2FC, 0x50, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C3_SCL__GPT_CAPIN1	IOMUX_PAD(0x2FC, 0x50, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C3_SCL__USBOTG_OC	IOMUX_PAD(0x2FC, 0x50, 7, 0x7E8, 0, MX50_USB_PAD_CTRL)
+
+#define MX50_PAD_I2C3_SDA__I2C3_SDA	IOMUX_PAD(0x300, 0x54, IOMUX_CONFIG_SION, 0x0, 0, \
+								MX50_I2C_PAD_CTRL)
+#define MX50_PAD_I2C3_SDA__GPIO_6_23	IOMUX_PAD(0x300, 0x54, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C3_SDA__FEC_MDIO	IOMUX_PAD(0x300, 0x54, 2, 0x774, 0, MX50_FEC_PAD_CTRL)
+#define MX50_PAD_I2C3_SDA__PWRFAIL_INT	IOMUX_PAD(0x300, 0x54, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C3_SDA__ALARM_DEB	IOMUX_PAD(0x300, 0x54, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C3_SDA__GPT_CAPIN1	IOMUX_PAD(0x300, 0x54, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_I2C3_SDA__USBOTG_PWR	IOMUX_PAD(0x300, 0x54, 7, 0x0, 0, \
+							PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_PWM1__PWM1_PWMO	IOMUX_PAD(0x304, 0x58, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_PWM1__GPIO_6_24	IOMUX_PAD(0x304, 0x58, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_PWM1__USBOTG_OC	IOMUX_PAD(0x304, 0x58, 2, 0x7E8, 1, MX50_USB_PAD_CTRL)
+#define MX50_PAD_PWM1__GPT_CMPOUT1	IOMUX_PAD(0x304, 0x58, 5, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PWM2__PWM2_PWMO	IOMUX_PAD(0x308, 0x5C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_PWM2__GPIO_6_25	IOMUX_PAD(0x308, 0x5C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_PWM2__USBOTG_PWR	IOMUX_PAD(0x308, 0x5C, 2, 0x0, 0, \
+							PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
+#define MX50_PAD_PWM2__DCDC_PWM		IOMUX_PAD(0x308, 0x5C, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_PWM2__GPT_CMPOUT2	IOMUX_PAD(0x308, 0x5C, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_PWM2__ANY_PU_RST	IOMUX_PAD(0x308, 0x5C, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_OWIRE__OWIRE		IOMUX_PAD(0x30C, 0x60, 0, 0x0, 0, MX50_OWIRE_PAD_CTRL)
+#define MX50_PAD_OWIRE__GPIO_6_26	IOMUX_PAD(0x30C, 0x60, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_OWIRE__USBH1_OC	IOMUX_PAD(0x30C, 0x60, 2, 0x0, 0, MX50_USB_PAD_CTRL)
+#define MX50_PAD_OWIRE__SSI_EXT1_CLK	IOMUX_PAD(0x30C, 0x60, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_OWIRE__EPDC_PWRIRQ	IOMUX_PAD(0x30C, 0x60, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_OWIRE__GPT_CMPOUT3	IOMUX_PAD(0x30C, 0x60, 5, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPITO__EPITO		IOMUX_PAD(0x310, 0x64, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPITO__GPIO_6_27	IOMUX_PAD(0x310, 0x64, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPITO__USBH1_PWR	IOMUX_PAD(0x310, 0x64, 2, 0x0, 0, \
+							PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
+#define MX50_PAD_EPITO__SSI_EXT2_CLK	IOMUX_PAD(0x310, 0x64, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPITO__TOG_EN		IOMUX_PAD(0x310, 0x64, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPITO__GPT_CLKIN	IOMUX_PAD(0x310, 0x64, 5, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_WDOG__WDOG		IOMUX_PAD(0x314, 0x68, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_WDOG__GPIO_6_28	IOMUX_PAD(0x314, 0x68, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_WDOG__WDOG_RST		IOMUX_PAD(0x314, 0x68, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_WDOG__XTAL32K		IOMUX_PAD(0x314, 0x68, 6, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SSI_TXFS__SSI_TXFS	IOMUX_PAD(0x318, 0x6C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_TXFS__GPIO_6_0	IOMUX_PAD(0x318, 0x6C, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SSI_TXC__SSI_TXC	IOMUX_PAD(0x31C, 0x70, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_TXC__GPIO_6_1	IOMUX_PAD(0x31C, 0x70, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SSI_TXD__SSI_TXD	IOMUX_PAD(0x320, 0x74, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_TXD__GPIO_6_2	IOMUX_PAD(0x320, 0x74, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_TXD__CSPI_RDY	IOMUX_PAD(0x320, 0x74, 4, 0x6e8, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SSI_RXD__SSI_RXD	IOMUX_PAD(0x324, 0x78, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXD__GPIO_6_3	IOMUX_PAD(0x324, 0x78, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXD__CSPI_SS3	IOMUX_PAD(0x324, 0x78, 4, 0x6f4, 0, MX50_CSPI_SS_PAD)
+
+#define MX50_PAD_SSI_RXFS__AUD3_RXFS	IOMUX_PAD(0x328, 0x7C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXFS__GPIO_6_4	IOMUX_PAD(0x328, 0x7C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXFS__UART5_TXD	IOMUX_PAD(0x328, 0x7C, 2, 0x0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_SSI_RXFS__WEIM_D6	IOMUX_PAD(0x328, 0x7C, 3, 0x804, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXFS__CSPI_SS2	IOMUX_PAD(0x328, 0x7C, 4, 0x6f0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_SSI_RXFS__FEC_COL	IOMUX_PAD(0x328, 0x7C, 5, 0x770, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SSI_RXFS__FEC_MDC	IOMUX_PAD(0x328, 0x7C, 6, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_SSI_RXC__AUD3_RXC	IOMUX_PAD(0x32C, 0x80, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXC__GPIO_6_5	IOMUX_PAD(0x32C, 0x80, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXC__UART5_RXD	IOMUX_PAD(0x32C, 0x80, 2, 0x7e4, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_SSI_RXC__WEIM_D7	IOMUX_PAD(0x32C, 0x80, 3, 0x808, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXC__CSPI_SS1	IOMUX_PAD(0x32C, 0x80, 4, 0x6ec, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_SSI_RXC__FEC_RX_CLK	IOMUX_PAD(0x32C, 0x80, 5, 0x780, 0, NO_PAD_CTRL)
+#define MX50_PAD_SSI_RXC__FEC_MDIO	IOMUX_PAD(0x32C, 0x80, 6, 0x774, 1, MX50_FEC_PAD_CTRL)
+
+#define MX50_PAD_UART1_TXD__UART1_TXD	IOMUX_PAD(0x330, 0x84, 0, 0x0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_TXD__GPIO_6_6	IOMUX_PAD(0x330, 0x84, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_UART1_RXD__UART1_RXD	IOMUX_PAD(0x334, 0x88, 0, 0x7c4, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_RXD__GPIO_6_7	IOMUX_PAD(0x334, 0x88, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_UART1_CTS__UART1_CTS	IOMUX_PAD(0x338, 0x8C, 0, 0x0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_CTS__GPIO_6_8	IOMUX_PAD(0x338, 0x8C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART1_CTS__UART5_TXD	IOMUX_PAD(0x338, 0x8C, 2, 0x0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_CTS__SD4_D4	IOMUX_PAD(0x338, 0x8C, 4, 0x760, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART1_CTS__SD4_CMD	IOMUX_PAD(0x338, 0x8C, 5, 0x74c, 0, MX50_SD_PAD_CTRL)
+
+#define MX50_PAD_UART1_RTS__UART1_RTS	IOMUX_PAD(0x33C, 0x90, 0, 0x7c0, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_RTS__GPIO_6_9	IOMUX_PAD(0x33C, 0x90, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART1_RTS__UART5_RXD	IOMUX_PAD(0x33C, 0x90, 2, 0x7e4, 3, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_RTS__SD4_D5	IOMUX_PAD(0x33C, 0x90, 4, 0x764, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART1_RTS__SD4_CLK	IOMUX_PAD(0x33C, 0x90, 5, 0x748, 0, MX50_SD_PAD_CTRL)
+
+#define MX50_PAD_UART2_TXD__UART2_TXD	IOMUX_PAD(0x340, 0x94, 0, 0x0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART2_TXD__GPIO_6_10	IOMUX_PAD(0x340, 0x94, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART2_TXD__SD4_D6	IOMUX_PAD(0x340, 0x94, 4, 0x768, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART2_TXD__SD4_D4	IOMUX_PAD(0x340, 0x94, 5, 0x760, 1, MX50_SD_PAD_CTRL)
+
+#define MX50_PAD_UART2_RXD__UART2_RXD	IOMUX_PAD(0x344, 0x98, 0, 0x7cc, 3, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART2_RXD__GPIO_6_11	IOMUX_PAD(0x344, 0x98, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART2_RXD__SD4_D7	IOMUX_PAD(0x344, 0x98, 4, 0x76c, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART2_RXD__SD4_D5	IOMUX_PAD(0x344, 0x98, 5, 0x764, 1, MX50_SD_PAD_CTRL)
+
+#define MX50_PAD_UART2_CTS__UART2_CTS	IOMUX_PAD(0x348, 0x9C, 0, 0x0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART2_CTS__GPIO_6_12	IOMUX_PAD(0x348, 0x9C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART2_CTS__SD4_CMD	IOMUX_PAD(0x348, 0x9C, 4, 0x74c, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART2_CTS__SD4_D6	IOMUX_PAD(0x348, 0x9C, 5, 0x768, 1, MX50_SD_PAD_CTRL)
+
+#define MX50_PAD_UART2_RTS__UART2_RTS	IOMUX_PAD(0x34C, 0xA0, 0, 0x7c8, 3, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART2_RTS__GPIO_6_13	IOMUX_PAD(0x34C, 0xA0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART2_RTS__SD4_CLK	IOMUX_PAD(0x34C, 0xA0, 4, 0x748, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART2_RTS__SD4_D7	IOMUX_PAD(0x34C, 0xA0, 5, 0x76c, 1, MX50_SD_PAD_CTRL)
+
+#define MX50_PAD_UART3_TXD__UART3_TXD	IOMUX_PAD(0x350, 0xA4, 0, 0x0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART3_TXD__GPIO_6_14	IOMUX_PAD(0x350, 0xA4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART3_TXD__SD1_D4	IOMUX_PAD(0x350, 0xA4, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART3_TXD__SD4_D0	IOMUX_PAD(0x350, 0xA4, 4, 0x750, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART3_TXD__SD2_WP	IOMUX_PAD(0x350, 0xA4, 5, 0x744, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART3_TXD__WEIM_D12	IOMUX_PAD(0x350, 0xA4, 6, 0x81c, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_UART3_RXD__UART3_RXD	IOMUX_PAD(0x354, 0xA8, 0, 0x7d4, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART3_RXD__GPIO_6_15	IOMUX_PAD(0x354, 0xA8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART3_RXD__SD1_D5	IOMUX_PAD(0x354, 0xA8, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART3_RXD__SD4_D1	IOMUX_PAD(0x354, 0xA8, 4, 0x754, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART3_RXD__SD2_CD	IOMUX_PAD(0x354, 0xA8, 5, 0x740, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART3_RXD__WEIM_D13	IOMUX_PAD(0x354, 0xA8, 6, 0x820, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_UART4_TXD__UART4_TXD	IOMUX_PAD(0x358, 0xAC, 0, 0x0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART4_TXD__GPIO_6_16	IOMUX_PAD(0x358, 0xAC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART4_TXD__UART3_CTS	IOMUX_PAD(0x358, 0xAC, 2, 0x0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART4_TXD__SD1_D6	IOMUX_PAD(0x358, 0xAC, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART4_TXD__SD4_D2	IOMUX_PAD(0x358, 0xAC, 4, 0x758, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART4_TXD__SD2_LCTL	IOMUX_PAD(0x358, 0xAC, 5, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART4_TXD__WEIM_D14	IOMUX_PAD(0x358, 0xAC, 6, 0x824, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_UART4_RXD__UART4_RXD	IOMUX_PAD(0x35C, 0xB0, 0, 0x7dc, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART4_RXD__GPIO_6_17	IOMUX_PAD(0x35C, 0xB0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_UART4_RXD__UART3_RTS	IOMUX_PAD(0x35C, 0xB0, 2, 0x7d0, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART4_RXD__SD1_D7	IOMUX_PAD(0x35C, 0xB0, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART4_RXD__SD4_D3	IOMUX_PAD(0x35C, 0xB0, 4, 0x75c, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART4_RXD__SD1_LCTL	IOMUX_PAD(0x35C, 0xB0, 5, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART4_RXD__WEIM_D15	IOMUX_PAD(0x35C, 0xB0, 6, 0x828, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_CSPI_SCLK__CSPI_SCLK	IOMUX_PAD(0x360, 0xB4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_CSPI_SCLK__GPIO_4_8	IOMUX_PAD(0x360, 0xB4, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_CSPI_MOSI__CSPI_MOSI	IOMUX_PAD(0x364, 0xB8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_CSPI_MOSI__GPIO_4_9	IOMUX_PAD(0x364, 0xB8, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_CSPI_MISO__CSPI_MISO	IOMUX_PAD(0x368, 0xBC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_CSPI_MISO__GPIO_4_10	IOMUX_PAD(0x368, 0xBC, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_CSPI_SS0__CSPI_SS0	IOMUX_PAD(0x36C, 0xC0, 0, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_CSPI_SS0__GPIO_4_11	IOMUX_PAD(0x36C, 0xC0, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_ECSPI1_SCLK__ECSPI1_SCLK	IOMUX_PAD(0x370, 0xC4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SCLK__GPIO_4_12		IOMUX_PAD(0x370, 0xC4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SCLK__CSPI_RDY		IOMUX_PAD(0x370, 0xC4, 2, 0x6e8, 1, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SCLK__ECSPI2_RDY	IOMUX_PAD(0x370, 0xC4, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SCLK__UART3_RTS		IOMUX_PAD(0x370, 0xC4, 4, 0x7d0, 2, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SCLK__EPDC_SDCE6	IOMUX_PAD(0x370, 0xC4, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SCLK__WEIM_D8		IOMUX_PAD(0x370, 0xC4, 7, 0x80c, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_ECSPI1_MOSI__ECSPI1_MOSI	IOMUX_PAD(0x374, 0xC8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MOSI__GPIO_4_13		IOMUX_PAD(0x374, 0xC8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MOSI__CSPI_SS1		IOMUX_PAD(0x374, 0xC8, 2, 0x6ec, 1, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI1_MOSI__ECSPI2_SS1	IOMUX_PAD(0x374, 0xC8, 3, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI1_MOSI__UART3_CTS		IOMUX_PAD(0x374, 0xC8, 4, 0x0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MOSI__EPDC_SDCE7	IOMUX_PAD(0x374, 0xC8, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MOSI__WEIM_D9		IOMUX_PAD(0x374, 0xC8, 7, 0x810, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_ECSPI1_MISO__ECSPI1_MISO	IOMUX_PAD(0x378, 0xCC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MISO__GPIO_4_14		IOMUX_PAD(0x378, 0xCC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MISO__CSPI_SS2		IOMUX_PAD(0x378, 0xCC, 2, 0x6f0, 1, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI1_MISO__ECSPI2_SS2	IOMUX_PAD(0x378, 0xCC, 3, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI1_MISO__UART4_RTS		IOMUX_PAD(0x378, 0xCC, 4, 0x7d8, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MISO__EPDC_SDCE8	IOMUX_PAD(0x378, 0xCC, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MISO__WEIM_D10		IOMUX_PAD(0x378, 0xCC, 7, 0x814, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_ECSPI1_SS0__ECSPI1_SS0		IOMUX_PAD(0x37C, 0xD0, 0, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI1_SS0__GPIO_4_15		IOMUX_PAD(0x37C, 0xD0, 1, 0x0, 0, PAD_CTL_PUS_100K_UP)
+#define MX50_PAD_ECSPI1_SS0__CSPI_SS3		IOMUX_PAD(0x37C, 0xD0, 2, 0x6f4, 1, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI1_SS0__ECSPI2_SS3		IOMUX_PAD(0x37C, 0xD0, 3, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI1_SS0__UART4_CTS		IOMUX_PAD(0x37C, 0xD0, 4, 0x0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SS0__EPDC_SDCE9		IOMUX_PAD(0x37C, 0xD0, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SS0__WEIM_D11		IOMUX_PAD(0x37C, 0xD0, 7, 0x818, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_ECSPI2_SCLK__ECSPI2_SCLK	IOMUX_PAD(0x380, 0xD4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SCLK__GPIO_4_16		IOMUX_PAD(0x380, 0xD4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SCLK__ELCDIF_WR		IOMUX_PAD(0x380, 0xD4, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SCLK__ECSPI1_RDY	IOMUX_PAD(0x380, 0xD4, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SCLK__UART5_RTS		IOMUX_PAD(0x380, 0xD4, 4, 0x7e0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SCLK__ELCDIF_DOTCLK	IOMUX_PAD(0x380, 0xD4, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SCLK__NANDF_CEN4	IOMUX_PAD(0x380, 0xD4, 6, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SCLK__WEIM_D8		IOMUX_PAD(0x380, 0xD4, 7, 0x80c, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_ECSPI2_MOSI__ECSPI2_MOSI	IOMUX_PAD(0x384, 0xD8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MOSI__GPIO_4_17		IOMUX_PAD(0x384, 0xD8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MOSI__ELCDIF_RD		IOMUX_PAD(0x384, 0xD8, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MOSI__ECSPI1_SS1	IOMUX_PAD(0x384, 0xD8, 3, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI2_MOSI__UART5_CTS		IOMUX_PAD(0x384, 0xD8, 4, 0x0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MOSI__ELCDIF_EN		IOMUX_PAD(0x384, 0xD8, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MOSI__NANDF_CEN5	IOMUX_PAD(0x384, 0xD8, 6, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MOSI__WEIM_D9		IOMUX_PAD(0x384, 0xD8, 7, 0x810, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_ECSPI2_MISO__ECSPI2_MISO	IOMUX_PAD(0x388, 0xDC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MISO__GPIO_4_18		IOMUX_PAD(0x388, 0xDC, 1, 0x0, 0, PAD_CTL_PUS_100K_UP)
+#define MX50_PAD_ECSPI2_MISO__ELCDIF_RS		IOMUX_PAD(0x388, 0xDC, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MISO__ECSPI1_SS2	IOMUX_PAD(0x388, 0xDC, 3, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI2_MISO__UART5_TXD		IOMUX_PAD(0x388, 0xDC, 4, 0x0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MISO__ELCDIF_VSYNC	IOMUX_PAD(0x388, 0xDC, 5, 0x73c, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MISO__NANDF_CEN6	IOMUX_PAD(0x388, 0xDC, 6, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MISO__WEIM_D10		IOMUX_PAD(0x388, 0xDC, 7, 0x814, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_ECSPI2_SS0__ECSPI2_SS0		IOMUX_PAD(0x38C, 0xE0, 0, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI2_SS0__GPIO_4_19		IOMUX_PAD(0x38C, 0xE0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SS0__ELCDIF_CS		IOMUX_PAD(0x38C, 0xE0, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SS0__ECSPI1_SS3		IOMUX_PAD(0x38C, 0xE0, 3, 0x0, 0, MX50_CSPI_SS_PAD)
+#define MX50_PAD_ECSPI2_SS0__UART5_RXD		IOMUX_PAD(0x38C, 0xE0, 4, 0x7e4, 5, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SS0__ELCDIF_HSYNC	IOMUX_PAD(0x38C, 0xE0, 5, 0x6f8, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SS0__NANDF_CEN7		IOMUX_PAD(0x38C, 0xE0, 6, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_SS0__WEIM_D11		IOMUX_PAD(0x38C, 0xE0, 7, 0x818, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_SD1_CLK__SD1_CLK	IOMUX_PAD(0x390, 0xE4, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD1_CLK__GPIO_5_0	IOMUX_PAD(0x390, 0xE4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD1_CLK__CLKO		IOMUX_PAD(0x390, 0xE4, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD1_CMD__SD1_CMD	IOMUX_PAD(0x394, 0xE8, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD1_CMD__GPIO_5_1	IOMUX_PAD(0x394, 0xE8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD1_CMD__CLKO2		IOMUX_PAD(0x394, 0xE8, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD1_D0__SD1_D0		IOMUX_PAD(0x398, 0xEC, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD1_D0__GPIO_5_2	IOMUX_PAD(0x398, 0xEC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD1_D0__PLL1_BYP	IOMUX_PAD(0x398, 0xEC, 7, 0x6dc, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD1_D1__SD1_D1		IOMUX_PAD(0x39C, 0xF0, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD1_D1__GPIO_5_3	IOMUX_PAD(0x39C, 0xF0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD1_D1__PLL2_BYP	IOMUX_PAD(0x39C, 0xF0, 7, 0x6e0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD1_D2__SD1_D2		IOMUX_PAD(0x3A0, 0xF4, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD1_D2__GPIO_5_4	IOMUX_PAD(0x3A0, 0xF4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD1_D2__PLL3_BYP	IOMUX_PAD(0x3A0, 0xF4, 7, 0x6e4, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD1_D3__SD1_D3		IOMUX_PAD(0x3A4, 0xF8, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD1_D3__GPIO_5_5	IOMUX_PAD(0x3A4, 0xF8, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_CLK__SD2_CLK	IOMUX_PAD(0x3A8, 0xFC, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_CLK__GPIO_5_6	IOMUX_PAD(0x3A8, 0xFC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_CLK__MSHC_SCLK	IOMUX_PAD(0x3A8, 0xFC, 2, 0x0, 0, MX50_SD_PAD_CTRL)
+
+#define MX50_PAD_SD2_CMD__SD2_CMD	IOMUX_PAD(0x3AC, 0x100, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_CMD__GPIO_5_7	IOMUX_PAD(0x3AC, 0x100, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_CMD__MSHC_BS	IOMUX_PAD(0x3AC, 0x100, 2, 0x0, 0, MX50_SD_PAD_CTRL)
+
+#define MX50_PAD_SD2_D0__SD2_D0		IOMUX_PAD(0x3B0, 0x104, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D0__GPIO_5_8	IOMUX_PAD(0x3B0, 0x104, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D0__MSHC_D0	IOMUX_PAD(0x3B0, 0x104, 2, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D0__KEY_COL4	IOMUX_PAD(0x3B0, 0x104, 3, 0x790, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_D1__SD2_D1		IOMUX_PAD(0x3B4, 0x108, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D1__GPIO_5_9	IOMUX_PAD(0x3B4, 0x108, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D1__MSHC_D1	IOMUX_PAD(0x3B4, 0x108, 2, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D1__KEY_ROW4	IOMUX_PAD(0x3B4, 0x108, 3, 0x7a0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_D2__SD2_D2		IOMUX_PAD(0x3B8, 0x10C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D2__GPIO_5_10	IOMUX_PAD(0x3B8, 0x10C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D2__MSHC_D2	IOMUX_PAD(0x3B8, 0x10C, 2, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D2__KEY_COL5	IOMUX_PAD(0x3B8, 0x10C, 3, 0x794, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_D3__SD2_D3		IOMUX_PAD(0x3BC, 0x110, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D3__GPIO_5_11	IOMUX_PAD(0x3BC, 0x110, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D3__MSHC_D3	IOMUX_PAD(0x3BC, 0x110, 2, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D3__KEY_ROW5	IOMUX_PAD(0x3BC, 0x110, 3, 0x7a4, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_D4__SD2_D4		IOMUX_PAD(0x3C0, 0x114, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D4__GPIO_5_12	IOMUX_PAD(0x3C0, 0x114, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D4__AUD4_RXFS	IOMUX_PAD(0x3C0, 0x114, 2, 0x6d0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D4__KEY_COL6	IOMUX_PAD(0x3C0, 0x114, 3, 0x798, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D4__WEIM_D0	IOMUX_PAD(0x3C0, 0x114, 4, 0x7ec, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D4__CCM_OUT0	IOMUX_PAD(0x3C0, 0x114, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_D5__SD2_D5		IOMUX_PAD(0x3C4, 0x118, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D5__GPIO_5_13	IOMUX_PAD(0x3C4, 0x118, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D5__AUD4_RXC	IOMUX_PAD(0x3C4, 0x118, 2, 0x6cc, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D5__KEY_ROW6	IOMUX_PAD(0x3C4, 0x118, 3, 0x7a8, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D5__WEIM_D1	IOMUX_PAD(0x3C4, 0x118, 4, 0x7f0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D5__CCM_OUT1	IOMUX_PAD(0x3C4, 0x118, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_D6__SD2_D6		IOMUX_PAD(0x3C8, 0x11C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D6__GPIO_5_14	IOMUX_PAD(0x3C8, 0x11C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D6__AUD4_RXD	IOMUX_PAD(0x3C8, 0x11C, 2, 0x6c4, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D6__KEY_COL7	IOMUX_PAD(0x3C8, 0x11C, 3, 0x79c, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D6__WEIM_D2	IOMUX_PAD(0x3C8, 0x11C, 4, 0x7f4, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D6__CCM_OUT2	IOMUX_PAD(0x3C8, 0x11C, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_D7__SD2_D7		IOMUX_PAD(0x3CC, 0x120, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_D7__GPIO_5_15	IOMUX_PAD(0x3CC, 0x120, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D7__AUD4_TXFS	IOMUX_PAD(0x3CC, 0x120, 2, 0x6d8, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D7__KEY_ROW7	IOMUX_PAD(0x3CC, 0x120, 3, 0x7ac, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D7__WEIM_D3	IOMUX_PAD(0x3CC, 0x120, 4, 0x7f8, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_D7__CCM_STOP	IOMUX_PAD(0x3CC, 0x120, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_WP__SD2_WP		IOMUX_PAD(0x3D0, 0x124, 0, 0x744, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_WP__GPIO_5_16	IOMUX_PAD(0x3D0, 0x124, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_WP__AUD4_TXD	IOMUX_PAD(0x3D0, 0x124, 2, 0x6c8, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_WP__WEIM_D4	IOMUX_PAD(0x3D0, 0x124, 4, 0x7fc, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_WP__CCM_WAIT	IOMUX_PAD(0x3D0, 0x124, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD2_CD__SD2_CD		IOMUX_PAD(0x3D4, 0x128, 0, 0x740, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD2_CD__GPIO_5_17	IOMUX_PAD(0x3D4, 0x128, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_CD__AUD4_TXC	IOMUX_PAD(0x3D4, 0x128, 2, 0x6d4, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_CD__WEIM_D5	IOMUX_PAD(0x3D4, 0x128, 4, 0x800, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD2_CD__CCM_REF_EN	IOMUX_PAD(0x3D4, 0x128, 7, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_ON_REQ__PMIC_ON_REQ	IOMUX_PAD(0x3D8, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_STBY_REQ__PMIC_STBY_REQ	IOMUX_PAD(0x3DC, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_PORT_B__PMIC_PORT_B	IOMUX_PAD(0x3E0, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_BOOT_MODE1__PMIC_BOOT_MODE1	IOMUX_PAD(0x3E4, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_RESET_IN_B__PMIC_RESET_IN_B	IOMUX_PAD(0x3E8, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_BOOT_MODE0__PMIC_BOOT_MODE0	IOMUX_PAD(0x3EC, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_TEST_MODE__PMIC_TEST_MODE	IOMUX_PAD(0x3F0, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_JTAG_TMS__PMIC_JTAG_TMS	IOMUX_PAD(0x3F4, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_JTAG_MOD__PMIC_JTAG_MOD	IOMUX_PAD(0x3F8, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_JTAG_TRSTB__PMIC_JTAG_TRSTB	IOMUX_PAD(0x3FC, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_JTAG_TDI__PMIC_JTAG_TDI	IOMUX_PAD(0x400, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_JTAG_TCK__PMIC_JTAG_TCK	IOMUX_PAD(0x404, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_PMIC_JTAG_TDO__PMIC_JTAG_TDO	IOMUX_PAD(0x408, 0, 0, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D0__DISP_D0	IOMUX_PAD(0x40C, 0x12C, 0, 0x6fc, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D0__GPIO_2_0	IOMUX_PAD(0x40C, 0x12C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D0__FEC_TXCLK	IOMUX_PAD(0x40C, 0x12C, 2, 0x78c, 0, PAD_CTL_HYS | PAD_CTL_PKE)
+
+#define MX50_PAD_DISP_D1__DISP_D1	IOMUX_PAD(0x410, 0x130, 0, 0x700, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D1__GPIO_2_1	IOMUX_PAD(0x410, 0x130, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D1__FEC_RX_ER	IOMUX_PAD(0x410, 0x130, 2, 0x788, 0, PAD_CTL_HYS | PAD_CTL_PKE)
+#define MX50_PAD_DISP_D1__WEIM_A17	IOMUX_PAD(0x410, 0x130, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D2__DISP_D2	IOMUX_PAD(0x414, 0x134, 0, 0x704, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D2__GPIO_2_2	IOMUX_PAD(0x414, 0x134, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D2__FEC_RX_DV	IOMUX_PAD(0x414, 0x134, 2, 0x784, 0, PAD_CTL_HYS | PAD_CTL_PKE)
+#define MX50_PAD_DISP_D2__WEIM_A18	IOMUX_PAD(0x414, 0x134, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D3__DISP_D3	IOMUX_PAD(0x418, 0x138, 0, 0x708, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D3__GPIO_2_3	IOMUX_PAD(0x418, 0x138, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D3__FEC_RXD1	IOMUX_PAD(0x418, 0x138, 2, 0x77C, 0, PAD_CTL_HYS | PAD_CTL_PKE)
+#define MX50_PAD_DISP_D3__WEIM_A19	IOMUX_PAD(0x418, 0x138, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D3__FEC_COL	IOMUX_PAD(0x418, 0x138, 4, 0x770, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D4__DISP_D4	IOMUX_PAD(0x41C, 0x13C, 0, 0x70c, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D4__GPIO_2_4	IOMUX_PAD(0x41C, 0x13C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D4__FEC_RXD0	IOMUX_PAD(0x41C, 0x13C, 2, 0x778, 0, PAD_CTL_HYS | PAD_CTL_PKE)
+#define MX50_PAD_DISP_D4__WEIM_A20	IOMUX_PAD(0x41C, 0x13C, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D5__DISP_D5	IOMUX_PAD(0x420, 0x140, 0, 0x710, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D5__GPIO_2_5	IOMUX_PAD(0x420, 0x140, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D5__FEC_TX_EN	IOMUX_PAD(0x420, 0x140, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_DISP_D5__WEIM_A21	IOMUX_PAD(0x420, 0x140, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D6__DISP_D6	IOMUX_PAD(0x424, 0x144, 0, 0x714, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D6__GPIO_2_6	IOMUX_PAD(0x424, 0x144, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D6__FEC_TXD1	IOMUX_PAD(0x424, 0x144, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_DISP_D6__WEIM_A22	IOMUX_PAD(0x424, 0x144, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D6__FEC_RX_CLK	IOMUX_PAD(0x424, 0x144, 4, 0x780, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D7__DISP_D7	IOMUX_PAD(0x428, 0x148, 0, 0x718, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D7__GPIO_2_7	IOMUX_PAD(0x428, 0x148, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D7__FEC_TXD0	IOMUX_PAD(0x428, 0x148, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_DISP_D7__WEIM_A23	IOMUX_PAD(0x428, 0x148, 3, 0x0, 0, NO_PAD_CTRL)
+
+
+#define MX50_PAD_DISP_WR__ELCDIF_WR	IOMUX_PAD(0x42C, 0x14C, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_WR__GPIO_2_16	IOMUX_PAD(0x42C, 0x14C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_WR__ELCDIF_PIXCLK	IOMUX_PAD(0x42C, 0x14C, 2, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_WR__WEIM_A24	IOMUX_PAD(0x42C, 0x14C, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_RD__ELCDIF_RD	IOMUX_PAD(0x430, 0x150, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_RD__GPIO_2_19	IOMUX_PAD(0x430, 0x150, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_RD__ELCDIF_EN	IOMUX_PAD(0x430, 0x150, 2, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_RD__WEIM_A25	IOMUX_PAD(0x430, 0x150, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_RS__ELCDIF_RS	IOMUX_PAD(0x434, 0x154, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_RS__GPIO_2_17	IOMUX_PAD(0x434, 0x154, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_RS__ELCDIF_VSYNC	IOMUX_PAD(0x434, 0x154, 2, 0x73c, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_RS__WEIM_A26	IOMUX_PAD(0x434, 0x154, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_CS__ELCDIF_CS	IOMUX_PAD(0x438, 0x158, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_CS__GPIO_2_21	IOMUX_PAD(0x438, 0x158, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_CS__ELCDIF_HSYNC	IOMUX_PAD(0x438, 0x158, 2, 0x6f8, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_CS__WEIM_A27	IOMUX_PAD(0x438, 0x158, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_CS__WEIM_CS3	IOMUX_PAD(0x438, 0x158, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_BUSY__ELCDIF_HSYNC	IOMUX_PAD(0x43C, 0x15C, 0, 0x6f8, 2, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_BUSY__GPIO_2_18		IOMUX_PAD(0x43C, 0x15C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_BUSY__WEIM_CS3		IOMUX_PAD(0x43C, 0x15C, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_RESET__ELCDIF_RST	IOMUX_PAD(0x440, 0x160, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_RESET__GPIO_2_20	IOMUX_PAD(0x440, 0x160, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_RESET__WEIM_CS3	IOMUX_PAD(0x440, 0x160, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_CMD__SD3_CMD	IOMUX_PAD(0x444, 0x164, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_CMD__GPIO_5_18	IOMUX_PAD(0x444, 0x164, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_CMD__NANDF_WRN	IOMUX_PAD(0x444, 0x164, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_CMD__SSP_CMD	IOMUX_PAD(0x444, 0x164, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_CLK__SD3_CLK	IOMUX_PAD(0x448, 0x168, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_CLK__GPIO_5_19	IOMUX_PAD(0x448, 0x168, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_CLK__NANDF_RDN	IOMUX_PAD(0x448, 0x168, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_CLK__SSP_CLK	IOMUX_PAD(0x448, 0x168, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_D0__SD3_D0		IOMUX_PAD(0x44C, 0x16C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_D0__GPIO_5_20	IOMUX_PAD(0x44C, 0x16C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_D0__NANDF_D4	IOMUX_PAD(0x44C, 0x16C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_D0__SSP_D0		IOMUX_PAD(0x44C, 0x16C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD3_D0__PLL1_BYP	IOMUX_PAD(0x44C, 0x16C, 7, 0x6dc, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_D1__SD3_D1		IOMUX_PAD(0x450, 0x170, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_D1__GPIO_5_21	IOMUX_PAD(0x450, 0x170, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_D1__NANDF_D5	IOMUX_PAD(0x450, 0x170, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_D1__PLL2_BYP	IOMUX_PAD(0x450, 0x170, 7, 0x6e0, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_D2__SD3_D2		IOMUX_PAD(0x454, 0x174, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_D2__GPIO_5_22	IOMUX_PAD(0x454, 0x174, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_D2__NANDF_D6	IOMUX_PAD(0x454, 0x174, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_D2__SSP_D2		IOMUX_PAD(0x454, 0x174, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD3_D2__PLL3_BYP	IOMUX_PAD(0x454, 0x174, 7, 0x6e4, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_D3__SD3_D3		IOMUX_PAD(0x458, 0x178, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_D3__GPIO_5_23	IOMUX_PAD(0x458, 0x178, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_D3__NANDF_D7	IOMUX_PAD(0x458, 0x178, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_D3__SSP_D3		IOMUX_PAD(0x458, 0x178, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_D4__SD3_D4		IOMUX_PAD(0x45C, 0x17C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_D4__GPIO_5_24	IOMUX_PAD(0x45C, 0x17C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_D4__NANDF_D0	IOMUX_PAD(0x45C, 0x17C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_D4__SSP_D4		IOMUX_PAD(0x45C, 0x17C, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_D5__SD3_D5		IOMUX_PAD(0x460, 0x180, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_D5__GPIO_5_25	IOMUX_PAD(0x460, 0x180, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_D5__NANDF_D1	IOMUX_PAD(0x460, 0x180, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_D5__SSP_D5		IOMUX_PAD(0x460, 0x180, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_D6__SD3_D6		IOMUX_PAD(0x464, 0x184, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_D6__GPIO_5_26	IOMUX_PAD(0x464, 0x184, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_D6__NANDF_D2	IOMUX_PAD(0x464, 0x184, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_D6__SSP_D6		IOMUX_PAD(0x464, 0x184, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_D7__SD3_D7		IOMUX_PAD(0x468, 0x188, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_D7__GPIO_5_27	IOMUX_PAD(0x468, 0x188, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_D7__NANDF_D3	IOMUX_PAD(0x468, 0x188, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_D7__SSP_D7		IOMUX_PAD(0x468, 0x188, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_SD3_WP__SD3_WP		IOMUX_PAD(0x46C, 0x18C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_WP__GPIO_5_28	IOMUX_PAD(0x46C, 0x18C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_SD3_WP__NANDF_RESETN	IOMUX_PAD(0x46C, 0x18C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_SD3_WP__SSP_CD		IOMUX_PAD(0x46C, 0x18C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_SD3_WP__SD4_LCTL	IOMUX_PAD(0x46C, 0x18C, 4, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_SD3_WP__WEIM_CS3	IOMUX_PAD(0x46C, 0x18C, 5, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D8__DISP_D8	IOMUX_PAD(0x470, 0x190, 0, 0x71c, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D8__GPIO_2_8	IOMUX_PAD(0x470, 0x190, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D8__NANDF_CLE	IOMUX_PAD(0x470, 0x190, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D8__SD1_LCTL	IOMUX_PAD(0x470, 0x190, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D8__SD4_CMD	IOMUX_PAD(0x470, 0x190, 4, 0x74c, 2, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D8__KEY_COL4	IOMUX_PAD(0x470, 0x190, 5, 0x790, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D8__FEC_TX_CLK	IOMUX_PAD(0x470, 0x190, 6, 0x78c, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D9__DISP_D9	IOMUX_PAD(0x474, 0x194, 0, 0x720, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D9__GPIO_2_9	IOMUX_PAD(0x474, 0x194, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D9__NANDF_ALE	IOMUX_PAD(0x474, 0x194, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D9__SD2_LCTL	IOMUX_PAD(0x474, 0x194, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D9__SD4_CLK	IOMUX_PAD(0x474, 0x194, 4, 0x748, 2, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D9__KEY_ROW4	IOMUX_PAD(0x474, 0x194, 5, 0x7a0, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D9__FEC_RX_ER	IOMUX_PAD(0x474, 0x194, 6, 0x788, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D10__DISP_D10	IOMUX_PAD(0x478, 0x198, 0, 0x724, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D10__GPIO_2_10	IOMUX_PAD(0x478, 0x198, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D10__NANDF_CEN0	IOMUX_PAD(0x478, 0x198, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D10__SD3_LCTL	IOMUX_PAD(0x478, 0x198, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D10__SD4_D0	IOMUX_PAD(0x478, 0x198, 4, 0x750, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D10__KEY_COL5	IOMUX_PAD(0x478, 0x198, 5, 0x794, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D10__FEC_RX_DV	IOMUX_PAD(0x478, 0x198, 6, 0x784, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D11__DISP_D11	IOMUX_PAD(0x47C, 0x19C, 0, 0x728, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D11__GPIO_2_11	IOMUX_PAD(0x47C, 0x19C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D11__NANDF_CEN1	IOMUX_PAD(0x47C, 0x19C, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D11__SD4_D1	IOMUX_PAD(0x47C, 0x19C, 4, 0x754, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D11__KEY_ROW5	IOMUX_PAD(0x47C, 0x19C, 5, 0x7a4, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D11__FEC_RDAT1	IOMUX_PAD(0x47C, 0x19C, 6, 0x77c, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D12__DISP_D12	IOMUX_PAD(0x480, 0x1A0, 0, 0x72c, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D12__GPIO_2_12	IOMUX_PAD(0x480, 0x1A0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D12__NANDF_CEN2	IOMUX_PAD(0x480, 0x1A0, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D12__SD1_CD	IOMUX_PAD(0x480, 0x1A0, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D12__SD4_D2	IOMUX_PAD(0x480, 0x1A0, 4, 0x758, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D12__KEY_COL6	IOMUX_PAD(0x480, 0x1A0, 5, 0x798, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D12__FEC_RDAT0	IOMUX_PAD(0x480, 0x1A0, 6, 0x778, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D13__DISP_D13	IOMUX_PAD(0x484, 0x1A4, 0, 0x730, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D13__GPIO_2_13	IOMUX_PAD(0x484, 0x1A4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D13__NANDF_CEN3	IOMUX_PAD(0x484, 0x1A4, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D13__SD3_CD	IOMUX_PAD(0x484, 0x1A4, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D13__SD4_D3	IOMUX_PAD(0x484, 0x1A4, 4, 0x75c, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D13__KEY_ROW6	IOMUX_PAD(0x484, 0x1A4, 5, 0x7a8, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D13__FEC_TX_EN	IOMUX_PAD(0x484, 0x1A4, 6, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D14__DISP_D14	IOMUX_PAD(0x488, 0x1A8, 0, 0x734, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D14__GPIO_2_14	IOMUX_PAD(0x488, 0x1A8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D14__NANDF_RDY0	IOMUX_PAD(0x488, 0x1A8, 2, 0x7b4, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D14__SD1_WP	IOMUX_PAD(0x488, 0x1A8, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D14__SD4_WP	IOMUX_PAD(0x488, 0x1A8, 4, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D14__KEY_COL7	IOMUX_PAD(0x488, 0x1A8, 5, 0x79c, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D14__FEC_TDAT1	IOMUX_PAD(0x488, 0x1A8, 6, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_DISP_D15__DISP_D15	IOMUX_PAD(0x48C, 0x1AC, 0, 0x738, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_D15__GPIO_2_15	IOMUX_PAD(0x48C, 0x1AC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D15__NANDF_DQS	IOMUX_PAD(0x48C, 0x1AC, 2, 0x7b0, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D15__SD3_RST	IOMUX_PAD(0x48C, 0x1AC, 3, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D15__SD4_CD	IOMUX_PAD(0x48C, 0x1AC, 4, 0x0, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_DISP_D15__KEY_ROW7	IOMUX_PAD(0x48C, 0x1AC, 5, 0x7ac, 1, NO_PAD_CTRL)
+#define MX50_PAD_DISP_D15__FEC_TDAT0	IOMUX_PAD(0x48C, 0x1AC, 6, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D0__EPDC_D0	IOMUX_PAD(0x54C, 0x1B0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D0__GPIO_3_0	IOMUX_PAD(0x54C, 0x1B0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D0__WEIM_D0	IOMUX_PAD(0x54C, 0x1B0, 2, 0x7ec, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D0__ELCDIF_RS	IOMUX_PAD(0x54C, 0x1B0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_D0__ELCDIF_PIXCLK	IOMUX_PAD(0x54C, 0x1B0, 4, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D1__EPDC_D1	IOMUX_PAD(0x550, 0x1B4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D1__GPIO_3_1	IOMUX_PAD(0x550, 0x1B4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D1__WEIM_D1	IOMUX_PAD(0x550, 0x1B4, 2, 0x7f0, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D1__ELCDIF_CS	IOMUX_PAD(0x550, 0x1B4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_D1__ELCDIF_EN	IOMUX_PAD(0x550, 0x1B4, 4, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D2__EPDC_D2	IOMUX_PAD(0x554, 0x1B8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D2__GPIO_3_2	IOMUX_PAD(0x554, 0x1B8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D2__WEIM_D2	IOMUX_PAD(0x554, 0x1B8, 2, 0x7f4, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D2__ELCDIF_WR	IOMUX_PAD(0x554, 0x1B8, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_D2__ELCDIF_VSYNC	IOMUX_PAD(0x554, 0x1B8, 4, 0x73c, 2, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D3__EPDC_D3	IOMUX_PAD(0x558, 0x1BC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D3__GPIO_3_3	IOMUX_PAD(0x558, 0x1BC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D3__WEIM_D3	IOMUX_PAD(0x558, 0x1BC, 2, 0x7f8, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D3__ELCDIF_RD	IOMUX_PAD(0x558, 0x1BC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_D3__ELCDIF_HSYNC	IOMUX_PAD(0x558, 0x1BC, 4, 0x6f8, 3, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D4__EPDC_D4	IOMUX_PAD(0x55C, 0x1C0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D4__GPIO_3_4	IOMUX_PAD(0x55C, 0x1C0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D4__WEIM_D4	IOMUX_PAD(0x55C, 0x1C0, 2, 0x7fc, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D5__EPDC_D5	IOMUX_PAD(0x560, 0x1C4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D5__GPIO_3_5	IOMUX_PAD(0x560, 0x1C4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D5__WEIM_D5	IOMUX_PAD(0x560, 0x1C4, 2, 0x800, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D6__EPDC_D6	IOMUX_PAD(0x564, 0x1C8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D6__GPIO_3_6	IOMUX_PAD(0x564, 0x1C8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D6__WEIM_D6	IOMUX_PAD(0x564, 0x1C8, 2, 0x804, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D7__EPDC_D7	IOMUX_PAD(0x568, 0x1CC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D7__GPIO_3_7	IOMUX_PAD(0x568, 0x1CC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D7__WEIM_D7	IOMUX_PAD(0x568, 0x1CC, 2, 0x808, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D8__EPDC_D8	IOMUX_PAD(0x56C, 0x1D0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D8__GPIO_3_8	IOMUX_PAD(0x56C, 0x1D0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D8__WEIM_D8	IOMUX_PAD(0x56C, 0x1D0, 2, 0x80c, 2, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D8__ELCDIF_D24	IOMUX_PAD(0x56C, 0x1D0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D9__EPDC_D9	IOMUX_PAD(0x570, 0x1D4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D9__GPIO_3_9	IOMUX_PAD(0x570, 0x1D4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D9__WEIM_D9	IOMUX_PAD(0x570, 0x1D4, 2, 0x810, 2, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D9__ELCDIF_D25	IOMUX_PAD(0x570, 0x1D4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D10__EPDC_D10	IOMUX_PAD(0x574, 0x1D8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D10__GPIO_3_10	IOMUX_PAD(0x574, 0x1D8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D10__WEIM_D10	IOMUX_PAD(0x574, 0x1D8, 2, 0x814, 2, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D10__ELCDIF_D26	IOMUX_PAD(0x574, 0x1D8, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D11__EPDC_D11	IOMUX_PAD(0x578, 0x1DC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D11__GPIO_3_11	IOMUX_PAD(0x578, 0x1DC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D11__WEIM_D11	IOMUX_PAD(0x578, 0x1DC, 2, 0x818, 2, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D11__ELCDIF_D27	IOMUX_PAD(0x578, 0x1DC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D12__EPDC_D12	IOMUX_PAD(0x57C, 0x1E0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D12__GPIO_3_12	IOMUX_PAD(0x57C, 0x1E0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D12__WEIM_D12	IOMUX_PAD(0x57C, 0x1E0, 2, 0x81c, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D12__ELCDIF_D28	IOMUX_PAD(0x57C, 0x1E0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D13__EPDC_D13	IOMUX_PAD(0x580, 0x1E4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D13__GPIO_3_13	IOMUX_PAD(0x580, 0x1E4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D13__WEIM_D13	IOMUX_PAD(0x580, 0x1E4, 2, 0x820, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D13__ELCDIF_D29	IOMUX_PAD(0x580, 0x1E4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D14__EPDC_D14	IOMUX_PAD(0x584, 0x1E8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D14__GPIO_3_14	IOMUX_PAD(0x584, 0x1E8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D14__WEIM_D14	IOMUX_PAD(0x584, 0x1E8, 2, 0x824, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D14__ELCDIF_D30	IOMUX_PAD(0x584, 0x1E8, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_D14__AUD6_TXD	IOMUX_PAD(0x584, 0x1E8, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_D15__EPDC_D15	IOMUX_PAD(0x588, 0x1EC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D15__GPIO_3_15	IOMUX_PAD(0x588, 0x1EC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D15__WEIM_D15	IOMUX_PAD(0x588, 0x1EC, 2, 0x828, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D15__ELCDIF_D31	IOMUX_PAD(0x588, 0x1EC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_D15__AUD6_TXC	IOMUX_PAD(0x588, 0x1EC, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_GDCLK__EPDC_GDCLK	IOMUX_PAD(0x58C, 0x1F0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDCLK__GPIO_3_16	IOMUX_PAD(0x58C, 0x1F0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDCLK__WEIM_D16	IOMUX_PAD(0x58C, 0x1F0, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDCLK__ELCDIF_D16	IOMUX_PAD(0x58C, 0x1F0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_GDCLK__AUD6_TXFS	IOMUX_PAD(0x58C, 0x1F0, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_GDSP__EPDC_GDSP	IOMUX_PAD(0x590, 0x1F4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDSP__GPIO_3_17	IOMUX_PAD(0x590, 0x1F4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDSP__WEIM_D17	IOMUX_PAD(0x590, 0x1F4, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDSP__ELCDIF_D17	IOMUX_PAD(0x590, 0x1F4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_GDSP__AUD6_RXD	IOMUX_PAD(0x590, 0x1F4, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_GDOE__EPDC_GDOE	IOMUX_PAD(0x594, 0x1F8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDOE__GPIO_3_18	IOMUX_PAD(0x594, 0x1F8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDOE__WEIM_D18	IOMUX_PAD(0x594, 0x1F8, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDOE__ELCDIF_D18	IOMUX_PAD(0x594, 0x1F8, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_GDOE__AUD6_RXC	IOMUX_PAD(0x594, 0x1F8, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_GDRL__EPDC_GDRL	IOMUX_PAD(0x598, 0x1FC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDRL__GPIO_3_19	IOMUX_PAD(0x598, 0x1FC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDRL__WEIM_D19	IOMUX_PAD(0x598, 0x1FC, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_GDRL__ELCDIF_D19	IOMUX_PAD(0x598, 0x1FC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_GDRL__AUD6_RXFS	IOMUX_PAD(0x598, 0x1FC, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDCLK__EPDC_SDCLK	IOMUX_PAD(0x59C, 0x200, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCLK__GPIO_3_20	IOMUX_PAD(0x59C, 0x200, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCLK__WEIM_D20	IOMUX_PAD(0x59C, 0x200, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCLK__ELCDIF_D20	IOMUX_PAD(0x59C, 0x200, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCLK__AUD5_TXD	IOMUX_PAD(0x59C, 0x200, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDOEZ__EPDC_SDOEZ	IOMUX_PAD(0x5A0, 0x204, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOEZ__GPIO_3_21	IOMUX_PAD(0x5A0, 0x204, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOEZ__WEIM_D21	IOMUX_PAD(0x5A0, 0x204, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOEZ__ELCDIF_D21	IOMUX_PAD(0x5A0, 0x204, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOEZ__AUD5_TXC	IOMUX_PAD(0x5A0, 0x204, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDOED__EPDC_SDOED	IOMUX_PAD(0x5A4, 0x208, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOED__GPIO_3_22	IOMUX_PAD(0x5A4, 0x208, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOED__WEIM_D22	IOMUX_PAD(0x5A4, 0x208, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOED__ELCDIF_D22	IOMUX_PAD(0x5A4, 0x208, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOED__AUD5_TXFS	IOMUX_PAD(0x5A4, 0x208, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDOE__EPDC_SDOE	IOMUX_PAD(0x5A8, 0x20C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOE__GPIO_3_23	IOMUX_PAD(0x5A8, 0x20C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOE__WEIM_D23	IOMUX_PAD(0x5A8, 0x20C, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOE__ELCDIF_D23	IOMUX_PAD(0x5A8, 0x20C, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_SDOE__AUD5_RXD	IOMUX_PAD(0x5A8, 0x20C, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDLE__EPDC_SDLE	IOMUX_PAD(0x5AC, 0x210, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDLE__GPIO_3_24	IOMUX_PAD(0x5AC, 0x210, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDLE__WEIM_D24	IOMUX_PAD(0x5AC, 0x210, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDLE__ELCDIF_D8	IOMUX_PAD(0x5AC, 0x210, 3, 0x71c, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_SDLE__AUD5_RXC	IOMUX_PAD(0x5AC, 0x210, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDCLKN__EPDC_SDCLKN	IOMUX_PAD(0x5B0, 0x214, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCLKN__GPIO_3_25		IOMUX_PAD(0x5B0, 0x214, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCLKN__WEIM_D25		IOMUX_PAD(0x5B0, 0x214, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCLKN__ELCDIF_D9		IOMUX_PAD(0x5B0, 0x214, 3, 0x720, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCLKN__AUD5_RXFS		IOMUX_PAD(0x5B0, 0x214, 4, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDSHR__EPDC_SDSHR	IOMUX_PAD(0x5B4, 0x218, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDSHR__GPIO_3_26	IOMUX_PAD(0x5B4, 0x218, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDSHR__WEIM_D26	IOMUX_PAD(0x5B4, 0x218, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDSHR__ELCDIF_D10	IOMUX_PAD(0x5B4, 0x218, 3, 0x724, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_SDSHR__AUD4_TXD	IOMUX_PAD(0x5B4, 0x218, 4, 0x6c8, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_PWRCOM__EPDC_PWRCOM	IOMUX_PAD(0x5B8, 0x21C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCOM__GPIO_3_27		IOMUX_PAD(0x5B8, 0x21C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCOM__WEIM_D27		IOMUX_PAD(0x5B8, 0x21C, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCOM__ELCDIF_D11	IOMUX_PAD(0x5B8, 0x21C, 3, 0x728, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCOM__AUD4_TXC		IOMUX_PAD(0x5B8, 0x21C, 4, 0x6d4, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_PWRSTAT__EPDC_PWRSTAT	IOMUX_PAD(0x5BC, 0x220, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRSTAT__GPIO_3_28	IOMUX_PAD(0x5BC, 0x220, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRSTAT__WEIM_D28		IOMUX_PAD(0x5BC, 0x220, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRSTAT__ELCDIF_D12	IOMUX_PAD(0x5BC, 0x220, 3, 0x72c, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRSTAT__AUD4_TXFS	IOMUX_PAD(0x5BC, 0x220, 4, 0x6d8, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_PWRCTRL0__EPDC_PWRCTRL0	IOMUX_PAD(0x5C0, 0x224, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL0__GPIO_3_29	IOMUX_PAD(0x5C0, 0x224, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL0__WEIM_D29	IOMUX_PAD(0x5C0, 0x224, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL0__ELCDIF_D13	IOMUX_PAD(0x5C0, 0x224, 3, 0x730, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL0__AUD4_RXD	IOMUX_PAD(0x5C0, 0x224, 4, 0x6c4, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_PWRCTRL1__EPDC_PWRCTRL1	IOMUX_PAD(0x5C4, 0x228, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL1__GPIO_3_30	IOMUX_PAD(0x5C4, 0x228, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL1__WEIM_D30	IOMUX_PAD(0x5C4, 0x228, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL1__ELCDIF_D14	IOMUX_PAD(0x5C4, 0x228, 3, 0x734, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL1__AUD4_RXC	IOMUX_PAD(0x5C4, 0x228, 4, 0x6cc, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_PWRCTRL2__EPDC_PWRCTRL2	IOMUX_PAD(0x5C8, 0x22C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL2__GPIO_3_31	IOMUX_PAD(0x5C8, 0x22C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL2__WEIM_D31	IOMUX_PAD(0x5C8, 0x22C, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL2__ELCDIF_D15	IOMUX_PAD(0x5C8, 0x22C, 3, 0x738, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL2__AUD4_RXFS	IOMUX_PAD(0x5C8, 0x22C, 4, 0x6d0, 1, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL2__SDMA_EXT0	IOMUX_PAD(0x5C8, 0x22C, 6, 0x7b8, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_PWRCTRL3__PWRCTRL3	IOMUX_PAD(0x5CC, 0x230, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL3__GPIO_4_20	IOMUX_PAD(0x5CC, 0x230, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL3__WEIM_EB2	IOMUX_PAD(0x5CC, 0x230, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_PWRCTRL3__SDMA_EXT1	IOMUX_PAD(0x5CC, 0x230, 6, 0x7bc, 1, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_VCOM0__EPDC_VCOM0	IOMUX_PAD(0x5D0, 0x234, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_VCOM0__GPIO_4_21	IOMUX_PAD(0x5D0, 0x234, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_VCOM0__WEIM_EB3	IOMUX_PAD(0x5D0, 0x234, 2, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_VCOM1__EPDC_VCOM1	IOMUX_PAD(0x5D4, 0x238, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_VCOM1__GPIO_4_22	IOMUX_PAD(0x5D4, 0x238, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_VCOM1__WEIM_CS3	IOMUX_PAD(0x5D4, 0x238, 2, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EPDC_BDR0__EPDC_BDR0	IOMUX_PAD(0x5D8, 0x23C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_BDR0__GPIO_4_23	IOMUX_PAD(0x5D8, 0x23C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_BDR0__ELCDIF_D7	IOMUX_PAD(0x5D8, 0x23C, 3, 0x718, 1, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_BDR1__EPDC_BDR1	IOMUX_PAD(0x5DC, 0x240, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_BDR1__GPIO_4_24	IOMUX_PAD(0x5DC, 0x240, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_BDR1__ELCDIF_D6	IOMUX_PAD(0x5DC, 0x240, 3, 0x714, 1, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDCE0__EPDC_SDCE0	IOMUX_PAD(0x5E0, 0x244, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE0__GPIO_4_25	IOMUX_PAD(0x5E0, 0x244, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE0__ELCDIF_D5	IOMUX_PAD(0x5E0, 0x244, 3, 0x710, 1, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDCE1__EPDC_SDCE1	IOMUX_PAD(0x5E4, 0x248, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE1__GPIO_4_26	IOMUX_PAD(0x5E4, 0x248, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE1__ELCDIF_D4	IOMUX_PAD(0x5E4, 0x248, 2, 0x70c, 1, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDCE2__EPDC_SDCE2		IOMUX_PAD(0x5E8, 0x24C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE2__GPIO_4_27		IOMUX_PAD(0x5E8, 0x24C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE2__ELCDIF_DAT3	IOMUX_PAD(0x5E8, 0x24C, 3, 0x708, 1, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDCE3__EPDC_SDCE3	IOMUX_PAD(0x5EC, 0x250, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE3__GPIO_4_28	IOMUX_PAD(0x5EC, 0x250, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE3__ELCDIF_D2	IOMUX_PAD(0x5EC, 0x250, 3, 0x704, 1, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDCE4__EPDC_SDCE4	IOMUX_PAD(0x5F0, 0x254, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE4__GPIO_4_29	IOMUX_PAD(0x5F0, 0x254, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE4__ELCDIF_D1	IOMUX_PAD(0x5F0, 0x254, 3, 0x700, 1, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EPDC_SDCE5__EPDC_SDCE5	IOMUX_PAD(0x5F4, 0x258, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE5__GPIO_4_30	IOMUX_PAD(0x5F4, 0x258, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_SDCE5__ELCDIF_D0	IOMUX_PAD(0x5F4, 0x258, 3, 0x6fc, 1, MX50_ELCDIF_PAD_CTRL)
+
+#define MX50_PAD_EIM_DA0__WEIM_A0	IOMUX_PAD(0x5F8, 0x25C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA0__GPIO_1_0	IOMUX_PAD(0x5F8, 0x25C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA0__KEY_COL4	IOMUX_PAD(0x5f8, 0x25C, 3, 0x790, 2, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_DA1__WEIM_A1	IOMUX_PAD(0x5FC, 0x260, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA1__GPIO_1_1	IOMUX_PAD(0x5FC, 0x260, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA1__KEY_ROW4	IOMUX_PAD(0x5fc, 0x260, 3, 0x7a0, 2, MX50_KEYPAD_CTRL)
+
+#define MX50_PAD_EIM_DA2__WEIM_A2	IOMUX_PAD(0x600, 0x264, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA2__GPIO_1_2	IOMUX_PAD(0x600, 0x264, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA2__KEY_COL5	IOMUX_PAD(0x600, 0x264, 3, 0x794, 2, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_DA3__WEIM_A3	IOMUX_PAD(0x604, 0x268, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA3__GPIO_1_3	IOMUX_PAD(0x604, 0x268, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA3__KEY_ROW5	IOMUX_PAD(0x604, 0x268, 3, 0x7a4, 2, MX50_KEYPAD_CTRL)
+
+#define MX50_PAD_EIM_DA4__WEIM_A4	IOMUX_PAD(0x608, 0x26C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA4__GPIO_1_4	IOMUX_PAD(0x608, 0x26C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA4__KEY_COL6	IOMUX_PAD(0x608, 0x26C, 3, 0x798, 2, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_DA5__WEIM_A5	IOMUX_PAD(0x60C, 0x270, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA5__GPIO_1_5	IOMUX_PAD(0x60C, 0x270, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA5__KEY_ROW6	IOMUX_PAD(0x60C, 0x270, 3, 0x7a8, 2, MX50_KEYPAD_CTRL)
+
+#define MX50_PAD_EIM_DA6__WEIM_A6	IOMUX_PAD(0x610, 0x274, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA6__GPIO_1_6	IOMUX_PAD(0x610, 0x274, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA6__KEY_COL7	IOMUX_PAD(0x610, 0x274, 3, 0x79c, 2, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_DA7__WEIM_A7	IOMUX_PAD(0x614, 0x278, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA7__GPIO_1_7	IOMUX_PAD(0x614, 0x278, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA7__KEY_ROW7	IOMUX_PAD(0x614, 0x278, 3, 0x7ac, 2, MX50_KEYPAD_CTRL)
+
+#define MX50_PAD_EIM_DA8__WEIM_A8	IOMUX_PAD(0x618, 0x27C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA8__GPIO_1_8	IOMUX_PAD(0x618, 0x27C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_EIM_DA8__NANDF_CLE	IOMUX_PAD(0x618, 0x27C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_EIM_DA9__WEIM_A9	IOMUX_PAD(0x61C, 0x280, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA9__GPIO_1_9	IOMUX_PAD(0x61C, 0x280, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_EIM_DA9__NANDF_ALE	IOMUX_PAD(0x61C, 0x280, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_EIM_DA10__WEIM_A10	IOMUX_PAD(0x620, 0x284, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA10__GPIO_1_10	IOMUX_PAD(0x620, 0x284, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_EIM_DA10__NANDF_CE0	IOMUX_PAD(0x620, 0x284, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_EIM_DA11__WEIM_A11	IOMUX_PAD(0x624, 0x288, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA11__GPIO_1_11	IOMUX_PAD(0x624, 0x288, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_EIM_DA11__NANDF_CE1	IOMUX_PAD(0x624, 0x288, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+
+#define MX50_PAD_EIM_DA12__WEIM_A12	IOMUX_PAD(0x628, 0x28C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA12__GPIO_1_12	IOMUX_PAD(0x628, 0x28C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_EIM_DA12__NANDF_CE2	IOMUX_PAD(0x628, 0x28C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_EIM_DA12__EPDC_SDCE6	IOMUX_PAD(0x628, 0x28C, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_DA13__WEIM_A13	IOMUX_PAD(0x62C, 0x290, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA13__GPIO_1_13	IOMUX_PAD(0x62C, 0x290, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_EIM_DA13__NANDF_CE3	IOMUX_PAD(0x62C, 0x290, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
+#define MX50_PIN_EIM_DA13__EPDC_SDCE7	IOMUX_PAD(0x62C, 0x290, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_DA14__WEIM_A14	IOMUX_PAD(0x630, 0x294, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA14__GPIO_1_14	IOMUX_PAD(0x630, 0x294, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA14__NANDF_READY	IOMUX_PAD(0x630, 0x294, 2, 0x7B4, 2, PAD_CTL_PKE | \
+							PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
+#define MX50_PAD_EIM_DA14__EPDC_SDCE8	IOMUX_PAD(0x630, 0x294, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_DA15__WEIM_A15	IOMUX_PAD(0x634, 0x298, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_DA15__GPIO_1_15	IOMUX_PAD(0x634, 0x298, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PIN_EIM_DA15__NANDF_DQS	IOMUX_PAD(0x634, 0x298, 2, 0x7B0, 2, PAD_CTL_DSE_HIGH)
+#define MX50_PAD_EIM_DA15__EPDC_SDCE9	IOMUX_PAD(0x634, 0x298, 3, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_CS2__WEIM_CS2	IOMUX_PAD(0x638, 0x29C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_CS2__GPIO_1_16	IOMUX_PAD(0x638, 0x29C, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_CS2__WEIM_A27	IOMUX_PAD(0x638, 0x29C, 2, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_CS1__WEIM_CS1	IOMUX_PAD(0x63C, 0x2A0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_CS1__GPIO_1_17	IOMUX_PAD(0x63C, 0x2A0, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_CS0__WEIM_CS0	IOMUX_PAD(0x640, 0x2A4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_CS0__GPIO_1_18	IOMUX_PAD(0x640, 0x2A4, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_EB0__WEIM_EB0	IOMUX_PAD(0x644, 0x2A8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_EB0__GPIO_1_19	IOMUX_PAD(0x644, 0x2A8, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_EB1__WEIM_EB1	IOMUX_PAD(0x648, 0x2AC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_EB1__GPIO_1_20	IOMUX_PAD(0x648, 0x2AC, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_WAIT__WEIM_WAIT	IOMUX_PAD(0x64C, 0x2B0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_WAIT__GPIO_1_21	IOMUX_PAD(0x64C, 0x2B0, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_BCLK__WEIM_BCLK	IOMUX_PAD(0x650, 0x2B4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_BCLK__GPIO_1_22	IOMUX_PAD(0x650, 0x2B4, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_RDY__WEIM_RDY	IOMUX_PAD(0x654, 0x2B8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_RDY__GPIO_1_23	IOMUX_PAD(0x654, 0x2B8, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_OE__WEIM_OE	IOMUX_PAD(0x658, 0x2BC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_OE__GPIO_1_24	IOMUX_PAD(0x658, 0x2BC, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_RW__WEIM_RW	IOMUX_PAD(0x65C, 0x2C0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_RW__GPIO_1_25	IOMUX_PAD(0x65C, 0x2C0, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_LBA__WEIM_LBA	IOMUX_PAD(0x660, 0x2C4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_LBA__GPIO_1_26	IOMUX_PAD(0x660, 0x2C4, 1, 0x0, 0, NO_PAD_CTRL)
+
+#define MX50_PAD_EIM_CRE__WEIM_CRE	IOMUX_PAD(0x664, 0x2C8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_EIM_CRE__GPIO_1_27	IOMUX_PAD(0x664, 0x2C8, 1, 0x0, 0, NO_PAD_CTRL)
+
+#endif /* __MACH_IOMUX_MX50_H__ */
diff --git a/arch/arm/mach-imx/iomux-mx51.h b/arch/arm/mach-imx/iomux-mx51.h
new file mode 100644
index 0000000..75bbcc4
--- /dev/null
+++ b/arch/arm/mach-imx/iomux-mx51.h
@@ -0,0 +1,827 @@
+/*
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __MACH_IOMUX_MX51_H__
+#define __MACH_IOMUX_MX51_H__
+
+#include "iomux-v3.h"
+#define __NA_	0x000
+
+
+/* Pad control groupings */
+#define MX51_UART_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_DSE_HIGH | \
+				PAD_CTL_HYS | PAD_CTL_SRE_FAST)
+#define MX51_I2C_PAD_CTRL	(PAD_CTL_SRE_FAST | PAD_CTL_ODE | \
+				PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP | \
+				PAD_CTL_HYS)
+#define MX51_ESDHC_PAD_CTRL	(PAD_CTL_SRE_FAST | PAD_CTL_ODE | \
+				PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP | \
+				PAD_CTL_HYS)
+#define MX51_USBH1_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_SRE_FAST | \
+				PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP | \
+				PAD_CTL_HYS | PAD_CTL_PUE)
+#define MX51_ECSPI_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_HYS | \
+				PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST)
+#define MX51_SDHCI_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \
+				PAD_CTL_PUS_47K_UP | PAD_CTL_PUE | \
+				PAD_CTL_SRE_FAST | PAD_CTL_DVS)
+#define MX51_GPIO_PAD_CTRL	(PAD_CTL_DSE_HIGH | PAD_CTL_PKE | PAD_CTL_SRE_FAST)
+
+#define MX51_PAD_CTRL_2		(PAD_CTL_PKE | PAD_CTL_HYS)
+#define MX51_PAD_CTRL_3		(PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_CTRL_4		(PAD_CTL_PKE | PAD_CTL_DVS | PAD_CTL_HYS)
+#define MX51_PAD_CTRL_5		(PAD_CTL_DVS | PAD_CTL_DSE_HIGH)
+
+/*
+ * The naming convention for the pad modes is MX51_PAD_<padname>__<padmode>
+ * If <padname> or <padmode> refers to a GPIO, it is named GPIO<unit>_<num>
+ * See also iomux-v3.h
+ */
+
+/* Raw pin modes without pad control */
+/*							  PAD    MUX ALT INPSE PATH PADCTRL */
+
+/* The same pins as above but with the default pad control values applied */
+#define MX51_PAD_EIM_D16__AUD4_RXFS		IOMUX_PAD(0x3f0, 0x05c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__AUD5_TXD		IOMUX_PAD(0x3f0, 0x05c, 7, 0x8d8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__EIM_D16		IOMUX_PAD(0x3f0, 0x05c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__GPIO2_0		IOMUX_PAD(0x3f0, 0x05c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__I2C1_SDA		IOMUX_PAD(0x3f0, 0x05c, 0x14, 0x9b4, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D16__UART2_CTS		IOMUX_PAD(0x3f0, 0x05c, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D16__USBH2_DATA0		IOMUX_PAD(0x3f0, 0x05c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__AUD5_RXD		IOMUX_PAD(0x3f4, 0x060, 7, 0x8d4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__EIM_D17		IOMUX_PAD(0x3f4, 0x060, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__GPIO2_1		IOMUX_PAD(0x3f4, 0x060, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__UART2_RXD		IOMUX_PAD(0x3f4, 0x060, 3, 0x9ec, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D17__UART3_CTS		IOMUX_PAD(0x3f4, 0x060, 4, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D17__USBH2_DATA1		IOMUX_PAD(0x3f4, 0x060, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__AUD5_TXC		IOMUX_PAD(0x3f8, 0x064, 7, 0x8e4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__EIM_D18		IOMUX_PAD(0x3f8, 0x064, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__GPIO2_2		IOMUX_PAD(0x3f8, 0x064, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__UART2_TXD		IOMUX_PAD(0x3f8, 0x064, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D18__UART3_RTS		IOMUX_PAD(0x3f8, 0x064, 4, 0x9f0, 1, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D18__USBH2_DATA2		IOMUX_PAD(0x3f8, 0x064, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__AUD4_RXC		IOMUX_PAD(0x3fc, 0x068, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__AUD5_TXFS		IOMUX_PAD(0x3fc, 0x068, 7, 0x8e8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__EIM_D19		IOMUX_PAD(0x3fc, 0x068, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__GPIO2_3		IOMUX_PAD(0x3fc, 0x068, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__I2C1_SCL		IOMUX_PAD(0x3fc, 0x068, 0x14, 0x9b0, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D19__UART2_RTS		IOMUX_PAD(0x3fc, 0x068, 3, 0x9e8, 1, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D19__USBH2_DATA3		IOMUX_PAD(0x3fc, 0x068, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__AUD4_TXD		IOMUX_PAD(0x400, 0x06c, 5, 0x8c8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__EIM_D20		IOMUX_PAD(0x400, 0x06c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__GPIO2_4		IOMUX_PAD(0x400, 0x06c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__SRTC_ALARM_DEB	IOMUX_PAD(0x400, 0x06c, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__USBH2_DATA4		IOMUX_PAD(0x400, 0x06c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__AUD4_RXD		IOMUX_PAD(0x404, 0x070, 5, 0x8c4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__EIM_D21		IOMUX_PAD(0x404, 0x070, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__GPIO2_5		IOMUX_PAD(0x404, 0x070, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__SRTC_ALARM_DEB	IOMUX_PAD(0x404, 0x070, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__USBH2_DATA5		IOMUX_PAD(0x404, 0x070, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__AUD4_TXC		IOMUX_PAD(0x408, 0x074, 5, 0x8cc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__EIM_D22		IOMUX_PAD(0x408, 0x074, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__GPIO2_6		IOMUX_PAD(0x408, 0x074, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__USBH2_DATA6		IOMUX_PAD(0x408, 0x074, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__AUD4_TXFS		IOMUX_PAD(0x40c, 0x078, 5, 0x8d0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__EIM_D23		IOMUX_PAD(0x40c, 0x078, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__GPIO2_7		IOMUX_PAD(0x40c, 0x078, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__SPDIF_OUT1		IOMUX_PAD(0x40c, 0x078, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__USBH2_DATA7		IOMUX_PAD(0x40c, 0x078, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__AUD6_RXFS		IOMUX_PAD(0x410, 0x07c, 5, 0x8f8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__EIM_D24		IOMUX_PAD(0x410, 0x07c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__GPIO2_8		IOMUX_PAD(0x410, 0x07c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__I2C2_SDA		IOMUX_PAD(0x410, 0x07c, 0x14, 0x9bc, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D24__UART3_CTS		IOMUX_PAD(0x410, 0x07c, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D24__USBOTG_DATA0		IOMUX_PAD(0x410, 0x07c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__EIM_D25		IOMUX_PAD(0x414, 0x080, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__KEY_COL6		IOMUX_PAD(0x414, 0x080, 1, 0x9c8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__UART2_CTS		IOMUX_PAD(0x414, 0x080, 4, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D25__UART3_RXD		IOMUX_PAD(0x414, 0x080, 3, 0x9f4, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D25__USBOTG_DATA1		IOMUX_PAD(0x414, 0x080, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__GPT_CMPOUT1		IOMUX_PAD(0x414, 0x080, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__EIM_D26		IOMUX_PAD(0x418, 0x084, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__KEY_COL7		IOMUX_PAD(0x418, 0x084, 1, 0x9cc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__UART2_RTS		IOMUX_PAD(0x418, 0x084, 4, 0x9e8, 3, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D26__UART3_TXD		IOMUX_PAD(0x418, 0x084, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D26__USBOTG_DATA2		IOMUX_PAD(0x418, 0x084, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__GPT_CMPOUT2		IOMUX_PAD(0x418, 0x084, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__AUD6_RXC		IOMUX_PAD(0x41c, 0x088, 5, 0x8f4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__EIM_D27		IOMUX_PAD(0x41c, 0x088, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__GPIO2_9		IOMUX_PAD(0x41c, 0x088, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__I2C2_SCL		IOMUX_PAD(0x41c, 0x088, 0x14, 0x9b8, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D27__UART3_RTS		IOMUX_PAD(0x41c, 0x088, 3, 0x9f0, 3, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D27__USBOTG_DATA3		IOMUX_PAD(0x41c, 0x088, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__AUD6_TXD		IOMUX_PAD(0x420, 0x08c, 5, 0x8f0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__EIM_D28		IOMUX_PAD(0x420, 0x08c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__KEY_ROW4		IOMUX_PAD(0x420, 0x08c, 1, 0x9d0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__USBOTG_DATA4		IOMUX_PAD(0x420, 0x08c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__AUD6_RXD		IOMUX_PAD(0x424, 0x090, 5, 0x8ec, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__EIM_D29		IOMUX_PAD(0x424, 0x090, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__KEY_ROW5		IOMUX_PAD(0x424, 0x090, 1, 0x9d4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__USBOTG_DATA5		IOMUX_PAD(0x424, 0x090, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__AUD6_TXC		IOMUX_PAD(0x428, 0x094, 5, 0x8fc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__EIM_D30		IOMUX_PAD(0x428, 0x094, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__KEY_ROW6		IOMUX_PAD(0x428, 0x094, 1, 0x9d8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__USBOTG_DATA6		IOMUX_PAD(0x428, 0x094, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__AUD6_TXFS		IOMUX_PAD(0x42c, 0x098, 5, 0x900, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__EIM_D31		IOMUX_PAD(0x42c, 0x098, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__KEY_ROW7		IOMUX_PAD(0x42c, 0x098, 1, 0x9dc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__USBOTG_DATA7		IOMUX_PAD(0x42c, 0x098, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A16__EIM_A16		IOMUX_PAD(0x430, 0x09c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A16__GPIO2_10		IOMUX_PAD(0x430, 0x09c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A16__OSC_FREQ_SEL0		IOMUX_PAD(0x430, 0x09c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A17__EIM_A17		IOMUX_PAD(0x434, 0x0a0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A17__GPIO2_11		IOMUX_PAD(0x434, 0x0a0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A17__OSC_FREQ_SEL1		IOMUX_PAD(0x434, 0x0a0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A18__BOOT_LPB0		IOMUX_PAD(0x438, 0x0a4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A18__EIM_A18		IOMUX_PAD(0x438, 0x0a4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A18__GPIO2_12		IOMUX_PAD(0x438, 0x0a4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A19__BOOT_LPB1		IOMUX_PAD(0x43c, 0x0a8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A19__EIM_A19		IOMUX_PAD(0x43c, 0x0a8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A19__GPIO2_13		IOMUX_PAD(0x43c, 0x0a8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A20__BOOT_UART_SRC0	IOMUX_PAD(0x440, 0x0ac, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A20__EIM_A20		IOMUX_PAD(0x440, 0x0ac, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A20__GPIO2_14		IOMUX_PAD(0x440, 0x0ac, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A21__BOOT_UART_SRC1	IOMUX_PAD(0x444, 0x0b0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A21__EIM_A21		IOMUX_PAD(0x444, 0x0b0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A21__GPIO2_15		IOMUX_PAD(0x444, 0x0b0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A22__EIM_A22		IOMUX_PAD(0x448, 0x0b4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A22__GPIO2_16		IOMUX_PAD(0x448, 0x0b4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A23__BOOT_HPN_EN		IOMUX_PAD(0x44c, 0x0b8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A23__EIM_A23		IOMUX_PAD(0x44c, 0x0b8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A23__GPIO2_17		IOMUX_PAD(0x44c, 0x0b8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A24__EIM_A24		IOMUX_PAD(0x450, 0x0bc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A24__GPIO2_18		IOMUX_PAD(0x450, 0x0bc, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A24__USBH2_CLK		IOMUX_PAD(0x450, 0x0bc, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__DISP1_PIN4		IOMUX_PAD(0x454, 0x0c0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__EIM_A25		IOMUX_PAD(0x454, 0x0c0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__GPIO2_19		IOMUX_PAD(0x454, 0x0c0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__USBH2_DIR		IOMUX_PAD(0x454, 0x0c0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__CSI1_DATA_EN		IOMUX_PAD(0x458, 0x0c4, 5, 0x9a0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__DISP2_EXT_CLK		IOMUX_PAD(0x458, 0x0c4, 6, 0x908, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__EIM_A26		IOMUX_PAD(0x458, 0x0c4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__GPIO2_20		IOMUX_PAD(0x458, 0x0c4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__USBH2_STP		IOMUX_PAD(0x458, 0x0c4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__CSI2_DATA_EN		IOMUX_PAD(0x45c, 0x0c8, 5, 0x99c, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__DISP1_PIN1		IOMUX_PAD(0x45c, 0x0c8, 6, 0x9a4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__EIM_A27		IOMUX_PAD(0x45c, 0x0c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__GPIO2_21		IOMUX_PAD(0x45c, 0x0c8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__USBH2_NXT		IOMUX_PAD(0x45c, 0x0c8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB0__EIM_EB0		IOMUX_PAD(0x460, 0x0cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB1__EIM_EB1		IOMUX_PAD(0x464, 0x0d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__AUD5_RXFS		IOMUX_PAD(0x468, 0x0d4, 6, 0x8e0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__CSI1_D2		IOMUX_PAD(0x468, 0x0d4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__EIM_EB2		IOMUX_PAD(0x468, 0x0d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__FEC_MDIO		(IOMUX_PAD(0x468, 0x0d4, 3, 0x954, 0, 0) | \
+		MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP | PAD_CTL_PKE | PAD_CTL_SRE_FAST | \
+		PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS))
+#define MX51_PAD_EIM_EB2__GPIO2_22		IOMUX_PAD(0x468, 0x0d4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__GPT_CMPOUT1		IOMUX_PAD(0x468, 0x0d4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__AUD5_RXC		IOMUX_PAD(0x46c, 0x0d8, 6, 0x8dc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__CSI1_D3		IOMUX_PAD(0x46c, 0x0d8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__EIM_EB3		IOMUX_PAD(0x46c, 0x0d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__FEC_RDATA1		IOMUX_PAD(0x46c, 0x0d8, 3, 0x95c, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__GPIO2_23		IOMUX_PAD(0x46c, 0x0d8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__GPT_CMPOUT2		IOMUX_PAD(0x46c, 0x0d8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_OE__EIM_OE			IOMUX_PAD(0x470, 0x0dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_OE__GPIO2_24		IOMUX_PAD(0x470, 0x0dc, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS0__EIM_CS0		IOMUX_PAD(0x474, 0x0e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS0__GPIO2_25		IOMUX_PAD(0x474, 0x0e0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS1__EIM_CS1		IOMUX_PAD(0x478, 0x0e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS1__GPIO2_26		IOMUX_PAD(0x478, 0x0e4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__AUD5_TXD		IOMUX_PAD(0x47c, 0x0e8, 6, 0x8d8, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__CSI1_D4		IOMUX_PAD(0x47c, 0x0e8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__EIM_CS2		IOMUX_PAD(0x47c, 0x0e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__FEC_RDATA2		IOMUX_PAD(0x47c, 0x0e8, 3, 0x960, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__GPIO2_27		IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__USBOTG_STP		IOMUX_PAD(0x47c, 0x0e8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__AUD5_RXD		IOMUX_PAD(0x480, 0x0ec, 6, 0x8d4, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__CSI1_D5		IOMUX_PAD(0x480, 0x0ec, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__EIM_CS3		IOMUX_PAD(0x480, 0x0ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__FEC_RDATA3		IOMUX_PAD(0x480, 0x0ec, 3, 0x964, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__GPIO2_28		IOMUX_PAD(0x480, 0x0ec, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__USBOTG_NXT		IOMUX_PAD(0x480, 0x0ec, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__AUD5_TXC		IOMUX_PAD(0x484, 0x0f0, 6, 0x8e4, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__CSI1_D6		IOMUX_PAD(0x484, 0x0f0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__EIM_CS4		IOMUX_PAD(0x484, 0x0f0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__FEC_RX_ER		IOMUX_PAD(0x484, 0x0f0, 3, 0x970, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_EIM_CS4__GPIO2_29		IOMUX_PAD(0x484, 0x0f0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__USBOTG_CLK		IOMUX_PAD(0x484, 0x0f0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__AUD5_TXFS		IOMUX_PAD(0x488, 0x0f4, 6, 0x8e8, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__CSI1_D7		IOMUX_PAD(0x488, 0x0f4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__DISP1_EXT_CLK		IOMUX_PAD(0x488, 0x0f4, 4, 0x904, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__EIM_CS5		IOMUX_PAD(0x488, 0x0f4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__FEC_CRS		IOMUX_PAD(0x488, 0x0f4, 3, 0x950, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_EIM_CS5__GPIO2_30		IOMUX_PAD(0x488, 0x0f4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__USBOTG_DIR		IOMUX_PAD(0x488, 0x0f4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DTACK__EIM_DTACK		IOMUX_PAD(0x48c, 0x0f8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DTACK__GPIO2_31		IOMUX_PAD(0x48c, 0x0f8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_LBA__EIM_LBA		IOMUX_PAD(0x494, 0x0fc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_LBA__GPIO3_1		IOMUX_PAD(0x494, 0x0fc, 1, 0x978, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CRE__EIM_CRE		IOMUX_PAD(0x4a0, 0x100, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CRE__GPIO3_2		IOMUX_PAD(0x4a0, 0x100, 1, 0x97c, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DRAM_CS1__DRAM_CS1		IOMUX_PAD(0x4d0, 0x104, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DRAM_CS1__CCM_CLKO		IOMUX_PAD(0x4d0, 0x104, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__GPIO3_3		IOMUX_PAD(0x4e4, 0x108, 3, 0x980, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__NANDF_WE_B		IOMUX_PAD(0x4e4, 0x108, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__PATA_DIOW		IOMUX_PAD(0x4e4, 0x108, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__SD3_DATA0		IOMUX_PAD(0x4e4, 0x108, 2, 0x93c, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__GPIO3_4		IOMUX_PAD(0x4e8, 0x10c, 3, 0x984, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__NANDF_RE_B		IOMUX_PAD(0x4e8, 0x10c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__PATA_DIOR		IOMUX_PAD(0x4e8, 0x10c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__SD3_DATA1		IOMUX_PAD(0x4e8, 0x10c, 2, 0x940, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_ALE__GPIO3_5		IOMUX_PAD(0x4ec, 0x110, 3, 0x988, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_ALE__NANDF_ALE		IOMUX_PAD(0x4ec, 0x110, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_ALE__PATA_BUFFER_EN	IOMUX_PAD(0x4ec, 0x110, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CLE__GPIO3_6		IOMUX_PAD(0x4f0, 0x114, 3, 0x98c, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CLE__NANDF_CLE		IOMUX_PAD(0x4f0, 0x114, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CLE__PATA_RESET_B	IOMUX_PAD(0x4f0, 0x114, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__GPIO3_7		IOMUX_PAD(0x4f4, 0x118, 3, 0x990, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__NANDF_WP_B		IOMUX_PAD(0x4f4, 0x118, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__PATA_DMACK		IOMUX_PAD(0x4f4, 0x118, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__SD3_DATA2		IOMUX_PAD(0x4f4, 0x118, 2, 0x944, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__ECSPI2_SS1		IOMUX_PAD(0x4f8, 0x11c, 5, 0x930, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__GPIO3_8		IOMUX_PAD(0x4f8, 0x11c, 3, 0x994, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__NANDF_RB0		IOMUX_PAD(0x4f8, 0x11c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__PATA_DMARQ		IOMUX_PAD(0x4f8, 0x11c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__SD3_DATA3		IOMUX_PAD(0x4f8, 0x11c, 2, 0x948, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__CSPI_MOSI		IOMUX_PAD(0x4fc, 0x120, 6, 0x91c, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__ECSPI2_RDY		IOMUX_PAD(0x4fc, 0x120, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__GPIO3_9		IOMUX_PAD(0x4fc, 0x120, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__NANDF_RB1		IOMUX_PAD(0x4fc, 0x120, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__PATA_IORDY		IOMUX_PAD(0x4fc, 0x120, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__GPT_CMPOUT2		IOMUX_PAD(0x4fc, 0x120, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__SD4_CMD		IOMUX_PAD(0x4fc, 0x120, 0x15, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__DISP2_WAIT		IOMUX_PAD(0x500, 0x124, 5, 0x9a8, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK		IOMUX_PAD(0x500, 0x124, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__FEC_COL		IOMUX_PAD(0x500, 0x124, 1, 0x94c, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_NANDF_RB2__GPIO3_10		IOMUX_PAD(0x500, 0x124, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__NANDF_RB2		IOMUX_PAD(0x500, 0x124, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__GPT_CMPOUT3		IOMUX_PAD(0x500, 0x124, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__USBH3_H3_DP		IOMUX_PAD(0x500, 0x124, 0x17, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__USBH3_NXT		IOMUX_PAD(0x500, 0x124, 6, 0xa20, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__DISP1_WAIT		IOMUX_PAD(0x504, 0x128, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__ECSPI2_MISO		IOMUX_PAD(0x504, 0x128, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__FEC_RX_CLK		IOMUX_PAD(0x504, 0x128, 1, 0x968, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_NANDF_RB3__GPIO3_11		IOMUX_PAD(0x504, 0x128, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__NANDF_RB3		IOMUX_PAD(0x504, 0x128, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__USBH3_CLK		IOMUX_PAD(0x504, 0x128, 6, 0x9f8, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__USBH3_H3_DM		IOMUX_PAD(0x504, 0x128, 0x17, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_NAND__GPIO_NAND		IOMUX_PAD(0x514, 0x12c, 0, 0x998, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_NAND__PATA_INTRQ		IOMUX_PAD(0x514, 0x12c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS0__GPIO3_16		IOMUX_PAD(0x518, 0x130, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS0__NANDF_CS0		IOMUX_PAD(0x518, 0x130, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS1__GPIO3_17		IOMUX_PAD(0x51c, 0x134, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS1__NANDF_CS1		IOMUX_PAD(0x51c, 0x134, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__CSPI_SCLK		IOMUX_PAD(0x520, 0x138, 6, 0x914, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__FEC_TX_ER		IOMUX_PAD(0x520, 0x138, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS2__GPIO3_18		IOMUX_PAD(0x520, 0x138, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__NANDF_CS2		IOMUX_PAD(0x520, 0x138, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__PATA_CS_0		IOMUX_PAD(0x520, 0x138, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__SD4_CLK		IOMUX_PAD(0x520, 0x138, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_NANDF_CS2__USBH3_H1_DP		IOMUX_PAD(0x520, 0x138, 0x17, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__FEC_MDC		IOMUX_PAD(0x524, 0x13c, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS3__GPIO3_19		IOMUX_PAD(0x524, 0x13c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__NANDF_CS3		IOMUX_PAD(0x524, 0x13c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__PATA_CS_1		IOMUX_PAD(0x524, 0x13c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__SD4_DAT0		IOMUX_PAD(0x524, 0x13c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__USBH3_H1_DM		IOMUX_PAD(0x524, 0x13c, 0x17, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__FEC_TDATA1		IOMUX_PAD(0x528, 0x140, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS4__GPIO3_20		IOMUX_PAD(0x528, 0x140, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__NANDF_CS4		IOMUX_PAD(0x528, 0x140, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__PATA_DA_0		IOMUX_PAD(0x528, 0x140, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__SD4_DAT1		IOMUX_PAD(0x528, 0x140, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__USBH3_STP		IOMUX_PAD(0x528, 0x140, 7, 0xa24, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__FEC_TDATA2		IOMUX_PAD(0x52c, 0x144, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS5__GPIO3_21		IOMUX_PAD(0x52c, 0x144, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__NANDF_CS5		IOMUX_PAD(0x52c, 0x144, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__PATA_DA_1		IOMUX_PAD(0x52c, 0x144, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__SD4_DAT2		IOMUX_PAD(0x52c, 0x144, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__USBH3_DIR		IOMUX_PAD(0x52c, 0x144, 7, 0xa1c, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__CSPI_SS3		IOMUX_PAD(0x530, 0x148, 7, 0x928, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__FEC_TDATA3		IOMUX_PAD(0x530, 0x148, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS6__GPIO3_22		IOMUX_PAD(0x530, 0x148, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__NANDF_CS6		IOMUX_PAD(0x530, 0x148, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__PATA_DA_2		IOMUX_PAD(0x530, 0x148, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__SD4_DAT3		IOMUX_PAD(0x530, 0x148, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__FEC_TX_EN		IOMUX_PAD(0x534, 0x14c, 1, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS7__GPIO3_23		IOMUX_PAD(0x534, 0x14c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__NANDF_CS7		IOMUX_PAD(0x534, 0x14c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__SD3_CLK		IOMUX_PAD(0x534, 0x14c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0	IOMUX_PAD(0x538, 0x150, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK	IOMUX_PAD(0x538, 0x150, 1, 0x974, 0, MX51_PAD_CTRL_4)
+#define MX51_PAD_NANDF_RDY_INT__GPIO3_24	IOMUX_PAD(0x538, 0x150, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT	IOMUX_PAD(0x538, 0x150, 0, 0x938, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__SD3_CMD		IOMUX_PAD(0x538, 0x150, 0x15, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__ECSPI2_MOSI		IOMUX_PAD(0x53c, 0x154, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__GPIO3_25		IOMUX_PAD(0x53c, 0x154, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__NANDF_D15		IOMUX_PAD(0x53c, 0x154, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__PATA_DATA15		IOMUX_PAD(0x53c, 0x154, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__SD3_DAT7		IOMUX_PAD(0x53c, 0x154, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__ECSPI2_SS3		IOMUX_PAD(0x540, 0x158, 2, 0x934, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__GPIO3_26		IOMUX_PAD(0x540, 0x158, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__NANDF_D14		IOMUX_PAD(0x540, 0x158, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__PATA_DATA14		IOMUX_PAD(0x540, 0x158, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__SD3_DAT6		IOMUX_PAD(0x540, 0x158, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__ECSPI2_SS2		IOMUX_PAD(0x544, 0x15c, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__GPIO3_27		IOMUX_PAD(0x544, 0x15c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__NANDF_D13		IOMUX_PAD(0x544, 0x15c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__PATA_DATA13		IOMUX_PAD(0x544, 0x15c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__SD3_DAT5		IOMUX_PAD(0x544, 0x15c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__ECSPI2_SS1		IOMUX_PAD(0x548, 0x160, 2, 0x930, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__GPIO3_28		IOMUX_PAD(0x548, 0x160, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__NANDF_D12		IOMUX_PAD(0x548, 0x160, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__PATA_DATA12		IOMUX_PAD(0x548, 0x160, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__SD3_DAT4		IOMUX_PAD(0x548, 0x160, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__FEC_RX_DV		IOMUX_PAD(0x54c, 0x164, 2, 0x96c, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__GPIO3_29		IOMUX_PAD(0x54c, 0x164, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__NANDF_D11		IOMUX_PAD(0x54c, 0x164, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__PATA_DATA11		IOMUX_PAD(0x54c, 0x164, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__SD3_DATA3		IOMUX_PAD(0x54c, 0x164, 5, 0x948, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__GPIO3_30		IOMUX_PAD(0x550, 0x168, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__NANDF_D10		IOMUX_PAD(0x550, 0x168, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__PATA_DATA10		IOMUX_PAD(0x550, 0x168, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__SD3_DATA2		IOMUX_PAD(0x550, 0x168, 5, 0x944, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__FEC_RDATA0		IOMUX_PAD(0x554, 0x16c, 0x12, 0x958, 0, MX51_PAD_CTRL_4)
+#define MX51_PAD_NANDF_D9__GPIO3_31		IOMUX_PAD(0x554, 0x16c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__NANDF_D9		IOMUX_PAD(0x554, 0x16c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__PATA_DATA9		IOMUX_PAD(0x554, 0x16c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__SD3_DATA1		IOMUX_PAD(0x554, 0x16c, 5, 0x940, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__FEC_TDATA0		IOMUX_PAD(0x558, 0x170, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_D8__GPIO4_0		IOMUX_PAD(0x558, 0x170, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__NANDF_D8		IOMUX_PAD(0x558, 0x170, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__PATA_DATA8		IOMUX_PAD(0x558, 0x170, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__SD3_DATA0		IOMUX_PAD(0x558, 0x170, 5, 0x93c, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__GPIO4_1		IOMUX_PAD(0x55c, 0x174, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__NANDF_D7		IOMUX_PAD(0x55c, 0x174, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__PATA_DATA7		IOMUX_PAD(0x55c, 0x174, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__USBH3_DATA0		IOMUX_PAD(0x55c, 0x174, 5, 0x9fc, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__GPIO4_2		IOMUX_PAD(0x560, 0x178, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__NANDF_D6		IOMUX_PAD(0x560, 0x178, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__PATA_DATA6		IOMUX_PAD(0x560, 0x178, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__SD4_LCTL		IOMUX_PAD(0x560, 0x178, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__USBH3_DATA1		IOMUX_PAD(0x560, 0x178, 5, 0xa00, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__GPIO4_3		IOMUX_PAD(0x564, 0x17c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__NANDF_D5		IOMUX_PAD(0x564, 0x17c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__PATA_DATA5		IOMUX_PAD(0x564, 0x17c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__SD4_WP		IOMUX_PAD(0x564, 0x17c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__USBH3_DATA2		IOMUX_PAD(0x564, 0x17c, 5, 0xa04, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__GPIO4_4		IOMUX_PAD(0x568, 0x180, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__NANDF_D4		IOMUX_PAD(0x568, 0x180, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__PATA_DATA4		IOMUX_PAD(0x568, 0x180, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__SD4_CD		IOMUX_PAD(0x568, 0x180, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__USBH3_DATA3		IOMUX_PAD(0x568, 0x180, 5, 0xa08, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__GPIO4_5		IOMUX_PAD(0x56c, 0x184, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__NANDF_D3		IOMUX_PAD(0x56c, 0x184, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__PATA_DATA3		IOMUX_PAD(0x56c, 0x184, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__SD4_DAT4		IOMUX_PAD(0x56c, 0x184, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__USBH3_DATA4		IOMUX_PAD(0x56c, 0x184, 5, 0xa0c, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__GPIO4_6		IOMUX_PAD(0x570, 0x188, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__NANDF_D2		IOMUX_PAD(0x570, 0x188, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__PATA_DATA2		IOMUX_PAD(0x570, 0x188, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__SD4_DAT5		IOMUX_PAD(0x570, 0x188, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__USBH3_DATA5		IOMUX_PAD(0x570, 0x188, 5, 0xa10, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__GPIO4_7		IOMUX_PAD(0x574, 0x18c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__NANDF_D1		IOMUX_PAD(0x574, 0x18c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__PATA_DATA1		IOMUX_PAD(0x574, 0x18c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__SD4_DAT6		IOMUX_PAD(0x574, 0x18c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__USBH3_DATA6		IOMUX_PAD(0x574, 0x18c, 5, 0xa14, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__GPIO4_8		IOMUX_PAD(0x578, 0x190, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__NANDF_D0		IOMUX_PAD(0x578, 0x190, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__PATA_DATA0		IOMUX_PAD(0x578, 0x190, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__SD4_DAT7		IOMUX_PAD(0x578, 0x190, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__USBH3_DATA7		IOMUX_PAD(0x578, 0x190, 5, 0xa18, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D8__CSI1_D8		IOMUX_PAD(0x57c, 0x194, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D8__GPIO3_12		IOMUX_PAD(0x57c, 0x194, 3, 0x998, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_D9__CSI1_D9		IOMUX_PAD(0x580, 0x198, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D9__GPIO3_13		IOMUX_PAD(0x580, 0x198, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_D10__CSI1_D10		IOMUX_PAD(0x584, 0x19c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D11__CSI1_D11		IOMUX_PAD(0x588, 0x1a0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D12__CSI1_D12		IOMUX_PAD(0x58c, 0x1a4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D13__CSI1_D13		IOMUX_PAD(0x590, 0x1a8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D14__CSI1_D14		IOMUX_PAD(0x594, 0x1ac, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D15__CSI1_D15		IOMUX_PAD(0x598, 0x1b0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D16__CSI1_D16		IOMUX_PAD(0x59c, 0x1b4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D17__CSI1_D17		IOMUX_PAD(0x5a0, 0x1b8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D18__CSI1_D18		IOMUX_PAD(0x5a4, 0x1bc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D19__CSI1_D19		IOMUX_PAD(0x5a8, 0x1c0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_VSYNC__CSI1_VSYNC		IOMUX_PAD(0x5ac, 0x1c4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_VSYNC__GPIO3_14		IOMUX_PAD(0x5ac, 0x1c4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_HSYNC__CSI1_HSYNC		IOMUX_PAD(0x5b0, 0x1c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_HSYNC__GPIO3_15		IOMUX_PAD(0x5b0, 0x1c8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK	IOMUX_PAD(0x5b4, __NA_, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_MCLK__CSI1_MCLK		IOMUX_PAD(0x5b8, __NA_, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D12__CSI2_D12		IOMUX_PAD(0x5bc, 0x1cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D12__GPIO4_9		IOMUX_PAD(0x5bc, 0x1cc, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_D13__CSI2_D13		IOMUX_PAD(0x5c0, 0x1d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D13__GPIO4_10		IOMUX_PAD(0x5c0, 0x1d0, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_D14__CSI2_D14		IOMUX_PAD(0x5c4, 0x1d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D15__CSI2_D15		IOMUX_PAD(0x5c8, 0x1d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D16__CSI2_D16		IOMUX_PAD(0x5cc, 0x1dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D17__CSI2_D17		IOMUX_PAD(0x5d0, 0x1e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D18__CSI2_D18		IOMUX_PAD(0x5d4, 0x1e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D18__GPIO4_11		IOMUX_PAD(0x5d4, 0x1e4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_D19__CSI2_D19		IOMUX_PAD(0x5d8, 0x1e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D19__GPIO4_12		IOMUX_PAD(0x5d8, 0x1e8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_VSYNC__CSI2_VSYNC		IOMUX_PAD(0x5dc, 0x1ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_VSYNC__GPIO4_13		IOMUX_PAD(0x5dc, 0x1ec, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_HSYNC__CSI2_HSYNC		IOMUX_PAD(0x5e0, 0x1f0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_HSYNC__GPIO4_14		IOMUX_PAD(0x5e0, 0x1f0, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK	IOMUX_PAD(0x5e4, 0x1f4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_PIXCLK__GPIO4_15		IOMUX_PAD(0x5e4, 0x1f4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_I2C1_CLK__GPIO4_16		IOMUX_PAD(0x5e8, 0x1f8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_I2C1_CLK__I2C1_CLK		IOMUX_PAD(0x5e8, 0x1f8, 0x10, __NA_, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_I2C1_DAT__GPIO4_17		IOMUX_PAD(0x5ec, 0x1fc, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_I2C1_DAT__I2C1_DAT		IOMUX_PAD(0x5ec, 0x1fc, 0x10, __NA_, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_TXD__AUD3_TXD		IOMUX_PAD(0x5f0, 0x200, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_TXD__GPIO4_18		IOMUX_PAD(0x5f0, 0x200, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__AUD3_RXD		IOMUX_PAD(0x5f4, 0x204, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__GPIO4_19		IOMUX_PAD(0x5f4, 0x204, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__UART3_RXD		IOMUX_PAD(0x5f4, 0x204, 1, 0x9f4, 2, MX51_UART_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_CK__AUD3_TXC		IOMUX_PAD(0x5f8, 0x208, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_CK__GPIO4_20		IOMUX_PAD(0x5f8, 0x208, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__AUD3_TXFS		IOMUX_PAD(0x5fc, 0x20c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__GPIO4_21		IOMUX_PAD(0x5fc, 0x20c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__UART3_TXD		IOMUX_PAD(0x5fc, 0x20c, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI	IOMUX_PAD(0x600, 0x210, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__GPIO4_22		IOMUX_PAD(0x600, 0x210, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__I2C1_SDA		IOMUX_PAD(0x600, 0x210, 0x11, 0x9b4, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__AUD4_RXD		IOMUX_PAD(0x604, 0x214, 1, 0x8c4, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO	IOMUX_PAD(0x604, 0x214, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__GPIO4_23		IOMUX_PAD(0x604, 0x214, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__AUD4_TXC		IOMUX_PAD(0x608, 0x218, 1, 0x8cc, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0		IOMUX_PAD(0x608, 0x218, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__GPIO4_24		IOMUX_PAD(0x608, 0x218, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__AUD4_TXD		IOMUX_PAD(0x60c, 0x21c, 1, 0x8c8, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1		IOMUX_PAD(0x60c, 0x21c, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__GPIO4_25		IOMUX_PAD(0x60c, 0x21c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__AUD4_TXFS		IOMUX_PAD(0x610, 0x220, 1, 0x8d0, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY		IOMUX_PAD(0x610, 0x220, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__GPIO4_26		IOMUX_PAD(0x610, 0x220, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK	IOMUX_PAD(0x614, 0x224, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__GPIO4_27		IOMUX_PAD(0x614, 0x224, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__I2C1_SCL		IOMUX_PAD(0x614, 0x224, 0x11, 0x9b0, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_UART1_RXD__GPIO4_28		IOMUX_PAD(0x618, 0x228, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_RXD__UART1_RXD		IOMUX_PAD(0x618, 0x228, 0, 0x9e4, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART1_TXD__GPIO4_29		IOMUX_PAD(0x61c, 0x22c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_TXD__PWM2_PWMO		IOMUX_PAD(0x61c, 0x22c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART1_TXD__UART1_TXD		IOMUX_PAD(0x61c, 0x22c, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART1_RTS__GPIO4_30		IOMUX_PAD(0x620, 0x230, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_RTS__UART1_RTS		IOMUX_PAD(0x620, 0x230, 0, 0x9e0, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART1_CTS__GPIO4_31		IOMUX_PAD(0x624, 0x234, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_CTS__UART1_CTS		IOMUX_PAD(0x624, 0x234, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART2_RXD__FIRI_TXD		IOMUX_PAD(0x628, 0x238, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART2_RXD__GPIO1_20		IOMUX_PAD(0x628, 0x238, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART2_RXD__UART2_RXD		IOMUX_PAD(0x628, 0x238, 0, 0x9ec, 2, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART2_TXD__FIRI_RXD		IOMUX_PAD(0x62c, 0x23c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART2_TXD__GPIO1_21		IOMUX_PAD(0x62c, 0x23c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART2_TXD__UART2_TXD		IOMUX_PAD(0x62c, 0x23c, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__CSI1_D0		IOMUX_PAD(0x630, 0x240, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__GPIO1_22		IOMUX_PAD(0x630, 0x240, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__UART1_DTR		IOMUX_PAD(0x630, 0x240, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__UART3_RXD		IOMUX_PAD(0x630, 0x240, 1, 0x9f4, 4, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__CSI1_D1		IOMUX_PAD(0x634, 0x244, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__GPIO1_23		IOMUX_PAD(0x634, 0x244, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__UART1_DSR		IOMUX_PAD(0x634, 0x244, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__UART3_TXD		IOMUX_PAD(0x634, 0x244, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_OWIRE_LINE__GPIO1_24		IOMUX_PAD(0x638, 0x248, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_OWIRE_LINE__OWIRE_LINE		IOMUX_PAD(0x638, 0x248, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_OWIRE_LINE__SPDIF_OUT		IOMUX_PAD(0x638, 0x248, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW0__KEY_ROW0		IOMUX_PAD(0x63c, 0x24c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW1__KEY_ROW1		IOMUX_PAD(0x640, 0x250, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW2__KEY_ROW2		IOMUX_PAD(0x644, 0x254, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW3__KEY_ROW3		IOMUX_PAD(0x648, 0x258, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL0__KEY_COL0		IOMUX_PAD(0x64c, 0x25c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL0__PLL1_BYP		IOMUX_PAD(0x64c, 0x25c, 7, 0x90c, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL1__KEY_COL1		IOMUX_PAD(0x650, 0x260, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL1__PLL2_BYP		IOMUX_PAD(0x650, 0x260, 7, 0x910, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL2__KEY_COL2		IOMUX_PAD(0x654, 0x264, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL2__PLL3_BYP		IOMUX_PAD(0x654, 0x264, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL3__KEY_COL3		IOMUX_PAD(0x658, 0x268, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__I2C2_SCL		IOMUX_PAD(0x65c, 0x26c, 0x13, 0x9b8, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__KEY_COL4		IOMUX_PAD(0x65c, 0x26c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__SPDIF_OUT1		IOMUX_PAD(0x65c, 0x26c, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__UART1_RI		IOMUX_PAD(0x65c, 0x26c, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__UART3_RTS		IOMUX_PAD(0x65c, 0x26c, 2, 0x9f0, 4, MX51_UART_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__I2C2_SDA		IOMUX_PAD(0x660, 0x270, 0x13, 0x9bc, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__KEY_COL5		IOMUX_PAD(0x660, 0x270, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__UART1_DCD		IOMUX_PAD(0x660, 0x270, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__UART3_CTS		IOMUX_PAD(0x660, 0x270, 2, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__CSPI_SCLK		IOMUX_PAD(0x678, 0x278, 1, 0x914, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__GPIO1_25		IOMUX_PAD(0x678, 0x278, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__I2C2_SCL		IOMUX_PAD(0x678, 0x278, 0x15, 0x9b8, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__USBH1_CLK		IOMUX_PAD(0x678, 0x278, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__CSPI_MOSI		IOMUX_PAD(0x67c, 0x27c, 1, 0x91c, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__GPIO1_26		IOMUX_PAD(0x67c, 0x27c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__I2C2_SDA		IOMUX_PAD(0x67c, 0x27c, 0x15, 0x9bc, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__USBH1_DIR		IOMUX_PAD(0x67c, 0x27c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__CSPI_RDY		IOMUX_PAD(0x680, 0x280, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__GPIO1_27		IOMUX_PAD(0x680, 0x280, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__UART3_RXD		IOMUX_PAD(0x680, 0x280, 5, 0x9f4, 6, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__USBH1_STP		IOMUX_PAD(0x680, 0x280, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__CSPI_MISO		IOMUX_PAD(0x684, 0x284, 1, 0x918, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__GPIO1_28		IOMUX_PAD(0x684, 0x284, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__UART3_TXD		IOMUX_PAD(0x684, 0x284, 5, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__USBH1_NXT		IOMUX_PAD(0x684, 0x284, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA0__GPIO1_11		IOMUX_PAD(0x688, 0x288, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA0__UART2_CTS		IOMUX_PAD(0x688, 0x288, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA0__USBH1_DATA0	IOMUX_PAD(0x688, 0x288, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA1__GPIO1_12		IOMUX_PAD(0x68c, 0x28c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA1__UART2_RXD		IOMUX_PAD(0x68c, 0x28c, 1, 0x9ec, 4, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA1__USBH1_DATA1	IOMUX_PAD(0x68c, 0x28c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA2__GPIO1_13		IOMUX_PAD(0x690, 0x290, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA2__UART2_TXD		IOMUX_PAD(0x690, 0x290, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA2__USBH1_DATA2	IOMUX_PAD(0x690, 0x290, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA3__GPIO1_14		IOMUX_PAD(0x694, 0x294, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA3__UART2_RTS		IOMUX_PAD(0x694, 0x294, 1, 0x9e8, 5, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA3__USBH1_DATA3	IOMUX_PAD(0x694, 0x294, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA4__CSPI_SS0		IOMUX_PAD(0x698, 0x298, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA4__GPIO1_15		IOMUX_PAD(0x698, 0x298, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA4__USBH1_DATA4	IOMUX_PAD(0x698, 0x298, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA5__CSPI_SS1		IOMUX_PAD(0x69c, 0x29c, 1, 0x920, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA5__GPIO1_16		IOMUX_PAD(0x69c, 0x29c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA5__USBH1_DATA5	IOMUX_PAD(0x69c, 0x29c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA6__CSPI_SS3		IOMUX_PAD(0x6a0, 0x2a0, 1, 0x928, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA6__GPIO1_17		IOMUX_PAD(0x6a0, 0x2a0, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA6__USBH1_DATA6	IOMUX_PAD(0x6a0, 0x2a0, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__ECSPI1_SS3	IOMUX_PAD(0x6a4, 0x2a4, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__ECSPI2_SS3	IOMUX_PAD(0x6a4, 0x2a4, 5, 0x934, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__GPIO1_18		IOMUX_PAD(0x6a4, 0x2a4, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__USBH1_DATA7	IOMUX_PAD(0x6a4, 0x2a4, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_DI1_PIN11__DI1_PIN11		IOMUX_PAD(0x6a8, 0x2a8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN11__ECSPI1_SS2		IOMUX_PAD(0x6a8, 0x2a8, 7, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_DI1_PIN11__GPIO3_0		IOMUX_PAD(0x6a8, 0x2a8, 4, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN12__DI1_PIN12		IOMUX_PAD(0x6ac, 0x2ac, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN12__GPIO3_1		IOMUX_PAD(0x6ac, 0x2ac, 4, 0x978, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN13__DI1_PIN13		IOMUX_PAD(0x6b0, 0x2b0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN13__GPIO3_2		IOMUX_PAD(0x6b0, 0x2b0, 4, 0x97c, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_D0_CS__DI1_D0_CS		IOMUX_PAD(0x6b4, 0x2b4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D0_CS__GPIO3_3		IOMUX_PAD(0x6b4, 0x2b4, 4, 0x980, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__DI1_D1_CS		IOMUX_PAD(0x6b8, 0x2b8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__DISP1_PIN14		IOMUX_PAD(0x6b8, 0x2b8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__DISP1_PIN5		IOMUX_PAD(0x6b8, 0x2b8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__GPIO3_4		IOMUX_PAD(0x6b8, 0x2b8, 4, 0x984, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1	IOMUX_PAD(0x6bc, 0x2bc, 2, 0x9a4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN	IOMUX_PAD(0x6bc, 0x2bc, 0, 0x9c4, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__GPIO3_5	IOMUX_PAD(0x6bc, 0x2bc, 4, 0x988, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6	IOMUX_PAD(0x6c0, 0x2c0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO	IOMUX_PAD(0x6c0, 0x2c0, 0, 0x9c4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__GPIO3_6	IOMUX_PAD(0x6c0, 0x2c0, 4, 0x98c, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17	IOMUX_PAD(0x6c4, 0x2c4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7	IOMUX_PAD(0x6c4, 0x2c4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK	IOMUX_PAD(0x6c4, 0x2c4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__GPIO3_7	IOMUX_PAD(0x6c4, 0x2c4, 4, 0x990, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK	IOMUX_PAD(0x6c8, 0x2c8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN16	IOMUX_PAD(0x6c8, 0x2c8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN8	IOMUX_PAD(0x6c8, 0x2c8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__GPIO3_8		IOMUX_PAD(0x6c8, 0x2c8, 4, 0x994, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT0__DISP1_DAT0		IOMUX_PAD(0x6cc, 0x2cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT1__DISP1_DAT1		IOMUX_PAD(0x6d0, 0x2d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT2__DISP1_DAT2		IOMUX_PAD(0x6d4, 0x2d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT3__DISP1_DAT3		IOMUX_PAD(0x6d8, 0x2d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT4__DISP1_DAT4		IOMUX_PAD(0x6dc, 0x2dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT5__DISP1_DAT5		IOMUX_PAD(0x6e0, 0x2e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT6__BOOT_USB_SRC	IOMUX_PAD(0x6e4, 0x2e4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT6__DISP1_DAT6		IOMUX_PAD(0x6e4, 0x2e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG	IOMUX_PAD(0x6e8, 0x2e8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT7__DISP1_DAT7		IOMUX_PAD(0x6e8, 0x2e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT8__BOOT_SRC0		IOMUX_PAD(0x6ec, 0x2ec, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT8__DISP1_DAT8		IOMUX_PAD(0x6ec, 0x2ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT9__BOOT_SRC1		IOMUX_PAD(0x6f0, 0x2f0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT9__DISP1_DAT9		IOMUX_PAD(0x6f0, 0x2f0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE	IOMUX_PAD(0x6f4, 0x2f4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT10__DISP1_DAT10	IOMUX_PAD(0x6f4, 0x2f4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2	IOMUX_PAD(0x6f8, 0x2f8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT11__DISP1_DAT11	IOMUX_PAD(0x6f8, 0x2f8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL	IOMUX_PAD(0x6fc, 0x2fc, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT12__DISP1_DAT12	IOMUX_PAD(0x6fc, 0x2fc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0	IOMUX_PAD(0x700, 0x300, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT13__DISP1_DAT13	IOMUX_PAD(0x700, 0x300, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1	IOMUX_PAD(0x704, 0x304, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT14__DISP1_DAT14	IOMUX_PAD(0x704, 0x304, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH	IOMUX_PAD(0x708, 0x308, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT15__DISP1_DAT15	IOMUX_PAD(0x708, 0x308, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0	IOMUX_PAD(0x70c, 0x30c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT16__DISP1_DAT16	IOMUX_PAD(0x70c, 0x30c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1	IOMUX_PAD(0x710, 0x310, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT17__DISP1_DAT17	IOMUX_PAD(0x710, 0x310, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0	IOMUX_PAD(0x714, 0x314, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__DISP1_DAT18	IOMUX_PAD(0x714, 0x314, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__DISP2_PIN11	IOMUX_PAD(0x714, 0x314, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__DISP2_PIN5	IOMUX_PAD(0x714, 0x314, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1	IOMUX_PAD(0x718, 0x318, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__DISP1_DAT19	IOMUX_PAD(0x718, 0x318, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__DISP2_PIN12	IOMUX_PAD(0x718, 0x318, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__DISP2_PIN6	IOMUX_PAD(0x718, 0x318, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0	IOMUX_PAD(0x71c, 0x31c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__DISP1_DAT20	IOMUX_PAD(0x71c, 0x31c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__DISP2_PIN13	IOMUX_PAD(0x71c, 0x31c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__DISP2_PIN7	IOMUX_PAD(0x71c, 0x31c, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1	IOMUX_PAD(0x720, 0x320, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__DISP1_DAT21	IOMUX_PAD(0x720, 0x320, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__DISP2_PIN14	IOMUX_PAD(0x720, 0x320, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__DISP2_PIN8	IOMUX_PAD(0x720, 0x320, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0	IOMUX_PAD(0x724, 0x324, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__DISP1_DAT22	IOMUX_PAD(0x724, 0x324, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__DISP2_D0_CS	IOMUX_PAD(0x724, 0x324, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__DISP2_DAT16	IOMUX_PAD(0x724, 0x324, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1	IOMUX_PAD(0x728, 0x328, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP1_DAT23	IOMUX_PAD(0x728, 0x328, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP2_D1_CS	IOMUX_PAD(0x728, 0x328, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP2_DAT17	IOMUX_PAD(0x728, 0x328, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP2_SER_CS	IOMUX_PAD(0x728, 0x328, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN3__DI1_PIN3		IOMUX_PAD(0x72c, 0x32c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_DISP_CLK__DI1_DISP_CLK	IOMUX_PAD(0x730, __NA_, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN2__DI1_PIN2		IOMUX_PAD(0x734, 0x330, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN15__DI1_PIN15		IOMUX_PAD(0x738, __NA_, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP2__DISP1_SER_CLK		IOMUX_PAD(0x740, 0x338, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP2__DISP2_WAIT		IOMUX_PAD(0x740, 0x338, 2, 0x9a8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP3__CSI1_DATA_EN		IOMUX_PAD(0x744, 0x33c, 3, 0x9a0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP3__DISP1_SER_DIO		IOMUX_PAD(0x744, 0x33c, 0, 0x9c0, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP3__FEC_TX_ER		IOMUX_PAD(0x744, 0x33c, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DI2_PIN4__CSI2_DATA_EN		IOMUX_PAD(0x748, 0x340, 3, 0x99c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN4__DI2_PIN4		IOMUX_PAD(0x748, 0x340, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN4__FEC_CRS		IOMUX_PAD(0x748, 0x340, 2, 0x950, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN2__DI2_PIN2		IOMUX_PAD(0x74c, 0x344, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN2__FEC_MDC		IOMUX_PAD(0x74c, 0x344, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DI2_PIN3__DI2_PIN3		IOMUX_PAD(0x750, 0x348, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN3__FEC_MDIO		IOMUX_PAD(0x750, 0x348, 2, 0x954, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK	IOMUX_PAD(0x754, 0x34c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_DISP_CLK__FEC_RDATA1	IOMUX_PAD(0x754, 0x34c, 2, 0x95c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__DI2_PIN15		IOMUX_PAD(0x758, 0x350, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__DISP1_SER_DIN		IOMUX_PAD(0x758, 0x350, 0, 0x9c0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__DISP2_PIN1		IOMUX_PAD(0x758, 0x350, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__FEC_RDATA2		IOMUX_PAD(0x758, 0x350, 2, 0x960, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__DISP2_DAT0		IOMUX_PAD(0x75c, 0x354, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__FEC_RDATA3		IOMUX_PAD(0x75c, 0x354, 2, 0x964, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__KEY_COL6		IOMUX_PAD(0x75c, 0x354, 4, 0x9c8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__UART3_RXD		IOMUX_PAD(0x75c, 0x354, 5, 0x9f4, 8, MX51_UART_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__USBH3_CLK		IOMUX_PAD(0x75c, 0x354, 3, 0x9f8, 1, MX51_UART_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__DISP2_DAT1		IOMUX_PAD(0x760, 0x358, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__FEC_RX_ER		IOMUX_PAD(0x760, 0x358, 2, 0x970, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__KEY_COL7		IOMUX_PAD(0x760, 0x358, 4, 0x9cc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__UART3_TXD		IOMUX_PAD(0x760, 0x358, 5, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__USBH3_DIR		IOMUX_PAD(0x760, 0x358, 3, 0xa1c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT2__DISP2_DAT2		IOMUX_PAD(0x764, 0x35c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT3__DISP2_DAT3		IOMUX_PAD(0x768, 0x360, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT4__DISP2_DAT4		IOMUX_PAD(0x76c, 0x364, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT5__DISP2_DAT5		IOMUX_PAD(0x770, 0x368, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__DISP2_DAT6		IOMUX_PAD(0x774, 0x36c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__FEC_TDATA1		IOMUX_PAD(0x774, 0x36c, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT6__GPIO1_19		IOMUX_PAD(0x774, 0x36c, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__KEY_ROW4		IOMUX_PAD(0x774, 0x36c, 4, 0x9d0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__USBH3_STP		IOMUX_PAD(0x774, 0x36c, 3, 0xa24, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__DISP2_DAT7		IOMUX_PAD(0x778, 0x370, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__FEC_TDATA2		IOMUX_PAD(0x778, 0x370, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT7__GPIO1_29		IOMUX_PAD(0x778, 0x370, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__KEY_ROW5		IOMUX_PAD(0x778, 0x370, 4, 0x9d4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__USBH3_NXT		IOMUX_PAD(0x778, 0x370, 3, 0xa20, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__DISP2_DAT8		IOMUX_PAD(0x77c, 0x374, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__FEC_TDATA3		IOMUX_PAD(0x77c, 0x374, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT8__GPIO1_30		IOMUX_PAD(0x77c, 0x374, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__KEY_ROW6		IOMUX_PAD(0x77c, 0x374, 4, 0x9d8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__USBH3_DATA0	IOMUX_PAD(0x77c, 0x374, 3, 0x9fc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__AUD6_RXC		IOMUX_PAD(0x780, 0x378, 4, 0x8f4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__DISP2_DAT9		IOMUX_PAD(0x780, 0x378, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__FEC_TX_EN		IOMUX_PAD(0x780, 0x378, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT9__GPIO1_31		IOMUX_PAD(0x780, 0x378, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__USBH3_DATA1	IOMUX_PAD(0x780, 0x378, 3, 0xa00, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__DISP2_DAT10	IOMUX_PAD(0x784, 0x37c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__DISP2_SER_CS	IOMUX_PAD(0x784, 0x37c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__FEC_COL		IOMUX_PAD(0x784, 0x37c, 2, 0x94c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__KEY_ROW7		IOMUX_PAD(0x784, 0x37c, 4, 0x9dc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__USBH3_DATA2	IOMUX_PAD(0x784, 0x37c, 3, 0xa04, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__AUD6_TXD		IOMUX_PAD(0x788, 0x380, 4, 0x8f0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__DISP2_DAT11	IOMUX_PAD(0x788, 0x380, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__FEC_RX_CLK	IOMUX_PAD(0x788, 0x380, 2, 0x968, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__GPIO1_10		IOMUX_PAD(0x788, 0x380, 7, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__USBH3_DATA3	IOMUX_PAD(0x788, 0x380, 3, 0xa08, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__AUD6_RXD		IOMUX_PAD(0x78c, 0x384, 4, 0x8ec, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__DISP2_DAT12	IOMUX_PAD(0x78c, 0x384, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__FEC_RX_DV		IOMUX_PAD(0x78c, 0x384, 2, 0x96c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__USBH3_DATA4	IOMUX_PAD(0x78c, 0x384, 3, 0xa0c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT13__AUD6_TXC		IOMUX_PAD(0x790, 0x388, 4, 0x8fc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT13__DISP2_DAT13	IOMUX_PAD(0x790, 0x388, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT13__FEC_TX_CLK	IOMUX_PAD(0x790, 0x388, 2, 0x974, 1, MX51_PAD_CTRL_4)
+#define MX51_PAD_DISP2_DAT13__USBH3_DATA5	IOMUX_PAD(0x790, 0x388, 3, 0xa10, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT14__AUD6_TXFS		IOMUX_PAD(0x794, 0x38c, 4, 0x900, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT14__DISP2_DAT14	IOMUX_PAD(0x794, 0x38c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT14__FEC_RDATA0	IOMUX_PAD(0x794, 0x38c, 2, 0x958, 1, MX51_PAD_CTRL_4)
+#define MX51_PAD_DISP2_DAT14__USBH3_DATA6	IOMUX_PAD(0x794, 0x38c, 3, 0xa14, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__AUD6_RXFS		IOMUX_PAD(0x798, 0x390, 4, 0x8f8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__DISP1_SER_CS	IOMUX_PAD(0x798, 0x390, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__DISP2_DAT15	IOMUX_PAD(0x798, 0x390, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__FEC_TDATA0	IOMUX_PAD(0x798, 0x390, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT15__USBH3_DATA7	IOMUX_PAD(0x798, 0x390, 3, 0xa18, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__AUD5_RXFS		IOMUX_PAD(0x79c, 0x394, 1, 0x8e0, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__CSPI_MOSI		IOMUX_PAD(0x79c, 0x394, 2, 0x91c, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__SD1_CMD		IOMUX_PAD(0x79c, 0x394, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__AUD5_RXC		IOMUX_PAD(0x7a0, 0x398, 1, 0x8dc, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__CSPI_SCLK		IOMUX_PAD(0x7a0, 0x398, 2, 0x914, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__SD1_CLK		IOMUX_PAD(0x7a0, 0x398, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD1_DATA0__AUD5_TXD		IOMUX_PAD(0x7a4, 0x39c, 1, 0x8d8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__CSPI_MISO		IOMUX_PAD(0x7a4, 0x39c, 2, 0x918, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__SD1_DATA0		IOMUX_PAD(0x7a4, 0x39c, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_EIM_DA0__EIM_DA0		IOMUX_PAD(__NA_, 0x01c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA1__EIM_DA1		IOMUX_PAD(__NA_, 0x020, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA2__EIM_DA2		IOMUX_PAD(__NA_, 0x024, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA3__EIM_DA3		IOMUX_PAD(__NA_, 0x028, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__AUD5_RXD		IOMUX_PAD(0x7a8, 0x3a0, 1, 0x8d4, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__SD1_DATA1		IOMUX_PAD(0x7a8, 0x3a0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_EIM_DA4__EIM_DA4		IOMUX_PAD(__NA_, 0x02c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA5__EIM_DA5		IOMUX_PAD(__NA_, 0x030, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA6__EIM_DA6		IOMUX_PAD(__NA_, 0x034, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA7__EIM_DA7		IOMUX_PAD(__NA_, 0x038, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__AUD5_TXC		IOMUX_PAD(0x7ac, 0x3a4, 1, 0x8e4, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__SD1_DATA2		IOMUX_PAD(0x7ac, 0x3a4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_EIM_DA10__EIM_DA10		IOMUX_PAD(__NA_, 0x044, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA11__EIM_DA11		IOMUX_PAD(__NA_, 0x048, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA8__EIM_DA8		IOMUX_PAD(__NA_, 0x03c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA9__EIM_DA9		IOMUX_PAD(__NA_, 0x040, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__AUD5_TXFS		IOMUX_PAD(0x7b0, 0x3a8, 1, 0x8e8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__CSPI_SS1		IOMUX_PAD(0x7b0, 0x3a8, 2, 0x920, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__SD1_DATA3		IOMUX_PAD(0x7b0, 0x3a8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_GPIO1_0__CSPI_SS2		IOMUX_PAD(0x7b4, 0x3ac, 2, 0x924, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_GPIO1_0__GPIO1_0		IOMUX_PAD(0x7b4, 0x3ac, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO1_0__SD1_CD		IOMUX_PAD(0x7b4, 0x3ac, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_GPIO1_1__CSPI_MISO		IOMUX_PAD(0x7b8, 0x3b0, 2, 0x918, 2, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_GPIO1_1__GPIO1_1		IOMUX_PAD(0x7b8, 0x3b0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO1_1__SD1_WP		IOMUX_PAD(0x7b8, 0x3b0, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_EIM_DA12__EIM_DA12		IOMUX_PAD(__NA_, 0x04c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA13__EIM_DA13		IOMUX_PAD(__NA_, 0x050, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA14__EIM_DA14		IOMUX_PAD(__NA_, 0x054, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA15__EIM_DA15		IOMUX_PAD(__NA_, 0x058, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__CSPI_MOSI		IOMUX_PAD(0x7bc, 0x3b4, 2, 0x91c, 3, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__I2C1_SCL		IOMUX_PAD(0x7bc, 0x3b4, 0x11, 0x9b0, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__SD2_CMD		IOMUX_PAD(0x7bc, 0x3b4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__CSPI_SCLK		IOMUX_PAD(0x7c0, 0x3b8, 2, 0x914, 3, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__I2C1_SDA		IOMUX_PAD(0x7c0, 0x3b8, 0x11, 0x9b4, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__SD2_CLK		IOMUX_PAD(0x7c0, 0x3b8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD2_DATA0__CSPI_MISO		IOMUX_PAD(0x7c4, 0x3bc, 2, 0x918, 3, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA0__SD1_DAT4		IOMUX_PAD(0x7c4, 0x3bc, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA0__SD2_DATA0		IOMUX_PAD(0x7c4, 0x3bc, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__SD1_DAT5		IOMUX_PAD(0x7c8, 0x3c0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__SD2_DATA1		IOMUX_PAD(0x7c8, 0x3c0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__USBH3_H2_DP		IOMUX_PAD(0x7c8, 0x3c0, 0x12, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__SD1_DAT6		IOMUX_PAD(0x7cc, 0x3c4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__SD2_DATA2		IOMUX_PAD(0x7cc, 0x3c4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__USBH3_H2_DM		IOMUX_PAD(0x7cc, 0x3c4, 0x12, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__CSPI_SS2		IOMUX_PAD(0x7d0, 0x3c8, 2, 0x924, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__SD1_DAT7		IOMUX_PAD(0x7d0, 0x3c8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__SD2_DATA3		IOMUX_PAD(0x7d0, 0x3c8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__CCM_OUT_2		IOMUX_PAD(0x7d4, 0x3cc, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__GPIO1_2		IOMUX_PAD(0x7d4, 0x3cc, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__I2C2_SCL		IOMUX_PAD(0x7d4, 0x3cc, 0x12, 0x9b8, 3, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__PLL1_BYP		IOMUX_PAD(0x7d4, 0x3cc, 7, 0x90c, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__PWM1_PWMO		IOMUX_PAD(0x7d4, 0x3cc, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__GPIO1_3		IOMUX_PAD(0x7d8, 0x3d0, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__I2C2_SDA		IOMUX_PAD(0x7d8, 0x3d0, 0x12, 0x9bc, 3, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__CCM_CLKO2		IOMUX_PAD(0x7d8, 0x3d0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__GPT_CLKIN		IOMUX_PAD(0x7d8, 0x3d0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__PLL2_BYP		IOMUX_PAD(0x7d8, 0x3d0, 7, 0x910, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__PWM2_PWMO		IOMUX_PAD(0x7d8, 0x3d0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	IOMUX_PAD(0x7fc, 0x3d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B	IOMUX_PAD(0x7fc, 0x3d4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__DISP2_EXT_CLK		IOMUX_PAD(0x804, 0x3d8, 4, 0x908, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__EIM_RDY		IOMUX_PAD(0x804, 0x3d8, 3, 0x938, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__GPIO1_4		IOMUX_PAD(0x804, 0x3d8, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__WDOG1_WDOG_B		IOMUX_PAD(0x804, 0x3d8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__GPT_CAPIN1		IOMUX_PAD(0x804, 0x3d8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__CSI2_MCLK		IOMUX_PAD(0x808, 0x3dc, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__DISP2_PIN16		IOMUX_PAD(0x808, 0x3dc, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__GPIO1_5		IOMUX_PAD(0x808, 0x3dc, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__WDOG2_WDOG_B		IOMUX_PAD(0x808, 0x3dc, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__CCM_CLKO		IOMUX_PAD(0x808, 0x3dc, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__DISP2_PIN17		IOMUX_PAD(0x80c, 0x3e0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__GPIO1_6		IOMUX_PAD(0x80c, 0x3e0, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__REF_EN_B		IOMUX_PAD(0x80c, 0x3e0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__GPT_CAPIN2		IOMUX_PAD(0x80c, 0x3e0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__CCM_OUT_0		IOMUX_PAD(0x810, 0x3e4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__GPIO1_7		IOMUX_PAD(0x810, 0x3e4, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__SD2_WP		IOMUX_PAD(0x810, 0x3e4, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__SPDIF_OUT1		IOMUX_PAD(0x810, 0x3e4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__CSI2_DATA_EN		IOMUX_PAD(0x814, 0x3e8, 2, 0x99c, 2, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__GPIO1_8		IOMUX_PAD(0x814, 0x3e8, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__SD2_CD		IOMUX_PAD(0x814, 0x3e8, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__USBH3_PWR		IOMUX_PAD(0x814, 0x3e8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__CCM_CLKO2		IOMUX_PAD(0x814, 0x3e8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__CCM_OUT_1		IOMUX_PAD(0x818, 0x3ec, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__DISP2_D1_CS		IOMUX_PAD(0x818, 0x3ec, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__DISP2_SER_CS		IOMUX_PAD(0x818, 0x3ec, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__GPIO1_9		IOMUX_PAD(0x818, 0x3ec, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__SD2_LCTL		IOMUX_PAD(0x818, 0x3ec, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__USBH3_OC		IOMUX_PAD(0x818, 0x3ec, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__CCM_CLKO		IOMUX_PAD(0x818, 0x3ec, 4, __NA_, 0, NO_PAD_CTRL)
+
+#endif /* __MACH_IOMUX_MX51_H__ */
diff --git a/arch/arm/mach-imx/iomux-v1.c b/arch/arm/mach-imx/iomux-v1.c
new file mode 100644
index 0000000..2b156d1
--- /dev/null
+++ b/arch/arm/mach-imx/iomux-v1.c
@@ -0,0 +1,189 @@
+/*
+ * arch/arm/plat-mxc/iomux-v1.c
+ *
+ * Copyright (C) 2004 Sascha Hauer, Synertronixx GmbH
+ * Copyright (C) 2009 Uwe Kleine-Koenig, Pengutronix
+ *
+ * Common code for i.MX1, i.MX21 and i.MX27
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/map.h>
+
+#include "hardware.h"
+#include "iomux-v1.h"
+
+static void __iomem *imx_iomuxv1_baseaddr;
+static unsigned imx_iomuxv1_numports;
+
+static inline unsigned long imx_iomuxv1_readl(unsigned offset)
+{
+	return __raw_readl(imx_iomuxv1_baseaddr + offset);
+}
+
+static inline void imx_iomuxv1_writel(unsigned long val, unsigned offset)
+{
+	__raw_writel(val, imx_iomuxv1_baseaddr + offset);
+}
+
+static inline void imx_iomuxv1_rmwl(unsigned offset,
+		unsigned long mask, unsigned long value)
+{
+	unsigned long reg = imx_iomuxv1_readl(offset);
+
+	reg &= ~mask;
+	reg |= value;
+
+	imx_iomuxv1_writel(reg, offset);
+}
+
+static inline void imx_iomuxv1_set_puen(
+		unsigned int port, unsigned int pin, int on)
+{
+	unsigned long mask = 1 << pin;
+
+	imx_iomuxv1_rmwl(MXC_PUEN(port), mask, on ? mask : 0);
+}
+
+static inline void imx_iomuxv1_set_ddir(
+		unsigned int port, unsigned int pin, int out)
+{
+	unsigned long mask = 1 << pin;
+
+	imx_iomuxv1_rmwl(MXC_DDIR(port), mask, out ? mask : 0);
+}
+
+static inline void imx_iomuxv1_set_gpr(
+		unsigned int port, unsigned int pin, int af)
+{
+	unsigned long mask = 1 << pin;
+
+	imx_iomuxv1_rmwl(MXC_GPR(port), mask, af ? mask : 0);
+}
+
+static inline void imx_iomuxv1_set_gius(
+		unsigned int port, unsigned int pin, int inuse)
+{
+	unsigned long mask = 1 << pin;
+
+	imx_iomuxv1_rmwl(MXC_GIUS(port), mask, inuse ? mask : 0);
+}
+
+static inline void imx_iomuxv1_set_ocr(
+		unsigned int port, unsigned int pin, unsigned int ocr)
+{
+	unsigned long shift = (pin & 0xf) << 1;
+	unsigned long mask = 3 << shift;
+	unsigned long value = ocr << shift;
+	unsigned long offset = pin < 16 ? MXC_OCR1(port) : MXC_OCR2(port);
+
+	imx_iomuxv1_rmwl(offset, mask, value);
+}
+
+static inline void imx_iomuxv1_set_iconfa(
+		unsigned int port, unsigned int pin, unsigned int aout)
+{
+	unsigned long shift = (pin & 0xf) << 1;
+	unsigned long mask = 3 << shift;
+	unsigned long value = aout << shift;
+	unsigned long offset = pin < 16 ? MXC_ICONFA1(port) : MXC_ICONFA2(port);
+
+	imx_iomuxv1_rmwl(offset, mask, value);
+}
+
+static inline void imx_iomuxv1_set_iconfb(
+		unsigned int port, unsigned int pin, unsigned int bout)
+{
+	unsigned long shift = (pin & 0xf) << 1;
+	unsigned long mask = 3 << shift;
+	unsigned long value = bout << shift;
+	unsigned long offset = pin < 16 ? MXC_ICONFB1(port) : MXC_ICONFB2(port);
+
+	imx_iomuxv1_rmwl(offset, mask, value);
+}
+
+int mxc_gpio_mode(int gpio_mode)
+{
+	unsigned int pin = gpio_mode & GPIO_PIN_MASK;
+	unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+	unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT;
+	unsigned int aout = (gpio_mode >> GPIO_AOUT_SHIFT) & 3;
+	unsigned int bout = (gpio_mode >> GPIO_BOUT_SHIFT) & 3;
+
+	if (port >= imx_iomuxv1_numports)
+		return -EINVAL;
+
+	/* Pullup enable */
+	imx_iomuxv1_set_puen(port, pin, gpio_mode & GPIO_PUEN);
+
+	/* Data direction */
+	imx_iomuxv1_set_ddir(port, pin, gpio_mode & GPIO_OUT);
+
+	/* Primary / alternate function */
+	imx_iomuxv1_set_gpr(port, pin, gpio_mode & GPIO_AF);
+
+	/* use as gpio? */
+	imx_iomuxv1_set_gius(port, pin, !(gpio_mode & (GPIO_PF | GPIO_AF)));
+
+	imx_iomuxv1_set_ocr(port, pin, ocr);
+
+	imx_iomuxv1_set_iconfa(port, pin, aout);
+
+	imx_iomuxv1_set_iconfb(port, pin, bout);
+
+	return 0;
+}
+EXPORT_SYMBOL(mxc_gpio_mode);
+
+static int imx_iomuxv1_setup_multiple(const int *list, unsigned count)
+{
+	size_t i;
+	int ret = 0;
+
+	for (i = 0; i < count; ++i) {
+		ret = mxc_gpio_mode(list[i]);
+
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+		const char *label)
+{
+	int ret;
+
+	ret = imx_iomuxv1_setup_multiple(pin_list, count);
+	return ret;
+}
+EXPORT_SYMBOL(mxc_gpio_setup_multiple_pins);
+
+int __init imx_iomuxv1_init(void __iomem *base, int numports)
+{
+	imx_iomuxv1_baseaddr = base;
+	imx_iomuxv1_numports = numports;
+
+	return 0;
+}
diff --git a/arch/arm/mach-imx/iomux-v1.h b/arch/arm/mach-imx/iomux-v1.h
new file mode 100644
index 0000000..02651a4
--- /dev/null
+++ b/arch/arm/mach-imx/iomux-v1.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#ifndef __MACH_IOMUX_V1_H__
+#define __MACH_IOMUX_V1_H__
+
+/*
+*  GPIO Module and I/O Multiplexer
+*  x = 0..3 for reg_A, reg_B, reg_C, reg_D
+*/
+#define MXC_DDIR(x)	(0x00 + ((x) << 8))
+#define MXC_OCR1(x)	(0x04 + ((x) << 8))
+#define MXC_OCR2(x)	(0x08 + ((x) << 8))
+#define MXC_ICONFA1(x)	(0x0c + ((x) << 8))
+#define MXC_ICONFA2(x)	(0x10 + ((x) << 8))
+#define MXC_ICONFB1(x)	(0x14 + ((x) << 8))
+#define MXC_ICONFB2(x)	(0x18 + ((x) << 8))
+#define MXC_DR(x)	(0x1c + ((x) << 8))
+#define MXC_GIUS(x)	(0x20 + ((x) << 8))
+#define MXC_SSR(x)	(0x24 + ((x) << 8))
+#define MXC_ICR1(x)	(0x28 + ((x) << 8))
+#define MXC_ICR2(x)	(0x2c + ((x) << 8))
+#define MXC_IMR(x)	(0x30 + ((x) << 8))
+#define MXC_ISR(x)	(0x34 + ((x) << 8))
+#define MXC_GPR(x)	(0x38 + ((x) << 8))
+#define MXC_SWR(x)	(0x3c + ((x) << 8))
+#define MXC_PUEN(x)	(0x40 + ((x) << 8))
+
+#define MX1_NUM_GPIO_PORT	4
+#define MX21_NUM_GPIO_PORT	6
+#define MX27_NUM_GPIO_PORT	6
+
+#define GPIO_PIN_MASK 0x1f
+
+#define GPIO_PORT_SHIFT 5
+#define GPIO_PORT_MASK (0x7 << GPIO_PORT_SHIFT)
+
+#define GPIO_PORTA	(0 << GPIO_PORT_SHIFT)
+#define GPIO_PORTB	(1 << GPIO_PORT_SHIFT)
+#define GPIO_PORTC	(2 << GPIO_PORT_SHIFT)
+#define GPIO_PORTD	(3 << GPIO_PORT_SHIFT)
+#define GPIO_PORTE	(4 << GPIO_PORT_SHIFT)
+#define GPIO_PORTF	(5 << GPIO_PORT_SHIFT)
+
+#define GPIO_OUT	(1 << 8)
+#define GPIO_IN		(0 << 8)
+#define GPIO_PUEN	(1 << 9)
+
+#define GPIO_PF		(1 << 10)
+#define GPIO_AF		(1 << 11)
+
+#define GPIO_OCR_SHIFT 12
+#define GPIO_OCR_MASK	(3 << GPIO_OCR_SHIFT)
+#define GPIO_AIN	(0 << GPIO_OCR_SHIFT)
+#define GPIO_BIN	(1 << GPIO_OCR_SHIFT)
+#define GPIO_CIN	(2 << GPIO_OCR_SHIFT)
+#define GPIO_GPIO	(3 << GPIO_OCR_SHIFT)
+
+#define GPIO_AOUT_SHIFT	14
+#define GPIO_AOUT_MASK	(3 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT	(0 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT_ISR	(1 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT_0	(2 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT_1	(3 << GPIO_AOUT_SHIFT)
+
+#define GPIO_BOUT_SHIFT	16
+#define GPIO_BOUT_MASK	(3 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT	(0 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT_ISR	(1 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT_0	(2 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT_1	(3 << GPIO_BOUT_SHIFT)
+
+extern int mxc_gpio_mode(int gpio_mode);
+extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+		const char *label);
+
+extern int imx_iomuxv1_init(void __iomem *base, int numports);
+
+#endif /* __MACH_IOMUX_V1_H__ */
diff --git a/arch/arm/mach-imx/iomux-v3.c b/arch/arm/mach-imx/iomux-v3.c
new file mode 100644
index 0000000..9dae74b
--- /dev/null
+++ b/arch/arm/mach-imx/iomux-v3.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
+ *                       <armlinux@phytec.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/map.h>
+
+#include "hardware.h"
+#include "iomux-v3.h"
+
+static void __iomem *base;
+
+/*
+ * configures a single pad in the iomuxer
+ */
+int mxc_iomux_v3_setup_pad(iomux_v3_cfg_t pad)
+{
+	u32 mux_ctrl_ofs = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT;
+	u32 mux_mode = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT;
+	u32 sel_input_ofs = (pad & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT;
+	u32 sel_input = (pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT;
+	u32 pad_ctrl_ofs = (pad & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT;
+	u32 pad_ctrl = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT;
+
+	if (mux_ctrl_ofs)
+		__raw_writel(mux_mode, base + mux_ctrl_ofs);
+
+	if (sel_input_ofs)
+		__raw_writel(sel_input, base + sel_input_ofs);
+
+	if (!(pad_ctrl & NO_PAD_CTRL) && pad_ctrl_ofs)
+		__raw_writel(pad_ctrl, base + pad_ctrl_ofs);
+
+	return 0;
+}
+EXPORT_SYMBOL(mxc_iomux_v3_setup_pad);
+
+int mxc_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count)
+{
+	iomux_v3_cfg_t *p = pad_list;
+	int i;
+	int ret;
+
+	for (i = 0; i < count; i++) {
+		ret = mxc_iomux_v3_setup_pad(*p);
+		if (ret)
+			return ret;
+		p++;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(mxc_iomux_v3_setup_multiple_pads);
+
+void mxc_iomux_v3_init(void __iomem *iomux_v3_base)
+{
+	base = iomux_v3_base;
+}
diff --git a/arch/arm/mach-imx/iomux-v3.h b/arch/arm/mach-imx/iomux-v3.h
new file mode 100644
index 0000000..2fa3b54
--- /dev/null
+++ b/arch/arm/mach-imx/iomux-v3.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
+ *			<armlinux@phytec.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __MACH_IOMUX_V3_H__
+#define __MACH_IOMUX_V3_H__
+
+/*
+ *	build IOMUX_PAD structure
+ *
+ * This iomux scheme is based around pads, which are the physical balls
+ * on the processor.
+ *
+ * - Each pad has a pad control register (IOMUXC_SW_PAD_CTRL_x) which controls
+ *   things like driving strength and pullup/pulldown.
+ * - Each pad can have but not necessarily does have an output routing register
+ *   (IOMUXC_SW_MUX_CTL_PAD_x).
+ * - Each pad can have but not necessarily does have an input routing register
+ *   (IOMUXC_x_SELECT_INPUT)
+ *
+ * The three register sets do not have a fixed offset to each other,
+ * hence we order this table by pad control registers (which all pads
+ * have) and put the optional i/o routing registers into additional
+ * fields.
+ *
+ * The naming convention for the pad modes is MX35_PAD_<padname>__<padmode>
+ * If <padname> or <padmode> refers to a GPIO, it is named
+ * GPIO_<unit>_<num>
+ *
+ * IOMUX/PAD Bit field definitions
+ *
+ * MUX_CTRL_OFS:	    0..11 (12)
+ * PAD_CTRL_OFS:	   12..23 (12)
+ * SEL_INPUT_OFS:	   24..35 (12)
+ * MUX_MODE + SION:	   36..40  (5)
+ * PAD_CTRL + NO_PAD_CTRL: 41..57 (17)
+ * SEL_INP:		   58..61  (4)
+ * reserved:		     63    (1)
+*/
+
+typedef u64 iomux_v3_cfg_t;
+
+#define MUX_CTRL_OFS_SHIFT	0
+#define MUX_CTRL_OFS_MASK	((iomux_v3_cfg_t)0xfff << MUX_CTRL_OFS_SHIFT)
+#define MUX_PAD_CTRL_OFS_SHIFT	12
+#define MUX_PAD_CTRL_OFS_MASK	((iomux_v3_cfg_t)0xfff << MUX_PAD_CTRL_OFS_SHIFT)
+#define MUX_SEL_INPUT_OFS_SHIFT	24
+#define MUX_SEL_INPUT_OFS_MASK	((iomux_v3_cfg_t)0xfff << MUX_SEL_INPUT_OFS_SHIFT)
+
+#define MUX_MODE_SHIFT		36
+#define MUX_MODE_MASK		((iomux_v3_cfg_t)0x1f << MUX_MODE_SHIFT)
+#define MUX_PAD_CTRL_SHIFT	41
+#define MUX_PAD_CTRL_MASK	((iomux_v3_cfg_t)0x1ffff << MUX_PAD_CTRL_SHIFT)
+#define MUX_SEL_INPUT_SHIFT	58
+#define MUX_SEL_INPUT_MASK	((iomux_v3_cfg_t)0xf << MUX_SEL_INPUT_SHIFT)
+
+#define MUX_PAD_CTRL(x)		((iomux_v3_cfg_t)(x) << MUX_PAD_CTRL_SHIFT)
+
+#define IOMUX_PAD(_pad_ctrl_ofs, _mux_ctrl_ofs, _mux_mode, _sel_input_ofs, \
+		_sel_input, _pad_ctrl)					\
+	(((iomux_v3_cfg_t)(_mux_ctrl_ofs) << MUX_CTRL_OFS_SHIFT) |	\
+		((iomux_v3_cfg_t)(_mux_mode) << MUX_MODE_SHIFT) |	\
+		((iomux_v3_cfg_t)(_pad_ctrl_ofs) << MUX_PAD_CTRL_OFS_SHIFT) | \
+		((iomux_v3_cfg_t)(_pad_ctrl) << MUX_PAD_CTRL_SHIFT) |	\
+		((iomux_v3_cfg_t)(_sel_input_ofs) << MUX_SEL_INPUT_OFS_SHIFT) | \
+		((iomux_v3_cfg_t)(_sel_input) << MUX_SEL_INPUT_SHIFT))
+
+#define NEW_PAD_CTRL(cfg, pad)	(((cfg) & ~MUX_PAD_CTRL_MASK) | MUX_PAD_CTRL(pad))
+/*
+ * Use to set PAD control
+ */
+
+#define NO_PAD_CTRL			(1 << 16)
+#define PAD_CTL_DVS			(1 << 13)
+#define PAD_CTL_HYS			(1 << 8)
+
+#define PAD_CTL_PKE			(1 << 7)
+#define PAD_CTL_PUE			(1 << 6 | PAD_CTL_PKE)
+#define PAD_CTL_PUS_100K_DOWN		(0 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_47K_UP		(1 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_100K_UP		(2 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_22K_UP		(3 << 4 | PAD_CTL_PUE)
+
+#define PAD_CTL_ODE			(1 << 3)
+
+#define PAD_CTL_DSE_LOW			(0 << 1)
+#define PAD_CTL_DSE_MED			(1 << 1)
+#define PAD_CTL_DSE_HIGH		(2 << 1)
+#define PAD_CTL_DSE_MAX			(3 << 1)
+
+#define PAD_CTL_SRE_FAST		(1 << 0)
+#define PAD_CTL_SRE_SLOW		(0 << 0)
+
+#define IOMUX_CONFIG_SION		(0x1 << 4)
+
+#define MX51_NUM_GPIO_PORT	4
+
+#define GPIO_PIN_MASK 0x1f
+
+#define GPIO_PORT_SHIFT 5
+#define GPIO_PORT_MASK (0x7 << GPIO_PORT_SHIFT)
+
+#define GPIO_PORTA	(0 << GPIO_PORT_SHIFT)
+#define GPIO_PORTB	(1 << GPIO_PORT_SHIFT)
+#define GPIO_PORTC	(2 << GPIO_PORT_SHIFT)
+#define GPIO_PORTD	(3 << GPIO_PORT_SHIFT)
+#define GPIO_PORTE	(4 << GPIO_PORT_SHIFT)
+#define GPIO_PORTF	(5 << GPIO_PORT_SHIFT)
+
+/*
+ * setups a single pad in the iomuxer
+ */
+int mxc_iomux_v3_setup_pad(iomux_v3_cfg_t pad);
+
+/*
+ * setups mutliple pads
+ * convenient way to call the above function with tables
+ */
+int mxc_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count);
+
+/*
+ * Initialise the iomux controller
+ */
+void mxc_iomux_v3_init(void __iomem *iomux_v3_base);
+
+#endif /* __MACH_IOMUX_V3_H__*/
+
diff --git a/arch/arm/mach-imx/iram.h b/arch/arm/mach-imx/iram.h
new file mode 100644
index 0000000..022690c
--- /dev/null
+++ b/arch/arm/mach-imx/iram.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#include <linux/errno.h>
+
+#ifdef CONFIG_IRAM_ALLOC
+
+int __init iram_init(unsigned long base, unsigned long size);
+void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr);
+void iram_free(unsigned long dma_addr, unsigned int size);
+
+#else
+
+static inline int __init iram_init(unsigned long base, unsigned long size)
+{
+	return -ENOMEM;
+}
+
+static inline void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr)
+{
+	return NULL;
+}
+
+static inline void iram_free(unsigned long base, unsigned long size) {}
+
+#endif
diff --git a/arch/arm/mach-imx/iram_alloc.c b/arch/arm/mach-imx/iram_alloc.c
new file mode 100644
index 0000000..6c80424
--- /dev/null
+++ b/arch/arm/mach-imx/iram_alloc.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/genalloc.h>
+
+#include "iram.h"
+
+static unsigned long iram_phys_base;
+static void __iomem *iram_virt_base;
+static struct gen_pool *iram_pool;
+
+static inline void __iomem *iram_phys_to_virt(unsigned long p)
+{
+	return iram_virt_base + (p - iram_phys_base);
+}
+
+void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr)
+{
+	if (!iram_pool)
+		return NULL;
+
+	*dma_addr = gen_pool_alloc(iram_pool, size);
+	pr_debug("iram alloc - %dB@0x%lX\n", size, *dma_addr);
+	if (!*dma_addr)
+		return NULL;
+	return iram_phys_to_virt(*dma_addr);
+}
+EXPORT_SYMBOL(iram_alloc);
+
+void iram_free(unsigned long addr, unsigned int size)
+{
+	if (!iram_pool)
+		return;
+
+	gen_pool_free(iram_pool, addr, size);
+}
+EXPORT_SYMBOL(iram_free);
+
+int __init iram_init(unsigned long base, unsigned long size)
+{
+	iram_phys_base = base;
+
+	iram_pool = gen_pool_create(PAGE_SHIFT, -1);
+	if (!iram_pool)
+		return -ENOMEM;
+
+	gen_pool_add(iram_pool, base, size, -1);
+	iram_virt_base = ioremap(iram_phys_base, size);
+	if (!iram_virt_base)
+		return -EIO;
+
+	pr_debug("i.MX IRAM pool: %ld KB@0x%p\n", size / 1024, iram_virt_base);
+	return 0;
+}
diff --git a/arch/arm/mach-imx/irq-common.c b/arch/arm/mach-imx/irq-common.c
new file mode 100644
index 0000000..b6e1145
--- /dev/null
+++ b/arch/arm/mach-imx/irq-common.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) BitBox Ltd 2010
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/irq.h>
+
+#include "irq-common.h"
+
+int imx_irq_set_priority(unsigned char irq, unsigned char prio)
+{
+	struct irq_chip_generic *gc;
+	struct mxc_extra_irq *exirq;
+	int ret;
+
+	ret = -ENOSYS;
+
+	gc = irq_get_chip_data(irq);
+	if (gc && gc->private) {
+		exirq = gc->private;
+		if (exirq->set_priority)
+			ret = exirq->set_priority(irq, prio);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(imx_irq_set_priority);
+
+int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
+{
+	struct irq_chip_generic *gc;
+	struct mxc_extra_irq *exirq;
+	int ret;
+
+	ret = -ENOSYS;
+
+	gc = irq_get_chip_data(irq);
+	if (gc && gc->private) {
+		exirq = gc->private;
+		if (exirq->set_irq_fiq)
+			ret = exirq->set_irq_fiq(irq, type);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(mxc_set_irq_fiq);
diff --git a/arch/arm/mach-imx/irq-common.h b/arch/arm/mach-imx/irq-common.h
new file mode 100644
index 0000000..5b2dabb
--- /dev/null
+++ b/arch/arm/mach-imx/irq-common.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) BitBox Ltd 2010
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ */
+
+#ifndef __PLAT_MXC_IRQ_COMMON_H__
+#define __PLAT_MXC_IRQ_COMMON_H__
+
+/* all normal IRQs can be FIQs */
+#define FIQ_START	0
+
+struct mxc_extra_irq
+{
+	int (*set_priority)(unsigned char irq, unsigned char prio);
+	int (*set_irq_fiq)(unsigned int irq, unsigned int type);
+};
+
+#endif
diff --git a/arch/arm/mach-imx/lluart.c b/arch/arm/mach-imx/lluart.c
index c40a34c..2fdc9bf 100644
--- a/arch/arm/mach-imx/lluart.c
+++ b/arch/arm/mach-imx/lluart.c
@@ -14,19 +14,28 @@
 #include <asm/page.h>
 #include <asm/sizes.h>
 #include <asm/mach/map.h>
-#include <mach/hardware.h>
+
+#include "hardware.h"
+
+#define IMX6Q_UART1_BASE_ADDR	0x02020000
+#define IMX6Q_UART2_BASE_ADDR	0x021e8000
+#define IMX6Q_UART3_BASE_ADDR	0x021ec000
+#define IMX6Q_UART4_BASE_ADDR	0x021f0000
+#define IMX6Q_UART5_BASE_ADDR	0x021f4000
+
+/*
+ * IMX6Q_UART_BASE_ADDR is put in the middle to force the expansion
+ * of IMX6Q_UART##n##_BASE_ADDR.
+ */
+#define IMX6Q_UART_BASE_ADDR(n)	IMX6Q_UART##n##_BASE_ADDR
+#define IMX6Q_UART_BASE(n)	IMX6Q_UART_BASE_ADDR(n)
+#define IMX6Q_DEBUG_UART_BASE	IMX6Q_UART_BASE(CONFIG_DEBUG_IMX6Q_UART_PORT)
 
 static struct map_desc imx_lluart_desc = {
-#ifdef CONFIG_DEBUG_IMX6Q_UART2
-	.virtual	= MX6Q_IO_P2V(MX6Q_UART2_BASE_ADDR),
-	.pfn		= __phys_to_pfn(MX6Q_UART2_BASE_ADDR),
-	.length		= MX6Q_UART2_SIZE,
-	.type		= MT_DEVICE,
-#endif
-#ifdef CONFIG_DEBUG_IMX6Q_UART4
-	.virtual	= MX6Q_IO_P2V(MX6Q_UART4_BASE_ADDR),
-	.pfn		= __phys_to_pfn(MX6Q_UART4_BASE_ADDR),
-	.length		= MX6Q_UART4_SIZE,
+#ifdef CONFIG_DEBUG_IMX6Q_UART
+	.virtual	= IMX_IO_P2V(IMX6Q_DEBUG_UART_BASE),
+	.pfn		= __phys_to_pfn(IMX6Q_DEBUG_UART_BASE),
+	.length		= 0x4000,
 	.type		= MT_DEVICE,
 #endif
 };
diff --git a/arch/arm/mach-imx/mach-apf9328.c b/arch/arm/mach-imx/mach-apf9328.c
index 7b99a79..5c9bd2c 100644
--- a/arch/arm/mach-imx/mach-apf9328.c
+++ b/arch/arm/mach-imx/mach-apf9328.c
@@ -25,11 +25,10 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx1.h>
-
+#include "common.h"
 #include "devices-imx1.h"
+#include "hardware.h"
+#include "iomux-mx1.h"
 
 static const int apf9328_pins[] __initconst = {
 	/* UART1 */
diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c
index 5985ed1..59bd6b0 100644
--- a/arch/arm/mach-imx/mach-armadillo5x0.c
+++ b/arch/arm/mach-imx/mach-armadillo5x0.c
@@ -41,19 +41,18 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/memory.h>
 #include <asm/mach/map.h>
 
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
-#include <mach/ulpi.h>
-
+#include "common.h"
 #include "devices-imx31.h"
 #include "crmregs-imx3.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
+#include "ulpi.h"
 
 static int armadillo5x0_pins[] = {
 	/* UART1 */
diff --git a/arch/arm/mach-imx/mach-bug.c b/arch/arm/mach-imx/mach-bug.c
index 9a98977..3a39d5a 100644
--- a/arch/arm/mach-imx/mach-bug.c
+++ b/arch/arm/mach-imx/mach-bug.c
@@ -19,15 +19,14 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
-#include <mach/iomux-mx3.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-
 #include <asm/mach/time.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
 
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c
index 2bb9e18..12a3706 100644
--- a/arch/arm/mach-imx/mach-cpuimx27.c
+++ b/arch/arm/mach-imx/mach-cpuimx27.c
@@ -34,13 +34,12 @@
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 
-#include <mach/eukrea-baseboards.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx27.h>
-#include <mach/ulpi.h>
-
+#include "common.h"
 #include "devices-imx27.h"
+#include "eukrea-baseboards.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
+#include "ulpi.h"
 
 static const int eukrea_cpuimx27_pins[] __initconst = {
 	/* UART1 */
diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c
index d49b0ec..5a31bf8 100644
--- a/arch/arm/mach-imx/mach-cpuimx35.c
+++ b/arch/arm/mach-imx/mach-cpuimx35.c
@@ -37,12 +37,11 @@
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 
-#include <mach/eukrea-baseboards.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx35.h>
-
+#include "common.h"
 #include "devices-imx35.h"
+#include "eukrea-baseboards.h"
+#include "hardware.h"
+#include "iomux-mx35.h"
 
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
diff --git a/arch/arm/mach-imx/mach-cpuimx51sd.c b/arch/arm/mach-imx/mach-cpuimx51sd.c
index b87cc49..b727de0 100644
--- a/arch/arm/mach-imx/mach-cpuimx51sd.c
+++ b/arch/arm/mach-imx/mach-cpuimx51sd.c
@@ -26,18 +26,17 @@
 #include <linux/spi/spi.h>
 #include <linux/can/platform/mcp251x.h>
 
-#include <mach/eukrea-baseboards.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
+#include "common.h"
 #include "devices-imx51.h"
 #include "cpu_op-mx51.h"
+#include "eukrea-baseboards.h"
+#include "hardware.h"
+#include "iomux-mx51.h"
 
 #define USBH1_RST		IMX_GPIO_NR(2, 28)
 #define ETH_RST			IMX_GPIO_NR(2, 31)
diff --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
index 017bbb7..75027a5 100644
--- a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
+++ b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
@@ -27,18 +27,18 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 
-#include <mach/eukrea-baseboards.h>
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/memory.h>
 #include <asm/mach/map.h>
-#include <mach/common.h>
-#include <mach/mx25.h>
-#include <mach/iomux-mx25.h>
 
+#include "common.h"
 #include "devices-imx25.h"
+#include "eukrea-baseboards.h"
+#include "hardware.h"
+#include "iomux-mx25.h"
+#include "mx25.h"
 
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
index 141756f..318bd8d 100644
--- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
@@ -40,17 +40,21 @@
 #include <asm/mach/time.h>
 #include <asm/system_info.h>
 #include <asm/memblock.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx27.h>
 
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
 
 #define TVP5150_RSTN (GPIO_PORTC + 18)
 #define TVP5150_PWDN (GPIO_PORTC + 19)
 #define OTG_PHY_CS_GPIO (GPIO_PORTF + 17)
 #define SDHC1_IRQ_GPIO IMX_GPIO_NR(2, 25)
 
+#define VERSION_MASK		0x7
+#define MOTHERBOARD_SHIFT	4
+#define EXPBOARD_SHIFT		0
+
 #define MOTHERBOARD_BIT2	(GPIO_PORTD + 31)
 #define MOTHERBOARD_BIT1	(GPIO_PORTD + 30)
 #define MOTHERBOARD_BIT0	(GPIO_PORTD + 29)
@@ -237,7 +241,7 @@ static struct mx2_camera_platform_data visstrim_camera = {
 static phys_addr_t mx2_camera_base __initdata;
 #define MX2_CAMERA_BUF_SIZE SZ_8M
 
-static void __init visstrim_camera_init(void)
+static void __init visstrim_analog_camera_init(void)
 {
 	struct platform_device *pdev;
 	int dma;
@@ -474,6 +478,27 @@ static void __init visstrim_deinterlace_init(void)
 		return;
 }
 
+/* Emma-PrP for format conversion */
+static void __init visstrim_emmaprp_init(void)
+{
+	struct platform_device *pdev;
+	int dma;
+
+	pdev = imx27_add_mx2_emmaprp();
+	if (IS_ERR(pdev))
+		return;
+
+	/*
+	 * Use the same memory area as the analog camera since both
+	 * devices are, by nature, exclusive.
+	 */
+	dma = dma_declare_coherent_memory(&pdev->dev,
+				mx2_camera_base, mx2_camera_base,
+				MX2_CAMERA_BUF_SIZE,
+				DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
+	if (!(dma & DMA_MEMORY_MAP))
+		pr_err("Failed to declare memory for emmaprp\n");
+}
 
 /* Audio */
 static const struct snd_mx27vis_platform_data snd_mx27vis_pdata __initconst = {
@@ -507,13 +532,14 @@ static void __init visstrim_m10_revision(void)
 	mo_version |= !gpio_get_value(MOTHERBOARD_BIT0);
 
 	system_rev = 0x27000;
-	system_rev |= (mo_version << 4);
-	system_rev |= exp_version;
+	system_rev |= (mo_version << MOTHERBOARD_SHIFT);
+	system_rev |= (exp_version << EXPBOARD_SHIFT);
 }
 
 static void __init visstrim_m10_board_init(void)
 {
 	int ret;
+	int mo_version;
 
 	imx27_soc_init();
 	visstrim_m10_revision();
@@ -546,8 +572,24 @@ static void __init visstrim_m10_board_init(void)
 	platform_device_register_resndata(NULL, "soc-camera-pdrv", 0, NULL, 0,
 				      &iclink_tvp5150, sizeof(iclink_tvp5150));
 	gpio_led_register_device(0, &visstrim_m10_led_data);
-	visstrim_deinterlace_init();
-	visstrim_camera_init();
+
+	/* Use mother board version to decide what video devices we shall use */
+	mo_version = (system_rev >> MOTHERBOARD_SHIFT) & VERSION_MASK;
+	if (mo_version & 0x1) {
+		visstrim_emmaprp_init();
+
+		/*
+		 * Despite not being used, tvp5150 must be
+		 * powered on to avoid I2C problems. To minimize
+		 * power consupmtion keep reset enabled.
+		 */
+		gpio_set_value(TVP5150_PWDN, 1);
+		ndelay(1);
+		gpio_set_value(TVP5150_RSTN, 0);
+	} else {
+		visstrim_deinterlace_init();
+		visstrim_analog_camera_init();
+	}
 	visstrim_coda_init();
 }
 
diff --git a/arch/arm/mach-imx/mach-imx27ipcam.c b/arch/arm/mach-imx/mach-imx27ipcam.c
index 7381387..53a8601 100644
--- a/arch/arm/mach-imx/mach-imx27ipcam.c
+++ b/arch/arm/mach-imx/mach-imx27ipcam.c
@@ -17,11 +17,11 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx27.h>
 
+#include "hardware.h"
+#include "common.h"
 #include "devices-imx27.h"
+#include "iomux-mx27.h"
 
 static const int mx27ipcam_pins[] __initconst = {
 	/* UART1 */
diff --git a/arch/arm/mach-imx/mach-imx27lite.c b/arch/arm/mach-imx/mach-imx27lite.c
index 1f45b91..fc8dce9 100644
--- a/arch/arm/mach-imx/mach-imx27lite.c
+++ b/arch/arm/mach-imx/mach-imx27lite.c
@@ -20,11 +20,11 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx27.h>
 
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
 
 static const int mx27lite_pins[] __initconst = {
 	/* UART1 */
diff --git a/arch/arm/mach-imx/mach-imx53.c b/arch/arm/mach-imx/mach-imx53.c
index 29711e9..860284d 100644
--- a/arch/arm/mach-imx/mach-imx53.c
+++ b/arch/arm/mach-imx/mach-imx53.c
@@ -19,36 +19,9 @@
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
-#include <mach/common.h>
-#include <mach/mx53.h>
 
-/*
- * Lookup table for attaching a specific name and platform_data pointer to
- * devices as they get created by of_platform_populate().  Ideally this table
- * would not exist, but the current clock implementation depends on some devices
- * having a specific name.
- */
-static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
-	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART1_BASE_ADDR, "imx21-uart.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART2_BASE_ADDR, "imx21-uart.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART3_BASE_ADDR, "imx21-uart.2", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART4_BASE_ADDR, "imx21-uart.3", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART5_BASE_ADDR, "imx21-uart.4", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-fec", MX53_FEC_BASE_ADDR, "imx25-fec.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx53.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx53.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx53.2", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx53.3", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
-	{ /* sentinel */ }
-};
+#include "common.h"
+#include "mx53.h"
 
 static void __init imx53_qsb_init(void)
 {
@@ -68,8 +41,7 @@ static void __init imx53_dt_init(void)
 	if (of_machine_is_compatible("fsl,imx53-qsb"))
 		imx53_qsb_init();
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     imx53_auxdata_lookup, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static void __init imx53_timer_init(void)
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 47c91f7..4eb1b3a 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -33,10 +33,44 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/system_misc.h>
-#include <mach/common.h>
-#include <mach/cpuidle.h>
-#include <mach/hardware.h>
 
+#include "common.h"
+#include "cpuidle.h"
+#include "hardware.h"
+
+#define IMX6Q_ANALOG_DIGPROG	0x260
+
+static int imx6q_revision(void)
+{
+	struct device_node *np;
+	void __iomem *base;
+	static u32 rev;
+
+	if (!rev) {
+		np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
+		if (!np)
+			return IMX_CHIP_REVISION_UNKNOWN;
+		base = of_iomap(np, 0);
+		if (!base) {
+			of_node_put(np);
+			return IMX_CHIP_REVISION_UNKNOWN;
+		}
+		rev =  readl_relaxed(base + IMX6Q_ANALOG_DIGPROG);
+		iounmap(base);
+		of_node_put(np);
+	}
+
+	switch (rev & 0xff) {
+	case 0:
+		return IMX_CHIP_REVISION_1_0;
+	case 1:
+		return IMX_CHIP_REVISION_1_1;
+	case 2:
+		return IMX_CHIP_REVISION_1_2;
+	default:
+		return IMX_CHIP_REVISION_UNKNOWN;
+	}
+}
 
 void imx6q_restart(char mode, const char *cmd)
 {
@@ -117,6 +151,17 @@ static void __init imx6q_sabrelite_init(void)
 	imx6q_sabrelite_cko1_setup();
 }
 
+static void __init imx6q_1588_init(void)
+{
+	struct regmap *gpr;
+
+	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+	if (!IS_ERR(gpr))
+		regmap_update_bits(gpr, 0x4, 1 << 21, 1 << 21);
+	else
+		pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n");
+
+}
 static void __init imx6q_usb_init(void)
 {
 	struct regmap *anatop;
@@ -153,6 +198,7 @@ static void __init imx6q_init_machine(void)
 
 	imx6q_pm_init();
 	imx6q_usb_init();
+	imx6q_1588_init();
 }
 
 static struct cpuidle_driver imx6q_cpuidle_driver = {
@@ -192,6 +238,7 @@ static void __init imx6q_timer_init(void)
 {
 	mx6q_clocks_init();
 	twd_local_timer_of_register();
+	imx_print_silicon_rev("i.MX6Q", imx6q_revision());
 }
 
 static struct sys_timer imx6q_timer = {
diff --git a/arch/arm/mach-imx/mach-kzm_arm11_01.c b/arch/arm/mach-imx/mach-kzm_arm11_01.c
index 0330078..2e536ea5 100644
--- a/arch/arm/mach-imx/mach-kzm_arm11_01.c
+++ b/arch/arm/mach-imx/mach-kzm_arm11_01.c
@@ -36,11 +36,10 @@
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx3.h>
-
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
 
 #define KZM_ARM11_IO_ADDRESS(x) (IOMEM(					\
 	IMX_IO_P2V_MODULE(x, MX31_CS4) ?:				\
diff --git a/arch/arm/mach-imx/mach-mx1ads.c b/arch/arm/mach-imx/mach-mx1ads.c
index 667f359..06b4837 100644
--- a/arch/arm/mach-imx/mach-mx1ads.c
+++ b/arch/arm/mach-imx/mach-mx1ads.c
@@ -23,11 +23,10 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx1.h>
-
+#include "common.h"
 #include "devices-imx1.h"
+#include "hardware.h"
+#include "iomux-mx1.h"
 
 static const int mx1ads_pins[] __initconst = {
 	/* UART1 */
diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c
index ed22e3f..6adb313 100644
--- a/arch/arm/mach-imx/mach-mx21ads.c
+++ b/arch/arm/mach-imx/mach-mx21ads.c
@@ -18,15 +18,15 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/physmap.h>
 #include <linux/gpio.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
-#include <mach/iomux-mx21.h>
 
+#include "common.h"
 #include "devices-imx21.h"
+#include "hardware.h"
+#include "iomux-mx21.h"
 
 /*
  * Memory-mapped I/O on MX21ADS base board
diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c
index ce247fd..b1b03aa 100644
--- a/arch/arm/mach-imx/mach-mx25_3ds.c
+++ b/arch/arm/mach-imx/mach-mx25_3ds.c
@@ -31,17 +31,17 @@
 #include <linux/platform_device.h>
 #include <linux/usb/otg.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/memory.h>
 #include <asm/mach/map.h>
-#include <mach/common.h>
-#include <mach/mx25.h>
-#include <mach/iomux-mx25.h>
 
+#include "common.h"
 #include "devices-imx25.h"
+#include "hardware.h"
+#include "iomux-mx25.h"
+#include "mx25.h"
 
 #define MX25PDK_CAN_PWDN	IMX_GPIO_NR(4, 6)
 
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index 05996f3..d0e547f 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -36,13 +36,13 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx27.h>
-#include <mach/ulpi.h>
-#include <mach/3ds_debugboard.h>
 
+#include "3ds_debugboard.h"
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
+#include "ulpi.h"
 
 #define SD1_EN_GPIO		IMX_GPIO_NR(2, 25)
 #define OTG_PHY_RESET_GPIO	IMX_GPIO_NR(2, 23)
diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c
index 7dc59ba..3d036f5 100644
--- a/arch/arm/mach-imx/mach-mx27ads.c
+++ b/arch/arm/mach-imx/mach-mx27ads.c
@@ -21,15 +21,15 @@
 #include <linux/mtd/physmap.h>
 #include <linux/i2c.h>
 #include <linux/irq.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
-#include <mach/iomux-mx27.h>
 
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
 
 /*
  * Base address of PBC controller, CS4
diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c
index 8915f93..bc301be 100644
--- a/arch/arm/mach-imx/mach-mx31_3ds.c
+++ b/arch/arm/mach-imx/mach-mx31_3ds.c
@@ -30,19 +30,19 @@
 
 #include <media/soc_camera.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/memory.h>
 #include <asm/mach/map.h>
 #include <asm/memblock.h>
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
-#include <mach/3ds_debugboard.h>
-#include <mach/ulpi.h>
 
+#include "3ds_debugboard.h"
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
+#include "ulpi.h"
 
 static int mx31_3ds_pins[] = {
 	/* UART1 */
@@ -393,7 +393,7 @@ static struct regulator_init_data gpo_init = {
 };
 
 static struct regulator_consumer_supply vmmc2_consumers[] = {
-	REGULATOR_SUPPLY("vmmc", "mxc-mmc.0"),
+	REGULATOR_SUPPLY("vmmc", "imx31-mmc.0"),
 };
 
 static struct regulator_init_data vmmc2_init = {
diff --git a/arch/arm/mach-imx/mach-mx31ads.c b/arch/arm/mach-imx/mach-mx31ads.c
index e774b07..8b56f88 100644
--- a/arch/arm/mach-imx/mach-mx31ads.c
+++ b/arch/arm/mach-imx/mach-mx31ads.c
@@ -28,8 +28,6 @@
 #include <asm/mach/time.h>
 #include <asm/memory.h>
 #include <asm/mach/map.h>
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
 
 #ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
 #include <linux/mfd/wm8350/audio.h>
@@ -37,7 +35,10 @@
 #include <linux/mfd/wm8350/pmic.h>
 #endif
 
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
 
 /* Base address of PBC controller */
 #define PBC_BASE_ADDRESS	MX31_CS4_BASE_ADDR_VIRT
diff --git a/arch/arm/mach-imx/mach-mx31lilly.c b/arch/arm/mach-imx/mach-mx31lilly.c
index 34b9bf0..08b9965 100644
--- a/arch/arm/mach-imx/mach-mx31lilly.c
+++ b/arch/arm/mach-imx/mach-mx31lilly.c
@@ -42,13 +42,12 @@
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
-#include <mach/board-mx31lilly.h>
-#include <mach/ulpi.h>
-
+#include "board-mx31lilly.h"
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
+#include "ulpi.h"
 
 /*
  * This file contains module-specific initialization routines for LILLY-1131.
diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c
index ef57cff..bdcd92e 100644
--- a/arch/arm/mach-imx/mach-mx31lite.c
+++ b/arch/arm/mach-imx/mach-mx31lite.c
@@ -39,13 +39,12 @@
 #include <asm/page.h>
 #include <asm/setup.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/board-mx31lite.h>
-#include <mach/iomux-mx3.h>
-#include <mach/ulpi.h>
-
+#include "board-mx31lite.h"
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
+#include "ulpi.h"
 
 /*
  * This file contains the module-specific initialization routines.
diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c
index 459e754..2517cfa 100644
--- a/arch/arm/mach-imx/mach-mx31moboard.c
+++ b/arch/arm/mach-imx/mach-mx31moboard.c
@@ -42,14 +42,14 @@
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 #include <asm/memblock.h>
-#include <mach/board-mx31moboard.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx3.h>
-#include <mach/ulpi.h>
 #include <linux/platform_data/asoc-imx-ssi.h>
 
+#include "board-mx31moboard.h"
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
+#include "ulpi.h"
 
 static unsigned int moboard_pins[] = {
 	/* UART0 */
@@ -175,11 +175,11 @@ static const struct spi_imx_master moboard_spi1_pdata __initconst = {
 
 static struct regulator_consumer_supply sdhc_consumers[] = {
 	{
-		.dev_name = "mxc-mmc.0",
+		.dev_name = "imx31-mmc.0",
 		.supply	= "sdhc0_vcc",
 	},
 	{
-		.dev_name = "mxc-mmc.1",
+		.dev_name = "imx31-mmc.1",
 		.supply	= "sdhc1_vcc",
 	},
 };
diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c
index 504983c..5277da4 100644
--- a/arch/arm/mach-imx/mach-mx35_3ds.c
+++ b/arch/arm/mach-imx/mach-mx35_3ds.c
@@ -43,15 +43,15 @@
 #include <asm/mach/map.h>
 #include <asm/memblock.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx35.h>
-#include <mach/3ds_debugboard.h>
 #include <video/platform_lcd.h>
 
 #include <media/soc_camera.h>
 
+#include "3ds_debugboard.h"
+#include "common.h"
 #include "devices-imx35.h"
+#include "hardware.h"
+#include "iomux-mx35.h"
 
 #define GPIO_MC9S08DZ60_GPS_ENABLE 0
 #define GPIO_MC9S08DZ60_HDD_ENABLE 4
diff --git a/arch/arm/mach-imx/mach-mx50_rdp.c b/arch/arm/mach-imx/mach-mx50_rdp.c
index 42b66e8..0c1f88a 100644
--- a/arch/arm/mach-imx/mach-mx50_rdp.c
+++ b/arch/arm/mach-imx/mach-mx50_rdp.c
@@ -24,17 +24,16 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx50.h>
-
 #include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
+#include "common.h"
 #include "devices-imx50.h"
+#include "hardware.h"
+#include "iomux-mx50.h"
 
 #define FEC_EN		IMX_GPIO_NR(6, 23)
 #define FEC_RESET_B	IMX_GPIO_NR(4, 12)
diff --git a/arch/arm/mach-imx/mach-mx51_3ds.c b/arch/arm/mach-imx/mach-mx51_3ds.c
index 9ee84a4..abc25bd 100644
--- a/arch/arm/mach-imx/mach-mx51_3ds.c
+++ b/arch/arm/mach-imx/mach-mx51_3ds.c
@@ -19,12 +19,11 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx51.h>
-#include <mach/3ds_debugboard.h>
-
+#include "3ds_debugboard.h"
+#include "common.h"
 #include "devices-imx51.h"
+#include "hardware.h"
+#include "iomux-mx51.h"
 
 #define MX51_3DS_ECSPI2_CS	(GPIO_PORTC + 28)
 
diff --git a/arch/arm/mach-imx/mach-mx51_babbage.c b/arch/arm/mach-imx/mach-mx51_babbage.c
index 7b31cbd..d9a84ca 100644
--- a/arch/arm/mach-imx/mach-mx51_babbage.c
+++ b/arch/arm/mach-imx/mach-mx51_babbage.c
@@ -20,17 +20,16 @@
 #include <linux/spi/flash.h>
 #include <linux/spi/spi.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
+#include "common.h"
 #include "devices-imx51.h"
 #include "cpu_op-mx51.h"
+#include "hardware.h"
+#include "iomux-mx51.h"
 
 #define BABBAGE_USB_HUB_RESET	IMX_GPIO_NR(1, 7)
 #define BABBAGE_USBH1_STP	IMX_GPIO_NR(1, 27)
diff --git a/arch/arm/mach-imx/mach-mxt_td60.c b/arch/arm/mach-imx/mach-mxt_td60.c
index 0bf6d30..f4a8c7e 100644
--- a/arch/arm/mach-imx/mach-mxt_td60.c
+++ b/arch/arm/mach-imx/mach-mxt_td60.c
@@ -21,17 +21,17 @@
 #include <linux/mtd/physmap.h>
 #include <linux/i2c.h>
 #include <linux/irq.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 #include <linux/gpio.h>
-#include <mach/iomux-mx27.h>
 #include <linux/i2c/pca953x.h>
 
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
 
 static const int mxt_td60_pins[] __initconst = {
 	/* UART0 */
diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c
index de8516b..eee369f 100644
--- a/arch/arm/mach-imx/mach-pca100.c
+++ b/arch/arm/mach-imx/mach-pca100.c
@@ -32,13 +32,13 @@
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx27.h>
 #include <asm/mach/time.h>
-#include <mach/ulpi.h>
 
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
+#include "ulpi.h"
 
 #define OTG_PHY_CS_GPIO (GPIO_PORTB + 23)
 #define USBH2_PHY_CS_GPIO (GPIO_PORTB + 24)
diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c
index e3c4513..547fef1 100644
--- a/arch/arm/mach-imx/mach-pcm037.c
+++ b/arch/arm/mach-imx/mach-pcm037.c
@@ -42,13 +42,13 @@
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 #include <asm/memblock.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx3.h>
-#include <mach/ulpi.h>
 
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
 #include "pcm037.h"
+#include "ulpi.h"
 
 static enum pcm037_board_variant pcm037_instance = PCM037_PCM970;
 
diff --git a/arch/arm/mach-imx/mach-pcm037_eet.c b/arch/arm/mach-imx/mach-pcm037_eet.c
index 11ffa81..8fd8255 100644
--- a/arch/arm/mach-imx/mach-pcm037_eet.c
+++ b/arch/arm/mach-imx/mach-pcm037_eet.c
@@ -11,13 +11,12 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
-
 #include <asm/mach-types.h>
 
 #include "pcm037.h"
+#include "common.h"
 #include "devices-imx31.h"
+#include "iomux-mx3.h"
 
 static unsigned int pcm037_eet_pins[] = {
 	/* Reserve and hardwire GPIO 57 high - S6E63D6 chipselect */
diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c
index 95f49d9..4aa0d07 100644
--- a/arch/arm/mach-imx/mach-pcm038.c
+++ b/arch/arm/mach-imx/mach-pcm038.c
@@ -33,13 +33,12 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-#include <mach/board-pcm038.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx27.h>
-#include <mach/ulpi.h>
-
+#include "board-pcm038.h"
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
+#include "ulpi.h"
 
 static const int pcm038_pins[] __initconst = {
 	/* UART1 */
@@ -212,7 +211,7 @@ static const struct spi_imx_master pcm038_spi0_data __initconst = {
 
 static struct regulator_consumer_supply sdhc1_consumers[] = {
 	{
-		.dev_name = "mxc-mmc.1",
+		.dev_name = "imx21-mmc.1",
 		.supply	= "sdhc_vcc",
 	},
 };
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index e4bd438..9244544 100644
--- a/arch/arm/mach-imx/mach-pcm043.c
+++ b/arch/arm/mach-imx/mach-pcm043.c
@@ -33,12 +33,11 @@
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx35.h>
-#include <mach/ulpi.h>
-
+#include "common.h"
 #include "devices-imx35.h"
+#include "hardware.h"
+#include "iomux-mx35.h"
+#include "ulpi.h"
 
 static const struct fb_videomode fb_modedb[] = {
 	{
diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c
index fb25fbd..96d9a91 100644
--- a/arch/arm/mach-imx/mach-qong.c
+++ b/arch/arm/mach-imx/mach-qong.c
@@ -21,17 +21,17 @@
 #include <linux/mtd/nand.h>
 #include <linux/gpio.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
-#include <mach/common.h>
 #include <asm/page.h>
 #include <asm/setup.h>
-#include <mach/iomux-mx3.h>
 
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
 
 /* FPGA defines */
 #define QONG_FPGA_VERSION(major, minor, rev)	\
diff --git a/arch/arm/mach-imx/mach-scb9328.c b/arch/arm/mach-imx/mach-scb9328.c
index 67ff38e..fc97040 100644
--- a/arch/arm/mach-imx/mach-scb9328.c
+++ b/arch/arm/mach-imx/mach-scb9328.c
@@ -20,11 +20,10 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx1.h>
-
+#include "common.h"
 #include "devices-imx1.h"
+#include "hardware.h"
+#include "iomux-mx1.h"
 
 /*
  * This scb9328 has a 32MiB flash
diff --git a/arch/arm/mach-imx/mach-vpr200.c b/arch/arm/mach-imx/mach-vpr200.c
index 39eb796..3aecf91 100644
--- a/arch/arm/mach-imx/mach-vpr200.c
+++ b/arch/arm/mach-imx/mach-vpr200.c
@@ -28,15 +28,14 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx35.h>
-
 #include <linux/i2c.h>
 #include <linux/i2c/at24.h>
 #include <linux/mfd/mc13xxx.h>
 
+#include "common.h"
 #include "devices-imx35.h"
+#include "hardware.h"
+#include "iomux-mx35.h"
 
 #define GPIO_LCDPWR	IMX_GPIO_NR(1, 2)
 #define GPIO_PMIC_INT	IMX_GPIO_NR(2, 0)
diff --git a/arch/arm/mach-imx/mm-imx1.c b/arch/arm/mach-imx/mm-imx1.c
index 6d60d51..7a14667 100644
--- a/arch/arm/mach-imx/mm-imx1.c
+++ b/arch/arm/mach-imx/mm-imx1.c
@@ -22,9 +22,10 @@
 
 #include <asm/mach/map.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-v1.h>
+#include "common.h"
+#include "devices/devices-common.h"
+#include "hardware.h"
+#include "iomux-v1.h"
 
 static struct map_desc imx_io_desc[] __initdata = {
 	imx_map_entry(MX1, IO, MT_DEVICE),
@@ -58,5 +59,7 @@ void __init imx1_soc_init(void)
 						MX1_GPIO_INT_PORTC, 0);
 	mxc_register_gpio("imx1-gpio", 3, MX1_GPIO4_BASE_ADDR, SZ_256,
 						MX1_GPIO_INT_PORTD, 0);
+	imx_add_imx_dma("imx1-dma", MX1_DMA_BASE_ADDR,
+			MX1_DMA_INT, MX1_DMA_ERR);
 	pinctrl_provide_dummies();
 }
diff --git a/arch/arm/mach-imx/mm-imx21.c b/arch/arm/mach-imx/mm-imx21.c
index d056dad..d8ccd3a 100644
--- a/arch/arm/mach-imx/mm-imx21.c
+++ b/arch/arm/mach-imx/mm-imx21.c
@@ -21,12 +21,13 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/pinctrl/machine.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/devices-common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
-#include <mach/iomux-v1.h>
+
+#include "common.h"
+#include "devices/devices-common.h"
+#include "hardware.h"
+#include "iomux-v1.h"
 
 /* MX21 memory map definition */
 static struct map_desc imx21_io_desc[] __initdata = {
@@ -81,6 +82,8 @@ static const struct resource imx21_audmux_res[] __initconst = {
 
 void __init imx21_soc_init(void)
 {
+	mxc_device_init();
+
 	mxc_register_gpio("imx21-gpio", 0, MX21_GPIO1_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
 	mxc_register_gpio("imx21-gpio", 1, MX21_GPIO2_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
 	mxc_register_gpio("imx21-gpio", 2, MX21_GPIO3_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
@@ -89,7 +92,8 @@ void __init imx21_soc_init(void)
 	mxc_register_gpio("imx21-gpio", 5, MX21_GPIO6_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
 
 	pinctrl_provide_dummies();
-	imx_add_imx_dma();
+	imx_add_imx_dma("imx21-dma", MX21_DMA_BASE_ADDR,
+			MX21_INT_DMACH0, 0); /* No ERR irq */
 	platform_device_register_simple("imx21-audmux", 0, imx21_audmux_res,
 					ARRAY_SIZE(imx21_audmux_res));
 }
diff --git a/arch/arm/mach-imx/mm-imx25.c b/arch/arm/mach-imx/mm-imx25.c
index f3f5c65..9357707 100644
--- a/arch/arm/mach-imx/mm-imx25.c
+++ b/arch/arm/mach-imx/mm-imx25.c
@@ -24,11 +24,11 @@
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
 
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/hardware.h>
-#include <mach/mx25.h>
-#include <mach/iomux-v3.h>
+#include "common.h"
+#include "devices/devices-common.h"
+#include "hardware.h"
+#include "iomux-v3.h"
+#include "mx25.h"
 
 /*
  * This table defines static virtual address mappings for I/O regions.
@@ -89,6 +89,8 @@ static const struct resource imx25_audmux_res[] __initconst = {
 
 void __init imx25_soc_init(void)
 {
+	mxc_device_init();
+
 	/* i.mx25 has the i.mx35 type gpio */
 	mxc_register_gpio("imx35-gpio", 0, MX25_GPIO1_BASE_ADDR, SZ_16K, MX25_INT_GPIO1, 0);
 	mxc_register_gpio("imx35-gpio", 1, MX25_GPIO2_BASE_ADDR, SZ_16K, MX25_INT_GPIO2, 0);
diff --git a/arch/arm/mach-imx/mm-imx27.c b/arch/arm/mach-imx/mm-imx27.c
index e7e24af..4f1be65 100644
--- a/arch/arm/mach-imx/mm-imx27.c
+++ b/arch/arm/mach-imx/mm-imx27.c
@@ -21,12 +21,13 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/pinctrl/machine.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/devices-common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
-#include <mach/iomux-v1.h>
+
+#include "common.h"
+#include "devices/devices-common.h"
+#include "hardware.h"
+#include "iomux-v1.h"
 
 /* MX27 memory map definition */
 static struct map_desc imx27_io_desc[] __initdata = {
@@ -81,6 +82,8 @@ static const struct resource imx27_audmux_res[] __initconst = {
 
 void __init imx27_soc_init(void)
 {
+	mxc_device_init();
+
 	/* i.mx27 has the i.mx21 type gpio */
 	mxc_register_gpio("imx21-gpio", 0, MX27_GPIO1_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
 	mxc_register_gpio("imx21-gpio", 1, MX27_GPIO2_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
@@ -90,7 +93,8 @@ void __init imx27_soc_init(void)
 	mxc_register_gpio("imx21-gpio", 5, MX27_GPIO6_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
 
 	pinctrl_provide_dummies();
-	imx_add_imx_dma();
+	imx_add_imx_dma("imx27-dma", MX27_DMA_BASE_ADDR,
+			MX27_INT_DMACH0, 0); /* No ERR irq */
 	/* imx27 has the imx21 type audmux */
 	platform_device_register_simple("imx21-audmux", 0, imx27_audmux_res,
 					ARRAY_SIZE(imx27_audmux_res));
diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c
index b5deb05..cefa047 100644
--- a/arch/arm/mach-imx/mm-imx3.c
+++ b/arch/arm/mach-imx/mm-imx3.c
@@ -26,12 +26,11 @@
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/map.h>
 
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-v3.h>
-
+#include "common.h"
 #include "crmregs-imx3.h"
+#include "devices/devices-common.h"
+#include "hardware.h"
+#include "iomux-v3.h"
 
 void __iomem *mx3_ccm_base;
 
@@ -175,6 +174,8 @@ void __init imx31_soc_init(void)
 
 	imx3_init_l2x0();
 
+	mxc_device_init();
+
 	mxc_register_gpio("imx31-gpio", 0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0);
 	mxc_register_gpio("imx31-gpio", 1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0);
 	mxc_register_gpio("imx31-gpio", 2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0);
@@ -271,6 +272,8 @@ void __init imx35_soc_init(void)
 
 	imx3_init_l2x0();
 
+	mxc_device_init();
+
 	mxc_register_gpio("imx35-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
 	mxc_register_gpio("imx35-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
 	mxc_register_gpio("imx35-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c
index acb0aad..79d71cf 100644
--- a/arch/arm/mach-imx/mm-imx5.c
+++ b/arch/arm/mach-imx/mm-imx5.c
@@ -18,10 +18,10 @@
 
 #include <asm/mach/map.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/iomux-v3.h>
+#include "common.h"
+#include "devices/devices-common.h"
+#include "hardware.h"
+#include "iomux-v3.h"
 
 /*
  * Define the MX50 memory map.
@@ -81,8 +81,28 @@ void __init imx50_init_early(void)
 	mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
 }
 
+/*
+ * The MIPI HSC unit has been removed from the i.MX51 Reference Manual by
+ * the Freescale marketing division. However this did not remove the
+ * hardware from the chip which still needs to be configured for proper
+ * IPU support.
+ */
+static void __init imx51_ipu_mipi_setup(void)
+{
+	void __iomem *hsc_addr;
+	hsc_addr = MX51_IO_ADDRESS(MX51_MIPI_HSC_BASE_ADDR);
+
+	/* setup MIPI module to legacy mode */
+	__raw_writel(0xf00, hsc_addr);
+
+	/* CSI mode: reserved; DI control mode: legacy (from Freescale BSP) */
+	__raw_writel(__raw_readl(hsc_addr + 0x800) | 0x30ff,
+		hsc_addr + 0x800);
+}
+
 void __init imx51_init_early(void)
 {
+	imx51_ipu_mipi_setup();
 	mxc_set_cpu_type(MXC_CPU_MX51);
 	mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
 	mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
@@ -138,6 +158,8 @@ static const struct resource imx51_audmux_res[] __initconst = {
 
 void __init imx50_soc_init(void)
 {
+	mxc_device_init();
+
 	/* i.mx50 has the i.mx35 type gpio */
 	mxc_register_gpio("imx35-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
 	mxc_register_gpio("imx35-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
@@ -153,6 +175,8 @@ void __init imx50_soc_init(void)
 
 void __init imx51_soc_init(void)
 {
+	mxc_device_init();
+
 	/* i.mx51 has the i.mx35 type gpio */
 	mxc_register_gpio("imx35-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH);
 	mxc_register_gpio("imx35-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH);
diff --git a/arch/arm/mach-imx/mx1.h b/arch/arm/mach-imx/mx1.h
new file mode 100644
index 0000000..45bd31c
--- /dev/null
+++ b/arch/arm/mach-imx/mx1.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 1997,1998 Russell King
+ * Copyright (C) 1999 ARM Limited
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (c) 2008 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __MACH_MX1_H__
+#define __MACH_MX1_H__
+
+/*
+ * Memory map
+ */
+#define MX1_IO_BASE_ADDR	0x00200000
+#define MX1_IO_SIZE		SZ_1M
+
+#define MX1_CS0_PHYS		0x10000000
+#define MX1_CS0_SIZE		0x02000000
+
+#define MX1_CS1_PHYS		0x12000000
+#define MX1_CS1_SIZE		0x01000000
+
+#define MX1_CS2_PHYS		0x13000000
+#define MX1_CS2_SIZE		0x01000000
+
+#define MX1_CS3_PHYS		0x14000000
+#define MX1_CS3_SIZE		0x01000000
+
+#define MX1_CS4_PHYS		0x15000000
+#define MX1_CS4_SIZE		0x01000000
+
+#define MX1_CS5_PHYS		0x16000000
+#define MX1_CS5_SIZE		0x01000000
+
+/*
+ *  Register BASEs, based on OFFSETs
+ */
+#define MX1_AIPI1_BASE_ADDR		(0x00000 + MX1_IO_BASE_ADDR)
+#define MX1_WDT_BASE_ADDR		(0x01000 + MX1_IO_BASE_ADDR)
+#define MX1_TIM1_BASE_ADDR		(0x02000 + MX1_IO_BASE_ADDR)
+#define MX1_TIM2_BASE_ADDR		(0x03000 + MX1_IO_BASE_ADDR)
+#define MX1_RTC_BASE_ADDR		(0x04000 + MX1_IO_BASE_ADDR)
+#define MX1_LCDC_BASE_ADDR		(0x05000 + MX1_IO_BASE_ADDR)
+#define MX1_UART1_BASE_ADDR		(0x06000 + MX1_IO_BASE_ADDR)
+#define MX1_UART2_BASE_ADDR		(0x07000 + MX1_IO_BASE_ADDR)
+#define MX1_PWM_BASE_ADDR		(0x08000 + MX1_IO_BASE_ADDR)
+#define MX1_DMA_BASE_ADDR		(0x09000 + MX1_IO_BASE_ADDR)
+#define MX1_AIPI2_BASE_ADDR		(0x10000 + MX1_IO_BASE_ADDR)
+#define MX1_SIM_BASE_ADDR		(0x11000 + MX1_IO_BASE_ADDR)
+#define MX1_USBD_BASE_ADDR		(0x12000 + MX1_IO_BASE_ADDR)
+#define MX1_CSPI1_BASE_ADDR		(0x13000 + MX1_IO_BASE_ADDR)
+#define MX1_MMC_BASE_ADDR		(0x14000 + MX1_IO_BASE_ADDR)
+#define MX1_ASP_BASE_ADDR		(0x15000 + MX1_IO_BASE_ADDR)
+#define MX1_BTA_BASE_ADDR		(0x16000 + MX1_IO_BASE_ADDR)
+#define MX1_I2C_BASE_ADDR		(0x17000 + MX1_IO_BASE_ADDR)
+#define MX1_SSI_BASE_ADDR		(0x18000 + MX1_IO_BASE_ADDR)
+#define MX1_CSPI2_BASE_ADDR		(0x19000 + MX1_IO_BASE_ADDR)
+#define MX1_MSHC_BASE_ADDR		(0x1A000 + MX1_IO_BASE_ADDR)
+#define MX1_CCM_BASE_ADDR		(0x1B000 + MX1_IO_BASE_ADDR)
+#define MX1_SCM_BASE_ADDR		(0x1B804 + MX1_IO_BASE_ADDR)
+#define MX1_GPIO_BASE_ADDR		(0x1C000 + MX1_IO_BASE_ADDR)
+#define MX1_GPIO1_BASE_ADDR		(0x1C000 + MX1_IO_BASE_ADDR)
+#define MX1_GPIO2_BASE_ADDR		(0x1C100 + MX1_IO_BASE_ADDR)
+#define MX1_GPIO3_BASE_ADDR		(0x1C200 + MX1_IO_BASE_ADDR)
+#define MX1_GPIO4_BASE_ADDR		(0x1C300 + MX1_IO_BASE_ADDR)
+#define MX1_EIM_BASE_ADDR		(0x20000 + MX1_IO_BASE_ADDR)
+#define MX1_SDRAMC_BASE_ADDR		(0x21000 + MX1_IO_BASE_ADDR)
+#define MX1_MMA_BASE_ADDR		(0x22000 + MX1_IO_BASE_ADDR)
+#define MX1_AVIC_BASE_ADDR		(0x23000 + MX1_IO_BASE_ADDR)
+#define MX1_CSI_BASE_ADDR		(0x24000 + MX1_IO_BASE_ADDR)
+
+/* macro to get at IO space when running virtually */
+#define MX1_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX1_IO_ADDRESS(x)		IOMEM(MX1_IO_P2V(x))
+
+/* fixed interrput numbers */
+#include <asm/irq.h>
+#define MX1_INT_SOFTINT		(NR_IRQS_LEGACY + 0)
+#define MX1_INT_CSI		(NR_IRQS_LEGACY + 6)
+#define MX1_DSPA_MAC_INT	(NR_IRQS_LEGACY + 7)
+#define MX1_DSPA_INT		(NR_IRQS_LEGACY + 8)
+#define MX1_COMP_INT		(NR_IRQS_LEGACY + 9)
+#define MX1_MSHC_XINT		(NR_IRQS_LEGACY + 10)
+#define MX1_GPIO_INT_PORTA	(NR_IRQS_LEGACY + 11)
+#define MX1_GPIO_INT_PORTB	(NR_IRQS_LEGACY + 12)
+#define MX1_GPIO_INT_PORTC	(NR_IRQS_LEGACY + 13)
+#define MX1_INT_LCDC		(NR_IRQS_LEGACY + 14)
+#define MX1_SIM_INT		(NR_IRQS_LEGACY + 15)
+#define MX1_SIM_DATA_INT	(NR_IRQS_LEGACY + 16)
+#define MX1_RTC_INT		(NR_IRQS_LEGACY + 17)
+#define MX1_RTC_SAMINT		(NR_IRQS_LEGACY + 18)
+#define MX1_INT_UART2PFERR	(NR_IRQS_LEGACY + 19)
+#define MX1_INT_UART2RTS	(NR_IRQS_LEGACY + 20)
+#define MX1_INT_UART2DTR	(NR_IRQS_LEGACY + 21)
+#define MX1_INT_UART2UARTC	(NR_IRQS_LEGACY + 22)
+#define MX1_INT_UART2TX		(NR_IRQS_LEGACY + 23)
+#define MX1_INT_UART2RX		(NR_IRQS_LEGACY + 24)
+#define MX1_INT_UART1PFERR	(NR_IRQS_LEGACY + 25)
+#define MX1_INT_UART1RTS	(NR_IRQS_LEGACY + 26)
+#define MX1_INT_UART1DTR	(NR_IRQS_LEGACY + 27)
+#define MX1_INT_UART1UARTC	(NR_IRQS_LEGACY + 28)
+#define MX1_INT_UART1TX		(NR_IRQS_LEGACY + 29)
+#define MX1_INT_UART1RX		(NR_IRQS_LEGACY + 30)
+#define MX1_VOICE_DAC_INT	(NR_IRQS_LEGACY + 31)
+#define MX1_VOICE_ADC_INT	(NR_IRQS_LEGACY + 32)
+#define MX1_PEN_DATA_INT	(NR_IRQS_LEGACY + 33)
+#define MX1_PWM_INT		(NR_IRQS_LEGACY + 34)
+#define MX1_SDHC_INT		(NR_IRQS_LEGACY + 35)
+#define MX1_INT_I2C		(NR_IRQS_LEGACY + 39)
+#define MX1_INT_CSPI2		(NR_IRQS_LEGACY + 40)
+#define MX1_INT_CSPI1		(NR_IRQS_LEGACY + 41)
+#define MX1_SSI_TX_INT		(NR_IRQS_LEGACY + 42)
+#define MX1_SSI_TX_ERR_INT	(NR_IRQS_LEGACY + 43)
+#define MX1_SSI_RX_INT		(NR_IRQS_LEGACY + 44)
+#define MX1_SSI_RX_ERR_INT	(NR_IRQS_LEGACY + 45)
+#define MX1_TOUCH_INT		(NR_IRQS_LEGACY + 46)
+#define MX1_INT_USBD0		(NR_IRQS_LEGACY + 47)
+#define MX1_INT_USBD1		(NR_IRQS_LEGACY + 48)
+#define MX1_INT_USBD2		(NR_IRQS_LEGACY + 49)
+#define MX1_INT_USBD3		(NR_IRQS_LEGACY + 50)
+#define MX1_INT_USBD4		(NR_IRQS_LEGACY + 51)
+#define MX1_INT_USBD5		(NR_IRQS_LEGACY + 52)
+#define MX1_INT_USBD6		(NR_IRQS_LEGACY + 53)
+#define MX1_BTSYS_INT		(NR_IRQS_LEGACY + 55)
+#define MX1_BTTIM_INT		(NR_IRQS_LEGACY + 56)
+#define MX1_BTWUI_INT		(NR_IRQS_LEGACY + 57)
+#define MX1_TIM2_INT		(NR_IRQS_LEGACY + 58)
+#define MX1_TIM1_INT		(NR_IRQS_LEGACY + 59)
+#define MX1_DMA_ERR		(NR_IRQS_LEGACY + 60)
+#define MX1_DMA_INT		(NR_IRQS_LEGACY + 61)
+#define MX1_GPIO_INT_PORTD	(NR_IRQS_LEGACY + 62)
+#define MX1_WDT_INT		(NR_IRQS_LEGACY + 63)
+
+/* DMA */
+#define MX1_DMA_REQ_UART3_T		2
+#define MX1_DMA_REQ_UART3_R		3
+#define MX1_DMA_REQ_SSI2_T		4
+#define MX1_DMA_REQ_SSI2_R		5
+#define MX1_DMA_REQ_CSI_STAT		6
+#define MX1_DMA_REQ_CSI_R		7
+#define MX1_DMA_REQ_MSHC		8
+#define MX1_DMA_REQ_DSPA_DCT_DOUT	9
+#define MX1_DMA_REQ_DSPA_DCT_DIN	10
+#define MX1_DMA_REQ_DSPA_MAC		11
+#define MX1_DMA_REQ_EXT			12
+#define MX1_DMA_REQ_SDHC		13
+#define MX1_DMA_REQ_SPI1_R		14
+#define MX1_DMA_REQ_SPI1_T		15
+#define MX1_DMA_REQ_SSI_T		16
+#define MX1_DMA_REQ_SSI_R		17
+#define MX1_DMA_REQ_ASP_DAC		18
+#define MX1_DMA_REQ_ASP_ADC		19
+#define MX1_DMA_REQ_USP_EP(x)		(20 + (x))
+#define MX1_DMA_REQ_SPI2_R		26
+#define MX1_DMA_REQ_SPI2_T		27
+#define MX1_DMA_REQ_UART2_T		28
+#define MX1_DMA_REQ_UART2_R		29
+#define MX1_DMA_REQ_UART1_T		30
+#define MX1_DMA_REQ_UART1_R		31
+
+/*
+ * This doesn't depend on IMX_NEEDS_DEPRECATED_SYMBOLS
+ * to not break drivers/usb/gadget/imx_udc.  Should go
+ * away after this driver uses the new name.
+ */
+#define USBD_INT0		MX1_INT_USBD0
+
+#endif /* ifndef __MACH_MX1_H__ */
diff --git a/arch/arm/mach-imx/mx21.h b/arch/arm/mach-imx/mx21.h
new file mode 100644
index 0000000..468738a
--- /dev/null
+++ b/arch/arm/mach-imx/mx21.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ * Copyright 2009 Holger Schurig, hs4233@mail.mn-solutions.de
+ *
+ * This contains i.MX21-specific hardware definitions. For those
+ * hardware pieces that are common between i.MX21 and i.MX27, have a
+ * look at mx2x.h.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ */
+
+#ifndef __MACH_MX21_H__
+#define __MACH_MX21_H__
+
+#define MX21_AIPI_BASE_ADDR		0x10000000
+#define MX21_AIPI_SIZE			SZ_1M
+#define MX21_DMA_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x01000)
+#define MX21_WDOG_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x02000)
+#define MX21_GPT1_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x03000)
+#define MX21_GPT2_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x04000)
+#define MX21_GPT3_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x05000)
+#define MX21_PWM_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x06000)
+#define MX21_RTC_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x07000)
+#define MX21_KPP_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x08000)
+#define MX21_OWIRE_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x09000)
+#define MX21_UART1_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x0a000)
+#define MX21_UART2_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x0b000)
+#define MX21_UART3_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x0c000)
+#define MX21_UART4_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x0d000)
+#define MX21_CSPI1_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x0e000)
+#define MX21_CSPI2_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x0f000)
+#define MX21_SSI1_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x10000)
+#define MX21_SSI2_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x11000)
+#define MX21_I2C_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x12000)
+#define MX21_SDHC1_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x13000)
+#define MX21_SDHC2_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x14000)
+#define MX21_GPIO_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x15000)
+#define MX21_GPIO1_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x000)
+#define MX21_GPIO2_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x100)
+#define MX21_GPIO3_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x200)
+#define MX21_GPIO4_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x300)
+#define MX21_GPIO5_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x400)
+#define MX21_GPIO6_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x500)
+#define MX21_AUDMUX_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x16000)
+#define MX21_CSPI3_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x17000)
+#define MX21_LCDC_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x21000)
+#define MX21_SLCDC_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x22000)
+#define MX21_USBOTG_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x24000)
+#define MX21_EMMA_PP_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x26000)
+#define MX21_EMMA_PRP_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x26400)
+#define MX21_CCM_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x27000)
+#define MX21_SYSCTRL_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x27800)
+#define MX21_JAM_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x3e000)
+#define MX21_MAX_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x3f000)
+
+#define MX21_AVIC_BASE_ADDR		0x10040000
+
+#define MX21_SAHB1_BASE_ADDR		0x80000000
+#define MX21_SAHB1_SIZE			SZ_1M
+#define MX21_CSI_BASE_ADDR			(MX2x_SAHB1_BASE_ADDR + 0x0000)
+
+/* Memory regions and CS */
+#define MX21_SDRAM_BASE_ADDR		0xc0000000
+#define MX21_CSD1_BASE_ADDR		0xc4000000
+
+#define MX21_CS0_BASE_ADDR		0xc8000000
+#define MX21_CS1_BASE_ADDR		0xcc000000
+#define MX21_CS2_BASE_ADDR		0xd0000000
+#define MX21_CS3_BASE_ADDR		0xd1000000
+#define MX21_CS4_BASE_ADDR		0xd2000000
+#define MX21_PCMCIA_MEM_BASE_ADDR	0xd4000000
+#define MX21_CS5_BASE_ADDR		0xdd000000
+
+/* NAND, SDRAM, WEIM etc controllers */
+#define MX21_X_MEMC_BASE_ADDR		0xdf000000
+#define MX21_X_MEMC_SIZE		SZ_256K
+
+#define MX21_SDRAMC_BASE_ADDR		(MX21_X_MEMC_BASE_ADDR + 0x0000)
+#define MX21_EIM_BASE_ADDR		(MX21_X_MEMC_BASE_ADDR + 0x1000)
+#define MX21_PCMCIA_CTL_BASE_ADDR	(MX21_X_MEMC_BASE_ADDR + 0x2000)
+#define MX21_NFC_BASE_ADDR		(MX21_X_MEMC_BASE_ADDR + 0x3000)
+
+#define MX21_IRAM_BASE_ADDR		0xffffe800	/* internal ram */
+
+#define MX21_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX21_IO_ADDRESS(x)		IOMEM(MX21_IO_P2V(x))
+
+/* fixed interrupt numbers */
+#include <asm/irq.h>
+#define MX21_INT_CSPI3		(NR_IRQS_LEGACY + 6)
+#define MX21_INT_GPIO		(NR_IRQS_LEGACY + 8)
+#define MX21_INT_FIRI		(NR_IRQS_LEGACY + 9)
+#define MX21_INT_SDHC2		(NR_IRQS_LEGACY + 10)
+#define MX21_INT_SDHC1		(NR_IRQS_LEGACY + 11)
+#define MX21_INT_I2C		(NR_IRQS_LEGACY + 12)
+#define MX21_INT_SSI2		(NR_IRQS_LEGACY + 13)
+#define MX21_INT_SSI1		(NR_IRQS_LEGACY + 14)
+#define MX21_INT_CSPI2		(NR_IRQS_LEGACY + 15)
+#define MX21_INT_CSPI1		(NR_IRQS_LEGACY + 16)
+#define MX21_INT_UART4		(NR_IRQS_LEGACY + 17)
+#define MX21_INT_UART3		(NR_IRQS_LEGACY + 18)
+#define MX21_INT_UART2		(NR_IRQS_LEGACY + 19)
+#define MX21_INT_UART1		(NR_IRQS_LEGACY + 20)
+#define MX21_INT_KPP		(NR_IRQS_LEGACY + 21)
+#define MX21_INT_RTC		(NR_IRQS_LEGACY + 22)
+#define MX21_INT_PWM		(NR_IRQS_LEGACY + 23)
+#define MX21_INT_GPT3		(NR_IRQS_LEGACY + 24)
+#define MX21_INT_GPT2		(NR_IRQS_LEGACY + 25)
+#define MX21_INT_GPT1		(NR_IRQS_LEGACY + 26)
+#define MX21_INT_WDOG		(NR_IRQS_LEGACY + 27)
+#define MX21_INT_PCMCIA		(NR_IRQS_LEGACY + 28)
+#define MX21_INT_NFC		(NR_IRQS_LEGACY + 29)
+#define MX21_INT_BMI		(NR_IRQS_LEGACY + 30)
+#define MX21_INT_CSI		(NR_IRQS_LEGACY + 31)
+#define MX21_INT_DMACH0		(NR_IRQS_LEGACY + 32)
+#define MX21_INT_DMACH1		(NR_IRQS_LEGACY + 33)
+#define MX21_INT_DMACH2		(NR_IRQS_LEGACY + 34)
+#define MX21_INT_DMACH3		(NR_IRQS_LEGACY + 35)
+#define MX21_INT_DMACH4		(NR_IRQS_LEGACY + 36)
+#define MX21_INT_DMACH5		(NR_IRQS_LEGACY + 37)
+#define MX21_INT_DMACH6		(NR_IRQS_LEGACY + 38)
+#define MX21_INT_DMACH7		(NR_IRQS_LEGACY + 39)
+#define MX21_INT_DMACH8		(NR_IRQS_LEGACY + 40)
+#define MX21_INT_DMACH9		(NR_IRQS_LEGACY + 41)
+#define MX21_INT_DMACH10	(NR_IRQS_LEGACY + 42)
+#define MX21_INT_DMACH11	(NR_IRQS_LEGACY + 43)
+#define MX21_INT_DMACH12	(NR_IRQS_LEGACY + 44)
+#define MX21_INT_DMACH13	(NR_IRQS_LEGACY + 45)
+#define MX21_INT_DMACH14	(NR_IRQS_LEGACY + 46)
+#define MX21_INT_DMACH15	(NR_IRQS_LEGACY + 47)
+#define MX21_INT_EMMAENC	(NR_IRQS_LEGACY + 49)
+#define MX21_INT_EMMADEC	(NR_IRQS_LEGACY + 50)
+#define MX21_INT_EMMAPRP	(NR_IRQS_LEGACY + 51)
+#define MX21_INT_EMMAPP		(NR_IRQS_LEGACY + 52)
+#define MX21_INT_USBWKUP	(NR_IRQS_LEGACY + 53)
+#define MX21_INT_USBDMA		(NR_IRQS_LEGACY + 54)
+#define MX21_INT_USBHOST	(NR_IRQS_LEGACY + 55)
+#define MX21_INT_USBFUNC	(NR_IRQS_LEGACY + 56)
+#define MX21_INT_USBMNP		(NR_IRQS_LEGACY + 57)
+#define MX21_INT_USBCTRL	(NR_IRQS_LEGACY + 58)
+#define MX21_INT_SLCDC		(NR_IRQS_LEGACY + 60)
+#define MX21_INT_LCDC		(NR_IRQS_LEGACY + 61)
+
+/* fixed DMA request numbers */
+#define MX21_DMA_REQ_CSPI3_RX	1
+#define MX21_DMA_REQ_CSPI3_TX	2
+#define MX21_DMA_REQ_EXT	3
+#define MX21_DMA_REQ_FIRI_RX	4
+#define MX21_DMA_REQ_SDHC2	6
+#define MX21_DMA_REQ_SDHC1	7
+#define MX21_DMA_REQ_SSI2_RX0	8
+#define MX21_DMA_REQ_SSI2_TX0	9
+#define MX21_DMA_REQ_SSI2_RX1	10
+#define MX21_DMA_REQ_SSI2_TX1	11
+#define MX21_DMA_REQ_SSI1_RX0	12
+#define MX21_DMA_REQ_SSI1_TX0	13
+#define MX21_DMA_REQ_SSI1_RX1	14
+#define MX21_DMA_REQ_SSI1_TX1	15
+#define MX21_DMA_REQ_CSPI2_RX	16
+#define MX21_DMA_REQ_CSPI2_TX	17
+#define MX21_DMA_REQ_CSPI1_RX	18
+#define MX21_DMA_REQ_CSPI1_TX	19
+#define MX21_DMA_REQ_UART4_RX	20
+#define MX21_DMA_REQ_UART4_TX	21
+#define MX21_DMA_REQ_UART3_RX	22
+#define MX21_DMA_REQ_UART3_TX	23
+#define MX21_DMA_REQ_UART2_RX	24
+#define MX21_DMA_REQ_UART2_TX	25
+#define MX21_DMA_REQ_UART1_RX	26
+#define MX21_DMA_REQ_UART1_TX	27
+#define MX21_DMA_REQ_BMI_TX	28
+#define MX21_DMA_REQ_BMI_RX	29
+#define MX21_DMA_REQ_CSI_STAT	30
+#define MX21_DMA_REQ_CSI_RX	31
+
+#endif /* ifndef __MACH_MX21_H__ */
diff --git a/arch/arm/mach-imx/mx25.h b/arch/arm/mach-imx/mx25.h
new file mode 100644
index 0000000..ec46640
--- /dev/null
+++ b/arch/arm/mach-imx/mx25.h
@@ -0,0 +1,117 @@
+#ifndef __MACH_MX25_H__
+#define __MACH_MX25_H__
+
+#define MX25_AIPS1_BASE_ADDR		0x43f00000
+#define MX25_AIPS1_SIZE			SZ_1M
+#define MX25_AIPS2_BASE_ADDR		0x53f00000
+#define MX25_AIPS2_SIZE			SZ_1M
+#define MX25_AVIC_BASE_ADDR		0x68000000
+#define MX25_AVIC_SIZE			SZ_1M
+
+#define MX25_I2C1_BASE_ADDR		(MX25_AIPS1_BASE_ADDR + 0x80000)
+#define MX25_I2C3_BASE_ADDR		(MX25_AIPS1_BASE_ADDR + 0x84000)
+#define MX25_CAN1_BASE_ADDR		(MX25_AIPS1_BASE_ADDR + 0x88000)
+#define MX25_CAN2_BASE_ADDR		(MX25_AIPS1_BASE_ADDR + 0x8c000)
+#define MX25_I2C2_BASE_ADDR		(MX25_AIPS1_BASE_ADDR + 0x98000)
+#define MX25_CSPI1_BASE_ADDR		(MX25_AIPS1_BASE_ADDR + 0xa4000)
+#define MX25_IOMUXC_BASE_ADDR		(MX25_AIPS1_BASE_ADDR + 0xac000)
+
+#define MX25_CRM_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0x80000)
+#define MX25_GPT1_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0x90000)
+#define MX25_GPIO4_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0x9c000)
+#define MX25_PWM2_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xa0000)
+#define MX25_GPIO3_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xa4000)
+#define MX25_PWM3_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xa8000)
+#define MX25_PWM4_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xc8000)
+#define MX25_GPIO1_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xcc000)
+#define MX25_GPIO2_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xd0000)
+#define MX25_WDOG_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xdc000)
+#define MX25_PWM1_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xe0000)
+
+#define MX25_UART1_BASE_ADDR		0x43f90000
+#define MX25_UART2_BASE_ADDR		0x43f94000
+#define MX25_AUDMUX_BASE_ADDR		0x43fb0000
+#define MX25_UART3_BASE_ADDR		0x5000c000
+#define MX25_UART4_BASE_ADDR		0x50008000
+#define MX25_UART5_BASE_ADDR		0x5002c000
+
+#define MX25_CSPI3_BASE_ADDR		0x50004000
+#define MX25_CSPI2_BASE_ADDR		0x50010000
+#define MX25_FEC_BASE_ADDR		0x50038000
+#define MX25_SSI2_BASE_ADDR		0x50014000
+#define MX25_SSI1_BASE_ADDR		0x50034000
+#define MX25_NFC_BASE_ADDR		0xbb000000
+#define MX25_IIM_BASE_ADDR		0x53ff0000
+#define MX25_DRYICE_BASE_ADDR		0x53ffc000
+#define MX25_ESDHC1_BASE_ADDR		0x53fb4000
+#define MX25_ESDHC2_BASE_ADDR		0x53fb8000
+#define MX25_LCDC_BASE_ADDR		0x53fbc000
+#define MX25_KPP_BASE_ADDR		0x43fa8000
+#define MX25_SDMA_BASE_ADDR		0x53fd4000
+#define MX25_USB_BASE_ADDR		0x53ff4000
+#define MX25_USB_OTG_BASE_ADDR			(MX25_USB_BASE_ADDR + 0x0000)
+/*
+ * The reference manual (IMX25RM, Rev. 1, 06/2009) specifies an offset of 0x200
+ * for the host controller.  Early documentation drafts specified 0x400 and
+ * Freescale internal sources confirm only the latter value to work.
+ */
+#define MX25_USB_HS_BASE_ADDR			(MX25_USB_BASE_ADDR + 0x0400)
+#define MX25_CSI_BASE_ADDR		0x53ff8000
+
+#define MX25_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX25_IO_ADDRESS(x)		IOMEM(MX25_IO_P2V(x))
+
+/*
+ * Interrupt numbers
+ */
+#include <asm/irq.h>
+#define MX25_INT_CSPI3		(NR_IRQS_LEGACY + 0)
+#define MX25_INT_I2C1		(NR_IRQS_LEGACY + 3)
+#define MX25_INT_I2C2		(NR_IRQS_LEGACY + 4)
+#define MX25_INT_UART4		(NR_IRQS_LEGACY + 5)
+#define MX25_INT_ESDHC2		(NR_IRQS_LEGACY + 8)
+#define MX25_INT_ESDHC1		(NR_IRQS_LEGACY + 9)
+#define MX25_INT_I2C3		(NR_IRQS_LEGACY + 10)
+#define MX25_INT_SSI2		(NR_IRQS_LEGACY + 11)
+#define MX25_INT_SSI1		(NR_IRQS_LEGACY + 12)
+#define MX25_INT_CSPI2		(NR_IRQS_LEGACY + 13)
+#define MX25_INT_CSPI1		(NR_IRQS_LEGACY + 14)
+#define MX25_INT_GPIO3		(NR_IRQS_LEGACY + 16)
+#define MX25_INT_CSI		(NR_IRQS_LEGACY + 17)
+#define MX25_INT_UART3		(NR_IRQS_LEGACY + 18)
+#define MX25_INT_GPIO4		(NR_IRQS_LEGACY + 23)
+#define MX25_INT_KPP		(NR_IRQS_LEGACY + 24)
+#define MX25_INT_DRYICE		(NR_IRQS_LEGACY + 25)
+#define MX25_INT_PWM1		(NR_IRQS_LEGACY + 26)
+#define MX25_INT_UART2		(NR_IRQS_LEGACY + 32)
+#define MX25_INT_NFC		(NR_IRQS_LEGACY + 33)
+#define MX25_INT_SDMA		(NR_IRQS_LEGACY + 34)
+#define MX25_INT_USB_HS		(NR_IRQS_LEGACY + 35)
+#define MX25_INT_PWM2		(NR_IRQS_LEGACY + 36)
+#define MX25_INT_USB_OTG	(NR_IRQS_LEGACY + 37)
+#define MX25_INT_LCDC		(NR_IRQS_LEGACY + 39)
+#define MX25_INT_UART5		(NR_IRQS_LEGACY + 40)
+#define MX25_INT_PWM3		(NR_IRQS_LEGACY + 41)
+#define MX25_INT_PWM4		(NR_IRQS_LEGACY + 42)
+#define MX25_INT_CAN1		(NR_IRQS_LEGACY + 43)
+#define MX25_INT_CAN2		(NR_IRQS_LEGACY + 44)
+#define MX25_INT_UART1		(NR_IRQS_LEGACY + 45)
+#define MX25_INT_GPIO2		(NR_IRQS_LEGACY + 51)
+#define MX25_INT_GPIO1		(NR_IRQS_LEGACY + 52)
+#define MX25_INT_GPT1		(NR_IRQS_LEGACY + 54)
+#define MX25_INT_FEC		(NR_IRQS_LEGACY + 57)
+
+#define MX25_DMA_REQ_SSI2_RX1	22
+#define MX25_DMA_REQ_SSI2_TX1	23
+#define MX25_DMA_REQ_SSI2_RX0	24
+#define MX25_DMA_REQ_SSI2_TX0	25
+#define MX25_DMA_REQ_SSI1_RX1	26
+#define MX25_DMA_REQ_SSI1_TX1	27
+#define MX25_DMA_REQ_SSI1_RX0	28
+#define MX25_DMA_REQ_SSI1_TX0	29
+
+#ifndef __ASSEMBLY__
+extern int mx25_revision(void);
+#endif
+
+#endif /* ifndef __MACH_MX25_H__ */
diff --git a/arch/arm/mach-imx/mx27.h b/arch/arm/mach-imx/mx27.h
new file mode 100644
index 0000000..e074616
--- /dev/null
+++ b/arch/arm/mach-imx/mx27.h
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ *
+ * This contains i.MX27-specific hardware definitions. For those
+ * hardware pieces that are common between i.MX21 and i.MX27, have a
+ * look at mx2x.h.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ */
+
+#ifndef __MACH_MX27_H__
+#define __MACH_MX27_H__
+
+#define MX27_AIPI_BASE_ADDR		0x10000000
+#define MX27_AIPI_SIZE			SZ_1M
+#define MX27_DMA_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x01000)
+#define MX27_WDOG_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x02000)
+#define MX27_GPT1_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x03000)
+#define MX27_GPT2_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x04000)
+#define MX27_GPT3_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x05000)
+#define MX27_PWM_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x06000)
+#define MX27_RTC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x07000)
+#define MX27_KPP_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x08000)
+#define MX27_OWIRE_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x09000)
+#define MX27_UART1_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x0a000)
+#define MX27_UART2_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x0b000)
+#define MX27_UART3_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x0c000)
+#define MX27_UART4_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x0d000)
+#define MX27_CSPI1_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x0e000)
+#define MX27_CSPI2_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x0f000)
+#define MX27_SSI1_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x10000)
+#define MX27_SSI2_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x11000)
+#define MX27_I2C1_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x12000)
+#define MX27_SDHC1_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x13000)
+#define MX27_SDHC2_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x14000)
+#define MX27_GPIO_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x15000)
+#define MX27_GPIO1_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x000)
+#define MX27_GPIO2_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x100)
+#define MX27_GPIO3_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x200)
+#define MX27_GPIO4_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x300)
+#define MX27_GPIO5_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x400)
+#define MX27_GPIO6_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x500)
+#define MX27_AUDMUX_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x16000)
+#define MX27_CSPI3_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x17000)
+#define MX27_MSHC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x18000)
+#define MX27_GPT4_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x19000)
+#define MX27_GPT5_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x1a000)
+#define MX27_UART5_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x1b000)
+#define MX27_UART6_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x1c000)
+#define MX27_I2C2_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x1d000)
+#define MX27_SDHC3_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x1e000)
+#define MX27_GPT6_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x1f000)
+#define MX27_LCDC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x21000)
+#define MX27_SLCDC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x22000)
+#define MX27_VPU_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x23000)
+#define MX27_USB_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x24000)
+#define MX27_USB_OTG_BASE_ADDR			(MX27_USB_BASE_ADDR + 0x0000)
+#define MX27_USB_HS1_BASE_ADDR			(MX27_USB_BASE_ADDR + 0x0200)
+#define MX27_USB_HS2_BASE_ADDR			(MX27_USB_BASE_ADDR + 0x0400)
+#define MX27_SAHARA_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x25000)
+#define MX27_EMMAPP_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x26000)
+#define MX27_EMMAPRP_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x26400)
+#define MX27_CCM_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x27000)
+#define MX27_SYSCTRL_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x27800)
+#define MX27_IIM_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x28000)
+#define MX27_RTIC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x2a000)
+#define MX27_FEC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x2b000)
+#define MX27_SCC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x2c000)
+#define MX27_ETB_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x3b000)
+#define MX27_ETB_RAM_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x3c000)
+#define MX27_JAM_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x3e000)
+#define MX27_MAX_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x3f000)
+
+#define MX27_AVIC_BASE_ADDR		0x10040000
+
+/* ROM patch */
+#define MX27_ROMP_BASE_ADDR		0x10041000
+
+#define MX27_SAHB1_BASE_ADDR		0x80000000
+#define MX27_SAHB1_SIZE			SZ_1M
+#define MX27_CSI_BASE_ADDR			(MX27_SAHB1_BASE_ADDR + 0x0000)
+#define MX27_ATA_BASE_ADDR			(MX27_SAHB1_BASE_ADDR + 0x1000)
+
+/* Memory regions and CS */
+#define MX27_SDRAM_BASE_ADDR		0xa0000000
+#define MX27_CSD1_BASE_ADDR		0xb0000000
+
+#define MX27_CS0_BASE_ADDR		0xc0000000
+#define MX27_CS1_BASE_ADDR		0xc8000000
+#define MX27_CS2_BASE_ADDR		0xd0000000
+#define MX27_CS3_BASE_ADDR		0xd2000000
+#define MX27_CS4_BASE_ADDR		0xd4000000
+#define MX27_CS5_BASE_ADDR		0xd6000000
+
+/* NAND, SDRAM, WEIM, M3IF, EMI controllers */
+#define MX27_X_MEMC_BASE_ADDR		0xd8000000
+#define MX27_X_MEMC_SIZE		SZ_1M
+#define MX27_NFC_BASE_ADDR			(MX27_X_MEMC_BASE_ADDR)
+#define MX27_SDRAMC_BASE_ADDR			(MX27_X_MEMC_BASE_ADDR + 0x1000)
+#define MX27_WEIM_BASE_ADDR			(MX27_X_MEMC_BASE_ADDR + 0x2000)
+#define MX27_M3IF_BASE_ADDR			(MX27_X_MEMC_BASE_ADDR + 0x3000)
+#define MX27_PCMCIA_CTL_BASE_ADDR		(MX27_X_MEMC_BASE_ADDR + 0x4000)
+
+#define MX27_WEIM_CSCRx_BASE_ADDR(cs)	(MX27_WEIM_BASE_ADDR + (cs) * 0x10)
+#define MX27_WEIM_CSCRxU(cs)			(MX27_WEIM_CSCRx_BASE_ADDR(cs))
+#define MX27_WEIM_CSCRxL(cs)			(MX27_WEIM_CSCRx_BASE_ADDR(cs) + 0x4)
+#define MX27_WEIM_CSCRxA(cs)			(MX27_WEIM_CSCRx_BASE_ADDR(cs) + 0x8)
+
+#define MX27_PCMCIA_MEM_BASE_ADDR	0xdc000000
+
+/* IRAM */
+#define MX27_IRAM_BASE_ADDR		0xffff4c00	/* internal ram */
+
+#define MX27_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX27_IO_ADDRESS(x)		IOMEM(MX27_IO_P2V(x))
+
+/* fixed interrupt numbers */
+#include <asm/irq.h>
+#define MX27_INT_I2C2		(NR_IRQS_LEGACY + 1)
+#define MX27_INT_GPT6		(NR_IRQS_LEGACY + 2)
+#define MX27_INT_GPT5		(NR_IRQS_LEGACY + 3)
+#define MX27_INT_GPT4		(NR_IRQS_LEGACY + 4)
+#define MX27_INT_RTIC		(NR_IRQS_LEGACY + 5)
+#define MX27_INT_CSPI3		(NR_IRQS_LEGACY + 6)
+#define MX27_INT_SDHC		(NR_IRQS_LEGACY + 7)
+#define MX27_INT_GPIO		(NR_IRQS_LEGACY + 8)
+#define MX27_INT_SDHC3		(NR_IRQS_LEGACY + 9)
+#define MX27_INT_SDHC2		(NR_IRQS_LEGACY + 10)
+#define MX27_INT_SDHC1		(NR_IRQS_LEGACY + 11)
+#define MX27_INT_I2C1		(NR_IRQS_LEGACY + 12)
+#define MX27_INT_SSI2		(NR_IRQS_LEGACY + 13)
+#define MX27_INT_SSI1		(NR_IRQS_LEGACY + 14)
+#define MX27_INT_CSPI2		(NR_IRQS_LEGACY + 15)
+#define MX27_INT_CSPI1		(NR_IRQS_LEGACY + 16)
+#define MX27_INT_UART4		(NR_IRQS_LEGACY + 17)
+#define MX27_INT_UART3		(NR_IRQS_LEGACY + 18)
+#define MX27_INT_UART2		(NR_IRQS_LEGACY + 19)
+#define MX27_INT_UART1		(NR_IRQS_LEGACY + 20)
+#define MX27_INT_KPP		(NR_IRQS_LEGACY + 21)
+#define MX27_INT_RTC		(NR_IRQS_LEGACY + 22)
+#define MX27_INT_PWM		(NR_IRQS_LEGACY + 23)
+#define MX27_INT_GPT3		(NR_IRQS_LEGACY + 24)
+#define MX27_INT_GPT2		(NR_IRQS_LEGACY + 25)
+#define MX27_INT_GPT1		(NR_IRQS_LEGACY + 26)
+#define MX27_INT_WDOG		(NR_IRQS_LEGACY + 27)
+#define MX27_INT_PCMCIA		(NR_IRQS_LEGACY + 28)
+#define MX27_INT_NFC		(NR_IRQS_LEGACY + 29)
+#define MX27_INT_ATA		(NR_IRQS_LEGACY + 30)
+#define MX27_INT_CSI		(NR_IRQS_LEGACY + 31)
+#define MX27_INT_DMACH0		(NR_IRQS_LEGACY + 32)
+#define MX27_INT_DMACH1		(NR_IRQS_LEGACY + 33)
+#define MX27_INT_DMACH2		(NR_IRQS_LEGACY + 34)
+#define MX27_INT_DMACH3		(NR_IRQS_LEGACY + 35)
+#define MX27_INT_DMACH4		(NR_IRQS_LEGACY + 36)
+#define MX27_INT_DMACH5		(NR_IRQS_LEGACY + 37)
+#define MX27_INT_DMACH6		(NR_IRQS_LEGACY + 38)
+#define MX27_INT_DMACH7		(NR_IRQS_LEGACY + 39)
+#define MX27_INT_DMACH8		(NR_IRQS_LEGACY + 40)
+#define MX27_INT_DMACH9		(NR_IRQS_LEGACY + 41)
+#define MX27_INT_DMACH10	(NR_IRQS_LEGACY + 42)
+#define MX27_INT_DMACH11	(NR_IRQS_LEGACY + 43)
+#define MX27_INT_DMACH12	(NR_IRQS_LEGACY + 44)
+#define MX27_INT_DMACH13	(NR_IRQS_LEGACY + 45)
+#define MX27_INT_DMACH14	(NR_IRQS_LEGACY + 46)
+#define MX27_INT_DMACH15	(NR_IRQS_LEGACY + 47)
+#define MX27_INT_UART6		(NR_IRQS_LEGACY + 48)
+#define MX27_INT_UART5		(NR_IRQS_LEGACY + 49)
+#define MX27_INT_FEC		(NR_IRQS_LEGACY + 50)
+#define MX27_INT_EMMAPRP	(NR_IRQS_LEGACY + 51)
+#define MX27_INT_EMMAPP		(NR_IRQS_LEGACY + 52)
+#define MX27_INT_VPU		(NR_IRQS_LEGACY + 53)
+#define MX27_INT_USB_HS1	(NR_IRQS_LEGACY + 54)
+#define MX27_INT_USB_HS2	(NR_IRQS_LEGACY + 55)
+#define MX27_INT_USB_OTG	(NR_IRQS_LEGACY + 56)
+#define MX27_INT_SCC_SMN	(NR_IRQS_LEGACY + 57)
+#define MX27_INT_SCC_SCM	(NR_IRQS_LEGACY + 58)
+#define MX27_INT_SAHARA		(NR_IRQS_LEGACY + 59)
+#define MX27_INT_SLCDC		(NR_IRQS_LEGACY + 60)
+#define MX27_INT_LCDC		(NR_IRQS_LEGACY + 61)
+#define MX27_INT_IIM		(NR_IRQS_LEGACY + 62)
+#define MX27_INT_CCM		(NR_IRQS_LEGACY + 63)
+
+/* fixed DMA request numbers */
+#define MX27_DMA_REQ_CSPI3_RX	1
+#define MX27_DMA_REQ_CSPI3_TX	2
+#define MX27_DMA_REQ_EXT	3
+#define MX27_DMA_REQ_MSHC	4
+#define MX27_DMA_REQ_SDHC2	6
+#define MX27_DMA_REQ_SDHC1	7
+#define MX27_DMA_REQ_SSI2_RX0	8
+#define MX27_DMA_REQ_SSI2_TX0	9
+#define MX27_DMA_REQ_SSI2_RX1	10
+#define MX27_DMA_REQ_SSI2_TX1	11
+#define MX27_DMA_REQ_SSI1_RX0	12
+#define MX27_DMA_REQ_SSI1_TX0	13
+#define MX27_DMA_REQ_SSI1_RX1	14
+#define MX27_DMA_REQ_SSI1_TX1	15
+#define MX27_DMA_REQ_CSPI2_RX	16
+#define MX27_DMA_REQ_CSPI2_TX	17
+#define MX27_DMA_REQ_CSPI1_RX	18
+#define MX27_DMA_REQ_CSPI1_TX	19
+#define MX27_DMA_REQ_UART4_RX	20
+#define MX27_DMA_REQ_UART4_TX	21
+#define MX27_DMA_REQ_UART3_RX	22
+#define MX27_DMA_REQ_UART3_TX	23
+#define MX27_DMA_REQ_UART2_RX	24
+#define MX27_DMA_REQ_UART2_TX	25
+#define MX27_DMA_REQ_UART1_RX	26
+#define MX27_DMA_REQ_UART1_TX	27
+#define MX27_DMA_REQ_ATA_TX	28
+#define MX27_DMA_REQ_ATA_RCV	29
+#define MX27_DMA_REQ_CSI_STAT	30
+#define MX27_DMA_REQ_CSI_RX	31
+#define MX27_DMA_REQ_UART5_TX	32
+#define MX27_DMA_REQ_UART5_RX	33
+#define MX27_DMA_REQ_UART6_TX	34
+#define MX27_DMA_REQ_UART6_RX	35
+#define MX27_DMA_REQ_SDHC3	36
+#define MX27_DMA_REQ_NFC	37
+
+#ifndef __ASSEMBLY__
+extern int mx27_revision(void);
+#endif
+
+#endif /* ifndef __MACH_MX27_H__ */
diff --git a/arch/arm/mach-imx/mx2x.h b/arch/arm/mach-imx/mx2x.h
new file mode 100644
index 0000000..11642f5
--- /dev/null
+++ b/arch/arm/mach-imx/mx2x.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ *
+ * This contains hardware definitions that are common between i.MX21 and
+ * i.MX27.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ */
+
+#ifndef __MACH_MX2x_H__
+#define __MACH_MX2x_H__
+
+/* The following addresses are common between i.MX21 and i.MX27 */
+
+/* Register offsets */
+#define MX2x_AIPI_BASE_ADDR		0x10000000
+#define MX2x_AIPI_SIZE			SZ_1M
+#define MX2x_DMA_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x01000)
+#define MX2x_WDOG_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x02000)
+#define MX2x_GPT1_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x03000)
+#define MX2x_GPT2_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x04000)
+#define MX2x_GPT3_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x05000)
+#define MX2x_PWM_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x06000)
+#define MX2x_RTC_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x07000)
+#define MX2x_KPP_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x08000)
+#define MX2x_OWIRE_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x09000)
+#define MX2x_UART1_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x0a000)
+#define MX2x_UART2_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x0b000)
+#define MX2x_UART3_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x0c000)
+#define MX2x_UART4_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x0d000)
+#define MX2x_CSPI1_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x0e000)
+#define MX2x_CSPI2_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x0f000)
+#define MX2x_SSI1_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x10000)
+#define MX2x_SSI2_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x11000)
+#define MX2x_I2C_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x12000)
+#define MX2x_SDHC1_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x13000)
+#define MX2x_SDHC2_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x14000)
+#define MX2x_GPIO_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x15000)
+#define MX2x_AUDMUX_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x16000)
+#define MX2x_CSPI3_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x17000)
+#define MX2x_LCDC_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x21000)
+#define MX2x_SLCDC_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x22000)
+#define MX2x_USBOTG_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x24000)
+#define MX2x_EMMA_PP_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x26000)
+#define MX2x_EMMA_PRP_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x26400)
+#define MX2x_CCM_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x27000)
+#define MX2x_SYSCTRL_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x27800)
+#define MX2x_JAM_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x3e000)
+#define MX2x_MAX_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x3f000)
+
+#define MX2x_AVIC_BASE_ADDR		0x10040000
+
+#define MX2x_SAHB1_BASE_ADDR		0x80000000
+#define MX2x_SAHB1_SIZE			SZ_1M
+#define MX2x_CSI_BASE_ADDR			(MX2x_SAHB1_BASE_ADDR + 0x0000)
+
+/* fixed interrupt numbers */
+#include <asm/irq.h>
+#define MX2x_INT_CSPI3		(NR_IRQS_LEGACY + 6)
+#define MX2x_INT_GPIO		(NR_IRQS_LEGACY + 8)
+#define MX2x_INT_SDHC2		(NR_IRQS_LEGACY + 10)
+#define MX2x_INT_SDHC1		(NR_IRQS_LEGACY + 11)
+#define MX2x_INT_I2C		(NR_IRQS_LEGACY + 12)
+#define MX2x_INT_SSI2		(NR_IRQS_LEGACY + 13)
+#define MX2x_INT_SSI1		(NR_IRQS_LEGACY + 14)
+#define MX2x_INT_CSPI2		(NR_IRQS_LEGACY + 15)
+#define MX2x_INT_CSPI1		(NR_IRQS_LEGACY + 16)
+#define MX2x_INT_UART4		(NR_IRQS_LEGACY + 17)
+#define MX2x_INT_UART3		(NR_IRQS_LEGACY + 18)
+#define MX2x_INT_UART2		(NR_IRQS_LEGACY + 19)
+#define MX2x_INT_UART1		(NR_IRQS_LEGACY + 20)
+#define MX2x_INT_KPP		(NR_IRQS_LEGACY + 21)
+#define MX2x_INT_RTC		(NR_IRQS_LEGACY + 22)
+#define MX2x_INT_PWM		(NR_IRQS_LEGACY + 23)
+#define MX2x_INT_GPT3		(NR_IRQS_LEGACY + 24)
+#define MX2x_INT_GPT2		(NR_IRQS_LEGACY + 25)
+#define MX2x_INT_GPT1		(NR_IRQS_LEGACY + 26)
+#define MX2x_INT_WDOG		(NR_IRQS_LEGACY + 27)
+#define MX2x_INT_PCMCIA		(NR_IRQS_LEGACY + 28)
+#define MX2x_INT_NANDFC		(NR_IRQS_LEGACY + 29)
+#define MX2x_INT_CSI		(NR_IRQS_LEGACY + 31)
+#define MX2x_INT_DMACH0		(NR_IRQS_LEGACY + 32)
+#define MX2x_INT_DMACH1		(NR_IRQS_LEGACY + 33)
+#define MX2x_INT_DMACH2		(NR_IRQS_LEGACY + 34)
+#define MX2x_INT_DMACH3		(NR_IRQS_LEGACY + 35)
+#define MX2x_INT_DMACH4		(NR_IRQS_LEGACY + 36)
+#define MX2x_INT_DMACH5		(NR_IRQS_LEGACY + 37)
+#define MX2x_INT_DMACH6		(NR_IRQS_LEGACY + 38)
+#define MX2x_INT_DMACH7		(NR_IRQS_LEGACY + 39)
+#define MX2x_INT_DMACH8		(NR_IRQS_LEGACY + 40)
+#define MX2x_INT_DMACH9		(NR_IRQS_LEGACY + 41)
+#define MX2x_INT_DMACH10	(NR_IRQS_LEGACY + 42)
+#define MX2x_INT_DMACH11	(NR_IRQS_LEGACY + 43)
+#define MX2x_INT_DMACH12	(NR_IRQS_LEGACY + 44)
+#define MX2x_INT_DMACH13	(NR_IRQS_LEGACY + 45)
+#define MX2x_INT_DMACH14	(NR_IRQS_LEGACY + 46)
+#define MX2x_INT_DMACH15	(NR_IRQS_LEGACY + 47)
+#define MX2x_INT_EMMAPRP	(NR_IRQS_LEGACY + 51)
+#define MX2x_INT_EMMAPP		(NR_IRQS_LEGACY + 52)
+#define MX2x_INT_SLCDC		(NR_IRQS_LEGACY + 60)
+#define MX2x_INT_LCDC		(NR_IRQS_LEGACY + 61)
+
+/* fixed DMA request numbers */
+#define MX2x_DMA_REQ_CSPI3_RX	1
+#define MX2x_DMA_REQ_CSPI3_TX	2
+#define MX2x_DMA_REQ_EXT	3
+#define MX2x_DMA_REQ_SDHC2	6
+#define MX2x_DMA_REQ_SDHC1	7
+#define MX2x_DMA_REQ_SSI2_RX0	8
+#define MX2x_DMA_REQ_SSI2_TX0	9
+#define MX2x_DMA_REQ_SSI2_RX1	10
+#define MX2x_DMA_REQ_SSI2_TX1	11
+#define MX2x_DMA_REQ_SSI1_RX0	12
+#define MX2x_DMA_REQ_SSI1_TX0	13
+#define MX2x_DMA_REQ_SSI1_RX1	14
+#define MX2x_DMA_REQ_SSI1_TX1	15
+#define MX2x_DMA_REQ_CSPI2_RX	16
+#define MX2x_DMA_REQ_CSPI2_TX	17
+#define MX2x_DMA_REQ_CSPI1_RX	18
+#define MX2x_DMA_REQ_CSPI1_TX	19
+#define MX2x_DMA_REQ_UART4_RX	20
+#define MX2x_DMA_REQ_UART4_TX	21
+#define MX2x_DMA_REQ_UART3_RX	22
+#define MX2x_DMA_REQ_UART3_TX	23
+#define MX2x_DMA_REQ_UART2_RX	24
+#define MX2x_DMA_REQ_UART2_TX	25
+#define MX2x_DMA_REQ_UART1_RX	26
+#define MX2x_DMA_REQ_UART1_TX	27
+#define MX2x_DMA_REQ_CSI_STAT	30
+#define MX2x_DMA_REQ_CSI_RX	31
+
+#endif /* ifndef __MACH_MX2x_H__ */
diff --git a/arch/arm/mach-imx/mx31.h b/arch/arm/mach-imx/mx31.h
new file mode 100644
index 0000000..ee9b1f9
--- /dev/null
+++ b/arch/arm/mach-imx/mx31.h
@@ -0,0 +1,196 @@
+#ifndef __MACH_MX31_H__
+#define __MACH_MX31_H__
+
+/*
+ * IRAM
+ */
+#define MX31_IRAM_BASE_ADDR		0x1ffc0000	/* internal ram */
+#define MX31_IRAM_SIZE			SZ_16K
+
+#define MX31_L2CC_BASE_ADDR		0x30000000
+#define MX31_L2CC_SIZE			SZ_1M
+
+#define MX31_AIPS1_BASE_ADDR		0x43f00000
+#define MX31_AIPS1_SIZE			SZ_1M
+#define MX31_MAX_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x04000)
+#define MX31_EVTMON_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x08000)
+#define MX31_CLKCTL_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x0c000)
+#define MX31_ETB_SLOT4_BASE_ADDR		(MX31_AIPS1_BASE_ADDR + 0x10000)
+#define MX31_ETB_SLOT5_BASE_ADDR		(MX31_AIPS1_BASE_ADDR + 0x14000)
+#define MX31_ECT_CTIO_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x18000)
+#define MX31_I2C1_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x80000)
+#define MX31_I2C3_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x84000)
+#define MX31_USB_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x88000)
+#define MX31_USB_OTG_BASE_ADDR			(MX31_USB_BASE_ADDR + 0x0000)
+#define MX31_USB_HS1_BASE_ADDR			(MX31_USB_BASE_ADDR + 0x0200)
+#define MX31_USB_HS2_BASE_ADDR			(MX31_USB_BASE_ADDR + 0x0400)
+#define MX31_ATA_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x8c000)
+#define MX31_UART1_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x90000)
+#define MX31_UART2_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x94000)
+#define MX31_I2C2_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x98000)
+#define MX31_OWIRE_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x9c000)
+#define MX31_SSI1_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xa0000)
+#define MX31_CSPI1_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xa4000)
+#define MX31_KPP_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xa8000)
+#define MX31_IOMUXC_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xac000)
+#define MX31_UART4_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xb0000)
+#define MX31_UART5_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xb4000)
+#define MX31_ECT_IP1_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xb8000)
+#define MX31_ECT_IP2_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xbc000)
+
+#define MX31_SPBA0_BASE_ADDR		0x50000000
+#define MX31_SPBA0_SIZE			SZ_1M
+#define MX31_SDHC1_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x04000)
+#define MX31_SDHC2_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x08000)
+#define MX31_UART3_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x0c000)
+#define MX31_CSPI2_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x10000)
+#define MX31_SSI2_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x14000)
+#define MX31_SIM1_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x18000)
+#define MX31_IIM_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x1c000)
+#define MX31_ATA_DMA_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x20000)
+#define MX31_MSHC1_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x24000)
+#define MX31_SPBA_CTRL_BASE_ADDR		(MX31_SPBA0_BASE_ADDR + 0x3c000)
+
+#define MX31_AIPS2_BASE_ADDR		0x53f00000
+#define MX31_AIPS2_SIZE			SZ_1M
+#define MX31_CCM_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0x80000)
+#define MX31_CSPI3_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0x84000)
+#define MX31_FIRI_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0x8c000)
+#define MX31_GPT1_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0x90000)
+#define MX31_EPIT1_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0x94000)
+#define MX31_EPIT2_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0x98000)
+#define MX31_GPIO3_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xa4000)
+#define MX31_SCC_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xac000)
+#define MX31_SCM_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xae000)
+#define MX31_SMN_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xaf000)
+#define MX31_RNGA_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xb0000)
+#define MX31_IPU_CTRL_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xc0000)
+#define MX31_AUDMUX_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xc4000)
+#define MX31_MPEG4_ENC_BASE_ADDR		(MX31_AIPS2_BASE_ADDR + 0xc8000)
+#define MX31_GPIO1_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xcc000)
+#define MX31_GPIO2_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xd0000)
+#define MX31_SDMA_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xd4000)
+#define MX31_RTC_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xd8000)
+#define MX31_WDOG_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xdc000)
+#define MX31_PWM_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xe0000)
+#define MX31_RTIC_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xec000)
+
+#define MX31_ROMP_BASE_ADDR		0x60000000
+#define MX31_ROMP_BASE_ADDR_VIRT	IOMEM(0xfc500000)
+#define MX31_ROMP_SIZE			SZ_1M
+
+#define MX31_AVIC_BASE_ADDR		0x68000000
+#define MX31_AVIC_SIZE			SZ_1M
+
+#define MX31_IPU_MEM_BASE_ADDR		0x70000000
+#define MX31_CSD0_BASE_ADDR		0x80000000
+#define MX31_CSD1_BASE_ADDR		0x90000000
+
+#define MX31_CS0_BASE_ADDR		0xa0000000
+#define MX31_CS1_BASE_ADDR		0xa8000000
+#define MX31_CS2_BASE_ADDR		0xb0000000
+#define MX31_CS3_BASE_ADDR		0xb2000000
+
+#define MX31_CS4_BASE_ADDR		0xb4000000
+#define MX31_CS4_BASE_ADDR_VIRT		IOMEM(0xf6000000)
+#define MX31_CS4_SIZE			SZ_32M
+
+#define MX31_CS5_BASE_ADDR		0xb6000000
+#define MX31_CS5_BASE_ADDR_VIRT		IOMEM(0xf8000000)
+#define MX31_CS5_SIZE			SZ_32M
+
+#define MX31_X_MEMC_BASE_ADDR		0xb8000000
+#define MX31_X_MEMC_SIZE		SZ_64K
+#define MX31_NFC_BASE_ADDR			(MX31_X_MEMC_BASE_ADDR + 0x0000)
+#define MX31_ESDCTL_BASE_ADDR			(MX31_X_MEMC_BASE_ADDR + 0x1000)
+#define MX31_WEIM_BASE_ADDR			(MX31_X_MEMC_BASE_ADDR + 0x2000)
+#define MX31_M3IF_BASE_ADDR			(MX31_X_MEMC_BASE_ADDR + 0x3000)
+#define MX31_EMI_CTL_BASE_ADDR			(MX31_X_MEMC_BASE_ADDR + 0x4000)
+#define MX31_PCMCIA_CTL_BASE_ADDR		MX31_EMI_CTL_BASE_ADDR
+
+#define MX31_WEIM_CSCRx_BASE_ADDR(cs)	(MX31_WEIM_BASE_ADDR + (cs) * 0x10)
+#define MX31_WEIM_CSCRxU(cs)			(MX31_WEIM_CSCRx_BASE_ADDR(cs))
+#define MX31_WEIM_CSCRxL(cs)			(MX31_WEIM_CSCRx_BASE_ADDR(cs) + 0x4)
+#define MX31_WEIM_CSCRxA(cs)			(MX31_WEIM_CSCRx_BASE_ADDR(cs) + 0x8)
+
+#define MX31_PCMCIA_MEM_BASE_ADDR	0xbc000000
+
+#define MX31_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX31_IO_ADDRESS(x)		IOMEM(MX31_IO_P2V(x))
+
+/*
+ * Interrupt numbers
+ */
+#include <asm/irq.h>
+#define MX31_INT_I2C3		(NR_IRQS_LEGACY + 3)
+#define MX31_INT_I2C2		(NR_IRQS_LEGACY + 4)
+#define MX31_INT_MPEG4_ENCODER	(NR_IRQS_LEGACY + 5)
+#define MX31_INT_RTIC		(NR_IRQS_LEGACY + 6)
+#define MX31_INT_FIRI		(NR_IRQS_LEGACY + 7)
+#define MX31_INT_SDHC2		(NR_IRQS_LEGACY + 8)
+#define MX31_INT_SDHC1		(NR_IRQS_LEGACY + 9)
+#define MX31_INT_I2C1		(NR_IRQS_LEGACY + 10)
+#define MX31_INT_SSI2		(NR_IRQS_LEGACY + 11)
+#define MX31_INT_SSI1		(NR_IRQS_LEGACY + 12)
+#define MX31_INT_CSPI2		(NR_IRQS_LEGACY + 13)
+#define MX31_INT_CSPI1		(NR_IRQS_LEGACY + 14)
+#define MX31_INT_ATA		(NR_IRQS_LEGACY + 15)
+#define MX31_INT_MBX		(NR_IRQS_LEGACY + 16)
+#define MX31_INT_CSPI3		(NR_IRQS_LEGACY + 17)
+#define MX31_INT_UART3		(NR_IRQS_LEGACY + 18)
+#define MX31_INT_IIM		(NR_IRQS_LEGACY + 19)
+#define MX31_INT_SIM2		(NR_IRQS_LEGACY + 20)
+#define MX31_INT_SIM1		(NR_IRQS_LEGACY + 21)
+#define MX31_INT_RNGA		(NR_IRQS_LEGACY + 22)
+#define MX31_INT_EVTMON		(NR_IRQS_LEGACY + 23)
+#define MX31_INT_KPP		(NR_IRQS_LEGACY + 24)
+#define MX31_INT_RTC		(NR_IRQS_LEGACY + 25)
+#define MX31_INT_PWM		(NR_IRQS_LEGACY + 26)
+#define MX31_INT_EPIT2		(NR_IRQS_LEGACY + 27)
+#define MX31_INT_EPIT1		(NR_IRQS_LEGACY + 28)
+#define MX31_INT_GPT		(NR_IRQS_LEGACY + 29)
+#define MX31_INT_POWER_FAIL	(NR_IRQS_LEGACY + 30)
+#define MX31_INT_CCM_DVFS	(NR_IRQS_LEGACY + 31)
+#define MX31_INT_UART2		(NR_IRQS_LEGACY + 32)
+#define MX31_INT_NFC		(NR_IRQS_LEGACY + 33)
+#define MX31_INT_SDMA		(NR_IRQS_LEGACY + 34)
+#define MX31_INT_USB_HS1	(NR_IRQS_LEGACY + 35)
+#define MX31_INT_USB_HS2	(NR_IRQS_LEGACY + 36)
+#define MX31_INT_USB_OTG	(NR_IRQS_LEGACY + 37)
+#define MX31_INT_MSHC1		(NR_IRQS_LEGACY + 39)
+#define MX31_INT_MSHC2		(NR_IRQS_LEGACY + 40)
+#define MX31_INT_IPU_ERR	(NR_IRQS_LEGACY + 41)
+#define MX31_INT_IPU_SYN	(NR_IRQS_LEGACY + 42)
+#define MX31_INT_UART1		(NR_IRQS_LEGACY + 45)
+#define MX31_INT_UART4		(NR_IRQS_LEGACY + 46)
+#define MX31_INT_UART5		(NR_IRQS_LEGACY + 47)
+#define MX31_INT_ECT		(NR_IRQS_LEGACY + 48)
+#define MX31_INT_SCC_SCM	(NR_IRQS_LEGACY + 49)
+#define MX31_INT_SCC_SMN	(NR_IRQS_LEGACY + 50)
+#define MX31_INT_GPIO2		(NR_IRQS_LEGACY + 51)
+#define MX31_INT_GPIO1		(NR_IRQS_LEGACY + 52)
+#define MX31_INT_CCM		(NR_IRQS_LEGACY + 53)
+#define MX31_INT_PCMCIA		(NR_IRQS_LEGACY + 54)
+#define MX31_INT_WDOG		(NR_IRQS_LEGACY + 55)
+#define MX31_INT_GPIO3		(NR_IRQS_LEGACY + 56)
+#define MX31_INT_EXT_POWER	(NR_IRQS_LEGACY + 58)
+#define MX31_INT_EXT_TEMPER	(NR_IRQS_LEGACY + 59)
+#define MX31_INT_EXT_SENSOR60	(NR_IRQS_LEGACY + 60)
+#define MX31_INT_EXT_SENSOR61	(NR_IRQS_LEGACY + 61)
+#define MX31_INT_EXT_WDOG	(NR_IRQS_LEGACY + 62)
+#define MX31_INT_EXT_TV		(NR_IRQS_LEGACY + 63)
+
+#define MX31_DMA_REQ_SDHC1	20
+#define MX31_DMA_REQ_SDHC2	21
+#define MX31_DMA_REQ_SSI2_RX1	22
+#define MX31_DMA_REQ_SSI2_TX1	23
+#define MX31_DMA_REQ_SSI2_RX0	24
+#define MX31_DMA_REQ_SSI2_TX0	25
+#define MX31_DMA_REQ_SSI1_RX1	26
+#define MX31_DMA_REQ_SSI1_TX1	27
+#define MX31_DMA_REQ_SSI1_RX0	28
+#define MX31_DMA_REQ_SSI1_TX0	29
+
+#define MX31_PROD_SIGNATURE		0x1	/* For MX31 */
+
+#endif /* ifndef __MACH_MX31_H__ */
diff --git a/arch/arm/mach-imx/mx31lilly-db.c b/arch/arm/mach-imx/mx31lilly-db.c
index 29e890f..d4361b8 100644
--- a/arch/arm/mach-imx/mx31lilly-db.c
+++ b/arch/arm/mach-imx/mx31lilly-db.c
@@ -30,12 +30,11 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
-#include <mach/board-mx31lilly.h>
-
+#include "board-mx31lilly.h"
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
 
 /*
  * This file contains board-specific initialization routines for the
diff --git a/arch/arm/mach-imx/mx31lite-db.c b/arch/arm/mach-imx/mx31lite-db.c
index 83d17d9..5a160b7 100644
--- a/arch/arm/mach-imx/mx31lite-db.c
+++ b/arch/arm/mach-imx/mx31lite-db.c
@@ -31,12 +31,11 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
-#include <mach/board-mx31lite.h>
-
+#include "board-mx31lite.h"
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
 
 /*
  * This file contains board-specific initialization routines for the
diff --git a/arch/arm/mach-imx/mx31moboard-devboard.c b/arch/arm/mach-imx/mx31moboard-devboard.c
index cc285e5..52d5b15 100644
--- a/arch/arm/mach-imx/mx31moboard-devboard.c
+++ b/arch/arm/mach-imx/mx31moboard-devboard.c
@@ -22,12 +22,11 @@
 
 #include <linux/usb/otg.h>
 
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
-#include <mach/hardware.h>
-#include <mach/ulpi.h>
-
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
+#include "ulpi.h"
 
 static unsigned int devboard_pins[] = {
 	/* UART1 */
diff --git a/arch/arm/mach-imx/mx31moboard-marxbot.c b/arch/arm/mach-imx/mx31moboard-marxbot.c
index 135c90e..a4f43e9 100644
--- a/arch/arm/mach-imx/mx31moboard-marxbot.c
+++ b/arch/arm/mach-imx/mx31moboard-marxbot.c
@@ -24,14 +24,13 @@
 
 #include <linux/usb/otg.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx3.h>
-#include <mach/ulpi.h>
-
 #include <media/soc_camera.h>
 
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
+#include "ulpi.h"
 
 static unsigned int marxbot_pins[] = {
 	/* SDHC2 */
diff --git a/arch/arm/mach-imx/mx31moboard-smartbot.c b/arch/arm/mach-imx/mx31moboard-smartbot.c
index fabb801..04ae45d 100644
--- a/arch/arm/mach-imx/mx31moboard-smartbot.c
+++ b/arch/arm/mach-imx/mx31moboard-smartbot.c
@@ -23,15 +23,14 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx3.h>
-#include <mach/board-mx31moboard.h>
-#include <mach/ulpi.h>
-
 #include <media/soc_camera.h>
 
+#include "board-mx31moboard.h"
+#include "common.h"
 #include "devices-imx31.h"
+#include "hardware.h"
+#include "iomux-mx3.h"
+#include "ulpi.h"
 
 static unsigned int smartbot_pins[] = {
 	/* UART1 */
diff --git a/arch/arm/mach-imx/mx35.h b/arch/arm/mach-imx/mx35.h
new file mode 100644
index 0000000..2af5d3a
--- /dev/null
+++ b/arch/arm/mach-imx/mx35.h
@@ -0,0 +1,190 @@
+#ifndef __MACH_MX35_H__
+#define __MACH_MX35_H__
+
+/*
+ * IRAM
+ */
+#define MX35_IRAM_BASE_ADDR		0x10000000	/* internal ram */
+#define MX35_IRAM_SIZE			SZ_128K
+
+#define MX35_L2CC_BASE_ADDR		0x30000000
+#define MX35_L2CC_SIZE			SZ_1M
+
+#define MX35_AIPS1_BASE_ADDR		0x43f00000
+#define MX35_AIPS1_SIZE			SZ_1M
+#define MX35_MAX_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x04000)
+#define MX35_EVTMON_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x08000)
+#define MX35_CLKCTL_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x0c000)
+#define MX35_ETB_SLOT4_BASE_ADDR		(MX35_AIPS1_BASE_ADDR + 0x10000)
+#define MX35_ETB_SLOT5_BASE_ADDR		(MX35_AIPS1_BASE_ADDR + 0x14000)
+#define MX35_ECT_CTIO_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x18000)
+#define MX35_I2C1_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x80000)
+#define MX35_I2C3_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x84000)
+#define MX35_UART1_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x90000)
+#define MX35_UART2_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x94000)
+#define MX35_I2C2_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x98000)
+#define MX35_OWIRE_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x9c000)
+#define MX35_SSI1_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0xa0000)
+#define MX35_CSPI1_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0xa4000)
+#define MX35_KPP_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0xa8000)
+#define MX35_IOMUXC_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0xac000)
+#define MX35_ECT_IP1_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0xb8000)
+#define MX35_ECT_IP2_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0xbc000)
+
+#define MX35_SPBA0_BASE_ADDR		0x50000000
+#define MX35_SPBA0_SIZE			SZ_1M
+#define MX35_UART3_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x0c000)
+#define MX35_CSPI2_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x10000)
+#define MX35_SSI2_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x14000)
+#define MX35_ATA_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x20000)
+#define MX35_MSHC1_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x24000)
+#define MX35_FEC_BASE_ADDR		0x50038000
+#define MX35_SPBA_CTRL_BASE_ADDR		(MX35_SPBA0_BASE_ADDR + 0x3c000)
+
+#define MX35_AIPS2_BASE_ADDR		0x53f00000
+#define MX35_AIPS2_SIZE			SZ_1M
+#define MX35_CCM_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0x80000)
+#define MX35_GPT1_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0x90000)
+#define MX35_EPIT1_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0x94000)
+#define MX35_EPIT2_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0x98000)
+#define MX35_GPIO3_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xa4000)
+#define MX35_SCC_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xac000)
+#define MX35_RNGA_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xb0000)
+#define MX35_ESDHC1_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xb4000)
+#define MX35_ESDHC2_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xb8000)
+#define MX35_ESDHC3_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xbc000)
+#define MX35_IPU_CTRL_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xc0000)
+#define MX35_AUDMUX_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xc4000)
+#define MX35_GPIO1_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xcc000)
+#define MX35_GPIO2_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xd0000)
+#define MX35_SDMA_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xd4000)
+#define MX35_RTC_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xd8000)
+#define MX35_WDOG_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xdc000)
+#define MX35_PWM_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xe0000)
+#define MX35_CAN1_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xe4000)
+#define MX35_CAN2_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xe8000)
+#define MX35_RTIC_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xec000)
+#define MX35_IIM_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xf0000)
+#define MX35_USB_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xf4000)
+#define MX35_USB_OTG_BASE_ADDR			(MX35_USB_BASE_ADDR + 0x0000)
+/*
+ * The Reference Manual (IMX35RM, Rev. 2, 3/2009) claims an offset of 0x200 for
+ * HS.  When host support was implemented only a preliminary document was
+ * available, which told 0x400.  This works fine.
+ */
+#define MX35_USB_HS_BASE_ADDR			(MX35_USB_BASE_ADDR + 0x0400)
+
+#define MX35_ROMP_BASE_ADDR		0x60000000
+#define MX35_ROMP_SIZE			SZ_1M
+
+#define MX35_AVIC_BASE_ADDR		0x68000000
+#define MX35_AVIC_SIZE			SZ_1M
+
+/*
+ * Memory regions and CS
+ */
+#define MX35_IPU_MEM_BASE_ADDR		0x70000000
+#define MX35_CSD0_BASE_ADDR		0x80000000
+#define MX35_CSD1_BASE_ADDR		0x90000000
+
+#define MX35_CS0_BASE_ADDR		0xa0000000
+#define MX35_CS1_BASE_ADDR		0xa8000000
+#define MX35_CS2_BASE_ADDR		0xb0000000
+#define MX35_CS3_BASE_ADDR		0xb2000000
+
+#define MX35_CS4_BASE_ADDR		0xb4000000
+#define MX35_CS4_BASE_ADDR_VIRT		0xf6000000
+#define MX35_CS4_SIZE			SZ_32M
+
+#define MX35_CS5_BASE_ADDR		0xb6000000
+#define MX35_CS5_BASE_ADDR_VIRT		0xf8000000
+#define MX35_CS5_SIZE			SZ_32M
+
+/*
+ * NAND, SDRAM, WEIM, M3IF, EMI controllers
+ */
+#define MX35_X_MEMC_BASE_ADDR		0xb8000000
+#define MX35_X_MEMC_SIZE		SZ_64K
+#define MX35_ESDCTL_BASE_ADDR			(MX35_X_MEMC_BASE_ADDR + 0x1000)
+#define MX35_WEIM_BASE_ADDR			(MX35_X_MEMC_BASE_ADDR + 0x2000)
+#define MX35_M3IF_BASE_ADDR			(MX35_X_MEMC_BASE_ADDR + 0x3000)
+#define MX35_EMI_CTL_BASE_ADDR			(MX35_X_MEMC_BASE_ADDR + 0x4000)
+#define MX35_PCMCIA_CTL_BASE_ADDR		MX35_EMI_CTL_BASE_ADDR
+
+#define MX35_NFC_BASE_ADDR		0xbb000000
+#define MX35_PCMCIA_MEM_BASE_ADDR	0xbc000000
+
+#define MX35_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX35_IO_ADDRESS(x)		IOMEM(MX35_IO_P2V(x))
+
+/*
+ * Interrupt numbers
+ */
+#include <asm/irq.h>
+#define MX35_INT_OWIRE		(NR_IRQS_LEGACY + 2)
+#define MX35_INT_I2C3		(NR_IRQS_LEGACY + 3)
+#define MX35_INT_I2C2		(NR_IRQS_LEGACY + 4)
+#define MX35_INT_RTIC		(NR_IRQS_LEGACY + 6)
+#define MX35_INT_ESDHC1		(NR_IRQS_LEGACY + 7)
+#define MX35_INT_ESDHC2		(NR_IRQS_LEGACY + 8)
+#define MX35_INT_ESDHC3		(NR_IRQS_LEGACY + 9)
+#define MX35_INT_I2C1		(NR_IRQS_LEGACY + 10)
+#define MX35_INT_SSI1		(NR_IRQS_LEGACY + 11)
+#define MX35_INT_SSI2		(NR_IRQS_LEGACY + 12)
+#define MX35_INT_CSPI2		(NR_IRQS_LEGACY + 13)
+#define MX35_INT_CSPI1		(NR_IRQS_LEGACY + 14)
+#define MX35_INT_ATA		(NR_IRQS_LEGACY + 15)
+#define MX35_INT_GPU2D		(NR_IRQS_LEGACY + 16)
+#define MX35_INT_ASRC		(NR_IRQS_LEGACY + 17)
+#define MX35_INT_UART3		(NR_IRQS_LEGACY + 18)
+#define MX35_INT_IIM		(NR_IRQS_LEGACY + 19)
+#define MX35_INT_RNGA		(NR_IRQS_LEGACY + 22)
+#define MX35_INT_EVTMON		(NR_IRQS_LEGACY + 23)
+#define MX35_INT_KPP		(NR_IRQS_LEGACY + 24)
+#define MX35_INT_RTC		(NR_IRQS_LEGACY + 25)
+#define MX35_INT_PWM		(NR_IRQS_LEGACY + 26)
+#define MX35_INT_EPIT2		(NR_IRQS_LEGACY + 27)
+#define MX35_INT_EPIT1		(NR_IRQS_LEGACY + 28)
+#define MX35_INT_GPT		(NR_IRQS_LEGACY + 29)
+#define MX35_INT_POWER_FAIL	(NR_IRQS_LEGACY + 30)
+#define MX35_INT_UART2		(NR_IRQS_LEGACY + 32)
+#define MX35_INT_NFC		(NR_IRQS_LEGACY + 33)
+#define MX35_INT_SDMA		(NR_IRQS_LEGACY + 34)
+#define MX35_INT_USB_HS		(NR_IRQS_LEGACY + 35)
+#define MX35_INT_USB_OTG	(NR_IRQS_LEGACY + 37)
+#define MX35_INT_MSHC1		(NR_IRQS_LEGACY + 39)
+#define MX35_INT_ESAI		(NR_IRQS_LEGACY + 40)
+#define MX35_INT_IPU_ERR	(NR_IRQS_LEGACY + 41)
+#define MX35_INT_IPU_SYN	(NR_IRQS_LEGACY + 42)
+#define MX35_INT_CAN1		(NR_IRQS_LEGACY + 43)
+#define MX35_INT_CAN2		(NR_IRQS_LEGACY + 44)
+#define MX35_INT_UART1		(NR_IRQS_LEGACY + 45)
+#define MX35_INT_MLB		(NR_IRQS_LEGACY + 46)
+#define MX35_INT_SPDIF		(NR_IRQS_LEGACY + 47)
+#define MX35_INT_ECT		(NR_IRQS_LEGACY + 48)
+#define MX35_INT_SCC_SCM	(NR_IRQS_LEGACY + 49)
+#define MX35_INT_SCC_SMN	(NR_IRQS_LEGACY + 50)
+#define MX35_INT_GPIO2		(NR_IRQS_LEGACY + 51)
+#define MX35_INT_GPIO1		(NR_IRQS_LEGACY + 52)
+#define MX35_INT_WDOG		(NR_IRQS_LEGACY + 55)
+#define MX35_INT_GPIO3		(NR_IRQS_LEGACY + 56)
+#define MX35_INT_FEC		(NR_IRQS_LEGACY + 57)
+#define MX35_INT_EXT_POWER	(NR_IRQS_LEGACY + 58)
+#define MX35_INT_EXT_TEMPER	(NR_IRQS_LEGACY + 59)
+#define MX35_INT_EXT_SENSOR60	(NR_IRQS_LEGACY + 60)
+#define MX35_INT_EXT_SENSOR61	(NR_IRQS_LEGACY + 61)
+#define MX35_INT_EXT_WDOG	(NR_IRQS_LEGACY + 62)
+#define MX35_INT_EXT_TV		(NR_IRQS_LEGACY + 63)
+
+#define MX35_DMA_REQ_SSI2_RX1   22
+#define MX35_DMA_REQ_SSI2_TX1   23
+#define MX35_DMA_REQ_SSI2_RX0   24
+#define MX35_DMA_REQ_SSI2_TX0   25
+#define MX35_DMA_REQ_SSI1_RX1   26
+#define MX35_DMA_REQ_SSI1_TX1   27
+#define MX35_DMA_REQ_SSI1_RX0   28
+#define MX35_DMA_REQ_SSI1_TX0   29
+
+#define MX35_PROD_SIGNATURE		0x1	/* For MX31 */
+
+#endif /* ifndef __MACH_MX35_H__ */
diff --git a/arch/arm/mach-imx/mx3x.h b/arch/arm/mach-imx/mx3x.h
new file mode 100644
index 0000000..96fb4fb
--- /dev/null
+++ b/arch/arm/mach-imx/mx3x.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __MACH_MX3x_H__
+#define __MACH_MX3x_H__
+
+/*
+ * MX31 memory map:
+ *
+ * Virt		Phys		Size	What
+ * ---------------------------------------------------------------------------
+ * FC000000	43F00000	1M	AIPS 1
+ * FC100000	50000000	1M	SPBA
+ * FC200000	53F00000	1M	AIPS 2
+ * FC500000	60000000	128M	ROMPATCH
+ * FC400000	68000000	128M	AVIC
+ *         	70000000	256M	IPU (MAX M2)
+ *         	80000000	256M	CSD0 SDRAM/DDR
+ *         	90000000	256M	CSD1 SDRAM/DDR
+ *         	A0000000	128M	CS0 Flash
+ *         	A8000000	128M	CS1 Flash
+ *         	B0000000	32M	CS2
+ *         	B2000000	32M	CS3
+ * F4000000	B4000000	32M	CS4
+ *         	B6000000	32M	CS5
+ * FC320000	B8000000	64K	NAND, SDRAM, WEIM, M3IF, EMI controllers
+ *         	C0000000	64M	PCMCIA/CF
+ */
+
+/*
+ * L2CC
+ */
+#define MX3x_L2CC_BASE_ADDR		0x30000000
+#define MX3x_L2CC_SIZE			SZ_1M
+
+/*
+ * AIPS 1
+ */
+#define MX3x_AIPS1_BASE_ADDR		0x43f00000
+#define MX3x_AIPS1_SIZE			SZ_1M
+#define MX3x_MAX_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x04000)
+#define MX3x_EVTMON_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x08000)
+#define MX3x_CLKCTL_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x0c000)
+#define MX3x_ETB_SLOT4_BASE_ADDR		(MX3x_AIPS1_BASE_ADDR + 0x10000)
+#define MX3x_ETB_SLOT5_BASE_ADDR		(MX3x_AIPS1_BASE_ADDR + 0x14000)
+#define MX3x_ECT_CTIO_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x18000)
+#define MX3x_I2C_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x80000)
+#define MX3x_I2C3_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x84000)
+#define MX3x_UART1_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x90000)
+#define MX3x_UART2_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x94000)
+#define MX3x_I2C2_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x98000)
+#define MX3x_OWIRE_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x9c000)
+#define MX3x_SSI1_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0xa0000)
+#define MX3x_CSPI1_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0xa4000)
+#define MX3x_KPP_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0xa8000)
+#define MX3x_IOMUXC_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0xac000)
+#define MX3x_ECT_IP1_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0xb8000)
+#define MX3x_ECT_IP2_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0xbc000)
+
+/*
+ * SPBA global module enabled #0
+ */
+#define MX3x_SPBA0_BASE_ADDR		0x50000000
+#define MX3x_SPBA0_SIZE			SZ_1M
+#define MX3x_UART3_BASE_ADDR			(MX3x_SPBA0_BASE_ADDR + 0x0c000)
+#define MX3x_CSPI2_BASE_ADDR			(MX3x_SPBA0_BASE_ADDR + 0x10000)
+#define MX3x_SSI2_BASE_ADDR			(MX3x_SPBA0_BASE_ADDR + 0x14000)
+#define MX3x_ATA_DMA_BASE_ADDR			(MX3x_SPBA0_BASE_ADDR + 0x20000)
+#define MX3x_MSHC1_BASE_ADDR			(MX3x_SPBA0_BASE_ADDR + 0x24000)
+#define MX3x_SPBA_CTRL_BASE_ADDR		(MX3x_SPBA0_BASE_ADDR + 0x3c000)
+
+/*
+ * AIPS 2
+ */
+#define MX3x_AIPS2_BASE_ADDR		0x53f00000
+#define MX3x_AIPS2_SIZE			SZ_1M
+#define MX3x_CCM_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0x80000)
+#define MX3x_GPT1_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0x90000)
+#define MX3x_EPIT1_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0x94000)
+#define MX3x_EPIT2_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0x98000)
+#define MX3x_GPIO3_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xa4000)
+#define MX3x_SCC_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xac000)
+#define MX3x_RNGA_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xb0000)
+#define MX3x_IPU_CTRL_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xc0000)
+#define MX3x_AUDMUX_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xc4000)
+#define MX3x_GPIO1_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xcc000)
+#define MX3x_GPIO2_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xd0000)
+#define MX3x_SDMA_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xd4000)
+#define MX3x_RTC_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xd8000)
+#define MX3x_WDOG_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xdc000)
+#define MX3x_PWM_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xe0000)
+#define MX3x_RTIC_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xec000)
+
+/*
+ * ROMP and AVIC
+ */
+#define MX3x_ROMP_BASE_ADDR		0x60000000
+#define MX3x_ROMP_SIZE			SZ_1M
+
+#define MX3x_AVIC_BASE_ADDR		0x68000000
+#define MX3x_AVIC_SIZE			SZ_1M
+
+/*
+ * Memory regions and CS
+ */
+#define MX3x_IPU_MEM_BASE_ADDR		0x70000000
+#define MX3x_CSD0_BASE_ADDR		0x80000000
+#define MX3x_CSD1_BASE_ADDR		0x90000000
+
+#define MX3x_CS0_BASE_ADDR		0xa0000000
+#define MX3x_CS1_BASE_ADDR		0xa8000000
+#define MX3x_CS2_BASE_ADDR		0xb0000000
+#define MX3x_CS3_BASE_ADDR		0xb2000000
+
+#define MX3x_CS4_BASE_ADDR		0xb4000000
+#define MX3x_CS4_BASE_ADDR_VIRT		0xf6000000
+#define MX3x_CS4_SIZE			SZ_32M
+
+#define MX3x_CS5_BASE_ADDR		0xb6000000
+#define MX3x_CS5_BASE_ADDR_VIRT		0xf8000000
+#define MX3x_CS5_SIZE			SZ_32M
+
+/*
+ * NAND, SDRAM, WEIM, M3IF, EMI controllers
+ */
+#define MX3x_X_MEMC_BASE_ADDR		0xb8000000
+#define MX3x_X_MEMC_SIZE		SZ_64K
+#define MX3x_ESDCTL_BASE_ADDR			(MX3x_X_MEMC_BASE_ADDR + 0x1000)
+#define MX3x_WEIM_BASE_ADDR			(MX3x_X_MEMC_BASE_ADDR + 0x2000)
+#define MX3x_M3IF_BASE_ADDR			(MX3x_X_MEMC_BASE_ADDR + 0x3000)
+#define MX3x_EMI_CTL_BASE_ADDR			(MX3x_X_MEMC_BASE_ADDR + 0x4000)
+#define MX3x_PCMCIA_CTL_BASE_ADDR		MX3x_EMI_CTL_BASE_ADDR
+
+#define MX3x_PCMCIA_MEM_BASE_ADDR	0xbc000000
+
+/*
+ * Interrupt numbers
+ */
+#include <asm/irq.h>
+#define MX3x_INT_I2C3		(NR_IRQS_LEGACY + 3)
+#define MX3x_INT_I2C2		(NR_IRQS_LEGACY + 4)
+#define MX3x_INT_RTIC		(NR_IRQS_LEGACY + 6)
+#define MX3x_INT_I2C		(NR_IRQS_LEGACY + 10)
+#define MX3x_INT_CSPI2		(NR_IRQS_LEGACY + 13)
+#define MX3x_INT_CSPI1		(NR_IRQS_LEGACY + 14)
+#define MX3x_INT_ATA		(NR_IRQS_LEGACY + 15)
+#define MX3x_INT_UART3		(NR_IRQS_LEGACY + 18)
+#define MX3x_INT_IIM		(NR_IRQS_LEGACY + 19)
+#define MX3x_INT_RNGA		(NR_IRQS_LEGACY + 22)
+#define MX3x_INT_EVTMON		(NR_IRQS_LEGACY + 23)
+#define MX3x_INT_KPP		(NR_IRQS_LEGACY + 24)
+#define MX3x_INT_RTC		(NR_IRQS_LEGACY + 25)
+#define MX3x_INT_PWM		(NR_IRQS_LEGACY + 26)
+#define MX3x_INT_EPIT2		(NR_IRQS_LEGACY + 27)
+#define MX3x_INT_EPIT1		(NR_IRQS_LEGACY + 28)
+#define MX3x_INT_GPT		(NR_IRQS_LEGACY + 29)
+#define MX3x_INT_POWER_FAIL	(NR_IRQS_LEGACY + 30)
+#define MX3x_INT_UART2		(NR_IRQS_LEGACY + 32)
+#define MX3x_INT_NANDFC		(NR_IRQS_LEGACY + 33)
+#define MX3x_INT_SDMA		(NR_IRQS_LEGACY + 34)
+#define MX3x_INT_MSHC1		(NR_IRQS_LEGACY + 39)
+#define MX3x_INT_IPU_ERR	(NR_IRQS_LEGACY + 41)
+#define MX3x_INT_IPU_SYN	(NR_IRQS_LEGACY + 42)
+#define MX3x_INT_UART1		(NR_IRQS_LEGACY + 45)
+#define MX3x_INT_ECT		(NR_IRQS_LEGACY + 48)
+#define MX3x_INT_SCC_SCM	(NR_IRQS_LEGACY + 49)
+#define MX3x_INT_SCC_SMN	(NR_IRQS_LEGACY + 50)
+#define MX3x_INT_GPIO2		(NR_IRQS_LEGACY + 51)
+#define MX3x_INT_GPIO1		(NR_IRQS_LEGACY + 52)
+#define MX3x_INT_WDOG		(NR_IRQS_LEGACY + 55)
+#define MX3x_INT_GPIO3		(NR_IRQS_LEGACY + 56)
+#define MX3x_INT_EXT_POWER	(NR_IRQS_LEGACY + 58)
+#define MX3x_INT_EXT_TEMPER	(NR_IRQS_LEGACY + 59)
+#define MX3x_INT_EXT_SENSOR60	(NR_IRQS_LEGACY + 60)
+#define MX3x_INT_EXT_SENSOR61	(NR_IRQS_LEGACY + 61)
+#define MX3x_INT_EXT_WDOG	(NR_IRQS_LEGACY + 62)
+#define MX3x_INT_EXT_TV		(NR_IRQS_LEGACY + 63)
+
+#define MX3x_PROD_SIGNATURE		0x1	/* For MX31 */
+
+/* Mandatory defines used globally */
+
+#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
+extern int mx35_revision(void);
+extern int mx31_revision(void);
+#endif
+
+#endif /* ifndef __MACH_MX3x_H__ */
diff --git a/arch/arm/mach-imx/mx50.h b/arch/arm/mach-imx/mx50.h
new file mode 100644
index 0000000..09ac19c
--- /dev/null
+++ b/arch/arm/mach-imx/mx50.h
@@ -0,0 +1,290 @@
+#ifndef __MACH_MX50_H__
+#define __MACH_MX50_H__
+
+/*
+ * IROM
+ */
+#define MX50_IROM_BASE_ADDR		0x0
+#define MX50_IROM_SIZE			SZ_64K
+
+/* TZIC */
+#define MX50_TZIC_BASE_ADDR		0x0fffc000
+#define MX50_TZIC_SIZE			SZ_16K
+
+/*
+ * IRAM
+ */
+#define MX50_IRAM_BASE_ADDR	0xf8000000	/* internal ram */
+#define MX50_IRAM_PARTITIONS	16
+#define MX50_IRAM_SIZE		(MX50_IRAM_PARTITIONS * SZ_8K)	/* 128KB */
+
+/*
+ * Databahn
+ */
+#define MX50_DATABAHN_BASE_ADDR			0x14000000
+
+/*
+ * Graphics Memory of GPU
+ */
+#define MX50_GPU2D_BASE_ADDR		0x20000000
+
+#define MX50_DEBUG_BASE_ADDR		0x40000000
+#define MX50_DEBUG_SIZE			SZ_1M
+#define MX50_ETB_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00001000)
+#define MX50_ETM_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00002000)
+#define MX50_TPIU_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00003000)
+#define MX50_CTI0_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00004000)
+#define MX50_CTI1_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00005000)
+#define MX50_CTI2_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00006000)
+#define MX50_CTI3_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00007000)
+#define MX50_CORTEX_DBG_BASE_ADDR	(MX50_DEBUG_BASE_ADDR + 0x00008000)
+
+#define MX50_APBHDMA_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01000000)
+#define MX50_OCOTP_CTRL_BASE_ADDR	(MX50_DEBUG_BASE_ADDR + 0x01002000)
+#define MX50_DIGCTL_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01004000)
+#define MX50_GPMI_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01006000)
+#define MX50_BCH_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01008000)
+#define MX50_ELCDIF_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x0100a000)
+#define MX50_EPXP_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x0100c000)
+#define MX50_DCP_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x0100e000)
+#define MX50_EPDC_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01010000)
+#define MX50_QOSC_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01012000)
+#define MX50_PERFMON_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01014000)
+#define MX50_SSP_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01016000)
+#define MX50_ANATOP_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01018000)
+#define MX50_NIC_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x08000000)
+
+/*
+ * SPBA global module enabled #0
+ */
+#define MX50_SPBA0_BASE_ADDR		0x50000000
+#define MX50_SPBA0_SIZE			SZ_1M
+
+#define MX50_MMC_SDHC1_BASE_ADDR	(MX50_SPBA0_BASE_ADDR + 0x00004000)
+#define MX50_MMC_SDHC2_BASE_ADDR	(MX50_SPBA0_BASE_ADDR + 0x00008000)
+#define MX50_UART3_BASE_ADDR		(MX50_SPBA0_BASE_ADDR + 0x0000c000)
+#define MX50_CSPI1_BASE_ADDR		(MX50_SPBA0_BASE_ADDR + 0x00010000)
+#define MX50_SSI2_BASE_ADDR		(MX50_SPBA0_BASE_ADDR + 0x00014000)
+#define MX50_MMC_SDHC3_BASE_ADDR	(MX50_SPBA0_BASE_ADDR + 0x00020000)
+#define MX50_MMC_SDHC4_BASE_ADDR	(MX50_SPBA0_BASE_ADDR + 0x00024000)
+
+/*
+ * AIPS 1
+ */
+#define MX50_AIPS1_BASE_ADDR	0x53f00000
+#define MX50_AIPS1_SIZE		SZ_1M
+
+#define MX50_OTG_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00080000)
+#define MX50_GPIO1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00084000)
+#define MX50_GPIO2_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00088000)
+#define MX50_GPIO3_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x0008c000)
+#define MX50_GPIO4_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00090000)
+#define MX50_KPP_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00094000)
+#define MX50_WDOG_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00098000)
+#define MX50_GPT1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000a0000)
+#define MX50_SRTC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000a4000)
+#define MX50_IOMUXC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000a8000)
+#define MX50_EPIT1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000ac000)
+#define MX50_PWM1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000b4000)
+#define MX50_PWM2_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000b8000)
+#define MX50_UART1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000bc000)
+#define MX50_UART2_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000c0000)
+#define MX50_SRC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000d0000)
+#define MX50_CCM_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000d4000)
+#define MX50_GPC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000d8000)
+#define MX50_GPIO5_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000dc000)
+#define MX50_GPIO6_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000e0000)
+#define MX50_I2C3_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000ec000)
+#define MX50_UART4_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000f0000)
+
+#define MX50_MSHC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000f4000)
+#define MX50_RNGB_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000f8000)
+
+/*
+ * AIPS 2
+ */
+#define MX50_AIPS2_BASE_ADDR	0x63f00000
+#define MX50_AIPS2_SIZE		SZ_1M
+
+#define MX50_PLL1_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00080000)
+#define MX50_PLL2_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00084000)
+#define MX50_PLL3_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00088000)
+#define MX50_UART5_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00090000)
+#define MX50_AHBMAX_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00094000)
+#define MX50_ARM_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000a0000)
+#define MX50_OWIRE_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000a4000)
+#define MX50_CSPI2_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000ac000)
+#define MX50_SDMA_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000b0000)
+#define MX50_ROMCP_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000b8000)
+#define MX50_CSPI3_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000c0000)
+#define MX50_I2C2_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000c4000)
+#define MX50_I2C1_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000c8000)
+#define MX50_SSI1_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000cc000)
+#define MX50_AUDMUX_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000d0000)
+#define MX50_WEIM_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000d8000)
+#define MX50_FEC_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000ec000)
+
+/*
+ * Memory regions and CS
+ */
+#define MX50_CSD0_BASE_ADDR		0x70000000
+#define MX50_CSD1_BASE_ADDR		0xb0000000
+#define MX50_CS0_BASE_ADDR		0xf0000000
+
+#define MX50_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX50_IO_ADDRESS(x)		IOMEM(MX50_IO_P2V(x))
+
+/*
+ * defines for SPBA modules
+ */
+#define MX50_SPBA_SDHC1		0x04
+#define MX50_SPBA_SDHC2		0x08
+#define MX50_SPBA_UART3		0x0c
+#define MX50_SPBA_CSPI1		0x10
+#define MX50_SPBA_SSI2		0x14
+#define MX50_SPBA_SDHC3		0x20
+#define MX50_SPBA_SDHC4		0x24
+#define MX50_SPBA_SPDIF		0x28
+#define MX50_SPBA_ATA		0x30
+#define MX50_SPBA_SLIM		0x34
+#define MX50_SPBA_HSI2C		0x38
+#define MX50_SPBA_CTRL		0x3c
+
+/*
+ * DMA request assignments
+ */
+#define MX50_DMA_REQ_GPC		1
+#define MX50_DMA_REQ_ATA_UART4_RX	2
+#define MX50_DMA_REQ_ATA_UART4_TX	3
+#define MX50_DMA_REQ_CSPI1_RX		6
+#define MX50_DMA_REQ_CSPI1_TX		7
+#define MX50_DMA_REQ_CSPI2_RX		8
+#define MX50_DMA_REQ_CSPI2_TX		9
+#define MX50_DMA_REQ_I2C3_SDHC3		10
+#define MX50_DMA_REQ_SDHC4		11
+#define MX50_DMA_REQ_UART2_FIRI_RX	12
+#define MX50_DMA_REQ_UART2_FIRI_TX	13
+#define MX50_DMA_REQ_EXT0		14
+#define MX50_DMA_REQ_EXT1		15
+#define MX50_DMA_REQ_UART5_RX		16
+#define MX50_DMA_REQ_UART5_TX		17
+#define MX50_DMA_REQ_UART1_RX		18
+#define MX50_DMA_REQ_UART1_TX		19
+#define MX50_DMA_REQ_I2C1_SDHC1		20
+#define MX50_DMA_REQ_I2C2_SDHC2		21
+#define MX50_DMA_REQ_SSI2_RX2		22
+#define MX50_DMA_REQ_SSI2_TX2		23
+#define MX50_DMA_REQ_SSI2_RX1		24
+#define MX50_DMA_REQ_SSI2_TX1		25
+#define MX50_DMA_REQ_SSI1_RX2		26
+#define MX50_DMA_REQ_SSI1_TX2		27
+#define MX50_DMA_REQ_SSI1_RX1		28
+#define MX50_DMA_REQ_SSI1_TX1		29
+#define MX50_DMA_REQ_CSPI_RX		38
+#define MX50_DMA_REQ_CSPI_TX		39
+#define MX50_DMA_REQ_UART3_RX		42
+#define MX50_DMA_REQ_UART3_TX		43
+
+/*
+ * Interrupt numbers
+ */
+#include <asm/irq.h>
+#define MX50_INT_MMC_SDHC1	(NR_IRQS_LEGACY + 1)
+#define MX50_INT_MMC_SDHC2	(NR_IRQS_LEGACY + 2)
+#define MX50_INT_MMC_SDHC3	(NR_IRQS_LEGACY + 3)
+#define MX50_INT_MMC_SDHC4	(NR_IRQS_LEGACY + 4)
+#define MX50_INT_DAP		(NR_IRQS_LEGACY + 5)
+#define MX50_INT_SDMA		(NR_IRQS_LEGACY + 6)
+#define MX50_INT_IOMUX		(NR_IRQS_LEGACY + 7)
+#define MX50_INT_UART4		(NR_IRQS_LEGACY + 13)
+#define MX50_INT_USB_H1		(NR_IRQS_LEGACY + 14)
+#define MX50_INT_USB_OTG	(NR_IRQS_LEGACY + 18)
+#define MX50_INT_DATABAHN	(NR_IRQS_LEGACY + 19)
+#define MX50_INT_ELCDIF		(NR_IRQS_LEGACY + 20)
+#define MX50_INT_EPXP		(NR_IRQS_LEGACY + 21)
+#define MX50_INT_SRTC_NTZ	(NR_IRQS_LEGACY + 24)
+#define MX50_INT_SRTC_TZ	(NR_IRQS_LEGACY + 25)
+#define MX50_INT_EPDC		(NR_IRQS_LEGACY + 27)
+#define MX50_INT_NIC		(NR_IRQS_LEGACY + 28)
+#define MX50_INT_SSI1		(NR_IRQS_LEGACY + 29)
+#define MX50_INT_SSI2		(NR_IRQS_LEGACY + 30)
+#define MX50_INT_UART1		(NR_IRQS_LEGACY + 31)
+#define MX50_INT_UART2		(NR_IRQS_LEGACY + 32)
+#define MX50_INT_UART3		(NR_IRQS_LEGACY + 33)
+#define MX50_INT_RESV34		(NR_IRQS_LEGACY + 34)
+#define MX50_INT_RESV35		(NR_IRQS_LEGACY + 35)
+#define MX50_INT_CSPI1		(NR_IRQS_LEGACY + 36)
+#define MX50_INT_CSPI2		(NR_IRQS_LEGACY + 37)
+#define MX50_INT_CSPI		(NR_IRQS_LEGACY + 38)
+#define MX50_INT_GPT		(NR_IRQS_LEGACY + 39)
+#define MX50_INT_EPIT1		(NR_IRQS_LEGACY + 40)
+#define MX50_INT_GPIO1_INT7	(NR_IRQS_LEGACY + 42)
+#define MX50_INT_GPIO1_INT6	(NR_IRQS_LEGACY + 43)
+#define MX50_INT_GPIO1_INT5	(NR_IRQS_LEGACY + 44)
+#define MX50_INT_GPIO1_INT4	(NR_IRQS_LEGACY + 45)
+#define MX50_INT_GPIO1_INT3	(NR_IRQS_LEGACY + 46)
+#define MX50_INT_GPIO1_INT2	(NR_IRQS_LEGACY + 47)
+#define MX50_INT_GPIO1_INT1	(NR_IRQS_LEGACY + 48)
+#define MX50_INT_GPIO1_INT0	(NR_IRQS_LEGACY + 49)
+#define MX50_INT_GPIO1_LOW	(NR_IRQS_LEGACY + 50)
+#define MX50_INT_GPIO1_HIGH	(NR_IRQS_LEGACY + 51)
+#define MX50_INT_GPIO2_LOW	(NR_IRQS_LEGACY + 52)
+#define MX50_INT_GPIO2_HIGH	(NR_IRQS_LEGACY + 53)
+#define MX50_INT_GPIO3_LOW	(NR_IRQS_LEGACY + 54)
+#define MX50_INT_GPIO3_HIGH	(NR_IRQS_LEGACY + 55)
+#define MX50_INT_GPIO4_LOW	(NR_IRQS_LEGACY + 56)
+#define MX50_INT_GPIO4_HIGH	(NR_IRQS_LEGACY + 57)
+#define MX50_INT_WDOG1		(NR_IRQS_LEGACY + 58)
+#define MX50_INT_KPP		(NR_IRQS_LEGACY + 60)
+#define MX50_INT_PWM1		(NR_IRQS_LEGACY + 61)
+#define MX50_INT_I2C1		(NR_IRQS_LEGACY + 62)
+#define MX50_INT_I2C2		(NR_IRQS_LEGACY + 63)
+#define MX50_INT_I2C3		(NR_IRQS_LEGACY + 64)
+#define MX50_INT_RESV65		(NR_IRQS_LEGACY + 65)
+#define MX50_INT_DCDC		(NR_IRQS_LEGACY + 66)
+#define MX50_INT_THERMAL_ALARM	(NR_IRQS_LEGACY + 67)
+#define MX50_INT_ANA3		(NR_IRQS_LEGACY + 68)
+#define MX50_INT_ANA4		(NR_IRQS_LEGACY + 69)
+#define MX50_INT_CCM1		(NR_IRQS_LEGACY + 71)
+#define MX50_INT_CCM2		(NR_IRQS_LEGACY + 72)
+#define MX50_INT_GPC1		(NR_IRQS_LEGACY + 73)
+#define MX50_INT_GPC2		(NR_IRQS_LEGACY + 74)
+#define MX50_INT_SRC		(NR_IRQS_LEGACY + 75)
+#define MX50_INT_NM		(NR_IRQS_LEGACY + 76)
+#define MX50_INT_PMU		(NR_IRQS_LEGACY + 77)
+#define MX50_INT_CTI_IRQ	(NR_IRQS_LEGACY + 78)
+#define MX50_INT_CTI1_TG0	(NR_IRQS_LEGACY + 79)
+#define MX50_INT_CTI1_TG1	(NR_IRQS_LEGACY + 80)
+#define MX50_INT_GPU2_IRQ	(NR_IRQS_LEGACY + 84)
+#define MX50_INT_GPU2_BUSY	(NR_IRQS_LEGACY + 85)
+#define MX50_INT_UART5		(NR_IRQS_LEGACY + 86)
+#define MX50_INT_FEC		(NR_IRQS_LEGACY + 87)
+#define MX50_INT_OWIRE		(NR_IRQS_LEGACY + 88)
+#define MX50_INT_CTI1_TG2	(NR_IRQS_LEGACY + 89)
+#define MX50_INT_SJC		(NR_IRQS_LEGACY + 90)
+#define MX50_INT_DCP_CHAN1_3	(NR_IRQS_LEGACY + 91)
+#define MX50_INT_DCP_CHAN0	(NR_IRQS_LEGACY + 92)
+#define MX50_INT_PWM2		(NR_IRQS_LEGACY + 94)
+#define MX50_INT_RNGB		(NR_IRQS_LEGACY + 97)
+#define MX50_INT_CTI1_TG3	(NR_IRQS_LEGACY + 98)
+#define MX50_INT_RAWNAND_BCH	(NR_IRQS_LEGACY + 100)
+#define MX50_INT_RAWNAND_GPMI	(NR_IRQS_LEGACY + 102)
+#define MX50_INT_GPIO5_LOW	(NR_IRQS_LEGACY + 103)
+#define MX50_INT_GPIO5_HIGH	(NR_IRQS_LEGACY + 104)
+#define MX50_INT_GPIO6_LOW	(NR_IRQS_LEGACY + 105)
+#define MX50_INT_GPIO6_HIGH	(NR_IRQS_LEGACY + 106)
+#define MX50_INT_MSHC		(NR_IRQS_LEGACY + 109)
+#define MX50_INT_APBHDMA_CHAN0	(NR_IRQS_LEGACY + 110)
+#define MX50_INT_APBHDMA_CHAN1	(NR_IRQS_LEGACY + 111)
+#define MX50_INT_APBHDMA_CHAN2	(NR_IRQS_LEGACY + 112)
+#define MX50_INT_APBHDMA_CHAN3	(NR_IRQS_LEGACY + 113)
+#define MX50_INT_APBHDMA_CHAN4	(NR_IRQS_LEGACY + 114)
+#define MX50_INT_APBHDMA_CHAN5	(NR_IRQS_LEGACY + 115)
+#define MX50_INT_APBHDMA_CHAN6	(NR_IRQS_LEGACY + 116)
+#define MX50_INT_APBHDMA_CHAN7	(NR_IRQS_LEGACY + 117)
+
+#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
+extern int mx50_revision(void);
+#endif
+
+#endif /* ifndef __MACH_MX50_H__ */
diff --git a/arch/arm/mach-imx/mx51.h b/arch/arm/mach-imx/mx51.h
new file mode 100644
index 0000000..af844f7
--- /dev/null
+++ b/arch/arm/mach-imx/mx51.h
@@ -0,0 +1,346 @@
+#ifndef __MACH_MX51_H__
+#define __MACH_MX51_H__
+
+/*
+ * IROM
+ */
+#define MX51_IROM_BASE_ADDR		0x0
+#define MX51_IROM_SIZE			SZ_64K
+
+/*
+ * IRAM
+ */
+#define MX51_IRAM_BASE_ADDR		0x1ffe0000	/* internal ram */
+#define MX51_IRAM_PARTITIONS		16
+#define MX51_IRAM_SIZE		(MX51_IRAM_PARTITIONS * SZ_8K)	/* 128KB */
+
+#define MX51_GPU_BASE_ADDR		0x20000000
+#define MX51_GPU_CTRL_BASE_ADDR		0x30000000
+#define MX51_IPU_CTRL_BASE_ADDR		0x40000000
+
+/*
+ * SPBA global module enabled #0
+ */
+#define MX51_SPBA0_BASE_ADDR		0x70000000
+#define MX51_SPBA0_SIZE			SZ_1M
+
+#define MX51_ESDHC1_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x04000)
+#define MX51_ESDHC2_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x08000)
+#define MX51_UART3_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x0c000)
+#define MX51_ECSPI1_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x10000)
+#define MX51_SSI2_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x14000)
+#define MX51_ESDHC3_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x20000)
+#define MX51_ESDHC4_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x24000)
+#define MX51_SPDIF_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x28000)
+#define MX51_ATA_DMA_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x30000)
+#define MX51_SLIM_DMA_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x34000)
+#define MX51_HSI2C_DMA_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x38000)
+#define MX51_SPBA_CTRL_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x3c000)
+
+/*
+ * AIPS 1
+ */
+#define MX51_AIPS1_BASE_ADDR		0x73f00000
+#define MX51_AIPS1_SIZE			SZ_1M
+
+#define MX51_USB_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x80000)
+#define MX51_USB_OTG_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0000)
+#define MX51_USB_HS1_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0200)
+#define MX51_USB_HS2_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0400)
+#define MX51_GPIO1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x84000)
+#define MX51_GPIO2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x88000)
+#define MX51_GPIO3_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x8c000)
+#define MX51_GPIO4_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x90000)
+#define MX51_KPP_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x94000)
+#define MX51_WDOG1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x98000)
+#define MX51_WDOG2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x9c000)
+#define MX51_GPT1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xa0000)
+#define MX51_SRTC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xa4000)
+#define MX51_IOMUXC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xa8000)
+#define MX51_EPIT1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xac000)
+#define MX51_EPIT2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xb0000)
+#define MX51_PWM1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xb4000)
+#define MX51_PWM2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xb8000)
+#define MX51_UART1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xbc000)
+#define MX51_UART2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xc0000)
+#define MX51_SRC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xd0000)
+#define MX51_CCM_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xd4000)
+#define MX51_GPC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xd8000)
+
+/*
+ * AIPS 2
+ */
+#define MX51_AIPS2_BASE_ADDR		0x83f00000
+#define MX51_AIPS2_SIZE			SZ_1M
+
+#define MX51_PLL1_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x80000)
+#define MX51_PLL2_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x84000)
+#define MX51_PLL3_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x88000)
+#define MX51_AHBMAX_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x94000)
+#define MX51_IIM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x98000)
+#define MX51_CSU_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x9c000)
+#define MX51_ARM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xa0000)
+#define MX51_OWIRE_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xa4000)
+#define MX51_FIRI_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xa8000)
+#define MX51_ECSPI2_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xac000)
+#define MX51_SDMA_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xb0000)
+#define MX51_SCC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xb4000)
+#define MX51_ROMCP_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xb8000)
+#define MX51_RTIC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xbc000)
+#define MX51_CSPI_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xc0000)
+#define MX51_I2C2_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xc4000)
+#define MX51_I2C1_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xc8000)
+#define MX51_SSI1_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xcc000)
+#define MX51_AUDMUX_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xd0000)
+#define MX51_M4IF_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xd8000)
+#define MX51_ESDCTL_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xd9000)
+#define MX51_WEIM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xda000)
+#define MX51_NFC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xdb000)
+#define MX51_EMI_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xdbf00)
+#define MX51_MIPI_HSC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xdc000)
+#define MX51_ATA_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xe0000)
+#define MX51_SIM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xe4000)
+#define MX51_SSI3_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xe8000)
+#define MX51_FEC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xec000)
+#define MX51_TVE_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xf0000)
+#define MX51_VPU_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xf4000)
+#define MX51_SAHARA_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xf8000)
+
+#define MX51_CSD0_BASE_ADDR		0x90000000
+#define MX51_CSD1_BASE_ADDR		0xa0000000
+#define MX51_CS0_BASE_ADDR		0xb0000000
+#define MX51_CS1_BASE_ADDR		0xb8000000
+#define MX51_CS2_BASE_ADDR		0xc0000000
+#define MX51_CS3_BASE_ADDR		0xc8000000
+#define MX51_CS4_BASE_ADDR		0xcc000000
+#define MX51_CS5_BASE_ADDR		0xce000000
+
+/*
+ * NFC
+ */
+#define MX51_NFC_AXI_BASE_ADDR		0xcfff0000	/* NAND flash AXI */
+#define MX51_NFC_AXI_SIZE		SZ_64K
+
+#define MX51_GPU2D_BASE_ADDR		0xd0000000
+#define MX51_TZIC_BASE_ADDR		0xe0000000
+#define MX51_TZIC_SIZE			SZ_16K
+
+#define MX51_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX51_IO_ADDRESS(x)		IOMEM(MX51_IO_P2V(x))
+
+/*
+ * defines for SPBA modules
+ */
+#define MX51_SPBA_SDHC1	0x04
+#define MX51_SPBA_SDHC2	0x08
+#define MX51_SPBA_UART3	0x0c
+#define MX51_SPBA_CSPI1	0x10
+#define MX51_SPBA_SSI2	0x14
+#define MX51_SPBA_SDHC3	0x20
+#define MX51_SPBA_SDHC4	0x24
+#define MX51_SPBA_SPDIF	0x28
+#define MX51_SPBA_ATA	0x30
+#define MX51_SPBA_SLIM	0x34
+#define MX51_SPBA_HSI2C	0x38
+#define MX51_SPBA_CTRL	0x3c
+
+/*
+ * Defines for modules using static and dynamic DMA channels
+ */
+#define MX51_MXC_DMA_CHANNEL_IRAM	30
+#define MX51_MXC_DMA_CHANNEL_SPDIF_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_UART1_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_UART1_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_UART2_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_UART2_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_UART3_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_UART3_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_MMC1	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_MMC2	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_SSI1_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_SSI1_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_SSI2_RX	MXC_DMA_DYNAMIC_CHANNEL
+#ifdef CONFIG_SDMA_IRAM
+#define MX51_MXC_DMA_CHANNEL_SSI2_TX	(MX51_MXC_DMA_CHANNEL_IRAM + 1)
+#else				/*CONFIG_SDMA_IRAM */
+#define MX51_MXC_DMA_CHANNEL_SSI2_TX	MXC_DMA_DYNAMIC_CHANNEL
+#endif				/*CONFIG_SDMA_IRAM */
+#define MX51_MXC_DMA_CHANNEL_CSPI1_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_CSPI1_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_CSPI2_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_CSPI2_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_CSPI3_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_CSPI3_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_ATA_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_ATA_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_MEMORY	MXC_DMA_DYNAMIC_CHANNEL
+
+#define MX51_IS_MEM_DEVICE_NONSHARED(x)		0
+
+/*
+ * DMA request assignments
+ */
+#define MX51_DMA_REQ_VPU		0
+#define MX51_DMA_REQ_GPC		1
+#define MX51_DMA_REQ_ATA_RX		2
+#define MX51_DMA_REQ_ATA_TX		3
+#define MX51_DMA_REQ_ATA_TX_END		4
+#define MX51_DMA_REQ_SLIM_B		5
+#define MX51_DMA_REQ_CSPI1_RX		6
+#define MX51_DMA_REQ_CSPI1_TX		7
+#define MX51_DMA_REQ_CSPI2_RX		8
+#define MX51_DMA_REQ_CSPI2_TX		9
+#define MX51_DMA_REQ_HS_I2C_TX		10
+#define MX51_DMA_REQ_HS_I2C_RX		11
+#define MX51_DMA_REQ_FIRI_RX		12
+#define MX51_DMA_REQ_FIRI_TX		13
+#define MX51_DMA_REQ_EXTREQ1		14
+#define MX51_DMA_REQ_GPU		15
+#define MX51_DMA_REQ_UART2_RX		16
+#define MX51_DMA_REQ_UART2_TX		17
+#define MX51_DMA_REQ_UART1_RX		18
+#define MX51_DMA_REQ_UART1_TX		19
+#define MX51_DMA_REQ_SDHC1		20
+#define MX51_DMA_REQ_SDHC2		21
+#define MX51_DMA_REQ_SSI2_RX1		22
+#define MX51_DMA_REQ_SSI2_TX1		23
+#define MX51_DMA_REQ_SSI2_RX0		24
+#define MX51_DMA_REQ_SSI2_TX0		25
+#define MX51_DMA_REQ_SSI1_RX1		26
+#define MX51_DMA_REQ_SSI1_TX1		27
+#define MX51_DMA_REQ_SSI1_RX0		28
+#define MX51_DMA_REQ_SSI1_TX0		29
+#define MX51_DMA_REQ_EMI_RD		30
+#define MX51_DMA_REQ_CTI2_0		31
+#define MX51_DMA_REQ_EMI_WR		32
+#define MX51_DMA_REQ_CTI2_1		33
+#define MX51_DMA_REQ_EPIT2		34
+#define MX51_DMA_REQ_SSI3_RX1		35
+#define MX51_DMA_REQ_IPU		36
+#define MX51_DMA_REQ_SSI3_TX1		37
+#define MX51_DMA_REQ_CSPI_RX		38
+#define MX51_DMA_REQ_CSPI_TX		39
+#define MX51_DMA_REQ_SDHC3		40
+#define MX51_DMA_REQ_SDHC4		41
+#define MX51_DMA_REQ_SLIM_B_TX		42
+#define MX51_DMA_REQ_UART3_RX		43
+#define MX51_DMA_REQ_UART3_TX		44
+#define MX51_DMA_REQ_SPDIF		45
+#define MX51_DMA_REQ_SSI3_RX0		46
+#define MX51_DMA_REQ_SSI3_TX0		47
+
+/*
+ * Interrupt numbers
+ */
+#include <asm/irq.h>
+#define MX51_INT_BASE			(NR_IRQS_LEGACY + 0)
+#define MX51_INT_RESV0			(NR_IRQS_LEGACY + 0)
+#define MX51_INT_ESDHC1			(NR_IRQS_LEGACY + 1)
+#define MX51_INT_ESDHC2			(NR_IRQS_LEGACY + 2)
+#define MX51_INT_ESDHC3			(NR_IRQS_LEGACY + 3)
+#define MX51_INT_ESDHC4			(NR_IRQS_LEGACY + 4)
+#define MX51_INT_RESV5			(NR_IRQS_LEGACY + 5)
+#define MX51_INT_SDMA			(NR_IRQS_LEGACY + 6)
+#define MX51_INT_IOMUX			(NR_IRQS_LEGACY + 7)
+#define MX51_INT_NFC			(NR_IRQS_LEGACY + 8)
+#define MX51_INT_VPU			(NR_IRQS_LEGACY + 9)
+#define MX51_INT_IPU_ERR		(NR_IRQS_LEGACY + 10)
+#define MX51_INT_IPU_SYN		(NR_IRQS_LEGACY + 11)
+#define MX51_INT_GPU			(NR_IRQS_LEGACY + 12)
+#define MX51_INT_RESV13			(NR_IRQS_LEGACY + 13)
+#define MX51_INT_USB_HS1		(NR_IRQS_LEGACY + 14)
+#define MX51_INT_EMI			(NR_IRQS_LEGACY + 15)
+#define MX51_INT_USB_HS2		(NR_IRQS_LEGACY + 16)
+#define MX51_INT_USB_HS3		(NR_IRQS_LEGACY + 17)
+#define MX51_INT_USB_OTG		(NR_IRQS_LEGACY + 18)
+#define MX51_INT_SAHARA_H0		(NR_IRQS_LEGACY + 19)
+#define MX51_INT_SAHARA_H1		(NR_IRQS_LEGACY + 20)
+#define MX51_INT_SCC_SMN		(NR_IRQS_LEGACY + 21)
+#define MX51_INT_SCC_STZ		(NR_IRQS_LEGACY + 22)
+#define MX51_INT_SCC_SCM		(NR_IRQS_LEGACY + 23)
+#define MX51_INT_SRTC_NTZ		(NR_IRQS_LEGACY + 24)
+#define MX51_INT_SRTC_TZ		(NR_IRQS_LEGACY + 25)
+#define MX51_INT_RTIC			(NR_IRQS_LEGACY + 26)
+#define MX51_INT_CSU			(NR_IRQS_LEGACY + 27)
+#define MX51_INT_SLIM_B			(NR_IRQS_LEGACY + 28)
+#define MX51_INT_SSI1			(NR_IRQS_LEGACY + 29)
+#define MX51_INT_SSI2			(NR_IRQS_LEGACY + 30)
+#define MX51_INT_UART1			(NR_IRQS_LEGACY + 31)
+#define MX51_INT_UART2			(NR_IRQS_LEGACY + 32)
+#define MX51_INT_UART3			(NR_IRQS_LEGACY + 33)
+#define MX51_INT_RESV34			(NR_IRQS_LEGACY + 34)
+#define MX51_INT_RESV35			(NR_IRQS_LEGACY + 35)
+#define MX51_INT_ECSPI1			(NR_IRQS_LEGACY + 36)
+#define MX51_INT_ECSPI2			(NR_IRQS_LEGACY + 37)
+#define MX51_INT_CSPI			(NR_IRQS_LEGACY + 38)
+#define MX51_INT_GPT			(NR_IRQS_LEGACY + 39)
+#define MX51_INT_EPIT1			(NR_IRQS_LEGACY + 40)
+#define MX51_INT_EPIT2			(NR_IRQS_LEGACY + 41)
+#define MX51_INT_GPIO1_INT7		(NR_IRQS_LEGACY + 42)
+#define MX51_INT_GPIO1_INT6		(NR_IRQS_LEGACY + 43)
+#define MX51_INT_GPIO1_INT5		(NR_IRQS_LEGACY + 44)
+#define MX51_INT_GPIO1_INT4		(NR_IRQS_LEGACY + 45)
+#define MX51_INT_GPIO1_INT3		(NR_IRQS_LEGACY + 46)
+#define MX51_INT_GPIO1_INT2		(NR_IRQS_LEGACY + 47)
+#define MX51_INT_GPIO1_INT1		(NR_IRQS_LEGACY + 48)
+#define MX51_INT_GPIO1_INT0		(NR_IRQS_LEGACY + 49)
+#define MX51_INT_GPIO1_LOW		(NR_IRQS_LEGACY + 50)
+#define MX51_INT_GPIO1_HIGH		(NR_IRQS_LEGACY + 51)
+#define MX51_INT_GPIO2_LOW		(NR_IRQS_LEGACY + 52)
+#define MX51_INT_GPIO2_HIGH		(NR_IRQS_LEGACY + 53)
+#define MX51_INT_GPIO3_LOW		(NR_IRQS_LEGACY + 54)
+#define MX51_INT_GPIO3_HIGH		(NR_IRQS_LEGACY + 55)
+#define MX51_INT_GPIO4_LOW		(NR_IRQS_LEGACY + 56)
+#define MX51_INT_GPIO4_HIGH		(NR_IRQS_LEGACY + 57)
+#define MX51_INT_WDOG1			(NR_IRQS_LEGACY + 58)
+#define MX51_INT_WDOG2			(NR_IRQS_LEGACY + 59)
+#define MX51_INT_KPP			(NR_IRQS_LEGACY + 60)
+#define MX51_INT_PWM1			(NR_IRQS_LEGACY + 61)
+#define MX51_INT_I2C1			(NR_IRQS_LEGACY + 62)
+#define MX51_INT_I2C2			(NR_IRQS_LEGACY + 63)
+#define MX51_INT_HS_I2C			(NR_IRQS_LEGACY + 64)
+#define MX51_INT_RESV65			(NR_IRQS_LEGACY + 65)
+#define MX51_INT_RESV66			(NR_IRQS_LEGACY + 66)
+#define MX51_INT_SIM_IPB		(NR_IRQS_LEGACY + 67)
+#define MX51_INT_SIM_DAT		(NR_IRQS_LEGACY + 68)
+#define MX51_INT_IIM			(NR_IRQS_LEGACY + 69)
+#define MX51_INT_ATA			(NR_IRQS_LEGACY + 70)
+#define MX51_INT_CCM1			(NR_IRQS_LEGACY + 71)
+#define MX51_INT_CCM2			(NR_IRQS_LEGACY + 72)
+#define MX51_INT_GPC1			(NR_IRQS_LEGACY + 73)
+#define MX51_INT_GPC2			(NR_IRQS_LEGACY + 74)
+#define MX51_INT_SRC			(NR_IRQS_LEGACY + 75)
+#define MX51_INT_NM			(NR_IRQS_LEGACY + 76)
+#define MX51_INT_PMU			(NR_IRQS_LEGACY + 77)
+#define MX51_INT_CTI_IRQ		(NR_IRQS_LEGACY + 78)
+#define MX51_INT_CTI1_TG0		(NR_IRQS_LEGACY + 79)
+#define MX51_INT_CTI1_TG1		(NR_IRQS_LEGACY + 80)
+#define MX51_INT_MCG_ERR		(NR_IRQS_LEGACY + 81)
+#define MX51_INT_MCG_TMR		(NR_IRQS_LEGACY + 82)
+#define MX51_INT_MCG_FUNC		(NR_IRQS_LEGACY + 83)
+#define MX51_INT_GPU2_IRQ		(NR_IRQS_LEGACY + 84)
+#define MX51_INT_GPU2_BUSY		(NR_IRQS_LEGACY + 85)
+#define MX51_INT_RESV86			(NR_IRQS_LEGACY + 86)
+#define MX51_INT_FEC			(NR_IRQS_LEGACY + 87)
+#define MX51_INT_OWIRE			(NR_IRQS_LEGACY + 88)
+#define MX51_INT_CTI1_TG2		(NR_IRQS_LEGACY + 89)
+#define MX51_INT_SJC			(NR_IRQS_LEGACY + 90)
+#define MX51_INT_SPDIF			(NR_IRQS_LEGACY + 91)
+#define MX51_INT_TVE			(NR_IRQS_LEGACY + 92)
+#define MX51_INT_FIRI			(NR_IRQS_LEGACY + 93)
+#define MX51_INT_PWM2			(NR_IRQS_LEGACY + 94)
+#define MX51_INT_SLIM_EXP		(NR_IRQS_LEGACY + 95)
+#define MX51_INT_SSI3			(NR_IRQS_LEGACY + 96)
+#define MX51_INT_EMI_BOOT		(NR_IRQS_LEGACY + 97)
+#define MX51_INT_CTI1_TG3		(NR_IRQS_LEGACY + 98)
+#define MX51_INT_SMC_RX			(NR_IRQS_LEGACY + 99)
+#define MX51_INT_VPU_IDLE		(NR_IRQS_LEGACY + 100)
+#define MX51_INT_EMI_NFC		(NR_IRQS_LEGACY + 101)
+#define MX51_INT_GPU_IDLE		(NR_IRQS_LEGACY + 102)
+
+#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
+extern int mx51_revision(void);
+extern void mx51_display_revision(void);
+#endif
+
+#endif	/* ifndef __MACH_MX51_H__ */
diff --git a/arch/arm/mach-imx/mx53.h b/arch/arm/mach-imx/mx53.h
new file mode 100644
index 0000000..f829d1c
--- /dev/null
+++ b/arch/arm/mach-imx/mx53.h
@@ -0,0 +1,342 @@
+#ifndef __MACH_MX53_H__
+#define __MACH_MX53_H__
+
+/*
+ * IROM
+ */
+#define MX53_IROM_BASE_ADDR		0x0
+#define MX53_IROM_SIZE			SZ_64K
+
+/* TZIC */
+#define MX53_TZIC_BASE_ADDR		0x0FFFC000
+#define MX53_TZIC_SIZE			SZ_16K
+
+/*
+ * AHCI SATA
+ */
+#define MX53_SATA_BASE_ADDR		0x10000000
+
+/*
+ * NFC
+ */
+#define MX53_NFC_AXI_BASE_ADDR	0xF7FF0000	/* NAND flash AXI */
+#define MX53_NFC_AXI_SIZE		SZ_64K
+
+/*
+ * IRAM
+ */
+#define MX53_IRAM_BASE_ADDR	0xF8000000	/* internal ram */
+#define MX53_IRAM_PARTITIONS	16
+#define MX53_IRAM_SIZE		(MX53_IRAM_PARTITIONS * SZ_8K)	/* 128KB */
+
+/*
+ * Graphics Memory of GPU
+ */
+#define MX53_IPU_CTRL_BASE_ADDR	0x18000000
+#define MX53_GPU2D_BASE_ADDR		0x20000000
+#define MX53_GPU_BASE_ADDR		0x30000000
+#define MX53_GPU_GMEM_BASE_ADDR	0xF8020000
+
+#define MX53_DEBUG_BASE_ADDR		0x40000000
+#define MX53_DEBUG_SIZE		SZ_1M
+#define MX53_ETB_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00001000)
+#define MX53_ETM_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00002000)
+#define MX53_TPIU_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00003000)
+#define MX53_CTI0_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00004000)
+#define MX53_CTI1_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00005000)
+#define MX53_CTI2_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00006000)
+#define MX53_CTI3_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00007000)
+#define MX53_CORTEX_DBG_BASE_ADDR	(MX53_DEBUG_BASE_ADDR + 0x00008000)
+
+/*
+ * SPBA global module enabled #0
+ */
+#define MX53_SPBA0_BASE_ADDR		0x50000000
+#define MX53_SPBA0_SIZE		SZ_1M
+
+#define MX53_ESDHC1_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00004000)
+#define MX53_ESDHC2_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00008000)
+#define MX53_UART3_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x0000C000)
+#define MX53_ECSPI1_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x00010000)
+#define MX53_SSI2_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x00014000)
+#define MX53_ESDHC3_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00020000)
+#define MX53_ESDHC4_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00024000)
+#define MX53_SPDIF_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x00028000)
+#define MX53_ASRC_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x0002C000)
+#define MX53_ATA_DMA_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00030000)
+#define MX53_SLIM_DMA_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00034000)
+#define MX53_HSI2C_DMA_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00038000)
+#define MX53_SPBA_CTRL_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x0003C000)
+
+/*
+ * AIPS 1
+ */
+#define MX53_AIPS1_BASE_ADDR	0x53F00000
+#define MX53_AIPS1_SIZE		SZ_1M
+
+#define MX53_OTG_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00080000)
+#define MX53_GPIO1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00084000)
+#define MX53_GPIO2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00088000)
+#define MX53_GPIO3_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x0008C000)
+#define MX53_GPIO4_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00090000)
+#define MX53_KPP_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00094000)
+#define MX53_WDOG1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00098000)
+#define MX53_WDOG2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x0009C000)
+#define MX53_GPT1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000A0000)
+#define MX53_SRTC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000A4000)
+#define MX53_IOMUXC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000A8000)
+#define MX53_EPIT1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000AC000)
+#define MX53_EPIT2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000B0000)
+#define MX53_PWM1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000B4000)
+#define MX53_PWM2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000B8000)
+#define MX53_UART1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000BC000)
+#define MX53_UART2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000C0000)
+#define MX53_SRC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000D0000)
+#define MX53_CCM_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000D4000)
+#define MX53_GPC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000D8000)
+#define MX53_GPIO5_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000DC000)
+#define MX53_GPIO6_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000E0000)
+#define MX53_GPIO7_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000E4000)
+#define MX53_ATA_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000E8000)
+#define MX53_I2C3_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000EC000)
+#define MX53_UART4_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000F0000)
+
+/*
+ * AIPS 2
+ */
+#define MX53_AIPS2_BASE_ADDR		0x63F00000
+#define MX53_AIPS2_SIZE			SZ_1M
+
+#define MX53_PLL1_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00080000)
+#define MX53_PLL2_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00084000)
+#define MX53_PLL3_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00088000)
+#define MX53_PLL4_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x0008C000)
+#define MX53_UART5_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00090000)
+#define MX53_AHBMAX_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00094000)
+#define MX53_IIM_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00098000)
+#define MX53_CSU_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x0009C000)
+#define MX53_ARM_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000A0000)
+#define MX53_OWIRE_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000A4000)
+#define MX53_FIRI_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000A8000)
+#define MX53_ECSPI2_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000AC000)
+#define MX53_SDMA_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000B0000)
+#define MX53_SCC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000B4000)
+#define MX53_ROMCP_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000B8000)
+#define MX53_RTIC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000BC000)
+#define MX53_CSPI_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000C0000)
+#define MX53_I2C2_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000C4000)
+#define MX53_I2C1_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000C8000)
+#define MX53_SSI1_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000CC000)
+#define MX53_AUDMUX_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000D0000)
+#define MX53_RTC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000D4000)
+#define MX53_M4IF_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000D8000)
+#define MX53_ESDCTL_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000D9000)
+#define MX53_WEIM_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000DA000)
+#define MX53_NFC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000DB000)
+#define MX53_EMI_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000DBF00)
+#define MX53_MIPI_HSC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000DC000)
+#define MX53_MLB_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000E4000)
+#define MX53_SSI3_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000E8000)
+#define MX53_FEC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000EC000)
+#define MX53_TVE_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000F0000)
+#define MX53_VPU_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000F4000)
+#define MX53_SAHARA_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000F8000)
+#define MX53_PTP_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000FC000)
+
+/*
+ * Memory regions and CS
+ */
+#define MX53_CSD0_BASE_ADDR		0x70000000
+#define MX53_CSD1_BASE_ADDR		0xB0000000
+#define MX53_CS0_BASE_ADDR		0xF0000000
+#define MX53_CS1_32MB_BASE_ADDR	0xF2000000
+#define MX53_CS1_64MB_BASE_ADDR		0xF4000000
+#define MX53_CS2_64MB_BASE_ADDR		0xF4000000
+#define MX53_CS2_96MB_BASE_ADDR		0xF6000000
+#define MX53_CS3_BASE_ADDR		0xF6000000
+
+#define MX53_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX53_IO_ADDRESS(x)		IOMEM(MX53_IO_P2V(x))
+
+/*
+ * defines for SPBA modules
+ */
+#define MX53_SPBA_SDHC1	0x04
+#define MX53_SPBA_SDHC2	0x08
+#define MX53_SPBA_UART3	0x0C
+#define MX53_SPBA_CSPI1	0x10
+#define MX53_SPBA_SSI2		0x14
+#define MX53_SPBA_SDHC3	0x20
+#define MX53_SPBA_SDHC4	0x24
+#define MX53_SPBA_SPDIF	0x28
+#define MX53_SPBA_ATA		0x30
+#define MX53_SPBA_SLIM		0x34
+#define MX53_SPBA_HSI2C	0x38
+#define MX53_SPBA_CTRL		0x3C
+
+/*
+ * DMA request assignments
+ */
+#define MX53_DMA_REQ_SSI3_TX0		47
+#define MX53_DMA_REQ_SSI3_RX0		46
+#define MX53_DMA_REQ_SSI3_TX1		45
+#define MX53_DMA_REQ_SSI3_RX1		44
+#define MX53_DMA_REQ_UART3_TX	43
+#define MX53_DMA_REQ_UART3_RX	42
+#define MX53_DMA_REQ_ESAI_TX		41
+#define MX53_DMA_REQ_ESAI_RX		40
+#define MX53_DMA_REQ_CSPI_TX		39
+#define MX53_DMA_REQ_CSPI_RX		38
+#define MX53_DMA_REQ_ASRC_DMA6	37
+#define MX53_DMA_REQ_ASRC_DMA5	36
+#define MX53_DMA_REQ_ASRC_DMA4	35
+#define MX53_DMA_REQ_ASRC_DMA3	34
+#define MX53_DMA_REQ_ASRC_DMA2	33
+#define MX53_DMA_REQ_ASRC_DMA1	32
+#define MX53_DMA_REQ_EMI_WR		31
+#define MX53_DMA_REQ_EMI_RD		30
+#define MX53_DMA_REQ_SSI1_TX0		29
+#define MX53_DMA_REQ_SSI1_RX0		28
+#define MX53_DMA_REQ_SSI1_TX1		27
+#define MX53_DMA_REQ_SSI1_RX1		26
+#define MX53_DMA_REQ_SSI2_TX0		25
+#define MX53_DMA_REQ_SSI2_RX0		24
+#define MX53_DMA_REQ_SSI2_TX1		23
+#define MX53_DMA_REQ_SSI2_RX1		22
+#define MX53_DMA_REQ_I2C2_SDHC2	21
+#define MX53_DMA_REQ_I2C1_SDHC1	20
+#define MX53_DMA_REQ_UART1_TX	19
+#define MX53_DMA_REQ_UART1_RX	18
+#define MX53_DMA_REQ_UART5_TX	17
+#define MX53_DMA_REQ_UART5_RX	16
+#define MX53_DMA_REQ_SPDIF_TX		15
+#define MX53_DMA_REQ_SPDIF_RX		14
+#define MX53_DMA_REQ_UART2_FIRI_TX	13
+#define MX53_DMA_REQ_UART2_FIRI_RX	12
+#define MX53_DMA_REQ_SDHC4		11
+#define MX53_DMA_REQ_I2C3_SDHC3	10
+#define MX53_DMA_REQ_CSPI2_TX		9
+#define MX53_DMA_REQ_CSPI2_RX		8
+#define MX53_DMA_REQ_CSPI1_TX		7
+#define MX53_DMA_REQ_CSPI1_RX		6
+#define MX53_DMA_REQ_IPU		5
+#define MX53_DMA_REQ_ATA_TX_END	4
+#define MX53_DMA_REQ_ATA_UART4_TX	3
+#define MX53_DMA_REQ_ATA_UART4_RX	2
+#define MX53_DMA_REQ_GPC		1
+#define MX53_DMA_REQ_VPU		0
+
+/*
+ * Interrupt numbers
+ */
+#include <asm/irq.h>
+#define MX53_INT_RESV0		(NR_IRQS_LEGACY + 0)
+#define MX53_INT_ESDHC1		(NR_IRQS_LEGACY + 1)
+#define MX53_INT_ESDHC2		(NR_IRQS_LEGACY + 2)
+#define MX53_INT_ESDHC3		(NR_IRQS_LEGACY + 3)
+#define MX53_INT_ESDHC4		(NR_IRQS_LEGACY + 4)
+#define MX53_INT_DAP		(NR_IRQS_LEGACY + 5)
+#define MX53_INT_SDMA		(NR_IRQS_LEGACY + 6)
+#define MX53_INT_IOMUX		(NR_IRQS_LEGACY + 7)
+#define MX53_INT_NFC		(NR_IRQS_LEGACY + 8)
+#define MX53_INT_VPU		(NR_IRQS_LEGACY + 9)
+#define MX53_INT_IPU_ERR	(NR_IRQS_LEGACY + 10)
+#define MX53_INT_IPU_SYN	(NR_IRQS_LEGACY + 11)
+#define MX53_INT_GPU		(NR_IRQS_LEGACY + 12)
+#define MX53_INT_UART4		(NR_IRQS_LEGACY + 13)
+#define MX53_INT_USB_H1		(NR_IRQS_LEGACY + 14)
+#define MX53_INT_EMI		(NR_IRQS_LEGACY + 15)
+#define MX53_INT_USB_H2		(NR_IRQS_LEGACY + 16)
+#define MX53_INT_USB_H3		(NR_IRQS_LEGACY + 17)
+#define MX53_INT_USB_OTG	(NR_IRQS_LEGACY + 18)
+#define MX53_INT_SAHARA_H0	(NR_IRQS_LEGACY + 19)
+#define MX53_INT_SAHARA_H1	(NR_IRQS_LEGACY + 20)
+#define MX53_INT_SCC_SMN	(NR_IRQS_LEGACY + 21)
+#define MX53_INT_SCC_STZ	(NR_IRQS_LEGACY + 22)
+#define MX53_INT_SCC_SCM	(NR_IRQS_LEGACY + 23)
+#define MX53_INT_SRTC_NTZ	(NR_IRQS_LEGACY + 24)
+#define MX53_INT_SRTC_TZ	(NR_IRQS_LEGACY + 25)
+#define MX53_INT_RTIC		(NR_IRQS_LEGACY + 26)
+#define MX53_INT_CSU		(NR_IRQS_LEGACY + 27)
+#define MX53_INT_SATA		(NR_IRQS_LEGACY + 28)
+#define MX53_INT_SSI1		(NR_IRQS_LEGACY + 29)
+#define MX53_INT_SSI2		(NR_IRQS_LEGACY + 30)
+#define MX53_INT_UART1		(NR_IRQS_LEGACY + 31)
+#define MX53_INT_UART2		(NR_IRQS_LEGACY + 32)
+#define MX53_INT_UART3		(NR_IRQS_LEGACY + 33)
+#define MX53_INT_RTC		(NR_IRQS_LEGACY + 34)
+#define MX53_INT_PTP		(NR_IRQS_LEGACY + 35)
+#define MX53_INT_ECSPI1		(NR_IRQS_LEGACY + 36)
+#define MX53_INT_ECSPI2		(NR_IRQS_LEGACY + 37)
+#define MX53_INT_CSPI		(NR_IRQS_LEGACY + 38)
+#define MX53_INT_GPT		(NR_IRQS_LEGACY + 39)
+#define MX53_INT_EPIT1		(NR_IRQS_LEGACY + 40)
+#define MX53_INT_EPIT2		(NR_IRQS_LEGACY + 41)
+#define MX53_INT_GPIO1_INT7	(NR_IRQS_LEGACY + 42)
+#define MX53_INT_GPIO1_INT6	(NR_IRQS_LEGACY + 43)
+#define MX53_INT_GPIO1_INT5	(NR_IRQS_LEGACY + 44)
+#define MX53_INT_GPIO1_INT4	(NR_IRQS_LEGACY + 45)
+#define MX53_INT_GPIO1_INT3	(NR_IRQS_LEGACY + 46)
+#define MX53_INT_GPIO1_INT2	(NR_IRQS_LEGACY + 47)
+#define MX53_INT_GPIO1_INT1	(NR_IRQS_LEGACY + 48)
+#define MX53_INT_GPIO1_INT0	(NR_IRQS_LEGACY + 49)
+#define MX53_INT_GPIO1_LOW	(NR_IRQS_LEGACY + 50)
+#define MX53_INT_GPIO1_HIGH	(NR_IRQS_LEGACY + 51)
+#define MX53_INT_GPIO2_LOW	(NR_IRQS_LEGACY + 52)
+#define MX53_INT_GPIO2_HIGH	(NR_IRQS_LEGACY + 53)
+#define MX53_INT_GPIO3_LOW	(NR_IRQS_LEGACY + 54)
+#define MX53_INT_GPIO3_HIGH	(NR_IRQS_LEGACY + 55)
+#define MX53_INT_GPIO4_LOW	(NR_IRQS_LEGACY + 56)
+#define MX53_INT_GPIO4_HIGH	(NR_IRQS_LEGACY + 57)
+#define MX53_INT_WDOG1		(NR_IRQS_LEGACY + 58)
+#define MX53_INT_WDOG2		(NR_IRQS_LEGACY + 59)
+#define MX53_INT_KPP		(NR_IRQS_LEGACY + 60)
+#define MX53_INT_PWM1		(NR_IRQS_LEGACY + 61)
+#define MX53_INT_I2C1		(NR_IRQS_LEGACY + 62)
+#define MX53_INT_I2C2		(NR_IRQS_LEGACY + 63)
+#define MX53_INT_I2C3		(NR_IRQS_LEGACY + 64)
+#define MX53_INT_MLB		(NR_IRQS_LEGACY + 65)
+#define MX53_INT_ASRC		(NR_IRQS_LEGACY + 66)
+#define MX53_INT_SPDIF		(NR_IRQS_LEGACY + 67)
+#define MX53_INT_SIM_DAT	(NR_IRQS_LEGACY + 68)
+#define MX53_INT_IIM		(NR_IRQS_LEGACY + 69)
+#define MX53_INT_ATA		(NR_IRQS_LEGACY + 70)
+#define MX53_INT_CCM1		(NR_IRQS_LEGACY + 71)
+#define MX53_INT_CCM2		(NR_IRQS_LEGACY + 72)
+#define MX53_INT_GPC1		(NR_IRQS_LEGACY + 73)
+#define MX53_INT_GPC2		(NR_IRQS_LEGACY + 74)
+#define MX53_INT_SRC		(NR_IRQS_LEGACY + 75)
+#define MX53_INT_NM		(NR_IRQS_LEGACY + 76)
+#define MX53_INT_PMU		(NR_IRQS_LEGACY + 77)
+#define MX53_INT_CTI_IRQ	(NR_IRQS_LEGACY + 78)
+#define MX53_INT_CTI1_TG0	(NR_IRQS_LEGACY + 79)
+#define MX53_INT_CTI1_TG1	(NR_IRQS_LEGACY + 80)
+#define MX53_INT_ESAI		(NR_IRQS_LEGACY + 81)
+#define MX53_INT_CAN1		(NR_IRQS_LEGACY + 82)
+#define MX53_INT_CAN2		(NR_IRQS_LEGACY + 83)
+#define MX53_INT_GPU2_IRQ	(NR_IRQS_LEGACY + 84)
+#define MX53_INT_GPU2_BUSY	(NR_IRQS_LEGACY + 85)
+#define MX53_INT_UART5		(NR_IRQS_LEGACY + 86)
+#define MX53_INT_FEC		(NR_IRQS_LEGACY + 87)
+#define MX53_INT_OWIRE		(NR_IRQS_LEGACY + 88)
+#define MX53_INT_CTI1_TG2	(NR_IRQS_LEGACY + 89)
+#define MX53_INT_SJC		(NR_IRQS_LEGACY + 90)
+#define MX53_INT_TVE		(NR_IRQS_LEGACY + 92)
+#define MX53_INT_FIRI		(NR_IRQS_LEGACY + 93)
+#define MX53_INT_PWM2		(NR_IRQS_LEGACY + 94)
+#define MX53_INT_SLIM_EXP	(NR_IRQS_LEGACY + 95)
+#define MX53_INT_SSI3		(NR_IRQS_LEGACY + 96)
+#define MX53_INT_EMI_BOOT	(NR_IRQS_LEGACY + 97)
+#define MX53_INT_CTI1_TG3	(NR_IRQS_LEGACY + 98)
+#define MX53_INT_SMC_RX		(NR_IRQS_LEGACY + 99)
+#define MX53_INT_VPU_IDLE	(NR_IRQS_LEGACY + 100)
+#define MX53_INT_EMI_NFC	(NR_IRQS_LEGACY + 101)
+#define MX53_INT_GPU_IDLE	(NR_IRQS_LEGACY + 102)
+#define MX53_INT_GPIO5_LOW	(NR_IRQS_LEGACY + 103)
+#define MX53_INT_GPIO5_HIGH	(NR_IRQS_LEGACY + 104)
+#define MX53_INT_GPIO6_LOW	(NR_IRQS_LEGACY + 105)
+#define MX53_INT_GPIO6_HIGH	(NR_IRQS_LEGACY + 106)
+#define MX53_INT_GPIO7_LOW	(NR_IRQS_LEGACY + 107)
+#define MX53_INT_GPIO7_HIGH	(NR_IRQS_LEGACY + 108)
+
+#endif /* ifndef __MACH_MX53_H__ */
diff --git a/arch/arm/mach-imx/mx6q.h b/arch/arm/mach-imx/mx6q.h
new file mode 100644
index 0000000..19d3f54
--- /dev/null
+++ b/arch/arm/mach-imx/mx6q.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __MACH_MX6Q_H__
+#define __MACH_MX6Q_H__
+
+#define MX6Q_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX6Q_IO_ADDRESS(x)		IOMEM(MX6Q_IO_P2V(x))
+
+/*
+ * The following are the blocks that need to be statically mapped.
+ * For other blocks, the base address really should be retrieved from
+ * device tree.
+ */
+#define MX6Q_SCU_BASE_ADDR		0x00a00000
+#define MX6Q_SCU_SIZE			0x1000
+#define MX6Q_CCM_BASE_ADDR		0x020c4000
+#define MX6Q_CCM_SIZE			0x4000
+#define MX6Q_ANATOP_BASE_ADDR		0x020c8000
+#define MX6Q_ANATOP_SIZE		0x1000
+
+#endif	/* __MACH_MX6Q_H__ */
diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h
new file mode 100644
index 0000000..d782983
--- /dev/null
+++ b/arch/arm/mach-imx/mxc.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2004-2007, 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __ASM_ARCH_MXC_H__
+#define __ASM_ARCH_MXC_H__
+
+#include <linux/types.h>
+
+#ifndef __ASM_ARCH_MXC_HARDWARE_H__
+#error "Do not include directly."
+#endif
+
+#define MXC_CPU_MX1		1
+#define MXC_CPU_MX21		21
+#define MXC_CPU_MX25		25
+#define MXC_CPU_MX27		27
+#define MXC_CPU_MX31		31
+#define MXC_CPU_MX35		35
+#define MXC_CPU_MX50		50
+#define MXC_CPU_MX51		51
+#define MXC_CPU_MX53		53
+
+#define IMX_CHIP_REVISION_1_0		0x10
+#define IMX_CHIP_REVISION_1_1		0x11
+#define IMX_CHIP_REVISION_1_2		0x12
+#define IMX_CHIP_REVISION_1_3		0x13
+#define IMX_CHIP_REVISION_2_0		0x20
+#define IMX_CHIP_REVISION_2_1		0x21
+#define IMX_CHIP_REVISION_2_2		0x22
+#define IMX_CHIP_REVISION_2_3		0x23
+#define IMX_CHIP_REVISION_3_0		0x30
+#define IMX_CHIP_REVISION_3_1		0x31
+#define IMX_CHIP_REVISION_3_2		0x32
+#define IMX_CHIP_REVISION_3_3		0x33
+#define IMX_CHIP_REVISION_UNKNOWN	0xff
+
+#ifndef __ASSEMBLY__
+extern unsigned int __mxc_cpu_type;
+#endif
+
+#ifdef CONFIG_SOC_IMX1
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX1
+# endif
+# define cpu_is_mx1()		(mxc_cpu_type == MXC_CPU_MX1)
+#else
+# define cpu_is_mx1()		(0)
+#endif
+
+#ifdef CONFIG_SOC_IMX21
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX21
+# endif
+# define cpu_is_mx21()		(mxc_cpu_type == MXC_CPU_MX21)
+#else
+# define cpu_is_mx21()		(0)
+#endif
+
+#ifdef CONFIG_SOC_IMX25
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX25
+# endif
+# define cpu_is_mx25()		(mxc_cpu_type == MXC_CPU_MX25)
+#else
+# define cpu_is_mx25()		(0)
+#endif
+
+#ifdef CONFIG_SOC_IMX27
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX27
+# endif
+# define cpu_is_mx27()		(mxc_cpu_type == MXC_CPU_MX27)
+#else
+# define cpu_is_mx27()		(0)
+#endif
+
+#ifdef CONFIG_SOC_IMX31
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX31
+# endif
+# define cpu_is_mx31()		(mxc_cpu_type == MXC_CPU_MX31)
+#else
+# define cpu_is_mx31()		(0)
+#endif
+
+#ifdef CONFIG_SOC_IMX35
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX35
+# endif
+# define cpu_is_mx35()		(mxc_cpu_type == MXC_CPU_MX35)
+#else
+# define cpu_is_mx35()		(0)
+#endif
+
+#ifdef CONFIG_SOC_IMX50
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX50
+# endif
+# define cpu_is_mx50()		(mxc_cpu_type == MXC_CPU_MX50)
+#else
+# define cpu_is_mx50()		(0)
+#endif
+
+#ifdef CONFIG_SOC_IMX51
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX51
+# endif
+# define cpu_is_mx51()		(mxc_cpu_type == MXC_CPU_MX51)
+#else
+# define cpu_is_mx51()		(0)
+#endif
+
+#ifdef CONFIG_SOC_IMX53
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX53
+# endif
+# define cpu_is_mx53()		(mxc_cpu_type == MXC_CPU_MX53)
+#else
+# define cpu_is_mx53()		(0)
+#endif
+
+#ifndef __ASSEMBLY__
+
+struct cpu_op {
+	u32 cpu_rate;
+};
+
+int tzic_enable_wake(void);
+
+extern struct cpu_op *(*get_cpu_op)(int *op);
+#endif
+
+#define cpu_is_mx3()	(cpu_is_mx31() || cpu_is_mx35())
+#define cpu_is_mx2()	(cpu_is_mx21() || cpu_is_mx27())
+
+#endif /*  __ASM_ARCH_MXC_H__ */
diff --git a/arch/arm/mach-imx/pcm970-baseboard.c b/arch/arm/mach-imx/pcm970-baseboard.c
index 9917e2f..51c6082 100644
--- a/arch/arm/mach-imx/pcm970-baseboard.c
+++ b/arch/arm/mach-imx/pcm970-baseboard.c
@@ -23,11 +23,10 @@
 
 #include <asm/mach/arch.h>
 
-#include <mach/common.h>
-#include <mach/iomux-mx27.h>
-#include <mach/hardware.h>
-
+#include "common.h"
 #include "devices-imx27.h"
+#include "hardware.h"
+#include "iomux-mx27.h"
 
 static const int pcm970_pins[] __initconst = {
 	/* SDHC */
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
index 2ac43e1..3777b80 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -16,8 +16,9 @@
 #include <asm/smp_scu.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/map.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
+
+#include "common.h"
+#include "hardware.h"
 
 static void __iomem *scu_base;
 
diff --git a/arch/arm/mach-imx/pm-imx27.c b/arch/arm/mach-imx/pm-imx27.c
index 6fcffa7..56d02d0 100644
--- a/arch/arm/mach-imx/pm-imx27.c
+++ b/arch/arm/mach-imx/pm-imx27.c
@@ -10,7 +10,8 @@
 #include <linux/kernel.h>
 #include <linux/suspend.h>
 #include <linux/io.h>
-#include <mach/hardware.h>
+
+#include "hardware.h"
 
 static int mx27_suspend_enter(suspend_state_t state)
 {
diff --git a/arch/arm/mach-imx/pm-imx3.c b/arch/arm/mach-imx/pm-imx3.c
index 822103b..6a07006 100644
--- a/arch/arm/mach-imx/pm-imx3.c
+++ b/arch/arm/mach-imx/pm-imx3.c
@@ -9,10 +9,11 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 #include <linux/io.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
+
+#include "common.h"
 #include "crmregs-imx3.h"
+#include "devices/devices-common.h"
+#include "hardware.h"
 
 /*
  * Set cpu low power mode before WFI instruction. This function is called
diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c
index 19621ed1..2e063c2 100644
--- a/arch/arm/mach-imx/pm-imx5.c
+++ b/arch/arm/mach-imx/pm-imx5.c
@@ -16,10 +16,11 @@
 #include <asm/cacheflush.h>
 #include <asm/system_misc.h>
 #include <asm/tlbflush.h>
-#include <mach/common.h>
-#include <mach/cpuidle.h>
-#include <mach/hardware.h>
+
+#include "common.h"
+#include "cpuidle.h"
 #include "crm-regs-imx5.h"
+#include "hardware.h"
 
 /*
  * The WAIT_UNCLOCKED_POWER_OFF state only requires <= 500ns to exit.
diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c
index f7b0c2b..a17543d 100644
--- a/arch/arm/mach-imx/pm-imx6q.c
+++ b/arch/arm/mach-imx/pm-imx6q.c
@@ -18,8 +18,9 @@
 #include <asm/proc-fns.h>
 #include <asm/suspend.h>
 #include <asm/hardware/cache-l2x0.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
+
+#include "common.h"
+#include "hardware.h"
 
 extern unsigned long phys_l2x0_saved_regs;
 
diff --git a/arch/arm/mach-imx/ssi-fiq-ksym.c b/arch/arm/mach-imx/ssi-fiq-ksym.c
new file mode 100644
index 0000000..792090f
--- /dev/null
+++ b/arch/arm/mach-imx/ssi-fiq-ksym.c
@@ -0,0 +1,20 @@
+/*
+ * Exported ksyms for the SSI FIQ handler
+ *
+ * Copyright (C) 2009, Sascha Hauer <s.hauer@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/module.h>
+
+#include <linux/platform_data/asoc-imx-ssi.h>
+
+EXPORT_SYMBOL(imx_ssi_fiq_tx_buffer);
+EXPORT_SYMBOL(imx_ssi_fiq_rx_buffer);
+EXPORT_SYMBOL(imx_ssi_fiq_start);
+EXPORT_SYMBOL(imx_ssi_fiq_end);
+EXPORT_SYMBOL(imx_ssi_fiq_base);
+
diff --git a/arch/arm/mach-imx/ssi-fiq.S b/arch/arm/mach-imx/ssi-fiq.S
new file mode 100644
index 0000000..a8b93c5
--- /dev/null
+++ b/arch/arm/mach-imx/ssi-fiq.S
@@ -0,0 +1,147 @@
+/*
+ *  Copyright (C) 2009 Sascha Hauer <s.hauer@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/linkage.h>
+#include <asm/assembler.h>
+
+/*
+ * r8  = bit 0-15: tx offset, bit 16-31: tx buffer size
+ * r9  = bit 0-15: rx offset, bit 16-31: rx buffer size
+ */
+
+#define SSI_STX0	0x00
+#define SSI_SRX0	0x08
+#define SSI_SISR	0x14
+#define SSI_SIER	0x18
+#define SSI_SACNT	0x38
+
+#define SSI_SACNT_AC97EN	(1 << 0)
+
+#define SSI_SIER_TFE0_EN	(1 << 0)
+#define SSI_SISR_TFE0		(1 << 0)
+#define SSI_SISR_RFF0		(1 << 2)
+#define SSI_SIER_RFF0_EN	(1 << 2)
+
+		.text
+		.global	imx_ssi_fiq_start
+		.global	imx_ssi_fiq_end
+		.global imx_ssi_fiq_base
+		.global imx_ssi_fiq_rx_buffer
+		.global imx_ssi_fiq_tx_buffer
+
+/*
+ * imx_ssi_fiq_start is _intentionally_ not marked as a function symbol
+ * using ENDPROC().  imx_ssi_fiq_start and imx_ssi_fiq_end are used to
+ * mark the function body so that it can be copied to the FIQ vector in
+ * the vectors page.  imx_ssi_fiq_start should only be called as the result
+ * of an FIQ: calling it directly will not work.
+ */
+imx_ssi_fiq_start:
+		ldr r12, .L_imx_ssi_fiq_base
+
+		/* TX */
+		ldr r13, .L_imx_ssi_fiq_tx_buffer
+
+		/* shall we send? */
+		ldr r11, [r12, #SSI_SIER]
+		tst r11, #SSI_SIER_TFE0_EN
+		beq 1f
+
+		/* TX FIFO empty? */
+		ldr r11, [r12, #SSI_SISR]
+		tst r11, #SSI_SISR_TFE0
+		beq 1f
+
+		mov r10, #0x10000
+		sub r10, #1
+		and r10, r10, r8	/* r10: current buffer offset */
+
+		add r13, r13, r10
+
+		ldrh r11, [r13]
+		strh r11, [r12, #SSI_STX0]
+
+		ldrh r11, [r13, #2]
+		strh r11, [r12, #SSI_STX0]
+
+		ldrh r11, [r13, #4]
+		strh r11, [r12, #SSI_STX0]
+
+		ldrh r11, [r13, #6]
+		strh r11, [r12, #SSI_STX0]
+
+		add r10, #8
+		lsr r11, r8, #16	/* r11: buffer size */
+		cmp r10, r11
+		lslgt r8, r11, #16
+		addle r8, #8
+1:
+		/* RX */
+
+		/* shall we receive? */
+		ldr r11, [r12, #SSI_SIER]
+		tst r11, #SSI_SIER_RFF0_EN
+		beq 1f
+
+		/* RX FIFO full? */
+		ldr r11, [r12, #SSI_SISR]
+		tst r11, #SSI_SISR_RFF0
+		beq 1f
+
+		ldr r13, .L_imx_ssi_fiq_rx_buffer
+
+		mov r10, #0x10000
+		sub r10, #1
+		and r10, r10, r9	/* r10: current buffer offset */
+
+		add r13, r13, r10
+
+		ldr r11, [r12, #SSI_SACNT]
+		tst r11, #SSI_SACNT_AC97EN
+
+		ldr r11, [r12, #SSI_SRX0]
+		strh r11, [r13]
+
+		ldr r11, [r12, #SSI_SRX0]
+		strh r11, [r13, #2]
+
+		/* dummy read to skip slot 12 */
+		ldrne r11, [r12, #SSI_SRX0]
+
+		ldr r11, [r12, #SSI_SRX0]
+		strh r11, [r13, #4]
+
+		ldr r11, [r12, #SSI_SRX0]
+		strh r11, [r13, #6]
+
+		/* dummy read to skip slot 12 */
+		ldrne r11, [r12, #SSI_SRX0]
+
+		add r10, #8
+		lsr r11, r9, #16	/* r11: buffer size */
+		cmp r10, r11
+		lslgt r9, r11, #16
+		addle r9, #8
+
+1:
+		@ return from FIQ
+		subs	pc, lr, #4
+
+		.align
+.L_imx_ssi_fiq_base:
+imx_ssi_fiq_base:
+		.word 0x0
+.L_imx_ssi_fiq_rx_buffer:
+imx_ssi_fiq_rx_buffer:
+		.word 0x0
+.L_imx_ssi_fiq_tx_buffer:
+imx_ssi_fiq_tx_buffer:
+		.word 0x0
+.L_imx_ssi_fiq_end:
+imx_ssi_fiq_end:
+
diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c
new file mode 100644
index 0000000..695e0d7
--- /dev/null
+++ b/arch/arm/mach-imx/system.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+#include <asm/system_misc.h>
+#include <asm/proc-fns.h>
+#include <asm/mach-types.h>
+
+#include "common.h"
+#include "hardware.h"
+
+static void __iomem *wdog_base;
+
+/*
+ * Reset the system. It is called by machine_restart().
+ */
+void mxc_restart(char mode, const char *cmd)
+{
+	unsigned int wcr_enable;
+
+	if (cpu_is_mx1()) {
+		wcr_enable = (1 << 0);
+	} else {
+		struct clk *clk;
+
+		clk = clk_get_sys("imx2-wdt.0", NULL);
+		if (!IS_ERR(clk))
+			clk_prepare_enable(clk);
+		wcr_enable = (1 << 2);
+	}
+
+	/* Assert SRS signal */
+	__raw_writew(wcr_enable, wdog_base);
+
+	/* wait for reset to assert... */
+	mdelay(500);
+
+	printk(KERN_ERR "Watchdog reset failed to assert reset\n");
+
+	/* delay to allow the serial port to show the message */
+	mdelay(50);
+
+	/* we'll take a jump through zero as a poor second */
+	soft_restart(0);
+}
+
+void mxc_arch_reset_init(void __iomem *base)
+{
+	wdog_base = base;
+}
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
new file mode 100644
index 0000000..f017302
--- /dev/null
+++ b/arch/arm/mach-imx/time.c
@@ -0,0 +1,326 @@
+/*
+ *  linux/arch/arm/plat-mxc/time.c
+ *
+ *  Copyright (C) 2000-2001 Deep Blue Solutions
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com)
+ *  Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <asm/sched_clock.h>
+#include <asm/mach/time.h>
+
+#include "common.h"
+#include "hardware.h"
+
+/*
+ * There are 2 versions of the timer hardware on Freescale MXC hardware.
+ * Version 1: MX1/MXL, MX21, MX27.
+ * Version 2: MX25, MX31, MX35, MX37, MX51
+ */
+
+/* defines common for all i.MX */
+#define MXC_TCTL		0x00
+#define MXC_TCTL_TEN		(1 << 0) /* Enable module */
+#define MXC_TPRER		0x04
+
+/* MX1, MX21, MX27 */
+#define MX1_2_TCTL_CLK_PCLK1	(1 << 1)
+#define MX1_2_TCTL_IRQEN	(1 << 4)
+#define MX1_2_TCTL_FRR		(1 << 8)
+#define MX1_2_TCMP		0x08
+#define MX1_2_TCN		0x10
+#define MX1_2_TSTAT		0x14
+
+/* MX21, MX27 */
+#define MX2_TSTAT_CAPT		(1 << 1)
+#define MX2_TSTAT_COMP		(1 << 0)
+
+/* MX31, MX35, MX25, MX5 */
+#define V2_TCTL_WAITEN		(1 << 3) /* Wait enable mode */
+#define V2_TCTL_CLK_IPG		(1 << 6)
+#define V2_TCTL_CLK_PER		(2 << 6)
+#define V2_TCTL_FRR		(1 << 9)
+#define V2_IR			0x0c
+#define V2_TSTAT		0x08
+#define V2_TSTAT_OF1		(1 << 0)
+#define V2_TCN			0x24
+#define V2_TCMP			0x10
+
+#define timer_is_v1()	(cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
+#define timer_is_v2()	(!timer_is_v1())
+
+static struct clock_event_device clockevent_mxc;
+static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
+
+static void __iomem *timer_base;
+
+static inline void gpt_irq_disable(void)
+{
+	unsigned int tmp;
+
+	if (timer_is_v2())
+		__raw_writel(0, timer_base + V2_IR);
+	else {
+		tmp = __raw_readl(timer_base + MXC_TCTL);
+		__raw_writel(tmp & ~MX1_2_TCTL_IRQEN, timer_base + MXC_TCTL);
+	}
+}
+
+static inline void gpt_irq_enable(void)
+{
+	if (timer_is_v2())
+		__raw_writel(1<<0, timer_base + V2_IR);
+	else {
+		__raw_writel(__raw_readl(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
+			timer_base + MXC_TCTL);
+	}
+}
+
+static void gpt_irq_acknowledge(void)
+{
+	if (timer_is_v1()) {
+		if (cpu_is_mx1())
+			__raw_writel(0, timer_base + MX1_2_TSTAT);
+		else
+			__raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP,
+				timer_base + MX1_2_TSTAT);
+	} else if (timer_is_v2())
+		__raw_writel(V2_TSTAT_OF1, timer_base + V2_TSTAT);
+}
+
+static void __iomem *sched_clock_reg;
+
+static u32 notrace mxc_read_sched_clock(void)
+{
+	return sched_clock_reg ? __raw_readl(sched_clock_reg) : 0;
+}
+
+static int __init mxc_clocksource_init(struct clk *timer_clk)
+{
+	unsigned int c = clk_get_rate(timer_clk);
+	void __iomem *reg = timer_base + (timer_is_v2() ? V2_TCN : MX1_2_TCN);
+
+	sched_clock_reg = reg;
+
+	setup_sched_clock(mxc_read_sched_clock, 32, c);
+	return clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32,
+			clocksource_mmio_readl_up);
+}
+
+/* clock event */
+
+static int mx1_2_set_next_event(unsigned long evt,
+			      struct clock_event_device *unused)
+{
+	unsigned long tcmp;
+
+	tcmp = __raw_readl(timer_base + MX1_2_TCN) + evt;
+
+	__raw_writel(tcmp, timer_base + MX1_2_TCMP);
+
+	return (int)(tcmp - __raw_readl(timer_base + MX1_2_TCN)) < 0 ?
+				-ETIME : 0;
+}
+
+static int v2_set_next_event(unsigned long evt,
+			      struct clock_event_device *unused)
+{
+	unsigned long tcmp;
+
+	tcmp = __raw_readl(timer_base + V2_TCN) + evt;
+
+	__raw_writel(tcmp, timer_base + V2_TCMP);
+
+	return (int)(tcmp - __raw_readl(timer_base + V2_TCN)) < 0 ?
+				-ETIME : 0;
+}
+
+#ifdef DEBUG
+static const char *clock_event_mode_label[] = {
+	[CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
+	[CLOCK_EVT_MODE_ONESHOT]  = "CLOCK_EVT_MODE_ONESHOT",
+	[CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
+	[CLOCK_EVT_MODE_UNUSED]   = "CLOCK_EVT_MODE_UNUSED",
+	[CLOCK_EVT_MODE_RESUME]   = "CLOCK_EVT_MODE_RESUME",
+};
+#endif /* DEBUG */
+
+static void mxc_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *evt)
+{
+	unsigned long flags;
+
+	/*
+	 * The timer interrupt generation is disabled at least
+	 * for enough time to call mxc_set_next_event()
+	 */
+	local_irq_save(flags);
+
+	/* Disable interrupt in GPT module */
+	gpt_irq_disable();
+
+	if (mode != clockevent_mode) {
+		/* Set event time into far-far future */
+		if (timer_is_v2())
+			__raw_writel(__raw_readl(timer_base + V2_TCN) - 3,
+					timer_base + V2_TCMP);
+		else
+			__raw_writel(__raw_readl(timer_base + MX1_2_TCN) - 3,
+					timer_base + MX1_2_TCMP);
+
+		/* Clear pending interrupt */
+		gpt_irq_acknowledge();
+	}
+
+#ifdef DEBUG
+	printk(KERN_INFO "mxc_set_mode: changing mode from %s to %s\n",
+		clock_event_mode_label[clockevent_mode],
+		clock_event_mode_label[mode]);
+#endif /* DEBUG */
+
+	/* Remember timer mode */
+	clockevent_mode = mode;
+	local_irq_restore(flags);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		printk(KERN_ERR"mxc_set_mode: Periodic mode is not "
+				"supported for i.MX\n");
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+	/*
+	 * Do not put overhead of interrupt enable/disable into
+	 * mxc_set_next_event(), the core has about 4 minutes
+	 * to call mxc_set_next_event() or shutdown clock after
+	 * mode switching
+	 */
+		local_irq_save(flags);
+		gpt_irq_enable();
+		local_irq_restore(flags);
+		break;
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_RESUME:
+		/* Left event sources disabled, no more interrupts appear */
+		break;
+	}
+}
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = &clockevent_mxc;
+	uint32_t tstat;
+
+	if (timer_is_v2())
+		tstat = __raw_readl(timer_base + V2_TSTAT);
+	else
+		tstat = __raw_readl(timer_base + MX1_2_TSTAT);
+
+	gpt_irq_acknowledge();
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction mxc_timer_irq = {
+	.name		= "i.MX Timer Tick",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= mxc_timer_interrupt,
+};
+
+static struct clock_event_device clockevent_mxc = {
+	.name		= "mxc_timer1",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.shift		= 32,
+	.set_mode	= mxc_set_mode,
+	.set_next_event	= mx1_2_set_next_event,
+	.rating		= 200,
+};
+
+static int __init mxc_clockevent_init(struct clk *timer_clk)
+{
+	unsigned int c = clk_get_rate(timer_clk);
+
+	if (timer_is_v2())
+		clockevent_mxc.set_next_event = v2_set_next_event;
+
+	clockevent_mxc.mult = div_sc(c, NSEC_PER_SEC,
+					clockevent_mxc.shift);
+	clockevent_mxc.max_delta_ns =
+			clockevent_delta2ns(0xfffffffe, &clockevent_mxc);
+	clockevent_mxc.min_delta_ns =
+			clockevent_delta2ns(0xff, &clockevent_mxc);
+
+	clockevent_mxc.cpumask = cpumask_of(0);
+
+	clockevents_register_device(&clockevent_mxc);
+
+	return 0;
+}
+
+void __init mxc_timer_init(void __iomem *base, int irq)
+{
+	uint32_t tctl_val;
+	struct clk *timer_clk;
+	struct clk *timer_ipg_clk;
+
+	timer_clk = clk_get_sys("imx-gpt.0", "per");
+	if (IS_ERR(timer_clk)) {
+		pr_err("i.MX timer: unable to get clk\n");
+		return;
+	}
+
+	timer_ipg_clk = clk_get_sys("imx-gpt.0", "ipg");
+	if (!IS_ERR(timer_ipg_clk))
+		clk_prepare_enable(timer_ipg_clk);
+
+	clk_prepare_enable(timer_clk);
+
+	timer_base = base;
+
+	/*
+	 * Initialise to a known state (all timers off, and timing reset)
+	 */
+
+	__raw_writel(0, timer_base + MXC_TCTL);
+	__raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
+
+	if (timer_is_v2())
+		tctl_val = V2_TCTL_CLK_PER | V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
+	else
+		tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
+
+	__raw_writel(tctl_val, timer_base + MXC_TCTL);
+
+	/* init and register the timer to the framework */
+	mxc_clocksource_init(timer_clk);
+	mxc_clockevent_init(timer_clk);
+
+	/* Make irqs happen */
+	setup_irq(irq, &mxc_timer_irq);
+}
diff --git a/arch/arm/mach-imx/tzic.c b/arch/arm/mach-imx/tzic.c
new file mode 100644
index 0000000..9721161
--- /dev/null
+++ b/arch/arm/mach-imx/tzic.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C)2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+
+#include <asm/mach/irq.h>
+#include <asm/exception.h>
+
+#include "common.h"
+#include "hardware.h"
+#include "irq-common.h"
+
+/*
+ *****************************************
+ * TZIC Registers                        *
+ *****************************************
+ */
+
+#define TZIC_INTCNTL	0x0000	/* Control register */
+#define TZIC_INTTYPE	0x0004	/* Controller Type register */
+#define TZIC_IMPID	0x0008	/* Distributor Implementer Identification */
+#define TZIC_PRIOMASK	0x000C	/* Priority Mask Reg */
+#define TZIC_SYNCCTRL	0x0010	/* Synchronizer Control register */
+#define TZIC_DSMINT	0x0014	/* DSM interrupt Holdoffregister */
+#define TZIC_INTSEC0(i)	(0x0080 + ((i) << 2)) /* Interrupt Security Reg 0 */
+#define TZIC_ENSET0(i)	(0x0100 + ((i) << 2)) /* Enable Set Reg 0 */
+#define TZIC_ENCLEAR0(i) (0x0180 + ((i) << 2)) /* Enable Clear Reg 0 */
+#define TZIC_SRCSET0	0x0200	/* Source Set Register 0 */
+#define TZIC_SRCCLAR0	0x0280	/* Source Clear Register 0 */
+#define TZIC_PRIORITY0	0x0400	/* Priority Register 0 */
+#define TZIC_PND0	0x0D00	/* Pending Register 0 */
+#define TZIC_HIPND(i)	(0x0D80+ ((i) << 2))	/* High Priority Pending Register */
+#define TZIC_WAKEUP0(i)	(0x0E00 + ((i) << 2))	/* Wakeup Config Register */
+#define TZIC_SWINT	0x0F00	/* Software Interrupt Rigger Register */
+#define TZIC_ID0	0x0FD0	/* Indentification Register 0 */
+
+void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */
+static struct irq_domain *domain;
+
+#define TZIC_NUM_IRQS 128
+
+#ifdef CONFIG_FIQ
+static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
+{
+	unsigned int index, mask, value;
+
+	index = irq >> 5;
+	if (unlikely(index >= 4))
+		return -EINVAL;
+	mask = 1U << (irq & 0x1F);
+
+	value = __raw_readl(tzic_base + TZIC_INTSEC0(index)) | mask;
+	if (type)
+		value &= ~mask;
+	__raw_writel(value, tzic_base + TZIC_INTSEC0(index));
+
+	return 0;
+}
+#else
+#define tzic_set_irq_fiq NULL
+#endif
+
+#ifdef CONFIG_PM
+static void tzic_irq_suspend(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	int idx = d->hwirq >> 5;
+
+	__raw_writel(gc->wake_active, tzic_base + TZIC_WAKEUP0(idx));
+}
+
+static void tzic_irq_resume(struct irq_data *d)
+{
+	int idx = d->hwirq >> 5;
+
+	__raw_writel(__raw_readl(tzic_base + TZIC_ENSET0(idx)),
+		     tzic_base + TZIC_WAKEUP0(idx));
+}
+
+#else
+#define tzic_irq_suspend NULL
+#define tzic_irq_resume NULL
+#endif
+
+static struct mxc_extra_irq tzic_extra_irq = {
+#ifdef CONFIG_FIQ
+	.set_irq_fiq = tzic_set_irq_fiq,
+#endif
+};
+
+static __init void tzic_init_gc(int idx, unsigned int irq_start)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+
+	gc = irq_alloc_generic_chip("tzic", 1, irq_start, tzic_base,
+				    handle_level_irq);
+	gc->private = &tzic_extra_irq;
+	gc->wake_enabled = IRQ_MSK(32);
+
+	ct = gc->chip_types;
+	ct->chip.irq_mask = irq_gc_mask_disable_reg;
+	ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
+	ct->chip.irq_set_wake = irq_gc_set_wake;
+	ct->chip.irq_suspend = tzic_irq_suspend;
+	ct->chip.irq_resume = tzic_irq_resume;
+	ct->regs.disable = TZIC_ENCLEAR0(idx);
+	ct->regs.enable = TZIC_ENSET0(idx);
+
+	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
+}
+
+asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
+{
+	u32 stat;
+	int i, irqofs, handled;
+
+	do {
+		handled = 0;
+
+		for (i = 0; i < 4; i++) {
+			stat = __raw_readl(tzic_base + TZIC_HIPND(i)) &
+				__raw_readl(tzic_base + TZIC_INTSEC0(i));
+
+			while (stat) {
+				handled = 1;
+				irqofs = fls(stat) - 1;
+				handle_IRQ(irq_find_mapping(domain,
+						irqofs + i * 32), regs);
+				stat &= ~(1 << irqofs);
+			}
+		}
+	} while (handled);
+}
+
+/*
+ * This function initializes the TZIC hardware and disables all the
+ * interrupts. It registers the interrupt enable and disable functions
+ * to the kernel for each interrupt source.
+ */
+void __init tzic_init_irq(void __iomem *irqbase)
+{
+	struct device_node *np;
+	int irq_base;
+	int i;
+
+	tzic_base = irqbase;
+	/* put the TZIC into the reset value with
+	 * all interrupts disabled
+	 */
+	i = __raw_readl(tzic_base + TZIC_INTCNTL);
+
+	__raw_writel(0x80010001, tzic_base + TZIC_INTCNTL);
+	__raw_writel(0x1f, tzic_base + TZIC_PRIOMASK);
+	__raw_writel(0x02, tzic_base + TZIC_SYNCCTRL);
+
+	for (i = 0; i < 4; i++)
+		__raw_writel(0xFFFFFFFF, tzic_base + TZIC_INTSEC0(i));
+
+	/* disable all interrupts */
+	for (i = 0; i < 4; i++)
+		__raw_writel(0xFFFFFFFF, tzic_base + TZIC_ENCLEAR0(i));
+
+	/* all IRQ no FIQ Warning :: No selection */
+
+	irq_base = irq_alloc_descs(-1, 0, TZIC_NUM_IRQS, numa_node_id());
+	WARN_ON(irq_base < 0);
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,tzic");
+	domain = irq_domain_add_legacy(np, TZIC_NUM_IRQS, irq_base, 0,
+				       &irq_domain_simple_ops, NULL);
+	WARN_ON(!domain);
+
+	for (i = 0; i < 4; i++, irq_base += 32)
+		tzic_init_gc(i, irq_base);
+
+#ifdef CONFIG_FIQ
+	/* Initialize FIQ */
+	init_FIQ(FIQ_START);
+#endif
+
+	pr_info("TrustZone Interrupt Controller (TZIC) initialized\n");
+}
+
+/**
+ * tzic_enable_wake() - enable wakeup interrupt
+ *
+ * @return			0 if successful; non-zero otherwise
+ *
+ * This function provides an interrupt synchronization point that is required
+ * by tzic enabled platforms before entering imx specific low power modes (ie,
+ * those low power modes beyond the WAIT_CLOCKED basic ARM WFI only mode).
+ */
+int tzic_enable_wake(void)
+{
+	unsigned int i;
+
+	__raw_writel(1, tzic_base + TZIC_DSMINT);
+	if (unlikely(__raw_readl(tzic_base + TZIC_DSMINT) == 0))
+		return -EAGAIN;
+
+	for (i = 0; i < 4; i++)
+		__raw_writel(__raw_readl(tzic_base + TZIC_ENSET0(i)),
+			     tzic_base + TZIC_WAKEUP0(i));
+
+	return 0;
+}
diff --git a/arch/arm/mach-imx/ulpi.c b/arch/arm/mach-imx/ulpi.c
new file mode 100644
index 0000000..0f05195
--- /dev/null
+++ b/arch/arm/mach-imx/ulpi.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ * Copyright 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+
+#include "ulpi.h"
+
+/* ULPIVIEW register bits */
+#define ULPIVW_WU		(1 << 31)	/* Wakeup */
+#define ULPIVW_RUN		(1 << 30)	/* read/write run */
+#define ULPIVW_WRITE		(1 << 29)	/* 0 = read  1 = write */
+#define ULPIVW_SS		(1 << 27)	/* SyncState */
+#define ULPIVW_PORT_MASK	0x07	/* Port field */
+#define ULPIVW_PORT_SHIFT	24
+#define ULPIVW_ADDR_MASK	0xff	/* data address field */
+#define ULPIVW_ADDR_SHIFT	16
+#define ULPIVW_RDATA_MASK	0xff	/* read data field */
+#define ULPIVW_RDATA_SHIFT	8
+#define ULPIVW_WDATA_MASK	0xff	/* write data field */
+#define ULPIVW_WDATA_SHIFT	0
+
+static int ulpi_poll(void __iomem *view, u32 bit)
+{
+	int timeout = 10000;
+
+	while (timeout--) {
+		u32 data = __raw_readl(view);
+
+		if (!(data & bit))
+			return 0;
+
+		cpu_relax();
+	};
+
+	printk(KERN_WARNING "timeout polling for ULPI device\n");
+
+	return -ETIMEDOUT;
+}
+
+static int ulpi_read(struct usb_phy *otg, u32 reg)
+{
+	int ret;
+	void __iomem *view = otg->io_priv;
+
+	/* make sure interface is running */
+	if (!(__raw_readl(view) & ULPIVW_SS)) {
+		__raw_writel(ULPIVW_WU, view);
+
+		/* wait for wakeup */
+		ret = ulpi_poll(view, ULPIVW_WU);
+		if (ret)
+			return ret;
+	}
+
+	/* read the register */
+	__raw_writel((ULPIVW_RUN | (reg << ULPIVW_ADDR_SHIFT)), view);
+
+	/* wait for completion */
+	ret = ulpi_poll(view, ULPIVW_RUN);
+	if (ret)
+		return ret;
+
+	return (__raw_readl(view) >> ULPIVW_RDATA_SHIFT) & ULPIVW_RDATA_MASK;
+}
+
+static int ulpi_write(struct usb_phy *otg, u32 val, u32 reg)
+{
+	int ret;
+	void __iomem *view = otg->io_priv;
+
+	/* make sure the interface is running */
+	if (!(__raw_readl(view) & ULPIVW_SS)) {
+		__raw_writel(ULPIVW_WU, view);
+		/* wait for wakeup */
+		ret = ulpi_poll(view, ULPIVW_WU);
+		if (ret)
+			return ret;
+	}
+
+	__raw_writel((ULPIVW_RUN | ULPIVW_WRITE |
+		      (reg << ULPIVW_ADDR_SHIFT) |
+		      ((val & ULPIVW_WDATA_MASK) << ULPIVW_WDATA_SHIFT)), view);
+
+	/* wait for completion */
+	return ulpi_poll(view, ULPIVW_RUN);
+}
+
+struct usb_phy_io_ops mxc_ulpi_access_ops = {
+	.read	= ulpi_read,
+	.write	= ulpi_write,
+};
+EXPORT_SYMBOL_GPL(mxc_ulpi_access_ops);
+
+struct usb_phy *imx_otg_ulpi_create(unsigned int flags)
+{
+	return otg_ulpi_create(&mxc_ulpi_access_ops, flags);
+}
diff --git a/arch/arm/mach-imx/ulpi.h b/arch/arm/mach-imx/ulpi.h
new file mode 100644
index 0000000..42bdaca
--- /dev/null
+++ b/arch/arm/mach-imx/ulpi.h
@@ -0,0 +1,16 @@
+#ifndef __MACH_ULPI_H
+#define __MACH_ULPI_H
+
+#ifdef CONFIG_USB_ULPI
+struct usb_phy *imx_otg_ulpi_create(unsigned int flags);
+#else
+static inline struct usb_phy *imx_otg_ulpi_create(unsigned int flags)
+{
+	return NULL;
+}
+#endif
+
+extern struct usb_phy_io_ops mxc_ulpi_access_ops;
+
+#endif /* __MACH_ULPI_H */
+
diff --git a/arch/arm/mach-integrator/Kconfig b/arch/arm/mach-integrator/Kconfig
index 350e266..abeff25 100644
--- a/arch/arm/mach-integrator/Kconfig
+++ b/arch/arm/mach-integrator/Kconfig
@@ -8,6 +8,7 @@ config ARCH_INTEGRATOR_AP
 	select MIGHT_HAVE_PCI
 	select SERIAL_AMBA_PL010
 	select SERIAL_AMBA_PL010_CONSOLE
+	select SOC_BUS
 	help
 	  Include support for the ARM(R) Integrator/AP and
 	  Integrator/PP2 platforms.
@@ -19,6 +20,7 @@ config ARCH_INTEGRATOR_CP
 	select PLAT_VERSATILE_CLCD
 	select SERIAL_AMBA_PL011
 	select SERIAL_AMBA_PL011_CONSOLE
+	select SOC_BUS
 	help
 	  Include support for the ARM(R) Integrator CP platform.
 
diff --git a/arch/arm/mach-integrator/common.h b/arch/arm/mach-integrator/common.h
index c3ff21b..79197d8 100644
--- a/arch/arm/mach-integrator/common.h
+++ b/arch/arm/mach-integrator/common.h
@@ -1,6 +1,12 @@
 #include <linux/amba/serial.h>
-extern struct amba_pl010_data integrator_uart_data;
+#ifdef CONFIG_ARCH_INTEGRATOR_AP
+extern struct amba_pl010_data ap_uart_data;
+#else
+/* Not used without Integrator/AP support anyway */
+struct amba_pl010_data ap_uart_data {};
+#endif
 void integrator_init_early(void);
 int integrator_init(bool is_cp);
 void integrator_reserve(void);
 void integrator_restart(char, const char *);
+void integrator_init_sysfs(struct device *parent, u32 id);
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index ea22a17..39c060f 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -18,10 +18,10 @@
 #include <linux/memblock.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
-#include <linux/termios.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/serial.h>
 #include <linux/io.h>
+#include <linux/stat.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
@@ -46,10 +46,10 @@ 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, &integrator_uart_data);
+	INTEGRATOR_UART0_BASE, INTEGRATOR_UART0_IRQ, NULL);
 
 static AMBA_APB_DEVICE(uart1, "uart1", 0,
-	INTEGRATOR_UART1_BASE, INTEGRATOR_UART1_IRQ, &integrator_uart_data);
+	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);
@@ -77,6 +77,8 @@ int __init integrator_init(bool is_cp)
 		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++) {
@@ -89,49 +91,6 @@ int __init integrator_init(bool is_cp)
 
 #endif
 
-/*
- * On the Integrator platform, the port RTS and DTR are provided by
- * bits in the following SC_CTRLS register bits:
- *        RTS  DTR
- *  UART0  7    6
- *  UART1  5    4
- */
-#define SC_CTRLC	__io_address(INTEGRATOR_SC_CTRLC)
-#define SC_CTRLS	__io_address(INTEGRATOR_SC_CTRLS)
-
-static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *base, unsigned int mctrl)
-{
-	unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask;
-	u32 phybase = dev->res.start;
-
-	if (phybase == INTEGRATOR_UART0_BASE) {
-		/* UART0 */
-		rts_mask = 1 << 4;
-		dtr_mask = 1 << 5;
-	} else {
-		/* UART1 */
-		rts_mask = 1 << 6;
-		dtr_mask = 1 << 7;
-	}
-
-	if (mctrl & TIOCM_RTS)
-		ctrlc |= rts_mask;
-	else
-		ctrls |= rts_mask;
-
-	if (mctrl & TIOCM_DTR)
-		ctrlc |= dtr_mask;
-	else
-		ctrls |= dtr_mask;
-
-	__raw_writel(ctrls, SC_CTRLS);
-	__raw_writel(ctrlc, SC_CTRLC);
-}
-
-struct amba_pl010_data integrator_uart_data = {
-	.set_mctrl = integrator_uart_set_mctrl,
-};
-
 static DEFINE_RAW_SPINLOCK(cm_lock);
 
 /**
@@ -169,3 +128,93 @@ void integrator_restart(char mode, const char *cmd)
 {
 	cm_control(CM_CTRL_RESET, CM_CTRL_RESET);
 }
+
+static u32 integrator_id;
+
+static ssize_t intcp_get_manf(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	return sprintf(buf, "%02x\n", integrator_id >> 24);
+}
+
+static struct device_attribute intcp_manf_attr =
+	__ATTR(manufacturer,  S_IRUGO, intcp_get_manf,  NULL);
+
+static ssize_t intcp_get_arch(struct device *dev,
+			      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);
+}
+
+static struct device_attribute intcp_arch_attr =
+	__ATTR(architecture,  S_IRUGO, intcp_get_arch,  NULL);
+
+static ssize_t intcp_get_fpga(struct device *dev,
+			      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);
+}
+
+static struct device_attribute intcp_fpga_attr =
+	__ATTR(fpga,  S_IRUGO, intcp_get_fpga,  NULL);
+
+static ssize_t intcp_get_build(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	return sprintf(buf, "%02x\n", (integrator_id >> 4) & 0xFF);
+}
+
+static struct device_attribute intcp_build_attr =
+	__ATTR(build,  S_IRUGO, intcp_get_build,  NULL);
+
+
+
+void integrator_init_sysfs(struct device *parent, u32 id)
+{
+	integrator_id = id;
+	device_create_file(parent, &intcp_manf_attr);
+	device_create_file(parent, &intcp_arch_attr);
+	device_create_file(parent, &intcp_fpga_attr);
+	device_create_file(parent, &intcp_build_attr);
+}
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index e428f3a..b3d86d7 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -21,10 +21,9 @@
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
 #include <linux/io.h>
+#include <linux/platform_data/clk-integrator.h>
 #include <linux/slab.h>
-#include <linux/clkdev.h>
 
-#include <asm/hardware/icst.h>
 #include <mach/lm.h>
 #include <mach/impd1.h>
 #include <asm/sizes.h>
@@ -36,45 +35,6 @@ MODULE_PARM_DESC(lmid, "logic module stack position");
 
 struct impd1_module {
 	void __iomem	*base;
-	struct clk	vcos[2];
-	struct clk_lookup *clks[3];
-};
-
-static const struct icst_params impd1_vco_params = {
-	.ref		= 24000000,	/* 24 MHz */
-	.vco_max	= ICST525_VCO_MAX_3V,
-	.vco_min	= ICST525_VCO_MIN,
-	.vd_min		= 12,
-	.vd_max		= 519,
-	.rd_min		= 3,
-	.rd_max		= 120,
-	.s2div		= icst525_s2div,
-	.idx2s		= icst525_idx2s,
-};
-
-static void impd1_setvco(struct clk *clk, struct icst_vco vco)
-{
-	struct impd1_module *impd1 = clk->data;
-	u32 val = vco.v | (vco.r << 9) | (vco.s << 16);
-
-	writel(0xa05f, impd1->base + IMPD1_LOCK);
-	writel(val, clk->vcoreg);
-	writel(0, impd1->base + IMPD1_LOCK);
-
-#ifdef DEBUG
-	vco.v = val & 0x1ff;
-	vco.r = (val >> 9) & 0x7f;
-	vco.s = (val >> 16) & 7;
-
-	pr_debug("IM-PD1: VCO%d clock is %ld Hz\n",
-		 vconr, icst525_hz(&impd1_vco_params, vco));
-#endif
-}
-
-static const struct clk_ops impd1_clk_ops = {
-	.round	= icst_clk_round,
-	.set	= icst_clk_set,
-	.setvco	= impd1_setvco,
 };
 
 void impd1_tweak_control(struct device *dev, u32 mask, u32 val)
@@ -344,10 +304,6 @@ static struct impd1_device impd1_devs[] = {
 	}
 };
 
-static struct clk fixed_14745600 = {
-	.rate = 14745600,
-};
-
 static int impd1_probe(struct lm_device *dev)
 {
 	struct impd1_module *impd1;
@@ -376,23 +332,7 @@ static int impd1_probe(struct lm_device *dev)
 	printk("IM-PD1 found at 0x%08lx\n",
 		(unsigned long)dev->resource.start);
 
-	for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) {
-		impd1->vcos[i].ops = &impd1_clk_ops,
-		impd1->vcos[i].owner = THIS_MODULE,
-		impd1->vcos[i].params = &impd1_vco_params,
-		impd1->vcos[i].data = impd1;
-	}
-	impd1->vcos[0].vcoreg = impd1->base + IMPD1_OSC1;
-	impd1->vcos[1].vcoreg = impd1->base + IMPD1_OSC2;
-
-	impd1->clks[0] = clkdev_alloc(&impd1->vcos[0], NULL, "lm%x:01000",
-					dev->id);
-	impd1->clks[1] = clkdev_alloc(&fixed_14745600, NULL, "lm%x:00100",
-					dev->id);
-	impd1->clks[2] = clkdev_alloc(&fixed_14745600, NULL, "lm%x:00200",
-					dev->id);
-	for (i = 0; i < ARRAY_SIZE(impd1->clks); i++)
-		clkdev_add(impd1->clks[i]);
+	integrator_impd1_clk_init(impd1->base, dev->id);
 
 	for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) {
 		struct impd1_device *idev = impd1_devs + i;
@@ -431,12 +371,9 @@ static int impd1_remove_one(struct device *dev, void *data)
 static void impd1_remove(struct lm_device *dev)
 {
 	struct impd1_module *impd1 = lm_get_drvdata(dev);
-	int i;
 
 	device_for_each_child(&dev->dev, NULL, impd1_remove_one);
-
-	for (i = 0; i < ARRAY_SIZE(impd1->clks); i++)
-		clkdev_drop(impd1->clks[i]);
+	integrator_impd1_clk_exit(dev->id);
 
 	lm_set_drvdata(dev, NULL);
 
diff --git a/arch/arm/mach-integrator/include/mach/irqs.h b/arch/arm/mach-integrator/include/mach/irqs.h
index 7371018..eff0ada 100644
--- a/arch/arm/mach-integrator/include/mach/irqs.h
+++ b/arch/arm/mach-integrator/include/mach/irqs.h
@@ -19,64 +19,63 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-/* 
- *  Interrupt numbers
+/*
+ * 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			1
-#define IRQ_SOFTINT			1
-#define IRQ_UARTINT0			2
-#define IRQ_UARTINT1			3
-#define IRQ_KMIINT0			4
-#define IRQ_KMIINT1			5
-#define IRQ_TIMERINT0			6
-#define IRQ_TIMERINT1			7
-#define IRQ_TIMERINT2			8
-#define IRQ_RTCINT			9
-#define IRQ_AP_EXPINT0			10
-#define IRQ_AP_EXPINT1			11
-#define IRQ_AP_EXPINT2			12
-#define IRQ_AP_EXPINT3			13
-#define IRQ_AP_PCIINT0			14
-#define IRQ_AP_PCIINT1			15
-#define IRQ_AP_PCIINT2			16
-#define IRQ_AP_PCIINT3			17
-#define IRQ_AP_V3INT			18
-#define IRQ_AP_CPINT0			19
-#define IRQ_AP_CPINT1			20
-#define IRQ_AP_LBUSTIMEOUT 		21
-#define IRQ_AP_APCINT			22
-#define IRQ_CP_CLCDCINT			23
-#define IRQ_CP_MMCIINT0			24
-#define IRQ_CP_MMCIINT1			25
-#define IRQ_CP_AACIINT			26
-#define IRQ_CP_CPPLDINT			27
-#define IRQ_CP_ETHINT			28
-#define IRQ_CP_TSPENINT			29
-#define IRQ_PIC_END			29
+#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			32
-#define IRQ_CM_SOFTINT			32
-#define IRQ_CM_COMMRX			33
-#define IRQ_CM_COMMTX			34
-#define IRQ_CIC_END			34
+#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			35
-#define IRQ_SIC_CP_SOFTINT		35
-#define IRQ_SIC_CP_RI0			36
-#define IRQ_SIC_CP_RI1			37
-#define IRQ_SIC_CP_CARDIN		38
-#define IRQ_SIC_CP_LMINT0		39
-#define IRQ_SIC_CP_LMINT1		40
-#define IRQ_SIC_CP_LMINT2		41
-#define IRQ_SIC_CP_LMINT3		42
-#define IRQ_SIC_CP_LMINT4		43
-#define IRQ_SIC_CP_LMINT5		44
-#define IRQ_SIC_CP_LMINT6		45
-#define IRQ_SIC_CP_LMINT7		46
-#define IRQ_SIC_END			46
-
-#define NR_IRQS_INTEGRATOR_AP		34
-#define NR_IRQS_INTEGRATOR_CP		47
+#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/include/mach/platform.h b/arch/arm/mach-integrator/include/mach/platform.h
index efeac5d..be5859e 100644
--- a/arch/arm/mach-integrator/include/mach/platform.h
+++ b/arch/arm/mach-integrator/include/mach/platform.h
@@ -190,7 +190,6 @@
 #define INTEGRATOR_SC_CTRLC_OFFSET      0x0C
 #define INTEGRATOR_SC_DEC_OFFSET        0x10
 #define INTEGRATOR_SC_ARB_OFFSET        0x14
-#define INTEGRATOR_SC_PCIENABLE_OFFSET  0x18
 #define INTEGRATOR_SC_LOCK_OFFSET       0x1C
 
 #define INTEGRATOR_SC_BASE              0x11000000
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index e6617c1..11e2a41 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -31,12 +31,16 @@
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/irqchip/versatile-fpga.h>
 #include <linux/mtd/physmap.h>
 #include <linux/clk.h>
 #include <linux/platform_data/clk-integrator.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
+#include <linux/stat.h>
+#include <linux/sys_soc.h>
+#include <linux/termios.h>
 #include <video/vga.h>
 
 #include <mach/hardware.h>
@@ -56,11 +60,12 @@
 #include <asm/mach/pci.h>
 #include <asm/mach/time.h>
 
-#include <plat/fpga-irq.h>
-
 #include "common.h"
 
-/* 
+/* Base address to the AP system controller */
+void __iomem *ap_syscon_base;
+
+/*
  * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx
  * is the (PA >> 12).
  *
@@ -68,7 +73,6 @@
  * just for now).
  */
 #define VA_IC_BASE	__io_address(INTEGRATOR_IC_BASE)
-#define VA_SC_BASE	__io_address(INTEGRATOR_SC_BASE)
 #define VA_EBI_BASE	__io_address(INTEGRATOR_EBI_BASE)
 #define VA_CMIC_BASE	__io_address(INTEGRATOR_HDR_IC)
 
@@ -97,11 +101,6 @@ static struct map_desc ap_io_desc[] __initdata = {
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	= IO_ADDRESS(INTEGRATOR_SC_BASE),
-		.pfn		= __phys_to_pfn(INTEGRATOR_SC_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE
-	}, {
 		.virtual	= IO_ADDRESS(INTEGRATOR_EBI_BASE),
 		.pfn		= __phys_to_pfn(INTEGRATOR_EBI_BASE),
 		.length		= SZ_4K,
@@ -122,11 +121,6 @@ static struct map_desc ap_io_desc[] __initdata = {
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	= IO_ADDRESS(INTEGRATOR_UART1_BASE),
-		.pfn		= __phys_to_pfn(INTEGRATOR_UART1_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE
-	}, {
 		.virtual	= IO_ADDRESS(INTEGRATOR_DBG_BASE),
 		.pfn		= __phys_to_pfn(INTEGRATOR_DBG_BASE),
 		.length		= SZ_4K,
@@ -201,8 +195,6 @@ device_initcall(irq_syscore_init);
 /*
  * Flash handling.
  */
-#define SC_CTRLC (VA_SC_BASE + INTEGRATOR_SC_CTRLC_OFFSET)
-#define SC_CTRLS (VA_SC_BASE + INTEGRATOR_SC_CTRLS_OFFSET)
 #define EBI_CSR1 (VA_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET)
 #define EBI_LOCK (VA_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET)
 
@@ -210,7 +202,8 @@ static int ap_flash_init(struct platform_device *dev)
 {
 	u32 tmp;
 
-	writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
+	writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP,
+	       ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
 
 	tmp = readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE;
 	writel(tmp, EBI_CSR1);
@@ -227,7 +220,8 @@ static void ap_flash_exit(struct platform_device *dev)
 {
 	u32 tmp;
 
-	writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
+	writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP,
+	       ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
 
 	tmp = readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE;
 	writel(tmp, EBI_CSR1);
@@ -241,9 +235,12 @@ static void ap_flash_exit(struct platform_device *dev)
 
 static void ap_flash_set_vpp(struct platform_device *pdev, int on)
 {
-	void __iomem *reg = on ? SC_CTRLS : SC_CTRLC;
-
-	writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg);
+	if (on)
+		writel(INTEGRATOR_SC_CTRL_nFLVPPEN,
+		       ap_syscon_base + INTEGRATOR_SC_CTRLS_OFFSET);
+	else
+		writel(INTEGRATOR_SC_CTRL_nFLVPPEN,
+		       ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
 }
 
 static struct physmap_flash_data ap_flash_data = {
@@ -254,6 +251,45 @@ static struct physmap_flash_data ap_flash_data = {
 };
 
 /*
+ * For the PL010 found in the Integrator/AP some of the UART control is
+ * implemented in the system controller and accessed using a callback
+ * from the driver.
+ */
+static void integrator_uart_set_mctrl(struct amba_device *dev,
+				void __iomem *base, unsigned int mctrl)
+{
+	unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask;
+	u32 phybase = dev->res.start;
+
+	if (phybase == INTEGRATOR_UART0_BASE) {
+		/* UART0 */
+		rts_mask = 1 << 4;
+		dtr_mask = 1 << 5;
+	} else {
+		/* UART1 */
+		rts_mask = 1 << 6;
+		dtr_mask = 1 << 7;
+	}
+
+	if (mctrl & TIOCM_RTS)
+		ctrlc |= rts_mask;
+	else
+		ctrls |= rts_mask;
+
+	if (mctrl & TIOCM_DTR)
+		ctrlc |= dtr_mask;
+	else
+		ctrls |= dtr_mask;
+
+	__raw_writel(ctrls, ap_syscon_base + INTEGRATOR_SC_CTRLS_OFFSET);
+	__raw_writel(ctrlc, ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
+}
+
+struct amba_pl010_data ap_uart_data = {
+	.set_mctrl = integrator_uart_set_mctrl,
+};
+
+/*
  * Where is the timer (VA)?
  */
 #define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE)
@@ -450,9 +486,9 @@ static struct of_dev_auxdata ap_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_RTC_BASE,
 		"rtc", NULL),
 	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE,
-		"uart0", &integrator_uart_data),
+		"uart0", &ap_uart_data),
 	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE,
-		"uart1", &integrator_uart_data),
+		"uart1", &ap_uart_data),
 	OF_DEV_AUXDATA("arm,primecell", KMI0_BASE,
 		"kmi0", NULL),
 	OF_DEV_AUXDATA("arm,primecell", KMI1_BASE,
@@ -465,12 +501,60 @@ static struct of_dev_auxdata ap_auxdata_lookup[] __initdata = {
 static void __init ap_init_of(void)
 {
 	unsigned long sc_dec;
+	struct device_node *root;
+	struct device_node *syscon;
+	struct device *parent;
+	struct soc_device *soc_dev;
+	struct soc_device_attribute *soc_dev_attr;
+	u32 ap_sc_id;
+	int err;
 	int i;
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			ap_auxdata_lookup, NULL);
+	/* Here we create an SoC device for the root node */
+	root = of_find_node_by_path("/");
+	if (!root)
+		return;
+	syscon = of_find_node_by_path("/syscon");
+	if (!syscon)
+		return;
+
+	ap_syscon_base = of_iomap(syscon, 0);
+	if (!ap_syscon_base)
+		return;
+
+	ap_sc_id = readl(ap_syscon_base);
+
+	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+	if (!soc_dev_attr)
+		return;
+
+	err = of_property_read_string(root, "compatible",
+				      &soc_dev_attr->soc_id);
+	if (err)
+		return;
+	err = of_property_read_string(root, "model", &soc_dev_attr->machine);
+	if (err)
+		return;
+	soc_dev_attr->family = "Integrator";
+	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c",
+					   'A' + (ap_sc_id & 0x0f));
+
+	soc_dev = soc_device_register(soc_dev_attr);
+	if (IS_ERR_OR_NULL(soc_dev)) {
+		kfree(soc_dev_attr->revision);
+		kfree(soc_dev_attr);
+		return;
+	}
+
+	parent = soc_device_to_device(soc_dev);
+
+	if (!IS_ERR_OR_NULL(parent))
+		integrator_init_sysfs(parent, ap_sc_id);
 
-	sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
+	of_platform_populate(root, of_default_bus_match_table,
+			ap_auxdata_lookup, parent);
+
+	sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET);
 	for (i = 0; i < 4; i++) {
 		struct lm_device *lmdev;
 
@@ -499,7 +583,6 @@ static const char * ap_dt_board_compat[] = {
 DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)")
 	.reserve	= integrator_reserve,
 	.map_io		= ap_map_io,
-	.nr_irqs	= NR_IRQS_INTEGRATOR_AP,
 	.init_early	= ap_init_early,
 	.init_irq	= ap_init_irq_of,
 	.handle_irq	= fpga_handle_irq,
@@ -514,6 +597,27 @@ MACHINE_END
 #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_syscon_base = __io_address(INTEGRATOR_SC_BASE);
+	ap_map_io();
+}
+
+/*
  * This is where non-devicetree initialization code is collected and stashed
  * for eventual deletion.
  */
@@ -581,7 +685,7 @@ static void __init ap_init(void)
 
 	platform_device_register(&cfi_flash_device);
 
-	sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
+	sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET);
 	for (i = 0; i < 4; i++) {
 		struct lm_device *lmdev;
 
@@ -608,8 +712,7 @@ MACHINE_START(INTEGRATOR, "ARM-Integrator")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
 	.atag_offset	= 0x100,
 	.reserve	= integrator_reserve,
-	.map_io		= ap_map_io,
-	.nr_irqs	= NR_IRQS_INTEGRATOR_AP,
+	.map_io		= ap_map_io_atag,
 	.init_early	= ap_init_early,
 	.init_irq	= ap_init_irq,
 	.handle_irq	= fpga_handle_irq,
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 5b08e8e..7322838 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -20,12 +20,14 @@
 #include <linux/amba/clcd.h>
 #include <linux/amba/mmci.h>
 #include <linux/io.h>
+#include <linux/irqchip/versatile-fpga.h>
 #include <linux/gfp.h>
 #include <linux/mtd/physmap.h>
 #include <linux/platform_data/clk-integrator.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
+#include <linux/sys_soc.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
@@ -46,16 +48,17 @@
 #include <asm/hardware/timer-sp.h>
 
 #include <plat/clcd.h>
-#include <plat/fpga-irq.h>
 #include <plat/sched_clock.h>
 
 #include "common.h"
 
+/* Base address to the CP controller */
+static void __iomem *intcp_con_base;
+
 #define INTCP_PA_FLASH_BASE		0x24000000
 
 #define INTCP_PA_CLCD_BASE		0xc0000000
 
-#define INTCP_VA_CTRL_BASE		__io_address(INTEGRATOR_CP_CTL_BASE)
 #define INTCP_FLASHPROG			0x04
 #define CINTEGRATOR_FLASHPROG_FLVPPEN	(1 << 0)
 #define CINTEGRATOR_FLASHPROG_FLWREN	(1 << 1)
@@ -82,11 +85,6 @@ static struct map_desc intcp_io_desc[] __initdata = {
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	= IO_ADDRESS(INTEGRATOR_SC_BASE),
-		.pfn		= __phys_to_pfn(INTEGRATOR_SC_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE
-	}, {
 		.virtual	= IO_ADDRESS(INTEGRATOR_EBI_BASE),
 		.pfn		= __phys_to_pfn(INTEGRATOR_EBI_BASE),
 		.length		= SZ_4K,
@@ -107,11 +105,6 @@ static struct map_desc intcp_io_desc[] __initdata = {
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	= IO_ADDRESS(INTEGRATOR_UART1_BASE),
-		.pfn		= __phys_to_pfn(INTEGRATOR_UART1_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE
-	}, {
 		.virtual	= IO_ADDRESS(INTEGRATOR_DBG_BASE),
 		.pfn		= __phys_to_pfn(INTEGRATOR_DBG_BASE),
 		.length		= SZ_4K,
@@ -126,11 +119,6 @@ static struct map_desc intcp_io_desc[] __initdata = {
 		.pfn		= __phys_to_pfn(INTEGRATOR_CP_SIC_BASE),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
-	}, {
-		.virtual	= IO_ADDRESS(INTEGRATOR_CP_CTL_BASE),
-		.pfn		= __phys_to_pfn(INTEGRATOR_CP_CTL_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE
 	}
 };
 
@@ -146,9 +134,9 @@ static int intcp_flash_init(struct platform_device *dev)
 {
 	u32 val;
 
-	val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+	val = readl(intcp_con_base + INTCP_FLASHPROG);
 	val |= CINTEGRATOR_FLASHPROG_FLWREN;
-	writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+	writel(val, intcp_con_base + INTCP_FLASHPROG);
 
 	return 0;
 }
@@ -157,21 +145,21 @@ static void intcp_flash_exit(struct platform_device *dev)
 {
 	u32 val;
 
-	val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+	val = readl(intcp_con_base + INTCP_FLASHPROG);
 	val &= ~(CINTEGRATOR_FLASHPROG_FLVPPEN|CINTEGRATOR_FLASHPROG_FLWREN);
-	writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+	writel(val, intcp_con_base + INTCP_FLASHPROG);
 }
 
 static void intcp_flash_set_vpp(struct platform_device *pdev, int on)
 {
 	u32 val;
 
-	val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+	val = readl(intcp_con_base + INTCP_FLASHPROG);
 	if (on)
 		val |= CINTEGRATOR_FLASHPROG_FLVPPEN;
 	else
 		val &= ~CINTEGRATOR_FLASHPROG_FLVPPEN;
-	writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+	writel(val, intcp_con_base + INTCP_FLASHPROG);
 }
 
 static struct physmap_flash_data intcp_flash_data = {
@@ -190,7 +178,7 @@ static struct physmap_flash_data intcp_flash_data = {
 static unsigned int mmc_status(struct device *dev)
 {
 	unsigned int status = readl(__io_address(0xca000000 + 4));
-	writel(8, __io_address(INTEGRATOR_CP_CTL_BASE + 8));
+	writel(8, intcp_con_base + 8);
 
 	return status & 8;
 }
@@ -318,9 +306,9 @@ static struct of_dev_auxdata intcp_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_RTC_BASE,
 		"rtc", NULL),
 	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE,
-		"uart0", &integrator_uart_data),
+		"uart0", NULL),
 	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE,
-		"uart1", &integrator_uart_data),
+		"uart1", NULL),
 	OF_DEV_AUXDATA("arm,primecell", KMI0_BASE,
 		"kmi0", NULL),
 	OF_DEV_AUXDATA("arm,primecell", KMI1_BASE,
@@ -338,8 +326,57 @@ static struct of_dev_auxdata intcp_auxdata_lookup[] __initdata = {
 
 static void __init intcp_init_of(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table,
-			intcp_auxdata_lookup, NULL);
+	struct device_node *root;
+	struct device_node *cpcon;
+	struct device *parent;
+	struct soc_device *soc_dev;
+	struct soc_device_attribute *soc_dev_attr;
+	u32 intcp_sc_id;
+	int err;
+
+	/* Here we create an SoC device for the root node */
+	root = of_find_node_by_path("/");
+	if (!root)
+		return;
+	cpcon = of_find_node_by_path("/cpcon");
+	if (!cpcon)
+		return;
+
+	intcp_con_base = of_iomap(cpcon, 0);
+	if (!intcp_con_base)
+		return;
+
+	intcp_sc_id = readl(intcp_con_base);
+
+	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+	if (!soc_dev_attr)
+		return;
+
+	err = of_property_read_string(root, "compatible",
+				      &soc_dev_attr->soc_id);
+	if (err)
+		return;
+	err = of_property_read_string(root, "model", &soc_dev_attr->machine);
+	if (err)
+		return;
+	soc_dev_attr->family = "Integrator";
+	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c",
+					   'A' + (intcp_sc_id & 0x0f));
+
+	soc_dev = soc_device_register(soc_dev_attr);
+	if (IS_ERR_OR_NULL(soc_dev)) {
+		kfree(soc_dev_attr->revision);
+		kfree(soc_dev_attr);
+		return;
+	}
+
+	parent = soc_device_to_device(soc_dev);
+
+	if (!IS_ERR_OR_NULL(parent))
+		integrator_init_sysfs(parent, intcp_sc_id);
+
+	of_platform_populate(root, of_default_bus_match_table,
+			intcp_auxdata_lookup, parent);
 }
 
 static const char * intcp_dt_board_compat[] = {
@@ -350,7 +387,6 @@ static const char * intcp_dt_board_compat[] = {
 DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
 	.reserve	= integrator_reserve,
 	.map_io		= intcp_map_io,
-	.nr_irqs	= NR_IRQS_INTEGRATOR_CP,
 	.init_early	= intcp_init_early,
 	.init_irq	= intcp_init_irq_of,
 	.handle_irq	= fpga_handle_irq,
@@ -365,6 +401,28 @@ MACHINE_END
 #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.
  */
@@ -423,7 +481,7 @@ 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 - IRQ_PIC_START));
+	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));
@@ -503,8 +561,7 @@ MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
 	.atag_offset	= 0x100,
 	.reserve	= integrator_reserve,
-	.map_io		= intcp_map_io,
-	.nr_irqs	= NR_IRQS_INTEGRATOR_CP,
+	.map_io		= intcp_map_io_atag,
 	.init_early	= intcp_init_early,
 	.init_irq	= intcp_init_irq,
 	.handle_irq	= fpga_handle_irq,
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index bbeca59..be50e79 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -191,12 +191,9 @@ static void __iomem *v3_open_config_window(struct pci_bus *bus,
 	/*
 	 * Trap out illegal values
 	 */
-	if (offset > 255)
-		BUG();
-	if (busnr > 255)
-		BUG();
-	if (devfn > 255)
-		BUG();
+	BUG_ON(offset > 255);
+	BUG_ON(busnr > 255);
+	BUG_ON(devfn > 255);
 
 	if (busnr == 0) {
 		int slot = PCI_SLOT(devfn);
@@ -388,9 +385,10 @@ static int __init pci_v3_setup_resources(struct pci_sys_data *sys)
  * means I can't get additional information on the reason for the pm2fb
  * problems.  I suppose I'll just have to mind-meld with the machine. ;)
  */
-#define SC_PCI     __io_address(INTEGRATOR_SC_PCIENABLE)
-#define SC_LBFADDR __io_address(INTEGRATOR_SC_BASE + 0x20)
-#define SC_LBFCODE __io_address(INTEGRATOR_SC_BASE + 0x24)
+static void __iomem *ap_syscon_base;
+#define INTEGRATOR_SC_PCIENABLE_OFFSET	0x18
+#define INTEGRATOR_SC_LBFADDR_OFFSET	0x20
+#define INTEGRATOR_SC_LBFCODE_OFFSET	0x24
 
 static int
 v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
@@ -401,13 +399,13 @@ v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 	char buf[128];
 
 	sprintf(buf, "V3 fault: addr 0x%08lx, FSR 0x%03x, PC 0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n",
-		addr, fsr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255,
+		addr, fsr, 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));
 	printk(KERN_DEBUG "%s", buf);
 #endif
 
 	v3_writeb(V3_LB_ISTAT, 0);
-	__raw_writel(3, SC_PCI);
+	__raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET);
 
 	/*
 	 * If the instruction being executed was a read,
@@ -449,15 +447,15 @@ static irqreturn_t v3_irq(int dummy, void *devid)
 
 	sprintf(buf, "V3 int %d: pc=0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x "
 		"ISTAT=%02x\n", IRQ_AP_V3INT, pc, instr,
-		__raw_readl(SC_LBFADDR),
-		__raw_readl(SC_LBFCODE) & 255,
+		__raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFADDR_OFFSET),
+		__raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFCODE_OFFSET) & 255,
 		v3_readb(V3_LB_ISTAT));
 	printascii(buf);
 #endif
 
 	v3_writew(V3_PCI_STAT, 0xf000);
 	v3_writeb(V3_LB_ISTAT, 0);
-	__raw_writel(3, SC_PCI);
+	__raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET);
 
 #ifdef CONFIG_DEBUG_LL
 	/*
@@ -480,6 +478,10 @@ int __init pci_v3_setup(int nr, struct pci_sys_data *sys)
 	if (nr == 0) {
 		sys->mem_offset = PHYS_PCI_MEM_BASE;
 		ret = pci_v3_setup_resources(sys);
+		/* Remap the Integrator system controller */
+		ap_syscon_base = ioremap(INTEGRATOR_SC_BASE, 0x100);
+		if (!ap_syscon_base)
+			return -EINVAL;
 	}
 
 	return ret;
@@ -568,7 +570,7 @@ void __init pci_v3_preinit(void)
 	v3_writeb(V3_LB_ISTAT, 0);
 	v3_writew(V3_LB_CFG, v3_readw(V3_LB_CFG) | (1 << 10));
 	v3_writeb(V3_LB_IMASK, 0x28);
-	__raw_writel(3, SC_PCI);
+	__raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET);
 
 	/*
 	 * Grab the PCI error interrupt.
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index 1694f01..6d6bde3 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -410,6 +410,7 @@ void __init ixp4xx_pci_preinit(void)
 		 * Enable the IO window to be way up high, at 0xfffffc00
 		 */
 		local_write_config(PCI_BASE_ADDRESS_5, 4, 0xfffffc01);
+		local_write_config(0x40, 4, 0x000080FF); /* No TRDY time limit */
 	} else {
 		printk("PCI: IXP4xx is target - No bus scan performed\n");
 	}
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index fdf91a1..8c0c0e2 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -67,15 +67,12 @@ static struct map_desc ixp4xx_io_desc[] __initdata = {
 		.pfn		= __phys_to_pfn(IXP4XX_PCI_CFG_BASE_PHYS),
 		.length		= IXP4XX_PCI_CFG_REGION_SIZE,
 		.type		= MT_DEVICE
-	},
-#ifdef CONFIG_DEBUG_LL
-	{	/* Debug UART mapping */
-		.virtual	= (unsigned long)IXP4XX_DEBUG_UART_BASE_VIRT,
-		.pfn		= __phys_to_pfn(IXP4XX_DEBUG_UART_BASE_PHYS),
-		.length		= IXP4XX_DEBUG_UART_REGION_SIZE,
+	}, {	/* Queue Manager */
+		.virtual	= (unsigned long)IXP4XX_QMGR_BASE_VIRT,
+		.pfn		= __phys_to_pfn(IXP4XX_QMGR_BASE_PHYS),
+		.length		= IXP4XX_QMGR_REGION_SIZE,
 		.type		= MT_DEVICE
-	}
-#endif
+	},
 };
 
 void __init ixp4xx_map_io(void)
diff --git a/arch/arm/mach-ixp4xx/goramo_mlr.c b/arch/arm/mach-ixp4xx/goramo_mlr.c
index b800a03..53b8348 100644
--- a/arch/arm/mach-ixp4xx/goramo_mlr.c
+++ b/arch/arm/mach-ixp4xx/goramo_mlr.c
@@ -15,6 +15,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/pci.h>
+#include <asm/system_info.h>
 
 #define SLOT_ETHA		0x0B	/* IDSEL = AD21 */
 #define SLOT_ETHB		0x0C	/* IDSEL = AD20 */
@@ -329,7 +330,7 @@ static struct platform_device device_hss_tab[] = {
 };
 
 
-static struct platform_device *device_tab[6] __initdata = {
+static struct platform_device *device_tab[7] __initdata = {
 	&device_flash,		/* index 0 */
 };
 
diff --git a/arch/arm/mach-ixp4xx/include/mach/debug-macro.S b/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
index 8c9f8d5..ff686cb 100644
--- a/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
@@ -17,8 +17,8 @@
 #else
 		mov	\rp, #0
 #endif
-                orr     \rv, \rp, #0xff000000	@ virtual
-		orr	\rv, \rv, #0x00b00000
+		orr	\rv, \rp, #0xfe000000	@ virtual
+		orr	\rv, \rv, #0x00f00000
                 orr     \rp, \rp, #0xc8000000	@ physical
                 .endm
 
diff --git a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
index eb68b61..c5bae9c 100644
--- a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
+++ b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
@@ -30,51 +30,43 @@
  *
  * 0x50000000	0x10000000	ioremap'd	EXP BUS
  *
- * 0x6000000	0x00004000	ioremap'd	QMgr
+ * 0xC8000000	0x00013000	0xFEF00000	On-Chip Peripherals
  *
- * 0xC0000000	0x00001000	0xffbff000	PCI CFG
+ * 0xC0000000	0x00001000	0xFEF13000	PCI CFG
  *
- * 0xC4000000	0x00001000	0xffbfe000	EXP CFG
+ * 0xC4000000	0x00001000	0xFEF14000	EXP CFG
  *
- * 0xC8000000	0x00013000	0xffbeb000	On-Chip Peripherals
+ * 0x60000000	0x00004000	0xFEF15000	QMgr
  */
 
 /*
  * Queue Manager
  */
-#define IXP4XX_QMGR_BASE_PHYS		(0x60000000)
-#define IXP4XX_QMGR_REGION_SIZE		(0x00004000)
+#define IXP4XX_QMGR_BASE_PHYS		0x60000000
+#define IXP4XX_QMGR_BASE_VIRT		IOMEM(0xFEF15000)
+#define IXP4XX_QMGR_REGION_SIZE		0x00004000
 
 /*
- * Expansion BUS Configuration registers
+ * Peripheral space, including debug UART. Must be section-aligned so that
+ * it can be used with the low-level debug code.
  */
-#define IXP4XX_EXP_CFG_BASE_PHYS	(0xC4000000)
-#define IXP4XX_EXP_CFG_BASE_VIRT	IOMEM(0xFFBFE000)
-#define IXP4XX_EXP_CFG_REGION_SIZE	(0x00001000)
+#define IXP4XX_PERIPHERAL_BASE_PHYS	0xC8000000
+#define IXP4XX_PERIPHERAL_BASE_VIRT	IOMEM(0xFEF00000)
+#define IXP4XX_PERIPHERAL_REGION_SIZE	0x00013000
 
 /*
  * PCI Config registers
  */
-#define IXP4XX_PCI_CFG_BASE_PHYS	(0xC0000000)
-#define	IXP4XX_PCI_CFG_BASE_VIRT	IOMEM(0xFFBFF000)
-#define IXP4XX_PCI_CFG_REGION_SIZE	(0x00001000)
-
-/*
- * Peripheral space
- */
-#define IXP4XX_PERIPHERAL_BASE_PHYS	(0xC8000000)
-#define IXP4XX_PERIPHERAL_BASE_VIRT	IOMEM(0xFFBEB000)
-#define IXP4XX_PERIPHERAL_REGION_SIZE	(0x00013000)
+#define IXP4XX_PCI_CFG_BASE_PHYS	0xC0000000
+#define IXP4XX_PCI_CFG_BASE_VIRT	IOMEM(0xFEF13000)
+#define IXP4XX_PCI_CFG_REGION_SIZE	0x00001000
 
 /*
- * Debug UART
- *
- * This is basically a remap of UART1 into a region that is section
- * aligned so that it * can be used with the low-level debug code.
+ * Expansion BUS Configuration registers
  */
-#define	IXP4XX_DEBUG_UART_BASE_PHYS	(0xC8000000)
-#define	IXP4XX_DEBUG_UART_BASE_VIRT	IOMEM(0xffb00000)
-#define	IXP4XX_DEBUG_UART_REGION_SIZE	(0x00001000)
+#define IXP4XX_EXP_CFG_BASE_PHYS	0xC4000000
+#define IXP4XX_EXP_CFG_BASE_VIRT	0xFEF14000
+#define IXP4XX_EXP_CFG_REGION_SIZE	0x00001000
 
 #define IXP4XX_EXP_CS0_OFFSET	0x00
 #define IXP4XX_EXP_CS1_OFFSET   0x04
diff --git a/arch/arm/mach-ixp4xx/include/mach/qmgr.h b/arch/arm/mach-ixp4xx/include/mach/qmgr.h
index 9e7cad2..4de8da5 100644
--- a/arch/arm/mach-ixp4xx/include/mach/qmgr.h
+++ b/arch/arm/mach-ixp4xx/include/mach/qmgr.h
@@ -86,7 +86,7 @@ void qmgr_release_queue(unsigned int queue);
 
 static inline void qmgr_put_entry(unsigned int queue, u32 val)
 {
-	extern struct qmgr_regs __iomem *qmgr_regs;
+	struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
 #if DEBUG_QMGR
 	BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */
 
@@ -99,7 +99,7 @@ static inline void qmgr_put_entry(unsigned int queue, u32 val)
 static inline u32 qmgr_get_entry(unsigned int queue)
 {
 	u32 val;
-	extern struct qmgr_regs __iomem *qmgr_regs;
+	const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
 	val = __raw_readl(&qmgr_regs->acc[queue][0]);
 #if DEBUG_QMGR
 	BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */
@@ -112,14 +112,14 @@ static inline u32 qmgr_get_entry(unsigned int queue)
 
 static inline int __qmgr_get_stat1(unsigned int queue)
 {
-	extern struct qmgr_regs __iomem *qmgr_regs;
+	const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
 	return (__raw_readl(&qmgr_regs->stat1[queue >> 3])
 		>> ((queue & 7) << 2)) & 0xF;
 }
 
 static inline int __qmgr_get_stat2(unsigned int queue)
 {
-	extern struct qmgr_regs __iomem *qmgr_regs;
+	const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
 	BUG_ON(queue >= HALF_QUEUES);
 	return (__raw_readl(&qmgr_regs->stat2[queue >> 4])
 		>> ((queue & 0xF) << 1)) & 0x3;
@@ -145,7 +145,7 @@ static inline int qmgr_stat_empty(unsigned int queue)
  */
 static inline int qmgr_stat_below_low_watermark(unsigned int queue)
 {
-	extern struct qmgr_regs __iomem *qmgr_regs;
+	const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
 	if (queue >= HALF_QUEUES)
 		return (__raw_readl(&qmgr_regs->statne_h) >>
 			(queue - HALF_QUEUES)) & 0x01;
@@ -172,7 +172,7 @@ static inline int qmgr_stat_above_high_watermark(unsigned int queue)
  */
 static inline int qmgr_stat_full(unsigned int queue)
 {
-	extern struct qmgr_regs __iomem *qmgr_regs;
+	const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
 	if (queue >= HALF_QUEUES)
 		return (__raw_readl(&qmgr_regs->statf_h) >>
 			(queue - HALF_QUEUES)) & 0x01;
diff --git a/arch/arm/mach-ixp4xx/include/mach/udc.h b/arch/arm/mach-ixp4xx/include/mach/udc.h
index 80d6da2..7bd8b96 100644
--- a/arch/arm/mach-ixp4xx/include/mach/udc.h
+++ b/arch/arm/mach-ixp4xx/include/mach/udc.h
@@ -2,7 +2,7 @@
  * arch/arm/mach-ixp4xx/include/mach/udc.h
  *
  */
-#include <asm/mach/udc_pxa2xx.h>
+#include <linux/platform_data/pxa2xx_udc.h>
 
 extern void ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info);
 
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_npe.c b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
index a17ed79..d4eb09a 100644
--- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c
+++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
@@ -116,7 +116,11 @@
 /* NPE mailbox_status value for reset */
 #define RESET_MBOX_STAT			0x0000F0F0
 
-const char *npe_names[] = { "NPE-A", "NPE-B", "NPE-C" };
+#define NPE_A_FIRMWARE "NPE-A"
+#define NPE_B_FIRMWARE "NPE-B"
+#define NPE_C_FIRMWARE "NPE-C"
+
+const char *npe_names[] = { NPE_A_FIRMWARE, NPE_B_FIRMWARE, NPE_C_FIRMWARE };
 
 #define print_npe(pri, npe, fmt, ...)					\
 	printk(pri "%s: " fmt, npe_name(npe), ## __VA_ARGS__)
@@ -724,6 +728,9 @@ module_exit(npe_cleanup_module);
 
 MODULE_AUTHOR("Krzysztof Halasa");
 MODULE_LICENSE("GPL v2");
+MODULE_FIRMWARE(NPE_A_FIRMWARE);
+MODULE_FIRMWARE(NPE_B_FIRMWARE);
+MODULE_FIRMWARE(NPE_C_FIRMWARE);
 
 EXPORT_SYMBOL(npe_names);
 EXPORT_SYMBOL(npe_running);
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
index 852f7c9..9d1b6b7 100644
--- a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
+++ b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
@@ -14,7 +14,7 @@
 #include <linux/module.h>
 #include <mach/qmgr.h>
 
-struct qmgr_regs __iomem *qmgr_regs;
+static struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
 static struct resource *mem_res;
 static spinlock_t qmgr_lock;
 static u32 used_sram_bitmap[4]; /* 128 16-dword pages */
@@ -293,12 +293,6 @@ static int qmgr_init(void)
 	if (mem_res == NULL)
 		return -EBUSY;
 
-	qmgr_regs = ioremap(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
-	if (qmgr_regs == NULL) {
-		err = -ENOMEM;
-		goto error_map;
-	}
-
 	/* reset qmgr registers */
 	for (i = 0; i < 4; i++) {
 		__raw_writel(0x33333333, &qmgr_regs->stat1[i]);
@@ -347,8 +341,6 @@ static int qmgr_init(void)
 error_irq2:
 	free_irq(IRQ_IXP4XX_QM1, NULL);
 error_irq:
-	iounmap(qmgr_regs);
-error_map:
 	release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
 	return err;
 }
@@ -359,7 +351,6 @@ static void qmgr_remove(void)
 	free_irq(IRQ_IXP4XX_QM2, NULL);
 	synchronize_irq(IRQ_IXP4XX_QM1);
 	synchronize_irq(IRQ_IXP4XX_QM2);
-	iounmap(qmgr_regs);
 	release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
 }
 
@@ -369,7 +360,6 @@ module_exit(qmgr_remove);
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Krzysztof Halasa");
 
-EXPORT_SYMBOL(qmgr_regs);
 EXPORT_SYMBOL(qmgr_set_irq);
 EXPORT_SYMBOL(qmgr_enable_irq);
 EXPORT_SYMBOL(qmgr_disable_irq);
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index 50bca50..503d7dd 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -46,6 +46,11 @@ config MACH_GURUPLUG
 
 config ARCH_KIRKWOOD_DT
 	bool "Marvell Kirkwood Flattened Device Tree"
+	select POWER_SUPPLY
+	select POWER_RESET
+	select POWER_RESET_GPIO
+	select REGULATOR
+	select REGULATOR_FIXED_VOLTAGE
 	select USE_OF
 	help
 	  Say 'Y' here if you want your kernel to support the
@@ -130,6 +135,63 @@ config MACH_KM_KIRKWOOD_DT
 	  Say 'Y' here if you want your kernel to support the
 	  Keymile Kirkwood Reference Desgin, using Flattened Device Tree.
 
+config MACH_INETSPACE_V2_DT
+	bool "LaCie Internet Space v2 NAS (Flattened Device Tree)"
+	select ARCH_KIRKWOOD_DT
+	help
+	  Say 'Y' here if you want your kernel to support the LaCie
+	  Internet Space v2 NAS, using Flattened Device Tree.
+
+config MACH_MPLCEC4_DT
+	bool "MPL CEC4 (Flattened Device Tree)"
+	select ARCH_KIRKWOOD_DT
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  MPL CEC4 (Flattened Device Tree).
+
+config MACH_NETSPACE_V2_DT
+	bool "LaCie Network Space v2 NAS (Flattened Device Tree)"
+	select ARCH_KIRKWOOD_DT
+	help
+	  Say 'Y' here if you want your kernel to support the LaCie
+	  Network Space v2 NAS, using Flattened Device Tree.
+
+config MACH_NETSPACE_MAX_V2_DT
+	bool "LaCie Network Space Max v2 NAS (Flattened Device Tree)"
+	select ARCH_KIRKWOOD_DT
+	help
+	  Say 'Y' here if you want your kernel to support the LaCie
+	  Network Space Max v2 NAS, using Flattened Device Tree.
+
+config MACH_NETSPACE_LITE_V2_DT
+	bool "LaCie Network Space Lite v2 NAS (Flattened Device Tree)"
+	select ARCH_KIRKWOOD_DT
+	help
+	  Say 'Y' here if you want your kernel to support the LaCie
+	  Network Space Lite v2 NAS, using Flattened Device Tree.
+
+config MACH_NETSPACE_MINI_V2_DT
+	bool "LaCie Network Space Mini v2 NAS (Flattened Device Tree)"
+	select ARCH_KIRKWOOD_DT
+	help
+	  Say 'Y' here if you want your kernel to support the LaCie
+	  Network Space Mini v2 NAS (aka SafeBox), using Flattened
+	  Device Tree.
+
+config MACH_OPENBLOCKS_A6_DT
+	bool "Plat'Home OpenBlocks A6 (Flattened Device Tree)"
+	select ARCH_KIRKWOOD_DT
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Plat'Home OpenBlocks A6 (Flattened Device Tree).
+
+config MACH_TOPKICK_DT
+	bool "USI Topkick (Flattened Device Tree)"
+	select ARCH_KIRKWOOD_DT
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  USI Topkick, using Flattened Device Tree
+
 config MACH_TS219
 	bool "QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and TS-219P+ Turbo NAS"
 	help
@@ -216,6 +278,14 @@ config MACH_T5325
 	  Say 'Y' here if you want your kernel to support the
 	  HP t5325 Thin Client.
 
+config MACH_NSA310_DT
+	bool "ZyXEL NSA-310 (Flattened Device Tree)"
+	select ARCH_KIRKWOOD_DT
+	select ARM_ATAG_DTB_COMPAT
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  ZyXEL NSA-310 board (Flattened Device Tree).
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
index 294779f..8d2e5a9 100644
--- a/arch/arm/mach-kirkwood/Makefile
+++ b/arch/arm/mach-kirkwood/Makefile
@@ -31,3 +31,12 @@ obj-$(CONFIG_MACH_GOFLEXNET_DT)		+= board-goflexnet.o
 obj-$(CONFIG_MACH_LSXL_DT)		+= board-lsxl.o
 obj-$(CONFIG_MACH_IOMEGA_IX2_200_DT)	+= board-iomega_ix2_200.o
 obj-$(CONFIG_MACH_KM_KIRKWOOD_DT)	+= board-km_kirkwood.o
+obj-$(CONFIG_MACH_INETSPACE_V2_DT)	+= board-ns2.o
+obj-$(CONFIG_MACH_MPLCEC4_DT)		+= board-mplcec4.o
+obj-$(CONFIG_MACH_NETSPACE_V2_DT)	+= board-ns2.o
+obj-$(CONFIG_MACH_NETSPACE_MAX_V2_DT)	+= board-ns2.o
+obj-$(CONFIG_MACH_NETSPACE_LITE_V2_DT)	+= board-ns2.o
+obj-$(CONFIG_MACH_NETSPACE_MINI_V2_DT)	+= board-ns2.o
+obj-$(CONFIG_MACH_NSA310_DT)		+= board-nsa310.o
+obj-$(CONFIG_MACH_OPENBLOCKS_A6_DT)	+= board-openblocks_a6.o
+obj-$(CONFIG_MACH_TOPKICK_DT)		+= board-usi_topkick.o
diff --git a/arch/arm/mach-kirkwood/board-dnskw.c b/arch/arm/mach-kirkwood/board-dnskw.c
index 43d16d6..a1aa87f 100644
--- a/arch/arm/mach-kirkwood/board-dnskw.c
+++ b/arch/arm/mach-kirkwood/board-dnskw.c
@@ -17,51 +17,11 @@
 #include <linux/mv643xx_eth.h>
 #include <linux/gpio.h>
 #include "common.h"
-#include "mpp.h"
 
 static struct mv643xx_eth_platform_data dnskw_ge00_data = {
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
 };
 
-static unsigned int dnskw_mpp_config[] __initdata = {
-	MPP13_UART1_TXD,	/* Custom ... */
-	MPP14_UART1_RXD,	/* ... Controller (DNS-320 only) */
-	MPP20_SATA1_ACTn,	/* LED: White Right HDD */
-	MPP21_SATA0_ACTn,	/* LED: White Left HDD */
-	MPP24_GPIO,
-	MPP25_GPIO,
-	MPP26_GPIO,	/* LED: Power */
-	MPP27_GPIO,	/* LED: Red Right HDD */
-	MPP28_GPIO,	/* LED: Red Left HDD */
-	MPP29_GPIO,	/* LED: Red USB (DNS-325 only) */
-	MPP30_GPIO,
-	MPP31_GPIO,
-	MPP32_GPIO,
-	MPP33_GPO,
-	MPP34_GPIO,	/* Button: Front power */
-	MPP35_GPIO,	/* LED: Red USB (DNS-320 only) */
-	MPP36_GPIO,	/* Power: Turn off board */
-	MPP37_GPIO,	/* Power: Turn back on after power failure */
-	MPP38_GPIO,
-	MPP39_GPIO,	/* Power: SATA0 */
-	MPP40_GPIO,	/* Power: SATA1 */
-	MPP41_GPIO,	/* SATA0 present */
-	MPP42_GPIO,	/* SATA1 present */
-	MPP43_GPIO,	/* LED: White USB */
-	MPP44_GPIO,	/* Fan: Tachometer Pin */
-	MPP45_GPIO,	/* Fan: high speed */
-	MPP46_GPIO,	/* Fan: low speed */
-	MPP47_GPIO,	/* Button: Back unmount */
-	MPP48_GPIO,	/* Button: Back reset */
-	MPP49_GPIO,	/* Temp Alarm (DNS-325) Pin of U5 (DNS-320) */
-	0
-};
-
-static void dnskw_power_off(void)
-{
-	gpio_set_value(36, 1);
-}
-
 /* Register any GPIO for output and set the value */
 static void __init dnskw_gpio_register(unsigned gpio, char *name, int def)
 {
@@ -76,22 +36,8 @@ static void __init dnskw_gpio_register(unsigned gpio, char *name, int def)
 
 void __init dnskw_init(void)
 {
-	kirkwood_mpp_conf(dnskw_mpp_config);
-
-	kirkwood_ehci_init();
 	kirkwood_ge00_init(&dnskw_ge00_data);
 
-	/* Register power-off GPIO. */
-	if (gpio_request(36, "dnskw:power:off") == 0
-	    && gpio_direction_output(36, 0) == 0)
-		pm_power_off = dnskw_power_off;
-	else
-		pr_err("dnskw: failed to configure power-off GPIO\n");
-
-	/* Ensure power is supplied to both HDDs */
-	dnskw_gpio_register(39, "dnskw:power:sata0", 1);
-	dnskw_gpio_register(40, "dnskw:power:sata1", 1);
-
 	/* Set NAS to turn back on after a power failure */
 	dnskw_gpio_register(37, "dnskw:power:recover", 1);
 }
diff --git a/arch/arm/mach-kirkwood/board-dockstar.c b/arch/arm/mach-kirkwood/board-dockstar.c
index f2fbb02..d7196db 100644
--- a/arch/arm/mach-kirkwood/board-dockstar.c
+++ b/arch/arm/mach-kirkwood/board-dockstar.c
@@ -16,46 +16,17 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_fdt.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/gpio.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <mach/kirkwood.h>
-#include <mach/bridge-regs.h>
-#include <linux/platform_data/mmc-mvsdio.h>
 #include "common.h"
-#include "mpp.h"
 
 static struct mv643xx_eth_platform_data dockstar_ge00_data = {
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
 };
 
-static unsigned int dockstar_mpp_config[] __initdata = {
-	MPP29_GPIO,	/* USB Power Enable */
-	MPP46_GPIO,	/* LED green */
-	MPP47_GPIO,	/* LED orange */
-	0
-};
-
 void __init dockstar_dt_init(void)
 {
 	/*
 	 * Basic setup. Needs to be called early.
 	 */
-	kirkwood_mpp_conf(dockstar_mpp_config);
-
-	if (gpio_request(29, "USB Power Enable") != 0 ||
-	    gpio_direction_output(29, 1) != 0)
-		pr_err("can't setup GPIO 29 (USB Power Enable)\n");
-	kirkwood_ehci_init();
-
 	kirkwood_ge00_init(&dockstar_ge00_data);
 }
diff --git a/arch/arm/mach-kirkwood/board-dreamplug.c b/arch/arm/mach-kirkwood/board-dreamplug.c
index 20af53a..08248e2 100644
--- a/arch/arm/mach-kirkwood/board-dreamplug.c
+++ b/arch/arm/mach-kirkwood/board-dreamplug.c
@@ -13,26 +13,10 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_fdt.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
 #include <linux/gpio.h>
-#include <linux/mtd/physmap.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <mach/kirkwood.h>
-#include <mach/bridge-regs.h>
 #include <linux/platform_data/mmc-mvsdio.h>
 #include "common.h"
-#include "mpp.h"
 
 static struct mv643xx_eth_platform_data dreamplug_ge00_data = {
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
@@ -46,25 +30,11 @@ static struct mvsdio_platform_data dreamplug_mvsdio_data = {
 	/* unfortunately the CD signal has not been connected */
 };
 
-static unsigned int dreamplug_mpp_config[] __initdata = {
-	MPP0_SPI_SCn,
-	MPP1_SPI_MOSI,
-	MPP2_SPI_SCK,
-	MPP3_SPI_MISO,
-	MPP47_GPIO,	/* Bluetooth LED */
-	MPP48_GPIO,	/* Wifi LED */
-	MPP49_GPIO,	/* Wifi AP LED */
-	0
-};
-
 void __init dreamplug_init(void)
 {
 	/*
 	 * Basic setup. Needs to be called early.
 	 */
-	kirkwood_mpp_conf(dreamplug_mpp_config);
-
-	kirkwood_ehci_init();
 	kirkwood_ge00_init(&dreamplug_ge00_data);
 	kirkwood_ge01_init(&dreamplug_ge01_data);
 	kirkwood_sdio_init(&dreamplug_mvsdio_data);
diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
index d94872f..375f7d8 100644
--- a/arch/arm/mach-kirkwood/board-dt.c
+++ b/arch/arm/mach-kirkwood/board-dt.c
@@ -26,10 +26,12 @@ static struct of_device_id kirkwood_dt_match_table[] __initdata = {
 	{ }
 };
 
-struct of_dev_auxdata kirkwood_auxdata_lookup[] __initdata = {
+static struct of_dev_auxdata kirkwood_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("marvell,orion-spi", 0xf1010600, "orion_spi.0", NULL),
 	OF_DEV_AUXDATA("marvell,mv64xxx-i2c", 0xf1011000, "mv64xxx_i2c.0",
 		       NULL),
+	OF_DEV_AUXDATA("marvell,mv64xxx-i2c", 0xf1011100, "mv64xxx_i2c.1",
+		       NULL),
 	OF_DEV_AUXDATA("marvell,orion-wdt", 0xf1020300, "orion_wdt", NULL),
 	OF_DEV_AUXDATA("marvell,orion-sata", 0xf1080000, "sata_mv.0", NULL),
 	OF_DEV_AUXDATA("marvell,orion-nand", 0xf4000000, "orion_nand", NULL),
@@ -94,11 +96,30 @@ static void __init kirkwood_dt_init(void)
 	if (of_machine_is_compatible("keymile,km_kirkwood"))
 		km_kirkwood_init();
 
+	if (of_machine_is_compatible("lacie,inetspace_v2") ||
+	    of_machine_is_compatible("lacie,netspace_v2") ||
+	    of_machine_is_compatible("lacie,netspace_max_v2") ||
+	    of_machine_is_compatible("lacie,netspace_lite_v2") ||
+	    of_machine_is_compatible("lacie,netspace_mini_v2"))
+		ns2_init();
+
+	if (of_machine_is_compatible("mpl,cec4"))
+		mplcec4_init();
+
+	if (of_machine_is_compatible("plathome,openblocks-a6"))
+		openblocks_a6_init();
+
+	if (of_machine_is_compatible("usi,topkick"))
+		usi_topkick_init();
+
+	if (of_machine_is_compatible("zyxel,nsa310"))
+		nsa310_init();
+
 	of_platform_populate(NULL, kirkwood_dt_match_table,
 			     kirkwood_auxdata_lookup, NULL);
 }
 
-static const char *kirkwood_dt_board_compat[] = {
+static const char * const kirkwood_dt_board_compat[] = {
 	"globalscale,dreamplug",
 	"dlink,dns-320",
 	"dlink,dns-325",
@@ -110,6 +131,15 @@ static const char *kirkwood_dt_board_compat[] = {
 	"buffalo,lsxl",
 	"iom,ix2-200",
 	"keymile,km_kirkwood",
+	"lacie,inetspace_v2",
+	"lacie,netspace_max_v2",
+	"lacie,netspace_v2",
+	"lacie,netspace_lite_v2",
+	"lacie,netspace_mini_v2",
+	"mpl,cec4",
+	"plathome,openblocks-a6",
+	"usi,topkick",
+	"zyxel,nsa310",
 	NULL
 };
 
diff --git a/arch/arm/mach-kirkwood/board-goflexnet.c b/arch/arm/mach-kirkwood/board-goflexnet.c
index 001ca8c..9db979a 100644
--- a/arch/arm/mach-kirkwood/board-goflexnet.c
+++ b/arch/arm/mach-kirkwood/board-goflexnet.c
@@ -18,54 +18,17 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_fdt.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/gpio.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <mach/kirkwood.h>
-#include <mach/bridge-regs.h>
-#include <linux/platform_data/mmc-mvsdio.h>
 #include "common.h"
-#include "mpp.h"
 
 static struct mv643xx_eth_platform_data goflexnet_ge00_data = {
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
 };
 
-static unsigned int goflexnet_mpp_config[] __initdata = {
-	MPP29_GPIO,	/* USB Power Enable */
-	MPP47_GPIO,	/* LED Orange */
-	MPP46_GPIO,	/* LED Green */
-	MPP45_GPIO,	/* LED Left Capacity 3 */
-	MPP44_GPIO,	/* LED Left Capacity 2 */
-	MPP43_GPIO,	/* LED Left Capacity 1 */
-	MPP42_GPIO,	/* LED Left Capacity 0 */
-	MPP41_GPIO,	/* LED Right Capacity 3 */
-	MPP40_GPIO,	/* LED Right Capacity 2 */
-	MPP39_GPIO,	/* LED Right Capacity 1 */
-	MPP38_GPIO,	/* LED Right Capacity 0 */
-	0
-};
-
 void __init goflexnet_init(void)
 {
 	/*
 	 * Basic setup. Needs to be called early.
 	 */
-	kirkwood_mpp_conf(goflexnet_mpp_config);
-
-	if (gpio_request(29, "USB Power Enable") != 0 ||
-	    gpio_direction_output(29, 1) != 0)
-		pr_err("can't setup GPIO 29 (USB Power Enable)\n");
-	kirkwood_ehci_init();
-
 	kirkwood_ge00_init(&goflexnet_ge00_data);
 }
diff --git a/arch/arm/mach-kirkwood/board-ib62x0.c b/arch/arm/mach-kirkwood/board-ib62x0.c
index cfc47f8..9f6f496 100644
--- a/arch/arm/mach-kirkwood/board-ib62x0.c
+++ b/arch/arm/mach-kirkwood/board-ib62x0.c
@@ -13,59 +13,18 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/partitions.h>
-#include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
-#include <linux/gpio.h>
 #include <linux/input.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
 #include "common.h"
-#include "mpp.h"
-
-#define IB62X0_GPIO_POWER_OFF	24
 
 static struct mv643xx_eth_platform_data ib62x0_ge00_data = {
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
 };
 
-static unsigned int ib62x0_mpp_config[] __initdata = {
-	MPP0_NF_IO2,
-	MPP1_NF_IO3,
-	MPP2_NF_IO4,
-	MPP3_NF_IO5,
-	MPP4_NF_IO6,
-	MPP5_NF_IO7,
-	MPP18_NF_IO0,
-	MPP19_NF_IO1,
-	MPP22_GPIO,	/* OS LED red */
-	MPP24_GPIO,	/* Power off device */
-	MPP25_GPIO,	/* OS LED green */
-	MPP27_GPIO,	/* USB transfer LED */
-	MPP28_GPIO,	/* Reset button */
-	MPP29_GPIO,	/* USB Copy button */
-	0
-};
-
-static void ib62x0_power_off(void)
-{
-	gpio_set_value(IB62X0_GPIO_POWER_OFF, 1);
-}
-
 void __init ib62x0_init(void)
 {
 	/*
 	 * Basic setup. Needs to be called early.
 	 */
-	kirkwood_mpp_conf(ib62x0_mpp_config);
-
-	kirkwood_ehci_init();
 	kirkwood_ge00_init(&ib62x0_ge00_data);
-	if (gpio_request(IB62X0_GPIO_POWER_OFF, "ib62x0:power:off") == 0 &&
-	    gpio_direction_output(IB62X0_GPIO_POWER_OFF, 0) == 0)
-		pm_power_off = ib62x0_power_off;
-	else
-		pr_err("board-ib62x0: failed to configure power-off GPIO\n");
 }
diff --git a/arch/arm/mach-kirkwood/board-iconnect.c b/arch/arm/mach-kirkwood/board-iconnect.c
index d084b1e..c8ebde4 100644
--- a/arch/arm/mach-kirkwood/board-iconnect.c
+++ b/arch/arm/mach-kirkwood/board-iconnect.c
@@ -10,42 +10,16 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/platform_device.h>
 #include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_fdt.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
 #include <linux/mv643xx_eth.h>
-#include <linux/gpio.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
 #include "common.h"
-#include "mpp.h"
 
 static struct mv643xx_eth_platform_data iconnect_ge00_data = {
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(11),
 };
 
-static unsigned int iconnect_mpp_config[] __initdata = {
-	MPP12_GPIO,
-	MPP35_GPIO,
-	MPP41_GPIO,
-	MPP42_GPIO,
-	MPP43_GPIO,
-	MPP44_GPIO,
-	MPP45_GPIO,
-	MPP46_GPIO,
-	MPP47_GPIO,
-	MPP48_GPIO,
-	0
-};
-
 void __init iconnect_init(void)
 {
-	kirkwood_mpp_conf(iconnect_mpp_config);
-
-	kirkwood_ehci_init();
 	kirkwood_ge00_init(&iconnect_ge00_data);
 }
 
diff --git a/arch/arm/mach-kirkwood/board-iomega_ix2_200.c b/arch/arm/mach-kirkwood/board-iomega_ix2_200.c
index 158fb97..f655b26 100644
--- a/arch/arm/mach-kirkwood/board-iomega_ix2_200.c
+++ b/arch/arm/mach-kirkwood/board-iomega_ix2_200.c
@@ -10,12 +10,9 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/platform_device.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/ethtool.h>
-#include <mach/kirkwood.h>
 #include "common.h"
-#include "mpp.h"
 
 static struct mv643xx_eth_platform_data iomega_ix2_200_ge00_data = {
 	.phy_addr       = MV643XX_ETH_PHY_NONE,
@@ -23,35 +20,10 @@ static struct mv643xx_eth_platform_data iomega_ix2_200_ge00_data = {
 	.duplex         = DUPLEX_FULL,
 };
 
-static unsigned int iomega_ix2_200_mpp_config[] __initdata = {
-	MPP12_GPIO,			/* Reset Button */
-	MPP14_GPIO,			/* Power Button */
-	MPP15_GPIO,			/* Backup LED (blue) */
-	MPP16_GPIO,			/* Power LED (white) */
-	MPP35_GPIO,			/* OTB Button */
-	MPP36_GPIO,			/* Rebuild LED (white) */
-	MPP37_GPIO,			/* Health LED (red) */
-	MPP38_GPIO,			/* SATA LED brightness control 1 */
-	MPP39_GPIO,			/* SATA LED brightness control 2 */
-	MPP40_GPIO,			/* Backup LED brightness control 1 */
-	MPP41_GPIO,			/* Backup LED brightness control 2 */
-	MPP42_GPIO,			/* Power LED brightness control 1 */
-	MPP43_GPIO,			/* Power LED brightness control 2 */
-	MPP44_GPIO,			/* Health LED brightness control 1 */
-	MPP45_GPIO,			/* Health LED brightness control 2 */
-	MPP46_GPIO,			/* Rebuild LED brightness control 1 */
-	MPP47_GPIO,			/* Rebuild LED brightness control 2 */
-	0
-};
-
 void __init iomega_ix2_200_init(void)
 {
 	/*
 	 * Basic setup. Needs to be called early.
 	 */
-	kirkwood_mpp_conf(iomega_ix2_200_mpp_config);
-
-	kirkwood_ehci_init();
-
 	kirkwood_ge01_init(&iomega_ix2_200_ge00_data);
 }
diff --git a/arch/arm/mach-kirkwood/board-km_kirkwood.c b/arch/arm/mach-kirkwood/board-km_kirkwood.c
index f7d3283..44e4605 100644
--- a/arch/arm/mach-kirkwood/board-km_kirkwood.c
+++ b/arch/arm/mach-kirkwood/board-km_kirkwood.c
@@ -18,27 +18,15 @@
 #include <linux/clk.h>
 #include <linux/clk-private.h>
 #include "common.h"
-#include "mpp.h"
 
 static struct mv643xx_eth_platform_data km_kirkwood_ge00_data = {
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
 };
 
-static unsigned int km_kirkwood_mpp_config[] __initdata = {
-	MPP8_GPIO,	/* I2C SDA */
-	MPP9_GPIO,	/* I2C SCL */
-	0
-};
-
 void __init km_kirkwood_init(void)
 {
 	struct clk *sata_clk;
 	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_mpp_conf(km_kirkwood_mpp_config);
-
-	/*
 	 * Our variant of kirkwood (integrated in the Bobcat) hangs on accessing
 	 * SATA bits (14-15) of the Clock Gating Control Register. Since these
 	 * devices are also not present in this variant, their clocks get
@@ -52,6 +40,5 @@ void __init km_kirkwood_init(void)
 	if (!IS_ERR(sata_clk))
 		sata_clk->flags |= CLK_IGNORE_UNUSED;
 
-	kirkwood_ehci_init();
 	kirkwood_ge00_init(&km_kirkwood_ge00_data);
 }
diff --git a/arch/arm/mach-kirkwood/board-lsxl.c b/arch/arm/mach-kirkwood/board-lsxl.c
index 83d8975..4ec8b7a 100644
--- a/arch/arm/mach-kirkwood/board-lsxl.c
+++ b/arch/arm/mach-kirkwood/board-lsxl.c
@@ -14,19 +14,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/mtd/partitions.h>
-#include <linux/ata_platform.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
 #include <linux/mv643xx_eth.h>
-#include <linux/gpio.h>
-#include <linux/gpio-fan.h>
-#include <linux/input.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
 #include "common.h"
-#include "mpp.h"
 
 static struct mv643xx_eth_platform_data lsxl_ge00_data = {
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
@@ -36,68 +25,6 @@ static struct mv643xx_eth_platform_data lsxl_ge01_data = {
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
 };
 
-static unsigned int lsxl_mpp_config[] __initdata = {
-	MPP10_GPO,	/* HDD Power Enable */
-	MPP11_GPIO,	/* USB Vbus Enable */
-	MPP18_GPO,	/* FAN High Enable# */
-	MPP19_GPO,	/* FAN Low Enable# */
-	MPP36_GPIO,	/* Function Blue LED */
-	MPP37_GPIO,	/* Alarm LED */
-	MPP38_GPIO,	/* Info LED */
-	MPP39_GPIO,	/* Power LED */
-	MPP40_GPIO,	/* Fan Lock */
-	MPP41_GPIO,	/* Function Button */
-	MPP42_GPIO,	/* Power Switch */
-	MPP43_GPIO,	/* Power Auto Switch */
-	MPP48_GPIO,	/* Function Red LED */
-	0
-};
-
-#define LSXL_GPIO_FAN_HIGH	18
-#define LSXL_GPIO_FAN_LOW	19
-#define LSXL_GPIO_FAN_LOCK	40
-
-static struct gpio_fan_alarm lsxl_alarm = {
-	.gpio = LSXL_GPIO_FAN_LOCK,
-};
-
-static struct gpio_fan_speed lsxl_speeds[] = {
-	{
-		.rpm = 0,
-		.ctrl_val = 3,
-	}, {
-		.rpm = 1500,
-		.ctrl_val = 1,
-	}, {
-		.rpm = 3250,
-		.ctrl_val = 2,
-	}, {
-		.rpm = 5000,
-		.ctrl_val = 0,
-	}
-};
-
-static int lsxl_gpio_list[] = {
-	LSXL_GPIO_FAN_HIGH, LSXL_GPIO_FAN_LOW,
-};
-
-static struct gpio_fan_platform_data lsxl_fan_data = {
-	.num_ctrl = ARRAY_SIZE(lsxl_gpio_list),
-	.ctrl = lsxl_gpio_list,
-	.alarm = &lsxl_alarm,
-	.num_speed = ARRAY_SIZE(lsxl_speeds),
-	.speed = lsxl_speeds,
-};
-
-static struct platform_device lsxl_fan_device = {
-	.name = "gpio-fan",
-	.id = -1,
-	.num_resources = 0,
-	.dev = {
-		.platform_data = &lsxl_fan_data,
-	},
-};
-
 /*
  * On the LS-XHL/LS-CHLv2, the shutdown process is following:
  * - Userland monitors key events until the power switch goes to off position
@@ -111,24 +38,14 @@ static void lsxl_power_off(void)
 	kirkwood_restart('h', NULL);
 }
 
-#define LSXL_GPIO_HDD_POWER 10
-#define LSXL_GPIO_USB_POWER 11
-
 void __init lsxl_init(void)
 {
 	/*
 	 * Basic setup. Needs to be called early.
 	 */
-	kirkwood_mpp_conf(lsxl_mpp_config);
-
-	/* usb and sata power on */
-	gpio_set_value(LSXL_GPIO_USB_POWER, 1);
-	gpio_set_value(LSXL_GPIO_HDD_POWER, 1);
 
-	kirkwood_ehci_init();
 	kirkwood_ge00_init(&lsxl_ge00_data);
 	kirkwood_ge01_init(&lsxl_ge01_data);
-	platform_device_register(&lsxl_fan_device);
 
 	/* register power-off method */
 	pm_power_off = lsxl_power_off;
diff --git a/arch/arm/mach-kirkwood/board-mplcec4.c b/arch/arm/mach-kirkwood/board-mplcec4.c
new file mode 100644
index 0000000..56bfe5a
--- /dev/null
+++ b/arch/arm/mach-kirkwood/board-mplcec4.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012 MPL AG, Switzerland
+ * Stefan Peter <s.peter@mpl.ch>
+ *
+ * arch/arm/mach-kirkwood/board-mplcec4.c
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/platform_data/mmc-mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mv643xx_eth_platform_data mplcec4_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(1),
+};
+
+static struct mv643xx_eth_platform_data mplcec4_ge01_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(2),
+};
+
+static struct mvsdio_platform_data mplcec4_mvsdio_data = {
+	.gpio_card_detect = 47,	/* MPP47 used as SD card detect */
+};
+
+
+void __init mplcec4_init(void)
+{
+	/*
+	 * Basic setup. Needs to be called early.
+	 */
+	kirkwood_ge00_init(&mplcec4_ge00_data);
+	kirkwood_ge01_init(&mplcec4_ge01_data);
+	kirkwood_sdio_init(&mplcec4_mvsdio_data);
+	kirkwood_pcie_init(KW_PCIE0);
+}
+
+
+
diff --git a/arch/arm/mach-kirkwood/board-ns2.c b/arch/arm/mach-kirkwood/board-ns2.c
new file mode 100644
index 0000000..8821720
--- /dev/null
+++ b/arch/arm/mach-kirkwood/board-ns2.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2012 (C), Simon Guinot <simon.guinot@sequanux.org>
+ *
+ * arch/arm/mach-kirkwood/board-ns2.c
+ *
+ * LaCie Network Space v2 board (and parents) initialization for drivers
+ * not converted to flattened device tree yet.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mv643xx_eth_platform_data ns2_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
+};
+
+static unsigned int ns2_mpp_config[] __initdata = {
+	MPP0_SPI_SCn,
+	MPP1_SPI_MOSI,
+	MPP2_SPI_SCK,
+	MPP3_SPI_MISO,
+	MPP4_NF_IO6,
+	MPP5_NF_IO7,
+	MPP6_SYSRST_OUTn,
+	MPP7_GPO,		/* Fan speed (bit 1) */
+	MPP8_TW0_SDA,
+	MPP9_TW0_SCK,
+	MPP10_UART0_TXD,
+	MPP11_UART0_RXD,
+	MPP12_GPO,		/* Red led */
+	MPP14_GPIO,		/* USB fuse */
+	MPP16_GPIO,		/* SATA 0 power */
+	MPP17_GPIO,		/* SATA 1 power */
+	MPP18_NF_IO0,
+	MPP19_NF_IO1,
+	MPP20_SATA1_ACTn,
+	MPP21_SATA0_ACTn,
+	MPP22_GPIO,		/* Fan speed (bit 0) */
+	MPP23_GPIO,		/* Fan power */
+	MPP24_GPIO,		/* USB mode select */
+	MPP25_GPIO,		/* Fan rotation fail */
+	MPP26_GPIO,		/* USB device vbus */
+	MPP28_GPIO,		/* USB enable host vbus */
+	MPP29_GPIO,		/* Blue led (slow register) */
+	MPP30_GPIO,		/* Blue led (command register) */
+	MPP31_GPIO,		/* Board power off */
+	MPP32_GPIO,		/* Power button (0 = Released, 1 = Pushed) */
+	MPP33_GPO,		/* Fan speed (bit 2) */
+	0
+};
+
+#define NS2_GPIO_POWER_OFF	31
+
+static void ns2_power_off(void)
+{
+	gpio_set_value(NS2_GPIO_POWER_OFF, 1);
+}
+
+void __init ns2_init(void)
+{
+	/*
+	 * Basic setup. Needs to be called early.
+	 */
+	kirkwood_mpp_conf(ns2_mpp_config);
+
+	if (of_machine_is_compatible("lacie,netspace_lite_v2") ||
+	    of_machine_is_compatible("lacie,netspace_mini_v2"))
+		ns2_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
+	kirkwood_ge00_init(&ns2_ge00_data);
+
+	if (gpio_request(NS2_GPIO_POWER_OFF, "power-off") == 0 &&
+	    gpio_direction_output(NS2_GPIO_POWER_OFF, 0) == 0)
+		pm_power_off = ns2_power_off;
+	else
+		pr_err("ns2: failed to configure power-off GPIO\n");
+}
diff --git a/arch/arm/mach-kirkwood/board-nsa310.c b/arch/arm/mach-kirkwood/board-nsa310.c
new file mode 100644
index 0000000..f58d2e1
--- /dev/null
+++ b/arch/arm/mach-kirkwood/board-nsa310.c
@@ -0,0 +1,101 @@
+/*
+ * arch/arm/mach-kirkwood/nsa-310-setup.c
+ *
+ * ZyXEL NSA-310 Setup
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include "common.h"
+#include "mpp.h"
+
+#define NSA310_GPIO_USB_POWER_OFF	21
+#define NSA310_GPIO_POWER_OFF		48
+
+static unsigned int nsa310_mpp_config[] __initdata = {
+	MPP12_GPIO, /* led esata green */
+	MPP13_GPIO, /* led esata red */
+	MPP15_GPIO, /* led usb green */
+	MPP16_GPIO, /* led usb red */
+	MPP21_GPIO, /* control usb power off */
+	MPP28_GPIO, /* led sys green */
+	MPP29_GPIO, /* led sys red */
+	MPP36_GPIO, /* key reset */
+	MPP37_GPIO, /* key copy */
+	MPP39_GPIO, /* led copy green */
+	MPP40_GPIO, /* led copy red */
+	MPP41_GPIO, /* led hdd green */
+	MPP42_GPIO, /* led hdd red */
+	MPP44_GPIO, /* ?? */
+	MPP46_GPIO, /* key power */
+	MPP48_GPIO, /* control power off */
+	0
+};
+
+static struct i2c_board_info __initdata nsa310_i2c_info[] = {
+	{ I2C_BOARD_INFO("adt7476", 0x2e) },
+};
+
+static void nsa310_power_off(void)
+{
+	gpio_set_value(NSA310_GPIO_POWER_OFF, 1);
+}
+
+static int __init nsa310_gpio_request(unsigned int gpio, unsigned long flags,
+				       const char *label)
+{
+	int err;
+
+	err = gpio_request_one(gpio, flags, label);
+	if (err)
+		pr_err("NSA-310: can't setup GPIO%u (%s), err=%d\n",
+			gpio, label, err);
+
+	return err;
+}
+
+static void __init nsa310_gpio_init(void)
+{
+	int err;
+
+	err = nsa310_gpio_request(NSA310_GPIO_POWER_OFF, GPIOF_OUT_INIT_LOW,
+				  "Power Off");
+	if (!err)
+		pm_power_off = nsa310_power_off;
+
+	nsa310_gpio_request(NSA310_GPIO_USB_POWER_OFF, GPIOF_OUT_INIT_LOW,
+			    "USB Power Off");
+}
+
+void __init nsa310_init(void)
+{
+	u32 dev, rev;
+
+	kirkwood_mpp_conf(nsa310_mpp_config);
+
+	nsa310_gpio_init();
+
+	kirkwood_pcie_id(&dev, &rev);
+
+	i2c_register_board_info(0, ARRAY_AND_SIZE(nsa310_i2c_info));
+}
+
+static int __init nsa310_pci_init(void)
+{
+	if (of_machine_is_compatible("zyxel,nsa310"))
+		kirkwood_pcie_init(KW_PCIE0);
+
+	return 0;
+}
+
+subsys_initcall(nsa310_pci_init);
diff --git a/arch/arm/mach-kirkwood/board-openblocks_a6.c b/arch/arm/mach-kirkwood/board-openblocks_a6.c
new file mode 100644
index 0000000..815fc64
--- /dev/null
+++ b/arch/arm/mach-kirkwood/board-openblocks_a6.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2012 Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+ *
+ * arch/arm/mach-kirkwood/board-openblocks_a6.c
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/clk.h>
+#include <linux/clk-private.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mv643xx_eth_platform_data openblocks_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
+};
+
+static unsigned int openblocks_a6_mpp_config[] __initdata = {
+	MPP0_NF_IO2,
+	MPP1_NF_IO3,
+	MPP2_NF_IO4,
+	MPP3_NF_IO5,
+	MPP4_NF_IO6,
+	MPP5_NF_IO7,
+	MPP6_SYSRST_OUTn,
+	MPP8_UART1_RTS,
+	MPP9_UART1_CTS,
+	MPP10_UART0_TXD,
+	MPP11_UART0_RXD,
+	MPP13_UART1_TXD,
+	MPP14_UART1_RXD,
+	MPP15_UART0_RTS,
+	MPP16_UART0_CTS,
+	MPP18_NF_IO0,
+	MPP19_NF_IO1,
+	MPP20_GPIO, /* DIP SW0 */
+	MPP21_GPIO, /* DIP SW1 */
+	MPP22_GPIO, /* DIP SW2 */
+	MPP23_GPIO, /* DIP SW3 */
+	MPP24_GPIO, /* GPIO 0 */
+	MPP25_GPIO, /* GPIO 1 */
+	MPP26_GPIO, /* GPIO 2 */
+	MPP27_GPIO, /* GPIO 3 */
+	MPP28_GPIO, /* GPIO 4 */
+	MPP29_GPIO, /* GPIO 5 */
+	MPP30_GPIO, /* GPIO 6 */
+	MPP31_GPIO, /* GPIO 7 */
+	MPP36_TW1_SDA,
+	MPP37_TW1_SCK,
+	MPP38_GPIO, /* INIT */
+	MPP39_GPIO, /* USB OC */
+	MPP41_GPIO, /* LED: Red */
+	MPP42_GPIO, /* LED: Green */
+	MPP43_GPIO, /* LED: Yellow */
+	0,
+};
+
+void __init openblocks_a6_init(void)
+{
+	/*
+	 * Basic setup. Needs to be called early.
+	 */
+	kirkwood_mpp_conf(openblocks_a6_mpp_config);
+	kirkwood_ge00_init(&openblocks_ge00_data);
+}
diff --git a/arch/arm/mach-kirkwood/board-ts219.c b/arch/arm/mach-kirkwood/board-ts219.c
index 1750e68..acb0187 100644
--- a/arch/arm/mach-kirkwood/board-ts219.c
+++ b/arch/arm/mach-kirkwood/board-ts219.c
@@ -19,54 +19,25 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/mv643xx_eth.h>
-#include <linux/ata_platform.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
 #include "common.h"
-#include "mpp.h"
 #include "tsx1x-common.h"
 
 static struct mv643xx_eth_platform_data qnap_ts219_ge00_data = {
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
 };
 
-static unsigned int qnap_ts219_mpp_config[] __initdata = {
-	MPP0_SPI_SCn,
-	MPP1_SPI_MOSI,
-	MPP2_SPI_SCK,
-	MPP3_SPI_MISO,
-	MPP4_SATA1_ACTn,
-	MPP5_SATA0_ACTn,
-	MPP8_TW0_SDA,
-	MPP9_TW0_SCK,
-	MPP10_UART0_TXD,
-	MPP11_UART0_RXD,
-	MPP13_UART1_TXD,	/* PIC controller */
-	MPP14_UART1_RXD,	/* PIC controller */
-	MPP15_GPIO,		/* USB Copy button (on devices with 88F6281) */
-	MPP16_GPIO,		/* Reset button (on devices with 88F6281) */
-	MPP36_GPIO,		/* RAM: 0: 256 MB, 1: 512 MB */
-	MPP37_GPIO,		/* Reset button (on devices with 88F6282) */
-	MPP43_GPIO,		/* USB Copy button (on devices with 88F6282) */
-	MPP44_GPIO,		/* Board ID: 0: TS-11x, 1: TS-21x */
-	0
-};
-
 void __init qnap_dt_ts219_init(void)
 {
 	u32 dev, rev;
 
-	kirkwood_mpp_conf(qnap_ts219_mpp_config);
-
 	kirkwood_pcie_id(&dev, &rev);
 	if (dev == MV88F6282_DEV_ID)
 		qnap_ts219_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
 
 	kirkwood_ge00_init(&qnap_ts219_ge00_data);
-	kirkwood_ehci_init();
 
 	pm_power_off = qnap_tsx1x_power_off;
 }
diff --git a/arch/arm/mach-kirkwood/board-usi_topkick.c b/arch/arm/mach-kirkwood/board-usi_topkick.c
new file mode 100644
index 0000000..15e69fc
--- /dev/null
+++ b/arch/arm/mach-kirkwood/board-usi_topkick.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012 (C), Jason Cooper <jason@lakedaemon.net>
+ *
+ * arch/arm/mach-kirkwood/board-usi_topkick.c
+ *
+ * USI Topkick Init for drivers not converted to flattened device tree yet.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/platform_data/mmc-mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mv643xx_eth_platform_data topkick_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
+};
+
+static struct mvsdio_platform_data topkick_mvsdio_data = {
+	/* unfortunately the CD signal has not been connected */
+};
+
+/*
+ * GPIO LED layout
+ *
+ *       /-SYS_LED(2)
+ *       |
+ *       |   /-DISK_LED
+ *       |   |
+ *       |   |   /-WLAN_LED(2)
+ *       |   |   |
+ * [SW] [*] [*] [*]
+ */
+
+/*
+ * Switch positions
+ *
+ *     /-SW_LEFT
+ *     |
+ *     |   /-SW_IDLE
+ *     |   |
+ *     |   |   /-SW_RIGHT
+ *     |   |   |
+ * PS [L] [I] [R] LEDS
+ */
+
+static unsigned int topkick_mpp_config[] __initdata = {
+	MPP21_GPIO,	/* DISK_LED           (low active) - yellow */
+	MPP36_GPIO,	/* SATA0 power enable (high active) */
+	MPP37_GPIO,	/* SYS_LED2           (low active) - red */
+	MPP38_GPIO,	/* SYS_LED            (low active) - blue */
+	MPP39_GPIO,	/* WLAN_LED           (low active) - green */
+	MPP43_GPIO,	/* SW_LEFT            (low active) */
+	MPP44_GPIO,     /* SW_RIGHT           (low active) */
+	MPP45_GPIO,	/* SW_IDLE            (low active) */
+	MPP46_GPIO,     /* SW_LEFT            (low active) */
+	MPP48_GPIO,	/* WLAN_LED2          (low active) - yellow */
+	0
+};
+
+#define TOPKICK_SATA0_PWR_ENABLE 36
+
+void __init usi_topkick_init(void)
+{
+	/*
+	 * Basic setup. Needs to be called early.
+	 */
+	kirkwood_mpp_conf(topkick_mpp_config);
+
+	/* SATA0 power enable */
+	gpio_set_value(TOPKICK_SATA0_PWR_ENABLE, 1);
+
+	kirkwood_ge00_init(&topkick_ge00_data);
+	kirkwood_sdio_init(&topkick_mvsdio_data);
+}
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index 2c6c218..5303be6 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -18,10 +18,10 @@
 #include <linux/clk-provider.h>
 #include <linux/spinlock.h>
 #include <linux/mv643xx_i2c.h>
+#include <linux/timex.h>
+#include <linux/kexec.h>
 #include <net/dsa.h>
 #include <asm/page.h>
-#include <asm/timex.h>
-#include <asm/kexec.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <mach/kirkwood.h>
@@ -266,6 +266,7 @@ void __init kirkwood_clk_init(void)
 	orion_clkdev_add("1", "pcie", pex1);
 	orion_clkdev_add(NULL, "kirkwood-i2s", audio);
 	orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".0", runit);
+	orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".1", runit);
 
 	/* Marvell says runit is used by SPI, UART, NAND, TWSI, ...,
 	 * so should never be gated.
@@ -425,7 +426,7 @@ void __init kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data)
 /*****************************************************************************
  * SPI
  ****************************************************************************/
-void __init kirkwood_spi_init()
+void __init kirkwood_spi_init(void)
 {
 	orion_spi_init(SPI_PHYS_BASE);
 }
@@ -646,8 +647,7 @@ void __init kirkwood_l2_init(void)
 
 void __init kirkwood_init(void)
 {
-	printk(KERN_INFO "Kirkwood: %s, TCLK=%d.\n",
-		kirkwood_id(), kirkwood_tclk);
+	pr_info("Kirkwood: %s, TCLK=%d.\n", kirkwood_id(), kirkwood_tclk);
 
 	/*
 	 * Disable propagation of mbus errors to the CPU local bus,
@@ -671,7 +671,7 @@ void __init kirkwood_init(void)
 	kirkwood_xor1_init();
 	kirkwood_crypto_init();
 
-#ifdef CONFIG_KEXEC 
+#ifdef CONFIG_KEXEC
 	kexec_reinit = kirkwood_enable_pcie;
 #endif
 }
diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
index bcffd7c..5ffa57f 100644
--- a/arch/arm/mach-kirkwood/common.h
+++ b/arch/arm/mach-kirkwood/common.h
@@ -47,7 +47,8 @@ void kirkwood_i2c_init(void);
 void kirkwood_uart0_init(void);
 void kirkwood_uart1_init(void);
 void kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, int delay);
-void kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts, int (*dev_ready)(struct mtd_info *));
+void kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts,
+			    int (*dev_ready)(struct mtd_info *));
 void kirkwood_audio_init(void);
 void kirkwood_restart(char, const char *);
 void kirkwood_clk_init(void);
@@ -112,6 +113,40 @@ void km_kirkwood_init(void);
 static inline void km_kirkwood_init(void) {};
 #endif
 
+#ifdef CONFIG_MACH_MPLCEC4_DT
+void mplcec4_init(void);
+#else
+static inline void mplcec4_init(void) {};
+#endif
+
+#if defined(CONFIG_MACH_INETSPACE_V2_DT) || \
+	defined(CONFIG_MACH_NETSPACE_V2_DT) || \
+	defined(CONFIG_MACH_NETSPACE_MAX_V2_DT) || \
+	defined(CONFIG_MACH_NETSPACE_LITE_V2_DT) || \
+	defined(CONFIG_MACH_NETSPACE_MINI_V2_DT)
+void ns2_init(void);
+#else
+static inline void ns2_init(void) {};
+#endif
+
+#ifdef CONFIG_MACH_NSA310_DT
+void nsa310_init(void);
+#else
+static inline void nsa310_init(void) {};
+#endif
+
+#ifdef CONFIG_MACH_OPENBLOCKS_A6_DT
+void openblocks_a6_init(void);
+#else
+static inline void openblocks_a6_init(void) {};
+#endif
+
+#ifdef CONFIG_MACH_TOPKICK_DT
+void usi_topkick_init(void);
+#else
+static inline void usi_topkick_init(void) {};
+#endif
+
 /* early init functions not converted to fdt yet */
 char *kirkwood_id(void);
 void kirkwood_l2_init(void);
diff --git a/arch/arm/mach-kirkwood/cpuidle.c b/arch/arm/mach-kirkwood/cpuidle.c
index 0f17109..f730467 100644
--- a/arch/arm/mach-kirkwood/cpuidle.c
+++ b/arch/arm/mach-kirkwood/cpuidle.c
@@ -64,7 +64,7 @@ static int kirkwood_init_cpuidle(void)
 
 	cpuidle_register_driver(&kirkwood_idle_driver);
 	if (cpuidle_register_device(device)) {
-		printk(KERN_ERR "kirkwood_init_cpuidle: Failed registering\n");
+		pr_err("kirkwood_init_cpuidle: Failed registering\n");
 		return -EIO;
 	}
 	return 0;
diff --git a/arch/arm/mach-kirkwood/dockstar-setup.c b/arch/arm/mach-kirkwood/dockstar-setup.c
index 23dcb19..791a98f 100644
--- a/arch/arm/mach-kirkwood/dockstar-setup.c
+++ b/arch/arm/mach-kirkwood/dockstar-setup.c
@@ -93,7 +93,7 @@ static void __init dockstar_init(void)
 
 	if (gpio_request(29, "USB Power Enable") != 0 ||
 	    gpio_direction_output(29, 1) != 0)
-		printk(KERN_ERR "can't set up GPIO 29 (USB Power Enable)\n");
+		pr_err("can't set up GPIO 29 (USB Power Enable)\n");
 	kirkwood_ehci_init();
 
 	kirkwood_ge00_init(&dockstar_ge00_data);
diff --git a/arch/arm/mach-kirkwood/irq.c b/arch/arm/mach-kirkwood/irq.c
index 8847035..2a97a2e 100644
--- a/arch/arm/mach-kirkwood/irq.c
+++ b/arch/arm/mach-kirkwood/irq.c
@@ -14,6 +14,7 @@
 #include <mach/bridge-regs.h>
 #include <plat/orion-gpio.h>
 #include <plat/irq.h>
+#include "common.h"
 
 static int __initdata gpio0_irqs[4] = {
 	IRQ_KIRKWOOD_GPIO_LOW_0_7,
diff --git a/arch/arm/mach-kirkwood/lacie_v2-common.c b/arch/arm/mach-kirkwood/lacie_v2-common.c
index 285edab..4894959 100644
--- a/arch/arm/mach-kirkwood/lacie_v2-common.c
+++ b/arch/arm/mach-kirkwood/lacie_v2-common.c
@@ -19,6 +19,7 @@
 #include <mach/irqs.h>
 #include <plat/time.h>
 #include "common.h"
+#include "lacie_v2-common.h"
 
 /*****************************************************************************
  * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005)
diff --git a/arch/arm/mach-kirkwood/mpp.c b/arch/arm/mach-kirkwood/mpp.c
index 0c6ad63..827cde4 100644
--- a/arch/arm/mach-kirkwood/mpp.c
+++ b/arch/arm/mach-kirkwood/mpp.c
@@ -30,8 +30,8 @@ static unsigned int __init kirkwood_variant(void)
 	if (dev == MV88F6180_DEV_ID)
 		return MPP_F6180_MASK;
 
-	printk(KERN_ERR "MPP setup: unknown kirkwood variant "
-			"(dev %#x rev %#x)\n", dev, rev);
+	pr_err("MPP setup: unknown kirkwood variant (dev %#x rev %#x)\n",
+	       dev, rev);
 	return 0;
 }
 
diff --git a/arch/arm/mach-kirkwood/netspace_v2-setup.c b/arch/arm/mach-kirkwood/netspace_v2-setup.c
index 88b0788..728e86d 100644
--- a/arch/arm/mach-kirkwood/netspace_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netspace_v2-setup.c
@@ -79,7 +79,7 @@ static struct platform_device netspace_v2_gpio_buttons = {
 	.name		= "gpio-keys",
 	.id		= -1,
 	.dev		= {
-		.platform_data 	= &netspace_v2_button_data,
+		.platform_data	= &netspace_v2_button_data,
 	},
 };
 
@@ -211,7 +211,7 @@ static unsigned int netspace_v2_mpp_config[] __initdata = {
 	MPP29_GPIO,		/* Blue led (slow register) */
 	MPP30_GPIO,		/* Blue led (command register) */
 	MPP31_GPIO,		/* Board power off */
-	MPP32_GPIO, 		/* Power button (0 = Released, 1 = Pushed) */
+	MPP32_GPIO,		/* Power button (0 = Released, 1 = Pushed) */
 	MPP33_GPO,		/* Fan speed (bit 2) */
 	0
 };
diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
index 134ef50..7e81e9b 100644
--- a/arch/arm/mach-kirkwood/openrd-setup.c
+++ b/arch/arm/mach-kirkwood/openrd-setup.c
@@ -121,14 +121,12 @@ static int __init uart1_mpp_config(void)
 	kirkwood_mpp_conf(openrd_uart1_mpp_config);
 
 	if (gpio_request(34, "SD_UART1_SEL")) {
-		printk(KERN_ERR "GPIO request failed for SD/UART1 selection"
-				", gpio: 34\n");
+		pr_err("GPIO request 34 failed for SD/UART1 selection\n");
 		return -EIO;
 	}
 
 	if (gpio_request(28, "RS232_RS485_SEL")) {
-		printk(KERN_ERR "GPIO request failed for RS232/RS485 selection"
-				", gpio# 28\n");
+		pr_err("GPIO request 28 failed for RS232/RS485 selection\n");
 		gpio_free(34);
 		return -EIO;
 	}
@@ -185,15 +183,13 @@ static void __init openrd_init(void)
 
 	if (uart1 <= 0) {
 		if (uart1 < 0)
-			printk(KERN_ERR "Invalid kernel parameter to select "
-				"UART1. Defaulting to SD. ERROR CODE: %d\n",
-				uart1);
+			pr_err("Invalid kernel parameter to select UART1. Defaulting to SD. ERROR CODE: %d\n",
+			       uart1);
 
 		/* Select SD
 		 * Pin # 34: 0 => UART1, 1 => SD */
 		if (gpio_request(34, "SD_UART1_SEL")) {
-			printk(KERN_ERR "GPIO request failed for SD/UART1 "
-					"selection, gpio: 34\n");
+			pr_err("GPIO request 34 failed for SD/UART1 selection\n");
 		} else {
 
 			gpio_direction_output(34, 1);
diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c
index ec54491..ef10264 100644
--- a/arch/arm/mach-kirkwood/pcie.c
+++ b/arch/arm/mach-kirkwood/pcie.c
@@ -26,7 +26,7 @@ static void kirkwood_enable_pcie_clk(const char *port)
 
 	clk = clk_get_sys("pcie", port);
 	if (IS_ERR(clk)) {
-		printk(KERN_ERR "PCIE clock %s missing\n", port);
+		pr_err("PCIE clock %s missing\n", port);
 		return;
 	}
 	clk_prepare_enable(clk);
@@ -168,7 +168,7 @@ static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
 		return 0;
 
 	index = pcie_port_map[nr];
-	printk(KERN_INFO "PCI: bus%d uses PCIe port %d\n", sys->busnr, index);
+	pr_info("PCI: bus%d uses PCIe port %d\n", sys->busnr, index);
 
 	pp = kzalloc(sizeof(*pp), GFP_KERNEL);
 	if (!pp)
@@ -186,7 +186,8 @@ static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
 	case 1:
 		kirkwood_enable_pcie_clk("1");
 		pcie1_ioresources_init(pp);
-		pci_ioremap_io(SZ_64K * sys->busnr, KIRKWOOD_PCIE1_IO_PHYS_BASE);
+		pci_ioremap_io(SZ_64K * sys->busnr,
+			       KIRKWOOD_PCIE1_IO_PHYS_BASE);
 		break;
 	default:
 		panic("PCIe setup: invalid controller %d", index);
@@ -207,14 +208,19 @@ static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
 	return 1;
 }
 
+/*
+ * The root complex has a hardwired class of PCI_CLASS_MEMORY_OTHER, when it
+ * is operating as a root complex this needs to be switched to
+ * PCI_CLASS_BRIDGE_HOST or Linux will errantly try to process the BAR's on
+ * the device. Decoding setup is handled by the orion code.
+ */
 static void __devinit rc_pci_fixup(struct pci_dev *dev)
 {
-	/*
-	 * Prevent enumeration of root complex.
-	 */
 	if (dev->bus->parent == NULL && dev->devfn == 0) {
 		int i;
 
+		dev->class &= 0xff;
+		dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
 		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
 			dev->resource[i].start = 0;
 			dev->resource[i].end   = 0;
@@ -224,22 +230,6 @@ static void __devinit rc_pci_fixup(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
 
-static struct pci_bus __init *
-kirkwood_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
-	struct pci_bus *bus;
-
-	if (nr < num_pcie_ports) {
-		bus = pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
-					&sys->resources);
-	} else {
-		bus = NULL;
-		BUG();
-	}
-
-	return bus;
-}
-
 static int __init kirkwood_pcie_map_irq(const struct pci_dev *dev, u8 slot,
 	u8 pin)
 {
@@ -251,19 +241,19 @@ static int __init kirkwood_pcie_map_irq(const struct pci_dev *dev, u8 slot,
 
 static struct hw_pci kirkwood_pci __initdata = {
 	.setup		= kirkwood_pcie_setup,
-	.scan		= kirkwood_pcie_scan_bus,
 	.map_irq	= kirkwood_pcie_map_irq,
+	.ops            = &pcie_ops,
 };
 
 static void __init add_pcie_port(int index, void __iomem *base)
 {
-	printk(KERN_INFO "Kirkwood PCIe port %d: ", index);
+	pr_info("Kirkwood PCIe port %d: ", index);
 
 	if (orion_pcie_link_up(base)) {
-		printk(KERN_INFO "link up\n");
+		pr_info("link up\n");
 		pcie_port_map[num_pcie_ports++] = index;
 	} else
-		printk(KERN_INFO "link down, ignoring\n");
+		pr_info("link down, ignoring\n");
 }
 
 void __init kirkwood_pcie_init(unsigned int portmask)
diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c
index 28d0aba..8a17594 100644
--- a/arch/arm/mach-kirkwood/sheevaplug-setup.c
+++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c
@@ -117,7 +117,7 @@ static void __init sheevaplug_init(void)
 
 	if (gpio_request(29, "USB Power Enable") != 0 ||
 	    gpio_direction_output(29, 1) != 0)
-		printk(KERN_ERR "can't set up GPIO 29 (USB Power Enable)\n");
+		pr_err("can't set up GPIO 29 (USB Power Enable)\n");
 	kirkwood_ehci_init();
 
 	kirkwood_ge00_init(&sheevaplug_ge00_data);
diff --git a/arch/arm/mach-kirkwood/t5325-setup.c b/arch/arm/mach-kirkwood/t5325-setup.c
index bad738e..f2daf71 100644
--- a/arch/arm/mach-kirkwood/t5325-setup.c
+++ b/arch/arm/mach-kirkwood/t5325-setup.c
@@ -29,7 +29,7 @@
 #include "common.h"
 #include "mpp.h"
 
-struct mtd_partition hp_t5325_partitions[] = {
+static struct mtd_partition hp_t5325_partitions[] = {
 	{
 		.name		= "u-boot env",
 		.size		= SZ_64K,
@@ -59,14 +59,14 @@ struct mtd_partition hp_t5325_partitions[] = {
 	},
 };
 
-const struct flash_platform_data hp_t5325_flash = {
+static const struct flash_platform_data hp_t5325_flash = {
 	.type		= "mx25l8005",
 	.name		= "spi_flash",
 	.parts		= hp_t5325_partitions,
 	.nr_parts	= ARRAY_SIZE(hp_t5325_partitions),
 };
 
-struct spi_board_info __initdata hp_t5325_spi_slave_info[] = {
+static struct spi_board_info __initdata hp_t5325_spi_slave_info[] = {
 	{
 		.modalias	= "m25p80",
 		.platform_data	= &hp_t5325_flash,
diff --git a/arch/arm/mach-kirkwood/ts41x-setup.c b/arch/arm/mach-kirkwood/ts41x-setup.c
index 367a940..e4c6127 100644
--- a/arch/arm/mach-kirkwood/ts41x-setup.c
+++ b/arch/arm/mach-kirkwood/ts41x-setup.c
@@ -170,8 +170,7 @@ static int __init ts41x_pci_init(void)
 		else
 			kirkwood_pcie_init(KW_PCIE0);
 	}
-
-   return 0;
+	return 0;
 }
 subsys_initcall(ts41x_pci_init);
 
diff --git a/arch/arm/mach-kirkwood/tsx1x-common.c b/arch/arm/mach-kirkwood/tsx1x-common.c
index 8943ede..cec87ce 100644
--- a/arch/arm/mach-kirkwood/tsx1x-common.c
+++ b/arch/arm/mach-kirkwood/tsx1x-common.c
@@ -7,6 +7,7 @@
 #include <linux/serial_reg.h>
 #include <mach/kirkwood.h>
 #include "common.h"
+#include "tsx1x-common.h"
 
 /*
  * QNAP TS-x1x Boards flash
@@ -29,7 +30,7 @@
  *
  ***************************************************************************/
 
-struct mtd_partition qnap_tsx1x_partitions[] = {
+static struct mtd_partition qnap_tsx1x_partitions[] = {
 	{
 		.name		= "U-Boot",
 		.size		= 0x00080000,
@@ -58,14 +59,14 @@ struct mtd_partition qnap_tsx1x_partitions[] = {
 	},
 };
 
-const struct flash_platform_data qnap_tsx1x_flash = {
+static const struct flash_platform_data qnap_tsx1x_flash = {
 	.type		= "m25p128",
 	.name		= "spi_flash",
 	.parts		= qnap_tsx1x_partitions,
 	.nr_parts	= ARRAY_SIZE(qnap_tsx1x_partitions),
 };
 
-struct spi_board_info __initdata qnap_tsx1x_spi_slave_info[] = {
+static struct spi_board_info __initdata qnap_tsx1x_spi_slave_info[] = {
 	{
 		.modalias	= "m25p80",
 		.platform_data	= &qnap_tsx1x_flash,
diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c
index f48c2e9..dd5d6f5 100644
--- a/arch/arm/mach-lpc32xx/clock.c
+++ b/arch/arm/mach-lpc32xx/clock.c
@@ -585,6 +585,13 @@ static struct clk clk_timer3 = {
 	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER3_EN,
 	.get_rate	= local_return_parent_rate,
 };
+static struct clk clk_mpwm = {
+	.parent		= &clk_pclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
+	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_MPWM_EN,
+	.get_rate	= local_return_parent_rate,
+};
 static struct clk clk_wdt = {
 	.parent		= &clk_pclk,
 	.enable		= local_onoff_enable,
@@ -1202,6 +1209,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_INIT("pl08xdmac", NULL, &clk_dma),
 	CLKDEV_INIT("4003c000.watchdog", NULL, &clk_wdt),
 	CLKDEV_INIT("4005c000.pwm", NULL, &clk_pwm),
+	CLKDEV_INIT("400e8000.mpwm", NULL, &clk_mpwm),
 	CLKDEV_INIT(NULL, "uart3_ck", &clk_uart3),
 	CLKDEV_INIT(NULL, "uart4_ck", &clk_uart4),
 	CLKDEV_INIT(NULL, "uart5_ck", &clk_uart5),
diff --git a/arch/arm/mach-lpc32xx/include/mach/platform.h b/arch/arm/mach-lpc32xx/include/mach/platform.h
index acc4aab..b5612a1 100644
--- a/arch/arm/mach-lpc32xx/include/mach/platform.h
+++ b/arch/arm/mach-lpc32xx/include/mach/platform.h
@@ -515,6 +515,7 @@
 /*
  * clkpwr_timers_pwms_clk_ctrl_1 register definitions
  */
+#define LPC32XX_CLKPWR_TMRPWMCLK_MPWM_EN	0x40
 #define LPC32XX_CLKPWR_TMRPWMCLK_TIMER3_EN	0x20
 #define LPC32XX_CLKPWR_TMRPWMCLK_TIMER2_EN	0x10
 #define LPC32XX_CLKPWR_TMRPWMCLK_TIMER1_EN	0x08
diff --git a/arch/arm/mach-lpc32xx/irq.c b/arch/arm/mach-lpc32xx/irq.c
index 3c63327..9ecb8f9 100644
--- a/arch/arm/mach-lpc32xx/irq.c
+++ b/arch/arm/mach-lpc32xx/irq.c
@@ -412,7 +412,6 @@ static const struct of_device_id mic_of_match[] __initconst = {
 void __init lpc32xx_init_irq(void)
 {
 	unsigned int i;
-	int irq_base;
 
 	/* Setup MIC */
 	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
@@ -443,15 +442,6 @@ void __init lpc32xx_init_irq(void)
 	lpc32xx_set_default_mappings(SIC1_APR_DEFAULT, SIC1_ATR_DEFAULT, 32);
 	lpc32xx_set_default_mappings(SIC2_APR_DEFAULT, SIC2_ATR_DEFAULT, 64);
 
-	/* mask all interrupts except SUBIRQ */
-	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
-	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE));
-	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
-
-	/* MIC SUBIRQx interrupts will route handling to the chain handlers */
-	irq_set_chained_handler(IRQ_LPC32XX_SUB1IRQ, lpc32xx_sic1_handler);
-	irq_set_chained_handler(IRQ_LPC32XX_SUB2IRQ, lpc32xx_sic2_handler);
-
 	/* Initially disable all wake events */
 	__raw_writel(0, LPC32XX_CLKPWR_P01_ER);
 	__raw_writel(0, LPC32XX_CLKPWR_INT_ER);
@@ -475,16 +465,13 @@ void __init lpc32xx_init_irq(void)
 
 	of_irq_init(mic_of_match);
 
-	irq_base = irq_alloc_descs(-1, 0, NR_IRQS, 0);
-	if (irq_base < 0) {
-		pr_warn("Cannot allocate irq_descs, assuming pre-allocated\n");
-		irq_base = 0;
-	}
-
 	lpc32xx_mic_domain = irq_domain_add_legacy(lpc32xx_mic_np, NR_IRQS,
-						   irq_base, 0,
-						   &irq_domain_simple_ops,
+						   0, 0, &irq_domain_simple_ops,
 						   NULL);
 	if (!lpc32xx_mic_domain)
 		panic("Unable to add MIC irq domain\n");
+
+	/* MIC SUBIRQx interrupts will route handling to the chain handlers */
+	irq_set_chained_handler(IRQ_LPC32XX_SUB1IRQ, lpc32xx_sic1_handler);
+	irq_set_chained_handler(IRQ_LPC32XX_SUB2IRQ, lpc32xx_sic2_handler);
 }
diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
index 178d4da..ebdda83 100644
--- a/arch/arm/mach-mmp/Kconfig
+++ b/arch/arm/mach-mmp/Kconfig
@@ -89,6 +89,8 @@ config MACH_MMP_DT
 	select CPU_PXA168
 	select CPU_PXA910
 	select USE_OF
+	select PINCTRL
+	select PINCTRL_SINGLE
 	help
 	  Include support for Marvell MMP2 based platforms using
 	  the device tree. Needn't select any other machine while
@@ -99,6 +101,8 @@ config MACH_MMP2_DT
 	depends on !CPU_MOHAWK
 	select CPU_MMP2
 	select USE_OF
+	select PINCTRL
+	select PINCTRL_SINGLE
 	help
 	  Include support for Marvell MMP2 based platforms using
 	  the device tree.
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index 4748ec5..c66129b 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -100,6 +100,25 @@ static struct fb_videomode apx4devkit_video_modes[] = {
 	},
 };
 
+static struct fb_videomode apf28dev_video_modes[] = {
+	{
+		.name = "LW700",
+		.refresh = 60,
+		.xres = 800,
+		.yres = 480,
+		.pixclock = 30303, /* picosecond */
+		.left_margin = 96,
+		.right_margin = 96, /* at least 3 & 1 */
+		.upper_margin = 0x14,
+		.lower_margin = 0x15,
+		.hsync_len = 64,
+		.vsync_len = 4,
+		.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT |
+				FB_SYNC_DATA_ENABLE_HIGH_ACT |
+				FB_SYNC_DOTCLK_FAILING_ACT,
+	},
+};
+
 static struct mxsfb_platform_data mxsfb_pdata __initdata;
 
 /*
@@ -160,6 +179,7 @@ static struct sys_timer imx28_timer = {
 enum mac_oui {
 	OUI_FSL,
 	OUI_DENX,
+	OUI_CRYSTALFONTZ,
 };
 
 static void __init update_fec_mac_prop(enum mac_oui oui)
@@ -175,8 +195,12 @@ static void __init update_fec_mac_prop(enum mac_oui oui)
 		np = of_find_compatible_node(from, NULL, "fsl,imx28-fec");
 		if (!np)
 			return;
+
 		from = np;
 
+		if (of_get_property(np, "local-mac-address", NULL))
+			continue;
+
 		newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL);
 		if (!newmac)
 			return;
@@ -205,13 +229,18 @@ static void __init update_fec_mac_prop(enum mac_oui oui)
 			macaddr[1] = 0xe5;
 			macaddr[2] = 0x4e;
 			break;
+		case OUI_CRYSTALFONTZ:
+			macaddr[0] = 0x58;
+			macaddr[1] = 0xb9;
+			macaddr[2] = 0xe1;
+			break;
 		}
 		val = ocotp[i];
 		macaddr[3] = (val >> 16) & 0xff;
 		macaddr[4] = (val >> 8) & 0xff;
 		macaddr[5] = (val >> 0) & 0xff;
 
-		prom_update_property(np, newmac);
+		of_update_property(np, newmac);
 	}
 }
 
@@ -261,6 +290,11 @@ static void __init m28evk_init(void)
 	mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT;
 }
 
+static void __init sc_sps1_init(void)
+{
+	enable_clk_enet_out();
+}
+
 static int apx4devkit_phy_fixup(struct phy_device *phy)
 {
 	phy->dev_flags |= MICREL_PHY_50MHZ_CLK;
@@ -355,6 +389,22 @@ static void __init tx28_post_init(void)
 	pinctrl_put(pctl);
 }
 
+static void __init cfa10049_init(void)
+{
+	enable_clk_enet_out();
+	update_fec_mac_prop(OUI_CRYSTALFONTZ);
+}
+
+static void __init apf28_init(void)
+{
+	enable_clk_enet_out();
+
+	mxsfb_pdata.mode_list = apf28dev_video_modes;
+	mxsfb_pdata.mode_count = ARRAY_SIZE(apf28dev_video_modes);
+	mxsfb_pdata.default_bpp = 16;
+	mxsfb_pdata.ld_intf_width = STMLCDIF_16BIT;
+}
+
 static void __init mxs_machine_init(void)
 {
 	if (of_machine_is_compatible("fsl,imx28-evk"))
@@ -365,6 +415,12 @@ static void __init mxs_machine_init(void)
 		m28evk_init();
 	else if (of_machine_is_compatible("bluegiga,apx4devkit"))
 		apx4devkit_init();
+	else if (of_machine_is_compatible("crystalfontz,cfa10049"))
+		cfa10049_init();
+	else if (of_machine_is_compatible("armadeus,imx28-apf28"))
+		apf28_init();
+	else if (of_machine_is_compatible("schulercontrol,imx28-sps1"))
+		sc_sps1_init();
 
 	of_platform_populate(NULL, of_default_bus_match_table,
 			     mxs_auxdata_lookup, NULL);
diff --git a/arch/arm/mach-mxs/timer.c b/arch/arm/mach-mxs/timer.c
index 7c37926..856f4c7 100644
--- a/arch/arm/mach-mxs/timer.c
+++ b/arch/arm/mach-mxs/timer.c
@@ -29,6 +29,7 @@
 #include <linux/of_irq.h>
 
 #include <asm/mach/time.h>
+#include <asm/sched_clock.h>
 #include <mach/mxs.h>
 #include <mach/common.h>
 
@@ -233,15 +234,22 @@ static struct clocksource clocksource_mxs = {
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
+static u32 notrace mxs_read_sched_clock_v2(void)
+{
+	return ~readl_relaxed(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1));
+}
+
 static int __init mxs_clocksource_init(struct clk *timer_clk)
 {
 	unsigned int c = clk_get_rate(timer_clk);
 
 	if (timrot_is_v1())
 		clocksource_register_hz(&clocksource_mxs, c);
-	else
+	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);
+	}
 
 	return 0;
 }
diff --git a/arch/arm/mach-nomadik/Kconfig b/arch/arm/mach-nomadik/Kconfig
index c744946..706dc57 100644
--- a/arch/arm/mach-nomadik/Kconfig
+++ b/arch/arm/mach-nomadik/Kconfig
@@ -4,7 +4,7 @@ menu "Nomadik boards"
 
 config MACH_NOMADIK_8815NHK
 	bool "ST 8815 Nomadik Hardware Kit (evaluation board)"
-	select HAS_MTU
+	select CLKSRC_NOMADIK_MTU
 	select NOMADIK_8815
 
 endmenu
diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c
index bfa1eab..9f19069 100644
--- a/arch/arm/mach-nomadik/board-nhk8815.c
+++ b/arch/arm/mach-nomadik/board-nhk8815.c
@@ -19,25 +19,21 @@
 #include <linux/gpio.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
+#include <linux/mtd/fsmc.h>
 #include <linux/mtd/onenand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/i2c.h>
 #include <linux/io.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
+#include <linux/platform_data/clocksource-nomadik-mtu.h>
 #include <asm/hardware/vic.h>
 #include <asm/sizes.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/irq.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/time.h>
-
-#include <plat/gpio-nomadik.h>
-#include <plat/mtu.h>
-#include <plat/pincfg.h>
-
-#include <linux/platform_data/mtd-nomadik-nand.h>
-#include <mach/fsmc.h>
+#include <mach/irqs.h>
 
 #include "cpu-8815.h"
 
@@ -45,39 +41,34 @@
 #define SRC_CR_INIT_MASK	0x00007fff
 #define SRC_CR_INIT_VAL		0x2aaa8000
 
+#define ALE_OFF 0x1000000
+#define CLE_OFF 0x800000
+
 /* These addresses span 16MB, so use three individual pages */
 static struct resource nhk8815_nand_resources[] = {
 	{
+		.name = "nand_data",
+		.start = 0x40000000,
+		.end = 0x40000000 + SZ_16K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
 		.name = "nand_addr",
-		.start = NAND_IO_ADDR,
-		.end = NAND_IO_ADDR + 0xfff,
+		.start = 0x40000000 + ALE_OFF,
+		.end = 0x40000000 +ALE_OFF + SZ_16K - 1,
 		.flags = IORESOURCE_MEM,
 	}, {
 		.name = "nand_cmd",
-		.start = NAND_IO_CMD,
-		.end = NAND_IO_CMD + 0xfff,
+		.start = 0x40000000 + CLE_OFF,
+		.end = 0x40000000 + CLE_OFF + SZ_16K - 1,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.name = "nand_data",
-		.start = NAND_IO_DATA,
-		.end = NAND_IO_DATA + 0xfff,
+		.name  = "fsmc_regs",
+		.start = NOMADIK_FSMC_BASE,
+		.end   = NOMADIK_FSMC_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
-	}
+	},
 };
 
-static int nhk8815_nand_init(void)
-{
-	/* FSMC setup for nand chip select (8-bit nand in 8815NHK) */
-	writel(0x0000000E, FSMC_PCR(0));
-	writel(0x000D0A00, FSMC_PMEM(0));
-	writel(0x00100A00, FSMC_PATT(0));
-
-	/* enable access to the chip select area */
-	writel(readl(FSMC_PCR(0)) | 0x04, FSMC_PCR(0));
-
-	return 0;
-}
-
 /*
  * These partitions are the same as those used in the 2.6.20 release
  * shipped by the vendor; the first two partitions are mandated
@@ -111,20 +102,28 @@ static struct mtd_partition nhk8815_partitions[] = {
 	}
 };
 
-static struct nomadik_nand_platform_data nhk8815_nand_data = {
-	.parts		= nhk8815_partitions,
-	.nparts		= ARRAY_SIZE(nhk8815_partitions),
-	.options	= NAND_COPYBACK | NAND_CACHEPRG | NAND_NO_PADDING,
-	.init		= nhk8815_nand_init,
+static struct fsmc_nand_timings nhk8815_nand_timings = {
+	.thiz	= 0,
+	.thold	= 0x10,
+	.twait	= 0x0A,
+	.tset	= 0,
+};
+
+static struct fsmc_nand_platform_data nhk8815_nand_platform_data = {
+	.nand_timings = &nhk8815_nand_timings,
+	.partitions = nhk8815_partitions,
+	.nr_partitions = ARRAY_SIZE(nhk8815_partitions),
+	.width = FSMC_NAND_BW8,
 };
 
 static struct platform_device nhk8815_nand_device = {
-	.name		= "nomadik_nand",
-	.dev		= {
-		.platform_data = &nhk8815_nand_data,
+	.name = "fsmc-nand",
+	.id = -1,
+	.resource = nhk8815_nand_resources,
+	.num_resources = ARRAY_SIZE(nhk8815_nand_resources),
+	.dev = {
+		.platform_data = &nhk8815_nand_platform_data,
 	},
-	.resource	= nhk8815_nand_resources,
-	.num_resources	= ARRAY_SIZE(nhk8815_nand_resources),
 };
 
 /* These are the partitions for the OneNand device, different from above */
@@ -179,6 +178,10 @@ static struct platform_device nhk8815_onenand_device = {
 	.num_resources	= ARRAY_SIZE(nhk8815_onenand_resource),
 };
 
+/* bus control reg. and bus timing reg. for CS0..CS3 */
+#define FSMC_BCR(x)	(NOMADIK_FSMC_VA + (x << 3))
+#define FSMC_BTR(x)	(NOMADIK_FSMC_VA + (x << 3) + 0x04)
+
 static void __init nhk8815_onenand_init(void)
 {
 #ifdef CONFIG_MTD_ONENAND
@@ -261,7 +264,7 @@ static void __init nomadik_timer_init(void)
 	src_cr |= SRC_CR_INIT_VAL;
 	writel(src_cr, io_p2v(NOMADIK_SRC_BASE));
 
-	nmdk_timer_init(io_p2v(NOMADIK_MTU0_BASE));
+	nmdk_timer_init(io_p2v(NOMADIK_MTU0_BASE), IRQ_MTU0);
 }
 
 static struct sys_timer nomadik_timer = {
diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c
index b617eae..1273931 100644
--- a/arch/arm/mach-nomadik/cpu-8815.c
+++ b/arch/arm/mach-nomadik/cpu-8815.c
@@ -26,8 +26,8 @@
 #include <linux/irq.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_data/clk-nomadik.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
-#include <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <asm/mach/map.h>
diff --git a/arch/arm/mach-nomadik/i2c-8815nhk.c b/arch/arm/mach-nomadik/i2c-8815nhk.c
index 6d14454..0c2f662 100644
--- a/arch/arm/mach-nomadik/i2c-8815nhk.c
+++ b/arch/arm/mach-nomadik/i2c-8815nhk.c
@@ -4,8 +4,7 @@
 #include <linux/i2c-algo-bit.h>
 #include <linux/i2c-gpio.h>
 #include <linux/platform_device.h>
-#include <plat/gpio-nomadik.h>
-#include <plat/pincfg.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 /*
  * There are two busses in the 8815NHK.
diff --git a/arch/arm/mach-nomadik/include/mach/fsmc.h b/arch/arm/mach-nomadik/include/mach/fsmc.h
deleted file mode 100644
index 8c2c051..0000000
--- a/arch/arm/mach-nomadik/include/mach/fsmc.h
+++ /dev/null
@@ -1,29 +0,0 @@
-
-/* Definitions for the Nomadik FSMC "Flexible Static Memory controller" */
-
-#ifndef __ASM_ARCH_FSMC_H
-#define __ASM_ARCH_FSMC_H
-
-#include <mach/hardware.h>
-/*
- * Register list
- */
-
-/* bus control reg. and bus timing reg. for CS0..CS3 */
-#define FSMC_BCR(x)     (NOMADIK_FSMC_VA + (x << 3))
-#define FSMC_BTR(x)     (NOMADIK_FSMC_VA + (x << 3) + 0x04)
-
-/* PC-card and NAND:
- * PCR = control register
- * PMEM = memory timing
- * PATT = attribute timing
- * PIO = I/O timing
- * PECCR = ECC result
- */
-#define FSMC_PCR(x)     (NOMADIK_FSMC_VA + ((2 + x) << 5) + 0x00)
-#define FSMC_PMEM(x)    (NOMADIK_FSMC_VA + ((2 + x) << 5) + 0x08)
-#define FSMC_PATT(x)    (NOMADIK_FSMC_VA + ((2 + x) << 5) + 0x0c)
-#define FSMC_PIO(x)     (NOMADIK_FSMC_VA + ((2 + x) << 5) + 0x10)
-#define FSMC_PECCR(x)   (NOMADIK_FSMC_VA + ((2 + x) << 5) + 0x14)
-
-#endif /* __ASM_ARCH_FSMC_H */
diff --git a/arch/arm/mach-nomadik/include/mach/irqs.h b/arch/arm/mach-nomadik/include/mach/irqs.h
index a118e61..b549d05 100644
--- a/arch/arm/mach-nomadik/include/mach/irqs.h
+++ b/arch/arm/mach-nomadik/include/mach/irqs.h
@@ -72,7 +72,7 @@
 #define NOMADIK_NR_GPIO			128 /* last 4 not wired to pins */
 #define NOMADIK_GPIO_TO_IRQ(gpio)	((gpio) + NOMADIK_GPIO_OFFSET)
 #define NOMADIK_IRQ_TO_GPIO(irq)	((irq) - NOMADIK_GPIO_OFFSET)
-#define NR_IRQS				NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO)
+#define NOMADIK_NR_IRQS			NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO)
 
 /* Following two are used by entry_macro.S, to access our dual-vic */
 #define VIC_REG_IRQSR0		0
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index cd169c3..f0e69cb 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -3,7 +3,8 @@
 #
 
 # Common support
-obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o
+obj-y := io.o id.o sram-init.o sram.o time.o irq.o mux.o flash.o \
+	 serial.o devices.o dma.o
 obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o timer.o
 
 ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),)
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index e255164..a8fce3c 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -625,7 +625,6 @@ MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
 	.atag_offset	= 0x100,
 	.map_io		= ams_delta_map_io,
 	.init_early	= omap1_init_early,
-	.reserve	= omap_reserve,
 	.init_irq	= omap1_init_irq,
 	.init_machine	= ams_delta_init,
 	.init_late	= ams_delta_init_late,
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index 4b6de70..560a7dc 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -27,16 +27,16 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/tc.h>
+#include <mach/tc.h>
 #include <mach/mux.h>
 #include <mach/flash.h>
-#include <plat/fpga.h>
 #include <linux/platform_data/keypad-omap.h>
 
 #include <mach/hardware.h>
 
 #include "iomap.h"
 #include "common.h"
+#include "fpga.h"
 
 /* fsample is pretty close to p2-sample */
 
@@ -123,9 +123,9 @@ static struct resource smc91x_resources[] = {
 
 static void __init fsample_init_smc91x(void)
 {
-	fpga_write(1, H2P2_DBG_FPGA_LAN_RESET);
+	__raw_writeb(1, H2P2_DBG_FPGA_LAN_RESET);
 	mdelay(50);
-	fpga_write(fpga_read(H2P2_DBG_FPGA_LAN_RESET) & ~1,
+	__raw_writeb(__raw_readb(H2P2_DBG_FPGA_LAN_RESET) & ~1,
 		   H2P2_DBG_FPGA_LAN_RESET);
 	mdelay(50);
 }
@@ -307,8 +307,7 @@ static void __init omap_fsample_init(void)
 
 	fsample_init_smc91x();
 
-	if (gpio_request(FSAMPLE_NAND_RB_GPIO_PIN, "NAND ready") < 0)
-		BUG();
+	BUG_ON(gpio_request(FSAMPLE_NAND_RB_GPIO_PIN, "NAND ready") < 0);
 	gpio_direction_input(FSAMPLE_NAND_RB_GPIO_PIN);
 
 	omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
@@ -362,7 +361,6 @@ MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
 	.atag_offset	= 0x100,
 	.map_io		= omap_fsample_map_io,
 	.init_early	= omap1_init_early,
-	.reserve	= omap_reserve,
 	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_fsample_init,
 	.init_late	= omap1_init_late,
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index 4ec579f..608e7d2 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -81,7 +81,6 @@ MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
 	.atag_offset	= 0x100,
 	.map_io		= omap16xx_map_io,
 	.init_early	= omap1_init_early,
-	.reserve	= omap_reserve,
 	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_generic_init,
 	.init_late	= omap1_init_late,
diff --git a/arch/arm/mach-omap1/board-h2-mmc.c b/arch/arm/mach-omap1/board-h2-mmc.c
index e1362ce..7119ef2 100644
--- a/arch/arm/mach-omap1/board-h2-mmc.c
+++ b/arch/arm/mach-omap1/board-h2-mmc.c
@@ -13,12 +13,11 @@
  */
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
-
+#include <linux/platform_data/gpio-omap.h>
 #include <linux/i2c/tps65010.h>
 
-#include <plat/mmc.h>
-
 #include "board-h2.h"
+#include "mmc.h"
 
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
 
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 376f7f2..4953cf7 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -39,8 +39,8 @@
 #include <asm/mach/map.h>
 
 #include <mach/mux.h>
-#include <plat/dma.h>
-#include <plat/tc.h>
+#include <plat-omap/dma-omap.h>
+#include <mach/tc.h>
 #include <mach/irda.h>
 #include <linux/platform_data/keypad-omap.h>
 #include <mach/flash.h>
@@ -50,6 +50,7 @@
 
 #include "common.h"
 #include "board-h2.h"
+#include "dma.h"
 
 /* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
 #define OMAP1610_ETHR_START		0x04000300
@@ -411,8 +412,7 @@ static void __init h2_init(void)
 
 	h2_nand_resource.end = h2_nand_resource.start = OMAP_CS2B_PHYS;
 	h2_nand_resource.end += SZ_4K - 1;
-	if (gpio_request(H2_NAND_RB_GPIO_PIN, "NAND ready") < 0)
-		BUG();
+	BUG_ON(gpio_request(H2_NAND_RB_GPIO_PIN, "NAND ready") < 0);
 	gpio_direction_input(H2_NAND_RB_GPIO_PIN);
 
 	omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
@@ -458,7 +458,6 @@ MACHINE_START(OMAP_H2, "TI-H2")
 	.atag_offset	= 0x100,
 	.map_io		= omap16xx_map_io,
 	.init_early     = omap1_init_early,
-	.reserve	= omap_reserve,
 	.init_irq	= omap1_init_irq,
 	.init_machine	= h2_init,
 	.init_late	= omap1_init_late,
diff --git a/arch/arm/mach-omap1/board-h3-mmc.c b/arch/arm/mach-omap1/board-h3-mmc.c
index c74daac..17d7791 100644
--- a/arch/arm/mach-omap1/board-h3-mmc.c
+++ b/arch/arm/mach-omap1/board-h3-mmc.c
@@ -16,9 +16,8 @@
 
 #include <linux/i2c/tps65010.h>
 
-#include <plat/mmc.h>
-
 #include "board-h3.h"
+#include "mmc.h"
 
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
 
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index ededdb7..563ba16 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -41,9 +41,9 @@
 #include <asm/mach/map.h>
 
 #include <mach/mux.h>
-#include <plat/tc.h>
+#include <mach/tc.h>
 #include <linux/platform_data/keypad-omap.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 #include <mach/flash.h>
 
 #include <mach/hardware.h>
@@ -406,8 +406,7 @@ static void __init h3_init(void)
 
 	nand_resource.end = nand_resource.start = OMAP_CS2B_PHYS;
 	nand_resource.end += SZ_4K - 1;
-	if (gpio_request(H3_NAND_RB_GPIO_PIN, "NAND ready") < 0)
-		BUG();
+	BUG_ON(gpio_request(H3_NAND_RB_GPIO_PIN, "NAND ready") < 0);
 	gpio_direction_input(H3_NAND_RB_GPIO_PIN);
 
 	/* GPIO10 Func_MUX_CTRL reg bit 29:27, Configure V2 to mode1 as GPIO */
@@ -452,7 +451,6 @@ MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
 	.atag_offset	= 0x100,
 	.map_io		= omap16xx_map_io,
 	.init_early     = omap1_init_early,
-	.reserve	= omap_reserve,
 	.init_irq	= omap1_init_irq,
 	.init_machine	= h3_init,
 	.init_late	= omap1_init_late,
diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
index 87ab208..356f816 100644
--- a/arch/arm/mach-omap1/board-htcherald.c
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -43,7 +43,7 @@
 #include <asm/mach/arch.h>
 
 #include <mach/omap7xx.h>
-#include <plat/mmc.h>
+#include "mmc.h"
 
 #include <mach/irqs.h>
 #include <mach/usb.h>
@@ -600,7 +600,6 @@ MACHINE_START(HERALD, "HTC Herald")
 	.atag_offset    = 0x100,
 	.map_io         = htcherald_map_io,
 	.init_early     = omap1_init_early,
-	.reserve	= omap_reserve,
 	.init_irq       = omap1_init_irq,
 	.init_machine   = htcherald_init,
 	.init_late	= omap1_init_late,
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index db5f7d2..f8033fa 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -33,16 +33,15 @@
 
 #include <mach/mux.h>
 #include <mach/flash.h>
-#include <plat/fpga.h>
-#include <plat/tc.h>
+#include <mach/tc.h>
 #include <linux/platform_data/keypad-omap.h>
-#include <plat/mmc.h>
 
 #include <mach/hardware.h>
 #include <mach/usb.h>
 
 #include "iomap.h"
 #include "common.h"
+#include "mmc.h"
 
 /* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
 #define INNOVATOR1610_ETHR_START	0x04000300
@@ -215,7 +214,7 @@ static struct platform_device *innovator1510_devices[] __initdata = {
 
 static int innovator_get_pendown_state(void)
 {
-	return !(fpga_read(OMAP1510_FPGA_TOUCHSCREEN) & (1 << 5));
+	return !(__raw_readb(OMAP1510_FPGA_TOUCHSCREEN) & (1 << 5));
 }
 
 static const struct ads7846_platform_data innovator1510_ts_info = {
@@ -279,7 +278,7 @@ static struct platform_device *innovator1610_devices[] __initdata = {
 static void __init innovator_init_smc91x(void)
 {
 	if (cpu_is_omap1510()) {
-		fpga_write(fpga_read(OMAP1510_FPGA_RST) & ~1,
+		__raw_writeb(__raw_readb(OMAP1510_FPGA_RST) & ~1,
 			   OMAP1510_FPGA_RST);
 		udelay(750);
 	} else {
@@ -335,10 +334,10 @@ static int mmc_set_power(struct device *dev, int slot, int power_on,
 				int vdd)
 {
 	if (power_on)
-		fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3),
+		__raw_writeb(__raw_readb(OMAP1510_FPGA_POWER) | (1 << 3),
 				OMAP1510_FPGA_POWER);
 	else
-		fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~(1 << 3),
+		__raw_writeb(__raw_readb(OMAP1510_FPGA_POWER) & ~(1 << 3),
 				OMAP1510_FPGA_POWER);
 
 	return 0;
@@ -390,14 +389,14 @@ static void __init innovator_init(void)
 		omap_cfg_reg(UART3_TX);
 		omap_cfg_reg(UART3_RX);
 
-		reg = fpga_read(OMAP1510_FPGA_POWER);
+		reg = __raw_readb(OMAP1510_FPGA_POWER);
 		reg |= OMAP1510_FPGA_PCR_COM1_EN;
-		fpga_write(reg, OMAP1510_FPGA_POWER);
+		__raw_writeb(reg, OMAP1510_FPGA_POWER);
 		udelay(10);
 
-		reg = fpga_read(OMAP1510_FPGA_POWER);
+		reg = __raw_readb(OMAP1510_FPGA_POWER);
 		reg |= OMAP1510_FPGA_PCR_COM2_EN;
-		fpga_write(reg, OMAP1510_FPGA_POWER);
+		__raw_writeb(reg, OMAP1510_FPGA_POWER);
 		udelay(10);
 
 		platform_add_devices(innovator1510_devices, ARRAY_SIZE(innovator1510_devices));
@@ -437,6 +436,7 @@ static void __init innovator_init(void)
  */
 static void __init innovator_map_io(void)
 {
+#ifdef CONFIG_ARCH_OMAP15XX
 	omap15xx_map_io();
 
 	iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc));
@@ -444,9 +444,10 @@ static void __init innovator_map_io(void)
 
 	/* Dump the Innovator FPGA rev early - useful info for support. */
 	pr_debug("Innovator FPGA Rev %d.%d Board Rev %d\n",
-			fpga_read(OMAP1510_FPGA_REV_HIGH),
-			fpga_read(OMAP1510_FPGA_REV_LOW),
-			fpga_read(OMAP1510_FPGA_BOARD_REV));
+			__raw_readb(OMAP1510_FPGA_REV_HIGH),
+			__raw_readb(OMAP1510_FPGA_REV_LOW),
+			__raw_readb(OMAP1510_FPGA_BOARD_REV));
+#endif
 }
 
 MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
@@ -454,7 +455,6 @@ MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
 	.atag_offset	= 0x100,
 	.map_io		= innovator_map_io,
 	.init_early     = omap1_init_early,
-	.reserve	= omap_reserve,
 	.init_irq	= omap1_init_irq,
 	.init_machine	= innovator_init,
 	.init_late	= omap1_init_late,
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index 7d5c06d..24d2f2d 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -29,13 +29,13 @@
 #include <asm/mach/map.h>
 
 #include <mach/mux.h>
-#include <plat/mmc.h>
-#include <plat/clock.h>
 
 #include <mach/hardware.h>
 #include <mach/usb.h>
 
 #include "common.h"
+#include "clock.h"
+#include "mmc.h"
 
 #define ADS7846_PENDOWN_GPIO	15
 
@@ -112,17 +112,6 @@ static void __init mipid_dev_init(void)
 	omapfb_set_lcd_config(&nokia770_lcd_config);
 }
 
-static void __init ads7846_dev_init(void)
-{
-	if (gpio_request(ADS7846_PENDOWN_GPIO, "ADS7846 pendown") < 0)
-		printk(KERN_ERR "can't get ads7846 pen down GPIO\n");
-}
-
-static int ads7846_get_pendown_state(void)
-{
-	return !gpio_get_value(ADS7846_PENDOWN_GPIO);
-}
-
 static struct ads7846_platform_data nokia770_ads7846_platform_data __initdata = {
 	.x_max		= 0x0fff,
 	.y_max		= 0x0fff,
@@ -131,7 +120,7 @@ static struct ads7846_platform_data nokia770_ads7846_platform_data __initdata =
 	.debounce_max	= 10,
 	.debounce_tol	= 3,
 	.debounce_rep	= 1,
-	.get_pendown_state	= ads7846_get_pendown_state,
+	.gpio_pendown	= ADS7846_PENDOWN_GPIO,
 };
 
 static struct spi_board_info nokia770_spi_board_info[] __initdata = {
@@ -241,7 +230,6 @@ static void __init omap_nokia770_init(void)
 	omap_serial_init();
 	omap_register_i2c_bus(1, 100, NULL, 0);
 	hwa742_dev_init();
-	ads7846_dev_init();
 	mipid_dev_init();
 	omap1_usb_init(&nokia770_usb_config);
 	nokia770_mmc_init();
@@ -251,7 +239,6 @@ MACHINE_START(NOKIA770, "Nokia 770")
 	.atag_offset	= 0x100,
 	.map_io		= omap16xx_map_io,
 	.init_early     = omap1_init_early,
-	.reserve	= omap_reserve,
 	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_nokia770_init,
 	.init_late	= omap1_init_late,
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 5973945..872ea47 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -48,7 +48,7 @@
 
 #include <mach/flash.h>
 #include <mach/mux.h>
-#include <plat/tc.h>
+#include <mach/tc.h>
 
 #include <mach/hardware.h>
 #include <mach/usb.h>
@@ -606,7 +606,6 @@ MACHINE_START(OMAP_OSK, "TI-OSK")
 	.atag_offset	= 0x100,
 	.map_io		= omap16xx_map_io,
 	.init_early	= omap1_init_early,
-	.reserve	= omap_reserve,
 	.init_irq	= omap1_init_irq,
 	.init_machine	= osk_init,
 	.init_late	= omap1_init_late,
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 1c578d5..584b6fa 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -36,8 +36,8 @@
 
 #include <mach/flash.h>
 #include <mach/mux.h>
-#include <plat/tc.h>
-#include <plat/dma.h>
+#include <mach/tc.h>
+#include <plat-omap/dma-omap.h>
 #include <mach/irda.h>
 #include <linux/platform_data/keypad-omap.h>
 
@@ -45,6 +45,7 @@
 #include <mach/usb.h>
 
 #include "common.h"
+#include "dma.h"
 
 #define PALMTE_USBDETECT_GPIO	0
 #define PALMTE_USB_OR_DC_GPIO	1
@@ -264,7 +265,6 @@ MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
 	.atag_offset	= 0x100,
 	.map_io		= omap15xx_map_io,
 	.init_early     = omap1_init_early,
-	.reserve	= omap_reserve,
 	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_palmte_init,
 	.init_late	= omap1_init_late,
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
index 9715809..fbc986b 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -28,16 +28,16 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/platform_data/omap1_bl.h>
+#include <linux/platform_data/leds-omap.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/led.h>
 #include <mach/flash.h>
 #include <mach/mux.h>
-#include <plat/dma.h>
-#include <plat/tc.h>
+#include <plat-omap/dma-omap.h>
+#include <mach/tc.h>
 #include <mach/irda.h>
 #include <linux/platform_data/keypad-omap.h>
 
@@ -45,6 +45,7 @@
 #include <mach/usb.h>
 
 #include "common.h"
+#include "dma.h"
 
 #define PALMTT_USBDETECT_GPIO	0
 #define PALMTT_CABLE_GPIO	1
@@ -310,7 +311,6 @@ MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T")
 	.atag_offset	= 0x100,
 	.map_io		= omap15xx_map_io,
 	.init_early     = omap1_init_early,
-	.reserve	= omap_reserve,
 	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_palmtt_init,
 	.init_late	= omap1_init_late,
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index e311032..60d917a 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -38,8 +38,8 @@
 
 #include <mach/flash.h>
 #include <mach/mux.h>
-#include <plat/dma.h>
-#include <plat/tc.h>
+#include <plat-omap/dma-omap.h>
+#include <mach/tc.h>
 #include <mach/irda.h>
 #include <linux/platform_data/keypad-omap.h>
 
@@ -47,6 +47,7 @@
 #include <mach/usb.h>
 
 #include "common.h"
+#include "dma.h"
 
 #define PALMZ71_USBDETECT_GPIO	0
 #define PALMZ71_PENIRQ_GPIO	6
@@ -326,7 +327,6 @@ MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71")
 	.atag_offset	= 0x100,
 	.map_io		= omap15xx_map_io,
 	.init_early     = omap1_init_early,
-	.reserve	= omap_reserve,
 	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_palmz71_init,
 	.init_late	= omap1_init_late,
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 198b054..27f8d12 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -28,15 +28,15 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/tc.h>
+#include <mach/tc.h>
 #include <mach/mux.h>
-#include <plat/fpga.h>
 #include <mach/flash.h>
 
 #include <mach/hardware.h>
 
 #include "iomap.h"
 #include "common.h"
+#include "fpga.h"
 
 static const unsigned int p2_keymap[] = {
 	KEY(0, 0, KEY_UP),
@@ -231,9 +231,9 @@ static struct omap_lcd_config perseus2_lcd_config __initdata = {
 
 static void __init perseus2_init_smc91x(void)
 {
-	fpga_write(1, H2P2_DBG_FPGA_LAN_RESET);
+	__raw_writeb(1, H2P2_DBG_FPGA_LAN_RESET);
 	mdelay(50);
-	fpga_write(fpga_read(H2P2_DBG_FPGA_LAN_RESET) & ~1,
+	__raw_writeb(__raw_readb(H2P2_DBG_FPGA_LAN_RESET) & ~1,
 		   H2P2_DBG_FPGA_LAN_RESET);
 	mdelay(50);
 }
@@ -275,8 +275,7 @@ static void __init omap_perseus2_init(void)
 
 	perseus2_init_smc91x();
 
-	if (gpio_request(P2_NAND_RB_GPIO_PIN, "NAND ready") < 0)
-		BUG();
+	BUG_ON(gpio_request(P2_NAND_RB_GPIO_PIN, "NAND ready") < 0);
 	gpio_direction_input(P2_NAND_RB_GPIO_PIN);
 
 	omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
@@ -324,7 +323,6 @@ MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
 	.atag_offset	= 0x100,
 	.map_io		= omap_perseus2_map_io,
 	.init_early     = omap1_init_early,
-	.reserve	= omap_reserve,
 	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_perseus2_init,
 	.init_late	= omap1_init_late,
diff --git a/arch/arm/mach-omap1/board-sx1-mmc.c b/arch/arm/mach-omap1/board-sx1-mmc.c
index 5932d56..4fcf19c 100644
--- a/arch/arm/mach-omap1/board-sx1-mmc.c
+++ b/arch/arm/mach-omap1/board-sx1-mmc.c
@@ -16,9 +16,10 @@
 #include <linux/platform_device.h>
 
 #include <mach/hardware.h>
-#include <plat/mmc.h>
 #include <mach/board-sx1.h>
 
+#include "mmc.h"
+
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
 
 static int mmc_set_power(struct device *dev, int slot, int power_on,
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
index 13bf2cc..1ebc7e0 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -36,15 +36,16 @@
 
 #include <mach/flash.h>
 #include <mach/mux.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 #include <mach/irda.h>
-#include <plat/tc.h>
+#include <mach/tc.h>
 #include <mach/board-sx1.h>
 
 #include <mach/hardware.h>
 #include <mach/usb.h>
 
 #include "common.h"
+#include "dma.h"
 
 /* Write to I2C device */
 int sx1_i2c_write_byte(u8 devaddr, u8 regoffset, u8 value)
@@ -403,7 +404,6 @@ MACHINE_START(SX1, "OMAP310 based Siemens SX1")
 	.atag_offset	= 0x100,
 	.map_io		= omap15xx_map_io,
 	.init_early     = omap1_init_early,
-	.reserve	= omap_reserve,
 	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_sx1_init,
 	.init_late	= omap1_init_late,
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index ad75e34..abf705f 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -34,7 +34,7 @@
 #include <mach/board-voiceblue.h>
 #include <mach/flash.h>
 #include <mach/mux.h>
-#include <plat/tc.h>
+#include <mach/tc.h>
 
 #include <mach/hardware.h>
 #include <mach/usb.h>
@@ -286,7 +286,6 @@ MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
 	.atag_offset	= 0x100,
 	.map_io		= omap15xx_map_io,
 	.init_early     = omap1_init_early,
-	.reserve	= omap_reserve,
 	.init_irq	= omap1_init_irq,
 	.init_machine	= voiceblue_init,
 	.init_late	= omap1_init_late,
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index 638f407..4f5fd4a 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -12,6 +12,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/err.h>
@@ -21,21 +22,21 @@
 
 #include <asm/mach-types.h>
 
-#include <plat/cpu.h>
-#include <plat/usb.h>
-#include <plat/clock.h>
-#include <plat/sram.h>
-#include <plat/clkdev_omap.h>
-
 #include <mach/hardware.h>
 
+#include "soc.h"
 #include "iomap.h"
 #include "clock.h"
 #include "opp.h"
+#include "sram.h"
 
 __u32 arm_idlect1_mask;
 struct clk *api_ck_p, *ck_dpll1_p, *ck_ref_p;
 
+static LIST_HEAD(clocks);
+static DEFINE_MUTEX(clocks_mutex);
+static DEFINE_SPINLOCK(clockfw_lock);
+
 /*
  * Omap1 specific clock functions
  */
@@ -607,3 +608,497 @@ void omap1_clk_disable_unused(struct clk *clk)
 }
 
 #endif
+
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret;
+
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+	ret = omap1_clk_enable(clk);
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+	if (clk->usecount == 0) {
+		pr_err("Trying disable clock %s with 0 usecount\n",
+		       clk->name);
+		WARN_ON(1);
+		goto out;
+	}
+
+	omap1_clk_disable(clk);
+
+out:
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	unsigned long flags;
+	unsigned long ret;
+
+	if (clk == NULL || IS_ERR(clk))
+		return 0;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+	ret = clk->rate;
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+/*
+ * Optional clock functions defined in include/linux/clk.h
+ */
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long flags;
+	long ret;
+
+	if (clk == NULL || IS_ERR(clk))
+		return 0;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+	ret = omap1_clk_round_rate(clk, rate);
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	if (clk == NULL || IS_ERR(clk))
+		return ret;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+	ret = omap1_clk_set_rate(clk, rate);
+	if (ret == 0)
+		propagate_rate(clk);
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	WARN_ONCE(1, "clk_set_parent() not implemented for OMAP1\n");
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	return clk->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+/*
+ * OMAP specific clock functions shared between omap1 and omap2
+ */
+
+int __initdata mpurate;
+
+/*
+ * By default we use the rate set by the bootloader.
+ * You can override this with mpurate= cmdline option.
+ */
+static int __init omap_clk_setup(char *str)
+{
+	get_option(&str, &mpurate);
+
+	if (!mpurate)
+		return 1;
+
+	if (mpurate < 1000)
+		mpurate *= 1000000;
+
+	return 1;
+}
+__setup("mpurate=", omap_clk_setup);
+
+/* Used for clocks that always have same value as the parent clock */
+unsigned long followparent_recalc(struct clk *clk)
+{
+	return clk->parent->rate;
+}
+
+/*
+ * Used for clocks that have the same value as the parent clock,
+ * divided by some factor
+ */
+unsigned long omap_fixed_divisor_recalc(struct clk *clk)
+{
+	WARN_ON(!clk->fixed_div);
+
+	return clk->parent->rate / clk->fixed_div;
+}
+
+void clk_reparent(struct clk *child, struct clk *parent)
+{
+	list_del_init(&child->sibling);
+	if (parent)
+		list_add(&child->sibling, &parent->children);
+	child->parent = parent;
+
+	/* now do the debugfs renaming to reattach the child
+	   to the proper parent */
+}
+
+/* Propagate rate to children */
+void propagate_rate(struct clk *tclk)
+{
+	struct clk *clkp;
+
+	list_for_each_entry(clkp, &tclk->children, sibling) {
+		if (clkp->recalc)
+			clkp->rate = clkp->recalc(clkp);
+		propagate_rate(clkp);
+	}
+}
+
+static LIST_HEAD(root_clks);
+
+/**
+ * recalculate_root_clocks - recalculate and propagate all root clocks
+ *
+ * Recalculates all root clocks (clocks with no parent), which if the
+ * clock's .recalc is set correctly, should also propagate their rates.
+ * Called at init.
+ */
+void recalculate_root_clocks(void)
+{
+	struct clk *clkp;
+
+	list_for_each_entry(clkp, &root_clks, sibling) {
+		if (clkp->recalc)
+			clkp->rate = clkp->recalc(clkp);
+		propagate_rate(clkp);
+	}
+}
+
+/**
+ * clk_preinit - initialize any fields in the struct clk before clk init
+ * @clk: struct clk * to initialize
+ *
+ * Initialize any struct clk fields needed before normal clk initialization
+ * can run.  No return value.
+ */
+void clk_preinit(struct clk *clk)
+{
+	INIT_LIST_HEAD(&clk->children);
+}
+
+int clk_register(struct clk *clk)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	/*
+	 * trap out already registered clocks
+	 */
+	if (clk->node.next || clk->node.prev)
+		return 0;
+
+	mutex_lock(&clocks_mutex);
+	if (clk->parent)
+		list_add(&clk->sibling, &clk->parent->children);
+	else
+		list_add(&clk->sibling, &root_clks);
+
+	list_add(&clk->node, &clocks);
+	if (clk->init)
+		clk->init(clk);
+	mutex_unlock(&clocks_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
+	mutex_lock(&clocks_mutex);
+	list_del(&clk->sibling);
+	list_del(&clk->node);
+	mutex_unlock(&clocks_mutex);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+void clk_enable_init_clocks(void)
+{
+	struct clk *clkp;
+
+	list_for_each_entry(clkp, &clocks, node)
+		if (clkp->flags & ENABLE_ON_INIT)
+			clk_enable(clkp);
+}
+
+/**
+ * omap_clk_get_by_name - locate OMAP struct clk by its name
+ * @name: name of the struct clk to locate
+ *
+ * Locate an OMAP struct clk by its name.  Assumes that struct clk
+ * names are unique.  Returns NULL if not found or a pointer to the
+ * struct clk if found.
+ */
+struct clk *omap_clk_get_by_name(const char *name)
+{
+	struct clk *c;
+	struct clk *ret = NULL;
+
+	mutex_lock(&clocks_mutex);
+
+	list_for_each_entry(c, &clocks, node) {
+		if (!strcmp(c->name, name)) {
+			ret = c;
+			break;
+		}
+	}
+
+	mutex_unlock(&clocks_mutex);
+
+	return ret;
+}
+
+int omap_clk_enable_autoidle_all(void)
+{
+	struct clk *c;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+
+	list_for_each_entry(c, &clocks, node)
+		if (c->ops->allow_idle)
+			c->ops->allow_idle(c);
+
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+
+	return 0;
+}
+
+int omap_clk_disable_autoidle_all(void)
+{
+	struct clk *c;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+
+	list_for_each_entry(c, &clocks, node)
+		if (c->ops->deny_idle)
+			c->ops->deny_idle(c);
+
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+
+	return 0;
+}
+
+/*
+ * Low level helpers
+ */
+static int clkll_enable_null(struct clk *clk)
+{
+	return 0;
+}
+
+static void clkll_disable_null(struct clk *clk)
+{
+}
+
+const struct clkops clkops_null = {
+	.enable		= clkll_enable_null,
+	.disable	= clkll_disable_null,
+};
+
+/*
+ * Dummy clock
+ *
+ * Used for clock aliases that are needed on some OMAPs, but not others
+ */
+struct clk dummy_ck = {
+	.name	= "dummy",
+	.ops	= &clkops_null,
+};
+
+/*
+ *
+ */
+
+#ifdef CONFIG_OMAP_RESET_CLOCKS
+/*
+ * Disable any unused clocks left on by the bootloader
+ */
+static int __init clk_disable_unused(void)
+{
+	struct clk *ck;
+	unsigned long flags;
+
+	pr_info("clock: disabling unused clocks to save power\n");
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+	list_for_each_entry(ck, &clocks, node) {
+		if (ck->ops == &clkops_null)
+			continue;
+
+		if (ck->usecount > 0 || !ck->enable_reg)
+			continue;
+
+		omap1_clk_disable_unused(ck);
+	}
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+
+	return 0;
+}
+late_initcall(clk_disable_unused);
+late_initcall(omap_clk_enable_autoidle_all);
+#endif
+
+#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
+/*
+ *	debugfs support to trace clock tree hierarchy and attributes
+ */
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+static struct dentry *clk_debugfs_root;
+
+static int clk_dbg_show_summary(struct seq_file *s, void *unused)
+{
+	struct clk *c;
+	struct clk *pa;
+
+	mutex_lock(&clocks_mutex);
+	seq_printf(s, "%-30s %-30s %-10s %s\n",
+		   "clock-name", "parent-name", "rate", "use-count");
+
+	list_for_each_entry(c, &clocks, node) {
+		pa = c->parent;
+		seq_printf(s, "%-30s %-30s %-10lu %d\n",
+			   c->name, pa ? pa->name : "none", c->rate,
+			   c->usecount);
+	}
+	mutex_unlock(&clocks_mutex);
+
+	return 0;
+}
+
+static int clk_dbg_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, clk_dbg_show_summary, inode->i_private);
+}
+
+static const struct file_operations debug_clock_fops = {
+	.open           = clk_dbg_open,
+	.read           = seq_read,
+	.llseek         = seq_lseek,
+	.release        = single_release,
+};
+
+static int clk_debugfs_register_one(struct clk *c)
+{
+	int err;
+	struct dentry *d;
+	struct clk *pa = c->parent;
+
+	d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root);
+	if (!d)
+		return -ENOMEM;
+	c->dent = d;
+
+	d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount);
+	if (!d) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+	d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
+	if (!d) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+	d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
+	if (!d) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+	return 0;
+
+err_out:
+	debugfs_remove_recursive(c->dent);
+	return err;
+}
+
+static int clk_debugfs_register(struct clk *c)
+{
+	int err;
+	struct clk *pa = c->parent;
+
+	if (pa && !pa->dent) {
+		err = clk_debugfs_register(pa);
+		if (err)
+			return err;
+	}
+
+	if (!c->dent) {
+		err = clk_debugfs_register_one(c);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+static int __init clk_debugfs_init(void)
+{
+	struct clk *c;
+	struct dentry *d;
+	int err;
+
+	d = debugfs_create_dir("clock", NULL);
+	if (!d)
+		return -ENOMEM;
+	clk_debugfs_root = d;
+
+	list_for_each_entry(c, &clocks, node) {
+		err = clk_debugfs_register(c);
+		if (err)
+			goto err_out;
+	}
+
+	d = debugfs_create_file("summary", S_IRUGO,
+		d, NULL, &debug_clock_fops);
+	if (!d)
+		return -ENOMEM;
+
+	return 0;
+err_out:
+	debugfs_remove_recursive(clk_debugfs_root);
+	return err;
+}
+late_initcall(clk_debugfs_init);
+
+#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index 3d04f4f..1e4918a 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -14,8 +14,184 @@
 #define __ARCH_ARM_MACH_OMAP1_CLOCK_H
 
 #include <linux/clk.h>
+#include <linux/list.h>
 
-#include <plat/clock.h>
+#include <linux/clkdev.h>
+
+struct module;
+struct clk;
+
+struct omap_clk {
+	u16				cpu;
+	struct clk_lookup		lk;
+};
+
+#define CLK(dev, con, ck, cp)		\
+	{				\
+		 .cpu = cp,		\
+		.lk = {			\
+			.dev_id = dev,	\
+			.con_id = con,	\
+			.clk = ck,	\
+		},			\
+	}
+
+/* Platform flags for the clkdev-OMAP integration code */
+#define CK_310		(1 << 0)
+#define CK_7XX		(1 << 1)	/* 7xx, 850 */
+#define CK_1510		(1 << 2)
+#define CK_16XX		(1 << 3)	/* 16xx, 17xx, 5912 */
+#define CK_1710		(1 << 4)	/* 1710 extra for rate selection */
+
+
+/* Temporary, needed during the common clock framework conversion */
+#define __clk_get_name(clk)	(clk->name)
+#define __clk_get_parent(clk)	(clk->parent)
+#define __clk_get_rate(clk)	(clk->rate)
+
+/**
+ * struct clkops - some clock function pointers
+ * @enable: fn ptr that enables the current clock in hardware
+ * @disable: fn ptr that enables the current clock in hardware
+ * @find_idlest: function returning the IDLEST register for the clock's IP blk
+ * @find_companion: function returning the "companion" clk reg for the clock
+ * @allow_idle: fn ptr that enables autoidle for the current clock in hardware
+ * @deny_idle: fn ptr that disables autoidle for the current clock in hardware
+ *
+ * A "companion" clk is an accompanying clock to the one being queried
+ * that must be enabled for the IP module connected to the clock to
+ * become accessible by the hardware.  Neither @find_idlest nor
+ * @find_companion should be needed; that information is IP
+ * block-specific; the hwmod code has been created to handle this, but
+ * until hwmod data is ready and drivers have been converted to use PM
+ * runtime calls in place of clk_enable()/clk_disable(), @find_idlest and
+ * @find_companion must, unfortunately, remain.
+ */
+struct clkops {
+	int			(*enable)(struct clk *);
+	void			(*disable)(struct clk *);
+	void			(*find_idlest)(struct clk *, void __iomem **,
+					       u8 *, u8 *);
+	void			(*find_companion)(struct clk *, void __iomem **,
+						  u8 *);
+	void			(*allow_idle)(struct clk *);
+	void			(*deny_idle)(struct clk *);
+};
+
+/*
+ * struct clk.flags possibilities
+ *
+ * XXX document the rest of the clock flags here
+ *
+ * CLOCK_CLKOUTX2: (OMAP4 only) DPLL CLKOUT and CLKOUTX2 GATE_CTRL
+ *     bits share the same register.  This flag allows the
+ *     omap4_dpllmx*() code to determine which GATE_CTRL bit field
+ *     should be used.  This is a temporary solution - a better approach
+ *     would be to associate clock type-specific data with the clock,
+ *     similar to the struct dpll_data approach.
+ */
+#define ENABLE_REG_32BIT	(1 << 0)	/* Use 32-bit access */
+#define CLOCK_IDLE_CONTROL	(1 << 1)
+#define CLOCK_NO_IDLE_PARENT	(1 << 2)
+#define ENABLE_ON_INIT		(1 << 3)	/* Enable upon framework init */
+#define INVERT_ENABLE		(1 << 4)	/* 0 enables, 1 disables */
+#define CLOCK_CLKOUTX2		(1 << 5)
+
+/**
+ * struct clk - OMAP struct clk
+ * @node: list_head connecting this clock into the full clock list
+ * @ops: struct clkops * for this clock
+ * @name: the name of the clock in the hardware (used in hwmod data and debug)
+ * @parent: pointer to this clock's parent struct clk
+ * @children: list_head connecting to the child clks' @sibling list_heads
+ * @sibling: list_head connecting this clk to its parent clk's @children
+ * @rate: current clock rate
+ * @enable_reg: register to write to enable the clock (see @enable_bit)
+ * @recalc: fn ptr that returns the clock's current rate
+ * @set_rate: fn ptr that can change the clock's current rate
+ * @round_rate: fn ptr that can round the clock's current rate
+ * @init: fn ptr to do clock-specific initialization
+ * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
+ * @usecount: number of users that have requested this clock to be enabled
+ * @fixed_div: when > 0, this clock's rate is its parent's rate / @fixed_div
+ * @flags: see "struct clk.flags possibilities" above
+ * @rate_offset: bitshift for rate selection bitfield (OMAP1 only)
+ * @src_offset: bitshift for source selection bitfield (OMAP1 only)
+ *
+ * XXX @rate_offset, @src_offset should probably be removed and OMAP1
+ * clock code converted to use clksel.
+ *
+ * XXX @usecount is poorly named.  It should be "enable_count" or
+ * something similar.  "users" in the description refers to kernel
+ * code (core code or drivers) that have called clk_enable() and not
+ * yet called clk_disable(); the usecount of parent clocks is also
+ * incremented by the clock code when clk_enable() is called on child
+ * clocks and decremented by the clock code when clk_disable() is
+ * called on child clocks.
+ *
+ * XXX @clkdm, @usecount, @children, @sibling should be marked for
+ * internal use only.
+ *
+ * @children and @sibling are used to optimize parent-to-child clock
+ * tree traversals.  (child-to-parent traversals use @parent.)
+ *
+ * XXX The notion of the clock's current rate probably needs to be
+ * separated from the clock's target rate.
+ */
+struct clk {
+	struct list_head	node;
+	const struct clkops	*ops;
+	const char		*name;
+	struct clk		*parent;
+	struct list_head	children;
+	struct list_head	sibling;	/* node for children */
+	unsigned long		rate;
+	void __iomem		*enable_reg;
+	unsigned long		(*recalc)(struct clk *);
+	int			(*set_rate)(struct clk *, unsigned long);
+	long			(*round_rate)(struct clk *, unsigned long);
+	void			(*init)(struct clk *);
+	u8			enable_bit;
+	s8			usecount;
+	u8			fixed_div;
+	u8			flags;
+	u8			rate_offset;
+	u8			src_offset;
+#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
+	struct dentry		*dent;	/* For visible tree hierarchy */
+#endif
+};
+
+struct clk_functions {
+	int		(*clk_enable)(struct clk *clk);
+	void		(*clk_disable)(struct clk *clk);
+	long		(*clk_round_rate)(struct clk *clk, unsigned long rate);
+	int		(*clk_set_rate)(struct clk *clk, unsigned long rate);
+	int		(*clk_set_parent)(struct clk *clk, struct clk *parent);
+	void		(*clk_allow_idle)(struct clk *clk);
+	void		(*clk_deny_idle)(struct clk *clk);
+	void		(*clk_disable_unused)(struct clk *clk);
+};
+
+extern int mpurate;
+
+extern int clk_init(struct clk_functions *custom_clocks);
+extern void clk_preinit(struct clk *clk);
+extern int clk_register(struct clk *clk);
+extern void clk_reparent(struct clk *child, struct clk *parent);
+extern void clk_unregister(struct clk *clk);
+extern void propagate_rate(struct clk *clk);
+extern void recalculate_root_clocks(void);
+extern unsigned long followparent_recalc(struct clk *clk);
+extern void clk_enable_init_clocks(void);
+unsigned long omap_fixed_divisor_recalc(struct clk *clk);
+extern struct clk *omap_clk_get_by_name(const char *name);
+extern int omap_clk_enable_autoidle_all(void);
+extern int omap_clk_disable_autoidle_all(void);
+
+extern const struct clkops clkops_null;
+
+extern struct clk dummy_ck;
 
 int omap1_clk_init(void);
 void omap1_clk_late_init(void);
diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c
index 9b45f4b..cb7c6ae 100644
--- a/arch/arm/mach-omap1/clock_data.c
+++ b/arch/arm/mach-omap1/clock_data.c
@@ -22,16 +22,14 @@
 
 #include <asm/mach-types.h>  /* for machine_is_* */
 
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/clkdev_omap.h>
-#include <plat/sram.h>	/* for omap_sram_reprogram_clock() */
+#include "soc.h"
 
 #include <mach/hardware.h>
 #include <mach/usb.h>   /* for OTG_BASE */
 
 #include "iomap.h"
 #include "clock.h"
+#include "sram.h"
 
 /* Some ARM_IDLECT1 bit shifts - used in struct arm_idlect1_clk */
 #define IDL_CLKOUT_ARM_SHIFT			12
@@ -765,14 +763,6 @@ static struct omap_clk omap_clks[] = {
  * init
  */
 
-static struct clk_functions omap1_clk_functions = {
-	.clk_enable		= omap1_clk_enable,
-	.clk_disable		= omap1_clk_disable,
-	.clk_round_rate		= omap1_clk_round_rate,
-	.clk_set_rate		= omap1_clk_set_rate,
-	.clk_disable_unused	= omap1_clk_disable_unused,
-};
-
 static void __init omap1_show_rates(void)
 {
 	pr_notice("Clocking rate (xtal/DPLL1/MPU): %ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
@@ -803,8 +793,6 @@ int __init omap1_clk_init(void)
 	if (!cpu_is_omap15xx())
 		omap_writew(0, SOFT_REQ_REG2);
 
-	clk_init(&omap1_clk_functions);
-
 	/* By default all idlect1 clocks are allowed to idle */
 	arm_idlect1_mask = ~0;
 
diff --git a/arch/arm/mach-omap1/common.h b/arch/arm/mach-omap1/common.h
index c2552b2..b53e085 100644
--- a/arch/arm/mach-omap1/common.h
+++ b/arch/arm/mach-omap1/common.h
@@ -26,8 +26,10 @@
 #ifndef __ARCH_ARM_MACH_OMAP1_COMMON_H
 #define __ARCH_ARM_MACH_OMAP1_COMMON_H
 
-#include <plat/common.h>
 #include <linux/mtd/mtd.h>
+#include <linux/i2c-omap.h>
+
+#include <plat/i2c.h>
 
 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
 void omap7xx_map_io(void);
@@ -38,6 +40,7 @@ static inline void omap7xx_map_io(void)
 #endif
 
 #ifdef CONFIG_ARCH_OMAP15XX
+void omap1510_fpga_init_irq(void);
 void omap15xx_map_io(void);
 #else
 static inline void omap15xx_map_io(void)
@@ -90,4 +93,6 @@ extern int ocpi_enable(void);
 static inline int ocpi_enable(void) { return 0; }
 #endif
 
+extern u32 omap1_get_reset_sources(void);
+
 #endif /* __ARCH_ARM_MACH_OMAP1_COMMON_H */
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index d3fec92..0af6352 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -17,12 +17,12 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 
+#include <linux/platform_data/omap-wd-timer.h>
+
 #include <asm/mach/map.h>
 
-#include <plat/tc.h>
+#include <mach/tc.h>
 #include <mach/mux.h>
-#include <plat/dma.h>
-#include <plat/mmc.h>
 
 #include <mach/omap7xx.h>
 #include <mach/camera.h>
@@ -30,6 +30,9 @@
 
 #include "common.h"
 #include "clock.h"
+#include "dma.h"
+#include "mmc.h"
+#include "sram.h"
 
 #if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE)
 
@@ -175,6 +178,13 @@ static int __init omap_mmc_add(const char *name, int id, unsigned long base,
 	res[3].name = "tx";
 	res[3].flags = IORESOURCE_DMA;
 
+	if (cpu_is_omap7xx())
+		data->slots[0].features = MMC_OMAP7XX;
+	if (cpu_is_omap15xx())
+		data->slots[0].features = MMC_OMAP15XX;
+	if (cpu_is_omap16xx())
+		data->slots[0].features = MMC_OMAP16XX;
+
 	ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
 	if (ret == 0)
 		ret = platform_device_add_data(pdev, data, sizeof(*data));
@@ -439,18 +449,31 @@ static struct resource wdt_resources[] = {
 };
 
 static struct platform_device omap_wdt_device = {
-	.name	   = "omap_wdt",
-	.id	     = -1,
+	.name		= "omap_wdt",
+	.id		= -1,
 	.num_resources	= ARRAY_SIZE(wdt_resources),
 	.resource	= wdt_resources,
 };
 
 static int __init omap_init_wdt(void)
 {
+	struct omap_wd_timer_platform_data pdata;
+	int ret;
+
 	if (!cpu_is_omap16xx())
 		return -ENODEV;
 
-	return platform_device_register(&omap_wdt_device);
+	pdata.read_reset_sources = omap1_get_reset_sources;
+
+	ret = platform_device_register(&omap_wdt_device);
+	if (!ret) {
+		ret = platform_device_add_data(&omap_wdt_device, &pdata,
+					       sizeof(pdata));
+		if (ret)
+			platform_device_del(&omap_wdt_device);
+	}
+
+	return ret;
 }
 subsys_initcall(omap_init_wdt);
 #endif
diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index 29007fe..978aed8 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -25,11 +25,13 @@
 #include <linux/device.h>
 #include <linux/io.h>
 
-#include <plat/dma.h>
-#include <plat/tc.h>
+#include <plat-omap/dma-omap.h>
+#include <mach/tc.h>
 
 #include <mach/irqs.h>
 
+#include "dma.h"
+
 #define OMAP1_DMA_BASE			(0xfffed800)
 #define OMAP1_LOGICAL_DMA_CH_COUNT	17
 #define OMAP1_DMA_STRIDE		0x40
@@ -319,6 +321,9 @@ static int __init omap1_system_dma_init(void)
 		d->dev_caps = ENABLE_1510_MODE;
 	enable_1510_mode = d->dev_caps & ENABLE_1510_MODE;
 
+	if (cpu_is_omap16xx())
+		d->dev_caps = ENABLE_16XX_MODE;
+
 	d->dev_caps		|= SRC_PORT;
 	d->dev_caps		|= DST_PORT;
 	d->dev_caps		|= SRC_INDEX;
diff --git a/arch/arm/mach-omap1/dma.h b/arch/arm/mach-omap1/dma.h
new file mode 100644
index 0000000..da6345d
--- /dev/null
+++ b/arch/arm/mach-omap1/dma.h
@@ -0,0 +1,83 @@
+/*
+ *  OMAP1 DMA channel definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 __OMAP1_DMA_CHANNEL_H
+#define __OMAP1_DMA_CHANNEL_H
+
+/* DMA channels for omap1 */
+#define OMAP_DMA_NO_DEVICE		0
+#define OMAP_DMA_MCSI1_TX		1
+#define OMAP_DMA_MCSI1_RX		2
+#define OMAP_DMA_I2C_RX			3
+#define OMAP_DMA_I2C_TX			4
+#define OMAP_DMA_EXT_NDMA_REQ		5
+#define OMAP_DMA_EXT_NDMA_REQ2		6
+#define OMAP_DMA_UWIRE_TX		7
+#define OMAP_DMA_MCBSP1_TX		8
+#define OMAP_DMA_MCBSP1_RX		9
+#define OMAP_DMA_MCBSP3_TX		10
+#define OMAP_DMA_MCBSP3_RX		11
+#define OMAP_DMA_UART1_TX		12
+#define OMAP_DMA_UART1_RX		13
+#define OMAP_DMA_UART2_TX		14
+#define OMAP_DMA_UART2_RX		15
+#define OMAP_DMA_MCBSP2_TX		16
+#define OMAP_DMA_MCBSP2_RX		17
+#define OMAP_DMA_UART3_TX		18
+#define OMAP_DMA_UART3_RX		19
+#define OMAP_DMA_CAMERA_IF_RX		20
+#define OMAP_DMA_MMC_TX			21
+#define OMAP_DMA_MMC_RX			22
+#define OMAP_DMA_NAND			23
+#define OMAP_DMA_IRQ_LCD_LINE		24
+#define OMAP_DMA_MEMORY_STICK		25
+#define OMAP_DMA_USB_W2FC_RX0		26
+#define OMAP_DMA_USB_W2FC_RX1		27
+#define OMAP_DMA_USB_W2FC_RX2		28
+#define OMAP_DMA_USB_W2FC_TX0		29
+#define OMAP_DMA_USB_W2FC_TX1		30
+#define OMAP_DMA_USB_W2FC_TX2		31
+
+/* These are only for 1610 */
+#define OMAP_DMA_CRYPTO_DES_IN		32
+#define OMAP_DMA_SPI_TX			33
+#define OMAP_DMA_SPI_RX			34
+#define OMAP_DMA_CRYPTO_HASH		35
+#define OMAP_DMA_CCP_ATTN		36
+#define OMAP_DMA_CCP_FIFO_NOT_EMPTY	37
+#define OMAP_DMA_CMT_APE_TX_CHAN_0	38
+#define OMAP_DMA_CMT_APE_RV_CHAN_0	39
+#define OMAP_DMA_CMT_APE_TX_CHAN_1	40
+#define OMAP_DMA_CMT_APE_RV_CHAN_1	41
+#define OMAP_DMA_CMT_APE_TX_CHAN_2	42
+#define OMAP_DMA_CMT_APE_RV_CHAN_2	43
+#define OMAP_DMA_CMT_APE_TX_CHAN_3	44
+#define OMAP_DMA_CMT_APE_RV_CHAN_3	45
+#define OMAP_DMA_CMT_APE_TX_CHAN_4	46
+#define OMAP_DMA_CMT_APE_RV_CHAN_4	47
+#define OMAP_DMA_CMT_APE_TX_CHAN_5	48
+#define OMAP_DMA_CMT_APE_RV_CHAN_5	49
+#define OMAP_DMA_CMT_APE_TX_CHAN_6	50
+#define OMAP_DMA_CMT_APE_RV_CHAN_6	51
+#define OMAP_DMA_CMT_APE_TX_CHAN_7	52
+#define OMAP_DMA_CMT_APE_RV_CHAN_7	53
+#define OMAP_DMA_MMC2_TX		54
+#define OMAP_DMA_MMC2_RX		55
+#define OMAP_DMA_CRYPTO_DES_OUT		56
+
+#endif /* __OMAP1_DMA_CHANNEL_H */
diff --git a/arch/arm/mach-omap1/flash.c b/arch/arm/mach-omap1/flash.c
index 73ae616..b3fb531 100644
--- a/arch/arm/mach-omap1/flash.c
+++ b/arch/arm/mach-omap1/flash.c
@@ -10,7 +10,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 
-#include <plat/tc.h>
+#include <mach/tc.h>
 #include <mach/flash.h>
 
 #include <mach/hardware.h>
diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c
index 29ec50f..8bd71b2 100644
--- a/arch/arm/mach-omap1/fpga.c
+++ b/arch/arm/mach-omap1/fpga.c
@@ -27,11 +27,11 @@
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 
-#include <plat/fpga.h>
-
 #include <mach/hardware.h>
 
 #include "iomap.h"
+#include "common.h"
+#include "fpga.h"
 
 static void fpga_mask_irq(struct irq_data *d)
 {
diff --git a/arch/arm/mach-omap1/fpga.h b/arch/arm/mach-omap1/fpga.h
new file mode 100644
index 0000000..4b4307a
--- /dev/null
+++ b/arch/arm/mach-omap1/fpga.h
@@ -0,0 +1,52 @@
+/*
+ * Interrupt handler for OMAP-1510 FPGA
+ *
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Author: Greg Lonnon <glonnon@ridgerun.com>
+ *
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ *
+ * Separated FPGA interrupts from innovator1510.c and cleaned up for 2.6
+ * Copyright (C) 2004 Nokia Corporation by Tony Lindrgen <tony@atomide.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_OMAP_FPGA_H
+#define __ASM_ARCH_OMAP_FPGA_H
+
+/*
+ * ---------------------------------------------------------------------------
+ *  H2/P2 Debug board FPGA
+ * ---------------------------------------------------------------------------
+ */
+/* maps in the FPGA registers and the ETHR registers */
+#define H2P2_DBG_FPGA_BASE		0xE8000000		/* VA */
+#define H2P2_DBG_FPGA_SIZE		SZ_4K			/* SIZE */
+#define H2P2_DBG_FPGA_START		0x04000000		/* PA */
+
+#define H2P2_DBG_FPGA_ETHR_START	(H2P2_DBG_FPGA_START + 0x300)
+#define H2P2_DBG_FPGA_FPGA_REV		IOMEM(H2P2_DBG_FPGA_BASE + 0x10)	/* FPGA Revision */
+#define H2P2_DBG_FPGA_BOARD_REV		IOMEM(H2P2_DBG_FPGA_BASE + 0x12)	/* Board Revision */
+#define H2P2_DBG_FPGA_GPIO		IOMEM(H2P2_DBG_FPGA_BASE + 0x14)	/* GPIO outputs */
+#define H2P2_DBG_FPGA_LEDS		IOMEM(H2P2_DBG_FPGA_BASE + 0x16)	/* LEDs outputs */
+#define H2P2_DBG_FPGA_MISC_INPUTS	IOMEM(H2P2_DBG_FPGA_BASE + 0x18)	/* Misc inputs */
+#define H2P2_DBG_FPGA_LAN_STATUS	IOMEM(H2P2_DBG_FPGA_BASE + 0x1A)	/* LAN Status line */
+#define H2P2_DBG_FPGA_LAN_RESET		IOMEM(H2P2_DBG_FPGA_BASE + 0x1C)	/* LAN Reset line */
+
+/* LEDs definition on debug board (16 LEDs, all physically green) */
+#define H2P2_DBG_FPGA_LED_GREEN		(1 << 15)
+#define H2P2_DBG_FPGA_LED_AMBER		(1 << 14)
+#define H2P2_DBG_FPGA_LED_RED		(1 << 13)
+#define H2P2_DBG_FPGA_LED_BLUE		(1 << 12)
+/*  cpu0 load-meter LEDs */
+#define H2P2_DBG_FPGA_LOAD_METER	(1 << 0)	// A bit of fun on our board ...
+#define H2P2_DBG_FPGA_LOAD_METER_SIZE	11
+#define H2P2_DBG_FPGA_LOAD_METER_MASK	((1 << H2P2_DBG_FPGA_LOAD_METER_SIZE) - 1)
+
+#define H2P2_DBG_FPGA_P2_LED_TIMER		(1 << 0)
+#define H2P2_DBG_FPGA_P2_LED_IDLE		(1 << 1)
+
+#endif
diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c
index 98e6f39..02b3eb2 100644
--- a/arch/arm/mach-omap1/gpio15xx.c
+++ b/arch/arm/mach-omap1/gpio15xx.c
@@ -19,6 +19,8 @@
 #include <linux/gpio.h>
 #include <linux/platform_data/gpio-omap.h>
 
+#include <mach/irqs.h>
+
 #define OMAP1_MPUIO_VBASE		OMAP1_MPUIO_BASE
 #define OMAP1510_GPIO_BASE		0xFFFCE000
 
diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c
index 33f4192..b9952a2 100644
--- a/arch/arm/mach-omap1/gpio16xx.c
+++ b/arch/arm/mach-omap1/gpio16xx.c
@@ -19,6 +19,8 @@
 #include <linux/gpio.h>
 #include <linux/platform_data/gpio-omap.h>
 
+#include <mach/irqs.h>
+
 #define OMAP1610_GPIO1_BASE		0xfffbe400
 #define OMAP1610_GPIO2_BASE		0xfffbec00
 #define OMAP1610_GPIO3_BASE		0xfffbb400
diff --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c
index 958ce9a..f5819b2 100644
--- a/arch/arm/mach-omap1/gpio7xx.c
+++ b/arch/arm/mach-omap1/gpio7xx.c
@@ -19,6 +19,8 @@
 #include <linux/gpio.h>
 #include <linux/platform_data/gpio-omap.h>
 
+#include <mach/irqs.h>
+
 #define OMAP7XX_GPIO1_BASE		0xfffbc000
 #define OMAP7XX_GPIO2_BASE		0xfffbc800
 #define OMAP7XX_GPIO3_BASE		0xfffbd000
diff --git a/arch/arm/mach-omap1/i2c.c b/arch/arm/mach-omap1/i2c.c
index a0551a6..faca808 100644
--- a/arch/arm/mach-omap1/i2c.c
+++ b/arch/arm/mach-omap1/i2c.c
@@ -19,11 +19,25 @@
  *
  */
 
-#include <plat/i2c.h>
+#include <linux/i2c-omap.h>
 #include <mach/mux.h>
-#include <plat/cpu.h>
+#include "soc.h"
+
+#include <plat/i2c.h>
+
+#define OMAP_I2C_SIZE		0x3f
+#define OMAP1_I2C_BASE		0xfffb3800
+#define OMAP1_INT_I2C		(32 + 4)
+
+static const char name[] = "omap_i2c";
 
-void __init omap1_i2c_mux_pins(int bus_id)
+static struct resource i2c_resources[2] = {
+};
+
+static struct platform_device omap_i2c_devices[1] = {
+};
+
+static void __init omap1_i2c_mux_pins(int bus_id)
 {
 	if (cpu_is_omap7xx()) {
 		omap_cfg_reg(I2C_7XX_SDA);
@@ -33,3 +47,47 @@ void __init omap1_i2c_mux_pins(int bus_id)
 		omap_cfg_reg(I2C_SCL);
 	}
 }
+
+int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *pdata,
+				int bus_id)
+{
+	struct platform_device *pdev;
+	struct resource *res;
+
+	if (bus_id > 1)
+		return -EINVAL;
+
+	omap1_i2c_mux_pins(bus_id);
+
+	pdev = &omap_i2c_devices[bus_id - 1];
+	pdev->id = bus_id;
+	pdev->name = name;
+	pdev->num_resources = ARRAY_SIZE(i2c_resources);
+	res = i2c_resources;
+	res[0].start = OMAP1_I2C_BASE;
+	res[0].end = res[0].start + OMAP_I2C_SIZE;
+	res[0].flags = IORESOURCE_MEM;
+	res[1].start = OMAP1_INT_I2C;
+	res[1].flags = IORESOURCE_IRQ;
+	pdev->resource = res;
+
+	/* all OMAP1 have IP version 1 register set */
+	pdata->rev = OMAP_I2C_IP_VERSION_1;
+
+	/* all OMAP1 I2C are implemented like this */
+	pdata->flags = OMAP_I2C_FLAG_NO_FIFO |
+		       OMAP_I2C_FLAG_SIMPLE_CLOCK |
+		       OMAP_I2C_FLAG_16BIT_DATA_REG |
+		       OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK;
+
+	/* how the cpu bus is wired up differs for 7xx only */
+
+	if (cpu_is_omap7xx())
+		pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_1;
+	else
+		pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_2;
+
+	pdev->dev.platform_data = pdata;
+
+	return platform_device_register(pdev);
+}
diff --git a/arch/arm/mach-omap1/id.c b/arch/arm/mach-omap1/id.c
index a1b846a..52de382 100644
--- a/arch/arm/mach-omap1/id.c
+++ b/arch/arm/mach-omap1/id.c
@@ -17,7 +17,7 @@
 #include <linux/io.h>
 #include <asm/system_info.h>
 
-#include <plat/cpu.h>
+#include "soc.h"
 
 #include <mach/hardware.h>
 
diff --git a/arch/arm/mach-omap1/include/mach/debug-macro.S b/arch/arm/mach-omap1/include/mach/debug-macro.S
index 2b36a28..5c1a26c 100644
--- a/arch/arm/mach-omap1/include/mach/debug-macro.S
+++ b/arch/arm/mach-omap1/include/mach/debug-macro.S
@@ -13,7 +13,7 @@
 
 #include <linux/serial_reg.h>
 
-#include <plat/serial.h>
+#include "serial.h"
 
 		.pushsection .data
 omap_uart_phys:	.word	0x0
diff --git a/arch/arm/mach-omap1/include/mach/entry-macro.S b/arch/arm/mach-omap1/include/mach/entry-macro.S
index 88f08ca..78a8c6c 100644
--- a/arch/arm/mach-omap1/include/mach/entry-macro.S
+++ b/arch/arm/mach-omap1/include/mach/entry-macro.S
@@ -13,8 +13,6 @@
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 
-#include "../../iomap.h"
-
 		.macro  get_irqnr_preamble, base, tmp
 		.endm
 
diff --git a/arch/arm/mach-omap1/include/mach/gpio.h b/arch/arm/mach-omap1/include/mach/gpio.h
deleted file mode 100644
index ebf86c0..0000000
--- a/arch/arm/mach-omap1/include/mach/gpio.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/*
- * arch/arm/mach-omap1/include/mach/gpio.h
- */
diff --git a/arch/arm/mach-omap1/include/mach/hardware.h b/arch/arm/mach-omap1/include/mach/hardware.h
index 84248d2..5875a50 100644
--- a/arch/arm/mach-omap1/include/mach/hardware.h
+++ b/arch/arm/mach-omap1/include/mach/hardware.h
@@ -39,7 +39,7 @@
 #include <asm/sizes.h>
 #ifndef __ASSEMBLER__
 #include <asm/types.h>
-#include <plat/cpu.h>
+#include <mach/soc.h>
 
 /*
  * NOTE: Please use ioremap + __raw_read/write where possible instead of these
@@ -51,7 +51,7 @@ extern void omap_writeb(u8 v, u32 pa);
 extern void omap_writew(u16 v, u32 pa);
 extern void omap_writel(u32 v, u32 pa);
 
-#include <plat/tc.h>
+#include <mach/tc.h>
 
 /* Almost all documentation for chip and board memory maps assumes
  * BM is clear.  Most devel boards have a switch to control booting
@@ -72,7 +72,10 @@ static inline u32 omap_cs3_phys(void)
 
 #endif	/* ifndef __ASSEMBLER__ */
 
-#include <plat/serial.h>
+#define OMAP1_IO_OFFSET		0x01000000	/* Virtual IO = 0xfefb0000 */
+#define OMAP1_IO_ADDRESS(pa)	IOMEM((pa) - OMAP1_IO_OFFSET)
+
+#include <mach/serial.h>
 
 /*
  * ---------------------------------------------------------------------------
diff --git a/arch/arm/mach-omap1/include/mach/memory.h b/arch/arm/mach-omap1/include/mach/memory.h
index 901082d..3c25305 100644
--- a/arch/arm/mach-omap1/include/mach/memory.h
+++ b/arch/arm/mach-omap1/include/mach/memory.h
@@ -19,7 +19,7 @@
  * because of the strncmp().
  */
 #if defined(CONFIG_ARCH_OMAP15XX) && !defined(__ASSEMBLER__)
-#include <plat/cpu.h>
+#include <mach/soc.h>
 
 /*
  * OMAP-1510 Local Bus address offset
diff --git a/arch/arm/mach-omap1/include/mach/omap1510.h b/arch/arm/mach-omap1/include/mach/omap1510.h
index 8fe05d6..3d23524 100644
--- a/arch/arm/mach-omap1/include/mach/omap1510.h
+++ b/arch/arm/mach-omap1/include/mach/omap1510.h
@@ -45,5 +45,118 @@
 
 #define OMAP1510_DSP_MMU_BASE	(0xfffed200)
 
+/*
+ * ---------------------------------------------------------------------------
+ *  OMAP-1510 FPGA
+ * ---------------------------------------------------------------------------
+ */
+#define OMAP1510_FPGA_BASE		0xE8000000		/* VA */
+#define OMAP1510_FPGA_SIZE		SZ_4K
+#define OMAP1510_FPGA_START		0x08000000		/* PA */
+
+/* Revision */
+#define OMAP1510_FPGA_REV_LOW			IOMEM(OMAP1510_FPGA_BASE + 0x0)
+#define OMAP1510_FPGA_REV_HIGH			IOMEM(OMAP1510_FPGA_BASE + 0x1)
+#define OMAP1510_FPGA_LCD_PANEL_CONTROL		IOMEM(OMAP1510_FPGA_BASE + 0x2)
+#define OMAP1510_FPGA_LED_DIGIT			IOMEM(OMAP1510_FPGA_BASE + 0x3)
+#define INNOVATOR_FPGA_HID_SPI			IOMEM(OMAP1510_FPGA_BASE + 0x4)
+#define OMAP1510_FPGA_POWER			IOMEM(OMAP1510_FPGA_BASE + 0x5)
+
+/* Interrupt status */
+#define OMAP1510_FPGA_ISR_LO			IOMEM(OMAP1510_FPGA_BASE + 0x6)
+#define OMAP1510_FPGA_ISR_HI			IOMEM(OMAP1510_FPGA_BASE + 0x7)
+
+/* Interrupt mask */
+#define OMAP1510_FPGA_IMR_LO			IOMEM(OMAP1510_FPGA_BASE + 0x8)
+#define OMAP1510_FPGA_IMR_HI			IOMEM(OMAP1510_FPGA_BASE + 0x9)
+
+/* Reset registers */
+#define OMAP1510_FPGA_HOST_RESET		IOMEM(OMAP1510_FPGA_BASE + 0xa)
+#define OMAP1510_FPGA_RST			IOMEM(OMAP1510_FPGA_BASE + 0xb)
+
+#define OMAP1510_FPGA_AUDIO			IOMEM(OMAP1510_FPGA_BASE + 0xc)
+#define OMAP1510_FPGA_DIP			IOMEM(OMAP1510_FPGA_BASE + 0xe)
+#define OMAP1510_FPGA_FPGA_IO			IOMEM(OMAP1510_FPGA_BASE + 0xf)
+#define OMAP1510_FPGA_UART1			IOMEM(OMAP1510_FPGA_BASE + 0x14)
+#define OMAP1510_FPGA_UART2			IOMEM(OMAP1510_FPGA_BASE + 0x15)
+#define OMAP1510_FPGA_OMAP1510_STATUS		IOMEM(OMAP1510_FPGA_BASE + 0x16)
+#define OMAP1510_FPGA_BOARD_REV			IOMEM(OMAP1510_FPGA_BASE + 0x18)
+#define INNOVATOR_FPGA_CAM_USB_CONTROL		IOMEM(OMAP1510_FPGA_BASE + 0x20c)
+#define OMAP1510P1_PPT_DATA			IOMEM(OMAP1510_FPGA_BASE + 0x100)
+#define OMAP1510P1_PPT_STATUS			IOMEM(OMAP1510_FPGA_BASE + 0x101)
+#define OMAP1510P1_PPT_CONTROL			IOMEM(OMAP1510_FPGA_BASE + 0x102)
+
+#define OMAP1510_FPGA_TOUCHSCREEN		IOMEM(OMAP1510_FPGA_BASE + 0x204)
+
+#define INNOVATOR_FPGA_INFO			IOMEM(OMAP1510_FPGA_BASE + 0x205)
+#define INNOVATOR_FPGA_LCD_BRIGHT_LO		IOMEM(OMAP1510_FPGA_BASE + 0x206)
+#define INNOVATOR_FPGA_LCD_BRIGHT_HI		IOMEM(OMAP1510_FPGA_BASE + 0x207)
+#define INNOVATOR_FPGA_LED_GRN_LO		IOMEM(OMAP1510_FPGA_BASE + 0x208)
+#define INNOVATOR_FPGA_LED_GRN_HI		IOMEM(OMAP1510_FPGA_BASE + 0x209)
+#define INNOVATOR_FPGA_LED_RED_LO		IOMEM(OMAP1510_FPGA_BASE + 0x20a)
+#define INNOVATOR_FPGA_LED_RED_HI		IOMEM(OMAP1510_FPGA_BASE + 0x20b)
+#define INNOVATOR_FPGA_EXP_CONTROL		IOMEM(OMAP1510_FPGA_BASE + 0x20d)
+#define INNOVATOR_FPGA_ISR2			IOMEM(OMAP1510_FPGA_BASE + 0x20e)
+#define INNOVATOR_FPGA_IMR2			IOMEM(OMAP1510_FPGA_BASE + 0x210)
+
+#define OMAP1510_FPGA_ETHR_START		(OMAP1510_FPGA_START + 0x300)
+
+/*
+ * Power up Giga UART driver, turn on HID clock.
+ * Turn off BT power, since we're not using it and it
+ * draws power.
+ */
+#define OMAP1510_FPGA_RESET_VALUE		0x42
+
+#define OMAP1510_FPGA_PCR_IF_PD0		(1 << 7)
+#define OMAP1510_FPGA_PCR_COM2_EN		(1 << 6)
+#define OMAP1510_FPGA_PCR_COM1_EN		(1 << 5)
+#define OMAP1510_FPGA_PCR_EXP_PD0		(1 << 4)
+#define OMAP1510_FPGA_PCR_EXP_PD1		(1 << 3)
+#define OMAP1510_FPGA_PCR_48MHZ_CLK		(1 << 2)
+#define OMAP1510_FPGA_PCR_4MHZ_CLK		(1 << 1)
+#define OMAP1510_FPGA_PCR_RSRVD_BIT0		(1 << 0)
+
+/*
+ * Innovator/OMAP1510 FPGA HID register bit definitions
+ */
+#define OMAP1510_FPGA_HID_SCLK	(1<<0)	/* output */
+#define OMAP1510_FPGA_HID_MOSI	(1<<1)	/* output */
+#define OMAP1510_FPGA_HID_nSS	(1<<2)	/* output 0/1 chip idle/select */
+#define OMAP1510_FPGA_HID_nHSUS	(1<<3)	/* output 0/1 host active/suspended */
+#define OMAP1510_FPGA_HID_MISO	(1<<4)	/* input */
+#define OMAP1510_FPGA_HID_ATN	(1<<5)	/* input  0/1 chip idle/ATN */
+#define OMAP1510_FPGA_HID_rsrvd	(1<<6)
+#define OMAP1510_FPGA_HID_RESETn (1<<7)	/* output - 0/1 USAR reset/run */
+
+/* The FPGA IRQ is cascaded through GPIO_13 */
+#define OMAP1510_INT_FPGA		(IH_GPIO_BASE + 13)
+
+/* IRQ Numbers for interrupts muxed through the FPGA */
+#define OMAP1510_INT_FPGA_ATN		(OMAP_FPGA_IRQ_BASE + 0)
+#define OMAP1510_INT_FPGA_ACK		(OMAP_FPGA_IRQ_BASE + 1)
+#define OMAP1510_INT_FPGA2		(OMAP_FPGA_IRQ_BASE + 2)
+#define OMAP1510_INT_FPGA3		(OMAP_FPGA_IRQ_BASE + 3)
+#define OMAP1510_INT_FPGA4		(OMAP_FPGA_IRQ_BASE + 4)
+#define OMAP1510_INT_FPGA5		(OMAP_FPGA_IRQ_BASE + 5)
+#define OMAP1510_INT_FPGA6		(OMAP_FPGA_IRQ_BASE + 6)
+#define OMAP1510_INT_FPGA7		(OMAP_FPGA_IRQ_BASE + 7)
+#define OMAP1510_INT_FPGA8		(OMAP_FPGA_IRQ_BASE + 8)
+#define OMAP1510_INT_FPGA9		(OMAP_FPGA_IRQ_BASE + 9)
+#define OMAP1510_INT_FPGA10		(OMAP_FPGA_IRQ_BASE + 10)
+#define OMAP1510_INT_FPGA11		(OMAP_FPGA_IRQ_BASE + 11)
+#define OMAP1510_INT_FPGA12		(OMAP_FPGA_IRQ_BASE + 12)
+#define OMAP1510_INT_ETHER		(OMAP_FPGA_IRQ_BASE + 13)
+#define OMAP1510_INT_FPGAUART1		(OMAP_FPGA_IRQ_BASE + 14)
+#define OMAP1510_INT_FPGAUART2		(OMAP_FPGA_IRQ_BASE + 15)
+#define OMAP1510_INT_FPGA_TS		(OMAP_FPGA_IRQ_BASE + 16)
+#define OMAP1510_INT_FPGA17		(OMAP_FPGA_IRQ_BASE + 17)
+#define OMAP1510_INT_FPGA_CAM		(OMAP_FPGA_IRQ_BASE + 18)
+#define OMAP1510_INT_FPGA_RTC_A		(OMAP_FPGA_IRQ_BASE + 19)
+#define OMAP1510_INT_FPGA_RTC_B		(OMAP_FPGA_IRQ_BASE + 20)
+#define OMAP1510_INT_FPGA_CD		(OMAP_FPGA_IRQ_BASE + 21)
+#define OMAP1510_INT_FPGA22		(OMAP_FPGA_IRQ_BASE + 22)
+#define OMAP1510_INT_FPGA23		(OMAP_FPGA_IRQ_BASE + 23)
+
 #endif /*  __ASM_ARCH_OMAP15XX_H */
 
diff --git a/arch/arm/mach-omap1/include/mach/serial.h b/arch/arm/mach-omap1/include/mach/serial.h
new file mode 100644
index 0000000..2ce6a2d
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/serial.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support- Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_SERIAL_H
+#define __ASM_ARCH_SERIAL_H
+
+#include <linux/init.h>
+
+/*
+ * Memory entry used for the DEBUG_LL UART configuration, relative to
+ * start of RAM. See also uncompress.h and debug-macro.S.
+ *
+ * Note that using a memory location for storing the UART configuration
+ * has at least two limitations:
+ *
+ * 1. Kernel uncompress code cannot overlap OMAP_UART_INFO as the
+ *    uncompress code could then partially overwrite itself
+ * 2. We assume printascii is called at least once before paging_init,
+ *    and addruart has a chance to read OMAP_UART_INFO
+ */
+#define OMAP_UART_INFO_OFS	0x3ffc
+
+/* OMAP1 serial ports */
+#define OMAP1_UART1_BASE	0xfffb0000
+#define OMAP1_UART2_BASE	0xfffb0800
+#define OMAP1_UART3_BASE	0xfffb9800
+
+#define OMAP_PORT_SHIFT		2
+#define OMAP7XX_PORT_SHIFT	0
+
+#define OMAP1510_BASE_BAUD	(12000000/16)
+#define OMAP16XX_BASE_BAUD	(48000000/16)
+
+/*
+ * DEBUG_LL port encoding stored into the UART1 scratchpad register by
+ * decomp_setup in uncompress.h
+ */
+#define OMAP1UART1		11
+#define OMAP1UART2		12
+#define OMAP1UART3		13
+
+#ifndef __ASSEMBLER__
+extern void omap_serial_init(void);
+#endif
+
+#endif
diff --git a/arch/arm/mach-omap1/include/mach/soc.h b/arch/arm/mach-omap1/include/mach/soc.h
new file mode 100644
index 0000000..6cf9c1c
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/soc.h
@@ -0,0 +1,229 @@
+/*
+ * OMAP cpu type detection
+ *
+ * Copyright (C) 2004, 2008 Nokia Corporation
+ *
+ * Copyright (C) 2009-11 Texas Instruments.
+ *
+ * Written by Tony Lindgren <tony.lindgren@nokia.com>
+ *
+ * Added OMAP4/5 specific defines - 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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_OMAP_CPU_H
+#define __ASM_ARCH_OMAP_CPU_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/bitops.h>
+
+/*
+ * Test if multicore OMAP support is needed
+ */
+#undef MULTI_OMAP1
+#undef OMAP_NAME
+
+#ifdef CONFIG_ARCH_OMAP730
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP1
+#  define MULTI_OMAP1
+# else
+#  define OMAP_NAME omap730
+# endif
+#endif
+#ifdef CONFIG_ARCH_OMAP850
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP1
+#  define MULTI_OMAP1
+# else
+#  define OMAP_NAME omap850
+# endif
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP1
+#  define MULTI_OMAP1
+# else
+#  define OMAP_NAME omap1510
+# endif
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP1
+#  define MULTI_OMAP1
+# else
+#  define OMAP_NAME omap16xx
+# endif
+#endif
+
+/*
+ * omap_rev bits:
+ * CPU id bits	(0730, 1510, 1710, 2422...)	[31:16]
+ * CPU revision	(See _REV_ defined in cpu.h)	[15:08]
+ * CPU class bits (15xx, 16xx, 24xx, 34xx...)	[07:00]
+ */
+unsigned int omap_rev(void);
+
+/*
+ * Get the CPU revision for OMAP devices
+ */
+#define GET_OMAP_REVISION()	((omap_rev() >> 8) & 0xff)
+
+/*
+ * Macros to group OMAP into cpu classes.
+ * These can be used in most places.
+ * cpu_is_omap7xx():	True for OMAP730, OMAP850
+ * cpu_is_omap15xx():	True for OMAP1510, OMAP5910 and OMAP310
+ * cpu_is_omap16xx():	True for OMAP1610, OMAP5912 and OMAP1710
+ */
+#define GET_OMAP_CLASS	(omap_rev() & 0xff)
+
+#define IS_OMAP_CLASS(class, id)			\
+static inline int is_omap ##class (void)		\
+{							\
+	return (GET_OMAP_CLASS == (id)) ? 1 : 0;	\
+}
+
+#define GET_OMAP_SUBCLASS	((omap_rev() >> 20) & 0x0fff)
+
+#define IS_OMAP_SUBCLASS(subclass, id)			\
+static inline int is_omap ##subclass (void)		\
+{							\
+	return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;	\
+}
+
+IS_OMAP_CLASS(7xx, 0x07)
+IS_OMAP_CLASS(15xx, 0x15)
+IS_OMAP_CLASS(16xx, 0x16)
+
+#define cpu_is_omap7xx()		0
+#define cpu_is_omap15xx()		0
+#define cpu_is_omap16xx()		0
+
+#if defined(MULTI_OMAP1)
+# if defined(CONFIG_ARCH_OMAP730)
+#  undef  cpu_is_omap7xx
+#  define cpu_is_omap7xx()		is_omap7xx()
+# endif
+# if defined(CONFIG_ARCH_OMAP850)
+#  undef  cpu_is_omap7xx
+#  define cpu_is_omap7xx()		is_omap7xx()
+# endif
+# if defined(CONFIG_ARCH_OMAP15XX)
+#  undef  cpu_is_omap15xx
+#  define cpu_is_omap15xx()		is_omap15xx()
+# endif
+# if defined(CONFIG_ARCH_OMAP16XX)
+#  undef  cpu_is_omap16xx
+#  define cpu_is_omap16xx()		is_omap16xx()
+# endif
+#else
+# if defined(CONFIG_ARCH_OMAP730)
+#  undef  cpu_is_omap7xx
+#  define cpu_is_omap7xx()		1
+# endif
+# if defined(CONFIG_ARCH_OMAP850)
+#  undef  cpu_is_omap7xx
+#  define cpu_is_omap7xx()		1
+# endif
+# if defined(CONFIG_ARCH_OMAP15XX)
+#  undef  cpu_is_omap15xx
+#  define cpu_is_omap15xx()		1
+# endif
+# if defined(CONFIG_ARCH_OMAP16XX)
+#  undef  cpu_is_omap16xx
+#  define cpu_is_omap16xx()		1
+# endif
+#endif
+
+/*
+ * Macros to detect individual cpu types.
+ * These are only rarely needed.
+ * cpu_is_omap310():	True for OMAP310
+ * cpu_is_omap1510():	True for OMAP1510
+ * cpu_is_omap1610():	True for OMAP1610
+ * cpu_is_omap1611():	True for OMAP1611
+ * cpu_is_omap5912():	True for OMAP5912
+ * cpu_is_omap1621():	True for OMAP1621
+ * cpu_is_omap1710():	True for OMAP1710
+ */
+#define GET_OMAP_TYPE	((omap_rev() >> 16) & 0xffff)
+
+#define IS_OMAP_TYPE(type, id)				\
+static inline int is_omap ##type (void)			\
+{							\
+	return (GET_OMAP_TYPE == (id)) ? 1 : 0;		\
+}
+
+IS_OMAP_TYPE(310, 0x0310)
+IS_OMAP_TYPE(1510, 0x1510)
+IS_OMAP_TYPE(1610, 0x1610)
+IS_OMAP_TYPE(1611, 0x1611)
+IS_OMAP_TYPE(5912, 0x1611)
+IS_OMAP_TYPE(1621, 0x1621)
+IS_OMAP_TYPE(1710, 0x1710)
+
+#define cpu_is_omap310()		0
+#define cpu_is_omap1510()		0
+#define cpu_is_omap1610()		0
+#define cpu_is_omap5912()		0
+#define cpu_is_omap1611()		0
+#define cpu_is_omap1621()		0
+#define cpu_is_omap1710()		0
+
+/* These are needed to compile common code */
+#ifdef CONFIG_ARCH_OMAP1
+#define cpu_is_omap242x()		0
+#define cpu_is_omap2430()		0
+#define cpu_is_omap243x()		0
+#define cpu_is_omap24xx()		0
+#define cpu_is_omap34xx()		0
+#define cpu_is_omap44xx()		0
+#define soc_is_omap54xx()		0
+#define soc_is_am33xx()			0
+#define cpu_class_is_omap1()		1
+#define cpu_class_is_omap2()		0
+#endif
+
+/*
+ * Whether we have MULTI_OMAP1 or not, we still need to distinguish
+ * between 310 vs. 1510 and 1611B/5912 vs. 1710.
+ */
+
+#if defined(CONFIG_ARCH_OMAP15XX)
+# undef  cpu_is_omap310
+# undef  cpu_is_omap1510
+# define cpu_is_omap310()		is_omap310()
+# define cpu_is_omap1510()		is_omap1510()
+#endif
+
+#if defined(CONFIG_ARCH_OMAP16XX)
+# undef  cpu_is_omap1610
+# undef  cpu_is_omap1611
+# undef  cpu_is_omap5912
+# undef  cpu_is_omap1621
+# undef  cpu_is_omap1710
+# define cpu_is_omap1610()		is_omap1610()
+# define cpu_is_omap1611()		is_omap1611()
+# define cpu_is_omap5912()		is_omap5912()
+# define cpu_is_omap1621()		is_omap1621()
+# define cpu_is_omap1710()		is_omap1710()
+#endif
+
+#endif	/* __ASSEMBLY__ */
+#endif
diff --git a/arch/arm/mach-omap1/include/mach/tc.h b/arch/arm/mach-omap1/include/mach/tc.h
new file mode 100644
index 0000000..1b4b2da
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/tc.h
@@ -0,0 +1,89 @@
+/*
+ * arch/arm/plat-omap/include/mach/tc.h
+ *
+ * OMAP Traffic Controller
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You 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_TC_H
+#define __ASM_ARCH_TC_H
+
+#define TCMIF_BASE		0xfffecc00
+#define OMAP_TC_OCPT1_PRIOR	(TCMIF_BASE + 0x00)
+#define OMAP_TC_EMIFS_PRIOR	(TCMIF_BASE + 0x04)
+#define OMAP_TC_EMIFF_PRIOR	(TCMIF_BASE + 0x08)
+#define EMIFS_CONFIG		(TCMIF_BASE + 0x0c)
+#define EMIFS_CS0_CONFIG	(TCMIF_BASE + 0x10)
+#define EMIFS_CS1_CONFIG	(TCMIF_BASE + 0x14)
+#define EMIFS_CS2_CONFIG	(TCMIF_BASE + 0x18)
+#define EMIFS_CS3_CONFIG	(TCMIF_BASE + 0x1c)
+#define EMIFF_SDRAM_CONFIG	(TCMIF_BASE + 0x20)
+#define EMIFF_MRS		(TCMIF_BASE + 0x24)
+#define TC_TIMEOUT1		(TCMIF_BASE + 0x28)
+#define TC_TIMEOUT2		(TCMIF_BASE + 0x2c)
+#define TC_TIMEOUT3		(TCMIF_BASE + 0x30)
+#define TC_ENDIANISM		(TCMIF_BASE + 0x34)
+#define EMIFF_SDRAM_CONFIG_2	(TCMIF_BASE + 0x3c)
+#define EMIF_CFG_DYNAMIC_WS	(TCMIF_BASE + 0x40)
+#define EMIFS_ACS0		(TCMIF_BASE + 0x50)
+#define EMIFS_ACS1		(TCMIF_BASE + 0x54)
+#define EMIFS_ACS2		(TCMIF_BASE + 0x58)
+#define EMIFS_ACS3		(TCMIF_BASE + 0x5c)
+#define OMAP_TC_OCPT2_PRIOR	(TCMIF_BASE + 0xd0)
+
+/* external EMIFS chipselect regions */
+#define	OMAP_CS0_PHYS		0x00000000
+#define	OMAP_CS0_SIZE		SZ_64M
+
+#define	OMAP_CS1_PHYS		0x04000000
+#define	OMAP_CS1_SIZE		SZ_64M
+
+#define	OMAP_CS1A_PHYS		OMAP_CS1_PHYS
+#define	OMAP_CS1A_SIZE		SZ_32M
+
+#define	OMAP_CS1B_PHYS		(OMAP_CS1A_PHYS + OMAP_CS1A_SIZE)
+#define	OMAP_CS1B_SIZE		SZ_32M
+
+#define	OMAP_CS2_PHYS		0x08000000
+#define	OMAP_CS2_SIZE		SZ_64M
+
+#define	OMAP_CS2A_PHYS		OMAP_CS2_PHYS
+#define	OMAP_CS2A_SIZE		SZ_32M
+
+#define	OMAP_CS2B_PHYS		(OMAP_CS2A_PHYS + OMAP_CS2A_SIZE)
+#define	OMAP_CS2B_SIZE		SZ_32M
+
+#define	OMAP_CS3_PHYS		0x0c000000
+#define	OMAP_CS3_SIZE		SZ_64M
+
+#ifndef	__ASSEMBLER__
+
+/* EMIF Slow Interface Configuration Register */
+#define OMAP_EMIFS_CONFIG_FR		(1 << 4)
+#define OMAP_EMIFS_CONFIG_PDE		(1 << 3)
+#define OMAP_EMIFS_CONFIG_PWD_EN	(1 << 2)
+#define OMAP_EMIFS_CONFIG_BM		(1 << 1)
+#define OMAP_EMIFS_CONFIG_WP		(1 << 0)
+
+#define EMIFS_CCS(n)		(EMIFS_CS0_CONFIG + (4 * (n)))
+#define EMIFS_ACS(n)		(EMIFS_ACS0 + (4 * (n)))
+
+#endif	/* __ASSEMBLER__ */
+
+#endif	/* __ASM_ARCH_TC_H */
diff --git a/arch/arm/mach-omap1/include/mach/uncompress.h b/arch/arm/mach-omap1/include/mach/uncompress.h
index 0ff22dc..ad6fbe7 100644
--- a/arch/arm/mach-omap1/include/mach/uncompress.h
+++ b/arch/arm/mach-omap1/include/mach/uncompress.h
@@ -1,5 +1,122 @@
 /*
- * arch/arm/mach-omap1/include/mach/uncompress.h
+ * arch/arm/plat-omap/include/mach/uncompress.h
+ *
+ * Serial port stubs for kernel decompress status messages
+ *
+ * Initially based on:
+ * linux-2.4.15-rmk1-dsplinux1.6/arch/arm/plat-omap/include/mach1510/uncompress.h
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: Greg Lonnon <glonnon@ridgerun.com>
+ *
+ * Rewritten by:
+ * Author: <source@mvista.com>
+ * 2004 (c) MontaVista Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
  */
 
-#include <plat/uncompress.h>
+#include <linux/types.h>
+#include <linux/serial_reg.h>
+
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+
+#include "serial.h"
+
+#define MDR1_MODE_MASK			0x07
+
+volatile u8 *uart_base;
+int uart_shift;
+
+/*
+ * Store the DEBUG_LL uart number into memory.
+ * See also debug-macro.S, and serial.c for related code.
+ */
+static void set_omap_uart_info(unsigned char port)
+{
+	/*
+	 * Get address of some.bss variable and round it down
+	 * a la CONFIG_AUTO_ZRELADDR.
+	 */
+	u32 ram_start = (u32)&uart_shift & 0xf8000000;
+	u32 *uart_info = (u32 *)(ram_start + OMAP_UART_INFO_OFS);
+	*uart_info = port;
+}
+
+static void putc(int c)
+{
+	if (!uart_base)
+		return;
+
+	/* Check for UART 16x mode */
+	if ((uart_base[UART_OMAP_MDR1 << uart_shift] & MDR1_MODE_MASK) != 0)
+		return;
+
+	while (!(uart_base[UART_LSR << uart_shift] & UART_LSR_THRE))
+		barrier();
+	uart_base[UART_TX << uart_shift] = c;
+}
+
+static inline void flush(void)
+{
+}
+
+/*
+ * Macros to configure UART1 and debug UART
+ */
+#define _DEBUG_LL_ENTRY(mach, dbg_uart, dbg_shft, dbg_id)		\
+	if (machine_is_##mach()) {					\
+		uart_base = (volatile u8 *)(dbg_uart);			\
+		uart_shift = (dbg_shft);				\
+		port = (dbg_id);					\
+		set_omap_uart_info(port);				\
+		break;							\
+	}
+
+#define DEBUG_LL_OMAP7XX(p, mach)					\
+	_DEBUG_LL_ENTRY(mach, OMAP1_UART##p##_BASE, OMAP7XX_PORT_SHIFT,	\
+		OMAP1UART##p)
+
+#define DEBUG_LL_OMAP1(p, mach)						\
+	_DEBUG_LL_ENTRY(mach, OMAP1_UART##p##_BASE, OMAP_PORT_SHIFT,	\
+		OMAP1UART##p)
+
+static inline void arch_decomp_setup(void)
+{
+	int port = 0;
+
+	/*
+	 * Initialize the port based on the machine ID from the bootloader.
+	 * Note that we're using macros here instead of switch statement
+	 * as machine_is functions are optimized out for the boards that
+	 * are not selected.
+	 */
+	do {
+		/* omap7xx/8xx based boards using UART1 with shift 0 */
+		DEBUG_LL_OMAP7XX(1, herald);
+		DEBUG_LL_OMAP7XX(1, omap_perseus2);
+
+		/* omap15xx/16xx based boards using UART1 */
+		DEBUG_LL_OMAP1(1, ams_delta);
+		DEBUG_LL_OMAP1(1, nokia770);
+		DEBUG_LL_OMAP1(1, omap_h2);
+		DEBUG_LL_OMAP1(1, omap_h3);
+		DEBUG_LL_OMAP1(1, omap_innovator);
+		DEBUG_LL_OMAP1(1, omap_osk);
+		DEBUG_LL_OMAP1(1, omap_palmte);
+		DEBUG_LL_OMAP1(1, omap_palmz71);
+
+		/* omap15xx/16xx based boards using UART2 */
+		DEBUG_LL_OMAP1(2, omap_palmtt);
+
+		/* omap15xx/16xx based boards using UART3 */
+		DEBUG_LL_OMAP1(3, sx1);
+	} while (0);
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_wdog()
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index 6a5baab..5a3b806 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -17,8 +17,8 @@
 #include <asm/mach/map.h>
 
 #include <mach/mux.h>
-#include <plat/tc.h>
-#include <plat/dma.h>
+#include <mach/tc.h>
+#include <plat-omap/dma-omap.h>
 
 #include "iomap.h"
 #include "common.h"
@@ -134,7 +134,6 @@ void __init omap1_init_early(void)
 	 */
 	omap1_clk_init();
 	omap1_mux_init();
-	omap_init_consistent_dma_size();
 }
 
 void __init omap1_init_late(void)
diff --git a/arch/arm/mach-omap1/iomap.h b/arch/arm/mach-omap1/iomap.h
index 330c471..f4e2d7a 100644
--- a/arch/arm/mach-omap1/iomap.h
+++ b/arch/arm/mach-omap1/iomap.h
@@ -22,9 +22,6 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define OMAP1_IO_OFFSET		0x01000000	/* Virtual IO = 0xfefb0000 */
-#define OMAP1_IO_ADDRESS(pa)	IOMEM((pa) - OMAP1_IO_OFFSET)
-
 /*
  * ----------------------------------------------------------------------------
  * Omap1 specific IO mapping
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index 6995fb6..122ef67 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -45,7 +45,7 @@
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 
-#include <plat/cpu.h>
+#include "soc.h"
 
 #include <mach/hardware.h>
 
diff --git a/arch/arm/mach-omap1/lcd_dma.c b/arch/arm/mach-omap1/lcd_dma.c
index ed42628..7ed8c18 100644
--- a/arch/arm/mach-omap1/lcd_dma.c
+++ b/arch/arm/mach-omap1/lcd_dma.c
@@ -27,11 +27,13 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 
 #include <mach/hardware.h>
 #include <mach/lcdc.h>
 
+#include "dma.h"
+
 int omap_lcd_dma_running(void)
 {
 	/*
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index bdc2e75..c6d8fdf 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -19,14 +19,15 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 #include <mach/mux.h>
-#include <plat/cpu.h>
+#include "soc.h"
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 
 #include <mach/irqs.h>
 
 #include "iomap.h"
+#include "dma.h"
 
 #define DPS_RSTCT2_PER_EN	(1 << 0)
 #define DSP_RSTCT2_WD_PER_EN	(1 << 1)
diff --git a/arch/arm/mach-omap1/mmc.h b/arch/arm/mach-omap1/mmc.h
new file mode 100644
index 0000000..39c2b13
--- /dev/null
+++ b/arch/arm/mach-omap1/mmc.h
@@ -0,0 +1,18 @@
+#include <linux/mmc/host.h>
+#include <linux/platform_data/mmc-omap.h>
+
+#define OMAP15XX_NR_MMC		1
+#define OMAP16XX_NR_MMC		2
+#define OMAP1_MMC_SIZE		0x080
+#define OMAP1_MMC1_BASE		0xfffb7800
+#define OMAP1_MMC2_BASE		0xfffb7c00	/* omap16xx only */
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
+				int nr_controllers);
+#else
+static inline void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
+				int nr_controllers)
+{
+}
+#endif
diff --git a/arch/arm/mach-omap1/opp_data.c b/arch/arm/mach-omap1/opp_data.c
index 9cd4ddb..8dcebe6 100644
--- a/arch/arm/mach-omap1/opp_data.c
+++ b/arch/arm/mach-omap1/opp_data.c
@@ -10,7 +10,7 @@
  * published by the Free Software Foundation.
  */
 
-#include <plat/clkdev_omap.h>
+#include "clock.h"
 #include "opp.h"
 
 /*-------------------------------------------------------------------------
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index 47ec161..66d663a 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -44,23 +44,23 @@
 #include <linux/io.h>
 #include <linux/atomic.h>
 
+#include <asm/fncpy.h>
 #include <asm/system_misc.h>
 #include <asm/irq.h>
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 
-#include <plat/cpu.h>
-#include <plat/clock.h>
-#include <plat/sram.h>
-#include <plat/tc.h>
+#include <mach/tc.h>
 #include <mach/mux.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 #include <plat/dmtimer.h>
 
 #include <mach/irqs.h>
 
 #include "iomap.h"
+#include "clock.h"
 #include "pm.h"
+#include "sram.h"
 
 static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
 static unsigned short dsp_sleep_save[DSP_SLEEP_SAVE_SIZE];
diff --git a/arch/arm/mach-omap1/pm_bus.c b/arch/arm/mach-omap1/pm_bus.c
index 7868e75..3f2d396 100644
--- a/arch/arm/mach-omap1/pm_bus.c
+++ b/arch/arm/mach-omap1/pm_bus.c
@@ -19,8 +19,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 
-#include <plat/omap_device.h>
-#include <plat/omap-pm.h>
+#include "soc.h"
 
 #ifdef CONFIG_PM_RUNTIME
 static int omap1_pm_runtime_suspend(struct device *dev)
diff --git a/arch/arm/mach-omap1/reset.c b/arch/arm/mach-omap1/reset.c
index b177091..5eebd7e 100644
--- a/arch/arm/mach-omap1/reset.c
+++ b/arch/arm/mach-omap1/reset.c
@@ -4,12 +4,24 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 
-#include <plat/prcm.h>
-
 #include <mach/hardware.h>
 
+#include "iomap.h"
 #include "common.h"
 
+/* ARM_SYSST bit shifts related to SoC reset sources */
+#define ARM_SYSST_POR_SHIFT				5
+#define ARM_SYSST_EXT_RST_SHIFT				4
+#define ARM_SYSST_ARM_WDRST_SHIFT			2
+#define ARM_SYSST_GLOB_SWRST_SHIFT			1
+
+/* Standardized reset source bits (across all OMAP SoCs) */
+#define OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT		0
+#define OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT		1
+#define OMAP_MPU_WD_RST_SRC_ID_SHIFT			3
+#define OMAP_EXTWARM_RST_SRC_ID_SHIFT			5
+
+
 void omap1_restart(char mode, const char *cmd)
 {
 	/*
@@ -23,3 +35,28 @@ void omap1_restart(char mode, const char *cmd)
 
 	omap_writew(1, ARM_RSTCT1);
 }
+
+/**
+ * omap1_get_reset_sources - return the source of the SoC's last reset
+ *
+ * Returns bits that represent the last reset source for the SoC.  The
+ * format is standardized across OMAPs for use by the OMAP watchdog.
+ */
+u32 omap1_get_reset_sources(void)
+{
+	u32 ret = 0;
+	u16 rs;
+
+	rs = __raw_readw(OMAP1_IO_ADDRESS(ARM_SYSST));
+
+	if (rs & (1 << ARM_SYSST_POR_SHIFT))
+		ret |= 1 << OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT;
+	if (rs & (1 << ARM_SYSST_EXT_RST_SHIFT))
+		ret |= 1 << OMAP_EXTWARM_RST_SRC_ID_SHIFT;
+	if (rs & (1 << ARM_SYSST_ARM_WDRST_SHIFT))
+		ret |= 1 << OMAP_MPU_WD_RST_SRC_ID_SHIFT;
+	if (rs & (1 << ARM_SYSST_GLOB_SWRST_SHIFT))
+		ret |= 1 << OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT;
+
+	return ret;
+}
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index b9d6834..d1ac080 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -23,7 +23,6 @@
 #include <asm/mach-types.h>
 
 #include <mach/mux.h>
-#include <plat/fpga.h>
 
 #include "pm.h"
 
diff --git a/arch/arm/mach-omap1/sleep.S b/arch/arm/mach-omap1/sleep.S
index 0e62874..a908c51 100644
--- a/arch/arm/mach-omap1/sleep.S
+++ b/arch/arm/mach-omap1/sleep.S
@@ -36,6 +36,8 @@
 
 #include <asm/assembler.h>
 
+#include <mach/hardware.h>
+
 #include "iomap.h"
 #include "pm.h"
 
diff --git a/arch/arm/mach-omap1/soc.h b/arch/arm/mach-omap1/soc.h
new file mode 100644
index 0000000..69daf01
--- /dev/null
+++ b/arch/arm/mach-omap1/soc.h
@@ -0,0 +1,4 @@
+/*
+ * We can move mach/soc.h here once the drivers are fixed
+ */
+#include <mach/soc.h>
diff --git a/arch/arm/mach-omap1/sram-init.c b/arch/arm/mach-omap1/sram-init.c
new file mode 100644
index 0000000..6431b0f
--- /dev/null
+++ b/arch/arm/mach-omap1/sram-init.c
@@ -0,0 +1,76 @@
+/*
+ * OMAP SRAM detection and management
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Written by Tony Lindgren <tony@atomide.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/fncpy.h>
+#include <asm/tlb.h>
+#include <asm/cacheflush.h>
+
+#include <asm/mach/map.h>
+
+#include "soc.h"
+#include "sram.h"
+
+#define OMAP1_SRAM_PA		0x20000000
+#define SRAM_BOOTLOADER_SZ	0x80
+
+/*
+ * The amount of SRAM depends on the core type.
+ * Note that we cannot try to test for SRAM here because writes
+ * to secure SRAM will hang the system. Also the SRAM is not
+ * yet mapped at this point.
+ */
+static void __init omap_detect_and_map_sram(void)
+{
+	unsigned long omap_sram_skip = SRAM_BOOTLOADER_SZ;
+	unsigned long omap_sram_start = OMAP1_SRAM_PA;
+	unsigned long omap_sram_size;
+
+	if (cpu_is_omap7xx())
+		omap_sram_size = 0x32000;	/* 200K */
+	else if (cpu_is_omap15xx())
+		omap_sram_size = 0x30000;	/* 192K */
+	else if (cpu_is_omap1610() || cpu_is_omap1611() ||
+			cpu_is_omap1621() || cpu_is_omap1710())
+		omap_sram_size = 0x4000;	/* 16K */
+	else {
+		pr_err("Could not detect SRAM size\n");
+		omap_sram_size = 0x4000;
+	}
+
+	omap_map_sram(omap_sram_start, omap_sram_size,
+		omap_sram_skip, 1);
+}
+
+static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl);
+
+void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl)
+{
+	BUG_ON(!_omap_sram_reprogram_clock);
+	/* On 730, bit 13 must always be 1 */
+	if (cpu_is_omap7xx())
+		ckctl |= 0x2000;
+	_omap_sram_reprogram_clock(dpllctl, ckctl);
+}
+
+int __init omap_sram_init(void)
+{
+	omap_detect_and_map_sram();
+	_omap_sram_reprogram_clock =
+			omap_sram_push(omap1_sram_reprogram_clock,
+					omap1_sram_reprogram_clock_sz);
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap1/sram.h b/arch/arm/mach-omap1/sram.h
new file mode 100644
index 0000000..d5a6c83
--- /dev/null
+++ b/arch/arm/mach-omap1/sram.h
@@ -0,0 +1,7 @@
+#include <plat/sram.h>
+
+extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
+
+/* Do not use these */
+extern void omap1_sram_reprogram_clock(u32 ckctl, u32 dpllctl);
+extern unsigned long omap1_sram_reprogram_clock_sz;
diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
index 7452954..8936819 100644
--- a/arch/arm/mach-omap1/timer32k.c
+++ b/arch/arm/mach-omap1/timer32k.c
@@ -50,6 +50,7 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
+#include <plat/counter-32k.h>
 #include <plat/dmtimer.h>
 
 #include <mach/hardware.h>
diff --git a/arch/arm/mach-omap1/usb.c b/arch/arm/mach-omap1/usb.c
index 84267ed..104fed3 100644
--- a/arch/arm/mach-omap1/usb.c
+++ b/arch/arm/mach-omap1/usb.c
@@ -301,7 +301,7 @@ static inline void otg_device_init(struct omap_usb_config *pdata)
 
 #endif
 
-u32 __init omap1_usb0_init(unsigned nwires, unsigned is_device)
+static u32 __init omap1_usb0_init(unsigned nwires, unsigned is_device)
 {
 	u32	syscon1 = 0;
 
@@ -409,7 +409,7 @@ u32 __init omap1_usb0_init(unsigned nwires, unsigned is_device)
 	return syscon1 << 16;
 }
 
-u32 __init omap1_usb1_init(unsigned nwires)
+static u32 __init omap1_usb1_init(unsigned nwires)
 {
 	u32	syscon1 = 0;
 
@@ -475,7 +475,7 @@ bad:
 	return syscon1 << 20;
 }
 
-u32 __init omap1_usb2_init(unsigned nwires, unsigned alt_pingroup)
+static u32 __init omap1_usb2_init(unsigned nwires, unsigned alt_pingroup)
 {
 	u32	syscon1 = 0;
 
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index d669e22..be0f62b 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -34,6 +34,7 @@ config ARCH_OMAP2
 	select CPU_V6
 	select MULTI_IRQ_HANDLER
 	select SOC_HAS_OMAP2_SDRC
+	select COMMON_CLK
 
 config ARCH_OMAP3
 	bool "TI OMAP3"
@@ -47,6 +48,7 @@ config ARCH_OMAP3
 	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
@@ -68,6 +70,7 @@ config ARCH_OMAP4
 	select PM_OPP if PM
 	select PM_RUNTIME if CPU_IDLE
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
+	select COMMON_CLK
 
 config SOC_OMAP5
 	bool "TI OMAP5"
@@ -77,6 +80,7 @@ config SOC_OMAP5
 	select CPU_V7
 	select HAVE_SMP
 	select SOC_HAS_REALTIME_COUNTER
+	select COMMON_CLK
 
 comment "OMAP Core Type"
 	depends on ARCH_OMAP2
@@ -111,6 +115,7 @@ config SOC_AM33XX
 	select ARM_CPU_SUSPEND if PM
 	select CPU_V7
 	select MULTI_IRQ_HANDLER
+	select COMMON_CLK
 
 config OMAP_PACKAGE_ZAF
        bool
@@ -270,14 +275,14 @@ config MACH_NOKIA_N8X0
 	select OMAP_PACKAGE_ZAC
 
 config MACH_NOKIA_RM680
-	bool "Nokia RM-680/696 board"
+	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 RX-51 board"
+	bool "Nokia N900 (RX-51) phone"
 	depends on ARCH_OMAP3
 	default y
 	select OMAP_PACKAGE_CBB
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index fe40d9e..88155db 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -4,30 +4,37 @@
 
 # Common support
 obj-y := id.o io.o control.o mux.o devices.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
-
-# INTCPS IP block support - XXX should be moved to drivers/
-obj-$(CONFIG_ARCH_OMAP2)		+= irq.o
-obj-$(CONFIG_ARCH_OMAP3)		+= irq.o
-obj-$(CONFIG_SOC_AM33XX)		+= irq.o
-
-# Secure monitor API support
-obj-$(CONFIG_ARCH_OMAP3)		+= omap-smc.o omap-secure.o
-obj-$(CONFIG_ARCH_OMAP4)		+= omap-smc.o omap-secure.o
-obj-$(CONFIG_SOC_OMAP5)			+= omap-smc.o omap-secure.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-2-3-common				= irq.o
+hwmod-common				= omap_hwmod.o \
+					  omap_hwmod_common_data.o
+clock-common				= clock.o clock_common_data.o \
+					  clkt_dpll.o clkt_clksel.o
+secure-common				= omap-smc.o omap-secure.o
+
+obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
+obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
+obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common) $(secure-common)
+obj-$(CONFIG_SOC_AM33XX) += irq.o $(hwmod-common)
+obj-$(CONFIG_SOC_OMAP5)	 += prm44xx.o $(hwmod-common) $(secure-common)
 
 ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),)
 obj-y += mcbsp.o
 endif
 
-obj-$(CONFIG_TWL4030_CORE)		+= omap_twl.o
+obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
+obj-$(CONFIG_SOC_HAS_OMAP2_SDRC)	+= sdrc.o
 
 # SMP support ONLY available for OMAP4
 
 obj-$(CONFIG_SMP)			+= omap-smp.o omap-headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= omap-hotplug.o
-obj-$(CONFIG_ARCH_OMAP4)		+= omap4-common.o omap-wakeupgen.o
-obj-$(CONFIG_SOC_OMAP5)			+= omap4-common.o omap-wakeupgen.o
+omap-4-5-common				=  omap4-common.o omap-wakeupgen.o \
+					   sleep44xx.o
+obj-$(CONFIG_ARCH_OMAP4)		+= $(omap-4-5-common)
+obj-$(CONFIG_SOC_OMAP5)			+= $(omap-4-5-common)
 
 plus_sec := $(call as-instr,.arch_extension sec,+sec)
 AFLAGS_omap-headsmp.o			:=-Wa,-march=armv7-a$(plus_sec)
@@ -43,6 +50,11 @@ AFLAGS_sram242x.o			:=-Wa,-march=armv6
 AFLAGS_sram243x.o			:=-Wa,-march=armv6
 AFLAGS_sram34xx.o			:=-Wa,-march=armv7-a
 
+# Restart code (OMAP4/5 currently in omap4-common.c)
+obj-$(CONFIG_SOC_OMAP2420)		+= omap2-restart.o
+obj-$(CONFIG_SOC_OMAP2430)		+= omap2-restart.o
+obj-$(CONFIG_ARCH_OMAP3)		+= omap3-restart.o
+
 # Pin multiplexing
 obj-$(CONFIG_SOC_OMAP2420)		+= mux2420.o
 obj-$(CONFIG_SOC_OMAP2430)		+= mux2430.o
@@ -52,7 +64,6 @@ obj-$(CONFIG_ARCH_OMAP4)		+= mux44xx.o
 # SMS/SDRC
 obj-$(CONFIG_ARCH_OMAP2)		+= sdrc2xxx.o
 # obj-$(CONFIG_ARCH_OMAP3)		+= sdrc3xxx.o
-obj-$(CONFIG_SOC_HAS_OMAP2_SDRC)	+= sdrc.o
 
 # OPP table initialization
 ifeq ($(CONFIG_PM_OPP),y)
@@ -62,16 +73,18 @@ obj-$(CONFIG_ARCH_OMAP4)		+= opp4xxx_data.o
 endif
 
 # Power Management
+obj-$(CONFIG_OMAP_PM_NOOP)		+= omap-pm-noop.o
+
 ifeq ($(CONFIG_PM),y)
-obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o sleep24xx.o
+obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o
+obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o
 obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o omap-mpuss-lowpower.o
-obj-$(CONFIG_ARCH_OMAP4)		+= sleep44xx.o
-obj-$(CONFIG_SOC_OMAP5)			+= omap-mpuss-lowpower.o sleep44xx.o
+obj-$(CONFIG_SOC_OMAP5)			+= omap-mpuss-lowpower.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
 
 obj-$(CONFIG_POWER_AVS_OMAP)		+= sr_device.o
-obj-$(CONFIG_POWER_AVS_OMAP_CLASS3)	+= smartreflex-class3.o
+obj-$(CONFIG_POWER_AVS_OMAP_CLASS3)    += smartreflex-class3.o
 
 AFLAGS_sleep24xx.o			:=-Wa,-march=armv6
 AFLAGS_sleep34xx.o			:=-Wa,-march=armv7-a$(plus_sec)
@@ -83,76 +96,82 @@ endif
 endif
 
 ifeq ($(CONFIG_CPU_IDLE),y)
-obj-$(CONFIG_ARCH_OMAP3)		+= cpuidle34xx.o
-obj-$(CONFIG_ARCH_OMAP4)		+= cpuidle44xx.o
+obj-$(CONFIG_ARCH_OMAP3)                += cpuidle34xx.o
+obj-$(CONFIG_ARCH_OMAP4)                += cpuidle44xx.o
 endif
 
 # PRCM
-obj-y					+= prcm.o prm_common.o
-obj-$(CONFIG_ARCH_OMAP2)		+= cm2xxx_3xxx.o prm2xxx_3xxx.o
-obj-$(CONFIG_ARCH_OMAP3)		+= cm2xxx_3xxx.o prm2xxx_3xxx.o
+obj-y					+= prm_common.o cm_common.o
+obj-$(CONFIG_ARCH_OMAP2)		+= prm2xxx_3xxx.o prm2xxx.o cm2xxx.o
+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
 omap-prcm-4-5-common			=  cminst44xx.o cm44xx.o prm44xx.o \
 					   prcm_mpu44xx.o prminst44xx.o \
-					   vc44xx_data.o vp44xx_data.o \
-					   prm44xx.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)
 
 # OMAP voltage domains
-obj-y					+= voltage.o vc.o vp.o
+voltagedomain-common			:= voltage.o vc.o vp.o
+obj-$(CONFIG_ARCH_OMAP2)		+= $(voltagedomain-common)
 obj-$(CONFIG_ARCH_OMAP2)		+= voltagedomains2xxx_data.o
+obj-$(CONFIG_ARCH_OMAP3)		+= $(voltagedomain-common)
 obj-$(CONFIG_ARCH_OMAP3)		+= voltagedomains3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP4)		+= $(voltagedomain-common)
 obj-$(CONFIG_ARCH_OMAP4)		+= voltagedomains44xx_data.o
-obj-$(CONFIG_SOC_AM33XX)		+= voltagedomains33xx_data.o
+obj-$(CONFIG_SOC_AM33XX)		+= $(voltagedomain-common)
+obj-$(CONFIG_SOC_AM33XX)                += voltagedomains33xx_data.o
+obj-$(CONFIG_SOC_OMAP5)			+= $(voltagedomain-common)
 
 # OMAP powerdomain framework
-obj-y					+= powerdomain.o powerdomain-common.o
+powerdomain-common			+= powerdomain.o powerdomain-common.o
+obj-$(CONFIG_ARCH_OMAP2)		+= $(powerdomain-common)
 obj-$(CONFIG_ARCH_OMAP2)		+= powerdomains2xxx_data.o
-obj-$(CONFIG_ARCH_OMAP2)		+= powerdomain2xxx_3xxx.o
 obj-$(CONFIG_ARCH_OMAP2)		+= powerdomains2xxx_3xxx_data.o
-obj-$(CONFIG_ARCH_OMAP3)		+= powerdomain2xxx_3xxx.o
+obj-$(CONFIG_ARCH_OMAP3)		+= $(powerdomain-common)
 obj-$(CONFIG_ARCH_OMAP3)		+= powerdomains3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= powerdomains2xxx_3xxx_data.o
-obj-$(CONFIG_ARCH_OMAP4)		+= powerdomain44xx.o
+obj-$(CONFIG_ARCH_OMAP4)		+= $(powerdomain-common)
 obj-$(CONFIG_ARCH_OMAP4)		+= powerdomains44xx_data.o
-obj-$(CONFIG_SOC_AM33XX)		+= powerdomain33xx.o
+obj-$(CONFIG_SOC_AM33XX)		+= $(powerdomain-common)
 obj-$(CONFIG_SOC_AM33XX)		+= powerdomains33xx_data.o
-obj-$(CONFIG_SOC_OMAP5)			+= powerdomain44xx.o
+obj-$(CONFIG_SOC_OMAP5)			+= $(powerdomain-common)
 
 # PRCM clockdomain control
-obj-y					+= clockdomain.o
-obj-$(CONFIG_ARCH_OMAP2)		+= clockdomain2xxx_3xxx.o
+clockdomain-common			+= clockdomain.o
+obj-$(CONFIG_ARCH_OMAP2)		+= $(clockdomain-common)
 obj-$(CONFIG_ARCH_OMAP2)		+= clockdomains2xxx_3xxx_data.o
 obj-$(CONFIG_SOC_OMAP2420)		+= clockdomains2420_data.o
 obj-$(CONFIG_SOC_OMAP2430)		+= clockdomains2430_data.o
-obj-$(CONFIG_ARCH_OMAP3)		+= clockdomain2xxx_3xxx.o
+obj-$(CONFIG_ARCH_OMAP3)		+= $(clockdomain-common)
 obj-$(CONFIG_ARCH_OMAP3)		+= clockdomains2xxx_3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clockdomains3xxx_data.o
-obj-$(CONFIG_ARCH_OMAP4)		+= clockdomain44xx.o
+obj-$(CONFIG_ARCH_OMAP4)		+= $(clockdomain-common)
 obj-$(CONFIG_ARCH_OMAP4)		+= clockdomains44xx_data.o
-obj-$(CONFIG_SOC_AM33XX)		+= clockdomain33xx.o
+obj-$(CONFIG_SOC_AM33XX)		+= $(clockdomain-common)
 obj-$(CONFIG_SOC_AM33XX)		+= clockdomains33xx_data.o
-obj-$(CONFIG_SOC_OMAP5)			+= clockdomain44xx.o
+obj-$(CONFIG_SOC_OMAP5)			+= $(clockdomain-common)
 
 # Clock framework
-obj-y					+= clock.o clock_common_data.o \
-					   clkt_dpll.o clkt_clksel.o
-obj-$(CONFIG_ARCH_OMAP2)		+= clock2xxx.o
-obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_dpllcore.o clkt2xxx_sys.o
+obj-$(CONFIG_ARCH_OMAP2)		+= $(clock-common) clock2xxx.o
+obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_sys.o
+obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_dpllcore.o
 obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_virt_prcm_set.o
 obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_apll.o clkt2xxx_osc.o
 obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_dpll.o clkt_iclk.o
-obj-$(CONFIG_SOC_OMAP2420)		+= clock2420_data.o
-obj-$(CONFIG_SOC_OMAP2430)		+= clock2430.o clock2430_data.o
-obj-$(CONFIG_ARCH_OMAP3)		+= clock3xxx.o
+obj-$(CONFIG_SOC_OMAP2420)		+= cclock2420_data.o
+obj-$(CONFIG_SOC_OMAP2430)		+= clock2430.o cclock2430_data.o
+obj-$(CONFIG_ARCH_OMAP3)		+= $(clock-common) clock3xxx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clock34xx.o clkt34xx_dpll3m2.o
-obj-$(CONFIG_ARCH_OMAP3)		+= clock3517.o clock36xx.o clkt_iclk.o
-obj-$(CONFIG_ARCH_OMAP3)		+= dpll3xxx.o clock3xxx_data.o
-obj-$(CONFIG_ARCH_OMAP4)		+= clock44xx_data.o
+obj-$(CONFIG_ARCH_OMAP3)		+= clock3517.o clock36xx.o
+obj-$(CONFIG_ARCH_OMAP3)		+= dpll3xxx.o cclock3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP3)		+= clkt_iclk.o
+obj-$(CONFIG_ARCH_OMAP4)		+= $(clock-common) cclock44xx_data.o
 obj-$(CONFIG_ARCH_OMAP4)		+= dpll3xxx.o dpll44xx.o
-obj-$(CONFIG_SOC_AM33XX)		+= dpll3xxx.o clock33xx_data.o
+obj-$(CONFIG_SOC_AM33XX)		+= $(clock-common) dpll3xxx.o
+obj-$(CONFIG_SOC_AM33XX)		+= cclock33xx_data.o
+obj-$(CONFIG_SOC_OMAP5)			+= $(clock-common)
 obj-$(CONFIG_SOC_OMAP5)			+= dpll3xxx.o dpll44xx.o
 
 # OMAP2 clock rate set data (old "OPP" data)
@@ -160,7 +179,6 @@ obj-$(CONFIG_SOC_OMAP2420)		+= opp2420_data.o
 obj-$(CONFIG_SOC_OMAP2430)		+= opp2430_data.o
 
 # hwmod data
-obj-y					+= omap_hwmod_common_data.o
 obj-$(CONFIG_SOC_OMAP2420)		+= omap_hwmod_2xxx_ipblock_data.o
 obj-$(CONFIG_SOC_OMAP2420)		+= omap_hwmod_2xxx_3xxx_ipblock_data.o
 obj-$(CONFIG_SOC_OMAP2420)		+= omap_hwmod_2xxx_interconnect_data.o
@@ -206,10 +224,10 @@ obj-$(CONFIG_MACH_OMAP_H4)		+= board-h4.o
 obj-$(CONFIG_MACH_OMAP_2430SDP)		+= board-2430sdp.o
 obj-$(CONFIG_MACH_OMAP_APOLLON)		+= board-apollon.o
 obj-$(CONFIG_MACH_OMAP3_BEAGLE)		+= board-omap3beagle.o
-obj-$(CONFIG_MACH_DEVKIT8000)		+= board-devkit8000.o
+obj-$(CONFIG_MACH_DEVKIT8000)     	+= board-devkit8000.o
 obj-$(CONFIG_MACH_OMAP_LDP)		+= board-ldp.o
-obj-$(CONFIG_MACH_OMAP3530_LV_SOM)	+= board-omap3logic.o
-obj-$(CONFIG_MACH_OMAP3_TORPEDO)	+= board-omap3logic.o
+obj-$(CONFIG_MACH_OMAP3530_LV_SOM)      += board-omap3logic.o
+obj-$(CONFIG_MACH_OMAP3_TORPEDO)        += board-omap3logic.o
 obj-$(CONFIG_MACH_ENCORE)		+= board-omap3encore.o
 obj-$(CONFIG_MACH_OVERO)		+= board-overo.o
 obj-$(CONFIG_MACH_OMAP3EVM)		+= board-omap3evm.o
@@ -279,4 +297,4 @@ endif
 emac-$(CONFIG_TI_DAVINCI_EMAC)		:= am35xx-emac.o
 obj-y					+= $(emac-m) $(emac-y)
 
-obj-y					+= common-board-devices.o twl-common.o
+obj-y					+= common-board-devices.o twl-common.o dss-common.o
diff --git a/arch/arm/mach-omap2/am33xx.h b/arch/arm/mach-omap2/am33xx.h
index 06c19bb..43296c1 100644
--- a/arch/arm/mach-omap2/am33xx.h
+++ b/arch/arm/mach-omap2/am33xx.h
@@ -21,5 +21,6 @@
 #define AM33XX_SCM_BASE		0x44E10000
 #define AM33XX_CTRL_BASE	AM33XX_SCM_BASE
 #define AM33XX_PRCM_BASE	0x44E00000
+#define AM33XX_TAP_BASE		(AM33XX_CTRL_BASE + 0x3FC)
 
 #endif /* __ASM_ARCH_AM33XX_H */
diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c
index d0c54c5..af11dcd 100644
--- a/arch/arm/mach-omap2/am35xx-emac.c
+++ b/arch/arm/mach-omap2/am35xx-emac.c
@@ -18,7 +18,7 @@
 #include <linux/err.h>
 #include <linux/davinci_emac.h>
 #include <asm/system.h>
-#include <plat/omap_device.h>
+#include "omap_device.h"
 #include "am35xx.h"
 #include "control.h"
 #include "am35xx-emac.h"
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 95b384d..4815ea6 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -28,14 +28,12 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
 #include "common.h"
-#include <plat/gpmc.h>
-#include <plat/usb.h>
+#include "gpmc.h"
 #include "gpmc-smc91x.h"
 
 #include <video/omapdss.h>
@@ -287,5 +285,5 @@ MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board")
 	.init_machine	= omap_2430sdp_init,
 	.init_late	= omap2430_init_late,
 	.timer		= &omap2_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap2xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 96cd369..6601754 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -30,15 +30,15 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/usb.h>
 #include "common.h"
-#include <plat/dma.h>
-#include <plat/gpmc.h>
+#include <plat-omap/dma-omap.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-tfp410.h>
 
+#include "gpmc.h"
 #include "gpmc-smc91x.h"
 
+#include "soc.h"
 #include "board-flash.h"
 #include "mux.h"
 #include "sdram-qimonda-hyb18m512160af-6.h"
@@ -597,5 +597,5 @@ MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
 	.init_machine	= omap_3430sdp_init,
 	.init_late	= omap3430_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index fc224ad..050aaa7 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -18,9 +18,8 @@
 
 #include "common.h"
 #include "gpmc-smc91x.h"
-#include <plat/usb.h>
 
-#include <mach/board-zoom.h>
+#include "board-zoom.h"
 
 #include "board-flash.h"
 #include "mux.h"
@@ -213,5 +212,5 @@ MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board")
 	.init_machine	= omap_sdp_init,
 	.init_late	= omap3630_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 3669c12..1cc6696 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -27,6 +27,7 @@
 #include <linux/leds.h>
 #include <linux/leds_pwm.h>
 #include <linux/platform_data/omap4-keypad.h>
+#include <linux/usb/musb.h>
 
 #include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
@@ -34,31 +35,23 @@
 #include <asm/mach/map.h>
 
 #include "common.h"
-#include <plat/usb.h>
-#include <plat/mmc.h>
 #include "omap4-keypad.h"
-#include <video/omapdss.h>
-#include <video/omap-panel-nokia-dsi.h>
-#include <video/omap-panel-picodlp.h>
 #include <linux/wl12xx.h>
 #include <linux/platform_data/omap-abe-twl6040.h>
 
 #include "soc.h"
 #include "mux.h"
+#include "mmc.h"
 #include "hsmmc.h"
 #include "control.h"
 #include "common-board-devices.h"
+#include "dss-common.h"
 
 #define ETH_KS8851_IRQ			34
 #define ETH_KS8851_POWER_ON		48
 #define ETH_KS8851_QUART		138
 #define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO	184
 #define OMAP4_SFH7741_ENABLE_GPIO		188
-#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */
-#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
-#define HDMI_GPIO_HPD  63 /* Hotplug detect */
-#define DISPLAY_SEL_GPIO	59	/* LCD2/PicoDLP switch */
-#define DLP_POWER_ON_GPIO	40
 
 #define GPIO_WIFI_PMENA		54
 #define GPIO_WIFI_IRQ		53
@@ -607,154 +600,6 @@ static void __init omap_sfh7741prox_init(void)
 			__func__, OMAP4_SFH7741_ENABLE_GPIO, error);
 }
 
-static struct nokia_dsi_panel_data dsi1_panel = {
-		.name		= "taal",
-		.reset_gpio	= 102,
-		.use_ext_te	= false,
-		.ext_te_gpio	= 101,
-		.esd_interval	= 0,
-		.pin_config = {
-			.num_pins	= 6,
-			.pins		= { 0, 1, 2, 3, 4, 5 },
-		},
-};
-
-static struct omap_dss_device sdp4430_lcd_device = {
-	.name			= "lcd",
-	.driver_name		= "taal",
-	.type			= OMAP_DISPLAY_TYPE_DSI,
-	.data			= &dsi1_panel,
-	.phy.dsi		= {
-		.module		= 0,
-	},
-	.channel		= OMAP_DSS_CHANNEL_LCD,
-};
-
-static struct nokia_dsi_panel_data dsi2_panel = {
-		.name		= "taal",
-		.reset_gpio	= 104,
-		.use_ext_te	= false,
-		.ext_te_gpio	= 103,
-		.esd_interval	= 0,
-		.pin_config = {
-			.num_pins	= 6,
-			.pins		= { 0, 1, 2, 3, 4, 5 },
-		},
-};
-
-static struct omap_dss_device sdp4430_lcd2_device = {
-	.name			= "lcd2",
-	.driver_name		= "taal",
-	.type			= OMAP_DISPLAY_TYPE_DSI,
-	.data			= &dsi2_panel,
-	.phy.dsi		= {
-
-		.module		= 1,
-	},
-	.channel		= OMAP_DSS_CHANNEL_LCD2,
-};
-
-static struct omap_dss_hdmi_data sdp4430_hdmi_data = {
-	.ct_cp_hpd_gpio = HDMI_GPIO_CT_CP_HPD,
-	.ls_oe_gpio = HDMI_GPIO_LS_OE,
-	.hpd_gpio = HDMI_GPIO_HPD,
-};
-
-static struct omap_dss_device sdp4430_hdmi_device = {
-	.name = "hdmi",
-	.driver_name = "hdmi_panel",
-	.type = OMAP_DISPLAY_TYPE_HDMI,
-	.channel = OMAP_DSS_CHANNEL_DIGIT,
-	.data = &sdp4430_hdmi_data,
-};
-
-static struct picodlp_panel_data sdp4430_picodlp_pdata = {
-	.picodlp_adapter_id	= 2,
-	.emu_done_gpio		= 44,
-	.pwrgood_gpio		= 45,
-};
-
-static void sdp4430_picodlp_init(void)
-{
-	int r;
-	const struct gpio picodlp_gpios[] = {
-		{DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW,
-			"DLP POWER ON"},
-		{sdp4430_picodlp_pdata.emu_done_gpio, GPIOF_IN,
-			"DLP EMU DONE"},
-		{sdp4430_picodlp_pdata.pwrgood_gpio, GPIOF_OUT_INIT_LOW,
-			"DLP PWRGOOD"},
-	};
-
-	r = gpio_request_array(picodlp_gpios, ARRAY_SIZE(picodlp_gpios));
-	if (r)
-		pr_err("Cannot request PicoDLP GPIOs, error %d\n", r);
-}
-
-static int sdp4430_panel_enable_picodlp(struct omap_dss_device *dssdev)
-{
-	gpio_set_value(DISPLAY_SEL_GPIO, 0);
-	gpio_set_value(DLP_POWER_ON_GPIO, 1);
-
-	return 0;
-}
-
-static void sdp4430_panel_disable_picodlp(struct omap_dss_device *dssdev)
-{
-	gpio_set_value(DLP_POWER_ON_GPIO, 0);
-	gpio_set_value(DISPLAY_SEL_GPIO, 1);
-}
-
-static struct omap_dss_device sdp4430_picodlp_device = {
-	.name			= "picodlp",
-	.driver_name		= "picodlp_panel",
-	.type			= OMAP_DISPLAY_TYPE_DPI,
-	.phy.dpi.data_lines	= 24,
-	.channel		= OMAP_DSS_CHANNEL_LCD2,
-	.platform_enable	= sdp4430_panel_enable_picodlp,
-	.platform_disable	= sdp4430_panel_disable_picodlp,
-	.data			= &sdp4430_picodlp_pdata,
-};
-
-static struct omap_dss_device *sdp4430_dss_devices[] = {
-	&sdp4430_lcd_device,
-	&sdp4430_lcd2_device,
-	&sdp4430_hdmi_device,
-	&sdp4430_picodlp_device,
-};
-
-static struct omap_dss_board_info sdp4430_dss_data = {
-	.num_devices	= ARRAY_SIZE(sdp4430_dss_devices),
-	.devices	= sdp4430_dss_devices,
-	.default_device	= &sdp4430_lcd_device,
-};
-
-static void __init omap_4430sdp_display_init(void)
-{
-	int r;
-
-	/* Enable LCD2 by default (instead of Pico DLP) */
-	r = gpio_request_one(DISPLAY_SEL_GPIO, GPIOF_OUT_INIT_HIGH,
-			"display_sel");
-	if (r)
-		pr_err("%s: Could not get display_sel GPIO\n", __func__);
-
-	sdp4430_picodlp_init();
-	omap_display_init(&sdp4430_dss_data);
-	/*
-	 * OMAP4460SDP/Blaze and OMAP4430 ES2.3 SDP/Blaze boards and
-	 * later have external pull up on the HDMI I2C lines
-	 */
-	if (cpu_is_omap446x() || omap_rev() > OMAP4430_REV_ES2_2)
-		omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP);
-	else
-		omap_hdmi_init(0);
-
-	omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT);
-	omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT);
-	omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	OMAP4_MUX(USBB2_ULPITLL_CLK, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
@@ -881,5 +726,5 @@ MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
 	.init_machine	= omap_4430sdp_init,
 	.init_late	= omap4430_init_late,
 	.timer		= &omap4_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap44xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-am3517crane.c b/arch/arm/mach-omap2/board-am3517crane.c
index 318fead..51b96a1 100644
--- a/arch/arm/mach-omap2/board-am3517crane.c
+++ b/arch/arm/mach-omap2/board-am3517crane.c
@@ -26,7 +26,6 @@
 #include <asm/mach/map.h>
 
 #include "common.h"
-#include <plat/usb.h>
 
 #include "am35xx-emac.h"
 #include "mux.h"
@@ -94,5 +93,5 @@ MACHINE_START(CRANEBOARD, "AM3517/05 CRANEBOARD")
 	.init_machine	= am3517_crane_init,
 	.init_late	= am35xx_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index e162897..4be58fd 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -25,6 +25,7 @@
 #include <linux/can/platform/ti_hecc.h>
 #include <linux/davinci_emac.h>
 #include <linux/mmc/host.h>
+#include <linux/usb/musb.h>
 #include <linux/platform_data/gpio-omap.h>
 
 #include "am35xx.h"
@@ -33,7 +34,6 @@
 #include <asm/mach/map.h>
 
 #include "common.h"
-#include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
 #include <video/omap-panel-tfp410.h>
@@ -393,5 +393,5 @@ MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
 	.init_machine	= am3517_evm_init,
 	.init_late	= am35xx_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index cea3aba..5d0a61f 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -28,14 +28,14 @@
 #include <linux/clk.h>
 #include <linux/smc91x.h>
 #include <linux/gpio.h>
+#include <linux/platform_data/leds-omap.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
-#include <plat/led.h>
 #include "common.h"
-#include <plat/gpmc.h>
+#include "gpmc.h"
 
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
@@ -338,5 +338,5 @@ MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
 	.init_machine	= omap_apollon_init,
 	.init_late	= omap2420_init_late,
 	.timer		= &omap2_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap2xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 376d26e..c8e37dc 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -38,21 +38,19 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include "common.h"
 #include <linux/platform_data/mtd-nand-omap2.h>
-#include <plat/gpmc.h>
-#include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
 #include <video/omap-panel-tfp410.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
-#include <mach/hardware.h>
-
+#include "common.h"
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "hsmmc.h"
 #include "common-board-devices.h"
+#include "gpmc.h"
+#include "gpmc-nand.h"
 
 #define CM_T35_GPIO_PENDOWN		57
 #define SB_T35_USB_HUB_RESET_GPIO	167
@@ -181,7 +179,7 @@ static struct omap_nand_platform_data cm_t35_nand_data = {
 
 static void __init cm_t35_init_nand(void)
 {
-	if (gpmc_nand_init(&cm_t35_nand_data) < 0)
+	if (gpmc_nand_init(&cm_t35_nand_data, NULL) < 0)
 		pr_err("CM-T35: Unable to register NAND device\n");
 }
 #else
@@ -753,18 +751,18 @@ MACHINE_START(CM_T35, "Compulab CM-T35")
 	.init_machine	= cm_t35_init,
 	.init_late	= omap35xx_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
 
 MACHINE_START(CM_T3730, "Compulab CM-T3730")
-	.atag_offset    = 0x100,
-	.reserve        = omap_reserve,
-	.map_io         = omap3_map_io,
-	.init_early     = omap3630_init_early,
-	.init_irq       = omap3_init_irq,
+	.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   = cm_t3730_init,
+	.init_machine	= cm_t3730_init,
 	.init_late     = omap3630_init_late,
-	.timer          = &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.timer		= &omap3_timer,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index 59c0a45..699caec 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -39,9 +39,8 @@
 #include <asm/mach/map.h>
 
 #include "common.h"
-#include <plat/usb.h>
 #include <linux/platform_data/mtd-nand-omap2.h>
-#include <plat/gpmc.h>
+#include "gpmc.h"
 
 #include "am35xx.h"
 
@@ -49,6 +48,7 @@
 #include "control.h"
 #include "common-board-devices.h"
 #include "am35xx-emac.h"
+#include "gpmc-nand.h"
 
 #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
 static struct gpio_led cm_t3517_leds[] = {
@@ -240,7 +240,7 @@ static struct omap_nand_platform_data cm_t3517_nand_data = {
 
 static void __init cm_t3517_init_nand(void)
 {
-	if (gpmc_nand_init(&cm_t3517_nand_data) < 0)
+	if (gpmc_nand_init(&cm_t3517_nand_data, NULL) < 0)
 		pr_err("CM-T3517: NAND initialization failed\n");
 }
 #else
@@ -298,5 +298,5 @@ MACHINE_START(CM_T3517, "Compulab CM-T3517")
 	.init_machine	= cm_t3517_init,
 	.init_late	= am35xx_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 1fd161e..7667eb7 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -39,9 +39,8 @@
 #include <asm/mach/flash.h>
 
 #include "common.h"
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <linux/platform_data/mtd-nand-omap2.h>
-#include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
 #include <video/omap-panel-tfp410.h>
@@ -55,8 +54,11 @@
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "mux.h"
 #include "hsmmc.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
+#define	NAND_CS			0
+
 #define OMAP_DM9000_GPIO_IRQ	25
 #define OMAP3_DEVKIT_TS_GPIO	27
 
@@ -621,8 +623,9 @@ static void __init devkit8000_init(void)
 
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions,
-			     ARRAY_SIZE(devkit8000_nand_partitions));
+	board_nand_init(devkit8000_nand_partitions,
+			ARRAY_SIZE(devkit8000_nand_partitions), NAND_CS,
+			NAND_BUSWIDTH_16, NULL);
 	omap_twl4030_audio_init("omap3beagle");
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
@@ -640,5 +643,5 @@ MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000")
 	.init_machine	= devkit8000_init,
 	.init_late	= omap35xx_init_late,
 	.timer		= &omap3_secure_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index e642acf..c33adea 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -17,14 +17,14 @@
 #include <linux/mtd/physmap.h>
 #include <linux/io.h>
 
-#include <plat/cpu.h>
-#include <plat/gpmc.h>
 #include <linux/platform_data/mtd-nand-omap2.h>
 #include <linux/platform_data/mtd-onenand-omap2.h>
-#include <plat/tc.h>
 
+#include "soc.h"
 #include "common.h"
 #include "board-flash.h"
+#include "gpmc-onenand.h"
+#include "gpmc-nand.h"
 
 #define REG_FPGA_REV			0x10
 #define REG_FPGA_DIP_SWITCH_INPUT2	0x60
@@ -104,36 +104,35 @@ __init board_onenand_init(struct mtd_partition *onenand_parts,
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE)
 
 /* Note that all values in this struct are in nanoseconds */
-static struct gpmc_timings nand_timings = {
+struct gpmc_timings nand_default_timings[1] = {
+	{
+		.sync_clk = 0,
 
-	.sync_clk = 0,
+		.cs_on = 0,
+		.cs_rd_off = 36,
+		.cs_wr_off = 36,
 
-	.cs_on = 0,
-	.cs_rd_off = 36,
-	.cs_wr_off = 36,
+		.adv_on = 6,
+		.adv_rd_off = 24,
+		.adv_wr_off = 36,
 
-	.adv_on = 6,
-	.adv_rd_off = 24,
-	.adv_wr_off = 36,
+		.we_off = 30,
+		.oe_off = 48,
 
-	.we_off = 30,
-	.oe_off = 48,
+		.access = 54,
+		.rd_cycle = 72,
+		.wr_cycle = 72,
 
-	.access = 54,
-	.rd_cycle = 72,
-	.wr_cycle = 72,
-
-	.wr_access = 30,
-	.wr_data_mux_bus = 0,
+		.wr_access = 30,
+		.wr_data_mux_bus = 0,
+	},
 };
 
-static struct omap_nand_platform_data board_nand_data = {
-	.gpmc_t		= &nand_timings,
-};
+static struct omap_nand_platform_data board_nand_data;
 
 void
-__init board_nand_init(struct mtd_partition *nand_parts,
-			u8 nr_parts, u8 cs, int nand_type)
+__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
+				int nand_type, struct gpmc_timings *gpmc_t)
 {
 	board_nand_data.cs		= cs;
 	board_nand_data.parts		= nand_parts;
@@ -141,7 +140,7 @@ __init board_nand_init(struct mtd_partition *nand_parts,
 	board_nand_data.devsize		= nand_type;
 
 	board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT;
-	gpmc_nand_init(&board_nand_data);
+	gpmc_nand_init(&board_nand_data, gpmc_t);
 }
 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
 
@@ -238,5 +237,6 @@ void __init board_flash_init(struct flash_partitions partition_info[],
 		pr_err("NAND: Unable to find configuration in GPMC\n");
 	else
 		board_nand_init(partition_info[2].parts,
-			partition_info[2].nr_parts, nandcs, nand_type);
+			partition_info[2].nr_parts, nandcs,
+			nand_type, nand_default_timings);
 }
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
index c44b70d..2fb5d41 100644
--- a/arch/arm/mach-omap2/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -12,7 +12,7 @@
  */
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
-#include <plat/gpmc.h>
+#include "gpmc.h"
 
 #define PDC_NOR		1
 #define PDC_NAND	2
@@ -40,12 +40,14 @@ static inline void board_flash_init(struct flash_partitions part[],
 #if defined(CONFIG_MTD_NAND_OMAP2) || \
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE)
 extern void board_nand_init(struct mtd_partition *nand_parts,
-					u8 nr_parts, u8 cs, int nand_type);
+		u8 nr_parts, u8 cs, int nand_type, struct gpmc_timings *gpmc_t);
+extern struct gpmc_timings nand_default_timings[];
 #else
 static inline void board_nand_init(struct mtd_partition *nand_parts,
-					u8 nr_parts, u8 cs, int nand_type)
+		u8 nr_parts, u8 cs, int nand_type, struct gpmc_timings *gpmc_t)
 {
 }
+#define	nand_default_timings	NULL
 #endif
 
 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 601ecdf..53cb380b 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -21,6 +21,7 @@
 
 #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
@@ -40,6 +41,15 @@ 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();
+	else if (of_machine_is_compatible("ti,omap4-sdp"))
+		omap_4430sdp_display_init_of();
 }
 
 #ifdef CONFIG_SOC_OMAP2420
@@ -57,7 +67,7 @@ DT_MACHINE_START(OMAP242X_DT, "Generic OMAP2420 (Flattened Device Tree)")
 	.init_machine	= omap_generic_init,
 	.timer		= &omap2_timer,
 	.dt_compat	= omap242x_boards_compat,
-	.restart	= omap_prcm_restart,
+	.restart	= omap2xxx_restart,
 MACHINE_END
 #endif
 
@@ -76,7 +86,7 @@ DT_MACHINE_START(OMAP243X_DT, "Generic OMAP2430 (Flattened Device Tree)")
 	.init_machine	= omap_generic_init,
 	.timer		= &omap2_timer,
 	.dt_compat	= omap243x_boards_compat,
-	.restart	= omap_prcm_restart,
+	.restart	= omap2xxx_restart,
 MACHINE_END
 #endif
 
@@ -95,7 +105,24 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
 	.init_machine	= omap_generic_init,
 	.timer		= &omap3_timer,
 	.dt_compat	= omap3_boards_compat,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
+MACHINE_END
+
+static const char *omap3_gp_boards_compat[] __initdata = {
+	"ti,omap3-beagle",
+	NULL,
+};
+
+DT_MACHINE_START(OMAP3_GP_DT, "Generic OMAP3-GP (Flattened Device Tree)")
+	.reserve	= omap_reserve,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3430_init_early,
+	.init_irq	= omap_intc_of_init,
+	.handle_irq	= omap3_intc_handle_irq,
+	.init_machine	= omap_generic_init,
+	.timer		= &omap3_secure_timer,
+	.dt_compat	= omap3_gp_boards_compat,
+	.restart	= omap3xxx_restart,
 MACHINE_END
 #endif
 
@@ -134,7 +161,7 @@ DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)")
 	.init_late	= omap4430_init_late,
 	.timer		= &omap4_timer,
 	.dt_compat	= omap4_boards_compat,
-	.restart	= omap_prcm_restart,
+	.restart	= omap44xx_restart,
 MACHINE_END
 #endif
 
@@ -154,6 +181,6 @@ DT_MACHINE_START(OMAP5_DT, "Generic OMAP5 (Flattened Device Tree)")
 	.init_machine	= omap_generic_init,
 	.timer		= &omap5_timer,
 	.dt_compat	= omap5_boards_compat,
-	.restart	= omap_prcm_restart,
+	.restart	= omap44xx_restart,
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 8d04bf8..b626dbe 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -26,15 +26,14 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/input/matrix_keypad.h>
+#include <linux/mfd/menelaus.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/menelaus.h>
-#include <plat/dma.h>
-#include <plat/gpmc.h>
-#include "debug-devices.h"
+#include <plat-omap/dma-omap.h>
+#include <plat/debug-devices.h>
 
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
@@ -42,6 +41,7 @@
 #include "common.h"
 #include "mux.h"
 #include "control.h"
+#include "gpmc.h"
 
 #define H4_FLASH_CS	0
 #define H4_SMC91X_CS	1
@@ -386,5 +386,5 @@ MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
 	.init_machine	= omap_h4_init,
 	.init_late	= omap2420_init_late,
 	.timer		= &omap2_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap2xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 3785906..0f24cb8 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -29,20 +29,19 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include "common.h"
-#include <plat/gpmc.h>
-#include <plat/usb.h>
-
 #include <video/omapdss.h>
 #include <video/omap-panel-tfp410.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
@@ -175,7 +174,7 @@ static void __init igep_flash_init(void)
 		pr_info("IGEP: initializing NAND memory device\n");
 		board_nand_init(igep_flash_partitions,
 				ARRAY_SIZE(igep_flash_partitions),
-				0, NAND_BUSWIDTH_16);
+				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,
@@ -657,7 +656,7 @@ MACHINE_START(IGEP0020, "IGEP v2 board")
 	.init_machine	= igep_init,
 	.init_late	= omap35xx_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
 
 MACHINE_START(IGEP0030, "IGEP OMAP3 module")
@@ -670,5 +669,5 @@ MACHINE_START(IGEP0030, "IGEP OMAP3 module")
 	.init_machine	= igep_init,
 	.init_late	= omap35xx_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index ee8c3cf..0869f4f 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -35,9 +35,8 @@
 #include <asm/mach/map.h>
 
 #include "common.h"
-#include <plat/gpmc.h>
-#include <mach/board-zoom.h>
-#include <plat/usb.h>
+#include "board-zoom.h"
+#include "gpmc.h"
 #include "gpmc-smsc911x.h"
 
 #include <video/omapdss.h>
@@ -420,8 +419,8 @@ static void __init omap_ldp_init(void)
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
 	usb_musb_init(NULL);
-	board_nand_init(ldp_nand_partitions,
-		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
+	board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions),
+			ZOOM_NAND_CS, 0, nand_default_timings);
 
 	omap_hsmmc_init(mmc);
 	ldp_display_init();
@@ -437,5 +436,5 @@ MACHINE_START(OMAP_LDP, "OMAP LDP board")
 	.init_machine	= omap_ldp_init,
 	.init_late	= omap3430_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index d95f727..0abb30f 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -16,22 +16,25 @@
 #include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/irq.h>
 #include <linux/stddef.h>
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
 #include <linux/usb/musb.h>
+#include <linux/platform_data/i2c-cbus-gpio.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/platform_data/mtd-onenand-omap2.h>
+#include <linux/mfd/menelaus.h>
 #include <sound/tlv320aic3x.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
 #include "common.h"
-#include <plat/menelaus.h>
-#include <plat/mmc.h>
+#include "mmc.h"
 
 #include "mux.h"
+#include "gpmc-onenand.h"
 
 #define TUSB6010_ASYNC_CS	1
 #define TUSB6010_SYNC_CS	4
@@ -39,6 +42,45 @@
 #define TUSB6010_GPIO_ENABLE	0
 #define TUSB6010_DMACHAN	0x3f
 
+#if defined(CONFIG_I2C_CBUS_GPIO) || defined(CONFIG_I2C_CBUS_GPIO_MODULE)
+static struct i2c_cbus_platform_data n8x0_cbus_data = {
+	.clk_gpio = 66,
+	.dat_gpio = 65,
+	.sel_gpio = 64,
+};
+
+static struct platform_device n8x0_cbus_device = {
+	.name	= "i2c-cbus-gpio",
+	.id	= 3,
+	.dev	= {
+		.platform_data = &n8x0_cbus_data,
+	},
+};
+
+static struct i2c_board_info n8x0_i2c_board_info_3[] __initdata = {
+	{
+		I2C_BOARD_INFO("retu-mfd", 0x01),
+	},
+};
+
+static void __init n8x0_cbus_init(void)
+{
+	const int retu_irq_gpio = 108;
+
+	if (gpio_request_one(retu_irq_gpio, GPIOF_IN, "Retu IRQ"))
+		return;
+	irq_set_irq_type(gpio_to_irq(retu_irq_gpio), IRQ_TYPE_EDGE_RISING);
+	n8x0_i2c_board_info_3[0].irq = gpio_to_irq(retu_irq_gpio);
+	i2c_register_board_info(3, n8x0_i2c_board_info_3,
+				ARRAY_SIZE(n8x0_i2c_board_info_3));
+	platform_device_register(&n8x0_cbus_device);
+}
+#else /* CONFIG_I2C_CBUS_GPIO */
+static void __init n8x0_cbus_init(void)
+{
+}
+#endif /* CONFIG_I2C_CBUS_GPIO */
+
 #if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
 /*
  * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and
@@ -677,6 +719,7 @@ static void __init n8x0_init_machine(void)
 	gpmc_onenand_init(board_onenand_data);
 	n8x0_mmc_init();
 	n8x0_usb_init();
+	n8x0_cbus_init();
 }
 
 MACHINE_START(NOKIA_N800, "Nokia N800")
@@ -689,7 +732,7 @@ MACHINE_START(NOKIA_N800, "Nokia N800")
 	.init_machine	= n8x0_init_machine,
 	.init_late	= omap2420_init_late,
 	.timer		= &omap2_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap2xxx_restart,
 MACHINE_END
 
 MACHINE_START(NOKIA_N810, "Nokia N810")
@@ -702,7 +745,7 @@ MACHINE_START(NOKIA_N810, "Nokia N810")
 	.init_machine	= n8x0_init_machine,
 	.init_late	= omap2420_init_late,
 	.timer		= &omap2_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap2xxx_restart,
 MACHINE_END
 
 MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
@@ -715,5 +758,5 @@ MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
 	.init_machine	= n8x0_init_machine,
 	.init_late	= omap2420_init_late,
 	.timer		= &omap2_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap2xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index d41ab98..22c483d 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -39,19 +39,22 @@
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 
-#include "common.h"
 #include <video/omapdss.h>
 #include <video/omap-panel-tfp410.h>
-#include <plat/gpmc.h>
 #include <linux/platform_data/mtd-nand-omap2.h>
-#include <plat/usb.h>
-#include <plat/omap_device.h>
 
+#include "common.h"
+#include "omap_device.h"
+#include "gpmc.h"
+#include "soc.h"
 #include "mux.h"
 #include "hsmmc.h"
 #include "pm.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
+#define	NAND_CS	0
+
 /*
  * OMAP3 Beagle revision
  * Run time detection of Beagle revision is done by reading GPIO.
@@ -518,8 +521,9 @@ static void __init omap3_beagle_init(void)
 
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions,
-			     ARRAY_SIZE(omap3beagle_nand_partitions));
+	board_nand_init(omap3beagle_nand_partitions,
+			ARRAY_SIZE(omap3beagle_nand_partitions), NAND_CS,
+			NAND_BUSWIDTH_16, NULL);
 	omap_twl4030_audio_init("omap3beagle");
 
 	/* Ensure msecure is mux'd to be able to set the RTC. */
@@ -541,5 +545,5 @@ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
 	.init_machine	= omap3_beagle_init,
 	.init_late	= omap3_init_late,
 	.timer		= &omap3_secure_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index b9b776b..54647d6 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -32,6 +32,7 @@
 #include <linux/spi/ads7846.h>
 #include <linux/i2c/twl.h>
 #include <linux/usb/otg.h>
+#include <linux/usb/musb.h>
 #include <linux/usb/nop-usb-xceiv.h>
 #include <linux/smsc911x.h>
 
@@ -45,17 +46,20 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/usb.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-tfp410.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
@@ -731,8 +735,9 @@ static void __init omap3_evm_init(void)
 	}
 	usb_musb_init(&musb_board_data);
 	usbhs_init(&usbhs_bdata);
-	omap_nand_flash_init(NAND_BUSWIDTH_16, omap3evm_nand_partitions,
-			     ARRAY_SIZE(omap3evm_nand_partitions));
+	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();
@@ -752,5 +757,5 @@ MACHINE_START(OMAP3EVM, "OMAP3 EVM")
 	.init_machine	= omap3_evm_init,
 	.init_late	= omap35xx_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 7bd8253..2a065ba 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -34,16 +34,13 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include "gpmc-smsc911x.h"
-#include <plat/gpmc.h>
-#include <plat/sdrc.h>
-#include <plat/usb.h>
-
 #include "common.h"
 #include "mux.h"
 #include "hsmmc.h"
 #include "control.h"
 #include "common-board-devices.h"
+#include "gpmc.h"
+#include "gpmc-smsc911x.h"
 
 #define OMAP3LOGIC_SMSC911X_CS			1
 
@@ -235,7 +232,7 @@ MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board")
 	.init_machine	= omap3logic_init,
 	.init_late	= omap35xx_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
 
 MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board")
@@ -248,5 +245,5 @@ MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board")
 	.init_machine	= omap3logic_init,
 	.init_late	= omap35xx_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 00a1f4a..a53a668 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -42,7 +42,6 @@
 #include <asm/mach/map.h>
 
 #include "common.h"
-#include <plat/usb.h>
 #include <video/omapdss.h>
 #include <linux/platform_data/mtd-nand-omap2.h>
 
@@ -50,6 +49,7 @@
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "hsmmc.h"
 #include "common-board-devices.h"
+#include "gpmc-nand.h"
 
 #define PANDORA_WIFI_IRQ_GPIO		21
 #define PANDORA_WIFI_NRESET_GPIO	23
@@ -602,7 +602,7 @@ static void __init omap3pandora_init(void)
 	omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL);
 	usbhs_init(&usbhs_bdata);
 	usb_musb_init(NULL);
-	gpmc_nand_init(&pandora_nand_data);
+	gpmc_nand_init(&pandora_nand_data, NULL);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
@@ -619,5 +619,5 @@ MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console")
 	.init_machine	= omap3pandora_init,
 	.init_late	= omap35xx_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 731235e..d8638b3 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -40,9 +40,8 @@
 #include <asm/mach/flash.h>
 
 #include "common.h"
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <linux/platform_data/mtd-nand-omap2.h>
-#include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
 #include <video/omap-panel-tfp410.h>
@@ -428,5 +427,5 @@ MACHINE_START(SBC3530, "OMAP3 STALKER")
 	.init_machine		= omap3_stalker_init,
 	.init_late		= omap35xx_init_late,
 	.timer			= &omap3_secure_timer,
-	.restart		= omap_prcm_restart,
+	.restart		= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 944ffc4..263cb9c 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -44,12 +44,12 @@
 #include <asm/system_info.h>
 
 #include "common.h"
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <linux/platform_data/mtd-nand-omap2.h>
-#include <plat/usb.h>
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 #include <asm/setup.h>
@@ -59,6 +59,8 @@
 #define TB_BL_PWM_TIMER		9
 #define TB_KILL_POWER_GPIO	168
 
+#define	NAND_CS			0
+
 static unsigned long touchbook_revision;
 
 static struct mtd_partition omap3touchbook_nand_partitions[] = {
@@ -365,8 +367,9 @@ static void __init omap3_touchbook_init(void)
 	omap_ads7846_init(4, OMAP3_TS_GPIO, 310, &ads7846_pdata);
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	omap_nand_flash_init(NAND_BUSWIDTH_16, omap3touchbook_nand_partitions,
-			     ARRAY_SIZE(omap3touchbook_nand_partitions));
+	board_nand_init(omap3touchbook_nand_partitions,
+			ARRAY_SIZE(omap3touchbook_nand_partitions), NAND_CS,
+			NAND_BUSWIDTH_16, NULL);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
@@ -384,5 +387,5 @@ MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board")
 	.init_machine	= omap3_touchbook_init,
 	.init_late	= omap3430_init_late,
 	.timer		= &omap3_secure_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index bfcd397..5c8e9ce 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -29,6 +29,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 #include <linux/ti_wilink_st.h>
+#include <linux/usb/musb.h>
 #include <linux/wl12xx.h>
 #include <linux/platform_data/omap-abe-twl6040.h>
 
@@ -36,26 +37,20 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
-#include <video/omapdss.h>
 
 #include "common.h"
-#include <plat/usb.h>
-#include <plat/mmc.h>
-#include <video/omap-panel-tfp410.h>
-
 #include "soc.h"
+#include "mmc.h"
 #include "hsmmc.h"
 #include "control.h"
 #include "mux.h"
 #include "common-board-devices.h"
+#include "dss-common.h"
 
 #define GPIO_HUB_POWER		1
 #define GPIO_HUB_NRESET		62
 #define GPIO_WIFI_PMENA		43
 #define GPIO_WIFI_IRQ		53
-#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */
-#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
-#define HDMI_GPIO_HPD  63 /* Hotplug detect */
 
 /* wl127x BT, FM, GPS connectivity chip */
 static struct ti_st_plat_data wilink_platform_data = {
@@ -409,68 +404,6 @@ static struct omap_board_mux board_mux[] __initdata = {
 #define board_mux	NULL
 #endif
 
-/* Display DVI */
-#define PANDA_DVI_TFP410_POWER_DOWN_GPIO	0
-
-/* Using generic display panel */
-static struct tfp410_platform_data omap4_dvi_panel = {
-	.i2c_bus_num		= 3,
-	.power_down_gpio	= PANDA_DVI_TFP410_POWER_DOWN_GPIO,
-};
-
-static struct omap_dss_device omap4_panda_dvi_device = {
-	.type			= OMAP_DISPLAY_TYPE_DPI,
-	.name			= "dvi",
-	.driver_name		= "tfp410",
-	.data			= &omap4_dvi_panel,
-	.phy.dpi.data_lines	= 24,
-	.reset_gpio		= PANDA_DVI_TFP410_POWER_DOWN_GPIO,
-	.channel		= OMAP_DSS_CHANNEL_LCD2,
-};
-
-static struct omap_dss_hdmi_data omap4_panda_hdmi_data = {
-	.ct_cp_hpd_gpio = HDMI_GPIO_CT_CP_HPD,
-	.ls_oe_gpio = HDMI_GPIO_LS_OE,
-	.hpd_gpio = HDMI_GPIO_HPD,
-};
-
-static struct omap_dss_device  omap4_panda_hdmi_device = {
-	.name = "hdmi",
-	.driver_name = "hdmi_panel",
-	.type = OMAP_DISPLAY_TYPE_HDMI,
-	.channel = OMAP_DSS_CHANNEL_DIGIT,
-	.data = &omap4_panda_hdmi_data,
-};
-
-static struct omap_dss_device *omap4_panda_dss_devices[] = {
-	&omap4_panda_dvi_device,
-	&omap4_panda_hdmi_device,
-};
-
-static struct omap_dss_board_info omap4_panda_dss_data = {
-	.num_devices	= ARRAY_SIZE(omap4_panda_dss_devices),
-	.devices	= omap4_panda_dss_devices,
-	.default_device	= &omap4_panda_dvi_device,
-};
-
-static void __init omap4_panda_display_init(void)
-{
-
-	omap_display_init(&omap4_panda_dss_data);
-
-	/*
-	 * OMAP4460SDP/Blaze and OMAP4430 ES2.3 SDP/Blaze boards and
-	 * later have external pull up on the HDMI I2C lines
-	 */
-	if (cpu_is_omap446x() || omap_rev() > OMAP4430_REV_ES2_2)
-		omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP);
-	else
-		omap_hdmi_init(0);
-
-	omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT);
-	omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT);
-	omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN);
-}
 
 static void omap4_panda_init_rev(void)
 {
@@ -524,5 +457,5 @@ MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
 	.init_machine	= omap4_panda_init,
 	.init_late	= omap4430_init_late,
 	.timer		= &omap4_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap44xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index b700685..c8fde3e 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -45,18 +45,20 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
 
-#include "common.h"
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
 #include <video/omap-panel-tfp410.h>
-#include <plat/gpmc.h>
-#include <plat/usb.h>
 
+#include "common.h"
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
+#include "gpmc.h"
 #include "hsmmc.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
+#define	NAND_CS			0
+
 #define OVERO_GPIO_BT_XGATE	15
 #define OVERO_GPIO_W2W_NRESET	16
 #define OVERO_GPIO_PENDOWN	114
@@ -495,8 +497,8 @@ static void __init overo_init(void)
 	omap_serial_init();
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
-	omap_nand_flash_init(0, overo_nand_partitions,
-			     ARRAY_SIZE(overo_nand_partitions));
+	board_nand_init(overo_nand_partitions,
+			ARRAY_SIZE(overo_nand_partitions), NAND_CS, 0, NULL);
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	overo_spi_init();
@@ -550,5 +552,5 @@ MACHINE_START(OVERO, "Gumstix Overo")
 	.init_machine	= overo_init,
 	.init_late	= omap35xx_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index 45997bf..0c777b7 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -1,5 +1,5 @@
 /*
- * Board support file for Nokia RM-680/696.
+ * Board support file for Nokia N950 (RM-680) / N9 (RM-696).
  *
  * Copyright (C) 2010 Nokia
  *
@@ -22,17 +22,14 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
-#include <plat/i2c.h>
-#include <plat/mmc.h>
-#include <plat/usb.h>
-#include <plat/gpmc.h>
 #include "common.h"
-#include <plat/serial.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"),
@@ -151,7 +148,7 @@ MACHINE_START(NOKIA_RM680, "Nokia RM-680 board")
 	.init_machine	= rm680_init,
 	.init_late	= omap3630_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
 
 MACHINE_START(NOKIA_RM696, "Nokia RM-696 board")
@@ -164,5 +161,5 @@ MACHINE_START(NOKIA_RM696, "Nokia RM-696 board")
 	.init_machine	= rm680_init,
 	.init_late	= omap3630_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.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 020e03c..07005fe 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -31,9 +31,7 @@
 #include <asm/system_info.h>
 
 #include "common.h"
-#include <plat/dma.h>
-#include <plat/gpmc.h>
-#include <plat/omap-pm.h>
+#include <plat-omap/dma-omap.h>
 #include "gpmc-smc91x.h"
 
 #include "board-rx51.h"
@@ -52,8 +50,11 @@
 #endif
 
 #include "mux.h"
+#include "omap-pm.h"
 #include "hsmmc.h"
 #include "common-board-devices.h"
+#include "gpmc.h"
+#include "gpmc-onenand.h"
 
 #define SYSTEM_REV_B_USES_VAUX3	0x1699
 #define SYSTEM_REV_S_USES_VAUX3 0x8
diff --git a/arch/arm/mach-omap2/board-rx51-video.c b/arch/arm/mach-omap2/board-rx51-video.c
index c22e111..46f4fc9 100644
--- a/arch/arm/mach-omap2/board-rx51-video.c
+++ b/arch/arm/mach-omap2/board-rx51-video.c
@@ -16,7 +16,6 @@
 #include <linux/mm.h>
 #include <asm/mach-types.h>
 #include <video/omapdss.h>
-#include <plat/vram.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
 #include "board-rx51.h"
@@ -87,17 +86,4 @@ static int __init rx51_video_init(void)
 }
 
 subsys_initcall(rx51_video_init);
-
-void __init rx51_video_mem_init(void)
-{
-	/*
-	 * GFX 864x480x32bpp
-	 * VID1/2 1280x720x32bpp double buffered
-	 */
-	omap_vram_set_sdram_vram(PAGE_ALIGN(864 * 480 * 4) +
-			2 * PAGE_ALIGN(1280 * 720 * 4 * 2), 0);
-}
-
-#else
-void __init rx51_video_mem_init(void) { }
 #endif /* defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) */
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index 7bbb05d..91c8344 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-omap2/board-rx51.c
+ * Board support file for Nokia N900 (aka RX-51).
  *
  * Copyright (C) 2007, 2008 Nokia
  *
@@ -17,25 +17,23 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
+#include <linux/usb/musb.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include "common.h"
-#include <plat/dma.h>
-#include <plat/gpmc.h>
-#include <plat/usb.h>
+#include <plat-omap/dma-omap.h>
 
+#include "common.h"
 #include "mux.h"
+#include "gpmc.h"
 #include "pm.h"
 #include "sdram-nokia.h"
 
 #define RX51_GPIO_SLEEP_IND 162
 
-extern void rx51_video_mem_init(void);
-
 static struct gpio_led gpio_leds[] = {
 	{
 		.name	= "sleep_ind",
@@ -112,7 +110,6 @@ static void __init rx51_init(void)
 
 static void __init rx51_reserve(void)
 {
-	rx51_video_mem_init();
 	omap_reserve();
 }
 
@@ -127,5 +124,5 @@ MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
 	.init_machine	= rx51_init,
 	.init_late	= omap3430_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-ti8168evm.c b/arch/arm/mach-omap2/board-ti8168evm.c
index c4f8833..1a3e056 100644
--- a/arch/arm/mach-omap2/board-ti8168evm.c
+++ b/arch/arm/mach-omap2/board-ti8168evm.c
@@ -14,13 +14,14 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/usb/musb.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
 #include "common.h"
-#include <plat/usb.h>
 
 static struct omap_musb_board_data musb_board_data = {
 	.set_phy_power	= ti81xx_musb_phy_power,
@@ -45,7 +46,7 @@ MACHINE_START(TI8168EVM, "ti8168evm")
 	.timer		= &omap3_timer,
 	.init_machine	= ti81xx_evm_init,
 	.init_late	= ti81xx_init_late,
-	.restart	= omap_prcm_restart,
+	.restart	= omap44xx_restart,
 MACHINE_END
 
 MACHINE_START(TI8148EVM, "ti8148evm")
@@ -57,5 +58,5 @@ MACHINE_START(TI8148EVM, "ti8148evm")
 	.timer		= &omap3_timer,
 	.init_machine	= ti81xx_evm_init,
 	.init_late	= ti81xx_init_late,
-	.restart	= omap_prcm_restart,
+	.restart	= omap44xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-zoom-debugboard.c b/arch/arm/mach-omap2/board-zoom-debugboard.c
index afb2278..42e5f23 100644
--- a/arch/arm/mach-omap2/board-zoom-debugboard.c
+++ b/arch/arm/mach-omap2/board-zoom-debugboard.c
@@ -17,10 +17,10 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include "gpmc-smsc911x.h"
 
-#include <mach/board-zoom.h>
+#include "board-zoom.h"
 
 #include "soc.h"
 #include "common.h"
diff --git a/arch/arm/mach-omap2/board-zoom-display.c b/arch/arm/mach-omap2/board-zoom-display.c
index b940ab2..1c7c834 100644
--- a/arch/arm/mach-omap2/board-zoom-display.c
+++ b/arch/arm/mach-omap2/board-zoom-display.c
@@ -16,8 +16,9 @@
 #include <linux/spi/spi.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <video/omapdss.h>
-#include <mach/board-zoom.h>
+#include "board-zoom.h"
 
+#include "soc.h"
 #include "common.h"
 
 #define LCD_PANEL_RESET_GPIO_PROD	96
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index c166fe1..26e07ad 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -26,9 +26,8 @@
 #include <asm/mach/map.h>
 
 #include "common.h"
-#include <plat/usb.h>
 
-#include <mach/board-zoom.h>
+#include "board-zoom.h"
 
 #include "mux.h"
 #include "hsmmc.h"
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
index 4994438..d7fa31e 100644
--- a/arch/arm/mach-omap2/board-zoom.c
+++ b/arch/arm/mach-omap2/board-zoom.c
@@ -22,9 +22,8 @@
 #include <asm/mach/arch.h>
 
 #include "common.h"
-#include <plat/usb.h>
 
-#include <mach/board-zoom.h>
+#include "board-zoom.h"
 
 #include "board-flash.h"
 #include "mux.h"
@@ -113,8 +112,9 @@ static void __init omap_zoom_init(void)
 		usbhs_init(&usbhs_bdata);
 	}
 
-	board_nand_init(zoom_nand_partitions, ARRAY_SIZE(zoom_nand_partitions),
-						ZOOM_NAND_CS, NAND_BUSWIDTH_16);
+	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();
 
@@ -138,7 +138,7 @@ MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
 	.init_machine	= omap_zoom_init,
 	.init_late	= omap3430_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
 
 MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
@@ -151,5 +151,5 @@ MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
 	.init_machine	= omap_zoom_init,
 	.init_late	= omap3630_init_late,
 	.timer		= &omap3_timer,
-	.restart	= omap_prcm_restart,
+	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-zoom.h b/arch/arm/mach-omap2/board-zoom.h
new file mode 100644
index 0000000..2e94869
--- /dev/null
+++ b/arch/arm/mach-omap2/board-zoom.h
@@ -0,0 +1,10 @@
+/*
+ * 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/cclock2420_data.c b/arch/arm/mach-omap2/cclock2420_data.c
new file mode 100644
index 0000000..7e5febe
--- /dev/null
+++ b/arch/arm/mach-omap2/cclock2420_data.c
@@ -0,0 +1,1950 @@
+/*
+ * OMAP2420 clock data
+ *
+ * Copyright (C) 2005-2012 Texas Instruments, Inc.
+ * Copyright (C) 2004-2011 Nokia Corporation
+ *
+ * Contacts:
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Paul Walmsley
+ * Updated to COMMON clk format by Rajendra Nayak <rnayak@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-private.h>
+#include <linux/list.h>
+
+#include "soc.h"
+#include "iomap.h"
+#include "clock.h"
+#include "clock2xxx.h"
+#include "opp2xxx.h"
+#include "cm2xxx.h"
+#include "prm2xxx.h"
+#include "prm-regbits-24xx.h"
+#include "cm-regbits-24xx.h"
+#include "sdrc.h"
+#include "control.h"
+
+#define OMAP_CM_REGADDR                 OMAP2420_CM_REGADDR
+
+/*
+ * 2420 clock tree.
+ *
+ * NOTE:In many cases here we are assigning a 'default' parent. In
+ *	many cases the parent is selectable. The set parent calls will
+ *	also switch sources.
+ *
+ *	Several sources are given initial rates which may be wrong, this will
+ *	be fixed up in the init func.
+ *
+ *	Things are broadly separated below by clock domains. It is
+ *	noteworthy that most peripherals have dependencies on multiple clock
+ *	domains. Many get their interface clocks from the L4 domain, but get
+ *	functional clocks from fixed sources or other core domain derived
+ *	clocks.
+ */
+
+DEFINE_CLK_FIXED_RATE(alt_ck, CLK_IS_ROOT, 54000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(func_32k_ck, CLK_IS_ROOT, 32768, 0x0);
+
+DEFINE_CLK_FIXED_RATE(mcbsp_clks, CLK_IS_ROOT, 0x0, 0x0);
+
+static struct clk osc_ck;
+
+static const struct clk_ops osc_ck_ops = {
+	.recalc_rate	= &omap2_osc_clk_recalc,
+};
+
+static struct clk_hw_omap osc_ck_hw = {
+	.hw = {
+		.clk = &osc_ck,
+	},
+};
+
+static struct clk osc_ck = {
+	.name	= "osc_ck",
+	.ops	= &osc_ck_ops,
+	.hw	= &osc_ck_hw.hw,
+	.flags	= CLK_IS_ROOT,
+};
+
+DEFINE_CLK_FIXED_RATE(secure_32k_ck, CLK_IS_ROOT, 32768, 0x0);
+
+static struct clk sys_ck;
+
+static const char *sys_ck_parent_names[] = {
+	"osc_ck",
+};
+
+static const struct clk_ops sys_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.recalc_rate	= &omap2xxx_sys_clk_recalc,
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(sys_ck, "wkup_clkdm");
+DEFINE_STRUCT_CLK(sys_ck, sys_ck_parent_names, sys_ck_ops);
+
+static struct dpll_data dpll_dd = {
+	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+	.mult_mask	= OMAP24XX_DPLL_MULT_MASK,
+	.div1_mask	= OMAP24XX_DPLL_DIV_MASK,
+	.clk_bypass	= &sys_ck,
+	.clk_ref	= &sys_ck,
+	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+	.enable_mask	= OMAP24XX_EN_DPLL_MASK,
+	.max_multiplier	= 1023,
+	.min_divider	= 1,
+	.max_divider	= 16,
+};
+
+static struct clk dpll_ck;
+
+static const char *dpll_ck_parent_names[] = {
+	"sys_ck",
+};
+
+static const struct clk_ops dpll_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.get_parent	= &omap2_init_dpll_parent,
+	.recalc_rate	= &omap2_dpllcore_recalc,
+	.round_rate	= &omap2_dpll_round_rate,
+	.set_rate	= &omap2_reprogram_dpllcore,
+};
+
+static struct clk_hw_omap dpll_ck_hw = {
+	.hw = {
+		.clk = &dpll_ck,
+	},
+	.ops		= &clkhwops_omap2xxx_dpll,
+	.dpll_data	= &dpll_dd,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll_ck, dpll_ck_parent_names, dpll_ck_ops);
+
+static struct clk core_ck;
+
+static const char *core_ck_parent_names[] = {
+	"dpll_ck",
+};
+
+static const struct clk_ops core_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(core_ck, "wkup_clkdm");
+DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops);
+
+DEFINE_CLK_DIVIDER(core_l3_ck, "core_ck", &core_ck, 0x0,
+		   OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+		   OMAP24XX_CLKSEL_L3_SHIFT, OMAP24XX_CLKSEL_L3_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+DEFINE_CLK_DIVIDER(l4_ck, "core_l3_ck", &core_l3_ck, 0x0,
+		   OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+		   OMAP24XX_CLKSEL_L4_SHIFT, OMAP24XX_CLKSEL_L4_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk aes_ick;
+
+static const char *aes_ick_parent_names[] = {
+	"l4_ck",
+};
+
+static const struct clk_ops aes_ick_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+};
+
+static struct clk_hw_omap aes_ick_hw = {
+	.hw = {
+		.clk = &aes_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+	.enable_bit	= OMAP24XX_EN_AES_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(aes_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk apll54_ck;
+
+static const struct clk_ops apll54_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_clk_apll54_enable,
+	.disable	= &omap2_clk_apll54_disable,
+	.recalc_rate	= &omap2_clk_apll54_recalc,
+};
+
+static struct clk_hw_omap apll54_ck_hw = {
+	.hw = {
+		.clk = &apll54_ck,
+	},
+	.ops		= &clkhwops_apll54,
+	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+	.enable_bit	= OMAP24XX_EN_54M_PLL_SHIFT,
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(apll54_ck, dpll_ck_parent_names, apll54_ck_ops);
+
+static struct clk apll96_ck;
+
+static const struct clk_ops apll96_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_clk_apll96_enable,
+	.disable	= &omap2_clk_apll96_disable,
+	.recalc_rate	= &omap2_clk_apll96_recalc,
+};
+
+static struct clk_hw_omap apll96_ck_hw = {
+	.hw = {
+		.clk = &apll96_ck,
+	},
+	.ops		= &clkhwops_apll96,
+	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+	.enable_bit	= OMAP24XX_EN_96M_PLL_SHIFT,
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(apll96_ck, dpll_ck_parent_names, apll96_ck_ops);
+
+static struct clk func_96m_ck;
+
+static const char *func_96m_ck_parent_names[] = {
+	"apll96_ck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(func_96m_ck, "wkup_clkdm");
+DEFINE_STRUCT_CLK(func_96m_ck, func_96m_ck_parent_names, core_ck_ops);
+
+static struct clk cam_fck;
+
+static const char *cam_fck_parent_names[] = {
+	"func_96m_ck",
+};
+
+static struct clk_hw_omap cam_fck_hw = {
+	.hw = {
+		.clk = &cam_fck,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(cam_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk cam_ick;
+
+static struct clk_hw_omap cam_ick_hw = {
+	.hw = {
+		.clk = &cam_ick,
+	},
+	.ops		= &clkhwops_iclk,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(cam_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk des_ick;
+
+static struct clk_hw_omap des_ick_hw = {
+	.hw = {
+		.clk = &des_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+	.enable_bit	= OMAP24XX_EN_DES_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(des_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate dsp_fck_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
+	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
+	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
+	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
+	{ .div = 12, .val = 12, .flags = RATE_IN_242X },
+	{ .div = 0 }
+};
+
+static const struct clksel dsp_fck_clksel[] = {
+	{ .parent = &core_ck, .rates = dsp_fck_core_rates },
+	{ .parent = NULL },
+};
+
+static const char *dsp_fck_parent_names[] = {
+	"core_ck",
+};
+
+static const struct clk_ops dsp_fck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.set_rate	= &omap2_clksel_set_rate,
+	.round_rate	= &omap2_clksel_round_rate,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(dsp_fck, "dsp_clkdm", dsp_fck_clksel,
+			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+			 OMAP24XX_CLKSEL_DSP_MASK,
+			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
+			 OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, &clkhwops_wait,
+			 dsp_fck_parent_names, dsp_fck_ops);
+
+static const struct clksel dsp_ick_clksel[] = {
+	{ .parent = &dsp_fck, .rates = dsp_ick_rates },
+	{ .parent = NULL },
+};
+
+static const char *dsp_ick_parent_names[] = {
+	"dsp_fck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(dsp_ick, "dsp_clkdm", dsp_ick_clksel,
+			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+			 OMAP24XX_CLKSEL_DSP_IF_MASK,
+			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN),
+			 OMAP2420_EN_DSP_IPI_SHIFT, &clkhwops_iclk_wait,
+			 dsp_ick_parent_names, dsp_fck_ops);
+
+static const struct clksel_rate dss1_fck_sys_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate dss1_fck_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
+	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
+	{ .div = 5, .val = 5, .flags = RATE_IN_24XX },
+	{ .div = 6, .val = 6, .flags = RATE_IN_24XX },
+	{ .div = 8, .val = 8, .flags = RATE_IN_24XX },
+	{ .div = 9, .val = 9, .flags = RATE_IN_24XX },
+	{ .div = 12, .val = 12, .flags = RATE_IN_24XX },
+	{ .div = 16, .val = 16, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel dss1_fck_clksel[] = {
+	{ .parent = &sys_ck, .rates = dss1_fck_sys_rates },
+	{ .parent = &core_ck, .rates = dss1_fck_core_rates },
+	{ .parent = NULL },
+};
+
+static const char *dss1_fck_parent_names[] = {
+	"sys_ck", "core_ck",
+};
+
+static struct clk dss1_fck;
+
+static const struct clk_ops dss1_fck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.get_parent	= &omap2_clksel_find_parent_index,
+	.set_parent	= &omap2_clksel_set_parent,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(dss1_fck, "dss_clkdm", dss1_fck_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+			 OMAP24XX_CLKSEL_DSS1_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_DSS1_SHIFT, NULL,
+			 dss1_fck_parent_names, dss1_fck_ops);
+
+static const struct clksel_rate dss2_fck_sys_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate dss2_fck_48m_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate func_48m_apll96_rates[] = {
+	{ .div = 2, .val = 0, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate func_48m_alt_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel func_48m_clksel[] = {
+	{ .parent = &apll96_ck, .rates = func_48m_apll96_rates },
+	{ .parent = &alt_ck, .rates = func_48m_alt_rates },
+	{ .parent = NULL },
+};
+
+static const char *func_48m_ck_parent_names[] = {
+	"apll96_ck", "alt_ck",
+};
+
+static struct clk func_48m_ck;
+
+static const struct clk_ops func_48m_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.set_rate	= &omap2_clksel_set_rate,
+	.round_rate	= &omap2_clksel_round_rate,
+	.get_parent	= &omap2_clksel_find_parent_index,
+	.set_parent	= &omap2_clksel_set_parent,
+};
+
+static struct clk_hw_omap func_48m_ck_hw = {
+	.hw = {
+		.clk = &func_48m_ck,
+	},
+	.clksel		= func_48m_clksel,
+	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+	.clksel_mask	= OMAP24XX_48M_SOURCE_MASK,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(func_48m_ck, func_48m_ck_parent_names, func_48m_ck_ops);
+
+static const struct clksel dss2_fck_clksel[] = {
+	{ .parent = &sys_ck, .rates = dss2_fck_sys_rates },
+	{ .parent = &func_48m_ck, .rates = dss2_fck_48m_rates },
+	{ .parent = NULL },
+};
+
+static const char *dss2_fck_parent_names[] = {
+	"sys_ck", "func_48m_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(dss2_fck, "dss_clkdm", dss2_fck_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+			 OMAP24XX_CLKSEL_DSS2_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_DSS2_SHIFT, NULL,
+			 dss2_fck_parent_names, dss1_fck_ops);
+
+static const char *func_54m_ck_parent_names[] = {
+	"apll54_ck", "alt_ck",
+};
+
+DEFINE_CLK_MUX(func_54m_ck, func_54m_ck_parent_names, NULL, 0x0,
+	       OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+	       OMAP24XX_54M_SOURCE_SHIFT, OMAP24XX_54M_SOURCE_WIDTH,
+	       0x0, NULL);
+
+static struct clk dss_54m_fck;
+
+static const char *dss_54m_fck_parent_names[] = {
+	"func_54m_ck",
+};
+
+static struct clk_hw_omap dss_54m_fck_hw = {
+	.hw = {
+		.clk = &dss_54m_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_TV_SHIFT,
+	.clkdm_name	= "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss_54m_fck, dss_54m_fck_parent_names, aes_ick_ops);
+
+static struct clk dss_ick;
+
+static struct clk_hw_omap dss_ick_hw = {
+	.hw = {
+		.clk = &dss_ick,
+	},
+	.ops		= &clkhwops_iclk,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
+	.clkdm_name	= "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk eac_fck;
+
+static struct clk_hw_omap eac_fck_hw = {
+	.hw = {
+		.clk = &eac_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP2420_EN_EAC_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(eac_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk eac_ick;
+
+static struct clk_hw_omap eac_ick_hw = {
+	.hw = {
+		.clk = &eac_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP2420_EN_EAC_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(eac_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk emul_ck;
+
+static struct clk_hw_omap emul_ck_hw = {
+	.hw = {
+		.clk = &emul_ck,
+	},
+	.enable_reg	= OMAP2420_PRCM_CLKEMUL_CTRL,
+	.enable_bit	= OMAP24XX_EMULATION_EN_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(emul_ck, dss_54m_fck_parent_names, aes_ick_ops);
+
+DEFINE_CLK_FIXED_FACTOR(func_12m_ck, "func_48m_ck", &func_48m_ck, 0x0, 1, 4);
+
+static struct clk fac_fck;
+
+static const char *fac_fck_parent_names[] = {
+	"func_12m_ck",
+};
+
+static struct clk_hw_omap fac_fck_hw = {
+	.hw = {
+		.clk = &fac_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(fac_fck, fac_fck_parent_names, aes_ick_ops);
+
+static struct clk fac_ick;
+
+static struct clk_hw_omap fac_ick_hw = {
+	.hw = {
+		.clk = &fac_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(fac_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel gfx_fck_clksel[] = {
+	{ .parent = &core_l3_ck, .rates = gfx_l3_rates },
+	{ .parent = NULL },
+};
+
+static const char *gfx_2d_fck_parent_names[] = {
+	"core_l3_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(gfx_2d_fck, "gfx_clkdm", gfx_fck_clksel,
+			 OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
+			 OMAP_CLKSEL_GFX_MASK,
+			 OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
+			 OMAP24XX_EN_2D_SHIFT, &clkhwops_wait,
+			 gfx_2d_fck_parent_names, dsp_fck_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gfx_3d_fck, "gfx_clkdm", gfx_fck_clksel,
+			 OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
+			 OMAP_CLKSEL_GFX_MASK,
+			 OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
+			 OMAP24XX_EN_3D_SHIFT, &clkhwops_wait,
+			 gfx_2d_fck_parent_names, dsp_fck_ops);
+
+static struct clk gfx_ick;
+
+static const char *gfx_ick_parent_names[] = {
+	"core_l3_ck",
+};
+
+static struct clk_hw_omap gfx_ick_hw = {
+	.hw = {
+		.clk = &gfx_ick,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP_EN_GFX_SHIFT,
+	.clkdm_name	= "gfx_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gfx_ick, gfx_ick_parent_names, aes_ick_ops);
+
+static struct clk gpios_fck;
+
+static const char *gpios_fck_parent_names[] = {
+	"func_32k_ck",
+};
+
+static struct clk_hw_omap gpios_fck_hw = {
+	.hw = {
+		.clk = &gpios_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpios_fck, gpios_fck_parent_names, aes_ick_ops);
+
+static struct clk wu_l4_ick;
+
+DEFINE_STRUCT_CLK_HW_OMAP(wu_l4_ick, "wkup_clkdm");
+DEFINE_STRUCT_CLK(wu_l4_ick, dpll_ck_parent_names, core_ck_ops);
+
+static struct clk gpios_ick;
+
+static const char *gpios_ick_parent_names[] = {
+	"wu_l4_ick",
+};
+
+static struct clk_hw_omap gpios_ick_hw = {
+	.hw = {
+		.clk = &gpios_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpios_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static struct clk gpmc_fck;
+
+static struct clk_hw_omap gpmc_fck_hw = {
+	.hw = {
+		.clk = &gpmc_fck,
+	},
+	.ops		= &clkhwops_iclk,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_GPMC_SHIFT,
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpmc_fck, gfx_ick_parent_names, core_ck_ops);
+
+static const struct clksel_rate gpt_alt_rates[] = {
+	{ .div = 1, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel omap24xx_gpt_clksel[] = {
+	{ .parent = &func_32k_ck, .rates = gpt_32k_rates },
+	{ .parent = &sys_ck, .rates = gpt_sys_rates },
+	{ .parent = &alt_ck, .rates = gpt_alt_rates },
+	{ .parent = NULL },
+};
+
+static const char *gpt10_fck_parent_names[] = {
+	"func_32k_ck", "sys_ck", "alt_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt10_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT10_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT10_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt10_ick;
+
+static struct clk_hw_omap gpt10_ick_hw = {
+	.hw = {
+		.clk = &gpt10_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt10_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt11_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT11_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT11_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt11_ick;
+
+static struct clk_hw_omap gpt11_ick_hw = {
+	.hw = {
+		.clk = &gpt11_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt11_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt12_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT12_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT12_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt12_ick;
+
+static struct clk_hw_omap gpt12_ick_hw = {
+	.hw = {
+		.clk = &gpt12_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt12_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clk_ops gpt1_fck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.set_rate	= &omap2_clksel_set_rate,
+	.round_rate	= &omap2_clksel_round_rate,
+	.get_parent	= &omap2_clksel_find_parent_index,
+	.set_parent	= &omap2_clksel_set_parent,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt1_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL1),
+			 OMAP24XX_CLKSEL_GPT1_MASK,
+			 OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+			 OMAP24XX_EN_GPT1_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, gpt1_fck_ops);
+
+static struct clk gpt1_ick;
+
+static struct clk_hw_omap gpt1_ick_hw = {
+	.hw = {
+		.clk = &gpt1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt1_ick, gpios_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt2_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT2_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT2_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt2_ick;
+
+static struct clk_hw_omap gpt2_ick_hw = {
+	.hw = {
+		.clk = &gpt2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt2_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt3_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT3_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT3_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt3_ick;
+
+static struct clk_hw_omap gpt3_ick_hw = {
+	.hw = {
+		.clk = &gpt3_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt3_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt4_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT4_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT4_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt4_ick;
+
+static struct clk_hw_omap gpt4_ick_hw = {
+	.hw = {
+		.clk = &gpt4_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt4_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt5_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT5_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT5_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt5_ick;
+
+static struct clk_hw_omap gpt5_ick_hw = {
+	.hw = {
+		.clk = &gpt5_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt5_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt6_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT6_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT6_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt6_ick;
+
+static struct clk_hw_omap gpt6_ick_hw = {
+	.hw = {
+		.clk = &gpt6_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt6_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt7_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT7_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT7_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt7_ick;
+
+static struct clk_hw_omap gpt7_ick_hw = {
+	.hw = {
+		.clk = &gpt7_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt7_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt8_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT8_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT8_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt8_ick;
+
+static struct clk_hw_omap gpt8_ick_hw = {
+	.hw = {
+		.clk = &gpt8_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt8_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt9_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT9_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT9_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt9_ick;
+
+static struct clk_hw_omap gpt9_ick_hw = {
+	.hw = {
+		.clk = &gpt9_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt9_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk hdq_fck;
+
+static struct clk_hw_omap hdq_fck_hw = {
+	.hw = {
+		.clk = &hdq_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hdq_fck, fac_fck_parent_names, aes_ick_ops);
+
+static struct clk hdq_ick;
+
+static struct clk_hw_omap hdq_ick_hw = {
+	.hw = {
+		.clk = &hdq_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hdq_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk i2c1_fck;
+
+static struct clk_hw_omap i2c1_fck_hw = {
+	.hw = {
+		.clk = &i2c1_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP2420_EN_I2C1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c1_fck, fac_fck_parent_names, aes_ick_ops);
+
+static struct clk i2c1_ick;
+
+static struct clk_hw_omap i2c1_ick_hw = {
+	.hw = {
+		.clk = &i2c1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP2420_EN_I2C1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c1_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk i2c2_fck;
+
+static struct clk_hw_omap i2c2_fck_hw = {
+	.hw = {
+		.clk = &i2c2_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP2420_EN_I2C2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c2_fck, fac_fck_parent_names, aes_ick_ops);
+
+static struct clk i2c2_ick;
+
+static struct clk_hw_omap i2c2_ick_hw = {
+	.hw = {
+		.clk = &i2c2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP2420_EN_I2C2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c2_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(iva1_ifck, "iva1_clkdm", dsp_fck_clksel,
+			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+			 OMAP2420_CLKSEL_IVA_MASK,
+			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
+			 OMAP2420_EN_IVA_COP_SHIFT, &clkhwops_wait,
+			 dsp_fck_parent_names, dsp_fck_ops);
+
+static struct clk iva1_mpu_int_ifck;
+
+static const char *iva1_mpu_int_ifck_parent_names[] = {
+	"iva1_ifck",
+};
+
+static const struct clk_ops iva1_mpu_int_ifck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.recalc_rate	= &omap_fixed_divisor_recalc,
+};
+
+static struct clk_hw_omap iva1_mpu_int_ifck_hw = {
+	.hw = {
+		.clk = &iva1_mpu_int_ifck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP2420_EN_IVA_MPU_SHIFT,
+	.clkdm_name	= "iva1_clkdm",
+	.fixed_div	= 2,
+};
+
+DEFINE_STRUCT_CLK(iva1_mpu_int_ifck, iva1_mpu_int_ifck_parent_names,
+		  iva1_mpu_int_ifck_ops);
+
+static struct clk mailboxes_ick;
+
+static struct clk_hw_omap mailboxes_ick_hw = {
+	.hw = {
+		.clk = &mailboxes_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_MAILBOXES_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mailboxes_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate common_mcbsp_96m_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel mcbsp_fck_clksel[] = {
+	{ .parent = &func_96m_ck, .rates = common_mcbsp_96m_rates },
+	{ .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
+	{ .parent = NULL },
+};
+
+static const char *mcbsp1_fck_parent_names[] = {
+	"func_96m_ck", "mcbsp_clks",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp1_fck, "core_l4_clkdm", mcbsp_fck_clksel,
+			 OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+			 OMAP2_MCBSP1_CLKS_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_MCBSP1_SHIFT, &clkhwops_wait,
+			 mcbsp1_fck_parent_names, dss1_fck_ops);
+
+static struct clk mcbsp1_ick;
+
+static struct clk_hw_omap mcbsp1_ick_hw = {
+	.hw = {
+		.clk = &mcbsp1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_MCBSP1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp1_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp2_fck, "core_l4_clkdm", mcbsp_fck_clksel,
+			 OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+			 OMAP2_MCBSP2_CLKS_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_MCBSP2_SHIFT, &clkhwops_wait,
+			 mcbsp1_fck_parent_names, dss1_fck_ops);
+
+static struct clk mcbsp2_ick;
+
+static struct clk_hw_omap mcbsp2_ick_hw = {
+	.hw = {
+		.clk = &mcbsp2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_MCBSP2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp2_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mcspi1_fck;
+
+static const char *mcspi1_fck_parent_names[] = {
+	"func_48m_ck",
+};
+
+static struct clk_hw_omap mcspi1_fck_hw = {
+	.hw = {
+		.clk = &mcspi1_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi1_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk mcspi1_ick;
+
+static struct clk_hw_omap mcspi1_ick_hw = {
+	.hw = {
+		.clk = &mcspi1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi1_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mcspi2_fck;
+
+static struct clk_hw_omap mcspi2_fck_hw = {
+	.hw = {
+		.clk = &mcspi2_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi2_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk mcspi2_ick;
+
+static struct clk_hw_omap mcspi2_ick_hw = {
+	.hw = {
+		.clk = &mcspi2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi2_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mmc_fck;
+
+static struct clk_hw_omap mmc_fck_hw = {
+	.hw = {
+		.clk = &mmc_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP2420_EN_MMC_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmc_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk mmc_ick;
+
+static struct clk_hw_omap mmc_ick_hw = {
+	.hw = {
+		.clk = &mmc_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP2420_EN_MMC_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmc_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_DIVIDER(mpu_ck, "core_ck", &core_ck, 0x0,
+		   OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
+		   OMAP24XX_CLKSEL_MPU_SHIFT, OMAP24XX_CLKSEL_MPU_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk mpu_wdt_fck;
+
+static struct clk_hw_omap mpu_wdt_fck_hw = {
+	.hw = {
+		.clk = &mpu_wdt_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mpu_wdt_fck, gpios_fck_parent_names, aes_ick_ops);
+
+static struct clk mpu_wdt_ick;
+
+static struct clk_hw_omap mpu_wdt_ick_hw = {
+	.hw = {
+		.clk = &mpu_wdt_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mpu_wdt_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static struct clk mspro_fck;
+
+static struct clk_hw_omap mspro_fck_hw = {
+	.hw = {
+		.clk = &mspro_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mspro_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk mspro_ick;
+
+static struct clk_hw_omap mspro_ick_hw = {
+	.hw = {
+		.clk = &mspro_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mspro_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk omapctrl_ick;
+
+static struct clk_hw_omap omapctrl_ick_hw = {
+	.hw = {
+		.clk = &omapctrl_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP24XX_EN_OMAPCTRL_SHIFT,
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(omapctrl_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static struct clk pka_ick;
+
+static struct clk_hw_omap pka_ick_hw = {
+	.hw = {
+		.clk = &pka_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+	.enable_bit	= OMAP24XX_EN_PKA_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(pka_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk rng_ick;
+
+static struct clk_hw_omap rng_ick_hw = {
+	.hw = {
+		.clk = &rng_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+	.enable_bit	= OMAP24XX_EN_RNG_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(rng_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk sdma_fck;
+
+DEFINE_STRUCT_CLK_HW_OMAP(sdma_fck, "core_l3_clkdm");
+DEFINE_STRUCT_CLK(sdma_fck, gfx_ick_parent_names, core_ck_ops);
+
+static struct clk sdma_ick;
+
+static struct clk_hw_omap sdma_ick_hw = {
+	.hw = {
+		.clk = &sdma_ick,
+	},
+	.ops		= &clkhwops_iclk,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_SDMA_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sdma_ick, gfx_ick_parent_names, core_ck_ops);
+
+static struct clk sdrc_ick;
+
+static struct clk_hw_omap sdrc_ick_hw = {
+	.hw = {
+		.clk = &sdrc_ick,
+	},
+	.ops		= &clkhwops_iclk,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_SDRC_SHIFT,
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sdrc_ick, gfx_ick_parent_names, core_ck_ops);
+
+static struct clk sha_ick;
+
+static struct clk_hw_omap sha_ick_hw = {
+	.hw = {
+		.clk = &sha_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+	.enable_bit	= OMAP24XX_EN_SHA_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sha_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk ssi_l4_ick;
+
+static struct clk_hw_omap ssi_l4_ick_hw = {
+	.hw = {
+		.clk = &ssi_l4_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP24XX_EN_SSI_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(ssi_l4_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate ssi_ssr_sst_fck_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
+	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
+	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
+	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
+	{ .div = 0 }
+};
+
+static const struct clksel ssi_ssr_sst_fck_clksel[] = {
+	{ .parent = &core_ck, .rates = ssi_ssr_sst_fck_core_rates },
+	{ .parent = NULL },
+};
+
+static const char *ssi_ssr_sst_fck_parent_names[] = {
+	"core_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_sst_fck, "core_l3_clkdm",
+			 ssi_ssr_sst_fck_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+			 OMAP24XX_CLKSEL_SSI_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+			 OMAP24XX_EN_SSI_SHIFT, &clkhwops_wait,
+			 ssi_ssr_sst_fck_parent_names, dsp_fck_ops);
+
+static struct clk sync_32k_ick;
+
+static struct clk_hw_omap sync_32k_ick_hw = {
+	.hw = {
+		.clk = &sync_32k_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP24XX_EN_32KSYNC_SHIFT,
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sync_32k_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate common_clkout_src_core_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate common_clkout_src_sys_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate common_clkout_src_96m_rates[] = {
+	{ .div = 1, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate common_clkout_src_54m_rates[] = {
+	{ .div = 1, .val = 3, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel common_clkout_src_clksel[] = {
+	{ .parent = &core_ck, .rates = common_clkout_src_core_rates },
+	{ .parent = &sys_ck, .rates = common_clkout_src_sys_rates },
+	{ .parent = &func_96m_ck, .rates = common_clkout_src_96m_rates },
+	{ .parent = &func_54m_ck, .rates = common_clkout_src_54m_rates },
+	{ .parent = NULL },
+};
+
+static const char *sys_clkout_src_parent_names[] = {
+	"core_ck", "sys_ck", "func_96m_ck", "func_54m_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(sys_clkout_src, "wkup_clkdm", common_clkout_src_clksel,
+			 OMAP2420_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_SOURCE_MASK,
+			 OMAP2420_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_EN_SHIFT,
+			 NULL, sys_clkout_src_parent_names, gpt1_fck_ops);
+
+DEFINE_CLK_DIVIDER(sys_clkout, "sys_clkout_src", &sys_clkout_src, 0x0,
+		   OMAP2420_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_DIV_SHIFT,
+		   OMAP24XX_CLKOUT_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
+
+DEFINE_CLK_OMAP_MUX_GATE(sys_clkout2_src, "wkup_clkdm",
+			 common_clkout_src_clksel, OMAP2420_PRCM_CLKOUT_CTRL,
+			 OMAP2420_CLKOUT2_SOURCE_MASK,
+			 OMAP2420_PRCM_CLKOUT_CTRL, OMAP2420_CLKOUT2_EN_SHIFT,
+			 NULL, sys_clkout_src_parent_names, gpt1_fck_ops);
+
+DEFINE_CLK_DIVIDER(sys_clkout2, "sys_clkout2_src", &sys_clkout2_src, 0x0,
+		   OMAP2420_PRCM_CLKOUT_CTRL, OMAP2420_CLKOUT2_DIV_SHIFT,
+		   OMAP2420_CLKOUT2_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
+
+static struct clk uart1_fck;
+
+static struct clk_hw_omap uart1_fck_hw = {
+	.hw = {
+		.clk = &uart1_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart1_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk uart1_ick;
+
+static struct clk_hw_omap uart1_ick_hw = {
+	.hw = {
+		.clk = &uart1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart1_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk uart2_fck;
+
+static struct clk_hw_omap uart2_fck_hw = {
+	.hw = {
+		.clk = &uart2_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart2_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk uart2_ick;
+
+static struct clk_hw_omap uart2_ick_hw = {
+	.hw = {
+		.clk = &uart2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart2_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk uart3_fck;
+
+static struct clk_hw_omap uart3_fck_hw = {
+	.hw = {
+		.clk = &uart3_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart3_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk uart3_ick;
+
+static struct clk_hw_omap uart3_ick_hw = {
+	.hw = {
+		.clk = &uart3_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart3_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk usb_fck;
+
+static struct clk_hw_omap usb_fck_hw = {
+	.hw = {
+		.clk = &usb_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usb_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static const struct clksel_rate usb_l4_ick_core_l3_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel usb_l4_ick_clksel[] = {
+	{ .parent = &core_l3_ck, .rates = usb_l4_ick_core_l3_rates },
+	{ .parent = NULL },
+};
+
+static const char *usb_l4_ick_parent_names[] = {
+	"core_l3_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(usb_l4_ick, "core_l4_clkdm", usb_l4_ick_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+			 OMAP24XX_CLKSEL_USB_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+			 OMAP24XX_EN_USB_SHIFT, &clkhwops_iclk_wait,
+			 usb_l4_ick_parent_names, dsp_fck_ops);
+
+static struct clk virt_prcm_set;
+
+static const char *virt_prcm_set_parent_names[] = {
+	"mpu_ck",
+};
+
+static const struct clk_ops virt_prcm_set_ops = {
+	.recalc_rate	= &omap2_table_mpu_recalc,
+	.set_rate	= &omap2_select_table_rate,
+	.round_rate	= &omap2_round_to_table_rate,
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(virt_prcm_set, NULL);
+DEFINE_STRUCT_CLK(virt_prcm_set, virt_prcm_set_parent_names, virt_prcm_set_ops);
+
+static const struct clksel_rate vlynq_fck_96m_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_242X },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate vlynq_fck_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_242X },
+	{ .div = 2, .val = 2, .flags = RATE_IN_242X },
+	{ .div = 3, .val = 3, .flags = RATE_IN_242X },
+	{ .div = 4, .val = 4, .flags = RATE_IN_242X },
+	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
+	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
+	{ .div = 9, .val = 9, .flags = RATE_IN_242X },
+	{ .div = 12, .val = 12, .flags = RATE_IN_242X },
+	{ .div = 16, .val = 16, .flags = RATE_IN_242X },
+	{ .div = 18, .val = 18, .flags = RATE_IN_242X },
+	{ .div = 0 }
+};
+
+static const struct clksel vlynq_fck_clksel[] = {
+	{ .parent = &func_96m_ck, .rates = vlynq_fck_96m_rates },
+	{ .parent = &core_ck, .rates = vlynq_fck_core_rates },
+	{ .parent = NULL },
+};
+
+static const char *vlynq_fck_parent_names[] = {
+	"func_96m_ck", "core_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(vlynq_fck, "core_l3_clkdm", vlynq_fck_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+			 OMAP2420_CLKSEL_VLYNQ_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP2420_EN_VLYNQ_SHIFT, &clkhwops_wait,
+			 vlynq_fck_parent_names, dss1_fck_ops);
+
+static struct clk vlynq_ick;
+
+static struct clk_hw_omap vlynq_ick_hw = {
+	.hw = {
+		.clk = &vlynq_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP2420_EN_VLYNQ_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(vlynq_ick, gfx_ick_parent_names, aes_ick_ops);
+
+static struct clk wdt1_ick;
+
+static struct clk_hw_omap wdt1_ick_hw = {
+	.hw = {
+		.clk = &wdt1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP24XX_EN_WDT1_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt1_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static struct clk wdt1_osc_ck;
+
+static const struct clk_ops wdt1_osc_ck_ops = {};
+
+DEFINE_STRUCT_CLK_HW_OMAP(wdt1_osc_ck, NULL);
+DEFINE_STRUCT_CLK(wdt1_osc_ck, sys_ck_parent_names, wdt1_osc_ck_ops);
+
+static struct clk wdt3_fck;
+
+static struct clk_hw_omap wdt3_fck_hw = {
+	.hw = {
+		.clk = &wdt3_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP2420_EN_WDT3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt3_fck, gpios_fck_parent_names, aes_ick_ops);
+
+static struct clk wdt3_ick;
+
+static struct clk_hw_omap wdt3_ick_hw = {
+	.hw = {
+		.clk = &wdt3_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP2420_EN_WDT3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt3_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk wdt4_fck;
+
+static struct clk_hw_omap wdt4_fck_hw = {
+	.hw = {
+		.clk = &wdt4_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt4_fck, gpios_fck_parent_names, aes_ick_ops);
+
+static struct clk wdt4_ick;
+
+static struct clk_hw_omap wdt4_ick_hw = {
+	.hw = {
+		.clk = &wdt4_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt4_ick, aes_ick_parent_names, aes_ick_ops);
+
+/*
+ * clkdev integration
+ */
+
+static struct omap_clk omap2420_clks[] = {
+	/* external root sources */
+	CLK(NULL,	"func_32k_ck",	&func_32k_ck,	CK_242X),
+	CLK(NULL,	"secure_32k_ck", &secure_32k_ck, CK_242X),
+	CLK(NULL,	"osc_ck",	&osc_ck,	CK_242X),
+	CLK(NULL,	"sys_ck",	&sys_ck,	CK_242X),
+	CLK(NULL,	"alt_ck",	&alt_ck,	CK_242X),
+	CLK(NULL,	"mcbsp_clks",	&mcbsp_clks,	CK_242X),
+	/* internal analog sources */
+	CLK(NULL,	"dpll_ck",	&dpll_ck,	CK_242X),
+	CLK(NULL,	"apll96_ck",	&apll96_ck,	CK_242X),
+	CLK(NULL,	"apll54_ck",	&apll54_ck,	CK_242X),
+	/* internal prcm root sources */
+	CLK(NULL,	"func_54m_ck",	&func_54m_ck,	CK_242X),
+	CLK(NULL,	"core_ck",	&core_ck,	CK_242X),
+	CLK(NULL,	"func_96m_ck",	&func_96m_ck,	CK_242X),
+	CLK(NULL,	"func_48m_ck",	&func_48m_ck,	CK_242X),
+	CLK(NULL,	"func_12m_ck",	&func_12m_ck,	CK_242X),
+	CLK(NULL,	"ck_wdt1_osc",	&wdt1_osc_ck,	CK_242X),
+	CLK(NULL,	"sys_clkout_src", &sys_clkout_src, CK_242X),
+	CLK(NULL,	"sys_clkout",	&sys_clkout,	CK_242X),
+	CLK(NULL,	"sys_clkout2_src", &sys_clkout2_src, CK_242X),
+	CLK(NULL,	"sys_clkout2",	&sys_clkout2,	CK_242X),
+	CLK(NULL,	"emul_ck",	&emul_ck,	CK_242X),
+	/* mpu domain clocks */
+	CLK(NULL,	"mpu_ck",	&mpu_ck,	CK_242X),
+	/* dsp domain clocks */
+	CLK(NULL,	"dsp_fck",	&dsp_fck,	CK_242X),
+	CLK(NULL,	"dsp_ick",	&dsp_ick,	CK_242X),
+	CLK(NULL,	"iva1_ifck",	&iva1_ifck,	CK_242X),
+	CLK(NULL,	"iva1_mpu_int_ifck", &iva1_mpu_int_ifck, CK_242X),
+	/* GFX domain clocks */
+	CLK(NULL,	"gfx_3d_fck",	&gfx_3d_fck,	CK_242X),
+	CLK(NULL,	"gfx_2d_fck",	&gfx_2d_fck,	CK_242X),
+	CLK(NULL,	"gfx_ick",	&gfx_ick,	CK_242X),
+	/* DSS domain clocks */
+	CLK("omapdss_dss",	"ick",		&dss_ick,	CK_242X),
+	CLK(NULL,	"dss_ick",		&dss_ick,	CK_242X),
+	CLK(NULL,	"dss1_fck",		&dss1_fck,	CK_242X),
+	CLK(NULL,	"dss2_fck",	&dss2_fck,	CK_242X),
+	CLK(NULL,	"dss_54m_fck",	&dss_54m_fck,	CK_242X),
+	/* L3 domain clocks */
+	CLK(NULL,	"core_l3_ck",	&core_l3_ck,	CK_242X),
+	CLK(NULL,	"ssi_fck",	&ssi_ssr_sst_fck, CK_242X),
+	CLK(NULL,	"usb_l4_ick",	&usb_l4_ick,	CK_242X),
+	/* L4 domain clocks */
+	CLK(NULL,	"l4_ck",	&l4_ck,		CK_242X),
+	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_242X),
+	CLK(NULL,	"wu_l4_ick",	&wu_l4_ick,	CK_242X),
+	/* virtual meta-group clock */
+	CLK(NULL,	"virt_prcm_set", &virt_prcm_set, CK_242X),
+	/* general l4 interface ck, multi-parent functional clk */
+	CLK(NULL,	"gpt1_ick",	&gpt1_ick,	CK_242X),
+	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_242X),
+	CLK(NULL,	"gpt2_ick",	&gpt2_ick,	CK_242X),
+	CLK(NULL,	"gpt2_fck",	&gpt2_fck,	CK_242X),
+	CLK(NULL,	"gpt3_ick",	&gpt3_ick,	CK_242X),
+	CLK(NULL,	"gpt3_fck",	&gpt3_fck,	CK_242X),
+	CLK(NULL,	"gpt4_ick",	&gpt4_ick,	CK_242X),
+	CLK(NULL,	"gpt4_fck",	&gpt4_fck,	CK_242X),
+	CLK(NULL,	"gpt5_ick",	&gpt5_ick,	CK_242X),
+	CLK(NULL,	"gpt5_fck",	&gpt5_fck,	CK_242X),
+	CLK(NULL,	"gpt6_ick",	&gpt6_ick,	CK_242X),
+	CLK(NULL,	"gpt6_fck",	&gpt6_fck,	CK_242X),
+	CLK(NULL,	"gpt7_ick",	&gpt7_ick,	CK_242X),
+	CLK(NULL,	"gpt7_fck",	&gpt7_fck,	CK_242X),
+	CLK(NULL,	"gpt8_ick",	&gpt8_ick,	CK_242X),
+	CLK(NULL,	"gpt8_fck",	&gpt8_fck,	CK_242X),
+	CLK(NULL,	"gpt9_ick",	&gpt9_ick,	CK_242X),
+	CLK(NULL,	"gpt9_fck",	&gpt9_fck,	CK_242X),
+	CLK(NULL,	"gpt10_ick",	&gpt10_ick,	CK_242X),
+	CLK(NULL,	"gpt10_fck",	&gpt10_fck,	CK_242X),
+	CLK(NULL,	"gpt11_ick",	&gpt11_ick,	CK_242X),
+	CLK(NULL,	"gpt11_fck",	&gpt11_fck,	CK_242X),
+	CLK(NULL,	"gpt12_ick",	&gpt12_ick,	CK_242X),
+	CLK(NULL,	"gpt12_fck",	&gpt12_fck,	CK_242X),
+	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick,	CK_242X),
+	CLK(NULL,	"mcbsp1_ick",	&mcbsp1_ick,	CK_242X),
+	CLK(NULL,	"mcbsp1_fck",	&mcbsp1_fck,	CK_242X),
+	CLK("omap-mcbsp.2", "ick",	&mcbsp2_ick,	CK_242X),
+	CLK(NULL,	"mcbsp2_ick",	&mcbsp2_ick,	CK_242X),
+	CLK(NULL,	"mcbsp2_fck",	&mcbsp2_fck,	CK_242X),
+	CLK("omap2_mcspi.1", "ick",	&mcspi1_ick,	CK_242X),
+	CLK(NULL,	"mcspi1_ick",	&mcspi1_ick,	CK_242X),
+	CLK(NULL,	"mcspi1_fck",	&mcspi1_fck,	CK_242X),
+	CLK("omap2_mcspi.2", "ick",	&mcspi2_ick,	CK_242X),
+	CLK(NULL,	"mcspi2_ick",	&mcspi2_ick,	CK_242X),
+	CLK(NULL,	"mcspi2_fck",	&mcspi2_fck,	CK_242X),
+	CLK(NULL,	"uart1_ick",	&uart1_ick,	CK_242X),
+	CLK(NULL,	"uart1_fck",	&uart1_fck,	CK_242X),
+	CLK(NULL,	"uart2_ick",	&uart2_ick,	CK_242X),
+	CLK(NULL,	"uart2_fck",	&uart2_fck,	CK_242X),
+	CLK(NULL,	"uart3_ick",	&uart3_ick,	CK_242X),
+	CLK(NULL,	"uart3_fck",	&uart3_fck,	CK_242X),
+	CLK(NULL,	"gpios_ick",	&gpios_ick,	CK_242X),
+	CLK(NULL,	"gpios_fck",	&gpios_fck,	CK_242X),
+	CLK("omap_wdt",	"ick",		&mpu_wdt_ick,	CK_242X),
+	CLK(NULL,	"mpu_wdt_ick",		&mpu_wdt_ick,	CK_242X),
+	CLK(NULL,	"mpu_wdt_fck",	&mpu_wdt_fck,	CK_242X),
+	CLK(NULL,	"sync_32k_ick",	&sync_32k_ick,	CK_242X),
+	CLK(NULL,	"wdt1_ick",	&wdt1_ick,	CK_242X),
+	CLK(NULL,	"omapctrl_ick",	&omapctrl_ick,	CK_242X),
+	CLK("omap24xxcam", "fck",	&cam_fck,	CK_242X),
+	CLK(NULL,	"cam_fck",	&cam_fck,	CK_242X),
+	CLK("omap24xxcam", "ick",	&cam_ick,	CK_242X),
+	CLK(NULL,	"cam_ick",	&cam_ick,	CK_242X),
+	CLK(NULL,	"mailboxes_ick", &mailboxes_ick,	CK_242X),
+	CLK(NULL,	"wdt4_ick",	&wdt4_ick,	CK_242X),
+	CLK(NULL,	"wdt4_fck",	&wdt4_fck,	CK_242X),
+	CLK(NULL,	"wdt3_ick",	&wdt3_ick,	CK_242X),
+	CLK(NULL,	"wdt3_fck",	&wdt3_fck,	CK_242X),
+	CLK(NULL,	"mspro_ick",	&mspro_ick,	CK_242X),
+	CLK(NULL,	"mspro_fck",	&mspro_fck,	CK_242X),
+	CLK("mmci-omap.0", "ick",	&mmc_ick,	CK_242X),
+	CLK(NULL,	"mmc_ick",	&mmc_ick,	CK_242X),
+	CLK("mmci-omap.0", "fck",	&mmc_fck,	CK_242X),
+	CLK(NULL,	"mmc_fck",	&mmc_fck,	CK_242X),
+	CLK(NULL,	"fac_ick",	&fac_ick,	CK_242X),
+	CLK(NULL,	"fac_fck",	&fac_fck,	CK_242X),
+	CLK(NULL,	"eac_ick",	&eac_ick,	CK_242X),
+	CLK(NULL,	"eac_fck",	&eac_fck,	CK_242X),
+	CLK("omap_hdq.0", "ick",	&hdq_ick,	CK_242X),
+	CLK(NULL,	"hdq_ick",	&hdq_ick,	CK_242X),
+	CLK("omap_hdq.0", "fck",	&hdq_fck,	CK_242X),
+	CLK(NULL,	"hdq_fck",	&hdq_fck,	CK_242X),
+	CLK("omap_i2c.1", "ick",	&i2c1_ick,	CK_242X),
+	CLK(NULL,	"i2c1_ick",	&i2c1_ick,	CK_242X),
+	CLK(NULL,	"i2c1_fck",	&i2c1_fck,	CK_242X),
+	CLK("omap_i2c.2", "ick",	&i2c2_ick,	CK_242X),
+	CLK(NULL,	"i2c2_ick",	&i2c2_ick,	CK_242X),
+	CLK(NULL,	"i2c2_fck",	&i2c2_fck,	CK_242X),
+	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_242X),
+	CLK(NULL,	"sdma_fck",	&sdma_fck,	CK_242X),
+	CLK(NULL,	"sdma_ick",	&sdma_ick,	CK_242X),
+	CLK(NULL,	"sdrc_ick",	&sdrc_ick,	CK_242X),
+	CLK(NULL,	"vlynq_ick",	&vlynq_ick,	CK_242X),
+	CLK(NULL,	"vlynq_fck",	&vlynq_fck,	CK_242X),
+	CLK(NULL,	"des_ick",	&des_ick,	CK_242X),
+	CLK("omap-sham",	"ick",	&sha_ick,	CK_242X),
+	CLK(NULL,	"sha_ick",	&sha_ick,	CK_242X),
+	CLK("omap_rng",	"ick",		&rng_ick,	CK_242X),
+	CLK(NULL,	"rng_ick",		&rng_ick,	CK_242X),
+	CLK("omap-aes",	"ick",	&aes_ick,	CK_242X),
+	CLK(NULL,	"aes_ick",	&aes_ick,	CK_242X),
+	CLK(NULL,	"pka_ick",	&pka_ick,	CK_242X),
+	CLK(NULL,	"usb_fck",	&usb_fck,	CK_242X),
+	CLK("musb-hdrc",	"fck",	&osc_ck,	CK_242X),
+	CLK(NULL,	"timer_32k_ck",	&func_32k_ck,	CK_242X),
+	CLK(NULL,	"timer_sys_ck",	&sys_ck,	CK_242X),
+	CLK(NULL,	"timer_ext_ck",	&alt_ck,	CK_242X),
+	CLK(NULL,	"cpufreq_ck",	&virt_prcm_set,	CK_242X),
+};
+
+
+static const char *enable_init_clks[] = {
+	"apll96_ck",
+	"apll54_ck",
+	"sync_32k_ick",
+	"omapctrl_ick",
+	"gpmc_fck",
+	"sdrc_ick",
+};
+
+/*
+ * init code
+ */
+
+int __init omap2420_clk_init(void)
+{
+	struct omap_clk *c;
+
+	prcm_clksrc_ctrl = OMAP2420_PRCM_CLKSRC_CTRL;
+	cpu_mask = RATE_IN_242X;
+	rate_table = omap2420_rate_table;
+
+	omap2xxx_clkt_dpllcore_init(&dpll_ck_hw.hw);
+
+	omap2xxx_clkt_vps_check_bootloader_rates();
+
+	for (c = omap2420_clks; c < omap2420_clks + ARRAY_SIZE(omap2420_clks);
+	     c++) {
+		clkdev_add(&c->lk);
+		if (!__clk_init(NULL, c->lk.clk))
+			omap2_init_clk_hw_omap_clocks(c->lk.clk);
+	}
+
+	omap2_clk_disable_autoidle_all();
+
+	omap2_clk_enable_init_clocks(enable_init_clks,
+				     ARRAY_SIZE(enable_init_clks));
+
+	pr_info("Clocking rate (Crystal/DPLL/MPU): %ld.%01ld/%ld/%ld MHz\n",
+		(clk_get_rate(&sys_ck) / 1000000),
+		(clk_get_rate(&sys_ck) / 100000) % 10,
+		(clk_get_rate(&dpll_ck) / 1000000),
+		(clk_get_rate(&mpu_ck) / 1000000));
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap2/cclock2430_data.c b/arch/arm/mach-omap2/cclock2430_data.c
new file mode 100644
index 0000000..eda079b
--- /dev/null
+++ b/arch/arm/mach-omap2/cclock2430_data.c
@@ -0,0 +1,2065 @@
+/*
+ * OMAP2430 clock data
+ *
+ * Copyright (C) 2005-2009, 2012 Texas Instruments, Inc.
+ * Copyright (C) 2004-2011 Nokia Corporation
+ *
+ * Contacts:
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/clk-private.h>
+#include <linux/list.h>
+
+#include "soc.h"
+#include "iomap.h"
+#include "clock.h"
+#include "clock2xxx.h"
+#include "opp2xxx.h"
+#include "cm2xxx.h"
+#include "prm2xxx.h"
+#include "prm-regbits-24xx.h"
+#include "cm-regbits-24xx.h"
+#include "sdrc.h"
+#include "control.h"
+
+#define OMAP_CM_REGADDR			OMAP2430_CM_REGADDR
+
+/*
+ * 2430 clock tree.
+ *
+ * NOTE:In many cases here we are assigning a 'default' parent. In
+ *	many cases the parent is selectable. The set parent calls will
+ *	also switch sources.
+ *
+ *	Several sources are given initial rates which may be wrong, this will
+ *	be fixed up in the init func.
+ *
+ *	Things are broadly separated below by clock domains. It is
+ *	noteworthy that most peripherals have dependencies on multiple clock
+ *	domains. Many get their interface clocks from the L4 domain, but get
+ *	functional clocks from fixed sources or other core domain derived
+ *	clocks.
+ */
+
+DEFINE_CLK_FIXED_RATE(alt_ck, CLK_IS_ROOT, 54000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(func_32k_ck, CLK_IS_ROOT, 32768, 0x0);
+
+DEFINE_CLK_FIXED_RATE(mcbsp_clks, CLK_IS_ROOT, 0x0, 0x0);
+
+static struct clk osc_ck;
+
+static const struct clk_ops osc_ck_ops = {
+	.enable		= &omap2_enable_osc_ck,
+	.disable	= omap2_disable_osc_ck,
+	.recalc_rate	= &omap2_osc_clk_recalc,
+};
+
+static struct clk_hw_omap osc_ck_hw = {
+	.hw = {
+		.clk = &osc_ck,
+	},
+};
+
+static struct clk osc_ck = {
+	.name	= "osc_ck",
+	.ops	= &osc_ck_ops,
+	.hw	= &osc_ck_hw.hw,
+	.flags	= CLK_IS_ROOT,
+};
+
+DEFINE_CLK_FIXED_RATE(secure_32k_ck, CLK_IS_ROOT, 32768, 0x0);
+
+static struct clk sys_ck;
+
+static const char *sys_ck_parent_names[] = {
+	"osc_ck",
+};
+
+static const struct clk_ops sys_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.recalc_rate	= &omap2xxx_sys_clk_recalc,
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(sys_ck, "wkup_clkdm");
+DEFINE_STRUCT_CLK(sys_ck, sys_ck_parent_names, sys_ck_ops);
+
+static struct dpll_data dpll_dd = {
+	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+	.mult_mask	= OMAP24XX_DPLL_MULT_MASK,
+	.div1_mask	= OMAP24XX_DPLL_DIV_MASK,
+	.clk_bypass	= &sys_ck,
+	.clk_ref	= &sys_ck,
+	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+	.enable_mask	= OMAP24XX_EN_DPLL_MASK,
+	.max_multiplier	= 1023,
+	.min_divider	= 1,
+	.max_divider	= 16,
+};
+
+static struct clk dpll_ck;
+
+static const char *dpll_ck_parent_names[] = {
+	"sys_ck",
+};
+
+static const struct clk_ops dpll_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.get_parent	= &omap2_init_dpll_parent,
+	.recalc_rate	= &omap2_dpllcore_recalc,
+	.round_rate	= &omap2_dpll_round_rate,
+	.set_rate	= &omap2_reprogram_dpllcore,
+};
+
+static struct clk_hw_omap dpll_ck_hw = {
+	.hw = {
+		.clk = &dpll_ck,
+	},
+	.ops		= &clkhwops_omap2xxx_dpll,
+	.dpll_data	= &dpll_dd,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll_ck, dpll_ck_parent_names, dpll_ck_ops);
+
+static struct clk core_ck;
+
+static const char *core_ck_parent_names[] = {
+	"dpll_ck",
+};
+
+static const struct clk_ops core_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(core_ck, "wkup_clkdm");
+DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops);
+
+DEFINE_CLK_DIVIDER(core_l3_ck, "core_ck", &core_ck, 0x0,
+		   OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+		   OMAP24XX_CLKSEL_L3_SHIFT, OMAP24XX_CLKSEL_L3_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+DEFINE_CLK_DIVIDER(l4_ck, "core_l3_ck", &core_l3_ck, 0x0,
+		   OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+		   OMAP24XX_CLKSEL_L4_SHIFT, OMAP24XX_CLKSEL_L4_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk aes_ick;
+
+static const char *aes_ick_parent_names[] = {
+	"l4_ck",
+};
+
+static const struct clk_ops aes_ick_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+};
+
+static struct clk_hw_omap aes_ick_hw = {
+	.hw = {
+		.clk = &aes_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+	.enable_bit	= OMAP24XX_EN_AES_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(aes_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk apll54_ck;
+
+static const struct clk_ops apll54_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_clk_apll54_enable,
+	.disable	= &omap2_clk_apll54_disable,
+	.recalc_rate	= &omap2_clk_apll54_recalc,
+};
+
+static struct clk_hw_omap apll54_ck_hw = {
+	.hw = {
+		.clk = &apll54_ck,
+	},
+	.ops		= &clkhwops_apll54,
+	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+	.enable_bit	= OMAP24XX_EN_54M_PLL_SHIFT,
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(apll54_ck, dpll_ck_parent_names, apll54_ck_ops);
+
+static struct clk apll96_ck;
+
+static const struct clk_ops apll96_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_clk_apll96_enable,
+	.disable	= &omap2_clk_apll96_disable,
+	.recalc_rate	= &omap2_clk_apll96_recalc,
+};
+
+static struct clk_hw_omap apll96_ck_hw = {
+	.hw = {
+		.clk = &apll96_ck,
+	},
+	.ops		= &clkhwops_apll96,
+	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+	.enable_bit	= OMAP24XX_EN_96M_PLL_SHIFT,
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(apll96_ck, dpll_ck_parent_names, apll96_ck_ops);
+
+static const char *func_96m_ck_parent_names[] = {
+	"apll96_ck", "alt_ck",
+};
+
+DEFINE_CLK_MUX(func_96m_ck, func_96m_ck_parent_names, NULL, 0x0,
+	       OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP2430_96M_SOURCE_SHIFT,
+	       OMAP2430_96M_SOURCE_WIDTH, 0x0, NULL);
+
+static struct clk cam_fck;
+
+static const char *cam_fck_parent_names[] = {
+	"func_96m_ck",
+};
+
+static struct clk_hw_omap cam_fck_hw = {
+	.hw = {
+		.clk = &cam_fck,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(cam_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk cam_ick;
+
+static struct clk_hw_omap cam_ick_hw = {
+	.hw = {
+		.clk = &cam_ick,
+	},
+	.ops		= &clkhwops_iclk,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(cam_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk des_ick;
+
+static struct clk_hw_omap des_ick_hw = {
+	.hw = {
+		.clk = &des_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+	.enable_bit	= OMAP24XX_EN_DES_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(des_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate dsp_fck_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
+	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel dsp_fck_clksel[] = {
+	{ .parent = &core_ck, .rates = dsp_fck_core_rates },
+	{ .parent = NULL },
+};
+
+static const char *dsp_fck_parent_names[] = {
+	"core_ck",
+};
+
+static struct clk dsp_fck;
+
+static const struct clk_ops dsp_fck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.set_rate	= &omap2_clksel_set_rate,
+	.round_rate	= &omap2_clksel_round_rate,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(dsp_fck, "dsp_clkdm", dsp_fck_clksel,
+			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+			 OMAP24XX_CLKSEL_DSP_MASK,
+			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
+			 OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, &clkhwops_wait,
+			 dsp_fck_parent_names, dsp_fck_ops);
+
+static const struct clksel_rate dss1_fck_sys_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate dss1_fck_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
+	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
+	{ .div = 5, .val = 5, .flags = RATE_IN_24XX },
+	{ .div = 6, .val = 6, .flags = RATE_IN_24XX },
+	{ .div = 8, .val = 8, .flags = RATE_IN_24XX },
+	{ .div = 9, .val = 9, .flags = RATE_IN_24XX },
+	{ .div = 12, .val = 12, .flags = RATE_IN_24XX },
+	{ .div = 16, .val = 16, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel dss1_fck_clksel[] = {
+	{ .parent = &sys_ck, .rates = dss1_fck_sys_rates },
+	{ .parent = &core_ck, .rates = dss1_fck_core_rates },
+	{ .parent = NULL },
+};
+
+static const char *dss1_fck_parent_names[] = {
+	"sys_ck", "core_ck",
+};
+
+static const struct clk_ops dss1_fck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.get_parent	= &omap2_clksel_find_parent_index,
+	.set_parent	= &omap2_clksel_set_parent,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(dss1_fck, "dss_clkdm", dss1_fck_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+			 OMAP24XX_CLKSEL_DSS1_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_DSS1_SHIFT, NULL,
+			 dss1_fck_parent_names, dss1_fck_ops);
+
+static const struct clksel_rate dss2_fck_sys_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate dss2_fck_48m_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate func_48m_apll96_rates[] = {
+	{ .div = 2, .val = 0, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate func_48m_alt_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel func_48m_clksel[] = {
+	{ .parent = &apll96_ck, .rates = func_48m_apll96_rates },
+	{ .parent = &alt_ck, .rates = func_48m_alt_rates },
+	{ .parent = NULL },
+};
+
+static const char *func_48m_ck_parent_names[] = {
+	"apll96_ck", "alt_ck",
+};
+
+static struct clk func_48m_ck;
+
+static const struct clk_ops func_48m_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.set_rate	= &omap2_clksel_set_rate,
+	.round_rate	= &omap2_clksel_round_rate,
+	.get_parent	= &omap2_clksel_find_parent_index,
+	.set_parent	= &omap2_clksel_set_parent,
+};
+
+static struct clk_hw_omap func_48m_ck_hw = {
+	.hw = {
+		.clk = &func_48m_ck,
+	},
+	.clksel		= func_48m_clksel,
+	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+	.clksel_mask	= OMAP24XX_48M_SOURCE_MASK,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(func_48m_ck, func_48m_ck_parent_names, func_48m_ck_ops);
+
+static const struct clksel dss2_fck_clksel[] = {
+	{ .parent = &sys_ck, .rates = dss2_fck_sys_rates },
+	{ .parent = &func_48m_ck, .rates = dss2_fck_48m_rates },
+	{ .parent = NULL },
+};
+
+static const char *dss2_fck_parent_names[] = {
+	"sys_ck", "func_48m_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(dss2_fck, "dss_clkdm", dss2_fck_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+			 OMAP24XX_CLKSEL_DSS2_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_DSS2_SHIFT, NULL,
+			 dss2_fck_parent_names, dss1_fck_ops);
+
+static const char *func_54m_ck_parent_names[] = {
+	"apll54_ck", "alt_ck",
+};
+
+DEFINE_CLK_MUX(func_54m_ck, func_54m_ck_parent_names, NULL, 0x0,
+	       OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+	       OMAP24XX_54M_SOURCE_SHIFT, OMAP24XX_54M_SOURCE_WIDTH, 0x0, NULL);
+
+static struct clk dss_54m_fck;
+
+static const char *dss_54m_fck_parent_names[] = {
+	"func_54m_ck",
+};
+
+static struct clk_hw_omap dss_54m_fck_hw = {
+	.hw = {
+		.clk = &dss_54m_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_TV_SHIFT,
+	.clkdm_name	= "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss_54m_fck, dss_54m_fck_parent_names, aes_ick_ops);
+
+static struct clk dss_ick;
+
+static struct clk_hw_omap dss_ick_hw = {
+	.hw = {
+		.clk = &dss_ick,
+	},
+	.ops		= &clkhwops_iclk,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
+	.clkdm_name	= "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk emul_ck;
+
+static struct clk_hw_omap emul_ck_hw = {
+	.hw = {
+		.clk = &emul_ck,
+	},
+	.enable_reg	= OMAP2430_PRCM_CLKEMUL_CTRL,
+	.enable_bit	= OMAP24XX_EMULATION_EN_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(emul_ck, dss_54m_fck_parent_names, aes_ick_ops);
+
+DEFINE_CLK_FIXED_FACTOR(func_12m_ck, "func_48m_ck", &func_48m_ck, 0x0, 1, 4);
+
+static struct clk fac_fck;
+
+static const char *fac_fck_parent_names[] = {
+	"func_12m_ck",
+};
+
+static struct clk_hw_omap fac_fck_hw = {
+	.hw = {
+		.clk = &fac_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(fac_fck, fac_fck_parent_names, aes_ick_ops);
+
+static struct clk fac_ick;
+
+static struct clk_hw_omap fac_ick_hw = {
+	.hw = {
+		.clk = &fac_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(fac_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel gfx_fck_clksel[] = {
+	{ .parent = &core_l3_ck, .rates = gfx_l3_rates },
+	{ .parent = NULL },
+};
+
+static const char *gfx_2d_fck_parent_names[] = {
+	"core_l3_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(gfx_2d_fck, "gfx_clkdm", gfx_fck_clksel,
+			 OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
+			 OMAP_CLKSEL_GFX_MASK,
+			 OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
+			 OMAP24XX_EN_2D_SHIFT, &clkhwops_wait,
+			 gfx_2d_fck_parent_names, dsp_fck_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gfx_3d_fck, "gfx_clkdm", gfx_fck_clksel,
+			 OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
+			 OMAP_CLKSEL_GFX_MASK,
+			 OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
+			 OMAP24XX_EN_3D_SHIFT, &clkhwops_wait,
+			 gfx_2d_fck_parent_names, dsp_fck_ops);
+
+static struct clk gfx_ick;
+
+static const char *gfx_ick_parent_names[] = {
+	"core_l3_ck",
+};
+
+static struct clk_hw_omap gfx_ick_hw = {
+	.hw = {
+		.clk = &gfx_ick,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP_EN_GFX_SHIFT,
+	.clkdm_name	= "gfx_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gfx_ick, gfx_ick_parent_names, aes_ick_ops);
+
+static struct clk gpio5_fck;
+
+static const char *gpio5_fck_parent_names[] = {
+	"func_32k_ck",
+};
+
+static struct clk_hw_omap gpio5_fck_hw = {
+	.hw = {
+		.clk = &gpio5_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+	.enable_bit	= OMAP2430_EN_GPIO5_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio5_fck, gpio5_fck_parent_names, aes_ick_ops);
+
+static struct clk gpio5_ick;
+
+static struct clk_hw_omap gpio5_ick_hw = {
+	.hw = {
+		.clk = &gpio5_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP2430_EN_GPIO5_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio5_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk gpios_fck;
+
+static struct clk_hw_omap gpios_fck_hw = {
+	.hw = {
+		.clk = &gpios_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpios_fck, gpio5_fck_parent_names, aes_ick_ops);
+
+static struct clk wu_l4_ick;
+
+DEFINE_STRUCT_CLK_HW_OMAP(wu_l4_ick, "wkup_clkdm");
+DEFINE_STRUCT_CLK(wu_l4_ick, dpll_ck_parent_names, core_ck_ops);
+
+static struct clk gpios_ick;
+
+static const char *gpios_ick_parent_names[] = {
+	"wu_l4_ick",
+};
+
+static struct clk_hw_omap gpios_ick_hw = {
+	.hw = {
+		.clk = &gpios_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpios_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static struct clk gpmc_fck;
+
+static struct clk_hw_omap gpmc_fck_hw = {
+	.hw = {
+		.clk = &gpmc_fck,
+	},
+	.ops		= &clkhwops_iclk,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_GPMC_SHIFT,
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpmc_fck, gfx_ick_parent_names, core_ck_ops);
+
+static const struct clksel_rate gpt_alt_rates[] = {
+	{ .div = 1, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel omap24xx_gpt_clksel[] = {
+	{ .parent = &func_32k_ck, .rates = gpt_32k_rates },
+	{ .parent = &sys_ck, .rates = gpt_sys_rates },
+	{ .parent = &alt_ck, .rates = gpt_alt_rates },
+	{ .parent = NULL },
+};
+
+static const char *gpt10_fck_parent_names[] = {
+	"func_32k_ck", "sys_ck", "alt_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt10_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT10_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT10_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt10_ick;
+
+static struct clk_hw_omap gpt10_ick_hw = {
+	.hw = {
+		.clk = &gpt10_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt10_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt11_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT11_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT11_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt11_ick;
+
+static struct clk_hw_omap gpt11_ick_hw = {
+	.hw = {
+		.clk = &gpt11_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt11_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt12_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT12_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT12_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt12_ick;
+
+static struct clk_hw_omap gpt12_ick_hw = {
+	.hw = {
+		.clk = &gpt12_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt12_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clk_ops gpt1_fck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.set_rate	= &omap2_clksel_set_rate,
+	.round_rate	= &omap2_clksel_round_rate,
+	.get_parent	= &omap2_clksel_find_parent_index,
+	.set_parent	= &omap2_clksel_set_parent,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt1_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL1),
+			 OMAP24XX_CLKSEL_GPT1_MASK,
+			 OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+			 OMAP24XX_EN_GPT1_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, gpt1_fck_ops);
+
+static struct clk gpt1_ick;
+
+static struct clk_hw_omap gpt1_ick_hw = {
+	.hw = {
+		.clk = &gpt1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt1_ick, gpios_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt2_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT2_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT2_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt2_ick;
+
+static struct clk_hw_omap gpt2_ick_hw = {
+	.hw = {
+		.clk = &gpt2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt2_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt3_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT3_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT3_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt3_ick;
+
+static struct clk_hw_omap gpt3_ick_hw = {
+	.hw = {
+		.clk = &gpt3_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt3_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt4_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT4_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT4_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt4_ick;
+
+static struct clk_hw_omap gpt4_ick_hw = {
+	.hw = {
+		.clk = &gpt4_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt4_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt5_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT5_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT5_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt5_ick;
+
+static struct clk_hw_omap gpt5_ick_hw = {
+	.hw = {
+		.clk = &gpt5_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt5_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt6_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT6_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT6_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt6_ick;
+
+static struct clk_hw_omap gpt6_ick_hw = {
+	.hw = {
+		.clk = &gpt6_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt6_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt7_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT7_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT7_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt7_ick;
+
+static struct clk_hw_omap gpt7_ick_hw = {
+	.hw = {
+		.clk = &gpt7_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt7_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk gpt8_fck;
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt8_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT8_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT8_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt8_ick;
+
+static struct clk_hw_omap gpt8_ick_hw = {
+	.hw = {
+		.clk = &gpt8_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt8_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt9_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
+			 OMAP24XX_CLKSEL_GPT9_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_GPT9_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, dss1_fck_ops);
+
+static struct clk gpt9_ick;
+
+static struct clk_hw_omap gpt9_ick_hw = {
+	.hw = {
+		.clk = &gpt9_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt9_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk hdq_fck;
+
+static struct clk_hw_omap hdq_fck_hw = {
+	.hw = {
+		.clk = &hdq_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hdq_fck, fac_fck_parent_names, aes_ick_ops);
+
+static struct clk hdq_ick;
+
+static struct clk_hw_omap hdq_ick_hw = {
+	.hw = {
+		.clk = &hdq_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hdq_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk i2c1_ick;
+
+static struct clk_hw_omap i2c1_ick_hw = {
+	.hw = {
+		.clk = &i2c1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP2420_EN_I2C1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c1_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk i2c2_ick;
+
+static struct clk_hw_omap i2c2_ick_hw = {
+	.hw = {
+		.clk = &i2c2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP2420_EN_I2C2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c2_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk i2chs1_fck;
+
+static struct clk_hw_omap i2chs1_fck_hw = {
+	.hw = {
+		.clk = &i2chs1_fck,
+	},
+	.ops		= &clkhwops_omap2430_i2chs_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+	.enable_bit	= OMAP2430_EN_I2CHS1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2chs1_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk i2chs2_fck;
+
+static struct clk_hw_omap i2chs2_fck_hw = {
+	.hw = {
+		.clk = &i2chs2_fck,
+	},
+	.ops		= &clkhwops_omap2430_i2chs_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+	.enable_bit	= OMAP2430_EN_I2CHS2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2chs2_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk icr_ick;
+
+static struct clk_hw_omap icr_ick_hw = {
+	.hw = {
+		.clk = &icr_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP2430_EN_ICR_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(icr_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static const struct clksel dsp_ick_clksel[] = {
+	{ .parent = &dsp_fck, .rates = dsp_ick_rates },
+	{ .parent = NULL },
+};
+
+static const char *iva2_1_ick_parent_names[] = {
+	"dsp_fck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(iva2_1_ick, "dsp_clkdm", dsp_ick_clksel,
+			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+			 OMAP24XX_CLKSEL_DSP_IF_MASK,
+			 OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
+			 OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, &clkhwops_wait,
+			 iva2_1_ick_parent_names, dsp_fck_ops);
+
+static struct clk mailboxes_ick;
+
+static struct clk_hw_omap mailboxes_ick_hw = {
+	.hw = {
+		.clk = &mailboxes_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_MAILBOXES_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mailboxes_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate common_mcbsp_96m_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel mcbsp_fck_clksel[] = {
+	{ .parent = &func_96m_ck, .rates = common_mcbsp_96m_rates },
+	{ .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
+	{ .parent = NULL },
+};
+
+static const char *mcbsp1_fck_parent_names[] = {
+	"func_96m_ck", "mcbsp_clks",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp1_fck, "core_l4_clkdm", mcbsp_fck_clksel,
+			 OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+			 OMAP2_MCBSP1_CLKS_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_MCBSP1_SHIFT, &clkhwops_wait,
+			 mcbsp1_fck_parent_names, dss1_fck_ops);
+
+static struct clk mcbsp1_ick;
+
+static struct clk_hw_omap mcbsp1_ick_hw = {
+	.hw = {
+		.clk = &mcbsp1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_MCBSP1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp1_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp2_fck, "core_l4_clkdm", mcbsp_fck_clksel,
+			 OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+			 OMAP2_MCBSP2_CLKS_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP24XX_EN_MCBSP2_SHIFT, &clkhwops_wait,
+			 mcbsp1_fck_parent_names, dss1_fck_ops);
+
+static struct clk mcbsp2_ick;
+
+static struct clk_hw_omap mcbsp2_ick_hw = {
+	.hw = {
+		.clk = &mcbsp2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_MCBSP2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp2_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp3_fck, "core_l4_clkdm", mcbsp_fck_clksel,
+			 OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
+			 OMAP2_MCBSP3_CLKS_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+			 OMAP2430_EN_MCBSP3_SHIFT, &clkhwops_wait,
+			 mcbsp1_fck_parent_names, dss1_fck_ops);
+
+static struct clk mcbsp3_ick;
+
+static struct clk_hw_omap mcbsp3_ick_hw = {
+	.hw = {
+		.clk = &mcbsp3_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP2430_EN_MCBSP3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp3_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp4_fck, "core_l4_clkdm", mcbsp_fck_clksel,
+			 OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
+			 OMAP2_MCBSP4_CLKS_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+			 OMAP2430_EN_MCBSP4_SHIFT, &clkhwops_wait,
+			 mcbsp1_fck_parent_names, dss1_fck_ops);
+
+static struct clk mcbsp4_ick;
+
+static struct clk_hw_omap mcbsp4_ick_hw = {
+	.hw = {
+		.clk = &mcbsp4_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP2430_EN_MCBSP4_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp4_ick, aes_ick_parent_names, aes_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp5_fck, "core_l4_clkdm", mcbsp_fck_clksel,
+			 OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
+			 OMAP2_MCBSP5_CLKS_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+			 OMAP2430_EN_MCBSP5_SHIFT, &clkhwops_wait,
+			 mcbsp1_fck_parent_names, dss1_fck_ops);
+
+static struct clk mcbsp5_ick;
+
+static struct clk_hw_omap mcbsp5_ick_hw = {
+	.hw = {
+		.clk = &mcbsp5_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP2430_EN_MCBSP5_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp5_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mcspi1_fck;
+
+static const char *mcspi1_fck_parent_names[] = {
+	"func_48m_ck",
+};
+
+static struct clk_hw_omap mcspi1_fck_hw = {
+	.hw = {
+		.clk = &mcspi1_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi1_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk mcspi1_ick;
+
+static struct clk_hw_omap mcspi1_ick_hw = {
+	.hw = {
+		.clk = &mcspi1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi1_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mcspi2_fck;
+
+static struct clk_hw_omap mcspi2_fck_hw = {
+	.hw = {
+		.clk = &mcspi2_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi2_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk mcspi2_ick;
+
+static struct clk_hw_omap mcspi2_ick_hw = {
+	.hw = {
+		.clk = &mcspi2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi2_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mcspi3_fck;
+
+static struct clk_hw_omap mcspi3_fck_hw = {
+	.hw = {
+		.clk = &mcspi3_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+	.enable_bit	= OMAP2430_EN_MCSPI3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi3_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk mcspi3_ick;
+
+static struct clk_hw_omap mcspi3_ick_hw = {
+	.hw = {
+		.clk = &mcspi3_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP2430_EN_MCSPI3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi3_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate mdm_ick_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_243X },
+	{ .div = 4, .val = 4, .flags = RATE_IN_243X },
+	{ .div = 6, .val = 6, .flags = RATE_IN_243X },
+	{ .div = 9, .val = 9, .flags = RATE_IN_243X },
+	{ .div = 0 }
+};
+
+static const struct clksel mdm_ick_clksel[] = {
+	{ .parent = &core_ck, .rates = mdm_ick_core_rates },
+	{ .parent = NULL },
+};
+
+static const char *mdm_ick_parent_names[] = {
+	"core_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(mdm_ick, "mdm_clkdm", mdm_ick_clksel,
+			 OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_CLKSEL),
+			 OMAP2430_CLKSEL_MDM_MASK,
+			 OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
+			 OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT,
+			 &clkhwops_iclk_wait, mdm_ick_parent_names,
+			 dsp_fck_ops);
+
+static struct clk mdm_intc_ick;
+
+static struct clk_hw_omap mdm_intc_ick_hw = {
+	.hw = {
+		.clk = &mdm_intc_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP2430_EN_MDM_INTC_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mdm_intc_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mdm_osc_ck;
+
+static struct clk_hw_omap mdm_osc_ck_hw = {
+	.hw = {
+		.clk = &mdm_osc_ck,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP2430_EN_OSC_SHIFT,
+	.clkdm_name	= "mdm_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mdm_osc_ck, sys_ck_parent_names, aes_ick_ops);
+
+static struct clk mmchs1_fck;
+
+static struct clk_hw_omap mmchs1_fck_hw = {
+	.hw = {
+		.clk = &mmchs1_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+	.enable_bit	= OMAP2430_EN_MMCHS1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs1_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk mmchs1_ick;
+
+static struct clk_hw_omap mmchs1_ick_hw = {
+	.hw = {
+		.clk = &mmchs1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP2430_EN_MMCHS1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs1_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mmchs2_fck;
+
+static struct clk_hw_omap mmchs2_fck_hw = {
+	.hw = {
+		.clk = &mmchs2_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+	.enable_bit	= OMAP2430_EN_MMCHS2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs2_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk mmchs2_ick;
+
+static struct clk_hw_omap mmchs2_ick_hw = {
+	.hw = {
+		.clk = &mmchs2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP2430_EN_MMCHS2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs2_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk mmchsdb1_fck;
+
+static struct clk_hw_omap mmchsdb1_fck_hw = {
+	.hw = {
+		.clk = &mmchsdb1_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+	.enable_bit	= OMAP2430_EN_MMCHSDB1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchsdb1_fck, gpio5_fck_parent_names, aes_ick_ops);
+
+static struct clk mmchsdb2_fck;
+
+static struct clk_hw_omap mmchsdb2_fck_hw = {
+	.hw = {
+		.clk = &mmchsdb2_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+	.enable_bit	= OMAP2430_EN_MMCHSDB2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchsdb2_fck, gpio5_fck_parent_names, aes_ick_ops);
+
+DEFINE_CLK_DIVIDER(mpu_ck, "core_ck", &core_ck, 0x0,
+		   OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
+		   OMAP24XX_CLKSEL_MPU_SHIFT, OMAP24XX_CLKSEL_MPU_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk mpu_wdt_fck;
+
+static struct clk_hw_omap mpu_wdt_fck_hw = {
+	.hw = {
+		.clk = &mpu_wdt_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mpu_wdt_fck, gpio5_fck_parent_names, aes_ick_ops);
+
+static struct clk mpu_wdt_ick;
+
+static struct clk_hw_omap mpu_wdt_ick_hw = {
+	.hw = {
+		.clk = &mpu_wdt_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mpu_wdt_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static struct clk mspro_fck;
+
+static struct clk_hw_omap mspro_fck_hw = {
+	.hw = {
+		.clk = &mspro_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mspro_fck, cam_fck_parent_names, aes_ick_ops);
+
+static struct clk mspro_ick;
+
+static struct clk_hw_omap mspro_ick_hw = {
+	.hw = {
+		.clk = &mspro_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mspro_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk omapctrl_ick;
+
+static struct clk_hw_omap omapctrl_ick_hw = {
+	.hw = {
+		.clk = &omapctrl_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP24XX_EN_OMAPCTRL_SHIFT,
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(omapctrl_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static struct clk pka_ick;
+
+static struct clk_hw_omap pka_ick_hw = {
+	.hw = {
+		.clk = &pka_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+	.enable_bit	= OMAP24XX_EN_PKA_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(pka_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk rng_ick;
+
+static struct clk_hw_omap rng_ick_hw = {
+	.hw = {
+		.clk = &rng_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+	.enable_bit	= OMAP24XX_EN_RNG_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(rng_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk sdma_fck;
+
+DEFINE_STRUCT_CLK_HW_OMAP(sdma_fck, "core_l3_clkdm");
+DEFINE_STRUCT_CLK(sdma_fck, gfx_ick_parent_names, core_ck_ops);
+
+static struct clk sdma_ick;
+
+static struct clk_hw_omap sdma_ick_hw = {
+	.hw = {
+		.clk = &sdma_ick,
+	},
+	.ops		= &clkhwops_iclk,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_SDMA_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sdma_ick, gfx_ick_parent_names, core_ck_ops);
+
+static struct clk sdrc_ick;
+
+static struct clk_hw_omap sdrc_ick_hw = {
+	.hw = {
+		.clk = &sdrc_ick,
+	},
+	.ops		= &clkhwops_iclk,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP2430_EN_SDRC_SHIFT,
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sdrc_ick, gfx_ick_parent_names, core_ck_ops);
+
+static struct clk sha_ick;
+
+static struct clk_hw_omap sha_ick_hw = {
+	.hw = {
+		.clk = &sha_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
+	.enable_bit	= OMAP24XX_EN_SHA_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sha_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk ssi_l4_ick;
+
+static struct clk_hw_omap ssi_l4_ick_hw = {
+	.hw = {
+		.clk = &ssi_l4_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP24XX_EN_SSI_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(ssi_l4_ick, aes_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate ssi_ssr_sst_fck_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
+	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
+	{ .div = 5, .val = 5, .flags = RATE_IN_243X },
+	{ .div = 0 }
+};
+
+static const struct clksel ssi_ssr_sst_fck_clksel[] = {
+	{ .parent = &core_ck, .rates = ssi_ssr_sst_fck_core_rates },
+	{ .parent = NULL },
+};
+
+static const char *ssi_ssr_sst_fck_parent_names[] = {
+	"core_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_sst_fck, "core_l3_clkdm",
+			 ssi_ssr_sst_fck_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+			 OMAP24XX_CLKSEL_SSI_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+			 OMAP24XX_EN_SSI_SHIFT, &clkhwops_wait,
+			 ssi_ssr_sst_fck_parent_names, dsp_fck_ops);
+
+static struct clk sync_32k_ick;
+
+static struct clk_hw_omap sync_32k_ick_hw = {
+	.hw = {
+		.clk = &sync_32k_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP24XX_EN_32KSYNC_SHIFT,
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sync_32k_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static const struct clksel_rate common_clkout_src_core_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate common_clkout_src_sys_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate common_clkout_src_96m_rates[] = {
+	{ .div = 1, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate common_clkout_src_54m_rates[] = {
+	{ .div = 1, .val = 3, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel common_clkout_src_clksel[] = {
+	{ .parent = &core_ck, .rates = common_clkout_src_core_rates },
+	{ .parent = &sys_ck, .rates = common_clkout_src_sys_rates },
+	{ .parent = &func_96m_ck, .rates = common_clkout_src_96m_rates },
+	{ .parent = &func_54m_ck, .rates = common_clkout_src_54m_rates },
+	{ .parent = NULL },
+};
+
+static const char *sys_clkout_src_parent_names[] = {
+	"core_ck", "sys_ck", "func_96m_ck", "func_54m_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(sys_clkout_src, "wkup_clkdm", common_clkout_src_clksel,
+			 OMAP2430_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_SOURCE_MASK,
+			 OMAP2430_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_EN_SHIFT,
+			 NULL, sys_clkout_src_parent_names, gpt1_fck_ops);
+
+DEFINE_CLK_DIVIDER(sys_clkout, "sys_clkout_src", &sys_clkout_src, 0x0,
+		   OMAP2430_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_DIV_SHIFT,
+		   OMAP24XX_CLKOUT_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
+
+static struct clk uart1_fck;
+
+static struct clk_hw_omap uart1_fck_hw = {
+	.hw = {
+		.clk = &uart1_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart1_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk uart1_ick;
+
+static struct clk_hw_omap uart1_ick_hw = {
+	.hw = {
+		.clk = &uart1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart1_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk uart2_fck;
+
+static struct clk_hw_omap uart2_fck_hw = {
+	.hw = {
+		.clk = &uart2_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart2_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk uart2_ick;
+
+static struct clk_hw_omap uart2_ick_hw = {
+	.hw = {
+		.clk = &uart2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart2_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk uart3_fck;
+
+static struct clk_hw_omap uart3_fck_hw = {
+	.hw = {
+		.clk = &uart3_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart3_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static struct clk uart3_ick;
+
+static struct clk_hw_omap uart3_ick_hw = {
+	.hw = {
+		.clk = &uart3_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart3_ick, aes_ick_parent_names, aes_ick_ops);
+
+static struct clk usb_fck;
+
+static struct clk_hw_omap usb_fck_hw = {
+	.hw = {
+		.clk = &usb_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
+	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usb_fck, mcspi1_fck_parent_names, aes_ick_ops);
+
+static const struct clksel_rate usb_l4_ick_core_l3_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel usb_l4_ick_clksel[] = {
+	{ .parent = &core_l3_ck, .rates = usb_l4_ick_core_l3_rates },
+	{ .parent = NULL },
+};
+
+static const char *usb_l4_ick_parent_names[] = {
+	"core_l3_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(usb_l4_ick, "core_l4_clkdm", usb_l4_ick_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+			 OMAP24XX_CLKSEL_USB_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+			 OMAP24XX_EN_USB_SHIFT, &clkhwops_iclk_wait,
+			 usb_l4_ick_parent_names, dsp_fck_ops);
+
+static struct clk usbhs_ick;
+
+static struct clk_hw_omap usbhs_ick_hw = {
+	.hw = {
+		.clk = &usbhs_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP2430_EN_USBHS_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usbhs_ick, gfx_ick_parent_names, aes_ick_ops);
+
+static struct clk virt_prcm_set;
+
+static const char *virt_prcm_set_parent_names[] = {
+	"mpu_ck",
+};
+
+static const struct clk_ops virt_prcm_set_ops = {
+	.recalc_rate	= &omap2_table_mpu_recalc,
+	.set_rate	= &omap2_select_table_rate,
+	.round_rate	= &omap2_round_to_table_rate,
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(virt_prcm_set, NULL);
+DEFINE_STRUCT_CLK(virt_prcm_set, virt_prcm_set_parent_names, virt_prcm_set_ops);
+
+static struct clk wdt1_ick;
+
+static struct clk_hw_omap wdt1_ick_hw = {
+	.hw = {
+		.clk = &wdt1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP24XX_EN_WDT1_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt1_ick, gpios_ick_parent_names, aes_ick_ops);
+
+static struct clk wdt1_osc_ck;
+
+static const struct clk_ops wdt1_osc_ck_ops = {};
+
+DEFINE_STRUCT_CLK_HW_OMAP(wdt1_osc_ck, NULL);
+DEFINE_STRUCT_CLK(wdt1_osc_ck, sys_ck_parent_names, wdt1_osc_ck_ops);
+
+static struct clk wdt4_fck;
+
+static struct clk_hw_omap wdt4_fck_hw = {
+	.hw = {
+		.clk = &wdt4_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt4_fck, gpio5_fck_parent_names, aes_ick_ops);
+
+static struct clk wdt4_ick;
+
+static struct clk_hw_omap wdt4_ick_hw = {
+	.hw = {
+		.clk = &wdt4_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt4_ick, aes_ick_parent_names, aes_ick_ops);
+
+/*
+ * clkdev integration
+ */
+
+static struct omap_clk omap2430_clks[] = {
+	/* external root sources */
+	CLK(NULL,	"func_32k_ck",	&func_32k_ck,	CK_243X),
+	CLK(NULL,	"secure_32k_ck", &secure_32k_ck, CK_243X),
+	CLK(NULL,	"osc_ck",	&osc_ck,	CK_243X),
+	CLK("twl",	"fck",		&osc_ck,	CK_243X),
+	CLK(NULL,	"sys_ck",	&sys_ck,	CK_243X),
+	CLK(NULL,	"alt_ck",	&alt_ck,	CK_243X),
+	CLK(NULL,	"mcbsp_clks",	&mcbsp_clks,	CK_243X),
+	/* internal analog sources */
+	CLK(NULL,	"dpll_ck",	&dpll_ck,	CK_243X),
+	CLK(NULL,	"apll96_ck",	&apll96_ck,	CK_243X),
+	CLK(NULL,	"apll54_ck",	&apll54_ck,	CK_243X),
+	/* internal prcm root sources */
+	CLK(NULL,	"func_54m_ck",	&func_54m_ck,	CK_243X),
+	CLK(NULL,	"core_ck",	&core_ck,	CK_243X),
+	CLK(NULL,	"func_96m_ck",	&func_96m_ck,	CK_243X),
+	CLK(NULL,	"func_48m_ck",	&func_48m_ck,	CK_243X),
+	CLK(NULL,	"func_12m_ck",	&func_12m_ck,	CK_243X),
+	CLK(NULL,	"ck_wdt1_osc",	&wdt1_osc_ck,	CK_243X),
+	CLK(NULL,	"sys_clkout_src", &sys_clkout_src, CK_243X),
+	CLK(NULL,	"sys_clkout",	&sys_clkout,	CK_243X),
+	CLK(NULL,	"emul_ck",	&emul_ck,	CK_243X),
+	/* mpu domain clocks */
+	CLK(NULL,	"mpu_ck",	&mpu_ck,	CK_243X),
+	/* dsp domain clocks */
+	CLK(NULL,	"dsp_fck",	&dsp_fck,	CK_243X),
+	CLK(NULL,	"iva2_1_ick",	&iva2_1_ick,	CK_243X),
+	/* GFX domain clocks */
+	CLK(NULL,	"gfx_3d_fck",	&gfx_3d_fck,	CK_243X),
+	CLK(NULL,	"gfx_2d_fck",	&gfx_2d_fck,	CK_243X),
+	CLK(NULL,	"gfx_ick",	&gfx_ick,	CK_243X),
+	/* Modem domain clocks */
+	CLK(NULL,	"mdm_ick",	&mdm_ick,	CK_243X),
+	CLK(NULL,	"mdm_osc_ck",	&mdm_osc_ck,	CK_243X),
+	/* DSS domain clocks */
+	CLK("omapdss_dss",	"ick",		&dss_ick,	CK_243X),
+	CLK(NULL,	"dss_ick",		&dss_ick,	CK_243X),
+	CLK(NULL,	"dss1_fck",		&dss1_fck,	CK_243X),
+	CLK(NULL,	"dss2_fck",	&dss2_fck,	CK_243X),
+	CLK(NULL,	"dss_54m_fck",	&dss_54m_fck,	CK_243X),
+	/* L3 domain clocks */
+	CLK(NULL,	"core_l3_ck",	&core_l3_ck,	CK_243X),
+	CLK(NULL,	"ssi_fck",	&ssi_ssr_sst_fck, CK_243X),
+	CLK(NULL,	"usb_l4_ick",	&usb_l4_ick,	CK_243X),
+	/* L4 domain clocks */
+	CLK(NULL,	"l4_ck",	&l4_ck,		CK_243X),
+	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_243X),
+	CLK(NULL,	"wu_l4_ick",	&wu_l4_ick,	CK_243X),
+	/* virtual meta-group clock */
+	CLK(NULL,	"virt_prcm_set", &virt_prcm_set, CK_243X),
+	/* general l4 interface ck, multi-parent functional clk */
+	CLK(NULL,	"gpt1_ick",	&gpt1_ick,	CK_243X),
+	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_243X),
+	CLK(NULL,	"gpt2_ick",	&gpt2_ick,	CK_243X),
+	CLK(NULL,	"gpt2_fck",	&gpt2_fck,	CK_243X),
+	CLK(NULL,	"gpt3_ick",	&gpt3_ick,	CK_243X),
+	CLK(NULL,	"gpt3_fck",	&gpt3_fck,	CK_243X),
+	CLK(NULL,	"gpt4_ick",	&gpt4_ick,	CK_243X),
+	CLK(NULL,	"gpt4_fck",	&gpt4_fck,	CK_243X),
+	CLK(NULL,	"gpt5_ick",	&gpt5_ick,	CK_243X),
+	CLK(NULL,	"gpt5_fck",	&gpt5_fck,	CK_243X),
+	CLK(NULL,	"gpt6_ick",	&gpt6_ick,	CK_243X),
+	CLK(NULL,	"gpt6_fck",	&gpt6_fck,	CK_243X),
+	CLK(NULL,	"gpt7_ick",	&gpt7_ick,	CK_243X),
+	CLK(NULL,	"gpt7_fck",	&gpt7_fck,	CK_243X),
+	CLK(NULL,	"gpt8_ick",	&gpt8_ick,	CK_243X),
+	CLK(NULL,	"gpt8_fck",	&gpt8_fck,	CK_243X),
+	CLK(NULL,	"gpt9_ick",	&gpt9_ick,	CK_243X),
+	CLK(NULL,	"gpt9_fck",	&gpt9_fck,	CK_243X),
+	CLK(NULL,	"gpt10_ick",	&gpt10_ick,	CK_243X),
+	CLK(NULL,	"gpt10_fck",	&gpt10_fck,	CK_243X),
+	CLK(NULL,	"gpt11_ick",	&gpt11_ick,	CK_243X),
+	CLK(NULL,	"gpt11_fck",	&gpt11_fck,	CK_243X),
+	CLK(NULL,	"gpt12_ick",	&gpt12_ick,	CK_243X),
+	CLK(NULL,	"gpt12_fck",	&gpt12_fck,	CK_243X),
+	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick,	CK_243X),
+	CLK(NULL,	"mcbsp1_ick",	&mcbsp1_ick,	CK_243X),
+	CLK(NULL,	"mcbsp1_fck",	&mcbsp1_fck,	CK_243X),
+	CLK("omap-mcbsp.2", "ick",	&mcbsp2_ick,	CK_243X),
+	CLK(NULL,	"mcbsp2_ick",	&mcbsp2_ick,	CK_243X),
+	CLK(NULL,	"mcbsp2_fck",	&mcbsp2_fck,	CK_243X),
+	CLK("omap-mcbsp.3", "ick",	&mcbsp3_ick,	CK_243X),
+	CLK(NULL,	"mcbsp3_ick",	&mcbsp3_ick,	CK_243X),
+	CLK(NULL,	"mcbsp3_fck",	&mcbsp3_fck,	CK_243X),
+	CLK("omap-mcbsp.4", "ick",	&mcbsp4_ick,	CK_243X),
+	CLK(NULL,	"mcbsp4_ick",	&mcbsp4_ick,	CK_243X),
+	CLK(NULL,	"mcbsp4_fck",	&mcbsp4_fck,	CK_243X),
+	CLK("omap-mcbsp.5", "ick",	&mcbsp5_ick,	CK_243X),
+	CLK(NULL,	"mcbsp5_ick",	&mcbsp5_ick,	CK_243X),
+	CLK(NULL,	"mcbsp5_fck",	&mcbsp5_fck,	CK_243X),
+	CLK("omap2_mcspi.1", "ick",	&mcspi1_ick,	CK_243X),
+	CLK(NULL,	"mcspi1_ick",	&mcspi1_ick,	CK_243X),
+	CLK(NULL,	"mcspi1_fck",	&mcspi1_fck,	CK_243X),
+	CLK("omap2_mcspi.2", "ick",	&mcspi2_ick,	CK_243X),
+	CLK(NULL,	"mcspi2_ick",	&mcspi2_ick,	CK_243X),
+	CLK(NULL,	"mcspi2_fck",	&mcspi2_fck,	CK_243X),
+	CLK("omap2_mcspi.3", "ick",	&mcspi3_ick,	CK_243X),
+	CLK(NULL,	"mcspi3_ick",	&mcspi3_ick,	CK_243X),
+	CLK(NULL,	"mcspi3_fck",	&mcspi3_fck,	CK_243X),
+	CLK(NULL,	"uart1_ick",	&uart1_ick,	CK_243X),
+	CLK(NULL,	"uart1_fck",	&uart1_fck,	CK_243X),
+	CLK(NULL,	"uart2_ick",	&uart2_ick,	CK_243X),
+	CLK(NULL,	"uart2_fck",	&uart2_fck,	CK_243X),
+	CLK(NULL,	"uart3_ick",	&uart3_ick,	CK_243X),
+	CLK(NULL,	"uart3_fck",	&uart3_fck,	CK_243X),
+	CLK(NULL,	"gpios_ick",	&gpios_ick,	CK_243X),
+	CLK(NULL,	"gpios_fck",	&gpios_fck,	CK_243X),
+	CLK("omap_wdt",	"ick",		&mpu_wdt_ick,	CK_243X),
+	CLK(NULL,	"mpu_wdt_ick",	&mpu_wdt_ick,	CK_243X),
+	CLK(NULL,	"mpu_wdt_fck",	&mpu_wdt_fck,	CK_243X),
+	CLK(NULL,	"sync_32k_ick",	&sync_32k_ick,	CK_243X),
+	CLK(NULL,	"wdt1_ick",	&wdt1_ick,	CK_243X),
+	CLK(NULL,	"omapctrl_ick",	&omapctrl_ick,	CK_243X),
+	CLK(NULL,	"icr_ick",	&icr_ick,	CK_243X),
+	CLK("omap24xxcam", "fck",	&cam_fck,	CK_243X),
+	CLK(NULL,	"cam_fck",	&cam_fck,	CK_243X),
+	CLK("omap24xxcam", "ick",	&cam_ick,	CK_243X),
+	CLK(NULL,	"cam_ick",	&cam_ick,	CK_243X),
+	CLK(NULL,	"mailboxes_ick", &mailboxes_ick,	CK_243X),
+	CLK(NULL,	"wdt4_ick",	&wdt4_ick,	CK_243X),
+	CLK(NULL,	"wdt4_fck",	&wdt4_fck,	CK_243X),
+	CLK(NULL,	"mspro_ick",	&mspro_ick,	CK_243X),
+	CLK(NULL,	"mspro_fck",	&mspro_fck,	CK_243X),
+	CLK(NULL,	"fac_ick",	&fac_ick,	CK_243X),
+	CLK(NULL,	"fac_fck",	&fac_fck,	CK_243X),
+	CLK("omap_hdq.0", "ick",	&hdq_ick,	CK_243X),
+	CLK(NULL,	"hdq_ick",	&hdq_ick,	CK_243X),
+	CLK("omap_hdq.1", "fck",	&hdq_fck,	CK_243X),
+	CLK(NULL,	"hdq_fck",	&hdq_fck,	CK_243X),
+	CLK("omap_i2c.1", "ick",	&i2c1_ick,	CK_243X),
+	CLK(NULL,	"i2c1_ick",	&i2c1_ick,	CK_243X),
+	CLK(NULL,	"i2chs1_fck",	&i2chs1_fck,	CK_243X),
+	CLK("omap_i2c.2", "ick",	&i2c2_ick,	CK_243X),
+	CLK(NULL,	"i2c2_ick",	&i2c2_ick,	CK_243X),
+	CLK(NULL,	"i2chs2_fck",	&i2chs2_fck,	CK_243X),
+	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_243X),
+	CLK(NULL,	"sdma_fck",	&sdma_fck,	CK_243X),
+	CLK(NULL,	"sdma_ick",	&sdma_ick,	CK_243X),
+	CLK(NULL,	"sdrc_ick",	&sdrc_ick,	CK_243X),
+	CLK(NULL,	"des_ick",	&des_ick,	CK_243X),
+	CLK("omap-sham",	"ick",	&sha_ick,	CK_243X),
+	CLK("omap_rng",	"ick",		&rng_ick,	CK_243X),
+	CLK(NULL,	"rng_ick",	&rng_ick,	CK_243X),
+	CLK("omap-aes",	"ick",	&aes_ick,	CK_243X),
+	CLK(NULL,	"pka_ick",	&pka_ick,	CK_243X),
+	CLK(NULL,	"usb_fck",	&usb_fck,	CK_243X),
+	CLK("musb-omap2430",	"ick",	&usbhs_ick,	CK_243X),
+	CLK(NULL,	"usbhs_ick",	&usbhs_ick,	CK_243X),
+	CLK("omap_hsmmc.0", "ick",	&mmchs1_ick,	CK_243X),
+	CLK(NULL,	"mmchs1_ick",	&mmchs1_ick,	CK_243X),
+	CLK(NULL,	"mmchs1_fck",	&mmchs1_fck,	CK_243X),
+	CLK("omap_hsmmc.1", "ick",	&mmchs2_ick,	CK_243X),
+	CLK(NULL,	"mmchs2_ick",	&mmchs2_ick,	CK_243X),
+	CLK(NULL,	"mmchs2_fck",	&mmchs2_fck,	CK_243X),
+	CLK(NULL,	"gpio5_ick",	&gpio5_ick,	CK_243X),
+	CLK(NULL,	"gpio5_fck",	&gpio5_fck,	CK_243X),
+	CLK(NULL,	"mdm_intc_ick",	&mdm_intc_ick,	CK_243X),
+	CLK("omap_hsmmc.0", "mmchsdb_fck",	&mmchsdb1_fck,	CK_243X),
+	CLK(NULL,	 "mmchsdb1_fck",	&mmchsdb1_fck,	CK_243X),
+	CLK("omap_hsmmc.1", "mmchsdb_fck",	&mmchsdb2_fck,	CK_243X),
+	CLK(NULL,	 "mmchsdb2_fck",	&mmchsdb2_fck,	CK_243X),
+	CLK(NULL,	"timer_32k_ck",  &func_32k_ck,   CK_243X),
+	CLK(NULL,	"timer_sys_ck",	&sys_ck,	CK_243X),
+	CLK(NULL,	"timer_ext_ck",	&alt_ck,	CK_243X),
+	CLK(NULL,	"cpufreq_ck",	&virt_prcm_set,	CK_243X),
+};
+
+static const char *enable_init_clks[] = {
+	"apll96_ck",
+	"apll54_ck",
+	"sync_32k_ick",
+	"omapctrl_ick",
+	"gpmc_fck",
+	"sdrc_ick",
+};
+
+/*
+ * init code
+ */
+
+int __init omap2430_clk_init(void)
+{
+	struct omap_clk *c;
+
+	prcm_clksrc_ctrl = OMAP2430_PRCM_CLKSRC_CTRL;
+	cpu_mask = RATE_IN_243X;
+	rate_table = omap2430_rate_table;
+
+	omap2xxx_clkt_dpllcore_init(&dpll_ck_hw.hw);
+
+	omap2xxx_clkt_vps_check_bootloader_rates();
+
+	for (c = omap2430_clks; c < omap2430_clks + ARRAY_SIZE(omap2430_clks);
+	     c++) {
+		clkdev_add(&c->lk);
+		if (!__clk_init(NULL, c->lk.clk))
+			omap2_init_clk_hw_omap_clocks(c->lk.clk);
+	}
+
+	omap2_clk_disable_autoidle_all();
+
+	omap2_clk_enable_init_clocks(enable_init_clks,
+				     ARRAY_SIZE(enable_init_clks));
+
+	pr_info("Clocking rate (Crystal/DPLL/MPU): %ld.%01ld/%ld/%ld MHz\n",
+		(clk_get_rate(&sys_ck) / 1000000),
+		(clk_get_rate(&sys_ck) / 100000) % 10,
+		(clk_get_rate(&dpll_ck) / 1000000),
+		(clk_get_rate(&mpu_ck) / 1000000));
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap2/cclock33xx_data.c b/arch/arm/mach-omap2/cclock33xx_data.c
new file mode 100644
index 0000000..ea64ad6
--- /dev/null
+++ b/arch/arm/mach-omap2/cclock33xx_data.c
@@ -0,0 +1,961 @@
+/*
+ * AM33XX Clock data
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Vaibhav Hiremath <hvaibhav@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/clk-private.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+
+#include "am33xx.h"
+#include "soc.h"
+#include "iomap.h"
+#include "clock.h"
+#include "control.h"
+#include "cm.h"
+#include "cm33xx.h"
+#include "cm-regbits-33xx.h"
+#include "prm.h"
+
+/* Modulemode control */
+#define AM33XX_MODULEMODE_HWCTRL_SHIFT		0
+#define AM33XX_MODULEMODE_SWCTRL_SHIFT		1
+
+/*LIST_HEAD(clocks);*/
+
+/* Root clocks */
+
+/* RTC 32k */
+DEFINE_CLK_FIXED_RATE(clk_32768_ck, CLK_IS_ROOT, 32768, 0x0);
+
+/* On-Chip 32KHz RC OSC */
+DEFINE_CLK_FIXED_RATE(clk_rc32k_ck, CLK_IS_ROOT, 32000, 0x0);
+
+/* Crystal input clks */
+DEFINE_CLK_FIXED_RATE(virt_19200000_ck, CLK_IS_ROOT, 19200000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_24000000_ck, CLK_IS_ROOT, 24000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_25000000_ck, CLK_IS_ROOT, 25000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_26000000_ck, CLK_IS_ROOT, 26000000, 0x0);
+
+/* Oscillator clock */
+/* 19.2, 24, 25 or 26 MHz */
+static const char *sys_clkin_ck_parents[] = {
+	"virt_19200000_ck", "virt_24000000_ck", "virt_25000000_ck",
+	"virt_26000000_ck",
+};
+
+/*
+ * sys_clk in: input to the dpll and also used as funtional clock for,
+ *   adc_tsc, smartreflex0-1, timer1-7, mcasp0-1, dcan0-1, cefuse
+ *
+ */
+DEFINE_CLK_MUX(sys_clkin_ck, sys_clkin_ck_parents, NULL, 0x0,
+	       AM33XX_CTRL_REGADDR(AM33XX_CONTROL_STATUS),
+	       AM33XX_CONTROL_STATUS_SYSBOOT1_SHIFT,
+	       AM33XX_CONTROL_STATUS_SYSBOOT1_WIDTH,
+	       0, NULL);
+
+/* External clock - 12 MHz */
+DEFINE_CLK_FIXED_RATE(tclkin_ck, CLK_IS_ROOT, 12000000, 0x0);
+
+/* Module clocks and DPLL outputs */
+
+/* DPLL_CORE */
+static struct dpll_data dpll_core_dd = {
+	.mult_div1_reg	= AM33XX_CM_CLKSEL_DPLL_CORE,
+	.clk_bypass	= &sys_clkin_ck,
+	.clk_ref	= &sys_clkin_ck,
+	.control_reg	= AM33XX_CM_CLKMODE_DPLL_CORE,
+	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	.idlest_reg	= AM33XX_CM_IDLEST_DPLL_CORE,
+	.mult_mask	= AM33XX_DPLL_MULT_MASK,
+	.div1_mask	= AM33XX_DPLL_DIV_MASK,
+	.enable_mask	= AM33XX_DPLL_EN_MASK,
+	.idlest_mask	= AM33XX_ST_DPLL_CLK_MASK,
+	.max_multiplier	= 2047,
+	.max_divider	= 128,
+	.min_divider	= 1,
+};
+
+/* CLKDCOLDO output */
+static const char *dpll_core_ck_parents[] = {
+	"sys_clkin_ck",
+};
+
+static struct clk dpll_core_ck;
+
+static const struct clk_ops dpll_core_ck_ops = {
+	.recalc_rate	= &omap3_dpll_recalc,
+	.get_parent	= &omap2_init_dpll_parent,
+};
+
+static struct clk_hw_omap dpll_core_ck_hw = {
+	.hw	= {
+		.clk	= &dpll_core_ck,
+	},
+	.dpll_data	= &dpll_core_dd,
+	.ops		= &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_core_ck, dpll_core_ck_parents, dpll_core_ck_ops);
+
+static const char *dpll_core_x2_ck_parents[] = {
+	"dpll_core_ck",
+};
+
+static struct clk dpll_core_x2_ck;
+
+static const struct clk_ops dpll_x2_ck_ops = {
+	.recalc_rate	= &omap3_clkoutx2_recalc,
+};
+
+static struct clk_hw_omap dpll_core_x2_ck_hw = {
+	.hw	= {
+		.clk	= &dpll_core_x2_ck,
+	},
+	.flags		= CLOCK_CLKOUTX2,
+};
+
+DEFINE_STRUCT_CLK(dpll_core_x2_ck, dpll_core_x2_ck_parents, dpll_x2_ck_ops);
+
+DEFINE_CLK_DIVIDER(dpll_core_m4_ck, "dpll_core_x2_ck", &dpll_core_x2_ck,
+		   0x0, AM33XX_CM_DIV_M4_DPLL_CORE,
+		   AM33XX_HSDIVIDER_CLKOUT1_DIV_SHIFT,
+		   AM33XX_HSDIVIDER_CLKOUT1_DIV_WIDTH, CLK_DIVIDER_ONE_BASED,
+		   NULL);
+
+DEFINE_CLK_DIVIDER(dpll_core_m5_ck, "dpll_core_x2_ck", &dpll_core_x2_ck,
+		   0x0, AM33XX_CM_DIV_M5_DPLL_CORE,
+		   AM33XX_HSDIVIDER_CLKOUT2_DIV_SHIFT,
+		   AM33XX_HSDIVIDER_CLKOUT2_DIV_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+DEFINE_CLK_DIVIDER(dpll_core_m6_ck, "dpll_core_x2_ck", &dpll_core_x2_ck,
+		   0x0, AM33XX_CM_DIV_M6_DPLL_CORE,
+		   AM33XX_HSDIVIDER_CLKOUT3_DIV_SHIFT,
+		   AM33XX_HSDIVIDER_CLKOUT3_DIV_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+
+/* DPLL_MPU */
+static struct dpll_data dpll_mpu_dd = {
+	.mult_div1_reg	= AM33XX_CM_CLKSEL_DPLL_MPU,
+	.clk_bypass	= &sys_clkin_ck,
+	.clk_ref	= &sys_clkin_ck,
+	.control_reg	= AM33XX_CM_CLKMODE_DPLL_MPU,
+	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	.idlest_reg	= AM33XX_CM_IDLEST_DPLL_MPU,
+	.mult_mask	= AM33XX_DPLL_MULT_MASK,
+	.div1_mask	= AM33XX_DPLL_DIV_MASK,
+	.enable_mask	= AM33XX_DPLL_EN_MASK,
+	.idlest_mask	= AM33XX_ST_DPLL_CLK_MASK,
+	.max_multiplier	= 2047,
+	.max_divider	= 128,
+	.min_divider	= 1,
+};
+
+/* CLKOUT: fdpll/M2 */
+static struct clk dpll_mpu_ck;
+
+static const struct clk_ops dpll_mpu_ck_ops = {
+	.enable		= &omap3_noncore_dpll_enable,
+	.disable	= &omap3_noncore_dpll_disable,
+	.recalc_rate	= &omap3_dpll_recalc,
+	.round_rate	= &omap2_dpll_round_rate,
+	.set_rate	= &omap3_noncore_dpll_set_rate,
+	.get_parent	= &omap2_init_dpll_parent,
+};
+
+static struct clk_hw_omap dpll_mpu_ck_hw = {
+	.hw = {
+		.clk	= &dpll_mpu_ck,
+	},
+	.dpll_data	= &dpll_mpu_dd,
+	.ops		= &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_mpu_ck, dpll_core_ck_parents, dpll_mpu_ck_ops);
+
+/*
+ * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
+ * and ALT_CLK1/2)
+ */
+DEFINE_CLK_DIVIDER(dpll_mpu_m2_ck, "dpll_mpu_ck", &dpll_mpu_ck,
+		   0x0, AM33XX_CM_DIV_M2_DPLL_MPU, AM33XX_DPLL_CLKOUT_DIV_SHIFT,
+		   AM33XX_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
+
+/* DPLL_DDR */
+static struct dpll_data dpll_ddr_dd = {
+	.mult_div1_reg	= AM33XX_CM_CLKSEL_DPLL_DDR,
+	.clk_bypass	= &sys_clkin_ck,
+	.clk_ref	= &sys_clkin_ck,
+	.control_reg	= AM33XX_CM_CLKMODE_DPLL_DDR,
+	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	.idlest_reg	= AM33XX_CM_IDLEST_DPLL_DDR,
+	.mult_mask	= AM33XX_DPLL_MULT_MASK,
+	.div1_mask	= AM33XX_DPLL_DIV_MASK,
+	.enable_mask	= AM33XX_DPLL_EN_MASK,
+	.idlest_mask	= AM33XX_ST_DPLL_CLK_MASK,
+	.max_multiplier	= 2047,
+	.max_divider	= 128,
+	.min_divider	= 1,
+};
+
+/* CLKOUT: fdpll/M2 */
+static struct clk dpll_ddr_ck;
+
+static const struct clk_ops dpll_ddr_ck_ops = {
+	.recalc_rate	= &omap3_dpll_recalc,
+	.get_parent	= &omap2_init_dpll_parent,
+	.round_rate	= &omap2_dpll_round_rate,
+	.set_rate	= &omap3_noncore_dpll_set_rate,
+};
+
+static struct clk_hw_omap dpll_ddr_ck_hw = {
+	.hw = {
+		.clk	= &dpll_ddr_ck,
+	},
+	.dpll_data	= &dpll_ddr_dd,
+	.ops		= &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_ddr_ck, dpll_core_ck_parents, dpll_ddr_ck_ops);
+
+/*
+ * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
+ * and ALT_CLK1/2)
+ */
+DEFINE_CLK_DIVIDER(dpll_ddr_m2_ck, "dpll_ddr_ck", &dpll_ddr_ck,
+		   0x0, AM33XX_CM_DIV_M2_DPLL_DDR,
+		   AM33XX_DPLL_CLKOUT_DIV_SHIFT, AM33XX_DPLL_CLKOUT_DIV_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+/* emif_fck functional clock */
+DEFINE_CLK_FIXED_FACTOR(dpll_ddr_m2_div2_ck, "dpll_ddr_m2_ck", &dpll_ddr_m2_ck,
+			0x0, 1, 2);
+
+/* DPLL_DISP */
+static struct dpll_data dpll_disp_dd = {
+	.mult_div1_reg	= AM33XX_CM_CLKSEL_DPLL_DISP,
+	.clk_bypass	= &sys_clkin_ck,
+	.clk_ref	= &sys_clkin_ck,
+	.control_reg	= AM33XX_CM_CLKMODE_DPLL_DISP,
+	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	.idlest_reg	= AM33XX_CM_IDLEST_DPLL_DISP,
+	.mult_mask	= AM33XX_DPLL_MULT_MASK,
+	.div1_mask	= AM33XX_DPLL_DIV_MASK,
+	.enable_mask	= AM33XX_DPLL_EN_MASK,
+	.idlest_mask	= AM33XX_ST_DPLL_CLK_MASK,
+	.max_multiplier	= 2047,
+	.max_divider	= 128,
+	.min_divider	= 1,
+};
+
+/* CLKOUT: fdpll/M2 */
+static struct clk dpll_disp_ck;
+
+static struct clk_hw_omap dpll_disp_ck_hw = {
+	.hw = {
+		.clk	= &dpll_disp_ck,
+	},
+	.dpll_data	= &dpll_disp_dd,
+	.ops		= &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_disp_ck, dpll_core_ck_parents, dpll_ddr_ck_ops);
+
+/*
+ * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
+ * and ALT_CLK1/2)
+ */
+DEFINE_CLK_DIVIDER(dpll_disp_m2_ck, "dpll_disp_ck", &dpll_disp_ck, 0x0,
+		   AM33XX_CM_DIV_M2_DPLL_DISP, AM33XX_DPLL_CLKOUT_DIV_SHIFT,
+		   AM33XX_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
+
+/* DPLL_PER */
+static struct dpll_data dpll_per_dd = {
+	.mult_div1_reg	= AM33XX_CM_CLKSEL_DPLL_PERIPH,
+	.clk_bypass	= &sys_clkin_ck,
+	.clk_ref	= &sys_clkin_ck,
+	.control_reg	= AM33XX_CM_CLKMODE_DPLL_PER,
+	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	.idlest_reg	= AM33XX_CM_IDLEST_DPLL_PER,
+	.mult_mask	= AM33XX_DPLL_MULT_PERIPH_MASK,
+	.div1_mask	= AM33XX_DPLL_PER_DIV_MASK,
+	.enable_mask	= AM33XX_DPLL_EN_MASK,
+	.idlest_mask	= AM33XX_ST_DPLL_CLK_MASK,
+	.max_multiplier	= 2047,
+	.max_divider	= 128,
+	.min_divider	= 1,
+	.flags		= DPLL_J_TYPE,
+};
+
+/* CLKDCOLDO */
+static struct clk dpll_per_ck;
+
+static struct clk_hw_omap dpll_per_ck_hw = {
+	.hw	= {
+		.clk	= &dpll_per_ck,
+	},
+	.dpll_data	= &dpll_per_dd,
+	.ops		= &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_per_ck, dpll_core_ck_parents, dpll_ddr_ck_ops);
+
+/* CLKOUT: fdpll/M2 */
+DEFINE_CLK_DIVIDER(dpll_per_m2_ck, "dpll_per_ck", &dpll_per_ck, 0x0,
+		   AM33XX_CM_DIV_M2_DPLL_PER, AM33XX_DPLL_CLKOUT_DIV_SHIFT,
+		   AM33XX_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED,
+		   NULL);
+
+DEFINE_CLK_FIXED_FACTOR(dpll_per_m2_div4_wkupdm_ck, "dpll_per_m2_ck",
+			&dpll_per_m2_ck, 0x0, 1, 4);
+
+DEFINE_CLK_FIXED_FACTOR(dpll_per_m2_div4_ck, "dpll_per_m2_ck",
+			&dpll_per_m2_ck, 0x0, 1, 4);
+
+DEFINE_CLK_FIXED_FACTOR(dpll_core_m4_div2_ck, "dpll_core_m4_ck",
+			&dpll_core_m4_ck, 0x0, 1, 2);
+
+DEFINE_CLK_FIXED_FACTOR(l4_rtc_gclk, "dpll_core_m4_ck", &dpll_core_m4_ck, 0x0,
+			1, 2);
+
+DEFINE_CLK_FIXED_FACTOR(clk_24mhz, "dpll_per_m2_ck", &dpll_per_m2_ck, 0x0, 1,
+			8);
+
+/*
+ * Below clock nodes describes clockdomains derived out
+ * of core clock.
+ */
+static const struct clk_ops clk_ops_null = {
+};
+
+static const char *l3_gclk_parents[] = {
+	"dpll_core_m4_ck"
+};
+
+static struct clk l3_gclk;
+DEFINE_STRUCT_CLK_HW_OMAP(l3_gclk, NULL);
+DEFINE_STRUCT_CLK(l3_gclk, l3_gclk_parents, clk_ops_null);
+
+static struct clk l4hs_gclk;
+DEFINE_STRUCT_CLK_HW_OMAP(l4hs_gclk, NULL);
+DEFINE_STRUCT_CLK(l4hs_gclk, l3_gclk_parents, clk_ops_null);
+
+static const char *l3s_gclk_parents[] = {
+	"dpll_core_m4_div2_ck"
+};
+
+static struct clk l3s_gclk;
+DEFINE_STRUCT_CLK_HW_OMAP(l3s_gclk, NULL);
+DEFINE_STRUCT_CLK(l3s_gclk, l3s_gclk_parents, clk_ops_null);
+
+static struct clk l4fw_gclk;
+DEFINE_STRUCT_CLK_HW_OMAP(l4fw_gclk, NULL);
+DEFINE_STRUCT_CLK(l4fw_gclk, l3s_gclk_parents, clk_ops_null);
+
+static struct clk l4ls_gclk;
+DEFINE_STRUCT_CLK_HW_OMAP(l4ls_gclk, NULL);
+DEFINE_STRUCT_CLK(l4ls_gclk, l3s_gclk_parents, clk_ops_null);
+
+static struct clk sysclk_div_ck;
+DEFINE_STRUCT_CLK_HW_OMAP(sysclk_div_ck, NULL);
+DEFINE_STRUCT_CLK(sysclk_div_ck, l3_gclk_parents, clk_ops_null);
+
+/*
+ * In order to match the clock domain with hwmod clockdomain entry,
+ * separate clock nodes is required for the modules which are
+ * directly getting their funtioncal clock from sys_clkin.
+ */
+static struct clk adc_tsc_fck;
+DEFINE_STRUCT_CLK_HW_OMAP(adc_tsc_fck, NULL);
+DEFINE_STRUCT_CLK(adc_tsc_fck, dpll_core_ck_parents, clk_ops_null);
+
+static struct clk dcan0_fck;
+DEFINE_STRUCT_CLK_HW_OMAP(dcan0_fck, NULL);
+DEFINE_STRUCT_CLK(dcan0_fck, dpll_core_ck_parents, clk_ops_null);
+
+static struct clk dcan1_fck;
+DEFINE_STRUCT_CLK_HW_OMAP(dcan1_fck, NULL);
+DEFINE_STRUCT_CLK(dcan1_fck, dpll_core_ck_parents, clk_ops_null);
+
+static struct clk mcasp0_fck;
+DEFINE_STRUCT_CLK_HW_OMAP(mcasp0_fck, NULL);
+DEFINE_STRUCT_CLK(mcasp0_fck, dpll_core_ck_parents, clk_ops_null);
+
+static struct clk mcasp1_fck;
+DEFINE_STRUCT_CLK_HW_OMAP(mcasp1_fck, NULL);
+DEFINE_STRUCT_CLK(mcasp1_fck, dpll_core_ck_parents, clk_ops_null);
+
+static struct clk smartreflex0_fck;
+DEFINE_STRUCT_CLK_HW_OMAP(smartreflex0_fck, NULL);
+DEFINE_STRUCT_CLK(smartreflex0_fck, dpll_core_ck_parents, clk_ops_null);
+
+static struct clk smartreflex1_fck;
+DEFINE_STRUCT_CLK_HW_OMAP(smartreflex1_fck, NULL);
+DEFINE_STRUCT_CLK(smartreflex1_fck, dpll_core_ck_parents, clk_ops_null);
+
+/*
+ * Modules clock nodes
+ *
+ * The following clock leaf nodes are added for the moment because:
+ *
+ *  - hwmod data is not present for these modules, either hwmod
+ *    control is not required or its not populated.
+ *  - Driver code is not yet migrated to use hwmod/runtime pm
+ *  - Modules outside kernel access (to disable them by default)
+ *
+ *     - debugss
+ *     - mmu (gfx domain)
+ *     - cefuse
+ *     - usbotg_fck (its additional clock and not really a modulemode)
+ *     - ieee5000
+ */
+DEFINE_CLK_GATE(debugss_ick, "dpll_core_m4_ck", &dpll_core_m4_ck, 0x0,
+		AM33XX_CM_WKUP_DEBUGSS_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(mmu_fck, "dpll_core_m4_ck", &dpll_core_m4_ck, 0x0,
+		AM33XX_CM_GFX_MMUDATA_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(cefuse_fck, "sys_clkin_ck", &sys_clkin_ck, 0x0,
+		AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
+		0x0, NULL);
+
+/*
+ * clkdiv32 is generated from fixed division of 732.4219
+ */
+DEFINE_CLK_FIXED_FACTOR(clkdiv32k_ck, "clk_24mhz", &clk_24mhz, 0x0, 1, 732);
+
+DEFINE_CLK_GATE(clkdiv32k_ick, "clkdiv32k_ck", &clkdiv32k_ck, 0x0,
+		AM33XX_CM_PER_CLKDIV32K_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
+		0x0, NULL);
+
+/* "usbotg_fck" is an additional clock and not really a modulemode */
+DEFINE_CLK_GATE(usbotg_fck, "dpll_per_ck", &dpll_per_ck, 0x0,
+		AM33XX_CM_CLKDCOLDO_DPLL_PER, AM33XX_ST_DPLL_CLKDCOLDO_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(ieee5000_fck, "dpll_core_m4_div2_ck", &dpll_core_m4_div2_ck,
+		0x0, AM33XX_CM_PER_IEEE5000_CLKCTRL,
+		AM33XX_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+/* Timers */
+static const struct clksel timer1_clkmux_sel[] = {
+	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
+	{ .parent = &clkdiv32k_ick, .rates = div_1_1_rates },
+	{ .parent = &tclkin_ck, .rates = div_1_2_rates },
+	{ .parent = &clk_rc32k_ck, .rates = div_1_3_rates },
+	{ .parent = &clk_32768_ck, .rates = div_1_4_rates },
+	{ .parent = NULL },
+};
+
+static const char *timer1_ck_parents[] = {
+	"sys_clkin_ck", "clkdiv32k_ick", "tclkin_ck", "clk_rc32k_ck",
+	"clk_32768_ck",
+};
+
+static struct clk timer1_fck;
+
+static const struct clk_ops timer1_fck_ops = {
+	.recalc_rate	= &omap2_clksel_recalc,
+	.get_parent	= &omap2_clksel_find_parent_index,
+	.set_parent	= &omap2_clksel_set_parent,
+	.init		= &omap2_init_clk_clkdm,
+};
+
+static struct clk_hw_omap timer1_fck_hw = {
+	.hw	= {
+		.clk	= &timer1_fck,
+	},
+	.clkdm_name	= "l4ls_clkdm",
+	.clksel		= timer1_clkmux_sel,
+	.clksel_reg	= AM33XX_CLKSEL_TIMER1MS_CLK,
+	.clksel_mask	= AM33XX_CLKSEL_0_2_MASK,
+};
+
+DEFINE_STRUCT_CLK(timer1_fck, timer1_ck_parents, timer1_fck_ops);
+
+static const struct clksel timer2_to_7_clk_sel[] = {
+	{ .parent = &tclkin_ck, .rates = div_1_0_rates },
+	{ .parent = &sys_clkin_ck, .rates = div_1_1_rates },
+	{ .parent = &clkdiv32k_ick, .rates = div_1_2_rates },
+	{ .parent = NULL },
+};
+
+static const char *timer2_to_7_ck_parents[] = {
+	"tclkin_ck", "sys_clkin_ck", "clkdiv32k_ick",
+};
+
+static struct clk timer2_fck;
+
+static struct clk_hw_omap timer2_fck_hw = {
+	.hw	= {
+		.clk	= &timer2_fck,
+	},
+	.clkdm_name	= "l4ls_clkdm",
+	.clksel		= timer2_to_7_clk_sel,
+	.clksel_reg	= AM33XX_CLKSEL_TIMER2_CLK,
+	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(timer2_fck, timer2_to_7_ck_parents, timer1_fck_ops);
+
+static struct clk timer3_fck;
+
+static struct clk_hw_omap timer3_fck_hw = {
+	.hw	= {
+		.clk	= &timer3_fck,
+	},
+	.clkdm_name	= "l4ls_clkdm",
+	.clksel		= timer2_to_7_clk_sel,
+	.clksel_reg	= AM33XX_CLKSEL_TIMER3_CLK,
+	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(timer3_fck, timer2_to_7_ck_parents, timer1_fck_ops);
+
+static struct clk timer4_fck;
+
+static struct clk_hw_omap timer4_fck_hw = {
+	.hw	= {
+		.clk	= &timer4_fck,
+	},
+	.clkdm_name	= "l4ls_clkdm",
+	.clksel		= timer2_to_7_clk_sel,
+	.clksel_reg	= AM33XX_CLKSEL_TIMER4_CLK,
+	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(timer4_fck, timer2_to_7_ck_parents, timer1_fck_ops);
+
+static struct clk timer5_fck;
+
+static struct clk_hw_omap timer5_fck_hw = {
+	.hw	= {
+		.clk	= &timer5_fck,
+	},
+	.clkdm_name	= "l4ls_clkdm",
+	.clksel		= timer2_to_7_clk_sel,
+	.clksel_reg	= AM33XX_CLKSEL_TIMER5_CLK,
+	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(timer5_fck, timer2_to_7_ck_parents, timer1_fck_ops);
+
+static struct clk timer6_fck;
+
+static struct clk_hw_omap timer6_fck_hw = {
+	.hw	= {
+		.clk	= &timer6_fck,
+	},
+	.clkdm_name	= "l4ls_clkdm",
+	.clksel		= timer2_to_7_clk_sel,
+	.clksel_reg	= AM33XX_CLKSEL_TIMER6_CLK,
+	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(timer6_fck, timer2_to_7_ck_parents, timer1_fck_ops);
+
+static struct clk timer7_fck;
+
+static struct clk_hw_omap timer7_fck_hw = {
+	.hw	= {
+		.clk	= &timer7_fck,
+	},
+	.clkdm_name	= "l4ls_clkdm",
+	.clksel		= timer2_to_7_clk_sel,
+	.clksel_reg	= AM33XX_CLKSEL_TIMER7_CLK,
+	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(timer7_fck, timer2_to_7_ck_parents, timer1_fck_ops);
+
+DEFINE_CLK_FIXED_FACTOR(cpsw_125mhz_gclk,
+			"dpll_core_m5_ck",
+			&dpll_core_m5_ck,
+			0x0,
+			1, 2);
+
+static const struct clk_ops cpsw_fck_ops = {
+	.recalc_rate	= &omap2_clksel_recalc,
+	.get_parent	= &omap2_clksel_find_parent_index,
+	.set_parent	= &omap2_clksel_set_parent,
+};
+
+static const struct clksel cpsw_cpts_rft_clkmux_sel[] = {
+	{ .parent = &dpll_core_m5_ck, .rates = div_1_0_rates },
+	{ .parent = &dpll_core_m4_ck, .rates = div_1_1_rates },
+	{ .parent = NULL },
+};
+
+static const char *cpsw_cpts_rft_ck_parents[] = {
+	"dpll_core_m5_ck", "dpll_core_m4_ck",
+};
+
+static struct clk cpsw_cpts_rft_clk;
+
+static struct clk_hw_omap cpsw_cpts_rft_clk_hw = {
+	.hw	= {
+		.clk	= &cpsw_cpts_rft_clk,
+	},
+	.clkdm_name	= "cpsw_125mhz_clkdm",
+	.clksel		= cpsw_cpts_rft_clkmux_sel,
+	.clksel_reg	= AM33XX_CM_CPTS_RFT_CLKSEL,
+	.clksel_mask	= AM33XX_CLKSEL_0_0_MASK,
+};
+
+DEFINE_STRUCT_CLK(cpsw_cpts_rft_clk, cpsw_cpts_rft_ck_parents, cpsw_fck_ops);
+
+
+/* gpio */
+static const char *gpio0_ck_parents[] = {
+	"clk_rc32k_ck", "clk_32768_ck", "clkdiv32k_ick",
+};
+
+static const struct clksel gpio0_dbclk_mux_sel[] = {
+	{ .parent = &clk_rc32k_ck, .rates = div_1_0_rates },
+	{ .parent = &clk_32768_ck, .rates = div_1_1_rates },
+	{ .parent = &clkdiv32k_ick, .rates = div_1_2_rates },
+	{ .parent = NULL },
+};
+
+static const struct clk_ops gpio_fck_ops = {
+	.recalc_rate	= &omap2_clksel_recalc,
+	.get_parent	= &omap2_clksel_find_parent_index,
+	.set_parent	= &omap2_clksel_set_parent,
+	.init		= &omap2_init_clk_clkdm,
+};
+
+static struct clk gpio0_dbclk_mux_ck;
+
+static struct clk_hw_omap gpio0_dbclk_mux_ck_hw = {
+	.hw	= {
+		.clk	= &gpio0_dbclk_mux_ck,
+	},
+	.clkdm_name	= "l4_wkup_clkdm",
+	.clksel		= gpio0_dbclk_mux_sel,
+	.clksel_reg	= AM33XX_CLKSEL_GPIO0_DBCLK,
+	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(gpio0_dbclk_mux_ck, gpio0_ck_parents, gpio_fck_ops);
+
+DEFINE_CLK_GATE(gpio0_dbclk, "gpio0_dbclk_mux_ck", &gpio0_dbclk_mux_ck, 0x0,
+		AM33XX_CM_WKUP_GPIO0_CLKCTRL,
+		AM33XX_OPTFCLKEN_GPIO0_GDBCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio1_dbclk, "clkdiv32k_ick", &clkdiv32k_ick, 0x0,
+		AM33XX_CM_PER_GPIO1_CLKCTRL,
+		AM33XX_OPTFCLKEN_GPIO_1_GDBCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio2_dbclk, "clkdiv32k_ick", &clkdiv32k_ick, 0x0,
+		AM33XX_CM_PER_GPIO2_CLKCTRL,
+		AM33XX_OPTFCLKEN_GPIO_2_GDBCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio3_dbclk, "clkdiv32k_ick", &clkdiv32k_ick, 0x0,
+		AM33XX_CM_PER_GPIO3_CLKCTRL,
+		AM33XX_OPTFCLKEN_GPIO_3_GDBCLK_SHIFT, 0x0, NULL);
+
+
+static const char *pruss_ck_parents[] = {
+	"l3_gclk", "dpll_disp_m2_ck",
+};
+
+static const struct clksel pruss_ocp_clk_mux_sel[] = {
+	{ .parent = &l3_gclk, .rates = div_1_0_rates },
+	{ .parent = &dpll_disp_m2_ck, .rates = div_1_1_rates },
+	{ .parent = NULL },
+};
+
+static struct clk pruss_ocp_gclk;
+
+static struct clk_hw_omap pruss_ocp_gclk_hw = {
+	.hw	= {
+		.clk	= &pruss_ocp_gclk,
+	},
+	.clkdm_name	= "pruss_ocp_clkdm",
+	.clksel		= pruss_ocp_clk_mux_sel,
+	.clksel_reg	= AM33XX_CLKSEL_PRUSS_OCP_CLK,
+	.clksel_mask	= AM33XX_CLKSEL_0_0_MASK,
+};
+
+DEFINE_STRUCT_CLK(pruss_ocp_gclk, pruss_ck_parents, gpio_fck_ops);
+
+static const char *lcd_ck_parents[] = {
+	"dpll_disp_m2_ck", "dpll_core_m5_ck", "dpll_per_m2_ck",
+};
+
+static const struct clksel lcd_clk_mux_sel[] = {
+	{ .parent = &dpll_disp_m2_ck, .rates = div_1_0_rates },
+	{ .parent = &dpll_core_m5_ck, .rates = div_1_1_rates },
+	{ .parent = &dpll_per_m2_ck, .rates = div_1_2_rates },
+	{ .parent = NULL },
+};
+
+static struct clk lcd_gclk;
+
+static struct clk_hw_omap lcd_gclk_hw = {
+	.hw	= {
+		.clk	= &lcd_gclk,
+	},
+	.clkdm_name	= "lcdc_clkdm",
+	.clksel		= lcd_clk_mux_sel,
+	.clksel_reg	= AM33XX_CLKSEL_LCDC_PIXEL_CLK,
+	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(lcd_gclk, lcd_ck_parents, gpio_fck_ops);
+
+DEFINE_CLK_FIXED_FACTOR(mmc_clk, "dpll_per_m2_ck", &dpll_per_m2_ck, 0x0, 1, 2);
+
+static const char *gfx_ck_parents[] = {
+	"dpll_core_m4_ck", "dpll_per_m2_ck",
+};
+
+static const struct clksel gfx_clksel_sel[] = {
+	{ .parent = &dpll_core_m4_ck, .rates = div_1_0_rates },
+	{ .parent = &dpll_per_m2_ck, .rates = div_1_1_rates },
+	{ .parent = NULL },
+};
+
+static struct clk gfx_fclk_clksel_ck;
+
+static struct clk_hw_omap gfx_fclk_clksel_ck_hw = {
+	.hw	= {
+		.clk	= &gfx_fclk_clksel_ck,
+	},
+	.clksel		= gfx_clksel_sel,
+	.clksel_reg	= AM33XX_CLKSEL_GFX_FCLK,
+	.clksel_mask	= AM33XX_CLKSEL_GFX_FCLK_MASK,
+};
+
+DEFINE_STRUCT_CLK(gfx_fclk_clksel_ck, gfx_ck_parents, gpio_fck_ops);
+
+static const struct clk_div_table div_1_0_2_1_rates[] = {
+	{ .div = 1, .val = 0, },
+	{ .div = 2, .val = 1, },
+	{ .div = 0 },
+};
+
+DEFINE_CLK_DIVIDER_TABLE(gfx_fck_div_ck, "gfx_fclk_clksel_ck",
+			 &gfx_fclk_clksel_ck, 0x0, AM33XX_CLKSEL_GFX_FCLK,
+			 AM33XX_CLKSEL_0_0_SHIFT, AM33XX_CLKSEL_0_0_WIDTH,
+			 0x0, div_1_0_2_1_rates, NULL);
+
+static const char *sysclkout_ck_parents[] = {
+	"clk_32768_ck", "l3_gclk", "dpll_ddr_m2_ck", "dpll_per_m2_ck",
+	"lcd_gclk",
+};
+
+static const struct clksel sysclkout_pre_sel[] = {
+	{ .parent = &clk_32768_ck, .rates = div_1_0_rates },
+	{ .parent = &l3_gclk, .rates = div_1_1_rates },
+	{ .parent = &dpll_ddr_m2_ck, .rates = div_1_2_rates },
+	{ .parent = &dpll_per_m2_ck, .rates = div_1_3_rates },
+	{ .parent = &lcd_gclk, .rates = div_1_4_rates },
+	{ .parent = NULL },
+};
+
+static struct clk sysclkout_pre_ck;
+
+static struct clk_hw_omap sysclkout_pre_ck_hw = {
+	.hw	= {
+		.clk	= &sysclkout_pre_ck,
+	},
+	.clksel		= sysclkout_pre_sel,
+	.clksel_reg	= AM33XX_CM_CLKOUT_CTRL,
+	.clksel_mask	= AM33XX_CLKOUT2SOURCE_MASK,
+};
+
+DEFINE_STRUCT_CLK(sysclkout_pre_ck, sysclkout_ck_parents, gpio_fck_ops);
+
+/* Divide by 8 clock rates with default clock is 1/1*/
+static const struct clk_div_table div8_rates[] = {
+	{ .div = 1, .val = 0, },
+	{ .div = 2, .val = 1, },
+	{ .div = 3, .val = 2, },
+	{ .div = 4, .val = 3, },
+	{ .div = 5, .val = 4, },
+	{ .div = 6, .val = 5, },
+	{ .div = 7, .val = 6, },
+	{ .div = 8, .val = 7, },
+	{ .div = 0 },
+};
+
+DEFINE_CLK_DIVIDER_TABLE(clkout2_div_ck, "sysclkout_pre_ck", &sysclkout_pre_ck,
+			 0x0, AM33XX_CM_CLKOUT_CTRL, AM33XX_CLKOUT2DIV_SHIFT,
+			 AM33XX_CLKOUT2DIV_WIDTH, 0x0, div8_rates, NULL);
+
+DEFINE_CLK_GATE(clkout2_ck, "clkout2_div_ck", &clkout2_div_ck, 0x0,
+		AM33XX_CM_CLKOUT_CTRL, AM33XX_CLKOUT2EN_SHIFT, 0x0, NULL);
+
+static const char *wdt_ck_parents[] = {
+	"clk_rc32k_ck", "clkdiv32k_ick",
+};
+
+static const struct clksel wdt_clkmux_sel[] = {
+	{ .parent = &clk_rc32k_ck, .rates = div_1_0_rates },
+	{ .parent = &clkdiv32k_ick, .rates = div_1_1_rates },
+	{ .parent = NULL },
+};
+
+static struct clk wdt1_fck;
+
+static struct clk_hw_omap wdt1_fck_hw = {
+	.hw	= {
+		.clk	= &wdt1_fck,
+	},
+	.clkdm_name	= "l4_wkup_clkdm",
+	.clksel		= wdt_clkmux_sel,
+	.clksel_reg	= AM33XX_CLKSEL_WDT1_CLK,
+	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
+};
+
+DEFINE_STRUCT_CLK(wdt1_fck, wdt_ck_parents, gpio_fck_ops);
+
+/*
+ * clkdev
+ */
+static struct omap_clk am33xx_clks[] = {
+	CLK(NULL,	"clk_32768_ck",		&clk_32768_ck,	CK_AM33XX),
+	CLK(NULL,	"clk_rc32k_ck",		&clk_rc32k_ck,	CK_AM33XX),
+	CLK(NULL,	"virt_19200000_ck",	&virt_19200000_ck,	CK_AM33XX),
+	CLK(NULL,	"virt_24000000_ck",	&virt_24000000_ck,	CK_AM33XX),
+	CLK(NULL,	"virt_25000000_ck",	&virt_25000000_ck,	CK_AM33XX),
+	CLK(NULL,	"virt_26000000_ck",	&virt_26000000_ck,	CK_AM33XX),
+	CLK(NULL,	"sys_clkin_ck",		&sys_clkin_ck,	CK_AM33XX),
+	CLK(NULL,	"tclkin_ck",		&tclkin_ck,	CK_AM33XX),
+	CLK(NULL,	"dpll_core_ck",		&dpll_core_ck,	CK_AM33XX),
+	CLK(NULL,	"dpll_core_x2_ck",	&dpll_core_x2_ck,	CK_AM33XX),
+	CLK(NULL,	"dpll_core_m4_ck",	&dpll_core_m4_ck,	CK_AM33XX),
+	CLK(NULL,	"dpll_core_m5_ck",	&dpll_core_m5_ck,	CK_AM33XX),
+	CLK(NULL,	"dpll_core_m6_ck",	&dpll_core_m6_ck,	CK_AM33XX),
+	CLK(NULL,	"dpll_mpu_ck",		&dpll_mpu_ck,	CK_AM33XX),
+	CLK("cpu0",	NULL,			&dpll_mpu_ck,	CK_AM33XX),
+	CLK(NULL,	"dpll_mpu_m2_ck",	&dpll_mpu_m2_ck,	CK_AM33XX),
+	CLK(NULL,	"dpll_ddr_ck",		&dpll_ddr_ck,	CK_AM33XX),
+	CLK(NULL,	"dpll_ddr_m2_ck",	&dpll_ddr_m2_ck,	CK_AM33XX),
+	CLK(NULL,	"dpll_ddr_m2_div2_ck",	&dpll_ddr_m2_div2_ck,	CK_AM33XX),
+	CLK(NULL,	"dpll_disp_ck",		&dpll_disp_ck,	CK_AM33XX),
+	CLK(NULL,	"dpll_disp_m2_ck",	&dpll_disp_m2_ck,	CK_AM33XX),
+	CLK(NULL,	"dpll_per_ck",		&dpll_per_ck,	CK_AM33XX),
+	CLK(NULL,	"dpll_per_m2_ck",	&dpll_per_m2_ck,	CK_AM33XX),
+	CLK(NULL,	"dpll_per_m2_div4_wkupdm_ck",	&dpll_per_m2_div4_wkupdm_ck,	CK_AM33XX),
+	CLK(NULL,	"dpll_per_m2_div4_ck",	&dpll_per_m2_div4_ck,	CK_AM33XX),
+	CLK(NULL,	"adc_tsc_fck",		&adc_tsc_fck,	CK_AM33XX),
+	CLK(NULL,	"cefuse_fck",		&cefuse_fck,	CK_AM33XX),
+	CLK(NULL,	"clkdiv32k_ck",		&clkdiv32k_ck,	CK_AM33XX),
+	CLK(NULL,	"clkdiv32k_ick",	&clkdiv32k_ick,	CK_AM33XX),
+	CLK(NULL,	"dcan0_fck",		&dcan0_fck,	CK_AM33XX),
+	CLK("481cc000.d_can",	NULL,		&dcan0_fck,	CK_AM33XX),
+	CLK(NULL,	"dcan1_fck",		&dcan1_fck,	CK_AM33XX),
+	CLK("481d0000.d_can",	NULL,		&dcan1_fck,	CK_AM33XX),
+	CLK(NULL,	"debugss_ick",		&debugss_ick,	CK_AM33XX),
+	CLK(NULL,	"pruss_ocp_gclk",	&pruss_ocp_gclk,	CK_AM33XX),
+	CLK(NULL,	"mcasp0_fck",		&mcasp0_fck,	CK_AM33XX),
+	CLK(NULL,	"mcasp1_fck",		&mcasp1_fck,	CK_AM33XX),
+	CLK(NULL,	"mmu_fck",		&mmu_fck,	CK_AM33XX),
+	CLK(NULL,	"smartreflex0_fck",	&smartreflex0_fck,	CK_AM33XX),
+	CLK(NULL,	"smartreflex1_fck",	&smartreflex1_fck,	CK_AM33XX),
+	CLK(NULL,	"timer1_fck",		&timer1_fck,	CK_AM33XX),
+	CLK(NULL,	"timer2_fck",		&timer2_fck,	CK_AM33XX),
+	CLK(NULL,	"timer3_fck",		&timer3_fck,	CK_AM33XX),
+	CLK(NULL,	"timer4_fck",		&timer4_fck,	CK_AM33XX),
+	CLK(NULL,	"timer5_fck",		&timer5_fck,	CK_AM33XX),
+	CLK(NULL,	"timer6_fck",		&timer6_fck,	CK_AM33XX),
+	CLK(NULL,	"timer7_fck",		&timer7_fck,	CK_AM33XX),
+	CLK(NULL,	"usbotg_fck",		&usbotg_fck,	CK_AM33XX),
+	CLK(NULL,	"ieee5000_fck",		&ieee5000_fck,	CK_AM33XX),
+	CLK(NULL,	"wdt1_fck",		&wdt1_fck,	CK_AM33XX),
+	CLK(NULL,	"l4_rtc_gclk",		&l4_rtc_gclk,	CK_AM33XX),
+	CLK(NULL,	"l3_gclk",		&l3_gclk,	CK_AM33XX),
+	CLK(NULL,	"dpll_core_m4_div2_ck",	&dpll_core_m4_div2_ck,	CK_AM33XX),
+	CLK(NULL,	"l4hs_gclk",		&l4hs_gclk,	CK_AM33XX),
+	CLK(NULL,	"l3s_gclk",		&l3s_gclk,	CK_AM33XX),
+	CLK(NULL,	"l4fw_gclk",		&l4fw_gclk,	CK_AM33XX),
+	CLK(NULL,	"l4ls_gclk",		&l4ls_gclk,	CK_AM33XX),
+	CLK(NULL,	"clk_24mhz",		&clk_24mhz,	CK_AM33XX),
+	CLK(NULL,	"sysclk_div_ck",	&sysclk_div_ck,	CK_AM33XX),
+	CLK(NULL,	"cpsw_125mhz_gclk",	&cpsw_125mhz_gclk,	CK_AM33XX),
+	CLK(NULL,	"cpsw_cpts_rft_clk",	&cpsw_cpts_rft_clk,	CK_AM33XX),
+	CLK(NULL,	"gpio0_dbclk_mux_ck",	&gpio0_dbclk_mux_ck,	CK_AM33XX),
+	CLK(NULL,	"gpio0_dbclk",		&gpio0_dbclk,	CK_AM33XX),
+	CLK(NULL,	"gpio1_dbclk",		&gpio1_dbclk,	CK_AM33XX),
+	CLK(NULL,	"gpio2_dbclk",		&gpio2_dbclk,	CK_AM33XX),
+	CLK(NULL,	"gpio3_dbclk",		&gpio3_dbclk,	CK_AM33XX),
+	CLK(NULL,	"lcd_gclk",		&lcd_gclk,	CK_AM33XX),
+	CLK(NULL,	"mmc_clk",		&mmc_clk,	CK_AM33XX),
+	CLK(NULL,	"gfx_fclk_clksel_ck",	&gfx_fclk_clksel_ck,	CK_AM33XX),
+	CLK(NULL,	"gfx_fck_div_ck",	&gfx_fck_div_ck,	CK_AM33XX),
+	CLK(NULL,	"sysclkout_pre_ck",	&sysclkout_pre_ck,	CK_AM33XX),
+	CLK(NULL,	"clkout2_div_ck",	&clkout2_div_ck,	CK_AM33XX),
+	CLK(NULL,	"timer_32k_ck",		&clkdiv32k_ick,	CK_AM33XX),
+	CLK(NULL,	"timer_sys_ck",		&sys_clkin_ck,	CK_AM33XX),
+};
+
+
+static const char *enable_init_clks[] = {
+	"dpll_ddr_m2_ck",
+	"dpll_mpu_m2_ck",
+	"l3_gclk",
+	"l4hs_gclk",
+	"l4fw_gclk",
+	"l4ls_gclk",
+};
+
+int __init am33xx_clk_init(void)
+{
+	struct omap_clk *c;
+	u32 cpu_clkflg;
+
+	if (soc_is_am33xx()) {
+		cpu_mask = RATE_IN_AM33XX;
+		cpu_clkflg = CK_AM33XX;
+	}
+
+	for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++) {
+		if (c->cpu & cpu_clkflg) {
+			clkdev_add(&c->lk);
+			if (!__clk_init(NULL, c->lk.clk))
+				omap2_init_clk_hw_omap_clocks(c->lk.clk);
+		}
+	}
+
+	omap2_clk_disable_autoidle_all();
+
+	omap2_clk_enable_init_clocks(enable_init_clks,
+				     ARRAY_SIZE(enable_init_clks));
+
+	/* TRM ERRATA: Timer 3 & 6 default parent (TCLKIN) may not be always
+	 *    physically present, in such a case HWMOD enabling of
+	 *    clock would be failure with default parent. And timer
+	 *    probe thinks clock is already enabled, this leads to
+	 *    crash upon accessing timer 3 & 6 registers in probe.
+	 *    Fix by setting parent of both these timers to master
+	 *    oscillator clock.
+	 */
+
+	clk_set_parent(&timer3_fck, &sys_clkin_ck);
+	clk_set_parent(&timer6_fck, &sys_clkin_ck);
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
new file mode 100644
index 0000000..bdf3948
--- /dev/null
+++ b/arch/arm/mach-omap2/cclock3xxx_data.c
@@ -0,0 +1,3595 @@
+/*
+ * OMAP3 clock data
+ *
+ * Copyright (C) 2007-2012 Texas Instruments, Inc.
+ * Copyright (C) 2007-2011 Nokia Corporation
+ *
+ * Written by Paul Walmsley
+ * Updated to COMMON clk data format by Rajendra Nayak <rnayak@ti.com>
+ * With many device clock fixes by Kevin Hilman and Jouni Högander
+ * DPLL bypass clock support added by Roman Tereshonkov
+ *
+ */
+
+/*
+ * Virtual clocks are introduced as convenient tools.
+ * They are sources for other clocks and not supposed
+ * to be requested from drivers directly.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/clk-private.h>
+#include <linux/list.h>
+#include <linux/io.h>
+
+#include "soc.h"
+#include "iomap.h"
+#include "clock.h"
+#include "clock3xxx.h"
+#include "clock34xx.h"
+#include "clock36xx.h"
+#include "clock3517.h"
+#include "cm3xxx.h"
+#include "cm-regbits-34xx.h"
+#include "prm3xxx.h"
+#include "prm-regbits-34xx.h"
+#include "control.h"
+
+/*
+ * clocks
+ */
+
+#define OMAP_CM_REGADDR		OMAP34XX_CM_REGADDR
+
+/* Maximum DPLL multiplier, divider values for OMAP3 */
+#define OMAP3_MAX_DPLL_MULT		2047
+#define OMAP3630_MAX_JTYPE_DPLL_MULT	4095
+#define OMAP3_MAX_DPLL_DIV		128
+
+DEFINE_CLK_FIXED_RATE(dummy_apb_pclk, CLK_IS_ROOT, 0x0, 0x0);
+
+DEFINE_CLK_FIXED_RATE(mcbsp_clks, CLK_IS_ROOT, 0x0, 0x0);
+
+DEFINE_CLK_FIXED_RATE(omap_32k_fck, CLK_IS_ROOT, 32768, 0x0);
+
+DEFINE_CLK_FIXED_RATE(pclk_ck, CLK_IS_ROOT, 27000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(rmii_ck, CLK_IS_ROOT, 50000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(secure_32k_fck, CLK_IS_ROOT, 32768, 0x0);
+
+DEFINE_CLK_FIXED_RATE(sys_altclk, CLK_IS_ROOT, 0x0, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_12m_ck, CLK_IS_ROOT, 12000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_13m_ck, CLK_IS_ROOT, 13000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_16_8m_ck, CLK_IS_ROOT, 16800000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_19200000_ck, CLK_IS_ROOT, 19200000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_26000000_ck, CLK_IS_ROOT, 26000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_38_4m_ck, CLK_IS_ROOT, 38400000, 0x0);
+
+static const char *osc_sys_ck_parent_names[] = {
+	"virt_12m_ck", "virt_13m_ck", "virt_19200000_ck", "virt_26000000_ck",
+	"virt_38_4m_ck", "virt_16_8m_ck",
+};
+
+DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0,
+	       OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT,
+	       OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_DIVIDER(sys_ck, "osc_sys_ck", &osc_sys_ck, 0x0,
+		   OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT,
+		   OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct dpll_data dpll3_dd = {
+	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+	.mult_mask	= OMAP3430_CORE_DPLL_MULT_MASK,
+	.div1_mask	= OMAP3430_CORE_DPLL_DIV_MASK,
+	.clk_bypass	= &sys_ck,
+	.clk_ref	= &sys_ck,
+	.freqsel_mask	= OMAP3430_CORE_DPLL_FREQSEL_MASK,
+	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+	.enable_mask	= OMAP3430_EN_CORE_DPLL_MASK,
+	.auto_recal_bit	= OMAP3430_EN_CORE_DPLL_DRIFTGUARD_SHIFT,
+	.recal_en_bit	= OMAP3430_CORE_DPLL_RECAL_EN_SHIFT,
+	.recal_st_bit	= OMAP3430_CORE_DPLL_ST_SHIFT,
+	.autoidle_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
+	.autoidle_mask	= OMAP3430_AUTO_CORE_DPLL_MASK,
+	.idlest_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
+	.idlest_mask	= OMAP3430_ST_CORE_CLK_MASK,
+	.max_multiplier	= OMAP3_MAX_DPLL_MULT,
+	.min_divider	= 1,
+	.max_divider	= OMAP3_MAX_DPLL_DIV,
+};
+
+static struct clk dpll3_ck;
+
+static const char *dpll3_ck_parent_names[] = {
+	"sys_ck",
+};
+
+static const struct clk_ops dpll3_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.get_parent	= &omap2_init_dpll_parent,
+	.recalc_rate	= &omap3_dpll_recalc,
+	.round_rate	= &omap2_dpll_round_rate,
+};
+
+static struct clk_hw_omap dpll3_ck_hw = {
+	.hw = {
+		.clk = &dpll3_ck,
+	},
+	.ops		= &clkhwops_omap3_dpll,
+	.dpll_data	= &dpll3_dd,
+	.clkdm_name	= "dpll3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops);
+
+DEFINE_CLK_DIVIDER(dpll3_m2_ck, "dpll3_ck", &dpll3_ck, 0x0,
+		   OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+		   OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT,
+		   OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk core_ck;
+
+static const char *core_ck_parent_names[] = {
+	"dpll3_m2_ck",
+};
+
+static const struct clk_ops core_ck_ops = {};
+
+DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL);
+DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops);
+
+DEFINE_CLK_DIVIDER(l3_ick, "core_ck", &core_ck, 0x0,
+		   OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+		   OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+DEFINE_CLK_DIVIDER(l4_ick, "l3_ick", &l3_ick, 0x0,
+		   OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+		   OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk security_l4_ick2;
+
+static const char *security_l4_ick2_parent_names[] = {
+	"l4_ick",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(security_l4_ick2, NULL);
+DEFINE_STRUCT_CLK(security_l4_ick2, security_l4_ick2_parent_names, core_ck_ops);
+
+static struct clk aes1_ick;
+
+static const char *aes1_ick_parent_names[] = {
+	"security_l4_ick2",
+};
+
+static const struct clk_ops aes1_ick_ops = {
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+};
+
+static struct clk_hw_omap aes1_ick_hw = {
+	.hw = {
+		.clk = &aes1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP3430_EN_AES1_SHIFT,
+};
+
+DEFINE_STRUCT_CLK(aes1_ick, aes1_ick_parent_names, aes1_ick_ops);
+
+static struct clk core_l4_ick;
+
+static const struct clk_ops core_l4_ick_ops = {
+	.init		= &omap2_init_clk_clkdm,
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(core_l4_ick, "core_l4_clkdm");
+DEFINE_STRUCT_CLK(core_l4_ick, security_l4_ick2_parent_names, core_l4_ick_ops);
+
+static struct clk aes2_ick;
+
+static const char *aes2_ick_parent_names[] = {
+	"core_l4_ick",
+};
+
+static const struct clk_ops aes2_ick_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+};
+
+static struct clk_hw_omap aes2_ick_hw = {
+	.hw = {
+		.clk = &aes2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_AES2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(aes2_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk dpll1_fck;
+
+static struct dpll_data dpll1_dd = {
+	.mult_div1_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
+	.mult_mask	= OMAP3430_MPU_DPLL_MULT_MASK,
+	.div1_mask	= OMAP3430_MPU_DPLL_DIV_MASK,
+	.clk_bypass	= &dpll1_fck,
+	.clk_ref	= &sys_ck,
+	.freqsel_mask	= OMAP3430_MPU_DPLL_FREQSEL_MASK,
+	.control_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKEN_PLL),
+	.enable_mask	= OMAP3430_EN_MPU_DPLL_MASK,
+	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	.auto_recal_bit	= OMAP3430_EN_MPU_DPLL_DRIFTGUARD_SHIFT,
+	.recal_en_bit	= OMAP3430_MPU_DPLL_RECAL_EN_SHIFT,
+	.recal_st_bit	= OMAP3430_MPU_DPLL_ST_SHIFT,
+	.autoidle_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL),
+	.autoidle_mask	= OMAP3430_AUTO_MPU_DPLL_MASK,
+	.idlest_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
+	.idlest_mask	= OMAP3430_ST_MPU_CLK_MASK,
+	.max_multiplier	= OMAP3_MAX_DPLL_MULT,
+	.min_divider	= 1,
+	.max_divider	= OMAP3_MAX_DPLL_DIV,
+};
+
+static struct clk dpll1_ck;
+
+static const struct clk_ops dpll1_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap3_noncore_dpll_enable,
+	.disable	= &omap3_noncore_dpll_disable,
+	.get_parent	= &omap2_init_dpll_parent,
+	.recalc_rate	= &omap3_dpll_recalc,
+	.set_rate	= &omap3_noncore_dpll_set_rate,
+	.round_rate	= &omap2_dpll_round_rate,
+};
+
+static struct clk_hw_omap dpll1_ck_hw = {
+	.hw = {
+		.clk = &dpll1_ck,
+	},
+	.ops		= &clkhwops_omap3_dpll,
+	.dpll_data	= &dpll1_dd,
+	.clkdm_name	= "dpll1_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops);
+
+DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, "dpll1_ck", &dpll1_ck, 0x0, 2, 1);
+
+DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, "dpll1_x2_ck", &dpll1_x2_ck, 0x0,
+		   OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL),
+		   OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT,
+		   OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk mpu_ck;
+
+static const char *mpu_ck_parent_names[] = {
+	"dpll1_x2m2_ck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, "mpu_clkdm");
+DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops);
+
+DEFINE_CLK_DIVIDER(arm_fck, "mpu_ck", &mpu_ck, 0x0,
+		   OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
+		   OMAP3430_ST_MPU_CLK_SHIFT, OMAP3430_ST_MPU_CLK_WIDTH,
+		   0x0, NULL);
+
+static struct clk cam_ick;
+
+static struct clk_hw_omap cam_ick_hw = {
+	.hw = {
+		.clk = &cam_ick,
+	},
+	.ops		= &clkhwops_iclk,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_CAM_SHIFT,
+	.clkdm_name	= "cam_clkdm",
+};
+
+DEFINE_STRUCT_CLK(cam_ick, security_l4_ick2_parent_names, aes2_ick_ops);
+
+/* DPLL4 */
+/* Supplies 96MHz, 54Mhz TV DAC, DSS fclk, CAM sensor clock, emul trace clk */
+/* Type: DPLL */
+static struct dpll_data dpll4_dd;
+
+static struct dpll_data dpll4_dd_34xx __initdata = {
+	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
+	.mult_mask	= OMAP3430_PERIPH_DPLL_MULT_MASK,
+	.div1_mask	= OMAP3430_PERIPH_DPLL_DIV_MASK,
+	.clk_bypass	= &sys_ck,
+	.clk_ref	= &sys_ck,
+	.freqsel_mask	= OMAP3430_PERIPH_DPLL_FREQSEL_MASK,
+	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+	.enable_mask	= OMAP3430_EN_PERIPH_DPLL_MASK,
+	.modes		= (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
+	.auto_recal_bit	= OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT,
+	.recal_en_bit	= OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT,
+	.recal_st_bit	= OMAP3430_PERIPH_DPLL_ST_SHIFT,
+	.autoidle_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
+	.autoidle_mask	= OMAP3430_AUTO_PERIPH_DPLL_MASK,
+	.idlest_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
+	.idlest_mask	= OMAP3430_ST_PERIPH_CLK_MASK,
+	.max_multiplier = OMAP3_MAX_DPLL_MULT,
+	.min_divider	= 1,
+	.max_divider	= OMAP3_MAX_DPLL_DIV,
+};
+
+static struct dpll_data dpll4_dd_3630 __initdata = {
+	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
+	.mult_mask	= OMAP3630_PERIPH_DPLL_MULT_MASK,
+	.div1_mask	= OMAP3430_PERIPH_DPLL_DIV_MASK,
+	.clk_bypass	= &sys_ck,
+	.clk_ref	= &sys_ck,
+	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+	.enable_mask	= OMAP3430_EN_PERIPH_DPLL_MASK,
+	.modes		= (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
+	.auto_recal_bit	= OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT,
+	.recal_en_bit	= OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT,
+	.recal_st_bit	= OMAP3430_PERIPH_DPLL_ST_SHIFT,
+	.autoidle_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
+	.autoidle_mask	= OMAP3430_AUTO_PERIPH_DPLL_MASK,
+	.idlest_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
+	.idlest_mask	= OMAP3430_ST_PERIPH_CLK_MASK,
+	.dco_mask	= OMAP3630_PERIPH_DPLL_DCO_SEL_MASK,
+	.sddiv_mask	= OMAP3630_PERIPH_DPLL_SD_DIV_MASK,
+	.max_multiplier = OMAP3630_MAX_JTYPE_DPLL_MULT,
+	.min_divider	= 1,
+	.max_divider	= OMAP3_MAX_DPLL_DIV,
+	.flags		= DPLL_J_TYPE
+};
+
+static struct clk dpll4_ck;
+
+static const struct clk_ops dpll4_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap3_noncore_dpll_enable,
+	.disable	= &omap3_noncore_dpll_disable,
+	.get_parent	= &omap2_init_dpll_parent,
+	.recalc_rate	= &omap3_dpll_recalc,
+	.set_rate	= &omap3_dpll4_set_rate,
+	.round_rate	= &omap2_dpll_round_rate,
+};
+
+static struct clk_hw_omap dpll4_ck_hw = {
+	.hw = {
+		.clk = &dpll4_ck,
+	},
+	.dpll_data	= &dpll4_dd,
+	.ops		= &clkhwops_omap3_dpll,
+	.clkdm_name	= "dpll4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll4_ck, dpll3_ck_parent_names, dpll4_ck_ops);
+
+DEFINE_CLK_DIVIDER(dpll4_m5_ck, "dpll4_ck", &dpll4_ck, 0x0,
+		   OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL),
+		   OMAP3430_CLKSEL_CAM_SHIFT, OMAP3630_CLKSEL_CAM_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk dpll4_m5x2_ck;
+
+static const char *dpll4_m5x2_ck_parent_names[] = {
+	"dpll4_m5_ck",
+};
+
+static const struct clk_ops dpll4_m5x2_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.recalc_rate	= &omap3_clkoutx2_recalc,
+};
+
+static const struct clk_ops dpll4_m5x2_ck_3630_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap36xx_pwrdn_clk_enable_with_hsdiv_restore,
+	.disable	= &omap2_dflt_clk_disable,
+	.recalc_rate	= &omap3_clkoutx2_recalc,
+};
+
+static struct clk_hw_omap dpll4_m5x2_ck_hw = {
+	.hw = {
+		.clk = &dpll4_m5x2_ck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+	.enable_bit	= OMAP3430_PWRDN_CAM_SHIFT,
+	.flags		= INVERT_ENABLE,
+	.clkdm_name	= "dpll4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll4_m5x2_ck, dpll4_m5x2_ck_parent_names, dpll4_m5x2_ck_ops);
+
+static struct clk dpll4_m5x2_ck_3630 = {
+	.name		= "dpll4_m5x2_ck",
+	.hw		= &dpll4_m5x2_ck_hw.hw,
+	.parent_names	= dpll4_m5x2_ck_parent_names,
+	.num_parents	= ARRAY_SIZE(dpll4_m5x2_ck_parent_names),
+	.ops		= &dpll4_m5x2_ck_3630_ops,
+};
+
+static struct clk cam_mclk;
+
+static const char *cam_mclk_parent_names[] = {
+	"dpll4_m5x2_ck",
+};
+
+static struct clk_hw_omap cam_mclk_hw = {
+	.hw = {
+		.clk = &cam_mclk,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_CAM_SHIFT,
+	.clkdm_name	= "cam_clkdm",
+};
+
+DEFINE_STRUCT_CLK(cam_mclk, cam_mclk_parent_names, aes2_ick_ops);
+
+static const struct clksel_rate clkout2_src_core_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_3XXX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate clkout2_src_sys_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate clkout2_src_96m_rates[] = {
+	{ .div = 1, .val = 2, .flags = RATE_IN_3XXX },
+	{ .div = 0 }
+};
+
+DEFINE_CLK_DIVIDER(dpll4_m2_ck, "dpll4_ck", &dpll4_ck, 0x0,
+		   OMAP_CM_REGADDR(PLL_MOD, OMAP3430_CM_CLKSEL3),
+		   OMAP3430_DIV_96M_SHIFT, OMAP3630_DIV_96M_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk dpll4_m2x2_ck;
+
+static const char *dpll4_m2x2_ck_parent_names[] = {
+	"dpll4_m2_ck",
+};
+
+static struct clk_hw_omap dpll4_m2x2_ck_hw = {
+	.hw = {
+		.clk = &dpll4_m2x2_ck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+	.enable_bit	= OMAP3430_PWRDN_96M_SHIFT,
+	.flags		= INVERT_ENABLE,
+	.clkdm_name	= "dpll4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll4_m2x2_ck, dpll4_m2x2_ck_parent_names, dpll4_m5x2_ck_ops);
+
+static struct clk dpll4_m2x2_ck_3630 = {
+	.name		= "dpll4_m2x2_ck",
+	.hw		= &dpll4_m2x2_ck_hw.hw,
+	.parent_names	= dpll4_m2x2_ck_parent_names,
+	.num_parents	= ARRAY_SIZE(dpll4_m2x2_ck_parent_names),
+	.ops		= &dpll4_m5x2_ck_3630_ops,
+};
+
+static struct clk omap_96m_alwon_fck;
+
+static const char *omap_96m_alwon_fck_parent_names[] = {
+	"dpll4_m2x2_ck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(omap_96m_alwon_fck, NULL);
+DEFINE_STRUCT_CLK(omap_96m_alwon_fck, omap_96m_alwon_fck_parent_names,
+		  core_ck_ops);
+
+static struct clk cm_96m_fck;
+
+static const char *cm_96m_fck_parent_names[] = {
+	"omap_96m_alwon_fck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(cm_96m_fck, NULL);
+DEFINE_STRUCT_CLK(cm_96m_fck, cm_96m_fck_parent_names, core_ck_ops);
+
+static const struct clksel_rate clkout2_src_54m_rates[] = {
+	{ .div = 1, .val = 3, .flags = RATE_IN_3XXX },
+	{ .div = 0 }
+};
+
+DEFINE_CLK_DIVIDER(dpll4_m3_ck, "dpll4_ck", &dpll4_ck, 0x0,
+		   OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
+		   OMAP3430_CLKSEL_TV_SHIFT, OMAP3630_CLKSEL_TV_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk dpll4_m3x2_ck;
+
+static const char *dpll4_m3x2_ck_parent_names[] = {
+	"dpll4_m3_ck",
+};
+
+static struct clk_hw_omap dpll4_m3x2_ck_hw = {
+	.hw = {
+		.clk = &dpll4_m3x2_ck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+	.enable_bit	= OMAP3430_PWRDN_TV_SHIFT,
+	.flags		= INVERT_ENABLE,
+	.clkdm_name	= "dpll4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll4_m3x2_ck, dpll4_m3x2_ck_parent_names, dpll4_m5x2_ck_ops);
+
+static struct clk dpll4_m3x2_ck_3630 = {
+	.name		= "dpll4_m3x2_ck",
+	.hw		= &dpll4_m3x2_ck_hw.hw,
+	.parent_names	= dpll4_m3x2_ck_parent_names,
+	.num_parents	= ARRAY_SIZE(dpll4_m3x2_ck_parent_names),
+	.ops		= &dpll4_m5x2_ck_3630_ops,
+};
+
+static const char *omap_54m_fck_parent_names[] = {
+	"dpll4_m3x2_ck", "sys_altclk",
+};
+
+DEFINE_CLK_MUX(omap_54m_fck, omap_54m_fck_parent_names, NULL, 0x0,
+	       OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_SOURCE_54M_SHIFT,
+	       OMAP3430_SOURCE_54M_WIDTH, 0x0, NULL);
+
+static const struct clksel clkout2_src_clksel[] = {
+	{ .parent = &core_ck, .rates = clkout2_src_core_rates },
+	{ .parent = &sys_ck, .rates = clkout2_src_sys_rates },
+	{ .parent = &cm_96m_fck, .rates = clkout2_src_96m_rates },
+	{ .parent = &omap_54m_fck, .rates = clkout2_src_54m_rates },
+	{ .parent = NULL },
+};
+
+static const char *clkout2_src_ck_parent_names[] = {
+	"core_ck", "sys_ck", "cm_96m_fck", "omap_54m_fck",
+};
+
+static const struct clk_ops clkout2_src_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.get_parent	= &omap2_clksel_find_parent_index,
+	.set_parent	= &omap2_clksel_set_parent,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(clkout2_src_ck, "core_clkdm",
+			 clkout2_src_clksel, OMAP3430_CM_CLKOUT_CTRL,
+			 OMAP3430_CLKOUT2SOURCE_MASK,
+			 OMAP3430_CM_CLKOUT_CTRL, OMAP3430_CLKOUT2_EN_SHIFT,
+			 NULL, clkout2_src_ck_parent_names, clkout2_src_ck_ops);
+
+static const struct clksel_rate omap_48m_cm96m_rates[] = {
+	{ .div = 2, .val = 0, .flags = RATE_IN_3XXX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate omap_48m_alt_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
+	{ .div = 0 }
+};
+
+static const struct clksel omap_48m_clksel[] = {
+	{ .parent = &cm_96m_fck, .rates = omap_48m_cm96m_rates },
+	{ .parent = &sys_altclk, .rates = omap_48m_alt_rates },
+	{ .parent = NULL },
+};
+
+static const char *omap_48m_fck_parent_names[] = {
+	"cm_96m_fck", "sys_altclk",
+};
+
+static struct clk omap_48m_fck;
+
+static const struct clk_ops omap_48m_fck_ops = {
+	.recalc_rate	= &omap2_clksel_recalc,
+	.get_parent	= &omap2_clksel_find_parent_index,
+	.set_parent	= &omap2_clksel_set_parent,
+};
+
+static struct clk_hw_omap omap_48m_fck_hw = {
+	.hw = {
+		.clk = &omap_48m_fck,
+	},
+	.clksel		= omap_48m_clksel,
+	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+	.clksel_mask	= OMAP3430_SOURCE_48M_MASK,
+};
+
+DEFINE_STRUCT_CLK(omap_48m_fck, omap_48m_fck_parent_names, omap_48m_fck_ops);
+
+DEFINE_CLK_FIXED_FACTOR(omap_12m_fck, "omap_48m_fck", &omap_48m_fck, 0x0, 1, 4);
+
+static struct clk core_12m_fck;
+
+static const char *core_12m_fck_parent_names[] = {
+	"omap_12m_fck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(core_12m_fck, "core_l4_clkdm");
+DEFINE_STRUCT_CLK(core_12m_fck, core_12m_fck_parent_names, core_l4_ick_ops);
+
+static struct clk core_48m_fck;
+
+static const char *core_48m_fck_parent_names[] = {
+	"omap_48m_fck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(core_48m_fck, "core_l4_clkdm");
+DEFINE_STRUCT_CLK(core_48m_fck, core_48m_fck_parent_names, core_l4_ick_ops);
+
+static const char *omap_96m_fck_parent_names[] = {
+	"cm_96m_fck", "sys_ck",
+};
+
+DEFINE_CLK_MUX(omap_96m_fck, omap_96m_fck_parent_names, NULL, 0x0,
+	       OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+	       OMAP3430_SOURCE_96M_SHIFT, OMAP3430_SOURCE_96M_WIDTH, 0x0, NULL);
+
+static struct clk core_96m_fck;
+
+static const char *core_96m_fck_parent_names[] = {
+	"omap_96m_fck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(core_96m_fck, "core_l4_clkdm");
+DEFINE_STRUCT_CLK(core_96m_fck, core_96m_fck_parent_names, core_l4_ick_ops);
+
+static struct clk core_l3_ick;
+
+static const char *core_l3_ick_parent_names[] = {
+	"l3_ick",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(core_l3_ick, "core_l3_clkdm");
+DEFINE_STRUCT_CLK(core_l3_ick, core_l3_ick_parent_names, core_l4_ick_ops);
+
+DEFINE_CLK_FIXED_FACTOR(dpll3_m2x2_ck, "dpll3_m2_ck", &dpll3_m2_ck, 0x0, 2, 1);
+
+static struct clk corex2_fck;
+
+static const char *corex2_fck_parent_names[] = {
+	"dpll3_m2x2_ck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(corex2_fck, NULL);
+DEFINE_STRUCT_CLK(corex2_fck, corex2_fck_parent_names, core_ck_ops);
+
+static struct clk cpefuse_fck;
+
+static struct clk_hw_omap cpefuse_fck_hw = {
+	.hw = {
+		.clk = &cpefuse_fck,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
+	.enable_bit	= OMAP3430ES2_EN_CPEFUSE_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(cpefuse_fck, dpll3_ck_parent_names, aes2_ick_ops);
+
+static struct clk csi2_96m_fck;
+
+static const char *csi2_96m_fck_parent_names[] = {
+	"core_96m_fck",
+};
+
+static struct clk_hw_omap csi2_96m_fck_hw = {
+	.hw = {
+		.clk = &csi2_96m_fck,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_CSI2_SHIFT,
+	.clkdm_name	= "cam_clkdm",
+};
+
+DEFINE_STRUCT_CLK(csi2_96m_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk d2d_26m_fck;
+
+static struct clk_hw_omap d2d_26m_fck_hw = {
+	.hw = {
+		.clk = &d2d_26m_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430ES1_EN_D2D_SHIFT,
+	.clkdm_name	= "d2d_clkdm",
+};
+
+DEFINE_STRUCT_CLK(d2d_26m_fck, dpll3_ck_parent_names, aes2_ick_ops);
+
+static struct clk des1_ick;
+
+static struct clk_hw_omap des1_ick_hw = {
+	.hw = {
+		.clk = &des1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP3430_EN_DES1_SHIFT,
+};
+
+DEFINE_STRUCT_CLK(des1_ick, aes1_ick_parent_names, aes1_ick_ops);
+
+static struct clk des2_ick;
+
+static struct clk_hw_omap des2_ick_hw = {
+	.hw = {
+		.clk = &des2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_DES2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(des2_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_DIVIDER(dpll1_fck, "core_ck", &core_ck, 0x0,
+		   OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
+		   OMAP3430_MPU_CLK_SRC_SHIFT, OMAP3430_MPU_CLK_SRC_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk dpll2_fck;
+
+static struct dpll_data dpll2_dd = {
+	.mult_div1_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
+	.mult_mask	= OMAP3430_IVA2_DPLL_MULT_MASK,
+	.div1_mask	= OMAP3430_IVA2_DPLL_DIV_MASK,
+	.clk_bypass	= &dpll2_fck,
+	.clk_ref	= &sys_ck,
+	.freqsel_mask	= OMAP3430_IVA2_DPLL_FREQSEL_MASK,
+	.control_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL),
+	.enable_mask	= OMAP3430_EN_IVA2_DPLL_MASK,
+	.modes		= ((1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED) |
+			   (1 << DPLL_LOW_POWER_BYPASS)),
+	.auto_recal_bit	= OMAP3430_EN_IVA2_DPLL_DRIFTGUARD_SHIFT,
+	.recal_en_bit	= OMAP3430_PRM_IRQENABLE_MPU_IVA2_DPLL_RECAL_EN_SHIFT,
+	.recal_st_bit	= OMAP3430_PRM_IRQSTATUS_MPU_IVA2_DPLL_ST_SHIFT,
+	.autoidle_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL),
+	.autoidle_mask	= OMAP3430_AUTO_IVA2_DPLL_MASK,
+	.idlest_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_IDLEST_PLL),
+	.idlest_mask	= OMAP3430_ST_IVA2_CLK_MASK,
+	.max_multiplier	= OMAP3_MAX_DPLL_MULT,
+	.min_divider	= 1,
+	.max_divider	= OMAP3_MAX_DPLL_DIV,
+};
+
+static struct clk dpll2_ck;
+
+static struct clk_hw_omap dpll2_ck_hw = {
+	.hw = {
+		.clk = &dpll2_ck,
+	},
+	.ops		= &clkhwops_omap3_dpll,
+	.dpll_data	= &dpll2_dd,
+	.clkdm_name	= "dpll2_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll2_ck, dpll3_ck_parent_names, dpll1_ck_ops);
+
+DEFINE_CLK_DIVIDER(dpll2_fck, "core_ck", &core_ck, 0x0,
+		   OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
+		   OMAP3430_IVA2_CLK_SRC_SHIFT, OMAP3430_IVA2_CLK_SRC_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+DEFINE_CLK_DIVIDER(dpll2_m2_ck, "dpll2_ck", &dpll2_ck, 0x0,
+		   OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL2_PLL),
+		   OMAP3430_IVA2_DPLL_CLKOUT_DIV_SHIFT,
+		   OMAP3430_IVA2_DPLL_CLKOUT_DIV_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+DEFINE_CLK_DIVIDER(dpll3_m3_ck, "dpll3_ck", &dpll3_ck, 0x0,
+		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
+		   OMAP3430_DIV_DPLL3_SHIFT, OMAP3430_DIV_DPLL3_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk dpll3_m3x2_ck;
+
+static const char *dpll3_m3x2_ck_parent_names[] = {
+	"dpll3_m3_ck",
+};
+
+static struct clk_hw_omap dpll3_m3x2_ck_hw = {
+	.hw = {
+		.clk = &dpll3_m3x2_ck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+	.enable_bit	= OMAP3430_PWRDN_EMU_CORE_SHIFT,
+	.flags		= INVERT_ENABLE,
+	.clkdm_name	= "dpll3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll3_m3x2_ck, dpll3_m3x2_ck_parent_names, dpll4_m5x2_ck_ops);
+
+static struct clk dpll3_m3x2_ck_3630 = {
+	.name		= "dpll3_m3x2_ck",
+	.hw		= &dpll3_m3x2_ck_hw.hw,
+	.parent_names	= dpll3_m3x2_ck_parent_names,
+	.num_parents	= ARRAY_SIZE(dpll3_m3x2_ck_parent_names),
+	.ops		= &dpll4_m5x2_ck_3630_ops,
+};
+
+DEFINE_CLK_FIXED_FACTOR(dpll3_x2_ck, "dpll3_ck", &dpll3_ck, 0x0, 2, 1);
+
+DEFINE_CLK_DIVIDER(dpll4_m4_ck, "dpll4_ck", &dpll4_ck, 0x0,
+		   OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
+		   OMAP3430_CLKSEL_DSS1_SHIFT, OMAP3630_CLKSEL_DSS1_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk dpll4_m4x2_ck;
+
+static const char *dpll4_m4x2_ck_parent_names[] = {
+	"dpll4_m4_ck",
+};
+
+static struct clk_hw_omap dpll4_m4x2_ck_hw = {
+	.hw = {
+		.clk = &dpll4_m4x2_ck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+	.enable_bit	= OMAP3430_PWRDN_DSS1_SHIFT,
+	.flags		= INVERT_ENABLE,
+	.clkdm_name	= "dpll4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll4_m4x2_ck, dpll4_m4x2_ck_parent_names, dpll4_m5x2_ck_ops);
+
+static struct clk dpll4_m4x2_ck_3630 = {
+	.name		= "dpll4_m4x2_ck",
+	.hw		= &dpll4_m4x2_ck_hw.hw,
+	.parent_names	= dpll4_m4x2_ck_parent_names,
+	.num_parents	= ARRAY_SIZE(dpll4_m4x2_ck_parent_names),
+	.ops		= &dpll4_m5x2_ck_3630_ops,
+};
+
+DEFINE_CLK_DIVIDER(dpll4_m6_ck, "dpll4_ck", &dpll4_ck, 0x0,
+		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
+		   OMAP3430_DIV_DPLL4_SHIFT, OMAP3630_DIV_DPLL4_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk dpll4_m6x2_ck;
+
+static const char *dpll4_m6x2_ck_parent_names[] = {
+	"dpll4_m6_ck",
+};
+
+static struct clk_hw_omap dpll4_m6x2_ck_hw = {
+	.hw = {
+		.clk = &dpll4_m6x2_ck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+	.enable_bit	= OMAP3430_PWRDN_EMU_PERIPH_SHIFT,
+	.flags		= INVERT_ENABLE,
+	.clkdm_name	= "dpll4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll4_m6x2_ck, dpll4_m6x2_ck_parent_names, dpll4_m5x2_ck_ops);
+
+static struct clk dpll4_m6x2_ck_3630 = {
+	.name		= "dpll4_m6x2_ck",
+	.hw		= &dpll4_m6x2_ck_hw.hw,
+	.parent_names	= dpll4_m6x2_ck_parent_names,
+	.num_parents	= ARRAY_SIZE(dpll4_m6x2_ck_parent_names),
+	.ops		= &dpll4_m5x2_ck_3630_ops,
+};
+
+DEFINE_CLK_FIXED_FACTOR(dpll4_x2_ck, "dpll4_ck", &dpll4_ck, 0x0, 2, 1);
+
+static struct dpll_data dpll5_dd = {
+	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4),
+	.mult_mask	= OMAP3430ES2_PERIPH2_DPLL_MULT_MASK,
+	.div1_mask	= OMAP3430ES2_PERIPH2_DPLL_DIV_MASK,
+	.clk_bypass	= &sys_ck,
+	.clk_ref	= &sys_ck,
+	.freqsel_mask	= OMAP3430ES2_PERIPH2_DPLL_FREQSEL_MASK,
+	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKEN2),
+	.enable_mask	= OMAP3430ES2_EN_PERIPH2_DPLL_MASK,
+	.modes		= (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
+	.auto_recal_bit	= OMAP3430ES2_EN_PERIPH2_DPLL_DRIFTGUARD_SHIFT,
+	.recal_en_bit	= OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN_SHIFT,
+	.recal_st_bit	= OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT,
+	.autoidle_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_AUTOIDLE2_PLL),
+	.autoidle_mask	= OMAP3430ES2_AUTO_PERIPH2_DPLL_MASK,
+	.idlest_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2),
+	.idlest_mask	= OMAP3430ES2_ST_PERIPH2_CLK_MASK,
+	.max_multiplier	= OMAP3_MAX_DPLL_MULT,
+	.min_divider	= 1,
+	.max_divider	= OMAP3_MAX_DPLL_DIV,
+};
+
+static struct clk dpll5_ck;
+
+static struct clk_hw_omap dpll5_ck_hw = {
+	.hw = {
+		.clk = &dpll5_ck,
+	},
+	.ops		= &clkhwops_omap3_dpll,
+	.dpll_data	= &dpll5_dd,
+	.clkdm_name	= "dpll5_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dpll5_ck, dpll3_ck_parent_names, dpll1_ck_ops);
+
+DEFINE_CLK_DIVIDER(dpll5_m2_ck, "dpll5_ck", &dpll5_ck, 0x0,
+		   OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL5),
+		   OMAP3430ES2_DIV_120M_SHIFT, OMAP3430ES2_DIV_120M_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk dss1_alwon_fck_3430es1;
+
+static const char *dss1_alwon_fck_3430es1_parent_names[] = {
+	"dpll4_m4x2_ck",
+};
+
+static struct clk_hw_omap dss1_alwon_fck_3430es1_hw = {
+	.hw = {
+		.clk = &dss1_alwon_fck_3430es1,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_DSS1_SHIFT,
+	.clkdm_name	= "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss1_alwon_fck_3430es1, dss1_alwon_fck_3430es1_parent_names,
+		  aes2_ick_ops);
+
+static struct clk dss1_alwon_fck_3430es2;
+
+static struct clk_hw_omap dss1_alwon_fck_3430es2_hw = {
+	.hw = {
+		.clk = &dss1_alwon_fck_3430es2,
+	},
+	.ops		= &clkhwops_omap3430es2_dss_usbhost_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_DSS1_SHIFT,
+	.clkdm_name	= "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss1_alwon_fck_3430es2, dss1_alwon_fck_3430es1_parent_names,
+		  aes2_ick_ops);
+
+static struct clk dss2_alwon_fck;
+
+static struct clk_hw_omap dss2_alwon_fck_hw = {
+	.hw = {
+		.clk = &dss2_alwon_fck,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_DSS2_SHIFT,
+	.clkdm_name	= "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss2_alwon_fck, dpll3_ck_parent_names, aes2_ick_ops);
+
+static struct clk dss_96m_fck;
+
+static struct clk_hw_omap dss_96m_fck_hw = {
+	.hw = {
+		.clk = &dss_96m_fck,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_TV_SHIFT,
+	.clkdm_name	= "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss_96m_fck, core_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk dss_ick_3430es1;
+
+static struct clk_hw_omap dss_ick_3430es1_hw = {
+	.hw = {
+		.clk = &dss_ick_3430es1,
+	},
+	.ops		= &clkhwops_iclk,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
+	.clkdm_name	= "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss_ick_3430es1, security_l4_ick2_parent_names, aes2_ick_ops);
+
+static struct clk dss_ick_3430es2;
+
+static struct clk_hw_omap dss_ick_3430es2_hw = {
+	.hw = {
+		.clk = &dss_ick_3430es2,
+	},
+	.ops		= &clkhwops_omap3430es2_iclk_dss_usbhost_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
+	.clkdm_name	= "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss_ick_3430es2, security_l4_ick2_parent_names, aes2_ick_ops);
+
+static struct clk dss_tv_fck;
+
+static const char *dss_tv_fck_parent_names[] = {
+	"omap_54m_fck",
+};
+
+static struct clk_hw_omap dss_tv_fck_hw = {
+	.hw = {
+		.clk = &dss_tv_fck,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_TV_SHIFT,
+	.clkdm_name	= "dss_clkdm",
+};
+
+DEFINE_STRUCT_CLK(dss_tv_fck, dss_tv_fck_parent_names, aes2_ick_ops);
+
+static struct clk emac_fck;
+
+static const char *emac_fck_parent_names[] = {
+	"rmii_ck",
+};
+
+static struct clk_hw_omap emac_fck_hw = {
+	.hw = {
+		.clk = &emac_fck,
+	},
+	.enable_reg	= OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+	.enable_bit	= AM35XX_CPGMAC_FCLK_SHIFT,
+};
+
+DEFINE_STRUCT_CLK(emac_fck, emac_fck_parent_names, aes1_ick_ops);
+
+static struct clk ipss_ick;
+
+static const char *ipss_ick_parent_names[] = {
+	"core_l3_ick",
+};
+
+static struct clk_hw_omap ipss_ick_hw = {
+	.hw = {
+		.clk = &ipss_ick,
+	},
+	.ops		= &clkhwops_am35xx_ipss_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= AM35XX_EN_IPSS_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(ipss_ick, ipss_ick_parent_names, aes2_ick_ops);
+
+static struct clk emac_ick;
+
+static const char *emac_ick_parent_names[] = {
+	"ipss_ick",
+};
+
+static struct clk_hw_omap emac_ick_hw = {
+	.hw = {
+		.clk = &emac_ick,
+	},
+	.ops		= &clkhwops_am35xx_ipss_module_wait,
+	.enable_reg	= OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+	.enable_bit	= AM35XX_CPGMAC_VBUSP_CLK_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(emac_ick, emac_ick_parent_names, aes2_ick_ops);
+
+static struct clk emu_core_alwon_ck;
+
+static const char *emu_core_alwon_ck_parent_names[] = {
+	"dpll3_m3x2_ck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(emu_core_alwon_ck, "dpll3_clkdm");
+DEFINE_STRUCT_CLK(emu_core_alwon_ck, emu_core_alwon_ck_parent_names,
+		  core_l4_ick_ops);
+
+static struct clk emu_mpu_alwon_ck;
+
+static const char *emu_mpu_alwon_ck_parent_names[] = {
+	"mpu_ck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(emu_mpu_alwon_ck, NULL);
+DEFINE_STRUCT_CLK(emu_mpu_alwon_ck, emu_mpu_alwon_ck_parent_names, core_ck_ops);
+
+static struct clk emu_per_alwon_ck;
+
+static const char *emu_per_alwon_ck_parent_names[] = {
+	"dpll4_m6x2_ck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(emu_per_alwon_ck, "dpll4_clkdm");
+DEFINE_STRUCT_CLK(emu_per_alwon_ck, emu_per_alwon_ck_parent_names,
+		  core_l4_ick_ops);
+
+static const char *emu_src_ck_parent_names[] = {
+	"sys_ck", "emu_core_alwon_ck", "emu_per_alwon_ck", "emu_mpu_alwon_ck",
+};
+
+static const struct clksel_rate emu_src_sys_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_3XXX },
+	{ .div = 0 },
+};
+
+static const struct clksel_rate emu_src_core_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
+	{ .div = 0 },
+};
+
+static const struct clksel_rate emu_src_per_rates[] = {
+	{ .div = 1, .val = 2, .flags = RATE_IN_3XXX },
+	{ .div = 0 },
+};
+
+static const struct clksel_rate emu_src_mpu_rates[] = {
+	{ .div = 1, .val = 3, .flags = RATE_IN_3XXX },
+	{ .div = 0 },
+};
+
+static const struct clksel emu_src_clksel[] = {
+	{ .parent = &sys_ck,		.rates = emu_src_sys_rates },
+	{ .parent = &emu_core_alwon_ck, .rates = emu_src_core_rates },
+	{ .parent = &emu_per_alwon_ck,	.rates = emu_src_per_rates },
+	{ .parent = &emu_mpu_alwon_ck,	.rates = emu_src_mpu_rates },
+	{ .parent = NULL },
+};
+
+static const struct clk_ops emu_src_ck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.get_parent	= &omap2_clksel_find_parent_index,
+	.set_parent	= &omap2_clksel_set_parent,
+};
+
+static struct clk emu_src_ck;
+
+static struct clk_hw_omap emu_src_ck_hw = {
+	.hw = {
+		.clk = &emu_src_ck,
+	},
+	.clksel		= emu_src_clksel,
+	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
+	.clksel_mask	= OMAP3430_MUX_CTRL_MASK,
+	.clkdm_name	= "emu_clkdm",
+};
+
+DEFINE_STRUCT_CLK(emu_src_ck, emu_src_ck_parent_names, emu_src_ck_ops);
+
+DEFINE_CLK_DIVIDER(atclk_fck, "emu_src_ck", &emu_src_ck, 0x0,
+		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
+		   OMAP3430_CLKSEL_ATCLK_SHIFT, OMAP3430_CLKSEL_ATCLK_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk fac_ick;
+
+static struct clk_hw_omap fac_ick_hw = {
+	.hw = {
+		.clk = &fac_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430ES1_EN_FAC_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(fac_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk fshostusb_fck;
+
+static const char *fshostusb_fck_parent_names[] = {
+	"core_48m_fck",
+};
+
+static struct clk_hw_omap fshostusb_fck_hw = {
+	.hw = {
+		.clk = &fshostusb_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(fshostusb_fck, fshostusb_fck_parent_names, aes2_ick_ops);
+
+static struct clk gfx_l3_ck;
+
+static struct clk_hw_omap gfx_l3_ck_hw = {
+	.hw = {
+		.clk = &gfx_l3_ck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP_EN_GFX_SHIFT,
+	.clkdm_name	= "gfx_3430es1_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gfx_l3_ck, core_l3_ick_parent_names, aes1_ick_ops);
+
+DEFINE_CLK_DIVIDER(gfx_l3_fck, "l3_ick", &l3_ick, 0x0,
+		   OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
+		   OMAP_CLKSEL_GFX_SHIFT, OMAP_CLKSEL_GFX_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk gfx_cg1_ck;
+
+static const char *gfx_cg1_ck_parent_names[] = {
+	"gfx_l3_fck",
+};
+
+static struct clk_hw_omap gfx_cg1_ck_hw = {
+	.hw = {
+		.clk = &gfx_cg1_ck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430ES1_EN_2D_SHIFT,
+	.clkdm_name	= "gfx_3430es1_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gfx_cg1_ck, gfx_cg1_ck_parent_names, aes2_ick_ops);
+
+static struct clk gfx_cg2_ck;
+
+static struct clk_hw_omap gfx_cg2_ck_hw = {
+	.hw = {
+		.clk = &gfx_cg2_ck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430ES1_EN_3D_SHIFT,
+	.clkdm_name	= "gfx_3430es1_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gfx_cg2_ck, gfx_cg1_ck_parent_names, aes2_ick_ops);
+
+static struct clk gfx_l3_ick;
+
+static const char *gfx_l3_ick_parent_names[] = {
+	"gfx_l3_ck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(gfx_l3_ick, "gfx_3430es1_clkdm");
+DEFINE_STRUCT_CLK(gfx_l3_ick, gfx_l3_ick_parent_names, core_l4_ick_ops);
+
+static struct clk wkup_32k_fck;
+
+static const char *wkup_32k_fck_parent_names[] = {
+	"omap_32k_fck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(wkup_32k_fck, "wkup_clkdm");
+DEFINE_STRUCT_CLK(wkup_32k_fck, wkup_32k_fck_parent_names, core_l4_ick_ops);
+
+static struct clk gpio1_dbck;
+
+static const char *gpio1_dbck_parent_names[] = {
+	"wkup_32k_fck",
+};
+
+static struct clk_hw_omap gpio1_dbck_hw = {
+	.hw = {
+		.clk = &gpio1_dbck,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_GPIO1_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio1_dbck, gpio1_dbck_parent_names, aes2_ick_ops);
+
+static struct clk wkup_l4_ick;
+
+DEFINE_STRUCT_CLK_HW_OMAP(wkup_l4_ick, "wkup_clkdm");
+DEFINE_STRUCT_CLK(wkup_l4_ick, dpll3_ck_parent_names, core_l4_ick_ops);
+
+static struct clk gpio1_ick;
+
+static const char *gpio1_ick_parent_names[] = {
+	"wkup_l4_ick",
+};
+
+static struct clk_hw_omap gpio1_ick_hw = {
+	.hw = {
+		.clk = &gpio1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_GPIO1_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio1_ick, gpio1_ick_parent_names, aes2_ick_ops);
+
+static struct clk per_32k_alwon_fck;
+
+DEFINE_STRUCT_CLK_HW_OMAP(per_32k_alwon_fck, "per_clkdm");
+DEFINE_STRUCT_CLK(per_32k_alwon_fck, wkup_32k_fck_parent_names,
+		  core_l4_ick_ops);
+
+static struct clk gpio2_dbck;
+
+static const char *gpio2_dbck_parent_names[] = {
+	"per_32k_alwon_fck",
+};
+
+static struct clk_hw_omap gpio2_dbck_hw = {
+	.hw = {
+		.clk = &gpio2_dbck,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_GPIO2_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio2_dbck, gpio2_dbck_parent_names, aes2_ick_ops);
+
+static struct clk per_l4_ick;
+
+DEFINE_STRUCT_CLK_HW_OMAP(per_l4_ick, "per_clkdm");
+DEFINE_STRUCT_CLK(per_l4_ick, security_l4_ick2_parent_names, core_l4_ick_ops);
+
+static struct clk gpio2_ick;
+
+static const char *gpio2_ick_parent_names[] = {
+	"per_l4_ick",
+};
+
+static struct clk_hw_omap gpio2_ick_hw = {
+	.hw = {
+		.clk = &gpio2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_GPIO2_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio2_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+static struct clk gpio3_dbck;
+
+static struct clk_hw_omap gpio3_dbck_hw = {
+	.hw = {
+		.clk = &gpio3_dbck,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_GPIO3_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio3_dbck, gpio2_dbck_parent_names, aes2_ick_ops);
+
+static struct clk gpio3_ick;
+
+static struct clk_hw_omap gpio3_ick_hw = {
+	.hw = {
+		.clk = &gpio3_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_GPIO3_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio3_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+static struct clk gpio4_dbck;
+
+static struct clk_hw_omap gpio4_dbck_hw = {
+	.hw = {
+		.clk = &gpio4_dbck,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_GPIO4_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio4_dbck, gpio2_dbck_parent_names, aes2_ick_ops);
+
+static struct clk gpio4_ick;
+
+static struct clk_hw_omap gpio4_ick_hw = {
+	.hw = {
+		.clk = &gpio4_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_GPIO4_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio4_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+static struct clk gpio5_dbck;
+
+static struct clk_hw_omap gpio5_dbck_hw = {
+	.hw = {
+		.clk = &gpio5_dbck,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_GPIO5_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio5_dbck, gpio2_dbck_parent_names, aes2_ick_ops);
+
+static struct clk gpio5_ick;
+
+static struct clk_hw_omap gpio5_ick_hw = {
+	.hw = {
+		.clk = &gpio5_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_GPIO5_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio5_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+static struct clk gpio6_dbck;
+
+static struct clk_hw_omap gpio6_dbck_hw = {
+	.hw = {
+		.clk = &gpio6_dbck,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_GPIO6_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio6_dbck, gpio2_dbck_parent_names, aes2_ick_ops);
+
+static struct clk gpio6_ick;
+
+static struct clk_hw_omap gpio6_ick_hw = {
+	.hw = {
+		.clk = &gpio6_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_GPIO6_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpio6_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+static struct clk gpmc_fck;
+
+static struct clk_hw_omap gpmc_fck_hw = {
+	.hw = {
+		.clk = &gpmc_fck,
+	},
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpmc_fck, ipss_ick_parent_names, core_l4_ick_ops);
+
+static const struct clksel omap343x_gpt_clksel[] = {
+	{ .parent = &omap_32k_fck, .rates = gpt_32k_rates },
+	{ .parent = &sys_ck, .rates = gpt_sys_rates },
+	{ .parent = NULL },
+};
+
+static const char *gpt10_fck_parent_names[] = {
+	"omap_32k_fck", "sys_ck",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt10_fck, "core_l4_clkdm", omap343x_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+			 OMAP3430_CLKSEL_GPT10_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP3430_EN_GPT10_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt10_ick;
+
+static struct clk_hw_omap gpt10_ick_hw = {
+	.hw = {
+		.clk = &gpt10_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_GPT10_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt10_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt11_fck, "core_l4_clkdm", omap343x_gpt_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+			 OMAP3430_CLKSEL_GPT11_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP3430_EN_GPT11_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt11_ick;
+
+static struct clk_hw_omap gpt11_ick_hw = {
+	.hw = {
+		.clk = &gpt11_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_GPT11_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt11_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk gpt12_fck;
+
+static const char *gpt12_fck_parent_names[] = {
+	"secure_32k_fck",
+};
+
+DEFINE_STRUCT_CLK_HW_OMAP(gpt12_fck, "wkup_clkdm");
+DEFINE_STRUCT_CLK(gpt12_fck, gpt12_fck_parent_names, core_l4_ick_ops);
+
+static struct clk gpt12_ick;
+
+static struct clk_hw_omap gpt12_ick_hw = {
+	.hw = {
+		.clk = &gpt12_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_GPT12_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt12_ick, gpio1_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt1_fck, "wkup_clkdm", omap343x_gpt_clksel,
+			 OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
+			 OMAP3430_CLKSEL_GPT1_MASK,
+			 OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+			 OMAP3430_EN_GPT1_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt1_ick;
+
+static struct clk_hw_omap gpt1_ick_hw = {
+	.hw = {
+		.clk = &gpt1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_GPT1_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt1_ick, gpio1_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt2_fck, "per_clkdm", omap343x_gpt_clksel,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
+			 OMAP3430_CLKSEL_GPT2_MASK,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+			 OMAP3430_EN_GPT2_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt2_ick;
+
+static struct clk_hw_omap gpt2_ick_hw = {
+	.hw = {
+		.clk = &gpt2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_GPT2_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt2_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt3_fck, "per_clkdm", omap343x_gpt_clksel,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
+			 OMAP3430_CLKSEL_GPT3_MASK,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+			 OMAP3430_EN_GPT3_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt3_ick;
+
+static struct clk_hw_omap gpt3_ick_hw = {
+	.hw = {
+		.clk = &gpt3_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_GPT3_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt3_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt4_fck, "per_clkdm", omap343x_gpt_clksel,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
+			 OMAP3430_CLKSEL_GPT4_MASK,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+			 OMAP3430_EN_GPT4_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt4_ick;
+
+static struct clk_hw_omap gpt4_ick_hw = {
+	.hw = {
+		.clk = &gpt4_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_GPT4_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt4_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt5_fck, "per_clkdm", omap343x_gpt_clksel,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
+			 OMAP3430_CLKSEL_GPT5_MASK,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+			 OMAP3430_EN_GPT5_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt5_ick;
+
+static struct clk_hw_omap gpt5_ick_hw = {
+	.hw = {
+		.clk = &gpt5_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_GPT5_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt5_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt6_fck, "per_clkdm", omap343x_gpt_clksel,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
+			 OMAP3430_CLKSEL_GPT6_MASK,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+			 OMAP3430_EN_GPT6_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt6_ick;
+
+static struct clk_hw_omap gpt6_ick_hw = {
+	.hw = {
+		.clk = &gpt6_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_GPT6_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt6_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt7_fck, "per_clkdm", omap343x_gpt_clksel,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
+			 OMAP3430_CLKSEL_GPT7_MASK,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+			 OMAP3430_EN_GPT7_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt7_ick;
+
+static struct clk_hw_omap gpt7_ick_hw = {
+	.hw = {
+		.clk = &gpt7_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_GPT7_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt7_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt8_fck, "per_clkdm", omap343x_gpt_clksel,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
+			 OMAP3430_CLKSEL_GPT8_MASK,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+			 OMAP3430_EN_GPT8_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt8_ick;
+
+static struct clk_hw_omap gpt8_ick_hw = {
+	.hw = {
+		.clk = &gpt8_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_GPT8_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt8_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(gpt9_fck, "per_clkdm", omap343x_gpt_clksel,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
+			 OMAP3430_CLKSEL_GPT9_MASK,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+			 OMAP3430_EN_GPT9_SHIFT, &clkhwops_wait,
+			 gpt10_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk gpt9_ick;
+
+static struct clk_hw_omap gpt9_ick_hw = {
+	.hw = {
+		.clk = &gpt9_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_GPT9_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(gpt9_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+static struct clk hdq_fck;
+
+static const char *hdq_fck_parent_names[] = {
+	"core_12m_fck",
+};
+
+static struct clk_hw_omap hdq_fck_hw = {
+	.hw = {
+		.clk = &hdq_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_HDQ_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hdq_fck, hdq_fck_parent_names, aes2_ick_ops);
+
+static struct clk hdq_ick;
+
+static struct clk_hw_omap hdq_ick_hw = {
+	.hw = {
+		.clk = &hdq_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_HDQ_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hdq_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk hecc_ck;
+
+static struct clk_hw_omap hecc_ck_hw = {
+	.hw = {
+		.clk = &hecc_ck,
+	},
+	.ops		= &clkhwops_am35xx_ipss_module_wait,
+	.enable_reg	= OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+	.enable_bit	= AM35XX_HECC_VBUSP_CLK_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hecc_ck, dpll3_ck_parent_names, aes2_ick_ops);
+
+static struct clk hsotgusb_fck_am35xx;
+
+static struct clk_hw_omap hsotgusb_fck_am35xx_hw = {
+	.hw = {
+		.clk = &hsotgusb_fck_am35xx,
+	},
+	.enable_reg	= OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+	.enable_bit	= AM35XX_USBOTG_FCLK_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hsotgusb_fck_am35xx, dpll3_ck_parent_names, aes2_ick_ops);
+
+static struct clk hsotgusb_ick_3430es1;
+
+static struct clk_hw_omap hsotgusb_ick_3430es1_hw = {
+	.hw = {
+		.clk = &hsotgusb_ick_3430es1,
+	},
+	.ops		= &clkhwops_iclk,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_HSOTGUSB_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hsotgusb_ick_3430es1, ipss_ick_parent_names, aes2_ick_ops);
+
+static struct clk hsotgusb_ick_3430es2;
+
+static struct clk_hw_omap hsotgusb_ick_3430es2_hw = {
+	.hw = {
+		.clk = &hsotgusb_ick_3430es2,
+	},
+	.ops		= &clkhwops_omap3430es2_iclk_hsotgusb_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_HSOTGUSB_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hsotgusb_ick_3430es2, ipss_ick_parent_names, aes2_ick_ops);
+
+static struct clk hsotgusb_ick_am35xx;
+
+static struct clk_hw_omap hsotgusb_ick_am35xx_hw = {
+	.hw = {
+		.clk = &hsotgusb_ick_am35xx,
+	},
+	.ops		= &clkhwops_am35xx_ipss_module_wait,
+	.enable_reg	= OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+	.enable_bit	= AM35XX_USBOTG_VBUSP_CLK_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(hsotgusb_ick_am35xx, emac_ick_parent_names, aes2_ick_ops);
+
+static struct clk i2c1_fck;
+
+static struct clk_hw_omap i2c1_fck_hw = {
+	.hw = {
+		.clk = &i2c1_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_I2C1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c1_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk i2c1_ick;
+
+static struct clk_hw_omap i2c1_ick_hw = {
+	.hw = {
+		.clk = &i2c1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_I2C1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c1_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk i2c2_fck;
+
+static struct clk_hw_omap i2c2_fck_hw = {
+	.hw = {
+		.clk = &i2c2_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_I2C2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c2_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk i2c2_ick;
+
+static struct clk_hw_omap i2c2_ick_hw = {
+	.hw = {
+		.clk = &i2c2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_I2C2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c2_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk i2c3_fck;
+
+static struct clk_hw_omap i2c3_fck_hw = {
+	.hw = {
+		.clk = &i2c3_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_I2C3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c3_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk i2c3_ick;
+
+static struct clk_hw_omap i2c3_ick_hw = {
+	.hw = {
+		.clk = &i2c3_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_I2C3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(i2c3_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk icr_ick;
+
+static struct clk_hw_omap icr_ick_hw = {
+	.hw = {
+		.clk = &icr_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_ICR_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(icr_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk iva2_ck;
+
+static const char *iva2_ck_parent_names[] = {
+	"dpll2_m2_ck",
+};
+
+static struct clk_hw_omap iva2_ck_hw = {
+	.hw = {
+		.clk = &iva2_ck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT,
+	.clkdm_name	= "iva2_clkdm",
+};
+
+DEFINE_STRUCT_CLK(iva2_ck, iva2_ck_parent_names, aes2_ick_ops);
+
+static struct clk mad2d_ick;
+
+static struct clk_hw_omap mad2d_ick_hw = {
+	.hw = {
+		.clk = &mad2d_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP3430_EN_MAD2D_SHIFT,
+	.clkdm_name	= "d2d_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mad2d_ick, core_l3_ick_parent_names, aes2_ick_ops);
+
+static struct clk mailboxes_ick;
+
+static struct clk_hw_omap mailboxes_ick_hw = {
+	.hw = {
+		.clk = &mailboxes_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_MAILBOXES_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mailboxes_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static const struct clksel_rate common_mcbsp_96m_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_3XXX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
+	{ .div = 0 }
+};
+
+static const struct clksel mcbsp_15_clksel[] = {
+	{ .parent = &core_96m_fck, .rates = common_mcbsp_96m_rates },
+	{ .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
+	{ .parent = NULL },
+};
+
+static const char *mcbsp1_fck_parent_names[] = {
+	"core_96m_fck", "mcbsp_clks",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp1_fck, "core_l4_clkdm", mcbsp_15_clksel,
+			 OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+			 OMAP2_MCBSP1_CLKS_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP3430_EN_MCBSP1_SHIFT, &clkhwops_wait,
+			 mcbsp1_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk mcbsp1_ick;
+
+static struct clk_hw_omap mcbsp1_ick_hw = {
+	.hw = {
+		.clk = &mcbsp1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_MCBSP1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp1_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk per_96m_fck;
+
+DEFINE_STRUCT_CLK_HW_OMAP(per_96m_fck, "per_clkdm");
+DEFINE_STRUCT_CLK(per_96m_fck, cm_96m_fck_parent_names, core_l4_ick_ops);
+
+static const struct clksel mcbsp_234_clksel[] = {
+	{ .parent = &per_96m_fck, .rates = common_mcbsp_96m_rates },
+	{ .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
+	{ .parent = NULL },
+};
+
+static const char *mcbsp2_fck_parent_names[] = {
+	"per_96m_fck", "mcbsp_clks",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp2_fck, "per_clkdm", mcbsp_234_clksel,
+			 OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+			 OMAP2_MCBSP2_CLKS_MASK,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+			 OMAP3430_EN_MCBSP2_SHIFT, &clkhwops_wait,
+			 mcbsp2_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk mcbsp2_ick;
+
+static struct clk_hw_omap mcbsp2_ick_hw = {
+	.hw = {
+		.clk = &mcbsp2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_MCBSP2_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp2_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp3_fck, "per_clkdm", mcbsp_234_clksel,
+			 OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
+			 OMAP2_MCBSP3_CLKS_MASK,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+			 OMAP3430_EN_MCBSP3_SHIFT, &clkhwops_wait,
+			 mcbsp2_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk mcbsp3_ick;
+
+static struct clk_hw_omap mcbsp3_ick_hw = {
+	.hw = {
+		.clk = &mcbsp3_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_MCBSP3_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp3_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp4_fck, "per_clkdm", mcbsp_234_clksel,
+			 OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
+			 OMAP2_MCBSP4_CLKS_MASK,
+			 OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+			 OMAP3430_EN_MCBSP4_SHIFT, &clkhwops_wait,
+			 mcbsp2_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk mcbsp4_ick;
+
+static struct clk_hw_omap mcbsp4_ick_hw = {
+	.hw = {
+		.clk = &mcbsp4_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_MCBSP4_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp4_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp5_fck, "core_l4_clkdm", mcbsp_15_clksel,
+			 OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
+			 OMAP2_MCBSP5_CLKS_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP3430_EN_MCBSP5_SHIFT, &clkhwops_wait,
+			 mcbsp1_fck_parent_names, clkout2_src_ck_ops);
+
+static struct clk mcbsp5_ick;
+
+static struct clk_hw_omap mcbsp5_ick_hw = {
+	.hw = {
+		.clk = &mcbsp5_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_MCBSP5_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcbsp5_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk mcspi1_fck;
+
+static struct clk_hw_omap mcspi1_fck_hw = {
+	.hw = {
+		.clk = &mcspi1_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_MCSPI1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi1_fck, fshostusb_fck_parent_names, aes2_ick_ops);
+
+static struct clk mcspi1_ick;
+
+static struct clk_hw_omap mcspi1_ick_hw = {
+	.hw = {
+		.clk = &mcspi1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_MCSPI1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi1_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk mcspi2_fck;
+
+static struct clk_hw_omap mcspi2_fck_hw = {
+	.hw = {
+		.clk = &mcspi2_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_MCSPI2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi2_fck, fshostusb_fck_parent_names, aes2_ick_ops);
+
+static struct clk mcspi2_ick;
+
+static struct clk_hw_omap mcspi2_ick_hw = {
+	.hw = {
+		.clk = &mcspi2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_MCSPI2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi2_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk mcspi3_fck;
+
+static struct clk_hw_omap mcspi3_fck_hw = {
+	.hw = {
+		.clk = &mcspi3_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_MCSPI3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi3_fck, fshostusb_fck_parent_names, aes2_ick_ops);
+
+static struct clk mcspi3_ick;
+
+static struct clk_hw_omap mcspi3_ick_hw = {
+	.hw = {
+		.clk = &mcspi3_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_MCSPI3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi3_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk mcspi4_fck;
+
+static struct clk_hw_omap mcspi4_fck_hw = {
+	.hw = {
+		.clk = &mcspi4_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_MCSPI4_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi4_fck, fshostusb_fck_parent_names, aes2_ick_ops);
+
+static struct clk mcspi4_ick;
+
+static struct clk_hw_omap mcspi4_ick_hw = {
+	.hw = {
+		.clk = &mcspi4_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_MCSPI4_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mcspi4_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk mmchs1_fck;
+
+static struct clk_hw_omap mmchs1_fck_hw = {
+	.hw = {
+		.clk = &mmchs1_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_MMC1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs1_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk mmchs1_ick;
+
+static struct clk_hw_omap mmchs1_ick_hw = {
+	.hw = {
+		.clk = &mmchs1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_MMC1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs1_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk mmchs2_fck;
+
+static struct clk_hw_omap mmchs2_fck_hw = {
+	.hw = {
+		.clk = &mmchs2_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_MMC2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs2_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk mmchs2_ick;
+
+static struct clk_hw_omap mmchs2_ick_hw = {
+	.hw = {
+		.clk = &mmchs2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_MMC2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs2_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk mmchs3_fck;
+
+static struct clk_hw_omap mmchs3_fck_hw = {
+	.hw = {
+		.clk = &mmchs3_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430ES2_EN_MMC3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs3_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk mmchs3_ick;
+
+static struct clk_hw_omap mmchs3_ick_hw = {
+	.hw = {
+		.clk = &mmchs3_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430ES2_EN_MMC3_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mmchs3_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk modem_fck;
+
+static struct clk_hw_omap modem_fck_hw = {
+	.hw = {
+		.clk = &modem_fck,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_MODEM_SHIFT,
+	.clkdm_name	= "d2d_clkdm",
+};
+
+DEFINE_STRUCT_CLK(modem_fck, dpll3_ck_parent_names, aes2_ick_ops);
+
+static struct clk mspro_fck;
+
+static struct clk_hw_omap mspro_fck_hw = {
+	.hw = {
+		.clk = &mspro_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_MSPRO_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mspro_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
+
+static struct clk mspro_ick;
+
+static struct clk_hw_omap mspro_ick_hw = {
+	.hw = {
+		.clk = &mspro_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_MSPRO_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(mspro_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk omap_192m_alwon_fck;
+
+DEFINE_STRUCT_CLK_HW_OMAP(omap_192m_alwon_fck, NULL);
+DEFINE_STRUCT_CLK(omap_192m_alwon_fck, omap_96m_alwon_fck_parent_names,
+		  core_ck_ops);
+
+static struct clk omap_32ksync_ick;
+
+static struct clk_hw_omap omap_32ksync_ick_hw = {
+	.hw = {
+		.clk = &omap_32ksync_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_32KSYNC_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(omap_32ksync_ick, gpio1_ick_parent_names, aes2_ick_ops);
+
+static const struct clksel_rate omap_96m_alwon_fck_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_36XX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_36XX },
+	{ .div = 0 }
+};
+
+static const struct clksel omap_96m_alwon_fck_clksel[] = {
+	{ .parent = &omap_192m_alwon_fck, .rates = omap_96m_alwon_fck_rates },
+	{ .parent = NULL }
+};
+
+static struct clk omap_96m_alwon_fck_3630;
+
+static const char *omap_96m_alwon_fck_3630_parent_names[] = {
+	"omap_192m_alwon_fck",
+};
+
+static const struct clk_ops omap_96m_alwon_fck_3630_ops = {
+	.set_rate	= &omap2_clksel_set_rate,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate,
+};
+
+static struct clk_hw_omap omap_96m_alwon_fck_3630_hw = {
+	.hw = {
+		.clk = &omap_96m_alwon_fck_3630,
+	},
+	.clksel		= omap_96m_alwon_fck_clksel,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP3630_CLKSEL_96M_MASK,
+};
+
+static struct clk omap_96m_alwon_fck_3630 = {
+	.name	= "omap_96m_alwon_fck",
+	.hw	= &omap_96m_alwon_fck_3630_hw.hw,
+	.parent_names	= omap_96m_alwon_fck_3630_parent_names,
+	.num_parents	= ARRAY_SIZE(omap_96m_alwon_fck_3630_parent_names),
+	.ops	= &omap_96m_alwon_fck_3630_ops,
+};
+
+static struct clk omapctrl_ick;
+
+static struct clk_hw_omap omapctrl_ick_hw = {
+	.hw = {
+		.clk = &omapctrl_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_OMAPCTRL_SHIFT,
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(omapctrl_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+DEFINE_CLK_DIVIDER(pclk_fck, "emu_src_ck", &emu_src_ck, 0x0,
+		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
+		   OMAP3430_CLKSEL_PCLK_SHIFT, OMAP3430_CLKSEL_PCLK_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+DEFINE_CLK_DIVIDER(pclkx2_fck, "emu_src_ck", &emu_src_ck, 0x0,
+		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
+		   OMAP3430_CLKSEL_PCLKX2_SHIFT, OMAP3430_CLKSEL_PCLKX2_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk per_48m_fck;
+
+DEFINE_STRUCT_CLK_HW_OMAP(per_48m_fck, "per_clkdm");
+DEFINE_STRUCT_CLK(per_48m_fck, core_48m_fck_parent_names, core_l4_ick_ops);
+
+static struct clk security_l3_ick;
+
+DEFINE_STRUCT_CLK_HW_OMAP(security_l3_ick, NULL);
+DEFINE_STRUCT_CLK(security_l3_ick, core_l3_ick_parent_names, core_ck_ops);
+
+static struct clk pka_ick;
+
+static const char *pka_ick_parent_names[] = {
+	"security_l3_ick",
+};
+
+static struct clk_hw_omap pka_ick_hw = {
+	.hw = {
+		.clk = &pka_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP3430_EN_PKA_SHIFT,
+};
+
+DEFINE_STRUCT_CLK(pka_ick, pka_ick_parent_names, aes1_ick_ops);
+
+DEFINE_CLK_DIVIDER(rm_ick, "l4_ick", &l4_ick, 0x0,
+		   OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
+		   OMAP3430_CLKSEL_RM_SHIFT, OMAP3430_CLKSEL_RM_WIDTH,
+		   CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk rng_ick;
+
+static struct clk_hw_omap rng_ick_hw = {
+	.hw = {
+		.clk = &rng_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP3430_EN_RNG_SHIFT,
+};
+
+DEFINE_STRUCT_CLK(rng_ick, aes1_ick_parent_names, aes1_ick_ops);
+
+static struct clk sad2d_ick;
+
+static struct clk_hw_omap sad2d_ick_hw = {
+	.hw = {
+		.clk = &sad2d_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_SAD2D_SHIFT,
+	.clkdm_name	= "d2d_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sad2d_ick, core_l3_ick_parent_names, aes2_ick_ops);
+
+static struct clk sdrc_ick;
+
+static struct clk_hw_omap sdrc_ick_hw = {
+	.hw = {
+		.clk = &sdrc_ick,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_SDRC_SHIFT,
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sdrc_ick, ipss_ick_parent_names, aes2_ick_ops);
+
+static const struct clksel_rate sgx_core_rates[] = {
+	{ .div = 2, .val = 5, .flags = RATE_IN_36XX },
+	{ .div = 3, .val = 0, .flags = RATE_IN_3XXX },
+	{ .div = 4, .val = 1, .flags = RATE_IN_3XXX },
+	{ .div = 6, .val = 2, .flags = RATE_IN_3XXX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate sgx_96m_rates[] = {
+	{ .div = 1, .val = 3, .flags = RATE_IN_3XXX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate sgx_192m_rates[] = {
+	{ .div = 1, .val = 4, .flags = RATE_IN_36XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate sgx_corex2_rates[] = {
+	{ .div = 3, .val = 6, .flags = RATE_IN_36XX },
+	{ .div = 5, .val = 7, .flags = RATE_IN_36XX },
+	{ .div = 0 }
+};
+
+static const struct clksel sgx_clksel[] = {
+	{ .parent = &core_ck, .rates = sgx_core_rates },
+	{ .parent = &cm_96m_fck, .rates = sgx_96m_rates },
+	{ .parent = &omap_192m_alwon_fck, .rates = sgx_192m_rates },
+	{ .parent = &corex2_fck, .rates = sgx_corex2_rates },
+	{ .parent = NULL },
+};
+
+static const char *sgx_fck_parent_names[] = {
+	"core_ck", "cm_96m_fck", "omap_192m_alwon_fck", "corex2_fck",
+};
+
+static struct clk sgx_fck;
+
+static const struct clk_ops sgx_fck_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.set_rate	= &omap2_clksel_set_rate,
+	.round_rate	= &omap2_clksel_round_rate,
+	.get_parent	= &omap2_clksel_find_parent_index,
+	.set_parent	= &omap2_clksel_set_parent,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(sgx_fck, "sgx_clkdm", sgx_clksel,
+			 OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_CLKSEL),
+			 OMAP3430ES2_CLKSEL_SGX_MASK,
+			 OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_FCLKEN),
+			 OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_SHIFT,
+			 &clkhwops_wait, sgx_fck_parent_names, sgx_fck_ops);
+
+static struct clk sgx_ick;
+
+static struct clk_hw_omap sgx_ick_hw = {
+	.hw = {
+		.clk = &sgx_ick,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_SHIFT,
+	.clkdm_name	= "sgx_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sgx_ick, core_l3_ick_parent_names, aes2_ick_ops);
+
+static struct clk sha11_ick;
+
+static struct clk_hw_omap sha11_ick_hw = {
+	.hw = {
+		.clk = &sha11_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP3430_EN_SHA11_SHIFT,
+};
+
+DEFINE_STRUCT_CLK(sha11_ick, aes1_ick_parent_names, aes1_ick_ops);
+
+static struct clk sha12_ick;
+
+static struct clk_hw_omap sha12_ick_hw = {
+	.hw = {
+		.clk = &sha12_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_SHA12_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sha12_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk sr1_fck;
+
+static struct clk_hw_omap sr1_fck_hw = {
+	.hw = {
+		.clk = &sr1_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_SR1_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sr1_fck, dpll3_ck_parent_names, aes2_ick_ops);
+
+static struct clk sr2_fck;
+
+static struct clk_hw_omap sr2_fck_hw = {
+	.hw = {
+		.clk = &sr2_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_SR2_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(sr2_fck, dpll3_ck_parent_names, aes2_ick_ops);
+
+static struct clk sr_l4_ick;
+
+DEFINE_STRUCT_CLK_HW_OMAP(sr_l4_ick, "core_l4_clkdm");
+DEFINE_STRUCT_CLK(sr_l4_ick, security_l4_ick2_parent_names, core_l4_ick_ops);
+
+static struct clk ssi_l4_ick;
+
+DEFINE_STRUCT_CLK_HW_OMAP(ssi_l4_ick, "core_l4_clkdm");
+DEFINE_STRUCT_CLK(ssi_l4_ick, security_l4_ick2_parent_names, core_l4_ick_ops);
+
+static struct clk ssi_ick_3430es1;
+
+static const char *ssi_ick_3430es1_parent_names[] = {
+	"ssi_l4_ick",
+};
+
+static struct clk_hw_omap ssi_ick_3430es1_hw = {
+	.hw = {
+		.clk = &ssi_ick_3430es1,
+	},
+	.ops		= &clkhwops_iclk,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(ssi_ick_3430es1, ssi_ick_3430es1_parent_names, aes2_ick_ops);
+
+static struct clk ssi_ick_3430es2;
+
+static struct clk_hw_omap ssi_ick_3430es2_hw = {
+	.hw = {
+		.clk = &ssi_ick_3430es2,
+	},
+	.ops		= &clkhwops_omap3430es2_iclk_ssi_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(ssi_ick_3430es2, ssi_ick_3430es1_parent_names, aes2_ick_ops);
+
+static const struct clksel_rate ssi_ssr_corex2_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_3XXX },
+	{ .div = 3, .val = 3, .flags = RATE_IN_3XXX },
+	{ .div = 4, .val = 4, .flags = RATE_IN_3XXX },
+	{ .div = 6, .val = 6, .flags = RATE_IN_3XXX },
+	{ .div = 8, .val = 8, .flags = RATE_IN_3XXX },
+	{ .div = 0 }
+};
+
+static const struct clksel ssi_ssr_clksel[] = {
+	{ .parent = &corex2_fck, .rates = ssi_ssr_corex2_rates },
+	{ .parent = NULL },
+};
+
+static const char *ssi_ssr_fck_3430es1_parent_names[] = {
+	"corex2_fck",
+};
+
+static const struct clk_ops ssi_ssr_fck_3430es1_ops = {
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.set_rate	= &omap2_clksel_set_rate,
+	.round_rate	= &omap2_clksel_round_rate,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_fck_3430es1, "core_l4_clkdm",
+			 ssi_ssr_clksel, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+			 OMAP3430_CLKSEL_SSI_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP3430_EN_SSI_SHIFT,
+			 NULL, ssi_ssr_fck_3430es1_parent_names,
+			 ssi_ssr_fck_3430es1_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_fck_3430es2, "core_l4_clkdm",
+			 ssi_ssr_clksel, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+			 OMAP3430_CLKSEL_SSI_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+			 OMAP3430_EN_SSI_SHIFT,
+			 NULL, ssi_ssr_fck_3430es1_parent_names,
+			 ssi_ssr_fck_3430es1_ops);
+
+DEFINE_CLK_FIXED_FACTOR(ssi_sst_fck_3430es1, "ssi_ssr_fck_3430es1",
+			&ssi_ssr_fck_3430es1, 0x0, 1, 2);
+
+DEFINE_CLK_FIXED_FACTOR(ssi_sst_fck_3430es2, "ssi_ssr_fck_3430es2",
+			&ssi_ssr_fck_3430es2, 0x0, 1, 2);
+
+static struct clk sys_clkout1;
+
+static const char *sys_clkout1_parent_names[] = {
+	"osc_sys_ck",
+};
+
+static struct clk_hw_omap sys_clkout1_hw = {
+	.hw = {
+		.clk = &sys_clkout1,
+	},
+	.enable_reg	= OMAP3430_PRM_CLKOUT_CTRL,
+	.enable_bit	= OMAP3430_CLKOUT_EN_SHIFT,
+};
+
+DEFINE_STRUCT_CLK(sys_clkout1, sys_clkout1_parent_names, aes1_ick_ops);
+
+DEFINE_CLK_DIVIDER(sys_clkout2, "clkout2_src_ck", &clkout2_src_ck, 0x0,
+		   OMAP3430_CM_CLKOUT_CTRL, OMAP3430_CLKOUT2_DIV_SHIFT,
+		   OMAP3430_CLKOUT2_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
+
+DEFINE_CLK_MUX(traceclk_src_fck, emu_src_ck_parent_names, NULL, 0x0,
+	       OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
+	       OMAP3430_TRACE_MUX_CTRL_SHIFT, OMAP3430_TRACE_MUX_CTRL_WIDTH,
+	       0x0, NULL);
+
+DEFINE_CLK_DIVIDER(traceclk_fck, "traceclk_src_fck", &traceclk_src_fck, 0x0,
+		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
+		   OMAP3430_CLKSEL_TRACECLK_SHIFT,
+		   OMAP3430_CLKSEL_TRACECLK_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
+
+static struct clk ts_fck;
+
+static struct clk_hw_omap ts_fck_hw = {
+	.hw = {
+		.clk = &ts_fck,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
+	.enable_bit	= OMAP3430ES2_EN_TS_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(ts_fck, wkup_32k_fck_parent_names, aes2_ick_ops);
+
+static struct clk uart1_fck;
+
+static struct clk_hw_omap uart1_fck_hw = {
+	.hw = {
+		.clk = &uart1_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_UART1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart1_fck, fshostusb_fck_parent_names, aes2_ick_ops);
+
+static struct clk uart1_ick;
+
+static struct clk_hw_omap uart1_ick_hw = {
+	.hw = {
+		.clk = &uart1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_UART1_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart1_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk uart2_fck;
+
+static struct clk_hw_omap uart2_fck_hw = {
+	.hw = {
+		.clk = &uart2_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_UART2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart2_fck, fshostusb_fck_parent_names, aes2_ick_ops);
+
+static struct clk uart2_ick;
+
+static struct clk_hw_omap uart2_ick_hw = {
+	.hw = {
+		.clk = &uart2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_UART2_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart2_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static struct clk uart3_fck;
+
+static const char *uart3_fck_parent_names[] = {
+	"per_48m_fck",
+};
+
+static struct clk_hw_omap uart3_fck_hw = {
+	.hw = {
+		.clk = &uart3_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_UART3_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart3_fck, uart3_fck_parent_names, aes2_ick_ops);
+
+static struct clk uart3_ick;
+
+static struct clk_hw_omap uart3_ick_hw = {
+	.hw = {
+		.clk = &uart3_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_UART3_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart3_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+static struct clk uart4_fck;
+
+static struct clk_hw_omap uart4_fck_hw = {
+	.hw = {
+		.clk = &uart4_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3630_EN_UART4_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart4_fck, uart3_fck_parent_names, aes2_ick_ops);
+
+static struct clk uart4_fck_am35xx;
+
+static struct clk_hw_omap uart4_fck_am35xx_hw = {
+	.hw = {
+		.clk = &uart4_fck_am35xx,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= AM35XX_EN_UART4_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart4_fck_am35xx, fshostusb_fck_parent_names, aes2_ick_ops);
+
+static struct clk uart4_ick;
+
+static struct clk_hw_omap uart4_ick_hw = {
+	.hw = {
+		.clk = &uart4_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3630_EN_UART4_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart4_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+static struct clk uart4_ick_am35xx;
+
+static struct clk_hw_omap uart4_ick_am35xx_hw = {
+	.hw = {
+		.clk = &uart4_ick_am35xx,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= AM35XX_EN_UART4_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(uart4_ick_am35xx, aes2_ick_parent_names, aes2_ick_ops);
+
+static const struct clksel_rate div2_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_3XXX },
+	{ .div = 0 }
+};
+
+static const struct clksel usb_l4_clksel[] = {
+	{ .parent = &l4_ick, .rates = div2_rates },
+	{ .parent = NULL },
+};
+
+static const char *usb_l4_ick_parent_names[] = {
+	"l4_ick",
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(usb_l4_ick, "core_l4_clkdm", usb_l4_clksel,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+			 OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK,
+			 OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+			 OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
+			 &clkhwops_iclk_wait, usb_l4_ick_parent_names,
+			 ssi_ssr_fck_3430es1_ops);
+
+static struct clk usbhost_120m_fck;
+
+static const char *usbhost_120m_fck_parent_names[] = {
+	"dpll5_m2_ck",
+};
+
+static struct clk_hw_omap usbhost_120m_fck_hw = {
+	.hw = {
+		.clk = &usbhost_120m_fck,
+	},
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430ES2_EN_USBHOST2_SHIFT,
+	.clkdm_name	= "usbhost_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usbhost_120m_fck, usbhost_120m_fck_parent_names,
+		  aes2_ick_ops);
+
+static struct clk usbhost_48m_fck;
+
+static struct clk_hw_omap usbhost_48m_fck_hw = {
+	.hw = {
+		.clk = &usbhost_48m_fck,
+	},
+	.ops		= &clkhwops_omap3430es2_dss_usbhost_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430ES2_EN_USBHOST1_SHIFT,
+	.clkdm_name	= "usbhost_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usbhost_48m_fck, core_48m_fck_parent_names, aes2_ick_ops);
+
+static struct clk usbhost_ick;
+
+static struct clk_hw_omap usbhost_ick_hw = {
+	.hw = {
+		.clk = &usbhost_ick,
+	},
+	.ops		= &clkhwops_omap3430es2_iclk_dss_usbhost_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430ES2_EN_USBHOST_SHIFT,
+	.clkdm_name	= "usbhost_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usbhost_ick, security_l4_ick2_parent_names, aes2_ick_ops);
+
+static struct clk usbtll_fck;
+
+static struct clk_hw_omap usbtll_fck_hw = {
+	.hw = {
+		.clk = &usbtll_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
+	.enable_bit	= OMAP3430ES2_EN_USBTLL_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usbtll_fck, usbhost_120m_fck_parent_names, aes2_ick_ops);
+
+static struct clk usbtll_ick;
+
+static struct clk_hw_omap usbtll_ick_hw = {
+	.hw = {
+		.clk = &usbtll_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP3430ES2_EN_USBTLL_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usbtll_ick, aes2_ick_parent_names, aes2_ick_ops);
+
+static const struct clksel_rate usim_96m_rates[] = {
+	{ .div = 2, .val = 3, .flags = RATE_IN_3XXX },
+	{ .div = 4, .val = 4, .flags = RATE_IN_3XXX },
+	{ .div = 8, .val = 5, .flags = RATE_IN_3XXX },
+	{ .div = 10, .val = 6, .flags = RATE_IN_3XXX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate usim_120m_rates[] = {
+	{ .div = 4, .val = 7, .flags = RATE_IN_3XXX },
+	{ .div = 8, .val = 8, .flags = RATE_IN_3XXX },
+	{ .div = 16, .val = 9, .flags = RATE_IN_3XXX },
+	{ .div = 20, .val = 10, .flags = RATE_IN_3XXX },
+	{ .div = 0 }
+};
+
+static const struct clksel usim_clksel[] = {
+	{ .parent = &omap_96m_fck, .rates = usim_96m_rates },
+	{ .parent = &dpll5_m2_ck, .rates = usim_120m_rates },
+	{ .parent = &sys_ck, .rates = div2_rates },
+	{ .parent = NULL },
+};
+
+static const char *usim_fck_parent_names[] = {
+	"omap_96m_fck", "dpll5_m2_ck", "sys_ck",
+};
+
+static struct clk usim_fck;
+
+static const struct clk_ops usim_fck_ops = {
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.get_parent	= &omap2_clksel_find_parent_index,
+	.set_parent	= &omap2_clksel_set_parent,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(usim_fck, NULL, usim_clksel,
+			 OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
+			 OMAP3430ES2_CLKSEL_USIMOCP_MASK,
+			 OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+			 OMAP3430ES2_EN_USIMOCP_SHIFT, &clkhwops_wait,
+			 usim_fck_parent_names, usim_fck_ops);
+
+static struct clk usim_ick;
+
+static struct clk_hw_omap usim_ick_hw = {
+	.hw = {
+		.clk = &usim_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430ES2_EN_USIMOCP_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usim_ick, gpio1_ick_parent_names, aes2_ick_ops);
+
+static struct clk vpfe_fck;
+
+static const char *vpfe_fck_parent_names[] = {
+	"pclk_ck",
+};
+
+static struct clk_hw_omap vpfe_fck_hw = {
+	.hw = {
+		.clk = &vpfe_fck,
+	},
+	.enable_reg	= OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+	.enable_bit	= AM35XX_VPFE_FCLK_SHIFT,
+};
+
+DEFINE_STRUCT_CLK(vpfe_fck, vpfe_fck_parent_names, aes1_ick_ops);
+
+static struct clk vpfe_ick;
+
+static struct clk_hw_omap vpfe_ick_hw = {
+	.hw = {
+		.clk = &vpfe_ick,
+	},
+	.ops		= &clkhwops_am35xx_ipss_module_wait,
+	.enable_reg	= OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
+	.enable_bit	= AM35XX_VPFE_VBUSP_CLK_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+};
+
+DEFINE_STRUCT_CLK(vpfe_ick, emac_ick_parent_names, aes2_ick_ops);
+
+static struct clk wdt1_fck;
+
+DEFINE_STRUCT_CLK_HW_OMAP(wdt1_fck, "wkup_clkdm");
+DEFINE_STRUCT_CLK(wdt1_fck, gpt12_fck_parent_names, core_l4_ick_ops);
+
+static struct clk wdt1_ick;
+
+static struct clk_hw_omap wdt1_ick_hw = {
+	.hw = {
+		.clk = &wdt1_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_WDT1_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt1_ick, gpio1_ick_parent_names, aes2_ick_ops);
+
+static struct clk wdt2_fck;
+
+static struct clk_hw_omap wdt2_fck_hw = {
+	.hw = {
+		.clk = &wdt2_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_WDT2_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt2_fck, gpio1_dbck_parent_names, aes2_ick_ops);
+
+static struct clk wdt2_ick;
+
+static struct clk_hw_omap wdt2_ick_hw = {
+	.hw = {
+		.clk = &wdt2_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_WDT2_SHIFT,
+	.clkdm_name	= "wkup_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt2_ick, gpio1_ick_parent_names, aes2_ick_ops);
+
+static struct clk wdt3_fck;
+
+static struct clk_hw_omap wdt3_fck_hw = {
+	.hw = {
+		.clk = &wdt3_fck,
+	},
+	.ops		= &clkhwops_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_WDT3_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt3_fck, gpio2_dbck_parent_names, aes2_ick_ops);
+
+static struct clk wdt3_ick;
+
+static struct clk_hw_omap wdt3_ick_hw = {
+	.hw = {
+		.clk = &wdt3_ick,
+	},
+	.ops		= &clkhwops_iclk_wait,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_EN_WDT3_SHIFT,
+	.clkdm_name	= "per_clkdm",
+};
+
+DEFINE_STRUCT_CLK(wdt3_ick, gpio2_ick_parent_names, aes2_ick_ops);
+
+/*
+ * clkdev
+ */
+static struct omap_clk omap3xxx_clks[] = {
+	CLK(NULL,	"apb_pclk",	&dummy_apb_pclk,	CK_3XXX),
+	CLK(NULL,	"omap_32k_fck",	&omap_32k_fck,	CK_3XXX),
+	CLK(NULL,	"virt_12m_ck",	&virt_12m_ck,	CK_3XXX),
+	CLK(NULL,	"virt_13m_ck",	&virt_13m_ck,	CK_3XXX),
+	CLK(NULL,	"virt_16_8m_ck", &virt_16_8m_ck, CK_3430ES2PLUS | CK_AM35XX  | CK_36XX),
+	CLK(NULL,	"virt_19200000_ck", &virt_19200000_ck, CK_3XXX),
+	CLK(NULL,	"virt_26000000_ck", &virt_26000000_ck, CK_3XXX),
+	CLK(NULL,	"virt_38_4m_ck", &virt_38_4m_ck, CK_3XXX),
+	CLK(NULL,	"osc_sys_ck",	&osc_sys_ck,	CK_3XXX),
+	CLK("twl",	"fck",		&osc_sys_ck,	CK_3XXX),
+	CLK(NULL,	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK(NULL,	"sys_altclk",	&sys_altclk,	CK_3XXX),
+	CLK(NULL,	"mcbsp_clks",	&mcbsp_clks,	CK_3XXX),
+	CLK(NULL,	"sys_clkout1",	&sys_clkout1,	CK_3XXX),
+	CLK(NULL,	"dpll1_ck",	&dpll1_ck,	CK_3XXX),
+	CLK(NULL,	"dpll1_x2_ck",	&dpll1_x2_ck,	CK_3XXX),
+	CLK(NULL,	"dpll1_x2m2_ck", &dpll1_x2m2_ck, CK_3XXX),
+	CLK(NULL,	"dpll2_ck",	&dpll2_ck,	CK_34XX | CK_36XX),
+	CLK(NULL,	"dpll2_m2_ck",	&dpll2_m2_ck,	CK_34XX | CK_36XX),
+	CLK(NULL,	"dpll3_ck",	&dpll3_ck,	CK_3XXX),
+	CLK(NULL,	"core_ck",	&core_ck,	CK_3XXX),
+	CLK(NULL,	"dpll3_x2_ck",	&dpll3_x2_ck,	CK_3XXX),
+	CLK(NULL,	"dpll3_m2_ck",	&dpll3_m2_ck,	CK_3XXX),
+	CLK(NULL,	"dpll3_m2x2_ck", &dpll3_m2x2_ck, CK_3XXX),
+	CLK(NULL,	"dpll3_m3_ck",	&dpll3_m3_ck,	CK_3XXX),
+	CLK(NULL,	"dpll3_m3x2_ck", &dpll3_m3x2_ck, CK_3XXX),
+	CLK("etb",	"emu_core_alwon_ck", &emu_core_alwon_ck, CK_3XXX),
+	CLK(NULL,	"dpll4_ck",	&dpll4_ck,	CK_3XXX),
+	CLK(NULL,	"dpll4_x2_ck",	&dpll4_x2_ck,	CK_3XXX),
+	CLK(NULL,	"omap_192m_alwon_fck", &omap_192m_alwon_fck, CK_36XX),
+	CLK(NULL,	"omap_96m_alwon_fck", &omap_96m_alwon_fck, CK_3XXX),
+	CLK(NULL,	"omap_96m_fck",	&omap_96m_fck,	CK_3XXX),
+	CLK(NULL,	"cm_96m_fck",	&cm_96m_fck,	CK_3XXX),
+	CLK(NULL,	"omap_54m_fck",	&omap_54m_fck,	CK_3XXX),
+	CLK(NULL,	"omap_48m_fck",	&omap_48m_fck,	CK_3XXX),
+	CLK(NULL,	"omap_12m_fck",	&omap_12m_fck,	CK_3XXX),
+	CLK(NULL,	"dpll4_m2_ck",	&dpll4_m2_ck,	CK_3XXX),
+	CLK(NULL,	"dpll4_m2x2_ck", &dpll4_m2x2_ck, CK_3XXX),
+	CLK(NULL,	"dpll4_m3_ck",	&dpll4_m3_ck,	CK_3XXX),
+	CLK(NULL,	"dpll4_m3x2_ck", &dpll4_m3x2_ck, CK_3XXX),
+	CLK(NULL,	"dpll4_m4_ck",	&dpll4_m4_ck,	CK_3XXX),
+	CLK(NULL,	"dpll4_m4x2_ck", &dpll4_m4x2_ck, CK_3XXX),
+	CLK(NULL,	"dpll4_m5_ck",	&dpll4_m5_ck,	CK_3XXX),
+	CLK(NULL,	"dpll4_m5x2_ck", &dpll4_m5x2_ck, CK_3XXX),
+	CLK(NULL,	"dpll4_m6_ck",	&dpll4_m6_ck,	CK_3XXX),
+	CLK(NULL,	"dpll4_m6x2_ck", &dpll4_m6x2_ck, CK_3XXX),
+	CLK("etb",	"emu_per_alwon_ck", &emu_per_alwon_ck, CK_3XXX),
+	CLK(NULL,	"dpll5_ck",	&dpll5_ck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"dpll5_m2_ck",	&dpll5_m2_ck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"clkout2_src_ck", &clkout2_src_ck, CK_3XXX),
+	CLK(NULL,	"sys_clkout2",	&sys_clkout2,	CK_3XXX),
+	CLK(NULL,	"corex2_fck",	&corex2_fck,	CK_3XXX),
+	CLK(NULL,	"dpll1_fck",	&dpll1_fck,	CK_3XXX),
+	CLK(NULL,	"mpu_ck",	&mpu_ck,	CK_3XXX),
+	CLK(NULL,	"arm_fck",	&arm_fck,	CK_3XXX),
+	CLK("etb",	"emu_mpu_alwon_ck", &emu_mpu_alwon_ck, CK_3XXX),
+	CLK(NULL,	"dpll2_fck",	&dpll2_fck,	CK_34XX | CK_36XX),
+	CLK(NULL,	"iva2_ck",	&iva2_ck,	CK_34XX | CK_36XX),
+	CLK(NULL,	"l3_ick",	&l3_ick,	CK_3XXX),
+	CLK(NULL,	"l4_ick",	&l4_ick,	CK_3XXX),
+	CLK(NULL,	"rm_ick",	&rm_ick,	CK_3XXX),
+	CLK(NULL,	"gfx_l3_ck",	&gfx_l3_ck,	CK_3430ES1),
+	CLK(NULL,	"gfx_l3_fck",	&gfx_l3_fck,	CK_3430ES1),
+	CLK(NULL,	"gfx_l3_ick",	&gfx_l3_ick,	CK_3430ES1),
+	CLK(NULL,	"gfx_cg1_ck",	&gfx_cg1_ck,	CK_3430ES1),
+	CLK(NULL,	"gfx_cg2_ck",	&gfx_cg2_ck,	CK_3430ES1),
+	CLK(NULL,	"sgx_fck",	&sgx_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"sgx_ick",	&sgx_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"d2d_26m_fck",	&d2d_26m_fck,	CK_3430ES1),
+	CLK(NULL,	"modem_fck",	&modem_fck,	CK_34XX | CK_36XX),
+	CLK(NULL,	"sad2d_ick",	&sad2d_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"mad2d_ick",	&mad2d_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"gpt10_fck",	&gpt10_fck,	CK_3XXX),
+	CLK(NULL,	"gpt11_fck",	&gpt11_fck,	CK_3XXX),
+	CLK(NULL,	"cpefuse_fck",	&cpefuse_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"ts_fck",	&ts_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"usbtll_fck",	&usbtll_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs_omap",	"usbtll_fck",	&usbtll_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs_tll",	"usbtll_fck",	&usbtll_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"core_96m_fck",	&core_96m_fck,	CK_3XXX),
+	CLK(NULL,	"mmchs3_fck",	&mmchs3_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"mmchs2_fck",	&mmchs2_fck,	CK_3XXX),
+	CLK(NULL,	"mspro_fck",	&mspro_fck,	CK_34XX | CK_36XX),
+	CLK(NULL,	"mmchs1_fck",	&mmchs1_fck,	CK_3XXX),
+	CLK(NULL,	"i2c3_fck",	&i2c3_fck,	CK_3XXX),
+	CLK(NULL,	"i2c2_fck",	&i2c2_fck,	CK_3XXX),
+	CLK(NULL,	"i2c1_fck",	&i2c1_fck,	CK_3XXX),
+	CLK(NULL,	"mcbsp5_fck",	&mcbsp5_fck,	CK_3XXX),
+	CLK(NULL,	"mcbsp1_fck",	&mcbsp1_fck,	CK_3XXX),
+	CLK(NULL,	"core_48m_fck",	&core_48m_fck,	CK_3XXX),
+	CLK(NULL,	"mcspi4_fck",	&mcspi4_fck,	CK_3XXX),
+	CLK(NULL,	"mcspi3_fck",	&mcspi3_fck,	CK_3XXX),
+	CLK(NULL,	"mcspi2_fck",	&mcspi2_fck,	CK_3XXX),
+	CLK(NULL,	"mcspi1_fck",	&mcspi1_fck,	CK_3XXX),
+	CLK(NULL,	"uart2_fck",	&uart2_fck,	CK_3XXX),
+	CLK(NULL,	"uart1_fck",	&uart1_fck,	CK_3XXX),
+	CLK(NULL,	"fshostusb_fck", &fshostusb_fck, CK_3430ES1),
+	CLK(NULL,	"core_12m_fck",	&core_12m_fck,	CK_3XXX),
+	CLK("omap_hdq.0",	"fck",	&hdq_fck,	CK_3XXX),
+	CLK(NULL,	"hdq_fck",	&hdq_fck,	CK_3XXX),
+	CLK(NULL,	"ssi_ssr_fck",	&ssi_ssr_fck_3430es1,	CK_3430ES1),
+	CLK(NULL,	"ssi_ssr_fck",	&ssi_ssr_fck_3430es2,	CK_3430ES2PLUS | CK_36XX),
+	CLK(NULL,	"ssi_sst_fck",	&ssi_sst_fck_3430es1,	CK_3430ES1),
+	CLK(NULL,	"ssi_sst_fck",	&ssi_sst_fck_3430es2,	CK_3430ES2PLUS | CK_36XX),
+	CLK(NULL,	"core_l3_ick",	&core_l3_ick,	CK_3XXX),
+	CLK("musb-omap2430",	"ick",	&hsotgusb_ick_3430es1,	CK_3430ES1),
+	CLK("musb-omap2430",	"ick",	&hsotgusb_ick_3430es2,	CK_3430ES2PLUS | CK_36XX),
+	CLK(NULL,	"hsotgusb_ick",	&hsotgusb_ick_3430es1,	CK_3430ES1),
+	CLK(NULL,	"hsotgusb_ick",	&hsotgusb_ick_3430es2,	CK_3430ES2PLUS | CK_36XX),
+	CLK(NULL,	"sdrc_ick",	&sdrc_ick,	CK_3XXX),
+	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_3XXX),
+	CLK(NULL,	"security_l3_ick", &security_l3_ick, CK_34XX | CK_36XX),
+	CLK(NULL,	"pka_ick",	&pka_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"core_l4_ick",	&core_l4_ick,	CK_3XXX),
+	CLK(NULL,	"usbtll_ick",	&usbtll_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs_omap",	"usbtll_ick",	&usbtll_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs_tll",	"usbtll_ick",	&usbtll_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("omap_hsmmc.2",	"ick",	&mmchs3_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"mmchs3_ick",	&mmchs3_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"icr_ick",	&icr_ick,	CK_34XX | CK_36XX),
+	CLK("omap-aes",	"ick",	&aes2_ick,	CK_34XX | CK_36XX),
+	CLK("omap-sham",	"ick",	&sha12_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"des2_ick",	&des2_ick,	CK_34XX | CK_36XX),
+	CLK("omap_hsmmc.1",	"ick",	&mmchs2_ick,	CK_3XXX),
+	CLK("omap_hsmmc.0",	"ick",	&mmchs1_ick,	CK_3XXX),
+	CLK(NULL,	"mmchs2_ick",	&mmchs2_ick,	CK_3XXX),
+	CLK(NULL,	"mmchs1_ick",	&mmchs1_ick,	CK_3XXX),
+	CLK(NULL,	"mspro_ick",	&mspro_ick,	CK_34XX | CK_36XX),
+	CLK("omap_hdq.0", "ick",	&hdq_ick,	CK_3XXX),
+	CLK(NULL,	"hdq_ick",	&hdq_ick,	CK_3XXX),
+	CLK("omap2_mcspi.4", "ick",	&mcspi4_ick,	CK_3XXX),
+	CLK("omap2_mcspi.3", "ick",	&mcspi3_ick,	CK_3XXX),
+	CLK("omap2_mcspi.2", "ick",	&mcspi2_ick,	CK_3XXX),
+	CLK("omap2_mcspi.1", "ick",	&mcspi1_ick,	CK_3XXX),
+	CLK(NULL,	"mcspi4_ick",	&mcspi4_ick,	CK_3XXX),
+	CLK(NULL,	"mcspi3_ick",	&mcspi3_ick,	CK_3XXX),
+	CLK(NULL,	"mcspi2_ick",	&mcspi2_ick,	CK_3XXX),
+	CLK(NULL,	"mcspi1_ick",	&mcspi1_ick,	CK_3XXX),
+	CLK("omap_i2c.3", "ick",	&i2c3_ick,	CK_3XXX),
+	CLK("omap_i2c.2", "ick",	&i2c2_ick,	CK_3XXX),
+	CLK("omap_i2c.1", "ick",	&i2c1_ick,	CK_3XXX),
+	CLK(NULL,	"i2c3_ick",	&i2c3_ick,	CK_3XXX),
+	CLK(NULL,	"i2c2_ick",	&i2c2_ick,	CK_3XXX),
+	CLK(NULL,	"i2c1_ick",	&i2c1_ick,	CK_3XXX),
+	CLK(NULL,	"uart2_ick",	&uart2_ick,	CK_3XXX),
+	CLK(NULL,	"uart1_ick",	&uart1_ick,	CK_3XXX),
+	CLK(NULL,	"gpt11_ick",	&gpt11_ick,	CK_3XXX),
+	CLK(NULL,	"gpt10_ick",	&gpt10_ick,	CK_3XXX),
+	CLK("omap-mcbsp.5", "ick",	&mcbsp5_ick,	CK_3XXX),
+	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick,	CK_3XXX),
+	CLK(NULL,	"mcbsp5_ick",	&mcbsp5_ick,	CK_3XXX),
+	CLK(NULL,	"mcbsp1_ick",	&mcbsp1_ick,	CK_3XXX),
+	CLK(NULL,	"fac_ick",	&fac_ick,	CK_3430ES1),
+	CLK(NULL,	"mailboxes_ick", &mailboxes_ick, CK_34XX | CK_36XX),
+	CLK(NULL,	"omapctrl_ick",	&omapctrl_ick,	CK_3XXX),
+	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"ssi_ick",	&ssi_ick_3430es1,	CK_3430ES1),
+	CLK(NULL,	"ssi_ick",	&ssi_ick_3430es2,	CK_3430ES2PLUS | CK_36XX),
+	CLK(NULL,	"usb_l4_ick",	&usb_l4_ick,	CK_3430ES1),
+	CLK(NULL,	"security_l4_ick2", &security_l4_ick2, CK_34XX | CK_36XX),
+	CLK(NULL,	"aes1_ick",	&aes1_ick,	CK_34XX | CK_36XX),
+	CLK("omap_rng",	"ick",		&rng_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"sha11_ick",	&sha11_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"des1_ick",	&des1_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"dss1_alwon_fck",		&dss1_alwon_fck_3430es1, CK_3430ES1),
+	CLK(NULL,	"dss1_alwon_fck",		&dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"dss_tv_fck",	&dss_tv_fck,	CK_3XXX),
+	CLK(NULL,	"dss_96m_fck",	&dss_96m_fck,	CK_3XXX),
+	CLK(NULL,	"dss2_alwon_fck",	&dss2_alwon_fck, CK_3XXX),
+	CLK("omapdss_dss",	"ick",		&dss_ick_3430es1,	CK_3430ES1),
+	CLK(NULL,	"dss_ick",		&dss_ick_3430es1,	CK_3430ES1),
+	CLK("omapdss_dss",	"ick",		&dss_ick_3430es2,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"dss_ick",		&dss_ick_3430es2,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"cam_mclk",	&cam_mclk,	CK_34XX | CK_36XX),
+	CLK(NULL,	"cam_ick",	&cam_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"csi2_96m_fck",	&csi2_96m_fck,	CK_34XX | CK_36XX),
+	CLK(NULL,	"usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs_omap",	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK(NULL,	"utmi_p1_gfclk",	&dummy_ck,	CK_3XXX),
+	CLK(NULL,	"utmi_p2_gfclk",	&dummy_ck,	CK_3XXX),
+	CLK(NULL,	"xclk60mhsp1_ck",	&dummy_ck,	CK_3XXX),
+	CLK(NULL,	"xclk60mhsp2_ck",	&dummy_ck,	CK_3XXX),
+	CLK(NULL,	"usb_host_hs_utmi_p1_clk",	&dummy_ck,	CK_3XXX),
+	CLK(NULL,	"usb_host_hs_utmi_p2_clk",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs_omap",	"usb_tll_hs_usb_ch0_clk",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs_omap",	"usb_tll_hs_usb_ch1_clk",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs_tll",	"usb_tll_hs_usb_ch0_clk",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs_tll",	"usb_tll_hs_usb_ch1_clk",	&dummy_ck,	CK_3XXX),
+	CLK(NULL,	"init_60m_fclk",	&dummy_ck,	CK_3XXX),
+	CLK(NULL,	"usim_fck",	&usim_fck,	CK_3430ES2PLUS | CK_36XX),
+	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_3XXX),
+	CLK(NULL,	"wkup_32k_fck",	&wkup_32k_fck,	CK_3XXX),
+	CLK(NULL,	"gpio1_dbck",	&gpio1_dbck,	CK_3XXX),
+	CLK(NULL,	"wdt2_fck",		&wdt2_fck,	CK_3XXX),
+	CLK(NULL,	"wkup_l4_ick",	&wkup_l4_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"usim_ick",	&usim_ick,	CK_3430ES2PLUS | CK_36XX),
+	CLK("omap_wdt",	"ick",		&wdt2_ick,	CK_3XXX),
+	CLK(NULL,	"wdt2_ick",	&wdt2_ick,	CK_3XXX),
+	CLK(NULL,	"wdt1_ick",	&wdt1_ick,	CK_3XXX),
+	CLK(NULL,	"gpio1_ick",	&gpio1_ick,	CK_3XXX),
+	CLK(NULL,	"omap_32ksync_ick", &omap_32ksync_ick, CK_3XXX),
+	CLK(NULL,	"gpt12_ick",	&gpt12_ick,	CK_3XXX),
+	CLK(NULL,	"gpt1_ick",	&gpt1_ick,	CK_3XXX),
+	CLK(NULL,	"per_96m_fck",	&per_96m_fck,	CK_3XXX),
+	CLK(NULL,	"per_48m_fck",	&per_48m_fck,	CK_3XXX),
+	CLK(NULL,	"uart3_fck",	&uart3_fck,	CK_3XXX),
+	CLK(NULL,	"uart4_fck",	&uart4_fck,	CK_36XX),
+	CLK(NULL,	"uart4_fck",	&uart4_fck_am35xx, CK_AM35XX),
+	CLK(NULL,	"gpt2_fck",	&gpt2_fck,	CK_3XXX),
+	CLK(NULL,	"gpt3_fck",	&gpt3_fck,	CK_3XXX),
+	CLK(NULL,	"gpt4_fck",	&gpt4_fck,	CK_3XXX),
+	CLK(NULL,	"gpt5_fck",	&gpt5_fck,	CK_3XXX),
+	CLK(NULL,	"gpt6_fck",	&gpt6_fck,	CK_3XXX),
+	CLK(NULL,	"gpt7_fck",	&gpt7_fck,	CK_3XXX),
+	CLK(NULL,	"gpt8_fck",	&gpt8_fck,	CK_3XXX),
+	CLK(NULL,	"gpt9_fck",	&gpt9_fck,	CK_3XXX),
+	CLK(NULL,	"per_32k_alwon_fck", &per_32k_alwon_fck, CK_3XXX),
+	CLK(NULL,	"gpio6_dbck",	&gpio6_dbck,	CK_3XXX),
+	CLK(NULL,	"gpio5_dbck",	&gpio5_dbck,	CK_3XXX),
+	CLK(NULL,	"gpio4_dbck",	&gpio4_dbck,	CK_3XXX),
+	CLK(NULL,	"gpio3_dbck",	&gpio3_dbck,	CK_3XXX),
+	CLK(NULL,	"gpio2_dbck",	&gpio2_dbck,	CK_3XXX),
+	CLK(NULL,	"wdt3_fck",	&wdt3_fck,	CK_3XXX),
+	CLK(NULL,	"per_l4_ick",	&per_l4_ick,	CK_3XXX),
+	CLK(NULL,	"gpio6_ick",	&gpio6_ick,	CK_3XXX),
+	CLK(NULL,	"gpio5_ick",	&gpio5_ick,	CK_3XXX),
+	CLK(NULL,	"gpio4_ick",	&gpio4_ick,	CK_3XXX),
+	CLK(NULL,	"gpio3_ick",	&gpio3_ick,	CK_3XXX),
+	CLK(NULL,	"gpio2_ick",	&gpio2_ick,	CK_3XXX),
+	CLK(NULL,	"wdt3_ick",	&wdt3_ick,	CK_3XXX),
+	CLK(NULL,	"uart3_ick",	&uart3_ick,	CK_3XXX),
+	CLK(NULL,	"uart4_ick",	&uart4_ick,	CK_36XX),
+	CLK(NULL,	"gpt9_ick",	&gpt9_ick,	CK_3XXX),
+	CLK(NULL,	"gpt8_ick",	&gpt8_ick,	CK_3XXX),
+	CLK(NULL,	"gpt7_ick",	&gpt7_ick,	CK_3XXX),
+	CLK(NULL,	"gpt6_ick",	&gpt6_ick,	CK_3XXX),
+	CLK(NULL,	"gpt5_ick",	&gpt5_ick,	CK_3XXX),
+	CLK(NULL,	"gpt4_ick",	&gpt4_ick,	CK_3XXX),
+	CLK(NULL,	"gpt3_ick",	&gpt3_ick,	CK_3XXX),
+	CLK(NULL,	"gpt2_ick",	&gpt2_ick,	CK_3XXX),
+	CLK("omap-mcbsp.2", "ick",	&mcbsp2_ick,	CK_3XXX),
+	CLK("omap-mcbsp.3", "ick",	&mcbsp3_ick,	CK_3XXX),
+	CLK("omap-mcbsp.4", "ick",	&mcbsp4_ick,	CK_3XXX),
+	CLK(NULL,	"mcbsp4_ick",	&mcbsp2_ick,	CK_3XXX),
+	CLK(NULL,	"mcbsp3_ick",	&mcbsp3_ick,	CK_3XXX),
+	CLK(NULL,	"mcbsp2_ick",	&mcbsp4_ick,	CK_3XXX),
+	CLK(NULL,	"mcbsp2_fck",	&mcbsp2_fck,	CK_3XXX),
+	CLK(NULL,	"mcbsp3_fck",	&mcbsp3_fck,	CK_3XXX),
+	CLK(NULL,	"mcbsp4_fck",	&mcbsp4_fck,	CK_3XXX),
+	CLK("etb",	"emu_src_ck",	&emu_src_ck,	CK_3XXX),
+	CLK(NULL,	"emu_src_ck",	&emu_src_ck,	CK_3XXX),
+	CLK(NULL,	"pclk_fck",	&pclk_fck,	CK_3XXX),
+	CLK(NULL,	"pclkx2_fck",	&pclkx2_fck,	CK_3XXX),
+	CLK(NULL,	"atclk_fck",	&atclk_fck,	CK_3XXX),
+	CLK(NULL,	"traceclk_src_fck", &traceclk_src_fck, CK_3XXX),
+	CLK(NULL,	"traceclk_fck",	&traceclk_fck,	CK_3XXX),
+	CLK(NULL,	"sr1_fck",	&sr1_fck,	CK_34XX | CK_36XX),
+	CLK(NULL,	"sr2_fck",	&sr2_fck,	CK_34XX | CK_36XX),
+	CLK(NULL,	"sr_l4_ick",	&sr_l4_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"secure_32k_fck", &secure_32k_fck, CK_3XXX),
+	CLK(NULL,	"gpt12_fck",	&gpt12_fck,	CK_3XXX),
+	CLK(NULL,	"wdt1_fck",	&wdt1_fck,	CK_3XXX),
+	CLK(NULL,	"ipss_ick",	&ipss_ick,	CK_AM35XX),
+	CLK(NULL,	"rmii_ck",	&rmii_ck,	CK_AM35XX),
+	CLK(NULL,	"pclk_ck",	&pclk_ck,	CK_AM35XX),
+	CLK(NULL,	"emac_ick",	&emac_ick,	CK_AM35XX),
+	CLK(NULL,	"emac_fck",	&emac_fck,	CK_AM35XX),
+	CLK("davinci_emac.0",	NULL,	&emac_ick,	CK_AM35XX),
+	CLK("davinci_mdio.0",	NULL,	&emac_fck,	CK_AM35XX),
+	CLK("vpfe-capture",	"master",	&vpfe_ick,	CK_AM35XX),
+	CLK("vpfe-capture",	"slave",	&vpfe_fck,	CK_AM35XX),
+	CLK(NULL,	"hsotgusb_ick",		&hsotgusb_ick_am35xx,	CK_AM35XX),
+	CLK(NULL,	"hsotgusb_fck",		&hsotgusb_fck_am35xx,	CK_AM35XX),
+	CLK(NULL,	"hecc_ck",	&hecc_ck,	CK_AM35XX),
+	CLK(NULL,	"uart4_ick",	&uart4_ick_am35xx,	CK_AM35XX),
+	CLK(NULL,	"timer_32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK(NULL,	"timer_sys_ck",	&sys_ck,	CK_3XXX),
+	CLK(NULL,	"cpufreq_ck",	&dpll1_ck,	CK_3XXX),
+};
+
+static const char *enable_init_clks[] = {
+	"sdrc_ick",
+	"gpmc_fck",
+	"omapctrl_ick",
+};
+
+int __init omap3xxx_clk_init(void)
+{
+	struct omap_clk *c;
+	u32 cpu_clkflg = 0;
+
+	/*
+	 * 3505 must be tested before 3517, since 3517 returns true
+	 * for both AM3517 chips and AM3517 family chips, which
+	 * includes 3505.  Unfortunately there's no obvious family
+	 * test for 3517/3505 :-(
+	 */
+	if (soc_is_am35xx()) {
+		cpu_mask = RATE_IN_34XX;
+		cpu_clkflg = CK_AM35XX;
+	} else if (cpu_is_omap3630()) {
+		cpu_mask = (RATE_IN_34XX | RATE_IN_36XX);
+		cpu_clkflg = CK_36XX;
+	} else if (cpu_is_ti816x()) {
+		cpu_mask = RATE_IN_TI816X;
+		cpu_clkflg = CK_TI816X;
+	} else if (soc_is_am33xx()) {
+		cpu_mask = RATE_IN_AM33XX;
+	} else if (cpu_is_ti814x()) {
+		cpu_mask = RATE_IN_TI814X;
+	} else if (cpu_is_omap34xx()) {
+		if (omap_rev() == OMAP3430_REV_ES1_0) {
+			cpu_mask = RATE_IN_3430ES1;
+			cpu_clkflg = CK_3430ES1;
+		} else {
+			/*
+			 * Assume that anything that we haven't matched yet
+			 * has 3430ES2-type clocks.
+			 */
+			cpu_mask = RATE_IN_3430ES2PLUS;
+			cpu_clkflg = CK_3430ES2PLUS;
+		}
+	} else {
+		WARN(1, "clock: could not identify OMAP3 variant\n");
+	}
+
+	if (omap3_has_192mhz_clk())
+		omap_96m_alwon_fck = omap_96m_alwon_fck_3630;
+
+	if (cpu_is_omap3630()) {
+		dpll3_m3x2_ck = dpll3_m3x2_ck_3630;
+		dpll4_m2x2_ck = dpll4_m2x2_ck_3630;
+		dpll4_m3x2_ck = dpll4_m3x2_ck_3630;
+		dpll4_m4x2_ck = dpll4_m4x2_ck_3630;
+		dpll4_m5x2_ck = dpll4_m5x2_ck_3630;
+		dpll4_m6x2_ck = dpll4_m6x2_ck_3630;
+	}
+
+	/*
+	 * XXX This type of dynamic rewriting of the clock tree is
+	 * deprecated and should be revised soon.
+	 */
+	if (cpu_is_omap3630())
+		dpll4_dd = dpll4_dd_3630;
+	else
+		dpll4_dd = dpll4_dd_34xx;
+
+	for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks);
+	     c++)
+		if (c->cpu & cpu_clkflg) {
+			clkdev_add(&c->lk);
+			if (!__clk_init(NULL, c->lk.clk))
+				omap2_init_clk_hw_omap_clocks(c->lk.clk);
+		}
+
+	omap2_clk_disable_autoidle_all();
+
+	omap2_clk_enable_init_clocks(enable_init_clks,
+				     ARRAY_SIZE(enable_init_clks));
+
+	pr_info("Clocking rate (Crystal/Core/MPU): %ld.%01ld/%ld/%ld MHz\n",
+		(clk_get_rate(&osc_sys_ck) / 1000000),
+		(clk_get_rate(&osc_sys_ck) / 100000) % 10,
+		(clk_get_rate(&core_ck) / 1000000),
+		(clk_get_rate(&arm_fck) / 1000000));
+
+	/*
+	 * Lock DPLL5 -- here only until other device init code can
+	 * handle this
+	 */
+	if (!cpu_is_ti81xx() && (omap_rev() >= OMAP3430_REV_ES2_0))
+		omap3_clk_lock_dpll5();
+
+	/* Avoid sleeping during omap3_core_dpll_m2_set_rate() */
+	sdrc_ick_p = clk_get(NULL, "sdrc_ick");
+	arm_fck_p = clk_get(NULL, "arm_fck");
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap2/cclock44xx_data.c b/arch/arm/mach-omap2/cclock44xx_data.c
new file mode 100644
index 0000000..aa56c3e
--- /dev/null
+++ b/arch/arm/mach-omap2/cclock44xx_data.c
@@ -0,0 +1,1987 @@
+/*
+ * OMAP4 Clock data
+ *
+ * Copyright (C) 2009-2012 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Paul Walmsley (paul@pwsan.com)
+ * Rajendra Nayak (rnayak@ti.com)
+ * Benoit Cousson (b-cousson@ti.com)
+ * Mike Turquette (mturquette@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.
+ *
+ * XXX Some of the ES1 clocks have been removed/changed; once support
+ * is added for discriminating clocks by ES level, these should be added back
+ * in.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/clk-private.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+
+#include "soc.h"
+#include "iomap.h"
+#include "clock.h"
+#include "clock44xx.h"
+#include "cm1_44xx.h"
+#include "cm2_44xx.h"
+#include "cm-regbits-44xx.h"
+#include "prm44xx.h"
+#include "prm-regbits-44xx.h"
+#include "control.h"
+#include "scrm44xx.h"
+
+/* OMAP4 modulemode control */
+#define OMAP4430_MODULEMODE_HWCTRL_SHIFT		0
+#define OMAP4430_MODULEMODE_SWCTRL_SHIFT		1
+
+/* Root clocks */
+
+DEFINE_CLK_FIXED_RATE(extalt_clkin_ck, CLK_IS_ROOT, 59000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(pad_clks_src_ck, CLK_IS_ROOT, 12000000, 0x0);
+
+DEFINE_CLK_GATE(pad_clks_ck, "pad_clks_src_ck", &pad_clks_src_ck, 0x0,
+		OMAP4430_CM_CLKSEL_ABE, OMAP4430_PAD_CLKS_GATE_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_FIXED_RATE(pad_slimbus_core_clks_ck, CLK_IS_ROOT, 12000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(secure_32k_clk_src_ck, CLK_IS_ROOT, 32768, 0x0);
+
+DEFINE_CLK_FIXED_RATE(slimbus_src_clk, CLK_IS_ROOT, 12000000, 0x0);
+
+DEFINE_CLK_GATE(slimbus_clk, "slimbus_src_clk", &slimbus_src_clk, 0x0,
+		OMAP4430_CM_CLKSEL_ABE, OMAP4430_SLIMBUS_CLK_GATE_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_FIXED_RATE(sys_32k_ck, CLK_IS_ROOT, 32768, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_12000000_ck, CLK_IS_ROOT, 12000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_13000000_ck, CLK_IS_ROOT, 13000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_16800000_ck, CLK_IS_ROOT, 16800000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_19200000_ck, CLK_IS_ROOT, 19200000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_26000000_ck, CLK_IS_ROOT, 26000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_27000000_ck, CLK_IS_ROOT, 27000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(virt_38400000_ck, CLK_IS_ROOT, 38400000, 0x0);
+
+static const char *sys_clkin_ck_parents[] = {
+	"virt_12000000_ck", "virt_13000000_ck", "virt_16800000_ck",
+	"virt_19200000_ck", "virt_26000000_ck", "virt_27000000_ck",
+	"virt_38400000_ck",
+};
+
+DEFINE_CLK_MUX(sys_clkin_ck, sys_clkin_ck_parents, NULL, 0x0,
+	       OMAP4430_CM_SYS_CLKSEL, OMAP4430_SYS_CLKSEL_SHIFT,
+	       OMAP4430_SYS_CLKSEL_WIDTH, CLK_MUX_INDEX_ONE, NULL);
+
+DEFINE_CLK_FIXED_RATE(tie_low_clock_ck, CLK_IS_ROOT, 0, 0x0);
+
+DEFINE_CLK_FIXED_RATE(utmi_phy_clkout_ck, CLK_IS_ROOT, 60000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(xclk60mhsp1_ck, CLK_IS_ROOT, 60000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(xclk60mhsp2_ck, CLK_IS_ROOT, 60000000, 0x0);
+
+DEFINE_CLK_FIXED_RATE(xclk60motg_ck, CLK_IS_ROOT, 60000000, 0x0);
+
+/* Module clocks and DPLL outputs */
+
+static const char *abe_dpll_bypass_clk_mux_ck_parents[] = {
+	"sys_clkin_ck", "sys_32k_ck",
+};
+
+DEFINE_CLK_MUX(abe_dpll_bypass_clk_mux_ck, abe_dpll_bypass_clk_mux_ck_parents,
+	       NULL, 0x0, OMAP4430_CM_L4_WKUP_CLKSEL, OMAP4430_CLKSEL_SHIFT,
+	       OMAP4430_CLKSEL_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_MUX(abe_dpll_refclk_mux_ck, abe_dpll_bypass_clk_mux_ck_parents, NULL,
+	       0x0, OMAP4430_CM_ABE_PLL_REF_CLKSEL, OMAP4430_CLKSEL_0_0_SHIFT,
+	       OMAP4430_CLKSEL_0_0_WIDTH, 0x0, NULL);
+
+/* DPLL_ABE */
+static struct dpll_data dpll_abe_dd = {
+	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_ABE,
+	.clk_bypass	= &abe_dpll_bypass_clk_mux_ck,
+	.clk_ref	= &abe_dpll_refclk_mux_ck,
+	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_ABE,
+	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_ABE,
+	.idlest_reg	= OMAP4430_CM_IDLEST_DPLL_ABE,
+	.mult_mask	= OMAP4430_DPLL_MULT_MASK,
+	.div1_mask	= OMAP4430_DPLL_DIV_MASK,
+	.enable_mask	= OMAP4430_DPLL_EN_MASK,
+	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
+	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
+	.max_multiplier	= 2047,
+	.max_divider	= 128,
+	.min_divider	= 1,
+};
+
+
+static const char *dpll_abe_ck_parents[] = {
+	"abe_dpll_refclk_mux_ck",
+};
+
+static struct clk dpll_abe_ck;
+
+static const struct clk_ops dpll_abe_ck_ops = {
+	.enable		= &omap3_noncore_dpll_enable,
+	.disable	= &omap3_noncore_dpll_disable,
+	.recalc_rate	= &omap4_dpll_regm4xen_recalc,
+	.round_rate	= &omap4_dpll_regm4xen_round_rate,
+	.set_rate	= &omap3_noncore_dpll_set_rate,
+	.get_parent	= &omap2_init_dpll_parent,
+};
+
+static struct clk_hw_omap dpll_abe_ck_hw = {
+	.hw = {
+		.clk = &dpll_abe_ck,
+	},
+	.dpll_data	= &dpll_abe_dd,
+	.ops		= &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_abe_ck, dpll_abe_ck_parents, dpll_abe_ck_ops);
+
+static const char *dpll_abe_x2_ck_parents[] = {
+	"dpll_abe_ck",
+};
+
+static struct clk dpll_abe_x2_ck;
+
+static const struct clk_ops dpll_abe_x2_ck_ops = {
+	.recalc_rate	= &omap3_clkoutx2_recalc,
+};
+
+static struct clk_hw_omap dpll_abe_x2_ck_hw = {
+	.hw = {
+		.clk = &dpll_abe_x2_ck,
+	},
+	.flags		= CLOCK_CLKOUTX2,
+	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
+	.ops		= &clkhwops_omap4_dpllmx,
+};
+
+DEFINE_STRUCT_CLK(dpll_abe_x2_ck, dpll_abe_x2_ck_parents, dpll_abe_x2_ck_ops);
+
+static const struct clk_ops omap_hsdivider_ops = {
+	.set_rate	= &omap2_clksel_set_rate,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate,
+};
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_abe_m2x2_ck, "dpll_abe_x2_ck", &dpll_abe_x2_ck,
+			  0x0, OMAP4430_CM_DIV_M2_DPLL_ABE,
+			  OMAP4430_DPLL_CLKOUT_DIV_MASK);
+
+DEFINE_CLK_FIXED_FACTOR(abe_24m_fclk, "dpll_abe_m2x2_ck", &dpll_abe_m2x2_ck,
+			0x0, 1, 8);
+
+DEFINE_CLK_DIVIDER(abe_clk, "dpll_abe_m2x2_ck", &dpll_abe_m2x2_ck, 0x0,
+		   OMAP4430_CM_CLKSEL_ABE, OMAP4430_CLKSEL_OPP_SHIFT,
+		   OMAP4430_CLKSEL_OPP_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
+
+DEFINE_CLK_DIVIDER(aess_fclk, "abe_clk", &abe_clk, 0x0,
+		   OMAP4430_CM1_ABE_AESS_CLKCTRL,
+		   OMAP4430_CLKSEL_AESS_FCLK_SHIFT,
+		   OMAP4430_CLKSEL_AESS_FCLK_WIDTH,
+		   0x0, NULL);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_abe_m3x2_ck, "dpll_abe_x2_ck", &dpll_abe_x2_ck,
+			  0x0, OMAP4430_CM_DIV_M3_DPLL_ABE,
+			  OMAP4430_DPLL_CLKOUTHIF_DIV_MASK);
+
+static const char *core_hsd_byp_clk_mux_ck_parents[] = {
+	"sys_clkin_ck", "dpll_abe_m3x2_ck",
+};
+
+DEFINE_CLK_MUX(core_hsd_byp_clk_mux_ck, core_hsd_byp_clk_mux_ck_parents, NULL,
+	       0x0, OMAP4430_CM_CLKSEL_DPLL_CORE,
+	       OMAP4430_DPLL_BYP_CLKSEL_SHIFT, OMAP4430_DPLL_BYP_CLKSEL_WIDTH,
+	       0x0, NULL);
+
+/* DPLL_CORE */
+static struct dpll_data dpll_core_dd = {
+	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_CORE,
+	.clk_bypass	= &core_hsd_byp_clk_mux_ck,
+	.clk_ref	= &sys_clkin_ck,
+	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_CORE,
+	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_CORE,
+	.idlest_reg	= OMAP4430_CM_IDLEST_DPLL_CORE,
+	.mult_mask	= OMAP4430_DPLL_MULT_MASK,
+	.div1_mask	= OMAP4430_DPLL_DIV_MASK,
+	.enable_mask	= OMAP4430_DPLL_EN_MASK,
+	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
+	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
+	.max_multiplier	= 2047,
+	.max_divider	= 128,
+	.min_divider	= 1,
+};
+
+
+static const char *dpll_core_ck_parents[] = {
+	"sys_clkin_ck",
+};
+
+static struct clk dpll_core_ck;
+
+static const struct clk_ops dpll_core_ck_ops = {
+	.recalc_rate	= &omap3_dpll_recalc,
+	.get_parent	= &omap2_init_dpll_parent,
+};
+
+static struct clk_hw_omap dpll_core_ck_hw = {
+	.hw = {
+		.clk = &dpll_core_ck,
+	},
+	.dpll_data	= &dpll_core_dd,
+	.ops		= &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_core_ck, dpll_core_ck_parents, dpll_core_ck_ops);
+
+static const char *dpll_core_x2_ck_parents[] = {
+	"dpll_core_ck",
+};
+
+static struct clk dpll_core_x2_ck;
+
+static struct clk_hw_omap dpll_core_x2_ck_hw = {
+	.hw = {
+		.clk = &dpll_core_x2_ck,
+	},
+};
+
+DEFINE_STRUCT_CLK(dpll_core_x2_ck, dpll_core_x2_ck_parents, dpll_abe_x2_ck_ops);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m6x2_ck, "dpll_core_x2_ck",
+			  &dpll_core_x2_ck, 0x0, OMAP4430_CM_DIV_M6_DPLL_CORE,
+			  OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m2_ck, "dpll_core_ck", &dpll_core_ck, 0x0,
+			  OMAP4430_CM_DIV_M2_DPLL_CORE,
+			  OMAP4430_DPLL_CLKOUT_DIV_MASK);
+
+DEFINE_CLK_FIXED_FACTOR(ddrphy_ck, "dpll_core_m2_ck", &dpll_core_m2_ck, 0x0, 1,
+			2);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m5x2_ck, "dpll_core_x2_ck",
+			  &dpll_core_x2_ck, 0x0, OMAP4430_CM_DIV_M5_DPLL_CORE,
+			  OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK);
+
+DEFINE_CLK_DIVIDER(div_core_ck, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck, 0x0,
+		   OMAP4430_CM_CLKSEL_CORE, OMAP4430_CLKSEL_CORE_SHIFT,
+		   OMAP4430_CLKSEL_CORE_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_OMAP_HSDIVIDER(div_iva_hs_clk, "dpll_core_m5x2_ck",
+			  &dpll_core_m5x2_ck, 0x0, OMAP4430_CM_BYPCLK_DPLL_IVA,
+			  OMAP4430_CLKSEL_0_1_MASK);
+
+DEFINE_CLK_DIVIDER(div_mpu_hs_clk, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck,
+		   0x0, OMAP4430_CM_BYPCLK_DPLL_MPU, OMAP4430_CLKSEL_0_1_SHIFT,
+		   OMAP4430_CLKSEL_0_1_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m4x2_ck, "dpll_core_x2_ck",
+			  &dpll_core_x2_ck, 0x0, OMAP4430_CM_DIV_M4_DPLL_CORE,
+			  OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK);
+
+DEFINE_CLK_FIXED_FACTOR(dll_clk_div_ck, "dpll_core_m4x2_ck", &dpll_core_m4x2_ck,
+			0x0, 1, 2);
+
+DEFINE_CLK_DIVIDER(dpll_abe_m2_ck, "dpll_abe_ck", &dpll_abe_ck, 0x0,
+		   OMAP4430_CM_DIV_M2_DPLL_ABE, OMAP4430_DPLL_CLKOUT_DIV_SHIFT,
+		   OMAP4430_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
+
+static const struct clk_ops dmic_fck_ops = {
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.get_parent	= &omap2_clksel_find_parent_index,
+	.set_parent	= &omap2_clksel_set_parent,
+	.init		= &omap2_init_clk_clkdm,
+};
+
+static const char *dpll_core_m3x2_ck_parents[] = {
+	"dpll_core_x2_ck",
+};
+
+static const struct clksel dpll_core_m3x2_div[] = {
+	{ .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates },
+	{ .parent = NULL },
+};
+
+/* XXX Missing round_rate, set_rate in ops */
+DEFINE_CLK_OMAP_MUX_GATE(dpll_core_m3x2_ck, NULL, dpll_core_m3x2_div,
+			 OMAP4430_CM_DIV_M3_DPLL_CORE,
+			 OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+			 OMAP4430_CM_DIV_M3_DPLL_CORE,
+			 OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT, NULL,
+			 dpll_core_m3x2_ck_parents, dmic_fck_ops);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m7x2_ck, "dpll_core_x2_ck",
+			  &dpll_core_x2_ck, 0x0, OMAP4430_CM_DIV_M7_DPLL_CORE,
+			  OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK);
+
+static const char *iva_hsd_byp_clk_mux_ck_parents[] = {
+	"sys_clkin_ck", "div_iva_hs_clk",
+};
+
+DEFINE_CLK_MUX(iva_hsd_byp_clk_mux_ck, iva_hsd_byp_clk_mux_ck_parents, NULL,
+	       0x0, OMAP4430_CM_CLKSEL_DPLL_IVA, OMAP4430_DPLL_BYP_CLKSEL_SHIFT,
+	       OMAP4430_DPLL_BYP_CLKSEL_WIDTH, 0x0, NULL);
+
+/* DPLL_IVA */
+static struct dpll_data dpll_iva_dd = {
+	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_IVA,
+	.clk_bypass	= &iva_hsd_byp_clk_mux_ck,
+	.clk_ref	= &sys_clkin_ck,
+	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_IVA,
+	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_IVA,
+	.idlest_reg	= OMAP4430_CM_IDLEST_DPLL_IVA,
+	.mult_mask	= OMAP4430_DPLL_MULT_MASK,
+	.div1_mask	= OMAP4430_DPLL_DIV_MASK,
+	.enable_mask	= OMAP4430_DPLL_EN_MASK,
+	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
+	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
+	.max_multiplier	= 2047,
+	.max_divider	= 128,
+	.min_divider	= 1,
+};
+
+static struct clk dpll_iva_ck;
+
+static struct clk_hw_omap dpll_iva_ck_hw = {
+	.hw = {
+		.clk = &dpll_iva_ck,
+	},
+	.dpll_data	= &dpll_iva_dd,
+	.ops		= &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_iva_ck, dpll_core_ck_parents, dpll_abe_ck_ops);
+
+static const char *dpll_iva_x2_ck_parents[] = {
+	"dpll_iva_ck",
+};
+
+static struct clk dpll_iva_x2_ck;
+
+static struct clk_hw_omap dpll_iva_x2_ck_hw = {
+	.hw = {
+		.clk = &dpll_iva_x2_ck,
+	},
+};
+
+DEFINE_STRUCT_CLK(dpll_iva_x2_ck, dpll_iva_x2_ck_parents, dpll_abe_x2_ck_ops);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_iva_m4x2_ck, "dpll_iva_x2_ck", &dpll_iva_x2_ck,
+			  0x0, OMAP4430_CM_DIV_M4_DPLL_IVA,
+			  OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_iva_m5x2_ck, "dpll_iva_x2_ck", &dpll_iva_x2_ck,
+			  0x0, OMAP4430_CM_DIV_M5_DPLL_IVA,
+			  OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK);
+
+/* DPLL_MPU */
+static struct dpll_data dpll_mpu_dd = {
+	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_MPU,
+	.clk_bypass	= &div_mpu_hs_clk,
+	.clk_ref	= &sys_clkin_ck,
+	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_MPU,
+	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_MPU,
+	.idlest_reg	= OMAP4430_CM_IDLEST_DPLL_MPU,
+	.mult_mask	= OMAP4430_DPLL_MULT_MASK,
+	.div1_mask	= OMAP4430_DPLL_DIV_MASK,
+	.enable_mask	= OMAP4430_DPLL_EN_MASK,
+	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
+	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
+	.max_multiplier	= 2047,
+	.max_divider	= 128,
+	.min_divider	= 1,
+};
+
+static struct clk dpll_mpu_ck;
+
+static struct clk_hw_omap dpll_mpu_ck_hw = {
+	.hw = {
+		.clk = &dpll_mpu_ck,
+	},
+	.dpll_data	= &dpll_mpu_dd,
+	.ops		= &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_mpu_ck, dpll_core_ck_parents, dpll_abe_ck_ops);
+
+DEFINE_CLK_FIXED_FACTOR(mpu_periphclk, "dpll_mpu_ck", &dpll_mpu_ck, 0x0, 1, 2);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_mpu_m2_ck, "dpll_mpu_ck", &dpll_mpu_ck, 0x0,
+			  OMAP4430_CM_DIV_M2_DPLL_MPU,
+			  OMAP4430_DPLL_CLKOUT_DIV_MASK);
+
+DEFINE_CLK_FIXED_FACTOR(per_hs_clk_div_ck, "dpll_abe_m3x2_ck",
+			&dpll_abe_m3x2_ck, 0x0, 1, 2);
+
+static const char *per_hsd_byp_clk_mux_ck_parents[] = {
+	"sys_clkin_ck", "per_hs_clk_div_ck",
+};
+
+DEFINE_CLK_MUX(per_hsd_byp_clk_mux_ck, per_hsd_byp_clk_mux_ck_parents, NULL,
+	       0x0, OMAP4430_CM_CLKSEL_DPLL_PER, OMAP4430_DPLL_BYP_CLKSEL_SHIFT,
+	       OMAP4430_DPLL_BYP_CLKSEL_WIDTH, 0x0, NULL);
+
+/* DPLL_PER */
+static struct dpll_data dpll_per_dd = {
+	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_PER,
+	.clk_bypass	= &per_hsd_byp_clk_mux_ck,
+	.clk_ref	= &sys_clkin_ck,
+	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_PER,
+	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_PER,
+	.idlest_reg	= OMAP4430_CM_IDLEST_DPLL_PER,
+	.mult_mask	= OMAP4430_DPLL_MULT_MASK,
+	.div1_mask	= OMAP4430_DPLL_DIV_MASK,
+	.enable_mask	= OMAP4430_DPLL_EN_MASK,
+	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
+	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
+	.max_multiplier	= 2047,
+	.max_divider	= 128,
+	.min_divider	= 1,
+};
+
+
+static struct clk dpll_per_ck;
+
+static struct clk_hw_omap dpll_per_ck_hw = {
+	.hw = {
+		.clk = &dpll_per_ck,
+	},
+	.dpll_data	= &dpll_per_dd,
+	.ops		= &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_per_ck, dpll_core_ck_parents, dpll_abe_ck_ops);
+
+DEFINE_CLK_DIVIDER(dpll_per_m2_ck, "dpll_per_ck", &dpll_per_ck, 0x0,
+		   OMAP4430_CM_DIV_M2_DPLL_PER, OMAP4430_DPLL_CLKOUT_DIV_SHIFT,
+		   OMAP4430_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
+
+static const char *dpll_per_x2_ck_parents[] = {
+	"dpll_per_ck",
+};
+
+static struct clk dpll_per_x2_ck;
+
+static struct clk_hw_omap dpll_per_x2_ck_hw = {
+	.hw = {
+		.clk = &dpll_per_x2_ck,
+	},
+	.flags		= CLOCK_CLKOUTX2,
+	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_PER,
+	.ops		= &clkhwops_omap4_dpllmx,
+};
+
+DEFINE_STRUCT_CLK(dpll_per_x2_ck, dpll_per_x2_ck_parents, dpll_abe_x2_ck_ops);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m2x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck,
+			  0x0, OMAP4430_CM_DIV_M2_DPLL_PER,
+			  OMAP4430_DPLL_CLKOUT_DIV_MASK);
+
+static const char *dpll_per_m3x2_ck_parents[] = {
+	"dpll_per_x2_ck",
+};
+
+static const struct clksel dpll_per_m3x2_div[] = {
+	{ .parent = &dpll_per_x2_ck, .rates = div31_1to31_rates },
+	{ .parent = NULL },
+};
+
+/* XXX Missing round_rate, set_rate in ops */
+DEFINE_CLK_OMAP_MUX_GATE(dpll_per_m3x2_ck, NULL, dpll_per_m3x2_div,
+			 OMAP4430_CM_DIV_M3_DPLL_PER,
+			 OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+			 OMAP4430_CM_DIV_M3_DPLL_PER,
+			 OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT, NULL,
+			 dpll_per_m3x2_ck_parents, dmic_fck_ops);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m4x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck,
+			  0x0, OMAP4430_CM_DIV_M4_DPLL_PER,
+			  OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m5x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck,
+			  0x0, OMAP4430_CM_DIV_M5_DPLL_PER,
+			  OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m6x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck,
+			  0x0, OMAP4430_CM_DIV_M6_DPLL_PER,
+			  OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m7x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck,
+			  0x0, OMAP4430_CM_DIV_M7_DPLL_PER,
+			  OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK);
+
+DEFINE_CLK_FIXED_FACTOR(usb_hs_clk_div_ck, "dpll_abe_m3x2_ck",
+			&dpll_abe_m3x2_ck, 0x0, 1, 3);
+
+/* DPLL_USB */
+static struct dpll_data dpll_usb_dd = {
+	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_USB,
+	.clk_bypass	= &usb_hs_clk_div_ck,
+	.flags		= DPLL_J_TYPE,
+	.clk_ref	= &sys_clkin_ck,
+	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_USB,
+	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_USB,
+	.idlest_reg	= OMAP4430_CM_IDLEST_DPLL_USB,
+	.mult_mask	= OMAP4430_DPLL_MULT_USB_MASK,
+	.div1_mask	= OMAP4430_DPLL_DIV_0_7_MASK,
+	.enable_mask	= OMAP4430_DPLL_EN_MASK,
+	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
+	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
+	.sddiv_mask	= OMAP4430_DPLL_SD_DIV_MASK,
+	.max_multiplier	= 4095,
+	.max_divider	= 256,
+	.min_divider	= 1,
+};
+
+static struct clk dpll_usb_ck;
+
+static struct clk_hw_omap dpll_usb_ck_hw = {
+	.hw = {
+		.clk = &dpll_usb_ck,
+	},
+	.dpll_data	= &dpll_usb_dd,
+	.ops		= &clkhwops_omap3_dpll,
+};
+
+DEFINE_STRUCT_CLK(dpll_usb_ck, dpll_core_ck_parents, dpll_abe_ck_ops);
+
+static const char *dpll_usb_clkdcoldo_ck_parents[] = {
+	"dpll_usb_ck",
+};
+
+static struct clk dpll_usb_clkdcoldo_ck;
+
+static const struct clk_ops dpll_usb_clkdcoldo_ck_ops = {
+};
+
+static struct clk_hw_omap dpll_usb_clkdcoldo_ck_hw = {
+	.hw = {
+		.clk = &dpll_usb_clkdcoldo_ck,
+	},
+	.clksel_reg	= OMAP4430_CM_CLKDCOLDO_DPLL_USB,
+	.ops		= &clkhwops_omap4_dpllmx,
+};
+
+DEFINE_STRUCT_CLK(dpll_usb_clkdcoldo_ck, dpll_usb_clkdcoldo_ck_parents,
+		  dpll_usb_clkdcoldo_ck_ops);
+
+DEFINE_CLK_OMAP_HSDIVIDER(dpll_usb_m2_ck, "dpll_usb_ck", &dpll_usb_ck, 0x0,
+			  OMAP4430_CM_DIV_M2_DPLL_USB,
+			  OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK);
+
+static const char *ducati_clk_mux_ck_parents[] = {
+	"div_core_ck", "dpll_per_m6x2_ck",
+};
+
+DEFINE_CLK_MUX(ducati_clk_mux_ck, ducati_clk_mux_ck_parents, NULL, 0x0,
+	       OMAP4430_CM_CLKSEL_DUCATI_ISS_ROOT, OMAP4430_CLKSEL_0_0_SHIFT,
+	       OMAP4430_CLKSEL_0_0_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_FIXED_FACTOR(func_12m_fclk, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck,
+			0x0, 1, 16);
+
+DEFINE_CLK_FIXED_FACTOR(func_24m_clk, "dpll_per_m2_ck", &dpll_per_m2_ck, 0x0,
+			1, 4);
+
+DEFINE_CLK_FIXED_FACTOR(func_24mc_fclk, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck,
+			0x0, 1, 8);
+
+static const struct clk_div_table func_48m_fclk_rates[] = {
+	{ .div = 4, .val = 0 },
+	{ .div = 8, .val = 1 },
+	{ .div = 0 },
+};
+DEFINE_CLK_DIVIDER_TABLE(func_48m_fclk, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck,
+			 0x0, OMAP4430_CM_SCALE_FCLK, OMAP4430_SCALE_FCLK_SHIFT,
+			 OMAP4430_SCALE_FCLK_WIDTH, 0x0, func_48m_fclk_rates,
+			 NULL);
+
+DEFINE_CLK_FIXED_FACTOR(func_48mc_fclk,	"dpll_per_m2x2_ck", &dpll_per_m2x2_ck,
+			0x0, 1, 4);
+
+static const struct clk_div_table func_64m_fclk_rates[] = {
+	{ .div = 2, .val = 0 },
+	{ .div = 4, .val = 1 },
+	{ .div = 0 },
+};
+DEFINE_CLK_DIVIDER_TABLE(func_64m_fclk, "dpll_per_m4x2_ck", &dpll_per_m4x2_ck,
+			 0x0, OMAP4430_CM_SCALE_FCLK, OMAP4430_SCALE_FCLK_SHIFT,
+			 OMAP4430_SCALE_FCLK_WIDTH, 0x0, func_64m_fclk_rates,
+			 NULL);
+
+static const struct clk_div_table func_96m_fclk_rates[] = {
+	{ .div = 2, .val = 0 },
+	{ .div = 4, .val = 1 },
+	{ .div = 0 },
+};
+DEFINE_CLK_DIVIDER_TABLE(func_96m_fclk, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck,
+			 0x0, OMAP4430_CM_SCALE_FCLK, OMAP4430_SCALE_FCLK_SHIFT,
+			 OMAP4430_SCALE_FCLK_WIDTH, 0x0, func_96m_fclk_rates,
+			 NULL);
+
+static const struct clk_div_table init_60m_fclk_rates[] = {
+	{ .div = 1, .val = 0 },
+	{ .div = 8, .val = 1 },
+	{ .div = 0 },
+};
+DEFINE_CLK_DIVIDER_TABLE(init_60m_fclk, "dpll_usb_m2_ck", &dpll_usb_m2_ck,
+			 0x0, OMAP4430_CM_CLKSEL_USB_60MHZ,
+			 OMAP4430_CLKSEL_0_0_SHIFT, OMAP4430_CLKSEL_0_0_WIDTH,
+			 0x0, init_60m_fclk_rates, NULL);
+
+DEFINE_CLK_DIVIDER(l3_div_ck, "div_core_ck", &div_core_ck, 0x0,
+		   OMAP4430_CM_CLKSEL_CORE, OMAP4430_CLKSEL_L3_SHIFT,
+		   OMAP4430_CLKSEL_L3_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_DIVIDER(l4_div_ck, "l3_div_ck", &l3_div_ck, 0x0,
+		   OMAP4430_CM_CLKSEL_CORE, OMAP4430_CLKSEL_L4_SHIFT,
+		   OMAP4430_CLKSEL_L4_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_FIXED_FACTOR(lp_clk_div_ck, "dpll_abe_m2x2_ck", &dpll_abe_m2x2_ck,
+			0x0, 1, 16);
+
+static const char *l4_wkup_clk_mux_ck_parents[] = {
+	"sys_clkin_ck", "lp_clk_div_ck",
+};
+
+DEFINE_CLK_MUX(l4_wkup_clk_mux_ck, l4_wkup_clk_mux_ck_parents, NULL, 0x0,
+	       OMAP4430_CM_L4_WKUP_CLKSEL, OMAP4430_CLKSEL_0_0_SHIFT,
+	       OMAP4430_CLKSEL_0_0_WIDTH, 0x0, NULL);
+
+static const struct clk_div_table ocp_abe_iclk_rates[] = {
+	{ .div = 2, .val = 0 },
+	{ .div = 1, .val = 1 },
+	{ .div = 0 },
+};
+DEFINE_CLK_DIVIDER_TABLE(ocp_abe_iclk, "aess_fclk", &aess_fclk, 0x0,
+			 OMAP4430_CM1_ABE_AESS_CLKCTRL,
+			 OMAP4430_CLKSEL_AESS_FCLK_SHIFT,
+			 OMAP4430_CLKSEL_AESS_FCLK_WIDTH,
+			 0x0, ocp_abe_iclk_rates, NULL);
+
+DEFINE_CLK_FIXED_FACTOR(per_abe_24m_fclk, "dpll_abe_m2_ck", &dpll_abe_m2_ck,
+			0x0, 1, 4);
+
+DEFINE_CLK_DIVIDER(per_abe_nc_fclk, "dpll_abe_m2_ck", &dpll_abe_m2_ck, 0x0,
+		   OMAP4430_CM_SCALE_FCLK, OMAP4430_SCALE_FCLK_SHIFT,
+		   OMAP4430_SCALE_FCLK_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_DIVIDER(syc_clk_div_ck, "sys_clkin_ck", &sys_clkin_ck, 0x0,
+		   OMAP4430_CM_ABE_DSS_SYS_CLKSEL, OMAP4430_CLKSEL_0_0_SHIFT,
+		   OMAP4430_CLKSEL_0_0_WIDTH, 0x0, NULL);
+
+static struct clk dbgclk_mux_ck;
+DEFINE_STRUCT_CLK_HW_OMAP(dbgclk_mux_ck, NULL);
+DEFINE_STRUCT_CLK(dbgclk_mux_ck, dpll_core_ck_parents,
+		  dpll_usb_clkdcoldo_ck_ops);
+
+/* Leaf clocks controlled by modules */
+
+DEFINE_CLK_GATE(aes1_fck, "l3_div_ck", &l3_div_ck, 0x0,
+		OMAP4430_CM_L4SEC_AES1_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(aes2_fck, "l3_div_ck", &l3_div_ck, 0x0,
+		OMAP4430_CM_L4SEC_AES2_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(aess_fck, "aess_fclk", &aess_fclk, 0x0,
+		OMAP4430_CM1_ABE_AESS_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(bandgap_fclk, "sys_32k_ck", &sys_32k_ck, 0x0,
+		OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+		OMAP4430_OPTFCLKEN_BGAP_32K_SHIFT, 0x0, NULL);
+
+static const struct clk_div_table div_ts_ck_rates[] = {
+	{ .div = 8, .val = 0 },
+	{ .div = 16, .val = 1 },
+	{ .div = 32, .val = 2 },
+	{ .div = 0 },
+};
+DEFINE_CLK_DIVIDER_TABLE(div_ts_ck, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck,
+			 0x0, OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+			 OMAP4430_CLKSEL_24_25_SHIFT,
+			 OMAP4430_CLKSEL_24_25_WIDTH, 0x0, div_ts_ck_rates,
+			 NULL);
+
+DEFINE_CLK_GATE(bandgap_ts_fclk, "div_ts_ck", &div_ts_ck, 0x0,
+		OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+		OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(des3des_fck, "l4_div_ck", &l4_div_ck, 0x0,
+		OMAP4430_CM_L4SEC_DES3DES_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT,
+		0x0, NULL);
+
+static const char *dmic_sync_mux_ck_parents[] = {
+	"abe_24m_fclk", "syc_clk_div_ck", "func_24m_clk",
+};
+
+DEFINE_CLK_MUX(dmic_sync_mux_ck, dmic_sync_mux_ck_parents, NULL,
+	       0x0, OMAP4430_CM1_ABE_DMIC_CLKCTRL,
+	       OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
+	       OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
+
+static const struct clksel func_dmic_abe_gfclk_sel[] = {
+	{ .parent = &dmic_sync_mux_ck, .rates = div_1_0_rates },
+	{ .parent = &pad_clks_ck, .rates = div_1_1_rates },
+	{ .parent = &slimbus_clk, .rates = div_1_2_rates },
+	{ .parent = NULL },
+};
+
+static const char *dmic_fck_parents[] = {
+	"dmic_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
+};
+
+/* Merged func_dmic_abe_gfclk into dmic */
+static struct clk dmic_fck;
+
+DEFINE_CLK_OMAP_MUX_GATE(dmic_fck, "abe_clkdm", func_dmic_abe_gfclk_sel,
+			 OMAP4430_CM1_ABE_DMIC_CLKCTRL,
+			 OMAP4430_CLKSEL_SOURCE_MASK,
+			 OMAP4430_CM1_ABE_DMIC_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 dmic_fck_parents, dmic_fck_ops);
+
+DEFINE_CLK_GATE(dsp_fck, "dpll_iva_m4x2_ck", &dpll_iva_m4x2_ck, 0x0,
+		OMAP4430_CM_TESLA_TESLA_CLKCTRL,
+		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(dss_sys_clk, "syc_clk_div_ck", &syc_clk_div_ck, 0x0,
+		OMAP4430_CM_DSS_DSS_CLKCTRL,
+		OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(dss_tv_clk, "extalt_clkin_ck", &extalt_clkin_ck, 0x0,
+		OMAP4430_CM_DSS_DSS_CLKCTRL,
+		OMAP4430_OPTFCLKEN_TV_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(dss_dss_clk, "dpll_per_m5x2_ck", &dpll_per_m5x2_ck, 0x0,
+		OMAP4430_CM_DSS_DSS_CLKCTRL, OMAP4430_OPTFCLKEN_DSSCLK_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(dss_48mhz_clk, "func_48mc_fclk", &func_48mc_fclk, 0x0,
+		OMAP4430_CM_DSS_DSS_CLKCTRL, OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(dss_fck, "l3_div_ck", &l3_div_ck, 0x0,
+		OMAP4430_CM_DSS_DSS_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(efuse_ctrl_cust_fck, "sys_clkin_ck", &sys_clkin_ck, 0x0,
+		OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(emif1_fck, "ddrphy_ck", &ddrphy_ck, 0x0,
+		OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL,
+		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(emif2_fck, "ddrphy_ck", &ddrphy_ck, 0x0,
+		OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL,
+		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_DIVIDER(fdif_fck, "dpll_per_m4x2_ck", &dpll_per_m4x2_ck, 0x0,
+		   OMAP4430_CM_CAM_FDIF_CLKCTRL, OMAP4430_CLKSEL_FCLK_SHIFT,
+		   OMAP4430_CLKSEL_FCLK_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
+
+DEFINE_CLK_GATE(fpka_fck, "l4_div_ck", &l4_div_ck, 0x0,
+		OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio1_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
+		OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
+		OMAP4430_OPTFCLKEN_DBCLK_SHIFT,	0x0, NULL);
+
+DEFINE_CLK_GATE(gpio1_ick, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck, 0x0,
+		OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
+		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio2_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
+		OMAP4430_CM_L4PER_GPIO2_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(gpio2_ick, "l4_div_ck", &l4_div_ck, 0x0,
+		OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
+		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio3_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
+		OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
+		OMAP4430_OPTFCLKEN_DBCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio3_ick, "l4_div_ck", &l4_div_ck, 0x0,
+		OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
+		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio4_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
+		OMAP4430_CM_L4PER_GPIO4_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(gpio4_ick, "l4_div_ck", &l4_div_ck, 0x0,
+		OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
+		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio5_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
+		OMAP4430_CM_L4PER_GPIO5_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(gpio5_ick, "l4_div_ck", &l4_div_ck, 0x0,
+		OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
+		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpio6_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
+		OMAP4430_CM_L4PER_GPIO6_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(gpio6_ick, "l4_div_ck", &l4_div_ck, 0x0,
+		OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
+		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(gpmc_ick, "l3_div_ck", &l3_div_ck, 0x0,
+		OMAP4430_CM_L3_2_GPMC_CLKCTRL, OMAP4430_MODULEMODE_HWCTRL_SHIFT,
+		0x0, NULL);
+
+static const struct clksel sgx_clk_mux_sel[] = {
+	{ .parent = &dpll_core_m7x2_ck, .rates = div_1_0_rates },
+	{ .parent = &dpll_per_m7x2_ck, .rates = div_1_1_rates },
+	{ .parent = NULL },
+};
+
+static const char *gpu_fck_parents[] = {
+	"dpll_core_m7x2_ck", "dpll_per_m7x2_ck",
+};
+
+/* Merged sgx_clk_mux into gpu */
+DEFINE_CLK_OMAP_MUX_GATE(gpu_fck, "l3_gfx_clkdm", sgx_clk_mux_sel,
+			 OMAP4430_CM_GFX_GFX_CLKCTRL,
+			 OMAP4430_CLKSEL_SGX_FCLK_MASK,
+			 OMAP4430_CM_GFX_GFX_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 gpu_fck_parents, dmic_fck_ops);
+
+DEFINE_CLK_GATE(hdq1w_fck, "func_12m_fclk", &func_12m_fclk, 0x0,
+		OMAP4430_CM_L4PER_HDQ1W_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_DIVIDER(hsi_fck, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck, 0x0,
+		   OMAP4430_CM_L3INIT_HSI_CLKCTRL, OMAP4430_CLKSEL_24_25_SHIFT,
+		   OMAP4430_CLKSEL_24_25_WIDTH, CLK_DIVIDER_POWER_OF_TWO,
+		   NULL);
+
+DEFINE_CLK_GATE(i2c1_fck, "func_96m_fclk", &func_96m_fclk, 0x0,
+		OMAP4430_CM_L4PER_I2C1_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(i2c2_fck, "func_96m_fclk", &func_96m_fclk, 0x0,
+		OMAP4430_CM_L4PER_I2C2_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(i2c3_fck, "func_96m_fclk", &func_96m_fclk, 0x0,
+		OMAP4430_CM_L4PER_I2C3_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(i2c4_fck, "func_96m_fclk", &func_96m_fclk, 0x0,
+		OMAP4430_CM_L4PER_I2C4_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(ipu_fck, "ducati_clk_mux_ck", &ducati_clk_mux_ck, 0x0,
+		OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
+		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(iss_ctrlclk, "func_96m_fclk", &func_96m_fclk, 0x0,
+		OMAP4430_CM_CAM_ISS_CLKCTRL, OMAP4430_OPTFCLKEN_CTRLCLK_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(iss_fck, "ducati_clk_mux_ck", &ducati_clk_mux_ck, 0x0,
+		OMAP4430_CM_CAM_ISS_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(iva_fck, "dpll_iva_m5x2_ck", &dpll_iva_m5x2_ck, 0x0,
+		OMAP4430_CM_IVAHD_IVAHD_CLKCTRL,
+		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(kbd_fck, "sys_32k_ck", &sys_32k_ck, 0x0,
+		OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+static struct clk l3_instr_ick;
+
+static const char *l3_instr_ick_parent_names[] = {
+	"l3_div_ck",
+};
+
+static const struct clk_ops l3_instr_ick_ops = {
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.init		= &omap2_init_clk_clkdm,
+};
+
+static struct clk_hw_omap l3_instr_ick_hw = {
+	.hw = {
+		.clk = &l3_instr_ick,
+	},
+	.enable_reg	= OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL_SHIFT,
+	.clkdm_name	= "l3_instr_clkdm",
+};
+
+DEFINE_STRUCT_CLK(l3_instr_ick, l3_instr_ick_parent_names, l3_instr_ick_ops);
+
+static struct clk l3_main_3_ick;
+static struct clk_hw_omap l3_main_3_ick_hw = {
+	.hw = {
+		.clk = &l3_main_3_ick,
+	},
+	.enable_reg	= OMAP4430_CM_L3INSTR_L3_3_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL_SHIFT,
+	.clkdm_name	= "l3_instr_clkdm",
+};
+
+DEFINE_STRUCT_CLK(l3_main_3_ick, l3_instr_ick_parent_names, l3_instr_ick_ops);
+
+DEFINE_CLK_MUX(mcasp_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0,
+	       OMAP4430_CM1_ABE_MCASP_CLKCTRL,
+	       OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
+	       OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
+
+static const struct clksel func_mcasp_abe_gfclk_sel[] = {
+	{ .parent = &mcasp_sync_mux_ck, .rates = div_1_0_rates },
+	{ .parent = &pad_clks_ck, .rates = div_1_1_rates },
+	{ .parent = &slimbus_clk, .rates = div_1_2_rates },
+	{ .parent = NULL },
+};
+
+static const char *mcasp_fck_parents[] = {
+	"mcasp_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
+};
+
+/* Merged func_mcasp_abe_gfclk into mcasp */
+DEFINE_CLK_OMAP_MUX_GATE(mcasp_fck, "abe_clkdm", func_mcasp_abe_gfclk_sel,
+			 OMAP4430_CM1_ABE_MCASP_CLKCTRL,
+			 OMAP4430_CLKSEL_SOURCE_MASK,
+			 OMAP4430_CM1_ABE_MCASP_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 mcasp_fck_parents, dmic_fck_ops);
+
+DEFINE_CLK_MUX(mcbsp1_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0,
+	       OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
+	       OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
+	       OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
+
+static const struct clksel func_mcbsp1_gfclk_sel[] = {
+	{ .parent = &mcbsp1_sync_mux_ck, .rates = div_1_0_rates },
+	{ .parent = &pad_clks_ck, .rates = div_1_1_rates },
+	{ .parent = &slimbus_clk, .rates = div_1_2_rates },
+	{ .parent = NULL },
+};
+
+static const char *mcbsp1_fck_parents[] = {
+	"mcbsp1_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
+};
+
+/* Merged func_mcbsp1_gfclk into mcbsp1 */
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp1_fck, "abe_clkdm", func_mcbsp1_gfclk_sel,
+			 OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
+			 OMAP4430_CLKSEL_SOURCE_MASK,
+			 OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 mcbsp1_fck_parents, dmic_fck_ops);
+
+DEFINE_CLK_MUX(mcbsp2_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0,
+	       OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
+	       OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
+	       OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
+
+static const struct clksel func_mcbsp2_gfclk_sel[] = {
+	{ .parent = &mcbsp2_sync_mux_ck, .rates = div_1_0_rates },
+	{ .parent = &pad_clks_ck, .rates = div_1_1_rates },
+	{ .parent = &slimbus_clk, .rates = div_1_2_rates },
+	{ .parent = NULL },
+};
+
+static const char *mcbsp2_fck_parents[] = {
+	"mcbsp2_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
+};
+
+/* Merged func_mcbsp2_gfclk into mcbsp2 */
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp2_fck, "abe_clkdm", func_mcbsp2_gfclk_sel,
+			 OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
+			 OMAP4430_CLKSEL_SOURCE_MASK,
+			 OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 mcbsp2_fck_parents, dmic_fck_ops);
+
+DEFINE_CLK_MUX(mcbsp3_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0,
+	       OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
+	       OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
+	       OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
+
+static const struct clksel func_mcbsp3_gfclk_sel[] = {
+	{ .parent = &mcbsp3_sync_mux_ck, .rates = div_1_0_rates },
+	{ .parent = &pad_clks_ck, .rates = div_1_1_rates },
+	{ .parent = &slimbus_clk, .rates = div_1_2_rates },
+	{ .parent = NULL },
+};
+
+static const char *mcbsp3_fck_parents[] = {
+	"mcbsp3_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
+};
+
+/* Merged func_mcbsp3_gfclk into mcbsp3 */
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp3_fck, "abe_clkdm", func_mcbsp3_gfclk_sel,
+			 OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
+			 OMAP4430_CLKSEL_SOURCE_MASK,
+			 OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 mcbsp3_fck_parents, dmic_fck_ops);
+
+static const char *mcbsp4_sync_mux_ck_parents[] = {
+	"func_96m_fclk", "per_abe_nc_fclk",
+};
+
+DEFINE_CLK_MUX(mcbsp4_sync_mux_ck, mcbsp4_sync_mux_ck_parents, NULL, 0x0,
+	       OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
+	       OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
+	       OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
+
+static const struct clksel per_mcbsp4_gfclk_sel[] = {
+	{ .parent = &mcbsp4_sync_mux_ck, .rates = div_1_0_rates },
+	{ .parent = &pad_clks_ck, .rates = div_1_1_rates },
+	{ .parent = NULL },
+};
+
+static const char *mcbsp4_fck_parents[] = {
+	"mcbsp4_sync_mux_ck", "pad_clks_ck",
+};
+
+/* Merged per_mcbsp4_gfclk into mcbsp4 */
+DEFINE_CLK_OMAP_MUX_GATE(mcbsp4_fck, "l4_per_clkdm", per_mcbsp4_gfclk_sel,
+			 OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
+			 OMAP4430_CLKSEL_SOURCE_24_24_MASK,
+			 OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 mcbsp4_fck_parents, dmic_fck_ops);
+
+DEFINE_CLK_GATE(mcpdm_fck, "pad_clks_ck", &pad_clks_ck, 0x0,
+		OMAP4430_CM1_ABE_PDM_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(mcspi1_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+		OMAP4430_CM_L4PER_MCSPI1_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(mcspi2_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+		OMAP4430_CM_L4PER_MCSPI2_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(mcspi3_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+		OMAP4430_CM_L4PER_MCSPI3_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(mcspi4_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+		OMAP4430_CM_L4PER_MCSPI4_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+static const struct clksel hsmmc1_fclk_sel[] = {
+	{ .parent = &func_64m_fclk, .rates = div_1_0_rates },
+	{ .parent = &func_96m_fclk, .rates = div_1_1_rates },
+	{ .parent = NULL },
+};
+
+static const char *mmc1_fck_parents[] = {
+	"func_64m_fclk", "func_96m_fclk",
+};
+
+/* Merged hsmmc1_fclk into mmc1 */
+DEFINE_CLK_OMAP_MUX_GATE(mmc1_fck, "l3_init_clkdm", hsmmc1_fclk_sel,
+			 OMAP4430_CM_L3INIT_MMC1_CLKCTRL, OMAP4430_CLKSEL_MASK,
+			 OMAP4430_CM_L3INIT_MMC1_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 mmc1_fck_parents, dmic_fck_ops);
+
+/* Merged hsmmc2_fclk into mmc2 */
+DEFINE_CLK_OMAP_MUX_GATE(mmc2_fck, "l3_init_clkdm", hsmmc1_fclk_sel,
+			 OMAP4430_CM_L3INIT_MMC2_CLKCTRL, OMAP4430_CLKSEL_MASK,
+			 OMAP4430_CM_L3INIT_MMC2_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 mmc1_fck_parents, dmic_fck_ops);
+
+DEFINE_CLK_GATE(mmc3_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+		OMAP4430_CM_L4PER_MMCSD3_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(mmc4_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+		OMAP4430_CM_L4PER_MMCSD4_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(mmc5_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+		OMAP4430_CM_L4PER_MMCSD5_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(ocp2scp_usb_phy_phy_48m, "func_48m_fclk", &func_48m_fclk, 0x0,
+		OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
+		OMAP4430_OPTFCLKEN_PHY_48M_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(ocp2scp_usb_phy_ick, "l4_div_ck", &l4_div_ck, 0x0,
+		OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
+		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+static struct clk ocp_wp_noc_ick;
+
+static struct clk_hw_omap ocp_wp_noc_ick_hw = {
+	.hw = {
+		.clk = &ocp_wp_noc_ick,
+	},
+	.enable_reg	= OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL_SHIFT,
+	.clkdm_name	= "l3_instr_clkdm",
+};
+
+DEFINE_STRUCT_CLK(ocp_wp_noc_ick, l3_instr_ick_parent_names, l3_instr_ick_ops);
+
+DEFINE_CLK_GATE(rng_ick, "l4_div_ck", &l4_div_ck, 0x0,
+		OMAP4430_CM_L4SEC_RNG_CLKCTRL, OMAP4430_MODULEMODE_HWCTRL_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(sha2md5_fck, "l3_div_ck", &l3_div_ck, 0x0,
+		OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(sl2if_ick, "dpll_iva_m5x2_ck", &dpll_iva_m5x2_ck, 0x0,
+		OMAP4430_CM_IVAHD_SL2_CLKCTRL, OMAP4430_MODULEMODE_HWCTRL_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus1_fclk_1, "func_24m_clk", &func_24m_clk, 0x0,
+		OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+		OMAP4430_OPTFCLKEN_FCLK1_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus1_fclk_0, "abe_24m_fclk", &abe_24m_fclk, 0x0,
+		OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+		OMAP4430_OPTFCLKEN_FCLK0_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus1_fclk_2, "pad_clks_ck", &pad_clks_ck, 0x0,
+		OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+		OMAP4430_OPTFCLKEN_FCLK2_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus1_slimbus_clk, "slimbus_clk", &slimbus_clk, 0x0,
+		OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+		OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus1_fck, "ocp_abe_iclk", &ocp_abe_iclk, 0x0,
+		OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus2_fclk_1, "per_abe_24m_fclk", &per_abe_24m_fclk, 0x0,
+		OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+		OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus2_fclk_0, "func_24mc_fclk", &func_24mc_fclk, 0x0,
+		OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+		OMAP4430_OPTFCLKEN_PER24MC_GFCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus2_slimbus_clk, "pad_slimbus_core_clks_ck",
+		&pad_slimbus_core_clks_ck, 0x0,
+		OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+		OMAP4430_OPTFCLKEN_SLIMBUS_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(slimbus2_fck, "l4_div_ck", &l4_div_ck, 0x0,
+		OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(smartreflex_core_fck, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck,
+		0x0, OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(smartreflex_iva_fck, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck,
+		0x0, OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(smartreflex_mpu_fck, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck,
+		0x0, OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+static const struct clksel dmt1_clk_mux_sel[] = {
+	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
+	{ .parent = &sys_32k_ck, .rates = div_1_1_rates },
+	{ .parent = NULL },
+};
+
+/* Merged dmt1_clk_mux into timer1 */
+DEFINE_CLK_OMAP_MUX_GATE(timer1_fck, "l4_wkup_clkdm", dmt1_clk_mux_sel,
+			 OMAP4430_CM_WKUP_TIMER1_CLKCTRL, OMAP4430_CLKSEL_MASK,
+			 OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+
+/* Merged cm2_dm10_mux into timer10 */
+DEFINE_CLK_OMAP_MUX_GATE(timer10_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
+			 OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+			 OMAP4430_CLKSEL_MASK,
+			 OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+
+/* Merged cm2_dm11_mux into timer11 */
+DEFINE_CLK_OMAP_MUX_GATE(timer11_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
+			 OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+			 OMAP4430_CLKSEL_MASK,
+			 OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+
+/* Merged cm2_dm2_mux into timer2 */
+DEFINE_CLK_OMAP_MUX_GATE(timer2_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
+			 OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+			 OMAP4430_CLKSEL_MASK,
+			 OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+
+/* Merged cm2_dm3_mux into timer3 */
+DEFINE_CLK_OMAP_MUX_GATE(timer3_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
+			 OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+			 OMAP4430_CLKSEL_MASK,
+			 OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+
+/* Merged cm2_dm4_mux into timer4 */
+DEFINE_CLK_OMAP_MUX_GATE(timer4_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
+			 OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
+			 OMAP4430_CLKSEL_MASK,
+			 OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+
+static const struct clksel timer5_sync_mux_sel[] = {
+	{ .parent = &syc_clk_div_ck, .rates = div_1_0_rates },
+	{ .parent = &sys_32k_ck, .rates = div_1_1_rates },
+	{ .parent = NULL },
+};
+
+static const char *timer5_fck_parents[] = {
+	"syc_clk_div_ck", "sys_32k_ck",
+};
+
+/* Merged timer5_sync_mux into timer5 */
+DEFINE_CLK_OMAP_MUX_GATE(timer5_fck, "abe_clkdm", timer5_sync_mux_sel,
+			 OMAP4430_CM1_ABE_TIMER5_CLKCTRL, OMAP4430_CLKSEL_MASK,
+			 OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 timer5_fck_parents, dmic_fck_ops);
+
+/* Merged timer6_sync_mux into timer6 */
+DEFINE_CLK_OMAP_MUX_GATE(timer6_fck, "abe_clkdm", timer5_sync_mux_sel,
+			 OMAP4430_CM1_ABE_TIMER6_CLKCTRL, OMAP4430_CLKSEL_MASK,
+			 OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 timer5_fck_parents, dmic_fck_ops);
+
+/* Merged timer7_sync_mux into timer7 */
+DEFINE_CLK_OMAP_MUX_GATE(timer7_fck, "abe_clkdm", timer5_sync_mux_sel,
+			 OMAP4430_CM1_ABE_TIMER7_CLKCTRL, OMAP4430_CLKSEL_MASK,
+			 OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 timer5_fck_parents, dmic_fck_ops);
+
+/* Merged timer8_sync_mux into timer8 */
+DEFINE_CLK_OMAP_MUX_GATE(timer8_fck, "abe_clkdm", timer5_sync_mux_sel,
+			 OMAP4430_CM1_ABE_TIMER8_CLKCTRL, OMAP4430_CLKSEL_MASK,
+			 OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 timer5_fck_parents, dmic_fck_ops);
+
+/* Merged cm2_dm9_mux into timer9 */
+DEFINE_CLK_OMAP_MUX_GATE(timer9_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
+			 OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
+			 OMAP4430_CLKSEL_MASK,
+			 OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
+			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
+			 abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+
+DEFINE_CLK_GATE(uart1_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+		OMAP4430_CM_L4PER_UART1_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(uart2_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+		OMAP4430_CM_L4PER_UART2_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(uart3_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+		OMAP4430_CM_L4PER_UART3_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(uart4_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
+		OMAP4430_CM_L4PER_UART4_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+static struct clk usb_host_fs_fck;
+
+static const char *usb_host_fs_fck_parent_names[] = {
+	"func_48mc_fclk",
+};
+
+static const struct clk_ops usb_host_fs_fck_ops = {
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+};
+
+static struct clk_hw_omap usb_host_fs_fck_hw = {
+	.hw = {
+		.clk = &usb_host_fs_fck,
+	},
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_FS_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL_SHIFT,
+	.clkdm_name	= "l3_init_clkdm",
+};
+
+DEFINE_STRUCT_CLK(usb_host_fs_fck, usb_host_fs_fck_parent_names,
+		  usb_host_fs_fck_ops);
+
+static const char *utmi_p1_gfclk_parents[] = {
+	"init_60m_fclk", "xclk60mhsp1_ck",
+};
+
+DEFINE_CLK_MUX(utmi_p1_gfclk, utmi_p1_gfclk_parents, NULL, 0x0,
+	       OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+	       OMAP4430_CLKSEL_UTMI_P1_SHIFT, OMAP4430_CLKSEL_UTMI_P1_WIDTH,
+	       0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_utmi_p1_clk, "utmi_p1_gfclk", &utmi_p1_gfclk, 0x0,
+		OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+		OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT, 0x0, NULL);
+
+static const char *utmi_p2_gfclk_parents[] = {
+	"init_60m_fclk", "xclk60mhsp2_ck",
+};
+
+DEFINE_CLK_MUX(utmi_p2_gfclk, utmi_p2_gfclk_parents, NULL, 0x0,
+	       OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+	       OMAP4430_CLKSEL_UTMI_P2_SHIFT, OMAP4430_CLKSEL_UTMI_P2_WIDTH,
+	       0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_utmi_p2_clk, "utmi_p2_gfclk", &utmi_p2_gfclk, 0x0,
+		OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+		OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_utmi_p3_clk, "init_60m_fclk", &init_60m_fclk, 0x0,
+		OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+		OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_hsic480m_p1_clk, "dpll_usb_m2_ck",
+		&dpll_usb_m2_ck, 0x0,
+		OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+		OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_hsic60m_p1_clk, "init_60m_fclk",
+		&init_60m_fclk, 0x0,
+		OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+		OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_hsic60m_p2_clk, "init_60m_fclk",
+		&init_60m_fclk, 0x0,
+		OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+		OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_hsic480m_p2_clk, "dpll_usb_m2_ck",
+		&dpll_usb_m2_ck, 0x0,
+		OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+		OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_func48mclk, "func_48mc_fclk", &func_48mc_fclk, 0x0,
+		OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+		OMAP4430_OPTFCLKEN_FUNC48MCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_host_hs_fck, "init_60m_fclk", &init_60m_fclk, 0x0,
+		OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+
+static const char *otg_60m_gfclk_parents[] = {
+	"utmi_phy_clkout_ck", "xclk60motg_ck",
+};
+
+DEFINE_CLK_MUX(otg_60m_gfclk, otg_60m_gfclk_parents, NULL, 0x0,
+	       OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL, OMAP4430_CLKSEL_60M_SHIFT,
+	       OMAP4430_CLKSEL_60M_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_otg_hs_xclk, "otg_60m_gfclk", &otg_60m_gfclk, 0x0,
+		OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+		OMAP4430_OPTFCLKEN_XCLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_otg_hs_ick, "l3_div_ck", &l3_div_ck, 0x0,
+		OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_phy_cm_clk32k, "sys_32k_ck", &sys_32k_ck, 0x0,
+		OMAP4430_CM_ALWON_USBPHY_CLKCTRL,
+		OMAP4430_OPTFCLKEN_CLK32K_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_tll_hs_usb_ch2_clk, "init_60m_fclk", &init_60m_fclk, 0x0,
+		OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+		OMAP4430_OPTFCLKEN_USB_CH2_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_tll_hs_usb_ch0_clk, "init_60m_fclk", &init_60m_fclk, 0x0,
+		OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+		OMAP4430_OPTFCLKEN_USB_CH0_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_tll_hs_usb_ch1_clk, "init_60m_fclk", &init_60m_fclk, 0x0,
+		OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+		OMAP4430_OPTFCLKEN_USB_CH1_CLK_SHIFT, 0x0, NULL);
+
+DEFINE_CLK_GATE(usb_tll_hs_ick, "l4_div_ck", &l4_div_ck, 0x0,
+		OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+
+static const struct clk_div_table usim_ck_rates[] = {
+	{ .div = 14, .val = 0 },
+	{ .div = 18, .val = 1 },
+	{ .div = 0 },
+};
+DEFINE_CLK_DIVIDER_TABLE(usim_ck, "dpll_per_m4x2_ck", &dpll_per_m4x2_ck, 0x0,
+			 OMAP4430_CM_WKUP_USIM_CLKCTRL,
+			 OMAP4430_CLKSEL_DIV_SHIFT, OMAP4430_CLKSEL_DIV_WIDTH,
+			 0x0, usim_ck_rates, NULL);
+
+DEFINE_CLK_GATE(usim_fclk, "usim_ck", &usim_ck, 0x0,
+		OMAP4430_CM_WKUP_USIM_CLKCTRL, OMAP4430_OPTFCLKEN_FCLK_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(usim_fck, "sys_32k_ck", &sys_32k_ck, 0x0,
+		OMAP4430_CM_WKUP_USIM_CLKCTRL, OMAP4430_MODULEMODE_HWCTRL_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(wd_timer2_fck, "sys_32k_ck", &sys_32k_ck, 0x0,
+		OMAP4430_CM_WKUP_WDT2_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
+		0x0, NULL);
+
+DEFINE_CLK_GATE(wd_timer3_fck, "sys_32k_ck", &sys_32k_ck, 0x0,
+		OMAP4430_CM1_ABE_WDT3_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
+		0x0, NULL);
+
+/* Remaining optional clocks */
+static const char *pmd_stm_clock_mux_ck_parents[] = {
+	"sys_clkin_ck", "dpll_core_m6x2_ck", "tie_low_clock_ck",
+};
+
+DEFINE_CLK_MUX(pmd_stm_clock_mux_ck, pmd_stm_clock_mux_ck_parents, NULL, 0x0,
+	       OMAP4430_CM_EMU_DEBUGSS_CLKCTRL, OMAP4430_PMD_STM_MUX_CTRL_SHIFT,
+	       OMAP4430_PMD_STM_MUX_CTRL_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_MUX(pmd_trace_clk_mux_ck, pmd_stm_clock_mux_ck_parents, NULL, 0x0,
+	       OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
+	       OMAP4430_PMD_TRACE_MUX_CTRL_SHIFT,
+	       OMAP4430_PMD_TRACE_MUX_CTRL_WIDTH, 0x0, NULL);
+
+DEFINE_CLK_DIVIDER(stm_clk_div_ck, "pmd_stm_clock_mux_ck",
+		   &pmd_stm_clock_mux_ck, 0x0, OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
+		   OMAP4430_CLKSEL_PMD_STM_CLK_SHIFT,
+		   OMAP4430_CLKSEL_PMD_STM_CLK_WIDTH, CLK_DIVIDER_POWER_OF_TWO,
+		   NULL);
+
+static const char *trace_clk_div_ck_parents[] = {
+	"pmd_trace_clk_mux_ck",
+};
+
+static const struct clksel trace_clk_div_div[] = {
+	{ .parent = &pmd_trace_clk_mux_ck, .rates = div3_1to4_rates },
+	{ .parent = NULL },
+};
+
+static struct clk trace_clk_div_ck;
+
+static const struct clk_ops trace_clk_div_ck_ops = {
+	.recalc_rate	= &omap2_clksel_recalc,
+	.set_rate	= &omap2_clksel_set_rate,
+	.round_rate	= &omap2_clksel_round_rate,
+	.init		= &omap2_init_clk_clkdm,
+	.enable		= &omap2_clkops_enable_clkdm,
+	.disable	= &omap2_clkops_disable_clkdm,
+};
+
+static struct clk_hw_omap trace_clk_div_ck_hw = {
+	.hw = {
+		.clk = &trace_clk_div_ck,
+	},
+	.clkdm_name	= "emu_sys_clkdm",
+	.clksel		= trace_clk_div_div,
+	.clksel_reg	= OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK,
+};
+
+DEFINE_STRUCT_CLK(trace_clk_div_ck, trace_clk_div_ck_parents,
+		  trace_clk_div_ck_ops);
+
+/* SCRM aux clk nodes */
+
+static const struct clksel auxclk_src_sel[] = {
+	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
+	{ .parent = &dpll_core_m3x2_ck, .rates = div_1_1_rates },
+	{ .parent = &dpll_per_m3x2_ck, .rates = div_1_2_rates },
+	{ .parent = NULL },
+};
+
+static const char *auxclk_src_ck_parents[] = {
+	"sys_clkin_ck", "dpll_core_m3x2_ck", "dpll_per_m3x2_ck",
+};
+
+static const struct clk_ops auxclk_src_ck_ops = {
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+	.is_enabled	= &omap2_dflt_clk_is_enabled,
+	.recalc_rate	= &omap2_clksel_recalc,
+	.get_parent	= &omap2_clksel_find_parent_index,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(auxclk0_src_ck, NULL, auxclk_src_sel,
+			 OMAP4_SCRM_AUXCLK0, OMAP4_SRCSELECT_MASK,
+			 OMAP4_SCRM_AUXCLK0, OMAP4_ENABLE_SHIFT, NULL,
+			 auxclk_src_ck_parents, auxclk_src_ck_ops);
+
+DEFINE_CLK_DIVIDER(auxclk0_ck, "auxclk0_src_ck", &auxclk0_src_ck, 0x0,
+		   OMAP4_SCRM_AUXCLK0, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
+		   0x0, NULL);
+
+DEFINE_CLK_OMAP_MUX_GATE(auxclk1_src_ck, NULL, auxclk_src_sel,
+			 OMAP4_SCRM_AUXCLK1, OMAP4_SRCSELECT_MASK,
+			 OMAP4_SCRM_AUXCLK1, OMAP4_ENABLE_SHIFT, NULL,
+			 auxclk_src_ck_parents, auxclk_src_ck_ops);
+
+DEFINE_CLK_DIVIDER(auxclk1_ck, "auxclk1_src_ck", &auxclk1_src_ck, 0x0,
+		   OMAP4_SCRM_AUXCLK1, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
+		   0x0, NULL);
+
+DEFINE_CLK_OMAP_MUX_GATE(auxclk2_src_ck, NULL, auxclk_src_sel,
+			 OMAP4_SCRM_AUXCLK2, OMAP4_SRCSELECT_MASK,
+			 OMAP4_SCRM_AUXCLK2, OMAP4_ENABLE_SHIFT, NULL,
+			 auxclk_src_ck_parents, auxclk_src_ck_ops);
+
+DEFINE_CLK_DIVIDER(auxclk2_ck, "auxclk2_src_ck", &auxclk2_src_ck, 0x0,
+		   OMAP4_SCRM_AUXCLK2, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
+		   0x0, NULL);
+
+DEFINE_CLK_OMAP_MUX_GATE(auxclk3_src_ck, NULL, auxclk_src_sel,
+			 OMAP4_SCRM_AUXCLK3, OMAP4_SRCSELECT_MASK,
+			 OMAP4_SCRM_AUXCLK3, OMAP4_ENABLE_SHIFT, NULL,
+			 auxclk_src_ck_parents, auxclk_src_ck_ops);
+
+DEFINE_CLK_DIVIDER(auxclk3_ck, "auxclk3_src_ck", &auxclk3_src_ck, 0x0,
+		   OMAP4_SCRM_AUXCLK3, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
+		   0x0, NULL);
+
+DEFINE_CLK_OMAP_MUX_GATE(auxclk4_src_ck, NULL, auxclk_src_sel,
+			 OMAP4_SCRM_AUXCLK4, OMAP4_SRCSELECT_MASK,
+			 OMAP4_SCRM_AUXCLK4, OMAP4_ENABLE_SHIFT, NULL,
+			 auxclk_src_ck_parents, auxclk_src_ck_ops);
+
+DEFINE_CLK_DIVIDER(auxclk4_ck, "auxclk4_src_ck", &auxclk4_src_ck, 0x0,
+		   OMAP4_SCRM_AUXCLK4, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
+		   0x0, NULL);
+
+DEFINE_CLK_OMAP_MUX_GATE(auxclk5_src_ck, NULL, auxclk_src_sel,
+			 OMAP4_SCRM_AUXCLK5, OMAP4_SRCSELECT_MASK,
+			 OMAP4_SCRM_AUXCLK5, OMAP4_ENABLE_SHIFT, NULL,
+			 auxclk_src_ck_parents, auxclk_src_ck_ops);
+
+DEFINE_CLK_DIVIDER(auxclk5_ck, "auxclk5_src_ck", &auxclk5_src_ck, 0x0,
+		   OMAP4_SCRM_AUXCLK5, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
+		   0x0, NULL);
+
+static const char *auxclkreq_ck_parents[] = {
+	"auxclk0_ck", "auxclk1_ck", "auxclk2_ck", "auxclk3_ck", "auxclk4_ck",
+	"auxclk5_ck",
+};
+
+DEFINE_CLK_MUX(auxclkreq0_ck, auxclkreq_ck_parents, NULL, 0x0,
+	       OMAP4_SCRM_AUXCLKREQ0, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
+	       0x0, NULL);
+
+DEFINE_CLK_MUX(auxclkreq1_ck, auxclkreq_ck_parents, NULL, 0x0,
+	       OMAP4_SCRM_AUXCLKREQ1, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
+	       0x0, NULL);
+
+DEFINE_CLK_MUX(auxclkreq2_ck, auxclkreq_ck_parents, NULL, 0x0,
+	       OMAP4_SCRM_AUXCLKREQ2, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
+	       0x0, NULL);
+
+DEFINE_CLK_MUX(auxclkreq3_ck, auxclkreq_ck_parents, NULL, 0x0,
+	       OMAP4_SCRM_AUXCLKREQ3, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
+	       0x0, NULL);
+
+DEFINE_CLK_MUX(auxclkreq4_ck, auxclkreq_ck_parents, NULL, 0x0,
+	       OMAP4_SCRM_AUXCLKREQ4, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
+	       0x0, NULL);
+
+DEFINE_CLK_MUX(auxclkreq5_ck, auxclkreq_ck_parents, NULL, 0x0,
+	       OMAP4_SCRM_AUXCLKREQ5, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
+	       0x0, NULL);
+
+/*
+ * clkdev
+ */
+
+static struct omap_clk omap44xx_clks[] = {
+	CLK(NULL,	"extalt_clkin_ck",		&extalt_clkin_ck,	CK_443X),
+	CLK(NULL,	"pad_clks_src_ck",		&pad_clks_src_ck,	CK_443X),
+	CLK(NULL,	"pad_clks_ck",			&pad_clks_ck,	CK_443X),
+	CLK(NULL,	"pad_slimbus_core_clks_ck",	&pad_slimbus_core_clks_ck,	CK_443X),
+	CLK(NULL,	"secure_32k_clk_src_ck",	&secure_32k_clk_src_ck,	CK_443X),
+	CLK(NULL,	"slimbus_src_clk",		&slimbus_src_clk,	CK_443X),
+	CLK(NULL,	"slimbus_clk",			&slimbus_clk,	CK_443X),
+	CLK(NULL,	"sys_32k_ck",			&sys_32k_ck,	CK_443X),
+	CLK(NULL,	"virt_12000000_ck",		&virt_12000000_ck,	CK_443X),
+	CLK(NULL,	"virt_13000000_ck",		&virt_13000000_ck,	CK_443X),
+	CLK(NULL,	"virt_16800000_ck",		&virt_16800000_ck,	CK_443X),
+	CLK(NULL,	"virt_19200000_ck",		&virt_19200000_ck,	CK_443X),
+	CLK(NULL,	"virt_26000000_ck",		&virt_26000000_ck,	CK_443X),
+	CLK(NULL,	"virt_27000000_ck",		&virt_27000000_ck,	CK_443X),
+	CLK(NULL,	"virt_38400000_ck",		&virt_38400000_ck,	CK_443X),
+	CLK(NULL,	"sys_clkin_ck",			&sys_clkin_ck,	CK_443X),
+	CLK(NULL,	"tie_low_clock_ck",		&tie_low_clock_ck,	CK_443X),
+	CLK(NULL,	"utmi_phy_clkout_ck",		&utmi_phy_clkout_ck,	CK_443X),
+	CLK(NULL,	"xclk60mhsp1_ck",		&xclk60mhsp1_ck,	CK_443X),
+	CLK(NULL,	"xclk60mhsp2_ck",		&xclk60mhsp2_ck,	CK_443X),
+	CLK(NULL,	"xclk60motg_ck",		&xclk60motg_ck,	CK_443X),
+	CLK(NULL,	"abe_dpll_bypass_clk_mux_ck",	&abe_dpll_bypass_clk_mux_ck,	CK_443X),
+	CLK(NULL,	"abe_dpll_refclk_mux_ck",	&abe_dpll_refclk_mux_ck,	CK_443X),
+	CLK(NULL,	"dpll_abe_ck",			&dpll_abe_ck,	CK_443X),
+	CLK(NULL,	"dpll_abe_x2_ck",		&dpll_abe_x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_abe_m2x2_ck",		&dpll_abe_m2x2_ck,	CK_443X),
+	CLK(NULL,	"abe_24m_fclk",			&abe_24m_fclk,	CK_443X),
+	CLK(NULL,	"abe_clk",			&abe_clk,	CK_443X),
+	CLK(NULL,	"aess_fclk",			&aess_fclk,	CK_443X),
+	CLK(NULL,	"dpll_abe_m3x2_ck",		&dpll_abe_m3x2_ck,	CK_443X),
+	CLK(NULL,	"core_hsd_byp_clk_mux_ck",	&core_hsd_byp_clk_mux_ck,	CK_443X),
+	CLK(NULL,	"dpll_core_ck",			&dpll_core_ck,	CK_443X),
+	CLK(NULL,	"dpll_core_x2_ck",		&dpll_core_x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_core_m6x2_ck",		&dpll_core_m6x2_ck,	CK_443X),
+	CLK(NULL,	"dbgclk_mux_ck",		&dbgclk_mux_ck,	CK_443X),
+	CLK(NULL,	"dpll_core_m2_ck",		&dpll_core_m2_ck,	CK_443X),
+	CLK(NULL,	"ddrphy_ck",			&ddrphy_ck,	CK_443X),
+	CLK(NULL,	"dpll_core_m5x2_ck",		&dpll_core_m5x2_ck,	CK_443X),
+	CLK(NULL,	"div_core_ck",			&div_core_ck,	CK_443X),
+	CLK(NULL,	"div_iva_hs_clk",		&div_iva_hs_clk,	CK_443X),
+	CLK(NULL,	"div_mpu_hs_clk",		&div_mpu_hs_clk,	CK_443X),
+	CLK(NULL,	"dpll_core_m4x2_ck",		&dpll_core_m4x2_ck,	CK_443X),
+	CLK(NULL,	"dll_clk_div_ck",		&dll_clk_div_ck,	CK_443X),
+	CLK(NULL,	"dpll_abe_m2_ck",		&dpll_abe_m2_ck,	CK_443X),
+	CLK(NULL,	"dpll_core_m3x2_ck",		&dpll_core_m3x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_core_m7x2_ck",		&dpll_core_m7x2_ck,	CK_443X),
+	CLK(NULL,	"iva_hsd_byp_clk_mux_ck",	&iva_hsd_byp_clk_mux_ck,	CK_443X),
+	CLK(NULL,	"dpll_iva_ck",			&dpll_iva_ck,	CK_443X),
+	CLK(NULL,	"dpll_iva_x2_ck",		&dpll_iva_x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_iva_m4x2_ck",		&dpll_iva_m4x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_iva_m5x2_ck",		&dpll_iva_m5x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_mpu_ck",			&dpll_mpu_ck,	CK_443X),
+	CLK(NULL,	"dpll_mpu_m2_ck",		&dpll_mpu_m2_ck,	CK_443X),
+	CLK(NULL,	"per_hs_clk_div_ck",		&per_hs_clk_div_ck,	CK_443X),
+	CLK(NULL,	"per_hsd_byp_clk_mux_ck",	&per_hsd_byp_clk_mux_ck,	CK_443X),
+	CLK(NULL,	"dpll_per_ck",			&dpll_per_ck,	CK_443X),
+	CLK(NULL,	"dpll_per_m2_ck",		&dpll_per_m2_ck,	CK_443X),
+	CLK(NULL,	"dpll_per_x2_ck",		&dpll_per_x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_per_m2x2_ck",		&dpll_per_m2x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_per_m3x2_ck",		&dpll_per_m3x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_per_m4x2_ck",		&dpll_per_m4x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_per_m5x2_ck",		&dpll_per_m5x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_per_m6x2_ck",		&dpll_per_m6x2_ck,	CK_443X),
+	CLK(NULL,	"dpll_per_m7x2_ck",		&dpll_per_m7x2_ck,	CK_443X),
+	CLK(NULL,	"usb_hs_clk_div_ck",		&usb_hs_clk_div_ck,	CK_443X),
+	CLK(NULL,	"dpll_usb_ck",			&dpll_usb_ck,	CK_443X),
+	CLK(NULL,	"dpll_usb_clkdcoldo_ck",	&dpll_usb_clkdcoldo_ck,	CK_443X),
+	CLK(NULL,	"dpll_usb_m2_ck",		&dpll_usb_m2_ck,	CK_443X),
+	CLK(NULL,	"ducati_clk_mux_ck",		&ducati_clk_mux_ck,	CK_443X),
+	CLK(NULL,	"func_12m_fclk",		&func_12m_fclk,	CK_443X),
+	CLK(NULL,	"func_24m_clk",			&func_24m_clk,	CK_443X),
+	CLK(NULL,	"func_24mc_fclk",		&func_24mc_fclk,	CK_443X),
+	CLK(NULL,	"func_48m_fclk",		&func_48m_fclk,	CK_443X),
+	CLK(NULL,	"func_48mc_fclk",		&func_48mc_fclk,	CK_443X),
+	CLK(NULL,	"func_64m_fclk",		&func_64m_fclk,	CK_443X),
+	CLK(NULL,	"func_96m_fclk",		&func_96m_fclk,	CK_443X),
+	CLK(NULL,	"init_60m_fclk",		&init_60m_fclk,	CK_443X),
+	CLK(NULL,	"l3_div_ck",			&l3_div_ck,	CK_443X),
+	CLK(NULL,	"l4_div_ck",			&l4_div_ck,	CK_443X),
+	CLK(NULL,	"lp_clk_div_ck",		&lp_clk_div_ck,	CK_443X),
+	CLK(NULL,	"l4_wkup_clk_mux_ck",		&l4_wkup_clk_mux_ck,	CK_443X),
+	CLK("smp_twd",	NULL,				&mpu_periphclk,	CK_443X),
+	CLK(NULL,	"ocp_abe_iclk",			&ocp_abe_iclk,	CK_443X),
+	CLK(NULL,	"per_abe_24m_fclk",		&per_abe_24m_fclk,	CK_443X),
+	CLK(NULL,	"per_abe_nc_fclk",		&per_abe_nc_fclk,	CK_443X),
+	CLK(NULL,	"syc_clk_div_ck",		&syc_clk_div_ck,	CK_443X),
+	CLK(NULL,	"aes1_fck",			&aes1_fck,	CK_443X),
+	CLK(NULL,	"aes2_fck",			&aes2_fck,	CK_443X),
+	CLK(NULL,	"aess_fck",			&aess_fck,	CK_443X),
+	CLK(NULL,	"bandgap_fclk",			&bandgap_fclk,	CK_443X),
+	CLK(NULL,	"div_ts_ck",			&div_ts_ck,	CK_446X),
+	CLK(NULL,	"bandgap_ts_fclk",		&bandgap_ts_fclk,	CK_446X),
+	CLK(NULL,	"des3des_fck",			&des3des_fck,	CK_443X),
+	CLK(NULL,	"dmic_sync_mux_ck",		&dmic_sync_mux_ck,	CK_443X),
+	CLK(NULL,	"dmic_fck",			&dmic_fck,	CK_443X),
+	CLK(NULL,	"dsp_fck",			&dsp_fck,	CK_443X),
+	CLK(NULL,	"dss_sys_clk",			&dss_sys_clk,	CK_443X),
+	CLK(NULL,	"dss_tv_clk",			&dss_tv_clk,	CK_443X),
+	CLK(NULL,	"dss_dss_clk",			&dss_dss_clk,	CK_443X),
+	CLK(NULL,	"dss_48mhz_clk",		&dss_48mhz_clk,	CK_443X),
+	CLK(NULL,	"dss_fck",			&dss_fck,	CK_443X),
+	CLK("omapdss_dss",	"ick",			&dss_fck,	CK_443X),
+	CLK(NULL,	"efuse_ctrl_cust_fck",		&efuse_ctrl_cust_fck,	CK_443X),
+	CLK(NULL,	"emif1_fck",			&emif1_fck,	CK_443X),
+	CLK(NULL,	"emif2_fck",			&emif2_fck,	CK_443X),
+	CLK(NULL,	"fdif_fck",			&fdif_fck,	CK_443X),
+	CLK(NULL,	"fpka_fck",			&fpka_fck,	CK_443X),
+	CLK(NULL,	"gpio1_dbclk",			&gpio1_dbclk,	CK_443X),
+	CLK(NULL,	"gpio1_ick",			&gpio1_ick,	CK_443X),
+	CLK(NULL,	"gpio2_dbclk",			&gpio2_dbclk,	CK_443X),
+	CLK(NULL,	"gpio2_ick",			&gpio2_ick,	CK_443X),
+	CLK(NULL,	"gpio3_dbclk",			&gpio3_dbclk,	CK_443X),
+	CLK(NULL,	"gpio3_ick",			&gpio3_ick,	CK_443X),
+	CLK(NULL,	"gpio4_dbclk",			&gpio4_dbclk,	CK_443X),
+	CLK(NULL,	"gpio4_ick",			&gpio4_ick,	CK_443X),
+	CLK(NULL,	"gpio5_dbclk",			&gpio5_dbclk,	CK_443X),
+	CLK(NULL,	"gpio5_ick",			&gpio5_ick,	CK_443X),
+	CLK(NULL,	"gpio6_dbclk",			&gpio6_dbclk,	CK_443X),
+	CLK(NULL,	"gpio6_ick",			&gpio6_ick,	CK_443X),
+	CLK(NULL,	"gpmc_ick",			&gpmc_ick,	CK_443X),
+	CLK(NULL,	"gpu_fck",			&gpu_fck,	CK_443X),
+	CLK(NULL,	"hdq1w_fck",			&hdq1w_fck,	CK_443X),
+	CLK(NULL,	"hsi_fck",			&hsi_fck,	CK_443X),
+	CLK(NULL,	"i2c1_fck",			&i2c1_fck,	CK_443X),
+	CLK(NULL,	"i2c2_fck",			&i2c2_fck,	CK_443X),
+	CLK(NULL,	"i2c3_fck",			&i2c3_fck,	CK_443X),
+	CLK(NULL,	"i2c4_fck",			&i2c4_fck,	CK_443X),
+	CLK(NULL,	"ipu_fck",			&ipu_fck,	CK_443X),
+	CLK(NULL,	"iss_ctrlclk",			&iss_ctrlclk,	CK_443X),
+	CLK(NULL,	"iss_fck",			&iss_fck,	CK_443X),
+	CLK(NULL,	"iva_fck",			&iva_fck,	CK_443X),
+	CLK(NULL,	"kbd_fck",			&kbd_fck,	CK_443X),
+	CLK(NULL,	"l3_instr_ick",			&l3_instr_ick,	CK_443X),
+	CLK(NULL,	"l3_main_3_ick",		&l3_main_3_ick,	CK_443X),
+	CLK(NULL,	"mcasp_sync_mux_ck",		&mcasp_sync_mux_ck,	CK_443X),
+	CLK(NULL,	"mcasp_fck",			&mcasp_fck,	CK_443X),
+	CLK(NULL,	"mcbsp1_sync_mux_ck",		&mcbsp1_sync_mux_ck,	CK_443X),
+	CLK(NULL,	"mcbsp1_fck",			&mcbsp1_fck,	CK_443X),
+	CLK(NULL,	"mcbsp2_sync_mux_ck",		&mcbsp2_sync_mux_ck,	CK_443X),
+	CLK(NULL,	"mcbsp2_fck",			&mcbsp2_fck,	CK_443X),
+	CLK(NULL,	"mcbsp3_sync_mux_ck",		&mcbsp3_sync_mux_ck,	CK_443X),
+	CLK(NULL,	"mcbsp3_fck",			&mcbsp3_fck,	CK_443X),
+	CLK(NULL,	"mcbsp4_sync_mux_ck",		&mcbsp4_sync_mux_ck,	CK_443X),
+	CLK(NULL,	"mcbsp4_fck",			&mcbsp4_fck,	CK_443X),
+	CLK(NULL,	"mcpdm_fck",			&mcpdm_fck,	CK_443X),
+	CLK(NULL,	"mcspi1_fck",			&mcspi1_fck,	CK_443X),
+	CLK(NULL,	"mcspi2_fck",			&mcspi2_fck,	CK_443X),
+	CLK(NULL,	"mcspi3_fck",			&mcspi3_fck,	CK_443X),
+	CLK(NULL,	"mcspi4_fck",			&mcspi4_fck,	CK_443X),
+	CLK(NULL,	"mmc1_fck",			&mmc1_fck,	CK_443X),
+	CLK(NULL,	"mmc2_fck",			&mmc2_fck,	CK_443X),
+	CLK(NULL,	"mmc3_fck",			&mmc3_fck,	CK_443X),
+	CLK(NULL,	"mmc4_fck",			&mmc4_fck,	CK_443X),
+	CLK(NULL,	"mmc5_fck",			&mmc5_fck,	CK_443X),
+	CLK(NULL,	"ocp2scp_usb_phy_phy_48m",	&ocp2scp_usb_phy_phy_48m,	CK_443X),
+	CLK(NULL,	"ocp2scp_usb_phy_ick",		&ocp2scp_usb_phy_ick,	CK_443X),
+	CLK(NULL,	"ocp_wp_noc_ick",		&ocp_wp_noc_ick,	CK_443X),
+	CLK(NULL,	"rng_ick",			&rng_ick,	CK_443X),
+	CLK("omap_rng",	"ick",				&rng_ick,	CK_443X),
+	CLK(NULL,	"sha2md5_fck",			&sha2md5_fck,	CK_443X),
+	CLK(NULL,	"sl2if_ick",			&sl2if_ick,	CK_443X),
+	CLK(NULL,	"slimbus1_fclk_1",		&slimbus1_fclk_1,	CK_443X),
+	CLK(NULL,	"slimbus1_fclk_0",		&slimbus1_fclk_0,	CK_443X),
+	CLK(NULL,	"slimbus1_fclk_2",		&slimbus1_fclk_2,	CK_443X),
+	CLK(NULL,	"slimbus1_slimbus_clk",		&slimbus1_slimbus_clk,	CK_443X),
+	CLK(NULL,	"slimbus1_fck",			&slimbus1_fck,	CK_443X),
+	CLK(NULL,	"slimbus2_fclk_1",		&slimbus2_fclk_1,	CK_443X),
+	CLK(NULL,	"slimbus2_fclk_0",		&slimbus2_fclk_0,	CK_443X),
+	CLK(NULL,	"slimbus2_slimbus_clk",		&slimbus2_slimbus_clk,	CK_443X),
+	CLK(NULL,	"slimbus2_fck",			&slimbus2_fck,	CK_443X),
+	CLK(NULL,	"smartreflex_core_fck",		&smartreflex_core_fck,	CK_443X),
+	CLK(NULL,	"smartreflex_iva_fck",		&smartreflex_iva_fck,	CK_443X),
+	CLK(NULL,	"smartreflex_mpu_fck",		&smartreflex_mpu_fck,	CK_443X),
+	CLK(NULL,	"timer1_fck",			&timer1_fck,	CK_443X),
+	CLK(NULL,	"timer10_fck",			&timer10_fck,	CK_443X),
+	CLK(NULL,	"timer11_fck",			&timer11_fck,	CK_443X),
+	CLK(NULL,	"timer2_fck",			&timer2_fck,	CK_443X),
+	CLK(NULL,	"timer3_fck",			&timer3_fck,	CK_443X),
+	CLK(NULL,	"timer4_fck",			&timer4_fck,	CK_443X),
+	CLK(NULL,	"timer5_fck",			&timer5_fck,	CK_443X),
+	CLK(NULL,	"timer6_fck",			&timer6_fck,	CK_443X),
+	CLK(NULL,	"timer7_fck",			&timer7_fck,	CK_443X),
+	CLK(NULL,	"timer8_fck",			&timer8_fck,	CK_443X),
+	CLK(NULL,	"timer9_fck",			&timer9_fck,	CK_443X),
+	CLK(NULL,	"uart1_fck",			&uart1_fck,	CK_443X),
+	CLK(NULL,	"uart2_fck",			&uart2_fck,	CK_443X),
+	CLK(NULL,	"uart3_fck",			&uart3_fck,	CK_443X),
+	CLK(NULL,	"uart4_fck",			&uart4_fck,	CK_443X),
+	CLK(NULL,	"usb_host_fs_fck",		&usb_host_fs_fck,	CK_443X),
+	CLK("usbhs_omap",	"fs_fck",		&usb_host_fs_fck,	CK_443X),
+	CLK(NULL,	"utmi_p1_gfclk",		&utmi_p1_gfclk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_utmi_p1_clk",	&usb_host_hs_utmi_p1_clk,	CK_443X),
+	CLK(NULL,	"utmi_p2_gfclk",		&utmi_p2_gfclk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_utmi_p2_clk",	&usb_host_hs_utmi_p2_clk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_utmi_p3_clk",	&usb_host_hs_utmi_p3_clk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_hsic480m_p1_clk",	&usb_host_hs_hsic480m_p1_clk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_hsic60m_p1_clk",	&usb_host_hs_hsic60m_p1_clk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_hsic60m_p2_clk",	&usb_host_hs_hsic60m_p2_clk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_hsic480m_p2_clk",	&usb_host_hs_hsic480m_p2_clk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_func48mclk",	&usb_host_hs_func48mclk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_fck",		&usb_host_hs_fck,	CK_443X),
+	CLK("usbhs_omap",	"hs_fck",		&usb_host_hs_fck,	CK_443X),
+	CLK(NULL,	"otg_60m_gfclk",		&otg_60m_gfclk,	CK_443X),
+	CLK(NULL,	"usb_otg_hs_xclk",		&usb_otg_hs_xclk,	CK_443X),
+	CLK(NULL,	"usb_otg_hs_ick",		&usb_otg_hs_ick,	CK_443X),
+	CLK("musb-omap2430",	"ick",			&usb_otg_hs_ick,	CK_443X),
+	CLK(NULL,	"usb_phy_cm_clk32k",		&usb_phy_cm_clk32k,	CK_443X),
+	CLK(NULL,	"usb_tll_hs_usb_ch2_clk",	&usb_tll_hs_usb_ch2_clk,	CK_443X),
+	CLK(NULL,	"usb_tll_hs_usb_ch0_clk",	&usb_tll_hs_usb_ch0_clk,	CK_443X),
+	CLK(NULL,	"usb_tll_hs_usb_ch1_clk",	&usb_tll_hs_usb_ch1_clk,	CK_443X),
+	CLK(NULL,	"usb_tll_hs_ick",		&usb_tll_hs_ick,	CK_443X),
+	CLK("usbhs_omap",	"usbtll_ick",		&usb_tll_hs_ick,	CK_443X),
+	CLK("usbhs_tll",	"usbtll_ick",		&usb_tll_hs_ick,	CK_443X),
+	CLK(NULL,	"usim_ck",			&usim_ck,	CK_443X),
+	CLK(NULL,	"usim_fclk",			&usim_fclk,	CK_443X),
+	CLK(NULL,	"usim_fck",			&usim_fck,	CK_443X),
+	CLK(NULL,	"wd_timer2_fck",		&wd_timer2_fck,	CK_443X),
+	CLK(NULL,	"wd_timer3_fck",		&wd_timer3_fck,	CK_443X),
+	CLK(NULL,	"pmd_stm_clock_mux_ck",		&pmd_stm_clock_mux_ck,	CK_443X),
+	CLK(NULL,	"pmd_trace_clk_mux_ck",		&pmd_trace_clk_mux_ck,	CK_443X),
+	CLK(NULL,	"stm_clk_div_ck",		&stm_clk_div_ck,	CK_443X),
+	CLK(NULL,	"trace_clk_div_ck",		&trace_clk_div_ck,	CK_443X),
+	CLK(NULL,	"auxclk0_src_ck",		&auxclk0_src_ck,	CK_443X),
+	CLK(NULL,	"auxclk0_ck",			&auxclk0_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq0_ck",		&auxclkreq0_ck,	CK_443X),
+	CLK(NULL,	"auxclk1_src_ck",		&auxclk1_src_ck,	CK_443X),
+	CLK(NULL,	"auxclk1_ck",			&auxclk1_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq1_ck",		&auxclkreq1_ck,	CK_443X),
+	CLK(NULL,	"auxclk2_src_ck",		&auxclk2_src_ck,	CK_443X),
+	CLK(NULL,	"auxclk2_ck",			&auxclk2_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq2_ck",		&auxclkreq2_ck,	CK_443X),
+	CLK(NULL,	"auxclk3_src_ck",		&auxclk3_src_ck,	CK_443X),
+	CLK(NULL,	"auxclk3_ck",			&auxclk3_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq3_ck",		&auxclkreq3_ck,	CK_443X),
+	CLK(NULL,	"auxclk4_src_ck",		&auxclk4_src_ck,	CK_443X),
+	CLK(NULL,	"auxclk4_ck",			&auxclk4_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq4_ck",		&auxclkreq4_ck,	CK_443X),
+	CLK(NULL,	"auxclk5_src_ck",		&auxclk5_src_ck,	CK_443X),
+	CLK(NULL,	"auxclk5_ck",			&auxclk5_ck,	CK_443X),
+	CLK(NULL,	"auxclkreq5_ck",		&auxclkreq5_ck,	CK_443X),
+	CLK("omap-gpmc",	"fck",			&dummy_ck,	CK_443X),
+	CLK("omap_i2c.1",	"ick",			&dummy_ck,	CK_443X),
+	CLK("omap_i2c.2",	"ick",			&dummy_ck,	CK_443X),
+	CLK("omap_i2c.3",	"ick",			&dummy_ck,	CK_443X),
+	CLK("omap_i2c.4",	"ick",			&dummy_ck,	CK_443X),
+	CLK(NULL,	"mailboxes_ick",		&dummy_ck,	CK_443X),
+	CLK("omap_hsmmc.0",	"ick",			&dummy_ck,	CK_443X),
+	CLK("omap_hsmmc.1",	"ick",			&dummy_ck,	CK_443X),
+	CLK("omap_hsmmc.2",	"ick",			&dummy_ck,	CK_443X),
+	CLK("omap_hsmmc.3",	"ick",			&dummy_ck,	CK_443X),
+	CLK("omap_hsmmc.4",	"ick",			&dummy_ck,	CK_443X),
+	CLK("omap-mcbsp.1",	"ick",			&dummy_ck,	CK_443X),
+	CLK("omap-mcbsp.2",	"ick",			&dummy_ck,	CK_443X),
+	CLK("omap-mcbsp.3",	"ick",			&dummy_ck,	CK_443X),
+	CLK("omap-mcbsp.4",	"ick",			&dummy_ck,	CK_443X),
+	CLK("omap2_mcspi.1",	"ick",			&dummy_ck,	CK_443X),
+	CLK("omap2_mcspi.2",	"ick",			&dummy_ck,	CK_443X),
+	CLK("omap2_mcspi.3",	"ick",			&dummy_ck,	CK_443X),
+	CLK("omap2_mcspi.4",	"ick",			&dummy_ck,	CK_443X),
+	CLK(NULL,	"uart1_ick",			&dummy_ck,	CK_443X),
+	CLK(NULL,	"uart2_ick",			&dummy_ck,	CK_443X),
+	CLK(NULL,	"uart3_ick",			&dummy_ck,	CK_443X),
+	CLK(NULL,	"uart4_ick",			&dummy_ck,	CK_443X),
+	CLK("usbhs_omap",	"usbhost_ick",		&dummy_ck,		CK_443X),
+	CLK("usbhs_omap",	"usbtll_fck",		&dummy_ck,	CK_443X),
+	CLK("usbhs_tll",	"usbtll_fck",		&dummy_ck,	CK_443X),
+	CLK("omap_wdt",	"ick",				&dummy_ck,	CK_443X),
+	CLK(NULL,	"timer_32k_ck",	&sys_32k_ck,	CK_443X),
+	/* TODO: Remove "omap_timer.X" aliases once DT migration is complete */
+	CLK("omap_timer.1",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.2",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.3",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.4",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.9",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.10",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.11",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.5",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("omap_timer.6",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("omap_timer.7",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("omap_timer.8",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("4a318000.timer",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("48032000.timer",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("48034000.timer",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("48036000.timer",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("4803e000.timer",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("48086000.timer",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("48088000.timer",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("49038000.timer",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("4903a000.timer",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("4903c000.timer",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("4903e000.timer",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK(NULL,	"cpufreq_ck",	&dpll_mpu_ck,	CK_443X),
+};
+
+static const char *enable_init_clks[] = {
+	"emif1_fck",
+	"emif2_fck",
+	"gpmc_ick",
+	"l3_instr_ick",
+	"l3_main_3_ick",
+	"ocp_wp_noc_ick",
+};
+
+int __init omap4xxx_clk_init(void)
+{
+	u32 cpu_clkflg;
+	struct omap_clk *c;
+
+	if (cpu_is_omap443x()) {
+		cpu_mask = RATE_IN_4430;
+		cpu_clkflg = CK_443X;
+	} else if (cpu_is_omap446x() || cpu_is_omap447x()) {
+		cpu_mask = RATE_IN_4460 | RATE_IN_4430;
+		cpu_clkflg = CK_446X | CK_443X;
+
+		if (cpu_is_omap447x())
+			pr_warn("WARNING: OMAP4470 clock data incomplete!\n");
+	} else {
+		return 0;
+	}
+
+	for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks);
+									c++) {
+		if (c->cpu & cpu_clkflg) {
+			clkdev_add(&c->lk);
+			if (!__clk_init(NULL, c->lk.clk))
+				omap2_init_clk_hw_omap_clocks(c->lk.clk);
+		}
+	}
+
+	omap2_clk_disable_autoidle_all();
+
+	omap2_clk_enable_init_clocks(enable_init_clks,
+				     ARRAY_SIZE(enable_init_clks));
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap2/clkt2xxx_apll.c b/arch/arm/mach-omap2/clkt2xxx_apll.c
index c2d1521..25b1fee 100644
--- a/arch/arm/mach-omap2/clkt2xxx_apll.c
+++ b/arch/arm/mach-omap2/clkt2xxx_apll.c
@@ -21,12 +21,10 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/clock.h>
-#include <plat/prcm.h>
 
 #include "clock.h"
 #include "clock2xxx.h"
-#include "cm2xxx_3xxx.h"
+#include "cm2xxx.h"
 #include "cm-regbits-24xx.h"
 
 /* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
@@ -38,92 +36,90 @@
 #define APLLS_CLKIN_13MHZ		2
 #define APLLS_CLKIN_12MHZ		3
 
-void __iomem *cm_idlest_pll;
-
 /* Private functions */
 
-/* Enable an APLL if off */
-static int omap2_clk_apll_enable(struct clk *clk, u32 status_mask)
+/**
+ * omap2xxx_clk_apll_locked - is the APLL locked?
+ * @hw: struct clk_hw * of the APLL to check
+ *
+ * If the APLL IP block referred to by @hw indicates that it's locked,
+ * return true; otherwise, return false.
+ */
+static bool omap2xxx_clk_apll_locked(struct clk_hw *hw)
 {
-	u32 cval, apll_mask;
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+	u32 r, apll_mask;
 
 	apll_mask = EN_APLL_LOCKED << clk->enable_bit;
 
-	cval = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
-
-	if ((cval & apll_mask) == apll_mask)
-		return 0;   /* apll already enabled */
-
-	cval &= ~apll_mask;
-	cval |= apll_mask;
-	omap2_cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
-
-	omap2_cm_wait_idlest(cm_idlest_pll, status_mask,
-			     OMAP24XX_CM_IDLEST_VAL, __clk_get_name(clk));
+	r = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
 
-	/*
-	 * REVISIT: Should we return an error code if omap2_wait_clock_ready()
-	 * fails?
-	 */
-	return 0;
+	return ((r & apll_mask) == apll_mask) ? true : false;
 }
 
-static int omap2_clk_apll96_enable(struct clk *clk)
+int omap2_clk_apll96_enable(struct clk_hw *hw)
 {
-	return omap2_clk_apll_enable(clk, OMAP24XX_ST_96M_APLL_MASK);
+	return omap2xxx_cm_apll96_enable();
 }
 
-static int omap2_clk_apll54_enable(struct clk *clk)
+int omap2_clk_apll54_enable(struct clk_hw *hw)
 {
-	return omap2_clk_apll_enable(clk, OMAP24XX_ST_54M_APLL_MASK);
+	return omap2xxx_cm_apll54_enable();
 }
 
-static void _apll96_allow_idle(struct clk *clk)
+static void _apll96_allow_idle(struct clk_hw_omap *clk)
 {
 	omap2xxx_cm_set_apll96_auto_low_power_stop();
 }
 
-static void _apll96_deny_idle(struct clk *clk)
+static void _apll96_deny_idle(struct clk_hw_omap *clk)
 {
 	omap2xxx_cm_set_apll96_disable_autoidle();
 }
 
-static void _apll54_allow_idle(struct clk *clk)
+static void _apll54_allow_idle(struct clk_hw_omap *clk)
 {
 	omap2xxx_cm_set_apll54_auto_low_power_stop();
 }
 
-static void _apll54_deny_idle(struct clk *clk)
+static void _apll54_deny_idle(struct clk_hw_omap *clk)
 {
 	omap2xxx_cm_set_apll54_disable_autoidle();
 }
 
-/* Stop APLL */
-static void omap2_clk_apll_disable(struct clk *clk)
+void omap2_clk_apll96_disable(struct clk_hw *hw)
 {
-	u32 cval;
+	omap2xxx_cm_apll96_disable();
+}
 
-	cval = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
-	cval &= ~(EN_APLL_LOCKED << clk->enable_bit);
-	omap2_cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
+void omap2_clk_apll54_disable(struct clk_hw *hw)
+{
+	omap2xxx_cm_apll54_disable();
 }
 
-/* Public data */
+unsigned long omap2_clk_apll54_recalc(struct clk_hw *hw,
+				      unsigned long parent_rate)
+{
+	return (omap2xxx_clk_apll_locked(hw)) ? 54000000 : 0;
+}
 
-const struct clkops clkops_apll96 = {
-	.enable		= omap2_clk_apll96_enable,
-	.disable	= omap2_clk_apll_disable,
-	.allow_idle	= _apll96_allow_idle,
-	.deny_idle	= _apll96_deny_idle,
-};
+unsigned long omap2_clk_apll96_recalc(struct clk_hw *hw,
+				      unsigned long parent_rate)
+{
+	return (omap2xxx_clk_apll_locked(hw)) ? 96000000 : 0;
+}
 
-const struct clkops clkops_apll54 = {
-	.enable		= omap2_clk_apll54_enable,
-	.disable	= omap2_clk_apll_disable,
+/* Public data */
+const struct clk_hw_omap_ops clkhwops_apll54 = {
 	.allow_idle	= _apll54_allow_idle,
 	.deny_idle	= _apll54_deny_idle,
 };
 
+const struct clk_hw_omap_ops clkhwops_apll96 = {
+	.allow_idle	= _apll96_allow_idle,
+	.deny_idle	= _apll96_deny_idle,
+};
+
 /* Public functions */
 
 u32 omap2xxx_get_apll_clkin(void)
diff --git a/arch/arm/mach-omap2/clkt2xxx_dpll.c b/arch/arm/mach-omap2/clkt2xxx_dpll.c
index 1502a7b..82572e2 100644
--- a/arch/arm/mach-omap2/clkt2xxx_dpll.c
+++ b/arch/arm/mach-omap2/clkt2xxx_dpll.c
@@ -14,10 +14,8 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/clock.h>
-
 #include "clock.h"
-#include "cm2xxx_3xxx.h"
+#include "cm2xxx.h"
 #include "cm-regbits-24xx.h"
 
 /* Private functions */
@@ -31,7 +29,7 @@
  * REVISIT: DPLL can optionally enter low-power bypass by writing 0x1
  * instead.  Add some mechanism to optionally enter this mode.
  */
-static void _allow_idle(struct clk *clk)
+static void _allow_idle(struct clk_hw_omap *clk)
 {
 	if (!clk || !clk->dpll_data)
 		return;
@@ -45,7 +43,7 @@ static void _allow_idle(struct clk *clk)
  *
  * Disable DPLL automatic idle control.  No return value.
  */
-static void _deny_idle(struct clk *clk)
+static void _deny_idle(struct clk_hw_omap *clk)
 {
 	if (!clk || !clk->dpll_data)
 		return;
@@ -55,9 +53,7 @@ static void _deny_idle(struct clk *clk)
 
 
 /* Public data */
-
-const struct clkops clkops_omap2xxx_dpll_ops = {
+const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll = {
 	.allow_idle	= _allow_idle,
 	.deny_idle	= _deny_idle,
 };
-
diff --git a/arch/arm/mach-omap2/clkt2xxx_dpllcore.c b/arch/arm/mach-omap2/clkt2xxx_dpllcore.c
index 4ae4392..d862010 100644
--- a/arch/arm/mach-omap2/clkt2xxx_dpllcore.c
+++ b/arch/arm/mach-omap2/clkt2xxx_dpllcore.c
@@ -25,21 +25,25 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/clock.h>
-#include <plat/sram.h>
-#include <plat/sdrc.h>
-
 #include "clock.h"
 #include "clock2xxx.h"
 #include "opp2xxx.h"
-#include "cm2xxx_3xxx.h"
+#include "cm2xxx.h"
 #include "cm-regbits-24xx.h"
+#include "sdrc.h"
+#include "sram.h"
 
 /* #define DOWN_VARIABLE_DPLL 1 */		/* Experimental */
 
+/*
+ * dpll_core_ck: pointer to the combined dpll_ck + core_ck on OMAP2xxx
+ * (currently defined as "dpll_ck" in the OMAP2xxx clock tree).  Set
+ * during dpll_ck init and used later by omap2xxx_clk_get_core_rate().
+ */
+static struct clk_hw_omap *dpll_core_ck;
+
 /**
  * omap2xxx_clk_get_core_rate - return the CORE_CLK rate
- * @clk: pointer to the combined dpll_ck + core_ck (currently "dpll_ck")
  *
  * Returns the CORE_CLK rate.  CORE_CLK can have one of three rate
  * sources on OMAP2xxx: the DPLL CLKOUT rate, DPLL CLKOUTX2, or 32KHz
@@ -47,12 +51,14 @@
  * struct clk *dpll_ck, which is a composite clock of dpll_ck and
  * core_ck.
  */
-unsigned long omap2xxx_clk_get_core_rate(struct clk *clk)
+unsigned long omap2xxx_clk_get_core_rate(void)
 {
 	long long core_clk;
 	u32 v;
 
-	core_clk = omap2_get_dpll_rate(clk);
+	WARN_ON(!dpll_core_ck);
+
+	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;
@@ -98,19 +104,22 @@ static long omap2_dpllcore_round_rate(unsigned long target_rate)
 
 }
 
-unsigned long omap2_dpllcore_recalc(struct clk *clk)
+unsigned long omap2_dpllcore_recalc(struct clk_hw *hw,
+				    unsigned long parent_rate)
 {
-	return omap2xxx_clk_get_core_rate(clk);
+	return omap2xxx_clk_get_core_rate();
 }
 
-int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
+int omap2_reprogram_dpllcore(struct clk_hw *hw, unsigned long rate,
+			     unsigned long parent_rate)
 {
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	u32 cur_rate, low, mult, div, valid_rate, done_rate;
 	u32 bypass = 0;
 	struct prcm_config tmpset;
 	const struct dpll_data *dd;
 
-	cur_rate = omap2xxx_clk_get_core_rate(dclk);
+	cur_rate = omap2xxx_clk_get_core_rate();
 	mult = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
 	mult &= OMAP24XX_CORE_CLK_SRC_MASK;
 
@@ -171,3 +180,19 @@ int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
 	return 0;
 }
 
+/**
+ * omap2xxx_clkt_dpllcore_init - clk init function for dpll_ck
+ * @clk: struct clk *dpll_ck
+ *
+ * Store a local copy of @clk in dpll_core_ck so other code can query
+ * the core rate without having to clk_get(), which can sleep.  Must
+ * only be called once.  No return value.  XXX If the clock
+ * registration process is ever changed such that dpll_ck is no longer
+ * statically defined, this code may need to change to increment some
+ * kind of use count on dpll_ck.
+ */
+void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw)
+{
+	WARN(dpll_core_ck, "dpll_core_ck already set - should never happen");
+	dpll_core_ck = to_clk_hw_omap(hw);
+}
diff --git a/arch/arm/mach-omap2/clkt2xxx_osc.c b/arch/arm/mach-omap2/clkt2xxx_osc.c
index c346092..19f54d4 100644
--- a/arch/arm/mach-omap2/clkt2xxx_osc.c
+++ b/arch/arm/mach-omap2/clkt2xxx_osc.c
@@ -23,8 +23,6 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/clock.h>
-
 #include "clock.h"
 #include "clock2xxx.h"
 #include "prm2xxx_3xxx.h"
@@ -37,7 +35,7 @@
  * clk_enable/clk_disable()-based usecounting for osc_ck should be
  * replaced with autoidle-based usecounting.
  */
-static int omap2_enable_osc_ck(struct clk *clk)
+int omap2_enable_osc_ck(struct clk_hw *clk)
 {
 	u32 pcc;
 
@@ -55,7 +53,7 @@ static int omap2_enable_osc_ck(struct clk *clk)
  * clk_enable/clk_disable()-based usecounting for osc_ck should be
  * replaced with autoidle-based usecounting.
  */
-static void omap2_disable_osc_ck(struct clk *clk)
+void omap2_disable_osc_ck(struct clk_hw *clk)
 {
 	u32 pcc;
 
@@ -64,13 +62,8 @@ static void omap2_disable_osc_ck(struct clk *clk)
 	__raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl);
 }
 
-const struct clkops clkops_oscck = {
-	.enable		= omap2_enable_osc_ck,
-	.disable	= omap2_disable_osc_ck,
-};
-
-unsigned long omap2_osc_clk_recalc(struct clk *clk)
+unsigned long omap2_osc_clk_recalc(struct clk_hw *clk,
+				   unsigned long parent_rate)
 {
 	return omap2xxx_get_apll_clkin() * omap2xxx_get_sysclkdiv();
 }
-
diff --git a/arch/arm/mach-omap2/clkt2xxx_sys.c b/arch/arm/mach-omap2/clkt2xxx_sys.c
index 8693cfd..f467d07 100644
--- a/arch/arm/mach-omap2/clkt2xxx_sys.c
+++ b/arch/arm/mach-omap2/clkt2xxx_sys.c
@@ -22,8 +22,6 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/clock.h>
-
 #include "clock.h"
 #include "clock2xxx.h"
 #include "prm2xxx_3xxx.h"
@@ -42,9 +40,8 @@ u32 omap2xxx_get_sysclkdiv(void)
 	return div;
 }
 
-unsigned long omap2xxx_sys_clk_recalc(struct clk *clk)
+unsigned long omap2xxx_sys_clk_recalc(struct clk_hw *clk,
+				      unsigned long parent_rate)
 {
-	return clk->parent->rate / omap2xxx_get_sysclkdiv();
+	return parent_rate / omap2xxx_get_sysclkdiv();
 }
-
-
diff --git a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
index 3524f0e..ae2b35e 100644
--- a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
+++ b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
@@ -1,7 +1,7 @@
 /*
  * OMAP2xxx DVFS virtual clock functions
  *
- * Copyright (C) 2005-2008 Texas Instruments, Inc.
+ * Copyright (C) 2005-2008, 2012 Texas Instruments, Inc.
  * Copyright (C) 2004-2010 Nokia Corporation
  *
  * Contacts:
@@ -33,27 +33,33 @@
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
 
-#include <plat/clock.h>
-#include <plat/sram.h>
-#include <plat/sdrc.h>
-
 #include "soc.h"
 #include "clock.h"
 #include "clock2xxx.h"
 #include "opp2xxx.h"
-#include "cm2xxx_3xxx.h"
+#include "cm2xxx.h"
 #include "cm-regbits-24xx.h"
+#include "sdrc.h"
+#include "sram.h"
 
 const struct prcm_config *curr_prcm_set;
 const struct prcm_config *rate_table;
 
+/*
+ * sys_ck_rate: the rate of the external high-frequency clock
+ * oscillator on the board.  Set by the SoC-specific clock init code.
+ * Once set during a boot, will not change.
+ */
+static unsigned long sys_ck_rate;
+
 /**
  * omap2_table_mpu_recalc - just return the MPU speed
  * @clk: virt_prcm_set struct clk
  *
  * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
  */
-unsigned long omap2_table_mpu_recalc(struct clk *clk)
+unsigned long omap2_table_mpu_recalc(struct clk_hw *clk,
+				     unsigned long parent_rate)
 {
 	return curr_prcm_set->mpu_speed;
 }
@@ -65,18 +71,18 @@ unsigned long omap2_table_mpu_recalc(struct clk *clk)
  * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
  * just uses the ARM rates.
  */
-long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
+long omap2_round_to_table_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long *parent_rate)
 {
 	const struct prcm_config *ptr;
-	long highest_rate, sys_clk_rate;
+	long highest_rate;
 
 	highest_rate = -EINVAL;
-	sys_clk_rate = __clk_get_rate(sclk);
 
 	for (ptr = rate_table; ptr->mpu_speed; ptr++) {
 		if (!(ptr->flags & cpu_mask))
 			continue;
-		if (ptr->xtal_speed != sys_clk_rate)
+		if (ptr->xtal_speed != sys_ck_rate)
 			continue;
 
 		highest_rate = ptr->mpu_speed;
@@ -89,21 +95,19 @@ long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
 }
 
 /* Sets basic clocks based on the specified rate */
-int omap2_select_table_rate(struct clk *clk, unsigned long rate)
+int omap2_select_table_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long parent_rate)
 {
 	u32 cur_rate, done_rate, bypass = 0, tmp;
 	const struct prcm_config *prcm;
 	unsigned long found_speed = 0;
 	unsigned long flags;
-	long sys_clk_rate;
-
-	sys_clk_rate = __clk_get_rate(sclk);
 
 	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
 		if (!(prcm->flags & cpu_mask))
 			continue;
 
-		if (prcm->xtal_speed != sys_clk_rate)
+		if (prcm->xtal_speed != sys_ck_rate)
 			continue;
 
 		if (prcm->mpu_speed <= rate) {
@@ -119,7 +123,7 @@ int omap2_select_table_rate(struct clk *clk, unsigned long rate)
 	}
 
 	curr_prcm_set = prcm;
-	cur_rate = omap2xxx_clk_get_core_rate(dclk);
+	cur_rate = omap2xxx_clk_get_core_rate();
 
 	if (prcm->dpll_speed == cur_rate / 2) {
 		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
@@ -169,3 +173,50 @@ int omap2_select_table_rate(struct clk *clk, unsigned long rate)
 
 	return 0;
 }
+
+/**
+ * omap2xxx_clkt_vps_check_bootloader_rate - determine which of the rate
+ * table sets matches the current CORE DPLL hardware rate
+ *
+ * Check the MPU rate set by bootloader.  Sets the 'curr_prcm_set'
+ * global to point to the active rate set when found; otherwise, sets
+ * it to NULL.  No return value;
+ */
+void omap2xxx_clkt_vps_check_bootloader_rates(void)
+{
+	const struct prcm_config *prcm = NULL;
+	unsigned long rate;
+
+	rate = omap2xxx_clk_get_core_rate();
+	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
+		if (!(prcm->flags & cpu_mask))
+			continue;
+		if (prcm->xtal_speed != sys_ck_rate)
+			continue;
+		if (prcm->dpll_speed <= rate)
+			break;
+	}
+	curr_prcm_set = prcm;
+}
+
+/**
+ * omap2xxx_clkt_vps_late_init - store a copy of the sys_ck rate
+ *
+ * Store a copy of the sys_ck rate for later use by the OMAP2xxx DVFS
+ * code.  (The sys_ck rate does not -- or rather, must not -- change
+ * during kernel runtime.)  Must be called after we have a valid
+ * sys_ck rate, but before the virt_prcm_set clock rate is
+ * recalculated.  No return value.
+ */
+void omap2xxx_clkt_vps_late_init(void)
+{
+	struct clk *c;
+
+	c = clk_get(NULL, "sys_ck");
+	if (IS_ERR(c)) {
+		WARN(1, "could not locate sys_ck\n");
+	} else {
+		sys_ck_rate = clk_get_rate(c);
+		clk_put(c);
+	}
+}
diff --git a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
index 7c6da2f..eb69acf 100644
--- a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
+++ b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
@@ -21,14 +21,11 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/clock.h>
-#include <plat/sram.h>
-#include <plat/sdrc.h>
-
 #include "clock.h"
 #include "clock3xxx.h"
 #include "clock34xx.h"
 #include "sdrc.h"
+#include "sram.h"
 
 #define CYCLES_PER_MHZ			1000000
 
@@ -47,8 +44,10 @@
  * Program the DPLL M2 divider with the rounded target rate.  Returns
  * -EINVAL upon error, or 0 upon success.
  */
-int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
+int omap3_core_dpll_m2_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long parent_rate)
 {
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	u32 new_div = 0;
 	u32 unlock_dll = 0;
 	u32 c;
@@ -66,7 +65,7 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
 		return -EINVAL;
 
 	sdrcrate = __clk_get_rate(sdrc_ick_p);
-	clkrate = __clk_get_rate(clk);
+	clkrate = __clk_get_rate(hw->clk);
 	if (rate > clkrate)
 		sdrcrate <<= ((rate / clkrate) >> 1);
 	else
@@ -115,8 +114,6 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
 				  sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
 				  sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
 				  0, 0, 0, 0);
-	clk->rate = rate;
-
 	return 0;
 }
 
diff --git a/arch/arm/mach-omap2/clkt_clksel.c b/arch/arm/mach-omap2/clkt_clksel.c
index 3ff2211..0ec9f6f 100644
--- a/arch/arm/mach-omap2/clkt_clksel.c
+++ b/arch/arm/mach-omap2/clkt_clksel.c
@@ -41,12 +41,10 @@
 
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/bug.h>
 
-#include <plat/clock.h>
-
 #include "clock.h"
 
 /* Private functions */
@@ -60,11 +58,14 @@
  * the element associated with the supplied parent clock address.
  * Returns a pointer to the struct clksel on success or NULL on error.
  */
-static const struct clksel *_get_clksel_by_parent(struct clk *clk,
+static const struct clksel *_get_clksel_by_parent(struct clk_hw_omap *clk,
 						  struct clk *src_clk)
 {
 	const struct clksel *clks;
 
+	if (!src_clk)
+		return NULL;
+
 	for (clks = clk->clksel; clks->parent; clks++)
 		if (clks->parent == src_clk)
 			break; /* Found the requested parent */
@@ -72,7 +73,7 @@ static const struct clksel *_get_clksel_by_parent(struct clk *clk,
 	if (!clks->parent) {
 		/* This indicates a data problem */
 		WARN(1, "clock: %s: could not find parent clock %s in clksel array\n",
-		     __clk_get_name(clk), __clk_get_name(src_clk));
+		     __clk_get_name(clk->hw.clk), __clk_get_name(src_clk));
 		return NULL;
 	}
 
@@ -80,64 +81,6 @@ static const struct clksel *_get_clksel_by_parent(struct clk *clk,
 }
 
 /**
- * _get_div_and_fieldval() - find the new clksel divisor and field value to use
- * @src_clk: planned new parent struct clk *
- * @clk: struct clk * that is being reparented
- * @field_val: pointer to a u32 to contain the register data for the divisor
- *
- * Given an intended new parent struct clk * @src_clk, and the struct
- * clk * @clk to the clock that is being reparented, find the
- * appropriate rate divisor for the new clock (returned as the return
- * value), and the corresponding register bitfield data to program to
- * reach that divisor (returned in the u32 pointed to by @field_val).
- * Returns 0 on error, or returns the newly-selected divisor upon
- * success (in this latter case, the corresponding register bitfield
- * value is passed back in the variable pointed to by @field_val)
- */
-static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
-				u32 *field_val)
-{
-	const struct clksel *clks;
-	const struct clksel_rate *clkr, *max_clkr = NULL;
-	u8 max_div = 0;
-
-	clks = _get_clksel_by_parent(clk, src_clk);
-	if (!clks)
-		return 0;
-
-	/*
-	 * Find the highest divisor (e.g., the one resulting in the
-	 * lowest rate) to use as the default.  This should avoid
-	 * clock rates that are too high for the device.  XXX A better
-	 * solution here would be to try to determine if there is a
-	 * divisor matching the original clock rate before the parent
-	 * switch, and if it cannot be found, to fall back to the
-	 * highest divisor.
-	 */
-	for (clkr = clks->rates; clkr->div; clkr++) {
-		if (!(clkr->flags & cpu_mask))
-			continue;
-
-		if (clkr->div > max_div) {
-			max_div = clkr->div;
-			max_clkr = clkr;
-		}
-	}
-
-	if (max_div == 0) {
-		/* This indicates an error in the clksel data */
-		WARN(1, "clock: %s: could not find divisor for parent %s\n",
-		     __clk_get_name(clk),
-		     __clk_get_name(__clk_get_parent(src_clk)));
-		return 0;
-	}
-
-	*field_val = max_clkr->val;
-
-	return max_div;
-}
-
-/**
  * _write_clksel_reg() - program a clock's clksel register in hardware
  * @clk: struct clk * to program
  * @v: clksel bitfield value to program (with LSB at bit 0)
@@ -150,7 +93,7 @@ static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
  * take into account any time the hardware might take to switch the
  * clock source.
  */
-static void _write_clksel_reg(struct clk *clk, u32 field_val)
+static void _write_clksel_reg(struct clk_hw_omap *clk, u32 field_val)
 {
 	u32 v;
 
@@ -173,13 +116,14 @@ static void _write_clksel_reg(struct clk *clk, u32 field_val)
  * before calling.  Returns 0 on error or returns the actual integer divisor
  * upon success.
  */
-static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
+static u32 _clksel_to_divisor(struct clk_hw_omap *clk, u32 field_val)
 {
 	const struct clksel *clks;
 	const struct clksel_rate *clkr;
 	struct clk *parent;
 
-	parent = __clk_get_parent(clk);
+	parent = __clk_get_parent(clk->hw.clk);
+
 	clks = _get_clksel_by_parent(clk, parent);
 	if (!clks)
 		return 0;
@@ -195,7 +139,8 @@ static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
 	if (!clkr->div) {
 		/* This indicates a data error */
 		WARN(1, "clock: %s: could not find fieldval %d for parent %s\n",
-		     __clk_get_name(clk), field_val, __clk_get_name(parent));
+		     __clk_get_name(clk->hw.clk), field_val,
+		     __clk_get_name(parent));
 		return 0;
 	}
 
@@ -212,7 +157,7 @@ static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
  * register field value _before_ left-shifting (i.e., LSB is at bit
  * 0); or returns 0xFFFFFFFF (~0) upon error.
  */
-static u32 _divisor_to_clksel(struct clk *clk, u32 div)
+static u32 _divisor_to_clksel(struct clk_hw_omap *clk, u32 div)
 {
 	const struct clksel *clks;
 	const struct clksel_rate *clkr;
@@ -221,7 +166,7 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
 	/* should never happen */
 	WARN_ON(div == 0);
 
-	parent = __clk_get_parent(clk);
+	parent = __clk_get_parent(clk->hw.clk);
 	clks = _get_clksel_by_parent(clk, parent);
 	if (!clks)
 		return ~0;
@@ -236,7 +181,8 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
 
 	if (!clkr->div) {
 		pr_err("clock: %s: could not find divisor %d for parent %s\n",
-		       __clk_get_name(clk), div, __clk_get_name(parent));
+		       __clk_get_name(clk->hw.clk), div,
+		       __clk_get_name(parent));
 		return ~0;
 	}
 
@@ -251,7 +197,7 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
  * into the hardware, convert it into the actual divisor value, and
  * return it; or return 0 on error.
  */
-static u32 _read_divisor(struct clk *clk)
+static u32 _read_divisor(struct clk_hw_omap *clk)
 {
 	u32 v;
 
@@ -279,7 +225,8 @@ static u32 _read_divisor(struct clk *clk)
  *
  * Returns the rounded clock rate or returns 0xffffffff on error.
  */
-u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
+u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
+						 unsigned long target_rate,
 				u32 *new_div)
 {
 	unsigned long test_rate;
@@ -290,9 +237,9 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
 	unsigned long parent_rate;
 	const char *clk_name;
 
-	parent = __clk_get_parent(clk);
+	parent = __clk_get_parent(clk->hw.clk);
+	clk_name = __clk_get_name(clk->hw.clk);
 	parent_rate = __clk_get_rate(parent);
-	clk_name = __clk_get_name(clk);
 
 	if (!clk->clksel || !clk->clksel_mask)
 		return ~0;
@@ -343,27 +290,35 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
  */
 
 /**
- * omap2_init_clksel_parent() - set a clksel clk's parent field from the hdwr
- * @clk: OMAP clock struct ptr to use
+ * omap2_clksel_find_parent_index() - return the array index of the current
+ * hardware parent of @hw
+ * @hw: struct clk_hw * to find the current hardware parent of
  *
- * Given a pointer @clk to a source-selectable struct clk, read the
- * hardware register and determine what its parent is currently set
- * to.  Update @clk's .parent field with the appropriate clk ptr.  No
- * return value.
+ * Given a struct clk_hw pointer @hw to the 'hw' member of a struct
+ * clk_hw_omap record representing a source-selectable hardware clock,
+ * read the hardware register and determine what its parent is
+ * currently set to.  Intended to be called only by the common clock
+ * framework struct clk_hw_ops.get_parent function pointer.  Return
+ * the array index of this parent clock upon success -- there is no
+ * way to return an error, so if we encounter an error, just WARN()
+ * and pretend that we know that we're doing.
  */
-void omap2_init_clksel_parent(struct clk *clk)
+u8 omap2_clksel_find_parent_index(struct clk_hw *hw)
 {
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	const struct clksel *clks;
 	const struct clksel_rate *clkr;
 	u32 r, found = 0;
 	struct clk *parent;
 	const char *clk_name;
+	int ret = 0, f = 0;
 
-	if (!clk->clksel || !clk->clksel_mask)
-		return;
+	parent = __clk_get_parent(hw->clk);
+	clk_name = __clk_get_name(hw->clk);
 
-	parent = __clk_get_parent(clk);
-	clk_name = __clk_get_name(clk);
+	/* XXX should be able to return an error */
+	WARN((!clk->clksel || !clk->clksel_mask),
+	     "clock: %s: attempt to call on a non-clksel clock", clk_name);
 
 	r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
 	r >>= __ffs(clk->clksel_mask);
@@ -374,27 +329,21 @@ void omap2_init_clksel_parent(struct clk *clk)
 				continue;
 
 			if (clkr->val == r) {
-				if (parent != clks->parent) {
-					pr_debug("clock: %s: inited parent to %s (was %s)\n",
-						 clk_name,
-						 __clk_get_name(clks->parent),
-						 ((parent) ?
-						  __clk_get_name(parent) :
-						 "NULL"));
-					clk_reparent(clk, clks->parent);
-				}
 				found = 1;
+				ret = f;
 			}
 		}
+		f++;
 	}
 
 	/* This indicates a data error */
 	WARN(!found, "clock: %s: init parent: could not find regval %0x\n",
 	     clk_name, r);
 
-	return;
+	return ret;
 }
 
+
 /**
  * omap2_clksel_recalc() - function ptr to pass via struct clk .recalc field
  * @clk: struct clk *
@@ -404,21 +353,23 @@ void omap2_init_clksel_parent(struct clk *clk)
  * function.  Returns the clock's current rate, based on its parent's rate
  * and its current divisor setting in the hardware.
  */
-unsigned long omap2_clksel_recalc(struct clk *clk)
+unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate)
 {
 	unsigned long rate;
 	u32 div = 0;
-	struct clk *parent;
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 
-	div = _read_divisor(clk);
-	if (div == 0)
-		return __clk_get_rate(clk);
+	if (!parent_rate)
+		return 0;
 
-	parent = __clk_get_parent(clk);
-	rate = __clk_get_rate(parent) / div;
+	div = _read_divisor(clk);
+	if (!div)
+		rate = parent_rate;
+	else
+		rate = parent_rate / div;
 
-	pr_debug("clock: %s: recalc'd rate is %ld (div %d)\n",
-		 __clk_get_name(clk), rate, div);
+	pr_debug("%s: recalc'd %s's rate to %lu (div %d)\n", __func__,
+		 __clk_get_name(hw->clk), rate, div);
 
 	return rate;
 }
@@ -434,8 +385,10 @@ unsigned long omap2_clksel_recalc(struct clk *clk)
  *
  * Returns the rounded clock rate or returns 0xffffffff on error.
  */
-long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
+long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
+			unsigned long *parent_rate)
 {
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	u32 new_div;
 
 	return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
@@ -456,8 +409,10 @@ long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
  * is changed, they will all be affected without any notification.
  * Returns -EINVAL upon error, or 0 upon success.
  */
-int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
+int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
 {
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	u32 field_val, validrate, new_div = 0;
 
 	if (!clk->clksel || !clk->clksel_mask)
@@ -473,10 +428,8 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
 
 	_write_clksel_reg(clk, field_val);
 
-	clk->rate = __clk_get_rate(__clk_get_parent(clk)) / new_div;
-
-	pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(clk),
-		 __clk_get_rate(clk));
+	pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(hw->clk),
+		 __clk_get_rate(hw->clk));
 
 	return 0;
 }
@@ -501,32 +454,13 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
  * affected without any notification.  Returns -EINVAL upon error, or
  * 0 upon success.
  */
-int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent)
+int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val)
 {
-	u32 field_val = 0;
-	u32 parent_div;
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 
 	if (!clk->clksel || !clk->clksel_mask)
 		return -EINVAL;
 
-	parent_div = _get_div_and_fieldval(new_parent, clk, &field_val);
-	if (!parent_div)
-		return -EINVAL;
-
 	_write_clksel_reg(clk, field_val);
-
-	clk_reparent(clk, new_parent);
-
-	/* CLKSEL clocks follow their parents' rates, divided by a divisor */
-	clk->rate = __clk_get_rate(new_parent);
-
-	if (parent_div > 0)
-		__clk_get_rate(clk) /= parent_div;
-
-	pr_debug("clock: %s: set parent to %s (new rate %ld)\n",
-		 __clk_get_name(clk),
-		 __clk_get_name(__clk_get_parent(clk)),
-		 __clk_get_rate(clk));
-
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c
index 8041114..924c230 100644
--- a/arch/arm/mach-omap2/clkt_dpll.c
+++ b/arch/arm/mach-omap2/clkt_dpll.c
@@ -16,13 +16,11 @@
 
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/io.h>
 
 #include <asm/div64.h>
 
-#include <plat/clock.h>
-
 #include "soc.h"
 #include "clock.h"
 #include "cm-regbits-24xx.h"
@@ -78,7 +76,7 @@
  * (assuming that it is counting N upwards), or -2 if the enclosing loop
  * should skip to the next iteration (again assuming N is increasing).
  */
-static int _dpll_test_fint(struct clk *clk, u8 n)
+static int _dpll_test_fint(struct clk_hw_omap *clk, u8 n)
 {
 	struct dpll_data *dd;
 	long fint, fint_min, fint_max;
@@ -87,7 +85,7 @@ static int _dpll_test_fint(struct clk *clk, u8 n)
 	dd = clk->dpll_data;
 
 	/* DPLL divider must result in a valid jitter correction val */
-	fint = __clk_get_rate(__clk_get_parent(clk)) / n;
+	fint = __clk_get_rate(__clk_get_parent(clk->hw.clk)) / n;
 
 	if (cpu_is_omap24xx()) {
 		/* Should not be called for OMAP2, so warn if it is called */
@@ -188,15 +186,15 @@ static int _dpll_test_mult(int *m, int n, unsigned long *new_rate,
 }
 
 /* Public functions */
-
-void omap2_init_dpll_parent(struct clk *clk)
+u8 omap2_init_dpll_parent(struct clk_hw *hw)
 {
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	u32 v;
 	struct dpll_data *dd;
 
 	dd = clk->dpll_data;
 	if (!dd)
-		return;
+		return -EINVAL;
 
 	v = __raw_readl(dd->control_reg);
 	v &= dd->enable_mask;
@@ -206,18 +204,18 @@ void omap2_init_dpll_parent(struct clk *clk)
 	if (cpu_is_omap24xx()) {
 		if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
 		    v == OMAP2XXX_EN_DPLL_FRBYPASS)
-			clk_reparent(clk, dd->clk_bypass);
+			return 1;
 	} else if (cpu_is_omap34xx()) {
 		if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
 		    v == OMAP3XXX_EN_DPLL_FRBYPASS)
-			clk_reparent(clk, dd->clk_bypass);
+			return 1;
 	} else if (soc_is_am33xx() || cpu_is_omap44xx()) {
 		if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
 		    v == OMAP4XXX_EN_DPLL_FRBYPASS ||
 		    v == OMAP4XXX_EN_DPLL_MNBYPASS)
-			clk_reparent(clk, dd->clk_bypass);
+			return 1;
 	}
-	return;
+	return 0;
 }
 
 /**
@@ -234,7 +232,7 @@ void omap2_init_dpll_parent(struct clk *clk)
  * locked, or the appropriate bypass rate if the DPLL is bypassed, or 0
  * if the clock @clk is not a DPLL.
  */
-u32 omap2_get_dpll_rate(struct clk *clk)
+unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
 {
 	long long dpll_clk;
 	u32 dpll_mult, dpll_div, v;
@@ -290,8 +288,10 @@ u32 omap2_get_dpll_rate(struct clk *clk)
  * (expensive) function again.  Returns ~0 if the target rate cannot
  * be rounded, or the rounded rate upon success.
  */
-long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
+long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
+		unsigned long *parent_rate)
 {
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	int m, n, r, scaled_max_m;
 	unsigned long scaled_rt_rp;
 	unsigned long new_rate = 0;
@@ -305,7 +305,7 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
 	dd = clk->dpll_data;
 
 	ref_rate = __clk_get_rate(dd->clk_ref);
-	clk_name = __clk_get_name(clk);
+	clk_name = __clk_get_name(hw->clk);
 	pr_debug("clock: %s: starting DPLL round_rate, target rate %ld\n",
 		 clk_name, target_rate);
 
diff --git a/arch/arm/mach-omap2/clkt_iclk.c b/arch/arm/mach-omap2/clkt_iclk.c
index 3d43fba..f10eb03 100644
--- a/arch/arm/mach-omap2/clkt_iclk.c
+++ b/arch/arm/mach-omap2/clkt_iclk.c
@@ -11,11 +11,9 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/io.h>
 
-#include <plat/clock.h>
-#include <plat/prcm.h>
 
 #include "clock.h"
 #include "clock2xxx.h"
@@ -25,7 +23,7 @@
 /* Private functions */
 
 /* XXX */
-void omap2_clkt_iclk_allow_idle(struct clk *clk)
+void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk)
 {
 	u32 v, r;
 
@@ -37,7 +35,7 @@ void omap2_clkt_iclk_allow_idle(struct clk *clk)
 }
 
 /* XXX */
-void omap2_clkt_iclk_deny_idle(struct clk *clk)
+void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk)
 {
 	u32 v, r;
 
@@ -50,33 +48,17 @@ void omap2_clkt_iclk_deny_idle(struct clk *clk)
 
 /* Public data */
 
-const struct clkops clkops_omap2_iclk_dflt_wait = {
-	.enable		= omap2_dflt_clk_enable,
-	.disable	= omap2_dflt_clk_disable,
-	.find_companion	= omap2_clk_dflt_find_companion,
-	.find_idlest	= omap2_clk_dflt_find_idlest,
+const struct clk_hw_omap_ops clkhwops_iclk = {
 	.allow_idle	= omap2_clkt_iclk_allow_idle,
 	.deny_idle	= omap2_clkt_iclk_deny_idle,
 };
 
-const struct clkops clkops_omap2_iclk_dflt = {
-	.enable		= omap2_dflt_clk_enable,
-	.disable	= omap2_dflt_clk_disable,
+const struct clk_hw_omap_ops clkhwops_iclk_wait = {
 	.allow_idle	= omap2_clkt_iclk_allow_idle,
 	.deny_idle	= omap2_clkt_iclk_deny_idle,
+	.find_idlest	= omap2_clk_dflt_find_idlest,
+	.find_companion	= omap2_clk_dflt_find_companion,
 };
 
-const struct clkops clkops_omap2_iclk_idle_only = {
-	.allow_idle	= omap2_clkt_iclk_allow_idle,
-	.deny_idle	= omap2_clkt_iclk_deny_idle,
-};
 
-const struct clkops clkops_omap2_mdmclk_dflt_wait = {
-	.enable		= omap2_dflt_clk_enable,
-	.disable	= omap2_dflt_clk_disable,
-	.find_companion	= omap2_clk_dflt_find_companion,
-	.find_idlest	= omap2_clk_dflt_find_idlest,
-	.allow_idle	= omap2_clkt_iclk_allow_idle,
-	.deny_idle	= omap2_clkt_iclk_deny_idle,
-};
 
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 961ac8f..e4ec3a6 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -15,27 +15,35 @@
 #undef DEBUG
 
 #include <linux/kernel.h>
+#include <linux/export.h>
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/delay.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
 
 #include <asm/cpu.h>
 
-#include <plat/clock.h>
-#include <plat/prcm.h>
 
 #include <trace/events/power.h>
 
 #include "soc.h"
 #include "clockdomain.h"
 #include "clock.h"
-#include "cm2xxx_3xxx.h"
+#include "cm.h"
+#include "cm2xxx.h"
+#include "cm3xxx.h"
 #include "cm-regbits-24xx.h"
 #include "cm-regbits-34xx.h"
+#include "common.h"
+
+/*
+ * MAX_MODULE_ENABLE_WAIT: maximum of number of microseconds to wait
+ * for a module to indicate that it is no longer in idle
+ */
+#define MAX_MODULE_ENABLE_WAIT		100000
 
 u16 cpu_mask;
 
@@ -47,12 +55,69 @@ u16 cpu_mask;
  */
 static bool clkdm_control = true;
 
+static LIST_HEAD(clk_hw_omap_clocks);
+
+/*
+ * Used for clocks that have the same value as the parent clock,
+ * divided by some factor
+ */
+unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_hw_omap *oclk;
+
+	if (!hw) {
+		pr_warn("%s: hw is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	oclk = to_clk_hw_omap(hw);
+
+	WARN_ON(!oclk->fixed_div);
+
+	return parent_rate / oclk->fixed_div;
+}
+
 /*
  * OMAP2+ specific clock functions
  */
 
 /* Private functions */
 
+
+/**
+ * _wait_idlest_generic - wait for a module to leave the idle state
+ * @reg: virtual address of module IDLEST register
+ * @mask: value to mask against to determine if the module is active
+ * @idlest: idle state indicator (0 or 1) for the clock
+ * @name: name of the clock (for printk)
+ *
+ * Wait for a module to leave idle, where its idle-status register is
+ * not inside the CM module.  Returns 1 if the module left idle
+ * promptly, or 0 if the module did not leave idle before the timeout
+ * elapsed.  XXX Deprecated - should be moved into drivers for the
+ * individual IP block that the IDLEST register exists in.
+ */
+static int _wait_idlest_generic(void __iomem *reg, u32 mask, u8 idlest,
+				const char *name)
+{
+	int i = 0, ena = 0;
+
+	ena = (idlest) ? 0 : mask;
+
+	omap_test_timeout(((__raw_readl(reg) & mask) == ena),
+			  MAX_MODULE_ENABLE_WAIT, i);
+
+	if (i < MAX_MODULE_ENABLE_WAIT)
+		pr_debug("omap clock: module associated with clock %s ready after %d loops\n",
+			 name, i);
+	else
+		pr_err("omap clock: module associated with clock %s didn't enable in %d tries\n",
+		       name, MAX_MODULE_ENABLE_WAIT);
+
+	return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0;
+};
+
 /**
  * _omap2_module_wait_ready - wait for an OMAP module to leave IDLE
  * @clk: struct clk * belonging to the module
@@ -63,10 +128,12 @@ static bool clkdm_control = true;
  * belong in the clock code and will be moved in the medium term to
  * module-dependent code.  No return value.
  */
-static void _omap2_module_wait_ready(struct clk *clk)
+static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
 {
 	void __iomem *companion_reg, *idlest_reg;
-	u8 other_bit, idlest_bit, idlest_val;
+	u8 other_bit, idlest_bit, idlest_val, idlest_reg_id;
+	s16 prcm_mod;
+	int r;
 
 	/* Not all modules have multiple clocks that their IDLEST depends on */
 	if (clk->ops->find_companion) {
@@ -76,9 +143,14 @@ static void _omap2_module_wait_ready(struct clk *clk)
 	}
 
 	clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val);
-
-	omap2_cm_wait_idlest(idlest_reg, (1 << idlest_bit), idlest_val,
-			     __clk_get_name(clk));
+	r = cm_split_idlest_reg(idlest_reg, &prcm_mod, &idlest_reg_id);
+	if (r) {
+		/* IDLEST register not in the CM module */
+		_wait_idlest_generic(idlest_reg, (1 << idlest_bit), idlest_val,
+				     __clk_get_name(clk->hw.clk));
+	} else {
+		cm_wait_module_ready(prcm_mod, idlest_reg_id, idlest_bit);
+	};
 }
 
 /* Public functions */
@@ -91,15 +163,16 @@ static void _omap2_module_wait_ready(struct clk *clk)
  * clockdomain pointer, and save it into the struct clk.  Intended to be
  * called during clk_register().  No return value.
  */
-void omap2_init_clk_clkdm(struct clk *clk)
+void omap2_init_clk_clkdm(struct clk_hw *hw)
 {
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	struct clockdomain *clkdm;
 	const char *clk_name;
 
 	if (!clk->clkdm_name)
 		return;
 
-	clk_name = __clk_get_name(clk);
+	clk_name = __clk_get_name(hw->clk);
 
 	clkdm = clkdm_lookup(clk->clkdm_name);
 	if (clkdm) {
@@ -146,8 +219,8 @@ void __init omap2_clk_disable_clkdm_control(void)
  * associate this type of code with per-module data structures to
  * avoid this issue, and remove the casts.  No return value.
  */
-void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
-				   u8 *other_bit)
+void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
+			void __iomem **other_reg, u8 *other_bit)
 {
 	u32 r;
 
@@ -175,8 +248,8 @@ void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
  * register address ID (e.g., that CM_FCLKEN2 corresponds to
  * CM_IDLEST2).  This is not true for all modules.  No return value.
  */
-void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
-				u8 *idlest_bit, u8 *idlest_val)
+void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
+		void __iomem **idlest_reg, u8 *idlest_bit, u8 *idlest_val)
 {
 	u32 r;
 
@@ -198,16 +271,44 @@ void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
 
 }
 
-int omap2_dflt_clk_enable(struct clk *clk)
+/**
+ * omap2_dflt_clk_enable - enable a clock in the hardware
+ * @hw: struct clk_hw * of the clock to enable
+ *
+ * Enable the clock @hw in the hardware.  We first call into the OMAP
+ * clockdomain code to "enable" the corresponding clockdomain if this
+ * is the first enabled user of the clockdomain.  Then program the
+ * hardware to enable the clock.  Then wait for the IP block that uses
+ * this clock to leave idle (if applicable).  Returns the error value
+ * from clkdm_clk_enable() if it terminated with an error, or -EINVAL
+ * if @hw has a null clock enable_reg, or zero upon success.
+ */
+int omap2_dflt_clk_enable(struct clk_hw *hw)
 {
+	struct clk_hw_omap *clk;
 	u32 v;
+	int ret = 0;
+
+	clk = to_clk_hw_omap(hw);
+
+	if (clkdm_control && clk->clkdm) {
+		ret = clkdm_clk_enable(clk->clkdm, hw->clk);
+		if (ret) {
+			WARN(1, "%s: could not enable %s's clockdomain %s: %d\n",
+			     __func__, __clk_get_name(hw->clk),
+			     clk->clkdm->name, ret);
+			return ret;
+		}
+	}
 
 	if (unlikely(clk->enable_reg == NULL)) {
-		pr_err("clock.c: Enable for %s without enable code\n",
-		       clk->name);
-		return 0; /* REVISIT: -EINVAL */
+		pr_err("%s: %s missing enable_reg\n", __func__,
+		       __clk_get_name(hw->clk));
+		ret = -EINVAL;
+		goto err;
 	}
 
+	/* FIXME should not have INVERT_ENABLE bit here */
 	v = __raw_readl(clk->enable_reg);
 	if (clk->flags & INVERT_ENABLE)
 		v &= ~(1 << clk->enable_bit);
@@ -216,22 +317,39 @@ int omap2_dflt_clk_enable(struct clk *clk)
 	__raw_writel(v, clk->enable_reg);
 	v = __raw_readl(clk->enable_reg); /* OCP barrier */
 
-	if (clk->ops->find_idlest)
+	if (clk->ops && clk->ops->find_idlest)
 		_omap2_module_wait_ready(clk);
 
 	return 0;
+
+err:
+	if (clkdm_control && clk->clkdm)
+		clkdm_clk_disable(clk->clkdm, hw->clk);
+	return ret;
 }
 
-void omap2_dflt_clk_disable(struct clk *clk)
+/**
+ * omap2_dflt_clk_disable - disable a clock in the hardware
+ * @hw: struct clk_hw * of the clock to disable
+ *
+ * Disable the clock @hw in the hardware, and call into the OMAP
+ * clockdomain code to "disable" the corresponding clockdomain if all
+ * clocks/hwmods in that clockdomain are now disabled.  No return
+ * value.
+ */
+void omap2_dflt_clk_disable(struct clk_hw *hw)
 {
+	struct clk_hw_omap *clk;
 	u32 v;
 
+	clk = to_clk_hw_omap(hw);
 	if (!clk->enable_reg) {
 		/*
-		 * 'Independent' here refers to a clock which is not
+		 * 'independent' here refers to a clock which is not
 		 * controlled by its parent.
 		 */
-		pr_err("clock: clk_disable called on independent clock %s which has no enable_reg\n", clk->name);
+		pr_err("%s: independent clock %s has no enable_reg\n",
+		       __func__, __clk_get_name(hw->clk));
 		return;
 	}
 
@@ -242,191 +360,213 @@ void omap2_dflt_clk_disable(struct clk *clk)
 		v &= ~(1 << clk->enable_bit);
 	__raw_writel(v, clk->enable_reg);
 	/* No OCP barrier needed here since it is a disable operation */
-}
-
-const struct clkops clkops_omap2_dflt_wait = {
-	.enable		= omap2_dflt_clk_enable,
-	.disable	= omap2_dflt_clk_disable,
-	.find_companion	= omap2_clk_dflt_find_companion,
-	.find_idlest	= omap2_clk_dflt_find_idlest,
-};
 
-const struct clkops clkops_omap2_dflt = {
-	.enable		= omap2_dflt_clk_enable,
-	.disable	= omap2_dflt_clk_disable,
-};
+	if (clkdm_control && clk->clkdm)
+		clkdm_clk_disable(clk->clkdm, hw->clk);
+}
 
 /**
- * omap2_clk_disable - disable a clock, if the system is not using it
- * @clk: struct clk * to disable
+ * omap2_clkops_enable_clkdm - increment usecount on clkdm of @hw
+ * @hw: struct clk_hw * of the clock being enabled
  *
- * Decrements the usecount on struct clk @clk.  If there are no users
- * left, call the clkops-specific clock disable function to disable it
- * in hardware.  If the clock is part of a clockdomain (which they all
- * should be), request that the clockdomain be disabled.  (It too has
- * a usecount, and so will not be disabled in the hardware until it no
- * longer has any users.)  If the clock has a parent clock (most of
- * them do), then call ourselves, recursing on the parent clock.  This
- * can cause an entire branch of the clock tree to be powered off by
- * simply disabling one clock.  Intended to be called with the clockfw_lock
- * spinlock held.  No return value.
+ * Increment the usecount of the clockdomain of the clock pointed to
+ * by @hw; if the usecount is 1, the clockdomain will be "enabled."
+ * Only needed for clocks that don't use omap2_dflt_clk_enable() as
+ * their enable function pointer.  Passes along the return value of
+ * clkdm_clk_enable(), -EINVAL if @hw is not associated with a
+ * clockdomain, or 0 if clock framework-based clockdomain control is
+ * not implemented.
  */
-void omap2_clk_disable(struct clk *clk)
+int omap2_clkops_enable_clkdm(struct clk_hw *hw)
 {
-	if (clk->usecount == 0) {
-		WARN(1, "clock: %s: omap2_clk_disable() called, but usecount already 0?", clk->name);
-		return;
-	}
+	struct clk_hw_omap *clk;
+	int ret = 0;
 
-	pr_debug("clock: %s: decrementing usecount\n", clk->name);
+	clk = to_clk_hw_omap(hw);
 
-	clk->usecount--;
-
-	if (clk->usecount > 0)
-		return;
+	if (unlikely(!clk->clkdm)) {
+		pr_err("%s: %s: no clkdm set ?!\n", __func__,
+		       __clk_get_name(hw->clk));
+		return -EINVAL;
+	}
 
-	pr_debug("clock: %s: disabling in hardware\n", clk->name);
+	if (unlikely(clk->enable_reg))
+		pr_err("%s: %s: should use dflt_clk_enable ?!\n", __func__,
+		       __clk_get_name(hw->clk));
 
-	if (clk->ops && clk->ops->disable) {
-		trace_clock_disable(clk->name, 0, smp_processor_id());
-		clk->ops->disable(clk);
+	if (!clkdm_control) {
+		pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
+		       __func__, __clk_get_name(hw->clk));
+		return 0;
 	}
 
-	if (clkdm_control && clk->clkdm)
-		clkdm_clk_disable(clk->clkdm, clk);
+	ret = clkdm_clk_enable(clk->clkdm, hw->clk);
+	WARN(ret, "%s: could not enable %s's clockdomain %s: %d\n",
+	     __func__, __clk_get_name(hw->clk), clk->clkdm->name, ret);
 
-	if (clk->parent)
-		omap2_clk_disable(clk->parent);
+	return ret;
 }
 
 /**
- * omap2_clk_enable - request that the system enable a clock
- * @clk: struct clk * to enable
+ * omap2_clkops_disable_clkdm - decrement usecount on clkdm of @hw
+ * @hw: struct clk_hw * of the clock being disabled
  *
- * Increments the usecount on struct clk @clk.  If there were no users
- * previously, then recurse up the clock tree, enabling all of the
- * clock's parents and all of the parent clockdomains, and finally,
- * enabling @clk's clockdomain, and @clk itself.  Intended to be
- * called with the clockfw_lock spinlock held.  Returns 0 upon success
- * or a negative error code upon failure.
+ * Decrement the usecount of the clockdomain of the clock pointed to
+ * by @hw; if the usecount is 0, the clockdomain will be "disabled."
+ * Only needed for clocks that don't use omap2_dflt_clk_disable() as their
+ * disable function pointer.  No return value.
  */
-int omap2_clk_enable(struct clk *clk)
+void omap2_clkops_disable_clkdm(struct clk_hw *hw)
 {
-	int ret;
-
-	pr_debug("clock: %s: incrementing usecount\n", clk->name);
-
-	clk->usecount++;
-
-	if (clk->usecount > 1)
-		return 0;
+	struct clk_hw_omap *clk;
 
-	pr_debug("clock: %s: enabling in hardware\n", clk->name);
+	clk = to_clk_hw_omap(hw);
 
-	if (clk->parent) {
-		ret = omap2_clk_enable(clk->parent);
-		if (ret) {
-			WARN(1, "clock: %s: could not enable parent %s: %d\n",
-			     clk->name, clk->parent->name, ret);
-			goto oce_err1;
-		}
+	if (unlikely(!clk->clkdm)) {
+		pr_err("%s: %s: no clkdm set ?!\n", __func__,
+		       __clk_get_name(hw->clk));
+		return;
 	}
 
-	if (clkdm_control && clk->clkdm) {
-		ret = clkdm_clk_enable(clk->clkdm, clk);
-		if (ret) {
-			WARN(1, "clock: %s: could not enable clockdomain %s: %d\n",
-			     clk->name, clk->clkdm->name, ret);
-			goto oce_err2;
-		}
-	}
+	if (unlikely(clk->enable_reg))
+		pr_err("%s: %s: should use dflt_clk_disable ?!\n", __func__,
+		       __clk_get_name(hw->clk));
 
-	if (clk->ops && clk->ops->enable) {
-		trace_clock_enable(clk->name, 1, smp_processor_id());
-		ret = clk->ops->enable(clk);
-		if (ret) {
-			WARN(1, "clock: %s: could not enable: %d\n",
-			     clk->name, ret);
-			goto oce_err3;
-		}
+	if (!clkdm_control) {
+		pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
+		       __func__, __clk_get_name(hw->clk));
+		return;
 	}
 
-	return 0;
-
-oce_err3:
-	if (clkdm_control && clk->clkdm)
-		clkdm_clk_disable(clk->clkdm, clk);
-oce_err2:
-	if (clk->parent)
-		omap2_clk_disable(clk->parent);
-oce_err1:
-	clk->usecount--;
-
-	return ret;
+	clkdm_clk_disable(clk->clkdm, hw->clk);
 }
 
-/* Given a clock and a rate apply a clock specific rounding function */
-long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
+/**
+ * omap2_dflt_clk_is_enabled - is clock enabled in the hardware?
+ * @hw: struct clk_hw * to check
+ *
+ * Return 1 if the clock represented by @hw is enabled in the
+ * hardware, or 0 otherwise.  Intended for use in the struct
+ * clk_ops.is_enabled function pointer.
+ */
+int omap2_dflt_clk_is_enabled(struct clk_hw *hw)
 {
-	if (clk->round_rate)
-		return clk->round_rate(clk, rate);
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+	u32 v;
+
+	v = __raw_readl(clk->enable_reg);
+
+	if (clk->flags & INVERT_ENABLE)
+		v ^= BIT(clk->enable_bit);
+
+	v &= BIT(clk->enable_bit);
 
-	return clk->rate;
+	return v ? 1 : 0;
 }
 
-/* Set the clock rate for a clock source */
-int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
+static int __initdata mpurate;
+
+/*
+ * By default we use the rate set by the bootloader.
+ * You can override this with mpurate= cmdline option.
+ */
+static int __init omap_clk_setup(char *str)
 {
-	int ret = -EINVAL;
+	get_option(&str, &mpurate);
 
-	pr_debug("clock: set_rate for clock %s to rate %ld\n", clk->name, rate);
+	if (!mpurate)
+		return 1;
 
-	/* dpll_ck, core_ck, virt_prcm_set; plus all clksel clocks */
-	if (clk->set_rate) {
-		trace_clock_set_rate(clk->name, rate, smp_processor_id());
-		ret = clk->set_rate(clk, rate);
-	}
+	if (mpurate < 1000)
+		mpurate *= 1000000;
 
-	return ret;
+	return 1;
 }
+__setup("mpurate=", omap_clk_setup);
 
-int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
+/**
+ * omap2_init_clk_hw_omap_clocks - initialize an OMAP clock
+ * @clk: struct clk * to initialize
+ *
+ * Add an OMAP clock @clk to the internal list of OMAP clocks.  Used
+ * temporarily for autoidle handling, until this support can be
+ * integrated into the common clock framework code in some way.  No
+ * return value.
+ */
+void omap2_init_clk_hw_omap_clocks(struct clk *clk)
 {
-	if (!clk->clksel)
-		return -EINVAL;
+	struct clk_hw_omap *c;
 
-	if (clk->parent == new_parent)
-		return 0;
+	if (__clk_get_flags(clk) & CLK_IS_BASIC)
+		return;
 
-	return omap2_clksel_set_parent(clk, new_parent);
+	c = to_clk_hw_omap(__clk_get_hw(clk));
+	list_add(&c->node, &clk_hw_omap_clocks);
 }
 
-/*
- * OMAP2+ clock reset and init functions
+/**
+ * omap2_clk_enable_autoidle_all - enable autoidle on all OMAP clocks that
+ * support it
+ *
+ * Enable clock autoidle on all OMAP clocks that have allow_idle
+ * function pointers associated with them.  This function is intended
+ * to be temporary until support for this is added to the common clock
+ * code.  Returns 0.
  */
+int omap2_clk_enable_autoidle_all(void)
+{
+	struct clk_hw_omap *c;
+
+	list_for_each_entry(c, &clk_hw_omap_clocks, node)
+		if (c->ops && c->ops->allow_idle)
+			c->ops->allow_idle(c);
+	return 0;
+}
 
-#ifdef CONFIG_OMAP_RESET_CLOCKS
-void omap2_clk_disable_unused(struct clk *clk)
+/**
+ * omap2_clk_disable_autoidle_all - disable autoidle on all OMAP clocks that
+ * support it
+ *
+ * Disable clock autoidle on all OMAP clocks that have allow_idle
+ * function pointers associated with them.  This function is intended
+ * to be temporary until support for this is added to the common clock
+ * code.  Returns 0.
+ */
+int omap2_clk_disable_autoidle_all(void)
 {
-	u32 regval32, v;
+	struct clk_hw_omap *c;
 
-	v = (clk->flags & INVERT_ENABLE) ? (1 << clk->enable_bit) : 0;
+	list_for_each_entry(c, &clk_hw_omap_clocks, node)
+		if (c->ops && c->ops->deny_idle)
+			c->ops->deny_idle(c);
+	return 0;
+}
 
-	regval32 = __raw_readl(clk->enable_reg);
-	if ((regval32 & (1 << clk->enable_bit)) == v)
-		return;
+/**
+ * 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
+ *
+ * Prepare and enable a list of clocks, named by @clk_names.  No
+ * return value. XXX Deprecated; only needed until these clocks are
+ * properly claimed and enabled by the drivers or core code that uses
+ * them.  XXX What code disables & calls clk_put on these clocks?
+ */
+void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks)
+{
+	struct clk *init_clk;
+	int i;
 
-	pr_debug("Disabling unused clock \"%s\"\n", clk->name);
-	if (cpu_is_omap34xx()) {
-		omap2_clk_enable(clk);
-		omap2_clk_disable(clk);
-	} else {
-		clk->ops->disable(clk);
+	for (i = 0; i < num_clocks; i++) {
+		init_clk = clk_get(NULL, clk_names[i]);
+		clk_prepare_enable(init_clk);
 	}
-	if (clk->clkdm != NULL)
-		pwrdm_state_switch(clk->clkdm->pwrdm.ptr);
 }
-#endif
+
+const struct clk_hw_omap_ops clkhwops_wait = {
+	.find_idlest	= omap2_clk_dflt_find_idlest,
+	.find_companion	= omap2_clk_dflt_find_companion,
+};
 
 /**
  * omap2_clk_switch_mpurate_at_boot - switch ARM MPU rate by boot-time argument
@@ -458,14 +598,12 @@ int __init omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name)
 	r = clk_set_rate(mpurate_ck, mpurate);
 	if (IS_ERR_VALUE(r)) {
 		WARN(1, "clock: %s: unable to set MPU rate to %d: %d\n",
-		     mpurate_ck->name, mpurate, r);
+		     mpurate_ck_name, mpurate, r);
 		clk_put(mpurate_ck);
 		return -EINVAL;
 	}
 
 	calibrate_delay();
-	recalculate_root_clocks();
-
 	clk_put(mpurate_ck);
 
 	return 0;
@@ -509,15 +647,3 @@ void __init omap2_clk_print_new_rates(const char *hfclkin_ck_name,
 		(clk_get_rate(core_ck) / 1000000),
 		(clk_get_rate(mpu_ck) / 1000000));
 }
-
-/* Common data */
-
-struct clk_functions omap2_clk_functions = {
-	.clk_enable		= omap2_clk_enable,
-	.clk_disable		= omap2_clk_disable,
-	.clk_round_rate		= omap2_clk_round_rate,
-	.clk_set_rate		= omap2_clk_set_rate,
-	.clk_set_parent		= omap2_clk_set_parent,
-	.clk_disable_unused	= omap2_clk_disable_unused,
-};
-
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 35ec5f3..9917f79 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -17,8 +17,311 @@
 #define __ARCH_ARM_MACH_OMAP2_CLOCK_H
 
 #include <linux/kernel.h>
+#include <linux/list.h>
 
-#include <plat/clock.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+
+struct omap_clk {
+	u16				cpu;
+	struct clk_lookup		lk;
+};
+
+#define CLK(dev, con, ck, cp)		\
+	{				\
+		 .cpu = cp,		\
+		.lk = {			\
+			.dev_id = dev,	\
+			.con_id = con,	\
+			.clk = ck,	\
+		},			\
+	}
+
+/* Platform flags for the clkdev-OMAP integration code */
+#define CK_242X		(1 << 0)
+#define CK_243X		(1 << 1)	/* 243x, 253x */
+#define CK_3430ES1	(1 << 2)	/* 34xxES1 only */
+#define CK_3430ES2PLUS	(1 << 3)	/* 34xxES2, ES3, non-Sitara 35xx only */
+#define CK_AM35XX	(1 << 4)	/* Sitara AM35xx */
+#define CK_36XX		(1 << 5)	/* 36xx/37xx-specific clocks */
+#define CK_443X		(1 << 6)
+#define CK_TI816X	(1 << 7)
+#define CK_446X		(1 << 8)
+#define CK_AM33XX	(1 << 9)	/* AM33xx specific clocks */
+
+
+#define CK_34XX		(CK_3430ES1 | CK_3430ES2PLUS)
+#define CK_3XXX		(CK_34XX | CK_AM35XX | CK_36XX)
+
+struct clockdomain;
+#define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw)
+
+#define DEFINE_STRUCT_CLK(_name, _parent_array_name, _clkops_name)	\
+	static struct clk _name = {				\
+		.name = #_name,					\
+		.hw = &_name##_hw.hw,				\
+		.parent_names = _parent_array_name,		\
+		.num_parents = ARRAY_SIZE(_parent_array_name),	\
+		.ops = &_clkops_name,				\
+	};
+
+#define DEFINE_STRUCT_CLK_HW_OMAP(_name, _clkdm_name)		\
+	static struct clk_hw_omap _name##_hw = {		\
+		.hw = {						\
+			.clk = &_name,				\
+		},						\
+		.clkdm_name = _clkdm_name,			\
+	};
+
+#define DEFINE_CLK_OMAP_MUX(_name, _clkdm_name, _clksel,	\
+			    _clksel_reg, _clksel_mask,		\
+			    _parent_names, _ops)		\
+	static struct clk _name;				\
+	static struct clk_hw_omap _name##_hw = {		\
+		.hw = {						\
+			.clk = &_name,				\
+		},						\
+		.clksel		= _clksel,			\
+		.clksel_reg	= _clksel_reg,			\
+		.clksel_mask	= _clksel_mask,			\
+		.clkdm_name	= _clkdm_name,			\
+	};							\
+	DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
+
+#define DEFINE_CLK_OMAP_MUX_GATE(_name, _clkdm_name, _clksel,	\
+				 _clksel_reg, _clksel_mask,	\
+				 _enable_reg, _enable_bit,	\
+				 _hwops, _parent_names, _ops)	\
+	static struct clk _name;				\
+	static struct clk_hw_omap _name##_hw = {		\
+		.hw = {						\
+			.clk = &_name,				\
+		},						\
+		.ops		= _hwops,			\
+		.enable_reg	= _enable_reg,			\
+		.enable_bit	= _enable_bit,			\
+		.clksel		= _clksel,			\
+		.clksel_reg	= _clksel_reg,			\
+		.clksel_mask	= _clksel_mask,			\
+		.clkdm_name	= _clkdm_name,			\
+	};							\
+	DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
+
+#define DEFINE_CLK_OMAP_HSDIVIDER(_name, _parent_name,		\
+				_parent_ptr, _flags,		\
+				_clksel_reg, _clksel_mask)	\
+	static const struct clksel _name##_div[] = {		\
+		{						\
+			.parent = _parent_ptr,			\
+			.rates = div31_1to31_rates		\
+		},						\
+		{ .parent = NULL },				\
+	};							\
+	static struct clk _name;				\
+	static const char *_name##_parent_names[] = {		\
+		_parent_name,					\
+	};							\
+	static struct clk_hw_omap _name##_hw = {		\
+		.hw = {						\
+			.clk = &_name,				\
+		},						\
+		.clksel		= _name##_div,			\
+		.clksel_reg	= _clksel_reg,			\
+		.clksel_mask	= _clksel_mask,			\
+		.ops		= &clkhwops_omap4_dpllmx,	\
+	};							\
+	DEFINE_STRUCT_CLK(_name, _name##_parent_names, omap_hsdivider_ops);
+
+/* struct clksel_rate.flags possibilities */
+#define RATE_IN_242X		(1 << 0)
+#define RATE_IN_243X		(1 << 1)
+#define RATE_IN_3430ES1		(1 << 2)	/* 3430ES1 rates only */
+#define RATE_IN_3430ES2PLUS	(1 << 3)	/* 3430 ES >= 2 rates only */
+#define RATE_IN_36XX		(1 << 4)
+#define RATE_IN_4430		(1 << 5)
+#define RATE_IN_TI816X		(1 << 6)
+#define RATE_IN_4460		(1 << 7)
+#define RATE_IN_AM33XX		(1 << 8)
+#define RATE_IN_TI814X		(1 << 9)
+
+#define RATE_IN_24XX		(RATE_IN_242X | RATE_IN_243X)
+#define RATE_IN_34XX		(RATE_IN_3430ES1 | RATE_IN_3430ES2PLUS)
+#define RATE_IN_3XXX		(RATE_IN_34XX | RATE_IN_36XX)
+#define RATE_IN_44XX		(RATE_IN_4430 | RATE_IN_4460)
+
+/* RATE_IN_3430ES2PLUS_36XX includes 34xx/35xx with ES >=2, and all 36xx/37xx */
+#define RATE_IN_3430ES2PLUS_36XX	(RATE_IN_3430ES2PLUS | RATE_IN_36XX)
+
+
+/**
+ * struct clksel_rate - register bitfield values corresponding to clk divisors
+ * @val: register bitfield value (shifted to bit 0)
+ * @div: clock divisor corresponding to @val
+ * @flags: (see "struct clksel_rate.flags possibilities" above)
+ *
+ * @val should match the value of a read from struct clk.clksel_reg
+ * AND'ed with struct clk.clksel_mask, shifted right to bit 0.
+ *
+ * @div is the divisor that should be applied to the parent clock's rate
+ * to produce the current clock's rate.
+ */
+struct clksel_rate {
+	u32			val;
+	u8			div;
+	u16			flags;
+};
+
+/**
+ * struct clksel - available parent clocks, and a pointer to their divisors
+ * @parent: struct clk * to a possible parent clock
+ * @rates: available divisors for this parent clock
+ *
+ * A struct clksel is always associated with one or more struct clks
+ * and one or more struct clksel_rates.
+ */
+struct clksel {
+	struct clk		 *parent;
+	const struct clksel_rate *rates;
+};
+
+/**
+ * struct dpll_data - DPLL registers and integration data
+ * @mult_div1_reg: register containing the DPLL M and N bitfields
+ * @mult_mask: mask of the DPLL M bitfield in @mult_div1_reg
+ * @div1_mask: mask of the DPLL N bitfield in @mult_div1_reg
+ * @clk_bypass: struct clk pointer to the clock's bypass clock input
+ * @clk_ref: struct clk pointer to the clock's reference clock input
+ * @control_reg: register containing the DPLL mode bitfield
+ * @enable_mask: mask of the DPLL mode bitfield in @control_reg
+ * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate()
+ * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate()
+ * @max_multiplier: maximum valid non-bypass multiplier value (actual)
+ * @last_rounded_n: cache of the last N result of omap2_dpll_round_rate()
+ * @min_divider: minimum valid non-bypass divider value (actual)
+ * @max_divider: maximum valid non-bypass divider value (actual)
+ * @modes: possible values of @enable_mask
+ * @autoidle_reg: register containing the DPLL autoidle mode bitfield
+ * @idlest_reg: register containing the DPLL idle status bitfield
+ * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg
+ * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg
+ * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg
+ * @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg
+ * @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs
+ * @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs
+ * @flags: DPLL type/features (see below)
+ *
+ * Possible values for @flags:
+ * DPLL_J_TYPE: "J-type DPLL" (only some 36xx, 4xxx DPLLs)
+ *
+ * @freqsel_mask is only used on the OMAP34xx family and AM35xx.
+ *
+ * XXX Some DPLLs have multiple bypass inputs, so it's not technically
+ * correct to only have one @clk_bypass pointer.
+ *
+ * XXX The runtime-variable fields (@last_rounded_rate, @last_rounded_m,
+ * @last_rounded_n) should be separated from the runtime-fixed fields
+ * and placed into a different structure, so that the runtime-fixed data
+ * can be placed into read-only space.
+ */
+struct dpll_data {
+	void __iomem		*mult_div1_reg;
+	u32			mult_mask;
+	u32			div1_mask;
+	struct clk		*clk_bypass;
+	struct clk		*clk_ref;
+	void __iomem		*control_reg;
+	u32			enable_mask;
+	unsigned long		last_rounded_rate;
+	u16			last_rounded_m;
+	u16			max_multiplier;
+	u8			last_rounded_n;
+	u8			min_divider;
+	u16			max_divider;
+	u8			modes;
+	void __iomem		*autoidle_reg;
+	void __iomem		*idlest_reg;
+	u32			autoidle_mask;
+	u32			freqsel_mask;
+	u32			idlest_mask;
+	u32			dco_mask;
+	u32			sddiv_mask;
+	u8			auto_recal_bit;
+	u8			recal_en_bit;
+	u8			recal_st_bit;
+	u8			flags;
+};
+
+/*
+ * struct clk.flags possibilities
+ *
+ * XXX document the rest of the clock flags here
+ *
+ * CLOCK_CLKOUTX2: (OMAP4 only) DPLL CLKOUT and CLKOUTX2 GATE_CTRL
+ *     bits share the same register.  This flag allows the
+ *     omap4_dpllmx*() code to determine which GATE_CTRL bit field
+ *     should be used.  This is a temporary solution - a better approach
+ *     would be to associate clock type-specific data with the clock,
+ *     similar to the struct dpll_data approach.
+ */
+#define ENABLE_REG_32BIT	(1 << 0)	/* Use 32-bit access */
+#define CLOCK_IDLE_CONTROL	(1 << 1)
+#define CLOCK_NO_IDLE_PARENT	(1 << 2)
+#define ENABLE_ON_INIT		(1 << 3)	/* Enable upon framework init */
+#define INVERT_ENABLE		(1 << 4)	/* 0 enables, 1 disables */
+#define CLOCK_CLKOUTX2		(1 << 5)
+
+/**
+ * struct clk_hw_omap - OMAP struct clk
+ * @node: list_head connecting this clock into the full clock list
+ * @enable_reg: register to write to enable the clock (see @enable_bit)
+ * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
+ * @flags: see "struct clk.flags possibilities" above
+ * @clksel_reg: for clksel clks, register va containing src/divisor select
+ * @clksel_mask: bitmask in @clksel_reg for the src/divisor selector
+ * @clksel: for clksel clks, pointer to struct clksel for this clock
+ * @dpll_data: for DPLLs, pointer to struct dpll_data for this clock
+ * @clkdm_name: clockdomain name that this clock is contained in
+ * @clkdm: pointer to struct clockdomain, resolved from @clkdm_name at runtime
+ * @rate_offset: bitshift for rate selection bitfield (OMAP1 only)
+ * @src_offset: bitshift for source selection bitfield (OMAP1 only)
+ *
+ * XXX @rate_offset, @src_offset should probably be removed and OMAP1
+ * clock code converted to use clksel.
+ *
+ */
+
+struct clk_hw_omap_ops;
+
+struct clk_hw_omap {
+	struct clk_hw		hw;
+	struct list_head	node;
+	unsigned long		fixed_rate;
+	u8			fixed_div;
+	void __iomem		*enable_reg;
+	u8			enable_bit;
+	u8			flags;
+	void __iomem		*clksel_reg;
+	u32			clksel_mask;
+	const struct clksel	*clksel;
+	struct dpll_data	*dpll_data;
+	const char		*clkdm_name;
+	struct clockdomain	*clkdm;
+	const struct clk_hw_omap_ops	*ops;
+};
+
+struct clk_hw_omap_ops {
+	void			(*find_idlest)(struct clk_hw_omap *oclk,
+					void __iomem **idlest_reg,
+					u8 *idlest_bit, u8 *idlest_val);
+	void			(*find_companion)(struct clk_hw_omap *oclk,
+					void __iomem **other_reg,
+					u8 *other_bit);
+	void			(*allow_idle)(struct clk_hw_omap *oclk);
+	void			(*deny_idle)(struct clk_hw_omap *oclk);
+};
+
+unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
+					unsigned long parent_rate);
 
 /* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
 #define CORE_CLK_SRC_32K		0x0
@@ -49,84 +352,62 @@
 /* DPLL Type and DCO Selection Flags */
 #define DPLL_J_TYPE		0x1
 
-int omap2_clk_enable(struct clk *clk);
-void omap2_clk_disable(struct clk *clk);
-long omap2_clk_round_rate(struct clk *clk, unsigned long rate);
-int omap2_clk_set_rate(struct clk *clk, unsigned long rate);
-int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent);
-long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate);
-unsigned long omap3_dpll_recalc(struct clk *clk);
-unsigned long omap3_clkoutx2_recalc(struct clk *clk);
-void omap3_dpll_allow_idle(struct clk *clk);
-void omap3_dpll_deny_idle(struct clk *clk);
-u32 omap3_dpll_autoidle_read(struct clk *clk);
-int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate);
-int omap3_noncore_dpll_enable(struct clk *clk);
-void omap3_noncore_dpll_disable(struct clk *clk);
-int omap4_dpllmx_gatectrl_read(struct clk *clk);
-void omap4_dpllmx_allow_gatectrl(struct clk *clk);
-void omap4_dpllmx_deny_gatectrl(struct clk *clk);
-long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate);
-unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk);
-
-#ifdef CONFIG_OMAP_RESET_CLOCKS
-void omap2_clk_disable_unused(struct clk *clk);
-#else
-#define omap2_clk_disable_unused	NULL
-#endif
+long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
+			unsigned long *parent_rate);
+unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
+int omap3_noncore_dpll_enable(struct clk_hw *hw);
+void omap3_noncore_dpll_disable(struct clk_hw *hw);
+int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate);
+u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk);
+void omap3_dpll_allow_idle(struct clk_hw_omap *clk);
+void omap3_dpll_deny_idle(struct clk_hw_omap *clk);
+unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
+				    unsigned long parent_rate);
+int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk);
+void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk);
+void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk);
+unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
+				unsigned long parent_rate);
+long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
+				    unsigned long target_rate,
+				    unsigned long *parent_rate);
 
-void omap2_init_clk_clkdm(struct clk *clk);
+void omap2_init_clk_clkdm(struct clk_hw *clk);
 void __init omap2_clk_disable_clkdm_control(void);
 
 /* clkt_clksel.c public functions */
-u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
+u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
+				unsigned long target_rate,
 				u32 *new_div);
-void omap2_init_clksel_parent(struct clk *clk);
-unsigned long omap2_clksel_recalc(struct clk *clk);
-long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
-int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
-int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent);
+u8 omap2_clksel_find_parent_index(struct clk_hw *hw);
+unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate);
+long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
+				unsigned long *parent_rate);
+int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate);
+int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val);
 
 /* clkt_iclk.c public functions */
-extern void omap2_clkt_iclk_allow_idle(struct clk *clk);
-extern void omap2_clkt_iclk_deny_idle(struct clk *clk);
-
-u32 omap2_get_dpll_rate(struct clk *clk);
-void omap2_init_dpll_parent(struct clk *clk);
+extern void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk);
+extern void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk);
 
-int omap2_wait_clock_ready(void __iomem *reg, u32 cval, const char *name);
-
-
-#ifdef CONFIG_ARCH_OMAP2
-void omap2xxx_clk_prepare_for_reboot(void);
-#else
-static inline void omap2xxx_clk_prepare_for_reboot(void)
-{
-}
-#endif
+u8 omap2_init_dpll_parent(struct clk_hw *hw);
+unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk);
 
-#ifdef CONFIG_ARCH_OMAP3
-void omap3_clk_prepare_for_reboot(void);
-#else
-static inline void omap3_clk_prepare_for_reboot(void)
-{
-}
-#endif
-
-#ifdef CONFIG_ARCH_OMAP4
-void omap4_clk_prepare_for_reboot(void);
-#else
-static inline void omap4_clk_prepare_for_reboot(void)
-{
-}
-#endif
-
-int omap2_dflt_clk_enable(struct clk *clk);
-void omap2_dflt_clk_disable(struct clk *clk);
-void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
+int omap2_dflt_clk_enable(struct clk_hw *hw);
+void omap2_dflt_clk_disable(struct clk_hw *hw);
+int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
+void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
+				   void __iomem **other_reg,
 				   u8 *other_bit);
-void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
+void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
+				void __iomem **idlest_reg,
 				u8 *idlest_bit, u8 *idlest_val);
+void omap2_init_clk_hw_omap_clocks(struct clk *clk);
+int omap2_clk_enable_autoidle_all(void);
+int omap2_clk_disable_autoidle_all(void);
+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,
 			       const char *core_ck_name,
@@ -139,34 +420,43 @@ extern const struct clkops clkops_dummy;
 extern const struct clkops clkops_omap2_dflt;
 
 extern struct clk_functions omap2_clk_functions;
-extern struct clk *vclk, *sclk;
 
 extern const struct clksel_rate gpt_32k_rates[];
 extern const struct clksel_rate gpt_sys_rates[];
 extern const struct clksel_rate gfx_l3_rates[];
 extern const struct clksel_rate dsp_ick_rates[];
+extern struct clk dummy_ck;
 
-extern const struct clkops clkops_omap2_iclk_dflt_wait;
-extern const struct clkops clkops_omap2_iclk_dflt;
-extern const struct clkops clkops_omap2_iclk_idle_only;
-extern const struct clkops clkops_omap2_mdmclk_dflt_wait;
-extern const struct clkops clkops_omap2xxx_dpll_ops;
-extern const struct clkops clkops_omap3_noncore_dpll_ops;
-extern const struct clkops clkops_omap3_core_dpll_ops;
-extern const struct clkops clkops_omap4_dpllmx_ops;
+extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
+extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
+extern const struct clk_hw_omap_ops clkhwops_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
+extern const struct clk_hw_omap_ops clkhwops_iclk;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait;
+extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
+extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;
+extern const struct clk_hw_omap_ops clkhwops_apll54;
+extern const struct clk_hw_omap_ops clkhwops_apll96;
+extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
+extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait;
 
 /* clksel_rate blocks shared between OMAP44xx and AM33xx */
 extern const struct clksel_rate div_1_0_rates[];
+extern const struct clksel_rate div3_1to4_rates[];
 extern const struct clksel_rate div_1_1_rates[];
 extern const struct clksel_rate div_1_2_rates[];
 extern const struct clksel_rate div_1_3_rates[];
 extern const struct clksel_rate div_1_4_rates[];
 extern const struct clksel_rate div31_1to31_rates[];
 
-/* clocks shared between various OMAP SoCs */
-extern struct clk virt_19200000_ck;
-extern struct clk virt_26000000_ck;
-
 extern int am33xx_clk_init(void);
 
+extern int omap2_clkops_enable_clkdm(struct clk_hw *hw);
+extern void omap2_clkops_disable_clkdm(struct clk_hw *hw);
+
 #endif
diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
deleted file mode 100644
index c3cde1a..0000000
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ /dev/null
@@ -1,1990 +0,0 @@
-/*
- * OMAP2420 clock data
- *
- * Copyright (C) 2005-2009 Texas Instruments, Inc.
- * Copyright (C) 2004-2011 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/list.h>
-
-#include <plat/clkdev_omap.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "clock2xxx.h"
-#include "opp2xxx.h"
-#include "cm2xxx_3xxx.h"
-#include "prm2xxx_3xxx.h"
-#include "prm-regbits-24xx.h"
-#include "cm-regbits-24xx.h"
-#include "sdrc.h"
-#include "control.h"
-
-#define OMAP_CM_REGADDR                 OMAP2420_CM_REGADDR
-
-/*
- * 2420 clock tree.
- *
- * NOTE:In many cases here we are assigning a 'default' parent. In
- *	many cases the parent is selectable. The set parent calls will
- *	also switch sources.
- *
- *	Several sources are given initial rates which may be wrong, this will
- *	be fixed up in the init func.
- *
- *	Things are broadly separated below by clock domains. It is
- *	noteworthy that most peripherals have dependencies on multiple clock
- *	domains. Many get their interface clocks from the L4 domain, but get
- *	functional clocks from fixed sources or other core domain derived
- *	clocks.
- */
-
-/* Base external input clocks */
-static struct clk func_32k_ck = {
-	.name		= "func_32k_ck",
-	.ops		= &clkops_null,
-	.rate		= 32768,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-static struct clk secure_32k_ck = {
-	.name		= "secure_32k_ck",
-	.ops		= &clkops_null,
-	.rate		= 32768,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-/* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
-static struct clk osc_ck = {		/* (*12, *13, 19.2, *26, 38.4)MHz */
-	.name		= "osc_ck",
-	.ops		= &clkops_oscck,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &omap2_osc_clk_recalc,
-};
-
-/* Without modem likely 12MHz, with modem likely 13MHz */
-static struct clk sys_ck = {		/* (*12, *13, 19.2, 26, 38.4)MHz */
-	.name		= "sys_ck",		/* ~ ref_clk also */
-	.ops		= &clkops_null,
-	.parent		= &osc_ck,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &omap2xxx_sys_clk_recalc,
-};
-
-static struct clk alt_ck = {		/* Typical 54M or 48M, may not exist */
-	.name		= "alt_ck",
-	.ops		= &clkops_null,
-	.rate		= 54000000,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-/* Optional external clock input for McBSP CLKS */
-static struct clk mcbsp_clks = {
-	.name		= "mcbsp_clks",
-	.ops		= &clkops_null,
-};
-
-/*
- * Analog domain root source clocks
- */
-
-/* dpll_ck, is broken out in to special cases through clksel */
-/* REVISIT: Rate changes on dpll_ck trigger a full set change.	...
- * deal with this
- */
-
-static struct dpll_data dpll_dd = {
-	.mult_div1_reg		= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.mult_mask		= OMAP24XX_DPLL_MULT_MASK,
-	.div1_mask		= OMAP24XX_DPLL_DIV_MASK,
-	.clk_bypass		= &sys_ck,
-	.clk_ref		= &sys_ck,
-	.control_reg		= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_mask		= OMAP24XX_EN_DPLL_MASK,
-	.max_multiplier		= 1023,
-	.min_divider		= 1,
-	.max_divider		= 16,
-};
-
-/*
- * XXX Cannot add round_rate here yet, as this is still a composite clock,
- * not just a DPLL
- */
-static struct clk dpll_ck = {
-	.name		= "dpll_ck",
-	.ops		= &clkops_omap2xxx_dpll_ops,
-	.parent		= &sys_ck,		/* Can be func_32k also */
-	.dpll_data	= &dpll_dd,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &omap2_dpllcore_recalc,
-	.set_rate	= &omap2_reprogram_dpllcore,
-};
-
-static struct clk apll96_ck = {
-	.name		= "apll96_ck",
-	.ops		= &clkops_apll96,
-	.parent		= &sys_ck,
-	.rate		= 96000000,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_bit	= OMAP24XX_EN_96M_PLL_SHIFT,
-};
-
-static struct clk apll54_ck = {
-	.name		= "apll54_ck",
-	.ops		= &clkops_apll54,
-	.parent		= &sys_ck,
-	.rate		= 54000000,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_bit	= OMAP24XX_EN_54M_PLL_SHIFT,
-};
-
-/*
- * PRCM digital base sources
- */
-
-/* func_54m_ck */
-
-static const struct clksel_rate func_54m_apll54_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 },
-};
-
-static const struct clksel_rate func_54m_alt_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 },
-};
-
-static const struct clksel func_54m_clksel[] = {
-	{ .parent = &apll54_ck, .rates = func_54m_apll54_rates, },
-	{ .parent = &alt_ck,	.rates = func_54m_alt_rates, },
-	{ .parent = NULL },
-};
-
-static struct clk func_54m_ck = {
-	.name		= "func_54m_ck",
-	.ops		= &clkops_null,
-	.parent		= &apll54_ck,	/* can also be alt_clk */
-	.clkdm_name	= "wkup_clkdm",
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_54M_SOURCE_MASK,
-	.clksel		= func_54m_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk core_ck = {
-	.name		= "core_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll_ck,		/* can also be 32k */
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk func_96m_ck = {
-	.name		= "func_96m_ck",
-	.ops		= &clkops_null,
-	.parent		= &apll96_ck,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* func_48m_ck */
-
-static const struct clksel_rate func_48m_apll96_rates[] = {
-	{ .div = 2, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 },
-};
-
-static const struct clksel_rate func_48m_alt_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 },
-};
-
-static const struct clksel func_48m_clksel[] = {
-	{ .parent = &apll96_ck,	.rates = func_48m_apll96_rates },
-	{ .parent = &alt_ck, .rates = func_48m_alt_rates },
-	{ .parent = NULL }
-};
-
-static struct clk func_48m_ck = {
-	.name		= "func_48m_ck",
-	.ops		= &clkops_null,
-	.parent		= &apll96_ck,	 /* 96M or Alt */
-	.clkdm_name	= "wkup_clkdm",
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_48M_SOURCE_MASK,
-	.clksel		= func_48m_clksel,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
-};
-
-static struct clk func_12m_ck = {
-	.name		= "func_12m_ck",
-	.ops		= &clkops_null,
-	.parent		= &func_48m_ck,
-	.fixed_div	= 4,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-/* Secure timer, only available in secure mode */
-static struct clk wdt1_osc_ck = {
-	.name		= "ck_wdt1_osc",
-	.ops		= &clkops_null, /* RMK: missing? */
-	.parent		= &osc_ck,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * The common_clkout* clksel_rate structs are common to
- * sys_clkout, sys_clkout_src, sys_clkout2, and sys_clkout2_src.
- * sys_clkout2_* are 2420-only, so the
- * clksel_rate flags fields are inaccurate for those clocks. This is
- * harmless since access to those clocks are gated by the struct clk
- * flags fields, which mark them as 2420-only.
- */
-static const struct clksel_rate common_clkout_src_core_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_sys_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_96m_rates[] = {
-	{ .div = 1, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_54m_rates[] = {
-	{ .div = 1, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel common_clkout_src_clksel[] = {
-	{ .parent = &core_ck,	  .rates = common_clkout_src_core_rates },
-	{ .parent = &sys_ck,	  .rates = common_clkout_src_sys_rates },
-	{ .parent = &func_96m_ck, .rates = common_clkout_src_96m_rates },
-	{ .parent = &func_54m_ck, .rates = common_clkout_src_54m_rates },
-	{ .parent = NULL }
-};
-
-static struct clk sys_clkout_src = {
-	.name		= "sys_clkout_src",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &func_54m_ck,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP2420_PRCM_CLKOUT_CTRL,
-	.enable_bit	= OMAP24XX_CLKOUT_EN_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP2420_PRCM_CLKOUT_CTRL,
-	.clksel_mask	= OMAP24XX_CLKOUT_SOURCE_MASK,
-	.clksel		= common_clkout_src_clksel,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
-};
-
-static const struct clksel_rate common_clkout_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 8, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 16, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 0 },
-};
-
-static const struct clksel sys_clkout_clksel[] = {
-	{ .parent = &sys_clkout_src, .rates = common_clkout_rates },
-	{ .parent = NULL }
-};
-
-static struct clk sys_clkout = {
-	.name		= "sys_clkout",
-	.ops		= &clkops_null,
-	.parent		= &sys_clkout_src,
-	.clkdm_name	= "wkup_clkdm",
-	.clksel_reg	= OMAP2420_PRCM_CLKOUT_CTRL,
-	.clksel_mask	= OMAP24XX_CLKOUT_DIV_MASK,
-	.clksel		= sys_clkout_clksel,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
-};
-
-/* In 2430, new in 2420 ES2 */
-static struct clk sys_clkout2_src = {
-	.name		= "sys_clkout2_src",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &func_54m_ck,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP2420_PRCM_CLKOUT_CTRL,
-	.enable_bit	= OMAP2420_CLKOUT2_EN_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP2420_PRCM_CLKOUT_CTRL,
-	.clksel_mask	= OMAP2420_CLKOUT2_SOURCE_MASK,
-	.clksel		= common_clkout_src_clksel,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
-};
-
-static const struct clksel sys_clkout2_clksel[] = {
-	{ .parent = &sys_clkout2_src, .rates = common_clkout_rates },
-	{ .parent = NULL }
-};
-
-/* In 2430, new in 2420 ES2 */
-static struct clk sys_clkout2 = {
-	.name		= "sys_clkout2",
-	.ops		= &clkops_null,
-	.parent		= &sys_clkout2_src,
-	.clkdm_name	= "wkup_clkdm",
-	.clksel_reg	= OMAP2420_PRCM_CLKOUT_CTRL,
-	.clksel_mask	= OMAP2420_CLKOUT2_DIV_MASK,
-	.clksel		= sys_clkout2_clksel,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
-};
-
-static struct clk emul_ck = {
-	.name		= "emul_ck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &func_54m_ck,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP2420_PRCM_CLKEMUL_CTRL,
-	.enable_bit	= OMAP24XX_EMULATION_EN_SHIFT,
-	.recalc		= &followparent_recalc,
-
-};
-
-/*
- * MPU clock domain
- *	Clocks:
- *		MPU_FCLK, MPU_ICLK
- *		INT_M_FCLK, INT_M_I_CLK
- *
- * - Individual clocks are hardware managed.
- * - Base divider comes from: CM_CLKSEL_MPU
- *
- */
-static const struct clksel_rate mpu_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_242X },
-	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
-	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
-	{ .div = 0 },
-};
-
-static const struct clksel mpu_clksel[] = {
-	{ .parent = &core_ck, .rates = mpu_core_rates },
-	{ .parent = NULL }
-};
-
-static struct clk mpu_ck = {	/* Control cpu */
-	.name		= "mpu_ck",
-	.ops		= &clkops_null,
-	.parent		= &core_ck,
-	.clkdm_name	= "mpu_clkdm",
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP24XX_CLKSEL_MPU_MASK,
-	.clksel		= mpu_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/*
- * DSP (2420-UMA+IVA1) clock domain
- * Clocks:
- *	2420: UMA_FCLK, UMA_ICLK, IVA_MPU, IVA_COP
- *
- * Won't be too specific here. The core clock comes into this block
- * it is divided then tee'ed. One branch goes directly to xyz enable
- * controls. The other branch gets further divided by 2 then possibly
- * routed into a synchronizer and out of clocks abc.
- */
-static const struct clksel_rate dsp_fck_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
-	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
-	{ .div = 12, .val = 12, .flags = RATE_IN_242X },
-	{ .div = 0 },
-};
-
-static const struct clksel dsp_fck_clksel[] = {
-	{ .parent = &core_ck, .rates = dsp_fck_core_rates },
-	{ .parent = NULL }
-};
-
-static struct clk dsp_fck = {
-	.name		= "dsp_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_ck,
-	.clkdm_name	= "dsp_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP24XX_CLKSEL_DSP_MASK,
-	.clksel		= dsp_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel dsp_ick_clksel[] = {
-	{ .parent = &dsp_fck, .rates = dsp_ick_rates },
-	{ .parent = NULL }
-};
-
-static struct clk dsp_ick = {
-	.name		= "dsp_ick",	 /* apparently ipi and isp */
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &dsp_fck,
-	.clkdm_name	= "dsp_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP2420_EN_DSP_IPI_SHIFT,	      /* for ipi */
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
-	.clksel		= dsp_ick_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/*
- * The IVA1 is an ARM7 core on the 2420 that has nothing to do with
- * the C54x, but which is contained in the DSP powerdomain.  Does not
- * exist on later OMAPs.
- */
-static struct clk iva1_ifck = {
-	.name		= "iva1_ifck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_ck,
-	.clkdm_name	= "iva1_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP2420_EN_IVA_COP_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP2420_CLKSEL_IVA_MASK,
-	.clksel		= dsp_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* IVA1 mpu/int/i/f clocks are /2 of parent */
-static struct clk iva1_mpu_int_ifck = {
-	.name		= "iva1_mpu_int_ifck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &iva1_ifck,
-	.clkdm_name	= "iva1_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP2420_EN_IVA_MPU_SHIFT,
-	.fixed_div	= 2,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-/*
- * L3 clock domain
- * L3 clocks are used for both interface and functional clocks to
- * multiple entities. Some of these clocks are completely managed
- * by hardware, and some others allow software control. Hardware
- * managed ones general are based on directly CLK_REQ signals and
- * various auto idle settings. The functional spec sets many of these
- * as 'tie-high' for their enables.
- *
- * I-CLOCKS:
- *	L3-Interconnect, SMS, GPMC, SDRC, OCM_RAM, OCM_ROM, SDMA
- *	CAM, HS-USB.
- * F-CLOCK
- *	SSI.
- *
- * GPMC memories and SDRC have timing and clock sensitive registers which
- * may very well need notification when the clock changes. Currently for low
- * operating points, these are taken care of in sleep.S.
- */
-static const struct clksel_rate core_l3_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_242X },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 6, .val = 6, .flags = RATE_IN_24XX },
-	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
-	{ .div = 12, .val = 12, .flags = RATE_IN_242X },
-	{ .div = 16, .val = 16, .flags = RATE_IN_242X },
-	{ .div = 0 }
-};
-
-static const struct clksel core_l3_clksel[] = {
-	{ .parent = &core_ck, .rates = core_l3_core_rates },
-	{ .parent = NULL }
-};
-
-static struct clk core_l3_ck = {	/* Used for ick and fck, interconnect */
-	.name		= "core_l3_ck",
-	.ops		= &clkops_null,
-	.parent		= &core_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_CLKSEL_L3_MASK,
-	.clksel		= core_l3_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* usb_l4_ick */
-static const struct clksel_rate usb_l4_ick_core_l3_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel usb_l4_ick_clksel[] = {
-	{ .parent = &core_l3_ck, .rates = usb_l4_ick_core_l3_rates },
-	{ .parent = NULL },
-};
-
-/* It is unclear from TRM whether usb_l4_ick is really in L3 or L4 clkdm */
-static struct clk usb_l4_ick = {	/* FS-USB interface clock */
-	.name		= "usb_l4_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l3_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_CLKSEL_USB_MASK,
-	.clksel		= usb_l4_ick_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/*
- * L4 clock management domain
- *
- * This domain contains lots of interface clocks from the L4 interface, some
- * functional clocks.	Fixed APLL functional source clocks are managed in
- * this domain.
- */
-static const struct clksel_rate l4_core_l3_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel l4_clksel[] = {
-	{ .parent = &core_l3_ck, .rates = l4_core_l3_rates },
-	{ .parent = NULL }
-};
-
-static struct clk l4_ck = {		/* used both as an ick and fck */
-	.name		= "l4_ck",
-	.ops		= &clkops_null,
-	.parent		= &core_l3_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_CLKSEL_L4_MASK,
-	.clksel		= l4_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/*
- * SSI is in L3 management domain, its direct parent is core not l3,
- * many core power domain entities are grouped into the L3 clock
- * domain.
- * SSI_SSR_FCLK, SSI_SST_FCLK, SSI_L4_ICLK
- *
- * ssr = core/1/2/3/4/5, sst = 1/2 ssr.
- */
-static const struct clksel_rate ssi_ssr_sst_fck_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
-	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
-	{ .div = 0 }
-};
-
-static const struct clksel ssi_ssr_sst_fck_clksel[] = {
-	{ .parent = &core_ck, .rates = ssi_ssr_sst_fck_core_rates },
-	{ .parent = NULL }
-};
-
-static struct clk ssi_ssr_sst_fck = {
-	.name		= "ssi_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP24XX_EN_SSI_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_CLKSEL_SSI_MASK,
-	.clksel		= ssi_ssr_sst_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/*
- * Presumably this is the same as SSI_ICLK.
- * TRM contradicts itself on what clockdomain SSI_ICLK is in
- */
-static struct clk ssi_l4_ick = {
-	.name		= "ssi_l4_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP24XX_EN_SSI_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-
-/*
- * GFX clock domain
- *	Clocks:
- * GFX_FCLK, GFX_ICLK
- * GFX_CG1(2d), GFX_CG2(3d)
- *
- * GFX_FCLK runs from L3, and is divided by (1,2,3,4)
- * The 2d and 3d clocks run at a hardware determined
- * divided value of fclk.
- *
- */
-
-/* This clksel struct is shared between gfx_3d_fck and gfx_2d_fck */
-static const struct clksel gfx_fck_clksel[] = {
-	{ .parent = &core_l3_ck, .rates = gfx_l3_rates },
-	{ .parent = NULL },
-};
-
-static struct clk gfx_3d_fck = {
-	.name		= "gfx_3d_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_l3_ck,
-	.clkdm_name	= "gfx_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_EN_3D_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
-	.clksel		= gfx_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
-};
-
-static struct clk gfx_2d_fck = {
-	.name		= "gfx_2d_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_l3_ck,
-	.clkdm_name	= "gfx_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_EN_2D_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
-	.clksel		= gfx_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* This interface clock does not have a CM_AUTOIDLE bit */
-static struct clk gfx_ick = {
-	.name		= "gfx_ick",		/* From l3 */
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_l3_ck,
-	.clkdm_name	= "gfx_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP_EN_GFX_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * DSS clock domain
- * CLOCKs:
- * DSS_L4_ICLK, DSS_L3_ICLK,
- * DSS_CLK1, DSS_CLK2, DSS_54MHz_CLK
- *
- * DSS is both initiator and target.
- */
-/* XXX Add RATE_NOT_VALIDATED */
-
-static const struct clksel_rate dss1_fck_sys_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate dss1_fck_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 5, .val = 5, .flags = RATE_IN_24XX },
-	{ .div = 6, .val = 6, .flags = RATE_IN_24XX },
-	{ .div = 8, .val = 8, .flags = RATE_IN_24XX },
-	{ .div = 9, .val = 9, .flags = RATE_IN_24XX },
-	{ .div = 12, .val = 12, .flags = RATE_IN_24XX },
-	{ .div = 16, .val = 16, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel dss1_fck_clksel[] = {
-	{ .parent = &sys_ck,  .rates = dss1_fck_sys_rates },
-	{ .parent = &core_ck, .rates = dss1_fck_core_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dss_ick = {		/* Enables both L3,L4 ICLK's */
-	.name		= "dss_ick",
-	.ops		= &clkops_omap2_iclk_dflt,
-	.parent		= &l4_ck,	/* really both l3 and l4 */
-	.clkdm_name	= "dss_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dss1_fck = {
-	.name		= "dss1_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &core_ck,		/* Core or sys */
-	.clkdm_name	= "dss_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_CLKSEL_DSS1_MASK,
-	.clksel		= dss1_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate dss2_fck_sys_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate dss2_fck_48m_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel dss2_fck_clksel[] = {
-	{ .parent = &sys_ck,	  .rates = dss2_fck_sys_rates },
-	{ .parent = &func_48m_ck, .rates = dss2_fck_48m_rates },
-	{ .parent = NULL }
-};
-
-static struct clk dss2_fck = {		/* Alt clk used in power management */
-	.name		= "dss2_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &sys_ck,		/* fixed at sys_ck or 48MHz */
-	.clkdm_name	= "dss_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_DSS2_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_CLKSEL_DSS2_MASK,
-	.clksel		= dss2_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk dss_54m_fck = {	/* Alt clk used in power management */
-	.name		= "dss_54m_fck",	/* 54m tv clk */
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_54m_ck,
-	.clkdm_name	= "dss_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_TV_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wu_l4_ick = {
-	.name		= "wu_l4_ick",
-	.ops		= &clkops_null,
-	.parent		= &sys_ck,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * CORE power domain ICLK & FCLK defines.
- * Many of the these can have more than one possible parent. Entries
- * here will likely have an L4 interface parent, and may have multiple
- * functional clock parents.
- */
-static const struct clksel_rate gpt_alt_rates[] = {
-	{ .div = 1, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel omap24xx_gpt_clksel[] = {
-	{ .parent = &func_32k_ck, .rates = gpt_32k_rates },
-	{ .parent = &sys_ck,	  .rates = gpt_sys_rates },
-	{ .parent = &alt_ck,	  .rates = gpt_alt_rates },
-	{ .parent = NULL },
-};
-
-static struct clk gpt1_ick = {
-	.name		= "gpt1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wu_l4_ick,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt1_fck = {
-	.name		= "gpt1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT1_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
-};
-
-static struct clk gpt2_ick = {
-	.name		= "gpt2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt2_fck = {
-	.name		= "gpt2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT2_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt3_ick = {
-	.name		= "gpt3_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt3_fck = {
-	.name		= "gpt3_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT3_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt4_ick = {
-	.name		= "gpt4_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt4_fck = {
-	.name		= "gpt4_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT4_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt5_ick = {
-	.name		= "gpt5_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt5_fck = {
-	.name		= "gpt5_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT5_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt6_ick = {
-	.name		= "gpt6_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt6_fck = {
-	.name		= "gpt6_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT6_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt7_ick = {
-	.name		= "gpt7_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt7_fck = {
-	.name		= "gpt7_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT7_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt8_ick = {
-	.name		= "gpt8_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt8_fck = {
-	.name		= "gpt8_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT8_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt9_ick = {
-	.name		= "gpt9_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt9_fck = {
-	.name		= "gpt9_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT9_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt10_ick = {
-	.name		= "gpt10_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt10_fck = {
-	.name		= "gpt10_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT10_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt11_ick = {
-	.name		= "gpt11_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt11_fck = {
-	.name		= "gpt11_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT11_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt12_ick = {
-	.name		= "gpt12_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt12_fck = {
-	.name		= "gpt12_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &secure_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT12_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp1_ick = {
-	.name		= "mcbsp1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCBSP1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel_rate common_mcbsp_96m_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel mcbsp_fck_clksel[] = {
-	{ .parent = &func_96m_ck,  .rates = common_mcbsp_96m_rates },
-	{ .parent = &mcbsp_clks,   .rates = common_mcbsp_mcbsp_rates },
-	{ .parent = NULL }
-};
-
-static struct clk mcbsp1_fck = {
-	.name		= "mcbsp1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_96m_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCBSP1_SHIFT,
-	.clksel_reg	= OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
-	.clksel_mask	= OMAP2_MCBSP1_CLKS_MASK,
-	.clksel		= mcbsp_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp2_ick = {
-	.name		= "mcbsp2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCBSP2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcbsp2_fck = {
-	.name		= "mcbsp2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_96m_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCBSP2_SHIFT,
-	.clksel_reg	= OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
-	.clksel_mask	= OMAP2_MCBSP2_CLKS_MASK,
-	.clksel		= mcbsp_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk mcspi1_ick = {
-	.name		= "mcspi1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi1_fck = {
-	.name		= "mcspi1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_48m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi2_ick = {
-	.name		= "mcspi2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi2_fck = {
-	.name		= "mcspi2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_48m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart1_ick = {
-	.name		= "uart1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart1_fck = {
-	.name		= "uart1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_48m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart2_ick = {
-	.name		= "uart2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart2_fck = {
-	.name		= "uart2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_48m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart3_ick = {
-	.name		= "uart3_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart3_fck = {
-	.name		= "uart3_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_48m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpios_ick = {
-	.name		= "gpios_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wu_l4_ick,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpios_fck = {
-	.name		= "gpios_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mpu_wdt_ick = {
-	.name		= "mpu_wdt_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wu_l4_ick,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mpu_wdt_fck = {
-	.name		= "mpu_wdt_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk sync_32k_ick = {
-	.name		= "sync_32k_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wu_l4_ick,
-	.clkdm_name	= "wkup_clkdm",
-	.flags		= ENABLE_ON_INIT,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_32KSYNC_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wdt1_ick = {
-	.name		= "wdt1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wu_l4_ick,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_WDT1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk omapctrl_ick = {
-	.name		= "omapctrl_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wu_l4_ick,
-	.clkdm_name	= "wkup_clkdm",
-	.flags		= ENABLE_ON_INIT,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_OMAPCTRL_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk cam_ick = {
-	.name		= "cam_ick",
-	.ops		= &clkops_omap2_iclk_dflt,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * cam_fck controls both CAM_MCLK and CAM_FCLK.  It should probably be
- * split into two separate clocks, since the parent clocks are different
- * and the clockdomains are also different.
- */
-static struct clk cam_fck = {
-	.name		= "cam_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &func_96m_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mailboxes_ick = {
-	.name		= "mailboxes_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MAILBOXES_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wdt4_ick = {
-	.name		= "wdt4_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wdt4_fck = {
-	.name		= "wdt4_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wdt3_ick = {
-	.name		= "wdt3_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP2420_EN_WDT3_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wdt3_fck = {
-	.name		= "wdt3_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP2420_EN_WDT3_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mspro_ick = {
-	.name		= "mspro_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mspro_fck = {
-	.name		= "mspro_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_96m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmc_ick = {
-	.name		= "mmc_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP2420_EN_MMC_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmc_fck = {
-	.name		= "mmc_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_96m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP2420_EN_MMC_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk fac_ick = {
-	.name		= "fac_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk fac_fck = {
-	.name		= "fac_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_12m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk eac_ick = {
-	.name		= "eac_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP2420_EN_EAC_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk eac_fck = {
-	.name		= "eac_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_96m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP2420_EN_EAC_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk hdq_ick = {
-	.name		= "hdq_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk hdq_fck = {
-	.name		= "hdq_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_12m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk i2c2_ick = {
-	.name		= "i2c2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP2420_EN_I2C2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk i2c2_fck = {
-	.name		= "i2c2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_12m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP2420_EN_I2C2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk i2c1_ick = {
-	.name		= "i2c1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP2420_EN_I2C1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk i2c1_fck = {
-	.name		= "i2c1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_12m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP2420_EN_I2C1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
- * accesses derived from this data.
- */
-static struct clk gpmc_fck = {
-	.name		= "gpmc_fck",
-	.ops		= &clkops_omap2_iclk_idle_only,
-	.parent		= &core_l3_ck,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
-	.enable_bit	= OMAP24XX_AUTO_GPMC_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk sdma_fck = {
-	.name		= "sdma_fck",
-	.ops		= &clkops_null, /* RMK: missing? */
-	.parent		= &core_l3_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
- * accesses derived from this data.
- */
-static struct clk sdma_ick = {
-	.name		= "sdma_ick",
-	.ops		= &clkops_omap2_iclk_idle_only,
-	.parent		= &core_l3_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
-	.enable_bit	= OMAP24XX_AUTO_SDMA_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
- * accesses derived from this data.
- */
-static struct clk sdrc_ick = {
-	.name		= "sdrc_ick",
-	.ops		= &clkops_omap2_iclk_idle_only,
-	.parent		= &core_l3_ck,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
-	.enable_bit	= OMAP24XX_AUTO_SDRC_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk vlynq_ick = {
-	.name		= "vlynq_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l3_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP2420_EN_VLYNQ_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel_rate vlynq_fck_96m_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_242X },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate vlynq_fck_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_242X },
-	{ .div = 2, .val = 2, .flags = RATE_IN_242X },
-	{ .div = 3, .val = 3, .flags = RATE_IN_242X },
-	{ .div = 4, .val = 4, .flags = RATE_IN_242X },
-	{ .div = 6, .val = 6, .flags = RATE_IN_242X },
-	{ .div = 8, .val = 8, .flags = RATE_IN_242X },
-	{ .div = 9, .val = 9, .flags = RATE_IN_242X },
-	{ .div = 12, .val = 12, .flags = RATE_IN_242X },
-	{ .div = 16, .val = 16, .flags = RATE_IN_242X },
-	{ .div = 18, .val = 18, .flags = RATE_IN_242X },
-	{ .div = 0 }
-};
-
-static const struct clksel vlynq_fck_clksel[] = {
-	{ .parent = &func_96m_ck, .rates = vlynq_fck_96m_rates },
-	{ .parent = &core_ck,	  .rates = vlynq_fck_core_rates },
-	{ .parent = NULL }
-};
-
-static struct clk vlynq_fck = {
-	.name		= "vlynq_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_96m_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP2420_EN_VLYNQ_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP2420_CLKSEL_VLYNQ_MASK,
-	.clksel		= vlynq_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk des_ick = {
-	.name		= "des_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_DES_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk sha_ick = {
-	.name		= "sha_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_SHA_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk rng_ick = {
-	.name		= "rng_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_RNG_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk aes_ick = {
-	.name		= "aes_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_AES_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk pka_ick = {
-	.name		= "pka_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_PKA_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_fck = {
-	.name		= "usb_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_48m_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * This clock is a composite clock which does entire set changes then
- * forces a rebalance. It keys on the MPU speed, but it really could
- * be any key speed part of a set in the rate table.
- *
- * to really change a set, you need memory table sets which get changed
- * in sram, pre-notifiers & post notifiers, changing the top set, without
- * having low level display recalc's won't work... this is why dpm notifiers
- * work, isr's off, walk a list of clocks already _off_ and not messing with
- * the bus.
- *
- * This clock should have no parent. It embodies the entire upper level
- * active set. A parent will mess up some of the init also.
- */
-static struct clk virt_prcm_set = {
-	.name		= "virt_prcm_set",
-	.ops		= &clkops_null,
-	.parent		= &mpu_ck,	/* Indexed by mpu speed, no parent */
-	.recalc		= &omap2_table_mpu_recalc,	/* sets are keyed on mpu rate */
-	.set_rate	= &omap2_select_table_rate,
-	.round_rate	= &omap2_round_to_table_rate,
-};
-
-
-/*
- * clkdev integration
- */
-
-static struct omap_clk omap2420_clks[] = {
-	/* external root sources */
-	CLK(NULL,	"func_32k_ck",	&func_32k_ck,	CK_242X),
-	CLK(NULL,	"secure_32k_ck", &secure_32k_ck, CK_242X),
-	CLK(NULL,	"osc_ck",	&osc_ck,	CK_242X),
-	CLK(NULL,	"sys_ck",	&sys_ck,	CK_242X),
-	CLK(NULL,	"alt_ck",	&alt_ck,	CK_242X),
-	CLK(NULL,	"mcbsp_clks",	&mcbsp_clks,	CK_242X),
-	/* internal analog sources */
-	CLK(NULL,	"dpll_ck",	&dpll_ck,	CK_242X),
-	CLK(NULL,	"apll96_ck",	&apll96_ck,	CK_242X),
-	CLK(NULL,	"apll54_ck",	&apll54_ck,	CK_242X),
-	/* internal prcm root sources */
-	CLK(NULL,	"func_54m_ck",	&func_54m_ck,	CK_242X),
-	CLK(NULL,	"core_ck",	&core_ck,	CK_242X),
-	CLK(NULL,	"func_96m_ck",	&func_96m_ck,	CK_242X),
-	CLK(NULL,	"func_48m_ck",	&func_48m_ck,	CK_242X),
-	CLK(NULL,	"func_12m_ck",	&func_12m_ck,	CK_242X),
-	CLK(NULL,	"ck_wdt1_osc",	&wdt1_osc_ck,	CK_242X),
-	CLK(NULL,	"sys_clkout_src", &sys_clkout_src, CK_242X),
-	CLK(NULL,	"sys_clkout",	&sys_clkout,	CK_242X),
-	CLK(NULL,	"sys_clkout2_src", &sys_clkout2_src, CK_242X),
-	CLK(NULL,	"sys_clkout2",	&sys_clkout2,	CK_242X),
-	CLK(NULL,	"emul_ck",	&emul_ck,	CK_242X),
-	/* mpu domain clocks */
-	CLK(NULL,	"mpu_ck",	&mpu_ck,	CK_242X),
-	/* dsp domain clocks */
-	CLK(NULL,	"dsp_fck",	&dsp_fck,	CK_242X),
-	CLK(NULL,	"dsp_ick",	&dsp_ick,	CK_242X),
-	CLK(NULL,	"iva1_ifck",	&iva1_ifck,	CK_242X),
-	CLK(NULL,	"iva1_mpu_int_ifck", &iva1_mpu_int_ifck, CK_242X),
-	/* GFX domain clocks */
-	CLK(NULL,	"gfx_3d_fck",	&gfx_3d_fck,	CK_242X),
-	CLK(NULL,	"gfx_2d_fck",	&gfx_2d_fck,	CK_242X),
-	CLK(NULL,	"gfx_ick",	&gfx_ick,	CK_242X),
-	/* DSS domain clocks */
-	CLK("omapdss_dss",	"ick",		&dss_ick,	CK_242X),
-	CLK(NULL,	"dss_ick",		&dss_ick,	CK_242X),
-	CLK(NULL,	"dss1_fck",		&dss1_fck,	CK_242X),
-	CLK(NULL,	"dss2_fck",	&dss2_fck,	CK_242X),
-	CLK(NULL,	"dss_54m_fck",	&dss_54m_fck,	CK_242X),
-	/* L3 domain clocks */
-	CLK(NULL,	"core_l3_ck",	&core_l3_ck,	CK_242X),
-	CLK(NULL,	"ssi_fck",	&ssi_ssr_sst_fck, CK_242X),
-	CLK(NULL,	"usb_l4_ick",	&usb_l4_ick,	CK_242X),
-	/* L4 domain clocks */
-	CLK(NULL,	"l4_ck",	&l4_ck,		CK_242X),
-	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_242X),
-	CLK(NULL,	"wu_l4_ick",	&wu_l4_ick,	CK_242X),
-	/* virtual meta-group clock */
-	CLK(NULL,	"virt_prcm_set", &virt_prcm_set, CK_242X),
-	/* general l4 interface ck, multi-parent functional clk */
-	CLK(NULL,	"gpt1_ick",	&gpt1_ick,	CK_242X),
-	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_242X),
-	CLK(NULL,	"gpt2_ick",	&gpt2_ick,	CK_242X),
-	CLK(NULL,	"gpt2_fck",	&gpt2_fck,	CK_242X),
-	CLK(NULL,	"gpt3_ick",	&gpt3_ick,	CK_242X),
-	CLK(NULL,	"gpt3_fck",	&gpt3_fck,	CK_242X),
-	CLK(NULL,	"gpt4_ick",	&gpt4_ick,	CK_242X),
-	CLK(NULL,	"gpt4_fck",	&gpt4_fck,	CK_242X),
-	CLK(NULL,	"gpt5_ick",	&gpt5_ick,	CK_242X),
-	CLK(NULL,	"gpt5_fck",	&gpt5_fck,	CK_242X),
-	CLK(NULL,	"gpt6_ick",	&gpt6_ick,	CK_242X),
-	CLK(NULL,	"gpt6_fck",	&gpt6_fck,	CK_242X),
-	CLK(NULL,	"gpt7_ick",	&gpt7_ick,	CK_242X),
-	CLK(NULL,	"gpt7_fck",	&gpt7_fck,	CK_242X),
-	CLK(NULL,	"gpt8_ick",	&gpt8_ick,	CK_242X),
-	CLK(NULL,	"gpt8_fck",	&gpt8_fck,	CK_242X),
-	CLK(NULL,	"gpt9_ick",	&gpt9_ick,	CK_242X),
-	CLK(NULL,	"gpt9_fck",	&gpt9_fck,	CK_242X),
-	CLK(NULL,	"gpt10_ick",	&gpt10_ick,	CK_242X),
-	CLK(NULL,	"gpt10_fck",	&gpt10_fck,	CK_242X),
-	CLK(NULL,	"gpt11_ick",	&gpt11_ick,	CK_242X),
-	CLK(NULL,	"gpt11_fck",	&gpt11_fck,	CK_242X),
-	CLK(NULL,	"gpt12_ick",	&gpt12_ick,	CK_242X),
-	CLK(NULL,	"gpt12_fck",	&gpt12_fck,	CK_242X),
-	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick,	CK_242X),
-	CLK(NULL,	"mcbsp1_ick",	&mcbsp1_ick,	CK_242X),
-	CLK(NULL,	"mcbsp1_fck",	&mcbsp1_fck,	CK_242X),
-	CLK("omap-mcbsp.2", "ick",	&mcbsp2_ick,	CK_242X),
-	CLK(NULL,	"mcbsp2_ick",	&mcbsp2_ick,	CK_242X),
-	CLK(NULL,	"mcbsp2_fck",	&mcbsp2_fck,	CK_242X),
-	CLK("omap2_mcspi.1", "ick",	&mcspi1_ick,	CK_242X),
-	CLK(NULL,	"mcspi1_ick",	&mcspi1_ick,	CK_242X),
-	CLK(NULL,	"mcspi1_fck",	&mcspi1_fck,	CK_242X),
-	CLK("omap2_mcspi.2", "ick",	&mcspi2_ick,	CK_242X),
-	CLK(NULL,	"mcspi2_ick",	&mcspi2_ick,	CK_242X),
-	CLK(NULL,	"mcspi2_fck",	&mcspi2_fck,	CK_242X),
-	CLK(NULL,	"uart1_ick",	&uart1_ick,	CK_242X),
-	CLK(NULL,	"uart1_fck",	&uart1_fck,	CK_242X),
-	CLK(NULL,	"uart2_ick",	&uart2_ick,	CK_242X),
-	CLK(NULL,	"uart2_fck",	&uart2_fck,	CK_242X),
-	CLK(NULL,	"uart3_ick",	&uart3_ick,	CK_242X),
-	CLK(NULL,	"uart3_fck",	&uart3_fck,	CK_242X),
-	CLK(NULL,	"gpios_ick",	&gpios_ick,	CK_242X),
-	CLK(NULL,	"gpios_fck",	&gpios_fck,	CK_242X),
-	CLK("omap_wdt",	"ick",		&mpu_wdt_ick,	CK_242X),
-	CLK(NULL,	"mpu_wdt_ick",		&mpu_wdt_ick,	CK_242X),
-	CLK(NULL,	"mpu_wdt_fck",	&mpu_wdt_fck,	CK_242X),
-	CLK(NULL,	"sync_32k_ick",	&sync_32k_ick,	CK_242X),
-	CLK(NULL,	"wdt1_ick",	&wdt1_ick,	CK_242X),
-	CLK(NULL,	"omapctrl_ick",	&omapctrl_ick,	CK_242X),
-	CLK("omap24xxcam", "fck",	&cam_fck,	CK_242X),
-	CLK(NULL,	"cam_fck",	&cam_fck,	CK_242X),
-	CLK("omap24xxcam", "ick",	&cam_ick,	CK_242X),
-	CLK(NULL,	"cam_ick",	&cam_ick,	CK_242X),
-	CLK(NULL,	"mailboxes_ick", &mailboxes_ick,	CK_242X),
-	CLK(NULL,	"wdt4_ick",	&wdt4_ick,	CK_242X),
-	CLK(NULL,	"wdt4_fck",	&wdt4_fck,	CK_242X),
-	CLK(NULL,	"wdt3_ick",	&wdt3_ick,	CK_242X),
-	CLK(NULL,	"wdt3_fck",	&wdt3_fck,	CK_242X),
-	CLK(NULL,	"mspro_ick",	&mspro_ick,	CK_242X),
-	CLK(NULL,	"mspro_fck",	&mspro_fck,	CK_242X),
-	CLK("mmci-omap.0", "ick",	&mmc_ick,	CK_242X),
-	CLK(NULL,	"mmc_ick",	&mmc_ick,	CK_242X),
-	CLK("mmci-omap.0", "fck",	&mmc_fck,	CK_242X),
-	CLK(NULL,	"mmc_fck",	&mmc_fck,	CK_242X),
-	CLK(NULL,	"fac_ick",	&fac_ick,	CK_242X),
-	CLK(NULL,	"fac_fck",	&fac_fck,	CK_242X),
-	CLK(NULL,	"eac_ick",	&eac_ick,	CK_242X),
-	CLK(NULL,	"eac_fck",	&eac_fck,	CK_242X),
-	CLK("omap_hdq.0", "ick",	&hdq_ick,	CK_242X),
-	CLK(NULL,	"hdq_ick",	&hdq_ick,	CK_242X),
-	CLK("omap_hdq.0", "fck",	&hdq_fck,	CK_242X),
-	CLK(NULL,	"hdq_fck",	&hdq_fck,	CK_242X),
-	CLK("omap_i2c.1", "ick",	&i2c1_ick,	CK_242X),
-	CLK(NULL,	"i2c1_ick",	&i2c1_ick,	CK_242X),
-	CLK(NULL,	"i2c1_fck",	&i2c1_fck,	CK_242X),
-	CLK("omap_i2c.2", "ick",	&i2c2_ick,	CK_242X),
-	CLK(NULL,	"i2c2_ick",	&i2c2_ick,	CK_242X),
-	CLK(NULL,	"i2c2_fck",	&i2c2_fck,	CK_242X),
-	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_242X),
-	CLK(NULL,	"sdma_fck",	&sdma_fck,	CK_242X),
-	CLK(NULL,	"sdma_ick",	&sdma_ick,	CK_242X),
-	CLK(NULL,	"sdrc_ick",	&sdrc_ick,	CK_242X),
-	CLK(NULL,	"vlynq_ick",	&vlynq_ick,	CK_242X),
-	CLK(NULL,	"vlynq_fck",	&vlynq_fck,	CK_242X),
-	CLK(NULL,	"des_ick",	&des_ick,	CK_242X),
-	CLK("omap-sham",	"ick",	&sha_ick,	CK_242X),
-	CLK(NULL,	"sha_ick",	&sha_ick,	CK_242X),
-	CLK("omap_rng",	"ick",		&rng_ick,	CK_242X),
-	CLK(NULL,	"rng_ick",		&rng_ick,	CK_242X),
-	CLK("omap-aes",	"ick",	&aes_ick,	CK_242X),
-	CLK(NULL,	"aes_ick",	&aes_ick,	CK_242X),
-	CLK(NULL,	"pka_ick",	&pka_ick,	CK_242X),
-	CLK(NULL,	"usb_fck",	&usb_fck,	CK_242X),
-	CLK("musb-hdrc",	"fck",	&osc_ck,	CK_242X),
-	CLK(NULL,	"timer_32k_ck",	&func_32k_ck,	CK_242X),
-	CLK(NULL,	"timer_sys_ck",	&sys_ck,	CK_242X),
-	CLK(NULL,	"timer_ext_ck",	&alt_ck,	CK_242X),
-	CLK(NULL,	"cpufreq_ck",	&virt_prcm_set,	CK_242X),
-};
-
-/*
- * init code
- */
-
-int __init omap2420_clk_init(void)
-{
-	const struct prcm_config *prcm;
-	struct omap_clk *c;
-	u32 clkrate;
-
-	prcm_clksrc_ctrl = OMAP2420_PRCM_CLKSRC_CTRL;
-	cm_idlest_pll = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST);
-	cpu_mask = RATE_IN_242X;
-	rate_table = omap2420_rate_table;
-
-	clk_init(&omap2_clk_functions);
-
-	for (c = omap2420_clks; c < omap2420_clks + ARRAY_SIZE(omap2420_clks);
-	     c++)
-		clk_preinit(c->lk.clk);
-
-	osc_ck.rate = omap2_osc_clk_recalc(&osc_ck);
-	propagate_rate(&osc_ck);
-	sys_ck.rate = omap2xxx_sys_clk_recalc(&sys_ck);
-	propagate_rate(&sys_ck);
-
-	for (c = omap2420_clks; c < omap2420_clks + ARRAY_SIZE(omap2420_clks);
-	     c++) {
-		clkdev_add(&c->lk);
-		clk_register(c->lk.clk);
-		omap2_init_clk_clkdm(c->lk.clk);
-	}
-
-	/* Disable autoidle on all clocks; let the PM code enable it later */
-	omap_clk_disable_autoidle_all();
-
-	/* Check the MPU rate set by bootloader */
-	clkrate = omap2xxx_clk_get_core_rate(&dpll_ck);
-	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
-		if (!(prcm->flags & cpu_mask))
-			continue;
-		if (prcm->xtal_speed != sys_ck.rate)
-			continue;
-		if (prcm->dpll_speed <= clkrate)
-			break;
-	}
-	curr_prcm_set = prcm;
-
-	recalculate_root_clocks();
-
-	pr_info("Clocking rate (Crystal/DPLL/MPU): %ld.%01ld/%ld/%ld MHz\n",
-		(sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
-		(dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
-
-	/*
-	 * Only enable those clocks we will need, let the drivers
-	 * enable other clocks as necessary
-	 */
-	clk_enable_init_clocks();
-
-	/* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
-	vclk = clk_get(NULL, "virt_prcm_set");
-	sclk = clk_get(NULL, "sys_ck");
-	dclk = clk_get(NULL, "dpll_ck");
-
-	return 0;
-}
-
diff --git a/arch/arm/mach-omap2/clock2430.c b/arch/arm/mach-omap2/clock2430.c
index a8e3261..cef0c8d 100644
--- a/arch/arm/mach-omap2/clock2430.c
+++ b/arch/arm/mach-omap2/clock2430.c
@@ -21,13 +21,11 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/clock.h>
-
 #include "soc.h"
 #include "iomap.h"
 #include "clock.h"
 #include "clock2xxx.h"
-#include "cm2xxx_3xxx.h"
+#include "cm2xxx.h"
 #include "cm-regbits-24xx.h"
 
 /**
@@ -42,7 +40,7 @@
  * passes back the correct CM_IDLEST register address for I2CHS
  * modules.  No return value.
  */
-static void omap2430_clk_i2chs_find_idlest(struct clk *clk,
+static void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk,
 					   void __iomem **idlest_reg,
 					   u8 *idlest_bit,
 					   u8 *idlest_val)
@@ -53,9 +51,7 @@ static void omap2430_clk_i2chs_find_idlest(struct clk *clk,
 }
 
 /* 2430 I2CHS has non-standard IDLEST register */
-const struct clkops clkops_omap2430_i2chs_wait = {
-	.enable		= omap2_dflt_clk_enable,
-	.disable	= omap2_dflt_clk_disable,
+const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait = {
 	.find_idlest	= omap2430_clk_i2chs_find_idlest,
-	.find_companion = omap2_clk_dflt_find_companion,
+	.find_companion	= omap2_clk_dflt_find_companion,
 };
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
deleted file mode 100644
index 22404fe..0000000
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ /dev/null
@@ -1,2089 +0,0 @@
-/*
- * OMAP2430 clock data
- *
- * Copyright (C) 2005-2009 Texas Instruments, Inc.
- * Copyright (C) 2004-2011 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/list.h>
-
-#include <plat/clkdev_omap.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "clock2xxx.h"
-#include "opp2xxx.h"
-#include "cm2xxx_3xxx.h"
-#include "prm2xxx_3xxx.h"
-#include "prm-regbits-24xx.h"
-#include "cm-regbits-24xx.h"
-#include "sdrc.h"
-#include "control.h"
-
-#define OMAP_CM_REGADDR			OMAP2430_CM_REGADDR
-
-/*
- * 2430 clock tree.
- *
- * NOTE:In many cases here we are assigning a 'default' parent. In
- *	many cases the parent is selectable. The set parent calls will
- *	also switch sources.
- *
- *	Several sources are given initial rates which may be wrong, this will
- *	be fixed up in the init func.
- *
- *	Things are broadly separated below by clock domains. It is
- *	noteworthy that most peripherals have dependencies on multiple clock
- *	domains. Many get their interface clocks from the L4 domain, but get
- *	functional clocks from fixed sources or other core domain derived
- *	clocks.
- */
-
-/* Base external input clocks */
-static struct clk func_32k_ck = {
-	.name		= "func_32k_ck",
-	.ops		= &clkops_null,
-	.rate		= 32768,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-static struct clk secure_32k_ck = {
-	.name		= "secure_32k_ck",
-	.ops		= &clkops_null,
-	.rate		= 32768,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-/* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
-static struct clk osc_ck = {		/* (*12, *13, 19.2, *26, 38.4)MHz */
-	.name		= "osc_ck",
-	.ops		= &clkops_oscck,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &omap2_osc_clk_recalc,
-};
-
-/* Without modem likely 12MHz, with modem likely 13MHz */
-static struct clk sys_ck = {		/* (*12, *13, 19.2, 26, 38.4)MHz */
-	.name		= "sys_ck",		/* ~ ref_clk also */
-	.ops		= &clkops_null,
-	.parent		= &osc_ck,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &omap2xxx_sys_clk_recalc,
-};
-
-static struct clk alt_ck = {		/* Typical 54M or 48M, may not exist */
-	.name		= "alt_ck",
-	.ops		= &clkops_null,
-	.rate		= 54000000,
-	.clkdm_name	= "wkup_clkdm",
-};
-
-/* Optional external clock input for McBSP CLKS */
-static struct clk mcbsp_clks = {
-	.name		= "mcbsp_clks",
-	.ops		= &clkops_null,
-};
-
-/*
- * Analog domain root source clocks
- */
-
-/* dpll_ck, is broken out in to special cases through clksel */
-/* REVISIT: Rate changes on dpll_ck trigger a full set change.	...
- * deal with this
- */
-
-static struct dpll_data dpll_dd = {
-	.mult_div1_reg		= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.mult_mask		= OMAP24XX_DPLL_MULT_MASK,
-	.div1_mask		= OMAP24XX_DPLL_DIV_MASK,
-	.clk_bypass		= &sys_ck,
-	.clk_ref		= &sys_ck,
-	.control_reg		= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_mask		= OMAP24XX_EN_DPLL_MASK,
-	.max_multiplier		= 1023,
-	.min_divider		= 1,
-	.max_divider		= 16,
-};
-
-/*
- * XXX Cannot add round_rate here yet, as this is still a composite clock,
- * not just a DPLL
- */
-static struct clk dpll_ck = {
-	.name		= "dpll_ck",
-	.ops		= &clkops_omap2xxx_dpll_ops,
-	.parent		= &sys_ck,		/* Can be func_32k also */
-	.dpll_data	= &dpll_dd,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &omap2_dpllcore_recalc,
-	.set_rate	= &omap2_reprogram_dpllcore,
-};
-
-static struct clk apll96_ck = {
-	.name		= "apll96_ck",
-	.ops		= &clkops_apll96,
-	.parent		= &sys_ck,
-	.rate		= 96000000,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_bit	= OMAP24XX_EN_96M_PLL_SHIFT,
-};
-
-static struct clk apll54_ck = {
-	.name		= "apll54_ck",
-	.ops		= &clkops_apll54,
-	.parent		= &sys_ck,
-	.rate		= 54000000,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_bit	= OMAP24XX_EN_54M_PLL_SHIFT,
-};
-
-/*
- * PRCM digital base sources
- */
-
-/* func_54m_ck */
-
-static const struct clksel_rate func_54m_apll54_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 },
-};
-
-static const struct clksel_rate func_54m_alt_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 },
-};
-
-static const struct clksel func_54m_clksel[] = {
-	{ .parent = &apll54_ck, .rates = func_54m_apll54_rates, },
-	{ .parent = &alt_ck,	.rates = func_54m_alt_rates, },
-	{ .parent = NULL },
-};
-
-static struct clk func_54m_ck = {
-	.name		= "func_54m_ck",
-	.ops		= &clkops_null,
-	.parent		= &apll54_ck,	/* can also be alt_clk */
-	.clkdm_name	= "wkup_clkdm",
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_54M_SOURCE_MASK,
-	.clksel		= func_54m_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk core_ck = {
-	.name		= "core_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll_ck,		/* can also be 32k */
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* func_96m_ck */
-static const struct clksel_rate func_96m_apll96_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 },
-};
-
-static const struct clksel_rate func_96m_alt_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_243X },
-	{ .div = 0 },
-};
-
-static const struct clksel func_96m_clksel[] = {
-	{ .parent = &apll96_ck,	.rates = func_96m_apll96_rates },
-	{ .parent = &alt_ck,	.rates = func_96m_alt_rates },
-	{ .parent = NULL }
-};
-
-static struct clk func_96m_ck = {
-	.name		= "func_96m_ck",
-	.ops		= &clkops_null,
-	.parent		= &apll96_ck,
-	.clkdm_name	= "wkup_clkdm",
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP2430_96M_SOURCE_MASK,
-	.clksel		= func_96m_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* func_48m_ck */
-
-static const struct clksel_rate func_48m_apll96_rates[] = {
-	{ .div = 2, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 },
-};
-
-static const struct clksel_rate func_48m_alt_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 },
-};
-
-static const struct clksel func_48m_clksel[] = {
-	{ .parent = &apll96_ck,	.rates = func_48m_apll96_rates },
-	{ .parent = &alt_ck, .rates = func_48m_alt_rates },
-	{ .parent = NULL }
-};
-
-static struct clk func_48m_ck = {
-	.name		= "func_48m_ck",
-	.ops		= &clkops_null,
-	.parent		= &apll96_ck,	 /* 96M or Alt */
-	.clkdm_name	= "wkup_clkdm",
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_48M_SOURCE_MASK,
-	.clksel		= func_48m_clksel,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
-};
-
-static struct clk func_12m_ck = {
-	.name		= "func_12m_ck",
-	.ops		= &clkops_null,
-	.parent		= &func_48m_ck,
-	.fixed_div	= 4,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-/* Secure timer, only available in secure mode */
-static struct clk wdt1_osc_ck = {
-	.name		= "ck_wdt1_osc",
-	.ops		= &clkops_null, /* RMK: missing? */
-	.parent		= &osc_ck,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * The common_clkout* clksel_rate structs are common to
- * sys_clkout, sys_clkout_src, sys_clkout2, and sys_clkout2_src.
- * sys_clkout2_* are 2420-only, so the
- * clksel_rate flags fields are inaccurate for those clocks. This is
- * harmless since access to those clocks are gated by the struct clk
- * flags fields, which mark them as 2420-only.
- */
-static const struct clksel_rate common_clkout_src_core_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_sys_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_96m_rates[] = {
-	{ .div = 1, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_54m_rates[] = {
-	{ .div = 1, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel common_clkout_src_clksel[] = {
-	{ .parent = &core_ck,	  .rates = common_clkout_src_core_rates },
-	{ .parent = &sys_ck,	  .rates = common_clkout_src_sys_rates },
-	{ .parent = &func_96m_ck, .rates = common_clkout_src_96m_rates },
-	{ .parent = &func_54m_ck, .rates = common_clkout_src_54m_rates },
-	{ .parent = NULL }
-};
-
-static struct clk sys_clkout_src = {
-	.name		= "sys_clkout_src",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &func_54m_ck,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP2430_PRCM_CLKOUT_CTRL,
-	.enable_bit	= OMAP24XX_CLKOUT_EN_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP2430_PRCM_CLKOUT_CTRL,
-	.clksel_mask	= OMAP24XX_CLKOUT_SOURCE_MASK,
-	.clksel		= common_clkout_src_clksel,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
-};
-
-static const struct clksel_rate common_clkout_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 8, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 16, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 0 },
-};
-
-static const struct clksel sys_clkout_clksel[] = {
-	{ .parent = &sys_clkout_src, .rates = common_clkout_rates },
-	{ .parent = NULL }
-};
-
-static struct clk sys_clkout = {
-	.name		= "sys_clkout",
-	.ops		= &clkops_null,
-	.parent		= &sys_clkout_src,
-	.clkdm_name	= "wkup_clkdm",
-	.clksel_reg	= OMAP2430_PRCM_CLKOUT_CTRL,
-	.clksel_mask	= OMAP24XX_CLKOUT_DIV_MASK,
-	.clksel		= sys_clkout_clksel,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
-};
-
-static struct clk emul_ck = {
-	.name		= "emul_ck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &func_54m_ck,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP2430_PRCM_CLKEMUL_CTRL,
-	.enable_bit	= OMAP24XX_EMULATION_EN_SHIFT,
-	.recalc		= &followparent_recalc,
-
-};
-
-/*
- * MPU clock domain
- *	Clocks:
- *		MPU_FCLK, MPU_ICLK
- *		INT_M_FCLK, INT_M_I_CLK
- *
- * - Individual clocks are hardware managed.
- * - Base divider comes from: CM_CLKSEL_MPU
- *
- */
-static const struct clksel_rate mpu_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 0 },
-};
-
-static const struct clksel mpu_clksel[] = {
-	{ .parent = &core_ck, .rates = mpu_core_rates },
-	{ .parent = NULL }
-};
-
-static struct clk mpu_ck = {	/* Control cpu */
-	.name		= "mpu_ck",
-	.ops		= &clkops_null,
-	.parent		= &core_ck,
-	.clkdm_name	= "mpu_clkdm",
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP24XX_CLKSEL_MPU_MASK,
-	.clksel		= mpu_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/*
- * DSP (2430-IVA2.1) clock domain
- * Clocks:
- *	2430: IVA2.1_FCLK (really just DSP_FCLK), IVA2.1_ICLK
- *
- * Won't be too specific here. The core clock comes into this block
- * it is divided then tee'ed. One branch goes directly to xyz enable
- * controls. The other branch gets further divided by 2 then possibly
- * routed into a synchronizer and out of clocks abc.
- */
-static const struct clksel_rate dsp_fck_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 0 },
-};
-
-static const struct clksel dsp_fck_clksel[] = {
-	{ .parent = &core_ck, .rates = dsp_fck_core_rates },
-	{ .parent = NULL }
-};
-
-static struct clk dsp_fck = {
-	.name		= "dsp_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_ck,
-	.clkdm_name	= "dsp_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP24XX_CLKSEL_DSP_MASK,
-	.clksel		= dsp_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel dsp_ick_clksel[] = {
-	{ .parent = &dsp_fck, .rates = dsp_ick_rates },
-	{ .parent = NULL }
-};
-
-/* 2430 only - EN_DSP controls both dsp fclk and iclk on 2430 */
-static struct clk iva2_1_ick = {
-	.name		= "iva2_1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &dsp_fck,
-	.clkdm_name	= "dsp_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
-	.clksel		= dsp_ick_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/*
- * L3 clock domain
- * L3 clocks are used for both interface and functional clocks to
- * multiple entities. Some of these clocks are completely managed
- * by hardware, and some others allow software control. Hardware
- * managed ones general are based on directly CLK_REQ signals and
- * various auto idle settings. The functional spec sets many of these
- * as 'tie-high' for their enables.
- *
- * I-CLOCKS:
- *	L3-Interconnect, SMS, GPMC, SDRC, OCM_RAM, OCM_ROM, SDMA
- *	CAM, HS-USB.
- * F-CLOCK
- *	SSI.
- *
- * GPMC memories and SDRC have timing and clock sensitive registers which
- * may very well need notification when the clock changes. Currently for low
- * operating points, these are taken care of in sleep.S.
- */
-static const struct clksel_rate core_l3_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 6, .val = 6, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel core_l3_clksel[] = {
-	{ .parent = &core_ck, .rates = core_l3_core_rates },
-	{ .parent = NULL }
-};
-
-static struct clk core_l3_ck = {	/* Used for ick and fck, interconnect */
-	.name		= "core_l3_ck",
-	.ops		= &clkops_null,
-	.parent		= &core_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_CLKSEL_L3_MASK,
-	.clksel		= core_l3_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* usb_l4_ick */
-static const struct clksel_rate usb_l4_ick_core_l3_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel usb_l4_ick_clksel[] = {
-	{ .parent = &core_l3_ck, .rates = usb_l4_ick_core_l3_rates },
-	{ .parent = NULL },
-};
-
-/* It is unclear from TRM whether usb_l4_ick is really in L3 or L4 clkdm */
-static struct clk usb_l4_ick = {	/* FS-USB interface clock */
-	.name		= "usb_l4_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l3_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_CLKSEL_USB_MASK,
-	.clksel		= usb_l4_ick_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/*
- * L4 clock management domain
- *
- * This domain contains lots of interface clocks from the L4 interface, some
- * functional clocks.	Fixed APLL functional source clocks are managed in
- * this domain.
- */
-static const struct clksel_rate l4_core_l3_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel l4_clksel[] = {
-	{ .parent = &core_l3_ck, .rates = l4_core_l3_rates },
-	{ .parent = NULL }
-};
-
-static struct clk l4_ck = {		/* used both as an ick and fck */
-	.name		= "l4_ck",
-	.ops		= &clkops_null,
-	.parent		= &core_l3_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_CLKSEL_L4_MASK,
-	.clksel		= l4_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/*
- * SSI is in L3 management domain, its direct parent is core not l3,
- * many core power domain entities are grouped into the L3 clock
- * domain.
- * SSI_SSR_FCLK, SSI_SST_FCLK, SSI_L4_ICLK
- *
- * ssr = core/1/2/3/4/5, sst = 1/2 ssr.
- */
-static const struct clksel_rate ssi_ssr_sst_fck_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 5, .val = 5, .flags = RATE_IN_243X },
-	{ .div = 0 }
-};
-
-static const struct clksel ssi_ssr_sst_fck_clksel[] = {
-	{ .parent = &core_ck, .rates = ssi_ssr_sst_fck_core_rates },
-	{ .parent = NULL }
-};
-
-static struct clk ssi_ssr_sst_fck = {
-	.name		= "ssi_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP24XX_EN_SSI_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_CLKSEL_SSI_MASK,
-	.clksel		= ssi_ssr_sst_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/*
- * Presumably this is the same as SSI_ICLK.
- * TRM contradicts itself on what clockdomain SSI_ICLK is in
- */
-static struct clk ssi_l4_ick = {
-	.name		= "ssi_l4_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP24XX_EN_SSI_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-
-/*
- * GFX clock domain
- *	Clocks:
- * GFX_FCLK, GFX_ICLK
- * GFX_CG1(2d), GFX_CG2(3d)
- *
- * GFX_FCLK runs from L3, and is divided by (1,2,3,4)
- * The 2d and 3d clocks run at a hardware determined
- * divided value of fclk.
- *
- */
-
-/* This clksel struct is shared between gfx_3d_fck and gfx_2d_fck */
-static const struct clksel gfx_fck_clksel[] = {
-	{ .parent = &core_l3_ck, .rates = gfx_l3_rates },
-	{ .parent = NULL },
-};
-
-static struct clk gfx_3d_fck = {
-	.name		= "gfx_3d_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_l3_ck,
-	.clkdm_name	= "gfx_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_EN_3D_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
-	.clksel		= gfx_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
-};
-
-static struct clk gfx_2d_fck = {
-	.name		= "gfx_2d_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_l3_ck,
-	.clkdm_name	= "gfx_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_EN_2D_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
-	.clksel		= gfx_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* This interface clock does not have a CM_AUTOIDLE bit */
-static struct clk gfx_ick = {
-	.name		= "gfx_ick",		/* From l3 */
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_l3_ck,
-	.clkdm_name	= "gfx_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP_EN_GFX_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * Modem clock domain (2430)
- *	CLOCKS:
- *		MDM_OSC_CLK
- *		MDM_ICLK
- * These clocks are usable in chassis mode only.
- */
-static const struct clksel_rate mdm_ick_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_243X },
-	{ .div = 4, .val = 4, .flags = RATE_IN_243X },
-	{ .div = 6, .val = 6, .flags = RATE_IN_243X },
-	{ .div = 9, .val = 9, .flags = RATE_IN_243X },
-	{ .div = 0 }
-};
-
-static const struct clksel mdm_ick_clksel[] = {
-	{ .parent = &core_ck, .rates = mdm_ick_core_rates },
-	{ .parent = NULL }
-};
-
-static struct clk mdm_ick = {		/* used both as a ick and fck */
-	.name		= "mdm_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_ck,
-	.clkdm_name	= "mdm_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP2430_CLKSEL_MDM_MASK,
-	.clksel		= mdm_ick_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk mdm_osc_ck = {
-	.name		= "mdm_osc_ck",
-	.ops		= &clkops_omap2_mdmclk_dflt_wait,
-	.parent		= &osc_ck,
-	.clkdm_name	= "mdm_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP2430_EN_OSC_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * DSS clock domain
- * CLOCKs:
- * DSS_L4_ICLK, DSS_L3_ICLK,
- * DSS_CLK1, DSS_CLK2, DSS_54MHz_CLK
- *
- * DSS is both initiator and target.
- */
-/* XXX Add RATE_NOT_VALIDATED */
-
-static const struct clksel_rate dss1_fck_sys_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate dss1_fck_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_24XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_24XX },
-	{ .div = 5, .val = 5, .flags = RATE_IN_24XX },
-	{ .div = 6, .val = 6, .flags = RATE_IN_24XX },
-	{ .div = 8, .val = 8, .flags = RATE_IN_24XX },
-	{ .div = 9, .val = 9, .flags = RATE_IN_24XX },
-	{ .div = 12, .val = 12, .flags = RATE_IN_24XX },
-	{ .div = 16, .val = 16, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel dss1_fck_clksel[] = {
-	{ .parent = &sys_ck,  .rates = dss1_fck_sys_rates },
-	{ .parent = &core_ck, .rates = dss1_fck_core_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dss_ick = {		/* Enables both L3,L4 ICLK's */
-	.name		= "dss_ick",
-	.ops		= &clkops_omap2_iclk_dflt,
-	.parent		= &l4_ck,	/* really both l3 and l4 */
-	.clkdm_name	= "dss_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dss1_fck = {
-	.name		= "dss1_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &core_ck,		/* Core or sys */
-	.clkdm_name	= "dss_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_CLKSEL_DSS1_MASK,
-	.clksel		= dss1_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate dss2_fck_sys_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate dss2_fck_48m_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel dss2_fck_clksel[] = {
-	{ .parent = &sys_ck,	  .rates = dss2_fck_sys_rates },
-	{ .parent = &func_48m_ck, .rates = dss2_fck_48m_rates },
-	{ .parent = NULL }
-};
-
-static struct clk dss2_fck = {		/* Alt clk used in power management */
-	.name		= "dss2_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &sys_ck,		/* fixed at sys_ck or 48MHz */
-	.clkdm_name	= "dss_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_DSS2_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_CLKSEL_DSS2_MASK,
-	.clksel		= dss2_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk dss_54m_fck = {	/* Alt clk used in power management */
-	.name		= "dss_54m_fck",	/* 54m tv clk */
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_54m_ck,
-	.clkdm_name	= "dss_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_TV_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wu_l4_ick = {
-	.name		= "wu_l4_ick",
-	.ops		= &clkops_null,
-	.parent		= &sys_ck,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * CORE power domain ICLK & FCLK defines.
- * Many of the these can have more than one possible parent. Entries
- * here will likely have an L4 interface parent, and may have multiple
- * functional clock parents.
- */
-static const struct clksel_rate gpt_alt_rates[] = {
-	{ .div = 1, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel omap24xx_gpt_clksel[] = {
-	{ .parent = &func_32k_ck, .rates = gpt_32k_rates },
-	{ .parent = &sys_ck,	  .rates = gpt_sys_rates },
-	{ .parent = &alt_ck,	  .rates = gpt_alt_rates },
-	{ .parent = NULL },
-};
-
-static struct clk gpt1_ick = {
-	.name		= "gpt1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wu_l4_ick,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt1_fck = {
-	.name		= "gpt1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT1_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
-};
-
-static struct clk gpt2_ick = {
-	.name		= "gpt2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt2_fck = {
-	.name		= "gpt2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT2_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt3_ick = {
-	.name		= "gpt3_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt3_fck = {
-	.name		= "gpt3_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT3_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt4_ick = {
-	.name		= "gpt4_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt4_fck = {
-	.name		= "gpt4_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT4_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt5_ick = {
-	.name		= "gpt5_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt5_fck = {
-	.name		= "gpt5_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT5_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt6_ick = {
-	.name		= "gpt6_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt6_fck = {
-	.name		= "gpt6_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT6_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt7_ick = {
-	.name		= "gpt7_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt7_fck = {
-	.name		= "gpt7_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT7_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt8_ick = {
-	.name		= "gpt8_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt8_fck = {
-	.name		= "gpt8_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT8_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt9_ick = {
-	.name		= "gpt9_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt9_fck = {
-	.name		= "gpt9_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT9_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt10_ick = {
-	.name		= "gpt10_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt10_fck = {
-	.name		= "gpt10_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT10_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt11_ick = {
-	.name		= "gpt11_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt11_fck = {
-	.name		= "gpt11_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT11_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt12_ick = {
-	.name		= "gpt12_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt12_fck = {
-	.name		= "gpt12_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &secure_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
-	.clksel_mask	= OMAP24XX_CLKSEL_GPT12_MASK,
-	.clksel		= omap24xx_gpt_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp1_ick = {
-	.name		= "mcbsp1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCBSP1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel_rate common_mcbsp_96m_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 0 }
-};
-
-static const struct clksel mcbsp_fck_clksel[] = {
-	{ .parent = &func_96m_ck,  .rates = common_mcbsp_96m_rates },
-	{ .parent = &mcbsp_clks,   .rates = common_mcbsp_mcbsp_rates },
-	{ .parent = NULL }
-};
-
-static struct clk mcbsp1_fck = {
-	.name		= "mcbsp1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_96m_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCBSP1_SHIFT,
-	.clksel_reg	= OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
-	.clksel_mask	= OMAP2_MCBSP1_CLKS_MASK,
-	.clksel		= mcbsp_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp2_ick = {
-	.name		= "mcbsp2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCBSP2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcbsp2_fck = {
-	.name		= "mcbsp2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_96m_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCBSP2_SHIFT,
-	.clksel_reg	= OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
-	.clksel_mask	= OMAP2_MCBSP2_CLKS_MASK,
-	.clksel		= mcbsp_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp3_ick = {
-	.name		= "mcbsp3_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_MCBSP3_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcbsp3_fck = {
-	.name		= "mcbsp3_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_96m_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_MCBSP3_SHIFT,
-	.clksel_reg	= OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
-	.clksel_mask	= OMAP2_MCBSP3_CLKS_MASK,
-	.clksel		= mcbsp_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp4_ick = {
-	.name		= "mcbsp4_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_MCBSP4_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcbsp4_fck = {
-	.name		= "mcbsp4_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_96m_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_MCBSP4_SHIFT,
-	.clksel_reg	= OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
-	.clksel_mask	= OMAP2_MCBSP4_CLKS_MASK,
-	.clksel		= mcbsp_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp5_ick = {
-	.name		= "mcbsp5_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_MCBSP5_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcbsp5_fck = {
-	.name		= "mcbsp5_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_96m_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_MCBSP5_SHIFT,
-	.clksel_reg	= OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
-	.clksel_mask	= OMAP2_MCBSP5_CLKS_MASK,
-	.clksel		= mcbsp_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk mcspi1_ick = {
-	.name		= "mcspi1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi1_fck = {
-	.name		= "mcspi1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_48m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi2_ick = {
-	.name		= "mcspi2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi2_fck = {
-	.name		= "mcspi2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_48m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi3_ick = {
-	.name		= "mcspi3_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_MCSPI3_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi3_fck = {
-	.name		= "mcspi3_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_48m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_MCSPI3_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart1_ick = {
-	.name		= "uart1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart1_fck = {
-	.name		= "uart1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_48m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart2_ick = {
-	.name		= "uart2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart2_fck = {
-	.name		= "uart2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_48m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart3_ick = {
-	.name		= "uart3_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart3_fck = {
-	.name		= "uart3_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_48m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpios_ick = {
-	.name		= "gpios_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wu_l4_ick,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpios_fck = {
-	.name		= "gpios_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mpu_wdt_ick = {
-	.name		= "mpu_wdt_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wu_l4_ick,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mpu_wdt_fck = {
-	.name		= "mpu_wdt_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk sync_32k_ick = {
-	.name		= "sync_32k_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.flags		= ENABLE_ON_INIT,
-	.parent		= &wu_l4_ick,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_32KSYNC_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wdt1_ick = {
-	.name		= "wdt1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wu_l4_ick,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_WDT1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk omapctrl_ick = {
-	.name		= "omapctrl_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.flags		= ENABLE_ON_INIT,
-	.parent		= &wu_l4_ick,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP24XX_EN_OMAPCTRL_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk icr_ick = {
-	.name		= "icr_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wu_l4_ick,
-	.clkdm_name	= "wkup_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP2430_EN_ICR_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk cam_ick = {
-	.name		= "cam_ick",
-	.ops		= &clkops_omap2_iclk_dflt,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * cam_fck controls both CAM_MCLK and CAM_FCLK.  It should probably be
- * split into two separate clocks, since the parent clocks are different
- * and the clockdomains are also different.
- */
-static struct clk cam_fck = {
-	.name		= "cam_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &func_96m_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mailboxes_ick = {
-	.name		= "mailboxes_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MAILBOXES_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wdt4_ick = {
-	.name		= "wdt4_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wdt4_fck = {
-	.name		= "wdt4_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mspro_ick = {
-	.name		= "mspro_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mspro_fck = {
-	.name		= "mspro_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_96m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk fac_ick = {
-	.name		= "fac_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk fac_fck = {
-	.name		= "fac_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_12m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk hdq_ick = {
-	.name		= "hdq_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk hdq_fck = {
-	.name		= "hdq_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_12m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * XXX This is marked as a 2420-only define, but it claims to be present
- * on 2430 also.  Double-check.
- */
-static struct clk i2c2_ick = {
-	.name		= "i2c2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP2420_EN_I2C2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk i2chs2_fck = {
-	.name		= "i2chs2_fck",
-	.ops		= &clkops_omap2430_i2chs_wait,
-	.parent		= &func_96m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_I2CHS2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * XXX This is marked as a 2420-only define, but it claims to be present
- * on 2430 also.  Double-check.
- */
-static struct clk i2c1_ick = {
-	.name		= "i2c1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP2420_EN_I2C1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk i2chs1_fck = {
-	.name		= "i2chs1_fck",
-	.ops		= &clkops_omap2430_i2chs_wait,
-	.parent		= &func_96m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_I2CHS1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
- * accesses derived from this data.
- */
-static struct clk gpmc_fck = {
-	.name		= "gpmc_fck",
-	.ops		= &clkops_omap2_iclk_idle_only,
-	.parent		= &core_l3_ck,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
-	.enable_bit	= OMAP24XX_AUTO_GPMC_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk sdma_fck = {
-	.name		= "sdma_fck",
-	.ops		= &clkops_null, /* RMK: missing? */
-	.parent		= &core_l3_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
- * accesses derived from this data.
- */
-static struct clk sdma_ick = {
-	.name		= "sdma_ick",
-	.ops		= &clkops_omap2_iclk_idle_only,
-	.parent		= &core_l3_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
-	.enable_bit	= OMAP24XX_AUTO_SDMA_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk sdrc_ick = {
-	.name		= "sdrc_ick",
-	.ops		= &clkops_omap2_iclk_idle_only,
-	.parent		= &core_l3_ck,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
-	.enable_bit	= OMAP2430_EN_SDRC_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk des_ick = {
-	.name		= "des_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_DES_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk sha_ick = {
-	.name		= "sha_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_SHA_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk rng_ick = {
-	.name		= "rng_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_RNG_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk aes_ick = {
-	.name		= "aes_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_AES_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk pka_ick = {
-	.name		= "pka_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
-	.enable_bit	= OMAP24XX_EN_PKA_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_fck = {
-	.name		= "usb_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_48m_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usbhs_ick = {
-	.name		= "usbhs_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l3_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_USBHS_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmchs1_ick = {
-	.name		= "mmchs1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_MMCHS1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmchs1_fck = {
-	.name		= "mmchs1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_96m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_MMCHS1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmchs2_ick = {
-	.name		= "mmchs2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_MMCHS2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmchs2_fck = {
-	.name		= "mmchs2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_96m_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_MMCHS2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio5_ick = {
-	.name		= "gpio5_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_GPIO5_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio5_fck = {
-	.name		= "gpio5_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_GPIO5_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mdm_intc_ick = {
-	.name		= "mdm_intc_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP2430_EN_MDM_INTC_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmchsdb1_fck = {
-	.name		= "mmchsdb1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_MMCHSDB1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmchsdb2_fck = {
-	.name		= "mmchsdb2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &func_32k_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
-	.enable_bit	= OMAP2430_EN_MMCHSDB2_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * This clock is a composite clock which does entire set changes then
- * forces a rebalance. It keys on the MPU speed, but it really could
- * be any key speed part of a set in the rate table.
- *
- * to really change a set, you need memory table sets which get changed
- * in sram, pre-notifiers & post notifiers, changing the top set, without
- * having low level display recalc's won't work... this is why dpm notifiers
- * work, isr's off, walk a list of clocks already _off_ and not messing with
- * the bus.
- *
- * This clock should have no parent. It embodies the entire upper level
- * active set. A parent will mess up some of the init also.
- */
-static struct clk virt_prcm_set = {
-	.name		= "virt_prcm_set",
-	.ops		= &clkops_null,
-	.parent		= &mpu_ck,	/* Indexed by mpu speed, no parent */
-	.recalc		= &omap2_table_mpu_recalc,	/* sets are keyed on mpu rate */
-	.set_rate	= &omap2_select_table_rate,
-	.round_rate	= &omap2_round_to_table_rate,
-};
-
-
-/*
- * clkdev integration
- */
-
-static struct omap_clk omap2430_clks[] = {
-	/* external root sources */
-	CLK(NULL,	"func_32k_ck",	&func_32k_ck,	CK_243X),
-	CLK(NULL,	"secure_32k_ck", &secure_32k_ck, CK_243X),
-	CLK(NULL,	"osc_ck",	&osc_ck,	CK_243X),
-	CLK("twl",	"fck",		&osc_ck,	CK_243X),
-	CLK(NULL,	"sys_ck",	&sys_ck,	CK_243X),
-	CLK(NULL,	"alt_ck",	&alt_ck,	CK_243X),
-	CLK(NULL,	"mcbsp_clks",	&mcbsp_clks,	CK_243X),
-	/* internal analog sources */
-	CLK(NULL,	"dpll_ck",	&dpll_ck,	CK_243X),
-	CLK(NULL,	"apll96_ck",	&apll96_ck,	CK_243X),
-	CLK(NULL,	"apll54_ck",	&apll54_ck,	CK_243X),
-	/* internal prcm root sources */
-	CLK(NULL,	"func_54m_ck",	&func_54m_ck,	CK_243X),
-	CLK(NULL,	"core_ck",	&core_ck,	CK_243X),
-	CLK(NULL,	"func_96m_ck",	&func_96m_ck,	CK_243X),
-	CLK(NULL,	"func_48m_ck",	&func_48m_ck,	CK_243X),
-	CLK(NULL,	"func_12m_ck",	&func_12m_ck,	CK_243X),
-	CLK(NULL,	"ck_wdt1_osc",	&wdt1_osc_ck,	CK_243X),
-	CLK(NULL,	"sys_clkout_src", &sys_clkout_src, CK_243X),
-	CLK(NULL,	"sys_clkout",	&sys_clkout,	CK_243X),
-	CLK(NULL,	"emul_ck",	&emul_ck,	CK_243X),
-	/* mpu domain clocks */
-	CLK(NULL,	"mpu_ck",	&mpu_ck,	CK_243X),
-	/* dsp domain clocks */
-	CLK(NULL,	"dsp_fck",	&dsp_fck,	CK_243X),
-	CLK(NULL,	"iva2_1_ick",	&iva2_1_ick,	CK_243X),
-	/* GFX domain clocks */
-	CLK(NULL,	"gfx_3d_fck",	&gfx_3d_fck,	CK_243X),
-	CLK(NULL,	"gfx_2d_fck",	&gfx_2d_fck,	CK_243X),
-	CLK(NULL,	"gfx_ick",	&gfx_ick,	CK_243X),
-	/* Modem domain clocks */
-	CLK(NULL,	"mdm_ick",	&mdm_ick,	CK_243X),
-	CLK(NULL,	"mdm_osc_ck",	&mdm_osc_ck,	CK_243X),
-	/* DSS domain clocks */
-	CLK("omapdss_dss",	"ick",		&dss_ick,	CK_243X),
-	CLK(NULL,	"dss_ick",		&dss_ick,	CK_243X),
-	CLK(NULL,	"dss1_fck",		&dss1_fck,	CK_243X),
-	CLK(NULL,	"dss2_fck",	&dss2_fck,	CK_243X),
-	CLK(NULL,	"dss_54m_fck",	&dss_54m_fck,	CK_243X),
-	/* L3 domain clocks */
-	CLK(NULL,	"core_l3_ck",	&core_l3_ck,	CK_243X),
-	CLK(NULL,	"ssi_fck",	&ssi_ssr_sst_fck, CK_243X),
-	CLK(NULL,	"usb_l4_ick",	&usb_l4_ick,	CK_243X),
-	/* L4 domain clocks */
-	CLK(NULL,	"l4_ck",	&l4_ck,		CK_243X),
-	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_243X),
-	CLK(NULL,	"wu_l4_ick",	&wu_l4_ick,	CK_243X),
-	/* virtual meta-group clock */
-	CLK(NULL,	"virt_prcm_set", &virt_prcm_set, CK_243X),
-	/* general l4 interface ck, multi-parent functional clk */
-	CLK(NULL,	"gpt1_ick",	&gpt1_ick,	CK_243X),
-	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_243X),
-	CLK(NULL,	"gpt2_ick",	&gpt2_ick,	CK_243X),
-	CLK(NULL,	"gpt2_fck",	&gpt2_fck,	CK_243X),
-	CLK(NULL,	"gpt3_ick",	&gpt3_ick,	CK_243X),
-	CLK(NULL,	"gpt3_fck",	&gpt3_fck,	CK_243X),
-	CLK(NULL,	"gpt4_ick",	&gpt4_ick,	CK_243X),
-	CLK(NULL,	"gpt4_fck",	&gpt4_fck,	CK_243X),
-	CLK(NULL,	"gpt5_ick",	&gpt5_ick,	CK_243X),
-	CLK(NULL,	"gpt5_fck",	&gpt5_fck,	CK_243X),
-	CLK(NULL,	"gpt6_ick",	&gpt6_ick,	CK_243X),
-	CLK(NULL,	"gpt6_fck",	&gpt6_fck,	CK_243X),
-	CLK(NULL,	"gpt7_ick",	&gpt7_ick,	CK_243X),
-	CLK(NULL,	"gpt7_fck",	&gpt7_fck,	CK_243X),
-	CLK(NULL,	"gpt8_ick",	&gpt8_ick,	CK_243X),
-	CLK(NULL,	"gpt8_fck",	&gpt8_fck,	CK_243X),
-	CLK(NULL,	"gpt9_ick",	&gpt9_ick,	CK_243X),
-	CLK(NULL,	"gpt9_fck",	&gpt9_fck,	CK_243X),
-	CLK(NULL,	"gpt10_ick",	&gpt10_ick,	CK_243X),
-	CLK(NULL,	"gpt10_fck",	&gpt10_fck,	CK_243X),
-	CLK(NULL,	"gpt11_ick",	&gpt11_ick,	CK_243X),
-	CLK(NULL,	"gpt11_fck",	&gpt11_fck,	CK_243X),
-	CLK(NULL,	"gpt12_ick",	&gpt12_ick,	CK_243X),
-	CLK(NULL,	"gpt12_fck",	&gpt12_fck,	CK_243X),
-	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick,	CK_243X),
-	CLK(NULL,	"mcbsp1_ick",	&mcbsp1_ick,	CK_243X),
-	CLK(NULL,	"mcbsp1_fck",	&mcbsp1_fck,	CK_243X),
-	CLK("omap-mcbsp.2", "ick",	&mcbsp2_ick,	CK_243X),
-	CLK(NULL,	"mcbsp2_ick",	&mcbsp2_ick,	CK_243X),
-	CLK(NULL,	"mcbsp2_fck",	&mcbsp2_fck,	CK_243X),
-	CLK("omap-mcbsp.3", "ick",	&mcbsp3_ick,	CK_243X),
-	CLK(NULL,	"mcbsp3_ick",	&mcbsp3_ick,	CK_243X),
-	CLK(NULL,	"mcbsp3_fck",	&mcbsp3_fck,	CK_243X),
-	CLK("omap-mcbsp.4", "ick",	&mcbsp4_ick,	CK_243X),
-	CLK(NULL,	"mcbsp4_ick",	&mcbsp4_ick,	CK_243X),
-	CLK(NULL,	"mcbsp4_fck",	&mcbsp4_fck,	CK_243X),
-	CLK("omap-mcbsp.5", "ick",	&mcbsp5_ick,	CK_243X),
-	CLK(NULL,	"mcbsp5_ick",	&mcbsp5_ick,	CK_243X),
-	CLK(NULL,	"mcbsp5_fck",	&mcbsp5_fck,	CK_243X),
-	CLK("omap2_mcspi.1", "ick",	&mcspi1_ick,	CK_243X),
-	CLK(NULL,	"mcspi1_ick",	&mcspi1_ick,	CK_243X),
-	CLK(NULL,	"mcspi1_fck",	&mcspi1_fck,	CK_243X),
-	CLK("omap2_mcspi.2", "ick",	&mcspi2_ick,	CK_243X),
-	CLK(NULL,	"mcspi2_ick",	&mcspi2_ick,	CK_243X),
-	CLK(NULL,	"mcspi2_fck",	&mcspi2_fck,	CK_243X),
-	CLK("omap2_mcspi.3", "ick",	&mcspi3_ick,	CK_243X),
-	CLK(NULL,	"mcspi3_ick",	&mcspi3_ick,	CK_243X),
-	CLK(NULL,	"mcspi3_fck",	&mcspi3_fck,	CK_243X),
-	CLK(NULL,	"uart1_ick",	&uart1_ick,	CK_243X),
-	CLK(NULL,	"uart1_fck",	&uart1_fck,	CK_243X),
-	CLK(NULL,	"uart2_ick",	&uart2_ick,	CK_243X),
-	CLK(NULL,	"uart2_fck",	&uart2_fck,	CK_243X),
-	CLK(NULL,	"uart3_ick",	&uart3_ick,	CK_243X),
-	CLK(NULL,	"uart3_fck",	&uart3_fck,	CK_243X),
-	CLK(NULL,	"gpios_ick",	&gpios_ick,	CK_243X),
-	CLK(NULL,	"gpios_fck",	&gpios_fck,	CK_243X),
-	CLK("omap_wdt",	"ick",		&mpu_wdt_ick,	CK_243X),
-	CLK(NULL,	"mpu_wdt_ick",	&mpu_wdt_ick,	CK_243X),
-	CLK(NULL,	"mpu_wdt_fck",	&mpu_wdt_fck,	CK_243X),
-	CLK(NULL,	"sync_32k_ick",	&sync_32k_ick,	CK_243X),
-	CLK(NULL,	"wdt1_ick",	&wdt1_ick,	CK_243X),
-	CLK(NULL,	"omapctrl_ick",	&omapctrl_ick,	CK_243X),
-	CLK(NULL,	"icr_ick",	&icr_ick,	CK_243X),
-	CLK("omap24xxcam", "fck",	&cam_fck,	CK_243X),
-	CLK(NULL,	"cam_fck",	&cam_fck,	CK_243X),
-	CLK("omap24xxcam", "ick",	&cam_ick,	CK_243X),
-	CLK(NULL,	"cam_ick",	&cam_ick,	CK_243X),
-	CLK(NULL,	"mailboxes_ick", &mailboxes_ick,	CK_243X),
-	CLK(NULL,	"wdt4_ick",	&wdt4_ick,	CK_243X),
-	CLK(NULL,	"wdt4_fck",	&wdt4_fck,	CK_243X),
-	CLK(NULL,	"mspro_ick",	&mspro_ick,	CK_243X),
-	CLK(NULL,	"mspro_fck",	&mspro_fck,	CK_243X),
-	CLK(NULL,	"fac_ick",	&fac_ick,	CK_243X),
-	CLK(NULL,	"fac_fck",	&fac_fck,	CK_243X),
-	CLK("omap_hdq.0", "ick",	&hdq_ick,	CK_243X),
-	CLK(NULL,	"hdq_ick",	&hdq_ick,	CK_243X),
-	CLK("omap_hdq.1", "fck",	&hdq_fck,	CK_243X),
-	CLK(NULL,	"hdq_fck",	&hdq_fck,	CK_243X),
-	CLK("omap_i2c.1", "ick",	&i2c1_ick,	CK_243X),
-	CLK(NULL,	"i2c1_ick",	&i2c1_ick,	CK_243X),
-	CLK(NULL,	"i2chs1_fck",	&i2chs1_fck,	CK_243X),
-	CLK("omap_i2c.2", "ick",	&i2c2_ick,	CK_243X),
-	CLK(NULL,	"i2c2_ick",	&i2c2_ick,	CK_243X),
-	CLK(NULL,	"i2chs2_fck",	&i2chs2_fck,	CK_243X),
-	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_243X),
-	CLK(NULL,	"sdma_fck",	&sdma_fck,	CK_243X),
-	CLK(NULL,	"sdma_ick",	&sdma_ick,	CK_243X),
-	CLK(NULL,	"sdrc_ick",	&sdrc_ick,	CK_243X),
-	CLK(NULL,	"des_ick",	&des_ick,	CK_243X),
-	CLK("omap-sham",	"ick",	&sha_ick,	CK_243X),
-	CLK("omap_rng",	"ick",		&rng_ick,	CK_243X),
-	CLK(NULL,	"rng_ick",	&rng_ick,	CK_243X),
-	CLK("omap-aes",	"ick",	&aes_ick,	CK_243X),
-	CLK(NULL,	"pka_ick",	&pka_ick,	CK_243X),
-	CLK(NULL,	"usb_fck",	&usb_fck,	CK_243X),
-	CLK("musb-omap2430",	"ick",	&usbhs_ick,	CK_243X),
-	CLK(NULL,	"usbhs_ick",	&usbhs_ick,	CK_243X),
-	CLK("omap_hsmmc.0", "ick",	&mmchs1_ick,	CK_243X),
-	CLK(NULL,	"mmchs1_ick",	&mmchs1_ick,	CK_243X),
-	CLK(NULL,	"mmchs1_fck",	&mmchs1_fck,	CK_243X),
-	CLK("omap_hsmmc.1", "ick",	&mmchs2_ick,	CK_243X),
-	CLK(NULL,	"mmchs2_ick",	&mmchs2_ick,	CK_243X),
-	CLK(NULL,	"mmchs2_fck",	&mmchs2_fck,	CK_243X),
-	CLK(NULL,	"gpio5_ick",	&gpio5_ick,	CK_243X),
-	CLK(NULL,	"gpio5_fck",	&gpio5_fck,	CK_243X),
-	CLK(NULL,	"mdm_intc_ick",	&mdm_intc_ick,	CK_243X),
-	CLK("omap_hsmmc.0", "mmchsdb_fck",	&mmchsdb1_fck,	CK_243X),
-	CLK(NULL,	"mmchsdb1_fck",		&mmchsdb1_fck,	CK_243X),
-	CLK("omap_hsmmc.1", "mmchsdb_fck",	&mmchsdb2_fck,	CK_243X),
-	CLK(NULL,	"mmchsdb2_fck",		&mmchsdb2_fck,	CK_243X),
-	CLK(NULL,	"timer_32k_ck",  &func_32k_ck,   CK_243X),
-	CLK(NULL,	"timer_sys_ck",	&sys_ck,	CK_243X),
-	CLK(NULL,	"timer_ext_ck",	&alt_ck,	CK_243X),
-	CLK(NULL,	"cpufreq_ck",	&virt_prcm_set,	CK_243X),
-};
-
-/*
- * init code
- */
-
-int __init omap2430_clk_init(void)
-{
-	const struct prcm_config *prcm;
-	struct omap_clk *c;
-	u32 clkrate;
-
-	prcm_clksrc_ctrl = OMAP2430_PRCM_CLKSRC_CTRL;
-	cm_idlest_pll = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST);
-	cpu_mask = RATE_IN_243X;
-	rate_table = omap2430_rate_table;
-
-	clk_init(&omap2_clk_functions);
-
-	for (c = omap2430_clks; c < omap2430_clks + ARRAY_SIZE(omap2430_clks);
-	     c++)
-		clk_preinit(c->lk.clk);
-
-	osc_ck.rate = omap2_osc_clk_recalc(&osc_ck);
-	propagate_rate(&osc_ck);
-	sys_ck.rate = omap2xxx_sys_clk_recalc(&sys_ck);
-	propagate_rate(&sys_ck);
-
-	for (c = omap2430_clks; c < omap2430_clks + ARRAY_SIZE(omap2430_clks);
-	     c++) {
-		clkdev_add(&c->lk);
-		clk_register(c->lk.clk);
-		omap2_init_clk_clkdm(c->lk.clk);
-	}
-
-	/* Disable autoidle on all clocks; let the PM code enable it later */
-	omap_clk_disable_autoidle_all();
-
-	/* Check the MPU rate set by bootloader */
-	clkrate = omap2xxx_clk_get_core_rate(&dpll_ck);
-	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
-		if (!(prcm->flags & cpu_mask))
-			continue;
-		if (prcm->xtal_speed != sys_ck.rate)
-			continue;
-		if (prcm->dpll_speed <= clkrate)
-			break;
-	}
-	curr_prcm_set = prcm;
-
-	recalculate_root_clocks();
-
-	pr_info("Clocking rate (Crystal/DPLL/MPU): %ld.%01ld/%ld/%ld MHz\n",
-		(sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
-		(dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
-
-	/*
-	 * Only enable those clocks we will need, let the drivers
-	 * enable other clocks as necessary
-	 */
-	clk_enable_init_clocks();
-
-	/* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
-	vclk = clk_get(NULL, "virt_prcm_set");
-	sclk = clk_get(NULL, "sys_ck");
-	dclk = clk_get(NULL, "dpll_ck");
-
-	return 0;
-}
-
diff --git a/arch/arm/mach-omap2/clock2xxx.c b/arch/arm/mach-omap2/clock2xxx.c
index e92be1fc..1ff6469 100644
--- a/arch/arm/mach-omap2/clock2xxx.c
+++ b/arch/arm/mach-omap2/clock2xxx.c
@@ -22,35 +22,18 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/clock.h>
-
 #include "soc.h"
 #include "clock.h"
 #include "clock2xxx.h"
 #include "cm.h"
 #include "cm-regbits-24xx.h"
 
-struct clk *vclk, *sclk, *dclk;
-
+struct clk_hw *dclk_hw;
 /*
  * Omap24xx specific clock functions
  */
 
 /*
- * Set clocks for bypass mode for reboot to work.
- */
-void omap2xxx_clk_prepare_for_reboot(void)
-{
-	u32 rate;
-
-	if (vclk == NULL || sclk == NULL)
-		return;
-
-	rate = clk_get_rate(sclk);
-	clk_set_rate(vclk, rate);
-}
-
-/*
  * Switch the MPU rate if specified on cmdline.  We cannot do this
  * early until cmdline is parsed.  XXX This should be removed from the
  * clock code and handled by the OPP layer code in the near future.
diff --git a/arch/arm/mach-omap2/clock2xxx.h b/arch/arm/mach-omap2/clock2xxx.h
index cb6df8c..539dc08 100644
--- a/arch/arm/mach-omap2/clock2xxx.h
+++ b/arch/arm/mach-omap2/clock2xxx.h
@@ -8,17 +8,34 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK2XXX_H
 #define __ARCH_ARM_MACH_OMAP2_CLOCK2XXX_H
 
-unsigned long omap2_table_mpu_recalc(struct clk *clk);
-int omap2_select_table_rate(struct clk *clk, unsigned long rate);
-long omap2_round_to_table_rate(struct clk *clk, unsigned long rate);
-unsigned long omap2xxx_sys_clk_recalc(struct clk *clk);
-unsigned long omap2_osc_clk_recalc(struct clk *clk);
-unsigned long omap2_dpllcore_recalc(struct clk *clk);
-int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate);
-unsigned long omap2xxx_clk_get_core_rate(struct clk *clk);
+#include <linux/clk-provider.h>
+#include "clock.h"
+
+unsigned long omap2_table_mpu_recalc(struct clk_hw *clk,
+				     unsigned long parent_rate);
+int omap2_select_table_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long parent_rate);
+long omap2_round_to_table_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long *parent_rate);
+unsigned long omap2xxx_sys_clk_recalc(struct clk_hw *clk,
+				      unsigned long parent_rate);
+unsigned long omap2_osc_clk_recalc(struct clk_hw *clk,
+				   unsigned long parent_rate);
+unsigned long omap2_dpllcore_recalc(struct clk_hw *hw,
+				    unsigned long parent_rate);
+int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate,
+			     unsigned long parent_rate);
+void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw);
+unsigned long omap2_clk_apll54_recalc(struct clk_hw *hw,
+				      unsigned long parent_rate);
+unsigned long omap2_clk_apll96_recalc(struct clk_hw *hw,
+				      unsigned long parent_rate);
+unsigned long omap2xxx_clk_get_core_rate(void);
 u32 omap2xxx_get_apll_clkin(void);
 u32 omap2xxx_get_sysclkdiv(void);
 void omap2xxx_clk_prepare_for_reboot(void);
+void omap2xxx_clkt_vps_check_bootloader_rates(void);
+void omap2xxx_clkt_vps_late_init(void);
 
 #ifdef CONFIG_SOC_OMAP2420
 int omap2420_clk_init(void);
@@ -32,13 +49,14 @@ int omap2430_clk_init(void);
 #define omap2430_clk_init()	do { } while(0)
 #endif
 
-extern void __iomem *prcm_clksrc_ctrl, *cm_idlest_pll;
+extern void __iomem *prcm_clksrc_ctrl;
 
-extern struct clk *dclk;
-
-extern const struct clkops clkops_omap2430_i2chs_wait;
-extern const struct clkops clkops_oscck;
-extern const struct clkops clkops_apll96;
-extern const struct clkops clkops_apll54;
+extern struct clk_hw *dclk_hw;
+int omap2_enable_osc_ck(struct clk_hw *hw);
+void omap2_disable_osc_ck(struct clk_hw *hw);
+int omap2_clk_apll96_enable(struct clk_hw *hw);
+int omap2_clk_apll54_enable(struct clk_hw *hw);
+void omap2_clk_apll96_disable(struct clk_hw *hw);
+void omap2_clk_apll54_disable(struct clk_hw *hw);
 
 #endif
diff --git a/arch/arm/mach-omap2/clock33xx_data.c b/arch/arm/mach-omap2/clock33xx_data.c
deleted file mode 100644
index 1a45d6b..0000000
--- a/arch/arm/mach-omap2/clock33xx_data.c
+++ /dev/null
@@ -1,1112 +0,0 @@
-/*
- * AM33XX Clock data
- *
- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
- * Vaibhav Hiremath <hvaibhav@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/clk.h>
-#include <plat/clkdev_omap.h>
-
-#include "am33xx.h"
-#include "iomap.h"
-#include "control.h"
-#include "clock.h"
-#include "cm.h"
-#include "cm33xx.h"
-#include "cm-regbits-33xx.h"
-#include "prm.h"
-
-/* Maximum DPLL multiplier, divider values for AM33XX */
-#define AM33XX_MAX_DPLL_MULT		2047
-#define AM33XX_MAX_DPLL_DIV		128
-
-/* Modulemode control */
-#define AM33XX_MODULEMODE_HWCTRL	0
-#define AM33XX_MODULEMODE_SWCTRL	1
-
-/* TRM ERRATA: Timer 3 & 6 default parent (TCLKIN) may not be always
- *    physically present, in such a case HWMOD enabling of
- *    clock would be failure with default parent. And timer
- *    probe thinks clock is already enabled, this leads to
- *    crash upon accessing timer 3 & 6 registers in probe.
- *    Fix by setting parent of both these timers to master
- *    oscillator clock.
- */
-static inline void am33xx_init_timer_parent(struct clk *clk)
-{
-	omap2_clksel_set_parent(clk, clk->parent);
-}
-
-/* Root clocks */
-
-/* RTC 32k */
-static struct clk clk_32768_ck = {
-	.name		= "clk_32768_ck",
-	.clkdm_name	= "l4_rtc_clkdm",
-	.rate		= 32768,
-	.ops		= &clkops_null,
-};
-
-/* On-Chip 32KHz RC OSC */
-static struct clk clk_rc32k_ck = {
-	.name		= "clk_rc32k_ck",
-	.rate		= 32000,
-	.ops		= &clkops_null,
-};
-
-/* Crystal input clks */
-static struct clk virt_24000000_ck = {
-	.name		= "virt_24000000_ck",
-	.rate		= 24000000,
-	.ops		= &clkops_null,
-};
-
-static struct clk virt_25000000_ck = {
-	.name		= "virt_25000000_ck",
-	.rate		= 25000000,
-	.ops		= &clkops_null,
-};
-
-/* Oscillator clock */
-/* 19.2, 24, 25 or 26 MHz */
-static const struct clksel sys_clkin_sel[] = {
-	{ .parent = &virt_19200000_ck, .rates = div_1_0_rates },
-	{ .parent = &virt_24000000_ck, .rates = div_1_1_rates },
-	{ .parent = &virt_25000000_ck, .rates = div_1_2_rates },
-	{ .parent = &virt_26000000_ck, .rates = div_1_3_rates },
-	{ .parent = NULL },
-};
-
-/* External clock - 12 MHz */
-static struct clk tclkin_ck = {
-	.name		= "tclkin_ck",
-	.rate		= 12000000,
-	.ops		= &clkops_null,
-};
-
-/*
- * sys_clk in: input to the dpll and also used as funtional clock for,
- *   adc_tsc, smartreflex0-1, timer1-7, mcasp0-1, dcan0-1, cefuse
- *
- */
-static struct clk sys_clkin_ck = {
-	.name		= "sys_clkin_ck",
-	.parent		= &virt_24000000_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= AM33XX_CTRL_REGADDR(AM33XX_CONTROL_STATUS),
-	.clksel_mask	= AM33XX_CONTROL_STATUS_SYSBOOT1_MASK,
-	.clksel		= sys_clkin_sel,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* DPLL_CORE */
-static struct dpll_data dpll_core_dd = {
-	.mult_div1_reg	= AM33XX_CM_CLKSEL_DPLL_CORE,
-	.clk_bypass	= &sys_clkin_ck,
-	.clk_ref	= &sys_clkin_ck,
-	.control_reg	= AM33XX_CM_CLKMODE_DPLL_CORE,
-	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-	.idlest_reg	= AM33XX_CM_IDLEST_DPLL_CORE,
-	.mult_mask	= AM33XX_DPLL_MULT_MASK,
-	.div1_mask	= AM33XX_DPLL_DIV_MASK,
-	.enable_mask	= AM33XX_DPLL_EN_MASK,
-	.idlest_mask	= AM33XX_ST_DPLL_CLK_MASK,
-	.max_multiplier	= AM33XX_MAX_DPLL_MULT,
-	.max_divider	= AM33XX_MAX_DPLL_DIV,
-	.min_divider	= 1,
-};
-
-/* CLKDCOLDO output */
-static struct clk dpll_core_ck = {
-	.name		= "dpll_core_ck",
-	.parent		= &sys_clkin_ck,
-	.dpll_data	= &dpll_core_dd,
-	.init		= &omap2_init_dpll_parent,
-	.ops		= &clkops_omap3_core_dpll_ops,
-	.recalc		= &omap3_dpll_recalc,
-};
-
-static struct clk dpll_core_x2_ck = {
-	.name		= "dpll_core_x2_ck",
-	.parent		= &dpll_core_ck,
-	.flags		= CLOCK_CLKOUTX2,
-	.ops		= &clkops_null,
-	.recalc		= &omap3_clkoutx2_recalc,
-};
-
-
-static const struct clksel dpll_core_m4_div[] = {
-	{ .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_core_m4_ck = {
-	.name		= "dpll_core_m4_ck",
-	.parent		= &dpll_core_x2_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel		= dpll_core_m4_div,
-	.clksel_reg	= AM33XX_CM_DIV_M4_DPLL_CORE,
-	.clksel_mask	= AM33XX_HSDIVIDER_CLKOUT1_DIV_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel dpll_core_m5_div[] = {
-	{ .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_core_m5_ck = {
-	.name		= "dpll_core_m5_ck",
-	.parent		= &dpll_core_x2_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel		= dpll_core_m5_div,
-	.clksel_reg	= AM33XX_CM_DIV_M5_DPLL_CORE,
-	.clksel_mask	= AM33XX_HSDIVIDER_CLKOUT2_DIV_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel dpll_core_m6_div[] = {
-	{ .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_core_m6_ck = {
-	.name		= "dpll_core_m6_ck",
-	.parent		= &dpll_core_x2_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel		= dpll_core_m6_div,
-	.clksel_reg	= AM33XX_CM_DIV_M6_DPLL_CORE,
-	.clksel_mask	= AM33XX_HSDIVIDER_CLKOUT3_DIV_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-/* DPLL_MPU */
-static struct dpll_data dpll_mpu_dd = {
-	.mult_div1_reg	= AM33XX_CM_CLKSEL_DPLL_MPU,
-	.clk_bypass	= &sys_clkin_ck,
-	.clk_ref	= &sys_clkin_ck,
-	.control_reg	= AM33XX_CM_CLKMODE_DPLL_MPU,
-	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-	.idlest_reg	= AM33XX_CM_IDLEST_DPLL_MPU,
-	.mult_mask	= AM33XX_DPLL_MULT_MASK,
-	.div1_mask	= AM33XX_DPLL_DIV_MASK,
-	.enable_mask	= AM33XX_DPLL_EN_MASK,
-	.idlest_mask	= AM33XX_ST_DPLL_CLK_MASK,
-	.max_multiplier	= AM33XX_MAX_DPLL_MULT,
-	.max_divider	= AM33XX_MAX_DPLL_DIV,
-	.min_divider	= 1,
-};
-
-/* CLKOUT: fdpll/M2 */
-static struct clk dpll_mpu_ck = {
-	.name		= "dpll_mpu_ck",
-	.parent		= &sys_clkin_ck,
-	.dpll_data	= &dpll_mpu_dd,
-	.init		= &omap2_init_dpll_parent,
-	.ops		= &clkops_omap3_noncore_dpll_ops,
-	.recalc		= &omap3_dpll_recalc,
-	.round_rate	= &omap2_dpll_round_rate,
-	.set_rate	= &omap3_noncore_dpll_set_rate,
-};
-
-/*
- * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
- * and ALT_CLK1/2)
- */
-static const struct clksel dpll_mpu_m2_div[] = {
-	{ .parent = &dpll_mpu_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_mpu_m2_ck = {
-	.name		= "dpll_mpu_m2_ck",
-	.clkdm_name	= "mpu_clkdm",
-	.parent		= &dpll_mpu_ck,
-	.clksel		= dpll_mpu_m2_div,
-	.clksel_reg	= AM33XX_CM_DIV_M2_DPLL_MPU,
-	.clksel_mask	= AM33XX_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-/* DPLL_DDR */
-static struct dpll_data dpll_ddr_dd = {
-	.mult_div1_reg	= AM33XX_CM_CLKSEL_DPLL_DDR,
-	.clk_bypass	= &sys_clkin_ck,
-	.clk_ref	= &sys_clkin_ck,
-	.control_reg	= AM33XX_CM_CLKMODE_DPLL_DDR,
-	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-	.idlest_reg	= AM33XX_CM_IDLEST_DPLL_DDR,
-	.mult_mask	= AM33XX_DPLL_MULT_MASK,
-	.div1_mask	= AM33XX_DPLL_DIV_MASK,
-	.enable_mask	= AM33XX_DPLL_EN_MASK,
-	.idlest_mask	= AM33XX_ST_DPLL_CLK_MASK,
-	.max_multiplier	= AM33XX_MAX_DPLL_MULT,
-	.max_divider	= AM33XX_MAX_DPLL_DIV,
-	.min_divider	= 1,
-};
-
-/* CLKOUT: fdpll/M2 */
-static struct clk dpll_ddr_ck = {
-	.name		= "dpll_ddr_ck",
-	.parent		= &sys_clkin_ck,
-	.dpll_data	= &dpll_ddr_dd,
-	.init		= &omap2_init_dpll_parent,
-	.ops		= &clkops_null,
-	.recalc		= &omap3_dpll_recalc,
-};
-
-/*
- * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
- * and ALT_CLK1/2)
- */
-static const struct clksel dpll_ddr_m2_div[] = {
-	{ .parent = &dpll_ddr_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_ddr_m2_ck = {
-	.name		= "dpll_ddr_m2_ck",
-	.parent		= &dpll_ddr_ck,
-	.clksel		= dpll_ddr_m2_div,
-	.clksel_reg	= AM33XX_CM_DIV_M2_DPLL_DDR,
-	.clksel_mask	= AM33XX_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-/* emif_fck functional clock */
-static struct clk dpll_ddr_m2_div2_ck = {
-	.name		= "dpll_ddr_m2_div2_ck",
-	.clkdm_name	= "l3_clkdm",
-	.parent		= &dpll_ddr_m2_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 2,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-/* DPLL_DISP */
-static struct dpll_data dpll_disp_dd = {
-	.mult_div1_reg	= AM33XX_CM_CLKSEL_DPLL_DISP,
-	.clk_bypass	= &sys_clkin_ck,
-	.clk_ref	= &sys_clkin_ck,
-	.control_reg	= AM33XX_CM_CLKMODE_DPLL_DISP,
-	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-	.idlest_reg	= AM33XX_CM_IDLEST_DPLL_DISP,
-	.mult_mask	= AM33XX_DPLL_MULT_MASK,
-	.div1_mask	= AM33XX_DPLL_DIV_MASK,
-	.enable_mask	= AM33XX_DPLL_EN_MASK,
-	.idlest_mask	= AM33XX_ST_DPLL_CLK_MASK,
-	.max_multiplier	= AM33XX_MAX_DPLL_MULT,
-	.max_divider	= AM33XX_MAX_DPLL_DIV,
-	.min_divider	= 1,
-};
-
-/* CLKOUT: fdpll/M2 */
-static struct clk dpll_disp_ck = {
-	.name		= "dpll_disp_ck",
-	.parent		= &sys_clkin_ck,
-	.dpll_data	= &dpll_disp_dd,
-	.init		= &omap2_init_dpll_parent,
-	.ops		= &clkops_null,
-	.recalc		= &omap3_dpll_recalc,
-	.round_rate	= &omap2_dpll_round_rate,
-	.set_rate	= &omap3_noncore_dpll_set_rate,
-};
-
-/*
- * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
- * and ALT_CLK1/2)
- */
-static const struct clksel dpll_disp_m2_div[] = {
-	{ .parent = &dpll_disp_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_disp_m2_ck = {
-	.name		= "dpll_disp_m2_ck",
-	.parent		= &dpll_disp_ck,
-	.clksel		= dpll_disp_m2_div,
-	.clksel_reg	= AM33XX_CM_DIV_M2_DPLL_DISP,
-	.clksel_mask	= AM33XX_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-/* DPLL_PER */
-static struct dpll_data dpll_per_dd = {
-	.mult_div1_reg	= AM33XX_CM_CLKSEL_DPLL_PERIPH,
-	.clk_bypass	= &sys_clkin_ck,
-	.clk_ref	= &sys_clkin_ck,
-	.control_reg	= AM33XX_CM_CLKMODE_DPLL_PER,
-	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-	.idlest_reg	= AM33XX_CM_IDLEST_DPLL_PER,
-	.mult_mask	= AM33XX_DPLL_MULT_PERIPH_MASK,
-	.div1_mask	= AM33XX_DPLL_PER_DIV_MASK,
-	.enable_mask	= AM33XX_DPLL_EN_MASK,
-	.idlest_mask	= AM33XX_ST_DPLL_CLK_MASK,
-	.max_multiplier	= AM33XX_MAX_DPLL_MULT,
-	.max_divider	= AM33XX_MAX_DPLL_DIV,
-	.min_divider	= 1,
-	.flags		= DPLL_J_TYPE,
-};
-
-/* CLKDCOLDO */
-static struct clk dpll_per_ck = {
-	.name		= "dpll_per_ck",
-	.parent		= &sys_clkin_ck,
-	.dpll_data	= &dpll_per_dd,
-	.init		= &omap2_init_dpll_parent,
-	.ops		= &clkops_null,
-	.recalc		= &omap3_dpll_recalc,
-	.round_rate	= &omap2_dpll_round_rate,
-	.set_rate	= &omap3_noncore_dpll_set_rate,
-};
-
-/* CLKOUT: fdpll/M2 */
-static const struct clksel dpll_per_m2_div[] = {
-	{ .parent = &dpll_per_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_per_m2_ck = {
-	.name		= "dpll_per_m2_ck",
-	.parent		= &dpll_per_ck,
-	.clksel		= dpll_per_m2_div,
-	.clksel_reg	= AM33XX_CM_DIV_M2_DPLL_PER,
-	.clksel_mask	= AM33XX_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_per_m2_div4_wkupdm_ck = {
-	.name		= "dpll_per_m2_div4_wkupdm_ck",
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &dpll_per_m2_ck,
-	.fixed_div	= 4,
-	.ops		= &clkops_null,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static struct clk dpll_per_m2_div4_ck = {
-	.name		= "dpll_per_m2_div4_ck",
-	.clkdm_name	= "l4ls_clkdm",
-	.parent		= &dpll_per_m2_ck,
-	.fixed_div	= 4,
-	.ops		= &clkops_null,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static struct clk l3_gclk = {
-	.name		= "l3_gclk",
-	.clkdm_name	= "l3_clkdm",
-	.parent		= &dpll_core_m4_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dpll_core_m4_div2_ck = {
-	.name		= "dpll_core_m4_div2_ck",
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &dpll_core_m4_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 2,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static struct clk l4_rtc_gclk = {
-	.name		= "l4_rtc_gclk",
-	.parent		= &dpll_core_m4_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 2,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static struct clk clk_24mhz = {
-	.name		= "clk_24mhz",
-	.parent		= &dpll_per_m2_ck,
-	.fixed_div	= 8,
-	.ops		= &clkops_null,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-/*
- * Below clock nodes describes clockdomains derived out
- * of core clock.
- */
-static struct clk l4hs_gclk = {
-	.name		= "l4hs_gclk",
-	.clkdm_name	= "l4hs_clkdm",
-	.parent		= &dpll_core_m4_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk l3s_gclk = {
-	.name		= "l3s_gclk",
-	.clkdm_name	= "l3s_clkdm",
-	.parent		= &dpll_core_m4_div2_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk l4fw_gclk = {
-	.name		= "l4fw_gclk",
-	.clkdm_name	= "l4fw_clkdm",
-	.parent		= &dpll_core_m4_div2_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk l4ls_gclk = {
-	.name		= "l4ls_gclk",
-	.clkdm_name	= "l4ls_clkdm",
-	.parent		= &dpll_core_m4_div2_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk sysclk_div_ck = {
-	.name		= "sysclk_div_ck",
-	.parent		= &dpll_core_m4_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * In order to match the clock domain with hwmod clockdomain entry,
- * separate clock nodes is required for the modules which are
- * directly getting their funtioncal clock from sys_clkin.
- */
-static struct clk adc_tsc_fck = {
-	.name		= "adc_tsc_fck",
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &sys_clkin_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dcan0_fck = {
-	.name		= "dcan0_fck",
-	.clkdm_name	= "l4ls_clkdm",
-	.parent		= &sys_clkin_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dcan1_fck = {
-	.name		= "dcan1_fck",
-	.clkdm_name	= "l4ls_clkdm",
-	.parent		= &sys_clkin_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcasp0_fck = {
-	.name		= "mcasp0_fck",
-	.clkdm_name	= "l3s_clkdm",
-	.parent		= &sys_clkin_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcasp1_fck = {
-	.name		= "mcasp1_fck",
-	.clkdm_name	= "l3s_clkdm",
-	.parent		= &sys_clkin_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk smartreflex0_fck = {
-	.name		= "smartreflex0_fck",
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &sys_clkin_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk smartreflex1_fck = {
-	.name		= "smartreflex1_fck",
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &sys_clkin_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * Modules clock nodes
- *
- * The following clock leaf nodes are added for the moment because:
- *
- *  - hwmod data is not present for these modules, either hwmod
- *    control is not required or its not populated.
- *  - Driver code is not yet migrated to use hwmod/runtime pm
- *  - Modules outside kernel access (to disable them by default)
- *
- *     - debugss
- *     - mmu (gfx domain)
- *     - cefuse
- *     - usbotg_fck (its additional clock and not really a modulemode)
- *     - ieee5000
- */
-static struct clk debugss_ick = {
-	.name		= "debugss_ick",
-	.clkdm_name	= "l3_aon_clkdm",
-	.parent		= &dpll_core_m4_ck,
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= AM33XX_CM_WKUP_DEBUGSS_CLKCTRL,
-	.enable_bit	= AM33XX_MODULEMODE_SWCTRL,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmu_fck = {
-	.name		= "mmu_fck",
-	.clkdm_name	= "gfx_l3_clkdm",
-	.parent		= &dpll_core_m4_ck,
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= AM33XX_CM_GFX_MMUDATA_CLKCTRL,
-	.enable_bit	= AM33XX_MODULEMODE_SWCTRL,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk cefuse_fck = {
-	.name		= "cefuse_fck",
-	.clkdm_name	= "l4_cefuse_clkdm",
-	.parent		= &sys_clkin_ck,
-	.enable_reg	= AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL,
-	.enable_bit	= AM33XX_MODULEMODE_SWCTRL,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * clkdiv32 is generated from fixed division of 732.4219
- */
-static struct clk clkdiv32k_ick = {
-	.name		= "clkdiv32k_ick",
-	.clkdm_name	= "clk_24mhz_clkdm",
-	.rate		= 32768,
-	.parent		= &clk_24mhz,
-	.enable_reg	= AM33XX_CM_PER_CLKDIV32K_CLKCTRL,
-	.enable_bit	= AM33XX_MODULEMODE_SWCTRL,
-	.ops		= &clkops_omap2_dflt,
-};
-
-static struct clk usbotg_fck = {
-	.name		= "usbotg_fck",
-	.clkdm_name	= "l3s_clkdm",
-	.parent		= &dpll_per_ck,
-	.enable_reg	= AM33XX_CM_CLKDCOLDO_DPLL_PER,
-	.enable_bit	= AM33XX_ST_DPLL_CLKDCOLDO_SHIFT,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk ieee5000_fck = {
-	.name		= "ieee5000_fck",
-	.clkdm_name	= "l3s_clkdm",
-	.parent		= &dpll_core_m4_div2_ck,
-	.enable_reg	= AM33XX_CM_PER_IEEE5000_CLKCTRL,
-	.enable_bit	= AM33XX_MODULEMODE_SWCTRL,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &followparent_recalc,
-};
-
-/* Timers */
-static const struct clksel timer1_clkmux_sel[] = {
-	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-	{ .parent = &clkdiv32k_ick, .rates = div_1_1_rates },
-	{ .parent = &tclkin_ck, .rates = div_1_2_rates },
-	{ .parent = &clk_rc32k_ck, .rates = div_1_3_rates },
-	{ .parent = &clk_32768_ck, .rates = div_1_4_rates },
-	{ .parent = NULL },
-};
-
-static struct clk timer1_fck = {
-	.name		= "timer1_fck",
-	.clkdm_name	= "l4ls_clkdm",
-	.parent		= &sys_clkin_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel		= timer1_clkmux_sel,
-	.clksel_reg	= AM33XX_CLKSEL_TIMER1MS_CLK,
-	.clksel_mask	= AM33XX_CLKSEL_0_2_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel timer2_to_7_clk_sel[] = {
-	{ .parent = &tclkin_ck, .rates = div_1_0_rates },
-	{ .parent = &sys_clkin_ck, .rates = div_1_1_rates },
-	{ .parent = &clkdiv32k_ick, .rates = div_1_2_rates },
-	{ .parent = NULL },
-};
-
-static struct clk timer2_fck = {
-	.name		= "timer2_fck",
-	.clkdm_name	= "l4ls_clkdm",
-	.parent		= &sys_clkin_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel		= timer2_to_7_clk_sel,
-	.clksel_reg	= AM33XX_CLKSEL_TIMER2_CLK,
-	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk timer3_fck = {
-	.name		= "timer3_fck",
-	.clkdm_name	= "l4ls_clkdm",
-	.parent		= &sys_clkin_ck,
-	.init		= &am33xx_init_timer_parent,
-	.clksel		= timer2_to_7_clk_sel,
-	.clksel_reg	= AM33XX_CLKSEL_TIMER3_CLK,
-	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk timer4_fck = {
-	.name		= "timer4_fck",
-	.clkdm_name	= "l4ls_clkdm",
-	.parent		= &sys_clkin_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel		= timer2_to_7_clk_sel,
-	.clksel_reg	= AM33XX_CLKSEL_TIMER4_CLK,
-	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk timer5_fck = {
-	.name		= "timer5_fck",
-	.clkdm_name	= "l4ls_clkdm",
-	.parent		= &sys_clkin_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel		= timer2_to_7_clk_sel,
-	.clksel_reg	= AM33XX_CLKSEL_TIMER5_CLK,
-	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk timer6_fck = {
-	.name		= "timer6_fck",
-	.clkdm_name	= "l4ls_clkdm",
-	.parent		= &sys_clkin_ck,
-	.init		= &am33xx_init_timer_parent,
-	.clksel		= timer2_to_7_clk_sel,
-	.clksel_reg	= AM33XX_CLKSEL_TIMER6_CLK,
-	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk timer7_fck = {
-	.name		= "timer7_fck",
-	.clkdm_name	= "l4ls_clkdm",
-	.parent		= &sys_clkin_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel		= timer2_to_7_clk_sel,
-	.clksel_reg	= AM33XX_CLKSEL_TIMER7_CLK,
-	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk cpsw_125mhz_gclk = {
-	.name		= "cpsw_125mhz_gclk",
-	.clkdm_name	= "cpsw_125mhz_clkdm",
-	.parent		= &dpll_core_m5_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 2,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static const struct clksel cpsw_cpts_rft_clkmux_sel[] = {
-	{ .parent = &dpll_core_m5_ck, .rates = div_1_0_rates },
-	{ .parent = &dpll_core_m4_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk cpsw_cpts_rft_clk = {
-	.name		= "cpsw_cpts_rft_clk",
-	.clkdm_name	= "cpsw_125mhz_clkdm",
-	.parent		= &dpll_core_m5_ck,
-	.clksel		= cpsw_cpts_rft_clkmux_sel,
-	.clksel_reg	= AM33XX_CM_CPTS_RFT_CLKSEL,
-	.clksel_mask	= AM33XX_CLKSEL_0_0_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-/* gpio */
-static const struct clksel gpio0_dbclk_mux_sel[] = {
-	{ .parent = &clk_rc32k_ck, .rates = div_1_0_rates },
-	{ .parent = &clk_32768_ck, .rates = div_1_1_rates },
-	{ .parent = &clkdiv32k_ick, .rates = div_1_2_rates },
-	{ .parent = NULL },
-};
-
-static struct clk gpio0_dbclk_mux_ck = {
-	.name		= "gpio0_dbclk_mux_ck",
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &clk_rc32k_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel		= gpio0_dbclk_mux_sel,
-	.clksel_reg	= AM33XX_CLKSEL_GPIO0_DBCLK,
-	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpio0_dbclk = {
-	.name		= "gpio0_dbclk",
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &gpio0_dbclk_mux_ck,
-	.enable_reg	= AM33XX_CM_WKUP_GPIO0_CLKCTRL,
-	.enable_bit	= AM33XX_OPTFCLKEN_GPIO0_GDBCLK_SHIFT,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio1_dbclk = {
-	.name		= "gpio1_dbclk",
-	.clkdm_name	= "l4ls_clkdm",
-	.parent		= &clkdiv32k_ick,
-	.enable_reg	= AM33XX_CM_PER_GPIO1_CLKCTRL,
-	.enable_bit	= AM33XX_OPTFCLKEN_GPIO_1_GDBCLK_SHIFT,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio2_dbclk = {
-	.name		= "gpio2_dbclk",
-	.clkdm_name	= "l4ls_clkdm",
-	.parent		= &clkdiv32k_ick,
-	.enable_reg	= AM33XX_CM_PER_GPIO2_CLKCTRL,
-	.enable_bit	= AM33XX_OPTFCLKEN_GPIO_2_GDBCLK_SHIFT,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio3_dbclk = {
-	.name		= "gpio3_dbclk",
-	.clkdm_name	= "l4ls_clkdm",
-	.parent		= &clkdiv32k_ick,
-	.enable_reg	= AM33XX_CM_PER_GPIO3_CLKCTRL,
-	.enable_bit	= AM33XX_OPTFCLKEN_GPIO_3_GDBCLK_SHIFT,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel pruss_ocp_clk_mux_sel[] = {
-	{ .parent = &l3_gclk, .rates = div_1_0_rates },
-	{ .parent = &dpll_disp_m2_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk pruss_ocp_gclk = {
-	.name		= "pruss_ocp_gclk",
-	.clkdm_name	= "pruss_ocp_clkdm",
-	.parent		= &l3_gclk,
-	.init		= &omap2_init_clksel_parent,
-	.clksel		= pruss_ocp_clk_mux_sel,
-	.clksel_reg	= AM33XX_CLKSEL_PRUSS_OCP_CLK,
-	.clksel_mask	= AM33XX_CLKSEL_0_0_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel lcd_clk_mux_sel[] = {
-	{ .parent = &dpll_disp_m2_ck, .rates = div_1_0_rates },
-	{ .parent = &dpll_core_m5_ck, .rates = div_1_1_rates },
-	{ .parent = &dpll_per_m2_ck, .rates = div_1_2_rates },
-	{ .parent = NULL },
-};
-
-static struct clk lcd_gclk = {
-	.name		= "lcd_gclk",
-	.clkdm_name	= "lcdc_clkdm",
-	.parent		= &dpll_disp_m2_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel		= lcd_clk_mux_sel,
-	.clksel_reg	= AM33XX_CLKSEL_LCDC_PIXEL_CLK,
-	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmc_clk = {
-	.name		= "mmc_clk",
-	.clkdm_name	= "l4ls_clkdm",
-	.parent		= &dpll_per_m2_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 2,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static struct clk mmc2_fck = {
-	.name		= "mmc2_fck",
-	.clkdm_name	= "l3s_clkdm",
-	.parent		= &mmc_clk,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel gfx_clksel_sel[] = {
-	{ .parent = &dpll_core_m4_ck, .rates = div_1_0_rates },
-	{ .parent = &dpll_per_m2_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk gfx_fclk_clksel_ck = {
-	.name		= "gfx_fclk_clksel_ck",
-	.parent		= &dpll_core_m4_ck,
-	.clksel		= gfx_clksel_sel,
-	.ops		= &clkops_null,
-	.clksel_reg	= AM33XX_CLKSEL_GFX_FCLK,
-	.clksel_mask	= AM33XX_CLKSEL_GFX_FCLK_MASK,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate div_1_0_2_1_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_AM33XX },
-	{ .div = 2, .val = 1, .flags = RATE_IN_AM33XX },
-	{ .div = 0 },
-};
-
-static const struct clksel gfx_div_sel[] = {
-	{ .parent = &gfx_fclk_clksel_ck, .rates = div_1_0_2_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk gfx_fck_div_ck = {
-	.name		= "gfx_fck_div_ck",
-	.clkdm_name	= "gfx_l3_clkdm",
-	.parent		= &gfx_fclk_clksel_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel		= gfx_div_sel,
-	.clksel_reg	= AM33XX_CLKSEL_GFX_FCLK,
-	.clksel_mask	= AM33XX_CLKSEL_0_0_MASK,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-	.ops		= &clkops_null,
-};
-
-static const struct clksel sysclkout_pre_sel[] = {
-	{ .parent = &clk_32768_ck, .rates = div_1_0_rates },
-	{ .parent = &l3_gclk, .rates = div_1_1_rates },
-	{ .parent = &dpll_ddr_m2_ck, .rates = div_1_2_rates },
-	{ .parent = &dpll_per_m2_ck, .rates = div_1_3_rates },
-	{ .parent = &lcd_gclk, .rates = div_1_4_rates },
-	{ .parent = NULL },
-};
-
-static struct clk sysclkout_pre_ck = {
-	.name		= "sysclkout_pre_ck",
-	.parent		= &clk_32768_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel		= sysclkout_pre_sel,
-	.clksel_reg	= AM33XX_CM_CLKOUT_CTRL,
-	.clksel_mask	= AM33XX_CLKOUT2SOURCE_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* Divide by 8 clock rates with default clock is 1/1*/
-static const struct clksel_rate div8_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_AM33XX },
-	{ .div = 2, .val = 1, .flags = RATE_IN_AM33XX },
-	{ .div = 3, .val = 2, .flags = RATE_IN_AM33XX },
-	{ .div = 4, .val = 3, .flags = RATE_IN_AM33XX },
-	{ .div = 5, .val = 4, .flags = RATE_IN_AM33XX },
-	{ .div = 6, .val = 5, .flags = RATE_IN_AM33XX },
-	{ .div = 7, .val = 6, .flags = RATE_IN_AM33XX },
-	{ .div = 8, .val = 7, .flags = RATE_IN_AM33XX },
-	{ .div = 0 },
-};
-
-static const struct clksel clkout2_div[] = {
-	{ .parent = &sysclkout_pre_ck, .rates = div8_rates },
-	{ .parent = NULL },
-};
-
-static struct clk clkout2_ck = {
-	.name		= "clkout2_ck",
-	.parent		= &sysclkout_pre_ck,
-	.ops		= &clkops_omap2_dflt,
-	.clksel		= clkout2_div,
-	.clksel_reg	= AM33XX_CM_CLKOUT_CTRL,
-	.clksel_mask	= AM33XX_CLKOUT2DIV_MASK,
-	.enable_reg	= AM33XX_CM_CLKOUT_CTRL,
-	.enable_bit	= AM33XX_CLKOUT2EN_SHIFT,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel wdt_clkmux_sel[] = {
-	{ .parent = &clk_rc32k_ck, .rates = div_1_0_rates },
-	{ .parent = &clkdiv32k_ick, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk wdt1_fck = {
-	.name		= "wdt1_fck",
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &clk_rc32k_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel		= wdt_clkmux_sel,
-	.clksel_reg	= AM33XX_CLKSEL_WDT1_CLK,
-	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/*
- * clkdev
- */
-static struct omap_clk am33xx_clks[] = {
-	CLK(NULL,	"clk_32768_ck",		&clk_32768_ck,	CK_AM33XX),
-	CLK(NULL,	"clk_rc32k_ck",		&clk_rc32k_ck,	CK_AM33XX),
-	CLK(NULL,	"virt_19200000_ck",	&virt_19200000_ck,	CK_AM33XX),
-	CLK(NULL,	"virt_24000000_ck",	&virt_24000000_ck,	CK_AM33XX),
-	CLK(NULL,	"virt_25000000_ck",	&virt_25000000_ck,	CK_AM33XX),
-	CLK(NULL,	"virt_26000000_ck",	&virt_26000000_ck,	CK_AM33XX),
-	CLK(NULL,	"sys_clkin_ck",		&sys_clkin_ck,	CK_AM33XX),
-	CLK(NULL,	"tclkin_ck",		&tclkin_ck,	CK_AM33XX),
-	CLK(NULL,	"dpll_core_ck",		&dpll_core_ck,	CK_AM33XX),
-	CLK(NULL,	"dpll_core_x2_ck",	&dpll_core_x2_ck,	CK_AM33XX),
-	CLK(NULL,	"dpll_core_m4_ck",	&dpll_core_m4_ck,	CK_AM33XX),
-	CLK(NULL,	"dpll_core_m5_ck",	&dpll_core_m5_ck,	CK_AM33XX),
-	CLK(NULL,	"dpll_core_m6_ck",	&dpll_core_m6_ck,	CK_AM33XX),
-	CLK(NULL,	"dpll_mpu_ck",		&dpll_mpu_ck,	CK_AM33XX),
-	CLK("cpu0",	NULL,			&dpll_mpu_ck,		CK_AM33XX),
-	CLK(NULL,	"dpll_mpu_m2_ck",	&dpll_mpu_m2_ck,	CK_AM33XX),
-	CLK(NULL,	"dpll_ddr_ck",		&dpll_ddr_ck,	CK_AM33XX),
-	CLK(NULL,	"dpll_ddr_m2_ck",	&dpll_ddr_m2_ck,	CK_AM33XX),
-	CLK(NULL,	"dpll_ddr_m2_div2_ck",	&dpll_ddr_m2_div2_ck,	CK_AM33XX),
-	CLK(NULL,	"dpll_disp_ck",		&dpll_disp_ck,	CK_AM33XX),
-	CLK(NULL,	"dpll_disp_m2_ck",	&dpll_disp_m2_ck,	CK_AM33XX),
-	CLK(NULL,	"dpll_per_ck",		&dpll_per_ck,	CK_AM33XX),
-	CLK(NULL,	"dpll_per_m2_ck",	&dpll_per_m2_ck,	CK_AM33XX),
-	CLK(NULL,	"dpll_per_m2_div4_wkupdm_ck",	&dpll_per_m2_div4_wkupdm_ck,	CK_AM33XX),
-	CLK(NULL,	"dpll_per_m2_div4_ck",	&dpll_per_m2_div4_ck,	CK_AM33XX),
-	CLK(NULL,	"adc_tsc_fck",		&adc_tsc_fck,	CK_AM33XX),
-	CLK(NULL,	"cefuse_fck",		&cefuse_fck,	CK_AM33XX),
-	CLK(NULL,	"clkdiv32k_ick",	&clkdiv32k_ick,	CK_AM33XX),
-	CLK(NULL,	"dcan0_fck",		&dcan0_fck,	CK_AM33XX),
-	CLK("481cc000.d_can",	NULL,		&dcan0_fck,	CK_AM33XX),
-	CLK(NULL,	"dcan1_fck",		&dcan1_fck,	CK_AM33XX),
-	CLK("481d0000.d_can",	NULL,		&dcan1_fck,	CK_AM33XX),
-	CLK(NULL,	"debugss_ick",		&debugss_ick,	CK_AM33XX),
-	CLK(NULL,	"pruss_ocp_gclk",	&pruss_ocp_gclk,	CK_AM33XX),
-	CLK("davinci-mcasp.0",  NULL,           &mcasp0_fck,    CK_AM33XX),
-	CLK("davinci-mcasp.1",  NULL,           &mcasp1_fck,    CK_AM33XX),
-	CLK(NULL,	"mcasp0_fck",		&mcasp0_fck,	CK_AM33XX),
-	CLK(NULL,	"mcasp1_fck",		&mcasp1_fck,	CK_AM33XX),
-	CLK("NULL",	"mmc2_fck",		&mmc2_fck,	CK_AM33XX),
-	CLK(NULL,	"mmu_fck",		&mmu_fck,	CK_AM33XX),
-	CLK(NULL,	"smartreflex0_fck",	&smartreflex0_fck,	CK_AM33XX),
-	CLK(NULL,	"smartreflex1_fck",	&smartreflex1_fck,	CK_AM33XX),
-	CLK(NULL,	"timer1_fck",		&timer1_fck,	CK_AM33XX),
-	CLK(NULL,	"timer2_fck",		&timer2_fck,	CK_AM33XX),
-	CLK(NULL,	"timer3_fck",		&timer3_fck,	CK_AM33XX),
-	CLK(NULL,	"timer4_fck",		&timer4_fck,	CK_AM33XX),
-	CLK(NULL,	"timer5_fck",		&timer5_fck,	CK_AM33XX),
-	CLK(NULL,	"timer6_fck",		&timer6_fck,	CK_AM33XX),
-	CLK(NULL,	"timer7_fck",		&timer7_fck,	CK_AM33XX),
-	CLK(NULL,	"usbotg_fck",		&usbotg_fck,	CK_AM33XX),
-	CLK(NULL,	"ieee5000_fck",		&ieee5000_fck,	CK_AM33XX),
-	CLK(NULL,	"wdt1_fck",		&wdt1_fck,	CK_AM33XX),
-	CLK(NULL,	"l4_rtc_gclk",		&l4_rtc_gclk,	CK_AM33XX),
-	CLK(NULL,	"l3_gclk",		&l3_gclk,	CK_AM33XX),
-	CLK(NULL,	"dpll_core_m4_div2_ck",	&dpll_core_m4_div2_ck,	CK_AM33XX),
-	CLK(NULL,	"l4hs_gclk",		&l4hs_gclk,	CK_AM33XX),
-	CLK(NULL,	"l3s_gclk",		&l3s_gclk,	CK_AM33XX),
-	CLK(NULL,	"l4fw_gclk",		&l4fw_gclk,	CK_AM33XX),
-	CLK(NULL,	"l4ls_gclk",		&l4ls_gclk,	CK_AM33XX),
-	CLK(NULL,	"clk_24mhz",		&clk_24mhz,	CK_AM33XX),
-	CLK(NULL,	"sysclk_div_ck",	&sysclk_div_ck,	CK_AM33XX),
-	CLK(NULL,	"cpsw_125mhz_gclk",	&cpsw_125mhz_gclk,	CK_AM33XX),
-	CLK(NULL,	"cpsw_cpts_rft_clk",	&cpsw_cpts_rft_clk,	CK_AM33XX),
-	CLK(NULL,	"gpio0_dbclk_mux_ck",	&gpio0_dbclk_mux_ck,	CK_AM33XX),
-	CLK(NULL,	"gpio0_dbclk",		&gpio0_dbclk,	CK_AM33XX),
-	CLK(NULL,	"gpio1_dbclk",		&gpio1_dbclk,	CK_AM33XX),
-	CLK(NULL,	"gpio2_dbclk",		&gpio2_dbclk,	CK_AM33XX),
-	CLK(NULL,	"gpio3_dbclk",		&gpio3_dbclk,	CK_AM33XX),
-	CLK(NULL,	"lcd_gclk",		&lcd_gclk,	CK_AM33XX),
-	CLK(NULL,	"mmc_clk",		&mmc_clk,	CK_AM33XX),
-	CLK(NULL,	"gfx_fclk_clksel_ck",	&gfx_fclk_clksel_ck,	CK_AM33XX),
-	CLK(NULL,	"gfx_fck_div_ck",	&gfx_fck_div_ck,	CK_AM33XX),
-	CLK(NULL,	"sysclkout_pre_ck",	&sysclkout_pre_ck,	CK_AM33XX),
-	CLK(NULL,	"clkout2_ck",		&clkout2_ck,	CK_AM33XX),
-	CLK(NULL,	"timer_32k_ck",		&clkdiv32k_ick,	CK_AM33XX),
-	CLK(NULL,	"timer_sys_ck",		&sys_clkin_ck,	CK_AM33XX),
-};
-
-int __init am33xx_clk_init(void)
-{
-	struct omap_clk *c;
-	u32 cpu_clkflg;
-
-	if (soc_is_am33xx()) {
-		cpu_mask = RATE_IN_AM33XX;
-		cpu_clkflg = CK_AM33XX;
-	}
-
-	clk_init(&omap2_clk_functions);
-
-	for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++)
-		clk_preinit(c->lk.clk);
-
-	for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++) {
-		if (c->cpu & cpu_clkflg) {
-			clkdev_add(&c->lk);
-			clk_register(c->lk.clk);
-			omap2_init_clk_clkdm(c->lk.clk);
-		}
-	}
-
-	recalculate_root_clocks();
-
-	/*
-	 * Only enable those clocks we will need, let the drivers
-	 * enable other clocks as necessary
-	 */
-	clk_enable_init_clocks();
-
-	return 0;
-}
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 1fc96b9..4596468 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -21,11 +21,9 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/clock.h>
-
 #include "clock.h"
 #include "clock34xx.h"
-#include "cm2xxx_3xxx.h"
+#include "cm3xxx.h"
 #include "cm-regbits-34xx.h"
 
 /**
@@ -39,7 +37,7 @@
  * from the CM_{I,F}CLKEN bit.  Pass back the correct info via
  * @idlest_reg and @idlest_bit.  No return value.
  */
-static void omap3430es2_clk_ssi_find_idlest(struct clk *clk,
+static void omap3430es2_clk_ssi_find_idlest(struct clk_hw_omap *clk,
 					    void __iomem **idlest_reg,
 					    u8 *idlest_bit,
 					    u8 *idlest_val)
@@ -51,21 +49,16 @@ static void omap3430es2_clk_ssi_find_idlest(struct clk *clk,
 	*idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
 	*idlest_val = OMAP34XX_CM_IDLEST_VAL;
 }
-
-const struct clkops clkops_omap3430es2_ssi_wait = {
-	.enable		= omap2_dflt_clk_enable,
-	.disable	= omap2_dflt_clk_disable,
+const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait = {
 	.find_idlest	= omap3430es2_clk_ssi_find_idlest,
-	.find_companion = omap2_clk_dflt_find_companion,
+	.find_companion	= omap2_clk_dflt_find_companion,
 };
 
-const struct clkops clkops_omap3430es2_iclk_ssi_wait = {
-	.enable		= omap2_dflt_clk_enable,
-	.disable	= omap2_dflt_clk_disable,
-	.find_idlest	= omap3430es2_clk_ssi_find_idlest,
-	.find_companion = omap2_clk_dflt_find_companion,
+const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait = {
 	.allow_idle	= omap2_clkt_iclk_allow_idle,
 	.deny_idle	= omap2_clkt_iclk_deny_idle,
+	.find_idlest	= omap3430es2_clk_ssi_find_idlest,
+	.find_companion = omap2_clk_dflt_find_companion,
 };
 
 /**
@@ -82,7 +75,7 @@ const struct clkops clkops_omap3430es2_iclk_ssi_wait = {
  * default find_idlest code assumes that they are at the same
  * position.)  No return value.
  */
-static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk,
+static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk,
 						    void __iomem **idlest_reg,
 						    u8 *idlest_bit,
 						    u8 *idlest_val)
@@ -96,20 +89,16 @@ static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk,
 	*idlest_val = OMAP34XX_CM_IDLEST_VAL;
 }
 
-const struct clkops clkops_omap3430es2_dss_usbhost_wait = {
-	.enable		= omap2_dflt_clk_enable,
-	.disable	= omap2_dflt_clk_disable,
+const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait = {
 	.find_idlest	= omap3430es2_clk_dss_usbhost_find_idlest,
-	.find_companion = omap2_clk_dflt_find_companion,
+	.find_companion	= omap2_clk_dflt_find_companion,
 };
 
-const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait = {
-	.enable		= omap2_dflt_clk_enable,
-	.disable	= omap2_dflt_clk_disable,
-	.find_idlest	= omap3430es2_clk_dss_usbhost_find_idlest,
-	.find_companion = omap2_clk_dflt_find_companion,
+const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait = {
 	.allow_idle	= omap2_clkt_iclk_allow_idle,
 	.deny_idle	= omap2_clkt_iclk_deny_idle,
+	.find_idlest	= omap3430es2_clk_dss_usbhost_find_idlest,
+	.find_companion	= omap2_clk_dflt_find_companion,
 };
 
 /**
@@ -123,7 +112,7 @@ const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait = {
  * shift from the CM_{I,F}CLKEN bit.  Pass back the correct info via
  * @idlest_reg and @idlest_bit.  No return value.
  */
-static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk,
+static void omap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk,
 						 void __iomem **idlest_reg,
 						 u8 *idlest_bit,
 						 u8 *idlest_val)
@@ -136,18 +125,14 @@ static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk,
 	*idlest_val = OMAP34XX_CM_IDLEST_VAL;
 }
 
-const struct clkops clkops_omap3430es2_hsotgusb_wait = {
-	.enable		= omap2_dflt_clk_enable,
-	.disable	= omap2_dflt_clk_disable,
+const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait = {
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
 	.find_idlest	= omap3430es2_clk_hsotgusb_find_idlest,
-	.find_companion = omap2_clk_dflt_find_companion,
+	.find_companion	= omap2_clk_dflt_find_companion,
 };
 
-const struct clkops clkops_omap3430es2_iclk_hsotgusb_wait = {
-	.enable		= omap2_dflt_clk_enable,
-	.disable	= omap2_dflt_clk_disable,
+const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait = {
 	.find_idlest	= omap3430es2_clk_hsotgusb_find_idlest,
-	.find_companion = omap2_clk_dflt_find_companion,
-	.allow_idle	= omap2_clkt_iclk_allow_idle,
-	.deny_idle	= omap2_clkt_iclk_deny_idle,
+	.find_companion	= omap2_clk_dflt_find_companion,
 };
diff --git a/arch/arm/mach-omap2/clock3517.c b/arch/arm/mach-omap2/clock3517.c
index 2e97d08..4d79ae2 100644
--- a/arch/arm/mach-omap2/clock3517.c
+++ b/arch/arm/mach-omap2/clock3517.c
@@ -21,11 +21,9 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/clock.h>
-
 #include "clock.h"
 #include "clock3517.h"
-#include "cm2xxx_3xxx.h"
+#include "cm3xxx.h"
 #include "cm-regbits-34xx.h"
 
 /*
@@ -49,7 +47,7 @@
  * in the enable register itsel at a bit offset of 4 from the enable
  * bit. A value of 1 indicates that clock is enabled.
  */
-static void am35xx_clk_find_idlest(struct clk *clk,
+static void am35xx_clk_find_idlest(struct clk_hw_omap *clk,
 					    void __iomem **idlest_reg,
 					    u8 *idlest_bit,
 					    u8 *idlest_val)
@@ -73,8 +71,9 @@ static void am35xx_clk_find_idlest(struct clk *clk,
  * associate this type of code with per-module data structures to
  * avoid this issue, and remove the casts.  No return value.
  */
-static void am35xx_clk_find_companion(struct clk *clk, void __iomem **other_reg,
-					    u8 *other_bit)
+static void am35xx_clk_find_companion(struct clk_hw_omap *clk,
+				      void __iomem **other_reg,
+				      u8 *other_bit)
 {
 	*other_reg = (__force void __iomem *)(clk->enable_reg);
 	if (clk->enable_bit & AM35XX_IPSS_ICK_MASK)
@@ -82,10 +81,7 @@ static void am35xx_clk_find_companion(struct clk *clk, void __iomem **other_reg,
 	else
 		*other_bit = clk->enable_bit - AM35XX_IPSS_ICK_FCK_OFFSET;
 }
-
-const struct clkops clkops_am35xx_ipss_module_wait = {
-	.enable		= omap2_dflt_clk_enable,
-	.disable	= omap2_dflt_clk_disable,
+const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait = {
 	.find_idlest	= am35xx_clk_find_idlest,
 	.find_companion	= am35xx_clk_find_companion,
 };
@@ -101,7 +97,7 @@ const struct clkops clkops_am35xx_ipss_module_wait = {
  * CM_{I,F}CLKEN bit.  Pass back the correct info via @idlest_reg
  * and @idlest_bit.  No return value.
  */
-static void am35xx_clk_ipss_find_idlest(struct clk *clk,
+static void am35xx_clk_ipss_find_idlest(struct clk_hw_omap *clk,
 					    void __iomem **idlest_reg,
 					    u8 *idlest_bit,
 					    u8 *idlest_val)
@@ -114,13 +110,9 @@ static void am35xx_clk_ipss_find_idlest(struct clk *clk,
 	*idlest_val = OMAP34XX_CM_IDLEST_VAL;
 }
 
-const struct clkops clkops_am35xx_ipss_wait = {
-	.enable		= omap2_dflt_clk_enable,
-	.disable	= omap2_dflt_clk_disable,
-	.find_idlest	= am35xx_clk_ipss_find_idlest,
-	.find_companion	= omap2_clk_dflt_find_companion,
+const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait = {
 	.allow_idle	= omap2_clkt_iclk_allow_idle,
 	.deny_idle	= omap2_clkt_iclk_deny_idle,
+	.find_idlest	= am35xx_clk_ipss_find_idlest,
+	.find_companion	= omap2_clk_dflt_find_companion,
 };
-
-
diff --git a/arch/arm/mach-omap2/clock36xx.c b/arch/arm/mach-omap2/clock36xx.c
index 0c5e25e..8f3bf4e 100644
--- a/arch/arm/mach-omap2/clock36xx.c
+++ b/arch/arm/mach-omap2/clock36xx.c
@@ -22,8 +22,6 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/clock.h>
-
 #include "clock.h"
 #include "clock36xx.h"
 
@@ -39,34 +37,32 @@
  * (Any other value different from the Read value) to the
  * corresponding CM_CLKSEL register will refresh the dividers.
  */
-static int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk *clk)
+int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
 {
+	struct clk_hw_omap *parent;
+	struct clk_hw *parent_hw;
 	u32 dummy_v, orig_v, clksel_shift;
 	int ret;
 
 	/* Clear PWRDN bit of HSDIVIDER */
 	ret = omap2_dflt_clk_enable(clk);
 
+	parent_hw = __clk_get_hw(__clk_get_parent(clk->clk));
+	parent = to_clk_hw_omap(parent_hw);
+
 	/* Restore the dividers */
 	if (!ret) {
-		clksel_shift = __ffs(clk->parent->clksel_mask);
-		orig_v = __raw_readl(clk->parent->clksel_reg);
+		clksel_shift = __ffs(parent->clksel_mask);
+		orig_v = __raw_readl(parent->clksel_reg);
 		dummy_v = orig_v;
 
 		/* Write any other value different from the Read value */
 		dummy_v ^= (1 << clksel_shift);
-		__raw_writel(dummy_v, clk->parent->clksel_reg);
+		__raw_writel(dummy_v, parent->clksel_reg);
 
 		/* Write the original divider */
-		__raw_writel(orig_v, clk->parent->clksel_reg);
+		__raw_writel(orig_v, parent->clksel_reg);
 	}
 
 	return ret;
 }
-
-const struct clkops clkops_omap36xx_pwrdn_with_hsdiv_wait_restore = {
-	.enable		= omap36xx_pwrdn_clk_enable_with_hsdiv_restore,
-	.disable	= omap2_dflt_clk_disable,
-	.find_companion	= omap2_clk_dflt_find_companion,
-	.find_idlest	= omap2_clk_dflt_find_idlest,
-};
diff --git a/arch/arm/mach-omap2/clock36xx.h b/arch/arm/mach-omap2/clock36xx.h
index a7dee5b..945bb7f 100644
--- a/arch/arm/mach-omap2/clock36xx.h
+++ b/arch/arm/mach-omap2/clock36xx.h
@@ -8,6 +8,6 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK36XX_H
 #define __ARCH_ARM_MACH_OMAP2_CLOCK36XX_H
 
-extern const struct clkops clkops_omap36xx_pwrdn_with_hsdiv_wait_restore;
+extern int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *hw);
 
 #endif
diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c
index 83bb014..4eacab8 100644
--- a/arch/arm/mach-omap2/clock3xxx.c
+++ b/arch/arm/mach-omap2/clock3xxx.c
@@ -21,8 +21,6 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/clock.h>
-
 #include "soc.h"
 #include "clock.h"
 #include "clock3xxx.h"
@@ -40,8 +38,8 @@
 
 /* needed by omap3_core_dpll_m2_set_rate() */
 struct clk *sdrc_ick_p, *arm_fck_p;
-
-int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
+int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
 {
 	/*
 	 * According to the 12-5 CDP code from TI, "Limitation 2.5"
@@ -53,7 +51,7 @@ int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
 		return -EINVAL;
 	}
 
-	return omap3_noncore_dpll_set_rate(clk, rate);
+	return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
 }
 
 void __init omap3_clk_lock_dpll5(void)
diff --git a/arch/arm/mach-omap2/clock3xxx.h b/arch/arm/mach-omap2/clock3xxx.h
index 8bbeeaf..8cd4b0a 100644
--- a/arch/arm/mach-omap2/clock3xxx.h
+++ b/arch/arm/mach-omap2/clock3xxx.h
@@ -9,8 +9,10 @@
 #define __ARCH_ARM_MACH_OMAP2_CLOCK3XXX_H
 
 int omap3xxx_clk_init(void);
-int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate);
-int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate);
+int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
+					unsigned long parent_rate);
+int omap3_core_dpll_m2_set_rate(struct clk_hw *clk, unsigned long rate,
+					unsigned long parent_rate);
 void omap3_clk_lock_dpll5(void);
 
 extern struct clk *sdrc_ick_p;
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
deleted file mode 100644
index 1f42c9d..0000000
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ /dev/null
@@ -1,3617 +0,0 @@
-/*
- * OMAP3 clock data
- *
- * Copyright (C) 2007-2010, 2012 Texas Instruments, Inc.
- * Copyright (C) 2007-2011 Nokia Corporation
- *
- * Written by Paul Walmsley
- * With many device clock fixes by Kevin Hilman and Jouni Högander
- * DPLL bypass clock support added by Roman Tereshonkov
- *
- */
-
-/*
- * Virtual clocks are introduced as convenient tools.
- * They are sources for other clocks and not supposed
- * to be requested from drivers directly.
- */
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/list.h>
-#include <linux/io.h>
-
-#include <plat/clkdev_omap.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "clock3xxx.h"
-#include "clock34xx.h"
-#include "clock36xx.h"
-#include "clock3517.h"
-#include "cm2xxx_3xxx.h"
-#include "cm-regbits-34xx.h"
-#include "prm2xxx_3xxx.h"
-#include "prm-regbits-34xx.h"
-#include "control.h"
-
-/*
- * clocks
- */
-
-#define OMAP_CM_REGADDR		OMAP34XX_CM_REGADDR
-
-/* Maximum DPLL multiplier, divider values for OMAP3 */
-#define OMAP3_MAX_DPLL_MULT		2047
-#define OMAP3630_MAX_JTYPE_DPLL_MULT	4095
-#define OMAP3_MAX_DPLL_DIV		128
-
-/*
- * DPLL1 supplies clock to the MPU.
- * DPLL2 supplies clock to the IVA2.
- * DPLL3 supplies CORE domain clocks.
- * DPLL4 supplies peripheral clocks.
- * DPLL5 supplies other peripheral clocks (USBHOST, USIM).
- */
-
-/* Forward declarations for DPLL bypass clocks */
-static struct clk dpll1_fck;
-static struct clk dpll2_fck;
-
-/* PRM CLOCKS */
-
-/* According to timer32k.c, this is a 32768Hz clock, not a 32000Hz clock. */
-static struct clk omap_32k_fck = {
-	.name		= "omap_32k_fck",
-	.ops		= &clkops_null,
-	.rate		= 32768,
-};
-
-static struct clk secure_32k_fck = {
-	.name		= "secure_32k_fck",
-	.ops		= &clkops_null,
-	.rate		= 32768,
-};
-
-/* Virtual source clocks for osc_sys_ck */
-static struct clk virt_12m_ck = {
-	.name		= "virt_12m_ck",
-	.ops		= &clkops_null,
-	.rate		= 12000000,
-};
-
-static struct clk virt_13m_ck = {
-	.name		= "virt_13m_ck",
-	.ops		= &clkops_null,
-	.rate		= 13000000,
-};
-
-static struct clk virt_16_8m_ck = {
-	.name		= "virt_16_8m_ck",
-	.ops		= &clkops_null,
-	.rate		= 16800000,
-};
-
-static struct clk virt_38_4m_ck = {
-	.name		= "virt_38_4m_ck",
-	.ops		= &clkops_null,
-	.rate		= 38400000,
-};
-
-static const struct clksel_rate osc_sys_12m_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate osc_sys_13m_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate osc_sys_16_8m_rates[] = {
-	{ .div = 1, .val = 5, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate osc_sys_19_2m_rates[] = {
-	{ .div = 1, .val = 2, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate osc_sys_26m_rates[] = {
-	{ .div = 1, .val = 3, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate osc_sys_38_4m_rates[] = {
-	{ .div = 1, .val = 4, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel osc_sys_clksel[] = {
-	{ .parent = &virt_12m_ck,   .rates = osc_sys_12m_rates },
-	{ .parent = &virt_13m_ck,   .rates = osc_sys_13m_rates },
-	{ .parent = &virt_16_8m_ck, .rates = osc_sys_16_8m_rates },
-	{ .parent = &virt_19200000_ck, .rates = osc_sys_19_2m_rates },
-	{ .parent = &virt_26000000_ck,   .rates = osc_sys_26m_rates },
-	{ .parent = &virt_38_4m_ck, .rates = osc_sys_38_4m_rates },
-	{ .parent = NULL },
-};
-
-/* Oscillator clock */
-/* 12, 13, 16.8, 19.2, 26, or 38.4 MHz */
-static struct clk osc_sys_ck = {
-	.name		= "osc_sys_ck",
-	.ops		= &clkops_null,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP3430_PRM_CLKSEL,
-	.clksel_mask	= OMAP3430_SYS_CLKIN_SEL_MASK,
-	.clksel		= osc_sys_clksel,
-	/* REVISIT: deal with autoextclkmode? */
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate div2_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel sys_clksel[] = {
-	{ .parent = &osc_sys_ck, .rates = div2_rates },
-	{ .parent = NULL }
-};
-
-/* Latency: this clock is only enabled after PRM_CLKSETUP.SETUP_TIME */
-/* Feeds DPLLs - divided first by PRM_CLKSRC_CTRL.SYSCLKDIV? */
-static struct clk sys_ck = {
-	.name		= "sys_ck",
-	.ops		= &clkops_null,
-	.parent		= &osc_sys_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP3430_PRM_CLKSRC_CTRL,
-	.clksel_mask	= OMAP_SYSCLKDIV_MASK,
-	.clksel		= sys_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk sys_altclk = {
-	.name		= "sys_altclk",
-	.ops		= &clkops_null,
-};
-
-/* Optional external clock input for some McBSPs */
-static struct clk mcbsp_clks = {
-	.name		= "mcbsp_clks",
-	.ops		= &clkops_null,
-};
-
-/* PRM EXTERNAL CLOCK OUTPUT */
-
-static struct clk sys_clkout1 = {
-	.name		= "sys_clkout1",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &osc_sys_ck,
-	.enable_reg	= OMAP3430_PRM_CLKOUT_CTRL,
-	.enable_bit	= OMAP3430_CLKOUT_EN_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/* DPLLS */
-
-/* CM CLOCKS */
-
-static const struct clksel_rate div16_dpll_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_3XXX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_3XXX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_3XXX },
-	{ .div = 5, .val = 5, .flags = RATE_IN_3XXX },
-	{ .div = 6, .val = 6, .flags = RATE_IN_3XXX },
-	{ .div = 7, .val = 7, .flags = RATE_IN_3XXX },
-	{ .div = 8, .val = 8, .flags = RATE_IN_3XXX },
-	{ .div = 9, .val = 9, .flags = RATE_IN_3XXX },
-	{ .div = 10, .val = 10, .flags = RATE_IN_3XXX },
-	{ .div = 11, .val = 11, .flags = RATE_IN_3XXX },
-	{ .div = 12, .val = 12, .flags = RATE_IN_3XXX },
-	{ .div = 13, .val = 13, .flags = RATE_IN_3XXX },
-	{ .div = 14, .val = 14, .flags = RATE_IN_3XXX },
-	{ .div = 15, .val = 15, .flags = RATE_IN_3XXX },
-	{ .div = 16, .val = 16, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate dpll4_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_3XXX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_3XXX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_3XXX },
-	{ .div = 5, .val = 5, .flags = RATE_IN_3XXX },
-	{ .div = 6, .val = 6, .flags = RATE_IN_3XXX },
-	{ .div = 7, .val = 7, .flags = RATE_IN_3XXX },
-	{ .div = 8, .val = 8, .flags = RATE_IN_3XXX },
-	{ .div = 9, .val = 9, .flags = RATE_IN_3XXX },
-	{ .div = 10, .val = 10, .flags = RATE_IN_3XXX },
-	{ .div = 11, .val = 11, .flags = RATE_IN_3XXX },
-	{ .div = 12, .val = 12, .flags = RATE_IN_3XXX },
-	{ .div = 13, .val = 13, .flags = RATE_IN_3XXX },
-	{ .div = 14, .val = 14, .flags = RATE_IN_3XXX },
-	{ .div = 15, .val = 15, .flags = RATE_IN_3XXX },
-	{ .div = 16, .val = 16, .flags = RATE_IN_3XXX },
-	{ .div = 17, .val = 17, .flags = RATE_IN_36XX },
-	{ .div = 18, .val = 18, .flags = RATE_IN_36XX },
-	{ .div = 19, .val = 19, .flags = RATE_IN_36XX },
-	{ .div = 20, .val = 20, .flags = RATE_IN_36XX },
-	{ .div = 21, .val = 21, .flags = RATE_IN_36XX },
-	{ .div = 22, .val = 22, .flags = RATE_IN_36XX },
-	{ .div = 23, .val = 23, .flags = RATE_IN_36XX },
-	{ .div = 24, .val = 24, .flags = RATE_IN_36XX },
-	{ .div = 25, .val = 25, .flags = RATE_IN_36XX },
-	{ .div = 26, .val = 26, .flags = RATE_IN_36XX },
-	{ .div = 27, .val = 27, .flags = RATE_IN_36XX },
-	{ .div = 28, .val = 28, .flags = RATE_IN_36XX },
-	{ .div = 29, .val = 29, .flags = RATE_IN_36XX },
-	{ .div = 30, .val = 30, .flags = RATE_IN_36XX },
-	{ .div = 31, .val = 31, .flags = RATE_IN_36XX },
-	{ .div = 32, .val = 32, .flags = RATE_IN_36XX },
-	{ .div = 0 }
-};
-
-/* DPLL1 */
-/* MPU clock source */
-/* Type: DPLL */
-static struct dpll_data dpll1_dd = {
-	.mult_div1_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
-	.mult_mask	= OMAP3430_MPU_DPLL_MULT_MASK,
-	.div1_mask	= OMAP3430_MPU_DPLL_DIV_MASK,
-	.clk_bypass	= &dpll1_fck,
-	.clk_ref	= &sys_ck,
-	.freqsel_mask	= OMAP3430_MPU_DPLL_FREQSEL_MASK,
-	.control_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKEN_PLL),
-	.enable_mask	= OMAP3430_EN_MPU_DPLL_MASK,
-	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-	.auto_recal_bit	= OMAP3430_EN_MPU_DPLL_DRIFTGUARD_SHIFT,
-	.recal_en_bit	= OMAP3430_MPU_DPLL_RECAL_EN_SHIFT,
-	.recal_st_bit	= OMAP3430_MPU_DPLL_ST_SHIFT,
-	.autoidle_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL),
-	.autoidle_mask	= OMAP3430_AUTO_MPU_DPLL_MASK,
-	.idlest_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
-	.idlest_mask	= OMAP3430_ST_MPU_CLK_MASK,
-	.max_multiplier = OMAP3_MAX_DPLL_MULT,
-	.min_divider	= 1,
-	.max_divider	= OMAP3_MAX_DPLL_DIV,
-};
-
-static struct clk dpll1_ck = {
-	.name		= "dpll1_ck",
-	.ops		= &clkops_omap3_noncore_dpll_ops,
-	.parent		= &sys_ck,
-	.dpll_data	= &dpll1_dd,
-	.round_rate	= &omap2_dpll_round_rate,
-	.set_rate	= &omap3_noncore_dpll_set_rate,
-	.clkdm_name	= "dpll1_clkdm",
-	.recalc		= &omap3_dpll_recalc,
-};
-
-/*
- * This virtual clock provides the CLKOUTX2 output from the DPLL if the
- * DPLL isn't bypassed.
- */
-static struct clk dpll1_x2_ck = {
-	.name		= "dpll1_x2_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll1_ck,
-	.clkdm_name	= "dpll1_clkdm",
-	.recalc		= &omap3_clkoutx2_recalc,
-};
-
-/* On DPLL1, unlike other DPLLs, the divider is downstream from CLKOUTX2 */
-static const struct clksel div16_dpll1_x2m2_clksel[] = {
-	{ .parent = &dpll1_x2_ck, .rates = div16_dpll_rates },
-	{ .parent = NULL }
-};
-
-/*
- * Does not exist in the TRM - needed to separate the M2 divider from
- * bypass selection in mpu_ck
- */
-static struct clk dpll1_x2m2_ck = {
-	.name		= "dpll1_x2m2_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll1_x2_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL),
-	.clksel_mask	= OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK,
-	.clksel		= div16_dpll1_x2m2_clksel,
-	.clkdm_name	= "dpll1_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* DPLL2 */
-/* IVA2 clock source */
-/* Type: DPLL */
-
-static struct dpll_data dpll2_dd = {
-	.mult_div1_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
-	.mult_mask	= OMAP3430_IVA2_DPLL_MULT_MASK,
-	.div1_mask	= OMAP3430_IVA2_DPLL_DIV_MASK,
-	.clk_bypass	= &dpll2_fck,
-	.clk_ref	= &sys_ck,
-	.freqsel_mask	= OMAP3430_IVA2_DPLL_FREQSEL_MASK,
-	.control_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL),
-	.enable_mask	= OMAP3430_EN_IVA2_DPLL_MASK,
-	.modes		= (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED) |
-				(1 << DPLL_LOW_POWER_BYPASS),
-	.auto_recal_bit	= OMAP3430_EN_IVA2_DPLL_DRIFTGUARD_SHIFT,
-	.recal_en_bit	= OMAP3430_PRM_IRQENABLE_MPU_IVA2_DPLL_RECAL_EN_SHIFT,
-	.recal_st_bit	= OMAP3430_PRM_IRQSTATUS_MPU_IVA2_DPLL_ST_SHIFT,
-	.autoidle_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL),
-	.autoidle_mask	= OMAP3430_AUTO_IVA2_DPLL_MASK,
-	.idlest_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_IDLEST_PLL),
-	.idlest_mask	= OMAP3430_ST_IVA2_CLK_MASK,
-	.max_multiplier = OMAP3_MAX_DPLL_MULT,
-	.min_divider	= 1,
-	.max_divider	= OMAP3_MAX_DPLL_DIV,
-};
-
-static struct clk dpll2_ck = {
-	.name		= "dpll2_ck",
-	.ops		= &clkops_omap3_noncore_dpll_ops,
-	.parent		= &sys_ck,
-	.dpll_data	= &dpll2_dd,
-	.round_rate	= &omap2_dpll_round_rate,
-	.set_rate	= &omap3_noncore_dpll_set_rate,
-	.clkdm_name	= "dpll2_clkdm",
-	.recalc		= &omap3_dpll_recalc,
-};
-
-static const struct clksel div16_dpll2_m2x2_clksel[] = {
-	{ .parent = &dpll2_ck, .rates = div16_dpll_rates },
-	{ .parent = NULL }
-};
-
-/*
- * The TRM is conflicted on whether IVA2 clock comes from DPLL2 CLKOUT
- * or CLKOUTX2. CLKOUT seems most plausible.
- */
-static struct clk dpll2_m2_ck = {
-	.name		= "dpll2_m2_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll2_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD,
-					  OMAP3430_CM_CLKSEL2_PLL),
-	.clksel_mask	= OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK,
-	.clksel		= div16_dpll2_m2x2_clksel,
-	.clkdm_name	= "dpll2_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/*
- * DPLL3
- * Source clock for all interfaces and for some device fclks
- * REVISIT: Also supports fast relock bypass - not included below
- */
-static struct dpll_data dpll3_dd = {
-	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.mult_mask	= OMAP3430_CORE_DPLL_MULT_MASK,
-	.div1_mask	= OMAP3430_CORE_DPLL_DIV_MASK,
-	.clk_bypass	= &sys_ck,
-	.clk_ref	= &sys_ck,
-	.freqsel_mask	= OMAP3430_CORE_DPLL_FREQSEL_MASK,
-	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_mask	= OMAP3430_EN_CORE_DPLL_MASK,
-	.auto_recal_bit	= OMAP3430_EN_CORE_DPLL_DRIFTGUARD_SHIFT,
-	.recal_en_bit	= OMAP3430_CORE_DPLL_RECAL_EN_SHIFT,
-	.recal_st_bit	= OMAP3430_CORE_DPLL_ST_SHIFT,
-	.autoidle_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
-	.autoidle_mask	= OMAP3430_AUTO_CORE_DPLL_MASK,
-	.idlest_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-	.idlest_mask	= OMAP3430_ST_CORE_CLK_MASK,
-	.max_multiplier = OMAP3_MAX_DPLL_MULT,
-	.min_divider	= 1,
-	.max_divider	= OMAP3_MAX_DPLL_DIV,
-};
-
-static struct clk dpll3_ck = {
-	.name		= "dpll3_ck",
-	.ops		= &clkops_omap3_core_dpll_ops,
-	.parent		= &sys_ck,
-	.dpll_data	= &dpll3_dd,
-	.round_rate	= &omap2_dpll_round_rate,
-	.clkdm_name	= "dpll3_clkdm",
-	.recalc		= &omap3_dpll_recalc,
-};
-
-/*
- * This virtual clock provides the CLKOUTX2 output from the DPLL if the
- * DPLL isn't bypassed
- */
-static struct clk dpll3_x2_ck = {
-	.name		= "dpll3_x2_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll3_ck,
-	.clkdm_name	= "dpll3_clkdm",
-	.recalc		= &omap3_clkoutx2_recalc,
-};
-
-static const struct clksel_rate div31_dpll3_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_3XXX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 5, .val = 5, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 6, .val = 6, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 7, .val = 7, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 8, .val = 8, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 9, .val = 9, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 10, .val = 10, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 11, .val = 11, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 12, .val = 12, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 13, .val = 13, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 14, .val = 14, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 15, .val = 15, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 16, .val = 16, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 17, .val = 17, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 18, .val = 18, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 19, .val = 19, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 20, .val = 20, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 21, .val = 21, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 22, .val = 22, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 23, .val = 23, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 24, .val = 24, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 25, .val = 25, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 26, .val = 26, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 27, .val = 27, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 28, .val = 28, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 29, .val = 29, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 30, .val = 30, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 31, .val = 31, .flags = RATE_IN_3430ES2PLUS_36XX },
-	{ .div = 0 },
-};
-
-static const struct clksel div31_dpll3m2_clksel[] = {
-	{ .parent = &dpll3_ck, .rates = div31_dpll3_rates },
-	{ .parent = NULL }
-};
-
-/* DPLL3 output M2 - primary control point for CORE speed */
-static struct clk dpll3_m2_ck = {
-	.name		= "dpll3_m2_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll3_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK,
-	.clksel		= div31_dpll3m2_clksel,
-	.clkdm_name	= "dpll3_clkdm",
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap3_core_dpll_m2_set_rate,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk core_ck = {
-	.name		= "core_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll3_m2_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dpll3_m2x2_ck = {
-	.name		= "dpll3_m2x2_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll3_m2_ck,
-	.clkdm_name	= "dpll3_clkdm",
-	.recalc		= &omap3_clkoutx2_recalc,
-};
-
-/* The PWRDN bit is apparently only available on 3430ES2 and above */
-static const struct clksel div16_dpll3_clksel[] = {
-	{ .parent = &dpll3_ck, .rates = div16_dpll_rates },
-	{ .parent = NULL }
-};
-
-/* This virtual clock is the source for dpll3_m3x2_ck */
-static struct clk dpll3_m3_ck = {
-	.name		= "dpll3_m3_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll3_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP3430_DIV_DPLL3_MASK,
-	.clksel		= div16_dpll3_clksel,
-	.clkdm_name	= "dpll3_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* The PWRDN bit is apparently only available on 3430ES2 and above */
-static struct clk dpll3_m3x2_ck = {
-	.name		= "dpll3_m3x2_ck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &dpll3_m3_ck,
-	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_bit	= OMAP3430_PWRDN_EMU_CORE_SHIFT,
-	.flags		= INVERT_ENABLE,
-	.clkdm_name	= "dpll3_clkdm",
-	.recalc		= &omap3_clkoutx2_recalc,
-};
-
-static struct clk emu_core_alwon_ck = {
-	.name		= "emu_core_alwon_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll3_m3x2_ck,
-	.clkdm_name	= "dpll3_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* DPLL4 */
-/* Supplies 96MHz, 54Mhz TV DAC, DSS fclk, CAM sensor clock, emul trace clk */
-/* Type: DPLL */
-static struct dpll_data dpll4_dd;
-
-static struct dpll_data dpll4_dd_34xx __initdata = {
-	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
-	.mult_mask	= OMAP3430_PERIPH_DPLL_MULT_MASK,
-	.div1_mask	= OMAP3430_PERIPH_DPLL_DIV_MASK,
-	.clk_bypass	= &sys_ck,
-	.clk_ref	= &sys_ck,
-	.freqsel_mask	= OMAP3430_PERIPH_DPLL_FREQSEL_MASK,
-	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_mask	= OMAP3430_EN_PERIPH_DPLL_MASK,
-	.modes		= (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
-	.auto_recal_bit	= OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT,
-	.recal_en_bit	= OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT,
-	.recal_st_bit	= OMAP3430_PERIPH_DPLL_ST_SHIFT,
-	.autoidle_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
-	.autoidle_mask	= OMAP3430_AUTO_PERIPH_DPLL_MASK,
-	.idlest_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-	.idlest_mask	= OMAP3430_ST_PERIPH_CLK_MASK,
-	.max_multiplier = OMAP3_MAX_DPLL_MULT,
-	.min_divider	= 1,
-	.max_divider	= OMAP3_MAX_DPLL_DIV,
-};
-
-static struct dpll_data dpll4_dd_3630 __initdata = {
-	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
-	.mult_mask	= OMAP3630_PERIPH_DPLL_MULT_MASK,
-	.div1_mask	= OMAP3430_PERIPH_DPLL_DIV_MASK,
-	.clk_bypass	= &sys_ck,
-	.clk_ref	= &sys_ck,
-	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_mask	= OMAP3430_EN_PERIPH_DPLL_MASK,
-	.modes		= (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
-	.auto_recal_bit	= OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT,
-	.recal_en_bit	= OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT,
-	.recal_st_bit	= OMAP3430_PERIPH_DPLL_ST_SHIFT,
-	.autoidle_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
-	.autoidle_mask	= OMAP3430_AUTO_PERIPH_DPLL_MASK,
-	.idlest_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-	.idlest_mask	= OMAP3430_ST_PERIPH_CLK_MASK,
-	.dco_mask	= OMAP3630_PERIPH_DPLL_DCO_SEL_MASK,
-	.sddiv_mask	= OMAP3630_PERIPH_DPLL_SD_DIV_MASK,
-	.max_multiplier = OMAP3630_MAX_JTYPE_DPLL_MULT,
-	.min_divider	= 1,
-	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.flags		= DPLL_J_TYPE
-};
-
-static struct clk dpll4_ck = {
-	.name		= "dpll4_ck",
-	.ops		= &clkops_omap3_noncore_dpll_ops,
-	.parent		= &sys_ck,
-	.dpll_data	= &dpll4_dd,
-	.round_rate	= &omap2_dpll_round_rate,
-	.set_rate	= &omap3_dpll4_set_rate,
-	.clkdm_name	= "dpll4_clkdm",
-	.recalc		= &omap3_dpll_recalc,
-};
-
-/*
- * This virtual clock provides the CLKOUTX2 output from the DPLL if the
- * DPLL isn't bypassed --
- * XXX does this serve any downstream clocks?
- */
-static struct clk dpll4_x2_ck = {
-	.name		= "dpll4_x2_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll4_ck,
-	.clkdm_name	= "dpll4_clkdm",
-	.recalc		= &omap3_clkoutx2_recalc,
-};
-
-static const struct clksel dpll4_clksel[] = {
-	{ .parent = &dpll4_ck, .rates = dpll4_rates },
-	{ .parent = NULL }
-};
-
-/* This virtual clock is the source for dpll4_m2x2_ck */
-static struct clk dpll4_m2_ck = {
-	.name		= "dpll4_m2_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll4_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430_CM_CLKSEL3),
-	.clksel_mask	= OMAP3630_DIV_96M_MASK,
-	.clksel		= dpll4_clksel,
-	.clkdm_name	= "dpll4_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* The PWRDN bit is apparently only available on 3430ES2 and above */
-static struct clk dpll4_m2x2_ck = {
-	.name		= "dpll4_m2x2_ck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &dpll4_m2_ck,
-	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_bit	= OMAP3430_PWRDN_96M_SHIFT,
-	.flags		= INVERT_ENABLE,
-	.clkdm_name	= "dpll4_clkdm",
-	.recalc		= &omap3_clkoutx2_recalc,
-};
-
-/*
- * DPLL4 generates DPLL4_M2X2_CLK which is then routed into the PRM as
- * PRM_96M_ALWON_(F)CLK.  Two clocks then emerge from the PRM:
- * 96M_ALWON_FCLK (called "omap_96m_alwon_fck" below) and
- * CM_96K_(F)CLK.
- */
-
-/* Adding 192MHz Clock node needed by SGX */
-static struct clk omap_192m_alwon_fck = {
-	.name		= "omap_192m_alwon_fck",
-	.ops		= &clkops_null,
-	.parent		= &dpll4_m2x2_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel_rate omap_96m_alwon_fck_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_36XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_36XX },
-	{ .div = 0 }
-};
-
-static const struct clksel omap_96m_alwon_fck_clksel[] = {
-	{ .parent = &omap_192m_alwon_fck, .rates = omap_96m_alwon_fck_rates },
-	{ .parent = NULL }
-};
-
-static const struct clksel_rate omap_96m_dpll_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate omap_96m_sys_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static struct clk omap_96m_alwon_fck = {
-	.name		= "omap_96m_alwon_fck",
-	.ops		= &clkops_null,
-	.parent		= &dpll4_m2x2_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk omap_96m_alwon_fck_3630 = {
-	.name		= "omap_96m_alwon_fck",
-	.parent		= &omap_192m_alwon_fck,
-	.init		= &omap2_init_clksel_parent,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3630_CLKSEL_96M_MASK,
-	.clksel		= omap_96m_alwon_fck_clksel
-};
-
-static struct clk cm_96m_fck = {
-	.name		= "cm_96m_fck",
-	.ops		= &clkops_null,
-	.parent		= &omap_96m_alwon_fck,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel omap_96m_fck_clksel[] = {
-	{ .parent = &cm_96m_fck, .rates = omap_96m_dpll_rates },
-	{ .parent = &sys_ck,	 .rates = omap_96m_sys_rates },
-	{ .parent = NULL }
-};
-
-static struct clk omap_96m_fck = {
-	.name		= "omap_96m_fck",
-	.ops		= &clkops_null,
-	.parent		= &sys_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP3430_SOURCE_96M_MASK,
-	.clksel		= omap_96m_fck_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* This virtual clock is the source for dpll4_m3x2_ck */
-static struct clk dpll4_m3_ck = {
-	.name		= "dpll4_m3_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll4_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3630_CLKSEL_TV_MASK,
-	.clksel		= dpll4_clksel,
-	.clkdm_name	= "dpll4_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* The PWRDN bit is apparently only available on 3430ES2 and above */
-static struct clk dpll4_m3x2_ck = {
-	.name		= "dpll4_m3x2_ck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &dpll4_m3_ck,
-	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_bit	= OMAP3430_PWRDN_TV_SHIFT,
-	.flags		= INVERT_ENABLE,
-	.clkdm_name	= "dpll4_clkdm",
-	.recalc		= &omap3_clkoutx2_recalc,
-};
-
-static const struct clksel_rate omap_54m_d4m3x2_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate omap_54m_alt_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel omap_54m_clksel[] = {
-	{ .parent = &dpll4_m3x2_ck, .rates = omap_54m_d4m3x2_rates },
-	{ .parent = &sys_altclk,    .rates = omap_54m_alt_rates },
-	{ .parent = NULL }
-};
-
-static struct clk omap_54m_fck = {
-	.name		= "omap_54m_fck",
-	.ops		= &clkops_null,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP3430_SOURCE_54M_MASK,
-	.clksel		= omap_54m_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate omap_48m_cm96m_rates[] = {
-	{ .div = 2, .val = 0, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate omap_48m_alt_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel omap_48m_clksel[] = {
-	{ .parent = &cm_96m_fck, .rates = omap_48m_cm96m_rates },
-	{ .parent = &sys_altclk, .rates = omap_48m_alt_rates },
-	{ .parent = NULL }
-};
-
-static struct clk omap_48m_fck = {
-	.name		= "omap_48m_fck",
-	.ops		= &clkops_null,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP3430_SOURCE_48M_MASK,
-	.clksel		= omap_48m_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk omap_12m_fck = {
-	.name		= "omap_12m_fck",
-	.ops		= &clkops_null,
-	.parent		= &omap_48m_fck,
-	.fixed_div	= 4,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-/* This virtual clock is the source for dpll4_m4x2_ck */
-static struct clk dpll4_m4_ck = {
-	.name		= "dpll4_m4_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll4_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3630_CLKSEL_DSS1_MASK,
-	.clksel		= dpll4_clksel,
-	.clkdm_name	= "dpll4_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-	.set_rate	= &omap2_clksel_set_rate,
-	.round_rate	= &omap2_clksel_round_rate,
-};
-
-/* The PWRDN bit is apparently only available on 3430ES2 and above */
-static struct clk dpll4_m4x2_ck = {
-	.name		= "dpll4_m4x2_ck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &dpll4_m4_ck,
-	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_bit	= OMAP3430_PWRDN_DSS1_SHIFT,
-	.flags		= INVERT_ENABLE,
-	.clkdm_name	= "dpll4_clkdm",
-	.recalc		= &omap3_clkoutx2_recalc,
-};
-
-/* This virtual clock is the source for dpll4_m5x2_ck */
-static struct clk dpll4_m5_ck = {
-	.name		= "dpll4_m5_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll4_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3630_CLKSEL_CAM_MASK,
-	.clksel		= dpll4_clksel,
-	.clkdm_name	= "dpll4_clkdm",
-	.set_rate	= &omap2_clksel_set_rate,
-	.round_rate	= &omap2_clksel_round_rate,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* The PWRDN bit is apparently only available on 3430ES2 and above */
-static struct clk dpll4_m5x2_ck = {
-	.name		= "dpll4_m5x2_ck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &dpll4_m5_ck,
-	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_bit	= OMAP3430_PWRDN_CAM_SHIFT,
-	.flags		= INVERT_ENABLE,
-	.clkdm_name	= "dpll4_clkdm",
-	.recalc		= &omap3_clkoutx2_recalc,
-};
-
-/* This virtual clock is the source for dpll4_m6x2_ck */
-static struct clk dpll4_m6_ck = {
-	.name		= "dpll4_m6_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll4_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP3630_DIV_DPLL4_MASK,
-	.clksel		= dpll4_clksel,
-	.clkdm_name	= "dpll4_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* The PWRDN bit is apparently only available on 3430ES2 and above */
-static struct clk dpll4_m6x2_ck = {
-	.name		= "dpll4_m6x2_ck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &dpll4_m6_ck,
-	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
-	.enable_bit	= OMAP3430_PWRDN_EMU_PERIPH_SHIFT,
-	.flags		= INVERT_ENABLE,
-	.clkdm_name	= "dpll4_clkdm",
-	.recalc		= &omap3_clkoutx2_recalc,
-};
-
-static struct clk emu_per_alwon_ck = {
-	.name		= "emu_per_alwon_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll4_m6x2_ck,
-	.clkdm_name	= "dpll4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* DPLL5 */
-/* Supplies 120MHz clock, USIM source clock */
-/* Type: DPLL */
-/* 3430ES2 only */
-static struct dpll_data dpll5_dd = {
-	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4),
-	.mult_mask	= OMAP3430ES2_PERIPH2_DPLL_MULT_MASK,
-	.div1_mask	= OMAP3430ES2_PERIPH2_DPLL_DIV_MASK,
-	.clk_bypass	= &sys_ck,
-	.clk_ref	= &sys_ck,
-	.freqsel_mask	= OMAP3430ES2_PERIPH2_DPLL_FREQSEL_MASK,
-	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKEN2),
-	.enable_mask	= OMAP3430ES2_EN_PERIPH2_DPLL_MASK,
-	.modes		= (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
-	.auto_recal_bit	= OMAP3430ES2_EN_PERIPH2_DPLL_DRIFTGUARD_SHIFT,
-	.recal_en_bit	= OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN_SHIFT,
-	.recal_st_bit	= OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT,
-	.autoidle_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_AUTOIDLE2_PLL),
-	.autoidle_mask	= OMAP3430ES2_AUTO_PERIPH2_DPLL_MASK,
-	.idlest_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2),
-	.idlest_mask	= OMAP3430ES2_ST_PERIPH2_CLK_MASK,
-	.max_multiplier = OMAP3_MAX_DPLL_MULT,
-	.min_divider	= 1,
-	.max_divider	= OMAP3_MAX_DPLL_DIV,
-};
-
-static struct clk dpll5_ck = {
-	.name		= "dpll5_ck",
-	.ops		= &clkops_omap3_noncore_dpll_ops,
-	.parent		= &sys_ck,
-	.dpll_data	= &dpll5_dd,
-	.round_rate	= &omap2_dpll_round_rate,
-	.set_rate	= &omap3_noncore_dpll_set_rate,
-	.clkdm_name	= "dpll5_clkdm",
-	.recalc		= &omap3_dpll_recalc,
-};
-
-static const struct clksel div16_dpll5_clksel[] = {
-	{ .parent = &dpll5_ck, .rates = div16_dpll_rates },
-	{ .parent = NULL }
-};
-
-static struct clk dpll5_m2_ck = {
-	.name		= "dpll5_m2_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll5_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL5),
-	.clksel_mask	= OMAP3430ES2_DIV_120M_MASK,
-	.clksel		= div16_dpll5_clksel,
-	.clkdm_name	= "dpll5_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* CM EXTERNAL CLOCK OUTPUTS */
-
-static const struct clksel_rate clkout2_src_core_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate clkout2_src_sys_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate clkout2_src_96m_rates[] = {
-	{ .div = 1, .val = 2, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate clkout2_src_54m_rates[] = {
-	{ .div = 1, .val = 3, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel clkout2_src_clksel[] = {
-	{ .parent = &core_ck,		.rates = clkout2_src_core_rates },
-	{ .parent = &sys_ck,		.rates = clkout2_src_sys_rates },
-	{ .parent = &cm_96m_fck,	.rates = clkout2_src_96m_rates },
-	{ .parent = &omap_54m_fck,	.rates = clkout2_src_54m_rates },
-	{ .parent = NULL }
-};
-
-static struct clk clkout2_src_ck = {
-	.name		= "clkout2_src_ck",
-	.ops		= &clkops_omap2_dflt,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP3430_CM_CLKOUT_CTRL,
-	.enable_bit	= OMAP3430_CLKOUT2_EN_SHIFT,
-	.clksel_reg	= OMAP3430_CM_CLKOUT_CTRL,
-	.clksel_mask	= OMAP3430_CLKOUT2SOURCE_MASK,
-	.clksel		= clkout2_src_clksel,
-	.clkdm_name	= "core_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate sys_clkout2_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_3XXX },
-	{ .div = 2, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 4, .val = 2, .flags = RATE_IN_3XXX },
-	{ .div = 8, .val = 3, .flags = RATE_IN_3XXX },
-	{ .div = 16, .val = 4, .flags = RATE_IN_3XXX },
-	{ .div = 0 },
-};
-
-static const struct clksel sys_clkout2_clksel[] = {
-	{ .parent = &clkout2_src_ck, .rates = sys_clkout2_rates },
-	{ .parent = NULL },
-};
-
-static struct clk sys_clkout2 = {
-	.name		= "sys_clkout2",
-	.ops		= &clkops_null,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP3430_CM_CLKOUT_CTRL,
-	.clksel_mask	= OMAP3430_CLKOUT2_DIV_MASK,
-	.clksel		= sys_clkout2_clksel,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate
-};
-
-/* CM OUTPUT CLOCKS */
-
-static struct clk corex2_fck = {
-	.name		= "corex2_fck",
-	.ops		= &clkops_null,
-	.parent		= &dpll3_m2x2_ck,
-	.recalc		= &followparent_recalc,
-};
-
-/* DPLL power domain clock controls */
-
-static const struct clksel_rate div4_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_3XXX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel div4_core_clksel[] = {
-	{ .parent = &core_ck, .rates = div4_rates },
-	{ .parent = NULL }
-};
-
-/*
- * REVISIT: Are these in DPLL power domain or CM power domain? docs
- * may be inconsistent here?
- */
-static struct clk dpll1_fck = {
-	.name		= "dpll1_fck",
-	.ops		= &clkops_null,
-	.parent		= &core_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
-	.clksel_mask	= OMAP3430_MPU_CLK_SRC_MASK,
-	.clksel		= div4_core_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk mpu_ck = {
-	.name		= "mpu_ck",
-	.ops		= &clkops_null,
-	.parent		= &dpll1_x2m2_ck,
-	.clkdm_name	= "mpu_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* arm_fck is divided by two when DPLL1 locked; otherwise, passthrough mpu_ck */
-static const struct clksel_rate arm_fck_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_3XXX },
-	{ .div = 2, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 0 },
-};
-
-static const struct clksel arm_fck_clksel[] = {
-	{ .parent = &mpu_ck, .rates = arm_fck_rates },
-	{ .parent = NULL }
-};
-
-static struct clk arm_fck = {
-	.name		= "arm_fck",
-	.ops		= &clkops_null,
-	.parent		= &mpu_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
-	.clksel_mask	= OMAP3430_ST_MPU_CLK_MASK,
-	.clksel		= arm_fck_clksel,
-	.clkdm_name	= "mpu_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* XXX What about neon_clkdm ? */
-
-/*
- * REVISIT: This clock is never specifically defined in the 3430 TRM,
- * although it is referenced - so this is a guess
- */
-static struct clk emu_mpu_alwon_ck = {
-	.name		= "emu_mpu_alwon_ck",
-	.ops		= &clkops_null,
-	.parent		= &mpu_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dpll2_fck = {
-	.name		= "dpll2_fck",
-	.ops		= &clkops_null,
-	.parent		= &core_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
-	.clksel_mask	= OMAP3430_IVA2_CLK_SRC_MASK,
-	.clksel		= div4_core_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk iva2_ck = {
-	.name		= "iva2_ck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &dpll2_m2_ck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT,
-	.clkdm_name	= "iva2_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* Common interface clocks */
-
-static const struct clksel div2_core_clksel[] = {
-	{ .parent = &core_ck, .rates = div2_rates },
-	{ .parent = NULL }
-};
-
-static struct clk l3_ick = {
-	.name		= "l3_ick",
-	.ops		= &clkops_null,
-	.parent		= &core_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430_CLKSEL_L3_MASK,
-	.clksel		= div2_core_clksel,
-	.clkdm_name	= "core_l3_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel div2_l3_clksel[] = {
-	{ .parent = &l3_ick, .rates = div2_rates },
-	{ .parent = NULL }
-};
-
-static struct clk l4_ick = {
-	.name		= "l4_ick",
-	.ops		= &clkops_null,
-	.parent		= &l3_ick,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430_CLKSEL_L4_MASK,
-	.clksel		= div2_l3_clksel,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-
-};
-
-static const struct clksel div2_l4_clksel[] = {
-	{ .parent = &l4_ick, .rates = div2_rates },
-	{ .parent = NULL }
-};
-
-static struct clk rm_ick = {
-	.name		= "rm_ick",
-	.ops		= &clkops_null,
-	.parent		= &l4_ick,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430_CLKSEL_RM_MASK,
-	.clksel		= div2_l4_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* GFX power domain */
-
-/* GFX clocks are in 3430ES1 only. 3430ES2 and later uses the SGX instead */
-
-static const struct clksel gfx_l3_clksel[] = {
-	{ .parent = &l3_ick, .rates = gfx_l3_rates },
-	{ .parent = NULL }
-};
-
-/*
- * Virtual parent clock for gfx_l3_ick and gfx_l3_fck
- * This interface clock does not have a CM_AUTOIDLE bit
- */
-static struct clk gfx_l3_ck = {
-	.name		= "gfx_l3_ck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l3_ick,
-	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP_EN_GFX_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gfx_l3_fck = {
-	.name		= "gfx_l3_fck",
-	.ops		= &clkops_null,
-	.parent		= &gfx_l3_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
-	.clksel		= gfx_l3_clksel,
-	.clkdm_name	= "gfx_3430es1_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gfx_l3_ick = {
-	.name		= "gfx_l3_ick",
-	.ops		= &clkops_null,
-	.parent		= &gfx_l3_ck,
-	.clkdm_name	= "gfx_3430es1_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gfx_cg1_ck = {
-	.name		= "gfx_cg1_ck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &gfx_l3_fck, /* REVISIT: correct? */
-	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430ES1_EN_2D_SHIFT,
-	.clkdm_name	= "gfx_3430es1_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gfx_cg2_ck = {
-	.name		= "gfx_cg2_ck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &gfx_l3_fck, /* REVISIT: correct? */
-	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430ES1_EN_3D_SHIFT,
-	.clkdm_name	= "gfx_3430es1_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* SGX power domain - 3430ES2 only */
-
-static const struct clksel_rate sgx_core_rates[] = {
-	{ .div = 2, .val = 5, .flags = RATE_IN_36XX },
-	{ .div = 3, .val = 0, .flags = RATE_IN_3XXX },
-	{ .div = 4, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 6, .val = 2, .flags = RATE_IN_3XXX },
-	{ .div = 0 },
-};
-
-static const struct clksel_rate sgx_192m_rates[] = {
-	{ .div = 1,  .val = 4, .flags = RATE_IN_36XX },
-	{ .div = 0 },
-};
-
-static const struct clksel_rate sgx_corex2_rates[] = {
-	{ .div = 3, .val = 6, .flags = RATE_IN_36XX },
-	{ .div = 5, .val = 7, .flags = RATE_IN_36XX },
-	{ .div = 0 },
-};
-
-static const struct clksel_rate sgx_96m_rates[] = {
-	{ .div = 1,  .val = 3, .flags = RATE_IN_3XXX },
-	{ .div = 0 },
-};
-
-static const struct clksel sgx_clksel[] = {
-	{ .parent = &core_ck,	 .rates = sgx_core_rates },
-	{ .parent = &cm_96m_fck, .rates = sgx_96m_rates },
-	{ .parent = &omap_192m_alwon_fck, .rates = sgx_192m_rates },
-	{ .parent = &corex2_fck, .rates = sgx_corex2_rates },
-	{ .parent = NULL }
-};
-
-static struct clk sgx_fck = {
-	.name		= "sgx_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430ES2_CLKSEL_SGX_MASK,
-	.clksel		= sgx_clksel,
-	.clkdm_name	= "sgx_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-	.set_rate	= &omap2_clksel_set_rate,
-	.round_rate	= &omap2_clksel_round_rate
-};
-
-/* This interface clock does not have a CM_AUTOIDLE bit */
-static struct clk sgx_ick = {
-	.name		= "sgx_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l3_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_SHIFT,
-	.clkdm_name	= "sgx_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* CORE power domain */
-
-static struct clk d2d_26m_fck = {
-	.name		= "d2d_26m_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &sys_ck,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430ES1_EN_D2D_SHIFT,
-	.clkdm_name	= "d2d_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk modem_fck = {
-	.name		= "modem_fck",
-	.ops		= &clkops_omap2_mdmclk_dflt_wait,
-	.parent		= &sys_ck,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_MODEM_SHIFT,
-	.clkdm_name	= "d2d_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk sad2d_ick = {
-	.name		= "sad2d_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l3_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_SAD2D_SHIFT,
-	.clkdm_name	= "d2d_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mad2d_ick = {
-	.name		= "mad2d_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l3_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
-	.enable_bit	= OMAP3430_EN_MAD2D_SHIFT,
-	.clkdm_name	= "d2d_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel omap343x_gpt_clksel[] = {
-	{ .parent = &omap_32k_fck, .rates = gpt_32k_rates },
-	{ .parent = &sys_ck,	   .rates = gpt_sys_rates },
-	{ .parent = NULL}
-};
-
-static struct clk gpt10_fck = {
-	.name		= "gpt10_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &sys_ck,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_GPT10_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430_CLKSEL_GPT10_MASK,
-	.clksel		= omap343x_gpt_clksel,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt11_fck = {
-	.name		= "gpt11_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &sys_ck,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_GPT11_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430_CLKSEL_GPT11_MASK,
-	.clksel		= omap343x_gpt_clksel,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk cpefuse_fck = {
-	.name		= "cpefuse_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &sys_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
-	.enable_bit	= OMAP3430ES2_EN_CPEFUSE_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk ts_fck = {
-	.name		= "ts_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &omap_32k_fck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
-	.enable_bit	= OMAP3430ES2_EN_TS_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usbtll_fck = {
-	.name		= "usbtll_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &dpll5_m2_ck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
-	.enable_bit	= OMAP3430ES2_EN_USBTLL_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/* CORE 96M FCLK-derived clocks */
-
-static struct clk core_96m_fck = {
-	.name		= "core_96m_fck",
-	.ops		= &clkops_null,
-	.parent		= &omap_96m_fck,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmchs3_fck = {
-	.name		= "mmchs3_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_96m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430ES2_EN_MMC3_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmchs2_fck = {
-	.name		= "mmchs2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_96m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_MMC2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mspro_fck = {
-	.name		= "mspro_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_96m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_MSPRO_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmchs1_fck = {
-	.name		= "mmchs1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_96m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_MMC1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk i2c3_fck = {
-	.name		= "i2c3_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_96m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_I2C3_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk i2c2_fck = {
-	.name		= "i2c2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_96m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_I2C2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk i2c1_fck = {
-	.name		= "i2c1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_96m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_I2C1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * MCBSP 1 & 5 get their 96MHz clock from core_96m_fck;
- * MCBSP 2, 3, 4 get their 96MHz clock from per_96m_fck.
- */
-static const struct clksel_rate common_mcbsp_96m_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel mcbsp_15_clksel[] = {
-	{ .parent = &core_96m_fck, .rates = common_mcbsp_96m_rates },
-	{ .parent = &mcbsp_clks,   .rates = common_mcbsp_mcbsp_rates },
-	{ .parent = NULL }
-};
-
-static struct clk mcbsp5_fck = {
-	.name		= "mcbsp5_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_MCBSP5_SHIFT,
-	.clksel_reg	= OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
-	.clksel_mask	= OMAP2_MCBSP5_CLKS_MASK,
-	.clksel		= mcbsp_15_clksel,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp1_fck = {
-	.name		= "mcbsp1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_MCBSP1_SHIFT,
-	.clksel_reg	= OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
-	.clksel_mask	= OMAP2_MCBSP1_CLKS_MASK,
-	.clksel		= mcbsp_15_clksel,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* CORE_48M_FCK-derived clocks */
-
-static struct clk core_48m_fck = {
-	.name		= "core_48m_fck",
-	.ops		= &clkops_null,
-	.parent		= &omap_48m_fck,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi4_fck = {
-	.name		= "mcspi4_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_48m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_MCSPI4_SHIFT,
-	.recalc		= &followparent_recalc,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-static struct clk mcspi3_fck = {
-	.name		= "mcspi3_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_48m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_MCSPI3_SHIFT,
-	.recalc		= &followparent_recalc,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-static struct clk mcspi2_fck = {
-	.name		= "mcspi2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_48m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_MCSPI2_SHIFT,
-	.recalc		= &followparent_recalc,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-static struct clk mcspi1_fck = {
-	.name		= "mcspi1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_48m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_MCSPI1_SHIFT,
-	.recalc		= &followparent_recalc,
-	.clkdm_name	= "core_l4_clkdm",
-};
-
-static struct clk uart2_fck = {
-	.name		= "uart2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_48m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_UART2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart1_fck = {
-	.name		= "uart1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_48m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_UART1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk fshostusb_fck = {
-	.name		= "fshostusb_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_48m_fck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/* CORE_12M_FCK based clocks */
-
-static struct clk core_12m_fck = {
-	.name		= "core_12m_fck",
-	.ops		= &clkops_null,
-	.parent		= &omap_12m_fck,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk hdq_fck = {
-	.name		= "hdq_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_12m_fck,
-	.clkdm_name	= "core_l4_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_HDQ_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/* DPLL3-derived clock */
-
-static const struct clksel_rate ssi_ssr_corex2_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_3XXX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_3XXX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_3XXX },
-	{ .div = 6, .val = 6, .flags = RATE_IN_3XXX },
-	{ .div = 8, .val = 8, .flags = RATE_IN_3XXX },
-	{ .div = 0 }
-};
-
-static const struct clksel ssi_ssr_clksel[] = {
-	{ .parent = &corex2_fck, .rates = ssi_ssr_corex2_rates },
-	{ .parent = NULL }
-};
-
-static struct clk ssi_ssr_fck_3430es1 = {
-	.name		= "ssi_ssr_fck",
-	.ops		= &clkops_omap2_dflt,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430_CLKSEL_SSI_MASK,
-	.clksel		= ssi_ssr_clksel,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk ssi_ssr_fck_3430es2 = {
-	.name		= "ssi_ssr_fck",
-	.ops		= &clkops_omap3430es2_ssi_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430_CLKSEL_SSI_MASK,
-	.clksel		= ssi_ssr_clksel,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk ssi_sst_fck_3430es1 = {
-	.name		= "ssi_sst_fck",
-	.ops		= &clkops_null,
-	.parent		= &ssi_ssr_fck_3430es1,
-	.fixed_div	= 2,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static struct clk ssi_sst_fck_3430es2 = {
-	.name		= "ssi_sst_fck",
-	.ops		= &clkops_null,
-	.parent		= &ssi_ssr_fck_3430es2,
-	.fixed_div	= 2,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-
-
-/* CORE_L3_ICK based clocks */
-
-/*
- * XXX must add clk_enable/clk_disable for these if standard code won't
- * handle it
- */
-static struct clk core_l3_ick = {
-	.name		= "core_l3_ick",
-	.ops		= &clkops_null,
-	.parent		= &l3_ick,
-	.clkdm_name	= "core_l3_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk hsotgusb_ick_3430es1 = {
-	.name		= "hsotgusb_ick",
-	.ops		= &clkops_omap2_iclk_dflt,
-	.parent		= &core_l3_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_HSOTGUSB_SHIFT,
-	.clkdm_name	= "core_l3_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk hsotgusb_ick_3430es2 = {
-	.name		= "hsotgusb_ick",
-	.ops		= &clkops_omap3430es2_iclk_hsotgusb_wait,
-	.parent		= &core_l3_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_HSOTGUSB_SHIFT,
-	.clkdm_name	= "core_l3_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* This interface clock does not have a CM_AUTOIDLE bit */
-static struct clk sdrc_ick = {
-	.name		= "sdrc_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_l3_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_SDRC_SHIFT,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l3_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpmc_fck = {
-	.name		= "gpmc_fck",
-	.ops		= &clkops_null,
-	.parent		= &core_l3_ick,
-	.flags		= ENABLE_ON_INIT, /* huh? */
-	.clkdm_name	= "core_l3_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* SECURITY_L3_ICK based clocks */
-
-static struct clk security_l3_ick = {
-	.name		= "security_l3_ick",
-	.ops		= &clkops_null,
-	.parent		= &l3_ick,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk pka_ick = {
-	.name		= "pka_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &security_l3_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP3430_EN_PKA_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/* CORE_L4_ICK based clocks */
-
-static struct clk core_l4_ick = {
-	.name		= "core_l4_ick",
-	.ops		= &clkops_null,
-	.parent		= &l4_ick,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usbtll_ick = {
-	.name		= "usbtll_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
-	.enable_bit	= OMAP3430ES2_EN_USBTLL_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmchs3_ick = {
-	.name		= "mmchs3_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430ES2_EN_MMC3_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* Intersystem Communication Registers - chassis mode only */
-static struct clk icr_ick = {
-	.name		= "icr_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_ICR_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk aes2_ick = {
-	.name		= "aes2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_AES2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk sha12_ick = {
-	.name		= "sha12_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_SHA12_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk des2_ick = {
-	.name		= "des2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_DES2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmchs2_ick = {
-	.name		= "mmchs2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_MMC2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmchs1_ick = {
-	.name		= "mmchs1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_MMC1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mspro_ick = {
-	.name		= "mspro_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_MSPRO_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk hdq_ick = {
-	.name		= "hdq_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_HDQ_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi4_ick = {
-	.name		= "mcspi4_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_MCSPI4_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi3_ick = {
-	.name		= "mcspi3_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_MCSPI3_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi2_ick = {
-	.name		= "mcspi2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_MCSPI2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi1_ick = {
-	.name		= "mcspi1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_MCSPI1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk i2c3_ick = {
-	.name		= "i2c3_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_I2C3_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk i2c2_ick = {
-	.name		= "i2c2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_I2C2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk i2c1_ick = {
-	.name		= "i2c1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_I2C1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart2_ick = {
-	.name		= "uart2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_UART2_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart1_ick = {
-	.name		= "uart1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_UART1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt11_ick = {
-	.name		= "gpt11_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_GPT11_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt10_ick = {
-	.name		= "gpt10_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_GPT10_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcbsp5_ick = {
-	.name		= "mcbsp5_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_MCBSP5_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcbsp1_ick = {
-	.name		= "mcbsp1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_MCBSP1_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk fac_ick = {
-	.name		= "fac_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430ES1_EN_FAC_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mailboxes_ick = {
-	.name		= "mailboxes_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_MAILBOXES_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk omapctrl_ick = {
-	.name		= "omapctrl_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_OMAPCTRL_SHIFT,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* SSI_L4_ICK based clocks */
-
-static struct clk ssi_l4_ick = {
-	.name		= "ssi_l4_ick",
-	.ops		= &clkops_null,
-	.parent		= &l4_ick,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk ssi_ick_3430es1 = {
-	.name		= "ssi_ick",
-	.ops		= &clkops_omap2_iclk_dflt,
-	.parent		= &ssi_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk ssi_ick_3430es2 = {
-	.name		= "ssi_ick",
-	.ops		= &clkops_omap3430es2_iclk_ssi_wait,
-	.parent		= &ssi_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* REVISIT: Technically the TRM claims that this is CORE_CLK based,
- * but l4_ick makes more sense to me */
-
-static const struct clksel usb_l4_clksel[] = {
-	{ .parent = &l4_ick, .rates = div2_rates },
-	{ .parent = NULL },
-};
-
-static struct clk usb_l4_ick = {
-	.name		= "usb_l4_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &l4_ick,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK,
-	.clksel		= usb_l4_clksel,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* SECURITY_L4_ICK2 based clocks */
-
-static struct clk security_l4_ick2 = {
-	.name		= "security_l4_ick2",
-	.ops		= &clkops_null,
-	.parent		= &l4_ick,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk aes1_ick = {
-	.name		= "aes1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &security_l4_ick2,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP3430_EN_AES1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk rng_ick = {
-	.name		= "rng_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &security_l4_ick2,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP3430_EN_RNG_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk sha11_ick = {
-	.name		= "sha11_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &security_l4_ick2,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP3430_EN_SHA11_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk des1_ick = {
-	.name		= "des1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &security_l4_ick2,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-	.enable_bit	= OMAP3430_EN_DES1_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/* DSS */
-static struct clk dss1_alwon_fck_3430es1 = {
-	.name		= "dss1_alwon_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &dpll4_m4x2_ck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_DSS1_SHIFT,
-	.clkdm_name	= "dss_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dss1_alwon_fck_3430es2 = {
-	.name		= "dss1_alwon_fck",
-	.ops		= &clkops_omap3430es2_dss_usbhost_wait,
-	.parent		= &dpll4_m4x2_ck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_DSS1_SHIFT,
-	.clkdm_name	= "dss_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dss_tv_fck = {
-	.name		= "dss_tv_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &omap_54m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_TV_SHIFT,
-	.clkdm_name	= "dss_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dss_96m_fck = {
-	.name		= "dss_96m_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &omap_96m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_TV_SHIFT,
-	.clkdm_name	= "dss_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dss2_alwon_fck = {
-	.name		= "dss2_alwon_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &sys_ck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_DSS2_SHIFT,
-	.clkdm_name	= "dss_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dss_ick_3430es1 = {
-	/* Handles both L3 and L4 clocks */
-	.name		= "dss_ick",
-	.ops		= &clkops_omap2_iclk_dflt,
-	.parent		= &l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
-	.clkdm_name	= "dss_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dss_ick_3430es2 = {
-	/* Handles both L3 and L4 clocks */
-	.name		= "dss_ick",
-	.ops		= &clkops_omap3430es2_iclk_dss_usbhost_wait,
-	.parent		= &l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
-	.clkdm_name	= "dss_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* CAM */
-
-static struct clk cam_mclk = {
-	.name		= "cam_mclk",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &dpll4_m5x2_ck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_CAM_SHIFT,
-	.clkdm_name	= "cam_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk cam_ick = {
-	/* Handles both L3 and L4 clocks */
-	.name		= "cam_ick",
-	.ops		= &clkops_omap2_iclk_dflt,
-	.parent		= &l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_CAM_SHIFT,
-	.clkdm_name	= "cam_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk csi2_96m_fck = {
-	.name		= "csi2_96m_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &core_96m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_CSI2_SHIFT,
-	.clkdm_name	= "cam_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* USBHOST - 3430ES2 only */
-
-static struct clk usbhost_120m_fck = {
-	.name		= "usbhost_120m_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &dpll5_m2_ck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430ES2_EN_USBHOST2_SHIFT,
-	.clkdm_name	= "usbhost_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usbhost_48m_fck = {
-	.name		= "usbhost_48m_fck",
-	.ops		= &clkops_omap3430es2_dss_usbhost_wait,
-	.parent		= &omap_48m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430ES2_EN_USBHOST1_SHIFT,
-	.clkdm_name	= "usbhost_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usbhost_ick = {
-	/* Handles both L3 and L4 clocks */
-	.name		= "usbhost_ick",
-	.ops		= &clkops_omap3430es2_iclk_dss_usbhost_wait,
-	.parent		= &l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430ES2_EN_USBHOST_SHIFT,
-	.clkdm_name	= "usbhost_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* WKUP */
-
-static const struct clksel_rate usim_96m_rates[] = {
-	{ .div = 2,  .val = 3, .flags = RATE_IN_3XXX },
-	{ .div = 4,  .val = 4, .flags = RATE_IN_3XXX },
-	{ .div = 8,  .val = 5, .flags = RATE_IN_3XXX },
-	{ .div = 10, .val = 6, .flags = RATE_IN_3XXX },
-	{ .div = 0 },
-};
-
-static const struct clksel_rate usim_120m_rates[] = {
-	{ .div = 4,  .val = 7,	.flags = RATE_IN_3XXX },
-	{ .div = 8,  .val = 8,	.flags = RATE_IN_3XXX },
-	{ .div = 16, .val = 9,	.flags = RATE_IN_3XXX },
-	{ .div = 20, .val = 10, .flags = RATE_IN_3XXX },
-	{ .div = 0 },
-};
-
-static const struct clksel usim_clksel[] = {
-	{ .parent = &omap_96m_fck,	.rates = usim_96m_rates },
-	{ .parent = &dpll5_m2_ck,	.rates = usim_120m_rates },
-	{ .parent = &sys_ck,		.rates = div2_rates },
-	{ .parent = NULL },
-};
-
-/* 3430ES2 only */
-static struct clk usim_fck = {
-	.name		= "usim_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430ES2_EN_USIMOCP_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430ES2_CLKSEL_USIMOCP_MASK,
-	.clksel		= usim_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* XXX should gpt1's clksel have wkup_32k_fck as the 32k opt? */
-static struct clk gpt1_fck = {
-	.name		= "gpt1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_GPT1_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430_CLKSEL_GPT1_MASK,
-	.clksel		= omap343x_gpt_clksel,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk wkup_32k_fck = {
-	.name		= "wkup_32k_fck",
-	.ops		= &clkops_null,
-	.parent		= &omap_32k_fck,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio1_dbck = {
-	.name		= "gpio1_dbck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &wkup_32k_fck,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_GPIO1_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wdt2_fck = {
-	.name		= "wdt2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &wkup_32k_fck,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_WDT2_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wkup_l4_ick = {
-	.name		= "wkup_l4_ick",
-	.ops		= &clkops_null,
-	.parent		= &sys_ck,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* 3430ES2 only */
-/* Never specifically named in the TRM, so we have to infer a likely name */
-static struct clk usim_ick = {
-	.name		= "usim_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wkup_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430ES2_EN_USIMOCP_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wdt2_ick = {
-	.name		= "wdt2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wkup_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_WDT2_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wdt1_ick = {
-	.name		= "wdt1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wkup_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_WDT1_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio1_ick = {
-	.name		= "gpio1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wkup_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_GPIO1_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk omap_32ksync_ick = {
-	.name		= "omap_32ksync_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wkup_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_32KSYNC_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* XXX This clock no longer exists in 3430 TRM rev F */
-static struct clk gpt12_ick = {
-	.name		= "gpt12_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wkup_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_GPT12_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt1_ick = {
-	.name		= "gpt1_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &wkup_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_GPT1_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-
-
-/* PER clock domain */
-
-static struct clk per_96m_fck = {
-	.name		= "per_96m_fck",
-	.ops		= &clkops_null,
-	.parent		= &omap_96m_alwon_fck,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk per_48m_fck = {
-	.name		= "per_48m_fck",
-	.ops		= &clkops_null,
-	.parent		= &omap_48m_fck,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart3_fck = {
-	.name		= "uart3_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &per_48m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_UART3_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart4_fck = {
-	.name		= "uart4_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &per_48m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3630_EN_UART4_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart4_fck_am35xx = {
-	.name		= "uart4_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &core_48m_fck,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-	.enable_bit	= AM35XX_EN_UART4_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt2_fck = {
-	.name		= "gpt2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_GPT2_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430_CLKSEL_GPT2_MASK,
-	.clksel		= omap343x_gpt_clksel,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt3_fck = {
-	.name		= "gpt3_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_GPT3_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430_CLKSEL_GPT3_MASK,
-	.clksel		= omap343x_gpt_clksel,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt4_fck = {
-	.name		= "gpt4_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_GPT4_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430_CLKSEL_GPT4_MASK,
-	.clksel		= omap343x_gpt_clksel,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt5_fck = {
-	.name		= "gpt5_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_GPT5_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430_CLKSEL_GPT5_MASK,
-	.clksel		= omap343x_gpt_clksel,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt6_fck = {
-	.name		= "gpt6_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_GPT6_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430_CLKSEL_GPT6_MASK,
-	.clksel		= omap343x_gpt_clksel,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt7_fck = {
-	.name		= "gpt7_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_GPT7_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430_CLKSEL_GPT7_MASK,
-	.clksel		= omap343x_gpt_clksel,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt8_fck = {
-	.name		= "gpt8_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_GPT8_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430_CLKSEL_GPT8_MASK,
-	.clksel		= omap343x_gpt_clksel,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk gpt9_fck = {
-	.name		= "gpt9_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_GPT9_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP3430_CLKSEL_GPT9_MASK,
-	.clksel		= omap343x_gpt_clksel,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk per_32k_alwon_fck = {
-	.name		= "per_32k_alwon_fck",
-	.ops		= &clkops_null,
-	.parent		= &omap_32k_fck,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio6_dbck = {
-	.name		= "gpio6_dbck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &per_32k_alwon_fck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_GPIO6_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio5_dbck = {
-	.name		= "gpio5_dbck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &per_32k_alwon_fck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_GPIO5_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio4_dbck = {
-	.name		= "gpio4_dbck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &per_32k_alwon_fck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_GPIO4_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio3_dbck = {
-	.name		= "gpio3_dbck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &per_32k_alwon_fck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_GPIO3_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio2_dbck = {
-	.name		= "gpio2_dbck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &per_32k_alwon_fck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_GPIO2_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wdt3_fck = {
-	.name		= "wdt3_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &per_32k_alwon_fck,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_WDT3_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk per_l4_ick = {
-	.name		= "per_l4_ick",
-	.ops		= &clkops_null,
-	.parent		= &l4_ick,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio6_ick = {
-	.name		= "gpio6_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_GPIO6_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio5_ick = {
-	.name		= "gpio5_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_GPIO5_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio4_ick = {
-	.name		= "gpio4_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_GPIO4_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio3_ick = {
-	.name		= "gpio3_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_GPIO3_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio2_ick = {
-	.name		= "gpio2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_GPIO2_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wdt3_ick = {
-	.name		= "wdt3_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_WDT3_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart3_ick = {
-	.name		= "uart3_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_UART3_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart4_ick = {
-	.name		= "uart4_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3630_EN_UART4_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt9_ick = {
-	.name		= "gpt9_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_GPT9_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt8_ick = {
-	.name		= "gpt8_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_GPT8_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt7_ick = {
-	.name		= "gpt7_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_GPT7_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt6_ick = {
-	.name		= "gpt6_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_GPT6_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt5_ick = {
-	.name		= "gpt5_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_GPT5_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt4_ick = {
-	.name		= "gpt4_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_GPT4_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt3_ick = {
-	.name		= "gpt3_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_GPT3_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpt2_ick = {
-	.name		= "gpt2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_GPT2_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcbsp2_ick = {
-	.name		= "mcbsp2_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_MCBSP2_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcbsp3_ick = {
-	.name		= "mcbsp3_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_MCBSP3_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcbsp4_ick = {
-	.name		= "mcbsp4_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &per_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430_EN_MCBSP4_SHIFT,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel mcbsp_234_clksel[] = {
-	{ .parent = &per_96m_fck,  .rates = common_mcbsp_96m_rates },
-	{ .parent = &mcbsp_clks,   .rates = common_mcbsp_mcbsp_rates },
-	{ .parent = NULL }
-};
-
-static struct clk mcbsp2_fck = {
-	.name		= "mcbsp2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_MCBSP2_SHIFT,
-	.clksel_reg	= OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
-	.clksel_mask	= OMAP2_MCBSP2_CLKS_MASK,
-	.clksel		= mcbsp_234_clksel,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp3_fck = {
-	.name		= "mcbsp3_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_MCBSP3_SHIFT,
-	.clksel_reg	= OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
-	.clksel_mask	= OMAP2_MCBSP3_CLKS_MASK,
-	.clksel		= mcbsp_234_clksel,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk mcbsp4_fck = {
-	.name		= "mcbsp4_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.init		= &omap2_init_clksel_parent,
-	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_MCBSP4_SHIFT,
-	.clksel_reg	= OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
-	.clksel_mask	= OMAP2_MCBSP4_CLKS_MASK,
-	.clksel		= mcbsp_234_clksel,
-	.clkdm_name	= "per_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* EMU clocks */
-
-/* More information: ARM Cortex-A8 Technical Reference Manual, sect 10.1 */
-
-static const struct clksel_rate emu_src_sys_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_3XXX },
-	{ .div = 0 },
-};
-
-static const struct clksel_rate emu_src_core_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 0 },
-};
-
-static const struct clksel_rate emu_src_per_rates[] = {
-	{ .div = 1, .val = 2, .flags = RATE_IN_3XXX },
-	{ .div = 0 },
-};
-
-static const struct clksel_rate emu_src_mpu_rates[] = {
-	{ .div = 1, .val = 3, .flags = RATE_IN_3XXX },
-	{ .div = 0 },
-};
-
-static const struct clksel emu_src_clksel[] = {
-	{ .parent = &sys_ck,		.rates = emu_src_sys_rates },
-	{ .parent = &emu_core_alwon_ck, .rates = emu_src_core_rates },
-	{ .parent = &emu_per_alwon_ck,	.rates = emu_src_per_rates },
-	{ .parent = &emu_mpu_alwon_ck,	.rates = emu_src_mpu_rates },
-	{ .parent = NULL },
-};
-
-/*
- * Like the clkout_src clocks, emu_src_clk is a virtual clock, existing only
- * to switch the source of some of the EMU clocks.
- * XXX Are there CLKEN bits for these EMU clks?
- */
-static struct clk emu_src_ck = {
-	.name		= "emu_src_ck",
-	.ops		= &clkops_null,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP3430_MUX_CTRL_MASK,
-	.clksel		= emu_src_clksel,
-	.clkdm_name	= "emu_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate pclk_emu_rates[] = {
-	{ .div = 2, .val = 2, .flags = RATE_IN_3XXX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_3XXX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_3XXX },
-	{ .div = 6, .val = 6, .flags = RATE_IN_3XXX },
-	{ .div = 0 },
-};
-
-static const struct clksel pclk_emu_clksel[] = {
-	{ .parent = &emu_src_ck, .rates = pclk_emu_rates },
-	{ .parent = NULL },
-};
-
-static struct clk pclk_fck = {
-	.name		= "pclk_fck",
-	.ops		= &clkops_null,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP3430_CLKSEL_PCLK_MASK,
-	.clksel		= pclk_emu_clksel,
-	.clkdm_name	= "emu_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate pclkx2_emu_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_3XXX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_3XXX },
-	{ .div = 0 },
-};
-
-static const struct clksel pclkx2_emu_clksel[] = {
-	{ .parent = &emu_src_ck, .rates = pclkx2_emu_rates },
-	{ .parent = NULL },
-};
-
-static struct clk pclkx2_fck = {
-	.name		= "pclkx2_fck",
-	.ops		= &clkops_null,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP3430_CLKSEL_PCLKX2_MASK,
-	.clksel		= pclkx2_emu_clksel,
-	.clkdm_name	= "emu_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel atclk_emu_clksel[] = {
-	{ .parent = &emu_src_ck, .rates = div2_rates },
-	{ .parent = NULL },
-};
-
-static struct clk atclk_fck = {
-	.name		= "atclk_fck",
-	.ops		= &clkops_null,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP3430_CLKSEL_ATCLK_MASK,
-	.clksel		= atclk_emu_clksel,
-	.clkdm_name	= "emu_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk traceclk_src_fck = {
-	.name		= "traceclk_src_fck",
-	.ops		= &clkops_null,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP3430_TRACE_MUX_CTRL_MASK,
-	.clksel		= emu_src_clksel,
-	.clkdm_name	= "emu_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate traceclk_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_3XXX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_3XXX },
-	{ .div = 4, .val = 4, .flags = RATE_IN_3XXX },
-	{ .div = 0 },
-};
-
-static const struct clksel traceclk_clksel[] = {
-	{ .parent = &traceclk_src_fck, .rates = traceclk_rates },
-	{ .parent = NULL },
-};
-
-static struct clk traceclk_fck = {
-	.name		= "traceclk_fck",
-	.ops		= &clkops_null,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP3430_CLKSEL_TRACECLK_MASK,
-	.clksel		= traceclk_clksel,
-	.clkdm_name	= "emu_clkdm",
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* SR clocks */
-
-/* SmartReflex fclk (VDD1) */
-static struct clk sr1_fck = {
-	.name		= "sr1_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &sys_ck,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_SR1_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* SmartReflex fclk (VDD2) */
-static struct clk sr2_fck = {
-	.name		= "sr2_fck",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &sys_ck,
-	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430_EN_SR2_SHIFT,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk sr_l4_ick = {
-	.name		= "sr_l4_ick",
-	.ops		= &clkops_null, /* RMK: missing? */
-	.parent		= &l4_ick,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* SECURE_32K_FCK clocks */
-
-static struct clk gpt12_fck = {
-	.name		= "gpt12_fck",
-	.ops		= &clkops_null,
-	.parent		= &secure_32k_fck,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wdt1_fck = {
-	.name		= "wdt1_fck",
-	.ops		= &clkops_null,
-	.parent		= &secure_32k_fck,
-	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-/* Clocks for AM35XX */
-static struct clk ipss_ick = {
-	.name		= "ipss_ick",
-	.ops		= &clkops_am35xx_ipss_wait,
-	.parent		= &core_l3_ick,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= AM35XX_EN_IPSS_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk emac_ick = {
-	.name		= "emac_ick",
-	.ops		= &clkops_am35xx_ipss_module_wait,
-	.parent		= &ipss_ick,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
-	.enable_bit	= AM35XX_CPGMAC_VBUSP_CLK_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk rmii_ck = {
-	.name		= "rmii_ck",
-	.ops		= &clkops_null,
-	.rate		= 50000000,
-};
-
-static struct clk emac_fck = {
-	.name		= "emac_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &rmii_ck,
-	.enable_reg	= OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
-	.enable_bit	= AM35XX_CPGMAC_FCLK_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk hsotgusb_ick_am35xx = {
-	.name		= "hsotgusb_ick",
-	.ops		= &clkops_am35xx_ipss_module_wait,
-	.parent		= &ipss_ick,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
-	.enable_bit	= AM35XX_USBOTG_VBUSP_CLK_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk hsotgusb_fck_am35xx = {
-	.name		= "hsotgusb_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &sys_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
-	.enable_bit	= AM35XX_USBOTG_FCLK_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk hecc_ck = {
-	.name		= "hecc_ck",
-	.ops		= &clkops_am35xx_ipss_module_wait,
-	.parent		= &sys_ck,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
-	.enable_bit	= AM35XX_HECC_VBUSP_CLK_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk vpfe_ick = {
-	.name		= "vpfe_ick",
-	.ops		= &clkops_am35xx_ipss_module_wait,
-	.parent		= &ipss_ick,
-	.clkdm_name	= "core_l3_clkdm",
-	.enable_reg	= OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
-	.enable_bit	= AM35XX_VPFE_VBUSP_CLK_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk pclk_ck = {
-	.name		= "pclk_ck",
-	.ops		= &clkops_null,
-	.rate		= 27000000,
-};
-
-static struct clk vpfe_fck = {
-	.name		= "vpfe_fck",
-	.ops		= &clkops_omap2_dflt,
-	.parent		= &pclk_ck,
-	.enable_reg	= OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
-	.enable_bit	= AM35XX_VPFE_FCLK_SHIFT,
-	.recalc		= &followparent_recalc,
-};
-
-/*
- * The UART1/2 functional clock acts as the functional clock for
- * UART4. No separate fclk control available.  XXX Well now we have a
- * uart4_fck that is apparently used as the UART4 functional clock,
- * but it also seems that uart1_fck or uart2_fck are still needed, at
- * least for UART4 softresets to complete.  This really needs
- * clarification.
- */
-static struct clk uart4_ick_am35xx = {
-	.name		= "uart4_ick",
-	.ops		= &clkops_omap2_iclk_dflt_wait,
-	.parent		= &core_l4_ick,
-	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
-	.enable_bit	= AM35XX_EN_UART4_SHIFT,
-	.clkdm_name	= "core_l4_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dummy_apb_pclk = {
-	.name		= "apb_pclk",
-	.ops		= &clkops_null,
-};
-
-/*
- * clkdev
- */
-
-static struct omap_clk omap3xxx_clks[] = {
-	CLK(NULL,	"apb_pclk",	&dummy_apb_pclk,	CK_3XXX),
-	CLK(NULL,	"omap_32k_fck",	&omap_32k_fck,	CK_3XXX),
-	CLK(NULL,	"virt_12m_ck",	&virt_12m_ck,	CK_3XXX),
-	CLK(NULL,	"virt_13m_ck",	&virt_13m_ck,	CK_3XXX),
-	CLK(NULL,	"virt_16_8m_ck", &virt_16_8m_ck, CK_3430ES2PLUS | CK_AM35XX  | CK_36XX),
-	CLK(NULL,	"virt_19200000_ck", &virt_19200000_ck, CK_3XXX),
-	CLK(NULL,	"virt_26000000_ck",	&virt_26000000_ck,	CK_3XXX),
-	CLK(NULL,	"virt_38_4m_ck", &virt_38_4m_ck, CK_3XXX),
-	CLK(NULL,	"osc_sys_ck",	&osc_sys_ck,	CK_3XXX),
-	CLK("twl",	"fck",		&osc_sys_ck,	CK_3XXX),
-	CLK(NULL,	"sys_ck",	&sys_ck,	CK_3XXX),
-	CLK(NULL,	"sys_altclk",	&sys_altclk,	CK_3XXX),
-	CLK(NULL,	"mcbsp_clks",	&mcbsp_clks,	CK_3XXX),
-	CLK(NULL,	"sys_clkout1",	&sys_clkout1,	CK_3XXX),
-	CLK(NULL,	"dpll1_ck",	&dpll1_ck,	CK_3XXX),
-	CLK(NULL,	"dpll1_x2_ck",	&dpll1_x2_ck,	CK_3XXX),
-	CLK(NULL,	"dpll1_x2m2_ck", &dpll1_x2m2_ck, CK_3XXX),
-	CLK(NULL,	"dpll2_ck",	&dpll2_ck,	CK_34XX | CK_36XX),
-	CLK(NULL,	"dpll2_m2_ck",	&dpll2_m2_ck,	CK_34XX | CK_36XX),
-	CLK(NULL,	"dpll3_ck",	&dpll3_ck,	CK_3XXX),
-	CLK(NULL,	"core_ck",	&core_ck,	CK_3XXX),
-	CLK(NULL,	"dpll3_x2_ck",	&dpll3_x2_ck,	CK_3XXX),
-	CLK(NULL,	"dpll3_m2_ck",	&dpll3_m2_ck,	CK_3XXX),
-	CLK(NULL,	"dpll3_m2x2_ck", &dpll3_m2x2_ck, CK_3XXX),
-	CLK(NULL,	"dpll3_m3_ck",	&dpll3_m3_ck,	CK_3XXX),
-	CLK(NULL,	"dpll3_m3x2_ck", &dpll3_m3x2_ck, CK_3XXX),
-	CLK(NULL,	"emu_core_alwon_ck", &emu_core_alwon_ck, CK_3XXX),
-	CLK("etb",	"emu_core_alwon_ck", &emu_core_alwon_ck, CK_3XXX),
-	CLK(NULL,	"dpll4_ck",	&dpll4_ck,	CK_3XXX),
-	CLK(NULL,	"dpll4_x2_ck",	&dpll4_x2_ck,	CK_3XXX),
-	CLK(NULL,	"omap_192m_alwon_fck", &omap_192m_alwon_fck, CK_36XX),
-	CLK(NULL,	"omap_96m_alwon_fck", &omap_96m_alwon_fck, CK_3XXX),
-	CLK(NULL,	"omap_96m_alwon_fck_3630", &omap_96m_alwon_fck_3630, CK_36XX),
-	CLK(NULL,	"omap_96m_fck",	&omap_96m_fck,	CK_3XXX),
-	CLK(NULL,	"cm_96m_fck",	&cm_96m_fck,	CK_3XXX),
-	CLK(NULL,	"omap_54m_fck",	&omap_54m_fck,	CK_3XXX),
-	CLK(NULL,	"omap_48m_fck",	&omap_48m_fck,	CK_3XXX),
-	CLK(NULL,	"omap_12m_fck",	&omap_12m_fck,	CK_3XXX),
-	CLK(NULL,	"dpll4_m2_ck",	&dpll4_m2_ck,	CK_3XXX),
-	CLK(NULL,	"dpll4_m2x2_ck", &dpll4_m2x2_ck, CK_3XXX),
-	CLK(NULL,	"dpll4_m3_ck",	&dpll4_m3_ck,	CK_3XXX),
-	CLK(NULL,	"dpll4_m3x2_ck", &dpll4_m3x2_ck, CK_3XXX),
-	CLK(NULL,	"dpll4_m4_ck",	&dpll4_m4_ck,	CK_3XXX),
-	CLK(NULL,	"dpll4_m4x2_ck", &dpll4_m4x2_ck, CK_3XXX),
-	CLK(NULL,	"dpll4_m5_ck",	&dpll4_m5_ck,	CK_3XXX),
-	CLK(NULL,	"dpll4_m5x2_ck", &dpll4_m5x2_ck, CK_3XXX),
-	CLK(NULL,	"dpll4_m6_ck",	&dpll4_m6_ck,	CK_3XXX),
-	CLK(NULL,	"dpll4_m6x2_ck", &dpll4_m6x2_ck, CK_3XXX),
-	CLK(NULL,	"emu_per_alwon_ck", &emu_per_alwon_ck, CK_3XXX),
-	CLK("etb",	"emu_per_alwon_ck", &emu_per_alwon_ck, CK_3XXX),
-	CLK(NULL,	"dpll5_ck",	&dpll5_ck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK(NULL,	"dpll5_m2_ck",	&dpll5_m2_ck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK(NULL,	"clkout2_src_ck", &clkout2_src_ck, CK_3XXX),
-	CLK(NULL,	"sys_clkout2",	&sys_clkout2,	CK_3XXX),
-	CLK(NULL,	"corex2_fck",	&corex2_fck,	CK_3XXX),
-	CLK(NULL,	"dpll1_fck",	&dpll1_fck,	CK_3XXX),
-	CLK(NULL,	"mpu_ck",	&mpu_ck,	CK_3XXX),
-	CLK(NULL,	"arm_fck",	&arm_fck,	CK_3XXX),
-	CLK(NULL,	"emu_mpu_alwon_ck", &emu_mpu_alwon_ck, CK_3XXX),
-	CLK("etb",	"emu_mpu_alwon_ck", &emu_mpu_alwon_ck, CK_3XXX),
-	CLK(NULL,	"dpll2_fck",	&dpll2_fck,	CK_34XX | CK_36XX),
-	CLK(NULL,	"iva2_ck",	&iva2_ck,	CK_34XX | CK_36XX),
-	CLK(NULL,	"l3_ick",	&l3_ick,	CK_3XXX),
-	CLK(NULL,	"l4_ick",	&l4_ick,	CK_3XXX),
-	CLK(NULL,	"rm_ick",	&rm_ick,	CK_3XXX),
-	CLK(NULL,	"gfx_l3_ck",	&gfx_l3_ck,	CK_3430ES1),
-	CLK(NULL,	"gfx_l3_fck",	&gfx_l3_fck,	CK_3430ES1),
-	CLK(NULL,	"gfx_l3_ick",	&gfx_l3_ick,	CK_3430ES1),
-	CLK(NULL,	"gfx_cg1_ck",	&gfx_cg1_ck,	CK_3430ES1),
-	CLK(NULL,	"gfx_cg2_ck",	&gfx_cg2_ck,	CK_3430ES1),
-	CLK(NULL,	"sgx_fck",	&sgx_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK(NULL,	"sgx_ick",	&sgx_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK(NULL,	"d2d_26m_fck",	&d2d_26m_fck,	CK_3430ES1),
-	CLK(NULL,	"modem_fck",	&modem_fck,	CK_34XX | CK_36XX),
-	CLK(NULL,	"sad2d_ick",	&sad2d_ick,	CK_34XX | CK_36XX),
-	CLK(NULL,	"mad2d_ick",	&mad2d_ick,	CK_34XX | CK_36XX),
-	CLK(NULL,	"gpt10_fck",	&gpt10_fck,	CK_3XXX),
-	CLK(NULL,	"gpt11_fck",	&gpt11_fck,	CK_3XXX),
-	CLK(NULL,	"cpefuse_fck",	&cpefuse_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK(NULL,	"ts_fck",	&ts_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK(NULL,	"usbtll_fck",	&usbtll_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("usbhs_omap",	"usbtll_fck",	&usbtll_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("usbhs_tll",	"usbtll_fck",	&usbtll_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK(NULL,	"core_96m_fck",	&core_96m_fck,	CK_3XXX),
-	CLK(NULL,	"mmchs3_fck",	&mmchs3_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK(NULL,	"mmchs2_fck",	&mmchs2_fck,	CK_3XXX),
-	CLK(NULL,	"mspro_fck",	&mspro_fck,	CK_34XX | CK_36XX),
-	CLK(NULL,	"mmchs1_fck",	&mmchs1_fck,	CK_3XXX),
-	CLK(NULL,	"i2c3_fck",	&i2c3_fck,	CK_3XXX),
-	CLK(NULL,	"i2c2_fck",	&i2c2_fck,	CK_3XXX),
-	CLK(NULL,	"i2c1_fck",	&i2c1_fck,	CK_3XXX),
-	CLK(NULL,	"mcbsp5_fck",	&mcbsp5_fck,	CK_3XXX),
-	CLK(NULL,	"mcbsp1_fck",	&mcbsp1_fck,	CK_3XXX),
-	CLK(NULL,	"core_48m_fck",	&core_48m_fck,	CK_3XXX),
-	CLK(NULL,	"mcspi4_fck",	&mcspi4_fck,	CK_3XXX),
-	CLK(NULL,	"mcspi3_fck",	&mcspi3_fck,	CK_3XXX),
-	CLK(NULL,	"mcspi2_fck",	&mcspi2_fck,	CK_3XXX),
-	CLK(NULL,	"mcspi1_fck",	&mcspi1_fck,	CK_3XXX),
-	CLK(NULL,	"uart2_fck",	&uart2_fck,	CK_3XXX),
-	CLK(NULL,	"uart1_fck",	&uart1_fck,	CK_3XXX),
-	CLK(NULL,	"fshostusb_fck", &fshostusb_fck, CK_3430ES1),
-	CLK(NULL,	"core_12m_fck",	&core_12m_fck,	CK_3XXX),
-	CLK("omap_hdq.0",	"fck",	&hdq_fck,	CK_3XXX),
-	CLK(NULL,	"hdq_fck",	&hdq_fck,	CK_3XXX),
-	CLK(NULL,	"ssi_ssr_fck",	&ssi_ssr_fck_3430es1,	CK_3430ES1),
-	CLK(NULL,	"ssi_ssr_fck",	&ssi_ssr_fck_3430es2,	CK_3430ES2PLUS | CK_36XX),
-	CLK(NULL,	"ssi_sst_fck",	&ssi_sst_fck_3430es1,	CK_3430ES1),
-	CLK(NULL,	"ssi_sst_fck",	&ssi_sst_fck_3430es2,	CK_3430ES2PLUS | CK_36XX),
-	CLK(NULL,	"core_l3_ick",	&core_l3_ick,	CK_3XXX),
-	CLK("musb-omap2430",	"ick",	&hsotgusb_ick_3430es1,	CK_3430ES1),
-	CLK("musb-omap2430",	"ick",	&hsotgusb_ick_3430es2,	CK_3430ES2PLUS | CK_36XX),
-	CLK(NULL,	"hsotgusb_ick",	&hsotgusb_ick_3430es1,	CK_3430ES1),
-	CLK(NULL,	"hsotgusb_ick",	&hsotgusb_ick_3430es2,	CK_3430ES2PLUS | CK_36XX),
-	CLK(NULL,	"sdrc_ick",	&sdrc_ick,	CK_3XXX),
-	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_3XXX),
-	CLK(NULL,	"security_l3_ick", &security_l3_ick, CK_34XX | CK_36XX),
-	CLK(NULL,	"pka_ick",	&pka_ick,	CK_34XX | CK_36XX),
-	CLK(NULL,	"core_l4_ick",	&core_l4_ick,	CK_3XXX),
-	CLK(NULL,	"usbtll_ick",	&usbtll_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("usbhs_omap",	"usbtll_ick",	&usbtll_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("usbhs_tll",	"usbtll_ick",	&usbtll_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("omap_hsmmc.2",	"ick",	&mmchs3_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK(NULL,	"mmchs3_ick",	&mmchs3_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK(NULL,	"icr_ick",	&icr_ick,	CK_34XX | CK_36XX),
-	CLK("omap-aes",	"ick",	&aes2_ick,	CK_34XX | CK_36XX),
-	CLK("omap-sham",	"ick",	&sha12_ick,	CK_34XX | CK_36XX),
-	CLK(NULL,	"des2_ick",	&des2_ick,	CK_34XX | CK_36XX),
-	CLK("omap_hsmmc.1",	"ick",	&mmchs2_ick,	CK_3XXX),
-	CLK("omap_hsmmc.0",	"ick",	&mmchs1_ick,	CK_3XXX),
-	CLK(NULL,	"mmchs2_ick",	&mmchs2_ick,	CK_3XXX),
-	CLK(NULL,	"mmchs1_ick",	&mmchs1_ick,	CK_3XXX),
-	CLK(NULL,	"mspro_ick",	&mspro_ick,	CK_34XX | CK_36XX),
-	CLK("omap_hdq.0", "ick",	&hdq_ick,	CK_3XXX),
-	CLK(NULL,	"hdq_ick",	&hdq_ick,	CK_3XXX),
-	CLK("omap2_mcspi.4", "ick",	&mcspi4_ick,	CK_3XXX),
-	CLK("omap2_mcspi.3", "ick",	&mcspi3_ick,	CK_3XXX),
-	CLK("omap2_mcspi.2", "ick",	&mcspi2_ick,	CK_3XXX),
-	CLK("omap2_mcspi.1", "ick",	&mcspi1_ick,	CK_3XXX),
-	CLK(NULL,	"mcspi4_ick",	&mcspi4_ick,	CK_3XXX),
-	CLK(NULL,	"mcspi3_ick",	&mcspi3_ick,	CK_3XXX),
-	CLK(NULL,	"mcspi2_ick",	&mcspi2_ick,	CK_3XXX),
-	CLK(NULL,	"mcspi1_ick",	&mcspi1_ick,	CK_3XXX),
-	CLK("omap_i2c.3", "ick",	&i2c3_ick,	CK_3XXX),
-	CLK("omap_i2c.2", "ick",	&i2c2_ick,	CK_3XXX),
-	CLK("omap_i2c.1", "ick",	&i2c1_ick,	CK_3XXX),
-	CLK(NULL,	"i2c3_ick",	&i2c3_ick,	CK_3XXX),
-	CLK(NULL,	"i2c2_ick",	&i2c2_ick,	CK_3XXX),
-	CLK(NULL,	"i2c1_ick",	&i2c1_ick,	CK_3XXX),
-	CLK(NULL,	"uart2_ick",	&uart2_ick,	CK_3XXX),
-	CLK(NULL,	"uart1_ick",	&uart1_ick,	CK_3XXX),
-	CLK(NULL,	"gpt11_ick",	&gpt11_ick,	CK_3XXX),
-	CLK(NULL,	"gpt10_ick",	&gpt10_ick,	CK_3XXX),
-	CLK("omap-mcbsp.5", "ick",	&mcbsp5_ick,	CK_3XXX),
-	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick,	CK_3XXX),
-	CLK(NULL,	"mcbsp5_ick",	&mcbsp5_ick,	CK_3XXX),
-	CLK(NULL,	"mcbsp1_ick",	&mcbsp1_ick,	CK_3XXX),
-	CLK(NULL,	"fac_ick",	&fac_ick,	CK_3430ES1),
-	CLK(NULL,	"mailboxes_ick", &mailboxes_ick, CK_34XX | CK_36XX),
-	CLK(NULL,	"omapctrl_ick",	&omapctrl_ick,	CK_3XXX),
-	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_34XX | CK_36XX),
-	CLK(NULL,	"ssi_ick",	&ssi_ick_3430es1,	CK_3430ES1),
-	CLK(NULL,	"ssi_ick",	&ssi_ick_3430es2,	CK_3430ES2PLUS | CK_36XX),
-	CLK(NULL,	"usb_l4_ick",	&usb_l4_ick,	CK_3430ES1),
-	CLK(NULL,	"security_l4_ick2", &security_l4_ick2, CK_34XX | CK_36XX),
-	CLK(NULL,	"aes1_ick",	&aes1_ick,	CK_34XX | CK_36XX),
-	CLK("omap_rng",	"ick",		&rng_ick,	CK_34XX | CK_36XX),
-	CLK(NULL,	"sha11_ick",	&sha11_ick,	CK_34XX | CK_36XX),
-	CLK(NULL,	"des1_ick",	&des1_ick,	CK_34XX | CK_36XX),
-	CLK(NULL,	"dss1_alwon_fck",		&dss1_alwon_fck_3430es1, CK_3430ES1),
-	CLK(NULL,	"dss1_alwon_fck",		&dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK(NULL,	"dss_tv_fck",	&dss_tv_fck,	CK_3XXX),
-	CLK(NULL,	"dss_96m_fck",	&dss_96m_fck,	CK_3XXX),
-	CLK(NULL,	"dss2_alwon_fck",	&dss2_alwon_fck, CK_3XXX),
-	CLK("omapdss_dss",	"ick",		&dss_ick_3430es1,	CK_3430ES1),
-	CLK(NULL,	"dss_ick",		&dss_ick_3430es1,	CK_3430ES1),
-	CLK("omapdss_dss",	"ick",		&dss_ick_3430es2,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK(NULL,	"dss_ick",		&dss_ick_3430es2,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK(NULL,	"cam_mclk",	&cam_mclk,	CK_34XX | CK_36XX),
-	CLK(NULL,	"cam_ick",	&cam_ick,	CK_34XX | CK_36XX),
-	CLK(NULL,	"csi2_96m_fck",	&csi2_96m_fck,	CK_34XX | CK_36XX),
-	CLK(NULL,	"usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK(NULL,	"usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK(NULL,	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("usbhs_omap",	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK(NULL,	"utmi_p1_gfclk",	&dummy_ck,	CK_3XXX),
-	CLK(NULL,	"utmi_p2_gfclk",	&dummy_ck,	CK_3XXX),
-	CLK(NULL,	"xclk60mhsp1_ck",	&dummy_ck,	CK_3XXX),
-	CLK(NULL,	"xclk60mhsp2_ck",	&dummy_ck,	CK_3XXX),
-	CLK(NULL,	"usb_host_hs_utmi_p1_clk",	&dummy_ck,	CK_3XXX),
-	CLK(NULL,	"usb_host_hs_utmi_p2_clk",	&dummy_ck,	CK_3XXX),
-	CLK("usbhs_omap",	"usb_tll_hs_usb_ch0_clk",	&dummy_ck,	CK_3XXX),
-	CLK("usbhs_omap",	"usb_tll_hs_usb_ch1_clk",	&dummy_ck,	CK_3XXX),
-	CLK("usbhs_tll",	"usb_tll_hs_usb_ch0_clk",	&dummy_ck,	CK_3XXX),
-	CLK("usbhs_tll",	"usb_tll_hs_usb_ch1_clk",	&dummy_ck,	CK_3XXX),
-	CLK(NULL,	"init_60m_fclk",	&dummy_ck,	CK_3XXX),
-	CLK(NULL,	"usim_fck",	&usim_fck,	CK_3430ES2PLUS | CK_36XX),
-	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_3XXX),
-	CLK(NULL,	"wkup_32k_fck",	&wkup_32k_fck,	CK_3XXX),
-	CLK(NULL,	"gpio1_dbck",	&gpio1_dbck,	CK_3XXX),
-	CLK(NULL,	"wdt2_fck",		&wdt2_fck,	CK_3XXX),
-	CLK(NULL,	"wkup_l4_ick",	&wkup_l4_ick,	CK_34XX | CK_36XX),
-	CLK(NULL,	"usim_ick",	&usim_ick,	CK_3430ES2PLUS | CK_36XX),
-	CLK("omap_wdt",	"ick",		&wdt2_ick,	CK_3XXX),
-	CLK(NULL,	"wdt2_ick",	&wdt2_ick,	CK_3XXX),
-	CLK(NULL,	"wdt1_ick",	&wdt1_ick,	CK_3XXX),
-	CLK(NULL,	"gpio1_ick",	&gpio1_ick,	CK_3XXX),
-	CLK(NULL,	"omap_32ksync_ick", &omap_32ksync_ick, CK_3XXX),
-	CLK(NULL,	"gpt12_ick",	&gpt12_ick,	CK_3XXX),
-	CLK(NULL,	"gpt1_ick",	&gpt1_ick,	CK_3XXX),
-	CLK(NULL,	"per_96m_fck",	&per_96m_fck,	CK_3XXX),
-	CLK(NULL,	"per_48m_fck",	&per_48m_fck,	CK_3XXX),
-	CLK(NULL,	"uart3_fck",	&uart3_fck,	CK_3XXX),
-	CLK(NULL,	"uart4_fck",	&uart4_fck,	CK_36XX),
-	CLK(NULL,	"uart4_fck",	&uart4_fck_am35xx, CK_AM35XX),
-	CLK(NULL,	"gpt2_fck",	&gpt2_fck,	CK_3XXX),
-	CLK(NULL,	"gpt3_fck",	&gpt3_fck,	CK_3XXX),
-	CLK(NULL,	"gpt4_fck",	&gpt4_fck,	CK_3XXX),
-	CLK(NULL,	"gpt5_fck",	&gpt5_fck,	CK_3XXX),
-	CLK(NULL,	"gpt6_fck",	&gpt6_fck,	CK_3XXX),
-	CLK(NULL,	"gpt7_fck",	&gpt7_fck,	CK_3XXX),
-	CLK(NULL,	"gpt8_fck",	&gpt8_fck,	CK_3XXX),
-	CLK(NULL,	"gpt9_fck",	&gpt9_fck,	CK_3XXX),
-	CLK(NULL,	"per_32k_alwon_fck", &per_32k_alwon_fck, CK_3XXX),
-	CLK(NULL,	"gpio6_dbck",	&gpio6_dbck,	CK_3XXX),
-	CLK(NULL,	"gpio5_dbck",	&gpio5_dbck,	CK_3XXX),
-	CLK(NULL,	"gpio4_dbck",	&gpio4_dbck,	CK_3XXX),
-	CLK(NULL,	"gpio3_dbck",	&gpio3_dbck,	CK_3XXX),
-	CLK(NULL,	"gpio2_dbck",	&gpio2_dbck,	CK_3XXX),
-	CLK(NULL,	"wdt3_fck",	&wdt3_fck,	CK_3XXX),
-	CLK(NULL,	"per_l4_ick",	&per_l4_ick,	CK_3XXX),
-	CLK(NULL,	"gpio6_ick",	&gpio6_ick,	CK_3XXX),
-	CLK(NULL,	"gpio5_ick",	&gpio5_ick,	CK_3XXX),
-	CLK(NULL,	"gpio4_ick",	&gpio4_ick,	CK_3XXX),
-	CLK(NULL,	"gpio3_ick",	&gpio3_ick,	CK_3XXX),
-	CLK(NULL,	"gpio2_ick",	&gpio2_ick,	CK_3XXX),
-	CLK(NULL,	"wdt3_ick",	&wdt3_ick,	CK_3XXX),
-	CLK(NULL,	"uart3_ick",	&uart3_ick,	CK_3XXX),
-	CLK(NULL,	"uart4_ick",	&uart4_ick,	CK_36XX),
-	CLK(NULL,	"gpt9_ick",	&gpt9_ick,	CK_3XXX),
-	CLK(NULL,	"gpt8_ick",	&gpt8_ick,	CK_3XXX),
-	CLK(NULL,	"gpt7_ick",	&gpt7_ick,	CK_3XXX),
-	CLK(NULL,	"gpt6_ick",	&gpt6_ick,	CK_3XXX),
-	CLK(NULL,	"gpt5_ick",	&gpt5_ick,	CK_3XXX),
-	CLK(NULL,	"gpt4_ick",	&gpt4_ick,	CK_3XXX),
-	CLK(NULL,	"gpt3_ick",	&gpt3_ick,	CK_3XXX),
-	CLK(NULL,	"gpt2_ick",	&gpt2_ick,	CK_3XXX),
-	CLK("omap-mcbsp.2", "ick",	&mcbsp2_ick,	CK_3XXX),
-	CLK("omap-mcbsp.3", "ick",	&mcbsp3_ick,	CK_3XXX),
-	CLK("omap-mcbsp.4", "ick",	&mcbsp4_ick,	CK_3XXX),
-	CLK(NULL,	"mcbsp4_ick",	&mcbsp2_ick,	CK_3XXX),
-	CLK(NULL,	"mcbsp3_ick",	&mcbsp3_ick,	CK_3XXX),
-	CLK(NULL,	"mcbsp2_ick",	&mcbsp4_ick,	CK_3XXX),
-	CLK(NULL,	"mcbsp2_fck",	&mcbsp2_fck,	CK_3XXX),
-	CLK(NULL,	"mcbsp3_fck",	&mcbsp3_fck,	CK_3XXX),
-	CLK(NULL,	"mcbsp4_fck",	&mcbsp4_fck,	CK_3XXX),
-	CLK(NULL,	"emu_src_ck",	&emu_src_ck,	CK_3XXX),
-	CLK("etb",	"emu_src_ck",	&emu_src_ck,	CK_3XXX),
-	CLK(NULL,	"pclk_fck",	&pclk_fck,	CK_3XXX),
-	CLK(NULL,	"pclkx2_fck",	&pclkx2_fck,	CK_3XXX),
-	CLK(NULL,	"atclk_fck",	&atclk_fck,	CK_3XXX),
-	CLK(NULL,	"traceclk_src_fck", &traceclk_src_fck, CK_3XXX),
-	CLK(NULL,	"traceclk_fck",	&traceclk_fck,	CK_3XXX),
-	CLK(NULL,	"sr1_fck",	&sr1_fck,	CK_34XX | CK_36XX),
-	CLK(NULL,	"sr2_fck",	&sr2_fck,	CK_34XX | CK_36XX),
-	CLK(NULL,	"sr_l4_ick",	&sr_l4_ick,	CK_34XX | CK_36XX),
-	CLK(NULL,	"secure_32k_fck", &secure_32k_fck, CK_3XXX),
-	CLK(NULL,	"gpt12_fck",	&gpt12_fck,	CK_3XXX),
-	CLK(NULL,	"wdt1_fck",	&wdt1_fck,	CK_3XXX),
-	CLK(NULL,	"ipss_ick",	&ipss_ick,	CK_AM35XX),
-	CLK(NULL,	"rmii_ck",	&rmii_ck,	CK_AM35XX),
-	CLK(NULL,	"pclk_ck",	&pclk_ck,	CK_AM35XX),
-	CLK(NULL,	"emac_ick",	&emac_ick,	CK_AM35XX),
-	CLK(NULL,	"emac_fck",	&emac_fck,	CK_AM35XX),
-	CLK("davinci_emac.0",	NULL,	&emac_ick,	CK_AM35XX),
-	CLK("davinci_mdio.0",	NULL,	&emac_fck,	CK_AM35XX),
-	CLK(NULL,	"vpfe_ick",	&emac_ick,	CK_AM35XX),
-	CLK(NULL,	"vpfe_fck",	&emac_fck,	CK_AM35XX),
-	CLK("vpfe-capture",	"master",	&vpfe_ick,	CK_AM35XX),
-	CLK("vpfe-capture",	"slave",	&vpfe_fck,	CK_AM35XX),
-	CLK(NULL,	"hsotgusb_ick",		&hsotgusb_ick_am35xx,	CK_AM35XX),
-	CLK(NULL,	"hsotgusb_fck",		&hsotgusb_fck_am35xx,	CK_AM35XX),
-	CLK(NULL,	"hecc_ck",	&hecc_ck,	CK_AM35XX),
-	CLK(NULL,	"uart4_ick",	&uart4_ick_am35xx,	CK_AM35XX),
-	CLK(NULL,	"timer_32k_ck",	&omap_32k_fck,  CK_3XXX),
-	CLK(NULL,	"timer_sys_ck",	&sys_ck,	CK_3XXX),
-	CLK(NULL,	"cpufreq_ck",	&dpll1_ck,	CK_3XXX),
-};
-
-
-int __init omap3xxx_clk_init(void)
-{
-	struct omap_clk *c;
-	u32 cpu_clkflg = 0;
-
-	if (soc_is_am35xx()) {
-		cpu_mask = RATE_IN_34XX;
-		cpu_clkflg = CK_AM35XX;
-	} else if (cpu_is_omap3630()) {
-		cpu_mask = (RATE_IN_34XX | RATE_IN_36XX);
-		cpu_clkflg = CK_36XX;
-	} else if (cpu_is_ti816x()) {
-		cpu_mask = RATE_IN_TI816X;
-		cpu_clkflg = CK_TI816X;
-	} else if (soc_is_am33xx()) {
-		cpu_mask = RATE_IN_AM33XX;
-	} else if (cpu_is_ti814x()) {
-		cpu_mask = RATE_IN_TI814X;
-	} else if (cpu_is_omap34xx()) {
-		if (omap_rev() == OMAP3430_REV_ES1_0) {
-			cpu_mask = RATE_IN_3430ES1;
-			cpu_clkflg = CK_3430ES1;
-		} else {
-			/*
-			 * Assume that anything that we haven't matched yet
-			 * has 3430ES2-type clocks.
-			 */
-			cpu_mask = RATE_IN_3430ES2PLUS;
-			cpu_clkflg = CK_3430ES2PLUS;
-		}
-	} else {
-		WARN(1, "clock: could not identify OMAP3 variant\n");
-	}
-
-	if (omap3_has_192mhz_clk())
-		omap_96m_alwon_fck = omap_96m_alwon_fck_3630;
-
-	if (cpu_is_omap3630()) {
-		/*
-		 * XXX This type of dynamic rewriting of the clock tree is
-		 * deprecated and should be revised soon.
-		 *
-		 * For 3630: override clkops_omap2_dflt_wait for the
-		 * clocks affected from PWRDN reset Limitation
-		 */
-		dpll3_m3x2_ck.ops =
-				&clkops_omap36xx_pwrdn_with_hsdiv_wait_restore;
-		dpll4_m2x2_ck.ops =
-				&clkops_omap36xx_pwrdn_with_hsdiv_wait_restore;
-		dpll4_m3x2_ck.ops =
-				&clkops_omap36xx_pwrdn_with_hsdiv_wait_restore;
-		dpll4_m4x2_ck.ops =
-				&clkops_omap36xx_pwrdn_with_hsdiv_wait_restore;
-		dpll4_m5x2_ck.ops =
-				&clkops_omap36xx_pwrdn_with_hsdiv_wait_restore;
-		dpll4_m6x2_ck.ops =
-				&clkops_omap36xx_pwrdn_with_hsdiv_wait_restore;
-	}
-
-	/*
-	 * XXX This type of dynamic rewriting of the clock tree is
-	 * deprecated and should be revised soon.
-	 */
-	if (cpu_is_omap3630())
-		dpll4_dd = dpll4_dd_3630;
-	else
-		dpll4_dd = dpll4_dd_34xx;
-
-	clk_init(&omap2_clk_functions);
-
-	for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks);
-	     c++)
-		clk_preinit(c->lk.clk);
-
-	for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks);
-	     c++)
-		if (c->cpu & cpu_clkflg) {
-			clkdev_add(&c->lk);
-			clk_register(c->lk.clk);
-			omap2_init_clk_clkdm(c->lk.clk);
-		}
-
-	/* Disable autoidle on all clocks; let the PM code enable it later */
-	omap_clk_disable_autoidle_all();
-
-	recalculate_root_clocks();
-
-	pr_info("Clocking rate (Crystal/Core/MPU): %ld.%01ld/%ld/%ld MHz\n",
-		(osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10,
-		(core_ck.rate / 1000000), (arm_fck.rate / 1000000));
-
-	/*
-	 * Only enable those clocks we will need, let the drivers
-	 * enable other clocks as necessary
-	 */
-	clk_enable_init_clocks();
-
-	/*
-	 * Lock DPLL5 -- here only until other device init code can
-	 * handle this
-	 */
-	if (!cpu_is_ti81xx() && (omap_rev() >= OMAP3430_REV_ES2_0))
-		omap3_clk_lock_dpll5();
-
-	/* Avoid sleeping during omap3_core_dpll_m2_set_rate() */
-	sdrc_ick_p = clk_get(NULL, "sdrc_ick");
-	arm_fck_p = clk_get(NULL, "arm_fck");
-
-	return 0;
-}
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
deleted file mode 100644
index 6efc30c..0000000
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ /dev/null
@@ -1,3402 +0,0 @@
-/*
- * OMAP4 Clock data
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- * Copyright (C) 2009-2010 Nokia Corporation
- *
- * Paul Walmsley (paul@pwsan.com)
- * Rajendra Nayak (rnayak@ti.com)
- * Benoit Cousson (b-cousson@ti.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * XXX Some of the ES1 clocks have been removed/changed; once support
- * is added for discriminating clocks by ES level, these should be added back
- * in.
- */
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include <plat/clkdev_omap.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "clock44xx.h"
-#include "cm1_44xx.h"
-#include "cm2_44xx.h"
-#include "cm-regbits-44xx.h"
-#include "prm44xx.h"
-#include "prm-regbits-44xx.h"
-#include "control.h"
-#include "scrm44xx.h"
-
-/* OMAP4 modulemode control */
-#define OMAP4430_MODULEMODE_HWCTRL			0
-#define OMAP4430_MODULEMODE_SWCTRL			1
-
-/* Root clocks */
-
-static struct clk extalt_clkin_ck = {
-	.name		= "extalt_clkin_ck",
-	.rate		= 59000000,
-	.ops		= &clkops_null,
-};
-
-static struct clk pad_clks_ck = {
-	.name		= "pad_clks_ck",
-	.rate		= 12000000,
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_CLKSEL_ABE,
-	.enable_bit	= OMAP4430_PAD_CLKS_GATE_SHIFT,
-};
-
-static struct clk pad_slimbus_core_clks_ck = {
-	.name		= "pad_slimbus_core_clks_ck",
-	.rate		= 12000000,
-	.ops		= &clkops_null,
-};
-
-static struct clk secure_32k_clk_src_ck = {
-	.name		= "secure_32k_clk_src_ck",
-	.rate		= 32768,
-	.ops		= &clkops_null,
-};
-
-static struct clk slimbus_clk = {
-	.name		= "slimbus_clk",
-	.rate		= 12000000,
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_CLKSEL_ABE,
-	.enable_bit	= OMAP4430_SLIMBUS_CLK_GATE_SHIFT,
-};
-
-static struct clk sys_32k_ck = {
-	.name		= "sys_32k_ck",
-	.clkdm_name	= "prm_clkdm",
-	.rate		= 32768,
-	.ops		= &clkops_null,
-};
-
-static struct clk virt_12000000_ck = {
-	.name		= "virt_12000000_ck",
-	.ops		= &clkops_null,
-	.rate		= 12000000,
-};
-
-static struct clk virt_13000000_ck = {
-	.name		= "virt_13000000_ck",
-	.ops		= &clkops_null,
-	.rate		= 13000000,
-};
-
-static struct clk virt_16800000_ck = {
-	.name		= "virt_16800000_ck",
-	.ops		= &clkops_null,
-	.rate		= 16800000,
-};
-
-static struct clk virt_27000000_ck = {
-	.name		= "virt_27000000_ck",
-	.ops		= &clkops_null,
-	.rate		= 27000000,
-};
-
-static struct clk virt_38400000_ck = {
-	.name		= "virt_38400000_ck",
-	.ops		= &clkops_null,
-	.rate		= 38400000,
-};
-
-static const struct clksel_rate div_1_5_rates[] = {
-	{ .div = 1, .val = 5, .flags = RATE_IN_4430 },
-	{ .div = 0 },
-};
-
-static const struct clksel_rate div_1_6_rates[] = {
-	{ .div = 1, .val = 6, .flags = RATE_IN_4430 },
-	{ .div = 0 },
-};
-
-static const struct clksel_rate div_1_7_rates[] = {
-	{ .div = 1, .val = 7, .flags = RATE_IN_4430 },
-	{ .div = 0 },
-};
-
-static const struct clksel sys_clkin_sel[] = {
-	{ .parent = &virt_12000000_ck, .rates = div_1_1_rates },
-	{ .parent = &virt_13000000_ck, .rates = div_1_2_rates },
-	{ .parent = &virt_16800000_ck, .rates = div_1_3_rates },
-	{ .parent = &virt_19200000_ck, .rates = div_1_4_rates },
-	{ .parent = &virt_26000000_ck, .rates = div_1_5_rates },
-	{ .parent = &virt_27000000_ck, .rates = div_1_6_rates },
-	{ .parent = &virt_38400000_ck, .rates = div_1_7_rates },
-	{ .parent = NULL },
-};
-
-static struct clk sys_clkin_ck = {
-	.name		= "sys_clkin_ck",
-	.rate		= 38400000,
-	.clksel		= sys_clkin_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_SYS_CLKSEL,
-	.clksel_mask	= OMAP4430_SYS_CLKSEL_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk tie_low_clock_ck = {
-	.name		= "tie_low_clock_ck",
-	.rate		= 0,
-	.ops		= &clkops_null,
-};
-
-static struct clk utmi_phy_clkout_ck = {
-	.name		= "utmi_phy_clkout_ck",
-	.rate		= 60000000,
-	.ops		= &clkops_null,
-};
-
-static struct clk xclk60mhsp1_ck = {
-	.name		= "xclk60mhsp1_ck",
-	.rate		= 60000000,
-	.ops		= &clkops_null,
-};
-
-static struct clk xclk60mhsp2_ck = {
-	.name		= "xclk60mhsp2_ck",
-	.rate		= 60000000,
-	.ops		= &clkops_null,
-};
-
-static struct clk xclk60motg_ck = {
-	.name		= "xclk60motg_ck",
-	.rate		= 60000000,
-	.ops		= &clkops_null,
-};
-
-/* Module clocks and DPLL outputs */
-
-static const struct clksel abe_dpll_bypass_clk_mux_sel[] = {
-	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-	{ .parent = &sys_32k_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk abe_dpll_bypass_clk_mux_ck = {
-	.name		= "abe_dpll_bypass_clk_mux_ck",
-	.parent		= &sys_clkin_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk abe_dpll_refclk_mux_ck = {
-	.name		= "abe_dpll_refclk_mux_ck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= abe_dpll_bypass_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_ABE_PLL_REF_CLKSEL,
-	.clksel_mask	= OMAP4430_CLKSEL_0_0_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* DPLL_ABE */
-static struct dpll_data dpll_abe_dd = {
-	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_ABE,
-	.clk_bypass	= &abe_dpll_bypass_clk_mux_ck,
-	.clk_ref	= &abe_dpll_refclk_mux_ck,
-	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_ABE,
-	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_ABE,
-	.idlest_reg	= OMAP4430_CM_IDLEST_DPLL_ABE,
-	.mult_mask	= OMAP4430_DPLL_MULT_MASK,
-	.div1_mask	= OMAP4430_DPLL_DIV_MASK,
-	.enable_mask	= OMAP4430_DPLL_EN_MASK,
-	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
-	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
-	.max_multiplier	= 2047,
-	.max_divider	= 128,
-	.min_divider	= 1,
-};
-
-
-static struct clk dpll_abe_ck = {
-	.name		= "dpll_abe_ck",
-	.parent		= &abe_dpll_refclk_mux_ck,
-	.dpll_data	= &dpll_abe_dd,
-	.init		= &omap2_init_dpll_parent,
-	.ops		= &clkops_omap3_noncore_dpll_ops,
-	.recalc		= &omap4_dpll_regm4xen_recalc,
-	.round_rate	= &omap4_dpll_regm4xen_round_rate,
-	.set_rate	= &omap3_noncore_dpll_set_rate,
-};
-
-static struct clk dpll_abe_x2_ck = {
-	.name		= "dpll_abe_x2_ck",
-	.parent		= &dpll_abe_ck,
-	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
-	.flags		= CLOCK_CLKOUTX2,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap3_clkoutx2_recalc,
-};
-
-static const struct clksel dpll_abe_m2x2_div[] = {
-	{ .parent = &dpll_abe_x2_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_abe_m2x2_ck = {
-	.name		= "dpll_abe_m2x2_ck",
-	.parent		= &dpll_abe_x2_ck,
-	.clksel		= dpll_abe_m2x2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
-	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk abe_24m_fclk = {
-	.name		= "abe_24m_fclk",
-	.parent		= &dpll_abe_m2x2_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 8,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static const struct clksel_rate div3_1to4_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_4430 },
-	{ .div = 2, .val = 1, .flags = RATE_IN_4430 },
-	{ .div = 4, .val = 2, .flags = RATE_IN_4430 },
-	{ .div = 0 },
-};
-
-static const struct clksel abe_clk_div[] = {
-	{ .parent = &dpll_abe_m2x2_ck, .rates = div3_1to4_rates },
-	{ .parent = NULL },
-};
-
-static struct clk abe_clk = {
-	.name		= "abe_clk",
-	.parent		= &dpll_abe_m2x2_ck,
-	.clksel		= abe_clk_div,
-	.clksel_reg	= OMAP4430_CM_CLKSEL_ABE,
-	.clksel_mask	= OMAP4430_CLKSEL_OPP_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel_rate div2_1to2_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_4430 },
-	{ .div = 2, .val = 1, .flags = RATE_IN_4430 },
-	{ .div = 0 },
-};
-
-static const struct clksel aess_fclk_div[] = {
-	{ .parent = &abe_clk, .rates = div2_1to2_rates },
-	{ .parent = NULL },
-};
-
-static struct clk aess_fclk = {
-	.name		= "aess_fclk",
-	.parent		= &abe_clk,
-	.clksel		= aess_fclk_div,
-	.clksel_reg	= OMAP4430_CM1_ABE_AESS_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_AESS_FCLK_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_abe_m3x2_ck = {
-	.name		= "dpll_abe_m3x2_ck",
-	.parent		= &dpll_abe_x2_ck,
-	.clksel		= dpll_abe_m2x2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M3_DPLL_ABE,
-	.clksel_mask	= OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel core_hsd_byp_clk_mux_sel[] = {
-	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-	{ .parent = &dpll_abe_m3x2_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk core_hsd_byp_clk_mux_ck = {
-	.name		= "core_hsd_byp_clk_mux_ck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= core_hsd_byp_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_CLKSEL_DPLL_CORE,
-	.clksel_mask	= OMAP4430_DPLL_BYP_CLKSEL_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* DPLL_CORE */
-static struct dpll_data dpll_core_dd = {
-	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_CORE,
-	.clk_bypass	= &core_hsd_byp_clk_mux_ck,
-	.clk_ref	= &sys_clkin_ck,
-	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_CORE,
-	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_CORE,
-	.idlest_reg	= OMAP4430_CM_IDLEST_DPLL_CORE,
-	.mult_mask	= OMAP4430_DPLL_MULT_MASK,
-	.div1_mask	= OMAP4430_DPLL_DIV_MASK,
-	.enable_mask	= OMAP4430_DPLL_EN_MASK,
-	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
-	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
-	.max_multiplier	= 2047,
-	.max_divider	= 128,
-	.min_divider	= 1,
-};
-
-
-static struct clk dpll_core_ck = {
-	.name		= "dpll_core_ck",
-	.parent		= &sys_clkin_ck,
-	.dpll_data	= &dpll_core_dd,
-	.init		= &omap2_init_dpll_parent,
-	.ops		= &clkops_omap3_core_dpll_ops,
-	.recalc		= &omap3_dpll_recalc,
-};
-
-static struct clk dpll_core_x2_ck = {
-	.name		= "dpll_core_x2_ck",
-	.parent		= &dpll_core_ck,
-	.flags		= CLOCK_CLKOUTX2,
-	.ops		= &clkops_null,
-	.recalc		= &omap3_clkoutx2_recalc,
-};
-
-static const struct clksel dpll_core_m6x2_div[] = {
-	{ .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_core_m6x2_ck = {
-	.name		= "dpll_core_m6x2_ck",
-	.parent		= &dpll_core_x2_ck,
-	.clksel		= dpll_core_m6x2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M6_DPLL_CORE,
-	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel dbgclk_mux_sel[] = {
-	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-	{ .parent = &dpll_core_m6x2_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dbgclk_mux_ck = {
-	.name		= "dbgclk_mux_ck",
-	.parent		= &sys_clkin_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel dpll_core_m2_div[] = {
-	{ .parent = &dpll_core_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_core_m2_ck = {
-	.name		= "dpll_core_m2_ck",
-	.parent		= &dpll_core_ck,
-	.clksel		= dpll_core_m2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_CORE,
-	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk ddrphy_ck = {
-	.name		= "ddrphy_ck",
-	.parent		= &dpll_core_m2_ck,
-	.ops		= &clkops_null,
-	.clkdm_name	= "l3_emif_clkdm",
-	.fixed_div	= 2,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static struct clk dpll_core_m5x2_ck = {
-	.name		= "dpll_core_m5x2_ck",
-	.parent		= &dpll_core_x2_ck,
-	.clksel		= dpll_core_m6x2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M5_DPLL_CORE,
-	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel div_core_div[] = {
-	{ .parent = &dpll_core_m5x2_ck, .rates = div2_1to2_rates },
-	{ .parent = NULL },
-};
-
-static struct clk div_core_ck = {
-	.name		= "div_core_ck",
-	.parent		= &dpll_core_m5x2_ck,
-	.clksel		= div_core_div,
-	.clksel_reg	= OMAP4430_CM_CLKSEL_CORE,
-	.clksel_mask	= OMAP4430_CLKSEL_CORE_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel_rate div4_1to8_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_4430 },
-	{ .div = 2, .val = 1, .flags = RATE_IN_4430 },
-	{ .div = 4, .val = 2, .flags = RATE_IN_4430 },
-	{ .div = 8, .val = 3, .flags = RATE_IN_4430 },
-	{ .div = 0 },
-};
-
-static const struct clksel div_iva_hs_clk_div[] = {
-	{ .parent = &dpll_core_m5x2_ck, .rates = div4_1to8_rates },
-	{ .parent = NULL },
-};
-
-static struct clk div_iva_hs_clk = {
-	.name		= "div_iva_hs_clk",
-	.parent		= &dpll_core_m5x2_ck,
-	.clksel		= div_iva_hs_clk_div,
-	.clksel_reg	= OMAP4430_CM_BYPCLK_DPLL_IVA,
-	.clksel_mask	= OMAP4430_CLKSEL_0_1_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk div_mpu_hs_clk = {
-	.name		= "div_mpu_hs_clk",
-	.parent		= &dpll_core_m5x2_ck,
-	.clksel		= div_iva_hs_clk_div,
-	.clksel_reg	= OMAP4430_CM_BYPCLK_DPLL_MPU,
-	.clksel_mask	= OMAP4430_CLKSEL_0_1_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_core_m4x2_ck = {
-	.name		= "dpll_core_m4x2_ck",
-	.parent		= &dpll_core_x2_ck,
-	.clksel		= dpll_core_m6x2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M4_DPLL_CORE,
-	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk dll_clk_div_ck = {
-	.name		= "dll_clk_div_ck",
-	.parent		= &dpll_core_m4x2_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 2,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static const struct clksel dpll_abe_m2_div[] = {
-	{ .parent = &dpll_abe_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_abe_m2_ck = {
-	.name		= "dpll_abe_m2_ck",
-	.parent		= &dpll_abe_ck,
-	.clksel		= dpll_abe_m2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
-	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_core_m3x2_ck = {
-	.name		= "dpll_core_m3x2_ck",
-	.parent		= &dpll_core_x2_ck,
-	.clksel		= dpll_core_m6x2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M3_DPLL_CORE,
-	.clksel_mask	= OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-	.enable_reg	= OMAP4430_CM_DIV_M3_DPLL_CORE,
-	.enable_bit	= OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT,
-};
-
-static struct clk dpll_core_m7x2_ck = {
-	.name		= "dpll_core_m7x2_ck",
-	.parent		= &dpll_core_x2_ck,
-	.clksel		= dpll_core_m6x2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M7_DPLL_CORE,
-	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel iva_hsd_byp_clk_mux_sel[] = {
-	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-	{ .parent = &div_iva_hs_clk, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk iva_hsd_byp_clk_mux_ck = {
-	.name		= "iva_hsd_byp_clk_mux_ck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= iva_hsd_byp_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_CLKSEL_DPLL_IVA,
-	.clksel_mask	= OMAP4430_DPLL_BYP_CLKSEL_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* DPLL_IVA */
-static struct dpll_data dpll_iva_dd = {
-	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_IVA,
-	.clk_bypass	= &iva_hsd_byp_clk_mux_ck,
-	.clk_ref	= &sys_clkin_ck,
-	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_IVA,
-	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_IVA,
-	.idlest_reg	= OMAP4430_CM_IDLEST_DPLL_IVA,
-	.mult_mask	= OMAP4430_DPLL_MULT_MASK,
-	.div1_mask	= OMAP4430_DPLL_DIV_MASK,
-	.enable_mask	= OMAP4430_DPLL_EN_MASK,
-	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
-	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
-	.max_multiplier	= 2047,
-	.max_divider	= 128,
-	.min_divider	= 1,
-};
-
-
-static struct clk dpll_iva_ck = {
-	.name		= "dpll_iva_ck",
-	.parent		= &sys_clkin_ck,
-	.dpll_data	= &dpll_iva_dd,
-	.init		= &omap2_init_dpll_parent,
-	.ops		= &clkops_omap3_noncore_dpll_ops,
-	.recalc		= &omap3_dpll_recalc,
-	.round_rate	= &omap2_dpll_round_rate,
-	.set_rate	= &omap3_noncore_dpll_set_rate,
-};
-
-static struct clk dpll_iva_x2_ck = {
-	.name		= "dpll_iva_x2_ck",
-	.parent		= &dpll_iva_ck,
-	.flags		= CLOCK_CLKOUTX2,
-	.ops		= &clkops_null,
-	.recalc		= &omap3_clkoutx2_recalc,
-};
-
-static const struct clksel dpll_iva_m4x2_div[] = {
-	{ .parent = &dpll_iva_x2_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_iva_m4x2_ck = {
-	.name		= "dpll_iva_m4x2_ck",
-	.parent		= &dpll_iva_x2_ck,
-	.clksel		= dpll_iva_m4x2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M4_DPLL_IVA,
-	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_iva_m5x2_ck = {
-	.name		= "dpll_iva_m5x2_ck",
-	.parent		= &dpll_iva_x2_ck,
-	.clksel		= dpll_iva_m4x2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M5_DPLL_IVA,
-	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-/* DPLL_MPU */
-static struct dpll_data dpll_mpu_dd = {
-	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_MPU,
-	.clk_bypass	= &div_mpu_hs_clk,
-	.clk_ref	= &sys_clkin_ck,
-	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_MPU,
-	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_MPU,
-	.idlest_reg	= OMAP4430_CM_IDLEST_DPLL_MPU,
-	.mult_mask	= OMAP4430_DPLL_MULT_MASK,
-	.div1_mask	= OMAP4430_DPLL_DIV_MASK,
-	.enable_mask	= OMAP4430_DPLL_EN_MASK,
-	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
-	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
-	.max_multiplier	= 2047,
-	.max_divider	= 128,
-	.min_divider	= 1,
-};
-
-
-static struct clk dpll_mpu_ck = {
-	.name		= "dpll_mpu_ck",
-	.parent		= &sys_clkin_ck,
-	.dpll_data	= &dpll_mpu_dd,
-	.init		= &omap2_init_dpll_parent,
-	.ops		= &clkops_omap3_noncore_dpll_ops,
-	.recalc		= &omap3_dpll_recalc,
-	.round_rate	= &omap2_dpll_round_rate,
-	.set_rate	= &omap3_noncore_dpll_set_rate,
-};
-
-static const struct clksel dpll_mpu_m2_div[] = {
-	{ .parent = &dpll_mpu_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_mpu_m2_ck = {
-	.name		= "dpll_mpu_m2_ck",
-	.parent		= &dpll_mpu_ck,
-	.clkdm_name	= "cm_clkdm",
-	.clksel		= dpll_mpu_m2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_MPU,
-	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk per_hs_clk_div_ck = {
-	.name		= "per_hs_clk_div_ck",
-	.parent		= &dpll_abe_m3x2_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 2,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static const struct clksel per_hsd_byp_clk_mux_sel[] = {
-	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-	{ .parent = &per_hs_clk_div_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk per_hsd_byp_clk_mux_ck = {
-	.name		= "per_hsd_byp_clk_mux_ck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= per_hsd_byp_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_CLKSEL_DPLL_PER,
-	.clksel_mask	= OMAP4430_DPLL_BYP_CLKSEL_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* DPLL_PER */
-static struct dpll_data dpll_per_dd = {
-	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_PER,
-	.clk_bypass	= &per_hsd_byp_clk_mux_ck,
-	.clk_ref	= &sys_clkin_ck,
-	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_PER,
-	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_PER,
-	.idlest_reg	= OMAP4430_CM_IDLEST_DPLL_PER,
-	.mult_mask	= OMAP4430_DPLL_MULT_MASK,
-	.div1_mask	= OMAP4430_DPLL_DIV_MASK,
-	.enable_mask	= OMAP4430_DPLL_EN_MASK,
-	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
-	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
-	.max_multiplier	= 2047,
-	.max_divider	= 128,
-	.min_divider	= 1,
-};
-
-
-static struct clk dpll_per_ck = {
-	.name		= "dpll_per_ck",
-	.parent		= &sys_clkin_ck,
-	.dpll_data	= &dpll_per_dd,
-	.init		= &omap2_init_dpll_parent,
-	.ops		= &clkops_omap3_noncore_dpll_ops,
-	.recalc		= &omap3_dpll_recalc,
-	.round_rate	= &omap2_dpll_round_rate,
-	.set_rate	= &omap3_noncore_dpll_set_rate,
-};
-
-static const struct clksel dpll_per_m2_div[] = {
-	{ .parent = &dpll_per_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_per_m2_ck = {
-	.name		= "dpll_per_m2_ck",
-	.parent		= &dpll_per_ck,
-	.clksel		= dpll_per_m2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_PER,
-	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_per_x2_ck = {
-	.name		= "dpll_per_x2_ck",
-	.parent		= &dpll_per_ck,
-	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_PER,
-	.flags		= CLOCK_CLKOUTX2,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap3_clkoutx2_recalc,
-};
-
-static const struct clksel dpll_per_m2x2_div[] = {
-	{ .parent = &dpll_per_x2_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_per_m2x2_ck = {
-	.name		= "dpll_per_m2x2_ck",
-	.parent		= &dpll_per_x2_ck,
-	.clksel		= dpll_per_m2x2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_PER,
-	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_per_m3x2_ck = {
-	.name		= "dpll_per_m3x2_ck",
-	.parent		= &dpll_per_x2_ck,
-	.clksel		= dpll_per_m2x2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M3_DPLL_PER,
-	.clksel_mask	= OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-	.enable_reg	= OMAP4430_CM_DIV_M3_DPLL_PER,
-	.enable_bit	= OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT,
-};
-
-static struct clk dpll_per_m4x2_ck = {
-	.name		= "dpll_per_m4x2_ck",
-	.parent		= &dpll_per_x2_ck,
-	.clksel		= dpll_per_m2x2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M4_DPLL_PER,
-	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_per_m5x2_ck = {
-	.name		= "dpll_per_m5x2_ck",
-	.parent		= &dpll_per_x2_ck,
-	.clksel		= dpll_per_m2x2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M5_DPLL_PER,
-	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_per_m6x2_ck = {
-	.name		= "dpll_per_m6x2_ck",
-	.parent		= &dpll_per_x2_ck,
-	.clksel		= dpll_per_m2x2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M6_DPLL_PER,
-	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk dpll_per_m7x2_ck = {
-	.name		= "dpll_per_m7x2_ck",
-	.parent		= &dpll_per_x2_ck,
-	.clksel		= dpll_per_m2x2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M7_DPLL_PER,
-	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk usb_hs_clk_div_ck = {
-	.name		= "usb_hs_clk_div_ck",
-	.parent		= &dpll_abe_m3x2_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 3,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-/* DPLL_USB */
-static struct dpll_data dpll_usb_dd = {
-	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_USB,
-	.clk_bypass	= &usb_hs_clk_div_ck,
-	.flags		= DPLL_J_TYPE,
-	.clk_ref	= &sys_clkin_ck,
-	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_USB,
-	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_USB,
-	.idlest_reg	= OMAP4430_CM_IDLEST_DPLL_USB,
-	.mult_mask	= OMAP4430_DPLL_MULT_USB_MASK,
-	.div1_mask	= OMAP4430_DPLL_DIV_0_7_MASK,
-	.enable_mask	= OMAP4430_DPLL_EN_MASK,
-	.autoidle_mask	= OMAP4430_AUTO_DPLL_MODE_MASK,
-	.idlest_mask	= OMAP4430_ST_DPLL_CLK_MASK,
-	.sddiv_mask	= OMAP4430_DPLL_SD_DIV_MASK,
-	.max_multiplier	= 4095,
-	.max_divider	= 256,
-	.min_divider	= 1,
-};
-
-
-static struct clk dpll_usb_ck = {
-	.name		= "dpll_usb_ck",
-	.parent		= &sys_clkin_ck,
-	.dpll_data	= &dpll_usb_dd,
-	.init		= &omap2_init_dpll_parent,
-	.ops		= &clkops_omap3_noncore_dpll_ops,
-	.recalc		= &omap3_dpll_recalc,
-	.round_rate	= &omap2_dpll_round_rate,
-	.set_rate	= &omap3_noncore_dpll_set_rate,
-	.clkdm_name	= "l3_init_clkdm",
-};
-
-static struct clk dpll_usb_clkdcoldo_ck = {
-	.name		= "dpll_usb_clkdcoldo_ck",
-	.parent		= &dpll_usb_ck,
-	.clksel_reg	= OMAP4430_CM_CLKDCOLDO_DPLL_USB,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel dpll_usb_m2_div[] = {
-	{ .parent = &dpll_usb_ck, .rates = div31_1to31_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_usb_m2_ck = {
-	.name		= "dpll_usb_m2_ck",
-	.parent		= &dpll_usb_ck,
-	.clksel		= dpll_usb_m2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_USB,
-	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK,
-	.ops		= &clkops_omap4_dpllmx_ops,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel ducati_clk_mux_sel[] = {
-	{ .parent = &div_core_ck, .rates = div_1_0_rates },
-	{ .parent = &dpll_per_m6x2_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk ducati_clk_mux_ck = {
-	.name		= "ducati_clk_mux_ck",
-	.parent		= &div_core_ck,
-	.clksel		= ducati_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_CLKSEL_DUCATI_ISS_ROOT,
-	.clksel_mask	= OMAP4430_CLKSEL_0_0_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk func_12m_fclk = {
-	.name		= "func_12m_fclk",
-	.parent		= &dpll_per_m2x2_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 16,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static struct clk func_24m_clk = {
-	.name		= "func_24m_clk",
-	.parent		= &dpll_per_m2_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 4,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static struct clk func_24mc_fclk = {
-	.name		= "func_24mc_fclk",
-	.parent		= &dpll_per_m2x2_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 8,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static const struct clksel_rate div2_4to8_rates[] = {
-	{ .div = 4, .val = 0, .flags = RATE_IN_4430 },
-	{ .div = 8, .val = 1, .flags = RATE_IN_4430 },
-	{ .div = 0 },
-};
-
-static const struct clksel func_48m_fclk_div[] = {
-	{ .parent = &dpll_per_m2x2_ck, .rates = div2_4to8_rates },
-	{ .parent = NULL },
-};
-
-static struct clk func_48m_fclk = {
-	.name		= "func_48m_fclk",
-	.parent		= &dpll_per_m2x2_ck,
-	.clksel		= func_48m_fclk_div,
-	.clksel_reg	= OMAP4430_CM_SCALE_FCLK,
-	.clksel_mask	= OMAP4430_SCALE_FCLK_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk func_48mc_fclk = {
-	.name		= "func_48mc_fclk",
-	.parent		= &dpll_per_m2x2_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 4,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static const struct clksel_rate div2_2to4_rates[] = {
-	{ .div = 2, .val = 0, .flags = RATE_IN_4430 },
-	{ .div = 4, .val = 1, .flags = RATE_IN_4430 },
-	{ .div = 0 },
-};
-
-static const struct clksel func_64m_fclk_div[] = {
-	{ .parent = &dpll_per_m4x2_ck, .rates = div2_2to4_rates },
-	{ .parent = NULL },
-};
-
-static struct clk func_64m_fclk = {
-	.name		= "func_64m_fclk",
-	.parent		= &dpll_per_m4x2_ck,
-	.clksel		= func_64m_fclk_div,
-	.clksel_reg	= OMAP4430_CM_SCALE_FCLK,
-	.clksel_mask	= OMAP4430_SCALE_FCLK_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel func_96m_fclk_div[] = {
-	{ .parent = &dpll_per_m2x2_ck, .rates = div2_2to4_rates },
-	{ .parent = NULL },
-};
-
-static struct clk func_96m_fclk = {
-	.name		= "func_96m_fclk",
-	.parent		= &dpll_per_m2x2_ck,
-	.clksel		= func_96m_fclk_div,
-	.clksel_reg	= OMAP4430_CM_SCALE_FCLK,
-	.clksel_mask	= OMAP4430_SCALE_FCLK_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel_rate div2_1to8_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_4430 },
-	{ .div = 8, .val = 1, .flags = RATE_IN_4430 },
-	{ .div = 0 },
-};
-
-static const struct clksel init_60m_fclk_div[] = {
-	{ .parent = &dpll_usb_m2_ck, .rates = div2_1to8_rates },
-	{ .parent = NULL },
-};
-
-static struct clk init_60m_fclk = {
-	.name		= "init_60m_fclk",
-	.parent		= &dpll_usb_m2_ck,
-	.clksel		= init_60m_fclk_div,
-	.clksel_reg	= OMAP4430_CM_CLKSEL_USB_60MHZ,
-	.clksel_mask	= OMAP4430_CLKSEL_0_0_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel l3_div_div[] = {
-	{ .parent = &div_core_ck, .rates = div2_1to2_rates },
-	{ .parent = NULL },
-};
-
-static struct clk l3_div_ck = {
-	.name		= "l3_div_ck",
-	.parent		= &div_core_ck,
-	.clkdm_name	= "cm_clkdm",
-	.clksel		= l3_div_div,
-	.clksel_reg	= OMAP4430_CM_CLKSEL_CORE,
-	.clksel_mask	= OMAP4430_CLKSEL_L3_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel l4_div_div[] = {
-	{ .parent = &l3_div_ck, .rates = div2_1to2_rates },
-	{ .parent = NULL },
-};
-
-static struct clk l4_div_ck = {
-	.name		= "l4_div_ck",
-	.parent		= &l3_div_ck,
-	.clksel		= l4_div_div,
-	.clksel_reg	= OMAP4430_CM_CLKSEL_CORE,
-	.clksel_mask	= OMAP4430_CLKSEL_L4_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk lp_clk_div_ck = {
-	.name		= "lp_clk_div_ck",
-	.parent		= &dpll_abe_m2x2_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 16,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static const struct clksel l4_wkup_clk_mux_sel[] = {
-	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-	{ .parent = &lp_clk_div_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk l4_wkup_clk_mux_ck = {
-	.name		= "l4_wkup_clk_mux_ck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= l4_wkup_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L4_WKUP_CLKSEL,
-	.clksel_mask	= OMAP4430_CLKSEL_0_0_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel_rate div2_2to1_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_4430 },
-	{ .div = 2, .val = 0, .flags = RATE_IN_4430 },
-	{ .div = 0 },
-};
-
-static const struct clksel ocp_abe_iclk_div[] = {
-	{ .parent = &aess_fclk, .rates = div2_2to1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk mpu_periphclk = {
-	.name		= "mpu_periphclk",
-	.parent		= &dpll_mpu_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 2,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static struct clk ocp_abe_iclk = {
-	.name		= "ocp_abe_iclk",
-	.parent		= &aess_fclk,
-	.clksel		= ocp_abe_iclk_div,
-	.clksel_reg	= OMAP4430_CM1_ABE_AESS_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_AESS_FCLK_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk per_abe_24m_fclk = {
-	.name		= "per_abe_24m_fclk",
-	.parent		= &dpll_abe_m2_ck,
-	.ops		= &clkops_null,
-	.fixed_div	= 4,
-	.recalc		= &omap_fixed_divisor_recalc,
-};
-
-static const struct clksel per_abe_nc_fclk_div[] = {
-	{ .parent = &dpll_abe_m2_ck, .rates = div2_1to2_rates },
-	{ .parent = NULL },
-};
-
-static struct clk per_abe_nc_fclk = {
-	.name		= "per_abe_nc_fclk",
-	.parent		= &dpll_abe_m2_ck,
-	.clksel		= per_abe_nc_fclk_div,
-	.clksel_reg	= OMAP4430_CM_SCALE_FCLK,
-	.clksel_mask	= OMAP4430_SCALE_FCLK_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel pmd_stm_clock_mux_sel[] = {
-	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-	{ .parent = &dpll_core_m6x2_ck, .rates = div_1_1_rates },
-	{ .parent = &tie_low_clock_ck, .rates = div_1_2_rates },
-	{ .parent = NULL },
-};
-
-static struct clk pmd_stm_clock_mux_ck = {
-	.name		= "pmd_stm_clock_mux_ck",
-	.parent		= &sys_clkin_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk pmd_trace_clk_mux_ck = {
-	.name		= "pmd_trace_clk_mux_ck",
-	.parent		= &sys_clkin_ck,
-	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel syc_clk_div_div[] = {
-	{ .parent = &sys_clkin_ck, .rates = div2_1to2_rates },
-	{ .parent = NULL },
-};
-
-static struct clk syc_clk_div_ck = {
-	.name		= "syc_clk_div_ck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= syc_clk_div_div,
-	.clksel_reg	= OMAP4430_CM_ABE_DSS_SYS_CLKSEL,
-	.clksel_mask	= OMAP4430_CLKSEL_0_0_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-/* Leaf clocks controlled by modules */
-
-static struct clk aes1_fck = {
-	.name		= "aes1_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4SEC_AES1_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_secure_clkdm",
-	.parent		= &l3_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk aes2_fck = {
-	.name		= "aes2_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4SEC_AES2_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_secure_clkdm",
-	.parent		= &l3_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk aess_fck = {
-	.name		= "aess_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM1_ABE_AESS_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-	.parent		= &aess_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk bandgap_fclk = {
-	.name		= "bandgap_fclk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_BGAP_32K_SHIFT,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &sys_32k_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk des3des_fck = {
-	.name		= "des3des_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4SEC_DES3DES_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_secure_clkdm",
-	.parent		= &l4_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel dmic_sync_mux_sel[] = {
-	{ .parent = &abe_24m_fclk, .rates = div_1_0_rates },
-	{ .parent = &syc_clk_div_ck, .rates = div_1_1_rates },
-	{ .parent = &func_24m_clk, .rates = div_1_2_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dmic_sync_mux_ck = {
-	.name		= "dmic_sync_mux_ck",
-	.parent		= &abe_24m_fclk,
-	.clksel		= dmic_sync_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_DMIC_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel func_dmic_abe_gfclk_sel[] = {
-	{ .parent = &dmic_sync_mux_ck, .rates = div_1_0_rates },
-	{ .parent = &pad_clks_ck, .rates = div_1_1_rates },
-	{ .parent = &slimbus_clk, .rates = div_1_2_rates },
-	{ .parent = NULL },
-};
-
-/* Merged func_dmic_abe_gfclk into dmic */
-static struct clk dmic_fck = {
-	.name		= "dmic_fck",
-	.parent		= &dmic_sync_mux_ck,
-	.clksel		= func_dmic_abe_gfclk_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_DMIC_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_SOURCE_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM1_ABE_DMIC_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-};
-
-static struct clk dsp_fck = {
-	.name		= "dsp_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_TESLA_TESLA_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "tesla_clkdm",
-	.parent		= &dpll_iva_m4x2_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dss_sys_clk = {
-	.name		= "dss_sys_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_DSS_DSS_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT,
-	.clkdm_name	= "l3_dss_clkdm",
-	.parent		= &syc_clk_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dss_tv_clk = {
-	.name		= "dss_tv_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_DSS_DSS_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_TV_CLK_SHIFT,
-	.clkdm_name	= "l3_dss_clkdm",
-	.parent		= &extalt_clkin_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dss_dss_clk = {
-	.name		= "dss_dss_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_DSS_DSS_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_DSSCLK_SHIFT,
-	.clkdm_name	= "l3_dss_clkdm",
-	.parent		= &dpll_per_m5x2_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel_rate div3_8to32_rates[] = {
-	{ .div = 8, .val = 0, .flags = RATE_IN_4460 },
-	{ .div = 16, .val = 1, .flags = RATE_IN_4460 },
-	{ .div = 32, .val = 2, .flags = RATE_IN_4460 },
-	{ .div = 0 },
-};
-
-static const struct clksel div_ts_div[] = {
-	{ .parent = &l4_wkup_clk_mux_ck, .rates = div3_8to32_rates },
-	{ .parent = NULL },
-};
-
-static struct clk div_ts_ck = {
-	.name		= "div_ts_ck",
-	.parent		= &l4_wkup_clk_mux_ck,
-	.clksel		= div_ts_div,
-	.clksel_reg	= OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_24_25_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk bandgap_ts_fclk = {
-	.name		= "bandgap_ts_fclk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
-	.enable_bit	= OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &div_ts_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dss_48mhz_clk = {
-	.name		= "dss_48mhz_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_DSS_DSS_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT,
-	.clkdm_name	= "l3_dss_clkdm",
-	.parent		= &func_48mc_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk dss_fck = {
-	.name		= "dss_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_DSS_DSS_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l3_dss_clkdm",
-	.parent		= &l3_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk efuse_ctrl_cust_fck = {
-	.name		= "efuse_ctrl_cust_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_cefuse_clkdm",
-	.parent		= &sys_clkin_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk emif1_fck = {
-	.name		= "emif1_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "l3_emif_clkdm",
-	.parent		= &ddrphy_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk emif2_fck = {
-	.name		= "emif2_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "l3_emif_clkdm",
-	.parent		= &ddrphy_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel fdif_fclk_div[] = {
-	{ .parent = &dpll_per_m4x2_ck, .rates = div3_1to4_rates },
-	{ .parent = NULL },
-};
-
-/* Merged fdif_fclk into fdif */
-static struct clk fdif_fck = {
-	.name		= "fdif_fck",
-	.parent		= &dpll_per_m4x2_ck,
-	.clksel		= fdif_fclk_div,
-	.clksel_reg	= OMAP4430_CM_CAM_FDIF_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_FCLK_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-	.enable_reg	= OMAP4430_CM_CAM_FDIF_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "iss_clkdm",
-};
-
-static struct clk fpka_fck = {
-	.name		= "fpka_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_secure_clkdm",
-	.parent		= &l4_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio1_dbclk = {
-	.name		= "gpio1_dbclk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &sys_32k_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio1_ick = {
-	.name		= "gpio1_ick",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &l4_wkup_clk_mux_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio2_dbclk = {
-	.name		= "gpio2_dbclk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &sys_32k_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio2_ick = {
-	.name		= "gpio2_ick",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &l4_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio3_dbclk = {
-	.name		= "gpio3_dbclk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &sys_32k_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio3_ick = {
-	.name		= "gpio3_ick",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &l4_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio4_dbclk = {
-	.name		= "gpio4_dbclk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &sys_32k_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio4_ick = {
-	.name		= "gpio4_ick",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &l4_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio5_dbclk = {
-	.name		= "gpio5_dbclk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &sys_32k_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio5_ick = {
-	.name		= "gpio5_ick",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &l4_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio6_dbclk = {
-	.name		= "gpio6_dbclk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &sys_32k_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpio6_ick = {
-	.name		= "gpio6_ick",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &l4_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk gpmc_ick = {
-	.name		= "gpmc_ick",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3_2_GPMC_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "l3_2_clkdm",
-	.parent		= &l3_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel sgx_clk_mux_sel[] = {
-	{ .parent = &dpll_core_m7x2_ck, .rates = div_1_0_rates },
-	{ .parent = &dpll_per_m7x2_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-/* Merged sgx_clk_mux into gpu */
-static struct clk gpu_fck = {
-	.name		= "gpu_fck",
-	.parent		= &dpll_core_m7x2_ck,
-	.clksel		= sgx_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_GFX_GFX_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_SGX_FCLK_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_GFX_GFX_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l3_gfx_clkdm",
-};
-
-static struct clk hdq1w_fck = {
-	.name		= "hdq1w_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_HDQ1W_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_12m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel hsi_fclk_div[] = {
-	{ .parent = &dpll_per_m2x2_ck, .rates = div3_1to4_rates },
-	{ .parent = NULL },
-};
-
-/* Merged hsi_fclk into hsi */
-static struct clk hsi_fck = {
-	.name		= "hsi_fck",
-	.parent		= &dpll_per_m2x2_ck,
-	.clksel		= hsi_fclk_div,
-	.clksel_reg	= OMAP4430_CM_L3INIT_HSI_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_24_25_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-	.enable_reg	= OMAP4430_CM_L3INIT_HSI_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "l3_init_clkdm",
-};
-
-static struct clk i2c1_fck = {
-	.name		= "i2c1_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_I2C1_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_96m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk i2c2_fck = {
-	.name		= "i2c2_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_I2C2_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_96m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk i2c3_fck = {
-	.name		= "i2c3_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_I2C3_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_96m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk i2c4_fck = {
-	.name		= "i2c4_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_I2C4_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_96m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk ipu_fck = {
-	.name		= "ipu_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "ducati_clkdm",
-	.parent		= &ducati_clk_mux_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk iss_ctrlclk = {
-	.name		= "iss_ctrlclk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_CAM_ISS_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_CTRLCLK_SHIFT,
-	.clkdm_name	= "iss_clkdm",
-	.parent		= &func_96m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk iss_fck = {
-	.name		= "iss_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_CAM_ISS_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "iss_clkdm",
-	.parent		= &ducati_clk_mux_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk iva_fck = {
-	.name		= "iva_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_IVAHD_IVAHD_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "ivahd_clkdm",
-	.parent		= &dpll_iva_m5x2_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk kbd_fck = {
-	.name		= "kbd_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &sys_32k_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk l3_instr_ick = {
-	.name		= "l3_instr_ick",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "l3_instr_clkdm",
-	.parent		= &l3_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk l3_main_3_ick = {
-	.name		= "l3_main_3_ick",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INSTR_L3_3_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "l3_instr_clkdm",
-	.parent		= &l3_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcasp_sync_mux_ck = {
-	.name		= "mcasp_sync_mux_ck",
-	.parent		= &abe_24m_fclk,
-	.clksel		= dmic_sync_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_MCASP_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel func_mcasp_abe_gfclk_sel[] = {
-	{ .parent = &mcasp_sync_mux_ck, .rates = div_1_0_rates },
-	{ .parent = &pad_clks_ck, .rates = div_1_1_rates },
-	{ .parent = &slimbus_clk, .rates = div_1_2_rates },
-	{ .parent = NULL },
-};
-
-/* Merged func_mcasp_abe_gfclk into mcasp */
-static struct clk mcasp_fck = {
-	.name		= "mcasp_fck",
-	.parent		= &mcasp_sync_mux_ck,
-	.clksel		= func_mcasp_abe_gfclk_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_MCASP_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_SOURCE_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM1_ABE_MCASP_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-};
-
-static struct clk mcbsp1_sync_mux_ck = {
-	.name		= "mcbsp1_sync_mux_ck",
-	.parent		= &abe_24m_fclk,
-	.clksel		= dmic_sync_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel func_mcbsp1_gfclk_sel[] = {
-	{ .parent = &mcbsp1_sync_mux_ck, .rates = div_1_0_rates },
-	{ .parent = &pad_clks_ck, .rates = div_1_1_rates },
-	{ .parent = &slimbus_clk, .rates = div_1_2_rates },
-	{ .parent = NULL },
-};
-
-/* Merged func_mcbsp1_gfclk into mcbsp1 */
-static struct clk mcbsp1_fck = {
-	.name		= "mcbsp1_fck",
-	.parent		= &mcbsp1_sync_mux_ck,
-	.clksel		= func_mcbsp1_gfclk_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_SOURCE_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-};
-
-static struct clk mcbsp2_sync_mux_ck = {
-	.name		= "mcbsp2_sync_mux_ck",
-	.parent		= &abe_24m_fclk,
-	.clksel		= dmic_sync_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel func_mcbsp2_gfclk_sel[] = {
-	{ .parent = &mcbsp2_sync_mux_ck, .rates = div_1_0_rates },
-	{ .parent = &pad_clks_ck, .rates = div_1_1_rates },
-	{ .parent = &slimbus_clk, .rates = div_1_2_rates },
-	{ .parent = NULL },
-};
-
-/* Merged func_mcbsp2_gfclk into mcbsp2 */
-static struct clk mcbsp2_fck = {
-	.name		= "mcbsp2_fck",
-	.parent		= &mcbsp2_sync_mux_ck,
-	.clksel		= func_mcbsp2_gfclk_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_SOURCE_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-};
-
-static struct clk mcbsp3_sync_mux_ck = {
-	.name		= "mcbsp3_sync_mux_ck",
-	.parent		= &abe_24m_fclk,
-	.clksel		= dmic_sync_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel func_mcbsp3_gfclk_sel[] = {
-	{ .parent = &mcbsp3_sync_mux_ck, .rates = div_1_0_rates },
-	{ .parent = &pad_clks_ck, .rates = div_1_1_rates },
-	{ .parent = &slimbus_clk, .rates = div_1_2_rates },
-	{ .parent = NULL },
-};
-
-/* Merged func_mcbsp3_gfclk into mcbsp3 */
-static struct clk mcbsp3_fck = {
-	.name		= "mcbsp3_fck",
-	.parent		= &mcbsp3_sync_mux_ck,
-	.clksel		= func_mcbsp3_gfclk_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_SOURCE_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-};
-
-static const struct clksel mcbsp4_sync_mux_sel[] = {
-	{ .parent = &func_96m_fclk, .rates = div_1_0_rates },
-	{ .parent = &per_abe_nc_fclk, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk mcbsp4_sync_mux_ck = {
-	.name		= "mcbsp4_sync_mux_ck",
-	.parent		= &func_96m_fclk,
-	.clksel		= mcbsp4_sync_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel per_mcbsp4_gfclk_sel[] = {
-	{ .parent = &mcbsp4_sync_mux_ck, .rates = div_1_0_rates },
-	{ .parent = &pad_clks_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-/* Merged per_mcbsp4_gfclk into mcbsp4 */
-static struct clk mcbsp4_fck = {
-	.name		= "mcbsp4_fck",
-	.parent		= &mcbsp4_sync_mux_ck,
-	.clksel		= per_mcbsp4_gfclk_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_SOURCE_24_24_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-};
-
-static struct clk mcpdm_fck = {
-	.name		= "mcpdm_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM1_ABE_PDM_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-	.parent		= &pad_clks_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi1_fck = {
-	.name		= "mcspi1_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_MCSPI1_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_48m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi2_fck = {
-	.name		= "mcspi2_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_MCSPI2_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_48m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi3_fck = {
-	.name		= "mcspi3_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_MCSPI3_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_48m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mcspi4_fck = {
-	.name		= "mcspi4_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_MCSPI4_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_48m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel hsmmc1_fclk_sel[] = {
-	{ .parent = &func_64m_fclk, .rates = div_1_0_rates },
-	{ .parent = &func_96m_fclk, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-/* Merged hsmmc1_fclk into mmc1 */
-static struct clk mmc1_fck = {
-	.name		= "mmc1_fck",
-	.parent		= &func_64m_fclk,
-	.clksel		= hsmmc1_fclk_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L3INIT_MMC1_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_L3INIT_MMC1_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l3_init_clkdm",
-};
-
-/* Merged hsmmc2_fclk into mmc2 */
-static struct clk mmc2_fck = {
-	.name		= "mmc2_fck",
-	.parent		= &func_64m_fclk,
-	.clksel		= hsmmc1_fclk_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L3INIT_MMC2_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_L3INIT_MMC2_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l3_init_clkdm",
-};
-
-static struct clk mmc3_fck = {
-	.name		= "mmc3_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_MMCSD3_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_48m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmc4_fck = {
-	.name		= "mmc4_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_MMCSD4_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_48m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk mmc5_fck = {
-	.name		= "mmc5_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_MMCSD5_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_48m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk ocp2scp_usb_phy_phy_48m = {
-	.name		= "ocp2scp_usb_phy_phy_48m",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_PHY_48M_SHIFT,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &func_48m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk ocp2scp_usb_phy_ick = {
-	.name		= "ocp2scp_usb_phy_ick",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &l4_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk ocp_wp_noc_ick = {
-	.name		= "ocp_wp_noc_ick",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "l3_instr_clkdm",
-	.parent		= &l3_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk rng_ick = {
-	.name		= "rng_ick",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4SEC_RNG_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "l4_secure_clkdm",
-	.parent		= &l4_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk sha2md5_fck = {
-	.name		= "sha2md5_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_secure_clkdm",
-	.parent		= &l3_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk sl2if_ick = {
-	.name		= "sl2if_ick",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_IVAHD_SL2_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "ivahd_clkdm",
-	.parent		= &dpll_iva_m5x2_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk slimbus1_fclk_1 = {
-	.name		= "slimbus1_fclk_1",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_FCLK1_SHIFT,
-	.clkdm_name	= "abe_clkdm",
-	.parent		= &func_24m_clk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk slimbus1_fclk_0 = {
-	.name		= "slimbus1_fclk_0",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_FCLK0_SHIFT,
-	.clkdm_name	= "abe_clkdm",
-	.parent		= &abe_24m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk slimbus1_fclk_2 = {
-	.name		= "slimbus1_fclk_2",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_FCLK2_SHIFT,
-	.clkdm_name	= "abe_clkdm",
-	.parent		= &pad_clks_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk slimbus1_slimbus_clk = {
-	.name		= "slimbus1_slimbus_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_SHIFT,
-	.clkdm_name	= "abe_clkdm",
-	.parent		= &slimbus_clk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk slimbus1_fck = {
-	.name		= "slimbus1_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-	.parent		= &ocp_abe_iclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk slimbus2_fclk_1 = {
-	.name		= "slimbus2_fclk_1",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_SHIFT,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &per_abe_24m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk slimbus2_fclk_0 = {
-	.name		= "slimbus2_fclk_0",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_PER24MC_GFCLK_SHIFT,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_24mc_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk slimbus2_slimbus_clk = {
-	.name		= "slimbus2_slimbus_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_SLIMBUS_CLK_SHIFT,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &pad_slimbus_core_clks_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk slimbus2_fck = {
-	.name		= "slimbus2_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &l4_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk smartreflex_core_fck = {
-	.name		= "smartreflex_core_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_ao_clkdm",
-	.parent		= &l4_wkup_clk_mux_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk smartreflex_iva_fck = {
-	.name		= "smartreflex_iva_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_ao_clkdm",
-	.parent		= &l4_wkup_clk_mux_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk smartreflex_mpu_fck = {
-	.name		= "smartreflex_mpu_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_ao_clkdm",
-	.parent		= &l4_wkup_clk_mux_ck,
-	.recalc		= &followparent_recalc,
-};
-
-/* Merged dmt1_clk_mux into timer1 */
-static struct clk timer1_fck = {
-	.name		= "timer1_fck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= abe_dpll_bypass_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_wkup_clkdm",
-};
-
-/* Merged cm2_dm10_mux into timer10 */
-static struct clk timer10_fck = {
-	.name		= "timer10_fck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= abe_dpll_bypass_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-};
-
-/* Merged cm2_dm11_mux into timer11 */
-static struct clk timer11_fck = {
-	.name		= "timer11_fck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= abe_dpll_bypass_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-};
-
-/* Merged cm2_dm2_mux into timer2 */
-static struct clk timer2_fck = {
-	.name		= "timer2_fck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= abe_dpll_bypass_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-};
-
-/* Merged cm2_dm3_mux into timer3 */
-static struct clk timer3_fck = {
-	.name		= "timer3_fck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= abe_dpll_bypass_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-};
-
-/* Merged cm2_dm4_mux into timer4 */
-static struct clk timer4_fck = {
-	.name		= "timer4_fck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= abe_dpll_bypass_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-};
-
-static const struct clksel timer5_sync_mux_sel[] = {
-	{ .parent = &syc_clk_div_ck, .rates = div_1_0_rates },
-	{ .parent = &sys_32k_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-/* Merged timer5_sync_mux into timer5 */
-static struct clk timer5_fck = {
-	.name		= "timer5_fck",
-	.parent		= &syc_clk_div_ck,
-	.clksel		= timer5_sync_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-};
-
-/* Merged timer6_sync_mux into timer6 */
-static struct clk timer6_fck = {
-	.name		= "timer6_fck",
-	.parent		= &syc_clk_div_ck,
-	.clksel		= timer5_sync_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-};
-
-/* Merged timer7_sync_mux into timer7 */
-static struct clk timer7_fck = {
-	.name		= "timer7_fck",
-	.parent		= &syc_clk_div_ck,
-	.clksel		= timer5_sync_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-};
-
-/* Merged timer8_sync_mux into timer8 */
-static struct clk timer8_fck = {
-	.name		= "timer8_fck",
-	.parent		= &syc_clk_div_ck,
-	.clksel		= timer5_sync_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-};
-
-/* Merged cm2_dm9_mux into timer9 */
-static struct clk timer9_fck = {
-	.name		= "timer9_fck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= abe_dpll_bypass_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-};
-
-static struct clk uart1_fck = {
-	.name		= "uart1_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_UART1_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_48m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart2_fck = {
-	.name		= "uart2_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_UART2_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_48m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart3_fck = {
-	.name		= "uart3_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_UART3_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_48m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk uart4_fck = {
-	.name		= "uart4_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4PER_UART4_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-	.parent		= &func_48m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_host_fs_fck = {
-	.name		= "usb_host_fs_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_FS_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &func_48mc_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel utmi_p1_gfclk_sel[] = {
-	{ .parent = &init_60m_fclk, .rates = div_1_0_rates },
-	{ .parent = &xclk60mhsp1_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk utmi_p1_gfclk = {
-	.name		= "utmi_p1_gfclk",
-	.parent		= &init_60m_fclk,
-	.clksel		= utmi_p1_gfclk_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_UTMI_P1_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk usb_host_hs_utmi_p1_clk = {
-	.name		= "usb_host_hs_utmi_p1_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &utmi_p1_gfclk,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel utmi_p2_gfclk_sel[] = {
-	{ .parent = &init_60m_fclk, .rates = div_1_0_rates },
-	{ .parent = &xclk60mhsp2_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk utmi_p2_gfclk = {
-	.name		= "utmi_p2_gfclk",
-	.parent		= &init_60m_fclk,
-	.clksel		= utmi_p2_gfclk_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_UTMI_P2_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk usb_host_hs_utmi_p2_clk = {
-	.name		= "usb_host_hs_utmi_p2_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &utmi_p2_gfclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_host_hs_utmi_p3_clk = {
-	.name		= "usb_host_hs_utmi_p3_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &init_60m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_host_hs_hsic480m_p1_clk = {
-	.name		= "usb_host_hs_hsic480m_p1_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_SHIFT,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &dpll_usb_m2_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_host_hs_hsic60m_p1_clk = {
-	.name		= "usb_host_hs_hsic60m_p1_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &init_60m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_host_hs_hsic60m_p2_clk = {
-	.name		= "usb_host_hs_hsic60m_p2_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &init_60m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_host_hs_hsic480m_p2_clk = {
-	.name		= "usb_host_hs_hsic480m_p2_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_SHIFT,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &dpll_usb_m2_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_host_hs_func48mclk = {
-	.name		= "usb_host_hs_func48mclk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_FUNC48MCLK_SHIFT,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &func_48mc_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_host_hs_fck = {
-	.name		= "usb_host_hs_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &init_60m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel otg_60m_gfclk_sel[] = {
-	{ .parent = &utmi_phy_clkout_ck, .rates = div_1_0_rates },
-	{ .parent = &xclk60motg_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk otg_60m_gfclk = {
-	.name		= "otg_60m_gfclk",
-	.parent		= &utmi_phy_clkout_ck,
-	.clksel		= otg_60m_gfclk_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_60M_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk usb_otg_hs_xclk = {
-	.name		= "usb_otg_hs_xclk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_XCLK_SHIFT,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &otg_60m_gfclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_otg_hs_ick = {
-	.name		= "usb_otg_hs_ick",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &l3_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_phy_cm_clk32k = {
-	.name		= "usb_phy_cm_clk32k",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_ALWON_USBPHY_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_CLK32K_SHIFT,
-	.clkdm_name	= "l4_ao_clkdm",
-	.parent		= &sys_32k_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_tll_hs_usb_ch2_clk = {
-	.name		= "usb_tll_hs_usb_ch2_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_USB_CH2_CLK_SHIFT,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &init_60m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_tll_hs_usb_ch0_clk = {
-	.name		= "usb_tll_hs_usb_ch0_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_USB_CH0_CLK_SHIFT,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &init_60m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_tll_hs_usb_ch1_clk = {
-	.name		= "usb_tll_hs_usb_ch1_clk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_USB_CH1_CLK_SHIFT,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &init_60m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_tll_hs_ick = {
-	.name		= "usb_tll_hs_ick",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &l4_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static const struct clksel_rate div2_14to18_rates[] = {
-	{ .div = 14, .val = 0, .flags = RATE_IN_4430 },
-	{ .div = 18, .val = 1, .flags = RATE_IN_4430 },
-	{ .div = 0 },
-};
-
-static const struct clksel usim_fclk_div[] = {
-	{ .parent = &dpll_per_m4x2_ck, .rates = div2_14to18_rates },
-	{ .parent = NULL },
-};
-
-static struct clk usim_ck = {
-	.name		= "usim_ck",
-	.parent		= &dpll_per_m4x2_ck,
-	.clksel		= usim_fclk_div,
-	.clksel_reg	= OMAP4430_CM_WKUP_USIM_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_DIV_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk usim_fclk = {
-	.name		= "usim_fclk",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_WKUP_USIM_CLKCTRL,
-	.enable_bit	= OMAP4430_OPTFCLKEN_FCLK_SHIFT,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &usim_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usim_fck = {
-	.name		= "usim_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_WKUP_USIM_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &sys_32k_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wd_timer2_fck = {
-	.name		= "wd_timer2_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_WKUP_WDT2_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &sys_32k_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk wd_timer3_fck = {
-	.name		= "wd_timer3_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM1_ABE_WDT3_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-	.parent		= &sys_32k_ck,
-	.recalc		= &followparent_recalc,
-};
-
-/* Remaining optional clocks */
-static const struct clksel stm_clk_div_div[] = {
-	{ .parent = &pmd_stm_clock_mux_ck, .rates = div3_1to4_rates },
-	{ .parent = NULL },
-};
-
-static struct clk stm_clk_div_ck = {
-	.name		= "stm_clk_div_ck",
-	.parent		= &pmd_stm_clock_mux_ck,
-	.clksel		= stm_clk_div_div,
-	.clksel_reg	= OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_PMD_STM_CLK_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel trace_clk_div_div[] = {
-	{ .parent = &pmd_trace_clk_mux_ck, .rates = div3_1to4_rates },
-	{ .parent = NULL },
-};
-
-static struct clk trace_clk_div_ck = {
-	.name		= "trace_clk_div_ck",
-	.parent		= &pmd_trace_clk_mux_ck,
-	.clkdm_name	= "emu_sys_clkdm",
-	.clksel		= trace_clk_div_div,
-	.clksel_reg	= OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-/* SCRM aux clk nodes */
-
-static const struct clksel auxclk_src_sel[] = {
-	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-	{ .parent = &dpll_core_m3x2_ck, .rates = div_1_1_rates },
-	{ .parent = &dpll_per_m3x2_ck, .rates = div_1_2_rates },
-	{ .parent = NULL },
-};
-
-static const struct clksel_rate div16_1to16_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_4430 },
-	{ .div = 2, .val = 1, .flags = RATE_IN_4430 },
-	{ .div = 3, .val = 2, .flags = RATE_IN_4430 },
-	{ .div = 4, .val = 3, .flags = RATE_IN_4430 },
-	{ .div = 5, .val = 4, .flags = RATE_IN_4430 },
-	{ .div = 6, .val = 5, .flags = RATE_IN_4430 },
-	{ .div = 7, .val = 6, .flags = RATE_IN_4430 },
-	{ .div = 8, .val = 7, .flags = RATE_IN_4430 },
-	{ .div = 9, .val = 8, .flags = RATE_IN_4430 },
-	{ .div = 10, .val = 9, .flags = RATE_IN_4430 },
-	{ .div = 11, .val = 10, .flags = RATE_IN_4430 },
-	{ .div = 12, .val = 11, .flags = RATE_IN_4430 },
-	{ .div = 13, .val = 12, .flags = RATE_IN_4430 },
-	{ .div = 14, .val = 13, .flags = RATE_IN_4430 },
-	{ .div = 15, .val = 14, .flags = RATE_IN_4430 },
-	{ .div = 16, .val = 15, .flags = RATE_IN_4430 },
-	{ .div = 0 },
-};
-
-static struct clk auxclk0_src_ck = {
-	.name		= "auxclk0_src_ck",
-	.parent		= &sys_clkin_ck,
-	.init		= &omap2_init_clksel_parent,
-	.ops		= &clkops_omap2_dflt,
-	.clksel		= auxclk_src_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLK0,
-	.clksel_mask	= OMAP4_SRCSELECT_MASK,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4_SCRM_AUXCLK0,
-	.enable_bit	= OMAP4_ENABLE_SHIFT,
-};
-
-static const struct clksel auxclk0_sel[] = {
-	{ .parent = &auxclk0_src_ck, .rates = div16_1to16_rates },
-	{ .parent = NULL },
-};
-
-static struct clk auxclk0_ck = {
-	.name		= "auxclk0_ck",
-	.parent		= &auxclk0_src_ck,
-	.clksel		= auxclk0_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLK0,
-	.clksel_mask	= OMAP4_CLKDIV_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk auxclk1_src_ck = {
-	.name		= "auxclk1_src_ck",
-	.parent		= &sys_clkin_ck,
-	.init		= &omap2_init_clksel_parent,
-	.ops		= &clkops_omap2_dflt,
-	.clksel		= auxclk_src_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLK1,
-	.clksel_mask	= OMAP4_SRCSELECT_MASK,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4_SCRM_AUXCLK1,
-	.enable_bit	= OMAP4_ENABLE_SHIFT,
-};
-
-static const struct clksel auxclk1_sel[] = {
-	{ .parent = &auxclk1_src_ck, .rates = div16_1to16_rates },
-	{ .parent = NULL },
-};
-
-static struct clk auxclk1_ck = {
-	.name		= "auxclk1_ck",
-	.parent		= &auxclk1_src_ck,
-	.clksel		= auxclk1_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLK1,
-	.clksel_mask	= OMAP4_CLKDIV_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk auxclk2_src_ck = {
-	.name		= "auxclk2_src_ck",
-	.parent		= &sys_clkin_ck,
-	.init		= &omap2_init_clksel_parent,
-	.ops		= &clkops_omap2_dflt,
-	.clksel		= auxclk_src_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLK2,
-	.clksel_mask	= OMAP4_SRCSELECT_MASK,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4_SCRM_AUXCLK2,
-	.enable_bit	= OMAP4_ENABLE_SHIFT,
-};
-
-static const struct clksel auxclk2_sel[] = {
-	{ .parent = &auxclk2_src_ck, .rates = div16_1to16_rates },
-	{ .parent = NULL },
-};
-
-static struct clk auxclk2_ck = {
-	.name		= "auxclk2_ck",
-	.parent		= &auxclk2_src_ck,
-	.clksel		= auxclk2_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLK2,
-	.clksel_mask	= OMAP4_CLKDIV_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk auxclk3_src_ck = {
-	.name		= "auxclk3_src_ck",
-	.parent		= &sys_clkin_ck,
-	.init		= &omap2_init_clksel_parent,
-	.ops		= &clkops_omap2_dflt,
-	.clksel		= auxclk_src_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLK3,
-	.clksel_mask	= OMAP4_SRCSELECT_MASK,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4_SCRM_AUXCLK3,
-	.enable_bit	= OMAP4_ENABLE_SHIFT,
-};
-
-static const struct clksel auxclk3_sel[] = {
-	{ .parent = &auxclk3_src_ck, .rates = div16_1to16_rates },
-	{ .parent = NULL },
-};
-
-static struct clk auxclk3_ck = {
-	.name		= "auxclk3_ck",
-	.parent		= &auxclk3_src_ck,
-	.clksel		= auxclk3_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLK3,
-	.clksel_mask	= OMAP4_CLKDIV_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk auxclk4_src_ck = {
-	.name		= "auxclk4_src_ck",
-	.parent		= &sys_clkin_ck,
-	.init		= &omap2_init_clksel_parent,
-	.ops		= &clkops_omap2_dflt,
-	.clksel		= auxclk_src_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLK4,
-	.clksel_mask	= OMAP4_SRCSELECT_MASK,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4_SCRM_AUXCLK4,
-	.enable_bit	= OMAP4_ENABLE_SHIFT,
-};
-
-static const struct clksel auxclk4_sel[] = {
-	{ .parent = &auxclk4_src_ck, .rates = div16_1to16_rates },
-	{ .parent = NULL },
-};
-
-static struct clk auxclk4_ck = {
-	.name		= "auxclk4_ck",
-	.parent		= &auxclk4_src_ck,
-	.clksel		= auxclk4_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLK4,
-	.clksel_mask	= OMAP4_CLKDIV_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static struct clk auxclk5_src_ck = {
-	.name		= "auxclk5_src_ck",
-	.parent		= &sys_clkin_ck,
-	.init		= &omap2_init_clksel_parent,
-	.ops		= &clkops_omap2_dflt,
-	.clksel		= auxclk_src_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLK5,
-	.clksel_mask	= OMAP4_SRCSELECT_MASK,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4_SCRM_AUXCLK5,
-	.enable_bit	= OMAP4_ENABLE_SHIFT,
-};
-
-static const struct clksel auxclk5_sel[] = {
-	{ .parent = &auxclk5_src_ck, .rates = div16_1to16_rates },
-	{ .parent = NULL },
-};
-
-static struct clk auxclk5_ck = {
-	.name		= "auxclk5_ck",
-	.parent		= &auxclk5_src_ck,
-	.clksel		= auxclk5_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLK5,
-	.clksel_mask	= OMAP4_CLKDIV_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel auxclkreq_sel[] = {
-	{ .parent = &auxclk0_ck, .rates = div_1_0_rates },
-	{ .parent = &auxclk1_ck, .rates = div_1_1_rates },
-	{ .parent = &auxclk2_ck, .rates = div_1_2_rates },
-	{ .parent = &auxclk3_ck, .rates = div_1_3_rates },
-	{ .parent = &auxclk4_ck, .rates = div_1_4_rates },
-	{ .parent = &auxclk5_ck, .rates = div_1_5_rates },
-	{ .parent = NULL },
-};
-
-static struct clk auxclkreq0_ck = {
-	.name		= "auxclkreq0_ck",
-	.parent		= &auxclk0_ck,
-	.init		= &omap2_init_clksel_parent,
-	.ops		= &clkops_null,
-	.clksel         = auxclkreq_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLKREQ0,
-	.clksel_mask	= OMAP4_MAPPING_MASK,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk auxclkreq1_ck = {
-	.name		= "auxclkreq1_ck",
-	.parent		= &auxclk1_ck,
-	.init		= &omap2_init_clksel_parent,
-	.ops		= &clkops_null,
-	.clksel         = auxclkreq_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLKREQ1,
-	.clksel_mask	= OMAP4_MAPPING_MASK,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk auxclkreq2_ck = {
-	.name		= "auxclkreq2_ck",
-	.parent		= &auxclk2_ck,
-	.init		= &omap2_init_clksel_parent,
-	.ops		= &clkops_null,
-	.clksel         = auxclkreq_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLKREQ2,
-	.clksel_mask	= OMAP4_MAPPING_MASK,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk auxclkreq3_ck = {
-	.name		= "auxclkreq3_ck",
-	.parent		= &auxclk3_ck,
-	.init		= &omap2_init_clksel_parent,
-	.ops		= &clkops_null,
-	.clksel         = auxclkreq_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLKREQ3,
-	.clksel_mask	= OMAP4_MAPPING_MASK,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk auxclkreq4_ck = {
-	.name		= "auxclkreq4_ck",
-	.parent		= &auxclk4_ck,
-	.init		= &omap2_init_clksel_parent,
-	.ops		= &clkops_null,
-	.clksel         = auxclkreq_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLKREQ4,
-	.clksel_mask	= OMAP4_MAPPING_MASK,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk auxclkreq5_ck = {
-	.name		= "auxclkreq5_ck",
-	.parent		= &auxclk5_ck,
-	.init		= &omap2_init_clksel_parent,
-	.ops		= &clkops_null,
-	.clksel         = auxclkreq_sel,
-	.clksel_reg	= OMAP4_SCRM_AUXCLKREQ5,
-	.clksel_mask	= OMAP4_MAPPING_MASK,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/*
- * clkdev
- */
-
-static struct omap_clk omap44xx_clks[] = {
-	CLK(NULL,	"extalt_clkin_ck",		&extalt_clkin_ck,	CK_443X),
-	CLK(NULL,	"pad_clks_ck",			&pad_clks_ck,	CK_443X),
-	CLK(NULL,	"pad_slimbus_core_clks_ck",	&pad_slimbus_core_clks_ck,	CK_443X),
-	CLK(NULL,	"secure_32k_clk_src_ck",	&secure_32k_clk_src_ck,	CK_443X),
-	CLK(NULL,	"slimbus_clk",			&slimbus_clk,	CK_443X),
-	CLK(NULL,	"sys_32k_ck",			&sys_32k_ck,	CK_443X),
-	CLK(NULL,	"virt_12000000_ck",		&virt_12000000_ck,	CK_443X),
-	CLK(NULL,	"virt_13000000_ck",		&virt_13000000_ck,	CK_443X),
-	CLK(NULL,	"virt_16800000_ck",		&virt_16800000_ck,	CK_443X),
-	CLK(NULL,	"virt_19200000_ck",		&virt_19200000_ck,	CK_443X),
-	CLK(NULL,	"virt_26000000_ck",		&virt_26000000_ck,	CK_443X),
-	CLK(NULL,	"virt_27000000_ck",		&virt_27000000_ck,	CK_443X),
-	CLK(NULL,	"virt_38400000_ck",		&virt_38400000_ck,	CK_443X),
-	CLK(NULL,	"sys_clkin_ck",			&sys_clkin_ck,	CK_443X),
-	CLK(NULL,	"tie_low_clock_ck",		&tie_low_clock_ck,	CK_443X),
-	CLK(NULL,	"utmi_phy_clkout_ck",		&utmi_phy_clkout_ck,	CK_443X),
-	CLK(NULL,	"xclk60mhsp1_ck",		&xclk60mhsp1_ck,	CK_443X),
-	CLK(NULL,	"xclk60mhsp2_ck",		&xclk60mhsp2_ck,	CK_443X),
-	CLK(NULL,	"xclk60motg_ck",		&xclk60motg_ck,	CK_443X),
-	CLK(NULL,	"abe_dpll_bypass_clk_mux_ck",	&abe_dpll_bypass_clk_mux_ck,	CK_443X),
-	CLK(NULL,	"abe_dpll_refclk_mux_ck",	&abe_dpll_refclk_mux_ck,	CK_443X),
-	CLK(NULL,	"dpll_abe_ck",			&dpll_abe_ck,	CK_443X),
-	CLK(NULL,	"dpll_abe_x2_ck",		&dpll_abe_x2_ck,	CK_443X),
-	CLK(NULL,	"dpll_abe_m2x2_ck",		&dpll_abe_m2x2_ck,	CK_443X),
-	CLK(NULL,	"abe_24m_fclk",			&abe_24m_fclk,	CK_443X),
-	CLK(NULL,	"abe_clk",			&abe_clk,	CK_443X),
-	CLK(NULL,	"aess_fclk",			&aess_fclk,	CK_443X),
-	CLK(NULL,	"dpll_abe_m3x2_ck",		&dpll_abe_m3x2_ck,	CK_443X),
-	CLK(NULL,	"core_hsd_byp_clk_mux_ck",	&core_hsd_byp_clk_mux_ck,	CK_443X),
-	CLK(NULL,	"dpll_core_ck",			&dpll_core_ck,	CK_443X),
-	CLK(NULL,	"dpll_core_x2_ck",		&dpll_core_x2_ck,	CK_443X),
-	CLK(NULL,	"dpll_core_m6x2_ck",		&dpll_core_m6x2_ck,	CK_443X),
-	CLK(NULL,	"dbgclk_mux_ck",		&dbgclk_mux_ck,	CK_443X),
-	CLK(NULL,	"dpll_core_m2_ck",		&dpll_core_m2_ck,	CK_443X),
-	CLK(NULL,	"ddrphy_ck",			&ddrphy_ck,	CK_443X),
-	CLK(NULL,	"dpll_core_m5x2_ck",		&dpll_core_m5x2_ck,	CK_443X),
-	CLK(NULL,	"div_core_ck",			&div_core_ck,	CK_443X),
-	CLK(NULL,	"div_iva_hs_clk",		&div_iva_hs_clk,	CK_443X),
-	CLK(NULL,	"div_mpu_hs_clk",		&div_mpu_hs_clk,	CK_443X),
-	CLK(NULL,	"dpll_core_m4x2_ck",		&dpll_core_m4x2_ck,	CK_443X),
-	CLK(NULL,	"dll_clk_div_ck",		&dll_clk_div_ck,	CK_443X),
-	CLK(NULL,	"dpll_abe_m2_ck",		&dpll_abe_m2_ck,	CK_443X),
-	CLK(NULL,	"dpll_core_m3x2_ck",		&dpll_core_m3x2_ck,	CK_443X),
-	CLK(NULL,	"dpll_core_m7x2_ck",		&dpll_core_m7x2_ck,	CK_443X),
-	CLK(NULL,	"iva_hsd_byp_clk_mux_ck",	&iva_hsd_byp_clk_mux_ck,	CK_443X),
-	CLK(NULL,	"dpll_iva_ck",			&dpll_iva_ck,	CK_443X),
-	CLK(NULL,	"dpll_iva_x2_ck",		&dpll_iva_x2_ck,	CK_443X),
-	CLK(NULL,	"dpll_iva_m4x2_ck",		&dpll_iva_m4x2_ck,	CK_443X),
-	CLK(NULL,	"dpll_iva_m5x2_ck",		&dpll_iva_m5x2_ck,	CK_443X),
-	CLK(NULL,	"dpll_mpu_ck",			&dpll_mpu_ck,	CK_443X),
-	CLK(NULL,	"dpll_mpu_m2_ck",		&dpll_mpu_m2_ck,	CK_443X),
-	CLK(NULL,	"per_hs_clk_div_ck",		&per_hs_clk_div_ck,	CK_443X),
-	CLK(NULL,	"per_hsd_byp_clk_mux_ck",	&per_hsd_byp_clk_mux_ck,	CK_443X),
-	CLK(NULL,	"dpll_per_ck",			&dpll_per_ck,	CK_443X),
-	CLK(NULL,	"dpll_per_m2_ck",		&dpll_per_m2_ck,	CK_443X),
-	CLK(NULL,	"dpll_per_x2_ck",		&dpll_per_x2_ck,	CK_443X),
-	CLK(NULL,	"dpll_per_m2x2_ck",		&dpll_per_m2x2_ck,	CK_443X),
-	CLK(NULL,	"dpll_per_m3x2_ck",		&dpll_per_m3x2_ck,	CK_443X),
-	CLK(NULL,	"dpll_per_m4x2_ck",		&dpll_per_m4x2_ck,	CK_443X),
-	CLK(NULL,	"dpll_per_m5x2_ck",		&dpll_per_m5x2_ck,	CK_443X),
-	CLK(NULL,	"dpll_per_m6x2_ck",		&dpll_per_m6x2_ck,	CK_443X),
-	CLK(NULL,	"dpll_per_m7x2_ck",		&dpll_per_m7x2_ck,	CK_443X),
-	CLK(NULL,	"usb_hs_clk_div_ck",		&usb_hs_clk_div_ck,	CK_443X),
-	CLK(NULL,	"dpll_usb_ck",			&dpll_usb_ck,	CK_443X),
-	CLK(NULL,	"dpll_usb_clkdcoldo_ck",	&dpll_usb_clkdcoldo_ck,	CK_443X),
-	CLK(NULL,	"dpll_usb_m2_ck",		&dpll_usb_m2_ck,	CK_443X),
-	CLK(NULL,	"ducati_clk_mux_ck",		&ducati_clk_mux_ck,	CK_443X),
-	CLK(NULL,	"func_12m_fclk",		&func_12m_fclk,	CK_443X),
-	CLK(NULL,	"func_24m_clk",			&func_24m_clk,	CK_443X),
-	CLK(NULL,	"func_24mc_fclk",		&func_24mc_fclk,	CK_443X),
-	CLK(NULL,	"func_48m_fclk",		&func_48m_fclk,	CK_443X),
-	CLK(NULL,	"func_48mc_fclk",		&func_48mc_fclk,	CK_443X),
-	CLK(NULL,	"func_64m_fclk",		&func_64m_fclk,	CK_443X),
-	CLK(NULL,	"func_96m_fclk",		&func_96m_fclk,	CK_443X),
-	CLK(NULL,	"init_60m_fclk",		&init_60m_fclk,	CK_443X),
-	CLK(NULL,	"l3_div_ck",			&l3_div_ck,	CK_443X),
-	CLK(NULL,	"l4_div_ck",			&l4_div_ck,	CK_443X),
-	CLK(NULL,	"lp_clk_div_ck",		&lp_clk_div_ck,	CK_443X),
-	CLK(NULL,	"l4_wkup_clk_mux_ck",		&l4_wkup_clk_mux_ck,	CK_443X),
-	CLK("smp_twd",	NULL,				&mpu_periphclk,	CK_443X),
-	CLK(NULL,	"ocp_abe_iclk",			&ocp_abe_iclk,	CK_443X),
-	CLK(NULL,	"per_abe_24m_fclk",		&per_abe_24m_fclk,	CK_443X),
-	CLK(NULL,	"per_abe_nc_fclk",		&per_abe_nc_fclk,	CK_443X),
-	CLK(NULL,	"pmd_stm_clock_mux_ck",		&pmd_stm_clock_mux_ck,	CK_443X),
-	CLK(NULL,	"pmd_trace_clk_mux_ck",		&pmd_trace_clk_mux_ck,	CK_443X),
-	CLK(NULL,	"syc_clk_div_ck",		&syc_clk_div_ck,	CK_443X),
-	CLK(NULL,	"aes1_fck",			&aes1_fck,	CK_443X),
-	CLK(NULL,	"aes2_fck",			&aes2_fck,	CK_443X),
-	CLK(NULL,	"aess_fck",			&aess_fck,	CK_443X),
-	CLK(NULL,	"bandgap_fclk",			&bandgap_fclk,	CK_443X),
-	CLK(NULL,	"bandgap_ts_fclk",		&bandgap_ts_fclk,	CK_446X),
-	CLK(NULL,	"des3des_fck",			&des3des_fck,	CK_443X),
-	CLK(NULL,	"div_ts_ck",			&div_ts_ck,	CK_446X),
-	CLK(NULL,	"dmic_sync_mux_ck",		&dmic_sync_mux_ck,	CK_443X),
-	CLK(NULL,	"dmic_fck",			&dmic_fck,	CK_443X),
-	CLK(NULL,	"dsp_fck",			&dsp_fck,	CK_443X),
-	CLK(NULL,	"dss_sys_clk",			&dss_sys_clk,	CK_443X),
-	CLK(NULL,	"dss_tv_clk",			&dss_tv_clk,	CK_443X),
-	CLK(NULL,	"dss_48mhz_clk",		&dss_48mhz_clk,	CK_443X),
-	CLK(NULL,	"dss_dss_clk",			&dss_dss_clk,	CK_443X),
-	CLK(NULL,	"dss_fck",			&dss_fck,	CK_443X),
-	CLK("omapdss_dss",	"ick",				&dss_fck,	CK_443X),
-	CLK(NULL,	"efuse_ctrl_cust_fck",		&efuse_ctrl_cust_fck,	CK_443X),
-	CLK(NULL,	"emif1_fck",			&emif1_fck,	CK_443X),
-	CLK(NULL,	"emif2_fck",			&emif2_fck,	CK_443X),
-	CLK(NULL,	"fdif_fck",			&fdif_fck,	CK_443X),
-	CLK(NULL,	"fpka_fck",			&fpka_fck,	CK_443X),
-	CLK(NULL,	"gpio1_dbclk",			&gpio1_dbclk,	CK_443X),
-	CLK(NULL,	"gpio1_ick",			&gpio1_ick,	CK_443X),
-	CLK(NULL,	"gpio2_dbclk",			&gpio2_dbclk,	CK_443X),
-	CLK(NULL,	"gpio2_ick",			&gpio2_ick,	CK_443X),
-	CLK(NULL,	"gpio3_dbclk",			&gpio3_dbclk,	CK_443X),
-	CLK(NULL,	"gpio3_ick",			&gpio3_ick,	CK_443X),
-	CLK(NULL,	"gpio4_dbclk",			&gpio4_dbclk,	CK_443X),
-	CLK(NULL,	"gpio4_ick",			&gpio4_ick,	CK_443X),
-	CLK(NULL,	"gpio5_dbclk",			&gpio5_dbclk,	CK_443X),
-	CLK(NULL,	"gpio5_ick",			&gpio5_ick,	CK_443X),
-	CLK(NULL,	"gpio6_dbclk",			&gpio6_dbclk,	CK_443X),
-	CLK(NULL,	"gpio6_ick",			&gpio6_ick,	CK_443X),
-	CLK(NULL,	"gpmc_ick",			&gpmc_ick,	CK_443X),
-	CLK(NULL,	"gpu_fck",			&gpu_fck,	CK_443X),
-	CLK(NULL,	"hdq1w_fck",			&hdq1w_fck,	CK_443X),
-	CLK(NULL,	"hsi_fck",			&hsi_fck,	CK_443X),
-	CLK(NULL,	"i2c1_fck",			&i2c1_fck,	CK_443X),
-	CLK(NULL,	"i2c2_fck",			&i2c2_fck,	CK_443X),
-	CLK(NULL,	"i2c3_fck",			&i2c3_fck,	CK_443X),
-	CLK(NULL,	"i2c4_fck",			&i2c4_fck,	CK_443X),
-	CLK(NULL,	"ipu_fck",			&ipu_fck,	CK_443X),
-	CLK(NULL,	"iss_ctrlclk",			&iss_ctrlclk,	CK_443X),
-	CLK(NULL,	"iss_fck",			&iss_fck,	CK_443X),
-	CLK(NULL,	"iva_fck",			&iva_fck,	CK_443X),
-	CLK(NULL,	"kbd_fck",			&kbd_fck,	CK_443X),
-	CLK(NULL,	"l3_instr_ick",			&l3_instr_ick,	CK_443X),
-	CLK(NULL,	"l3_main_3_ick",		&l3_main_3_ick,	CK_443X),
-	CLK(NULL,	"mcasp_sync_mux_ck",		&mcasp_sync_mux_ck,	CK_443X),
-	CLK(NULL,	"mcasp_fck",			&mcasp_fck,	CK_443X),
-	CLK(NULL,	"mcbsp1_sync_mux_ck",		&mcbsp1_sync_mux_ck,	CK_443X),
-	CLK(NULL,	"mcbsp1_fck",			&mcbsp1_fck,	CK_443X),
-	CLK(NULL,	"mcbsp2_sync_mux_ck",		&mcbsp2_sync_mux_ck,	CK_443X),
-	CLK(NULL,	"mcbsp2_fck",			&mcbsp2_fck,	CK_443X),
-	CLK(NULL,	"mcbsp3_sync_mux_ck",		&mcbsp3_sync_mux_ck,	CK_443X),
-	CLK(NULL,	"mcbsp3_fck",			&mcbsp3_fck,	CK_443X),
-	CLK(NULL,	"mcbsp4_sync_mux_ck",		&mcbsp4_sync_mux_ck,	CK_443X),
-	CLK(NULL,	"mcbsp4_fck",			&mcbsp4_fck,	CK_443X),
-	CLK(NULL,	"mcpdm_fck",			&mcpdm_fck,	CK_443X),
-	CLK(NULL,	"mcspi1_fck",			&mcspi1_fck,	CK_443X),
-	CLK(NULL,	"mcspi2_fck",			&mcspi2_fck,	CK_443X),
-	CLK(NULL,	"mcspi3_fck",			&mcspi3_fck,	CK_443X),
-	CLK(NULL,	"mcspi4_fck",			&mcspi4_fck,	CK_443X),
-	CLK(NULL,	"mmc1_fck",			&mmc1_fck,	CK_443X),
-	CLK(NULL,	"mmc2_fck",			&mmc2_fck,	CK_443X),
-	CLK(NULL,	"mmc3_fck",			&mmc3_fck,	CK_443X),
-	CLK(NULL,	"mmc4_fck",			&mmc4_fck,	CK_443X),
-	CLK(NULL,	"mmc5_fck",			&mmc5_fck,	CK_443X),
-	CLK(NULL,	"ocp2scp_usb_phy_phy_48m",	&ocp2scp_usb_phy_phy_48m,	CK_443X),
-	CLK(NULL,	"ocp2scp_usb_phy_ick",		&ocp2scp_usb_phy_ick,	CK_443X),
-	CLK(NULL,	"ocp_wp_noc_ick",		&ocp_wp_noc_ick,	CK_443X),
-	CLK(NULL,	"rng_ick",			&rng_ick,	CK_443X),
-	CLK("omap_rng",	"ick",				&rng_ick,	CK_443X),
-	CLK(NULL,	"sha2md5_fck",			&sha2md5_fck,	CK_443X),
-	CLK(NULL,	"sl2if_ick",			&sl2if_ick,	CK_443X),
-	CLK(NULL,	"slimbus1_fclk_1",		&slimbus1_fclk_1,	CK_443X),
-	CLK(NULL,	"slimbus1_fclk_0",		&slimbus1_fclk_0,	CK_443X),
-	CLK(NULL,	"slimbus1_fclk_2",		&slimbus1_fclk_2,	CK_443X),
-	CLK(NULL,	"slimbus1_slimbus_clk",		&slimbus1_slimbus_clk,	CK_443X),
-	CLK(NULL,	"slimbus1_fck",			&slimbus1_fck,	CK_443X),
-	CLK(NULL,	"slimbus2_fclk_1",		&slimbus2_fclk_1,	CK_443X),
-	CLK(NULL,	"slimbus2_fclk_0",		&slimbus2_fclk_0,	CK_443X),
-	CLK(NULL,	"slimbus2_slimbus_clk",		&slimbus2_slimbus_clk,	CK_443X),
-	CLK(NULL,	"slimbus2_fck",			&slimbus2_fck,	CK_443X),
-	CLK(NULL,	"smartreflex_core_fck",		&smartreflex_core_fck,	CK_443X),
-	CLK(NULL,	"smartreflex_iva_fck",		&smartreflex_iva_fck,	CK_443X),
-	CLK(NULL,	"smartreflex_mpu_fck",		&smartreflex_mpu_fck,	CK_443X),
-	CLK(NULL,	"timer1_fck",			&timer1_fck,	CK_443X),
-	CLK(NULL,	"timer10_fck",			&timer10_fck,	CK_443X),
-	CLK(NULL,	"timer11_fck",			&timer11_fck,	CK_443X),
-	CLK(NULL,	"timer2_fck",			&timer2_fck,	CK_443X),
-	CLK(NULL,	"timer3_fck",			&timer3_fck,	CK_443X),
-	CLK(NULL,	"timer4_fck",			&timer4_fck,	CK_443X),
-	CLK(NULL,	"timer5_fck",			&timer5_fck,	CK_443X),
-	CLK(NULL,	"timer6_fck",			&timer6_fck,	CK_443X),
-	CLK(NULL,	"timer7_fck",			&timer7_fck,	CK_443X),
-	CLK(NULL,	"timer8_fck",			&timer8_fck,	CK_443X),
-	CLK(NULL,	"timer9_fck",			&timer9_fck,	CK_443X),
-	CLK(NULL,	"uart1_fck",			&uart1_fck,	CK_443X),
-	CLK(NULL,	"uart2_fck",			&uart2_fck,	CK_443X),
-	CLK(NULL,	"uart3_fck",			&uart3_fck,	CK_443X),
-	CLK(NULL,	"uart4_fck",			&uart4_fck,	CK_443X),
-	CLK("usbhs_omap",	"fs_fck",		&usb_host_fs_fck,	CK_443X),
-	CLK(NULL,	"usb_host_fs_fck",		&usb_host_fs_fck,	CK_443X),
-	CLK(NULL,	"utmi_p1_gfclk",		&utmi_p1_gfclk,	CK_443X),
-	CLK(NULL,	"usb_host_hs_utmi_p1_clk",	&usb_host_hs_utmi_p1_clk,	CK_443X),
-	CLK(NULL,	"utmi_p2_gfclk",		&utmi_p2_gfclk,	CK_443X),
-	CLK(NULL,	"usb_host_hs_utmi_p2_clk",	&usb_host_hs_utmi_p2_clk,	CK_443X),
-	CLK(NULL,	"usb_host_hs_utmi_p3_clk",	&usb_host_hs_utmi_p3_clk,	CK_443X),
-	CLK(NULL,	"usb_host_hs_hsic480m_p1_clk",	&usb_host_hs_hsic480m_p1_clk,	CK_443X),
-	CLK(NULL,	"usb_host_hs_hsic60m_p1_clk",	&usb_host_hs_hsic60m_p1_clk,	CK_443X),
-	CLK(NULL,	"usb_host_hs_hsic60m_p2_clk",	&usb_host_hs_hsic60m_p2_clk,	CK_443X),
-	CLK(NULL,	"usb_host_hs_hsic480m_p2_clk",	&usb_host_hs_hsic480m_p2_clk,	CK_443X),
-	CLK(NULL,	"usb_host_hs_func48mclk",	&usb_host_hs_func48mclk,	CK_443X),
-	CLK(NULL,	"usb_host_hs_fck",		&usb_host_hs_fck,	CK_443X),
-	CLK("usbhs_omap",	"hs_fck",		&usb_host_hs_fck,	CK_443X),
-	CLK(NULL,	"otg_60m_gfclk",		&otg_60m_gfclk,	CK_443X),
-	CLK(NULL,	"usb_otg_hs_xclk",		&usb_otg_hs_xclk,	CK_443X),
-	CLK(NULL,	"usb_otg_hs_ick",		&usb_otg_hs_ick,	CK_443X),
-	CLK("musb-omap2430",	"ick",				&usb_otg_hs_ick,	CK_443X),
-	CLK(NULL,	"usb_phy_cm_clk32k",		&usb_phy_cm_clk32k,	CK_443X),
-	CLK(NULL,	"usb_tll_hs_usb_ch2_clk",	&usb_tll_hs_usb_ch2_clk,	CK_443X),
-	CLK(NULL,	"usb_tll_hs_usb_ch0_clk",	&usb_tll_hs_usb_ch0_clk,	CK_443X),
-	CLK(NULL,	"usb_tll_hs_usb_ch1_clk",	&usb_tll_hs_usb_ch1_clk,	CK_443X),
-	CLK(NULL,	"usb_tll_hs_ick",		&usb_tll_hs_ick,	CK_443X),
-	CLK("usbhs_omap",	"usbtll_ick",		&usb_tll_hs_ick,	CK_443X),
-	CLK("usbhs_tll",	"usbtll_ick",		&usb_tll_hs_ick,	CK_443X),
-	CLK(NULL,	"usim_ck",			&usim_ck,	CK_443X),
-	CLK(NULL,	"usim_fclk",			&usim_fclk,	CK_443X),
-	CLK(NULL,	"usim_fck",			&usim_fck,	CK_443X),
-	CLK(NULL,	"wd_timer2_fck",		&wd_timer2_fck,	CK_443X),
-	CLK(NULL,	"wd_timer3_fck",		&wd_timer3_fck,	CK_443X),
-	CLK(NULL,	"stm_clk_div_ck",		&stm_clk_div_ck,	CK_443X),
-	CLK(NULL,	"trace_clk_div_ck",		&trace_clk_div_ck,	CK_443X),
-	CLK(NULL,	"auxclk0_src_ck",		&auxclk0_src_ck,	CK_443X),
-	CLK(NULL,	"auxclk0_ck",			&auxclk0_ck,	CK_443X),
-	CLK(NULL,	"auxclkreq0_ck",		&auxclkreq0_ck,	CK_443X),
-	CLK(NULL,	"auxclk1_src_ck",		&auxclk1_src_ck,	CK_443X),
-	CLK(NULL,	"auxclk1_ck",			&auxclk1_ck,	CK_443X),
-	CLK(NULL,	"auxclkreq1_ck",		&auxclkreq1_ck,	CK_443X),
-	CLK(NULL,	"auxclk2_src_ck",		&auxclk2_src_ck,	CK_443X),
-	CLK(NULL,	"auxclk2_ck",			&auxclk2_ck,	CK_443X),
-	CLK(NULL,	"auxclkreq2_ck",		&auxclkreq2_ck,	CK_443X),
-	CLK(NULL,	"auxclk3_src_ck",		&auxclk3_src_ck,	CK_443X),
-	CLK(NULL,	"auxclk3_ck",			&auxclk3_ck,	CK_443X),
-	CLK(NULL,	"auxclkreq3_ck",		&auxclkreq3_ck,	CK_443X),
-	CLK(NULL,	"auxclk4_src_ck",		&auxclk4_src_ck,	CK_443X),
-	CLK(NULL,	"auxclk4_ck",			&auxclk4_ck,	CK_443X),
-	CLK(NULL,	"auxclkreq4_ck",		&auxclkreq4_ck,	CK_443X),
-	CLK(NULL,	"auxclk5_src_ck",		&auxclk5_src_ck,	CK_443X),
-	CLK(NULL,	"auxclk5_ck",			&auxclk5_ck,	CK_443X),
-	CLK(NULL,	"auxclkreq5_ck",		&auxclkreq5_ck,	CK_443X),
-	CLK("omap-gpmc",	"fck",				&dummy_ck,	CK_443X),
-	CLK("omap_i2c.1",	"ick",				&dummy_ck,	CK_443X),
-	CLK("omap_i2c.2",	"ick",				&dummy_ck,	CK_443X),
-	CLK("omap_i2c.3",	"ick",				&dummy_ck,	CK_443X),
-	CLK("omap_i2c.4",	"ick",				&dummy_ck,	CK_443X),
-	CLK(NULL,	"mailboxes_ick",		&dummy_ck,	CK_443X),
-	CLK("omap_hsmmc.0",	"ick",				&dummy_ck,	CK_443X),
-	CLK("omap_hsmmc.1",	"ick",				&dummy_ck,	CK_443X),
-	CLK("omap_hsmmc.2",	"ick",				&dummy_ck,	CK_443X),
-	CLK("omap_hsmmc.3",	"ick",				&dummy_ck,	CK_443X),
-	CLK("omap_hsmmc.4",	"ick",				&dummy_ck,	CK_443X),
-	CLK("omap-mcbsp.1",	"ick",				&dummy_ck,	CK_443X),
-	CLK("omap-mcbsp.2",	"ick",				&dummy_ck,	CK_443X),
-	CLK("omap-mcbsp.3",	"ick",				&dummy_ck,	CK_443X),
-	CLK("omap-mcbsp.4",	"ick",				&dummy_ck,	CK_443X),
-	CLK("omap2_mcspi.1",	"ick",				&dummy_ck,	CK_443X),
-	CLK("omap2_mcspi.2",	"ick",				&dummy_ck,	CK_443X),
-	CLK("omap2_mcspi.3",	"ick",				&dummy_ck,	CK_443X),
-	CLK("omap2_mcspi.4",	"ick",				&dummy_ck,	CK_443X),
-	CLK(NULL,	"uart1_ick",			&dummy_ck,	CK_443X),
-	CLK(NULL,	"uart2_ick",			&dummy_ck,	CK_443X),
-	CLK(NULL,	"uart3_ick",			&dummy_ck,	CK_443X),
-	CLK(NULL,	"uart4_ick",			&dummy_ck,	CK_443X),
-	CLK("usbhs_omap",	"usbhost_ick",		&dummy_ck,		CK_443X),
-	CLK("usbhs_omap",	"usbtll_fck",		&dummy_ck,	CK_443X),
-	CLK("usbhs_tll",	"usbtll_fck",		&dummy_ck,	CK_443X),
-	CLK("omap_wdt",	"ick",				&dummy_ck,	CK_443X),
-	CLK(NULL,	"timer_32k_ck",	&sys_32k_ck,	CK_443X),
-	/* TODO: Remove "omap_timer.X" aliases once DT migration is complete */
-	CLK("omap_timer.1",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
-	CLK("omap_timer.2",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
-	CLK("omap_timer.3",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
-	CLK("omap_timer.4",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
-	CLK("omap_timer.9",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
-	CLK("omap_timer.10",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
-	CLK("omap_timer.11",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
-	CLK("omap_timer.5",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
-	CLK("omap_timer.6",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
-	CLK("omap_timer.7",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
-	CLK("omap_timer.8",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
-	CLK("4a318000.timer",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
-	CLK("48032000.timer",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
-	CLK("48034000.timer",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
-	CLK("48036000.timer",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
-	CLK("4803e000.timer",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
-	CLK("48086000.timer",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
-	CLK("48088000.timer",	"timer_sys_ck",	&sys_clkin_ck,	CK_443X),
-	CLK("49038000.timer",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
-	CLK("4903a000.timer",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
-	CLK("4903c000.timer",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
-	CLK("4903e000.timer",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
-	CLK(NULL,	"cpufreq_ck",	&dpll_mpu_ck,	CK_443X),
-};
-
-int __init omap4xxx_clk_init(void)
-{
-	struct omap_clk *c;
-	u32 cpu_clkflg;
-
-	if (cpu_is_omap443x()) {
-		cpu_mask = RATE_IN_4430;
-		cpu_clkflg = CK_443X;
-	} else if (cpu_is_omap446x() || cpu_is_omap447x()) {
-		cpu_mask = RATE_IN_4460 | RATE_IN_4430;
-		cpu_clkflg = CK_446X | CK_443X;
-
-		if (cpu_is_omap447x())
-			pr_warn("WARNING: OMAP4470 clock data incomplete!\n");
-	} else {
-		return 0;
-	}
-
-	clk_init(&omap2_clk_functions);
-
-	/*
-	 * Must stay commented until all OMAP SoC drivers are
-	 * converted to runtime PM, or drivers may start crashing
-	 *
-	 * omap2_clk_disable_clkdm_control();
-	 */
-
-	for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks);
-									  c++)
-		clk_preinit(c->lk.clk);
-
-	for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks);
-									  c++)
-		if (c->cpu & cpu_clkflg) {
-			clkdev_add(&c->lk);
-			clk_register(c->lk.clk);
-			omap2_init_clk_clkdm(c->lk.clk);
-		}
-
-	/* Disable autoidle on all clocks; let the PM code enable it later */
-	omap_clk_disable_autoidle_all();
-
-	recalculate_root_clocks();
-
-	/*
-	 * Only enable those clocks we will need, let the drivers
-	 * enable other clocks as necessary
-	 */
-	clk_enable_init_clocks();
-
-	return 0;
-}
diff --git a/arch/arm/mach-omap2/clock_common_data.c b/arch/arm/mach-omap2/clock_common_data.c
index b9f3ba6..ef4d21b 100644
--- a/arch/arm/mach-omap2/clock_common_data.c
+++ b/arch/arm/mach-omap2/clock_common_data.c
@@ -16,6 +16,7 @@
  * OMAP3xxx clock definition files.
  */
 
+#include <linux/clk-private.h>
 #include "clock.h"
 
 /* clksel_rate data common to 24xx/343x */
@@ -52,6 +53,13 @@ const struct clksel_rate div_1_0_rates[] = {
 	{ .div = 0 },
 };
 
+const struct clksel_rate div3_1to4_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_4430 },
+	{ .div = 2, .val = 1, .flags = RATE_IN_4430 },
+	{ .div = 4, .val = 2, .flags = RATE_IN_4430 },
+	{ .div = 0 },
+};
+
 const struct clksel_rate div_1_1_rates[] = {
 	{ .div = 1, .val = 1, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
 	{ .div = 0 },
@@ -109,14 +117,10 @@ const struct clksel_rate div31_1to31_rates[] = {
 
 /* Clocks shared between various OMAP SoCs */
 
-struct clk virt_19200000_ck = {
-	.name		= "virt_19200000_ck",
-	.ops		= &clkops_null,
-	.rate		= 19200000,
-};
+static struct clk_ops dummy_ck_ops = {};
 
-struct clk virt_26000000_ck = {
-	.name		= "virt_26000000_ck",
-	.ops		= &clkops_null,
-	.rate		= 26000000,
+struct clk dummy_ck = {
+	.name = "dummy_clk",
+	.ops = &dummy_ck_ops,
+	.flags = CLK_IS_BASIC,
 };
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 512e79a..3848735 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -22,12 +22,14 @@
 #include <linux/clk.h>
 #include <linux/limits.h>
 #include <linux/err.h>
+#include <linux/clk-provider.h>
 
 #include <linux/io.h>
 
 #include <linux/bitops.h>
 
-#include <plat/clock.h>
+#include "soc.h"
+#include "clock.h"
 #include "clockdomain.h"
 
 /* clkdm_list contains all registered struct clockdomains */
@@ -946,35 +948,6 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
 	return 0;
 }
 
-static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
-{
-	unsigned long flags;
-
-	if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
-		return -EINVAL;
-
-	spin_lock_irqsave(&clkdm->lock, flags);
-
-	if (atomic_read(&clkdm->usecount) == 0) {
-		spin_unlock_irqrestore(&clkdm->lock, flags);
-		WARN_ON(1); /* underflow */
-		return -ERANGE;
-	}
-
-	if (atomic_dec_return(&clkdm->usecount) > 0) {
-		spin_unlock_irqrestore(&clkdm->lock, flags);
-		return 0;
-	}
-
-	arch_clkdm->clkdm_clk_disable(clkdm);
-	pwrdm_state_switch(clkdm->pwrdm.ptr);
-	spin_unlock_irqrestore(&clkdm->lock, flags);
-
-	pr_debug("clockdomain: %s: disabled\n", clkdm->name);
-
-	return 0;
-}
-
 /**
  * clkdm_clk_enable - add an enabled downstream clock to this clkdm
  * @clkdm: struct clockdomain *
@@ -1017,15 +990,37 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
  */
 int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 {
-	/*
-	 * XXX Rewrite this code to maintain a list of enabled
-	 * downstream clocks for debugging purposes?
-	 */
+	unsigned long flags;
 
-	if (!clk)
+	if (!clkdm || !clk || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
 		return -EINVAL;
 
-	return _clkdm_clk_hwmod_disable(clkdm);
+	spin_lock_irqsave(&clkdm->lock, flags);
+
+	/* corner case: disabling unused clocks */
+	if (__clk_get_enable_count(clk) == 0)
+		goto ccd_exit;
+
+	if (atomic_read(&clkdm->usecount) == 0) {
+		spin_unlock_irqrestore(&clkdm->lock, flags);
+		WARN_ON(1); /* underflow */
+		return -ERANGE;
+	}
+
+	if (atomic_dec_return(&clkdm->usecount) > 0) {
+		spin_unlock_irqrestore(&clkdm->lock, flags);
+		return 0;
+	}
+
+	arch_clkdm->clkdm_clk_disable(clkdm);
+	pwrdm_state_switch(clkdm->pwrdm.ptr);
+
+	pr_debug("clockdomain: %s: disabled\n", clkdm->name);
+
+ccd_exit:
+	spin_unlock_irqrestore(&clkdm->lock, flags);
+
+	return 0;
 }
 
 /**
@@ -1076,6 +1071,8 @@ int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh)
  */
 int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
 {
+	unsigned long flags;
+
 	/* The clkdm attribute does not exist yet prior OMAP4 */
 	if (cpu_is_omap24xx() || cpu_is_omap34xx())
 		return 0;
@@ -1085,9 +1082,28 @@ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
 	 * downstream hwmods for debugging purposes?
 	 */
 
-	if (!oh)
+	if (!clkdm || !oh || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
 		return -EINVAL;
 
-	return _clkdm_clk_hwmod_disable(clkdm);
+	spin_lock_irqsave(&clkdm->lock, flags);
+
+	if (atomic_read(&clkdm->usecount) == 0) {
+		spin_unlock_irqrestore(&clkdm->lock, flags);
+		WARN_ON(1); /* underflow */
+		return -ERANGE;
+	}
+
+	if (atomic_dec_return(&clkdm->usecount) > 0) {
+		spin_unlock_irqrestore(&clkdm->lock, flags);
+		return 0;
+	}
+
+	arch_clkdm->clkdm_clk_disable(clkdm);
+	pwrdm_state_switch(clkdm->pwrdm.ptr);
+	spin_unlock_irqrestore(&clkdm->lock, flags);
+
+	pr_debug("clockdomain: %s: disabled\n", clkdm->name);
+
+	return 0;
 }
 
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 629576b..bc42446 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -18,9 +18,8 @@
 #include <linux/spinlock.h>
 
 #include "powerdomain.h"
-#include <plat/clock.h>
-#include <plat/omap_hwmod.h>
-#include <plat/cpu.h>
+#include "clock.h"
+#include "omap_hwmod.h"
 
 /*
  * Clockdomain flags
diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
deleted file mode 100644
index 70294f5..0000000
--- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * OMAP2 and OMAP3 clockdomain control
- *
- * Copyright (C) 2008-2010 Texas Instruments, Inc.
- * Copyright (C) 2008-2010 Nokia Corporation
- *
- * Derived from mach-omap2/clockdomain.c written by Paul Walmsley
- * Rajendra Nayak <rnayak@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/types.h>
-#include <plat/prcm.h>
-#include "prm.h"
-#include "prm2xxx_3xxx.h"
-#include "cm.h"
-#include "cm2xxx_3xxx.h"
-#include "cm-regbits-24xx.h"
-#include "cm-regbits-34xx.h"
-#include "prm-regbits-24xx.h"
-#include "clockdomain.h"
-
-static int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1,
-						struct clockdomain *clkdm2)
-{
-	omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
-				clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
-	return 0;
-}
-
-static int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1,
-						 struct clockdomain *clkdm2)
-{
-	omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
-				clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
-	return 0;
-}
-
-static int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1,
-						 struct clockdomain *clkdm2)
-{
-	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
-				PM_WKDEP, (1 << clkdm2->dep_bit));
-}
-
-static int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
-{
-	struct clkdm_dep *cd;
-	u32 mask = 0;
-
-	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
-		if (!cd->clkdm)
-			continue; /* only happens if data is erroneous */
-
-		/* PRM accesses are slow, so minimize them */
-		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->wkdep_usecount, 0);
-	}
-
-	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
-				 PM_WKDEP);
-	return 0;
-}
-
-static int omap3_clkdm_add_sleepdep(struct clockdomain *clkdm1,
-						 struct clockdomain *clkdm2)
-{
-	omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
-				clkdm1->pwrdm.ptr->prcm_offs,
-				OMAP3430_CM_SLEEPDEP);
-	return 0;
-}
-
-static int omap3_clkdm_del_sleepdep(struct clockdomain *clkdm1,
-						 struct clockdomain *clkdm2)
-{
-	omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
-				clkdm1->pwrdm.ptr->prcm_offs,
-				OMAP3430_CM_SLEEPDEP);
-	return 0;
-}
-
-static int omap3_clkdm_read_sleepdep(struct clockdomain *clkdm1,
-						 struct clockdomain *clkdm2)
-{
-	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
-				OMAP3430_CM_SLEEPDEP, (1 << clkdm2->dep_bit));
-}
-
-static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
-{
-	struct clkdm_dep *cd;
-	u32 mask = 0;
-
-	for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
-		if (!cd->clkdm)
-			continue; /* only happens if data is erroneous */
-
-		/* PRM accesses are slow, so minimize them */
-		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->sleepdep_usecount, 0);
-	}
-	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
-				OMAP3430_CM_SLEEPDEP);
-	return 0;
-}
-
-static int omap2_clkdm_sleep(struct clockdomain *clkdm)
-{
-	omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
-				clkdm->pwrdm.ptr->prcm_offs,
-				OMAP2_PM_PWSTCTRL);
-	return 0;
-}
-
-static int omap2_clkdm_wakeup(struct clockdomain *clkdm)
-{
-	omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
-				clkdm->pwrdm.ptr->prcm_offs,
-				OMAP2_PM_PWSTCTRL);
-	return 0;
-}
-
-static void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
-{
-	if (atomic_read(&clkdm->usecount) > 0)
-		_clkdm_add_autodeps(clkdm);
-
-	omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-				clkdm->clktrctrl_mask);
-}
-
-static void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
-{
-	omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-				clkdm->clktrctrl_mask);
-
-	if (atomic_read(&clkdm->usecount) > 0)
-		_clkdm_del_autodeps(clkdm);
-}
-
-static void _enable_hwsup(struct clockdomain *clkdm)
-{
-	if (cpu_is_omap24xx())
-		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-					       clkdm->clktrctrl_mask);
-	else if (cpu_is_omap34xx())
-		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-					       clkdm->clktrctrl_mask);
-}
-
-static void _disable_hwsup(struct clockdomain *clkdm)
-{
-	if (cpu_is_omap24xx())
-		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						clkdm->clktrctrl_mask);
-	else if (cpu_is_omap34xx())
-		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						clkdm->clktrctrl_mask);
-}
-
-static int omap3_clkdm_sleep(struct clockdomain *clkdm)
-{
-	omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
-				clkdm->clktrctrl_mask);
-	return 0;
-}
-
-static int omap3_clkdm_wakeup(struct clockdomain *clkdm)
-{
-	omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
-				clkdm->clktrctrl_mask);
-	return 0;
-}
-
-static int omap2_clkdm_clk_enable(struct clockdomain *clkdm)
-{
-	bool hwsup = false;
-
-	if (!clkdm->clktrctrl_mask)
-		return 0;
-
-	hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-				clkdm->clktrctrl_mask);
-
-	if (hwsup) {
-		/* Disable HW transitions when we are changing deps */
-		_disable_hwsup(clkdm);
-		_clkdm_add_autodeps(clkdm);
-		_enable_hwsup(clkdm);
-	} else {
-		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
-			omap2_clkdm_wakeup(clkdm);
-	}
-
-	return 0;
-}
-
-static int omap2_clkdm_clk_disable(struct clockdomain *clkdm)
-{
-	bool hwsup = false;
-
-	if (!clkdm->clktrctrl_mask)
-		return 0;
-
-	hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-				clkdm->clktrctrl_mask);
-
-	if (hwsup) {
-		/* Disable HW transitions when we are changing deps */
-		_disable_hwsup(clkdm);
-		_clkdm_del_autodeps(clkdm);
-		_enable_hwsup(clkdm);
-	} else {
-		if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
-			omap2_clkdm_sleep(clkdm);
-	}
-
-	return 0;
-}
-
-static void omap3_clkdm_allow_idle(struct clockdomain *clkdm)
-{
-	if (atomic_read(&clkdm->usecount) > 0)
-		_clkdm_add_autodeps(clkdm);
-
-	omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-				clkdm->clktrctrl_mask);
-}
-
-static void omap3_clkdm_deny_idle(struct clockdomain *clkdm)
-{
-	omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-				clkdm->clktrctrl_mask);
-
-	if (atomic_read(&clkdm->usecount) > 0)
-		_clkdm_del_autodeps(clkdm);
-}
-
-static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm)
-{
-	bool hwsup = false;
-
-	if (!clkdm->clktrctrl_mask)
-		return 0;
-
-	/*
-	 * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
-	 * more details on the unpleasant problem this is working
-	 * around
-	 */
-	if ((clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) &&
-	    (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
-		omap3_clkdm_wakeup(clkdm);
-		return 0;
-	}
-
-	hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-				clkdm->clktrctrl_mask);
-
-	if (hwsup) {
-		/* Disable HW transitions when we are changing deps */
-		_disable_hwsup(clkdm);
-		_clkdm_add_autodeps(clkdm);
-		_enable_hwsup(clkdm);
-	} else {
-		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
-			omap3_clkdm_wakeup(clkdm);
-	}
-
-	return 0;
-}
-
-static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm)
-{
-	bool hwsup = false;
-
-	if (!clkdm->clktrctrl_mask)
-		return 0;
-
-	/*
-	 * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
-	 * more details on the unpleasant problem this is working
-	 * around
-	 */
-	if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
-	    !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
-		_enable_hwsup(clkdm);
-		return 0;
-	}
-
-	hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-				clkdm->clktrctrl_mask);
-
-	if (hwsup) {
-		/* Disable HW transitions when we are changing deps */
-		_disable_hwsup(clkdm);
-		_clkdm_del_autodeps(clkdm);
-		_enable_hwsup(clkdm);
-	} else {
-		if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
-			omap3_clkdm_sleep(clkdm);
-	}
-
-	return 0;
-}
-
-struct clkdm_ops omap2_clkdm_operations = {
-	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
-	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
-	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
-	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
-	.clkdm_sleep		= omap2_clkdm_sleep,
-	.clkdm_wakeup		= omap2_clkdm_wakeup,
-	.clkdm_allow_idle	= omap2_clkdm_allow_idle,
-	.clkdm_deny_idle	= omap2_clkdm_deny_idle,
-	.clkdm_clk_enable	= omap2_clkdm_clk_enable,
-	.clkdm_clk_disable	= omap2_clkdm_clk_disable,
-};
-
-struct clkdm_ops omap3_clkdm_operations = {
-	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
-	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
-	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
-	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
-	.clkdm_add_sleepdep	= omap3_clkdm_add_sleepdep,
-	.clkdm_del_sleepdep	= omap3_clkdm_del_sleepdep,
-	.clkdm_read_sleepdep	= omap3_clkdm_read_sleepdep,
-	.clkdm_clear_all_sleepdeps	= omap3_clkdm_clear_all_sleepdeps,
-	.clkdm_sleep		= omap3_clkdm_sleep,
-	.clkdm_wakeup		= omap3_clkdm_wakeup,
-	.clkdm_allow_idle	= omap3_clkdm_allow_idle,
-	.clkdm_deny_idle	= omap3_clkdm_deny_idle,
-	.clkdm_clk_enable	= omap3xxx_clkdm_clk_enable,
-	.clkdm_clk_disable	= omap3xxx_clkdm_clk_disable,
-};
diff --git a/arch/arm/mach-omap2/clockdomain33xx.c b/arch/arm/mach-omap2/clockdomain33xx.c
deleted file mode 100644
index aca6388..0000000
--- a/arch/arm/mach-omap2/clockdomain33xx.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * AM33XX clockdomain control
- *
- * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
- * Vaibhav Hiremath <hvaibhav@ti.com>
- *
- * Derived from mach-omap2/clockdomain44xx.c written by Rajendra Nayak
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-
-#include "clockdomain.h"
-#include "cm33xx.h"
-
-
-static int am33xx_clkdm_sleep(struct clockdomain *clkdm)
-{
-	am33xx_cm_clkdm_force_sleep(clkdm->cm_inst, clkdm->clkdm_offs);
-	return 0;
-}
-
-static int am33xx_clkdm_wakeup(struct clockdomain *clkdm)
-{
-	am33xx_cm_clkdm_force_wakeup(clkdm->cm_inst, clkdm->clkdm_offs);
-	return 0;
-}
-
-static void am33xx_clkdm_allow_idle(struct clockdomain *clkdm)
-{
-	am33xx_cm_clkdm_enable_hwsup(clkdm->cm_inst, clkdm->clkdm_offs);
-}
-
-static void am33xx_clkdm_deny_idle(struct clockdomain *clkdm)
-{
-	am33xx_cm_clkdm_disable_hwsup(clkdm->cm_inst, clkdm->clkdm_offs);
-}
-
-static int am33xx_clkdm_clk_enable(struct clockdomain *clkdm)
-{
-	if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
-		return am33xx_clkdm_wakeup(clkdm);
-
-	return 0;
-}
-
-static int am33xx_clkdm_clk_disable(struct clockdomain *clkdm)
-{
-	bool hwsup = false;
-
-	hwsup = am33xx_cm_is_clkdm_in_hwsup(clkdm->cm_inst, clkdm->clkdm_offs);
-
-	if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
-		am33xx_clkdm_sleep(clkdm);
-
-	return 0;
-}
-
-struct clkdm_ops am33xx_clkdm_operations = {
-	.clkdm_sleep		= am33xx_clkdm_sleep,
-	.clkdm_wakeup		= am33xx_clkdm_wakeup,
-	.clkdm_allow_idle	= am33xx_clkdm_allow_idle,
-	.clkdm_deny_idle	= am33xx_clkdm_deny_idle,
-	.clkdm_clk_enable	= am33xx_clkdm_clk_enable,
-	.clkdm_clk_disable	= am33xx_clkdm_clk_disable,
-};
diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c
deleted file mode 100644
index 6fc6155..0000000
--- a/arch/arm/mach-omap2/clockdomain44xx.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * OMAP4 clockdomain control
- *
- * Copyright (C) 2008-2010 Texas Instruments, Inc.
- * Copyright (C) 2008-2010 Nokia Corporation
- *
- * Derived from mach-omap2/clockdomain.c written by Paul Walmsley
- * Rajendra Nayak <rnayak@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include "clockdomain.h"
-#include "cminst44xx.h"
-#include "cm44xx.h"
-
-static int omap4_clkdm_add_wkup_sleep_dep(struct clockdomain *clkdm1,
-					struct clockdomain *clkdm2)
-{
-	omap4_cminst_set_inst_reg_bits((1 << clkdm2->dep_bit),
-					clkdm1->prcm_partition,
-					clkdm1->cm_inst, clkdm1->clkdm_offs +
-					OMAP4_CM_STATICDEP);
-	return 0;
-}
-
-static int omap4_clkdm_del_wkup_sleep_dep(struct clockdomain *clkdm1,
-					struct clockdomain *clkdm2)
-{
-	omap4_cminst_clear_inst_reg_bits((1 << clkdm2->dep_bit),
-					clkdm1->prcm_partition,
-					clkdm1->cm_inst, clkdm1->clkdm_offs +
-					OMAP4_CM_STATICDEP);
-	return 0;
-}
-
-static int omap4_clkdm_read_wkup_sleep_dep(struct clockdomain *clkdm1,
-					struct clockdomain *clkdm2)
-{
-	return omap4_cminst_read_inst_reg_bits(clkdm1->prcm_partition,
-					clkdm1->cm_inst, clkdm1->clkdm_offs +
-					OMAP4_CM_STATICDEP,
-					(1 << clkdm2->dep_bit));
-}
-
-static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm)
-{
-	struct clkdm_dep *cd;
-	u32 mask = 0;
-
-	if (!clkdm->prcm_partition)
-		return 0;
-
-	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
-		if (!cd->clkdm)
-			continue; /* only happens if data is erroneous */
-
-		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->wkdep_usecount, 0);
-	}
-
-	omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition,
-					clkdm->cm_inst, clkdm->clkdm_offs +
-					OMAP4_CM_STATICDEP);
-	return 0;
-}
-
-static int omap4_clkdm_sleep(struct clockdomain *clkdm)
-{
-	omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
-					clkdm->cm_inst, clkdm->clkdm_offs);
-	return 0;
-}
-
-static int omap4_clkdm_wakeup(struct clockdomain *clkdm)
-{
-	omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition,
-					clkdm->cm_inst, clkdm->clkdm_offs);
-	return 0;
-}
-
-static void omap4_clkdm_allow_idle(struct clockdomain *clkdm)
-{
-	omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
-					clkdm->cm_inst, clkdm->clkdm_offs);
-}
-
-static void omap4_clkdm_deny_idle(struct clockdomain *clkdm)
-{
-	if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
-		omap4_clkdm_wakeup(clkdm);
-	else
-		omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition,
-						 clkdm->cm_inst,
-						 clkdm->clkdm_offs);
-}
-
-static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
-{
-	if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
-		return omap4_clkdm_wakeup(clkdm);
-
-	return 0;
-}
-
-static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
-{
-	bool hwsup = false;
-
-	if (!clkdm->prcm_partition)
-		return 0;
-
-	/*
-	 * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
-	 * more details on the unpleasant problem this is working
-	 * around
-	 */
-	if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
-	    !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
-		omap4_clkdm_allow_idle(clkdm);
-		return 0;
-	}
-
-	hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
-					clkdm->cm_inst, clkdm->clkdm_offs);
-
-	if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
-		omap4_clkdm_sleep(clkdm);
-
-	return 0;
-}
-
-struct clkdm_ops omap4_clkdm_operations = {
-	.clkdm_add_wkdep	= omap4_clkdm_add_wkup_sleep_dep,
-	.clkdm_del_wkdep	= omap4_clkdm_del_wkup_sleep_dep,
-	.clkdm_read_wkdep	= omap4_clkdm_read_wkup_sleep_dep,
-	.clkdm_clear_all_wkdeps	= omap4_clkdm_clear_all_wkup_sleep_deps,
-	.clkdm_add_sleepdep	= omap4_clkdm_add_wkup_sleep_dep,
-	.clkdm_del_sleepdep	= omap4_clkdm_del_wkup_sleep_dep,
-	.clkdm_read_sleepdep	= omap4_clkdm_read_wkup_sleep_dep,
-	.clkdm_clear_all_sleepdeps	= omap4_clkdm_clear_all_wkup_sleep_deps,
-	.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/clockdomains2420_data.c b/arch/arm/mach-omap2/clockdomains2420_data.c
index 5c74185..7e76bec 100644
--- a/arch/arm/mach-omap2/clockdomains2420_data.c
+++ b/arch/arm/mach-omap2/clockdomains2420_data.c
@@ -35,6 +35,7 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 
+#include "soc.h"
 #include "clockdomain.h"
 #include "prm2xxx_3xxx.h"
 #include "cm2xxx_3xxx.h"
diff --git a/arch/arm/mach-omap2/clockdomains2430_data.c b/arch/arm/mach-omap2/clockdomains2430_data.c
index f096175..b923007 100644
--- a/arch/arm/mach-omap2/clockdomains2430_data.c
+++ b/arch/arm/mach-omap2/clockdomains2430_data.c
@@ -35,6 +35,7 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 
+#include "soc.h"
 #include "clockdomain.h"
 #include "prm2xxx_3xxx.h"
 #include "cm2xxx_3xxx.h"
diff --git a/arch/arm/mach-omap2/clockdomains3xxx_data.c b/arch/arm/mach-omap2/clockdomains3xxx_data.c
index 933a35c..e6b91e5 100644
--- a/arch/arm/mach-omap2/clockdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/clockdomains3xxx_data.c
@@ -33,6 +33,7 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 
+#include "soc.h"
 #include "clockdomain.h"
 #include "prm2xxx_3xxx.h"
 #include "cm2xxx_3xxx.h"
diff --git a/arch/arm/mach-omap2/cm-regbits-24xx.h b/arch/arm/mach-omap2/cm-regbits-24xx.h
index 6862904..669ef51 100644
--- a/arch/arm/mach-omap2/cm-regbits-24xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-24xx.h
@@ -59,6 +59,7 @@
 /* CM_CLKSEL_MPU */
 #define OMAP24XX_CLKSEL_MPU_SHIFT			0
 #define OMAP24XX_CLKSEL_MPU_MASK			(0x1f << 0)
+#define OMAP24XX_CLKSEL_MPU_WIDTH			5
 
 /* CM_CLKSTCTRL_MPU */
 #define OMAP24XX_AUTOSTATE_MPU_SHIFT			0
@@ -237,8 +238,10 @@
 #define OMAP24XX_CLKSEL_DSS1_MASK			(0x1f << 8)
 #define OMAP24XX_CLKSEL_L4_SHIFT			5
 #define OMAP24XX_CLKSEL_L4_MASK				(0x3 << 5)
+#define OMAP24XX_CLKSEL_L4_WIDTH			2
 #define OMAP24XX_CLKSEL_L3_SHIFT			0
 #define OMAP24XX_CLKSEL_L3_MASK				(0x1f << 0)
+#define OMAP24XX_CLKSEL_L3_WIDTH			5
 
 /* CM_CLKSEL2_CORE */
 #define OMAP24XX_CLKSEL_GPT12_SHIFT			22
@@ -333,7 +336,9 @@
 #define OMAP24XX_EN_DPLL_MASK				(0x3 << 0)
 
 /* CM_IDLEST_CKGEN */
+#define OMAP24XX_ST_54M_APLL_SHIFT			9
 #define OMAP24XX_ST_54M_APLL_MASK			(1 << 9)
+#define OMAP24XX_ST_96M_APLL_SHIFT			8
 #define OMAP24XX_ST_96M_APLL_MASK			(1 << 8)
 #define OMAP24XX_ST_54M_CLK_MASK			(1 << 6)
 #define OMAP24XX_ST_12M_CLK_MASK			(1 << 5)
@@ -361,8 +366,10 @@
 #define OMAP24XX_DPLL_DIV_MASK				(0xf << 8)
 #define OMAP24XX_54M_SOURCE_SHIFT			5
 #define OMAP24XX_54M_SOURCE_MASK			(1 << 5)
+#define OMAP24XX_54M_SOURCE_WIDTH			1
 #define OMAP2430_96M_SOURCE_SHIFT			4
 #define OMAP2430_96M_SOURCE_MASK			(1 << 4)
+#define OMAP2430_96M_SOURCE_WIDTH			1
 #define OMAP24XX_48M_SOURCE_SHIFT			3
 #define OMAP24XX_48M_SOURCE_MASK			(1 << 3)
 #define OMAP2430_ALTCLK_SOURCE_SHIFT			0
diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h
index 59598ff..adf78d3 100644
--- a/arch/arm/mach-omap2/cm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-34xx.h
@@ -81,6 +81,7 @@
 /* CM_CLKSEL1_PLL_IVA2 */
 #define OMAP3430_IVA2_CLK_SRC_SHIFT			19
 #define OMAP3430_IVA2_CLK_SRC_MASK			(0x7 << 19)
+#define OMAP3430_IVA2_CLK_SRC_WIDTH			3
 #define OMAP3430_IVA2_DPLL_MULT_SHIFT			8
 #define OMAP3430_IVA2_DPLL_MULT_MASK			(0x7ff << 8)
 #define OMAP3430_IVA2_DPLL_DIV_SHIFT			0
@@ -89,6 +90,7 @@
 /* CM_CLKSEL2_PLL_IVA2 */
 #define OMAP3430_IVA2_DPLL_CLKOUT_DIV_SHIFT		0
 #define OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK		(0x1f << 0)
+#define OMAP3430_IVA2_DPLL_CLKOUT_DIV_WIDTH		5
 
 /* CM_CLKSTCTRL_IVA2 */
 #define OMAP3430_CLKTRCTRL_IVA2_SHIFT			0
@@ -118,6 +120,7 @@
 /* CM_IDLEST_PLL_MPU */
 #define OMAP3430_ST_MPU_CLK_SHIFT			0
 #define OMAP3430_ST_MPU_CLK_MASK			(1 << 0)
+#define OMAP3430_ST_MPU_CLK_WIDTH			1
 
 /* CM_AUTOIDLE_PLL_MPU */
 #define OMAP3430_AUTO_MPU_DPLL_SHIFT			0
@@ -126,6 +129,7 @@
 /* CM_CLKSEL1_PLL_MPU */
 #define OMAP3430_MPU_CLK_SRC_SHIFT			19
 #define OMAP3430_MPU_CLK_SRC_MASK			(0x7 << 19)
+#define OMAP3430_MPU_CLK_SRC_WIDTH			3
 #define OMAP3430_MPU_DPLL_MULT_SHIFT			8
 #define OMAP3430_MPU_DPLL_MULT_MASK			(0x7ff << 8)
 #define OMAP3430_MPU_DPLL_DIV_SHIFT			0
@@ -134,6 +138,7 @@
 /* CM_CLKSEL2_PLL_MPU */
 #define OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT		0
 #define OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK		(0x1f << 0)
+#define OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH		5
 
 /* CM_CLKSTCTRL_MPU */
 #define OMAP3430_CLKTRCTRL_MPU_SHIFT			0
@@ -345,10 +350,13 @@
 #define OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK		(0x3 << 4)
 #define OMAP3430_CLKSEL_L4_SHIFT			2
 #define OMAP3430_CLKSEL_L4_MASK				(0x3 << 2)
+#define OMAP3430_CLKSEL_L4_WIDTH			2
 #define OMAP3430_CLKSEL_L3_SHIFT			0
 #define OMAP3430_CLKSEL_L3_MASK				(0x3 << 0)
+#define OMAP3430_CLKSEL_L3_WIDTH			2
 #define OMAP3630_CLKSEL_96M_SHIFT			12
 #define OMAP3630_CLKSEL_96M_MASK			(0x3 << 12)
+#define OMAP3630_CLKSEL_96M_WIDTH			2
 
 /* CM_CLKSTCTRL_CORE */
 #define OMAP3430ES1_CLKTRCTRL_D2D_SHIFT			4
@@ -452,6 +460,7 @@
 #define OMAP3430ES2_CLKSEL_USIMOCP_MASK			(0xf << 3)
 #define OMAP3430_CLKSEL_RM_SHIFT			1
 #define OMAP3430_CLKSEL_RM_MASK				(0x3 << 1)
+#define OMAP3430_CLKSEL_RM_WIDTH			2
 #define OMAP3430_CLKSEL_GPT1_SHIFT			0
 #define OMAP3430_CLKSEL_GPT1_MASK			(1 << 0)
 
@@ -520,14 +529,17 @@
 /* Note that OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK was (0x3 << 27) on 3430ES1 */
 #define OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT		27
 #define OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK		(0x1f << 27)
+#define OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH		5
 #define OMAP3430_CORE_DPLL_MULT_SHIFT			16
 #define OMAP3430_CORE_DPLL_MULT_MASK			(0x7ff << 16)
 #define OMAP3430_CORE_DPLL_DIV_SHIFT			8
 #define OMAP3430_CORE_DPLL_DIV_MASK			(0x7f << 8)
 #define OMAP3430_SOURCE_96M_SHIFT			6
 #define OMAP3430_SOURCE_96M_MASK			(1 << 6)
+#define OMAP3430_SOURCE_96M_WIDTH			1
 #define OMAP3430_SOURCE_54M_SHIFT			5
 #define OMAP3430_SOURCE_54M_MASK			(1 << 5)
+#define OMAP3430_SOURCE_54M_WIDTH			1
 #define OMAP3430_SOURCE_48M_SHIFT			3
 #define OMAP3430_SOURCE_48M_MASK			(1 << 3)
 
@@ -545,7 +557,9 @@
 /* CM_CLKSEL3_PLL */
 #define OMAP3430_DIV_96M_SHIFT				0
 #define OMAP3430_DIV_96M_MASK				(0x1f << 0)
+#define OMAP3430_DIV_96M_WIDTH				5
 #define OMAP3630_DIV_96M_MASK				(0x3f << 0)
+#define OMAP3630_DIV_96M_WIDTH				6
 
 /* CM_CLKSEL4_PLL */
 #define OMAP3430ES2_PERIPH2_DPLL_MULT_SHIFT		8
@@ -556,12 +570,14 @@
 /* CM_CLKSEL5_PLL */
 #define OMAP3430ES2_DIV_120M_SHIFT			0
 #define OMAP3430ES2_DIV_120M_MASK			(0x1f << 0)
+#define OMAP3430ES2_DIV_120M_WIDTH			5
 
 /* CM_CLKOUT_CTRL */
 #define OMAP3430_CLKOUT2_EN_SHIFT			7
 #define OMAP3430_CLKOUT2_EN_MASK			(1 << 7)
 #define OMAP3430_CLKOUT2_DIV_SHIFT			3
 #define OMAP3430_CLKOUT2_DIV_MASK			(0x7 << 3)
+#define OMAP3430_CLKOUT2_DIV_WIDTH			3
 #define OMAP3430_CLKOUT2SOURCE_SHIFT			0
 #define OMAP3430_CLKOUT2SOURCE_MASK			(0x3 << 0)
 
@@ -592,10 +608,14 @@
 /* CM_CLKSEL_DSS */
 #define OMAP3430_CLKSEL_TV_SHIFT			8
 #define OMAP3430_CLKSEL_TV_MASK				(0x1f << 8)
+#define OMAP3430_CLKSEL_TV_WIDTH			5
 #define OMAP3630_CLKSEL_TV_MASK				(0x3f << 8)
+#define OMAP3630_CLKSEL_TV_WIDTH			6
 #define OMAP3430_CLKSEL_DSS1_SHIFT			0
 #define OMAP3430_CLKSEL_DSS1_MASK			(0x1f << 0)
+#define OMAP3430_CLKSEL_DSS1_WIDTH			5
 #define OMAP3630_CLKSEL_DSS1_MASK			(0x3f << 0)
+#define OMAP3630_CLKSEL_DSS1_WIDTH			6
 
 /* CM_SLEEPDEP_DSS specific bits */
 
@@ -623,7 +643,9 @@
 /* CM_CLKSEL_CAM */
 #define OMAP3430_CLKSEL_CAM_SHIFT			0
 #define OMAP3430_CLKSEL_CAM_MASK			(0x1f << 0)
+#define OMAP3430_CLKSEL_CAM_WIDTH			5
 #define OMAP3630_CLKSEL_CAM_MASK			(0x3f << 0)
+#define OMAP3630_CLKSEL_CAM_WIDTH			6
 
 /* CM_SLEEPDEP_CAM specific bits */
 
@@ -721,21 +743,30 @@
 /* CM_CLKSEL1_EMU */
 #define OMAP3430_DIV_DPLL4_SHIFT			24
 #define OMAP3430_DIV_DPLL4_MASK				(0x1f << 24)
+#define OMAP3430_DIV_DPLL4_WIDTH			5
 #define OMAP3630_DIV_DPLL4_MASK				(0x3f << 24)
+#define OMAP3630_DIV_DPLL4_WIDTH			6
 #define OMAP3430_DIV_DPLL3_SHIFT			16
 #define OMAP3430_DIV_DPLL3_MASK				(0x1f << 16)
+#define OMAP3430_DIV_DPLL3_WIDTH			5
 #define OMAP3430_CLKSEL_TRACECLK_SHIFT			11
 #define OMAP3430_CLKSEL_TRACECLK_MASK			(0x7 << 11)
+#define OMAP3430_CLKSEL_TRACECLK_WIDTH			3
 #define OMAP3430_CLKSEL_PCLK_SHIFT			8
 #define OMAP3430_CLKSEL_PCLK_MASK			(0x7 << 8)
+#define OMAP3430_CLKSEL_PCLK_WIDTH			3
 #define OMAP3430_CLKSEL_PCLKX2_SHIFT			6
 #define OMAP3430_CLKSEL_PCLKX2_MASK			(0x3 << 6)
+#define OMAP3430_CLKSEL_PCLKX2_WIDTH			2
 #define OMAP3430_CLKSEL_ATCLK_SHIFT			4
 #define OMAP3430_CLKSEL_ATCLK_MASK			(0x3 << 4)
+#define OMAP3430_CLKSEL_ATCLK_WIDTH			2
 #define OMAP3430_TRACE_MUX_CTRL_SHIFT			2
 #define OMAP3430_TRACE_MUX_CTRL_MASK			(0x3 << 2)
+#define OMAP3430_TRACE_MUX_CTRL_WIDTH			2
 #define OMAP3430_MUX_CTRL_SHIFT				0
 #define OMAP3430_MUX_CTRL_MASK				(0x3 << 0)
+#define OMAP3430_MUX_CTRL_WIDTH				2
 
 /* CM_CLKSTCTRL_EMU */
 #define OMAP3430_CLKTRCTRL_EMU_SHIFT			0
diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h
index f24e3f7..93473f9 100644
--- a/arch/arm/mach-omap2/cm.h
+++ b/arch/arm/mach-omap2/cm.h
@@ -1,7 +1,7 @@
 /*
  * OMAP2+ Clock Management prototypes
  *
- * Copyright (C) 2007-2009 Texas Instruments, Inc.
+ * Copyright (C) 2007-2009, 2012 Texas Instruments, Inc.
  * Copyright (C) 2007-2009 Nokia Corporation
  *
  * Written by Paul Walmsley
@@ -22,6 +22,12 @@
  */
 #define MAX_MODULE_READY_TIME		2000
 
+# ifndef __ASSEMBLER__
+extern void __iomem *cm_base;
+extern void __iomem *cm2_base;
+extern void omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2);
+# endif
+
 /*
  * MAX_MODULE_DISABLE_TIME: max duration in microseconds to wait for
  * the PRCM to request that a module enter the inactive state in the
@@ -33,4 +39,26 @@
  */
 #define MAX_MODULE_DISABLE_TIME		5000
 
+# ifndef __ASSEMBLER__
+
+/**
+ * struct cm_ll_data - fn ptrs to per-SoC CM function implementations
+ * @split_idlest_reg: ptr to the SoC CM-specific split_idlest_reg impl
+ * @wait_module_ready: ptr to the SoC CM-specific wait_module_ready impl
+ */
+struct cm_ll_data {
+	int (*split_idlest_reg)(void __iomem *idlest_reg, s16 *prcm_inst,
+				u8 *idlest_reg_id);
+	int (*wait_module_ready)(s16 prcm_mod, u8 idlest_id, u8 idlest_shift);
+};
+
+extern int cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
+			       u8 *idlest_reg_id);
+extern int cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift);
+
+extern int cm_register(struct cm_ll_data *cld);
+extern int cm_unregister(struct cm_ll_data *cld);
+
+# endif
+
 #endif
diff --git a/arch/arm/mach-omap2/cm2xxx.c b/arch/arm/mach-omap2/cm2xxx.c
new file mode 100644
index 0000000..db65069
--- /dev/null
+++ b/arch/arm/mach-omap2/cm2xxx.c
@@ -0,0 +1,381 @@
+/*
+ * OMAP2xxx CM module functions
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2008-2010, 2012 Texas Instruments, Inc.
+ * Paul Walmsley
+ * Rajendra Nayak <rnayak@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include "soc.h"
+#include "iomap.h"
+#include "common.h"
+#include "prm2xxx.h"
+#include "cm.h"
+#include "cm2xxx.h"
+#include "cm-regbits-24xx.h"
+#include "clockdomain.h"
+
+/* CM_AUTOIDLE_PLL.AUTO_* bit values for DPLLs */
+#define DPLL_AUTOIDLE_DISABLE				0x0
+#define OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP		0x3
+
+/* CM_AUTOIDLE_PLL.AUTO_* bit values for APLLs (OMAP2xxx only) */
+#define OMAP2XXX_APLL_AUTOIDLE_DISABLE			0x0
+#define OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP		0x3
+
+/* CM_IDLEST_PLL bit value offset for APLLs (OMAP2xxx only) */
+#define EN_APLL_LOCKED					3
+
+static const u8 omap2xxx_cm_idlest_offs[] = {
+	CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3, OMAP24XX_CM_IDLEST4
+};
+
+/*
+ *
+ */
+
+static void _write_clktrctrl(u8 c, s16 module, u32 mask)
+{
+	u32 v;
+
+	v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
+	v &= ~mask;
+	v |= c << __ffs(mask);
+	omap2_cm_write_mod_reg(v, module, OMAP2_CM_CLKSTCTRL);
+}
+
+bool omap2xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
+{
+	u32 v;
+
+	v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
+	v &= mask;
+	v >>= __ffs(mask);
+
+	return (v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
+}
+
+void omap2xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
+{
+	_write_clktrctrl(OMAP24XX_CLKSTCTRL_ENABLE_AUTO, module, mask);
+}
+
+void omap2xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
+{
+	_write_clktrctrl(OMAP24XX_CLKSTCTRL_DISABLE_AUTO, module, mask);
+}
+
+/*
+ * DPLL autoidle control
+ */
+
+static void _omap2xxx_set_dpll_autoidle(u8 m)
+{
+	u32 v;
+
+	v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
+	v &= ~OMAP24XX_AUTO_DPLL_MASK;
+	v |= m << OMAP24XX_AUTO_DPLL_SHIFT;
+	omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
+}
+
+void omap2xxx_cm_set_dpll_disable_autoidle(void)
+{
+	_omap2xxx_set_dpll_autoidle(OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP);
+}
+
+void omap2xxx_cm_set_dpll_auto_low_power_stop(void)
+{
+	_omap2xxx_set_dpll_autoidle(DPLL_AUTOIDLE_DISABLE);
+}
+
+/*
+ * APLL control
+ */
+
+static void _omap2xxx_set_apll_autoidle(u8 m, u32 mask)
+{
+	u32 v;
+
+	v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
+	v &= ~mask;
+	v |= m << __ffs(mask);
+	omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
+}
+
+void omap2xxx_cm_set_apll54_disable_autoidle(void)
+{
+	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP,
+				    OMAP24XX_AUTO_54M_MASK);
+}
+
+void omap2xxx_cm_set_apll54_auto_low_power_stop(void)
+{
+	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE,
+				    OMAP24XX_AUTO_54M_MASK);
+}
+
+void omap2xxx_cm_set_apll96_disable_autoidle(void)
+{
+	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP,
+				    OMAP24XX_AUTO_96M_MASK);
+}
+
+void omap2xxx_cm_set_apll96_auto_low_power_stop(void)
+{
+	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE,
+				    OMAP24XX_AUTO_96M_MASK);
+}
+
+/* Enable an APLL if off */
+static int _omap2xxx_apll_enable(u8 enable_bit, u8 status_bit)
+{
+	u32 v, m;
+
+	m = EN_APLL_LOCKED << enable_bit;
+
+	v = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
+	if (v & m)
+		return 0;   /* apll already enabled */
+
+	v |= m;
+	omap2_cm_write_mod_reg(v, PLL_MOD, CM_CLKEN);
+
+	omap2xxx_cm_wait_module_ready(PLL_MOD, 1, status_bit);
+
+	/*
+	 * REVISIT: Should we return an error code if
+	 * omap2xxx_cm_wait_module_ready() fails?
+	 */
+	return 0;
+}
+
+/* Stop APLL */
+static void _omap2xxx_apll_disable(u8 enable_bit)
+{
+	u32 v;
+
+	v = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
+	v &= ~(EN_APLL_LOCKED << enable_bit);
+	omap2_cm_write_mod_reg(v, PLL_MOD, CM_CLKEN);
+}
+
+/* Enable an APLL if off */
+int omap2xxx_cm_apll54_enable(void)
+{
+	return _omap2xxx_apll_enable(OMAP24XX_EN_54M_PLL_SHIFT,
+				     OMAP24XX_ST_54M_APLL_SHIFT);
+}
+
+/* Enable an APLL if off */
+int omap2xxx_cm_apll96_enable(void)
+{
+	return _omap2xxx_apll_enable(OMAP24XX_EN_96M_PLL_SHIFT,
+				     OMAP24XX_ST_96M_APLL_SHIFT);
+}
+
+/* Stop APLL */
+void omap2xxx_cm_apll54_disable(void)
+{
+	_omap2xxx_apll_disable(OMAP24XX_EN_54M_PLL_SHIFT);
+}
+
+/* Stop APLL */
+void omap2xxx_cm_apll96_disable(void)
+{
+	_omap2xxx_apll_disable(OMAP24XX_EN_96M_PLL_SHIFT);
+}
+
+/**
+ * omap2xxx_cm_split_idlest_reg - split CM_IDLEST reg addr into its components
+ * @idlest_reg: CM_IDLEST* virtual address
+ * @prcm_inst: pointer to an s16 to return the PRCM instance offset
+ * @idlest_reg_id: pointer to a u8 to return the CM_IDLESTx register ID
+ *
+ * XXX This function is only needed until absolute register addresses are
+ * removed from the OMAP struct clk records.
+ */
+int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
+				 u8 *idlest_reg_id)
+{
+	unsigned long offs;
+	u8 idlest_offs;
+	int i;
+
+	if (idlest_reg < cm_base || idlest_reg > (cm_base + 0x0fff))
+		return -EINVAL;
+
+	idlest_offs = (unsigned long)idlest_reg & 0xff;
+	for (i = 0; i < ARRAY_SIZE(omap2xxx_cm_idlest_offs); i++) {
+		if (idlest_offs == omap2xxx_cm_idlest_offs[i]) {
+			*idlest_reg_id = i + 1;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(omap2xxx_cm_idlest_offs))
+		return -EINVAL;
+
+	offs = idlest_reg - cm_base;
+	offs &= 0xff00;
+	*prcm_inst = offs;
+
+	return 0;
+}
+
+/*
+ *
+ */
+
+/**
+ * omap2xxx_cm_wait_module_ready - wait for a module to leave idle or standby
+ * @prcm_mod: PRCM module offset
+ * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
+ * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
+ *
+ * Wait for the PRCM to indicate that the module identified by
+ * (@prcm_mod, @idlest_id, @idlest_shift) is clocked.  Return 0 upon
+ * success or -EBUSY if the module doesn't enable in time.
+ */
+int omap2xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
+{
+	int ena = 0, i = 0;
+	u8 cm_idlest_reg;
+	u32 mask;
+
+	if (!idlest_id || (idlest_id > ARRAY_SIZE(omap2xxx_cm_idlest_offs)))
+		return -EINVAL;
+
+	cm_idlest_reg = omap2xxx_cm_idlest_offs[idlest_id - 1];
+
+	mask = 1 << idlest_shift;
+	ena = mask;
+
+	omap_test_timeout(((omap2_cm_read_mod_reg(prcm_mod, cm_idlest_reg) &
+			    mask) == ena), MAX_MODULE_READY_TIME, i);
+
+	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
+}
+
+/* Clockdomain low-level functions */
+
+static void omap2xxx_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+	if (atomic_read(&clkdm->usecount) > 0)
+		_clkdm_add_autodeps(clkdm);
+
+	omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				       clkdm->clktrctrl_mask);
+}
+
+static void omap2xxx_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+	omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					clkdm->clktrctrl_mask);
+
+	if (atomic_read(&clkdm->usecount) > 0)
+		_clkdm_del_autodeps(clkdm);
+}
+
+static int omap2xxx_clkdm_clk_enable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	if (!clkdm->clktrctrl_mask)
+		return 0;
+
+	hwsup = omap2xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					      clkdm->clktrctrl_mask);
+
+	if (hwsup) {
+		/* Disable HW transitions when we are changing deps */
+		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+						clkdm->clktrctrl_mask);
+		_clkdm_add_autodeps(clkdm);
+		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					       clkdm->clktrctrl_mask);
+	} else {
+		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+			omap2xxx_clkdm_wakeup(clkdm);
+	}
+
+	return 0;
+}
+
+static int omap2xxx_clkdm_clk_disable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	if (!clkdm->clktrctrl_mask)
+		return 0;
+
+	hwsup = omap2xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					      clkdm->clktrctrl_mask);
+
+	if (hwsup) {
+		/* Disable HW transitions when we are changing deps */
+		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+						clkdm->clktrctrl_mask);
+		_clkdm_del_autodeps(clkdm);
+		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					       clkdm->clktrctrl_mask);
+	} else {
+		if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
+			omap2xxx_clkdm_sleep(clkdm);
+	}
+
+	return 0;
+}
+
+struct clkdm_ops omap2_clkdm_operations = {
+	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
+	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
+	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
+	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
+	.clkdm_sleep		= omap2xxx_clkdm_sleep,
+	.clkdm_wakeup		= omap2xxx_clkdm_wakeup,
+	.clkdm_allow_idle	= omap2xxx_clkdm_allow_idle,
+	.clkdm_deny_idle	= omap2xxx_clkdm_deny_idle,
+	.clkdm_clk_enable	= omap2xxx_clkdm_clk_enable,
+	.clkdm_clk_disable	= omap2xxx_clkdm_clk_disable,
+};
+
+/*
+ *
+ */
+
+static struct cm_ll_data omap2xxx_cm_ll_data = {
+	.split_idlest_reg	= &omap2xxx_cm_split_idlest_reg,
+	.wait_module_ready	= &omap2xxx_cm_wait_module_ready,
+};
+
+int __init omap2xxx_cm_init(void)
+{
+	if (!cpu_is_omap24xx())
+		return 0;
+
+	return cm_register(&omap2xxx_cm_ll_data);
+}
+
+static void __exit omap2xxx_cm_exit(void)
+{
+	if (!cpu_is_omap24xx())
+		return;
+
+	/* Should never happen */
+	WARN(cm_unregister(&omap2xxx_cm_ll_data),
+	     "%s: cm_ll_data function pointer mismatch\n", __func__);
+}
+__exitcall(omap2xxx_cm_exit);
diff --git a/arch/arm/mach-omap2/cm2xxx.h b/arch/arm/mach-omap2/cm2xxx.h
new file mode 100644
index 0000000..4cbb39b
--- /dev/null
+++ b/arch/arm/mach-omap2/cm2xxx.h
@@ -0,0 +1,70 @@
+/*
+ * OMAP2xxx Clock Management (CM) register definitions
+ *
+ * Copyright (C) 2007-2009, 2012 Texas Instruments, Inc.
+ * Copyright (C) 2007-2010 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The CM hardware modules on the OMAP2/3 are quite similar to each
+ * other.  The CM modules/instances on OMAP4 are quite different, so
+ * they are handled in a separate file.
+ */
+#ifndef __ARCH_ASM_MACH_OMAP2_CM2XXX_H
+#define __ARCH_ASM_MACH_OMAP2_CM2XXX_H
+
+#include "prcm-common.h"
+#include "cm2xxx_3xxx.h"
+
+#define OMAP2420_CM_REGADDR(module, reg)				\
+			OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE + (module) + (reg))
+#define OMAP2430_CM_REGADDR(module, reg)				\
+			OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE + (module) + (reg))
+
+/*
+ * Module specific CM register offsets from CM_BASE + domain offset
+ * Use cm_{read,write}_mod_reg() with these registers.
+ * These register offsets generally appear in more than one PRCM submodule.
+ */
+
+/* OMAP2-specific register offsets */
+
+#define OMAP24XX_CM_FCLKEN2				0x0004
+#define OMAP24XX_CM_ICLKEN4				0x001c
+#define OMAP24XX_CM_AUTOIDLE4				0x003c
+#define OMAP24XX_CM_IDLEST4				0x002c
+
+/* CM_IDLEST bit field values to indicate deasserted IdleReq */
+
+#define OMAP24XX_CM_IDLEST_VAL				0
+
+
+/* Clock management domain register get/set */
+
+#ifndef __ASSEMBLER__
+
+extern void omap2xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask);
+extern void omap2xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask);
+
+extern void omap2xxx_cm_set_dpll_disable_autoidle(void);
+extern void omap2xxx_cm_set_dpll_auto_low_power_stop(void);
+
+extern void omap2xxx_cm_set_apll54_disable_autoidle(void);
+extern void omap2xxx_cm_set_apll54_auto_low_power_stop(void);
+extern void omap2xxx_cm_set_apll96_disable_autoidle(void);
+extern void omap2xxx_cm_set_apll96_auto_low_power_stop(void);
+
+extern bool omap2xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask);
+extern int omap2xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id,
+					 u8 idlest_shift);
+extern int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
+					s16 *prcm_inst, u8 *idlest_reg_id);
+
+extern int __init omap2xxx_cm_init(void);
+
+#endif
+
+#endif
diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.c b/arch/arm/mach-omap2/cm2xxx_3xxx.c
deleted file mode 100644
index 7f07ab0..0000000
--- a/arch/arm/mach-omap2/cm2xxx_3xxx.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- * OMAP2/3 CM module functions
- *
- * Copyright (C) 2009 Nokia Corporation
- * Paul Walmsley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "common.h"
-#include "cm.h"
-#include "cm2xxx_3xxx.h"
-#include "cm-regbits-24xx.h"
-#include "cm-regbits-34xx.h"
-
-/* CM_AUTOIDLE_PLL.AUTO_* bit values for DPLLs */
-#define DPLL_AUTOIDLE_DISABLE				0x0
-#define OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP		0x3
-
-/* CM_AUTOIDLE_PLL.AUTO_* bit values for APLLs (OMAP2xxx only) */
-#define OMAP2XXX_APLL_AUTOIDLE_DISABLE			0x0
-#define OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP		0x3
-
-static const u8 cm_idlest_offs[] = {
-	CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3, OMAP24XX_CM_IDLEST4
-};
-
-u32 omap2_cm_read_mod_reg(s16 module, u16 idx)
-{
-	return __raw_readl(cm_base + module + idx);
-}
-
-void omap2_cm_write_mod_reg(u32 val, s16 module, u16 idx)
-{
-	__raw_writel(val, cm_base + module + idx);
-}
-
-/* Read-modify-write a register in a CM module. Caller must lock */
-u32 omap2_cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
-{
-	u32 v;
-
-	v = omap2_cm_read_mod_reg(module, idx);
-	v &= ~mask;
-	v |= bits;
-	omap2_cm_write_mod_reg(v, module, idx);
-
-	return v;
-}
-
-u32 omap2_cm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
-{
-	return omap2_cm_rmw_mod_reg_bits(bits, bits, module, idx);
-}
-
-u32 omap2_cm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
-{
-	return omap2_cm_rmw_mod_reg_bits(bits, 0x0, module, idx);
-}
-
-/*
- *
- */
-
-static void _write_clktrctrl(u8 c, s16 module, u32 mask)
-{
-	u32 v;
-
-	v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
-	v &= ~mask;
-	v |= c << __ffs(mask);
-	omap2_cm_write_mod_reg(v, module, OMAP2_CM_CLKSTCTRL);
-}
-
-bool omap2_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
-{
-	u32 v;
-	bool ret = 0;
-
-	BUG_ON(!cpu_is_omap24xx() && !cpu_is_omap34xx());
-
-	v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
-	v &= mask;
-	v >>= __ffs(mask);
-
-	if (cpu_is_omap24xx())
-		ret = (v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
-	else
-		ret = (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
-
-	return ret;
-}
-
-void omap2xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
-{
-	_write_clktrctrl(OMAP24XX_CLKSTCTRL_ENABLE_AUTO, module, mask);
-}
-
-void omap2xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
-{
-	_write_clktrctrl(OMAP24XX_CLKSTCTRL_DISABLE_AUTO, module, mask);
-}
-
-void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
-{
-	_write_clktrctrl(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, module, mask);
-}
-
-void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
-{
-	_write_clktrctrl(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, module, mask);
-}
-
-void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask)
-{
-	_write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, module, mask);
-}
-
-void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask)
-{
-	_write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, module, mask);
-}
-
-/*
- * DPLL autoidle control
- */
-
-static void _omap2xxx_set_dpll_autoidle(u8 m)
-{
-	u32 v;
-
-	v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
-	v &= ~OMAP24XX_AUTO_DPLL_MASK;
-	v |= m << OMAP24XX_AUTO_DPLL_SHIFT;
-	omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
-}
-
-void omap2xxx_cm_set_dpll_disable_autoidle(void)
-{
-	_omap2xxx_set_dpll_autoidle(OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP);
-}
-
-void omap2xxx_cm_set_dpll_auto_low_power_stop(void)
-{
-	_omap2xxx_set_dpll_autoidle(DPLL_AUTOIDLE_DISABLE);
-}
-
-/*
- * APLL autoidle control
- */
-
-static void _omap2xxx_set_apll_autoidle(u8 m, u32 mask)
-{
-	u32 v;
-
-	v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
-	v &= ~mask;
-	v |= m << __ffs(mask);
-	omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
-}
-
-void omap2xxx_cm_set_apll54_disable_autoidle(void)
-{
-	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP,
-				    OMAP24XX_AUTO_54M_MASK);
-}
-
-void omap2xxx_cm_set_apll54_auto_low_power_stop(void)
-{
-	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE,
-				    OMAP24XX_AUTO_54M_MASK);
-}
-
-void omap2xxx_cm_set_apll96_disable_autoidle(void)
-{
-	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP,
-				    OMAP24XX_AUTO_96M_MASK);
-}
-
-void omap2xxx_cm_set_apll96_auto_low_power_stop(void)
-{
-	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE,
-				    OMAP24XX_AUTO_96M_MASK);
-}
-
-/*
- *
- */
-
-/**
- * omap2_cm_wait_idlest_ready - wait for a module to leave idle or standby
- * @prcm_mod: PRCM module offset
- * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
- * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
- *
- * XXX document
- */
-int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
-{
-	int ena = 0, i = 0;
-	u8 cm_idlest_reg;
-	u32 mask;
-
-	if (!idlest_id || (idlest_id > ARRAY_SIZE(cm_idlest_offs)))
-		return -EINVAL;
-
-	cm_idlest_reg = cm_idlest_offs[idlest_id - 1];
-
-	mask = 1 << idlest_shift;
-
-	if (cpu_is_omap24xx())
-		ena = mask;
-	else if (cpu_is_omap34xx())
-		ena = 0;
-	else
-		BUG();
-
-	omap_test_timeout(((omap2_cm_read_mod_reg(prcm_mod, cm_idlest_reg) & mask) == ena),
-			  MAX_MODULE_READY_TIME, i);
-
-	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
-}
-
-/*
- * Context save/restore code - OMAP3 only
- */
-#ifdef CONFIG_ARCH_OMAP3
-struct omap3_cm_regs {
-	u32 iva2_cm_clksel1;
-	u32 iva2_cm_clksel2;
-	u32 cm_sysconfig;
-	u32 sgx_cm_clksel;
-	u32 dss_cm_clksel;
-	u32 cam_cm_clksel;
-	u32 per_cm_clksel;
-	u32 emu_cm_clksel;
-	u32 emu_cm_clkstctrl;
-	u32 pll_cm_autoidle;
-	u32 pll_cm_autoidle2;
-	u32 pll_cm_clksel4;
-	u32 pll_cm_clksel5;
-	u32 pll_cm_clken2;
-	u32 cm_polctrl;
-	u32 iva2_cm_fclken;
-	u32 iva2_cm_clken_pll;
-	u32 core_cm_fclken1;
-	u32 core_cm_fclken3;
-	u32 sgx_cm_fclken;
-	u32 wkup_cm_fclken;
-	u32 dss_cm_fclken;
-	u32 cam_cm_fclken;
-	u32 per_cm_fclken;
-	u32 usbhost_cm_fclken;
-	u32 core_cm_iclken1;
-	u32 core_cm_iclken2;
-	u32 core_cm_iclken3;
-	u32 sgx_cm_iclken;
-	u32 wkup_cm_iclken;
-	u32 dss_cm_iclken;
-	u32 cam_cm_iclken;
-	u32 per_cm_iclken;
-	u32 usbhost_cm_iclken;
-	u32 iva2_cm_autoidle2;
-	u32 mpu_cm_autoidle2;
-	u32 iva2_cm_clkstctrl;
-	u32 mpu_cm_clkstctrl;
-	u32 core_cm_clkstctrl;
-	u32 sgx_cm_clkstctrl;
-	u32 dss_cm_clkstctrl;
-	u32 cam_cm_clkstctrl;
-	u32 per_cm_clkstctrl;
-	u32 neon_cm_clkstctrl;
-	u32 usbhost_cm_clkstctrl;
-	u32 core_cm_autoidle1;
-	u32 core_cm_autoidle2;
-	u32 core_cm_autoidle3;
-	u32 wkup_cm_autoidle;
-	u32 dss_cm_autoidle;
-	u32 cam_cm_autoidle;
-	u32 per_cm_autoidle;
-	u32 usbhost_cm_autoidle;
-	u32 sgx_cm_sleepdep;
-	u32 dss_cm_sleepdep;
-	u32 cam_cm_sleepdep;
-	u32 per_cm_sleepdep;
-	u32 usbhost_cm_sleepdep;
-	u32 cm_clkout_ctrl;
-};
-
-static struct omap3_cm_regs cm_context;
-
-void omap3_cm_save_context(void)
-{
-	cm_context.iva2_cm_clksel1 =
-		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL1);
-	cm_context.iva2_cm_clksel2 =
-		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL2);
-	cm_context.cm_sysconfig = __raw_readl(OMAP3430_CM_SYSCONFIG);
-	cm_context.sgx_cm_clksel =
-		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_CLKSEL);
-	cm_context.dss_cm_clksel =
-		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_CLKSEL);
-	cm_context.cam_cm_clksel =
-		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_CLKSEL);
-	cm_context.per_cm_clksel =
-		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_CLKSEL);
-	cm_context.emu_cm_clksel =
-		omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
-	cm_context.emu_cm_clkstctrl =
-		omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
-	/*
-	 * As per erratum i671, ROM code does not respect the PER DPLL
-	 * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
-	 * In this case, even though this register has been saved in
-	 * scratchpad contents, we need to restore AUTO_PERIPH_DPLL
-	 * by ourselves. So, we need to save it anyway.
-	 */
-	cm_context.pll_cm_autoidle =
-		omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
-	cm_context.pll_cm_autoidle2 =
-		omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
-	cm_context.pll_cm_clksel4 =
-		omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL4);
-	cm_context.pll_cm_clksel5 =
-		omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL5);
-	cm_context.pll_cm_clken2 =
-		omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKEN2);
-	cm_context.cm_polctrl = __raw_readl(OMAP3430_CM_POLCTRL);
-	cm_context.iva2_cm_fclken =
-		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_FCLKEN);
-	cm_context.iva2_cm_clken_pll =
-		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL);
-	cm_context.core_cm_fclken1 =
-		omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
-	cm_context.core_cm_fclken3 =
-		omap2_cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
-	cm_context.sgx_cm_fclken =
-		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_FCLKEN);
-	cm_context.wkup_cm_fclken =
-		omap2_cm_read_mod_reg(WKUP_MOD, CM_FCLKEN);
-	cm_context.dss_cm_fclken =
-		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_FCLKEN);
-	cm_context.cam_cm_fclken =
-		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_FCLKEN);
-	cm_context.per_cm_fclken =
-		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN);
-	cm_context.usbhost_cm_fclken =
-		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
-	cm_context.core_cm_iclken1 =
-		omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN1);
-	cm_context.core_cm_iclken2 =
-		omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN2);
-	cm_context.core_cm_iclken3 =
-		omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN3);
-	cm_context.sgx_cm_iclken =
-		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_ICLKEN);
-	cm_context.wkup_cm_iclken =
-		omap2_cm_read_mod_reg(WKUP_MOD, CM_ICLKEN);
-	cm_context.dss_cm_iclken =
-		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_ICLKEN);
-	cm_context.cam_cm_iclken =
-		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_ICLKEN);
-	cm_context.per_cm_iclken =
-		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN);
-	cm_context.usbhost_cm_iclken =
-		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
-	cm_context.iva2_cm_autoidle2 =
-		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
-	cm_context.mpu_cm_autoidle2 =
-		omap2_cm_read_mod_reg(MPU_MOD, CM_AUTOIDLE2);
-	cm_context.iva2_cm_clkstctrl =
-		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP2_CM_CLKSTCTRL);
-	cm_context.mpu_cm_clkstctrl =
-		omap2_cm_read_mod_reg(MPU_MOD, OMAP2_CM_CLKSTCTRL);
-	cm_context.core_cm_clkstctrl =
-		omap2_cm_read_mod_reg(CORE_MOD, OMAP2_CM_CLKSTCTRL);
-	cm_context.sgx_cm_clkstctrl =
-		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, OMAP2_CM_CLKSTCTRL);
-	cm_context.dss_cm_clkstctrl =
-		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP2_CM_CLKSTCTRL);
-	cm_context.cam_cm_clkstctrl =
-		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP2_CM_CLKSTCTRL);
-	cm_context.per_cm_clkstctrl =
-		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, OMAP2_CM_CLKSTCTRL);
-	cm_context.neon_cm_clkstctrl =
-		omap2_cm_read_mod_reg(OMAP3430_NEON_MOD, OMAP2_CM_CLKSTCTRL);
-	cm_context.usbhost_cm_clkstctrl =
-		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
-				      OMAP2_CM_CLKSTCTRL);
-	cm_context.core_cm_autoidle1 =
-		omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE1);
-	cm_context.core_cm_autoidle2 =
-		omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE2);
-	cm_context.core_cm_autoidle3 =
-		omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE3);
-	cm_context.wkup_cm_autoidle =
-		omap2_cm_read_mod_reg(WKUP_MOD, CM_AUTOIDLE);
-	cm_context.dss_cm_autoidle =
-		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_AUTOIDLE);
-	cm_context.cam_cm_autoidle =
-		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_AUTOIDLE);
-	cm_context.per_cm_autoidle =
-		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
-	cm_context.usbhost_cm_autoidle =
-		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
-	cm_context.sgx_cm_sleepdep =
-		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD,
-				      OMAP3430_CM_SLEEPDEP);
-	cm_context.dss_cm_sleepdep =
-		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP3430_CM_SLEEPDEP);
-	cm_context.cam_cm_sleepdep =
-		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP3430_CM_SLEEPDEP);
-	cm_context.per_cm_sleepdep =
-		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, OMAP3430_CM_SLEEPDEP);
-	cm_context.usbhost_cm_sleepdep =
-		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
-				      OMAP3430_CM_SLEEPDEP);
-	cm_context.cm_clkout_ctrl =
-		omap2_cm_read_mod_reg(OMAP3430_CCR_MOD,
-				      OMAP3_CM_CLKOUT_CTRL_OFFSET);
-}
-
-void omap3_cm_restore_context(void)
-{
-	omap2_cm_write_mod_reg(cm_context.iva2_cm_clksel1, OMAP3430_IVA2_MOD,
-			       CM_CLKSEL1);
-	omap2_cm_write_mod_reg(cm_context.iva2_cm_clksel2, OMAP3430_IVA2_MOD,
-			       CM_CLKSEL2);
-	__raw_writel(cm_context.cm_sysconfig, OMAP3430_CM_SYSCONFIG);
-	omap2_cm_write_mod_reg(cm_context.sgx_cm_clksel, OMAP3430ES2_SGX_MOD,
-			       CM_CLKSEL);
-	omap2_cm_write_mod_reg(cm_context.dss_cm_clksel, OMAP3430_DSS_MOD,
-			       CM_CLKSEL);
-	omap2_cm_write_mod_reg(cm_context.cam_cm_clksel, OMAP3430_CAM_MOD,
-			       CM_CLKSEL);
-	omap2_cm_write_mod_reg(cm_context.per_cm_clksel, OMAP3430_PER_MOD,
-			       CM_CLKSEL);
-	omap2_cm_write_mod_reg(cm_context.emu_cm_clksel, OMAP3430_EMU_MOD,
-			       CM_CLKSEL1);
-	omap2_cm_write_mod_reg(cm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD,
-			       OMAP2_CM_CLKSTCTRL);
-	/*
-	 * As per erratum i671, ROM code does not respect the PER DPLL
-	 * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
-	 * In this case, we need to restore AUTO_PERIPH_DPLL by ourselves.
-	 */
-	omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle, PLL_MOD,
-			       CM_AUTOIDLE);
-	omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle2, PLL_MOD,
-			       CM_AUTOIDLE2);
-	omap2_cm_write_mod_reg(cm_context.pll_cm_clksel4, PLL_MOD,
-			       OMAP3430ES2_CM_CLKSEL4);
-	omap2_cm_write_mod_reg(cm_context.pll_cm_clksel5, PLL_MOD,
-			       OMAP3430ES2_CM_CLKSEL5);
-	omap2_cm_write_mod_reg(cm_context.pll_cm_clken2, PLL_MOD,
-			       OMAP3430ES2_CM_CLKEN2);
-	__raw_writel(cm_context.cm_polctrl, OMAP3430_CM_POLCTRL);
-	omap2_cm_write_mod_reg(cm_context.iva2_cm_fclken, OMAP3430_IVA2_MOD,
-			       CM_FCLKEN);
-	omap2_cm_write_mod_reg(cm_context.iva2_cm_clken_pll, OMAP3430_IVA2_MOD,
-			       OMAP3430_CM_CLKEN_PLL);
-	omap2_cm_write_mod_reg(cm_context.core_cm_fclken1, CORE_MOD,
-			       CM_FCLKEN1);
-	omap2_cm_write_mod_reg(cm_context.core_cm_fclken3, CORE_MOD,
-			       OMAP3430ES2_CM_FCLKEN3);
-	omap2_cm_write_mod_reg(cm_context.sgx_cm_fclken, OMAP3430ES2_SGX_MOD,
-			       CM_FCLKEN);
-	omap2_cm_write_mod_reg(cm_context.wkup_cm_fclken, WKUP_MOD, CM_FCLKEN);
-	omap2_cm_write_mod_reg(cm_context.dss_cm_fclken, OMAP3430_DSS_MOD,
-			       CM_FCLKEN);
-	omap2_cm_write_mod_reg(cm_context.cam_cm_fclken, OMAP3430_CAM_MOD,
-			       CM_FCLKEN);
-	omap2_cm_write_mod_reg(cm_context.per_cm_fclken, OMAP3430_PER_MOD,
-			       CM_FCLKEN);
-	omap2_cm_write_mod_reg(cm_context.usbhost_cm_fclken,
-			       OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
-	omap2_cm_write_mod_reg(cm_context.core_cm_iclken1, CORE_MOD,
-			       CM_ICLKEN1);
-	omap2_cm_write_mod_reg(cm_context.core_cm_iclken2, CORE_MOD,
-			       CM_ICLKEN2);
-	omap2_cm_write_mod_reg(cm_context.core_cm_iclken3, CORE_MOD,
-			       CM_ICLKEN3);
-	omap2_cm_write_mod_reg(cm_context.sgx_cm_iclken, OMAP3430ES2_SGX_MOD,
-			       CM_ICLKEN);
-	omap2_cm_write_mod_reg(cm_context.wkup_cm_iclken, WKUP_MOD, CM_ICLKEN);
-	omap2_cm_write_mod_reg(cm_context.dss_cm_iclken, OMAP3430_DSS_MOD,
-			       CM_ICLKEN);
-	omap2_cm_write_mod_reg(cm_context.cam_cm_iclken, OMAP3430_CAM_MOD,
-			       CM_ICLKEN);
-	omap2_cm_write_mod_reg(cm_context.per_cm_iclken, OMAP3430_PER_MOD,
-			       CM_ICLKEN);
-	omap2_cm_write_mod_reg(cm_context.usbhost_cm_iclken,
-			       OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
-	omap2_cm_write_mod_reg(cm_context.iva2_cm_autoidle2, OMAP3430_IVA2_MOD,
-			       CM_AUTOIDLE2);
-	omap2_cm_write_mod_reg(cm_context.mpu_cm_autoidle2, MPU_MOD,
-			       CM_AUTOIDLE2);
-	omap2_cm_write_mod_reg(cm_context.iva2_cm_clkstctrl, OMAP3430_IVA2_MOD,
-			       OMAP2_CM_CLKSTCTRL);
-	omap2_cm_write_mod_reg(cm_context.mpu_cm_clkstctrl, MPU_MOD,
-			       OMAP2_CM_CLKSTCTRL);
-	omap2_cm_write_mod_reg(cm_context.core_cm_clkstctrl, CORE_MOD,
-			       OMAP2_CM_CLKSTCTRL);
-	omap2_cm_write_mod_reg(cm_context.sgx_cm_clkstctrl, OMAP3430ES2_SGX_MOD,
-			       OMAP2_CM_CLKSTCTRL);
-	omap2_cm_write_mod_reg(cm_context.dss_cm_clkstctrl, OMAP3430_DSS_MOD,
-			       OMAP2_CM_CLKSTCTRL);
-	omap2_cm_write_mod_reg(cm_context.cam_cm_clkstctrl, OMAP3430_CAM_MOD,
-			       OMAP2_CM_CLKSTCTRL);
-	omap2_cm_write_mod_reg(cm_context.per_cm_clkstctrl, OMAP3430_PER_MOD,
-			       OMAP2_CM_CLKSTCTRL);
-	omap2_cm_write_mod_reg(cm_context.neon_cm_clkstctrl, OMAP3430_NEON_MOD,
-			       OMAP2_CM_CLKSTCTRL);
-	omap2_cm_write_mod_reg(cm_context.usbhost_cm_clkstctrl,
-			       OMAP3430ES2_USBHOST_MOD, OMAP2_CM_CLKSTCTRL);
-	omap2_cm_write_mod_reg(cm_context.core_cm_autoidle1, CORE_MOD,
-			       CM_AUTOIDLE1);
-	omap2_cm_write_mod_reg(cm_context.core_cm_autoidle2, CORE_MOD,
-			       CM_AUTOIDLE2);
-	omap2_cm_write_mod_reg(cm_context.core_cm_autoidle3, CORE_MOD,
-			       CM_AUTOIDLE3);
-	omap2_cm_write_mod_reg(cm_context.wkup_cm_autoidle, WKUP_MOD,
-			       CM_AUTOIDLE);
-	omap2_cm_write_mod_reg(cm_context.dss_cm_autoidle, OMAP3430_DSS_MOD,
-			       CM_AUTOIDLE);
-	omap2_cm_write_mod_reg(cm_context.cam_cm_autoidle, OMAP3430_CAM_MOD,
-			       CM_AUTOIDLE);
-	omap2_cm_write_mod_reg(cm_context.per_cm_autoidle, OMAP3430_PER_MOD,
-			       CM_AUTOIDLE);
-	omap2_cm_write_mod_reg(cm_context.usbhost_cm_autoidle,
-			       OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
-	omap2_cm_write_mod_reg(cm_context.sgx_cm_sleepdep, OMAP3430ES2_SGX_MOD,
-			       OMAP3430_CM_SLEEPDEP);
-	omap2_cm_write_mod_reg(cm_context.dss_cm_sleepdep, OMAP3430_DSS_MOD,
-			       OMAP3430_CM_SLEEPDEP);
-	omap2_cm_write_mod_reg(cm_context.cam_cm_sleepdep, OMAP3430_CAM_MOD,
-			       OMAP3430_CM_SLEEPDEP);
-	omap2_cm_write_mod_reg(cm_context.per_cm_sleepdep, OMAP3430_PER_MOD,
-			       OMAP3430_CM_SLEEPDEP);
-	omap2_cm_write_mod_reg(cm_context.usbhost_cm_sleepdep,
-			       OMAP3430ES2_USBHOST_MOD, OMAP3430_CM_SLEEPDEP);
-	omap2_cm_write_mod_reg(cm_context.cm_clkout_ctrl, OMAP3430_CCR_MOD,
-			       OMAP3_CM_CLKOUT_CTRL_OFFSET);
-}
-#endif
diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.h b/arch/arm/mach-omap2/cm2xxx_3xxx.h
index 57b2f3c..bfbd16f 100644
--- a/arch/arm/mach-omap2/cm2xxx_3xxx.h
+++ b/arch/arm/mach-omap2/cm2xxx_3xxx.h
@@ -16,28 +16,7 @@
 #ifndef __ARCH_ASM_MACH_OMAP2_CM2XXX_3XXX_H
 #define __ARCH_ASM_MACH_OMAP2_CM2XXX_3XXX_H
 
-#include "prcm-common.h"
-
-#define OMAP2420_CM_REGADDR(module, reg)				\
-			OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE + (module) + (reg))
-#define OMAP2430_CM_REGADDR(module, reg)				\
-			OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE + (module) + (reg))
-#define OMAP34XX_CM_REGADDR(module, reg)				\
-			OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE + (module) + (reg))
-
-
-/*
- * OMAP3-specific global CM registers
- * Use cm_{read,write}_reg() with these registers.
- * These registers appear once per CM module.
- */
-
-#define OMAP3430_CM_REVISION		OMAP34XX_CM_REGADDR(OCP_MOD, 0x0000)
-#define OMAP3430_CM_SYSCONFIG		OMAP34XX_CM_REGADDR(OCP_MOD, 0x0010)
-#define OMAP3430_CM_POLCTRL		OMAP34XX_CM_REGADDR(OCP_MOD, 0x009c)
-
-#define OMAP3_CM_CLKOUT_CTRL_OFFSET	0x0070
-#define OMAP3430_CM_CLKOUT_CTRL		OMAP_CM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
+#include "cm.h"
 
 /*
  * Module specific CM register offsets from CM_BASE + domain offset
@@ -57,6 +36,7 @@
 #define CM_IDLEST					0x0020
 #define CM_IDLEST1					CM_IDLEST
 #define CM_IDLEST2					0x0024
+#define OMAP2430_CM_IDLEST3				0x0028
 #define CM_AUTOIDLE					0x0030
 #define CM_AUTOIDLE1					CM_AUTOIDLE
 #define CM_AUTOIDLE2					0x0034
@@ -66,70 +46,60 @@
 #define CM_CLKSEL2					0x0044
 #define OMAP2_CM_CLKSTCTRL				0x0048
 
-/* OMAP2-specific register offsets */
-
-#define OMAP24XX_CM_FCLKEN2				0x0004
-#define OMAP24XX_CM_ICLKEN4				0x001c
-#define OMAP24XX_CM_AUTOIDLE4				0x003c
-#define OMAP24XX_CM_IDLEST4				0x002c
-
-#define OMAP2430_CM_IDLEST3				0x0028
-
-/* OMAP3-specific register offsets */
-
-#define OMAP3430_CM_CLKEN_PLL				0x0004
-#define OMAP3430ES2_CM_CLKEN2				0x0004
-#define OMAP3430ES2_CM_FCLKEN3				0x0008
-#define OMAP3430_CM_IDLEST_PLL				CM_IDLEST2
-#define OMAP3430_CM_AUTOIDLE_PLL			CM_AUTOIDLE2
-#define OMAP3430ES2_CM_AUTOIDLE2_PLL			CM_AUTOIDLE2
-#define OMAP3430_CM_CLKSEL1				CM_CLKSEL
-#define OMAP3430_CM_CLKSEL1_PLL				CM_CLKSEL
-#define OMAP3430_CM_CLKSEL2_PLL				CM_CLKSEL2
-#define OMAP3430_CM_SLEEPDEP				CM_CLKSEL2
-#define OMAP3430_CM_CLKSEL3				OMAP2_CM_CLKSTCTRL
-#define OMAP3430_CM_CLKSTST				0x004c
-#define OMAP3430ES2_CM_CLKSEL4				0x004c
-#define OMAP3430ES2_CM_CLKSEL5				0x0050
-#define OMAP3430_CM_CLKSEL2_EMU				0x0050
-#define OMAP3430_CM_CLKSEL3_EMU				0x0054
+#ifndef __ASSEMBLER__
 
+#include <linux/io.h>
 
-/* CM_IDLEST bit field values to indicate deasserted IdleReq */
+static inline u32 omap2_cm_read_mod_reg(s16 module, u16 idx)
+{
+	return __raw_readl(cm_base + module + idx);
+}
 
-#define OMAP24XX_CM_IDLEST_VAL				0
-#define OMAP34XX_CM_IDLEST_VAL				1
+static inline void omap2_cm_write_mod_reg(u32 val, s16 module, u16 idx)
+{
+	__raw_writel(val, cm_base + module + idx);
+}
 
+/* Read-modify-write a register in a CM module. Caller must lock */
+static inline u32 omap2_cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module,
+					    s16 idx)
+{
+	u32 v;
 
-/* Clock management domain register get/set */
+	v = omap2_cm_read_mod_reg(module, idx);
+	v &= ~mask;
+	v |= bits;
+	omap2_cm_write_mod_reg(v, module, idx);
 
-#ifndef __ASSEMBLER__
+	return v;
+}
 
-extern u32 omap2_cm_read_mod_reg(s16 module, u16 idx);
-extern void omap2_cm_write_mod_reg(u32 val, s16 module, u16 idx);
-extern u32 omap2_cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
+/* Read a CM register, AND it, and shift the result down to bit 0 */
+static inline u32 omap2_cm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
+{
+	u32 v;
 
-extern int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id,
-				      u8 idlest_shift);
-extern u32 omap2_cm_set_mod_reg_bits(u32 bits, s16 module, s16 idx);
-extern u32 omap2_cm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx);
+	v = omap2_cm_read_mod_reg(domain, idx);
+	v &= mask;
+	v >>= __ffs(mask);
 
-extern bool omap2_cm_is_clkdm_in_hwsup(s16 module, u32 mask);
-extern void omap2xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask);
-extern void omap2xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask);
+	return v;
+}
 
-extern void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask);
-extern void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask);
-extern void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask);
-extern void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask);
+static inline u32 omap2_cm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
+{
+	return omap2_cm_rmw_mod_reg_bits(bits, bits, module, idx);
+}
 
-extern void omap2xxx_cm_set_dpll_disable_autoidle(void);
-extern void omap2xxx_cm_set_dpll_auto_low_power_stop(void);
+static inline u32 omap2_cm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
+{
+	return omap2_cm_rmw_mod_reg_bits(bits, 0x0, module, idx);
+}
 
-extern void omap2xxx_cm_set_apll54_disable_autoidle(void);
-extern void omap2xxx_cm_set_apll54_auto_low_power_stop(void);
-extern void omap2xxx_cm_set_apll96_disable_autoidle(void);
-extern void omap2xxx_cm_set_apll96_auto_low_power_stop(void);
+extern int omap2xxx_cm_apll54_enable(void);
+extern void omap2xxx_cm_apll54_disable(void);
+extern int omap2xxx_cm_apll96_enable(void);
+extern void omap2xxx_cm_apll96_disable(void);
 
 #endif
 
@@ -138,6 +108,7 @@ extern void omap2xxx_cm_set_apll96_auto_low_power_stop(void);
 /* CM_CLKSEL_GFX */
 #define OMAP_CLKSEL_GFX_SHIFT				0
 #define OMAP_CLKSEL_GFX_MASK				(0x7 << 0)
+#define OMAP_CLKSEL_GFX_WIDTH				3
 
 /* CM_ICLKEN_GFX */
 #define OMAP_EN_GFX_SHIFT				0
@@ -146,11 +117,4 @@ extern void omap2xxx_cm_set_apll96_auto_low_power_stop(void);
 /* CM_IDLEST_GFX */
 #define OMAP_ST_GFX_MASK				(1 << 0)
 
-
-/* Function prototypes */
-# ifndef __ASSEMBLER__
-extern void omap3_cm_save_context(void);
-extern void omap3_cm_restore_context(void);
-# endif
-
 #endif
diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c
index 13f56ea..058ce3c 100644
--- a/arch/arm/mach-omap2/cm33xx.c
+++ b/arch/arm/mach-omap2/cm33xx.c
@@ -22,8 +22,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 
-#include <plat/common.h>
-
+#include "clockdomain.h"
 #include "cm.h"
 #include "cm33xx.h"
 #include "cm-regbits-34xx.h"
@@ -311,3 +310,58 @@ void am33xx_cm_module_disable(u16 inst, s16 cdoffs, u16 clkctrl_offs)
 	v &= ~AM33XX_MODULEMODE_MASK;
 	am33xx_cm_write_reg(v, inst, clkctrl_offs);
 }
+
+/*
+ * Clockdomain low-level functions
+ */
+
+static int am33xx_clkdm_sleep(struct clockdomain *clkdm)
+{
+	am33xx_cm_clkdm_force_sleep(clkdm->cm_inst, clkdm->clkdm_offs);
+	return 0;
+}
+
+static int am33xx_clkdm_wakeup(struct clockdomain *clkdm)
+{
+	am33xx_cm_clkdm_force_wakeup(clkdm->cm_inst, clkdm->clkdm_offs);
+	return 0;
+}
+
+static void am33xx_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+	am33xx_cm_clkdm_enable_hwsup(clkdm->cm_inst, clkdm->clkdm_offs);
+}
+
+static void am33xx_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+	am33xx_cm_clkdm_disable_hwsup(clkdm->cm_inst, clkdm->clkdm_offs);
+}
+
+static int am33xx_clkdm_clk_enable(struct clockdomain *clkdm)
+{
+	if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+		return am33xx_clkdm_wakeup(clkdm);
+
+	return 0;
+}
+
+static int am33xx_clkdm_clk_disable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	hwsup = am33xx_cm_is_clkdm_in_hwsup(clkdm->cm_inst, clkdm->clkdm_offs);
+
+	if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
+		am33xx_clkdm_sleep(clkdm);
+
+	return 0;
+}
+
+struct clkdm_ops am33xx_clkdm_operations = {
+	.clkdm_sleep		= am33xx_clkdm_sleep,
+	.clkdm_wakeup		= am33xx_clkdm_wakeup,
+	.clkdm_allow_idle	= am33xx_clkdm_allow_idle,
+	.clkdm_deny_idle	= am33xx_clkdm_deny_idle,
+	.clkdm_clk_enable	= am33xx_clkdm_clk_enable,
+	.clkdm_clk_disable	= am33xx_clkdm_clk_disable,
+};
diff --git a/arch/arm/mach-omap2/cm3xxx.c b/arch/arm/mach-omap2/cm3xxx.c
new file mode 100644
index 0000000..c2086f2
--- /dev/null
+++ b/arch/arm/mach-omap2/cm3xxx.c
@@ -0,0 +1,665 @@
+/*
+ * OMAP3xxx CM module functions
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2008-2010, 2012 Texas Instruments, Inc.
+ * Paul Walmsley
+ * Rajendra Nayak <rnayak@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include "soc.h"
+#include "iomap.h"
+#include "common.h"
+#include "prm2xxx_3xxx.h"
+#include "cm.h"
+#include "cm3xxx.h"
+#include "cm-regbits-34xx.h"
+#include "clockdomain.h"
+
+static const u8 omap3xxx_cm_idlest_offs[] = {
+	CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3
+};
+
+/*
+ *
+ */
+
+static void _write_clktrctrl(u8 c, s16 module, u32 mask)
+{
+	u32 v;
+
+	v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
+	v &= ~mask;
+	v |= c << __ffs(mask);
+	omap2_cm_write_mod_reg(v, module, OMAP2_CM_CLKSTCTRL);
+}
+
+bool omap3xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
+{
+	u32 v;
+
+	v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
+	v &= mask;
+	v >>= __ffs(mask);
+
+	return (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
+}
+
+void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
+{
+	_write_clktrctrl(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, module, mask);
+}
+
+void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
+{
+	_write_clktrctrl(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, module, mask);
+}
+
+void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask)
+{
+	_write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, module, mask);
+}
+
+void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask)
+{
+	_write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, module, mask);
+}
+
+/*
+ *
+ */
+
+/**
+ * omap3xxx_cm_wait_module_ready - wait for a module to leave idle or standby
+ * @prcm_mod: PRCM module offset
+ * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
+ * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
+ *
+ * Wait for the PRCM to indicate that the module identified by
+ * (@prcm_mod, @idlest_id, @idlest_shift) is clocked.  Return 0 upon
+ * success or -EBUSY if the module doesn't enable in time.
+ */
+int omap3xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
+{
+	int ena = 0, i = 0;
+	u8 cm_idlest_reg;
+	u32 mask;
+
+	if (!idlest_id || (idlest_id > ARRAY_SIZE(omap3xxx_cm_idlest_offs)))
+		return -EINVAL;
+
+	cm_idlest_reg = omap3xxx_cm_idlest_offs[idlest_id - 1];
+
+	mask = 1 << idlest_shift;
+	ena = 0;
+
+	omap_test_timeout(((omap2_cm_read_mod_reg(prcm_mod, cm_idlest_reg) &
+			    mask) == ena), MAX_MODULE_READY_TIME, i);
+
+	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
+}
+
+/**
+ * omap3xxx_cm_split_idlest_reg - split CM_IDLEST reg addr into its components
+ * @idlest_reg: CM_IDLEST* virtual address
+ * @prcm_inst: pointer to an s16 to return the PRCM instance offset
+ * @idlest_reg_id: pointer to a u8 to return the CM_IDLESTx register ID
+ *
+ * XXX This function is only needed until absolute register addresses are
+ * removed from the OMAP struct clk records.
+ */
+int omap3xxx_cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
+				 u8 *idlest_reg_id)
+{
+	unsigned long offs;
+	u8 idlest_offs;
+	int i;
+
+	if (idlest_reg < (cm_base + OMAP3430_IVA2_MOD) ||
+	    idlest_reg > (cm_base + 0x1ffff))
+		return -EINVAL;
+
+	idlest_offs = (unsigned long)idlest_reg & 0xff;
+	for (i = 0; i < ARRAY_SIZE(omap3xxx_cm_idlest_offs); i++) {
+		if (idlest_offs == omap3xxx_cm_idlest_offs[i]) {
+			*idlest_reg_id = i + 1;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(omap3xxx_cm_idlest_offs))
+		return -EINVAL;
+
+	offs = idlest_reg - cm_base;
+	offs &= 0xff00;
+	*prcm_inst = offs;
+
+	return 0;
+}
+
+/* Clockdomain low-level operations */
+
+static int omap3xxx_clkdm_add_sleepdep(struct clockdomain *clkdm1,
+				       struct clockdomain *clkdm2)
+{
+	omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+				  clkdm1->pwrdm.ptr->prcm_offs,
+				  OMAP3430_CM_SLEEPDEP);
+	return 0;
+}
+
+static int omap3xxx_clkdm_del_sleepdep(struct clockdomain *clkdm1,
+				       struct clockdomain *clkdm2)
+{
+	omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+				    clkdm1->pwrdm.ptr->prcm_offs,
+				    OMAP3430_CM_SLEEPDEP);
+	return 0;
+}
+
+static int omap3xxx_clkdm_read_sleepdep(struct clockdomain *clkdm1,
+					struct clockdomain *clkdm2)
+{
+	return omap2_cm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
+					    OMAP3430_CM_SLEEPDEP,
+					    (1 << clkdm2->dep_bit));
+}
+
+static int omap3xxx_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
+{
+	struct clkdm_dep *cd;
+	u32 mask = 0;
+
+	for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
+		if (!cd->clkdm)
+			continue; /* only happens if data is erroneous */
+
+		mask |= 1 << cd->clkdm->dep_bit;
+		atomic_set(&cd->sleepdep_usecount, 0);
+	}
+	omap2_cm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
+				    OMAP3430_CM_SLEEPDEP);
+	return 0;
+}
+
+static int omap3xxx_clkdm_sleep(struct clockdomain *clkdm)
+{
+	omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
+				      clkdm->clktrctrl_mask);
+	return 0;
+}
+
+static int omap3xxx_clkdm_wakeup(struct clockdomain *clkdm)
+{
+	omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
+				       clkdm->clktrctrl_mask);
+	return 0;
+}
+
+static void omap3xxx_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+	if (atomic_read(&clkdm->usecount) > 0)
+		_clkdm_add_autodeps(clkdm);
+
+	omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				       clkdm->clktrctrl_mask);
+}
+
+static void omap3xxx_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+	omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					clkdm->clktrctrl_mask);
+
+	if (atomic_read(&clkdm->usecount) > 0)
+		_clkdm_del_autodeps(clkdm);
+}
+
+static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	if (!clkdm->clktrctrl_mask)
+		return 0;
+
+	/*
+	 * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
+	 * more details on the unpleasant problem this is working
+	 * around
+	 */
+	if ((clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) &&
+	    (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
+		omap3xxx_clkdm_wakeup(clkdm);
+		return 0;
+	}
+
+	hwsup = omap3xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					      clkdm->clktrctrl_mask);
+
+	if (hwsup) {
+		/* Disable HW transitions when we are changing deps */
+		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+						clkdm->clktrctrl_mask);
+		_clkdm_add_autodeps(clkdm);
+		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					       clkdm->clktrctrl_mask);
+	} else {
+		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+			omap3xxx_clkdm_wakeup(clkdm);
+	}
+
+	return 0;
+}
+
+static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	if (!clkdm->clktrctrl_mask)
+		return 0;
+
+	/*
+	 * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
+	 * more details on the unpleasant problem this is working
+	 * around
+	 */
+	if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
+	    !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
+		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					       clkdm->clktrctrl_mask);
+		return 0;
+	}
+
+	hwsup = omap3xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					      clkdm->clktrctrl_mask);
+
+	if (hwsup) {
+		/* Disable HW transitions when we are changing deps */
+		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+						clkdm->clktrctrl_mask);
+		_clkdm_del_autodeps(clkdm);
+		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					       clkdm->clktrctrl_mask);
+	} else {
+		if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
+			omap3xxx_clkdm_sleep(clkdm);
+	}
+
+	return 0;
+}
+
+struct clkdm_ops omap3_clkdm_operations = {
+	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
+	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
+	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
+	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
+	.clkdm_add_sleepdep	= omap3xxx_clkdm_add_sleepdep,
+	.clkdm_del_sleepdep	= omap3xxx_clkdm_del_sleepdep,
+	.clkdm_read_sleepdep	= omap3xxx_clkdm_read_sleepdep,
+	.clkdm_clear_all_sleepdeps	= omap3xxx_clkdm_clear_all_sleepdeps,
+	.clkdm_sleep		= omap3xxx_clkdm_sleep,
+	.clkdm_wakeup		= omap3xxx_clkdm_wakeup,
+	.clkdm_allow_idle	= omap3xxx_clkdm_allow_idle,
+	.clkdm_deny_idle	= omap3xxx_clkdm_deny_idle,
+	.clkdm_clk_enable	= omap3xxx_clkdm_clk_enable,
+	.clkdm_clk_disable	= omap3xxx_clkdm_clk_disable,
+};
+
+/*
+ * Context save/restore code - OMAP3 only
+ */
+struct omap3_cm_regs {
+	u32 iva2_cm_clksel1;
+	u32 iva2_cm_clksel2;
+	u32 cm_sysconfig;
+	u32 sgx_cm_clksel;
+	u32 dss_cm_clksel;
+	u32 cam_cm_clksel;
+	u32 per_cm_clksel;
+	u32 emu_cm_clksel;
+	u32 emu_cm_clkstctrl;
+	u32 pll_cm_autoidle;
+	u32 pll_cm_autoidle2;
+	u32 pll_cm_clksel4;
+	u32 pll_cm_clksel5;
+	u32 pll_cm_clken2;
+	u32 cm_polctrl;
+	u32 iva2_cm_fclken;
+	u32 iva2_cm_clken_pll;
+	u32 core_cm_fclken1;
+	u32 core_cm_fclken3;
+	u32 sgx_cm_fclken;
+	u32 wkup_cm_fclken;
+	u32 dss_cm_fclken;
+	u32 cam_cm_fclken;
+	u32 per_cm_fclken;
+	u32 usbhost_cm_fclken;
+	u32 core_cm_iclken1;
+	u32 core_cm_iclken2;
+	u32 core_cm_iclken3;
+	u32 sgx_cm_iclken;
+	u32 wkup_cm_iclken;
+	u32 dss_cm_iclken;
+	u32 cam_cm_iclken;
+	u32 per_cm_iclken;
+	u32 usbhost_cm_iclken;
+	u32 iva2_cm_autoidle2;
+	u32 mpu_cm_autoidle2;
+	u32 iva2_cm_clkstctrl;
+	u32 mpu_cm_clkstctrl;
+	u32 core_cm_clkstctrl;
+	u32 sgx_cm_clkstctrl;
+	u32 dss_cm_clkstctrl;
+	u32 cam_cm_clkstctrl;
+	u32 per_cm_clkstctrl;
+	u32 neon_cm_clkstctrl;
+	u32 usbhost_cm_clkstctrl;
+	u32 core_cm_autoidle1;
+	u32 core_cm_autoidle2;
+	u32 core_cm_autoidle3;
+	u32 wkup_cm_autoidle;
+	u32 dss_cm_autoidle;
+	u32 cam_cm_autoidle;
+	u32 per_cm_autoidle;
+	u32 usbhost_cm_autoidle;
+	u32 sgx_cm_sleepdep;
+	u32 dss_cm_sleepdep;
+	u32 cam_cm_sleepdep;
+	u32 per_cm_sleepdep;
+	u32 usbhost_cm_sleepdep;
+	u32 cm_clkout_ctrl;
+};
+
+static struct omap3_cm_regs cm_context;
+
+void omap3_cm_save_context(void)
+{
+	cm_context.iva2_cm_clksel1 =
+		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL1);
+	cm_context.iva2_cm_clksel2 =
+		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL2);
+	cm_context.cm_sysconfig = __raw_readl(OMAP3430_CM_SYSCONFIG);
+	cm_context.sgx_cm_clksel =
+		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_CLKSEL);
+	cm_context.dss_cm_clksel =
+		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_CLKSEL);
+	cm_context.cam_cm_clksel =
+		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_CLKSEL);
+	cm_context.per_cm_clksel =
+		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_CLKSEL);
+	cm_context.emu_cm_clksel =
+		omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
+	cm_context.emu_cm_clkstctrl =
+		omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
+	/*
+	 * As per erratum i671, ROM code does not respect the PER DPLL
+	 * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
+	 * In this case, even though this register has been saved in
+	 * scratchpad contents, we need to restore AUTO_PERIPH_DPLL
+	 * by ourselves. So, we need to save it anyway.
+	 */
+	cm_context.pll_cm_autoidle =
+		omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
+	cm_context.pll_cm_autoidle2 =
+		omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
+	cm_context.pll_cm_clksel4 =
+		omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL4);
+	cm_context.pll_cm_clksel5 =
+		omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL5);
+	cm_context.pll_cm_clken2 =
+		omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKEN2);
+	cm_context.cm_polctrl = __raw_readl(OMAP3430_CM_POLCTRL);
+	cm_context.iva2_cm_fclken =
+		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_FCLKEN);
+	cm_context.iva2_cm_clken_pll =
+		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL);
+	cm_context.core_cm_fclken1 =
+		omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
+	cm_context.core_cm_fclken3 =
+		omap2_cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
+	cm_context.sgx_cm_fclken =
+		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_FCLKEN);
+	cm_context.wkup_cm_fclken =
+		omap2_cm_read_mod_reg(WKUP_MOD, CM_FCLKEN);
+	cm_context.dss_cm_fclken =
+		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_FCLKEN);
+	cm_context.cam_cm_fclken =
+		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_FCLKEN);
+	cm_context.per_cm_fclken =
+		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN);
+	cm_context.usbhost_cm_fclken =
+		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
+	cm_context.core_cm_iclken1 =
+		omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN1);
+	cm_context.core_cm_iclken2 =
+		omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN2);
+	cm_context.core_cm_iclken3 =
+		omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN3);
+	cm_context.sgx_cm_iclken =
+		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_ICLKEN);
+	cm_context.wkup_cm_iclken =
+		omap2_cm_read_mod_reg(WKUP_MOD, CM_ICLKEN);
+	cm_context.dss_cm_iclken =
+		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_ICLKEN);
+	cm_context.cam_cm_iclken =
+		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_ICLKEN);
+	cm_context.per_cm_iclken =
+		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN);
+	cm_context.usbhost_cm_iclken =
+		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
+	cm_context.iva2_cm_autoidle2 =
+		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
+	cm_context.mpu_cm_autoidle2 =
+		omap2_cm_read_mod_reg(MPU_MOD, CM_AUTOIDLE2);
+	cm_context.iva2_cm_clkstctrl =
+		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.mpu_cm_clkstctrl =
+		omap2_cm_read_mod_reg(MPU_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.core_cm_clkstctrl =
+		omap2_cm_read_mod_reg(CORE_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.sgx_cm_clkstctrl =
+		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.dss_cm_clkstctrl =
+		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.cam_cm_clkstctrl =
+		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.per_cm_clkstctrl =
+		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.neon_cm_clkstctrl =
+		omap2_cm_read_mod_reg(OMAP3430_NEON_MOD, OMAP2_CM_CLKSTCTRL);
+	cm_context.usbhost_cm_clkstctrl =
+		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
+				      OMAP2_CM_CLKSTCTRL);
+	cm_context.core_cm_autoidle1 =
+		omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE1);
+	cm_context.core_cm_autoidle2 =
+		omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE2);
+	cm_context.core_cm_autoidle3 =
+		omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE3);
+	cm_context.wkup_cm_autoidle =
+		omap2_cm_read_mod_reg(WKUP_MOD, CM_AUTOIDLE);
+	cm_context.dss_cm_autoidle =
+		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_AUTOIDLE);
+	cm_context.cam_cm_autoidle =
+		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_AUTOIDLE);
+	cm_context.per_cm_autoidle =
+		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
+	cm_context.usbhost_cm_autoidle =
+		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
+	cm_context.sgx_cm_sleepdep =
+		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD,
+				      OMAP3430_CM_SLEEPDEP);
+	cm_context.dss_cm_sleepdep =
+		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP3430_CM_SLEEPDEP);
+	cm_context.cam_cm_sleepdep =
+		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP3430_CM_SLEEPDEP);
+	cm_context.per_cm_sleepdep =
+		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, OMAP3430_CM_SLEEPDEP);
+	cm_context.usbhost_cm_sleepdep =
+		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
+				      OMAP3430_CM_SLEEPDEP);
+	cm_context.cm_clkout_ctrl =
+		omap2_cm_read_mod_reg(OMAP3430_CCR_MOD,
+				      OMAP3_CM_CLKOUT_CTRL_OFFSET);
+}
+
+void omap3_cm_restore_context(void)
+{
+	omap2_cm_write_mod_reg(cm_context.iva2_cm_clksel1, OMAP3430_IVA2_MOD,
+			       CM_CLKSEL1);
+	omap2_cm_write_mod_reg(cm_context.iva2_cm_clksel2, OMAP3430_IVA2_MOD,
+			       CM_CLKSEL2);
+	__raw_writel(cm_context.cm_sysconfig, OMAP3430_CM_SYSCONFIG);
+	omap2_cm_write_mod_reg(cm_context.sgx_cm_clksel, OMAP3430ES2_SGX_MOD,
+			       CM_CLKSEL);
+	omap2_cm_write_mod_reg(cm_context.dss_cm_clksel, OMAP3430_DSS_MOD,
+			       CM_CLKSEL);
+	omap2_cm_write_mod_reg(cm_context.cam_cm_clksel, OMAP3430_CAM_MOD,
+			       CM_CLKSEL);
+	omap2_cm_write_mod_reg(cm_context.per_cm_clksel, OMAP3430_PER_MOD,
+			       CM_CLKSEL);
+	omap2_cm_write_mod_reg(cm_context.emu_cm_clksel, OMAP3430_EMU_MOD,
+			       CM_CLKSEL1);
+	omap2_cm_write_mod_reg(cm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	/*
+	 * As per erratum i671, ROM code does not respect the PER DPLL
+	 * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
+	 * In this case, we need to restore AUTO_PERIPH_DPLL by ourselves.
+	 */
+	omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle, PLL_MOD,
+			       CM_AUTOIDLE);
+	omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle2, PLL_MOD,
+			       CM_AUTOIDLE2);
+	omap2_cm_write_mod_reg(cm_context.pll_cm_clksel4, PLL_MOD,
+			       OMAP3430ES2_CM_CLKSEL4);
+	omap2_cm_write_mod_reg(cm_context.pll_cm_clksel5, PLL_MOD,
+			       OMAP3430ES2_CM_CLKSEL5);
+	omap2_cm_write_mod_reg(cm_context.pll_cm_clken2, PLL_MOD,
+			       OMAP3430ES2_CM_CLKEN2);
+	__raw_writel(cm_context.cm_polctrl, OMAP3430_CM_POLCTRL);
+	omap2_cm_write_mod_reg(cm_context.iva2_cm_fclken, OMAP3430_IVA2_MOD,
+			       CM_FCLKEN);
+	omap2_cm_write_mod_reg(cm_context.iva2_cm_clken_pll, OMAP3430_IVA2_MOD,
+			       OMAP3430_CM_CLKEN_PLL);
+	omap2_cm_write_mod_reg(cm_context.core_cm_fclken1, CORE_MOD,
+			       CM_FCLKEN1);
+	omap2_cm_write_mod_reg(cm_context.core_cm_fclken3, CORE_MOD,
+			       OMAP3430ES2_CM_FCLKEN3);
+	omap2_cm_write_mod_reg(cm_context.sgx_cm_fclken, OMAP3430ES2_SGX_MOD,
+			       CM_FCLKEN);
+	omap2_cm_write_mod_reg(cm_context.wkup_cm_fclken, WKUP_MOD, CM_FCLKEN);
+	omap2_cm_write_mod_reg(cm_context.dss_cm_fclken, OMAP3430_DSS_MOD,
+			       CM_FCLKEN);
+	omap2_cm_write_mod_reg(cm_context.cam_cm_fclken, OMAP3430_CAM_MOD,
+			       CM_FCLKEN);
+	omap2_cm_write_mod_reg(cm_context.per_cm_fclken, OMAP3430_PER_MOD,
+			       CM_FCLKEN);
+	omap2_cm_write_mod_reg(cm_context.usbhost_cm_fclken,
+			       OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
+	omap2_cm_write_mod_reg(cm_context.core_cm_iclken1, CORE_MOD,
+			       CM_ICLKEN1);
+	omap2_cm_write_mod_reg(cm_context.core_cm_iclken2, CORE_MOD,
+			       CM_ICLKEN2);
+	omap2_cm_write_mod_reg(cm_context.core_cm_iclken3, CORE_MOD,
+			       CM_ICLKEN3);
+	omap2_cm_write_mod_reg(cm_context.sgx_cm_iclken, OMAP3430ES2_SGX_MOD,
+			       CM_ICLKEN);
+	omap2_cm_write_mod_reg(cm_context.wkup_cm_iclken, WKUP_MOD, CM_ICLKEN);
+	omap2_cm_write_mod_reg(cm_context.dss_cm_iclken, OMAP3430_DSS_MOD,
+			       CM_ICLKEN);
+	omap2_cm_write_mod_reg(cm_context.cam_cm_iclken, OMAP3430_CAM_MOD,
+			       CM_ICLKEN);
+	omap2_cm_write_mod_reg(cm_context.per_cm_iclken, OMAP3430_PER_MOD,
+			       CM_ICLKEN);
+	omap2_cm_write_mod_reg(cm_context.usbhost_cm_iclken,
+			       OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
+	omap2_cm_write_mod_reg(cm_context.iva2_cm_autoidle2, OMAP3430_IVA2_MOD,
+			       CM_AUTOIDLE2);
+	omap2_cm_write_mod_reg(cm_context.mpu_cm_autoidle2, MPU_MOD,
+			       CM_AUTOIDLE2);
+	omap2_cm_write_mod_reg(cm_context.iva2_cm_clkstctrl, OMAP3430_IVA2_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.mpu_cm_clkstctrl, MPU_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.core_cm_clkstctrl, CORE_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.sgx_cm_clkstctrl, OMAP3430ES2_SGX_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.dss_cm_clkstctrl, OMAP3430_DSS_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.cam_cm_clkstctrl, OMAP3430_CAM_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.per_cm_clkstctrl, OMAP3430_PER_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.neon_cm_clkstctrl, OMAP3430_NEON_MOD,
+			       OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.usbhost_cm_clkstctrl,
+			       OMAP3430ES2_USBHOST_MOD, OMAP2_CM_CLKSTCTRL);
+	omap2_cm_write_mod_reg(cm_context.core_cm_autoidle1, CORE_MOD,
+			       CM_AUTOIDLE1);
+	omap2_cm_write_mod_reg(cm_context.core_cm_autoidle2, CORE_MOD,
+			       CM_AUTOIDLE2);
+	omap2_cm_write_mod_reg(cm_context.core_cm_autoidle3, CORE_MOD,
+			       CM_AUTOIDLE3);
+	omap2_cm_write_mod_reg(cm_context.wkup_cm_autoidle, WKUP_MOD,
+			       CM_AUTOIDLE);
+	omap2_cm_write_mod_reg(cm_context.dss_cm_autoidle, OMAP3430_DSS_MOD,
+			       CM_AUTOIDLE);
+	omap2_cm_write_mod_reg(cm_context.cam_cm_autoidle, OMAP3430_CAM_MOD,
+			       CM_AUTOIDLE);
+	omap2_cm_write_mod_reg(cm_context.per_cm_autoidle, OMAP3430_PER_MOD,
+			       CM_AUTOIDLE);
+	omap2_cm_write_mod_reg(cm_context.usbhost_cm_autoidle,
+			       OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
+	omap2_cm_write_mod_reg(cm_context.sgx_cm_sleepdep, OMAP3430ES2_SGX_MOD,
+			       OMAP3430_CM_SLEEPDEP);
+	omap2_cm_write_mod_reg(cm_context.dss_cm_sleepdep, OMAP3430_DSS_MOD,
+			       OMAP3430_CM_SLEEPDEP);
+	omap2_cm_write_mod_reg(cm_context.cam_cm_sleepdep, OMAP3430_CAM_MOD,
+			       OMAP3430_CM_SLEEPDEP);
+	omap2_cm_write_mod_reg(cm_context.per_cm_sleepdep, OMAP3430_PER_MOD,
+			       OMAP3430_CM_SLEEPDEP);
+	omap2_cm_write_mod_reg(cm_context.usbhost_cm_sleepdep,
+			       OMAP3430ES2_USBHOST_MOD, OMAP3430_CM_SLEEPDEP);
+	omap2_cm_write_mod_reg(cm_context.cm_clkout_ctrl, OMAP3430_CCR_MOD,
+			       OMAP3_CM_CLKOUT_CTRL_OFFSET);
+}
+
+/*
+ *
+ */
+
+static struct cm_ll_data omap3xxx_cm_ll_data = {
+	.split_idlest_reg	= &omap3xxx_cm_split_idlest_reg,
+	.wait_module_ready	= &omap3xxx_cm_wait_module_ready,
+};
+
+int __init omap3xxx_cm_init(void)
+{
+	if (!cpu_is_omap34xx())
+		return 0;
+
+	return cm_register(&omap3xxx_cm_ll_data);
+}
+
+static void __exit omap3xxx_cm_exit(void)
+{
+	if (!cpu_is_omap34xx())
+		return;
+
+	/* Should never happen */
+	WARN(cm_unregister(&omap3xxx_cm_ll_data),
+	     "%s: cm_ll_data function pointer mismatch\n", __func__);
+}
+__exitcall(omap3xxx_cm_exit);
diff --git a/arch/arm/mach-omap2/cm3xxx.h b/arch/arm/mach-omap2/cm3xxx.h
new file mode 100644
index 0000000..e8e146f
--- /dev/null
+++ b/arch/arm/mach-omap2/cm3xxx.h
@@ -0,0 +1,91 @@
+/*
+ * OMAP2/3 Clock Management (CM) register definitions
+ *
+ * Copyright (C) 2007-2009 Texas Instruments, Inc.
+ * Copyright (C) 2007-2010 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The CM hardware modules on the OMAP2/3 are quite similar to each
+ * other.  The CM modules/instances on OMAP4 are quite different, so
+ * they are handled in a separate file.
+ */
+#ifndef __ARCH_ASM_MACH_OMAP2_CM3XXX_H
+#define __ARCH_ASM_MACH_OMAP2_CM3XXX_H
+
+#include "prcm-common.h"
+#include "cm2xxx_3xxx.h"
+
+#define OMAP34XX_CM_REGADDR(module, reg)				\
+			OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE + (module) + (reg))
+
+
+/*
+ * OMAP3-specific global CM registers
+ * Use cm_{read,write}_reg() with these registers.
+ * These registers appear once per CM module.
+ */
+
+#define OMAP3430_CM_REVISION		OMAP34XX_CM_REGADDR(OCP_MOD, 0x0000)
+#define OMAP3430_CM_SYSCONFIG		OMAP34XX_CM_REGADDR(OCP_MOD, 0x0010)
+#define OMAP3430_CM_POLCTRL		OMAP34XX_CM_REGADDR(OCP_MOD, 0x009c)
+
+#define OMAP3_CM_CLKOUT_CTRL_OFFSET	0x0070
+#define OMAP3430_CM_CLKOUT_CTRL		OMAP_CM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
+
+/*
+ * Module specific CM register offsets from CM_BASE + domain offset
+ * Use cm_{read,write}_mod_reg() with these registers.
+ * These register offsets generally appear in more than one PRCM submodule.
+ */
+
+/* OMAP3-specific register offsets */
+
+#define OMAP3430_CM_CLKEN_PLL				0x0004
+#define OMAP3430ES2_CM_CLKEN2				0x0004
+#define OMAP3430ES2_CM_FCLKEN3				0x0008
+#define OMAP3430_CM_IDLEST_PLL				CM_IDLEST2
+#define OMAP3430_CM_AUTOIDLE_PLL			CM_AUTOIDLE2
+#define OMAP3430ES2_CM_AUTOIDLE2_PLL			CM_AUTOIDLE2
+#define OMAP3430_CM_CLKSEL1				CM_CLKSEL
+#define OMAP3430_CM_CLKSEL1_PLL				CM_CLKSEL
+#define OMAP3430_CM_CLKSEL2_PLL				CM_CLKSEL2
+#define OMAP3430_CM_SLEEPDEP				CM_CLKSEL2
+#define OMAP3430_CM_CLKSEL3				OMAP2_CM_CLKSTCTRL
+#define OMAP3430_CM_CLKSTST				0x004c
+#define OMAP3430ES2_CM_CLKSEL4				0x004c
+#define OMAP3430ES2_CM_CLKSEL5				0x0050
+#define OMAP3430_CM_CLKSEL2_EMU				0x0050
+#define OMAP3430_CM_CLKSEL3_EMU				0x0054
+
+
+/* CM_IDLEST bit field values to indicate deasserted IdleReq */
+
+#define OMAP34XX_CM_IDLEST_VAL				1
+
+
+#ifndef __ASSEMBLER__
+
+extern void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask);
+extern void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask);
+extern void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask);
+extern void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask);
+
+extern bool omap3xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask);
+extern int omap3xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id,
+					 u8 idlest_shift);
+
+extern int omap3xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
+					s16 *prcm_inst, u8 *idlest_reg_id);
+
+extern void omap3_cm_save_context(void);
+extern void omap3_cm_restore_context(void);
+
+extern int __init omap3xxx_cm_init(void);
+
+#endif
+
+#endif
diff --git a/arch/arm/mach-omap2/cm_common.c b/arch/arm/mach-omap2/cm_common.c
new file mode 100644
index 0000000..40b3b5a
--- /dev/null
+++ b/arch/arm/mach-omap2/cm_common.c
@@ -0,0 +1,140 @@
+/*
+ * OMAP2+ common Clock Management (CM) IP block functions
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * XXX This code should eventually be moved to a CM driver.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+
+#include "cm2xxx.h"
+#include "cm3xxx.h"
+#include "cm44xx.h"
+#include "common.h"
+
+/*
+ * cm_ll_data: function pointers to SoC-specific implementations of
+ * common CM functions
+ */
+static struct cm_ll_data null_cm_ll_data;
+static struct cm_ll_data *cm_ll_data = &null_cm_ll_data;
+
+/* cm_base: base virtual address of the CM IP block */
+void __iomem *cm_base;
+
+/* cm2_base: base virtual address of the CM2 IP block (OMAP44xx only) */
+void __iomem *cm2_base;
+
+/**
+ * omap2_set_globals_cm - set the CM/CM2 base addresses (for early use)
+ * @cm: CM base virtual address
+ * @cm2: CM2 base virtual address (if present on the booted SoC)
+ *
+ * XXX Will be replaced when the PRM/CM drivers are completed.
+ */
+void __init omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2)
+{
+	cm_base = cm;
+	cm2_base = cm2;
+}
+
+/**
+ * cm_split_idlest_reg - split CM_IDLEST reg addr into its components
+ * @idlest_reg: CM_IDLEST* virtual address
+ * @prcm_inst: pointer to an s16 to return the PRCM instance offset
+ * @idlest_reg_id: pointer to a u8 to return the CM_IDLESTx register ID
+ *
+ * Given an absolute CM_IDLEST register address @idlest_reg, passes
+ * the PRCM instance offset and IDLEST register ID back to the caller
+ * via the @prcm_inst and @idlest_reg_id.  Returns -EINVAL upon error,
+ * or 0 upon success.  XXX This function is only needed until absolute
+ * register addresses are removed from the OMAP struct clk records.
+ */
+int cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
+			u8 *idlest_reg_id)
+{
+	if (!cm_ll_data->split_idlest_reg) {
+		WARN_ONCE(1, "cm: %s: no low-level function defined\n",
+			  __func__);
+		return -EINVAL;
+	}
+
+	return cm_ll_data->split_idlest_reg(idlest_reg, prcm_inst,
+					   idlest_reg_id);
+}
+
+/**
+ * cm_wait_module_ready - wait for a module to leave idle or standby
+ * @prcm_mod: PRCM module offset
+ * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
+ * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
+ *
+ * Wait for the PRCM to indicate that the module identified by
+ * (@prcm_mod, @idlest_id, @idlest_shift) is clocked.  Return 0 upon
+ * success, -EBUSY if the module doesn't enable in time, or -EINVAL if
+ * no per-SoC wait_module_ready() function pointer has been registered
+ * or if the idlest register is unknown on the SoC.
+ */
+int cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
+{
+	if (!cm_ll_data->wait_module_ready) {
+		WARN_ONCE(1, "cm: %s: no low-level function defined\n",
+			  __func__);
+		return -EINVAL;
+	}
+
+	return cm_ll_data->wait_module_ready(prcm_mod, idlest_id, idlest_shift);
+}
+
+/**
+ * cm_register - register per-SoC low-level data with the CM
+ * @cld: low-level per-SoC OMAP CM data & function pointers to register
+ *
+ * Register per-SoC low-level OMAP CM data and function pointers with
+ * the OMAP CM common interface.  The caller must keep the data
+ * pointed to by @cld valid until it calls cm_unregister() and
+ * it returns successfully.  Returns 0 upon success, -EINVAL if @cld
+ * is NULL, or -EEXIST if cm_register() has already been called
+ * without an intervening cm_unregister().
+ */
+int cm_register(struct cm_ll_data *cld)
+{
+	if (!cld)
+		return -EINVAL;
+
+	if (cm_ll_data != &null_cm_ll_data)
+		return -EEXIST;
+
+	cm_ll_data = cld;
+
+	return 0;
+}
+
+/**
+ * cm_unregister - unregister per-SoC low-level data & function pointers
+ * @cld: low-level per-SoC OMAP CM data & function pointers to unregister
+ *
+ * Unregister per-SoC low-level OMAP CM data and function pointers
+ * that were previously registered with cm_register().  The
+ * caller may not destroy any of the data pointed to by @cld until
+ * this function returns successfully.  Returns 0 upon success, or
+ * -EINVAL if @cld is NULL or if @cld does not match the struct
+ * cm_ll_data * previously registered by cm_register().
+ */
+int cm_unregister(struct cm_ll_data *cld)
+{
+	if (!cld || cm_ll_data != cld)
+		return -EINVAL;
+
+	cm_ll_data = &null_cm_ll_data;
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c
index 1894015..7f9a464 100644
--- a/arch/arm/mach-omap2/cminst44xx.c
+++ b/arch/arm/mach-omap2/cminst44xx.c
@@ -2,8 +2,9 @@
  * OMAP4 CM instance functions
  *
  * Copyright (C) 2009 Nokia Corporation
- * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
  * Paul Walmsley
+ * Rajendra Nayak <rnayak@ti.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -22,6 +23,7 @@
 
 #include "iomap.h"
 #include "common.h"
+#include "clockdomain.h"
 #include "cm.h"
 #include "cm1_44xx.h"
 #include "cm2_44xx.h"
@@ -343,3 +345,141 @@ void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
 	v &= ~OMAP4430_MODULEMODE_MASK;
 	omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs);
 }
+
+/*
+ * Clockdomain low-level functions
+ */
+
+static int omap4_clkdm_add_wkup_sleep_dep(struct clockdomain *clkdm1,
+					struct clockdomain *clkdm2)
+{
+	omap4_cminst_set_inst_reg_bits((1 << clkdm2->dep_bit),
+				       clkdm1->prcm_partition,
+				       clkdm1->cm_inst, clkdm1->clkdm_offs +
+				       OMAP4_CM_STATICDEP);
+	return 0;
+}
+
+static int omap4_clkdm_del_wkup_sleep_dep(struct clockdomain *clkdm1,
+					struct clockdomain *clkdm2)
+{
+	omap4_cminst_clear_inst_reg_bits((1 << clkdm2->dep_bit),
+					 clkdm1->prcm_partition,
+					 clkdm1->cm_inst, clkdm1->clkdm_offs +
+					 OMAP4_CM_STATICDEP);
+	return 0;
+}
+
+static int omap4_clkdm_read_wkup_sleep_dep(struct clockdomain *clkdm1,
+					struct clockdomain *clkdm2)
+{
+	return omap4_cminst_read_inst_reg_bits(clkdm1->prcm_partition,
+					       clkdm1->cm_inst,
+					       clkdm1->clkdm_offs +
+					       OMAP4_CM_STATICDEP,
+					       (1 << clkdm2->dep_bit));
+}
+
+static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm)
+{
+	struct clkdm_dep *cd;
+	u32 mask = 0;
+
+	if (!clkdm->prcm_partition)
+		return 0;
+
+	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
+		if (!cd->clkdm)
+			continue; /* only happens if data is erroneous */
+
+		mask |= 1 << cd->clkdm->dep_bit;
+		atomic_set(&cd->wkdep_usecount, 0);
+	}
+
+	omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition,
+					 clkdm->cm_inst, clkdm->clkdm_offs +
+					 OMAP4_CM_STATICDEP);
+	return 0;
+}
+
+static int omap4_clkdm_sleep(struct clockdomain *clkdm)
+{
+	omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+	return 0;
+}
+
+static int omap4_clkdm_wakeup(struct clockdomain *clkdm)
+{
+	omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+	return 0;
+}
+
+static void omap4_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+	omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+}
+
+static void omap4_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+	if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+		omap4_clkdm_wakeup(clkdm);
+	else
+		omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition,
+						 clkdm->cm_inst,
+						 clkdm->clkdm_offs);
+}
+
+static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
+{
+	if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+		return omap4_clkdm_wakeup(clkdm);
+
+	return 0;
+}
+
+static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	if (!clkdm->prcm_partition)
+		return 0;
+
+	/*
+	 * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
+	 * more details on the unpleasant problem this is working
+	 * around
+	 */
+	if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
+	    !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
+		omap4_clkdm_allow_idle(clkdm);
+		return 0;
+	}
+
+	hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+
+	if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
+		omap4_clkdm_sleep(clkdm);
+
+	return 0;
+}
+
+struct clkdm_ops omap4_clkdm_operations = {
+	.clkdm_add_wkdep	= omap4_clkdm_add_wkup_sleep_dep,
+	.clkdm_del_wkdep	= omap4_clkdm_del_wkup_sleep_dep,
+	.clkdm_read_wkdep	= omap4_clkdm_read_wkup_sleep_dep,
+	.clkdm_clear_all_wkdeps	= omap4_clkdm_clear_all_wkup_sleep_deps,
+	.clkdm_add_sleepdep	= omap4_clkdm_add_wkup_sleep_dep,
+	.clkdm_del_sleepdep	= omap4_clkdm_del_wkup_sleep_dep,
+	.clkdm_read_sleepdep	= omap4_clkdm_read_wkup_sleep_dep,
+	.clkdm_clear_all_sleepdeps	= omap4_clkdm_clear_all_wkup_sleep_deps,
+	.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 d69fdef..bd7bab8 100644
--- a/arch/arm/mach-omap2/cminst44xx.h
+++ b/arch/arm/mach-omap2/cminst44xx.h
@@ -38,4 +38,6 @@ extern u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, s16 inst,
 extern u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx,
 					   u32 mask);
 
+extern void omap_cm_base_init(void);
+
 #endif
diff --git a/arch/arm/mach-omap2/common-board-devices.c b/arch/arm/mach-omap2/common-board-devices.c
index 84551f2..d246efd 100644
--- a/arch/arm/mach-omap2/common-board-devices.c
+++ b/arch/arm/mach-omap2/common-board-devices.c
@@ -25,7 +25,6 @@
 #include <linux/spi/ads7846.h>
 
 #include <linux/platform_data/spi-omap2-mcspi.h>
-#include <linux/platform_data/mtd-nand-omap2.h>
 
 #include "common.h"
 #include "common-board-devices.h"
@@ -102,48 +101,3 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
 {
 }
 #endif
-
-#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-static struct omap_nand_platform_data nand_data;
-
-void __init omap_nand_flash_init(int options, struct mtd_partition *parts,
-				 int nr_parts)
-{
-	u8 cs = 0;
-	u8 nandcs = GPMC_CS_NUM + 1;
-
-	/* find out the chip-select on which NAND exists */
-	while (cs < GPMC_CS_NUM) {
-		u32 ret = 0;
-		ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-
-		if ((ret & 0xC00) == 0x800) {
-			printk(KERN_INFO "Found NAND on CS%d\n", cs);
-			if (nandcs > GPMC_CS_NUM)
-				nandcs = cs;
-		}
-		cs++;
-	}
-
-	if (nandcs > GPMC_CS_NUM) {
-		pr_info("NAND: Unable to find configuration in GPMC\n");
-		return;
-	}
-
-	if (nandcs < GPMC_CS_NUM) {
-		nand_data.cs = nandcs;
-		nand_data.parts = parts;
-		nand_data.nr_parts = nr_parts;
-		nand_data.devsize = options;
-
-		printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
-		if (gpmc_nand_init(&nand_data) < 0)
-			printk(KERN_ERR "Unable to register NAND device\n");
-	}
-}
-#else
-void __init omap_nand_flash_init(int options, struct mtd_partition *parts,
-				 int nr_parts)
-{
-}
-#endif
diff --git a/arch/arm/mach-omap2/common-board-devices.h b/arch/arm/mach-omap2/common-board-devices.h
index a0b4a428..72bb41b 100644
--- a/arch/arm/mach-omap2/common-board-devices.h
+++ b/arch/arm/mach-omap2/common-board-devices.h
@@ -10,6 +10,5 @@ struct ads7846_platform_data;
 
 void omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
 		       struct ads7846_platform_data *board_pdata);
-void omap_nand_flash_init(int opts, struct mtd_partition *parts, int n_parts);
 
 #endif /* __OMAP_COMMON_BOARD_DEVICES__ */
diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c
index 17950c6..2dabb9e 100644
--- a/arch/arm/mach-omap2/common.c
+++ b/arch/arm/mach-omap2/common.c
@@ -14,189 +14,23 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/io.h>
+#include <linux/platform_data/dsp-omap.h>
 
-#include <plat/clock.h>
-
-#include "soc.h"
-#include "iomap.h"
 #include "common.h"
-#include "sdrc.h"
-#include "control.h"
-
-/* Global address base setup code */
-
-static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
-{
-	omap2_set_globals_tap(omap2_globals);
-	omap2_set_globals_sdrc(omap2_globals);
-	omap2_set_globals_control(omap2_globals);
-	omap2_set_globals_prcm(omap2_globals);
-}
-
-#if defined(CONFIG_SOC_OMAP2420)
-
-static struct omap_globals omap242x_globals = {
-	.class	= OMAP242X_CLASS,
-	.tap	= OMAP2_L4_IO_ADDRESS(0x48014000),
-	.sdrc	= OMAP2_L3_IO_ADDRESS(OMAP2420_SDRC_BASE),
-	.sms	= OMAP2_L3_IO_ADDRESS(OMAP2420_SMS_BASE),
-	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE),
-	.prm	= OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE),
-	.cm	= OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE),
-};
-
-void __init omap2_set_globals_242x(void)
-{
-	__omap2_set_globals(&omap242x_globals);
-}
-
-void __init omap242x_map_io(void)
-{
-	omap242x_map_common_io();
-}
-#endif
-
-#if defined(CONFIG_SOC_OMAP2430)
-
-static struct omap_globals omap243x_globals = {
-	.class	= OMAP243X_CLASS,
-	.tap	= OMAP2_L4_IO_ADDRESS(0x4900a000),
-	.sdrc	= OMAP2_L3_IO_ADDRESS(OMAP243X_SDRC_BASE),
-	.sms	= OMAP2_L3_IO_ADDRESS(OMAP243X_SMS_BASE),
-	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE),
-	.prm	= OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE),
-	.cm	= OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE),
-};
-
-void __init omap2_set_globals_243x(void)
-{
-	__omap2_set_globals(&omap243x_globals);
-}
-
-void __init omap243x_map_io(void)
-{
-	omap243x_map_common_io();
-}
-#endif
-
-#if defined(CONFIG_ARCH_OMAP3)
-
-static struct omap_globals omap3_globals = {
-	.class	= OMAP343X_CLASS,
-	.tap	= OMAP2_L4_IO_ADDRESS(0x4830A000),
-	.sdrc	= OMAP2_L3_IO_ADDRESS(OMAP343X_SDRC_BASE),
-	.sms	= OMAP2_L3_IO_ADDRESS(OMAP343X_SMS_BASE),
-	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE),
-	.prm	= OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE),
-	.cm	= OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE),
-};
-
-void __init omap2_set_globals_3xxx(void)
-{
-	__omap2_set_globals(&omap3_globals);
-}
-
-void __init omap3_map_io(void)
-{
-	omap34xx_map_common_io();
-}
+#include "omap-secure.h"
 
 /*
- * Adjust TAP register base such that omap3_check_revision accesses the correct
- * TI81XX register for checking device ID (it adds 0x204 to tap base while
- * TI81XX DEVICE ID register is at offset 0x600 from control base).
+ * Stub function for OMAP2 so that common files
+ * continue to build when custom builds are used
  */
-#define TI81XX_TAP_BASE		(TI81XX_CTRL_BASE + \
-				TI81XX_CONTROL_DEVICE_ID - 0x204)
-
-static struct omap_globals ti81xx_globals = {
-	.class  = OMAP343X_CLASS,
-	.tap    = OMAP2_L4_IO_ADDRESS(TI81XX_TAP_BASE),
-	.ctrl   = OMAP2_L4_IO_ADDRESS(TI81XX_CTRL_BASE),
-	.prm    = OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE),
-	.cm     = OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE),
-};
-
-void __init omap2_set_globals_ti81xx(void)
-{
-	__omap2_set_globals(&ti81xx_globals);
-}
-
-void __init ti81xx_map_io(void)
-{
-	omapti81xx_map_common_io();
-}
-#endif
-
-#if defined(CONFIG_SOC_AM33XX)
-#define AM33XX_TAP_BASE		(AM33XX_CTRL_BASE + \
-				TI81XX_CONTROL_DEVICE_ID - 0x204)
-
-static struct omap_globals am33xx_globals = {
-	.class  = AM335X_CLASS,
-	.tap    = AM33XX_L4_WK_IO_ADDRESS(AM33XX_TAP_BASE),
-	.ctrl   = AM33XX_L4_WK_IO_ADDRESS(AM33XX_CTRL_BASE),
-	.prm    = AM33XX_L4_WK_IO_ADDRESS(AM33XX_PRCM_BASE),
-	.cm     = AM33XX_L4_WK_IO_ADDRESS(AM33XX_PRCM_BASE),
-};
-
-void __init omap2_set_globals_am33xx(void)
-{
-	__omap2_set_globals(&am33xx_globals);
-}
-
-void __init am33xx_map_io(void)
-{
-	omapam33xx_map_common_io();
-}
-#endif
-
-#if defined(CONFIG_ARCH_OMAP4)
-static struct omap_globals omap4_globals = {
-	.class	= OMAP443X_CLASS,
-	.tap	= OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
-	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
-	.ctrl_pad	= OMAP2_L4_IO_ADDRESS(OMAP443X_CTRL_BASE),
-	.prm	= OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE),
-	.cm	= OMAP2_L4_IO_ADDRESS(OMAP4430_CM_BASE),
-	.cm2	= OMAP2_L4_IO_ADDRESS(OMAP4430_CM2_BASE),
-	.prcm_mpu	= OMAP2_L4_IO_ADDRESS(OMAP4430_PRCM_MPU_BASE),
-};
-
-void __init omap2_set_globals_443x(void)
-{
-	__omap2_set_globals(&omap4_globals);
-}
-
-void __init omap4_map_io(void)
-{
-	omap44xx_map_common_io();
-}
-#endif
-
-#if defined(CONFIG_SOC_OMAP5)
-static struct omap_globals omap5_globals = {
-	.class	= OMAP54XX_CLASS,
-	.tap	= OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE),
-	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE),
-	.ctrl_pad	= OMAP2_L4_IO_ADDRESS(OMAP54XX_CTRL_BASE),
-	.prm	= OMAP2_L4_IO_ADDRESS(OMAP54XX_PRM_BASE),
-	.cm	= OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_AON_BASE),
-	.cm2	= OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_BASE),
-	.prcm_mpu = OMAP2_L4_IO_ADDRESS(OMAP54XX_PRCM_MPU_BASE),
-};
-
-void __init omap2_set_globals_5xxx(void)
+int __weak omap_secure_ram_reserve_memblock(void)
 {
-	omap2_set_globals_tap(&omap5_globals);
-	omap2_set_globals_control(&omap5_globals);
-	omap2_set_globals_prcm(&omap5_globals);
+	return 0;
 }
 
-void __init omap5_map_io(void)
+void __init omap_reserve(void)
 {
-	omap5_map_common_io();
+	omap_dsp_reserve_sdram_memblock();
+	omap_secure_ram_reserve_memblock();
+	omap_barrier_reserve_memblock();
 }
-#endif
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 7045e4d..dae55d8 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -28,63 +28,18 @@
 
 #include <linux/irq.h>
 #include <linux/delay.h>
+#include <linux/i2c.h>
 #include <linux/i2c/twl.h>
+#include <linux/i2c-omap.h>
 
 #include <asm/proc-fns.h>
 
-#include <plat/cpu.h>
-#include <plat/serial.h>
-#include <plat/common.h>
+#include "i2c.h"
+#include "serial.h"
 
-#define OMAP_INTC_START		NR_IRQS
-
-#ifdef CONFIG_SOC_OMAP2420
-extern void omap242x_map_common_io(void);
-#else
-static inline void omap242x_map_common_io(void)
-{
-}
-#endif
-
-#ifdef CONFIG_SOC_OMAP2430
-extern void omap243x_map_common_io(void);
-#else
-static inline void omap243x_map_common_io(void)
-{
-}
-#endif
-
-#ifdef CONFIG_ARCH_OMAP3
-extern void omap34xx_map_common_io(void);
-#else
-static inline void omap34xx_map_common_io(void)
-{
-}
-#endif
-
-#ifdef CONFIG_SOC_TI81XX
-extern void omapti81xx_map_common_io(void);
-#else
-static inline void omapti81xx_map_common_io(void)
-{
-}
-#endif
+#include "usb.h"
 
-#ifdef CONFIG_SOC_AM33XX
-extern void omapam33xx_map_common_io(void);
-#else
-static inline void omapam33xx_map_common_io(void)
-{
-}
-#endif
-
-#ifdef CONFIG_ARCH_OMAP4
-extern void omap44xx_map_common_io(void);
-#else
-static inline void omap44xx_map_common_io(void)
-{
-}
-#endif
+#define OMAP_INTC_START		NR_IRQS
 
 #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP2)
 int omap2_pm_init(void);
@@ -122,14 +77,6 @@ static inline int omap_mux_late_init(void)
 }
 #endif
 
-#ifdef CONFIG_SOC_OMAP5
-extern void omap5_map_common_io(void);
-#else
-static inline void omap5_map_common_io(void)
-{
-}
-#endif
-
 extern void omap2_init_common_infrastructure(void);
 
 extern struct sys_timer omap2_timer;
@@ -162,52 +109,43 @@ void am35xx_init_late(void);
 void ti81xx_init_late(void);
 void omap4430_init_late(void);
 int omap2_common_pm_late_init(void);
-void omap_prcm_restart(char, const char *);
 
-/*
- * IO bases for various OMAP processors
- * Except the tap base, rest all the io bases
- * listed are physical addresses.
- */
-struct omap_globals {
-	u32		class;		/* OMAP class to detect */
-	void __iomem	*tap;		/* Control module ID code */
-	void __iomem	*sdrc;           /* SDRAM Controller */
-	void __iomem	*sms;            /* SDRAM Memory Scheduler */
-	void __iomem	*ctrl;           /* System Control Module */
-	void __iomem	*ctrl_pad;	/* PAD Control Module */
-	void __iomem	*prm;            /* Power and Reset Management */
-	void __iomem	*cm;             /* Clock Management */
-	void __iomem	*cm2;
-	void __iomem	*prcm_mpu;
-};
-
-void omap2_set_globals_242x(void);
-void omap2_set_globals_243x(void);
-void omap2_set_globals_3xxx(void);
-void omap2_set_globals_443x(void);
-void omap2_set_globals_5xxx(void);
-void omap2_set_globals_ti81xx(void);
-void omap2_set_globals_am33xx(void);
-
-/* These get called from omap2_set_globals_xxxx(), do not call these */
-void omap2_set_globals_tap(struct omap_globals *);
-#if defined(CONFIG_SOC_HAS_OMAP2_SDRC)
-void omap2_set_globals_sdrc(struct omap_globals *);
+#if defined(CONFIG_SOC_OMAP2420) || defined(CONFIG_SOC_OMAP2430)
+void omap2xxx_restart(char mode, const char *cmd);
+#else
+static inline void omap2xxx_restart(char mode, const char *cmd)
+{
+}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+void omap3xxx_restart(char mode, const char *cmd);
+#else
+static inline void omap3xxx_restart(char mode, const char *cmd)
+{
+}
+#endif
+
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
+void omap44xx_restart(char mode, const char *cmd);
 #else
-static inline void omap2_set_globals_sdrc(struct omap_globals *omap2_globals)
-{ }
+static inline void omap44xx_restart(char mode, const char *cmd)
+{
+}
 #endif
-void omap2_set_globals_control(struct omap_globals *);
-void omap2_set_globals_prcm(struct omap_globals *);
-
-void omap242x_map_io(void);
-void omap243x_map_io(void);
-void omap3_map_io(void);
-void am33xx_map_io(void);
-void omap4_map_io(void);
-void omap5_map_io(void);
-void ti81xx_map_io(void);
+
+/* This gets called from mach-omap2/io.c, do not call this */
+void __init omap2_set_globals_tap(u32 class, void __iomem *tap);
+
+void __init omap242x_map_io(void);
+void __init omap243x_map_io(void);
+void __init omap3_map_io(void);
+void __init am33xx_map_io(void);
+void __init omap4_map_io(void);
+void __init omap5_map_io(void);
+void __init ti81xx_map_io(void);
+
+/* omap_barriers_init() is OMAP4 only */
 void omap_barriers_init(void);
 
 /**
@@ -275,6 +213,9 @@ static inline void __iomem *omap4_get_scu_base(void)
 #endif
 
 extern void __init gic_init_irq(void);
+extern void gic_dist_disable(void);
+extern bool gic_dist_disabled(void);
+extern void gic_timer_retrigger(void);
 extern void omap_smc1(u32 fn, u32 arg);
 extern void __iomem *omap4_get_sar_ram_base(void);
 extern void omap_do_wfi(void);
@@ -282,6 +223,7 @@ extern void omap_do_wfi(void);
 #ifdef CONFIG_SMP
 /* Needed for secondary core boot */
 extern void omap_secondary_startup(void);
+extern void omap_secondary_startup_4460(void);
 extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask);
 extern void omap_auxcoreboot_addr(u32 cpu_addr);
 extern u32 omap_read_auxcoreboot0(void);
@@ -338,6 +280,10 @@ extern void omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
 				      struct omap_sdrc_params *sdrc_cs1);
 struct omap2_hsmmc_info;
 extern int omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers);
+extern void omap_reserve(void);
+
+struct omap_hwmod;
+extern int omap_dss_reset(struct omap_hwmod *);
 
 #endif /* __ASSEMBLER__ */
 #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index d1ff839..2adb268 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -1,7 +1,7 @@
 /*
  * OMAP2/3 System Control Module register access
  *
- * Copyright (C) 2007 Texas Instruments, Inc.
+ * Copyright (C) 2007, 2012 Texas Instruments, Inc.
  * Copyright (C) 2007 Nokia Corporation
  *
  * Written by Paul Walmsley
@@ -15,15 +15,13 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 
-#include <plat/sdrc.h>
-
 #include "soc.h"
 #include "iomap.h"
 #include "common.h"
 #include "cm-regbits-34xx.h"
 #include "prm-regbits-34xx.h"
-#include "prm2xxx_3xxx.h"
-#include "cm2xxx_3xxx.h"
+#include "prm3xxx.h"
+#include "cm3xxx.h"
 #include "sdrc.h"
 #include "pm.h"
 #include "control.h"
@@ -149,13 +147,11 @@ static struct omap3_control_regs control_context;
 #define OMAP_CTRL_REGADDR(reg)		(omap2_ctrl_base + (reg))
 #define OMAP4_CTRL_PAD_REGADDR(reg)	(omap4_ctrl_pad_base + (reg))
 
-void __init omap2_set_globals_control(struct omap_globals *omap2_globals)
+void __init omap2_set_globals_control(void __iomem *ctrl,
+				      void __iomem *ctrl_pad)
 {
-	if (omap2_globals->ctrl)
-		omap2_ctrl_base = omap2_globals->ctrl;
-
-	if (omap2_globals->ctrl_pad)
-		omap4_ctrl_pad_base = omap2_globals->ctrl_pad;
+	omap2_ctrl_base = ctrl;
+	omap4_ctrl_pad_base = ctrl_pad;
 }
 
 void __iomem *omap_ctrl_base_get(void)
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index a89e825..3d944d3 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -201,6 +201,7 @@
 #define OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO	0x249
 #define OMAP44XX_CONTROL_FUSE_CORE_OPP50	0x254
 #define OMAP44XX_CONTROL_FUSE_CORE_OPP100	0x257
+#define OMAP44XX_CONTROL_FUSE_CORE_OPP100OV	0x25A
 
 /* AM35XX only CONTROL_GENERAL register offsets */
 #define AM35XX_CONTROL_MSUSPENDMUX_6    (OMAP2_CONTROL_GENERAL + 0x0038)
@@ -414,6 +415,8 @@ extern void omap_ctrl_write_dsp_boot_addr(u32 bootaddr);
 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 omap2_set_globals_control(void __iomem *ctrl,
+				      void __iomem *ctrl_pad);
 #else
 #define omap_ctrl_base_get()		0
 #define omap_ctrl_readb(x)		0
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index bc27569..bca7a88 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -27,7 +27,6 @@
 #include <linux/export.h>
 #include <linux/cpu_pm.h>
 
-#include <plat/prcm.h>
 #include "powerdomain.h"
 #include "clockdomain.h"
 
diff --git a/arch/arm/mach-omap2/debug-devices.h b/arch/arm/mach-omap2/debug-devices.h
deleted file mode 100644
index a4edbd2..0000000
--- a/arch/arm/mach-omap2/debug-devices.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _OMAP_DEBUG_DEVICES_H
-#define _OMAP_DEBUG_DEVICES_H
-
-#include <linux/types.h>
-
-/* for TI reference platforms sharing the same debug card */
-extern int debug_card_init(u32 addr, unsigned gpio);
-
-#endif
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index c72b5a7..d2215e9 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -24,10 +24,11 @@
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 
+#include <plat-omap/dma-omap.h>
+
 #include "iomap.h"
-#include <plat/dma.h>
-#include <plat/omap_hwmod.h>
-#include <plat/omap_device.h>
+#include "omap_hwmod.h"
+#include "omap_device.h"
 #include "omap4-keypad.h"
 
 #include "soc.h"
@@ -35,6 +36,7 @@
 #include "mux.h"
 #include "control.h"
 #include "devices.h"
+#include "dma.h"
 
 #define L3_MODULES_MAX_LEN 12
 #define L3_MODULES 3
@@ -723,29 +725,3 @@ static int __init omap2_init_devices(void)
 	return 0;
 }
 arch_initcall(omap2_init_devices);
-
-#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
-static int __init omap_init_wdt(void)
-{
-	int id = -1;
-	struct platform_device *pdev;
-	struct omap_hwmod *oh;
-	char *oh_name = "wd_timer2";
-	char *dev_name = "omap_wdt";
-
-	if (!cpu_class_is_omap2() || of_have_populated_dt())
-		return 0;
-
-	oh = omap_hwmod_lookup(oh_name);
-	if (!oh) {
-		pr_err("Could not look up wd_timer%d hwmod\n", id);
-		return -EINVAL;
-	}
-
-	pdev = omap_device_build(dev_name, id, oh, NULL, 0, NULL, 0, 0);
-	WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n",
-				dev_name, oh->name);
-	return 0;
-}
-subsys_initcall(omap_init_wdt);
-#endif
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 1011995..cc75aaf 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -25,15 +25,17 @@
 #include <linux/delay.h>
 
 #include <video/omapdss.h>
-#include <plat/omap_hwmod.h>
-#include <plat/omap_device.h>
-#include <plat/omap-pm.h>
+#include "omap_hwmod.h"
+#include "omap_device.h"
+#include "omap-pm.h"
 #include "common.h"
 
+#include "soc.h"
 #include "iomap.h"
 #include "mux.h"
 #include "control.h"
 #include "display.h"
+#include "prm.h"
 
 #define DISPC_CONTROL		0x0040
 #define DISPC_CONTROL2		0x0238
@@ -100,17 +102,20 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initconst = {
 	{ "dss_hdmi", "omapdss_hdmi", -1 },
 };
 
-static void __init omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
+static void __init omap4_tpd12s015_mux_pads(void)
 {
-	u32 reg;
-	u16 control_i2c_1;
-
 	omap_mux_init_signal("hdmi_cec",
 			OMAP_PIN_INPUT_PULLUP);
 	omap_mux_init_signal("hdmi_ddc_scl",
 			OMAP_PIN_INPUT_PULLUP);
 	omap_mux_init_signal("hdmi_ddc_sda",
 			OMAP_PIN_INPUT_PULLUP);
+}
+
+static void __init omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
+{
+	u32 reg;
+	u16 control_i2c_1;
 
 	/*
 	 * CONTROL_I2C_1: HDMI_DDC_SDA_PULLUPRESX (bit 28) and
@@ -161,8 +166,10 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
 
 int __init omap_hdmi_init(enum omap_hdmi_flags flags)
 {
-	if (cpu_is_omap44xx())
+	if (cpu_is_omap44xx()) {
 		omap4_hdmi_mux_pads(flags);
+		omap4_tpd12s015_mux_pads();
+	}
 
 	return 0;
 }
@@ -284,6 +291,35 @@ err:
 	return ERR_PTR(r);
 }
 
+static enum omapdss_version __init omap_display_get_version(void)
+{
+	if (cpu_is_omap24xx())
+		return OMAPDSS_VER_OMAP24xx;
+	else if (cpu_is_omap3630())
+		return OMAPDSS_VER_OMAP3630;
+	else if (cpu_is_omap34xx()) {
+		if (soc_is_am35xx()) {
+			return OMAPDSS_VER_AM35xx;
+		} else {
+			if (omap_rev() < OMAP3430_REV_ES3_0)
+				return OMAPDSS_VER_OMAP34xx_ES1;
+			else
+				return OMAPDSS_VER_OMAP34xx_ES3;
+		}
+	} else if (omap_rev() == OMAP4430_REV_ES1_0)
+		return OMAPDSS_VER_OMAP4430_ES1;
+	else if (omap_rev() == OMAP4430_REV_ES2_0 ||
+			omap_rev() == OMAP4430_REV_ES2_1 ||
+			omap_rev() == OMAP4430_REV_ES2_2)
+		return OMAPDSS_VER_OMAP4430_ES2;
+	else if (cpu_is_omap44xx())
+		return OMAPDSS_VER_OMAP4;
+	else if (soc_is_omap54xx())
+		return OMAPDSS_VER_OMAP5;
+	else
+		return OMAPDSS_VER_UNKNOWN;
+}
+
 int __init omap_display_init(struct omap_dss_board_info *board_data)
 {
 	int r = 0;
@@ -291,9 +327,18 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
 	int i, oh_count;
 	const struct omap_dss_hwmod_data *curr_dss_hwmod;
 	struct platform_device *dss_pdev;
+	enum omapdss_version ver;
 
 	/* create omapdss device */
 
+	ver = omap_display_get_version();
+
+	if (ver == OMAPDSS_VER_UNKNOWN) {
+		pr_err("DSS not supported on this SoC\n");
+		return -ENODEV;
+	}
+
+	board_data->version = ver;
 	board_data->dsi_enable_pads = omap_dsi_enable_pads;
 	board_data->dsi_disable_pads = omap_dsi_disable_pads;
 	board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count;
@@ -473,7 +518,6 @@ static void dispc_disable_outputs(void)
 	}
 }
 
-#define MAX_MODULE_SOFTRESET_WAIT	10000
 int omap_dss_reset(struct omap_hwmod *oh)
 {
 	struct omap_hwmod_opt_clk *oc;
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index ff75abe..e5aba58 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -28,9 +28,11 @@
 #include <linux/init.h>
 #include <linux/device.h>
 
-#include <plat/omap_hwmod.h>
-#include <plat/omap_device.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
+
+#include "soc.h"
+#include "omap_hwmod.h"
+#include "omap_device.h"
 
 #define OMAP2_DMA_STRIDE	0x60
 
@@ -274,6 +276,9 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 		return -ENOMEM;
 	}
 
+	if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
+		d->dev_caps |= HS_CHANNELS_RESERVED;
+
 	/* Check the capabilities register for descriptor loading feature */
 	if (dma_read(CAPS_0, 0) & DMA_HAS_DESCRIPTOR_CAPS)
 		dma_common_ch_end = CCDN;
diff --git a/arch/arm/mach-omap2/dma.h b/arch/arm/mach-omap2/dma.h
new file mode 100644
index 0000000..eba80db
--- /dev/null
+++ b/arch/arm/mach-omap2/dma.h
@@ -0,0 +1,131 @@
+/*
+ *  OMAP2PLUS DMA channel definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 __OMAP2PLUS_DMA_CHANNEL_H
+#define __OMAP2PLUS_DMA_CHANNEL_H
+
+
+/* DMA channels for 24xx */
+#define OMAP24XX_DMA_NO_DEVICE		0
+#define OMAP24XX_DMA_XTI_DMA		1	/* S_DMA_0 */
+#define OMAP24XX_DMA_EXT_DMAREQ0	2	/* S_DMA_1 */
+#define OMAP24XX_DMA_EXT_DMAREQ1	3	/* S_DMA_2 */
+#define OMAP24XX_DMA_GPMC		4	/* S_DMA_3 */
+#define OMAP24XX_DMA_GFX		5	/* S_DMA_4 */
+#define OMAP24XX_DMA_DSS		6	/* S_DMA_5 */
+#define OMAP242X_DMA_VLYNQ_TX		7	/* S_DMA_6 */
+#define OMAP24XX_DMA_EXT_DMAREQ2	7	/* S_DMA_6 */
+#define OMAP24XX_DMA_CWT		8	/* S_DMA_7 */
+#define OMAP24XX_DMA_AES_TX		9	/* S_DMA_8 */
+#define OMAP24XX_DMA_AES_RX		10	/* S_DMA_9 */
+#define OMAP24XX_DMA_DES_TX		11	/* S_DMA_10 */
+#define OMAP24XX_DMA_DES_RX		12	/* S_DMA_11 */
+#define OMAP24XX_DMA_SHA1MD5_RX		13	/* S_DMA_12 */
+#define OMAP34XX_DMA_SHA2MD5_RX		13	/* S_DMA_12 */
+#define OMAP242X_DMA_EXT_DMAREQ2	14	/* S_DMA_13 */
+#define OMAP242X_DMA_EXT_DMAREQ3	15	/* S_DMA_14 */
+#define OMAP242X_DMA_EXT_DMAREQ4	16	/* S_DMA_15 */
+#define OMAP242X_DMA_EAC_AC_RD		17	/* S_DMA_16 */
+#define OMAP242X_DMA_EAC_AC_WR		18	/* S_DMA_17 */
+#define OMAP242X_DMA_EAC_MD_UL_RD	19	/* S_DMA_18 */
+#define OMAP242X_DMA_EAC_MD_UL_WR	20	/* S_DMA_19 */
+#define OMAP242X_DMA_EAC_MD_DL_RD	21	/* S_DMA_20 */
+#define OMAP242X_DMA_EAC_MD_DL_WR	22	/* S_DMA_21 */
+#define OMAP242X_DMA_EAC_BT_UL_RD	23	/* S_DMA_22 */
+#define OMAP242X_DMA_EAC_BT_UL_WR	24	/* S_DMA_23 */
+#define OMAP242X_DMA_EAC_BT_DL_RD	25	/* S_DMA_24 */
+#define OMAP242X_DMA_EAC_BT_DL_WR	26	/* S_DMA_25 */
+#define OMAP243X_DMA_EXT_DMAREQ3	14	/* S_DMA_13 */
+#define OMAP24XX_DMA_SPI3_TX0		15	/* S_DMA_14 */
+#define OMAP24XX_DMA_SPI3_RX0		16	/* S_DMA_15 */
+#define OMAP24XX_DMA_MCBSP3_TX		17	/* S_DMA_16 */
+#define OMAP24XX_DMA_MCBSP3_RX		18	/* S_DMA_17 */
+#define OMAP24XX_DMA_MCBSP4_TX		19	/* S_DMA_18 */
+#define OMAP24XX_DMA_MCBSP4_RX		20	/* S_DMA_19 */
+#define OMAP24XX_DMA_MCBSP5_TX		21	/* S_DMA_20 */
+#define OMAP24XX_DMA_MCBSP5_RX		22	/* S_DMA_21 */
+#define OMAP24XX_DMA_SPI3_TX1		23	/* S_DMA_22 */
+#define OMAP24XX_DMA_SPI3_RX1		24	/* S_DMA_23 */
+#define OMAP243X_DMA_EXT_DMAREQ4	25	/* S_DMA_24 */
+#define OMAP243X_DMA_EXT_DMAREQ5	26	/* S_DMA_25 */
+#define OMAP34XX_DMA_I2C3_TX		25	/* S_DMA_24 */
+#define OMAP34XX_DMA_I2C3_RX		26	/* S_DMA_25 */
+#define OMAP24XX_DMA_I2C1_TX		27	/* S_DMA_26 */
+#define OMAP24XX_DMA_I2C1_RX		28	/* S_DMA_27 */
+#define OMAP24XX_DMA_I2C2_TX		29	/* S_DMA_28 */
+#define OMAP24XX_DMA_I2C2_RX		30	/* S_DMA_29 */
+#define OMAP24XX_DMA_MCBSP1_TX		31	/* S_DMA_30 */
+#define OMAP24XX_DMA_MCBSP1_RX		32	/* S_DMA_31 */
+#define OMAP24XX_DMA_MCBSP2_TX		33	/* S_DMA_32 */
+#define OMAP24XX_DMA_MCBSP2_RX		34	/* S_DMA_33 */
+#define OMAP24XX_DMA_SPI1_TX0		35	/* S_DMA_34 */
+#define OMAP24XX_DMA_SPI1_RX0		36	/* S_DMA_35 */
+#define OMAP24XX_DMA_SPI1_TX1		37	/* S_DMA_36 */
+#define OMAP24XX_DMA_SPI1_RX1		38	/* S_DMA_37 */
+#define OMAP24XX_DMA_SPI1_TX2		39	/* S_DMA_38 */
+#define OMAP24XX_DMA_SPI1_RX2		40	/* S_DMA_39 */
+#define OMAP24XX_DMA_SPI1_TX3		41	/* S_DMA_40 */
+#define OMAP24XX_DMA_SPI1_RX3		42	/* S_DMA_41 */
+#define OMAP24XX_DMA_SPI2_TX0		43	/* S_DMA_42 */
+#define OMAP24XX_DMA_SPI2_RX0		44	/* S_DMA_43 */
+#define OMAP24XX_DMA_SPI2_TX1		45	/* S_DMA_44 */
+#define OMAP24XX_DMA_SPI2_RX1		46	/* S_DMA_45 */
+#define OMAP24XX_DMA_MMC2_TX		47	/* S_DMA_46 */
+#define OMAP24XX_DMA_MMC2_RX		48	/* S_DMA_47 */
+#define OMAP24XX_DMA_UART1_TX		49	/* S_DMA_48 */
+#define OMAP24XX_DMA_UART1_RX		50	/* S_DMA_49 */
+#define OMAP24XX_DMA_UART2_TX		51	/* S_DMA_50 */
+#define OMAP24XX_DMA_UART2_RX		52	/* S_DMA_51 */
+#define OMAP24XX_DMA_UART3_TX		53	/* S_DMA_52 */
+#define OMAP24XX_DMA_UART3_RX		54	/* S_DMA_53 */
+#define OMAP24XX_DMA_USB_W2FC_TX0	55	/* S_DMA_54 */
+#define OMAP24XX_DMA_USB_W2FC_RX0	56	/* S_DMA_55 */
+#define OMAP24XX_DMA_USB_W2FC_TX1	57	/* S_DMA_56 */
+#define OMAP24XX_DMA_USB_W2FC_RX1	58	/* S_DMA_57 */
+#define OMAP24XX_DMA_USB_W2FC_TX2	59	/* S_DMA_58 */
+#define OMAP24XX_DMA_USB_W2FC_RX2	60	/* S_DMA_59 */
+#define OMAP24XX_DMA_MMC1_TX		61	/* S_DMA_60 */
+#define OMAP24XX_DMA_MMC1_RX		62	/* S_DMA_61 */
+#define OMAP24XX_DMA_MS			63	/* S_DMA_62 */
+#define OMAP242X_DMA_EXT_DMAREQ5	64	/* S_DMA_63 */
+#define OMAP243X_DMA_EXT_DMAREQ6	64	/* S_DMA_63 */
+#define OMAP34XX_DMA_EXT_DMAREQ3	64	/* S_DMA_63 */
+#define OMAP34XX_DMA_AES2_TX		65	/* S_DMA_64 */
+#define OMAP34XX_DMA_AES2_RX		66	/* S_DMA_65 */
+#define OMAP34XX_DMA_DES2_TX		67	/* S_DMA_66 */
+#define OMAP34XX_DMA_DES2_RX		68	/* S_DMA_67 */
+#define OMAP34XX_DMA_SHA1MD5_RX		69	/* S_DMA_68 */
+#define OMAP34XX_DMA_SPI4_TX0		70	/* S_DMA_69 */
+#define OMAP34XX_DMA_SPI4_RX0		71	/* S_DMA_70 */
+#define OMAP34XX_DSS_DMA0		72	/* S_DMA_71 */
+#define OMAP34XX_DSS_DMA1		73	/* S_DMA_72 */
+#define OMAP34XX_DSS_DMA2		74	/* S_DMA_73 */
+#define OMAP34XX_DSS_DMA3		75	/* S_DMA_74 */
+#define OMAP34XX_DMA_MMC3_TX		77	/* S_DMA_76 */
+#define OMAP34XX_DMA_MMC3_RX		78	/* S_DMA_77 */
+#define OMAP34XX_DMA_USIM_TX		79	/* S_DMA_78 */
+#define OMAP34XX_DMA_USIM_RX		80	/* S_DMA_79 */
+
+#define OMAP36XX_DMA_UART4_TX		81	/* S_DMA_80 */
+#define OMAP36XX_DMA_UART4_RX		82	/* S_DMA_81 */
+
+/* Only for AM35xx */
+#define AM35XX_DMA_UART4_TX		54
+#define AM35XX_DMA_UART4_RX		55
+
+#endif /* __OMAP2PLUS_DMA_CHANNEL_H */
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index 814e180..fafb28c 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -28,9 +28,8 @@
 #include <linux/bitops.h>
 #include <linux/clkdev.h>
 
-#include <plat/clock.h>
-
 #include "soc.h"
+#include "clockdomain.h"
 #include "clock.h"
 #include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
@@ -44,7 +43,7 @@
 /* Private functions */
 
 /* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
-static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
+static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits)
 {
 	const struct dpll_data *dd;
 	u32 v;
@@ -58,7 +57,7 @@ static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
 }
 
 /* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
-static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
+static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state)
 {
 	const struct dpll_data *dd;
 	int i = 0;
@@ -66,7 +65,7 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
 	const char *clk_name;
 
 	dd = clk->dpll_data;
-	clk_name = __clk_get_name(clk);
+	clk_name = __clk_get_name(clk->hw.clk);
 
 	state <<= __ffs(dd->idlest_mask);
 
@@ -90,7 +89,7 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
 }
 
 /* From 3430 TRM ES2 4.7.6.2 */
-static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
+static u16 _omap3_dpll_compute_freqsel(struct clk_hw_omap *clk, u8 n)
 {
 	unsigned long fint;
 	u16 f = 0;
@@ -135,14 +134,14 @@ static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
  * locked successfully, return 0; if the DPLL did not lock in the time
  * allotted, or DPLL3 was passed in, return -EINVAL.
  */
-static int _omap3_noncore_dpll_lock(struct clk *clk)
+static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk)
 {
 	const struct dpll_data *dd;
 	u8 ai;
 	u8 state = 1;
 	int r = 0;
 
-	pr_debug("clock: locking DPLL %s\n", __clk_get_name(clk));
+	pr_debug("clock: locking DPLL %s\n", __clk_get_name(clk->hw.clk));
 
 	dd = clk->dpll_data;
 	state <<= __ffs(dd->idlest_mask);
@@ -180,7 +179,7 @@ done:
  * DPLL3 was passed in, or the DPLL does not support low-power bypass,
  * return -EINVAL.
  */
-static int _omap3_noncore_dpll_bypass(struct clk *clk)
+static int _omap3_noncore_dpll_bypass(struct clk_hw_omap *clk)
 {
 	int r;
 	u8 ai;
@@ -189,7 +188,7 @@ static int _omap3_noncore_dpll_bypass(struct clk *clk)
 		return -EINVAL;
 
 	pr_debug("clock: configuring DPLL %s for low-power bypass\n",
-		 __clk_get_name(clk));
+		 __clk_get_name(clk->hw.clk));
 
 	ai = omap3_dpll_autoidle_read(clk);
 
@@ -212,14 +211,14 @@ static int _omap3_noncore_dpll_bypass(struct clk *clk)
  * code.  If DPLL3 was passed in, or the DPLL does not support
  * low-power stop, return -EINVAL; otherwise, return 0.
  */
-static int _omap3_noncore_dpll_stop(struct clk *clk)
+static int _omap3_noncore_dpll_stop(struct clk_hw_omap *clk)
 {
 	u8 ai;
 
 	if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP)))
 		return -EINVAL;
 
-	pr_debug("clock: stopping DPLL %s\n", __clk_get_name(clk));
+	pr_debug("clock: stopping DPLL %s\n", __clk_get_name(clk->hw.clk));
 
 	ai = omap3_dpll_autoidle_read(clk);
 
@@ -243,11 +242,11 @@ static int _omap3_noncore_dpll_stop(struct clk *clk)
  * XXX This code is not needed for 3430/AM35xx; can it be optimized
  * out in non-multi-OMAP builds for those chips?
  */
-static void _lookup_dco(struct clk *clk, u8 *dco, u16 m, u8 n)
+static void _lookup_dco(struct clk_hw_omap *clk, u8 *dco, u16 m, u8 n)
 {
 	unsigned long fint, clkinp; /* watch out for overflow */
 
-	clkinp = __clk_get_rate(__clk_get_parent(clk));
+	clkinp = __clk_get_rate(__clk_get_parent(clk->hw.clk));
 	fint = (clkinp / n) * m;
 
 	if (fint < 1000000000)
@@ -268,12 +267,12 @@ static void _lookup_dco(struct clk *clk, u8 *dco, u16 m, u8 n)
  * XXX This code is not needed for 3430/AM35xx; can it be optimized
  * out in non-multi-OMAP builds for those chips?
  */
-static void _lookup_sddiv(struct clk *clk, u8 *sd_div, u16 m, u8 n)
+static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n)
 {
 	unsigned long clkinp, sd; /* watch out for overflow */
 	int mod1, mod2;
 
-	clkinp = __clk_get_rate(__clk_get_parent(clk));
+	clkinp = __clk_get_rate(__clk_get_parent(clk->hw.clk));
 
 	/*
 	 * target sigma-delta to near 250MHz
@@ -300,7 +299,8 @@ static void _lookup_sddiv(struct clk *clk, u8 *sd_div, u16 m, u8 n)
  * Program the DPLL with the supplied M, N values, and wait for the DPLL to
  * lock..  Returns -EINVAL upon error, or 0 upon success.
  */
-static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
+static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 m, u8 n,
+				      u16 freqsel)
 {
 	struct dpll_data *dd = clk->dpll_data;
 	u8 dco, sd_div;
@@ -357,8 +357,10 @@ static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
  *
  * Recalculate and propagate the DPLL rate.
  */
-unsigned long omap3_dpll_recalc(struct clk *clk)
+unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate)
 {
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+
 	return omap2_get_dpll_rate(clk);
 }
 
@@ -378,8 +380,9 @@ unsigned long omap3_dpll_recalc(struct clk *clk)
  * support low-power stop, or if the DPLL took too long to enter
  * bypass or lock, return -EINVAL; otherwise, return 0.
  */
-int omap3_noncore_dpll_enable(struct clk *clk)
+int omap3_noncore_dpll_enable(struct clk_hw *hw)
 {
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	int r;
 	struct dpll_data *dd;
 	struct clk *parent;
@@ -388,22 +391,26 @@ int omap3_noncore_dpll_enable(struct clk *clk)
 	if (!dd)
 		return -EINVAL;
 
-	parent = __clk_get_parent(clk);
+	if (clk->clkdm) {
+		r = clkdm_clk_enable(clk->clkdm, hw->clk);
+		if (r) {
+			WARN(1,
+			     "%s: could not enable %s's clockdomain %s: %d\n",
+			     __func__, __clk_get_name(hw->clk),
+			     clk->clkdm->name, r);
+			return r;
+		}
+	}
 
-	if (__clk_get_rate(clk) == __clk_get_rate(dd->clk_bypass)) {
+	parent = __clk_get_parent(hw->clk);
+
+	if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
 		WARN_ON(parent != dd->clk_bypass);
 		r = _omap3_noncore_dpll_bypass(clk);
 	} else {
 		WARN_ON(parent != dd->clk_ref);
 		r = _omap3_noncore_dpll_lock(clk);
 	}
-	/*
-	 *FIXME: this is dubious - if clk->rate has changed, what about
-	 * propagating?
-	 */
-	if (!r)
-		clk->rate = (clk->recalc) ? clk->recalc(clk) :
-			omap2_get_dpll_rate(clk);
 
 	return r;
 }
@@ -415,9 +422,13 @@ int omap3_noncore_dpll_enable(struct clk *clk)
  * Instructs a non-CORE DPLL to enter low-power stop.  This function is
  * intended for use in struct clkops.  No return value.
  */
-void omap3_noncore_dpll_disable(struct clk *clk)
+void omap3_noncore_dpll_disable(struct clk_hw *hw)
 {
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+
 	_omap3_noncore_dpll_stop(clk);
+	if (clk->clkdm)
+		clkdm_clk_disable(clk->clkdm, hw->clk);
 }
 
 
@@ -434,80 +445,72 @@ void omap3_noncore_dpll_disable(struct clk *clk)
  * target rate if it hasn't been done already, then program and lock
  * the DPLL.  Returns -EINVAL upon error, or 0 upon success.
  */
-int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
+int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long parent_rate)
 {
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	struct clk *new_parent = NULL;
-	unsigned long hw_rate, bypass_rate;
 	u16 freqsel = 0;
 	struct dpll_data *dd;
 	int ret;
 
-	if (!clk || !rate)
+	if (!hw || !rate)
 		return -EINVAL;
 
 	dd = clk->dpll_data;
 	if (!dd)
 		return -EINVAL;
 
-	hw_rate = (clk->recalc) ? clk->recalc(clk) : omap2_get_dpll_rate(clk);
-	if (rate == hw_rate)
-		return 0;
+	__clk_prepare(dd->clk_bypass);
+	clk_enable(dd->clk_bypass);
+	__clk_prepare(dd->clk_ref);
+	clk_enable(dd->clk_ref);
 
-	/*
-	 * Ensure both the bypass and ref clocks are enabled prior to
-	 * doing anything; we need the bypass clock running to reprogram
-	 * the DPLL.
-	 */
-	omap2_clk_enable(dd->clk_bypass);
-	omap2_clk_enable(dd->clk_ref);
-
-	bypass_rate = __clk_get_rate(dd->clk_bypass);
-	if (bypass_rate == rate &&
-	    (clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
-		pr_debug("clock: %s: set rate: entering bypass.\n", clk->name);
+	if (__clk_get_rate(dd->clk_bypass) == rate &&
+	    (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
+		pr_debug("%s: %s: set rate: entering bypass.\n",
+			 __func__, __clk_get_name(hw->clk));
 
 		ret = _omap3_noncore_dpll_bypass(clk);
 		if (!ret)
 			new_parent = dd->clk_bypass;
 	} else {
 		if (dd->last_rounded_rate != rate)
-			rate = clk->round_rate(clk, rate);
+			rate = __clk_round_rate(hw->clk, rate);
 
 		if (dd->last_rounded_rate == 0)
 			return -EINVAL;
 
 		/* No freqsel on OMAP4 and OMAP3630 */
-		if (!soc_is_am33xx() && !cpu_is_omap44xx() && !cpu_is_omap3630()) {
+		if (!cpu_is_omap44xx() && !cpu_is_omap3630()) {
 			freqsel = _omap3_dpll_compute_freqsel(clk,
 						dd->last_rounded_n);
 			if (!freqsel)
 				WARN_ON(1);
 		}
 
-		pr_debug("clock: %s: set rate: locking rate to %lu.\n",
-			 __clk_get_name(clk), rate);
+		pr_debug("%s: %s: set rate: locking rate to %lu.\n",
+			 __func__, __clk_get_name(hw->clk), rate);
 
 		ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m,
-						 dd->last_rounded_n, freqsel);
+						dd->last_rounded_n, freqsel);
 		if (!ret)
 			new_parent = dd->clk_ref;
 	}
-	if (!ret) {
-		/*
-		 * Switch the parent clock in the hierarchy, and make sure
-		 * that the new parent's usecount is correct.  Note: we
-		 * enable the new parent before disabling the old to avoid
-		 * any unnecessary hardware disable->enable transitions.
-		 */
-		if (clk->usecount) {
-			omap2_clk_enable(new_parent);
-			omap2_clk_disable(clk->parent);
-		}
-		clk_reparent(clk, new_parent);
-		clk->rate = rate;
-	}
-	omap2_clk_disable(dd->clk_ref);
-	omap2_clk_disable(dd->clk_bypass);
+	/*
+	* FIXME - this is all wrong.  common code handles reparenting and
+	* migrating prepare/enable counts.  dplls should be a multiplexer
+	* clock and this should be a set_parent operation so that all of that
+	* stuff is inherited for free
+	*/
+
+	if (!ret)
+		__clk_reparent(hw->clk, new_parent);
+
+	clk_disable(dd->clk_ref);
+	__clk_unprepare(dd->clk_ref);
+	clk_disable(dd->clk_bypass);
+	__clk_unprepare(dd->clk_bypass);
 
 	return 0;
 }
@@ -522,7 +525,7 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
  * -EINVAL if passed a null pointer or if the struct clk does not
  * appear to refer to a DPLL.
  */
-u32 omap3_dpll_autoidle_read(struct clk *clk)
+u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
 {
 	const struct dpll_data *dd;
 	u32 v;
@@ -551,7 +554,7 @@ u32 omap3_dpll_autoidle_read(struct clk *clk)
  * OMAP3430.  The DPLL will enter low-power stop when its downstream
  * clocks are gated.  No return value.
  */
-void omap3_dpll_allow_idle(struct clk *clk)
+void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
 {
 	const struct dpll_data *dd;
 	u32 v;
@@ -561,11 +564,8 @@ void omap3_dpll_allow_idle(struct clk *clk)
 
 	dd = clk->dpll_data;
 
-	if (!dd->autoidle_reg) {
-		pr_debug("clock: DPLL %s: autoidle not supported\n",
-			__clk_get_name(clk));
+	if (!dd->autoidle_reg)
 		return;
-	}
 
 	/*
 	 * REVISIT: CORE DPLL can optionally enter low-power bypass
@@ -585,7 +585,7 @@ void omap3_dpll_allow_idle(struct clk *clk)
  *
  * Disable DPLL automatic idle control.  No return value.
  */
-void omap3_dpll_deny_idle(struct clk *clk)
+void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
 {
 	const struct dpll_data *dd;
 	u32 v;
@@ -595,11 +595,8 @@ void omap3_dpll_deny_idle(struct clk *clk)
 
 	dd = clk->dpll_data;
 
-	if (!dd->autoidle_reg) {
-		pr_debug("clock: DPLL %s: autoidle not supported\n",
-			__clk_get_name(clk));
+	if (!dd->autoidle_reg)
 		return;
-	}
 
 	v = __raw_readl(dd->autoidle_reg);
 	v &= ~dd->autoidle_mask;
@@ -617,18 +614,25 @@ void omap3_dpll_deny_idle(struct clk *clk)
  * Using parent clock DPLL data, look up DPLL state.  If locked, set our
  * rate to the dpll_clk * 2; otherwise, just use dpll_clk.
  */
-unsigned long omap3_clkoutx2_recalc(struct clk *clk)
+unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
+				    unsigned long parent_rate)
 {
 	const struct dpll_data *dd;
 	unsigned long rate;
 	u32 v;
-	struct clk *pclk;
-	unsigned long parent_rate;
+	struct clk_hw_omap *pclk = NULL;
+	struct clk *parent;
 
 	/* Walk up the parents of clk, looking for a DPLL */
-	pclk = __clk_get_parent(clk);
-	while (pclk && !pclk->dpll_data)
-		pclk = __clk_get_parent(pclk);
+	do {
+		do {
+			parent = __clk_get_parent(hw->clk);
+			hw = __clk_get_hw(parent);
+		} while (hw && (__clk_get_flags(hw->clk) & CLK_IS_BASIC));
+		if (!hw)
+			break;
+		pclk = to_clk_hw_omap(hw);
+	} while (pclk && !pclk->dpll_data);
 
 	/* clk does not have a DPLL as a parent?  error in the clock data */
 	if (!pclk) {
@@ -640,7 +644,6 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
 
 	WARN_ON(!dd->enable_mask);
 
-	parent_rate = __clk_get_rate(__clk_get_parent(clk));
 	v = __raw_readl(dd->control_reg) & dd->enable_mask;
 	v >>= __ffs(dd->enable_mask);
 	if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
@@ -651,15 +654,7 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
 }
 
 /* OMAP3/4 non-CORE DPLL clkops */
-
-const struct clkops clkops_omap3_noncore_dpll_ops = {
-	.enable		= omap3_noncore_dpll_enable,
-	.disable	= omap3_noncore_dpll_disable,
-	.allow_idle	= omap3_dpll_allow_idle,
-	.deny_idle	= omap3_dpll_deny_idle,
-};
-
-const struct clkops clkops_omap3_core_dpll_ops = {
+const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
 	.allow_idle	= omap3_dpll_allow_idle,
 	.deny_idle	= omap3_dpll_deny_idle,
 };
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index 09d0ccc..d3326c4 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -15,15 +15,13 @@
 #include <linux/io.h>
 #include <linux/bitops.h>
 
-#include <plat/clock.h>
-
 #include "soc.h"
 #include "clock.h"
 #include "clock44xx.h"
 #include "cm-regbits-44xx.h"
 
 /* Supported only on OMAP4 */
-int omap4_dpllmx_gatectrl_read(struct clk *clk)
+int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk)
 {
 	u32 v;
 	u32 mask;
@@ -42,7 +40,7 @@ int omap4_dpllmx_gatectrl_read(struct clk *clk)
 	return v;
 }
 
-void omap4_dpllmx_allow_gatectrl(struct clk *clk)
+void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
 {
 	u32 v;
 	u32 mask;
@@ -60,7 +58,7 @@ void omap4_dpllmx_allow_gatectrl(struct clk *clk)
 	__raw_writel(v, clk->clksel_reg);
 }
 
-void omap4_dpllmx_deny_gatectrl(struct clk *clk)
+void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
 {
 	u32 v;
 	u32 mask;
@@ -78,9 +76,9 @@ void omap4_dpllmx_deny_gatectrl(struct clk *clk)
 	__raw_writel(v, clk->clksel_reg);
 }
 
-const struct clkops clkops_omap4_dpllmx_ops = {
+const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = {
 	.allow_idle	= omap4_dpllmx_allow_gatectrl,
-	.deny_idle	= omap4_dpllmx_deny_gatectrl,
+	.deny_idle      = omap4_dpllmx_deny_gatectrl,
 };
 
 /**
@@ -92,8 +90,10 @@ const struct clkops clkops_omap4_dpllmx_ops = {
  * OMAP4 ABE DPLL.  Returns the DPLL's output rate (before M-dividers)
  * upon success, or 0 upon error.
  */
-unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk)
+unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
+			unsigned long parent_rate)
 {
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	u32 v;
 	unsigned long rate;
 	struct dpll_data *dd;
@@ -125,8 +125,11 @@ unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk)
  * M-dividers) upon success, -EINVAL if @clk is null or not a DPLL, or
  * ~0 if an error occurred in omap2_dpll_round_rate().
  */
-long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate)
+long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
+				    unsigned long target_rate,
+				    unsigned long *parent_rate)
 {
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	u32 v;
 	struct dpll_data *dd;
 	long r;
@@ -142,7 +145,7 @@ long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate)
 	if (v)
 		target_rate = target_rate / OMAP4430_REGM4XEN_MULT;
 
-	r = omap2_dpll_round_rate(clk, target_rate);
+	r = omap2_dpll_round_rate(hw, target_rate, NULL);
 	if (r == ~0)
 		return r;
 
diff --git a/arch/arm/mach-omap2/drm.c b/arch/arm/mach-omap2/drm.c
index 72e0f01b..fce5aa3 100644
--- a/arch/arm/mach-omap2/drm.c
+++ b/arch/arm/mach-omap2/drm.c
@@ -23,15 +23,20 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/platform_data/omap_drm.h>
 
-#include <plat/omap_device.h>
-#include <plat/omap_hwmod.h>
+#include "omap_device.h"
+#include "omap_hwmod.h"
+#include <plat/cpu.h>
 
 #if defined(CONFIG_DRM_OMAP) || (CONFIG_DRM_OMAP_MODULE)
 
+static struct omap_drm_platform_data platform_data;
+
 static struct platform_device omap_drm_device = {
 	.dev = {
 		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &platform_data,
 	},
 	.name = "omapdrm",
 	.id = 0,
@@ -52,6 +57,8 @@ static int __init omap_init_drm(void)
 			oh->name);
 	}
 
+	platform_data.omaprev = GET_OMAP_REVISION();
+
 	return platform_device_register(&omap_drm_device);
 
 }
diff --git a/arch/arm/mach-omap2/dsp.c b/arch/arm/mach-omap2/dsp.c
index 9838810..b155500 100644
--- a/arch/arm/mach-omap2/dsp.c
+++ b/arch/arm/mach-omap2/dsp.c
@@ -27,7 +27,7 @@
 #include "cm2xxx_3xxx.h"
 #include "prm2xxx_3xxx.h"
 #ifdef CONFIG_BRIDGE_DVFS
-#include <plat/omap-pm.h>
+#include "omap-pm.h"
 #endif
 
 #include <linux/platform_data/dsp-omap.h>
diff --git a/arch/arm/mach-omap2/dss-common.c b/arch/arm/mach-omap2/dss-common.c
new file mode 100644
index 0000000..679a047
--- /dev/null
+++ b/arch/arm/mach-omap2/dss-common.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2012 Texas Instruments, Inc..
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+/*
+ * NOTE: this is a transitional file to help with DT adaptation.
+ * This file will be removed when DSS supports DT.
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-tfp410.h>
+#include <video/omap-panel-nokia-dsi.h>
+#include <video/omap-panel-picodlp.h>
+
+#include <plat/cpu.h>
+
+#include "dss-common.h"
+#include "mux.h"
+
+#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */
+#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+#define HDMI_GPIO_HPD  63 /* Hotplug detect */
+
+/* Display DVI */
+#define PANDA_DVI_TFP410_POWER_DOWN_GPIO	0
+
+/* Using generic display panel */
+static struct tfp410_platform_data omap4_dvi_panel = {
+	.i2c_bus_num		= 3,
+	.power_down_gpio	= PANDA_DVI_TFP410_POWER_DOWN_GPIO,
+};
+
+static struct omap_dss_device omap4_panda_dvi_device = {
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.name			= "dvi",
+	.driver_name		= "tfp410",
+	.data			= &omap4_dvi_panel,
+	.phy.dpi.data_lines	= 24,
+	.reset_gpio		= PANDA_DVI_TFP410_POWER_DOWN_GPIO,
+	.channel		= OMAP_DSS_CHANNEL_LCD2,
+};
+
+static struct omap_dss_hdmi_data omap4_panda_hdmi_data = {
+	.ct_cp_hpd_gpio = HDMI_GPIO_CT_CP_HPD,
+	.ls_oe_gpio = HDMI_GPIO_LS_OE,
+	.hpd_gpio = HDMI_GPIO_HPD,
+};
+
+static struct omap_dss_device  omap4_panda_hdmi_device = {
+	.name = "hdmi",
+	.driver_name = "hdmi_panel",
+	.type = OMAP_DISPLAY_TYPE_HDMI,
+	.channel = OMAP_DSS_CHANNEL_DIGIT,
+	.data = &omap4_panda_hdmi_data,
+};
+
+static struct omap_dss_device *omap4_panda_dss_devices[] = {
+	&omap4_panda_dvi_device,
+	&omap4_panda_hdmi_device,
+};
+
+static struct omap_dss_board_info omap4_panda_dss_data = {
+	.num_devices	= ARRAY_SIZE(omap4_panda_dss_devices),
+	.devices	= omap4_panda_dss_devices,
+	.default_device	= &omap4_panda_dvi_device,
+};
+
+void __init omap4_panda_display_init(void)
+{
+	omap_display_init(&omap4_panda_dss_data);
+
+	/*
+	 * OMAP4460SDP/Blaze and OMAP4430 ES2.3 SDP/Blaze boards and
+	 * later have external pull up on the HDMI I2C lines
+	 */
+	if (cpu_is_omap446x() || omap_rev() > OMAP4430_REV_ES2_2)
+		omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP);
+	else
+		omap_hdmi_init(0);
+
+	omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT);
+	omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT);
+	omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN);
+}
+
+void __init omap4_panda_display_init_of(void)
+{
+	omap_display_init(&omap4_panda_dss_data);
+}
+
+
+/* OMAP4 Blaze display data */
+
+#define DISPLAY_SEL_GPIO	59	/* LCD2/PicoDLP switch */
+#define DLP_POWER_ON_GPIO	40
+
+static struct nokia_dsi_panel_data dsi1_panel = {
+		.name		= "taal",
+		.reset_gpio	= 102,
+		.use_ext_te	= false,
+		.ext_te_gpio	= 101,
+		.esd_interval	= 0,
+		.pin_config = {
+			.num_pins	= 6,
+			.pins		= { 0, 1, 2, 3, 4, 5 },
+		},
+};
+
+static struct omap_dss_device sdp4430_lcd_device = {
+	.name			= "lcd",
+	.driver_name		= "taal",
+	.type			= OMAP_DISPLAY_TYPE_DSI,
+	.data			= &dsi1_panel,
+	.phy.dsi		= {
+		.module		= 0,
+	},
+	.channel		= OMAP_DSS_CHANNEL_LCD,
+};
+
+static struct nokia_dsi_panel_data dsi2_panel = {
+		.name		= "taal",
+		.reset_gpio	= 104,
+		.use_ext_te	= false,
+		.ext_te_gpio	= 103,
+		.esd_interval	= 0,
+		.pin_config = {
+			.num_pins	= 6,
+			.pins		= { 0, 1, 2, 3, 4, 5 },
+		},
+};
+
+static struct omap_dss_device sdp4430_lcd2_device = {
+	.name			= "lcd2",
+	.driver_name		= "taal",
+	.type			= OMAP_DISPLAY_TYPE_DSI,
+	.data			= &dsi2_panel,
+	.phy.dsi		= {
+
+		.module		= 1,
+	},
+	.channel		= OMAP_DSS_CHANNEL_LCD2,
+};
+
+static struct omap_dss_hdmi_data sdp4430_hdmi_data = {
+	.ct_cp_hpd_gpio = HDMI_GPIO_CT_CP_HPD,
+	.ls_oe_gpio = HDMI_GPIO_LS_OE,
+	.hpd_gpio = HDMI_GPIO_HPD,
+};
+
+static struct omap_dss_device sdp4430_hdmi_device = {
+	.name = "hdmi",
+	.driver_name = "hdmi_panel",
+	.type = OMAP_DISPLAY_TYPE_HDMI,
+	.channel = OMAP_DSS_CHANNEL_DIGIT,
+	.data = &sdp4430_hdmi_data,
+};
+
+static struct picodlp_panel_data sdp4430_picodlp_pdata = {
+	.picodlp_adapter_id	= 2,
+	.emu_done_gpio		= 44,
+	.pwrgood_gpio		= 45,
+};
+
+static void sdp4430_picodlp_init(void)
+{
+	int r;
+	const struct gpio picodlp_gpios[] = {
+		{DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW,
+			"DLP POWER ON"},
+		{sdp4430_picodlp_pdata.emu_done_gpio, GPIOF_IN,
+			"DLP EMU DONE"},
+		{sdp4430_picodlp_pdata.pwrgood_gpio, GPIOF_OUT_INIT_LOW,
+			"DLP PWRGOOD"},
+	};
+
+	r = gpio_request_array(picodlp_gpios, ARRAY_SIZE(picodlp_gpios));
+	if (r)
+		pr_err("Cannot request PicoDLP GPIOs, error %d\n", r);
+}
+
+static int sdp4430_panel_enable_picodlp(struct omap_dss_device *dssdev)
+{
+	gpio_set_value(DISPLAY_SEL_GPIO, 0);
+	gpio_set_value(DLP_POWER_ON_GPIO, 1);
+
+	return 0;
+}
+
+static void sdp4430_panel_disable_picodlp(struct omap_dss_device *dssdev)
+{
+	gpio_set_value(DLP_POWER_ON_GPIO, 0);
+	gpio_set_value(DISPLAY_SEL_GPIO, 1);
+}
+
+static struct omap_dss_device sdp4430_picodlp_device = {
+	.name			= "picodlp",
+	.driver_name		= "picodlp_panel",
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.phy.dpi.data_lines	= 24,
+	.channel		= OMAP_DSS_CHANNEL_LCD2,
+	.platform_enable	= sdp4430_panel_enable_picodlp,
+	.platform_disable	= sdp4430_panel_disable_picodlp,
+	.data			= &sdp4430_picodlp_pdata,
+};
+
+static struct omap_dss_device *sdp4430_dss_devices[] = {
+	&sdp4430_lcd_device,
+	&sdp4430_lcd2_device,
+	&sdp4430_hdmi_device,
+	&sdp4430_picodlp_device,
+};
+
+static struct omap_dss_board_info sdp4430_dss_data = {
+	.num_devices	= ARRAY_SIZE(sdp4430_dss_devices),
+	.devices	= sdp4430_dss_devices,
+	.default_device	= &sdp4430_lcd_device,
+};
+
+void __init omap_4430sdp_display_init(void)
+{
+	int r;
+
+	/* Enable LCD2 by default (instead of Pico DLP) */
+	r = gpio_request_one(DISPLAY_SEL_GPIO, GPIOF_OUT_INIT_HIGH,
+			"display_sel");
+	if (r)
+		pr_err("%s: Could not get display_sel GPIO\n", __func__);
+
+	sdp4430_picodlp_init();
+	omap_display_init(&sdp4430_dss_data);
+	/*
+	 * OMAP4460SDP/Blaze and OMAP4430 ES2.3 SDP/Blaze boards and
+	 * later have external pull up on the HDMI I2C lines
+	 */
+	if (cpu_is_omap446x() || omap_rev() > OMAP4430_REV_ES2_2)
+		omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP);
+	else
+		omap_hdmi_init(0);
+
+	omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT);
+	omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT);
+	omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN);
+}
+
+void __init omap_4430sdp_display_init_of(void)
+{
+	int r;
+
+	/* Enable LCD2 by default (instead of Pico DLP) */
+	r = gpio_request_one(DISPLAY_SEL_GPIO, GPIOF_OUT_INIT_HIGH,
+			"display_sel");
+	if (r)
+		pr_err("%s: Could not get display_sel GPIO\n", __func__);
+
+	sdp4430_picodlp_init();
+	omap_display_init(&sdp4430_dss_data);
+}
diff --git a/arch/arm/mach-omap2/dss-common.h b/arch/arm/mach-omap2/dss-common.h
new file mode 100644
index 0000000..915f6ff
--- /dev/null
+++ b/arch/arm/mach-omap2/dss-common.h
@@ -0,0 +1,14 @@
+#ifndef __OMAP_DSS_COMMON__
+#define __OMAP_DSS_COMMON__
+
+/*
+ * NOTE: this is a transitional file to help with DT adaptation.
+ * This file will be removed when DSS supports DT.
+ */
+
+void __init omap4_panda_display_init(void);
+void __init omap4_panda_display_init_of(void);
+void __init omap_4430sdp_display_init(void);
+void __init omap_4430sdp_display_init_of(void);
+
+#endif
diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c
index d1058f1..399acab 100644
--- a/arch/arm/mach-omap2/gpio.c
+++ b/arch/arm/mach-omap2/gpio.c
@@ -23,9 +23,9 @@
 #include <linux/of.h>
 #include <linux/platform_data/gpio-omap.h>
 
-#include <plat/omap_hwmod.h>
-#include <plat/omap_device.h>
-#include <plat/omap-pm.h>
+#include "omap_hwmod.h"
+#include "omap_device.h"
+#include "omap-pm.h"
 
 #include "powerdomain.h"
 
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 4acf497..db969a5 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -17,9 +17,12 @@
 
 #include <asm/mach/flash.h>
 
-#include <plat/gpmc.h>
-
+#include "gpmc.h"
 #include "soc.h"
+#include "gpmc-nand.h"
+
+/* minimum size for IO mapping */
+#define	NAND_IO_SIZE	4
 
 static struct resource gpmc_nand_resource[] = {
 	{
@@ -40,41 +43,36 @@ static struct platform_device gpmc_nand_device = {
 	.resource	= gpmc_nand_resource,
 };
 
-static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data)
+static int omap2_nand_gpmc_retime(
+				struct omap_nand_platform_data *gpmc_nand_data,
+				struct gpmc_timings *gpmc_t)
 {
 	struct gpmc_timings t;
 	int err;
 
-	if (!gpmc_nand_data->gpmc_t)
-		return 0;
-
 	memset(&t, 0, sizeof(t));
-	t.sync_clk = gpmc_nand_data->gpmc_t->sync_clk;
-	t.cs_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_on);
-	t.adv_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->adv_on);
+	t.sync_clk = gpmc_t->sync_clk;
+	t.cs_on = gpmc_t->cs_on;
+	t.adv_on = gpmc_t->adv_on;
 
 	/* Read */
-	t.adv_rd_off = gpmc_round_ns_to_ticks(
-				gpmc_nand_data->gpmc_t->adv_rd_off);
+	t.adv_rd_off = gpmc_t->adv_rd_off;
 	t.oe_on  = t.adv_on;
-	t.access = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->access);
-	t.oe_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->oe_off);
-	t.cs_rd_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_rd_off);
-	t.rd_cycle  = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->rd_cycle);
+	t.access = gpmc_t->access;
+	t.oe_off = gpmc_t->oe_off;
+	t.cs_rd_off = gpmc_t->cs_rd_off;
+	t.rd_cycle = gpmc_t->rd_cycle;
 
 	/* Write */
-	t.adv_wr_off = gpmc_round_ns_to_ticks(
-				gpmc_nand_data->gpmc_t->adv_wr_off);
+	t.adv_wr_off = gpmc_t->adv_wr_off;
 	t.we_on  = t.oe_on;
 	if (cpu_is_omap34xx()) {
-	    t.wr_data_mux_bus =	gpmc_round_ns_to_ticks(
-				gpmc_nand_data->gpmc_t->wr_data_mux_bus);
-	    t.wr_access = gpmc_round_ns_to_ticks(
-				gpmc_nand_data->gpmc_t->wr_access);
+		t.wr_data_mux_bus = gpmc_t->wr_data_mux_bus;
+		t.wr_access = gpmc_t->wr_access;
 	}
-	t.we_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->we_off);
-	t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_wr_off);
-	t.wr_cycle  = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle);
+	t.we_off = gpmc_t->we_off;
+	t.cs_wr_off = gpmc_t->cs_wr_off;
+	t.wr_cycle = gpmc_t->wr_cycle;
 
 	/* Configure GPMC */
 	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
@@ -91,7 +89,29 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data
 	return 0;
 }
 
-int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
+static bool __init gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
+{
+	/* support only OMAP3 class */
+	if (!cpu_is_omap34xx()) {
+		pr_err("BCH ecc is not supported on this CPU\n");
+		return 0;
+	}
+
+	/*
+	 * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1.
+	 * Other chips may be added if confirmed to work.
+	 */
+	if ((ecc_opt == OMAP_ECC_BCH4_CODE_HW) &&
+	    (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0))) {
+		pr_err("BCH 4-bit mode is not supported on this CPU\n");
+		return 0;
+	}
+
+	return 1;
+}
+
+int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
+			  struct gpmc_timings *gpmc_t)
 {
 	int err	= 0;
 	struct device *dev = &gpmc_nand_device.dev;
@@ -112,11 +132,13 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
 				gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE);
 	gpmc_nand_resource[2].start =
 				gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
-	 /* Set timings in GPMC */
-	err = omap2_nand_gpmc_retime(gpmc_nand_data);
-	if (err < 0) {
-		dev_err(dev, "Unable to set gpmc timings: %d\n", err);
-		return err;
+
+	if (gpmc_t) {
+		err = omap2_nand_gpmc_retime(gpmc_nand_data, gpmc_t);
+		if (err < 0) {
+			dev_err(dev, "Unable to set gpmc timings: %d\n", err);
+			return err;
+		}
 	}
 
 	/* Enable RD PIN Monitoring Reg */
@@ -126,6 +148,9 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
 
 	gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs);
 
+	if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt))
+		return -EINVAL;
+
 	err = platform_device_register(&gpmc_nand_device);
 	if (err < 0) {
 		dev_err(dev, "Unable to register NAND device\n");
diff --git a/arch/arm/mach-omap2/gpmc-nand.h b/arch/arm/mach-omap2/gpmc-nand.h
new file mode 100644
index 0000000..d59e128
--- /dev/null
+++ b/arch/arm/mach-omap2/gpmc-nand.h
@@ -0,0 +1,27 @@
+/*
+ *  arch/arm/mach-omap2/gpmc-nand.h
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef	__OMAP2_GPMC_NAND_H
+#define	__OMAP2_GPMC_NAND_H
+
+#include "gpmc.h"
+#include <linux/platform_data/mtd-nand-omap2.h>
+
+#if IS_ENABLED(CONFIG_MTD_NAND_OMAP2)
+extern int gpmc_nand_init(struct omap_nand_platform_data *d,
+			  struct gpmc_timings *gpmc_t);
+#else
+static inline int gpmc_nand_init(struct omap_nand_platform_data *d,
+				 struct gpmc_timings *gpmc_t)
+{
+	return 0;
+}
+#endif
+
+#endif
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index 916716e..94a349e 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -16,15 +16,24 @@
 #include <linux/mtd/onenand_regs.h>
 #include <linux/io.h>
 #include <linux/platform_data/mtd-onenand-omap2.h>
+#include <linux/err.h>
 
 #include <asm/mach/flash.h>
 
-#include <plat/gpmc.h>
-
+#include "gpmc.h"
 #include "soc.h"
+#include "gpmc-onenand.h"
 
 #define	ONENAND_IO_SIZE	SZ_128K
 
+#define	ONENAND_FLAG_SYNCREAD	(1 << 0)
+#define	ONENAND_FLAG_SYNCWRITE	(1 << 1)
+#define	ONENAND_FLAG_HF		(1 << 2)
+#define	ONENAND_FLAG_VHF	(1 << 3)
+
+static unsigned onenand_flags;
+static unsigned latency;
+
 static struct omap_onenand_platform_data *gpmc_onenand_data;
 
 static struct resource gpmc_onenand_resource = {
@@ -38,11 +47,10 @@ static struct platform_device gpmc_onenand_device = {
 	.resource	= &gpmc_onenand_resource,
 };
 
-static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
+static struct gpmc_timings omap2_onenand_calc_async_timings(void)
 {
+	struct gpmc_device_timings dev_t;
 	struct gpmc_timings t;
-	u32 reg;
-	int err;
 
 	const int t_cer = 15;
 	const int t_avdp = 12;
@@ -51,60 +59,49 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
 	const int t_aa = 76;
 	const int t_oe = 20;
 	const int t_cez = 20; /* max of t_cez, t_oez */
-	const int t_ds = 30;
 	const int t_wpl = 40;
 	const int t_wph = 30;
 
-	/* Ensure sync read and sync write are disabled */
-	reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
-	reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE;
-	writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
+	memset(&dev_t, 0, sizeof(dev_t));
 
-	memset(&t, 0, sizeof(t));
-	t.sync_clk = 0;
-	t.cs_on = 0;
-	t.adv_on = 0;
-
-	/* Read */
-	t.adv_rd_off = gpmc_round_ns_to_ticks(max_t(int, t_avdp, t_cer));
-	t.oe_on  = t.adv_rd_off + gpmc_round_ns_to_ticks(t_aavdh);
-	t.access = t.adv_on + gpmc_round_ns_to_ticks(t_aa);
-	t.access = max_t(int, t.access, t.cs_on + gpmc_round_ns_to_ticks(t_ce));
-	t.access = max_t(int, t.access, t.oe_on + gpmc_round_ns_to_ticks(t_oe));
-	t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
-	t.cs_rd_off = t.oe_off;
-	t.rd_cycle  = t.cs_rd_off + gpmc_round_ns_to_ticks(t_cez);
-
-	/* Write */
-	t.adv_wr_off = t.adv_rd_off;
-	t.we_on  = t.oe_on;
-	if (cpu_is_omap34xx()) {
-		t.wr_data_mux_bus = t.we_on;
-		t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds);
-	}
-	t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl);
-	t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
-	t.wr_cycle  = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
+	dev_t.mux = true;
+	dev_t.t_avdp_r = max_t(int, t_avdp, t_cer) * 1000;
+	dev_t.t_avdp_w = dev_t.t_avdp_r;
+	dev_t.t_aavdh = t_aavdh * 1000;
+	dev_t.t_aa = t_aa * 1000;
+	dev_t.t_ce = t_ce * 1000;
+	dev_t.t_oe = t_oe * 1000;
+	dev_t.t_cez_r = t_cez * 1000;
+	dev_t.t_cez_w = dev_t.t_cez_r;
+	dev_t.t_wpl = t_wpl * 1000;
+	dev_t.t_wph = t_wph * 1000;
+
+	gpmc_calc_timings(&t, &dev_t);
+
+	return t;
+}
 
+static int gpmc_set_async_mode(int cs, struct gpmc_timings *t)
+{
 	/* Configure GPMC for asynchronous read */
 	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
 			  GPMC_CONFIG1_DEVICESIZE_16 |
 			  GPMC_CONFIG1_MUXADDDATA);
 
-	err = gpmc_cs_set_timings(cs, &t);
-	if (err)
-		return err;
+	return gpmc_cs_set_timings(cs, t);
+}
+
+static void omap2_onenand_set_async_mode(void __iomem *onenand_base)
+{
+	u32 reg;
 
 	/* Ensure sync read and sync write are disabled */
 	reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
 	reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE;
 	writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
-
-	return 0;
 }
 
-static void set_onenand_cfg(void __iomem *onenand_base, int latency,
-				int sync_read, int sync_write, int hf, int vhf)
+static void set_onenand_cfg(void __iomem *onenand_base)
 {
 	u32 reg;
 
@@ -112,19 +109,19 @@ static void set_onenand_cfg(void __iomem *onenand_base, int latency,
 	reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
 	reg |=	(latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
 		ONENAND_SYS_CFG1_BL_16;
-	if (sync_read)
+	if (onenand_flags & ONENAND_FLAG_SYNCREAD)
 		reg |= ONENAND_SYS_CFG1_SYNC_READ;
 	else
 		reg &= ~ONENAND_SYS_CFG1_SYNC_READ;
-	if (sync_write)
+	if (onenand_flags & ONENAND_FLAG_SYNCWRITE)
 		reg |= ONENAND_SYS_CFG1_SYNC_WRITE;
 	else
 		reg &= ~ONENAND_SYS_CFG1_SYNC_WRITE;
-	if (hf)
+	if (onenand_flags & ONENAND_FLAG_HF)
 		reg |= ONENAND_SYS_CFG1_HF;
 	else
 		reg &= ~ONENAND_SYS_CFG1_HF;
-	if (vhf)
+	if (onenand_flags & ONENAND_FLAG_VHF)
 		reg |= ONENAND_SYS_CFG1_VHF;
 	else
 		reg &= ~ONENAND_SYS_CFG1_VHF;
@@ -132,21 +129,10 @@ static void set_onenand_cfg(void __iomem *onenand_base, int latency,
 }
 
 static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg,
-				  void __iomem *onenand_base, bool *clk_dep)
+				  void __iomem *onenand_base)
 {
 	u16 ver = readw(onenand_base + ONENAND_REG_VERSION_ID);
-	int freq = 0;
-
-	if (cfg->get_freq) {
-		struct onenand_freq_info fi;
-
-		fi.maf_id = readw(onenand_base + ONENAND_REG_MANUFACTURER_ID);
-		fi.dev_id = readw(onenand_base + ONENAND_REG_DEVICE_ID);
-		fi.ver_id = ver;
-		freq = cfg->get_freq(&fi, clk_dep);
-		if (freq)
-			return freq;
-	}
+	int freq;
 
 	switch ((ver >> 4) & 0xf) {
 	case 0:
@@ -172,41 +158,24 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg,
 	return freq;
 }
 
-static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
-					void __iomem *onenand_base,
-					int *freq_ptr)
+static struct gpmc_timings
+omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
+				int freq)
 {
+	struct gpmc_device_timings dev_t;
 	struct gpmc_timings t;
 	const int t_cer  = 15;
 	const int t_avdp = 12;
 	const int t_cez  = 20; /* max of t_cez, t_oez */
-	const int t_ds   = 30;
 	const int t_wpl  = 40;
 	const int t_wph  = 30;
 	int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
-	int div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency;
-	int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0;
-	int err, ticks_cez;
-	int cs = cfg->cs, freq = *freq_ptr;
-	u32 reg;
-	bool clk_dep = false;
+	int div, gpmc_clk_ns;
 
-	if (cfg->flags & ONENAND_SYNC_READ) {
-		sync_read = 1;
-	} else if (cfg->flags & ONENAND_SYNC_READWRITE) {
-		sync_read = 1;
-		sync_write = 1;
-	} else
-		return omap2_onenand_set_async_mode(cs, onenand_base);
-
-	if (!freq) {
-		/* Very first call freq is not known */
-		err = omap2_onenand_set_async_mode(cs, onenand_base);
-		if (err)
-			return err;
-		freq = omap2_onenand_get_freq(cfg, onenand_base, &clk_dep);
-		first_time = 1;
-	}
+	if (cfg->flags & ONENAND_SYNC_READ)
+		onenand_flags = ONENAND_FLAG_SYNCREAD;
+	else if (cfg->flags & ONENAND_SYNC_READWRITE)
+		onenand_flags = ONENAND_FLAG_SYNCREAD | ONENAND_FLAG_SYNCWRITE;
 
 	switch (freq) {
 	case 104:
@@ -244,116 +213,67 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 		t_ach   = 9;
 		t_aavdh = 7;
 		t_rdyo  = 15;
-		sync_write = 0;
+		onenand_flags &= ~ONENAND_FLAG_SYNCWRITE;
 		break;
 	}
 
-	div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period);
+	div = gpmc_calc_divider(min_gpmc_clk_period);
 	gpmc_clk_ns = gpmc_ticks_to_ns(div);
 	if (gpmc_clk_ns < 15) /* >66Mhz */
-		hf = 1;
+		onenand_flags |= ONENAND_FLAG_HF;
+	else
+		onenand_flags &= ~ONENAND_FLAG_HF;
 	if (gpmc_clk_ns < 12) /* >83Mhz */
-		vhf = 1;
-	if (vhf)
+		onenand_flags |= ONENAND_FLAG_VHF;
+	else
+		onenand_flags &= ~ONENAND_FLAG_VHF;
+	if (onenand_flags & ONENAND_FLAG_VHF)
 		latency = 8;
-	else if (hf)
+	else if (onenand_flags & ONENAND_FLAG_HF)
 		latency = 6;
 	else if (gpmc_clk_ns >= 25) /* 40 MHz*/
 		latency = 3;
 	else
 		latency = 4;
 
-	if (clk_dep) {
-		if (gpmc_clk_ns < 12) { /* >83Mhz */
-			t_ces   = 3;
-			t_avds  = 4;
-		} else if (gpmc_clk_ns < 15) { /* >66Mhz */
-			t_ces   = 5;
-			t_avds  = 4;
-		} else if (gpmc_clk_ns < 25) { /* >40Mhz */
-			t_ces   = 6;
-			t_avds  = 5;
-		} else {
-			t_ces   = 7;
-			t_avds  = 7;
-		}
-	}
+	/* Set synchronous read timings */
+	memset(&dev_t, 0, sizeof(dev_t));
 
-	if (first_time)
-		set_onenand_cfg(onenand_base, latency,
-					sync_read, sync_write, hf, vhf);
-
-	if (div == 1) {
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
-		reg |= (1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
-		reg |= (1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
-		reg |= (1 << 7);
-		reg |= (1 << 23);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
+	dev_t.mux = true;
+	dev_t.sync_read = true;
+	if (onenand_flags & ONENAND_FLAG_SYNCWRITE) {
+		dev_t.sync_write = true;
 	} else {
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
-		reg &= ~(1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
-		reg &= ~(1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
-		reg &= ~(1 << 7);
-		reg &= ~(1 << 23);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
+		dev_t.t_avdp_w = max(t_avdp, t_cer) * 1000;
+		dev_t.t_wpl = t_wpl * 1000;
+		dev_t.t_wph = t_wph * 1000;
+		dev_t.t_aavdh = t_aavdh * 1000;
 	}
+	dev_t.ce_xdelay = true;
+	dev_t.avd_xdelay = true;
+	dev_t.oe_xdelay = true;
+	dev_t.we_xdelay = true;
+	dev_t.clk = min_gpmc_clk_period;
+	dev_t.t_bacc = dev_t.clk;
+	dev_t.t_ces = t_ces * 1000;
+	dev_t.t_avds = t_avds * 1000;
+	dev_t.t_avdh = t_avdh * 1000;
+	dev_t.t_ach = t_ach * 1000;
+	dev_t.cyc_iaa = (latency + 1);
+	dev_t.t_cez_r = t_cez * 1000;
+	dev_t.t_cez_w = dev_t.t_cez_r;
+	dev_t.cyc_aavdh_oe = 1;
+	dev_t.t_rdyo = t_rdyo * 1000 + min_gpmc_clk_period;
+
+	gpmc_calc_timings(&t, &dev_t);
+
+	return t;
+}
 
-	/* Set synchronous read timings */
-	memset(&t, 0, sizeof(t));
-	t.sync_clk = min_gpmc_clk_period;
-	t.cs_on = 0;
-	t.adv_on = 0;
-	fclk_offset_ns = gpmc_round_ns_to_ticks(max_t(int, t_ces, t_avds));
-	fclk_offset = gpmc_ns_to_ticks(fclk_offset_ns);
-	t.page_burst_access = gpmc_clk_ns;
-
-	/* Read */
-	t.adv_rd_off = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_avdh));
-	t.oe_on = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_ach));
-	/* Force at least 1 clk between AVD High to OE Low */
-	if (t.oe_on <= t.adv_rd_off)
-		t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(1);
-	t.access = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div);
-	t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
-	t.cs_rd_off = t.oe_off;
-	ticks_cez = ((gpmc_ns_to_ticks(t_cez) + div - 1) / div) * div;
-	t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div +
-		     ticks_cez);
-
-	/* Write */
-	if (sync_write) {
-		t.adv_wr_off = t.adv_rd_off;
-		t.we_on  = 0;
-		t.we_off = t.cs_rd_off;
-		t.cs_wr_off = t.cs_rd_off;
-		t.wr_cycle  = t.rd_cycle;
-		if (cpu_is_omap34xx()) {
-			t.wr_data_mux_bus = gpmc_ticks_to_ns(fclk_offset +
-					gpmc_ps_to_ticks(min_gpmc_clk_period +
-					t_rdyo * 1000));
-			t.wr_access = t.access;
-		}
-	} else {
-		t.adv_wr_off = gpmc_round_ns_to_ticks(max_t(int,
-							t_avdp, t_cer));
-		t.we_on  = t.adv_wr_off + gpmc_round_ns_to_ticks(t_aavdh);
-		t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl);
-		t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
-		t.wr_cycle  = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
-		if (cpu_is_omap34xx()) {
-			t.wr_data_mux_bus = t.we_on;
-			t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds);
-		}
-	}
+static int gpmc_set_sync_mode(int cs, struct gpmc_timings *t)
+{
+	unsigned sync_read = onenand_flags & ONENAND_FLAG_SYNCREAD;
+	unsigned sync_write = onenand_flags & ONENAND_FLAG_SYNCWRITE;
 
 	/* Configure GPMC for synchronous read */
 	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
@@ -362,7 +282,6 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 			  (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
 			  (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
 			  (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
-			  GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
 			  GPMC_CONFIG1_PAGE_LEN(2) |
 			  (cpu_is_omap34xx() ? 0 :
 				(GPMC_CONFIG1_WAIT_READ_MON |
@@ -371,11 +290,45 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 			  GPMC_CONFIG1_DEVICETYPE_NOR |
 			  GPMC_CONFIG1_MUXADDDATA);
 
-	err = gpmc_cs_set_timings(cs, &t);
-	if (err)
-		return err;
+	return gpmc_cs_set_timings(cs, t);
+}
+
+static int omap2_onenand_setup_async(void __iomem *onenand_base)
+{
+	struct gpmc_timings t;
+	int ret;
+
+	omap2_onenand_set_async_mode(onenand_base);
+
+	t = omap2_onenand_calc_async_timings();
+
+	ret = gpmc_set_async_mode(gpmc_onenand_data->cs, &t);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	omap2_onenand_set_async_mode(onenand_base);
+
+	return 0;
+}
+
+static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
+{
+	int ret, freq = *freq_ptr;
+	struct gpmc_timings t;
 
-	set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf, vhf);
+	if (!freq) {
+		/* Very first call freq is not known */
+		freq = omap2_onenand_get_freq(gpmc_onenand_data, onenand_base);
+		set_onenand_cfg(onenand_base);
+	}
+
+	t = omap2_onenand_calc_sync_timings(gpmc_onenand_data, freq);
+
+	ret = gpmc_set_sync_mode(gpmc_onenand_data->cs, &t);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	set_onenand_cfg(onenand_base);
 
 	*freq_ptr = freq;
 
@@ -385,15 +338,22 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
 {
 	struct device *dev = &gpmc_onenand_device.dev;
+	unsigned l = ONENAND_SYNC_READ | ONENAND_SYNC_READWRITE;
+	int ret;
 
-	/* Set sync timings in GPMC */
-	if (omap2_onenand_set_sync_mode(gpmc_onenand_data, onenand_base,
-			freq_ptr) < 0) {
-		dev_err(dev, "Unable to set synchronous mode\n");
-		return -EINVAL;
+	ret = omap2_onenand_setup_async(onenand_base);
+	if (ret) {
+		dev_err(dev, "unable to set to async mode\n");
+		return ret;
 	}
 
-	return 0;
+	if (!(gpmc_onenand_data->flags & l))
+		return 0;
+
+	ret = omap2_onenand_setup_sync(onenand_base, freq_ptr);
+	if (ret)
+		dev_err(dev, "unable to set to sync mode\n");
+	return ret;
 }
 
 void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
@@ -411,6 +371,11 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 		gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
 	}
 
+	if (cpu_is_omap34xx())
+		gpmc_onenand_data->flags |= ONENAND_IN_OMAP34XX;
+	else
+		gpmc_onenand_data->flags &= ~ONENAND_IN_OMAP34XX;
+
 	err = gpmc_cs_request(gpmc_onenand_data->cs, ONENAND_IO_SIZE,
 				(unsigned long *)&gpmc_onenand_resource.start);
 	if (err < 0) {
diff --git a/arch/arm/mach-omap2/gpmc-onenand.h b/arch/arm/mach-omap2/gpmc-onenand.h
new file mode 100644
index 0000000..216f23a
--- /dev/null
+++ b/arch/arm/mach-omap2/gpmc-onenand.h
@@ -0,0 +1,24 @@
+/*
+ *  arch/arm/mach-omap2/gpmc-onenand.h
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef	__OMAP2_GPMC_ONENAND_H
+#define	__OMAP2_GPMC_ONENAND_H
+
+#include <linux/platform_data/mtd-onenand-omap2.h>
+
+#if IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2)
+extern void gpmc_onenand_init(struct omap_onenand_platform_data *d);
+#else
+#define board_onenand_data	NULL
+static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d)
+{
+}
+#endif
+
+#endif
diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c
index 5654753..11d0b75 100644
--- a/arch/arm/mach-omap2/gpmc-smc91x.c
+++ b/arch/arm/mach-omap2/gpmc-smc91x.c
@@ -17,7 +17,7 @@
 #include <linux/io.h>
 #include <linux/smc91x.h>
 
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include "gpmc-smc91x.h"
 
 #include "soc.h"
@@ -58,6 +58,7 @@ static struct platform_device gpmc_smc91x_device = {
 static int smc91c96_gpmc_retime(void)
 {
 	struct gpmc_timings t;
+	struct gpmc_device_timings dev_t;
 	const int t3 = 10;	/* Figure 12.2 read and 12.4 write */
 	const int t4_r = 20;	/* Figure 12.2 read */
 	const int t4_w = 5;	/* Figure 12.4 write */
@@ -68,32 +69,6 @@ static int smc91c96_gpmc_retime(void)
 	const int t20 = 185;	/* Figure 12.2 read and 12.4 write */
 	u32 l;
 
-	memset(&t, 0, sizeof(t));
-
-	/* Read timings */
-	t.cs_on = 0;
-	t.adv_on = t.cs_on;
-	t.oe_on = t.adv_on + t3;
-	t.access = t.oe_on + t5;
-	t.oe_off = t.access;
-	t.adv_rd_off = t.oe_off + max(t4_r, t6);
-	t.cs_rd_off = t.oe_off;
-	t.rd_cycle = t20 - t.oe_on;
-
-	/* Write timings */
-	t.we_on = t.adv_on + t3;
-
-	if (cpu_is_omap34xx() && (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)) {
-		t.wr_data_mux_bus = t.we_on;
-		t.we_off = t.wr_data_mux_bus + t7;
-	} else
-		t.we_off = t.we_on + t7;
-	if (cpu_is_omap34xx())
-		t.wr_access = t.we_off;
-	t.adv_wr_off = t.we_off + max(t4_w, t8);
-	t.cs_wr_off = t.we_off + t4_w;
-	t.wr_cycle = t20 - t.we_on;
-
 	l = GPMC_CONFIG1_DEVICESIZE_16;
 	if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
 		l |= GPMC_CONFIG1_MUXADDDATA;
@@ -115,6 +90,22 @@ static int smc91c96_gpmc_retime(void)
 	if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
 		return 0;
 
+	memset(&dev_t, 0, sizeof(dev_t));
+
+	dev_t.t_oeasu = t3 * 1000;
+	dev_t.t_oe = t5 * 1000;
+	dev_t.t_cez_r = t4_r * 1000;
+	dev_t.t_oez = t6 * 1000;
+	dev_t.t_rd_cycle = (t20 - t3) * 1000;
+
+	dev_t.t_weasu = t3 * 1000;
+	dev_t.t_wpl = t7 * 1000;
+	dev_t.t_wph = t8 * 1000;
+	dev_t.t_cez_w = t4_w * 1000;
+	dev_t.t_wr_cycle = (t20 - t3) * 1000;
+
+	gpmc_calc_timings(&t, &dev_t);
+
 	return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
 }
 
diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c
index 249a0b4..ef99011 100644
--- a/arch/arm/mach-omap2/gpmc-smsc911x.c
+++ b/arch/arm/mach-omap2/gpmc-smsc911x.c
@@ -20,7 +20,7 @@
 #include <linux/io.h>
 #include <linux/smsc911x.h>
 
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include "gpmc-smsc911x.h"
 
 static struct resource gpmc_smsc911x_resources[] = {
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 92b5718..65468f6 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -26,16 +26,14 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 
-#include <asm/mach-types.h>
-#include <plat/gpmc.h>
+#include <linux/platform_data/mtd-nand-omap2.h>
 
-#include <plat/cpu.h>
-#include <plat/gpmc.h>
-#include <plat/sdrc.h>
-#include <plat/omap_device.h>
+#include <asm/mach-types.h>
 
 #include "soc.h"
 #include "common.h"
+#include "omap_device.h"
+#include "gpmc.h"
 
 #define	DEVICE_NAME		"omap-gpmc"
 
@@ -59,6 +57,9 @@
 #define GPMC_ECC_SIZE_CONFIG	0x1fc
 #define GPMC_ECC1_RESULT        0x200
 #define GPMC_ECC_BCH_RESULT_0   0x240   /* not available on OMAP2 */
+#define	GPMC_ECC_BCH_RESULT_1	0x244	/* not available on OMAP2 */
+#define	GPMC_ECC_BCH_RESULT_2	0x248	/* not available on OMAP2 */
+#define	GPMC_ECC_BCH_RESULT_3	0x24c	/* not available on OMAP2 */
 
 /* GPMC ECC control settings */
 #define GPMC_ECC_CTRL_ECCCLEAR		0x100
@@ -73,8 +74,16 @@
 #define GPMC_ECC_CTRL_ECCREG8		0x008
 #define GPMC_ECC_CTRL_ECCREG9		0x009
 
+#define	GPMC_CONFIG2_CSEXTRADELAY		BIT(7)
+#define	GPMC_CONFIG3_ADVEXTRADELAY		BIT(7)
+#define	GPMC_CONFIG4_OEEXTRADELAY		BIT(7)
+#define	GPMC_CONFIG4_WEEXTRADELAY		BIT(23)
+#define	GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN	BIT(6)
+#define	GPMC_CONFIG6_CYCLE2CYCLESAMECSEN	BIT(7)
+
 #define GPMC_CS0_OFFSET		0x60
 #define GPMC_CS_SIZE		0x30
+#define	GPMC_BCH_SIZE		0x10
 
 #define GPMC_MEM_START		0x00000000
 #define GPMC_MEM_END		0x3FFFFFFF
@@ -137,7 +146,6 @@ static struct resource	gpmc_mem_root;
 static struct resource	gpmc_cs_mem[GPMC_CS_NUM];
 static DEFINE_SPINLOCK(gpmc_mem_lock);
 static unsigned int gpmc_cs_map;	/* flag for cs which are initialized */
-static int gpmc_ecc_used = -EINVAL;	/* cs using ecc engine */
 static struct device *gpmc_dev;
 static int gpmc_irq;
 static resource_size_t phys_base, mem_size;
@@ -158,22 +166,6 @@ static u32 gpmc_read_reg(int idx)
 	return __raw_readl(gpmc_base + idx);
 }
 
-static void gpmc_cs_write_byte(int cs, int idx, u8 val)
-{
-	void __iomem *reg_addr;
-
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	__raw_writeb(val, reg_addr);
-}
-
-static u8 gpmc_cs_read_byte(int cs, int idx)
-{
-	void __iomem *reg_addr;
-
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	return __raw_readb(reg_addr);
-}
-
 void gpmc_cs_write_reg(int cs, int idx, u32 val)
 {
 	void __iomem *reg_addr;
@@ -238,6 +230,51 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
 	return ticks * gpmc_get_fclk_period() / 1000;
 }
 
+static unsigned int gpmc_ticks_to_ps(unsigned int ticks)
+{
+	return ticks * gpmc_get_fclk_period();
+}
+
+static unsigned int gpmc_round_ps_to_ticks(unsigned int time_ps)
+{
+	unsigned long ticks = gpmc_ps_to_ticks(time_ps);
+
+	return ticks * gpmc_get_fclk_period();
+}
+
+static inline void gpmc_cs_modify_reg(int cs, int reg, u32 mask, bool value)
+{
+	u32 l;
+
+	l = gpmc_cs_read_reg(cs, reg);
+	if (value)
+		l |= mask;
+	else
+		l &= ~mask;
+	gpmc_cs_write_reg(cs, reg, l);
+}
+
+static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p)
+{
+	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG1,
+			   GPMC_CONFIG1_TIME_PARA_GRAN,
+			   p->time_para_granularity);
+	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG2,
+			   GPMC_CONFIG2_CSEXTRADELAY, p->cs_extra_delay);
+	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG3,
+			   GPMC_CONFIG3_ADVEXTRADELAY, p->adv_extra_delay);
+	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
+			   GPMC_CONFIG4_OEEXTRADELAY, p->oe_extra_delay);
+	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
+			   GPMC_CONFIG4_OEEXTRADELAY, p->we_extra_delay);
+	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
+			   GPMC_CONFIG6_CYCLE2CYCLESAMECSEN,
+			   p->cycle2cyclesamecsen);
+	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
+			   GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN,
+			   p->cycle2cyclediffcsen);
+}
+
 #ifdef DEBUG
 static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 			       int time, const char *name)
@@ -288,7 +325,7 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 		return -1
 #endif
 
-int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
+int gpmc_calc_divider(unsigned int sync_clk)
 {
 	int div;
 	u32 l;
@@ -308,7 +345,7 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 	int div;
 	u32 l;
 
-	div = gpmc_cs_calc_divider(cs, t->sync_clk);
+	div = gpmc_calc_divider(t->sync_clk);
 	if (div < 0)
 		return div;
 
@@ -331,6 +368,12 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 
 	GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
 
+	GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, bus_turnaround);
+	GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay);
+
+	GPMC_SET_ONE(GPMC_CS_CONFIG1, 18, 19, wait_monitoring);
+	GPMC_SET_ONE(GPMC_CS_CONFIG1, 25, 26, clk_activation);
+
 	if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
 		GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
 	if (gpmc_capability & GPMC_HAS_WR_ACCESS)
@@ -350,6 +393,8 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
 	}
 
+	gpmc_cs_bool_timings(cs, &t->bool_timings);
+
 	return 0;
 }
 
@@ -509,44 +554,6 @@ void gpmc_cs_free(int cs)
 EXPORT_SYMBOL(gpmc_cs_free);
 
 /**
- * gpmc_read_status - read access request to get the different gpmc status
- * @cmd: command type
- * @return status
- */
-int gpmc_read_status(int cmd)
-{
-	int	status = -EINVAL;
-	u32	regval = 0;
-
-	switch (cmd) {
-	case GPMC_GET_IRQ_STATUS:
-		status = gpmc_read_reg(GPMC_IRQSTATUS);
-		break;
-
-	case GPMC_PREFETCH_FIFO_CNT:
-		regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
-		status = GPMC_PREFETCH_STATUS_FIFO_CNT(regval);
-		break;
-
-	case GPMC_PREFETCH_COUNT:
-		regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
-		status = GPMC_PREFETCH_STATUS_COUNT(regval);
-		break;
-
-	case GPMC_STATUS_BUFFER:
-		regval = gpmc_read_reg(GPMC_STATUS);
-		/* 1 : buffer is available to write */
-		status = regval & GPMC_STATUS_BUFF_EMPTY;
-		break;
-
-	default:
-		printk(KERN_ERR "gpmc_read_status: Not supported\n");
-	}
-	return status;
-}
-EXPORT_SYMBOL(gpmc_read_status);
-
-/**
  * gpmc_cs_configure - write request to configure gpmc
  * @cs: chip select number
  * @cmd: command type
@@ -614,121 +621,10 @@ int gpmc_cs_configure(int cs, int cmd, int wval)
 }
 EXPORT_SYMBOL(gpmc_cs_configure);
 
-/**
- * gpmc_nand_read - nand specific read access request
- * @cs: chip select number
- * @cmd: command type
- */
-int gpmc_nand_read(int cs, int cmd)
-{
-	int rval = -EINVAL;
-
-	switch (cmd) {
-	case GPMC_NAND_DATA:
-		rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA);
-		break;
-
-	default:
-		printk(KERN_ERR "gpmc_read_nand_ctrl: Not supported\n");
-	}
-	return rval;
-}
-EXPORT_SYMBOL(gpmc_nand_read);
-
-/**
- * gpmc_nand_write - nand specific write request
- * @cs: chip select number
- * @cmd: command type
- * @wval: value to write
- */
-int gpmc_nand_write(int cs, int cmd, int wval)
-{
-	int err = 0;
-
-	switch (cmd) {
-	case GPMC_NAND_COMMAND:
-		gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
-		break;
-
-	case GPMC_NAND_ADDRESS:
-		gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
-		break;
-
-	case GPMC_NAND_DATA:
-		gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
-
-	default:
-		printk(KERN_ERR "gpmc_write_nand_ctrl: Not supported\n");
-		err = -EINVAL;
-	}
-	return err;
-}
-EXPORT_SYMBOL(gpmc_nand_write);
-
-
-
-/**
- * gpmc_prefetch_enable - configures and starts prefetch transfer
- * @cs: cs (chip select) number
- * @fifo_th: fifo threshold to be used for read/ write
- * @dma_mode: dma mode enable (1) or disable (0)
- * @u32_count: number of bytes to be transferred
- * @is_write: prefetch read(0) or write post(1) mode
- */
-int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
-				unsigned int u32_count, int is_write)
-{
-
-	if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) {
-		pr_err("gpmc: fifo threshold is not supported\n");
-		return -1;
-	} else if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
-		/* Set the amount of bytes to be prefetched */
-		gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
-
-		/* Set dma/mpu mode, the prefetch read / post write and
-		 * enable the engine. Set which cs is has requested for.
-		 */
-		gpmc_write_reg(GPMC_PREFETCH_CONFIG1, ((cs << CS_NUM_SHIFT) |
-					PREFETCH_FIFOTHRESHOLD(fifo_th) |
-					ENABLE_PREFETCH |
-					(dma_mode << DMA_MPU_MODE) |
-					(0x1 & is_write)));
-
-		/*  Start the prefetch engine */
-		gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1);
-	} else {
-		return -EBUSY;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(gpmc_prefetch_enable);
-
-/**
- * gpmc_prefetch_reset - disables and stops the prefetch engine
- */
-int gpmc_prefetch_reset(int cs)
-{
-	u32 config1;
-
-	/* check if the same module/cs is trying to reset */
-	config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
-	if (((config1 >> CS_NUM_SHIFT) & 0x7) != cs)
-		return -EINVAL;
-
-	/* Stop the PFPW engine */
-	gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0);
-
-	/* Reset/disable the PFPW engine */
-	gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0);
-
-	return 0;
-}
-EXPORT_SYMBOL(gpmc_prefetch_reset);
-
 void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
 {
+	int i;
+
 	reg->gpmc_status = gpmc_base + GPMC_STATUS;
 	reg->gpmc_nand_command = gpmc_base + GPMC_CS0_OFFSET +
 				GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs;
@@ -744,7 +640,17 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
 	reg->gpmc_ecc_control = gpmc_base + GPMC_ECC_CONTROL;
 	reg->gpmc_ecc_size_config = gpmc_base + GPMC_ECC_SIZE_CONFIG;
 	reg->gpmc_ecc1_result = gpmc_base + GPMC_ECC1_RESULT;
-	reg->gpmc_bch_result0 = gpmc_base + GPMC_ECC_BCH_RESULT_0;
+
+	for (i = 0; i < GPMC_BCH_NUM_REMAINDER; i++) {
+		reg->gpmc_bch_result0[i] = gpmc_base + GPMC_ECC_BCH_RESULT_0 +
+					   GPMC_BCH_SIZE * i;
+		reg->gpmc_bch_result1[i] = gpmc_base + GPMC_ECC_BCH_RESULT_1 +
+					   GPMC_BCH_SIZE * i;
+		reg->gpmc_bch_result2[i] = gpmc_base + GPMC_ECC_BCH_RESULT_2 +
+					   GPMC_BCH_SIZE * i;
+		reg->gpmc_bch_result3[i] = gpmc_base + GPMC_ECC_BCH_RESULT_3 +
+					   GPMC_BCH_SIZE * i;
+	}
 }
 
 int gpmc_get_client_irq(unsigned irq_config)
@@ -902,6 +808,319 @@ static int __devinit gpmc_mem_init(void)
 	return 0;
 }
 
+static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk)
+{
+	u32 temp;
+	int div;
+
+	div = gpmc_calc_divider(sync_clk);
+	temp = gpmc_ps_to_ticks(time_ps);
+	temp = (temp + div - 1) / div;
+	return gpmc_ticks_to_ps(temp * div);
+}
+
+/* XXX: can the cycles be avoided ? */
+static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t,
+				struct gpmc_device_timings *dev_t)
+{
+	bool mux = dev_t->mux;
+	u32 temp;
+
+	/* adv_rd_off */
+	temp = dev_t->t_avdp_r;
+	/* XXX: mux check required ? */
+	if (mux) {
+		/* XXX: t_avdp not to be required for sync, only added for tusb
+		 * this indirectly necessitates requirement of t_avdp_r and
+		 * t_avdp_w instead of having a single t_avdp
+		 */
+		temp = max_t(u32, temp,	gpmc_t->clk_activation + dev_t->t_avdh);
+		temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
+	}
+	gpmc_t->adv_rd_off = gpmc_round_ps_to_ticks(temp);
+
+	/* oe_on */
+	temp = dev_t->t_oeasu; /* XXX: remove this ? */
+	if (mux) {
+		temp = max_t(u32, temp,	gpmc_t->clk_activation + dev_t->t_ach);
+		temp = max_t(u32, temp, gpmc_t->adv_rd_off +
+				gpmc_ticks_to_ps(dev_t->cyc_aavdh_oe));
+	}
+	gpmc_t->oe_on = gpmc_round_ps_to_ticks(temp);
+
+	/* access */
+	/* XXX: any scope for improvement ?, by combining oe_on
+	 * and clk_activation, need to check whether
+	 * access = clk_activation + round to sync clk ?
+	 */
+	temp = max_t(u32, dev_t->t_iaa,	dev_t->cyc_iaa * gpmc_t->sync_clk);
+	temp += gpmc_t->clk_activation;
+	if (dev_t->cyc_oe)
+		temp = max_t(u32, temp, gpmc_t->oe_on +
+				gpmc_ticks_to_ps(dev_t->cyc_oe));
+	gpmc_t->access = gpmc_round_ps_to_ticks(temp);
+
+	gpmc_t->oe_off = gpmc_t->access + gpmc_ticks_to_ps(1);
+	gpmc_t->cs_rd_off = gpmc_t->oe_off;
+
+	/* rd_cycle */
+	temp = max_t(u32, dev_t->t_cez_r, dev_t->t_oez);
+	temp = gpmc_round_ps_to_sync_clk(temp, gpmc_t->sync_clk) +
+							gpmc_t->access;
+	/* XXX: barter t_ce_rdyz with t_cez_r ? */
+	if (dev_t->t_ce_rdyz)
+		temp = max_t(u32, temp,	gpmc_t->cs_rd_off + dev_t->t_ce_rdyz);
+	gpmc_t->rd_cycle = gpmc_round_ps_to_ticks(temp);
+
+	return 0;
+}
+
+static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t,
+				struct gpmc_device_timings *dev_t)
+{
+	bool mux = dev_t->mux;
+	u32 temp;
+
+	/* adv_wr_off */
+	temp = dev_t->t_avdp_w;
+	if (mux) {
+		temp = max_t(u32, temp,
+			gpmc_t->clk_activation + dev_t->t_avdh);
+		temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
+	}
+	gpmc_t->adv_wr_off = gpmc_round_ps_to_ticks(temp);
+
+	/* wr_data_mux_bus */
+	temp = max_t(u32, dev_t->t_weasu,
+			gpmc_t->clk_activation + dev_t->t_rdyo);
+	/* XXX: shouldn't mux be kept as a whole for wr_data_mux_bus ?,
+	 * and in that case remember to handle we_on properly
+	 */
+	if (mux) {
+		temp = max_t(u32, temp,
+			gpmc_t->adv_wr_off + dev_t->t_aavdh);
+		temp = max_t(u32, temp, gpmc_t->adv_wr_off +
+				gpmc_ticks_to_ps(dev_t->cyc_aavdh_we));
+	}
+	gpmc_t->wr_data_mux_bus = gpmc_round_ps_to_ticks(temp);
+
+	/* we_on */
+	if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
+		gpmc_t->we_on = gpmc_round_ps_to_ticks(dev_t->t_weasu);
+	else
+		gpmc_t->we_on = gpmc_t->wr_data_mux_bus;
+
+	/* wr_access */
+	/* XXX: gpmc_capability check reqd ? , even if not, will not harm */
+	gpmc_t->wr_access = gpmc_t->access;
+
+	/* we_off */
+	temp = gpmc_t->we_on + dev_t->t_wpl;
+	temp = max_t(u32, temp,
+			gpmc_t->wr_access + gpmc_ticks_to_ps(1));
+	temp = max_t(u32, temp,
+		gpmc_t->we_on + gpmc_ticks_to_ps(dev_t->cyc_wpl));
+	gpmc_t->we_off = gpmc_round_ps_to_ticks(temp);
+
+	gpmc_t->cs_wr_off = gpmc_round_ps_to_ticks(gpmc_t->we_off +
+							dev_t->t_wph);
+
+	/* wr_cycle */
+	temp = gpmc_round_ps_to_sync_clk(dev_t->t_cez_w, gpmc_t->sync_clk);
+	temp += gpmc_t->wr_access;
+	/* XXX: barter t_ce_rdyz with t_cez_w ? */
+	if (dev_t->t_ce_rdyz)
+		temp = max_t(u32, temp,
+				 gpmc_t->cs_wr_off + dev_t->t_ce_rdyz);
+	gpmc_t->wr_cycle = gpmc_round_ps_to_ticks(temp);
+
+	return 0;
+}
+
+static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t,
+				struct gpmc_device_timings *dev_t)
+{
+	bool mux = dev_t->mux;
+	u32 temp;
+
+	/* adv_rd_off */
+	temp = dev_t->t_avdp_r;
+	if (mux)
+		temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
+	gpmc_t->adv_rd_off = gpmc_round_ps_to_ticks(temp);
+
+	/* oe_on */
+	temp = dev_t->t_oeasu;
+	if (mux)
+		temp = max_t(u32, temp,
+			gpmc_t->adv_rd_off + dev_t->t_aavdh);
+	gpmc_t->oe_on = gpmc_round_ps_to_ticks(temp);
+
+	/* access */
+	temp = max_t(u32, dev_t->t_iaa, /* XXX: remove t_iaa in async ? */
+				gpmc_t->oe_on + dev_t->t_oe);
+	temp = max_t(u32, temp,
+				gpmc_t->cs_on + dev_t->t_ce);
+	temp = max_t(u32, temp,
+				gpmc_t->adv_on + dev_t->t_aa);
+	gpmc_t->access = gpmc_round_ps_to_ticks(temp);
+
+	gpmc_t->oe_off = gpmc_t->access + gpmc_ticks_to_ps(1);
+	gpmc_t->cs_rd_off = gpmc_t->oe_off;
+
+	/* rd_cycle */
+	temp = max_t(u32, dev_t->t_rd_cycle,
+			gpmc_t->cs_rd_off + dev_t->t_cez_r);
+	temp = max_t(u32, temp, gpmc_t->oe_off + dev_t->t_oez);
+	gpmc_t->rd_cycle = gpmc_round_ps_to_ticks(temp);
+
+	return 0;
+}
+
+static int gpmc_calc_async_write_timings(struct gpmc_timings *gpmc_t,
+				struct gpmc_device_timings *dev_t)
+{
+	bool mux = dev_t->mux;
+	u32 temp;
+
+	/* adv_wr_off */
+	temp = dev_t->t_avdp_w;
+	if (mux)
+		temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
+	gpmc_t->adv_wr_off = gpmc_round_ps_to_ticks(temp);
+
+	/* wr_data_mux_bus */
+	temp = dev_t->t_weasu;
+	if (mux) {
+		temp = max_t(u32, temp,	gpmc_t->adv_wr_off + dev_t->t_aavdh);
+		temp = max_t(u32, temp, gpmc_t->adv_wr_off +
+				gpmc_ticks_to_ps(dev_t->cyc_aavdh_we));
+	}
+	gpmc_t->wr_data_mux_bus = gpmc_round_ps_to_ticks(temp);
+
+	/* we_on */
+	if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
+		gpmc_t->we_on = gpmc_round_ps_to_ticks(dev_t->t_weasu);
+	else
+		gpmc_t->we_on = gpmc_t->wr_data_mux_bus;
+
+	/* we_off */
+	temp = gpmc_t->we_on + dev_t->t_wpl;
+	gpmc_t->we_off = gpmc_round_ps_to_ticks(temp);
+
+	gpmc_t->cs_wr_off = gpmc_round_ps_to_ticks(gpmc_t->we_off +
+							dev_t->t_wph);
+
+	/* wr_cycle */
+	temp = max_t(u32, dev_t->t_wr_cycle,
+				gpmc_t->cs_wr_off + dev_t->t_cez_w);
+	gpmc_t->wr_cycle = gpmc_round_ps_to_ticks(temp);
+
+	return 0;
+}
+
+static int gpmc_calc_sync_common_timings(struct gpmc_timings *gpmc_t,
+			struct gpmc_device_timings *dev_t)
+{
+	u32 temp;
+
+	gpmc_t->sync_clk = gpmc_calc_divider(dev_t->clk) *
+						gpmc_get_fclk_period();
+
+	gpmc_t->page_burst_access = gpmc_round_ps_to_sync_clk(
+					dev_t->t_bacc,
+					gpmc_t->sync_clk);
+
+	temp = max_t(u32, dev_t->t_ces, dev_t->t_avds);
+	gpmc_t->clk_activation = gpmc_round_ps_to_ticks(temp);
+
+	if (gpmc_calc_divider(gpmc_t->sync_clk) != 1)
+		return 0;
+
+	if (dev_t->ce_xdelay)
+		gpmc_t->bool_timings.cs_extra_delay = true;
+	if (dev_t->avd_xdelay)
+		gpmc_t->bool_timings.adv_extra_delay = true;
+	if (dev_t->oe_xdelay)
+		gpmc_t->bool_timings.oe_extra_delay = true;
+	if (dev_t->we_xdelay)
+		gpmc_t->bool_timings.we_extra_delay = true;
+
+	return 0;
+}
+
+static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t,
+			struct gpmc_device_timings *dev_t)
+{
+	u32 temp;
+
+	/* cs_on */
+	gpmc_t->cs_on = gpmc_round_ps_to_ticks(dev_t->t_ceasu);
+
+	/* adv_on */
+	temp = dev_t->t_avdasu;
+	if (dev_t->t_ce_avd)
+		temp = max_t(u32, temp,
+				gpmc_t->cs_on + dev_t->t_ce_avd);
+	gpmc_t->adv_on = gpmc_round_ps_to_ticks(temp);
+
+	if (dev_t->sync_write || dev_t->sync_read)
+		gpmc_calc_sync_common_timings(gpmc_t, dev_t);
+
+	return 0;
+}
+
+/* TODO: remove this function once all peripherals are confirmed to
+ * work with generic timing. Simultaneously gpmc_cs_set_timings()
+ * has to be modified to handle timings in ps instead of ns
+*/
+static void gpmc_convert_ps_to_ns(struct gpmc_timings *t)
+{
+	t->cs_on /= 1000;
+	t->cs_rd_off /= 1000;
+	t->cs_wr_off /= 1000;
+	t->adv_on /= 1000;
+	t->adv_rd_off /= 1000;
+	t->adv_wr_off /= 1000;
+	t->we_on /= 1000;
+	t->we_off /= 1000;
+	t->oe_on /= 1000;
+	t->oe_off /= 1000;
+	t->page_burst_access /= 1000;
+	t->access /= 1000;
+	t->rd_cycle /= 1000;
+	t->wr_cycle /= 1000;
+	t->bus_turnaround /= 1000;
+	t->cycle2cycle_delay /= 1000;
+	t->wait_monitoring /= 1000;
+	t->clk_activation /= 1000;
+	t->wr_access /= 1000;
+	t->wr_data_mux_bus /= 1000;
+}
+
+int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
+			struct gpmc_device_timings *dev_t)
+{
+	memset(gpmc_t, 0, sizeof(*gpmc_t));
+
+	gpmc_calc_common_timings(gpmc_t, dev_t);
+
+	if (dev_t->sync_read)
+		gpmc_calc_sync_read_timings(gpmc_t, dev_t);
+	else
+		gpmc_calc_async_read_timings(gpmc_t, dev_t);
+
+	if (dev_t->sync_write)
+		gpmc_calc_sync_write_timings(gpmc_t, dev_t);
+	else
+		gpmc_calc_async_write_timings(gpmc_t, dev_t);
+
+	/* TODO: remove, see function definition */
+	gpmc_convert_ps_to_ns(gpmc_t);
+
+	return 0;
+}
+
 static __devinit int gpmc_probe(struct platform_device *pdev)
 {
 	int rc;
@@ -1093,267 +1312,3 @@ void omap3_gpmc_restore_context(void)
 	}
 }
 #endif /* CONFIG_ARCH_OMAP3 */
-
-/**
- * gpmc_enable_hwecc - enable hardware ecc functionality
- * @cs: chip select number
- * @mode: read/write mode
- * @dev_width: device bus width(1 for x16, 0 for x8)
- * @ecc_size: bytes for which ECC will be generated
- */
-int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size)
-{
-	unsigned int val;
-
-	/* check if ecc module is in used */
-	if (gpmc_ecc_used != -EINVAL)
-		return -EINVAL;
-
-	gpmc_ecc_used = cs;
-
-	/* clear ecc and enable bits */
-	gpmc_write_reg(GPMC_ECC_CONTROL,
-			GPMC_ECC_CTRL_ECCCLEAR |
-			GPMC_ECC_CTRL_ECCREG1);
-
-	/* program ecc and result sizes */
-	val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
-	gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
-
-	switch (mode) {
-	case GPMC_ECC_READ:
-	case GPMC_ECC_WRITE:
-		gpmc_write_reg(GPMC_ECC_CONTROL,
-				GPMC_ECC_CTRL_ECCCLEAR |
-				GPMC_ECC_CTRL_ECCREG1);
-		break;
-	case GPMC_ECC_READSYN:
-		gpmc_write_reg(GPMC_ECC_CONTROL,
-				GPMC_ECC_CTRL_ECCCLEAR |
-				GPMC_ECC_CTRL_ECCDISABLE);
-		break;
-	default:
-		printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode);
-		break;
-	}
-
-	/* (ECC 16 or 8 bit col) | ( CS  )  | ECC Enable */
-	val = (dev_width << 7) | (cs << 1) | (0x1);
-	gpmc_write_reg(GPMC_ECC_CONFIG, val);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(gpmc_enable_hwecc);
-
-/**
- * gpmc_calculate_ecc - generate non-inverted ecc bytes
- * @cs: chip select number
- * @dat: data pointer over which ecc is computed
- * @ecc_code: ecc code buffer
- *
- * Using non-inverted ECC is considered ugly since writing a blank
- * page (padding) will clear the ECC bytes. This is not a problem as long
- * no one is trying to write data on the seemingly unused page. Reading
- * an erased page will produce an ECC mismatch between generated and read
- * ECC bytes that has to be dealt with separately.
- */
-int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
-{
-	unsigned int val = 0x0;
-
-	if (gpmc_ecc_used != cs)
-		return -EINVAL;
-
-	/* read ecc result */
-	val = gpmc_read_reg(GPMC_ECC1_RESULT);
-	*ecc_code++ = val;          /* P128e, ..., P1e */
-	*ecc_code++ = val >> 16;    /* P128o, ..., P1o */
-	/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
-	*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
-
-	gpmc_ecc_used = -EINVAL;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(gpmc_calculate_ecc);
-
-#ifdef CONFIG_ARCH_OMAP3
-
-/**
- * gpmc_init_hwecc_bch - initialize hardware BCH ecc functionality
- * @cs: chip select number
- * @nsectors: how many 512-byte sectors to process
- * @nerrors: how many errors to correct per sector (4 or 8)
- *
- * This function must be executed before any call to gpmc_enable_hwecc_bch.
- */
-int gpmc_init_hwecc_bch(int cs, int nsectors, int nerrors)
-{
-	/* check if ecc module is in use */
-	if (gpmc_ecc_used != -EINVAL)
-		return -EINVAL;
-
-	/* support only OMAP3 class */
-	if (!cpu_is_omap34xx()) {
-		printk(KERN_ERR "BCH ecc is not supported on this CPU\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1.
-	 * Other chips may be added if confirmed to work.
-	 */
-	if ((nerrors == 4) &&
-	    (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0))) {
-		printk(KERN_ERR "BCH 4-bit mode is not supported on this CPU\n");
-		return -EINVAL;
-	}
-
-	/* sanity check */
-	if (nsectors > 8) {
-		printk(KERN_ERR "BCH cannot process %d sectors (max is 8)\n",
-		       nsectors);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(gpmc_init_hwecc_bch);
-
-/**
- * gpmc_enable_hwecc_bch - enable hardware BCH ecc functionality
- * @cs: chip select number
- * @mode: read/write mode
- * @dev_width: device bus width(1 for x16, 0 for x8)
- * @nsectors: how many 512-byte sectors to process
- * @nerrors: how many errors to correct per sector (4 or 8)
- */
-int gpmc_enable_hwecc_bch(int cs, int mode, int dev_width, int nsectors,
-			  int nerrors)
-{
-	unsigned int val;
-
-	/* check if ecc module is in use */
-	if (gpmc_ecc_used != -EINVAL)
-		return -EINVAL;
-
-	gpmc_ecc_used = cs;
-
-	/* clear ecc and enable bits */
-	gpmc_write_reg(GPMC_ECC_CONTROL, 0x1);
-
-	/*
-	 * When using BCH, sector size is hardcoded to 512 bytes.
-	 * Here we are using wrapping mode 6 both for reading and writing, with:
-	 *  size0 = 0  (no additional protected byte in spare area)
-	 *  size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
-	 */
-	gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, (32 << 22) | (0 << 12));
-
-	/* BCH configuration */
-	val = ((1                        << 16) | /* enable BCH */
-	       (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */
-	       (0x06                     <<  8) | /* wrap mode = 6 */
-	       (dev_width                <<  7) | /* bus width */
-	       (((nsectors-1) & 0x7)     <<  4) | /* number of sectors */
-	       (cs                       <<  1) | /* ECC CS */
-	       (0x1));                            /* enable ECC */
-
-	gpmc_write_reg(GPMC_ECC_CONFIG, val);
-	gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(gpmc_enable_hwecc_bch);
-
-/**
- * gpmc_calculate_ecc_bch4 - Generate 7 ecc bytes per sector of 512 data bytes
- * @cs:  chip select number
- * @dat: The pointer to data on which ecc is computed
- * @ecc: The ecc output buffer
- */
-int gpmc_calculate_ecc_bch4(int cs, const u_char *dat, u_char *ecc)
-{
-	int i;
-	unsigned long nsectors, reg, val1, val2;
-
-	if (gpmc_ecc_used != cs)
-		return -EINVAL;
-
-	nsectors = ((gpmc_read_reg(GPMC_ECC_CONFIG) >> 4) & 0x7) + 1;
-
-	for (i = 0; i < nsectors; i++) {
-
-		reg = GPMC_ECC_BCH_RESULT_0 + 16*i;
-
-		/* Read hw-computed remainder */
-		val1 = gpmc_read_reg(reg + 0);
-		val2 = gpmc_read_reg(reg + 4);
-
-		/*
-		 * Add constant polynomial to remainder, in order to get an ecc
-		 * sequence of 0xFFs for a buffer filled with 0xFFs; and
-		 * left-justify the resulting polynomial.
-		 */
-		*ecc++ = 0x28 ^ ((val2 >> 12) & 0xFF);
-		*ecc++ = 0x13 ^ ((val2 >>  4) & 0xFF);
-		*ecc++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF));
-		*ecc++ = 0x39 ^ ((val1 >> 20) & 0xFF);
-		*ecc++ = 0x96 ^ ((val1 >> 12) & 0xFF);
-		*ecc++ = 0xac ^ ((val1 >> 4) & 0xFF);
-		*ecc++ = 0x7f ^ ((val1 & 0xF) << 4);
-	}
-
-	gpmc_ecc_used = -EINVAL;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(gpmc_calculate_ecc_bch4);
-
-/**
- * gpmc_calculate_ecc_bch8 - Generate 13 ecc bytes per block of 512 data bytes
- * @cs:  chip select number
- * @dat: The pointer to data on which ecc is computed
- * @ecc: The ecc output buffer
- */
-int gpmc_calculate_ecc_bch8(int cs, const u_char *dat, u_char *ecc)
-{
-	int i;
-	unsigned long nsectors, reg, val1, val2, val3, val4;
-
-	if (gpmc_ecc_used != cs)
-		return -EINVAL;
-
-	nsectors = ((gpmc_read_reg(GPMC_ECC_CONFIG) >> 4) & 0x7) + 1;
-
-	for (i = 0; i < nsectors; i++) {
-
-		reg = GPMC_ECC_BCH_RESULT_0 + 16*i;
-
-		/* Read hw-computed remainder */
-		val1 = gpmc_read_reg(reg + 0);
-		val2 = gpmc_read_reg(reg + 4);
-		val3 = gpmc_read_reg(reg + 8);
-		val4 = gpmc_read_reg(reg + 12);
-
-		/*
-		 * Add constant polynomial to remainder, in order to get an ecc
-		 * sequence of 0xFFs for a buffer filled with 0xFFs.
-		 */
-		*ecc++ = 0xef ^ (val4 & 0xFF);
-		*ecc++ = 0x51 ^ ((val3 >> 24) & 0xFF);
-		*ecc++ = 0x2e ^ ((val3 >> 16) & 0xFF);
-		*ecc++ = 0x09 ^ ((val3 >> 8) & 0xFF);
-		*ecc++ = 0xed ^ (val3 & 0xFF);
-		*ecc++ = 0x93 ^ ((val2 >> 24) & 0xFF);
-		*ecc++ = 0x9a ^ ((val2 >> 16) & 0xFF);
-		*ecc++ = 0xc2 ^ ((val2 >> 8) & 0xFF);
-		*ecc++ = 0x97 ^ (val2 & 0xFF);
-		*ecc++ = 0x79 ^ ((val1 >> 24) & 0xFF);
-		*ecc++ = 0xe5 ^ ((val1 >> 16) & 0xFF);
-		*ecc++ = 0x24 ^ ((val1 >> 8) & 0xFF);
-		*ecc++ = 0xb5 ^ (val1 & 0xFF);
-	}
-
-	gpmc_ecc_used = -EINVAL;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(gpmc_calculate_ecc_bch8);
-
-#endif /* CONFIG_ARCH_OMAP3 */
diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h
new file mode 100644
index 0000000..fe0a844
--- /dev/null
+++ b/arch/arm/mach-omap2/gpmc.h
@@ -0,0 +1,216 @@
+/*
+ * General-Purpose Memory Controller for OMAP2
+ *
+ * Copyright (C) 2005-2006 Nokia 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.
+ */
+
+#ifndef __OMAP2_GPMC_H
+#define __OMAP2_GPMC_H
+
+#include <linux/platform_data/mtd-nand-omap2.h>
+
+/* Maximum Number of Chip Selects */
+#define GPMC_CS_NUM		8
+
+#define GPMC_CS_CONFIG1		0x00
+#define GPMC_CS_CONFIG2		0x04
+#define GPMC_CS_CONFIG3		0x08
+#define GPMC_CS_CONFIG4		0x0c
+#define GPMC_CS_CONFIG5		0x10
+#define GPMC_CS_CONFIG6		0x14
+#define GPMC_CS_CONFIG7		0x18
+#define GPMC_CS_NAND_COMMAND	0x1c
+#define GPMC_CS_NAND_ADDRESS	0x20
+#define GPMC_CS_NAND_DATA	0x24
+
+/* Control Commands */
+#define GPMC_CONFIG_RDY_BSY	0x00000001
+#define GPMC_CONFIG_DEV_SIZE	0x00000002
+#define GPMC_CONFIG_DEV_TYPE	0x00000003
+#define GPMC_SET_IRQ_STATUS	0x00000004
+#define GPMC_CONFIG_WP		0x00000005
+
+#define GPMC_ENABLE_IRQ		0x0000000d
+
+/* ECC commands */
+#define GPMC_ECC_READ		0 /* Reset Hardware ECC for read */
+#define GPMC_ECC_WRITE		1 /* Reset Hardware ECC for write */
+#define GPMC_ECC_READSYN	2 /* Reset before syndrom is read back */
+
+#define GPMC_CONFIG1_WRAPBURST_SUPP     (1 << 31)
+#define GPMC_CONFIG1_READMULTIPLE_SUPP  (1 << 30)
+#define GPMC_CONFIG1_READTYPE_ASYNC     (0 << 29)
+#define GPMC_CONFIG1_READTYPE_SYNC      (1 << 29)
+#define GPMC_CONFIG1_WRITEMULTIPLE_SUPP (1 << 28)
+#define GPMC_CONFIG1_WRITETYPE_ASYNC    (0 << 27)
+#define GPMC_CONFIG1_WRITETYPE_SYNC     (1 << 27)
+#define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25)
+#define GPMC_CONFIG1_PAGE_LEN(val)      ((val & 3) << 23)
+#define GPMC_CONFIG1_WAIT_READ_MON      (1 << 22)
+#define GPMC_CONFIG1_WAIT_WRITE_MON     (1 << 21)
+#define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18)
+#define GPMC_CONFIG1_WAIT_PIN_SEL(val)  ((val & 3) << 16)
+#define GPMC_CONFIG1_DEVICESIZE(val)    ((val & 3) << 12)
+#define GPMC_CONFIG1_DEVICESIZE_16      GPMC_CONFIG1_DEVICESIZE(1)
+#define GPMC_CONFIG1_DEVICETYPE(val)    ((val & 3) << 10)
+#define GPMC_CONFIG1_DEVICETYPE_NOR     GPMC_CONFIG1_DEVICETYPE(0)
+#define GPMC_CONFIG1_MUXADDDATA         (1 << 9)
+#define GPMC_CONFIG1_TIME_PARA_GRAN     (1 << 4)
+#define GPMC_CONFIG1_FCLK_DIV(val)      (val & 3)
+#define GPMC_CONFIG1_FCLK_DIV2          (GPMC_CONFIG1_FCLK_DIV(1))
+#define GPMC_CONFIG1_FCLK_DIV3          (GPMC_CONFIG1_FCLK_DIV(2))
+#define GPMC_CONFIG1_FCLK_DIV4          (GPMC_CONFIG1_FCLK_DIV(3))
+#define GPMC_CONFIG7_CSVALID		(1 << 6)
+
+#define GPMC_DEVICETYPE_NOR		0
+#define GPMC_DEVICETYPE_NAND		2
+#define GPMC_CONFIG_WRITEPROTECT	0x00000010
+#define WR_RD_PIN_MONITORING		0x00600000
+#define GPMC_IRQ_FIFOEVENTENABLE	0x01
+#define GPMC_IRQ_COUNT_EVENT		0x02
+
+
+/* bool type time settings */
+struct gpmc_bool_timings {
+	bool cycle2cyclediffcsen;
+	bool cycle2cyclesamecsen;
+	bool we_extra_delay;
+	bool oe_extra_delay;
+	bool adv_extra_delay;
+	bool cs_extra_delay;
+	bool time_para_granularity;
+};
+
+/*
+ * Note that all values in this struct are in nanoseconds except sync_clk
+ * (which is in picoseconds), while the register values are in gpmc_fck cycles.
+ */
+struct gpmc_timings {
+	/* Minimum clock period for synchronous mode (in picoseconds) */
+	u32 sync_clk;
+
+	/* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */
+	u32 cs_on;		/* Assertion time */
+	u32 cs_rd_off;		/* Read deassertion time */
+	u32 cs_wr_off;		/* Write deassertion time */
+
+	/* ADV signal timings corresponding to GPMC_CONFIG3 */
+	u32 adv_on;		/* Assertion time */
+	u32 adv_rd_off;		/* Read deassertion time */
+	u32 adv_wr_off;		/* Write deassertion time */
+
+	/* WE signals timings corresponding to GPMC_CONFIG4 */
+	u32 we_on;		/* WE assertion time */
+	u32 we_off;		/* WE deassertion time */
+
+	/* OE signals timings corresponding to GPMC_CONFIG4 */
+	u32 oe_on;		/* OE assertion time */
+	u32 oe_off;		/* OE deassertion time */
+
+	/* Access time and cycle time timings corresponding to GPMC_CONFIG5 */
+	u32 page_burst_access;	/* Multiple access word delay */
+	u32 access;		/* Start-cycle to first data valid delay */
+	u32 rd_cycle;		/* Total read cycle time */
+	u32 wr_cycle;		/* Total write cycle time */
+
+	u32 bus_turnaround;
+	u32 cycle2cycle_delay;
+
+	u32 wait_monitoring;
+	u32 clk_activation;
+
+	/* The following are only on OMAP3430 */
+	u32 wr_access;		/* WRACCESSTIME */
+	u32 wr_data_mux_bus;	/* WRDATAONADMUXBUS */
+
+	struct gpmc_bool_timings bool_timings;
+};
+
+/* Device timings in picoseconds */
+struct gpmc_device_timings {
+	u32 t_ceasu;	/* address setup to CS valid */
+	u32 t_avdasu;	/* address setup to ADV valid */
+	/* XXX: try to combine t_avdp_r & t_avdp_w. Issue is
+	 * of tusb using these timings even for sync whilst
+	 * ideally for adv_rd/(wr)_off it should have considered
+	 * t_avdh instead. This indirectly necessitates r/w
+	 * variations of t_avdp as it is possible to have one
+	 * sync & other async
+	 */
+	u32 t_avdp_r;	/* ADV low time (what about t_cer ?) */
+	u32 t_avdp_w;
+	u32 t_aavdh;	/* address hold time */
+	u32 t_oeasu;	/* address setup to OE valid */
+	u32 t_aa;	/* access time from ADV assertion */
+	u32 t_iaa;	/* initial access time */
+	u32 t_oe;	/* access time from OE assertion */
+	u32 t_ce;	/* access time from CS asertion */
+	u32 t_rd_cycle;	/* read cycle time */
+	u32 t_cez_r;	/* read CS deassertion to high Z */
+	u32 t_cez_w;	/* write CS deassertion to high Z */
+	u32 t_oez;	/* OE deassertion to high Z */
+	u32 t_weasu;	/* address setup to WE valid */
+	u32 t_wpl;	/* write assertion time */
+	u32 t_wph;	/* write deassertion time */
+	u32 t_wr_cycle;	/* write cycle time */
+
+	u32 clk;
+	u32 t_bacc;	/* burst access valid clock to output delay */
+	u32 t_ces;	/* CS setup time to clk */
+	u32 t_avds;	/* ADV setup time to clk */
+	u32 t_avdh;	/* ADV hold time from clk */
+	u32 t_ach;	/* address hold time from clk */
+	u32 t_rdyo;	/* clk to ready valid */
+
+	u32 t_ce_rdyz;	/* XXX: description ?, or use t_cez instead */
+	u32 t_ce_avd;	/* CS on to ADV on delay */
+
+	/* XXX: check the possibility of combining
+	 * cyc_aavhd_oe & cyc_aavdh_we
+	 */
+	u8 cyc_aavdh_oe;/* read address hold time in cycles */
+	u8 cyc_aavdh_we;/* write address hold time in cycles */
+	u8 cyc_oe;	/* access time from OE assertion in cycles */
+	u8 cyc_wpl;	/* write deassertion time in cycles */
+	u32 cyc_iaa;	/* initial access time in cycles */
+
+	bool mux;	/* address & data muxed */
+	bool sync_write;/* synchronous write */
+	bool sync_read;	/* synchronous read */
+
+	/* extra delays */
+	bool ce_xdelay;
+	bool avd_xdelay;
+	bool oe_xdelay;
+	bool we_xdelay;
+};
+
+extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
+				struct gpmc_device_timings *dev_t);
+
+extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
+extern int gpmc_get_client_irq(unsigned irq_config);
+
+extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
+extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);
+extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
+extern unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns);
+extern unsigned long gpmc_get_fclk_period(void);
+
+extern void gpmc_cs_write_reg(int cs, int idx, u32 val);
+extern u32 gpmc_cs_read_reg(int cs, int idx);
+extern int gpmc_calc_divider(unsigned int sync_clk);
+extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
+extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
+extern void gpmc_cs_free(int cs);
+extern int gpmc_cs_set_reserved(int cs, int reserved);
+extern int gpmc_cs_reserved(int cs);
+extern void omap3_gpmc_save_context(void);
+extern void omap3_gpmc_restore_context(void);
+extern int gpmc_cs_configure(int cs, int cmd, int wval);
+
+#endif
diff --git a/arch/arm/mach-omap2/hdq1w.c b/arch/arm/mach-omap2/hdq1w.c
index e003f2b..ab7bf18 100644
--- a/arch/arm/mach-omap2/hdq1w.c
+++ b/arch/arm/mach-omap2/hdq1w.c
@@ -27,15 +27,13 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 
-#include <plat/omap_hwmod.h>
-#include <plat/omap_device.h>
+#include "omap_hwmod.h"
+#include "omap_device.h"
 #include "hdq1w.h"
 
+#include "prm.h"
 #include "common.h"
 
-/* Maximum microseconds to wait for OMAP module to softreset */
-#define MAX_MODULE_SOFTRESET_WAIT	10000
-
 /**
  * omap_hdq1w_reset - reset the OMAP HDQ1W module
  * @oh: struct omap_hwmod *
diff --git a/arch/arm/mach-omap2/hdq1w.h b/arch/arm/mach-omap2/hdq1w.h
index 0c1efc8..c7e08d2 100644
--- a/arch/arm/mach-omap2/hdq1w.h
+++ b/arch/arm/mach-omap2/hdq1w.h
@@ -21,7 +21,7 @@
 #ifndef ARCH_ARM_MACH_OMAP2_HDQ1W_H
 #define ARCH_ARM_MACH_OMAP2_HDQ1W_H
 
-#include <plat/omap_hwmod.h>
+#include "omap_hwmod.h"
 
 /*
  * XXX A future cleanup patch should modify
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 4d3a632..4a96433 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -14,14 +14,14 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
-#include <mach/hardware.h>
 #include <linux/platform_data/gpio-omap.h>
 
-#include <plat/mmc.h>
-#include <plat/omap-pm.h>
-#include <plat/omap_device.h>
+#include "soc.h"
+#include "omap_device.h"
+#include "omap-pm.h"
 
 #include "mux.h"
+#include "mmc.h"
 #include "hsmmc.h"
 #include "control.h"
 
diff --git a/arch/arm/mach-omap2/hwspinlock.c b/arch/arm/mach-omap2/hwspinlock.c
index 8763c85..1df9b5f 100644
--- a/arch/arm/mach-omap2/hwspinlock.c
+++ b/arch/arm/mach-omap2/hwspinlock.c
@@ -21,8 +21,8 @@
 #include <linux/err.h>
 #include <linux/hwspinlock.h>
 
-#include <plat/omap_hwmod.h>
-#include <plat/omap_device.h>
+#include "omap_hwmod.h"
+#include "omap_device.h"
 
 static struct hwspinlock_pdata omap_hwspinlock_pdata __initdata = {
 	.base_id = 0,
diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c
index fc57e67..fbb9b15 100644
--- a/arch/arm/mach-omap2/i2c.c
+++ b/arch/arm/mach-omap2/i2c.c
@@ -19,21 +19,23 @@
  *
  */
 
-#include <plat/i2c.h>
-#include "common.h"
-#include <plat/omap_hwmod.h>
+#include "soc.h"
+#include "omap_hwmod.h"
+#include "omap_device.h"
 
+#include "prm.h"
+#include "common.h"
 #include "mux.h"
+#include "i2c.h"
 
 /* In register I2C_CON, Bit 15 is the I2C enable bit */
 #define I2C_EN					BIT(15)
 #define OMAP2_I2C_CON_OFFSET			0x24
 #define OMAP4_I2C_CON_OFFSET			0xA4
 
-/* Maximum microseconds to wait for OMAP module to softreset */
-#define MAX_MODULE_SOFTRESET_WAIT	10000
+#define MAX_OMAP_I2C_HWMOD_NAME_LEN	16
 
-void __init omap2_i2c_mux_pins(int bus_id)
+static void __init omap2_i2c_mux_pins(int bus_id)
 {
 	char mux_name[sizeof("i2c2_scl.i2c2_scl")];
 
@@ -104,3 +106,62 @@ int omap_i2c_reset(struct omap_hwmod *oh)
 
 	return 0;
 }
+
+static int __init omap_i2c_nr_ports(void)
+{
+	int ports = 0;
+
+	if (cpu_is_omap24xx())
+		ports = 2;
+	else if (cpu_is_omap34xx())
+		ports = 3;
+	else if (cpu_is_omap44xx())
+		ports = 4;
+	return ports;
+}
+
+static const char name[] = "omap_i2c";
+
+int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *i2c_pdata,
+				int bus_id)
+{
+	int l;
+	struct omap_hwmod *oh;
+	struct platform_device *pdev;
+	char oh_name[MAX_OMAP_I2C_HWMOD_NAME_LEN];
+	struct omap_i2c_bus_platform_data *pdata;
+	struct omap_i2c_dev_attr *dev_attr;
+
+	if (bus_id > omap_i2c_nr_ports())
+		return -EINVAL;
+
+	omap2_i2c_mux_pins(bus_id);
+
+	l = snprintf(oh_name, MAX_OMAP_I2C_HWMOD_NAME_LEN, "i2c%d", bus_id);
+	WARN(l >= MAX_OMAP_I2C_HWMOD_NAME_LEN,
+		"String buffer overflow in I2C%d device setup\n", bus_id);
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+			pr_err("Could not look up %s\n", oh_name);
+			return -EEXIST;
+	}
+
+	pdata = i2c_pdata;
+	/*
+	 * pass the hwmod class's CPU-specific knowledge of I2C IP revision in
+	 * use, and functionality implementation flags, up to the OMAP I2C
+	 * driver via platform data
+	 */
+	pdata->rev = oh->class->rev;
+
+	dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr;
+	pdata->flags = dev_attr->flags;
+
+	pdev = omap_device_build(name, bus_id, oh, pdata,
+			sizeof(struct omap_i2c_bus_platform_data),
+			NULL, 0, 0);
+	WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", name);
+
+	return PTR_RET(pdev);
+}
+
diff --git a/arch/arm/mach-omap2/i2c.h b/arch/arm/mach-omap2/i2c.h
new file mode 100644
index 0000000..42b6f2e
--- /dev/null
+++ b/arch/arm/mach-omap2/i2c.h
@@ -0,0 +1,42 @@
+/*
+ * Helper module for board specific I2C bus registration
+ *
+ * Copyright (C) 2009 Nokia 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <plat/i2c.h>
+
+#ifndef __MACH_OMAP2_I2C_H
+#define __MACH_OMAP2_I2C_H
+
+/**
+ * i2c_dev_attr - OMAP I2C controller device attributes for omap_hwmod
+ * @fifo_depth: total controller FIFO size (in bytes)
+ * @flags: differences in hardware support capability
+ *
+ * @fifo_depth represents what exists on the hardware, not what is
+ * actually configured at runtime by the device driver.
+ */
+struct omap_i2c_dev_attr {
+	u8	fifo_depth;
+	u32	flags;
+};
+
+int omap_i2c_reset(struct omap_hwmod *oh);
+
+#endif	/* __MACH_OMAP2_I2C_H */
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index cf2362c..45cc7ed4 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -28,6 +28,9 @@
 #include "soc.h"
 #include "control.h"
 
+#define OMAP4_SILICON_TYPE_STANDARD		0x01
+#define OMAP4_SILICON_TYPE_PERFORMANCE		0x02
+
 static unsigned int omap_revision;
 static const char *cpu_rev;
 u32 omap_features;
@@ -273,25 +276,11 @@ void __init omap4xxx_check_features(void)
 {
 	u32 si_type;
 
-	if (cpu_is_omap443x())
-		omap_features |= OMAP4_HAS_MPU_1GHZ;
-
+	si_type =
+	(read_tap_reg(OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1) >> 16) & 0x03;
 
-	if (cpu_is_omap446x()) {
-		si_type =
-			read_tap_reg(OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1);
-		switch ((si_type & (3 << 16)) >> 16) {
-		case 2:
-			/* High performance device */
-			omap_features |= OMAP4_HAS_MPU_1_5GHZ;
-			break;
-		case 1:
-		default:
-			/* Standard device */
-			omap_features |= OMAP4_HAS_MPU_1_2GHZ;
-			break;
-		}
-	}
+	if (si_type == OMAP4_SILICON_TYPE_PERFORMANCE)
+		omap_features = OMAP4_HAS_PERF_SILICON;
 }
 
 void __init ti81xx_check_features(void)
@@ -559,11 +548,12 @@ void __init omap5xxx_check_revision(void)
  * detect the exact revision later on in omap2_detect_revision() once map_io
  * is done.
  */
-void __init omap2_set_globals_tap(struct omap_globals *omap2_globals)
+void __init omap2_set_globals_tap(u32 class, void __iomem *tap)
 {
-	omap_revision = omap2_globals->class;
-	tap_base = omap2_globals->tap;
+	omap_revision = class;
+	tap_base = tap;
 
+	/* XXX What is this intended to do? */
 	if (cpu_is_omap34xx())
 		tap_prod_id = 0x0210;
 	else
diff --git a/arch/arm/mach-omap2/include/mach/board-zoom.h b/arch/arm/mach-omap2/include/mach/board-zoom.h
deleted file mode 100644
index 2e94869..0000000
--- a/arch/arm/mach-omap2/include/mach/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/include/mach/debug-macro.S b/arch/arm/mach-omap2/include/mach/debug-macro.S
index 93d10de..cfaed13 100644
--- a/arch/arm/mach-omap2/include/mach/debug-macro.S
+++ b/arch/arm/mach-omap2/include/mach/debug-macro.S
@@ -13,7 +13,7 @@
 
 #include <linux/serial_reg.h>
 
-#include <plat/serial.h>
+#include <mach/serial.h>
 
 #define UART_OFFSET(addr)	((addr) & 0x00ffffff)
 
diff --git a/arch/arm/mach-omap2/include/mach/gpio.h b/arch/arm/mach-omap2/include/mach/gpio.h
deleted file mode 100644
index 5621cc5..0000000
--- a/arch/arm/mach-omap2/include/mach/gpio.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/*
- * arch/arm/mach-omap2/include/mach/gpio.h
- */
diff --git a/arch/arm/mach-omap2/include/mach/serial.h b/arch/arm/mach-omap2/include/mach/serial.h
new file mode 100644
index 0000000..70eda00
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/serial.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support- Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * Memory entry used for the DEBUG_LL UART configuration, relative to
+ * start of RAM. See also uncompress.h and debug-macro.S.
+ *
+ * Note that using a memory location for storing the UART configuration
+ * has at least two limitations:
+ *
+ * 1. Kernel uncompress code cannot overlap OMAP_UART_INFO as the
+ *    uncompress code could then partially overwrite itself
+ * 2. We assume printascii is called at least once before paging_init,
+ *    and addruart has a chance to read OMAP_UART_INFO
+ */
+#define OMAP_UART_INFO_OFS	0x3ffc
+
+/* OMAP2 serial ports */
+#define OMAP2_UART1_BASE	0x4806a000
+#define OMAP2_UART2_BASE	0x4806c000
+#define OMAP2_UART3_BASE	0x4806e000
+
+/* OMAP3 serial ports */
+#define OMAP3_UART1_BASE	OMAP2_UART1_BASE
+#define OMAP3_UART2_BASE	OMAP2_UART2_BASE
+#define OMAP3_UART3_BASE	0x49020000
+#define OMAP3_UART4_BASE	0x49042000	/* Only on 36xx */
+#define OMAP3_UART4_AM35XX_BASE	0x4809E000	/* Only on AM35xx */
+
+/* OMAP4 serial ports */
+#define OMAP4_UART1_BASE	OMAP2_UART1_BASE
+#define OMAP4_UART2_BASE	OMAP2_UART2_BASE
+#define OMAP4_UART3_BASE	0x48020000
+#define OMAP4_UART4_BASE	0x4806e000
+
+/* TI81XX serial ports */
+#define TI81XX_UART1_BASE	0x48020000
+#define TI81XX_UART2_BASE	0x48022000
+#define TI81XX_UART3_BASE	0x48024000
+
+/* AM3505/3517 UART4 */
+#define AM35XX_UART4_BASE	0x4809E000	/* Only on AM3505/3517 */
+
+/* AM33XX serial port */
+#define AM33XX_UART1_BASE	0x44E09000
+
+/* OMAP5 serial ports */
+#define OMAP5_UART1_BASE	OMAP2_UART1_BASE
+#define OMAP5_UART2_BASE	OMAP2_UART2_BASE
+#define OMAP5_UART3_BASE	OMAP4_UART3_BASE
+#define OMAP5_UART4_BASE	OMAP4_UART4_BASE
+#define OMAP5_UART5_BASE	0x48066000
+#define OMAP5_UART6_BASE	0x48068000
+
+/* External port on Zoom2/3 */
+#define ZOOM_UART_BASE		0x10000000
+#define ZOOM_UART_VIRT		0xfa400000
+
+#define OMAP_PORT_SHIFT		2
+#define ZOOM_PORT_SHIFT		1
+
+#define OMAP24XX_BASE_BAUD	(48000000/16)
+
+/*
+ * DEBUG_LL port encoding stored into the UART1 scratchpad register by
+ * decomp_setup in uncompress.h
+ */
+#define OMAP2UART1		21
+#define OMAP2UART2		22
+#define OMAP2UART3		23
+#define OMAP3UART1		OMAP2UART1
+#define OMAP3UART2		OMAP2UART2
+#define OMAP3UART3		33
+#define OMAP3UART4		34		/* Only on 36xx */
+#define OMAP4UART1		OMAP2UART1
+#define OMAP4UART2		OMAP2UART2
+#define OMAP4UART3		43
+#define OMAP4UART4		44
+#define TI81XXUART1		81
+#define TI81XXUART2		82
+#define TI81XXUART3		83
+#define AM33XXUART1		84
+#define OMAP5UART3		OMAP4UART3
+#define OMAP5UART4		OMAP4UART4
+#define ZOOM_UART		95		/* Only on zoom2/3 */
+
+#ifndef __ASSEMBLER__
+
+struct omap_board_data;
+struct omap_uart_port_info;
+
+extern void omap_serial_init(void);
+extern void omap_serial_board_init(struct omap_uart_port_info *platform_data);
+extern void omap_serial_init_port(struct omap_board_data *bdata,
+		struct omap_uart_port_info *platform_data);
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/uncompress.h b/arch/arm/mach-omap2/include/mach/uncompress.h
index 78e0557..8e3546d 100644
--- a/arch/arm/mach-omap2/include/mach/uncompress.h
+++ b/arch/arm/mach-omap2/include/mach/uncompress.h
@@ -1,5 +1,176 @@
 /*
- * arch/arm/mach-omap2/include/mach/uncompress.h
+ * arch/arm/plat-omap/include/mach/uncompress.h
+ *
+ * Serial port stubs for kernel decompress status messages
+ *
+ * Initially based on:
+ * linux-2.4.15-rmk1-dsplinux1.6/arch/arm/plat-omap/include/mach1510/uncompress.h
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: Greg Lonnon <glonnon@ridgerun.com>
+ *
+ * Rewritten by:
+ * Author: <source@mvista.com>
+ * 2004 (c) MontaVista Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
  */
 
-#include <plat/uncompress.h>
+#include <linux/types.h>
+#include <linux/serial_reg.h>
+
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+
+#include <mach/serial.h>
+
+#define MDR1_MODE_MASK			0x07
+
+volatile u8 *uart_base;
+int uart_shift;
+
+/*
+ * Store the DEBUG_LL uart number into memory.
+ * See also debug-macro.S, and serial.c for related code.
+ */
+static void set_omap_uart_info(unsigned char port)
+{
+	/*
+	 * Get address of some.bss variable and round it down
+	 * a la CONFIG_AUTO_ZRELADDR.
+	 */
+	u32 ram_start = (u32)&uart_shift & 0xf8000000;
+	u32 *uart_info = (u32 *)(ram_start + OMAP_UART_INFO_OFS);
+	*uart_info = port;
+}
+
+static void putc(int c)
+{
+	if (!uart_base)
+		return;
+
+	/* Check for UART 16x mode */
+	if ((uart_base[UART_OMAP_MDR1 << uart_shift] & MDR1_MODE_MASK) != 0)
+		return;
+
+	while (!(uart_base[UART_LSR << uart_shift] & UART_LSR_THRE))
+		barrier();
+	uart_base[UART_TX << uart_shift] = c;
+}
+
+static inline void flush(void)
+{
+}
+
+/*
+ * Macros to configure UART1 and debug UART
+ */
+#define _DEBUG_LL_ENTRY(mach, dbg_uart, dbg_shft, dbg_id)		\
+	if (machine_is_##mach()) {					\
+		uart_base = (volatile u8 *)(dbg_uart);			\
+		uart_shift = (dbg_shft);				\
+		port = (dbg_id);					\
+		set_omap_uart_info(port);				\
+		break;							\
+	}
+
+#define DEBUG_LL_OMAP2(p, mach)						\
+	_DEBUG_LL_ENTRY(mach, OMAP2_UART##p##_BASE, OMAP_PORT_SHIFT,	\
+		OMAP2UART##p)
+
+#define DEBUG_LL_OMAP3(p, mach)						\
+	_DEBUG_LL_ENTRY(mach, OMAP3_UART##p##_BASE, OMAP_PORT_SHIFT,	\
+		OMAP3UART##p)
+
+#define DEBUG_LL_OMAP4(p, mach)						\
+	_DEBUG_LL_ENTRY(mach, OMAP4_UART##p##_BASE, OMAP_PORT_SHIFT,	\
+		OMAP4UART##p)
+
+#define DEBUG_LL_OMAP5(p, mach)						\
+	_DEBUG_LL_ENTRY(mach, OMAP5_UART##p##_BASE, OMAP_PORT_SHIFT,	\
+		OMAP5UART##p)
+/* Zoom2/3 shift is different for UART1 and external port */
+#define DEBUG_LL_ZOOM(mach)						\
+	_DEBUG_LL_ENTRY(mach, ZOOM_UART_BASE, ZOOM_PORT_SHIFT, ZOOM_UART)
+
+#define DEBUG_LL_TI81XX(p, mach)					\
+	_DEBUG_LL_ENTRY(mach, TI81XX_UART##p##_BASE, OMAP_PORT_SHIFT,	\
+		TI81XXUART##p)
+
+#define DEBUG_LL_AM33XX(p, mach)					\
+	_DEBUG_LL_ENTRY(mach, AM33XX_UART##p##_BASE, OMAP_PORT_SHIFT,	\
+		AM33XXUART##p)
+
+static inline void arch_decomp_setup(void)
+{
+	int port = 0;
+
+	/*
+	 * Initialize the port based on the machine ID from the bootloader.
+	 * Note that we're using macros here instead of switch statement
+	 * as machine_is functions are optimized out for the boards that
+	 * are not selected.
+	 */
+	do {
+		/* omap2 based boards using UART1 */
+		DEBUG_LL_OMAP2(1, omap_2430sdp);
+		DEBUG_LL_OMAP2(1, omap_apollon);
+		DEBUG_LL_OMAP2(1, omap_h4);
+
+		/* omap2 based boards using UART3 */
+		DEBUG_LL_OMAP2(3, nokia_n800);
+		DEBUG_LL_OMAP2(3, nokia_n810);
+		DEBUG_LL_OMAP2(3, nokia_n810_wimax);
+
+		/* omap3 based boards using UART1 */
+		DEBUG_LL_OMAP2(1, omap3evm);
+		DEBUG_LL_OMAP3(1, omap_3430sdp);
+		DEBUG_LL_OMAP3(1, omap_3630sdp);
+		DEBUG_LL_OMAP3(1, omap3530_lv_som);
+		DEBUG_LL_OMAP3(1, omap3_torpedo);
+
+		/* omap3 based boards using UART3 */
+		DEBUG_LL_OMAP3(3, cm_t35);
+		DEBUG_LL_OMAP3(3, cm_t3517);
+		DEBUG_LL_OMAP3(3, cm_t3730);
+		DEBUG_LL_OMAP3(3, craneboard);
+		DEBUG_LL_OMAP3(3, devkit8000);
+		DEBUG_LL_OMAP3(3, igep0020);
+		DEBUG_LL_OMAP3(3, igep0030);
+		DEBUG_LL_OMAP3(3, nokia_rm680);
+		DEBUG_LL_OMAP3(3, nokia_rm696);
+		DEBUG_LL_OMAP3(3, nokia_rx51);
+		DEBUG_LL_OMAP3(3, omap3517evm);
+		DEBUG_LL_OMAP3(3, omap3_beagle);
+		DEBUG_LL_OMAP3(3, omap3_pandora);
+		DEBUG_LL_OMAP3(3, omap_ldp);
+		DEBUG_LL_OMAP3(3, overo);
+		DEBUG_LL_OMAP3(3, touchbook);
+
+		/* omap4 based boards using UART3 */
+		DEBUG_LL_OMAP4(3, omap_4430sdp);
+		DEBUG_LL_OMAP4(3, omap4_panda);
+
+		/* omap5 based boards using UART3 */
+		DEBUG_LL_OMAP5(3, omap5_sevm);
+
+		/* zoom2/3 external uart */
+		DEBUG_LL_ZOOM(omap_zoom2);
+		DEBUG_LL_ZOOM(omap_zoom3);
+
+		/* TI8168 base boards using UART3 */
+		DEBUG_LL_TI81XX(3, ti8168evm);
+
+		/* TI8148 base boards using UART1 */
+		DEBUG_LL_TI81XX(1, ti8148evm);
+
+		/* AM33XX base boards using UART1 */
+		DEBUG_LL_AM33XX(1, am335xevm);
+	} while (0);
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_wdog()
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 4234d28..15cd441 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -25,14 +25,9 @@
 #include <asm/tlb.h>
 #include <asm/mach/map.h>
 
-#include <plat/sram.h>
-#include <plat/sdrc.h>
-#include <plat/serial.h>
-#include <plat/omap-pm.h>
-#include <plat/omap_hwmod.h>
-#include <plat/multi.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 
+#include "omap_hwmod.h"
 #include "soc.h"
 #include "iomap.h"
 #include "voltage.h"
@@ -43,6 +38,18 @@
 #include "clock2xxx.h"
 #include "clock3xxx.h"
 #include "clock44xx.h"
+#include "omap-pm.h"
+#include "sdrc.h"
+#include "control.h"
+#include "serial.h"
+#include "sram.h"
+#include "cm2xxx.h"
+#include "cm3xxx.h"
+#include "prm.h"
+#include "cm.h"
+#include "prcm_mpu44xx.h"
+#include "prminst44xx.h"
+#include "cminst44xx.h"
 
 /*
  * The machine specific code may provide the extra mapping besides the
@@ -265,7 +272,7 @@ static struct map_desc omap54xx_io_desc[] __initdata = {
 #endif
 
 #ifdef CONFIG_SOC_OMAP2420
-void __init omap242x_map_common_io(void)
+void __init omap242x_map_io(void)
 {
 	iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
 	iotable_init(omap242x_io_desc, ARRAY_SIZE(omap242x_io_desc));
@@ -273,7 +280,7 @@ void __init omap242x_map_common_io(void)
 #endif
 
 #ifdef CONFIG_SOC_OMAP2430
-void __init omap243x_map_common_io(void)
+void __init omap243x_map_io(void)
 {
 	iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
 	iotable_init(omap243x_io_desc, ARRAY_SIZE(omap243x_io_desc));
@@ -281,28 +288,28 @@ void __init omap243x_map_common_io(void)
 #endif
 
 #ifdef CONFIG_ARCH_OMAP3
-void __init omap34xx_map_common_io(void)
+void __init omap3_map_io(void)
 {
 	iotable_init(omap34xx_io_desc, ARRAY_SIZE(omap34xx_io_desc));
 }
 #endif
 
 #ifdef CONFIG_SOC_TI81XX
-void __init omapti81xx_map_common_io(void)
+void __init ti81xx_map_io(void)
 {
 	iotable_init(omapti81xx_io_desc, ARRAY_SIZE(omapti81xx_io_desc));
 }
 #endif
 
 #ifdef CONFIG_SOC_AM33XX
-void __init omapam33xx_map_common_io(void)
+void __init am33xx_map_io(void)
 {
 	iotable_init(omapam33xx_io_desc, ARRAY_SIZE(omapam33xx_io_desc));
 }
 #endif
 
 #ifdef CONFIG_ARCH_OMAP4
-void __init omap44xx_map_common_io(void)
+void __init omap4_map_io(void)
 {
 	iotable_init(omap44xx_io_desc, ARRAY_SIZE(omap44xx_io_desc));
 	omap_barriers_init();
@@ -310,7 +317,7 @@ void __init omap44xx_map_common_io(void)
 #endif
 
 #ifdef CONFIG_SOC_OMAP5
-void __init omap5_map_common_io(void)
+void __init omap5_map_io(void)
 {
 	iotable_init(omap54xx_io_desc, ARRAY_SIZE(omap54xx_io_desc));
 }
@@ -354,11 +361,6 @@ static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data)
 	return omap_hwmod_set_postsetup_state(oh, *(u8 *)data);
 }
 
-static void __init omap_common_init_early(void)
-{
-	omap_init_consistent_dma_size();
-}
-
 static void __init omap_hwmod_init_postsetup(void)
 {
 	u8 postsetup_state;
@@ -377,9 +379,15 @@ static void __init omap_hwmod_init_postsetup(void)
 #ifdef CONFIG_SOC_OMAP2420
 void __init omap2420_init_early(void)
 {
-	omap2_set_globals_242x();
+	omap2_set_globals_tap(OMAP242X_CLASS, OMAP2_L4_IO_ADDRESS(0x48014000));
+	omap2_set_globals_sdrc(OMAP2_L3_IO_ADDRESS(OMAP2420_SDRC_BASE),
+			       OMAP2_L3_IO_ADDRESS(OMAP2420_SMS_BASE));
+	omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE),
+				  NULL);
+	omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE));
+	omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE), NULL);
 	omap2xxx_check_revision();
-	omap_common_init_early();
+	omap2xxx_cm_init();
 	omap2xxx_voltagedomains_init();
 	omap242x_powerdomains_init();
 	omap242x_clockdomains_init();
@@ -393,15 +401,22 @@ void __init omap2420_init_late(void)
 	omap_mux_late_init();
 	omap2_common_pm_late_init();
 	omap2_pm_init();
+	omap2_clk_enable_autoidle_all();
 }
 #endif
 
 #ifdef CONFIG_SOC_OMAP2430
 void __init omap2430_init_early(void)
 {
-	omap2_set_globals_243x();
+	omap2_set_globals_tap(OMAP243X_CLASS, OMAP2_L4_IO_ADDRESS(0x4900a000));
+	omap2_set_globals_sdrc(OMAP2_L3_IO_ADDRESS(OMAP243X_SDRC_BASE),
+			       OMAP2_L3_IO_ADDRESS(OMAP243X_SMS_BASE));
+	omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE),
+				  NULL);
+	omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE));
+	omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE), NULL);
 	omap2xxx_check_revision();
-	omap_common_init_early();
+	omap2xxx_cm_init();
 	omap2xxx_voltagedomains_init();
 	omap243x_powerdomains_init();
 	omap243x_clockdomains_init();
@@ -415,6 +430,7 @@ void __init omap2430_init_late(void)
 	omap_mux_late_init();
 	omap2_common_pm_late_init();
 	omap2_pm_init();
+	omap2_clk_enable_autoidle_all();
 }
 #endif
 
@@ -425,10 +441,16 @@ void __init omap2430_init_late(void)
 #ifdef CONFIG_ARCH_OMAP3
 void __init omap3_init_early(void)
 {
-	omap2_set_globals_3xxx();
+	omap2_set_globals_tap(OMAP343X_CLASS, OMAP2_L4_IO_ADDRESS(0x4830A000));
+	omap2_set_globals_sdrc(OMAP2_L3_IO_ADDRESS(OMAP343X_SDRC_BASE),
+			       OMAP2_L3_IO_ADDRESS(OMAP343X_SMS_BASE));
+	omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE),
+				  NULL);
+	omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE));
+	omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE), NULL);
 	omap3xxx_check_revision();
 	omap3xxx_check_features();
-	omap_common_init_early();
+	omap3xxx_cm_init();
 	omap3xxx_voltagedomains_init();
 	omap3xxx_powerdomains_init();
 	omap3xxx_clockdomains_init();
@@ -459,10 +481,14 @@ void __init am35xx_init_early(void)
 
 void __init ti81xx_init_early(void)
 {
-	omap2_set_globals_ti81xx();
+	omap2_set_globals_tap(OMAP343X_CLASS,
+			      OMAP2_L4_IO_ADDRESS(TI81XX_TAP_BASE));
+	omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(TI81XX_CTRL_BASE),
+				  NULL);
+	omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE));
+	omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE), NULL);
 	omap3xxx_check_revision();
 	ti81xx_check_features();
-	omap_common_init_early();
 	omap3xxx_voltagedomains_init();
 	omap3xxx_powerdomains_init();
 	omap3xxx_clockdomains_init();
@@ -476,6 +502,7 @@ void __init omap3_init_late(void)
 	omap_mux_late_init();
 	omap2_common_pm_late_init();
 	omap3_pm_init();
+	omap2_clk_enable_autoidle_all();
 }
 
 void __init omap3430_init_late(void)
@@ -483,6 +510,7 @@ void __init omap3430_init_late(void)
 	omap_mux_late_init();
 	omap2_common_pm_late_init();
 	omap3_pm_init();
+	omap2_clk_enable_autoidle_all();
 }
 
 void __init omap35xx_init_late(void)
@@ -490,6 +518,7 @@ void __init omap35xx_init_late(void)
 	omap_mux_late_init();
 	omap2_common_pm_late_init();
 	omap3_pm_init();
+	omap2_clk_enable_autoidle_all();
 }
 
 void __init omap3630_init_late(void)
@@ -497,6 +526,7 @@ void __init omap3630_init_late(void)
 	omap_mux_late_init();
 	omap2_common_pm_late_init();
 	omap3_pm_init();
+	omap2_clk_enable_autoidle_all();
 }
 
 void __init am35xx_init_late(void)
@@ -504,6 +534,7 @@ void __init am35xx_init_late(void)
 	omap_mux_late_init();
 	omap2_common_pm_late_init();
 	omap3_pm_init();
+	omap2_clk_enable_autoidle_all();
 }
 
 void __init ti81xx_init_late(void)
@@ -511,16 +542,21 @@ void __init ti81xx_init_late(void)
 	omap_mux_late_init();
 	omap2_common_pm_late_init();
 	omap3_pm_init();
+	omap2_clk_enable_autoidle_all();
 }
 #endif
 
 #ifdef CONFIG_SOC_AM33XX
 void __init am33xx_init_early(void)
 {
-	omap2_set_globals_am33xx();
+	omap2_set_globals_tap(AM335X_CLASS,
+			      AM33XX_L4_WK_IO_ADDRESS(AM33XX_TAP_BASE));
+	omap2_set_globals_control(AM33XX_L4_WK_IO_ADDRESS(AM33XX_CTRL_BASE),
+				  NULL);
+	omap2_set_globals_prm(AM33XX_L4_WK_IO_ADDRESS(AM33XX_PRCM_BASE));
+	omap2_set_globals_cm(AM33XX_L4_WK_IO_ADDRESS(AM33XX_PRCM_BASE), NULL);
 	omap3xxx_check_revision();
 	ti81xx_check_features();
-	omap_common_init_early();
 	am33xx_voltagedomains_init();
 	am33xx_powerdomains_init();
 	am33xx_clockdomains_init();
@@ -533,10 +569,18 @@ void __init am33xx_init_early(void)
 #ifdef CONFIG_ARCH_OMAP4
 void __init omap4430_init_early(void)
 {
-	omap2_set_globals_443x();
+	omap2_set_globals_tap(OMAP443X_CLASS,
+			      OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE));
+	omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
+				  OMAP2_L4_IO_ADDRESS(OMAP443X_CTRL_BASE));
+	omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE));
+	omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP4430_CM_BASE),
+			     OMAP2_L4_IO_ADDRESS(OMAP4430_CM2_BASE));
+	omap2_set_globals_prcm_mpu(OMAP2_L4_IO_ADDRESS(OMAP4430_PRCM_MPU_BASE));
+	omap_prm_base_init();
+	omap_cm_base_init();
 	omap4xxx_check_revision();
 	omap4xxx_check_features();
-	omap_common_init_early();
 	omap44xx_voltagedomains_init();
 	omap44xx_powerdomains_init();
 	omap44xx_clockdomains_init();
@@ -550,15 +594,24 @@ void __init omap4430_init_late(void)
 	omap_mux_late_init();
 	omap2_common_pm_late_init();
 	omap4_pm_init();
+	omap2_clk_enable_autoidle_all();
 }
 #endif
 
 #ifdef CONFIG_SOC_OMAP5
 void __init omap5_init_early(void)
 {
-	omap2_set_globals_5xxx();
+	omap2_set_globals_tap(OMAP54XX_CLASS,
+			      OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE));
+	omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE),
+				  OMAP2_L4_IO_ADDRESS(OMAP54XX_CTRL_BASE));
+	omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP54XX_PRM_BASE));
+	omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_AON_BASE),
+			     OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_BASE));
+	omap2_set_globals_prcm_mpu(OMAP2_L4_IO_ADDRESS(OMAP54XX_PRCM_MPU_BASE));
+	omap_prm_base_init();
+	omap_cm_base_init();
 	omap5xxx_check_revision();
-	omap_common_init_early();
 }
 #endif
 
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index 37f8f94..bf49651 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -19,16 +19,17 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/platform_data/asoc-ti-mcbsp.h>
-
-#include <plat/dma.h>
-#include <plat/omap_device.h>
 #include <linux/pm_runtime.h>
 
+#include <plat-omap/dma-omap.h>
+
+#include "omap_device.h"
+
 /*
  * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle.
  * Sidetone needs non-gated ICLK and sidetone autoidle is broken.
  */
-#include "cm2xxx_3xxx.h"
+#include "cm3xxx.h"
 #include "cm-regbits-34xx.h"
 
 static int omap3_enable_st_clock(unsigned int id, bool enable)
diff --git a/arch/arm/mach-omap2/mmc.h b/arch/arm/mach-omap2/mmc.h
new file mode 100644
index 0000000..0cd4b08
--- /dev/null
+++ b/arch/arm/mach-omap2/mmc.h
@@ -0,0 +1,23 @@
+#include <linux/mmc/host.h>
+#include <linux/platform_data/mmc-omap.h>
+
+#define OMAP24XX_NR_MMC		2
+#define OMAP2420_MMC_SIZE	OMAP1_MMC_SIZE
+#define OMAP2_MMC1_BASE		0x4809c000
+
+#define OMAP4_MMC_REG_OFFSET	0x100
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data);
+#else
+static inline void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data)
+{
+}
+#endif
+
+struct omap_hwmod;
+int omap_msdi_reset(struct omap_hwmod *oh);
+
+/* called from board-specific card detection service routine */
+extern void omap_mmc_notify_cover_event(struct device *dev, int slot,
+					int is_closed);
diff --git a/arch/arm/mach-omap2/msdi.c b/arch/arm/mach-omap2/msdi.c
index 9e57b4a..aafdd4c 100644
--- a/arch/arm/mach-omap2/msdi.c
+++ b/arch/arm/mach-omap2/msdi.c
@@ -25,13 +25,13 @@
 #include <linux/err.h>
 #include <linux/platform_data/gpio-omap.h>
 
-#include <plat/omap_hwmod.h>
-#include <plat/omap_device.h>
-#include <plat/mmc.h>
-
+#include "prm.h"
 #include "common.h"
 #include "control.h"
+#include "omap_hwmod.h"
+#include "omap_device.h"
 #include "mux.h"
+#include "mmc.h"
 
 /*
  * MSDI_CON_OFFSET: offset in bytes of the MSDI IP block's CON register
@@ -44,9 +44,6 @@
 #define MSDI_CON_CLKD_MASK			(0x3f << 0)
 #define MSDI_CON_CLKD_SHIFT			0
 
-/* Maximum microseconds to wait for OMAP module to softreset */
-#define MAX_MODULE_SOFTRESET_WAIT	10000
-
 /* MSDI_TARGET_RESET_CLKD: clock divisor to use throughout the reset */
 #define MSDI_TARGET_RESET_CLKD		0x3ff
 
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 701e17c..2612634 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -36,8 +36,9 @@
 #include <linux/interrupt.h>
 
 
-#include <plat/omap_hwmod.h>
+#include "omap_hwmod.h"
 
+#include "soc.h"
 #include "control.h"
 #include "mux.h"
 #include "prm.h"
diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S
index 502e313..0ea09fa 100644
--- a/arch/arm/mach-omap2/omap-headsmp.S
+++ b/arch/arm/mach-omap2/omap-headsmp.S
@@ -18,6 +18,8 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 
+#include "omap44xx.h"
+
 	__CPUINIT
 
 /* Physical address needed since MMU not enabled yet on secondary core */
@@ -64,3 +66,39 @@ hold:	ldr	r12,=0x103
 	b	secondary_startup
 ENDPROC(omap_secondary_startup)
 
+ENTRY(omap_secondary_startup_4460)
+hold_2:	ldr	r12,=0x103
+	dsb
+	smc	#0			@ read from AuxCoreBoot0
+	mov	r0, r0, lsr #9
+	mrc	p15, 0, r4, c0, c0, 5
+	and	r4, r4, #0x0f
+	cmp	r0, r4
+	bne	hold_2
+
+	/*
+	 * GIC distributor control register has changed between
+	 * CortexA9 r1pX and r2pX. The Control Register secure
+	 * banked version is now composed of 2 bits:
+	 * bit 0 == Secure Enable
+	 * bit 1 == Non-Secure Enable
+	 * The Non-Secure banked register has not changed
+	 * Because the ROM Code is based on the r1pX GIC, the CPU1
+	 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
+	 * The workaround must be:
+	 * 1) Before doing the CPU1 wakeup, CPU0 must disable
+	 * the GIC distributor
+	 * 2) CPU1 must re-enable the GIC distributor on
+	 * it's wakeup path.
+	 */
+	ldr	r1, =OMAP44XX_GIC_DIST_BASE
+	ldr	r0, [r1]
+	orr	r0, #1
+	str	r0, [r1]
+
+	/*
+	 * we've been released from the wait loop,secondary_stack
+	 * should now contain the SVC stack for this core
+	 */
+	b	secondary_startup
+ENDPROC(omap_secondary_startup_4460)
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index ff4e6a0..aac46bf 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -50,6 +50,7 @@
 #include <asm/suspend.h>
 #include <asm/hardware/cache-l2x0.h>
 
+#include "soc.h"
 #include "common.h"
 #include "omap44xx.h"
 #include "omap4-sar-layout.h"
@@ -67,6 +68,7 @@ struct omap4_cpu_pm_info {
 	void __iomem *scu_sar_addr;
 	void __iomem *wkup_sar_addr;
 	void __iomem *l2x0_sar_addr;
+	void (*secondary_startup)(void);
 };
 
 static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
@@ -299,6 +301,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 {
 	unsigned int cpu_state = 0;
+	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu);
 
 	if (omap_rev() == OMAP4430_REV_ES1_0)
 		return -ENXIO;
@@ -308,7 +311,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 
 	clear_cpu_prev_pwrst(cpu);
 	set_cpu_next_pwrst(cpu, power_state);
-	set_cpu_wakeup_addr(cpu, virt_to_phys(omap_secondary_startup));
+	set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
 	scu_pwrst_prepare(cpu, power_state);
 
 	/*
@@ -359,6 +362,11 @@ int __init omap4_mpuss_init(void)
 	pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
 	pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
 	pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
+	if (cpu_is_omap446x())
+		pm_info->secondary_startup = omap_secondary_startup_4460;
+	else
+		pm_info->secondary_startup = omap_secondary_startup;
+
 	pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
 	if (!pm_info->pwrdm) {
 		pr_err("Lookup failed for CPU1 pwrdm\n");
diff --git a/arch/arm/mach-omap2/omap-pm-noop.c b/arch/arm/mach-omap2/omap-pm-noop.c
new file mode 100644
index 0000000..6a3be2b
--- /dev/null
+++ b/arch/arm/mach-omap2/omap-pm-noop.c
@@ -0,0 +1,371 @@
+/*
+ * omap-pm-noop.c - OMAP power management interface - dummy version
+ *
+ * This code implements the OMAP power management interface to
+ * drivers, CPUIdle, CPUFreq, and DSP Bridge.  It is strictly for
+ * debug/demonstration use, as it does nothing but printk() whenever a
+ * function is called (when DEBUG is defined, below)
+ *
+ * Copyright (C) 2008-2009 Texas Instruments, Inc.
+ * Copyright (C) 2008-2009 Nokia Corporation
+ * Paul Walmsley
+ *
+ * Interface developed by (in alphabetical order):
+ * Karthik Dasu, Tony Lindgren, Rajendra Nayak, Sakari Poussa, Veeramanikandan
+ * Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, Richard Woodruff
+ */
+
+#undef DEBUG
+
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
+#include "omap_device.h"
+#include "omap-pm.h"
+
+static bool off_mode_enabled;
+static int dummy_context_loss_counter;
+
+/*
+ * Device-driver-originated constraints (via board-*.c files)
+ */
+
+int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t)
+{
+	if (!dev || t < -1) {
+		WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
+		return -EINVAL;
+	}
+
+	if (t == -1)
+		pr_debug("OMAP PM: remove max MPU wakeup latency constraint: dev %s\n",
+			 dev_name(dev));
+	else
+		pr_debug("OMAP PM: add max MPU wakeup latency constraint: dev %s, t = %ld usec\n",
+			 dev_name(dev), t);
+
+	/*
+	 * For current Linux, this needs to map the MPU to a
+	 * powerdomain, then go through the list of current max lat
+	 * constraints on the MPU and find the smallest.  If
+	 * the latency constraint has changed, the code should
+	 * recompute the state to enter for the next powerdomain
+	 * state.
+	 *
+	 * TI CDP code can call constraint_set here.
+	 */
+
+	return 0;
+}
+
+int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r)
+{
+	if (!dev || (agent_id != OCP_INITIATOR_AGENT &&
+	    agent_id != OCP_TARGET_AGENT)) {
+		WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
+		return -EINVAL;
+	}
+
+	if (r == 0)
+		pr_debug("OMAP PM: remove min bus tput constraint: dev %s for agent_id %d\n",
+			 dev_name(dev), agent_id);
+	else
+		pr_debug("OMAP PM: add min bus tput constraint: dev %s for agent_id %d: rate %ld KiB\n",
+			 dev_name(dev), agent_id, r);
+
+	/*
+	 * This code should model the interconnect and compute the
+	 * required clock frequency, convert that to a VDD2 OPP ID, then
+	 * set the VDD2 OPP appropriately.
+	 *
+	 * TI CDP code can call constraint_set here on the VDD2 OPP.
+	 */
+
+	return 0;
+}
+
+int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev,
+				   long t)
+{
+	if (!req_dev || !dev || t < -1) {
+		WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
+		return -EINVAL;
+	}
+
+	if (t == -1)
+		pr_debug("OMAP PM: remove max device latency constraint: dev %s\n",
+			 dev_name(dev));
+	else
+		pr_debug("OMAP PM: add max device latency constraint: dev %s, t = %ld usec\n",
+			 dev_name(dev), t);
+
+	/*
+	 * For current Linux, this needs to map the device to a
+	 * powerdomain, then go through the list of current max lat
+	 * constraints on that powerdomain and find the smallest.  If
+	 * the latency constraint has changed, the code should
+	 * recompute the state to enter for the next powerdomain
+	 * state.  Conceivably, this code should also determine
+	 * whether to actually disable the device clocks or not,
+	 * depending on how long it takes to re-enable the clocks.
+	 *
+	 * TI CDP code can call constraint_set here.
+	 */
+
+	return 0;
+}
+
+int omap_pm_set_max_sdma_lat(struct device *dev, long t)
+{
+	if (!dev || t < -1) {
+		WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
+		return -EINVAL;
+	}
+
+	if (t == -1)
+		pr_debug("OMAP PM: remove max DMA latency constraint: dev %s\n",
+			 dev_name(dev));
+	else
+		pr_debug("OMAP PM: add max DMA latency constraint: dev %s, t = %ld usec\n",
+			 dev_name(dev), t);
+
+	/*
+	 * For current Linux PM QOS params, this code should scan the
+	 * list of maximum CPU and DMA latencies and select the
+	 * smallest, then set cpu_dma_latency pm_qos_param
+	 * accordingly.
+	 *
+	 * For future Linux PM QOS params, with separate CPU and DMA
+	 * latency params, this code should just set the dma_latency param.
+	 *
+	 * TI CDP code can call constraint_set here.
+	 */
+
+	return 0;
+}
+
+int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r)
+{
+	if (!dev || !c || r < 0) {
+		WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
+		return -EINVAL;
+	}
+
+	if (r == 0)
+		pr_debug("OMAP PM: remove min clk rate constraint: dev %s\n",
+			 dev_name(dev));
+	else
+		pr_debug("OMAP PM: add min clk rate constraint: dev %s, rate = %ld Hz\n",
+			 dev_name(dev), r);
+
+	/*
+	 * Code in a real implementation should keep track of these
+	 * constraints on the clock, and determine the highest minimum
+	 * clock rate.  It should iterate over each OPP and determine
+	 * whether the OPP will result in a clock rate that would
+	 * satisfy this constraint (and any other PM constraint in effect
+	 * at that time).  Once it finds the lowest-voltage OPP that
+	 * meets those conditions, it should switch to it, or return
+	 * an error if the code is not capable of doing so.
+	 */
+
+	return 0;
+}
+
+/*
+ * DSP Bridge-specific constraints
+ */
+
+const struct omap_opp *omap_pm_dsp_get_opp_table(void)
+{
+	pr_debug("OMAP PM: DSP request for OPP table\n");
+
+	/*
+	 * Return DSP frequency table here:  The final item in the
+	 * array should have .rate = .opp_id = 0.
+	 */
+
+	return NULL;
+}
+
+void omap_pm_dsp_set_min_opp(u8 opp_id)
+{
+	if (opp_id == 0) {
+		WARN_ON(1);
+		return;
+	}
+
+	pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id);
+
+	/*
+	 *
+	 * For l-o dev tree, our VDD1 clk is keyed on OPP ID, so we
+	 * can just test to see which is higher, the CPU's desired OPP
+	 * ID or the DSP's desired OPP ID, and use whichever is
+	 * highest.
+	 *
+	 * In CDP12.14+, the VDD1 OPP custom clock that controls the DSP
+	 * rate is keyed on MPU speed, not the OPP ID.  So we need to
+	 * map the OPP ID to the MPU speed for use with clk_set_rate()
+	 * if it is higher than the current OPP clock rate.
+	 *
+	 */
+}
+
+
+u8 omap_pm_dsp_get_opp(void)
+{
+	pr_debug("OMAP PM: DSP requests current DSP OPP ID\n");
+
+	/*
+	 * For l-o dev tree, call clk_get_rate() on VDD1 OPP clock
+	 *
+	 * CDP12.14+:
+	 * Call clk_get_rate() on the OPP custom clock, map that to an
+	 * OPP ID using the tables defined in board-*.c/chip-*.c files.
+	 */
+
+	return 0;
+}
+
+/*
+ * CPUFreq-originated constraint
+ *
+ * In the future, this should be handled by custom OPP clocktype
+ * functions.
+ */
+
+struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void)
+{
+	pr_debug("OMAP PM: CPUFreq request for frequency table\n");
+
+	/*
+	 * Return CPUFreq frequency table here: loop over
+	 * all VDD1 clkrates, pull out the mpu_ck frequencies, build
+	 * table
+	 */
+
+	return NULL;
+}
+
+void omap_pm_cpu_set_freq(unsigned long f)
+{
+	if (f == 0) {
+		WARN_ON(1);
+		return;
+	}
+
+	pr_debug("OMAP PM: CPUFreq requests CPU frequency to be set to %lu\n",
+		 f);
+
+	/*
+	 * For l-o dev tree, determine whether MPU freq or DSP OPP id
+	 * freq is higher.  Find the OPP ID corresponding to the
+	 * higher frequency.  Call clk_round_rate() and clk_set_rate()
+	 * on the OPP custom clock.
+	 *
+	 * CDP should just be able to set the VDD1 OPP clock rate here.
+	 */
+}
+
+unsigned long omap_pm_cpu_get_freq(void)
+{
+	pr_debug("OMAP PM: CPUFreq requests current CPU frequency\n");
+
+	/*
+	 * Call clk_get_rate() on the mpu_ck.
+	 */
+
+	return 0;
+}
+
+/**
+ * omap_pm_enable_off_mode - notify OMAP PM that off-mode is enabled
+ *
+ * Intended for use only by OMAP PM core code to notify this layer
+ * that off mode has been enabled.
+ */
+void omap_pm_enable_off_mode(void)
+{
+	off_mode_enabled = true;
+}
+
+/**
+ * omap_pm_disable_off_mode - notify OMAP PM that off-mode is disabled
+ *
+ * Intended for use only by OMAP PM core code to notify this layer
+ * that off mode has been disabled.
+ */
+void omap_pm_disable_off_mode(void)
+{
+	off_mode_enabled = false;
+}
+
+/*
+ * Device context loss tracking
+ */
+
+#ifdef CONFIG_ARCH_OMAP2PLUS
+
+int omap_pm_get_dev_context_loss_count(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	int count;
+
+	if (WARN_ON(!dev))
+		return -ENODEV;
+
+	if (dev->pm_domain == &omap_device_pm_domain) {
+		count = omap_device_get_context_loss_count(pdev);
+	} else {
+		WARN_ONCE(off_mode_enabled, "omap_pm: using dummy context loss counter; device %s should be converted to omap_device",
+			  dev_name(dev));
+
+		count = dummy_context_loss_counter;
+
+		if (off_mode_enabled) {
+			count++;
+			/*
+			 * Context loss count has to be a non-negative value.
+			 * Clear the sign bit to get a value range from 0 to
+			 * INT_MAX.
+			 */
+			count &= INT_MAX;
+			dummy_context_loss_counter = count;
+		}
+	}
+
+	pr_debug("OMAP PM: context loss count for dev %s = %d\n",
+		 dev_name(dev), count);
+
+	return count;
+}
+
+#else
+
+int omap_pm_get_dev_context_loss_count(struct device *dev)
+{
+	return dummy_context_loss_counter;
+}
+
+#endif
+
+/* Should be called before clk framework init */
+int __init omap_pm_if_early_init(void)
+{
+	return 0;
+}
+
+/* Must be called after clock framework is initialized */
+int __init omap_pm_if_init(void)
+{
+	return 0;
+}
+
+void omap_pm_if_exit(void)
+{
+	/* Deallocate CPUFreq frequency table here */
+}
+
diff --git a/arch/arm/mach-omap2/omap-pm.h b/arch/arm/mach-omap2/omap-pm.h
new file mode 100644
index 0000000..67faa7b
--- /dev/null
+++ b/arch/arm/mach-omap2/omap-pm.h
@@ -0,0 +1,352 @@
+/*
+ * omap-pm.h - OMAP power management interface
+ *
+ * Copyright (C) 2008-2010 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ * Paul Walmsley
+ *
+ * Interface developed by (in alphabetical order): Karthik Dasu, Jouni
+ * Högander, Tony Lindgren, Rajendra Nayak, Sakari Poussa,
+ * Veeramanikandan Raju, Anand Sawant, Igor Stoppa, Paul Walmsley,
+ * Richard Woodruff
+ */
+
+#ifndef ASM_ARM_ARCH_OMAP_OMAP_PM_H
+#define ASM_ARM_ARCH_OMAP_OMAP_PM_H
+
+#include <linux/device.h>
+#include <linux/cpufreq.h>
+#include <linux/clk.h>
+#include <linux/opp.h>
+
+/*
+ * agent_id values for use with omap_pm_set_min_bus_tput():
+ *
+ * OCP_INITIATOR_AGENT is only valid for devices that can act as
+ * initiators -- it represents the device's L3 interconnect
+ * connection.  OCP_TARGET_AGENT represents the device's L4
+ * interconnect connection.
+ */
+#define OCP_TARGET_AGENT		1
+#define OCP_INITIATOR_AGENT		2
+
+/**
+ * omap_pm_if_early_init - OMAP PM init code called before clock fw init
+ * @mpu_opp_table: array ptr to struct omap_opp for MPU
+ * @dsp_opp_table: array ptr to struct omap_opp for DSP
+ * @l3_opp_table : array ptr to struct omap_opp for CORE
+ *
+ * Initialize anything that must be configured before the clock
+ * framework starts.  The "_if_" is to avoid name collisions with the
+ * PM idle-loop code.
+ */
+int __init omap_pm_if_early_init(void);
+
+/**
+ * omap_pm_if_init - OMAP PM init code called after clock fw init
+ *
+ * The main initialization code.  OPP tables are passed in here.  The
+ * "_if_" is to avoid name collisions with the PM idle-loop code.
+ */
+int __init omap_pm_if_init(void);
+
+/**
+ * omap_pm_if_exit - OMAP PM exit code
+ *
+ * Exit code; currently unused.  The "_if_" is to avoid name
+ * collisions with the PM idle-loop code.
+ */
+void omap_pm_if_exit(void);
+
+/*
+ * Device-driver-originated constraints (via board-*.c files, platform_data)
+ */
+
+
+/**
+ * omap_pm_set_max_mpu_wakeup_lat - set the maximum MPU wakeup latency
+ * @dev: struct device * requesting the constraint
+ * @t: maximum MPU wakeup latency in microseconds
+ *
+ * Request that the maximum interrupt latency for the MPU to be no
+ * greater than @t microseconds. "Interrupt latency" in this case is
+ * defined as the elapsed time from the occurrence of a hardware or
+ * timer interrupt to the time when the device driver's interrupt
+ * service routine has been entered by the MPU.
+ *
+ * It is intended that underlying PM code will use this information to
+ * determine what power state to put the MPU powerdomain into, and
+ * possibly the CORE powerdomain as well, since interrupt handling
+ * code currently runs from SDRAM.  Advanced PM or board*.c code may
+ * also configure interrupt controller priorities, OCP bus priorities,
+ * CPU speed(s), etc.
+ *
+ * This function will not affect device wakeup latency, e.g., time
+ * elapsed from when a device driver enables a hardware device with
+ * clk_enable(), to when the device is ready for register access or
+ * other use.  To control this device wakeup latency, use
+ * omap_pm_set_max_dev_wakeup_lat()
+ *
+ * Multiple calls to omap_pm_set_max_mpu_wakeup_lat() will replace the
+ * previous t value.  To remove the latency target for the MPU, call
+ * with t = -1.
+ *
+ * XXX This constraint will be deprecated soon in favor of the more
+ * general omap_pm_set_max_dev_wakeup_lat()
+ *
+ * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
+ * is not satisfiable, or 0 upon success.
+ */
+int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t);
+
+
+/**
+ * omap_pm_set_min_bus_tput - set minimum bus throughput needed by device
+ * @dev: struct device * requesting the constraint
+ * @tbus_id: interconnect to operate on (OCP_{INITIATOR,TARGET}_AGENT)
+ * @r: minimum throughput (in KiB/s)
+ *
+ * Request that the minimum data throughput on the OCP interconnect
+ * attached to device @dev interconnect agent @tbus_id be no less
+ * than @r KiB/s.
+ *
+ * It is expected that the OMAP PM or bus code will use this
+ * information to set the interconnect clock to run at the lowest
+ * possible speed that satisfies all current system users.  The PM or
+ * bus code will adjust the estimate based on its model of the bus, so
+ * device driver authors should attempt to specify an accurate
+ * quantity for their device use case, and let the PM or bus code
+ * overestimate the numbers as necessary to handle request/response
+ * latency, other competing users on the system, etc.  On OMAP2/3, if
+ * a driver requests a minimum L4 interconnect speed constraint, the
+ * code will also need to add an minimum L3 interconnect speed
+ * constraint,
+ *
+ * Multiple calls to omap_pm_set_min_bus_tput() will replace the
+ * previous rate value for this device.  To remove the interconnect
+ * throughput restriction for this device, call with r = 0.
+ *
+ * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
+ * is not satisfiable, or 0 upon success.
+ */
+int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r);
+
+
+/**
+ * omap_pm_set_max_dev_wakeup_lat - set the maximum device enable latency
+ * @req_dev: struct device * requesting the constraint, or NULL if none
+ * @dev: struct device * to set the constraint one
+ * @t: maximum device wakeup latency in microseconds
+ *
+ * Request that the maximum amount of time necessary for a device @dev
+ * to become accessible after its clocks are enabled should be no
+ * greater than @t microseconds.  Specifically, this represents the
+ * time from when a device driver enables device clocks with
+ * clk_enable(), to when the register reads and writes on the device
+ * will succeed.  This function should be called before clk_disable()
+ * is called, since the power state transition decision may be made
+ * during clk_disable().
+ *
+ * It is intended that underlying PM code will use this information to
+ * determine what power state to put the powerdomain enclosing this
+ * device into.
+ *
+ * Multiple calls to omap_pm_set_max_dev_wakeup_lat() will replace the
+ * previous wakeup latency values for this device.  To remove the
+ * wakeup latency restriction for this device, call with t = -1.
+ *
+ * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
+ * is not satisfiable, or 0 upon success.
+ */
+int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev,
+				   long t);
+
+
+/**
+ * omap_pm_set_max_sdma_lat - set the maximum system DMA transfer start latency
+ * @dev: struct device *
+ * @t: maximum DMA transfer start latency in microseconds
+ *
+ * Request that the maximum system DMA transfer start latency for this
+ * device 'dev' should be no greater than 't' microseconds.  "DMA
+ * transfer start latency" here is defined as the elapsed time from
+ * when a device (e.g., McBSP) requests that a system DMA transfer
+ * start or continue, to the time at which data starts to flow into
+ * that device from the system DMA controller.
+ *
+ * It is intended that underlying PM code will use this information to
+ * determine what power state to put the CORE powerdomain into.
+ *
+ * Since system DMA transfers may not involve the MPU, this function
+ * will not affect MPU wakeup latency.  Use set_max_cpu_lat() to do
+ * so.  Similarly, this function will not affect device wakeup latency
+ * -- use set_max_dev_wakeup_lat() to affect that.
+ *
+ * Multiple calls to set_max_sdma_lat() will replace the previous t
+ * value for this device.  To remove the maximum DMA latency for this
+ * device, call with t = -1.
+ *
+ * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
+ * is not satisfiable, or 0 upon success.
+ */
+int omap_pm_set_max_sdma_lat(struct device *dev, long t);
+
+
+/**
+ * omap_pm_set_min_clk_rate - set minimum clock rate requested by @dev
+ * @dev: struct device * requesting the constraint
+ * @clk: struct clk * to set the minimum rate constraint on
+ * @r: minimum rate in Hz
+ *
+ * Request that the minimum clock rate on the device @dev's clk @clk
+ * be no less than @r Hz.
+ *
+ * It is expected that the OMAP PM code will use this information to
+ * find an OPP or clock setting that will satisfy this clock rate
+ * constraint, along with any other applicable system constraints on
+ * the clock rate or corresponding voltage, etc.
+ *
+ * omap_pm_set_min_clk_rate() differs from the clock code's
+ * clk_set_rate() in that it considers other constraints before taking
+ * any hardware action, and may change a system OPP rather than just a
+ * clock rate.  clk_set_rate() is intended to be a low-level
+ * interface.
+ *
+ * omap_pm_set_min_clk_rate() is easily open to abuse.  A better API
+ * would be something like "omap_pm_set_min_dev_performance()";
+ * however, there is no easily-generalizable concept of performance
+ * that applies to all devices.  Only a device (and possibly the
+ * device subsystem) has both the subsystem-specific knowledge, and
+ * the hardware IP block-specific knowledge, to translate a constraint
+ * on "touchscreen sampling accuracy" or "number of pixels or polygons
+ * rendered per second" to a clock rate.  This translation can be
+ * dependent on the hardware IP block's revision, or firmware version,
+ * and the driver is the only code on the system that has this
+ * information and can know how to translate that into a clock rate.
+ *
+ * The intended use-case for this function is for userspace or other
+ * kernel code to communicate a particular performance requirement to
+ * a subsystem; then for the subsystem to communicate that requirement
+ * to something that is meaningful to the device driver; then for the
+ * device driver to convert that requirement to a clock rate, and to
+ * then call omap_pm_set_min_clk_rate().
+ *
+ * Users of this function (such as device drivers) should not simply
+ * call this function with some high clock rate to ensure "high
+ * performance."  Rather, the device driver should take a performance
+ * constraint from its subsystem, such as "render at least X polygons
+ * per second," and use some formula or table to convert that into a
+ * clock rate constraint given the hardware type and hardware
+ * revision.  Device drivers or subsystems should not assume that they
+ * know how to make a power/performance tradeoff - some device use
+ * cases may tolerate a lower-fidelity device function for lower power
+ * consumption; others may demand a higher-fidelity device function,
+ * no matter what the power consumption.
+ *
+ * Multiple calls to omap_pm_set_min_clk_rate() will replace the
+ * previous rate value for the device @dev.  To remove the minimum clock
+ * rate constraint for the device, call with r = 0.
+ *
+ * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
+ * is not satisfiable, or 0 upon success.
+ */
+int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r);
+
+/*
+ * DSP Bridge-specific constraints
+ */
+
+/**
+ * omap_pm_dsp_get_opp_table - get OPP->DSP clock frequency table
+ *
+ * Intended for use by DSPBridge.  Returns an array of OPP->DSP clock
+ * frequency entries.  The final item in the array should have .rate =
+ * .opp_id = 0.
+ */
+const struct omap_opp *omap_pm_dsp_get_opp_table(void);
+
+/**
+ * omap_pm_dsp_set_min_opp - receive desired OPP target ID from DSP Bridge
+ * @opp_id: target DSP OPP ID
+ *
+ * Set a minimum OPP ID for the DSP.  This is intended to be called
+ * only from the DSP Bridge MPU-side driver.  Unfortunately, the only
+ * information that code receives from the DSP/BIOS load estimator is the
+ * target OPP ID; hence, this interface.  No return value.
+ */
+void omap_pm_dsp_set_min_opp(u8 opp_id);
+
+/**
+ * omap_pm_dsp_get_opp - report the current DSP OPP ID
+ *
+ * Report the current OPP for the DSP.  Since on OMAP3, the DSP and
+ * MPU share a single voltage domain, the OPP ID returned back may
+ * represent a higher DSP speed than the OPP requested via
+ * omap_pm_dsp_set_min_opp().
+ *
+ * Returns the current VDD1 OPP ID, or 0 upon error.
+ */
+u8 omap_pm_dsp_get_opp(void);
+
+
+/*
+ * CPUFreq-originated constraint
+ *
+ * In the future, this should be handled by custom OPP clocktype
+ * functions.
+ */
+
+/**
+ * omap_pm_cpu_get_freq_table - return a cpufreq_frequency_table array ptr
+ *
+ * Provide a frequency table usable by CPUFreq for the current chip/board.
+ * Returns a pointer to a struct cpufreq_frequency_table array or NULL
+ * upon error.
+ */
+struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void);
+
+/**
+ * omap_pm_cpu_set_freq - set the current minimum MPU frequency
+ * @f: MPU frequency in Hz
+ *
+ * Set the current minimum CPU frequency.  The actual CPU frequency
+ * used could end up higher if the DSP requested a higher OPP.
+ * Intended to be called by plat-omap/cpu_omap.c:omap_target().  No
+ * return value.
+ */
+void omap_pm_cpu_set_freq(unsigned long f);
+
+/**
+ * omap_pm_cpu_get_freq - report the current CPU frequency
+ *
+ * Returns the current MPU frequency, or 0 upon error.
+ */
+unsigned long omap_pm_cpu_get_freq(void);
+
+
+/*
+ * Device context loss tracking
+ */
+
+/**
+ * omap_pm_get_dev_context_loss_count - return count of times dev has lost ctx
+ * @dev: struct device *
+ *
+ * This function returns the number of times that the device @dev has
+ * lost its internal context.  This generally occurs on a powerdomain
+ * transition to OFF.  Drivers use this as an optimization to avoid restoring
+ * context if the device hasn't lost it.  To use, drivers should initially
+ * call this in their context save functions and store the result.  Early in
+ * the driver's context restore function, the driver should call this function
+ * again, and compare the result to the stored counter.  If they differ, the
+ * driver must restore device context.   If the number of context losses
+ * exceeds the maximum positive integer, the function will wrap to 0 and
+ * continue counting.  Returns the number of context losses for this device,
+ * or negative value upon error.
+ */
+int omap_pm_get_dev_context_loss_count(struct device *dev);
+
+void omap_pm_enable_off_mode(void);
+void omap_pm_disable_off_mode(void);
+
+#endif
diff --git a/arch/arm/mach-omap2/omap-secure.c b/arch/arm/mach-omap2/omap-secure.c
index e089e4d..b970440 100644
--- a/arch/arm/mach-omap2/omap-secure.c
+++ b/arch/arm/mach-omap2/omap-secure.c
@@ -18,7 +18,6 @@
 #include <asm/cacheflush.h>
 #include <asm/memblock.h>
 
-#include <plat/omap-secure.h>
 #include "omap-secure.h"
 
 static phys_addr_t omap_secure_memblock_base;
diff --git a/arch/arm/mach-omap2/omap-secure.h b/arch/arm/mach-omap2/omap-secure.h
index c90a435..0e72917 100644
--- a/arch/arm/mach-omap2/omap-secure.h
+++ b/arch/arm/mach-omap2/omap-secure.h
@@ -52,6 +52,13 @@ 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 phys_addr_t omap_secure_ram_mempool_base(void);
+extern int omap_secure_ram_reserve_memblock(void);
 
+#ifdef CONFIG_OMAP4_ERRATA_I688
+extern int omap_barrier_reserve_memblock(void);
+#else
+static inline void omap_barrier_reserve_memblock(void)
+{ }
+#endif
 #endif /* __ASSEMBLER__ */
 #endif /* OMAP_ARCH_OMAP_SECURE_H */
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index 4d05fa8..cd42d92 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -32,6 +32,7 @@
 #include "iomap.h"
 #include "common.h"
 #include "clockdomain.h"
+#include "pm.h"
 
 #define CPU_MASK		0xff0ffff0
 #define CPU_CORTEX_A9		0x410FC090
@@ -39,6 +40,8 @@
 
 #define OMAP5_CORE_COUNT	0x2
 
+u16 pm44xx_errata;
+
 /* SCU base address */
 static void __iomem *scu_base;
 
@@ -118,8 +121,37 @@ static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct *
 	 *	4.3.4.2 Power States of CPU0 and CPU1
 	 */
 	if (booted) {
+		/*
+		 * GIC distributor control register has changed between
+		 * CortexA9 r1pX and r2pX. The Control Register secure
+		 * banked version is now composed of 2 bits:
+		 * bit 0 == Secure Enable
+		 * bit 1 == Non-Secure Enable
+		 * The Non-Secure banked register has not changed
+		 * Because the ROM Code is based on the r1pX GIC, the CPU1
+		 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
+		 * The workaround must be:
+		 * 1) Before doing the CPU1 wakeup, CPU0 must disable
+		 * the GIC distributor
+		 * 2) CPU1 must re-enable the GIC distributor on
+		 * it's wakeup path.
+		 */
+		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
+			local_irq_disable();
+			gic_dist_disable();
+		}
+
 		clkdm_wakeup(cpu1_clkdm);
 		clkdm_allow_idle(cpu1_clkdm);
+
+		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
+			while (gic_dist_disabled()) {
+				udelay(1);
+				cpu_relax();
+			}
+			gic_timer_retrigger();
+			local_irq_enable();
+		}
 	} else {
 		dsb_sev();
 		booted = true;
@@ -138,7 +170,14 @@ static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct *
 
 static void __init wakeup_secondary(void)
 {
+	void *startup_addr = omap_secondary_startup;
 	void __iomem *base = omap_get_wakeupgen_base();
+
+	if (cpu_is_omap446x()) {
+		startup_addr = omap_secondary_startup_4460;
+		pm44xx_errata |= PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD;
+	}
+
 	/*
 	 * Write the address of secondary startup routine into the
 	 * AuxCoreBoot1 where ROM code will jump and start executing
@@ -146,7 +185,7 @@ static void __init wakeup_secondary(void)
 	 * A barrier is added to ensure that write buffer is drained
 	 */
 	if (omap_secure_apis_support())
-		omap_auxcoreboot_addr(virt_to_phys(omap_secondary_startup));
+		omap_auxcoreboot_addr(virt_to_phys(startup_addr));
 	else
 		__raw_writel(virt_to_phys(omap5_secondary_startup),
 						base + OMAP_AUX_CORE_BOOT_1);
diff --git a/arch/arm/mach-omap2/omap2-restart.c b/arch/arm/mach-omap2/omap2-restart.c
new file mode 100644
index 0000000..be6bc89
--- /dev/null
+++ b/arch/arm/mach-omap2/omap2-restart.c
@@ -0,0 +1,65 @@
+/*
+ * omap2-restart.c - code common to all OMAP2xxx machines.
+ *
+ * Copyright (C) 2012 Texas Instruments
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include "common.h"
+#include "prm2xxx.h"
+
+/*
+ * reset_virt_prcm_set_ck, reset_sys_ck: pointers to the virt_prcm_set
+ * clock and the sys_ck.  Used during the reset process
+ */
+static struct clk *reset_virt_prcm_set_ck, *reset_sys_ck;
+
+/* Reboot handling */
+
+/**
+ * omap2xxx_restart - Set DPLL to bypass mode for reboot to work
+ *
+ * Set the DPLL to bypass so that reboot completes successfully.  No
+ * return value.
+ */
+void omap2xxx_restart(char mode, const char *cmd)
+{
+	u32 rate;
+
+	rate = clk_get_rate(reset_sys_ck);
+	clk_set_rate(reset_virt_prcm_set_ck, rate);
+
+	/* XXX Should save the cmd argument for use after the reboot */
+
+	omap2xxx_prm_dpll_reset(); /* never returns */
+	while (1);
+}
+
+/**
+ * omap2xxx_common_look_up_clks_for_reset - look up clocks needed for restart
+ *
+ * Some clocks need to be looked up in advance for the SoC restart
+ * operation to work - see omap2xxx_restart().  Returns -EINVAL upon
+ * error or 0 upon success.
+ */
+static int __init omap2xxx_common_look_up_clks_for_reset(void)
+{
+	reset_virt_prcm_set_ck = clk_get(NULL, "virt_prcm_set");
+	if (IS_ERR(reset_virt_prcm_set_ck))
+		return -EINVAL;
+
+	reset_sys_ck = clk_get(NULL, "sys_ck");
+	if (IS_ERR(reset_sys_ck))
+		return -EINVAL;
+
+	return 0;
+}
+core_initcall(omap2xxx_common_look_up_clks_for_reset);
diff --git a/arch/arm/mach-omap2/omap3-restart.c b/arch/arm/mach-omap2/omap3-restart.c
new file mode 100644
index 0000000..923c582
--- /dev/null
+++ b/arch/arm/mach-omap2/omap3-restart.c
@@ -0,0 +1,36 @@
+/*
+ * omap3-restart.c - Code common to all OMAP3xxx machines.
+ *
+ * Copyright (C) 2009, 2012 Texas Instruments
+ * Copyright (C) 2010 Nokia Corporation
+ * Tony Lindgren <tony@atomide.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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include "iomap.h"
+#include "common.h"
+#include "control.h"
+#include "prm3xxx.h"
+
+/* Global address base setup code */
+
+/**
+ * omap3xxx_restart - trigger a software restart of the SoC
+ * @mode: the "reboot mode", see arch/arm/kernel/{setup,process}.c
+ * @cmd: passed from the userspace program rebooting the system (if provided)
+ *
+ * Resets the SoC.  For @cmd, see the 'reboot' syscall in
+ * kernel/sys.c.  No return value.
+ */
+void omap3xxx_restart(char mode, const char *cmd)
+{
+	omap3_ctrl_write_boot_mode((cmd ? (u8)*cmd : 0));
+	omap3xxx_prm_dpll3_reset(); /* never returns */
+	while (1);
+}
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index e1f2897..6897ae2 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/memblock.h>
 #include <linux/of_irq.h>
@@ -24,23 +25,29 @@
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/map.h>
 #include <asm/memblock.h>
-
-#include <plat/sram.h>
-#include <plat/omap-secure.h>
-#include <plat/mmc.h>
+#include <asm/smp_twd.h>
 
 #include "omap-wakeupgen.h"
-
 #include "soc.h"
+#include "iomap.h"
 #include "common.h"
+#include "mmc.h"
 #include "hsmmc.h"
+#include "prminst44xx.h"
+#include "prcm_mpu44xx.h"
 #include "omap4-sar-layout.h"
+#include "omap-secure.h"
+#include "sram.h"
 
 #ifdef CONFIG_CACHE_L2X0
 static void __iomem *l2cache_base;
 #endif
 
 static void __iomem *sar_ram_base;
+static void __iomem *gic_dist_base_addr;
+static void __iomem *twd_base;
+
+#define IRQ_LOCALTIMER		29
 
 #ifdef CONFIG_OMAP4_ERRATA_I688
 /* Used to implement memory barrier on DRAM path */
@@ -95,12 +102,14 @@ void __init omap_barriers_init(void)
 void __init gic_init_irq(void)
 {
 	void __iomem *omap_irq_base;
-	void __iomem *gic_dist_base_addr;
 
 	/* Static mapping, never released */
 	gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K);
 	BUG_ON(!gic_dist_base_addr);
 
+	twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_4K);
+	BUG_ON(!twd_base);
+
 	/* Static mapping, never released */
 	omap_irq_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
 	BUG_ON(!omap_irq_base);
@@ -110,6 +119,38 @@ void __init gic_init_irq(void)
 	gic_init(0, 29, gic_dist_base_addr, omap_irq_base);
 }
 
+void gic_dist_disable(void)
+{
+	if (gic_dist_base_addr)
+		__raw_writel(0x0, gic_dist_base_addr + GIC_DIST_CTRL);
+}
+
+bool gic_dist_disabled(void)
+{
+	return !(__raw_readl(gic_dist_base_addr + GIC_DIST_CTRL) & 0x1);
+}
+
+void gic_timer_retrigger(void)
+{
+	u32 twd_int = __raw_readl(twd_base + TWD_TIMER_INTSTAT);
+	u32 gic_int = __raw_readl(gic_dist_base_addr + GIC_DIST_PENDING_SET);
+	u32 twd_ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL);
+
+	if (twd_int && !(gic_int & BIT(IRQ_LOCALTIMER))) {
+		/*
+		 * The local timer interrupt got lost while the distributor was
+		 * disabled.  Ack the pending interrupt, and retrigger it.
+		 */
+		pr_warn("%s: lost localtimer interrupt\n", __func__);
+		__raw_writel(1, twd_base + TWD_TIMER_INTSTAT);
+		if (!(twd_ctrl & TWD_TIMER_CONTROL_PERIODIC)) {
+			__raw_writel(1, twd_base + TWD_TIMER_COUNTER);
+			twd_ctrl |= TWD_TIMER_CONTROL_ENABLE;
+			__raw_writel(twd_ctrl, twd_base + TWD_TIMER_CONTROL);
+		}
+	}
+}
+
 #ifdef CONFIG_CACHE_L2X0
 
 void __iomem *omap4_get_l2cache_base(void)
@@ -281,3 +322,19 @@ int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
 	return 0;
 }
 #endif
+
+/**
+ * omap44xx_restart - trigger a software restart of the SoC
+ * @mode: the "reboot mode", see arch/arm/kernel/{setup,process}.c
+ * @cmd: passed from the userspace program rebooting the system (if provided)
+ *
+ * Resets the SoC.  For @cmd, see the 'reboot' syscall in
+ * kernel/sys.c.  No return value.
+ */
+void omap44xx_restart(char mode, const char *cmd)
+{
+	/* XXX Should save 'cmd' into scratchpad for use after reboot */
+	omap4_prminst_global_warm_sw_reset(); /* never returns */
+	while (1);
+}
+
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
new file mode 100644
index 0000000..0ef934f
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -0,0 +1,1277 @@
+/*
+ * omap_device implementation
+ *
+ * Copyright (C) 2009-2010 Nokia Corporation
+ * Paul Walmsley, Kevin Hilman
+ *
+ * Developed in collaboration with (alphabetical order): Benoit
+ * Cousson, Thara Gopinath, Tony Lindgren, Rajendra Nayak, Vikram
+ * Pandita, Sakari Poussa, Anand Sawant, Santosh Shilimkar, Richard
+ * Woodruff
+ *
+ * This program is free software; you can 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 code provides a consistent interface for OMAP device drivers
+ * to control power management and interconnect properties of their
+ * devices.
+ *
+ * In the medium- to long-term, this code should either be
+ * a) implemented via arch-specific pointers in platform_data
+ * or
+ * b) implemented as a proper omap_bus/omap_device in Linux, no more
+ *    platform_data func pointers
+ *
+ *
+ * Guidelines for usage by driver authors:
+ *
+ * 1. These functions are intended to be used by device drivers via
+ * function pointers in struct platform_data.  As an example,
+ * omap_device_enable() should be passed to the driver as
+ *
+ * struct foo_driver_platform_data {
+ * ...
+ *      int (*device_enable)(struct platform_device *pdev);
+ * ...
+ * }
+ *
+ * Note that the generic "device_enable" name is used, rather than
+ * "omap_device_enable".  This is so other architectures can pass in their
+ * own enable/disable functions here.
+ *
+ * This should be populated during device setup:
+ *
+ * ...
+ * pdata->device_enable = omap_device_enable;
+ * ...
+ *
+ * 2. Drivers should first check to ensure the function pointer is not null
+ * before calling it, as in:
+ *
+ * if (pdata->device_enable)
+ *     pdata->device_enable(pdev);
+ *
+ * This allows other architectures that don't use similar device_enable()/
+ * device_shutdown() functions to execute normally.
+ *
+ * ...
+ *
+ * Suggested usage by device drivers:
+ *
+ * During device initialization:
+ * device_enable()
+ *
+ * During device idle:
+ * (save remaining device context if necessary)
+ * device_idle();
+ *
+ * During device resume:
+ * device_enable();
+ * (restore context if necessary)
+ *
+ * During device shutdown:
+ * device_shutdown()
+ * (device must be reinitialized at this point to use it again)
+ *
+ */
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/notifier.h>
+
+#include "omap_device.h"
+#include "omap_hwmod.h"
+
+/* These parameters are passed to _omap_device_{de,}activate() */
+#define USE_WAKEUP_LAT			0
+#define IGNORE_WAKEUP_LAT		1
+
+static int omap_early_device_register(struct platform_device *pdev);
+
+static struct omap_device_pm_latency omap_default_latency[] = {
+	{
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func   = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	}
+};
+
+/* Private functions */
+
+/**
+ * _omap_device_activate - increase device readiness
+ * @od: struct omap_device *
+ * @ignore_lat: increase to latency target (0) or full readiness (1)?
+ *
+ * Increase readiness of omap_device @od (thus decreasing device
+ * wakeup latency, but consuming more power).  If @ignore_lat is
+ * IGNORE_WAKEUP_LAT, make the omap_device fully active.  Otherwise,
+ * if @ignore_lat is USE_WAKEUP_LAT, and the device's maximum wakeup
+ * latency is greater than the requested maximum wakeup latency, step
+ * backwards in the omap_device_pm_latency table to ensure the
+ * device's maximum wakeup latency is less than or equal to the
+ * requested maximum wakeup latency.  Returns 0.
+ */
+static int _omap_device_activate(struct omap_device *od, u8 ignore_lat)
+{
+	struct timespec a, b, c;
+
+	dev_dbg(&od->pdev->dev, "omap_device: activating\n");
+
+	while (od->pm_lat_level > 0) {
+		struct omap_device_pm_latency *odpl;
+		unsigned long long act_lat = 0;
+
+		od->pm_lat_level--;
+
+		odpl = od->pm_lats + od->pm_lat_level;
+
+		if (!ignore_lat &&
+		    (od->dev_wakeup_lat <= od->_dev_wakeup_lat_limit))
+			break;
+
+		read_persistent_clock(&a);
+
+		/* XXX check return code */
+		odpl->activate_func(od);
+
+		read_persistent_clock(&b);
+
+		c = timespec_sub(b, a);
+		act_lat = timespec_to_ns(&c);
+
+		dev_dbg(&od->pdev->dev,
+			"omap_device: pm_lat %d: activate: elapsed time %llu nsec\n",
+			od->pm_lat_level, act_lat);
+
+		if (act_lat > odpl->activate_lat) {
+			odpl->activate_lat_worst = act_lat;
+			if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
+				odpl->activate_lat = act_lat;
+				dev_dbg(&od->pdev->dev,
+					"new worst case activate latency %d: %llu\n",
+					od->pm_lat_level, act_lat);
+			} else
+				dev_warn(&od->pdev->dev,
+					 "activate latency %d higher than expected. (%llu > %d)\n",
+					 od->pm_lat_level, act_lat,
+					 odpl->activate_lat);
+		}
+
+		od->dev_wakeup_lat -= odpl->activate_lat;
+	}
+
+	return 0;
+}
+
+/**
+ * _omap_device_deactivate - decrease device readiness
+ * @od: struct omap_device *
+ * @ignore_lat: decrease to latency target (0) or full inactivity (1)?
+ *
+ * Decrease readiness of omap_device @od (thus increasing device
+ * wakeup latency, but conserving power).  If @ignore_lat is
+ * IGNORE_WAKEUP_LAT, make the omap_device fully inactive.  Otherwise,
+ * if @ignore_lat is USE_WAKEUP_LAT, and the device's maximum wakeup
+ * latency is less than the requested maximum wakeup latency, step
+ * forwards in the omap_device_pm_latency table to ensure the device's
+ * maximum wakeup latency is less than or equal to the requested
+ * maximum wakeup latency.  Returns 0.
+ */
+static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
+{
+	struct timespec a, b, c;
+
+	dev_dbg(&od->pdev->dev, "omap_device: deactivating\n");
+
+	while (od->pm_lat_level < od->pm_lats_cnt) {
+		struct omap_device_pm_latency *odpl;
+		unsigned long long deact_lat = 0;
+
+		odpl = od->pm_lats + od->pm_lat_level;
+
+		if (!ignore_lat &&
+		    ((od->dev_wakeup_lat + odpl->activate_lat) >
+		     od->_dev_wakeup_lat_limit))
+			break;
+
+		read_persistent_clock(&a);
+
+		/* XXX check return code */
+		odpl->deactivate_func(od);
+
+		read_persistent_clock(&b);
+
+		c = timespec_sub(b, a);
+		deact_lat = timespec_to_ns(&c);
+
+		dev_dbg(&od->pdev->dev,
+			"omap_device: pm_lat %d: deactivate: elapsed time %llu nsec\n",
+			od->pm_lat_level, deact_lat);
+
+		if (deact_lat > odpl->deactivate_lat) {
+			odpl->deactivate_lat_worst = deact_lat;
+			if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
+				odpl->deactivate_lat = deact_lat;
+				dev_dbg(&od->pdev->dev,
+					"new worst case deactivate latency %d: %llu\n",
+					od->pm_lat_level, deact_lat);
+			} else
+				dev_warn(&od->pdev->dev,
+					 "deactivate latency %d higher than expected. (%llu > %d)\n",
+					 od->pm_lat_level, deact_lat,
+					 odpl->deactivate_lat);
+		}
+
+		od->dev_wakeup_lat += odpl->activate_lat;
+
+		od->pm_lat_level++;
+	}
+
+	return 0;
+}
+
+static void _add_clkdev(struct omap_device *od, const char *clk_alias,
+		       const char *clk_name)
+{
+	struct clk *r;
+	struct clk_lookup *l;
+
+	if (!clk_alias || !clk_name)
+		return;
+
+	dev_dbg(&od->pdev->dev, "Creating %s -> %s\n", clk_alias, clk_name);
+
+	r = clk_get_sys(dev_name(&od->pdev->dev), clk_alias);
+	if (!IS_ERR(r)) {
+		dev_warn(&od->pdev->dev,
+			 "alias %s already exists\n", clk_alias);
+		clk_put(r);
+		return;
+	}
+
+	r = clk_get(NULL, clk_name);
+	if (IS_ERR(r)) {
+		dev_err(&od->pdev->dev,
+			"clk_get for %s failed\n", clk_name);
+		return;
+	}
+
+	l = clkdev_alloc(r, clk_alias, dev_name(&od->pdev->dev));
+	if (!l) {
+		dev_err(&od->pdev->dev,
+			"clkdev_alloc for %s failed\n", clk_alias);
+		return;
+	}
+
+	clkdev_add(l);
+}
+
+/**
+ * _add_hwmod_clocks_clkdev - Add clkdev entry for hwmod optional clocks
+ * and main clock
+ * @od: struct omap_device *od
+ * @oh: struct omap_hwmod *oh
+ *
+ * For the main clock and every optional clock present per hwmod per
+ * omap_device, this function adds an entry in the clkdev table of the
+ * form <dev-id=dev_name, con-id=role> if it does not exist already.
+ *
+ * The function is called from inside omap_device_build_ss(), after
+ * omap_device_register.
+ *
+ * This allows drivers to get a pointer to its optional clocks based on its role
+ * by calling clk_get(<dev*>, <role>).
+ * In the case of the main clock, a "fck" alias is used.
+ *
+ * No return value.
+ */
+static void _add_hwmod_clocks_clkdev(struct omap_device *od,
+				     struct omap_hwmod *oh)
+{
+	int i;
+
+	_add_clkdev(od, "fck", oh->main_clk);
+
+	for (i = 0; i < oh->opt_clks_cnt; i++)
+		_add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk);
+}
+
+
+/**
+ * omap_device_build_from_dt - build an omap_device with multiple hwmods
+ * @pdev_name: name of the platform_device driver to use
+ * @pdev_id: this platform_device's connection ID
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ * @is_early_device: should the device be registered as an early device or not
+ *
+ * Function for building an omap_device already registered from device-tree
+ *
+ * Returns 0 or PTR_ERR() on error.
+ */
+static int omap_device_build_from_dt(struct platform_device *pdev)
+{
+	struct omap_hwmod **hwmods;
+	struct omap_device *od;
+	struct omap_hwmod *oh;
+	struct device_node *node = pdev->dev.of_node;
+	const char *oh_name;
+	int oh_cnt, i, ret = 0;
+
+	oh_cnt = of_property_count_strings(node, "ti,hwmods");
+	if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
+		dev_dbg(&pdev->dev, "No 'hwmods' to build omap_device\n");
+		return -ENODEV;
+	}
+
+	hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+	if (!hwmods) {
+		ret = -ENOMEM;
+		goto odbfd_exit;
+	}
+
+	for (i = 0; i < oh_cnt; i++) {
+		of_property_read_string_index(node, "ti,hwmods", i, &oh_name);
+		oh = omap_hwmod_lookup(oh_name);
+		if (!oh) {
+			dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n",
+				oh_name);
+			ret = -EINVAL;
+			goto odbfd_exit1;
+		}
+		hwmods[i] = oh;
+	}
+
+	od = omap_device_alloc(pdev, hwmods, oh_cnt, NULL, 0);
+	if (!od) {
+		dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
+			oh_name);
+		ret = PTR_ERR(od);
+		goto odbfd_exit1;
+	}
+
+	/* Fix up missing resource names */
+	for (i = 0; i < pdev->num_resources; i++) {
+		struct resource *r = &pdev->resource[i];
+
+		if (r->name == NULL)
+			r->name = dev_name(&pdev->dev);
+	}
+
+	if (of_get_property(node, "ti,no_idle_on_suspend", NULL))
+		omap_device_disable_idle_on_suspend(pdev);
+
+	pdev->dev.pm_domain = &omap_device_pm_domain;
+
+odbfd_exit1:
+	kfree(hwmods);
+odbfd_exit:
+	return ret;
+}
+
+static int _omap_device_notifier_call(struct notifier_block *nb,
+				      unsigned long event, void *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_device *od;
+
+	switch (event) {
+	case BUS_NOTIFY_DEL_DEVICE:
+		if (pdev->archdata.od)
+			omap_device_delete(pdev->archdata.od);
+		break;
+	case BUS_NOTIFY_ADD_DEVICE:
+		if (pdev->dev.of_node)
+			omap_device_build_from_dt(pdev);
+		/* fall through */
+	default:
+		od = to_omap_device(pdev);
+		if (od)
+			od->_driver_status = event;
+	}
+
+	return NOTIFY_DONE;
+}
+
+
+/* Public functions for use by core code */
+
+/**
+ * omap_device_get_context_loss_count - get lost context count
+ * @od: struct omap_device *
+ *
+ * Using the primary hwmod, query the context loss count for this
+ * device.
+ *
+ * Callers should consider context for this device lost any time this
+ * function returns a value different than the value the caller got
+ * the last time it called this function.
+ *
+ * If any hwmods exist for the omap_device assoiated with @pdev,
+ * return the context loss counter for that hwmod, otherwise return
+ * zero.
+ */
+int omap_device_get_context_loss_count(struct platform_device *pdev)
+{
+	struct omap_device *od;
+	u32 ret = 0;
+
+	od = to_omap_device(pdev);
+
+	if (od->hwmods_cnt)
+		ret = omap_hwmod_get_context_loss_count(od->hwmods[0]);
+
+	return ret;
+}
+
+/**
+ * omap_device_count_resources - count number of struct resource entries needed
+ * @od: struct omap_device *
+ *
+ * Count the number of struct resource entries needed for this
+ * omap_device @od.  Used by omap_device_build_ss() to determine how
+ * much memory to allocate before calling
+ * omap_device_fill_resources().  Returns the count.
+ */
+static int omap_device_count_resources(struct omap_device *od)
+{
+	int c = 0;
+	int i;
+
+	for (i = 0; i < od->hwmods_cnt; i++)
+		c += omap_hwmod_count_resources(od->hwmods[i]);
+
+	pr_debug("omap_device: %s: counted %d total resources across %d hwmods\n",
+		 od->pdev->name, c, od->hwmods_cnt);
+
+	return c;
+}
+
+/**
+ * omap_device_fill_resources - fill in array of struct resource
+ * @od: struct omap_device *
+ * @res: pointer to an array of struct resource to be filled in
+ *
+ * Populate one or more empty struct resource pointed to by @res with
+ * the resource data for this omap_device @od.  Used by
+ * omap_device_build_ss() after calling omap_device_count_resources().
+ * Ideally this function would not be needed at all.  If omap_device
+ * replaces platform_device, then we can specify our own
+ * get_resource()/ get_irq()/etc functions that use the underlying
+ * omap_hwmod information.  Or if platform_device is extended to use
+ * subarchitecture-specific function pointers, the various
+ * platform_device functions can simply call omap_device internal
+ * functions to get device resources.  Hacking around the existing
+ * platform_device code wastes memory.  Returns 0.
+ */
+static int omap_device_fill_resources(struct omap_device *od,
+				      struct resource *res)
+{
+	int i, r;
+
+	for (i = 0; i < od->hwmods_cnt; i++) {
+		r = omap_hwmod_fill_resources(od->hwmods[i], res);
+		res += r;
+	}
+
+	return 0;
+}
+
+/**
+ * _od_fill_dma_resources - fill in array of struct resource with dma resources
+ * @od: struct omap_device *
+ * @res: pointer to an array of struct resource to be filled in
+ *
+ * Populate one or more empty struct resource pointed to by @res with
+ * the dma resource data for this omap_device @od.  Used by
+ * omap_device_alloc() after calling omap_device_count_resources().
+ *
+ * Ideally this function would not be needed at all.  If we have
+ * mechanism to get dma resources from DT.
+ *
+ * Returns 0.
+ */
+static int _od_fill_dma_resources(struct omap_device *od,
+				      struct resource *res)
+{
+	int i, r;
+
+	for (i = 0; i < od->hwmods_cnt; i++) {
+		r = omap_hwmod_fill_dma_resources(od->hwmods[i], res);
+		res += r;
+	}
+
+	return 0;
+}
+
+/**
+ * omap_device_alloc - allocate an omap_device
+ * @pdev: platform_device that will be included in this omap_device
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ *
+ * Convenience function for allocating an omap_device structure and filling
+ * hwmods, resources and pm_latency attributes.
+ *
+ * Returns an struct omap_device pointer or ERR_PTR() on error;
+ */
+struct omap_device *omap_device_alloc(struct platform_device *pdev,
+					struct omap_hwmod **ohs, int oh_cnt,
+					struct omap_device_pm_latency *pm_lats,
+					int pm_lats_cnt)
+{
+	int ret = -ENOMEM;
+	struct omap_device *od;
+	struct resource *res = NULL;
+	int i, res_count;
+	struct omap_hwmod **hwmods;
+
+	od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
+	if (!od) {
+		ret = -ENOMEM;
+		goto oda_exit1;
+	}
+	od->hwmods_cnt = oh_cnt;
+
+	hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+	if (!hwmods)
+		goto oda_exit2;
+
+	od->hwmods = hwmods;
+	od->pdev = pdev;
+
+	res_count = omap_device_count_resources(od);
+	/*
+	 * DT Boot:
+	 *   OF framework will construct the resource structure (currently
+	 *   does for MEM & IRQ resource) and we should respect/use these
+	 *   resources, killing hwmod dependency.
+	 *   If pdev->num_resources > 0, we assume that MEM & IRQ resources
+	 *   have been allocated by OF layer already (through DTB).
+	 *
+	 * Non-DT Boot:
+	 *   Here, pdev->num_resources = 0, and we should get all the
+	 *   resources from hwmod.
+	 *
+	 * TODO: Once DMA resource is available from OF layer, we should
+	 *   kill filling any resources from hwmod.
+	 */
+	if (res_count > pdev->num_resources) {
+		/* Allocate resources memory to account for new resources */
+		res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
+		if (!res)
+			goto oda_exit3;
+
+		/*
+		 * If pdev->num_resources > 0, then assume that,
+		 * MEM and IRQ resources will only come from DT and only
+		 * fill DMA resource from hwmod layer.
+		 */
+		if (pdev->num_resources && pdev->resource) {
+			dev_dbg(&pdev->dev, "%s(): resources already allocated %d\n",
+				__func__, res_count);
+			memcpy(res, pdev->resource,
+			       sizeof(struct resource) * pdev->num_resources);
+			_od_fill_dma_resources(od, &res[pdev->num_resources]);
+		} else {
+			dev_dbg(&pdev->dev, "%s(): using resources from hwmod %d\n",
+				__func__, res_count);
+			omap_device_fill_resources(od, res);
+		}
+
+		ret = platform_device_add_resources(pdev, res, res_count);
+		kfree(res);
+
+		if (ret)
+			goto oda_exit3;
+	}
+
+	if (!pm_lats) {
+		pm_lats = omap_default_latency;
+		pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
+	}
+
+	od->pm_lats_cnt = pm_lats_cnt;
+	od->pm_lats = kmemdup(pm_lats,
+			sizeof(struct omap_device_pm_latency) * pm_lats_cnt,
+			GFP_KERNEL);
+	if (!od->pm_lats)
+		goto oda_exit3;
+
+	pdev->archdata.od = od;
+
+	for (i = 0; i < oh_cnt; i++) {
+		hwmods[i]->od = od;
+		_add_hwmod_clocks_clkdev(od, hwmods[i]);
+	}
+
+	return od;
+
+oda_exit3:
+	kfree(hwmods);
+oda_exit2:
+	kfree(od);
+oda_exit1:
+	dev_err(&pdev->dev, "omap_device: build failed (%d)\n", ret);
+
+	return ERR_PTR(ret);
+}
+
+void omap_device_delete(struct omap_device *od)
+{
+	if (!od)
+		return;
+
+	od->pdev->archdata.od = NULL;
+	kfree(od->pm_lats);
+	kfree(od->hwmods);
+	kfree(od);
+}
+
+/**
+ * omap_device_build - build and register an omap_device with one omap_hwmod
+ * @pdev_name: name of the platform_device driver to use
+ * @pdev_id: this platform_device's connection ID
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ * @is_early_device: should the device be registered as an early device or not
+ *
+ * Convenience function for building and registering a single
+ * omap_device record, which in turn builds and registers a
+ * platform_device record.  See omap_device_build_ss() for more
+ * information.  Returns ERR_PTR(-EINVAL) if @oh is NULL; otherwise,
+ * passes along the return value of omap_device_build_ss().
+ */
+struct platform_device __init *omap_device_build(const char *pdev_name, int pdev_id,
+				      struct omap_hwmod *oh, void *pdata,
+				      int pdata_len,
+				      struct omap_device_pm_latency *pm_lats,
+				      int pm_lats_cnt, int is_early_device)
+{
+	struct omap_hwmod *ohs[] = { oh };
+
+	if (!oh)
+		return ERR_PTR(-EINVAL);
+
+	return omap_device_build_ss(pdev_name, pdev_id, ohs, 1, pdata,
+				    pdata_len, pm_lats, pm_lats_cnt,
+				    is_early_device);
+}
+
+/**
+ * omap_device_build_ss - build and register an omap_device with multiple hwmods
+ * @pdev_name: name of the platform_device driver to use
+ * @pdev_id: this platform_device's connection ID
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ * @is_early_device: should the device be registered as an early device or not
+ *
+ * Convenience function for building and registering an omap_device
+ * subsystem record.  Subsystem records consist of multiple
+ * omap_hwmods.  This function in turn builds and registers a
+ * platform_device record.  Returns an ERR_PTR() on error, or passes
+ * along the return value of omap_device_register().
+ */
+struct platform_device __init *omap_device_build_ss(const char *pdev_name, int pdev_id,
+					 struct omap_hwmod **ohs, int oh_cnt,
+					 void *pdata, int pdata_len,
+					 struct omap_device_pm_latency *pm_lats,
+					 int pm_lats_cnt, int is_early_device)
+{
+	int ret = -ENOMEM;
+	struct platform_device *pdev;
+	struct omap_device *od;
+
+	if (!ohs || oh_cnt == 0 || !pdev_name)
+		return ERR_PTR(-EINVAL);
+
+	if (!pdata && pdata_len > 0)
+		return ERR_PTR(-EINVAL);
+
+	pdev = platform_device_alloc(pdev_name, pdev_id);
+	if (!pdev) {
+		ret = -ENOMEM;
+		goto odbs_exit;
+	}
+
+	/* Set the dev_name early to allow dev_xxx in omap_device_alloc */
+	if (pdev->id != -1)
+		dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
+	else
+		dev_set_name(&pdev->dev, "%s", pdev->name);
+
+	od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt);
+	if (IS_ERR(od))
+		goto odbs_exit1;
+
+	ret = platform_device_add_data(pdev, pdata, pdata_len);
+	if (ret)
+		goto odbs_exit2;
+
+	if (is_early_device)
+		ret = omap_early_device_register(pdev);
+	else
+		ret = omap_device_register(pdev);
+	if (ret)
+		goto odbs_exit2;
+
+	return pdev;
+
+odbs_exit2:
+	omap_device_delete(od);
+odbs_exit1:
+	platform_device_put(pdev);
+odbs_exit:
+
+	pr_err("omap_device: %s: build failed (%d)\n", pdev_name, ret);
+
+	return ERR_PTR(ret);
+}
+
+/**
+ * omap_early_device_register - register an omap_device as an early platform
+ * device.
+ * @od: struct omap_device * to register
+ *
+ * Register the omap_device structure.  This currently just calls
+ * platform_early_add_device() on the underlying platform_device.
+ * Returns 0 by default.
+ */
+static int __init omap_early_device_register(struct platform_device *pdev)
+{
+	struct platform_device *devices[1];
+
+	devices[0] = pdev;
+	early_platform_add_devices(devices, 1);
+	return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int _od_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	int ret;
+
+	ret = pm_generic_runtime_suspend(dev);
+
+	if (!ret)
+		omap_device_idle(pdev);
+
+	return ret;
+}
+
+static int _od_runtime_idle(struct device *dev)
+{
+	return pm_generic_runtime_idle(dev);
+}
+
+static int _od_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	omap_device_enable(pdev);
+
+	return pm_generic_runtime_resume(dev);
+}
+#endif
+
+#ifdef CONFIG_SUSPEND
+static int _od_suspend_noirq(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_device *od = to_omap_device(pdev);
+	int ret;
+
+	/* Don't attempt late suspend on a driver that is not bound */
+	if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER)
+		return 0;
+
+	ret = pm_generic_suspend_noirq(dev);
+
+	if (!ret && !pm_runtime_status_suspended(dev)) {
+		if (pm_generic_runtime_suspend(dev) == 0) {
+			if (!(od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND))
+				omap_device_idle(pdev);
+			od->flags |= OMAP_DEVICE_SUSPENDED;
+		}
+	}
+
+	return ret;
+}
+
+static int _od_resume_noirq(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_device *od = to_omap_device(pdev);
+
+	if ((od->flags & OMAP_DEVICE_SUSPENDED) &&
+	    !pm_runtime_status_suspended(dev)) {
+		od->flags &= ~OMAP_DEVICE_SUSPENDED;
+		if (!(od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND))
+			omap_device_enable(pdev);
+		pm_generic_runtime_resume(dev);
+	}
+
+	return pm_generic_resume_noirq(dev);
+}
+#else
+#define _od_suspend_noirq NULL
+#define _od_resume_noirq NULL
+#endif
+
+struct dev_pm_domain omap_device_pm_domain = {
+	.ops = {
+		SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
+				   _od_runtime_idle)
+		USE_PLATFORM_PM_SLEEP_OPS
+		.suspend_noirq = _od_suspend_noirq,
+		.resume_noirq = _od_resume_noirq,
+	}
+};
+
+/**
+ * omap_device_register - register an omap_device with one omap_hwmod
+ * @od: struct omap_device * to register
+ *
+ * Register the omap_device structure.  This currently just calls
+ * platform_device_register() on the underlying platform_device.
+ * Returns the return value of platform_device_register().
+ */
+int omap_device_register(struct platform_device *pdev)
+{
+	pr_debug("omap_device: %s: registering\n", pdev->name);
+
+	pdev->dev.pm_domain = &omap_device_pm_domain;
+	return platform_device_add(pdev);
+}
+
+
+/* Public functions for use by device drivers through struct platform_data */
+
+/**
+ * omap_device_enable - fully activate an omap_device
+ * @od: struct omap_device * to activate
+ *
+ * Do whatever is necessary for the hwmods underlying omap_device @od
+ * to be accessible and ready to operate.  This generally involves
+ * enabling clocks, setting SYSCONFIG registers; and in the future may
+ * involve remuxing pins.  Device drivers should call this function
+ * (through platform_data function pointers) where they would normally
+ * enable clocks, etc.  Returns -EINVAL if called when the omap_device
+ * is already enabled, or passes along the return value of
+ * _omap_device_activate().
+ */
+int omap_device_enable(struct platform_device *pdev)
+{
+	int ret;
+	struct omap_device *od;
+
+	od = to_omap_device(pdev);
+
+	if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
+		dev_warn(&pdev->dev,
+			 "omap_device: %s() called from invalid state %d\n",
+			 __func__, od->_state);
+		return -EINVAL;
+	}
+
+	/* Enable everything if we're enabling this device from scratch */
+	if (od->_state == OMAP_DEVICE_STATE_UNKNOWN)
+		od->pm_lat_level = od->pm_lats_cnt;
+
+	ret = _omap_device_activate(od, IGNORE_WAKEUP_LAT);
+
+	od->dev_wakeup_lat = 0;
+	od->_dev_wakeup_lat_limit = UINT_MAX;
+	od->_state = OMAP_DEVICE_STATE_ENABLED;
+
+	return ret;
+}
+
+/**
+ * omap_device_idle - idle an omap_device
+ * @od: struct omap_device * to idle
+ *
+ * Idle omap_device @od by calling as many .deactivate_func() entries
+ * in the omap_device's pm_lats table as is possible without exceeding
+ * the device's maximum wakeup latency limit, pm_lat_limit.  Device
+ * drivers should call this function (through platform_data function
+ * pointers) where they would normally disable clocks after operations
+ * complete, etc..  Returns -EINVAL if the omap_device is not
+ * currently enabled, or passes along the return value of
+ * _omap_device_deactivate().
+ */
+int omap_device_idle(struct platform_device *pdev)
+{
+	int ret;
+	struct omap_device *od;
+
+	od = to_omap_device(pdev);
+
+	if (od->_state != OMAP_DEVICE_STATE_ENABLED) {
+		dev_warn(&pdev->dev,
+			 "omap_device: %s() called from invalid state %d\n",
+			 __func__, od->_state);
+		return -EINVAL;
+	}
+
+	ret = _omap_device_deactivate(od, USE_WAKEUP_LAT);
+
+	od->_state = OMAP_DEVICE_STATE_IDLE;
+
+	return ret;
+}
+
+/**
+ * omap_device_shutdown - shut down an omap_device
+ * @od: struct omap_device * to shut down
+ *
+ * Shut down omap_device @od by calling all .deactivate_func() entries
+ * in the omap_device's pm_lats table and then shutting down all of
+ * the underlying omap_hwmods.  Used when a device is being "removed"
+ * or a device driver is being unloaded.  Returns -EINVAL if the
+ * omap_device is not currently enabled or idle, or passes along the
+ * return value of _omap_device_deactivate().
+ */
+int omap_device_shutdown(struct platform_device *pdev)
+{
+	int ret, i;
+	struct omap_device *od;
+
+	od = to_omap_device(pdev);
+
+	if (od->_state != OMAP_DEVICE_STATE_ENABLED &&
+	    od->_state != OMAP_DEVICE_STATE_IDLE) {
+		dev_warn(&pdev->dev,
+			 "omap_device: %s() called from invalid state %d\n",
+			 __func__, od->_state);
+		return -EINVAL;
+	}
+
+	ret = _omap_device_deactivate(od, IGNORE_WAKEUP_LAT);
+
+	for (i = 0; i < od->hwmods_cnt; i++)
+		omap_hwmod_shutdown(od->hwmods[i]);
+
+	od->_state = OMAP_DEVICE_STATE_SHUTDOWN;
+
+	return ret;
+}
+
+/**
+ * omap_device_assert_hardreset - set a device's hardreset line
+ * @pdev: struct platform_device * to reset
+ * @name: const char * name of the reset line
+ *
+ * Set the hardreset line identified by @name on the IP blocks
+ * associated with the hwmods backing the platform_device @pdev.  All
+ * of the hwmods associated with @pdev must have the same hardreset
+ * line linked to them for this to work.  Passes along the return value
+ * of omap_hwmod_assert_hardreset() in the event of any failure, or
+ * returns 0 upon success.
+ */
+int omap_device_assert_hardreset(struct platform_device *pdev, const char *name)
+{
+	struct omap_device *od = to_omap_device(pdev);
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < od->hwmods_cnt; i++) {
+		ret = omap_hwmod_assert_hardreset(od->hwmods[i], name);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+/**
+ * omap_device_deassert_hardreset - release a device's hardreset line
+ * @pdev: struct platform_device * to reset
+ * @name: const char * name of the reset line
+ *
+ * Release the hardreset line identified by @name on the IP blocks
+ * associated with the hwmods backing the platform_device @pdev.  All
+ * of the hwmods associated with @pdev must have the same hardreset
+ * line linked to them for this to work.  Passes along the return
+ * value of omap_hwmod_deassert_hardreset() in the event of any
+ * failure, or returns 0 upon success.
+ */
+int omap_device_deassert_hardreset(struct platform_device *pdev,
+				   const char *name)
+{
+	struct omap_device *od = to_omap_device(pdev);
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < od->hwmods_cnt; i++) {
+		ret = omap_hwmod_deassert_hardreset(od->hwmods[i], name);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+/**
+ * omap_device_align_pm_lat - activate/deactivate device to match wakeup lat lim
+ * @od: struct omap_device *
+ *
+ * When a device's maximum wakeup latency limit changes, call some of
+ * the .activate_func or .deactivate_func function pointers in the
+ * omap_device's pm_lats array to ensure that the device's maximum
+ * wakeup latency is less than or equal to the new latency limit.
+ * Intended to be called by OMAP PM code whenever a device's maximum
+ * wakeup latency limit changes (e.g., via
+ * omap_pm_set_dev_wakeup_lat()).  Returns 0 if nothing needs to be
+ * done (e.g., if the omap_device is not currently idle, or if the
+ * wakeup latency is already current with the new limit) or passes
+ * along the return value of _omap_device_deactivate() or
+ * _omap_device_activate().
+ */
+int omap_device_align_pm_lat(struct platform_device *pdev,
+			     u32 new_wakeup_lat_limit)
+{
+	int ret = -EINVAL;
+	struct omap_device *od;
+
+	od = to_omap_device(pdev);
+
+	if (new_wakeup_lat_limit == od->dev_wakeup_lat)
+		return 0;
+
+	od->_dev_wakeup_lat_limit = new_wakeup_lat_limit;
+
+	if (od->_state != OMAP_DEVICE_STATE_IDLE)
+		return 0;
+	else if (new_wakeup_lat_limit > od->dev_wakeup_lat)
+		ret = _omap_device_deactivate(od, USE_WAKEUP_LAT);
+	else if (new_wakeup_lat_limit < od->dev_wakeup_lat)
+		ret = _omap_device_activate(od, USE_WAKEUP_LAT);
+
+	return ret;
+}
+
+/**
+ * omap_device_get_pwrdm - return the powerdomain * associated with @od
+ * @od: struct omap_device *
+ *
+ * Return the powerdomain associated with the first underlying
+ * omap_hwmod for this omap_device.  Intended for use by core OMAP PM
+ * code.  Returns NULL on error or a struct powerdomain * upon
+ * success.
+ */
+struct powerdomain *omap_device_get_pwrdm(struct omap_device *od)
+{
+	/*
+	 * XXX Assumes that all omap_hwmod powerdomains are identical.
+	 * This may not necessarily be true.  There should be a sanity
+	 * check in here to WARN() if any difference appears.
+	 */
+	if (!od->hwmods_cnt)
+		return NULL;
+
+	return omap_hwmod_get_pwrdm(od->hwmods[0]);
+}
+
+/**
+ * omap_device_get_mpu_rt_va - return the MPU's virtual addr for the hwmod base
+ * @od: struct omap_device *
+ *
+ * Return the MPU's virtual address for the base of the hwmod, from
+ * the ioremap() that the hwmod code does.  Only valid if there is one
+ * hwmod associated with this device.  Returns NULL if there are zero
+ * or more than one hwmods associated with this omap_device;
+ * otherwise, passes along the return value from
+ * omap_hwmod_get_mpu_rt_va().
+ */
+void __iomem *omap_device_get_rt_va(struct omap_device *od)
+{
+	if (od->hwmods_cnt != 1)
+		return NULL;
+
+	return omap_hwmod_get_mpu_rt_va(od->hwmods[0]);
+}
+
+/**
+ * omap_device_get_by_hwmod_name() - convert a hwmod name to
+ * device pointer.
+ * @oh_name: name of the hwmod device
+ *
+ * Returns back a struct device * pointer associated with a hwmod
+ * device represented by a hwmod_name
+ */
+struct device *omap_device_get_by_hwmod_name(const char *oh_name)
+{
+	struct omap_hwmod *oh;
+
+	if (!oh_name) {
+		WARN(1, "%s: no hwmod name!\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (IS_ERR_OR_NULL(oh)) {
+		WARN(1, "%s: no hwmod for %s\n", __func__,
+			oh_name);
+		return ERR_PTR(oh ? PTR_ERR(oh) : -ENODEV);
+	}
+	if (IS_ERR_OR_NULL(oh->od)) {
+		WARN(1, "%s: no omap_device for %s\n", __func__,
+			oh_name);
+		return ERR_PTR(oh->od ? PTR_ERR(oh->od) : -ENODEV);
+	}
+
+	if (IS_ERR_OR_NULL(oh->od->pdev))
+		return ERR_PTR(oh->od->pdev ? PTR_ERR(oh->od->pdev) : -ENODEV);
+
+	return &oh->od->pdev->dev;
+}
+EXPORT_SYMBOL(omap_device_get_by_hwmod_name);
+
+/*
+ * Public functions intended for use in omap_device_pm_latency
+ * .activate_func and .deactivate_func function pointers
+ */
+
+/**
+ * omap_device_enable_hwmods - call omap_hwmod_enable() on all hwmods
+ * @od: struct omap_device *od
+ *
+ * Enable all underlying hwmods.  Returns 0.
+ */
+int omap_device_enable_hwmods(struct omap_device *od)
+{
+	int i;
+
+	for (i = 0; i < od->hwmods_cnt; i++)
+		omap_hwmod_enable(od->hwmods[i]);
+
+	/* XXX pass along return value here? */
+	return 0;
+}
+
+/**
+ * omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods
+ * @od: struct omap_device *od
+ *
+ * Idle all underlying hwmods.  Returns 0.
+ */
+int omap_device_idle_hwmods(struct omap_device *od)
+{
+	int i;
+
+	for (i = 0; i < od->hwmods_cnt; i++)
+		omap_hwmod_idle(od->hwmods[i]);
+
+	/* XXX pass along return value here? */
+	return 0;
+}
+
+/**
+ * omap_device_disable_clocks - disable all main and interface clocks
+ * @od: struct omap_device *od
+ *
+ * Disable the main functional clock and interface clock for all of the
+ * omap_hwmods associated with the omap_device.  Returns 0.
+ */
+int omap_device_disable_clocks(struct omap_device *od)
+{
+	int i;
+
+	for (i = 0; i < od->hwmods_cnt; i++)
+		omap_hwmod_disable_clocks(od->hwmods[i]);
+
+	/* XXX pass along return value here? */
+	return 0;
+}
+
+/**
+ * omap_device_enable_clocks - enable all main and interface clocks
+ * @od: struct omap_device *od
+ *
+ * Enable the main functional clock and interface clock for all of the
+ * omap_hwmods associated with the omap_device.  Returns 0.
+ */
+int omap_device_enable_clocks(struct omap_device *od)
+{
+	int i;
+
+	for (i = 0; i < od->hwmods_cnt; i++)
+		omap_hwmod_enable_clocks(od->hwmods[i]);
+
+	/* XXX pass along return value here? */
+	return 0;
+}
+
+static struct notifier_block platform_nb = {
+	.notifier_call = _omap_device_notifier_call,
+};
+
+static int __init omap_device_init(void)
+{
+	bus_register_notifier(&platform_bus_type, &platform_nb);
+	return 0;
+}
+core_initcall(omap_device_init);
+
+/**
+ * omap_device_late_idle - idle devices without drivers
+ * @dev: struct device * associated with omap_device
+ * @data: unused
+ *
+ * Check the driver bound status of this device, and idle it
+ * if there is no driver attached.
+ */
+static int __init omap_device_late_idle(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_device *od = to_omap_device(pdev);
+
+	if (!od)
+		return 0;
+
+	/*
+	 * If omap_device state is enabled, but has no driver bound,
+	 * idle it.
+	 */
+	if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
+		if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
+			dev_warn(dev, "%s: enabled but no driver.  Idling\n",
+				 __func__);
+			omap_device_idle(pdev);
+		}
+	}
+
+	return 0;
+}
+
+static int __init omap_device_late_init(void)
+{
+	bus_for_each_dev(&platform_bus_type, NULL, NULL, omap_device_late_idle);
+	return 0;
+}
+late_initcall(omap_device_late_init);
diff --git a/arch/arm/mach-omap2/omap_device.h b/arch/arm/mach-omap2/omap_device.h
new file mode 100644
index 0000000..0933c59
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_device.h
@@ -0,0 +1,176 @@
+/*
+ * omap_device headers
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Paul Walmsley
+ *
+ * Developed in collaboration with (alphabetical order): Benoit
+ * Cousson, Kevin Hilman, Tony Lindgren, Rajendra Nayak, Vikram
+ * Pandita, Sakari Poussa, Anand Sawant, Santosh Shilimkar, Richard
+ * Woodruff
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Eventually this type of functionality should either be
+ * a) implemented via arch-specific pointers in platform_device
+ * or
+ * b) implemented as a proper omap_bus/omap_device in Linux, no more
+ *    platform_device
+ *
+ * omap_device differs from omap_hwmod in that it includes external
+ * (e.g., board- and system-level) integration details.  omap_hwmod
+ * stores hardware data that is invariant for a given OMAP chip.
+ *
+ * To do:
+ * - GPIO integration
+ * - regulator integration
+ *
+ */
+#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_DEVICE_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_DEVICE_H
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include "omap_hwmod.h"
+
+extern struct dev_pm_domain omap_device_pm_domain;
+
+/* omap_device._state values */
+#define OMAP_DEVICE_STATE_UNKNOWN	0
+#define OMAP_DEVICE_STATE_ENABLED	1
+#define OMAP_DEVICE_STATE_IDLE		2
+#define OMAP_DEVICE_STATE_SHUTDOWN	3
+
+/* omap_device.flags values */
+#define OMAP_DEVICE_SUSPENDED BIT(0)
+#define OMAP_DEVICE_NO_IDLE_ON_SUSPEND BIT(1)
+
+/**
+ * struct omap_device - omap_device wrapper for platform_devices
+ * @pdev: platform_device
+ * @hwmods: (one .. many per omap_device)
+ * @hwmods_cnt: ARRAY_SIZE() of @hwmods
+ * @pm_lats: ptr to an omap_device_pm_latency table
+ * @pm_lats_cnt: ARRAY_SIZE() of what is passed to @pm_lats
+ * @pm_lat_level: array index of the last odpl entry executed - -1 if never
+ * @dev_wakeup_lat: dev wakeup latency in nanoseconds
+ * @_dev_wakeup_lat_limit: dev wakeup latency limit in nsec - set by OMAP PM
+ * @_state: one of OMAP_DEVICE_STATE_* (see above)
+ * @flags: device flags
+ * @_driver_status: one of BUS_NOTIFY_*_DRIVER from <linux/device.h>
+ *
+ * Integrates omap_hwmod data into Linux platform_device.
+ *
+ * Field names beginning with underscores are for the internal use of
+ * the omap_device code.
+ *
+ */
+struct omap_device {
+	struct platform_device		*pdev;
+	struct omap_hwmod		**hwmods;
+	struct omap_device_pm_latency	*pm_lats;
+	u32				dev_wakeup_lat;
+	u32				_dev_wakeup_lat_limit;
+	unsigned long			_driver_status;
+	u8				pm_lats_cnt;
+	s8				pm_lat_level;
+	u8				hwmods_cnt;
+	u8				_state;
+	u8                              flags;
+};
+
+/* Device driver interface (call via platform_data fn ptrs) */
+
+int omap_device_enable(struct platform_device *pdev);
+int omap_device_idle(struct platform_device *pdev);
+int omap_device_shutdown(struct platform_device *pdev);
+
+/* Core code interface */
+
+struct platform_device *omap_device_build(const char *pdev_name, int pdev_id,
+				      struct omap_hwmod *oh, void *pdata,
+				      int pdata_len,
+				      struct omap_device_pm_latency *pm_lats,
+				      int pm_lats_cnt, int is_early_device);
+
+struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
+					 struct omap_hwmod **oh, int oh_cnt,
+					 void *pdata, int pdata_len,
+					 struct omap_device_pm_latency *pm_lats,
+					 int pm_lats_cnt, int is_early_device);
+
+struct omap_device *omap_device_alloc(struct platform_device *pdev,
+				      struct omap_hwmod **ohs, int oh_cnt,
+				      struct omap_device_pm_latency *pm_lats,
+				      int pm_lats_cnt);
+void omap_device_delete(struct omap_device *od);
+int omap_device_register(struct platform_device *pdev);
+
+void __iomem *omap_device_get_rt_va(struct omap_device *od);
+struct device *omap_device_get_by_hwmod_name(const char *oh_name);
+
+/* OMAP PM interface */
+int omap_device_align_pm_lat(struct platform_device *pdev,
+			     u32 new_wakeup_lat_limit);
+struct powerdomain *omap_device_get_pwrdm(struct omap_device *od);
+int omap_device_get_context_loss_count(struct platform_device *pdev);
+
+/* Other */
+
+int omap_device_assert_hardreset(struct platform_device *pdev,
+				 const char *name);
+int omap_device_deassert_hardreset(struct platform_device *pdev,
+				 const char *name);
+int omap_device_idle_hwmods(struct omap_device *od);
+int omap_device_enable_hwmods(struct omap_device *od);
+
+int omap_device_disable_clocks(struct omap_device *od);
+int omap_device_enable_clocks(struct omap_device *od);
+
+/*
+ * Entries should be kept in latency order ascending
+ *
+ * deact_lat is the maximum number of microseconds required to complete
+ * deactivate_func() at the device's slowest OPP.
+ *
+ * act_lat is the maximum number of microseconds required to complete
+ * activate_func() at the device's slowest OPP.
+ *
+ * This will result in some suboptimal power management decisions at fast
+ * OPPs, but avoids having to recompute all device power management decisions
+ * if the system shifts from a fast OPP to a slow OPP (in order to meet
+ * latency requirements).
+ *
+ * XXX should deactivate_func/activate_func() take platform_device pointers
+ * rather than omap_device pointers?
+ */
+struct omap_device_pm_latency {
+	u32 deactivate_lat;
+	u32 deactivate_lat_worst;
+	int (*deactivate_func)(struct omap_device *od);
+	u32 activate_lat;
+	u32 activate_lat_worst;
+	int (*activate_func)(struct omap_device *od);
+	u32 flags;
+};
+
+#define OMAP_DEVICE_LATENCY_AUTO_ADJUST BIT(1)
+
+/* Get omap_device pointer from platform_device pointer */
+static inline struct omap_device *to_omap_device(struct platform_device *pdev)
+{
+	return pdev ? pdev->archdata.od : NULL;
+}
+
+static inline
+void omap_device_disable_idle_on_suspend(struct platform_device *pdev)
+{
+	struct omap_device *od = to_omap_device(pdev);
+
+	od->flags |= OMAP_DEVICE_NO_IDLE_ON_SUSPEND;
+}
+
+#endif
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 87cc6d0..3f3bf32 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -130,7 +130,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/io.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/list.h>
@@ -139,27 +139,25 @@
 #include <linux/slab.h>
 #include <linux/bootmem.h>
 
-#include <plat/clock.h>
-#include <plat/omap_hwmod.h>
-#include <plat/prcm.h>
+#include "clock.h"
+#include "omap_hwmod.h"
 
 #include "soc.h"
 #include "common.h"
 #include "clockdomain.h"
 #include "powerdomain.h"
-#include "cm2xxx_3xxx.h"
+#include "cm2xxx.h"
+#include "cm3xxx.h"
 #include "cminst44xx.h"
 #include "cm33xx.h"
-#include "prm2xxx_3xxx.h"
+#include "prm.h"
+#include "prm3xxx.h"
 #include "prm44xx.h"
 #include "prm33xx.h"
 #include "prminst44xx.h"
 #include "mux.h"
 #include "pm.h"
 
-/* Maximum microseconds to wait for OMAP module to softreset */
-#define MAX_MODULE_SOFTRESET_WAIT	10000
-
 /* Name of the OMAP hwmod for the MPU */
 #define MPU_INITIATOR_NAME		"mpu"
 
@@ -648,6 +646,19 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
 	return 0;
 }
 
+static struct clockdomain *_get_clkdm(struct omap_hwmod *oh)
+{
+	struct clk_hw_omap *clk;
+
+	if (oh->clkdm) {
+		return oh->clkdm;
+	} else if (oh->_clk) {
+		clk = to_clk_hw_omap(__clk_get_hw(oh->_clk));
+		return  clk->clkdm;
+	}
+	return NULL;
+}
+
 /**
  * _add_initiator_dep: prevent @oh from smart-idling while @init_oh is active
  * @oh: struct omap_hwmod *
@@ -663,13 +674,18 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
  */
 static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
 {
-	if (!oh->_clk)
+	struct clockdomain *clkdm, *init_clkdm;
+
+	clkdm = _get_clkdm(oh);
+	init_clkdm = _get_clkdm(init_oh);
+
+	if (!clkdm || !init_clkdm)
 		return -EINVAL;
 
-	if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS)
+	if (clkdm && clkdm->flags & CLKDM_NO_AUTODEPS)
 		return 0;
 
-	return clkdm_add_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
+	return clkdm_add_sleepdep(clkdm, init_clkdm);
 }
 
 /**
@@ -687,13 +703,18 @@ static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
  */
 static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
 {
-	if (!oh->_clk)
+	struct clockdomain *clkdm, *init_clkdm;
+
+	clkdm = _get_clkdm(oh);
+	init_clkdm = _get_clkdm(init_oh);
+
+	if (!clkdm || !init_clkdm)
 		return -EINVAL;
 
-	if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS)
+	if (clkdm && clkdm->flags & CLKDM_NO_AUTODEPS)
 		return 0;
 
-	return clkdm_del_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
+	return clkdm_del_sleepdep(clkdm, init_clkdm);
 }
 
 /**
@@ -727,7 +748,7 @@ static int _init_main_clk(struct omap_hwmod *oh)
 	 */
 	clk_prepare(oh->_clk);
 
-	if (!oh->_clk->clkdm)
+	if (!_get_clkdm(oh))
 		pr_debug("omap_hwmod: %s: missing clockdomain for %s.\n",
 			   oh->name, oh->main_clk);
 
@@ -1310,6 +1331,7 @@ static void _enable_sysc(struct omap_hwmod *oh)
 	u8 idlemode, sf;
 	u32 v;
 	bool clkdm_act;
+	struct clockdomain *clkdm;
 
 	if (!oh->class->sysc)
 		return;
@@ -1329,11 +1351,9 @@ static void _enable_sysc(struct omap_hwmod *oh)
 	v = oh->_sysc_cache;
 	sf = oh->class->sysc->sysc_flags;
 
+	clkdm = _get_clkdm(oh);
 	if (sf & SYSC_HAS_SIDLEMODE) {
-		clkdm_act = ((oh->clkdm &&
-			      oh->clkdm->flags & CLKDM_ACTIVE_WITH_MPU) ||
-			     (oh->_clk && oh->_clk->clkdm &&
-			      oh->_clk->clkdm->flags & CLKDM_ACTIVE_WITH_MPU));
+		clkdm_act = (clkdm && clkdm->flags & CLKDM_ACTIVE_WITH_MPU);
 		if (clkdm_act && !(oh->class->sysc->idlemodes &
 				   (SIDLE_SMART | SIDLE_SMART_WKUP)))
 			idlemode = HWMOD_IDLEMODE_FORCE;
@@ -1535,11 +1555,12 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)
 
 	pr_debug("omap_hwmod: %s: looking up clocks\n", oh->name);
 
+	if (soc_ops.init_clkdm)
+		ret |= soc_ops.init_clkdm(oh);
+
 	ret |= _init_main_clk(oh);
 	ret |= _init_interface_clks(oh);
 	ret |= _init_opt_clks(oh);
-	if (soc_ops.init_clkdm)
-		ret |= soc_ops.init_clkdm(oh);
 
 	if (!ret)
 		oh->_state = _HWMOD_STATE_CLKS_INITED;
@@ -2095,7 +2116,8 @@ static int _enable(struct omap_hwmod *oh)
 			_enable_sysc(oh);
 		}
 	} else {
-		_omap4_disable_module(oh);
+		if (soc_ops.disable_module)
+			soc_ops.disable_module(oh);
 		_disable_clocks(oh);
 		pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
 			 oh->name, r);
@@ -2703,7 +2725,34 @@ static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois)
 /* Static functions intended only for use in soc_ops field function pointers */
 
 /**
- * _omap2_wait_target_ready - wait for a module to leave slave idle
+ * _omap2xxx_wait_target_ready - wait for a module to leave slave idle
+ * @oh: struct omap_hwmod *
+ *
+ * Wait for a module @oh to leave slave idle.  Returns 0 if the module
+ * does not have an IDLEST bit or if the module successfully leaves
+ * slave idle; otherwise, pass along the return value of the
+ * appropriate *_cm*_wait_module_ready() function.
+ */
+static int _omap2xxx_wait_target_ready(struct omap_hwmod *oh)
+{
+	if (!oh)
+		return -EINVAL;
+
+	if (oh->flags & HWMOD_NO_IDLEST)
+		return 0;
+
+	if (!_find_mpu_rt_port(oh))
+		return 0;
+
+	/* XXX check module SIDLEMODE, hardreset status, enabled clocks */
+
+	return omap2xxx_cm_wait_module_ready(oh->prcm.omap2.module_offs,
+					     oh->prcm.omap2.idlest_reg_id,
+					     oh->prcm.omap2.idlest_idle_bit);
+}
+
+/**
+ * _omap3xxx_wait_target_ready - wait for a module to leave slave idle
  * @oh: struct omap_hwmod *
  *
  * Wait for a module @oh to leave slave idle.  Returns 0 if the module
@@ -2711,7 +2760,7 @@ static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois)
  * slave idle; otherwise, pass along the return value of the
  * appropriate *_cm*_wait_module_ready() function.
  */
-static int _omap2_wait_target_ready(struct omap_hwmod *oh)
+static int _omap3xxx_wait_target_ready(struct omap_hwmod *oh)
 {
 	if (!oh)
 		return -EINVAL;
@@ -2724,9 +2773,9 @@ static int _omap2_wait_target_ready(struct omap_hwmod *oh)
 
 	/* XXX check module SIDLEMODE, hardreset status, enabled clocks */
 
-	return omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs,
-					  oh->prcm.omap2.idlest_reg_id,
-					  oh->prcm.omap2.idlest_idle_bit);
+	return omap3xxx_cm_wait_module_ready(oh->prcm.omap2.module_offs,
+					     oh->prcm.omap2.idlest_reg_id,
+					     oh->prcm.omap2.idlest_idle_bit);
 }
 
 /**
@@ -3565,10 +3614,15 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh)
 {
 	struct clk *c;
 	struct omap_hwmod_ocp_if *oi;
+	struct clockdomain *clkdm;
+	struct clk_hw_omap *clk;
 
 	if (!oh)
 		return NULL;
 
+	if (oh->clkdm)
+		return oh->clkdm->pwrdm.ptr;
+
 	if (oh->_clk) {
 		c = oh->_clk;
 	} else {
@@ -3578,11 +3632,12 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh)
 		c = oi->_clk;
 	}
 
-	if (!c->clkdm)
+	clk = to_clk_hw_omap(__clk_get_hw(c));
+	clkdm = clk->clkdm;
+	if (!clkdm)
 		return NULL;
 
-	return c->clkdm->pwrdm.ptr;
-
+	return clkdm->pwrdm.ptr;
 }
 
 /**
@@ -3994,8 +4049,13 @@ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx)
  */
 void __init omap_hwmod_init(void)
 {
-	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-		soc_ops.wait_target_ready = _omap2_wait_target_ready;
+	if (cpu_is_omap24xx()) {
+		soc_ops.wait_target_ready = _omap2xxx_wait_target_ready;
+		soc_ops.assert_hardreset = _omap2_assert_hardreset;
+		soc_ops.deassert_hardreset = _omap2_deassert_hardreset;
+		soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted;
+	} else if (cpu_is_omap34xx()) {
+		soc_ops.wait_target_ready = _omap3xxx_wait_target_ready;
 		soc_ops.assert_hardreset = _omap2_assert_hardreset;
 		soc_ops.deassert_hardreset = _omap2_deassert_hardreset;
 		soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted;
diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h
new file mode 100644
index 0000000..87a3c5b
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod.h
@@ -0,0 +1,681 @@
+/*
+ * omap_hwmod macros, structures
+ *
+ * Copyright (C) 2009-2011 Nokia Corporation
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Paul Walmsley
+ *
+ * Created in collaboration with (alphabetical order): Benoît Cousson,
+ * Kevin Hilman, Tony Lindgren, Rajendra Nayak, Vikram Pandita, Sakari
+ * Poussa, Anand Sawant, Santosh Shilimkar, Richard Woodruff
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * These headers and macros are used to define OMAP on-chip module
+ * data and their integration with other OMAP modules and Linux.
+ * Copious documentation and references can also be found in the
+ * omap_hwmod code, in arch/arm/mach-omap2/omap_hwmod.c (as of this
+ * writing).
+ *
+ * To do:
+ * - add interconnect error log structures
+ * - add pinmuxing
+ * - init_conn_id_bit (CONNID_BIT_VECTOR)
+ * - implement default hwmod SMS/SDRC flags?
+ * - move Linux-specific data ("non-ROM data") out
+ *
+ */
+#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/ioport.h>
+#include <linux/spinlock.h>
+
+struct omap_device;
+
+extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type1;
+extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
+extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type3;
+
+/*
+ * OCP SYSCONFIG bit shifts/masks TYPE1. These are for IPs compliant
+ * with the original PRCM protocol defined for OMAP2420
+ */
+#define SYSC_TYPE1_MIDLEMODE_SHIFT	12
+#define SYSC_TYPE1_MIDLEMODE_MASK	(0x3 << SYSC_TYPE1_MIDLEMODE_SHIFT)
+#define SYSC_TYPE1_CLOCKACTIVITY_SHIFT	8
+#define SYSC_TYPE1_CLOCKACTIVITY_MASK	(0x3 << SYSC_TYPE1_CLOCKACTIVITY_SHIFT)
+#define SYSC_TYPE1_SIDLEMODE_SHIFT	3
+#define SYSC_TYPE1_SIDLEMODE_MASK	(0x3 << SYSC_TYPE1_SIDLEMODE_SHIFT)
+#define SYSC_TYPE1_ENAWAKEUP_SHIFT	2
+#define SYSC_TYPE1_ENAWAKEUP_MASK	(1 << SYSC_TYPE1_ENAWAKEUP_SHIFT)
+#define SYSC_TYPE1_SOFTRESET_SHIFT	1
+#define SYSC_TYPE1_SOFTRESET_MASK	(1 << SYSC_TYPE1_SOFTRESET_SHIFT)
+#define SYSC_TYPE1_AUTOIDLE_SHIFT	0
+#define SYSC_TYPE1_AUTOIDLE_MASK	(1 << SYSC_TYPE1_AUTOIDLE_SHIFT)
+
+/*
+ * OCP SYSCONFIG bit shifts/masks TYPE2. These are for IPs compliant
+ * with the new PRCM protocol defined for new OMAP4 IPs.
+ */
+#define SYSC_TYPE2_SOFTRESET_SHIFT	0
+#define SYSC_TYPE2_SOFTRESET_MASK	(1 << SYSC_TYPE2_SOFTRESET_SHIFT)
+#define SYSC_TYPE2_SIDLEMODE_SHIFT	2
+#define SYSC_TYPE2_SIDLEMODE_MASK	(0x3 << SYSC_TYPE2_SIDLEMODE_SHIFT)
+#define SYSC_TYPE2_MIDLEMODE_SHIFT	4
+#define SYSC_TYPE2_MIDLEMODE_MASK	(0x3 << SYSC_TYPE2_MIDLEMODE_SHIFT)
+#define SYSC_TYPE2_DMADISABLE_SHIFT	16
+#define SYSC_TYPE2_DMADISABLE_MASK	(0x1 << SYSC_TYPE2_DMADISABLE_SHIFT)
+
+/*
+ * OCP SYSCONFIG bit shifts/masks TYPE3.
+ * This is applicable for some IPs present in AM33XX
+ */
+#define SYSC_TYPE3_SIDLEMODE_SHIFT	0
+#define SYSC_TYPE3_SIDLEMODE_MASK	(0x3 << SYSC_TYPE3_SIDLEMODE_SHIFT)
+#define SYSC_TYPE3_MIDLEMODE_SHIFT	2
+#define SYSC_TYPE3_MIDLEMODE_MASK	(0x3 << SYSC_TYPE3_MIDLEMODE_SHIFT)
+
+/* OCP SYSSTATUS bit shifts/masks */
+#define SYSS_RESETDONE_SHIFT		0
+#define SYSS_RESETDONE_MASK		(1 << SYSS_RESETDONE_SHIFT)
+
+/* Master standby/slave idle mode flags */
+#define HWMOD_IDLEMODE_FORCE		(1 << 0)
+#define HWMOD_IDLEMODE_NO		(1 << 1)
+#define HWMOD_IDLEMODE_SMART		(1 << 2)
+#define HWMOD_IDLEMODE_SMART_WKUP	(1 << 3)
+
+/* modulemode control type (SW or HW) */
+#define MODULEMODE_HWCTRL		1
+#define MODULEMODE_SWCTRL		2
+
+
+/**
+ * struct omap_hwmod_mux_info - hwmod specific mux configuration
+ * @pads:              array of omap_device_pad entries
+ * @nr_pads:           number of omap_device_pad entries
+ *
+ * Note that this is currently built during init as needed.
+ */
+struct omap_hwmod_mux_info {
+	int				nr_pads;
+	struct omap_device_pad		*pads;
+	int				nr_pads_dynamic;
+	struct omap_device_pad		**pads_dynamic;
+	int				*irqs;
+	bool				enabled;
+};
+
+/**
+ * struct omap_hwmod_irq_info - MPU IRQs used by the hwmod
+ * @name: name of the IRQ channel (module local name)
+ * @irq: IRQ channel ID (should be non-negative except -1 = terminator)
+ *
+ * @name should be something short, e.g., "tx" or "rx".  It is for use
+ * by platform_get_resource_byname().  It is defined locally to the
+ * hwmod.
+ */
+struct omap_hwmod_irq_info {
+	const char	*name;
+	s16		irq;
+};
+
+/**
+ * struct omap_hwmod_dma_info - DMA channels used by the hwmod
+ * @name: name of the DMA channel (module local name)
+ * @dma_req: DMA request ID (should be non-negative except -1 = terminator)
+ *
+ * @name should be something short, e.g., "tx" or "rx".  It is for use
+ * by platform_get_resource_byname().  It is defined locally to the
+ * hwmod.
+ */
+struct omap_hwmod_dma_info {
+	const char	*name;
+	s16		dma_req;
+};
+
+/**
+ * struct omap_hwmod_rst_info - IPs reset lines use by hwmod
+ * @name: name of the reset line (module local name)
+ * @rst_shift: Offset of the reset bit
+ * @st_shift: Offset of the reset status bit (OMAP2/3 only)
+ *
+ * @name should be something short, e.g., "cpu0" or "rst". It is defined
+ * locally to the hwmod.
+ */
+struct omap_hwmod_rst_info {
+	const char	*name;
+	u8		rst_shift;
+	u8		st_shift;
+};
+
+/**
+ * struct omap_hwmod_opt_clk - optional clocks used by this hwmod
+ * @role: "sys", "32k", "tv", etc -- for use in clk_get()
+ * @clk: opt clock: OMAP clock name
+ * @_clk: pointer to the struct clk (filled in at runtime)
+ *
+ * The module's interface clock and main functional clock should not
+ * be added as optional clocks.
+ */
+struct omap_hwmod_opt_clk {
+	const char	*role;
+	const char	*clk;
+	struct clk	*_clk;
+};
+
+
+/* omap_hwmod_omap2_firewall.flags bits */
+#define OMAP_FIREWALL_L3		(1 << 0)
+#define OMAP_FIREWALL_L4		(1 << 1)
+
+/**
+ * struct omap_hwmod_omap2_firewall - OMAP2/3 device firewall data
+ * @l3_perm_bit: bit shift for L3_PM_*_PERMISSION_*
+ * @l4_fw_region: L4 firewall region ID
+ * @l4_prot_group: L4 protection group ID
+ * @flags: (see omap_hwmod_omap2_firewall.flags macros above)
+ */
+struct omap_hwmod_omap2_firewall {
+	u8 l3_perm_bit;
+	u8 l4_fw_region;
+	u8 l4_prot_group;
+	u8 flags;
+};
+
+
+/*
+ * omap_hwmod_addr_space.flags bits
+ *
+ * ADDR_MAP_ON_INIT: Map this address space during omap_hwmod init.
+ * ADDR_TYPE_RT: Address space contains module register target data.
+ */
+#define ADDR_MAP_ON_INIT	(1 << 0)	/* XXX does not belong */
+#define ADDR_TYPE_RT		(1 << 1)
+
+/**
+ * struct omap_hwmod_addr_space - address space handled by the hwmod
+ * @name: name of the address space
+ * @pa_start: starting physical address
+ * @pa_end: ending physical address
+ * @flags: (see omap_hwmod_addr_space.flags macros above)
+ *
+ * Address space doesn't necessarily follow physical interconnect
+ * structure.  GPMC is one example.
+ */
+struct omap_hwmod_addr_space {
+	const char *name;
+	u32 pa_start;
+	u32 pa_end;
+	u8 flags;
+};
+
+
+/*
+ * omap_hwmod_ocp_if.user bits: these indicate the initiators that use this
+ * interface to interact with the hwmod.  Used to add sleep dependencies
+ * when the module is enabled or disabled.
+ */
+#define OCP_USER_MPU			(1 << 0)
+#define OCP_USER_SDMA			(1 << 1)
+#define OCP_USER_DSP			(1 << 2)
+#define OCP_USER_IVA			(1 << 3)
+
+/* omap_hwmod_ocp_if.flags bits */
+#define OCPIF_SWSUP_IDLE		(1 << 0)
+#define OCPIF_CAN_BURST			(1 << 1)
+
+/* omap_hwmod_ocp_if._int_flags possibilities */
+#define _OCPIF_INT_FLAGS_REGISTERED	(1 << 0)
+
+
+/**
+ * struct omap_hwmod_ocp_if - OCP interface data
+ * @master: struct omap_hwmod that initiates OCP transactions on this link
+ * @slave: struct omap_hwmod that responds to OCP transactions on this link
+ * @addr: address space associated with this link
+ * @clk: interface clock: OMAP clock name
+ * @_clk: pointer to the interface struct clk (filled in at runtime)
+ * @fw: interface firewall data
+ * @width: OCP data width
+ * @user: initiators using this interface (see OCP_USER_* macros above)
+ * @flags: OCP interface flags (see OCPIF_* macros above)
+ * @_int_flags: internal flags (see _OCPIF_INT_FLAGS* macros above)
+ *
+ * It may also be useful to add a tag_cnt field for OCP2.x devices.
+ *
+ * Parameter names beginning with an underscore are managed internally by
+ * the omap_hwmod code and should not be set during initialization.
+ */
+struct omap_hwmod_ocp_if {
+	struct omap_hwmod		*master;
+	struct omap_hwmod		*slave;
+	struct omap_hwmod_addr_space	*addr;
+	const char			*clk;
+	struct clk			*_clk;
+	union {
+		struct omap_hwmod_omap2_firewall omap2;
+	}				fw;
+	u8				width;
+	u8				user;
+	u8				flags;
+	u8				_int_flags;
+};
+
+
+/* Macros for use in struct omap_hwmod_sysconfig */
+
+/* Flags for use in omap_hwmod_sysconfig.idlemodes */
+#define MASTER_STANDBY_SHIFT	4
+#define SLAVE_IDLE_SHIFT	0
+#define SIDLE_FORCE		(HWMOD_IDLEMODE_FORCE << SLAVE_IDLE_SHIFT)
+#define SIDLE_NO		(HWMOD_IDLEMODE_NO << SLAVE_IDLE_SHIFT)
+#define SIDLE_SMART		(HWMOD_IDLEMODE_SMART << SLAVE_IDLE_SHIFT)
+#define SIDLE_SMART_WKUP	(HWMOD_IDLEMODE_SMART_WKUP << SLAVE_IDLE_SHIFT)
+#define MSTANDBY_FORCE		(HWMOD_IDLEMODE_FORCE << MASTER_STANDBY_SHIFT)
+#define MSTANDBY_NO		(HWMOD_IDLEMODE_NO << MASTER_STANDBY_SHIFT)
+#define MSTANDBY_SMART		(HWMOD_IDLEMODE_SMART << MASTER_STANDBY_SHIFT)
+#define MSTANDBY_SMART_WKUP	(HWMOD_IDLEMODE_SMART_WKUP << MASTER_STANDBY_SHIFT)
+
+/* omap_hwmod_sysconfig.sysc_flags capability flags */
+#define SYSC_HAS_AUTOIDLE	(1 << 0)
+#define SYSC_HAS_SOFTRESET	(1 << 1)
+#define SYSC_HAS_ENAWAKEUP	(1 << 2)
+#define SYSC_HAS_EMUFREE	(1 << 3)
+#define SYSC_HAS_CLOCKACTIVITY	(1 << 4)
+#define SYSC_HAS_SIDLEMODE	(1 << 5)
+#define SYSC_HAS_MIDLEMODE	(1 << 6)
+#define SYSS_HAS_RESET_STATUS	(1 << 7)
+#define SYSC_NO_CACHE		(1 << 8)  /* XXX SW flag, belongs elsewhere */
+#define SYSC_HAS_RESET_STATUS	(1 << 9)
+#define SYSC_HAS_DMADISABLE	(1 << 10)
+
+/* omap_hwmod_sysconfig.clockact flags */
+#define CLOCKACT_TEST_BOTH	0x0
+#define CLOCKACT_TEST_MAIN	0x1
+#define CLOCKACT_TEST_ICLK	0x2
+#define CLOCKACT_TEST_NONE	0x3
+
+/**
+ * struct omap_hwmod_sysc_fields - hwmod OCP_SYSCONFIG register field offsets.
+ * @midle_shift: Offset of the midle bit
+ * @clkact_shift: Offset of the clockactivity bit
+ * @sidle_shift: Offset of the sidle bit
+ * @enwkup_shift: Offset of the enawakeup bit
+ * @srst_shift: Offset of the softreset bit
+ * @autoidle_shift: Offset of the autoidle bit
+ * @dmadisable_shift: Offset of the dmadisable bit
+ */
+struct omap_hwmod_sysc_fields {
+	u8 midle_shift;
+	u8 clkact_shift;
+	u8 sidle_shift;
+	u8 enwkup_shift;
+	u8 srst_shift;
+	u8 autoidle_shift;
+	u8 dmadisable_shift;
+};
+
+/**
+ * struct omap_hwmod_class_sysconfig - hwmod class OCP_SYS* data
+ * @rev_offs: IP block revision register offset (from module base addr)
+ * @sysc_offs: OCP_SYSCONFIG register offset (from module base addr)
+ * @syss_offs: OCP_SYSSTATUS register offset (from module base addr)
+ * @srst_udelay: Delay needed after doing a softreset in usecs
+ * @idlemodes: One or more of {SIDLE,MSTANDBY}_{OFF,FORCE,SMART}
+ * @sysc_flags: SYS{C,S}_HAS* flags indicating SYSCONFIG bits supported
+ * @clockact: the default value of the module CLOCKACTIVITY bits
+ *
+ * @clockact describes to the module which clocks are likely to be
+ * disabled when the PRCM issues its idle request to the module.  Some
+ * modules have separate clockdomains for the interface clock and main
+ * functional clock, and can check whether they should acknowledge the
+ * idle request based on the internal module functionality that has
+ * been associated with the clocks marked in @clockact.  This field is
+ * only used if HWMOD_SET_DEFAULT_CLOCKACT is set (see below)
+ *
+ * @sysc_fields: structure containing the offset positions of various bits in
+ * SYSCONFIG register. This can be populated using omap_hwmod_sysc_type1 or
+ * omap_hwmod_sysc_type2 defined in omap_hwmod_common_data.c depending on
+ * whether the device ip is compliant with the original PRCM protocol
+ * defined for OMAP2420 or the new PRCM protocol for new OMAP4 IPs.
+ * If the device follows a different scheme for the sysconfig register ,
+ * then this field has to be populated with the correct offset structure.
+ */
+struct omap_hwmod_class_sysconfig {
+	u32 rev_offs;
+	u32 sysc_offs;
+	u32 syss_offs;
+	u16 sysc_flags;
+	struct omap_hwmod_sysc_fields *sysc_fields;
+	u8 srst_udelay;
+	u8 idlemodes;
+	u8 clockact;
+};
+
+/**
+ * struct omap_hwmod_omap2_prcm - OMAP2/3-specific PRCM data
+ * @module_offs: PRCM submodule offset from the start of the PRM/CM
+ * @prcm_reg_id: PRCM register ID (e.g., 3 for CM_AUTOIDLE3)
+ * @module_bit: register bit shift for AUTOIDLE, WKST, WKEN, GRPSEL regs
+ * @idlest_reg_id: IDLEST register ID (e.g., 3 for CM_IDLEST3)
+ * @idlest_idle_bit: register bit shift for CM_IDLEST slave idle bit
+ * @idlest_stdby_bit: register bit shift for CM_IDLEST master standby bit
+ *
+ * @prcm_reg_id and @module_bit are specific to the AUTOIDLE, WKST,
+ * WKEN, GRPSEL registers.  In an ideal world, no extra information
+ * would be needed for IDLEST information, but alas, there are some
+ * exceptions, so @idlest_reg_id, @idlest_idle_bit, @idlest_stdby_bit
+ * are needed for the IDLEST registers (c.f. 2430 I2CHS, 3430 USBHOST)
+ */
+struct omap_hwmod_omap2_prcm {
+	s16 module_offs;
+	u8 prcm_reg_id;
+	u8 module_bit;
+	u8 idlest_reg_id;
+	u8 idlest_idle_bit;
+	u8 idlest_stdby_bit;
+};
+
+/*
+ * Possible values for struct omap_hwmod_omap4_prcm.flags
+ *
+ * HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT: Some IP blocks don't have a PRCM
+ *     module-level context loss register associated with them; this
+ *     flag bit should be set in those cases
+ */
+#define HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT		(1 << 0)
+
+/**
+ * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
+ * @clkctrl_reg: PRCM address of the clock control register
+ * @rstctrl_reg: address of the XXX_RSTCTRL register located in the PRM
+ * @lostcontext_mask: bitmask for selecting bits from RM_*_CONTEXT register
+ * @rstst_reg: (AM33XX only) address of the XXX_RSTST register in the PRM
+ * @submodule_wkdep_bit: bit shift of the WKDEP range
+ * @flags: PRCM register capabilities for this IP block
+ *
+ * If @lostcontext_mask is not defined, context loss check code uses
+ * whole register without masking. @lostcontext_mask should only be
+ * defined in cases where @context_offs register is shared by two or
+ * more hwmods.
+ */
+struct omap_hwmod_omap4_prcm {
+	u16		clkctrl_offs;
+	u16		rstctrl_offs;
+	u16		rstst_offs;
+	u16		context_offs;
+	u32		lostcontext_mask;
+	u8		submodule_wkdep_bit;
+	u8		modulemode;
+	u8		flags;
+};
+
+
+/*
+ * omap_hwmod.flags definitions
+ *
+ * HWMOD_SWSUP_SIDLE: omap_hwmod code should manually bring module in and out
+ *     of idle, rather than relying on module smart-idle
+ * HWMOD_SWSUP_MSTDBY: omap_hwmod code should manually bring module in and out
+ *     of standby, rather than relying on module smart-standby
+ * HWMOD_INIT_NO_RESET: don't reset this module at boot - important for
+ *     SDRAM controller, etc. XXX probably belongs outside the main hwmod file
+ *     XXX Should be HWMOD_SETUP_NO_RESET
+ * HWMOD_INIT_NO_IDLE: don't idle this module at boot - important for SDRAM
+ *     controller, etc. XXX probably belongs outside the main hwmod file
+ *     XXX Should be HWMOD_SETUP_NO_IDLE
+ * HWMOD_NO_OCP_AUTOIDLE: disable module autoidle (OCP_SYSCONFIG.AUTOIDLE)
+ *     when module is enabled, rather than the default, which is to
+ *     enable autoidle
+ * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup
+ * HWMOD_NO_IDLEST: this module does not have idle status - this is the case
+ *     only for few initiator modules on OMAP2 & 3.
+ * HWMOD_CONTROL_OPT_CLKS_IN_RESET: Enable all optional clocks during reset.
+ *     This is needed for devices like DSS that require optional clocks enabled
+ *     in order to complete the reset. Optional clocks will be disabled
+ *     again after the reset.
+ * HWMOD_16BIT_REG: Module has 16bit registers
+ * HWMOD_EXT_OPT_MAIN_CLK: The only main functional clock source for
+ *     this IP block comes from an off-chip source and is not always
+ *     enabled.  This prevents the hwmod code from being able to
+ *     enable and reset the IP block early.  XXX Eventually it should
+ *     be possible to query the clock framework for this information.
+ */
+#define HWMOD_SWSUP_SIDLE			(1 << 0)
+#define HWMOD_SWSUP_MSTANDBY			(1 << 1)
+#define HWMOD_INIT_NO_RESET			(1 << 2)
+#define HWMOD_INIT_NO_IDLE			(1 << 3)
+#define HWMOD_NO_OCP_AUTOIDLE			(1 << 4)
+#define HWMOD_SET_DEFAULT_CLOCKACT		(1 << 5)
+#define HWMOD_NO_IDLEST				(1 << 6)
+#define HWMOD_CONTROL_OPT_CLKS_IN_RESET		(1 << 7)
+#define HWMOD_16BIT_REG				(1 << 8)
+#define HWMOD_EXT_OPT_MAIN_CLK			(1 << 9)
+
+/*
+ * omap_hwmod._int_flags definitions
+ * These are for internal use only and are managed by the omap_hwmod code.
+ *
+ * _HWMOD_NO_MPU_PORT: no path exists for the MPU to write to this module
+ * _HWMOD_WAKEUP_ENABLED: set when the omap_hwmod code has enabled ENAWAKEUP
+ * _HWMOD_SYSCONFIG_LOADED: set when the OCP_SYSCONFIG value has been cached
+ * _HWMOD_SKIP_ENABLE: set if hwmod enabled during init (HWMOD_INIT_NO_IDLE) -
+ *     causes the first call to _enable() to only update the pinmux
+ */
+#define _HWMOD_NO_MPU_PORT			(1 << 0)
+#define _HWMOD_WAKEUP_ENABLED			(1 << 1)
+#define _HWMOD_SYSCONFIG_LOADED			(1 << 2)
+#define _HWMOD_SKIP_ENABLE			(1 << 3)
+
+/*
+ * omap_hwmod._state definitions
+ *
+ * INITIALIZED: reset (optionally), initialized, enabled, disabled
+ *              (optionally)
+ *
+ *
+ */
+#define _HWMOD_STATE_UNKNOWN			0
+#define _HWMOD_STATE_REGISTERED			1
+#define _HWMOD_STATE_CLKS_INITED		2
+#define _HWMOD_STATE_INITIALIZED		3
+#define _HWMOD_STATE_ENABLED			4
+#define _HWMOD_STATE_IDLE			5
+#define _HWMOD_STATE_DISABLED			6
+
+/**
+ * struct omap_hwmod_class - the type of an IP block
+ * @name: name of the hwmod_class
+ * @sysc: device SYSCONFIG/SYSSTATUS register data
+ * @rev: revision of the IP class
+ * @pre_shutdown: ptr to fn to be executed immediately prior to device shutdown
+ * @reset: ptr to fn to be executed in place of the standard hwmod reset fn
+ *
+ * Represent the class of a OMAP hardware "modules" (e.g. timer,
+ * smartreflex, gpio, uart...)
+ *
+ * @pre_shutdown is a function that will be run immediately before
+ * hwmod clocks are disabled, etc.  It is intended for use for hwmods
+ * like the MPU watchdog, which cannot be disabled with the standard
+ * omap_hwmod_shutdown().  The function should return 0 upon success,
+ * or some negative error upon failure.  Returning an error will cause
+ * omap_hwmod_shutdown() to abort the device shutdown and return an
+ * error.
+ *
+ * If @reset is defined, then the function it points to will be
+ * executed in place of the standard hwmod _reset() code in
+ * mach-omap2/omap_hwmod.c.  This is needed for IP blocks which have
+ * unusual reset sequences - usually processor IP blocks like the IVA.
+ */
+struct omap_hwmod_class {
+	const char				*name;
+	struct omap_hwmod_class_sysconfig	*sysc;
+	u32					rev;
+	int					(*pre_shutdown)(struct omap_hwmod *oh);
+	int					(*reset)(struct omap_hwmod *oh);
+};
+
+/**
+ * struct omap_hwmod_link - internal structure linking hwmods with ocp_ifs
+ * @ocp_if: OCP interface structure record pointer
+ * @node: list_head pointing to next struct omap_hwmod_link in a list
+ */
+struct omap_hwmod_link {
+	struct omap_hwmod_ocp_if	*ocp_if;
+	struct list_head		node;
+};
+
+/**
+ * struct omap_hwmod - integration data for OMAP hardware "modules" (IP blocks)
+ * @name: name of the hwmod
+ * @class: struct omap_hwmod_class * to the class of this hwmod
+ * @od: struct omap_device currently associated with this hwmod (internal use)
+ * @mpu_irqs: ptr to an array of MPU IRQs
+ * @sdma_reqs: ptr to an array of System DMA request IDs
+ * @prcm: PRCM data pertaining to this hwmod
+ * @main_clk: main clock: OMAP clock name
+ * @_clk: pointer to the main struct clk (filled in at runtime)
+ * @opt_clks: other device clocks that drivers can request (0..*)
+ * @voltdm: pointer to voltage domain (filled in at runtime)
+ * @dev_attr: arbitrary device attributes that can be passed to the driver
+ * @_sysc_cache: internal-use hwmod flags
+ * @_mpu_rt_va: cached register target start address (internal use)
+ * @_mpu_port: cached MPU register target slave (internal use)
+ * @opt_clks_cnt: number of @opt_clks
+ * @master_cnt: number of @master entries
+ * @slaves_cnt: number of @slave entries
+ * @response_lat: device OCP response latency (in interface clock cycles)
+ * @_int_flags: internal-use hwmod flags
+ * @_state: internal-use hwmod state
+ * @_postsetup_state: internal-use state to leave the hwmod in after _setup()
+ * @flags: hwmod flags (documented below)
+ * @_lock: spinlock serializing operations on this hwmod
+ * @node: list node for hwmod list (internal use)
+ *
+ * @main_clk refers to this module's "main clock," which for our
+ * purposes is defined as "the functional clock needed for register
+ * accesses to complete."  Modules may not have a main clock if the
+ * interface clock also serves as a main clock.
+ *
+ * Parameter names beginning with an underscore are managed internally by
+ * the omap_hwmod code and should not be set during initialization.
+ *
+ * @masters and @slaves are now deprecated.
+ */
+struct omap_hwmod {
+	const char			*name;
+	struct omap_hwmod_class		*class;
+	struct omap_device		*od;
+	struct omap_hwmod_mux_info	*mux;
+	struct omap_hwmod_irq_info	*mpu_irqs;
+	struct omap_hwmod_dma_info	*sdma_reqs;
+	struct omap_hwmod_rst_info	*rst_lines;
+	union {
+		struct omap_hwmod_omap2_prcm omap2;
+		struct omap_hwmod_omap4_prcm omap4;
+	}				prcm;
+	const char			*main_clk;
+	struct clk			*_clk;
+	struct omap_hwmod_opt_clk	*opt_clks;
+	char				*clkdm_name;
+	struct clockdomain		*clkdm;
+	struct list_head		master_ports; /* connect to *_IA */
+	struct list_head		slave_ports; /* connect to *_TA */
+	void				*dev_attr;
+	u32				_sysc_cache;
+	void __iomem			*_mpu_rt_va;
+	spinlock_t			_lock;
+	struct list_head		node;
+	struct omap_hwmod_ocp_if	*_mpu_port;
+	u16				flags;
+	u8				response_lat;
+	u8				rst_lines_cnt;
+	u8				opt_clks_cnt;
+	u8				masters_cnt;
+	u8				slaves_cnt;
+	u8				hwmods_cnt;
+	u8				_int_flags;
+	u8				_state;
+	u8				_postsetup_state;
+};
+
+struct omap_hwmod *omap_hwmod_lookup(const char *name);
+int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
+			void *data);
+
+int __init omap_hwmod_setup_one(const char *name);
+
+int omap_hwmod_enable(struct omap_hwmod *oh);
+int omap_hwmod_idle(struct omap_hwmod *oh);
+int omap_hwmod_shutdown(struct omap_hwmod *oh);
+
+int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name);
+int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name);
+int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name);
+
+int omap_hwmod_enable_clocks(struct omap_hwmod *oh);
+int omap_hwmod_disable_clocks(struct omap_hwmod *oh);
+
+int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode);
+int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle);
+
+int omap_hwmod_reset(struct omap_hwmod *oh);
+void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
+
+void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs);
+u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs);
+int omap_hwmod_softreset(struct omap_hwmod *oh);
+
+int omap_hwmod_count_resources(struct omap_hwmod *oh);
+int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
+int omap_hwmod_fill_dma_resources(struct omap_hwmod *oh, struct resource *res);
+int omap_hwmod_get_resource_byname(struct omap_hwmod *oh, unsigned int type,
+				   const char *name, struct resource *res);
+
+struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh);
+void __iomem *omap_hwmod_get_mpu_rt_va(struct omap_hwmod *oh);
+
+int omap_hwmod_add_initiator_dep(struct omap_hwmod *oh,
+				 struct omap_hwmod *init_oh);
+int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh,
+				 struct omap_hwmod *init_oh);
+
+int omap_hwmod_enable_wakeup(struct omap_hwmod *oh);
+int omap_hwmod_disable_wakeup(struct omap_hwmod *oh);
+
+int omap_hwmod_for_each_by_class(const char *classname,
+				 int (*fn)(struct omap_hwmod *oh,
+					   void *user),
+				 void *user);
+
+int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);
+int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
+
+int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
+
+int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx);
+
+extern void __init omap_hwmod_init(void);
+
+const char *omap_hwmod_get_main_clk(struct omap_hwmod *oh);
+
+/*
+ * Chip variant-specific hwmod init routines - XXX should be converted
+ * to use initcalls once the initial boot ordering is straightened out
+ */
+extern int omap2420_hwmod_init(void);
+extern int omap2430_hwmod_init(void);
+extern int omap3xxx_hwmod_init(void);
+extern int omap44xx_hwmod_init(void);
+extern int am33xx_hwmod_init(void);
+
+extern int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois);
+
+#endif
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index b5db600..a8b3368 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -12,21 +12,24 @@
  * XXX handle crossbar/shared link difference for L3?
  * XXX these should be marked initdata for multi-OMAP kernels
  */
+
+#include <linux/i2c-omap.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
-#include <plat/omap_hwmod.h>
-#include <plat/dma.h>
-#include <plat/serial.h>
-#include <plat/i2c.h>
+#include <plat-omap/dma-omap.h>
 #include <plat/dmtimer.h>
+
+#include "omap_hwmod.h"
 #include "l3_2xxx.h"
 #include "l4_2xxx.h"
-#include <plat/mmc.h>
 
 #include "omap_hwmod_common_data.h"
 
 #include "cm-regbits-24xx.h"
 #include "prm-regbits-24xx.h"
+#include "i2c.h"
+#include "mmc.h"
+#include "serial.h"
 #include "wd_timer.h"
 
 /*
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index c455e41..c2eaefc 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -12,21 +12,23 @@
  * XXX handle crossbar/shared link difference for L3?
  * XXX these should be marked initdata for multi-OMAP kernels
  */
+
+#include <linux/i2c-omap.h>
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
-#include <plat/omap_hwmod.h>
-#include <plat/dma.h>
-#include <plat/serial.h>
-#include <plat/i2c.h>
+#include <plat-omap/dma-omap.h>
 #include <plat/dmtimer.h>
-#include <plat/mmc.h>
+
+#include "omap_hwmod.h"
+#include "mmc.h"
 #include "l3_2xxx.h"
 
 #include "soc.h"
 #include "omap_hwmod_common_data.h"
 #include "prm-regbits-24xx.h"
 #include "cm-regbits-24xx.h"
+#include "i2c.h"
 #include "wd_timer.h"
 
 /*
@@ -76,8 +78,7 @@ static struct omap_hwmod_class i2c_class = {
 
 static struct omap_i2c_dev_attr i2c_dev_attr = {
 	.fifo_depth	= 8, /* bytes */
-	.flags		= OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
-			  OMAP_I2C_FLAG_BUS_SHIFT_2 |
+	.flags		= OMAP_I2C_FLAG_BUS_SHIFT_2 |
 			  OMAP_I2C_FLAG_FORCE_19200_INT_CLK,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
index cbb4ef6..0413dab 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
@@ -13,8 +13,7 @@
  */
 #include <asm/sizes.h>
 
-#include <plat/omap_hwmod.h>
-#include <plat/serial.h>
+#include "omap_hwmod.h"
 
 #include "omap_hwmod_common_data.h"
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
index 8851bbb..40d6c93 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
@@ -9,13 +9,14 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <plat/omap_hwmod.h>
-#include <plat/serial.h>
-#include <plat/dma.h>
-#include <plat/common.h>
+
+#include <plat-omap/dma-omap.h>
+
+#include "omap_hwmod.h"
 #include "hdq1w.h"
 
 #include "omap_hwmod_common_data.h"
+#include "dma.h"
 
 /* UART */
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
index 1a1287d..47901a5 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
@@ -13,10 +13,10 @@
  */
 #include <asm/sizes.h>
 
-#include <plat/omap_hwmod.h>
-#include <plat/serial.h>
+#include "omap_hwmod.h"
 #include "l3_2xxx.h"
 #include "l4_2xxx.h"
+#include "serial.h"
 
 #include "omap_hwmod_common_data.h"
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
index bd9220e..0db8f45 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -8,13 +8,13 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <plat/omap_hwmod.h>
-#include <plat/serial.h>
+
 #include <linux/platform_data/gpio-omap.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 #include <plat/dmtimer.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
+#include "omap_hwmod.h"
 #include "omap_hwmod_common_data.h"
 #include "cm-regbits-24xx.h"
 #include "prm-regbits-24xx.h"
@@ -58,8 +58,9 @@ static struct omap_hwmod_class_sysconfig omap2xxx_timer_sysc = {
 	.syss_offs	= 0x0014,
 	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
 			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.clockact       = CLOCKACT_TEST_ICLK,
 	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 
@@ -268,6 +269,7 @@ struct omap_hwmod omap2xxx_timer1_hwmod = {
 	},
 	.dev_attr	= &capability_alwon_dev_attr,
 	.class		= &omap2xxx_timer_hwmod_class,
+	.flags          = HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer2 */
@@ -286,6 +288,7 @@ struct omap_hwmod omap2xxx_timer2_hwmod = {
 		},
 	},
 	.class		= &omap2xxx_timer_hwmod_class,
+	.flags          = HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer3 */
@@ -304,6 +307,7 @@ struct omap_hwmod omap2xxx_timer3_hwmod = {
 		},
 	},
 	.class		= &omap2xxx_timer_hwmod_class,
+	.flags          = HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer4 */
@@ -322,6 +326,7 @@ struct omap_hwmod omap2xxx_timer4_hwmod = {
 		},
 	},
 	.class		= &omap2xxx_timer_hwmod_class,
+	.flags          = HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer5 */
@@ -341,6 +346,7 @@ struct omap_hwmod omap2xxx_timer5_hwmod = {
 	},
 	.dev_attr	= &capability_dsp_dev_attr,
 	.class		= &omap2xxx_timer_hwmod_class,
+	.flags          = HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer6 */
@@ -360,6 +366,7 @@ struct omap_hwmod omap2xxx_timer6_hwmod = {
 	},
 	.dev_attr	= &capability_dsp_dev_attr,
 	.class		= &omap2xxx_timer_hwmod_class,
+	.flags          = HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer7 */
@@ -379,6 +386,7 @@ struct omap_hwmod omap2xxx_timer7_hwmod = {
 	},
 	.dev_attr	= &capability_dsp_dev_attr,
 	.class		= &omap2xxx_timer_hwmod_class,
+	.flags          = HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer8 */
@@ -398,6 +406,7 @@ struct omap_hwmod omap2xxx_timer8_hwmod = {
 	},
 	.dev_attr	= &capability_dsp_dev_attr,
 	.class		= &omap2xxx_timer_hwmod_class,
+	.flags          = HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer9 */
@@ -417,6 +426,7 @@ struct omap_hwmod omap2xxx_timer9_hwmod = {
 	},
 	.dev_attr	= &capability_pwm_dev_attr,
 	.class		= &omap2xxx_timer_hwmod_class,
+	.flags          = HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer10 */
@@ -436,6 +446,7 @@ struct omap_hwmod omap2xxx_timer10_hwmod = {
 	},
 	.dev_attr	= &capability_pwm_dev_attr,
 	.class		= &omap2xxx_timer_hwmod_class,
+	.flags          = HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer11 */
@@ -455,6 +466,7 @@ struct omap_hwmod omap2xxx_timer11_hwmod = {
 	},
 	.dev_attr	= &capability_pwm_dev_attr,
 	.class		= &omap2xxx_timer_hwmod_class,
+	.flags          = HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer12 */
@@ -474,6 +486,7 @@ struct omap_hwmod omap2xxx_timer12_hwmod = {
 	},
 	.dev_attr	= &capability_pwm_dev_attr,
 	.class		= &omap2xxx_timer_hwmod_class,
+	.flags          = HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* wd_timer2 */
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
index 59d5c1c..32820d8 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
@@ -14,13 +14,11 @@
  * GNU General Public License for more details.
  */
 
-#include <plat/omap_hwmod.h>
-#include <plat/cpu.h>
+#include <linux/i2c-omap.h>
+
+#include "omap_hwmod.h"
 #include <linux/platform_data/gpio-omap.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
-#include <plat/dma.h>
-#include <plat/mmc.h>
-#include <plat/i2c.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -28,6 +26,8 @@
 #include "cm33xx.h"
 #include "prm33xx.h"
 #include "prm-regbits-33xx.h"
+#include "i2c.h"
+#include "mmc.h"
 
 /*
  * IP blocks
@@ -674,6 +674,7 @@ 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),
 	.mpu_irqs	= am33xx_cpgmac0_irqs,
 	.main_clk	= "cpsw_125mhz_gclk",
 	.prcm		= {
@@ -685,6 +686,20 @@ static struct omap_hwmod am33xx_cpgmac0_hwmod = {
 };
 
 /*
+ * 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 = {
@@ -2501,6 +2516,21 @@ static struct omap_hwmod_ocp_if am33xx_l4_hs__cpgmac0 = {
 	.user		= OCP_USER_MPU,
 };
 
+struct omap_hwmod_addr_space am33xx_mdio_addr_space[] = {
+	{
+		.pa_start	= 0x4A101000,
+		.pa_end		= 0x4A101000 + SZ_256 - 1,
+	},
+	{ }
+};
+
+struct omap_hwmod_ocp_if am33xx_cpgmac0__mdio = {
+	.master		= &am33xx_cpgmac0_hwmod,
+	.slave		= &am33xx_mdio_hwmod,
+	.addr		= am33xx_mdio_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
 static struct omap_hwmod_addr_space am33xx_elm_addr_space[] = {
 	{
 		.pa_start	= 0x48080000,
@@ -3371,6 +3401,7 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
 	&am33xx_l3_main__tptc2,
 	&am33xx_l3_s__usbss,
 	&am33xx_l4_hs__cpgmac0,
+	&am33xx_cpgmac0__mdio,
 	NULL,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index f67b7ee..34ef3d8 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -14,16 +14,14 @@
  *
  * XXX these should be marked initdata for multi-OMAP kernels
  */
+
+#include <linux/i2c-omap.h>
 #include <linux/power/smartreflex.h>
 #include <linux/platform_data/gpio-omap.h>
 
-#include <plat/omap_hwmod.h>
-#include <plat/dma.h>
-#include <plat/serial.h>
+#include <plat-omap/dma-omap.h>
 #include "l3_3xxx.h"
 #include "l4_3xxx.h"
-#include <plat/i2c.h>
-#include <plat/mmc.h>
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <plat/dmtimer.h>
@@ -32,10 +30,16 @@
 #include "am35xx.h"
 
 #include "soc.h"
+#include "omap_hwmod.h"
 #include "omap_hwmod_common_data.h"
 #include "prm-regbits-34xx.h"
 #include "cm-regbits-34xx.h"
+
+#include "dma.h"
+#include "i2c.h"
+#include "mmc.h"
 #include "wd_timer.h"
+#include "serial.h"
 
 /*
  * OMAP3xxx hardware module integration data
@@ -149,29 +153,16 @@ static struct omap_hwmod omap3xxx_debugss_hwmod = {
 };
 
 /* timer class */
-static struct omap_hwmod_class_sysconfig omap3xxx_timer_1ms_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
-				SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-				SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class omap3xxx_timer_1ms_hwmod_class = {
-	.name = "timer",
-	.sysc = &omap3xxx_timer_1ms_sysc,
-};
-
 static struct omap_hwmod_class_sysconfig omap3xxx_timer_sysc = {
 	.rev_offs	= 0x0000,
 	.sysc_offs	= 0x0010,
 	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP |
-			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.clockact	= CLOCKACT_TEST_ICLK,
 	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 
@@ -220,7 +211,8 @@ static struct omap_hwmod omap3xxx_timer1_hwmod = {
 		},
 	},
 	.dev_attr	= &capability_alwon_dev_attr,
-	.class		= &omap3xxx_timer_1ms_hwmod_class,
+	.class		= &omap3xxx_timer_hwmod_class,
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer2 */
@@ -237,7 +229,8 @@ static struct omap_hwmod omap3xxx_timer2_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT2_SHIFT,
 		},
 	},
-	.class		= &omap3xxx_timer_1ms_hwmod_class,
+	.class		= &omap3xxx_timer_hwmod_class,
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer3 */
@@ -255,6 +248,7 @@ static struct omap_hwmod omap3xxx_timer3_hwmod = {
 		},
 	},
 	.class		= &omap3xxx_timer_hwmod_class,
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer4 */
@@ -272,6 +266,7 @@ static struct omap_hwmod omap3xxx_timer4_hwmod = {
 		},
 	},
 	.class		= &omap3xxx_timer_hwmod_class,
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer5 */
@@ -290,6 +285,7 @@ static struct omap_hwmod omap3xxx_timer5_hwmod = {
 	},
 	.dev_attr	= &capability_dsp_dev_attr,
 	.class		= &omap3xxx_timer_hwmod_class,
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer6 */
@@ -308,6 +304,7 @@ static struct omap_hwmod omap3xxx_timer6_hwmod = {
 	},
 	.dev_attr	= &capability_dsp_dev_attr,
 	.class		= &omap3xxx_timer_hwmod_class,
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer7 */
@@ -326,6 +323,7 @@ static struct omap_hwmod omap3xxx_timer7_hwmod = {
 	},
 	.dev_attr	= &capability_dsp_dev_attr,
 	.class		= &omap3xxx_timer_hwmod_class,
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer8 */
@@ -344,6 +342,7 @@ static struct omap_hwmod omap3xxx_timer8_hwmod = {
 	},
 	.dev_attr	= &capability_dsp_pwm_dev_attr,
 	.class		= &omap3xxx_timer_hwmod_class,
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer9 */
@@ -362,6 +361,7 @@ static struct omap_hwmod omap3xxx_timer9_hwmod = {
 	},
 	.dev_attr	= &capability_pwm_dev_attr,
 	.class		= &omap3xxx_timer_hwmod_class,
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer10 */
@@ -379,7 +379,8 @@ static struct omap_hwmod omap3xxx_timer10_hwmod = {
 		},
 	},
 	.dev_attr	= &capability_pwm_dev_attr,
-	.class		= &omap3xxx_timer_1ms_hwmod_class,
+	.class		= &omap3xxx_timer_hwmod_class,
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer11 */
@@ -398,6 +399,7 @@ static struct omap_hwmod omap3xxx_timer11_hwmod = {
 	},
 	.dev_attr	= &capability_pwm_dev_attr,
 	.class		= &omap3xxx_timer_hwmod_class,
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /* timer12 */
@@ -421,6 +423,7 @@ static struct omap_hwmod omap3xxx_timer12_hwmod = {
 	},
 	.dev_attr	= &capability_secure_dev_attr,
 	.class		= &omap3xxx_timer_hwmod_class,
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
 /*
@@ -791,8 +794,7 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
 /* I2C1 */
 static struct omap_i2c_dev_attr i2c1_dev_attr = {
 	.fifo_depth	= 8, /* bytes */
-	.flags		= OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
-			  OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
+	.flags		= OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
 			  OMAP_I2C_FLAG_BUS_SHIFT_2,
 };
 
@@ -818,8 +820,7 @@ static struct omap_hwmod omap3xxx_i2c1_hwmod = {
 /* I2C2 */
 static struct omap_i2c_dev_attr i2c2_dev_attr = {
 	.fifo_depth	= 8, /* bytes */
-	.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
-		 OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
+	.flags = OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
 		 OMAP_I2C_FLAG_BUS_SHIFT_2,
 };
 
@@ -845,8 +846,7 @@ static struct omap_hwmod omap3xxx_i2c2_hwmod = {
 /* I2C3 */
 static struct omap_i2c_dev_attr i2c3_dev_attr = {
 	.fifo_depth	= 64, /* bytes */
-	.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
-		 OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
+	.flags = OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
 		 OMAP_I2C_FLAG_BUS_SHIFT_2,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 0b1249e..e5eda55 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -21,23 +21,25 @@
 #include <linux/io.h>
 #include <linux/platform_data/gpio-omap.h>
 #include <linux/power/smartreflex.h>
+#include <linux/i2c-omap.h>
 #include <linux/platform_data/omap_ocp2scp.h>
 
-#include <plat/omap_hwmod.h>
-#include <plat/i2c.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
+
+#include <linux/platform_data/omap_ocp2scp.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/platform_data/asoc-ti-mcbsp.h>
-#include <plat/mmc.h>
 #include <plat/dmtimer.h>
-#include <plat/common.h>
 #include <plat/iommu.h>
 
+#include "omap_hwmod.h"
 #include "omap_hwmod_common_data.h"
 #include "cm1_44xx.h"
 #include "cm2_44xx.h"
 #include "prm44xx.h"
 #include "prm-regbits-44xx.h"
+#include "i2c.h"
+#include "mmc.h"
 #include "wd_timer.h"
 
 /* Base offset for all OMAP4 interrupts external to MPUSS */
@@ -3102,6 +3104,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_timer_1ms_sysc = {
 			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
 			   SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.clockact	= CLOCKACT_TEST_ICLK,
 	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 
@@ -3155,6 +3158,7 @@ static struct omap_hwmod omap44xx_timer1_hwmod = {
 	.name		= "timer1",
 	.class		= &omap44xx_timer_1ms_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_timer1_irqs,
 	.main_clk	= "timer1_fck",
 	.prcm = {
@@ -3177,6 +3181,7 @@ static struct omap_hwmod omap44xx_timer2_hwmod = {
 	.name		= "timer2",
 	.class		= &omap44xx_timer_1ms_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_timer2_irqs,
 	.main_clk	= "timer2_fck",
 	.prcm = {
@@ -3351,6 +3356,7 @@ static struct omap_hwmod omap44xx_timer10_hwmod = {
 	.name		= "timer10",
 	.class		= &omap44xx_timer_1ms_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_timer10_irqs,
 	.main_clk	= "timer10_fck",
 	.prcm = {
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.c b/arch/arm/mach-omap2/omap_hwmod_common_data.c
index 9f1ccdc..79d623b 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.c
@@ -16,7 +16,7 @@
  * data and their integration with other OMAP modules and Linux.
  */
 
-#include <plat/omap_hwmod.h>
+#include "omap_hwmod.h"
 
 #include "omap_hwmod_common_data.h"
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h
index 2bc8f17..cfcce29 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.h
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.h
@@ -13,7 +13,7 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_OMAP_HWMOD_COMMON_DATA_H
 #define __ARCH_ARM_MACH_OMAP2_OMAP_HWMOD_COMMON_DATA_H
 
-#include <plat/omap_hwmod.h>
+#include "omap_hwmod.h"
 
 #include "common.h"
 #include "display.h"
diff --git a/arch/arm/mach-omap2/omap_opp_data.h b/arch/arm/mach-omap2/omap_opp_data.h
index c784c12..336fdfc 100644
--- a/arch/arm/mach-omap2/omap_opp_data.h
+++ b/arch/arm/mach-omap2/omap_opp_data.h
@@ -19,7 +19,7 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H
 #define __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H
 
-#include <plat/omap_hwmod.h>
+#include "omap_hwmod.h"
 
 #include "voltage.h"
 
@@ -89,8 +89,11 @@ extern struct omap_volt_data omap34xx_vddcore_volt_data[];
 extern struct omap_volt_data omap36xx_vddmpu_volt_data[];
 extern struct omap_volt_data omap36xx_vddcore_volt_data[];
 
-extern struct omap_volt_data omap44xx_vdd_mpu_volt_data[];
-extern struct omap_volt_data omap44xx_vdd_iva_volt_data[];
-extern struct omap_volt_data omap44xx_vdd_core_volt_data[];
+extern struct omap_volt_data omap443x_vdd_mpu_volt_data[];
+extern struct omap_volt_data omap443x_vdd_iva_volt_data[];
+extern struct omap_volt_data omap443x_vdd_core_volt_data[];
+extern struct omap_volt_data omap446x_vdd_mpu_volt_data[];
+extern struct omap_volt_data omap446x_vdd_iva_volt_data[];
+extern struct omap_volt_data omap446x_vdd_core_volt_data[];
 
 #endif		/* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */
diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c
index d992db8..e237602 100644
--- a/arch/arm/mach-omap2/omap_phy_internal.c
+++ b/arch/arm/mach-omap2/omap_phy_internal.c
@@ -27,11 +27,43 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/usb.h>
-
-#include <plat/usb.h>
+#include <linux/usb/musb.h>
 
 #include "soc.h"
 #include "control.h"
+#include "usb.h"
+
+#define CONTROL_DEV_CONF		0x300
+#define PHY_PD				0x1
+
+/**
+ * omap4430_phy_power_down: disable MUSB PHY during early init
+ *
+ * OMAP4 MUSB PHY module is enabled by default on reset, but this will
+ * prevent core retention if not disabled by SW. USB driver will
+ * later on enable this, once and if the driver needs it.
+ */
+static int __init omap4430_phy_power_down(void)
+{
+	void __iomem *ctrl_base;
+
+	if (!cpu_is_omap44xx())
+		return 0;
+
+	ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K);
+	if (!ctrl_base) {
+		pr_err("control module ioremap failed\n");
+		return -ENOMEM;
+	}
+
+	/* Power down the phy */
+	__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
+
+	iounmap(ctrl_base);
+
+	return 0;
+}
+early_initcall(omap4430_phy_power_down);
 
 void am35x_musb_reset(void)
 {
diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c
index f515a1a..fefd401 100644
--- a/arch/arm/mach-omap2/omap_twl.c
+++ b/arch/arm/mach-omap2/omap_twl.c
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/i2c/twl.h>
 
+#include "soc.h"
 #include "voltage.h"
 
 #include "pm.h"
@@ -30,16 +31,6 @@
 #define OMAP3_VP_VSTEPMAX_VSTEPMAX	0x04
 #define OMAP3_VP_VLIMITTO_TIMEOUT_US	200
 
-#define OMAP3430_VP1_VLIMITTO_VDDMIN	0x14
-#define OMAP3430_VP1_VLIMITTO_VDDMAX	0x42
-#define OMAP3430_VP2_VLIMITTO_VDDMIN	0x18
-#define OMAP3430_VP2_VLIMITTO_VDDMAX	0x2c
-
-#define OMAP3630_VP1_VLIMITTO_VDDMIN	0x18
-#define OMAP3630_VP1_VLIMITTO_VDDMAX	0x3c
-#define OMAP3630_VP2_VLIMITTO_VDDMIN	0x18
-#define OMAP3630_VP2_VLIMITTO_VDDMAX	0x30
-
 #define OMAP4_SRI2C_SLAVE_ADDR		0x12
 #define OMAP4_VDD_MPU_SR_VOLT_REG	0x55
 #define OMAP4_VDD_MPU_SR_CMD_REG	0x56
@@ -53,13 +44,6 @@
 #define OMAP4_VP_VSTEPMAX_VSTEPMAX	0x04
 #define OMAP4_VP_VLIMITTO_TIMEOUT_US	200
 
-#define OMAP4_VP_MPU_VLIMITTO_VDDMIN	0xA
-#define OMAP4_VP_MPU_VLIMITTO_VDDMAX	0x39
-#define OMAP4_VP_IVA_VLIMITTO_VDDMIN	0xA
-#define OMAP4_VP_IVA_VLIMITTO_VDDMAX	0x2D
-#define OMAP4_VP_CORE_VLIMITTO_VDDMIN	0xA
-#define OMAP4_VP_CORE_VLIMITTO_VDDMAX	0x28
-
 static bool is_offset_valid;
 static u8 smps_offset;
 /*
@@ -158,16 +142,11 @@ static u8 twl6030_uv_to_vsel(unsigned long uv)
 static struct omap_voltdm_pmic omap3_mpu_pmic = {
 	.slew_rate		= 4000,
 	.step_size		= 12500,
-	.on_volt		= 1200000,
-	.onlp_volt		= 1000000,
-	.ret_volt		= 975000,
-	.off_volt		= 600000,
-	.volt_setup_time	= 0xfff,
 	.vp_erroroffset		= OMAP3_VP_CONFIG_ERROROFFSET,
 	.vp_vstepmin		= OMAP3_VP_VSTEPMIN_VSTEPMIN,
 	.vp_vstepmax		= OMAP3_VP_VSTEPMAX_VSTEPMAX,
-	.vp_vddmin		= OMAP3430_VP1_VLIMITTO_VDDMIN,
-	.vp_vddmax		= OMAP3430_VP1_VLIMITTO_VDDMAX,
+	.vddmin			= 600000,
+	.vddmax			= 1450000,
 	.vp_timeout_us		= OMAP3_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP3_SRI2C_SLAVE_ADDR,
 	.volt_reg_addr		= OMAP3_VDD_MPU_SR_CONTROL_REG,
@@ -179,16 +158,11 @@ static struct omap_voltdm_pmic omap3_mpu_pmic = {
 static struct omap_voltdm_pmic omap3_core_pmic = {
 	.slew_rate		= 4000,
 	.step_size		= 12500,
-	.on_volt                = 1200000,
-	.onlp_volt              = 1000000,
-	.ret_volt               = 975000,
-	.off_volt               = 600000,
-	.volt_setup_time        = 0xfff,
 	.vp_erroroffset		= OMAP3_VP_CONFIG_ERROROFFSET,
 	.vp_vstepmin		= OMAP3_VP_VSTEPMIN_VSTEPMIN,
 	.vp_vstepmax		= OMAP3_VP_VSTEPMAX_VSTEPMAX,
-	.vp_vddmin		= OMAP3430_VP2_VLIMITTO_VDDMIN,
-	.vp_vddmax		= OMAP3430_VP2_VLIMITTO_VDDMAX,
+	.vddmin			= 600000,
+	.vddmax			= 1450000,
 	.vp_timeout_us		= OMAP3_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP3_SRI2C_SLAVE_ADDR,
 	.volt_reg_addr		= OMAP3_VDD_CORE_SR_CONTROL_REG,
@@ -200,21 +174,17 @@ static struct omap_voltdm_pmic omap3_core_pmic = {
 static struct omap_voltdm_pmic omap4_mpu_pmic = {
 	.slew_rate		= 4000,
 	.step_size		= 12660,
-	.on_volt		= 1375000,
-	.onlp_volt		= 1375000,
-	.ret_volt		= 830000,
-	.off_volt		= 0,
-	.volt_setup_time	= 0,
 	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
 	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
 	.vp_vstepmax		= OMAP4_VP_VSTEPMAX_VSTEPMAX,
-	.vp_vddmin		= OMAP4_VP_MPU_VLIMITTO_VDDMIN,
-	.vp_vddmax		= OMAP4_VP_MPU_VLIMITTO_VDDMAX,
+	.vddmin			= 0,
+	.vddmax			= 2100000,
 	.vp_timeout_us		= OMAP4_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP4_SRI2C_SLAVE_ADDR,
 	.volt_reg_addr		= OMAP4_VDD_MPU_SR_VOLT_REG,
 	.cmd_reg_addr		= OMAP4_VDD_MPU_SR_CMD_REG,
 	.i2c_high_speed		= true,
+	.i2c_pad_load		= 3,
 	.vsel_to_uv		= twl6030_vsel_to_uv,
 	.uv_to_vsel		= twl6030_uv_to_vsel,
 };
@@ -222,21 +192,17 @@ static struct omap_voltdm_pmic omap4_mpu_pmic = {
 static struct omap_voltdm_pmic omap4_iva_pmic = {
 	.slew_rate		= 4000,
 	.step_size		= 12660,
-	.on_volt		= 1188000,
-	.onlp_volt		= 1188000,
-	.ret_volt		= 830000,
-	.off_volt		= 0,
-	.volt_setup_time	= 0,
 	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
 	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
 	.vp_vstepmax		= OMAP4_VP_VSTEPMAX_VSTEPMAX,
-	.vp_vddmin		= OMAP4_VP_IVA_VLIMITTO_VDDMIN,
-	.vp_vddmax		= OMAP4_VP_IVA_VLIMITTO_VDDMAX,
+	.vddmin			= 0,
+	.vddmax			= 2100000,
 	.vp_timeout_us		= OMAP4_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP4_SRI2C_SLAVE_ADDR,
 	.volt_reg_addr		= OMAP4_VDD_IVA_SR_VOLT_REG,
 	.cmd_reg_addr		= OMAP4_VDD_IVA_SR_CMD_REG,
 	.i2c_high_speed		= true,
+	.i2c_pad_load		= 3,
 	.vsel_to_uv		= twl6030_vsel_to_uv,
 	.uv_to_vsel		= twl6030_uv_to_vsel,
 };
@@ -244,20 +210,17 @@ static struct omap_voltdm_pmic omap4_iva_pmic = {
 static struct omap_voltdm_pmic omap4_core_pmic = {
 	.slew_rate		= 4000,
 	.step_size		= 12660,
-	.on_volt		= 1200000,
-	.onlp_volt		= 1200000,
-	.ret_volt		= 830000,
-	.off_volt		= 0,
-	.volt_setup_time	= 0,
 	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
 	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
 	.vp_vstepmax		= OMAP4_VP_VSTEPMAX_VSTEPMAX,
-	.vp_vddmin		= OMAP4_VP_CORE_VLIMITTO_VDDMIN,
-	.vp_vddmax		= OMAP4_VP_CORE_VLIMITTO_VDDMAX,
+	.vddmin			= 0,
+	.vddmax			= 2100000,
 	.vp_timeout_us		= OMAP4_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP4_SRI2C_SLAVE_ADDR,
 	.volt_reg_addr		= OMAP4_VDD_CORE_SR_VOLT_REG,
 	.cmd_reg_addr		= OMAP4_VDD_CORE_SR_CMD_REG,
+	.i2c_high_speed		= true,
+	.i2c_pad_load		= 3,
 	.vsel_to_uv		= twl6030_vsel_to_uv,
 	.uv_to_vsel		= twl6030_uv_to_vsel,
 };
@@ -288,13 +251,6 @@ int __init omap3_twl_init(void)
 	if (!cpu_is_omap34xx())
 		return -ENODEV;
 
-	if (cpu_is_omap3630()) {
-		omap3_mpu_pmic.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN;
-		omap3_mpu_pmic.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX;
-		omap3_core_pmic.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN;
-		omap3_core_pmic.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
-	}
-
 	/*
 	 * The smartreflex bit on twl4030 specifies if the setting of voltage
 	 * is done over the I2C_SR path. Since this setting is independent of
diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c
index 58e16ae..bd41d59 100644
--- a/arch/arm/mach-omap2/opp.c
+++ b/arch/arm/mach-omap2/opp.c
@@ -20,7 +20,7 @@
 #include <linux/opp.h>
 #include <linux/cpu.h>
 
-#include <plat/omap_device.h>
+#include "omap_device.h"
 
 #include "omap_opp_data.h"
 
diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c
index 75cef5f..62772e0 100644
--- a/arch/arm/mach-omap2/opp3xxx_data.c
+++ b/arch/arm/mach-omap2/opp3xxx_data.c
@@ -19,6 +19,7 @@
  */
 #include <linux/module.h>
 
+#include "soc.h"
 #include "control.h"
 #include "omap_opp_data.h"
 #include "pm.h"
diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c
index a9fd6d5..d470b72 100644
--- a/arch/arm/mach-omap2/opp4xxx_data.c
+++ b/arch/arm/mach-omap2/opp4xxx_data.c
@@ -1,7 +1,7 @@
 /*
  * OMAP4 OPP table definitions.
  *
- * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2010-2012 Texas Instruments Incorporated - http://www.ti.com/
  *	Nishanth Menon
  *	Kevin Hilman
  *	Thara Gopinath
@@ -35,7 +35,7 @@
 #define OMAP4430_VDD_MPU_OPPTURBO_UV		1313000
 #define OMAP4430_VDD_MPU_OPPNITRO_UV		1375000
 
-struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
+struct omap_volt_data omap443x_vdd_mpu_volt_data[] = {
 	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
 	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
 	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
@@ -47,7 +47,7 @@ struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
 #define OMAP4430_VDD_IVA_OPP100_UV		1188000
 #define OMAP4430_VDD_IVA_OPPTURBO_UV		1300000
 
-struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
+struct omap_volt_data omap443x_vdd_iva_volt_data[] = {
 	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
 	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
 	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
@@ -57,14 +57,14 @@ struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
 #define OMAP4430_VDD_CORE_OPP50_UV		1025000
 #define OMAP4430_VDD_CORE_OPP100_UV		1200000
 
-struct omap_volt_data omap44xx_vdd_core_volt_data[] = {
+struct omap_volt_data omap443x_vdd_core_volt_data[] = {
 	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
 	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
 	VOLT_DATA_DEFINE(0, 0, 0, 0),
 };
 
 
-static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
+static struct omap_opp_def __initdata omap443x_opp_def_list[] = {
 	/* MPU OPP1 - OPP50 */
 	OPP_INITIALIZER("mpu", true, 300000000, OMAP4430_VDD_MPU_OPP50_UV),
 	/* MPU OPP2 - OPP100 */
@@ -86,6 +86,82 @@ static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
 	/* TODO: add DSP, aess, fdif, gpu */
 };
 
+#define OMAP4460_VDD_MPU_OPP50_UV		1025000
+#define OMAP4460_VDD_MPU_OPP100_UV		1200000
+#define OMAP4460_VDD_MPU_OPPTURBO_UV		1313000
+#define OMAP4460_VDD_MPU_OPPNITRO_UV		1375000
+
+struct omap_volt_data omap446x_vdd_mpu_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
+	VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+#define OMAP4460_VDD_IVA_OPP50_UV		1025000
+#define OMAP4460_VDD_IVA_OPP100_UV		1200000
+#define OMAP4460_VDD_IVA_OPPTURBO_UV		1313000
+#define OMAP4460_VDD_IVA_OPPNITRO_UV		1375000
+
+struct omap_volt_data omap446x_vdd_iva_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
+	VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPNITRO, 0xfa, 0x23),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+#define OMAP4460_VDD_CORE_OPP50_UV		1025000
+#define OMAP4460_VDD_CORE_OPP100_UV		1200000
+#define OMAP4460_VDD_CORE_OPP100_OV_UV		1250000
+
+struct omap_volt_data omap446x_vdd_core_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_OV_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100OV, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+static struct omap_opp_def __initdata omap446x_opp_def_list[] = {
+	/* MPU OPP1 - OPP50 */
+	OPP_INITIALIZER("mpu", true, 350000000, OMAP4460_VDD_MPU_OPP50_UV),
+	/* MPU OPP2 - OPP100 */
+	OPP_INITIALIZER("mpu", true, 700000000, OMAP4460_VDD_MPU_OPP100_UV),
+	/* MPU OPP3 - OPP-Turbo */
+	OPP_INITIALIZER("mpu", true, 920000000, OMAP4460_VDD_MPU_OPPTURBO_UV),
+	/*
+	 * MPU OPP4 - OPP-Nitro + Disabled as the reference schematics
+	 * recommends TPS623631 - confirm and enable the opp in board file
+	 * XXX: May be we should enable these based on mpu capability and
+	 * Exception board files disable it...
+	 */
+	OPP_INITIALIZER("mpu", false, 1200000000, OMAP4460_VDD_MPU_OPPNITRO_UV),
+	/* MPU OPP4 - OPP-Nitro SpeedBin */
+	OPP_INITIALIZER("mpu", false, 1500000000, OMAP4460_VDD_MPU_OPPNITRO_UV),
+	/* L3 OPP1 - OPP50 */
+	OPP_INITIALIZER("l3_main_1", true, 100000000, OMAP4460_VDD_CORE_OPP50_UV),
+	/* L3 OPP2 - OPP100 */
+	OPP_INITIALIZER("l3_main_1", true, 200000000, OMAP4460_VDD_CORE_OPP100_UV),
+	/* IVA OPP1 - OPP50 */
+	OPP_INITIALIZER("iva", true, 133000000, OMAP4460_VDD_IVA_OPP50_UV),
+	/* IVA OPP2 - OPP100 */
+	OPP_INITIALIZER("iva", true, 266100000, OMAP4460_VDD_IVA_OPP100_UV),
+	/*
+	 * IVA OPP3 - OPP-Turbo + Disabled as the reference schematics
+	 * recommends Phoenix VCORE2 which can supply only 600mA - so the ones
+	 * above this OPP frequency, even though OMAP is capable, should be
+	 * enabled by board file which is sure of the chip power capability
+	 */
+	OPP_INITIALIZER("iva", false, 332000000, OMAP4460_VDD_IVA_OPPTURBO_UV),
+	/* IVA OPP4 - OPP-Nitro */
+	OPP_INITIALIZER("iva", false, 430000000, OMAP4460_VDD_IVA_OPPNITRO_UV),
+	/* IVA OPP5 - OPP-Nitro SpeedBin*/
+	OPP_INITIALIZER("iva", false, 500000000, OMAP4460_VDD_IVA_OPPNITRO_UV),
+
+	/* TODO: add DSP, aess, fdif, gpu */
+};
+
 /**
  * omap4_opp_init() - initialize omap4 opp table
  */
@@ -93,12 +169,12 @@ int __init omap4_opp_init(void)
 {
 	int r = -ENODEV;
 
-	if (!cpu_is_omap443x())
-		return r;
-
-	r = omap_init_opp_table(omap44xx_opp_def_list,
-			ARRAY_SIZE(omap44xx_opp_def_list));
-
+	if (cpu_is_omap443x())
+		r = omap_init_opp_table(omap443x_opp_def_list,
+			ARRAY_SIZE(omap443x_opp_def_list));
+	else if (cpu_is_omap446x())
+		r = omap_init_opp_table(omap446x_opp_def_list,
+			ARRAY_SIZE(omap446x_opp_def_list));
 	return r;
 }
 device_initcall(omap4_opp_init);
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 46092cd..3cf4fdf 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -27,12 +27,13 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 
-#include <plat/clock.h>
+#include "clock.h"
 #include "powerdomain.h"
 #include "clockdomain.h"
 #include <plat/dmtimer.h>
-#include <plat/omap-pm.h>
+#include "omap-pm.h"
 
+#include "soc.h"
 #include "cm2xxx_3xxx.h"
 #include "prm2xxx_3xxx.h"
 #include "pm.h"
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index ea61c32..f4b3143 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -20,10 +20,11 @@
 
 #include <asm/system_misc.h>
 
-#include <plat/omap-pm.h>
-#include <plat/omap_device.h>
+#include "omap-pm.h"
+#include "omap_device.h"
 #include "common.h"
 
+#include "soc.h"
 #include "prcm-common.h"
 #include "voltage.h"
 #include "powerdomain.h"
@@ -39,6 +40,38 @@ static struct omap_device_pm_latency *pm_lats;
  */
 int (*omap_pm_suspend)(void);
 
+#ifdef CONFIG_PM
+/**
+ * struct omap2_oscillator - Describe the board main oscillator latencies
+ * @startup_time: oscillator startup latency
+ * @shutdown_time: oscillator shutdown latency
+ */
+struct omap2_oscillator {
+	u32 startup_time;
+	u32 shutdown_time;
+};
+
+static struct omap2_oscillator oscillator = {
+	.startup_time = ULONG_MAX,
+	.shutdown_time = ULONG_MAX,
+};
+
+void omap_pm_setup_oscillator(u32 tstart, u32 tshut)
+{
+	oscillator.startup_time = tstart;
+	oscillator.shutdown_time = tshut;
+}
+
+void omap_pm_get_oscillator(u32 *tstart, u32 *tshut)
+{
+	if (!tstart || !tshut)
+		return;
+
+	*tstart = oscillator.startup_time;
+	*tshut = oscillator.shutdown_time;
+}
+#endif
+
 static int __init _init_omap_device(char *name)
 {
 	struct omap_hwmod *oh;
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 67d6613..c22503b 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -102,6 +102,15 @@ extern void enable_omap3630_toggle_l2_on_restore(void);
 static inline void enable_omap3630_toggle_l2_on_restore(void) { }
 #endif		/* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */
 
+#define PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD	(1 << 0)
+
+#if defined(CONFIG_ARCH_OMAP4)
+extern u16 pm44xx_errata;
+#define IS_PM44XX_ERRATUM(id)		(pm44xx_errata & (id))
+#else
+#define IS_PM44XX_ERRATUM(id)		0
+#endif
+
 #ifdef CONFIG_POWER_AVS_OMAP
 extern int omap_devinit_smartreflex(void);
 extern void omap_enable_smartreflex_on_init(void);
@@ -129,4 +138,14 @@ static inline int omap4_twl_init(void)
 }
 #endif
 
+#ifdef CONFIG_PM
+extern void omap_pm_setup_oscillator(u32 tstart, u32 tshut);
+extern void omap_pm_get_oscillator(u32 *tstart, u32 *tshut);
+extern void omap_pm_setup_sr_i2c_pcb_length(u32 mm);
+#else
+static inline void omap_pm_setup_oscillator(u32 tstart, u32 tshut) { }
+static inline void omap_pm_get_oscillator(u32 *tstart, u32 *tshut) { *tstart = *tshut = 0; }
+static inline void omap_pm_setup_sr_i2c_pcb_length(u32 mm) { }
+#endif
+
 #endif
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 8af6cd6..c289b33 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -25,27 +25,30 @@
 #include <linux/sysfs.h>
 #include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/irq.h>
 #include <linux/time.h>
 #include <linux/gpio.h>
 #include <linux/platform_data/gpio-omap.h>
 
+#include <asm/fncpy.h>
+
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 #include <asm/mach-types.h>
 #include <asm/system_misc.h>
 
-#include <plat/clock.h>
-#include <plat/sram.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 
+#include "soc.h"
 #include "common.h"
-#include "prm2xxx_3xxx.h"
+#include "clock.h"
+#include "prm2xxx.h"
 #include "prm-regbits-24xx.h"
-#include "cm2xxx_3xxx.h"
+#include "cm2xxx.h"
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
+#include "sram.h"
 #include "pm.h"
 #include "control.h"
 #include "powerdomain.h"
@@ -200,7 +203,7 @@ static int omap2_can_sleep(void)
 {
 	if (omap2_fclks_active())
 		return 0;
-	if (osc_ck->usecount > 1)
+	if (__clk_is_enabled(osc_ck))
 		return 0;
 	if (omap_dma_running())
 		return 0;
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 3a904de..7703200 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -32,25 +32,24 @@
 
 #include <trace/events/power.h>
 
+#include <asm/fncpy.h>
 #include <asm/suspend.h>
 #include <asm/system_misc.h>
 
-#include <plat/sram.h>
 #include "clockdomain.h"
 #include "powerdomain.h"
-#include <plat/sdrc.h>
-#include <plat/prcm.h>
-#include <plat/gpmc.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 
+#include "soc.h"
 #include "common.h"
-#include "cm2xxx_3xxx.h"
+#include "cm3xxx.h"
 #include "cm-regbits-34xx.h"
+#include "gpmc.h"
 #include "prm-regbits-34xx.h"
-
-#include "prm2xxx_3xxx.h"
+#include "prm3xxx.h"
 #include "pm.h"
 #include "sdrc.h"
+#include "sram.h"
 #include "control.h"
 
 /* pm34xx errata defined in pm.h */
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 04922d1..aa6fd98 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <asm/system_misc.h>
 
+#include "soc.h"
 #include "common.h"
 #include "clockdomain.h"
 #include "powerdomain.h"
@@ -100,13 +101,6 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 	if (!strncmp(pwrdm->name, "cpu", 3))
 		return 0;
 
-	/*
-	 * FIXME: Remove this check when core retention is supported
-	 * Only MPUSS power domain is added in the list.
-	 */
-	if (strcmp(pwrdm->name, "mpu_pwrdm"))
-		return 0;
-
 	pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
 	if (!pwrst)
 		return -ENOMEM;
diff --git a/arch/arm/mach-omap2/pmu.c b/arch/arm/mach-omap2/pmu.c
index 2a79176..250d909 100644
--- a/arch/arm/mach-omap2/pmu.c
+++ b/arch/arm/mach-omap2/pmu.c
@@ -15,8 +15,9 @@
 
 #include <asm/pmu.h>
 
-#include <plat/omap_hwmod.h>
-#include <plat/omap_device.h>
+#include "soc.h"
+#include "omap_hwmod.h"
+#include "omap_device.h"
 
 static char *omap2_pmu_oh_names[] = {"mpu"};
 static char *omap3_pmu_oh_names[] = {"mpu", "debugss"};
@@ -57,8 +58,6 @@ static int __init omap2_init_pmu(unsigned oh_num, char *oh_names[])
 	if (IS_ERR(omap_pmu_dev))
 		return PTR_ERR(omap_pmu_dev);
 
-	pm_runtime_enable(&omap_pmu_dev->dev);
-
 	return 0;
 }
 
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 1678a32..dea62a9 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -29,8 +29,6 @@
 
 #include <asm/cpu.h>
 
-#include <plat/prcm.h>
-
 #include "powerdomain.h"
 #include "clockdomain.h"
 
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index baee906..5277d56eb 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -22,8 +22,6 @@
 
 #include <linux/atomic.h>
 
-#include <plat/cpu.h>
-
 #include "voltage.h"
 
 /* Powerdomain basic power states */
diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
deleted file mode 100644
index 3950ccf..0000000
--- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * OMAP2 and OMAP3 powerdomain control
- *
- * Copyright (C) 2009-2011 Texas Instruments, Inc.
- * Copyright (C) 2007-2009 Nokia Corporation
- *
- * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
- * Rajendra Nayak <rnayak@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/io.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/bug.h>
-
-#include <plat/prcm.h>
-
-#include "powerdomain.h"
-#include "prm.h"
-#include "prm-regbits-24xx.h"
-#include "prm-regbits-34xx.h"
-
-
-/* Common functions across OMAP2 and OMAP3 */
-static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
-{
-	omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
-				(pwrst << OMAP_POWERSTATE_SHIFT),
-				pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
-	return 0;
-}
-
-static int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
-{
-	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
-					     OMAP2_PM_PWSTCTRL,
-					     OMAP_POWERSTATE_MASK);
-}
-
-static int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm)
-{
-	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
-					     OMAP2_PM_PWSTST,
-					     OMAP_POWERSTATEST_MASK);
-}
-
-static int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
-								u8 pwrst)
-{
-	u32 m;
-
-	m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
-
-	omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
-				   OMAP2_PM_PWSTCTRL);
-
-	return 0;
-}
-
-static int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
-								u8 pwrst)
-{
-	u32 m;
-
-	m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
-
-	omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
-				   OMAP2_PM_PWSTCTRL);
-
-	return 0;
-}
-
-static int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
-{
-	u32 m;
-
-	m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
-
-	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTST,
-					     m);
-}
-
-static int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
-{
-	u32 m;
-
-	m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
-
-	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
-					     OMAP2_PM_PWSTCTRL, m);
-}
-
-static int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
-{
-	u32 v;
-
-	v = pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE_MASK);
-	omap2_prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE_MASK, v,
-				   pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
-
-	return 0;
-}
-
-static int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm)
-{
-	u32 c = 0;
-
-	/*
-	 * REVISIT: pwrdm_wait_transition() may be better implemented
-	 * via a callback and a periodic timer check -- how long do we expect
-	 * powerdomain transitions to take?
-	 */
-
-	/* XXX Is this udelay() value meaningful? */
-	while ((omap2_prm_read_mod_reg(pwrdm->prcm_offs, OMAP2_PM_PWSTST) &
-		OMAP_INTRANSITION_MASK) &&
-		(c++ < PWRDM_TRANSITION_BAILOUT))
-			udelay(1);
-
-	if (c > PWRDM_TRANSITION_BAILOUT) {
-		pr_err("powerdomain: %s: waited too long to complete transition\n",
-		       pwrdm->name);
-		return -EAGAIN;
-	}
-
-	pr_debug("powerdomain: completed transition in %d loops\n", c);
-
-	return 0;
-}
-
-/* Applicable only for OMAP3. Not supported on OMAP2 */
-static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
-{
-	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
-					     OMAP3430_PM_PREPWSTST,
-					     OMAP3430_LASTPOWERSTATEENTERED_MASK);
-}
-
-static int omap3_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
-{
-	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
-					     OMAP2_PM_PWSTST,
-					     OMAP3430_LOGICSTATEST_MASK);
-}
-
-static int omap3_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
-{
-	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
-					     OMAP2_PM_PWSTCTRL,
-					     OMAP3430_LOGICSTATEST_MASK);
-}
-
-static int omap3_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
-{
-	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
-					     OMAP3430_PM_PREPWSTST,
-					     OMAP3430_LASTLOGICSTATEENTERED_MASK);
-}
-
-static int omap3_get_mem_bank_lastmemst_mask(u8 bank)
-{
-	switch (bank) {
-	case 0:
-		return OMAP3430_LASTMEM1STATEENTERED_MASK;
-	case 1:
-		return OMAP3430_LASTMEM2STATEENTERED_MASK;
-	case 2:
-		return OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
-	case 3:
-		return OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
-	default:
-		WARN_ON(1); /* should never happen */
-		return -EEXIST;
-	}
-	return 0;
-}
-
-static int omap3_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
-{
-	u32 m;
-
-	m = omap3_get_mem_bank_lastmemst_mask(bank);
-
-	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
-				OMAP3430_PM_PREPWSTST, m);
-}
-
-static int omap3_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
-{
-	omap2_prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
-	return 0;
-}
-
-static int omap3_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
-{
-	return omap2_prm_rmw_mod_reg_bits(0,
-					  1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
-					  pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
-}
-
-static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
-{
-	return omap2_prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
-					  0, pwrdm->prcm_offs,
-					  OMAP2_PM_PWSTCTRL);
-}
-
-struct pwrdm_ops omap2_pwrdm_operations = {
-	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
-	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
-	.pwrdm_read_pwrst	= omap2_pwrdm_read_pwrst,
-	.pwrdm_set_logic_retst	= omap2_pwrdm_set_logic_retst,
-	.pwrdm_set_mem_onst	= omap2_pwrdm_set_mem_onst,
-	.pwrdm_set_mem_retst	= omap2_pwrdm_set_mem_retst,
-	.pwrdm_read_mem_pwrst	= omap2_pwrdm_read_mem_pwrst,
-	.pwrdm_read_mem_retst	= omap2_pwrdm_read_mem_retst,
-	.pwrdm_wait_transition	= omap2_pwrdm_wait_transition,
-};
-
-struct pwrdm_ops omap3_pwrdm_operations = {
-	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
-	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
-	.pwrdm_read_pwrst	= omap2_pwrdm_read_pwrst,
-	.pwrdm_read_prev_pwrst	= omap3_pwrdm_read_prev_pwrst,
-	.pwrdm_set_logic_retst	= omap2_pwrdm_set_logic_retst,
-	.pwrdm_read_logic_pwrst	= omap3_pwrdm_read_logic_pwrst,
-	.pwrdm_read_logic_retst	= omap3_pwrdm_read_logic_retst,
-	.pwrdm_read_prev_logic_pwrst	= omap3_pwrdm_read_prev_logic_pwrst,
-	.pwrdm_set_mem_onst	= omap2_pwrdm_set_mem_onst,
-	.pwrdm_set_mem_retst	= omap2_pwrdm_set_mem_retst,
-	.pwrdm_read_mem_pwrst	= omap2_pwrdm_read_mem_pwrst,
-	.pwrdm_read_mem_retst	= omap2_pwrdm_read_mem_retst,
-	.pwrdm_read_prev_mem_pwrst	= omap3_pwrdm_read_prev_mem_pwrst,
-	.pwrdm_clear_all_prev_pwrst	= omap3_pwrdm_clear_all_prev_pwrst,
-	.pwrdm_enable_hdwr_sar	= omap3_pwrdm_enable_hdwr_sar,
-	.pwrdm_disable_hdwr_sar	= omap3_pwrdm_disable_hdwr_sar,
-	.pwrdm_wait_transition	= omap2_pwrdm_wait_transition,
-};
diff --git a/arch/arm/mach-omap2/powerdomain33xx.c b/arch/arm/mach-omap2/powerdomain33xx.c
deleted file mode 100644
index 67c5663..0000000
--- a/arch/arm/mach-omap2/powerdomain33xx.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * AM33XX Powerdomain control
- *
- * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
- *
- * Derived from mach-omap2/powerdomain44xx.c written by 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 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/io.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-
-#include <plat/prcm.h>
-
-#include "powerdomain.h"
-#include "prm33xx.h"
-#include "prm-regbits-33xx.h"
-
-
-static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
-{
-	am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK,
-				(pwrst << OMAP_POWERSTATE_SHIFT),
-				pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
-	return 0;
-}
-
-static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
-{
-	u32 v;
-
-	v = am33xx_prm_read_reg(pwrdm->prcm_offs,  pwrdm->pwrstctrl_offs);
-	v &= OMAP_POWERSTATE_MASK;
-	v >>= OMAP_POWERSTATE_SHIFT;
-
-	return v;
-}
-
-static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
-{
-	u32 v;
-
-	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
-	v &= OMAP_POWERSTATEST_MASK;
-	v >>= OMAP_POWERSTATEST_SHIFT;
-
-	return v;
-}
-
-static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
-{
-	u32 v;
-
-	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
-	v &= AM33XX_LASTPOWERSTATEENTERED_MASK;
-	v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT;
-
-	return v;
-}
-
-static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
-{
-	am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK,
-				(1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT),
-				pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
-	return 0;
-}
-
-static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
-{
-	am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK,
-				AM33XX_LASTPOWERSTATEENTERED_MASK,
-				pwrdm->prcm_offs, pwrdm->pwrstst_offs);
-	return 0;
-}
-
-static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
-{
-	u32 m;
-
-	m = pwrdm->logicretstate_mask;
-	if (!m)
-		return -EINVAL;
-
-	am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
-				pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
-
-	return 0;
-}
-
-static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
-{
-	u32 v;
-
-	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
-	v &= AM33XX_LOGICSTATEST_MASK;
-	v >>= AM33XX_LOGICSTATEST_SHIFT;
-
-	return v;
-}
-
-static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
-{
-	u32 v, m;
-
-	m = pwrdm->logicretstate_mask;
-	if (!m)
-		return -EINVAL;
-
-	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
-	v &= m;
-	v >>= __ffs(m);
-
-	return v;
-}
-
-static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
-		u8 pwrst)
-{
-	u32 m;
-
-	m = pwrdm->mem_on_mask[bank];
-	if (!m)
-		return -EINVAL;
-
-	am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
-				pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
-
-	return 0;
-}
-
-static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
-					u8 pwrst)
-{
-	u32 m;
-
-	m = pwrdm->mem_ret_mask[bank];
-	if (!m)
-		return -EINVAL;
-
-	am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
-				pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
-
-	return 0;
-}
-
-static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
-{
-	u32 m, v;
-
-	m = pwrdm->mem_pwrst_mask[bank];
-	if (!m)
-		return -EINVAL;
-
-	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
-	v &= m;
-	v >>= __ffs(m);
-
-	return v;
-}
-
-static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
-{
-	u32 m, v;
-
-	m = pwrdm->mem_retst_mask[bank];
-	if (!m)
-		return -EINVAL;
-
-	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
-	v &= m;
-	v >>= __ffs(m);
-
-	return v;
-}
-
-static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm)
-{
-	u32 c = 0;
-
-	/*
-	 * REVISIT: pwrdm_wait_transition() may be better implemented
-	 * via a callback and a periodic timer check -- how long do we expect
-	 * powerdomain transitions to take?
-	 */
-
-	/* XXX Is this udelay() value meaningful? */
-	while ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs)
-			& OMAP_INTRANSITION_MASK) &&
-			(c++ < PWRDM_TRANSITION_BAILOUT))
-		udelay(1);
-
-	if (c > PWRDM_TRANSITION_BAILOUT) {
-		pr_err("powerdomain: %s: waited too long to complete transition\n",
-		       pwrdm->name);
-		return -EAGAIN;
-	}
-
-	pr_debug("powerdomain: completed transition in %d loops\n", c);
-
-	return 0;
-}
-
-struct pwrdm_ops am33xx_pwrdm_operations = {
-	.pwrdm_set_next_pwrst		= am33xx_pwrdm_set_next_pwrst,
-	.pwrdm_read_next_pwrst		= am33xx_pwrdm_read_next_pwrst,
-	.pwrdm_read_pwrst		= am33xx_pwrdm_read_pwrst,
-	.pwrdm_read_prev_pwrst		= am33xx_pwrdm_read_prev_pwrst,
-	.pwrdm_set_logic_retst		= am33xx_pwrdm_set_logic_retst,
-	.pwrdm_read_logic_pwrst		= am33xx_pwrdm_read_logic_pwrst,
-	.pwrdm_read_logic_retst		= am33xx_pwrdm_read_logic_retst,
-	.pwrdm_clear_all_prev_pwrst	= am33xx_pwrdm_clear_all_prev_pwrst,
-	.pwrdm_set_lowpwrstchange	= am33xx_pwrdm_set_lowpwrstchange,
-	.pwrdm_read_mem_pwrst		= am33xx_pwrdm_read_mem_pwrst,
-	.pwrdm_read_mem_retst		= am33xx_pwrdm_read_mem_retst,
-	.pwrdm_set_mem_onst		= am33xx_pwrdm_set_mem_onst,
-	.pwrdm_set_mem_retst		= am33xx_pwrdm_set_mem_retst,
-	.pwrdm_wait_transition		= am33xx_pwrdm_wait_transition,
-};
diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
deleted file mode 100644
index aceb4f4..0000000
--- a/arch/arm/mach-omap2/powerdomain44xx.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * OMAP4 powerdomain control
- *
- * Copyright (C) 2009-2010, 2012 Texas Instruments, Inc.
- * Copyright (C) 2007-2009 Nokia Corporation
- *
- * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
- * Rajendra Nayak <rnayak@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/io.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/bug.h>
-
-#include "powerdomain.h"
-#include <plat/prcm.h>
-#include "prm2xxx_3xxx.h"
-#include "prm44xx.h"
-#include "prminst44xx.h"
-#include "prm-regbits-44xx.h"
-
-static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
-{
-	omap4_prminst_rmw_inst_reg_bits(OMAP_POWERSTATE_MASK,
-					(pwrst << OMAP_POWERSTATE_SHIFT),
-					pwrdm->prcm_partition,
-					pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
-	return 0;
-}
-
-static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
-{
-	u32 v;
-
-	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
-					OMAP4_PM_PWSTCTRL);
-	v &= OMAP_POWERSTATE_MASK;
-	v >>= OMAP_POWERSTATE_SHIFT;
-
-	return v;
-}
-
-static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm)
-{
-	u32 v;
-
-	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
-					OMAP4_PM_PWSTST);
-	v &= OMAP_POWERSTATEST_MASK;
-	v >>= OMAP_POWERSTATEST_SHIFT;
-
-	return v;
-}
-
-static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
-{
-	u32 v;
-
-	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
-					OMAP4_PM_PWSTST);
-	v &= OMAP4430_LASTPOWERSTATEENTERED_MASK;
-	v >>= OMAP4430_LASTPOWERSTATEENTERED_SHIFT;
-
-	return v;
-}
-
-static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
-{
-	omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK,
-					(1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT),
-					pwrdm->prcm_partition,
-					pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
-	return 0;
-}
-
-static int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
-{
-	omap4_prminst_rmw_inst_reg_bits(OMAP4430_LASTPOWERSTATEENTERED_MASK,
-					OMAP4430_LASTPOWERSTATEENTERED_MASK,
-					pwrdm->prcm_partition,
-					pwrdm->prcm_offs, OMAP4_PM_PWSTST);
-	return 0;
-}
-
-static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
-{
-	u32 v;
-
-	v = pwrst << __ffs(OMAP4430_LOGICRETSTATE_MASK);
-	omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOGICRETSTATE_MASK, v,
-					pwrdm->prcm_partition, pwrdm->prcm_offs,
-					OMAP4_PM_PWSTCTRL);
-
-	return 0;
-}
-
-static int omap4_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
-				    u8 pwrst)
-{
-	u32 m;
-
-	m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
-
-	omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
-					pwrdm->prcm_partition, pwrdm->prcm_offs,
-					OMAP4_PM_PWSTCTRL);
-
-	return 0;
-}
-
-static int omap4_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
-				     u8 pwrst)
-{
-	u32 m;
-
-	m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
-
-	omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
-					pwrdm->prcm_partition, pwrdm->prcm_offs,
-					OMAP4_PM_PWSTCTRL);
-
-	return 0;
-}
-
-static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
-{
-	u32 v;
-
-	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
-					OMAP4_PM_PWSTST);
-	v &= OMAP4430_LOGICSTATEST_MASK;
-	v >>= OMAP4430_LOGICSTATEST_SHIFT;
-
-	return v;
-}
-
-static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
-{
-	u32 v;
-
-	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
-					OMAP4_PM_PWSTCTRL);
-	v &= OMAP4430_LOGICRETSTATE_MASK;
-	v >>= OMAP4430_LOGICRETSTATE_SHIFT;
-
-	return v;
-}
-
-/**
- * omap4_pwrdm_read_prev_logic_pwrst - read the previous logic powerstate
- * @pwrdm: struct powerdomain * to read the state for
- *
- * Reads the previous logic powerstate for a powerdomain. This
- * function must determine the previous logic powerstate by first
- * checking the previous powerstate for the domain. If that was OFF,
- * then logic has been lost. If previous state was RETENTION, the
- * function reads the setting for the next retention logic state to
- * see the actual value.  In every other case, the logic is
- * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
- * depending whether the logic was retained or not.
- */
-static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
-{
-	int state;
-
-	state = omap4_pwrdm_read_prev_pwrst(pwrdm);
-
-	if (state == PWRDM_POWER_OFF)
-		return PWRDM_POWER_OFF;
-
-	if (state != PWRDM_POWER_RET)
-		return PWRDM_POWER_RET;
-
-	return omap4_pwrdm_read_logic_retst(pwrdm);
-}
-
-static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
-{
-	u32 m, v;
-
-	m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
-
-	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
-					OMAP4_PM_PWSTST);
-	v &= m;
-	v >>= __ffs(m);
-
-	return v;
-}
-
-static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
-{
-	u32 m, v;
-
-	m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
-
-	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
-					OMAP4_PM_PWSTCTRL);
-	v &= m;
-	v >>= __ffs(m);
-
-	return v;
-}
-
-/**
- * omap4_pwrdm_read_prev_mem_pwrst - reads the previous memory powerstate
- * @pwrdm: struct powerdomain * to read mem powerstate for
- * @bank: memory bank index
- *
- * Reads the previous memory powerstate for a powerdomain. This
- * function must determine the previous memory powerstate by first
- * checking the previous powerstate for the domain. If that was OFF,
- * then logic has been lost. If previous state was RETENTION, the
- * function reads the setting for the next memory retention state to
- * see the actual value.  In every other case, the logic is
- * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
- * depending whether logic was retained or not.
- */
-static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
-{
-	int state;
-
-	state = omap4_pwrdm_read_prev_pwrst(pwrdm);
-
-	if (state == PWRDM_POWER_OFF)
-		return PWRDM_POWER_OFF;
-
-	if (state != PWRDM_POWER_RET)
-		return PWRDM_POWER_RET;
-
-	return omap4_pwrdm_read_mem_retst(pwrdm, bank);
-}
-
-static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
-{
-	u32 c = 0;
-
-	/*
-	 * REVISIT: pwrdm_wait_transition() may be better implemented
-	 * via a callback and a periodic timer check -- how long do we expect
-	 * powerdomain transitions to take?
-	 */
-
-	/* XXX Is this udelay() value meaningful? */
-	while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
-					    pwrdm->prcm_offs,
-					    OMAP4_PM_PWSTST) &
-		OMAP_INTRANSITION_MASK) &&
-	       (c++ < PWRDM_TRANSITION_BAILOUT))
-		udelay(1);
-
-	if (c > PWRDM_TRANSITION_BAILOUT) {
-		pr_err("powerdomain: %s: waited too long to complete transition\n",
-		       pwrdm->name);
-		return -EAGAIN;
-	}
-
-	pr_debug("powerdomain: completed transition in %d loops\n", c);
-
-	return 0;
-}
-
-struct pwrdm_ops omap4_pwrdm_operations = {
-	.pwrdm_set_next_pwrst	= omap4_pwrdm_set_next_pwrst,
-	.pwrdm_read_next_pwrst	= omap4_pwrdm_read_next_pwrst,
-	.pwrdm_read_pwrst	= omap4_pwrdm_read_pwrst,
-	.pwrdm_read_prev_pwrst	= omap4_pwrdm_read_prev_pwrst,
-	.pwrdm_set_lowpwrstchange	= omap4_pwrdm_set_lowpwrstchange,
-	.pwrdm_clear_all_prev_pwrst	= omap4_pwrdm_clear_all_prev_pwrst,
-	.pwrdm_set_logic_retst	= omap4_pwrdm_set_logic_retst,
-	.pwrdm_read_logic_pwrst	= omap4_pwrdm_read_logic_pwrst,
-	.pwrdm_read_prev_logic_pwrst	= omap4_pwrdm_read_prev_logic_pwrst,
-	.pwrdm_read_logic_retst	= omap4_pwrdm_read_logic_retst,
-	.pwrdm_read_mem_pwrst	= omap4_pwrdm_read_mem_pwrst,
-	.pwrdm_read_mem_retst	= omap4_pwrdm_read_mem_retst,
-	.pwrdm_read_prev_mem_pwrst	= omap4_pwrdm_read_prev_mem_pwrst,
-	.pwrdm_set_mem_onst	= omap4_pwrdm_set_mem_onst,
-	.pwrdm_set_mem_retst	= omap4_pwrdm_set_mem_retst,
-	.pwrdm_wait_transition	= omap4_pwrdm_wait_transition,
-};
diff --git a/arch/arm/mach-omap2/powerdomains2xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_data.c
index 2385c1f..ba520d4 100644
--- a/arch/arm/mach-omap2/powerdomains2xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains2xxx_data.c
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
+#include "soc.h"
 #include "powerdomain.h"
 #include "powerdomains2xxx_3xxx_data.h"
 
diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h
index 72df974..c7d355f 100644
--- a/arch/arm/mach-omap2/prcm-common.h
+++ b/arch/arm/mach-omap2/prcm-common.h
@@ -406,11 +406,6 @@
 #define OMAP3430_EN_CORE_MASK				(1 << 0)
 
 
-/*
- * MAX_MODULE_HARDRESET_WAIT: Maximum microseconds to wait for an OMAP
- * submodule to exit hardreset
- */
-#define MAX_MODULE_HARDRESET_WAIT		10000
 
 /*
  * Maximum time(us) it takes to output the signal WUCLKOUT of the last
@@ -419,24 +414,7 @@
  * microseconds on OMAP4, so this timeout may be too high.
  */
 #define MAX_IOPAD_LATCH_TIME			100
-
 # ifndef __ASSEMBLER__
-extern void __iomem *prm_base;
-extern void __iomem *cm_base;
-extern void __iomem *cm2_base;
-extern void __iomem *prcm_mpu_base;
-
-#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
-extern void omap_prm_base_init(void);
-extern void omap_cm_base_init(void);
-#else
-static inline void omap_prm_base_init(void)
-{
-}
-static inline void omap_cm_base_init(void)
-{
-}
-#endif
 
 /**
  * struct omap_prcm_irq - describes a PRCM interrupt bit
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
deleted file mode 100644
index 0f51e03..0000000
--- a/arch/arm/mach-omap2/prcm.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/prcm.c
- *
- * OMAP 24xx Power Reset and Clock Management (PRCM) functions
- *
- * Copyright (C) 2005 Nokia Corporation
- *
- * Written by Tony Lindgren <tony.lindgren@nokia.com>
- *
- * Copyright (C) 2007 Texas Instruments, Inc.
- * Rajendra Nayak <rnayak@ti.com>
- *
- * Some pieces of code Copyright (C) 2005 Texas Instruments, Inc.
- * Upgraded with OMAP4 support by Abhijit Pagare <abhijitpagare@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/export.h>
-
-#include "common.h"
-#include <plat/prcm.h>
-
-#include "clock.h"
-#include "clock2xxx.h"
-#include "cm2xxx_3xxx.h"
-#include "prm2xxx_3xxx.h"
-#include "prm44xx.h"
-#include "prminst44xx.h"
-#include "cminst44xx.h"
-#include "prm-regbits-24xx.h"
-#include "prm-regbits-44xx.h"
-#include "control.h"
-
-void __iomem *prm_base;
-void __iomem *cm_base;
-void __iomem *cm2_base;
-void __iomem *prcm_mpu_base;
-
-#define MAX_MODULE_ENABLE_WAIT		100000
-
-u32 omap_prcm_get_reset_sources(void)
-{
-	/* XXX This presumably needs modification for 34XX */
-	if (cpu_is_omap24xx() || cpu_is_omap34xx())
-		return omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST) & 0x7f;
-	if (cpu_is_omap44xx())
-		return omap2_prm_read_mod_reg(WKUP_MOD, OMAP4_RM_RSTST) & 0x7f;
-
-	return 0;
-}
-EXPORT_SYMBOL(omap_prcm_get_reset_sources);
-
-/* Resets clock rates and reboots the system. Only called from system.h */
-void omap_prcm_restart(char mode, const char *cmd)
-{
-	s16 prcm_offs = 0;
-
-	if (cpu_is_omap24xx()) {
-		omap2xxx_clk_prepare_for_reboot();
-
-		prcm_offs = WKUP_MOD;
-	} else if (cpu_is_omap34xx()) {
-		prcm_offs = OMAP3430_GR_MOD;
-		omap3_ctrl_write_boot_mode((cmd ? (u8)*cmd : 0));
-	} else if (cpu_is_omap44xx()) {
-		omap4_prminst_global_warm_sw_reset(); /* never returns */
-	} else {
-		WARN_ON(1);
-	}
-
-	/*
-	 * As per Errata i520, in some cases, user will not be able to
-	 * access DDR memory after warm-reset.
-	 * This situation occurs while the warm-reset happens during a read
-	 * access to DDR memory. In that particular condition, DDR memory
-	 * does not respond to a corrupted read command due to the warm
-	 * reset occurrence but SDRC is waiting for read completion.
-	 * SDRC is not sensitive to the warm reset, but the interconnect is
-	 * reset on the fly, thus causing a misalignment between SDRC logic,
-	 * interconnect logic and DDR memory state.
-	 * WORKAROUND:
-	 * Steps to perform before a Warm reset is trigged:
-	 * 1. enable self-refresh on idle request
-	 * 2. put SDRC in idle
-	 * 3. wait until SDRC goes to idle
-	 * 4. generate SW reset (Global SW reset)
-	 *
-	 * Steps to be performed after warm reset occurs (in bootloader):
-	 * if HW warm reset is the source, apply below steps before any
-	 * accesses to SDRAM:
-	 * 1. Reset SMS and SDRC and wait till reset is complete
-	 * 2. Re-initialize SMS, SDRC and memory
-	 *
-	 * NOTE: Above work around is required only if arch reset is implemented
-	 * using Global SW reset(GLOBAL_SW_RST). DPLL3 reset does not need
-	 * the WA since it resets SDRC as well as part of cold reset.
-	 */
-
-	/* XXX should be moved to some OMAP2/3 specific code */
-	omap2_prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, prcm_offs,
-				   OMAP2_RM_RSTCTRL);
-	omap2_prm_read_mod_reg(prcm_offs, OMAP2_RM_RSTCTRL); /* OCP barrier */
-}
-
-/**
- * omap2_cm_wait_idlest - wait for IDLEST bit to indicate module readiness
- * @reg: physical address of module IDLEST register
- * @mask: value to mask against to determine if the module is active
- * @idlest: idle state indicator (0 or 1) for the clock
- * @name: name of the clock (for printk)
- *
- * Returns 1 if the module indicated readiness in time, or 0 if it
- * failed to enable in roughly MAX_MODULE_ENABLE_WAIT microseconds.
- *
- * XXX This function is deprecated.  It should be removed once the
- * hwmod conversion is complete.
- */
-int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
-				const char *name)
-{
-	int i = 0;
-	int ena = 0;
-
-	if (idlest)
-		ena = 0;
-	else
-		ena = mask;
-
-	/* Wait for lock */
-	omap_test_timeout(((__raw_readl(reg) & mask) == ena),
-			  MAX_MODULE_ENABLE_WAIT, i);
-
-	if (i < MAX_MODULE_ENABLE_WAIT)
-		pr_debug("cm: Module associated with clock %s ready after %d loops\n",
-			 name, i);
-	else
-		pr_err("cm: Module associated with clock %s didn't enable in %d tries\n",
-		       name, MAX_MODULE_ENABLE_WAIT);
-
-	return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0;
-};
-
-void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals)
-{
-	if (omap2_globals->prm)
-		prm_base = omap2_globals->prm;
-	if (omap2_globals->cm)
-		cm_base = omap2_globals->cm;
-	if (omap2_globals->cm2)
-		cm2_base = omap2_globals->cm2;
-	if (omap2_globals->prcm_mpu)
-		prcm_mpu_base = omap2_globals->prcm_mpu;
-
-	if (cpu_is_omap44xx() || soc_is_omap54xx()) {
-		omap_prm_base_init();
-		omap_cm_base_init();
-	}
-}
-
-/*
- * Stubbed functions so that common files continue to build when
- * custom builds are used
- * XXX These are temporary and should be removed at the earliest possible
- * opportunity
- */
-int __weak omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs,
-					u16 clkctrl_offs)
-{
-	return 0;
-}
-
-void __weak omap4_cminst_module_enable(u8 mode, u8 part, u16 inst,
-				s16 cdoffs, u16 clkctrl_offs)
-{
-}
-
-void __weak omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
-				 u16 clkctrl_offs)
-{
-}
diff --git a/arch/arm/mach-omap2/prcm_mpu44xx.c b/arch/arm/mach-omap2/prcm_mpu44xx.c
index 928dbd4..c30e44a 100644
--- a/arch/arm/mach-omap2/prcm_mpu44xx.c
+++ b/arch/arm/mach-omap2/prcm_mpu44xx.c
@@ -20,6 +20,12 @@
 #include "prcm_mpu44xx.h"
 #include "cm-regbits-44xx.h"
 
+/*
+ * prcm_mpu_base: the virtual address of the start of the PRCM_MPU IP
+ *   block registers
+ */
+void __iomem *prcm_mpu_base;
+
 /* PRCM_MPU low-level functions */
 
 u32 omap4_prcm_mpu_read_inst_reg(s16 inst, u16 reg)
@@ -43,3 +49,14 @@ u32 omap4_prcm_mpu_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
 
 	return v;
 }
+
+/**
+ * omap2_set_globals_prcm_mpu - set the MPU PRCM base address (for early use)
+ * @prcm_mpu: PRCM_MPU base virtual address
+ *
+ * XXX Will be replaced when the PRM/CM drivers are completed.
+ */
+void __init omap2_set_globals_prcm_mpu(void __iomem *prcm_mpu)
+{
+	prcm_mpu_base = prcm_mpu;
+}
diff --git a/arch/arm/mach-omap2/prcm_mpu44xx.h b/arch/arm/mach-omap2/prcm_mpu44xx.h
index 8a6e250..884af7b 100644
--- a/arch/arm/mach-omap2/prcm_mpu44xx.h
+++ b/arch/arm/mach-omap2/prcm_mpu44xx.h
@@ -1,7 +1,7 @@
 /*
  * OMAP44xx PRCM MPU instance offset macros
  *
- * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2010, 2012 Texas Instruments, Inc.
  * Copyright (C) 2010 Nokia Corporation
  *
  * Paul Walmsley (paul@pwsan.com)
@@ -25,6 +25,12 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_PRCM_MPU44XX_H
 #define __ARCH_ARM_MACH_OMAP2_PRCM_MPU44XX_H
 
+#include "common.h"
+
+# ifndef __ASSEMBLER__
+extern void __iomem *prcm_mpu_base;
+# endif
+
 #define OMAP4430_PRCM_MPU_BASE			0x48243000
 
 #define OMAP44XX_PRCM_MPU_REGADDR(inst, reg)				\
@@ -98,6 +104,7 @@ extern u32 omap4_prcm_mpu_read_inst_reg(s16 inst, u16 idx);
 extern void omap4_prcm_mpu_write_inst_reg(u32 val, s16 inst, u16 idx);
 extern u32 omap4_prcm_mpu_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst,
 					    s16 idx);
+extern void __init omap2_set_globals_prcm_mpu(void __iomem *prcm_mpu);
 # endif
 
 #endif
diff --git a/arch/arm/mach-omap2/prm-regbits-24xx.h b/arch/arm/mach-omap2/prm-regbits-24xx.h
index 6ac9661..91aa510 100644
--- a/arch/arm/mach-omap2/prm-regbits-24xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-24xx.h
@@ -14,7 +14,7 @@
  * published by the Free Software Foundation.
  */
 
-#include "prm2xxx_3xxx.h"
+#include "prm2xxx.h"
 
 /* Bits shared between registers */
 
@@ -107,12 +107,14 @@
 #define OMAP2420_CLKOUT2_EN_MASK			(1 << 15)
 #define OMAP2420_CLKOUT2_DIV_SHIFT			11
 #define OMAP2420_CLKOUT2_DIV_MASK			(0x7 << 11)
+#define OMAP2420_CLKOUT2_DIV_WIDTH			3
 #define OMAP2420_CLKOUT2_SOURCE_SHIFT			8
 #define OMAP2420_CLKOUT2_SOURCE_MASK			(0x3 << 8)
 #define OMAP24XX_CLKOUT_EN_SHIFT			7
 #define OMAP24XX_CLKOUT_EN_MASK				(1 << 7)
 #define OMAP24XX_CLKOUT_DIV_SHIFT			3
 #define OMAP24XX_CLKOUT_DIV_MASK			(0x7 << 3)
+#define OMAP24XX_CLKOUT_DIV_WIDTH			3
 #define OMAP24XX_CLKOUT_SOURCE_SHIFT			0
 #define OMAP24XX_CLKOUT_SOURCE_MASK			(0x3 << 0)
 
@@ -209,9 +211,13 @@
 
 /* RM_RSTST_WKUP specific bits */
 /* 2430 calls EXTWMPU_RST "EXTWARM_RST" and GLOBALWMPU_RST "GLOBALWARM_RST" */
+#define OMAP24XX_EXTWMPU_RST_SHIFT			6
 #define OMAP24XX_EXTWMPU_RST_MASK			(1 << 6)
+#define OMAP24XX_SECU_WD_RST_SHIFT			5
 #define OMAP24XX_SECU_WD_RST_MASK			(1 << 5)
+#define OMAP24XX_MPU_WD_RST_SHIFT			4
 #define OMAP24XX_MPU_WD_RST_MASK			(1 << 4)
+#define OMAP24XX_SECU_VIOL_RST_SHIFT			3
 #define OMAP24XX_SECU_VIOL_RST_MASK			(1 << 3)
 
 /* PM_WKEN_WKUP specific bits */
diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h
index 64c087a..b0a2142 100644
--- a/arch/arm/mach-omap2/prm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-34xx.h
@@ -14,7 +14,7 @@
 #define __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_34XX_H
 
 
-#include "prm2xxx_3xxx.h"
+#include "prm3xxx.h"
 
 /* Shared register bits */
 
@@ -384,6 +384,7 @@
 /* PRM_CLKSEL */
 #define OMAP3430_SYS_CLKIN_SEL_SHIFT			0
 #define OMAP3430_SYS_CLKIN_SEL_MASK			(0x7 << 0)
+#define OMAP3430_SYS_CLKIN_SEL_WIDTH			3
 
 /* PRM_CLKOUT_CTRL */
 #define OMAP3430_CLKOUT_EN_MASK				(1 << 7)
@@ -509,15 +510,25 @@
 #define OMAP3430_RSTTIME1_MASK				(0xff << 0)
 
 /* PRM_RSTST */
+#define OMAP3430_ICECRUSHER_RST_SHIFT			10
 #define OMAP3430_ICECRUSHER_RST_MASK			(1 << 10)
+#define OMAP3430_ICEPICK_RST_SHIFT			9
 #define OMAP3430_ICEPICK_RST_MASK			(1 << 9)
+#define OMAP3430_VDD2_VOLTAGE_MANAGER_RST_SHIFT		8
 #define OMAP3430_VDD2_VOLTAGE_MANAGER_RST_MASK		(1 << 8)
+#define OMAP3430_VDD1_VOLTAGE_MANAGER_RST_SHIFT		7
 #define OMAP3430_VDD1_VOLTAGE_MANAGER_RST_MASK		(1 << 7)
+#define OMAP3430_EXTERNAL_WARM_RST_SHIFT		6
 #define OMAP3430_EXTERNAL_WARM_RST_MASK			(1 << 6)
+#define OMAP3430_SECURE_WD_RST_SHIFT			5
 #define OMAP3430_SECURE_WD_RST_MASK			(1 << 5)
+#define OMAP3430_MPU_WD_RST_SHIFT			4
 #define OMAP3430_MPU_WD_RST_MASK			(1 << 4)
+#define OMAP3430_SECURITY_VIOL_RST_SHIFT		3
 #define OMAP3430_SECURITY_VIOL_RST_MASK			(1 << 3)
+#define OMAP3430_GLOBAL_SW_RST_SHIFT			1
 #define OMAP3430_GLOBAL_SW_RST_MASK			(1 << 1)
+#define OMAP3430_GLOBAL_COLD_RST_SHIFT			0
 #define OMAP3430_GLOBAL_COLD_RST_MASK			(1 << 0)
 
 /* PRM_VOLTCTRL */
diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h
index 39d5621..a1a266c 100644
--- a/arch/arm/mach-omap2/prm.h
+++ b/arch/arm/mach-omap2/prm.h
@@ -1,7 +1,7 @@
 /*
  * OMAP2/3/4 Power/Reset Management (PRM) bitfield definitions
  *
- * Copyright (C) 2007-2009 Texas Instruments, Inc.
+ * Copyright (C) 2007-2009, 2012 Texas Instruments, Inc.
  * Copyright (C) 2010 Nokia Corporation
  *
  * Paul Walmsley
@@ -15,6 +15,28 @@
 
 #include "prcm-common.h"
 
+# ifndef __ASSEMBLER__
+extern void __iomem *prm_base;
+extern void omap2_set_globals_prm(void __iomem *prm);
+# endif
+
+
+/*
+ * MAX_MODULE_SOFTRESET_WAIT: Maximum microseconds to wait for OMAP
+ * module to softreset
+ */
+#define MAX_MODULE_SOFTRESET_WAIT		10000
+
+/*
+ * MAX_MODULE_HARDRESET_WAIT: Maximum microseconds to wait for an OMAP
+ * submodule to exit hardreset
+ */
+#define MAX_MODULE_HARDRESET_WAIT		10000
+
+/*
+ * Register bitfields
+ */
+
 /*
  * 24XX: PM_PWSTST_CORE, PM_PWSTST_GFX, PM_PWSTST_MPU, PM_PWSTST_DSP
  *
@@ -52,5 +74,58 @@
 #define OMAP_POWERSTATE_SHIFT				0
 #define OMAP_POWERSTATE_MASK				(0x3 << 0)
 
+/*
+ * Standardized OMAP reset source bits
+ *
+ * To the extent these happen to match the hardware register bit
+ * shifts, it's purely coincidental.  Used by omap-wdt.c.
+ * OMAP_UNKNOWN_RST_SRC_ID_SHIFT is a special value, used whenever
+ * there are any bits remaining in the global PRM_RSTST register that
+ * haven't been identified, or when the PRM code for the current SoC
+ * doesn't know how to interpret the register.
+ */
+#define OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT			0
+#define OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT			1
+#define OMAP_SECU_VIOL_RST_SRC_ID_SHIFT				2
+#define OMAP_MPU_WD_RST_SRC_ID_SHIFT				3
+#define OMAP_SECU_WD_RST_SRC_ID_SHIFT				4
+#define OMAP_EXTWARM_RST_SRC_ID_SHIFT				5
+#define OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT			6
+#define OMAP_VDD_IVA_VM_RST_SRC_ID_SHIFT			7
+#define OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT			8
+#define OMAP_ICEPICK_RST_SRC_ID_SHIFT				9
+#define OMAP_ICECRUSHER_RST_SRC_ID_SHIFT			10
+#define OMAP_C2C_RST_SRC_ID_SHIFT				11
+#define OMAP_UNKNOWN_RST_SRC_ID_SHIFT				12
+
+#ifndef __ASSEMBLER__
+
+/**
+ * struct prm_reset_src_map - map register bitshifts to standard bitshifts
+ * @reg_shift: bitshift in the PRM reset source register
+ * @std_shift: bitshift equivalent in the standard reset source list
+ *
+ * The fields are signed because -1 is used as a terminator.
+ */
+struct prm_reset_src_map {
+	s8 reg_shift;
+	s8 std_shift;
+};
+
+/**
+ * struct prm_ll_data - fn ptrs to per-SoC PRM function implementations
+ * @read_reset_sources: ptr to the Soc PRM-specific get_reset_source impl
+ */
+struct prm_ll_data {
+	u32 (*read_reset_sources)(void);
+};
+
+extern int prm_register(struct prm_ll_data *pld);
+extern int prm_unregister(struct prm_ll_data *pld);
+
+extern u32 prm_read_reset_sources(void);
+
+#endif
+
 
 #endif
diff --git a/arch/arm/mach-omap2/prm2xxx.c b/arch/arm/mach-omap2/prm2xxx.c
new file mode 100644
index 0000000..bf24fc4
--- /dev/null
+++ b/arch/arm/mach-omap2/prm2xxx.c
@@ -0,0 +1,139 @@
+/*
+ * OMAP2xxx PRM module functions
+ *
+ * Copyright (C) 2010-2012 Texas Instruments, Inc.
+ * Copyright (C) 2010 Nokia Corporation
+ * Benoît Cousson
+ * Paul Walmsley
+ * Rajendra Nayak <rnayak@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#include "common.h"
+#include <plat/cpu.h>
+
+#include "vp.h"
+#include "powerdomain.h"
+#include "clockdomain.h"
+#include "prm2xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "prm-regbits-24xx.h"
+
+/*
+ * omap2xxx_prm_reset_src_map - map from bits in the PRM_RSTST_WKUP
+ *   hardware register (which are specific to the OMAP2xxx SoCs) to
+ *   reset source ID bit shifts (which is an OMAP SoC-independent
+ *   enumeration)
+ */
+static struct prm_reset_src_map omap2xxx_prm_reset_src_map[] = {
+	{ OMAP_GLOBALCOLD_RST_SHIFT, OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
+	{ OMAP_GLOBALWARM_RST_SHIFT, OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
+	{ OMAP24XX_SECU_VIOL_RST_SHIFT, OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
+	{ OMAP24XX_MPU_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
+	{ OMAP24XX_SECU_WD_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
+	{ OMAP24XX_EXTWMPU_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
+	{ -1, -1 },
+};
+
+/**
+ * omap2xxx_prm_read_reset_sources - return the last SoC reset source
+ *
+ * Return a u32 representing the last reset sources of the SoC.  The
+ * returned reset source bits are standardized across OMAP SoCs.
+ */
+static u32 omap2xxx_prm_read_reset_sources(void)
+{
+	struct prm_reset_src_map *p;
+	u32 r = 0;
+	u32 v;
+
+	v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST);
+
+	p = omap2xxx_prm_reset_src_map;
+	while (p->reg_shift >= 0 && p->std_shift >= 0) {
+		if (v & (1 << p->reg_shift))
+			r |= 1 << p->std_shift;
+		p++;
+	}
+
+	return r;
+}
+
+/**
+ * omap2xxx_prm_dpll_reset - use DPLL reset to reboot the OMAP SoC
+ *
+ * Set the DPLL reset bit, which should reboot the SoC.  This is the
+ * recommended way to restart the SoC.  No return value.
+ */
+void omap2xxx_prm_dpll_reset(void)
+{
+	omap2_prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, WKUP_MOD,
+				   OMAP2_RM_RSTCTRL);
+	/* OCP barrier */
+	omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTCTRL);
+}
+
+int omap2xxx_clkdm_sleep(struct clockdomain *clkdm)
+{
+	omap2_prm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
+				   clkdm->pwrdm.ptr->prcm_offs,
+				   OMAP2_PM_PWSTCTRL);
+	return 0;
+}
+
+int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm)
+{
+	omap2_prm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
+				     clkdm->pwrdm.ptr->prcm_offs,
+				     OMAP2_PM_PWSTCTRL);
+	return 0;
+}
+
+struct pwrdm_ops omap2_pwrdm_operations = {
+	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
+	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
+	.pwrdm_read_pwrst	= omap2_pwrdm_read_pwrst,
+	.pwrdm_set_logic_retst	= omap2_pwrdm_set_logic_retst,
+	.pwrdm_set_mem_onst	= omap2_pwrdm_set_mem_onst,
+	.pwrdm_set_mem_retst	= omap2_pwrdm_set_mem_retst,
+	.pwrdm_read_mem_pwrst	= omap2_pwrdm_read_mem_pwrst,
+	.pwrdm_read_mem_retst	= omap2_pwrdm_read_mem_retst,
+	.pwrdm_wait_transition	= omap2_pwrdm_wait_transition,
+};
+
+/*
+ *
+ */
+
+static struct prm_ll_data omap2xxx_prm_ll_data = {
+	.read_reset_sources = &omap2xxx_prm_read_reset_sources,
+};
+
+static int __init omap2xxx_prm_init(void)
+{
+	if (!cpu_is_omap24xx())
+		return 0;
+
+	return prm_register(&omap2xxx_prm_ll_data);
+}
+subsys_initcall(omap2xxx_prm_init);
+
+static void __exit omap2xxx_prm_exit(void)
+{
+	if (!cpu_is_omap24xx())
+		return;
+
+	/* Should never happen */
+	WARN(prm_unregister(&omap2xxx_prm_ll_data),
+	     "%s: prm_ll_data function pointer mismatch\n", __func__);
+}
+__exitcall(omap2xxx_prm_exit);
diff --git a/arch/arm/mach-omap2/prm2xxx.h b/arch/arm/mach-omap2/prm2xxx.h
new file mode 100644
index 0000000..fe8a14f
--- /dev/null
+++ b/arch/arm/mach-omap2/prm2xxx.h
@@ -0,0 +1,134 @@
+/*
+ * OMAP2xxx Power/Reset Management (PRM) register definitions
+ *
+ * Copyright (C) 2007-2009, 2011-2012 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The PRM hardware modules on the OMAP2/3 are quite similar to each
+ * other.  The PRM on OMAP4 has a new register layout, and is handled
+ * in a separate file.
+ */
+#ifndef __ARCH_ARM_MACH_OMAP2_PRM2XXX_H
+#define __ARCH_ARM_MACH_OMAP2_PRM2XXX_H
+
+#include "prcm-common.h"
+#include "prm.h"
+#include "prm2xxx_3xxx.h"
+
+#define OMAP2420_PRM_REGADDR(module, reg)				\
+		OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE + (module) + (reg))
+#define OMAP2430_PRM_REGADDR(module, reg)				\
+		OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE + (module) + (reg))
+
+/*
+ * OMAP2-specific global PRM registers
+ * Use __raw_{read,write}l() with these registers.
+ *
+ * With a few exceptions, these are the register names beginning with
+ * PRCM_* on 24xx.  (The exceptions are the IRQSTATUS and IRQENABLE
+ * bits.)
+ *
+ */
+
+#define OMAP2_PRCM_REVISION_OFFSET	0x0000
+#define OMAP2420_PRCM_REVISION		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0000)
+#define OMAP2_PRCM_SYSCONFIG_OFFSET	0x0010
+#define OMAP2420_PRCM_SYSCONFIG		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0010)
+
+#define OMAP2_PRCM_IRQSTATUS_MPU_OFFSET	0x0018
+#define OMAP2420_PRCM_IRQSTATUS_MPU	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0018)
+#define OMAP2_PRCM_IRQENABLE_MPU_OFFSET	0x001c
+#define OMAP2420_PRCM_IRQENABLE_MPU	OMAP2420_PRM_REGADDR(OCP_MOD, 0x001c)
+
+#define OMAP2_PRCM_VOLTCTRL_OFFSET	0x0050
+#define OMAP2420_PRCM_VOLTCTRL		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0050)
+#define OMAP2_PRCM_VOLTST_OFFSET	0x0054
+#define OMAP2420_PRCM_VOLTST		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0054)
+#define OMAP2_PRCM_CLKSRC_CTRL_OFFSET	0x0060
+#define OMAP2420_PRCM_CLKSRC_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0060)
+#define OMAP2_PRCM_CLKOUT_CTRL_OFFSET	0x0070
+#define OMAP2420_PRCM_CLKOUT_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0070)
+#define OMAP2_PRCM_CLKEMUL_CTRL_OFFSET	0x0078
+#define OMAP2420_PRCM_CLKEMUL_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0078)
+#define OMAP2_PRCM_CLKCFG_CTRL_OFFSET	0x0080
+#define OMAP2420_PRCM_CLKCFG_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0080)
+#define OMAP2_PRCM_CLKCFG_STATUS_OFFSET	0x0084
+#define OMAP2420_PRCM_CLKCFG_STATUS	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0084)
+#define OMAP2_PRCM_VOLTSETUP_OFFSET	0x0090
+#define OMAP2420_PRCM_VOLTSETUP		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0090)
+#define OMAP2_PRCM_CLKSSETUP_OFFSET	0x0094
+#define OMAP2420_PRCM_CLKSSETUP		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0094)
+#define OMAP2_PRCM_POLCTRL_OFFSET	0x0098
+#define OMAP2420_PRCM_POLCTRL		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0098)
+
+#define OMAP2430_PRCM_REVISION		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0000)
+#define OMAP2430_PRCM_SYSCONFIG		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0010)
+
+#define OMAP2430_PRCM_IRQSTATUS_MPU	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0018)
+#define OMAP2430_PRCM_IRQENABLE_MPU	OMAP2430_PRM_REGADDR(OCP_MOD, 0x001c)
+
+#define OMAP2430_PRCM_VOLTCTRL		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0050)
+#define OMAP2430_PRCM_VOLTST		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0054)
+#define OMAP2430_PRCM_CLKSRC_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0060)
+#define OMAP2430_PRCM_CLKOUT_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0070)
+#define OMAP2430_PRCM_CLKEMUL_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0078)
+#define OMAP2430_PRCM_CLKCFG_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0080)
+#define OMAP2430_PRCM_CLKCFG_STATUS	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0084)
+#define OMAP2430_PRCM_VOLTSETUP		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0090)
+#define OMAP2430_PRCM_CLKSSETUP		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0094)
+#define OMAP2430_PRCM_POLCTRL		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0098)
+
+/*
+ * Module specific PRM register offsets from PRM_BASE + domain offset
+ *
+ * Use prm_{read,write}_mod_reg() with these registers.
+ *
+ * With a few exceptions, these are the register names beginning with
+ * {PM,RM}_* on both OMAP2/3 SoC families..  (The exceptions are the
+ * IRQSTATUS and IRQENABLE bits.)
+ */
+
+/* Register offsets appearing on both OMAP2 and OMAP3 */
+
+#define OMAP2_RM_RSTCTRL				0x0050
+#define OMAP2_RM_RSTTIME				0x0054
+#define OMAP2_RM_RSTST					0x0058
+#define OMAP2_PM_PWSTCTRL				0x00e0
+#define OMAP2_PM_PWSTST					0x00e4
+
+#define PM_WKEN						0x00a0
+#define PM_WKEN1					PM_WKEN
+#define PM_WKST						0x00b0
+#define PM_WKST1					PM_WKST
+#define PM_WKDEP					0x00c8
+#define PM_EVGENCTRL					0x00d4
+#define PM_EVGENONTIM					0x00d8
+#define PM_EVGENOFFTIM					0x00dc
+
+/* OMAP2xxx specific register offsets */
+#define OMAP24XX_PM_WKEN2				0x00a4
+#define OMAP24XX_PM_WKST2				0x00b4
+
+#define OMAP24XX_PRCM_IRQSTATUS_DSP			0x00f0	/* IVA mod */
+#define OMAP24XX_PRCM_IRQENABLE_DSP			0x00f4	/* IVA mod */
+#define OMAP24XX_PRCM_IRQSTATUS_IVA			0x00f8
+#define OMAP24XX_PRCM_IRQENABLE_IVA			0x00fc
+
+#ifndef __ASSEMBLER__
+/* Function prototypes */
+extern int omap2xxx_clkdm_sleep(struct clockdomain *clkdm);
+extern int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm);
+
+extern void omap2xxx_prm_dpll_reset(void);
+
+extern int __init prm2xxx_init(void);
+extern int __exit prm2xxx_exit(void);
+
+#endif
+
+#endif
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c
index 9529984..30517f5 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c
@@ -15,82 +15,12 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/io.h>
-#include <linux/irq.h>
 
-#include <plat/prcm.h>
-
-#include "soc.h"
 #include "common.h"
-#include "vp.h"
-
+#include "powerdomain.h"
 #include "prm2xxx_3xxx.h"
-#include "cm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
-#include "prm-regbits-34xx.h"
-
-static const struct omap_prcm_irq omap3_prcm_irqs[] = {
-	OMAP_PRCM_IRQ("wkup",	0,	0),
-	OMAP_PRCM_IRQ("io",	9,	1),
-};
-
-static struct omap_prcm_irq_setup omap3_prcm_irq_setup = {
-	.ack			= OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
-	.mask			= OMAP3_PRM_IRQENABLE_MPU_OFFSET,
-	.nr_regs		= 1,
-	.irqs			= omap3_prcm_irqs,
-	.nr_irqs		= ARRAY_SIZE(omap3_prcm_irqs),
-	.irq			= 11 + OMAP_INTC_START,
-	.read_pending_irqs	= &omap3xxx_prm_read_pending_irqs,
-	.ocp_barrier		= &omap3xxx_prm_ocp_barrier,
-	.save_and_clear_irqen	= &omap3xxx_prm_save_and_clear_irqen,
-	.restore_irqen		= &omap3xxx_prm_restore_irqen,
-};
-
-u32 omap2_prm_read_mod_reg(s16 module, u16 idx)
-{
-	return __raw_readl(prm_base + module + idx);
-}
-
-void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx)
-{
-	__raw_writel(val, prm_base + module + idx);
-}
-
-/* Read-modify-write a register in a PRM module. Caller must lock */
-u32 omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
-{
-	u32 v;
-
-	v = omap2_prm_read_mod_reg(module, idx);
-	v &= ~mask;
-	v |= bits;
-	omap2_prm_write_mod_reg(v, module, idx);
-
-	return v;
-}
-
-/* Read a PRM register, AND it, and shift the result down to bit 0 */
-u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
-{
-	u32 v;
-
-	v = omap2_prm_read_mod_reg(domain, idx);
-	v &= mask;
-	v >>= __ffs(mask);
-
-	return v;
-}
-
-u32 omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
-{
-	return omap2_prm_rmw_mod_reg_bits(bits, bits, module, idx);
-}
-
-u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
-{
-	return omap2_prm_rmw_mod_reg_bits(bits, 0x0, module, idx);
-}
-
+#include "clockdomain.h"
 
 /**
  * omap2_prm_is_hardreset_asserted - read the HW reset line state of
@@ -104,9 +34,6 @@ u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
  */
 int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
 {
-	if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
-		return -EINVAL;
-
 	return omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL,
 				       (1 << shift));
 }
@@ -127,9 +54,6 @@ int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
 {
 	u32 mask;
 
-	if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
-		return -EINVAL;
-
 	mask = 1 << shift;
 	omap2_prm_rmw_mod_reg_bits(mask, mask, prm_mod, OMAP2_RM_RSTCTRL);
 
@@ -156,9 +80,6 @@ int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift)
 	u32 rst, st;
 	int c;
 
-	if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
-		return -EINVAL;
-
 	rst = 1 << rst_shift;
 	st = 1 << st_shift;
 
@@ -178,188 +99,155 @@ int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift)
 	return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
 }
 
-/* PRM VP */
-
-/*
- * struct omap3_vp - OMAP3 VP register access description.
- * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
- */
-struct omap3_vp {
-	u32 tranxdone_status;
-};
-
-static struct omap3_vp omap3_vp[] = {
-	[OMAP3_VP_VDD_MPU_ID] = {
-		.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
-	},
-	[OMAP3_VP_VDD_CORE_ID] = {
-		.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
-	},
-};
-
-#define MAX_VP_ID ARRAY_SIZE(omap3_vp);
-
-u32 omap3_prm_vp_check_txdone(u8 vp_id)
-{
-	struct omap3_vp *vp = &omap3_vp[vp_id];
-	u32 irqstatus;
 
-	irqstatus = omap2_prm_read_mod_reg(OCP_MOD,
-					   OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
-	return irqstatus & vp->tranxdone_status;
-}
+/* Powerdomain low-level functions */
 
-void omap3_prm_vp_clear_txdone(u8 vp_id)
+/* Common functions across OMAP2 and OMAP3 */
+int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 {
-	struct omap3_vp *vp = &omap3_vp[vp_id];
-
-	omap2_prm_write_mod_reg(vp->tranxdone_status,
-				OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+	omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
+				   (pwrst << OMAP_POWERSTATE_SHIFT),
+				   pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
+	return 0;
 }
 
-u32 omap3_prm_vcvp_read(u8 offset)
+int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
 {
-	return omap2_prm_read_mod_reg(OMAP3430_GR_MOD, offset);
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+					     OMAP2_PM_PWSTCTRL,
+					     OMAP_POWERSTATE_MASK);
 }
 
-void omap3_prm_vcvp_write(u32 val, u8 offset)
+int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm)
 {
-	omap2_prm_write_mod_reg(val, OMAP3430_GR_MOD, offset);
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+					     OMAP2_PM_PWSTST,
+					     OMAP_POWERSTATEST_MASK);
 }
 
-u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
+int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
+								u8 pwrst)
 {
-	return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset);
+	u32 m;
+
+	m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
+
+	omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
+				   OMAP2_PM_PWSTCTRL);
+
+	return 0;
 }
 
-/**
- * omap3xxx_prm_read_pending_irqs - read pending PRM MPU IRQs into @events
- * @events: ptr to a u32, preallocated by caller
- *
- * Read PRM_IRQSTATUS_MPU bits, AND'ed with the currently-enabled PRM
- * MPU IRQs, and store the result into the u32 pointed to by @events.
- * No return value.
- */
-void omap3xxx_prm_read_pending_irqs(unsigned long *events)
+int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
+								u8 pwrst)
 {
-	u32 mask, st;
+	u32 m;
+
+	m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
 
-	/* XXX Can the mask read be avoided (e.g., can it come from RAM?) */
-	mask = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
-	st = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+	omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
+				   OMAP2_PM_PWSTCTRL);
 
-	events[0] = mask & st;
+	return 0;
 }
 
-/**
- * omap3xxx_prm_ocp_barrier - force buffered MPU writes to the PRM to complete
- *
- * Force any buffered writes to the PRM IP block to complete.  Needed
- * by the PRM IRQ handler, which reads and writes directly to the IP
- * block, to avoid race conditions after acknowledging or clearing IRQ
- * bits.  No return value.
- */
-void omap3xxx_prm_ocp_barrier(void)
+int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
 {
-	omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET);
+	u32 m;
+
+	m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
+
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTST,
+					     m);
 }
 
-/**
- * omap3xxx_prm_save_and_clear_irqen - save/clear PRM_IRQENABLE_MPU reg
- * @saved_mask: ptr to a u32 array to save IRQENABLE bits
- *
- * Save the PRM_IRQENABLE_MPU register to @saved_mask.  @saved_mask
- * must be allocated by the caller.  Intended to be used in the PRM
- * interrupt handler suspend callback.  The OCP barrier is needed to
- * ensure the write to disable PRM interrupts reaches the PRM before
- * returning; otherwise, spurious interrupts might occur.  No return
- * value.
- */
-void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask)
+int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
 {
-	saved_mask[0] = omap2_prm_read_mod_reg(OCP_MOD,
-					       OMAP3_PRM_IRQENABLE_MPU_OFFSET);
-	omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
+	u32 m;
+
+	m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
 
-	/* OCP barrier */
-	omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET);
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+					     OMAP2_PM_PWSTCTRL, m);
 }
 
-/**
- * omap3xxx_prm_restore_irqen - set PRM_IRQENABLE_MPU register from args
- * @saved_mask: ptr to a u32 array of IRQENABLE bits saved previously
- *
- * Restore the PRM_IRQENABLE_MPU register from @saved_mask.  Intended
- * to be used in the PRM interrupt handler resume callback to restore
- * values saved by omap3xxx_prm_save_and_clear_irqen().  No OCP
- * barrier should be needed here; any pending PRM interrupts will fire
- * once the writes reach the PRM.  No return value.
- */
-void omap3xxx_prm_restore_irqen(u32 *saved_mask)
+int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
 {
-	omap2_prm_write_mod_reg(saved_mask[0], OCP_MOD,
-				OMAP3_PRM_IRQENABLE_MPU_OFFSET);
+	u32 v;
+
+	v = pwrst << __ffs(OMAP_LOGICRETSTATE_MASK);
+	omap2_prm_rmw_mod_reg_bits(OMAP_LOGICRETSTATE_MASK, v, pwrdm->prcm_offs,
+				   OMAP2_PM_PWSTCTRL);
+
+	return 0;
 }
 
-/**
- * omap3xxx_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain
- *
- * Clear any previously-latched I/O wakeup events and ensure that the
- * I/O wakeup gates are aligned with the current mux settings.  Works
- * by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then
- * deasserting WUCLKIN and clearing the ST_IO_CHAIN WKST bit.  No
- * return value.
- */
-void omap3xxx_prm_reconfigure_io_chain(void)
+int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm)
 {
-	int i = 0;
+	u32 c = 0;
 
-	omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
-				   PM_WKEN);
+	/*
+	 * REVISIT: pwrdm_wait_transition() may be better implemented
+	 * via a callback and a periodic timer check -- how long do we expect
+	 * powerdomain transitions to take?
+	 */
 
-	omap_test_timeout(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST) &
-			  OMAP3430_ST_IO_CHAIN_MASK,
-			  MAX_IOPAD_LATCH_TIME, i);
-	if (i == MAX_IOPAD_LATCH_TIME)
-		pr_warn("PRM: I/O chain clock line assertion timed out\n");
+	/* XXX Is this udelay() value meaningful? */
+	while ((omap2_prm_read_mod_reg(pwrdm->prcm_offs, OMAP2_PM_PWSTST) &
+		OMAP_INTRANSITION_MASK) &&
+		(c++ < PWRDM_TRANSITION_BAILOUT))
+			udelay(1);
 
-	omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
-				     PM_WKEN);
+	if (c > PWRDM_TRANSITION_BAILOUT) {
+		pr_err("powerdomain: %s: waited too long to complete transition\n",
+		       pwrdm->name);
+		return -EAGAIN;
+	}
 
-	omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK, WKUP_MOD,
-				   PM_WKST);
+	pr_debug("powerdomain: completed transition in %d loops\n", c);
 
-	omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST);
+	return 0;
 }
 
-/**
- * omap3xxx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches
- *
- * Activates the I/O wakeup event latches and allows events logged by
- * those latches to signal a wakeup event to the PRCM.  For I/O
- * wakeups to occur, WAKEUPENABLE bits must be set in the pad mux
- * registers, and omap3xxx_prm_reconfigure_io_chain() must be called.
- * No return value.
- */
-static void __init omap3xxx_prm_enable_io_wakeup(void)
+int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1,
+			  struct clockdomain *clkdm2)
+{
+	omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+				   clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+	return 0;
+}
+
+int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1,
+			  struct clockdomain *clkdm2)
+{
+	omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+				     clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+	return 0;
+}
+
+int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1,
+			   struct clockdomain *clkdm2)
 {
-	if (omap3_has_io_wakeup())
-		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
-					   PM_WKEN);
+	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
+					     PM_WKDEP, (1 << clkdm2->dep_bit));
 }
 
-static int __init omap3xxx_prcm_init(void)
+int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
 {
-	int ret = 0;
-
-	if (cpu_is_omap34xx()) {
-		omap3xxx_prm_enable_io_wakeup();
-		ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
-		if (!ret)
-			irq_set_status_flags(omap_prcm_event_to_irq("io"),
-					     IRQ_NOAUTOEN);
+	struct clkdm_dep *cd;
+	u32 mask = 0;
+
+	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
+		if (!cd->clkdm)
+			continue; /* only happens if data is erroneous */
+
+		/* PRM accesses are slow, so minimize them */
+		mask |= 1 << cd->clkdm->dep_bit;
+		atomic_set(&cd->wkdep_usecount, 0);
 	}
 
-	return ret;
+	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
+				     PM_WKDEP);
+	return 0;
 }
-subsys_initcall(omap3xxx_prcm_init);
+
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h
index c19d249..9624b40 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.h
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h
@@ -1,7 +1,7 @@
 /*
- * OMAP2/3 Power/Reset Management (PRM) register definitions
+ * OMAP2xxx/3xxx-common Power/Reset Management (PRM) register definitions
  *
- * Copyright (C) 2007-2009, 2011 Texas Instruments, Inc.
+ * Copyright (C) 2007-2009, 2011-2012 Texas Instruments, Inc.
  * Copyright (C) 2008-2010 Nokia Corporation
  * Paul Walmsley
  *
@@ -19,160 +19,6 @@
 #include "prcm-common.h"
 #include "prm.h"
 
-#define OMAP2420_PRM_REGADDR(module, reg)				\
-		OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE + (module) + (reg))
-#define OMAP2430_PRM_REGADDR(module, reg)				\
-		OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE + (module) + (reg))
-#define OMAP34XX_PRM_REGADDR(module, reg)				\
-		OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE + (module) + (reg))
-
-
-/*
- * OMAP2-specific global PRM registers
- * Use __raw_{read,write}l() with these registers.
- *
- * With a few exceptions, these are the register names beginning with
- * PRCM_* on 24xx.  (The exceptions are the IRQSTATUS and IRQENABLE
- * bits.)
- *
- */
-
-#define OMAP2_PRCM_REVISION_OFFSET	0x0000
-#define OMAP2420_PRCM_REVISION		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0000)
-#define OMAP2_PRCM_SYSCONFIG_OFFSET	0x0010
-#define OMAP2420_PRCM_SYSCONFIG		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0010)
-
-#define OMAP2_PRCM_IRQSTATUS_MPU_OFFSET	0x0018
-#define OMAP2420_PRCM_IRQSTATUS_MPU	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0018)
-#define OMAP2_PRCM_IRQENABLE_MPU_OFFSET	0x001c
-#define OMAP2420_PRCM_IRQENABLE_MPU	OMAP2420_PRM_REGADDR(OCP_MOD, 0x001c)
-
-#define OMAP2_PRCM_VOLTCTRL_OFFSET	0x0050
-#define OMAP2420_PRCM_VOLTCTRL		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0050)
-#define OMAP2_PRCM_VOLTST_OFFSET	0x0054
-#define OMAP2420_PRCM_VOLTST		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0054)
-#define OMAP2_PRCM_CLKSRC_CTRL_OFFSET	0x0060
-#define OMAP2420_PRCM_CLKSRC_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0060)
-#define OMAP2_PRCM_CLKOUT_CTRL_OFFSET	0x0070
-#define OMAP2420_PRCM_CLKOUT_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0070)
-#define OMAP2_PRCM_CLKEMUL_CTRL_OFFSET	0x0078
-#define OMAP2420_PRCM_CLKEMUL_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0078)
-#define OMAP2_PRCM_CLKCFG_CTRL_OFFSET	0x0080
-#define OMAP2420_PRCM_CLKCFG_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0080)
-#define OMAP2_PRCM_CLKCFG_STATUS_OFFSET	0x0084
-#define OMAP2420_PRCM_CLKCFG_STATUS	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0084)
-#define OMAP2_PRCM_VOLTSETUP_OFFSET	0x0090
-#define OMAP2420_PRCM_VOLTSETUP		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0090)
-#define OMAP2_PRCM_CLKSSETUP_OFFSET	0x0094
-#define OMAP2420_PRCM_CLKSSETUP		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0094)
-#define OMAP2_PRCM_POLCTRL_OFFSET	0x0098
-#define OMAP2420_PRCM_POLCTRL		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0098)
-
-#define OMAP2430_PRCM_REVISION		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0000)
-#define OMAP2430_PRCM_SYSCONFIG		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0010)
-
-#define OMAP2430_PRCM_IRQSTATUS_MPU	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0018)
-#define OMAP2430_PRCM_IRQENABLE_MPU	OMAP2430_PRM_REGADDR(OCP_MOD, 0x001c)
-
-#define OMAP2430_PRCM_VOLTCTRL		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0050)
-#define OMAP2430_PRCM_VOLTST		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0054)
-#define OMAP2430_PRCM_CLKSRC_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0060)
-#define OMAP2430_PRCM_CLKOUT_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0070)
-#define OMAP2430_PRCM_CLKEMUL_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0078)
-#define OMAP2430_PRCM_CLKCFG_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0080)
-#define OMAP2430_PRCM_CLKCFG_STATUS	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0084)
-#define OMAP2430_PRCM_VOLTSETUP		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0090)
-#define OMAP2430_PRCM_CLKSSETUP		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0094)
-#define OMAP2430_PRCM_POLCTRL		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0098)
-
-/*
- * OMAP3-specific global PRM registers
- * Use __raw_{read,write}l() with these registers.
- *
- * With a few exceptions, these are the register names beginning with
- * PRM_* on 34xx.  (The exceptions are the IRQSTATUS and IRQENABLE
- * bits.)
- */
-
-#define OMAP3_PRM_REVISION_OFFSET	0x0004
-#define OMAP3430_PRM_REVISION		OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0004)
-#define OMAP3_PRM_SYSCONFIG_OFFSET	0x0014
-#define OMAP3430_PRM_SYSCONFIG		OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0014)
-
-#define OMAP3_PRM_IRQSTATUS_MPU_OFFSET	0x0018
-#define OMAP3430_PRM_IRQSTATUS_MPU	OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0018)
-#define OMAP3_PRM_IRQENABLE_MPU_OFFSET	0x001c
-#define OMAP3430_PRM_IRQENABLE_MPU	OMAP34XX_PRM_REGADDR(OCP_MOD, 0x001c)
-
-
-#define OMAP3_PRM_VC_SMPS_SA_OFFSET	0x0020
-#define OMAP3430_PRM_VC_SMPS_SA		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0020)
-#define OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET	0x0024
-#define OMAP3430_PRM_VC_SMPS_VOL_RA	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0024)
-#define OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET	0x0028
-#define OMAP3430_PRM_VC_SMPS_CMD_RA	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0028)
-#define OMAP3_PRM_VC_CMD_VAL_0_OFFSET	0x002c
-#define OMAP3430_PRM_VC_CMD_VAL_0	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x002c)
-#define OMAP3_PRM_VC_CMD_VAL_1_OFFSET	0x0030
-#define OMAP3430_PRM_VC_CMD_VAL_1	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0030)
-#define OMAP3_PRM_VC_CH_CONF_OFFSET	0x0034
-#define OMAP3430_PRM_VC_CH_CONF		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0034)
-#define OMAP3_PRM_VC_I2C_CFG_OFFSET	0x0038
-#define OMAP3430_PRM_VC_I2C_CFG		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0038)
-#define OMAP3_PRM_VC_BYPASS_VAL_OFFSET	0x003c
-#define OMAP3430_PRM_VC_BYPASS_VAL	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x003c)
-#define OMAP3_PRM_RSTCTRL_OFFSET	0x0050
-#define OMAP3430_PRM_RSTCTRL		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0050)
-#define OMAP3_PRM_RSTTIME_OFFSET	0x0054
-#define OMAP3430_PRM_RSTTIME		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0054)
-#define OMAP3_PRM_RSTST_OFFSET	0x0058
-#define OMAP3430_PRM_RSTST		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0058)
-#define OMAP3_PRM_VOLTCTRL_OFFSET	0x0060
-#define OMAP3430_PRM_VOLTCTRL		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0060)
-#define OMAP3_PRM_SRAM_PCHARGE_OFFSET	0x0064
-#define OMAP3430_PRM_SRAM_PCHARGE	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0064)
-#define OMAP3_PRM_CLKSRC_CTRL_OFFSET	0x0070
-#define OMAP3430_PRM_CLKSRC_CTRL	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0070)
-#define OMAP3_PRM_VOLTSETUP1_OFFSET	0x0090
-#define OMAP3430_PRM_VOLTSETUP1		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0090)
-#define OMAP3_PRM_VOLTOFFSET_OFFSET	0x0094
-#define OMAP3430_PRM_VOLTOFFSET		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0094)
-#define OMAP3_PRM_CLKSETUP_OFFSET	0x0098
-#define OMAP3430_PRM_CLKSETUP		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0098)
-#define OMAP3_PRM_POLCTRL_OFFSET	0x009c
-#define OMAP3430_PRM_POLCTRL		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x009c)
-#define OMAP3_PRM_VOLTSETUP2_OFFSET	0x00a0
-#define OMAP3430_PRM_VOLTSETUP2		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00a0)
-#define OMAP3_PRM_VP1_CONFIG_OFFSET	0x00b0
-#define OMAP3430_PRM_VP1_CONFIG		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b0)
-#define OMAP3_PRM_VP1_VSTEPMIN_OFFSET	0x00b4
-#define OMAP3430_PRM_VP1_VSTEPMIN	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b4)
-#define OMAP3_PRM_VP1_VSTEPMAX_OFFSET	0x00b8
-#define OMAP3430_PRM_VP1_VSTEPMAX	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b8)
-#define OMAP3_PRM_VP1_VLIMITTO_OFFSET	0x00bc
-#define OMAP3430_PRM_VP1_VLIMITTO	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00bc)
-#define OMAP3_PRM_VP1_VOLTAGE_OFFSET	0x00c0
-#define OMAP3430_PRM_VP1_VOLTAGE	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c0)
-#define OMAP3_PRM_VP1_STATUS_OFFSET	0x00c4
-#define OMAP3430_PRM_VP1_STATUS		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c4)
-#define OMAP3_PRM_VP2_CONFIG_OFFSET	0x00d0
-#define OMAP3430_PRM_VP2_CONFIG		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d0)
-#define OMAP3_PRM_VP2_VSTEPMIN_OFFSET	0x00d4
-#define OMAP3430_PRM_VP2_VSTEPMIN	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d4)
-#define OMAP3_PRM_VP2_VSTEPMAX_OFFSET	0x00d8
-#define OMAP3430_PRM_VP2_VSTEPMAX	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d8)
-#define OMAP3_PRM_VP2_VLIMITTO_OFFSET	0x00dc
-#define OMAP3430_PRM_VP2_VLIMITTO	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00dc)
-#define OMAP3_PRM_VP2_VOLTAGE_OFFSET	0x00e0
-#define OMAP3430_PRM_VP2_VOLTAGE	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0)
-#define OMAP3_PRM_VP2_STATUS_OFFSET	0x00e4
-#define OMAP3430_PRM_VP2_STATUS		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4)
-
-#define OMAP3_PRM_CLKSEL_OFFSET	0x0040
-#define OMAP3430_PRM_CLKSEL		OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040)
-#define OMAP3_PRM_CLKOUT_CTRL_OFFSET	0x0070
-#define OMAP3430_PRM_CLKOUT_CTRL	OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
-
 /*
  * Module specific PRM register offsets from PRM_BASE + domain offset
  *
@@ -200,66 +46,83 @@
 #define PM_EVGENONTIM					0x00d8
 #define PM_EVGENOFFTIM					0x00dc
 
-/* OMAP2xxx specific register offsets */
-#define OMAP24XX_PM_WKEN2				0x00a4
-#define OMAP24XX_PM_WKST2				0x00b4
-
-#define OMAP24XX_PRCM_IRQSTATUS_DSP			0x00f0	/* IVA mod */
-#define OMAP24XX_PRCM_IRQENABLE_DSP			0x00f4	/* IVA mod */
-#define OMAP24XX_PRCM_IRQSTATUS_IVA			0x00f8
-#define OMAP24XX_PRCM_IRQENABLE_IVA			0x00fc
 
-/* OMAP3 specific register offsets */
-#define OMAP3430ES2_PM_WKEN3				0x00f0
-#define OMAP3430ES2_PM_WKST3				0x00b8
-
-#define OMAP3430_PM_MPUGRPSEL				0x00a4
-#define OMAP3430_PM_MPUGRPSEL1				OMAP3430_PM_MPUGRPSEL
-#define OMAP3430ES2_PM_MPUGRPSEL3			0x00f8
-
-#define OMAP3430_PM_IVAGRPSEL				0x00a8
-#define OMAP3430_PM_IVAGRPSEL1				OMAP3430_PM_IVAGRPSEL
-#define OMAP3430ES2_PM_IVAGRPSEL3			0x00f4
-
-#define OMAP3430_PM_PREPWSTST				0x00e8
-
-#define OMAP3430_PRM_IRQSTATUS_IVA2			0x00f8
-#define OMAP3430_PRM_IRQENABLE_IVA2			0x00fc
+#ifndef __ASSEMBLER__
 
+#include <linux/io.h>
+#include "powerdomain.h"
 
-#ifndef __ASSEMBLER__
 /* Power/reset management domain register get/set */
-extern u32 omap2_prm_read_mod_reg(s16 module, u16 idx);
-extern void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx);
-extern u32 omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
-extern u32 omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx);
-extern u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx);
-extern u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask);
+static inline u32 omap2_prm_read_mod_reg(s16 module, u16 idx)
+{
+	return __raw_readl(prm_base + module + idx);
+}
+
+static inline void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx)
+{
+	__raw_writel(val, prm_base + module + idx);
+}
+
+/* Read-modify-write a register in a PRM module. Caller must lock */
+static inline u32 omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module,
+					     s16 idx)
+{
+	u32 v;
+
+	v = omap2_prm_read_mod_reg(module, idx);
+	v &= ~mask;
+	v |= bits;
+	omap2_prm_write_mod_reg(v, module, idx);
+
+	return v;
+}
+
+/* Read a PRM register, AND it, and shift the result down to bit 0 */
+static inline u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
+{
+	u32 v;
+
+	v = omap2_prm_read_mod_reg(domain, idx);
+	v &= mask;
+	v >>= __ffs(mask);
+
+	return v;
+}
+
+static inline u32 omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
+{
+	return omap2_prm_rmw_mod_reg_bits(bits, bits, module, idx);
+}
+
+static inline u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
+{
+	return omap2_prm_rmw_mod_reg_bits(bits, 0x0, module, idx);
+}
 
 /* These omap2_ PRM functions apply to both OMAP2 and 3 */
 extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
 extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
 extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift);
 
-/* OMAP3-specific VP functions */
-u32 omap3_prm_vp_check_txdone(u8 vp_id);
-void omap3_prm_vp_clear_txdone(u8 vp_id);
-
-/*
- * OMAP3 access functions for voltage controller (VC) and
- * voltage proccessor (VP) in the PRM.
- */
-extern u32 omap3_prm_vcvp_read(u8 offset);
-extern void omap3_prm_vcvp_write(u32 val, u8 offset);
-extern u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
-
-extern void omap3xxx_prm_reconfigure_io_chain(void);
-
-/* PRM interrupt-related functions */
-extern void omap3xxx_prm_read_pending_irqs(unsigned long *events);
-extern void omap3xxx_prm_ocp_barrier(void);
-extern void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask);
-extern void omap3xxx_prm_restore_irqen(u32 *saved_mask);
+extern int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
+extern int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
+extern int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm);
+extern int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
+				    u8 pwrst);
+extern int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
+				     u8 pwrst);
+extern int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank);
+extern int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank);
+extern int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
+extern int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm);
+
+extern int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1,
+				 struct clockdomain *clkdm2);
+extern int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1,
+				 struct clockdomain *clkdm2);
+extern int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1,
+				  struct clockdomain *clkdm2);
+extern int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm);
 
 #endif /* __ASSEMBLER */
 
@@ -289,6 +152,7 @@ extern void omap3xxx_prm_restore_irqen(u32 *saved_mask);
 /* Named PRCM_CLKSRC_CTRL on the 24XX */
 #define OMAP_SYSCLKDIV_SHIFT				6
 #define OMAP_SYSCLKDIV_MASK				(0x3 << 6)
+#define OMAP_SYSCLKDIV_WIDTH				2
 #define OMAP_AUTOEXTCLKMODE_SHIFT			3
 #define OMAP_AUTOEXTCLKMODE_MASK			(0x3 << 3)
 #define OMAP_SYSCLKSEL_SHIFT				0
@@ -348,7 +212,9 @@ extern void omap3xxx_prm_restore_irqen(u32 *saved_mask);
  *
  * 3430: RM_RSTST_CORE, RM_RSTST_EMU
  */
+#define OMAP_GLOBALWARM_RST_SHIFT			1
 #define OMAP_GLOBALWARM_RST_MASK			(1 << 1)
+#define OMAP_GLOBALCOLD_RST_SHIFT			0
 #define OMAP_GLOBALCOLD_RST_MASK			(1 << 0)
 
 /*
@@ -376,11 +242,4 @@ extern void omap3xxx_prm_restore_irqen(u32 *saved_mask);
 #define OMAP_LOGICRETSTATE_MASK				(1 << 2)
 
 
-/*
- * MAX_MODULE_HARDRESET_WAIT: Maximum microseconds to wait for an OMAP
- * submodule to exit hardreset
- */
-#define MAX_MODULE_HARDRESET_WAIT		10000
-
-
 #endif
diff --git a/arch/arm/mach-omap2/prm33xx.c b/arch/arm/mach-omap2/prm33xx.c
index e7dbb6c..1ac7388 100644
--- a/arch/arm/mach-omap2/prm33xx.c
+++ b/arch/arm/mach-omap2/prm33xx.c
@@ -19,9 +19,8 @@
 #include <linux/err.h>
 #include <linux/io.h>
 
-#include <plat/common.h>
-
 #include "common.h"
+#include "powerdomain.h"
 #include "prm33xx.h"
 #include "prm-regbits-33xx.h"
 
@@ -133,3 +132,204 @@ int am33xx_prm_deassert_hardreset(u8 shift, s16 inst,
 
 	return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
 }
+
+static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
+{
+	am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK,
+				(pwrst << OMAP_POWERSTATE_SHIFT),
+				pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+	return 0;
+}
+
+static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
+{
+	u32 v;
+
+	v = am33xx_prm_read_reg(pwrdm->prcm_offs,  pwrdm->pwrstctrl_offs);
+	v &= OMAP_POWERSTATE_MASK;
+	v >>= OMAP_POWERSTATE_SHIFT;
+
+	return v;
+}
+
+static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
+{
+	u32 v;
+
+	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
+	v &= OMAP_POWERSTATEST_MASK;
+	v >>= OMAP_POWERSTATEST_SHIFT;
+
+	return v;
+}
+
+static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
+{
+	u32 v;
+
+	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
+	v &= AM33XX_LASTPOWERSTATEENTERED_MASK;
+	v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT;
+
+	return v;
+}
+
+static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
+{
+	am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK,
+				(1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT),
+				pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+	return 0;
+}
+
+static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
+{
+	am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK,
+				AM33XX_LASTPOWERSTATEENTERED_MASK,
+				pwrdm->prcm_offs, pwrdm->pwrstst_offs);
+	return 0;
+}
+
+static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
+{
+	u32 m;
+
+	m = pwrdm->logicretstate_mask;
+	if (!m)
+		return -EINVAL;
+
+	am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
+				pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+
+	return 0;
+}
+
+static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
+{
+	u32 v;
+
+	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
+	v &= AM33XX_LOGICSTATEST_MASK;
+	v >>= AM33XX_LOGICSTATEST_SHIFT;
+
+	return v;
+}
+
+static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
+{
+	u32 v, m;
+
+	m = pwrdm->logicretstate_mask;
+	if (!m)
+		return -EINVAL;
+
+	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+	v &= m;
+	v >>= __ffs(m);
+
+	return v;
+}
+
+static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
+		u8 pwrst)
+{
+	u32 m;
+
+	m = pwrdm->mem_on_mask[bank];
+	if (!m)
+		return -EINVAL;
+
+	am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
+				pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+
+	return 0;
+}
+
+static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
+					u8 pwrst)
+{
+	u32 m;
+
+	m = pwrdm->mem_ret_mask[bank];
+	if (!m)
+		return -EINVAL;
+
+	am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
+				pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+
+	return 0;
+}
+
+static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
+{
+	u32 m, v;
+
+	m = pwrdm->mem_pwrst_mask[bank];
+	if (!m)
+		return -EINVAL;
+
+	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
+	v &= m;
+	v >>= __ffs(m);
+
+	return v;
+}
+
+static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
+{
+	u32 m, v;
+
+	m = pwrdm->mem_retst_mask[bank];
+	if (!m)
+		return -EINVAL;
+
+	v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+	v &= m;
+	v >>= __ffs(m);
+
+	return v;
+}
+
+static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm)
+{
+	u32 c = 0;
+
+	/*
+	 * REVISIT: pwrdm_wait_transition() may be better implemented
+	 * via a callback and a periodic timer check -- how long do we expect
+	 * powerdomain transitions to take?
+	 */
+
+	/* XXX Is this udelay() value meaningful? */
+	while ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs)
+			& OMAP_INTRANSITION_MASK) &&
+			(c++ < PWRDM_TRANSITION_BAILOUT))
+		udelay(1);
+
+	if (c > PWRDM_TRANSITION_BAILOUT) {
+		pr_err("powerdomain: %s: waited too long to complete transition\n",
+		       pwrdm->name);
+		return -EAGAIN;
+	}
+
+	pr_debug("powerdomain: completed transition in %d loops\n", c);
+
+	return 0;
+}
+
+struct pwrdm_ops am33xx_pwrdm_operations = {
+	.pwrdm_set_next_pwrst		= am33xx_pwrdm_set_next_pwrst,
+	.pwrdm_read_next_pwrst		= am33xx_pwrdm_read_next_pwrst,
+	.pwrdm_read_pwrst		= am33xx_pwrdm_read_pwrst,
+	.pwrdm_read_prev_pwrst		= am33xx_pwrdm_read_prev_pwrst,
+	.pwrdm_set_logic_retst		= am33xx_pwrdm_set_logic_retst,
+	.pwrdm_read_logic_pwrst		= am33xx_pwrdm_read_logic_pwrst,
+	.pwrdm_read_logic_retst		= am33xx_pwrdm_read_logic_retst,
+	.pwrdm_clear_all_prev_pwrst	= am33xx_pwrdm_clear_all_prev_pwrst,
+	.pwrdm_set_lowpwrstchange	= am33xx_pwrdm_set_lowpwrstchange,
+	.pwrdm_read_mem_pwrst		= am33xx_pwrdm_read_mem_pwrst,
+	.pwrdm_read_mem_retst		= am33xx_pwrdm_read_mem_retst,
+	.pwrdm_set_mem_onst		= am33xx_pwrdm_set_mem_onst,
+	.pwrdm_set_mem_retst		= am33xx_pwrdm_set_mem_retst,
+	.pwrdm_wait_transition		= am33xx_pwrdm_wait_transition,
+};
diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c
new file mode 100644
index 0000000..b86116c
--- /dev/null
+++ b/arch/arm/mach-omap2/prm3xxx.c
@@ -0,0 +1,417 @@
+/*
+ * OMAP3xxx PRM module functions
+ *
+ * Copyright (C) 2010-2012 Texas Instruments, Inc.
+ * Copyright (C) 2010 Nokia Corporation
+ * Benoît Cousson
+ * Paul Walmsley
+ * Rajendra Nayak <rnayak@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#include "common.h"
+#include <plat/cpu.h>
+
+#include "vp.h"
+#include "powerdomain.h"
+#include "prm3xxx.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "prm-regbits-34xx.h"
+
+static const struct omap_prcm_irq omap3_prcm_irqs[] = {
+	OMAP_PRCM_IRQ("wkup",	0,	0),
+	OMAP_PRCM_IRQ("io",	9,	1),
+};
+
+static struct omap_prcm_irq_setup omap3_prcm_irq_setup = {
+	.ack			= OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
+	.mask			= OMAP3_PRM_IRQENABLE_MPU_OFFSET,
+	.nr_regs		= 1,
+	.irqs			= omap3_prcm_irqs,
+	.nr_irqs		= ARRAY_SIZE(omap3_prcm_irqs),
+	.irq			= 11 + OMAP_INTC_START,
+	.read_pending_irqs	= &omap3xxx_prm_read_pending_irqs,
+	.ocp_barrier		= &omap3xxx_prm_ocp_barrier,
+	.save_and_clear_irqen	= &omap3xxx_prm_save_and_clear_irqen,
+	.restore_irqen		= &omap3xxx_prm_restore_irqen,
+};
+
+/*
+ * omap3_prm_reset_src_map - map from bits in the PRM_RSTST hardware
+ *   register (which are specific to OMAP3xxx SoCs) to reset source ID
+ *   bit shifts (which is an OMAP SoC-independent enumeration)
+ */
+static struct prm_reset_src_map omap3xxx_prm_reset_src_map[] = {
+	{ OMAP3430_GLOBAL_COLD_RST_SHIFT, OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
+	{ OMAP3430_GLOBAL_SW_RST_SHIFT, OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
+	{ OMAP3430_SECURITY_VIOL_RST_SHIFT, OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
+	{ OMAP3430_MPU_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
+	{ OMAP3430_SECURE_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
+	{ OMAP3430_EXTERNAL_WARM_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
+	{ OMAP3430_VDD1_VOLTAGE_MANAGER_RST_SHIFT,
+	  OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT },
+	{ OMAP3430_VDD2_VOLTAGE_MANAGER_RST_SHIFT,
+	  OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT },
+	{ OMAP3430_ICEPICK_RST_SHIFT, OMAP_ICEPICK_RST_SRC_ID_SHIFT },
+	{ OMAP3430_ICECRUSHER_RST_SHIFT, OMAP_ICECRUSHER_RST_SRC_ID_SHIFT },
+	{ -1, -1 },
+};
+
+/* PRM VP */
+
+/*
+ * struct omap3_vp - OMAP3 VP register access description.
+ * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
+ */
+struct omap3_vp {
+	u32 tranxdone_status;
+};
+
+static struct omap3_vp omap3_vp[] = {
+	[OMAP3_VP_VDD_MPU_ID] = {
+		.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
+	},
+	[OMAP3_VP_VDD_CORE_ID] = {
+		.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
+	},
+};
+
+#define MAX_VP_ID ARRAY_SIZE(omap3_vp);
+
+u32 omap3_prm_vp_check_txdone(u8 vp_id)
+{
+	struct omap3_vp *vp = &omap3_vp[vp_id];
+	u32 irqstatus;
+
+	irqstatus = omap2_prm_read_mod_reg(OCP_MOD,
+					   OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+	return irqstatus & vp->tranxdone_status;
+}
+
+void omap3_prm_vp_clear_txdone(u8 vp_id)
+{
+	struct omap3_vp *vp = &omap3_vp[vp_id];
+
+	omap2_prm_write_mod_reg(vp->tranxdone_status,
+				OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+}
+
+u32 omap3_prm_vcvp_read(u8 offset)
+{
+	return omap2_prm_read_mod_reg(OMAP3430_GR_MOD, offset);
+}
+
+void omap3_prm_vcvp_write(u32 val, u8 offset)
+{
+	omap2_prm_write_mod_reg(val, OMAP3430_GR_MOD, offset);
+}
+
+u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
+{
+	return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset);
+}
+
+/**
+ * omap3xxx_prm_dpll3_reset - use DPLL3 reset to reboot the OMAP SoC
+ *
+ * Set the DPLL3 reset bit, which should reboot the SoC.  This is the
+ * recommended way to restart the SoC, considering Errata i520.  No
+ * return value.
+ */
+void omap3xxx_prm_dpll3_reset(void)
+{
+	omap2_prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, OMAP3430_GR_MOD,
+				   OMAP2_RM_RSTCTRL);
+	/* OCP barrier */
+	omap2_prm_read_mod_reg(OMAP3430_GR_MOD, OMAP2_RM_RSTCTRL);
+}
+
+/**
+ * omap3xxx_prm_read_pending_irqs - read pending PRM MPU IRQs into @events
+ * @events: ptr to a u32, preallocated by caller
+ *
+ * Read PRM_IRQSTATUS_MPU bits, AND'ed with the currently-enabled PRM
+ * MPU IRQs, and store the result into the u32 pointed to by @events.
+ * No return value.
+ */
+void omap3xxx_prm_read_pending_irqs(unsigned long *events)
+{
+	u32 mask, st;
+
+	/* XXX Can the mask read be avoided (e.g., can it come from RAM?) */
+	mask = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
+	st = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+
+	events[0] = mask & st;
+}
+
+/**
+ * omap3xxx_prm_ocp_barrier - force buffered MPU writes to the PRM to complete
+ *
+ * Force any buffered writes to the PRM IP block to complete.  Needed
+ * by the PRM IRQ handler, which reads and writes directly to the IP
+ * block, to avoid race conditions after acknowledging or clearing IRQ
+ * bits.  No return value.
+ */
+void omap3xxx_prm_ocp_barrier(void)
+{
+	omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET);
+}
+
+/**
+ * omap3xxx_prm_save_and_clear_irqen - save/clear PRM_IRQENABLE_MPU reg
+ * @saved_mask: ptr to a u32 array to save IRQENABLE bits
+ *
+ * Save the PRM_IRQENABLE_MPU register to @saved_mask.  @saved_mask
+ * must be allocated by the caller.  Intended to be used in the PRM
+ * interrupt handler suspend callback.  The OCP barrier is needed to
+ * ensure the write to disable PRM interrupts reaches the PRM before
+ * returning; otherwise, spurious interrupts might occur.  No return
+ * value.
+ */
+void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask)
+{
+	saved_mask[0] = omap2_prm_read_mod_reg(OCP_MOD,
+					       OMAP3_PRM_IRQENABLE_MPU_OFFSET);
+	omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
+
+	/* OCP barrier */
+	omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET);
+}
+
+/**
+ * omap3xxx_prm_restore_irqen - set PRM_IRQENABLE_MPU register from args
+ * @saved_mask: ptr to a u32 array of IRQENABLE bits saved previously
+ *
+ * Restore the PRM_IRQENABLE_MPU register from @saved_mask.  Intended
+ * to be used in the PRM interrupt handler resume callback to restore
+ * values saved by omap3xxx_prm_save_and_clear_irqen().  No OCP
+ * barrier should be needed here; any pending PRM interrupts will fire
+ * once the writes reach the PRM.  No return value.
+ */
+void omap3xxx_prm_restore_irqen(u32 *saved_mask)
+{
+	omap2_prm_write_mod_reg(saved_mask[0], OCP_MOD,
+				OMAP3_PRM_IRQENABLE_MPU_OFFSET);
+}
+
+/**
+ * omap3xxx_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain
+ *
+ * Clear any previously-latched I/O wakeup events and ensure that the
+ * I/O wakeup gates are aligned with the current mux settings.  Works
+ * by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then
+ * deasserting WUCLKIN and clearing the ST_IO_CHAIN WKST bit.  No
+ * return value.
+ */
+void omap3xxx_prm_reconfigure_io_chain(void)
+{
+	int i = 0;
+
+	omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+				   PM_WKEN);
+
+	omap_test_timeout(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST) &
+			  OMAP3430_ST_IO_CHAIN_MASK,
+			  MAX_IOPAD_LATCH_TIME, i);
+	if (i == MAX_IOPAD_LATCH_TIME)
+		pr_warn("PRM: I/O chain clock line assertion timed out\n");
+
+	omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+				     PM_WKEN);
+
+	omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK, WKUP_MOD,
+				   PM_WKST);
+
+	omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST);
+}
+
+/**
+ * omap3xxx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches
+ *
+ * Activates the I/O wakeup event latches and allows events logged by
+ * those latches to signal a wakeup event to the PRCM.  For I/O
+ * wakeups to occur, WAKEUPENABLE bits must be set in the pad mux
+ * registers, and omap3xxx_prm_reconfigure_io_chain() must be called.
+ * No return value.
+ */
+static void __init omap3xxx_prm_enable_io_wakeup(void)
+{
+	if (omap3_has_io_wakeup())
+		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
+					   PM_WKEN);
+}
+
+/**
+ * omap3xxx_prm_read_reset_sources - return the last SoC reset source
+ *
+ * Return a u32 representing the last reset sources of the SoC.  The
+ * returned reset source bits are standardized across OMAP SoCs.
+ */
+static u32 omap3xxx_prm_read_reset_sources(void)
+{
+	struct prm_reset_src_map *p;
+	u32 r = 0;
+	u32 v;
+
+	v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST);
+
+	p = omap3xxx_prm_reset_src_map;
+	while (p->reg_shift >= 0 && p->std_shift >= 0) {
+		if (v & (1 << p->reg_shift))
+			r |= 1 << p->std_shift;
+		p++;
+	}
+
+	return r;
+}
+
+/* Powerdomain low-level functions */
+
+/* Applicable only for OMAP3. Not supported on OMAP2 */
+static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
+{
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+					     OMAP3430_PM_PREPWSTST,
+					     OMAP3430_LASTPOWERSTATEENTERED_MASK);
+}
+
+static int omap3_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
+{
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+					     OMAP2_PM_PWSTST,
+					     OMAP3430_LOGICSTATEST_MASK);
+}
+
+static int omap3_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
+{
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+					     OMAP2_PM_PWSTCTRL,
+					     OMAP3430_LOGICSTATEST_MASK);
+}
+
+static int omap3_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
+{
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+					     OMAP3430_PM_PREPWSTST,
+					     OMAP3430_LASTLOGICSTATEENTERED_MASK);
+}
+
+static int omap3_get_mem_bank_lastmemst_mask(u8 bank)
+{
+	switch (bank) {
+	case 0:
+		return OMAP3430_LASTMEM1STATEENTERED_MASK;
+	case 1:
+		return OMAP3430_LASTMEM2STATEENTERED_MASK;
+	case 2:
+		return OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
+	case 3:
+		return OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
+	default:
+		WARN_ON(1); /* should never happen */
+		return -EEXIST;
+	}
+	return 0;
+}
+
+static int omap3_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
+{
+	u32 m;
+
+	m = omap3_get_mem_bank_lastmemst_mask(bank);
+
+	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+				OMAP3430_PM_PREPWSTST, m);
+}
+
+static int omap3_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
+{
+	omap2_prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
+	return 0;
+}
+
+static int omap3_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
+{
+	return omap2_prm_rmw_mod_reg_bits(0,
+					  1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
+					  pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
+}
+
+static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
+{
+	return omap2_prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
+					  0, pwrdm->prcm_offs,
+					  OMAP2_PM_PWSTCTRL);
+}
+
+struct pwrdm_ops omap3_pwrdm_operations = {
+	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
+	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
+	.pwrdm_read_pwrst	= omap2_pwrdm_read_pwrst,
+	.pwrdm_read_prev_pwrst	= omap3_pwrdm_read_prev_pwrst,
+	.pwrdm_set_logic_retst	= omap2_pwrdm_set_logic_retst,
+	.pwrdm_read_logic_pwrst	= omap3_pwrdm_read_logic_pwrst,
+	.pwrdm_read_logic_retst	= omap3_pwrdm_read_logic_retst,
+	.pwrdm_read_prev_logic_pwrst	= omap3_pwrdm_read_prev_logic_pwrst,
+	.pwrdm_set_mem_onst	= omap2_pwrdm_set_mem_onst,
+	.pwrdm_set_mem_retst	= omap2_pwrdm_set_mem_retst,
+	.pwrdm_read_mem_pwrst	= omap2_pwrdm_read_mem_pwrst,
+	.pwrdm_read_mem_retst	= omap2_pwrdm_read_mem_retst,
+	.pwrdm_read_prev_mem_pwrst	= omap3_pwrdm_read_prev_mem_pwrst,
+	.pwrdm_clear_all_prev_pwrst	= omap3_pwrdm_clear_all_prev_pwrst,
+	.pwrdm_enable_hdwr_sar	= omap3_pwrdm_enable_hdwr_sar,
+	.pwrdm_disable_hdwr_sar	= omap3_pwrdm_disable_hdwr_sar,
+	.pwrdm_wait_transition	= omap2_pwrdm_wait_transition,
+};
+
+/*
+ *
+ */
+
+static struct prm_ll_data omap3xxx_prm_ll_data = {
+	.read_reset_sources = &omap3xxx_prm_read_reset_sources,
+};
+
+static int __init omap3xxx_prm_init(void)
+{
+	int ret;
+
+	if (!cpu_is_omap34xx())
+		return 0;
+
+	ret = prm_register(&omap3xxx_prm_ll_data);
+	if (ret)
+		return ret;
+
+	omap3xxx_prm_enable_io_wakeup();
+	ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
+	if (!ret)
+		irq_set_status_flags(omap_prcm_event_to_irq("io"),
+				     IRQ_NOAUTOEN);
+
+
+	return ret;
+}
+subsys_initcall(omap3xxx_prm_init);
+
+static void __exit omap3xxx_prm_exit(void)
+{
+	if (!cpu_is_omap34xx())
+		return;
+
+	/* Should never happen */
+	WARN(prm_unregister(&omap3xxx_prm_ll_data),
+	     "%s: prm_ll_data function pointer mismatch\n", __func__);
+}
+__exitcall(omap3xxx_prm_exit);
diff --git a/arch/arm/mach-omap2/prm3xxx.h b/arch/arm/mach-omap2/prm3xxx.h
new file mode 100644
index 0000000..10cd41a
--- /dev/null
+++ b/arch/arm/mach-omap2/prm3xxx.h
@@ -0,0 +1,162 @@
+/*
+ * OMAP3xxx Power/Reset Management (PRM) register definitions
+ *
+ * Copyright (C) 2007-2009, 2011-2012 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The PRM hardware modules on the OMAP2/3 are quite similar to each
+ * other.  The PRM on OMAP4 has a new register layout, and is handled
+ * in a separate file.
+ */
+#ifndef __ARCH_ARM_MACH_OMAP2_PRM3XXX_H
+#define __ARCH_ARM_MACH_OMAP2_PRM3XXX_H
+
+#include "prcm-common.h"
+#include "prm.h"
+#include "prm2xxx_3xxx.h"
+
+#define OMAP34XX_PRM_REGADDR(module, reg)				\
+		OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE + (module) + (reg))
+
+
+/*
+ * OMAP3-specific global PRM registers
+ * Use __raw_{read,write}l() with these registers.
+ *
+ * With a few exceptions, these are the register names beginning with
+ * PRM_* on 34xx.  (The exceptions are the IRQSTATUS and IRQENABLE
+ * bits.)
+ */
+
+#define OMAP3_PRM_REVISION_OFFSET	0x0004
+#define OMAP3430_PRM_REVISION		OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0004)
+#define OMAP3_PRM_SYSCONFIG_OFFSET	0x0014
+#define OMAP3430_PRM_SYSCONFIG		OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0014)
+
+#define OMAP3_PRM_IRQSTATUS_MPU_OFFSET	0x0018
+#define OMAP3430_PRM_IRQSTATUS_MPU	OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0018)
+#define OMAP3_PRM_IRQENABLE_MPU_OFFSET	0x001c
+#define OMAP3430_PRM_IRQENABLE_MPU	OMAP34XX_PRM_REGADDR(OCP_MOD, 0x001c)
+
+
+#define OMAP3_PRM_VC_SMPS_SA_OFFSET	0x0020
+#define OMAP3430_PRM_VC_SMPS_SA		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0020)
+#define OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET	0x0024
+#define OMAP3430_PRM_VC_SMPS_VOL_RA	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0024)
+#define OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET	0x0028
+#define OMAP3430_PRM_VC_SMPS_CMD_RA	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0028)
+#define OMAP3_PRM_VC_CMD_VAL_0_OFFSET	0x002c
+#define OMAP3430_PRM_VC_CMD_VAL_0	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x002c)
+#define OMAP3_PRM_VC_CMD_VAL_1_OFFSET	0x0030
+#define OMAP3430_PRM_VC_CMD_VAL_1	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0030)
+#define OMAP3_PRM_VC_CH_CONF_OFFSET	0x0034
+#define OMAP3430_PRM_VC_CH_CONF		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0034)
+#define OMAP3_PRM_VC_I2C_CFG_OFFSET	0x0038
+#define OMAP3430_PRM_VC_I2C_CFG		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0038)
+#define OMAP3_PRM_VC_BYPASS_VAL_OFFSET	0x003c
+#define OMAP3430_PRM_VC_BYPASS_VAL	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x003c)
+#define OMAP3_PRM_RSTCTRL_OFFSET	0x0050
+#define OMAP3430_PRM_RSTCTRL		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0050)
+#define OMAP3_PRM_RSTTIME_OFFSET	0x0054
+#define OMAP3430_PRM_RSTTIME		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0054)
+#define OMAP3_PRM_RSTST_OFFSET	0x0058
+#define OMAP3430_PRM_RSTST		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0058)
+#define OMAP3_PRM_VOLTCTRL_OFFSET	0x0060
+#define OMAP3430_PRM_VOLTCTRL		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0060)
+#define OMAP3_PRM_SRAM_PCHARGE_OFFSET	0x0064
+#define OMAP3430_PRM_SRAM_PCHARGE	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0064)
+#define OMAP3_PRM_CLKSRC_CTRL_OFFSET	0x0070
+#define OMAP3430_PRM_CLKSRC_CTRL	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0070)
+#define OMAP3_PRM_VOLTSETUP1_OFFSET	0x0090
+#define OMAP3430_PRM_VOLTSETUP1		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0090)
+#define OMAP3_PRM_VOLTOFFSET_OFFSET	0x0094
+#define OMAP3430_PRM_VOLTOFFSET		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0094)
+#define OMAP3_PRM_CLKSETUP_OFFSET	0x0098
+#define OMAP3430_PRM_CLKSETUP		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0098)
+#define OMAP3_PRM_POLCTRL_OFFSET	0x009c
+#define OMAP3430_PRM_POLCTRL		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x009c)
+#define OMAP3_PRM_VOLTSETUP2_OFFSET	0x00a0
+#define OMAP3430_PRM_VOLTSETUP2		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00a0)
+#define OMAP3_PRM_VP1_CONFIG_OFFSET	0x00b0
+#define OMAP3430_PRM_VP1_CONFIG		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b0)
+#define OMAP3_PRM_VP1_VSTEPMIN_OFFSET	0x00b4
+#define OMAP3430_PRM_VP1_VSTEPMIN	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b4)
+#define OMAP3_PRM_VP1_VSTEPMAX_OFFSET	0x00b8
+#define OMAP3430_PRM_VP1_VSTEPMAX	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b8)
+#define OMAP3_PRM_VP1_VLIMITTO_OFFSET	0x00bc
+#define OMAP3430_PRM_VP1_VLIMITTO	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00bc)
+#define OMAP3_PRM_VP1_VOLTAGE_OFFSET	0x00c0
+#define OMAP3430_PRM_VP1_VOLTAGE	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c0)
+#define OMAP3_PRM_VP1_STATUS_OFFSET	0x00c4
+#define OMAP3430_PRM_VP1_STATUS		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c4)
+#define OMAP3_PRM_VP2_CONFIG_OFFSET	0x00d0
+#define OMAP3430_PRM_VP2_CONFIG		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d0)
+#define OMAP3_PRM_VP2_VSTEPMIN_OFFSET	0x00d4
+#define OMAP3430_PRM_VP2_VSTEPMIN	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d4)
+#define OMAP3_PRM_VP2_VSTEPMAX_OFFSET	0x00d8
+#define OMAP3430_PRM_VP2_VSTEPMAX	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d8)
+#define OMAP3_PRM_VP2_VLIMITTO_OFFSET	0x00dc
+#define OMAP3430_PRM_VP2_VLIMITTO	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00dc)
+#define OMAP3_PRM_VP2_VOLTAGE_OFFSET	0x00e0
+#define OMAP3430_PRM_VP2_VOLTAGE	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0)
+#define OMAP3_PRM_VP2_STATUS_OFFSET	0x00e4
+#define OMAP3430_PRM_VP2_STATUS		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4)
+
+#define OMAP3_PRM_CLKSEL_OFFSET	0x0040
+#define OMAP3430_PRM_CLKSEL		OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040)
+#define OMAP3_PRM_CLKOUT_CTRL_OFFSET	0x0070
+#define OMAP3430_PRM_CLKOUT_CTRL	OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
+
+/* OMAP3 specific register offsets */
+#define OMAP3430ES2_PM_WKEN3				0x00f0
+#define OMAP3430ES2_PM_WKST3				0x00b8
+
+#define OMAP3430_PM_MPUGRPSEL				0x00a4
+#define OMAP3430_PM_MPUGRPSEL1				OMAP3430_PM_MPUGRPSEL
+#define OMAP3430ES2_PM_MPUGRPSEL3			0x00f8
+
+#define OMAP3430_PM_IVAGRPSEL				0x00a8
+#define OMAP3430_PM_IVAGRPSEL1				OMAP3430_PM_IVAGRPSEL
+#define OMAP3430ES2_PM_IVAGRPSEL3			0x00f4
+
+#define OMAP3430_PM_PREPWSTST				0x00e8
+
+#define OMAP3430_PRM_IRQSTATUS_IVA2			0x00f8
+#define OMAP3430_PRM_IRQENABLE_IVA2			0x00fc
+
+
+#ifndef __ASSEMBLER__
+
+/* OMAP3-specific VP functions */
+u32 omap3_prm_vp_check_txdone(u8 vp_id);
+void omap3_prm_vp_clear_txdone(u8 vp_id);
+
+/*
+ * OMAP3 access functions for voltage controller (VC) and
+ * voltage proccessor (VP) in the PRM.
+ */
+extern u32 omap3_prm_vcvp_read(u8 offset);
+extern void omap3_prm_vcvp_write(u32 val, u8 offset);
+extern u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
+
+extern void omap3xxx_prm_reconfigure_io_chain(void);
+
+/* PRM interrupt-related functions */
+extern void omap3xxx_prm_read_pending_irqs(unsigned long *events);
+extern void omap3xxx_prm_ocp_barrier(void);
+extern void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask);
+extern void omap3xxx_prm_restore_irqen(u32 *saved_mask);
+
+extern void omap3xxx_prm_dpll3_reset(void);
+
+extern u32 omap3xxx_prm_get_reset_sources(void);
+
+#endif /* __ASSEMBLER */
+
+
+#endif
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
index f0c4d5f..6d3467a 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -1,10 +1,11 @@
 /*
  * OMAP4 PRM module functions
  *
- * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011-2012 Texas Instruments, Inc.
  * Copyright (C) 2010 Nokia Corporation
  * Benoît Cousson
  * Paul Walmsley
+ * Rajendra Nayak <rnayak@ti.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -17,7 +18,6 @@
 #include <linux/err.h>
 #include <linux/io.h>
 
-#include <plat/prcm.h>
 
 #include "soc.h"
 #include "iomap.h"
@@ -27,6 +27,9 @@
 #include "prm-regbits-44xx.h"
 #include "prcm44xx.h"
 #include "prminst44xx.h"
+#include "powerdomain.h"
+
+/* Static data */
 
 static const struct omap_prcm_irq omap4_prcm_irqs[] = {
 	OMAP_PRCM_IRQ("wkup",   0,      0),
@@ -46,6 +49,33 @@ static struct omap_prcm_irq_setup omap4_prcm_irq_setup = {
 	.restore_irqen		= &omap44xx_prm_restore_irqen,
 };
 
+/*
+ * omap44xx_prm_reset_src_map - map from bits in the PRM_RSTST
+ *   hardware register (which are specific to OMAP44xx SoCs) to reset
+ *   source ID bit shifts (which is an OMAP SoC-independent
+ *   enumeration)
+ */
+static struct prm_reset_src_map omap44xx_prm_reset_src_map[] = {
+	{ OMAP4430_RST_GLOBAL_WARM_SW_SHIFT,
+	  OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
+	{ OMAP4430_RST_GLOBAL_COLD_SW_SHIFT,
+	  OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
+	{ OMAP4430_MPU_SECURITY_VIOL_RST_SHIFT,
+	  OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
+	{ OMAP4430_MPU_WDT_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
+	{ OMAP4430_SECURE_WDT_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
+	{ OMAP4430_EXTERNAL_WARM_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
+	{ OMAP4430_VDD_MPU_VOLT_MGR_RST_SHIFT,
+	  OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT },
+	{ OMAP4430_VDD_IVA_VOLT_MGR_RST_SHIFT,
+	  OMAP_VDD_IVA_VM_RST_SRC_ID_SHIFT },
+	{ OMAP4430_VDD_CORE_VOLT_MGR_RST_SHIFT,
+	  OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT },
+	{ OMAP4430_ICEPICK_RST_SHIFT, OMAP_ICEPICK_RST_SRC_ID_SHIFT },
+	{ OMAP4430_C2C_RST_SHIFT, OMAP_C2C_RST_SRC_ID_SHIFT },
+	{ -1, -1 },
+};
+
 /* PRM low-level functions */
 
 /* Read a register in a CM/PRM instance in the PRM module */
@@ -291,12 +321,324 @@ static void __init omap44xx_prm_enable_io_wakeup(void)
 				    OMAP4_PRM_IO_PMCTRL_OFFSET);
 }
 
-static int __init omap4xxx_prcm_init(void)
+/**
+ * omap44xx_prm_read_reset_sources - return the last SoC reset source
+ *
+ * Return a u32 representing the last reset sources of the SoC.  The
+ * returned reset source bits are standardized across OMAP SoCs.
+ */
+static u32 omap44xx_prm_read_reset_sources(void)
+{
+	struct prm_reset_src_map *p;
+	u32 r = 0;
+	u32 v;
+
+	v = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
+				    OMAP4_RM_RSTST);
+
+	p = omap44xx_prm_reset_src_map;
+	while (p->reg_shift >= 0 && p->std_shift >= 0) {
+		if (v & (1 << p->reg_shift))
+			r |= 1 << p->std_shift;
+		p++;
+	}
+
+	return r;
+}
+
+/* Powerdomain low-level functions */
+
+static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
+{
+	omap4_prminst_rmw_inst_reg_bits(OMAP_POWERSTATE_MASK,
+					(pwrst << OMAP_POWERSTATE_SHIFT),
+					pwrdm->prcm_partition,
+					pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
+	return 0;
+}
+
+static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
+{
+	u32 v;
+
+	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTCTRL);
+	v &= OMAP_POWERSTATE_MASK;
+	v >>= OMAP_POWERSTATE_SHIFT;
+
+	return v;
+}
+
+static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm)
+{
+	u32 v;
+
+	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTST);
+	v &= OMAP_POWERSTATEST_MASK;
+	v >>= OMAP_POWERSTATEST_SHIFT;
+
+	return v;
+}
+
+static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
+{
+	u32 v;
+
+	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTST);
+	v &= OMAP4430_LASTPOWERSTATEENTERED_MASK;
+	v >>= OMAP4430_LASTPOWERSTATEENTERED_SHIFT;
+
+	return v;
+}
+
+static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
+{
+	omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK,
+					(1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT),
+					pwrdm->prcm_partition,
+					pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
+	return 0;
+}
+
+static int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
+{
+	omap4_prminst_rmw_inst_reg_bits(OMAP4430_LASTPOWERSTATEENTERED_MASK,
+					OMAP4430_LASTPOWERSTATEENTERED_MASK,
+					pwrdm->prcm_partition,
+					pwrdm->prcm_offs, OMAP4_PM_PWSTST);
+	return 0;
+}
+
+static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
+{
+	u32 v;
+
+	v = pwrst << __ffs(OMAP4430_LOGICRETSTATE_MASK);
+	omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOGICRETSTATE_MASK, v,
+					pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTCTRL);
+
+	return 0;
+}
+
+static int omap4_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
+				    u8 pwrst)
+{
+	u32 m;
+
+	m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
+
+	omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
+					pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTCTRL);
+
+	return 0;
+}
+
+static int omap4_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
+				     u8 pwrst)
+{
+	u32 m;
+
+	m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
+
+	omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
+					pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTCTRL);
+
+	return 0;
+}
+
+static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
+{
+	u32 v;
+
+	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTST);
+	v &= OMAP4430_LOGICSTATEST_MASK;
+	v >>= OMAP4430_LOGICSTATEST_SHIFT;
+
+	return v;
+}
+
+static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
 {
-	if (cpu_is_omap44xx()) {
-		omap44xx_prm_enable_io_wakeup();
-		return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
+	u32 v;
+
+	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTCTRL);
+	v &= OMAP4430_LOGICRETSTATE_MASK;
+	v >>= OMAP4430_LOGICRETSTATE_SHIFT;
+
+	return v;
+}
+
+/**
+ * omap4_pwrdm_read_prev_logic_pwrst - read the previous logic powerstate
+ * @pwrdm: struct powerdomain * to read the state for
+ *
+ * Reads the previous logic powerstate for a powerdomain. This
+ * function must determine the previous logic powerstate by first
+ * checking the previous powerstate for the domain. If that was OFF,
+ * then logic has been lost. If previous state was RETENTION, the
+ * function reads the setting for the next retention logic state to
+ * see the actual value.  In every other case, the logic is
+ * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
+ * depending whether the logic was retained or not.
+ */
+static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
+{
+	int state;
+
+	state = omap4_pwrdm_read_prev_pwrst(pwrdm);
+
+	if (state == PWRDM_POWER_OFF)
+		return PWRDM_POWER_OFF;
+
+	if (state != PWRDM_POWER_RET)
+		return PWRDM_POWER_RET;
+
+	return omap4_pwrdm_read_logic_retst(pwrdm);
+}
+
+static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
+{
+	u32 m, v;
+
+	m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
+
+	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTST);
+	v &= m;
+	v >>= __ffs(m);
+
+	return v;
+}
+
+static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
+{
+	u32 m, v;
+
+	m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
+
+	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
+					OMAP4_PM_PWSTCTRL);
+	v &= m;
+	v >>= __ffs(m);
+
+	return v;
+}
+
+/**
+ * omap4_pwrdm_read_prev_mem_pwrst - reads the previous memory powerstate
+ * @pwrdm: struct powerdomain * to read mem powerstate for
+ * @bank: memory bank index
+ *
+ * Reads the previous memory powerstate for a powerdomain. This
+ * function must determine the previous memory powerstate by first
+ * checking the previous powerstate for the domain. If that was OFF,
+ * then logic has been lost. If previous state was RETENTION, the
+ * function reads the setting for the next memory retention state to
+ * see the actual value.  In every other case, the logic is
+ * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
+ * depending whether logic was retained or not.
+ */
+static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
+{
+	int state;
+
+	state = omap4_pwrdm_read_prev_pwrst(pwrdm);
+
+	if (state == PWRDM_POWER_OFF)
+		return PWRDM_POWER_OFF;
+
+	if (state != PWRDM_POWER_RET)
+		return PWRDM_POWER_RET;
+
+	return omap4_pwrdm_read_mem_retst(pwrdm, bank);
+}
+
+static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
+{
+	u32 c = 0;
+
+	/*
+	 * REVISIT: pwrdm_wait_transition() may be better implemented
+	 * via a callback and a periodic timer check -- how long do we expect
+	 * powerdomain transitions to take?
+	 */
+
+	/* XXX Is this udelay() value meaningful? */
+	while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
+					    pwrdm->prcm_offs,
+					    OMAP4_PM_PWSTST) &
+		OMAP_INTRANSITION_MASK) &&
+	       (c++ < PWRDM_TRANSITION_BAILOUT))
+		udelay(1);
+
+	if (c > PWRDM_TRANSITION_BAILOUT) {
+		pr_err("powerdomain: %s: waited too long to complete transition\n",
+		       pwrdm->name);
+		return -EAGAIN;
 	}
+
+	pr_debug("powerdomain: completed transition in %d loops\n", c);
+
 	return 0;
 }
-subsys_initcall(omap4xxx_prcm_init);
+
+struct pwrdm_ops omap4_pwrdm_operations = {
+	.pwrdm_set_next_pwrst	= omap4_pwrdm_set_next_pwrst,
+	.pwrdm_read_next_pwrst	= omap4_pwrdm_read_next_pwrst,
+	.pwrdm_read_pwrst	= omap4_pwrdm_read_pwrst,
+	.pwrdm_read_prev_pwrst	= omap4_pwrdm_read_prev_pwrst,
+	.pwrdm_set_lowpwrstchange	= omap4_pwrdm_set_lowpwrstchange,
+	.pwrdm_clear_all_prev_pwrst	= omap4_pwrdm_clear_all_prev_pwrst,
+	.pwrdm_set_logic_retst	= omap4_pwrdm_set_logic_retst,
+	.pwrdm_read_logic_pwrst	= omap4_pwrdm_read_logic_pwrst,
+	.pwrdm_read_prev_logic_pwrst	= omap4_pwrdm_read_prev_logic_pwrst,
+	.pwrdm_read_logic_retst	= omap4_pwrdm_read_logic_retst,
+	.pwrdm_read_mem_pwrst	= omap4_pwrdm_read_mem_pwrst,
+	.pwrdm_read_mem_retst	= omap4_pwrdm_read_mem_retst,
+	.pwrdm_read_prev_mem_pwrst	= omap4_pwrdm_read_prev_mem_pwrst,
+	.pwrdm_set_mem_onst	= omap4_pwrdm_set_mem_onst,
+	.pwrdm_set_mem_retst	= omap4_pwrdm_set_mem_retst,
+	.pwrdm_wait_transition	= omap4_pwrdm_wait_transition,
+};
+
+/*
+ * XXX document
+ */
+static struct prm_ll_data omap44xx_prm_ll_data = {
+	.read_reset_sources = &omap44xx_prm_read_reset_sources,
+};
+
+static int __init omap44xx_prm_init(void)
+{
+	int ret;
+
+	if (!cpu_is_omap44xx())
+		return 0;
+
+	ret = prm_register(&omap44xx_prm_ll_data);
+	if (ret)
+		return ret;
+
+	omap44xx_prm_enable_io_wakeup();
+
+	return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
+}
+subsys_initcall(omap44xx_prm_init);
+
+static void __exit omap44xx_prm_exit(void)
+{
+	if (!cpu_is_omap44xx())
+		return;
+
+	/* Should never happen */
+	WARN(prm_unregister(&omap44xx_prm_ll_data),
+	     "%s: prm_ll_data function pointer mismatch\n", __func__);
+}
+__exitcall(omap44xx_prm_exit);
diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h
index ee72ae6..c8e1acc 100644
--- a/arch/arm/mach-omap2/prm44xx.h
+++ b/arch/arm/mach-omap2/prm44xx.h
@@ -771,6 +771,8 @@ extern void omap44xx_prm_ocp_barrier(void);
 extern void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask);
 extern void omap44xx_prm_restore_irqen(u32 *saved_mask);
 
+extern u32 omap44xx_prm_get_reset_sources(void);
+
 # endif
 
 #endif
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 6b4d332..f596e1e 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -24,11 +24,11 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 
-#include <plat/common.h>
-#include <plat/prcm.h>
-
 #include "prm2xxx_3xxx.h"
+#include "prm2xxx.h"
+#include "prm3xxx.h"
 #include "prm44xx.h"
+#include "common.h"
 
 /*
  * OMAP_PRCM_MAX_NR_PENDING_REG: maximum number of PRM_IRQ*_MPU regs
@@ -53,6 +53,16 @@ static struct irq_chip_generic **prcm_irq_chips;
  */
 static struct omap_prcm_irq_setup *prcm_irq_setup;
 
+/* prm_base: base virtual address of the PRM IP block */
+void __iomem *prm_base;
+
+/*
+ * prm_ll_data: function pointers to SoC-specific implementations of
+ * common PRM functions
+ */
+static struct prm_ll_data null_prm_ll_data;
+static struct prm_ll_data *prm_ll_data = &null_prm_ll_data;
+
 /* Private functions */
 
 /*
@@ -319,64 +329,82 @@ err:
 	return -ENOMEM;
 }
 
-/*
- * Stubbed functions so that common files continue to build when
- * custom builds are used
- * XXX These are temporary and should be removed at the earliest possible
- * opportunity
+/**
+ * omap2_set_globals_prm - set the PRM base address (for early use)
+ * @prm: PRM base virtual address
+ *
+ * XXX Will be replaced when the PRM/CM drivers are completed.
  */
-u32 __weak omap2_prm_read_mod_reg(s16 module, u16 idx)
+void __init omap2_set_globals_prm(void __iomem *prm)
 {
-	WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
-	return 0;
+	prm_base = prm;
 }
 
-void __weak omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx)
+/**
+ * prm_read_reset_sources - return the sources of the SoC's last reset
+ *
+ * Return a u32 bitmask representing the reset sources that caused the
+ * SoC to reset.  The low-level per-SoC functions called by this
+ * function remap the SoC-specific reset source bits into an
+ * OMAP-common set of reset source bits, defined in
+ * arch/arm/mach-omap2/prm.h.  Returns the standardized reset source
+ * u32 bitmask from the hardware upon success, or returns (1 <<
+ * OMAP_UNKNOWN_RST_SRC_ID_SHIFT) if no low-level read_reset_sources()
+ * function was registered.
+ */
+u32 prm_read_reset_sources(void)
 {
-	WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
-}
+	u32 ret = 1 << OMAP_UNKNOWN_RST_SRC_ID_SHIFT;
 
-u32 __weak omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits,
-		s16 module, s16 idx)
-{
-	WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
-	return 0;
-}
+	if (prm_ll_data->read_reset_sources)
+		ret = prm_ll_data->read_reset_sources();
+	else
+		WARN_ONCE(1, "prm: %s: no mapping function defined for reset sources\n", __func__);
 
-u32 __weak omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
-{
-	WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
-	return 0;
+	return ret;
 }
 
-u32 __weak omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
+/**
+ * prm_register - register per-SoC low-level data with the PRM
+ * @pld: low-level per-SoC OMAP PRM data & function pointers to register
+ *
+ * Register per-SoC low-level OMAP PRM data and function pointers with
+ * the OMAP PRM common interface.  The caller must keep the data
+ * pointed to by @pld valid until it calls prm_unregister() and
+ * it returns successfully.  Returns 0 upon success, -EINVAL if @pld
+ * is NULL, or -EEXIST if prm_register() has already been called
+ * without an intervening prm_unregister().
+ */
+int prm_register(struct prm_ll_data *pld)
 {
-	WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
-	return 0;
-}
+	if (!pld)
+		return -EINVAL;
 
-u32 __weak omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
-{
-	WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
-	return 0;
-}
+	if (prm_ll_data != &null_prm_ll_data)
+		return -EEXIST;
 
-int __weak omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
-{
-	WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
-	return 0;
-}
+	prm_ll_data = pld;
 
-int __weak omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
-{
-	WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
 	return 0;
 }
 
-int __weak omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift,
-						u8 st_shift)
+/**
+ * prm_unregister - unregister per-SoC low-level data & function pointers
+ * @pld: low-level per-SoC OMAP PRM data & function pointers to unregister
+ *
+ * Unregister per-SoC low-level OMAP PRM data and function pointers
+ * that were previously registered with prm_register().  The
+ * caller may not destroy any of the data pointed to by @pld until
+ * this function returns successfully.  Returns 0 upon success, or
+ * -EINVAL if @pld is NULL or if @pld does not match the struct
+ * prm_ll_data * previously registered by prm_register().
+ */
+int prm_unregister(struct prm_ll_data *pld)
 {
-	WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
+	if (!pld || prm_ll_data != pld)
+		return -EINVAL;
+
+	prm_ll_data = &null_prm_ll_data;
+
 	return 0;
 }
-
diff --git a/arch/arm/mach-omap2/prminst44xx.h b/arch/arm/mach-omap2/prminst44xx.h
index 46f2efb..a2ede2d 100644
--- a/arch/arm/mach-omap2/prminst44xx.h
+++ b/arch/arm/mach-omap2/prminst44xx.h
@@ -30,4 +30,6 @@ extern int omap4_prminst_assert_hardreset(u8 shift, u8 part, s16 inst,
 extern int omap4_prminst_deassert_hardreset(u8 shift, u8 part, s16 inst,
 					    u16 rstctrl_offs);
 
+extern void omap_prm_base_init(void);
+
 #endif
diff --git a/arch/arm/mach-omap2/scrm44xx.h b/arch/arm/mach-omap2/scrm44xx.h
index 701bf2d..e897ac8 100644
--- a/arch/arm/mach-omap2/scrm44xx.h
+++ b/arch/arm/mach-omap2/scrm44xx.h
@@ -127,12 +127,14 @@
 /* AUXCLKREQ0 */
 #define OMAP4_MAPPING_SHIFT			2
 #define OMAP4_MAPPING_MASK			(0x7 << 2)
+#define OMAP4_MAPPING_WIDTH			3
 #define OMAP4_ACCURACY_SHIFT			1
 #define OMAP4_ACCURACY_MASK			(1 << 1)
 
 /* AUXCLK0 */
 #define OMAP4_CLKDIV_SHIFT			16
 #define OMAP4_CLKDIV_MASK			(0xf << 16)
+#define OMAP4_CLKDIV_WIDTH			4
 #define OMAP4_DISABLECLK_SHIFT			9
 #define OMAP4_DISABLECLK_MASK			(1 << 9)
 #define OMAP4_ENABLE_SHIFT			8
diff --git a/arch/arm/mach-omap2/sdram-hynix-h8mbx00u0mer-0em.h b/arch/arm/mach-omap2/sdram-hynix-h8mbx00u0mer-0em.h
index 8bfaf34..1ee58c2 100644
--- a/arch/arm/mach-omap2/sdram-hynix-h8mbx00u0mer-0em.h
+++ b/arch/arm/mach-omap2/sdram-hynix-h8mbx00u0mer-0em.h
@@ -11,7 +11,7 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_SDRAM_HYNIX_H8MBX00U0MER0EM
 #define __ARCH_ARM_MACH_OMAP2_SDRAM_HYNIX_H8MBX00U0MER0EM
 
-#include <plat/sdrc.h>
+#include "sdrc.h"
 
 /* Hynix H8MBX00U0MER-0EM */
 static struct omap_sdrc_params h8mbx00u0mer0em_sdrc_params[] = {
diff --git a/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h b/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h
index a391b49..85cccc0 100644
--- a/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h
+++ b/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h
@@ -14,7 +14,7 @@
 #ifndef ARCH_ARM_MACH_OMAP2_SDRAM_MICRON_MT46H32M32LF
 #define ARCH_ARM_MACH_OMAP2_SDRAM_MICRON_MT46H32M32LF
 
-#include <plat/sdrc.h>
+#include "sdrc.h"
 
 /* Micron MT46H32M32LF-6 */
 /* XXX Using ARE = 0x1 (no autorefresh burst) -- can this be changed? */
diff --git a/arch/arm/mach-omap2/sdram-nokia.c b/arch/arm/mach-omap2/sdram-nokia.c
index 845c4fd..0fa7ffa 100644
--- a/arch/arm/mach-omap2/sdram-nokia.c
+++ b/arch/arm/mach-omap2/sdram-nokia.c
@@ -18,10 +18,8 @@
 #include <linux/io.h>
 
 #include "common.h"
-#include <plat/clock.h>
-#include <plat/sdrc.h>
-
 #include "sdram-nokia.h"
+#include "sdrc.h"
 
 /* In picoseconds, except for tREF (ns), tXP, tCKE, tWTR (clks) */
 struct sdram_timings {
diff --git a/arch/arm/mach-omap2/sdram-numonyx-m65kxxxxam.h b/arch/arm/mach-omap2/sdram-numonyx-m65kxxxxam.h
index cd43529..003f7bf 100644
--- a/arch/arm/mach-omap2/sdram-numonyx-m65kxxxxam.h
+++ b/arch/arm/mach-omap2/sdram-numonyx-m65kxxxxam.h
@@ -11,7 +11,7 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_SDRAM_NUMONYX_M65KXXXXAM
 #define __ARCH_ARM_MACH_OMAP2_SDRAM_NUMONYX_M65KXXXXAM
 
-#include <plat/sdrc.h>
+#include "sdrc.h"
 
 /* Numonyx  M65KXXXXAM */
 static struct omap_sdrc_params m65kxxxxam_sdrc_params[] = {
diff --git a/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h b/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h
index 0e518a7..8dc3de5 100644
--- a/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h
+++ b/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h
@@ -14,7 +14,7 @@
 #ifndef ARCH_ARM_MACH_OMAP2_SDRAM_QIMONDA_HYB18M512160AF6
 #define ARCH_ARM_MACH_OMAP2_SDRAM_QIMONDA_HYB18M512160AF6
 
-#include <plat/sdrc.h>
+#include "sdrc.h"
 
 /* Qimonda HYB18M512160AF-6 */
 static struct omap_sdrc_params hyb18m512160af6_sdrc_params[] = {
diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c
index e3d345f..dae7e48 100644
--- a/arch/arm/mach-omap2/sdrc.c
+++ b/arch/arm/mach-omap2/sdrc.c
@@ -24,10 +24,7 @@
 #include <linux/io.h>
 
 #include "common.h"
-#include <plat/clock.h>
-#include <plat/sram.h>
-
-#include <plat/sdrc.h>
+#include "clock.h"
 #include "sdrc.h"
 
 static struct omap_sdrc_params *sdrc_init_params_cs0, *sdrc_init_params_cs1;
@@ -115,12 +112,10 @@ int omap2_sdrc_get_params(unsigned long r,
 }
 
 
-void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals)
+void __init omap2_set_globals_sdrc(void __iomem *sdrc, void __iomem *sms)
 {
-	if (omap2_globals->sdrc)
-		omap2_sdrc_base = omap2_globals->sdrc;
-	if (omap2_globals->sms)
-		omap2_sms_base = omap2_globals->sms;
+	omap2_sdrc_base = sdrc;
+	omap2_sms_base = sms;
 }
 
 /**
@@ -160,19 +155,3 @@ void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
 	sdrc_write_reg(l, SDRC_POWER);
 	omap2_sms_save_context();
 }
-
-void omap2_sms_write_rot_control(u32 val, unsigned ctx)
-{
-	sms_write_reg(val, SMS_ROT_CONTROL(ctx));
-}
-
-void omap2_sms_write_rot_size(u32 val, unsigned ctx)
-{
-	sms_write_reg(val, SMS_ROT_SIZE(ctx));
-}
-
-void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
-{
-	sms_write_reg(val, SMS_ROT_PHYSICAL_BA(ctx));
-}
-
diff --git a/arch/arm/mach-omap2/sdrc.h b/arch/arm/mach-omap2/sdrc.h
index b3f8379..446aa13 100644
--- a/arch/arm/mach-omap2/sdrc.h
+++ b/arch/arm/mach-omap2/sdrc.h
@@ -2,12 +2,14 @@
 #define __ARCH_ARM_MACH_OMAP2_SDRC_H
 
 /*
- * OMAP2 SDRC register definitions
+ * OMAP2/3 SDRC/SMS macros and prototypes
  *
- * Copyright (C) 2007 Texas Instruments, Inc.
- * Copyright (C) 2007 Nokia Corporation
+ * Copyright (C) 2007-2008, 2012 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008 Nokia Corporation
  *
- * Written by Paul Walmsley
+ * Paul Walmsley
+ * Tony Lindgren
+ * Richard Woodruff
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,8 +17,6 @@
  */
 #undef DEBUG
 
-#include <plat/sdrc.h>
-
 #ifndef __ASSEMBLER__
 
 #include <linux/io.h>
@@ -50,6 +50,60 @@ static inline u32 sms_read_reg(u16 reg)
 {
 	return __raw_readl(OMAP_SMS_REGADDR(reg));
 }
+
+extern void omap2_set_globals_sdrc(void __iomem *sdrc, void __iomem *sms);
+
+
+/**
+ * struct omap_sdrc_params - SDRC parameters for a given SDRC clock rate
+ * @rate: SDRC clock rate (in Hz)
+ * @actim_ctrla: Value to program to SDRC_ACTIM_CTRLA for this rate
+ * @actim_ctrlb: Value to program to SDRC_ACTIM_CTRLB for this rate
+ * @rfr_ctrl: Value to program to SDRC_RFR_CTRL for this rate
+ * @mr: Value to program to SDRC_MR for this rate
+ *
+ * This structure holds a pre-computed set of register values for the
+ * SDRC for a given SDRC clock rate and SDRAM chip.  These are
+ * intended to be pre-computed and specified in an array in the board-*.c
+ * files.  The structure is keyed off the 'rate' field.
+ */
+struct omap_sdrc_params {
+	unsigned long rate;
+	u32 actim_ctrla;
+	u32 actim_ctrlb;
+	u32 rfr_ctrl;
+	u32 mr;
+};
+
+#ifdef CONFIG_SOC_HAS_OMAP2_SDRC
+void omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
+			    struct omap_sdrc_params *sdrc_cs1);
+#else
+static inline void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
+					  struct omap_sdrc_params *sdrc_cs1) {};
+#endif
+
+int omap2_sdrc_get_params(unsigned long r,
+			  struct omap_sdrc_params **sdrc_cs0,
+			  struct omap_sdrc_params **sdrc_cs1);
+void omap2_sms_save_context(void);
+void omap2_sms_restore_context(void);
+
+struct memory_timings {
+	u32 m_type;		/* ddr = 1, sdr = 0 */
+	u32 dll_mode;		/* use lock mode = 1, unlock mode = 0 */
+	u32 slow_dll_ctrl;	/* unlock mode, dll value for slow speed */
+	u32 fast_dll_ctrl;	/* unlock mode, dll value for fast speed */
+	u32 base_cs;		/* base chip select to use for calculations */
+};
+
+extern void omap2xxx_sdrc_init_params(u32 force_lock_to_unlock_mode);
+struct omap_sdrc_params *rx51_get_sdram_timings(void);
+
+u32 omap2xxx_sdrc_dll_is_unlocked(void);
+u32 omap2xxx_sdrc_reprogram(u32 level, u32 force);
+
+
 #else
 #define OMAP242X_SDRC_REGADDR(reg)					\
 			OMAP2_L3_IO_ADDRESS(OMAP2420_SDRC_BASE + (reg))
@@ -57,6 +111,7 @@ static inline u32 sms_read_reg(u16 reg)
 			OMAP2_L3_IO_ADDRESS(OMAP243X_SDRC_BASE + (reg))
 #define OMAP34XX_SDRC_REGADDR(reg)					\
 			OMAP2_L3_IO_ADDRESS(OMAP343X_SDRC_BASE + (reg))
+
 #endif	/* __ASSEMBLER__ */
 
 /* Minimum frequency that the SDRC DLL can lock at */
@@ -74,4 +129,85 @@ static inline u32 sms_read_reg(u16 reg)
  */
 #define SDRC_MPURATE_LOOPS		96
 
+/* SDRC register offsets - read/write with sdrc_{read,write}_reg() */
+
+#define SDRC_SYSCONFIG		0x010
+#define SDRC_CS_CFG		0x040
+#define SDRC_SHARING		0x044
+#define SDRC_ERR_TYPE		0x04C
+#define SDRC_DLLA_CTRL		0x060
+#define SDRC_DLLA_STATUS	0x064
+#define SDRC_DLLB_CTRL		0x068
+#define SDRC_DLLB_STATUS	0x06C
+#define SDRC_POWER		0x070
+#define SDRC_MCFG_0		0x080
+#define SDRC_MR_0		0x084
+#define SDRC_EMR2_0		0x08c
+#define SDRC_ACTIM_CTRL_A_0	0x09c
+#define SDRC_ACTIM_CTRL_B_0	0x0a0
+#define SDRC_RFR_CTRL_0		0x0a4
+#define SDRC_MANUAL_0		0x0a8
+#define SDRC_MCFG_1		0x0B0
+#define SDRC_MR_1		0x0B4
+#define SDRC_EMR2_1		0x0BC
+#define SDRC_ACTIM_CTRL_A_1	0x0C4
+#define SDRC_ACTIM_CTRL_B_1	0x0C8
+#define SDRC_RFR_CTRL_1		0x0D4
+#define SDRC_MANUAL_1		0x0D8
+
+#define SDRC_POWER_AUTOCOUNT_SHIFT	8
+#define SDRC_POWER_AUTOCOUNT_MASK	(0xffff << SDRC_POWER_AUTOCOUNT_SHIFT)
+#define SDRC_POWER_CLKCTRL_SHIFT	4
+#define SDRC_POWER_CLKCTRL_MASK		(0x3 << SDRC_POWER_CLKCTRL_SHIFT)
+#define SDRC_SELF_REFRESH_ON_AUTOCOUNT	(0x2 << SDRC_POWER_CLKCTRL_SHIFT)
+
+/*
+ * These values represent the number of memory clock cycles between
+ * autorefresh initiation.  They assume 1 refresh per 64 ms (JEDEC), 8192
+ * rows per device, and include a subtraction of a 50 cycle window in the
+ * event that the autorefresh command is delayed due to other SDRC activity.
+ * The '| 1' sets the ARE field to send one autorefresh when the autorefresh
+ * counter reaches 0.
+ *
+ * These represent optimal values for common parts, it won't work for all.
+ * As long as you scale down, most parameters are still work, they just
+ * become sub-optimal. The RFR value goes in the opposite direction. If you
+ * don't adjust it down as your clock period increases the refresh interval
+ * will not be met. Setting all parameters for complete worst case may work,
+ * but may cut memory performance by 2x. Due to errata the DLLs need to be
+ * unlocked and their value needs run time calibration.	A dynamic call is
+ * need for that as no single right value exists acorss production samples.
+ *
+ * Only the FULL speed values are given. Current code is such that rate
+ * changes must be made at DPLLoutx2. The actual value adjustment for low
+ * frequency operation will be handled by omap_set_performance()
+ *
+ * By having the boot loader boot up in the fastest L4 speed available likely
+ * will result in something which you can switch between.
+ */
+#define SDRC_RFR_CTRL_165MHz	(0x00044c00 | 1)
+#define SDRC_RFR_CTRL_133MHz	(0x0003de00 | 1)
+#define SDRC_RFR_CTRL_100MHz	(0x0002da01 | 1)
+#define SDRC_RFR_CTRL_110MHz	(0x0002da01 | 1) /* Need to calc */
+#define SDRC_RFR_CTRL_BYPASS	(0x00005000 | 1) /* Need to calc */
+
+
+/*
+ * SMS register access
+ */
+
+#define OMAP242X_SMS_REGADDR(reg)					\
+		(void __iomem *)OMAP2_L3_IO_ADDRESS(OMAP2420_SMS_BASE + reg)
+#define OMAP243X_SMS_REGADDR(reg)					\
+		(void __iomem *)OMAP2_L3_IO_ADDRESS(OMAP243X_SMS_BASE + reg)
+#define OMAP343X_SMS_REGADDR(reg)					\
+		(void __iomem *)OMAP2_L3_IO_ADDRESS(OMAP343X_SMS_BASE + reg)
+
+/* SMS register offsets - read/write with sms_{read,write}_reg() */
+
+#define SMS_SYSCONFIG			0x010
+/* REVISIT: fill in other SMS registers here */
+
+
+
 #endif
diff --git a/arch/arm/mach-omap2/sdrc2xxx.c b/arch/arm/mach-omap2/sdrc2xxx.c
index 73e55e4..9072917 100644
--- a/arch/arm/mach-omap2/sdrc2xxx.c
+++ b/arch/arm/mach-omap2/sdrc2xxx.c
@@ -24,16 +24,13 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/clock.h>
-#include <plat/sram.h>
-#include <plat/sdrc.h>
-
 #include "soc.h"
 #include "iomap.h"
 #include "common.h"
-#include "prm2xxx_3xxx.h"
+#include "prm2xxx.h"
 #include "clock.h"
 #include "sdrc.h"
+#include "sram.h"
 
 /* Memory timing, DLL mode flags */
 #define M_DDR		1
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index a507cd6..aa30a3c 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -28,19 +28,20 @@
 #include <linux/console.h>
 
 #include <plat/omap-serial.h>
-#include "common.h"
-#include <plat/dma.h>
-#include <plat/omap_hwmod.h>
-#include <plat/omap_device.h>
-#include <plat/omap-pm.h>
-#include <plat/serial.h>
+#include <plat-omap/dma-omap.h>
 
+#include "common.h"
+#include "omap_hwmod.h"
+#include "omap_device.h"
+#include "omap-pm.h"
+#include "soc.h"
 #include "prm2xxx_3xxx.h"
 #include "pm.h"
 #include "cm2xxx_3xxx.h"
 #include "prm-regbits-34xx.h"
 #include "control.h"
 #include "mux.h"
+#include "serial.h"
 
 /*
  * NOTE: By default the serial auto_suspend timeout is disabled as it causes
diff --git a/arch/arm/mach-omap2/serial.h b/arch/arm/mach-omap2/serial.h
new file mode 100644
index 0000000..c4014f0
--- /dev/null
+++ b/arch/arm/mach-omap2/serial.h
@@ -0,0 +1 @@
+#include <mach/serial.h>
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index 5069879..d1dedc8 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -26,13 +26,12 @@
 
 #include <asm/assembler.h>
 
-#include <plat/sram.h>
-
 #include "omap34xx.h"
 #include "iomap.h"
-#include "cm2xxx_3xxx.h"
-#include "prm2xxx_3xxx.h"
+#include "cm3xxx.h"
+#include "prm3xxx.h"
 #include "sdrc.h"
+#include "sram.h"
 #include "control.h"
 
 /*
diff --git a/arch/arm/mach-omap2/soc.h b/arch/arm/mach-omap2/soc.h
index fc9b96d..f31d907 100644
--- a/arch/arm/mach-omap2/soc.h
+++ b/arch/arm/mach-omap2/soc.h
@@ -1,7 +1,469 @@
-#include <plat/cpu.h>
+/*
+ * OMAP cpu type detection
+ *
+ * Copyright (C) 2004, 2008 Nokia Corporation
+ *
+ * Copyright (C) 2009-11 Texas Instruments.
+ *
+ * Written by Tony Lindgren <tony.lindgren@nokia.com>
+ *
+ * Added OMAP4/5 specific defines - 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 "omap24xx.h"
 #include "omap34xx.h"
 #include "omap44xx.h"
 #include "ti81xx.h"
 #include "am33xx.h"
 #include "omap54xx.h"
+
+#ifndef __ASSEMBLY__
+
+#include <linux/bitops.h>
+
+/*
+ * Test if multicore OMAP support is needed
+ */
+#undef MULTI_OMAP2
+#undef OMAP_NAME
+
+#ifdef CONFIG_SOC_OMAP2420
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP2
+#  define MULTI_OMAP2
+# else
+#  define OMAP_NAME omap2420
+# endif
+#endif
+#ifdef CONFIG_SOC_OMAP2430
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP2
+#  define MULTI_OMAP2
+# else
+#  define OMAP_NAME omap2430
+# endif
+#endif
+#ifdef CONFIG_ARCH_OMAP3
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP2
+#  define MULTI_OMAP2
+# else
+#  define OMAP_NAME omap3
+# endif
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP2
+#  define MULTI_OMAP2
+# else
+#  define OMAP_NAME omap4
+# endif
+#endif
+
+#ifdef CONFIG_SOC_OMAP5
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP2
+#  define MULTI_OMAP2
+# else
+#  define OMAP_NAME omap5
+# endif
+#endif
+
+#ifdef CONFIG_SOC_AM33XX
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP2
+#  define MULTI_OMAP2
+# else
+#  define OMAP_NAME am33xx
+# endif
+#endif
+
+/*
+ * Omap device type i.e. EMU/HS/TST/GP/BAD
+ */
+#define OMAP2_DEVICE_TYPE_TEST		0
+#define OMAP2_DEVICE_TYPE_EMU		1
+#define OMAP2_DEVICE_TYPE_SEC		2
+#define OMAP2_DEVICE_TYPE_GP		3
+#define OMAP2_DEVICE_TYPE_BAD		4
+
+int omap_type(void);
+
+/*
+ * omap_rev bits:
+ * CPU id bits	(0730, 1510, 1710, 2422...)	[31:16]
+ * CPU revision	(See _REV_ defined in cpu.h)	[15:08]
+ * CPU class bits (15xx, 16xx, 24xx, 34xx...)	[07:00]
+ */
+unsigned int omap_rev(void);
+
+/*
+ * Get the CPU revision for OMAP devices
+ */
+#define GET_OMAP_REVISION()	((omap_rev() >> 8) & 0xff)
+
+/*
+ * Macros to group OMAP into cpu classes.
+ * These can be used in most places.
+ * cpu_is_omap24xx():	True for OMAP2420, OMAP2422, OMAP2423, OMAP2430
+ * cpu_is_omap242x():	True for OMAP2420, OMAP2422, OMAP2423
+ * cpu_is_omap243x():	True for OMAP2430
+ * cpu_is_omap343x():	True for OMAP3430
+ * cpu_is_omap443x():	True for OMAP4430
+ * cpu_is_omap446x():	True for OMAP4460
+ * cpu_is_omap447x():	True for OMAP4470
+ * soc_is_omap543x():	True for OMAP5430, OMAP5432
+ */
+#define GET_OMAP_CLASS	(omap_rev() & 0xff)
+
+#define IS_OMAP_CLASS(class, id)			\
+static inline int is_omap ##class (void)		\
+{							\
+	return (GET_OMAP_CLASS == (id)) ? 1 : 0;	\
+}
+
+#define GET_AM_CLASS	((omap_rev() >> 24) & 0xff)
+
+#define IS_AM_CLASS(class, id)				\
+static inline int is_am ##class (void)			\
+{							\
+	return (GET_AM_CLASS == (id)) ? 1 : 0;		\
+}
+
+#define GET_TI_CLASS	((omap_rev() >> 24) & 0xff)
+
+#define IS_TI_CLASS(class, id)			\
+static inline int is_ti ##class (void)		\
+{							\
+	return (GET_TI_CLASS == (id)) ? 1 : 0;	\
+}
+
+#define GET_OMAP_SUBCLASS	((omap_rev() >> 20) & 0x0fff)
+
+#define IS_OMAP_SUBCLASS(subclass, id)			\
+static inline int is_omap ##subclass (void)		\
+{							\
+	return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;	\
+}
+
+#define IS_TI_SUBCLASS(subclass, id)			\
+static inline int is_ti ##subclass (void)		\
+{							\
+	return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;	\
+}
+
+#define IS_AM_SUBCLASS(subclass, id)			\
+static inline int is_am ##subclass (void)		\
+{							\
+	return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;	\
+}
+
+IS_OMAP_CLASS(24xx, 0x24)
+IS_OMAP_CLASS(34xx, 0x34)
+IS_OMAP_CLASS(44xx, 0x44)
+IS_AM_CLASS(35xx, 0x35)
+IS_OMAP_CLASS(54xx, 0x54)
+IS_AM_CLASS(33xx, 0x33)
+
+IS_TI_CLASS(81xx, 0x81)
+
+IS_OMAP_SUBCLASS(242x, 0x242)
+IS_OMAP_SUBCLASS(243x, 0x243)
+IS_OMAP_SUBCLASS(343x, 0x343)
+IS_OMAP_SUBCLASS(363x, 0x363)
+IS_OMAP_SUBCLASS(443x, 0x443)
+IS_OMAP_SUBCLASS(446x, 0x446)
+IS_OMAP_SUBCLASS(447x, 0x447)
+IS_OMAP_SUBCLASS(543x, 0x543)
+
+IS_TI_SUBCLASS(816x, 0x816)
+IS_TI_SUBCLASS(814x, 0x814)
+IS_AM_SUBCLASS(335x, 0x335)
+
+#define cpu_is_omap24xx()		0
+#define cpu_is_omap242x()		0
+#define cpu_is_omap243x()		0
+#define cpu_is_omap34xx()		0
+#define cpu_is_omap343x()		0
+#define cpu_is_ti81xx()			0
+#define cpu_is_ti816x()			0
+#define cpu_is_ti814x()			0
+#define soc_is_am35xx()			0
+#define soc_is_am33xx()			0
+#define soc_is_am335x()			0
+#define cpu_is_omap44xx()		0
+#define cpu_is_omap443x()		0
+#define cpu_is_omap446x()		0
+#define cpu_is_omap447x()		0
+#define soc_is_omap54xx()		0
+#define soc_is_omap543x()		0
+
+#if defined(MULTI_OMAP2)
+# if defined(CONFIG_ARCH_OMAP2)
+#  undef  cpu_is_omap24xx
+#  define cpu_is_omap24xx()		is_omap24xx()
+# endif
+# if defined (CONFIG_SOC_OMAP2420)
+#  undef  cpu_is_omap242x
+#  define cpu_is_omap242x()		is_omap242x()
+# endif
+# if defined (CONFIG_SOC_OMAP2430)
+#  undef  cpu_is_omap243x
+#  define cpu_is_omap243x()		is_omap243x()
+# endif
+# if defined(CONFIG_ARCH_OMAP3)
+#  undef  cpu_is_omap34xx
+#  undef  cpu_is_omap343x
+#  define cpu_is_omap34xx()		is_omap34xx()
+#  define cpu_is_omap343x()		is_omap343x()
+# endif
+#else
+# if defined(CONFIG_ARCH_OMAP2)
+#  undef  cpu_is_omap24xx
+#  define cpu_is_omap24xx()		1
+# endif
+# if defined(CONFIG_SOC_OMAP2420)
+#  undef  cpu_is_omap242x
+#  define cpu_is_omap242x()		1
+# endif
+# if defined(CONFIG_SOC_OMAP2430)
+#  undef  cpu_is_omap243x
+#  define cpu_is_omap243x()		1
+# endif
+# if defined(CONFIG_ARCH_OMAP3)
+#  undef  cpu_is_omap34xx
+#  define cpu_is_omap34xx()		1
+# endif
+# if defined(CONFIG_SOC_OMAP3430)
+#  undef  cpu_is_omap343x
+#  define cpu_is_omap343x()		1
+# endif
+#endif
+
+/*
+ * Macros to detect individual cpu types.
+ * These are only rarely needed.
+ * cpu_is_omap2420():	True for OMAP2420
+ * cpu_is_omap2422():	True for OMAP2422
+ * cpu_is_omap2423():	True for OMAP2423
+ * cpu_is_omap2430():	True for OMAP2430
+ * cpu_is_omap3430():	True for OMAP3430
+ */
+#define GET_OMAP_TYPE	((omap_rev() >> 16) & 0xffff)
+
+#define IS_OMAP_TYPE(type, id)				\
+static inline int is_omap ##type (void)			\
+{							\
+	return (GET_OMAP_TYPE == (id)) ? 1 : 0;		\
+}
+
+IS_OMAP_TYPE(2420, 0x2420)
+IS_OMAP_TYPE(2422, 0x2422)
+IS_OMAP_TYPE(2423, 0x2423)
+IS_OMAP_TYPE(2430, 0x2430)
+IS_OMAP_TYPE(3430, 0x3430)
+
+#define cpu_is_omap2420()		0
+#define cpu_is_omap2422()		0
+#define cpu_is_omap2423()		0
+#define cpu_is_omap2430()		0
+#define cpu_is_omap3430()		0
+#define cpu_is_omap3630()		0
+#define soc_is_omap5430()		0
+
+/* These are needed for the common code */
+#ifdef CONFIG_ARCH_OMAP2PLUS
+#define cpu_is_omap7xx()		0
+#define cpu_is_omap15xx()		0
+#define cpu_is_omap16xx()		0
+#define cpu_is_omap1510()		0
+#define cpu_is_omap1610()		0
+#define cpu_is_omap1611()		0
+#define cpu_is_omap1621()		0
+#define cpu_is_omap1710()		0
+#define cpu_class_is_omap1()		0
+#define cpu_class_is_omap2()		1
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2)
+# undef  cpu_is_omap2420
+# undef  cpu_is_omap2422
+# undef  cpu_is_omap2423
+# undef  cpu_is_omap2430
+# define cpu_is_omap2420()		is_omap2420()
+# define cpu_is_omap2422()		is_omap2422()
+# define cpu_is_omap2423()		is_omap2423()
+# define cpu_is_omap2430()		is_omap2430()
+#endif
+
+#if defined(CONFIG_ARCH_OMAP3)
+# undef cpu_is_omap3430
+# undef cpu_is_ti81xx
+# undef cpu_is_ti816x
+# undef cpu_is_ti814x
+# undef soc_is_am35xx
+# define cpu_is_omap3430()		is_omap3430()
+# undef cpu_is_omap3630
+# define cpu_is_omap3630()		is_omap363x()
+# define cpu_is_ti81xx()		is_ti81xx()
+# define cpu_is_ti816x()		is_ti816x()
+# define cpu_is_ti814x()		is_ti814x()
+# define soc_is_am35xx()		is_am35xx()
+#endif
+
+# if defined(CONFIG_SOC_AM33XX)
+# undef soc_is_am33xx
+# undef soc_is_am335x
+# define soc_is_am33xx()		is_am33xx()
+# define soc_is_am335x()		is_am335x()
+#endif
+
+# if defined(CONFIG_ARCH_OMAP4)
+# undef cpu_is_omap44xx
+# undef cpu_is_omap443x
+# undef cpu_is_omap446x
+# undef cpu_is_omap447x
+# define cpu_is_omap44xx()		is_omap44xx()
+# define cpu_is_omap443x()		is_omap443x()
+# define cpu_is_omap446x()		is_omap446x()
+# define cpu_is_omap447x()		is_omap447x()
+# endif
+
+# if defined(CONFIG_SOC_OMAP5)
+# undef soc_is_omap54xx
+# undef soc_is_omap543x
+# define soc_is_omap54xx()		is_omap54xx()
+# define soc_is_omap543x()		is_omap543x()
+#endif
+
+/* Various silicon revisions for omap2 */
+#define OMAP242X_CLASS		0x24200024
+#define OMAP2420_REV_ES1_0	OMAP242X_CLASS
+#define OMAP2420_REV_ES2_0	(OMAP242X_CLASS | (0x1 << 8))
+
+#define OMAP243X_CLASS		0x24300024
+#define OMAP2430_REV_ES1_0	OMAP243X_CLASS
+
+#define OMAP343X_CLASS		0x34300034
+#define OMAP3430_REV_ES1_0	OMAP343X_CLASS
+#define OMAP3430_REV_ES2_0	(OMAP343X_CLASS | (0x1 << 8))
+#define OMAP3430_REV_ES2_1	(OMAP343X_CLASS | (0x2 << 8))
+#define OMAP3430_REV_ES3_0	(OMAP343X_CLASS | (0x3 << 8))
+#define OMAP3430_REV_ES3_1	(OMAP343X_CLASS | (0x4 << 8))
+#define OMAP3430_REV_ES3_1_2	(OMAP343X_CLASS | (0x5 << 8))
+
+#define OMAP363X_CLASS		0x36300034
+#define OMAP3630_REV_ES1_0	OMAP363X_CLASS
+#define OMAP3630_REV_ES1_1	(OMAP363X_CLASS | (0x1 << 8))
+#define OMAP3630_REV_ES1_2	(OMAP363X_CLASS | (0x2 << 8))
+
+#define TI816X_CLASS		0x81600034
+#define TI8168_REV_ES1_0	TI816X_CLASS
+#define TI8168_REV_ES1_1	(TI816X_CLASS | (0x1 << 8))
+
+#define TI814X_CLASS		0x81400034
+#define TI8148_REV_ES1_0	TI814X_CLASS
+#define TI8148_REV_ES2_0	(TI814X_CLASS | (0x1 << 8))
+#define TI8148_REV_ES2_1	(TI814X_CLASS | (0x2 << 8))
+
+#define AM35XX_CLASS		0x35170034
+#define AM35XX_REV_ES1_0	AM35XX_CLASS
+#define AM35XX_REV_ES1_1	(AM35XX_CLASS | (0x1 << 8))
+
+#define AM335X_CLASS		0x33500033
+#define AM335X_REV_ES1_0	AM335X_CLASS
+
+#define OMAP443X_CLASS		0x44300044
+#define OMAP4430_REV_ES1_0	(OMAP443X_CLASS | (0x10 << 8))
+#define OMAP4430_REV_ES2_0	(OMAP443X_CLASS | (0x20 << 8))
+#define OMAP4430_REV_ES2_1	(OMAP443X_CLASS | (0x21 << 8))
+#define OMAP4430_REV_ES2_2	(OMAP443X_CLASS | (0x22 << 8))
+#define OMAP4430_REV_ES2_3	(OMAP443X_CLASS | (0x23 << 8))
+
+#define OMAP446X_CLASS		0x44600044
+#define OMAP4460_REV_ES1_0	(OMAP446X_CLASS | (0x10 << 8))
+#define OMAP4460_REV_ES1_1	(OMAP446X_CLASS | (0x11 << 8))
+
+#define OMAP447X_CLASS		0x44700044
+#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 OMAP5432_REV_ES1_0	(OMAP54XX_CLASS | (0x32 << 16) | (0x10 << 8))
+
+void omap2xxx_check_revision(void);
+void omap3xxx_check_revision(void);
+void omap4xxx_check_revision(void);
+void omap5xxx_check_revision(void);
+void omap3xxx_check_features(void);
+void ti81xx_check_features(void);
+void omap4xxx_check_features(void);
+
+/*
+ * Runtime detection of OMAP3 features
+ *
+ * OMAP3_HAS_IO_CHAIN_CTRL: Some later members of the OMAP3 chip
+ *    family have OS-level control over the I/O chain clock.  This is
+ *    to avoid a window during which wakeups could potentially be lost
+ *    during powerdomain transitions.  If this bit is set, it
+ *    indicates that the chip does support OS-level control of this
+ *    feature.
+ */
+extern u32 omap_features;
+
+#define OMAP3_HAS_L2CACHE		BIT(0)
+#define OMAP3_HAS_IVA			BIT(1)
+#define OMAP3_HAS_SGX			BIT(2)
+#define OMAP3_HAS_NEON			BIT(3)
+#define OMAP3_HAS_ISP			BIT(4)
+#define OMAP3_HAS_192MHZ_CLK		BIT(5)
+#define OMAP3_HAS_IO_WAKEUP		BIT(6)
+#define OMAP3_HAS_SDRC			BIT(7)
+#define OMAP3_HAS_IO_CHAIN_CTRL		BIT(8)
+#define OMAP4_HAS_PERF_SILICON		BIT(9)
+
+
+#define OMAP3_HAS_FEATURE(feat,flag)			\
+static inline unsigned int omap3_has_ ##feat(void)	\
+{							\
+	return omap_features & OMAP3_HAS_ ##flag;	\
+}							\
+
+OMAP3_HAS_FEATURE(l2cache, L2CACHE)
+OMAP3_HAS_FEATURE(sgx, SGX)
+OMAP3_HAS_FEATURE(iva, IVA)
+OMAP3_HAS_FEATURE(neon, NEON)
+OMAP3_HAS_FEATURE(isp, ISP)
+OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
+OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
+OMAP3_HAS_FEATURE(sdrc, SDRC)
+OMAP3_HAS_FEATURE(io_chain_ctrl, IO_CHAIN_CTRL)
+
+/*
+ * Runtime detection of OMAP4 features
+ */
+#define OMAP4_HAS_FEATURE(feat, flag)			\
+static inline unsigned int omap4_has_ ##feat(void)	\
+{							\
+	return omap_features & OMAP4_HAS_ ##flag;	\
+}							\
+
+OMAP4_HAS_FEATURE(perf_silicon, PERF_SILICON)
+
+#endif	/* __ASSEMBLY__ */
+
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index f8217a5..b9753fe 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -23,8 +23,8 @@
 #include <linux/slab.h>
 #include <linux/io.h>
 
-#include <plat/omap_device.h>
-
+#include "soc.h"
+#include "omap_device.h"
 #include "voltage.h"
 #include "control.h"
 #include "pm.h"
@@ -121,6 +121,19 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
 	sr_data->senn_mod = 0x1;
 	sr_data->senp_mod = 0x1;
 
+	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+		sr_data->err_weight = OMAP3430_SR_ERRWEIGHT;
+		sr_data->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
+		sr_data->accum_data = OMAP3430_SR_ACCUMDATA;
+		if (!(strcmp(sr_data->name, "smartreflex_mpu"))) {
+			sr_data->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
+			sr_data->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
+		} else {
+			sr_data->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
+			sr_data->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
+		}
+	}
+
 	sr_data->voltdm = voltdm_lookup(sr_dev_attr->sensor_voltdm_name);
 	if (!sr_data->voltdm) {
 		pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
diff --git a/arch/arm/mach-omap2/sram.c b/arch/arm/mach-omap2/sram.c
new file mode 100644
index 0000000..0ff0f06
--- /dev/null
+++ b/arch/arm/mach-omap2/sram.c
@@ -0,0 +1,305 @@
+/*
+ *
+ * OMAP SRAM detection and management
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Written by Tony Lindgren <tony@atomide.com>
+ *
+ * Copyright (C) 2009-2012 Texas Instruments
+ * Added OMAP4/5 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/fncpy.h>
+#include <asm/tlb.h>
+#include <asm/cacheflush.h>
+
+#include <asm/mach/map.h>
+
+#include "soc.h"
+#include "iomap.h"
+#include "prm2xxx_3xxx.h"
+#include "sdrc.h"
+#include "sram.h"
+
+#define OMAP2_SRAM_PUB_PA	(OMAP2_SRAM_PA + 0xf800)
+#define OMAP3_SRAM_PUB_PA       (OMAP3_SRAM_PA + 0x8000)
+#ifdef CONFIG_OMAP4_ERRATA_I688
+#define OMAP4_SRAM_PUB_PA	OMAP4_SRAM_PA
+#else
+#define OMAP4_SRAM_PUB_PA	(OMAP4_SRAM_PA + 0x4000)
+#endif
+#define OMAP5_SRAM_PA		0x40300000
+
+#define SRAM_BOOTLOADER_SZ	0x00
+
+#define OMAP24XX_VA_REQINFOPERM0	OMAP2_L3_IO_ADDRESS(0x68005048)
+#define OMAP24XX_VA_READPERM0		OMAP2_L3_IO_ADDRESS(0x68005050)
+#define OMAP24XX_VA_WRITEPERM0		OMAP2_L3_IO_ADDRESS(0x68005058)
+
+#define OMAP34XX_VA_REQINFOPERM0	OMAP2_L3_IO_ADDRESS(0x68012848)
+#define OMAP34XX_VA_READPERM0		OMAP2_L3_IO_ADDRESS(0x68012850)
+#define OMAP34XX_VA_WRITEPERM0		OMAP2_L3_IO_ADDRESS(0x68012858)
+#define OMAP34XX_VA_ADDR_MATCH2		OMAP2_L3_IO_ADDRESS(0x68012880)
+#define OMAP34XX_VA_SMS_RG_ATT0		OMAP2_L3_IO_ADDRESS(0x6C000048)
+
+#define GP_DEVICE		0x300
+
+#define ROUND_DOWN(value,boundary)	((value) & (~((boundary)-1)))
+
+static unsigned long omap_sram_start;
+static unsigned long omap_sram_skip;
+static unsigned long omap_sram_size;
+
+/*
+ * Depending on the target RAMFS firewall setup, the public usable amount of
+ * SRAM varies.  The default accessible size for all device types is 2k. A GP
+ * device allows ARM11 but not other initiators for full size. This
+ * functionality seems ok until some nice security API happens.
+ */
+static int is_sram_locked(void)
+{
+	if (OMAP2_DEVICE_TYPE_GP == omap_type()) {
+		/* RAMFW: R/W access to all initiators for all qualifier sets */
+		if (cpu_is_omap242x()) {
+			__raw_writel(0xFF, OMAP24XX_VA_REQINFOPERM0); /* all q-vects */
+			__raw_writel(0xCFDE, OMAP24XX_VA_READPERM0);  /* all i-read */
+			__raw_writel(0xCFDE, OMAP24XX_VA_WRITEPERM0); /* all i-write */
+		}
+		if (cpu_is_omap34xx()) {
+			__raw_writel(0xFFFF, OMAP34XX_VA_REQINFOPERM0); /* all q-vects */
+			__raw_writel(0xFFFF, OMAP34XX_VA_READPERM0);  /* all i-read */
+			__raw_writel(0xFFFF, OMAP34XX_VA_WRITEPERM0); /* all i-write */
+			__raw_writel(0x0, OMAP34XX_VA_ADDR_MATCH2);
+			__raw_writel(0xFFFFFFFF, OMAP34XX_VA_SMS_RG_ATT0);
+		}
+		return 0;
+	} else
+		return 1; /* assume locked with no PPA or security driver */
+}
+
+/*
+ * The amount of SRAM depends on the core type.
+ * Note that we cannot try to test for SRAM here because writes
+ * to secure SRAM will hang the system. Also the SRAM is not
+ * yet mapped at this point.
+ */
+static void __init omap_detect_sram(void)
+{
+	omap_sram_skip = SRAM_BOOTLOADER_SZ;
+	if (is_sram_locked()) {
+		if (cpu_is_omap34xx()) {
+			omap_sram_start = OMAP3_SRAM_PUB_PA;
+			if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) ||
+			    (omap_type() == OMAP2_DEVICE_TYPE_SEC)) {
+				omap_sram_size = 0x7000; /* 28K */
+				omap_sram_skip += SZ_16K;
+			} else {
+				omap_sram_size = 0x8000; /* 32K */
+			}
+		} else if (cpu_is_omap44xx()) {
+			omap_sram_start = OMAP4_SRAM_PUB_PA;
+			omap_sram_size = 0xa000; /* 40K */
+		} else if (soc_is_omap54xx()) {
+			omap_sram_start = OMAP5_SRAM_PA;
+			omap_sram_size = SZ_128K; /* 128KB */
+		} else {
+			omap_sram_start = OMAP2_SRAM_PUB_PA;
+			omap_sram_size = 0x800; /* 2K */
+		}
+	} else {
+		if (soc_is_am33xx()) {
+			omap_sram_start = AM33XX_SRAM_PA;
+			omap_sram_size = 0x10000; /* 64K */
+		} else if (cpu_is_omap34xx()) {
+			omap_sram_start = OMAP3_SRAM_PA;
+			omap_sram_size = 0x10000; /* 64K */
+		} else if (cpu_is_omap44xx()) {
+			omap_sram_start = OMAP4_SRAM_PA;
+			omap_sram_size = 0xe000; /* 56K */
+		} else if (soc_is_omap54xx()) {
+			omap_sram_start = OMAP5_SRAM_PA;
+			omap_sram_size = SZ_128K; /* 128KB */
+		} else {
+			omap_sram_start = OMAP2_SRAM_PA;
+			if (cpu_is_omap242x())
+				omap_sram_size = 0xa0000; /* 640K */
+			else if (cpu_is_omap243x())
+				omap_sram_size = 0x10000; /* 64K */
+		}
+	}
+}
+
+/*
+ * Note that we cannot use ioremap for SRAM, as clock init needs SRAM early.
+ */
+static void __init omap2_map_sram(void)
+{
+	int cached = 1;
+
+#ifdef CONFIG_OMAP4_ERRATA_I688
+	if (cpu_is_omap44xx()) {
+		omap_sram_start += PAGE_SIZE;
+		omap_sram_size -= SZ_16K;
+	}
+#endif
+	if (cpu_is_omap34xx()) {
+		/*
+		 * SRAM must be marked as non-cached on OMAP3 since the
+		 * CORE DPLL M2 divider change code (in SRAM) runs with the
+		 * SDRAM controller disabled, and if it is marked cached,
+		 * the ARM may attempt to write cache lines back to SDRAM
+		 * which will cause the system to hang.
+		 */
+		cached = 0;
+	}
+
+	omap_map_sram(omap_sram_start, omap_sram_size,
+			omap_sram_skip, cached);
+}
+
+static void (*_omap2_sram_ddr_init)(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
+			      u32 base_cs, u32 force_unlock);
+
+void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
+		   u32 base_cs, u32 force_unlock)
+{
+	BUG_ON(!_omap2_sram_ddr_init);
+	_omap2_sram_ddr_init(slow_dll_ctrl, fast_dll_ctrl,
+			     base_cs, force_unlock);
+}
+
+static void (*_omap2_sram_reprogram_sdrc)(u32 perf_level, u32 dll_val,
+					  u32 mem_type);
+
+void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, u32 mem_type)
+{
+	BUG_ON(!_omap2_sram_reprogram_sdrc);
+	_omap2_sram_reprogram_sdrc(perf_level, dll_val, mem_type);
+}
+
+static u32 (*_omap2_set_prcm)(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
+
+u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass)
+{
+	BUG_ON(!_omap2_set_prcm);
+	return _omap2_set_prcm(dpll_ctrl_val, sdrc_rfr_val, bypass);
+}
+
+#ifdef CONFIG_SOC_OMAP2420
+static int __init omap242x_sram_init(void)
+{
+	_omap2_sram_ddr_init = omap_sram_push(omap242x_sram_ddr_init,
+					omap242x_sram_ddr_init_sz);
+
+	_omap2_sram_reprogram_sdrc = omap_sram_push(omap242x_sram_reprogram_sdrc,
+					    omap242x_sram_reprogram_sdrc_sz);
+
+	_omap2_set_prcm = omap_sram_push(omap242x_sram_set_prcm,
+					 omap242x_sram_set_prcm_sz);
+
+	return 0;
+}
+#else
+static inline int omap242x_sram_init(void)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_SOC_OMAP2430
+static int __init omap243x_sram_init(void)
+{
+	_omap2_sram_ddr_init = omap_sram_push(omap243x_sram_ddr_init,
+					omap243x_sram_ddr_init_sz);
+
+	_omap2_sram_reprogram_sdrc = omap_sram_push(omap243x_sram_reprogram_sdrc,
+					    omap243x_sram_reprogram_sdrc_sz);
+
+	_omap2_set_prcm = omap_sram_push(omap243x_sram_set_prcm,
+					 omap243x_sram_set_prcm_sz);
+
+	return 0;
+}
+#else
+static inline int omap243x_sram_init(void)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+
+static u32 (*_omap3_sram_configure_core_dpll)(
+			u32 m2, u32 unlock_dll, u32 f, u32 inc,
+			u32 sdrc_rfr_ctrl_0, u32 sdrc_actim_ctrl_a_0,
+			u32 sdrc_actim_ctrl_b_0, u32 sdrc_mr_0,
+			u32 sdrc_rfr_ctrl_1, u32 sdrc_actim_ctrl_a_1,
+			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
+
+u32 omap3_configure_core_dpll(u32 m2, u32 unlock_dll, u32 f, u32 inc,
+			u32 sdrc_rfr_ctrl_0, u32 sdrc_actim_ctrl_a_0,
+			u32 sdrc_actim_ctrl_b_0, u32 sdrc_mr_0,
+			u32 sdrc_rfr_ctrl_1, u32 sdrc_actim_ctrl_a_1,
+			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1)
+{
+	BUG_ON(!_omap3_sram_configure_core_dpll);
+	return _omap3_sram_configure_core_dpll(
+			m2, unlock_dll, f, inc,
+			sdrc_rfr_ctrl_0, sdrc_actim_ctrl_a_0,
+			sdrc_actim_ctrl_b_0, sdrc_mr_0,
+			sdrc_rfr_ctrl_1, sdrc_actim_ctrl_a_1,
+			sdrc_actim_ctrl_b_1, sdrc_mr_1);
+}
+
+void omap3_sram_restore_context(void)
+{
+	omap_sram_reset();
+
+	_omap3_sram_configure_core_dpll =
+		omap_sram_push(omap3_sram_configure_core_dpll,
+			       omap3_sram_configure_core_dpll_sz);
+	omap_push_sram_idle();
+}
+
+static inline int omap34xx_sram_init(void)
+{
+	omap3_sram_restore_context();
+	return 0;
+}
+#else
+static inline int omap34xx_sram_init(void)
+{
+	return 0;
+}
+#endif /* CONFIG_ARCH_OMAP3 */
+
+static inline int am33xx_sram_init(void)
+{
+	return 0;
+}
+
+int __init omap_sram_init(void)
+{
+	omap_detect_sram();
+	omap2_map_sram();
+
+	if (cpu_is_omap242x())
+		omap242x_sram_init();
+	else if (cpu_is_omap2430())
+		omap243x_sram_init();
+	else if (soc_is_am33xx())
+		am33xx_sram_init();
+	else if (cpu_is_omap34xx())
+		omap34xx_sram_init();
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap2/sram.h b/arch/arm/mach-omap2/sram.h
new file mode 100644
index 0000000..ca7277c
--- /dev/null
+++ b/arch/arm/mach-omap2/sram.h
@@ -0,0 +1,83 @@
+/*
+ * Interface for functions that need to be run in internal SRAM
+ *
+ * This program is free software; you can 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 __ASSEMBLY__
+#include <plat/sram.h>
+
+extern void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
+				u32 base_cs, u32 force_unlock);
+extern void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
+				      u32 mem_type);
+extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
+
+extern u32 omap3_configure_core_dpll(
+			u32 m2, u32 unlock_dll, u32 f, u32 inc,
+			u32 sdrc_rfr_ctrl_0, u32 sdrc_actim_ctrl_a_0,
+			u32 sdrc_actim_ctrl_b_0, u32 sdrc_mr_0,
+			u32 sdrc_rfr_ctrl_1, u32 sdrc_actim_ctrl_a_1,
+			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
+extern void omap3_sram_restore_context(void);
+
+/* Do not use these */
+extern void omap24xx_sram_reprogram_clock(u32 ckctl, u32 dpllctl);
+extern unsigned long omap24xx_sram_reprogram_clock_sz;
+
+extern void omap242x_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
+						u32 base_cs, u32 force_unlock);
+extern unsigned long omap242x_sram_ddr_init_sz;
+
+extern u32 omap242x_sram_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val,
+						int bypass);
+extern unsigned long omap242x_sram_set_prcm_sz;
+
+extern void omap242x_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
+						u32 mem_type);
+extern unsigned long omap242x_sram_reprogram_sdrc_sz;
+
+
+extern void omap243x_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
+						u32 base_cs, u32 force_unlock);
+extern unsigned long omap243x_sram_ddr_init_sz;
+
+extern u32 omap243x_sram_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val,
+						int bypass);
+extern unsigned long omap243x_sram_set_prcm_sz;
+
+extern void omap243x_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
+						u32 mem_type);
+extern unsigned long omap243x_sram_reprogram_sdrc_sz;
+
+extern u32 omap3_sram_configure_core_dpll(
+			u32 m2, u32 unlock_dll, u32 f, u32 inc,
+			u32 sdrc_rfr_ctrl_0, u32 sdrc_actim_ctrl_a_0,
+			u32 sdrc_actim_ctrl_b_0, u32 sdrc_mr_0,
+			u32 sdrc_rfr_ctrl_1, u32 sdrc_actim_ctrl_a_1,
+			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
+extern unsigned long omap3_sram_configure_core_dpll_sz;
+
+#ifdef CONFIG_PM
+extern void omap_push_sram_idle(void);
+#else
+static inline void omap_push_sram_idle(void) {}
+#endif /* CONFIG_PM */
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * OMAP2+: define the SRAM PA addresses.
+ * Used by the SRAM management code and the idle sleep code.
+ */
+#define OMAP2_SRAM_PA		0x40200000
+#define OMAP3_SRAM_PA           0x40200000
+#ifdef CONFIG_OMAP4_ERRATA_I688
+#define OMAP4_SRAM_PA		0x40304000
+#define OMAP4_SRAM_VA		0xfe404000
+#else
+#define OMAP4_SRAM_PA		0x40300000
+#endif
+#define AM33XX_SRAM_PA		0x40300000
diff --git a/arch/arm/mach-omap2/sram242x.S b/arch/arm/mach-omap2/sram242x.S
index 8f7326c..680a7c5 100644
--- a/arch/arm/mach-omap2/sram242x.S
+++ b/arch/arm/mach-omap2/sram242x.S
@@ -34,8 +34,8 @@
 
 #include "soc.h"
 #include "iomap.h"
-#include "prm2xxx_3xxx.h"
-#include "cm2xxx_3xxx.h"
+#include "prm2xxx.h"
+#include "cm2xxx.h"
 #include "sdrc.h"
 
 	.text
diff --git a/arch/arm/mach-omap2/sram243x.S b/arch/arm/mach-omap2/sram243x.S
index b140d65..a1e9edd 100644
--- a/arch/arm/mach-omap2/sram243x.S
+++ b/arch/arm/mach-omap2/sram243x.S
@@ -34,8 +34,8 @@
 
 #include "soc.h"
 #include "iomap.h"
-#include "prm2xxx_3xxx.h"
-#include "cm2xxx_3xxx.h"
+#include "prm2xxx.h"
+#include "cm2xxx.h"
 #include "sdrc.h"
 
 	.text
diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S
index 2d0ceaa..1446331 100644
--- a/arch/arm/mach-omap2/sram34xx.S
+++ b/arch/arm/mach-omap2/sram34xx.S
@@ -32,7 +32,7 @@
 #include "soc.h"
 #include "iomap.h"
 #include "sdrc.h"
-#include "cm2xxx_3xxx.h"
+#include "cm3xxx.h"
 
 /*
  * This file needs be built unconditionally as ARM to interoperate correctly
diff --git a/arch/arm/mach-omap2/ti81xx.h b/arch/arm/mach-omap2/ti81xx.h
index 8f9843f..a1e6caf 100644
--- a/arch/arm/mach-omap2/ti81xx.h
+++ b/arch/arm/mach-omap2/ti81xx.h
@@ -22,6 +22,15 @@
 #define TI81XX_CTRL_BASE	TI81XX_SCM_BASE
 #define TI81XX_PRCM_BASE	0x48180000
 
+/*
+ * Adjust TAP register base such that omap3_check_revision accesses the correct
+ * TI81XX register for checking device ID (it adds 0x204 to tap base while
+ * TI81XX DEVICE ID register is at offset 0x600 from control base).
+ */
+#define TI81XX_TAP_BASE		(TI81XX_CTRL_BASE + \
+				 TI81XX_CONTROL_DEVICE_ID - 0x204)
+
+
 #define TI81XX_ARM_INTC_BASE	0x48200000
 
 #endif /* __ASM_ARCH_TI81XX_H */
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 69e4663..099e406 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -37,16 +37,19 @@
 #include <linux/clockchips.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <asm/mach/time.h>
 #include <asm/smp_twd.h>
 #include <asm/sched_clock.h>
 
 #include <asm/arch_timer.h>
-#include <plat/omap_hwmod.h>
-#include <plat/omap_device.h>
+#include "omap_hwmod.h"
+#include "omap_device.h"
+#include <plat/counter-32k.h>
 #include <plat/dmtimer.h>
-#include <plat/omap-pm.h>
+#include "omap-pm.h"
 
 #include "soc.h"
 #include "common.h"
@@ -66,11 +69,13 @@
 #define OMAP3_CLKEV_SOURCE	OMAP3_32K_SOURCE
 #define OMAP4_CLKEV_SOURCE	OMAP4_32K_SOURCE
 #define OMAP3_SECURE_TIMER	12
+#define TIMER_PROP_SECURE	"ti,timer-secure"
 #else
 #define OMAP2_CLKEV_SOURCE	OMAP2_MPU_SOURCE
 #define OMAP3_CLKEV_SOURCE	OMAP3_MPU_SOURCE
 #define OMAP4_CLKEV_SOURCE	OMAP4_MPU_SOURCE
 #define OMAP3_SECURE_TIMER	1
+#define TIMER_PROP_SECURE	"ti,timer-alwon"
 #endif
 
 #define REALTIME_COUNTER_BASE				0x48243200
@@ -103,7 +108,7 @@ static int omap2_gp_timer_set_next_event(unsigned long cycles,
 					 struct clock_event_device *evt)
 {
 	__omap_dm_timer_load_start(&clkev, OMAP_TIMER_CTRL_ST,
-						0xffffffff - cycles, 1);
+				   0xffffffff - cycles, OMAP_TIMER_POSTED);
 
 	return 0;
 }
@@ -113,7 +118,7 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
 {
 	u32 period;
 
-	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
+	__omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate);
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
@@ -121,10 +126,10 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
 		period -= 1;
 		/* Looks like we need to first set the load value separately */
 		__omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG,
-					0xffffffff - period, 1);
+				      0xffffffff - period, OMAP_TIMER_POSTED);
 		__omap_dm_timer_load_start(&clkev,
 					OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
-						0xffffffff - period, 1);
+					0xffffffff - period, OMAP_TIMER_POSTED);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
 		break;
@@ -144,36 +149,153 @@ static struct clock_event_device clockevent_gpt = {
 	.set_mode	= omap2_gp_timer_set_mode,
 };
 
+static struct property device_disabled = {
+	.name = "status",
+	.length = sizeof("disabled"),
+	.value = "disabled",
+};
+
+static struct of_device_id omap_timer_match[] __initdata = {
+	{ .compatible = "ti,omap2-timer", },
+	{ }
+};
+
+static struct of_device_id omap_counter_match[] __initdata = {
+	{ .compatible = "ti,omap-counter32k", },
+	{ }
+};
+
+/**
+ * omap_get_timer_dt - get a timer using device-tree
+ * @match	- device-tree match structure for matching a device type
+ * @property	- optional timer property to match
+ *
+ * Helper function to get a timer during early boot using device-tree for use
+ * as kernel system timer. Optionally, the property argument can be used to
+ * select a timer with a specific property. Once a timer is found then mark
+ * the timer node in device-tree as disabled, to prevent the kernel from
+ * registering this timer as a platform device and so no one else can use it.
+ */
+static struct device_node * __init omap_get_timer_dt(struct of_device_id *match,
+						     const char *property)
+{
+	struct device_node *np;
+
+	for_each_matching_node(np, match) {
+		if (!of_device_is_available(np)) {
+			of_node_put(np);
+			continue;
+		}
+
+		if (property && !of_get_property(np, property, NULL)) {
+			of_node_put(np);
+			continue;
+		}
+
+		prom_add_property(np, &device_disabled);
+		return np;
+	}
+
+	return NULL;
+}
+
+/**
+ * omap_dmtimer_init - initialisation function when device tree is used
+ *
+ * For secure OMAP3 devices, timers with device type "timer-secure" cannot
+ * be used by the kernel as they are reserved. Therefore, to prevent the
+ * kernel registering these devices remove them dynamically from the device
+ * tree on boot.
+ */
+void __init omap_dmtimer_init(void)
+{
+	struct device_node *np;
+
+	if (!cpu_is_omap34xx())
+		return;
+
+	/* If we are a secure device, remove any secure timer nodes */
+	if ((omap_type() != OMAP2_DEVICE_TYPE_GP)) {
+		np = omap_get_timer_dt(omap_timer_match, "ti,timer-secure");
+		if (np)
+			of_node_put(np);
+	}
+}
+
+/**
+ * omap_dm_timer_get_errata - get errata flags for a timer
+ *
+ * Get the timer errata flags that are specific to the OMAP device being used.
+ */
+u32 __init omap_dm_timer_get_errata(void)
+{
+	if (cpu_is_omap24xx())
+		return 0;
+
+	return OMAP_TIMER_ERRATA_I103_I767;
+}
+
 static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
 						int gptimer_id,
-						const char *fck_source)
+						const char *fck_source,
+						const char *property,
+						int posted)
 {
 	char name[10]; /* 10 = sizeof("gptXX_Xck0") */
+	const char *oh_name;
+	struct device_node *np;
 	struct omap_hwmod *oh;
 	struct resource irq_rsrc, mem_rsrc;
 	size_t size;
 	int res = 0;
 	int r;
 
-	sprintf(name, "timer%d", gptimer_id);
-	omap_hwmod_setup_one(name);
-	oh = omap_hwmod_lookup(name);
+	if (of_have_populated_dt()) {
+		np = omap_get_timer_dt(omap_timer_match, NULL);
+		if (!np)
+			return -ENODEV;
+
+		of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
+		if (!oh_name)
+			return -ENODEV;
+
+		timer->irq = irq_of_parse_and_map(np, 0);
+		if (!timer->irq)
+			return -ENXIO;
+
+		timer->io_base = of_iomap(np, 0);
+
+		of_node_put(np);
+	} else {
+		if (omap_dm_timer_reserve_systimer(gptimer_id))
+			return -ENODEV;
+
+		sprintf(name, "timer%d", gptimer_id);
+		oh_name = name;
+	}
+
+	oh = omap_hwmod_lookup(oh_name);
 	if (!oh)
 		return -ENODEV;
 
-	r = omap_hwmod_get_resource_byname(oh, IORESOURCE_IRQ, NULL, &irq_rsrc);
-	if (r)
-		return -ENXIO;
-	timer->irq = irq_rsrc.start;
-
-	r = omap_hwmod_get_resource_byname(oh, IORESOURCE_MEM, NULL, &mem_rsrc);
-	if (r)
-		return -ENXIO;
-	timer->phys_base = mem_rsrc.start;
-	size = mem_rsrc.end - mem_rsrc.start;
+	if (!of_have_populated_dt()) {
+		r = omap_hwmod_get_resource_byname(oh, IORESOURCE_IRQ, NULL,
+						   &irq_rsrc);
+		if (r)
+			return -ENXIO;
+		timer->irq = irq_rsrc.start;
+
+		r = omap_hwmod_get_resource_byname(oh, IORESOURCE_MEM, NULL,
+						   &mem_rsrc);
+		if (r)
+			return -ENXIO;
+		timer->phys_base = mem_rsrc.start;
+		size = mem_rsrc.end - mem_rsrc.start;
+
+		/* Static mapping, never released */
+		timer->io_base = ioremap(timer->phys_base, size);
+	}
 
-	/* Static mapping, never released */
-	timer->io_base = ioremap(timer->phys_base, size);
 	if (!timer->io_base)
 		return -ENXIO;
 
@@ -182,11 +304,7 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
 	if (IS_ERR(timer->fclk))
 		return -ENODEV;
 
-	omap_hwmod_enable(oh);
-
-	if (omap_dm_timer_reserve_systimer(gptimer_id))
-		return -ENODEV;
-
+	/* FIXME: Need to remove hard-coded test on timer ID */
 	if (gptimer_id != 12) {
 		struct clk *src;
 
@@ -194,30 +312,48 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
 		if (IS_ERR(src)) {
 			res = -EINVAL;
 		} else {
-			res = __omap_dm_timer_set_source(timer->fclk, src);
+			res = clk_set_parent(timer->fclk, src);
 			if (IS_ERR_VALUE(res))
-				pr_warning("%s: timer%i cannot set source\n",
-						__func__, gptimer_id);
+				pr_warn("%s: %s cannot set source\n",
+					__func__, oh->name);
 			clk_put(src);
 		}
 	}
+
+	omap_hwmod_setup_one(oh_name);
+	omap_hwmod_enable(oh);
 	__omap_dm_timer_init_regs(timer);
-	__omap_dm_timer_reset(timer, 1, 1);
-	timer->posted = 1;
 
-	timer->rate = clk_get_rate(timer->fclk);
+	if (posted)
+		__omap_dm_timer_enable_posted(timer);
+
+	/* Check that the intended posted configuration matches the actual */
+	if (posted != timer->posted)
+		return -EINVAL;
 
+	timer->rate = clk_get_rate(timer->fclk);
 	timer->reserved = 1;
 
 	return res;
 }
 
 static void __init omap2_gp_clockevent_init(int gptimer_id,
-						const char *fck_source)
+						const char *fck_source,
+						const char *property)
 {
 	int res;
 
-	res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source);
+	clkev.errata = omap_dm_timer_get_errata();
+
+	/*
+	 * For clock-event timers we never read the timer counter and
+	 * so we are not impacted by errata i103 and i767. Therefore,
+	 * we can safely ignore this errata for clock-event timers.
+	 */
+	__omap_dm_timer_override_errata(&clkev, OMAP_TIMER_ERRATA_I103_I767);
+
+	res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source, property,
+				     OMAP_TIMER_POSTED);
 	BUG_ON(res);
 
 	omap2_gp_timer_irq.dev_id = &clkev;
@@ -250,7 +386,8 @@ static bool use_gptimer_clksrc;
  */
 static cycle_t clocksource_read_cycles(struct clocksource *cs)
 {
-	return (cycle_t)__omap_dm_timer_read_counter(&clksrc, 1);
+	return (cycle_t)__omap_dm_timer_read_counter(&clksrc,
+						     OMAP_TIMER_NONPOSTED);
 }
 
 static struct clocksource clocksource_gpt = {
@@ -264,7 +401,8 @@ static struct clocksource clocksource_gpt = {
 static u32 notrace dmtimer_read_sched_clock(void)
 {
 	if (clksrc.reserved)
-		return __omap_dm_timer_read_counter(&clksrc, 1);
+		return __omap_dm_timer_read_counter(&clksrc,
+						    OMAP_TIMER_NONPOSTED);
 
 	return 0;
 }
@@ -274,11 +412,26 @@ static u32 notrace dmtimer_read_sched_clock(void)
 static int __init omap2_sync32k_clocksource_init(void)
 {
 	int ret;
+	struct device_node *np = NULL;
 	struct omap_hwmod *oh;
 	void __iomem *vbase;
 	const char *oh_name = "counter_32k";
 
 	/*
+	 * If device-tree is present, then search the DT blob
+	 * to see if the 32kHz counter is supported.
+	 */
+	if (of_have_populated_dt()) {
+		np = omap_get_timer_dt(omap_counter_match, NULL);
+		if (!np)
+			return -ENODEV;
+
+		of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
+		if (!oh_name)
+			return -ENODEV;
+	}
+
+	/*
 	 * First check hwmod data is available for sync32k counter
 	 */
 	oh = omap_hwmod_lookup(oh_name);
@@ -287,7 +440,13 @@ static int __init omap2_sync32k_clocksource_init(void)
 
 	omap_hwmod_setup_one(oh_name);
 
-	vbase = omap_hwmod_get_mpu_rt_va(oh);
+	if (np) {
+		vbase = of_iomap(np, 0);
+		of_node_put(np);
+	} else {
+		vbase = omap_hwmod_get_mpu_rt_va(oh);
+	}
+
 	if (!vbase) {
 		pr_warn("%s: failed to get counter_32k resource\n", __func__);
 		return -ENXIO;
@@ -321,11 +480,15 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id,
 {
 	int res;
 
-	res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source);
+	clksrc.errata = omap_dm_timer_get_errata();
+
+	res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source, NULL,
+				     OMAP_TIMER_NONPOSTED);
 	BUG_ON(res);
 
 	__omap_dm_timer_load_start(&clksrc,
-			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
+				   OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0,
+				   OMAP_TIMER_NONPOSTED);
 	setup_sched_clock(dmtimer_read_sched_clock, 32, clksrc.rate);
 
 	if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
@@ -433,11 +596,12 @@ static inline void __init realtime_counter_init(void)
 {}
 #endif
 
-#define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src,			\
+#define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop,	\
 				clksrc_nr, clksrc_src)			\
 static void __init omap##name##_timer_init(void)			\
 {									\
-	omap2_gp_clockevent_init((clkev_nr), clkev_src);		\
+	omap_dmtimer_init();						\
+	omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);	\
 	omap2_clocksource_init((clksrc_nr), clksrc_src);		\
 }
 
@@ -447,20 +611,23 @@ struct sys_timer omap##name##_timer = {					\
 };
 
 #ifdef CONFIG_ARCH_OMAP2
-OMAP_SYS_TIMER_INIT(2, 1, OMAP2_CLKEV_SOURCE, 2, OMAP2_MPU_SOURCE)
+OMAP_SYS_TIMER_INIT(2, 1, OMAP2_CLKEV_SOURCE, "ti,timer-alwon",
+		    2, OMAP2_MPU_SOURCE)
 OMAP_SYS_TIMER(2)
 #endif
 
 #ifdef CONFIG_ARCH_OMAP3
-OMAP_SYS_TIMER_INIT(3, 1, OMAP3_CLKEV_SOURCE, 2, OMAP3_MPU_SOURCE)
+OMAP_SYS_TIMER_INIT(3, 1, OMAP3_CLKEV_SOURCE, "ti,timer-alwon",
+		    2, OMAP3_MPU_SOURCE)
 OMAP_SYS_TIMER(3)
 OMAP_SYS_TIMER_INIT(3_secure, OMAP3_SECURE_TIMER, OMAP3_CLKEV_SOURCE,
-			2, OMAP3_MPU_SOURCE)
+			TIMER_PROP_SECURE, 2, OMAP3_MPU_SOURCE)
 OMAP_SYS_TIMER(3_secure)
 #endif
 
 #ifdef CONFIG_SOC_AM33XX
-OMAP_SYS_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, 2, OMAP4_MPU_SOURCE)
+OMAP_SYS_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, "ti,timer-alwon",
+		    2, OMAP4_MPU_SOURCE)
 OMAP_SYS_TIMER(3_am33xx)
 #endif
 
@@ -472,7 +639,7 @@ static DEFINE_TWD_LOCAL_TIMER(twd_local_timer,
 
 static void __init omap4_timer_init(void)
 {
-	omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE);
+	omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE, "ti,timer-alwon");
 	omap2_clocksource_init(2, OMAP4_MPU_SOURCE);
 #ifdef CONFIG_LOCAL_TIMERS
 	/* Local timers are not supprted on OMAP4430 ES1.0 */
@@ -498,7 +665,7 @@ static void __init omap5_timer_init(void)
 {
 	int err;
 
-	omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE);
+	omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE, "ti,timer-alwon");
 	omap2_clocksource_init(2, OMAP4_MPU_SOURCE);
 	realtime_counter_init();
 
@@ -559,6 +726,9 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
 	if (timer_dev_attr)
 		pdata->timer_capability = timer_dev_attr->timer_capability;
 
+	pdata->timer_errata = omap_dm_timer_get_errata();
+	pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
+
 	pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
 				 NULL, 0, 0);
 
@@ -583,6 +753,10 @@ static int __init omap2_dm_timer_init(void)
 {
 	int ret;
 
+	/* If dtb is there, the devices will be created dynamically */
+	if (of_have_populated_dt())
+		return -ENODEV;
+
 	ret = omap_hwmod_for_each_by_class("timer", omap_timer_init, NULL);
 	if (unlikely(ret)) {
 		pr_err("%s: device registration failed.\n", __func__);
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
index a256135..e49b40b 100644
--- a/arch/arm/mach-omap2/twl-common.c
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -26,9 +26,6 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 
-#include <plat/i2c.h>
-#include <plat/usb.h>
-
 #include "soc.h"
 #include "twl-common.h"
 #include "pm.h"
diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c
index 3c43449..d1dbe12 100644
--- a/arch/arm/mach-omap2/usb-host.c
+++ b/arch/arm/mach-omap2/usb-host.c
@@ -25,10 +25,10 @@
 
 #include <asm/io.h>
 
-#include <plat/usb.h>
-#include <plat/omap_device.h>
-
+#include "soc.h"
+#include "omap_device.h"
 #include "mux.h"
+#include "usb.h"
 
 #ifdef CONFIG_MFD_OMAP_USB_HOST
 
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 51da21c..7b33b37 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -25,12 +25,10 @@
 #include <linux/io.h>
 #include <linux/usb/musb.h>
 
-#include <plat/usb.h>
-#include <plat/omap_device.h>
-
-#include "am35xx.h"
-
+#include "omap_device.h"
+#include "soc.h"
 #include "mux.h"
+#include "usb.h"
 
 static struct musb_hdrc_config musb_config = {
 	.multipoint	= 1,
diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c
index 805bea6..c5a3c6f 100644
--- a/arch/arm/mach-omap2/usb-tusb6010.c
+++ b/arch/arm/mach-omap2/usb-tusb6010.c
@@ -15,10 +15,11 @@
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/export.h>
+#include <linux/platform_data/usb-omap.h>
 
 #include <linux/usb/musb.h>
 
-#include <plat/gpmc.h>
+#include "gpmc.h"
 
 #include "mux.h"
 
@@ -26,180 +27,88 @@ static u8		async_cs, sync_cs;
 static unsigned		refclk_psec;
 
 
-/* t2_ps, when quantized to fclk units, must happen no earlier than
- * the clock after after t1_NS.
- *
- * Return a possibly updated value of t2_ps, converted to nsec.
- */
-static unsigned
-next_clk(unsigned t1_NS, unsigned t2_ps, unsigned fclk_ps)
-{
-	unsigned	t1_ps = t1_NS * 1000;
-	unsigned	t1_f, t2_f;
-
-	if ((t1_ps + fclk_ps) < t2_ps)
-		return t2_ps / 1000;
-
-	t1_f = (t1_ps + fclk_ps - 1) / fclk_ps;
-	t2_f = (t2_ps + fclk_ps - 1) / fclk_ps;
-
-	if (t1_f >= t2_f)
-		t2_f = t1_f + 1;
-
-	return (t2_f * fclk_ps) / 1000;
-}
-
 /* NOTE:  timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */
 
-static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
+static int tusb_set_async_mode(unsigned sysclk_ps)
 {
+	struct gpmc_device_timings dev_t;
 	struct gpmc_timings	t;
 	unsigned		t_acsnh_advnh = sysclk_ps + 3000;
-	unsigned		tmp;
-
-	memset(&t, 0, sizeof(t));
-
-	/* CS_ON = t_acsnh_acsnl */
-	t.cs_on = 8;
-	/* ADV_ON = t_acsnh_advnh - t_advn */
-	t.adv_on = next_clk(t.cs_on, t_acsnh_advnh - 7000, fclk_ps);
-
-	/*
-	 * READ ... from omap2420 TRM fig 12-13
-	 */
-
-	/* ADV_RD_OFF = t_acsnh_advnh */
-	t.adv_rd_off = next_clk(t.adv_on, t_acsnh_advnh, fclk_ps);
-
-	/* OE_ON = t_acsnh_advnh + t_advn_oen (then wait for nRDY) */
-	t.oe_on = next_clk(t.adv_on, t_acsnh_advnh + 1000, fclk_ps);
-
-	/* ACCESS = counters continue only after nRDY */
-	tmp = t.oe_on * 1000 + 300;
-	t.access = next_clk(t.oe_on, tmp, fclk_ps);
-
-	/* OE_OFF = after data gets sampled */
-	tmp = t.access * 1000;
-	t.oe_off = next_clk(t.access, tmp, fclk_ps);
-
-	t.cs_rd_off = t.oe_off;
-
-	tmp = t.cs_rd_off * 1000 + 7000 /* t_acsn_rdy_z */;
-	t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps);
-
-	/*
-	 * WRITE ... from omap2420 TRM fig 12-15
-	 */
-
-	/* ADV_WR_OFF = t_acsnh_advnh */
-	t.adv_wr_off = t.adv_rd_off;
 
-	/* WE_ON = t_acsnh_advnh + t_advn_wen (then wait for nRDY) */
-	t.we_on = next_clk(t.adv_wr_off, t_acsnh_advnh + 1000, fclk_ps);
+	memset(&dev_t, 0, sizeof(dev_t));
 
-	/* WE_OFF = after data gets sampled */
-	tmp = t.we_on * 1000 + 300;
-	t.we_off = next_clk(t.we_on, tmp, fclk_ps);
+	dev_t.mux = true;
 
-	t.cs_wr_off = t.we_off;
+	dev_t.t_ceasu = 8 * 1000;
+	dev_t.t_avdasu = t_acsnh_advnh - 7000;
+	dev_t.t_ce_avd = 1000;
+	dev_t.t_avdp_r = t_acsnh_advnh;
+	dev_t.t_oeasu = t_acsnh_advnh + 1000;
+	dev_t.t_oe = 300;
+	dev_t.t_cez_r = 7000;
+	dev_t.t_cez_w = dev_t.t_cez_r;
+	dev_t.t_avdp_w = t_acsnh_advnh;
+	dev_t.t_weasu = t_acsnh_advnh + 1000;
+	dev_t.t_wpl = 300;
+	dev_t.cyc_aavdh_we = 1;
 
-	tmp = t.cs_wr_off * 1000 + 7000 /* t_acsn_rdy_z */;
-	t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
+	gpmc_calc_timings(&t, &dev_t);
 
 	return gpmc_cs_set_timings(async_cs, &t);
 }
 
-static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
+static int tusb_set_sync_mode(unsigned sysclk_ps)
 {
+	struct gpmc_device_timings dev_t;
 	struct gpmc_timings	t;
 	unsigned		t_scsnh_advnh = sysclk_ps + 3000;
-	unsigned		tmp;
-
-	memset(&t, 0, sizeof(t));
-	t.cs_on = 8;
-
-	/* ADV_ON = t_acsnh_advnh - t_advn */
-	t.adv_on = next_clk(t.cs_on, t_scsnh_advnh - 7000, fclk_ps);
-
-	/* GPMC_CLK rate = fclk rate / div */
-	t.sync_clk = 11100 /* 11.1 nsec */;
-	tmp = (t.sync_clk + fclk_ps - 1) / fclk_ps;
-	if (tmp > 4)
-		return -ERANGE;
-	if (tmp == 0)
-		tmp = 1;
-	t.page_burst_access = (fclk_ps * tmp) / 1000;
-
-	/*
-	 * READ ... based on omap2420 TRM fig 12-19, 12-20
-	 */
-
-	/* ADV_RD_OFF = t_scsnh_advnh */
-	t.adv_rd_off = next_clk(t.adv_on, t_scsnh_advnh, fclk_ps);
-
-	/* OE_ON = t_scsnh_advnh + t_advn_oen * fclk_ps (then wait for nRDY) */
-	tmp = (t.adv_rd_off * 1000) + (3 * fclk_ps);
-	t.oe_on = next_clk(t.adv_on, tmp, fclk_ps);
-
-	/* ACCESS = number of clock cycles after t_adv_eon */
-	tmp = (t.oe_on * 1000) + (5 * fclk_ps);
-	t.access = next_clk(t.oe_on, tmp, fclk_ps);
 
-	/* OE_OFF = after data gets sampled */
-	tmp = (t.access * 1000) + (1 * fclk_ps);
-	t.oe_off = next_clk(t.access, tmp, fclk_ps);
-
-	t.cs_rd_off = t.oe_off;
-
-	tmp = t.cs_rd_off * 1000 + 7000 /* t_scsn_rdy_z */;
-	t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps);
-
-	/*
-	 * WRITE ... based on omap2420 TRM fig 12-21
-	 */
-
-	/* ADV_WR_OFF = t_scsnh_advnh */
-	t.adv_wr_off = t.adv_rd_off;
-
-	/* WE_ON = t_scsnh_advnh + t_advn_wen * fclk_ps (then wait for nRDY) */
-	tmp = (t.adv_wr_off * 1000) + (3 * fclk_ps);
-	t.we_on = next_clk(t.adv_wr_off, tmp, fclk_ps);
-
-	/* WE_OFF = number of clock cycles after t_adv_wen */
-	tmp = (t.we_on * 1000) + (6 * fclk_ps);
-	t.we_off = next_clk(t.we_on, tmp, fclk_ps);
-
-	t.cs_wr_off = t.we_off;
-
-	tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */;
-	t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
+	memset(&dev_t, 0, sizeof(dev_t));
+
+	dev_t.mux = true;
+	dev_t.sync_read = true;
+	dev_t.sync_write = true;
+
+	dev_t.clk = 11100;
+	dev_t.t_bacc = 1000;
+	dev_t.t_ces = 1000;
+	dev_t.t_ceasu = 8 * 1000;
+	dev_t.t_avdasu = t_scsnh_advnh - 7000;
+	dev_t.t_ce_avd = 1000;
+	dev_t.t_avdp_r = t_scsnh_advnh;
+	dev_t.cyc_aavdh_oe = 3;
+	dev_t.cyc_oe = 5;
+	dev_t.t_ce_rdyz = 7000;
+	dev_t.t_avdp_w = t_scsnh_advnh;
+	dev_t.cyc_aavdh_we = 3;
+	dev_t.cyc_wpl = 6;
+	dev_t.t_ce_rdyz = 7000;
+
+	gpmc_calc_timings(&t, &dev_t);
 
 	return gpmc_cs_set_timings(sync_cs, &t);
 }
 
-extern unsigned long gpmc_get_fclk_period(void);
-
 /* tusb driver calls this when it changes the chip's clocking */
 int tusb6010_platform_retime(unsigned is_refclk)
 {
 	static const char	error[] =
 		KERN_ERR "tusb6010 %s retime error %d\n";
 
-	unsigned	fclk_ps = gpmc_get_fclk_period();
 	unsigned	sysclk_ps;
 	int		status;
 
-	if (!refclk_psec || fclk_ps == 0)
+	if (!refclk_psec)
 		return -ENODEV;
 
 	sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60;
 
-	status = tusb_set_async_mode(sysclk_ps, fclk_ps);
+	status = tusb_set_async_mode(sysclk_ps);
 	if (status < 0) {
 		printk(error, "async", status);
 		goto done;
 	}
-	status = tusb_set_sync_mode(sysclk_ps, fclk_ps);
+	status = tusb_set_sync_mode(sysclk_ps);
 	if (status < 0)
 		printk(error, "sync", status);
 done:
@@ -283,7 +192,6 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
 			| GPMC_CONFIG1_READTYPE_SYNC
 			| GPMC_CONFIG1_WRITEMULTIPLE_SUPP
 			| GPMC_CONFIG1_WRITETYPE_SYNC
-			| GPMC_CONFIG1_CLKACTIVATIONTIME(1)
 			| GPMC_CONFIG1_PAGE_LEN(2)
 			| GPMC_CONFIG1_WAIT_READ_MON
 			| GPMC_CONFIG1_WAIT_WRITE_MON
diff --git a/arch/arm/mach-omap2/usb.h b/arch/arm/mach-omap2/usb.h
new file mode 100644
index 0000000..9b986ea
--- /dev/null
+++ b/arch/arm/mach-omap2/usb.h
@@ -0,0 +1,82 @@
+#include <linux/platform_data/usb-omap.h>
+
+/* AM35x */
+/* USB 2.0 PHY Control */
+#define CONF2_PHY_GPIOMODE	(1 << 23)
+#define CONF2_OTGMODE		(3 << 14)
+#define CONF2_NO_OVERRIDE	(0 << 14)
+#define CONF2_FORCE_HOST	(1 << 14)
+#define CONF2_FORCE_DEVICE	(2 << 14)
+#define CONF2_FORCE_HOST_VBUS_LOW (3 << 14)
+#define CONF2_SESENDEN		(1 << 13)
+#define CONF2_VBDTCTEN		(1 << 12)
+#define CONF2_REFFREQ_24MHZ	(2 << 8)
+#define CONF2_REFFREQ_26MHZ	(7 << 8)
+#define CONF2_REFFREQ_13MHZ	(6 << 8)
+#define CONF2_REFFREQ		(0xf << 8)
+#define CONF2_PHYCLKGD		(1 << 7)
+#define CONF2_VBUSSENSE		(1 << 6)
+#define CONF2_PHY_PLLON		(1 << 5)
+#define CONF2_RESET		(1 << 4)
+#define CONF2_PHYPWRDN		(1 << 3)
+#define CONF2_OTGPWRDN		(1 << 2)
+#define CONF2_DATPOL		(1 << 1)
+
+/* TI81XX specific definitions */
+#define USBCTRL0	0x620
+#define USBSTAT0	0x624
+
+/* TI816X PHY controls bits */
+#define TI816X_USBPHY0_NORMAL_MODE	(1 << 0)
+#define TI816X_USBPHY_REFCLK_OSC	(1 << 8)
+
+/* TI814X PHY controls bits */
+#define USBPHY_CM_PWRDN		(1 << 0)
+#define USBPHY_OTG_PWRDN	(1 << 1)
+#define USBPHY_CHGDET_DIS	(1 << 2)
+#define USBPHY_CHGDET_RSTRT	(1 << 3)
+#define USBPHY_SRCONDM		(1 << 4)
+#define USBPHY_SINKONDP		(1 << 5)
+#define USBPHY_CHGISINK_EN	(1 << 6)
+#define USBPHY_CHGVSRC_EN	(1 << 7)
+#define USBPHY_DMPULLUP		(1 << 8)
+#define USBPHY_DPPULLUP		(1 << 9)
+#define USBPHY_CDET_EXTCTL	(1 << 10)
+#define USBPHY_GPIO_MODE	(1 << 12)
+#define USBPHY_DPOPBUFCTL	(1 << 13)
+#define USBPHY_DMOPBUFCTL	(1 << 14)
+#define USBPHY_DPINPUT		(1 << 15)
+#define USBPHY_DMINPUT		(1 << 16)
+#define USBPHY_DPGPIO_PD	(1 << 17)
+#define USBPHY_DMGPIO_PD	(1 << 18)
+#define USBPHY_OTGVDET_EN	(1 << 19)
+#define USBPHY_OTGSESSEND_EN	(1 << 20)
+#define USBPHY_DATA_POLARITY	(1 << 23)
+
+struct usbhs_omap_board_data {
+	enum usbhs_omap_port_mode	port_mode[OMAP3_HS_USB_PORTS];
+
+	/* have to be valid if phy_reset is true and portx is in phy mode */
+	int	reset_gpio_port[OMAP3_HS_USB_PORTS];
+
+	/* Set this to true for ES2.x silicon */
+	unsigned			es2_compatibility:1;
+
+	unsigned			phy_reset:1;
+
+	/*
+	 * Regulators for USB PHYs.
+	 * Each PHY can have a separate regulator.
+	 */
+	struct regulator		*regulator[OMAP3_HS_USB_PORTS];
+};
+
+extern void usb_musb_init(struct omap_musb_board_data *board_data);
+extern void usbhs_init(const struct usbhs_omap_board_data *pdata);
+
+extern void am35x_musb_reset(void);
+extern void am35x_musb_phy_power(u8 on);
+extern void am35x_musb_clear_irq(void);
+extern void am35x_set_mode(u8 musb_mode);
+extern void ti81xx_musb_phy_power(u8 on);
+
diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c
index 75878c3..49ac797 100644
--- a/arch/arm/mach-omap2/vc.c
+++ b/arch/arm/mach-omap2/vc.c
@@ -11,13 +11,20 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/bug.h>
+#include <linux/io.h>
 
+#include <asm/div64.h>
+
+#include "iomap.h"
 #include "soc.h"
 #include "voltage.h"
 #include "vc.h"
 #include "prm-regbits-34xx.h"
 #include "prm-regbits-44xx.h"
 #include "prm44xx.h"
+#include "pm.h"
+#include "scrm44xx.h"
+#include "control.h"
 
 /**
  * struct omap_vc_channel_cfg - describe the cfg_channel bitfield
@@ -63,6 +70,9 @@ static struct omap_vc_channel_cfg vc_mutant_channel_cfg = {
 };
 
 static struct omap_vc_channel_cfg *vc_cfg_bits;
+
+/* Default I2C trace length on pcb, 6.3cm. Used for capacitance calculations. */
+static u32 sr_i2c_pcb_length = 63;
 #define CFG_CHANNEL_MASK 0x1f
 
 /**
@@ -135,6 +145,8 @@ int omap_vc_pre_scale(struct voltagedomain *voltdm,
 	vc_cmdval |= (*target_vsel << vc->common->cmd_on_shift);
 	voltdm->write(vc_cmdval, vc->cmdval_reg);
 
+	voltdm->vc_param->on = target_volt;
+
 	omap_vp_update_errorgain(voltdm, target_volt);
 
 	return 0;
@@ -202,46 +214,389 @@ int omap_vc_bypass_scale(struct voltagedomain *voltdm,
 	return 0;
 }
 
-static void __init omap3_vfsm_init(struct voltagedomain *voltdm)
+/* Convert microsecond value to number of 32kHz clock cycles */
+static inline u32 omap_usec_to_32k(u32 usec)
+{
+	return DIV_ROUND_UP_ULL(32768ULL * (u64)usec, 1000000ULL);
+}
+
+/* Set oscillator setup time for omap3 */
+static void omap3_set_clksetup(u32 usec, struct voltagedomain *voltdm)
+{
+	voltdm->write(omap_usec_to_32k(usec), OMAP3_PRM_CLKSETUP_OFFSET);
+}
+
+/**
+ * omap3_set_i2c_timings - sets i2c sleep timings for a channel
+ * @voltdm: channel to configure
+ * @off_mode: select whether retention or off mode values used
+ *
+ * Calculates and sets up voltage controller to use I2C based
+ * voltage scaling for sleep modes. This can be used for either off mode
+ * or retention. Off mode has additionally an option to use sys_off_mode
+ * pad, which uses a global signal to program the whole power IC to
+ * off-mode.
+ */
+static void omap3_set_i2c_timings(struct voltagedomain *voltdm, bool off_mode)
 {
+	unsigned long voltsetup1;
+	u32 tgt_volt;
+
+	/*
+	 * Oscillator is shut down only if we are using sys_off_mode pad,
+	 * thus we set a minimal setup time here
+	 */
+	omap3_set_clksetup(1, voltdm);
+
+	if (off_mode)
+		tgt_volt = voltdm->vc_param->off;
+	else
+		tgt_volt = voltdm->vc_param->ret;
+
+	voltsetup1 = (voltdm->vc_param->on - tgt_volt) /
+			voltdm->pmic->slew_rate;
+
+	voltsetup1 = voltsetup1 * voltdm->sys_clk.rate / 8 / 1000000 + 1;
+
+	voltdm->rmw(voltdm->vfsm->voltsetup_mask,
+		voltsetup1 << __ffs(voltdm->vfsm->voltsetup_mask),
+		voltdm->vfsm->voltsetup_reg);
+
 	/*
-	 * Voltage Manager FSM parameters init
-	 * XXX This data should be passed in from the board file
+	 * pmic is not controlling the voltage scaling during retention,
+	 * thus set voltsetup2 to 0
 	 */
-	voltdm->write(OMAP3_CLKSETUP, OMAP3_PRM_CLKSETUP_OFFSET);
-	voltdm->write(OMAP3_VOLTOFFSET, OMAP3_PRM_VOLTOFFSET_OFFSET);
-	voltdm->write(OMAP3_VOLTSETUP2, OMAP3_PRM_VOLTSETUP2_OFFSET);
+	voltdm->write(0, OMAP3_PRM_VOLTSETUP2_OFFSET);
 }
 
-static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
+/**
+ * omap3_set_off_timings - sets off-mode timings for a channel
+ * @voltdm: channel to configure
+ *
+ * Calculates and sets up off-mode timings for a channel. Off-mode
+ * can use either I2C based voltage scaling, or alternatively
+ * sys_off_mode pad can be used to send a global command to power IC.
+ * This function first checks which mode is being used, and calls
+ * omap3_set_i2c_timings() if the system is using I2C control mode.
+ * sys_off_mode has the additional benefit that voltages can be
+ * scaled to zero volt level with TWL4030 / TWL5030, I2C can only
+ * scale to 600mV.
+ */
+static void omap3_set_off_timings(struct voltagedomain *voltdm)
 {
-	static bool is_initialized;
+	unsigned long clksetup;
+	unsigned long voltsetup2;
+	unsigned long voltsetup2_old;
+	u32 val;
+	u32 tstart, tshut;
 
-	if (is_initialized)
+	/* check if sys_off_mode is used to control off-mode voltages */
+	val = voltdm->read(OMAP3_PRM_VOLTCTRL_OFFSET);
+	if (!(val & OMAP3430_SEL_OFF_MASK)) {
+		/* No, omap is controlling them over I2C */
+		omap3_set_i2c_timings(voltdm, true);
 		return;
+	}
+
+	omap_pm_get_oscillator(&tstart, &tshut);
+	omap3_set_clksetup(tstart, voltdm);
+
+	clksetup = voltdm->read(OMAP3_PRM_CLKSETUP_OFFSET);
+
+	/* voltsetup 2 in us */
+	voltsetup2 = voltdm->vc_param->on / voltdm->pmic->slew_rate;
+
+	/* convert to 32k clk cycles */
+	voltsetup2 = DIV_ROUND_UP(voltsetup2 * 32768, 1000000);
+
+	voltsetup2_old = voltdm->read(OMAP3_PRM_VOLTSETUP2_OFFSET);
+
+	/*
+	 * Update voltsetup2 if higher than current value (needed because
+	 * we have multiple channels with different ramp times), also
+	 * update voltoffset always to value recommended by TRM
+	 */
+	if (voltsetup2 > voltsetup2_old) {
+		voltdm->write(voltsetup2, OMAP3_PRM_VOLTSETUP2_OFFSET);
+		voltdm->write(clksetup - voltsetup2,
+			OMAP3_PRM_VOLTOFFSET_OFFSET);
+	} else
+		voltdm->write(clksetup - voltsetup2_old,
+			OMAP3_PRM_VOLTOFFSET_OFFSET);
+
+	/*
+	 * omap is not controlling voltage scaling during off-mode,
+	 * thus set voltsetup1 to 0
+	 */
+	voltdm->rmw(voltdm->vfsm->voltsetup_mask, 0,
+		voltdm->vfsm->voltsetup_reg);
+
+	/* voltoffset must be clksetup minus voltsetup2 according to TRM */
+	voltdm->write(clksetup - voltsetup2, OMAP3_PRM_VOLTOFFSET_OFFSET);
+}
+
+static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
+{
+	omap3_set_off_timings(voltdm);
+}
+
+/**
+ * omap4_calc_volt_ramp - calculates voltage ramping delays on omap4
+ * @voltdm: channel to calculate values for
+ * @voltage_diff: voltage difference in microvolts
+ *
+ * Calculates voltage ramp prescaler + counter values for a voltage
+ * difference on omap4. Returns a field value suitable for writing to
+ * VOLTSETUP register for a channel in following format:
+ * bits[8:9] prescaler ... bits[0:5] counter. See OMAP4 TRM for reference.
+ */
+static u32 omap4_calc_volt_ramp(struct voltagedomain *voltdm, u32 voltage_diff)
+{
+	u32 prescaler;
+	u32 cycles;
+	u32 time;
+
+	time = voltage_diff / voltdm->pmic->slew_rate;
+
+	cycles = voltdm->sys_clk.rate / 1000 * time / 1000;
+
+	cycles /= 64;
+	prescaler = 0;
+
+	/* shift to next prescaler until no overflow */
+
+	/* scale for div 256 = 64 * 4 */
+	if (cycles > 63) {
+		cycles /= 4;
+		prescaler++;
+	}
+
+	/* scale for div 512 = 256 * 2 */
+	if (cycles > 63) {
+		cycles /= 2;
+		prescaler++;
+	}
+
+	/* scale for div 2048 = 512 * 4 */
+	if (cycles > 63) {
+		cycles /= 4;
+		prescaler++;
+	}
+
+	/* check for overflow => invalid ramp time */
+	if (cycles > 63) {
+		pr_warn("%s: invalid setuptime for vdd_%s\n", __func__,
+			voltdm->name);
+		return 0;
+	}
+
+	cycles++;
 
-	omap3_vfsm_init(voltdm);
+	return (prescaler << OMAP4430_RAMP_UP_PRESCAL_SHIFT) |
+		(cycles << OMAP4430_RAMP_UP_COUNT_SHIFT);
+}
+
+/**
+ * omap4_usec_to_val_scrm - convert microsecond value to SCRM module bitfield
+ * @usec: microseconds
+ * @shift: number of bits to shift left
+ * @mask: bitfield mask
+ *
+ * Converts microsecond value to OMAP4 SCRM bitfield. Bitfield is
+ * shifted to requested position, and checked agains the mask value.
+ * If larger, forced to the max value of the field (i.e. the mask itself.)
+ * Returns the SCRM bitfield value.
+ */
+static u32 omap4_usec_to_val_scrm(u32 usec, int shift, u32 mask)
+{
+	u32 val;
+
+	val = omap_usec_to_32k(usec) << shift;
 
-	is_initialized = true;
+	/* Check for overflow, if yes, force to max value */
+	if (val > mask)
+		val = mask;
+
+	return val;
 }
 
+/**
+ * omap4_set_timings - set voltage ramp timings for a channel
+ * @voltdm: channel to configure
+ * @off_mode: whether off-mode values are used
+ *
+ * Calculates and sets the voltage ramp up / down values for a channel.
+ */
+static void omap4_set_timings(struct voltagedomain *voltdm, bool off_mode)
+{
+	u32 val;
+	u32 ramp;
+	int offset;
+	u32 tstart, tshut;
+
+	if (off_mode) {
+		ramp = omap4_calc_volt_ramp(voltdm,
+			voltdm->vc_param->on - voltdm->vc_param->off);
+		offset = voltdm->vfsm->voltsetup_off_reg;
+	} else {
+		ramp = omap4_calc_volt_ramp(voltdm,
+			voltdm->vc_param->on - voltdm->vc_param->ret);
+		offset = voltdm->vfsm->voltsetup_reg;
+	}
+
+	if (!ramp)
+		return;
+
+	val = voltdm->read(offset);
+
+	val |= ramp << OMAP4430_RAMP_DOWN_COUNT_SHIFT;
+
+	val |= ramp << OMAP4430_RAMP_UP_COUNT_SHIFT;
+
+	voltdm->write(val, offset);
+
+	omap_pm_get_oscillator(&tstart, &tshut);
+
+	val = omap4_usec_to_val_scrm(tstart, OMAP4_SETUPTIME_SHIFT,
+		OMAP4_SETUPTIME_MASK);
+	val |= omap4_usec_to_val_scrm(tshut, OMAP4_DOWNTIME_SHIFT,
+		OMAP4_DOWNTIME_MASK);
+
+	__raw_writel(val, OMAP4_SCRM_CLKSETUPTIME);
+}
 
 /* OMAP4 specific voltage init functions */
 static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
 {
-	static bool is_initialized;
-	u32 vc_val;
+	omap4_set_timings(voltdm, true);
+	omap4_set_timings(voltdm, false);
+}
+
+struct i2c_init_data {
+	u8 loadbits;
+	u8 load;
+	u8 hsscll_38_4;
+	u8 hsscll_26;
+	u8 hsscll_19_2;
+	u8 hsscll_16_8;
+	u8 hsscll_12;
+};
 
-	if (is_initialized)
+static const __initdata struct i2c_init_data omap4_i2c_timing_data[] = {
+	{
+		.load = 50,
+		.loadbits = 0x3,
+		.hsscll_38_4 = 13,
+		.hsscll_26 = 11,
+		.hsscll_19_2 = 9,
+		.hsscll_16_8 = 9,
+		.hsscll_12 = 8,
+	},
+	{
+		.load = 25,
+		.loadbits = 0x2,
+		.hsscll_38_4 = 13,
+		.hsscll_26 = 11,
+		.hsscll_19_2 = 9,
+		.hsscll_16_8 = 9,
+		.hsscll_12 = 8,
+	},
+	{
+		.load = 12,
+		.loadbits = 0x1,
+		.hsscll_38_4 = 11,
+		.hsscll_26 = 10,
+		.hsscll_19_2 = 9,
+		.hsscll_16_8 = 9,
+		.hsscll_12 = 8,
+	},
+	{
+		.load = 0,
+		.loadbits = 0x0,
+		.hsscll_38_4 = 12,
+		.hsscll_26 = 10,
+		.hsscll_19_2 = 9,
+		.hsscll_16_8 = 8,
+		.hsscll_12 = 8,
+	},
+};
+
+/**
+ * omap4_vc_i2c_timing_init - sets up board I2C timing parameters
+ * @voltdm: voltagedomain pointer to get data from
+ *
+ * Use PMIC + board supplied settings for calculating the total I2C
+ * channel capacitance and set the timing parameters based on this.
+ * Pre-calculated values are provided in data tables, as it is not
+ * too straightforward to calculate these runtime.
+ */
+static void __init omap4_vc_i2c_timing_init(struct voltagedomain *voltdm)
+{
+	u32 capacitance;
+	u32 val;
+	u16 hsscll;
+	const struct i2c_init_data *i2c_data;
+
+	if (!voltdm->pmic->i2c_high_speed) {
+		pr_warn("%s: only high speed supported!\n", __func__);
 		return;
+	}
+
+	/* PCB trace capacitance, 0.125pF / mm => mm / 8 */
+	capacitance = DIV_ROUND_UP(sr_i2c_pcb_length, 8);
+
+	/* OMAP pad capacitance */
+	capacitance += 4;
+
+	/* PMIC pad capacitance */
+	capacitance += voltdm->pmic->i2c_pad_load;
+
+	/* Search for capacitance match in the table */
+	i2c_data = omap4_i2c_timing_data;
+
+	while (i2c_data->load > capacitance)
+		i2c_data++;
+
+	/* Select proper values based on sysclk frequency */
+	switch (voltdm->sys_clk.rate) {
+	case 38400000:
+		hsscll = i2c_data->hsscll_38_4;
+		break;
+	case 26000000:
+		hsscll = i2c_data->hsscll_26;
+		break;
+	case 19200000:
+		hsscll = i2c_data->hsscll_19_2;
+		break;
+	case 16800000:
+		hsscll = i2c_data->hsscll_16_8;
+		break;
+	case 12000000:
+		hsscll = i2c_data->hsscll_12;
+		break;
+	default:
+		pr_warn("%s: unsupported sysclk rate: %d!\n", __func__,
+			voltdm->sys_clk.rate);
+		return;
+	}
 
-	/* XXX These are magic numbers and do not belong! */
-	vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
-	voltdm->write(vc_val, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
+	/* Loadbits define pull setup for the I2C channels */
+	val = i2c_data->loadbits << 25 | i2c_data->loadbits << 29;
 
-	is_initialized = true;
+	/* Write to SYSCTRL_PADCONF_WKUP_CTRL_I2C_2 to setup I2C pull */
+	__raw_writel(val, OMAP2_L4_IO_ADDRESS(OMAP4_CTRL_MODULE_PAD_WKUP +
+				OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_I2C_2));
+
+	/* HSSCLH can always be zero */
+	val = hsscll << OMAP4430_HSSCLL_SHIFT;
+	val |= (0x28 << OMAP4430_SCLL_SHIFT | 0x2c << OMAP4430_SCLH_SHIFT);
+
+	/* Write setup times to I2C config register */
+	voltdm->write(val, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
 }
 
+
+
 /**
  * omap_vc_i2c_init - initialize I2C interface to PMIC
  * @voltdm: voltage domain containing VC data
@@ -281,9 +636,51 @@ static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
 			    mcode << __ffs(vc->common->i2c_mcode_mask),
 			    vc->common->i2c_cfg_reg);
 
+	if (cpu_is_omap44xx())
+		omap4_vc_i2c_timing_init(voltdm);
+
 	initialized = true;
 }
 
+/**
+ * omap_vc_calc_vsel - calculate vsel value for a channel
+ * @voltdm: channel to calculate value for
+ * @uvolt: microvolt value to convert to vsel
+ *
+ * Converts a microvolt value to vsel value for the used PMIC.
+ * This checks whether the microvolt value is out of bounds, and
+ * adjusts the value accordingly. If unsupported value detected,
+ * warning is thrown.
+ */
+static u8 omap_vc_calc_vsel(struct voltagedomain *voltdm, u32 uvolt)
+{
+	if (voltdm->pmic->vddmin > uvolt)
+		uvolt = voltdm->pmic->vddmin;
+	if (voltdm->pmic->vddmax < uvolt) {
+		WARN(1, "%s: voltage not supported by pmic: %u vs max %u\n",
+			__func__, uvolt, voltdm->pmic->vddmax);
+		/* Lets try maximum value anyway */
+		uvolt = voltdm->pmic->vddmax;
+	}
+
+	return voltdm->pmic->uv_to_vsel(uvolt);
+}
+
+#ifdef CONFIG_PM
+/**
+ * omap_pm_setup_sr_i2c_pcb_length - set length of SR I2C traces on PCB
+ * @mm: length of the PCB trace in millimetres
+ *
+ * Sets the PCB trace length for the I2C channel. By default uses 63mm.
+ * This is needed for properly calculating the capacitance value for
+ * the PCB trace, and for setting the SR I2C channel timing parameters.
+ */
+void __init omap_pm_setup_sr_i2c_pcb_length(u32 mm)
+{
+	sr_i2c_pcb_length = mm;
+}
+#endif
+
 void __init omap_vc_init_channel(struct voltagedomain *voltdm)
 {
 	struct omap_vc_channel *vc = voltdm->vc;
@@ -311,7 +708,6 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
 	vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr;
 	vc->volt_reg_addr = voltdm->pmic->volt_reg_addr;
 	vc->cmd_reg_addr = voltdm->pmic->cmd_reg_addr;
-	vc->setup_time = voltdm->pmic->volt_setup_time;
 
 	/* Configure the i2c slave address for this VC */
 	voltdm->rmw(vc->smps_sa_mask,
@@ -331,14 +727,18 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
 		voltdm->rmw(vc->smps_cmdra_mask,
 			    vc->cmd_reg_addr << __ffs(vc->smps_cmdra_mask),
 			    vc->smps_cmdra_reg);
-		vc->cfg_channel |= vc_cfg_bits->rac | vc_cfg_bits->racen;
+		vc->cfg_channel |= vc_cfg_bits->rac;
 	}
 
+	if (vc->cmd_reg_addr == vc->volt_reg_addr)
+		vc->cfg_channel |= vc_cfg_bits->racen;
+
 	/* Set up the on, inactive, retention and off voltage */
-	on_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->on_volt);
-	onlp_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->onlp_volt);
-	ret_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->ret_volt);
-	off_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->off_volt);
+	on_vsel = omap_vc_calc_vsel(voltdm, voltdm->vc_param->on);
+	onlp_vsel = omap_vc_calc_vsel(voltdm, voltdm->vc_param->onlp);
+	ret_vsel = omap_vc_calc_vsel(voltdm, voltdm->vc_param->ret);
+	off_vsel = omap_vc_calc_vsel(voltdm, voltdm->vc_param->off);
+
 	val = ((on_vsel << vc->common->cmd_on_shift) |
 	       (onlp_vsel << vc->common->cmd_onlp_shift) |
 	       (ret_vsel << vc->common->cmd_ret_shift) |
@@ -349,11 +749,6 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
 	/* Channel configuration */
 	omap_vc_config_channel(voltdm);
 
-	/* Configure the setup times */
-	voltdm->rmw(voltdm->vfsm->voltsetup_mask,
-		    vc->setup_time << __ffs(voltdm->vfsm->voltsetup_mask),
-		    voltdm->vfsm->voltsetup_reg);
-
 	omap_vc_i2c_init(voltdm);
 
 	if (cpu_is_omap34xx())
diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h
index 478bf6b..91c8d75 100644
--- a/arch/arm/mach-omap2/vc.h
+++ b/arch/arm/mach-omap2/vc.h
@@ -86,7 +86,6 @@ struct omap_vc_channel {
 	u16 i2c_slave_addr;
 	u16 volt_reg_addr;
 	u16 cmd_reg_addr;
-	u16 setup_time;
 	u8 cfg_channel;
 	bool i2c_high_speed;
 
@@ -111,6 +110,13 @@ extern struct omap_vc_channel omap4_vc_mpu;
 extern struct omap_vc_channel omap4_vc_iva;
 extern struct omap_vc_channel omap4_vc_core;
 
+extern struct omap_vc_param omap3_mpu_vc_data;
+extern struct omap_vc_param omap3_core_vc_data;
+
+extern struct omap_vc_param omap4_mpu_vc_data;
+extern struct omap_vc_param omap4_iva_vc_data;
+extern struct omap_vc_param omap4_core_vc_data;
+
 void omap_vc_init_channel(struct voltagedomain *voltdm);
 int omap_vc_pre_scale(struct voltagedomain *voltdm,
 		      unsigned long target_volt,
diff --git a/arch/arm/mach-omap2/vc3xxx_data.c b/arch/arm/mach-omap2/vc3xxx_data.c
index 5d8eaf3..75bc4aa 100644
--- a/arch/arm/mach-omap2/vc3xxx_data.c
+++ b/arch/arm/mach-omap2/vc3xxx_data.c
@@ -71,3 +71,25 @@ struct omap_vc_channel omap3_vc_core = {
 	.smps_cmdra_mask = OMAP3430_CMDRA1_MASK,
 	.cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
 };
+
+/*
+ * Voltage levels for different operating modes: on, sleep, retention and off
+ */
+#define OMAP3_ON_VOLTAGE_UV		1200000
+#define OMAP3_ONLP_VOLTAGE_UV		1000000
+#define OMAP3_RET_VOLTAGE_UV		975000
+#define OMAP3_OFF_VOLTAGE_UV		600000
+
+struct omap_vc_param omap3_mpu_vc_data = {
+	.on		= OMAP3_ON_VOLTAGE_UV,
+	.onlp		= OMAP3_ONLP_VOLTAGE_UV,
+	.ret		= OMAP3_RET_VOLTAGE_UV,
+	.off		= OMAP3_OFF_VOLTAGE_UV,
+};
+
+struct omap_vc_param omap3_core_vc_data = {
+	.on		= OMAP3_ON_VOLTAGE_UV,
+	.onlp		= OMAP3_ONLP_VOLTAGE_UV,
+	.ret		= OMAP3_RET_VOLTAGE_UV,
+	.off		= OMAP3_OFF_VOLTAGE_UV,
+};
diff --git a/arch/arm/mach-omap2/vc44xx_data.c b/arch/arm/mach-omap2/vc44xx_data.c
index d70b930..085e5d6 100644
--- a/arch/arm/mach-omap2/vc44xx_data.c
+++ b/arch/arm/mach-omap2/vc44xx_data.c
@@ -87,3 +87,31 @@ struct omap_vc_channel omap4_vc_core = {
 	.cfg_channel_sa_shift = OMAP4430_SA_VDD_CORE_L_SHIFT,
 };
 
+/*
+ * Voltage levels for different operating modes: on, sleep, retention and off
+ */
+#define OMAP4_ON_VOLTAGE_UV			1375000
+#define OMAP4_ONLP_VOLTAGE_UV			1375000
+#define OMAP4_RET_VOLTAGE_UV			837500
+#define OMAP4_OFF_VOLTAGE_UV			0
+
+struct omap_vc_param omap4_mpu_vc_data = {
+	.on			= OMAP4_ON_VOLTAGE_UV,
+	.onlp			= OMAP4_ONLP_VOLTAGE_UV,
+	.ret			= OMAP4_RET_VOLTAGE_UV,
+	.off			= OMAP4_OFF_VOLTAGE_UV,
+};
+
+struct omap_vc_param omap4_iva_vc_data = {
+	.on			= OMAP4_ON_VOLTAGE_UV,
+	.onlp			= OMAP4_ONLP_VOLTAGE_UV,
+	.ret			= OMAP4_RET_VOLTAGE_UV,
+	.off			= OMAP4_OFF_VOLTAGE_UV,
+};
+
+struct omap_vc_param omap4_core_vc_data = {
+	.on			= OMAP4_ON_VOLTAGE_UV,
+	.onlp			= OMAP4_ONLP_VOLTAGE_UV,
+	.ret			= OMAP4_RET_VOLTAGE_UV,
+	.off			= OMAP4_OFF_VOLTAGE_UV,
+};
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
index 7283b7e..a0ce4f1 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -40,12 +40,14 @@ struct powerdomain;
  * data
  * @voltsetup_mask: SETUP_TIME* bitmask in the PRM_VOLTSETUP* register
  * @voltsetup_reg: register offset of PRM_VOLTSETUP from PRM base
+ * @voltsetup_off_reg: register offset of PRM_VOLTSETUP_OFF from PRM base
  *
  * XXX What about VOLTOFFSET/VOLTCTRL?
  */
 struct omap_vfsm_instance {
 	u32 voltsetup_mask;
 	u8 voltsetup_reg;
+	u8 voltsetup_off_reg;
 };
 
 /**
@@ -74,6 +76,8 @@ struct voltagedomain {
 	const struct omap_vfsm_instance *vfsm;
 	struct omap_vp_instance *vp;
 	struct omap_voltdm_pmic *pmic;
+	struct omap_vp_param *vp_param;
+	struct omap_vc_param *vc_param;
 
 	/* VC/VP register access functions: SoC specific */
 	u32 (*read) (u8 offset);
@@ -92,6 +96,24 @@ struct voltagedomain {
 	struct omap_volt_data *volt_data;
 };
 
+/* Min and max voltages from OMAP perspective */
+#define OMAP3430_VP1_VLIMITTO_VDDMIN	850000
+#define OMAP3430_VP1_VLIMITTO_VDDMAX	1425000
+#define OMAP3430_VP2_VLIMITTO_VDDMIN	900000
+#define OMAP3430_VP2_VLIMITTO_VDDMAX	1150000
+
+#define OMAP3630_VP1_VLIMITTO_VDDMIN	900000
+#define OMAP3630_VP1_VLIMITTO_VDDMAX	1350000
+#define OMAP3630_VP2_VLIMITTO_VDDMIN	900000
+#define OMAP3630_VP2_VLIMITTO_VDDMAX	1200000
+
+#define OMAP4_VP_MPU_VLIMITTO_VDDMIN	830000
+#define OMAP4_VP_MPU_VLIMITTO_VDDMAX	1410000
+#define OMAP4_VP_IVA_VLIMITTO_VDDMIN	830000
+#define OMAP4_VP_IVA_VLIMITTO_VDDMAX	1260000
+#define OMAP4_VP_CORE_VLIMITTO_VDDMIN	830000
+#define OMAP4_VP_CORE_VLIMITTO_VDDMAX	1200000
+
 /**
  * struct omap_voltdm_pmic - PMIC specific data required by voltage driver.
  * @slew_rate:	PMIC slew rate (in uv/us)
@@ -107,26 +129,34 @@ struct voltagedomain {
 struct omap_voltdm_pmic {
 	int slew_rate;
 	int step_size;
-	u32 on_volt;
-	u32 onlp_volt;
-	u32 ret_volt;
-	u32 off_volt;
-	u16 volt_setup_time;
 	u16 i2c_slave_addr;
 	u16 volt_reg_addr;
 	u16 cmd_reg_addr;
 	u8 vp_erroroffset;
 	u8 vp_vstepmin;
 	u8 vp_vstepmax;
-	u8 vp_vddmin;
-	u8 vp_vddmax;
+	u32 vddmin;
+	u32 vddmax;
 	u8 vp_timeout_us;
 	bool i2c_high_speed;
+	u32 i2c_pad_load;
 	u8 i2c_mcode;
 	unsigned long (*vsel_to_uv) (const u8 vsel);
 	u8 (*uv_to_vsel) (unsigned long uV);
 };
 
+struct omap_vp_param {
+	u32 vddmax;
+	u32 vddmin;
+};
+
+struct omap_vc_param {
+	u32 on;
+	u32 onlp;
+	u32 ret;
+	u32 off;
+};
+
 void omap_voltage_get_volttable(struct voltagedomain *voltdm,
 		struct omap_volt_data **volt_data);
 struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
diff --git a/arch/arm/mach-omap2/voltagedomains3xxx_data.c b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
index 63afbfe..261bb7c 100644
--- a/arch/arm/mach-omap2/voltagedomains3xxx_data.c
+++ b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
@@ -117,6 +117,11 @@ void __init omap3xxx_voltagedomains_init(void)
 	}
 #endif
 
+	omap3_voltdm_mpu.vp_param = &omap3_mpu_vp_data;
+	omap3_voltdm_core.vp_param = &omap3_core_vp_data;
+	omap3_voltdm_mpu.vc_param = &omap3_mpu_vc_data;
+	omap3_voltdm_core.vc_param = &omap3_core_vc_data;
+
 	if (soc_is_am35xx())
 		voltdms = voltagedomains_am35xx;
 	else
diff --git a/arch/arm/mach-omap2/voltagedomains44xx_data.c b/arch/arm/mach-omap2/voltagedomains44xx_data.c
index c3115f6..48b22a0 100644
--- a/arch/arm/mach-omap2/voltagedomains44xx_data.c
+++ b/arch/arm/mach-omap2/voltagedomains44xx_data.c
@@ -22,7 +22,7 @@
 #include <linux/init.h>
 
 #include "common.h"
-
+#include "soc.h"
 #include "prm-regbits-44xx.h"
 #include "prm44xx.h"
 #include "prcm44xx.h"
@@ -34,14 +34,17 @@
 
 static const struct omap_vfsm_instance omap4_vdd_mpu_vfsm = {
 	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET,
+	.voltsetup_off_reg = OMAP4_PRM_VOLTSETUP_MPU_OFF_OFFSET,
 };
 
 static const struct omap_vfsm_instance omap4_vdd_iva_vfsm = {
 	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET,
+	.voltsetup_off_reg = OMAP4_PRM_VOLTSETUP_IVA_OFF_OFFSET,
 };
 
 static const struct omap_vfsm_instance omap4_vdd_core_vfsm = {
 	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET,
+	.voltsetup_off_reg = OMAP4_PRM_VOLTSETUP_CORE_OFF_OFFSET,
 };
 
 static struct voltagedomain omap4_voltdm_mpu = {
@@ -101,11 +104,25 @@ void __init omap44xx_voltagedomains_init(void)
 	 * for the currently-running IC
 	 */
 #ifdef CONFIG_PM_OPP
-	omap4_voltdm_mpu.volt_data = omap44xx_vdd_mpu_volt_data;
-	omap4_voltdm_iva.volt_data = omap44xx_vdd_iva_volt_data;
-	omap4_voltdm_core.volt_data = omap44xx_vdd_core_volt_data;
+	if (cpu_is_omap443x()) {
+		omap4_voltdm_mpu.volt_data = omap443x_vdd_mpu_volt_data;
+		omap4_voltdm_iva.volt_data = omap443x_vdd_iva_volt_data;
+		omap4_voltdm_core.volt_data = omap443x_vdd_core_volt_data;
+	} else if (cpu_is_omap446x()) {
+		omap4_voltdm_mpu.volt_data = omap446x_vdd_mpu_volt_data;
+		omap4_voltdm_iva.volt_data = omap446x_vdd_iva_volt_data;
+		omap4_voltdm_core.volt_data = omap446x_vdd_core_volt_data;
+	}
 #endif
 
+	omap4_voltdm_mpu.vp_param = &omap4_mpu_vp_data;
+	omap4_voltdm_iva.vp_param = &omap4_iva_vp_data;
+	omap4_voltdm_core.vp_param = &omap4_core_vp_data;
+
+	omap4_voltdm_mpu.vc_param = &omap4_mpu_vc_data;
+	omap4_voltdm_iva.vc_param = &omap4_iva_vc_data;
+	omap4_voltdm_core.vc_param = &omap4_core_vc_data;
+
 	for (i = 0; voltdm = voltagedomains_omap4[i], voltdm; i++)
 		voltdm->sys_clk.name = sys_clk_name;
 
diff --git a/arch/arm/mach-omap2/vp.c b/arch/arm/mach-omap2/vp.c
index 85241b8..a3c3065 100644
--- a/arch/arm/mach-omap2/vp.c
+++ b/arch/arm/mach-omap2/vp.c
@@ -58,8 +58,10 @@ void __init omap_vp_init(struct voltagedomain *voltdm)
 	sys_clk_rate = voltdm->sys_clk.rate / 1000;
 
 	timeout = (sys_clk_rate * voltdm->pmic->vp_timeout_us) / 1000;
-	vddmin = voltdm->pmic->vp_vddmin;
-	vddmax = voltdm->pmic->vp_vddmax;
+	vddmin = max(voltdm->vp_param->vddmin, voltdm->pmic->vddmin);
+	vddmax = min(voltdm->vp_param->vddmax, voltdm->pmic->vddmax);
+	vddmin = voltdm->pmic->uv_to_vsel(vddmin);
+	vddmax = voltdm->pmic->uv_to_vsel(vddmax);
 
 	waittime = DIV_ROUND_UP(voltdm->pmic->step_size * sys_clk_rate,
 				1000 * voltdm->pmic->slew_rate);
@@ -138,7 +140,7 @@ int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
 		udelay(1);
 	}
 	if (timeout >= VP_TRANXDONE_TIMEOUT) {
-		pr_warn("%s: vdd_%s TRANXDONE timeout exceeded. Voltage change aborted",
+		pr_warn("%s: vdd_%s TRANXDONE timeout exceeded. Voltage change aborted\n",
 			__func__, voltdm->name);
 		return -ETIMEDOUT;
 	}
@@ -197,7 +199,7 @@ void omap_vp_enable(struct voltagedomain *voltdm)
 	u32 vpconfig, volt;
 
 	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
+		pr_warn("%s: VDD specified does not exist!\n", __func__);
 		return;
 	}
 
@@ -214,8 +216,8 @@ void omap_vp_enable(struct voltagedomain *voltdm)
 
 	volt = voltdm_get_voltage(voltdm);
 	if (!volt) {
-		pr_warning("%s: unable to find current voltage for %s\n",
-			   __func__, voltdm->name);
+		pr_warn("%s: unable to find current voltage for %s\n",
+			__func__, voltdm->name);
 		return;
 	}
 
@@ -242,7 +244,7 @@ void omap_vp_disable(struct voltagedomain *voltdm)
 	int timeout;
 
 	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
+		pr_warn("%s: VDD specified does not exist!\n", __func__);
 		return;
 	}
 
@@ -272,8 +274,7 @@ void omap_vp_disable(struct voltagedomain *voltdm)
 			  VP_IDLE_TIMEOUT, timeout);
 
 	if (timeout >= VP_IDLE_TIMEOUT)
-		pr_warning("%s: vdd_%s idle timedout\n",
-			__func__, voltdm->name);
+		pr_warn("%s: vdd_%s idle timedout\n", __func__, voltdm->name);
 
 	vp->enabled = false;
 
diff --git a/arch/arm/mach-omap2/vp.h b/arch/arm/mach-omap2/vp.h
index 7c155d2..0fdf7080 100644
--- a/arch/arm/mach-omap2/vp.h
+++ b/arch/arm/mach-omap2/vp.h
@@ -117,6 +117,13 @@ extern struct omap_vp_instance omap4_vp_mpu;
 extern struct omap_vp_instance omap4_vp_iva;
 extern struct omap_vp_instance omap4_vp_core;
 
+extern struct omap_vp_param omap3_mpu_vp_data;
+extern struct omap_vp_param omap3_core_vp_data;
+
+extern struct omap_vp_param omap4_mpu_vp_data;
+extern struct omap_vp_param omap4_iva_vp_data;
+extern struct omap_vp_param omap4_core_vp_data;
+
 void omap_vp_init(struct voltagedomain *voltdm);
 void omap_vp_enable(struct voltagedomain *voltdm);
 void omap_vp_disable(struct voltagedomain *voltdm);
diff --git a/arch/arm/mach-omap2/vp3xxx_data.c b/arch/arm/mach-omap2/vp3xxx_data.c
index bd89f80..1914e02 100644
--- a/arch/arm/mach-omap2/vp3xxx_data.c
+++ b/arch/arm/mach-omap2/vp3xxx_data.c
@@ -77,3 +77,13 @@ struct omap_vp_instance omap3_vp_core = {
 	.vstatus = OMAP3_PRM_VP2_STATUS_OFFSET,
 	.voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET,
 };
+
+struct omap_vp_param omap3_mpu_vp_data = {
+	.vddmin			= OMAP3430_VP1_VLIMITTO_VDDMIN,
+	.vddmax			= OMAP3430_VP1_VLIMITTO_VDDMAX,
+};
+
+struct omap_vp_param omap3_core_vp_data = {
+	.vddmin			= OMAP3430_VP2_VLIMITTO_VDDMIN,
+	.vddmax			= OMAP3430_VP2_VLIMITTO_VDDMAX,
+};
diff --git a/arch/arm/mach-omap2/vp44xx_data.c b/arch/arm/mach-omap2/vp44xx_data.c
index 8c031d1..e62f6b0 100644
--- a/arch/arm/mach-omap2/vp44xx_data.c
+++ b/arch/arm/mach-omap2/vp44xx_data.c
@@ -87,3 +87,18 @@ struct omap_vp_instance omap4_vp_core = {
 	.vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET,
 	.voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET,
 };
+
+struct omap_vp_param omap4_mpu_vp_data = {
+	.vddmin			= OMAP4_VP_MPU_VLIMITTO_VDDMIN,
+	.vddmax			= OMAP4_VP_MPU_VLIMITTO_VDDMAX,
+};
+
+struct omap_vp_param omap4_iva_vp_data = {
+	.vddmin			= OMAP4_VP_IVA_VLIMITTO_VDDMIN,
+	.vddmax			= OMAP4_VP_IVA_VLIMITTO_VDDMAX,
+};
+
+struct omap_vp_param omap4_core_vp_data = {
+	.vddmin			= OMAP4_VP_CORE_VLIMITTO_VDDMIN,
+	.vddmax			= OMAP4_VP_CORE_VLIMITTO_VDDMAX,
+};
diff --git a/arch/arm/mach-omap2/wd_timer.c b/arch/arm/mach-omap2/wd_timer.c
index b2f1c67..7c2b4ed 100644
--- a/arch/arm/mach-omap2/wd_timer.c
+++ b/arch/arm/mach-omap2/wd_timer.c
@@ -1,6 +1,8 @@
 /*
  * OMAP2+ MPU WD_TIMER-specific code
  *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -11,10 +13,14 @@
 #include <linux/io.h>
 #include <linux/err.h>
 
-#include <plat/omap_hwmod.h>
+#include <linux/platform_data/omap-wd-timer.h>
 
+#include "omap_hwmod.h"
+#include "omap_device.h"
 #include "wd_timer.h"
 #include "common.h"
+#include "prm.h"
+#include "soc.h"
 
 /*
  * In order to avoid any assumptions from bootloader regarding WDT
@@ -26,9 +32,6 @@
 #define OMAP_WDT_WPS		0x34
 #define OMAP_WDT_SPR		0x48
 
-/* Maximum microseconds to wait for OMAP module to softreset */
-#define MAX_MODULE_SOFTRESET_WAIT	10000
-
 int omap2_wd_timer_disable(struct omap_hwmod *oh)
 {
 	void __iomem *base;
@@ -99,3 +102,32 @@ int omap2_wd_timer_reset(struct omap_hwmod *oh)
 	return (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT :
 		omap2_wd_timer_disable(oh);
 }
+
+static int __init omap_init_wdt(void)
+{
+	int id = -1;
+	struct platform_device *pdev;
+	struct omap_hwmod *oh;
+	char *oh_name = "wd_timer2";
+	char *dev_name = "omap_wdt";
+	struct omap_wd_timer_platform_data pdata;
+
+	if (!cpu_class_is_omap2() || of_have_populated_dt())
+		return 0;
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up wd_timer%d hwmod\n", id);
+		return -EINVAL;
+	}
+
+	pdata.read_reset_sources = prm_read_reset_sources;
+
+	pdev = omap_device_build(dev_name, id, oh, &pdata,
+				 sizeof(struct omap_wd_timer_platform_data),
+				 NULL, 0, 0);
+	WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n",
+	     dev_name, oh->name);
+	return 0;
+}
+subsys_initcall(omap_init_wdt);
diff --git a/arch/arm/mach-omap2/wd_timer.h b/arch/arm/mach-omap2/wd_timer.h
index f6bbba7..a78f810 100644
--- a/arch/arm/mach-omap2/wd_timer.h
+++ b/arch/arm/mach-omap2/wd_timer.h
@@ -10,7 +10,7 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_WD_TIMER_H
 #define __ARCH_ARM_MACH_OMAP2_WD_TIMER_H
 
-#include <plat/omap_hwmod.h>
+#include "omap_hwmod.h"
 
 extern int omap2_wd_timer_disable(struct omap_hwmod *oh);
 extern int omap2_wd_timer_reset(struct omap_hwmod *oh);
diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig
index 0673f0c..2cb2f06 100644
--- a/arch/arm/mach-orion5x/Kconfig
+++ b/arch/arm/mach-orion5x/Kconfig
@@ -2,6 +2,13 @@ if ARCH_ORION5X
 
 menu "Orion Implementations"
 
+config ARCH_ORION5X_DT
+	bool "Marvell Orion5x Flattened Device Tree"
+	select USE_OF
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Marvell Orion5x using flattened device tree.
+
 config MACH_DB88F5281
 	bool "Marvell Orion-2 Development Board"
 	select I2C_BOARDINFO
@@ -96,12 +103,13 @@ config MACH_MV2120
 	  Say 'Y' here if you want your kernel to support the
 	  HP Media Vault mv2120 or mv5100.
 
-config MACH_EDMINI_V2
-	bool "LaCie Ethernet Disk mini V2"
+config MACH_EDMINI_V2_DT
+	bool "LaCie Ethernet Disk mini V2 (Flattened Device Tree)"
 	select I2C_BOARDINFO
+	select ARCH_ORION5X_DT
 	help
 	  Say 'Y' here if you want your kernel to support the
-	  LaCie Ethernet Disk mini V2.
+	  LaCie Ethernet Disk mini V2 (Flattened Device Tree).
 
 config MACH_D2NET
 	bool "LaCie d2 Network"
diff --git a/arch/arm/mach-orion5x/Makefile b/arch/arm/mach-orion5x/Makefile
index 7f18cda..9e809a7 100644
--- a/arch/arm/mach-orion5x/Makefile
+++ b/arch/arm/mach-orion5x/Makefile
@@ -12,7 +12,6 @@ obj-$(CONFIG_MACH_TS409)	+= ts409-setup.o tsx09-common.o
 obj-$(CONFIG_MACH_WRT350N_V2)	+= wrt350n-v2-setup.o
 obj-$(CONFIG_MACH_TS78XX)	+= ts78xx-setup.o
 obj-$(CONFIG_MACH_MV2120)	+= mv2120-setup.o
-obj-$(CONFIG_MACH_EDMINI_V2)	+= edmini_v2-setup.o
 obj-$(CONFIG_MACH_D2NET)	+= d2net-setup.o
 obj-$(CONFIG_MACH_BIGDISK)	+= d2net-setup.o
 obj-$(CONFIG_MACH_NET2BIG)	+= net2big-setup.o
@@ -22,3 +21,6 @@ obj-$(CONFIG_MACH_RD88F5181L_GE)	+= rd88f5181l-ge-setup.o
 obj-$(CONFIG_MACH_RD88F5181L_FXO)	+= rd88f5181l-fxo-setup.o
 obj-$(CONFIG_MACH_RD88F6183AP_GE)	+= rd88f6183ap-ge-setup.o
 obj-$(CONFIG_MACH_LINKSTATION_LSCHL)	+= ls-chl-setup.o
+
+obj-$(CONFIG_ARCH_ORION5X_DT)		+= board-dt.o
+obj-$(CONFIG_MACH_EDMINI_V2_DT)	+= edmini_v2-setup.o
diff --git a/arch/arm/mach-orion5x/board-dt.c b/arch/arm/mach-orion5x/board-dt.c
new file mode 100644
index 0000000..32e5c21
--- /dev/null
+++ b/arch/arm/mach-orion5x/board-dt.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2012 (C), Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * arch/arm/mach-orion5x/board-dt.c
+ *
+ * Flattened Device Tree board initialization
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <asm/system_misc.h>
+#include <asm/mach/arch.h>
+#include <mach/orion5x.h>
+#include <plat/irq.h>
+#include "common.h"
+
+struct of_dev_auxdata orion5x_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("marvell,orion-spi", 0xf1010600, "orion_spi.0", NULL),
+	OF_DEV_AUXDATA("marvell,mv64xxx-i2c", 0xf1011000, "mv64xxx_i2c.0",
+		       NULL),
+	OF_DEV_AUXDATA("marvell,orion-wdt", 0xf1020300, "orion_wdt", NULL),
+	OF_DEV_AUXDATA("marvell,orion-sata", 0xf1080000, "sata_mv.0", NULL),
+	OF_DEV_AUXDATA("marvell,orion-crypto", 0xf1090000, "mv_crypto", NULL),
+	{},
+};
+
+static void __init orion5x_dt_init(void)
+{
+	char *dev_name;
+	u32 dev, rev;
+
+	orion5x_id(&dev, &rev, &dev_name);
+	printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, orion5x_tclk);
+
+	/*
+	 * Setup Orion address map
+	 */
+	orion5x_setup_cpu_mbus_bridge();
+
+	/* Setup root of clk tree */
+	clk_init();
+
+	/*
+	 * Don't issue "Wait for Interrupt" instruction if we are
+	 * running on D0 5281 silicon.
+	 */
+	if (dev == MV88F5281_DEV_ID && rev == MV88F5281_REV_D0) {
+		printk(KERN_INFO "Orion: Applying 5281 D0 WFI workaround.\n");
+		disable_hlt();
+	}
+
+	if (of_machine_is_compatible("lacie,ethernet-disk-mini-v2"))
+		edmini_v2_init();
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     orion5x_auxdata_lookup, NULL);
+}
+
+static const char *orion5x_dt_compat[] = {
+	"marvell,orion5x",
+	NULL,
+};
+
+DT_MACHINE_START(ORION5X_DT, "Marvell Orion5x (Flattened Device Tree)")
+	/* Maintainer: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> */
+	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
+	.init_irq	= orion_dt_init_irq,
+	.timer		= &orion5x_timer,
+	.init_machine	= orion5x_dt_init,
+	.restart	= orion5x_restart,
+	.dt_compat	= orion5x_dt_compat,
+MACHINE_END
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index b3eb3da..550f923 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -65,7 +65,7 @@ void __init orion5x_map_io(void)
  ****************************************************************************/
 static struct clk *tclk;
 
-static void __init clk_init(void)
+void __init clk_init(void)
 {
 	tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT,
 				       orion5x_tclk);
@@ -236,7 +236,7 @@ struct sys_timer orion5x_timer = {
 /*
  * Identify device ID and rev from PCIe configuration header space '0'.
  */
-static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name)
+void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name)
 {
 	orion5x_pcie_id(dev, rev);
 
diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h
index 31bab92..7db5cdd 100644
--- a/arch/arm/mach-orion5x/common.h
+++ b/arch/arm/mach-orion5x/common.h
@@ -12,6 +12,8 @@ void orion5x_map_io(void);
 void orion5x_init_early(void);
 void orion5x_init_irq(void);
 void orion5x_init(void);
+void orion5x_id(u32 *dev, u32 *rev, char **dev_name);
+void clk_init(void);
 extern int orion5x_tclk;
 extern struct sys_timer orion5x_timer;
 
@@ -54,6 +56,13 @@ int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys);
 struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
 int orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
 
+/* board init functions for boards not fully converted to fdt */
+#ifdef CONFIG_MACH_EDMINI_V2_DT
+void edmini_v2_init(void);
+#else
+static inline void edmini_v2_init(void) {};
+#endif
+
 struct meminfo;
 struct tag;
 extern void __init tag_fixup_mem32(struct tag *, char **, struct meminfo *);
diff --git a/arch/arm/mach-orion5x/edmini_v2-setup.c b/arch/arm/mach-orion5x/edmini_v2-setup.c
index 355e962..d675e72 100644
--- a/arch/arm/mach-orion5x/edmini_v2-setup.c
+++ b/arch/arm/mach-orion5x/edmini_v2-setup.c
@@ -115,69 +115,6 @@ static struct i2c_board_info __initdata edmini_v2_i2c_rtc = {
 };
 
 /*****************************************************************************
- * Sata
- ****************************************************************************/
-
-static struct mv_sata_platform_data edmini_v2_sata_data = {
-	.n_ports	= 2,
-};
-
-/*****************************************************************************
- * GPIO LED (simple - doesn't use hardware blinking support)
- ****************************************************************************/
-
-#define EDMINI_V2_GPIO_LED_POWER	16
-
-static struct gpio_led edmini_v2_leds[] = {
-	{
-		.name = "power:blue",
-		.gpio = EDMINI_V2_GPIO_LED_POWER,
-		.active_low = 1,
-	},
-};
-
-static struct gpio_led_platform_data edmini_v2_led_data = {
-	.num_leds = ARRAY_SIZE(edmini_v2_leds),
-	.leds = edmini_v2_leds,
-};
-
-static struct platform_device edmini_v2_gpio_leds = {
-	.name           = "leds-gpio",
-	.id             = -1,
-	.dev            = {
-		.platform_data  = &edmini_v2_led_data,
-	},
-};
-
-/****************************************************************************
- * GPIO key
- ****************************************************************************/
-
-#define EDMINI_V2_GPIO_KEY_POWER	18
-
-static struct gpio_keys_button edmini_v2_buttons[] = {
-	{
-		.code		= KEY_POWER,
-		.gpio		= EDMINI_V2_GPIO_KEY_POWER,
-		.desc		= "Power Button",
-		.active_low	= 0,
-	},
-};
-
-static struct gpio_keys_platform_data edmini_v2_button_data = {
-	.buttons	= edmini_v2_buttons,
-	.nbuttons	= ARRAY_SIZE(edmini_v2_buttons),
-};
-
-static struct platform_device edmini_v2_gpio_buttons = {
-	.name		= "gpio-keys",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &edmini_v2_button_data,
-	},
-};
-
-/*****************************************************************************
  * General Setup
  ****************************************************************************/
 static unsigned int edminiv2_mpp_modes[] __initdata = {
@@ -207,13 +144,8 @@ static unsigned int edminiv2_mpp_modes[] __initdata = {
 	0,
 };
 
-static void __init edmini_v2_init(void)
+void __init edmini_v2_init(void)
 {
-	/*
-	 * Setup basic Orion functions. Need to be called early.
-	 */
-	orion5x_init();
-
 	orion5x_mpp_conf(edminiv2_mpp_modes);
 
 	/*
@@ -221,15 +153,10 @@ static void __init edmini_v2_init(void)
 	 */
 	orion5x_ehci0_init();
 	orion5x_eth_init(&edmini_v2_eth_data);
-	orion5x_i2c_init();
-	orion5x_sata_init(&edmini_v2_sata_data);
-	orion5x_uart0_init();
 
 	orion5x_setup_dev_boot_win(EDMINI_V2_NOR_BOOT_BASE,
 				EDMINI_V2_NOR_BOOT_SIZE);
 	platform_device_register(&edmini_v2_nor_flash);
-	platform_device_register(&edmini_v2_gpio_leds);
-	platform_device_register(&edmini_v2_gpio_buttons);
 
 	pr_notice("edmini_v2: USB device port, flash write and power-off "
 		  "are not yet supported.\n");
@@ -247,16 +174,3 @@ static void __init edmini_v2_init(void)
 
 	i2c_register_board_info(0, &edmini_v2_i2c_rtc, 1);
 }
-
-/* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */
-MACHINE_START(EDMINI_V2, "LaCie Ethernet Disk mini V2")
-	/* Maintainer: Christopher Moore <moore@free.fr> */
-	.atag_offset	= 0x100,
-	.init_machine	= edmini_v2_init,
-	.map_io		= orion5x_map_io,
-	.init_early	= orion5x_init_early,
-	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
-	.fixup		= tag_fixup_mem32,
-	.restart	= orion5x_restart,
-MACHINE_END
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 11aa739..86eec41 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -2,27 +2,6 @@ if ARCH_PXA
 
 menu "Intel PXA2xx/PXA3xx Implementations"
 
-config ARCH_PXA_V7
-	bool "ARMv7 (PXA95x) based systems"
-
-if ARCH_PXA_V7
-comment "Marvell Dev Platforms (sorted by hardware release time)"
-config MACH_TAVOREVB3
-	bool "PXA95x Development Platform (aka TavorEVB III)"
-	select CPU_PXA955
-
-config MACH_SAARB
-	bool "PXA955 Handheld Platform (aka SAARB)"
-	select CPU_PXA955
-endif
-
-config PXA_V7_MACH_AUTO
-	def_bool y
-	depends on ARCH_PXA_V7
-	depends on !MACH_SAARB
-	select MACH_TAVOREVB3
-
-if !ARCH_PXA_V7
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
 config MACH_PXA3XX_DT
@@ -630,7 +609,6 @@ config MACH_ZIPIT2
 	bool "Zipit Z2 Handheld"
 	select HAVE_PWM
 	select PXA27x
-endif
 endmenu
 
 config PXA25x
@@ -688,18 +666,6 @@ config CPU_PXA935
 	help
 	  PXA935 (codename Tavor-P65)
 
-config PXA95x
-	bool
-	select CPU_PJ4
-	help
-	  Select code specific to PXA95x variants
-
-config CPU_PXA955
-	bool
-	select PXA95x
-	help
-	  PXA950 (codename MG1)
-
 config PXA_SHARP_C7xx
 	bool
 	select SHARPSL_PM
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index ee88d6e..12c5005 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -19,7 +19,6 @@ endif
 obj-$(CONFIG_PXA25x)		+= mfp-pxa2xx.o clock-pxa2xx.o pxa2xx.o pxa25x.o
 obj-$(CONFIG_PXA27x)		+= mfp-pxa2xx.o clock-pxa2xx.o pxa2xx.o pxa27x.o
 obj-$(CONFIG_PXA3xx)		+= mfp-pxa3xx.o clock-pxa3xx.o pxa3xx.o smemc.o pxa3xx-ulpi.o
-obj-$(CONFIG_PXA95x)		+= mfp-pxa3xx.o clock-pxa3xx.o pxa3xx.o pxa95x.o smemc.o
 obj-$(CONFIG_CPU_PXA300)	+= pxa300.o
 obj-$(CONFIG_CPU_PXA320)	+= pxa320.o
 obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
@@ -36,9 +35,7 @@ obj-$(CONFIG_MACH_ZYLONITE300)	+= zylonite.o zylonite_pxa300.o
 obj-$(CONFIG_MACH_ZYLONITE320)	+= zylonite.o zylonite_pxa320.o
 obj-$(CONFIG_MACH_LITTLETON)	+= littleton.o
 obj-$(CONFIG_MACH_TAVOREVB)	+= tavorevb.o
-obj-$(CONFIG_MACH_TAVOREVB3)	+= tavorevb3.o
 obj-$(CONFIG_MACH_SAAR)		+= saar.o
-obj-$(CONFIG_MACH_SAARB)	+= saarb.o
 
 # 3rd Party Dev Platforms
 obj-$(CONFIG_ARCH_PXA_IDP)	+= idp.o
diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h
index 3a258b1..1f65d32 100644
--- a/arch/arm/mach-pxa/clock.h
+++ b/arch/arm/mach-pxa/clock.h
@@ -57,7 +57,7 @@ void clk_pxa2xx_cken_disable(struct clk *clk);
 
 extern struct syscore_ops pxa2xx_clock_syscore_ops;
 
-#if defined(CONFIG_PXA3xx) || defined(CONFIG_PXA95x)
+#if defined(CONFIG_PXA3xx)
 #define DEFINE_PXA3_CKEN(_name, _cken, _rate, _delay)	\
 struct clk clk_##_name = {				\
 		.ops	= &clk_pxa3xx_cken_ops,		\
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index ddaa04d..daa86d3 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -703,7 +703,7 @@ void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
 }
 #endif /* CONFIG_PXA27x || CONFIG_PXA3xx */
 
-#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) || defined(CONFIG_PXA95x)
+#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
 static struct resource pxa27x_resource_keypad[] = {
 	[0] = {
 		.start	= 0x41500000,
@@ -872,7 +872,7 @@ struct platform_device pxa27x_device_pwm1 = {
 	.resource	= pxa27x_resource_pwm1,
 	.num_resources	= ARRAY_SIZE(pxa27x_resource_pwm1),
 };
-#endif /* CONFIG_PXA27x || CONFIG_PXA3xx || CONFIG_PXA95x*/
+#endif /* CONFIG_PXA27x || CONFIG_PXA3xx */
 
 #ifdef CONFIG_PXA3xx
 static struct resource pxa3xx_resources_mci2[] = {
@@ -981,7 +981,7 @@ struct platform_device pxa3xx_device_gcu = {
 
 #endif /* CONFIG_PXA3xx */
 
-#if defined(CONFIG_PXA3xx) || defined(CONFIG_PXA95x)
+#if defined(CONFIG_PXA3xx)
 static struct resource pxa3xx_resources_i2c_power[] = {
 	{
 		.start  = 0x40f500c0,
@@ -1082,7 +1082,7 @@ struct platform_device pxa3xx_device_ssp4 = {
 	.resource	= pxa3xx_resource_ssp4,
 	.num_resources	= ARRAY_SIZE(pxa3xx_resource_ssp4),
 };
-#endif /* CONFIG_PXA3xx || CONFIG_PXA95x */
+#endif /* CONFIG_PXA3xx */
 
 struct resource pxa_resource_gpio[] = {
 	{
diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h
index 56d92e5..ccb06e4 100644
--- a/arch/arm/mach-pxa/include/mach/hardware.h
+++ b/arch/arm/mach-pxa/include/mach/hardware.h
@@ -194,17 +194,6 @@
 #define __cpu_is_pxa935(id)	(0)
 #endif
 
-#ifdef CONFIG_CPU_PXA955
-#define __cpu_is_pxa955(id)				\
-	({						\
-		unsigned int _id = (id) >> 4 & 0xfff;	\
-		_id == 0x581 || _id == 0xc08		\
-			|| _id == 0xb76;		\
-	})
-#else
-#define __cpu_is_pxa955(id)	(0)
-#endif
-
 #define cpu_is_pxa210()					\
 	({						\
 		__cpu_is_pxa210(read_cpuid_id());	\
@@ -255,10 +244,6 @@
 		__cpu_is_pxa935(read_cpuid_id());	\
 	 })
 
-#define cpu_is_pxa955()					\
-	({						\
-		__cpu_is_pxa955(read_cpuid_id());	\
-	})
 
 
 /*
@@ -297,15 +282,6 @@
 #define __cpu_is_pxa93x(id)	(0)
 #endif
 
-#ifdef CONFIG_PXA95x
-#define __cpu_is_pxa95x(id)				\
-	({						\
-		__cpu_is_pxa955(id);			\
-	})
-#else
-#define __cpu_is_pxa95x(id)	(0)
-#endif
-
 #define cpu_is_pxa2xx()					\
 	({						\
 		__cpu_is_pxa2xx(read_cpuid_id());	\
@@ -321,10 +297,6 @@
 		__cpu_is_pxa93x(read_cpuid_id());	\
 	 })
 
-#define cpu_is_pxa95x()					\
-	({						\
-		__cpu_is_pxa95x(read_cpuid_id());	\
-	})
 
 /*
  * return current memory and LCD clock frequency in units of 10kHz
diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index 8765782..48c2fd8 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -84,7 +84,6 @@
 #define IRQ_PXA935_MMC0	PXA_IRQ(72)	/* MMC0 Controller (PXA935) */
 #define IRQ_PXA935_MMC1	PXA_IRQ(73)	/* MMC1 Controller (PXA935) */
 #define IRQ_PXA935_MMC2	PXA_IRQ(74)	/* MMC2 Controller (PXA935) */
-#define IRQ_PXA955_MMC3	PXA_IRQ(75)	/* MMC3 Controller (PXA955) */
 #define IRQ_U2P		PXA_IRQ(93)	/* USB PHY D+/D- Lines (PXA935) */
 
 #define PXA_GPIO_IRQ_BASE	PXA_IRQ(96)
diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx.h b/arch/arm/mach-pxa/include/mach/pxa3xx.h
index cd3e57f..6dd7fa1 100644
--- a/arch/arm/mach-pxa/include/mach/pxa3xx.h
+++ b/arch/arm/mach-pxa/include/mach/pxa3xx.h
@@ -7,7 +7,6 @@
 
 extern void __init pxa3xx_map_io(void);
 extern void __init pxa3xx_init_irq(void);
-extern void __init pxa95x_init_irq(void);
 
 #define pxa3xx_handle_irq	ichp_handle_irq
 
diff --git a/arch/arm/mach-pxa/include/mach/pxa95x.h b/arch/arm/mach-pxa/include/mach/pxa95x.h
deleted file mode 100644
index cbb097c..0000000
--- a/arch/arm/mach-pxa/include/mach/pxa95x.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __MACH_PXA95X_H
-#define __MACH_PXA95X_H
-
-#include <mach/pxa3xx.h>
-#include <mach/mfp-pxa930.h>
-
-#endif /* __MACH_PXA95X_H */
diff --git a/arch/arm/mach-pxa/include/mach/udc.h b/arch/arm/mach-pxa/include/mach/udc.h
index 2f82332..9a827e3 100644
--- a/arch/arm/mach-pxa/include/mach/udc.h
+++ b/arch/arm/mach-pxa/include/mach/udc.h
@@ -2,7 +2,7 @@
  * arch/arm/mach-pxa/include/mach/udc.h
  *
  */
-#include <asm/mach/udc_pxa2xx.h>
+#include <linux/platform_data/pxa2xx_udc.h>
 
 extern void pxa_set_udc_info(struct pxa2xx_udc_mach_info *info);
 
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 113c57a..fb7f1d1 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -26,6 +26,7 @@
 #include <linux/i2c/pxa-i2c.h>
 #include <linux/pwm_backlight.h>
 
+#include <media/mt9v022.h>
 #include <media/soc_camera.h>
 
 #include <linux/platform_data/camera-pxa.h>
@@ -468,6 +469,10 @@ static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
 	},
 };
 
+static struct mt9v022_platform_data mt9v022_pdata = {
+	.y_skip_top = 1,
+};
+
 static struct i2c_board_info pcm990_camera_i2c[] = {
 	{
 		I2C_BOARD_INFO("mt9v022", 0x48),
@@ -480,6 +485,7 @@ static struct soc_camera_link iclink[] = {
 	{
 		.bus_id			= 0, /* Must match with the camera ID */
 		.board_info		= &pcm990_camera_i2c[0],
+		.priv			= &mt9v022_pdata,
 		.i2c_adapter_id		= 0,
 		.query_bus_param	= pcm990_camera_query_bus_param,
 		.set_bus_param		= pcm990_camera_set_bus_param,
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 3352b37..3f5171e 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -209,6 +209,7 @@ static struct clk_lookup pxa25x_clkregs[] = {
 	INIT_CLKREG(&clk_pxa25x_gpio12, NULL, "GPIO12_CLK"),
 	INIT_CLKREG(&clk_pxa25x_mem, "pxa2xx-pcmcia", NULL),
 	INIT_CLKREG(&clk_dummy, "pxa-gpio", NULL),
+	INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
 };
 
 static struct clk_lookup pxa25x_hwuart_clkreg =
@@ -338,6 +339,10 @@ void __init pxa25x_map_io(void)
 	pxa25x_get_clk_frequency_khz(1);
 }
 
+static struct pxa_gpio_platform_data pxa25x_gpio_info __initdata = {
+	.gpio_set_wake = gpio_set_wake,
+};
+
 static struct platform_device *pxa25x_devices[] __initdata = {
 	&pxa25x_device_udc,
 	&pxa_device_pmu,
@@ -370,6 +375,7 @@ static int __init pxa25x_init(void)
 		register_syscore_ops(&pxa2xx_mfp_syscore_ops);
 		register_syscore_ops(&pxa2xx_clock_syscore_ops);
 
+		pxa_register_device(&pxa_device_gpio, &pxa25x_gpio_info);
 		ret = platform_add_devices(pxa25x_devices,
 					   ARRAY_SIZE(pxa25x_devices));
 		if (ret)
diff --git a/arch/arm/mach-pxa/pxa3xx-ulpi.c b/arch/arm/mach-pxa/pxa3xx-ulpi.c
index 7dbe3cc..e329cce 100644
--- a/arch/arm/mach-pxa/pxa3xx-ulpi.c
+++ b/arch/arm/mach-pxa/pxa3xx-ulpi.c
@@ -384,18 +384,7 @@ static struct platform_driver pxa3xx_u2d_ulpi_driver = {
         .probe          = pxa3xx_u2d_probe,
         .remove         = pxa3xx_u2d_remove,
 };
-
-static int pxa3xx_u2d_ulpi_init(void)
-{
-	return platform_driver_register(&pxa3xx_u2d_ulpi_driver);
-}
-module_init(pxa3xx_u2d_ulpi_init);
-
-static void __exit pxa3xx_u2d_ulpi_exit(void)
-{
-	platform_driver_unregister(&pxa3xx_u2d_ulpi_driver);
-}
-module_exit(pxa3xx_u2d_ulpi_exit);
+module_platform_driver(pxa3xx_u2d_ulpi_driver);
 
 MODULE_DESCRIPTION("PXA3xx U2D ULPI driver");
 MODULE_AUTHOR("Igor Grinberg");
diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c
deleted file mode 100644
index 47601f8..0000000
--- a/arch/arm/mach-pxa/pxa95x.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * linux/arch/arm/mach-pxa/pxa95x.c
- *
- * code specific to PXA95x aka MGx
- *
- * Copyright (C) 2009-2010 Marvell International Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pm.h>
-#include <linux/platform_device.h>
-#include <linux/i2c/pxa-i2c.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <mach/hardware.h>
-#include <mach/pxa3xx-regs.h>
-#include <mach/pxa930.h>
-#include <mach/reset.h>
-#include <mach/pm.h>
-#include <mach/dma.h>
-
-#include "generic.h"
-#include "devices.h"
-#include "clock.h"
-
-static struct mfp_addr_map pxa95x_mfp_addr_map[] __initdata = {
-
-	MFP_ADDR(GPIO0, 0x02e0),
-	MFP_ADDR(GPIO1, 0x02dc),
-	MFP_ADDR(GPIO2, 0x02e8),
-	MFP_ADDR(GPIO3, 0x02d8),
-	MFP_ADDR(GPIO4, 0x02e4),
-	MFP_ADDR(GPIO5, 0x02ec),
-	MFP_ADDR(GPIO6, 0x02f8),
-	MFP_ADDR(GPIO7, 0x02fc),
-	MFP_ADDR(GPIO8, 0x0300),
-	MFP_ADDR(GPIO9, 0x02d4),
-	MFP_ADDR(GPIO10, 0x02f4),
-	MFP_ADDR(GPIO11, 0x02f0),
-	MFP_ADDR(GPIO12, 0x0304),
-	MFP_ADDR(GPIO13, 0x0310),
-	MFP_ADDR(GPIO14, 0x0308),
-	MFP_ADDR(GPIO15, 0x030c),
-	MFP_ADDR(GPIO16, 0x04e8),
-	MFP_ADDR(GPIO17, 0x04f4),
-	MFP_ADDR(GPIO18, 0x04f8),
-	MFP_ADDR(GPIO19, 0x04fc),
-	MFP_ADDR(GPIO20, 0x0518),
-	MFP_ADDR(GPIO21, 0x051c),
-	MFP_ADDR(GPIO22, 0x04ec),
-	MFP_ADDR(GPIO23, 0x0500),
-	MFP_ADDR(GPIO24, 0x04f0),
-	MFP_ADDR(GPIO25, 0x0504),
-	MFP_ADDR(GPIO26, 0x0510),
-	MFP_ADDR(GPIO27, 0x0514),
-	MFP_ADDR(GPIO28, 0x0520),
-	MFP_ADDR(GPIO29, 0x0600),
-	MFP_ADDR(GPIO30, 0x0618),
-	MFP_ADDR(GPIO31, 0x0610),
-	MFP_ADDR(GPIO32, 0x060c),
-	MFP_ADDR(GPIO33, 0x061c),
-	MFP_ADDR(GPIO34, 0x0620),
-	MFP_ADDR(GPIO35, 0x0628),
-	MFP_ADDR(GPIO36, 0x062c),
-	MFP_ADDR(GPIO37, 0x0630),
-	MFP_ADDR(GPIO38, 0x0634),
-	MFP_ADDR(GPIO39, 0x0638),
-	MFP_ADDR(GPIO40, 0x063c),
-	MFP_ADDR(GPIO41, 0x0614),
-	MFP_ADDR(GPIO42, 0x0624),
-	MFP_ADDR(GPIO43, 0x0608),
-	MFP_ADDR(GPIO44, 0x0604),
-	MFP_ADDR(GPIO45, 0x050c),
-	MFP_ADDR(GPIO46, 0x0508),
-	MFP_ADDR(GPIO47, 0x02bc),
-	MFP_ADDR(GPIO48, 0x02b4),
-	MFP_ADDR(GPIO49, 0x02b8),
-	MFP_ADDR(GPIO50, 0x02c8),
-	MFP_ADDR(GPIO51, 0x02c0),
-	MFP_ADDR(GPIO52, 0x02c4),
-	MFP_ADDR(GPIO53, 0x02d0),
-	MFP_ADDR(GPIO54, 0x02cc),
-	MFP_ADDR(GPIO55, 0x029c),
-	MFP_ADDR(GPIO56, 0x02a0),
-	MFP_ADDR(GPIO57, 0x0294),
-	MFP_ADDR(GPIO58, 0x0298),
-	MFP_ADDR(GPIO59, 0x02a4),
-	MFP_ADDR(GPIO60, 0x02a8),
-	MFP_ADDR(GPIO61, 0x02b0),
-	MFP_ADDR(GPIO62, 0x02ac),
-	MFP_ADDR(GPIO63, 0x0640),
-	MFP_ADDR(GPIO64, 0x065c),
-	MFP_ADDR(GPIO65, 0x0648),
-	MFP_ADDR(GPIO66, 0x0644),
-	MFP_ADDR(GPIO67, 0x0674),
-	MFP_ADDR(GPIO68, 0x0658),
-	MFP_ADDR(GPIO69, 0x0654),
-	MFP_ADDR(GPIO70, 0x0660),
-	MFP_ADDR(GPIO71, 0x0668),
-	MFP_ADDR(GPIO72, 0x0664),
-	MFP_ADDR(GPIO73, 0x0650),
-	MFP_ADDR(GPIO74, 0x066c),
-	MFP_ADDR(GPIO75, 0x064c),
-	MFP_ADDR(GPIO76, 0x0670),
-	MFP_ADDR(GPIO77, 0x0678),
-	MFP_ADDR(GPIO78, 0x067c),
-	MFP_ADDR(GPIO79, 0x0694),
-	MFP_ADDR(GPIO80, 0x069c),
-	MFP_ADDR(GPIO81, 0x06a0),
-	MFP_ADDR(GPIO82, 0x06a4),
-	MFP_ADDR(GPIO83, 0x0698),
-	MFP_ADDR(GPIO84, 0x06bc),
-	MFP_ADDR(GPIO85, 0x06b4),
-	MFP_ADDR(GPIO86, 0x06b0),
-	MFP_ADDR(GPIO87, 0x06c0),
-	MFP_ADDR(GPIO88, 0x06c4),
-	MFP_ADDR(GPIO89, 0x06ac),
-	MFP_ADDR(GPIO90, 0x0680),
-	MFP_ADDR(GPIO91, 0x0684),
-	MFP_ADDR(GPIO92, 0x0688),
-	MFP_ADDR(GPIO93, 0x0690),
-	MFP_ADDR(GPIO94, 0x068c),
-	MFP_ADDR(GPIO95, 0x06a8),
-	MFP_ADDR(GPIO96, 0x06b8),
-	MFP_ADDR(GPIO97, 0x0410),
-	MFP_ADDR(GPIO98, 0x0418),
-	MFP_ADDR(GPIO99, 0x041c),
-	MFP_ADDR(GPIO100, 0x0414),
-	MFP_ADDR(GPIO101, 0x0408),
-	MFP_ADDR(GPIO102, 0x0324),
-	MFP_ADDR(GPIO103, 0x040c),
-	MFP_ADDR(GPIO104, 0x0400),
-	MFP_ADDR(GPIO105, 0x0328),
-	MFP_ADDR(GPIO106, 0x0404),
-
-	MFP_ADDR(GPIO159, 0x0524),
-	MFP_ADDR(GPIO163, 0x0534),
-	MFP_ADDR(GPIO167, 0x0544),
-	MFP_ADDR(GPIO168, 0x0548),
-	MFP_ADDR(GPIO169, 0x054c),
-	MFP_ADDR(GPIO170, 0x0550),
-	MFP_ADDR(GPIO171, 0x0554),
-	MFP_ADDR(GPIO172, 0x0558),
-	MFP_ADDR(GPIO173, 0x055c),
-
-	MFP_ADDR(nXCVREN, 0x0204),
-	MFP_ADDR(DF_CLE_nOE, 0x020c),
-	MFP_ADDR(DF_nADV1_ALE, 0x0218),
-	MFP_ADDR(DF_SCLK_E, 0x0214),
-	MFP_ADDR(DF_SCLK_S, 0x0210),
-	MFP_ADDR(nBE0, 0x021c),
-	MFP_ADDR(nBE1, 0x0220),
-	MFP_ADDR(DF_nADV2_ALE, 0x0224),
-	MFP_ADDR(DF_INT_RnB, 0x0228),
-	MFP_ADDR(DF_nCS0, 0x022c),
-	MFP_ADDR(DF_nCS1, 0x0230),
-	MFP_ADDR(nLUA, 0x0254),
-	MFP_ADDR(nLLA, 0x0258),
-	MFP_ADDR(DF_nWE, 0x0234),
-	MFP_ADDR(DF_nRE_nOE, 0x0238),
-	MFP_ADDR(DF_ADDR0, 0x024c),
-	MFP_ADDR(DF_ADDR1, 0x0250),
-	MFP_ADDR(DF_ADDR2, 0x025c),
-	MFP_ADDR(DF_ADDR3, 0x0260),
-	MFP_ADDR(DF_IO0, 0x023c),
-	MFP_ADDR(DF_IO1, 0x0240),
-	MFP_ADDR(DF_IO2, 0x0244),
-	MFP_ADDR(DF_IO3, 0x0248),
-	MFP_ADDR(DF_IO4, 0x0264),
-	MFP_ADDR(DF_IO5, 0x0268),
-	MFP_ADDR(DF_IO6, 0x026c),
-	MFP_ADDR(DF_IO7, 0x0270),
-	MFP_ADDR(DF_IO8, 0x0274),
-	MFP_ADDR(DF_IO9, 0x0278),
-	MFP_ADDR(DF_IO10, 0x027c),
-	MFP_ADDR(DF_IO11, 0x0280),
-	MFP_ADDR(DF_IO12, 0x0284),
-	MFP_ADDR(DF_IO13, 0x0288),
-	MFP_ADDR(DF_IO14, 0x028c),
-	MFP_ADDR(DF_IO15, 0x0290),
-
-	MFP_ADDR(GSIM_UIO, 0x0314),
-	MFP_ADDR(GSIM_UCLK, 0x0318),
-	MFP_ADDR(GSIM_UDET, 0x031c),
-	MFP_ADDR(GSIM_nURST, 0x0320),
-
-	MFP_ADDR(PMIC_INT, 0x06c8),
-
-	MFP_ADDR(RDY, 0x0200),
-
-	MFP_ADDR_END,
-};
-
-static DEFINE_CK(pxa95x_lcd, LCD, &clk_pxa3xx_hsio_ops);
-static DEFINE_CLK(pxa95x_pout, &clk_pxa3xx_pout_ops, 13000000, 70);
-static DEFINE_PXA3_CKEN(pxa95x_ffuart, FFUART, 14857000, 1);
-static DEFINE_PXA3_CKEN(pxa95x_btuart, BTUART, 14857000, 1);
-static DEFINE_PXA3_CKEN(pxa95x_stuart, STUART, 14857000, 1);
-static DEFINE_PXA3_CKEN(pxa95x_i2c, I2C, 32842000, 0);
-static DEFINE_PXA3_CKEN(pxa95x_keypad, KEYPAD, 32768, 0);
-static DEFINE_PXA3_CKEN(pxa95x_ssp1, SSP1, 13000000, 0);
-static DEFINE_PXA3_CKEN(pxa95x_ssp2, SSP2, 13000000, 0);
-static DEFINE_PXA3_CKEN(pxa95x_ssp3, SSP3, 13000000, 0);
-static DEFINE_PXA3_CKEN(pxa95x_ssp4, SSP4, 13000000, 0);
-static DEFINE_PXA3_CKEN(pxa95x_pwm0, PWM0, 13000000, 0);
-static DEFINE_PXA3_CKEN(pxa95x_pwm1, PWM1, 13000000, 0);
-static DEFINE_PXA3_CKEN(pxa95x_gpio, GPIO, 13000000, 0);
-
-static struct clk_lookup pxa95x_clkregs[] = {
-	INIT_CLKREG(&clk_pxa95x_pout, NULL, "CLK_POUT"),
-	/* Power I2C clock is always on */
-	INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL),
-	INIT_CLKREG(&clk_pxa95x_lcd, "pxa2xx-fb", NULL),
-	INIT_CLKREG(&clk_pxa95x_ffuart, "pxa2xx-uart.0", NULL),
-	INIT_CLKREG(&clk_pxa95x_btuart, "pxa2xx-uart.1", NULL),
-	INIT_CLKREG(&clk_pxa95x_stuart, "pxa2xx-uart.2", NULL),
-	INIT_CLKREG(&clk_pxa95x_stuart, "pxa2xx-ir", "UARTCLK"),
-	INIT_CLKREG(&clk_pxa95x_i2c, "pxa2xx-i2c.0", NULL),
-	INIT_CLKREG(&clk_pxa95x_keypad, "pxa27x-keypad", NULL),
-	INIT_CLKREG(&clk_pxa95x_ssp1, "pxa27x-ssp.0", NULL),
-	INIT_CLKREG(&clk_pxa95x_ssp2, "pxa27x-ssp.1", NULL),
-	INIT_CLKREG(&clk_pxa95x_ssp3, "pxa27x-ssp.2", NULL),
-	INIT_CLKREG(&clk_pxa95x_ssp4, "pxa27x-ssp.3", NULL),
-	INIT_CLKREG(&clk_pxa95x_pwm0, "pxa27x-pwm.0", NULL),
-	INIT_CLKREG(&clk_pxa95x_pwm1, "pxa27x-pwm.1", NULL),
-	INIT_CLKREG(&clk_pxa95x_gpio, "pxa-gpio", NULL),
-	INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
-};
-
-void __init pxa95x_init_irq(void)
-{
-	pxa_init_irq(96, NULL);
-}
-
-/*
- * device registration specific to PXA93x.
- */
-
-void __init pxa95x_set_i2c_power_info(struct i2c_pxa_platform_data *info)
-{
-	pxa_register_device(&pxa3xx_device_i2c_power, info);
-}
-
-static struct platform_device *devices[] __initdata = {
-	&pxa_device_gpio,
-	&sa1100_device_rtc,
-	&pxa_device_rtc,
-	&pxa27x_device_ssp1,
-	&pxa27x_device_ssp2,
-	&pxa27x_device_ssp3,
-	&pxa3xx_device_ssp4,
-	&pxa27x_device_pwm0,
-	&pxa27x_device_pwm1,
-};
-
-static int __init pxa95x_init(void)
-{
-	int ret = 0, i;
-
-	if (cpu_is_pxa95x()) {
-		mfp_init_base(io_p2v(MFPR_BASE));
-		mfp_init_addr(pxa95x_mfp_addr_map);
-
-		reset_status = ARSR;
-
-		/*
-		 * clear RDH bit every time after reset
-		 *
-		 * Note: the last 3 bits DxS are write-1-to-clear so carefully
-		 * preserve them here in case they will be referenced later
-		 */
-		ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
-
-		clkdev_add_table(pxa95x_clkregs, ARRAY_SIZE(pxa95x_clkregs));
-
-		if ((ret = pxa_init_dma(IRQ_DMA, 32)))
-			return ret;
-
-		register_syscore_ops(&pxa_irq_syscore_ops);
-		register_syscore_ops(&pxa3xx_clock_syscore_ops);
-
-		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
-	}
-
-	return ret;
-}
-
-postcore_initcall(pxa95x_init);
diff --git a/arch/arm/mach-pxa/saarb.c b/arch/arm/mach-pxa/saarb.c
deleted file mode 100644
index 5aded5e..0000000
--- a/arch/arm/mach-pxa/saarb.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- *  linux/arch/arm/mach-pxa/saarb.c
- *
- *  Support for the Marvell Handheld Platform (aka SAARB)
- *
- *  Copyright (C) 2007-2010 Marvell International Ltd.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  publishhed by the Free Software Foundation.
- */
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/i2c/pxa-i2c.h>
-#include <linux/mfd/88pm860x.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include <mach/irqs.h>
-#include <mach/hardware.h>
-#include <mach/mfp.h>
-#include <mach/mfp-pxa930.h>
-#include <mach/pxa95x.h>
-
-#include "generic.h"
-
-#define SAARB_NR_IRQS	(IRQ_BOARD_START + 40)
-
-static struct pm860x_touch_pdata saarb_touch = {
-	.gpadc_prebias	= 1,
-	.slot_cycle	= 1,
-	.tsi_prebias	= 6,
-	.pen_prebias	= 16,
-	.pen_prechg	= 2,
-	.res_x		= 300,
-};
-
-static struct pm860x_backlight_pdata saarb_backlight[] = {
-	{
-		.id	= PM8606_ID_BACKLIGHT,
-		.iset	= PM8606_WLED_CURRENT(24),
-		.flags	= PM8606_BACKLIGHT1,
-	},
-	{},
-};
-
-static struct pm860x_led_pdata saarb_led[] = {
-	{
-		.id	= PM8606_ID_LED,
-		.iset	= PM8606_LED_CURRENT(12),
-		.flags	= PM8606_LED1_RED,
-	}, {
-		.id	= PM8606_ID_LED,
-		.iset	= PM8606_LED_CURRENT(12),
-		.flags	= PM8606_LED1_GREEN,
-	}, {
-		.id	= PM8606_ID_LED,
-		.iset	= PM8606_LED_CURRENT(12),
-		.flags	= PM8606_LED1_BLUE,
-	}, {
-		.id	= PM8606_ID_LED,
-		.iset	= PM8606_LED_CURRENT(12),
-		.flags	= PM8606_LED2_RED,
-	}, {
-		.id	= PM8606_ID_LED,
-		.iset	= PM8606_LED_CURRENT(12),
-		.flags	= PM8606_LED2_GREEN,
-	}, {
-		.id	= PM8606_ID_LED,
-		.iset	= PM8606_LED_CURRENT(12),
-		.flags	= PM8606_LED2_BLUE,
-	},
-};
-
-static struct pm860x_platform_data saarb_pm8607_info = {
-	.touch		= &saarb_touch,
-	.backlight	= &saarb_backlight[0],
-	.led		= &saarb_led[0],
-	.companion_addr	= 0x10,
-	.irq_mode	= 0,
-	.irq_base	= IRQ_BOARD_START,
-
-	.i2c_port	= GI2C_PORT,
-};
-
-static struct i2c_board_info saarb_i2c_info[] = {
-	{
-		.type		= "88PM860x",
-		.addr		= 0x34,
-		.platform_data	= &saarb_pm8607_info,
-		.irq		= PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO83)),
-	},
-};
-
-static void __init saarb_init(void)
-{
-	pxa_set_ffuart_info(NULL);
-	pxa_set_i2c_info(NULL);
-	i2c_register_board_info(0, ARRAY_AND_SIZE(saarb_i2c_info));
-}
-
-MACHINE_START(SAARB, "PXA955 Handheld Platform (aka SAARB)")
-	.atag_offset    = 0x100,
-	.map_io         = pxa3xx_map_io,
-	.nr_irqs	= SAARB_NR_IRQS,
-	.init_irq       = pxa95x_init_irq,
-	.handle_irq	= pxa3xx_handle_irq,
-	.timer          = &pxa_timer,
-	.init_machine   = saarb_init,
-	.restart	= pxa_restart,
-MACHINE_END
-
diff --git a/arch/arm/mach-pxa/tavorevb3.c b/arch/arm/mach-pxa/tavorevb3.c
deleted file mode 100644
index f7d9305..0000000
--- a/arch/arm/mach-pxa/tavorevb3.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- *  linux/arch/arm/mach-pxa/tavorevb3.c
- *
- *  Support for the Marvell EVB3 Development Platform.
- *
- *  Copyright:  (C) Copyright 2008-2010 Marvell International Ltd.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  publishhed by the Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/i2c/pxa-i2c.h>
-#include <linux/gpio.h>
-#include <linux/mfd/88pm860x.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include <mach/pxa930.h>
-
-#include "devices.h"
-#include "generic.h"
-
-#define TAVOREVB3_NR_IRQS	(IRQ_BOARD_START + 24)
-
-static mfp_cfg_t evb3_mfp_cfg[] __initdata = {
-	/* UART */
-	GPIO53_UART1_TXD,
-	GPIO54_UART1_RXD,
-
-	/* PMIC */
-	PMIC_INT_GPIO83,
-};
-
-#if defined(CONFIG_I2C_PXA) || defined(CONFIG_I2C_PXA_MODULE)
-static struct pm860x_touch_pdata evb3_touch = {
-	.gpadc_prebias	= 1,
-	.slot_cycle	= 1,
-	.tsi_prebias	= 6,
-	.pen_prebias	= 16,
-	.pen_prechg	= 2,
-	.res_x		= 300,
-};
-
-static struct pm860x_backlight_pdata evb3_backlight[] = {
-	{
-		.id	= PM8606_ID_BACKLIGHT,
-		.iset	= PM8606_WLED_CURRENT(24),
-		.flags	= PM8606_BACKLIGHT1,
-	},
-	{},
-};
-
-static struct pm860x_led_pdata evb3_led[] = {
-	{
-		.id	= PM8606_ID_LED,
-		.iset	= PM8606_LED_CURRENT(12),
-		.flags	= PM8606_LED1_RED,
-	}, {
-		.id	= PM8606_ID_LED,
-		.iset	= PM8606_LED_CURRENT(12),
-		.flags	= PM8606_LED1_GREEN,
-	}, {
-		.id	= PM8606_ID_LED,
-		.iset	= PM8606_LED_CURRENT(12),
-		.flags	= PM8606_LED1_BLUE,
-	}, {
-		.id	= PM8606_ID_LED,
-		.iset	= PM8606_LED_CURRENT(12),
-		.flags	= PM8606_LED2_RED,
-	}, {
-		.id	= PM8606_ID_LED,
-		.iset	= PM8606_LED_CURRENT(12),
-		.flags	= PM8606_LED2_GREEN,
-	}, {
-		.id	= PM8606_ID_LED,
-		.iset	= PM8606_LED_CURRENT(12),
-		.flags	= PM8606_LED2_BLUE,
-	},
-};
-
-static struct pm860x_platform_data evb3_pm8607_info = {
-	.touch				= &evb3_touch,
-	.backlight			= &evb3_backlight[0],
-	.led				= &evb3_led[0],
-	.companion_addr			= 0x10,
-	.irq_mode			= 0,
-	.irq_base			= IRQ_BOARD_START,
-
-	.i2c_port			= GI2C_PORT,
-};
-
-static struct i2c_board_info evb3_i2c_info[] = {
-	{
-		.type		= "88PM860x",
-		.addr		= 0x34,
-		.platform_data	= &evb3_pm8607_info,
-		.irq		= PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO83)),
-	},
-};
-
-static void __init evb3_init_i2c(void)
-{
-	pxa_set_i2c_info(NULL);
-	i2c_register_board_info(0, ARRAY_AND_SIZE(evb3_i2c_info));
-}
-#else
-static inline void evb3_init_i2c(void) {}
-#endif
-
-static void __init evb3_init(void)
-{
-	/* initialize MFP configurations */
-	pxa3xx_mfp_config(ARRAY_AND_SIZE(evb3_mfp_cfg));
-
-	pxa_set_ffuart_info(NULL);
-
-	evb3_init_i2c();
-}
-
-MACHINE_START(TAVOREVB3, "PXA950 Evaluation Board (aka TavorEVB3)")
-	.atag_offset	= 0x100,
-	.map_io         = pxa3xx_map_io,
-	.nr_irqs	= TAVOREVB3_NR_IRQS,
-	.init_irq       = pxa3xx_init_irq,
-	.handle_irq       = pxa3xx_handle_irq,
-	.timer          = &pxa_timer,
-	.init_machine   = evb3_init,
-	.restart	= pxa_restart,
-MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig
index 2b6cb5f..25df14a 100644
--- a/arch/arm/mach-s3c24xx/Kconfig
+++ b/arch/arm/mach-s3c24xx/Kconfig
@@ -400,11 +400,12 @@ config MACH_MINI2440
 	bool "MINI2440 development board"
 	select EEPROM_AT24
 	select LEDS_CLASS
-	select LEDS_TRIGGER
+	select LEDS_TRIGGERS
 	select LEDS_TRIGGER_BACKLIGHT
 	select NEW_LEDS
 	select S3C_DEV_NAND
 	select S3C_DEV_USB_HOST
+	select S3C_SETUP_CAMIF
 	help
 	  Say Y here to select support for the MINI2440. Is a 10cm x 10cm board
 	  available via various sources. It can come with a 3.5" or 7" touch LCD.
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2440.c b/arch/arm/mach-s3c24xx/clock-s3c2440.c
index 4407b17..04b87ec 100644
--- a/arch/arm/mach-s3c24xx/clock-s3c2440.c
+++ b/arch/arm/mach-s3c24xx/clock-s3c2440.c
@@ -161,6 +161,7 @@ static struct clk_lookup s3c2440_clk_lookup[] = {
 	CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
 	CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
 	CLKDEV_INIT(NULL, "clk_uart_baud3", &s3c2440_clk_fclk_n),
+	CLKDEV_INIT("s3c2440-camif", "camera", &s3c2440_clk_cam_upll),
 };
 
 static int __init_refok s3c2440_clk_add(struct device *dev, struct subsys_interface *sif)
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2443.c b/arch/arm/mach-s3c24xx/clock-s3c2443.c
index 7f689ce..bdaba59 100644
--- a/arch/arm/mach-s3c24xx/clock-s3c2443.c
+++ b/arch/arm/mach-s3c24xx/clock-s3c2443.c
@@ -158,12 +158,6 @@ static struct clk init_clocks_off[] = {
 		.devname	= "s3c2410-spi.0",
 		.parent		= &clk_p,
 		.enable		= s3c2443_clkcon_enable_p,
-		.ctrlbit	= S3C2443_PCLKCON_SPI0,
-	}, {
-		.name		= "spi",
-		.devname	= "s3c2410-spi.1",
-		.parent		= &clk_p,
-		.enable		= s3c2443_clkcon_enable_p,
 		.ctrlbit	= S3C2443_PCLKCON_SPI1,
 	}
 };
diff --git a/arch/arm/mach-s3c24xx/include/mach/bast-map.h b/arch/arm/mach-s3c24xx/include/mach/bast-map.h
index 6e7dc9d..eecea2a 100644
--- a/arch/arm/mach-s3c24xx/include/mach/bast-map.h
+++ b/arch/arm/mach-s3c24xx/include/mach/bast-map.h
@@ -74,7 +74,7 @@
 
 
 /* 0xE0000000 contains the IO space that is split by speed and
- * wether the access is for 8 or 16bit IO... this ensures that
+ * whether the access is for 8 or 16bit IO... this ensures that
  * the correct access is made
  *
  * 0x10000000 of space, partitioned as so:
diff --git a/arch/arm/mach-s3c24xx/include/mach/dma.h b/arch/arm/mach-s3c24xx/include/mach/dma.h
index ee99fd5..6b72d5a 100644
--- a/arch/arm/mach-s3c24xx/include/mach/dma.h
+++ b/arch/arm/mach-s3c24xx/include/mach/dma.h
@@ -88,7 +88,7 @@ enum s3c2410_dma_state {
  *
  * This represents the state of the DMA engine, wrt to the loaded / running
  * transfers. Since we don't have any way of knowing exactly the state of
- * the DMA transfers, we need to know the state to make decisions on wether
+ * the DMA transfers, we need to know the state to make decisions on whether
  * we can
  *
  * S3C2410_DMA_NONE
diff --git a/arch/arm/mach-s3c24xx/include/mach/vr1000-map.h b/arch/arm/mach-s3c24xx/include/mach/vr1000-map.h
index 99612fc..28376e5 100644
--- a/arch/arm/mach-s3c24xx/include/mach/vr1000-map.h
+++ b/arch/arm/mach-s3c24xx/include/mach/vr1000-map.h
@@ -51,7 +51,7 @@
 #define VR1000_VA_PC104_IRQMASK VR1000_IOADDR(0x00600000)
 
 /* 0xE0000000 contains the IO space that is split by speed and
- * wether the access is for 8 or 16bit IO... this ensures that
+ * whether the access is for 8 or 16bit IO... this ensures that
  * the correct access is made
  *
  * 0x10000000 of space, partitioned as so:
diff --git a/arch/arm/mach-s3c24xx/pm.c b/arch/arm/mach-s3c24xx/pm.c
index 60627e6..724755f 100644
--- a/arch/arm/mach-s3c24xx/pm.c
+++ b/arch/arm/mach-s3c24xx/pm.c
@@ -121,7 +121,7 @@ void s3c_pm_configure_extint(void)
 	int pin;
 
 	/* for each of the external interrupts (EINT0..EINT15) we
-	 * need to check wether it is an external interrupt source,
+	 * need to check whether it is an external interrupt source,
 	 * and then configure it as an input if it is not
 	*/
 
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
index 63e7ae3..131c862 100644
--- a/arch/arm/mach-s3c64xx/Kconfig
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -294,6 +294,7 @@ config MACH_WLF_CRAGG_6410
 	select S3C64XX_SETUP_SDHCI
 	select S3C64XX_SETUP_SPI
 	select S3C64XX_SETUP_USB_PHY
+	select S3C_DEV_FB
 	select S3C_DEV_HSMMC
 	select S3C_DEV_HSMMC1
 	select S3C_DEV_HSMMC2
@@ -304,6 +305,7 @@ config MACH_WLF_CRAGG_6410
 	select S3C_DEV_WDT
 	select SAMSUNG_DEV_ADC
 	select SAMSUNG_DEV_KEYPAD
+	select SAMSUNG_DEV_PWM
 	select SAMSUNG_GPIO_EXTRA128
 	help
 	  Machine support for the Wolfson Cragganmore S3C6410 variant.
diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c
index 28041e8..803711e 100644
--- a/arch/arm/mach-s3c64xx/clock.c
+++ b/arch/arm/mach-s3c64xx/clock.c
@@ -138,11 +138,7 @@ static struct clk init_clocks_off[] = {
 		.ctrlbit	= S3C_CLKCON_PCLK_TSADC,
 	}, {
 		.name		= "i2c",
-#ifdef CONFIG_S3C_DEV_I2C1
 		.devname        = "s3c2440-i2c.0",
-#else
-		.devname	= "s3c2440-i2c",
-#endif
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_PCLK_IIC,
@@ -153,25 +149,6 @@ static struct clk init_clocks_off[] = {
 		.enable		= s3c64xx_pclk_ctrl,
 		.ctrlbit	= S3C6410_CLKCON_PCLK_I2C1,
 	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.0",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_IIS0,
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.1",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_IIS1,
-	}, {
-#ifdef CONFIG_CPU_S3C6410
-		.name		= "iis",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C6410_CLKCON_PCLK_IIS2,
-	}, {
-#endif
 		.name		= "keypad",
 		.parent		= &clk_p,
 		.enable		= s3c64xx_pclk_ctrl,
@@ -319,10 +296,6 @@ static struct clk init_clocks_off[] = {
 		.enable		= s3c64xx_sclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_SCLK_MFC,
 	}, {
-		.name		= "cam",
-		.enable		= s3c64xx_sclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_SCLK_CAM,
-	}, {
 		.name		= "sclk_jpeg",
 		.enable		= s3c64xx_sclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_SCLK_JPEG,
@@ -345,6 +318,32 @@ static struct clk clk_48m_spi1 = {
 	.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",
@@ -668,6 +667,7 @@ static struct clksrc_sources clkset_audio1 = {
 	.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,
@@ -680,15 +680,7 @@ static struct clksrc_sources clkset_audio2 = {
 	.sources	= clkset_audio2_list,
 	.nr_sources	= ARRAY_SIZE(clkset_audio2_list),
 };
-
-static struct clk *clkset_camif_list[] = {
-	&clk_h2,
-};
-
-static struct clksrc_sources clkset_camif = {
-	.sources	= clkset_camif_list,
-	.nr_sources	= ARRAY_SIZE(clkset_camif_list),
-};
+#endif
 
 static struct clksrc_clk clksrcs[] = {
 	{
@@ -702,36 +694,6 @@ static struct clksrc_clk clksrcs[] = {
 		.sources	= &clkset_uhost,
 	}, {
 		.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,
-	}, {
-		.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,
-	}, {
-		.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,
-	}, {
-		.clk	= {
 			.name		= "irda-bus",
 			.ctrlbit        = S3C_CLKCON_SCLK_IRDA,
 			.enable		= s3c64xx_sclk_ctrl,
@@ -744,10 +706,9 @@ static struct clksrc_clk clksrcs[] = {
 			.name		= "camera",
 			.ctrlbit        = S3C_CLKCON_SCLK_CAM,
 			.enable		= s3c64xx_sclk_ctrl,
+			.parent		= &clk_h2,
 		},
 		.reg_div	= { .reg = S3C_CLK_DIV0, .shift = 20, .size = 4  },
-		.reg_src	= { .reg = NULL, .shift = 0, .size = 0  },
-		.sources	= &clkset_camif,
 	},
 };
 
@@ -823,6 +784,43 @@ static struct clksrc_clk clk_sclk_spi1 = {
 	.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[] = {
@@ -838,6 +836,8 @@ static struct clksrc_clk *clksrc_cdev[] = {
 	&clk_sclk_mmc2,
 	&clk_sclk_spi0,
 	&clk_sclk_spi1,
+	&clk_audio_bus0,
+	&clk_audio_bus1,
 };
 
 static struct clk *clk_cdev[] = {
@@ -846,6 +846,8 @@ static struct clk *clk_cdev[] = {
 	&clk_hsmmc2,
 	&clk_48m_spi0,
 	&clk_48m_spi1,
+	&clk_i2s0,
+	&clk_i2s1,
 };
 
 static struct clk_lookup s3c64xx_clk_lookup[] = {
@@ -862,6 +864,14 @@ static struct clk_lookup s3c64xx_clk_lookup[] = {
 	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)
diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c
index be746e3..aef303b 100644
--- a/arch/arm/mach-s3c64xx/common.c
+++ b/arch/arm/mach-s3c64xx/common.c
@@ -155,7 +155,6 @@ void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
 	/* initialise the io descriptors we need for initialisation */
 	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
 	iotable_init(mach_desc, size);
-	init_consistent_dma_size(SZ_8M);
 
 	/* detect cpu id */
 	s3c64xx_init_cpu();
diff --git a/arch/arm/mach-s3c64xx/dev-audio.c b/arch/arm/mach-s3c64xx/dev-audio.c
index 35f3e07..e367e87 100644
--- a/arch/arm/mach-s3c64xx/dev-audio.c
+++ b/arch/arm/mach-s3c64xx/dev-audio.c
@@ -23,11 +23,6 @@
 #include <linux/platform_data/asoc-s3c.h>
 #include <plat/gpio-cfg.h>
 
-static const char *rclksrc[] = {
-	[0] = "iis",
-	[1] = "audio-bus",
-};
-
 static int s3c64xx_i2s_cfg_gpio(struct platform_device *pdev)
 {
 	unsigned int base;
@@ -64,11 +59,6 @@ static struct resource s3c64xx_iis0_resource[] = {
 
 static struct s3c_audio_pdata i2sv3_pdata = {
 	.cfg_gpio = s3c64xx_i2s_cfg_gpio,
-	.type = {
-		.i2s = {
-			.src_clk = rclksrc,
-		},
-	},
 };
 
 struct platform_device s3c64xx_device_iis0 = {
@@ -110,7 +100,6 @@ static struct s3c_audio_pdata i2sv4_pdata = {
 	.type = {
 		.i2s = {
 			.quirks = QUIRK_PRI_6CHAN,
-			.src_clk = rclksrc,
 		},
 	},
 };
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
index 4e3fe57..c6d8dba 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
@@ -20,6 +20,8 @@
 
 #include <linux/regulator/machine.h>
 
+#include <sound/wm0010.h>
+#include <sound/wm2200.h>
 #include <sound/wm5100.h>
 #include <sound/wm8996.h>
 #include <sound/wm8962.h>
@@ -33,14 +35,34 @@ static struct s3c64xx_spi_csinfo wm0010_spi_csinfo = {
 	.line = S3C64XX_GPC(3),
 };
 
+static struct wm0010_pdata wm0010_pdata = {
+	.gpio_reset = S3C64XX_GPN(6),
+	.reset_active_high = 1, /* Active high for Glenfarclas Rev 2 */
+};
+
 static struct spi_board_info wm1253_devs[] = {
 	[0] = {
 		.modalias	= "wm0010",
+		.max_speed_hz	= 26 * 1000 * 1000,
 		.bus_num	= 0,
 		.chip_select	= 0,
 		.mode		= SPI_MODE_0,
 		.irq		= S3C_EINT(5),
 		.controller_data = &wm0010_spi_csinfo,
+		.platform_data = &wm0010_pdata,
+	},
+};
+
+static struct spi_board_info balblair_devs[] = {
+	[0] = {
+		.modalias	= "wm0010",
+		.max_speed_hz	= 26 * 1000 * 1000,
+		.bus_num	= 0,
+		.chip_select	= 0,
+		.mode		= SPI_MODE_0,
+		.irq		= S3C_EINT(4),
+		.controller_data = &wm0010_spi_csinfo,
+		.platform_data = &wm0010_pdata,
 	},
 };
 
@@ -166,12 +188,13 @@ static struct regulator_init_data wm8994_ldo2 = {
 
 static struct wm8994_pdata wm8994_pdata = {
 	.gpio_base = CODEC_GPIO_BASE,
+	.micb2_delay = 150,
 	.gpio_defaults = {
 		0x3,          /* IRQ out, active high, CMOS */
 	},
 	.ldo = {
-		 { .init_data = &wm8994_ldo1, },
-		 { .init_data = &wm8994_ldo2, },
+		 { .enable = S3C64XX_GPN(6), .init_data = &wm8994_ldo1, },
+		 { .enable = S3C64XX_GPN(4), .init_data = &wm8994_ldo2, },
 	},
 };
 
@@ -182,7 +205,7 @@ static const struct i2c_board_info wm1277_devs[] = {
 	},
 };
 
-static struct arizona_pdata wm5102_pdata = {
+static struct arizona_pdata wm5102_reva_pdata = {
 	.ldoena = S3C64XX_GPN(7),
 	.gpio_base = CODEC_GPIO_BASE,
 	.irq_active_high = true,
@@ -193,64 +216,131 @@ static struct arizona_pdata wm5102_pdata = {
 	},
 };
 
-static struct s3c64xx_spi_csinfo wm5102_spi_csinfo = {
+static struct s3c64xx_spi_csinfo codec_spi_csinfo = {
 	.line = S3C64XX_GPN(5),
 };
 
+static struct spi_board_info wm5102_reva_spi_devs[] = {
+	[0] = {
+		.modalias	= "wm5102",
+		.max_speed_hz	= 10 * 1000 * 1000,
+		.bus_num	= 0,
+		.chip_select	= 1,
+		.mode		= SPI_MODE_0,
+		.irq		= GLENFARCLAS_PMIC_IRQ_BASE +
+				  WM831X_IRQ_GPIO_2,
+		.controller_data = &codec_spi_csinfo,
+		.platform_data = &wm5102_reva_pdata,
+	},
+};
+
+static struct arizona_pdata wm5102_pdata = {
+	.ldoena = S3C64XX_GPN(7),
+	.gpio_base = CODEC_GPIO_BASE,
+	.irq_active_high = true,
+	.micd_pol_gpio = CODEC_GPIO_BASE + 2,
+	.gpio_defaults = {
+		[2] = 0x10000, /* AIF3TXLRCLK */
+		[3] = 0x4,     /* OPCLK */
+	},
+};
+
 static struct spi_board_info wm5102_spi_devs[] = {
 	[0] = {
 		.modalias	= "wm5102",
 		.max_speed_hz	= 10 * 1000 * 1000,
 		.bus_num	= 0,
-		.chip_select	= 0,
+		.chip_select	= 1,
 		.mode		= SPI_MODE_0,
 		.irq		= GLENFARCLAS_PMIC_IRQ_BASE +
 				  WM831X_IRQ_GPIO_2,
-		.controller_data = &wm5102_spi_csinfo,
+		.controller_data = &codec_spi_csinfo,
 		.platform_data = &wm5102_pdata,
 	},
 };
 
+static struct spi_board_info wm5110_spi_devs[] = {
+	[0] = {
+		.modalias	= "wm5110",
+		.max_speed_hz	= 10 * 1000 * 1000,
+		.bus_num	= 0,
+		.chip_select	= 1,
+		.mode		= SPI_MODE_0,
+		.irq		= GLENFARCLAS_PMIC_IRQ_BASE +
+				  WM831X_IRQ_GPIO_2,
+		.controller_data = &codec_spi_csinfo,
+		.platform_data = &wm5102_reva_pdata,
+	},
+};
+
 static const struct i2c_board_info wm6230_i2c_devs[] = {
 	{ I2C_BOARD_INFO("wm9081", 0x6c),
 	  .platform_data = &wm9081_pdata, },
 };
 
+static struct wm2200_pdata wm2200_pdata = {
+	.ldo_ena = S3C64XX_GPN(7),
+	.gpio_defaults = {
+		[2] = 0x0005,  /* GPIO3 24.576MHz output clock */
+	},
+};
+
+static const struct i2c_board_info wm2200_i2c[] = {
+	{ I2C_BOARD_INFO("wm2200", 0x3a),
+	  .platform_data = &wm2200_pdata, },
+};
+
 static __devinitdata const struct {
 	u8 id;
+	u8 rev;
 	const char *name;
 	const struct i2c_board_info *i2c_devs;
 	int num_i2c_devs;
 	const struct spi_board_info *spi_devs;
 	int num_spi_devs;
 } gf_mods[] = {
-	{ .id = 0x01, .name = "1250-EV1 Springbank" },
-	{ .id = 0x02, .name = "1251-EV1 Jura" },
-	{ .id = 0x03, .name = "1252-EV1 Glenlivet" },
-	{ .id = 0x11, .name = "6249-EV2 Glenfarclas", },
-	{ .id = 0x14, .name = "6271-EV1 Lochnagar" },
-	{ .id = 0x15, .name = "6320-EV1 Bells",
+	{ .id = 0x01, .rev = 0xff, .name = "1250-EV1 Springbank" },
+	{ .id = 0x02, .rev = 0xff, .name = "1251-EV1 Jura" },
+	{ .id = 0x03, .rev = 0xff, .name = "1252-EV1 Glenlivet" },
+	{ .id = 0x06, .rev = 0xff, .name = "WM8997-6721-CS96-EV1 Lapraoig" },
+	{ .id = 0x07, .rev = 0xff, .name = "WM5110-6271 Deanston",
+	  .spi_devs = wm5110_spi_devs,
+	  .num_spi_devs = ARRAY_SIZE(wm5110_spi_devs) },
+	{ .id = 0x08, .rev = 0xff, .name = "WM8903-6102 Tamdhu" },
+	{ .id = 0x09, .rev = 0xff, .name = "WM1811A-6305 Adelphi" },
+	{ .id = 0x0a, .rev = 0xff, .name = "WM8996-6272 Blackadder" },
+	{ .id = 0x0b, .rev = 0xff, .name = "WM8994-6235 Benromach" },
+	{ .id = 0x11, .rev = 0xff, .name = "6249-EV2 Glenfarclas", },
+	{ .id = 0x14, .rev = 0xff, .name = "6271-EV1 Lochnagar" },
+	{ .id = 0x15, .rev = 0xff, .name = "6320-EV1 Bells",
 	  .i2c_devs = wm6230_i2c_devs,
 	  .num_i2c_devs = ARRAY_SIZE(wm6230_i2c_devs) },
-	{ .id = 0x21, .name = "1275-EV1 Mortlach" },
-	{ .id = 0x25, .name = "1274-EV1 Glencadam" },
-	{ .id = 0x31, .name = "1253-EV1 Tomatin",
+	{ .id = 0x21, .rev = 0xff, .name = "1275-EV1 Mortlach" },
+	{ .id = 0x25, .rev = 0xff, .name = "1274-EV1 Glencadam" },
+	{ .id = 0x31, .rev = 0xff, .name = "1253-EV1 Tomatin",
 	  .spi_devs = wm1253_devs, .num_spi_devs = ARRAY_SIZE(wm1253_devs) },
-	{ .id = 0x32, .name = "XXXX-EV1 Caol Illa" },
-	{ .id = 0x33, .name = "XXXX-EV1 Oban" },
-	{ .id = 0x34, .name = "WM0010-6320-CS42 Balblair" },
-	{ .id = 0x39, .name = "1254-EV1 Dallas Dhu",
+	{ .id = 0x32, .rev = 0xff, .name = "XXXX-EV1 Caol Illa" },
+	{ .id = 0x33, .rev = 0xff, .name = "XXXX-EV1 Oban" },
+	{ .id = 0x34, .rev = 0xff, .name = "WM0010-6320-CS42 Balblair",
+	  .spi_devs = balblair_devs,
+	  .num_spi_devs = ARRAY_SIZE(balblair_devs) },
+	{ .id = 0x39, .rev = 0xff, .name = "1254-EV1 Dallas Dhu",
 	  .i2c_devs = wm1254_devs, .num_i2c_devs = ARRAY_SIZE(wm1254_devs) },
-	{ .id = 0x3a, .name = "1259-EV1 Tobermory",
+	{ .id = 0x3a, .rev = 0xff, .name = "1259-EV1 Tobermory",
 	  .i2c_devs = wm1259_devs, .num_i2c_devs = ARRAY_SIZE(wm1259_devs) },
-	{ .id = 0x3b, .name = "1255-EV1 Kilchoman",
+	{ .id = 0x3b, .rev = 0xff, .name = "1255-EV1 Kilchoman",
 	  .i2c_devs = wm1255_devs, .num_i2c_devs = ARRAY_SIZE(wm1255_devs) },
-	{ .id = 0x3c, .name = "1273-EV1 Longmorn" },
-	{ .id = 0x3d, .name = "1277-EV1 Littlemill",
+	{ .id = 0x3c, .rev = 0xff, .name = "1273-EV1 Longmorn" },
+	{ .id = 0x3d, .rev = 0xff, .name = "1277-EV1 Littlemill",
 	  .i2c_devs = wm1277_devs, .num_i2c_devs = ARRAY_SIZE(wm1277_devs) },
-	{ .id = 0x3e, .name = "WM5102-6271-EV1-CS127 Amrut",
+	{ .id = 0x3e, .rev = 0, .name = "WM5102-6271-EV1-CS127 Amrut",
+	  .spi_devs = wm5102_reva_spi_devs,
+	  .num_spi_devs = ARRAY_SIZE(wm5102_reva_spi_devs) },
+	{ .id = 0x3e, .rev = -1, .name = "WM5102-6271-EV1-CS127 Amrut",
 	  .spi_devs = wm5102_spi_devs,
 	  .num_spi_devs = ARRAY_SIZE(wm5102_spi_devs) },
+	{ .id = 0x3f, .rev = -1, .name = "WM2200-6271-CS90-M-REV1",
+	  .i2c_devs = wm2200_i2c, .num_i2c_devs = ARRAY_SIZE(wm2200_i2c) },
 };
 
 static __devinit int wlf_gf_module_probe(struct i2c_client *i2c,
@@ -267,7 +357,8 @@ static __devinit int wlf_gf_module_probe(struct i2c_client *i2c,
 	id = (ret & 0xfe) >> 2;
 	rev = ret & 0x3;
 	for (i = 0; i < ARRAY_SIZE(gf_mods); i++)
-		if (id == gf_mods[i].id)
+		if (id == gf_mods[i].id && (gf_mods[i].rev == 0xff ||
+					    rev == gf_mods[i].rev))
 			break;
 
 	if (i < ARRAY_SIZE(gf_mods)) {
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index 13b7eaa..701f421 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -287,16 +287,21 @@ static struct platform_device littlemill_device = {
 	.id		= -1,
 };
 
-static struct platform_device bells_wm5102_device = {
+static struct platform_device bells_wm2200_device = {
 	.name		= "bells",
 	.id		= 0,
 };
 
-static struct platform_device bells_wm5110_device = {
+static struct platform_device bells_wm5102_device = {
 	.name		= "bells",
 	.id		= 1,
 };
 
+static struct platform_device bells_wm5110_device = {
+	.name		= "bells",
+	.id		= 2,
+};
+
 static struct regulator_consumer_supply wallvdd_consumers[] = {
 	REGULATOR_SUPPLY("SPKVDD", "1-001a"),
 	REGULATOR_SUPPLY("SPKVDD1", "1-001a"),
@@ -304,6 +309,13 @@ static struct regulator_consumer_supply wallvdd_consumers[] = {
 	REGULATOR_SUPPLY("SPKVDDL", "1-001a"),
 	REGULATOR_SUPPLY("SPKVDDR", "1-001a"),
 
+	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"),
 	REGULATOR_SUPPLY("DC3VDD", "0-0034"),
@@ -321,6 +333,16 @@ static struct regulator_consumer_supply wallvdd_consumers[] = {
 	REGULATOR_SUPPLY("DC1VDD", "1-0034"),
 	REGULATOR_SUPPLY("DC2VDD", "1-0034"),
 	REGULATOR_SUPPLY("DC3VDD", "1-0034"),
+	REGULATOR_SUPPLY("LDO1VDD", "1-0034"),
+	REGULATOR_SUPPLY("LDO2VDD", "1-0034"),
+	REGULATOR_SUPPLY("LDO4VDD", "1-0034"),
+	REGULATOR_SUPPLY("LDO5VDD", "1-0034"),
+	REGULATOR_SUPPLY("LDO6VDD", "1-0034"),
+	REGULATOR_SUPPLY("LDO7VDD", "1-0034"),
+	REGULATOR_SUPPLY("LDO8VDD", "1-0034"),
+	REGULATOR_SUPPLY("LDO9VDD", "1-0034"),
+	REGULATOR_SUPPLY("LDO10VDD", "1-0034"),
+	REGULATOR_SUPPLY("LDO11VDD", "1-0034"),
 };
 
 static struct regulator_init_data wallvdd_data = {
@@ -369,6 +391,7 @@ static struct platform_device *crag6410_devices[] __initdata = {
 	&tobermory_device,
 	&littlemill_device,
 	&lowland_device,
+	&bells_wm2200_device,
 	&bells_wm5102_device,
 	&bells_wm5110_device,
 	&wallvdd_device,
@@ -597,6 +620,7 @@ static struct s3c2410_platform_i2c i2c0_pdata = {
 static struct regulator_consumer_supply pvdd_1v2_consumers[] __devinitdata = {
 	REGULATOR_SUPPLY("DCVDD", "spi0.0"),
 	REGULATOR_SUPPLY("AVDD", "spi0.0"),
+	REGULATOR_SUPPLY("AVDD", "spi0.1"),
 };
 
 static struct regulator_init_data pvdd_1v2 __devinitdata = {
@@ -621,6 +645,24 @@ static struct regulator_consumer_supply pvdd_1v8_consumers[] __devinitdata = {
 	REGULATOR_SUPPLY("DCVDD", "1-001a"),
 	REGULATOR_SUPPLY("AVDD", "1-001a"),
 	REGULATOR_SUPPLY("DBVDD", "spi0.0"),
+
+	REGULATOR_SUPPLY("DBVDD", "1-003a"),
+	REGULATOR_SUPPLY("LDOVDD", "1-003a"),
+	REGULATOR_SUPPLY("CPVDD", "1-003a"),
+	REGULATOR_SUPPLY("AVDD", "1-003a"),
+	REGULATOR_SUPPLY("DBVDD1", "spi0.1"),
+	REGULATOR_SUPPLY("DBVDD2", "spi0.1"),
+	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 __devinitdata = {
@@ -685,6 +727,7 @@ static struct i2c_board_info i2c_devs1[] __devinitdata = {
 	  .irq = S3C_EINT(0),
 	  .platform_data = &glenfarclas_pmic_pdata },
 
+	{ I2C_BOARD_INFO("wlf-gf-module", 0x20) },
 	{ I2C_BOARD_INFO("wlf-gf-module", 0x22) },
 	{ I2C_BOARD_INFO("wlf-gf-module", 0x24) },
 	{ I2C_BOARD_INFO("wlf-gf-module", 0x25) },
@@ -810,7 +853,7 @@ static void __init crag6410_machine_init(void)
 	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
 
 	samsung_keypad_set_platdata(&crag6410_keypad_data);
-	s3c64xx_spi0_set_platdata(NULL, 0, 1);
+	s3c64xx_spi0_set_platdata(NULL, 0, 2);
 
 	platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));
 
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c
index 0004455..5112371 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6440.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c
@@ -243,12 +243,6 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 25),
 	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.0",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 26),
-	}, {
 		.name		= "dsim",
 		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p64x0_pclk_ctrl,
@@ -405,15 +399,6 @@ static struct clksrc_clk clksrcs[] = {
 		.sources = &clkset_group1,
 		.reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 },
 		.reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_audio2",
-			.ctrlbit	= (1 << 11),
-			.enable		= s5p64x0_sclk_ctrl,
-		},
-		.sources = &clkset_audio,
-		.reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 0, .size = 3 },
-		.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 24, .size = 4 },
 	},
 };
 
@@ -464,6 +449,26 @@ static struct clksrc_clk clk_sclk_uclk = {
 	.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
 };
 
+static struct clk clk_i2s0 = {
+	.name		= "iis",
+	.devname	= "samsung-i2s.0",
+	.parent		= &clk_pclk_low.clk,
+	.enable		= s5p64x0_pclk_ctrl,
+	.ctrlbit	= (1 << 26),
+};
+
+static struct clksrc_clk clk_audio_bus2 = {
+	.clk	= {
+		.name		= "sclk_audio2",
+		.devname	= "samsung-i2s.0",
+		.ctrlbit	= (1 << 11),
+		.enable		= s5p64x0_sclk_ctrl,
+	},
+	.sources = &clkset_audio,
+	.reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 0, .size = 3 },
+	.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 24, .size = 4 },
+};
+
 static struct clksrc_clk clk_sclk_spi0 = {
 	.clk	= {
 		.name		= "sclk_spi",
@@ -506,13 +511,18 @@ static struct clk dummy_apb_pclk = {
 	.id		= -1,
 };
 
+static struct clk *clk_cdev[] = {
+	&clk_i2s0,
+};
+
 static struct clksrc_clk *clksrc_cdev[] = {
 	&clk_sclk_uclk,
 	&clk_sclk_spi0,
 	&clk_sclk_spi1,
 	&clk_sclk_mmc0,
 	&clk_sclk_mmc1,
-	&clk_sclk_mmc2
+	&clk_sclk_mmc2,
+	&clk_audio_bus2,
 };
 
 static struct clk_lookup s5p6440_clk_lookup[] = {
@@ -524,6 +534,8 @@ static struct clk_lookup s5p6440_clk_lookup[] = {
 	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("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
+	CLKDEV_INIT("samsung-i2s.0", "i2s_opclk1", &clk_audio_bus2.clk),
 };
 
 void __init_or_cpufreq s5p6440_setup_clocks(void)
@@ -596,12 +608,17 @@ static struct clk *clks[] __initdata = {
 void __init s5p6440_register_clocks(void)
 {
 	int ptr;
+	unsigned int cnt;
 
 	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
 
 	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
 		s3c_register_clksrc(sysclks[ptr], 1);
 
+	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);
+
 	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
 	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 	for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c
index f3e0ef3..154dea7 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6450.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c
@@ -247,24 +247,6 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5p64x0_pclk_ctrl,
 		.ctrlbit	= (1 << 22),
 	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.0",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 26),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.1",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.2",
-		.parent		= &clk_pclk_low.clk,
-		.enable		= s5p64x0_pclk_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
 		.name		= "i2c",
 		.devname	= "s3c2440-i2c.1",
 		.parent		= &clk_pclk_low.clk,
@@ -402,6 +384,7 @@ static struct clksrc_sources clkset_sclk_audio0 = {
 static struct clksrc_clk clk_sclk_audio0 = {
 	.clk		= {
 		.name		= "audio-bus",
+		.devname	= "samsung-i2s.0",
 		.enable		= s5p64x0_sclk_ctrl,
 		.ctrlbit	= (1 << 8),
 		.parent		= &clk_dout_epll.clk,
@@ -549,6 +532,36 @@ static struct clksrc_clk clk_sclk_spi1 = {
 	.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
 };
 
+static struct clk clk_i2s0 = {
+	.name		= "iis",
+	.devname	= "samsung-i2s.0",
+	.parent		= &clk_pclk_low.clk,
+	.enable		= s5p64x0_pclk_ctrl,
+	.ctrlbit	= (1 << 26),
+};
+
+static struct clk clk_i2s1 = {
+	.name		= "iis",
+	.devname	= "samsung-i2s.1",
+	.parent		= &clk_pclk_low.clk,
+	.enable		= s5p64x0_pclk_ctrl,
+	.ctrlbit	= (1 << 15),
+};
+
+static struct clk clk_i2s2 = {
+	.name		= "iis",
+	.devname	= "samsung-i2s.2",
+	.parent		= &clk_pclk_low.clk,
+	.enable		= s5p64x0_pclk_ctrl,
+	.ctrlbit	= (1 << 16),
+};
+
+static struct clk *clk_cdev[] = {
+	&clk_i2s0,
+	&clk_i2s1,
+	&clk_i2s2,
+};
+
 static struct clksrc_clk *clksrc_cdev[] = {
 	&clk_sclk_uclk,
 	&clk_sclk_spi0,
@@ -556,6 +569,7 @@ static struct clksrc_clk *clksrc_cdev[] = {
 	&clk_sclk_mmc0,
 	&clk_sclk_mmc1,
 	&clk_sclk_mmc2,
+	&clk_sclk_audio0,
 };
 
 static struct clk_lookup s5p6450_clk_lookup[] = {
@@ -567,6 +581,10 @@ static struct clk_lookup s5p6450_clk_lookup[] = {
 	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("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
+	CLKDEV_INIT("samsung-i2s.0", "i2s_opclk1", &clk_sclk_audio0.clk),
+	CLKDEV_INIT("samsung-i2s.1", "i2s_opclk0", &clk_i2s1),
+	CLKDEV_INIT("samsung-i2s.2", "i2s_opclk0", &clk_i2s2),
 };
 
 /* Clock initialization code */
@@ -584,7 +602,6 @@ static struct clksrc_clk *sysclks[] = {
 	&clk_pclk,
 	&clk_hclk_low,
 	&clk_pclk_low,
-	&clk_sclk_audio0,
 };
 
 static struct clk dummy_apb_pclk = {
@@ -661,10 +678,16 @@ void __init_or_cpufreq s5p6450_setup_clocks(void)
 void __init s5p6450_register_clocks(void)
 {
 	int ptr;
+	unsigned int cnt;
 
 	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
 		s3c_register_clksrc(sysclks[ptr], 1);
 
+
+	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);
+
 	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
 	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 	for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
diff --git a/arch/arm/mach-s5p64x0/common.c b/arch/arm/mach-s5p64x0/common.c
index 111e404..8ae5800 100644
--- a/arch/arm/mach-s5p64x0/common.c
+++ b/arch/arm/mach-s5p64x0/common.c
@@ -187,7 +187,6 @@ void __init s5p6440_map_io(void)
 	s5p6440_default_sdhci2();
 
 	iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc));
-	init_consistent_dma_size(SZ_8M);
 }
 
 void __init s5p6450_map_io(void)
@@ -202,7 +201,6 @@ void __init s5p6450_map_io(void)
 	s5p6450_default_sdhci2();
 
 	iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc));
-	init_consistent_dma_size(SZ_8M);
 }
 
 /*
diff --git a/arch/arm/mach-s5p64x0/dev-audio.c b/arch/arm/mach-s5p64x0/dev-audio.c
index a0d6edf..723d477 100644
--- a/arch/arm/mach-s5p64x0/dev-audio.c
+++ b/arch/arm/mach-s5p64x0/dev-audio.c
@@ -19,11 +19,6 @@
 #include <mach/dma.h>
 #include <mach/irqs.h>
 
-static const char *rclksrc[] = {
-	[0] = "iis",
-	[1] = "sclk_audio2",
-};
-
 static int s5p6440_cfg_i2s(struct platform_device *pdev)
 {
 	switch (pdev->id) {
@@ -45,7 +40,6 @@ static struct s3c_audio_pdata s5p6440_i2s_pdata = {
 	.type = {
 		.i2s = {
 			.quirks = QUIRK_PRI_6CHAN,
-			.src_clk = rclksrc,
 		},
 	},
 };
@@ -93,7 +87,6 @@ static struct s3c_audio_pdata s5p6450_i2s0_pdata = {
 	.type = {
 		.i2s = {
 			.quirks = QUIRK_PRI_6CHAN,
-			.src_clk = rclksrc,
 		},
 	},
 };
@@ -110,11 +103,6 @@ struct platform_device s5p6450_device_iis0 = {
 
 static struct s3c_audio_pdata s5p6450_i2s_pdata = {
 	.cfg_gpio = s5p6450_cfg_i2s,
-	.type = {
-		.i2s = {
-			.src_clk = rclksrc,
-		},
-	},
 };
 
 static struct resource s5p6450_i2s1_resource[] = {
diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c
index 9262197..a206dc3 100644
--- a/arch/arm/mach-s5pc100/clock.c
+++ b/arch/arm/mach-s5pc100/clock.c
@@ -606,24 +606,6 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5pc100_d1_4_ctrl,
 		.ctrlbit	= (1 << 13),
 	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.0",
-		.parent		= &clk_div_pclkd1.clk,
-		.enable		= s5pc100_d1_5_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.1",
-		.parent		= &clk_div_pclkd1.clk,
-		.enable		= s5pc100_d1_5_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.2",
-		.parent		= &clk_div_pclkd1.clk,
-		.enable		= s5pc100_d1_5_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
 		.name		= "ac97",
 		.parent		= &clk_div_pclkd1.clk,
 		.enable		= s5pc100_d1_5_ctrl,
@@ -724,6 +706,30 @@ static struct clk clk_48m_spi2 = {
 	.ctrlbit	= (1 << 9),
 };
 
+static struct clk clk_i2s0 = {
+	.name		= "iis",
+	.devname	= "samsung-i2s.0",
+	.parent		= &clk_div_pclkd1.clk,
+	.enable		= s5pc100_d1_5_ctrl,
+	.ctrlbit	= (1 << 0),
+};
+
+static struct clk clk_i2s1 = {
+	.name		= "iis",
+	.devname	= "samsung-i2s.1",
+	.parent		= &clk_div_pclkd1.clk,
+	.enable		= s5pc100_d1_5_ctrl,
+	.ctrlbit	= (1 << 1),
+};
+
+static struct clk clk_i2s2 = {
+	.name		= "iis",
+	.devname	= "samsung-i2s.2",
+	.parent		= &clk_div_pclkd1.clk,
+	.enable		= s5pc100_d1_5_ctrl,
+	.ctrlbit	= (1 << 2),
+};
+
 static struct clk clk_vclk54m = {
 	.name		= "vclk_54m",
 	.rate		= 54000000,
@@ -1154,6 +1160,9 @@ static struct clk *clk_cdev[] = {
 	&clk_48m_spi0,
 	&clk_48m_spi1,
 	&clk_48m_spi2,
+	&clk_i2s0,
+	&clk_i2s1,
+	&clk_i2s2,
 };
 
 static struct clksrc_clk *clksrc_cdev[] = {
@@ -1321,6 +1330,9 @@ static struct clk_lookup s5pc100_clk_lookup[] = {
 	CLKDEV_INIT("s5pc100-spi.1", "spi_busclk2", &clk_sclk_spi1.clk),
 	CLKDEV_INIT("s5pc100-spi.2", "spi_busclk1", &clk_48m_spi2),
 	CLKDEV_INIT("s5pc100-spi.2", "spi_busclk2", &clk_sclk_spi2.clk),
+	CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
+	CLKDEV_INIT("samsung-i2s.1", "i2s_opclk0", &clk_i2s1),
+	CLKDEV_INIT("samsung-i2s.2", "i2s_opclk0", &clk_i2s2),
 };
 
 void __init s5pc100_register_clocks(void)
diff --git a/arch/arm/mach-s5pc100/dev-audio.c b/arch/arm/mach-s5pc100/dev-audio.c
index 1cc252c..46f488b 100644
--- a/arch/arm/mach-s5pc100/dev-audio.c
+++ b/arch/arm/mach-s5pc100/dev-audio.c
@@ -39,18 +39,12 @@ static int s5pc100_cfg_i2s(struct platform_device *pdev)
 	return 0;
 }
 
-static const char *rclksrc_v5[] = {
-	[0] = "iis",
-	[1] = "i2sclkd2",
-};
-
 static struct s3c_audio_pdata i2sv5_pdata = {
 	.cfg_gpio = s5pc100_cfg_i2s,
 	.type = {
 		.i2s = {
 			.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
 					 | QUIRK_NEED_RSTCLR,
-			.src_clk = rclksrc_v5,
 		},
 	},
 };
@@ -72,18 +66,8 @@ struct platform_device s5pc100_device_iis0 = {
 	},
 };
 
-static const char *rclksrc_v3[] = {
-	[0] = "iis",
-	[1] = "sclk_audio",
-};
-
 static struct s3c_audio_pdata i2sv3_pdata = {
 	.cfg_gpio = s5pc100_cfg_i2s,
-	.type = {
-		.i2s = {
-			.src_clk = rclksrc_v3,
-		},
-	},
 };
 
 static struct resource s5pc100_iis1_resource[] = {
diff --git a/arch/arm/mach-s5pv210/common.c b/arch/arm/mach-s5pv210/common.c
index a0c50ef..9dfe93e 100644
--- a/arch/arm/mach-s5pv210/common.c
+++ b/arch/arm/mach-s5pv210/common.c
@@ -169,8 +169,6 @@ void __init s5pv210_init_io(struct map_desc *mach_desc, int size)
 
 void __init s5pv210_map_io(void)
 {
-	init_consistent_dma_size(14 << 20);
-
 	/* initialise device information early */
 	s5pv210_default_sdhci0();
 	s5pv210_default_sdhci1();
diff --git a/arch/arm/mach-s5pv210/dev-audio.c b/arch/arm/mach-s5pv210/dev-audio.c
index 0a5480b..addfb16 100644
--- a/arch/arm/mach-s5pv210/dev-audio.c
+++ b/arch/arm/mach-s5pv210/dev-audio.c
@@ -20,11 +20,6 @@
 #include <mach/irqs.h>
 #include <mach/regs-audss.h>
 
-static const char *rclksrc[] = {
-	[0] = "busclk",
-	[1] = "i2sclk",
-};
-
 static int s5pv210_cfg_i2s(struct platform_device *pdev)
 {
 	/* configure GPIO for i2s port */
@@ -52,7 +47,6 @@ static struct s3c_audio_pdata i2sv5_pdata = {
 		.i2s = {
 			.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
 					 | QUIRK_NEED_RSTCLR,
-			.src_clk = rclksrc,
 			.idma_addr = S5PV210_AUDSS_INT_MEM,
 		},
 	},
@@ -75,18 +69,8 @@ struct platform_device s5pv210_device_iis0 = {
 	},
 };
 
-static const char *rclksrc_v3[] = {
-	[0] = "iis",
-	[1] = "audio-bus",
-};
-
 static struct s3c_audio_pdata i2sv3_pdata = {
 	.cfg_gpio = s5pv210_cfg_i2s,
-	.type = {
-		.i2s = {
-			.src_clk = rclksrc_v3,
-		},
-	},
 };
 
 static struct resource s5pv210_iis1_resource[] = {
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 55e1dba..c72b310 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -774,7 +774,6 @@ static void __init goni_pmic_init(void)
 /* MoviNAND */
 static struct s3c_sdhci_platdata goni_hsmmc0_data __initdata = {
 	.max_width		= 4,
-	.host_caps2		= MMC_CAP2_BROKEN_VOLTAGE,
 	.cd_type		= S3C_SDHCI_CD_PERMANENT,
 };
 
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index 6a7ad3c..9a23739 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
+#include <linux/platform_data/sa11x0-serial.h>
 #include <linux/serial_core.h>
 #include <linux/mfd/ucb1x00.h>
 #include <linux/mtd/mtd.h>
@@ -37,7 +38,6 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/irda.h>
 #include <asm/mach/map.h>
-#include <asm/mach/serial_sa1100.h>
 #include <mach/assabet.h>
 #include <linux/platform_data/mfd-mcp-sa11x0.h>
 #include <mach/irqs.h>
diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c
index 038df48..b2dadf3 100644
--- a/arch/arm/mach-sa1100/badge4.c
+++ b/arch/arm/mach-sa1100/badge4.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/platform_data/sa11x0-serial.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/tty.h>
@@ -34,7 +35,6 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
 #include <asm/hardware/sa1111.h>
-#include <asm/mach/serial_sa1100.h>
 
 #include <mach/badge4.h>
 
diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
index ad0eb08..304bca4 100644
--- a/arch/arm/mach-sa1100/cerf.c
+++ b/arch/arm/mach-sa1100/cerf.c
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/tty.h>
+#include <linux/platform_data/sa11x0-serial.h>
 #include <linux/platform_device.h>
 #include <linux/irq.h>
 #include <linux/mtd/mtd.h>
@@ -27,7 +28,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
-#include <asm/mach/serial_sa1100.h>
 
 #include <mach/cerf.h>
 #include <linux/platform_data/mfd-mcp-sa11x0.h>
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 170cb61..45f424f 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/tty.h>
 #include <linux/delay.h>
+#include <linux/platform_data/sa11x0-serial.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/ucb1x00.h>
 #include <linux/mtd/mtd.h>
@@ -40,7 +41,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
-#include <asm/mach/serial_sa1100.h>
 
 #include <asm/hardware/scoop.h>
 #include <asm/mach/sharpsl_param.h>
diff --git a/arch/arm/mach-sa1100/h3xxx.c b/arch/arm/mach-sa1100/h3xxx.c
index 63150e1..f17e738 100644
--- a/arch/arm/mach-sa1100/h3xxx.c
+++ b/arch/arm/mach-sa1100/h3xxx.c
@@ -17,12 +17,12 @@
 #include <linux/mfd/htc-egpio.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/platform_data/sa11x0-serial.h>
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
 
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
-#include <asm/mach/serial_sa1100.h>
 
 #include <mach/h3xxx.h>
 
diff --git a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c
index fc106aa..d005939 100644
--- a/arch/arm/mach-sa1100/hackkit.c
+++ b/arch/arm/mach-sa1100/hackkit.c
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/cpufreq.h>
+#include <linux/platform_data/sa11x0-serial.h>
 #include <linux/serial_core.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -35,7 +36,6 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
-#include <asm/mach/serial_sa1100.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index e3084f4..35cfc42 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/tty.h>
 #include <linux/delay.h>
+#include <linux/platform_data/sa11x0-serial.h>
 #include <linux/platform_device.h>
 #include <linux/ioport.h>
 #include <linux/mtd/mtd.h>
@@ -30,7 +31,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
-#include <asm/mach/serial_sa1100.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
index 3048b17..f69f78f 100644
--- a/arch/arm/mach-sa1100/lart.c
+++ b/arch/arm/mach-sa1100/lart.c
@@ -4,6 +4,7 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/platform_data/sa11x0-serial.h>
 #include <linux/tty.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
@@ -18,7 +19,6 @@
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
-#include <asm/mach/serial_sa1100.h>
 #include <linux/platform_data/mfd-mcp-sa11x0.h>
 #include <mach/irqs.h>
 
diff --git a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c
index 41f69d9..102e08f 100644
--- a/arch/arm/mach-sa1100/nanoengine.c
+++ b/arch/arm/mach-sa1100/nanoengine.c
@@ -13,6 +13,7 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/platform_data/sa11x0-serial.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/root_dev.h>
@@ -24,7 +25,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
-#include <asm/mach/serial_sa1100.h>
 
 #include <mach/hardware.h>
 #include <mach/nanoengine.h>
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index 266db87..88be047 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -7,6 +7,7 @@
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/platform_data/sa11x0-serial.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/serial_core.h>
@@ -14,7 +15,6 @@
 
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
-#include <asm/mach/serial_sa1100.h>
 #include <asm/hardware/sa1111.h>
 #include <asm/sizes.h>
 
diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c
index 37fe0a0..c51bb63 100644
--- a/arch/arm/mach-sa1100/pleb.c
+++ b/arch/arm/mach-sa1100/pleb.c
@@ -6,6 +6,7 @@
 #include <linux/kernel.h>
 #include <linux/tty.h>
 #include <linux/ioport.h>
+#include <linux/platform_data/sa11x0-serial.h>
 #include <linux/platform_device.h>
 #include <linux/irq.h>
 #include <linux/io.h>
@@ -18,7 +19,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
-#include <asm/mach/serial_sa1100.h>
 #include <mach/irqs.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c
index ff6b7b3..6460d25 100644
--- a/arch/arm/mach-sa1100/shannon.c
+++ b/arch/arm/mach-sa1100/shannon.c
@@ -5,6 +5,7 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
+#include <linux/platform_data/sa11x0-serial.h>
 #include <linux/tty.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -18,7 +19,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
-#include <asm/mach/serial_sa1100.h>
 #include <linux/platform_data/mfd-mcp-sa11x0.h>
 #include <mach/shannon.h>
 #include <mach/irqs.h>
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 71790e5..6d65f65 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -9,6 +9,7 @@
 #include <linux/proc_fs.h>
 #include <linux/string.h>
 #include <linux/pm.h>
+#include <linux/platform_data/sa11x0-serial.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/ucb1x00.h>
 #include <linux/mtd/mtd.h>
@@ -23,7 +24,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
-#include <asm/mach/serial_sa1100.h>
 #include <linux/platform_data/mfd-mcp-sa11x0.h>
 #include <mach/simpad.h>
 #include <mach/irqs.h>
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 8ae100c..9255546 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -2,18 +2,6 @@ if ARCH_SHMOBILE
 
 comment "SH-Mobile System Type"
 
-config ARCH_SH7367
-	bool "SH-Mobile G3 (SH7367)"
-	select ARCH_WANT_OPTIONAL_GPIOLIB
-	select CPU_V6
-	select SH_CLK_CPG
-
-config ARCH_SH7377
-	bool "SH-Mobile G4 (SH7377)"
-	select ARCH_WANT_OPTIONAL_GPIOLIB
-	select CPU_V7
-	select SH_CLK_CPG
-
 config ARCH_SH7372
 	bool "SH-Mobile AP4 (SH7372)"
 	select ARCH_WANT_OPTIONAL_GPIOLIB
@@ -41,6 +29,8 @@ config ARCH_R8A7779
 	select ARM_GIC
 	select CPU_V7
 	select SH_CLK_CPG
+	select USB_ARCH_HAS_EHCI
+	select USB_ARCH_HAS_OHCI
 
 config ARCH_EMEV2
 	bool "Emma Mobile EV2"
@@ -50,17 +40,6 @@ config ARCH_EMEV2
 
 comment "SH-Mobile Board Type"
 
-config MACH_G3EVM
-	bool "G3EVM board"
-	depends on ARCH_SH7367
-	select ARCH_REQUIRE_GPIOLIB
-
-config MACH_G4EVM
-	bool "G4EVM board"
-	depends on ARCH_SH7377
-	select ARCH_REQUIRE_GPIOLIB
-	select REGULATOR_FIXED_VOLTAGE if REGULATOR
-
 config MACH_AP4EVB
 	bool "AP4EVB board"
 	depends on ARCH_SH7372
@@ -95,6 +74,7 @@ config MACH_MACKEREL
 	select ARCH_REQUIRE_GPIOLIB
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
 	select SND_SOC_AK4642 if SND_SIMPLE_CARD
+	select USE_OF
 
 config MACH_KOTA2
 	bool "KOTA2 board"
@@ -146,8 +126,7 @@ menu "Memory configuration"
 
 config MEMORY_START
 	hex "Physical memory start address"
-	default "0x50000000" if MACH_G3EVM
-	default "0x40000000" if MACH_G4EVM || MACH_AP4EVB || MACH_AG5EVM || \
+	default "0x40000000" if MACH_AP4EVB || MACH_AG5EVM || \
 				MACH_MACKEREL || MACH_BONITO || \
 				MACH_ARMADILLO800EVA
 	default "0x41000000" if MACH_KOTA2
@@ -159,8 +138,6 @@ config MEMORY_START
 
 config MEMORY_SIZE
 	hex "Physical memory size"
-	default "0x08000000" if MACH_G3EVM
-	default "0x08000000" if MACH_G4EVM
 	default "0x20000000" if MACH_AG5EVM || MACH_BONITO || \
 				MACH_ARMADILLO800EVA
 	default "0x1e000000" if MACH_KOTA2
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index fe2c97c..0b71479 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -6,8 +6,6 @@
 obj-y				:= timer.o console.o clock.o
 
 # CPU objects
-obj-$(CONFIG_ARCH_SH7367)	+= setup-sh7367.o clock-sh7367.o intc-sh7367.o
-obj-$(CONFIG_ARCH_SH7377)	+= setup-sh7377.o clock-sh7377.o intc-sh7377.o
 obj-$(CONFIG_ARCH_SH7372)	+= setup-sh7372.o clock-sh7372.o intc-sh7372.o
 obj-$(CONFIG_ARCH_SH73A0)	+= setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o
 obj-$(CONFIG_ARCH_R8A7740)	+= setup-r8a7740.o clock-r8a7740.o intc-r8a7740.o
@@ -23,16 +21,12 @@ smp-$(CONFIG_ARCH_EMEV2)	+= smp-emev2.o
 
 # Pinmux setup
 pfc-y				:=
-pfc-$(CONFIG_ARCH_SH7367)	+= pfc-sh7367.o
-pfc-$(CONFIG_ARCH_SH7377)	+= pfc-sh7377.o
 pfc-$(CONFIG_ARCH_SH7372)	+= pfc-sh7372.o
 pfc-$(CONFIG_ARCH_SH73A0)	+= pfc-sh73a0.o
 pfc-$(CONFIG_ARCH_R8A7740)	+= pfc-r8a7740.o
 pfc-$(CONFIG_ARCH_R8A7779)	+= pfc-r8a7779.o
 
 # IRQ objects
-obj-$(CONFIG_ARCH_SH7367)	+= entry-intc.o
-obj-$(CONFIG_ARCH_SH7377)	+= entry-intc.o
 obj-$(CONFIG_ARCH_SH7372)	+= entry-intc.o
 obj-$(CONFIG_ARCH_R8A7740)	+= entry-intc.o
 
@@ -45,8 +39,6 @@ obj-$(CONFIG_ARCH_R8A7740)	+= pm-r8a7740.o
 obj-$(CONFIG_ARCH_R8A7779)	+= pm-r8a7779.o
 
 # Board objects
-obj-$(CONFIG_MACH_G3EVM)	+= board-g3evm.o
-obj-$(CONFIG_MACH_G4EVM)	+= board-g4evm.o
 obj-$(CONFIG_MACH_AP4EVB)	+= board-ap4evb.o
 obj-$(CONFIG_MACH_AG5EVM)	+= board-ag5evm.o
 obj-$(CONFIG_MACH_MACKEREL)	+= board-mackerel.o
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 790dc68..4065785 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -658,133 +658,16 @@ static struct platform_device lcdc_device = {
 
 /* FSI */
 #define IRQ_FSI		evt2irq(0x1840)
-static int __fsi_set_rate(struct clk *clk, long rate, int enable)
-{
-	int ret = 0;
-
-	if (rate <= 0)
-		return ret;
-
-	if (enable) {
-		ret = clk_set_rate(clk, rate);
-		if (0 == ret)
-			ret = clk_enable(clk);
-	} else {
-		clk_disable(clk);
-	}
-
-	return ret;
-}
-
-static int __fsi_set_round_rate(struct clk *clk, long rate, int enable)
-{
-	return __fsi_set_rate(clk, clk_round_rate(clk, rate), enable);
-}
-
-static int fsi_ak4642_set_rate(struct device *dev, int rate, int enable)
-{
-	struct clk *fsia_ick;
-	struct clk *fsiack;
-	int ret = -EIO;
-
-	fsia_ick = clk_get(dev, "icka");
-	if (IS_ERR(fsia_ick))
-		return PTR_ERR(fsia_ick);
-
-	/*
-	 * FSIACK is connected to AK4642,
-	 * and use external clock pin from it.
-	 * it is parent of fsia_ick now.
-	 */
-	fsiack = clk_get_parent(fsia_ick);
-	if (!fsiack)
-		goto fsia_ick_out;
-
-	/*
-	 * we get 1/1 divided clock by setting same rate to fsiack and fsia_ick
-	 *
-	 ** FIXME **
-	 * Because the freq_table of external clk (fsiack) are all 0,
-	 * the return value of clk_round_rate became 0.
-	 * So, it use __fsi_set_rate here.
-	 */
-	ret = __fsi_set_rate(fsiack, rate, enable);
-	if (ret < 0)
-		goto fsiack_out;
-
-	ret = __fsi_set_round_rate(fsia_ick, rate, enable);
-	if ((ret < 0) && enable)
-		__fsi_set_round_rate(fsiack, rate, 0); /* disable FSI ACK */
-
-fsiack_out:
-	clk_put(fsiack);
-
-fsia_ick_out:
-	clk_put(fsia_ick);
-
-	return 0;
-}
-
-static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable)
-{
-	struct clk *fsib_clk;
-	struct clk *fdiv_clk = &sh7372_fsidivb_clk;
-	long fsib_rate = 0;
-	long fdiv_rate = 0;
-	int ackmd_bpfmd;
-	int ret;
-
-	switch (rate) {
-	case 44100:
-		fsib_rate	= rate * 256;
-		ackmd_bpfmd	= SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
-		break;
-	case 48000:
-		fsib_rate	= 85428000; /* around 48kHz x 256 x 7 */
-		fdiv_rate	= rate * 256;
-		ackmd_bpfmd	= SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
-		break;
-	default:
-		pr_err("unsupported rate in FSI2 port B\n");
-		return -EINVAL;
-	}
-
-	/* FSI B setting */
-	fsib_clk = clk_get(dev, "ickb");
-	if (IS_ERR(fsib_clk))
-		return -EIO;
-
-	ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable);
-	if (ret < 0)
-		goto fsi_set_rate_end;
-
-	/* FSI DIV setting */
-	ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable);
-	if (ret < 0) {
-		/* disable FSI B */
-		if (enable)
-			__fsi_set_round_rate(fsib_clk, fsib_rate, 0);
-		goto fsi_set_rate_end;
-	}
-
-	ret = ackmd_bpfmd;
-
-fsi_set_rate_end:
-	clk_put(fsib_clk);
-	return ret;
-}
-
 static struct sh_fsi_platform_info fsi_info = {
 	.port_a = {
 		.flags		= SH_FSI_BRS_INV,
-		.set_rate	= fsi_ak4642_set_rate,
 	},
 	.port_b = {
 		.flags		= SH_FSI_BRS_INV |
 				  SH_FSI_BRM_INV |
 				  SH_FSI_LRS_INV |
+				  SH_FSI_CLK_CPG |
 				  SH_FSI_FMT_SPDIF,
-		.set_rate	= fsi_hdmi_set_rate,
 	},
 };
 
@@ -1144,25 +1027,6 @@ out:
 		clk_put(hdmi_ick);
 }
 
-static void __init fsi_init_pm_clock(void)
-{
-	struct clk *fsia_ick;
-	int ret;
-
-	fsia_ick = clk_get(&fsi_device.dev, "icka");
-	if (IS_ERR(fsia_ick)) {
-		ret = PTR_ERR(fsia_ick);
-		pr_err("Cannot get FSI ICK: %d\n", ret);
-		return;
-	}
-
-	ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk);
-	if (ret < 0)
-		pr_err("Cannot set FSI-A parent: %d\n", ret);
-
-	clk_put(fsia_ick);
-}
-
 /* TouchScreen */
 #ifdef CONFIG_AP4EVB_QHD
 # define GPIO_TSC_IRQ	GPIO_FN_IRQ28_123
@@ -1476,7 +1340,6 @@ static void __init ap4evb_init(void)
 				       ARRAY_SIZE(domain_devices));
 
 	hdmi_init_pm_clock();
-	fsi_init_pm_clock();
 	sh7372_pm_init();
 	pm_clk_add(&fsi_device.dev, "spu2");
 	pm_clk_add(&lcdc1_device.dev, "hdmi");
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index 3cc8b1c..5353adf 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -768,32 +768,6 @@ static struct platform_device ceu0_device = {
 };
 
 /* FSI */
-static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable)
-{
-	struct clk *fsib;
-	int ret;
-
-	/* it support 48KHz only */
-	if (48000 != rate)
-		return -EINVAL;
-
-	fsib = clk_get(dev, "ickb");
-	if (IS_ERR(fsib))
-		return -EINVAL;
-
-	if (enable) {
-		ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
-		clk_enable(fsib);
-	} else {
-		ret = 0;
-		clk_disable(fsib);
-	}
-
-	clk_put(fsib);
-
-	return ret;
-}
-
 static struct sh_fsi_platform_info fsi_info = {
 	/* FSI-WM8978 */
 	.port_a = {
@@ -802,8 +776,8 @@ static struct sh_fsi_platform_info fsi_info = {
 	/* FSI-HDMI */
 	.port_b = {
 		.flags		= SH_FSI_FMT_SPDIF |
-				  SH_FSI_ENABLE_STREAM_MODE,
-		.set_rate	= fsi_hdmi_set_rate,
+				  SH_FSI_ENABLE_STREAM_MODE |
+				  SH_FSI_CLK_CPG,
 		.tx_id		= SHDMA_SLAVE_FSIB_TX,
 	}
 };
@@ -938,13 +912,11 @@ static void __init eva_clock_init(void)
 	struct clk *xtal1	= clk_get(NULL, "extal1");
 	struct clk *usb24s	= clk_get(NULL, "usb24s");
 	struct clk *fsibck	= clk_get(NULL, "fsibck");
-	struct clk *fsib	= clk_get(&fsi_device.dev, "ickb");
 
 	if (IS_ERR(system)	||
 	    IS_ERR(xtal1)	||
 	    IS_ERR(usb24s)	||
-	    IS_ERR(fsibck)	||
-	    IS_ERR(fsib)) {
+	    IS_ERR(fsibck)) {
 		pr_err("armadillo800eva board clock init failed\n");
 		goto clock_error;
 	}
@@ -956,9 +928,7 @@ static void __init eva_clock_init(void)
 	clk_set_parent(usb24s, system);
 
 	/* FSIBCK is 12.288MHz, and it is parent of FSI-B */
-	clk_set_parent(fsib, fsibck);
 	clk_set_rate(fsibck, 12288000);
-	clk_set_rate(fsib,   12288000);
 
 clock_error:
 	if (!IS_ERR(system))
@@ -969,8 +939,6 @@ clock_error:
 		clk_put(usb24s);
 	if (!IS_ERR(fsibck))
 		clk_put(fsibck);
-	if (!IS_ERR(fsib))
-		clk_put(fsib);
 }
 
 /*
@@ -1229,6 +1197,13 @@ static void __init eva_add_early_devices(void)
 	shmobile_timer.init = eva_earlytimer_init;
 }
 
+#define RESCNT2 IOMEM(0xe6188020)
+static void eva_restart(char mode, const char *cmd)
+{
+	/* Do soft power on reset */
+	writel((1 << 31), RESCNT2);
+}
+
 static const char *eva_boards_compat_dt[] __initdata = {
 	"renesas,armadillo800eva",
 	NULL,
@@ -1243,4 +1218,5 @@ DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva")
 	.init_late	= shmobile_init_late,
 	.timer		= &shmobile_timer,
 	.dt_compat	= eva_boards_compat_dt,
+	.restart	= eva_restart,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-g3evm.c b/arch/arm/mach-shmobile/board-g3evm.c
deleted file mode 100644
index b179d4c..0000000
--- a/arch/arm/mach-shmobile/board-g3evm.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * G3EVM board support
- *
- * Copyright (C) 2010  Magnus Damm
- * Copyright (C) 2008  Yoshihiro Shimoda
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/sh_flctl.h>
-#include <linux/usb/r8a66597.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/input.h>
-#include <linux/input/sh_keysc.h>
-#include <linux/dma-mapping.h>
-#include <mach/irqs.h>
-#include <mach/sh7367.h>
-#include <mach/common.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-/*
- * IrDA
- *
- * S67: 5bit : ON  power
- *    : 6bit : ON  remote control
- *             OFF IrDA
- */
-
-static struct mtd_partition nor_flash_partitions[] = {
-	{
-		.name		= "loader",
-		.offset		= 0x00000000,
-		.size		= 512 * 1024,
-	},
-	{
-		.name		= "bootenv",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= 512 * 1024,
-	},
-	{
-		.name		= "kernel_ro",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= 8 * 1024 * 1024,
-		.mask_flags	= MTD_WRITEABLE,
-	},
-	{
-		.name		= "kernel",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= 8 * 1024 * 1024,
-	},
-	{
-		.name		= "data",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= MTDPART_SIZ_FULL,
-	},
-};
-
-static struct physmap_flash_data nor_flash_data = {
-	.width		= 2,
-	.parts		= nor_flash_partitions,
-	.nr_parts	= ARRAY_SIZE(nor_flash_partitions),
-};
-
-static struct resource nor_flash_resources[] = {
-	[0]	= {
-		.start	= 0x00000000,
-		.end	= 0x08000000 - 1,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device nor_flash_device = {
-	.name		= "physmap-flash",
-	.dev		= {
-		.platform_data	= &nor_flash_data,
-	},
-	.num_resources	= ARRAY_SIZE(nor_flash_resources),
-	.resource	= nor_flash_resources,
-};
-
-/* USBHS */
-static void usb_host_port_power(int port, int power)
-{
-	if (!power) /* only power-on supported for now */
-		return;
-
-	/* set VBOUT/PWEN and EXTLP0 in DVSTCTR */
-	__raw_writew(__raw_readw(IOMEM(0xe6890008)) | 0x600, IOMEM(0xe6890008));
-}
-
-static struct r8a66597_platdata usb_host_data = {
-	.on_chip = 1,
-	.port_power = usb_host_port_power,
-};
-
-static struct resource usb_host_resources[] = {
-	[0] = {
-		.name	= "USBHS",
-		.start	= 0xe6890000,
-		.end	= 0xe68900e5,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0xa20), /* USBHS_USHI0 */
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device usb_host_device = {
-	.name		= "r8a66597_hcd",
-	.id		= 0,
-	.dev = {
-		.platform_data		= &usb_host_data,
-		.dma_mask		= NULL,
-		.coherent_dma_mask	= 0xffffffff,
-	},
-	.num_resources	= ARRAY_SIZE(usb_host_resources),
-	.resource	= usb_host_resources,
-};
-
-/* KEYSC */
-static struct sh_keysc_info keysc_info = {
-	.mode		= SH_KEYSC_MODE_5,
-	.scan_timing	= 3,
-	.delay		= 100,
-	.keycodes = {
-		KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G,
-		KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N,
-		KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U,
-		KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_HOME, KEY_SLEEP,
-		KEY_WAKEUP, KEY_COFFEE, KEY_0, KEY_1, KEY_2, KEY_3, KEY_4,
-		KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_STOP, KEY_COMPUTER,
-	},
-};
-
-static struct resource keysc_resources[] = {
-	[0] = {
-		.name	= "KEYSC",
-		.start  = 0xe61b0000,
-		.end    = 0xe61b000f,
-		.flags  = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start  = evt2irq(0xbe0), /* KEYSC_KEY */
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device keysc_device = {
-	.name           = "sh_keysc",
-	.num_resources  = ARRAY_SIZE(keysc_resources),
-	.resource       = keysc_resources,
-	.dev	= {
-		.platform_data	= &keysc_info,
-	},
-};
-
-static struct mtd_partition nand_partition_info[] = {
-	{
-		.name	= "system",
-		.offset	= 0,
-		.size	= 64 * 1024 * 1024,
-	},
-	{
-		.name	= "userdata",
-		.offset	= MTDPART_OFS_APPEND,
-		.size	= 128 * 1024 * 1024,
-	},
-	{
-		.name	= "cache",
-		.offset	= MTDPART_OFS_APPEND,
-		.size	= 64 * 1024 * 1024,
-	},
-};
-
-static struct resource nand_flash_resources[] = {
-	[0] = {
-		.start	= 0xe6a30000,
-		.end	= 0xe6a3009b,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct sh_flctl_platform_data nand_flash_data = {
-	.parts		= nand_partition_info,
-	.nr_parts	= ARRAY_SIZE(nand_partition_info),
-	.flcmncr_val	= QTSEL_E | FCKSEL_E | TYPESEL_SET | NANWF_E
-			| SHBUSSEL | SEL_16BIT,
-};
-
-static struct platform_device nand_flash_device = {
-	.name		= "sh_flctl",
-	.resource	= nand_flash_resources,
-	.num_resources	= ARRAY_SIZE(nand_flash_resources),
-	.dev		= {
-		.platform_data = &nand_flash_data,
-	},
-};
-
-static struct resource irda_resources[] = {
-	[0] = {
-		.start	= 0xE6D00000,
-		.end	= 0xE6D01FD4 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start  = evt2irq(0x480), /* IRDA */
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device irda_device = {
-	.name		= "sh_irda",
-	.id		= -1,
-	.resource	= irda_resources,
-	.num_resources	= ARRAY_SIZE(irda_resources),
-};
-
-static struct platform_device *g3evm_devices[] __initdata = {
-	&nor_flash_device,
-	&usb_host_device,
-	&keysc_device,
-	&nand_flash_device,
-	&irda_device,
-};
-
-static void __init g3evm_init(void)
-{
-	sh7367_pinmux_init();
-
-	/* Lit DS4 LED */
-	gpio_request(GPIO_PORT22, NULL);
-	gpio_direction_output(GPIO_PORT22, 1);
-	gpio_export(GPIO_PORT22, 0);
-
-	/* Lit DS8 LED */
-	gpio_request(GPIO_PORT23, NULL);
-	gpio_direction_output(GPIO_PORT23, 1);
-	gpio_export(GPIO_PORT23, 0);
-
-	/* Lit DS3 LED */
-	gpio_request(GPIO_PORT24, NULL);
-	gpio_direction_output(GPIO_PORT24, 1);
-	gpio_export(GPIO_PORT24, 0);
-
-	/* SCIFA1 */
-	gpio_request(GPIO_FN_SCIFA1_TXD, NULL);
-	gpio_request(GPIO_FN_SCIFA1_RXD, NULL);
-	gpio_request(GPIO_FN_SCIFA1_CTS, NULL);
-	gpio_request(GPIO_FN_SCIFA1_RTS, NULL);
-
-	/* USBHS */
-	gpio_request(GPIO_FN_VBUS0, NULL);
-	gpio_request(GPIO_FN_PWEN, NULL);
-	gpio_request(GPIO_FN_OVCN, NULL);
-	gpio_request(GPIO_FN_OVCN2, NULL);
-	gpio_request(GPIO_FN_EXTLP, NULL);
-	gpio_request(GPIO_FN_IDIN, NULL);
-
-	/* setup USB phy */
-	__raw_writew(0x0300, IOMEM(0xe605810a));	/* USBCR1 */
-	__raw_writew(0x00e0, IOMEM(0xe60581c0));	/* CPFCH */
-	__raw_writew(0x6010, IOMEM(0xe60581c6));	/* CGPOSR */
-	__raw_writew(0x8a0a, IOMEM(0xe605810c));	/* USBCR2 */
-
-	/* KEYSC @ CN7 */
-	gpio_request(GPIO_FN_PORT42_KEYOUT0, NULL);
-	gpio_request(GPIO_FN_PORT43_KEYOUT1, NULL);
-	gpio_request(GPIO_FN_PORT44_KEYOUT2, NULL);
-	gpio_request(GPIO_FN_PORT45_KEYOUT3, NULL);
-	gpio_request(GPIO_FN_PORT46_KEYOUT4, NULL);
-	gpio_request(GPIO_FN_PORT47_KEYOUT5, NULL);
-	gpio_request(GPIO_FN_PORT48_KEYIN0_PU, NULL);
-	gpio_request(GPIO_FN_PORT49_KEYIN1_PU, NULL);
-	gpio_request(GPIO_FN_PORT50_KEYIN2_PU, NULL);
-	gpio_request(GPIO_FN_PORT55_KEYIN3_PU, NULL);
-	gpio_request(GPIO_FN_PORT56_KEYIN4_PU, NULL);
-	gpio_request(GPIO_FN_PORT57_KEYIN5_PU, NULL);
-	gpio_request(GPIO_FN_PORT58_KEYIN6_PU, NULL);
-
-	/* FLCTL */
-	gpio_request(GPIO_FN_FCE0, NULL);
-	gpio_request(GPIO_FN_D0_ED0_NAF0, NULL);
-	gpio_request(GPIO_FN_D1_ED1_NAF1, NULL);
-	gpio_request(GPIO_FN_D2_ED2_NAF2, NULL);
-	gpio_request(GPIO_FN_D3_ED3_NAF3, NULL);
-	gpio_request(GPIO_FN_D4_ED4_NAF4, NULL);
-	gpio_request(GPIO_FN_D5_ED5_NAF5, NULL);
-	gpio_request(GPIO_FN_D6_ED6_NAF6, NULL);
-	gpio_request(GPIO_FN_D7_ED7_NAF7, NULL);
-	gpio_request(GPIO_FN_D8_ED8_NAF8, NULL);
-	gpio_request(GPIO_FN_D9_ED9_NAF9, NULL);
-	gpio_request(GPIO_FN_D10_ED10_NAF10, NULL);
-	gpio_request(GPIO_FN_D11_ED11_NAF11, NULL);
-	gpio_request(GPIO_FN_D12_ED12_NAF12, NULL);
-	gpio_request(GPIO_FN_D13_ED13_NAF13, NULL);
-	gpio_request(GPIO_FN_D14_ED14_NAF14, NULL);
-	gpio_request(GPIO_FN_D15_ED15_NAF15, NULL);
-	gpio_request(GPIO_FN_WE0_XWR0_FWE, NULL);
-	gpio_request(GPIO_FN_FRB, NULL);
-	/* FOE, FCDE, FSC on dedicated pins */
-	__raw_writel(__raw_readl(IOMEM(0xe6158048)) & ~(1 << 15), IOMEM(0xe6158048));
-
-	/* IrDA */
-	gpio_request(GPIO_FN_IRDA_OUT, NULL);
-	gpio_request(GPIO_FN_IRDA_IN, NULL);
-	gpio_request(GPIO_FN_IRDA_FIRSEL, NULL);
-
-	sh7367_add_standard_devices();
-
-	platform_add_devices(g3evm_devices, ARRAY_SIZE(g3evm_devices));
-}
-
-MACHINE_START(G3EVM, "g3evm")
-	.map_io		= sh7367_map_io,
-	.init_early	= sh7367_add_early_devices,
-	.init_irq	= sh7367_init_irq,
-	.handle_irq	= shmobile_handle_irq_intc,
-	.init_machine	= g3evm_init,
-	.init_late	= shmobile_init_late,
-	.timer		= &shmobile_timer,
-MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-g4evm.c b/arch/arm/mach-shmobile/board-g4evm.c
deleted file mode 100644
index 35c126c..0000000
--- a/arch/arm/mach-shmobile/board-g4evm.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * G4EVM board support
- *
- * Copyright (C) 2010  Magnus Damm
- * Copyright (C) 2008  Yoshihiro Shimoda
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/machine.h>
-#include <linux/usb/r8a66597.h>
-#include <linux/io.h>
-#include <linux/input.h>
-#include <linux/input/sh_keysc.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/sh_mobile_sdhi.h>
-#include <linux/gpio.h>
-#include <linux/dma-mapping.h>
-#include <mach/irqs.h>
-#include <mach/sh7377.h>
-#include <mach/common.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include "sh-gpio.h"
-
-/*
- * SDHI
- *
- * SDHI0 : card detection is possible
- * SDHI1 : card detection is impossible
- *
- * [G4-MAIN-BOARD]
- * JP74 : short		# DBG_2V8A    for SDHI0
- * JP75 : NC		# DBG_3V3A    for SDHI0
- * JP76 : NC		# DBG_3V3A_SD for SDHI0
- * JP77 : NC		# 3V3A_SDIO   for SDHI1
- * JP78 : short		# DBG_2V8A    for SDHI1
- * JP79 : NC		# DBG_3V3A    for SDHI1
- * JP80 : NC		# DBG_3V3A_SD for SDHI1
- *
- * [G4-CORE-BOARD]
- * S32 : all off	# to dissever from G3-CORE_DBG board
- * S33 : all off	# to dissever from G3-CORE_DBG board
- *
- * [G3-CORE_DBG-BOARD]
- * S1  : all off	# to dissever from G3-CORE_DBG board
- * S3  : all off	# to dissever from G3-CORE_DBG board
- * S4  : all off	# to dissever from G3-CORE_DBG board
- */
-
-static struct mtd_partition nor_flash_partitions[] = {
-	{
-		.name		= "loader",
-		.offset		= 0x00000000,
-		.size		= 512 * 1024,
-	},
-	{
-		.name		= "bootenv",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= 512 * 1024,
-	},
-	{
-		.name		= "kernel_ro",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= 8 * 1024 * 1024,
-		.mask_flags	= MTD_WRITEABLE,
-	},
-	{
-		.name		= "kernel",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= 8 * 1024 * 1024,
-	},
-	{
-		.name		= "data",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= MTDPART_SIZ_FULL,
-	},
-};
-
-static struct physmap_flash_data nor_flash_data = {
-	.width		= 2,
-	.parts		= nor_flash_partitions,
-	.nr_parts	= ARRAY_SIZE(nor_flash_partitions),
-};
-
-static struct resource nor_flash_resources[] = {
-	[0]	= {
-		.start	= 0x00000000,
-		.end	= 0x08000000 - 1,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device nor_flash_device = {
-	.name		= "physmap-flash",
-	.dev		= {
-		.platform_data	= &nor_flash_data,
-	},
-	.num_resources	= ARRAY_SIZE(nor_flash_resources),
-	.resource	= nor_flash_resources,
-};
-
-/* USBHS */
-static void usb_host_port_power(int port, int power)
-{
-	if (!power) /* only power-on supported for now */
-		return;
-
-	/* set VBOUT/PWEN and EXTLP0 in DVSTCTR */
-	__raw_writew(__raw_readw(IOMEM(0xe6890008)) | 0x600, IOMEM(0xe6890008));
-}
-
-static struct r8a66597_platdata usb_host_data = {
-	.on_chip = 1,
-	.port_power = usb_host_port_power,
-};
-
-static struct resource usb_host_resources[] = {
-	[0] = {
-		.name	= "USBHS",
-		.start	= 0xe6890000,
-		.end	= 0xe68900e5,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0x0a20), /* USBHS_USHI0 */
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device usb_host_device = {
-	.name		= "r8a66597_hcd",
-	.id		= 0,
-	.dev = {
-		.platform_data		= &usb_host_data,
-		.dma_mask		= NULL,
-		.coherent_dma_mask	= 0xffffffff,
-	},
-	.num_resources	= ARRAY_SIZE(usb_host_resources),
-	.resource	= usb_host_resources,
-};
-
-/* KEYSC */
-static struct sh_keysc_info keysc_info = {
-	.mode		= SH_KEYSC_MODE_5,
-	.scan_timing	= 3,
-	.delay		= 100,
-	.keycodes = {
-		KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F,
-		KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L,
-		KEY_M, KEY_N, KEY_U, KEY_P, KEY_Q, KEY_R,
-		KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, KEY_X,
-		KEY_Y, KEY_Z, KEY_HOME, KEY_SLEEP, KEY_WAKEUP, KEY_COFFEE,
-		KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5,
-		KEY_6, KEY_7, KEY_8, KEY_9, KEY_STOP, KEY_COMPUTER,
-	},
-};
-
-static struct resource keysc_resources[] = {
-	[0] = {
-		.name	= "KEYSC",
-		.start  = 0xe61b0000,
-		.end    = 0xe61b000f,
-		.flags  = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start  = evt2irq(0x0be0), /* KEYSC_KEY */
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device keysc_device = {
-	.name           = "sh_keysc",
-	.id             = 0, /* keysc0 clock */
-	.num_resources  = ARRAY_SIZE(keysc_resources),
-	.resource       = keysc_resources,
-	.dev	= {
-		.platform_data	= &keysc_info,
-	},
-};
-
-/* Fixed 3.3V regulator to be used by SDHI0 and SDHI1 */
-static struct regulator_consumer_supply fixed3v3_power_consumers[] =
-{
-	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
-	REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"),
-	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"),
-	REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.1"),
-};
-
-/* SDHI */
-static struct sh_mobile_sdhi_info sdhi0_info = {
-	.tmio_caps	= MMC_CAP_SDIO_IRQ,
-};
-
-static struct resource sdhi0_resources[] = {
-	[0] = {
-		.name	= "SDHI0",
-		.start  = 0xe6d50000,
-		.end    = 0xe6d500ff,
-		.flags  = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start  = evt2irq(0x0e00), /* SDHI0 */
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device sdhi0_device = {
-	.name           = "sh_mobile_sdhi",
-	.num_resources  = ARRAY_SIZE(sdhi0_resources),
-	.resource       = sdhi0_resources,
-	.id             = 0,
-	.dev	= {
-		.platform_data	= &sdhi0_info,
-	},
-};
-
-static struct sh_mobile_sdhi_info sdhi1_info = {
-	.tmio_caps	= MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ,
-};
-
-static struct resource sdhi1_resources[] = {
-	[0] = {
-		.name	= "SDHI1",
-		.start  = 0xe6d60000,
-		.end    = 0xe6d600ff,
-		.flags  = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start  = evt2irq(0x0e80), /* SDHI1 */
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device sdhi1_device = {
-	.name           = "sh_mobile_sdhi",
-	.num_resources  = ARRAY_SIZE(sdhi1_resources),
-	.resource       = sdhi1_resources,
-	.id             = 1,
-	.dev	= {
-		.platform_data	= &sdhi1_info,
-	},
-};
-
-static struct platform_device *g4evm_devices[] __initdata = {
-	&nor_flash_device,
-	&usb_host_device,
-	&keysc_device,
-	&sdhi0_device,
-	&sdhi1_device,
-};
-
-#define GPIO_SDHID0_D0	IOMEM(0xe60520fc)
-#define GPIO_SDHID0_D1	IOMEM(0xe60520fd)
-#define GPIO_SDHID0_D2	IOMEM(0xe60520fe)
-#define GPIO_SDHID0_D3	IOMEM(0xe60520ff)
-#define GPIO_SDHICMD0	IOMEM(0xe6052100)
-
-#define GPIO_SDHID1_D0	IOMEM(0xe6052103)
-#define GPIO_SDHID1_D1	IOMEM(0xe6052104)
-#define GPIO_SDHID1_D2	IOMEM(0xe6052105)
-#define GPIO_SDHID1_D3	IOMEM(0xe6052106)
-#define GPIO_SDHICMD1	IOMEM(0xe6052107)
-
-static void __init g4evm_init(void)
-{
-	regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
-				     ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
-
-	sh7377_pinmux_init();
-
-	/* Lit DS14 LED */
-	gpio_request(GPIO_PORT109, NULL);
-	gpio_direction_output(GPIO_PORT109, 1);
-	gpio_export(GPIO_PORT109, 1);
-
-	/* Lit DS15 LED */
-	gpio_request(GPIO_PORT110, NULL);
-	gpio_direction_output(GPIO_PORT110, 1);
-	gpio_export(GPIO_PORT110, 1);
-
-	/* Lit DS16 LED */
-	gpio_request(GPIO_PORT112, NULL);
-	gpio_direction_output(GPIO_PORT112, 1);
-	gpio_export(GPIO_PORT112, 1);
-
-	/* Lit DS17 LED */
-	gpio_request(GPIO_PORT113, NULL);
-	gpio_direction_output(GPIO_PORT113, 1);
-	gpio_export(GPIO_PORT113, 1);
-
-	/* USBHS */
-	gpio_request(GPIO_FN_VBUS_0, NULL);
-	gpio_request(GPIO_FN_PWEN, NULL);
-	gpio_request(GPIO_FN_OVCN, NULL);
-	gpio_request(GPIO_FN_OVCN2, NULL);
-	gpio_request(GPIO_FN_EXTLP, NULL);
-	gpio_request(GPIO_FN_IDIN, NULL);
-
-	/* setup USB phy */
-	__raw_writew(0x0200, IOMEM(0xe605810a));       /* USBCR1 */
-	__raw_writew(0x00e0, IOMEM(0xe60581c0));       /* CPFCH */
-	__raw_writew(0x6010, IOMEM(0xe60581c6));       /* CGPOSR */
-	__raw_writew(0x8a0a, IOMEM(0xe605810c));       /* USBCR2 */
-
-	/* KEYSC @ CN31 */
-	gpio_request(GPIO_FN_PORT60_KEYOUT5, NULL);
-	gpio_request(GPIO_FN_PORT61_KEYOUT4, NULL);
-	gpio_request(GPIO_FN_PORT62_KEYOUT3, NULL);
-	gpio_request(GPIO_FN_PORT63_KEYOUT2, NULL);
-	gpio_request(GPIO_FN_PORT64_KEYOUT1, NULL);
-	gpio_request(GPIO_FN_PORT65_KEYOUT0, NULL);
-	gpio_request(GPIO_FN_PORT66_KEYIN0_PU, NULL);
-	gpio_request(GPIO_FN_PORT67_KEYIN1_PU, NULL);
-	gpio_request(GPIO_FN_PORT68_KEYIN2_PU, NULL);
-	gpio_request(GPIO_FN_PORT69_KEYIN3_PU, NULL);
-	gpio_request(GPIO_FN_PORT70_KEYIN4_PU, NULL);
-	gpio_request(GPIO_FN_PORT71_KEYIN5_PU, NULL);
-	gpio_request(GPIO_FN_PORT72_KEYIN6_PU, NULL);
-
-	/* SDHI0 */
-	gpio_request(GPIO_FN_SDHICLK0, NULL);
-	gpio_request(GPIO_FN_SDHICD0, NULL);
-	gpio_request(GPIO_FN_SDHID0_0, NULL);
-	gpio_request(GPIO_FN_SDHID0_1, NULL);
-	gpio_request(GPIO_FN_SDHID0_2, NULL);
-	gpio_request(GPIO_FN_SDHID0_3, NULL);
-	gpio_request(GPIO_FN_SDHICMD0, NULL);
-	gpio_request(GPIO_FN_SDHIWP0, NULL);
-	gpio_request_pullup(GPIO_SDHID0_D0);
-	gpio_request_pullup(GPIO_SDHID0_D1);
-	gpio_request_pullup(GPIO_SDHID0_D2);
-	gpio_request_pullup(GPIO_SDHID0_D3);
-	gpio_request_pullup(GPIO_SDHICMD0);
-
-	/* SDHI1 */
-	gpio_request(GPIO_FN_SDHICLK1, NULL);
-	gpio_request(GPIO_FN_SDHID1_0, NULL);
-	gpio_request(GPIO_FN_SDHID1_1, NULL);
-	gpio_request(GPIO_FN_SDHID1_2, NULL);
-	gpio_request(GPIO_FN_SDHID1_3, NULL);
-	gpio_request(GPIO_FN_SDHICMD1, NULL);
-	gpio_request_pullup(GPIO_SDHID1_D0);
-	gpio_request_pullup(GPIO_SDHID1_D1);
-	gpio_request_pullup(GPIO_SDHID1_D2);
-	gpio_request_pullup(GPIO_SDHID1_D3);
-	gpio_request_pullup(GPIO_SDHICMD1);
-
-	sh7377_add_standard_devices();
-
-	platform_add_devices(g4evm_devices, ARRAY_SIZE(g4evm_devices));
-}
-
-MACHINE_START(G4EVM, "g4evm")
-	.map_io		= sh7377_map_io,
-	.init_early	= sh7377_add_early_devices,
-	.init_irq	= sh7377_init_irq,
-	.handle_irq	= shmobile_handle_irq_intc,
-	.init_machine	= g4evm_init,
-	.init_late	= shmobile_init_late,
-	.timer		= &shmobile_timer,
-MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
index 0a43f31..f63f2ee 100644
--- a/arch/arm/mach-shmobile/board-kzm9g.c
+++ b/arch/arm/mach-shmobile/board-kzm9g.c
@@ -384,6 +384,8 @@ static struct regulator_consumer_supply fixed2v8_power_consumers[] =
 
 /* SDHI */
 static struct sh_mobile_sdhi_info sdhi0_info = {
+	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
+	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
 	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT,
 	.tmio_caps	= MMC_CAP_SD_HIGHSPEED,
 	.tmio_ocr_mask	= MMC_VDD_27_28 | MMC_VDD_28_29,
@@ -424,6 +426,8 @@ static struct platform_device sdhi0_device = {
 
 /* Micro SD */
 static struct sh_mobile_sdhi_info sdhi2_info = {
+	.dma_slave_tx	= SHDMA_SLAVE_SDHI2_TX,
+	.dma_slave_rx	= SHDMA_SLAVE_SDHI2_RX,
 	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT |
 			  TMIO_MMC_USE_GPIO_CD |
 			  TMIO_MMC_WRPROTECT_DISABLE,
@@ -557,7 +561,15 @@ static struct i2c_board_info i2c0_devices[] = {
 	},
 	{
 		I2C_BOARD_INFO("r2025sd", 0x32),
-	}
+	},
+	{
+		I2C_BOARD_INFO("ak8975", 0x0c),
+		.irq = intcs_evt2irq(0x3380), /* IRQ28 */
+	},
+	{
+		I2C_BOARD_INFO("adxl34x", 0x1d),
+		.irq = intcs_evt2irq(0x3340), /* IRQ26 */
+	},
 };
 
 static struct i2c_board_info i2c1_devices[] = {
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 0c27c81..3f56e70 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -816,6 +816,8 @@ static struct platform_device usbhs1_device = {
 	.id	= 1,
 	.dev = {
 		.platform_data		= &usbhs1_private.info,
+		.dma_mask		= &usbhs1_device.dev.coherent_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
 	},
 	.num_resources	= ARRAY_SIZE(usbhs1_resources),
 	.resource	= usbhs1_resources,
@@ -860,76 +862,6 @@ static struct platform_device leds_device = {
 
 /* FSI */
 #define IRQ_FSI evt2irq(0x1840)
-static int __fsi_set_round_rate(struct clk *clk, long rate, int enable)
-{
-	int ret;
-
-	if (rate <= 0)
-		return 0;
-
-	if (!enable) {
-		clk_disable(clk);
-		return 0;
-	}
-
-	ret = clk_set_rate(clk, clk_round_rate(clk, rate));
-	if (ret < 0)
-		return ret;
-
-	return clk_enable(clk);
-}
-
-static int fsi_b_set_rate(struct device *dev, int rate, int enable)
-{
-	struct clk *fsib_clk;
-	struct clk *fdiv_clk = &sh7372_fsidivb_clk;
-	long fsib_rate = 0;
-	long fdiv_rate = 0;
-	int ackmd_bpfmd;
-	int ret;
-
-	/* clock start */
-	switch (rate) {
-	case 44100:
-		fsib_rate	= rate * 256;
-		ackmd_bpfmd	= SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
-		break;
-	case 48000:
-		fsib_rate	= 85428000; /* around 48kHz x 256 x 7 */
-		fdiv_rate	= rate * 256;
-		ackmd_bpfmd	= SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
-		break;
-	default:
-		pr_err("unsupported rate in FSI2 port B\n");
-		return -EINVAL;
-	}
-
-	/* FSI B setting */
-	fsib_clk = clk_get(dev, "ickb");
-	if (IS_ERR(fsib_clk))
-		return -EIO;
-
-	/* fsib */
-	ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable);
-	if (ret < 0)
-		goto fsi_set_rate_end;
-
-	/* FSI DIV */
-	ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable);
-	if (ret < 0) {
-		/* disable FSI B */
-		if (enable)
-			__fsi_set_round_rate(fsib_clk, fsib_rate, 0);
-		goto fsi_set_rate_end;
-	}
-
-	ret = ackmd_bpfmd;
-
-fsi_set_rate_end:
-	clk_put(fsib_clk);
-	return ret;
-}
-
 static struct sh_fsi_platform_info fsi_info = {
 	.port_a = {
 		.flags = SH_FSI_BRS_INV,
@@ -940,8 +872,8 @@ static struct sh_fsi_platform_info fsi_info = {
 		.flags = SH_FSI_BRS_INV	|
 			SH_FSI_BRM_INV	|
 			SH_FSI_LRS_INV	|
+			SH_FSI_CLK_CPG	|
 			SH_FSI_FMT_SPDIF,
-		.set_rate = fsi_b_set_rate,
 	}
 };
 
@@ -1018,7 +950,11 @@ static struct resource nand_flash_resources[] = {
 		.start	= 0xe6a30000,
 		.end	= 0xe6a3009b,
 		.flags	= IORESOURCE_MEM,
-	}
+	},
+	[1] = {
+		.start	= evt2irq(0x0d80), /* flstei: status error irq */
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static struct sh_flctl_platform_data nand_flash_data = {
@@ -1651,7 +1587,12 @@ static void __init mackerel_init(void)
 	pm_clk_add(&hdmi_lcdc_device.dev, "hdmi");
 }
 
-MACHINE_START(MACKEREL, "mackerel")
+static const char *mackerel_boards_compat_dt[] __initdata = {
+	"renesas,mackerel",
+	NULL,
+};
+
+DT_MACHINE_START(MACKEREL_DT, "mackerel")
 	.map_io		= sh7372_map_io,
 	.init_early	= sh7372_add_early_devices,
 	.init_irq	= sh7372_init_irq,
@@ -1659,4 +1600,5 @@ MACHINE_START(MACKEREL, "mackerel")
 	.init_machine	= mackerel_init,
 	.init_late	= sh7372_pm_init_late,
 	.timer		= &shmobile_timer,
+	.dt_compat  = mackerel_boards_compat_dt,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
index b8a7525..449f928 100644
--- a/arch/arm/mach-shmobile/board-marzen.c
+++ b/arch/arm/mach-shmobile/board-marzen.c
@@ -30,8 +30,14 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/smsc911x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/sh_hspi.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
+#include <linux/pm_runtime.h>
 #include <mach/hardware.h>
 #include <mach/r8a7779.h>
 #include <mach/common.h>
@@ -126,12 +132,201 @@ static struct platform_device thermal_device = {
 	.num_resources	= ARRAY_SIZE(thermal_resources),
 };
 
+/* HSPI */
+static struct resource hspi_resources[] = {
+	[0] = {
+		.start		= 0xFFFC7000,
+		.end		= 0xFFFC7018 - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device hspi_device = {
+	.name	= "sh-hspi",
+	.id	= 0,
+	.resource	= hspi_resources,
+	.num_resources	= ARRAY_SIZE(hspi_resources),
+};
+
+/* USB PHY */
+static struct resource usb_phy_resources[] = {
+	[0] = {
+		.start		= 0xffe70000,
+		.end		= 0xffe70900 - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= 0xfff70000,
+		.end		= 0xfff70900 - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device usb_phy_device = {
+	.name		= "rcar_usb_phy",
+	.resource	= usb_phy_resources,
+	.num_resources	= ARRAY_SIZE(usb_phy_resources),
+};
+
 static struct platform_device *marzen_devices[] __initdata = {
 	&eth_device,
 	&sdhi0_device,
 	&thermal_device,
+	&hspi_device,
+	&usb_phy_device,
 };
 
+/* USB */
+static struct usb_phy *phy;
+static int usb_power_on(struct platform_device *pdev)
+{
+	if (!phy)
+		return -EIO;
+
+	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 (!phy)
+		return;
+
+	usb_phy_shutdown(phy);
+
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+}
+
+static struct usb_ehci_pdata ehcix_pdata = {
+	.power_on	= usb_power_on,
+	.power_off	= usb_power_off,
+	.power_suspend	= usb_power_off,
+};
+
+static struct resource ehci0_resources[] = {
+	[0] = {
+		.start	= 0xffe70000,
+		.end	= 0xffe70400 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gic_spi(44),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device ehci0_device = {
+	.name	= "ehci-platform",
+	.id	= 0,
+	.dev	= {
+		.dma_mask		= &ehci0_device.dev.coherent_dma_mask,
+		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &ehcix_pdata,
+	},
+	.num_resources	= ARRAY_SIZE(ehci0_resources),
+	.resource	= ehci0_resources,
+};
+
+static struct resource ehci1_resources[] = {
+	[0] = {
+		.start	= 0xfff70000,
+		.end	= 0xfff70400 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gic_spi(45),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device ehci1_device = {
+	.name	= "ehci-platform",
+	.id	= 1,
+	.dev	= {
+		.dma_mask		= &ehci1_device.dev.coherent_dma_mask,
+		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &ehcix_pdata,
+	},
+	.num_resources	= ARRAY_SIZE(ehci1_resources),
+	.resource	= ehci1_resources,
+};
+
+static struct usb_ohci_pdata ohcix_pdata = {
+	.power_on	= usb_power_on,
+	.power_off	= usb_power_off,
+	.power_suspend	= usb_power_off,
+};
+
+static struct resource ohci0_resources[] = {
+	[0] = {
+		.start	= 0xffe70400,
+		.end	= 0xffe70800 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gic_spi(44),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device ohci0_device = {
+	.name	= "ohci-platform",
+	.id	= 0,
+	.dev	= {
+		.dma_mask		= &ohci0_device.dev.coherent_dma_mask,
+		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &ohcix_pdata,
+	},
+	.num_resources	= ARRAY_SIZE(ohci0_resources),
+	.resource	= ohci0_resources,
+};
+
+static struct resource ohci1_resources[] = {
+	[0] = {
+		.start	= 0xfff70400,
+		.end	= 0xfff70800 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gic_spi(45),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device ohci1_device = {
+	.name	= "ohci-platform",
+	.id	= 1,
+	.dev	= {
+		.dma_mask		= &ohci1_device.dev.coherent_dma_mask,
+		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &ohcix_pdata,
+	},
+	.num_resources	= ARRAY_SIZE(ohci1_resources),
+	.resource	= ohci1_resources,
+};
+
+static struct platform_device *marzen_late_devices[] __initdata = {
+	&ehci0_device,
+	&ehci1_device,
+	&ohci0_device,
+	&ohci1_device,
+};
+
+void __init marzen_init_late(void)
+{
+	/* get usb phy */
+	phy = usb_get_phy(USB_PHY_TYPE_USB2);
+
+	shmobile_init_late();
+	platform_add_devices(marzen_late_devices,
+			     ARRAY_SIZE(marzen_late_devices));
+}
+
 static void __init marzen_init(void)
 {
 	regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
@@ -163,6 +358,20 @@ static void __init marzen_init(void)
 	gpio_request(GPIO_FN_SD0_CD, NULL);
 	gpio_request(GPIO_FN_SD0_WP, NULL);
 
+	/* HSPI 0 */
+	gpio_request(GPIO_FN_HSPI_CLK0,	NULL);
+	gpio_request(GPIO_FN_HSPI_CS0,	NULL);
+	gpio_request(GPIO_FN_HSPI_TX0,	NULL);
+	gpio_request(GPIO_FN_HSPI_RX0,	NULL);
+
+	/* USB (CN21) */
+	gpio_request(GPIO_FN_USB_OVC0, NULL);
+	gpio_request(GPIO_FN_USB_OVC1, NULL);
+	gpio_request(GPIO_FN_USB_OVC2, NULL);
+
+	/* USB (CN22) */
+	gpio_request(GPIO_FN_USB_PENC2, NULL);
+
 	r8a7779_add_standard_devices();
 	platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
 }
@@ -175,6 +384,6 @@ MACHINE_START(MARZEN, "marzen")
 	.init_irq	= r8a7779_init_irq,
 	.handle_irq	= gic_handle_irq,
 	.init_machine	= marzen_init,
-	.init_late	= shmobile_init_late,
+	.init_late	= marzen_init_late,
 	.timer		= &shmobile_timer,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
index 6729e00..eac49d5 100644
--- a/arch/arm/mach-shmobile/clock-r8a7740.c
+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
@@ -65,6 +65,9 @@
 #define SMSTPCR3	IOMEM(0xe615013c)
 #define SMSTPCR4	IOMEM(0xe6150140)
 
+#define FSIDIVA		IOMEM(0xFE1F8000)
+#define FSIDIVB		IOMEM(0xFE1F8008)
+
 /* Fixed 32 KHz root clock from EXTALR pin */
 static struct clk extalr_clk = {
 	.rate	= 32768,
@@ -188,6 +191,22 @@ static struct clk pllc1_div2_clk = {
 };
 
 /* USB clock */
+/*
+ * USBCKCR is controlling usb24 clock
+ * bit[7] : parent clock
+ * bit[6] : clock divide rate
+ * And this bit[7] is used as a "usb24s" from other devices.
+ * (Video clock / Sub clock / SPU clock)
+ * You can controll this clock as a below.
+ *
+ * struct clk *usb24	= clk_get(dev,  "usb24");
+ * struct clk *usb24s	= clk_get(NULL, "usb24s");
+ * struct clk *system	= clk_get(NULL, "system_clk");
+ * int rate = clk_get_rate(system);
+ *
+ * clk_set_parent(usb24s, system);  // for bit[7]
+ * clk_set_rate(usb24, rate / 2);   // for bit[6]
+ */
 static struct clk *usb24s_parents[] = {
 	[0] = &system_clk,
 	[1] = &extal2_clk
@@ -427,6 +446,14 @@ static struct clk *late_main_clks[] = {
 	&hdmi2_clk,
 };
 
+/* FSI DIV */
+enum { FSIDIV_A, FSIDIV_B, FSIDIV_REPARENT_NR };
+
+static struct clk fsidivs[] = {
+	[FSIDIV_A] = SH_CLK_FSIDIV(FSIDIVA, &div6_reparent_clks[DIV6_FSIA]),
+	[FSIDIV_B] = SH_CLK_FSIDIV(FSIDIVB, &div6_reparent_clks[DIV6_FSIB]),
+};
+
 /* MSTP */
 enum {
 	DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP,
@@ -596,6 +623,10 @@ static struct clk_lookup lookups[] = {
 
 	CLKDEV_ICK_ID("icka", "sh_fsi2",	&div6_reparent_clks[DIV6_FSIA]),
 	CLKDEV_ICK_ID("ickb", "sh_fsi2",	&div6_reparent_clks[DIV6_FSIB]),
+	CLKDEV_ICK_ID("diva", "sh_fsi2",	&fsidivs[FSIDIV_A]),
+	CLKDEV_ICK_ID("divb", "sh_fsi2",	&fsidivs[FSIDIV_B]),
+	CLKDEV_ICK_ID("xcka", "sh_fsi2",	&fsiack_clk),
+	CLKDEV_ICK_ID("xckb", "sh_fsi2",	&fsibck_clk),
 };
 
 void __init r8a7740_clock_init(u8 md_ck)
@@ -641,6 +672,9 @@ void __init r8a7740_clock_init(u8 md_ck)
 	for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
 		ret = clk_register(late_main_clks[k]);
 
+	if (!ret)
+		ret = sh_clk_fsidiv_register(fsidivs, FSIDIV_REPARENT_NR);
+
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
 	if (!ret)
diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c
index 37b2a31..c019609 100644
--- a/arch/arm/mach-shmobile/clock-r8a7779.c
+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
@@ -87,8 +87,11 @@ static struct clk div4_clks[DIV4_NR] = {
 };
 
 enum { MSTP323, MSTP322, MSTP321, MSTP320,
-	MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
+	MSTP101, MSTP100,
+	MSTP030,
+	MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
 	MSTP016, MSTP015, MSTP014,
+	MSTP007,
 	MSTP_NR };
 
 static struct clk mstp_clks[MSTP_NR] = {
@@ -96,6 +99,12 @@ static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP322] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 22, 0), /* SDHI1 */
 	[MSTP321] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 21, 0), /* SDHI2 */
 	[MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 20, 0), /* SDHI3 */
+	[MSTP101] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1,  1, 0), /* USB2 */
+	[MSTP100] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1,  0, 0), /* USB0/1 */
+	[MSTP030] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 30, 0), /* I2C0 */
+	[MSTP029] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 29, 0), /* I2C1 */
+	[MSTP028] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 28, 0), /* I2C2 */
+	[MSTP027] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 27, 0), /* I2C3 */
 	[MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0), /* SCIF0 */
 	[MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0), /* SCIF1 */
 	[MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0), /* SCIF2 */
@@ -105,6 +114,7 @@ static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP016] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 16, 0), /* TMU0 */
 	[MSTP015] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0), /* TMU1 */
 	[MSTP014] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 14, 0), /* TMU2 */
+	[MSTP007] = SH_CLK_MSTP32(&div4_clks[DIV4_S], MSTPCR0,  7, 0), /* HSPI */
 };
 
 static unsigned long mul4_recalc(struct clk *clk)
@@ -146,14 +156,25 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_CON_ID("peripheral_clk",	&div4_clks[DIV4_P]),
 
 	/* MSTP32 clocks */
+	CLKDEV_DEV_ID("ehci-platform.1", &mstp_clks[MSTP101]), /* USB EHCI port2 */
+	CLKDEV_DEV_ID("ohci-platform.1", &mstp_clks[MSTP101]), /* USB OHCI port2 */
+	CLKDEV_DEV_ID("ehci-platform.0", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */
+	CLKDEV_DEV_ID("ohci-platform.0", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */
 	CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP016]), /* TMU00 */
 	CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP016]), /* TMU01 */
+	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 */
+	CLKDEV_DEV_ID("i2c-rcar.3", &mstp_clks[MSTP027]), /* I2C3 */
 	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
 	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
 	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
 	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP023]), /* SCIF3 */
 	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */
 	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */
+	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("sh_mobile_sdhi.0", &mstp_clks[MSTP323]), /* SDHI0 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
diff --git a/arch/arm/mach-shmobile/clock-sh7367.c b/arch/arm/mach-shmobile/clock-sh7367.c
deleted file mode 100644
index ef0a95e..0000000
--- a/arch/arm/mach-shmobile/clock-sh7367.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * SH7367 clock framework support
- *
- * Copyright (C) 2010  Magnus Damm
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/sh_clk.h>
-#include <linux/clkdev.h>
-#include <mach/common.h>
-
-/* SH7367 registers */
-#define RTFRQCR    IOMEM(0xe6150000)
-#define SYFRQCR    IOMEM(0xe6150004)
-#define CMFRQCR    IOMEM(0xe61500E0)
-#define VCLKCR1    IOMEM(0xe6150008)
-#define VCLKCR2    IOMEM(0xe615000C)
-#define VCLKCR3    IOMEM(0xe615001C)
-#define SCLKACR    IOMEM(0xe6150010)
-#define SCLKBCR    IOMEM(0xe6150014)
-#define SUBUSBCKCR IOMEM(0xe6158080)
-#define SPUCKCR    IOMEM(0xe6150084)
-#define MSUCKCR    IOMEM(0xe6150088)
-#define MVI3CKCR   IOMEM(0xe6150090)
-#define VOUCKCR    IOMEM(0xe6150094)
-#define MFCK1CR    IOMEM(0xe6150098)
-#define MFCK2CR    IOMEM(0xe615009C)
-#define PLLC1CR    IOMEM(0xe6150028)
-#define PLLC2CR    IOMEM(0xe615002C)
-#define RTMSTPCR0  IOMEM(0xe6158030)
-#define RTMSTPCR2  IOMEM(0xe6158038)
-#define SYMSTPCR0  IOMEM(0xe6158040)
-#define SYMSTPCR2  IOMEM(0xe6158048)
-#define CMMSTPCR0  IOMEM(0xe615804c)
-
-/* Fixed 32 KHz root clock from EXTALR pin */
-static struct clk r_clk = {
-	.rate           = 32768,
-};
-
-/*
- * 26MHz default rate for the EXTALB1 root input clock.
- * If needed, reset this with clk_set_rate() from the platform code.
- */
-struct clk sh7367_extalb1_clk = {
-	.rate		= 26666666,
-};
-
-/*
- * 48MHz default rate for the EXTAL2 root input clock.
- * If needed, reset this with clk_set_rate() from the platform code.
- */
-struct clk sh7367_extal2_clk = {
-	.rate		= 48000000,
-};
-
-/* A fixed divide-by-2 block */
-static unsigned long div2_recalc(struct clk *clk)
-{
-	return clk->parent->rate / 2;
-}
-
-static struct sh_clk_ops div2_clk_ops = {
-	.recalc		= div2_recalc,
-};
-
-/* Divide extalb1 by two */
-static struct clk extalb1_div2_clk = {
-	.ops		= &div2_clk_ops,
-	.parent		= &sh7367_extalb1_clk,
-};
-
-/* Divide extal2 by two */
-static struct clk extal2_div2_clk = {
-	.ops		= &div2_clk_ops,
-	.parent		= &sh7367_extal2_clk,
-};
-
-/* PLLC1 */
-static unsigned long pllc1_recalc(struct clk *clk)
-{
-	unsigned long mult = 1;
-
-	if (__raw_readl(PLLC1CR) & (1 << 14))
-		mult = (((__raw_readl(RTFRQCR) >> 24) & 0x3f) + 1) * 2;
-
-	return clk->parent->rate * mult;
-}
-
-static struct sh_clk_ops pllc1_clk_ops = {
-	.recalc		= pllc1_recalc,
-};
-
-static struct clk pllc1_clk = {
-	.ops		= &pllc1_clk_ops,
-	.flags		= CLK_ENABLE_ON_INIT,
-	.parent		= &extalb1_div2_clk,
-};
-
-/* Divide PLLC1 by two */
-static struct clk pllc1_div2_clk = {
-	.ops		= &div2_clk_ops,
-	.parent		= &pllc1_clk,
-};
-
-/* PLLC2 */
-static unsigned long pllc2_recalc(struct clk *clk)
-{
-	unsigned long mult = 1;
-
-	if (__raw_readl(PLLC2CR) & (1 << 31))
-		mult = (((__raw_readl(PLLC2CR) >> 24) & 0x3f) + 1) * 2;
-
-	return clk->parent->rate * mult;
-}
-
-static struct sh_clk_ops pllc2_clk_ops = {
-	.recalc		= pllc2_recalc,
-};
-
-static struct clk pllc2_clk = {
-	.ops		= &pllc2_clk_ops,
-	.flags		= CLK_ENABLE_ON_INIT,
-	.parent		= &extalb1_div2_clk,
-};
-
-static struct clk *main_clks[] = {
-	&r_clk,
-	&sh7367_extalb1_clk,
-	&sh7367_extal2_clk,
-	&extalb1_div2_clk,
-	&extal2_div2_clk,
-	&pllc1_clk,
-	&pllc1_div2_clk,
-	&pllc2_clk,
-};
-
-static void div4_kick(struct clk *clk)
-{
-	unsigned long value;
-
-	/* set KICK bit in SYFRQCR to update hardware setting */
-	value = __raw_readl(SYFRQCR);
-	value |= (1 << 31);
-	__raw_writel(value, SYFRQCR);
-}
-
-static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
-			  24, 32, 36, 48, 0, 72, 0, 0 };
-
-static struct clk_div_mult_table div4_div_mult_table = {
-	.divisors = divisors,
-	.nr_divisors = ARRAY_SIZE(divisors),
-};
-
-static struct clk_div4_table div4_table = {
-	.div_mult_table = &div4_div_mult_table,
-	.kick = div4_kick,
-};
-
-enum { DIV4_I, DIV4_G, DIV4_S, DIV4_B,
-       DIV4_ZX, DIV4_ZT, DIV4_Z, DIV4_ZD, DIV4_HP,
-       DIV4_ZS, DIV4_ZB, DIV4_ZB3, DIV4_CP, DIV4_NR };
-
-#define DIV4(_reg, _bit, _mask, _flags) \
-  SH_CLK_DIV4(&pllc1_clk, _reg, _bit, _mask, _flags)
-
-static struct clk div4_clks[DIV4_NR] = {
-	[DIV4_I] = DIV4(RTFRQCR, 20, 0x6fff, CLK_ENABLE_ON_INIT),
-	[DIV4_G] = DIV4(RTFRQCR, 16, 0x6fff, CLK_ENABLE_ON_INIT),
-	[DIV4_S] = DIV4(RTFRQCR, 12, 0x6fff, CLK_ENABLE_ON_INIT),
-	[DIV4_B] = DIV4(RTFRQCR, 8, 0x6fff, CLK_ENABLE_ON_INIT),
-	[DIV4_ZX] = DIV4(SYFRQCR, 20, 0x6fff, 0),
-	[DIV4_ZT] = DIV4(SYFRQCR, 16, 0x6fff, 0),
-	[DIV4_Z] = DIV4(SYFRQCR, 12, 0x6fff, 0),
-	[DIV4_ZD] = DIV4(SYFRQCR, 8, 0x6fff, 0),
-	[DIV4_HP] = DIV4(SYFRQCR, 4, 0x6fff, 0),
-	[DIV4_ZS] = DIV4(CMFRQCR, 12, 0x6fff, 0),
-	[DIV4_ZB] = DIV4(CMFRQCR, 8, 0x6fff, 0),
-	[DIV4_ZB3] = DIV4(CMFRQCR, 4, 0x6fff, 0),
-	[DIV4_CP] = DIV4(CMFRQCR, 0, 0x6fff, 0),
-};
-
-enum { DIV6_SUB, DIV6_SIUA, DIV6_SIUB, DIV6_MSU, DIV6_SPU,
-       DIV6_MVI3, DIV6_MF1, DIV6_MF2,
-       DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_VOU,
-       DIV6_NR };
-
-static struct clk div6_clks[DIV6_NR] = {
-	[DIV6_SUB] = SH_CLK_DIV6(&sh7367_extal2_clk, SUBUSBCKCR, 0),
-	[DIV6_SIUA] = SH_CLK_DIV6(&pllc1_div2_clk, SCLKACR, 0),
-	[DIV6_SIUB] = SH_CLK_DIV6(&pllc1_div2_clk, SCLKBCR, 0),
-	[DIV6_MSU] = SH_CLK_DIV6(&pllc1_div2_clk, MSUCKCR, 0),
-	[DIV6_SPU] = SH_CLK_DIV6(&pllc1_div2_clk, SPUCKCR, 0),
-	[DIV6_MVI3] = SH_CLK_DIV6(&pllc1_div2_clk, MVI3CKCR, 0),
-	[DIV6_MF1] = SH_CLK_DIV6(&pllc1_div2_clk, MFCK1CR, 0),
-	[DIV6_MF2] = SH_CLK_DIV6(&pllc1_div2_clk, MFCK2CR, 0),
-	[DIV6_VCK1] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR1, 0),
-	[DIV6_VCK2] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR2, 0),
-	[DIV6_VCK3] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR3, 0),
-	[DIV6_VOU] = SH_CLK_DIV6(&pllc1_div2_clk, VOUCKCR, 0),
-};
-
-enum { RTMSTP001,
-       RTMSTP231, RTMSTP230, RTMSTP229, RTMSTP228, RTMSTP226,
-       RTMSTP216, RTMSTP206, RTMSTP205, RTMSTP201,
-       SYMSTP023, SYMSTP007, SYMSTP006, SYMSTP004,
-       SYMSTP003, SYMSTP002, SYMSTP001, SYMSTP000,
-       SYMSTP231, SYMSTP229, SYMSTP225, SYMSTP223, SYMSTP222,
-       SYMSTP215, SYMSTP214, SYMSTP213, SYMSTP211,
-       CMMSTP003,
-       MSTP_NR };
-
-#define MSTP(_parent, _reg, _bit, _flags) \
-  SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
-
-static struct clk mstp_clks[MSTP_NR] = {
-	[RTMSTP001] = MSTP(&div6_clks[DIV6_SUB], RTMSTPCR0, 1, 0), /* IIC2 */
-	[RTMSTP231] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 31, 0), /* VEU3 */
-	[RTMSTP230] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 30, 0), /* VEU2 */
-	[RTMSTP229] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 29, 0), /* VEU1 */
-	[RTMSTP228] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 28, 0), /* VEU0 */
-	[RTMSTP226] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 26, 0), /* VEU2H */
-	[RTMSTP216] = MSTP(&div6_clks[DIV6_SUB], RTMSTPCR2, 16, 0), /* IIC0 */
-	[RTMSTP206] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 6, 0), /* JPU */
-	[RTMSTP205] = MSTP(&div6_clks[DIV6_VOU], RTMSTPCR2, 5, 0), /* VOU */
-	[RTMSTP201] = MSTP(&div4_clks[DIV4_B], RTMSTPCR2, 1, 0), /* VPU */
-	[SYMSTP023] = MSTP(&div6_clks[DIV6_SPU], SYMSTPCR0, 23, 0), /* SPU1 */
-	[SYMSTP007] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 7, 0), /* SCIFA5 */
-	[SYMSTP006] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 6, 0), /* SCIFB */
-	[SYMSTP004] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 4, 0), /* SCIFA0 */
-	[SYMSTP003] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 3, 0), /* SCIFA1 */
-	[SYMSTP002] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 2, 0), /* SCIFA2 */
-	[SYMSTP001] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 1, 0), /* SCIFA3 */
-	[SYMSTP000] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR0, 0, 0), /* SCIFA4 */
-	[SYMSTP231] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 31, 0), /* SIU */
-	[SYMSTP229] = MSTP(&r_clk, SYMSTPCR2, 29, 0), /* CMT10 */
-	[SYMSTP225] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 25, 0), /* IRDA */
-	[SYMSTP223] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 23, 0), /* IIC1 */
-	[SYMSTP222] = MSTP(&div6_clks[DIV6_SUB], SYMSTPCR2, 22, 0), /* USBHS */
-	[SYMSTP215] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 15, 0), /* FLCTL */
-	[SYMSTP214] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 14, 0), /* SDHI0 */
-	[SYMSTP213] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 13, 0), /* SDHI1 */
-	[SYMSTP211] = MSTP(&div4_clks[DIV4_HP], SYMSTPCR2, 11, 0), /* SDHI2 */
-	[CMMSTP003] = MSTP(&r_clk, CMMSTPCR0, 3, 0), /* KEYSC */
-};
-
-static struct clk_lookup lookups[] = {
-	/* main clocks */
-	CLKDEV_CON_ID("r_clk", &r_clk),
-	CLKDEV_CON_ID("extalb1", &sh7367_extalb1_clk),
-	CLKDEV_CON_ID("extal2", &sh7367_extal2_clk),
-	CLKDEV_CON_ID("extalb1_div2_clk", &extalb1_div2_clk),
-	CLKDEV_CON_ID("extal2_div2_clk", &extal2_div2_clk),
-	CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
-	CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
-	CLKDEV_CON_ID("pllc2_clk", &pllc2_clk),
-
-	/* DIV4 clocks */
-	CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
-	CLKDEV_CON_ID("g_clk", &div4_clks[DIV4_G]),
-	CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]),
-	CLKDEV_CON_ID("zx_clk", &div4_clks[DIV4_ZX]),
-	CLKDEV_CON_ID("zt_clk", &div4_clks[DIV4_ZT]),
-	CLKDEV_CON_ID("z_clk", &div4_clks[DIV4_Z]),
-	CLKDEV_CON_ID("zd_clk", &div4_clks[DIV4_ZD]),
-	CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]),
-	CLKDEV_CON_ID("zs_clk", &div4_clks[DIV4_ZS]),
-	CLKDEV_CON_ID("zb_clk", &div4_clks[DIV4_ZB]),
-	CLKDEV_CON_ID("zb3_clk", &div4_clks[DIV4_ZB3]),
-	CLKDEV_CON_ID("cp_clk", &div4_clks[DIV4_CP]),
-
-	/* DIV6 clocks */
-	CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
-	CLKDEV_CON_ID("siua_clk", &div6_clks[DIV6_SIUA]),
-	CLKDEV_CON_ID("siub_clk", &div6_clks[DIV6_SIUB]),
-	CLKDEV_CON_ID("msu_clk", &div6_clks[DIV6_MSU]),
-	CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]),
-	CLKDEV_CON_ID("mvi3_clk", &div6_clks[DIV6_MVI3]),
-	CLKDEV_CON_ID("mf1_clk", &div6_clks[DIV6_MF1]),
-	CLKDEV_CON_ID("mf2_clk", &div6_clks[DIV6_MF2]),
-	CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]),
-	CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]),
-	CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
-	CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]),
-
-	/* MSTP32 clocks */
-	CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[RTMSTP001]), /* IIC2 */
-	CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[RTMSTP231]), /* VEU3 */
-	CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[RTMSTP230]), /* VEU2 */
-	CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[RTMSTP229]), /* VEU1 */
-	CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[RTMSTP228]), /* VEU0 */
-	CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[RTMSTP226]), /* VEU2H */
-	CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[RTMSTP216]), /* IIC0 */
-	CLKDEV_DEV_ID("uio_pdrv_genirq.6", &mstp_clks[RTMSTP206]), /* JPU */
-	CLKDEV_DEV_ID("sh-vou", &mstp_clks[RTMSTP205]), /* VOU */
-	CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[RTMSTP201]), /* VPU */
-	CLKDEV_DEV_ID("uio_pdrv_genirq.7", &mstp_clks[SYMSTP023]), /* SPU1 */
-	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[SYMSTP007]), /* SCIFA5 */
-	CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[SYMSTP006]), /* SCIFB */
-	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[SYMSTP004]), /* SCIFA0 */
-	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[SYMSTP003]), /* SCIFA1 */
-	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[SYMSTP002]), /* SCIFA2 */
-	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[SYMSTP001]), /* SCIFA3 */
-	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[SYMSTP000]), /* SCIFA4 */
-	CLKDEV_DEV_ID("sh_siu", &mstp_clks[SYMSTP231]), /* SIU */
-	CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[SYMSTP229]), /* CMT10 */
-	CLKDEV_DEV_ID("sh_irda", &mstp_clks[SYMSTP225]), /* IRDA */
-	CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[SYMSTP223]), /* IIC1 */
-	CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[SYMSTP222]), /* USBHS */
-	CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[SYMSTP222]), /* USBHS */
-	CLKDEV_DEV_ID("sh_flctl", &mstp_clks[SYMSTP215]), /* FLCTL */
-	CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[SYMSTP214]), /* SDHI0 */
-	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[SYMSTP213]), /* SDHI1 */
-	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[SYMSTP211]), /* SDHI2 */
-	CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[CMMSTP003]), /* KEYSC */
-};
-
-void __init sh7367_clock_init(void)
-{
-	int k, ret = 0;
-
-	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
-		ret = clk_register(main_clks[k]);
-
-	if (!ret)
-		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
-
-	if (!ret)
-		ret = sh_clk_div6_register(div6_clks, DIV6_NR);
-
-	if (!ret)
-		ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
-
-	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
-	if (!ret)
-		shmobile_clk_init();
-	else
-		panic("failed to setup sh7367 clocks\n");
-}
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
index 430a90f..3ca6757b 100644
--- a/arch/arm/mach-shmobile/clock-sh7372.c
+++ b/arch/arm/mach-shmobile/clock-sh7372.c
@@ -295,10 +295,10 @@ struct clk sh7372_pllc2_clk = {
 };
 
 /* External input clock (pin name: FSIACK/FSIBCK ) */
-struct clk sh7372_fsiack_clk = {
+static struct clk fsiack_clk = {
 };
 
-struct clk sh7372_fsibck_clk = {
+static struct clk fsibck_clk = {
 };
 
 static struct clk *main_clks[] = {
@@ -314,8 +314,8 @@ static struct clk *main_clks[] = {
 	&pllc1_clk,
 	&pllc1_div2_clk,
 	&sh7372_pllc2_clk,
-	&sh7372_fsiack_clk,
-	&sh7372_fsibck_clk,
+	&fsiack_clk,
+	&fsibck_clk,
 };
 
 static void div4_kick(struct clk *clk)
@@ -399,14 +399,14 @@ static struct clk *hdmi_parent[] = {
 static struct clk *fsiackcr_parent[] = {
 	[0] = &pllc1_div2_clk,
 	[1] = &sh7372_pllc2_clk,
-	[2] = &sh7372_fsiack_clk, /* external input for FSI A */
+	[2] = &fsiack_clk, /* external input for FSI A */
 	[3] = NULL,	/* setting prohibited */
 };
 
 static struct clk *fsibckcr_parent[] = {
 	[0] = &pllc1_div2_clk,
 	[1] = &sh7372_pllc2_clk,
-	[2] = &sh7372_fsibck_clk, /* external input for FSI B */
+	[2] = &fsibck_clk, /* external input for FSI B */
 	[3] = NULL,	/* setting prohibited */
 };
 
@@ -420,87 +420,11 @@ static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
 };
 
 /* FSI DIV */
-static unsigned long fsidiv_recalc(struct clk *clk)
-{
-	unsigned long value;
-
-	value = __raw_readl(clk->mapping->base);
-
-	value >>= 16;
-	if (value < 2)
-		return 0;
-
-	return clk->parent->rate / value;
-}
-
-static long fsidiv_round_rate(struct clk *clk, unsigned long rate)
-{
-	return clk_rate_div_range_round(clk, 2, 0xffff, rate);
-}
-
-static void fsidiv_disable(struct clk *clk)
-{
-	__raw_writel(0, clk->mapping->base);
-}
-
-static int fsidiv_enable(struct clk *clk)
-{
-	unsigned long value;
-
-	value  = __raw_readl(clk->mapping->base) >> 16;
-	if (value < 2)
-		return -EIO;
-
-	__raw_writel((value << 16) | 0x3, clk->mapping->base);
-
-	return 0;
-}
+enum { FSIDIV_A, FSIDIV_B, FSIDIV_REPARENT_NR };
 
-static int fsidiv_set_rate(struct clk *clk, unsigned long rate)
-{
-	int idx;
-
-	idx = (clk->parent->rate / rate) & 0xffff;
-	if (idx < 2)
-		return -EINVAL;
-
-	__raw_writel(idx << 16, clk->mapping->base);
-	return 0;
-}
-
-static struct sh_clk_ops fsidiv_clk_ops = {
-	.recalc		= fsidiv_recalc,
-	.round_rate	= fsidiv_round_rate,
-	.set_rate	= fsidiv_set_rate,
-	.enable		= fsidiv_enable,
-	.disable	= fsidiv_disable,
-};
-
-static struct clk_mapping fsidiva_clk_mapping = {
-	.phys	= FSIDIVA,
-	.len	= 8,
-};
-
-struct clk sh7372_fsidiva_clk = {
-	.ops		= &fsidiv_clk_ops,
-	.parent		= &div6_reparent_clks[DIV6_FSIA], /* late install */
-	.mapping	= &fsidiva_clk_mapping,
-};
-
-static struct clk_mapping fsidivb_clk_mapping = {
-	.phys	= FSIDIVB,
-	.len	= 8,
-};
-
-struct clk sh7372_fsidivb_clk = {
-	.ops		= &fsidiv_clk_ops,
-	.parent		= &div6_reparent_clks[DIV6_FSIB],  /* late install */
-	.mapping	= &fsidivb_clk_mapping,
-};
-
-static struct clk *late_main_clks[] = {
-	&sh7372_fsidiva_clk,
-	&sh7372_fsidivb_clk,
+static struct clk fsidivs[] = {
+	[FSIDIV_A] = SH_CLK_FSIDIV(FSIDIVA, &div6_reparent_clks[DIV6_FSIA]),
+	[FSIDIV_B] = SH_CLK_FSIDIV(FSIDIVB, &div6_reparent_clks[DIV6_FSIB]),
 };
 
 enum { MSTP001, MSTP000,
@@ -583,6 +507,8 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
 	CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
 	CLKDEV_CON_ID("pllc2_clk", &sh7372_pllc2_clk),
+	CLKDEV_CON_ID("fsiack", &fsiack_clk),
+	CLKDEV_CON_ID("fsibck", &fsibck_clk),
 
 	/* DIV4 clocks */
 	CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
@@ -678,6 +604,10 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]),
 	CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]),
 	CLKDEV_ICK_ID("spu2", "sh_fsi2", &mstp_clks[MSTP223]),
+	CLKDEV_ICK_ID("diva", "sh_fsi2", &fsidivs[FSIDIV_A]),
+	CLKDEV_ICK_ID("divb", "sh_fsi2", &fsidivs[FSIDIV_B]),
+	CLKDEV_ICK_ID("xcka", "sh_fsi2", &fsiack_clk),
+	CLKDEV_ICK_ID("xckb", "sh_fsi2", &fsibck_clk),
 };
 
 void __init sh7372_clock_init(void)
@@ -706,8 +636,8 @@ void __init sh7372_clock_init(void)
 	if (!ret)
 		ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
 
-	for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
-		ret = clk_register(late_main_clks[k]);
+	if (!ret)
+		ret = sh_clk_fsidiv_register(fsidivs, FSIDIV_REPARENT_NR);
 
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
diff --git a/arch/arm/mach-shmobile/clock-sh7377.c b/arch/arm/mach-shmobile/clock-sh7377.c
deleted file mode 100644
index b8480d1..0000000
--- a/arch/arm/mach-shmobile/clock-sh7377.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * SH7377 clock framework support
- *
- * Copyright (C) 2010 Magnus Damm
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/sh_clk.h>
-#include <linux/clkdev.h>
-#include <mach/common.h>
-
-/* SH7377 registers */
-#define RTFRQCR    IOMEM(0xe6150000)
-#define SYFRQCR    IOMEM(0xe6150004)
-#define CMFRQCR    IOMEM(0xe61500E0)
-#define VCLKCR1    IOMEM(0xe6150008)
-#define VCLKCR2    IOMEM(0xe615000C)
-#define VCLKCR3    IOMEM(0xe615001C)
-#define FMSICKCR   IOMEM(0xe6150010)
-#define FMSOCKCR   IOMEM(0xe6150014)
-#define FSICKCR    IOMEM(0xe6150018)
-#define PLLC1CR    IOMEM(0xe6150028)
-#define PLLC2CR    IOMEM(0xe615002C)
-#define SUBUSBCKCR IOMEM(0xe6150080)
-#define SPUCKCR    IOMEM(0xe6150084)
-#define MSUCKCR    IOMEM(0xe6150088)
-#define MVI3CKCR   IOMEM(0xe6150090)
-#define HDMICKCR   IOMEM(0xe6150094)
-#define MFCK1CR    IOMEM(0xe6150098)
-#define MFCK2CR    IOMEM(0xe615009C)
-#define DSITCKCR   IOMEM(0xe6150060)
-#define DSIPCKCR   IOMEM(0xe6150064)
-#define SMSTPCR0   IOMEM(0xe6150130)
-#define SMSTPCR1   IOMEM(0xe6150134)
-#define SMSTPCR2   IOMEM(0xe6150138)
-#define SMSTPCR3   IOMEM(0xe615013C)
-#define SMSTPCR4   IOMEM(0xe6150140)
-
-/* Fixed 32 KHz root clock from EXTALR pin */
-static struct clk r_clk = {
-	.rate           = 32768,
-};
-
-/*
- * 26MHz default rate for the EXTALC1 root input clock.
- * If needed, reset this with clk_set_rate() from the platform code.
- */
-struct clk sh7377_extalc1_clk = {
-	.rate		= 26666666,
-};
-
-/*
- * 48MHz default rate for the EXTAL2 root input clock.
- * If needed, reset this with clk_set_rate() from the platform code.
- */
-struct clk sh7377_extal2_clk = {
-	.rate		= 48000000,
-};
-
-/* A fixed divide-by-2 block */
-static unsigned long div2_recalc(struct clk *clk)
-{
-	return clk->parent->rate / 2;
-}
-
-static struct sh_clk_ops div2_clk_ops = {
-	.recalc		= div2_recalc,
-};
-
-/* Divide extalc1 by two */
-static struct clk extalc1_div2_clk = {
-	.ops		= &div2_clk_ops,
-	.parent		= &sh7377_extalc1_clk,
-};
-
-/* Divide extal2 by two */
-static struct clk extal2_div2_clk = {
-	.ops		= &div2_clk_ops,
-	.parent		= &sh7377_extal2_clk,
-};
-
-/* Divide extal2 by four */
-static struct clk extal2_div4_clk = {
-	.ops		= &div2_clk_ops,
-	.parent		= &extal2_div2_clk,
-};
-
-/* PLLC1 */
-static unsigned long pllc1_recalc(struct clk *clk)
-{
-	unsigned long mult = 1;
-
-	if (__raw_readl(PLLC1CR) & (1 << 14))
-		mult = (((__raw_readl(RTFRQCR) >> 24) & 0x3f) + 1) * 2;
-
-	return clk->parent->rate * mult;
-}
-
-static struct sh_clk_ops pllc1_clk_ops = {
-	.recalc		= pllc1_recalc,
-};
-
-static struct clk pllc1_clk = {
-	.ops		= &pllc1_clk_ops,
-	.flags		= CLK_ENABLE_ON_INIT,
-	.parent		= &extalc1_div2_clk,
-};
-
-/* Divide PLLC1 by two */
-static struct clk pllc1_div2_clk = {
-	.ops		= &div2_clk_ops,
-	.parent		= &pllc1_clk,
-};
-
-/* PLLC2 */
-static unsigned long pllc2_recalc(struct clk *clk)
-{
-	unsigned long mult = 1;
-
-	if (__raw_readl(PLLC2CR) & (1 << 31))
-		mult = (((__raw_readl(PLLC2CR) >> 24) & 0x3f) + 1) * 2;
-
-	return clk->parent->rate * mult;
-}
-
-static struct sh_clk_ops pllc2_clk_ops = {
-	.recalc		= pllc2_recalc,
-};
-
-static struct clk pllc2_clk = {
-	.ops		= &pllc2_clk_ops,
-	.flags		= CLK_ENABLE_ON_INIT,
-	.parent		= &extalc1_div2_clk,
-};
-
-static struct clk *main_clks[] = {
-	&r_clk,
-	&sh7377_extalc1_clk,
-	&sh7377_extal2_clk,
-	&extalc1_div2_clk,
-	&extal2_div2_clk,
-	&extal2_div4_clk,
-	&pllc1_clk,
-	&pllc1_div2_clk,
-	&pllc2_clk,
-};
-
-static void div4_kick(struct clk *clk)
-{
-	unsigned long value;
-
-	/* set KICK bit in SYFRQCR to update hardware setting */
-	value = __raw_readl(SYFRQCR);
-	value |= (1 << 31);
-	__raw_writel(value, SYFRQCR);
-}
-
-static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
-			  24, 32, 36, 48, 0, 72, 96, 0 };
-
-static struct clk_div_mult_table div4_div_mult_table = {
-	.divisors = divisors,
-	.nr_divisors = ARRAY_SIZE(divisors),
-};
-
-static struct clk_div4_table div4_table = {
-	.div_mult_table = &div4_div_mult_table,
-	.kick = div4_kick,
-};
-
-enum { DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_CSIR,
-       DIV4_ZTR, DIV4_ZT, DIV4_Z, DIV4_HP,
-       DIV4_ZS, DIV4_ZB, DIV4_ZB3, DIV4_CP, DIV4_NR };
-
-#define DIV4(_reg, _bit, _mask, _flags) \
-  SH_CLK_DIV4(&pllc1_clk, _reg, _bit, _mask, _flags)
-
-static struct clk div4_clks[DIV4_NR] = {
-	[DIV4_I] = DIV4(RTFRQCR, 20, 0x6fff, CLK_ENABLE_ON_INIT),
-	[DIV4_ZG] = DIV4(RTFRQCR, 16, 0x6fff, CLK_ENABLE_ON_INIT),
-	[DIV4_B] = DIV4(RTFRQCR, 8, 0x6fff, CLK_ENABLE_ON_INIT),
-	[DIV4_M1] = DIV4(RTFRQCR, 4, 0x6fff, CLK_ENABLE_ON_INIT),
-	[DIV4_CSIR] = DIV4(RTFRQCR, 0, 0x6fff, 0),
-	[DIV4_ZTR] = DIV4(SYFRQCR, 20, 0x6fff, 0),
-	[DIV4_ZT] = DIV4(SYFRQCR, 16, 0x6fff, 0),
-	[DIV4_Z] = DIV4(SYFRQCR, 12, 0x6fff, 0),
-	[DIV4_HP] = DIV4(SYFRQCR, 4, 0x6fff, 0),
-	[DIV4_ZS] = DIV4(CMFRQCR, 12, 0x6fff, 0),
-	[DIV4_ZB] = DIV4(CMFRQCR, 8, 0x6fff, 0),
-	[DIV4_ZB3] = DIV4(CMFRQCR, 4, 0x6fff, 0),
-	[DIV4_CP] = DIV4(CMFRQCR, 0, 0x6fff, 0),
-};
-
-enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_FMSI, DIV6_FMSO,
-       DIV6_FSI, DIV6_SUB, DIV6_SPU, DIV6_MSU, DIV6_MVI3, DIV6_HDMI,
-       DIV6_MF1, DIV6_MF2, DIV6_DSIT, DIV6_DSIP,
-       DIV6_NR };
-
-static struct clk div6_clks[] = {
-	[DIV6_VCK1] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR1, 0),
-	[DIV6_VCK2] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR2, 0),
-	[DIV6_VCK3] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR3, 0),
-	[DIV6_FMSI] = SH_CLK_DIV6(&pllc1_div2_clk, FMSICKCR, 0),
-	[DIV6_FMSO] = SH_CLK_DIV6(&pllc1_div2_clk, FMSOCKCR, 0),
-	[DIV6_FSI] = SH_CLK_DIV6(&pllc1_div2_clk, FSICKCR, 0),
-	[DIV6_SUB] = SH_CLK_DIV6(&sh7377_extal2_clk, SUBUSBCKCR, 0),
-	[DIV6_SPU] = SH_CLK_DIV6(&pllc1_div2_clk, SPUCKCR, 0),
-	[DIV6_MSU] = SH_CLK_DIV6(&pllc1_div2_clk, MSUCKCR, 0),
-	[DIV6_MVI3] = SH_CLK_DIV6(&pllc1_div2_clk, MVI3CKCR, 0),
-	[DIV6_HDMI] = SH_CLK_DIV6(&pllc1_div2_clk, HDMICKCR, 0),
-	[DIV6_MF1] = SH_CLK_DIV6(&pllc1_div2_clk, MFCK1CR, 0),
-	[DIV6_MF2] = SH_CLK_DIV6(&pllc1_div2_clk, MFCK2CR, 0),
-	[DIV6_DSIT] = SH_CLK_DIV6(&pllc1_div2_clk, DSITCKCR, 0),
-	[DIV6_DSIP] = SH_CLK_DIV6(&pllc1_div2_clk, DSIPCKCR, 0),
-};
-
-enum { MSTP001,
-       MSTP131, MSTP130, MSTP129, MSTP128, MSTP116, MSTP106, MSTP101,
-       MSTP223, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
-       MSTP331, MSTP329, MSTP325, MSTP323, MSTP322,
-       MSTP315, MSTP314, MSTP313,
-       MSTP403,
-       MSTP_NR };
-
-#define MSTP(_parent, _reg, _bit, _flags) \
-  SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
-
-static struct clk mstp_clks[] = {
-	[MSTP001] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR0, 1, 0), /* IIC2 */
-	[MSTP131] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 31, 0), /* VEU3 */
-	[MSTP130] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 30, 0), /* VEU2 */
-	[MSTP129] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 29, 0), /* VEU1 */
-	[MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* VEU0 */
-	[MSTP116] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */
-	[MSTP106] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 6, 0), /* JPU */
-	[MSTP101] = MSTP(&div4_clks[DIV4_M1], SMSTPCR1, 1, 0), /* VPU */
-	[MSTP223] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR2, 23, 0), /* SPU2 */
-	[MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */
-	[MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */
-	[MSTP204] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */
-	[MSTP203] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 3, 0), /* SCIFA1 */
-	[MSTP202] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 2, 0), /* SCIFA2 */
-	[MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */
-	[MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
-	[MSTP331] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 31, 0), /* SCIFA6 */
-	[MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
-	[MSTP325] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 25, 0), /* IRDA */
-	[MSTP323] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
-	[MSTP322] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 22, 0), /* USB0 */
-	[MSTP315] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 15, 0), /* FLCTL */
-	[MSTP314] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
-	[MSTP313] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */
-	[MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
-};
-
-static struct clk_lookup lookups[] = {
-	/* main clocks */
-	CLKDEV_CON_ID("r_clk", &r_clk),
-	CLKDEV_CON_ID("extalc1", &sh7377_extalc1_clk),
-	CLKDEV_CON_ID("extal2", &sh7377_extal2_clk),
-	CLKDEV_CON_ID("extalc1_div2_clk", &extalc1_div2_clk),
-	CLKDEV_CON_ID("extal2_div2_clk", &extal2_div2_clk),
-	CLKDEV_CON_ID("extal2_div4_clk", &extal2_div4_clk),
-	CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
-	CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
-	CLKDEV_CON_ID("pllc2_clk", &pllc2_clk),
-
-	/* DIV4 clocks */
-	CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
-	CLKDEV_CON_ID("zg_clk", &div4_clks[DIV4_ZG]),
-	CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]),
-	CLKDEV_CON_ID("m1_clk", &div4_clks[DIV4_M1]),
-	CLKDEV_CON_ID("csir_clk", &div4_clks[DIV4_CSIR]),
-	CLKDEV_CON_ID("ztr_clk", &div4_clks[DIV4_ZTR]),
-	CLKDEV_CON_ID("zt_clk", &div4_clks[DIV4_ZT]),
-	CLKDEV_CON_ID("z_clk", &div4_clks[DIV4_Z]),
-	CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]),
-	CLKDEV_CON_ID("zs_clk", &div4_clks[DIV4_ZS]),
-	CLKDEV_CON_ID("zb_clk", &div4_clks[DIV4_ZB]),
-	CLKDEV_CON_ID("zb3_clk", &div4_clks[DIV4_ZB3]),
-	CLKDEV_CON_ID("cp_clk", &div4_clks[DIV4_CP]),
-
-	/* DIV6 clocks */
-	CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]),
-	CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]),
-	CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
-	CLKDEV_CON_ID("fmsi_clk", &div6_clks[DIV6_FMSI]),
-	CLKDEV_CON_ID("fmso_clk", &div6_clks[DIV6_FMSO]),
-	CLKDEV_CON_ID("fsi_clk", &div6_clks[DIV6_FSI]),
-	CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
-	CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]),
-	CLKDEV_CON_ID("msu_clk", &div6_clks[DIV6_MSU]),
-	CLKDEV_CON_ID("mvi3_clk", &div6_clks[DIV6_MVI3]),
-	CLKDEV_CON_ID("hdmi_clk", &div6_clks[DIV6_HDMI]),
-	CLKDEV_CON_ID("mf1_clk", &div6_clks[DIV6_MF1]),
-	CLKDEV_CON_ID("mf2_clk", &div6_clks[DIV6_MF2]),
-	CLKDEV_CON_ID("dsit_clk", &div6_clks[DIV6_DSIT]),
-	CLKDEV_CON_ID("dsip_clk", &div6_clks[DIV6_DSIP]),
-
-	/* MSTP32 clocks */
-	CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */
-	CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[MSTP131]), /* VEU3 */
-	CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[MSTP130]), /* VEU2 */
-	CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[MSTP129]), /* VEU1 */
-	CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[MSTP128]), /* VEU0 */
-	CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */
-	CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[MSTP106]), /* JPU */
-	CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[MSTP101]), /* VPU */
-	CLKDEV_DEV_ID("uio_pdrv_genirq.6", &mstp_clks[MSTP223]), /* SPU2DSP0 */
-	CLKDEV_DEV_ID("uio_pdrv_genirq.7", &mstp_clks[MSTP223]), /* SPU2DSP1 */
-	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */
-	CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP206]), /* SCIFB */
-	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */
-	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */
-	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */
-	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */
-	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
-	CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */
-	CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
-	CLKDEV_DEV_ID("sh_irda", &mstp_clks[MSTP325]), /* IRDA */
-	CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */
-	CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USBHS */
-	CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP322]), /* USBHS */
-	CLKDEV_DEV_ID("sh_flctl", &mstp_clks[MSTP315]), /* FLCTL */
-	CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
-	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
-	CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
-};
-
-void __init sh7377_clock_init(void)
-{
-	int k, ret = 0;
-
-	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
-		ret = clk_register(main_clks[k]);
-
-	if (!ret)
-		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
-
-	if (!ret)
-		ret = sh_clk_div6_register(div6_clks, DIV6_NR);
-
-	if (!ret)
-		ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
-
-	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
-	if (!ret)
-		shmobile_clk_init();
-	else
-		panic("failed to setup sh7377 clocks\n");
-}
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index d47e215..dfeca79 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -18,24 +18,6 @@ extern int shmobile_enter_wfi(struct cpuidle_device *dev,
 			      struct cpuidle_driver *drv, int index);
 extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv);
 
-extern void sh7367_init_irq(void);
-extern void sh7367_map_io(void);
-extern void sh7367_add_early_devices(void);
-extern void sh7367_add_standard_devices(void);
-extern void sh7367_clock_init(void);
-extern void sh7367_pinmux_init(void);
-extern struct clk sh7367_extalb1_clk;
-extern struct clk sh7367_extal2_clk;
-
-extern void sh7377_init_irq(void);
-extern void sh7377_map_io(void);
-extern void sh7377_add_early_devices(void);
-extern void sh7377_add_standard_devices(void);
-extern void sh7377_clock_init(void);
-extern void sh7377_pinmux_init(void);
-extern struct clk sh7377_extalc1_clk;
-extern struct clk sh7377_extal2_clk;
-
 extern void sh7372_init_irq(void);
 extern void sh7372_map_io(void);
 extern void sh7372_add_early_devices(void);
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7779.h b/arch/arm/mach-shmobile/include/mach/r8a7779.h
index 499f52d..8ab0cd6 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7779.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7779.h
@@ -71,7 +71,7 @@ enum {
 	GPIO_FN_A19,
 
 	/* IPSR0 */
-	GPIO_FN_PENC2, GPIO_FN_SCK0, GPIO_FN_PWM1, GPIO_FN_PWMFSW0,
+	GPIO_FN_USB_PENC2, GPIO_FN_SCK0, GPIO_FN_PWM1, GPIO_FN_PWMFSW0,
 	GPIO_FN_SCIF_CLK, GPIO_FN_TCLK0_C, GPIO_FN_BS, GPIO_FN_SD1_DAT2,
 	GPIO_FN_MMC0_D2, GPIO_FN_FD2, GPIO_FN_ATADIR0, GPIO_FN_SDSELF,
 	GPIO_FN_HCTS1, GPIO_FN_TX4_C, GPIO_FN_A0, GPIO_FN_SD1_DAT3,
diff --git a/arch/arm/mach-shmobile/include/mach/sh7367.h b/arch/arm/mach-shmobile/include/mach/sh7367.h
deleted file mode 100644
index 52d0de6..0000000
--- a/arch/arm/mach-shmobile/include/mach/sh7367.h
+++ /dev/null
@@ -1,332 +0,0 @@
-#ifndef __ASM_SH7367_H__
-#define __ASM_SH7367_H__
-
-/* Pin Function Controller:
- * GPIO_FN_xx - GPIO used to select pin function
- * GPIO_PORTxx - GPIO mapped to real I/O pin on CPU
- */
-enum {
-	/* 49-1 -> 49-6 (GPIO) */
-	GPIO_PORT0, GPIO_PORT1, GPIO_PORT2, GPIO_PORT3, GPIO_PORT4,
-	GPIO_PORT5, GPIO_PORT6, GPIO_PORT7, GPIO_PORT8, GPIO_PORT9,
-
-	GPIO_PORT10, GPIO_PORT11, GPIO_PORT12, GPIO_PORT13, GPIO_PORT14,
-	GPIO_PORT15, GPIO_PORT16, GPIO_PORT17, GPIO_PORT18, GPIO_PORT19,
-
-	GPIO_PORT20, GPIO_PORT21, GPIO_PORT22, GPIO_PORT23, GPIO_PORT24,
-	GPIO_PORT25, GPIO_PORT26, GPIO_PORT27, GPIO_PORT28, GPIO_PORT29,
-
-	GPIO_PORT30, GPIO_PORT31, GPIO_PORT32, GPIO_PORT33, GPIO_PORT34,
-	GPIO_PORT35, GPIO_PORT36, GPIO_PORT37, GPIO_PORT38, GPIO_PORT39,
-
-	GPIO_PORT40, GPIO_PORT41, GPIO_PORT42, GPIO_PORT43, GPIO_PORT44,
-	GPIO_PORT45, GPIO_PORT46, GPIO_PORT47, GPIO_PORT48, GPIO_PORT49,
-
-	GPIO_PORT50, GPIO_PORT51, GPIO_PORT52, GPIO_PORT53, GPIO_PORT54,
-	GPIO_PORT55, GPIO_PORT56, GPIO_PORT57, GPIO_PORT58, GPIO_PORT59,
-
-	GPIO_PORT60, GPIO_PORT61, GPIO_PORT62, GPIO_PORT63, GPIO_PORT64,
-	GPIO_PORT65, GPIO_PORT66, GPIO_PORT67, GPIO_PORT68, GPIO_PORT69,
-
-	GPIO_PORT70, GPIO_PORT71, GPIO_PORT72, GPIO_PORT73, GPIO_PORT74,
-	GPIO_PORT75, GPIO_PORT76, GPIO_PORT77, GPIO_PORT78, GPIO_PORT79,
-
-	GPIO_PORT80, GPIO_PORT81, GPIO_PORT82, GPIO_PORT83, GPIO_PORT84,
-	GPIO_PORT85, GPIO_PORT86, GPIO_PORT87, GPIO_PORT88, GPIO_PORT89,
-
-	GPIO_PORT90, GPIO_PORT91, GPIO_PORT92, GPIO_PORT93, GPIO_PORT94,
-	GPIO_PORT95, GPIO_PORT96, GPIO_PORT97, GPIO_PORT98, GPIO_PORT99,
-
-	GPIO_PORT100, GPIO_PORT101, GPIO_PORT102, GPIO_PORT103, GPIO_PORT104,
-	GPIO_PORT105, GPIO_PORT106, GPIO_PORT107, GPIO_PORT108, GPIO_PORT109,
-
-	GPIO_PORT110, GPIO_PORT111, GPIO_PORT112, GPIO_PORT113, GPIO_PORT114,
-	GPIO_PORT115, GPIO_PORT116, GPIO_PORT117, GPIO_PORT118, GPIO_PORT119,
-
-	GPIO_PORT120, GPIO_PORT121, GPIO_PORT122, GPIO_PORT123, GPIO_PORT124,
-	GPIO_PORT125, GPIO_PORT126, GPIO_PORT127, GPIO_PORT128, GPIO_PORT129,
-
-	GPIO_PORT130, GPIO_PORT131, GPIO_PORT132, GPIO_PORT133, GPIO_PORT134,
-	GPIO_PORT135, GPIO_PORT136, GPIO_PORT137, GPIO_PORT138, GPIO_PORT139,
-
-	GPIO_PORT140, GPIO_PORT141, GPIO_PORT142, GPIO_PORT143, GPIO_PORT144,
-	GPIO_PORT145, GPIO_PORT146, GPIO_PORT147, GPIO_PORT148, GPIO_PORT149,
-
-	GPIO_PORT150, GPIO_PORT151, GPIO_PORT152, GPIO_PORT153, GPIO_PORT154,
-	GPIO_PORT155, GPIO_PORT156, GPIO_PORT157, GPIO_PORT158, GPIO_PORT159,
-
-	GPIO_PORT160, GPIO_PORT161, GPIO_PORT162, GPIO_PORT163, GPIO_PORT164,
-	GPIO_PORT165, GPIO_PORT166, GPIO_PORT167, GPIO_PORT168, GPIO_PORT169,
-
-	GPIO_PORT170, GPIO_PORT171, GPIO_PORT172, GPIO_PORT173, GPIO_PORT174,
-	GPIO_PORT175, GPIO_PORT176, GPIO_PORT177, GPIO_PORT178, GPIO_PORT179,
-
-	GPIO_PORT180, GPIO_PORT181, GPIO_PORT182, GPIO_PORT183, GPIO_PORT184,
-	GPIO_PORT185, GPIO_PORT186, GPIO_PORT187, GPIO_PORT188, GPIO_PORT189,
-
-	GPIO_PORT190, GPIO_PORT191, GPIO_PORT192, GPIO_PORT193, GPIO_PORT194,
-	GPIO_PORT195, GPIO_PORT196, GPIO_PORT197, GPIO_PORT198, GPIO_PORT199,
-
-	GPIO_PORT200, GPIO_PORT201, GPIO_PORT202, GPIO_PORT203, GPIO_PORT204,
-	GPIO_PORT205, GPIO_PORT206, GPIO_PORT207, GPIO_PORT208, GPIO_PORT209,
-
-	GPIO_PORT210, GPIO_PORT211, GPIO_PORT212, GPIO_PORT213, GPIO_PORT214,
-	GPIO_PORT215, GPIO_PORT216, GPIO_PORT217, GPIO_PORT218, GPIO_PORT219,
-
-	GPIO_PORT220, GPIO_PORT221, GPIO_PORT222, GPIO_PORT223, GPIO_PORT224,
-	GPIO_PORT225, GPIO_PORT226, GPIO_PORT227, GPIO_PORT228, GPIO_PORT229,
-
-	GPIO_PORT230, GPIO_PORT231, GPIO_PORT232, GPIO_PORT233, GPIO_PORT234,
-	GPIO_PORT235, GPIO_PORT236, GPIO_PORT237, GPIO_PORT238, GPIO_PORT239,
-
-	GPIO_PORT240, GPIO_PORT241, GPIO_PORT242, GPIO_PORT243, GPIO_PORT244,
-	GPIO_PORT245, GPIO_PORT246, GPIO_PORT247, GPIO_PORT248, GPIO_PORT249,
-
-	GPIO_PORT250, GPIO_PORT251, GPIO_PORT252, GPIO_PORT253, GPIO_PORT254,
-	GPIO_PORT255, GPIO_PORT256, GPIO_PORT257, GPIO_PORT258, GPIO_PORT259,
-
-	GPIO_PORT260, GPIO_PORT261, GPIO_PORT262, GPIO_PORT263, GPIO_PORT264,
-	GPIO_PORT265, GPIO_PORT266, GPIO_PORT267, GPIO_PORT268, GPIO_PORT269,
-
-	GPIO_PORT270, GPIO_PORT271, GPIO_PORT272,
-
-	/* Special Pull-up / Pull-down Functions */
-	GPIO_FN_PORT48_KEYIN0_PU, GPIO_FN_PORT49_KEYIN1_PU,
-	GPIO_FN_PORT50_KEYIN2_PU, GPIO_FN_PORT55_KEYIN3_PU,
-	GPIO_FN_PORT56_KEYIN4_PU, GPIO_FN_PORT57_KEYIN5_PU,
-	GPIO_FN_PORT58_KEYIN6_PU,
-
-	/* 49-1 (FN) */
-	GPIO_FN_VBUS0, GPIO_FN_CPORT0, GPIO_FN_CPORT1, GPIO_FN_CPORT2,
-	GPIO_FN_CPORT3, GPIO_FN_CPORT4, GPIO_FN_CPORT5, GPIO_FN_CPORT6,
-	GPIO_FN_CPORT7, GPIO_FN_CPORT8, GPIO_FN_CPORT9, GPIO_FN_CPORT10,
-	GPIO_FN_CPORT11, GPIO_FN_SIN2, GPIO_FN_CPORT12, GPIO_FN_XCTS2,
-	GPIO_FN_CPORT13, GPIO_FN_RFSPO4, GPIO_FN_CPORT14, GPIO_FN_RFSPO5,
-	GPIO_FN_CPORT15, GPIO_FN_CPORT16, GPIO_FN_CPORT17, GPIO_FN_SOUT2,
-	GPIO_FN_CPORT18, GPIO_FN_XRTS2, GPIO_FN_CPORT19, GPIO_FN_CPORT20,
-	GPIO_FN_RFSPO6, GPIO_FN_CPORT21, GPIO_FN_STATUS0, GPIO_FN_CPORT22,
-	GPIO_FN_STATUS1, GPIO_FN_CPORT23, GPIO_FN_STATUS2, GPIO_FN_RFSPO7,
-	GPIO_FN_MPORT0, GPIO_FN_MPORT1, GPIO_FN_B_SYNLD1, GPIO_FN_B_SYNLD2,
-	GPIO_FN_XMAINPS, GPIO_FN_XDIVPS, GPIO_FN_XIDRST, GPIO_FN_IDCLK,
-	GPIO_FN_IDIO, GPIO_FN_SOUT1, GPIO_FN_SCIFA4_TXD,
-	GPIO_FN_M02_BERDAT, GPIO_FN_SIN1, GPIO_FN_SCIFA4_RXD, GPIO_FN_XWUP,
-	GPIO_FN_XRTS1, GPIO_FN_SCIFA4_RTS, GPIO_FN_M03_BERCLK,
-	GPIO_FN_XCTS1, GPIO_FN_SCIFA4_CTS,
-
-	/* 49-2 (FN) */
-	GPIO_FN_HSU_IQ_AGC6, GPIO_FN_MFG2_IN2, GPIO_FN_MSIOF2_MCK0,
-	GPIO_FN_HSU_IQ_AGC5, GPIO_FN_MFG2_IN1, GPIO_FN_MSIOF2_MCK1,
-	GPIO_FN_HSU_IQ_AGC4, GPIO_FN_MSIOF2_RSYNC,
-	GPIO_FN_HSU_IQ_AGC3, GPIO_FN_MFG2_OUT1, GPIO_FN_MSIOF2_RSCK,
-	GPIO_FN_HSU_IQ_AGC2, GPIO_FN_PORT42_KEYOUT0,
-	GPIO_FN_HSU_IQ_AGC1, GPIO_FN_PORT43_KEYOUT1,
-	GPIO_FN_HSU_IQ_AGC0, GPIO_FN_PORT44_KEYOUT2,
-	GPIO_FN_HSU_IQ_AGC_ST, GPIO_FN_PORT45_KEYOUT3,
-	GPIO_FN_HSU_IQ_PDO, GPIO_FN_PORT46_KEYOUT4,
-	GPIO_FN_HSU_IQ_PYO, GPIO_FN_PORT47_KEYOUT5,
-	GPIO_FN_HSU_EN_TXMUX_G3MO, GPIO_FN_PORT48_KEYIN0,
-	GPIO_FN_HSU_I_TXMUX_G3MO, GPIO_FN_PORT49_KEYIN1,
-	GPIO_FN_HSU_Q_TXMUX_G3MO, GPIO_FN_PORT50_KEYIN2,
-	GPIO_FN_HSU_SYO, GPIO_FN_PORT51_MSIOF2_TSYNC,
-	GPIO_FN_HSU_SDO, GPIO_FN_PORT52_MSIOF2_TSCK,
-	GPIO_FN_HSU_TGTTI_G3MO, GPIO_FN_PORT53_MSIOF2_TXD,
-	GPIO_FN_B_TIME_STAMP, GPIO_FN_PORT54_MSIOF2_RXD,
-	GPIO_FN_HSU_SDI, GPIO_FN_PORT55_KEYIN3,
-	GPIO_FN_HSU_SCO, GPIO_FN_PORT56_KEYIN4,
-	GPIO_FN_HSU_DREQ, GPIO_FN_PORT57_KEYIN5,
-	GPIO_FN_HSU_DACK, GPIO_FN_PORT58_KEYIN6,
-	GPIO_FN_HSU_CLK61M, GPIO_FN_PORT59_MSIOF2_SS1,
-	GPIO_FN_HSU_XRST, GPIO_FN_PORT60_MSIOF2_SS2,
-	GPIO_FN_PCMCLKO, GPIO_FN_SYNC8KO, GPIO_FN_DNPCM_A, GPIO_FN_UPPCM_A,
-	GPIO_FN_XTALB1L,
-	GPIO_FN_GPS_AGC1, GPIO_FN_SCIFA0_RTS,
-	GPIO_FN_GPS_AGC2, GPIO_FN_SCIFA0_SCK,
-	GPIO_FN_GPS_AGC3, GPIO_FN_SCIFA0_TXD,
-	GPIO_FN_GPS_AGC4, GPIO_FN_SCIFA0_RXD,
-	GPIO_FN_GPS_PWRD, GPIO_FN_SCIFA0_CTS,
-	GPIO_FN_GPS_IM, GPIO_FN_GPS_IS, GPIO_FN_GPS_QM, GPIO_FN_GPS_QS,
-	GPIO_FN_SIUBOMC, GPIO_FN_TPU2TO0,
-	GPIO_FN_SIUCKB, GPIO_FN_TPU2TO1,
-	GPIO_FN_SIUBOLR, GPIO_FN_BBIF2_TSYNC, GPIO_FN_TPU2TO2,
-	GPIO_FN_SIUBOBT, GPIO_FN_BBIF2_TSCK, GPIO_FN_TPU2TO3,
-	GPIO_FN_SIUBOSLD, GPIO_FN_BBIF2_TXD, GPIO_FN_TPU3TO0,
-	GPIO_FN_SIUBILR, GPIO_FN_TPU3TO1,
-	GPIO_FN_SIUBIBT, GPIO_FN_TPU3TO2,
-	GPIO_FN_SIUBISLD, GPIO_FN_TPU3TO3,
-	GPIO_FN_NMI, GPIO_FN_TPU4TO0,
-	GPIO_FN_DNPCM_M, GPIO_FN_TPU4TO1, GPIO_FN_TPU4TO2, GPIO_FN_TPU4TO3,
-	GPIO_FN_IRQ_TMPB,
-	GPIO_FN_PWEN, GPIO_FN_MFG1_OUT1,
-	GPIO_FN_OVCN, GPIO_FN_MFG1_IN1,
-	GPIO_FN_OVCN2, GPIO_FN_MFG1_IN2,
-
-	/* 49-3 (FN) */
-	GPIO_FN_RFSPO1, GPIO_FN_RFSPO2, GPIO_FN_RFSPO3, GPIO_FN_PORT93_VIO_CKO2,
-	GPIO_FN_USBTERM, GPIO_FN_EXTLP, GPIO_FN_IDIN,
-	GPIO_FN_SCIFA5_CTS, GPIO_FN_MFG0_IN1,
-	GPIO_FN_SCIFA5_RTS, GPIO_FN_MFG0_IN2,
-	GPIO_FN_SCIFA5_RXD,
-	GPIO_FN_SCIFA5_TXD,
-	GPIO_FN_SCIFA5_SCK, GPIO_FN_MFG0_OUT1,
-	GPIO_FN_A0_EA0, GPIO_FN_BS,
-	GPIO_FN_A14_EA14, GPIO_FN_PORT102_KEYOUT0,
-	GPIO_FN_A15_EA15, GPIO_FN_PORT103_KEYOUT1, GPIO_FN_DV_CLKOL,
-	GPIO_FN_A16_EA16, GPIO_FN_PORT104_KEYOUT2,
-	GPIO_FN_DV_VSYNCL, GPIO_FN_MSIOF0_SS1,
-	GPIO_FN_A17_EA17, GPIO_FN_PORT105_KEYOUT3,
-	GPIO_FN_DV_HSYNCL, GPIO_FN_MSIOF0_TSYNC,
-	GPIO_FN_A18_EA18, GPIO_FN_PORT106_KEYOUT4,
-	GPIO_FN_DV_DL0, GPIO_FN_MSIOF0_TSCK,
-	GPIO_FN_A19_EA19, GPIO_FN_PORT107_KEYOUT5,
-	GPIO_FN_DV_DL1, GPIO_FN_MSIOF0_TXD,
-	GPIO_FN_A20_EA20, GPIO_FN_PORT108_KEYIN0,
-	GPIO_FN_DV_DL2, GPIO_FN_MSIOF0_RSCK,
-	GPIO_FN_A21_EA21, GPIO_FN_PORT109_KEYIN1,
-	GPIO_FN_DV_DL3, GPIO_FN_MSIOF0_RSYNC,
-	GPIO_FN_A22_EA22, GPIO_FN_PORT110_KEYIN2,
-	GPIO_FN_DV_DL4, GPIO_FN_MSIOF0_MCK0,
-	GPIO_FN_A23_EA23, GPIO_FN_PORT111_KEYIN3,
-	GPIO_FN_DV_DL5, GPIO_FN_MSIOF0_MCK1,
-	GPIO_FN_A24_EA24, GPIO_FN_PORT112_KEYIN4,
-	GPIO_FN_DV_DL6, GPIO_FN_MSIOF0_RXD,
-	GPIO_FN_A25_EA25, GPIO_FN_PORT113_KEYIN5,
-	GPIO_FN_DV_DL7, GPIO_FN_MSIOF0_SS2,
-	GPIO_FN_A26, GPIO_FN_PORT113_KEYIN6, GPIO_FN_DV_CLKIL,
-	GPIO_FN_D0_ED0_NAF0, GPIO_FN_D1_ED1_NAF1, GPIO_FN_D2_ED2_NAF2,
-	GPIO_FN_D3_ED3_NAF3, GPIO_FN_D4_ED4_NAF4, GPIO_FN_D5_ED5_NAF5,
-	GPIO_FN_D6_ED6_NAF6, GPIO_FN_D7_ED7_NAF7, GPIO_FN_D8_ED8_NAF8,
-	GPIO_FN_D9_ED9_NAF9, GPIO_FN_D10_ED10_NAF10, GPIO_FN_D11_ED11_NAF11,
-	GPIO_FN_D12_ED12_NAF12, GPIO_FN_D13_ED13_NAF13,
-	GPIO_FN_D14_ED14_NAF14, GPIO_FN_D15_ED15_NAF15,
-	GPIO_FN_CS4, GPIO_FN_CS5A, GPIO_FN_CS5B, GPIO_FN_FCE1,
-	GPIO_FN_CS6B, GPIO_FN_XCS2, GPIO_FN_FCE0, GPIO_FN_CS6A,
-	GPIO_FN_DACK0, GPIO_FN_WAIT, GPIO_FN_DREQ0, GPIO_FN_RD_XRD,
-	GPIO_FN_A27, GPIO_FN_RDWR_XWE, GPIO_FN_WE0_XWR0_FWE,
-	GPIO_FN_WE1_XWR1, GPIO_FN_FRB, GPIO_FN_CKO,
-	GPIO_FN_NBRSTOUT, GPIO_FN_NBRST,
-
-	/* 49-4 (FN) */
-	GPIO_FN_RFSPO0, GPIO_FN_PORT146_VIO_CKO2, GPIO_FN_TSTMD,
-	GPIO_FN_VIO_VD, GPIO_FN_VIO_HD,
-	GPIO_FN_VIO_D0, GPIO_FN_VIO_D1, GPIO_FN_VIO_D2,
-	GPIO_FN_VIO_D3, GPIO_FN_VIO_D4, GPIO_FN_VIO_D5,
-	GPIO_FN_VIO_D6, GPIO_FN_VIO_D7, GPIO_FN_VIO_D8,
-	GPIO_FN_VIO_D9, GPIO_FN_VIO_D10, GPIO_FN_VIO_D11,
-	GPIO_FN_VIO_D12, GPIO_FN_VIO_D13, GPIO_FN_VIO_D14,
-	GPIO_FN_VIO_D15, GPIO_FN_VIO_CLK, GPIO_FN_VIO_FIELD,
-	GPIO_FN_VIO_CKO,
-	GPIO_FN_MFG3_IN1, GPIO_FN_MFG3_IN2,
-	GPIO_FN_M9_SLCD_A01, GPIO_FN_MFG3_OUT1, GPIO_FN_TPU0TO0,
-	GPIO_FN_M10_SLCD_CK1, GPIO_FN_MFG4_IN1, GPIO_FN_TPU0TO1,
-	GPIO_FN_M11_SLCD_SO1, GPIO_FN_MFG4_IN2, GPIO_FN_TPU0TO2,
-	GPIO_FN_M12_SLCD_CE1, GPIO_FN_MFG4_OUT1, GPIO_FN_TPU0TO3,
-	GPIO_FN_LCDD0, GPIO_FN_PORT175_KEYOUT0, GPIO_FN_DV_D0,
-	GPIO_FN_SIUCKA, GPIO_FN_MFG0_OUT2,
-	GPIO_FN_LCDD1, GPIO_FN_PORT176_KEYOUT1, GPIO_FN_DV_D1,
-	GPIO_FN_SIUAOLR, GPIO_FN_BBIF2_TSYNC1,
-	GPIO_FN_LCDD2, GPIO_FN_PORT177_KEYOUT2, GPIO_FN_DV_D2,
-	GPIO_FN_SIUAOBT, GPIO_FN_BBIF2_TSCK1,
-	GPIO_FN_LCDD3, GPIO_FN_PORT178_KEYOUT3, GPIO_FN_DV_D3,
-	GPIO_FN_SIUAOSLD, GPIO_FN_BBIF2_TXD1,
-	GPIO_FN_LCDD4, GPIO_FN_PORT179_KEYOUT4, GPIO_FN_DV_D4,
-	GPIO_FN_SIUAISPD, GPIO_FN_MFG1_OUT2,
-	GPIO_FN_LCDD5, GPIO_FN_PORT180_KEYOUT5, GPIO_FN_DV_D5,
-	GPIO_FN_SIUAILR, GPIO_FN_MFG2_OUT2,
-	GPIO_FN_LCDD6, GPIO_FN_DV_D6,
-	GPIO_FN_SIUAIBT, GPIO_FN_MFG3_OUT2, GPIO_FN_XWR2,
-	GPIO_FN_LCDD7, GPIO_FN_DV_D7,
-	GPIO_FN_SIUAISLD, GPIO_FN_MFG4_OUT2, GPIO_FN_XWR3,
-	GPIO_FN_LCDD8, GPIO_FN_DV_D8, GPIO_FN_D16, GPIO_FN_ED16,
-	GPIO_FN_LCDD9, GPIO_FN_DV_D9, GPIO_FN_D17, GPIO_FN_ED17,
-	GPIO_FN_LCDD10, GPIO_FN_DV_D10, GPIO_FN_D18, GPIO_FN_ED18,
-	GPIO_FN_LCDD11, GPIO_FN_DV_D11, GPIO_FN_D19, GPIO_FN_ED19,
-	GPIO_FN_LCDD12, GPIO_FN_DV_D12, GPIO_FN_D20, GPIO_FN_ED20,
-	GPIO_FN_LCDD13, GPIO_FN_DV_D13, GPIO_FN_D21, GPIO_FN_ED21,
-	GPIO_FN_LCDD14, GPIO_FN_DV_D14, GPIO_FN_D22, GPIO_FN_ED22,
-	GPIO_FN_LCDD15, GPIO_FN_DV_D15, GPIO_FN_D23, GPIO_FN_ED23,
-	GPIO_FN_LCDD16, GPIO_FN_DV_HSYNC, GPIO_FN_D24, GPIO_FN_ED24,
-	GPIO_FN_LCDD17, GPIO_FN_DV_VSYNC, GPIO_FN_D25, GPIO_FN_ED25,
-	GPIO_FN_LCDD18, GPIO_FN_DREQ2, GPIO_FN_MSIOF0L_TSCK,
-	GPIO_FN_D26, GPIO_FN_ED26,
-	GPIO_FN_LCDD19, GPIO_FN_MSIOF0L_TSYNC,
-	GPIO_FN_D27, GPIO_FN_ED27,
-	GPIO_FN_LCDD20, GPIO_FN_TS_SPSYNC1, GPIO_FN_MSIOF0L_MCK0,
-	GPIO_FN_D28, GPIO_FN_ED28,
-	GPIO_FN_LCDD21, GPIO_FN_TS_SDAT1, GPIO_FN_MSIOF0L_MCK1,
-	GPIO_FN_D29, GPIO_FN_ED29,
-	GPIO_FN_LCDD22, GPIO_FN_TS_SDEN1, GPIO_FN_MSIOF0L_SS1,
-	GPIO_FN_D30, GPIO_FN_ED30,
-	GPIO_FN_LCDD23, GPIO_FN_TS_SCK1, GPIO_FN_MSIOF0L_SS2,
-	GPIO_FN_D31, GPIO_FN_ED31,
-	GPIO_FN_LCDDCK, GPIO_FN_LCDWR, GPIO_FN_DV_CKO, GPIO_FN_SIUAOSPD,
-	GPIO_FN_LCDRD, GPIO_FN_DACK2, GPIO_FN_MSIOF0L_RSYNC,
-
-
-	/* 49-5 (FN) */
-	GPIO_FN_LCDHSYN, GPIO_FN_LCDCS, GPIO_FN_LCDCS2, GPIO_FN_DACK3,
-	GPIO_FN_LCDDISP, GPIO_FN_LCDRS, GPIO_FN_DREQ3, GPIO_FN_MSIOF0L_RSCK,
-	GPIO_FN_LCDCSYN, GPIO_FN_LCDCSYN2, GPIO_FN_DV_CKI,
-	GPIO_FN_LCDLCLK, GPIO_FN_DREQ1, GPIO_FN_MSIOF0L_RXD,
-	GPIO_FN_LCDDON, GPIO_FN_LCDDON2, GPIO_FN_DACK1, GPIO_FN_MSIOF0L_TXD,
-	GPIO_FN_VIO_DR0, GPIO_FN_VIO_DR1, GPIO_FN_VIO_DR2, GPIO_FN_VIO_DR3,
-	GPIO_FN_VIO_DR4, GPIO_FN_VIO_DR5, GPIO_FN_VIO_DR6, GPIO_FN_VIO_DR7,
-	GPIO_FN_VIO_VDR, GPIO_FN_VIO_HDR,
-	GPIO_FN_VIO_CLKR, GPIO_FN_VIO_CKOR,
-	GPIO_FN_SCIFA1_TXD, GPIO_FN_GPS_PGFA0,
-	GPIO_FN_SCIFA1_SCK, GPIO_FN_GPS_PGFA1,
-	GPIO_FN_SCIFA1_RTS, GPIO_FN_GPS_EPPSINMON,
-	GPIO_FN_SCIFA1_RXD, GPIO_FN_SCIFA1_CTS,
-	GPIO_FN_MSIOF1_TXD, GPIO_FN_SCIFA1_TXD2, GPIO_FN_GPS_TXD,
-	GPIO_FN_MSIOF1_TSYNC, GPIO_FN_SCIFA1_CTS2, GPIO_FN_I2C_SDA2,
-	GPIO_FN_MSIOF1_TSCK, GPIO_FN_SCIFA1_SCK2,
-	GPIO_FN_MSIOF1_RXD, GPIO_FN_SCIFA1_RXD2, GPIO_FN_GPS_RXD,
-	GPIO_FN_MSIOF1_RSCK, GPIO_FN_SCIFA1_RTS2,
-	GPIO_FN_MSIOF1_RSYNC, GPIO_FN_I2C_SCL2,
-	GPIO_FN_MSIOF1_MCK0, GPIO_FN_MSIOF1_MCK1,
-	GPIO_FN_MSIOF1_SS1, GPIO_FN_EDBGREQ3,
-	GPIO_FN_MSIOF1_SS2,
-	GPIO_FN_PORT236_IROUT, GPIO_FN_IRDA_OUT,
-	GPIO_FN_IRDA_IN, GPIO_FN_IRDA_FIRSEL,
-	GPIO_FN_TPU1TO0, GPIO_FN_TS_SPSYNC3,
-	GPIO_FN_TPU1TO1, GPIO_FN_TS_SDAT3,
-	GPIO_FN_TPU1TO2, GPIO_FN_TS_SDEN3, GPIO_FN_PORT241_MSIOF2_SS1,
-	GPIO_FN_TPU1TO3, GPIO_FN_PORT242_MSIOF2_TSCK,
-	GPIO_FN_M13_BSW, GPIO_FN_PORT243_MSIOF2_TSYNC,
-	GPIO_FN_M14_GSW, GPIO_FN_PORT244_MSIOF2_TXD,
-	GPIO_FN_PORT245_IROUT, GPIO_FN_M15_RSW,
-	GPIO_FN_SOUT3, GPIO_FN_SCIFA2_TXD1,
-	GPIO_FN_SIN3, GPIO_FN_SCIFA2_RXD1,
-	GPIO_FN_XRTS3, GPIO_FN_SCIFA2_RTS1, GPIO_FN_PORT248_MSIOF2_SS2,
-	GPIO_FN_XCTS3, GPIO_FN_SCIFA2_CTS1, GPIO_FN_PORT249_MSIOF2_RXD,
-	GPIO_FN_DINT, GPIO_FN_SCIFA2_SCK1, GPIO_FN_TS_SCK3,
-	GPIO_FN_SDHICLK0, GPIO_FN_TCK2,
-	GPIO_FN_SDHICD0,
-	GPIO_FN_SDHID0_0, GPIO_FN_TMS2,
-	GPIO_FN_SDHID0_1, GPIO_FN_TDO2,
-	GPIO_FN_SDHID0_2, GPIO_FN_TDI2,
-	GPIO_FN_SDHID0_3, GPIO_FN_RTCK2,
-
-	/* 49-6 (FN) */
-	GPIO_FN_SDHICMD0, GPIO_FN_TRST2,
-	GPIO_FN_SDHIWP0, GPIO_FN_EDBGREQ2,
-	GPIO_FN_SDHICLK1, GPIO_FN_TCK3,
-	GPIO_FN_SDHID1_0, GPIO_FN_M11_SLCD_SO2,
-	GPIO_FN_TS_SPSYNC2, GPIO_FN_TMS3,
-	GPIO_FN_SDHID1_1, GPIO_FN_M9_SLCD_AO2,
-	GPIO_FN_TS_SDAT2, GPIO_FN_TDO3,
-	GPIO_FN_SDHID1_2, GPIO_FN_M10_SLCD_CK2,
-	GPIO_FN_TS_SDEN2, GPIO_FN_TDI3,
-	GPIO_FN_SDHID1_3, GPIO_FN_M12_SLCD_CE2,
-	GPIO_FN_TS_SCK2, GPIO_FN_RTCK3,
-	GPIO_FN_SDHICMD1, GPIO_FN_TRST3,
-	GPIO_FN_SDHICLK2, GPIO_FN_SCIFB_SCK,
-	GPIO_FN_SDHID2_0, GPIO_FN_SCIFB_TXD,
-	GPIO_FN_SDHID2_1, GPIO_FN_SCIFB_CTS,
-	GPIO_FN_SDHID2_2, GPIO_FN_SCIFB_RXD,
-	GPIO_FN_SDHID2_3, GPIO_FN_SCIFB_RTS,
-	GPIO_FN_SDHICMD2,
-	GPIO_FN_RESETOUTS,
-	GPIO_FN_DIVLOCK,
-};
-
-#endif /* __ASM_SH7367_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
index eb98b45..b582fac 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -452,6 +452,10 @@ enum {
 	SHDMA_SLAVE_SCIF5_RX,
 	SHDMA_SLAVE_SCIF6_TX,
 	SHDMA_SLAVE_SCIF6_RX,
+	SHDMA_SLAVE_FLCTL0_TX,
+	SHDMA_SLAVE_FLCTL0_RX,
+	SHDMA_SLAVE_FLCTL1_TX,
+	SHDMA_SLAVE_FLCTL1_RX,
 	SHDMA_SLAVE_SDHI0_RX,
 	SHDMA_SLAVE_SDHI0_TX,
 	SHDMA_SLAVE_SDHI1_RX,
@@ -473,10 +477,6 @@ extern struct clk sh7372_extal2_clk;
 extern struct clk sh7372_dv_clki_clk;
 extern struct clk sh7372_dv_clki_div2_clk;
 extern struct clk sh7372_pllc2_clk;
-extern struct clk sh7372_fsiack_clk;
-extern struct clk sh7372_fsibck_clk;
-extern struct clk sh7372_fsidiva_clk;
-extern struct clk sh7372_fsidivb_clk;
 
 extern void sh7372_intcs_suspend(void);
 extern void sh7372_intcs_resume(void);
diff --git a/arch/arm/mach-shmobile/include/mach/sh7377.h b/arch/arm/mach-shmobile/include/mach/sh7377.h
deleted file mode 100644
index f580e22..0000000
--- a/arch/arm/mach-shmobile/include/mach/sh7377.h
+++ /dev/null
@@ -1,360 +0,0 @@
-#ifndef __ASM_SH7377_H__
-#define __ASM_SH7377_H__
-
-/* Pin Function Controller:
- * GPIO_FN_xx - GPIO used to select pin function
- * GPIO_PORTxx - GPIO mapped to real I/O pin on CPU
- */
-enum {
-	/* 55-1 -> 55-5 (GPIO) */
-	GPIO_PORT0, GPIO_PORT1, GPIO_PORT2, GPIO_PORT3, GPIO_PORT4,
-	GPIO_PORT5, GPIO_PORT6, GPIO_PORT7, GPIO_PORT8, GPIO_PORT9,
-
-	GPIO_PORT10, GPIO_PORT11, GPIO_PORT12, GPIO_PORT13, GPIO_PORT14,
-	GPIO_PORT15, GPIO_PORT16, GPIO_PORT17, GPIO_PORT18, GPIO_PORT19,
-
-	GPIO_PORT20, GPIO_PORT21, GPIO_PORT22, GPIO_PORT23, GPIO_PORT24,
-	GPIO_PORT25, GPIO_PORT26, GPIO_PORT27, GPIO_PORT28, GPIO_PORT29,
-
-	GPIO_PORT30, GPIO_PORT31, GPIO_PORT32, GPIO_PORT33, GPIO_PORT34,
-	GPIO_PORT35, GPIO_PORT36, GPIO_PORT37, GPIO_PORT38, GPIO_PORT39,
-
-	GPIO_PORT40, GPIO_PORT41, GPIO_PORT42, GPIO_PORT43, GPIO_PORT44,
-	GPIO_PORT45, GPIO_PORT46, GPIO_PORT47, GPIO_PORT48, GPIO_PORT49,
-
-	GPIO_PORT50, GPIO_PORT51, GPIO_PORT52, GPIO_PORT53, GPIO_PORT54,
-	GPIO_PORT55, GPIO_PORT56, GPIO_PORT57, GPIO_PORT58, GPIO_PORT59,
-
-	GPIO_PORT60, GPIO_PORT61, GPIO_PORT62, GPIO_PORT63, GPIO_PORT64,
-	GPIO_PORT65, GPIO_PORT66, GPIO_PORT67, GPIO_PORT68, GPIO_PORT69,
-
-	GPIO_PORT70, GPIO_PORT71, GPIO_PORT72, GPIO_PORT73, GPIO_PORT74,
-	GPIO_PORT75, GPIO_PORT76, GPIO_PORT77, GPIO_PORT78, GPIO_PORT79,
-
-	GPIO_PORT80, GPIO_PORT81, GPIO_PORT82, GPIO_PORT83, GPIO_PORT84,
-	GPIO_PORT85, GPIO_PORT86, GPIO_PORT87, GPIO_PORT88, GPIO_PORT89,
-
-	GPIO_PORT90, GPIO_PORT91, GPIO_PORT92, GPIO_PORT93, GPIO_PORT94,
-	GPIO_PORT95, GPIO_PORT96, GPIO_PORT97, GPIO_PORT98, GPIO_PORT99,
-
-	GPIO_PORT100, GPIO_PORT101, GPIO_PORT102, GPIO_PORT103, GPIO_PORT104,
-	GPIO_PORT105, GPIO_PORT106, GPIO_PORT107, GPIO_PORT108, GPIO_PORT109,
-
-	GPIO_PORT110, GPIO_PORT111, GPIO_PORT112, GPIO_PORT113, GPIO_PORT114,
-	GPIO_PORT115, GPIO_PORT116, GPIO_PORT117, GPIO_PORT118,
-
-	GPIO_PORT128, GPIO_PORT129,
-
-	GPIO_PORT130, GPIO_PORT131, GPIO_PORT132, GPIO_PORT133, GPIO_PORT134,
-	GPIO_PORT135, GPIO_PORT136, GPIO_PORT137, GPIO_PORT138, GPIO_PORT139,
-
-	GPIO_PORT140, GPIO_PORT141, GPIO_PORT142, GPIO_PORT143, GPIO_PORT144,
-	GPIO_PORT145, GPIO_PORT146, GPIO_PORT147, GPIO_PORT148, GPIO_PORT149,
-
-	GPIO_PORT150, GPIO_PORT151, GPIO_PORT152, GPIO_PORT153, GPIO_PORT154,
-	GPIO_PORT155, GPIO_PORT156, GPIO_PORT157, GPIO_PORT158, GPIO_PORT159,
-
-	GPIO_PORT160, GPIO_PORT161, GPIO_PORT162, GPIO_PORT163, GPIO_PORT164,
-
-	GPIO_PORT192, GPIO_PORT193, GPIO_PORT194,
-	GPIO_PORT195, GPIO_PORT196, GPIO_PORT197, GPIO_PORT198, GPIO_PORT199,
-
-	GPIO_PORT200, GPIO_PORT201, GPIO_PORT202, GPIO_PORT203, GPIO_PORT204,
-	GPIO_PORT205, GPIO_PORT206, GPIO_PORT207, GPIO_PORT208, GPIO_PORT209,
-
-	GPIO_PORT210, GPIO_PORT211, GPIO_PORT212, GPIO_PORT213, GPIO_PORT214,
-	GPIO_PORT215, GPIO_PORT216, GPIO_PORT217, GPIO_PORT218, GPIO_PORT219,
-
-	GPIO_PORT220, GPIO_PORT221, GPIO_PORT222, GPIO_PORT223, GPIO_PORT224,
-	GPIO_PORT225, GPIO_PORT226, GPIO_PORT227, GPIO_PORT228, GPIO_PORT229,
-
-	GPIO_PORT230, GPIO_PORT231, GPIO_PORT232, GPIO_PORT233, GPIO_PORT234,
-	GPIO_PORT235, GPIO_PORT236, GPIO_PORT237, GPIO_PORT238, GPIO_PORT239,
-
-	GPIO_PORT240, GPIO_PORT241, GPIO_PORT242, GPIO_PORT243, GPIO_PORT244,
-	GPIO_PORT245, GPIO_PORT246, GPIO_PORT247, GPIO_PORT248, GPIO_PORT249,
-
-	GPIO_PORT250, GPIO_PORT251, GPIO_PORT252, GPIO_PORT253, GPIO_PORT254,
-	GPIO_PORT255, GPIO_PORT256, GPIO_PORT257, GPIO_PORT258, GPIO_PORT259,
-
-	GPIO_PORT260, GPIO_PORT261, GPIO_PORT262, GPIO_PORT263, GPIO_PORT264,
-
-	/* Special Pull-up / Pull-down Functions */
-	GPIO_FN_PORT66_KEYIN0_PU, GPIO_FN_PORT67_KEYIN1_PU,
-	GPIO_FN_PORT68_KEYIN2_PU, GPIO_FN_PORT69_KEYIN3_PU,
-	GPIO_FN_PORT70_KEYIN4_PU, GPIO_FN_PORT71_KEYIN5_PU,
-	GPIO_FN_PORT72_KEYIN6_PU,
-
-	/* 55-1 (FN) */
-	GPIO_FN_VBUS_0,
-	GPIO_FN_CPORT0,
-	GPIO_FN_CPORT1,
-	GPIO_FN_CPORT2,
-	GPIO_FN_CPORT3,
-	GPIO_FN_CPORT4,
-	GPIO_FN_CPORT5,
-	GPIO_FN_CPORT6,
-	GPIO_FN_CPORT7,
-	GPIO_FN_CPORT8,
-	GPIO_FN_CPORT9,
-	GPIO_FN_CPORT10,
-	GPIO_FN_CPORT11, GPIO_FN_SIN2,
-	GPIO_FN_CPORT12, GPIO_FN_XCTS2,
-	GPIO_FN_CPORT13, GPIO_FN_RFSPO4,
-	GPIO_FN_CPORT14, GPIO_FN_RFSPO5,
-	GPIO_FN_CPORT15, GPIO_FN_SCIFA0_SCK, GPIO_FN_GPS_AGC2,
-	GPIO_FN_CPORT16, GPIO_FN_SCIFA0_TXD, GPIO_FN_GPS_AGC3,
-	GPIO_FN_CPORT17_IC_OE, GPIO_FN_SOUT2,
-	GPIO_FN_CPORT18, GPIO_FN_XRTS2, GPIO_FN_PORT19_VIO_CKO2,
-	GPIO_FN_CPORT19_MPORT1,
-	GPIO_FN_CPORT20, GPIO_FN_RFSPO6,
-	GPIO_FN_CPORT21, GPIO_FN_STATUS0,
-	GPIO_FN_CPORT22, GPIO_FN_STATUS1,
-	GPIO_FN_CPORT23, GPIO_FN_STATUS2, GPIO_FN_RFSPO7,
-	GPIO_FN_B_SYNLD1,
-	GPIO_FN_B_SYNLD2, GPIO_FN_SYSENMSK,
-	GPIO_FN_XMAINPS,
-	GPIO_FN_XDIVPS,
-	GPIO_FN_XIDRST,
-	GPIO_FN_IDCLK, GPIO_FN_IC_DP,
-	GPIO_FN_IDIO, GPIO_FN_IC_DM,
-	GPIO_FN_SOUT1, GPIO_FN_SCIFA4_TXD, GPIO_FN_M02_BERDAT,
-	GPIO_FN_SIN1, GPIO_FN_SCIFA4_RXD, GPIO_FN_XWUP,
-	GPIO_FN_XRTS1, GPIO_FN_SCIFA4_RTS, GPIO_FN_M03_BERCLK,
-	GPIO_FN_XCTS1, GPIO_FN_SCIFA4_CTS,
-	GPIO_FN_PCMCLKO,
-	GPIO_FN_SYNC8KO,
-
-	/* 55-2 (FN) */
-	GPIO_FN_DNPCM_A,
-	GPIO_FN_UPPCM_A,
-	GPIO_FN_VACK,
-	GPIO_FN_XTALB1L,
-	GPIO_FN_GPS_AGC1, GPIO_FN_SCIFA0_RTS,
-	GPIO_FN_GPS_AGC4, GPIO_FN_SCIFA0_RXD,
-	GPIO_FN_GPS_PWRDOWN, GPIO_FN_SCIFA0_CTS,
-	GPIO_FN_GPS_IM,
-	GPIO_FN_GPS_IS,
-	GPIO_FN_GPS_QM,
-	GPIO_FN_GPS_QS,
-	GPIO_FN_FMSOCK, GPIO_FN_PORT49_IRDA_OUT, GPIO_FN_PORT49_IROUT,
-	GPIO_FN_FMSOOLR, GPIO_FN_BBIF2_TSYNC2, GPIO_FN_TPU2TO2, GPIO_FN_IPORT3,
-	GPIO_FN_FMSIOLR,
-	GPIO_FN_FMSOOBT, GPIO_FN_BBIF2_TSCK2, GPIO_FN_TPU2TO3, GPIO_FN_OPORT1,
-	GPIO_FN_FMSIOBT,
-	GPIO_FN_FMSOSLD, GPIO_FN_BBIF2_TXD2, GPIO_FN_OPORT2,
-	GPIO_FN_FMSOILR, GPIO_FN_PORT53_IRDA_IN, GPIO_FN_TPU3TO3,
-	GPIO_FN_OPORT3, GPIO_FN_FMSIILR,
-	GPIO_FN_FMSOIBT, GPIO_FN_PORT54_IRDA_FIRSEL, GPIO_FN_TPU3TO2,
-	GPIO_FN_FMSIIBT,
-	GPIO_FN_FMSISLD, GPIO_FN_MFG0_OUT1, GPIO_FN_TPU0TO0,
-	GPIO_FN_A0_EA0, GPIO_FN_BS,
-	GPIO_FN_A12_EA12, GPIO_FN_PORT58_VIO_CKOR, GPIO_FN_TPU4TO2,
-	GPIO_FN_A13_EA13, GPIO_FN_PORT59_IROUT, GPIO_FN_MFG0_OUT2,
-	GPIO_FN_TPU0TO1,
-	GPIO_FN_A14_EA14, GPIO_FN_PORT60_KEYOUT5,
-	GPIO_FN_A15_EA15, GPIO_FN_PORT61_KEYOUT4,
-	GPIO_FN_A16_EA16, GPIO_FN_PORT62_KEYOUT3, GPIO_FN_MSIOF0_SS1,
-	GPIO_FN_A17_EA17, GPIO_FN_PORT63_KEYOUT2, GPIO_FN_MSIOF0_TSYNC,
-	GPIO_FN_A18_EA18, GPIO_FN_PORT64_KEYOUT1, GPIO_FN_MSIOF0_TSCK,
-	GPIO_FN_A19_EA19, GPIO_FN_PORT65_KEYOUT0, GPIO_FN_MSIOF0_TXD,
-	GPIO_FN_A20_EA20, GPIO_FN_PORT66_KEYIN0, GPIO_FN_MSIOF0_RSCK,
-	GPIO_FN_A21_EA21, GPIO_FN_PORT67_KEYIN1, GPIO_FN_MSIOF0_RSYNC,
-	GPIO_FN_A22_EA22, GPIO_FN_PORT68_KEYIN2, GPIO_FN_MSIOF0_MCK0,
-	GPIO_FN_A23_EA23, GPIO_FN_PORT69_KEYIN3, GPIO_FN_MSIOF0_MCK1,
-	GPIO_FN_A24_EA24, GPIO_FN_PORT70_KEYIN4, GPIO_FN_MSIOF0_RXD,
-	GPIO_FN_A25_EA25, GPIO_FN_PORT71_KEYIN5, GPIO_FN_MSIOF0_SS2,
-	GPIO_FN_A26, GPIO_FN_PORT72_KEYIN6,
-	GPIO_FN_D0_ED0_NAF0,
-	GPIO_FN_D1_ED1_NAF1,
-	GPIO_FN_D2_ED2_NAF2,
-	GPIO_FN_D3_ED3_NAF3,
-	GPIO_FN_D4_ED4_NAF4,
-	GPIO_FN_D5_ED5_NAF5,
-	GPIO_FN_D6_ED6_NAF6,
-	GPIO_FN_D7_ED7_NAF7,
-	GPIO_FN_D8_ED8_NAF8,
-	GPIO_FN_D9_ED9_NAF9,
-	GPIO_FN_D10_ED10_NAF10,
-	GPIO_FN_D11_ED11_NAF11,
-	GPIO_FN_D12_ED12_NAF12,
-	GPIO_FN_D13_ED13_NAF13,
-	GPIO_FN_D14_ED14_NAF14,
-	GPIO_FN_D15_ED15_NAF15,
-	GPIO_FN_CS4,
-	GPIO_FN_CS5A, GPIO_FN_FMSICK,
-	GPIO_FN_CS5B, GPIO_FN_FCE1,
-
-	/* 55-3 (FN) */
-	GPIO_FN_CS6B, GPIO_FN_XCS2, GPIO_FN_CS6A, GPIO_FN_DACK0,
-	GPIO_FN_FCE0,
-	GPIO_FN_WAIT, GPIO_FN_DREQ0,
-	GPIO_FN_RD_XRD,
-	GPIO_FN_WE0_XWR0_FWE,
-	GPIO_FN_WE1_XWR1,
-	GPIO_FN_FRB,
-	GPIO_FN_CKO,
-	GPIO_FN_NBRSTOUT,
-	GPIO_FN_NBRST,
-	GPIO_FN_GPS_EPPSIN,
-	GPIO_FN_LATCHPULSE,
-	GPIO_FN_LTESIGNAL,
-	GPIO_FN_LEGACYSTATE,
-	GPIO_FN_TCKON,
-	GPIO_FN_VIO_VD, GPIO_FN_PORT128_KEYOUT0, GPIO_FN_IPORT0,
-	GPIO_FN_VIO_HD, GPIO_FN_PORT129_KEYOUT1, GPIO_FN_IPORT1,
-	GPIO_FN_VIO_D0, GPIO_FN_PORT130_KEYOUT2, GPIO_FN_PORT130_MSIOF2_RXD,
-	GPIO_FN_VIO_D1, GPIO_FN_PORT131_KEYOUT3, GPIO_FN_PORT131_MSIOF2_SS1,
-	GPIO_FN_VIO_D2, GPIO_FN_PORT132_KEYOUT4, GPIO_FN_PORT132_MSIOF2_SS2,
-	GPIO_FN_VIO_D3, GPIO_FN_PORT133_KEYOUT5, GPIO_FN_PORT133_MSIOF2_TSYNC,
-	GPIO_FN_VIO_D4, GPIO_FN_PORT134_KEYIN0, GPIO_FN_PORT134_MSIOF2_TXD,
-	GPIO_FN_VIO_D5, GPIO_FN_PORT135_KEYIN1, GPIO_FN_PORT135_MSIOF2_TSCK,
-	GPIO_FN_VIO_D6, GPIO_FN_PORT136_KEYIN2,
-	GPIO_FN_VIO_D7, GPIO_FN_PORT137_KEYIN3,
-	GPIO_FN_VIO_D8, GPIO_FN_M9_SLCD_A01, GPIO_FN_PORT138_FSIAOMC,
-	GPIO_FN_VIO_D9, GPIO_FN_M10_SLCD_CK1, GPIO_FN_PORT139_FSIAOLR,
-	GPIO_FN_VIO_D10, GPIO_FN_M11_SLCD_SO1, GPIO_FN_TPU0TO2,
-	GPIO_FN_PORT140_FSIAOBT,
-	GPIO_FN_VIO_D11, GPIO_FN_M12_SLCD_CE1, GPIO_FN_TPU0TO3,
-	GPIO_FN_PORT141_FSIAOSLD,
-	GPIO_FN_VIO_D12, GPIO_FN_M13_BSW, GPIO_FN_PORT142_FSIACK,
-	GPIO_FN_VIO_D13, GPIO_FN_M14_GSW, GPIO_FN_PORT143_FSIAILR,
-	GPIO_FN_VIO_D14, GPIO_FN_M15_RSW, GPIO_FN_PORT144_FSIAIBT,
-	GPIO_FN_VIO_D15, GPIO_FN_TPU1TO3, GPIO_FN_PORT145_FSIAISLD,
-	GPIO_FN_VIO_CLK, GPIO_FN_PORT146_KEYIN4, GPIO_FN_IPORT2,
-	GPIO_FN_VIO_FIELD, GPIO_FN_PORT147_KEYIN5,
-	GPIO_FN_VIO_CKO, GPIO_FN_PORT148_KEYIN6,
-	GPIO_FN_A27, GPIO_FN_RDWR_XWE, GPIO_FN_MFG0_IN1,
-	GPIO_FN_MFG0_IN2,
-	GPIO_FN_TS_SPSYNC3, GPIO_FN_MSIOF2_RSCK,
-	GPIO_FN_TS_SDAT3, GPIO_FN_MSIOF2_RSYNC,
-	GPIO_FN_TPU1TO2, GPIO_FN_TS_SDEN3, GPIO_FN_PORT153_MSIOF2_SS1,
-	GPIO_FN_SOUT3, GPIO_FN_SCIFA2_TXD1, GPIO_FN_MSIOF2_MCK0,
-	GPIO_FN_SIN3, GPIO_FN_SCIFA2_RXD1, GPIO_FN_MSIOF2_MCK1,
-	GPIO_FN_XRTS3, GPIO_FN_SCIFA2_RTS1, GPIO_FN_PORT156_MSIOF2_SS2,
-	GPIO_FN_XCTS3, GPIO_FN_SCIFA2_CTS1, GPIO_FN_PORT157_MSIOF2_RXD,
-
-	/* 55-4 (FN) */
-	GPIO_FN_DINT, GPIO_FN_SCIFA2_SCK1, GPIO_FN_TS_SCK3,
-	GPIO_FN_PORT159_SCIFB_SCK, GPIO_FN_PORT159_SCIFA5_SCK, GPIO_FN_NMI,
-	GPIO_FN_PORT160_SCIFB_TXD, GPIO_FN_PORT160_SCIFA5_TXD, GPIO_FN_SOUT0,
-	GPIO_FN_PORT161_SCIFB_CTS, GPIO_FN_PORT161_SCIFA5_CTS, GPIO_FN_XCTS0,
-	GPIO_FN_MFG3_IN2,
-	GPIO_FN_PORT162_SCIFB_RXD, GPIO_FN_PORT162_SCIFA5_RXD, GPIO_FN_SIN0,
-	GPIO_FN_MFG3_IN1,
-	GPIO_FN_PORT163_SCIFB_RTS, GPIO_FN_PORT163_SCIFA5_RTS, GPIO_FN_XRTS0,
-	GPIO_FN_MFG3_OUT1,
-	GPIO_FN_TPU3TO0,
-	GPIO_FN_LCDD0, GPIO_FN_PORT192_KEYOUT0, GPIO_FN_EXT_CKI,
-	GPIO_FN_LCDD1, GPIO_FN_PORT193_KEYOUT1, GPIO_FN_PORT193_SCIFA5_CTS,
-	GPIO_FN_BBIF2_TSYNC1,
-	GPIO_FN_LCDD2, GPIO_FN_PORT194_KEYOUT2, GPIO_FN_PORT194_SCIFA5_RTS,
-	GPIO_FN_BBIF2_TSCK1,
-	GPIO_FN_LCDD3, GPIO_FN_PORT195_KEYOUT3, GPIO_FN_PORT195_SCIFA5_RXD,
-	GPIO_FN_BBIF2_TXD1,
-	GPIO_FN_LCDD4, GPIO_FN_PORT196_KEYOUT4, GPIO_FN_PORT196_SCIFA5_TXD,
-	GPIO_FN_LCDD5, GPIO_FN_PORT197_KEYOUT5, GPIO_FN_PORT197_SCIFA5_SCK,
-	GPIO_FN_MFG2_OUT2, GPIO_FN_TPU2TO1,
-	GPIO_FN_LCDD6, GPIO_FN_XWR2,
-	GPIO_FN_LCDD7, GPIO_FN_TPU4TO1, GPIO_FN_MFG4_OUT2, GPIO_FN_XWR3,
-	GPIO_FN_LCDD8, GPIO_FN_PORT200_KEYIN0, GPIO_FN_VIO_DR0, GPIO_FN_D16,
-	GPIO_FN_ED16,
-	GPIO_FN_LCDD9, GPIO_FN_PORT201_KEYIN1, GPIO_FN_VIO_DR1, GPIO_FN_D17,
-	GPIO_FN_ED17,
-	GPIO_FN_LCDD10, GPIO_FN_PORT202_KEYIN2, GPIO_FN_VIO_DR2, GPIO_FN_D18,
-	GPIO_FN_ED18,
-	GPIO_FN_LCDD11, GPIO_FN_PORT203_KEYIN3, GPIO_FN_VIO_DR3, GPIO_FN_D19,
-	GPIO_FN_ED19,
-	GPIO_FN_LCDD12, GPIO_FN_PORT204_KEYIN4, GPIO_FN_VIO_DR4, GPIO_FN_D20,
-	GPIO_FN_ED20,
-	GPIO_FN_LCDD13, GPIO_FN_PORT205_KEYIN5, GPIO_FN_VIO_DR5, GPIO_FN_D21,
-	GPIO_FN_ED21,
-	GPIO_FN_LCDD14, GPIO_FN_PORT206_KEYIN6, GPIO_FN_VIO_DR6, GPIO_FN_D22,
-	GPIO_FN_ED22,
-	GPIO_FN_LCDD15, GPIO_FN_PORT207_MSIOF0L_SS1, GPIO_FN_PORT207_KEYOUT0,
-	GPIO_FN_VIO_DR7,
-	GPIO_FN_D23, GPIO_FN_ED23,
-	GPIO_FN_LCDD16, GPIO_FN_PORT208_MSIOF0L_SS2, GPIO_FN_PORT208_KEYOUT1,
-	GPIO_FN_VIO_VDR,
-	GPIO_FN_D24, GPIO_FN_ED24,
-	GPIO_FN_LCDD17, GPIO_FN_PORT209_KEYOUT2, GPIO_FN_VIO_HDR, GPIO_FN_D25,
-	GPIO_FN_ED25,
-	GPIO_FN_LCDD18, GPIO_FN_DREQ2, GPIO_FN_PORT210_MSIOF0L_SS1, GPIO_FN_D26,
-	GPIO_FN_ED26,
-	GPIO_FN_LCDD19, GPIO_FN_PORT211_MSIOF0L_SS2, GPIO_FN_D27, GPIO_FN_ED27,
-	GPIO_FN_LCDD20, GPIO_FN_TS_SPSYNC1, GPIO_FN_MSIOF0L_MCK0, GPIO_FN_D28,
-	GPIO_FN_ED28,
-	GPIO_FN_LCDD21, GPIO_FN_TS_SDAT1, GPIO_FN_MSIOF0L_MCK1, GPIO_FN_D29,
-	GPIO_FN_ED29,
-	GPIO_FN_LCDD22, GPIO_FN_TS_SDEN1, GPIO_FN_MSIOF0L_RSCK, GPIO_FN_D30,
-	GPIO_FN_ED30,
-	GPIO_FN_LCDD23, GPIO_FN_TS_SCK1, GPIO_FN_MSIOF0L_RSYNC, GPIO_FN_D31,
-	GPIO_FN_ED31,
-	GPIO_FN_LCDDCK, GPIO_FN_LCDWR, GPIO_FN_PORT216_KEYOUT3,
-	GPIO_FN_VIO_CLKR,
-	GPIO_FN_LCDRD, GPIO_FN_DACK2, GPIO_FN_MSIOF0L_TSYNC,
-	GPIO_FN_LCDHSYN, GPIO_FN_LCDCS, GPIO_FN_LCDCS2, GPIO_FN_DACK3,
-	GPIO_FN_PORT218_VIO_CKOR, GPIO_FN_PORT218_KEYOUT4,
-	GPIO_FN_LCDDISP, GPIO_FN_LCDRS, GPIO_FN_DREQ3, GPIO_FN_MSIOF0L_TSCK,
-	GPIO_FN_LCDVSYN, GPIO_FN_LCDVSYN2, GPIO_FN_PORT220_KEYOUT5,
-	GPIO_FN_LCDLCLK, GPIO_FN_DREQ1, GPIO_FN_PWEN, GPIO_FN_MSIOF0L_RXD,
-	GPIO_FN_LCDDON, GPIO_FN_LCDDON2, GPIO_FN_DACK1, GPIO_FN_OVCN,
-	GPIO_FN_MSIOF0L_TXD,
-	GPIO_FN_SCIFA1_TXD, GPIO_FN_OVCN2,
-	GPIO_FN_EXTLP, GPIO_FN_SCIFA1_SCK, GPIO_FN_USBTERM,
-	GPIO_FN_PORT226_VIO_CKO2,
-	GPIO_FN_SCIFA1_RTS, GPIO_FN_IDIN,
-	GPIO_FN_SCIFA1_RXD,
-	GPIO_FN_SCIFA1_CTS, GPIO_FN_MFG1_IN1,
-	GPIO_FN_MSIOF1_TXD, GPIO_FN_SCIFA2_TXD2, GPIO_FN_PORT230_FSIAOMC,
-	GPIO_FN_MSIOF1_TSYNC, GPIO_FN_SCIFA2_CTS2, GPIO_FN_PORT231_FSIAOLR,
-	GPIO_FN_MSIOF1_TSCK, GPIO_FN_SCIFA2_SCK2, GPIO_FN_PORT232_FSIAOBT,
-	GPIO_FN_MSIOF1_RXD, GPIO_FN_SCIFA2_RXD2, GPIO_FN_GPS_VCOTRIG,
-	GPIO_FN_PORT233_FSIACK,
-	GPIO_FN_MSIOF1_RSCK, GPIO_FN_SCIFA2_RTS2, GPIO_FN_PORT234_FSIAOSLD,
-	GPIO_FN_MSIOF1_RSYNC, GPIO_FN_OPORT0, GPIO_FN_MFG1_IN2,
-	GPIO_FN_PORT235_FSIAILR,
-	GPIO_FN_MSIOF1_MCK0, GPIO_FN_I2C_SDA2, GPIO_FN_PORT236_FSIAIBT,
-	GPIO_FN_MSIOF1_MCK1, GPIO_FN_I2C_SCL2, GPIO_FN_PORT237_FSIAISLD,
-	GPIO_FN_MSIOF1_SS1, GPIO_FN_EDBGREQ3,
-
-	/* 55-5 (FN) */
-	GPIO_FN_MSIOF1_SS2,
-	GPIO_FN_SCIFA6_TXD,
-	GPIO_FN_PORT241_IRDA_OUT, GPIO_FN_PORT241_IROUT, GPIO_FN_MFG4_OUT1,
-	GPIO_FN_TPU4TO0,
-	GPIO_FN_PORT242_IRDA_IN, GPIO_FN_MFG4_IN2,
-	GPIO_FN_PORT243_IRDA_FIRSEL, GPIO_FN_PORT243_VIO_CKO2,
-	GPIO_FN_PORT244_SCIFA5_CTS, GPIO_FN_MFG2_IN1, GPIO_FN_PORT244_SCIFB_CTS,
-	GPIO_FN_PORT244_MSIOF2_RXD,
-	GPIO_FN_PORT245_SCIFA5_RTS, GPIO_FN_MFG2_IN2, GPIO_FN_PORT245_SCIFB_RTS,
-	GPIO_FN_PORT245_MSIOF2_TXD,
-	GPIO_FN_PORT246_SCIFA5_RXD, GPIO_FN_MFG1_OUT1,
-	GPIO_FN_PORT246_SCIFB_RXD, GPIO_FN_TPU1TO0,
-	GPIO_FN_PORT247_SCIFA5_TXD, GPIO_FN_MFG3_OUT2,
-	GPIO_FN_PORT247_SCIFB_TXD, GPIO_FN_TPU3TO1,
-	GPIO_FN_PORT248_SCIFA5_SCK, GPIO_FN_MFG2_OUT1,
-	GPIO_FN_PORT248_SCIFB_SCK, GPIO_FN_TPU2TO0,
-	GPIO_FN_PORT248_MSIOF2_TSCK,
-	GPIO_FN_PORT249_IROUT, GPIO_FN_MFG4_IN1, GPIO_FN_PORT249_MSIOF2_TSYNC,
-	GPIO_FN_SDHICLK0, GPIO_FN_TCK2_SWCLK_MC0,
-	GPIO_FN_SDHICD0,
-	GPIO_FN_SDHID0_0, GPIO_FN_TMS2_SWDIO_MC0,
-	GPIO_FN_SDHID0_1, GPIO_FN_TDO2_SWO0_MC0,
-	GPIO_FN_SDHID0_2, GPIO_FN_TDI2,
-	GPIO_FN_SDHID0_3, GPIO_FN_RTCK2_SWO1_MC0,
-	GPIO_FN_SDHICMD0, GPIO_FN_TRST2,
-	GPIO_FN_SDHIWP0, GPIO_FN_EDBGREQ2,
-	GPIO_FN_SDHICLK1, GPIO_FN_TCK3_SWCLK_MC1,
-	GPIO_FN_SDHID1_0, GPIO_FN_M11_SLCD_SO2, GPIO_FN_TS_SPSYNC2,
-	GPIO_FN_TMS3_SWDIO_MC1,
-	GPIO_FN_SDHID1_1, GPIO_FN_M9_SLCD_A02, GPIO_FN_TS_SDAT2,
-	GPIO_FN_TDO3_SWO0_MC1,
-	GPIO_FN_SDHID1_2, GPIO_FN_M10_SLCD_CK2, GPIO_FN_TS_SDEN2, GPIO_FN_TDI3,
-	GPIO_FN_SDHID1_3, GPIO_FN_M12_SLCD_CE2, GPIO_FN_TS_SCK2,
-	GPIO_FN_RTCK3_SWO1_MC1,
-	GPIO_FN_SDHICMD1, GPIO_FN_TRST3,
-	GPIO_FN_RESETOUTS,
-};
-
-#endif /* __ASM_SH7377_H__ */
diff --git a/arch/arm/mach-shmobile/intc-sh7367.c b/arch/arm/mach-shmobile/intc-sh7367.c
deleted file mode 100644
index 5bf7764..0000000
--- a/arch/arm/mach-shmobile/intc-sh7367.c
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- * sh7367 processor support - INTC hardware block
- *
- * Copyright (C) 2010  Magnus Damm
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/sh_intc.h>
-#include <mach/intc.h>
-#include <mach/irqs.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-enum {
-	UNUSED_INTCA = 0,
-	ENABLED,
-	DISABLED,
-
-	/* interrupt sources INTCA */
-	DIRC,
-	CRYPT1_ERR, CRYPT2_STD,
-	IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1,
-	ARM11_IRQPMU, ARM11_COMMTX, ARM11_COMMRX,
-	ETM11_ACQCMP, ETM11_FULL,
-	MFI_MFIM, MFI_MFIS,
-	BBIF1, BBIF2,
-	USBDMAC_USHDMI,
-	USBHS_USHI0, USBHS_USHI1,
-	CMT1_CMT10, CMT1_CMT11, CMT1_CMT12, CMT1_CMT13, CMT2, CMT3,
-	KEYSC_KEY,
-	SCIFA0, SCIFA1, SCIFA2, SCIFA3,
-	MSIOF2, MSIOF1,
-	SCIFA4, SCIFA5, SCIFB,
-	FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
-	SDHI0,
-	SDHI1,
-	MSU_MSU, MSU_MSU2,
-	IREM,
-	SIU,
-	SPU,
-	IRDA,
-	TPU0, TPU1, TPU2, TPU3, TPU4,
-	LCRC,
-	PINT1, PINT2,
-	TTI20,
-	MISTY,
-	DDM,
-	SDHI2,
-	RWDT0, RWDT1,
-	DMAC_1_DEI0, DMAC_1_DEI1, DMAC_1_DEI2, DMAC_1_DEI3,
-	DMAC_2_DEI4, DMAC_2_DEI5, DMAC_2_DADERR,
-	DMAC2_1_DEI0, DMAC2_1_DEI1, DMAC2_1_DEI2, DMAC2_1_DEI3,
-	DMAC2_2_DEI4, DMAC2_2_DEI5, DMAC2_2_DADERR,
-	DMAC3_1_DEI0, DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3,
-	DMAC3_2_DEI4, DMAC3_2_DEI5, DMAC3_2_DADERR,
-
-	/* interrupt groups INTCA */
-	DMAC_1, DMAC_2,	DMAC2_1, DMAC2_2, DMAC3_1, DMAC3_2,
-	ETM11, ARM11, USBHS, FLCTL, IIC1
-};
-
-static struct intc_vect intca_vectors[] __initdata = {
-	INTC_VECT(DIRC, 0x0560),
-	INTC_VECT(CRYPT1_ERR, 0x05e0),
-	INTC_VECT(CRYPT2_STD, 0x0700),
-	INTC_VECT(IIC1_ALI1, 0x0780), INTC_VECT(IIC1_TACKI1, 0x07a0),
-	INTC_VECT(IIC1_WAITI1, 0x07c0), INTC_VECT(IIC1_DTEI1, 0x07e0),
-	INTC_VECT(ARM11_IRQPMU, 0x0800), INTC_VECT(ARM11_COMMTX, 0x0840),
-	INTC_VECT(ARM11_COMMRX, 0x0860),
-	INTC_VECT(ETM11_ACQCMP, 0x0880), INTC_VECT(ETM11_FULL, 0x08a0),
-	INTC_VECT(MFI_MFIM, 0x0900), INTC_VECT(MFI_MFIS, 0x0920),
-	INTC_VECT(BBIF1, 0x0940), INTC_VECT(BBIF2, 0x0960),
-	INTC_VECT(USBDMAC_USHDMI, 0x0a00),
-	INTC_VECT(USBHS_USHI0, 0x0a20), INTC_VECT(USBHS_USHI1, 0x0a40),
-	INTC_VECT(CMT1_CMT10, 0x0b00), INTC_VECT(CMT1_CMT11, 0x0b20),
-	INTC_VECT(CMT1_CMT12, 0x0b40), INTC_VECT(CMT1_CMT13, 0x0b60),
-	INTC_VECT(CMT2, 0x0b80), INTC_VECT(CMT3, 0x0ba0),
-	INTC_VECT(KEYSC_KEY, 0x0be0),
-	INTC_VECT(SCIFA0, 0x0c00), INTC_VECT(SCIFA1, 0x0c20),
-	INTC_VECT(SCIFA2, 0x0c40), INTC_VECT(SCIFA3, 0x0c60),
-	INTC_VECT(MSIOF2, 0x0c80), INTC_VECT(MSIOF1, 0x0d00),
-	INTC_VECT(SCIFA4, 0x0d20), INTC_VECT(SCIFA5, 0x0d40),
-	INTC_VECT(SCIFB, 0x0d60),
-	INTC_VECT(FLCTL_FLSTEI, 0x0d80), INTC_VECT(FLCTL_FLTENDI, 0x0da0),
-	INTC_VECT(FLCTL_FLTREQ0I, 0x0dc0), INTC_VECT(FLCTL_FLTREQ1I, 0x0de0),
-	INTC_VECT(SDHI0, 0x0e00), INTC_VECT(SDHI0, 0x0e20),
-	INTC_VECT(SDHI0, 0x0e40), INTC_VECT(SDHI0, 0x0e60),
-	INTC_VECT(SDHI1, 0x0e80), INTC_VECT(SDHI1, 0x0ea0),
-	INTC_VECT(SDHI1, 0x0ec0), INTC_VECT(SDHI1, 0x0ee0),
-	INTC_VECT(MSU_MSU, 0x0f20), INTC_VECT(MSU_MSU2, 0x0f40),
-	INTC_VECT(IREM, 0x0f60),
-	INTC_VECT(SIU, 0x0fa0),
-	INTC_VECT(SPU, 0x0fc0),
-	INTC_VECT(IRDA, 0x0480),
-	INTC_VECT(TPU0, 0x04a0), INTC_VECT(TPU1, 0x04c0),
-	INTC_VECT(TPU2, 0x04e0), INTC_VECT(TPU3, 0x0500),
-	INTC_VECT(TPU4, 0x0520),
-	INTC_VECT(LCRC, 0x0540),
-	INTC_VECT(PINT1, 0x1000), INTC_VECT(PINT2, 0x1020),
-	INTC_VECT(TTI20, 0x1100),
-	INTC_VECT(MISTY, 0x1120),
-	INTC_VECT(DDM, 0x1140),
-	INTC_VECT(SDHI2, 0x1200), INTC_VECT(SDHI2, 0x1220),
-	INTC_VECT(SDHI2, 0x1240), INTC_VECT(SDHI2, 0x1260),
-	INTC_VECT(RWDT0, 0x1280), INTC_VECT(RWDT1, 0x12a0),
-	INTC_VECT(DMAC_1_DEI0, 0x2000), INTC_VECT(DMAC_1_DEI1, 0x2020),
-	INTC_VECT(DMAC_1_DEI2, 0x2040), INTC_VECT(DMAC_1_DEI3, 0x2060),
-	INTC_VECT(DMAC_2_DEI4, 0x2080), INTC_VECT(DMAC_2_DEI5, 0x20a0),
-	INTC_VECT(DMAC_2_DADERR, 0x20c0),
-	INTC_VECT(DMAC2_1_DEI0, 0x2100), INTC_VECT(DMAC2_1_DEI1, 0x2120),
-	INTC_VECT(DMAC2_1_DEI2, 0x2140), INTC_VECT(DMAC2_1_DEI3, 0x2160),
-	INTC_VECT(DMAC2_2_DEI4, 0x2180), INTC_VECT(DMAC2_2_DEI5, 0x21a0),
-	INTC_VECT(DMAC2_2_DADERR, 0x21c0),
-	INTC_VECT(DMAC3_1_DEI0, 0x2200), INTC_VECT(DMAC3_1_DEI1, 0x2220),
-	INTC_VECT(DMAC3_1_DEI2, 0x2240), INTC_VECT(DMAC3_1_DEI3, 0x2260),
-	INTC_VECT(DMAC3_2_DEI4, 0x2280), INTC_VECT(DMAC3_2_DEI5, 0x22a0),
-	INTC_VECT(DMAC3_2_DADERR, 0x22c0),
-};
-
-static struct intc_group intca_groups[] __initdata = {
-	INTC_GROUP(DMAC_1, DMAC_1_DEI0,
-		   DMAC_1_DEI1, DMAC_1_DEI2, DMAC_1_DEI3),
-	INTC_GROUP(DMAC_2, DMAC_2_DEI4,
-		   DMAC_2_DEI5, DMAC_2_DADERR),
-	INTC_GROUP(DMAC2_1, DMAC2_1_DEI0,
-		   DMAC2_1_DEI1, DMAC2_1_DEI2, DMAC2_1_DEI3),
-	INTC_GROUP(DMAC2_2, DMAC2_2_DEI4,
-		   DMAC2_2_DEI5, DMAC2_2_DADERR),
-	INTC_GROUP(DMAC3_1, DMAC3_1_DEI0,
-		   DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3),
-	INTC_GROUP(DMAC3_2, DMAC3_2_DEI4,
-		   DMAC3_2_DEI5, DMAC3_2_DADERR),
-	INTC_GROUP(ETM11, ETM11_ACQCMP, ETM11_FULL),
-	INTC_GROUP(ARM11, ARM11_IRQPMU, ARM11_COMMTX, ARM11_COMMTX),
-	INTC_GROUP(USBHS, USBHS_USHI0, USBHS_USHI1),
-	INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLTENDI,
-		   FLCTL_FLTREQ0I, FLCTL_FLTREQ1I),
-	INTC_GROUP(IIC1, IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1),
-};
-
-static struct intc_mask_reg intca_mask_registers[] __initdata = {
-	{ 0xe6940080, 0xe69400c0, 8, /* IMR0A / IMCR0A */
-	  { DMAC2_1_DEI3, DMAC2_1_DEI2, DMAC2_1_DEI1, DMAC2_1_DEI0,
-	    ARM11_IRQPMU, 0, ARM11_COMMTX, ARM11_COMMRX } },
-	{ 0xe6940084, 0xe69400c4, 8, /* IMR1A / IMCR1A */
-	  { CRYPT1_ERR, CRYPT2_STD, DIRC, 0,
-	    DMAC_1_DEI3, DMAC_1_DEI2, DMAC_1_DEI1, DMAC_1_DEI0 } },
-	{ 0xe6940088, 0xe69400c8, 8, /* IMR2A / IMCR2A */
-	  { PINT1, PINT2, 0, 0,
-	    BBIF1, BBIF2, MFI_MFIS, MFI_MFIM } },
-	{ 0xe694008c, 0xe69400cc, 8, /* IMR3A / IMCR3A */
-	  { DMAC3_1_DEI3, DMAC3_1_DEI2, DMAC3_1_DEI1, DMAC3_1_DEI0,
-	    DMAC3_2_DADERR, DMAC3_2_DEI5, DMAC3_2_DEI4, IRDA } },
-	{ 0xe6940090, 0xe69400d0, 8, /* IMR4A / IMCR4A */
-	  { DDM, 0, 0, 0,
-	    0, 0, ETM11_FULL, ETM11_ACQCMP } },
-	{ 0xe6940094, 0xe69400d4, 8, /* IMR5A / IMCR5A */
-	  { KEYSC_KEY, DMAC_2_DADERR, DMAC_2_DEI5, DMAC_2_DEI4,
-	    SCIFA3, SCIFA2, SCIFA1, SCIFA0 } },
-	{ 0xe6940098, 0xe69400d8, 8, /* IMR6A / IMCR6A */
-	  { SCIFB, SCIFA5, SCIFA4, MSIOF1,
-	    0, 0, MSIOF2, 0 } },
-	{ 0xe694009c, 0xe69400dc, 8, /* IMR7A / IMCR7A */
-	  { DISABLED, ENABLED, ENABLED, ENABLED,
-	    FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } },
-	{ 0xe69400a0, 0xe69400e0, 8, /* IMR8A / IMCR8A */
-	  { DISABLED, ENABLED, ENABLED, ENABLED,
-	    TTI20, USBDMAC_USHDMI, SPU, SIU } },
-	{ 0xe69400a4, 0xe69400e4, 8, /* IMR9A / IMCR9A */
-	  { CMT1_CMT13, CMT1_CMT12, CMT1_CMT11, CMT1_CMT10,
-	    CMT2, USBHS_USHI1, USBHS_USHI0, 0 } },
-	{ 0xe69400a8, 0xe69400e8, 8, /* IMR10A / IMCR10A */
-	  { 0, DMAC2_2_DADERR, DMAC2_2_DEI5, DMAC2_2_DEI4,
-	    0, 0, 0, 0 } },
-	{ 0xe69400ac, 0xe69400ec, 8, /* IMR11A / IMCR11A */
-	  { IIC1_DTEI1, IIC1_WAITI1, IIC1_TACKI1, IIC1_ALI1,
-	    LCRC, MSU_MSU2, IREM, MSU_MSU } },
-	{ 0xe69400b0, 0xe69400f0, 8, /* IMR12A / IMCR12A */
-	  { 0, 0, TPU0, TPU1,
-	    TPU2, TPU3, TPU4, 0 } },
-	{ 0xe69400b4, 0xe69400f4, 8, /* IMR13A / IMCR13A */
-	  { DISABLED, ENABLED, ENABLED, ENABLED,
-	    MISTY, CMT3, RWDT1, RWDT0 } },
-};
-
-static struct intc_prio_reg intca_prio_registers[] __initdata = {
-	{ 0xe6940000, 0, 16, 4, /* IPRAA */ { DMAC3_1, DMAC3_2, CMT2, LCRC } },
-	{ 0xe6940004, 0, 16, 4, /* IPRBA */ { IRDA, ETM11, BBIF1, BBIF2 } },
-	{ 0xe6940008, 0, 16, 4, /* IPRCA */ { CRYPT1_ERR, CRYPT2_STD,
-					      CMT1_CMT11, ARM11 } },
-	{ 0xe694000c, 0, 16, 4, /* IPRDA */ { PINT1, PINT2,
-					      CMT1_CMT12, TPU4 } },
-	{ 0xe6940010, 0, 16, 4, /* IPREA */ { DMAC_1, MFI_MFIS,
-					      MFI_MFIM, USBHS } },
-	{ 0xe6940014, 0, 16, 4, /* IPRFA */ { KEYSC_KEY, DMAC_2,
-					      0, CMT1_CMT10 } },
-	{ 0xe6940018, 0, 16, 4, /* IPRGA */ { SCIFA0, SCIFA1,
-					      SCIFA2, SCIFA3 } },
-	{ 0xe694001c, 0, 16, 4, /* IPRGH */ { MSIOF2, USBDMAC_USHDMI,
-					      FLCTL, SDHI0 } },
-	{ 0xe6940020, 0, 16, 4, /* IPRIA */ { MSIOF1, SCIFA4, MSU_MSU, IIC1 } },
-	{ 0xe6940024, 0, 16, 4, /* IPRJA */ { DMAC2_1, DMAC2_2, SIU, TTI20 } },
-	{ 0xe6940028, 0, 16, 4, /* IPRKA */ { 0, CMT1_CMT13, IREM, SDHI1 } },
-	{ 0xe694002c, 0, 16, 4, /* IPRLA */ { TPU0, TPU1, TPU2, TPU3 } },
-	{ 0xe6940030, 0, 16, 4, /* IPRMA */ { MISTY, CMT3, RWDT1, RWDT0 } },
-	{ 0xe6940034, 0, 16, 4, /* IPRNA */ { SCIFB, SCIFA5, SPU, DDM } },
-	{ 0xe6940038, 0, 16, 4, /* IPROA */ { 0, 0, DIRC, SDHI2 } },
-};
-
-static struct intc_desc intca_desc __initdata = {
-	.name = "sh7367-intca",
-	.force_enable = ENABLED,
-	.force_disable = DISABLED,
-	.hw = INTC_HW_DESC(intca_vectors, intca_groups,
-			   intca_mask_registers, intca_prio_registers,
-			   NULL, NULL),
-};
-
-INTC_IRQ_PINS_16(intca_irq_pins, 0xe6900000,
-		 INTC_VECT, "sh7367-intca-irq-pins");
-
-enum {
-	UNUSED_INTCS = 0,
-
-	INTCS,
-
-	/* interrupt sources INTCS */
-	VIO2_VEU0, VIO2_VEU1, VIO2_VEU2, VIO2_VEU3,
-	VIO3_VOU,
-	RTDMAC_1_DEI0, RTDMAC_1_DEI1, RTDMAC_1_DEI2, RTDMAC_1_DEI3,
-	VIO1_CEU, VIO1_BEU0, VIO1_BEU1, VIO1_BEU2,
-	VPU,
-	SGX530,
-	_2DDMAC_2DDM0, _2DDMAC_2DDM1, _2DDMAC_2DDM2, _2DDMAC_2DDM3,
-	IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2,
-	IPMMU_IPMMUB, IPMMU_IPMMUS,
-	RTDMAC_2_DEI4, RTDMAC_2_DEI5, RTDMAC_2_DADERR,
-	MSIOF,
-	IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0,
-	TMU_TUNI0, TMU_TUNI1, TMU_TUNI2,
-	CMT,
-	TSIF,
-	IPMMUI,
-	MVI3,
-	ICB,
-	PEP,
-	ASA,
-	BEM,
-	VE2HO,
-	HQE,
-	JPEG,
-	LCDC,
-
-	/* interrupt groups INTCS */
-	_2DDMAC, RTDMAC_1, RTDMAC_2, VEU, BEU, IIC0, IPMMU, IIC2,
-};
-
-static struct intc_vect intcs_vectors[] = {
-	INTCS_VECT(VIO2_VEU0, 0x700), INTCS_VECT(VIO2_VEU1, 0x720),
-	INTCS_VECT(VIO2_VEU2, 0x740), INTCS_VECT(VIO2_VEU3, 0x760),
-	INTCS_VECT(VIO3_VOU, 0x780),
-	INTCS_VECT(RTDMAC_1_DEI0, 0x800), INTCS_VECT(RTDMAC_1_DEI1, 0x820),
-	INTCS_VECT(RTDMAC_1_DEI2, 0x840), INTCS_VECT(RTDMAC_1_DEI3, 0x860),
-	INTCS_VECT(VIO1_CEU, 0x880), INTCS_VECT(VIO1_BEU0, 0x8a0),
-	INTCS_VECT(VIO1_BEU1, 0x8c0), INTCS_VECT(VIO1_BEU2, 0x8e0),
-	INTCS_VECT(VPU, 0x980),
-	INTCS_VECT(SGX530, 0x9e0),
-	INTCS_VECT(_2DDMAC_2DDM0, 0xa00), INTCS_VECT(_2DDMAC_2DDM1, 0xa20),
-	INTCS_VECT(_2DDMAC_2DDM2, 0xa40), INTCS_VECT(_2DDMAC_2DDM3, 0xa60),
-	INTCS_VECT(IIC2_ALI2, 0xa80), INTCS_VECT(IIC2_TACKI2, 0xaa0),
-	INTCS_VECT(IIC2_WAITI2, 0xac0), INTCS_VECT(IIC2_DTEI2, 0xae0),
-	INTCS_VECT(IPMMU_IPMMUB, 0xb20), INTCS_VECT(IPMMU_IPMMUS, 0xb60),
-	INTCS_VECT(RTDMAC_2_DEI4, 0xb80), INTCS_VECT(RTDMAC_2_DEI5, 0xba0),
-	INTCS_VECT(RTDMAC_2_DADERR, 0xbc0),
-	INTCS_VECT(MSIOF, 0xd20),
-	INTCS_VECT(IIC0_ALI0, 0xe00), INTCS_VECT(IIC0_TACKI0, 0xe20),
-	INTCS_VECT(IIC0_WAITI0, 0xe40), INTCS_VECT(IIC0_DTEI0, 0xe60),
-	INTCS_VECT(TMU_TUNI0, 0xe80), INTCS_VECT(TMU_TUNI1, 0xea0),
-	INTCS_VECT(TMU_TUNI2, 0xec0),
-	INTCS_VECT(CMT, 0xf00),
-	INTCS_VECT(TSIF, 0xf20),
-	INTCS_VECT(IPMMUI, 0xf60),
-	INTCS_VECT(MVI3, 0x420),
-	INTCS_VECT(ICB, 0x480),
-	INTCS_VECT(PEP, 0x4a0),
-	INTCS_VECT(ASA, 0x4c0),
-	INTCS_VECT(BEM, 0x4e0),
-	INTCS_VECT(VE2HO, 0x520),
-	INTCS_VECT(HQE, 0x540),
-	INTCS_VECT(JPEG, 0x560),
-	INTCS_VECT(LCDC, 0x580),
-
-	INTC_VECT(INTCS, 0xf80),
-};
-
-static struct intc_group intcs_groups[] __initdata = {
-	INTC_GROUP(_2DDMAC, _2DDMAC_2DDM0, _2DDMAC_2DDM1,
-		   _2DDMAC_2DDM2, _2DDMAC_2DDM3),
-	INTC_GROUP(RTDMAC_1, RTDMAC_1_DEI0, RTDMAC_1_DEI1,
-		   RTDMAC_1_DEI2, RTDMAC_1_DEI3),
-	INTC_GROUP(RTDMAC_2, RTDMAC_2_DEI4, RTDMAC_2_DEI5, RTDMAC_2_DADERR),
-	INTC_GROUP(VEU, VIO2_VEU0, VIO2_VEU1, VIO2_VEU2, VIO2_VEU3),
-	INTC_GROUP(BEU, VIO1_BEU0, VIO1_BEU1, VIO1_BEU2),
-	INTC_GROUP(IIC0, IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0),
-	INTC_GROUP(IPMMU, IPMMU_IPMMUS, IPMMU_IPMMUB),
-	INTC_GROUP(IIC2, IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2),
-};
-
-static struct intc_mask_reg intcs_mask_registers[] = {
-	{ 0xffd20184, 0xffd201c4, 8, /* IMR1SA / IMCR1SA */
-	  { VIO1_BEU2, VIO1_BEU1, VIO1_BEU0, VIO1_CEU,
-	    VIO2_VEU3, VIO2_VEU2, VIO2_VEU1, VIO2_VEU0 } },
-	{ 0xffd20188, 0xffd201c8, 8, /* IMR2SA / IMCR2SA */
-	  { VIO3_VOU, 0, VE2HO, VPU,
-	    0, 0, 0, 0 } },
-	{ 0xffd2018c, 0xffd201cc, 8, /* IMR3SA / IMCR3SA */
-	  { _2DDMAC_2DDM3, _2DDMAC_2DDM2, _2DDMAC_2DDM1, _2DDMAC_2DDM0,
-	    BEM, ASA, PEP, ICB } },
-	{ 0xffd20190, 0xffd201d0, 8, /* IMR4SA / IMCR4SA */
-	  { 0, 0, MVI3, 0,
-	    JPEG, HQE, 0, LCDC } },
-	{ 0xffd20194, 0xffd201d4, 8, /* IMR5SA / IMCR5SA */
-	  { 0, RTDMAC_2_DADERR, RTDMAC_2_DEI5, RTDMAC_2_DEI4,
-	    RTDMAC_1_DEI3, RTDMAC_1_DEI2, RTDMAC_1_DEI1, RTDMAC_1_DEI0 } },
-	{ 0xffd20198, 0xffd201d8, 8, /* IMR6SA / IMCR6SA */
-	  { 0, 0, MSIOF, 0,
-	    SGX530, 0, 0, 0 } },
-	{ 0xffd2019c, 0xffd201dc, 8, /* IMR7SA / IMCR7SA */
-	  { 0, TMU_TUNI2, TMU_TUNI1, TMU_TUNI0,
-	    0, 0, 0, 0 } },
-	{ 0xffd201a4, 0xffd201e4, 8, /* IMR9SA / IMCR9SA */
-	  { 0, 0, 0, CMT,
-	    IIC2_DTEI2, IIC2_WAITI2, IIC2_TACKI2, IIC2_ALI2 } },
-	{ 0xffd201a8, 0xffd201e8, 8, /* IMR10SA / IMCR10SA */
-	  { IPMMU_IPMMUS, 0, IPMMU_IPMMUB, 0,
-	    0, 0, 0, 0 } },
-	{ 0xffd201ac, 0xffd201ec, 8, /* IMR11SA / IMCR11SA */
-	  { IIC0_DTEI0, IIC0_WAITI0, IIC0_TACKI0, IIC0_ALI0,
-	    0, 0, IPMMUI, TSIF } },
-	{ 0xffd20104, 0, 16, /* INTAMASK */
-	  { 0, 0, 0, 0, 0, 0, 0, 0,
-	    0, 0, 0, 0, 0, 0, 0, INTCS } },
-};
-
-/* Priority is needed for INTCA to receive the INTCS interrupt */
-static struct intc_prio_reg intcs_prio_registers[] = {
-	{ 0xffd20000, 0, 16, 4, /* IPRAS */ { 0, MVI3, _2DDMAC, ICB } },
-	{ 0xffd20004, 0, 16, 4, /* IPRBS */ { JPEG, LCDC, 0, 0 } },
-	{ 0xffd20008, 0, 16, 4, /* IPRCS */ { BBIF2, 0, 0, 0 } },
-	{ 0xffd20010, 0, 16, 4, /* IPRES */ { RTDMAC_1, VIO1_CEU, 0, VPU } },
-	{ 0xffd20014, 0, 16, 4, /* IPRFS */ { 0, RTDMAC_2, 0, CMT } },
-	{ 0xffd20018, 0, 16, 4, /* IPRGS */ { TMU_TUNI0, TMU_TUNI1,
-					      TMU_TUNI2, 0 } },
-	{ 0xffd2001c, 0, 16, 4, /* IPRHS */ { 0, VIO3_VOU, VEU, BEU } },
-	{ 0xffd20020, 0, 16, 4, /* IPRIS */ { 0, MSIOF, TSIF, IIC0 } },
-	{ 0xffd20024, 0, 16, 4, /* IPRJS */ { 0, SGX530, 0, 0 } },
-	{ 0xffd20028, 0, 16, 4, /* IPRKS */ { BEM, ASA, IPMMUI, PEP } },
-	{ 0xffd2002c, 0, 16, 4, /* IPRLS */ { IPMMU, 0, VE2HO, HQE } },
-	{ 0xffd20030, 0, 16, 4, /* IPRMS */ { IIC2, 0, 0, 0 } },
-};
-
-static struct resource intcs_resources[] __initdata = {
-	[0] = {
-		.start	= 0xffd20000,
-		.end	= 0xffd2ffff,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct intc_desc intcs_desc __initdata = {
-	.name = "sh7367-intcs",
-	.resource = intcs_resources,
-	.num_resources = ARRAY_SIZE(intcs_resources),
-	.hw = INTC_HW_DESC(intcs_vectors, intcs_groups, intcs_mask_registers,
-			   intcs_prio_registers, NULL, NULL),
-};
-
-static void intcs_demux(unsigned int irq, struct irq_desc *desc)
-{
-	void __iomem *reg = (void *)irq_get_handler_data(irq);
-	unsigned int evtcodeas = ioread32(reg);
-
-	generic_handle_irq(intcs_evt2irq(evtcodeas));
-}
-
-void __init sh7367_init_irq(void)
-{
-	void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
-
-	register_intc_controller(&intca_desc);
-	register_intc_controller(&intca_irq_pins_desc);
-	register_intc_controller(&intcs_desc);
-
-	/* demux using INTEVTSA */
-	irq_set_handler_data(evt2irq(0xf80), (void *)intevtsa);
-	irq_set_chained_handler(evt2irq(0xf80), intcs_demux);
-}
diff --git a/arch/arm/mach-shmobile/intc-sh7377.c b/arch/arm/mach-shmobile/intc-sh7377.c
deleted file mode 100644
index b84a460..0000000
--- a/arch/arm/mach-shmobile/intc-sh7377.c
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * sh7377 processor support - INTC hardware block
- *
- * Copyright (C) 2010  Magnus Damm
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/sh_intc.h>
-#include <mach/intc.h>
-#include <mach/irqs.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-enum {
-	UNUSED_INTCA = 0,
-	ENABLED,
-	DISABLED,
-
-	/* interrupt sources INTCA */
-	DIRC,
-	_2DG,
-	CRYPT_STD,
-	IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1,
-	AP_ARM_IRQPMU, AP_ARM_COMMTX, AP_ARM_COMMRX,
-	MFI_MFIM, MFI_MFIS,
-	BBIF1, BBIF2,
-	USBDMAC_USHDMI,
-	USBHS_USHI0, USBHS_USHI1,
-	_3DG_SGX540,
-	CMT1_CMT10, CMT1_CMT11, CMT1_CMT12, CMT1_CMT13, CMT2, CMT3,
-	KEYSC_KEY,
-	SCIFA0, SCIFA1, SCIFA2, SCIFA3,
-	MSIOF2, MSIOF1,
-	SCIFA4, SCIFA5, SCIFB,
-	FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
-	SDHI0,
-	SDHI1,
-	MSU_MSU, MSU_MSU2,
-	IRREM,
-	MSUG,
-	IRDA,
-	TPU0, TPU1, TPU2, TPU3, TPU4,
-	LCRC,
-	PINTCA_PINT1, PINTCA_PINT2,
-	TTI20,
-	MISTY,
-	DDM,
-	RWDT0, RWDT1,
-	DMAC_1_DEI0, DMAC_1_DEI1, DMAC_1_DEI2, DMAC_1_DEI3,
-	DMAC_2_DEI4, DMAC_2_DEI5, DMAC_2_DADERR,
-	DMAC2_1_DEI0, DMAC2_1_DEI1, DMAC2_1_DEI2, DMAC2_1_DEI3,
-	DMAC2_2_DEI4, DMAC2_2_DEI5, DMAC2_2_DADERR,
-	DMAC3_1_DEI0, DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3,
-	DMAC3_2_DEI4, DMAC3_2_DEI5, DMAC3_2_DADERR,
-	SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM,
-	ICUSB_ICUSB0, ICUSB_ICUSB1,
-	ICUDMC_ICUDMC1, ICUDMC_ICUDMC2,
-	SPU2_SPU0, SPU2_SPU1,
-	FSI,
-	FMSI,
-	SCUV,
-	IPMMU_IPMMUB,
-	AP_ARM_CTIIRQ, AP_ARM_DMAEXTERRIRQ, AP_ARM_DMAIRQ, AP_ARM_DMASIRQ,
-	MFIS2,
-	CPORTR2S,
-	CMT14, CMT15,
-	SCIFA6,
-
-	/* interrupt groups INTCA */
-	DMAC_1, DMAC_2,	DMAC2_1, DMAC2_2, DMAC3_1, DMAC3_2, SHWYSTAT,
-	AP_ARM1, AP_ARM2, USBHS, SPU2, FLCTL, IIC1,
-	ICUSB, ICUDMC
-};
-
-static struct intc_vect intca_vectors[] __initdata = {
-	INTC_VECT(DIRC, 0x0560),
-	INTC_VECT(_2DG, 0x05e0),
-	INTC_VECT(CRYPT_STD, 0x0700),
-	INTC_VECT(IIC1_ALI1, 0x0780), INTC_VECT(IIC1_TACKI1, 0x07a0),
-	INTC_VECT(IIC1_WAITI1, 0x07c0), INTC_VECT(IIC1_DTEI1, 0x07e0),
-	INTC_VECT(AP_ARM_IRQPMU, 0x0800), INTC_VECT(AP_ARM_COMMTX, 0x0840),
-	INTC_VECT(AP_ARM_COMMRX, 0x0860),
-	INTC_VECT(MFI_MFIM, 0x0900), INTC_VECT(MFI_MFIS, 0x0920),
-	INTC_VECT(BBIF1, 0x0940), INTC_VECT(BBIF2, 0x0960),
-	INTC_VECT(USBDMAC_USHDMI, 0x0a00),
-	INTC_VECT(USBHS_USHI0, 0x0a20), INTC_VECT(USBHS_USHI1, 0x0a40),
-	INTC_VECT(_3DG_SGX540, 0x0a60),
-	INTC_VECT(CMT1_CMT10, 0x0b00), INTC_VECT(CMT1_CMT11, 0x0b20),
-	INTC_VECT(CMT1_CMT12, 0x0b40), INTC_VECT(CMT1_CMT13, 0x0b60),
-	INTC_VECT(CMT2, 0x0b80), INTC_VECT(CMT3, 0x0ba0),
-	INTC_VECT(KEYSC_KEY, 0x0be0),
-	INTC_VECT(SCIFA0, 0x0c00), INTC_VECT(SCIFA1, 0x0c20),
-	INTC_VECT(SCIFA2, 0x0c40), INTC_VECT(SCIFA3, 0x0c60),
-	INTC_VECT(MSIOF2, 0x0c80), INTC_VECT(MSIOF1, 0x0d00),
-	INTC_VECT(SCIFA4, 0x0d20), INTC_VECT(SCIFA5, 0x0d40),
-	INTC_VECT(SCIFB, 0x0d60),
-	INTC_VECT(FLCTL_FLSTEI, 0x0d80), INTC_VECT(FLCTL_FLTENDI, 0x0da0),
-	INTC_VECT(FLCTL_FLTREQ0I, 0x0dc0), INTC_VECT(FLCTL_FLTREQ1I, 0x0de0),
-	INTC_VECT(SDHI0, 0x0e00), INTC_VECT(SDHI0, 0x0e20),
-	INTC_VECT(SDHI0, 0x0e40), INTC_VECT(SDHI0, 0x0e60),
-	INTC_VECT(SDHI1, 0x0e80), INTC_VECT(SDHI1, 0x0ea0),
-	INTC_VECT(SDHI1, 0x0ec0), INTC_VECT(SDHI1, 0x0ee0),
-	INTC_VECT(MSU_MSU, 0x0f20), INTC_VECT(MSU_MSU2, 0x0f40),
-	INTC_VECT(IRREM, 0x0f60),
-	INTC_VECT(MSUG, 0x0fa0),
-	INTC_VECT(IRDA, 0x0480),
-	INTC_VECT(TPU0, 0x04a0), INTC_VECT(TPU1, 0x04c0),
-	INTC_VECT(TPU2, 0x04e0), INTC_VECT(TPU3, 0x0500),
-	INTC_VECT(TPU4, 0x0520),
-	INTC_VECT(LCRC, 0x0540),
-	INTC_VECT(PINTCA_PINT1, 0x1000), INTC_VECT(PINTCA_PINT2, 0x1020),
-	INTC_VECT(TTI20, 0x1100),
-	INTC_VECT(MISTY, 0x1120),
-	INTC_VECT(DDM, 0x1140),
-	INTC_VECT(RWDT0, 0x1280), INTC_VECT(RWDT1, 0x12a0),
-	INTC_VECT(DMAC_1_DEI0, 0x2000), INTC_VECT(DMAC_1_DEI1, 0x2020),
-	INTC_VECT(DMAC_1_DEI2, 0x2040), INTC_VECT(DMAC_1_DEI3, 0x2060),
-	INTC_VECT(DMAC_2_DEI4, 0x2080), INTC_VECT(DMAC_2_DEI5, 0x20a0),
-	INTC_VECT(DMAC_2_DADERR, 0x20c0),
-	INTC_VECT(DMAC2_1_DEI0, 0x2100), INTC_VECT(DMAC2_1_DEI1, 0x2120),
-	INTC_VECT(DMAC2_1_DEI2, 0x2140), INTC_VECT(DMAC2_1_DEI3, 0x2160),
-	INTC_VECT(DMAC2_2_DEI4, 0x2180), INTC_VECT(DMAC2_2_DEI5, 0x21a0),
-	INTC_VECT(DMAC2_2_DADERR, 0x21c0),
-	INTC_VECT(DMAC3_1_DEI0, 0x2200), INTC_VECT(DMAC3_1_DEI1, 0x2220),
-	INTC_VECT(DMAC3_1_DEI2, 0x2240), INTC_VECT(DMAC3_1_DEI3, 0x2260),
-	INTC_VECT(DMAC3_2_DEI4, 0x2280), INTC_VECT(DMAC3_2_DEI5, 0x22a0),
-	INTC_VECT(DMAC3_2_DADERR, 0x22c0),
-	INTC_VECT(SHWYSTAT_RT, 0x1300), INTC_VECT(SHWYSTAT_HS, 0x1d20),
-	INTC_VECT(SHWYSTAT_COM, 0x1340),
-	INTC_VECT(ICUSB_ICUSB0, 0x1700), INTC_VECT(ICUSB_ICUSB1, 0x1720),
-	INTC_VECT(ICUDMC_ICUDMC1, 0x1780), INTC_VECT(ICUDMC_ICUDMC2, 0x17a0),
-	INTC_VECT(SPU2_SPU0, 0x1800), INTC_VECT(SPU2_SPU1, 0x1820),
-	INTC_VECT(FSI, 0x1840),
-	INTC_VECT(FMSI, 0x1860),
-	INTC_VECT(SCUV, 0x1880),
-	INTC_VECT(IPMMU_IPMMUB, 0x1900),
-	INTC_VECT(AP_ARM_CTIIRQ, 0x1980),
-	INTC_VECT(AP_ARM_DMAEXTERRIRQ, 0x19a0),
-	INTC_VECT(AP_ARM_DMAIRQ, 0x19c0),
-	INTC_VECT(AP_ARM_DMASIRQ, 0x19e0),
-	INTC_VECT(MFIS2, 0x1a00),
-	INTC_VECT(CPORTR2S, 0x1a20),
-	INTC_VECT(CMT14, 0x1a40), INTC_VECT(CMT15, 0x1a60),
-	INTC_VECT(SCIFA6, 0x1a80),
-};
-
-static struct intc_group intca_groups[] __initdata = {
-	INTC_GROUP(DMAC_1, DMAC_1_DEI0,
-		   DMAC_1_DEI1, DMAC_1_DEI2, DMAC_1_DEI3),
-	INTC_GROUP(DMAC_2, DMAC_2_DEI4,
-		   DMAC_2_DEI5, DMAC_2_DADERR),
-	INTC_GROUP(DMAC2_1, DMAC2_1_DEI0,
-		   DMAC2_1_DEI1, DMAC2_1_DEI2, DMAC2_1_DEI3),
-	INTC_GROUP(DMAC2_2, DMAC2_2_DEI4,
-		   DMAC2_2_DEI5, DMAC2_2_DADERR),
-	INTC_GROUP(DMAC3_1, DMAC3_1_DEI0,
-		   DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3),
-	INTC_GROUP(DMAC3_2, DMAC3_2_DEI4,
-		   DMAC3_2_DEI5, DMAC3_2_DADERR),
-	INTC_GROUP(AP_ARM1, AP_ARM_IRQPMU, AP_ARM_COMMTX, AP_ARM_COMMTX),
-	INTC_GROUP(USBHS, USBHS_USHI0, USBHS_USHI1),
-	INTC_GROUP(SPU2, SPU2_SPU0, SPU2_SPU1),
-	INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLTENDI,
-		   FLCTL_FLTREQ0I, FLCTL_FLTREQ1I),
-	INTC_GROUP(IIC1, IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1),
-	INTC_GROUP(SHWYSTAT, SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM),
-	INTC_GROUP(ICUSB, ICUSB_ICUSB0, ICUSB_ICUSB1),
-	INTC_GROUP(ICUDMC, ICUDMC_ICUDMC1, ICUDMC_ICUDMC2),
-};
-
-static struct intc_mask_reg intca_mask_registers[] __initdata = {
-	{ 0xe6940080, 0xe69400c0, 8, /* IMR0A / IMCR0A */
-	  { DMAC2_1_DEI3, DMAC2_1_DEI2, DMAC2_1_DEI1, DMAC2_1_DEI0,
-	    AP_ARM_IRQPMU, 0, AP_ARM_COMMTX, AP_ARM_COMMRX } },
-	{ 0xe6940084, 0xe69400c4, 8, /* IMR1A / IMCR1A */
-	  { _2DG, CRYPT_STD, DIRC, 0,
-	    DMAC_1_DEI3, DMAC_1_DEI2, DMAC_1_DEI1, DMAC_1_DEI0 } },
-	{ 0xe6940088, 0xe69400c8, 8, /* IMR2A / IMCR2A */
-	  { PINTCA_PINT1, PINTCA_PINT2, 0, 0,
-	    BBIF1, BBIF2, MFI_MFIS, MFI_MFIM } },
-	{ 0xe694008c, 0xe69400cc, 8, /* IMR3A / IMCR3A */
-	  { DMAC3_1_DEI3, DMAC3_1_DEI2, DMAC3_1_DEI1, DMAC3_1_DEI0,
-	    DMAC3_2_DADERR, DMAC3_2_DEI5, DMAC3_2_DEI4, IRDA } },
-	{ 0xe6940090, 0xe69400d0, 8, /* IMR4A / IMCR4A */
-	  { DDM, 0, 0, 0,
-	    0, 0, 0, 0 } },
-	{ 0xe6940094, 0xe69400d4, 8, /* IMR5A / IMCR5A */
-	  { KEYSC_KEY, DMAC_2_DADERR, DMAC_2_DEI5, DMAC_2_DEI4,
-	    SCIFA3, SCIFA2, SCIFA1, SCIFA0 } },
-	{ 0xe6940098, 0xe69400d8, 8, /* IMR6A / IMCR6A */
-	  { SCIFB, SCIFA5, SCIFA4, MSIOF1,
-	    0, 0, MSIOF2, 0 } },
-	{ 0xe694009c, 0xe69400dc, 8, /* IMR7A / IMCR7A */
-	  { DISABLED, ENABLED, ENABLED, ENABLED,
-	    FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } },
-	{ 0xe69400a0, 0xe69400e0, 8, /* IMR8A / IMCR8A */
-	  { DISABLED, ENABLED, ENABLED, ENABLED,
-	    TTI20, USBDMAC_USHDMI, 0, MSUG } },
-	{ 0xe69400a4, 0xe69400e4, 8, /* IMR9A / IMCR9A */
-	  { CMT1_CMT13, CMT1_CMT12, CMT1_CMT11, CMT1_CMT10,
-	    CMT2, USBHS_USHI1, USBHS_USHI0, _3DG_SGX540 } },
-	{ 0xe69400a8, 0xe69400e8, 8, /* IMR10A / IMCR10A */
-	  { 0, DMAC2_2_DADERR, DMAC2_2_DEI5, DMAC2_2_DEI4,
-	    0, 0, 0, 0 } },
-	{ 0xe69400ac, 0xe69400ec, 8, /* IMR11A / IMCR11A */
-	  { IIC1_DTEI1, IIC1_WAITI1, IIC1_TACKI1, IIC1_ALI1,
-	    LCRC, MSU_MSU2, IRREM, MSU_MSU } },
-	{ 0xe69400b0, 0xe69400f0, 8, /* IMR12A / IMCR12A */
-	  { 0, 0, TPU0, TPU1,
-	    TPU2, TPU3, TPU4, 0 } },
-	{ 0xe69400b4, 0xe69400f4, 8, /* IMR13A / IMCR13A */
-	  { 0, 0, 0, 0,
-	    MISTY, CMT3, RWDT1, RWDT0 } },
-	{ 0xe6950080, 0xe69500c0, 8, /* IMR0A3 / IMCR0A3 */
-	  { SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM, 0,
-	    0, 0, 0, 0 } },
-	{ 0xe6950090, 0xe69500d0, 8, /* IMR4A3 / IMCR4A3 */
-	  { ICUSB_ICUSB0, ICUSB_ICUSB1, 0, 0,
-	    ICUDMC_ICUDMC1, ICUDMC_ICUDMC2, 0, 0 } },
-	{ 0xe6950094, 0xe69500d4, 8, /* IMR5A3 / IMCR5A3 */
-	  { SPU2_SPU0, SPU2_SPU1, FSI, FMSI,
-	    SCUV, 0, 0, 0 } },
-	{ 0xe6950098, 0xe69500d8, 8, /* IMR6A3 / IMCR6A3 */
-	  { IPMMU_IPMMUB, 0, 0, 0,
-	    AP_ARM_CTIIRQ, AP_ARM_DMAEXTERRIRQ,
-	    AP_ARM_DMAIRQ, AP_ARM_DMASIRQ } },
-	{ 0xe695009c, 0xe69500dc, 8, /* IMR7A3 / IMCR7A3 */
-	  { MFIS2, CPORTR2S, CMT14, CMT15,
-	    SCIFA6, 0, 0, 0 } },
-};
-
-static struct intc_prio_reg intca_prio_registers[] __initdata = {
-	{ 0xe6940000, 0, 16, 4, /* IPRAA */ { DMAC3_1, DMAC3_2, CMT2, LCRC } },
-	{ 0xe6940004, 0, 16, 4, /* IPRBA */ { IRDA, 0, BBIF1, BBIF2 } },
-	{ 0xe6940008, 0, 16, 4, /* IPRCA */ { _2DG, CRYPT_STD,
-					      CMT1_CMT11, AP_ARM1 } },
-	{ 0xe694000c, 0, 16, 4, /* IPRDA */ { PINTCA_PINT1, PINTCA_PINT2,
-					      CMT1_CMT12, TPU4 } },
-	{ 0xe6940010, 0, 16, 4, /* IPREA */ { DMAC_1, MFI_MFIS,
-					      MFI_MFIM, USBHS } },
-	{ 0xe6940014, 0, 16, 4, /* IPRFA */ { KEYSC_KEY, DMAC_2,
-					      _3DG_SGX540, CMT1_CMT10 } },
-	{ 0xe6940018, 0, 16, 4, /* IPRGA */ { SCIFA0, SCIFA1,
-					      SCIFA2, SCIFA3 } },
-	{ 0xe694001c, 0, 16, 4, /* IPRGH */ { MSIOF2, USBDMAC_USHDMI,
-					      FLCTL, SDHI0 } },
-	{ 0xe6940020, 0, 16, 4, /* IPRIA */ { MSIOF1, SCIFA4, MSU_MSU, IIC1 } },
-	{ 0xe6940024, 0, 16, 4, /* IPRJA */ { DMAC2_1, DMAC2_2, MSUG, TTI20 } },
-	{ 0xe6940028, 0, 16, 4, /* IPRKA */ { 0, CMT1_CMT13, IRREM, SDHI1 } },
-	{ 0xe694002c, 0, 16, 4, /* IPRLA */ { TPU0, TPU1, TPU2, TPU3 } },
-	{ 0xe6940030, 0, 16, 4, /* IPRMA */ { MISTY, CMT3, RWDT1, RWDT0 } },
-	{ 0xe6940034, 0, 16, 4, /* IPRNA */ { SCIFB, SCIFA5, 0, DDM } },
-	{ 0xe6940038, 0, 16, 4, /* IPROA */ { 0, 0, DIRC, 0 } },
-	{ 0xe6950000, 0, 16, 4, /* IPRAA3 */ { SHWYSTAT, 0, 0, 0 } },
-	{ 0xe6950020, 0, 16, 4, /* IPRIA3 */ { ICUSB, 0, 0, 0 } },
-	{ 0xe6950024, 0, 16, 4, /* IPRJA3 */ { ICUDMC, 0, 0, 0 } },
-	{ 0xe6950028, 0, 16, 4, /* IPRKA3 */ { SPU2, 0, FSI, FMSI } },
-	{ 0xe695002c, 0, 16, 4, /* IPRLA3 */ { SCUV, 0, 0, 0 } },
-	{ 0xe6950030, 0, 16, 4, /* IPRMA3 */ { IPMMU_IPMMUB, 0, 0, 0 } },
-	{ 0xe6950034, 0, 16, 4, /* IPRNA3 */ { AP_ARM2, 0, 0, 0 } },
-	{ 0xe6950038, 0, 16, 4, /* IPROA3 */ { MFIS2, CPORTR2S,
-					       CMT14, CMT15 } },
-	{ 0xe694003c, 0, 16, 4, /* IPRPA3 */ { SCIFA6, 0, 0, 0 } },
-};
-
-static struct intc_desc intca_desc __initdata = {
-	.name = "sh7377-intca",
-	.force_enable = ENABLED,
-	.force_disable = DISABLED,
-	.hw = INTC_HW_DESC(intca_vectors, intca_groups,
-			   intca_mask_registers, intca_prio_registers,
-			   NULL, NULL),
-};
-
-INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
-		 INTC_VECT, "sh7377-intca-irq-pins");
-
-/* this macro ignore entry which is also in INTCA */
-#define __IGNORE(a...)
-#define __IGNORE0(a...) 0
-
-enum {
-	UNUSED_INTCS = 0,
-
-	INTCS,
-
-	/* interrupt sources INTCS */
-	VEU_VEU0, VEU_VEU1, VEU_VEU2, VEU_VEU3,
-	RTDMAC1_1_DEI0, RTDMAC1_1_DEI1, RTDMAC1_1_DEI2, RTDMAC1_1_DEI3,
-	CEU,
-	BEU_BEU0, BEU_BEU1, BEU_BEU2,
-	__IGNORE(MFI)
-	__IGNORE(BBIF2)
-	VPU,
-	TSIF1,
-	__IGNORE(SGX540)
-	_2DDMAC,
-	IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2,
-	IPMMU_IPMMUR, IPMMU_IPMMUR2,
-	RTDMAC1_2_DEI4, RTDMAC1_2_DEI5, RTDMAC1_2_DADERR,
-	__IGNORE(KEYSC)
-	__IGNORE(TTI20)
-	__IGNORE(MSIOF)
-	IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0,
-	TMU_TUNI0, TMU_TUNI1, TMU_TUNI2,
-	CMT0,
-	TSIF0,
-	__IGNORE(CMT2)
-	LMB,
-	__IGNORE(MSUG)
-	__IGNORE(MSU_MSU, MSU_MSU2)
-	__IGNORE(CTI)
-	MVI3,
-	__IGNORE(RWDT0)
-	__IGNORE(RWDT1)
-	ICB,
-	PEP,
-	ASA,
-	__IGNORE(_2DG)
-	HQE,
-	JPU,
-	LCDC0,
-	__IGNORE(LCRC)
-	RTDMAC2_1_DEI0, RTDMAC2_1_DEI1, RTDMAC2_1_DEI2, RTDMAC2_1_DEI3,
-	RTDMAC2_2_DEI4, RTDMAC2_2_DEI5, RTDMAC2_2_DADERR,
-	FRC,
-	LCDC1,
-	CSIRX,
-	DSITX_DSITX0, DSITX_DSITX1,
-	__IGNORE(SPU2_SPU0, SPU2_SPU1)
-	__IGNORE(FSI)
-	__IGNORE(FMSI)
-	__IGNORE(SCUV)
-	TMU1_TUNI10, TMU1_TUNI11, TMU1_TUNI12,
-	TSIF2,
-	CMT4,
-	__IGNORE(MFIS2)
-	CPORTS2R,
-
-	/* interrupt groups INTCS */
-	RTDMAC1_1, RTDMAC1_2, VEU, BEU, IIC0, __IGNORE(MSU) IPMMU,
-	IIC2, RTDMAC2_1, RTDMAC2_2, DSITX, __IGNORE(SPU2) TMU1,
-};
-
-#define INTCS_INTVECT 0x0F80
-static struct intc_vect intcs_vectors[] __initdata = {
-	INTCS_VECT(VEU_VEU0, 0x0700), INTCS_VECT(VEU_VEU1, 0x0720),
-	INTCS_VECT(VEU_VEU2, 0x0740), INTCS_VECT(VEU_VEU3, 0x0760),
-	INTCS_VECT(RTDMAC1_1_DEI0, 0x0800), INTCS_VECT(RTDMAC1_1_DEI1, 0x0820),
-	INTCS_VECT(RTDMAC1_1_DEI2, 0x0840), INTCS_VECT(RTDMAC1_1_DEI3, 0x0860),
-	INTCS_VECT(CEU, 0x0880),
-	INTCS_VECT(BEU_BEU0, 0x08A0),
-	INTCS_VECT(BEU_BEU1, 0x08C0),
-	INTCS_VECT(BEU_BEU2, 0x08E0),
-	__IGNORE(INTCS_VECT(MFI, 0x0900))
-	__IGNORE(INTCS_VECT(BBIF2, 0x0960))
-	INTCS_VECT(VPU, 0x0980),
-	INTCS_VECT(TSIF1, 0x09A0),
-	__IGNORE(INTCS_VECT(SGX540, 0x09E0))
-	INTCS_VECT(_2DDMAC, 0x0A00),
-	INTCS_VECT(IIC2_ALI2, 0x0A80), INTCS_VECT(IIC2_TACKI2, 0x0AA0),
-	INTCS_VECT(IIC2_WAITI2, 0x0AC0), INTCS_VECT(IIC2_DTEI2, 0x0AE0),
-	INTCS_VECT(IPMMU_IPMMUR, 0x0B00), INTCS_VECT(IPMMU_IPMMUR2, 0x0B20),
-	INTCS_VECT(RTDMAC1_2_DEI4, 0x0B80),
-	INTCS_VECT(RTDMAC1_2_DEI5, 0x0BA0),
-	INTCS_VECT(RTDMAC1_2_DADERR, 0x0BC0),
-	__IGNORE(INTCS_VECT(KEYSC 0x0BE0))
-	__IGNORE(INTCS_VECT(TTI20, 0x0C80))
-	__IGNORE(INTCS_VECT(MSIOF, 0x0D20))
-	INTCS_VECT(IIC0_ALI0, 0x0E00), INTCS_VECT(IIC0_TACKI0, 0x0E20),
-	INTCS_VECT(IIC0_WAITI0, 0x0E40), INTCS_VECT(IIC0_DTEI0, 0x0E60),
-	INTCS_VECT(TMU_TUNI0, 0x0E80),
-	INTCS_VECT(TMU_TUNI1, 0x0EA0),
-	INTCS_VECT(TMU_TUNI2, 0x0EC0),
-	INTCS_VECT(CMT0, 0x0F00),
-	INTCS_VECT(TSIF0, 0x0F20),
-	__IGNORE(INTCS_VECT(CMT2, 0x0F40))
-	INTCS_VECT(LMB, 0x0F60),
-	__IGNORE(INTCS_VECT(MSUG, 0x0F80))
-	__IGNORE(INTCS_VECT(MSU_MSU, 0x0FA0))
-	__IGNORE(INTCS_VECT(MSU_MSU2, 0x0FC0))
-	__IGNORE(INTCS_VECT(CTI, 0x0400))
-	INTCS_VECT(MVI3, 0x0420),
-	__IGNORE(INTCS_VECT(RWDT0, 0x0440))
-	__IGNORE(INTCS_VECT(RWDT1, 0x0460))
-	INTCS_VECT(ICB, 0x0480),
-	INTCS_VECT(PEP, 0x04A0),
-	INTCS_VECT(ASA, 0x04C0),
-	__IGNORE(INTCS_VECT(_2DG, 0x04E0))
-	INTCS_VECT(HQE, 0x0540),
-	INTCS_VECT(JPU, 0x0560),
-	INTCS_VECT(LCDC0, 0x0580),
-	__IGNORE(INTCS_VECT(LCRC, 0x05A0))
-	INTCS_VECT(RTDMAC2_1_DEI0, 0x1300), INTCS_VECT(RTDMAC2_1_DEI1, 0x1320),
-	INTCS_VECT(RTDMAC2_1_DEI2, 0x1340), INTCS_VECT(RTDMAC2_1_DEI3, 0x1360),
-	INTCS_VECT(RTDMAC2_2_DEI4, 0x1380), INTCS_VECT(RTDMAC2_2_DEI5, 0x13A0),
-	INTCS_VECT(RTDMAC2_2_DADERR, 0x13C0),
-	INTCS_VECT(FRC, 0x1700),
-	INTCS_VECT(LCDC1, 0x1780),
-	INTCS_VECT(CSIRX, 0x17A0),
-	INTCS_VECT(DSITX_DSITX0, 0x17C0), INTCS_VECT(DSITX_DSITX1, 0x17E0),
-	__IGNORE(INTCS_VECT(SPU2_SPU0, 0x1800))
-	__IGNORE(INTCS_VECT(SPU2_SPU1, 0x1820))
-	__IGNORE(INTCS_VECT(FSI, 0x1840))
-	__IGNORE(INTCS_VECT(FMSI, 0x1860))
-	__IGNORE(INTCS_VECT(SCUV, 0x1880))
-	INTCS_VECT(TMU1_TUNI10, 0x1900), INTCS_VECT(TMU1_TUNI11, 0x1920),
-	INTCS_VECT(TMU1_TUNI12, 0x1940),
-	INTCS_VECT(TSIF2, 0x1960),
-	INTCS_VECT(CMT4, 0x1980),
-	__IGNORE(INTCS_VECT(MFIS2, 0x1A00))
-	INTCS_VECT(CPORTS2R, 0x1A20),
-
-	INTC_VECT(INTCS, INTCS_INTVECT),
-};
-
-static struct intc_group intcs_groups[] __initdata = {
-	INTC_GROUP(RTDMAC1_1,
-		   RTDMAC1_1_DEI0, RTDMAC1_1_DEI1,
-		   RTDMAC1_1_DEI2, RTDMAC1_1_DEI3),
-	INTC_GROUP(RTDMAC1_2,
-		   RTDMAC1_2_DEI4, RTDMAC1_2_DEI5, RTDMAC1_2_DADERR),
-	INTC_GROUP(VEU, VEU_VEU0, VEU_VEU1, VEU_VEU2, VEU_VEU3),
-	INTC_GROUP(BEU, BEU_BEU0, BEU_BEU1, BEU_BEU2),
-	INTC_GROUP(IIC0, IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0),
-	__IGNORE(INTC_GROUP(MSU, MSU_MSU, MSU_MSU2))
-	INTC_GROUP(IPMMU, IPMMU_IPMMUR, IPMMU_IPMMUR2),
-	INTC_GROUP(IIC2, IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2),
-	INTC_GROUP(RTDMAC2_1,
-		   RTDMAC2_1_DEI0, RTDMAC2_1_DEI1,
-		   RTDMAC2_1_DEI2, RTDMAC2_1_DEI3),
-	INTC_GROUP(RTDMAC2_2, RTDMAC2_2_DEI4, RTDMAC2_2_DEI5, RTDMAC2_2_DADERR),
-	INTC_GROUP(DSITX, DSITX_DSITX0, DSITX_DSITX1),
-	__IGNORE(INTC_GROUP(SPU2, SPU2_SPU0, SPU2_SPU1))
-	INTC_GROUP(TMU1, TMU1_TUNI10, TMU1_TUNI11, TMU1_TUNI12),
-};
-
-static struct intc_mask_reg intcs_mask_registers[] __initdata = {
-	{ 0xE6940184, 0xE69401C4, 8, /* IMR1AS / IMCR1AS  */
-	  { BEU_BEU2, BEU_BEU1, BEU_BEU0, CEU,
-	    VEU_VEU3, VEU_VEU2, VEU_VEU1, VEU_VEU0 } },
-	{ 0xE6940188, 0xE69401C8, 8, /* IMR2AS / IMCR2AS */
-	  { 0, 0, 0, VPU,
-	    __IGNORE0(BBIF2), 0, 0, __IGNORE0(MFI) } },
-	{ 0xE694018C, 0xE69401CC, 8, /* IMR3AS / IMCR3AS */
-	  { 0, 0, 0, _2DDMAC,
-	    __IGNORE0(_2DG), ASA, PEP, ICB } },
-	{ 0xE6940190, 0xE69401D0, 8, /* IMR4AS / IMCR4AS */
-	  { 0, 0, MVI3, __IGNORE0(CTI),
-	    JPU, HQE, __IGNORE0(LCRC), LCDC0 } },
-	{ 0xE6940194, 0xE69401D4, 8, /* IMR5AS / IMCR5AS */
-	  { __IGNORE0(KEYSC), RTDMAC1_2_DADERR, RTDMAC1_2_DEI5, RTDMAC1_2_DEI4,
-	    RTDMAC1_1_DEI3, RTDMAC1_1_DEI2, RTDMAC1_1_DEI1, RTDMAC1_1_DEI0 } },
-	__IGNORE({ 0xE6940198, 0xE69401D8, 8, /* IMR6AS / IMCR6AS */
-	  { 0, 0, MSIOF, 0,
-	    SGX540, 0, TTI20, 0 } })
-	{ 0xE694019C, 0xE69401DC, 8, /* IMR7AS / IMCR7AS */
-	  { 0, TMU_TUNI2, TMU_TUNI1, TMU_TUNI0,
-	    0, 0, 0, 0 } },
-	__IGNORE({ 0xE69401A0, 0xE69401E0, 8, /* IMR8AS / IMCR8AS */
-	  { 0, 0, 0, 0,
-	    0, MSU_MSU, MSU_MSU2, MSUG } })
-	{ 0xE69401A4, 0xE69401E4, 8, /* IMR9AS / IMCR9AS */
-	  { __IGNORE0(RWDT1), __IGNORE0(RWDT0), __IGNORE0(CMT2), CMT0,
-	    IIC2_DTEI2, IIC2_WAITI2, IIC2_TACKI2, IIC2_ALI2 } },
-	{ 0xE69401A8, 0xE69401E8, 8, /* IMR10AS / IMCR10AS */
-	  { 0, 0, IPMMU_IPMMUR, IPMMU_IPMMUR2,
-	    0, 0, 0, 0 } },
-	{ 0xE69401AC, 0xE69401EC, 8, /* IMR11AS / IMCR11AS */
-	  { IIC0_DTEI0, IIC0_WAITI0, IIC0_TACKI0, IIC0_ALI0,
-	    0, TSIF1, LMB, TSIF0 } },
-	{ 0xE6950180, 0xE69501C0, 8, /* IMR0AS3 / IMCR0AS3 */
-	  { RTDMAC2_1_DEI0, RTDMAC2_1_DEI1, RTDMAC2_1_DEI2, RTDMAC2_1_DEI3,
-	    RTDMAC2_2_DEI4, RTDMAC2_2_DEI5, RTDMAC2_2_DADERR, 0 } },
-	{ 0xE6950190, 0xE69501D0, 8, /* IMR4AS3 / IMCR4AS3 */
-	  { FRC, 0, 0, 0,
-	    LCDC1, CSIRX, DSITX_DSITX0, DSITX_DSITX1 } },
-	__IGNORE({ 0xE6950194, 0xE69501D4, 8, /* IMR5AS3 / IMCR5AS3 */
-	  {SPU2_SPU0, SPU2_SPU1, FSI, FMSI,
-	   SCUV, 0, 0, 0 } })
-	{ 0xE6950198, 0xE69501D8, 8, /* IMR6AS3 / IMCR6AS3 */
-	  { TMU1_TUNI10, TMU1_TUNI11, TMU1_TUNI12, TSIF2,
-	    CMT4, 0, 0, 0 } },
-	{ 0xE695019C, 0xE69501DC, 8, /* IMR7AS3 / IMCR7AS3 */
-	  { __IGNORE0(MFIS2), CPORTS2R, 0, 0,
-	    0, 0, 0, 0 } },
-	{ 0xFFD20104, 0, 16, /* INTAMASK */
-	  { 0, 0, 0, 0, 0, 0, 0, 0,
-	    0, 0, 0, 0, 0, 0, 0, INTCS } }
-};
-
-static struct intc_prio_reg intcs_prio_registers[] __initdata = {
-	/* IPRAS */
-	{ 0xFFD20000, 0, 16, 4, { __IGNORE0(CTI), MVI3, _2DDMAC, ICB } },
-	/* IPRBS */
-	{ 0xFFD20004, 0, 16, 4, { JPU, LCDC0, 0, __IGNORE0(LCRC) } },
-	/* IPRCS */
-	__IGNORE({ 0xFFD20008, 0, 16, 4, { BBIF2, 0, 0, 0 } })
-	/* IPRES */
-	{ 0xFFD20010, 0, 16, 4, { RTDMAC1_1, CEU, __IGNORE0(MFI), VPU } },
-	/* IPRFS */
-	{ 0xFFD20014, 0, 16, 4,
-	  { __IGNORE0(KEYSC), RTDMAC1_2, __IGNORE0(CMT2), CMT0 } },
-	/* IPRGS */
-	{ 0xFFD20018, 0, 16, 4, { TMU_TUNI0, TMU_TUNI1, TMU_TUNI2, TSIF1 } },
-	/* IPRHS */
-	{ 0xFFD2001C, 0, 16, 4, { __IGNORE0(TTI20), 0, VEU, BEU } },
-	/* IPRIS */
-	{ 0xFFD20020, 0, 16, 4, { 0, __IGNORE0(MSIOF), TSIF0, IIC0 } },
-	/* IPRJS */
-	__IGNORE({ 0xFFD20024, 0, 16, 4, { 0, SGX540, MSUG, MSU } })
-	/* IPRKS */
-	{ 0xFFD20028, 0, 16, 4, { __IGNORE0(_2DG), ASA, LMB, PEP } },
-	/* IPRLS */
-	{ 0xFFD2002C, 0, 16, 4, { IPMMU, 0, 0, HQE } },
-	/* IPRMS */
-	{ 0xFFD20030, 0, 16, 4,
-	  { IIC2, 0, __IGNORE0(RWDT1), __IGNORE0(RWDT0) } },
-	/* IPRAS3 */
-	{ 0xFFD50000, 0, 16, 4, { RTDMAC2_1, 0, 0, 0 } },
-	/* IPRBS3 */
-	{ 0xFFD50004, 0, 16, 4, { RTDMAC2_2, 0, 0, 0 } },
-	/* IPRIS3 */
-	{ 0xFFD50020, 0, 16, 4, { FRC, 0, 0, 0 } },
-	/* IPRJS3 */
-	{ 0xFFD50024, 0, 16, 4, { LCDC1, CSIRX, DSITX, 0 } },
-	/* IPRKS3 */
-	__IGNORE({ 0xFFD50028, 0, 16, 4, { SPU2, 0, FSI, FMSI } })
-	/* IPRLS3 */
-	__IGNORE({ 0xFFD5002C, 0, 16, 4, { SCUV, 0, 0, 0 } })
-	/* IPRMS3 */
-	{ 0xFFD50030, 0, 16, 4, { TMU1, 0, 0, TSIF2 } },
-	/* IPRNS3 */
-	{ 0xFFD50034, 0, 16, 4, { CMT4, 0, 0, 0 } },
-	/* IPROS3 */
-	{ 0xFFD50038, 0, 16, 4, { __IGNORE0(MFIS2), CPORTS2R, 0, 0 } },
-};
-
-static struct resource intcs_resources[] __initdata = {
-	[0] = {
-		.start	= 0xffd20000,
-		.end	= 0xffd500ff,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct intc_desc intcs_desc __initdata = {
-	.name = "sh7377-intcs",
-	.resource = intcs_resources,
-	.num_resources = ARRAY_SIZE(intcs_resources),
-	.hw = INTC_HW_DESC(intcs_vectors, intcs_groups,
-			   intcs_mask_registers, intcs_prio_registers,
-			   NULL, NULL),
-};
-
-static void intcs_demux(unsigned int irq, struct irq_desc *desc)
-{
-	void __iomem *reg = (void *)irq_get_handler_data(irq);
-	unsigned int evtcodeas = ioread32(reg);
-
-	generic_handle_irq(intcs_evt2irq(evtcodeas));
-}
-
-#define INTEVTSA 0xFFD20100
-void __init sh7377_init_irq(void)
-{
-	void __iomem *intevtsa = ioremap_nocache(INTEVTSA, PAGE_SIZE);
-
-	register_intc_controller(&intca_desc);
-	register_intc_controller(&intca_irq_pins_desc);
-	register_intc_controller(&intcs_desc);
-
-	/* demux using INTEVTSA */
-	irq_set_handler_data(evt2irq(INTCS_INTVECT), (void *)intevtsa);
-	irq_set_chained_handler(evt2irq(INTCS_INTVECT), intcs_demux);
-}
diff --git a/arch/arm/mach-shmobile/pfc-r8a7779.c b/arch/arm/mach-shmobile/pfc-r8a7779.c
index cbc26ba..9513234 100644
--- a/arch/arm/mach-shmobile/pfc-r8a7779.c
+++ b/arch/arm/mach-shmobile/pfc-r8a7779.c
@@ -140,7 +140,7 @@ enum {
 	FN_IP7_3_2, FN_IP7_6_4, FN_IP7_9_7, FN_IP7_12_10,
 	FN_IP7_14_13, FN_IP2_7_4, FN_IP2_11_8, FN_IP2_15_12,
 	FN_IP1_28_25, FN_IP2_3_0, FN_IP8_3_0, FN_IP8_7_4,
-	FN_IP8_11_8, FN_IP8_15_12, FN_PENC0, FN_PENC1,
+	FN_IP8_11_8, FN_IP8_15_12, FN_USB_PENC0, FN_USB_PENC1,
 	FN_IP0_2_0, FN_IP8_17_16, FN_IP8_18, FN_IP8_19,
 
 	/* GPSR5 */
@@ -176,7 +176,7 @@ enum {
 	FN_A0, FN_SD1_DAT3, FN_MMC0_D3, FN_FD3,
 	FN_BS, FN_SD1_DAT2, FN_MMC0_D2, FN_FD2,
 	FN_ATADIR0, FN_SDSELF, FN_HCTS1, FN_TX4_C,
-	FN_PENC2, FN_SCK0, FN_PWM1, FN_PWMFSW0,
+	FN_USB_PENC2, FN_SCK0, FN_PWM1, FN_PWMFSW0,
 	FN_SCIF_CLK, FN_TCLK0_C,
 
 	/* IPSR1 */
@@ -447,7 +447,7 @@ enum {
 	A0_MARK, SD1_DAT3_MARK, MMC0_D3_MARK, FD3_MARK,
 	BS_MARK, SD1_DAT2_MARK, MMC0_D2_MARK, FD2_MARK,
 	ATADIR0_MARK, SDSELF_MARK, HCTS1_MARK, TX4_C_MARK,
-	PENC2_MARK, SCK0_MARK, PWM1_MARK, PWMFSW0_MARK,
+	USB_PENC2_MARK, SCK0_MARK, PWM1_MARK, PWMFSW0_MARK,
 	SCIF_CLK_MARK, TCLK0_C_MARK,
 
 	EX_CS0_MARK, RX3_C_IRDA_RX_C_MARK, MMC0_D6_MARK,
@@ -658,7 +658,7 @@ static pinmux_enum_t pinmux_data[] = {
 	PINMUX_DATA(A18_MARK, FN_A18),
 	PINMUX_DATA(A19_MARK, FN_A19),
 
-	PINMUX_IPSR_DATA(IP0_2_0, PENC2),
+	PINMUX_IPSR_DATA(IP0_2_0, USB_PENC2),
 	PINMUX_IPSR_MODSEL_DATA(IP0_2_0, SCK0, SEL_SCIF0_0),
 	PINMUX_IPSR_DATA(IP0_2_0, PWM1),
 	PINMUX_IPSR_MODSEL_DATA(IP0_2_0, PWMFSW0, SEL_PWMFSW_0),
@@ -1456,7 +1456,7 @@ static struct pinmux_gpio pinmux_gpios[] = {
 	GPIO_FN(A19),
 
 	/* IPSR0 */
-	GPIO_FN(PENC2), GPIO_FN(SCK0), GPIO_FN(PWM1), GPIO_FN(PWMFSW0),
+	GPIO_FN(USB_PENC2), GPIO_FN(SCK0), GPIO_FN(PWM1), GPIO_FN(PWMFSW0),
 	GPIO_FN(SCIF_CLK), GPIO_FN(TCLK0_C), GPIO_FN(BS), GPIO_FN(SD1_DAT2),
 	GPIO_FN(MMC0_D2), GPIO_FN(FD2), GPIO_FN(ATADIR0), GPIO_FN(SDSELF),
 	GPIO_FN(HCTS1), GPIO_FN(TX4_C), GPIO_FN(A0), GPIO_FN(SD1_DAT3),
@@ -1865,8 +1865,8 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		GP_4_30_FN, FN_IP8_18,
 		GP_4_29_FN, FN_IP8_17_16,
 		GP_4_28_FN, FN_IP0_2_0,
-		GP_4_27_FN, FN_PENC1,
-		GP_4_26_FN, FN_PENC0,
+		GP_4_27_FN, FN_USB_PENC1,
+		GP_4_26_FN, FN_USB_PENC0,
 		GP_4_25_FN, FN_IP8_15_12,
 		GP_4_24_FN, FN_IP8_11_8,
 		GP_4_23_FN, FN_IP8_7_4,
@@ -1981,7 +1981,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
 		FN_BS, FN_SD1_DAT2, FN_MMC0_D2, FN_FD2,
 		FN_ATADIR0, FN_SDSELF, FN_HCTS1, FN_TX4_C,
 		/* IP0_2_0 [3] */
-		FN_PENC2, FN_SCK0, FN_PWM1, FN_PWMFSW0,
+		FN_USB_PENC2, FN_SCK0, FN_PWM1, FN_PWMFSW0,
 		FN_SCIF_CLK, FN_TCLK0_C, 0, 0 }
 	},
 	{ PINMUX_CFG_REG_VAR("IPSR1", 0xfffc0024, 32,
diff --git a/arch/arm/mach-shmobile/pfc-sh7367.c b/arch/arm/mach-shmobile/pfc-sh7367.c
deleted file mode 100644
index c0c137f..0000000
--- a/arch/arm/mach-shmobile/pfc-sh7367.c
+++ /dev/null
@@ -1,1727 +0,0 @@
-/*
- * sh7367 processor support - PFC hardware block
- *
- * Copyright (C) 2010  Magnus Damm
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sh_pfc.h>
-#include <mach/sh7367.h>
-
-#define CPU_ALL_PORT(fn, pfx, sfx)				\
-	PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx),		\
-	PORT_10(fn, pfx##10, sfx), PORT_90(fn, pfx##1, sfx),	\
-	PORT_10(fn, pfx##20, sfx), PORT_10(fn, pfx##21, sfx),	\
-	PORT_10(fn, pfx##22, sfx), PORT_10(fn, pfx##23, sfx),	\
-	PORT_10(fn, pfx##24, sfx), PORT_10(fn, pfx##25, sfx),	\
-	PORT_10(fn, pfx##26, sfx), PORT_1(fn, pfx##270, sfx),	\
-	PORT_1(fn, pfx##271, sfx), PORT_1(fn, pfx##272, sfx)
-
-enum {
-	PINMUX_RESERVED = 0,
-
-	PINMUX_DATA_BEGIN,
-	PORT_ALL(DATA), /* PORT0_DATA -> PORT272_DATA */
-	PINMUX_DATA_END,
-
-	PINMUX_INPUT_BEGIN,
-	PORT_ALL(IN), /* PORT0_IN -> PORT272_IN */
-	PINMUX_INPUT_END,
-
-	PINMUX_INPUT_PULLUP_BEGIN,
-	PORT_ALL(IN_PU), /* PORT0_IN_PU -> PORT272_IN_PU */
-	PINMUX_INPUT_PULLUP_END,
-
-	PINMUX_INPUT_PULLDOWN_BEGIN,
-	PORT_ALL(IN_PD), /* PORT0_IN_PD -> PORT272_IN_PD */
-	PINMUX_INPUT_PULLDOWN_END,
-
-	PINMUX_OUTPUT_BEGIN,
-	PORT_ALL(OUT), /* PORT0_OUT -> PORT272_OUT */
-	PINMUX_OUTPUT_END,
-
-	PINMUX_FUNCTION_BEGIN,
-	PORT_ALL(FN_IN), /* PORT0_FN_IN -> PORT272_FN_IN */
-	PORT_ALL(FN_OUT), /* PORT0_FN_OUT -> PORT272_FN_OUT */
-	PORT_ALL(FN0), /* PORT0_FN0 -> PORT272_FN0 */
-	PORT_ALL(FN1), /* PORT0_FN1 -> PORT272_FN1 */
-	PORT_ALL(FN2), /* PORT0_FN2 -> PORT272_FN2 */
-	PORT_ALL(FN3), /* PORT0_FN3 -> PORT272_FN3 */
-	PORT_ALL(FN4), /* PORT0_FN4 -> PORT272_FN4 */
-	PORT_ALL(FN5), /* PORT0_FN5 -> PORT272_FN5 */
-	PORT_ALL(FN6), /* PORT0_FN6 -> PORT272_FN6 */
-	PORT_ALL(FN7), /* PORT0_FN7 -> PORT272_FN7 */
-
-	MSELBCR_MSEL2_1, MSELBCR_MSEL2_0,
-	PINMUX_FUNCTION_END,
-
-	PINMUX_MARK_BEGIN,
-	/* Special Pull-up / Pull-down Functions */
-	PORT48_KEYIN0_PU_MARK, PORT49_KEYIN1_PU_MARK,
-	PORT50_KEYIN2_PU_MARK, PORT55_KEYIN3_PU_MARK,
-	PORT56_KEYIN4_PU_MARK, PORT57_KEYIN5_PU_MARK,
-	PORT58_KEYIN6_PU_MARK,
-
-	/* 49-1 */
-	VBUS0_MARK, CPORT0_MARK, CPORT1_MARK, CPORT2_MARK,
-	CPORT3_MARK, CPORT4_MARK, CPORT5_MARK, CPORT6_MARK,
-	CPORT7_MARK, CPORT8_MARK, CPORT9_MARK, CPORT10_MARK,
-	CPORT11_MARK, SIN2_MARK, CPORT12_MARK, XCTS2_MARK,
-	CPORT13_MARK, RFSPO4_MARK, CPORT14_MARK, RFSPO5_MARK,
-	CPORT15_MARK, CPORT16_MARK, CPORT17_MARK, SOUT2_MARK,
-	CPORT18_MARK, XRTS2_MARK, CPORT19_MARK, CPORT20_MARK,
-	RFSPO6_MARK, CPORT21_MARK, STATUS0_MARK, CPORT22_MARK,
-	STATUS1_MARK, CPORT23_MARK, STATUS2_MARK, RFSPO7_MARK,
-	MPORT0_MARK, MPORT1_MARK, B_SYNLD1_MARK, B_SYNLD2_MARK,
-	XMAINPS_MARK, XDIVPS_MARK, XIDRST_MARK, IDCLK_MARK,
-	IDIO_MARK, SOUT1_MARK, SCIFA4_TXD_MARK,
-	M02_BERDAT_MARK, SIN1_MARK, SCIFA4_RXD_MARK, XWUP_MARK,
-	XRTS1_MARK, SCIFA4_RTS_MARK, M03_BERCLK_MARK,
-	XCTS1_MARK, SCIFA4_CTS_MARK,
-
-	/* 49-2 */
-	HSU_IQ_AGC6_MARK, MFG2_IN2_MARK, MSIOF2_MCK0_MARK,
-	HSU_IQ_AGC5_MARK, MFG2_IN1_MARK, MSIOF2_MCK1_MARK,
-	HSU_IQ_AGC4_MARK, MSIOF2_RSYNC_MARK,
-	HSU_IQ_AGC3_MARK, MFG2_OUT1_MARK, MSIOF2_RSCK_MARK,
-	HSU_IQ_AGC2_MARK, PORT42_KEYOUT0_MARK,
-	HSU_IQ_AGC1_MARK, PORT43_KEYOUT1_MARK,
-	HSU_IQ_AGC0_MARK, PORT44_KEYOUT2_MARK,
-	HSU_IQ_AGC_ST_MARK, PORT45_KEYOUT3_MARK,
-	HSU_IQ_PDO_MARK, PORT46_KEYOUT4_MARK,
-	HSU_IQ_PYO_MARK, PORT47_KEYOUT5_MARK,
-	HSU_EN_TXMUX_G3MO_MARK, PORT48_KEYIN0_MARK,
-	HSU_I_TXMUX_G3MO_MARK, PORT49_KEYIN1_MARK,
-	HSU_Q_TXMUX_G3MO_MARK, PORT50_KEYIN2_MARK,
-	HSU_SYO_MARK, PORT51_MSIOF2_TSYNC_MARK,
-	HSU_SDO_MARK, PORT52_MSIOF2_TSCK_MARK,
-	HSU_TGTTI_G3MO_MARK, PORT53_MSIOF2_TXD_MARK,
-	B_TIME_STAMP_MARK, PORT54_MSIOF2_RXD_MARK,
-	HSU_SDI_MARK, PORT55_KEYIN3_MARK,
-	HSU_SCO_MARK, PORT56_KEYIN4_MARK,
-	HSU_DREQ_MARK, PORT57_KEYIN5_MARK,
-	HSU_DACK_MARK, PORT58_KEYIN6_MARK,
-	HSU_CLK61M_MARK, PORT59_MSIOF2_SS1_MARK,
-	HSU_XRST_MARK, PORT60_MSIOF2_SS2_MARK,
-	PCMCLKO_MARK, SYNC8KO_MARK, DNPCM_A_MARK, UPPCM_A_MARK,
-	XTALB1L_MARK,
-	GPS_AGC1_MARK, SCIFA0_RTS_MARK,
-	GPS_AGC2_MARK, SCIFA0_SCK_MARK,
-	GPS_AGC3_MARK, SCIFA0_TXD_MARK,
-	GPS_AGC4_MARK, SCIFA0_RXD_MARK,
-	GPS_PWRD_MARK, SCIFA0_CTS_MARK,
-	GPS_IM_MARK, GPS_IS_MARK, GPS_QM_MARK, GPS_QS_MARK,
-	SIUBOMC_MARK, TPU2TO0_MARK,
-	SIUCKB_MARK, TPU2TO1_MARK,
-	SIUBOLR_MARK, BBIF2_TSYNC_MARK, TPU2TO2_MARK,
-	SIUBOBT_MARK, BBIF2_TSCK_MARK, TPU2TO3_MARK,
-	SIUBOSLD_MARK, BBIF2_TXD_MARK, TPU3TO0_MARK,
-	SIUBILR_MARK, TPU3TO1_MARK,
-	SIUBIBT_MARK, TPU3TO2_MARK,
-	SIUBISLD_MARK, TPU3TO3_MARK,
-	NMI_MARK, TPU4TO0_MARK,
-	DNPCM_M_MARK, TPU4TO1_MARK, TPU4TO2_MARK, TPU4TO3_MARK,
-	IRQ_TMPB_MARK,
-	PWEN_MARK, MFG1_OUT1_MARK,
-	OVCN_MARK, MFG1_IN1_MARK,
-	OVCN2_MARK, MFG1_IN2_MARK,
-
-	/* 49-3 */
-	RFSPO1_MARK, RFSPO2_MARK, RFSPO3_MARK, PORT93_VIO_CKO2_MARK,
-	USBTERM_MARK, EXTLP_MARK, IDIN_MARK,
-	SCIFA5_CTS_MARK, MFG0_IN1_MARK,
-	SCIFA5_RTS_MARK, MFG0_IN2_MARK,
-	SCIFA5_RXD_MARK,
-	SCIFA5_TXD_MARK,
-	SCIFA5_SCK_MARK, MFG0_OUT1_MARK,
-	A0_EA0_MARK, BS_MARK,
-	A14_EA14_MARK, PORT102_KEYOUT0_MARK,
-	A15_EA15_MARK, PORT103_KEYOUT1_MARK, DV_CLKOL_MARK,
-	A16_EA16_MARK, PORT104_KEYOUT2_MARK,
-	DV_VSYNCL_MARK, MSIOF0_SS1_MARK,
-	A17_EA17_MARK, PORT105_KEYOUT3_MARK,
-	DV_HSYNCL_MARK, MSIOF0_TSYNC_MARK,
-	A18_EA18_MARK, PORT106_KEYOUT4_MARK,
-	DV_DL0_MARK, MSIOF0_TSCK_MARK,
-	A19_EA19_MARK, PORT107_KEYOUT5_MARK,
-	DV_DL1_MARK, MSIOF0_TXD_MARK,
-	A20_EA20_MARK, PORT108_KEYIN0_MARK,
-	DV_DL2_MARK, MSIOF0_RSCK_MARK,
-	A21_EA21_MARK, PORT109_KEYIN1_MARK,
-	DV_DL3_MARK, MSIOF0_RSYNC_MARK,
-	A22_EA22_MARK, PORT110_KEYIN2_MARK,
-	DV_DL4_MARK, MSIOF0_MCK0_MARK,
-	A23_EA23_MARK, PORT111_KEYIN3_MARK,
-	DV_DL5_MARK, MSIOF0_MCK1_MARK,
-	A24_EA24_MARK, PORT112_KEYIN4_MARK,
-	DV_DL6_MARK, MSIOF0_RXD_MARK,
-	A25_EA25_MARK, PORT113_KEYIN5_MARK,
-	DV_DL7_MARK, MSIOF0_SS2_MARK,
-	A26_MARK, PORT113_KEYIN6_MARK, DV_CLKIL_MARK,
-	D0_ED0_NAF0_MARK, D1_ED1_NAF1_MARK, D2_ED2_NAF2_MARK,
-	D3_ED3_NAF3_MARK, D4_ED4_NAF4_MARK, D5_ED5_NAF5_MARK,
-	D6_ED6_NAF6_MARK, D7_ED7_NAF7_MARK, D8_ED8_NAF8_MARK,
-	D9_ED9_NAF9_MARK, D10_ED10_NAF10_MARK, D11_ED11_NAF11_MARK,
-	D12_ED12_NAF12_MARK, D13_ED13_NAF13_MARK,
-	D14_ED14_NAF14_MARK, D15_ED15_NAF15_MARK,
-	CS4_MARK, CS5A_MARK, CS5B_MARK, FCE1_MARK,
-	CS6B_MARK, XCS2_MARK, FCE0_MARK, CS6A_MARK,
-	DACK0_MARK, WAIT_MARK, DREQ0_MARK, RD_XRD_MARK,
-	A27_MARK, RDWR_XWE_MARK, WE0_XWR0_FWE_MARK,
-	WE1_XWR1_MARK, FRB_MARK, CKO_MARK,
-	NBRSTOUT_MARK, NBRST_MARK,
-
-	/* 49-4 */
-	RFSPO0_MARK, PORT146_VIO_CKO2_MARK, TSTMD_MARK,
-	VIO_VD_MARK, VIO_HD_MARK,
-	VIO_D0_MARK, VIO_D1_MARK, VIO_D2_MARK,
-	VIO_D3_MARK, VIO_D4_MARK, VIO_D5_MARK,
-	VIO_D6_MARK, VIO_D7_MARK, VIO_D8_MARK,
-	VIO_D9_MARK, VIO_D10_MARK, VIO_D11_MARK,
-	VIO_D12_MARK, VIO_D13_MARK, VIO_D14_MARK,
-	VIO_D15_MARK, VIO_CLK_MARK, VIO_FIELD_MARK,
-	VIO_CKO_MARK,
-	MFG3_IN1_MARK, MFG3_IN2_MARK,
-	M9_SLCD_A01_MARK, MFG3_OUT1_MARK, TPU0TO0_MARK,
-	M10_SLCD_CK1_MARK, MFG4_IN1_MARK, TPU0TO1_MARK,
-	M11_SLCD_SO1_MARK, MFG4_IN2_MARK, TPU0TO2_MARK,
-	M12_SLCD_CE1_MARK, MFG4_OUT1_MARK, TPU0TO3_MARK,
-	LCDD0_MARK, PORT175_KEYOUT0_MARK, DV_D0_MARK,
-	SIUCKA_MARK, MFG0_OUT2_MARK,
-	LCDD1_MARK, PORT176_KEYOUT1_MARK, DV_D1_MARK,
-	SIUAOLR_MARK, BBIF2_TSYNC1_MARK,
-	LCDD2_MARK, PORT177_KEYOUT2_MARK, DV_D2_MARK,
-	SIUAOBT_MARK, BBIF2_TSCK1_MARK,
-	LCDD3_MARK, PORT178_KEYOUT3_MARK, DV_D3_MARK,
-	SIUAOSLD_MARK, BBIF2_TXD1_MARK,
-	LCDD4_MARK, PORT179_KEYOUT4_MARK, DV_D4_MARK,
-	SIUAISPD_MARK, MFG1_OUT2_MARK,
-	LCDD5_MARK, PORT180_KEYOUT5_MARK, DV_D5_MARK,
-	SIUAILR_MARK, MFG2_OUT2_MARK,
-	LCDD6_MARK, DV_D6_MARK,
-	SIUAIBT_MARK, MFG3_OUT2_MARK, XWR2_MARK,
-	LCDD7_MARK, DV_D7_MARK,
-	SIUAISLD_MARK, MFG4_OUT2_MARK, XWR3_MARK,
-	LCDD8_MARK, DV_D8_MARK, D16_MARK, ED16_MARK,
-	LCDD9_MARK, DV_D9_MARK, D17_MARK, ED17_MARK,
-	LCDD10_MARK, DV_D10_MARK, D18_MARK, ED18_MARK,
-	LCDD11_MARK, DV_D11_MARK, D19_MARK, ED19_MARK,
-	LCDD12_MARK, DV_D12_MARK, D20_MARK, ED20_MARK,
-	LCDD13_MARK, DV_D13_MARK, D21_MARK, ED21_MARK,
-	LCDD14_MARK, DV_D14_MARK, D22_MARK, ED22_MARK,
-	LCDD15_MARK, DV_D15_MARK, D23_MARK, ED23_MARK,
-	LCDD16_MARK, DV_HSYNC_MARK, D24_MARK, ED24_MARK,
-	LCDD17_MARK, DV_VSYNC_MARK, D25_MARK, ED25_MARK,
-	LCDD18_MARK, DREQ2_MARK, MSIOF0L_TSCK_MARK,
-	D26_MARK, ED26_MARK,
-	LCDD19_MARK, MSIOF0L_TSYNC_MARK,
-	D27_MARK, ED27_MARK,
-	LCDD20_MARK, TS_SPSYNC1_MARK, MSIOF0L_MCK0_MARK,
-	D28_MARK, ED28_MARK,
-	LCDD21_MARK, TS_SDAT1_MARK, MSIOF0L_MCK1_MARK,
-	D29_MARK, ED29_MARK,
-	LCDD22_MARK, TS_SDEN1_MARK, MSIOF0L_SS1_MARK,
-	D30_MARK, ED30_MARK,
-	LCDD23_MARK, TS_SCK1_MARK, MSIOF0L_SS2_MARK,
-	D31_MARK, ED31_MARK,
-	LCDDCK_MARK, LCDWR_MARK, DV_CKO_MARK, SIUAOSPD_MARK,
-	LCDRD_MARK, DACK2_MARK, MSIOF0L_RSYNC_MARK,
-
-	/* 49-5 */
-	LCDHSYN_MARK, LCDCS_MARK, LCDCS2_MARK, DACK3_MARK,
-	LCDDISP_MARK, LCDRS_MARK, DREQ3_MARK, MSIOF0L_RSCK_MARK,
-	LCDCSYN_MARK, LCDCSYN2_MARK, DV_CKI_MARK,
-	LCDLCLK_MARK, DREQ1_MARK, MSIOF0L_RXD_MARK,
-	LCDDON_MARK, LCDDON2_MARK, DACK1_MARK, MSIOF0L_TXD_MARK,
-	VIO_DR0_MARK, VIO_DR1_MARK, VIO_DR2_MARK, VIO_DR3_MARK,
-	VIO_DR4_MARK, VIO_DR5_MARK, VIO_DR6_MARK, VIO_DR7_MARK,
-	VIO_VDR_MARK, VIO_HDR_MARK,
-	VIO_CLKR_MARK, VIO_CKOR_MARK,
-	SCIFA1_TXD_MARK, GPS_PGFA0_MARK,
-	SCIFA1_SCK_MARK, GPS_PGFA1_MARK,
-	SCIFA1_RTS_MARK, GPS_EPPSINMON_MARK,
-	SCIFA1_RXD_MARK, SCIFA1_CTS_MARK,
-	MSIOF1_TXD_MARK, SCIFA1_TXD2_MARK, GPS_TXD_MARK,
-	MSIOF1_TSYNC_MARK, SCIFA1_CTS2_MARK, I2C_SDA2_MARK,
-	MSIOF1_TSCK_MARK, SCIFA1_SCK2_MARK,
-	MSIOF1_RXD_MARK, SCIFA1_RXD2_MARK, GPS_RXD_MARK,
-	MSIOF1_RSCK_MARK, SCIFA1_RTS2_MARK,
-	MSIOF1_RSYNC_MARK, I2C_SCL2_MARK,
-	MSIOF1_MCK0_MARK, MSIOF1_MCK1_MARK,
-	MSIOF1_SS1_MARK, EDBGREQ3_MARK,
-	MSIOF1_SS2_MARK,
-	PORT236_IROUT_MARK, IRDA_OUT_MARK,
-	IRDA_IN_MARK, IRDA_FIRSEL_MARK,
-	TPU1TO0_MARK, TS_SPSYNC3_MARK,
-	TPU1TO1_MARK, TS_SDAT3_MARK,
-	TPU1TO2_MARK, TS_SDEN3_MARK, PORT241_MSIOF2_SS1_MARK,
-	TPU1TO3_MARK, PORT242_MSIOF2_TSCK_MARK,
-	M13_BSW_MARK, PORT243_MSIOF2_TSYNC_MARK,
-	M14_GSW_MARK, PORT244_MSIOF2_TXD_MARK,
-	PORT245_IROUT_MARK, M15_RSW_MARK,
-	SOUT3_MARK, SCIFA2_TXD1_MARK,
-	SIN3_MARK, SCIFA2_RXD1_MARK,
-	XRTS3_MARK, SCIFA2_RTS1_MARK, PORT248_MSIOF2_SS2_MARK,
-	XCTS3_MARK, SCIFA2_CTS1_MARK, PORT249_MSIOF2_RXD_MARK,
-	DINT_MARK, SCIFA2_SCK1_MARK, TS_SCK3_MARK,
-	SDHICLK0_MARK, TCK2_MARK,
-	SDHICD0_MARK,
-	SDHID0_0_MARK, TMS2_MARK,
-	SDHID0_1_MARK, TDO2_MARK,
-	SDHID0_2_MARK, TDI2_MARK,
-	SDHID0_3_MARK, RTCK2_MARK,
-
-	/* 49-6 */
-	SDHICMD0_MARK, TRST2_MARK,
-	SDHIWP0_MARK, EDBGREQ2_MARK,
-	SDHICLK1_MARK, TCK3_MARK,
-	SDHID1_0_MARK, M11_SLCD_SO2_MARK,
-	TS_SPSYNC2_MARK, TMS3_MARK,
-	SDHID1_1_MARK, M9_SLCD_AO2_MARK,
-	TS_SDAT2_MARK, TDO3_MARK,
-	SDHID1_2_MARK, M10_SLCD_CK2_MARK,
-	TS_SDEN2_MARK, TDI3_MARK,
-	SDHID1_3_MARK, M12_SLCD_CE2_MARK,
-	TS_SCK2_MARK, RTCK3_MARK,
-	SDHICMD1_MARK, TRST3_MARK,
-	SDHICLK2_MARK, SCIFB_SCK_MARK,
-	SDHID2_0_MARK, SCIFB_TXD_MARK,
-	SDHID2_1_MARK, SCIFB_CTS_MARK,
-	SDHID2_2_MARK, SCIFB_RXD_MARK,
-	SDHID2_3_MARK, SCIFB_RTS_MARK,
-	SDHICMD2_MARK,
-	RESETOUTS_MARK,
-	DIVLOCK_MARK,
-	PINMUX_MARK_END,
-};
-
-static pinmux_enum_t pinmux_data[] = {
-
-	/* specify valid pin states for each pin in GPIO mode */
-
-	/* 49-1 (GPIO) */
-	PORT_DATA_I_PD(0),
-	PORT_DATA_I_PU(1), PORT_DATA_I_PU(2), PORT_DATA_I_PU(3),
-	PORT_DATA_I_PU(4), PORT_DATA_I_PU(5), PORT_DATA_I_PU(6),
-	PORT_DATA_I_PU(7), PORT_DATA_I_PU(8), PORT_DATA_I_PU(9),
-	PORT_DATA_I_PU(10), PORT_DATA_I_PU(11), PORT_DATA_I_PU(12),
-	PORT_DATA_I_PU(13),
-	PORT_DATA_IO_PU_PD(14), PORT_DATA_IO_PU_PD(15),
-	PORT_DATA_O(16), PORT_DATA_O(17), PORT_DATA_O(18), PORT_DATA_O(19),
-	PORT_DATA_O(20), PORT_DATA_O(21), PORT_DATA_O(22), PORT_DATA_O(23),
-	PORT_DATA_O(24), PORT_DATA_O(25), PORT_DATA_O(26),
-	PORT_DATA_I_PD(27), PORT_DATA_I_PD(28),
-	PORT_DATA_O(29), PORT_DATA_O(30), PORT_DATA_O(31), PORT_DATA_O(32),
-	PORT_DATA_IO_PU(33),
-	PORT_DATA_O(34),
-	PORT_DATA_I_PU(35),
-	PORT_DATA_O(36),
-	PORT_DATA_I_PU_PD(37),
-
-	/* 49-2 (GPIO) */
-	PORT_DATA_IO_PU_PD(38),
-	PORT_DATA_IO_PD(39), PORT_DATA_IO_PD(40), PORT_DATA_IO_PD(41),
-	PORT_DATA_O(42), PORT_DATA_O(43), PORT_DATA_O(44), PORT_DATA_O(45),
-	PORT_DATA_O(46), PORT_DATA_O(47),
-	PORT_DATA_I_PU_PD(48), PORT_DATA_I_PU_PD(49), PORT_DATA_I_PU_PD(50),
-	PORT_DATA_IO_PD(51), PORT_DATA_IO_PD(52),
-	PORT_DATA_O(53),
-	PORT_DATA_IO_PD(54),
-	PORT_DATA_I_PU_PD(55),
-	PORT_DATA_IO_PU_PD(56),
-	PORT_DATA_I_PU_PD(57),
-	PORT_DATA_IO_PU_PD(58),
-	PORT_DATA_O(59), PORT_DATA_O(60), PORT_DATA_O(61), PORT_DATA_O(62),
-	PORT_DATA_O(63),
-	PORT_DATA_I_PU(64),
-	PORT_DATA_O(65), PORT_DATA_O(66), PORT_DATA_O(67), PORT_DATA_O(68),
-	PORT_DATA_IO_PD(69), PORT_DATA_IO_PD(70),
-	PORT_DATA_I_PD(71), PORT_DATA_I_PD(72), PORT_DATA_I_PD(73),
-	PORT_DATA_I_PD(74),
-	PORT_DATA_IO_PU_PD(75), PORT_DATA_IO_PU_PD(76),
-	PORT_DATA_IO_PD(77), PORT_DATA_IO_PD(78),
-	PORT_DATA_O(79),
-	PORT_DATA_IO_PD(80), PORT_DATA_IO_PD(81), PORT_DATA_IO_PD(82),
-	PORT_DATA_IO_PU_PD(83), PORT_DATA_IO_PU_PD(84),
-	PORT_DATA_IO_PU_PD(85), PORT_DATA_IO_PU_PD(86),
-	PORT_DATA_I_PD(87),
-	PORT_DATA_IO_PU_PD(88),
-	PORT_DATA_I_PU_PD(89), PORT_DATA_I_PU_PD(90),
-
-	/* 49-3 (GPIO) */
-	PORT_DATA_O(91), PORT_DATA_O(92), PORT_DATA_O(93), PORT_DATA_O(94),
-	PORT_DATA_I_PU_PD(95),
-	PORT_DATA_IO_PU_PD(96), PORT_DATA_IO_PU_PD(97), PORT_DATA_IO_PU_PD(98),
-	PORT_DATA_IO_PU_PD(99),	PORT_DATA_IO_PU_PD(100),
-	PORT_DATA_IO(101), PORT_DATA_IO(102), PORT_DATA_IO(103),
-	PORT_DATA_IO_PD(104), PORT_DATA_IO_PD(105), PORT_DATA_IO_PD(106),
-	PORT_DATA_IO_PD(107),
-	PORT_DATA_IO_PU_PD(108), PORT_DATA_IO_PU_PD(109),
-	PORT_DATA_IO_PU_PD(110), PORT_DATA_IO_PU_PD(111),
-	PORT_DATA_IO_PU_PD(112), PORT_DATA_IO_PU_PD(113),
-	PORT_DATA_IO_PU_PD(114),
-	PORT_DATA_IO_PU(115), PORT_DATA_IO_PU(116), PORT_DATA_IO_PU(117),
-	PORT_DATA_IO_PU(118), PORT_DATA_IO_PU(119), PORT_DATA_IO_PU(120),
-	PORT_DATA_IO_PU(121), PORT_DATA_IO_PU(122), PORT_DATA_IO_PU(123),
-	PORT_DATA_IO_PU(124), PORT_DATA_IO_PU(125), PORT_DATA_IO_PU(126),
-	PORT_DATA_IO_PU(127), PORT_DATA_IO_PU(128), PORT_DATA_IO_PU(129),
-	PORT_DATA_IO_PU(130),
-	PORT_DATA_O(131), PORT_DATA_O(132), PORT_DATA_O(133),
-	PORT_DATA_IO_PU(134),
-	PORT_DATA_O(135), PORT_DATA_O(136),
-	PORT_DATA_I_PU_PD(137),
-	PORT_DATA_IO(138),
-	PORT_DATA_IO_PU_PD(139),
-	PORT_DATA_IO(140), PORT_DATA_IO(141),
-	PORT_DATA_I_PU(142),
-	PORT_DATA_O(143), PORT_DATA_O(144),
-	PORT_DATA_I_PU(145),
-
-	/* 49-4 (GPIO) */
-	PORT_DATA_O(146),
-	PORT_DATA_I_PU_PD(147),
-	PORT_DATA_I_PD(148), PORT_DATA_I_PD(149),
-	PORT_DATA_IO_PD(150), PORT_DATA_IO_PD(151), PORT_DATA_IO_PD(152),
-	PORT_DATA_IO_PD(153), PORT_DATA_IO_PD(154), PORT_DATA_IO_PD(155),
-	PORT_DATA_IO_PD(156), PORT_DATA_IO_PD(157), PORT_DATA_IO_PD(158),
-	PORT_DATA_IO_PD(159), PORT_DATA_IO_PD(160), PORT_DATA_IO_PD(161),
-	PORT_DATA_IO_PD(162), PORT_DATA_IO_PD(163), PORT_DATA_IO_PD(164),
-	PORT_DATA_IO_PD(165), PORT_DATA_IO_PD(166),
-	PORT_DATA_IO_PU_PD(167),
-	PORT_DATA_O(168),
-	PORT_DATA_I_PD(169), PORT_DATA_I_PD(170),
-	PORT_DATA_O(171),
-	PORT_DATA_IO_PD(172), PORT_DATA_IO_PD(173),
-	PORT_DATA_O(174),
-	PORT_DATA_IO_PD(175), PORT_DATA_IO_PD(176), PORT_DATA_IO_PD(177),
-	PORT_DATA_IO_PD(178), PORT_DATA_IO_PD(179), PORT_DATA_IO_PD(180),
-	PORT_DATA_IO_PD(181), PORT_DATA_IO_PD(182), PORT_DATA_IO_PD(183),
-	PORT_DATA_IO_PD(184), PORT_DATA_IO_PD(185), PORT_DATA_IO_PD(186),
-	PORT_DATA_IO_PD(187), PORT_DATA_IO_PD(188), PORT_DATA_IO_PD(189),
-	PORT_DATA_IO_PD(190), PORT_DATA_IO_PD(191), PORT_DATA_IO_PD(192),
-	PORT_DATA_IO_PD(193), PORT_DATA_IO_PD(194), PORT_DATA_IO_PD(195),
-	PORT_DATA_IO_PD(196), PORT_DATA_IO_PD(197), PORT_DATA_IO_PD(198),
-	PORT_DATA_O(199),
-	PORT_DATA_IO_PD(200),
-
-	/* 49-5 (GPIO) */
-	PORT_DATA_O(201),
-	PORT_DATA_IO_PD(202), PORT_DATA_IO_PD(203),
-	PORT_DATA_I(204),
-	PORT_DATA_O(205),
-	PORT_DATA_IO_PD(206), PORT_DATA_IO_PD(207), PORT_DATA_IO_PD(208),
-	PORT_DATA_IO_PD(209), PORT_DATA_IO_PD(210), PORT_DATA_IO_PD(211),
-	PORT_DATA_IO_PD(212), PORT_DATA_IO_PD(213), PORT_DATA_IO_PD(214),
-	PORT_DATA_IO_PD(215), PORT_DATA_IO_PD(216),
-	PORT_DATA_O(217),
-	PORT_DATA_I_PU_PD(218), PORT_DATA_I_PU_PD(219),
-	PORT_DATA_O(220), PORT_DATA_O(221), PORT_DATA_O(222),
-	PORT_DATA_I_PD(223),
-	PORT_DATA_I_PU_PD(224),
-	PORT_DATA_O(225),
-	PORT_DATA_IO_PD(226),
-	PORT_DATA_IO_PU_PD(227),
-	PORT_DATA_I_PD(228),
-	PORT_DATA_IO_PD(229), PORT_DATA_IO_PD(230),
-	PORT_DATA_I_PU_PD(231), PORT_DATA_I_PU_PD(232),
-	PORT_DATA_IO_PU_PD(233), PORT_DATA_IO_PU_PD(234),
-	PORT_DATA_I_PU_PD(235),
-	PORT_DATA_O(236),
-	PORT_DATA_I_PD(237),
-	PORT_DATA_IO_PU_PD(238), PORT_DATA_IO_PU_PD(239),
-	PORT_DATA_IO_PD(240), PORT_DATA_IO_PD(241),
-	PORT_DATA_IO_PD(242), PORT_DATA_IO_PD(243),
-	PORT_DATA_O(244),
-	PORT_DATA_IO_PU_PD(245),
-	PORT_DATA_O(246),
-	PORT_DATA_I_PD(247),
-	PORT_DATA_IO_PU_PD(248),
-	PORT_DATA_I_PU_PD(249),
-	PORT_DATA_IO_PD(250), PORT_DATA_IO_PD(251),
-	PORT_DATA_IO_PU_PD(252), PORT_DATA_IO_PU_PD(253),
-	PORT_DATA_IO_PU_PD(254), PORT_DATA_IO_PU_PD(255),
-	PORT_DATA_IO_PU_PD(256),
-
-	/* 49-6 (GPIO) */
-	PORT_DATA_IO_PU_PD(257), PORT_DATA_IO_PU_PD(258),
-	PORT_DATA_IO_PD(259),
-	PORT_DATA_IO_PU(260), PORT_DATA_IO_PU(261), PORT_DATA_IO_PU(262),
-	PORT_DATA_IO_PU(263), PORT_DATA_IO_PU(264),
-	PORT_DATA_O(265),
-	PORT_DATA_IO_PU(266), PORT_DATA_IO_PU(267), PORT_DATA_IO_PU(268),
-	PORT_DATA_IO_PU(269), PORT_DATA_IO_PU(270),
-	PORT_DATA_O(271),
-	PORT_DATA_I_PD(272),
-
-	/* Special Pull-up / Pull-down Functions */
-	PINMUX_DATA(PORT48_KEYIN0_PU_MARK, MSELBCR_MSEL2_1,
-		    PORT48_FN2, PORT48_IN_PU),
-	PINMUX_DATA(PORT49_KEYIN1_PU_MARK, MSELBCR_MSEL2_1,
-		    PORT49_FN2, PORT49_IN_PU),
-	PINMUX_DATA(PORT50_KEYIN2_PU_MARK, MSELBCR_MSEL2_1,
-		    PORT50_FN2, PORT50_IN_PU),
-	PINMUX_DATA(PORT55_KEYIN3_PU_MARK, MSELBCR_MSEL2_1,
-		    PORT55_FN2, PORT55_IN_PU),
-	PINMUX_DATA(PORT56_KEYIN4_PU_MARK, MSELBCR_MSEL2_1,
-		    PORT56_FN2, PORT56_IN_PU),
-	PINMUX_DATA(PORT57_KEYIN5_PU_MARK, MSELBCR_MSEL2_1,
-		    PORT57_FN2, PORT57_IN_PU),
-	PINMUX_DATA(PORT58_KEYIN6_PU_MARK, MSELBCR_MSEL2_1,
-		    PORT58_FN2, PORT58_IN_PU),
-
-	/* 49-1 (FN) */
-	PINMUX_DATA(VBUS0_MARK, PORT0_FN1),
-	PINMUX_DATA(CPORT0_MARK, PORT1_FN1),
-	PINMUX_DATA(CPORT1_MARK, PORT2_FN1),
-	PINMUX_DATA(CPORT2_MARK, PORT3_FN1),
-	PINMUX_DATA(CPORT3_MARK, PORT4_FN1),
-	PINMUX_DATA(CPORT4_MARK, PORT5_FN1),
-	PINMUX_DATA(CPORT5_MARK, PORT6_FN1),
-	PINMUX_DATA(CPORT6_MARK, PORT7_FN1),
-	PINMUX_DATA(CPORT7_MARK, PORT8_FN1),
-	PINMUX_DATA(CPORT8_MARK, PORT9_FN1),
-	PINMUX_DATA(CPORT9_MARK, PORT10_FN1),
-	PINMUX_DATA(CPORT10_MARK, PORT11_FN1),
-	PINMUX_DATA(CPORT11_MARK, PORT12_FN1),
-	PINMUX_DATA(SIN2_MARK, PORT12_FN2),
-	PINMUX_DATA(CPORT12_MARK, PORT13_FN1),
-	PINMUX_DATA(XCTS2_MARK, PORT13_FN2),
-	PINMUX_DATA(CPORT13_MARK, PORT14_FN1),
-	PINMUX_DATA(RFSPO4_MARK, PORT14_FN2),
-	PINMUX_DATA(CPORT14_MARK, PORT15_FN1),
-	PINMUX_DATA(RFSPO5_MARK, PORT15_FN2),
-	PINMUX_DATA(CPORT15_MARK, PORT16_FN1),
-	PINMUX_DATA(CPORT16_MARK, PORT17_FN1),
-	PINMUX_DATA(CPORT17_MARK, PORT18_FN1),
-	PINMUX_DATA(SOUT2_MARK, PORT18_FN2),
-	PINMUX_DATA(CPORT18_MARK, PORT19_FN1),
-	PINMUX_DATA(XRTS2_MARK, PORT19_FN1),
-	PINMUX_DATA(CPORT19_MARK, PORT20_FN1),
-	PINMUX_DATA(CPORT20_MARK, PORT21_FN1),
-	PINMUX_DATA(RFSPO6_MARK, PORT21_FN2),
-	PINMUX_DATA(CPORT21_MARK, PORT22_FN1),
-	PINMUX_DATA(STATUS0_MARK, PORT22_FN2),
-	PINMUX_DATA(CPORT22_MARK, PORT23_FN1),
-	PINMUX_DATA(STATUS1_MARK, PORT23_FN2),
-	PINMUX_DATA(CPORT23_MARK, PORT24_FN1),
-	PINMUX_DATA(STATUS2_MARK, PORT24_FN2),
-	PINMUX_DATA(RFSPO7_MARK, PORT24_FN3),
-	PINMUX_DATA(MPORT0_MARK, PORT25_FN1),
-	PINMUX_DATA(MPORT1_MARK, PORT26_FN1),
-	PINMUX_DATA(B_SYNLD1_MARK, PORT27_FN1),
-	PINMUX_DATA(B_SYNLD2_MARK, PORT28_FN1),
-	PINMUX_DATA(XMAINPS_MARK, PORT29_FN1),
-	PINMUX_DATA(XDIVPS_MARK, PORT30_FN1),
-	PINMUX_DATA(XIDRST_MARK, PORT31_FN1),
-	PINMUX_DATA(IDCLK_MARK, PORT32_FN1),
-	PINMUX_DATA(IDIO_MARK, PORT33_FN1),
-	PINMUX_DATA(SOUT1_MARK, PORT34_FN1),
-	PINMUX_DATA(SCIFA4_TXD_MARK, PORT34_FN2),
-	PINMUX_DATA(M02_BERDAT_MARK, PORT34_FN3),
-	PINMUX_DATA(SIN1_MARK, PORT35_FN1),
-	PINMUX_DATA(SCIFA4_RXD_MARK, PORT35_FN2),
-	PINMUX_DATA(XWUP_MARK, PORT35_FN3),
-	PINMUX_DATA(XRTS1_MARK, PORT36_FN1),
-	PINMUX_DATA(SCIFA4_RTS_MARK, PORT36_FN2),
-	PINMUX_DATA(M03_BERCLK_MARK, PORT36_FN3),
-	PINMUX_DATA(XCTS1_MARK, PORT37_FN1),
-	PINMUX_DATA(SCIFA4_CTS_MARK, PORT37_FN2),
-
-	/* 49-2 (FN) */
-	PINMUX_DATA(HSU_IQ_AGC6_MARK, PORT38_FN1),
-	PINMUX_DATA(MFG2_IN2_MARK, PORT38_FN2),
-	PINMUX_DATA(MSIOF2_MCK0_MARK, PORT38_FN3),
-	PINMUX_DATA(HSU_IQ_AGC5_MARK, PORT39_FN1),
-	PINMUX_DATA(MFG2_IN1_MARK, PORT39_FN2),
-	PINMUX_DATA(MSIOF2_MCK1_MARK, PORT39_FN3),
-	PINMUX_DATA(HSU_IQ_AGC4_MARK, PORT40_FN1),
-	PINMUX_DATA(MSIOF2_RSYNC_MARK, PORT40_FN3),
-	PINMUX_DATA(HSU_IQ_AGC3_MARK, PORT41_FN1),
-	PINMUX_DATA(MFG2_OUT1_MARK, PORT41_FN2),
-	PINMUX_DATA(MSIOF2_RSCK_MARK, PORT41_FN3),
-	PINMUX_DATA(HSU_IQ_AGC2_MARK, PORT42_FN1),
-	PINMUX_DATA(PORT42_KEYOUT0_MARK, MSELBCR_MSEL2_1, PORT42_FN2),
-	PINMUX_DATA(HSU_IQ_AGC1_MARK, PORT43_FN1),
-	PINMUX_DATA(PORT43_KEYOUT1_MARK, MSELBCR_MSEL2_1, PORT43_FN2),
-	PINMUX_DATA(HSU_IQ_AGC0_MARK, PORT44_FN1),
-	PINMUX_DATA(PORT44_KEYOUT2_MARK, MSELBCR_MSEL2_1, PORT44_FN2),
-	PINMUX_DATA(HSU_IQ_AGC_ST_MARK, PORT45_FN1),
-	PINMUX_DATA(PORT45_KEYOUT3_MARK, MSELBCR_MSEL2_1, PORT45_FN2),
-	PINMUX_DATA(HSU_IQ_PDO_MARK, PORT46_FN1),
-	PINMUX_DATA(PORT46_KEYOUT4_MARK, MSELBCR_MSEL2_1, PORT46_FN2),
-	PINMUX_DATA(HSU_IQ_PYO_MARK, PORT47_FN1),
-	PINMUX_DATA(PORT47_KEYOUT5_MARK, MSELBCR_MSEL2_1, PORT47_FN2),
-	PINMUX_DATA(HSU_EN_TXMUX_G3MO_MARK, PORT48_FN1),
-	PINMUX_DATA(PORT48_KEYIN0_MARK, MSELBCR_MSEL2_1, PORT48_FN2),
-	PINMUX_DATA(HSU_I_TXMUX_G3MO_MARK, PORT49_FN1),
-	PINMUX_DATA(PORT49_KEYIN1_MARK, MSELBCR_MSEL2_1, PORT49_FN2),
-	PINMUX_DATA(HSU_Q_TXMUX_G3MO_MARK, PORT50_FN1),
-	PINMUX_DATA(PORT50_KEYIN2_MARK, MSELBCR_MSEL2_1, PORT50_FN2),
-	PINMUX_DATA(HSU_SYO_MARK, PORT51_FN1),
-	PINMUX_DATA(PORT51_MSIOF2_TSYNC_MARK, PORT51_FN2),
-	PINMUX_DATA(HSU_SDO_MARK, PORT52_FN1),
-	PINMUX_DATA(PORT52_MSIOF2_TSCK_MARK, PORT52_FN2),
-	PINMUX_DATA(HSU_TGTTI_G3MO_MARK, PORT53_FN1),
-	PINMUX_DATA(PORT53_MSIOF2_TXD_MARK, PORT53_FN2),
-	PINMUX_DATA(B_TIME_STAMP_MARK, PORT54_FN1),
-	PINMUX_DATA(PORT54_MSIOF2_RXD_MARK, PORT54_FN2),
-	PINMUX_DATA(HSU_SDI_MARK, PORT55_FN1),
-	PINMUX_DATA(PORT55_KEYIN3_MARK, MSELBCR_MSEL2_1, PORT55_FN2),
-	PINMUX_DATA(HSU_SCO_MARK, PORT56_FN1),
-	PINMUX_DATA(PORT56_KEYIN4_MARK, MSELBCR_MSEL2_1, PORT56_FN2),
-	PINMUX_DATA(HSU_DREQ_MARK, PORT57_FN1),
-	PINMUX_DATA(PORT57_KEYIN5_MARK, MSELBCR_MSEL2_1, PORT57_FN2),
-	PINMUX_DATA(HSU_DACK_MARK, PORT58_FN1),
-	PINMUX_DATA(PORT58_KEYIN6_MARK, MSELBCR_MSEL2_1, PORT58_FN2),
-	PINMUX_DATA(HSU_CLK61M_MARK, PORT59_FN1),
-	PINMUX_DATA(PORT59_MSIOF2_SS1_MARK, PORT59_FN2),
-	PINMUX_DATA(HSU_XRST_MARK, PORT60_FN1),
-	PINMUX_DATA(PORT60_MSIOF2_SS2_MARK, PORT60_FN2),
-	PINMUX_DATA(PCMCLKO_MARK, PORT61_FN1),
-	PINMUX_DATA(SYNC8KO_MARK, PORT62_FN1),
-	PINMUX_DATA(DNPCM_A_MARK, PORT63_FN1),
-	PINMUX_DATA(UPPCM_A_MARK, PORT64_FN1),
-	PINMUX_DATA(XTALB1L_MARK, PORT65_FN1),
-	PINMUX_DATA(GPS_AGC1_MARK, PORT66_FN1),
-	PINMUX_DATA(SCIFA0_RTS_MARK, PORT66_FN2),
-	PINMUX_DATA(GPS_AGC2_MARK, PORT67_FN1),
-	PINMUX_DATA(SCIFA0_SCK_MARK, PORT67_FN2),
-	PINMUX_DATA(GPS_AGC3_MARK, PORT68_FN1),
-	PINMUX_DATA(SCIFA0_TXD_MARK, PORT68_FN2),
-	PINMUX_DATA(GPS_AGC4_MARK, PORT69_FN1),
-	PINMUX_DATA(SCIFA0_RXD_MARK, PORT69_FN2),
-	PINMUX_DATA(GPS_PWRD_MARK, PORT70_FN1),
-	PINMUX_DATA(SCIFA0_CTS_MARK, PORT70_FN2),
-	PINMUX_DATA(GPS_IM_MARK, PORT71_FN1),
-	PINMUX_DATA(GPS_IS_MARK, PORT72_FN1),
-	PINMUX_DATA(GPS_QM_MARK, PORT73_FN1),
-	PINMUX_DATA(GPS_QS_MARK, PORT74_FN1),
-	PINMUX_DATA(SIUBOMC_MARK, PORT75_FN1),
-	PINMUX_DATA(TPU2TO0_MARK, PORT75_FN3),
-	PINMUX_DATA(SIUCKB_MARK, PORT76_FN1),
-	PINMUX_DATA(TPU2TO1_MARK, PORT76_FN3),
-	PINMUX_DATA(SIUBOLR_MARK, PORT77_FN1),
-	PINMUX_DATA(BBIF2_TSYNC_MARK, PORT77_FN2),
-	PINMUX_DATA(TPU2TO2_MARK, PORT77_FN3),
-	PINMUX_DATA(SIUBOBT_MARK, PORT78_FN1),
-	PINMUX_DATA(BBIF2_TSCK_MARK, PORT78_FN2),
-	PINMUX_DATA(TPU2TO3_MARK, PORT78_FN3),
-	PINMUX_DATA(SIUBOSLD_MARK, PORT79_FN1),
-	PINMUX_DATA(BBIF2_TXD_MARK, PORT79_FN2),
-	PINMUX_DATA(TPU3TO0_MARK, PORT79_FN3),
-	PINMUX_DATA(SIUBILR_MARK, PORT80_FN1),
-	PINMUX_DATA(TPU3TO1_MARK, PORT80_FN3),
-	PINMUX_DATA(SIUBIBT_MARK, PORT81_FN1),
-	PINMUX_DATA(TPU3TO2_MARK, PORT81_FN3),
-	PINMUX_DATA(SIUBISLD_MARK, PORT82_FN1),
-	PINMUX_DATA(TPU3TO3_MARK, PORT82_FN3),
-	PINMUX_DATA(NMI_MARK, PORT83_FN1),
-	PINMUX_DATA(TPU4TO0_MARK, PORT83_FN3),
-	PINMUX_DATA(DNPCM_M_MARK, PORT84_FN1),
-	PINMUX_DATA(TPU4TO1_MARK, PORT84_FN3),
-	PINMUX_DATA(TPU4TO2_MARK, PORT85_FN3),
-	PINMUX_DATA(TPU4TO3_MARK, PORT86_FN3),
-	PINMUX_DATA(IRQ_TMPB_MARK, PORT87_FN1),
-	PINMUX_DATA(PWEN_MARK, PORT88_FN1),
-	PINMUX_DATA(MFG1_OUT1_MARK, PORT88_FN2),
-	PINMUX_DATA(OVCN_MARK, PORT89_FN1),
-	PINMUX_DATA(MFG1_IN1_MARK, PORT89_FN2),
-	PINMUX_DATA(OVCN2_MARK, PORT90_FN1),
-	PINMUX_DATA(MFG1_IN2_MARK, PORT90_FN2),
-
-	/* 49-3 (FN) */
-	PINMUX_DATA(RFSPO1_MARK, PORT91_FN1),
-	PINMUX_DATA(RFSPO2_MARK, PORT92_FN1),
-	PINMUX_DATA(RFSPO3_MARK, PORT93_FN1),
-	PINMUX_DATA(PORT93_VIO_CKO2_MARK, PORT93_FN2),
-	PINMUX_DATA(USBTERM_MARK, PORT94_FN1),
-	PINMUX_DATA(EXTLP_MARK, PORT94_FN2),
-	PINMUX_DATA(IDIN_MARK, PORT95_FN1),
-	PINMUX_DATA(SCIFA5_CTS_MARK, PORT96_FN1),
-	PINMUX_DATA(MFG0_IN1_MARK, PORT96_FN2),
-	PINMUX_DATA(SCIFA5_RTS_MARK, PORT97_FN1),
-	PINMUX_DATA(MFG0_IN2_MARK, PORT97_FN2),
-	PINMUX_DATA(SCIFA5_RXD_MARK, PORT98_FN1),
-	PINMUX_DATA(SCIFA5_TXD_MARK, PORT99_FN1),
-	PINMUX_DATA(SCIFA5_SCK_MARK, PORT100_FN1),
-	PINMUX_DATA(MFG0_OUT1_MARK, PORT100_FN2),
-	PINMUX_DATA(A0_EA0_MARK, PORT101_FN1),
-	PINMUX_DATA(BS_MARK, PORT101_FN2),
-	PINMUX_DATA(A14_EA14_MARK, PORT102_FN1),
-	PINMUX_DATA(PORT102_KEYOUT0_MARK, MSELBCR_MSEL2_0, PORT102_FN2),
-	PINMUX_DATA(A15_EA15_MARK, PORT103_FN1),
-	PINMUX_DATA(PORT103_KEYOUT1_MARK, MSELBCR_MSEL2_0, PORT103_FN2),
-	PINMUX_DATA(DV_CLKOL_MARK, PORT103_FN3),
-	PINMUX_DATA(A16_EA16_MARK, PORT104_FN1),
-	PINMUX_DATA(PORT104_KEYOUT2_MARK, MSELBCR_MSEL2_0, PORT104_FN2),
-	PINMUX_DATA(DV_VSYNCL_MARK, PORT104_FN3),
-	PINMUX_DATA(MSIOF0_SS1_MARK, PORT104_FN4),
-	PINMUX_DATA(A17_EA17_MARK, PORT105_FN1),
-	PINMUX_DATA(PORT105_KEYOUT3_MARK, MSELBCR_MSEL2_0, PORT105_FN2),
-	PINMUX_DATA(DV_HSYNCL_MARK, PORT105_FN3),
-	PINMUX_DATA(MSIOF0_TSYNC_MARK, PORT105_FN4),
-	PINMUX_DATA(A18_EA18_MARK, PORT106_FN1),
-	PINMUX_DATA(PORT106_KEYOUT4_MARK, MSELBCR_MSEL2_0, PORT106_FN2),
-	PINMUX_DATA(DV_DL0_MARK, PORT106_FN3),
-	PINMUX_DATA(MSIOF0_TSCK_MARK, PORT106_FN4),
-	PINMUX_DATA(A19_EA19_MARK, PORT107_FN1),
-	PINMUX_DATA(PORT107_KEYOUT5_MARK, MSELBCR_MSEL2_0, PORT107_FN2),
-	PINMUX_DATA(DV_DL1_MARK, PORT107_FN3),
-	PINMUX_DATA(MSIOF0_TXD_MARK, PORT107_FN4),
-	PINMUX_DATA(A20_EA20_MARK, PORT108_FN1),
-	PINMUX_DATA(PORT108_KEYIN0_MARK, MSELBCR_MSEL2_0, PORT108_FN2),
-	PINMUX_DATA(DV_DL2_MARK, PORT108_FN3),
-	PINMUX_DATA(MSIOF0_RSCK_MARK, PORT108_FN4),
-	PINMUX_DATA(A21_EA21_MARK, PORT109_FN1),
-	PINMUX_DATA(PORT109_KEYIN1_MARK, MSELBCR_MSEL2_0, PORT109_FN2),
-	PINMUX_DATA(DV_DL3_MARK, PORT109_FN3),
-	PINMUX_DATA(MSIOF0_RSYNC_MARK, PORT109_FN4),
-	PINMUX_DATA(A22_EA22_MARK, PORT110_FN1),
-	PINMUX_DATA(PORT110_KEYIN2_MARK, MSELBCR_MSEL2_0, PORT110_FN2),
-	PINMUX_DATA(DV_DL4_MARK, PORT110_FN3),
-	PINMUX_DATA(MSIOF0_MCK0_MARK, PORT110_FN4),
-	PINMUX_DATA(A23_EA23_MARK, PORT111_FN1),
-	PINMUX_DATA(PORT111_KEYIN3_MARK, MSELBCR_MSEL2_0, PORT111_FN2),
-	PINMUX_DATA(DV_DL5_MARK, PORT111_FN3),
-	PINMUX_DATA(MSIOF0_MCK1_MARK, PORT111_FN4),
-	PINMUX_DATA(A24_EA24_MARK, PORT112_FN1),
-	PINMUX_DATA(PORT112_KEYIN4_MARK, MSELBCR_MSEL2_0, PORT112_FN2),
-	PINMUX_DATA(DV_DL6_MARK, PORT112_FN3),
-	PINMUX_DATA(MSIOF0_RXD_MARK, PORT112_FN4),
-	PINMUX_DATA(A25_EA25_MARK, PORT113_FN1),
-	PINMUX_DATA(PORT113_KEYIN5_MARK, MSELBCR_MSEL2_0, PORT113_FN2),
-	PINMUX_DATA(DV_DL7_MARK, PORT113_FN3),
-	PINMUX_DATA(MSIOF0_SS2_MARK, PORT113_FN4),
-	PINMUX_DATA(A26_MARK, PORT114_FN1),
-	PINMUX_DATA(PORT113_KEYIN6_MARK, MSELBCR_MSEL2_0, PORT114_FN2),
-	PINMUX_DATA(DV_CLKIL_MARK, PORT114_FN3),
-	PINMUX_DATA(D0_ED0_NAF0_MARK, PORT115_FN1),
-	PINMUX_DATA(D1_ED1_NAF1_MARK, PORT116_FN1),
-	PINMUX_DATA(D2_ED2_NAF2_MARK, PORT117_FN1),
-	PINMUX_DATA(D3_ED3_NAF3_MARK, PORT118_FN1),
-	PINMUX_DATA(D4_ED4_NAF4_MARK, PORT119_FN1),
-	PINMUX_DATA(D5_ED5_NAF5_MARK, PORT120_FN1),
-	PINMUX_DATA(D6_ED6_NAF6_MARK, PORT121_FN1),
-	PINMUX_DATA(D7_ED7_NAF7_MARK, PORT122_FN1),
-	PINMUX_DATA(D8_ED8_NAF8_MARK, PORT123_FN1),
-	PINMUX_DATA(D9_ED9_NAF9_MARK, PORT124_FN1),
-	PINMUX_DATA(D10_ED10_NAF10_MARK, PORT125_FN1),
-	PINMUX_DATA(D11_ED11_NAF11_MARK, PORT126_FN1),
-	PINMUX_DATA(D12_ED12_NAF12_MARK, PORT127_FN1),
-	PINMUX_DATA(D13_ED13_NAF13_MARK, PORT128_FN1),
-	PINMUX_DATA(D14_ED14_NAF14_MARK, PORT129_FN1),
-	PINMUX_DATA(D15_ED15_NAF15_MARK, PORT130_FN1),
-	PINMUX_DATA(CS4_MARK, PORT131_FN1),
-	PINMUX_DATA(CS5A_MARK, PORT132_FN1),
-	PINMUX_DATA(CS5B_MARK, PORT133_FN1),
-	PINMUX_DATA(FCE1_MARK, PORT133_FN2),
-	PINMUX_DATA(CS6B_MARK, PORT134_FN1),
-	PINMUX_DATA(XCS2_MARK, PORT134_FN2),
-	PINMUX_DATA(FCE0_MARK, PORT135_FN1),
-	PINMUX_DATA(CS6A_MARK, PORT136_FN1),
-	PINMUX_DATA(DACK0_MARK, PORT136_FN2),
-	PINMUX_DATA(WAIT_MARK, PORT137_FN1),
-	PINMUX_DATA(DREQ0_MARK, PORT137_FN2),
-	PINMUX_DATA(RD_XRD_MARK, PORT138_FN1),
-	PINMUX_DATA(A27_MARK, PORT139_FN1),
-	PINMUX_DATA(RDWR_XWE_MARK, PORT139_FN2),
-	PINMUX_DATA(WE0_XWR0_FWE_MARK, PORT140_FN1),
-	PINMUX_DATA(WE1_XWR1_MARK, PORT141_FN1),
-	PINMUX_DATA(FRB_MARK, PORT142_FN1),
-	PINMUX_DATA(CKO_MARK, PORT143_FN1),
-	PINMUX_DATA(NBRSTOUT_MARK, PORT144_FN1),
-	PINMUX_DATA(NBRST_MARK, PORT145_FN1),
-
-	/* 49-4 (FN) */
-	PINMUX_DATA(RFSPO0_MARK, PORT146_FN1),
-	PINMUX_DATA(PORT146_VIO_CKO2_MARK, PORT146_FN2),
-	PINMUX_DATA(TSTMD_MARK, PORT147_FN1),
-	PINMUX_DATA(VIO_VD_MARK, PORT148_FN1),
-	PINMUX_DATA(VIO_HD_MARK, PORT149_FN1),
-	PINMUX_DATA(VIO_D0_MARK, PORT150_FN1),
-	PINMUX_DATA(VIO_D1_MARK, PORT151_FN1),
-	PINMUX_DATA(VIO_D2_MARK, PORT152_FN1),
-	PINMUX_DATA(VIO_D3_MARK, PORT153_FN1),
-	PINMUX_DATA(VIO_D4_MARK, PORT154_FN1),
-	PINMUX_DATA(VIO_D5_MARK, PORT155_FN1),
-	PINMUX_DATA(VIO_D6_MARK, PORT156_FN1),
-	PINMUX_DATA(VIO_D7_MARK, PORT157_FN1),
-	PINMUX_DATA(VIO_D8_MARK, PORT158_FN1),
-	PINMUX_DATA(VIO_D9_MARK, PORT159_FN1),
-	PINMUX_DATA(VIO_D10_MARK, PORT160_FN1),
-	PINMUX_DATA(VIO_D11_MARK, PORT161_FN1),
-	PINMUX_DATA(VIO_D12_MARK, PORT162_FN1),
-	PINMUX_DATA(VIO_D13_MARK, PORT163_FN1),
-	PINMUX_DATA(VIO_D14_MARK, PORT164_FN1),
-	PINMUX_DATA(VIO_D15_MARK, PORT165_FN1),
-	PINMUX_DATA(VIO_CLK_MARK, PORT166_FN1),
-	PINMUX_DATA(VIO_FIELD_MARK, PORT167_FN1),
-	PINMUX_DATA(VIO_CKO_MARK, PORT168_FN1),
-	PINMUX_DATA(MFG3_IN1_MARK, PORT169_FN2),
-	PINMUX_DATA(MFG3_IN2_MARK, PORT170_FN2),
-	PINMUX_DATA(M9_SLCD_A01_MARK, PORT171_FN1),
-	PINMUX_DATA(MFG3_OUT1_MARK, PORT171_FN2),
-	PINMUX_DATA(TPU0TO0_MARK, PORT171_FN3),
-	PINMUX_DATA(M10_SLCD_CK1_MARK, PORT172_FN1),
-	PINMUX_DATA(MFG4_IN1_MARK, PORT172_FN2),
-	PINMUX_DATA(TPU0TO1_MARK, PORT172_FN3),
-	PINMUX_DATA(M11_SLCD_SO1_MARK, PORT173_FN1),
-	PINMUX_DATA(MFG4_IN2_MARK, PORT173_FN2),
-	PINMUX_DATA(TPU0TO2_MARK, PORT173_FN3),
-	PINMUX_DATA(M12_SLCD_CE1_MARK, PORT174_FN1),
-	PINMUX_DATA(MFG4_OUT1_MARK, PORT174_FN2),
-	PINMUX_DATA(TPU0TO3_MARK, PORT174_FN3),
-	PINMUX_DATA(LCDD0_MARK, PORT175_FN1),
-	PINMUX_DATA(PORT175_KEYOUT0_MARK, PORT175_FN2),
-	PINMUX_DATA(DV_D0_MARK, PORT175_FN3),
-	PINMUX_DATA(SIUCKA_MARK, PORT175_FN4),
-	PINMUX_DATA(MFG0_OUT2_MARK, PORT175_FN5),
-	PINMUX_DATA(LCDD1_MARK, PORT176_FN1),
-	PINMUX_DATA(PORT176_KEYOUT1_MARK, PORT176_FN2),
-	PINMUX_DATA(DV_D1_MARK, PORT176_FN3),
-	PINMUX_DATA(SIUAOLR_MARK, PORT176_FN4),
-	PINMUX_DATA(BBIF2_TSYNC1_MARK, PORT176_FN5),
-	PINMUX_DATA(LCDD2_MARK, PORT177_FN1),
-	PINMUX_DATA(PORT177_KEYOUT2_MARK, PORT177_FN2),
-	PINMUX_DATA(DV_D2_MARK, PORT177_FN3),
-	PINMUX_DATA(SIUAOBT_MARK, PORT177_FN4),
-	PINMUX_DATA(BBIF2_TSCK1_MARK, PORT177_FN5),
-	PINMUX_DATA(LCDD3_MARK, PORT178_FN1),
-	PINMUX_DATA(PORT178_KEYOUT3_MARK, PORT178_FN2),
-	PINMUX_DATA(DV_D3_MARK, PORT178_FN3),
-	PINMUX_DATA(SIUAOSLD_MARK, PORT178_FN4),
-	PINMUX_DATA(BBIF2_TXD1_MARK, PORT178_FN5),
-	PINMUX_DATA(LCDD4_MARK, PORT179_FN1),
-	PINMUX_DATA(PORT179_KEYOUT4_MARK, PORT179_FN2),
-	PINMUX_DATA(DV_D4_MARK, PORT179_FN3),
-	PINMUX_DATA(SIUAISPD_MARK, PORT179_FN4),
-	PINMUX_DATA(MFG1_OUT2_MARK, PORT179_FN5),
-	PINMUX_DATA(LCDD5_MARK, PORT180_FN1),
-	PINMUX_DATA(PORT180_KEYOUT5_MARK, PORT180_FN2),
-	PINMUX_DATA(DV_D5_MARK, PORT180_FN3),
-	PINMUX_DATA(SIUAILR_MARK, PORT180_FN4),
-	PINMUX_DATA(MFG2_OUT2_MARK, PORT180_FN5),
-	PINMUX_DATA(LCDD6_MARK, PORT181_FN1),
-	PINMUX_DATA(DV_D6_MARK, PORT181_FN3),
-	PINMUX_DATA(SIUAIBT_MARK, PORT181_FN4),
-	PINMUX_DATA(MFG3_OUT2_MARK, PORT181_FN5),
-	PINMUX_DATA(XWR2_MARK, PORT181_FN7),
-	PINMUX_DATA(LCDD7_MARK, PORT182_FN1),
-	PINMUX_DATA(DV_D7_MARK, PORT182_FN3),
-	PINMUX_DATA(SIUAISLD_MARK, PORT182_FN4),
-	PINMUX_DATA(MFG4_OUT2_MARK, PORT182_FN5),
-	PINMUX_DATA(XWR3_MARK, PORT182_FN7),
-	PINMUX_DATA(LCDD8_MARK, PORT183_FN1),
-	PINMUX_DATA(DV_D8_MARK, PORT183_FN3),
-	PINMUX_DATA(D16_MARK, PORT183_FN6),
-	PINMUX_DATA(ED16_MARK, PORT183_FN7),
-	PINMUX_DATA(LCDD9_MARK, PORT184_FN1),
-	PINMUX_DATA(DV_D9_MARK, PORT184_FN3),
-	PINMUX_DATA(D17_MARK, PORT184_FN6),
-	PINMUX_DATA(ED17_MARK, PORT184_FN7),
-	PINMUX_DATA(LCDD10_MARK, PORT185_FN1),
-	PINMUX_DATA(DV_D10_MARK, PORT185_FN3),
-	PINMUX_DATA(D18_MARK, PORT185_FN6),
-	PINMUX_DATA(ED18_MARK, PORT185_FN7),
-	PINMUX_DATA(LCDD11_MARK, PORT186_FN1),
-	PINMUX_DATA(DV_D11_MARK, PORT186_FN3),
-	PINMUX_DATA(D19_MARK, PORT186_FN6),
-	PINMUX_DATA(ED19_MARK, PORT186_FN7),
-	PINMUX_DATA(LCDD12_MARK, PORT187_FN1),
-	PINMUX_DATA(DV_D12_MARK, PORT187_FN3),
-	PINMUX_DATA(D20_MARK, PORT187_FN6),
-	PINMUX_DATA(ED20_MARK, PORT187_FN7),
-	PINMUX_DATA(LCDD13_MARK, PORT188_FN1),
-	PINMUX_DATA(DV_D13_MARK, PORT188_FN3),
-	PINMUX_DATA(D21_MARK, PORT188_FN6),
-	PINMUX_DATA(ED21_MARK, PORT188_FN7),
-	PINMUX_DATA(LCDD14_MARK, PORT189_FN1),
-	PINMUX_DATA(DV_D14_MARK, PORT189_FN3),
-	PINMUX_DATA(D22_MARK, PORT189_FN6),
-	PINMUX_DATA(ED22_MARK, PORT189_FN7),
-	PINMUX_DATA(LCDD15_MARK, PORT190_FN1),
-	PINMUX_DATA(DV_D15_MARK, PORT190_FN3),
-	PINMUX_DATA(D23_MARK, PORT190_FN6),
-	PINMUX_DATA(ED23_MARK, PORT190_FN7),
-	PINMUX_DATA(LCDD16_MARK, PORT191_FN1),
-	PINMUX_DATA(DV_HSYNC_MARK, PORT191_FN3),
-	PINMUX_DATA(D24_MARK, PORT191_FN6),
-	PINMUX_DATA(ED24_MARK, PORT191_FN7),
-	PINMUX_DATA(LCDD17_MARK, PORT192_FN1),
-	PINMUX_DATA(DV_VSYNC_MARK, PORT192_FN3),
-	PINMUX_DATA(D25_MARK, PORT192_FN6),
-	PINMUX_DATA(ED25_MARK, PORT192_FN7),
-	PINMUX_DATA(LCDD18_MARK, PORT193_FN1),
-	PINMUX_DATA(DREQ2_MARK, PORT193_FN2),
-	PINMUX_DATA(MSIOF0L_TSCK_MARK, PORT193_FN5),
-	PINMUX_DATA(D26_MARK, PORT193_FN6),
-	PINMUX_DATA(ED26_MARK, PORT193_FN7),
-	PINMUX_DATA(LCDD19_MARK, PORT194_FN1),
-	PINMUX_DATA(MSIOF0L_TSYNC_MARK, PORT194_FN5),
-	PINMUX_DATA(D27_MARK, PORT194_FN6),
-	PINMUX_DATA(ED27_MARK, PORT194_FN7),
-	PINMUX_DATA(LCDD20_MARK, PORT195_FN1),
-	PINMUX_DATA(TS_SPSYNC1_MARK, PORT195_FN2),
-	PINMUX_DATA(MSIOF0L_MCK0_MARK, PORT195_FN5),
-	PINMUX_DATA(D28_MARK, PORT195_FN6),
-	PINMUX_DATA(ED28_MARK, PORT195_FN7),
-	PINMUX_DATA(LCDD21_MARK, PORT196_FN1),
-	PINMUX_DATA(TS_SDAT1_MARK, PORT196_FN2),
-	PINMUX_DATA(MSIOF0L_MCK1_MARK, PORT196_FN5),
-	PINMUX_DATA(D29_MARK, PORT196_FN6),
-	PINMUX_DATA(ED29_MARK, PORT196_FN7),
-	PINMUX_DATA(LCDD22_MARK, PORT197_FN1),
-	PINMUX_DATA(TS_SDEN1_MARK, PORT197_FN2),
-	PINMUX_DATA(MSIOF0L_SS1_MARK, PORT197_FN5),
-	PINMUX_DATA(D30_MARK, PORT197_FN6),
-	PINMUX_DATA(ED30_MARK, PORT197_FN7),
-	PINMUX_DATA(LCDD23_MARK, PORT198_FN1),
-	PINMUX_DATA(TS_SCK1_MARK, PORT198_FN2),
-	PINMUX_DATA(MSIOF0L_SS2_MARK, PORT198_FN5),
-	PINMUX_DATA(D31_MARK, PORT198_FN6),
-	PINMUX_DATA(ED31_MARK, PORT198_FN7),
-	PINMUX_DATA(LCDDCK_MARK, PORT199_FN1),
-	PINMUX_DATA(LCDWR_MARK, PORT199_FN2),
-	PINMUX_DATA(DV_CKO_MARK, PORT199_FN3),
-	PINMUX_DATA(SIUAOSPD_MARK, PORT199_FN4),
-	PINMUX_DATA(LCDRD_MARK, PORT200_FN1),
-	PINMUX_DATA(DACK2_MARK, PORT200_FN2),
-	PINMUX_DATA(MSIOF0L_RSYNC_MARK, PORT200_FN5),
-
-	/* 49-5 (FN) */
-	PINMUX_DATA(LCDHSYN_MARK, PORT201_FN1),
-	PINMUX_DATA(LCDCS_MARK, PORT201_FN2),
-	PINMUX_DATA(LCDCS2_MARK, PORT201_FN3),
-	PINMUX_DATA(DACK3_MARK, PORT201_FN4),
-	PINMUX_DATA(LCDDISP_MARK, PORT202_FN1),
-	PINMUX_DATA(LCDRS_MARK, PORT202_FN2),
-	PINMUX_DATA(DREQ3_MARK, PORT202_FN4),
-	PINMUX_DATA(MSIOF0L_RSCK_MARK, PORT202_FN5),
-	PINMUX_DATA(LCDCSYN_MARK, PORT203_FN1),
-	PINMUX_DATA(LCDCSYN2_MARK, PORT203_FN2),
-	PINMUX_DATA(DV_CKI_MARK, PORT203_FN3),
-	PINMUX_DATA(LCDLCLK_MARK, PORT204_FN1),
-	PINMUX_DATA(DREQ1_MARK, PORT204_FN3),
-	PINMUX_DATA(MSIOF0L_RXD_MARK, PORT204_FN5),
-	PINMUX_DATA(LCDDON_MARK, PORT205_FN1),
-	PINMUX_DATA(LCDDON2_MARK, PORT205_FN2),
-	PINMUX_DATA(DACK1_MARK, PORT205_FN3),
-	PINMUX_DATA(MSIOF0L_TXD_MARK, PORT205_FN5),
-	PINMUX_DATA(VIO_DR0_MARK, PORT206_FN1),
-	PINMUX_DATA(VIO_DR1_MARK, PORT207_FN1),
-	PINMUX_DATA(VIO_DR2_MARK, PORT208_FN1),
-	PINMUX_DATA(VIO_DR3_MARK, PORT209_FN1),
-	PINMUX_DATA(VIO_DR4_MARK, PORT210_FN1),
-	PINMUX_DATA(VIO_DR5_MARK, PORT211_FN1),
-	PINMUX_DATA(VIO_DR6_MARK, PORT212_FN1),
-	PINMUX_DATA(VIO_DR7_MARK, PORT213_FN1),
-	PINMUX_DATA(VIO_VDR_MARK, PORT214_FN1),
-	PINMUX_DATA(VIO_HDR_MARK, PORT215_FN1),
-	PINMUX_DATA(VIO_CLKR_MARK, PORT216_FN1),
-	PINMUX_DATA(VIO_CKOR_MARK, PORT217_FN1),
-	PINMUX_DATA(SCIFA1_TXD_MARK, PORT220_FN2),
-	PINMUX_DATA(GPS_PGFA0_MARK, PORT220_FN3),
-	PINMUX_DATA(SCIFA1_SCK_MARK, PORT221_FN2),
-	PINMUX_DATA(GPS_PGFA1_MARK, PORT221_FN3),
-	PINMUX_DATA(SCIFA1_RTS_MARK, PORT222_FN2),
-	PINMUX_DATA(GPS_EPPSINMON_MARK, PORT222_FN3),
-	PINMUX_DATA(SCIFA1_RXD_MARK, PORT223_FN2),
-	PINMUX_DATA(SCIFA1_CTS_MARK, PORT224_FN2),
-	PINMUX_DATA(MSIOF1_TXD_MARK, PORT225_FN1),
-	PINMUX_DATA(SCIFA1_TXD2_MARK, PORT225_FN2),
-	PINMUX_DATA(GPS_TXD_MARK, PORT225_FN3),
-	PINMUX_DATA(MSIOF1_TSYNC_MARK, PORT226_FN1),
-	PINMUX_DATA(SCIFA1_CTS2_MARK, PORT226_FN2),
-	PINMUX_DATA(I2C_SDA2_MARK, PORT226_FN3),
-	PINMUX_DATA(MSIOF1_TSCK_MARK, PORT227_FN1),
-	PINMUX_DATA(SCIFA1_SCK2_MARK, PORT227_FN2),
-	PINMUX_DATA(MSIOF1_RXD_MARK, PORT228_FN1),
-	PINMUX_DATA(SCIFA1_RXD2_MARK, PORT228_FN2),
-	PINMUX_DATA(GPS_RXD_MARK, PORT228_FN3),
-	PINMUX_DATA(MSIOF1_RSCK_MARK, PORT229_FN1),
-	PINMUX_DATA(SCIFA1_RTS2_MARK, PORT229_FN2),
-	PINMUX_DATA(MSIOF1_RSYNC_MARK, PORT230_FN1),
-	PINMUX_DATA(I2C_SCL2_MARK, PORT230_FN3),
-	PINMUX_DATA(MSIOF1_MCK0_MARK, PORT231_FN1),
-	PINMUX_DATA(MSIOF1_MCK1_MARK, PORT232_FN1),
-	PINMUX_DATA(MSIOF1_SS1_MARK, PORT233_FN1),
-	PINMUX_DATA(EDBGREQ3_MARK, PORT233_FN2),
-	PINMUX_DATA(MSIOF1_SS2_MARK, PORT234_FN1),
-	PINMUX_DATA(PORT236_IROUT_MARK, PORT236_FN1),
-	PINMUX_DATA(IRDA_OUT_MARK, PORT236_FN2),
-	PINMUX_DATA(IRDA_IN_MARK, PORT237_FN2),
-	PINMUX_DATA(IRDA_FIRSEL_MARK, PORT238_FN1),
-	PINMUX_DATA(TPU1TO0_MARK, PORT239_FN3),
-	PINMUX_DATA(TS_SPSYNC3_MARK, PORT239_FN4),
-	PINMUX_DATA(TPU1TO1_MARK, PORT240_FN3),
-	PINMUX_DATA(TS_SDAT3_MARK, PORT240_FN4),
-	PINMUX_DATA(TPU1TO2_MARK, PORT241_FN3),
-	PINMUX_DATA(TS_SDEN3_MARK, PORT241_FN4),
-	PINMUX_DATA(PORT241_MSIOF2_SS1_MARK, PORT241_FN5),
-	PINMUX_DATA(TPU1TO3_MARK, PORT242_FN3),
-	PINMUX_DATA(PORT242_MSIOF2_TSCK_MARK, PORT242_FN5),
-	PINMUX_DATA(M13_BSW_MARK, PORT243_FN2),
-	PINMUX_DATA(PORT243_MSIOF2_TSYNC_MARK, PORT243_FN5),
-	PINMUX_DATA(M14_GSW_MARK, PORT244_FN2),
-	PINMUX_DATA(PORT244_MSIOF2_TXD_MARK, PORT244_FN5),
-	PINMUX_DATA(PORT245_IROUT_MARK, PORT245_FN1),
-	PINMUX_DATA(M15_RSW_MARK, PORT245_FN2),
-	PINMUX_DATA(SOUT3_MARK, PORT246_FN1),
-	PINMUX_DATA(SCIFA2_TXD1_MARK, PORT246_FN2),
-	PINMUX_DATA(SIN3_MARK, PORT247_FN1),
-	PINMUX_DATA(SCIFA2_RXD1_MARK, PORT247_FN2),
-	PINMUX_DATA(XRTS3_MARK, PORT248_FN1),
-	PINMUX_DATA(SCIFA2_RTS1_MARK, PORT248_FN2),
-	PINMUX_DATA(PORT248_MSIOF2_SS2_MARK, PORT248_FN5),
-	PINMUX_DATA(XCTS3_MARK, PORT249_FN1),
-	PINMUX_DATA(SCIFA2_CTS1_MARK, PORT249_FN2),
-	PINMUX_DATA(PORT249_MSIOF2_RXD_MARK, PORT249_FN5),
-	PINMUX_DATA(DINT_MARK, PORT250_FN1),
-	PINMUX_DATA(SCIFA2_SCK1_MARK, PORT250_FN2),
-	PINMUX_DATA(TS_SCK3_MARK, PORT250_FN4),
-	PINMUX_DATA(SDHICLK0_MARK, PORT251_FN1),
-	PINMUX_DATA(TCK2_MARK, PORT251_FN2),
-	PINMUX_DATA(SDHICD0_MARK, PORT252_FN1),
-	PINMUX_DATA(SDHID0_0_MARK, PORT253_FN1),
-	PINMUX_DATA(TMS2_MARK, PORT253_FN2),
-	PINMUX_DATA(SDHID0_1_MARK, PORT254_FN1),
-	PINMUX_DATA(TDO2_MARK, PORT254_FN2),
-	PINMUX_DATA(SDHID0_2_MARK, PORT255_FN1),
-	PINMUX_DATA(TDI2_MARK, PORT255_FN2),
-	PINMUX_DATA(SDHID0_3_MARK, PORT256_FN1),
-	PINMUX_DATA(RTCK2_MARK, PORT256_FN2),
-
-	/* 49-6 (FN) */
-	PINMUX_DATA(SDHICMD0_MARK, PORT257_FN1),
-	PINMUX_DATA(TRST2_MARK, PORT257_FN2),
-	PINMUX_DATA(SDHIWP0_MARK, PORT258_FN1),
-	PINMUX_DATA(EDBGREQ2_MARK, PORT258_FN2),
-	PINMUX_DATA(SDHICLK1_MARK, PORT259_FN1),
-	PINMUX_DATA(TCK3_MARK, PORT259_FN4),
-	PINMUX_DATA(SDHID1_0_MARK, PORT260_FN1),
-	PINMUX_DATA(M11_SLCD_SO2_MARK, PORT260_FN2),
-	PINMUX_DATA(TS_SPSYNC2_MARK, PORT260_FN3),
-	PINMUX_DATA(TMS3_MARK, PORT260_FN4),
-	PINMUX_DATA(SDHID1_1_MARK, PORT261_FN1),
-	PINMUX_DATA(M9_SLCD_AO2_MARK, PORT261_FN2),
-	PINMUX_DATA(TS_SDAT2_MARK, PORT261_FN3),
-	PINMUX_DATA(TDO3_MARK, PORT261_FN4),
-	PINMUX_DATA(SDHID1_2_MARK, PORT262_FN1),
-	PINMUX_DATA(M10_SLCD_CK2_MARK, PORT262_FN2),
-	PINMUX_DATA(TS_SDEN2_MARK, PORT262_FN3),
-	PINMUX_DATA(TDI3_MARK, PORT262_FN4),
-	PINMUX_DATA(SDHID1_3_MARK, PORT263_FN1),
-	PINMUX_DATA(M12_SLCD_CE2_MARK, PORT263_FN2),
-	PINMUX_DATA(TS_SCK2_MARK, PORT263_FN3),
-	PINMUX_DATA(RTCK3_MARK, PORT263_FN4),
-	PINMUX_DATA(SDHICMD1_MARK, PORT264_FN1),
-	PINMUX_DATA(TRST3_MARK, PORT264_FN4),
-	PINMUX_DATA(SDHICLK2_MARK, PORT265_FN1),
-	PINMUX_DATA(SCIFB_SCK_MARK, PORT265_FN2),
-	PINMUX_DATA(SDHID2_0_MARK, PORT266_FN1),
-	PINMUX_DATA(SCIFB_TXD_MARK, PORT266_FN2),
-	PINMUX_DATA(SDHID2_1_MARK, PORT267_FN1),
-	PINMUX_DATA(SCIFB_CTS_MARK, PORT267_FN2),
-	PINMUX_DATA(SDHID2_2_MARK, PORT268_FN1),
-	PINMUX_DATA(SCIFB_RXD_MARK, PORT268_FN2),
-	PINMUX_DATA(SDHID2_3_MARK, PORT269_FN1),
-	PINMUX_DATA(SCIFB_RTS_MARK, PORT269_FN2),
-	PINMUX_DATA(SDHICMD2_MARK, PORT270_FN1),
-	PINMUX_DATA(RESETOUTS_MARK, PORT271_FN1),
-	PINMUX_DATA(DIVLOCK_MARK, PORT272_FN1),
-};
-
-static struct pinmux_gpio pinmux_gpios[] = {
-	/* 49-1 -> 49-6 (GPIO) */
-	GPIO_PORT_ALL(),
-
-	/* Special Pull-up / Pull-down Functions */
-	GPIO_FN(PORT48_KEYIN0_PU), GPIO_FN(PORT49_KEYIN1_PU),
-	GPIO_FN(PORT50_KEYIN2_PU), GPIO_FN(PORT55_KEYIN3_PU),
-	GPIO_FN(PORT56_KEYIN4_PU), GPIO_FN(PORT57_KEYIN5_PU),
-	GPIO_FN(PORT58_KEYIN6_PU),
-
-	/* 49-1 (FN) */
-	GPIO_FN(VBUS0), GPIO_FN(CPORT0), GPIO_FN(CPORT1), GPIO_FN(CPORT2),
-	GPIO_FN(CPORT3), GPIO_FN(CPORT4), GPIO_FN(CPORT5), GPIO_FN(CPORT6),
-	GPIO_FN(CPORT7), GPIO_FN(CPORT8), GPIO_FN(CPORT9), GPIO_FN(CPORT10),
-	GPIO_FN(CPORT11), GPIO_FN(SIN2), GPIO_FN(CPORT12), GPIO_FN(XCTS2),
-	GPIO_FN(CPORT13), GPIO_FN(RFSPO4), GPIO_FN(CPORT14), GPIO_FN(RFSPO5),
-	GPIO_FN(CPORT15), GPIO_FN(CPORT16), GPIO_FN(CPORT17), GPIO_FN(SOUT2),
-	GPIO_FN(CPORT18), GPIO_FN(XRTS2), GPIO_FN(CPORT19), GPIO_FN(CPORT20),
-	GPIO_FN(RFSPO6), GPIO_FN(CPORT21), GPIO_FN(STATUS0), GPIO_FN(CPORT22),
-	GPIO_FN(STATUS1), GPIO_FN(CPORT23), GPIO_FN(STATUS2), GPIO_FN(RFSPO7),
-	GPIO_FN(MPORT0), GPIO_FN(MPORT1), GPIO_FN(B_SYNLD1), GPIO_FN(B_SYNLD2),
-	GPIO_FN(XMAINPS), GPIO_FN(XDIVPS), GPIO_FN(XIDRST), GPIO_FN(IDCLK),
-	GPIO_FN(IDIO), GPIO_FN(SOUT1), GPIO_FN(SCIFA4_TXD),
-	GPIO_FN(M02_BERDAT), GPIO_FN(SIN1), GPIO_FN(SCIFA4_RXD), GPIO_FN(XWUP),
-	GPIO_FN(XRTS1), GPIO_FN(SCIFA4_RTS), GPIO_FN(M03_BERCLK),
-	GPIO_FN(XCTS1), GPIO_FN(SCIFA4_CTS),
-
-	/* 49-2 (FN) */
-	GPIO_FN(HSU_IQ_AGC6), GPIO_FN(MFG2_IN2), GPIO_FN(MSIOF2_MCK0),
-	GPIO_FN(HSU_IQ_AGC5), GPIO_FN(MFG2_IN1), GPIO_FN(MSIOF2_MCK1),
-	GPIO_FN(HSU_IQ_AGC4), GPIO_FN(MSIOF2_RSYNC),
-	GPIO_FN(HSU_IQ_AGC3), GPIO_FN(MFG2_OUT1), GPIO_FN(MSIOF2_RSCK),
-	GPIO_FN(HSU_IQ_AGC2), GPIO_FN(PORT42_KEYOUT0),
-	GPIO_FN(HSU_IQ_AGC1), GPIO_FN(PORT43_KEYOUT1),
-	GPIO_FN(HSU_IQ_AGC0), GPIO_FN(PORT44_KEYOUT2),
-	GPIO_FN(HSU_IQ_AGC_ST), GPIO_FN(PORT45_KEYOUT3),
-	GPIO_FN(HSU_IQ_PDO), GPIO_FN(PORT46_KEYOUT4),
-	GPIO_FN(HSU_IQ_PYO), GPIO_FN(PORT47_KEYOUT5),
-	GPIO_FN(HSU_EN_TXMUX_G3MO), GPIO_FN(PORT48_KEYIN0),
-	GPIO_FN(HSU_I_TXMUX_G3MO), GPIO_FN(PORT49_KEYIN1),
-	GPIO_FN(HSU_Q_TXMUX_G3MO), GPIO_FN(PORT50_KEYIN2),
-	GPIO_FN(HSU_SYO), GPIO_FN(PORT51_MSIOF2_TSYNC),
-	GPIO_FN(HSU_SDO), GPIO_FN(PORT52_MSIOF2_TSCK),
-	GPIO_FN(HSU_TGTTI_G3MO), GPIO_FN(PORT53_MSIOF2_TXD),
-	GPIO_FN(B_TIME_STAMP), GPIO_FN(PORT54_MSIOF2_RXD),
-	GPIO_FN(HSU_SDI), GPIO_FN(PORT55_KEYIN3),
-	GPIO_FN(HSU_SCO), GPIO_FN(PORT56_KEYIN4),
-	GPIO_FN(HSU_DREQ), GPIO_FN(PORT57_KEYIN5),
-	GPIO_FN(HSU_DACK), GPIO_FN(PORT58_KEYIN6),
-	GPIO_FN(HSU_CLK61M), GPIO_FN(PORT59_MSIOF2_SS1),
-	GPIO_FN(HSU_XRST), GPIO_FN(PORT60_MSIOF2_SS2),
-	GPIO_FN(PCMCLKO), GPIO_FN(SYNC8KO), GPIO_FN(DNPCM_A), GPIO_FN(UPPCM_A),
-	GPIO_FN(XTALB1L),
-	GPIO_FN(GPS_AGC1), GPIO_FN(SCIFA0_RTS),
-	GPIO_FN(GPS_AGC2), GPIO_FN(SCIFA0_SCK),
-	GPIO_FN(GPS_AGC3), GPIO_FN(SCIFA0_TXD),
-	GPIO_FN(GPS_AGC4), GPIO_FN(SCIFA0_RXD),
-	GPIO_FN(GPS_PWRD), GPIO_FN(SCIFA0_CTS),
-	GPIO_FN(GPS_IM), GPIO_FN(GPS_IS), GPIO_FN(GPS_QM), GPIO_FN(GPS_QS),
-	GPIO_FN(SIUBOMC), GPIO_FN(TPU2TO0),
-	GPIO_FN(SIUCKB), GPIO_FN(TPU2TO1),
-	GPIO_FN(SIUBOLR), GPIO_FN(BBIF2_TSYNC), GPIO_FN(TPU2TO2),
-	GPIO_FN(SIUBOBT), GPIO_FN(BBIF2_TSCK), GPIO_FN(TPU2TO3),
-	GPIO_FN(SIUBOSLD), GPIO_FN(BBIF2_TXD), GPIO_FN(TPU3TO0),
-	GPIO_FN(SIUBILR), GPIO_FN(TPU3TO1),
-	GPIO_FN(SIUBIBT), GPIO_FN(TPU3TO2),
-	GPIO_FN(SIUBISLD), GPIO_FN(TPU3TO3),
-	GPIO_FN(NMI), GPIO_FN(TPU4TO0),
-	GPIO_FN(DNPCM_M), GPIO_FN(TPU4TO1), GPIO_FN(TPU4TO2), GPIO_FN(TPU4TO3),
-	GPIO_FN(IRQ_TMPB),
-	GPIO_FN(PWEN), GPIO_FN(MFG1_OUT1),
-	GPIO_FN(OVCN), GPIO_FN(MFG1_IN1),
-	GPIO_FN(OVCN2), GPIO_FN(MFG1_IN2),
-
-	/* 49-3 (FN) */
-	GPIO_FN(RFSPO1), GPIO_FN(RFSPO2), GPIO_FN(RFSPO3),
-	GPIO_FN(PORT93_VIO_CKO2),
-	GPIO_FN(USBTERM), GPIO_FN(EXTLP), GPIO_FN(IDIN),
-	GPIO_FN(SCIFA5_CTS), GPIO_FN(MFG0_IN1),
-	GPIO_FN(SCIFA5_RTS), GPIO_FN(MFG0_IN2),
-	GPIO_FN(SCIFA5_RXD),
-	GPIO_FN(SCIFA5_TXD),
-	GPIO_FN(SCIFA5_SCK), GPIO_FN(MFG0_OUT1),
-	GPIO_FN(A0_EA0), GPIO_FN(BS),
-	GPIO_FN(A14_EA14), GPIO_FN(PORT102_KEYOUT0),
-	GPIO_FN(A15_EA15), GPIO_FN(PORT103_KEYOUT1), GPIO_FN(DV_CLKOL),
-	GPIO_FN(A16_EA16), GPIO_FN(PORT104_KEYOUT2),
-	GPIO_FN(DV_VSYNCL), GPIO_FN(MSIOF0_SS1),
-	GPIO_FN(A17_EA17), GPIO_FN(PORT105_KEYOUT3),
-	GPIO_FN(DV_HSYNCL), GPIO_FN(MSIOF0_TSYNC),
-	GPIO_FN(A18_EA18), GPIO_FN(PORT106_KEYOUT4),
-	GPIO_FN(DV_DL0), GPIO_FN(MSIOF0_TSCK),
-	GPIO_FN(A19_EA19), GPIO_FN(PORT107_KEYOUT5),
-	GPIO_FN(DV_DL1), GPIO_FN(MSIOF0_TXD),
-	GPIO_FN(A20_EA20), GPIO_FN(PORT108_KEYIN0),
-	GPIO_FN(DV_DL2), GPIO_FN(MSIOF0_RSCK),
-	GPIO_FN(A21_EA21), GPIO_FN(PORT109_KEYIN1),
-	GPIO_FN(DV_DL3), GPIO_FN(MSIOF0_RSYNC),
-	GPIO_FN(A22_EA22), GPIO_FN(PORT110_KEYIN2),
-	GPIO_FN(DV_DL4), GPIO_FN(MSIOF0_MCK0),
-	GPIO_FN(A23_EA23), GPIO_FN(PORT111_KEYIN3),
-	GPIO_FN(DV_DL5), GPIO_FN(MSIOF0_MCK1),
-	GPIO_FN(A24_EA24), GPIO_FN(PORT112_KEYIN4),
-	GPIO_FN(DV_DL6), GPIO_FN(MSIOF0_RXD),
-	GPIO_FN(A25_EA25), GPIO_FN(PORT113_KEYIN5),
-	GPIO_FN(DV_DL7), GPIO_FN(MSIOF0_SS2),
-	GPIO_FN(A26), GPIO_FN(PORT113_KEYIN6), GPIO_FN(DV_CLKIL),
-	GPIO_FN(D0_ED0_NAF0), GPIO_FN(D1_ED1_NAF1), GPIO_FN(D2_ED2_NAF2),
-	GPIO_FN(D3_ED3_NAF3), GPIO_FN(D4_ED4_NAF4), GPIO_FN(D5_ED5_NAF5),
-	GPIO_FN(D6_ED6_NAF6), GPIO_FN(D7_ED7_NAF7), GPIO_FN(D8_ED8_NAF8),
-	GPIO_FN(D9_ED9_NAF9), GPIO_FN(D10_ED10_NAF10), GPIO_FN(D11_ED11_NAF11),
-	GPIO_FN(D12_ED12_NAF12), GPIO_FN(D13_ED13_NAF13),
-	GPIO_FN(D14_ED14_NAF14), GPIO_FN(D15_ED15_NAF15),
-	GPIO_FN(CS4), GPIO_FN(CS5A), GPIO_FN(CS5B), GPIO_FN(FCE1),
-	GPIO_FN(CS6B), GPIO_FN(XCS2), GPIO_FN(FCE0), GPIO_FN(CS6A),
-	GPIO_FN(DACK0), GPIO_FN(WAIT), GPIO_FN(DREQ0), GPIO_FN(RD_XRD),
-	GPIO_FN(A27), GPIO_FN(RDWR_XWE), GPIO_FN(WE0_XWR0_FWE),
-	GPIO_FN(WE1_XWR1), GPIO_FN(FRB), GPIO_FN(CKO),
-	GPIO_FN(NBRSTOUT), GPIO_FN(NBRST),
-
-	/* 49-4 (FN) */
-	GPIO_FN(RFSPO0), GPIO_FN(PORT146_VIO_CKO2), GPIO_FN(TSTMD),
-	GPIO_FN(VIO_VD), GPIO_FN(VIO_HD),
-	GPIO_FN(VIO_D0), GPIO_FN(VIO_D1), GPIO_FN(VIO_D2),
-	GPIO_FN(VIO_D3), GPIO_FN(VIO_D4), GPIO_FN(VIO_D5),
-	GPIO_FN(VIO_D6), GPIO_FN(VIO_D7), GPIO_FN(VIO_D8),
-	GPIO_FN(VIO_D9), GPIO_FN(VIO_D10), GPIO_FN(VIO_D11),
-	GPIO_FN(VIO_D12), GPIO_FN(VIO_D13), GPIO_FN(VIO_D14),
-	GPIO_FN(VIO_D15), GPIO_FN(VIO_CLK), GPIO_FN(VIO_FIELD),
-	GPIO_FN(VIO_CKO),
-	GPIO_FN(MFG3_IN1), GPIO_FN(MFG3_IN2),
-	GPIO_FN(M9_SLCD_A01), GPIO_FN(MFG3_OUT1), GPIO_FN(TPU0TO0),
-	GPIO_FN(M10_SLCD_CK1), GPIO_FN(MFG4_IN1), GPIO_FN(TPU0TO1),
-	GPIO_FN(M11_SLCD_SO1), GPIO_FN(MFG4_IN2), GPIO_FN(TPU0TO2),
-	GPIO_FN(M12_SLCD_CE1), GPIO_FN(MFG4_OUT1), GPIO_FN(TPU0TO3),
-	GPIO_FN(LCDD0), GPIO_FN(PORT175_KEYOUT0), GPIO_FN(DV_D0),
-	GPIO_FN(SIUCKA), GPIO_FN(MFG0_OUT2),
-	GPIO_FN(LCDD1), GPIO_FN(PORT176_KEYOUT1), GPIO_FN(DV_D1),
-	GPIO_FN(SIUAOLR), GPIO_FN(BBIF2_TSYNC1),
-	GPIO_FN(LCDD2), GPIO_FN(PORT177_KEYOUT2), GPIO_FN(DV_D2),
-	GPIO_FN(SIUAOBT), GPIO_FN(BBIF2_TSCK1),
-	GPIO_FN(LCDD3), GPIO_FN(PORT178_KEYOUT3), GPIO_FN(DV_D3),
-	GPIO_FN(SIUAOSLD), GPIO_FN(BBIF2_TXD1),
-	GPIO_FN(LCDD4), GPIO_FN(PORT179_KEYOUT4), GPIO_FN(DV_D4),
-	GPIO_FN(SIUAISPD), GPIO_FN(MFG1_OUT2),
-	GPIO_FN(LCDD5), GPIO_FN(PORT180_KEYOUT5), GPIO_FN(DV_D5),
-	GPIO_FN(SIUAILR), GPIO_FN(MFG2_OUT2),
-	GPIO_FN(LCDD6), GPIO_FN(DV_D6),
-	GPIO_FN(SIUAIBT), GPIO_FN(MFG3_OUT2), GPIO_FN(XWR2),
-	GPIO_FN(LCDD7), GPIO_FN(DV_D7),
-	GPIO_FN(SIUAISLD), GPIO_FN(MFG4_OUT2), GPIO_FN(XWR3),
-	GPIO_FN(LCDD8), GPIO_FN(DV_D8), GPIO_FN(D16), GPIO_FN(ED16),
-	GPIO_FN(LCDD9), GPIO_FN(DV_D9), GPIO_FN(D17), GPIO_FN(ED17),
-	GPIO_FN(LCDD10), GPIO_FN(DV_D10), GPIO_FN(D18), GPIO_FN(ED18),
-	GPIO_FN(LCDD11), GPIO_FN(DV_D11), GPIO_FN(D19), GPIO_FN(ED19),
-	GPIO_FN(LCDD12), GPIO_FN(DV_D12), GPIO_FN(D20), GPIO_FN(ED20),
-	GPIO_FN(LCDD13), GPIO_FN(DV_D13), GPIO_FN(D21), GPIO_FN(ED21),
-	GPIO_FN(LCDD14), GPIO_FN(DV_D14), GPIO_FN(D22), GPIO_FN(ED22),
-	GPIO_FN(LCDD15), GPIO_FN(DV_D15), GPIO_FN(D23), GPIO_FN(ED23),
-	GPIO_FN(LCDD16), GPIO_FN(DV_HSYNC), GPIO_FN(D24), GPIO_FN(ED24),
-	GPIO_FN(LCDD17), GPIO_FN(DV_VSYNC), GPIO_FN(D25), GPIO_FN(ED25),
-	GPIO_FN(LCDD18), GPIO_FN(DREQ2), GPIO_FN(MSIOF0L_TSCK),
-	GPIO_FN(D26), GPIO_FN(ED26),
-	GPIO_FN(LCDD19), GPIO_FN(MSIOF0L_TSYNC),
-	GPIO_FN(D27), GPIO_FN(ED27),
-	GPIO_FN(LCDD20), GPIO_FN(TS_SPSYNC1), GPIO_FN(MSIOF0L_MCK0),
-	GPIO_FN(D28), GPIO_FN(ED28),
-	GPIO_FN(LCDD21), GPIO_FN(TS_SDAT1), GPIO_FN(MSIOF0L_MCK1),
-	GPIO_FN(D29), GPIO_FN(ED29),
-	GPIO_FN(LCDD22), GPIO_FN(TS_SDEN1), GPIO_FN(MSIOF0L_SS1),
-	GPIO_FN(D30), GPIO_FN(ED30),
-	GPIO_FN(LCDD23), GPIO_FN(TS_SCK1), GPIO_FN(MSIOF0L_SS2),
-	GPIO_FN(D31), GPIO_FN(ED31),
-	GPIO_FN(LCDDCK), GPIO_FN(LCDWR), GPIO_FN(DV_CKO), GPIO_FN(SIUAOSPD),
-	GPIO_FN(LCDRD), GPIO_FN(DACK2), GPIO_FN(MSIOF0L_RSYNC),
-
-	/* 49-5 (FN) */
-	GPIO_FN(LCDHSYN), GPIO_FN(LCDCS), GPIO_FN(LCDCS2), GPIO_FN(DACK3),
-	GPIO_FN(LCDDISP), GPIO_FN(LCDRS), GPIO_FN(DREQ3), GPIO_FN(MSIOF0L_RSCK),
-	GPIO_FN(LCDCSYN), GPIO_FN(LCDCSYN2), GPIO_FN(DV_CKI),
-	GPIO_FN(LCDLCLK), GPIO_FN(DREQ1), GPIO_FN(MSIOF0L_RXD),
-	GPIO_FN(LCDDON), GPIO_FN(LCDDON2), GPIO_FN(DACK1), GPIO_FN(MSIOF0L_TXD),
-	GPIO_FN(VIO_DR0), GPIO_FN(VIO_DR1), GPIO_FN(VIO_DR2), GPIO_FN(VIO_DR3),
-	GPIO_FN(VIO_DR4), GPIO_FN(VIO_DR5), GPIO_FN(VIO_DR6), GPIO_FN(VIO_DR7),
-	GPIO_FN(VIO_VDR), GPIO_FN(VIO_HDR),
-	GPIO_FN(VIO_CLKR), GPIO_FN(VIO_CKOR),
-	GPIO_FN(SCIFA1_TXD), GPIO_FN(GPS_PGFA0),
-	GPIO_FN(SCIFA1_SCK), GPIO_FN(GPS_PGFA1),
-	GPIO_FN(SCIFA1_RTS), GPIO_FN(GPS_EPPSINMON),
-	GPIO_FN(SCIFA1_RXD), GPIO_FN(SCIFA1_CTS),
-	GPIO_FN(MSIOF1_TXD), GPIO_FN(SCIFA1_TXD2), GPIO_FN(GPS_TXD),
-	GPIO_FN(MSIOF1_TSYNC), GPIO_FN(SCIFA1_CTS2), GPIO_FN(I2C_SDA2),
-	GPIO_FN(MSIOF1_TSCK), GPIO_FN(SCIFA1_SCK2),
-	GPIO_FN(MSIOF1_RXD), GPIO_FN(SCIFA1_RXD2), GPIO_FN(GPS_RXD),
-	GPIO_FN(MSIOF1_RSCK), GPIO_FN(SCIFA1_RTS2),
-	GPIO_FN(MSIOF1_RSYNC), GPIO_FN(I2C_SCL2),
-	GPIO_FN(MSIOF1_MCK0), GPIO_FN(MSIOF1_MCK1),
-	GPIO_FN(MSIOF1_SS1), GPIO_FN(EDBGREQ3),
-	GPIO_FN(MSIOF1_SS2),
-	GPIO_FN(PORT236_IROUT), GPIO_FN(IRDA_OUT),
-	GPIO_FN(IRDA_IN), GPIO_FN(IRDA_FIRSEL),
-	GPIO_FN(TPU1TO0), GPIO_FN(TS_SPSYNC3),
-	GPIO_FN(TPU1TO1), GPIO_FN(TS_SDAT3),
-	GPIO_FN(TPU1TO2), GPIO_FN(TS_SDEN3), GPIO_FN(PORT241_MSIOF2_SS1),
-	GPIO_FN(TPU1TO3), GPIO_FN(PORT242_MSIOF2_TSCK),
-	GPIO_FN(M13_BSW), GPIO_FN(PORT243_MSIOF2_TSYNC),
-	GPIO_FN(M14_GSW), GPIO_FN(PORT244_MSIOF2_TXD),
-	GPIO_FN(PORT245_IROUT), GPIO_FN(M15_RSW),
-	GPIO_FN(SOUT3), GPIO_FN(SCIFA2_TXD1),
-	GPIO_FN(SIN3), GPIO_FN(SCIFA2_RXD1),
-	GPIO_FN(XRTS3), GPIO_FN(SCIFA2_RTS1), GPIO_FN(PORT248_MSIOF2_SS2),
-	GPIO_FN(XCTS3), GPIO_FN(SCIFA2_CTS1), GPIO_FN(PORT249_MSIOF2_RXD),
-	GPIO_FN(DINT), GPIO_FN(SCIFA2_SCK1), GPIO_FN(TS_SCK3),
-	GPIO_FN(SDHICLK0), GPIO_FN(TCK2),
-	GPIO_FN(SDHICD0),
-	GPIO_FN(SDHID0_0), GPIO_FN(TMS2),
-	GPIO_FN(SDHID0_1), GPIO_FN(TDO2),
-	GPIO_FN(SDHID0_2), GPIO_FN(TDI2),
-	GPIO_FN(SDHID0_3), GPIO_FN(RTCK2),
-
-	/* 49-6 (FN) */
-	GPIO_FN(SDHICMD0), GPIO_FN(TRST2),
-	GPIO_FN(SDHIWP0), GPIO_FN(EDBGREQ2),
-	GPIO_FN(SDHICLK1), GPIO_FN(TCK3),
-	GPIO_FN(SDHID1_0), GPIO_FN(M11_SLCD_SO2),
-	GPIO_FN(TS_SPSYNC2), GPIO_FN(TMS3),
-	GPIO_FN(SDHID1_1), GPIO_FN(M9_SLCD_AO2),
-	GPIO_FN(TS_SDAT2), GPIO_FN(TDO3),
-	GPIO_FN(SDHID1_2), GPIO_FN(M10_SLCD_CK2),
-	GPIO_FN(TS_SDEN2), GPIO_FN(TDI3),
-	GPIO_FN(SDHID1_3), GPIO_FN(M12_SLCD_CE2),
-	GPIO_FN(TS_SCK2), GPIO_FN(RTCK3),
-	GPIO_FN(SDHICMD1), GPIO_FN(TRST3),
-	GPIO_FN(SDHICLK2), GPIO_FN(SCIFB_SCK),
-	GPIO_FN(SDHID2_0), GPIO_FN(SCIFB_TXD),
-	GPIO_FN(SDHID2_1), GPIO_FN(SCIFB_CTS),
-	GPIO_FN(SDHID2_2), GPIO_FN(SCIFB_RXD),
-	GPIO_FN(SDHID2_3), GPIO_FN(SCIFB_RTS),
-	GPIO_FN(SDHICMD2),
-	GPIO_FN(RESETOUTS),
-	GPIO_FN(DIVLOCK),
-};
-
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
-	PORTCR(0, 0xe6050000), /* PORT0CR */
-	PORTCR(1, 0xe6050001), /* PORT1CR */
-	PORTCR(2, 0xe6050002), /* PORT2CR */
-	PORTCR(3, 0xe6050003), /* PORT3CR */
-	PORTCR(4, 0xe6050004), /* PORT4CR */
-	PORTCR(5, 0xe6050005), /* PORT5CR */
-	PORTCR(6, 0xe6050006), /* PORT6CR */
-	PORTCR(7, 0xe6050007), /* PORT7CR */
-	PORTCR(8, 0xe6050008), /* PORT8CR */
-	PORTCR(9, 0xe6050009), /* PORT9CR */
-
-	PORTCR(10, 0xe605000a), /* PORT10CR */
-	PORTCR(11, 0xe605000b), /* PORT11CR */
-	PORTCR(12, 0xe605000c), /* PORT12CR */
-	PORTCR(13, 0xe605000d), /* PORT13CR */
-	PORTCR(14, 0xe605000e), /* PORT14CR */
-	PORTCR(15, 0xe605000f), /* PORT15CR */
-	PORTCR(16, 0xe6050010), /* PORT16CR */
-	PORTCR(17, 0xe6050011), /* PORT17CR */
-	PORTCR(18, 0xe6050012), /* PORT18CR */
-	PORTCR(19, 0xe6050013), /* PORT19CR */
-
-	PORTCR(20, 0xe6050014), /* PORT20CR */
-	PORTCR(21, 0xe6050015), /* PORT21CR */
-	PORTCR(22, 0xe6050016), /* PORT22CR */
-	PORTCR(23, 0xe6050017), /* PORT23CR */
-	PORTCR(24, 0xe6050018), /* PORT24CR */
-	PORTCR(25, 0xe6050019), /* PORT25CR */
-	PORTCR(26, 0xe605001a), /* PORT26CR */
-	PORTCR(27, 0xe605001b), /* PORT27CR */
-	PORTCR(28, 0xe605001c), /* PORT28CR */
-	PORTCR(29, 0xe605001d), /* PORT29CR */
-
-	PORTCR(30, 0xe605001e), /* PORT30CR */
-	PORTCR(31, 0xe605001f), /* PORT31CR */
-	PORTCR(32, 0xe6050020), /* PORT32CR */
-	PORTCR(33, 0xe6050021), /* PORT33CR */
-	PORTCR(34, 0xe6050022), /* PORT34CR */
-	PORTCR(35, 0xe6050023), /* PORT35CR */
-	PORTCR(36, 0xe6050024), /* PORT36CR */
-	PORTCR(37, 0xe6050025), /* PORT37CR */
-	PORTCR(38, 0xe6050026), /* PORT38CR */
-	PORTCR(39, 0xe6050027), /* PORT39CR */
-
-	PORTCR(40, 0xe6050028), /* PORT40CR */
-	PORTCR(41, 0xe6050029), /* PORT41CR */
-	PORTCR(42, 0xe605002a), /* PORT42CR */
-	PORTCR(43, 0xe605002b), /* PORT43CR */
-	PORTCR(44, 0xe605002c), /* PORT44CR */
-	PORTCR(45, 0xe605002d), /* PORT45CR */
-	PORTCR(46, 0xe605002e), /* PORT46CR */
-	PORTCR(47, 0xe605002f), /* PORT47CR */
-	PORTCR(48, 0xe6050030), /* PORT48CR */
-	PORTCR(49, 0xe6050031), /* PORT49CR */
-
-	PORTCR(50, 0xe6050032), /* PORT50CR */
-	PORTCR(51, 0xe6050033), /* PORT51CR */
-	PORTCR(52, 0xe6050034), /* PORT52CR */
-	PORTCR(53, 0xe6050035), /* PORT53CR */
-	PORTCR(54, 0xe6050036), /* PORT54CR */
-	PORTCR(55, 0xe6050037), /* PORT55CR */
-	PORTCR(56, 0xe6050038), /* PORT56CR */
-	PORTCR(57, 0xe6050039), /* PORT57CR */
-	PORTCR(58, 0xe605003a), /* PORT58CR */
-	PORTCR(59, 0xe605003b), /* PORT59CR */
-
-	PORTCR(60, 0xe605003c), /* PORT60CR */
-	PORTCR(61, 0xe605003d), /* PORT61CR */
-	PORTCR(62, 0xe605003e), /* PORT62CR */
-	PORTCR(63, 0xe605003f), /* PORT63CR */
-	PORTCR(64, 0xe6050040), /* PORT64CR */
-	PORTCR(65, 0xe6050041), /* PORT65CR */
-	PORTCR(66, 0xe6050042), /* PORT66CR */
-	PORTCR(67, 0xe6050043), /* PORT67CR */
-	PORTCR(68, 0xe6050044), /* PORT68CR */
-	PORTCR(69, 0xe6050045), /* PORT69CR */
-
-	PORTCR(70, 0xe6050046), /* PORT70CR */
-	PORTCR(71, 0xe6050047), /* PORT71CR */
-	PORTCR(72, 0xe6050048), /* PORT72CR */
-	PORTCR(73, 0xe6050049), /* PORT73CR */
-	PORTCR(74, 0xe605004a), /* PORT74CR */
-	PORTCR(75, 0xe605004b), /* PORT75CR */
-	PORTCR(76, 0xe605004c), /* PORT76CR */
-	PORTCR(77, 0xe605004d), /* PORT77CR */
-	PORTCR(78, 0xe605004e), /* PORT78CR */
-	PORTCR(79, 0xe605004f), /* PORT79CR */
-
-	PORTCR(80, 0xe6050050), /* PORT80CR */
-	PORTCR(81, 0xe6050051), /* PORT81CR */
-	PORTCR(82, 0xe6050052), /* PORT82CR */
-	PORTCR(83, 0xe6050053), /* PORT83CR */
-	PORTCR(84, 0xe6050054), /* PORT84CR */
-	PORTCR(85, 0xe6050055), /* PORT85CR */
-	PORTCR(86, 0xe6050056), /* PORT86CR */
-	PORTCR(87, 0xe6050057), /* PORT87CR */
-	PORTCR(88, 0xe6051058), /* PORT88CR */
-	PORTCR(89, 0xe6051059), /* PORT89CR */
-
-	PORTCR(90, 0xe605105a), /* PORT90CR */
-	PORTCR(91, 0xe605105b), /* PORT91CR */
-	PORTCR(92, 0xe605105c), /* PORT92CR */
-	PORTCR(93, 0xe605105d), /* PORT93CR */
-	PORTCR(94, 0xe605105e), /* PORT94CR */
-	PORTCR(95, 0xe605105f), /* PORT95CR */
-	PORTCR(96, 0xe6051060), /* PORT96CR */
-	PORTCR(97, 0xe6051061), /* PORT97CR */
-	PORTCR(98, 0xe6051062), /* PORT98CR */
-	PORTCR(99, 0xe6051063), /* PORT99CR */
-
-	PORTCR(100, 0xe6051064), /* PORT100CR */
-	PORTCR(101, 0xe6051065), /* PORT101CR */
-	PORTCR(102, 0xe6051066), /* PORT102CR */
-	PORTCR(103, 0xe6051067), /* PORT103CR */
-	PORTCR(104, 0xe6051068), /* PORT104CR */
-	PORTCR(105, 0xe6051069), /* PORT105CR */
-	PORTCR(106, 0xe605106a), /* PORT106CR */
-	PORTCR(107, 0xe605106b), /* PORT107CR */
-	PORTCR(108, 0xe605106c), /* PORT108CR */
-	PORTCR(109, 0xe605106d), /* PORT109CR */
-
-	PORTCR(110, 0xe605106e), /* PORT110CR */
-	PORTCR(111, 0xe605106f), /* PORT111CR */
-	PORTCR(112, 0xe6051070), /* PORT112CR */
-	PORTCR(113, 0xe6051071), /* PORT113CR */
-	PORTCR(114, 0xe6051072), /* PORT114CR */
-	PORTCR(115, 0xe6051073), /* PORT115CR */
-	PORTCR(116, 0xe6051074), /* PORT116CR */
-	PORTCR(117, 0xe6051075), /* PORT117CR */
-	PORTCR(118, 0xe6051076), /* PORT118CR */
-	PORTCR(119, 0xe6051077), /* PORT119CR */
-
-	PORTCR(120, 0xe6051078), /* PORT120CR */
-	PORTCR(121, 0xe6051079), /* PORT121CR */
-	PORTCR(122, 0xe605107a), /* PORT122CR */
-	PORTCR(123, 0xe605107b), /* PORT123CR */
-	PORTCR(124, 0xe605107c), /* PORT124CR */
-	PORTCR(125, 0xe605107d), /* PORT125CR */
-	PORTCR(126, 0xe605107e), /* PORT126CR */
-	PORTCR(127, 0xe605107f), /* PORT127CR */
-	PORTCR(128, 0xe6051080), /* PORT128CR */
-	PORTCR(129, 0xe6051081), /* PORT129CR */
-
-	PORTCR(130, 0xe6051082), /* PORT130CR */
-	PORTCR(131, 0xe6051083), /* PORT131CR */
-	PORTCR(132, 0xe6051084), /* PORT132CR */
-	PORTCR(133, 0xe6051085), /* PORT133CR */
-	PORTCR(134, 0xe6051086), /* PORT134CR */
-	PORTCR(135, 0xe6051087), /* PORT135CR */
-	PORTCR(136, 0xe6051088), /* PORT136CR */
-	PORTCR(137, 0xe6051089), /* PORT137CR */
-	PORTCR(138, 0xe605108a), /* PORT138CR */
-	PORTCR(139, 0xe605108b), /* PORT139CR */
-
-	PORTCR(140, 0xe605108c), /* PORT140CR */
-	PORTCR(141, 0xe605108d), /* PORT141CR */
-	PORTCR(142, 0xe605108e), /* PORT142CR */
-	PORTCR(143, 0xe605108f), /* PORT143CR */
-	PORTCR(144, 0xe6051090), /* PORT144CR */
-	PORTCR(145, 0xe6051091), /* PORT145CR */
-	PORTCR(146, 0xe6051092), /* PORT146CR */
-	PORTCR(147, 0xe6051093), /* PORT147CR */
-	PORTCR(148, 0xe6051094), /* PORT148CR */
-	PORTCR(149, 0xe6051095), /* PORT149CR */
-
-	PORTCR(150, 0xe6051096), /* PORT150CR */
-	PORTCR(151, 0xe6051097), /* PORT151CR */
-	PORTCR(152, 0xe6051098), /* PORT152CR */
-	PORTCR(153, 0xe6051099), /* PORT153CR */
-	PORTCR(154, 0xe605109a), /* PORT154CR */
-	PORTCR(155, 0xe605109b), /* PORT155CR */
-	PORTCR(156, 0xe605109c), /* PORT156CR */
-	PORTCR(157, 0xe605109d), /* PORT157CR */
-	PORTCR(158, 0xe605109e), /* PORT158CR */
-	PORTCR(159, 0xe605109f), /* PORT159CR */
-
-	PORTCR(160, 0xe60510a0), /* PORT160CR */
-	PORTCR(161, 0xe60510a1), /* PORT161CR */
-	PORTCR(162, 0xe60510a2), /* PORT162CR */
-	PORTCR(163, 0xe60510a3), /* PORT163CR */
-	PORTCR(164, 0xe60510a4), /* PORT164CR */
-	PORTCR(165, 0xe60510a5), /* PORT165CR */
-	PORTCR(166, 0xe60510a6), /* PORT166CR */
-	PORTCR(167, 0xe60510a7), /* PORT167CR */
-	PORTCR(168, 0xe60510a8), /* PORT168CR */
-	PORTCR(169, 0xe60510a9), /* PORT169CR */
-
-	PORTCR(170, 0xe60510aa), /* PORT170CR */
-	PORTCR(171, 0xe60510ab), /* PORT171CR */
-	PORTCR(172, 0xe60510ac), /* PORT172CR */
-	PORTCR(173, 0xe60510ad), /* PORT173CR */
-	PORTCR(174, 0xe60510ae), /* PORT174CR */
-	PORTCR(175, 0xe60520af), /* PORT175CR */
-	PORTCR(176, 0xe60520b0), /* PORT176CR */
-	PORTCR(177, 0xe60520b1), /* PORT177CR */
-	PORTCR(178, 0xe60520b2), /* PORT178CR */
-	PORTCR(179, 0xe60520b3), /* PORT179CR */
-
-	PORTCR(180, 0xe60520b4), /* PORT180CR */
-	PORTCR(181, 0xe60520b5), /* PORT181CR */
-	PORTCR(182, 0xe60520b6), /* PORT182CR */
-	PORTCR(183, 0xe60520b7), /* PORT183CR */
-	PORTCR(184, 0xe60520b8), /* PORT184CR */
-	PORTCR(185, 0xe60520b9), /* PORT185CR */
-	PORTCR(186, 0xe60520ba), /* PORT186CR */
-	PORTCR(187, 0xe60520bb), /* PORT187CR */
-	PORTCR(188, 0xe60520bc), /* PORT188CR */
-	PORTCR(189, 0xe60520bd), /* PORT189CR */
-
-	PORTCR(190, 0xe60520be), /* PORT190CR */
-	PORTCR(191, 0xe60520bf), /* PORT191CR */
-	PORTCR(192, 0xe60520c0), /* PORT192CR */
-	PORTCR(193, 0xe60520c1), /* PORT193CR */
-	PORTCR(194, 0xe60520c2), /* PORT194CR */
-	PORTCR(195, 0xe60520c3), /* PORT195CR */
-	PORTCR(196, 0xe60520c4), /* PORT196CR */
-	PORTCR(197, 0xe60520c5), /* PORT197CR */
-	PORTCR(198, 0xe60520c6), /* PORT198CR */
-	PORTCR(199, 0xe60520c7), /* PORT199CR */
-
-	PORTCR(200, 0xe60520c8), /* PORT200CR */
-	PORTCR(201, 0xe60520c9), /* PORT201CR */
-	PORTCR(202, 0xe60520ca), /* PORT202CR */
-	PORTCR(203, 0xe60520cb), /* PORT203CR */
-	PORTCR(204, 0xe60520cc), /* PORT204CR */
-	PORTCR(205, 0xe60520cd), /* PORT205CR */
-	PORTCR(206, 0xe60520ce), /* PORT206CR */
-	PORTCR(207, 0xe60520cf), /* PORT207CR */
-	PORTCR(208, 0xe60520d0), /* PORT208CR */
-	PORTCR(209, 0xe60520d1), /* PORT209CR */
-
-	PORTCR(210, 0xe60520d2), /* PORT210CR */
-	PORTCR(211, 0xe60520d3), /* PORT211CR */
-	PORTCR(212, 0xe60520d4), /* PORT212CR */
-	PORTCR(213, 0xe60520d5), /* PORT213CR */
-	PORTCR(214, 0xe60520d6), /* PORT214CR */
-	PORTCR(215, 0xe60520d7), /* PORT215CR */
-	PORTCR(216, 0xe60520d8), /* PORT216CR */
-	PORTCR(217, 0xe60520d9), /* PORT217CR */
-	PORTCR(218, 0xe60520da), /* PORT218CR */
-	PORTCR(219, 0xe60520db), /* PORT219CR */
-
-	PORTCR(220, 0xe60520dc), /* PORT220CR */
-	PORTCR(221, 0xe60520dd), /* PORT221CR */
-	PORTCR(222, 0xe60520de), /* PORT222CR */
-	PORTCR(223, 0xe60520df), /* PORT223CR */
-	PORTCR(224, 0xe60520e0), /* PORT224CR */
-	PORTCR(225, 0xe60520e1), /* PORT225CR */
-	PORTCR(226, 0xe60520e2), /* PORT226CR */
-	PORTCR(227, 0xe60520e3), /* PORT227CR */
-	PORTCR(228, 0xe60520e4), /* PORT228CR */
-	PORTCR(229, 0xe60520e5), /* PORT229CR */
-
-	PORTCR(230, 0xe60520e6), /* PORT230CR */
-	PORTCR(231, 0xe60520e7), /* PORT231CR */
-	PORTCR(232, 0xe60520e8), /* PORT232CR */
-	PORTCR(233, 0xe60520e9), /* PORT233CR */
-	PORTCR(234, 0xe60520ea), /* PORT234CR */
-	PORTCR(235, 0xe60520eb), /* PORT235CR */
-	PORTCR(236, 0xe60530ec), /* PORT236CR */
-	PORTCR(237, 0xe60530ed), /* PORT237CR */
-	PORTCR(238, 0xe60530ee), /* PORT238CR */
-	PORTCR(239, 0xe60530ef), /* PORT239CR */
-
-	PORTCR(240, 0xe60530f0), /* PORT240CR */
-	PORTCR(241, 0xe60530f1), /* PORT241CR */
-	PORTCR(242, 0xe60530f2), /* PORT242CR */
-	PORTCR(243, 0xe60530f3), /* PORT243CR */
-	PORTCR(244, 0xe60530f4), /* PORT244CR */
-	PORTCR(245, 0xe60530f5), /* PORT245CR */
-	PORTCR(246, 0xe60530f6), /* PORT246CR */
-	PORTCR(247, 0xe60530f7), /* PORT247CR */
-	PORTCR(248, 0xe60530f8), /* PORT248CR */
-	PORTCR(249, 0xe60530f9), /* PORT249CR */
-
-	PORTCR(250, 0xe60530fa), /* PORT250CR */
-	PORTCR(251, 0xe60530fb), /* PORT251CR */
-	PORTCR(252, 0xe60530fc), /* PORT252CR */
-	PORTCR(253, 0xe60530fd), /* PORT253CR */
-	PORTCR(254, 0xe60530fe), /* PORT254CR */
-	PORTCR(255, 0xe60530ff), /* PORT255CR */
-	PORTCR(256, 0xe6053100), /* PORT256CR */
-	PORTCR(257, 0xe6053101), /* PORT257CR */
-	PORTCR(258, 0xe6053102), /* PORT258CR */
-	PORTCR(259, 0xe6053103), /* PORT259CR */
-
-	PORTCR(260, 0xe6053104), /* PORT260CR */
-	PORTCR(261, 0xe6053105), /* PORT261CR */
-	PORTCR(262, 0xe6053106), /* PORT262CR */
-	PORTCR(263, 0xe6053107), /* PORT263CR */
-	PORTCR(264, 0xe6053108), /* PORT264CR */
-	PORTCR(265, 0xe6053109), /* PORT265CR */
-	PORTCR(266, 0xe605310a), /* PORT266CR */
-	PORTCR(267, 0xe605310b), /* PORT267CR */
-	PORTCR(268, 0xe605310c), /* PORT268CR */
-	PORTCR(269, 0xe605310d), /* PORT269CR */
-
-	PORTCR(270, 0xe605310e), /* PORT270CR */
-	PORTCR(271, 0xe605310f), /* PORT271CR */
-	PORTCR(272, 0xe6053110), /* PORT272CR */
-
-	{ PINMUX_CFG_REG("MSELBCR", 0xe6058024, 32, 1) {
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-		0, 0,
-		0, 0,
-		0, 0,
-		0, 0,
-		0, 0,
-		MSELBCR_MSEL2_0, MSELBCR_MSEL2_1,
-		0, 0,
-		0, 0 }
-	},
-	{ },
-};
-
-static struct pinmux_data_reg pinmux_data_regs[] = {
-	{ PINMUX_DATA_REG("PORTL031_000DR", 0xe6054000, 32) {
-		PORT31_DATA, PORT30_DATA, PORT29_DATA, PORT28_DATA,
-		PORT27_DATA, PORT26_DATA, PORT25_DATA, PORT24_DATA,
-		PORT23_DATA, PORT22_DATA, PORT21_DATA, PORT20_DATA,
-		PORT19_DATA, PORT18_DATA, PORT17_DATA, PORT16_DATA,
-		PORT15_DATA, PORT14_DATA, PORT13_DATA, PORT12_DATA,
-		PORT11_DATA, PORT10_DATA, PORT9_DATA, PORT8_DATA,
-		PORT7_DATA, PORT6_DATA, PORT5_DATA, PORT4_DATA,
-		PORT3_DATA, PORT2_DATA, PORT1_DATA, PORT0_DATA }
-	},
-	{ PINMUX_DATA_REG("PORTL063_032DR", 0xe6054004, 32) {
-		PORT63_DATA, PORT62_DATA, PORT61_DATA, PORT60_DATA,
-		PORT59_DATA, PORT58_DATA, PORT57_DATA, PORT56_DATA,
-		PORT55_DATA, PORT54_DATA, PORT53_DATA, PORT52_DATA,
-		PORT51_DATA, PORT50_DATA, PORT49_DATA, PORT48_DATA,
-		PORT47_DATA, PORT46_DATA, PORT45_DATA, PORT44_DATA,
-		PORT43_DATA, PORT42_DATA, PORT41_DATA, PORT40_DATA,
-		PORT39_DATA, PORT38_DATA, PORT37_DATA, PORT36_DATA,
-		PORT35_DATA, PORT34_DATA, PORT33_DATA, PORT32_DATA }
-	},
-	{ PINMUX_DATA_REG("PORTL095_064DR", 0xe6054008, 32) {
-		PORT95_DATA, PORT94_DATA, PORT93_DATA, PORT92_DATA,
-		PORT91_DATA, PORT90_DATA, PORT89_DATA, PORT88_DATA,
-		PORT87_DATA, PORT86_DATA, PORT85_DATA, PORT84_DATA,
-		PORT83_DATA, PORT82_DATA, PORT81_DATA, PORT80_DATA,
-		PORT79_DATA, PORT78_DATA, PORT77_DATA, PORT76_DATA,
-		PORT75_DATA, PORT74_DATA, PORT73_DATA, PORT72_DATA,
-		PORT71_DATA, PORT70_DATA, PORT69_DATA, PORT68_DATA,
-		PORT67_DATA, PORT66_DATA, PORT65_DATA, PORT64_DATA }
-	},
-	{ PINMUX_DATA_REG("PORTD127_096DR", 0xe6055004, 32) {
-		PORT127_DATA, PORT126_DATA, PORT125_DATA, PORT124_DATA,
-		PORT123_DATA, PORT122_DATA, PORT121_DATA, PORT120_DATA,
-		PORT119_DATA, PORT118_DATA, PORT117_DATA, PORT116_DATA,
-		PORT115_DATA, PORT114_DATA, PORT113_DATA, PORT112_DATA,
-		PORT111_DATA, PORT110_DATA, PORT109_DATA, PORT108_DATA,
-		PORT107_DATA, PORT106_DATA, PORT105_DATA, PORT104_DATA,
-		PORT103_DATA, PORT102_DATA, PORT101_DATA, PORT100_DATA,
-		PORT99_DATA, PORT98_DATA, PORT97_DATA, PORT96_DATA }
-	},
-	{ PINMUX_DATA_REG("PORTD159_128DR", 0xe6055008, 32) {
-		PORT159_DATA, PORT158_DATA, PORT157_DATA, PORT156_DATA,
-		PORT155_DATA, PORT154_DATA, PORT153_DATA, PORT152_DATA,
-		PORT151_DATA, PORT150_DATA, PORT149_DATA, PORT148_DATA,
-		PORT147_DATA, PORT146_DATA, PORT145_DATA, PORT144_DATA,
-		PORT143_DATA, PORT142_DATA, PORT141_DATA, PORT140_DATA,
-		PORT139_DATA, PORT138_DATA, PORT137_DATA, PORT136_DATA,
-		PORT135_DATA, PORT134_DATA, PORT133_DATA, PORT132_DATA,
-		PORT131_DATA, PORT130_DATA, PORT129_DATA, PORT128_DATA }
-	},
-	{ PINMUX_DATA_REG("PORTR191_160DR", 0xe6056000, 32) {
-		PORT191_DATA, PORT190_DATA, PORT189_DATA, PORT188_DATA,
-		PORT187_DATA, PORT186_DATA, PORT185_DATA, PORT184_DATA,
-		PORT183_DATA, PORT182_DATA, PORT181_DATA, PORT180_DATA,
-		PORT179_DATA, PORT178_DATA, PORT177_DATA, PORT176_DATA,
-		PORT175_DATA, PORT174_DATA, PORT173_DATA, PORT172_DATA,
-		PORT171_DATA, PORT170_DATA, PORT169_DATA, PORT168_DATA,
-		PORT167_DATA, PORT166_DATA, PORT165_DATA, PORT164_DATA,
-		PORT163_DATA, PORT162_DATA, PORT161_DATA, PORT160_DATA }
-	},
-	{ PINMUX_DATA_REG("PORTR223_192DR", 0xe6056004, 32) {
-		PORT223_DATA, PORT222_DATA, PORT221_DATA, PORT220_DATA,
-		PORT219_DATA, PORT218_DATA, PORT217_DATA, PORT216_DATA,
-		PORT215_DATA, PORT214_DATA, PORT213_DATA, PORT212_DATA,
-		PORT211_DATA, PORT210_DATA, PORT209_DATA, PORT208_DATA,
-		PORT207_DATA, PORT206_DATA, PORT205_DATA, PORT204_DATA,
-		PORT203_DATA, PORT202_DATA, PORT201_DATA, PORT200_DATA,
-		PORT199_DATA, PORT198_DATA, PORT197_DATA, PORT196_DATA,
-		PORT195_DATA, PORT194_DATA, PORT193_DATA, PORT192_DATA }
-	},
-	{ PINMUX_DATA_REG("PORTU255_224DR", 0xe6057000, 32) {
-		PORT255_DATA, PORT254_DATA, PORT253_DATA, PORT252_DATA,
-		PORT251_DATA, PORT250_DATA, PORT249_DATA, PORT248_DATA,
-		PORT247_DATA, PORT246_DATA, PORT245_DATA, PORT244_DATA,
-		PORT243_DATA, PORT242_DATA, PORT241_DATA, PORT240_DATA,
-		PORT239_DATA, PORT238_DATA, PORT237_DATA, PORT236_DATA,
-		PORT235_DATA, PORT234_DATA, PORT233_DATA, PORT232_DATA,
-		PORT231_DATA, PORT230_DATA, PORT229_DATA, PORT228_DATA,
-		PORT227_DATA, PORT226_DATA, PORT225_DATA, PORT224_DATA }
-	},
-	{ PINMUX_DATA_REG("PORTU287_256DR", 0xe6057004, 32) {
-		0, 0, 0, 0,
-		0, 0, 0, 0,
-		0, 0, 0, 0,
-		0, 0, 0, PORT272_DATA,
-		PORT271_DATA, PORT270_DATA, PORT269_DATA, PORT268_DATA,
-		PORT267_DATA, PORT266_DATA, PORT265_DATA, PORT264_DATA,
-		PORT263_DATA, PORT262_DATA, PORT261_DATA, PORT260_DATA,
-		PORT259_DATA, PORT258_DATA, PORT257_DATA, PORT256_DATA }
-	},
-	{ },
-};
-
-static struct pinmux_info sh7367_pinmux_info = {
-	.name = "sh7367_pfc",
-	.reserved_id = PINMUX_RESERVED,
-	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
-	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
-	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
-	.input_pd = { PINMUX_INPUT_PULLDOWN_BEGIN, PINMUX_INPUT_PULLDOWN_END },
-	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
-	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
-	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
-
-	.first_gpio = GPIO_PORT0,
-	.last_gpio = GPIO_FN_DIVLOCK,
-
-	.gpios = pinmux_gpios,
-	.cfg_regs = pinmux_config_regs,
-	.data_regs = pinmux_data_regs,
-
-	.gpio_data = pinmux_data,
-	.gpio_data_size = ARRAY_SIZE(pinmux_data),
-};
-
-void sh7367_pinmux_init(void)
-{
-	register_pinmux(&sh7367_pinmux_info);
-}
diff --git a/arch/arm/mach-shmobile/pfc-sh7377.c b/arch/arm/mach-shmobile/pfc-sh7377.c
deleted file mode 100644
index f3117f6..0000000
--- a/arch/arm/mach-shmobile/pfc-sh7377.c
+++ /dev/null
@@ -1,1688 +0,0 @@
-/*
- * sh7377 processor support - PFC hardware block
- *
- * Copyright (C) 2010  NISHIMOTO Hiroki
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; version 2 of the
- * License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sh_pfc.h>
-#include <mach/sh7377.h>
-
-#define CPU_ALL_PORT(fn, pfx, sfx)				\
-	PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx),		\
-	PORT_10(fn, pfx##10, sfx),				\
-	PORT_1(fn, pfx##110, sfx), PORT_1(fn, pfx##111, sfx),	\
-	PORT_1(fn, pfx##112, sfx), PORT_1(fn, pfx##113, sfx),	\
-	PORT_1(fn, pfx##114, sfx), PORT_1(fn, pfx##115, sfx),	\
-	PORT_1(fn, pfx##116, sfx), PORT_1(fn, pfx##117, sfx),	\
-	PORT_1(fn, pfx##118, sfx),				\
-	PORT_1(fn, pfx##128, sfx), PORT_1(fn, pfx##129, sfx),	\
-	PORT_10(fn, pfx##13, sfx), PORT_10(fn, pfx##14, sfx),	\
-	PORT_10(fn, pfx##15, sfx),				\
-	PORT_1(fn, pfx##160, sfx), PORT_1(fn, pfx##161, sfx),	\
-	PORT_1(fn, pfx##162, sfx), PORT_1(fn, pfx##163, sfx),	\
-	PORT_1(fn, pfx##164, sfx),				\
-	PORT_1(fn, pfx##192, sfx), PORT_1(fn, pfx##193, sfx),	\
-	PORT_1(fn, pfx##194, sfx), PORT_1(fn, pfx##195, sfx),	\
-	PORT_1(fn, pfx##196, sfx), PORT_1(fn, pfx##197, sfx),	\
-	PORT_1(fn, pfx##198, sfx), PORT_1(fn, pfx##199, sfx),	\
-	PORT_10(fn, pfx##20, sfx), PORT_10(fn, pfx##21, sfx),	\
-	PORT_10(fn, pfx##22, sfx), PORT_10(fn, pfx##23, sfx),	\
-	PORT_10(fn, pfx##24, sfx), PORT_10(fn, pfx##25, sfx),	\
-	PORT_1(fn, pfx##260, sfx), PORT_1(fn, pfx##261, sfx),	\
-	PORT_1(fn, pfx##262, sfx), PORT_1(fn, pfx##263, sfx),	\
-	PORT_1(fn, pfx##264, sfx)
-
-enum {
-	PINMUX_RESERVED = 0,
-
-	PINMUX_DATA_BEGIN,
-	PORT_ALL(DATA), /* PORT0_DATA -> PORT264_DATA */
-	PINMUX_DATA_END,
-
-	PINMUX_INPUT_BEGIN,
-	PORT_ALL(IN), /* PORT0_IN -> PORT264_IN */
-	PINMUX_INPUT_END,
-
-	PINMUX_INPUT_PULLUP_BEGIN,
-	PORT_ALL(IN_PU), /* PORT0_IN_PU -> PORT264_IN_PU */
-	PINMUX_INPUT_PULLUP_END,
-
-	PINMUX_INPUT_PULLDOWN_BEGIN,
-	PORT_ALL(IN_PD), /* PORT0_IN_PD -> PORT264_IN_PD */
-	PINMUX_INPUT_PULLDOWN_END,
-
-	PINMUX_OUTPUT_BEGIN,
-	PORT_ALL(OUT), /* PORT0_OUT -> PORT264_OUT */
-	PINMUX_OUTPUT_END,
-
-	PINMUX_FUNCTION_BEGIN,
-	PORT_ALL(FN_IN), /* PORT0_FN_IN -> PORT264_FN_IN */
-	PORT_ALL(FN_OUT), /* PORT0_FN_OUT -> PORT264_FN_OUT */
-	PORT_ALL(FN0), /* PORT0_FN0 -> PORT264_FN0 */
-	PORT_ALL(FN1), /* PORT0_FN1 -> PORT264_FN1 */
-	PORT_ALL(FN2), /* PORT0_FN2 -> PORT264_FN2 */
-	PORT_ALL(FN3), /* PORT0_FN3 -> PORT264_FN3 */
-	PORT_ALL(FN4), /* PORT0_FN4 -> PORT264_FN4 */
-	PORT_ALL(FN5), /* PORT0_FN5 -> PORT264_FN5 */
-	PORT_ALL(FN6), /* PORT0_FN6 -> PORT264_FN6 */
-	PORT_ALL(FN7), /* PORT0_FN7 -> PORT264_FN7 */
-
-	MSELBCR_MSEL17_1, MSELBCR_MSEL17_0,
-	MSELBCR_MSEL16_1, MSELBCR_MSEL16_0,
-	PINMUX_FUNCTION_END,
-
-	PINMUX_MARK_BEGIN,
-	/* Special Pull-up / Pull-down Functions */
-	PORT66_KEYIN0_PU_MARK, PORT67_KEYIN1_PU_MARK,
-	PORT68_KEYIN2_PU_MARK, PORT69_KEYIN3_PU_MARK,
-	PORT70_KEYIN4_PU_MARK, PORT71_KEYIN5_PU_MARK,
-	PORT72_KEYIN6_PU_MARK,
-
-	/* 55-1 */
-	VBUS_0_MARK,
-	CPORT0_MARK,
-	CPORT1_MARK,
-	CPORT2_MARK,
-	CPORT3_MARK,
-	CPORT4_MARK,
-	CPORT5_MARK,
-	CPORT6_MARK,
-	CPORT7_MARK,
-	CPORT8_MARK,
-	CPORT9_MARK,
-	CPORT10_MARK,
-	CPORT11_MARK, SIN2_MARK,
-	CPORT12_MARK, XCTS2_MARK,
-	CPORT13_MARK, RFSPO4_MARK,
-	CPORT14_MARK, RFSPO5_MARK,
-	CPORT15_MARK, SCIFA0_SCK_MARK, GPS_AGC2_MARK,
-	CPORT16_MARK, SCIFA0_TXD_MARK, GPS_AGC3_MARK,
-	CPORT17_IC_OE_MARK, SOUT2_MARK,
-	CPORT18_MARK, XRTS2_MARK, PORT19_VIO_CKO2_MARK,
-	CPORT19_MPORT1_MARK,
-	CPORT20_MARK, RFSPO6_MARK,
-	CPORT21_MARK, STATUS0_MARK,
-	CPORT22_MARK, STATUS1_MARK,
-	CPORT23_MARK, STATUS2_MARK, RFSPO7_MARK,
-	B_SYNLD1_MARK,
-	B_SYNLD2_MARK, SYSENMSK_MARK,
-	XMAINPS_MARK,
-	XDIVPS_MARK,
-	XIDRST_MARK,
-	IDCLK_MARK, IC_DP_MARK,
-	IDIO_MARK, IC_DM_MARK,
-	SOUT1_MARK, SCIFA4_TXD_MARK, M02_BERDAT_MARK,
-	SIN1_MARK, SCIFA4_RXD_MARK, XWUP_MARK,
-	XRTS1_MARK, SCIFA4_RTS_MARK, M03_BERCLK_MARK,
-	XCTS1_MARK, SCIFA4_CTS_MARK,
-	PCMCLKO_MARK,
-	SYNC8KO_MARK,
-
-	/* 55-2 */
-	DNPCM_A_MARK,
-	UPPCM_A_MARK,
-	VACK_MARK,
-	XTALB1L_MARK,
-	GPS_AGC1_MARK, SCIFA0_RTS_MARK,
-	GPS_AGC4_MARK, SCIFA0_RXD_MARK,
-	GPS_PWRDOWN_MARK, SCIFA0_CTS_MARK,
-	GPS_IM_MARK,
-	GPS_IS_MARK,
-	GPS_QM_MARK,
-	GPS_QS_MARK,
-	FMSOCK_MARK, PORT49_IRDA_OUT_MARK, PORT49_IROUT_MARK,
-	FMSOOLR_MARK, BBIF2_TSYNC2_MARK, TPU2TO2_MARK, IPORT3_MARK,
-	FMSIOLR_MARK,
-	FMSOOBT_MARK, BBIF2_TSCK2_MARK, TPU2TO3_MARK, OPORT1_MARK,
-	FMSIOBT_MARK,
-	FMSOSLD_MARK, BBIF2_TXD2_MARK, OPORT2_MARK,
-	FMSOILR_MARK, PORT53_IRDA_IN_MARK, TPU3TO3_MARK, OPORT3_MARK,
-	FMSIILR_MARK,
-	FMSOIBT_MARK, PORT54_IRDA_FIRSEL_MARK, TPU3TO2_MARK, FMSIIBT_MARK,
-	FMSISLD_MARK, MFG0_OUT1_MARK, TPU0TO0_MARK,
-	A0_EA0_MARK, BS_MARK,
-	A12_EA12_MARK, PORT58_VIO_CKOR_MARK, TPU4TO2_MARK,
-	A13_EA13_MARK, PORT59_IROUT_MARK, MFG0_OUT2_MARK, TPU0TO1_MARK,
-	A14_EA14_MARK, PORT60_KEYOUT5_MARK,
-	A15_EA15_MARK, PORT61_KEYOUT4_MARK,
-	A16_EA16_MARK, PORT62_KEYOUT3_MARK, MSIOF0_SS1_MARK,
-	A17_EA17_MARK, PORT63_KEYOUT2_MARK, MSIOF0_TSYNC_MARK,
-	A18_EA18_MARK, PORT64_KEYOUT1_MARK, MSIOF0_TSCK_MARK,
-	A19_EA19_MARK, PORT65_KEYOUT0_MARK, MSIOF0_TXD_MARK,
-	A20_EA20_MARK, PORT66_KEYIN0_MARK, MSIOF0_RSCK_MARK,
-	A21_EA21_MARK, PORT67_KEYIN1_MARK, MSIOF0_RSYNC_MARK,
-	A22_EA22_MARK, PORT68_KEYIN2_MARK, MSIOF0_MCK0_MARK,
-	A23_EA23_MARK, PORT69_KEYIN3_MARK, MSIOF0_MCK1_MARK,
-	A24_EA24_MARK, PORT70_KEYIN4_MARK, MSIOF0_RXD_MARK,
-	A25_EA25_MARK, PORT71_KEYIN5_MARK, MSIOF0_SS2_MARK,
-	A26_MARK, PORT72_KEYIN6_MARK,
-	D0_ED0_NAF0_MARK,
-	D1_ED1_NAF1_MARK,
-	D2_ED2_NAF2_MARK,
-	D3_ED3_NAF3_MARK,
-	D4_ED4_NAF4_MARK,
-	D5_ED5_NAF5_MARK,
-	D6_ED6_NAF6_MARK,
-	D7_ED7_NAF7_MARK,
-	D8_ED8_NAF8_MARK,
-	D9_ED9_NAF9_MARK,
-	D10_ED10_NAF10_MARK,
-	D11_ED11_NAF11_MARK,
-	D12_ED12_NAF12_MARK,
-	D13_ED13_NAF13_MARK,
-	D14_ED14_NAF14_MARK,
-	D15_ED15_NAF15_MARK,
-	CS4_MARK,
-	CS5A_MARK, FMSICK_MARK,
-	CS5B_MARK, FCE1_MARK,
-
-	/* 55-3 */
-	CS6B_MARK, XCS2_MARK, CS6A_MARK, DACK0_MARK,
-	FCE0_MARK,
-	WAIT_MARK, DREQ0_MARK,
-	RD_XRD_MARK,
-	WE0_XWR0_FWE_MARK,
-	WE1_XWR1_MARK,
-	FRB_MARK,
-	CKO_MARK,
-	NBRSTOUT_MARK,
-	NBRST_MARK,
-	GPS_EPPSIN_MARK,
-	LATCHPULSE_MARK,
-	LTESIGNAL_MARK,
-	LEGACYSTATE_MARK,
-	TCKON_MARK,
-	VIO_VD_MARK, PORT128_KEYOUT0_MARK, IPORT0_MARK,
-	VIO_HD_MARK, PORT129_KEYOUT1_MARK, IPORT1_MARK,
-	VIO_D0_MARK, PORT130_KEYOUT2_MARK, PORT130_MSIOF2_RXD_MARK,
-	VIO_D1_MARK, PORT131_KEYOUT3_MARK, PORT131_MSIOF2_SS1_MARK,
-	VIO_D2_MARK, PORT132_KEYOUT4_MARK, PORT132_MSIOF2_SS2_MARK,
-	VIO_D3_MARK, PORT133_KEYOUT5_MARK, PORT133_MSIOF2_TSYNC_MARK,
-	VIO_D4_MARK, PORT134_KEYIN0_MARK, PORT134_MSIOF2_TXD_MARK,
-	VIO_D5_MARK, PORT135_KEYIN1_MARK, PORT135_MSIOF2_TSCK_MARK,
-	VIO_D6_MARK, PORT136_KEYIN2_MARK,
-	VIO_D7_MARK, PORT137_KEYIN3_MARK,
-	VIO_D8_MARK, M9_SLCD_A01_MARK, PORT138_FSIAOMC_MARK,
-	VIO_D9_MARK, M10_SLCD_CK1_MARK, PORT139_FSIAOLR_MARK,
-	VIO_D10_MARK, M11_SLCD_SO1_MARK, TPU0TO2_MARK, PORT140_FSIAOBT_MARK,
-	VIO_D11_MARK, M12_SLCD_CE1_MARK, TPU0TO3_MARK, PORT141_FSIAOSLD_MARK,
-	VIO_D12_MARK, M13_BSW_MARK, PORT142_FSIACK_MARK,
-	VIO_D13_MARK, M14_GSW_MARK, PORT143_FSIAILR_MARK,
-	VIO_D14_MARK, M15_RSW_MARK, PORT144_FSIAIBT_MARK,
-	VIO_D15_MARK, TPU1TO3_MARK, PORT145_FSIAISLD_MARK,
-	VIO_CLK_MARK, PORT146_KEYIN4_MARK, IPORT2_MARK,
-	VIO_FIELD_MARK, PORT147_KEYIN5_MARK,
-	VIO_CKO_MARK, PORT148_KEYIN6_MARK,
-	A27_MARK, RDWR_XWE_MARK, MFG0_IN1_MARK,
-	MFG0_IN2_MARK,
-	TS_SPSYNC3_MARK, MSIOF2_RSCK_MARK,
-	TS_SDAT3_MARK, MSIOF2_RSYNC_MARK,
-	TPU1TO2_MARK, TS_SDEN3_MARK, PORT153_MSIOF2_SS1_MARK,
-	SOUT3_MARK, SCIFA2_TXD1_MARK, MSIOF2_MCK0_MARK,
-	SIN3_MARK, SCIFA2_RXD1_MARK, MSIOF2_MCK1_MARK,
-	XRTS3_MARK, SCIFA2_RTS1_MARK, PORT156_MSIOF2_SS2_MARK,
-	XCTS3_MARK, SCIFA2_CTS1_MARK, PORT157_MSIOF2_RXD_MARK,
-
-	/* 55-4 */
-	DINT_MARK, SCIFA2_SCK1_MARK, TS_SCK3_MARK,
-	PORT159_SCIFB_SCK_MARK, PORT159_SCIFA5_SCK_MARK, NMI_MARK,
-	PORT160_SCIFB_TXD_MARK, PORT160_SCIFA5_TXD_MARK, SOUT0_MARK,
-	PORT161_SCIFB_CTS_MARK, PORT161_SCIFA5_CTS_MARK, XCTS0_MARK,
-	MFG3_IN2_MARK,
-	PORT162_SCIFB_RXD_MARK, PORT162_SCIFA5_RXD_MARK, SIN0_MARK,
-	MFG3_IN1_MARK,
-	PORT163_SCIFB_RTS_MARK, PORT163_SCIFA5_RTS_MARK, XRTS0_MARK,
-	MFG3_OUT1_MARK, TPU3TO0_MARK,
-	LCDD0_MARK, PORT192_KEYOUT0_MARK, EXT_CKI_MARK,
-	LCDD1_MARK, PORT193_KEYOUT1_MARK, PORT193_SCIFA5_CTS_MARK,
-	BBIF2_TSYNC1_MARK,
-	LCDD2_MARK, PORT194_KEYOUT2_MARK, PORT194_SCIFA5_RTS_MARK,
-	BBIF2_TSCK1_MARK,
-	LCDD3_MARK, PORT195_KEYOUT3_MARK, PORT195_SCIFA5_RXD_MARK,
-	BBIF2_TXD1_MARK,
-	LCDD4_MARK, PORT196_KEYOUT4_MARK, PORT196_SCIFA5_TXD_MARK,
-	LCDD5_MARK, PORT197_KEYOUT5_MARK, PORT197_SCIFA5_SCK_MARK,
-	MFG2_OUT2_MARK,
-	TPU2TO1_MARK,
-	LCDD6_MARK, XWR2_MARK,
-	LCDD7_MARK, TPU4TO1_MARK, MFG4_OUT2_MARK, XWR3_MARK,
-	LCDD8_MARK, PORT200_KEYIN0_MARK, VIO_DR0_MARK, D16_MARK, ED16_MARK,
-	LCDD9_MARK, PORT201_KEYIN1_MARK, VIO_DR1_MARK, D17_MARK, ED17_MARK,
-	LCDD10_MARK, PORT202_KEYIN2_MARK, VIO_DR2_MARK, D18_MARK, ED18_MARK,
-	LCDD11_MARK, PORT203_KEYIN3_MARK, VIO_DR3_MARK, D19_MARK, ED19_MARK,
-	LCDD12_MARK, PORT204_KEYIN4_MARK, VIO_DR4_MARK, D20_MARK, ED20_MARK,
-	LCDD13_MARK, PORT205_KEYIN5_MARK, VIO_DR5_MARK, D21_MARK, ED21_MARK,
-	LCDD14_MARK, PORT206_KEYIN6_MARK, VIO_DR6_MARK, D22_MARK, ED22_MARK,
-	LCDD15_MARK, PORT207_MSIOF0L_SS1_MARK, PORT207_KEYOUT0_MARK,
-	VIO_DR7_MARK, D23_MARK, ED23_MARK,
-	LCDD16_MARK, PORT208_MSIOF0L_SS2_MARK, PORT208_KEYOUT1_MARK,
-	VIO_VDR_MARK, D24_MARK, ED24_MARK,
-	LCDD17_MARK, PORT209_KEYOUT2_MARK, VIO_HDR_MARK, D25_MARK, ED25_MARK,
-	LCDD18_MARK, DREQ2_MARK, PORT210_MSIOF0L_SS1_MARK, D26_MARK, ED26_MARK,
-	LCDD19_MARK, PORT211_MSIOF0L_SS2_MARK, D27_MARK, ED27_MARK,
-	LCDD20_MARK, TS_SPSYNC1_MARK, MSIOF0L_MCK0_MARK, D28_MARK, ED28_MARK,
-	LCDD21_MARK, TS_SDAT1_MARK, MSIOF0L_MCK1_MARK, D29_MARK, ED29_MARK,
-	LCDD22_MARK, TS_SDEN1_MARK, MSIOF0L_RSCK_MARK, D30_MARK, ED30_MARK,
-	LCDD23_MARK, TS_SCK1_MARK, MSIOF0L_RSYNC_MARK, D31_MARK, ED31_MARK,
-	LCDDCK_MARK, LCDWR_MARK, PORT216_KEYOUT3_MARK, VIO_CLKR_MARK,
-	LCDRD_MARK, DACK2_MARK, MSIOF0L_TSYNC_MARK,
-	LCDHSYN_MARK, LCDCS_MARK, LCDCS2_MARK, DACK3_MARK,
-	PORT218_VIO_CKOR_MARK, PORT218_KEYOUT4_MARK,
-	LCDDISP_MARK, LCDRS_MARK, DREQ3_MARK, MSIOF0L_TSCK_MARK,
-	LCDVSYN_MARK, LCDVSYN2_MARK, PORT220_KEYOUT5_MARK,
-	LCDLCLK_MARK, DREQ1_MARK, PWEN_MARK, MSIOF0L_RXD_MARK,
-	LCDDON_MARK, LCDDON2_MARK, DACK1_MARK, OVCN_MARK, MSIOF0L_TXD_MARK,
-	SCIFA1_TXD_MARK, OVCN2_MARK,
-	EXTLP_MARK, SCIFA1_SCK_MARK, USBTERM_MARK, PORT226_VIO_CKO2_MARK,
-	SCIFA1_RTS_MARK, IDIN_MARK,
-	SCIFA1_RXD_MARK,
-	SCIFA1_CTS_MARK, MFG1_IN1_MARK,
-	MSIOF1_TXD_MARK, SCIFA2_TXD2_MARK, PORT230_FSIAOMC_MARK,
-	MSIOF1_TSYNC_MARK, SCIFA2_CTS2_MARK, PORT231_FSIAOLR_MARK,
-	MSIOF1_TSCK_MARK, SCIFA2_SCK2_MARK, PORT232_FSIAOBT_MARK,
-	MSIOF1_RXD_MARK, SCIFA2_RXD2_MARK, GPS_VCOTRIG_MARK,
-	PORT233_FSIACK_MARK,
-	MSIOF1_RSCK_MARK, SCIFA2_RTS2_MARK, PORT234_FSIAOSLD_MARK,
-	MSIOF1_RSYNC_MARK, OPORT0_MARK, MFG1_IN2_MARK, PORT235_FSIAILR_MARK,
-	MSIOF1_MCK0_MARK, I2C_SDA2_MARK, PORT236_FSIAIBT_MARK,
-	MSIOF1_MCK1_MARK, I2C_SCL2_MARK, PORT237_FSIAISLD_MARK,
-	MSIOF1_SS1_MARK, EDBGREQ3_MARK,
-
-	/* 55-5 */
-	MSIOF1_SS2_MARK,
-	SCIFA6_TXD_MARK,
-	PORT241_IRDA_OUT_MARK, PORT241_IROUT_MARK, MFG4_OUT1_MARK,
-	TPU4TO0_MARK,
-	PORT242_IRDA_IN_MARK, MFG4_IN2_MARK,
-	PORT243_IRDA_FIRSEL_MARK, PORT243_VIO_CKO2_MARK,
-	PORT244_SCIFA5_CTS_MARK, MFG2_IN1_MARK, PORT244_SCIFB_CTS_MARK,
-	PORT244_MSIOF2_RXD_MARK,
-	PORT245_SCIFA5_RTS_MARK, MFG2_IN2_MARK, PORT245_SCIFB_RTS_MARK,
-	PORT245_MSIOF2_TXD_MARK,
-	PORT246_SCIFA5_RXD_MARK, MFG1_OUT1_MARK, PORT246_SCIFB_RXD_MARK,
-	TPU1TO0_MARK,
-	PORT247_SCIFA5_TXD_MARK, MFG3_OUT2_MARK, PORT247_SCIFB_TXD_MARK,
-	TPU3TO1_MARK,
-	PORT248_SCIFA5_SCK_MARK, MFG2_OUT1_MARK, PORT248_SCIFB_SCK_MARK,
-	TPU2TO0_MARK,
-	PORT248_MSIOF2_TSCK_MARK,
-	PORT249_IROUT_MARK, MFG4_IN1_MARK, PORT249_MSIOF2_TSYNC_MARK,
-	SDHICLK0_MARK, TCK2_SWCLK_MC0_MARK,
-	SDHICD0_MARK,
-	SDHID0_0_MARK, TMS2_SWDIO_MC0_MARK,
-	SDHID0_1_MARK, TDO2_SWO0_MC0_MARK,
-	SDHID0_2_MARK, TDI2_MARK,
-	SDHID0_3_MARK, RTCK2_SWO1_MC0_MARK,
-	SDHICMD0_MARK, TRST2_MARK,
-	SDHIWP0_MARK, EDBGREQ2_MARK,
-	SDHICLK1_MARK, TCK3_SWCLK_MC1_MARK,
-	SDHID1_0_MARK, M11_SLCD_SO2_MARK, TS_SPSYNC2_MARK,
-	TMS3_SWDIO_MC1_MARK,
-	SDHID1_1_MARK, M9_SLCD_A02_MARK, TS_SDAT2_MARK, TDO3_SWO0_MC1_MARK,
-	SDHID1_2_MARK, M10_SLCD_CK2_MARK, TS_SDEN2_MARK, TDI3_MARK,
-	SDHID1_3_MARK, M12_SLCD_CE2_MARK, TS_SCK2_MARK, RTCK3_SWO1_MC1_MARK,
-	SDHICMD1_MARK, TRST3_MARK,
-	RESETOUTS_MARK,
-	PINMUX_MARK_END,
-};
-
-static pinmux_enum_t pinmux_data[] = {
-	/* specify valid pin states for each pin in GPIO mode */
-	/* 55-1 (GPIO) */
-	PORT_DATA_I_PD(0), PORT_DATA_I_PU(1),
-	PORT_DATA_I_PU(2), PORT_DATA_I_PU(3),
-	PORT_DATA_I_PU(4), PORT_DATA_I_PU(5),
-	PORT_DATA_I_PU(6), PORT_DATA_I_PU(7),
-	PORT_DATA_I_PU(8), PORT_DATA_I_PU(9),
-	PORT_DATA_I_PU(10), PORT_DATA_I_PU(11),
-	PORT_DATA_IO_PU(12), PORT_DATA_IO_PU(13),
-	PORT_DATA_IO_PU_PD(14), PORT_DATA_IO_PU_PD(15),
-	PORT_DATA_O(16), PORT_DATA_IO(17),
-	PORT_DATA_O(18), PORT_DATA_O(19),
-	PORT_DATA_O(20), PORT_DATA_O(21),
-	PORT_DATA_O(22), PORT_DATA_O(23),
-	PORT_DATA_O(24), PORT_DATA_I_PD(25),
-	PORT_DATA_I_PD(26), PORT_DATA_O(27),
-	PORT_DATA_O(28), PORT_DATA_O(29),
-	PORT_DATA_IO(30), PORT_DATA_IO_PU(31),
-	PORT_DATA_IO_PD(32), PORT_DATA_I_PU(33),
-	PORT_DATA_IO_PD(34), PORT_DATA_I_PU_PD(35),
-	PORT_DATA_O(36), PORT_DATA_IO(37),
-
-	/* 55-2 (GPIO) */
-	PORT_DATA_O(38), PORT_DATA_I_PU(39),
-	PORT_DATA_I_PU_PD(40), PORT_DATA_O(41),
-	PORT_DATA_IO_PD(42), PORT_DATA_IO_PD(43),
-	PORT_DATA_IO_PD(44), PORT_DATA_I_PD(45),
-	PORT_DATA_I_PD(46), PORT_DATA_I_PD(47),
-	PORT_DATA_I_PD(48), PORT_DATA_IO_PU_PD(49),
-	PORT_DATA_IO_PD(50), PORT_DATA_IO_PD(51),
-	PORT_DATA_O(52), PORT_DATA_IO_PU_PD(53),
-	PORT_DATA_IO_PU_PD(54), PORT_DATA_IO_PD(55),
-	PORT_DATA_I_PU_PD(56), PORT_DATA_IO(57),
-	PORT_DATA_IO(58), PORT_DATA_IO(59),
-	PORT_DATA_IO(60), PORT_DATA_IO(61),
-	PORT_DATA_IO_PD(62), PORT_DATA_IO_PD(63),
-	PORT_DATA_IO_PD(64), PORT_DATA_IO_PD(65),
-	PORT_DATA_IO_PU_PD(66), PORT_DATA_IO_PU_PD(67),
-	PORT_DATA_IO_PU_PD(68), PORT_DATA_IO_PU_PD(69),
-	PORT_DATA_IO_PU_PD(70), PORT_DATA_IO_PU_PD(71),
-	PORT_DATA_IO_PU_PD(72), PORT_DATA_I_PU_PD(73),
-	PORT_DATA_IO_PU(74), PORT_DATA_IO_PU(75),
-	PORT_DATA_IO_PU(76), PORT_DATA_IO_PU(77),
-	PORT_DATA_IO_PU(78), PORT_DATA_IO_PU(79),
-	PORT_DATA_IO_PU(80), PORT_DATA_IO_PU(81),
-	PORT_DATA_IO_PU(82), PORT_DATA_IO_PU(83),
-	PORT_DATA_IO_PU(84), PORT_DATA_IO_PU(85),
-	PORT_DATA_IO_PU(86), PORT_DATA_IO_PU(87),
-	PORT_DATA_IO_PU(88), PORT_DATA_IO_PU(89),
-	PORT_DATA_O(90), PORT_DATA_IO_PU(91),
-	PORT_DATA_O(92),
-
-	/* 55-3 (GPIO) */
-	PORT_DATA_IO_PU(93),
-	PORT_DATA_O(94),
-	PORT_DATA_I_PU_PD(95),
-	PORT_DATA_IO(96), PORT_DATA_IO(97),
-	PORT_DATA_IO(98), PORT_DATA_I_PU(99),
-	PORT_DATA_O(100), PORT_DATA_O(101),
-	PORT_DATA_I_PU(102), PORT_DATA_IO_PD(103),
-	PORT_DATA_I_PD(104), PORT_DATA_I_PD(105),
-	PORT_DATA_I_PD(106), PORT_DATA_I_PD(107),
-	PORT_DATA_I_PD(108), PORT_DATA_IO_PD(109),
-	PORT_DATA_IO_PD(110), PORT_DATA_I_PD(111),
-	PORT_DATA_IO_PD(112), PORT_DATA_IO_PD(113),
-	PORT_DATA_IO_PD(114), PORT_DATA_I_PD(115),
-	PORT_DATA_I_PD(116), PORT_DATA_IO_PD(117),
-	PORT_DATA_I_PD(118), PORT_DATA_IO_PD(128),
-	PORT_DATA_IO_PD(129), PORT_DATA_IO_PD(130),
-	PORT_DATA_IO_PD(131), PORT_DATA_IO_PD(132),
-	PORT_DATA_IO_PD(133), PORT_DATA_IO_PU_PD(134),
-	PORT_DATA_IO_PU_PD(135), PORT_DATA_IO_PU_PD(136),
-	PORT_DATA_IO_PU_PD(137), PORT_DATA_IO_PD(138),
-	PORT_DATA_IO_PD(139), PORT_DATA_IO_PD(140),
-	PORT_DATA_IO_PD(141), PORT_DATA_IO_PD(142),
-	PORT_DATA_IO_PD(143), PORT_DATA_IO_PU_PD(144),
-	PORT_DATA_IO_PD(145), PORT_DATA_IO_PU_PD(146),
-	PORT_DATA_IO_PU_PD(147), PORT_DATA_IO_PU_PD(148),
-	PORT_DATA_IO_PU_PD(149), PORT_DATA_I_PD(150),
-	PORT_DATA_IO_PU_PD(151), PORT_DATA_IO_PD(152),
-	PORT_DATA_IO_PD(153), PORT_DATA_IO_PD(154),
-	PORT_DATA_I_PD(155), PORT_DATA_IO_PU_PD(156),
-	PORT_DATA_I_PD(157), PORT_DATA_IO_PD(158),
-
-	/* 55-4 (GPIO) */
-	PORT_DATA_IO_PU_PD(159), PORT_DATA_IO_PU_PD(160),
-	PORT_DATA_I_PU_PD(161), PORT_DATA_I_PU_PD(162),
-	PORT_DATA_IO_PU_PD(163), PORT_DATA_I_PU_PD(164),
-	PORT_DATA_IO_PD(192), PORT_DATA_IO_PD(193),
-	PORT_DATA_IO_PD(194), PORT_DATA_IO_PD(195),
-	PORT_DATA_IO_PD(196), PORT_DATA_IO_PD(197),
-	PORT_DATA_IO_PD(198), PORT_DATA_IO_PD(199),
-	PORT_DATA_IO_PU_PD(200), PORT_DATA_IO_PU_PD(201),
-	PORT_DATA_IO_PU_PD(202), PORT_DATA_IO_PU_PD(203),
-	PORT_DATA_IO_PU_PD(204), PORT_DATA_IO_PU_PD(205),
-	PORT_DATA_IO_PU_PD(206), PORT_DATA_IO_PD(207),
-	PORT_DATA_IO_PD(208), PORT_DATA_IO_PD(209),
-	PORT_DATA_IO_PD(210), PORT_DATA_IO_PD(211),
-	PORT_DATA_IO_PD(212), PORT_DATA_IO_PD(213),
-	PORT_DATA_IO_PD(214), PORT_DATA_IO_PD(215),
-	PORT_DATA_IO_PD(216), PORT_DATA_IO_PD(217),
-	PORT_DATA_O(218), PORT_DATA_IO_PD(219),
-	PORT_DATA_IO_PD(220), PORT_DATA_IO_PD(221),
-	PORT_DATA_IO_PU_PD(222),
-	PORT_DATA_I_PU_PD(223), PORT_DATA_I_PU_PD(224),
-	PORT_DATA_IO_PU_PD(225), PORT_DATA_O(226),
-	PORT_DATA_IO_PU_PD(227), PORT_DATA_I_PD(228),
-	PORT_DATA_I_PD(229), PORT_DATA_IO(230),
-	PORT_DATA_IO_PD(231), PORT_DATA_IO_PU_PD(232),
-	PORT_DATA_I_PD(233), PORT_DATA_IO_PU_PD(234),
-	PORT_DATA_IO_PU_PD(235), PORT_DATA_IO_PU_PD(236),
-	PORT_DATA_IO_PD(237), PORT_DATA_IO_PU_PD(238),
-
-	/* 55-5 (GPIO) */
-	PORT_DATA_IO_PU_PD(239), PORT_DATA_IO_PU_PD(240),
-	PORT_DATA_O(241), PORT_DATA_I_PD(242),
-	PORT_DATA_IO_PU_PD(243), PORT_DATA_IO_PU_PD(244),
-	PORT_DATA_IO_PU_PD(245), PORT_DATA_IO_PU_PD(246),
-	PORT_DATA_IO_PU_PD(247), PORT_DATA_IO_PU_PD(248),
-	PORT_DATA_IO_PU_PD(249), PORT_DATA_IO_PD(250),
-	PORT_DATA_IO_PU_PD(251), PORT_DATA_IO_PU_PD(252),
-	PORT_DATA_IO_PU_PD(253), PORT_DATA_IO_PU_PD(254),
-	PORT_DATA_IO_PU_PD(255), PORT_DATA_IO_PU_PD(256),
-	PORT_DATA_IO_PU_PD(257), PORT_DATA_IO_PD(258),
-	PORT_DATA_IO_PU_PD(259), PORT_DATA_IO_PU_PD(260),
-	PORT_DATA_IO_PU_PD(261), PORT_DATA_IO_PU_PD(262),
-	PORT_DATA_IO_PU_PD(263),
-
-	/* Special Pull-up / Pull-down Functions */
-	PINMUX_DATA(PORT66_KEYIN0_PU_MARK, MSELBCR_MSEL17_0, MSELBCR_MSEL16_0,
-				PORT66_FN2, PORT66_IN_PU),
-	PINMUX_DATA(PORT67_KEYIN1_PU_MARK, MSELBCR_MSEL17_0, MSELBCR_MSEL16_0,
-				PORT67_FN2, PORT67_IN_PU),
-	PINMUX_DATA(PORT68_KEYIN2_PU_MARK, MSELBCR_MSEL17_0, MSELBCR_MSEL16_0,
-				PORT68_FN2, PORT68_IN_PU),
-	PINMUX_DATA(PORT69_KEYIN3_PU_MARK, MSELBCR_MSEL17_0, MSELBCR_MSEL16_0,
-				PORT69_FN2, PORT69_IN_PU),
-	PINMUX_DATA(PORT70_KEYIN4_PU_MARK, MSELBCR_MSEL17_0, MSELBCR_MSEL16_0,
-				PORT70_FN2, PORT70_IN_PU),
-	PINMUX_DATA(PORT71_KEYIN5_PU_MARK, MSELBCR_MSEL17_0, MSELBCR_MSEL16_0,
-				PORT71_FN2, PORT71_IN_PU),
-	PINMUX_DATA(PORT72_KEYIN6_PU_MARK, MSELBCR_MSEL17_0, MSELBCR_MSEL16_0,
-				PORT72_FN2, PORT72_IN_PU),
-
-
-	/* 55-1 (FN) */
-	PINMUX_DATA(VBUS_0_MARK, PORT0_FN1),
-	PINMUX_DATA(CPORT0_MARK, PORT1_FN1),
-	PINMUX_DATA(CPORT1_MARK, PORT2_FN1),
-	PINMUX_DATA(CPORT2_MARK, PORT3_FN1),
-	PINMUX_DATA(CPORT3_MARK, PORT4_FN1),
-	PINMUX_DATA(CPORT4_MARK, PORT5_FN1),
-	PINMUX_DATA(CPORT5_MARK, PORT6_FN1),
-	PINMUX_DATA(CPORT6_MARK, PORT7_FN1),
-	PINMUX_DATA(CPORT7_MARK, PORT8_FN1),
-	PINMUX_DATA(CPORT8_MARK, PORT9_FN1),
-	PINMUX_DATA(CPORT9_MARK, PORT10_FN1),
-	PINMUX_DATA(CPORT10_MARK, PORT11_FN1),
-	PINMUX_DATA(CPORT11_MARK, PORT12_FN1),
-	PINMUX_DATA(SIN2_MARK, PORT12_FN2),
-	PINMUX_DATA(CPORT12_MARK, PORT13_FN1),
-	PINMUX_DATA(XCTS2_MARK, PORT13_FN2),
-	PINMUX_DATA(CPORT13_MARK, PORT14_FN1),
-	PINMUX_DATA(RFSPO4_MARK, PORT14_FN2),
-	PINMUX_DATA(CPORT14_MARK, PORT15_FN1),
-	PINMUX_DATA(RFSPO5_MARK, PORT15_FN2),
-	PINMUX_DATA(CPORT15_MARK, PORT16_FN1),
-	PINMUX_DATA(SCIFA0_SCK_MARK, PORT16_FN2),
-	PINMUX_DATA(GPS_AGC2_MARK, PORT16_FN3),
-	PINMUX_DATA(CPORT16_MARK, PORT17_FN1),
-	PINMUX_DATA(SCIFA0_TXD_MARK, PORT17_FN2),
-	PINMUX_DATA(GPS_AGC3_MARK, PORT17_FN3),
-	PINMUX_DATA(CPORT17_IC_OE_MARK, PORT18_FN1),
-	PINMUX_DATA(SOUT2_MARK, PORT18_FN2),
-	PINMUX_DATA(CPORT18_MARK, PORT19_FN1),
-	PINMUX_DATA(XRTS2_MARK, PORT19_FN2),
-	PINMUX_DATA(PORT19_VIO_CKO2_MARK, PORT19_FN3),
-	PINMUX_DATA(CPORT19_MPORT1_MARK, PORT20_FN1),
-	PINMUX_DATA(CPORT20_MARK, PORT21_FN1),
-	PINMUX_DATA(RFSPO6_MARK, PORT21_FN2),
-	PINMUX_DATA(CPORT21_MARK, PORT22_FN1),
-	PINMUX_DATA(STATUS0_MARK, PORT22_FN2),
-	PINMUX_DATA(CPORT22_MARK, PORT23_FN1),
-	PINMUX_DATA(STATUS1_MARK, PORT23_FN2),
-	PINMUX_DATA(CPORT23_MARK, PORT24_FN1),
-	PINMUX_DATA(STATUS2_MARK, PORT24_FN2),
-	PINMUX_DATA(RFSPO7_MARK, PORT24_FN3),
-	PINMUX_DATA(B_SYNLD1_MARK, PORT25_FN1),
-	PINMUX_DATA(B_SYNLD2_MARK, PORT26_FN1),
-	PINMUX_DATA(SYSENMSK_MARK, PORT26_FN2),
-	PINMUX_DATA(XMAINPS_MARK, PORT27_FN1),
-	PINMUX_DATA(XDIVPS_MARK, PORT28_FN1),
-	PINMUX_DATA(XIDRST_MARK, PORT29_FN1),
-	PINMUX_DATA(IDCLK_MARK, PORT30_FN1),
-	PINMUX_DATA(IC_DP_MARK, PORT30_FN2),
-	PINMUX_DATA(IDIO_MARK, PORT31_FN1),
-	PINMUX_DATA(IC_DM_MARK, PORT31_FN2),
-	PINMUX_DATA(SOUT1_MARK, PORT32_FN1),
-	PINMUX_DATA(SCIFA4_TXD_MARK, PORT32_FN2),
-	PINMUX_DATA(M02_BERDAT_MARK, PORT32_FN3),
-	PINMUX_DATA(SIN1_MARK, PORT33_FN1),
-	PINMUX_DATA(SCIFA4_RXD_MARK, PORT33_FN2),
-	PINMUX_DATA(XWUP_MARK, PORT33_FN3),
-	PINMUX_DATA(XRTS1_MARK, PORT34_FN1),
-	PINMUX_DATA(SCIFA4_RTS_MARK, PORT34_FN2),
-	PINMUX_DATA(M03_BERCLK_MARK, PORT34_FN3),
-	PINMUX_DATA(XCTS1_MARK, PORT35_FN1),
-	PINMUX_DATA(SCIFA4_CTS_MARK, PORT35_FN2),
-	PINMUX_DATA(PCMCLKO_MARK, PORT36_FN1),
-	PINMUX_DATA(SYNC8KO_MARK, PORT37_FN1),
-
-	/* 55-2 (FN) */
-	PINMUX_DATA(DNPCM_A_MARK, PORT38_FN1),
-	PINMUX_DATA(UPPCM_A_MARK, PORT39_FN1),
-	PINMUX_DATA(VACK_MARK, PORT40_FN1),
-	PINMUX_DATA(XTALB1L_MARK, PORT41_FN1),
-	PINMUX_DATA(GPS_AGC1_MARK, PORT42_FN1),
-	PINMUX_DATA(SCIFA0_RTS_MARK, PORT42_FN2),
-	PINMUX_DATA(GPS_AGC4_MARK, PORT43_FN1),
-	PINMUX_DATA(SCIFA0_RXD_MARK, PORT43_FN2),
-	PINMUX_DATA(GPS_PWRDOWN_MARK, PORT44_FN1),
-	PINMUX_DATA(SCIFA0_CTS_MARK, PORT44_FN2),
-	PINMUX_DATA(GPS_IM_MARK, PORT45_FN1),
-	PINMUX_DATA(GPS_IS_MARK, PORT46_FN1),
-	PINMUX_DATA(GPS_QM_MARK, PORT47_FN1),
-	PINMUX_DATA(GPS_QS_MARK, PORT48_FN1),
-	PINMUX_DATA(FMSOCK_MARK, PORT49_FN1),
-	PINMUX_DATA(PORT49_IRDA_OUT_MARK, PORT49_FN2),
-	PINMUX_DATA(PORT49_IROUT_MARK, PORT49_FN3),
-	PINMUX_DATA(FMSOOLR_MARK, PORT50_FN1),
-	PINMUX_DATA(BBIF2_TSYNC2_MARK, PORT50_FN2),
-	PINMUX_DATA(TPU2TO2_MARK, PORT50_FN3),
-	PINMUX_DATA(IPORT3_MARK, PORT50_FN4),
-	PINMUX_DATA(FMSIOLR_MARK, PORT50_FN5),
-	PINMUX_DATA(FMSOOBT_MARK, PORT51_FN1),
-	PINMUX_DATA(BBIF2_TSCK2_MARK, PORT51_FN2),
-	PINMUX_DATA(TPU2TO3_MARK, PORT51_FN3),
-	PINMUX_DATA(OPORT1_MARK, PORT51_FN4),
-	PINMUX_DATA(FMSIOBT_MARK, PORT51_FN5),
-	PINMUX_DATA(FMSOSLD_MARK, PORT52_FN1),
-	PINMUX_DATA(BBIF2_TXD2_MARK, PORT52_FN2),
-	PINMUX_DATA(OPORT2_MARK, PORT52_FN3),
-	PINMUX_DATA(FMSOILR_MARK, PORT53_FN1),
-	PINMUX_DATA(PORT53_IRDA_IN_MARK, PORT53_FN2),
-	PINMUX_DATA(TPU3TO3_MARK, PORT53_FN3),
-	PINMUX_DATA(OPORT3_MARK, PORT53_FN4),
-	PINMUX_DATA(FMSIILR_MARK, PORT53_FN5),
-	PINMUX_DATA(FMSOIBT_MARK, PORT54_FN1),
-	PINMUX_DATA(PORT54_IRDA_FIRSEL_MARK, PORT54_FN2),
-	PINMUX_DATA(TPU3TO2_MARK, PORT54_FN3),
-	PINMUX_DATA(FMSIIBT_MARK, PORT54_FN4),
-	PINMUX_DATA(FMSISLD_MARK, PORT55_FN1),
-	PINMUX_DATA(MFG0_OUT1_MARK, PORT55_FN2),
-	PINMUX_DATA(TPU0TO0_MARK, PORT55_FN3),
-	PINMUX_DATA(A0_EA0_MARK, PORT57_FN1),
-	PINMUX_DATA(BS_MARK, PORT57_FN2),
-	PINMUX_DATA(A12_EA12_MARK, PORT58_FN1),
-	PINMUX_DATA(PORT58_VIO_CKOR_MARK, PORT58_FN2),
-	PINMUX_DATA(TPU4TO2_MARK, PORT58_FN3),
-	PINMUX_DATA(A13_EA13_MARK, PORT59_FN1),
-	PINMUX_DATA(PORT59_IROUT_MARK, PORT59_FN2),
-	PINMUX_DATA(MFG0_OUT2_MARK, PORT59_FN3),
-	PINMUX_DATA(TPU0TO1_MARK, PORT59_FN4),
-	PINMUX_DATA(A14_EA14_MARK, PORT60_FN1),
-	PINMUX_DATA(PORT60_KEYOUT5_MARK, PORT60_FN2),
-	PINMUX_DATA(A15_EA15_MARK, PORT61_FN1),
-	PINMUX_DATA(PORT61_KEYOUT4_MARK, PORT61_FN2),
-	PINMUX_DATA(A16_EA16_MARK, PORT62_FN1),
-	PINMUX_DATA(PORT62_KEYOUT3_MARK, PORT62_FN2),
-	PINMUX_DATA(MSIOF0_SS1_MARK, PORT62_FN3),
-	PINMUX_DATA(A17_EA17_MARK, PORT63_FN1),
-	PINMUX_DATA(PORT63_KEYOUT2_MARK, PORT63_FN2),
-	PINMUX_DATA(MSIOF0_TSYNC_MARK, PORT63_FN3),
-	PINMUX_DATA(A18_EA18_MARK, PORT64_FN1),
-	PINMUX_DATA(PORT64_KEYOUT1_MARK, PORT64_FN2),
-	PINMUX_DATA(MSIOF0_TSCK_MARK, PORT64_FN3),
-	PINMUX_DATA(A19_EA19_MARK, PORT65_FN1),
-	PINMUX_DATA(PORT65_KEYOUT0_MARK, PORT65_FN2),
-	PINMUX_DATA(MSIOF0_TXD_MARK, PORT65_FN3),
-	PINMUX_DATA(A20_EA20_MARK, PORT66_FN1),
-	PINMUX_DATA(PORT66_KEYIN0_MARK, PORT66_FN2),
-	PINMUX_DATA(MSIOF0_RSCK_MARK, PORT66_FN3),
-	PINMUX_DATA(A21_EA21_MARK, PORT67_FN1),
-	PINMUX_DATA(PORT67_KEYIN1_MARK, PORT67_FN2),
-	PINMUX_DATA(MSIOF0_RSYNC_MARK, PORT67_FN3),
-	PINMUX_DATA(A22_EA22_MARK, PORT68_FN1),
-	PINMUX_DATA(PORT68_KEYIN2_MARK, PORT68_FN2),
-	PINMUX_DATA(MSIOF0_MCK0_MARK, PORT68_FN3),
-	PINMUX_DATA(A23_EA23_MARK, PORT69_FN1),
-	PINMUX_DATA(PORT69_KEYIN3_MARK, PORT69_FN2),
-	PINMUX_DATA(MSIOF0_MCK1_MARK, PORT69_FN3),
-	PINMUX_DATA(A24_EA24_MARK, PORT70_FN1),
-	PINMUX_DATA(PORT70_KEYIN4_MARK, PORT70_FN2),
-	PINMUX_DATA(MSIOF0_RXD_MARK, PORT70_FN3),
-	PINMUX_DATA(A25_EA25_MARK, PORT71_FN1),
-	PINMUX_DATA(PORT71_KEYIN5_MARK, PORT71_FN2),
-	PINMUX_DATA(MSIOF0_SS2_MARK, PORT71_FN3),
-	PINMUX_DATA(A26_MARK, PORT72_FN1),
-	PINMUX_DATA(PORT72_KEYIN6_MARK, PORT72_FN2),
-	PINMUX_DATA(D0_ED0_NAF0_MARK, PORT74_FN1),
-	PINMUX_DATA(D1_ED1_NAF1_MARK, PORT75_FN1),
-	PINMUX_DATA(D2_ED2_NAF2_MARK, PORT76_FN1),
-	PINMUX_DATA(D3_ED3_NAF3_MARK, PORT77_FN1),
-	PINMUX_DATA(D4_ED4_NAF4_MARK, PORT78_FN1),
-	PINMUX_DATA(D5_ED5_NAF5_MARK, PORT79_FN1),
-	PINMUX_DATA(D6_ED6_NAF6_MARK, PORT80_FN1),
-	PINMUX_DATA(D7_ED7_NAF7_MARK, PORT81_FN1),
-	PINMUX_DATA(D8_ED8_NAF8_MARK, PORT82_FN1),
-	PINMUX_DATA(D9_ED9_NAF9_MARK, PORT83_FN1),
-	PINMUX_DATA(D10_ED10_NAF10_MARK, PORT84_FN1),
-	PINMUX_DATA(D11_ED11_NAF11_MARK, PORT85_FN1),
-	PINMUX_DATA(D12_ED12_NAF12_MARK, PORT86_FN1),
-	PINMUX_DATA(D13_ED13_NAF13_MARK, PORT87_FN1),
-	PINMUX_DATA(D14_ED14_NAF14_MARK, PORT88_FN1),
-	PINMUX_DATA(D15_ED15_NAF15_MARK, PORT89_FN1),
-	PINMUX_DATA(CS4_MARK, PORT90_FN1),
-	PINMUX_DATA(CS5A_MARK, PORT91_FN1),
-	PINMUX_DATA(FMSICK_MARK, PORT91_FN2),
-	PINMUX_DATA(CS5B_MARK, PORT92_FN1),
-	PINMUX_DATA(FCE1_MARK, PORT92_FN2),
-
-	/* 55-3 (FN) */
-	PINMUX_DATA(CS6B_MARK, PORT93_FN1),
-	PINMUX_DATA(XCS2_MARK, PORT93_FN2),
-	PINMUX_DATA(CS6A_MARK, PORT93_FN3),
-	PINMUX_DATA(DACK0_MARK, PORT93_FN4),
-	PINMUX_DATA(FCE0_MARK, PORT94_FN1),
-	PINMUX_DATA(WAIT_MARK, PORT95_FN1),
-	PINMUX_DATA(DREQ0_MARK, PORT95_FN2),
-	PINMUX_DATA(RD_XRD_MARK, PORT96_FN1),
-	PINMUX_DATA(WE0_XWR0_FWE_MARK, PORT97_FN1),
-	PINMUX_DATA(WE1_XWR1_MARK, PORT98_FN1),
-	PINMUX_DATA(FRB_MARK, PORT99_FN1),
-	PINMUX_DATA(CKO_MARK, PORT100_FN1),
-	PINMUX_DATA(NBRSTOUT_MARK, PORT101_FN1),
-	PINMUX_DATA(NBRST_MARK, PORT102_FN1),
-	PINMUX_DATA(GPS_EPPSIN_MARK, PORT106_FN1),
-	PINMUX_DATA(LATCHPULSE_MARK, PORT110_FN1),
-	PINMUX_DATA(LTESIGNAL_MARK, PORT111_FN1),
-	PINMUX_DATA(LEGACYSTATE_MARK, PORT112_FN1),
-	PINMUX_DATA(TCKON_MARK, PORT118_FN1),
-	PINMUX_DATA(VIO_VD_MARK, PORT128_FN1),
-	PINMUX_DATA(PORT128_KEYOUT0_MARK, PORT128_FN2),
-	PINMUX_DATA(IPORT0_MARK, PORT128_FN3),
-	PINMUX_DATA(VIO_HD_MARK, PORT129_FN1),
-	PINMUX_DATA(PORT129_KEYOUT1_MARK, PORT129_FN2),
-	PINMUX_DATA(IPORT1_MARK, PORT129_FN3),
-	PINMUX_DATA(VIO_D0_MARK, PORT130_FN1),
-	PINMUX_DATA(PORT130_KEYOUT2_MARK, PORT130_FN2),
-	PINMUX_DATA(PORT130_MSIOF2_RXD_MARK, PORT130_FN3),
-	PINMUX_DATA(VIO_D1_MARK, PORT131_FN1),
-	PINMUX_DATA(PORT131_KEYOUT3_MARK, PORT131_FN2),
-	PINMUX_DATA(PORT131_MSIOF2_SS1_MARK, PORT131_FN3),
-	PINMUX_DATA(VIO_D2_MARK, PORT132_FN1),
-	PINMUX_DATA(PORT132_KEYOUT4_MARK, PORT132_FN2),
-	PINMUX_DATA(PORT132_MSIOF2_SS2_MARK, PORT132_FN3),
-	PINMUX_DATA(VIO_D3_MARK, PORT133_FN1),
-	PINMUX_DATA(PORT133_KEYOUT5_MARK, PORT133_FN2),
-	PINMUX_DATA(PORT133_MSIOF2_TSYNC_MARK, PORT133_FN3),
-	PINMUX_DATA(VIO_D4_MARK, PORT134_FN1),
-	PINMUX_DATA(PORT134_KEYIN0_MARK, PORT134_FN2),
-	PINMUX_DATA(PORT134_MSIOF2_TXD_MARK, PORT134_FN3),
-	PINMUX_DATA(VIO_D5_MARK, PORT135_FN1),
-	PINMUX_DATA(PORT135_KEYIN1_MARK, PORT135_FN2),
-	PINMUX_DATA(PORT135_MSIOF2_TSCK_MARK, PORT135_FN3),
-	PINMUX_DATA(VIO_D6_MARK, PORT136_FN1),
-	PINMUX_DATA(PORT136_KEYIN2_MARK, PORT136_FN2),
-	PINMUX_DATA(VIO_D7_MARK, PORT137_FN1),
-	PINMUX_DATA(PORT137_KEYIN3_MARK, PORT137_FN2),
-	PINMUX_DATA(VIO_D8_MARK, PORT138_FN1),
-	PINMUX_DATA(M9_SLCD_A01_MARK, PORT138_FN2),
-	PINMUX_DATA(PORT138_FSIAOMC_MARK, PORT138_FN3),
-	PINMUX_DATA(VIO_D9_MARK, PORT139_FN1),
-	PINMUX_DATA(M10_SLCD_CK1_MARK, PORT139_FN2),
-	PINMUX_DATA(PORT139_FSIAOLR_MARK, PORT139_FN3),
-	PINMUX_DATA(VIO_D10_MARK, PORT140_FN1),
-	PINMUX_DATA(M11_SLCD_SO1_MARK, PORT140_FN2),
-	PINMUX_DATA(TPU0TO2_MARK, PORT140_FN3),
-	PINMUX_DATA(PORT140_FSIAOBT_MARK, PORT140_FN4),
-	PINMUX_DATA(VIO_D11_MARK, PORT141_FN1),
-	PINMUX_DATA(M12_SLCD_CE1_MARK, PORT141_FN2),
-	PINMUX_DATA(TPU0TO3_MARK, PORT141_FN3),
-	PINMUX_DATA(PORT141_FSIAOSLD_MARK, PORT141_FN4),
-	PINMUX_DATA(VIO_D12_MARK, PORT142_FN1),
-	PINMUX_DATA(M13_BSW_MARK, PORT142_FN2),
-	PINMUX_DATA(PORT142_FSIACK_MARK, PORT142_FN3),
-	PINMUX_DATA(VIO_D13_MARK, PORT143_FN1),
-	PINMUX_DATA(M14_GSW_MARK, PORT143_FN2),
-	PINMUX_DATA(PORT143_FSIAILR_MARK, PORT143_FN3),
-	PINMUX_DATA(VIO_D14_MARK, PORT144_FN1),
-	PINMUX_DATA(M15_RSW_MARK, PORT144_FN2),
-	PINMUX_DATA(PORT144_FSIAIBT_MARK, PORT144_FN3),
-	PINMUX_DATA(VIO_D15_MARK, PORT145_FN1),
-	PINMUX_DATA(TPU1TO3_MARK, PORT145_FN2),
-	PINMUX_DATA(PORT145_FSIAISLD_MARK, PORT145_FN3),
-	PINMUX_DATA(VIO_CLK_MARK, PORT146_FN1),
-	PINMUX_DATA(PORT146_KEYIN4_MARK, PORT146_FN2),
-	PINMUX_DATA(IPORT2_MARK, PORT146_FN3),
-	PINMUX_DATA(VIO_FIELD_MARK, PORT147_FN1),
-	PINMUX_DATA(PORT147_KEYIN5_MARK, PORT147_FN2),
-	PINMUX_DATA(VIO_CKO_MARK, PORT148_FN1),
-	PINMUX_DATA(PORT148_KEYIN6_MARK, PORT148_FN2),
-	PINMUX_DATA(A27_MARK, PORT149_FN1),
-	PINMUX_DATA(RDWR_XWE_MARK, PORT149_FN2),
-	PINMUX_DATA(MFG0_IN1_MARK, PORT149_FN3),
-	PINMUX_DATA(MFG0_IN2_MARK, PORT150_FN1),
-	PINMUX_DATA(TS_SPSYNC3_MARK, PORT151_FN1),
-	PINMUX_DATA(MSIOF2_RSCK_MARK, PORT151_FN2),
-	PINMUX_DATA(TS_SDAT3_MARK, PORT152_FN1),
-	PINMUX_DATA(MSIOF2_RSYNC_MARK, PORT152_FN2),
-	PINMUX_DATA(TPU1TO2_MARK, PORT153_FN1),
-	PINMUX_DATA(TS_SDEN3_MARK, PORT153_FN2),
-	PINMUX_DATA(PORT153_MSIOF2_SS1_MARK, PORT153_FN3),
-	PINMUX_DATA(SOUT3_MARK, PORT154_FN1),
-	PINMUX_DATA(SCIFA2_TXD1_MARK, PORT154_FN2),
-	PINMUX_DATA(MSIOF2_MCK0_MARK, PORT154_FN3),
-	PINMUX_DATA(SIN3_MARK, PORT155_FN1),
-	PINMUX_DATA(SCIFA2_RXD1_MARK, PORT155_FN2),
-	PINMUX_DATA(MSIOF2_MCK1_MARK, PORT155_FN3),
-	PINMUX_DATA(XRTS3_MARK, PORT156_FN1),
-	PINMUX_DATA(SCIFA2_RTS1_MARK, PORT156_FN2),
-	PINMUX_DATA(PORT156_MSIOF2_SS2_MARK, PORT156_FN3),
-	PINMUX_DATA(XCTS3_MARK, PORT157_FN1),
-	PINMUX_DATA(SCIFA2_CTS1_MARK, PORT157_FN2),
-	PINMUX_DATA(PORT157_MSIOF2_RXD_MARK, PORT157_FN3),
-
-	/* 55-4 (FN) */
-	PINMUX_DATA(DINT_MARK, PORT158_FN1),
-	PINMUX_DATA(SCIFA2_SCK1_MARK, PORT158_FN2),
-	PINMUX_DATA(TS_SCK3_MARK, PORT158_FN3),
-	PINMUX_DATA(PORT159_SCIFB_SCK_MARK, PORT159_FN1),
-	PINMUX_DATA(PORT159_SCIFA5_SCK_MARK, PORT159_FN2),
-	PINMUX_DATA(NMI_MARK, PORT159_FN3),
-	PINMUX_DATA(PORT160_SCIFB_TXD_MARK, PORT160_FN1),
-	PINMUX_DATA(PORT160_SCIFA5_TXD_MARK, PORT160_FN2),
-	PINMUX_DATA(SOUT0_MARK, PORT160_FN3),
-	PINMUX_DATA(PORT161_SCIFB_CTS_MARK, PORT161_FN1),
-	PINMUX_DATA(PORT161_SCIFA5_CTS_MARK, PORT161_FN2),
-	PINMUX_DATA(XCTS0_MARK, PORT161_FN3),
-	PINMUX_DATA(MFG3_IN2_MARK, PORT161_FN4),
-	PINMUX_DATA(PORT162_SCIFB_RXD_MARK, PORT162_FN1),
-	PINMUX_DATA(PORT162_SCIFA5_RXD_MARK, PORT162_FN2),
-	PINMUX_DATA(SIN0_MARK, PORT162_FN3),
-	PINMUX_DATA(MFG3_IN1_MARK, PORT162_FN4),
-	PINMUX_DATA(PORT163_SCIFB_RTS_MARK, PORT163_FN1),
-	PINMUX_DATA(PORT163_SCIFA5_RTS_MARK, PORT163_FN2),
-	PINMUX_DATA(XRTS0_MARK, PORT163_FN3),
-	PINMUX_DATA(MFG3_OUT1_MARK, PORT163_FN4),
-	PINMUX_DATA(TPU3TO0_MARK, PORT163_FN5),
-	PINMUX_DATA(LCDD0_MARK, PORT192_FN1),
-	PINMUX_DATA(PORT192_KEYOUT0_MARK, PORT192_FN2),
-	PINMUX_DATA(EXT_CKI_MARK, PORT192_FN3),
-	PINMUX_DATA(LCDD1_MARK, PORT193_FN1),
-	PINMUX_DATA(PORT193_KEYOUT1_MARK, PORT193_FN2),
-	PINMUX_DATA(PORT193_SCIFA5_CTS_MARK, PORT193_FN3),
-	PINMUX_DATA(BBIF2_TSYNC1_MARK, PORT193_FN4),
-	PINMUX_DATA(LCDD2_MARK, PORT194_FN1),
-	PINMUX_DATA(PORT194_KEYOUT2_MARK, PORT194_FN2),
-	PINMUX_DATA(PORT194_SCIFA5_RTS_MARK, PORT194_FN3),
-	PINMUX_DATA(BBIF2_TSCK1_MARK, PORT194_FN4),
-	PINMUX_DATA(LCDD3_MARK, PORT195_FN1),
-	PINMUX_DATA(PORT195_KEYOUT3_MARK, PORT195_FN2),
-	PINMUX_DATA(PORT195_SCIFA5_RXD_MARK, PORT195_FN3),
-	PINMUX_DATA(BBIF2_TXD1_MARK, PORT195_FN4),
-	PINMUX_DATA(LCDD4_MARK, PORT196_FN1),
-	PINMUX_DATA(PORT196_KEYOUT4_MARK, PORT196_FN2),
-	PINMUX_DATA(PORT196_SCIFA5_TXD_MARK, PORT196_FN3),
-	PINMUX_DATA(LCDD5_MARK, PORT197_FN1),
-	PINMUX_DATA(PORT197_KEYOUT5_MARK, PORT197_FN2),
-	PINMUX_DATA(PORT197_SCIFA5_SCK_MARK, PORT197_FN3),
-	PINMUX_DATA(MFG2_OUT2_MARK, PORT197_FN4),
-	PINMUX_DATA(LCDD6_MARK, PORT198_FN1),
-	PINMUX_DATA(LCDD7_MARK, PORT199_FN1),
-	PINMUX_DATA(TPU4TO1_MARK, PORT199_FN2),
-	PINMUX_DATA(MFG4_OUT2_MARK, PORT199_FN3),
-	PINMUX_DATA(LCDD8_MARK, PORT200_FN1),
-	PINMUX_DATA(PORT200_KEYIN0_MARK, PORT200_FN2),
-	PINMUX_DATA(VIO_DR0_MARK, PORT200_FN3),
-	PINMUX_DATA(D16_MARK, PORT200_FN4),
-	PINMUX_DATA(LCDD9_MARK, PORT201_FN1),
-	PINMUX_DATA(PORT201_KEYIN1_MARK, PORT201_FN2),
-	PINMUX_DATA(VIO_DR1_MARK, PORT201_FN3),
-	PINMUX_DATA(D17_MARK, PORT201_FN4),
-	PINMUX_DATA(LCDD10_MARK, PORT202_FN1),
-	PINMUX_DATA(PORT202_KEYIN2_MARK, PORT202_FN2),
-	PINMUX_DATA(VIO_DR2_MARK, PORT202_FN3),
-	PINMUX_DATA(D18_MARK, PORT202_FN4),
-	PINMUX_DATA(LCDD11_MARK, PORT203_FN1),
-	PINMUX_DATA(PORT203_KEYIN3_MARK, PORT203_FN2),
-	PINMUX_DATA(VIO_DR3_MARK, PORT203_FN3),
-	PINMUX_DATA(D19_MARK, PORT203_FN4),
-	PINMUX_DATA(LCDD12_MARK, PORT204_FN1),
-	PINMUX_DATA(PORT204_KEYIN4_MARK, PORT204_FN2),
-	PINMUX_DATA(VIO_DR4_MARK, PORT204_FN3),
-	PINMUX_DATA(D20_MARK, PORT204_FN4),
-	PINMUX_DATA(LCDD13_MARK, PORT205_FN1),
-	PINMUX_DATA(PORT205_KEYIN5_MARK, PORT205_FN2),
-	PINMUX_DATA(VIO_DR5_MARK, PORT205_FN3),
-	PINMUX_DATA(D21_MARK, PORT205_FN4),
-	PINMUX_DATA(LCDD14_MARK, PORT206_FN1),
-	PINMUX_DATA(PORT206_KEYIN6_MARK, PORT206_FN2),
-	PINMUX_DATA(VIO_DR6_MARK, PORT206_FN3),
-	PINMUX_DATA(D22_MARK, PORT206_FN4),
-	PINMUX_DATA(LCDD15_MARK, PORT207_FN1),
-	PINMUX_DATA(PORT207_MSIOF0L_SS1_MARK, PORT207_FN2),
-	PINMUX_DATA(PORT207_KEYOUT0_MARK, PORT207_FN3),
-	PINMUX_DATA(VIO_DR7_MARK, PORT207_FN4),
-	PINMUX_DATA(D23_MARK, PORT207_FN5),
-	PINMUX_DATA(LCDD16_MARK, PORT208_FN1),
-	PINMUX_DATA(PORT208_MSIOF0L_SS2_MARK, PORT208_FN2),
-	PINMUX_DATA(PORT208_KEYOUT1_MARK, PORT208_FN3),
-	PINMUX_DATA(VIO_VDR_MARK, PORT208_FN4),
-	PINMUX_DATA(D24_MARK, PORT208_FN5),
-	PINMUX_DATA(LCDD17_MARK, PORT209_FN1),
-	PINMUX_DATA(PORT209_KEYOUT2_MARK, PORT209_FN2),
-	PINMUX_DATA(VIO_HDR_MARK, PORT209_FN3),
-	PINMUX_DATA(D25_MARK, PORT209_FN4),
-	PINMUX_DATA(LCDD18_MARK, PORT210_FN1),
-	PINMUX_DATA(DREQ2_MARK, PORT210_FN2),
-	PINMUX_DATA(PORT210_MSIOF0L_SS1_MARK, PORT210_FN3),
-	PINMUX_DATA(D26_MARK, PORT210_FN4),
-	PINMUX_DATA(LCDD19_MARK, PORT211_FN1),
-	PINMUX_DATA(PORT211_MSIOF0L_SS2_MARK, PORT211_FN2),
-	PINMUX_DATA(D27_MARK, PORT211_FN3),
-	PINMUX_DATA(LCDD20_MARK, PORT212_FN1),
-	PINMUX_DATA(TS_SPSYNC1_MARK, PORT212_FN2),
-	PINMUX_DATA(MSIOF0L_MCK0_MARK, PORT212_FN3),
-	PINMUX_DATA(D28_MARK, PORT212_FN4),
-	PINMUX_DATA(LCDD21_MARK, PORT213_FN1),
-	PINMUX_DATA(TS_SDAT1_MARK, PORT213_FN2),
-	PINMUX_DATA(MSIOF0L_MCK1_MARK, PORT213_FN3),
-	PINMUX_DATA(D29_MARK, PORT213_FN4),
-	PINMUX_DATA(LCDD22_MARK, PORT214_FN1),
-	PINMUX_DATA(TS_SDEN1_MARK, PORT214_FN2),
-	PINMUX_DATA(MSIOF0L_RSCK_MARK, PORT214_FN3),
-	PINMUX_DATA(D30_MARK, PORT214_FN4),
-	PINMUX_DATA(LCDD23_MARK, PORT215_FN1),
-	PINMUX_DATA(TS_SCK1_MARK, PORT215_FN2),
-	PINMUX_DATA(MSIOF0L_RSYNC_MARK, PORT215_FN3),
-	PINMUX_DATA(D31_MARK, PORT215_FN4),
-	PINMUX_DATA(LCDDCK_MARK, PORT216_FN1),
-	PINMUX_DATA(LCDWR_MARK, PORT216_FN2),
-	PINMUX_DATA(PORT216_KEYOUT3_MARK, PORT216_FN3),
-	PINMUX_DATA(VIO_CLKR_MARK, PORT216_FN4),
-	PINMUX_DATA(LCDRD_MARK, PORT217_FN1),
-	PINMUX_DATA(DACK2_MARK, PORT217_FN2),
-	PINMUX_DATA(MSIOF0L_TSYNC_MARK, PORT217_FN3),
-	PINMUX_DATA(LCDHSYN_MARK, PORT218_FN1),
-	PINMUX_DATA(LCDCS_MARK, PORT218_FN2),
-	PINMUX_DATA(LCDCS2_MARK, PORT218_FN3),
-	PINMUX_DATA(DACK3_MARK, PORT218_FN4),
-	PINMUX_DATA(PORT218_VIO_CKOR_MARK, PORT218_FN5),
-	PINMUX_DATA(PORT218_KEYOUT4_MARK, PORT218_FN6),
-	PINMUX_DATA(LCDDISP_MARK, PORT219_FN1),
-	PINMUX_DATA(LCDRS_MARK, PORT219_FN2),
-	PINMUX_DATA(DREQ3_MARK, PORT219_FN3),
-	PINMUX_DATA(MSIOF0L_TSCK_MARK, PORT219_FN4),
-	PINMUX_DATA(LCDVSYN_MARK, PORT220_FN1),
-	PINMUX_DATA(LCDVSYN2_MARK, PORT220_FN2),
-	PINMUX_DATA(PORT220_KEYOUT5_MARK, PORT220_FN3),
-	PINMUX_DATA(LCDLCLK_MARK, PORT221_FN1),
-	PINMUX_DATA(DREQ1_MARK, PORT221_FN2),
-	PINMUX_DATA(PWEN_MARK, PORT221_FN3),
-	PINMUX_DATA(MSIOF0L_RXD_MARK, PORT221_FN4),
-	PINMUX_DATA(LCDDON_MARK, PORT222_FN1),
-	PINMUX_DATA(LCDDON2_MARK, PORT222_FN2),
-	PINMUX_DATA(DACK1_MARK, PORT222_FN3),
-	PINMUX_DATA(OVCN_MARK, PORT222_FN4),
-	PINMUX_DATA(MSIOF0L_TXD_MARK, PORT222_FN5),
-	PINMUX_DATA(SCIFA1_TXD_MARK, PORT225_FN1),
-	PINMUX_DATA(OVCN2_MARK, PORT225_FN2),
-	PINMUX_DATA(EXTLP_MARK, PORT226_FN1),
-	PINMUX_DATA(SCIFA1_SCK_MARK, PORT226_FN2),
-	PINMUX_DATA(USBTERM_MARK, PORT226_FN3),
-	PINMUX_DATA(PORT226_VIO_CKO2_MARK, PORT226_FN4),
-	PINMUX_DATA(SCIFA1_RTS_MARK, PORT227_FN1),
-	PINMUX_DATA(IDIN_MARK, PORT227_FN2),
-	PINMUX_DATA(SCIFA1_RXD_MARK, PORT228_FN1),
-	PINMUX_DATA(SCIFA1_CTS_MARK, PORT229_FN1),
-	PINMUX_DATA(MFG1_IN1_MARK, PORT229_FN2),
-	PINMUX_DATA(MSIOF1_TXD_MARK, PORT230_FN1),
-	PINMUX_DATA(SCIFA2_TXD2_MARK, PORT230_FN2),
-	PINMUX_DATA(PORT230_FSIAOMC_MARK, PORT230_FN3),
-	PINMUX_DATA(MSIOF1_TSYNC_MARK, PORT231_FN1),
-	PINMUX_DATA(SCIFA2_CTS2_MARK, PORT231_FN2),
-	PINMUX_DATA(PORT231_FSIAOLR_MARK, PORT231_FN3),
-	PINMUX_DATA(MSIOF1_TSCK_MARK, PORT232_FN1),
-	PINMUX_DATA(SCIFA2_SCK2_MARK, PORT232_FN2),
-	PINMUX_DATA(PORT232_FSIAOBT_MARK, PORT232_FN3),
-	PINMUX_DATA(MSIOF1_RXD_MARK, PORT233_FN1),
-	PINMUX_DATA(SCIFA2_RXD2_MARK, PORT233_FN2),
-	PINMUX_DATA(GPS_VCOTRIG_MARK, PORT233_FN3),
-	PINMUX_DATA(PORT233_FSIACK_MARK, PORT233_FN4),
-	PINMUX_DATA(MSIOF1_RSCK_MARK, PORT234_FN1),
-	PINMUX_DATA(SCIFA2_RTS2_MARK, PORT234_FN2),
-	PINMUX_DATA(PORT234_FSIAOSLD_MARK, PORT234_FN3),
-	PINMUX_DATA(MSIOF1_RSYNC_MARK, PORT235_FN1),
-	PINMUX_DATA(OPORT0_MARK, PORT235_FN2),
-	PINMUX_DATA(MFG1_IN2_MARK, PORT235_FN3),
-	PINMUX_DATA(PORT235_FSIAILR_MARK, PORT235_FN4),
-	PINMUX_DATA(MSIOF1_MCK0_MARK, PORT236_FN1),
-	PINMUX_DATA(I2C_SDA2_MARK, PORT236_FN2),
-	PINMUX_DATA(PORT236_FSIAIBT_MARK, PORT236_FN3),
-	PINMUX_DATA(MSIOF1_MCK1_MARK, PORT237_FN1),
-	PINMUX_DATA(I2C_SCL2_MARK, PORT237_FN2),
-	PINMUX_DATA(PORT237_FSIAISLD_MARK, PORT237_FN3),
-	PINMUX_DATA(MSIOF1_SS1_MARK, PORT238_FN1),
-	PINMUX_DATA(EDBGREQ3_MARK, PORT238_FN2),
-
-	/* 55-5 (FN) */
-	PINMUX_DATA(MSIOF1_SS2_MARK, PORT239_FN1),
-	PINMUX_DATA(SCIFA6_TXD_MARK, PORT240_FN1),
-	PINMUX_DATA(PORT241_IRDA_OUT_MARK, PORT241_FN1),
-	PINMUX_DATA(PORT241_IROUT_MARK, PORT241_FN2),
-	PINMUX_DATA(MFG4_OUT1_MARK, PORT241_FN3),
-	PINMUX_DATA(TPU4TO0_MARK, PORT241_FN4),
-	PINMUX_DATA(PORT242_IRDA_IN_MARK, PORT242_FN1),
-	PINMUX_DATA(MFG4_IN2_MARK, PORT242_FN2),
-	PINMUX_DATA(PORT243_IRDA_FIRSEL_MARK, PORT243_FN1),
-	PINMUX_DATA(PORT243_VIO_CKO2_MARK, PORT243_FN2),
-	PINMUX_DATA(PORT244_SCIFA5_CTS_MARK, PORT244_FN1),
-	PINMUX_DATA(MFG2_IN1_MARK, PORT244_FN2),
-	PINMUX_DATA(PORT244_SCIFB_CTS_MARK, PORT244_FN3),
-	PINMUX_DATA(PORT245_SCIFA5_RTS_MARK, PORT245_FN1),
-	PINMUX_DATA(MFG2_IN2_MARK, PORT245_FN2),
-	PINMUX_DATA(PORT245_SCIFB_RTS_MARK, PORT245_FN3),
-	PINMUX_DATA(PORT246_SCIFA5_RXD_MARK, PORT246_FN1),
-	PINMUX_DATA(MFG1_OUT1_MARK, PORT246_FN2),
-	PINMUX_DATA(PORT246_SCIFB_RXD_MARK, PORT246_FN3),
-	PINMUX_DATA(TPU1TO0_MARK, PORT246_FN4),
-	PINMUX_DATA(PORT247_SCIFA5_TXD_MARK, PORT247_FN1),
-	PINMUX_DATA(MFG3_OUT2_MARK, PORT247_FN2),
-	PINMUX_DATA(PORT247_SCIFB_TXD_MARK, PORT247_FN3),
-	PINMUX_DATA(TPU3TO1_MARK, PORT247_FN4),
-	PINMUX_DATA(PORT248_SCIFA5_SCK_MARK, PORT248_FN1),
-	PINMUX_DATA(MFG2_OUT1_MARK, PORT248_FN2),
-	PINMUX_DATA(PORT248_SCIFB_SCK_MARK, PORT248_FN3),
-	PINMUX_DATA(TPU2TO0_MARK, PORT248_FN4),
-	PINMUX_DATA(PORT249_IROUT_MARK, PORT249_FN1),
-	PINMUX_DATA(MFG4_IN1_MARK, PORT249_FN2),
-	PINMUX_DATA(SDHICLK0_MARK, PORT250_FN1),
-	PINMUX_DATA(TCK2_SWCLK_MC0_MARK, PORT250_FN2),
-	PINMUX_DATA(SDHICD0_MARK, PORT251_FN1),
-	PINMUX_DATA(SDHID0_0_MARK, PORT252_FN1),
-	PINMUX_DATA(TMS2_SWDIO_MC0_MARK, PORT252_FN2),
-	PINMUX_DATA(SDHID0_1_MARK, PORT253_FN1),
-	PINMUX_DATA(TDO2_SWO0_MC0_MARK, PORT253_FN2),
-	PINMUX_DATA(SDHID0_2_MARK, PORT254_FN1),
-	PINMUX_DATA(TDI2_MARK, PORT254_FN2),
-	PINMUX_DATA(SDHID0_3_MARK, PORT255_FN1),
-	PINMUX_DATA(RTCK2_SWO1_MC0_MARK, PORT255_FN2),
-	PINMUX_DATA(SDHICMD0_MARK, PORT256_FN1),
-	PINMUX_DATA(TRST2_MARK, PORT256_FN2),
-	PINMUX_DATA(SDHIWP0_MARK, PORT257_FN1),
-	PINMUX_DATA(EDBGREQ2_MARK, PORT257_FN2),
-	PINMUX_DATA(SDHICLK1_MARK, PORT258_FN1),
-	PINMUX_DATA(TCK3_SWCLK_MC1_MARK, PORT258_FN2),
-	PINMUX_DATA(SDHID1_0_MARK, PORT259_FN1),
-	PINMUX_DATA(M11_SLCD_SO2_MARK, PORT259_FN2),
-	PINMUX_DATA(TS_SPSYNC2_MARK, PORT259_FN3),
-	PINMUX_DATA(TMS3_SWDIO_MC1_MARK, PORT259_FN4),
-	PINMUX_DATA(SDHID1_1_MARK, PORT260_FN1),
-	PINMUX_DATA(M9_SLCD_A02_MARK, PORT260_FN2),
-	PINMUX_DATA(TS_SDAT2_MARK, PORT260_FN3),
-	PINMUX_DATA(TDO3_SWO0_MC1_MARK, PORT260_FN4),
-	PINMUX_DATA(SDHID1_2_MARK, PORT261_FN1),
-	PINMUX_DATA(M10_SLCD_CK2_MARK, PORT261_FN2),
-	PINMUX_DATA(TS_SDEN2_MARK, PORT261_FN3),
-	PINMUX_DATA(TDI3_MARK, PORT261_FN4),
-	PINMUX_DATA(SDHID1_3_MARK, PORT262_FN1),
-	PINMUX_DATA(M12_SLCD_CE2_MARK, PORT262_FN2),
-	PINMUX_DATA(TS_SCK2_MARK, PORT262_FN3),
-	PINMUX_DATA(RTCK3_SWO1_MC1_MARK, PORT262_FN4),
-	PINMUX_DATA(SDHICMD1_MARK, PORT263_FN1),
-	PINMUX_DATA(TRST3_MARK, PORT263_FN2),
-	PINMUX_DATA(RESETOUTS_MARK, PORT264_FN1),
-};
-
-static struct pinmux_gpio pinmux_gpios[] = {
-	/* 55-1 -> 55-5 (GPIO) */
-	GPIO_PORT_ALL(),
-
-	/* Special Pull-up / Pull-down Functions */
-	GPIO_FN(PORT66_KEYIN0_PU), GPIO_FN(PORT67_KEYIN1_PU),
-	GPIO_FN(PORT68_KEYIN2_PU), GPIO_FN(PORT69_KEYIN3_PU),
-	GPIO_FN(PORT70_KEYIN4_PU), GPIO_FN(PORT71_KEYIN5_PU),
-	GPIO_FN(PORT72_KEYIN6_PU),
-
-	/* 55-1 (FN) */
-	GPIO_FN(VBUS_0),
-	GPIO_FN(CPORT0),
-	GPIO_FN(CPORT1),
-	GPIO_FN(CPORT2),
-	GPIO_FN(CPORT3),
-	GPIO_FN(CPORT4),
-	GPIO_FN(CPORT5),
-	GPIO_FN(CPORT6),
-	GPIO_FN(CPORT7),
-	GPIO_FN(CPORT8),
-	GPIO_FN(CPORT9),
-	GPIO_FN(CPORT10),
-	GPIO_FN(CPORT11), GPIO_FN(SIN2),
-	GPIO_FN(CPORT12), GPIO_FN(XCTS2),
-	GPIO_FN(CPORT13), GPIO_FN(RFSPO4),
-	GPIO_FN(CPORT14), GPIO_FN(RFSPO5),
-	GPIO_FN(CPORT15), GPIO_FN(SCIFA0_SCK), GPIO_FN(GPS_AGC2),
-	GPIO_FN(CPORT16), GPIO_FN(SCIFA0_TXD), GPIO_FN(GPS_AGC3),
-	GPIO_FN(CPORT17_IC_OE), GPIO_FN(SOUT2),
-	GPIO_FN(CPORT18), GPIO_FN(XRTS2), GPIO_FN(PORT19_VIO_CKO2),
-	GPIO_FN(CPORT19_MPORT1),
-	GPIO_FN(CPORT20), GPIO_FN(RFSPO6),
-	GPIO_FN(CPORT21), GPIO_FN(STATUS0),
-	GPIO_FN(CPORT22), GPIO_FN(STATUS1),
-	GPIO_FN(CPORT23), GPIO_FN(STATUS2), GPIO_FN(RFSPO7),
-	GPIO_FN(B_SYNLD1),
-	GPIO_FN(B_SYNLD2), GPIO_FN(SYSENMSK),
-	GPIO_FN(XMAINPS),
-	GPIO_FN(XDIVPS),
-	GPIO_FN(XIDRST),
-	GPIO_FN(IDCLK), GPIO_FN(IC_DP),
-	GPIO_FN(IDIO), GPIO_FN(IC_DM),
-	GPIO_FN(SOUT1), GPIO_FN(SCIFA4_TXD), GPIO_FN(M02_BERDAT),
-	GPIO_FN(SIN1), GPIO_FN(SCIFA4_RXD), GPIO_FN(XWUP),
-	GPIO_FN(XRTS1), GPIO_FN(SCIFA4_RTS), GPIO_FN(M03_BERCLK),
-	GPIO_FN(XCTS1), GPIO_FN(SCIFA4_CTS),
-	GPIO_FN(PCMCLKO),
-	GPIO_FN(SYNC8KO),
-
-	/* 55-2 (FN) */
-	GPIO_FN(DNPCM_A),
-	GPIO_FN(UPPCM_A),
-	GPIO_FN(VACK),
-	GPIO_FN(XTALB1L),
-	GPIO_FN(GPS_AGC1), GPIO_FN(SCIFA0_RTS),
-	GPIO_FN(GPS_AGC4), GPIO_FN(SCIFA0_RXD),
-	GPIO_FN(GPS_PWRDOWN), GPIO_FN(SCIFA0_CTS),
-	GPIO_FN(GPS_IM),
-	GPIO_FN(GPS_IS),
-	GPIO_FN(GPS_QM),
-	GPIO_FN(GPS_QS),
-	GPIO_FN(FMSOCK), GPIO_FN(PORT49_IRDA_OUT), GPIO_FN(PORT49_IROUT),
-	GPIO_FN(FMSOOLR), GPIO_FN(BBIF2_TSYNC2), GPIO_FN(TPU2TO2),
-	GPIO_FN(IPORT3), GPIO_FN(FMSIOLR),
-	GPIO_FN(FMSOOBT), GPIO_FN(BBIF2_TSCK2), GPIO_FN(TPU2TO3),
-	GPIO_FN(OPORT1), GPIO_FN(FMSIOBT),
-	GPIO_FN(FMSOSLD), GPIO_FN(BBIF2_TXD2), GPIO_FN(OPORT2),
-	GPIO_FN(FMSOILR), GPIO_FN(PORT53_IRDA_IN), GPIO_FN(TPU3TO3),
-	GPIO_FN(OPORT3), GPIO_FN(FMSIILR),
-	GPIO_FN(FMSOIBT), GPIO_FN(PORT54_IRDA_FIRSEL), GPIO_FN(TPU3TO2),
-	GPIO_FN(FMSIIBT),
-	GPIO_FN(FMSISLD), GPIO_FN(MFG0_OUT1), GPIO_FN(TPU0TO0),
-	GPIO_FN(A0_EA0), GPIO_FN(BS),
-	GPIO_FN(A12_EA12), GPIO_FN(PORT58_VIO_CKOR), GPIO_FN(TPU4TO2),
-	GPIO_FN(A13_EA13), GPIO_FN(PORT59_IROUT), GPIO_FN(MFG0_OUT2),
-	GPIO_FN(TPU0TO1),
-	GPIO_FN(A14_EA14), GPIO_FN(PORT60_KEYOUT5),
-	GPIO_FN(A15_EA15), GPIO_FN(PORT61_KEYOUT4),
-	GPIO_FN(A16_EA16), GPIO_FN(PORT62_KEYOUT3), GPIO_FN(MSIOF0_SS1),
-	GPIO_FN(A17_EA17), GPIO_FN(PORT63_KEYOUT2), GPIO_FN(MSIOF0_TSYNC),
-	GPIO_FN(A18_EA18), GPIO_FN(PORT64_KEYOUT1), GPIO_FN(MSIOF0_TSCK),
-	GPIO_FN(A19_EA19), GPIO_FN(PORT65_KEYOUT0), GPIO_FN(MSIOF0_TXD),
-	GPIO_FN(A20_EA20), GPIO_FN(PORT66_KEYIN0), GPIO_FN(MSIOF0_RSCK),
-	GPIO_FN(A21_EA21), GPIO_FN(PORT67_KEYIN1), GPIO_FN(MSIOF0_RSYNC),
-	GPIO_FN(A22_EA22), GPIO_FN(PORT68_KEYIN2), GPIO_FN(MSIOF0_MCK0),
-	GPIO_FN(A23_EA23), GPIO_FN(PORT69_KEYIN3), GPIO_FN(MSIOF0_MCK1),
-	GPIO_FN(A24_EA24), GPIO_FN(PORT70_KEYIN4), GPIO_FN(MSIOF0_RXD),
-	GPIO_FN(A25_EA25), GPIO_FN(PORT71_KEYIN5), GPIO_FN(MSIOF0_SS2),
-	GPIO_FN(A26), GPIO_FN(PORT72_KEYIN6),
-	GPIO_FN(D0_ED0_NAF0),
-	GPIO_FN(D1_ED1_NAF1),
-	GPIO_FN(D2_ED2_NAF2),
-	GPIO_FN(D3_ED3_NAF3),
-	GPIO_FN(D4_ED4_NAF4),
-	GPIO_FN(D5_ED5_NAF5),
-	GPIO_FN(D6_ED6_NAF6),
-	GPIO_FN(D7_ED7_NAF7),
-	GPIO_FN(D8_ED8_NAF8),
-	GPIO_FN(D9_ED9_NAF9),
-	GPIO_FN(D10_ED10_NAF10),
-	GPIO_FN(D11_ED11_NAF11),
-	GPIO_FN(D12_ED12_NAF12),
-	GPIO_FN(D13_ED13_NAF13),
-	GPIO_FN(D14_ED14_NAF14),
-	GPIO_FN(D15_ED15_NAF15),
-	GPIO_FN(CS4),
-	GPIO_FN(CS5A), GPIO_FN(FMSICK),
-
-	/* 55-3 (FN) */
-	GPIO_FN(CS5B), GPIO_FN(FCE1),
-	GPIO_FN(CS6B), GPIO_FN(XCS2), GPIO_FN(CS6A), GPIO_FN(DACK0),
-	GPIO_FN(FCE0),
-	GPIO_FN(WAIT), GPIO_FN(DREQ0),
-	GPIO_FN(RD_XRD),
-	GPIO_FN(WE0_XWR0_FWE),
-	GPIO_FN(WE1_XWR1),
-	GPIO_FN(FRB),
-	GPIO_FN(CKO),
-	GPIO_FN(NBRSTOUT),
-	GPIO_FN(NBRST),
-	GPIO_FN(GPS_EPPSIN),
-	GPIO_FN(LATCHPULSE),
-	GPIO_FN(LTESIGNAL),
-	GPIO_FN(LEGACYSTATE),
-	GPIO_FN(TCKON),
-	GPIO_FN(VIO_VD), GPIO_FN(PORT128_KEYOUT0), GPIO_FN(IPORT0),
-	GPIO_FN(VIO_HD), GPIO_FN(PORT129_KEYOUT1), GPIO_FN(IPORT1),
-	GPIO_FN(VIO_D0), GPIO_FN(PORT130_KEYOUT2), GPIO_FN(PORT130_MSIOF2_RXD),
-	GPIO_FN(VIO_D1), GPIO_FN(PORT131_KEYOUT3), GPIO_FN(PORT131_MSIOF2_SS1),
-	GPIO_FN(VIO_D2), GPIO_FN(PORT132_KEYOUT4), GPIO_FN(PORT132_MSIOF2_SS2),
-	GPIO_FN(VIO_D3), GPIO_FN(PORT133_KEYOUT5),
-	GPIO_FN(PORT133_MSIOF2_TSYNC),
-	GPIO_FN(VIO_D4), GPIO_FN(PORT134_KEYIN0), GPIO_FN(PORT134_MSIOF2_TXD),
-	GPIO_FN(VIO_D5), GPIO_FN(PORT135_KEYIN1), GPIO_FN(PORT135_MSIOF2_TSCK),
-	GPIO_FN(VIO_D6), GPIO_FN(PORT136_KEYIN2),
-	GPIO_FN(VIO_D7), GPIO_FN(PORT137_KEYIN3),
-	GPIO_FN(VIO_D8), GPIO_FN(M9_SLCD_A01), GPIO_FN(PORT138_FSIAOMC),
-	GPIO_FN(VIO_D9), GPIO_FN(M10_SLCD_CK1), GPIO_FN(PORT139_FSIAOLR),
-	GPIO_FN(VIO_D10), GPIO_FN(M11_SLCD_SO1), GPIO_FN(TPU0TO2),
-	GPIO_FN(PORT140_FSIAOBT),
-	GPIO_FN(VIO_D11), GPIO_FN(M12_SLCD_CE1), GPIO_FN(TPU0TO3),
-	GPIO_FN(PORT141_FSIAOSLD),
-	GPIO_FN(VIO_D12), GPIO_FN(M13_BSW), GPIO_FN(PORT142_FSIACK),
-	GPIO_FN(VIO_D13), GPIO_FN(M14_GSW), GPIO_FN(PORT143_FSIAILR),
-	GPIO_FN(VIO_D14), GPIO_FN(M15_RSW), GPIO_FN(PORT144_FSIAIBT),
-	GPIO_FN(VIO_D15), GPIO_FN(TPU1TO3), GPIO_FN(PORT145_FSIAISLD),
-	GPIO_FN(VIO_CLK), GPIO_FN(PORT146_KEYIN4), GPIO_FN(IPORT2),
-	GPIO_FN(VIO_FIELD), GPIO_FN(PORT147_KEYIN5),
-	GPIO_FN(VIO_CKO), GPIO_FN(PORT148_KEYIN6),
-	GPIO_FN(A27), GPIO_FN(RDWR_XWE), GPIO_FN(MFG0_IN1),
-	GPIO_FN(MFG0_IN2),
-	GPIO_FN(TS_SPSYNC3), GPIO_FN(MSIOF2_RSCK),
-	GPIO_FN(TS_SDAT3), GPIO_FN(MSIOF2_RSYNC),
-	GPIO_FN(TPU1TO2), GPIO_FN(TS_SDEN3), GPIO_FN(PORT153_MSIOF2_SS1),
-	GPIO_FN(SOUT3), GPIO_FN(SCIFA2_TXD1), GPIO_FN(MSIOF2_MCK0),
-	GPIO_FN(SIN3), GPIO_FN(SCIFA2_RXD1), GPIO_FN(MSIOF2_MCK1),
-	GPIO_FN(XRTS3), GPIO_FN(SCIFA2_RTS1), GPIO_FN(PORT156_MSIOF2_SS2),
-	GPIO_FN(XCTS3), GPIO_FN(SCIFA2_CTS1), GPIO_FN(PORT157_MSIOF2_RXD),
-
-	/* 55-4 (FN) */
-	GPIO_FN(DINT), GPIO_FN(SCIFA2_SCK1), GPIO_FN(TS_SCK3),
-	GPIO_FN(PORT159_SCIFB_SCK), GPIO_FN(PORT159_SCIFA5_SCK), GPIO_FN(NMI),
-	GPIO_FN(PORT160_SCIFB_TXD), GPIO_FN(PORT160_SCIFA5_TXD), GPIO_FN(SOUT0),
-	GPIO_FN(PORT161_SCIFB_CTS), GPIO_FN(PORT161_SCIFA5_CTS), GPIO_FN(XCTS0),
-	GPIO_FN(MFG3_IN2),
-	GPIO_FN(PORT162_SCIFB_RXD), GPIO_FN(PORT162_SCIFA5_RXD), GPIO_FN(SIN0),
-	GPIO_FN(MFG3_IN1),
-	GPIO_FN(PORT163_SCIFB_RTS), GPIO_FN(PORT163_SCIFA5_RTS), GPIO_FN(XRTS0),
-	GPIO_FN(MFG3_OUT1), GPIO_FN(TPU3TO0),
-	GPIO_FN(LCDD0), GPIO_FN(PORT192_KEYOUT0), GPIO_FN(EXT_CKI),
-	GPIO_FN(LCDD1), GPIO_FN(PORT193_KEYOUT1), GPIO_FN(PORT193_SCIFA5_CTS),
-	GPIO_FN(BBIF2_TSYNC1),
-	GPIO_FN(LCDD2), GPIO_FN(PORT194_KEYOUT2), GPIO_FN(PORT194_SCIFA5_RTS),
-	GPIO_FN(BBIF2_TSCK1),
-	GPIO_FN(LCDD3), GPIO_FN(PORT195_KEYOUT3), GPIO_FN(PORT195_SCIFA5_RXD),
-	GPIO_FN(BBIF2_TXD1),
-	GPIO_FN(LCDD4), GPIO_FN(PORT196_KEYOUT4), GPIO_FN(PORT196_SCIFA5_TXD),
-	GPIO_FN(LCDD5), GPIO_FN(PORT197_KEYOUT5), GPIO_FN(PORT197_SCIFA5_SCK),
-	GPIO_FN(MFG2_OUT2),
-	GPIO_FN(LCDD6),
-	GPIO_FN(LCDD7), GPIO_FN(TPU4TO1), GPIO_FN(MFG4_OUT2),
-	GPIO_FN(LCDD8), GPIO_FN(PORT200_KEYIN0), GPIO_FN(VIO_DR0),
-	GPIO_FN(D16),
-	GPIO_FN(LCDD9), GPIO_FN(PORT201_KEYIN1), GPIO_FN(VIO_DR1),
-	GPIO_FN(D17),
-	GPIO_FN(LCDD10), GPIO_FN(PORT202_KEYIN2), GPIO_FN(VIO_DR2),
-	GPIO_FN(D18),
-	GPIO_FN(LCDD11), GPIO_FN(PORT203_KEYIN3), GPIO_FN(VIO_DR3),
-	GPIO_FN(D19),
-	GPIO_FN(LCDD12), GPIO_FN(PORT204_KEYIN4), GPIO_FN(VIO_DR4),
-	GPIO_FN(D20),
-	GPIO_FN(LCDD13), GPIO_FN(PORT205_KEYIN5), GPIO_FN(VIO_DR5),
-	GPIO_FN(D21),
-	GPIO_FN(LCDD14), GPIO_FN(PORT206_KEYIN6), GPIO_FN(VIO_DR6),
-	GPIO_FN(D22),
-	GPIO_FN(LCDD15), GPIO_FN(PORT207_MSIOF0L_SS1), GPIO_FN(PORT207_KEYOUT0),
-	GPIO_FN(VIO_DR7), GPIO_FN(D23),
-	GPIO_FN(LCDD16), GPIO_FN(PORT208_MSIOF0L_SS2), GPIO_FN(PORT208_KEYOUT1),
-	GPIO_FN(VIO_VDR), GPIO_FN(D24),
-	GPIO_FN(LCDD17), GPIO_FN(PORT209_KEYOUT2), GPIO_FN(VIO_HDR),
-	GPIO_FN(D25),
-	GPIO_FN(LCDD18), GPIO_FN(DREQ2), GPIO_FN(PORT210_MSIOF0L_SS1),
-	GPIO_FN(D26),
-	GPIO_FN(LCDD19), GPIO_FN(PORT211_MSIOF0L_SS2), GPIO_FN(D27),
-	GPIO_FN(LCDD20), GPIO_FN(TS_SPSYNC1), GPIO_FN(MSIOF0L_MCK0),
-	GPIO_FN(D28),
-	GPIO_FN(LCDD21), GPIO_FN(TS_SDAT1), GPIO_FN(MSIOF0L_MCK1),
-	GPIO_FN(D29),
-	GPIO_FN(LCDD22), GPIO_FN(TS_SDEN1), GPIO_FN(MSIOF0L_RSCK),
-	GPIO_FN(D30),
-	GPIO_FN(LCDD23), GPIO_FN(TS_SCK1), GPIO_FN(MSIOF0L_RSYNC),
-	GPIO_FN(D31),
-	GPIO_FN(LCDDCK), GPIO_FN(LCDWR), GPIO_FN(PORT216_KEYOUT3),
-	GPIO_FN(VIO_CLKR),
-	GPIO_FN(LCDRD), GPIO_FN(DACK2), GPIO_FN(MSIOF0L_TSYNC),
-	GPIO_FN(LCDHSYN), GPIO_FN(LCDCS), GPIO_FN(LCDCS2), GPIO_FN(DACK3),
-	GPIO_FN(PORT218_VIO_CKOR), GPIO_FN(PORT218_KEYOUT4),
-	GPIO_FN(LCDDISP), GPIO_FN(LCDRS), GPIO_FN(DREQ3), GPIO_FN(MSIOF0L_TSCK),
-	GPIO_FN(LCDVSYN), GPIO_FN(LCDVSYN2), GPIO_FN(PORT220_KEYOUT5),
-	GPIO_FN(LCDLCLK), GPIO_FN(DREQ1), GPIO_FN(PWEN), GPIO_FN(MSIOF0L_RXD),
-	GPIO_FN(LCDDON), GPIO_FN(LCDDON2), GPIO_FN(DACK1), GPIO_FN(OVCN),
-	GPIO_FN(MSIOF0L_TXD),
-	GPIO_FN(SCIFA1_TXD), GPIO_FN(OVCN2),
-	GPIO_FN(EXTLP), GPIO_FN(SCIFA1_SCK), GPIO_FN(USBTERM),
-	GPIO_FN(PORT226_VIO_CKO2),
-	GPIO_FN(SCIFA1_RTS), GPIO_FN(IDIN),
-	GPIO_FN(SCIFA1_RXD),
-	GPIO_FN(SCIFA1_CTS), GPIO_FN(MFG1_IN1),
-	GPIO_FN(MSIOF1_TXD), GPIO_FN(SCIFA2_TXD2), GPIO_FN(PORT230_FSIAOMC),
-	GPIO_FN(MSIOF1_TSYNC), GPIO_FN(SCIFA2_CTS2), GPIO_FN(PORT231_FSIAOLR),
-	GPIO_FN(MSIOF1_TSCK), GPIO_FN(SCIFA2_SCK2), GPIO_FN(PORT232_FSIAOBT),
-	GPIO_FN(MSIOF1_RXD), GPIO_FN(SCIFA2_RXD2), GPIO_FN(GPS_VCOTRIG),
-	GPIO_FN(PORT233_FSIACK),
-	GPIO_FN(MSIOF1_RSCK), GPIO_FN(SCIFA2_RTS2), GPIO_FN(PORT234_FSIAOSLD),
-	GPIO_FN(MSIOF1_RSYNC), GPIO_FN(OPORT0), GPIO_FN(MFG1_IN2),
-	GPIO_FN(PORT235_FSIAILR),
-	GPIO_FN(MSIOF1_MCK0), GPIO_FN(I2C_SDA2), GPIO_FN(PORT236_FSIAIBT),
-	GPIO_FN(MSIOF1_MCK1), GPIO_FN(I2C_SCL2), GPIO_FN(PORT237_FSIAISLD),
-	GPIO_FN(MSIOF1_SS1), GPIO_FN(EDBGREQ3),
-
-	/* 55-5 (FN) */
-	GPIO_FN(MSIOF1_SS2),
-	GPIO_FN(SCIFA6_TXD),
-	GPIO_FN(PORT241_IRDA_OUT), GPIO_FN(PORT241_IROUT), GPIO_FN(MFG4_OUT1),
-	GPIO_FN(TPU4TO0),
-	GPIO_FN(PORT242_IRDA_IN), GPIO_FN(MFG4_IN2),
-	GPIO_FN(PORT243_IRDA_FIRSEL), GPIO_FN(PORT243_VIO_CKO2),
-	GPIO_FN(PORT244_SCIFA5_CTS), GPIO_FN(MFG2_IN1),
-	GPIO_FN(PORT244_SCIFB_CTS),
-	GPIO_FN(PORT245_SCIFA5_RTS), GPIO_FN(MFG2_IN2),
-	GPIO_FN(PORT245_SCIFB_RTS),
-	GPIO_FN(PORT246_SCIFA5_RXD), GPIO_FN(MFG1_OUT1),
-	GPIO_FN(PORT246_SCIFB_RXD), GPIO_FN(TPU1TO0),
-	GPIO_FN(PORT247_SCIFA5_TXD), GPIO_FN(MFG3_OUT2),
-	GPIO_FN(PORT247_SCIFB_TXD), GPIO_FN(TPU3TO1),
-	GPIO_FN(PORT248_SCIFA5_SCK), GPIO_FN(MFG2_OUT1),
-	GPIO_FN(PORT248_SCIFB_SCK), GPIO_FN(TPU2TO0),
-	GPIO_FN(PORT249_IROUT), GPIO_FN(MFG4_IN1),
-	GPIO_FN(SDHICLK0), GPIO_FN(TCK2_SWCLK_MC0),
-	GPIO_FN(SDHICD0),
-	GPIO_FN(SDHID0_0), GPIO_FN(TMS2_SWDIO_MC0),
-	GPIO_FN(SDHID0_1), GPIO_FN(TDO2_SWO0_MC0),
-	GPIO_FN(SDHID0_2), GPIO_FN(TDI2),
-	GPIO_FN(SDHID0_3), GPIO_FN(RTCK2_SWO1_MC0),
-	GPIO_FN(SDHICMD0), GPIO_FN(TRST2),
-	GPIO_FN(SDHIWP0), GPIO_FN(EDBGREQ2),
-	GPIO_FN(SDHICLK1), GPIO_FN(TCK3_SWCLK_MC1),
-	GPIO_FN(SDHID1_0), GPIO_FN(M11_SLCD_SO2), GPIO_FN(TS_SPSYNC2),
-	GPIO_FN(TMS3_SWDIO_MC1),
-	GPIO_FN(SDHID1_1), GPIO_FN(M9_SLCD_A02), GPIO_FN(TS_SDAT2),
-	GPIO_FN(TDO3_SWO0_MC1),
-	GPIO_FN(SDHID1_2), GPIO_FN(M10_SLCD_CK2), GPIO_FN(TS_SDEN2),
-	GPIO_FN(TDI3),
-	GPIO_FN(SDHID1_3), GPIO_FN(M12_SLCD_CE2), GPIO_FN(TS_SCK2),
-	GPIO_FN(RTCK3_SWO1_MC1),
-	GPIO_FN(SDHICMD1), GPIO_FN(TRST3),
-	GPIO_FN(RESETOUTS),
-};
-
-static struct pinmux_cfg_reg pinmux_config_regs[] = {
-	PORTCR(0, 0xe6050000), /* PORT0CR */
-	PORTCR(1, 0xe6050001), /* PORT1CR */
-	PORTCR(2, 0xe6050002), /* PORT2CR */
-	PORTCR(3, 0xe6050003), /* PORT3CR */
-	PORTCR(4, 0xe6050004), /* PORT4CR */
-	PORTCR(5, 0xe6050005), /* PORT5CR */
-	PORTCR(6, 0xe6050006), /* PORT6CR */
-	PORTCR(7, 0xe6050007), /* PORT7CR */
-	PORTCR(8, 0xe6050008), /* PORT8CR */
-	PORTCR(9, 0xe6050009), /* PORT9CR */
-
-	PORTCR(10, 0xe605000a), /* PORT10CR */
-	PORTCR(11, 0xe605000b), /* PORT11CR */
-	PORTCR(12, 0xe605000c), /* PORT12CR */
-	PORTCR(13, 0xe605000d), /* PORT13CR */
-	PORTCR(14, 0xe605000e), /* PORT14CR */
-	PORTCR(15, 0xe605000f), /* PORT15CR */
-	PORTCR(16, 0xe6050010), /* PORT16CR */
-	PORTCR(17, 0xe6050011), /* PORT17CR */
-	PORTCR(18, 0xe6050012), /* PORT18CR */
-	PORTCR(19, 0xe6050013), /* PORT19CR */
-
-	PORTCR(20, 0xe6050014), /* PORT20CR */
-	PORTCR(21, 0xe6050015), /* PORT21CR */
-	PORTCR(22, 0xe6050016), /* PORT22CR */
-	PORTCR(23, 0xe6050017), /* PORT23CR */
-	PORTCR(24, 0xe6050018), /* PORT24CR */
-	PORTCR(25, 0xe6050019), /* PORT25CR */
-	PORTCR(26, 0xe605001a), /* PORT26CR */
-	PORTCR(27, 0xe605001b), /* PORT27CR */
-	PORTCR(28, 0xe605001c), /* PORT28CR */
-	PORTCR(29, 0xe605001d), /* PORT29CR */
-
-	PORTCR(30, 0xe605001e), /* PORT30CR */
-	PORTCR(31, 0xe605001f), /* PORT31CR */
-	PORTCR(32, 0xe6050020), /* PORT32CR */
-	PORTCR(33, 0xe6050021), /* PORT33CR */
-	PORTCR(34, 0xe6050022), /* PORT34CR */
-	PORTCR(35, 0xe6050023), /* PORT35CR */
-	PORTCR(36, 0xe6050024), /* PORT36CR */
-	PORTCR(37, 0xe6050025), /* PORT37CR */
-	PORTCR(38, 0xe6050026), /* PORT38CR */
-	PORTCR(39, 0xe6050027), /* PORT39CR */
-
-	PORTCR(40, 0xe6050028), /* PORT40CR */
-	PORTCR(41, 0xe6050029), /* PORT41CR */
-	PORTCR(42, 0xe605002a), /* PORT42CR */
-	PORTCR(43, 0xe605002b), /* PORT43CR */
-	PORTCR(44, 0xe605002c), /* PORT44CR */
-	PORTCR(45, 0xe605002d), /* PORT45CR */
-	PORTCR(46, 0xe605002e), /* PORT46CR */
-	PORTCR(47, 0xe605002f), /* PORT47CR */
-	PORTCR(48, 0xe6050030), /* PORT48CR */
-	PORTCR(49, 0xe6050031), /* PORT49CR */
-
-	PORTCR(50, 0xe6050032), /* PORT50CR */
-	PORTCR(51, 0xe6050033), /* PORT51CR */
-	PORTCR(52, 0xe6050034), /* PORT52CR */
-	PORTCR(53, 0xe6050035), /* PORT53CR */
-	PORTCR(54, 0xe6050036), /* PORT54CR */
-	PORTCR(55, 0xe6050037), /* PORT55CR */
-	PORTCR(56, 0xe6050038), /* PORT56CR */
-	PORTCR(57, 0xe6050039), /* PORT57CR */
-	PORTCR(58, 0xe605003a), /* PORT58CR */
-	PORTCR(59, 0xe605003b), /* PORT59CR */
-
-	PORTCR(60, 0xe605003c), /* PORT60CR */
-	PORTCR(61, 0xe605003d), /* PORT61CR */
-	PORTCR(62, 0xe605003e), /* PORT62CR */
-	PORTCR(63, 0xe605003f), /* PORT63CR */
-	PORTCR(64, 0xe6050040), /* PORT64CR */
-	PORTCR(65, 0xe6050041), /* PORT65CR */
-	PORTCR(66, 0xe6050042), /* PORT66CR */
-	PORTCR(67, 0xe6050043), /* PORT67CR */
-	PORTCR(68, 0xe6050044), /* PORT68CR */
-	PORTCR(69, 0xe6050045), /* PORT69CR */
-
-	PORTCR(70, 0xe6050046), /* PORT70CR */
-	PORTCR(71, 0xe6050047), /* PORT71CR */
-	PORTCR(72, 0xe6050048), /* PORT72CR */
-	PORTCR(73, 0xe6050049), /* PORT73CR */
-	PORTCR(74, 0xe605004a), /* PORT74CR */
-	PORTCR(75, 0xe605004b), /* PORT75CR */
-	PORTCR(76, 0xe605004c), /* PORT76CR */
-	PORTCR(77, 0xe605004d), /* PORT77CR */
-	PORTCR(78, 0xe605004e), /* PORT78CR */
-	PORTCR(79, 0xe605004f), /* PORT79CR */
-
-	PORTCR(80, 0xe6050050), /* PORT80CR */
-	PORTCR(81, 0xe6050051), /* PORT81CR */
-	PORTCR(82, 0xe6050052), /* PORT82CR */
-	PORTCR(83, 0xe6050053), /* PORT83CR */
-	PORTCR(84, 0xe6050054), /* PORT84CR */
-	PORTCR(85, 0xe6050055), /* PORT85CR */
-	PORTCR(86, 0xe6050056), /* PORT86CR */
-	PORTCR(87, 0xe6050057), /* PORT87CR */
-	PORTCR(88, 0xe6050058), /* PORT88CR */
-	PORTCR(89, 0xe6050059), /* PORT89CR */
-
-	PORTCR(90, 0xe605005a), /* PORT90CR */
-	PORTCR(91, 0xe605005b), /* PORT91CR */
-	PORTCR(92, 0xe605005c), /* PORT92CR */
-	PORTCR(93, 0xe605005d), /* PORT93CR */
-	PORTCR(94, 0xe605005e), /* PORT94CR */
-	PORTCR(95, 0xe605005f), /* PORT95CR */
-	PORTCR(96, 0xe6050060), /* PORT96CR */
-	PORTCR(97, 0xe6050061), /* PORT97CR */
-	PORTCR(98, 0xe6050062), /* PORT98CR */
-	PORTCR(99, 0xe6050063), /* PORT99CR */
-
-	PORTCR(100, 0xe6050064), /* PORT100CR */
-	PORTCR(101, 0xe6050065), /* PORT101CR */
-	PORTCR(102, 0xe6050066), /* PORT102CR */
-	PORTCR(103, 0xe6050067), /* PORT103CR */
-	PORTCR(104, 0xe6050068), /* PORT104CR */
-	PORTCR(105, 0xe6050069), /* PORT105CR */
-	PORTCR(106, 0xe605006a), /* PORT106CR */
-	PORTCR(107, 0xe605006b), /* PORT107CR */
-	PORTCR(108, 0xe605006c), /* PORT108CR */
-	PORTCR(109, 0xe605006d), /* PORT109CR */
-
-	PORTCR(110, 0xe605006e), /* PORT110CR */
-	PORTCR(111, 0xe605006f), /* PORT111CR */
-	PORTCR(112, 0xe6050070), /* PORT112CR */
-	PORTCR(113, 0xe6050071), /* PORT113CR */
-	PORTCR(114, 0xe6050072), /* PORT114CR */
-	PORTCR(115, 0xe6050073), /* PORT115CR */
-	PORTCR(116, 0xe6050074), /* PORT116CR */
-	PORTCR(117, 0xe6050075), /* PORT117CR */
-	PORTCR(118, 0xe6050076), /* PORT118CR */
-
-	PORTCR(128, 0xe6051080), /* PORT128CR */
-	PORTCR(129, 0xe6051081), /* PORT129CR */
-
-	PORTCR(130, 0xe6051082), /* PORT130CR */
-	PORTCR(131, 0xe6051083), /* PORT131CR */
-	PORTCR(132, 0xe6051084), /* PORT132CR */
-	PORTCR(133, 0xe6051085), /* PORT133CR */
-	PORTCR(134, 0xe6051086), /* PORT134CR */
-	PORTCR(135, 0xe6051087), /* PORT135CR */
-	PORTCR(136, 0xe6051088), /* PORT136CR */
-	PORTCR(137, 0xe6051089), /* PORT137CR */
-	PORTCR(138, 0xe605108a), /* PORT138CR */
-	PORTCR(139, 0xe605108b), /* PORT139CR */
-
-	PORTCR(140, 0xe605108c), /* PORT140CR */
-	PORTCR(141, 0xe605108d), /* PORT141CR */
-	PORTCR(142, 0xe605108e), /* PORT142CR */
-	PORTCR(143, 0xe605108f), /* PORT143CR */
-	PORTCR(144, 0xe6051090), /* PORT144CR */
-	PORTCR(145, 0xe6051091), /* PORT145CR */
-	PORTCR(146, 0xe6051092), /* PORT146CR */
-	PORTCR(147, 0xe6051093), /* PORT147CR */
-	PORTCR(148, 0xe6051094), /* PORT148CR */
-	PORTCR(149, 0xe6051095), /* PORT149CR */
-
-	PORTCR(150, 0xe6051096), /* PORT150CR */
-	PORTCR(151, 0xe6051097), /* PORT151CR */
-	PORTCR(152, 0xe6051098), /* PORT152CR */
-	PORTCR(153, 0xe6051099), /* PORT153CR */
-	PORTCR(154, 0xe605109a), /* PORT154CR */
-	PORTCR(155, 0xe605109b), /* PORT155CR */
-	PORTCR(156, 0xe605109c), /* PORT156CR */
-	PORTCR(157, 0xe605109d), /* PORT157CR */
-	PORTCR(158, 0xe605109e), /* PORT158CR */
-	PORTCR(159, 0xe605109f), /* PORT159CR */
-
-	PORTCR(160, 0xe60510a0), /* PORT160CR */
-	PORTCR(161, 0xe60510a1), /* PORT161CR */
-	PORTCR(162, 0xe60510a2), /* PORT162CR */
-	PORTCR(163, 0xe60510a3), /* PORT163CR */
-	PORTCR(164, 0xe60510a4), /* PORT164CR */
-
-	PORTCR(192, 0xe60520c0), /* PORT192CR */
-	PORTCR(193, 0xe60520c1), /* PORT193CR */
-	PORTCR(194, 0xe60520c2), /* PORT194CR */
-	PORTCR(195, 0xe60520c3), /* PORT195CR */
-	PORTCR(196, 0xe60520c4), /* PORT196CR */
-	PORTCR(197, 0xe60520c5), /* PORT197CR */
-	PORTCR(198, 0xe60520c6), /* PORT198CR */
-	PORTCR(199, 0xe60520c7), /* PORT199CR */
-
-	PORTCR(200, 0xe60520c8), /* PORT200CR */
-	PORTCR(201, 0xe60520c9), /* PORT201CR */
-	PORTCR(202, 0xe60520ca), /* PORT202CR */
-	PORTCR(203, 0xe60520cb), /* PORT203CR */
-	PORTCR(204, 0xe60520cc), /* PORT204CR */
-	PORTCR(205, 0xe60520cd), /* PORT205CR */
-	PORTCR(206, 0xe60520ce), /* PORT206CR */
-	PORTCR(207, 0xe60520cf), /* PORT207CR */
-	PORTCR(208, 0xe60520d0), /* PORT208CR */
-	PORTCR(209, 0xe60520d1), /* PORT209CR */
-
-	PORTCR(210, 0xe60520d2), /* PORT210CR */
-	PORTCR(211, 0xe60520d3), /* PORT211CR */
-	PORTCR(212, 0xe60520d4), /* PORT212CR */
-	PORTCR(213, 0xe60520d5), /* PORT213CR */
-	PORTCR(214, 0xe60520d6), /* PORT214CR */
-	PORTCR(215, 0xe60520d7), /* PORT215CR */
-	PORTCR(216, 0xe60520d8), /* PORT216CR */
-	PORTCR(217, 0xe60520d9), /* PORT217CR */
-	PORTCR(218, 0xe60520da), /* PORT218CR */
-	PORTCR(219, 0xe60520db), /* PORT219CR */
-
-	PORTCR(220, 0xe60520dc), /* PORT220CR */
-	PORTCR(221, 0xe60520dd), /* PORT221CR */
-	PORTCR(222, 0xe60520de), /* PORT222CR */
-	PORTCR(223, 0xe60520df), /* PORT223CR */
-	PORTCR(224, 0xe60520e0), /* PORT224CR */
-	PORTCR(225, 0xe60520e1), /* PORT225CR */
-	PORTCR(226, 0xe60520e2), /* PORT226CR */
-	PORTCR(227, 0xe60520e3), /* PORT227CR */
-	PORTCR(228, 0xe60520e4), /* PORT228CR */
-	PORTCR(229, 0xe60520e5), /* PORT229CR */
-
-	PORTCR(230, 0xe60520e6), /* PORT230CR */
-	PORTCR(231, 0xe60520e7), /* PORT231CR */
-	PORTCR(232, 0xe60520e8), /* PORT232CR */
-	PORTCR(233, 0xe60520e9), /* PORT233CR */
-	PORTCR(234, 0xe60520ea), /* PORT234CR */
-	PORTCR(235, 0xe60520eb), /* PORT235CR */
-	PORTCR(236, 0xe60520ec), /* PORT236CR */
-	PORTCR(237, 0xe60520ed), /* PORT237CR */
-	PORTCR(238, 0xe60520ee), /* PORT238CR */
-	PORTCR(239, 0xe60520ef), /* PORT239CR */
-
-	PORTCR(240, 0xe60520f0), /* PORT240CR */
-	PORTCR(241, 0xe60520f1), /* PORT241CR */
-	PORTCR(242, 0xe60520f2), /* PORT242CR */
-	PORTCR(243, 0xe60520f3), /* PORT243CR */
-	PORTCR(244, 0xe60520f4), /* PORT244CR */
-	PORTCR(245, 0xe60520f5), /* PORT245CR */
-	PORTCR(246, 0xe60520f6), /* PORT246CR */
-	PORTCR(247, 0xe60520f7), /* PORT247CR */
-	PORTCR(248, 0xe60520f8), /* PORT248CR */
-	PORTCR(249, 0xe60520f9), /* PORT249CR */
-
-	PORTCR(250, 0xe60520fa), /* PORT250CR */
-	PORTCR(251, 0xe60520fb), /* PORT251CR */
-	PORTCR(252, 0xe60520fc), /* PORT252CR */
-	PORTCR(253, 0xe60520fd), /* PORT253CR */
-	PORTCR(254, 0xe60520fe), /* PORT254CR */
-	PORTCR(255, 0xe60520ff), /* PORT255CR */
-	PORTCR(256, 0xe6052100), /* PORT256CR */
-	PORTCR(257, 0xe6052101), /* PORT257CR */
-	PORTCR(258, 0xe6052102), /* PORT258CR */
-	PORTCR(259, 0xe6052103), /* PORT259CR */
-
-	PORTCR(260, 0xe6052104), /* PORT260CR */
-	PORTCR(261, 0xe6052105), /* PORT261CR */
-	PORTCR(262, 0xe6052106), /* PORT262CR */
-	PORTCR(263, 0xe6052107), /* PORT263CR */
-	PORTCR(264, 0xe6052108), /* PORT264CR */
-
-	{ PINMUX_CFG_REG("MSELBCR", 0xe6058024, 32, 1) {
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			MSELBCR_MSEL17_0, MSELBCR_MSEL17_1,
-			MSELBCR_MSEL16_0, MSELBCR_MSEL16_1,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
-	},
-	{ },
-};
-
-static struct pinmux_data_reg pinmux_data_regs[] = {
-	{ PINMUX_DATA_REG("PORTL031_000DR", 0xe6054000, 32) {
-			PORT31_DATA, PORT30_DATA, PORT29_DATA, PORT28_DATA,
-			PORT27_DATA, PORT26_DATA, PORT25_DATA, PORT24_DATA,
-			PORT23_DATA, PORT22_DATA, PORT21_DATA, PORT20_DATA,
-			PORT19_DATA, PORT18_DATA, PORT17_DATA, PORT16_DATA,
-			PORT15_DATA, PORT14_DATA, PORT13_DATA, PORT12_DATA,
-			PORT11_DATA, PORT10_DATA, PORT9_DATA, PORT8_DATA,
-			PORT7_DATA, PORT6_DATA, PORT5_DATA, PORT4_DATA,
-			PORT3_DATA, PORT2_DATA, PORT1_DATA, PORT0_DATA }
-	},
-	{ PINMUX_DATA_REG("PORTL063_032DR", 0xe6054004, 32) {
-			PORT63_DATA, PORT62_DATA, PORT61_DATA, PORT60_DATA,
-			PORT59_DATA, PORT58_DATA, PORT57_DATA, PORT56_DATA,
-			PORT55_DATA, PORT54_DATA, PORT53_DATA, PORT52_DATA,
-			PORT51_DATA, PORT50_DATA, PORT49_DATA, PORT48_DATA,
-			PORT47_DATA, PORT46_DATA, PORT45_DATA, PORT44_DATA,
-			PORT43_DATA, PORT42_DATA, PORT41_DATA, PORT40_DATA,
-			PORT39_DATA, PORT38_DATA, PORT37_DATA, PORT36_DATA,
-			PORT35_DATA, PORT34_DATA, PORT33_DATA, PORT32_DATA }
-	},
-	{ PINMUX_DATA_REG("PORTL095_064DR", 0xe6054008, 32) {
-			PORT95_DATA, PORT94_DATA, PORT93_DATA, PORT92_DATA,
-			PORT91_DATA, PORT90_DATA, PORT89_DATA, PORT88_DATA,
-			PORT87_DATA, PORT86_DATA, PORT85_DATA, PORT84_DATA,
-			PORT83_DATA, PORT82_DATA, PORT81_DATA, PORT80_DATA,
-			PORT79_DATA, PORT78_DATA, PORT77_DATA, PORT76_DATA,
-			PORT75_DATA, PORT74_DATA, PORT73_DATA, PORT72_DATA,
-			PORT71_DATA, PORT70_DATA, PORT69_DATA, PORT68_DATA,
-			PORT67_DATA, PORT66_DATA, PORT65_DATA, PORT64_DATA }
-	},
-	{ PINMUX_DATA_REG("PORTD127_096DR", 0xe605400C, 32) {
-			0, 0, 0, 0,
-			0, 0, 0, 0,
-			0, PORT118_DATA, PORT117_DATA, PORT116_DATA,
-			PORT115_DATA, PORT114_DATA, PORT113_DATA, PORT112_DATA,
-			PORT111_DATA, PORT110_DATA, PORT109_DATA, PORT108_DATA,
-			PORT107_DATA, PORT106_DATA, PORT105_DATA, PORT104_DATA,
-			PORT103_DATA, PORT102_DATA, PORT101_DATA, PORT100_DATA,
-			PORT99_DATA, PORT98_DATA, PORT97_DATA, PORT96_DATA }
-	},
-	{ PINMUX_DATA_REG("PORTD159_128DR", 0xe6055000, 32) {
-			PORT159_DATA, PORT158_DATA, PORT157_DATA, PORT156_DATA,
-			PORT155_DATA, PORT154_DATA, PORT153_DATA, PORT152_DATA,
-			PORT151_DATA, PORT150_DATA, PORT149_DATA, PORT148_DATA,
-			PORT147_DATA, PORT146_DATA, PORT145_DATA, PORT144_DATA,
-			PORT143_DATA, PORT142_DATA, PORT141_DATA, PORT140_DATA,
-			PORT139_DATA, PORT138_DATA, PORT137_DATA, PORT136_DATA,
-			PORT135_DATA, PORT134_DATA, PORT133_DATA, PORT132_DATA,
-			PORT131_DATA, PORT130_DATA, PORT129_DATA, PORT128_DATA }
-	},
-	{ PINMUX_DATA_REG("PORTR191_160DR", 0xe6055004, 32) {
-			0, 0, 0, 0,
-			0, 0, 0, 0,
-			0, 0, 0, 0,
-			0, 0, 0, 0,
-			0, 0, 0, 0,
-			0, 0, 0, 0,
-			0, 0, 0, PORT164_DATA,
-			PORT163_DATA, PORT162_DATA, PORT161_DATA, PORT160_DATA }
-	},
-	{ PINMUX_DATA_REG("PORTR223_192DR", 0xe6056000, 32) {
-			PORT223_DATA, PORT222_DATA, PORT221_DATA, PORT220_DATA,
-			PORT219_DATA, PORT218_DATA, PORT217_DATA, PORT216_DATA,
-			PORT215_DATA, PORT214_DATA, PORT213_DATA, PORT212_DATA,
-			PORT211_DATA, PORT210_DATA, PORT209_DATA, PORT208_DATA,
-			PORT207_DATA, PORT206_DATA, PORT205_DATA, PORT204_DATA,
-			PORT203_DATA, PORT202_DATA, PORT201_DATA, PORT200_DATA,
-			PORT199_DATA, PORT198_DATA, PORT197_DATA, PORT196_DATA,
-			PORT195_DATA, PORT194_DATA, PORT193_DATA, PORT192_DATA }
-	},
-	{ PINMUX_DATA_REG("PORTU255_224DR", 0xe6056004, 32) {
-			PORT255_DATA, PORT254_DATA, PORT253_DATA, PORT252_DATA,
-			PORT251_DATA, PORT250_DATA, PORT249_DATA, PORT248_DATA,
-			PORT247_DATA, PORT246_DATA, PORT245_DATA, PORT244_DATA,
-			PORT243_DATA, PORT242_DATA, PORT241_DATA, PORT240_DATA,
-			PORT239_DATA, PORT238_DATA, PORT237_DATA, PORT236_DATA,
-			PORT235_DATA, PORT234_DATA, PORT233_DATA, PORT232_DATA,
-			PORT231_DATA, PORT230_DATA, PORT229_DATA, PORT228_DATA,
-			PORT227_DATA, PORT226_DATA, PORT225_DATA, PORT224_DATA }
-	},
-	{ PINMUX_DATA_REG("PORTU287_256DR", 0xe6056008, 32) {
-			0, 0, 0, 0,
-			0, 0, 0, 0,
-			0, 0, 0, 0,
-			0, 0, 0, 0,
-			0, 0, 0, 0,
-			0, 0, 0, PORT264_DATA,
-			PORT263_DATA, PORT262_DATA, PORT261_DATA, PORT260_DATA,
-			PORT259_DATA, PORT258_DATA, PORT257_DATA, PORT256_DATA }
-	},
-	{ },
-};
-
-static struct pinmux_info sh7377_pinmux_info = {
-	.name = "sh7377_pfc",
-	.reserved_id = PINMUX_RESERVED,
-	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
-	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
-	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
-	.input_pd = { PINMUX_INPUT_PULLDOWN_BEGIN, PINMUX_INPUT_PULLDOWN_END },
-	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
-	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
-	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
-
-	.first_gpio = GPIO_PORT0,
-	.last_gpio = GPIO_FN_RESETOUTS,
-
-	.gpios = pinmux_gpios,
-	.cfg_regs = pinmux_config_regs,
-	.data_regs = pinmux_data_regs,
-
-	.gpio_data = pinmux_data,
-	.gpio_data_size = ARRAY_SIZE(pinmux_data),
-};
-
-void sh7377_pinmux_init(void)
-{
-	register_pinmux(&sh7377_pinmux_info);
-}
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
index 11bb1d9..0952224 100644
--- a/arch/arm/mach-shmobile/setup-r8a7740.c
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -66,12 +66,6 @@ static struct map_desc r8a7740_io_desc[] __initdata = {
 void __init r8a7740_map_io(void)
 {
 	iotable_init(r8a7740_io_desc, ARRAY_SIZE(r8a7740_io_desc));
-
-	/*
-	 * DMA memory at 0xff200000 - 0xffdfffff. The default 2MB size isn't
-	 * enough to allocate the frame buffer memory.
-	 */
-	init_consistent_dma_size(12 << 20);
 }
 
 /* SCIFA0 */
@@ -590,6 +584,21 @@ static struct platform_device i2c1_device = {
 	.num_resources	= ARRAY_SIZE(i2c1_resources),
 };
 
+static struct resource pmu_resources[] = {
+	[0] = {
+		.start	= evt2irq(0x19a0),
+		.end	= evt2irq(0x19a0),
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device pmu_device = {
+	.name	= "arm-pmu",
+	.id	= -1,
+	.num_resources = ARRAY_SIZE(pmu_resources),
+	.resource = pmu_resources,
+};
+
 static struct platform_device *r8a7740_late_devices[] __initdata = {
 	&i2c0_device,
 	&i2c1_device,
@@ -597,6 +606,7 @@ static struct platform_device *r8a7740_late_devices[] __initdata = {
 	&dma1_device,
 	&dma2_device,
 	&usb_dma_device,
+	&pmu_device,
 };
 
 /*
@@ -747,7 +757,7 @@ static const char *r8a7740_boards_compat_dt[] __initdata = {
 	NULL,
 };
 
-DT_MACHINE_START(SH7372_DT, "Generic R8A7740 (Flattened Device Tree)")
+DT_MACHINE_START(R8A7740_DT, "Generic R8A7740 (Flattened Device Tree)")
 	.map_io		= r8a7740_map_io,
 	.init_early	= r8a7740_add_early_devices_dt,
 	.init_irq	= r8a7740_init_irq,
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c
index ebbffc2..7a1ad4f 100644
--- a/arch/arm/mach-shmobile/setup-r8a7779.c
+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
@@ -229,6 +229,79 @@ static struct platform_device tmu01_device = {
 	.num_resources	= ARRAY_SIZE(tmu01_resources),
 };
 
+/* I2C */
+static struct resource rcar_i2c0_res[] = {
+	{
+		.start  = 0xffc70000,
+		.end    = 0xffc70fff,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		.start  = gic_spi(79),
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device i2c0_device = {
+	.name		= "i2c-rcar",
+	.id		= 0,
+	.resource	= rcar_i2c0_res,
+	.num_resources	= ARRAY_SIZE(rcar_i2c0_res),
+};
+
+static struct resource rcar_i2c1_res[] = {
+	{
+		.start  = 0xffc71000,
+		.end    = 0xffc71fff,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		.start  = gic_spi(82),
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device i2c1_device = {
+	.name		= "i2c-rcar",
+	.id		= 1,
+	.resource	= rcar_i2c1_res,
+	.num_resources	= ARRAY_SIZE(rcar_i2c1_res),
+};
+
+static struct resource rcar_i2c2_res[] = {
+	{
+		.start  = 0xffc72000,
+		.end    = 0xffc72fff,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		.start  = gic_spi(80),
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device i2c2_device = {
+	.name		= "i2c-rcar",
+	.id		= 2,
+	.resource	= rcar_i2c2_res,
+	.num_resources	= ARRAY_SIZE(rcar_i2c2_res),
+};
+
+static struct resource rcar_i2c3_res[] = {
+	{
+		.start  = 0xffc73000,
+		.end    = 0xffc73fff,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		.start  = gic_spi(81),
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device i2c3_device = {
+	.name		= "i2c-rcar",
+	.id		= 3,
+	.resource	= rcar_i2c3_res,
+	.num_resources	= ARRAY_SIZE(rcar_i2c3_res),
+};
+
 static struct platform_device *r8a7779_early_devices[] __initdata = {
 	&scif0_device,
 	&scif1_device,
@@ -238,6 +311,10 @@ static struct platform_device *r8a7779_early_devices[] __initdata = {
 	&scif5_device,
 	&tmu00_device,
 	&tmu01_device,
+	&i2c0_device,
+	&i2c1_device,
+	&i2c2_device,
+	&i2c3_device,
 };
 
 static struct platform_device *r8a7779_late_devices[] __initdata = {
diff --git a/arch/arm/mach-shmobile/setup-sh7367.c b/arch/arm/mach-shmobile/setup-sh7367.c
deleted file mode 100644
index e647f54..0000000
--- a/arch/arm/mach-shmobile/setup-sh7367.c
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- * sh7367 processor support
- *
- * Copyright (C) 2010  Magnus Damm
- * Copyright (C) 2008  Yoshihiro Shimoda
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/uio_driver.h>
-#include <linux/delay.h>
-#include <linux/input.h>
-#include <linux/io.h>
-#include <linux/serial_sci.h>
-#include <linux/sh_timer.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/time.h>
-
-static struct map_desc sh7367_io_desc[] __initdata = {
-	/* create a 1:1 entity map for 0xe6xxxxxx
-	 * used by CPGA, INTC and PFC.
-	 */
-	{
-		.virtual	= 0xe6000000,
-		.pfn		= __phys_to_pfn(0xe6000000),
-		.length		= 256 << 20,
-		.type		= MT_DEVICE_NONSHARED
-	},
-};
-
-void __init sh7367_map_io(void)
-{
-	iotable_init(sh7367_io_desc, ARRAY_SIZE(sh7367_io_desc));
-}
-
-/* SCIFA0 */
-static struct plat_sci_port scif0_platform_data = {
-	.mapbase	= 0xe6c40000,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
-	.scbrr_algo_id	= SCBRR_ALGO_4,
-	.type		= PORT_SCIFA,
-	.irqs		= { evt2irq(0xc00), evt2irq(0xc00),
-			    evt2irq(0xc00), evt2irq(0xc00) },
-};
-
-static struct platform_device scif0_device = {
-	.name		= "sh-sci",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &scif0_platform_data,
-	},
-};
-
-/* SCIFA1 */
-static struct plat_sci_port scif1_platform_data = {
-	.mapbase	= 0xe6c50000,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
-	.scbrr_algo_id	= SCBRR_ALGO_4,
-	.type		= PORT_SCIFA,
-	.irqs		= { evt2irq(0xc20), evt2irq(0xc20),
-			    evt2irq(0xc20), evt2irq(0xc20) },
-};
-
-static struct platform_device scif1_device = {
-	.name		= "sh-sci",
-	.id		= 1,
-	.dev		= {
-		.platform_data	= &scif1_platform_data,
-	},
-};
-
-/* SCIFA2 */
-static struct plat_sci_port scif2_platform_data = {
-	.mapbase	= 0xe6c60000,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
-	.scbrr_algo_id	= SCBRR_ALGO_4,
-	.type		= PORT_SCIFA,
-	.irqs		= { evt2irq(0xc40), evt2irq(0xc40),
-			    evt2irq(0xc40), evt2irq(0xc40) },
-};
-
-static struct platform_device scif2_device = {
-	.name		= "sh-sci",
-	.id		= 2,
-	.dev		= {
-		.platform_data	= &scif2_platform_data,
-	},
-};
-
-/* SCIFA3 */
-static struct plat_sci_port scif3_platform_data = {
-	.mapbase	= 0xe6c70000,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
-	.scbrr_algo_id	= SCBRR_ALGO_4,
-	.type		= PORT_SCIFA,
-	.irqs		= { evt2irq(0xc60), evt2irq(0xc60),
-			    evt2irq(0xc60), evt2irq(0xc60) },
-};
-
-static struct platform_device scif3_device = {
-	.name		= "sh-sci",
-	.id		= 3,
-	.dev		= {
-		.platform_data	= &scif3_platform_data,
-	},
-};
-
-/* SCIFA4 */
-static struct plat_sci_port scif4_platform_data = {
-	.mapbase	= 0xe6c80000,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
-	.scbrr_algo_id	= SCBRR_ALGO_4,
-	.type		= PORT_SCIFA,
-	.irqs		= { evt2irq(0xd20), evt2irq(0xd20),
-			    evt2irq(0xd20), evt2irq(0xd20) },
-};
-
-static struct platform_device scif4_device = {
-	.name		= "sh-sci",
-	.id		= 4,
-	.dev		= {
-		.platform_data	= &scif4_platform_data,
-	},
-};
-
-/* SCIFA5 */
-static struct plat_sci_port scif5_platform_data = {
-	.mapbase	= 0xe6cb0000,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
-	.scbrr_algo_id	= SCBRR_ALGO_4,
-	.type		= PORT_SCIFA,
-	.irqs		= { evt2irq(0xd40), evt2irq(0xd40),
-			    evt2irq(0xd40), evt2irq(0xd40) },
-};
-
-static struct platform_device scif5_device = {
-	.name		= "sh-sci",
-	.id		= 5,
-	.dev		= {
-		.platform_data	= &scif5_platform_data,
-	},
-};
-
-/* SCIFB */
-static struct plat_sci_port scif6_platform_data = {
-	.mapbase	= 0xe6c30000,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
-	.scbrr_algo_id	= SCBRR_ALGO_4,
-	.type		= PORT_SCIFB,
-	.irqs		= { evt2irq(0xd60), evt2irq(0xd60),
-			    evt2irq(0xd60), evt2irq(0xd60) },
-};
-
-static struct platform_device scif6_device = {
-	.name		= "sh-sci",
-	.id		= 6,
-	.dev		= {
-		.platform_data	= &scif6_platform_data,
-	},
-};
-
-static struct sh_timer_config cmt10_platform_data = {
-	.name = "CMT10",
-	.channel_offset = 0x10,
-	.timer_bit = 0,
-	.clockevent_rating = 125,
-	.clocksource_rating = 125,
-};
-
-static struct resource cmt10_resources[] = {
-	[0] = {
-		.name	= "CMT10",
-		.start	= 0xe6138010,
-		.end	= 0xe613801b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0xb00), /* CMT1_CMT10 */
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cmt10_device = {
-	.name		= "sh_cmt",
-	.id		= 10,
-	.dev = {
-		.platform_data	= &cmt10_platform_data,
-	},
-	.resource	= cmt10_resources,
-	.num_resources	= ARRAY_SIZE(cmt10_resources),
-};
-
-/* VPU */
-static struct uio_info vpu_platform_data = {
-	.name = "VPU5",
-	.version = "0",
-	.irq = intcs_evt2irq(0x980),
-};
-
-static struct resource vpu_resources[] = {
-	[0] = {
-		.name	= "VPU",
-		.start	= 0xfe900000,
-		.end	= 0xfe902807,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device vpu_device = {
-	.name		= "uio_pdrv_genirq",
-	.id		= 0,
-	.dev = {
-		.platform_data	= &vpu_platform_data,
-	},
-	.resource	= vpu_resources,
-	.num_resources	= ARRAY_SIZE(vpu_resources),
-};
-
-/* VEU0 */
-static struct uio_info veu0_platform_data = {
-	.name = "VEU0",
-	.version = "0",
-	.irq = intcs_evt2irq(0x700),
-};
-
-static struct resource veu0_resources[] = {
-	[0] = {
-		.name	= "VEU0",
-		.start	= 0xfe920000,
-		.end	= 0xfe9200b7,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device veu0_device = {
-	.name		= "uio_pdrv_genirq",
-	.id		= 1,
-	.dev = {
-		.platform_data	= &veu0_platform_data,
-	},
-	.resource	= veu0_resources,
-	.num_resources	= ARRAY_SIZE(veu0_resources),
-};
-
-/* VEU1 */
-static struct uio_info veu1_platform_data = {
-	.name = "VEU1",
-	.version = "0",
-	.irq = intcs_evt2irq(0x720),
-};
-
-static struct resource veu1_resources[] = {
-	[0] = {
-		.name	= "VEU1",
-		.start	= 0xfe924000,
-		.end	= 0xfe9240b7,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device veu1_device = {
-	.name		= "uio_pdrv_genirq",
-	.id		= 2,
-	.dev = {
-		.platform_data	= &veu1_platform_data,
-	},
-	.resource	= veu1_resources,
-	.num_resources	= ARRAY_SIZE(veu1_resources),
-};
-
-/* VEU2 */
-static struct uio_info veu2_platform_data = {
-	.name = "VEU2",
-	.version = "0",
-	.irq = intcs_evt2irq(0x740),
-};
-
-static struct resource veu2_resources[] = {
-	[0] = {
-		.name	= "VEU2",
-		.start	= 0xfe928000,
-		.end	= 0xfe9280b7,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device veu2_device = {
-	.name		= "uio_pdrv_genirq",
-	.id		= 3,
-	.dev = {
-		.platform_data	= &veu2_platform_data,
-	},
-	.resource	= veu2_resources,
-	.num_resources	= ARRAY_SIZE(veu2_resources),
-};
-
-/* VEU3 */
-static struct uio_info veu3_platform_data = {
-	.name = "VEU3",
-	.version = "0",
-	.irq = intcs_evt2irq(0x760),
-};
-
-static struct resource veu3_resources[] = {
-	[0] = {
-		.name	= "VEU3",
-		.start	= 0xfe92c000,
-		.end	= 0xfe92c0b7,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device veu3_device = {
-	.name		= "uio_pdrv_genirq",
-	.id		= 4,
-	.dev = {
-		.platform_data	= &veu3_platform_data,
-	},
-	.resource	= veu3_resources,
-	.num_resources	= ARRAY_SIZE(veu3_resources),
-};
-
-/* VEU2H */
-static struct uio_info veu2h_platform_data = {
-	.name = "VEU2H",
-	.version = "0",
-	.irq = intcs_evt2irq(0x520),
-};
-
-static struct resource veu2h_resources[] = {
-	[0] = {
-		.name	= "VEU2H",
-		.start	= 0xfe93c000,
-		.end	= 0xfe93c27b,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device veu2h_device = {
-	.name		= "uio_pdrv_genirq",
-	.id		= 5,
-	.dev = {
-		.platform_data	= &veu2h_platform_data,
-	},
-	.resource	= veu2h_resources,
-	.num_resources	= ARRAY_SIZE(veu2h_resources),
-};
-
-/* JPU */
-static struct uio_info jpu_platform_data = {
-	.name = "JPU",
-	.version = "0",
-	.irq = intcs_evt2irq(0x560),
-};
-
-static struct resource jpu_resources[] = {
-	[0] = {
-		.name	= "JPU",
-		.start	= 0xfe980000,
-		.end	= 0xfe9902d3,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device jpu_device = {
-	.name		= "uio_pdrv_genirq",
-	.id		= 6,
-	.dev = {
-		.platform_data	= &jpu_platform_data,
-	},
-	.resource	= jpu_resources,
-	.num_resources	= ARRAY_SIZE(jpu_resources),
-};
-
-/* SPU1 */
-static struct uio_info spu1_platform_data = {
-	.name = "SPU1",
-	.version = "0",
-	.irq = evt2irq(0xfc0),
-};
-
-static struct resource spu1_resources[] = {
-	[0] = {
-		.name	= "SPU1",
-		.start	= 0xfe300000,
-		.end	= 0xfe3fffff,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device spu1_device = {
-	.name		= "uio_pdrv_genirq",
-	.id		= 7,
-	.dev = {
-		.platform_data	= &spu1_platform_data,
-	},
-	.resource	= spu1_resources,
-	.num_resources	= ARRAY_SIZE(spu1_resources),
-};
-
-static struct platform_device *sh7367_early_devices[] __initdata = {
-	&scif0_device,
-	&scif1_device,
-	&scif2_device,
-	&scif3_device,
-	&scif4_device,
-	&scif5_device,
-	&scif6_device,
-	&cmt10_device,
-};
-
-static struct platform_device *sh7367_devices[] __initdata = {
-	&vpu_device,
-	&veu0_device,
-	&veu1_device,
-	&veu2_device,
-	&veu3_device,
-	&veu2h_device,
-	&jpu_device,
-	&spu1_device,
-};
-
-void __init sh7367_add_standard_devices(void)
-{
-	platform_add_devices(sh7367_early_devices,
-			     ARRAY_SIZE(sh7367_early_devices));
-
-	platform_add_devices(sh7367_devices,
-			    ARRAY_SIZE(sh7367_devices));
-}
-
-static void __init sh7367_earlytimer_init(void)
-{
-	sh7367_clock_init();
-	shmobile_earlytimer_init();
-}
-
-#define SYMSTPCR2 IOMEM(0xe6158048)
-#define SYMSTPCR2_CMT1 (1 << 29)
-
-void __init sh7367_add_early_devices(void)
-{
-	/* enable clock to CMT1 */
-	__raw_writel(__raw_readl(SYMSTPCR2) & ~SYMSTPCR2_CMT1, SYMSTPCR2);
-
-	early_platform_add_devices(sh7367_early_devices,
-				   ARRAY_SIZE(sh7367_early_devices));
-
-	/* setup early console here as well */
-	shmobile_setup_console();
-
-	/* override timer setup with soc-specific code */
-	shmobile_timer.init = sh7367_earlytimer_init;
-}
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index a07954f..c917882 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -58,12 +58,6 @@ static struct map_desc sh7372_io_desc[] __initdata = {
 void __init sh7372_map_io(void)
 {
 	iotable_init(sh7372_io_desc, ARRAY_SIZE(sh7372_io_desc));
-
-	/*
-	 * DMA memory at 0xff200000 - 0xffdfffff. The default 2MB size isn't
-	 * enough to allocate the frame buffer memory.
-	 */
-	init_consistent_dma_size(12 << 20);
 }
 
 /* SCIFA0 */
@@ -408,6 +402,26 @@ static const struct sh_dmae_slave_config sh7372_dmae_slaves[] = {
 		.chcr		= CHCR_RX(XMIT_SZ_8BIT),
 		.mid_rid	= 0x3e,
 	}, {
+		.slave_id	= SHDMA_SLAVE_FLCTL0_TX,
+		.addr		= 0xe6a30050,
+		.chcr		= CHCR_TX(XMIT_SZ_32BIT),
+		.mid_rid	= 0x83,
+	}, {
+		.slave_id	= SHDMA_SLAVE_FLCTL0_RX,
+		.addr		= 0xe6a30050,
+		.chcr		= CHCR_RX(XMIT_SZ_32BIT),
+		.mid_rid	= 0x83,
+	}, {
+		.slave_id	= SHDMA_SLAVE_FLCTL1_TX,
+		.addr		= 0xe6a30060,
+		.chcr		= CHCR_TX(XMIT_SZ_32BIT),
+		.mid_rid	= 0x87,
+	}, {
+		.slave_id	= SHDMA_SLAVE_FLCTL1_RX,
+		.addr		= 0xe6a30060,
+		.chcr		= CHCR_RX(XMIT_SZ_32BIT),
+		.mid_rid	= 0x87,
+	}, {
 		.slave_id	= SHDMA_SLAVE_SDHI0_TX,
 		.addr		= 0xe6850030,
 		.chcr		= CHCR_TX(XMIT_SZ_16BIT),
diff --git a/arch/arm/mach-shmobile/setup-sh7377.c b/arch/arm/mach-shmobile/setup-sh7377.c
deleted file mode 100644
index edcf98b..0000000
--- a/arch/arm/mach-shmobile/setup-sh7377.c
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
- * sh7377 processor support
- *
- * Copyright (C) 2010  Magnus Damm
- * Copyright (C) 2008  Yoshihiro Shimoda
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/of_platform.h>
-#include <linux/uio_driver.h>
-#include <linux/delay.h>
-#include <linux/input.h>
-#include <linux/io.h>
-#include <linux/serial_sci.h>
-#include <linux/sh_intc.h>
-#include <linux/sh_timer.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <asm/mach/map.h>
-#include <mach/irqs.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-static struct map_desc sh7377_io_desc[] __initdata = {
-	/* create a 1:1 entity map for 0xe6xxxxxx
-	 * used by CPGA, INTC and PFC.
-	 */
-	{
-		.virtual	= 0xe6000000,
-		.pfn		= __phys_to_pfn(0xe6000000),
-		.length		= 256 << 20,
-		.type		= MT_DEVICE_NONSHARED
-	},
-};
-
-void __init sh7377_map_io(void)
-{
-	iotable_init(sh7377_io_desc, ARRAY_SIZE(sh7377_io_desc));
-}
-
-/* SCIFA0 */
-static struct plat_sci_port scif0_platform_data = {
-	.mapbase	= 0xe6c40000,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
-	.scbrr_algo_id	= SCBRR_ALGO_4,
-	.type		= PORT_SCIFA,
-	.irqs		= { evt2irq(0xc00), evt2irq(0xc00),
-			    evt2irq(0xc00), evt2irq(0xc00) },
-};
-
-static struct platform_device scif0_device = {
-	.name		= "sh-sci",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &scif0_platform_data,
-	},
-};
-
-/* SCIFA1 */
-static struct plat_sci_port scif1_platform_data = {
-	.mapbase	= 0xe6c50000,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
-	.scbrr_algo_id	= SCBRR_ALGO_4,
-	.type		= PORT_SCIFA,
-	.irqs		= { evt2irq(0xc20), evt2irq(0xc20),
-			    evt2irq(0xc20), evt2irq(0xc20) },
-};
-
-static struct platform_device scif1_device = {
-	.name		= "sh-sci",
-	.id		= 1,
-	.dev		= {
-		.platform_data	= &scif1_platform_data,
-	},
-};
-
-/* SCIFA2 */
-static struct plat_sci_port scif2_platform_data = {
-	.mapbase	= 0xe6c60000,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
-	.scbrr_algo_id	= SCBRR_ALGO_4,
-	.type		= PORT_SCIFA,
-	.irqs		= { evt2irq(0xc40), evt2irq(0xc40),
-			    evt2irq(0xc40), evt2irq(0xc40) },
-};
-
-static struct platform_device scif2_device = {
-	.name		= "sh-sci",
-	.id		= 2,
-	.dev		= {
-		.platform_data	= &scif2_platform_data,
-	},
-};
-
-/* SCIFA3 */
-static struct plat_sci_port scif3_platform_data = {
-	.mapbase	= 0xe6c70000,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
-	.scbrr_algo_id	= SCBRR_ALGO_4,
-	.type		= PORT_SCIFA,
-	.irqs		= { evt2irq(0xc60), evt2irq(0xc60),
-			    evt2irq(0xc60), evt2irq(0xc60) },
-};
-
-static struct platform_device scif3_device = {
-	.name		= "sh-sci",
-	.id		= 3,
-	.dev		= {
-		.platform_data	= &scif3_platform_data,
-	},
-};
-
-/* SCIFA4 */
-static struct plat_sci_port scif4_platform_data = {
-	.mapbase	= 0xe6c80000,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
-	.scbrr_algo_id	= SCBRR_ALGO_4,
-	.type		= PORT_SCIFA,
-	.irqs		= { evt2irq(0xd20), evt2irq(0xd20),
-			    evt2irq(0xd20), evt2irq(0xd20) },
-};
-
-static struct platform_device scif4_device = {
-	.name		= "sh-sci",
-	.id		= 4,
-	.dev		= {
-		.platform_data	= &scif4_platform_data,
-	},
-};
-
-/* SCIFA5 */
-static struct plat_sci_port scif5_platform_data = {
-	.mapbase	= 0xe6cb0000,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
-	.scbrr_algo_id	= SCBRR_ALGO_4,
-	.type		= PORT_SCIFA,
-	.irqs		= { evt2irq(0xd40), evt2irq(0xd40),
-			    evt2irq(0xd40), evt2irq(0xd40) },
-};
-
-static struct platform_device scif5_device = {
-	.name		= "sh-sci",
-	.id		= 5,
-	.dev		= {
-		.platform_data	= &scif5_platform_data,
-	},
-};
-
-/* SCIFA6 */
-static struct plat_sci_port scif6_platform_data = {
-	.mapbase	= 0xe6cc0000,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
-	.scbrr_algo_id	= SCBRR_ALGO_4,
-	.type		= PORT_SCIFA,
-	.irqs		= { intcs_evt2irq(0x1a80), intcs_evt2irq(0x1a80),
-			    intcs_evt2irq(0x1a80), intcs_evt2irq(0x1a80) },
-};
-
-static struct platform_device scif6_device = {
-	.name		= "sh-sci",
-	.id		= 6,
-	.dev		= {
-		.platform_data	= &scif6_platform_data,
-	},
-};
-
-/* SCIFB */
-static struct plat_sci_port scif7_platform_data = {
-	.mapbase	= 0xe6c30000,
-	.flags		= UPF_BOOT_AUTOCONF,
-	.scscr		= SCSCR_RE | SCSCR_TE,
-	.scbrr_algo_id	= SCBRR_ALGO_4,
-	.type		= PORT_SCIFB,
-	.irqs		= { evt2irq(0xd60), evt2irq(0xd60),
-			    evt2irq(0xd60), evt2irq(0xd60) },
-};
-
-static struct platform_device scif7_device = {
-	.name		= "sh-sci",
-	.id		= 7,
-	.dev		= {
-		.platform_data	= &scif7_platform_data,
-	},
-};
-
-static struct sh_timer_config cmt10_platform_data = {
-	.name = "CMT10",
-	.channel_offset = 0x10,
-	.timer_bit = 0,
-	.clockevent_rating = 125,
-	.clocksource_rating = 125,
-};
-
-static struct resource cmt10_resources[] = {
-	[0] = {
-		.name	= "CMT10",
-		.start	= 0xe6138010,
-		.end	= 0xe613801b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0xb00), /* CMT1_CMT10 */
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cmt10_device = {
-	.name		= "sh_cmt",
-	.id		= 10,
-	.dev = {
-		.platform_data	= &cmt10_platform_data,
-	},
-	.resource	= cmt10_resources,
-	.num_resources	= ARRAY_SIZE(cmt10_resources),
-};
-
-/* VPU */
-static struct uio_info vpu_platform_data = {
-	.name = "VPU5HG",
-	.version = "0",
-	.irq = intcs_evt2irq(0x980),
-};
-
-static struct resource vpu_resources[] = {
-	[0] = {
-		.name	= "VPU",
-		.start	= 0xfe900000,
-		.end	= 0xfe900157,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device vpu_device = {
-	.name		= "uio_pdrv_genirq",
-	.id		= 0,
-	.dev = {
-		.platform_data	= &vpu_platform_data,
-	},
-	.resource	= vpu_resources,
-	.num_resources	= ARRAY_SIZE(vpu_resources),
-};
-
-/* VEU0 */
-static struct uio_info veu0_platform_data = {
-	.name = "VEU0",
-	.version = "0",
-	.irq = intcs_evt2irq(0x700),
-};
-
-static struct resource veu0_resources[] = {
-	[0] = {
-		.name	= "VEU0",
-		.start	= 0xfe920000,
-		.end	= 0xfe9200cb,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device veu0_device = {
-	.name		= "uio_pdrv_genirq",
-	.id		= 1,
-	.dev = {
-		.platform_data	= &veu0_platform_data,
-	},
-	.resource	= veu0_resources,
-	.num_resources	= ARRAY_SIZE(veu0_resources),
-};
-
-/* VEU1 */
-static struct uio_info veu1_platform_data = {
-	.name = "VEU1",
-	.version = "0",
-	.irq = intcs_evt2irq(0x720),
-};
-
-static struct resource veu1_resources[] = {
-	[0] = {
-		.name	= "VEU1",
-		.start	= 0xfe924000,
-		.end	= 0xfe9240cb,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device veu1_device = {
-	.name		= "uio_pdrv_genirq",
-	.id		= 2,
-	.dev = {
-		.platform_data	= &veu1_platform_data,
-	},
-	.resource	= veu1_resources,
-	.num_resources	= ARRAY_SIZE(veu1_resources),
-};
-
-/* VEU2 */
-static struct uio_info veu2_platform_data = {
-	.name = "VEU2",
-	.version = "0",
-	.irq = intcs_evt2irq(0x740),
-};
-
-static struct resource veu2_resources[] = {
-	[0] = {
-		.name	= "VEU2",
-		.start	= 0xfe928000,
-		.end	= 0xfe928307,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device veu2_device = {
-	.name		= "uio_pdrv_genirq",
-	.id		= 3,
-	.dev = {
-		.platform_data	= &veu2_platform_data,
-	},
-	.resource	= veu2_resources,
-	.num_resources	= ARRAY_SIZE(veu2_resources),
-};
-
-/* VEU3 */
-static struct uio_info veu3_platform_data = {
-	.name = "VEU3",
-	.version = "0",
-	.irq = intcs_evt2irq(0x760),
-};
-
-static struct resource veu3_resources[] = {
-	[0] = {
-		.name	= "VEU3",
-		.start	= 0xfe92c000,
-		.end	= 0xfe92c307,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device veu3_device = {
-	.name		= "uio_pdrv_genirq",
-	.id		= 4,
-	.dev = {
-		.platform_data	= &veu3_platform_data,
-	},
-	.resource	= veu3_resources,
-	.num_resources	= ARRAY_SIZE(veu3_resources),
-};
-
-/* JPU */
-static struct uio_info jpu_platform_data = {
-	.name = "JPU",
-	.version = "0",
-	.irq = intcs_evt2irq(0x560),
-};
-
-static struct resource jpu_resources[] = {
-	[0] = {
-		.name	= "JPU",
-		.start	= 0xfe980000,
-		.end	= 0xfe9902d3,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device jpu_device = {
-	.name		= "uio_pdrv_genirq",
-	.id		= 5,
-	.dev = {
-		.platform_data	= &jpu_platform_data,
-	},
-	.resource	= jpu_resources,
-	.num_resources	= ARRAY_SIZE(jpu_resources),
-};
-
-/* SPU2DSP0 */
-static struct uio_info spu0_platform_data = {
-	.name = "SPU2DSP0",
-	.version = "0",
-	.irq = evt2irq(0x1800),
-};
-
-static struct resource spu0_resources[] = {
-	[0] = {
-		.name	= "SPU2DSP0",
-		.start	= 0xfe200000,
-		.end	= 0xfe2fffff,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device spu0_device = {
-	.name		= "uio_pdrv_genirq",
-	.id		= 6,
-	.dev = {
-		.platform_data	= &spu0_platform_data,
-	},
-	.resource	= spu0_resources,
-	.num_resources	= ARRAY_SIZE(spu0_resources),
-};
-
-/* SPU2DSP1 */
-static struct uio_info spu1_platform_data = {
-	.name = "SPU2DSP1",
-	.version = "0",
-	.irq = evt2irq(0x1820),
-};
-
-static struct resource spu1_resources[] = {
-	[0] = {
-		.name	= "SPU2DSP1",
-		.start	= 0xfe300000,
-		.end	= 0xfe3fffff,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device spu1_device = {
-	.name		= "uio_pdrv_genirq",
-	.id		= 7,
-	.dev = {
-		.platform_data	= &spu1_platform_data,
-	},
-	.resource	= spu1_resources,
-	.num_resources	= ARRAY_SIZE(spu1_resources),
-};
-
-static struct platform_device *sh7377_early_devices[] __initdata = {
-	&scif0_device,
-	&scif1_device,
-	&scif2_device,
-	&scif3_device,
-	&scif4_device,
-	&scif5_device,
-	&scif6_device,
-	&scif7_device,
-	&cmt10_device,
-};
-
-static struct platform_device *sh7377_devices[] __initdata = {
-	&vpu_device,
-	&veu0_device,
-	&veu1_device,
-	&veu2_device,
-	&veu3_device,
-	&jpu_device,
-	&spu0_device,
-	&spu1_device,
-};
-
-void __init sh7377_add_standard_devices(void)
-{
-	platform_add_devices(sh7377_early_devices,
-			    ARRAY_SIZE(sh7377_early_devices));
-
-	platform_add_devices(sh7377_devices,
-			    ARRAY_SIZE(sh7377_devices));
-}
-
-static void __init sh7377_earlytimer_init(void)
-{
-	sh7377_clock_init();
-	shmobile_earlytimer_init();
-}
-
-#define SMSTPCR3 IOMEM(0xe615013c)
-#define SMSTPCR3_CMT1 (1 << 29)
-
-void __init sh7377_add_early_devices(void)
-{
-	/* enable clock to CMT1 */
-	__raw_writel(__raw_readl(SMSTPCR3) & ~SMSTPCR3_CMT1, SMSTPCR3);
-
-	early_platform_add_devices(sh7377_early_devices,
-				   ARRAY_SIZE(sh7377_early_devices));
-
-	/* setup early console here as well */
-	shmobile_setup_console();
-
-	/* override timer setup with soc-specific code */
-	shmobile_timer.init = sh7377_earlytimer_init;
-}
-
-#ifdef CONFIG_USE_OF
-
-void __init sh7377_add_early_devices_dt(void)
-{
-	shmobile_setup_delay(600, 1, 3); /* Cortex-A8 @ 600MHz */
-
-	early_platform_add_devices(sh7377_early_devices,
-				   ARRAY_SIZE(sh7377_early_devices));
-
-	/* setup early console here as well */
-	shmobile_setup_console();
-}
-
-static const struct of_dev_auxdata sh7377_auxdata_lookup[] __initconst = {
-	{ }
-};
-
-void __init sh7377_add_standard_devices_dt(void)
-{
-	/* clocks are setup late during boot in the case of DT */
-	sh7377_clock_init();
-
-	platform_add_devices(sh7377_early_devices,
-			    ARRAY_SIZE(sh7377_early_devices));
-
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     sh7377_auxdata_lookup, NULL);
-}
-
-static const char *sh7377_boards_compat_dt[] __initdata = {
-	"renesas,sh7377",
-	NULL,
-};
-
-DT_MACHINE_START(SH7377_DT, "Generic SH7377 (Flattened Device Tree)")
-	.map_io		= sh7377_map_io,
-	.init_early	= sh7377_add_early_devices_dt,
-	.init_irq	= sh7377_init_irq,
-	.handle_irq	= shmobile_handle_irq_intc,
-	.init_machine	= sh7377_add_standard_devices_dt,
-	.timer		= &shmobile_timer,
-	.dt_compat	= sh7377_boards_compat_dt,
-MACHINE_END
-
-#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig
index 803a328..566e804 100644
--- a/arch/arm/mach-socfpga/Kconfig
+++ b/arch/arm/mach-socfpga/Kconfig
@@ -12,5 +12,6 @@ config ARCH_SOCFPGA
 	select GENERIC_CLOCKEVENTS
 	select GPIO_PL061 if GPIOLIB
 	select HAVE_ARM_SCU
+	select HAVE_SMP
 	select SPARSE_IRQ
 	select USE_OF
diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile
index 4fb9324..6dd7a93 100644
--- a/arch/arm/mach-socfpga/Makefile
+++ b/arch/arm/mach-socfpga/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-y					:= socfpga.o
+obj-$(CONFIG_SMP)	+= headsmp.o platsmp.o
diff --git a/arch/arm/mach-socfpga/core.h b/arch/arm/mach-socfpga/core.h
new file mode 100644
index 0000000..9941caa
--- /dev/null
+++ b/arch/arm/mach-socfpga/core.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012 Pavel Machek <pavel@denx.de>
+ * Copyright (C) 2012 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MACH_CORE_H
+#define __MACH_CORE_H
+
+extern void secondary_startup(void);
+extern void __iomem *socfpga_scu_base_addr;
+
+extern void socfpga_init_clocks(void);
+extern void socfpga_sysmgr_init(void);
+
+extern struct smp_operations socfpga_smp_ops;
+extern char secondary_trampoline, secondary_trampoline_end;
+
+#define SOCFPGA_SCU_VIRT_BASE   0xfffec000
+
+#endif
diff --git a/arch/arm/mach-socfpga/headsmp.S b/arch/arm/mach-socfpga/headsmp.S
new file mode 100644
index 0000000..f09b128
--- /dev/null
+++ b/arch/arm/mach-socfpga/headsmp.S
@@ -0,0 +1,25 @@
+/*
+ *  Copyright (c) 2003 ARM Limited
+ *  Copyright (c) u-boot contributors
+ *  Copyright (c) 2012 Pavel Machek <pavel@denx.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/linkage.h>
+#include <linux/init.h>
+
+	__CPUINIT
+	.arch	armv7-a
+
+#define CPU1_START_ADDR 	        0xffd08010
+
+ENTRY(secondary_trampoline)
+	movw	r0, #:lower16:CPU1_START_ADDR
+	movt  r0, #:upper16:CPU1_START_ADDR
+
+	ldr	r1, [r0]
+	bx	r1
+
+ENTRY(secondary_trampoline_end)
diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c
new file mode 100644
index 0000000..68dd1b6
--- /dev/null
+++ b/arch/arm/mach-socfpga/platsmp.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ * Copyright 2012 Pavel Machek <pavel@denx.de>
+ * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
+ * Copyright (C) 2012 Altera 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware/gic.h>
+#include <asm/smp_scu.h>
+#include <asm/smp_plat.h>
+
+#include "core.h"
+
+extern void __iomem *sys_manager_base_addr;
+extern void __iomem *rst_manager_base_addr;
+
+static void __cpuinit socfpga_secondary_init(unsigned int cpu)
+{
+	/*
+	 * if any interrupts are already enabled for the primary
+	 * core (e.g. timer irq), then they will not have been enabled
+	 * for us: do so
+	 */
+	gic_secondary_init(0);
+}
+
+static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
+
+	memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
+
+	__raw_writel(virt_to_phys(secondary_startup), (sys_manager_base_addr+0x10));
+
+	flush_cache_all();
+	smp_wmb();
+	outer_clean_range(0, trampoline_size);
+
+	/* This will release CPU #1 out of reset.*/
+	__raw_writel(0, rst_manager_base_addr + 0x10);
+
+	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 socfpga_smp_init_cpus(void)
+{
+	unsigned int i, ncores;
+
+	ncores = scu_get_core_count(socfpga_scu_base_addr);
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+
+	/* sanity check */
+	if (ncores > num_possible_cpus()) {
+		pr_warn("socfpga: no. of cores (%d) greater than configured"
+			"maximum of %d - clipping\n", ncores, num_possible_cpus());
+		ncores = num_possible_cpus();
+	}
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+
+	set_smp_cross_call(gic_raise_softirq);
+}
+
+static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus)
+{
+	scu_enable(socfpga_scu_base_addr);
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+static void socfpga_cpu_die(unsigned int cpu)
+{
+	cpu_do_idle();
+
+	/* We should have never returned from idle */
+	panic("cpu %d unexpectedly exit from shutdown\n", cpu);
+}
+
+struct smp_operations socfpga_smp_ops __initdata = {
+	.smp_init_cpus		= socfpga_smp_init_cpus,
+	.smp_prepare_cpus	= socfpga_smp_prepare_cpus,
+	.smp_secondary_init	= socfpga_secondary_init,
+	.smp_boot_secondary	= socfpga_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= socfpga_cpu_die,
+#endif
+};
diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c
index f01e1eb..6732924 100644
--- a/arch/arm/mach-socfpga/socfpga.c
+++ b/arch/arm/mach-socfpga/socfpga.c
@@ -15,23 +15,73 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include <linux/dw_apb_timer.h>
+#include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
+#include <asm/mach/map.h>
 
-extern void socfpga_init_clocks(void);
+#include "core.h"
+
+void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
+void __iomem *sys_manager_base_addr;
+void __iomem *rst_manager_base_addr;
+
+static struct map_desc scu_io_desc __initdata = {
+	.virtual	= SOCFPGA_SCU_VIRT_BASE,
+	.pfn		= 0, /* run-time */
+	.length		= SZ_8K,
+	.type		= MT_DEVICE,
+};
+
+static struct map_desc uart_io_desc __initdata = {
+	.virtual	= 0xfec02000,
+	.pfn		= __phys_to_pfn(0xffc02000),
+	.length		= SZ_8K,
+	.type		= MT_DEVICE,
+};
+
+static void __init socfpga_scu_map_io(void)
+{
+	unsigned long base;
+
+	/* Get SCU base */
+	asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+	scu_io_desc.pfn = __phys_to_pfn(base);
+	iotable_init(&scu_io_desc, 1);
+}
+
+static void __init socfpga_map_io(void)
+{
+	socfpga_scu_map_io();
+	iotable_init(&uart_io_desc, 1);
+	early_printk("Early printk initialized\n");
+}
 
 const static struct of_device_id irq_match[] = {
 	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
 	{}
 };
 
+void __init socfpga_sysmgr_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr");
+	sys_manager_base_addr = of_iomap(np, 0);
+
+	np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr");
+	rst_manager_base_addr = of_iomap(np, 0);
+}
+
 static void __init gic_init_irq(void)
 {
 	of_irq_init(irq_match);
+	socfpga_sysmgr_init();
 }
 
 static void socfpga_cyclone5_restart(char mode, const char *cmd)
@@ -53,6 +103,8 @@ static const char *altera_dt_match[] = {
 };
 
 DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA")
+	.smp		= smp_ops(socfpga_smp_ops),
+	.map_io		= socfpga_map_io,
 	.init_irq	= gic_init_irq,
 	.handle_irq     = gic_handle_irq,
 	.timer		= &dw_apb_timer,
diff --git a/arch/arm/mach-spear13xx/include/mach/spear.h b/arch/arm/mach-spear13xx/include/mach/spear.h
index 07d90ac..972a151 100644
--- a/arch/arm/mach-spear13xx/include/mach/spear.h
+++ b/arch/arm/mach-spear13xx/include/mach/spear.h
@@ -43,18 +43,8 @@
 #define VA_L2CC_BASE				IOMEM(UL(0xFB000000))
 
 /* others */
-#define DMAC0_BASE				UL(0xEA800000)
-#define DMAC1_BASE				UL(0xEB000000)
 #define MCIF_CF_BASE				UL(0xB2800000)
 
-/* Devices present in SPEAr1310 */
-#ifdef CONFIG_MACH_SPEAR1310
-#define SPEAR1310_RAS_GRP1_BASE			UL(0xD8000000)
-#define VA_SPEAR1310_RAS_GRP1_BASE		UL(0xFA000000)
-#define SPEAR1310_RAS_BASE			UL(0xD8400000)
-#define VA_SPEAR1310_RAS_BASE			IOMEM(UL(0xFA400000))
-#endif /* CONFIG_MACH_SPEAR1310 */
-
 /* Debug uart for linux, will be used for debug and uncompress messages */
 #define SPEAR_DBG_UART_BASE			UART_BASE
 #define VA_SPEAR_DBG_UART_BASE			VA_UART_BASE
diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c
index 9fbbfc5..f65ad5b 100644
--- a/arch/arm/mach-spear13xx/spear1310.c
+++ b/arch/arm/mach-spear13xx/spear1310.c
@@ -15,6 +15,7 @@
 
 #include <linux/amba/pl022.h>
 #include <linux/of_platform.h>
+#include <linux/pata_arasan_cf_data.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -27,18 +28,25 @@
 #define SPEAR1310_SATA1_BASE			UL(0xB1800000)
 #define SPEAR1310_SATA2_BASE			UL(0xB4000000)
 
+#define SPEAR1310_RAS_GRP1_BASE			UL(0xD8000000)
+#define VA_SPEAR1310_RAS_GRP1_BASE		UL(0xFA000000)
+#define SPEAR1310_RAS_BASE			UL(0xD8400000)
+#define VA_SPEAR1310_RAS_BASE			IOMEM(UL(0xFA400000))
+
+static struct arasan_cf_pdata cf_pdata = {
+	.cf_if_clk = CF_IF_CLK_166M,
+	.quirk = CF_BROKEN_UDMA,
+	.dma_priv = &cf_dma_priv,
+};
+
 /* ssp device registration */
 static struct pl022_ssp_controller ssp1_plat_data = {
-	.bus_id = 0,
 	.enable_dma = 0,
-	.num_chipselect = 3,
 };
 
 /* Add SPEAr1310 auxdata to pass platform data */
 static struct of_dev_auxdata spear1310_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_dma_priv),
-	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
-	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
+	OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_pdata),
 	OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data),
 
 	OF_DEV_AUXDATA("arm,pl022", SPEAR1310_SSP1_BASE, NULL, &ssp1_plat_data),
diff --git a/arch/arm/mach-spear13xx/spear1340.c b/arch/arm/mach-spear13xx/spear1340.c
index 081014f..7301f14 100644
--- a/arch/arm/mach-spear13xx/spear1340.c
+++ b/arch/arm/mach-spear13xx/spear1340.c
@@ -20,7 +20,6 @@
 #include <linux/of_platform.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
-#include <mach/dma.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
 
@@ -78,26 +77,10 @@
 			(SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
 			SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
 
-static struct dw_dma_slave uart1_dma_param[] = {
-	{
-		/* Tx */
-		.cfg_hi = DWC_CFGH_DST_PER(SPEAR1340_DMA_REQ_UART1_TX),
-		.cfg_lo = 0,
-		.src_master = DMA_MASTER_MEMORY,
-		.dst_master = SPEAR1340_DMA_MASTER_UART1,
-	}, {
-		/* Rx */
-		.cfg_hi = DWC_CFGH_SRC_PER(SPEAR1340_DMA_REQ_UART1_RX),
-		.cfg_lo = 0,
-		.src_master = SPEAR1340_DMA_MASTER_UART1,
-		.dst_master = DMA_MASTER_MEMORY,
-	}
-};
-
 static struct amba_pl011_data uart1_data = {
-	.dma_filter = dw_dma_filter,
-	.dma_tx_param = &uart1_dma_param[0],
-	.dma_rx_param = &uart1_dma_param[1],
+	.dma_filter = dw_dma_generic_filter,
+	.dma_tx_param = "uart1_tx",
+	.dma_rx_param = "uart1_rx",
 };
 
 /* SATA device registration */
@@ -158,9 +141,7 @@ static struct ahci_platform_data sata_pdata = {
 
 /* Add SPEAr1340 auxdata to pass platform data */
 static struct of_dev_auxdata spear1340_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_dma_priv),
-	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
-	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
+	OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, "cf"),
 	OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data),
 
 	OF_DEV_AUXDATA("snps,spear-ahci", SPEAR1340_SATA_BASE, NULL,
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 5633d69..e0e5b53 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -22,65 +22,15 @@
 #include <asm/hardware/gic.h>
 #include <asm/mach/map.h>
 #include <asm/smp_twd.h>
-#include <mach/dma.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
 
-/* common dw_dma filter routine to be used by peripherals */
-bool dw_dma_filter(struct dma_chan *chan, void *slave)
-{
-	struct dw_dma_slave *dws = (struct dw_dma_slave *)slave;
-
-	if (chan->device->dev == dws->dma_dev) {
-		chan->private = slave;
-		return true;
-	} else {
-		return false;
-	}
-}
-
 /* ssp device registration */
-static struct dw_dma_slave ssp_dma_param[] = {
-	{
-		/* Tx */
-		.cfg_hi = DWC_CFGH_DST_PER(DMA_REQ_SSP0_TX),
-		.cfg_lo = 0,
-		.src_master = DMA_MASTER_MEMORY,
-		.dst_master = DMA_MASTER_SSP0,
-	}, {
-		/* Rx */
-		.cfg_hi = DWC_CFGH_SRC_PER(DMA_REQ_SSP0_RX),
-		.cfg_lo = 0,
-		.src_master = DMA_MASTER_SSP0,
-		.dst_master = DMA_MASTER_MEMORY,
-	}
-};
-
 struct pl022_ssp_controller pl022_plat_data = {
-	.bus_id = 0,
 	.enable_dma = 1,
-	.dma_filter = dw_dma_filter,
-	.dma_rx_param = &ssp_dma_param[1],
-	.dma_tx_param = &ssp_dma_param[0],
-	.num_chipselect = 3,
-};
-
-/* CF device registration */
-struct dw_dma_slave cf_dma_priv = {
-	.cfg_hi = 0,
-	.cfg_lo = 0,
-	.src_master = 0,
-	.dst_master = 0,
-};
-
-/* dmac device registeration */
-struct dw_dma_platform_data dmac_plat_data = {
-	.nr_channels = 8,
-	.chan_allocation_order = CHAN_ALLOCATION_DESCENDING,
-	.chan_priority = CHAN_PRIORITY_DESCENDING,
-	.block_size = 4095U,
-	.nr_masters = 2,
-	.data_width = { 3, 3, 0, 0 },
+	.dma_filter = dw_dma_generic_filter,
+	.dma_rx_param = "ssp0_rx",
+	.dma_tx_param = "ssp0_tx",
 };
 
 void __init spear13xx_l2x0_init(void)
diff --git a/arch/arm/mach-spear3xx/include/mach/irqs.h b/arch/arm/mach-spear3xx/include/mach/irqs.h
index 803de76..f95e5b2 100644
--- a/arch/arm/mach-spear3xx/include/mach/irqs.h
+++ b/arch/arm/mach-spear3xx/include/mach/irqs.h
@@ -14,14 +14,6 @@
 #ifndef __MACH_IRQS_H
 #define __MACH_IRQS_H
 
-/* FIXME: probe all these from DT */
-#define SPEAR3XX_IRQ_INTRCOMM_RAS_ARM		1
-#define SPEAR3XX_IRQ_GEN_RAS_1			28
-#define SPEAR3XX_IRQ_GEN_RAS_2			29
-#define SPEAR3XX_IRQ_GEN_RAS_3			30
-#define SPEAR3XX_IRQ_VIC_END			32
-#define SPEAR3XX_VIRQ_START			SPEAR3XX_IRQ_VIC_END
-
-#define NR_IRQS			160
+#define NR_IRQS			256
 
 #endif /* __MACH_IRQS_H */
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index 6ec3005..a69cbfd 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -17,102 +17,9 @@
 #include <linux/of_platform.h>
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
-#include <plat/shirq.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
 
-/* Base address of various IPs */
-#define SPEAR300_TELECOM_BASE		UL(0x50000000)
-
-/* Interrupt registers offsets and masks */
-#define SPEAR300_INT_ENB_MASK_REG	0x54
-#define SPEAR300_INT_STS_MASK_REG	0x58
-#define SPEAR300_IT_PERS_S_IRQ_MASK	(1 << 0)
-#define SPEAR300_IT_CHANGE_S_IRQ_MASK	(1 << 1)
-#define SPEAR300_I2S_IRQ_MASK		(1 << 2)
-#define SPEAR300_TDM_IRQ_MASK		(1 << 3)
-#define SPEAR300_CAMERA_L_IRQ_MASK	(1 << 4)
-#define SPEAR300_CAMERA_F_IRQ_MASK	(1 << 5)
-#define SPEAR300_CAMERA_V_IRQ_MASK	(1 << 6)
-#define SPEAR300_KEYBOARD_IRQ_MASK	(1 << 7)
-#define SPEAR300_GPIO1_IRQ_MASK		(1 << 8)
-
-#define SPEAR300_SHIRQ_RAS1_MASK	0x1FF
-
-#define SPEAR300_SOC_CONFIG_BASE	UL(0x99000000)
-
-
-/* SPEAr300 Virtual irq definitions */
-/* IRQs sharing IRQ_GEN_RAS_1 */
-#define SPEAR300_VIRQ_IT_PERS_S			(SPEAR3XX_VIRQ_START + 0)
-#define SPEAR300_VIRQ_IT_CHANGE_S		(SPEAR3XX_VIRQ_START + 1)
-#define SPEAR300_VIRQ_I2S			(SPEAR3XX_VIRQ_START + 2)
-#define SPEAR300_VIRQ_TDM			(SPEAR3XX_VIRQ_START + 3)
-#define SPEAR300_VIRQ_CAMERA_L			(SPEAR3XX_VIRQ_START + 4)
-#define SPEAR300_VIRQ_CAMERA_F			(SPEAR3XX_VIRQ_START + 5)
-#define SPEAR300_VIRQ_CAMERA_V			(SPEAR3XX_VIRQ_START + 6)
-#define SPEAR300_VIRQ_KEYBOARD			(SPEAR3XX_VIRQ_START + 7)
-#define SPEAR300_VIRQ_GPIO1			(SPEAR3XX_VIRQ_START + 8)
-
-/* IRQs sharing IRQ_GEN_RAS_3 */
-#define SPEAR300_IRQ_CLCD			SPEAR3XX_IRQ_GEN_RAS_3
-
-/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
-#define SPEAR300_IRQ_SDHCI			SPEAR3XX_IRQ_INTRCOMM_RAS_ARM
-
-/* spear3xx shared irq */
-static struct shirq_dev_config shirq_ras1_config[] = {
-	{
-		.virq = SPEAR300_VIRQ_IT_PERS_S,
-		.enb_mask = SPEAR300_IT_PERS_S_IRQ_MASK,
-		.status_mask = SPEAR300_IT_PERS_S_IRQ_MASK,
-	}, {
-		.virq = SPEAR300_VIRQ_IT_CHANGE_S,
-		.enb_mask = SPEAR300_IT_CHANGE_S_IRQ_MASK,
-		.status_mask = SPEAR300_IT_CHANGE_S_IRQ_MASK,
-	}, {
-		.virq = SPEAR300_VIRQ_I2S,
-		.enb_mask = SPEAR300_I2S_IRQ_MASK,
-		.status_mask = SPEAR300_I2S_IRQ_MASK,
-	}, {
-		.virq = SPEAR300_VIRQ_TDM,
-		.enb_mask = SPEAR300_TDM_IRQ_MASK,
-		.status_mask = SPEAR300_TDM_IRQ_MASK,
-	}, {
-		.virq = SPEAR300_VIRQ_CAMERA_L,
-		.enb_mask = SPEAR300_CAMERA_L_IRQ_MASK,
-		.status_mask = SPEAR300_CAMERA_L_IRQ_MASK,
-	}, {
-		.virq = SPEAR300_VIRQ_CAMERA_F,
-		.enb_mask = SPEAR300_CAMERA_F_IRQ_MASK,
-		.status_mask = SPEAR300_CAMERA_F_IRQ_MASK,
-	}, {
-		.virq = SPEAR300_VIRQ_CAMERA_V,
-		.enb_mask = SPEAR300_CAMERA_V_IRQ_MASK,
-		.status_mask = SPEAR300_CAMERA_V_IRQ_MASK,
-	}, {
-		.virq = SPEAR300_VIRQ_KEYBOARD,
-		.enb_mask = SPEAR300_KEYBOARD_IRQ_MASK,
-		.status_mask = SPEAR300_KEYBOARD_IRQ_MASK,
-	}, {
-		.virq = SPEAR300_VIRQ_GPIO1,
-		.enb_mask = SPEAR300_GPIO1_IRQ_MASK,
-		.status_mask = SPEAR300_GPIO1_IRQ_MASK,
-	},
-};
-
-static struct spear_shirq shirq_ras1 = {
-	.irq = SPEAR3XX_IRQ_GEN_RAS_1,
-	.dev_config = shirq_ras1_config,
-	.dev_count = ARRAY_SIZE(shirq_ras1_config),
-	.regs = {
-		.enb_reg = SPEAR300_INT_ENB_MASK_REG,
-		.status_reg = SPEAR300_INT_STS_MASK_REG,
-		.status_reg_mask = SPEAR300_SHIRQ_RAS1_MASK,
-		.clear_reg = -1,
-	},
-};
-
 /* DMAC platform data's slave info */
 struct pl08x_channel_data spear300_dma_info[] = {
 	{
@@ -285,21 +192,11 @@ static struct of_dev_auxdata spear300_auxdata_lookup[] __initdata = {
 
 static void __init spear300_dt_init(void)
 {
-	int ret;
-
 	pl080_plat_data.slave_channels = spear300_dma_info;
 	pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear300_dma_info);
 
 	of_platform_populate(NULL, of_default_bus_match_table,
 			spear300_auxdata_lookup, NULL);
-
-	/* shared irq registration */
-	shirq_ras1.regs.base = ioremap(SPEAR300_TELECOM_BASE, SZ_4K);
-	if (shirq_ras1.regs.base) {
-		ret = spear_shirq_register(&shirq_ras1);
-		if (ret)
-			pr_err("Error registering Shared IRQ\n");
-	}
 }
 
 static const char * const spear300_dt_board_compat[] = {
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index 1d0e435..b963ebb 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -18,7 +18,6 @@
 #include <linux/of_platform.h>
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
-#include <plat/shirq.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
 
@@ -27,176 +26,6 @@
 #define SPEAR310_UART3_BASE		UL(0xB2100000)
 #define SPEAR310_UART4_BASE		UL(0xB2180000)
 #define SPEAR310_UART5_BASE		UL(0xB2200000)
-#define SPEAR310_SOC_CONFIG_BASE	UL(0xB4000000)
-
-/* Interrupt registers offsets and masks */
-#define SPEAR310_INT_STS_MASK_REG	0x04
-#define SPEAR310_SMII0_IRQ_MASK		(1 << 0)
-#define SPEAR310_SMII1_IRQ_MASK		(1 << 1)
-#define SPEAR310_SMII2_IRQ_MASK		(1 << 2)
-#define SPEAR310_SMII3_IRQ_MASK		(1 << 3)
-#define SPEAR310_WAKEUP_SMII0_IRQ_MASK	(1 << 4)
-#define SPEAR310_WAKEUP_SMII1_IRQ_MASK	(1 << 5)
-#define SPEAR310_WAKEUP_SMII2_IRQ_MASK	(1 << 6)
-#define SPEAR310_WAKEUP_SMII3_IRQ_MASK	(1 << 7)
-#define SPEAR310_UART1_IRQ_MASK		(1 << 8)
-#define SPEAR310_UART2_IRQ_MASK		(1 << 9)
-#define SPEAR310_UART3_IRQ_MASK		(1 << 10)
-#define SPEAR310_UART4_IRQ_MASK		(1 << 11)
-#define SPEAR310_UART5_IRQ_MASK		(1 << 12)
-#define SPEAR310_EMI_IRQ_MASK		(1 << 13)
-#define SPEAR310_TDM_HDLC_IRQ_MASK	(1 << 14)
-#define SPEAR310_RS485_0_IRQ_MASK	(1 << 15)
-#define SPEAR310_RS485_1_IRQ_MASK	(1 << 16)
-
-#define SPEAR310_SHIRQ_RAS1_MASK	0x000FF
-#define SPEAR310_SHIRQ_RAS2_MASK	0x01F00
-#define SPEAR310_SHIRQ_RAS3_MASK	0x02000
-#define SPEAR310_SHIRQ_INTRCOMM_RAS_MASK	0x1C000
-
-/* SPEAr310 Virtual irq definitions */
-/* IRQs sharing IRQ_GEN_RAS_1 */
-#define SPEAR310_VIRQ_SMII0			(SPEAR3XX_VIRQ_START + 0)
-#define SPEAR310_VIRQ_SMII1			(SPEAR3XX_VIRQ_START + 1)
-#define SPEAR310_VIRQ_SMII2			(SPEAR3XX_VIRQ_START + 2)
-#define SPEAR310_VIRQ_SMII3			(SPEAR3XX_VIRQ_START + 3)
-#define SPEAR310_VIRQ_WAKEUP_SMII0		(SPEAR3XX_VIRQ_START + 4)
-#define SPEAR310_VIRQ_WAKEUP_SMII1		(SPEAR3XX_VIRQ_START + 5)
-#define SPEAR310_VIRQ_WAKEUP_SMII2		(SPEAR3XX_VIRQ_START + 6)
-#define SPEAR310_VIRQ_WAKEUP_SMII3		(SPEAR3XX_VIRQ_START + 7)
-
-/* IRQs sharing IRQ_GEN_RAS_2 */
-#define SPEAR310_VIRQ_UART1			(SPEAR3XX_VIRQ_START + 8)
-#define SPEAR310_VIRQ_UART2			(SPEAR3XX_VIRQ_START + 9)
-#define SPEAR310_VIRQ_UART3			(SPEAR3XX_VIRQ_START + 10)
-#define SPEAR310_VIRQ_UART4			(SPEAR3XX_VIRQ_START + 11)
-#define SPEAR310_VIRQ_UART5			(SPEAR3XX_VIRQ_START + 12)
-
-/* IRQs sharing IRQ_GEN_RAS_3 */
-#define SPEAR310_VIRQ_EMI			(SPEAR3XX_VIRQ_START + 13)
-#define SPEAR310_VIRQ_PLGPIO			(SPEAR3XX_VIRQ_START + 14)
-
-/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
-#define SPEAR310_VIRQ_TDM_HDLC			(SPEAR3XX_VIRQ_START + 15)
-#define SPEAR310_VIRQ_RS485_0			(SPEAR3XX_VIRQ_START + 16)
-#define SPEAR310_VIRQ_RS485_1			(SPEAR3XX_VIRQ_START + 17)
-
-
-/* spear3xx shared irq */
-static struct shirq_dev_config shirq_ras1_config[] = {
-	{
-		.virq = SPEAR310_VIRQ_SMII0,
-		.status_mask = SPEAR310_SMII0_IRQ_MASK,
-	}, {
-		.virq = SPEAR310_VIRQ_SMII1,
-		.status_mask = SPEAR310_SMII1_IRQ_MASK,
-	}, {
-		.virq = SPEAR310_VIRQ_SMII2,
-		.status_mask = SPEAR310_SMII2_IRQ_MASK,
-	}, {
-		.virq = SPEAR310_VIRQ_SMII3,
-		.status_mask = SPEAR310_SMII3_IRQ_MASK,
-	}, {
-		.virq = SPEAR310_VIRQ_WAKEUP_SMII0,
-		.status_mask = SPEAR310_WAKEUP_SMII0_IRQ_MASK,
-	}, {
-		.virq = SPEAR310_VIRQ_WAKEUP_SMII1,
-		.status_mask = SPEAR310_WAKEUP_SMII1_IRQ_MASK,
-	}, {
-		.virq = SPEAR310_VIRQ_WAKEUP_SMII2,
-		.status_mask = SPEAR310_WAKEUP_SMII2_IRQ_MASK,
-	}, {
-		.virq = SPEAR310_VIRQ_WAKEUP_SMII3,
-		.status_mask = SPEAR310_WAKEUP_SMII3_IRQ_MASK,
-	},
-};
-
-static struct spear_shirq shirq_ras1 = {
-	.irq = SPEAR3XX_IRQ_GEN_RAS_1,
-	.dev_config = shirq_ras1_config,
-	.dev_count = ARRAY_SIZE(shirq_ras1_config),
-	.regs = {
-		.enb_reg = -1,
-		.status_reg = SPEAR310_INT_STS_MASK_REG,
-		.status_reg_mask = SPEAR310_SHIRQ_RAS1_MASK,
-		.clear_reg = -1,
-	},
-};
-
-static struct shirq_dev_config shirq_ras2_config[] = {
-	{
-		.virq = SPEAR310_VIRQ_UART1,
-		.status_mask = SPEAR310_UART1_IRQ_MASK,
-	}, {
-		.virq = SPEAR310_VIRQ_UART2,
-		.status_mask = SPEAR310_UART2_IRQ_MASK,
-	}, {
-		.virq = SPEAR310_VIRQ_UART3,
-		.status_mask = SPEAR310_UART3_IRQ_MASK,
-	}, {
-		.virq = SPEAR310_VIRQ_UART4,
-		.status_mask = SPEAR310_UART4_IRQ_MASK,
-	}, {
-		.virq = SPEAR310_VIRQ_UART5,
-		.status_mask = SPEAR310_UART5_IRQ_MASK,
-	},
-};
-
-static struct spear_shirq shirq_ras2 = {
-	.irq = SPEAR3XX_IRQ_GEN_RAS_2,
-	.dev_config = shirq_ras2_config,
-	.dev_count = ARRAY_SIZE(shirq_ras2_config),
-	.regs = {
-		.enb_reg = -1,
-		.status_reg = SPEAR310_INT_STS_MASK_REG,
-		.status_reg_mask = SPEAR310_SHIRQ_RAS2_MASK,
-		.clear_reg = -1,
-	},
-};
-
-static struct shirq_dev_config shirq_ras3_config[] = {
-	{
-		.virq = SPEAR310_VIRQ_EMI,
-		.status_mask = SPEAR310_EMI_IRQ_MASK,
-	},
-};
-
-static struct spear_shirq shirq_ras3 = {
-	.irq = SPEAR3XX_IRQ_GEN_RAS_3,
-	.dev_config = shirq_ras3_config,
-	.dev_count = ARRAY_SIZE(shirq_ras3_config),
-	.regs = {
-		.enb_reg = -1,
-		.status_reg = SPEAR310_INT_STS_MASK_REG,
-		.status_reg_mask = SPEAR310_SHIRQ_RAS3_MASK,
-		.clear_reg = -1,
-	},
-};
-
-static struct shirq_dev_config shirq_intrcomm_ras_config[] = {
-	{
-		.virq = SPEAR310_VIRQ_TDM_HDLC,
-		.status_mask = SPEAR310_TDM_HDLC_IRQ_MASK,
-	}, {
-		.virq = SPEAR310_VIRQ_RS485_0,
-		.status_mask = SPEAR310_RS485_0_IRQ_MASK,
-	}, {
-		.virq = SPEAR310_VIRQ_RS485_1,
-		.status_mask = SPEAR310_RS485_1_IRQ_MASK,
-	},
-};
-
-static struct spear_shirq shirq_intrcomm_ras = {
-	.irq = SPEAR3XX_IRQ_INTRCOMM_RAS_ARM,
-	.dev_config = shirq_intrcomm_ras_config,
-	.dev_count = ARRAY_SIZE(shirq_intrcomm_ras_config),
-	.regs = {
-		.enb_reg = -1,
-		.status_reg = SPEAR310_INT_STS_MASK_REG,
-		.status_reg_mask = SPEAR310_SHIRQ_INTRCOMM_RAS_MASK,
-		.clear_reg = -1,
-	},
-};
 
 /* DMAC platform data's slave info */
 struct pl08x_channel_data spear310_dma_info[] = {
@@ -405,42 +234,11 @@ static struct of_dev_auxdata spear310_auxdata_lookup[] __initdata = {
 
 static void __init spear310_dt_init(void)
 {
-	void __iomem *base;
-	int ret;
-
 	pl080_plat_data.slave_channels = spear310_dma_info;
 	pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear310_dma_info);
 
 	of_platform_populate(NULL, of_default_bus_match_table,
 			spear310_auxdata_lookup, NULL);
-
-	/* shared irq registration */
-	base = ioremap(SPEAR310_SOC_CONFIG_BASE, SZ_4K);
-	if (base) {
-		/* shirq 1 */
-		shirq_ras1.regs.base = base;
-		ret = spear_shirq_register(&shirq_ras1);
-		if (ret)
-			pr_err("Error registering Shared IRQ 1\n");
-
-		/* shirq 2 */
-		shirq_ras2.regs.base = base;
-		ret = spear_shirq_register(&shirq_ras2);
-		if (ret)
-			pr_err("Error registering Shared IRQ 2\n");
-
-		/* shirq 3 */
-		shirq_ras3.regs.base = base;
-		ret = spear_shirq_register(&shirq_ras3);
-		if (ret)
-			pr_err("Error registering Shared IRQ 3\n");
-
-		/* shirq 4 */
-		shirq_intrcomm_ras.regs.base = base;
-		ret = spear_shirq_register(&shirq_intrcomm_ras);
-		if (ret)
-			pr_err("Error registering Shared IRQ 4\n");
-	}
 }
 
 static const char * const spear310_dt_board_compat[] = {
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index fd823c6..66e3a0c 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -19,7 +19,6 @@
 #include <linux/of_platform.h>
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
-#include <plat/shirq.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
 
@@ -28,184 +27,6 @@
 #define SPEAR320_SSP0_BASE		UL(0xA5000000)
 #define SPEAR320_SSP1_BASE		UL(0xA6000000)
 
-/* Interrupt registers offsets and masks */
-#define SPEAR320_INT_STS_MASK_REG		0x04
-#define SPEAR320_INT_CLR_MASK_REG		0x04
-#define SPEAR320_INT_ENB_MASK_REG		0x08
-#define SPEAR320_GPIO_IRQ_MASK			(1 << 0)
-#define SPEAR320_I2S_PLAY_IRQ_MASK		(1 << 1)
-#define SPEAR320_I2S_REC_IRQ_MASK		(1 << 2)
-#define SPEAR320_EMI_IRQ_MASK			(1 << 7)
-#define SPEAR320_CLCD_IRQ_MASK			(1 << 8)
-#define SPEAR320_SPP_IRQ_MASK			(1 << 9)
-#define SPEAR320_SDHCI_IRQ_MASK			(1 << 10)
-#define SPEAR320_CAN_U_IRQ_MASK			(1 << 11)
-#define SPEAR320_CAN_L_IRQ_MASK			(1 << 12)
-#define SPEAR320_UART1_IRQ_MASK			(1 << 13)
-#define SPEAR320_UART2_IRQ_MASK			(1 << 14)
-#define SPEAR320_SSP1_IRQ_MASK			(1 << 15)
-#define SPEAR320_SSP2_IRQ_MASK			(1 << 16)
-#define SPEAR320_SMII0_IRQ_MASK			(1 << 17)
-#define SPEAR320_MII1_SMII1_IRQ_MASK		(1 << 18)
-#define SPEAR320_WAKEUP_SMII0_IRQ_MASK		(1 << 19)
-#define SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK	(1 << 20)
-#define SPEAR320_I2C1_IRQ_MASK			(1 << 21)
-
-#define SPEAR320_SHIRQ_RAS1_MASK		0x000380
-#define SPEAR320_SHIRQ_RAS3_MASK		0x000007
-#define SPEAR320_SHIRQ_INTRCOMM_RAS_MASK	0x3FF800
-
-/* SPEAr320 Virtual irq definitions */
-/* IRQs sharing IRQ_GEN_RAS_1 */
-#define SPEAR320_VIRQ_EMI			(SPEAR3XX_VIRQ_START + 0)
-#define SPEAR320_VIRQ_CLCD			(SPEAR3XX_VIRQ_START + 1)
-#define SPEAR320_VIRQ_SPP			(SPEAR3XX_VIRQ_START + 2)
-
-/* IRQs sharing IRQ_GEN_RAS_2 */
-#define SPEAR320_IRQ_SDHCI			SPEAR3XX_IRQ_GEN_RAS_2
-
-/* IRQs sharing IRQ_GEN_RAS_3 */
-#define SPEAR320_VIRQ_PLGPIO			(SPEAR3XX_VIRQ_START + 3)
-#define SPEAR320_VIRQ_I2S_PLAY			(SPEAR3XX_VIRQ_START + 4)
-#define SPEAR320_VIRQ_I2S_REC			(SPEAR3XX_VIRQ_START + 5)
-
-/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
-#define SPEAR320_VIRQ_CANU			(SPEAR3XX_VIRQ_START + 6)
-#define SPEAR320_VIRQ_CANL			(SPEAR3XX_VIRQ_START + 7)
-#define SPEAR320_VIRQ_UART1			(SPEAR3XX_VIRQ_START + 8)
-#define SPEAR320_VIRQ_UART2			(SPEAR3XX_VIRQ_START + 9)
-#define SPEAR320_VIRQ_SSP1			(SPEAR3XX_VIRQ_START + 10)
-#define SPEAR320_VIRQ_SSP2			(SPEAR3XX_VIRQ_START + 11)
-#define SPEAR320_VIRQ_SMII0			(SPEAR3XX_VIRQ_START + 12)
-#define SPEAR320_VIRQ_MII1_SMII1		(SPEAR3XX_VIRQ_START + 13)
-#define SPEAR320_VIRQ_WAKEUP_SMII0		(SPEAR3XX_VIRQ_START + 14)
-#define SPEAR320_VIRQ_WAKEUP_MII1_SMII1		(SPEAR3XX_VIRQ_START + 15)
-#define SPEAR320_VIRQ_I2C1			(SPEAR3XX_VIRQ_START + 16)
-
-/* spear3xx shared irq */
-static struct shirq_dev_config shirq_ras1_config[] = {
-	{
-		.virq = SPEAR320_VIRQ_EMI,
-		.status_mask = SPEAR320_EMI_IRQ_MASK,
-		.clear_mask = SPEAR320_EMI_IRQ_MASK,
-	}, {
-		.virq = SPEAR320_VIRQ_CLCD,
-		.status_mask = SPEAR320_CLCD_IRQ_MASK,
-		.clear_mask = SPEAR320_CLCD_IRQ_MASK,
-	}, {
-		.virq = SPEAR320_VIRQ_SPP,
-		.status_mask = SPEAR320_SPP_IRQ_MASK,
-		.clear_mask = SPEAR320_SPP_IRQ_MASK,
-	},
-};
-
-static struct spear_shirq shirq_ras1 = {
-	.irq = SPEAR3XX_IRQ_GEN_RAS_1,
-	.dev_config = shirq_ras1_config,
-	.dev_count = ARRAY_SIZE(shirq_ras1_config),
-	.regs = {
-		.enb_reg = -1,
-		.status_reg = SPEAR320_INT_STS_MASK_REG,
-		.status_reg_mask = SPEAR320_SHIRQ_RAS1_MASK,
-		.clear_reg = SPEAR320_INT_CLR_MASK_REG,
-		.reset_to_clear = 1,
-	},
-};
-
-static struct shirq_dev_config shirq_ras3_config[] = {
-	{
-		.virq = SPEAR320_VIRQ_PLGPIO,
-		.enb_mask = SPEAR320_GPIO_IRQ_MASK,
-		.status_mask = SPEAR320_GPIO_IRQ_MASK,
-		.clear_mask = SPEAR320_GPIO_IRQ_MASK,
-	}, {
-		.virq = SPEAR320_VIRQ_I2S_PLAY,
-		.enb_mask = SPEAR320_I2S_PLAY_IRQ_MASK,
-		.status_mask = SPEAR320_I2S_PLAY_IRQ_MASK,
-		.clear_mask = SPEAR320_I2S_PLAY_IRQ_MASK,
-	}, {
-		.virq = SPEAR320_VIRQ_I2S_REC,
-		.enb_mask = SPEAR320_I2S_REC_IRQ_MASK,
-		.status_mask = SPEAR320_I2S_REC_IRQ_MASK,
-		.clear_mask = SPEAR320_I2S_REC_IRQ_MASK,
-	},
-};
-
-static struct spear_shirq shirq_ras3 = {
-	.irq = SPEAR3XX_IRQ_GEN_RAS_3,
-	.dev_config = shirq_ras3_config,
-	.dev_count = ARRAY_SIZE(shirq_ras3_config),
-	.regs = {
-		.enb_reg = SPEAR320_INT_ENB_MASK_REG,
-		.reset_to_enb = 1,
-		.status_reg = SPEAR320_INT_STS_MASK_REG,
-		.status_reg_mask = SPEAR320_SHIRQ_RAS3_MASK,
-		.clear_reg = SPEAR320_INT_CLR_MASK_REG,
-		.reset_to_clear = 1,
-	},
-};
-
-static struct shirq_dev_config shirq_intrcomm_ras_config[] = {
-	{
-		.virq = SPEAR320_VIRQ_CANU,
-		.status_mask = SPEAR320_CAN_U_IRQ_MASK,
-		.clear_mask = SPEAR320_CAN_U_IRQ_MASK,
-	}, {
-		.virq = SPEAR320_VIRQ_CANL,
-		.status_mask = SPEAR320_CAN_L_IRQ_MASK,
-		.clear_mask = SPEAR320_CAN_L_IRQ_MASK,
-	}, {
-		.virq = SPEAR320_VIRQ_UART1,
-		.status_mask = SPEAR320_UART1_IRQ_MASK,
-		.clear_mask = SPEAR320_UART1_IRQ_MASK,
-	}, {
-		.virq = SPEAR320_VIRQ_UART2,
-		.status_mask = SPEAR320_UART2_IRQ_MASK,
-		.clear_mask = SPEAR320_UART2_IRQ_MASK,
-	}, {
-		.virq = SPEAR320_VIRQ_SSP1,
-		.status_mask = SPEAR320_SSP1_IRQ_MASK,
-		.clear_mask = SPEAR320_SSP1_IRQ_MASK,
-	}, {
-		.virq = SPEAR320_VIRQ_SSP2,
-		.status_mask = SPEAR320_SSP2_IRQ_MASK,
-		.clear_mask = SPEAR320_SSP2_IRQ_MASK,
-	}, {
-		.virq = SPEAR320_VIRQ_SMII0,
-		.status_mask = SPEAR320_SMII0_IRQ_MASK,
-		.clear_mask = SPEAR320_SMII0_IRQ_MASK,
-	}, {
-		.virq = SPEAR320_VIRQ_MII1_SMII1,
-		.status_mask = SPEAR320_MII1_SMII1_IRQ_MASK,
-		.clear_mask = SPEAR320_MII1_SMII1_IRQ_MASK,
-	}, {
-		.virq = SPEAR320_VIRQ_WAKEUP_SMII0,
-		.status_mask = SPEAR320_WAKEUP_SMII0_IRQ_MASK,
-		.clear_mask = SPEAR320_WAKEUP_SMII0_IRQ_MASK,
-	}, {
-		.virq = SPEAR320_VIRQ_WAKEUP_MII1_SMII1,
-		.status_mask = SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK,
-		.clear_mask = SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK,
-	}, {
-		.virq = SPEAR320_VIRQ_I2C1,
-		.status_mask = SPEAR320_I2C1_IRQ_MASK,
-		.clear_mask = SPEAR320_I2C1_IRQ_MASK,
-	},
-};
-
-static struct spear_shirq shirq_intrcomm_ras = {
-	.irq = SPEAR3XX_IRQ_INTRCOMM_RAS_ARM,
-	.dev_config = shirq_intrcomm_ras_config,
-	.dev_count = ARRAY_SIZE(shirq_intrcomm_ras_config),
-	.regs = {
-		.enb_reg = -1,
-		.status_reg = SPEAR320_INT_STS_MASK_REG,
-		.status_reg_mask = SPEAR320_SHIRQ_INTRCOMM_RAS_MASK,
-		.clear_reg = SPEAR320_INT_CLR_MASK_REG,
-		.reset_to_clear = 1,
-	},
-};
-
 /* DMAC platform data's slave info */
 struct pl08x_channel_data spear320_dma_info[] = {
 	{
@@ -416,41 +237,17 @@ static struct of_dev_auxdata spear320_auxdata_lookup[] __initdata = {
 
 static void __init spear320_dt_init(void)
 {
-	void __iomem *base;
-	int ret;
-
 	pl080_plat_data.slave_channels = spear320_dma_info;
 	pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear320_dma_info);
 
 	of_platform_populate(NULL, of_default_bus_match_table,
 			spear320_auxdata_lookup, NULL);
-
-	/* shared irq registration */
-	base = ioremap(SPEAR320_SOC_CONFIG_BASE, SZ_4K);
-	if (base) {
-		/* shirq 1 */
-		shirq_ras1.regs.base = base;
-		ret = spear_shirq_register(&shirq_ras1);
-		if (ret)
-			pr_err("Error registering Shared IRQ 1\n");
-
-		/* shirq 3 */
-		shirq_ras3.regs.base = base;
-		ret = spear_shirq_register(&shirq_ras3);
-		if (ret)
-			pr_err("Error registering Shared IRQ 3\n");
-
-		/* shirq 4 */
-		shirq_intrcomm_ras.regs.base = base;
-		ret = spear_shirq_register(&shirq_intrcomm_ras);
-		if (ret)
-			pr_err("Error registering Shared IRQ 4\n");
-	}
 }
 
 static const char * const spear320_dt_board_compat[] = {
 	"st,spear320",
 	"st,spear320-evb",
+	"st,spear320-hmi",
 	NULL,
 };
 
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 98144ba..38fe95d 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -15,6 +15,7 @@
 
 #include <linux/amba/pl022.h>
 #include <linux/amba/pl08x.h>
+#include <linux/irqchip/spear-shirq.h>
 #include <linux/of_irq.h>
 #include <linux/io.h>
 #include <asm/hardware/pl080.h>
@@ -121,6 +122,9 @@ struct sys_timer spear3xx_timer = {
 
 static const struct of_device_id vic_of_match[] __initconst = {
 	{ .compatible = "arm,pl190-vic", .data = vic_of_init, },
+	{ .compatible = "st,spear300-shirq", .data = spear300_shirq_of_init, },
+	{ .compatible = "st,spear310-shirq", .data = spear310_shirq_of_init, },
+	{ .compatible = "st,spear320-shirq", .data = spear320_shirq_of_init, },
 	{ /* Sentinel */ }
 };
 
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
new file mode 100644
index 0000000..3fdd008
--- /dev/null
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -0,0 +1,9 @@
+config ARCH_SUNXI
+	bool "Allwinner A1X SOCs" if ARCH_MULTI_V7
+	select CLKSRC_MMIO
+	select COMMON_CLK
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_IRQ_CHIP
+	select PINCTRL
+	select SPARSE_IRQ
+	select SUNXI_TIMER
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
new file mode 100644
index 0000000..93bebfc
--- /dev/null
+++ b/arch/arm/mach-sunxi/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_SUNXI) += sunxi.o
diff --git a/arch/arm/mach-sunxi/Makefile.boot b/arch/arm/mach-sunxi/Makefile.boot
new file mode 100644
index 0000000..46d4cf0
--- /dev/null
+++ b/arch/arm/mach-sunxi/Makefile.boot
@@ -0,0 +1 @@
+zreladdr-$(CONFIG_ARCH_SUNXI)	+= 0x40008000
diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c
new file mode 100644
index 0000000..dc634ae
--- /dev/null
+++ b/arch/arm/mach-sunxi/sunxi.c
@@ -0,0 +1,95 @@
+/*
+ * Device Tree support for Allwinner A1X SoCs
+ *
+ * Copyright (C) 2012 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/sunxi_timer.h>
+
+#include <linux/irqchip/sunxi.h>
+
+#include <asm/hardware/vic.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include "sunxi.h"
+
+#define WATCHDOG_CTRL_REG	0x00
+#define WATCHDOG_MODE_REG	0x04
+
+static void __iomem *wdt_base;
+
+static void sunxi_setup_restart(void)
+{
+	struct device_node *np = of_find_compatible_node(NULL, NULL,
+						"allwinner,sunxi-wdt");
+	if (WARN(!np, "unable to setup watchdog restart"))
+		return;
+
+	wdt_base = of_iomap(np, 0);
+	WARN(!wdt_base, "failed to map watchdog base address");
+}
+
+static void sunxi_restart(char mode, const char *cmd)
+{
+	if (!wdt_base)
+		return;
+
+	/* Enable timer and set reset bit in the watchdog */
+	writel(3, wdt_base + WATCHDOG_MODE_REG);
+	writel(0xa57 << 1 | 1, wdt_base + WATCHDOG_CTRL_REG);
+	while(1) {
+		mdelay(5);
+		writel(3, wdt_base + WATCHDOG_MODE_REG);
+	}
+}
+
+static struct map_desc sunxi_io_desc[] __initdata = {
+	{
+		.virtual	= (unsigned long) SUNXI_REGS_VIRT_BASE,
+		.pfn		= __phys_to_pfn(SUNXI_REGS_PHYS_BASE),
+		.length		= SUNXI_REGS_SIZE,
+		.type		= MT_DEVICE,
+	},
+};
+
+void __init sunxi_map_io(void)
+{
+	iotable_init(sunxi_io_desc, ARRAY_SIZE(sunxi_io_desc));
+}
+
+static void __init sunxi_dt_init(void)
+{
+	sunxi_setup_restart();
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char * const sunxi_board_dt_compat[] = {
+	"allwinner,sun4i",
+	"allwinner,sun5i",
+	NULL,
+};
+
+DT_MACHINE_START(SUNXI_DT, "Allwinner A1X (Device Tree)")
+	.init_machine	= sunxi_dt_init,
+	.map_io		= sunxi_map_io,
+	.init_irq	= sunxi_init_irq,
+	.handle_irq	= sunxi_handle_irq,
+	.restart	= sunxi_restart,
+	.timer		= &sunxi_timer,
+	.dt_compat	= sunxi_board_dt_compat,
+MACHINE_END
diff --git a/arch/arm/mach-sunxi/sunxi.h b/arch/arm/mach-sunxi/sunxi.h
new file mode 100644
index 0000000..33b5871
--- /dev/null
+++ b/arch/arm/mach-sunxi/sunxi.h
@@ -0,0 +1,20 @@
+/*
+ * Generic definitions for Allwinner SunXi SoCs
+ *
+ * Copyright (C) 2012 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@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.
+ */
+
+#ifndef __MACH_SUNXI_H
+#define __MACH_SUNXI_H
+
+#define SUNXI_REGS_PHYS_BASE	0x01c00000
+#define SUNXI_REGS_VIRT_BASE	IOMEM(0xf1c00000)
+#define SUNXI_REGS_SIZE		(SZ_2M + SZ_1M)
+
+#endif /* __MACH_SUNXI_H */
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 9ff6f6e..e426d1b 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -57,57 +57,6 @@ config TEGRA_AHB
 	  which controls AHB bus master arbitration and some
 	  perfomance parameters(priority, prefech size).
 
-choice
-        prompt "Default low-level debug console UART"
-        default TEGRA_DEBUG_UART_NONE
-
-config TEGRA_DEBUG_UART_NONE
-        bool "None"
-
-config TEGRA_DEBUG_UARTA
-        bool "UART-A"
-
-config TEGRA_DEBUG_UARTB
-        bool "UART-B"
-
-config TEGRA_DEBUG_UARTC
-        bool "UART-C"
-
-config TEGRA_DEBUG_UARTD
-        bool "UART-D"
-
-config TEGRA_DEBUG_UARTE
-        bool "UART-E"
-
-endchoice
-
-choice
-	prompt "Automatic low-level debug console UART"
-	default TEGRA_DEBUG_UART_AUTO_NONE
-
-config TEGRA_DEBUG_UART_AUTO_NONE
-	bool "None"
-
-config TEGRA_DEBUG_UART_AUTO_ODMDATA
-	bool "Via ODMDATA"
-	help
-	  Automatically determines which UART to use for low-level debug based
-	  on the ODMDATA value. This value is part of the BCT, and is written
-	  to the boot memory device using nvflash, or other flashing tool.
-	  When bits 19:18 are 3, then bits 17:15 indicate which UART to use;
-	  0/1/2/3/4 are UART A/B/C/D/E.
-
-config TEGRA_DEBUG_UART_AUTO_SCRATCH
-	bool "Via UART scratch register"
-	help
-	  Automatically determines which UART to use for low-level debug based
-	  on the UART scratch register value. Some bootloaders put ASCII 'D'
-	  in this register when they initialize their own console UART output.
-	  Using this option allows the kernel to automatically pick the same
-	  UART.
-
-endchoice
-
 config TEGRA_EMC_SCALING_ENABLE
 	bool "Enable scaling the memory frequency"
 
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 9aa653b..0979e8b 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -8,15 +8,24 @@ obj-y					+= pmc.o
 obj-y					+= flowctrl.o
 obj-y					+= powergate.o
 obj-y					+= apbio.o
+obj-y					+= pm.o
 obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
 obj-$(CONFIG_CPU_IDLE)			+= sleep.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra20_clocks.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra20_clocks_data.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra20_speedo.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra2_emc.o
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= sleep-t20.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= sleep-tegra20.o
+ifeq ($(CONFIG_CPU_IDLE),y)
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= cpuidle-tegra20.o
+endif
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_clocks.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_clocks_data.o
-obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= sleep-t30.o
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_speedo.o
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= sleep-tegra30.o
+ifeq ($(CONFIG_CPU_IDLE),y)
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= cpuidle-tegra30.o
+endif
 obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
 obj-$(CONFIG_SMP)                       += reset.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c
index b5015d0..d091675 100644
--- a/arch/arm/mach-tegra/apbio.c
+++ b/arch/arm/mach-tegra/apbio.c
@@ -15,7 +15,6 @@
 
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <mach/iomap.h>
 #include <linux/of.h>
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
@@ -24,9 +23,8 @@
 #include <linux/sched.h>
 #include <linux/mutex.h>
 
-#include <mach/dma.h>
-
 #include "apbio.h"
+#include "iomap.h"
 
 #if defined(CONFIG_TEGRA20_APB_DMA)
 static DEFINE_MUTEX(tegra_apb_dma_lock);
@@ -71,7 +69,6 @@ bool tegra_apb_dma_init(void)
 
 	dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 	dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-	dma_sconfig.slave_id = TEGRA_DMA_REQ_SEL_CNTR;
 	dma_sconfig.src_maxburst = 1;
 	dma_sconfig.dst_maxburst = 1;
 
diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c
index aa5325c..734d9cc 100644
--- a/arch/arm/mach-tegra/board-dt-tegra20.c
+++ b/arch/arm/mach-tegra/board-dt-tegra20.c
@@ -40,12 +40,10 @@
 #include <asm/mach/time.h>
 #include <asm/setup.h>
 
-#include <mach/iomap.h>
-#include <mach/irqs.h>
-
 #include "board.h"
 #include "clock.h"
 #include "common.h"
+#include "iomap.h"
 
 struct tegra_ehci_platform_data tegra_ehci1_pdata = {
 	.operating_mode = TEGRA_USB_OTG,
@@ -91,6 +89,17 @@ struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
 		       &tegra_ehci3_pdata),
 	OF_DEV_AUXDATA("nvidia,tegra20-apbdma", TEGRA_APB_DMA_BASE, "tegra-apbdma", NULL),
 	OF_DEV_AUXDATA("nvidia,tegra20-pwm", TEGRA_PWFM_BASE, "tegra-pwm", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-sflash", 0x7000c380, "spi", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-slink", 0x7000D400, "spi_tegra.0", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-slink", 0x7000D600, "spi_tegra.1", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-slink", 0x7000D800, "spi_tegra.2", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-slink", 0x7000DA00, "spi_tegra.3", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-host1x", 0x50000000, "host1x", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-dc", 0x54200000, "tegradc.0", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-dc", 0x54240000, "tegradc.1", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-hdmi", 0x54280000, "hdmi", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-dsi", 0x54300000, "dsi", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra20-tvo", 0x542c0000, "tvo", NULL),
 	{}
 };
 
@@ -104,8 +113,20 @@ static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
 	{ "pll_a",      "pll_p_out1",   56448000,       true },
 	{ "pll_a_out0", "pll_a",        11289600,       true },
 	{ "cdev1",      NULL,           0,              true },
+	{ "blink",      "clk_32k",      32768,          true },
 	{ "i2s1",       "pll_a_out0",   11289600,       false},
 	{ "i2s2",       "pll_a_out0",   11289600,       false},
+	{ "sdmmc1",	"pll_p",	48000000,	false},
+	{ "sdmmc3",	"pll_p",	48000000,	false},
+	{ "sdmmc4",	"pll_p",	48000000,	false},
+	{ "spi",	"pll_p",	20000000,	false },
+	{ "sbc1",	"pll_p",	100000000,	false },
+	{ "sbc2",	"pll_p",	100000000,	false },
+	{ "sbc3",	"pll_p",	100000000,	false },
+	{ "sbc4",	"pll_p",	100000000,	false },
+	{ "host1x",	"pll_c",	150000000,	false },
+	{ "disp1",	"pll_p",	600000000,	false },
+	{ "disp2",	"pll_p",	600000000,	false },
 	{ NULL,		NULL,		0,		0},
 };
 
diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c
index 5e92a81..6497d12 100644
--- a/arch/arm/mach-tegra/board-dt-tegra30.c
+++ b/arch/arm/mach-tegra/board-dt-tegra30.c
@@ -33,11 +33,10 @@
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
 
-#include <mach/iomap.h>
-
 #include "board.h"
 #include "clock.h"
 #include "common.h"
+#include "iomap.h"
 
 struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000000, "sdhci-tegra.0", NULL),
@@ -52,6 +51,18 @@ struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("nvidia,tegra30-ahub", 0x70080000, "tegra30-ahub", NULL),
 	OF_DEV_AUXDATA("nvidia,tegra30-apbdma", 0x6000a000, "tegra-apbdma", NULL),
 	OF_DEV_AUXDATA("nvidia,tegra30-pwm", TEGRA_PWFM_BASE, "tegra-pwm", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000D400, "spi_tegra.0", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000D600, "spi_tegra.1", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000D800, "spi_tegra.2", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000DA00, "spi_tegra.3", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000DC00, "spi_tegra.4", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000DE00, "spi_tegra.5", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra30-host1x", 0x50000000, "host1x", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra30-dc", 0x54200000, "tegradc.0", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra30-dc", 0x54240000, "tegradc.1", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra30-hdmi", 0x54280000, "hdmi", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra30-dsi", 0x54300000, "dsi", NULL),
+	OF_DEV_AUXDATA("nvidia,tegra30-tvo", 0x542c0000, "tvo", NULL),
 	{}
 };
 
@@ -62,11 +73,24 @@ static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
 	{ "pll_a_out0",	"pll_a",	11289600,	true },
 	{ "extern1",	"pll_a_out0",	0,		true },
 	{ "clk_out_1",	"extern1",	0,		true },
+	{ "blink",	"clk_32k",	32768,		true },
 	{ "i2s0",	"pll_a_out0",	11289600,	false},
 	{ "i2s1",	"pll_a_out0",	11289600,	false},
 	{ "i2s2",	"pll_a_out0",	11289600,	false},
 	{ "i2s3",	"pll_a_out0",	11289600,	false},
 	{ "i2s4",	"pll_a_out0",	11289600,	false},
+	{ "sdmmc1",	"pll_p",	48000000,	false},
+	{ "sdmmc3",	"pll_p",	48000000,	false},
+	{ "sdmmc4",	"pll_p",	48000000,	false},
+	{ "sbc1",	"pll_p",	100000000,	false},
+	{ "sbc2",	"pll_p",	100000000,	false},
+	{ "sbc3",	"pll_p",	100000000,	false},
+	{ "sbc4",	"pll_p",	100000000,	false},
+	{ "sbc5",	"pll_p",	100000000,	false},
+	{ "sbc6",	"pll_p",	100000000,	false},
+	{ "host1x",	"pll_c",	150000000,	false},
+	{ "disp1",	"pll_p",	600000000,	false},
+	{ "disp2",	"pll_p",	600000000,	false},
 	{ NULL,		NULL,		0,		0},
 };
 
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index fd82085..867bf8b 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -27,8 +27,6 @@
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 
-#include <mach/clk.h>
-
 #include "board.h"
 #include "clock.h"
 #include "tegra_cpu_car.h"
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 0b0a5f5..d54cfc5 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -26,16 +26,17 @@
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/gic.h>
 
-#include <mach/iomap.h>
 #include <mach/powergate.h>
 
 #include "board.h"
 #include "clock.h"
 #include "common.h"
 #include "fuse.h"
+#include "iomap.h"
 #include "pmc.h"
 #include "apbio.h"
 #include "sleep.h"
+#include "pm.h"
 
 /*
  * Storage for debug-macro.S's state.
@@ -44,14 +45,15 @@
  * 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.
  */
-#define TEGRA_DEBUG_UART_OFFSET (TEGRA_DEBUG_UART_BASE & 0xFFFF)
-u32 tegra_uart_config[3] = {
+u32 tegra_uart_config[4] = {
 	/* Debug UART initialization required */
 	1,
 	/* Debug UART physical address */
-	(u32)(IO_APB_PHYS + TEGRA_DEBUG_UART_OFFSET),
+	0,
 	/* Debug UART virtual address */
-	(u32)(IO_APB_VIRT + TEGRA_DEBUG_UART_OFFSET),
+	0,
+	/* Scratch space for debug macro */
+	0,
 };
 
 #ifdef CONFIG_OF
@@ -102,27 +104,32 @@ static __initdata struct tegra_clk_init_table tegra20_clk_init_table[] = {
 static __initdata struct tegra_clk_init_table tegra30_clk_init_table[] = {
 	/* name		parent		rate		enabled */
 	{ "clk_m",	NULL,		0,		true },
-	{ "pll_p",	"clk_m",	408000000,	true },
+	{ "pll_p",	"pll_ref",	408000000,	true },
 	{ "pll_p_out1",	"pll_p",	9600000,	true },
+	{ "pll_p_out4",	"pll_p",	102000000,	true },
+	{ "sclk",	"pll_p_out4",	102000000,	true },
+	{ "hclk",	"sclk",		102000000,	true },
+	{ "pclk",	"hclk",		51000000,	true },
+	{ "csite",	NULL,		0,		true },
 	{ NULL,		NULL,		0,		0},
 };
 #endif
 
 
-static void __init tegra_init_cache(u32 tag_latency, u32 data_latency)
+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;
 
-	writel_relaxed(tag_latency, p + L2X0_TAG_LATENCY_CTRL);
-	writel_relaxed(data_latency, p + L2X0_DATA_LATENCY_CTRL);
-
 	cache_type = readl(p + L2X0_CACHE_TYPE);
 	aux_ctrl = (cache_type & 0x700) << (17-8);
-	aux_ctrl |= 0x6C000001;
+	aux_ctrl |= 0x7C400001;
 
-	l2x0_init(p, aux_ctrl, 0x8200c3fe);
+	ret = l2x0_of_init(aux_ctrl, 0x8200c3fe);
+	if (!ret)
+		l2x0_saved_regs_addr = virt_to_phys(&l2x0_saved_regs);
 #endif
 
 }
@@ -134,7 +141,7 @@ void __init tegra20_init_early(void)
 	tegra_init_fuse();
 	tegra2_init_clocks();
 	tegra_clk_init_from_table(tegra20_clk_init_table);
-	tegra_init_cache(0x331, 0x441);
+	tegra_init_cache();
 	tegra_pmc_init();
 	tegra_powergate_init();
 	tegra20_hotplug_init();
@@ -147,7 +154,7 @@ void __init tegra30_init_early(void)
 	tegra_init_fuse();
 	tegra30_init_clocks();
 	tegra_clk_init_from_table(tegra30_clk_init_table);
-	tegra_init_cache(0x441, 0x551);
+	tegra_init_cache();
 	tegra_pmc_init();
 	tegra_powergate_init();
 	tegra30_hotplug_init();
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
index 627bf0f..a74d3c7 100644
--- a/arch/arm/mach-tegra/cpu-tegra.c
+++ b/arch/arm/mach-tegra/cpu-tegra.c
@@ -30,9 +30,6 @@
 #include <linux/io.h>
 #include <linux/suspend.h>
 
-
-#include <mach/clk.h>
-
 /* Frequency table index must be sequential starting at 0 */
 static struct cpufreq_frequency_table freq_table[] = {
 	{ 0, 216000 },
diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c
new file mode 100644
index 0000000..d32e8b0
--- /dev/null
+++ b/arch/arm/mach-tegra/cpuidle-tegra20.c
@@ -0,0 +1,66 @@
+/*
+ * CPU idle driver for Tegra CPUs
+ *
+ * Copyright (c) 2010-2012, NVIDIA Corporation.
+ * Copyright (c) 2011 Google, Inc.
+ * Author: Colin Cross <ccross@android.com>
+ *         Gary King <gking@nvidia.com>
+ *
+ * Rework for 3.3 by Peter De Schrijver <pdeschrijver@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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/cpuidle.h>
+
+#include <asm/cpuidle.h>
+
+static struct cpuidle_driver tegra_idle_driver = {
+	.name = "tegra_idle",
+	.owner = THIS_MODULE,
+	.en_core_tk_irqen = 1,
+	.state_count = 1,
+	.states = {
+		[0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
+	},
+};
+
+static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device);
+
+int __init tegra20_cpuidle_init(void)
+{
+	int ret;
+	unsigned int cpu;
+	struct cpuidle_device *dev;
+	struct cpuidle_driver *drv = &tegra_idle_driver;
+
+	ret = cpuidle_register_driver(&tegra_idle_driver);
+	if (ret) {
+		pr_err("CPUidle driver registration failed\n");
+		return ret;
+	}
+
+	for_each_possible_cpu(cpu) {
+		dev = &per_cpu(tegra_idle_device, cpu);
+		dev->cpu = cpu;
+
+		dev->state_count = drv->state_count;
+		ret = cpuidle_register_device(dev);
+		if (ret) {
+			pr_err("CPU%u: CPUidle device registration failed\n",
+				cpu);
+			return ret;
+		}
+	}
+	return 0;
+}
diff --git a/arch/arm/mach-tegra/cpuidle-tegra30.c b/arch/arm/mach-tegra/cpuidle-tegra30.c
new file mode 100644
index 0000000..5e8cbf5
--- /dev/null
+++ b/arch/arm/mach-tegra/cpuidle-tegra30.c
@@ -0,0 +1,188 @@
+/*
+ * CPU idle driver for Tegra CPUs
+ *
+ * Copyright (c) 2010-2012, NVIDIA Corporation.
+ * Copyright (c) 2011 Google, Inc.
+ * Author: Colin Cross <ccross@android.com>
+ *         Gary King <gking@nvidia.com>
+ *
+ * Rework for 3.3 by Peter De Schrijver <pdeschrijver@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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/cpuidle.h>
+#include <linux/cpu_pm.h>
+#include <linux/clockchips.h>
+
+#include <asm/cpuidle.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+#include <asm/smp_plat.h>
+
+#include "pm.h"
+#include "sleep.h"
+#include "tegra_cpu_car.h"
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra30_idle_lp2(struct cpuidle_device *dev,
+			    struct cpuidle_driver *drv,
+			    int index);
+#endif
+
+static struct cpuidle_driver tegra_idle_driver = {
+	.name = "tegra_idle",
+	.owner = THIS_MODULE,
+	.en_core_tk_irqen = 1,
+#ifdef CONFIG_PM_SLEEP
+	.state_count = 2,
+#else
+	.state_count = 1,
+#endif
+	.states = {
+		[0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
+#ifdef CONFIG_PM_SLEEP
+		[1] = {
+			.enter			= tegra30_idle_lp2,
+			.exit_latency		= 2000,
+			.target_residency	= 2200,
+			.power_usage		= 0,
+			.flags			= CPUIDLE_FLAG_TIME_VALID,
+			.name			= "powered-down",
+			.desc			= "CPU power gated",
+		},
+#endif
+	},
+};
+
+static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device);
+
+#ifdef CONFIG_PM_SLEEP
+static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
+					   struct cpuidle_driver *drv,
+					   int index)
+{
+	struct cpuidle_state *state = &drv->states[index];
+	u32 cpu_on_time = state->exit_latency;
+	u32 cpu_off_time = state->target_residency - state->exit_latency;
+
+	/* All CPUs entering LP2 is not working.
+	 * Don't let CPU0 enter LP2 when any secondary CPU is online.
+	 */
+	if (num_online_cpus() > 1 || !tegra_cpu_rail_off_ready()) {
+		cpu_do_idle();
+		return false;
+	}
+
+	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+
+	tegra_idle_lp2_last(cpu_on_time, cpu_off_time);
+
+	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+
+	return true;
+}
+
+#ifdef CONFIG_SMP
+static bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
+					struct cpuidle_driver *drv,
+					int index)
+{
+	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+
+	smp_wmb();
+
+	save_cpu_arch_register();
+
+	cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
+
+	restore_cpu_arch_register();
+
+	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+
+	return true;
+}
+#else
+static inline bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
+					       struct cpuidle_driver *drv,
+					       int index)
+{
+	return true;
+}
+#endif
+
+static int __cpuinit tegra30_idle_lp2(struct cpuidle_device *dev,
+				      struct cpuidle_driver *drv,
+				      int index)
+{
+	u32 cpu = is_smp() ? cpu_logical_map(dev->cpu) : dev->cpu;
+	bool entered_lp2 = false;
+	bool last_cpu;
+
+	local_fiq_disable();
+
+	last_cpu = tegra_set_cpu_in_lp2(cpu);
+	cpu_pm_enter();
+
+	if (cpu == 0) {
+		if (last_cpu)
+			entered_lp2 = tegra30_cpu_cluster_power_down(dev, drv,
+								     index);
+		else
+			cpu_do_idle();
+	} else {
+		entered_lp2 = tegra30_cpu_core_power_down(dev, drv, index);
+	}
+
+	cpu_pm_exit();
+	tegra_clear_cpu_in_lp2(cpu);
+
+	local_fiq_enable();
+
+	smp_rmb();
+
+	return (entered_lp2) ? index : 0;
+}
+#endif
+
+int __init tegra30_cpuidle_init(void)
+{
+	int ret;
+	unsigned int cpu;
+	struct cpuidle_device *dev;
+	struct cpuidle_driver *drv = &tegra_idle_driver;
+
+#ifdef CONFIG_PM_SLEEP
+	tegra_tear_down_cpu = tegra30_tear_down_cpu;
+#endif
+
+	ret = cpuidle_register_driver(&tegra_idle_driver);
+	if (ret) {
+		pr_err("CPUidle driver registration failed\n");
+		return ret;
+	}
+
+	for_each_possible_cpu(cpu) {
+		dev = &per_cpu(tegra_idle_device, cpu);
+		dev->cpu = cpu;
+
+		dev->state_count = drv->state_count;
+		ret = cpuidle_register_device(dev);
+		if (ret) {
+			pr_err("CPU%u: CPUidle device registration failed\n",
+				cpu);
+			return ret;
+		}
+	}
+	return 0;
+}
diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c
index 566e2f8..d065139 100644
--- a/arch/arm/mach-tegra/cpuidle.c
+++ b/arch/arm/mach-tegra/cpuidle.c
@@ -23,85 +23,26 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/cpu.h>
-#include <linux/cpuidle.h>
-#include <linux/hrtimer.h>
 
-#include <asm/proc-fns.h>
-
-#include <mach/iomap.h>
-
-static int tegra_idle_enter_lp3(struct cpuidle_device *dev,
-				struct cpuidle_driver *drv, int index);
-
-struct cpuidle_driver tegra_idle_driver = {
-	.name = "tegra_idle",
-	.owner = THIS_MODULE,
-	.state_count = 1,
-	.states = {
-		[0] = {
-			.enter			= tegra_idle_enter_lp3,
-			.exit_latency		= 10,
-			.target_residency	= 10,
-			.power_usage		= 600,
-			.flags			= CPUIDLE_FLAG_TIME_VALID,
-			.name			= "LP3",
-			.desc			= "CPU flow-controlled",
-		},
-	},
-};
-
-static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device);
-
-static int tegra_idle_enter_lp3(struct cpuidle_device *dev,
-	struct cpuidle_driver *drv, int index)
-{
-	ktime_t enter, exit;
-	s64 us;
-
-	local_irq_disable();
-	local_fiq_disable();
-
-	enter = ktime_get();
-
-	cpu_do_idle();
-
-	exit = ktime_sub(ktime_get(), enter);
-	us = ktime_to_us(exit);
-
-	local_fiq_enable();
-	local_irq_enable();
-
-	dev->last_residency = us;
-
-	return index;
-}
+#include "fuse.h"
+#include "cpuidle.h"
 
 static int __init tegra_cpuidle_init(void)
 {
 	int ret;
-	unsigned int cpu;
-	struct cpuidle_device *dev;
-	struct cpuidle_driver *drv = &tegra_idle_driver;
 
-	ret = cpuidle_register_driver(&tegra_idle_driver);
-	if (ret) {
-		pr_err("CPUidle driver registration failed\n");
-		return ret;
+	switch (tegra_chip_id) {
+	case TEGRA20:
+		ret = tegra20_cpuidle_init();
+		break;
+	case TEGRA30:
+		ret = tegra30_cpuidle_init();
+		break;
+	default:
+		ret = -ENODEV;
+		break;
 	}
 
-	for_each_possible_cpu(cpu) {
-		dev = &per_cpu(tegra_idle_device, cpu);
-		dev->cpu = cpu;
-
-		dev->state_count = drv->state_count;
-		ret = cpuidle_register_device(dev);
-		if (ret) {
-			pr_err("CPU%u: CPUidle device registration failed\n",
-				cpu);
-			return ret;
-		}
-	}
-	return 0;
+	return ret;
 }
 device_initcall(tegra_cpuidle_init);
diff --git a/arch/arm/mach-tegra/cpuidle.h b/arch/arm/mach-tegra/cpuidle.h
new file mode 100644
index 0000000..496204d
--- /dev/null
+++ b/arch/arm/mach-tegra/cpuidle.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MACH_TEGRA_CPUIDLE_H
+#define __MACH_TEGRA_CPUIDLE_H
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+int tegra20_cpuidle_init(void);
+#else
+static inline int tegra20_cpuidle_init(void) { return -ENODEV; }
+#endif
+
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+int tegra30_cpuidle_init(void);
+#else
+static inline int tegra30_cpuidle_init(void) { return -ENODEV; }
+#endif
+
+#endif
diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c
index f07488e..a2250dd 100644
--- a/arch/arm/mach-tegra/flowctrl.c
+++ b/arch/arm/mach-tegra/flowctrl.c
@@ -21,10 +21,10 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-
-#include <mach/iomap.h>
+#include <linux/cpumask.h>
 
 #include "flowctrl.h"
+#include "iomap.h"
 
 u8 flowctrl_offset_halt_cpu[] = {
 	FLOW_CTRL_HALT_CPU0_EVENTS,
@@ -51,6 +51,14 @@ static void flowctrl_update(u8 offset, u32 value)
 	readl_relaxed(addr);
 }
 
+u32 flowctrl_read_cpu_csr(unsigned int cpuid)
+{
+	u8 offset = flowctrl_offset_cpu_csr[cpuid];
+	void __iomem *addr = IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + offset;
+
+	return readl(addr);
+}
+
 void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value)
 {
 	return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value);
@@ -60,3 +68,41 @@ void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value)
 {
 	return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value);
 }
+
+void flowctrl_cpu_suspend_enter(unsigned int cpuid)
+{
+	unsigned int reg;
+	int i;
+
+	reg = flowctrl_read_cpu_csr(cpuid);
+	reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;	/* clear wfe bitmap */
+	reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP;	/* clear wfi bitmap */
+	reg |= FLOW_CTRL_CSR_INTR_FLAG;			/* clear intr flag */
+	reg |= FLOW_CTRL_CSR_EVENT_FLAG;		/* clear event flag */
+	reg |= TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 << cpuid;	/* pwr gating on wfi */
+	reg |= FLOW_CTRL_CSR_ENABLE;			/* pwr gating */
+	flowctrl_write_cpu_csr(cpuid, reg);
+
+	for (i = 0; i < num_possible_cpus(); i++) {
+		if (i == cpuid)
+			continue;
+		reg = flowctrl_read_cpu_csr(i);
+		reg |= FLOW_CTRL_CSR_EVENT_FLAG;
+		reg |= FLOW_CTRL_CSR_INTR_FLAG;
+		flowctrl_write_cpu_csr(i, reg);
+	}
+}
+
+void flowctrl_cpu_suspend_exit(unsigned int cpuid)
+{
+	unsigned int reg;
+
+	/* Disable powergating via flow controller for CPU0 */
+	reg = flowctrl_read_cpu_csr(cpuid);
+	reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;	/* clear wfe bitmap */
+	reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP;	/* clear wfi bitmap */
+	reg &= ~FLOW_CTRL_CSR_ENABLE;			/* clear enable */
+	reg |= FLOW_CTRL_CSR_INTR_FLAG;			/* clear intr */
+	reg |= FLOW_CTRL_CSR_EVENT_FLAG;		/* clear event */
+	flowctrl_write_cpu_csr(cpuid, reg);
+}
diff --git a/arch/arm/mach-tegra/flowctrl.h b/arch/arm/mach-tegra/flowctrl.h
index 1942817..0798dec 100644
--- a/arch/arm/mach-tegra/flowctrl.h
+++ b/arch/arm/mach-tegra/flowctrl.h
@@ -34,9 +34,17 @@
 #define FLOW_CTRL_HALT_CPU1_EVENTS	0x14
 #define FLOW_CTRL_CPU1_CSR		0x18
 
+#define TEGRA30_FLOW_CTRL_CSR_WFI_CPU0		(1 << 8)
+#define TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP	(0xF << 4)
+#define TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP	(0xF << 8)
+
 #ifndef __ASSEMBLY__
+u32 flowctrl_read_cpu_csr(unsigned int cpuid);
 void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value);
 void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value);
+
+void flowctrl_cpu_suspend_enter(unsigned int cpuid);
+void flowctrl_cpu_suspend_exit(unsigned int cpuid);
 #endif
 
 #endif
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
index 0b7db17..8121742 100644
--- a/arch/arm/mach-tegra/fuse.c
+++ b/arch/arm/mach-tegra/fuse.c
@@ -21,22 +21,28 @@
 #include <linux/io.h>
 #include <linux/export.h>
 
-#include <mach/iomap.h>
-
 #include "fuse.h"
+#include "iomap.h"
 #include "apbio.h"
 
 #define FUSE_UID_LOW		0x108
 #define FUSE_UID_HIGH		0x10c
 #define FUSE_SKU_INFO		0x110
-#define FUSE_SPARE_BIT		0x200
+
+#define TEGRA20_FUSE_SPARE_BIT		0x200
+#define TEGRA30_FUSE_SPARE_BIT		0x244
 
 int tegra_sku_id;
 int tegra_cpu_process_id;
 int tegra_core_process_id;
 int tegra_chip_id;
+int tegra_cpu_speedo_id;		/* only exist in Tegra30 and later */
+int tegra_soc_speedo_id;
 enum tegra_revision tegra_revision;
 
+static int tegra_fuse_spare_bit;
+static void (*tegra_init_speedo_data)(void);
+
 /* The BCT to use at boot is specified by board straps that can be read
  * through a APB misc register and decoded. 2 bits, i.e. 4 possible BCTs.
  */
@@ -57,14 +63,14 @@ static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
 	[TEGRA_REVISION_A04]     = "A04",
 };
 
-static inline u32 tegra_fuse_readl(unsigned long offset)
+u32 tegra_fuse_readl(unsigned long offset)
 {
 	return tegra_apb_readl(TEGRA_FUSE_BASE + offset);
 }
 
-static inline bool get_spare_fuse(int bit)
+bool tegra_spare_fuse(int bit)
 {
-	return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4);
+	return tegra_fuse_readl(tegra_fuse_spare_bit + bit * 4);
 }
 
 static enum tegra_revision tegra_get_revision(u32 id)
@@ -78,7 +84,7 @@ static enum tegra_revision tegra_get_revision(u32 id)
 		return TEGRA_REVISION_A02;
 	case 3:
 		if (tegra_chip_id == TEGRA20 &&
-			(get_spare_fuse(18) || get_spare_fuse(19)))
+			(tegra_spare_fuse(18) || tegra_spare_fuse(19)))
 			return TEGRA_REVISION_A03p;
 		else
 			return TEGRA_REVISION_A03;
@@ -89,6 +95,16 @@ static enum tegra_revision tegra_get_revision(u32 id)
 	}
 }
 
+static void tegra_get_process_id(void)
+{
+	u32 reg;
+
+	reg = tegra_fuse_readl(tegra_fuse_spare_bit);
+	tegra_cpu_process_id = (reg >> 6) & 3;
+	reg = tegra_fuse_readl(tegra_fuse_spare_bit);
+	tegra_core_process_id = (reg >> 12) & 3;
+}
+
 void tegra_init_fuse(void)
 {
 	u32 id;
@@ -100,19 +116,29 @@ void tegra_init_fuse(void)
 	reg = tegra_fuse_readl(FUSE_SKU_INFO);
 	tegra_sku_id = reg & 0xFF;
 
-	reg = tegra_fuse_readl(FUSE_SPARE_BIT);
-	tegra_cpu_process_id = (reg >> 6) & 3;
-
-	reg = tegra_fuse_readl(FUSE_SPARE_BIT);
-	tegra_core_process_id = (reg >> 12) & 3;
-
 	reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT);
 	tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT;
 
 	id = readl_relaxed(IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804);
 	tegra_chip_id = (id >> 8) & 0xff;
 
+	switch (tegra_chip_id) {
+	case TEGRA20:
+		tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT;
+		tegra_init_speedo_data = &tegra20_init_speedo_data;
+		break;
+	case TEGRA30:
+		tegra_fuse_spare_bit = TEGRA30_FUSE_SPARE_BIT;
+		tegra_init_speedo_data = &tegra30_init_speedo_data;
+		break;
+	default:
+		pr_warn("Tegra: unknown chip id %d\n", tegra_chip_id);
+		tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT;
+		tegra_init_speedo_data = &tegra_get_process_id;
+	}
+
 	tegra_revision = tegra_get_revision(id);
+	tegra_init_speedo_data();
 
 	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 d2107b2..ff1383d 100644
--- a/arch/arm/mach-tegra/fuse.h
+++ b/arch/arm/mach-tegra/fuse.h
@@ -42,11 +42,27 @@ extern int tegra_sku_id;
 extern int tegra_cpu_process_id;
 extern int tegra_core_process_id;
 extern int tegra_chip_id;
+extern int tegra_cpu_speedo_id;		/* only exist in Tegra30 and later */
+extern int tegra_soc_speedo_id;
 extern enum tegra_revision tegra_revision;
 
 extern int tegra_bct_strapping;
 
 unsigned long long tegra_chip_uid(void);
 void tegra_init_fuse(void);
+bool tegra_spare_fuse(int bit);
+u32 tegra_fuse_readl(unsigned long offset);
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+void tegra20_init_speedo_data(void);
+#else
+static inline void tegra20_init_speedo_data(void) {}
+#endif
+
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+void tegra30_init_speedo_data(void);
+#else
+static inline void tegra30_init_speedo_data(void) {}
+#endif
 
 #endif
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
index 6addc78..4a317fa 100644
--- a/arch/arm/mach-tegra/headsmp.S
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -2,10 +2,11 @@
 #include <linux/init.h>
 
 #include <asm/cache.h>
-
-#include <mach/iomap.h>
+#include <asm/asm-offsets.h>
+#include <asm/hardware/cache-l2x0.h>
 
 #include "flowctrl.h"
+#include "iomap.h"
 #include "reset.h"
 #include "sleep.h"
 
@@ -69,6 +70,64 @@ ENTRY(tegra_secondary_startup)
         b       secondary_startup
 ENDPROC(tegra_secondary_startup)
 
+#ifdef CONFIG_PM_SLEEP
+/*
+ *	tegra_resume
+ *
+ *	  CPU boot vector when restarting the a CPU following
+ *	  an LP2 transition. Also branched to by LP0 and LP1 resume after
+ *	  re-enabling sdram.
+ */
+ENTRY(tegra_resume)
+	bl	v7_invalidate_l1
+	/* Enable coresight */
+	mov32	r0, 0xC5ACCE55
+	mcr	p14, 0, r0, c7, c12, 6
+
+	cpu_id	r0
+	cmp	r0, #0				@ CPU0?
+	bne	cpu_resume			@ no
+
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+	/* Are we on Tegra20? */
+	mov32	r6, TEGRA_APB_MISC_BASE
+	ldr	r0, [r6, #APB_MISC_GP_HIDREV]
+	and	r0, r0, #0xff00
+	cmp	r0, #(0x20 << 8)
+	beq	1f				@ Yes
+	/* Clear the flow controller flags for this CPU. */
+	mov32	r2, TEGRA_FLOW_CTRL_BASE + FLOW_CTRL_CPU0_CSR	@ CPU0 CSR
+	ldr	r1, [r2]
+	/* Clear event & intr flag */
+	orr	r1, r1, \
+		#FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
+	movw	r0, #0x0FFD	@ enable, cluster_switch, immed, & bitmaps
+	bic	r1, r1, r0
+	str	r1, [r2]
+1:
+#endif
+
+#ifdef CONFIG_HAVE_ARM_SCU
+	/* enable SCU */
+	mov32	r0, TEGRA_ARM_PERIF_BASE
+	ldr	r1, [r0]
+	orr	r1, r1, #1
+	str	r1, [r0]
+#endif
+
+	/* L2 cache resume & re-enable */
+	l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr
+
+	b	cpu_resume
+ENDPROC(tegra_resume)
+#endif
+
+#ifdef CONFIG_CACHE_L2X0
+	.globl	l2x0_saved_regs_addr
+l2x0_saved_regs_addr:
+	.long	0
+#endif
+
 	.align L1_CACHE_SHIFT
 ENTRY(__tegra_cpu_reset_handler_start)
 
@@ -122,6 +181,17 @@ ENTRY(__tegra_cpu_reset_handler)
 1:
 #endif
 
+	/* Waking up from LP2? */
+	ldr	r9, [r12, #RESET_DATA(MASK_LP2)]
+	tst	r9, r11				@ if in_lp2
+	beq	__is_not_lp2
+	ldr	lr, [r12, #RESET_DATA(STARTUP_LP2)]
+	cmp	lr, #0
+	bleq	__die				@ no LP2 startup handler
+	bx	lr
+
+__is_not_lp2:
+
 #ifdef CONFIG_SMP
 	/*
 	 * Can only be secondary boot (initial or hotplug) but CPU 0
diff --git a/arch/arm/mach-tegra/include/mach/debug-macro.S b/arch/arm/mach-tegra/include/mach/debug-macro.S
deleted file mode 100644
index 8ce0661..0000000
--- a/arch/arm/mach-tegra/include/mach/debug-macro.S
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/debug-macro.S
- *
- * Copyright (C) 2010,2011 Google, Inc.
- * Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *	Erik Gilling <konkers@google.com>
- *	Doug Anderson <dianders@chromium.org>
- *	Stephen Warren <swarren@nvidia.com>
- *
- * Portions based on mach-omap2's debug-macro.S
- * Copyright (C) 1994-1999 Russell King
- *
- * 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/serial_reg.h>
-
-#include <mach/iomap.h>
-#include <mach/irammap.h>
-
-		.macro  addruart, rp, rv, tmp
-		adr	\rp, 99f		@ actual addr of 99f
-		ldr	\rv, [\rp]		@ linked addr is stored there
-		sub	\rv, \rv, \rp		@ offset between the two
-		ldr	\rp, [\rp, #4]		@ linked tegra_uart_config
-		sub	\tmp, \rp, \rv		@ actual tegra_uart_config
-		ldr	\rp, [\tmp]		@ Load tegra_uart_config
-		cmp	\rp, #1			@ needs intitialization?
-		bne	100f			@ no; go load the addresses
-		mov	\rv, #0			@ yes; record init is done
-		str	\rv, [\tmp]
-		mov	\rp, #TEGRA_IRAM_BASE	@ See if cookie is in IRAM
-		ldr	\rv, [\rp, #TEGRA_IRAM_DEBUG_UART_OFFSET]
-		movw	\rp, #TEGRA_IRAM_DEBUG_UART_COOKIE & 0xffff
-		movt	\rp, #TEGRA_IRAM_DEBUG_UART_COOKIE >> 16
-		cmp	\rv, \rp		@ Cookie present?
-		bne	100f			@ No, use default UART
-		mov	\rp, #TEGRA_IRAM_BASE	@ Load UART address from IRAM
-		ldr	\rv, [\rp, #TEGRA_IRAM_DEBUG_UART_OFFSET + 4]
-		str	\rv, [\tmp, #4]		@ Store in tegra_uart_phys
-		sub	\rv, \rv, #IO_APB_PHYS	@ Calculate virt address
-		add	\rv, \rv, #IO_APB_VIRT
-		str	\rv, [\tmp, #8]		@ Store in tegra_uart_virt
-		b	100f
-
-		.align
-99:		.word	.
-		.word	tegra_uart_config
-		.ltorg
-
-100:		ldr	\rp, [\tmp, #4]		@ Load tegra_uart_phys
-		ldr	\rv, [\tmp, #8]		@ Load tegra_uart_virt
-		.endm
-
-#define UART_SHIFT 2
-
-/*
- * Code below is swiped from <asm/hardware/debug-8250.S>, but add an extra
- * check to make sure that we aren't in the CONFIG_TEGRA_DEBUG_UART_NONE case.
- * We use the fact that all 5 valid UART addresses all have something in the
- * 2nd-to-lowest byte.
- */
-
-		.macro	senduart, rd, rx
-		tst	\rx, #0x0000ff00
-		strneb	\rd, [\rx, #UART_TX << UART_SHIFT]
-1001:
-		.endm
-
-		.macro	busyuart, rd, rx
-		tst	\rx, #0x0000ff00
-		beq	1002f
-1001:		ldrb	\rd, [\rx, #UART_LSR << UART_SHIFT]
-		and	\rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
-		teq	\rd, #UART_LSR_TEMT | UART_LSR_THRE
-		bne	1001b
-1002:
-		.endm
-
-		.macro	waituart, rd, rx
-#ifdef FLOW_CONTROL
-		tst	\rx, #0x0000ff00
-		beq	1002f
-1001:		ldrb	\rd, [\rx, #UART_MSR << UART_SHIFT]
-		tst	\rd, #UART_MSR_CTS
-		beq	1001b
-1002:
-#endif
-		.endm
diff --git a/arch/arm/mach-tegra/include/mach/dma.h b/arch/arm/mach-tegra/include/mach/dma.h
deleted file mode 100644
index 3081cc6..0000000
--- a/arch/arm/mach-tegra/include/mach/dma.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/dma.h
- *
- * Copyright (c) 2008-2009, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-#ifndef __MACH_TEGRA_DMA_H
-#define __MACH_TEGRA_DMA_H
-
-#include <linux/list.h>
-
-#define TEGRA_DMA_REQ_SEL_CNTR			0
-#define TEGRA_DMA_REQ_SEL_I2S_2			1
-#define TEGRA_DMA_REQ_SEL_I2S_1			2
-#define TEGRA_DMA_REQ_SEL_SPD_I			3
-#define TEGRA_DMA_REQ_SEL_UI_I			4
-#define TEGRA_DMA_REQ_SEL_MIPI			5
-#define TEGRA_DMA_REQ_SEL_I2S2_2		6
-#define TEGRA_DMA_REQ_SEL_I2S2_1		7
-#define TEGRA_DMA_REQ_SEL_UARTA			8
-#define TEGRA_DMA_REQ_SEL_UARTB			9
-#define TEGRA_DMA_REQ_SEL_UARTC			10
-#define TEGRA_DMA_REQ_SEL_SPI			11
-#define TEGRA_DMA_REQ_SEL_AC97			12
-#define TEGRA_DMA_REQ_SEL_ACMODEM		13
-#define TEGRA_DMA_REQ_SEL_SL4B			14
-#define TEGRA_DMA_REQ_SEL_SL2B1			15
-#define TEGRA_DMA_REQ_SEL_SL2B2			16
-#define TEGRA_DMA_REQ_SEL_SL2B3			17
-#define TEGRA_DMA_REQ_SEL_SL2B4			18
-#define TEGRA_DMA_REQ_SEL_UARTD			19
-#define TEGRA_DMA_REQ_SEL_UARTE			20
-#define TEGRA_DMA_REQ_SEL_I2C			21
-#define TEGRA_DMA_REQ_SEL_I2C2			22
-#define TEGRA_DMA_REQ_SEL_I2C3			23
-#define TEGRA_DMA_REQ_SEL_DVC_I2C		24
-#define TEGRA_DMA_REQ_SEL_OWR			25
-#define TEGRA_DMA_REQ_SEL_INVALID		31
-
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/include/mach/iomap.h
deleted file mode 100644
index fee3a94..0000000
--- a/arch/arm/mach-tegra/include/mach/iomap.h
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/iomap.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *	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_IOMAP_H
-#define __MACH_TEGRA_IOMAP_H
-
-#include <asm/sizes.h>
-
-#define TEGRA_IRAM_BASE			0x40000000
-#define TEGRA_IRAM_SIZE			SZ_256K
-
-#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
-
-#define TEGRA_SECONDARY_ICTLR_BASE	0x60004100
-#define TEGRA_SECONDARY_ICTLR_SIZE	SZ_64
-
-#define TEGRA_TERTIARY_ICTLR_BASE	0x60004200
-#define TEGRA_TERTIARY_ICTLR_SIZE	SZ_64
-
-#define TEGRA_QUATERNARY_ICTLR_BASE	0x60004300
-#define TEGRA_QUATERNARY_ICTLR_SIZE	SZ_64
-
-#define TEGRA_QUINARY_ICTLR_BASE	0x60004400
-#define TEGRA_QUINARY_ICTLR_SIZE	SZ_64
-
-#define TEGRA_TMR1_BASE			0x60005000
-#define TEGRA_TMR1_SIZE			SZ_8
-
-#define TEGRA_TMR2_BASE			0x60005008
-#define TEGRA_TMR2_SIZE			SZ_8
-
-#define TEGRA_TMRUS_BASE		0x60005010
-#define TEGRA_TMRUS_SIZE		SZ_64
-
-#define TEGRA_TMR3_BASE			0x60005050
-#define TEGRA_TMR3_SIZE			SZ_8
-
-#define TEGRA_TMR4_BASE			0x60005058
-#define TEGRA_TMR4_SIZE			SZ_8
-
-#define TEGRA_CLK_RESET_BASE		0x60006000
-#define TEGRA_CLK_RESET_SIZE		SZ_4K
-
-#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
-
-#define TEGRA_UARTB_BASE		0x70006040
-#define TEGRA_UARTB_SIZE		SZ_64
-
-#define TEGRA_UARTC_BASE		0x70006200
-#define TEGRA_UARTC_SIZE		SZ_256
-
-#define TEGRA_UARTD_BASE		0x70006300
-#define TEGRA_UARTD_SIZE		SZ_256
-
-#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_CSITE_BASE		0x70040000
-#define TEGRA_CSITE_SIZE		SZ_256K
-
-#define TEGRA_USB_BASE			0xC5000000
-#define TEGRA_USB_SIZE			SZ_16K
-
-#define TEGRA_USB2_BASE			0xC5004000
-#define TEGRA_USB2_SIZE			SZ_16K
-
-#define TEGRA_USB3_BASE			0xC5008000
-#define TEGRA_USB3_SIZE			SZ_16K
-
-#define TEGRA_SDMMC1_BASE		0xC8000000
-#define TEGRA_SDMMC1_SIZE		SZ_512
-
-#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
-
-#if defined(CONFIG_TEGRA_DEBUG_UART_NONE)
-# define TEGRA_DEBUG_UART_BASE 0
-#elif defined(CONFIG_TEGRA_DEBUG_UARTA)
-# define TEGRA_DEBUG_UART_BASE TEGRA_UARTA_BASE
-#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
-# define TEGRA_DEBUG_UART_BASE TEGRA_UARTB_BASE
-#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
-# define TEGRA_DEBUG_UART_BASE TEGRA_UARTC_BASE
-#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
-# define TEGRA_DEBUG_UART_BASE TEGRA_UARTD_BASE
-#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
-# define TEGRA_DEBUG_UART_BASE TEGRA_UARTE_BASE
-#endif
-
-/* On TEGRA, many peripherals are very closely packed in
- * two 256MB io windows (that actually only use about 64KB
- * at the start of each).
- *
- * We will just map the first 1MB of each window (to minimize
- * pt entries needed) and provide a macro to transform physical
- * io addresses to an appropriate void __iomem *.
- *
- */
-
-#define IO_IRAM_PHYS	0x40000000
-#define IO_IRAM_VIRT	IOMEM(0xFE400000)
-#define IO_IRAM_SIZE	SZ_256K
-
-#define IO_CPU_PHYS     0x50040000
-#define IO_CPU_VIRT     IOMEM(0xFE000000)
-#define IO_CPU_SIZE	SZ_16K
-
-#define IO_PPSB_PHYS	0x60000000
-#define IO_PPSB_VIRT	IOMEM(0xFE200000)
-#define IO_PPSB_SIZE	SZ_1M
-
-#define IO_APB_PHYS	0x70000000
-#define IO_APB_VIRT	IOMEM(0xFE300000)
-#define IO_APB_SIZE	SZ_1M
-
-#define TEGRA_PCIE_BASE		0x80000000
-#define TEGRA_PCIE_IO_BASE	(TEGRA_PCIE_BASE + SZ_4M)
-
-#define IO_TO_VIRT_BETWEEN(p, st, sz)	((p) >= (st) && (p) < ((st) + (sz)))
-#define IO_TO_VIRT_XLATE(p, pst, vst)	(((p) - (pst) + (vst)))
-
-#define IO_TO_VIRT(n) ( \
-	IO_TO_VIRT_BETWEEN((n), IO_PPSB_PHYS, IO_PPSB_SIZE) ?		\
-		IO_TO_VIRT_XLATE((n), IO_PPSB_PHYS, IO_PPSB_VIRT) :	\
-	IO_TO_VIRT_BETWEEN((n), IO_APB_PHYS, IO_APB_SIZE) ?		\
-		IO_TO_VIRT_XLATE((n), IO_APB_PHYS, IO_APB_VIRT) :	\
-	IO_TO_VIRT_BETWEEN((n), IO_CPU_PHYS, IO_CPU_SIZE) ?		\
-		IO_TO_VIRT_XLATE((n), IO_CPU_PHYS, IO_CPU_VIRT) :	\
-	IO_TO_VIRT_BETWEEN((n), IO_IRAM_PHYS, IO_IRAM_SIZE) ?		\
-		IO_TO_VIRT_XLATE((n), IO_IRAM_PHYS, IO_IRAM_VIRT) :	\
-	NULL)
-
-#define IO_ADDRESS(n) (IO_TO_VIRT(n))
-
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/irammap.h b/arch/arm/mach-tegra/include/mach/irammap.h
deleted file mode 100644
index 0cbe632..0000000
--- a/arch/arm/mach-tegra/include/mach/irammap.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __MACH_TEGRA_IRAMMAP_H
-#define __MACH_TEGRA_IRAMMAP_H
-
-#include <asm/sizes.h>
-
-/* The first 1K of IRAM is permanently reserved for the CPU reset handler */
-#define TEGRA_IRAM_RESET_HANDLER_OFFSET	0
-#define TEGRA_IRAM_RESET_HANDLER_SIZE	SZ_1K
-
-/*
- * These locations are written to by uncompress.h, and read by debug-macro.S.
- * The first word holds the cookie value if the data is valid. The second
- * word holds the UART physical address.
- */
-#define TEGRA_IRAM_DEBUG_UART_OFFSET	SZ_1K
-#define TEGRA_IRAM_DEBUG_UART_SIZE	8
-#define TEGRA_IRAM_DEBUG_UART_COOKIE	0x55415254
-
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/irqs.h b/arch/arm/mach-tegra/include/mach/irqs.h
deleted file mode 100644
index aad1a2c..0000000
--- a/arch/arm/mach-tegra/include/mach/irqs.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/irqs.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *	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_IRQS_H
-#define __MACH_TEGRA_IRQS_H
-
-#define INT_GIC_BASE			0
-
-#define IRQ_LOCALTIMER                  29
-
-/* Primary Interrupt Controller */
-#define INT_PRI_BASE			(INT_GIC_BASE + 32)
-#define INT_TMR1			(INT_PRI_BASE + 0)
-#define INT_TMR2			(INT_PRI_BASE + 1)
-#define INT_RTC				(INT_PRI_BASE + 2)
-#define INT_I2S2			(INT_PRI_BASE + 3)
-#define INT_SHR_SEM_INBOX_IBF		(INT_PRI_BASE + 4)
-#define INT_SHR_SEM_INBOX_IBE		(INT_PRI_BASE + 5)
-#define INT_SHR_SEM_OUTBOX_IBF		(INT_PRI_BASE + 6)
-#define INT_SHR_SEM_OUTBOX_IBE		(INT_PRI_BASE + 7)
-#define INT_VDE_UCQ_ERROR		(INT_PRI_BASE + 8)
-#define INT_VDE_SYNC_TOKEN		(INT_PRI_BASE + 9)
-#define INT_VDE_BSE_V			(INT_PRI_BASE + 10)
-#define INT_VDE_BSE_A			(INT_PRI_BASE + 11)
-#define INT_VDE_SXE			(INT_PRI_BASE + 12)
-#define INT_I2S1			(INT_PRI_BASE + 13)
-#define INT_SDMMC1			(INT_PRI_BASE + 14)
-#define INT_SDMMC2			(INT_PRI_BASE + 15)
-#define INT_XIO				(INT_PRI_BASE + 16)
-#define INT_VDE				(INT_PRI_BASE + 17)
-#define INT_AVP_UCQ			(INT_PRI_BASE + 18)
-#define INT_SDMMC3			(INT_PRI_BASE + 19)
-#define INT_USB				(INT_PRI_BASE + 20)
-#define INT_USB2			(INT_PRI_BASE + 21)
-#define INT_PRI_RES_22			(INT_PRI_BASE + 22)
-#define INT_EIDE			(INT_PRI_BASE + 23)
-#define INT_NANDFLASH			(INT_PRI_BASE + 24)
-#define INT_VCP				(INT_PRI_BASE + 25)
-#define INT_APB_DMA			(INT_PRI_BASE + 26)
-#define INT_AHB_DMA			(INT_PRI_BASE + 27)
-#define INT_GNT_0			(INT_PRI_BASE + 28)
-#define INT_GNT_1			(INT_PRI_BASE + 29)
-#define INT_OWR				(INT_PRI_BASE + 30)
-#define INT_SDMMC4			(INT_PRI_BASE + 31)
-
-/* Secondary Interrupt Controller */
-#define INT_SEC_BASE			(INT_PRI_BASE + 32)
-#define INT_GPIO1			(INT_SEC_BASE + 0)
-#define INT_GPIO2			(INT_SEC_BASE + 1)
-#define INT_GPIO3			(INT_SEC_BASE + 2)
-#define INT_GPIO4			(INT_SEC_BASE + 3)
-#define INT_UARTA			(INT_SEC_BASE + 4)
-#define INT_UARTB			(INT_SEC_BASE + 5)
-#define INT_I2C				(INT_SEC_BASE + 6)
-#define INT_SPI				(INT_SEC_BASE + 7)
-#define INT_TWC				(INT_SEC_BASE + 8)
-#define INT_TMR3			(INT_SEC_BASE + 9)
-#define INT_TMR4			(INT_SEC_BASE + 10)
-#define INT_FLOW_RSM0			(INT_SEC_BASE + 11)
-#define INT_FLOW_RSM1			(INT_SEC_BASE + 12)
-#define INT_SPDIF			(INT_SEC_BASE + 13)
-#define INT_UARTC			(INT_SEC_BASE + 14)
-#define INT_MIPI			(INT_SEC_BASE + 15)
-#define INT_EVENTA			(INT_SEC_BASE + 16)
-#define INT_EVENTB			(INT_SEC_BASE + 17)
-#define INT_EVENTC			(INT_SEC_BASE + 18)
-#define INT_EVENTD			(INT_SEC_BASE + 19)
-#define INT_VFIR			(INT_SEC_BASE + 20)
-#define INT_DVC				(INT_SEC_BASE + 21)
-#define INT_SYS_STATS_MON		(INT_SEC_BASE + 22)
-#define INT_GPIO5			(INT_SEC_BASE + 23)
-#define INT_CPU0_PMU_INTR		(INT_SEC_BASE + 24)
-#define INT_CPU1_PMU_INTR		(INT_SEC_BASE + 25)
-#define INT_SEC_RES_26			(INT_SEC_BASE + 26)
-#define INT_S_LINK1			(INT_SEC_BASE + 27)
-#define INT_APB_DMA_COP			(INT_SEC_BASE + 28)
-#define INT_AHB_DMA_COP			(INT_SEC_BASE + 29)
-#define INT_DMA_TX			(INT_SEC_BASE + 30)
-#define INT_DMA_RX			(INT_SEC_BASE + 31)
-
-/* Tertiary Interrupt Controller */
-#define INT_TRI_BASE			(INT_SEC_BASE + 32)
-#define INT_HOST1X_COP_SYNCPT		(INT_TRI_BASE + 0)
-#define INT_HOST1X_MPCORE_SYNCPT	(INT_TRI_BASE + 1)
-#define INT_HOST1X_COP_GENERAL		(INT_TRI_BASE + 2)
-#define INT_HOST1X_MPCORE_GENERAL	(INT_TRI_BASE + 3)
-#define INT_MPE_GENERAL			(INT_TRI_BASE + 4)
-#define INT_VI_GENERAL			(INT_TRI_BASE + 5)
-#define INT_EPP_GENERAL			(INT_TRI_BASE + 6)
-#define INT_ISP_GENERAL			(INT_TRI_BASE + 7)
-#define INT_2D_GENERAL			(INT_TRI_BASE + 8)
-#define INT_DISPLAY_GENERAL		(INT_TRI_BASE + 9)
-#define INT_DISPLAY_B_GENERAL		(INT_TRI_BASE + 10)
-#define INT_HDMI			(INT_TRI_BASE + 11)
-#define INT_TVO_GENERAL			(INT_TRI_BASE + 12)
-#define INT_MC_GENERAL			(INT_TRI_BASE + 13)
-#define INT_EMC_GENERAL			(INT_TRI_BASE + 14)
-#define INT_TRI_RES_15			(INT_TRI_BASE + 15)
-#define INT_TRI_RES_16			(INT_TRI_BASE + 16)
-#define INT_AC97			(INT_TRI_BASE + 17)
-#define INT_SPI_2			(INT_TRI_BASE + 18)
-#define INT_SPI_3			(INT_TRI_BASE + 19)
-#define INT_I2C2			(INT_TRI_BASE + 20)
-#define INT_KBC				(INT_TRI_BASE + 21)
-#define INT_EXTERNAL_PMU		(INT_TRI_BASE + 22)
-#define INT_GPIO6			(INT_TRI_BASE + 23)
-#define INT_TVDAC			(INT_TRI_BASE + 24)
-#define INT_GPIO7			(INT_TRI_BASE + 25)
-#define INT_UARTD			(INT_TRI_BASE + 26)
-#define INT_UARTE			(INT_TRI_BASE + 27)
-#define INT_I2C3			(INT_TRI_BASE + 28)
-#define INT_SPI_4			(INT_TRI_BASE + 29)
-#define INT_TRI_RES_30			(INT_TRI_BASE + 30)
-#define INT_SW_RESERVED			(INT_TRI_BASE + 31)
-
-/* Quaternary Interrupt Controller */
-#define INT_QUAD_BASE			(INT_TRI_BASE + 32)
-#define INT_SNOR			(INT_QUAD_BASE + 0)
-#define INT_USB3			(INT_QUAD_BASE + 1)
-#define INT_PCIE_INTR			(INT_QUAD_BASE + 2)
-#define INT_PCIE_MSI			(INT_QUAD_BASE + 3)
-#define INT_QUAD_RES_4			(INT_QUAD_BASE + 4)
-#define INT_QUAD_RES_5			(INT_QUAD_BASE + 5)
-#define INT_QUAD_RES_6			(INT_QUAD_BASE + 6)
-#define INT_QUAD_RES_7			(INT_QUAD_BASE + 7)
-#define INT_APB_DMA_CH0			(INT_QUAD_BASE + 8)
-#define INT_APB_DMA_CH1			(INT_QUAD_BASE + 9)
-#define INT_APB_DMA_CH2			(INT_QUAD_BASE + 10)
-#define INT_APB_DMA_CH3			(INT_QUAD_BASE + 11)
-#define INT_APB_DMA_CH4			(INT_QUAD_BASE + 12)
-#define INT_APB_DMA_CH5			(INT_QUAD_BASE + 13)
-#define INT_APB_DMA_CH6			(INT_QUAD_BASE + 14)
-#define INT_APB_DMA_CH7			(INT_QUAD_BASE + 15)
-#define INT_APB_DMA_CH8			(INT_QUAD_BASE + 16)
-#define INT_APB_DMA_CH9			(INT_QUAD_BASE + 17)
-#define INT_APB_DMA_CH10		(INT_QUAD_BASE + 18)
-#define INT_APB_DMA_CH11		(INT_QUAD_BASE + 19)
-#define INT_APB_DMA_CH12		(INT_QUAD_BASE + 20)
-#define INT_APB_DMA_CH13		(INT_QUAD_BASE + 21)
-#define INT_APB_DMA_CH14		(INT_QUAD_BASE + 22)
-#define INT_APB_DMA_CH15		(INT_QUAD_BASE + 23)
-#define INT_QUAD_RES_24			(INT_QUAD_BASE + 24)
-#define INT_QUAD_RES_25			(INT_QUAD_BASE + 25)
-#define INT_QUAD_RES_26			(INT_QUAD_BASE + 26)
-#define INT_QUAD_RES_27			(INT_QUAD_BASE + 27)
-#define INT_QUAD_RES_28			(INT_QUAD_BASE + 28)
-#define INT_QUAD_RES_29			(INT_QUAD_BASE + 29)
-#define INT_QUAD_RES_30			(INT_QUAD_BASE + 30)
-#define INT_QUAD_RES_31			(INT_QUAD_BASE + 31)
-
-/* Tegra30 has 5 banks of 32 IRQs */
-#define INT_MAIN_NR			(32 * 5)
-#define INT_GPIO_BASE			(INT_PRI_BASE + INT_MAIN_NR)
-
-/* Tegra30 has 8 banks of 32 GPIOs */
-#define INT_GPIO_NR			(32 * 8)
-
-#define TEGRA_NR_IRQS			(INT_GPIO_BASE + INT_GPIO_NR)
-
-#define INT_BOARD_BASE			TEGRA_NR_IRQS
-#define NR_BOARD_IRQS			32
-
-#define NR_IRQS				(INT_BOARD_BASE + NR_BOARD_IRQS)
-
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/powergate.h b/arch/arm/mach-tegra/include/mach/powergate.h
index 4752b1a..06763fe 100644
--- a/arch/arm/mach-tegra/include/mach/powergate.h
+++ b/arch/arm/mach-tegra/include/mach/powergate.h
@@ -20,6 +20,8 @@
 #ifndef _MACH_TEGRA_POWERGATE_H_
 #define _MACH_TEGRA_POWERGATE_H_
 
+struct clk;
+
 #define TEGRA_POWERGATE_CPU	0
 #define TEGRA_POWERGATE_3D	1
 #define TEGRA_POWERGATE_VENC	2
diff --git a/arch/arm/mach-tegra/include/mach/tegra-ahb.h b/arch/arm/mach-tegra/include/mach/tegra-ahb.h
deleted file mode 100644
index e0f8c84..0000000
--- a/arch/arm/mach-tegra/include/mach/tegra-ahb.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * 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.
- */
-
-#ifndef __MACH_TEGRA_AHB_H__
-#define __MACH_TEGRA_AHB_H__
-
-extern int tegra_ahb_enable_smmu(struct device_node *ahb);
-
-#endif	/* __MACH_TEGRA_AHB_H__ */
diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h
index 937c4c5..485003f 100644
--- a/arch/arm/mach-tegra/include/mach/uncompress.h
+++ b/arch/arm/mach-tegra/include/mach/uncompress.h
@@ -28,8 +28,7 @@
 #include <linux/types.h>
 #include <linux/serial_reg.h>
 
-#include <mach/iomap.h>
-#include <mach/irammap.h>
+#include "../../iomap.h"
 
 #define BIT(x) (1 << (x))
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
@@ -52,17 +51,6 @@ static inline void flush(void)
 {
 }
 
-static inline void save_uart_address(void)
-{
-	u32 *buf = (u32 *)(TEGRA_IRAM_BASE + TEGRA_IRAM_DEBUG_UART_OFFSET);
-
-	if (uart) {
-		buf[0] = TEGRA_IRAM_DEBUG_UART_COOKIE;
-		buf[1] = (u32)uart;
-	} else
-		buf[0] = 0;
-}
-
 static const struct {
 	u32 base;
 	u32 reset_reg;
@@ -139,51 +127,19 @@ int auto_odmdata(void)
 }
 #endif
 
-#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH
-int auto_scratch(void)
-{
-	int i;
-
-	/*
-	 * Look for the first UART that:
-	 * a) Is not in reset.
-	 * b) Is clocked.
-	 * c) Has a 'D' in the scratchpad register.
-	 *
-	 * Note that on Tegra30, the first two conditions are required, since
-	 * if not true, accesses to the UART scratch register will hang.
-	 * Tegra20 doesn't have this issue.
-	 *
-	 * The intent is that the bootloader will tell the kernel which UART
-	 * to use by setting up those conditions. If nothing found, we'll fall
-	 * back to what's specified in TEGRA_DEBUG_UART_BASE.
-	 */
-	for (i = 0; i < ARRAY_SIZE(uarts); i++) {
-		if (!uart_clocked(i))
-			continue;
-
-		uart = (volatile u8 *)uarts[i].base;
-		if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D')
-			continue;
-
-		return i;
-	}
-
-	return -1;
-}
-#endif
-
 /*
  * Setup before decompression.  This is where we do UART selection for
  * earlyprintk and init the uart_base register.
  */
 static inline void arch_decomp_setup(void)
 {
-	int uart_id, auto_uart_id;
+	int uart_id;
 	volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
 	u32 chip, div;
 
-#if defined(CONFIG_TEGRA_DEBUG_UARTA)
+#if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
+	uart_id = auto_odmdata();
+#elif defined(CONFIG_TEGRA_DEBUG_UARTA)
 	uart_id = 0;
 #elif defined(CONFIG_TEGRA_DEBUG_UARTB)
 	uart_id = 1;
@@ -193,19 +149,7 @@ static inline void arch_decomp_setup(void)
 	uart_id = 3;
 #elif defined(CONFIG_TEGRA_DEBUG_UARTE)
 	uart_id = 4;
-#else
-	uart_id = -1;
-#endif
-
-#if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
-	auto_uart_id = auto_odmdata();
-#elif defined(CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH)
-	auto_uart_id = auto_scratch();
-#else
-	auto_uart_id = -1;
 #endif
-	if (auto_uart_id != -1)
-		uart_id = auto_uart_id;
 
 	if (uart_id < 0 || uart_id >= ARRAY_SIZE(uarts) ||
 	    !uart_clocked(uart_id))
@@ -213,7 +157,6 @@ static inline void arch_decomp_setup(void)
 	else
 		uart = (volatile u8 *)uarts[uart_id].base;
 
-	save_uart_address();
 	if (uart == NULL)
 		return;
 
diff --git a/arch/arm/mach-tegra/io.c b/arch/arm/mach-tegra/io.c
index 58b4baf..bb9c9c2 100644
--- a/arch/arm/mach-tegra/io.c
+++ b/arch/arm/mach-tegra/io.c
@@ -26,9 +26,9 @@
 
 #include <asm/page.h>
 #include <asm/mach/map.h>
-#include <mach/iomap.h>
 
 #include "board.h"
+#include "iomap.h"
 
 static struct map_desc tegra_io_desc[] __initdata = {
 	{
@@ -59,5 +59,6 @@ static struct map_desc tegra_io_desc[] __initdata = {
 
 void __init tegra_map_common_io(void)
 {
+	debug_ll_io_init();
 	iotable_init(tegra_io_desc, ARRAY_SIZE(tegra_io_desc));
 }
diff --git a/arch/arm/mach-tegra/iomap.h b/arch/arm/mach-tegra/iomap.h
new file mode 100644
index 0000000..db8be51
--- /dev/null
+++ b/arch/arm/mach-tegra/iomap.h
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *	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_IOMAP_H
+#define __MACH_TEGRA_IOMAP_H
+
+#include <asm/sizes.h>
+
+#define TEGRA_IRAM_BASE			0x40000000
+#define TEGRA_IRAM_SIZE			SZ_256K
+
+#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
+
+#define TEGRA_SECONDARY_ICTLR_BASE	0x60004100
+#define TEGRA_SECONDARY_ICTLR_SIZE	SZ_64
+
+#define TEGRA_TERTIARY_ICTLR_BASE	0x60004200
+#define TEGRA_TERTIARY_ICTLR_SIZE	SZ_64
+
+#define TEGRA_QUATERNARY_ICTLR_BASE	0x60004300
+#define TEGRA_QUATERNARY_ICTLR_SIZE	SZ_64
+
+#define TEGRA_QUINARY_ICTLR_BASE	0x60004400
+#define TEGRA_QUINARY_ICTLR_SIZE	SZ_64
+
+#define TEGRA_TMR1_BASE			0x60005000
+#define TEGRA_TMR1_SIZE			SZ_8
+
+#define TEGRA_TMR2_BASE			0x60005008
+#define TEGRA_TMR2_SIZE			SZ_8
+
+#define TEGRA_TMRUS_BASE		0x60005010
+#define TEGRA_TMRUS_SIZE		SZ_64
+
+#define TEGRA_TMR3_BASE			0x60005050
+#define TEGRA_TMR3_SIZE			SZ_8
+
+#define TEGRA_TMR4_BASE			0x60005058
+#define TEGRA_TMR4_SIZE			SZ_8
+
+#define TEGRA_CLK_RESET_BASE		0x60006000
+#define TEGRA_CLK_RESET_SIZE		SZ_4K
+
+#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
+
+#define TEGRA_UARTB_BASE		0x70006040
+#define TEGRA_UARTB_SIZE		SZ_64
+
+#define TEGRA_UARTC_BASE		0x70006200
+#define TEGRA_UARTC_SIZE		SZ_256
+
+#define TEGRA_UARTD_BASE		0x70006300
+#define TEGRA_UARTD_SIZE		SZ_256
+
+#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_CSITE_BASE		0x70040000
+#define TEGRA_CSITE_SIZE		SZ_256K
+
+#define TEGRA_USB_BASE			0xC5000000
+#define TEGRA_USB_SIZE			SZ_16K
+
+#define TEGRA_USB2_BASE			0xC5004000
+#define TEGRA_USB2_SIZE			SZ_16K
+
+#define TEGRA_USB3_BASE			0xC5008000
+#define TEGRA_USB3_SIZE			SZ_16K
+
+#define TEGRA_SDMMC1_BASE		0xC8000000
+#define TEGRA_SDMMC1_SIZE		SZ_512
+
+#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).
+ *
+ * We will just map the first 1MB of each window (to minimize
+ * pt entries needed) and provide a macro to transform physical
+ * io addresses to an appropriate void __iomem *.
+ *
+ */
+
+#define IO_IRAM_PHYS	0x40000000
+#define IO_IRAM_VIRT	IOMEM(0xFE400000)
+#define IO_IRAM_SIZE	SZ_256K
+
+#define IO_CPU_PHYS     0x50040000
+#define IO_CPU_VIRT     IOMEM(0xFE000000)
+#define IO_CPU_SIZE	SZ_16K
+
+#define IO_PPSB_PHYS	0x60000000
+#define IO_PPSB_VIRT	IOMEM(0xFE200000)
+#define IO_PPSB_SIZE	SZ_1M
+
+#define IO_APB_PHYS	0x70000000
+#define IO_APB_VIRT	IOMEM(0xFE300000)
+#define IO_APB_SIZE	SZ_1M
+
+#define TEGRA_PCIE_BASE		0x80000000
+#define TEGRA_PCIE_IO_BASE	(TEGRA_PCIE_BASE + SZ_4M)
+
+#define IO_TO_VIRT_BETWEEN(p, st, sz)	((p) >= (st) && (p) < ((st) + (sz)))
+#define IO_TO_VIRT_XLATE(p, pst, vst)	(((p) - (pst) + (vst)))
+
+#define IO_TO_VIRT(n) ( \
+	IO_TO_VIRT_BETWEEN((n), IO_PPSB_PHYS, IO_PPSB_SIZE) ?		\
+		IO_TO_VIRT_XLATE((n), IO_PPSB_PHYS, IO_PPSB_VIRT) :	\
+	IO_TO_VIRT_BETWEEN((n), IO_APB_PHYS, IO_APB_SIZE) ?		\
+		IO_TO_VIRT_XLATE((n), IO_APB_PHYS, IO_APB_VIRT) :	\
+	IO_TO_VIRT_BETWEEN((n), IO_CPU_PHYS, IO_CPU_SIZE) ?		\
+		IO_TO_VIRT_XLATE((n), IO_CPU_PHYS, IO_CPU_VIRT) :	\
+	IO_TO_VIRT_BETWEEN((n), IO_IRAM_PHYS, IO_IRAM_SIZE) ?		\
+		IO_TO_VIRT_XLATE((n), IO_IRAM_PHYS, IO_IRAM_VIRT) :	\
+	NULL)
+
+#define IO_ADDRESS(n) (IO_TO_VIRT(n))
+
+#endif
diff --git a/arch/arm/mach-tegra/irammap.h b/arch/arm/mach-tegra/irammap.h
new file mode 100644
index 0000000..501952a
--- /dev/null
+++ b/arch/arm/mach-tegra/irammap.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MACH_TEGRA_IRAMMAP_H
+#define __MACH_TEGRA_IRAMMAP_H
+
+#include <asm/sizes.h>
+
+/* The first 1K of IRAM is permanently reserved for the CPU reset handler */
+#define TEGRA_IRAM_RESET_HANDLER_OFFSET	0
+#define TEGRA_IRAM_RESET_HANDLER_SIZE	SZ_1K
+
+#endif
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index 2f5bd2d..b7886f1 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -25,9 +25,8 @@
 
 #include <asm/hardware/gic.h>
 
-#include <mach/iomap.h>
-
 #include "board.h"
+#include "iomap.h"
 
 #define ICTLR_CPU_IEP_VFIQ	0x08
 #define ICTLR_CPU_IEP_FIR	0x14
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index a8dba64..53d0858 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -37,11 +37,14 @@
 #include <asm/sizes.h>
 #include <asm/mach/pci.h>
 
-#include <mach/iomap.h>
 #include <mach/clk.h>
 #include <mach/powergate.h>
 
 #include "board.h"
+#include "iomap.h"
+
+/* Hack - need to parse this from DT */
+#define INT_PCIE_INTR 130
 
 /* register definitions */
 #define AFI_OFFSET	0x3800
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 81cb265..1b926df 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -24,8 +24,6 @@
 #include <asm/mach-types.h>
 #include <asm/smp_scu.h>
 
-#include <mach/clk.h>
-#include <mach/iomap.h>
 #include <mach/powergate.h>
 
 #include "fuse.h"
@@ -34,6 +32,7 @@
 #include "tegra_cpu_car.h"
 
 #include "common.h"
+#include "iomap.h"
 
 extern void tegra_secondary_startup(void);
 
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
new file mode 100644
index 0000000..1b11707
--- /dev/null
+++ b/arch/arm/mach-tegra/pm.c
@@ -0,0 +1,216 @@
+/*
+ * CPU complex suspend & resume functions for Tegra SoCs
+ *
+ * Copyright (c) 2009-2012, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/cpumask.h>
+#include <linux/delay.h>
+#include <linux/cpu_pm.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <asm/smp_plat.h>
+#include <asm/cacheflush.h>
+#include <asm/suspend.h>
+#include <asm/idmap.h>
+#include <asm/proc-fns.h>
+#include <asm/tlbflush.h>
+
+#include "iomap.h"
+#include "reset.h"
+#include "flowctrl.h"
+#include "sleep.h"
+#include "tegra_cpu_car.h"
+
+#define TEGRA_POWER_CPU_PWRREQ_OE	(1 << 16)  /* CPU pwr req enable */
+
+#define PMC_CTRL		0x0
+#define PMC_CPUPWRGOOD_TIMER	0xc8
+#define PMC_CPUPWROFF_TIMER	0xcc
+
+#ifdef CONFIG_PM_SLEEP
+static unsigned int g_diag_reg;
+static DEFINE_SPINLOCK(tegra_lp2_lock);
+static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
+static struct clk *tegra_pclk;
+void (*tegra_tear_down_cpu)(void);
+
+void save_cpu_arch_register(void)
+{
+	/* read diagnostic register */
+	asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");
+	return;
+}
+
+void restore_cpu_arch_register(void)
+{
+	/* write diagnostic register */
+	asm("mcr p15, 0, %0, c15, c0, 1" : : "r"(g_diag_reg) : "cc");
+	return;
+}
+
+static void set_power_timers(unsigned long us_on, unsigned long us_off)
+{
+	unsigned long long ticks;
+	unsigned long long pclk;
+	unsigned long rate;
+	static unsigned long tegra_last_pclk;
+
+	if (tegra_pclk == NULL) {
+		tegra_pclk = clk_get_sys(NULL, "pclk");
+		WARN_ON(IS_ERR(tegra_pclk));
+	}
+
+	rate = clk_get_rate(tegra_pclk);
+
+	if (WARN_ON_ONCE(rate <= 0))
+		pclk = 100000000;
+	else
+		pclk = rate;
+
+	if ((rate != tegra_last_pclk)) {
+		ticks = (us_on * pclk) + 999999ull;
+		do_div(ticks, 1000000);
+		writel((unsigned long)ticks, pmc + PMC_CPUPWRGOOD_TIMER);
+
+		ticks = (us_off * pclk) + 999999ull;
+		do_div(ticks, 1000000);
+		writel((unsigned long)ticks, pmc + PMC_CPUPWROFF_TIMER);
+		wmb();
+	}
+	tegra_last_pclk = pclk;
+}
+
+/*
+ * restore_cpu_complex
+ *
+ * restores cpu clock setting, clears flow controller
+ *
+ * Always called on CPU 0.
+ */
+static void restore_cpu_complex(void)
+{
+	int cpu = smp_processor_id();
+
+	BUG_ON(cpu != 0);
+
+#ifdef CONFIG_SMP
+	cpu = cpu_logical_map(cpu);
+#endif
+
+	/* Restore the CPU clock settings */
+	tegra_cpu_clock_resume();
+
+	flowctrl_cpu_suspend_exit(cpu);
+
+	restore_cpu_arch_register();
+}
+
+/*
+ * suspend_cpu_complex
+ *
+ * saves pll state for use by restart_plls, prepares flow controller for
+ * transition to suspend state
+ *
+ * Must always be called on cpu 0.
+ */
+static void suspend_cpu_complex(void)
+{
+	int cpu = smp_processor_id();
+
+	BUG_ON(cpu != 0);
+
+#ifdef CONFIG_SMP
+	cpu = cpu_logical_map(cpu);
+#endif
+
+	/* Save the CPU clock settings */
+	tegra_cpu_clock_suspend();
+
+	flowctrl_cpu_suspend_enter(cpu);
+
+	save_cpu_arch_register();
+}
+
+void __cpuinit tegra_clear_cpu_in_lp2(int phy_cpu_id)
+{
+	u32 *cpu_in_lp2 = tegra_cpu_lp2_mask;
+
+	spin_lock(&tegra_lp2_lock);
+
+	BUG_ON(!(*cpu_in_lp2 & BIT(phy_cpu_id)));
+	*cpu_in_lp2 &= ~BIT(phy_cpu_id);
+
+	spin_unlock(&tegra_lp2_lock);
+}
+
+bool __cpuinit tegra_set_cpu_in_lp2(int phy_cpu_id)
+{
+	bool last_cpu = false;
+	cpumask_t *cpu_lp2_mask = tegra_cpu_lp2_mask;
+	u32 *cpu_in_lp2 = tegra_cpu_lp2_mask;
+
+	spin_lock(&tegra_lp2_lock);
+
+	BUG_ON((*cpu_in_lp2 & BIT(phy_cpu_id)));
+	*cpu_in_lp2 |= BIT(phy_cpu_id);
+
+	if ((phy_cpu_id == 0) && cpumask_equal(cpu_lp2_mask, cpu_online_mask))
+		last_cpu = true;
+
+	spin_unlock(&tegra_lp2_lock);
+	return last_cpu;
+}
+
+static int tegra_sleep_cpu(unsigned long v2p)
+{
+	/* Switch to the identity mapping. */
+	cpu_switch_mm(idmap_pgd, &init_mm);
+
+	/* Flush the TLB. */
+	local_flush_tlb_all();
+
+	tegra_sleep_cpu_finish(v2p);
+
+	/* should never here */
+	BUG();
+
+	return 0;
+}
+
+void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time)
+{
+	u32 mode;
+
+	/* Only the last cpu down does the final suspend steps */
+	mode = readl(pmc + PMC_CTRL);
+	mode |= TEGRA_POWER_CPU_PWRREQ_OE;
+	writel(mode, pmc + PMC_CTRL);
+
+	set_power_timers(cpu_on_time, cpu_off_time);
+
+	cpu_cluster_pm_enter();
+	suspend_cpu_complex();
+
+	cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
+
+	restore_cpu_complex();
+	cpu_cluster_pm_exit();
+}
+#endif
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
new file mode 100644
index 0000000..787335c
--- /dev/null
+++ b/arch/arm/mach-tegra/pm.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (c) 2010-2012 NVIDIA Corporation. All rights reserved.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.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/>.
+ */
+
+#ifndef _MACH_TEGRA_PM_H_
+#define _MACH_TEGRA_PM_H_
+
+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(int phy_cpu_id);
+bool tegra_set_cpu_in_lp2(int phy_cpu_id);
+
+void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time);
+extern void (*tegra_tear_down_cpu)(void);
+
+#endif /* _MACH_TEGRA_PM_H_ */
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
index 7af6a54..d4fdb5f 100644
--- a/arch/arm/mach-tegra/pmc.c
+++ b/arch/arm/mach-tegra/pmc.c
@@ -19,7 +19,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 
-#include <mach/iomap.h>
+#include "iomap.h"
 
 #define PMC_CTRL		0x0
 #define PMC_CTRL_INTR_LOW	(1 << 17)
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
index de0662d..2cc1185 100644
--- a/arch/arm/mach-tegra/powergate.c
+++ b/arch/arm/mach-tegra/powergate.c
@@ -28,10 +28,10 @@
 #include <linux/spinlock.h>
 
 #include <mach/clk.h>
-#include <mach/iomap.h>
 #include <mach/powergate.h>
 
 #include "fuse.h"
+#include "iomap.h"
 
 #define PWRGATE_TOGGLE		0x30
 #define  PWRGATE_TOGGLE_START	(1 << 8)
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c
index 5beb7eb..3fd89ec 100644
--- a/arch/arm/mach-tegra/reset.c
+++ b/arch/arm/mach-tegra/reset.c
@@ -22,10 +22,10 @@
 #include <asm/cacheflush.h>
 #include <asm/hardware/cache-l2x0.h>
 
-#include <mach/iomap.h>
-#include <mach/irammap.h>
-
+#include "iomap.h"
+#include "irammap.h"
 #include "reset.h"
+#include "sleep.h"
 #include "fuse.h"
 
 #define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \
@@ -80,5 +80,10 @@ void __init tegra_cpu_reset_handler_init(void)
 		virt_to_phys((void *)tegra_secondary_startup);
 #endif
 
+#ifdef CONFIG_PM_SLEEP
+	__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP2] =
+		virt_to_phys((void *)tegra_resume);
+#endif
+
 	tegra_cpu_reset_handler_enable();
 }
diff --git a/arch/arm/mach-tegra/reset.h b/arch/arm/mach-tegra/reset.h
index de88bf8..c90d8e9 100644
--- a/arch/arm/mach-tegra/reset.h
+++ b/arch/arm/mach-tegra/reset.h
@@ -29,6 +29,8 @@
 
 #ifndef __ASSEMBLY__
 
+#include "irammap.h"
+
 extern unsigned long __tegra_cpu_reset_handler_data[TEGRA_RESET_DATA_SIZE];
 
 void __tegra_cpu_reset_handler_start(void);
@@ -36,6 +38,13 @@ void __tegra_cpu_reset_handler(void);
 void __tegra_cpu_reset_handler_end(void);
 void tegra_secondary_startup(void);
 
+#ifdef CONFIG_PM_SLEEP
+#define tegra_cpu_lp2_mask \
+	(IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \
+	((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_LP2] - \
+	 (u32)__tegra_cpu_reset_handler_start)))
+#endif
+
 #define tegra_cpu_reset_handler_offset \
 		((u32)__tegra_cpu_reset_handler - \
 		 (u32)__tegra_cpu_reset_handler_start)
diff --git a/arch/arm/mach-tegra/sleep-t20.S b/arch/arm/mach-tegra/sleep-t20.S
deleted file mode 100644
index a36ae41..0000000
--- a/arch/arm/mach-tegra/sleep-t20.S
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
- * Copyright (c) 2011, Google, Inc.
- *
- * Author: Colin Cross <ccross@android.com>
- *         Gary King <gking@nvidia.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/>.
- */
-
-#include <linux/linkage.h>
-
-#include <asm/assembler.h>
-
-#include <mach/iomap.h>
-
-#include "sleep.h"
-#include "flowctrl.h"
-
-#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
-/*
- * tegra20_hotplug_shutdown(void)
- *
- * puts the current cpu in reset
- * should never return
- */
-ENTRY(tegra20_hotplug_shutdown)
-	/* Turn off SMP coherency */
-	exit_smp r4, r5
-
-	/* Put this CPU down */
-	cpu_id	r0
-	bl	tegra20_cpu_shutdown
-	mov	pc, lr			@ should never get here
-ENDPROC(tegra20_hotplug_shutdown)
-
-/*
- * tegra20_cpu_shutdown(int cpu)
- *
- * r0 is cpu to reset
- *
- * puts the specified CPU in wait-for-event mode on the flow controller
- * and puts the CPU in reset
- * can be called on the current cpu or another cpu
- * if called on the current cpu, does not return
- * MUST NOT BE CALLED FOR CPU 0.
- *
- * corrupts r0-r3, r12
- */
-ENTRY(tegra20_cpu_shutdown)
-	cmp	r0, #0
-	moveq	pc, lr			@ must not be called for CPU 0
-
-	cpu_to_halt_reg r1, r0
-	ldr	r3, =TEGRA_FLOW_CTRL_VIRT
-	mov	r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
-	str	r2, [r3, r1]		@ put flow controller in wait event mode
-	ldr	r2, [r3, r1]
-	isb
-	dsb
-	movw	r1, 0x1011
-	mov	r1, r1, lsl r0
-	ldr	r3, =TEGRA_CLK_RESET_VIRT
-	str	r1, [r3, #0x340]	@ put slave CPU in reset
-	isb
-	dsb
-	cpu_id	r3
-	cmp	r3, r0
-	beq	.
-	mov	pc, lr
-ENDPROC(tegra20_cpu_shutdown)
-#endif
diff --git a/arch/arm/mach-tegra/sleep-t30.S b/arch/arm/mach-tegra/sleep-t30.S
deleted file mode 100644
index 777d9ce..0000000
--- a/arch/arm/mach-tegra/sleep-t30.S
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
- *
- * 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/linkage.h>
-
-#include <asm/assembler.h>
-
-#include <mach/iomap.h>
-
-#include "sleep.h"
-#include "flowctrl.h"
-
-#define TEGRA30_POWER_HOTPLUG_SHUTDOWN	(1 << 27) /* Hotplug shutdown */
-
-#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
-/*
- * tegra30_hotplug_shutdown(void)
- *
- * Powergates the current CPU.
- * Should never return.
- */
-ENTRY(tegra30_hotplug_shutdown)
-	/* Turn off SMP coherency */
-	exit_smp r4, r5
-
-	/* Powergate this CPU */
-	mov	r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
-	bl	tegra30_cpu_shutdown
-	mov	pc, lr			@ should never get here
-ENDPROC(tegra30_hotplug_shutdown)
-
-/*
- * tegra30_cpu_shutdown(unsigned long flags)
- *
- * Puts the current CPU in wait-for-event mode on the flow controller
- * and powergates it -- flags (in R0) indicate the request type.
- * Must never be called for CPU 0.
- *
- * corrupts r0-r4, r12
- */
-ENTRY(tegra30_cpu_shutdown)
-	cpu_id	r3
-	cmp	r3, #0
-	moveq	pc, lr		@ Must never be called for CPU 0
-
-	ldr	r12, =TEGRA_FLOW_CTRL_VIRT
-	cpu_to_csr_reg r1, r3
-	add	r1, r1, r12	@ virtual CSR address for this CPU
-	cpu_to_halt_reg r2, r3
-	add	r2, r2, r12	@ virtual HALT_EVENTS address for this CPU
-
-	/*
-	 * Clear this CPU's "event" and "interrupt" flags and power gate
-	 * it when halting but not before it is in the "WFE" state.
-	 */
-	movw	r12, \
-		FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG | \
-		FLOW_CTRL_CSR_ENABLE
-	mov	r4, #(1 << 4)
-	orr	r12, r12, r4, lsl r3
-	str	r12, [r1]
-
-	/* Halt this CPU. */
-	mov	r3, #0x400
-delay_1:
-	subs	r3, r3, #1			@ delay as a part of wfe war.
-	bge	delay_1;
-	cpsid	a				@ disable imprecise aborts.
-	ldr	r3, [r1]			@ read CSR
-	str	r3, [r1]			@ clear CSR
-	tst	r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
-	movne	r3, #FLOW_CTRL_WAITEVENT		@ For hotplug
-	str	r3, [r2]
-	ldr	r0, [r2]
-	b	wfe_war
-
-__cpu_reset_again:
-	dsb
-	.align 5
-	wfe					@ CPU should be power gated here
-wfe_war:
-	b	__cpu_reset_again
-
-	/*
-	 * 38 nop's, which fills reset of wfe cache line and
-	 * 4 more cachelines with nop
-	 */
-	.rept 38
-	nop
-	.endr
-	b	.				@ should never get here
-
-ENDPROC(tegra30_cpu_shutdown)
-#endif
diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S
new file mode 100644
index 0000000..72ce709
--- /dev/null
+++ b/arch/arm/mach-tegra/sleep-tegra20.S
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2011, Google, Inc.
+ *
+ * Author: Colin Cross <ccross@android.com>
+ *         Gary King <gking@nvidia.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/>.
+ */
+
+#include <linux/linkage.h>
+
+#include <asm/assembler.h>
+
+#include "sleep.h"
+#include "flowctrl.h"
+
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
+/*
+ * tegra20_hotplug_shutdown(void)
+ *
+ * puts the current cpu in reset
+ * should never return
+ */
+ENTRY(tegra20_hotplug_shutdown)
+	/* Turn off SMP coherency */
+	exit_smp r4, r5
+
+	/* Put this CPU down */
+	cpu_id	r0
+	bl	tegra20_cpu_shutdown
+	mov	pc, lr			@ should never get here
+ENDPROC(tegra20_hotplug_shutdown)
+
+/*
+ * tegra20_cpu_shutdown(int cpu)
+ *
+ * r0 is cpu to reset
+ *
+ * puts the specified CPU in wait-for-event mode on the flow controller
+ * and puts the CPU in reset
+ * can be called on the current cpu or another cpu
+ * if called on the current cpu, does not return
+ * MUST NOT BE CALLED FOR CPU 0.
+ *
+ * corrupts r0-r3, r12
+ */
+ENTRY(tegra20_cpu_shutdown)
+	cmp	r0, #0
+	moveq	pc, lr			@ must not be called for CPU 0
+
+	cpu_to_halt_reg r1, r0
+	ldr	r3, =TEGRA_FLOW_CTRL_VIRT
+	mov	r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
+	str	r2, [r3, r1]		@ put flow controller in wait event mode
+	ldr	r2, [r3, r1]
+	isb
+	dsb
+	movw	r1, 0x1011
+	mov	r1, r1, lsl r0
+	ldr	r3, =TEGRA_CLK_RESET_VIRT
+	str	r1, [r3, #0x340]	@ put slave CPU in reset
+	isb
+	dsb
+	cpu_id	r3
+	cmp	r3, r0
+	beq	.
+	mov	pc, lr
+ENDPROC(tegra20_cpu_shutdown)
+#endif
diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S
new file mode 100644
index 0000000..562a8e7
--- /dev/null
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
+ *
+ * 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/linkage.h>
+
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+
+#include "sleep.h"
+#include "flowctrl.h"
+
+#define TEGRA30_POWER_HOTPLUG_SHUTDOWN	(1 << 27) /* Hotplug shutdown */
+
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
+/*
+ * tegra30_hotplug_shutdown(void)
+ *
+ * Powergates the current CPU.
+ * Should never return.
+ */
+ENTRY(tegra30_hotplug_shutdown)
+	/* Turn off SMP coherency */
+	exit_smp r4, r5
+
+	/* Powergate this CPU */
+	mov	r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
+	bl	tegra30_cpu_shutdown
+	mov	pc, lr			@ should never get here
+ENDPROC(tegra30_hotplug_shutdown)
+
+/*
+ * tegra30_cpu_shutdown(unsigned long flags)
+ *
+ * Puts the current CPU in wait-for-event mode on the flow controller
+ * and powergates it -- flags (in R0) indicate the request type.
+ * Must never be called for CPU 0.
+ *
+ * corrupts r0-r4, r12
+ */
+ENTRY(tegra30_cpu_shutdown)
+	cpu_id	r3
+	cmp	r3, #0
+	moveq	pc, lr		@ Must never be called for CPU 0
+
+	ldr	r12, =TEGRA_FLOW_CTRL_VIRT
+	cpu_to_csr_reg r1, r3
+	add	r1, r1, r12	@ virtual CSR address for this CPU
+	cpu_to_halt_reg r2, r3
+	add	r2, r2, r12	@ virtual HALT_EVENTS address for this CPU
+
+	/*
+	 * Clear this CPU's "event" and "interrupt" flags and power gate
+	 * it when halting but not before it is in the "WFE" state.
+	 */
+	movw	r12, \
+		FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG | \
+		FLOW_CTRL_CSR_ENABLE
+	mov	r4, #(1 << 4)
+	orr	r12, r12, r4, lsl r3
+	str	r12, [r1]
+
+	/* Halt this CPU. */
+	mov	r3, #0x400
+delay_1:
+	subs	r3, r3, #1			@ delay as a part of wfe war.
+	bge	delay_1;
+	cpsid	a				@ disable imprecise aborts.
+	ldr	r3, [r1]			@ read CSR
+	str	r3, [r1]			@ clear CSR
+	tst	r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
+	moveq   r3, #FLOW_CTRL_WAIT_FOR_INTERRUPT	@ For LP2
+	movne	r3, #FLOW_CTRL_WAITEVENT		@ For hotplug
+	str	r3, [r2]
+	ldr	r0, [r2]
+	b	wfe_war
+
+__cpu_reset_again:
+	dsb
+	.align 5
+	wfe					@ CPU should be power gated here
+wfe_war:
+	b	__cpu_reset_again
+
+	/*
+	 * 38 nop's, which fills reset of wfe cache line and
+	 * 4 more cachelines with nop
+	 */
+	.rept 38
+	nop
+	.endr
+	b	.				@ should never get here
+
+ENDPROC(tegra30_cpu_shutdown)
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+/*
+ * tegra30_sleep_cpu_secondary_finish(unsigned long v2p)
+ *
+ * Enters LP2 on secondary CPU by exiting coherency and powergating the CPU.
+ */
+ENTRY(tegra30_sleep_cpu_secondary_finish)
+	mov	r7, lr
+
+	/* Flush and disable the L1 data cache */
+	bl	tegra_disable_clean_inv_dcache
+
+	/* Powergate this CPU. */
+	mov	r0, #0                          @ power mode flags (!hotplug)
+	bl	tegra30_cpu_shutdown
+	mov	r0, #1                          @ never return here
+	mov	pc, r7
+ENDPROC(tegra30_sleep_cpu_secondary_finish)
+
+/*
+ * tegra30_tear_down_cpu
+ *
+ * Switches the CPU to enter sleep.
+ */
+ENTRY(tegra30_tear_down_cpu)
+	mov32	r6, TEGRA_FLOW_CTRL_BASE
+
+	b	tegra30_enter_sleep
+ENDPROC(tegra30_tear_down_cpu)
+
+/*
+ * tegra30_enter_sleep
+ *
+ * uses flow controller to enter sleep state
+ * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1
+ * executes from SDRAM with target state is LP2
+ * r6 = TEGRA_FLOW_CTRL_BASE
+ */
+tegra30_enter_sleep:
+	cpu_id	r1
+
+	cpu_to_csr_reg	r2, r1
+	ldr	r0, [r6, r2]
+	orr	r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
+	orr	r0, r0, #FLOW_CTRL_CSR_ENABLE
+	str	r0, [r6, r2]
+
+	mov	r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
+	orr	r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
+	cpu_to_halt_reg r2, r1
+	str	r0, [r6, r2]
+	dsb
+	ldr	r0, [r6, r2] /* memory barrier */
+
+halted:
+	isb
+	dsb
+	wfi	/* CPU should be power gated here */
+
+	/* !!!FIXME!!! Implement halt failure handler */
+	b	halted
+
+#endif
diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index ea81554..26afa7c 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -25,9 +25,87 @@
 #include <linux/linkage.h>
 
 #include <asm/assembler.h>
+#include <asm/cache.h>
+#include <asm/cp15.h>
+#include <asm/hardware/cache-l2x0.h>
 
-#include <mach/iomap.h>
+#include "iomap.h"
 
 #include "flowctrl.h"
 #include "sleep.h"
 
+#ifdef CONFIG_PM_SLEEP
+/*
+ * tegra_disable_clean_inv_dcache
+ *
+ * disable, clean & invalidate the D-cache
+ *
+ * Corrupted registers: r1-r3, r6, r8, r9-r11
+ */
+ENTRY(tegra_disable_clean_inv_dcache)
+	stmfd	sp!, {r0, r4-r5, r7, r9-r11, lr}
+	dmb					@ ensure ordering
+
+	/* Disable the D-cache */
+	mrc	p15, 0, r2, c1, c0, 0
+	bic	r2, r2, #CR_C
+	mcr	p15, 0, r2, c1, c0, 0
+	isb
+
+	/* Flush the D-cache */
+	bl	v7_flush_dcache_louis
+
+	/* Trun off coherency */
+	exit_smp r4, r5
+
+	ldmfd	sp!, {r0, r4-r5, r7, r9-r11, pc}
+ENDPROC(tegra_disable_clean_inv_dcache)
+
+/*
+ * tegra_sleep_cpu_finish(unsigned long v2p)
+ *
+ * enters suspend in LP2 by turning off the mmu and jumping to
+ * tegra?_tear_down_cpu
+ */
+ENTRY(tegra_sleep_cpu_finish)
+	/* Flush and disable the L1 data cache */
+	bl	tegra_disable_clean_inv_dcache
+
+	mov32	r6, tegra_tear_down_cpu
+	ldr	r1, [r6]
+	add	r1, r1, r0
+
+	mov32	r3, tegra_shut_off_mmu
+	add	r3, r3, r0
+	mov	r0, r1
+
+	mov	pc, r3
+ENDPROC(tegra_sleep_cpu_finish)
+
+/*
+ * tegra_shut_off_mmu
+ *
+ * r0 = physical address to jump to with mmu off
+ *
+ * called with VA=PA mapping
+ * turns off MMU, icache, dcache and branch prediction
+ */
+	.align	L1_CACHE_SHIFT
+	.pushsection	.idmap.text, "ax"
+ENTRY(tegra_shut_off_mmu)
+	mrc	p15, 0, r3, c1, c0, 0
+	movw	r2, #CR_I | CR_Z | CR_C | CR_M
+	bic	r3, r3, r2
+	dsb
+	mcr	p15, 0, r3, c1, c0, 0
+	isb
+#ifdef CONFIG_CACHE_L2X0
+	/* Disable L2 cache */
+	mov32	r4, TEGRA_ARM_PERIF_BASE + 0x3000
+	mov	r5, #0
+	str	r5, [r4, #L2X0_CTRL]
+#endif
+	mov	pc, r0
+ENDPROC(tegra_shut_off_mmu)
+	.popsection
+#endif
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index e25a7cd..9821ee7 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -17,7 +17,7 @@
 #ifndef __MACH_TEGRA_SLEEP_H
 #define __MACH_TEGRA_SLEEP_H
 
-#include <mach/iomap.h>
+#include "iomap.h"
 
 #define TEGRA_ARM_PERIF_VIRT (TEGRA_ARM_PERIF_BASE - IO_CPU_PHYS \
 					+ IO_CPU_VIRT)
@@ -71,7 +71,41 @@
 	str	\tmp2, [\tmp1]			@ invalidate SCU tags for CPU
 	dsb
 .endm
+
+/* Macro to resume & re-enable L2 cache */
+#ifndef L2X0_CTRL_EN
+#define L2X0_CTRL_EN	1
+#endif
+
+#ifdef CONFIG_CACHE_L2X0
+.macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs
+	adr	\tmp1, \phys_l2x0_saved_regs
+	ldr	\tmp1, [\tmp1]
+	ldr	\tmp2, [\tmp1, #L2X0_R_PHY_BASE]
+	ldr	\tmp3, [\tmp2, #L2X0_CTRL]
+	tst	\tmp3, #L2X0_CTRL_EN
+	bne	exit_l2_resume
+	ldr	\tmp3, [\tmp1, #L2X0_R_TAG_LATENCY]
+	str	\tmp3, [\tmp2, #L2X0_TAG_LATENCY_CTRL]
+	ldr	\tmp3, [\tmp1, #L2X0_R_DATA_LATENCY]
+	str	\tmp3, [\tmp2, #L2X0_DATA_LATENCY_CTRL]
+	ldr	\tmp3, [\tmp1, #L2X0_R_PREFETCH_CTRL]
+	str	\tmp3, [\tmp2, #L2X0_PREFETCH_CTRL]
+	ldr	\tmp3, [\tmp1, #L2X0_R_PWR_CTRL]
+	str	\tmp3, [\tmp2, #L2X0_POWER_CTRL]
+	ldr	\tmp3, [\tmp1, #L2X0_R_AUX_CTRL]
+	str	\tmp3, [\tmp2, #L2X0_AUX_CTRL]
+	mov	\tmp3, #L2X0_CTRL_EN
+	str	\tmp3, [\tmp2, #L2X0_CTRL]
+exit_l2_resume:
+.endm
+#else /* CONFIG_CACHE_L2X0 */
+.macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs
+.endm
+#endif /* CONFIG_CACHE_L2X0 */
 #else
+void tegra_resume(void);
+int tegra_sleep_cpu_finish(unsigned long);
 
 #ifdef CONFIG_HOTPLUG_CPU
 void tegra20_hotplug_init(void);
@@ -81,5 +115,8 @@ static inline void tegra20_hotplug_init(void) {}
 static inline void tegra30_hotplug_init(void) {}
 #endif
 
+int tegra30_sleep_cpu_secondary_finish(unsigned long);
+void tegra30_tear_down_cpu(void);
+
 #endif
 #endif
diff --git a/arch/arm/mach-tegra/tegra20_clocks.c b/arch/arm/mach-tegra/tegra20_clocks.c
index deb873f..4eb6bc8 100644
--- a/arch/arm/mach-tegra/tegra20_clocks.c
+++ b/arch/arm/mach-tegra/tegra20_clocks.c
@@ -27,10 +27,9 @@
 #include <linux/clkdev.h>
 #include <linux/clk.h>
 
-#include <mach/iomap.h>
-
 #include "clock.h"
 #include "fuse.h"
+#include "iomap.h"
 #include "tegra2_emc.h"
 #include "tegra_cpu_car.h"
 
diff --git a/arch/arm/mach-tegra/tegra20_clocks_data.c b/arch/arm/mach-tegra/tegra20_clocks_data.c
index 8d398a3..a23a073 100644
--- a/arch/arm/mach-tegra/tegra20_clocks_data.c
+++ b/arch/arm/mach-tegra/tegra20_clocks_data.c
@@ -27,8 +27,6 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 
-#include <mach/iomap.h>
-
 #include "clock.h"
 #include "fuse.h"
 #include "tegra2_emc.h"
@@ -248,11 +246,16 @@ static struct clk_pll_freq_table tegra_pll_d_freq_table[] = {
 	{ 19200000, 216000000, 135, 12, 1, 3},
 	{ 26000000, 216000000, 216, 26, 1, 4},
 
+	{ 12000000, 297000000,  99,  4, 1, 4 },
+	{ 12000000, 339000000, 113,  4, 1, 4 },
+
 	{ 12000000, 594000000, 594, 12, 1, 8},
 	{ 13000000, 594000000, 594, 13, 1, 8},
 	{ 19200000, 594000000, 495, 16, 1, 8},
 	{ 26000000, 594000000, 594, 26, 1, 8},
 
+	{ 12000000, 616000000, 616, 12, 1, 8},
+
 	{ 12000000, 1000000000, 1000, 12, 1, 12},
 	{ 13000000, 1000000000, 1000, 13, 1, 12},
 	{ 19200000, 1000000000, 625,  12, 1, 8},
@@ -1038,9 +1041,6 @@ static struct clk_duplicate tegra_clk_duplicates[] = {
 	CLK_DUPLICATE("usbd",	"utmip-pad",	NULL),
 	CLK_DUPLICATE("usbd",	"tegra-ehci.0",	NULL),
 	CLK_DUPLICATE("usbd",	"tegra-otg",	NULL),
-	CLK_DUPLICATE("hdmi",	"tegradc.0",	"hdmi"),
-	CLK_DUPLICATE("hdmi",	"tegradc.1",	"hdmi"),
-	CLK_DUPLICATE("host1x",	"tegra_grhost",	"host1x"),
 	CLK_DUPLICATE("2d",	"tegra_grhost",	"gr2d"),
 	CLK_DUPLICATE("3d",	"tegra_grhost",	"gr3d"),
 	CLK_DUPLICATE("epp",	"tegra_grhost",	"epp"),
@@ -1053,6 +1053,9 @@ static struct clk_duplicate tegra_clk_duplicates[] = {
 	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.1", "fast-clk"),
 	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.2", "fast-clk"),
 	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.3", "fast-clk"),
+	CLK_DUPLICATE("pll_p", "tegradc.0", "parent"),
+	CLK_DUPLICATE("pll_p", "tegradc.1", "parent"),
+	CLK_DUPLICATE("pll_d_out0", "hdmi", "parent"),
 };
 
 #define CLK(dev, con, ck)	\
diff --git a/arch/arm/mach-tegra/tegra20_speedo.c b/arch/arm/mach-tegra/tegra20_speedo.c
new file mode 100644
index 0000000..fa6eb57
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra20_speedo.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+
+#include "fuse.h"
+
+#define CPU_SPEEDO_LSBIT		20
+#define CPU_SPEEDO_MSBIT		29
+#define CPU_SPEEDO_REDUND_LSBIT		30
+#define CPU_SPEEDO_REDUND_MSBIT		39
+#define CPU_SPEEDO_REDUND_OFFS	(CPU_SPEEDO_REDUND_MSBIT - CPU_SPEEDO_MSBIT)
+
+#define CORE_SPEEDO_LSBIT		40
+#define CORE_SPEEDO_MSBIT		47
+#define CORE_SPEEDO_REDUND_LSBIT	48
+#define CORE_SPEEDO_REDUND_MSBIT	55
+#define CORE_SPEEDO_REDUND_OFFS	(CORE_SPEEDO_REDUND_MSBIT - CORE_SPEEDO_MSBIT)
+
+#define SPEEDO_MULT			4
+
+#define PROCESS_CORNERS_NUM		4
+
+#define SPEEDO_ID_SELECT_0(rev)		((rev) <= 2)
+#define SPEEDO_ID_SELECT_1(sku)		\
+	(((sku) != 20) && ((sku) != 23) && ((sku) != 24) && \
+	 ((sku) != 27) && ((sku) != 28))
+
+enum {
+	SPEEDO_ID_0,
+	SPEEDO_ID_1,
+	SPEEDO_ID_2,
+	SPEEDO_ID_COUNT,
+};
+
+static const u32 cpu_process_speedos[][PROCESS_CORNERS_NUM] = {
+	{315, 366, 420, UINT_MAX},
+	{303, 368, 419, UINT_MAX},
+	{316, 331, 383, UINT_MAX},
+};
+
+static const u32 core_process_speedos[][PROCESS_CORNERS_NUM] = {
+	{165, 195, 224, UINT_MAX},
+	{165, 195, 224, UINT_MAX},
+	{165, 195, 224, UINT_MAX},
+};
+
+void tegra20_init_speedo_data(void)
+{
+	u32 reg;
+	u32 val;
+	int i;
+
+	BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != SPEEDO_ID_COUNT);
+	BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != SPEEDO_ID_COUNT);
+
+	if (SPEEDO_ID_SELECT_0(tegra_revision))
+		tegra_soc_speedo_id = SPEEDO_ID_0;
+	else if (SPEEDO_ID_SELECT_1(tegra_sku_id))
+		tegra_soc_speedo_id = SPEEDO_ID_1;
+	else
+		tegra_soc_speedo_id = SPEEDO_ID_2;
+
+	val = 0;
+	for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) {
+		reg = tegra_spare_fuse(i) |
+			tegra_spare_fuse(i + CPU_SPEEDO_REDUND_OFFS);
+		val = (val << 1) | (reg & 0x1);
+	}
+	val = val * SPEEDO_MULT;
+	pr_debug("%s CPU speedo value %u\n", __func__, val);
+
+	for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
+		if (val <= cpu_process_speedos[tegra_soc_speedo_id][i])
+			break;
+	}
+	tegra_cpu_process_id = i;
+
+	val = 0;
+	for (i = CORE_SPEEDO_MSBIT; i >= CORE_SPEEDO_LSBIT; i--) {
+		reg = tegra_spare_fuse(i) |
+			tegra_spare_fuse(i + CORE_SPEEDO_REDUND_OFFS);
+		val = (val << 1) | (reg & 0x1);
+	}
+	val = val * SPEEDO_MULT;
+	pr_debug("%s Core speedo value %u\n", __func__, val);
+
+	for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
+		if (val <= core_process_speedos[tegra_soc_speedo_id][i])
+			break;
+	}
+	tegra_core_process_id = i;
+
+	pr_info("Tegra20 Soc Speedo ID %d", tegra_soc_speedo_id);
+}
diff --git a/arch/arm/mach-tegra/tegra2_emc.c b/arch/arm/mach-tegra/tegra2_emc.c
index 5070d83..837c7b9 100644
--- a/arch/arm/mach-tegra/tegra2_emc.c
+++ b/arch/arm/mach-tegra/tegra2_emc.c
@@ -25,8 +25,6 @@
 #include <linux/platform_device.h>
 #include <linux/platform_data/tegra_emc.h>
 
-#include <mach/iomap.h>
-
 #include "tegra2_emc.h"
 #include "fuse.h"
 
diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c
index e9de5df..d714777 100644
--- a/arch/arm/mach-tegra/tegra30_clocks.c
+++ b/arch/arm/mach-tegra/tegra30_clocks.c
@@ -31,10 +31,11 @@
 
 #include <asm/clkdev.h>
 
-#include <mach/iomap.h>
+#include <mach/powergate.h>
 
 #include "clock.h"
 #include "fuse.h"
+#include "iomap.h"
 #include "tegra_cpu_car.h"
 
 #define USE_PLL_LOCK_BITS 0
@@ -310,6 +311,31 @@
 #define CPU_CLOCK(cpu)	(0x1 << (8 + cpu))
 #define CPU_RESET(cpu)	(0x1111ul << (cpu))
 
+#define CLK_RESET_CCLK_BURST	0x20
+#define CLK_RESET_CCLK_DIVIDER  0x24
+#define CLK_RESET_PLLX_BASE	0xe0
+#define CLK_RESET_PLLX_MISC	0xe4
+
+#define CLK_RESET_SOURCE_CSITE	0x1d4
+
+#define CLK_RESET_CCLK_BURST_POLICY_SHIFT	28
+#define CLK_RESET_CCLK_RUN_POLICY_SHIFT		4
+#define CLK_RESET_CCLK_IDLE_POLICY_SHIFT	0
+#define CLK_RESET_CCLK_IDLE_POLICY		1
+#define CLK_RESET_CCLK_RUN_POLICY		2
+#define CLK_RESET_CCLK_BURST_POLICY_PLLX	8
+
+#ifdef CONFIG_PM_SLEEP
+static struct cpu_clk_suspend_context {
+	u32 pllx_misc;
+	u32 pllx_base;
+
+	u32 cpu_burst;
+	u32 clk_csite_src;
+	u32 cclk_divider;
+} tegra30_cpu_clk_sctx;
+#endif
+
 /**
 * Structure defining the fields for USB UTMI clocks Parameters.
 */
@@ -792,6 +818,112 @@ struct clk_ops tegra30_twd_ops = {
 	.recalc_rate = tegra30_twd_clk_recalc_rate,
 };
 
+/* bus clock functions */
+static int tegra30_bus_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val = clk_readl(c->reg);
+
+	c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON;
+	return c->state;
+}
+
+static int tegra30_bus_clk_enable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val;
+
+	val = clk_readl(c->reg);
+	val &= ~(BUS_CLK_DISABLE << c->reg_shift);
+	clk_writel(val, c->reg);
+
+	return 0;
+}
+
+static void tegra30_bus_clk_disable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val;
+
+	val = clk_readl(c->reg);
+	val |= BUS_CLK_DISABLE << c->reg_shift;
+	clk_writel(val, c->reg);
+}
+
+static unsigned long tegra30_bus_clk_recalc_rate(struct clk_hw *hw,
+			unsigned long prate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val = clk_readl(c->reg);
+	u64 rate = prate;
+
+	c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1;
+	c->mul = 1;
+
+	if (c->mul != 0 && c->div != 0) {
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
+		do_div(rate, c->div);
+	}
+	return rate;
+}
+
+static int tegra30_bus_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	int ret = -EINVAL;
+	u32 val;
+	int i;
+
+	val = clk_readl(c->reg);
+	for (i = 1; i <= 4; i++) {
+		if (rate == parent_rate / i) {
+			val &= ~(BUS_CLK_DIV_MASK << c->reg_shift);
+			val |= (i - 1) << c->reg_shift;
+			clk_writel(val, c->reg);
+			c->div = i;
+			c->mul = 1;
+			ret = 0;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static long tegra30_bus_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	unsigned long parent_rate = *prate;
+	s64 divider;
+
+	if (rate >= parent_rate)
+		return parent_rate;
+
+	divider = parent_rate;
+	divider += rate - 1;
+	do_div(divider, rate);
+
+	if (divider < 0)
+		return divider;
+
+	if (divider > 4)
+		divider = 4;
+	do_div(parent_rate, divider);
+
+	return parent_rate;
+}
+
+struct clk_ops tegra30_bus_ops = {
+	.is_enabled = tegra30_bus_clk_is_enabled,
+	.enable = tegra30_bus_clk_enable,
+	.disable = tegra30_bus_clk_disable,
+	.set_rate = tegra30_bus_clk_set_rate,
+	.round_rate = tegra30_bus_clk_round_rate,
+	.recalc_rate = tegra30_bus_clk_recalc_rate,
+};
+
 /* Blink output functions */
 static int tegra30_blink_clk_is_enabled(struct clk_hw *hw)
 {
@@ -1913,9 +2045,7 @@ struct clk_ops tegra30_periph_clk_ops = {
 static int tegra30_dsib_clk_set_parent(struct clk_hw *hw, u8 index)
 {
 	struct clk *d = clk_get_sys(NULL, "pll_d");
-	/* The DSIB parent selection bit is in PLLD base
-	   register - can not do direct r-m-w, must be
-	   protected by PLLD lock */
+	/* The DSIB parent selection bit is in PLLD base register */
 	tegra_clk_cfg_ex(
 		d, TEGRA_CLK_PLLD_MIPI_MUX_SEL, index);
 
@@ -2281,12 +2411,93 @@ static void tegra30_disable_cpu_clock(u32 cpu)
 	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
 }
 
+#ifdef CONFIG_PM_SLEEP
+static bool tegra30_cpu_rail_off_ready(void)
+{
+	unsigned int cpu_rst_status;
+	int cpu_pwr_status;
+
+	cpu_rst_status = readl(reg_clk_base +
+			       TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS);
+	cpu_pwr_status = tegra_powergate_is_powered(TEGRA_POWERGATE_CPU1) ||
+			 tegra_powergate_is_powered(TEGRA_POWERGATE_CPU2) ||
+			 tegra_powergate_is_powered(TEGRA_POWERGATE_CPU3);
+
+	if (((cpu_rst_status & 0xE) != 0xE) || cpu_pwr_status)
+		return false;
+
+	return true;
+}
+
+static void tegra30_cpu_clock_suspend(void)
+{
+	/* switch coresite to clk_m, save off original source */
+	tegra30_cpu_clk_sctx.clk_csite_src =
+				readl(reg_clk_base + CLK_RESET_SOURCE_CSITE);
+	writel(3<<30, reg_clk_base + CLK_RESET_SOURCE_CSITE);
+
+	tegra30_cpu_clk_sctx.cpu_burst =
+				readl(reg_clk_base + CLK_RESET_CCLK_BURST);
+	tegra30_cpu_clk_sctx.pllx_base =
+				readl(reg_clk_base + CLK_RESET_PLLX_BASE);
+	tegra30_cpu_clk_sctx.pllx_misc =
+				readl(reg_clk_base + CLK_RESET_PLLX_MISC);
+	tegra30_cpu_clk_sctx.cclk_divider =
+				readl(reg_clk_base + CLK_RESET_CCLK_DIVIDER);
+}
+
+static void tegra30_cpu_clock_resume(void)
+{
+	unsigned int reg, policy;
+
+	/* Is CPU complex already running on PLLX? */
+	reg = readl(reg_clk_base + CLK_RESET_CCLK_BURST);
+	policy = (reg >> CLK_RESET_CCLK_BURST_POLICY_SHIFT) & 0xF;
+
+	if (policy == CLK_RESET_CCLK_IDLE_POLICY)
+		reg = (reg >> CLK_RESET_CCLK_IDLE_POLICY_SHIFT) & 0xF;
+	else if (policy == CLK_RESET_CCLK_RUN_POLICY)
+		reg = (reg >> CLK_RESET_CCLK_RUN_POLICY_SHIFT) & 0xF;
+	else
+		BUG();
+
+	if (reg != CLK_RESET_CCLK_BURST_POLICY_PLLX) {
+		/* restore PLLX settings if CPU is on different PLL */
+		writel(tegra30_cpu_clk_sctx.pllx_misc,
+					reg_clk_base + CLK_RESET_PLLX_MISC);
+		writel(tegra30_cpu_clk_sctx.pllx_base,
+					reg_clk_base + CLK_RESET_PLLX_BASE);
+
+		/* wait for PLL stabilization if PLLX was enabled */
+		if (tegra30_cpu_clk_sctx.pllx_base & (1 << 30))
+			udelay(300);
+	}
+
+	/*
+	 * Restore original burst policy setting for calls resulting from CPU
+	 * LP2 in idle or system suspend.
+	 */
+	writel(tegra30_cpu_clk_sctx.cclk_divider,
+					reg_clk_base + CLK_RESET_CCLK_DIVIDER);
+	writel(tegra30_cpu_clk_sctx.cpu_burst,
+					reg_clk_base + CLK_RESET_CCLK_BURST);
+
+	writel(tegra30_cpu_clk_sctx.clk_csite_src,
+					reg_clk_base + CLK_RESET_SOURCE_CSITE);
+}
+#endif
+
 static struct tegra_cpu_car_ops tegra30_cpu_car_ops = {
 	.wait_for_reset	= tegra30_wait_cpu_in_reset,
 	.put_in_reset	= tegra30_put_cpu_in_reset,
 	.out_of_reset	= tegra30_cpu_out_of_reset,
 	.enable_clock	= tegra30_enable_cpu_clock,
 	.disable_clock	= tegra30_disable_cpu_clock,
+#ifdef CONFIG_PM_SLEEP
+	.rail_off_ready	= tegra30_cpu_rail_off_ready,
+	.suspend	= tegra30_cpu_clock_suspend,
+	.resume		= tegra30_cpu_clock_resume,
+#endif
 };
 
 void __init tegra30_cpu_car_ops_init(void)
diff --git a/arch/arm/mach-tegra/tegra30_clocks.h b/arch/arm/mach-tegra/tegra30_clocks.h
index f2f88fe..7a34adb 100644
--- a/arch/arm/mach-tegra/tegra30_clocks.h
+++ b/arch/arm/mach-tegra/tegra30_clocks.h
@@ -34,6 +34,7 @@ extern struct clk_ops tegra_clk_out_ops;
 extern struct clk_ops tegra30_super_ops;
 extern struct clk_ops tegra30_blink_clk_ops;
 extern struct clk_ops tegra30_twd_ops;
+extern struct clk_ops tegra30_bus_ops;
 extern struct clk_ops tegra30_periph_clk_ops;
 extern struct clk_ops tegra30_dsib_clk_ops;
 extern struct clk_ops tegra_nand_clk_ops;
diff --git a/arch/arm/mach-tegra/tegra30_clocks_data.c b/arch/arm/mach-tegra/tegra30_clocks_data.c
index 3d2e553..6942c7a 100644
--- a/arch/arm/mach-tegra/tegra30_clocks_data.c
+++ b/arch/arm/mach-tegra/tegra30_clocks_data.c
@@ -711,6 +711,50 @@ static struct clk tegra_clk_sclk = {
 	.num_parents = ARRAY_SIZE(mux_sclk),
 };
 
+static const char *tegra_hclk_parent_names[] = {
+	"tegra_sclk",
+};
+
+static struct clk *tegra_hclk_parents[] = {
+	&tegra_clk_sclk,
+};
+
+static struct clk tegra_hclk;
+static struct clk_tegra tegra_hclk_hw = {
+	.hw = {
+		.clk = &tegra_hclk,
+	},
+	.flags = DIV_BUS,
+	.reg = 0x30,
+	.reg_shift = 4,
+	.max_rate = 378000000,
+	.min_rate = 12000000,
+};
+DEFINE_CLK_TEGRA(hclk, 0, &tegra30_bus_ops, 0, tegra_hclk_parent_names,
+		tegra_hclk_parents, &tegra_clk_sclk);
+
+static const char *tegra_pclk_parent_names[] = {
+	"tegra_hclk",
+};
+
+static struct clk *tegra_pclk_parents[] = {
+	&tegra_hclk,
+};
+
+static struct clk tegra_pclk;
+static struct clk_tegra tegra_pclk_hw = {
+	.hw = {
+		.clk = &tegra_pclk,
+	},
+	.flags = DIV_BUS,
+	.reg = 0x30,
+	.reg_shift = 0,
+	.max_rate = 167000000,
+	.min_rate = 12000000,
+};
+DEFINE_CLK_TEGRA(pclk, 0, &tegra30_bus_ops, 0, tegra_pclk_parent_names,
+		tegra_pclk_parents, &tegra_hclk);
+
 static const char *mux_blink[] = {
 	"clk_32k",
 };
@@ -1254,8 +1298,6 @@ struct clk_duplicate tegra_clk_duplicates[] = {
 	CLK_DUPLICATE("usbd", "utmip-pad", NULL),
 	CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL),
 	CLK_DUPLICATE("usbd", "tegra-otg", NULL),
-	CLK_DUPLICATE("hdmi", "tegradc.0", "hdmi"),
-	CLK_DUPLICATE("hdmi", "tegradc.1", "hdmi"),
 	CLK_DUPLICATE("dsib", "tegradc.0", "dsib"),
 	CLK_DUPLICATE("dsia", "tegradc.1", "dsia"),
 	CLK_DUPLICATE("bsev", "tegra-avp", "bsev"),
@@ -1293,6 +1335,9 @@ struct clk_duplicate tegra_clk_duplicates[] = {
 	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.2", "fast-clk"),
 	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.3", "fast-clk"),
 	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.4", "fast-clk"),
+	CLK_DUPLICATE("pll_p", "tegradc.0", "parent"),
+	CLK_DUPLICATE("pll_p", "tegradc.1", "parent"),
+	CLK_DUPLICATE("pll_d2_out0", "hdmi", "parent"),
 };
 
 struct clk *tegra_ptr_clks[] = {
@@ -1325,6 +1370,8 @@ struct clk *tegra_ptr_clks[] = {
 	&tegra_cml1,
 	&tegra_pciex,
 	&tegra_clk_sclk,
+	&tegra_hclk,
+	&tegra_pclk,
 	&tegra_clk_blink,
 	&tegra30_clk_twd,
 };
diff --git a/arch/arm/mach-tegra/tegra30_speedo.c b/arch/arm/mach-tegra/tegra30_speedo.c
new file mode 100644
index 0000000..125cb16
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra30_speedo.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+
+#include "fuse.h"
+
+#define CORE_PROCESS_CORNERS_NUM	1
+#define CPU_PROCESS_CORNERS_NUM		6
+
+#define FUSE_SPEEDO_CALIB_0	0x114
+#define FUSE_PACKAGE_INFO	0X1FC
+#define FUSE_TEST_PROG_VER	0X128
+
+#define G_SPEEDO_BIT_MINUS1	58
+#define G_SPEEDO_BIT_MINUS1_R	59
+#define G_SPEEDO_BIT_MINUS2	60
+#define G_SPEEDO_BIT_MINUS2_R	61
+#define LP_SPEEDO_BIT_MINUS1	62
+#define LP_SPEEDO_BIT_MINUS1_R	63
+#define LP_SPEEDO_BIT_MINUS2	64
+#define LP_SPEEDO_BIT_MINUS2_R	65
+
+enum {
+	THRESHOLD_INDEX_0,
+	THRESHOLD_INDEX_1,
+	THRESHOLD_INDEX_2,
+	THRESHOLD_INDEX_3,
+	THRESHOLD_INDEX_4,
+	THRESHOLD_INDEX_5,
+	THRESHOLD_INDEX_6,
+	THRESHOLD_INDEX_7,
+	THRESHOLD_INDEX_8,
+	THRESHOLD_INDEX_9,
+	THRESHOLD_INDEX_10,
+	THRESHOLD_INDEX_11,
+	THRESHOLD_INDEX_COUNT,
+};
+
+static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
+	{180},
+	{170},
+	{195},
+	{180},
+	{168},
+	{192},
+	{180},
+	{170},
+	{195},
+	{180},
+	{180},
+	{180},
+};
+
+static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
+	{306, 338, 360, 376, UINT_MAX},
+	{295, 336, 358, 375, UINT_MAX},
+	{325, 325, 358, 375, UINT_MAX},
+	{325, 325, 358, 375, UINT_MAX},
+	{292, 324, 348, 364, UINT_MAX},
+	{324, 324, 348, 364, UINT_MAX},
+	{324, 324, 348, 364, UINT_MAX},
+	{295, 336, 358, 375, UINT_MAX},
+	{358, 358, 358, 358, 397, UINT_MAX},
+	{364, 364, 364, 364, 397, UINT_MAX},
+	{295, 336, 358, 375, 391, UINT_MAX},
+	{295, 336, 358, 375, 391, UINT_MAX},
+};
+
+static int threshold_index;
+static int package_id;
+
+static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
+{
+	u32 reg;
+	int ate_ver;
+	int bit_minus1;
+	int bit_minus2;
+
+	reg = tegra_fuse_readl(FUSE_SPEEDO_CALIB_0);
+
+	*speedo_lp = (reg & 0xFFFF) * 4;
+	*speedo_g = ((reg >> 16) & 0xFFFF) * 4;
+
+	ate_ver = tegra_fuse_readl(FUSE_TEST_PROG_VER);
+	pr_info("%s: ATE prog ver %d.%d\n", __func__, ate_ver/10, ate_ver%10);
+
+	if (ate_ver >= 26) {
+		bit_minus1 = tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1);
+		bit_minus1 |= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1_R);
+		bit_minus2 = tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2);
+		bit_minus2 |= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2_R);
+		*speedo_lp |= (bit_minus1 << 1) | bit_minus2;
+
+		bit_minus1 = tegra_spare_fuse(G_SPEEDO_BIT_MINUS1);
+		bit_minus1 |= tegra_spare_fuse(G_SPEEDO_BIT_MINUS1_R);
+		bit_minus2 = tegra_spare_fuse(G_SPEEDO_BIT_MINUS2);
+		bit_minus2 |= tegra_spare_fuse(G_SPEEDO_BIT_MINUS2_R);
+		*speedo_g |= (bit_minus1 << 1) | bit_minus2;
+	} else {
+		*speedo_lp |= 0x3;
+		*speedo_g |= 0x3;
+	}
+}
+
+static void rev_sku_to_speedo_ids(int rev, int sku)
+{
+	switch (rev) {
+	case TEGRA_REVISION_A01:
+		tegra_cpu_speedo_id = 0;
+		tegra_soc_speedo_id = 0;
+		threshold_index = THRESHOLD_INDEX_0;
+		break;
+	case TEGRA_REVISION_A02:
+	case TEGRA_REVISION_A03:
+		switch (sku) {
+		case 0x87:
+		case 0x82:
+			tegra_cpu_speedo_id = 1;
+			tegra_soc_speedo_id = 1;
+			threshold_index = THRESHOLD_INDEX_1;
+			break;
+		case 0x81:
+			switch (package_id) {
+			case 1:
+				tegra_cpu_speedo_id = 2;
+				tegra_soc_speedo_id = 2;
+				threshold_index = THRESHOLD_INDEX_2;
+				break;
+			case 2:
+				tegra_cpu_speedo_id = 4;
+				tegra_soc_speedo_id = 1;
+				threshold_index = THRESHOLD_INDEX_7;
+				break;
+			default:
+				pr_err("Tegra30: Unknown pkg %d\n", package_id);
+				BUG();
+				break;
+			}
+			break;
+		case 0x80:
+			switch (package_id) {
+			case 1:
+				tegra_cpu_speedo_id = 5;
+				tegra_soc_speedo_id = 2;
+				threshold_index = THRESHOLD_INDEX_8;
+				break;
+			case 2:
+				tegra_cpu_speedo_id = 6;
+				tegra_soc_speedo_id = 2;
+				threshold_index = THRESHOLD_INDEX_9;
+				break;
+			default:
+				pr_err("Tegra30: Unknown pkg %d\n", package_id);
+				BUG();
+				break;
+			}
+			break;
+		case 0x83:
+			switch (package_id) {
+			case 1:
+				tegra_cpu_speedo_id = 7;
+				tegra_soc_speedo_id = 1;
+				threshold_index = THRESHOLD_INDEX_10;
+				break;
+			case 2:
+				tegra_cpu_speedo_id = 3;
+				tegra_soc_speedo_id = 2;
+				threshold_index = THRESHOLD_INDEX_3;
+				break;
+			default:
+				pr_err("Tegra30: Unknown pkg %d\n", package_id);
+				BUG();
+				break;
+			}
+			break;
+		case 0x8F:
+			tegra_cpu_speedo_id = 8;
+			tegra_soc_speedo_id = 1;
+			threshold_index = THRESHOLD_INDEX_11;
+			break;
+		case 0x08:
+			tegra_cpu_speedo_id = 1;
+			tegra_soc_speedo_id = 1;
+			threshold_index = THRESHOLD_INDEX_4;
+			break;
+		case 0x02:
+			tegra_cpu_speedo_id = 2;
+			tegra_soc_speedo_id = 2;
+			threshold_index = THRESHOLD_INDEX_5;
+			break;
+		case 0x04:
+			tegra_cpu_speedo_id = 3;
+			tegra_soc_speedo_id = 2;
+			threshold_index = THRESHOLD_INDEX_6;
+			break;
+		case 0:
+			switch (package_id) {
+			case 1:
+				tegra_cpu_speedo_id = 2;
+				tegra_soc_speedo_id = 2;
+				threshold_index = THRESHOLD_INDEX_2;
+				break;
+			case 2:
+				tegra_cpu_speedo_id = 3;
+				tegra_soc_speedo_id = 2;
+				threshold_index = THRESHOLD_INDEX_3;
+				break;
+			default:
+				pr_err("Tegra30: Unknown pkg %d\n", package_id);
+				BUG();
+				break;
+			}
+			break;
+		default:
+			pr_warn("Tegra30: Unknown SKU %d\n", sku);
+			tegra_cpu_speedo_id = 0;
+			tegra_soc_speedo_id = 0;
+			threshold_index = THRESHOLD_INDEX_0;
+			break;
+		}
+		break;
+	default:
+		pr_warn("Tegra30: Unknown chip rev %d\n", rev);
+		tegra_cpu_speedo_id = 0;
+		tegra_soc_speedo_id = 0;
+		threshold_index = THRESHOLD_INDEX_0;
+		break;
+	}
+}
+
+void tegra30_init_speedo_data(void)
+{
+	u32 cpu_speedo_val;
+	u32 core_speedo_val;
+	int i;
+
+	BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
+			THRESHOLD_INDEX_COUNT);
+	BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
+			THRESHOLD_INDEX_COUNT);
+
+	package_id = tegra_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
+
+	rev_sku_to_speedo_ids(tegra_revision, tegra_sku_id);
+	fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val);
+	pr_debug("%s CPU speedo value %u\n", __func__, cpu_speedo_val);
+	pr_debug("%s Core speedo value %u\n", __func__, core_speedo_val);
+
+	for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++) {
+		if (cpu_speedo_val < cpu_process_speedos[threshold_index][i])
+			break;
+	}
+	tegra_cpu_process_id = i - 1;
+
+	if (tegra_cpu_process_id == -1) {
+		pr_warn("Tegra30: CPU speedo value %3d out of range",
+		       cpu_speedo_val);
+		tegra_cpu_process_id = 0;
+		tegra_cpu_speedo_id = 1;
+	}
+
+	for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++) {
+		if (core_speedo_val < core_process_speedos[threshold_index][i])
+			break;
+	}
+	tegra_core_process_id = i - 1;
+
+	if (tegra_core_process_id == -1) {
+		pr_warn("Tegra30: CORE speedo value %3d out of range",
+		       core_speedo_val);
+		tegra_core_process_id = 0;
+		tegra_soc_speedo_id = 1;
+	}
+
+	pr_info("Tegra30: CPU Speedo ID %d, Soc Speedo ID %d",
+		tegra_cpu_speedo_id, tegra_soc_speedo_id);
+}
diff --git a/arch/arm/mach-tegra/tegra_cpu_car.h b/arch/arm/mach-tegra/tegra_cpu_car.h
index 30d063a..9764d31 100644
--- a/arch/arm/mach-tegra/tegra_cpu_car.h
+++ b/arch/arm/mach-tegra/tegra_cpu_car.h
@@ -30,6 +30,12 @@
  *	CPU clock un-gate
  * disable_clock:
  *	CPU clock gate
+ * rail_off_ready:
+ *	CPU is ready for rail off
+ * suspend:
+ *	save the clock settings when CPU go into low-power state
+ * resume:
+ *	restore the clock settings when CPU exit low-power state
  */
 struct tegra_cpu_car_ops {
 	void (*wait_for_reset)(u32 cpu);
@@ -37,6 +43,11 @@ struct tegra_cpu_car_ops {
 	void (*out_of_reset)(u32 cpu);
 	void (*enable_clock)(u32 cpu);
 	void (*disable_clock)(u32 cpu);
+#ifdef CONFIG_PM_SLEEP
+	bool (*rail_off_ready)(void);
+	void (*suspend)(void);
+	void (*resume)(void);
+#endif
 };
 
 extern struct tegra_cpu_car_ops *tegra_cpu_car_ops;
@@ -81,6 +92,32 @@ static inline void tegra_disable_cpu_clock(u32 cpu)
 	tegra_cpu_car_ops->disable_clock(cpu);
 }
 
+#ifdef CONFIG_PM_SLEEP
+static inline bool tegra_cpu_rail_off_ready(void)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->rail_off_ready))
+		return false;
+
+	return tegra_cpu_car_ops->rail_off_ready();
+}
+
+static inline void tegra_cpu_clock_suspend(void)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->suspend))
+		return;
+
+	tegra_cpu_car_ops->suspend();
+}
+
+static inline void tegra_cpu_clock_resume(void)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->resume))
+		return;
+
+	tegra_cpu_car_ops->resume();
+}
+#endif
+
 void tegra20_cpu_car_ops_init(void);
 void tegra30_cpu_car_ops_init(void);
 
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
index d3b8c8e..e4863f3 100644
--- a/arch/arm/mach-tegra/timer.c
+++ b/arch/arm/mach-tegra/timer.c
@@ -26,16 +26,14 @@
 #include <linux/clocksource.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <asm/mach/time.h>
 #include <asm/smp_twd.h>
 #include <asm/sched_clock.h>
 
-#include <mach/iomap.h>
-#include <mach/irqs.h>
-
 #include "board.h"
-#include "clock.h"
 
 #define RTC_SECONDS            0x08
 #define RTC_SHADOW_SECONDS     0x0c
@@ -53,8 +51,8 @@
 #define TIMER_PTV 0x0
 #define TIMER_PCR 0x4
 
-static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE);
-static void __iomem *rtc_base = IO_ADDRESS(TEGRA_RTC_BASE);
+static void __iomem *timer_reg_base;
+static void __iomem *rtc_base;
 
 static struct timespec persistent_ts;
 static u64 persistent_ms, last_persistent_ms;
@@ -158,40 +156,66 @@ static struct irqaction tegra_timer_irq = {
 	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH,
 	.handler	= tegra_timer_interrupt,
 	.dev_id		= &tegra_clockevent,
-	.irq		= INT_TMR3,
 };
 
-#ifdef CONFIG_HAVE_ARM_TWD
-static DEFINE_TWD_LOCAL_TIMER(twd_local_timer,
-			      TEGRA_ARM_PERIF_BASE + 0x600,
-			      IRQ_LOCALTIMER);
+static const struct of_device_id timer_match[] __initconst = {
+	{ .compatible = "nvidia,tegra20-timer" },
+	{}
+};
 
-static void __init tegra_twd_init(void)
-{
-	int err = twd_local_timer_register(&twd_local_timer);
-	if (err)
-		pr_err("twd_local_timer_register failed %d\n", err);
-}
-#else
-#define tegra_twd_init()	do {} while(0)
-#endif
+static const struct of_device_id rtc_match[] __initconst = {
+	{ .compatible = "nvidia,tegra20-rtc" },
+	{}
+};
 
 static void __init tegra_init_timer(void)
 {
+	struct device_node *np;
 	struct clk *clk;
 	unsigned long rate;
 	int ret;
 
+	np = of_find_matching_node(NULL, timer_match);
+	if (!np) {
+		pr_err("Failed to find timer DT node\n");
+		BUG();
+	}
+
+	timer_reg_base = of_iomap(np, 0);
+	if (!timer_reg_base) {
+		pr_err("Can't map timer registers");
+		BUG();
+	}
+
+	tegra_timer_irq.irq = irq_of_parse_and_map(np, 2);
+	if (tegra_timer_irq.irq <= 0) {
+		pr_err("Failed to map timer IRQ\n");
+		BUG();
+	}
+
 	clk = clk_get_sys("timer", NULL);
 	if (IS_ERR(clk)) {
-		pr_warn("Unable to get timer clock."
-			" Assuming 12Mhz input clock.\n");
+		pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n");
 		rate = 12000000;
 	} else {
 		clk_prepare_enable(clk);
 		rate = clk_get_rate(clk);
 	}
 
+	of_node_put(np);
+
+	np = of_find_matching_node(NULL, rtc_match);
+	if (!np) {
+		pr_err("Failed to find RTC DT node\n");
+		BUG();
+	}
+
+	rtc_base = of_iomap(np, 0);
+	if (!rtc_base) {
+		pr_err("Can't map RTC registers");
+		BUG();
+	}
+
 	/*
 	 * rtc registers are used by read_persistent_clock, keep the rtc clock
 	 * enabled
@@ -202,6 +226,8 @@ static void __init tegra_init_timer(void)
 	else
 		clk_prepare_enable(clk);
 
+	of_node_put(np);
+
 	switch (rate) {
 	case 12000000:
 		timer_writel(0x000b, TIMERUS_USEC_CFG);
@@ -223,13 +249,13 @@ static void __init tegra_init_timer(void)
 
 	if (clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US,
 		"timer_us", 1000000, 300, 32, clocksource_mmio_readl_up)) {
-		printk(KERN_ERR "Failed to register clocksource\n");
+		pr_err("Failed to register clocksource\n");
 		BUG();
 	}
 
 	ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq);
 	if (ret) {
-		printk(KERN_ERR "Failed to register timer IRQ: %d\n", ret);
+		pr_err("Failed to register timer IRQ: %d\n", ret);
 		BUG();
 	}
 
@@ -241,7 +267,9 @@ static void __init tegra_init_timer(void)
 	tegra_clockevent.cpumask = cpu_all_mask;
 	tegra_clockevent.irq = tegra_timer_irq.irq;
 	clockevents_register_device(&tegra_clockevent);
-	tegra_twd_init();
+#ifdef CONFIG_HAVE_ARM_TWD
+	twd_local_timer_of_register();
+#endif
 	register_persistent_clock(NULL, tegra_read_persistent_clock);
 }
 
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index b8efac4..8b204ae 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -82,8 +82,6 @@ static struct map_desc u300_io_desc[] __initdata = {
 static void __init u300_map_io(void)
 {
 	iotable_init(u300_io_desc, ARRAY_SIZE(u300_io_desc));
-	/* We enable a real big DMA buffer if need be. */
-	init_consistent_dma_size(SZ_4M);
 }
 
 /*
@@ -252,6 +250,18 @@ static struct resource rtc_resources[] = {
  */
 static struct resource fsmc_resources[] = {
 	{
+		.name  = "nand_addr",
+		.start = U300_NAND_CS0_PHYS_BASE + PLAT_NAND_ALE,
+		.end   = U300_NAND_CS0_PHYS_BASE + PLAT_NAND_ALE + SZ_16K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name  = "nand_cmd",
+		.start = U300_NAND_CS0_PHYS_BASE + PLAT_NAND_CLE,
+		.end   = U300_NAND_CS0_PHYS_BASE + PLAT_NAND_CLE + SZ_16K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
 		.name  = "nand_data",
 		.start = U300_NAND_CS0_PHYS_BASE,
 		.end   = U300_NAND_CS0_PHYS_BASE + SZ_16K - 1,
@@ -1445,8 +1455,6 @@ static struct platform_device pinctrl_device = {
 static struct u300_gpio_platform u300_gpio_plat = {
 	.ports = 7,
 	.gpio_base = 0,
-	.gpio_irq_base = IRQ_U300_GPIO_BASE,
-	.pinctrl_device = &pinctrl_device,
 };
 
 static struct platform_device gpio_device = {
@@ -1496,8 +1504,6 @@ static struct fsmc_nand_platform_data nand_platform_data = {
 	.nr_partitions = ARRAY_SIZE(u300_partitions),
 	.options = NAND_SKIP_BBTSCAN,
 	.width = FSMC_NAND_BW8,
-	.ale_off = PLAT_NAND_ALE,
-	.cle_off = PLAT_NAND_CLE,
 };
 
 static struct platform_device nand_device = {
@@ -1590,6 +1596,7 @@ static struct platform_device *platform_devs[] __initdata = {
 	&i2c1_device,
 	&keypad_device,
 	&rtc_device,
+	&pinctrl_device,
 	&gpio_device,
 	&nand_device,
 	&wdog_device,
@@ -1804,7 +1811,7 @@ MACHINE_START(U300, "Ericsson AB U335 S335/B335 Prototype Board")
 	/* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
 	.atag_offset	= 0x100,
 	.map_io		= u300_map_io,
-	.nr_irqs	= NR_IRQS_U300,
+	.nr_irqs	= 0,
 	.init_irq	= u300_init_irq,
 	.handle_irq	= vic_handle_irq,
 	.timer		= &u300_timer,
diff --git a/arch/arm/mach-u300/include/mach/irqs.h b/arch/arm/mach-u300/include/mach/irqs.h
index e27425a..21d5e76 100644
--- a/arch/arm/mach-u300/include/mach/irqs.h
+++ b/arch/arm/mach-u300/include/mach/irqs.h
@@ -12,79 +12,69 @@
 #ifndef __MACH_IRQS_H
 #define __MACH_IRQS_H
 
-#define IRQ_U300_INTCON0_START		1
-#define IRQ_U300_INTCON1_START		33
+#define IRQ_U300_INTCON0_START		32
+#define IRQ_U300_INTCON1_START		64
 /* These are on INTCON0 - 30 lines */
-#define IRQ_U300_IRQ0_EXT		1
-#define IRQ_U300_IRQ1_EXT		2
-#define IRQ_U300_DMA			3
-#define IRQ_U300_VIDEO_ENC_0		4
-#define IRQ_U300_VIDEO_ENC_1		5
-#define IRQ_U300_AAIF_RX		6
-#define IRQ_U300_AAIF_TX		7
-#define IRQ_U300_AAIF_VGPIO		8
-#define IRQ_U300_AAIF_WAKEUP		9
-#define IRQ_U300_PCM_I2S0_FRAME		10
-#define IRQ_U300_PCM_I2S0_FIFO		11
-#define IRQ_U300_PCM_I2S1_FRAME		12
-#define IRQ_U300_PCM_I2S1_FIFO		13
-#define IRQ_U300_XGAM_GAMCON		14
-#define IRQ_U300_XGAM_CDI		15
-#define IRQ_U300_XGAM_CDICON		16
-#define IRQ_U300_XGAM_PDI		18
-#define IRQ_U300_XGAM_PDICON		19
-#define IRQ_U300_XGAM_GAMEACC		20
-#define IRQ_U300_XGAM_MCIDCT		21
-#define IRQ_U300_APEX			22
-#define IRQ_U300_UART0			23
-#define IRQ_U300_SPI			24
-#define IRQ_U300_TIMER_APP_OS		25
-#define IRQ_U300_TIMER_APP_DD		26
-#define IRQ_U300_TIMER_APP_GP1		27
-#define IRQ_U300_TIMER_APP_GP2		28
-#define IRQ_U300_TIMER_OS		29
-#define IRQ_U300_TIMER_MS		30
-#define IRQ_U300_KEYPAD_KEYBF		31
-#define IRQ_U300_KEYPAD_KEYBR		32
+#define IRQ_U300_IRQ0_EXT		32
+#define IRQ_U300_IRQ1_EXT		33
+#define IRQ_U300_DMA			34
+#define IRQ_U300_VIDEO_ENC_0		35
+#define IRQ_U300_VIDEO_ENC_1		36
+#define IRQ_U300_AAIF_RX		37
+#define IRQ_U300_AAIF_TX		38
+#define IRQ_U300_AAIF_VGPIO		39
+#define IRQ_U300_AAIF_WAKEUP		40
+#define IRQ_U300_PCM_I2S0_FRAME		41
+#define IRQ_U300_PCM_I2S0_FIFO		42
+#define IRQ_U300_PCM_I2S1_FRAME		43
+#define IRQ_U300_PCM_I2S1_FIFO		44
+#define IRQ_U300_XGAM_GAMCON		45
+#define IRQ_U300_XGAM_CDI		46
+#define IRQ_U300_XGAM_CDICON		47
+#define IRQ_U300_XGAM_PDI		49
+#define IRQ_U300_XGAM_PDICON		50
+#define IRQ_U300_XGAM_GAMEACC		51
+#define IRQ_U300_XGAM_MCIDCT		52
+#define IRQ_U300_APEX			53
+#define IRQ_U300_UART0			54
+#define IRQ_U300_SPI			55
+#define IRQ_U300_TIMER_APP_OS		56
+#define IRQ_U300_TIMER_APP_DD		57
+#define IRQ_U300_TIMER_APP_GP1		58
+#define IRQ_U300_TIMER_APP_GP2		59
+#define IRQ_U300_TIMER_OS		60
+#define IRQ_U300_TIMER_MS		61
+#define IRQ_U300_KEYPAD_KEYBF		62
+#define IRQ_U300_KEYPAD_KEYBR		63
 /* These are on INTCON1 - 32 lines */
-#define IRQ_U300_GPIO_PORT0		33
-#define IRQ_U300_GPIO_PORT1		34
-#define IRQ_U300_GPIO_PORT2		35
+#define IRQ_U300_GPIO_PORT0		64
+#define IRQ_U300_GPIO_PORT1		65
+#define IRQ_U300_GPIO_PORT2		66
 
 /* These are for DB3150, DB3200 and DB3350 */
-#define IRQ_U300_WDOG			36
-#define IRQ_U300_EVHIST			37
-#define IRQ_U300_MSPRO			38
-#define IRQ_U300_MMCSD_MCIINTR0		39
-#define IRQ_U300_MMCSD_MCIINTR1		40
-#define IRQ_U300_I2C0			41
-#define IRQ_U300_I2C1			42
-#define IRQ_U300_RTC			43
-#define IRQ_U300_NFIF			44
-#define IRQ_U300_NFIF2			45
+#define IRQ_U300_WDOG			67
+#define IRQ_U300_EVHIST			68
+#define IRQ_U300_MSPRO			69
+#define IRQ_U300_MMCSD_MCIINTR0		70
+#define IRQ_U300_MMCSD_MCIINTR1		71
+#define IRQ_U300_I2C0			72
+#define IRQ_U300_I2C1			73
+#define IRQ_U300_RTC			74
+#define IRQ_U300_NFIF			75
+#define IRQ_U300_NFIF2			76
 
 /* The DB3350-specific interrupt lines */
-#define IRQ_U300_ISP_F0			46
-#define IRQ_U300_ISP_F1			47
-#define IRQ_U300_ISP_F2			48
-#define IRQ_U300_ISP_F3			49
-#define IRQ_U300_ISP_F4			50
-#define IRQ_U300_GPIO_PORT3		51
-#define IRQ_U300_SYSCON_PLL_LOCK	52
-#define IRQ_U300_UART1			53
-#define IRQ_U300_GPIO_PORT4		54
-#define IRQ_U300_GPIO_PORT5		55
-#define IRQ_U300_GPIO_PORT6		56
-#define U300_VIC_IRQS_END		57
-
-/* Maximum 8*7 GPIO lines */
-#ifdef CONFIG_PINCTRL_COH901
-#define IRQ_U300_GPIO_BASE		(U300_VIC_IRQS_END)
-#define IRQ_U300_GPIO_END		(IRQ_U300_GPIO_BASE + 56)
-#else
-#define IRQ_U300_GPIO_END		(U300_VIC_IRQS_END)
-#endif
-
-#define NR_IRQS_U300			(IRQ_U300_GPIO_END - IRQ_U300_INTCON0_START)
+#define IRQ_U300_ISP_F0			77
+#define IRQ_U300_ISP_F1			78
+#define IRQ_U300_ISP_F2			79
+#define IRQ_U300_ISP_F3			80
+#define IRQ_U300_ISP_F4			81
+#define IRQ_U300_GPIO_PORT3		82
+#define IRQ_U300_SYSCON_PLL_LOCK	83
+#define IRQ_U300_UART1			84
+#define IRQ_U300_GPIO_PORT4		85
+#define IRQ_U300_GPIO_PORT5		86
+#define IRQ_U300_GPIO_PORT6		87
+#define U300_VIC_IRQS_END		88
 
 #endif
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index e8c3f0d..5dea906 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -7,8 +7,8 @@ config UX500_SOC_COMMON
 	select ARM_ERRATA_764369 if SMP
 	select ARM_GIC
 	select CACHE_L2X0
+	select CLKSRC_NOMADIK_MTU
 	select COMMON_CLK
-	select HAS_MTU
 	select PINCTRL
 	select PINCTRL_NOMADIK
 	select PL310_ERRATA_753970 if CACHE_PL310
diff --git a/arch/arm/mach-ux500/board-mop500-audio.c b/arch/arm/mach-ux500/board-mop500-audio.c
index 070629a..7209db7 100644
--- a/arch/arm/mach-ux500/board-mop500-audio.c
+++ b/arch/arm/mach-ux500/board-mop500-audio.c
@@ -7,10 +7,8 @@
 #include <linux/platform_device.h>
 #include <linux/init.h>
 #include <linux/gpio.h>
-
-#include <plat/gpio-nomadik.h>
-#include <plat/pincfg.h>
-#include <plat/ste_dma40.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
+#include <linux/platform_data/dma-ste-dma40.h>
 
 #include <mach/devices.h>
 #include <mach/hardware.h>
@@ -150,15 +148,6 @@ static struct platform_device snd_soc_mop500 = {
 	},
 };
 
-/* Platform device for Ux500-PCM */
-static struct platform_device ux500_pcm = {
-		.name = "ux500-pcm",
-		.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,
@@ -186,10 +175,3 @@ void mop500_audio_init(struct device *parent)
 	db8500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1,
 			   &msp3_platform_data);
 }
-
-/* Due for removal once the MSP driver has been fully DT:ed. */
-void mop500_of_audio_init(struct device *parent)
-{
-	pr_info("%s: Register platform-device 'ux500-pcm'\n", __func__);
-	platform_device_register(&ux500_pcm);
-}
diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c
index a267c6d..0a3f30d 100644
--- a/arch/arm/mach-ux500/board-mop500-pins.c
+++ b/arch/arm/mach-ux500/board-mop500-pins.c
@@ -9,10 +9,9 @@
 #include <linux/bug.h>
 #include <linux/string.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 #include <asm/mach-types.h>
-#include <plat/pincfg.h>
-#include <plat/gpio-nomadik.h>
 
 #include <mach/hardware.h>
 
@@ -34,8 +33,6 @@ BIAS(in_nopull, PIN_INPUT_NOPULL);
 BIAS(in_nopull_slpm_nowkup, PIN_INPUT_NOPULL|PIN_SLPM_WAKEUP_DISABLE);
 BIAS(in_pu, PIN_INPUT_PULLUP);
 BIAS(in_pd, PIN_INPUT_PULLDOWN);
-BIAS(in_pd_slpm_in_pu, PIN_INPUT_PULLDOWN|PIN_SLPM_INPUT_PULLUP);
-BIAS(in_pu_slpm_out_lo, PIN_INPUT_PULLUP|PIN_SLPM_OUTPUT_LOW);
 BIAS(out_hi, PIN_OUTPUT_HIGH);
 BIAS(out_lo, PIN_OUTPUT_LOW);
 BIAS(out_lo_slpm_nowkup, PIN_OUTPUT_LOW|PIN_SLPM_WAKEUP_DISABLE);
@@ -47,14 +44,34 @@ BIAS(gpio_in_pd_slpm_gpio_nopull, PIN_INPUT_PULLDOWN|PIN_GPIOMODE_ENABLED|PIN_SL
 BIAS(gpio_out_hi, PIN_OUTPUT_HIGH|PIN_GPIOMODE_ENABLED);
 BIAS(gpio_out_lo, PIN_OUTPUT_LOW|PIN_GPIOMODE_ENABLED);
 /* Sleep modes */
-BIAS(slpm_in_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
-BIAS(slpm_in_nopull_wkup, PIN_SLEEPMODE_ENABLED|PIN_SLPM_DIR_INPUT|PIN_SLPM_PULL_NONE|PIN_SLPM_WAKEUP_ENABLE);
-BIAS(slpm_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
-BIAS(slpm_out_hi_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_HIGH|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
-BIAS(slpm_out_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
-BIAS(slpm_out_lo_wkup, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE);
-BIAS(slpm_out_lo_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
-BIAS(slpm_in_nopull_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_INPUT_NOPULL|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(slpm_in_nopull_wkup, PIN_SLEEPMODE_ENABLED|
+	PIN_SLPM_DIR_INPUT|PIN_SLPM_PULL_NONE|PIN_SLPM_WAKEUP_ENABLE);
+BIAS(slpm_in_wkup_pdis, PIN_SLEEPMODE_ENABLED|
+	PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(slpm_wkup_pdis, PIN_SLEEPMODE_ENABLED|
+	PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(slpm_out_lo_pdis, PIN_SLEEPMODE_ENABLED|
+	PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_DISABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(slpm_out_lo_wkup, PIN_SLEEPMODE_ENABLED|
+	PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE);
+BIAS(slpm_out_lo_wkup_pdis, PIN_SLEEPMODE_ENABLED|
+	PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(slpm_out_hi_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_HIGH|
+	PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(slpm_in_nopull_wkup_pdis, PIN_SLEEPMODE_ENABLED|
+	PIN_SLPM_INPUT_NOPULL|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(slpm_in_pu_wkup_pdis_en, PIN_SLEEPMODE_ENABLED|PIN_SLPM_INPUT_PULLUP|
+	PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_ENABLED);
+BIAS(slpm_out_wkup_pdis, PIN_SLEEPMODE_ENABLED|
+	PIN_SLPM_DIR_OUTPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(out_lo_wkup_pdis, PIN_SLPM_OUTPUT_LOW|
+	PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(in_wkup_pdis_en, PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|
+	PIN_SLPM_PDIS_ENABLED);
+BIAS(in_wkup_pdis, PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|
+	PIN_SLPM_PDIS_DISABLED);
+BIAS(out_wkup_pdis, PIN_SLPM_DIR_OUTPUT|PIN_SLPM_WAKEUP_ENABLE|
+	PIN_SLPM_PDIS_DISABLED);
 
 /* We use these to define hog settings that are always done on boot */
 #define DB8500_MUX_HOG(group,func) \
@@ -70,13 +87,16 @@ BIAS(slpm_in_nopull_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_INPUT_NOPULL|PIN_S
 	PIN_MAP_MUX_GROUP_DEFAULT(dev, "pinctrl-db8500", group, func)
 #define DB8500_PIN(pin,conf,dev) \
 	PIN_MAP_CONFIGS_PIN_DEFAULT(dev, "pinctrl-db8500", pin, conf)
-#define DB8500_PIN_SLEEP(pin, conf, dev) \
-	PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_SLEEP, "pinctrl-db8500",	\
+#define DB8500_PIN_IDLE(pin, conf, dev) \
+	PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_IDLE, "pinctrl-db8500",	\
 			    pin, conf)
-
-#define DB8500_PIN_SLEEP(pin,conf,dev) \
+#define DB8500_PIN_SLEEP(pin, conf, dev) \
 	PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_SLEEP, "pinctrl-db8500",	\
 			    pin, conf)
+#define DB8500_MUX_STATE(group, func, dev, state) \
+	PIN_MAP_MUX_GROUP(dev, state, "pinctrl-db8500", group, func)
+#define DB8500_PIN_STATE(pin, conf, dev, state) \
+	PIN_MAP_CONFIGS_PIN(dev, state, "pinctrl-db8500", pin, conf)
 
 /* Pin control settings */
 static struct pinctrl_map __initdata mop500_family_pinmap[] = {
@@ -113,7 +133,7 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
 	 * UART0, we do not mux in u0 here.
 	 * uart-0 pins gpio configuration should be kept intact to prevent
 	 * a glitch in tx line when the tty dev is opened. Later these pins
-	 * are configured to uart mop500_pins_uart0
+	 * are configured by uart driver
 	 */
 	DB8500_PIN_HOG("GPIO0_AJ5", in_pu), /* CTS */
 	DB8500_PIN_HOG("GPIO1_AJ3", out_hi), /* RTS */
@@ -124,12 +144,13 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
 	 * TODO: is this used on U8500 variants and Snowball really?
 	 * The setting on GPIO31 conflicts with magnetometer use on hrefv60
 	 */
-	DB8500_MUX_HOG("u2rxtx_c_1", "u2"),
-	DB8500_MUX_HOG("u2ctsrts_c_1", "u2"),
-	DB8500_PIN_HOG("GPIO29_W2", in_pu), /* RXD */
-	DB8500_PIN_HOG("GPIO30_W3", out_hi), /* TXD */
-	DB8500_PIN_HOG("GPIO31_V3", in_pu), /* CTS */
-	DB8500_PIN_HOG("GPIO32_V2", out_hi), /* RTS */
+	/* default state for UART2 */
+	DB8500_MUX("u2rxtx_c_1", "u2", "uart2"),
+	DB8500_PIN("GPIO29_W2", in_pu, "uart2"), /* RXD */
+	DB8500_PIN("GPIO30_W3", out_hi, "uart2"), /* TXD */
+	/* Sleep state for UART2 */
+	DB8500_PIN_SLEEP("GPIO29_W2", in_wkup_pdis, "uart2"),
+	DB8500_PIN_SLEEP("GPIO30_W3", out_wkup_pdis, "uart2"),
 	/*
 	 * The following pin sets were known as "runtime pins" before being
 	 * converted to the pinctrl model. Here we model them as "default"
@@ -141,11 +162,18 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
 	DB8500_PIN("GPIO1_AJ3", out_hi, "uart0"), /* RTS */
 	DB8500_PIN("GPIO2_AH4", in_pu, "uart0"), /* RXD */
 	DB8500_PIN("GPIO3_AH3", out_hi, "uart0"), /* TXD */
-	/* UART0 sleep state */
+	/* Sleep state for UART0 */
 	DB8500_PIN_SLEEP("GPIO0_AJ5", slpm_in_wkup_pdis, "uart0"),
 	DB8500_PIN_SLEEP("GPIO1_AJ3", slpm_out_hi_wkup_pdis, "uart0"),
 	DB8500_PIN_SLEEP("GPIO2_AH4", slpm_in_wkup_pdis, "uart0"),
 	DB8500_PIN_SLEEP("GPIO3_AH3", slpm_out_wkup_pdis, "uart0"),
+	/* Mux in UART1 after initialization */
+	DB8500_MUX("u1rxtx_a_1", "u1", "uart1"),
+	DB8500_PIN("GPIO4_AH6", in_pu, "uart1"), /* RXD */
+	DB8500_PIN("GPIO5_AG6", out_hi, "uart1"), /* TXD */
+	/* Sleep state for UART1 */
+	DB8500_PIN_SLEEP("GPIO4_AH6", slpm_in_wkup_pdis, "uart1"),
+	DB8500_PIN_SLEEP("GPIO5_AG6", slpm_out_wkup_pdis, "uart1"),
 	/* MSP1 for ALSA codec */
 	DB8500_MUX("msp1txrx_a_1", "msp1", "ux500-msp-i2s.1"),
 	DB8500_MUX("msp1_a_1", "msp1", "ux500-msp-i2s.1"),
@@ -162,7 +190,10 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
 	DB8500_MUX("lcd_d8_d11_a_1", "lcd", "mcde-tvout"),
 	DB8500_MUX("lcdaclk_b_1", "lcda", "mcde-tvout"),
 	/* Mux in LCD VSI1 and pull it up for MCDE HDMI output */
-	DB8500_MUX("lcdvsi1_a_1", "lcd", "av8100-hdmi"),
+	DB8500_MUX("lcdvsi1_a_1", "lcd", "0-0070"),
+	DB8500_PIN("GPIO69_E2", in_pu, "0-0070"),
+	/* LCD VSI1 sleep state */
+	DB8500_PIN_SLEEP("GPIO69_E2", slpm_in_wkup_pdis, "0-0070"),
 	/* Mux in i2c0 block, default state */
 	DB8500_MUX("i2c0_a_1", "i2c0", "nmk-i2c.0"),
 	/* i2c0 sleep state */
@@ -195,6 +226,18 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
 	DB8500_PIN("GPIO26_Y2", in_pu, "sdi0"), /* DAT1 */
 	DB8500_PIN("GPIO27_AA2", in_pu, "sdi0"), /* DAT2 */
 	DB8500_PIN("GPIO28_AA1", in_pu, "sdi0"), /* DAT3 */
+	/* SDI0 sleep state */
+	DB8500_PIN_SLEEP("GPIO18_AC2", slpm_out_hi_wkup_pdis, "sdi0"),
+	DB8500_PIN_SLEEP("GPIO19_AC1", slpm_out_hi_wkup_pdis, "sdi0"),
+	DB8500_PIN_SLEEP("GPIO20_AB4", slpm_out_hi_wkup_pdis, "sdi0"),
+	DB8500_PIN_SLEEP("GPIO22_AA3", slpm_in_wkup_pdis, "sdi0"),
+	DB8500_PIN_SLEEP("GPIO23_AA4", slpm_out_lo_wkup_pdis, "sdi0"),
+	DB8500_PIN_SLEEP("GPIO24_AB2", slpm_in_wkup_pdis, "sdi0"),
+	DB8500_PIN_SLEEP("GPIO25_Y4", slpm_in_wkup_pdis, "sdi0"),
+	DB8500_PIN_SLEEP("GPIO26_Y2", slpm_in_wkup_pdis, "sdi0"),
+	DB8500_PIN_SLEEP("GPIO27_AA2", slpm_in_wkup_pdis, "sdi0"),
+	DB8500_PIN_SLEEP("GPIO28_AA1", slpm_in_wkup_pdis, "sdi0"),
+
 	/* Mux in SDI1 (here called MC1) used for SDIO for CW1200 WLAN */
 	DB8500_MUX("mc1_a_1", "mc1", "sdi1"),
 	DB8500_PIN("GPIO208_AH16", out_lo, "sdi1"), /* CLK */
@@ -204,6 +247,15 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
 	DB8500_PIN("GPIO212_AF13", in_pu, "sdi1"), /* DAT1 */
 	DB8500_PIN("GPIO213_AG13", in_pu, "sdi1"), /* DAT2 */
 	DB8500_PIN("GPIO214_AH15", in_pu, "sdi1"), /* DAT3 */
+	/* SDI1 sleep state */
+	DB8500_PIN_SLEEP("GPIO208_AH16", slpm_out_lo_wkup_pdis, "sdi1"), /* CLK */
+	DB8500_PIN_SLEEP("GPIO209_AG15", slpm_in_wkup_pdis, "sdi1"), /* FBCLK */
+	DB8500_PIN_SLEEP("GPIO210_AJ15", slpm_in_wkup_pdis, "sdi1"), /* CMD */
+	DB8500_PIN_SLEEP("GPIO211_AG14", slpm_in_wkup_pdis, "sdi1"), /* DAT0 */
+	DB8500_PIN_SLEEP("GPIO212_AF13", slpm_in_wkup_pdis, "sdi1"), /* DAT1 */
+	DB8500_PIN_SLEEP("GPIO213_AG13", slpm_in_wkup_pdis, "sdi1"), /* DAT2 */
+	DB8500_PIN_SLEEP("GPIO214_AH15", slpm_in_wkup_pdis, "sdi1"), /* DAT3 */
+
 	/* Mux in SDI2 (here called MC2) used for for PoP eMMC */
 	DB8500_MUX("mc2_a_1", "mc2", "sdi2"),
 	DB8500_PIN("GPIO128_A5", out_lo, "sdi2"), /* CLK */
@@ -217,6 +269,19 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
 	DB8500_PIN("GPIO136_C7", in_pu, "sdi2"), /* DAT5 */
 	DB8500_PIN("GPIO137_A7", in_pu, "sdi2"), /* DAT6 */
 	DB8500_PIN("GPIO138_C5", in_pu, "sdi2"), /* DAT7 */
+	/* SDI2 sleep state */
+	DB8500_PIN_SLEEP("GPIO128_A5", out_lo_wkup_pdis, "sdi2"), /* CLK */
+	DB8500_PIN_SLEEP("GPIO129_B4", in_wkup_pdis_en, "sdi2"), /* CMD */
+	DB8500_PIN_SLEEP("GPIO130_C8", in_wkup_pdis_en, "sdi2"), /* FBCLK */
+	DB8500_PIN_SLEEP("GPIO131_A12", in_wkup_pdis, "sdi2"), /* DAT0 */
+	DB8500_PIN_SLEEP("GPIO132_C10", in_wkup_pdis, "sdi2"), /* DAT1 */
+	DB8500_PIN_SLEEP("GPIO133_B10", in_wkup_pdis, "sdi2"), /* DAT2 */
+	DB8500_PIN_SLEEP("GPIO134_B9", in_wkup_pdis, "sdi2"), /* DAT3 */
+	DB8500_PIN_SLEEP("GPIO135_A9", in_wkup_pdis, "sdi2"), /* DAT4 */
+	DB8500_PIN_SLEEP("GPIO136_C7", in_wkup_pdis, "sdi2"), /* DAT5 */
+	DB8500_PIN_SLEEP("GPIO137_A7", in_wkup_pdis, "sdi2"), /* DAT6 */
+	DB8500_PIN_SLEEP("GPIO138_C5", in_wkup_pdis, "sdi2"), /* DAT7 */
+
 	/* Mux in SDI4 (here called MC4) used for for PCB-mounted eMMC */
 	DB8500_MUX("mc4_a_1", "mc4", "sdi4"),
 	DB8500_PIN("GPIO197_AH24", in_pu, "sdi4"), /* DAT3 */
@@ -230,6 +295,19 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
 	DB8500_PIN("GPIO205_AG23", in_pu, "sdi4"), /* DAT6 */
 	DB8500_PIN("GPIO206_AG24", in_pu, "sdi4"), /* DAT5 */
 	DB8500_PIN("GPIO207_AJ23", in_pu, "sdi4"), /* DAT4 */
+	/*SDI4 sleep state */
+	DB8500_PIN_SLEEP("GPIO197_AH24", slpm_in_wkup_pdis, "sdi4"), /* DAT3 */
+	DB8500_PIN_SLEEP("GPIO198_AG25", slpm_in_wkup_pdis, "sdi4"), /* DAT2 */
+	DB8500_PIN_SLEEP("GPIO199_AH23", slpm_in_wkup_pdis, "sdi4"), /* DAT1 */
+	DB8500_PIN_SLEEP("GPIO200_AH26", slpm_in_wkup_pdis, "sdi4"), /* DAT0 */
+	DB8500_PIN_SLEEP("GPIO201_AF24", slpm_in_wkup_pdis, "sdi4"), /* CMD */
+	DB8500_PIN_SLEEP("GPIO202_AF25", slpm_in_wkup_pdis, "sdi4"), /* FBCLK */
+	DB8500_PIN_SLEEP("GPIO203_AE23", slpm_out_lo_wkup_pdis, "sdi4"), /* CLK */
+	DB8500_PIN_SLEEP("GPIO204_AF23", slpm_in_wkup_pdis, "sdi4"), /* DAT7 */
+	DB8500_PIN_SLEEP("GPIO205_AG23", slpm_in_wkup_pdis, "sdi4"), /* DAT6 */
+	DB8500_PIN_SLEEP("GPIO206_AG24", slpm_in_wkup_pdis, "sdi4"), /* DAT5 */
+	DB8500_PIN_SLEEP("GPIO207_AJ23", slpm_in_wkup_pdis, "sdi4"), /* DAT4 */
+
 	/* Mux in USB pins, drive STP high */
 	DB8500_MUX("usb_a_1", "usb", "musb-ux500.0"),
 	DB8500_PIN("GPIO257_AE29", out_hi, "musb-ux500.0"), /* STP */
@@ -239,10 +317,232 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
 	DB8500_PIN("GPIO218_AH11", in_pd, "spi2"), /* RXD */
 	DB8500_PIN("GPIO215_AH13", out_lo, "spi2"), /* TXD */
 	DB8500_PIN("GPIO217_AH12", out_lo, "spi2"), /* CLK */
+	/* SPI2 idle state */
+	DB8500_PIN_SLEEP("GPIO218_AH11", slpm_in_wkup_pdis, "spi2"), /* RXD */
+	DB8500_PIN_SLEEP("GPIO215_AH13", slpm_out_lo_wkup_pdis, "spi2"), /* TXD */
+	DB8500_PIN_SLEEP("GPIO217_AH12", slpm_wkup_pdis, "spi2"), /* CLK */
 	/* SPI2 sleep state */
+	DB8500_PIN_SLEEP("GPIO216_AG12", slpm_in_wkup_pdis, "spi2"), /* FRM */
 	DB8500_PIN_SLEEP("GPIO218_AH11", slpm_in_wkup_pdis, "spi2"), /* RXD */
 	DB8500_PIN_SLEEP("GPIO215_AH13", slpm_out_lo_wkup_pdis, "spi2"), /* TXD */
 	DB8500_PIN_SLEEP("GPIO217_AH12", slpm_wkup_pdis, "spi2"), /* CLK */
+
+	/* ske default state */
+	DB8500_MUX("kp_a_2", "kp", "nmk-ske-keypad"),
+	DB8500_PIN("GPIO153_B17", in_pd, "nmk-ske-keypad"), /* I7 */
+	DB8500_PIN("GPIO154_C16", in_pd, "nmk-ske-keypad"), /* I6 */
+	DB8500_PIN("GPIO155_C19", in_pd, "nmk-ske-keypad"), /* I5 */
+	DB8500_PIN("GPIO156_C17", in_pd, "nmk-ske-keypad"), /* I4 */
+	DB8500_PIN("GPIO161_D21", in_pd, "nmk-ske-keypad"), /* I3 */
+	DB8500_PIN("GPIO162_D20", in_pd, "nmk-ske-keypad"), /* I2 */
+	DB8500_PIN("GPIO163_C20", in_pd, "nmk-ske-keypad"), /* I1 */
+	DB8500_PIN("GPIO164_B21", in_pd, "nmk-ske-keypad"), /* I0 */
+	DB8500_PIN("GPIO157_A18", out_lo, "nmk-ske-keypad"), /* O7 */
+	DB8500_PIN("GPIO158_C18", out_lo, "nmk-ske-keypad"), /* O6 */
+	DB8500_PIN("GPIO159_B19", out_lo, "nmk-ske-keypad"), /* O5 */
+	DB8500_PIN("GPIO160_B20", out_lo, "nmk-ske-keypad"), /* O4 */
+	DB8500_PIN("GPIO165_C21", out_lo, "nmk-ske-keypad"), /* O3 */
+	DB8500_PIN("GPIO166_A22", out_lo, "nmk-ske-keypad"), /* O2 */
+	DB8500_PIN("GPIO167_B24", out_lo, "nmk-ske-keypad"), /* O1 */
+	DB8500_PIN("GPIO168_C22", out_lo, "nmk-ske-keypad"), /* O0 */
+	/* ske sleep state */
+	DB8500_PIN_SLEEP("GPIO153_B17", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I7 */
+	DB8500_PIN_SLEEP("GPIO154_C16", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I6 */
+	DB8500_PIN_SLEEP("GPIO155_C19", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I5 */
+	DB8500_PIN_SLEEP("GPIO156_C17", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I4 */
+	DB8500_PIN_SLEEP("GPIO161_D21", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I3 */
+	DB8500_PIN_SLEEP("GPIO162_D20", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I2 */
+	DB8500_PIN_SLEEP("GPIO163_C20", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I1 */
+	DB8500_PIN_SLEEP("GPIO164_B21", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I0 */
+	DB8500_PIN_SLEEP("GPIO157_A18", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O7 */
+	DB8500_PIN_SLEEP("GPIO158_C18", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O6 */
+	DB8500_PIN_SLEEP("GPIO159_B19", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O5 */
+	DB8500_PIN_SLEEP("GPIO160_B20", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O4 */
+	DB8500_PIN_SLEEP("GPIO165_C21", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O3 */
+	DB8500_PIN_SLEEP("GPIO166_A22", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O2 */
+	DB8500_PIN_SLEEP("GPIO167_B24", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O1 */
+	DB8500_PIN_SLEEP("GPIO168_C22", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O0 */
+
+	/* STM APE pins states */
+	DB8500_MUX_STATE("stmape_c_1", "stmape",
+		"stm", "ape_mipi34"),
+	DB8500_PIN_STATE("GPIO70_G5", in_nopull,
+		"stm", "ape_mipi34"), /* clk */
+	DB8500_PIN_STATE("GPIO71_G4", in_nopull,
+		"stm", "ape_mipi34"), /* dat3 */
+	DB8500_PIN_STATE("GPIO72_H4", in_nopull,
+		"stm", "ape_mipi34"), /* dat2 */
+	DB8500_PIN_STATE("GPIO73_H3", in_nopull,
+		"stm", "ape_mipi34"), /* dat1 */
+	DB8500_PIN_STATE("GPIO74_J3", in_nopull,
+		"stm", "ape_mipi34"), /* dat0 */
+
+	DB8500_PIN_STATE("GPIO70_G5", slpm_out_lo_pdis,
+		"stm", "ape_mipi34_sleep"), /* clk */
+	DB8500_PIN_STATE("GPIO71_G4", slpm_out_lo_pdis,
+		"stm", "ape_mipi34_sleep"), /* dat3 */
+	DB8500_PIN_STATE("GPIO72_H4", slpm_out_lo_pdis,
+		"stm", "ape_mipi34_sleep"), /* dat2 */
+	DB8500_PIN_STATE("GPIO73_H3", slpm_out_lo_pdis,
+		"stm", "ape_mipi34_sleep"), /* dat1 */
+	DB8500_PIN_STATE("GPIO74_J3", slpm_out_lo_pdis,
+		"stm", "ape_mipi34_sleep"), /* dat0 */
+
+	DB8500_MUX_STATE("stmape_oc1_1", "stmape",
+		"stm", "ape_microsd"),
+	DB8500_PIN_STATE("GPIO23_AA4", in_nopull,
+		"stm", "ape_microsd"), /* clk */
+	DB8500_PIN_STATE("GPIO25_Y4", in_nopull,
+		"stm", "ape_microsd"), /* dat0 */
+	DB8500_PIN_STATE("GPIO26_Y2", in_nopull,
+		"stm", "ape_microsd"), /* dat1 */
+	DB8500_PIN_STATE("GPIO27_AA2", in_nopull,
+		"stm", "ape_microsd"), /* dat2 */
+	DB8500_PIN_STATE("GPIO28_AA1", in_nopull,
+		"stm", "ape_microsd"), /* dat3 */
+
+	DB8500_PIN_STATE("GPIO23_AA4", slpm_out_lo_wkup_pdis,
+		"stm", "ape_microsd_sleep"), /* clk */
+	DB8500_PIN_STATE("GPIO25_Y4", slpm_in_wkup_pdis,
+		"stm", "ape_microsd_sleep"), /* dat0 */
+	DB8500_PIN_STATE("GPIO26_Y2", slpm_in_wkup_pdis,
+		"stm", "ape_microsd_sleep"), /* dat1 */
+	DB8500_PIN_STATE("GPIO27_AA2", slpm_in_wkup_pdis,
+		"stm", "ape_microsd_sleep"), /* dat2 */
+	DB8500_PIN_STATE("GPIO28_AA1", slpm_in_wkup_pdis,
+		"stm", "ape_microsd_sleep"), /* dat3 */
+
+	/*  STM Modem pins states */
+	DB8500_MUX_STATE("stmmod_oc3_2", "stmmod",
+		"stm", "mod_mipi34"),
+	DB8500_MUX_STATE("uartmodrx_oc3_1", "uartmod",
+		"stm", "mod_mipi34"),
+	DB8500_MUX_STATE("uartmodtx_oc3_1", "uartmod",
+		"stm", "mod_mipi34"),
+	DB8500_PIN_STATE("GPIO70_G5", in_nopull,
+		"stm", "mod_mipi34"), /* clk */
+	DB8500_PIN_STATE("GPIO71_G4", in_nopull,
+		"stm", "mod_mipi34"), /* dat3 */
+	DB8500_PIN_STATE("GPIO72_H4", in_nopull,
+		"stm", "mod_mipi34"), /* dat2 */
+	DB8500_PIN_STATE("GPIO73_H3", in_nopull,
+		"stm", "mod_mipi34"), /* dat1 */
+	DB8500_PIN_STATE("GPIO74_J3", in_nopull,
+		"stm", "mod_mipi34"), /* dat0 */
+	DB8500_PIN_STATE("GPIO75_H2", in_pu,
+		"stm", "mod_mipi34"), /* uartmod rx */
+	DB8500_PIN_STATE("GPIO76_J2", out_lo,
+		"stm", "mod_mipi34"), /* uartmod tx */
+
+	DB8500_PIN_STATE("GPIO70_G5", slpm_out_lo_pdis,
+		"stm", "mod_mipi34_sleep"), /* clk */
+	DB8500_PIN_STATE("GPIO71_G4", slpm_out_lo_pdis,
+		"stm", "mod_mipi34_sleep"), /* dat3 */
+	DB8500_PIN_STATE("GPIO72_H4", slpm_out_lo_pdis,
+		"stm", "mod_mipi34_sleep"), /* dat2 */
+	DB8500_PIN_STATE("GPIO73_H3", slpm_out_lo_pdis,
+		"stm", "mod_mipi34_sleep"), /* dat1 */
+	DB8500_PIN_STATE("GPIO74_J3", slpm_out_lo_pdis,
+		"stm", "mod_mipi34_sleep"), /* dat0 */
+	DB8500_PIN_STATE("GPIO75_H2", slpm_in_wkup_pdis,
+		"stm", "mod_mipi34_sleep"), /* uartmod rx */
+	DB8500_PIN_STATE("GPIO76_J2", slpm_out_lo_wkup_pdis,
+		"stm", "mod_mipi34_sleep"), /* uartmod tx */
+
+	DB8500_MUX_STATE("stmmod_b_1", "stmmod",
+		"stm", "mod_microsd"),
+	DB8500_MUX_STATE("uartmodrx_oc3_1", "uartmod",
+		"stm", "mod_microsd"),
+	DB8500_MUX_STATE("uartmodtx_oc3_1", "uartmod",
+		"stm", "mod_microsd"),
+	DB8500_PIN_STATE("GPIO23_AA4", in_nopull,
+		"stm", "mod_microsd"), /* clk */
+	DB8500_PIN_STATE("GPIO25_Y4", in_nopull,
+		"stm", "mod_microsd"), /* dat0 */
+	DB8500_PIN_STATE("GPIO26_Y2", in_nopull,
+		"stm", "mod_microsd"), /* dat1 */
+	DB8500_PIN_STATE("GPIO27_AA2", in_nopull,
+		"stm", "mod_microsd"), /* dat2 */
+	DB8500_PIN_STATE("GPIO28_AA1", in_nopull,
+		"stm", "mod_microsd"), /* dat3 */
+	DB8500_PIN_STATE("GPIO75_H2", in_pu,
+		"stm", "mod_microsd"), /* uartmod rx */
+	DB8500_PIN_STATE("GPIO76_J2", out_lo,
+		"stm", "mod_microsd"), /* uartmod tx */
+
+	DB8500_PIN_STATE("GPIO23_AA4", slpm_out_lo_wkup_pdis,
+		"stm", "mod_microsd_sleep"), /* clk */
+	DB8500_PIN_STATE("GPIO25_Y4", slpm_in_wkup_pdis,
+		"stm", "mod_microsd_sleep"), /* dat0 */
+	DB8500_PIN_STATE("GPIO26_Y2", slpm_in_wkup_pdis,
+		"stm", "mod_microsd_sleep"), /* dat1 */
+	DB8500_PIN_STATE("GPIO27_AA2", slpm_in_wkup_pdis,
+		"stm", "mod_microsd_sleep"), /* dat2 */
+	DB8500_PIN_STATE("GPIO28_AA1", slpm_in_wkup_pdis,
+		"stm", "mod_microsd_sleep"), /* dat3 */
+	DB8500_PIN_STATE("GPIO75_H2", slpm_in_wkup_pdis,
+		"stm", "mod_microsd_sleep"), /* uartmod rx */
+	DB8500_PIN_STATE("GPIO76_J2", slpm_out_lo_wkup_pdis,
+		"stm", "mod_microsd_sleep"), /* uartmod tx */
+
+	/*  STM dual Modem/APE pins state */
+	DB8500_MUX_STATE("stmmod_oc3_2", "stmmod",
+		"stm", "mod_mipi34_ape_mipi60"),
+	DB8500_MUX_STATE("stmape_c_2", "stmape",
+		"stm", "mod_mipi34_ape_mipi60"),
+	DB8500_MUX_STATE("uartmodrx_oc3_1", "uartmod",
+		"stm", "mod_mipi34_ape_mipi60"),
+	DB8500_MUX_STATE("uartmodtx_oc3_1", "uartmod",
+		"stm", "mod_mipi34_ape_mipi60"),
+	DB8500_PIN_STATE("GPIO70_G5", in_nopull,
+		"stm", "mod_mipi34_ape_mipi60"), /* clk */
+	DB8500_PIN_STATE("GPIO71_G4", in_nopull,
+		"stm", "mod_mipi34_ape_mipi60"), /* dat3 */
+	DB8500_PIN_STATE("GPIO72_H4", in_nopull,
+		"stm", "mod_mipi34_ape_mipi60"), /* dat2 */
+	DB8500_PIN_STATE("GPIO73_H3", in_nopull,
+		"stm", "mod_mipi34_ape_mipi60"), /* dat1 */
+	DB8500_PIN_STATE("GPIO74_J3", in_nopull,
+		"stm", "mod_mipi34_ape_mipi60"), /* dat0 */
+	DB8500_PIN_STATE("GPIO75_H2", in_pu,
+		"stm", "mod_mipi34_ape_mipi60"), /* uartmod rx */
+	DB8500_PIN_STATE("GPIO76_J2", out_lo,
+		"stm", "mod_mipi34_ape_mipi60"), /* uartmod tx */
+	DB8500_PIN_STATE("GPIO155_C19", in_nopull,
+		"stm", "mod_mipi34_ape_mipi60"), /* clk */
+	DB8500_PIN_STATE("GPIO156_C17", in_nopull,
+		"stm", "mod_mipi34_ape_mipi60"), /* dat3 */
+	DB8500_PIN_STATE("GPIO157_A18", in_nopull,
+		"stm", "mod_mipi34_ape_mipi60"), /* dat2 */
+	DB8500_PIN_STATE("GPIO158_C18", in_nopull,
+		"stm", "mod_mipi34_ape_mipi60"), /* dat1 */
+	DB8500_PIN_STATE("GPIO159_B19", in_nopull,
+		"stm", "mod_mipi34_ape_mipi60"), /* dat0 */
+
+	DB8500_PIN_STATE("GPIO70_G5", slpm_out_lo_pdis,
+		"stm", "mod_mipi34_ape_mipi60_sleep"), /* clk */
+	DB8500_PIN_STATE("GPIO71_G4", slpm_out_lo_pdis,
+		"stm", "mod_mipi34_ape_mipi60_sleep"), /* dat3 */
+	DB8500_PIN_STATE("GPIO72_H4", slpm_out_lo_pdis,
+		"stm", "mod_mipi34_ape_mipi60_sleep"), /* dat2 */
+	DB8500_PIN_STATE("GPIO73_H3", slpm_out_lo_pdis,
+		"stm", "mod_mipi34_ape_mipi60_sleep"), /* dat1 */
+	DB8500_PIN_STATE("GPIO74_J3", slpm_out_lo_pdis,
+		"stm", "mod_mipi34_ape_mipi60_sleep"), /* dat0 */
+	DB8500_PIN_STATE("GPIO75_H2", slpm_in_wkup_pdis,
+		"stm", "mod_mipi34_ape_mipi60_sleep"), /* uartmod rx */
+	DB8500_PIN_STATE("GPIO76_J2", slpm_out_lo_wkup_pdis,
+		"stm", "mod_mipi34_ape_mipi60_sleep"), /* uartmod tx */
+	DB8500_PIN_STATE("GPIO155_C19", slpm_in_wkup_pdis,
+		"stm", "mod_mipi34_ape_mipi60_sleep"), /* clk */
+	DB8500_PIN_STATE("GPIO156_C17", slpm_in_wkup_pdis,
+		"stm", "mod_mipi34_ape_mipi60_sleep"), /* dat3 */
+	DB8500_PIN_STATE("GPIO157_A18", slpm_in_wkup_pdis,
+		"stm", "mod_mipi34_ape_mipi60_sleep"), /* dat2 */
+	DB8500_PIN_STATE("GPIO158_C18", slpm_in_wkup_pdis,
+		"stm", "mod_mipi34_ape_mipi60_sleep"), /* dat1 */
+	DB8500_PIN_STATE("GPIO159_B19", slpm_in_wkup_pdis,
+		"stm", "mod_mipi34_ape_mipi60_sleep"), /* dat0 */
 };
 
 /*
@@ -268,32 +568,48 @@ static struct pinctrl_map __initdata mop500_pinmap[] = {
 	DB8500_PIN_HOG("GPIO217_AH12", gpio_in_pu),
 	/* Mux in UART1 and set the pull-ups */
 	DB8500_MUX_HOG("u1rxtx_a_1", "u1"),
-	DB8500_MUX_HOG("u1ctsrts_a_1", "u1"),
 	DB8500_PIN_HOG("GPIO4_AH6", in_pu), /* RXD */
 	DB8500_PIN_HOG("GPIO5_AG6", out_hi), /* TXD */
-	DB8500_PIN_HOG("GPIO6_AF6", in_pu), /* CTS */
-	DB8500_PIN_HOG("GPIO7_AG5", out_hi), /* RTS */
 	/*
 	 * Runtime stuff: make it possible to mux in the SKE keypad
 	 * and bias the pins
 	 */
-	DB8500_MUX("kp_a_2", "kp", "ske"),
-	DB8500_PIN("GPIO153_B17", in_pd_slpm_in_pu, "ske"), /* I7 */
-	DB8500_PIN("GPIO154_C16", in_pd_slpm_in_pu, "ske"), /* I6 */
-	DB8500_PIN("GPIO155_C19", in_pd_slpm_in_pu, "ske"), /* I5 */
-	DB8500_PIN("GPIO156_C17", in_pd_slpm_in_pu, "ske"), /* I4 */
-	DB8500_PIN("GPIO161_D21", in_pd_slpm_in_pu, "ske"), /* I3 */
-	DB8500_PIN("GPIO162_D20", in_pd_slpm_in_pu, "ske"), /* I2 */
-	DB8500_PIN("GPIO163_C20", in_pd_slpm_in_pu, "ske"), /* I1 */
-	DB8500_PIN("GPIO164_B21", in_pd_slpm_in_pu, "ske"), /* I0 */
-	DB8500_PIN("GPIO157_A18", in_pu_slpm_out_lo, "ske"), /* O7 */
-	DB8500_PIN("GPIO158_C18", in_pu_slpm_out_lo, "ske"), /* O6 */
-	DB8500_PIN("GPIO159_B19", in_pu_slpm_out_lo, "ske"), /* O5 */
-	DB8500_PIN("GPIO160_B20", in_pu_slpm_out_lo, "ske"), /* O4 */
-	DB8500_PIN("GPIO165_C21", in_pu_slpm_out_lo, "ske"), /* O3 */
-	DB8500_PIN("GPIO166_A22", in_pu_slpm_out_lo, "ske"), /* O2 */
-	DB8500_PIN("GPIO167_B24", in_pu_slpm_out_lo, "ske"), /* O1 */
-	DB8500_PIN("GPIO168_C22", in_pu_slpm_out_lo, "ske"), /* O0 */
+	/* ske default state */
+	DB8500_MUX("kp_a_2", "kp", "nmk-ske-keypad"),
+	DB8500_PIN("GPIO153_B17", in_pu, "nmk-ske-keypad"), /* I7 */
+	DB8500_PIN("GPIO154_C16", in_pu, "nmk-ske-keypad"), /* I6 */
+	DB8500_PIN("GPIO155_C19", in_pu, "nmk-ske-keypad"), /* I5 */
+	DB8500_PIN("GPIO156_C17", in_pu, "nmk-ske-keypad"), /* I4 */
+	DB8500_PIN("GPIO161_D21", in_pu, "nmk-ske-keypad"), /* I3 */
+	DB8500_PIN("GPIO162_D20", in_pu, "nmk-ske-keypad"), /* I2 */
+	DB8500_PIN("GPIO163_C20", in_pu, "nmk-ske-keypad"), /* I1 */
+	DB8500_PIN("GPIO164_B21", in_pu, "nmk-ske-keypad"), /* I0 */
+	DB8500_PIN("GPIO157_A18", out_lo, "nmk-ske-keypad"), /* O7 */
+	DB8500_PIN("GPIO158_C18", out_lo, "nmk-ske-keypad"), /* O6 */
+	DB8500_PIN("GPIO159_B19", out_lo, "nmk-ske-keypad"), /* O5 */
+	DB8500_PIN("GPIO160_B20", out_lo, "nmk-ske-keypad"), /* O4 */
+	DB8500_PIN("GPIO165_C21", out_lo, "nmk-ske-keypad"), /* O3 */
+	DB8500_PIN("GPIO166_A22", out_lo, "nmk-ske-keypad"), /* O2 */
+	DB8500_PIN("GPIO167_B24", out_lo, "nmk-ske-keypad"), /* O1 */
+	DB8500_PIN("GPIO168_C22", out_lo, "nmk-ske-keypad"), /* O0 */
+	/* ske sleep state */
+	DB8500_PIN_SLEEP("GPIO153_B17", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I7 */
+	DB8500_PIN_SLEEP("GPIO154_C16", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I6 */
+	DB8500_PIN_SLEEP("GPIO155_C19", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I5 */
+	DB8500_PIN_SLEEP("GPIO156_C17", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I4 */
+	DB8500_PIN_SLEEP("GPIO161_D21", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I3 */
+	DB8500_PIN_SLEEP("GPIO162_D20", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I2 */
+	DB8500_PIN_SLEEP("GPIO163_C20", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I1 */
+	DB8500_PIN_SLEEP("GPIO164_B21", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I0 */
+	DB8500_PIN_SLEEP("GPIO157_A18", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O7 */
+	DB8500_PIN_SLEEP("GPIO158_C18", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O6 */
+	DB8500_PIN_SLEEP("GPIO159_B19", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O5 */
+	DB8500_PIN_SLEEP("GPIO160_B20", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O4 */
+	DB8500_PIN_SLEEP("GPIO165_C21", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O3 */
+	DB8500_PIN_SLEEP("GPIO166_A22", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O2 */
+	DB8500_PIN_SLEEP("GPIO167_B24", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O1 */
+	DB8500_PIN_SLEEP("GPIO168_C22", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O0 */
+
 	/* Mux in and drive the SDI0 DAT31DIR line high at runtime */
 	DB8500_MUX("mc0dat31dir_a_1", "mc0", "sdi0"),
 	DB8500_PIN("GPIO21_AB3", out_hi, "sdi0"),
@@ -396,28 +712,6 @@ static struct pinctrl_map __initdata hrefv60_pinmap[] = {
 	DB8500_PIN("GPIO217_AH12", gpio_in_pu_slpm_gpio_nopull, "gpio-keys.0"),
 	DB8500_PIN("GPIO145_C13", gpio_in_pd_slpm_gpio_nopull, "gpio-keys.0"),
 	DB8500_PIN("GPIO139_C9", gpio_in_pu_slpm_gpio_nopull, "gpio-keys.0"),
-	/*
-	 * Make it possible to mux in the SKE keypad and bias the pins
-	 * FIXME: what's the point with this on HREFv60? KP/SKE is already
-	 * muxed in at another place! Enabling this will bork.
-	 */
-	DB8500_MUX("kp_a_2", "kp", "ske"),
-	DB8500_PIN("GPIO153_B17", in_pd_slpm_in_pu, "ske"), /* I7 */
-	DB8500_PIN("GPIO154_C16", in_pd_slpm_in_pu, "ske"), /* I6 */
-	DB8500_PIN("GPIO155_C19", in_pd_slpm_in_pu, "ske"), /* I5 */
-	DB8500_PIN("GPIO156_C17", in_pd_slpm_in_pu, "ske"), /* I4 */
-	DB8500_PIN("GPIO161_D21", in_pd_slpm_in_pu, "ske"), /* I3 */
-	DB8500_PIN("GPIO162_D20", in_pd_slpm_in_pu, "ske"), /* I2 */
-	DB8500_PIN("GPIO163_C20", in_pd_slpm_in_pu, "ske"), /* I1 */
-	DB8500_PIN("GPIO164_B21", in_pd_slpm_in_pu, "ske"), /* I0 */
-	DB8500_PIN("GPIO157_A18", in_pu_slpm_out_lo, "ske"), /* O7 */
-	DB8500_PIN("GPIO158_C18", in_pu_slpm_out_lo, "ske"), /* O6 */
-	DB8500_PIN("GPIO159_B19", in_pu_slpm_out_lo, "ske"), /* O5 */
-	DB8500_PIN("GPIO160_B20", in_pu_slpm_out_lo, "ske"), /* O4 */
-	DB8500_PIN("GPIO165_C21", in_pu_slpm_out_lo, "ske"), /* O3 */
-	DB8500_PIN("GPIO166_A22", in_pu_slpm_out_lo, "ske"), /* O2 */
-	DB8500_PIN("GPIO167_B24", in_pu_slpm_out_lo, "ske"), /* O1 */
-	DB8500_PIN("GPIO168_C22", in_pu_slpm_out_lo, "ske"), /* O0 */
 };
 
 static struct pinctrl_map __initdata u9500_pinmap[] = {
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
index 9c8e4a9..051b62c 100644
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -11,9 +11,9 @@
 #include <linux/amba/mmci.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
+#include <linux/platform_data/dma-ste-dma40.h>
 
 #include <asm/mach-types.h>
-#include <plat/ste_dma40.h>
 #include <mach/devices.h>
 #include <mach/hardware.h>
 
diff --git a/arch/arm/mach-ux500/board-mop500-stuib.c b/arch/arm/mach-ux500/board-mop500-stuib.c
index 8c97977..7e1f294 100644
--- a/arch/arm/mach-ux500/board-mop500-stuib.c
+++ b/arch/arm/mach-ux500/board-mop500-stuib.c
@@ -77,9 +77,6 @@ static struct i2c_board_info __initdata mop500_i2c0_devices_stuib[] = {
  * BU21013 ROHM touchscreen interface on the STUIBs
  */
 
-/* tracks number of bu21013 devices being enabled */
-static int bu21013_devices;
-
 #define TOUCH_GPIO_PIN  84
 
 #define TOUCH_XMAX	384
@@ -88,85 +85,8 @@ static int bu21013_devices;
 #define PRCMU_CLOCK_OCR		0x1CC
 #define TSC_EXT_CLOCK_9_6MHZ	0x840000
 
-/**
- * bu21013_gpio_board_init : configures the touch panel.
- * @reset_pin: reset pin number
- * This function can be used to configures
- * the voltage and reset the touch panel controller.
- */
-static int bu21013_gpio_board_init(int reset_pin)
-{
-	int retval = 0;
-
-	bu21013_devices++;
-	if (bu21013_devices == 1) {
-		retval = gpio_request(reset_pin, "touchp_reset");
-		if (retval) {
-			printk(KERN_ERR "Unable to request gpio reset_pin");
-			return retval;
-		}
-		retval = gpio_direction_output(reset_pin, 1);
-		if (retval < 0) {
-			printk(KERN_ERR "%s: gpio direction failed\n",
-					__func__);
-			return retval;
-		}
-	}
-
-	return retval;
-}
-
-/**
- * bu21013_gpio_board_exit : deconfigures the touch panel controller
- * @reset_pin: reset pin number
- * This function can be used to deconfigures the chip selection
- * for touch panel controller.
- */
-static int bu21013_gpio_board_exit(int reset_pin)
-{
-	int retval = 0;
-
-	if (bu21013_devices == 1) {
-		retval = gpio_direction_output(reset_pin, 0);
-		if (retval < 0) {
-			printk(KERN_ERR "%s: gpio direction failed\n",
-					__func__);
-			return retval;
-		}
-		gpio_set_value(reset_pin, 0);
-	}
-	bu21013_devices--;
-
-	return retval;
-}
-
-/**
- * bu21013_read_pin_val : get the interrupt pin value
- * This function can be used to get the interrupt pin value for touch panel
- * controller.
- */
-static int bu21013_read_pin_val(void)
-{
-	return gpio_get_value(TOUCH_GPIO_PIN);
-}
-
 static struct bu21013_platform_device tsc_plat_device = {
-	.cs_en = bu21013_gpio_board_init,
-	.cs_dis = bu21013_gpio_board_exit,
-	.irq_read_val = bu21013_read_pin_val,
-	.irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN),
-	.touch_x_max = TOUCH_XMAX,
-	.touch_y_max = TOUCH_YMAX,
-	.ext_clk = false,
-	.x_flip = false,
-	.y_flip = true,
-};
-
-static struct bu21013_platform_device tsc_plat2_device = {
-	.cs_en = bu21013_gpio_board_init,
-	.cs_dis = bu21013_gpio_board_exit,
-	.irq_read_val = bu21013_read_pin_val,
-	.irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN),
+	.touch_pin = TOUCH_GPIO_PIN,
 	.touch_x_max = TOUCH_XMAX,
 	.touch_y_max = TOUCH_YMAX,
 	.ext_clk = false,
@@ -181,21 +101,16 @@ static struct i2c_board_info __initdata u8500_i2c3_devices_stuib[] = {
 	},
 	{
 		I2C_BOARD_INFO("bu21013_tp", 0x5D),
-		.platform_data = &tsc_plat2_device,
+		.platform_data = &tsc_plat_device,
 	},
-
 };
 
 void __init mop500_stuib_init(void)
 {
-	if (machine_is_hrefv60()) {
+	if (machine_is_hrefv60())
 		tsc_plat_device.cs_pin = HREFV60_TOUCH_RST_GPIO;
-		tsc_plat2_device.cs_pin = HREFV60_TOUCH_RST_GPIO;
-	} else {
+	else
 		tsc_plat_device.cs_pin = GPIO_BU21013_CS;
-		tsc_plat2_device.cs_pin = GPIO_BU21013_CS;
-
-	}
 
 	mop500_uib_i2c_add(0, mop500_i2c0_devices_stuib,
 			ARRAY_SIZE(mop500_i2c0_devices_stuib));
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 416d436..d453522 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -1,6 +1,5 @@
-
 /*
- * Copyright (C) 2008-2009 ST-Ericsson
+ * Copyright (C) 2008-2012 ST-Ericsson
  *
  * Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
  *
@@ -16,6 +15,7 @@
 #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>
@@ -33,18 +33,15 @@
 #include <linux/smsc911x.h>
 #include <linux/gpio_keys.h>
 #include <linux/delay.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
 #include <linux/leds.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
+#include <linux/platform_data/dma-ste-dma40.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
 
-#include <plat/ste_dma40.h>
-#include <plat/gpio-nomadik.h>
-
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
@@ -229,6 +226,67 @@ static struct ab8500_platform_data ab8500_platdata = {
 };
 
 /*
+ * Thermal Sensor
+ */
+
+static struct resource db8500_thsens_resources[] = {
+	{
+		.name = "IRQ_HOTMON_LOW",
+		.start  = IRQ_PRCMU_HOTMON_LOW,
+		.end    = IRQ_PRCMU_HOTMON_LOW,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name = "IRQ_HOTMON_HIGH",
+		.start  = IRQ_PRCMU_HOTMON_HIGH,
+		.end    = IRQ_PRCMU_HOTMON_HIGH,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct db8500_thsens_platform_data db8500_thsens_data = {
+	.trip_points[0] = {
+		.temp = 70000,
+		.type = THERMAL_TRIP_ACTIVE,
+		.cdev_name = {
+			[0] = "thermal-cpufreq-0",
+		},
+	},
+	.trip_points[1] = {
+		.temp = 75000,
+		.type = THERMAL_TRIP_ACTIVE,
+		.cdev_name = {
+			[0] = "thermal-cpufreq-0",
+		},
+	},
+	.trip_points[2] = {
+		.temp = 80000,
+		.type = THERMAL_TRIP_ACTIVE,
+		.cdev_name = {
+			[0] = "thermal-cpufreq-0",
+		},
+	},
+	.trip_points[3] = {
+		.temp = 85000,
+		.type = THERMAL_TRIP_CRITICAL,
+	},
+	.num_trips = 4,
+};
+
+static struct platform_device u8500_thsens_device = {
+	.name           = "db8500-thermal",
+	.resource       = db8500_thsens_resources,
+	.num_resources  = ARRAY_SIZE(db8500_thsens_resources),
+	.dev	= {
+		.platform_data	= &db8500_thsens_data,
+	},
+};
+
+static struct platform_device u8500_cpufreq_cooling_device = {
+	.name           = "db8500-cpufreq-cooling",
+};
+
+/*
  * TPS61052
  */
 
@@ -464,7 +522,7 @@ static struct stedma40_chan_cfg ssp0_dma_cfg_tx = {
 };
 #endif
 
-static struct pl022_ssp_controller ssp0_plat = {
+struct pl022_ssp_controller ssp0_plat = {
 	.bus_id = 0,
 #ifdef CONFIG_STE_DMA40
 	.enable_dma = 1,
@@ -541,7 +599,7 @@ static struct stedma40_chan_cfg uart2_dma_cfg_tx = {
 };
 #endif
 
-static struct amba_pl011_data uart0_plat = {
+struct amba_pl011_data uart0_plat = {
 #ifdef CONFIG_STE_DMA40
 	.dma_filter = stedma40_filter,
 	.dma_rx_param = &uart0_dma_cfg_rx,
@@ -549,7 +607,7 @@ static struct amba_pl011_data uart0_plat = {
 #endif
 };
 
-static struct amba_pl011_data uart1_plat = {
+struct amba_pl011_data uart1_plat = {
 #ifdef CONFIG_STE_DMA40
 	.dma_filter = stedma40_filter,
 	.dma_rx_param = &uart1_dma_cfg_rx,
@@ -557,7 +615,7 @@ static struct amba_pl011_data uart1_plat = {
 #endif
 };
 
-static struct amba_pl011_data uart2_plat = {
+struct amba_pl011_data uart2_plat = {
 #ifdef CONFIG_STE_DMA40
 	.dma_filter = stedma40_filter,
 	.dma_rx_param = &uart2_dma_cfg_rx,
@@ -583,6 +641,8 @@ static struct platform_device *snowball_platform_devs[] __initdata = {
 	&snowball_key_dev,
 	&snowball_sbnet_dev,
 	&snowball_gpio_en_3v3_regulator_dev,
+	&u8500_thsens_device,
+	&u8500_cpufreq_cooling_device,
 };
 
 static void __init mop500_init_machine(void)
@@ -618,8 +678,6 @@ static void __init mop500_init_machine(void)
 
 	/* This board has full regulator constraints */
 	regulator_has_full_constraints();
-
-	mop500_uib_init();
 }
 
 static void __init snowball_init_machine(void)
@@ -684,8 +742,6 @@ static void __init hrefv60_init_machine(void)
 
 	/* This board has full regulator constraints */
 	regulator_has_full_constraints();
-
-	mop500_uib_init();
 }
 
 MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
@@ -701,155 +757,35 @@ MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
 	.init_late	= ux500_init_late,
 MACHINE_END
 
-MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
+MACHINE_START(U8520, "ST-Ericsson U8520 Platform HREFP520")
 	.atag_offset	= 0x100,
-	.smp		= smp_ops(ux500_smp_ops),
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
 	.timer		= &ux500_timer,
 	.handle_irq	= gic_handle_irq,
-	.init_machine	= hrefv60_init_machine,
+	.init_machine	= mop500_init_machine,
 	.init_late	= ux500_init_late,
 MACHINE_END
 
-MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
+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,
-	/* we re-use nomadik timer here */
 	.timer		= &ux500_timer,
 	.handle_irq	= gic_handle_irq,
-	.init_machine	= snowball_init_machine,
+	.init_machine	= hrefv60_init_machine,
 	.init_late	= ux500_init_late,
 MACHINE_END
 
-#ifdef CONFIG_MACH_UX500_DT
-
-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 and call-back bindings. */
-	OF_DEV_AUXDATA("arm,pl011", 0x80120000, "uart0", &uart0_plat),
-	OF_DEV_AUXDATA("arm,pl011", 0x80121000, "uart1", &uart1_plat),
-	OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", &uart2_plat),
-	/* Requires DMA bindings. */
-	OF_DEV_AUXDATA("arm,pl022", 0x80002000, "ssp0",  &ssp0_plat),
-	OF_DEV_AUXDATA("arm,pl18x", 0x80126000, "sdi0",  &mop500_sdi0_data),
-	OF_DEV_AUXDATA("arm,pl18x", 0x80118000, "sdi1",  &mop500_sdi1_data),
-	OF_DEV_AUXDATA("arm,pl18x", 0x80005000, "sdi2",  &mop500_sdi2_data),
-	OF_DEV_AUXDATA("arm,pl18x", 0x80114000, "sdi4",  &mop500_sdi4_data),
-	/* 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),
-	/* Requires device name bindings. */
-	OF_DEV_AUXDATA("stericsson,nmk_pinctrl", 0, "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),
-	{},
-};
-
-static const struct of_device_id u8500_local_bus_nodes[] = {
-	/* only create devices below soc node */
-	{ .compatible = "stericsson,db8500", },
-	{ .compatible = "stericsson,db8500-prcmu", },
-	{ .compatible = "simple-bus"},
-	{ },
-};
-
-static void __init u8500_init_machine(void)
-{
-	struct device *parent = NULL;
-	int i2c0_devs;
-	int i;
-
-	/* Pinmaps must be in place before devices register */
-	if (of_machine_is_compatible("st-ericsson,mop500"))
-		mop500_pinmaps_init();
-	else if (of_machine_is_compatible("calaosystems,snowball-a9500"))
-		snowball_pinmaps_init();
-	else if (of_machine_is_compatible("st-ericsson,hrefv60+"))
-		hrefv60_pinmaps_init();
-
-	parent = u8500_of_init_devices();
-
-	for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
-		mop500_platform_devs[i]->dev.parent = parent;
-
-	/* automatically probe child nodes of db8500 device */
-	of_platform_populate(NULL, u8500_local_bus_nodes, u8500_auxdata_lookup, parent);
-
-	if (of_machine_is_compatible("st-ericsson,mop500")) {
-		mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
-
-		platform_add_devices(mop500_platform_devs,
-				ARRAY_SIZE(mop500_platform_devs));
-
-		mop500_sdi_init(parent);
-		mop500_audio_init(parent);
-		i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
-		i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
-		i2c_register_board_info(2, mop500_i2c2_devices,
-					ARRAY_SIZE(mop500_i2c2_devices));
-
-		mop500_uib_init();
-
-	} else if (of_machine_is_compatible("calaosystems,snowball-a9500")) {
-		mop500_of_audio_init(parent);
-	} else if (of_machine_is_compatible("st-ericsson,hrefv60+")) {
-		/*
-		 * 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;
-		platform_add_devices(mop500_platform_devs,
-				ARRAY_SIZE(mop500_platform_devs));
-
-		mop500_uib_init();
-	}
-
-	/* This board has full regulator constraints */
-	regulator_has_full_constraints();
-}
-
-static const char * u8500_dt_board_compat[] = {
-	"calaosystems,snowball-a9500",
-	"st-ericsson,hrefv60+",
-	"st-ericsson,u8500",
-	"st-ericsson,mop500",
-	NULL,
-};
-
-
-DT_MACHINE_START(U8500_DT, "ST-Ericsson U8500 platform (Device Tree Support)")
+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 */
 	.timer		= &ux500_timer,
 	.handle_irq	= gic_handle_irq,
-	.init_machine	= u8500_init_machine,
-	.init_late	= ux500_init_late,
-	.dt_compat      = u8500_dt_board_compat,
+	.init_machine	= snowball_init_machine,
+	.init_late	= NULL,
 MACHINE_END
-#endif
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index aca39a6..eaa605f 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -89,6 +89,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 void mop500_sdi_init(struct device *parent);
 extern void snowball_sdi_init(struct device *parent);
@@ -100,14 +104,8 @@ 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);
-/* Due for removal once the MSP driver has been fully DT:ed. */
-void mop500_of_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);
-
-/* TODO: Once all pieces are DT:ed, remove completely. */
-struct device * __init u8500_of_init_devices(void);
-
 #endif
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index bcdfe6b..0bad82a 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -17,18 +17,28 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/mfd/abx500/ab8500.h>
+#include <linux/platform_data/usb-musb-ux500.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
+#include <linux/random.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/regulator/machine.h>
 
 #include <asm/pmu.h>
 #include <asm/mach/map.h>
-#include <plat/gpio-nomadik.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware/gic.h>
+
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
-#include <linux/platform_data/usb-musb-ux500.h>
 #include <mach/db8500-regs.h>
+#include <mach/irqs.h>
 
 #include "devices-db8500.h"
 #include "ste-dma40-db8500.h"
+#include "board-mop500.h"
 
 /* minimum static i/o mapping required to boot U8500 platforms */
 static struct map_desc u8500_uart_io_desc[] __initdata = {
@@ -158,7 +168,7 @@ static void __init db8500_add_gpios(struct device *parent)
 
 	dbx500_add_gpios(parent, ARRAY_AND_SIZE(db8500_gpio_base),
 			 IRQ_DB8500_GPIO0, &pdata);
-	dbx500_add_pinctrl(parent, "pinctrl-db8500");
+	dbx500_add_pinctrl(parent, "pinctrl-db8500", U8500_PRCMU_BASE);
 }
 
 static int usb_db8500_rx_dma_cfg[] = {
@@ -187,6 +197,8 @@ static const char *db8500_read_soc_id(void)
 {
 	void __iomem *uid = __io_address(U8500_BB_UID_BASE);
 
+	/* Throw these device-specific numbers into the entropy pool */
+	add_device_randomness(uid, 0x14);
 	return kasprintf(GFP_KERNEL, "%08x%08x%08x%08x%08x",
 			 readl((u32 *)uid+1),
 			 readl((u32 *)uid+1), readl((u32 *)uid+2),
@@ -214,9 +226,6 @@ struct device * __init u8500_init_devices(struct ab8500_platform_data *ab8500)
 	db8500_add_gpios(parent);
 	db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
 
-	platform_device_register_data(parent,
-		"cpufreq-u8500", -1, NULL, 0);
-
 	for (i = 0; i < ARRAY_SIZE(platform_devs); i++)
 		platform_devs[i]->dev.parent = parent;
 
@@ -227,18 +236,15 @@ struct device * __init u8500_init_devices(struct ab8500_platform_data *ab8500)
 	return parent;
 }
 
+#ifdef CONFIG_MACH_UX500_DT
+
 /* TODO: Once all pieces are DT:ed, remove completely. */
-struct device * __init u8500_of_init_devices(void)
+static struct device * __init u8500_of_init_devices(void)
 {
-	struct device *parent;
-
-	parent = db8500_soc_device_init();
+	struct device *parent = db8500_soc_device_init();
 
 	db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
 
-	platform_device_register_data(parent,
-		"cpufreq-u8500", -1, NULL, 0);
-
 	u8500_dma40_device.dev.parent = parent;
 
 	/*
@@ -251,3 +257,95 @@ struct device * __init u8500_of_init_devices(void)
 
 	return parent;
 }
+
+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", &uart0_plat),
+	OF_DEV_AUXDATA("arm,pl011", 0x80121000, "uart1", &uart1_plat),
+	OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", &uart2_plat),
+	OF_DEV_AUXDATA("arm,pl022", 0x80002000, "ssp0",  &ssp0_plat),
+	OF_DEV_AUXDATA("arm,pl18x", 0x80126000, "sdi0",  &mop500_sdi0_data),
+	OF_DEV_AUXDATA("arm,pl18x", 0x80118000, "sdi1",  &mop500_sdi1_data),
+	OF_DEV_AUXDATA("arm,pl18x", 0x80005000, "sdi2",  &mop500_sdi2_data),
+	OF_DEV_AUXDATA("arm,pl18x", 0x80114000, "sdi4",  &mop500_sdi4_data),
+	/* 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),
+	/* Requires device name bindings. */
+	OF_DEV_AUXDATA("stericsson,nmk_pinctrl", 0, "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),
+	{},
+};
+
+static const struct of_device_id u8500_local_bus_nodes[] = {
+	/* only create devices below soc node */
+	{ .compatible = "stericsson,db8500", },
+	{ .compatible = "stericsson,db8500-prcmu", },
+	{ .compatible = "simple-bus"},
+	{ },
+};
+
+static void __init u8500_init_machine(void)
+{
+	struct device *parent = NULL;
+
+	/* Pinmaps must be in place before devices register */
+	if (of_machine_is_compatible("st-ericsson,mop500"))
+		mop500_pinmaps_init();
+	else if (of_machine_is_compatible("calaosystems,snowball-a9500"))
+		snowball_pinmaps_init();
+	else if (of_machine_is_compatible("st-ericsson,hrefv60+"))
+		hrefv60_pinmaps_init();
+	else if (of_machine_is_compatible("st-ericsson,ccu9540")) {}
+		/* TODO: Add pinmaps for ccu9540 board. */
+
+	/* TODO: Export SoC, USB, cpu-freq and DMA40 */
+	parent = u8500_of_init_devices();
+
+	/* automatically probe child nodes of db8500 device */
+	of_platform_populate(NULL, u8500_local_bus_nodes, u8500_auxdata_lookup, parent);
+}
+
+static const char * stericsson_dt_platform_compat[] = {
+	"st-ericsson,u8500",
+	"st-ericsson,u8540",
+	"st-ericsson,u9500",
+	"st-ericsson,u9540",
+	NULL,
+};
+
+DT_MACHINE_START(U8500_DT, "ST-Ericsson Ux5x0 platform (Device Tree Support)")
+	.smp            = smp_ops(ux500_smp_ops),
+	.map_io		= u8500_map_io,
+	.init_irq	= ux500_init_irq,
+	/* we re-use nomadik timer here */
+	.timer		= &ux500_timer,
+	.handle_irq	= gic_handle_irq,
+	.init_machine	= u8500_init_machine,
+	.init_late	= NULL,
+	.dt_compat      = stericsson_dt_platform_compat,
+MACHINE_END
+
+#endif
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index 1f3fbc2..721e7b4 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -26,6 +26,8 @@
 #include <mach/setup.h>
 #include <mach/devices.h>
 
+#include "board-mop500.h"
+
 void __iomem *_PRCMU_BASE;
 
 /*
@@ -82,6 +84,7 @@ void __init ux500_init_irq(void)
 
 void __init ux500_init_late(void)
 {
+	mop500_uib_init();
 }
 
 static const char * __init ux500_get_machine(void)
diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c
index dfdd4a5..16b5f71 100644
--- a/arch/arm/mach-ux500/devices-common.c
+++ b/arch/arm/mach-ux500/devices-common.c
@@ -11,10 +11,10 @@
 #include <linux/irq.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
-
-#include <plat/gpio-nomadik.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 
 #include "devices-common.h"
 
diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h
index 7fbf0ba..96fa4ac 100644
--- a/arch/arm/mach-ux500/devices-common.h
+++ b/arch/arm/mach-ux500/devices-common.h
@@ -129,12 +129,18 @@ 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)
+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);
diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c
index 91754a8..318d490 100644
--- a/arch/arm/mach-ux500/devices-db8500.c
+++ b/arch/arm/mach-ux500/devices-db8500.c
@@ -12,11 +12,11 @@
 #include <linux/gpio.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl022.h>
-
-#include <plat/ste_dma40.h>
+#include <linux/platform_data/dma-ste-dma40.h>
 
 #include <mach/hardware.h>
 #include <mach/setup.h>
+#include <mach/irqs.h>
 
 #include "ste-dma40-db8500.h"
 
diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h
index 3c8010f..4b24c99 100644
--- a/arch/arm/mach-ux500/devices-db8500.h
+++ b/arch/arm/mach-ux500/devices-db8500.h
@@ -8,6 +8,7 @@
 #ifndef __DEVICES_DB8500_H
 #define __DEVICES_DB8500_H
 
+#include <mach/irqs.h>
 #include "devices-common.h"
 
 struct ske_keypad_platform_data;
diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h
index e892854..fc77b42 100644
--- a/arch/arm/mach-ux500/include/mach/irqs.h
+++ b/arch/arm/mach-ux500/include/mach/irqs.h
@@ -46,6 +46,6 @@
 #include <mach/irqs-board-mop500.h>
 #endif
 
-#define NR_IRQS			IRQ_BOARD_END
+#define UX500_NR_IRQS		IRQ_BOARD_END
 
 #endif /* ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-ux500/include/mach/msp.h b/arch/arm/mach-ux500/include/mach/msp.h
index 3cc7142..9991aea 100644
--- a/arch/arm/mach-ux500/include/mach/msp.h
+++ b/arch/arm/mach-ux500/include/mach/msp.h
@@ -8,7 +8,7 @@
 #ifndef __MSP_H
 #define __MSP_H
 
-#include <plat/ste_dma40.h>
+#include <linux/platform_data/dma-ste-dma40.h>
 
 enum msp_i2s_id {
 	MSP_I2S_0 = 0,
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c
index 6f39731..875309a 100644
--- a/arch/arm/mach-ux500/timer.c
+++ b/arch/arm/mach-ux500/timer.c
@@ -9,11 +9,10 @@
 #include <linux/clksrc-dbx500-prcmu.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/platform_data/clocksource-nomadik-mtu.h>
 
 #include <asm/smp_twd.h>
 
-#include <plat/mtu.h>
-
 #include <mach/setup.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
@@ -96,7 +95,7 @@ dt_fail:
 	 *
 	 */
 
-	nmdk_timer_init(mtu_timer_base);
+	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
index 145482e..78ac65f 100644
--- a/arch/arm/mach-ux500/usb.c
+++ b/arch/arm/mach-ux500/usb.c
@@ -7,10 +7,10 @@
 #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 <plat/ste_dma40.h>
 #include <mach/hardware.h>
-#include <linux/platform_data/usb-musb-ux500.h>
 
 #define MUSB_DMA40_RX_CH { \
 		.mode = STEDMA40_MODE_LOGICAL, \
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 5b5c1ee..5d59294 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -32,6 +32,7 @@
 #include <linux/amba/mmci.h>
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
+#include <linux/irqchip/versatile-fpga.h>
 #include <linux/gfp.h>
 #include <linux/clkdev.h>
 #include <linux/mtd/physmap.h>
@@ -51,7 +52,6 @@
 #include <asm/hardware/timer-sp.h>
 
 #include <plat/clcd.h>
-#include <plat/fpga-irq.h>
 #include <plat/sched_clock.h>
 
 #include "core.h"
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index c952960..99e63f5 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -1,11 +1,12 @@
 config ARCH_VEXPRESS
 	bool "ARM Ltd. Versatile Express family" if ARCH_MULTI_V7
-	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select ARCH_REQUIRE_GPIOLIB
 	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_CLK
@@ -17,6 +18,7 @@ config ARCH_VEXPRESS
 	select PLAT_VERSATILE
 	select PLAT_VERSATILE_CLCD
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
+	select VEXPRESS_CONFIG
 	help
 	  This option enables support for systems using Cortex processor based
 	  ARM core and logic (FPGA) tiles on the Versatile Express motherboard,
diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile
index 42703e8..80b6497 100644
--- a/arch/arm/mach-vexpress/Makefile
+++ b/arch/arm/mach-vexpress/Makefile
@@ -4,7 +4,7 @@
 ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
 	-I$(srctree)/arch/arm/plat-versatile/include
 
-obj-y					:= v2m.o
+obj-y					:= v2m.o reset.o
 obj-$(CONFIG_ARCH_VEXPRESS_CA9X4)	+= ct-ca9x4.o
 obj-$(CONFIG_SMP)			+= platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index 4f471fa..60838dd 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -9,6 +9,7 @@
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
 #include <linux/clkdev.h>
+#include <linux/vexpress.h>
 
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -64,19 +65,6 @@ static void __init ct_ca9x4_init_irq(void)
 	ca9x4_twd_init();
 }
 
-static void ct_ca9x4_clcd_enable(struct clcd_fb *fb)
-{
-	u32 site = v2m_get_master_site();
-
-	/*
-	 * Old firmware was using the "site" component of the command
-	 * to control the DVI muxer (while it should be always 0 ie. MB).
-	 * Newer firmware uses the data register. Keep both for compatibility.
-	 */
-	v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE(site), site);
-	v2m_cfg_write(SYS_CFG_DVIMODE | SYS_CFG_SITE(SYS_CFG_SITE_MB), 2);
-}
-
 static int ct_ca9x4_clcd_setup(struct clcd_fb *fb)
 {
 	unsigned long framesize = 1024 * 768 * 2;
@@ -93,7 +81,6 @@ static struct clcd_board ct_ca9x4_clcd_data = {
 	.caps		= CLCD_CAP_5551 | CLCD_CAP_565,
 	.check		= clcdfb_check,
 	.decode		= clcdfb_decode,
-	.enable		= ct_ca9x4_clcd_enable,
 	.setup		= ct_ca9x4_clcd_setup,
 	.mmap		= versatile_clcd_mmap_dma,
 	.remove		= versatile_clcd_remove_dma,
@@ -111,14 +98,6 @@ static struct amba_device *ct_ca9x4_amba_devs[] __initdata = {
 	&gpio_device,
 };
 
-
-static struct v2m_osc ct_osc1 = {
-	.osc = 1,
-	.rate_min = 10000000,
-	.rate_max = 80000000,
-	.rate_default = 23750000,
-};
-
 static struct resource pmu_resources[] = {
 	[0] = {
 		.start	= IRQ_CT_CA9X4_PMU_CPU0,
@@ -149,10 +128,18 @@ static struct platform_device pmu_device = {
 	.resource	= pmu_resources,
 };
 
+static struct platform_device osc1_device = {
+	.name		= "vexpress-osc",
+	.id		= 1,
+	.num_resources	= 1,
+	.resource	= (struct resource []) {
+		VEXPRESS_RES_FUNC(0xf, 1),
+	},
+};
+
 static void __init ct_ca9x4_init(void)
 {
 	int i;
-	struct clk *clk;
 
 #ifdef CONFIG_CACHE_L2X0
 	void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K);
@@ -164,14 +151,14 @@ static void __init ct_ca9x4_init(void)
 	l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff);
 #endif
 
-	ct_osc1.site = v2m_get_master_site();
-	clk = v2m_osc_register("ct:osc1", &ct_osc1);
-	clk_register_clkdev(clk, NULL, "ct:clcd");
-
 	for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++)
 		amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource);
 
 	platform_device_register(&pmu_device);
+	platform_device_register(&osc1_device);
+
+	WARN_ON(clk_register_clkdev(vexpress_osc_setup(&osc1_device.dev),
+			NULL, "ct:clcd"));
 }
 
 #ifdef CONFIG_SMP
diff --git a/arch/arm/mach-vexpress/include/mach/motherboard.h b/arch/arm/mach-vexpress/include/mach/motherboard.h
index 1e388c7..68abc8b 100644
--- a/arch/arm/mach-vexpress/include/mach/motherboard.h
+++ b/arch/arm/mach-vexpress/include/mach/motherboard.h
@@ -1,8 +1,6 @@
 #ifndef __MACH_MOTHERBOARD_H
 #define __MACH_MOTHERBOARD_H
 
-#include <linux/clk-provider.h>
-
 /*
  * Physical addresses, offset from V2M_PA_CS0-3
  */
@@ -41,31 +39,6 @@
 #define V2M_CF			(V2M_PA_CS7 + 0x0001a000)
 #define V2M_CLCD		(V2M_PA_CS7 + 0x0001f000)
 
-/*
- * Offsets from SYSREGS base
- */
-#define V2M_SYS_ID		0x000
-#define V2M_SYS_SW		0x004
-#define V2M_SYS_LED		0x008
-#define V2M_SYS_100HZ		0x024
-#define V2M_SYS_FLAGS		0x030
-#define V2M_SYS_FLAGSSET	0x030
-#define V2M_SYS_FLAGSCLR	0x034
-#define V2M_SYS_NVFLAGS		0x038
-#define V2M_SYS_NVFLAGSSET	0x038
-#define V2M_SYS_NVFLAGSCLR	0x03c
-#define V2M_SYS_MCI		0x048
-#define V2M_SYS_FLASH		0x03c
-#define V2M_SYS_CFGSW		0x058
-#define V2M_SYS_24MHZ		0x05c
-#define V2M_SYS_MISC		0x060
-#define V2M_SYS_DMA		0x064
-#define V2M_SYS_PROCID0		0x084
-#define V2M_SYS_PROCID1		0x088
-#define V2M_SYS_CFGDATA		0x0a0
-#define V2M_SYS_CFGCTRL		0x0a4
-#define V2M_SYS_CFGSTAT		0x0a8
-
 
 /*
  * Interrupts.  Those in {} are for AMBA devices
@@ -91,43 +64,6 @@
 
 
 /*
- * Configuration
- */
-#define SYS_CFG_START		(1 << 31)
-#define SYS_CFG_WRITE		(1 << 30)
-#define SYS_CFG_OSC		(1 << 20)
-#define SYS_CFG_VOLT		(2 << 20)
-#define SYS_CFG_AMP		(3 << 20)
-#define SYS_CFG_TEMP		(4 << 20)
-#define SYS_CFG_RESET		(5 << 20)
-#define SYS_CFG_SCC		(6 << 20)
-#define SYS_CFG_MUXFPGA		(7 << 20)
-#define SYS_CFG_SHUTDOWN	(8 << 20)
-#define SYS_CFG_REBOOT		(9 << 20)
-#define SYS_CFG_DVIMODE		(11 << 20)
-#define SYS_CFG_POWER		(12 << 20)
-#define SYS_CFG_SITE(n)		((n) << 16)
-#define SYS_CFG_SITE_MB		0
-#define SYS_CFG_SITE_DB1	1
-#define SYS_CFG_SITE_DB2	2
-#define SYS_CFG_STACK(n)	((n) << 12)
-
-#define SYS_CFG_ERR		(1 << 1)
-#define SYS_CFG_COMPLETE	(1 << 0)
-
-int v2m_cfg_write(u32 devfn, u32 data);
-int v2m_cfg_read(u32 devfn, u32 *data);
-void v2m_flags_set(u32 data);
-
-/*
- * Miscellaneous
- */
-#define SYS_MISC_MASTERSITE	(1 << 14)
-#define SYS_PROCIDx_HBI_MASK	0xfff
-
-int v2m_get_master_site(void);
-
-/*
  * Core tile IDs
  */
 #define V2M_CT_ID_CA9		0x0c000191
@@ -149,21 +85,4 @@ struct ct_desc {
 
 extern struct ct_desc *ct_desc;
 
-/*
- * OSC clock provider
- */
-struct v2m_osc {
-	struct clk_hw hw;
-	u8 site; /* 0 = motherboard, 1 = site 1, 2 = site 2 */
-	u8 stack; /* board stack position */
-	u16 osc;
-	unsigned long rate_min;
-	unsigned long rate_max;
-	unsigned long rate_default;
-};
-
-#define to_v2m_osc(osc) container_of(osc, struct v2m_osc, hw)
-
-struct clk *v2m_osc_register(const char *name, struct v2m_osc *osc);
-
 #endif
diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
index 7db27c8..c5d70de 100644
--- a/arch/arm/mach-vexpress/platsmp.c
+++ b/arch/arm/mach-vexpress/platsmp.c
@@ -13,6 +13,7 @@
 #include <linux/smp.h>
 #include <linux/io.h>
 #include <linux/of_fdt.h>
+#include <linux/vexpress.h>
 
 #include <asm/smp_scu.h>
 #include <asm/hardware/gic.h>
@@ -193,7 +194,7 @@ static void __init vexpress_smp_prepare_cpus(unsigned int max_cpus)
 	 * until it receives a soft interrupt, and then the
 	 * secondary CPU branches to this address.
 	 */
-	v2m_flags_set(virt_to_phys(versatile_secondary_startup));
+	vexpress_flags_set(virt_to_phys(versatile_secondary_startup));
 }
 
 struct smp_operations __initdata vexpress_smp_ops = {
diff --git a/arch/arm/mach-vexpress/reset.c b/arch/arm/mach-vexpress/reset.c
new file mode 100644
index 0000000..465923a
--- /dev/null
+++ b/arch/arm/mach-vexpress/reset.c
@@ -0,0 +1,141 @@
+/*
+ * This program is free software; you can 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#include <linux/jiffies.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/stat.h>
+#include <linux/vexpress.h>
+
+static void vexpress_reset_do(struct device *dev, const char *what)
+{
+	int err = -ENOENT;
+	struct vexpress_config_func *func =
+			vexpress_config_func_get_by_dev(dev);
+
+	if (func) {
+		unsigned long timeout;
+
+		err = vexpress_config_write(func, 0, 0);
+
+		timeout = jiffies + HZ;
+		while (time_before(jiffies, timeout))
+			cpu_relax();
+	}
+
+	dev_emerg(dev, "Unable to %s (%d)\n", what, err);
+}
+
+static struct device *vexpress_power_off_device;
+
+void vexpress_power_off(void)
+{
+	vexpress_reset_do(vexpress_power_off_device, "power off");
+}
+
+static struct device *vexpress_restart_device;
+
+void vexpress_restart(char str, const char *cmd)
+{
+	vexpress_reset_do(vexpress_restart_device, "restart");
+}
+
+static ssize_t vexpress_reset_active_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", vexpress_restart_device == dev);
+}
+
+static ssize_t vexpress_reset_active_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	long value;
+	int err = kstrtol(buf, 0, &value);
+
+	if (!err && value)
+		vexpress_restart_device = dev;
+
+	return err ? err : count;
+}
+
+DEVICE_ATTR(active, S_IRUGO | S_IWUSR, vexpress_reset_active_show,
+		vexpress_reset_active_store);
+
+
+enum vexpress_reset_func { FUNC_RESET, FUNC_SHUTDOWN, FUNC_REBOOT };
+
+static struct of_device_id vexpress_reset_of_match[] = {
+	{
+		.compatible = "arm,vexpress-reset",
+		.data = (void *)FUNC_RESET,
+	}, {
+		.compatible = "arm,vexpress-shutdown",
+		.data = (void *)FUNC_SHUTDOWN
+	}, {
+		.compatible = "arm,vexpress-reboot",
+		.data = (void *)FUNC_REBOOT
+	},
+	{}
+};
+
+static int vexpress_reset_probe(struct platform_device *pdev)
+{
+	enum vexpress_reset_func func;
+	const struct of_device_id *match =
+			of_match_device(vexpress_reset_of_match, &pdev->dev);
+
+	if (match)
+		func = (enum vexpress_reset_func)match->data;
+	else
+		func = pdev->id_entry->driver_data;
+
+	switch (func) {
+	case FUNC_SHUTDOWN:
+		vexpress_power_off_device = &pdev->dev;
+		break;
+	case FUNC_RESET:
+		if (!vexpress_restart_device)
+			vexpress_restart_device = &pdev->dev;
+		device_create_file(&pdev->dev, &dev_attr_active);
+		break;
+	case FUNC_REBOOT:
+		vexpress_restart_device = &pdev->dev;
+		device_create_file(&pdev->dev, &dev_attr_active);
+		break;
+	};
+
+	return 0;
+}
+
+static const struct platform_device_id vexpress_reset_id_table[] = {
+	{ .name = "vexpress-reset", .driver_data = FUNC_RESET, },
+	{ .name = "vexpress-shutdown", .driver_data = FUNC_SHUTDOWN, },
+	{ .name = "vexpress-reboot", .driver_data = FUNC_REBOOT, },
+	{}
+};
+
+static struct platform_driver vexpress_reset_driver = {
+	.probe = vexpress_reset_probe,
+	.driver = {
+		.name = "vexpress-reset",
+		.of_match_table = vexpress_reset_of_match,
+	},
+	.id_table = vexpress_reset_id_table,
+};
+
+static int __init vexpress_reset_init(void)
+{
+	return platform_driver_register(&vexpress_reset_driver);
+}
+device_initcall(vexpress_reset_init);
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 560e0df..4e168e8 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -16,11 +16,10 @@
 #include <linux/smsc911x.h>
 #include <linux/spinlock.h>
 #include <linux/usb/isp1760.h>
-#include <linux/clkdev.h>
-#include <linux/clk-provider.h>
 #include <linux/mtd/physmap.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
+#include <linux/vexpress.h>
 
 #include <asm/arch_timer.h>
 #include <asm/mach-types.h>
@@ -33,7 +32,6 @@
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/timer-sp.h>
-#include <asm/hardware/sp810.h>
 
 #include <mach/ct-ca9x4.h>
 #include <mach/motherboard.h>
@@ -58,22 +56,6 @@ static struct map_desc v2m_io_desc[] __initdata = {
 	},
 };
 
-static void __iomem *v2m_sysreg_base;
-
-static void __init v2m_sysctl_init(void __iomem *base)
-{
-	u32 scctrl;
-
-	if (WARN_ON(!base))
-		return;
-
-	/* Select 1MHz TIMCLK as the reference clock for SP804 timers */
-	scctrl = readl(base + SCCTRL);
-	scctrl |= SCCTRL_TIMEREN0SEL_TIMCLK;
-	scctrl |= SCCTRL_TIMEREN1SEL_TIMCLK;
-	writel(scctrl, base + SCCTRL);
-}
-
 static void __init v2m_sp804_init(void __iomem *base, unsigned int irq)
 {
 	if (WARN_ON(!base || irq == NO_IRQ))
@@ -87,69 +69,6 @@ static void __init v2m_sp804_init(void __iomem *base, unsigned int irq)
 }
 
 
-static DEFINE_SPINLOCK(v2m_cfg_lock);
-
-int v2m_cfg_write(u32 devfn, u32 data)
-{
-	/* Configuration interface broken? */
-	u32 val;
-
-	printk("%s: writing %08x to %08x\n", __func__, data, devfn);
-
-	devfn |= SYS_CFG_START | SYS_CFG_WRITE;
-
-	spin_lock(&v2m_cfg_lock);
-	val = readl(v2m_sysreg_base + V2M_SYS_CFGSTAT);
-	writel(val & ~SYS_CFG_COMPLETE, v2m_sysreg_base + V2M_SYS_CFGSTAT);
-
-	writel(data, v2m_sysreg_base +  V2M_SYS_CFGDATA);
-	writel(devfn, v2m_sysreg_base + V2M_SYS_CFGCTRL);
-
-	do {
-		val = readl(v2m_sysreg_base + V2M_SYS_CFGSTAT);
-	} while (val == 0);
-	spin_unlock(&v2m_cfg_lock);
-
-	return !!(val & SYS_CFG_ERR);
-}
-
-int v2m_cfg_read(u32 devfn, u32 *data)
-{
-	u32 val;
-
-	devfn |= SYS_CFG_START;
-
-	spin_lock(&v2m_cfg_lock);
-	writel(0, v2m_sysreg_base + V2M_SYS_CFGSTAT);
-	writel(devfn, v2m_sysreg_base + V2M_SYS_CFGCTRL);
-
-	mb();
-
-	do {
-		cpu_relax();
-		val = readl(v2m_sysreg_base + V2M_SYS_CFGSTAT);
-	} while (val == 0);
-
-	*data = readl(v2m_sysreg_base + V2M_SYS_CFGDATA);
-	spin_unlock(&v2m_cfg_lock);
-
-	return !!(val & SYS_CFG_ERR);
-}
-
-void __init v2m_flags_set(u32 data)
-{
-	writel(~0, v2m_sysreg_base + V2M_SYS_FLAGSCLR);
-	writel(data, v2m_sysreg_base + V2M_SYS_FLAGSSET);
-}
-
-int v2m_get_master_site(void)
-{
-	u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC);
-
-	return misc & SYS_MISC_MASTERSITE ? SYS_CFG_SITE_DB2 : SYS_CFG_SITE_DB1;
-}
-
-
 static struct resource v2m_pcie_i2c_resource = {
 	.start	= V2M_SERIAL_BUS_PCI,
 	.end	= V2M_SERIAL_BUS_PCI + SZ_4K - 1,
@@ -237,14 +156,8 @@ static struct platform_device v2m_usb_device = {
 	.dev.platform_data = &v2m_usb_config,
 };
 
-static void v2m_flash_set_vpp(struct platform_device *pdev, int on)
-{
-	writel(on != 0, v2m_sysreg_base + V2M_SYS_FLASH);
-}
-
 static struct physmap_flash_data v2m_flash_data = {
 	.width		= 4,
-	.set_vpp	= v2m_flash_set_vpp,
 };
 
 static struct resource v2m_flash_resources[] = {
@@ -291,14 +204,61 @@ static struct platform_device v2m_cf_device = {
 	.dev.platform_data = &v2m_pata_data,
 };
 
-static unsigned int v2m_mmci_status(struct device *dev)
-{
-	return readl(v2m_sysreg_base + V2M_SYS_MCI) & (1 << 0);
-}
-
 static struct mmci_platform_data v2m_mmci_data = {
 	.ocr_mask	= MMC_VDD_32_33|MMC_VDD_33_34,
-	.status		= v2m_mmci_status,
+	.gpio_wp	= VEXPRESS_GPIO_MMC_WPROT,
+	.gpio_cd	= VEXPRESS_GPIO_MMC_CARDIN,
+};
+
+static struct resource v2m_sysreg_resources[] = {
+	{
+		.start	= V2M_SYSREGS,
+		.end	= V2M_SYSREGS + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device v2m_sysreg_device = {
+	.name		= "vexpress-sysreg",
+	.id		= -1,
+	.resource	= v2m_sysreg_resources,
+	.num_resources	= ARRAY_SIZE(v2m_sysreg_resources),
+};
+
+static struct platform_device v2m_muxfpga_device = {
+	.name		= "vexpress-muxfpga",
+	.id		= 0,
+	.num_resources	= 1,
+	.resource	= (struct resource []) {
+		VEXPRESS_RES_FUNC(0, 7),
+	}
+};
+
+static struct platform_device v2m_shutdown_device = {
+	.name		= "vexpress-shutdown",
+	.id		= 0,
+	.num_resources	= 1,
+	.resource	= (struct resource []) {
+		VEXPRESS_RES_FUNC(0, 8),
+	}
+};
+
+static struct platform_device v2m_reboot_device = {
+	.name		= "vexpress-reboot",
+	.id		= 0,
+	.num_resources	= 1,
+	.resource	= (struct resource []) {
+		VEXPRESS_RES_FUNC(0, 9),
+	}
+};
+
+static struct platform_device v2m_dvimode_device = {
+	.name		= "vexpress-dvimode",
+	.id		= 0,
+	.num_resources	= 1,
+	.resource	= (struct resource []) {
+		VEXPRESS_RES_FUNC(0, 11),
+	}
 };
 
 static AMBA_APB_DEVICE(aaci,  "mb:aaci",  0, V2M_AACI, IRQ_V2M_AACI, NULL);
@@ -325,123 +285,9 @@ static struct amba_device *v2m_amba_devs[] __initdata = {
 	&rtc_device,
 };
 
-
-static unsigned long v2m_osc_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct v2m_osc *osc = to_v2m_osc(hw);
-
-	return !parent_rate ? osc->rate_default : parent_rate;
-}
-
-static long v2m_osc_round_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long *parent_rate)
-{
-	struct v2m_osc *osc = to_v2m_osc(hw);
-
-	if (WARN_ON(rate < osc->rate_min))
-		rate = osc->rate_min;
-
-	if (WARN_ON(rate > osc->rate_max))
-		rate = osc->rate_max;
-
-	return rate;
-}
-
-static int v2m_osc_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	struct v2m_osc *osc = to_v2m_osc(hw);
-
-	v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE(osc->site) |
-			SYS_CFG_STACK(osc->stack) | osc->osc, rate);
-
-	return 0;
-}
-
-static struct clk_ops v2m_osc_ops = {
-	.recalc_rate = v2m_osc_recalc_rate,
-	.round_rate = v2m_osc_round_rate,
-	.set_rate = v2m_osc_set_rate,
-};
-
-struct clk * __init v2m_osc_register(const char *name, struct v2m_osc *osc)
-{
-	struct clk_init_data init;
-
-	WARN_ON(osc->site > 2);
-	WARN_ON(osc->stack > 15);
-	WARN_ON(osc->osc > 4095);
-
-	init.name = name;
-	init.ops = &v2m_osc_ops;
-	init.flags = CLK_IS_ROOT;
-	init.num_parents = 0;
-
-	osc->hw.init = &init;
-
-	return clk_register(NULL, &osc->hw);
-}
-
-static struct v2m_osc v2m_mb_osc1 = {
-	.site = SYS_CFG_SITE_MB,
-	.osc = 1,
-	.rate_min = 23750000,
-	.rate_max = 63500000,
-	.rate_default = 23750000,
-};
-
-static const char *v2m_ref_clk_periphs[] __initconst = {
-	"mb:wdt",   "1000f000.wdt",  "1c0f0000.wdt",	/* SP805 WDT */
-};
-
-static const char *v2m_osc1_periphs[] __initconst = {
-	"mb:clcd",  "1001f000.clcd", "1c1f0000.clcd",	/* PL111 CLCD */
-};
-
-static const char *v2m_osc2_periphs[] __initconst = {
-	"mb:mmci",  "10005000.mmci", "1c050000.mmci",	/* PL180 MMCI */
-	"mb:kmi0",  "10006000.kmi",  "1c060000.kmi",	/* PL050 KMI0 */
-	"mb:kmi1",  "10007000.kmi",  "1c070000.kmi",	/* PL050 KMI1 */
-	"mb:uart0", "10009000.uart", "1c090000.uart",	/* PL011 UART0 */
-	"mb:uart1", "1000a000.uart", "1c0a0000.uart",	/* PL011 UART1 */
-	"mb:uart2", "1000b000.uart", "1c0b0000.uart",	/* PL011 UART2 */
-	"mb:uart3", "1000c000.uart", "1c0c0000.uart",	/* PL011 UART3 */
-};
-
-static void __init v2m_clk_init(void)
-{
-	struct clk *clk;
-	int i;
-
-	clk = clk_register_fixed_rate(NULL, "dummy_apb_pclk", NULL,
-			CLK_IS_ROOT, 0);
-	WARN_ON(clk_register_clkdev(clk, "apb_pclk", NULL));
-
-	clk = clk_register_fixed_rate(NULL, "mb:ref_clk", NULL,
-			CLK_IS_ROOT, 32768);
-	for (i = 0; i < ARRAY_SIZE(v2m_ref_clk_periphs); i++)
-		WARN_ON(clk_register_clkdev(clk, NULL, v2m_ref_clk_periphs[i]));
-
-	clk = clk_register_fixed_rate(NULL, "mb:sp804_clk", NULL,
-			CLK_IS_ROOT, 1000000);
-	WARN_ON(clk_register_clkdev(clk, "v2m-timer0", "sp804"));
-	WARN_ON(clk_register_clkdev(clk, "v2m-timer1", "sp804"));
-
-	clk = v2m_osc_register("mb:osc1", &v2m_mb_osc1);
-	for (i = 0; i < ARRAY_SIZE(v2m_osc1_periphs); i++)
-		WARN_ON(clk_register_clkdev(clk, NULL, v2m_osc1_periphs[i]));
-
-	clk = clk_register_fixed_rate(NULL, "mb:osc2", NULL,
-			CLK_IS_ROOT, 24000000);
-	for (i = 0; i < ARRAY_SIZE(v2m_osc2_periphs); i++)
-		WARN_ON(clk_register_clkdev(clk, NULL, v2m_osc2_periphs[i]));
-}
-
 static void __init v2m_timer_init(void)
 {
-	v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K));
-	v2m_clk_init();
+	vexpress_clk_init(ioremap(V2M_SYSCTL, SZ_4K));
 	v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
 }
 
@@ -453,19 +299,7 @@ static void __init v2m_init_early(void)
 {
 	if (ct_desc->init_early)
 		ct_desc->init_early();
-	versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000);
-}
-
-static void v2m_power_off(void)
-{
-	if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE(SYS_CFG_SITE_MB), 0))
-		printk(KERN_EMERG "Unable to shutdown\n");
-}
-
-static void v2m_restart(char str, const char *cmd)
-{
-	if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE(SYS_CFG_SITE_MB), 0))
-		printk(KERN_EMERG "Unable to reboot\n");
+	versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000);
 }
 
 struct ct_desc *ct_desc;
@@ -482,7 +316,7 @@ static void __init v2m_populate_ct_desc(void)
 	u32 current_tile_id;
 
 	ct_desc = NULL;
-	current_tile_id = readl(v2m_sysreg_base + V2M_SYS_PROCID0)
+	current_tile_id = vexpress_get_procid(VEXPRESS_SITE_MASTER)
 				& V2M_CT_ID_MASK;
 
 	for (i = 0; i < ARRAY_SIZE(ct_descs) && !ct_desc; ++i)
@@ -498,7 +332,7 @@ static void __init v2m_populate_ct_desc(void)
 static void __init v2m_map_io(void)
 {
 	iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
-	v2m_sysreg_base = ioremap(V2M_SYSREGS, SZ_4K);
+	vexpress_sysreg_early_init(ioremap(V2M_SYSREGS, SZ_4K));
 	v2m_populate_ct_desc();
 	ct_desc->map_io();
 }
@@ -515,6 +349,12 @@ static void __init v2m_init(void)
 	regulator_register_fixed(0, v2m_eth_supplies,
 			ARRAY_SIZE(v2m_eth_supplies));
 
+	platform_device_register(&v2m_muxfpga_device);
+	platform_device_register(&v2m_shutdown_device);
+	platform_device_register(&v2m_reboot_device);
+	platform_device_register(&v2m_dvimode_device);
+
+	platform_device_register(&v2m_sysreg_device);
 	platform_device_register(&v2m_pcie_i2c_device);
 	platform_device_register(&v2m_ddc_i2c_device);
 	platform_device_register(&v2m_flash_device);
@@ -525,7 +365,7 @@ static void __init v2m_init(void)
 	for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++)
 		amba_device_register(v2m_amba_devs[i], &iomem_resource);
 
-	pm_power_off = v2m_power_off;
+	pm_power_off = vexpress_power_off;
 
 	ct_desc->init_tile();
 }
@@ -539,7 +379,7 @@ MACHINE_START(VEXPRESS, "ARM-Versatile Express")
 	.timer		= &v2m_timer,
 	.handle_irq	= gic_handle_irq,
 	.init_machine	= v2m_init,
-	.restart	= v2m_restart,
+	.restart	= vexpress_restart,
 MACHINE_END
 
 static struct map_desc v2m_rs1_io_desc __initdata = {
@@ -580,20 +420,13 @@ void __init v2m_dt_map_io(void)
 
 void __init v2m_dt_init_early(void)
 {
-	struct device_node *node;
 	u32 dt_hbi;
 
-	node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg");
-	v2m_sysreg_base = of_iomap(node, 0);
-	if (WARN_ON(!v2m_sysreg_base))
-		return;
+	vexpress_sysreg_of_early_init();
 
 	/* Confirm board type against DT property, if available */
 	if (of_property_read_u32(allnodes, "arm,hbi", &dt_hbi) == 0) {
-		int site = v2m_get_master_site();
-		u32 id = readl(v2m_sysreg_base + (site == SYS_CFG_SITE_DB2 ?
-				V2M_SYS_PROCID1 : V2M_SYS_PROCID0));
-		u32 hbi = id & SYS_PROCIDx_HBI_MASK;
+		u32 hbi = vexpress_get_hbi(VEXPRESS_SITE_MASTER);
 
 		if (WARN_ON(dt_hbi != hbi))
 			pr_warning("vexpress: DT HBI (%x) is not matching "
@@ -613,51 +446,47 @@ static void __init v2m_dt_init_irq(void)
 
 static void __init v2m_dt_timer_init(void)
 {
-	struct device_node *node;
-	const char *path;
-	int err;
+	struct device_node *node = NULL;
 
-	node = of_find_compatible_node(NULL, NULL, "arm,sp810");
-	v2m_sysctl_init(of_iomap(node, 0));
+	vexpress_clk_of_init();
 
-	v2m_clk_init();
+	do {
+		node = of_find_compatible_node(node, NULL, "arm,sp804");
+	} while (node && vexpress_get_site_by_node(node) != VEXPRESS_SITE_MB);
+	if (node) {
+		pr_info("Using SP804 '%s' as a clock & events source\n",
+				node->full_name);
+		v2m_sp804_init(of_iomap(node, 0),
+				irq_of_parse_and_map(node, 0));
+	}
 
-	err = of_property_read_string(of_aliases, "arm,v2m_timer", &path);
-	if (WARN_ON(err))
-		return;
-	node = of_find_node_by_path(path);
-	v2m_sp804_init(of_iomap(node, 0), irq_of_parse_and_map(node, 0));
 	if (arch_timer_of_register() != 0)
 		twd_local_timer_of_register();
 
 	if (arch_timer_sched_clock_init() != 0)
-		versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000);
+		versatile_sched_clock_init(vexpress_get_24mhz_clock_base(),
+				24000000);
 }
 
 static struct sys_timer v2m_dt_timer = {
 	.init = v2m_dt_timer_init,
 };
 
-static struct of_dev_auxdata v2m_dt_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("arm,vexpress-flash", V2M_NOR0, "physmap-flash",
-			&v2m_flash_data),
-	OF_DEV_AUXDATA("arm,primecell", V2M_MMCI, "mb:mmci", &v2m_mmci_data),
-	/* RS1 memory map */
-	OF_DEV_AUXDATA("arm,vexpress-flash", 0x08000000, "physmap-flash",
-			&v2m_flash_data),
-	OF_DEV_AUXDATA("arm,primecell", 0x1c050000, "mb:mmci", &v2m_mmci_data),
+static const struct of_device_id v2m_dt_bus_match[] __initconst = {
+	{ .compatible = "simple-bus", },
+	{ .compatible = "arm,amba-bus", },
+	{ .compatible = "arm,vexpress,config-bus", },
 	{}
 };
 
 static void __init v2m_dt_init(void)
 {
 	l2x0_of_init(0x00400000, 0xfe0fffff);
-	of_platform_populate(NULL, of_default_bus_match_table,
-			v2m_dt_auxdata_lookup, NULL);
-	pm_power_off = v2m_power_off;
+	of_platform_populate(NULL, v2m_dt_bus_match, NULL, NULL);
+	pm_power_off = vexpress_power_off;
 }
 
-const static char *v2m_dt_match[] __initconst = {
+static const char * const v2m_dt_match[] __initconst = {
 	"arm,vexpress",
 	"xen,xenvm",
 	NULL,
@@ -672,5 +501,5 @@ DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
 	.timer		= &v2m_dt_timer,
 	.init_machine	= v2m_dt_init,
 	.handle_irq	= gic_handle_irq,
-	.restart	= v2m_restart,
+	.restart	= vexpress_restart,
 MACHINE_END
diff --git a/arch/arm/mach-vt8500/Kconfig b/arch/arm/mach-vt8500/Kconfig
new file mode 100644
index 0000000..2ed0b7d
--- /dev/null
+++ b/arch/arm/mach-vt8500/Kconfig
@@ -0,0 +1,12 @@
+config ARCH_VT8500
+	bool "VIA/WonderMedia 85xx" if ARCH_MULTI_V5
+	default ARCH_VT8500_SINGLE
+	select ARCH_HAS_CPUFREQ
+	select ARCH_REQUIRE_GPIOLIB
+	select CLKDEV_LOOKUP
+	select CPU_ARM926T
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_GPIO
+	select HAVE_CLK
+	help
+	  Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
diff --git a/arch/arm/mach-vt8500/common.h b/arch/arm/mach-vt8500/common.h
index 2b24196..6f2b843 100644
--- a/arch/arm/mach-vt8500/common.h
+++ b/arch/arm/mach-vt8500/common.h
@@ -25,4 +25,7 @@ int __init vt8500_irq_init(struct device_node *node,
 /* defined in drivers/clk/clk-vt8500.c */
 void __init vtwm_clk_init(void __iomem *pmc_base);
 
+/* defined in irq.c */
+asmlinkage void vt8500_handle_irq(struct pt_regs *regs);
+
 #endif
diff --git a/arch/arm/mach-vt8500/include/mach/entry-macro.S b/arch/arm/mach-vt8500/include/mach/entry-macro.S
deleted file mode 100644
index 367d1b5..0000000
--- a/arch/arm/mach-vt8500/include/mach/entry-macro.S
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * arch/arm/mach-vt8500/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for VIA VT8500
- *
- * 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
-	@ physical 0xd8140000 is virtual 0xf8140000
-	mov	\base, #0xf8000000
-	orr	\base, \base, #0x00140000
-	.endm
-
-	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-	ldr	\irqnr, [\base]
-	cmp	\irqnr, #63 @ may be false positive, check interrupt status
-	bne	1001f
-	ldr	\irqstat, [\base, #0x84]
-	ands	\irqstat, #0x80000000
-	moveq	\irqnr, #0
-1001:
-	.endm
-
diff --git a/arch/arm/mach-vt8500/include/mach/hardware.h b/arch/arm/mach-vt8500/include/mach/hardware.h
deleted file mode 100644
index db4163f..0000000
--- a/arch/arm/mach-vt8500/include/mach/hardware.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* arch/arm/mach-vt8500/include/mach/hardware.h
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
diff --git a/arch/arm/mach-vt8500/include/mach/i8042.h b/arch/arm/mach-vt8500/include/mach/i8042.h
deleted file mode 100644
index cd7143c..0000000
--- a/arch/arm/mach-vt8500/include/mach/i8042.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* arch/arm/mach-vt8500/include/mach/i8042.h
- *
- * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-extern unsigned long wmt_i8042_base __initdata;
-extern int wmt_i8042_kbd_irq;
-extern int wmt_i8042_aux_irq;
diff --git a/arch/arm/mach-vt8500/include/mach/irqs.h b/arch/arm/mach-vt8500/include/mach/irqs.h
deleted file mode 100644
index a129fd1..0000000
--- a/arch/arm/mach-vt8500/include/mach/irqs.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- *  arch/arm/mach-vt8500/include/mach/irqs.h
- *
- *  Copyright (C) 2010 Alexey Charkov <alchark@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
- */
-
-/* This value is just to make the core happy, never used otherwise */
-#define NR_IRQS 128
diff --git a/arch/arm/mach-vt8500/include/mach/restart.h b/arch/arm/mach-vt8500/include/mach/restart.h
deleted file mode 100644
index 7389795..0000000
--- a/arch/arm/mach-vt8500/include/mach/restart.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* linux/arch/arm/mach-vt8500/restart.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.
- *
- */
-
-void vt8500_setup_restart(void);
-void vt8500_restart(char mode, const char *cmd);
diff --git a/arch/arm/mach-vt8500/irq.c b/arch/arm/mach-vt8500/irq.c
index f8f9ab9..b9cf5ce 100644
--- a/arch/arm/mach-vt8500/irq.c
+++ b/arch/arm/mach-vt8500/irq.c
@@ -36,7 +36,7 @@
 #include <linux/of_address.h>
 
 #include <asm/irq.h>
-
+#include <asm/exception.h>
 
 #define VT8500_ICPC_IRQ		0x20
 #define VT8500_ICPC_FIQ		0x24
@@ -66,30 +66,34 @@
 #define VT8500_EDGE		( VT8500_TRIGGER_RISING \
 				| VT8500_TRIGGER_FALLING)
 
-static int irq_cnt;
+/* vt8500 has 1 intc, wm8505 and wm8650 have 2 */
+#define VT8500_INTC_MAX		2
 
-struct vt8500_irq_priv {
-	void __iomem *base;
+struct vt8500_irq_data {
+	void __iomem 		*base;		/* IO Memory base address */
+	struct irq_domain	*domain;	/* Domain for this controller */
 };
 
+/* Global variable for accessing io-mem addresses */
+static struct vt8500_irq_data intc[VT8500_INTC_MAX];
+static u32 active_cnt = 0;
+
 static void vt8500_irq_mask(struct irq_data *d)
 {
-	struct vt8500_irq_priv *priv =
-			(struct vt8500_irq_priv *)(d->domain->host_data);
+	struct vt8500_irq_data *priv = d->domain->host_data;
 	void __iomem *base = priv->base;
-	u8 edge;
+	void __iomem *stat_reg = base + VT8500_ICIS + (d->hwirq < 32 ? 0 : 4);
+	u8 edge, dctr;
+	u32 status;
 
 	edge = readb(base + VT8500_ICDC + d->hwirq) & VT8500_EDGE;
 	if (edge) {
-		void __iomem *stat_reg = base + VT8500_ICIS
-						+ (d->hwirq < 32 ? 0 : 4);
-		unsigned status = readl(stat_reg);
+		status = readl(stat_reg);
 
 		status |= (1 << (d->hwirq & 0x1f));
 		writel(status, stat_reg);
 	} else {
-		u8 dctr = readb(base + VT8500_ICDC + d->hwirq);
-
+		dctr = readb(base + VT8500_ICDC + d->hwirq);
 		dctr &= ~VT8500_INT_ENABLE;
 		writeb(dctr, base + VT8500_ICDC + d->hwirq);
 	}
@@ -97,8 +101,7 @@ static void vt8500_irq_mask(struct irq_data *d)
 
 static void vt8500_irq_unmask(struct irq_data *d)
 {
-	struct vt8500_irq_priv *priv =
-			(struct vt8500_irq_priv *)(d->domain->host_data);
+	struct vt8500_irq_data *priv = d->domain->host_data;
 	void __iomem *base = priv->base;
 	u8 dctr;
 
@@ -109,8 +112,7 @@ static void vt8500_irq_unmask(struct irq_data *d)
 
 static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct vt8500_irq_priv *priv =
-			(struct vt8500_irq_priv *)(d->domain->host_data);
+	struct vt8500_irq_data *priv = d->domain->host_data;
 	void __iomem *base = priv->base;
 	u8 dctr;
 
@@ -148,17 +150,15 @@ static struct irq_chip vt8500_irq_chip = {
 
 static void __init vt8500_init_irq_hw(void __iomem *base)
 {
-	unsigned int i;
+	u32 i;
 
 	/* Enable rotating priority for IRQ */
 	writel(ICPC_ROTATE, base + VT8500_ICPC_IRQ);
 	writel(0x00, base + VT8500_ICPC_FIQ);
 
-	for (i = 0; i < 64; i++) {
-		/* Disable all interrupts and route them to IRQ */
-		writeb(VT8500_INT_DISABLE | ICDC_IRQ,
-						base + VT8500_ICDC + i);
-	}
+	/* Disable all interrupts and route them to IRQ */
+	for (i = 0; i < 64; i++)
+		writeb(VT8500_INT_DISABLE | ICDC_IRQ, base + VT8500_ICDC + i);
 }
 
 static int vt8500_irq_map(struct irq_domain *h, unsigned int virq,
@@ -175,33 +175,67 @@ static struct irq_domain_ops vt8500_irq_domain_ops = {
 	.xlate = irq_domain_xlate_onecell,
 };
 
+asmlinkage void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs)
+{
+	u32 stat, i;
+	int irqnr, virq;
+	void __iomem *base;
+
+	/* Loop through each active controller */
+	for (i=0; i<active_cnt; i++) {
+		base = intc[i].base;
+		irqnr = readl_relaxed(base) & 0x3F;
+		/*
+		  Highest Priority register default = 63, so check that this
+		  is a real interrupt by checking the status register
+		*/
+		if (irqnr == 63) {
+			stat = readl_relaxed(base + VT8500_ICIS + 4);
+			if (!(stat & BIT(31)))
+				continue;
+		}
+
+		virq = irq_find_mapping(intc[i].domain, irqnr);
+		handle_IRQ(virq, regs);
+	}
+}
+
 int __init vt8500_irq_init(struct device_node *node, struct device_node *parent)
 {
-	struct irq_domain *vt8500_irq_domain;
-	struct vt8500_irq_priv *priv;
 	int irq, i;
 	struct device_node *np = node;
 
-	priv = kzalloc(sizeof(struct vt8500_irq_priv), GFP_KERNEL);
-	priv->base = of_iomap(np, 0);
+	if (active_cnt == VT8500_INTC_MAX) {
+		pr_err("%s: Interrupt controllers > VT8500_INTC_MAX\n",
+								__func__);
+		goto out;
+	}
+
+	intc[active_cnt].base = of_iomap(np, 0);
+	intc[active_cnt].domain = irq_domain_add_linear(node, 64,
+			&vt8500_irq_domain_ops,	&intc[active_cnt]);
 
-	vt8500_irq_domain = irq_domain_add_legacy(node, 64, irq_cnt, 0,
-				&vt8500_irq_domain_ops, priv);
-	if (!vt8500_irq_domain)
-		pr_err("%s: Unable to add wmt irq domain!\n", __func__);
+	if (!intc[active_cnt].base) {
+		pr_err("%s: Unable to map IO memory\n", __func__);
+		goto out;
+	}
+
+	if (!intc[active_cnt].domain) {
+		pr_err("%s: Unable to add irq domain!\n", __func__);
+		goto out;
+	}
 
-	irq_set_default_host(vt8500_irq_domain);
+	vt8500_init_irq_hw(intc[active_cnt].base);
 
-	vt8500_init_irq_hw(priv->base);
+	pr_info("vt8500-irq: Added interrupt controller\n");
 
-	pr_info("Added IRQ Controller @ %x [virq_base = %d]\n",
-						(u32)(priv->base), irq_cnt);
+	active_cnt++;
 
 	/* check if this is a slaved controller */
 	if (of_irq_count(np) != 0) {
 		/* check that we have the correct number of interrupts */
 		if (of_irq_count(np) != 8) {
-			pr_err("%s: Incorrect IRQ map for slave controller\n",
+			pr_err("%s: Incorrect IRQ map for slaved controller\n",
 					__func__);
 			return -EINVAL;
 		}
@@ -213,9 +247,7 @@ int __init vt8500_irq_init(struct device_node *node, struct device_node *parent)
 
 		pr_info("vt8500-irq: Enabled slave->parent interrupts\n");
 	}
-
-	irq_cnt += 64;
-
+out:
 	return 0;
 }
 
diff --git a/arch/arm/mach-vt8500/timer.c b/arch/arm/mach-vt8500/timer.c
index 050e183..3dd21a4 100644
--- a/arch/arm/mach-vt8500/timer.c
+++ b/arch/arm/mach-vt8500/timer.c
@@ -1,5 +1,5 @@
 /*
- *  arch/arm/mach-vt8500/timer_dt.c
+ *  arch/arm/mach-vt8500/timer.c
  *
  *  Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
  *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
diff --git a/arch/arm/mach-vt8500/vt8500.c b/arch/arm/mach-vt8500/vt8500.c
index 8d3871f..3c66d48 100644
--- a/arch/arm/mach-vt8500/vt8500.c
+++ b/arch/arm/mach-vt8500/vt8500.c
@@ -31,8 +31,6 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
-#include <mach/restart.h>
-
 #include "common.h"
 
 #define LEGACY_GPIO_BASE	0xD8110000
@@ -194,5 +192,6 @@ DT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)")
 	.timer		= &vt8500_timer,
 	.init_machine	= vt8500_init,
 	.restart	= vt8500_restart,
+	.handle_irq	= vt8500_handle_irq,
 MACHINE_END
 
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
new file mode 100644
index 0000000..adb6c0e
--- /dev/null
+++ b/arch/arm/mach-zynq/Kconfig
@@ -0,0 +1,13 @@
+config ARCH_ZYNQ
+	bool "Xilinx Zynq ARM Cortex A9 Platform" if ARCH_MULTI_V7
+	select ARM_AMBA
+	select ARM_GIC
+	select COMMON_CLK
+	select CPU_V7
+	select GENERIC_CLOCKEVENTS
+	select ICST
+	select MIGHT_HAVE_CACHE_L2X0
+	select USE_OF
+	select SPARSE_IRQ
+	help
+	  Support for Xilinx Zynq ARM Cortex A9 Platform
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index ab5cfdd..e16d4be 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -19,19 +19,21 @@
 #include <linux/cpumask.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/clk/zynq.h>
+#include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/of.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/mach/time.h>
 #include <asm/mach-types.h>
 #include <asm/page.h>
+#include <asm/pgtable.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 
-#include <mach/zynq_soc.h>
-#include <mach/clkdev.h>
 #include "common.h"
 
 static struct of_device_id zynq_of_bus_ids[] __initdata = {
@@ -45,55 +47,57 @@ static struct of_device_id zynq_of_bus_ids[] __initdata = {
  */
 static void __init xilinx_init_machine(void)
 {
-#ifdef CONFIG_CACHE_L2X0
 	/*
 	 * 64KB way size, 8-way associativity, parity disabled
 	 */
-	l2x0_init(PL310_L2CC_BASE, 0x02060000, 0xF0F0FFFF);
-#endif
+	l2x0_of_init(0x02060000, 0xF0F0FFFF);
 
 	of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL);
 }
 
+static struct of_device_id irq_match[] __initdata = {
+	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+	{ }
+};
+
 /**
  * xilinx_irq_init() - Interrupt controller initialization for the GIC.
  */
 static void __init xilinx_irq_init(void)
 {
-	gic_init(0, 29, SCU_GIC_DIST_BASE, SCU_GIC_CPU_BASE);
+	of_irq_init(irq_match);
 }
 
-/* The minimum devices needed to be mapped before the VM system is up and
- * running include the GIC, UART and Timer Counter.
- */
+#define SCU_PERIPH_PHYS		0xF8F00000
+#define SCU_PERIPH_SIZE		SZ_8K
+#define SCU_PERIPH_VIRT		(VMALLOC_END - SCU_PERIPH_SIZE)
+
+static struct map_desc scu_desc __initdata = {
+	.virtual	= SCU_PERIPH_VIRT,
+	.pfn		= __phys_to_pfn(SCU_PERIPH_PHYS),
+	.length		= SCU_PERIPH_SIZE,
+	.type		= MT_DEVICE,
+};
+
+static void __init xilinx_zynq_timer_init(void)
+{
+	struct device_node *np;
+	void __iomem *slcr;
+
+	np = of_find_compatible_node(NULL, NULL, "xlnx,zynq-slcr");
+	slcr = of_iomap(np, 0);
+	WARN_ON(!slcr);
+
+	xilinx_zynq_clocks_init(slcr);
 
-static struct map_desc io_desc[] __initdata = {
-	{
-		.virtual	= TTC0_VIRT,
-		.pfn		= __phys_to_pfn(TTC0_PHYS),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= SCU_PERIPH_VIRT,
-		.pfn		= __phys_to_pfn(SCU_PERIPH_PHYS),
-		.length		= SZ_8K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= PL310_L2CC_VIRT,
-		.pfn		= __phys_to_pfn(PL310_L2CC_PHYS),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	},
-
-#ifdef CONFIG_DEBUG_LL
-	{
-		.virtual	= UART0_VIRT,
-		.pfn		= __phys_to_pfn(UART0_PHYS),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	},
-#endif
+	xttcpss_timer_init();
+}
 
+/*
+ * Instantiate and initialize the system timer structure
+ */
+static struct sys_timer xttcpss_sys_timer = {
+	.init		= xilinx_zynq_timer_init,
 };
 
 /**
@@ -101,11 +105,13 @@ static struct map_desc io_desc[] __initdata = {
  */
 static void __init xilinx_map_io(void)
 {
-	iotable_init(io_desc, ARRAY_SIZE(io_desc));
+	debug_ll_io_init();
+	iotable_init(&scu_desc, 1);
 }
 
 static const char *xilinx_dt_match[] = {
-	"xlnx,zynq-ep107",
+	"xlnx,zynq-zc702",
+	"xlnx,zynq-7000",
 	NULL
 };
 
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
index a009644..954b91c 100644
--- a/arch/arm/mach-zynq/common.h
+++ b/arch/arm/mach-zynq/common.h
@@ -17,8 +17,6 @@
 #ifndef __MACH_ZYNQ_COMMON_H__
 #define __MACH_ZYNQ_COMMON_H__
 
-#include <asm/mach/time.h>
-
-extern struct sys_timer xttcpss_sys_timer;
+void __init xttcpss_timer_init(void);
 
 #endif
diff --git a/arch/arm/mach-zynq/include/mach/clkdev.h b/arch/arm/mach-zynq/include/mach/clkdev.h
deleted file mode 100644
index c6e73d8..0000000
--- a/arch/arm/mach-zynq/include/mach/clkdev.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * arch/arm/mach-zynq/include/mach/clkdev.h
- *
- *  Copyright (C) 2011 Xilinx, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_CLKDEV_H__
-#define __MACH_CLKDEV_H__
-
-#include <plat/clock.h>
-
-struct clk {
-	unsigned long		rate;
-	const struct clk_ops	*ops;
-	const struct icst_params *params;
-	void __iomem		*vcoreg;
-};
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-zynq/include/mach/debug-macro.S b/arch/arm/mach-zynq/include/mach/debug-macro.S
deleted file mode 100644
index 3ab0be1..0000000
--- a/arch/arm/mach-zynq/include/mach/debug-macro.S
+++ /dev/null
@@ -1,36 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 2011 Xilinx
- *
- * 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 <mach/zynq_soc.h>
-#include <mach/uart.h>
-
-		.macro	addruart, rp, rv, tmp
-		ldr	\rp, =LL_UART_PADDR	@ physical
-		ldr	\rv, =LL_UART_VADDR	@ virtual
-		.endm
-
-		.macro	senduart,rd,rx
-		str	\rd, [\rx, #UART_FIFO_OFFSET]	@ TXDATA
-		.endm
-
-		.macro	waituart,rd,rx
-		.endm
-
-		.macro	busyuart,rd,rx
-1002:		ldr	\rd, [\rx, #UART_SR_OFFSET]	@ get status register
-		tst	\rd, #UART_SR_TXFULL		@
-		bne	1002b			@ wait if FIFO is full
-		.endm
diff --git a/arch/arm/mach-zynq/include/mach/hardware.h b/arch/arm/mach-zynq/include/mach/hardware.h
deleted file mode 100644
index d558d8a..0000000
--- a/arch/arm/mach-zynq/include/mach/hardware.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/hardware.h
- *
- *  Copyright (C) 2011 Xilinx
- *
- * 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_HARDWARE_H__
-#define __MACH_HARDWARE_H__
-
-#endif
diff --git a/arch/arm/mach-zynq/include/mach/irqs.h b/arch/arm/mach-zynq/include/mach/irqs.h
deleted file mode 100644
index 5fb04fd..0000000
--- a/arch/arm/mach-zynq/include/mach/irqs.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/irqs.h
- *
- *  Copyright (C) 2011 Xilinx
- *
- * 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_IRQS_H
-#define __MACH_IRQS_H
-
-#define ARCH_NR_GPIOS	118
-#define NR_IRQS		(128 + ARCH_NR_GPIOS)
-
-#endif
diff --git a/arch/arm/mach-zynq/include/mach/timex.h b/arch/arm/mach-zynq/include/mach/timex.h
deleted file mode 100644
index 6c0245e..0000000
--- a/arch/arm/mach-zynq/include/mach/timex.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/timex.h
- *
- *  Copyright (C) 2011 Xilinx
- *
- * 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_TIMEX_H__
-#define __MACH_TIMEX_H__
-
-/* the following is needed for the system to build but will be removed
-   in the future, the value is not important but won't hurt
-*/
-#define CLOCK_TICK_RATE	(100 * HZ)
-
-#endif
diff --git a/arch/arm/mach-zynq/include/mach/uart.h b/arch/arm/mach-zynq/include/mach/uart.h
deleted file mode 100644
index 5c47c97..0000000
--- a/arch/arm/mach-zynq/include/mach/uart.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/uart.h
- *
- *  Copyright (C) 2011 Xilinx
- *
- * 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_UART_H__
-#define __MACH_UART_H__
-
-#define UART_CR_OFFSET		0x00  /* Control Register [8:0] */
-#define UART_SR_OFFSET		0x2C  /* Channel Status [11:0] */
-#define UART_FIFO_OFFSET	0x30  /* FIFO [15:0] or [7:0] */
-
-#define UART_SR_TXFULL		0x00000010	/* TX FIFO full */
-#define UART_SR_TXEMPTY		0x00000008	/* TX FIFO empty */
-
-#endif
diff --git a/arch/arm/mach-zynq/include/mach/uncompress.h b/arch/arm/mach-zynq/include/mach/uncompress.h
deleted file mode 100644
index af4e844..0000000
--- a/arch/arm/mach-zynq/include/mach/uncompress.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/uncompress.h
- *
- *  Copyright (C) 2011 Xilinx
- *
- * 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_UNCOMPRESS_H__
-#define __MACH_UNCOMPRESS_H__
-
-#include <linux/io.h>
-#include <asm/processor.h>
-#include <mach/zynq_soc.h>
-#include <mach/uart.h>
-
-void arch_decomp_setup(void)
-{
-}
-
-static inline void flush(void)
-{
-	/*
-	 * Wait while the FIFO is not empty
-	 */
-	while (!(__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
-		UART_SR_TXEMPTY))
-		cpu_relax();
-}
-
-#define arch_decomp_wdog()
-
-static void putc(char ch)
-{
-	/*
-	 * Wait for room in the FIFO, then write the char into the FIFO
-	 */
-	while (__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
-		UART_SR_TXFULL)
-		cpu_relax();
-
-	__raw_writel(ch, IOMEM(LL_UART_PADDR + UART_FIFO_OFFSET));
-}
-
-#endif
diff --git a/arch/arm/mach-zynq/include/mach/zynq_soc.h b/arch/arm/mach-zynq/include/mach/zynq_soc.h
deleted file mode 100644
index d0d3f8f..0000000
--- a/arch/arm/mach-zynq/include/mach/zynq_soc.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/zynq_soc.h
- *
- *  Copyright (C) 2011 Xilinx
- *
- * 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_XILINX_SOC_H__
-#define __MACH_XILINX_SOC_H__
-
-#define PERIPHERAL_CLOCK_RATE		2500000
-
-/* For now, all mappings are flat (physical = virtual)
- */
-#define UART0_PHYS			0xE0000000
-#define UART0_VIRT			UART0_PHYS
-
-#define TTC0_PHYS			0xF8001000
-#define TTC0_VIRT			TTC0_PHYS
-
-#define PL310_L2CC_PHYS			0xF8F02000
-#define PL310_L2CC_VIRT			PL310_L2CC_PHYS
-
-#define SCU_PERIPH_PHYS			0xF8F00000
-#define SCU_PERIPH_VIRT			SCU_PERIPH_PHYS
-
-/* The following are intended for the devices that are mapped early */
-
-#define TTC0_BASE			IOMEM(TTC0_VIRT)
-#define SCU_PERIPH_BASE			IOMEM(SCU_PERIPH_VIRT)
-#define SCU_GIC_CPU_BASE		(SCU_PERIPH_BASE + 0x100)
-#define SCU_GIC_DIST_BASE		(SCU_PERIPH_BASE + 0x1000)
-#define PL310_L2CC_BASE			IOMEM(PL310_L2CC_VIRT)
-
-/*
- * Mandatory for CONFIG_LL_DEBUG, UART is mapped virtual = physical
- */
-#define LL_UART_PADDR	UART0_PHYS
-#define LL_UART_VADDR	UART0_VIRT
-
-#endif
diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
index c2c96cc..de3df28 100644
--- a/arch/arm/mach-zynq/timer.c
+++ b/arch/arm/mach-zynq/timer.c
@@ -23,32 +23,14 @@
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
 
-#include <asm/mach/time.h>
-#include <mach/zynq_soc.h>
 #include "common.h"
 
-#define IRQ_TIMERCOUNTER0	42
-
-/*
- * This driver configures the 2 16-bit count-up timers as follows:
- *
- * T1: Timer 1, clocksource for generic timekeeping
- * T2: Timer 2, clockevent source for hrtimers
- * T3: Timer 3, <unused>
- *
- * The input frequency to the timer module for emulation is 2.5MHz which is
- * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32,
- * the timers are clocked at 78.125KHz (12.8 us resolution).
- *
- * The input frequency to the timer module in silicon will be 200MHz. With the
- * pre-scaler of 32, the timers are clocked at 6.25MHz (160ns resolution).
- */
-#define XTTCPSS_CLOCKSOURCE	0	/* Timer 1 as a generic timekeeping */
-#define XTTCPSS_CLOCKEVENT	1	/* Timer 2 as a clock event */
-
-#define XTTCPSS_TIMER_BASE		TTC0_BASE
-#define XTTCPCC_EVENT_TIMER_IRQ		(IRQ_TIMERCOUNTER0 + 1)
 /*
  * Timer Register Offset Definitions of Timer 1, Increment base address by 4
  * and use same offsets for Timer 2
@@ -65,9 +47,14 @@
 
 #define XTTCPSS_CNT_CNTRL_DISABLE_MASK	0x1
 
-/* Setup the timers to use pre-scaling */
-
-#define TIMER_RATE (PERIPHERAL_CLOCK_RATE / 32)
+/* Setup the timers to use pre-scaling, using a fixed value for now that will
+ * work across most input frequency, but it may need to be more dynamic
+ */
+#define PRESCALE_EXPONENT	11	/* 2 ^ PRESCALE_EXPONENT = PRESCALE */
+#define PRESCALE		2048	/* The exponent must match this */
+#define CLK_CNTRL_PRESCALE	((PRESCALE_EXPONENT - 1) << 1)
+#define CLK_CNTRL_PRESCALE_EN	1
+#define CNT_CNTRL_RESET		(1<<4)
 
 /**
  * struct xttcpss_timer - This definition defines local timer structure
@@ -75,11 +62,25 @@
  * @base_addr:	Base address of timer
  **/
 struct xttcpss_timer {
-	void __iomem *base_addr;
+	void __iomem	*base_addr;
 };
 
-static struct xttcpss_timer timers[2];
-static struct clock_event_device xttcpss_clockevent;
+struct xttcpss_timer_clocksource {
+	struct xttcpss_timer	xttc;
+	struct clocksource	cs;
+};
+
+#define to_xttcpss_timer_clksrc(x) \
+		container_of(x, struct xttcpss_timer_clocksource, cs)
+
+struct xttcpss_timer_clockevent {
+	struct xttcpss_timer		xttc;
+	struct clock_event_device	ce;
+	struct clk			*clk;
+};
+
+#define to_xttcpss_timer_clkevent(x) \
+		container_of(x, struct xttcpss_timer_clockevent, ce)
 
 /**
  * xttcpss_set_interval - Set the timer interval value
@@ -101,7 +102,7 @@ static void xttcpss_set_interval(struct xttcpss_timer *timer,
 
 	/* Reset the counter (0x10) so that it starts from 0, one-shot
 	   mode makes this needed for timing to be right. */
-	ctrl_reg |= 0x10;
+	ctrl_reg |= CNT_CNTRL_RESET;
 	ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
 	__raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
 }
@@ -116,90 +117,31 @@ static void xttcpss_set_interval(struct xttcpss_timer *timer,
  **/
 static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id)
 {
-	struct clock_event_device *evt = &xttcpss_clockevent;
-	struct xttcpss_timer *timer = dev_id;
+	struct xttcpss_timer_clockevent *xttce = dev_id;
+	struct xttcpss_timer *timer = &xttce->xttc;
 
 	/* Acknowledge the interrupt and call event handler */
 	__raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET),
 			timer->base_addr + XTTCPSS_ISR_OFFSET);
 
-	evt->event_handler(evt);
+	xttce->ce.event_handler(&xttce->ce);
 
 	return IRQ_HANDLED;
 }
 
-static struct irqaction event_timer_irq = {
-	.name	= "xttcpss clockevent",
-	.flags	= IRQF_DISABLED | IRQF_TIMER,
-	.handler = xttcpss_clock_event_interrupt,
-};
-
 /**
- * xttcpss_timer_hardware_init - Initialize the timer hardware
- *
- * Initialize the hardware to start the clock source, get the clock
- * event timer ready to use, and hook up the interrupt.
- **/
-static void __init xttcpss_timer_hardware_init(void)
-{
-	/* Setup the clock source counter to be an incrementing counter
-	 * with no interrupt and it rolls over at 0xFFFF. Pre-scale
-	   it by 32 also. Let it start running now.
-	 */
-	timers[XTTCPSS_CLOCKSOURCE].base_addr = XTTCPSS_TIMER_BASE;
-
-	__raw_writel(0x0, timers[XTTCPSS_CLOCKSOURCE].base_addr +
-				XTTCPSS_IER_OFFSET);
-	__raw_writel(0x9, timers[XTTCPSS_CLOCKSOURCE].base_addr +
-				XTTCPSS_CLK_CNTRL_OFFSET);
-	__raw_writel(0x10, timers[XTTCPSS_CLOCKSOURCE].base_addr +
-				XTTCPSS_CNT_CNTRL_OFFSET);
-
-	/* Setup the clock event timer to be an interval timer which
-	 * is prescaled by 32 using the interval interrupt. Leave it
-	 * disabled for now.
-	 */
-
-	timers[XTTCPSS_CLOCKEVENT].base_addr = XTTCPSS_TIMER_BASE + 4;
-
-	__raw_writel(0x23, timers[XTTCPSS_CLOCKEVENT].base_addr +
-			XTTCPSS_CNT_CNTRL_OFFSET);
-	__raw_writel(0x9, timers[XTTCPSS_CLOCKEVENT].base_addr +
-			XTTCPSS_CLK_CNTRL_OFFSET);
-	__raw_writel(0x1, timers[XTTCPSS_CLOCKEVENT].base_addr +
-			XTTCPSS_IER_OFFSET);
-
-	/* Setup IRQ the clock event timer */
-	event_timer_irq.dev_id = &timers[XTTCPSS_CLOCKEVENT];
-	setup_irq(XTTCPCC_EVENT_TIMER_IRQ, &event_timer_irq);
-}
-
-/**
- * __raw_readl_cycles - Reads the timer counter register
+ * __xttc_clocksource_read - Reads the timer counter register
  *
  * returns: Current timer counter register value
  **/
-static cycle_t __raw_readl_cycles(struct clocksource *cs)
+static cycle_t __xttc_clocksource_read(struct clocksource *cs)
 {
-	struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
+	struct xttcpss_timer *timer = &to_xttcpss_timer_clksrc(cs)->xttc;
 
 	return (cycle_t)__raw_readl(timer->base_addr +
 				XTTCPSS_COUNT_VAL_OFFSET);
 }
 
-
-/*
- * Instantiate and initialize the clock source structure
- */
-static struct clocksource clocksource_xttcpss = {
-	.name		= "xttcpss_timer1",
-	.rating		= 200,			/* Reasonable clock source */
-	.read		= __raw_readl_cycles,
-	.mask		= CLOCKSOURCE_MASK(16),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-
 /**
  * xttcpss_set_next_event - Sets the time interval for next event
  *
@@ -211,7 +153,8 @@ static struct clocksource clocksource_xttcpss = {
 static int xttcpss_set_next_event(unsigned long cycles,
 					struct clock_event_device *evt)
 {
-	struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+	struct xttcpss_timer_clockevent *xttce = to_xttcpss_timer_clkevent(evt);
+	struct xttcpss_timer *timer = &xttce->xttc;
 
 	xttcpss_set_interval(timer, cycles);
 	return 0;
@@ -226,12 +169,15 @@ static int xttcpss_set_next_event(unsigned long cycles,
 static void xttcpss_set_mode(enum clock_event_mode mode,
 					struct clock_event_device *evt)
 {
-	struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+	struct xttcpss_timer_clockevent *xttce = to_xttcpss_timer_clkevent(evt);
+	struct xttcpss_timer *timer = &xttce->xttc;
 	u32 ctrl_reg;
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
-		xttcpss_set_interval(timer, TIMER_RATE / HZ);
+		xttcpss_set_interval(timer,
+				     DIV_ROUND_CLOSEST(clk_get_rate(xttce->clk),
+						       PRESCALE * HZ));
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
 	case CLOCK_EVT_MODE_UNUSED:
@@ -252,15 +198,106 @@ static void xttcpss_set_mode(enum clock_event_mode mode,
 	}
 }
 
-/*
- * Instantiate and initialize the clock event structure
- */
-static struct clock_event_device xttcpss_clockevent = {
-	.name		= "xttcpss_timer2",
-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.set_next_event	= xttcpss_set_next_event,
-	.set_mode	= xttcpss_set_mode,
-	.rating		= 200,
+static void __init zynq_ttc_setup_clocksource(struct device_node *np,
+					     void __iomem *base)
+{
+	struct xttcpss_timer_clocksource *ttccs;
+	struct clk *clk;
+	int err;
+	u32 reg;
+
+	ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL);
+	if (WARN_ON(!ttccs))
+		return;
+
+	err = of_property_read_u32(np, "reg", &reg);
+	if (WARN_ON(err))
+		return;
+
+	clk = of_clk_get_by_name(np, "cpu_1x");
+	if (WARN_ON(IS_ERR(clk)))
+		return;
+
+	err = clk_prepare_enable(clk);
+	if (WARN_ON(err))
+		return;
+
+	ttccs->xttc.base_addr = base + reg * 4;
+
+	ttccs->cs.name = np->name;
+	ttccs->cs.rating = 200;
+	ttccs->cs.read = __xttc_clocksource_read;
+	ttccs->cs.mask = CLOCKSOURCE_MASK(16);
+	ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+	__raw_writel(0x0,  ttccs->xttc.base_addr + XTTCPSS_IER_OFFSET);
+	__raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
+		     ttccs->xttc.base_addr + XTTCPSS_CLK_CNTRL_OFFSET);
+	__raw_writel(CNT_CNTRL_RESET,
+		     ttccs->xttc.base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+
+	err = clocksource_register_hz(&ttccs->cs, clk_get_rate(clk) / PRESCALE);
+	if (WARN_ON(err))
+		return;
+}
+
+static void __init zynq_ttc_setup_clockevent(struct device_node *np,
+					    void __iomem *base)
+{
+	struct xttcpss_timer_clockevent *ttcce;
+	int err, irq;
+	u32 reg;
+
+	ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL);
+	if (WARN_ON(!ttcce))
+		return;
+
+	err = of_property_read_u32(np, "reg", &reg);
+	if (WARN_ON(err))
+		return;
+
+	ttcce->xttc.base_addr = base + reg * 4;
+
+	ttcce->clk = of_clk_get_by_name(np, "cpu_1x");
+	if (WARN_ON(IS_ERR(ttcce->clk)))
+		return;
+
+	err = clk_prepare_enable(ttcce->clk);
+	if (WARN_ON(err))
+		return;
+
+	irq = irq_of_parse_and_map(np, 0);
+	if (WARN_ON(!irq))
+		return;
+
+	ttcce->ce.name = np->name;
+	ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	ttcce->ce.set_next_event = xttcpss_set_next_event;
+	ttcce->ce.set_mode = xttcpss_set_mode;
+	ttcce->ce.rating = 200;
+	ttcce->ce.irq = irq;
+
+	__raw_writel(0x23, ttcce->xttc.base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+	__raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
+		     ttcce->xttc.base_addr + XTTCPSS_CLK_CNTRL_OFFSET);
+	__raw_writel(0x1,  ttcce->xttc.base_addr + XTTCPSS_IER_OFFSET);
+
+	err = request_irq(irq, xttcpss_clock_event_interrupt, IRQF_TIMER,
+			  np->name, ttcce);
+	if (WARN_ON(err))
+		return;
+
+	clockevents_config_and_register(&ttcce->ce,
+					clk_get_rate(ttcce->clk) / PRESCALE,
+					1, 0xfffe);
+}
+
+static const __initconst struct of_device_id zynq_ttc_match[] = {
+	{ .compatible = "xlnx,ttc-counter-clocksource",
+		.data = zynq_ttc_setup_clocksource, },
+	{ .compatible = "xlnx,ttc-counter-clockevent",
+		.data = zynq_ttc_setup_clockevent, },
+	{}
 };
 
 /**
@@ -269,30 +306,27 @@ static struct clock_event_device xttcpss_clockevent = {
  * Initializes the timer hardware and register the clock source and clock event
  * timers with Linux kernal timer framework
  **/
-static void __init xttcpss_timer_init(void)
+void __init xttcpss_timer_init(void)
 {
-	xttcpss_timer_hardware_init();
-	clocksource_register_hz(&clocksource_xttcpss, TIMER_RATE);
-
-	/* Calculate the parameters to allow the clockevent to operate using
-	   integer math
-	*/
-	clockevents_calc_mult_shift(&xttcpss_clockevent, TIMER_RATE, 4);
-
-	xttcpss_clockevent.max_delta_ns =
-		clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
-	xttcpss_clockevent.min_delta_ns =
-		clockevent_delta2ns(1, &xttcpss_clockevent);
-
-	/* Indicate that clock event is on 1st CPU as SMP boot needs it */
-
-	xttcpss_clockevent.cpumask = cpumask_of(0);
-	clockevents_register_device(&xttcpss_clockevent);
+	struct device_node *np;
+
+	for_each_compatible_node(np, NULL, "xlnx,ttc") {
+		struct device_node *np_chld;
+		void __iomem *base;
+
+		base = of_iomap(np, 0);
+		if (WARN_ON(!base))
+			return;
+
+		for_each_available_child_of_node(np, np_chld) {
+			int (*cb)(struct device_node *np, void __iomem *base);
+			const struct of_device_id *match;
+
+			match = of_match_node(zynq_ttc_match, np_chld);
+			if (match) {
+				cb = match->data;
+				cb(np_chld, base);
+			}
+		}
+	}
 }
-
-/*
- * Instantiate and initialize the system timer structure
- */
-struct sys_timer xttcpss_sys_timer = {
-	.init		= xttcpss_timer_init,
-};
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index b820eda..feeb3ea 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -964,12 +964,14 @@ static int __init alignment_init(void)
 		return -ENOMEM;
 #endif
 
+#ifdef CONFIG_CPU_CP15
 	if (cpu_is_v6_unaligned()) {
 		cr_alignment &= ~CR_A;
 		cr_no_alignment &= ~CR_A;
 		set_cr(cr_alignment);
 		ai_usermode = safe_usermode(ai_usermode, false);
 	}
+#endif
 
 	hook_fault_code(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN,
 			"alignment exception");
diff --git a/arch/arm/mm/cache-aurora-l2.h b/arch/arm/mm/cache-aurora-l2.h
new file mode 100644
index 0000000..c861247
--- /dev/null
+++ b/arch/arm/mm/cache-aurora-l2.h
@@ -0,0 +1,55 @@
+/*
+ * AURORA shared L2 cache controller support
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Yehuda Yitschak <yehuday@marvell.com>
+ * Gregory CLEMENT <gregory.clement@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.
+ */
+
+#ifndef __ASM_ARM_HARDWARE_AURORA_L2_H
+#define __ASM_ARM_HARDWARE_AURORA_L2_H
+
+#define AURORA_SYNC_REG		    0x700
+#define AURORA_RANGE_BASE_ADDR_REG  0x720
+#define AURORA_FLUSH_PHY_ADDR_REG   0x7f0
+#define AURORA_INVAL_RANGE_REG	    0x774
+#define AURORA_CLEAN_RANGE_REG	    0x7b4
+#define AURORA_FLUSH_RANGE_REG	    0x7f4
+
+#define AURORA_ACR_REPLACEMENT_OFFSET	    27
+#define AURORA_ACR_REPLACEMENT_MASK	     \
+	(0x3 << AURORA_ACR_REPLACEMENT_OFFSET)
+#define AURORA_ACR_REPLACEMENT_TYPE_WAYRR    \
+	(0 << AURORA_ACR_REPLACEMENT_OFFSET)
+#define AURORA_ACR_REPLACEMENT_TYPE_LFSR     \
+	(1 << AURORA_ACR_REPLACEMENT_OFFSET)
+#define AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU \
+	(3 << AURORA_ACR_REPLACEMENT_OFFSET)
+
+#define AURORA_ACR_FORCE_WRITE_POLICY_OFFSET	0
+#define AURORA_ACR_FORCE_WRITE_POLICY_MASK	\
+	(0x3 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET)
+#define AURORA_ACR_FORCE_WRITE_POLICY_DIS	\
+	(0 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET)
+#define AURORA_ACR_FORCE_WRITE_BACK_POLICY	\
+	(1 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET)
+#define AURORA_ACR_FORCE_WRITE_THRO_POLICY	\
+	(2 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET)
+
+#define MAX_RANGE_SIZE		1024
+
+#define AURORA_WAY_SIZE_SHIFT	2
+
+#define AURORA_CTRL_FW		0x100
+
+/* chose a number outside L2X0_CACHE_ID_PART_MASK to be sure to make
+ * the distinction between a number coming from hardware and a number
+ * coming from the device tree */
+#define AURORA_CACHE_ID	       0x100
+
+#endif /* __ASM_ARM_HARDWARE_AURORA_L2_H */
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 8a97e64..6911b8b 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -25,6 +25,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/hardware/cache-l2x0.h>
+#include "cache-aurora-l2.h"
 
 #define CACHE_LINE_SIZE		32
 
@@ -34,14 +35,20 @@ static u32 l2x0_way_mask;	/* Bitmask of active ways */
 static u32 l2x0_size;
 static unsigned long sync_reg_offset = L2X0_CACHE_SYNC;
 
+/* Aurora don't have the cache ID register available, so we have to
+ * pass it though the device tree */
+static u32  cache_id_part_number_from_dt;
+
 struct l2x0_regs l2x0_saved_regs;
 
 struct l2x0_of_data {
 	void (*setup)(const struct device_node *, u32 *, u32 *);
 	void (*save)(void);
-	void (*resume)(void);
+	struct outer_cache_fns outer_cache;
 };
 
+static bool of_init = false;
+
 static inline void cache_wait_way(void __iomem *reg, unsigned long mask)
 {
 	/* wait for cache operation by line or way to complete */
@@ -168,7 +175,7 @@ static void l2x0_inv_all(void)
 	/* invalidate all ways */
 	raw_spin_lock_irqsave(&l2x0_lock, flags);
 	/* Invalidating when L2 is enabled is a nono */
-	BUG_ON(readl(l2x0_base + L2X0_CTRL) & 1);
+	BUG_ON(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN);
 	writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
 	cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
 	cache_sync();
@@ -292,11 +299,18 @@ static void l2x0_unlock(u32 cache_id)
 	int lockregs;
 	int i;
 
-	if (cache_id == L2X0_CACHE_ID_PART_L310)
+	switch (cache_id) {
+	case L2X0_CACHE_ID_PART_L310:
 		lockregs = 8;
-	else
+		break;
+	case AURORA_CACHE_ID:
+		lockregs = 4;
+		break;
+	default:
 		/* L210 and unknown types */
 		lockregs = 1;
+		break;
+	}
 
 	for (i = 0; i < lockregs; i++) {
 		writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
@@ -312,18 +326,22 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
 	u32 cache_id;
 	u32 way_size = 0;
 	int ways;
+	int way_size_shift = L2X0_WAY_SIZE_SHIFT;
 	const char *type;
 
 	l2x0_base = base;
-
-	cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
+	if (cache_id_part_number_from_dt)
+		cache_id = cache_id_part_number_from_dt;
+	else
+		cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID)
+			& L2X0_CACHE_ID_PART_MASK;
 	aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
 
 	aux &= aux_mask;
 	aux |= aux_val;
 
 	/* Determine the number of ways */
-	switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
+	switch (cache_id) {
 	case L2X0_CACHE_ID_PART_L310:
 		if (aux & (1 << 16))
 			ways = 16;
@@ -340,6 +358,14 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
 		ways = (aux >> 13) & 0xf;
 		type = "L210";
 		break;
+
+	case AURORA_CACHE_ID:
+		sync_reg_offset = AURORA_SYNC_REG;
+		ways = (aux >> 13) & 0xf;
+		ways = 2 << ((ways + 1) >> 2);
+		way_size_shift = AURORA_WAY_SIZE_SHIFT;
+		type = "Aurora";
+		break;
 	default:
 		/* Assume unknown chips have 8 ways */
 		ways = 8;
@@ -353,7 +379,8 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
 	 * L2 cache Size =  Way size * Number of ways
 	 */
 	way_size = (aux & L2X0_AUX_CTRL_WAY_SIZE_MASK) >> 17;
-	way_size = 1 << (way_size + 3);
+	way_size = 1 << (way_size + way_size_shift);
+
 	l2x0_size = ways * way_size * SZ_1K;
 
 	/*
@@ -361,7 +388,7 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
 	 * If you are booting from non-secure mode
 	 * accessing the below registers will fault.
 	 */
-	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
 		/* Make sure that I&D is not locked down when starting */
 		l2x0_unlock(cache_id);
 
@@ -371,7 +398,7 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
 		l2x0_inv_all();
 
 		/* enable L2X0 */
-		writel_relaxed(1, l2x0_base + L2X0_CTRL);
+		writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL);
 	}
 
 	/* Re-read it in case some bits are reserved. */
@@ -380,13 +407,15 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
 	/* Save the value for resuming. */
 	l2x0_saved_regs.aux_ctrl = aux;
 
-	outer_cache.inv_range = l2x0_inv_range;
-	outer_cache.clean_range = l2x0_clean_range;
-	outer_cache.flush_range = l2x0_flush_range;
-	outer_cache.sync = l2x0_cache_sync;
-	outer_cache.flush_all = l2x0_flush_all;
-	outer_cache.inv_all = l2x0_inv_all;
-	outer_cache.disable = l2x0_disable;
+	if (!of_init) {
+		outer_cache.inv_range = l2x0_inv_range;
+		outer_cache.clean_range = l2x0_clean_range;
+		outer_cache.flush_range = l2x0_flush_range;
+		outer_cache.sync = l2x0_cache_sync;
+		outer_cache.flush_all = l2x0_flush_all;
+		outer_cache.inv_all = l2x0_inv_all;
+		outer_cache.disable = l2x0_disable;
+	}
 
 	printk(KERN_INFO "%s cache controller enabled\n", type);
 	printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n",
@@ -394,6 +423,100 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
 }
 
 #ifdef CONFIG_OF
+static int l2_wt_override;
+
+/*
+ * Note that the end addresses passed to Linux primitives are
+ * noninclusive, while the hardware cache range operations use
+ * inclusive start and end addresses.
+ */
+static unsigned long calc_range_end(unsigned long start, unsigned long end)
+{
+	/*
+	 * Limit the number of cache lines processed at once,
+	 * since cache range operations stall the CPU pipeline
+	 * until completion.
+	 */
+	if (end > start + MAX_RANGE_SIZE)
+		end = start + MAX_RANGE_SIZE;
+
+	/*
+	 * Cache range operations can't straddle a page boundary.
+	 */
+	if (end > PAGE_ALIGN(start+1))
+		end = PAGE_ALIGN(start+1);
+
+	return end;
+}
+
+/*
+ * Make sure 'start' and 'end' reference the same page, as L2 is PIPT
+ * and range operations only do a TLB lookup on the start address.
+ */
+static void aurora_pa_range(unsigned long start, unsigned long end,
+			unsigned long offset)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&l2x0_lock, flags);
+	writel(start, l2x0_base + AURORA_RANGE_BASE_ADDR_REG);
+	writel(end, l2x0_base + offset);
+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
+
+	cache_sync();
+}
+
+static void aurora_inv_range(unsigned long start, unsigned long end)
+{
+	/*
+	 * round start and end adresses up to cache line size
+	 */
+	start &= ~(CACHE_LINE_SIZE - 1);
+	end = ALIGN(end, CACHE_LINE_SIZE);
+
+	/*
+	 * Invalidate all full cache lines between 'start' and 'end'.
+	 */
+	while (start < end) {
+		unsigned long range_end = calc_range_end(start, end);
+		aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
+				AURORA_INVAL_RANGE_REG);
+		start = range_end;
+	}
+}
+
+static void aurora_clean_range(unsigned long start, unsigned long end)
+{
+	/*
+	 * If L2 is forced to WT, the L2 will always be clean and we
+	 * don't need to do anything here.
+	 */
+	if (!l2_wt_override) {
+		start &= ~(CACHE_LINE_SIZE - 1);
+		end = ALIGN(end, CACHE_LINE_SIZE);
+		while (start != end) {
+			unsigned long range_end = calc_range_end(start, end);
+			aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
+					AURORA_CLEAN_RANGE_REG);
+			start = range_end;
+		}
+	}
+}
+
+static void aurora_flush_range(unsigned long start, unsigned long end)
+{
+	if (!l2_wt_override) {
+		start &= ~(CACHE_LINE_SIZE - 1);
+		end = ALIGN(end, CACHE_LINE_SIZE);
+		while (start != end) {
+			unsigned long range_end = calc_range_end(start, end);
+			aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
+					AURORA_FLUSH_RANGE_REG);
+			start = range_end;
+		}
+	}
+}
+
 static void __init l2x0_of_setup(const struct device_node *np,
 				 u32 *aux_val, u32 *aux_mask)
 {
@@ -491,9 +614,15 @@ static void __init pl310_save(void)
 	}
 }
 
+static void aurora_save(void)
+{
+	l2x0_saved_regs.ctrl = readl_relaxed(l2x0_base + L2X0_CTRL);
+	l2x0_saved_regs.aux_ctrl = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
+}
+
 static void l2x0_resume(void)
 {
-	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
 		/* restore aux ctrl and enable l2 */
 		l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID));
 
@@ -502,7 +631,7 @@ static void l2x0_resume(void)
 
 		l2x0_inv_all();
 
-		writel_relaxed(1, l2x0_base + L2X0_CTRL);
+		writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL);
 	}
 }
 
@@ -510,7 +639,7 @@ static void pl310_resume(void)
 {
 	u32 l2x0_revision;
 
-	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
 		/* restore pl310 setup */
 		writel_relaxed(l2x0_saved_regs.tag_latency,
 			l2x0_base + L2X0_TAG_LATENCY_CTRL);
@@ -536,22 +665,108 @@ static void pl310_resume(void)
 	l2x0_resume();
 }
 
+static void aurora_resume(void)
+{
+	if (!(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
+		writel(l2x0_saved_regs.aux_ctrl, l2x0_base + L2X0_AUX_CTRL);
+		writel(l2x0_saved_regs.ctrl, l2x0_base + L2X0_CTRL);
+	}
+}
+
+static void __init aurora_broadcast_l2_commands(void)
+{
+	__u32 u;
+	/* Enable Broadcasting of cache commands to L2*/
+	__asm__ __volatile__("mrc p15, 1, %0, c15, c2, 0" : "=r"(u));
+	u |= AURORA_CTRL_FW;		/* Set the FW bit */
+	__asm__ __volatile__("mcr p15, 1, %0, c15, c2, 0\n" : : "r"(u));
+	isb();
+}
+
+static void __init aurora_of_setup(const struct device_node *np,
+				u32 *aux_val, u32 *aux_mask)
+{
+	u32 val = AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU;
+	u32 mask =  AURORA_ACR_REPLACEMENT_MASK;
+
+	of_property_read_u32(np, "cache-id-part",
+			&cache_id_part_number_from_dt);
+
+	/* Determine and save the write policy */
+	l2_wt_override = of_property_read_bool(np, "wt-override");
+
+	if (l2_wt_override) {
+		val |= AURORA_ACR_FORCE_WRITE_THRO_POLICY;
+		mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK;
+	}
+
+	*aux_val &= ~mask;
+	*aux_val |= val;
+	*aux_mask &= ~mask;
+}
+
 static const struct l2x0_of_data pl310_data = {
-	pl310_of_setup,
-	pl310_save,
-	pl310_resume,
+	.setup = pl310_of_setup,
+	.save  = pl310_save,
+	.outer_cache = {
+		.resume      = pl310_resume,
+		.inv_range   = l2x0_inv_range,
+		.clean_range = l2x0_clean_range,
+		.flush_range = l2x0_flush_range,
+		.sync        = l2x0_cache_sync,
+		.flush_all   = l2x0_flush_all,
+		.inv_all     = l2x0_inv_all,
+		.disable     = l2x0_disable,
+		.set_debug   = pl310_set_debug,
+	},
 };
 
 static const struct l2x0_of_data l2x0_data = {
-	l2x0_of_setup,
-	NULL,
-	l2x0_resume,
+	.setup = l2x0_of_setup,
+	.save  = NULL,
+	.outer_cache = {
+		.resume      = l2x0_resume,
+		.inv_range   = l2x0_inv_range,
+		.clean_range = l2x0_clean_range,
+		.flush_range = l2x0_flush_range,
+		.sync        = l2x0_cache_sync,
+		.flush_all   = l2x0_flush_all,
+		.inv_all     = l2x0_inv_all,
+		.disable     = l2x0_disable,
+	},
+};
+
+static const struct l2x0_of_data aurora_with_outer_data = {
+	.setup = aurora_of_setup,
+	.save  = aurora_save,
+	.outer_cache = {
+		.resume      = aurora_resume,
+		.inv_range   = aurora_inv_range,
+		.clean_range = aurora_clean_range,
+		.flush_range = aurora_flush_range,
+		.sync        = l2x0_cache_sync,
+		.flush_all   = l2x0_flush_all,
+		.inv_all     = l2x0_inv_all,
+		.disable     = l2x0_disable,
+	},
+};
+
+static const struct l2x0_of_data aurora_no_outer_data = {
+	.setup = aurora_of_setup,
+	.save  = aurora_save,
+	.outer_cache = {
+		.resume      = aurora_resume,
+	},
 };
 
 static const struct of_device_id l2x0_ids[] __initconst = {
 	{ .compatible = "arm,pl310-cache", .data = (void *)&pl310_data },
 	{ .compatible = "arm,l220-cache", .data = (void *)&l2x0_data },
 	{ .compatible = "arm,l210-cache", .data = (void *)&l2x0_data },
+	{ .compatible = "marvell,aurora-system-cache",
+	  .data = (void *)&aurora_no_outer_data},
+	{ .compatible = "marvell,aurora-outer-cache",
+	  .data = (void *)&aurora_with_outer_data},
 	{}
 };
 
@@ -577,17 +792,24 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
 	data = of_match_node(l2x0_ids, np)->data;
 
 	/* L2 configuration can only be changed if the cache is disabled */
-	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
 		if (data->setup)
 			data->setup(np, &aux_val, &aux_mask);
+
+		/* For aurora cache in no outer mode select the
+		 * correct mode using the coprocessor*/
+		if (data == &aurora_no_outer_data)
+			aurora_broadcast_l2_commands();
 	}
 
 	if (data->save)
 		data->save();
 
+	of_init = true;
 	l2x0_init(l2x0_base, aux_val, aux_mask);
 
-	outer_cache.resume = data->resume;
+	memcpy(&outer_cache, &data->outer_cache, sizeof(outer_cache));
+
 	return 0;
 }
 #endif
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index 4e07eec..7a27d73 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -2,6 +2,9 @@
  *  linux/arch/arm/mm/context.c
  *
  *  Copyright (C) 2002-2003 Deep Blue Solutions Ltd, all rights reserved.
+ *  Copyright (C) 2012 ARM Limited
+ *
+ *  Author: Will Deacon <will.deacon@arm.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
@@ -14,14 +17,40 @@
 #include <linux/percpu.h>
 
 #include <asm/mmu_context.h>
+#include <asm/smp_plat.h>
 #include <asm/thread_notify.h>
 #include <asm/tlbflush.h>
 
+/*
+ * On ARMv6, we have the following structure in the Context ID:
+ *
+ * 31                         7          0
+ * +-------------------------+-----------+
+ * |      process ID         |   ASID    |
+ * +-------------------------+-----------+
+ * |              context ID             |
+ * +-------------------------------------+
+ *
+ * The ASID is used to tag entries in the CPU caches and TLBs.
+ * The context ID is used by debuggers and trace logic, and
+ * should be unique within all running processes.
+ */
+#define ASID_FIRST_VERSION	(1ULL << ASID_BITS)
+#define NUM_USER_ASIDS		(ASID_FIRST_VERSION - 1)
+
+#define ASID_TO_IDX(asid)	((asid & ~ASID_MASK) - 1)
+#define IDX_TO_ASID(idx)	((idx + 1) & ~ASID_MASK)
+
 static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
-unsigned int cpu_last_asid = ASID_FIRST_VERSION;
+static atomic64_t asid_generation = ATOMIC64_INIT(ASID_FIRST_VERSION);
+static DECLARE_BITMAP(asid_map, NUM_USER_ASIDS);
+
+static DEFINE_PER_CPU(atomic64_t, active_asids);
+static DEFINE_PER_CPU(u64, reserved_asids);
+static cpumask_t tlb_flush_pending;
 
 #ifdef CONFIG_ARM_LPAE
-void cpu_set_reserved_ttbr0(void)
+static void cpu_set_reserved_ttbr0(void)
 {
 	unsigned long ttbl = __pa(swapper_pg_dir);
 	unsigned long ttbh = 0;
@@ -37,7 +66,7 @@ void cpu_set_reserved_ttbr0(void)
 	isb();
 }
 #else
-void cpu_set_reserved_ttbr0(void)
+static void cpu_set_reserved_ttbr0(void)
 {
 	u32 ttb;
 	/* Copy TTBR1 into TTBR0 */
@@ -84,124 +113,104 @@ static int __init contextidr_notifier_init(void)
 arch_initcall(contextidr_notifier_init);
 #endif
 
-/*
- * We fork()ed a process, and we need a new context for the child
- * to run in.
- */
-void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+static void flush_context(unsigned int cpu)
 {
-	mm->context.id = 0;
-	raw_spin_lock_init(&mm->context.id_lock);
-}
+	int i;
+	u64 asid;
+
+	/* Update the list of reserved ASIDs and the ASID bitmap. */
+	bitmap_clear(asid_map, 0, NUM_USER_ASIDS);
+	for_each_possible_cpu(i) {
+		if (i == cpu) {
+			asid = 0;
+		} else {
+			asid = atomic64_xchg(&per_cpu(active_asids, i), 0);
+			__set_bit(ASID_TO_IDX(asid), asid_map);
+		}
+		per_cpu(reserved_asids, i) = asid;
+	}
 
-static void flush_context(void)
-{
-	cpu_set_reserved_ttbr0();
-	local_flush_tlb_all();
-	if (icache_is_vivt_asid_tagged()) {
+	/* Queue a TLB invalidate and flush the I-cache if necessary. */
+	if (!tlb_ops_need_broadcast())
+		cpumask_set_cpu(cpu, &tlb_flush_pending);
+	else
+		cpumask_setall(&tlb_flush_pending);
+
+	if (icache_is_vivt_asid_tagged())
 		__flush_icache_all();
-		dsb();
-	}
 }
 
-#ifdef CONFIG_SMP
+static int is_reserved_asid(u64 asid)
+{
+	int cpu;
+	for_each_possible_cpu(cpu)
+		if (per_cpu(reserved_asids, cpu) == asid)
+			return 1;
+	return 0;
+}
 
-static void set_mm_context(struct mm_struct *mm, unsigned int asid)
+static void new_context(struct mm_struct *mm, unsigned int cpu)
 {
-	unsigned long flags;
+	u64 asid = mm->context.id;
+	u64 generation = atomic64_read(&asid_generation);
 
-	/*
-	 * Locking needed for multi-threaded applications where the
-	 * same mm->context.id could be set from different CPUs during
-	 * the broadcast. This function is also called via IPI so the
-	 * mm->context.id_lock has to be IRQ-safe.
-	 */
-	raw_spin_lock_irqsave(&mm->context.id_lock, flags);
-	if (likely((mm->context.id ^ cpu_last_asid) >> ASID_BITS)) {
+	if (asid != 0 && is_reserved_asid(asid)) {
 		/*
-		 * Old version of ASID found. Set the new one and
-		 * reset mm_cpumask(mm).
+		 * Our current ASID was active during a rollover, we can
+		 * continue to use it and this was just a false alarm.
 		 */
-		mm->context.id = asid;
+		asid = generation | (asid & ~ASID_MASK);
+	} else {
+		/*
+		 * Allocate a free ASID. If we can't find one, take a
+		 * note of the currently active ASIDs and mark the TLBs
+		 * as requiring flushes.
+		 */
+		asid = find_first_zero_bit(asid_map, NUM_USER_ASIDS);
+		if (asid == NUM_USER_ASIDS) {
+			generation = atomic64_add_return(ASID_FIRST_VERSION,
+							 &asid_generation);
+			flush_context(cpu);
+			asid = find_first_zero_bit(asid_map, NUM_USER_ASIDS);
+		}
+		__set_bit(asid, asid_map);
+		asid = generation | IDX_TO_ASID(asid);
 		cpumask_clear(mm_cpumask(mm));
 	}
-	raw_spin_unlock_irqrestore(&mm->context.id_lock, flags);
 
-	/*
-	 * Set the mm_cpumask(mm) bit for the current CPU.
-	 */
-	cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
+	mm->context.id = asid;
 }
 
-/*
- * Reset the ASID on the current CPU. This function call is broadcast
- * from the CPU handling the ASID rollover and holding cpu_asid_lock.
- */
-static void reset_context(void *info)
+void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk)
 {
-	unsigned int asid;
+	unsigned long flags;
 	unsigned int cpu = smp_processor_id();
-	struct mm_struct *mm = current->active_mm;
 
-	smp_rmb();
-	asid = cpu_last_asid + cpu + 1;
+	if (unlikely(mm->context.kvm_seq != init_mm.context.kvm_seq))
+		__check_kvm_seq(mm);
 
-	flush_context();
-	set_mm_context(mm, asid);
-
-	/* set the new ASID */
-	cpu_switch_mm(mm->pgd, mm);
-}
+	/*
+	 * Required during context switch to avoid speculative page table
+	 * walking with the wrong TTBR.
+	 */
+	cpu_set_reserved_ttbr0();
 
-#else
+	if (!((mm->context.id ^ atomic64_read(&asid_generation)) >> ASID_BITS)
+	    && atomic64_xchg(&per_cpu(active_asids, cpu), mm->context.id))
+		goto switch_mm_fastpath;
 
-static inline void set_mm_context(struct mm_struct *mm, unsigned int asid)
-{
-	mm->context.id = asid;
-	cpumask_copy(mm_cpumask(mm), cpumask_of(smp_processor_id()));
-}
+	raw_spin_lock_irqsave(&cpu_asid_lock, flags);
+	/* Check that our ASID belongs to the current generation. */
+	if ((mm->context.id ^ atomic64_read(&asid_generation)) >> ASID_BITS)
+		new_context(mm, cpu);
 
-#endif
+	atomic64_set(&per_cpu(active_asids, cpu), mm->context.id);
+	cpumask_set_cpu(cpu, mm_cpumask(mm));
 
-void __new_context(struct mm_struct *mm)
-{
-	unsigned int asid;
+	if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending))
+		local_flush_tlb_all();
+	raw_spin_unlock_irqrestore(&cpu_asid_lock, flags);
 
-	raw_spin_lock(&cpu_asid_lock);
-#ifdef CONFIG_SMP
-	/*
-	 * Check the ASID again, in case the change was broadcast from
-	 * another CPU before we acquired the lock.
-	 */
-	if (unlikely(((mm->context.id ^ cpu_last_asid) >> ASID_BITS) == 0)) {
-		cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
-		raw_spin_unlock(&cpu_asid_lock);
-		return;
-	}
-#endif
-	/*
-	 * At this point, it is guaranteed that the current mm (with
-	 * an old ASID) isn't active on any other CPU since the ASIDs
-	 * are changed simultaneously via IPI.
-	 */
-	asid = ++cpu_last_asid;
-	if (asid == 0)
-		asid = cpu_last_asid = ASID_FIRST_VERSION;
-
-	/*
-	 * If we've used up all our ASIDs, we need
-	 * to start a new version and flush the TLB.
-	 */
-	if (unlikely((asid & ~ASID_MASK) == 0)) {
-		asid = cpu_last_asid + smp_processor_id() + 1;
-		flush_context();
-#ifdef CONFIG_SMP
-		smp_wmb();
-		smp_call_function(reset_context, NULL, 1);
-#endif
-		cpu_last_asid += NR_CPUS;
-	}
-
-	set_mm_context(mm, asid);
-	raw_spin_unlock(&cpu_asid_lock);
+switch_mm_fastpath:
+	cpu_switch_mm(mm->pgd, mm);
 }
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c
index ab88ed4..99db769 100644
--- a/arch/arm/mm/idmap.c
+++ b/arch/arm/mm/idmap.c
@@ -92,6 +92,9 @@ static int __init init_static_idmap(void)
 		(long long)idmap_start, (long long)idmap_end);
 	identity_mapping_add(idmap_pgd, idmap_start, idmap_end);
 
+	/* Flush L1 for the hardware to see this page table content */
+	flush_cache_louis();
+
 	return 0;
 }
 early_initcall(init_static_idmap);
@@ -103,12 +106,15 @@ early_initcall(init_static_idmap);
  */
 void setup_mm_for_reboot(void)
 {
-	/* Clean and invalidate L1. */
-	flush_cache_all();
-
 	/* Switch to the identity mapping. */
 	cpu_switch_mm(idmap_pgd, &init_mm);
 
-	/* Flush the TLB. */
+#ifdef CONFIG_CPU_HAS_ASID
+	/*
+	 * We don't have a clean ASID for the identity mapping, which
+	 * may clash with virtual addresses of the previous page tables
+	 * and therefore potentially in the TLB.
+	 */
 	local_flush_tlb_all();
+#endif
 }
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index ce8cb19..10062ce 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -11,18 +11,6 @@
 #include <linux/random.h>
 #include <asm/cachetype.h>
 
-static inline unsigned long COLOUR_ALIGN_DOWN(unsigned long addr,
-					      unsigned long pgoff)
-{
-	unsigned long base = addr & ~(SHMLBA-1);
-	unsigned long off = (pgoff << PAGE_SHIFT) & (SHMLBA-1);
-
-	if (base + off <= addr)
-		return base + off;
-
-	return base - off;
-}
-
 #define COLOUR_ALIGN(addr,pgoff)		\
 	((((addr)+SHMLBA-1)&~(SHMLBA-1)) +	\
 	 (((pgoff)<<PAGE_SHIFT) & (SHMLBA-1)))
@@ -69,9 +57,9 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
-	unsigned long start_addr;
 	int do_align = 0;
 	int aliasing = cache_is_vipt_aliasing();
+	struct vm_unmapped_area_info info;
 
 	/*
 	 * We only need to do colour alignment if either the I or D
@@ -104,46 +92,14 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 		    (!vma || addr + len <= vma->vm_start))
 			return addr;
 	}
-	if (len > mm->cached_hole_size) {
-	        start_addr = addr = mm->free_area_cache;
-	} else {
-	        start_addr = addr = mm->mmap_base;
-	        mm->cached_hole_size = 0;
-	}
 
-full_search:
-	if (do_align)
-		addr = COLOUR_ALIGN(addr, pgoff);
-	else
-		addr = PAGE_ALIGN(addr);
-
-	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
-		/* At this point:  (!vma || addr < vma->vm_end). */
-		if (TASK_SIZE - len < addr) {
-			/*
-			 * Start a new search - just in case we missed
-			 * some holes.
-			 */
-			if (start_addr != TASK_UNMAPPED_BASE) {
-				start_addr = addr = TASK_UNMAPPED_BASE;
-				mm->cached_hole_size = 0;
-				goto full_search;
-			}
-			return -ENOMEM;
-		}
-		if (!vma || addr + len <= vma->vm_start) {
-			/*
-			 * Remember the place where we stopped the search:
-			 */
-			mm->free_area_cache = addr + len;
-			return addr;
-		}
-		if (addr + mm->cached_hole_size < vma->vm_start)
-		        mm->cached_hole_size = vma->vm_start - addr;
-		addr = vma->vm_end;
-		if (do_align)
-			addr = COLOUR_ALIGN(addr, pgoff);
-	}
+	info.flags = 0;
+	info.length = len;
+	info.low_limit = mm->mmap_base;
+	info.high_limit = TASK_SIZE;
+	info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
+	info.align_offset = pgoff << PAGE_SHIFT;
+	return vm_unmapped_area(&info);
 }
 
 unsigned long
@@ -156,6 +112,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	unsigned long addr = addr0;
 	int do_align = 0;
 	int aliasing = cache_is_vipt_aliasing();
+	struct vm_unmapped_area_info info;
 
 	/*
 	 * We only need to do colour alignment if either the I or D
@@ -187,70 +144,27 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 			return addr;
 	}
 
-	/* check if free_area_cache is useful for us */
-	if (len <= mm->cached_hole_size) {
-		mm->cached_hole_size = 0;
-		mm->free_area_cache = mm->mmap_base;
-	}
-
-	/* either no address requested or can't fit in requested address hole */
-	addr = mm->free_area_cache;
-	if (do_align) {
-		unsigned long base = COLOUR_ALIGN_DOWN(addr - len, pgoff);
-		addr = base + len;
-	}
-
-	/* make sure it can fit in the remaining address space */
-	if (addr > len) {
-		vma = find_vma(mm, addr-len);
-		if (!vma || addr <= vma->vm_start)
-			/* remember the address as a hint for next time */
-			return (mm->free_area_cache = addr-len);
-	}
-
-	if (mm->mmap_base < len)
-		goto bottomup;
-
-	addr = mm->mmap_base - len;
-	if (do_align)
-		addr = COLOUR_ALIGN_DOWN(addr, pgoff);
-
-	do {
-		/*
-		 * Lookup failure means no vma is above this address,
-		 * else if new region fits below vma->vm_start,
-		 * return with success:
-		 */
-		vma = find_vma(mm, addr);
-		if (!vma || addr+len <= vma->vm_start)
-			/* remember the address as a hint for next time */
-			return (mm->free_area_cache = addr);
+	info.flags = VM_UNMAPPED_AREA_TOPDOWN;
+	info.length = len;
+	info.low_limit = PAGE_SIZE;
+	info.high_limit = mm->mmap_base;
+	info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
+	info.align_offset = pgoff << PAGE_SHIFT;
+	addr = vm_unmapped_area(&info);
 
-		/* remember the largest hole we saw so far */
-		if (addr + mm->cached_hole_size < vma->vm_start)
-			mm->cached_hole_size = vma->vm_start - addr;
-
-		/* try just below the current vma->vm_start */
-		addr = vma->vm_start - len;
-		if (do_align)
-			addr = COLOUR_ALIGN_DOWN(addr, pgoff);
-	} while (len < vma->vm_start);
-
-bottomup:
 	/*
 	 * A failed mmap() very likely causes application failure,
 	 * so fall back to the bottom-up function here. This scenario
 	 * can happen with large stack limits and large mmap()
 	 * allocations.
 	 */
-	mm->cached_hole_size = ~0UL;
-	mm->free_area_cache = TASK_UNMAPPED_BASE;
-	addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
-	/*
-	 * Restore the topdown base:
-	 */
-	mm->free_area_cache = mm->mmap_base;
-	mm->cached_hole_size = ~0UL;
+	if (addr & ~PAGE_MASK) {
+		VM_BUG_ON(addr != -ENOMEM);
+		info.flags = 0;
+		info.low_limit = mm->mmap_base;
+		info.high_limit = TASK_SIZE;
+		addr = vm_unmapped_area(&info);
+	}
 
 	return addr;
 }
@@ -279,7 +193,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
  * You really shouldn't be using read() or write() on /dev/mem.  This
  * might go away in the future.
  */
-int valid_phys_addr_range(unsigned long addr, size_t size)
+int valid_phys_addr_range(phys_addr_t addr, size_t size)
 {
 	if (addr < PHYS_OFFSET)
 		return 0;
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 941dfb9..a77bb0e 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -97,6 +97,7 @@ static struct cachepolicy cache_policies[] __initdata = {
 	}
 };
 
+#ifdef CONFIG_CPU_CP15
 /*
  * These are useful for identifying cache coherency
  * problems by allowing the cache or the cache and
@@ -195,6 +196,22 @@ void adjust_cr(unsigned long mask, unsigned long set)
 }
 #endif
 
+#else
+
+static int __init early_cachepolicy(char *p)
+{
+	pr_warning("cachepolicy kernel parameter not supported without cp15\n");
+}
+early_param("cachepolicy", early_cachepolicy);
+
+static int __init noalign_setup(char *__unused)
+{
+	pr_warning("noalign kernel parameter not supported without cp15\n");
+}
+__setup("noalign", noalign_setup);
+
+#endif
+
 #define PROT_PTE_DEVICE		L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN
 #define PROT_SECT_DEVICE	PMD_TYPE_SECT|PMD_SECT_AP_WRITE
 
@@ -488,7 +505,7 @@ static void __init build_mem_type_table(void)
 #endif
 
 	for (i = 0; i < 16; i++) {
-		unsigned long v = pgprot_val(protection_map[i]);
+		pteval_t v = pgprot_val(protection_map[i]);
 		protection_map[i] = __pgprot(v | user_pgprot);
 	}
 
@@ -876,6 +893,22 @@ static void __init pci_reserve_io(void)
 #define pci_reserve_io() do { } while (0)
 #endif
 
+#ifdef CONFIG_DEBUG_LL
+void __init debug_ll_io_init(void)
+{
+	struct map_desc map;
+
+	debug_ll_addr(&map.pfn, &map.virtual);
+	if (!map.pfn || !map.virtual)
+		return;
+	map.pfn = __phys_to_pfn(map.pfn);
+	map.virtual &= PAGE_MASK;
+	map.length = PAGE_SIZE;
+	map.type = MT_DEVICE;
+	create_mapping(&map);
+}
+#endif
+
 static void * __initdata vmalloc_min =
 	(void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET);
 
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index d51225f..4bc8ae5 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -20,12 +20,14 @@
 
 void __init arm_mm_memblock_reserve(void)
 {
+#ifndef CONFIG_CPU_V7M
 	/*
 	 * Register the exception vector page.
 	 * some architectures which the DRAM is the exception vector to trap,
 	 * alloc_page breaks with error, although it is not NULL, but "0."
 	 */
 	memblock_reserve(CONFIG_VECTORS_BASE, PAGE_SIZE);
+#endif
 }
 
 void __init sanity_check_meminfo(void)
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
index b29a226..eb6aa73 100644
--- a/arch/arm/mm/proc-macros.S
+++ b/arch/arm/mm/proc-macros.S
@@ -167,6 +167,10 @@
 	tst	r1, #L_PTE_YOUNG
 	tstne	r1, #L_PTE_PRESENT
 	moveq	r3, #0
+#ifndef CONFIG_CPU_USE_DOMAINS
+	tstne	r1, #L_PTE_NONE
+	movne	r3, #0
+#endif
 
 	str	r3, [r0]
 	mcr	p15, 0, r0, c7, c10, 1		@ flush_pte
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 86b8b48..09c5233 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -89,7 +89,7 @@ ENTRY(cpu_v6_dcache_clean_area)
 	mov	pc, lr
 
 /*
- *	cpu_arm926_switch_mm(pgd_phys, tsk)
+ *	cpu_v6_switch_mm(pgd_phys, tsk)
  *
  *	Set the translation table base pointer to be pgd_phys
  *
diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
index fd045e7..6d98c13 100644
--- a/arch/arm/mm/proc-v7-2level.S
+++ b/arch/arm/mm/proc-v7-2level.S
@@ -100,7 +100,11 @@ ENTRY(cpu_v7_set_pte_ext)
 	orrne	r3, r3, #PTE_EXT_XN
 
 	tst	r1, #L_PTE_YOUNG
-	tstne	r1, #L_PTE_PRESENT
+	tstne	r1, #L_PTE_VALID
+#ifndef CONFIG_CPU_USE_DOMAINS
+	eorne	r1, r1, #L_PTE_NONE
+	tstne	r1, #L_PTE_NONE
+#endif
 	moveq	r3, #0
 
  ARM(	str	r3, [r0, #2048]! )
@@ -161,11 +165,11 @@ ENDPROC(cpu_v7_set_pte_ext)
 	 *  TFR   EV X F   I D LR    S
 	 * .EEE ..EE PUI. .T.T 4RVI ZWRS BLDP WCAM
 	 * rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced
-	 *    1    0 110       0011 1100 .111 1101 < we want
+	 *   01    0 110       0011 1100 .111 1101 < we want
 	 */
 	.align	2
 	.type	v7_crval, #object
 v7_crval:
-	crval	clear=0x0120c302, mmuset=0x10c03c7d, ucset=0x00c01c7c
+	crval	clear=0x2120c302, mmuset=0x10c03c7d, ucset=0x00c01c7c
 
 	.previous
diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S
index 8de0f1d..7b56386 100644
--- a/arch/arm/mm/proc-v7-3level.S
+++ b/arch/arm/mm/proc-v7-3level.S
@@ -65,8 +65,11 @@ ENDPROC(cpu_v7_switch_mm)
  */
 ENTRY(cpu_v7_set_pte_ext)
 #ifdef CONFIG_MMU
-	tst	r2, #L_PTE_PRESENT
+	tst	r2, #L_PTE_VALID
 	beq	1f
+	tst	r3, #1 << (57 - 32)		@ L_PTE_NONE
+	bicne	r2, #L_PTE_VALID
+	bne	1f
 	tst	r3, #1 << (55 - 32)		@ L_PTE_DIRTY
 	orreq	r2, #L_PTE_RDONLY
 1:	strd	r2, r3, [r0]
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 846d279..42cc833 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -57,7 +57,7 @@ ENTRY(cpu_v7_reset)
  THUMB(	bic	r1, r1, #1 << 30 )		@ SCTLR.TE (Thumb exceptions)
 	mcr	p15, 0, r1, c1, c0, 0		@ disable MMU
 	isb
-	mov	pc, r0
+	bx	r0
 ENDPROC(cpu_v7_reset)
 	.popsection
 
diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S
new file mode 100644
index 0000000..2b8eb97
--- /dev/null
+++ b/arch/arm/mm/proc-v7m.S
@@ -0,0 +1,161 @@
+/*
+ *  linux/arch/arm/mm/proc-v7m.S
+ *
+ *  Copyright (C) 2008 ARM Ltd.
+ *  Copyright (C) 2001 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  This is the "shell" of the ARMv7-M processor support.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+ENTRY(cpu_v7m_proc_init)
+	mov	pc, lr
+ENDPROC(cpu_v7m_proc_init)
+
+ENTRY(cpu_v7m_proc_fin)
+	mov	pc, lr
+ENDPROC(cpu_v7m_proc_fin)
+
+/*
+ *	cpu_v7m_reset(loc)
+ *
+ *	Perform a soft reset of the system.  Put the CPU into the
+ *	same state as it would be if it had been reset, and branch
+ *	to what would be the reset vector.
+ *
+ *	- loc   - location to jump to for soft reset
+ */
+	.align	5
+ENTRY(cpu_v7m_reset)
+	mov	pc, r0
+ENDPROC(cpu_v7m_reset)
+
+/*
+ *	cpu_v7m_do_idle()
+ *
+ *	Idle the processor (eg, wait for interrupt).
+ *
+ *	IRQs are already disabled.
+ */
+ENTRY(cpu_v7m_do_idle)
+	wfi
+	mov	pc, lr
+ENDPROC(cpu_v7m_do_idle)
+
+ENTRY(cpu_v7m_dcache_clean_area)
+	mov	pc, lr
+ENDPROC(cpu_v7m_dcache_clean_area)
+
+/*
+ * There is no MMU, so here is nothing to do.
+ */
+ENTRY(cpu_v7m_switch_mm)
+	mov	pc, lr
+ENDPROC(cpu_v7m_switch_mm)
+
+cpu_v7m_name:
+	.ascii	"ARMv7-M Processor"
+	.align
+
+	.section ".text.init", #alloc, #execinstr
+
+/*
+ *	__v7m_setup
+ *
+ *	This should be able to cover all ARMv7-M cores.
+ */
+__v7m_setup:
+	@ Configure the vector table base address
+	ldr	r0, =0xe000ed08		@ vector table base address
+	ldr	r12, =vector_table
+	str	r12, [r0]
+
+	@ Lower the priority of the SVC and PendSV exceptions
+	ldr	r0, =0xe000ed1c
+	mov	r5, #0x80000000
+	str	r5, [r0]		@ set SVC priority
+	ldr	r0, =0xe000ed20
+	mov	r5, #0x00800000
+	str	r5, [r0]		@ set PendSV priority
+
+	@ SVC to run the kernel in this mode
+	adr	r0, BSYM(1f)
+	ldr	r5, [r12, #11 * 4]	@ read the SVC vector entry
+	str	r0, [r12, #11 * 4]	@ write the temporary SVC vector entry
+	mov	r6, lr			@ save LR
+	mov	r7, sp			@ save SP
+	ldr	sp, =__v7m_setup_stack_top
+	cpsie	i
+	svc	#0
+1:	cpsid	i
+	str	r5, [r12, #11 * 4]	@ restore the original SVC vector entry
+	mov	lr, r6			@ restore LR
+	mov	sp, r7			@ restore SP
+
+	@ Special-purpose control register
+	mov	r0, #1
+	msr	control, r0		@ Thread mode has unpriviledged access
+
+	@ Configure the System Control Register
+	ldr	r0, =0xe000ed14		@ system control register
+	ldr	r12, [r0]
+	orr	r12, #1 << 9		@ STKALIGN
+	str	r12, [r0]
+	mov	pc, lr
+ENDPROC(__v7m_setup)
+
+	.align	2
+	.type	v7m_processor_functions, #object
+ENTRY(v7m_processor_functions)
+	.word	nommu_early_abort
+	.word	cpu_v7m_proc_init
+	.word	cpu_v7m_proc_fin
+	.word	cpu_v7m_reset
+	.word	cpu_v7m_do_idle
+	.word	cpu_v7m_dcache_clean_area
+	.word	cpu_v7m_switch_mm
+	.word	0			@ cpu_v7m_set_pte_ext
+	.word	legacy_pabort
+	.size	v7m_processor_functions, . - v7m_processor_functions
+
+	.type	cpu_arch_name, #object
+cpu_arch_name:
+	.asciz	"armv7m"
+	.size	cpu_arch_name, . - cpu_arch_name
+
+	.type	cpu_elf_name, #object
+cpu_elf_name:
+	.asciz	"v7m"
+	.size	cpu_elf_name, . - cpu_elf_name
+	.align
+
+	.section ".proc.info.init", #alloc, #execinstr
+
+	/*
+	 * Match any ARMv7-M processor core.
+	 */
+	.type	__v7m_proc_info, #object
+__v7m_proc_info:
+	.long	0x000f0000		@ Required ID value
+	.long	0x000f0000		@ Mask for ID
+	.long   0			@ proc_info_list.__cpu_mm_mmu_flags
+	.long   0			@ proc_info_list.__cpu_io_mmu_flags
+	b	__v7m_setup		@ proc_info_list.__cpu_flush
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+	.long	cpu_v7m_name
+	.long	v7m_processor_functions	@ proc_info_list.proc
+	.long	0			@ proc_info_list.tlb
+	.long	0			@ proc_info_list.user
+	.long	0			@ proc_info_list.cache
+	.size	__v7m_proc_info, . - __v7m_proc_info
+
+__v7m_setup_stack:
+	.space	4 * 8				@ 8 registers
+__v7m_setup_stack_top:
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index c641fb6..9af9a69 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -16,6 +16,7 @@
 #include <linux/netdevice.h>
 #include <linux/string.h>
 #include <linux/slab.h>
+#include <linux/if_vlan.h>
 #include <asm/cacheflush.h>
 #include <asm/hwcap.h>
 
@@ -168,6 +169,8 @@ static inline bool is_load_to_a(u16 inst)
 	case BPF_S_ANC_MARK:
 	case BPF_S_ANC_PROTOCOL:
 	case BPF_S_ANC_RXHASH:
+	case BPF_S_ANC_VLAN_TAG:
+	case BPF_S_ANC_VLAN_TAG_PRESENT:
 	case BPF_S_ANC_QUEUE:
 		return true;
 	default:
@@ -646,6 +649,16 @@ load_ind:
 			update_on_xread(ctx);
 			emit(ARM_ORR_R(r_A, r_A, r_X), ctx);
 			break;
+		case BPF_S_ALU_XOR_K:
+			/* A ^= K; */
+			OP_IMM3(ARM_EOR, r_A, r_A, k, ctx);
+			break;
+		case BPF_S_ANC_ALU_XOR_X:
+		case BPF_S_ALU_XOR_X:
+			/* A ^= X */
+			update_on_xread(ctx);
+			emit(ARM_EOR_R(r_A, r_A, r_X), ctx);
+			break;
 		case BPF_S_ALU_AND_K:
 			/* A &= K */
 			OP_IMM3(ARM_AND, r_A, r_A, k, ctx);
@@ -762,11 +775,6 @@ b_epilogue:
 			update_on_xread(ctx);
 			emit(ARM_MOV_R(r_A, r_X), ctx);
 			break;
-		case BPF_S_ANC_ALU_XOR_X:
-			/* A ^= X */
-			update_on_xread(ctx);
-			emit(ARM_EOR_R(r_A, r_A, r_X), ctx);
-			break;
 		case BPF_S_ANC_PROTOCOL:
 			/* A = ntohs(skb->protocol) */
 			ctx->seen |= SEEN_SKB;
@@ -810,6 +818,17 @@ b_epilogue:
 			off = offsetof(struct sk_buff, rxhash);
 			emit(ARM_LDR_I(r_A, r_skb, off), ctx);
 			break;
+		case BPF_S_ANC_VLAN_TAG:
+		case BPF_S_ANC_VLAN_TAG_PRESENT:
+			ctx->seen |= SEEN_SKB;
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
+			off = offsetof(struct sk_buff, vlan_tci);
+			emit(ARM_LDRH_I(r_A, r_skb, off), ctx);
+			if (inst->code == BPF_S_ANC_VLAN_TAG)
+				OP_IMM3(ARM_AND, r_A, r_A, VLAN_VID_MASK, ctx);
+			else
+				OP_IMM3(ARM_AND, r_A, r_A, VLAN_TAG_PRESENT, ctx);
+			break;
 		case BPF_S_ANC_QUEUE:
 			ctx->seen |= SEEN_SKB;
 			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
diff --git a/arch/arm/net/bpf_jit_32.h b/arch/arm/net/bpf_jit_32.h
index 7fa2f7d..afb8462 100644
--- a/arch/arm/net/bpf_jit_32.h
+++ b/arch/arm/net/bpf_jit_32.h
@@ -69,6 +69,7 @@
 #define ARM_INST_CMP_I		0x03500000
 
 #define ARM_INST_EOR_R		0x00200000
+#define ARM_INST_EOR_I		0x02200000
 
 #define ARM_INST_LDRB_I		0x05d00000
 #define ARM_INST_LDRB_R		0x07d00000
@@ -135,6 +136,7 @@
 #define ARM_CMP_I(rn, imm)	_AL3_I(ARM_INST_CMP, 0, rn, imm)
 
 #define ARM_EOR_R(rd, rn, rm)	_AL3_R(ARM_INST_EOR, rd, rn, rm)
+#define ARM_EOR_I(rd, rn, imm)	_AL3_I(ARM_INST_EOR, rd, rn, imm)
 
 #define ARM_LDR_I(rt, rn, off)	(ARM_INST_LDR_I | (rt) << 12 | (rn) << 16 \
 				 | (off))
diff --git a/arch/arm/plat-mxc/3ds_debugboard.c b/arch/arm/plat-mxc/3ds_debugboard.c
deleted file mode 100644
index 5c10ad0..0000000
--- a/arch/arm/plat-mxc/3ds_debugboard.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2010 Jason Wang <jason77.wang@gmail.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/module.h>
-#include <linux/smsc911x.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-
-#include <mach/hardware.h>
-
-/* LAN9217 ethernet base address */
-#define LAN9217_BASE_ADDR(n)	(n + 0x0)
-/* External UART */
-#define UARTA_BASE_ADDR(n)	(n + 0x8000)
-#define UARTB_BASE_ADDR(n)	(n + 0x10000)
-
-#define BOARD_IO_ADDR(n)	(n + 0x20000)
-/* LED switchs */
-#define LED_SWITCH_REG		0x00
-/* buttons */
-#define SWITCH_BUTTONS_REG	0x08
-/* status, interrupt */
-#define INTR_STATUS_REG	0x10
-#define INTR_MASK_REG		0x38
-#define INTR_RESET_REG		0x20
-/* magic word for debug CPLD */
-#define MAGIC_NUMBER1_REG	0x40
-#define MAGIC_NUMBER2_REG	0x48
-/* CPLD code version */
-#define CPLD_CODE_VER_REG	0x50
-/* magic word for debug CPLD */
-#define MAGIC_NUMBER3_REG	0x58
-/* module reset register*/
-#define MODULE_RESET_REG	0x60
-/* CPU ID and Personality ID */
-#define MCU_BOARD_ID_REG	0x68
-
-#define MXC_MAX_EXP_IO_LINES	16
-
-/* interrupts like external uart , external ethernet etc*/
-#define EXPIO_INT_ENET		0
-#define EXPIO_INT_XUART_A	1
-#define EXPIO_INT_XUART_B	2
-#define EXPIO_INT_BUTTON_A	3
-#define EXPIO_INT_BUTTON_B	4
-
-static void __iomem *brd_io;
-static struct irq_domain *domain;
-
-static struct resource smsc911x_resources[] = {
-	{
-		.flags = IORESOURCE_MEM,
-	} , {
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct smsc911x_platform_config smsc911x_config = {
-	.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-	.flags = SMSC911X_USE_32BIT | SMSC911X_FORCE_INTERNAL_PHY,
-};
-
-static struct platform_device smsc_lan9217_device = {
-	.name = "smsc911x",
-	.id = -1,
-	.dev = {
-		.platform_data = &smsc911x_config,
-	},
-	.num_resources = ARRAY_SIZE(smsc911x_resources),
-	.resource = smsc911x_resources,
-};
-
-static void mxc_expio_irq_handler(u32 irq, struct irq_desc *desc)
-{
-	u32 imr_val;
-	u32 int_valid;
-	u32 expio_irq;
-
-	/* irq = gpio irq number */
-	desc->irq_data.chip->irq_mask(&desc->irq_data);
-
-	imr_val = __raw_readw(brd_io + INTR_MASK_REG);
-	int_valid = __raw_readw(brd_io + INTR_STATUS_REG) & ~imr_val;
-
-	expio_irq = 0;
-	for (; int_valid != 0; int_valid >>= 1, expio_irq++) {
-		if ((int_valid & 1) == 0)
-			continue;
-		generic_handle_irq(irq_find_mapping(domain, expio_irq));
-	}
-
-	desc->irq_data.chip->irq_ack(&desc->irq_data);
-	desc->irq_data.chip->irq_unmask(&desc->irq_data);
-}
-
-/*
- * Disable an expio pin's interrupt by setting the bit in the imr.
- * Irq is an expio virtual irq number
- */
-static void expio_mask_irq(struct irq_data *d)
-{
-	u16 reg;
-	u32 expio = d->hwirq;
-
-	reg = __raw_readw(brd_io + INTR_MASK_REG);
-	reg |= (1 << expio);
-	__raw_writew(reg, brd_io + INTR_MASK_REG);
-}
-
-static void expio_ack_irq(struct irq_data *d)
-{
-	u32 expio = d->hwirq;
-
-	__raw_writew(1 << expio, brd_io + INTR_RESET_REG);
-	__raw_writew(0, brd_io + INTR_RESET_REG);
-	expio_mask_irq(d);
-}
-
-static void expio_unmask_irq(struct irq_data *d)
-{
-	u16 reg;
-	u32 expio = d->hwirq;
-
-	reg = __raw_readw(brd_io + INTR_MASK_REG);
-	reg &= ~(1 << expio);
-	__raw_writew(reg, brd_io + INTR_MASK_REG);
-}
-
-static struct irq_chip expio_irq_chip = {
-	.irq_ack = expio_ack_irq,
-	.irq_mask = expio_mask_irq,
-	.irq_unmask = expio_unmask_irq,
-};
-
-static struct regulator_consumer_supply dummy_supplies[] = {
-	REGULATOR_SUPPLY("vdd33a", "smsc911x"),
-	REGULATOR_SUPPLY("vddvario", "smsc911x"),
-};
-
-int __init mxc_expio_init(u32 base, u32 intr_gpio)
-{
-	u32 p_irq = gpio_to_irq(intr_gpio);
-	int irq_base;
-	int i;
-
-	brd_io = ioremap(BOARD_IO_ADDR(base), SZ_4K);
-	if (brd_io == NULL)
-		return -ENOMEM;
-
-	if ((__raw_readw(brd_io + MAGIC_NUMBER1_REG) != 0xAAAA) ||
-	    (__raw_readw(brd_io + MAGIC_NUMBER2_REG) != 0x5555) ||
-	    (__raw_readw(brd_io + MAGIC_NUMBER3_REG) != 0xCAFE)) {
-		pr_info("3-Stack Debug board not detected\n");
-		iounmap(brd_io);
-		brd_io = NULL;
-		return -ENODEV;
-	}
-
-	pr_info("3-Stack Debug board detected, rev = 0x%04X\n",
-		readw(brd_io + CPLD_CODE_VER_REG));
-
-	/*
-	 * Configure INT line as GPIO input
-	 */
-	gpio_request(intr_gpio, "expio_pirq");
-	gpio_direction_input(intr_gpio);
-
-	/* disable the interrupt and clear the status */
-	__raw_writew(0, brd_io + INTR_MASK_REG);
-	__raw_writew(0xFFFF, brd_io + INTR_RESET_REG);
-	__raw_writew(0, brd_io + INTR_RESET_REG);
-	__raw_writew(0x1F, brd_io + INTR_MASK_REG);
-
-	irq_base = irq_alloc_descs(-1, 0, MXC_MAX_EXP_IO_LINES, numa_node_id());
-	WARN_ON(irq_base < 0);
-
-	domain = irq_domain_add_legacy(NULL, MXC_MAX_EXP_IO_LINES, irq_base, 0,
-				       &irq_domain_simple_ops, NULL);
-	WARN_ON(!domain);
-
-	for (i = irq_base; i < irq_base + MXC_MAX_EXP_IO_LINES; i++) {
-		irq_set_chip_and_handler(i, &expio_irq_chip, handle_level_irq);
-		set_irq_flags(i, IRQF_VALID);
-	}
-	irq_set_irq_type(p_irq, IRQF_TRIGGER_LOW);
-	irq_set_chained_handler(p_irq, mxc_expio_irq_handler);
-
-	/* Register Lan device on the debugboard */
-	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-
-	smsc911x_resources[0].start = LAN9217_BASE_ADDR(base);
-	smsc911x_resources[0].end = LAN9217_BASE_ADDR(base) + 0x100 - 1;
-	smsc911x_resources[1].start = irq_find_mapping(domain, EXPIO_INT_ENET);
-	smsc911x_resources[1].end = irq_find_mapping(domain, EXPIO_INT_ENET);
-	platform_device_register(&smsc_lan9217_device);
-
-	return 0;
-}
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
deleted file mode 100644
index 88e1e2e..0000000
--- a/arch/arm/plat-mxc/Kconfig
+++ /dev/null
@@ -1,89 +0,0 @@
-if ARCH_MXC
-
-source "arch/arm/plat-mxc/devices/Kconfig"
-
-menu "Freescale MXC Implementations"
-
-choice
-	prompt "Freescale CPU family:"
-	default ARCH_IMX_V6_V7
-
-config ARCH_IMX_V4_V5
-	bool "i.MX1, i.MX21, i.MX25, i.MX27"
-	select ARM_PATCH_PHYS_VIRT
-	select AUTO_ZRELADDR if !ZBOOT_ROM
-	help
-	  This enables support for systems based on the Freescale i.MX ARMv4
-	  and ARMv5 SoCs
-
-config ARCH_IMX_V6_V7
-	bool "i.MX3, i.MX5, i.MX6"
-	select ARM_PATCH_PHYS_VIRT
-	select AUTO_ZRELADDR if !ZBOOT_ROM
-	select MIGHT_HAVE_CACHE_L2X0
-	help
-	  This enables support for systems based on the Freescale i.MX3, i.MX5
-	  and i.MX6 family.
-
-endchoice
-
-source "arch/arm/mach-imx/Kconfig"
-
-endmenu
-
-config MXC_IRQ_PRIOR
-	bool "Use IRQ priority"
-	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.
-	  This may be useful in embedded applications, where are strong
-	  requirements for timing.
-	  Say N here, unless you have a specialized requirement.
-
-config MXC_TZIC
-	bool
-
-config MXC_AVIC
-	bool
-
-config MXC_DEBUG_BOARD
-	bool "Enable MXC debug board(for 3-stack)"
-	help
-	  The debug board is an integral part of the MXC 3-stack(PDK)
-	  platforms, it can be attached or removed from the peripheral
-	  board. On debug board, several debug devices(ethernet, UART,
-	  buttons, LEDs and JTAG) are implemented. Between the MCU and
-	  these devices, a CPLD is added as a bridge which performs
-	  data/address de-multiplexing and decode, signal level shift,
-	  interrupt control and various board functions.
-
-config HAVE_EPIT
-	bool
-
-config MXC_USE_EPIT
-	bool "Use EPIT instead of GPT"
-	depends on HAVE_EPIT
-	help
-	  Use EPIT as the system timer on systems that have it. Normally you
-	  don't have a reason to do so as the EPIT has the same features and
-	  uses the same clocks as the GPT. Anyway, on some systems the GPT
-	  may be in use for other purposes.
-
-config MXC_ULPI
-	bool
-
-config ARCH_HAS_RNGA
-	bool
-
-config IMX_HAVE_IOMUX_V1
-	bool
-
-config ARCH_MXC_IOMUX_V3
-	bool
-
-config IRAM_ALLOC
-	bool
-	select GENERIC_ALLOCATOR
-
-endif
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
deleted file mode 100644
index 149237e..0000000
--- a/arch/arm/plat-mxc/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Common support
-obj-y := time.o devices.o cpu.o system.o irq-common.o
-
-obj-$(CONFIG_MXC_TZIC) += tzic.o
-obj-$(CONFIG_MXC_AVIC) += avic.o
-
-obj-$(CONFIG_IMX_HAVE_IOMUX_V1) += iomux-v1.o
-obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
-obj-$(CONFIG_IRAM_ALLOC) += iram_alloc.o
-obj-$(CONFIG_MXC_ULPI) += ulpi.o
-obj-$(CONFIG_MXC_USE_EPIT) += epit.o
-obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
-obj-$(CONFIG_CPU_FREQ_IMX)    += cpufreq.o
-obj-$(CONFIG_CPU_IDLE) += cpuidle.o
-ifdef CONFIG_SND_IMX_SOC
-obj-y += ssi-fiq.o
-obj-y += ssi-fiq-ksym.o
-endif
-
-obj-y += devices/
diff --git a/arch/arm/plat-mxc/avic.c b/arch/arm/plat-mxc/avic.c
deleted file mode 100644
index cbd55c3..0000000
--- a/arch/arm/plat-mxc/avic.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <mach/common.h>
-#include <asm/mach/irq.h>
-#include <asm/exception.h>
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-
-#include "irq-common.h"
-
-#define AVIC_INTCNTL		0x00	/* int control reg */
-#define AVIC_NIMASK		0x04	/* int mask reg */
-#define AVIC_INTENNUM		0x08	/* int enable number reg */
-#define AVIC_INTDISNUM		0x0C	/* int disable number reg */
-#define AVIC_INTENABLEH		0x10	/* int enable reg high */
-#define AVIC_INTENABLEL		0x14	/* int enable reg low */
-#define AVIC_INTTYPEH		0x18	/* int type reg high */
-#define AVIC_INTTYPEL		0x1C	/* int type reg low */
-#define AVIC_NIPRIORITY(x)	(0x20 + 4 * (7 - (x))) /* int priority */
-#define AVIC_NIVECSR		0x40	/* norm int vector/status */
-#define AVIC_FIVECSR		0x44	/* fast int vector/status */
-#define AVIC_INTSRCH		0x48	/* int source reg high */
-#define AVIC_INTSRCL		0x4C	/* int source reg low */
-#define AVIC_INTFRCH		0x50	/* int force reg high */
-#define AVIC_INTFRCL		0x54	/* int force reg low */
-#define AVIC_NIPNDH		0x58	/* norm int pending high */
-#define AVIC_NIPNDL		0x5C	/* norm int pending low */
-#define AVIC_FIPNDH		0x60	/* fast int pending high */
-#define AVIC_FIPNDL		0x64	/* fast int pending low */
-
-#define AVIC_NUM_IRQS 64
-
-void __iomem *avic_base;
-static struct irq_domain *domain;
-
-static u32 avic_saved_mask_reg[2];
-
-#ifdef CONFIG_MXC_IRQ_PRIOR
-static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
-{
-	struct irq_data *d = irq_get_irq_data(irq);
-	unsigned int temp;
-	unsigned int mask = 0x0F << irq % 8 * 4;
-
-	irq = d->hwirq;
-
-	if (irq >= AVIC_NUM_IRQS)
-		return -EINVAL;
-
-	temp = __raw_readl(avic_base + AVIC_NIPRIORITY(irq / 8));
-	temp &= ~mask;
-	temp |= prio & mask;
-
-	__raw_writel(temp, avic_base + AVIC_NIPRIORITY(irq / 8));
-
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_FIQ
-static int avic_set_irq_fiq(unsigned int irq, unsigned int type)
-{
-	struct irq_data *d = irq_get_irq_data(irq);
-	unsigned int irqt;
-
-	irq = d->hwirq;
-
-	if (irq >= AVIC_NUM_IRQS)
-		return -EINVAL;
-
-	if (irq < AVIC_NUM_IRQS / 2) {
-		irqt = __raw_readl(avic_base + AVIC_INTTYPEL) & ~(1 << irq);
-		__raw_writel(irqt | (!!type << irq), avic_base + AVIC_INTTYPEL);
-	} else {
-		irq -= AVIC_NUM_IRQS / 2;
-		irqt = __raw_readl(avic_base + AVIC_INTTYPEH) & ~(1 << irq);
-		__raw_writel(irqt | (!!type << irq), avic_base + AVIC_INTTYPEH);
-	}
-
-	return 0;
-}
-#endif /* CONFIG_FIQ */
-
-
-static struct mxc_extra_irq avic_extra_irq = {
-#ifdef CONFIG_MXC_IRQ_PRIOR
-	.set_priority = avic_irq_set_priority,
-#endif
-#ifdef CONFIG_FIQ
-	.set_irq_fiq = avic_set_irq_fiq,
-#endif
-};
-
-#ifdef CONFIG_PM
-static void avic_irq_suspend(struct irq_data *d)
-{
-	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-	struct irq_chip_type *ct = gc->chip_types;
-	int idx = d->hwirq >> 5;
-
-	avic_saved_mask_reg[idx] = __raw_readl(avic_base + ct->regs.mask);
-	__raw_writel(gc->wake_active, avic_base + ct->regs.mask);
-}
-
-static void avic_irq_resume(struct irq_data *d)
-{
-	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-	struct irq_chip_type *ct = gc->chip_types;
-	int idx = d->hwirq >> 5;
-
-	__raw_writel(avic_saved_mask_reg[idx], avic_base + ct->regs.mask);
-}
-
-#else
-#define avic_irq_suspend NULL
-#define avic_irq_resume NULL
-#endif
-
-static __init void avic_init_gc(int idx, unsigned int irq_start)
-{
-	struct irq_chip_generic *gc;
-	struct irq_chip_type *ct;
-
-	gc = irq_alloc_generic_chip("mxc-avic", 1, irq_start, avic_base,
-				    handle_level_irq);
-	gc->private = &avic_extra_irq;
-	gc->wake_enabled = IRQ_MSK(32);
-
-	ct = gc->chip_types;
-	ct->chip.irq_mask = irq_gc_mask_clr_bit;
-	ct->chip.irq_unmask = irq_gc_mask_set_bit;
-	ct->chip.irq_ack = irq_gc_mask_clr_bit;
-	ct->chip.irq_set_wake = irq_gc_set_wake;
-	ct->chip.irq_suspend = avic_irq_suspend;
-	ct->chip.irq_resume = avic_irq_resume;
-	ct->regs.mask = !idx ? AVIC_INTENABLEL : AVIC_INTENABLEH;
-	ct->regs.ack = ct->regs.mask;
-
-	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
-}
-
-asmlinkage void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
-{
-	u32 nivector;
-
-	do {
-		nivector = __raw_readl(avic_base + AVIC_NIVECSR) >> 16;
-		if (nivector == 0xffff)
-			break;
-
-		handle_IRQ(irq_find_mapping(domain, nivector), regs);
-	} while (1);
-}
-
-/*
- * This function initializes the AVIC hardware and disables all the
- * interrupts. It registers the interrupt enable and disable functions
- * to the kernel for each interrupt source.
- */
-void __init mxc_init_irq(void __iomem *irqbase)
-{
-	struct device_node *np;
-	int irq_base;
-	int i;
-
-	avic_base = irqbase;
-
-	/* put the AVIC into the reset value with
-	 * all interrupts disabled
-	 */
-	__raw_writel(0, avic_base + AVIC_INTCNTL);
-	__raw_writel(0x1f, avic_base + AVIC_NIMASK);
-
-	/* disable all interrupts */
-	__raw_writel(0, avic_base + AVIC_INTENABLEH);
-	__raw_writel(0, avic_base + AVIC_INTENABLEL);
-
-	/* all IRQ no FIQ */
-	__raw_writel(0, avic_base + AVIC_INTTYPEH);
-	__raw_writel(0, avic_base + AVIC_INTTYPEL);
-
-	irq_base = irq_alloc_descs(-1, 0, AVIC_NUM_IRQS, numa_node_id());
-	WARN_ON(irq_base < 0);
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,avic");
-	domain = irq_domain_add_legacy(np, AVIC_NUM_IRQS, irq_base, 0,
-				       &irq_domain_simple_ops, NULL);
-	WARN_ON(!domain);
-
-	for (i = 0; i < AVIC_NUM_IRQS / 32; i++, irq_base += 32)
-		avic_init_gc(i, irq_base);
-
-	/* Set default priority value (0) for all IRQ's */
-	for (i = 0; i < 8; i++)
-		__raw_writel(0, avic_base + AVIC_NIPRIORITY(i));
-
-#ifdef CONFIG_FIQ
-	/* Initialize FIQ */
-	init_FIQ(FIQ_START);
-#endif
-
-	printk(KERN_INFO "MXC IRQ initialized\n");
-}
diff --git a/arch/arm/plat-mxc/cpu.c b/arch/arm/plat-mxc/cpu.c
deleted file mode 100644
index 220dd6f..0000000
--- a/arch/arm/plat-mxc/cpu.c
+++ /dev/null
@@ -1,44 +0,0 @@
-
-#include <linux/module.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-
-unsigned int __mxc_cpu_type;
-EXPORT_SYMBOL(__mxc_cpu_type);
-
-void mxc_set_cpu_type(unsigned int type)
-{
-	__mxc_cpu_type = type;
-}
-
-void imx_print_silicon_rev(const char *cpu, int srev)
-{
-	if (srev == IMX_CHIP_REVISION_UNKNOWN)
-		pr_info("CPU identified as %s, unknown revision\n", cpu);
-	else
-		pr_info("CPU identified as %s, silicon rev %d.%d\n",
-				cpu, (srev >> 4) & 0xf, srev & 0xf);
-}
-
-void __init imx_set_aips(void __iomem *base)
-{
-	unsigned int reg;
-/*
- * Set all MPROTx to be non-bufferable, trusted for R/W,
- * not forced to user-mode.
- */
-	__raw_writel(0x77777777, base + 0x0);
-	__raw_writel(0x77777777, base + 0x4);
-
-/*
- * Set all OPACRx to be non-bufferable, to not require
- * supervisor privilege level for access, allow for
- * write access and untrusted master access.
- */
-	__raw_writel(0x0, base + 0x40);
-	__raw_writel(0x0, base + 0x44);
-	__raw_writel(0x0, base + 0x48);
-	__raw_writel(0x0, base + 0x4C);
-	reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
-	__raw_writel(reg, base + 0x50);
-}
diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c
deleted file mode 100644
index b5b6f80..0000000
--- a/arch/arm/plat-mxc/cpufreq.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-/*
- * A driver for the Freescale Semiconductor i.MXC CPUfreq module.
- * The CPUFREQ driver is for controlling CPU frequency. It allows you to change
- * the CPU clock speed on the fly.
- */
-
-#include <linux/module.h>
-#include <linux/cpufreq.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <mach/hardware.h>
-
-#define CLK32_FREQ	32768
-#define NANOSECOND	(1000 * 1000 * 1000)
-
-struct cpu_op *(*get_cpu_op)(int *op);
-
-static int cpu_freq_khz_min;
-static int cpu_freq_khz_max;
-
-static struct clk *cpu_clk;
-static struct cpufreq_frequency_table *imx_freq_table;
-
-static int cpu_op_nr;
-static struct cpu_op *cpu_op_tbl;
-
-static int set_cpu_freq(int freq)
-{
-	int ret = 0;
-	int org_cpu_rate;
-
-	org_cpu_rate = clk_get_rate(cpu_clk);
-	if (org_cpu_rate == freq)
-		return ret;
-
-	ret = clk_set_rate(cpu_clk, freq);
-	if (ret != 0) {
-		printk(KERN_DEBUG "cannot set CPU clock rate\n");
-		return ret;
-	}
-
-	return ret;
-}
-
-static int mxc_verify_speed(struct cpufreq_policy *policy)
-{
-	if (policy->cpu != 0)
-		return -EINVAL;
-
-	return cpufreq_frequency_table_verify(policy, imx_freq_table);
-}
-
-static unsigned int mxc_get_speed(unsigned int cpu)
-{
-	if (cpu)
-		return 0;
-
-	return clk_get_rate(cpu_clk) / 1000;
-}
-
-static int mxc_set_target(struct cpufreq_policy *policy,
-			  unsigned int target_freq, unsigned int relation)
-{
-	struct cpufreq_freqs freqs;
-	int freq_Hz;
-	int ret = 0;
-	unsigned int index;
-
-	cpufreq_frequency_table_target(policy, imx_freq_table,
-			target_freq, relation, &index);
-	freq_Hz = imx_freq_table[index].frequency * 1000;
-
-	freqs.old = clk_get_rate(cpu_clk) / 1000;
-	freqs.new = freq_Hz / 1000;
-	freqs.cpu = 0;
-	freqs.flags = 0;
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
-	ret = set_cpu_freq(freq_Hz);
-
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
-	return ret;
-}
-
-static int mxc_cpufreq_init(struct cpufreq_policy *policy)
-{
-	int ret;
-	int i;
-
-	printk(KERN_INFO "i.MXC CPU frequency driver\n");
-
-	if (policy->cpu != 0)
-		return -EINVAL;
-
-	if (!get_cpu_op)
-		return -EINVAL;
-
-	cpu_clk = clk_get(NULL, "cpu_clk");
-	if (IS_ERR(cpu_clk)) {
-		printk(KERN_ERR "%s: failed to get cpu clock\n", __func__);
-		return PTR_ERR(cpu_clk);
-	}
-
-	cpu_op_tbl = get_cpu_op(&cpu_op_nr);
-
-	cpu_freq_khz_min = cpu_op_tbl[0].cpu_rate / 1000;
-	cpu_freq_khz_max = cpu_op_tbl[0].cpu_rate / 1000;
-
-	imx_freq_table = kmalloc(
-		sizeof(struct cpufreq_frequency_table) * (cpu_op_nr + 1),
-			GFP_KERNEL);
-	if (!imx_freq_table) {
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	for (i = 0; i < cpu_op_nr; i++) {
-		imx_freq_table[i].index = i;
-		imx_freq_table[i].frequency = cpu_op_tbl[i].cpu_rate / 1000;
-
-		if ((cpu_op_tbl[i].cpu_rate / 1000) < cpu_freq_khz_min)
-			cpu_freq_khz_min = cpu_op_tbl[i].cpu_rate / 1000;
-
-		if ((cpu_op_tbl[i].cpu_rate / 1000) > cpu_freq_khz_max)
-			cpu_freq_khz_max = cpu_op_tbl[i].cpu_rate / 1000;
-	}
-
-	imx_freq_table[i].index = i;
-	imx_freq_table[i].frequency = CPUFREQ_TABLE_END;
-
-	policy->cur = clk_get_rate(cpu_clk) / 1000;
-	policy->min = policy->cpuinfo.min_freq = cpu_freq_khz_min;
-	policy->max = policy->cpuinfo.max_freq = cpu_freq_khz_max;
-
-	/* Manual states, that PLL stabilizes in two CLK32 periods */
-	policy->cpuinfo.transition_latency = 2 * NANOSECOND / CLK32_FREQ;
-
-	ret = cpufreq_frequency_table_cpuinfo(policy, imx_freq_table);
-
-	if (ret < 0) {
-		printk(KERN_ERR "%s: failed to register i.MXC CPUfreq with error code %d\n",
-		       __func__, ret);
-		goto err;
-	}
-
-	cpufreq_frequency_table_get_attr(imx_freq_table, policy->cpu);
-	return 0;
-err:
-	kfree(imx_freq_table);
-err1:
-	clk_put(cpu_clk);
-	return ret;
-}
-
-static int mxc_cpufreq_exit(struct cpufreq_policy *policy)
-{
-	cpufreq_frequency_table_put_attr(policy->cpu);
-
-	set_cpu_freq(cpu_freq_khz_max * 1000);
-	clk_put(cpu_clk);
-	kfree(imx_freq_table);
-	return 0;
-}
-
-static struct cpufreq_driver mxc_driver = {
-	.flags = CPUFREQ_STICKY,
-	.verify = mxc_verify_speed,
-	.target = mxc_set_target,
-	.get = mxc_get_speed,
-	.init = mxc_cpufreq_init,
-	.exit = mxc_cpufreq_exit,
-	.name = "imx",
-};
-
-static int __devinit mxc_cpufreq_driver_init(void)
-{
-	return cpufreq_register_driver(&mxc_driver);
-}
-
-static void mxc_cpufreq_driver_exit(void)
-{
-	cpufreq_unregister_driver(&mxc_driver);
-}
-
-module_init(mxc_cpufreq_driver_init);
-module_exit(mxc_cpufreq_driver_exit);
-
-MODULE_AUTHOR("Freescale Semiconductor Inc. Yong Shen <yong.shen@linaro.org>");
-MODULE_DESCRIPTION("CPUfreq driver for i.MX");
-MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-mxc/cpuidle.c b/arch/arm/plat-mxc/cpuidle.c
deleted file mode 100644
index d4cb511..0000000
--- a/arch/arm/plat-mxc/cpuidle.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2012 Freescale Semiconductor, Inc.
- * Copyright 2012 Linaro Ltd.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/cpuidle.h>
-#include <linux/err.h>
-#include <linux/hrtimer.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-
-static struct cpuidle_device __percpu * imx_cpuidle_devices;
-
-static void __init imx_cpuidle_devices_uninit(void)
-{
-	int cpu_id;
-	struct cpuidle_device *dev;
-
-	for_each_possible_cpu(cpu_id) {
-		dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id);
-		cpuidle_unregister_device(dev);
-	}
-
-	free_percpu(imx_cpuidle_devices);
-}
-
-int __init imx_cpuidle_init(struct cpuidle_driver *drv)
-{
-	struct cpuidle_device *dev;
-	int cpu_id, ret;
-
-	if (drv->state_count > CPUIDLE_STATE_MAX) {
-		pr_err("%s: state_count exceeds maximum\n", __func__);
-		return -EINVAL;
-	}
-
-	ret = cpuidle_register_driver(drv);
-	if (ret) {
-		pr_err("%s: Failed to register cpuidle driver with error: %d\n",
-			 __func__, ret);
-		return ret;
-	}
-
-	imx_cpuidle_devices = alloc_percpu(struct cpuidle_device);
-	if (imx_cpuidle_devices == NULL) {
-		ret = -ENOMEM;
-		goto unregister_drv;
-	}
-
-	/* initialize state data for each cpuidle_device */
-	for_each_possible_cpu(cpu_id) {
-		dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id);
-		dev->cpu = cpu_id;
-		dev->state_count = drv->state_count;
-
-		ret = cpuidle_register_device(dev);
-		if (ret) {
-			pr_err("%s: Failed to register cpu %u, error: %d\n",
-				__func__, cpu_id, ret);
-			goto uninit;
-		}
-	}
-
-	return 0;
-
-uninit:
-	imx_cpuidle_devices_uninit();
-
-unregister_drv:
-	cpuidle_unregister_driver(drv);
-	return ret;
-}
diff --git a/arch/arm/plat-mxc/devices.c b/arch/arm/plat-mxc/devices.c
deleted file mode 100644
index 4d55a7a..0000000
--- a/arch/arm/plat-mxc/devices.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2008 Sascha Hauer, kernel@pengutronix.de
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA  02110-1301, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <mach/common.h>
-
-struct device mxc_aips_bus = {
-	.init_name	= "mxc_aips",
-	.parent		= &platform_bus,
-};
-
-struct device mxc_ahb_bus = {
-	.init_name	= "mxc_ahb",
-	.parent		= &platform_bus,
-};
-
-static int __init mxc_device_init(void)
-{
-	int ret;
-
-	ret = device_register(&mxc_aips_bus);
-	if (IS_ERR_VALUE(ret))
-		goto done;
-
-	ret = device_register(&mxc_ahb_bus);
-
-done:
-	return ret;
-}
-core_initcall(mxc_device_init);
diff --git a/arch/arm/plat-mxc/devices/Kconfig b/arch/arm/plat-mxc/devices/Kconfig
deleted file mode 100644
index a35d984..0000000
--- a/arch/arm/plat-mxc/devices/Kconfig
+++ /dev/null
@@ -1,89 +0,0 @@
-config IMX_HAVE_PLATFORM_FEC
-	bool
-	default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX50 || SOC_IMX51 || SOC_IMX53
-
-config IMX_HAVE_PLATFORM_FLEXCAN
-	bool
-	select HAVE_CAN_FLEXCAN if CAN
-
-config IMX_HAVE_PLATFORM_FSL_USB2_UDC
-	bool
-
-config IMX_HAVE_PLATFORM_GPIO_KEYS
-	bool
-	default y if SOC_IMX51
-
-config IMX_HAVE_PLATFORM_IMX21_HCD
-	bool
-
-config IMX_HAVE_PLATFORM_IMX27_CODA
-	bool
-	default y if SOC_IMX27
-
-config IMX_HAVE_PLATFORM_IMX2_WDT
-	bool
-
-config IMX_HAVE_PLATFORM_IMXDI_RTC
-	bool
-
-config IMX_HAVE_PLATFORM_IMX_FB
-	bool
-
-config IMX_HAVE_PLATFORM_IMX_I2C
-	bool
-
-config IMX_HAVE_PLATFORM_IMX_KEYPAD
-	bool
-
-config IMX_HAVE_PLATFORM_PATA_IMX
-	bool
-
-config IMX_HAVE_PLATFORM_IMX_SSI
-	bool
-
-config IMX_HAVE_PLATFORM_IMX_UART
-	bool
-
-config IMX_HAVE_PLATFORM_IMX_UDC
-	bool
-
-config IMX_HAVE_PLATFORM_IPU_CORE
-	bool
-
-config IMX_HAVE_PLATFORM_MX1_CAMERA
-	bool
-
-config IMX_HAVE_PLATFORM_MX2_CAMERA
-	bool
-
-config IMX_HAVE_PLATFORM_MXC_EHCI
-	bool
-
-config IMX_HAVE_PLATFORM_MXC_MMC
-	bool
-
-config IMX_HAVE_PLATFORM_MXC_NAND
-	bool
-
-config IMX_HAVE_PLATFORM_MXC_PWM
-	bool
-
-config IMX_HAVE_PLATFORM_MXC_RNGA
-	bool
-	select ARCH_HAS_RNGA
-
-config IMX_HAVE_PLATFORM_MXC_RTC
-	bool
-
-config IMX_HAVE_PLATFORM_MXC_W1
-	bool
-
-config IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	bool
-
-config IMX_HAVE_PLATFORM_SPI_IMX
-	bool
-
-config IMX_HAVE_PLATFORM_AHCI
-	bool
-	default y if ARCH_MX53
diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile
deleted file mode 100644
index 76f3195..0000000
--- a/arch/arm/plat-mxc/devices/Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
-obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC) += platform-fsl-usb2-udc.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_GPIO_KEYS) += platform-gpio_keys.o
-obj-y += platform-gpio-mxc.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX21_HCD) += platform-imx21-hcd.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX27_CODA) += platform-imx27-coda.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT) += platform-imx2-wdt.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_IMXDI_RTC) += platform-imxdi_rtc.o
-obj-y += platform-imx-dma.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_FB) += platform-imx-fb.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_I2C) += platform-imx-i2c.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_KEYPAD) += platform-imx-keypad.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_PATA_IMX) += platform-pata_imx.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_SSI) += platform-imx-ssi.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UART) += platform-imx-uart.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UDC) += platform-imx_udc.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_IPU_CORE) += platform-ipu-core.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_MX1_CAMERA) += platform-mx1-camera.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_MX2_CAMERA) += platform-mx2-camera.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_EHCI) += platform-mxc-ehci.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_MMC) += platform-mxc-mmc.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_NAND) += platform-mxc_nand.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_PWM) += platform-mxc_pwm.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_RNGA) += platform-mxc_rnga.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_RTC) += platform-mxc_rtc.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_W1) += platform-mxc_w1.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX) += platform-sdhci-esdhc-imx.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_SPI_IMX) +=  platform-spi_imx.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_AHCI) +=  platform-ahci-imx.o
diff --git a/arch/arm/plat-mxc/devices/platform-ahci-imx.c b/arch/arm/plat-mxc/devices/platform-ahci-imx.c
deleted file mode 100644
index ade4a1c..0000000
--- a/arch/arm/plat-mxc/devices/platform-ahci-imx.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <asm/sizes.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_ahci_imx_data_entry_single(soc, _devid)		\
-	{								\
-		.devid = _devid,					\
-		.iobase = soc ## _SATA_BASE_ADDR,			\
-		.irq = soc ## _INT_SATA,				\
-	}
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_ahci_imx_data imx53_ahci_imx_data __initconst =
-	imx_ahci_imx_data_entry_single(MX53, "imx53-ahci");
-#endif
-
-enum {
-	HOST_CAP = 0x00,
-	HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
-	HOST_PORTS_IMPL	= 0x0c,
-	HOST_TIMER1MS = 0xe0, /* Timer 1-ms */
-};
-
-static struct clk *sata_clk, *sata_ref_clk;
-
-/* AHCI module Initialization, if return 0, initialization is successful. */
-static int imx_sata_init(struct device *dev, void __iomem *addr)
-{
-	u32 tmpdata;
-	int ret = 0;
-	struct clk *clk;
-
-	sata_clk = clk_get(dev, "ahci");
-	if (IS_ERR(sata_clk)) {
-		dev_err(dev, "no sata clock.\n");
-		return PTR_ERR(sata_clk);
-	}
-	ret = clk_prepare_enable(sata_clk);
-	if (ret) {
-		dev_err(dev, "can't prepare/enable sata clock.\n");
-		goto put_sata_clk;
-	}
-
-	/* Get the AHCI SATA PHY CLK */
-	sata_ref_clk = clk_get(dev, "ahci_phy");
-	if (IS_ERR(sata_ref_clk)) {
-		dev_err(dev, "no sata ref clock.\n");
-		ret = PTR_ERR(sata_ref_clk);
-		goto release_sata_clk;
-	}
-	ret = clk_prepare_enable(sata_ref_clk);
-	if (ret) {
-		dev_err(dev, "can't prepare/enable sata ref clock.\n");
-		goto put_sata_ref_clk;
-	}
-
-	/* Get the AHB clock rate, and configure the TIMER1MS reg later */
-	clk = clk_get(dev, "ahci_dma");
-	if (IS_ERR(clk)) {
-		dev_err(dev, "no dma clock.\n");
-		ret = PTR_ERR(clk);
-		goto release_sata_ref_clk;
-	}
-	tmpdata = clk_get_rate(clk) / 1000;
-	clk_put(clk);
-
-	writel(tmpdata, addr + HOST_TIMER1MS);
-
-	tmpdata = readl(addr + HOST_CAP);
-	if (!(tmpdata & HOST_CAP_SSS)) {
-		tmpdata |= HOST_CAP_SSS;
-		writel(tmpdata, addr + HOST_CAP);
-	}
-
-	if (!(readl(addr + HOST_PORTS_IMPL) & 0x1))
-		writel((readl(addr + HOST_PORTS_IMPL) | 0x1),
-			addr + HOST_PORTS_IMPL);
-
-	return 0;
-
-release_sata_ref_clk:
-	clk_disable_unprepare(sata_ref_clk);
-put_sata_ref_clk:
-	clk_put(sata_ref_clk);
-release_sata_clk:
-	clk_disable_unprepare(sata_clk);
-put_sata_clk:
-	clk_put(sata_clk);
-
-	return ret;
-}
-
-static void imx_sata_exit(struct device *dev)
-{
-	clk_disable_unprepare(sata_ref_clk);
-	clk_put(sata_ref_clk);
-
-	clk_disable_unprepare(sata_clk);
-	clk_put(sata_clk);
-
-}
-struct platform_device *__init imx_add_ahci_imx(
-		const struct imx_ahci_imx_data *data,
-		const struct ahci_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + SZ_4K - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return imx_add_platform_device_dmamask(data->devid, 0,
-			res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata),  DMA_BIT_MASK(32));
-}
-
-struct platform_device *__init imx53_add_ahci_imx(void)
-{
-	struct ahci_platform_data pdata = {
-		.init = imx_sata_init,
-		.exit = imx_sata_exit,
-	};
-
-	return imx_add_ahci_imx(&imx53_ahci_imx_data, &pdata);
-}
diff --git a/arch/arm/plat-mxc/devices/platform-fec.c b/arch/arm/plat-mxc/devices/platform-fec.c
deleted file mode 100644
index 0bae44e..0000000
--- a/arch/arm/plat-mxc/devices/platform-fec.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <linux/dma-mapping.h>
-#include <asm/sizes.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_fec_data_entry_single(soc, _devid)				\
-	{								\
-		.devid = _devid,					\
-		.iobase = soc ## _FEC_BASE_ADDR,			\
-		.irq = soc ## _INT_FEC,					\
-	}
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_fec_data imx25_fec_data __initconst =
-	imx_fec_data_entry_single(MX25, "imx25-fec");
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_fec_data imx27_fec_data __initconst =
-	imx_fec_data_entry_single(MX27, "imx27-fec");
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-#ifdef CONFIG_SOC_IMX35
-/* i.mx35 has the i.mx27 type fec */
-const struct imx_fec_data imx35_fec_data __initconst =
-	imx_fec_data_entry_single(MX35, "imx27-fec");
-#endif
-
-#ifdef CONFIG_SOC_IMX50
-/* i.mx50 has the i.mx25 type fec */
-const struct imx_fec_data imx50_fec_data __initconst =
-	imx_fec_data_entry_single(MX50, "imx25-fec");
-#endif
-
-#ifdef CONFIG_SOC_IMX51
-/* i.mx51 has the i.mx27 type fec */
-const struct imx_fec_data imx51_fec_data __initconst =
-	imx_fec_data_entry_single(MX51, "imx27-fec");
-#endif
-
-#ifdef CONFIG_SOC_IMX53
-/* i.mx53 has the i.mx25 type fec */
-const struct imx_fec_data imx53_fec_data __initconst =
-	imx_fec_data_entry_single(MX53, "imx25-fec");
-#endif
-
-struct platform_device *__init imx_add_fec(
-		const struct imx_fec_data *data,
-		const struct fec_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + SZ_4K - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return imx_add_platform_device_dmamask(data->devid, 0,
-			res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-flexcan.c b/arch/arm/plat-mxc/devices/platform-flexcan.c
deleted file mode 100644
index 4e8497a..0000000
--- a/arch/arm/plat-mxc/devices/platform-flexcan.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_flexcan_data_entry_single(soc, _id, _hwid, _size)		\
-	{								\
-		.id = _id,						\
-		.iobase = soc ## _CAN ## _hwid ## _BASE_ADDR,		\
-		.iosize = _size,					\
-		.irq = soc ## _INT_CAN ## _hwid,			\
-	}
-
-#define imx_flexcan_data_entry(soc, _id, _hwid, _size)			\
-	[_id] = imx_flexcan_data_entry_single(soc, _id, _hwid, _size)
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_flexcan_data imx25_flexcan_data[] __initconst = {
-#define imx25_flexcan_data_entry(_id, _hwid)				\
-	imx_flexcan_data_entry(MX25, _id, _hwid, SZ_16K)
-	imx25_flexcan_data_entry(0, 1),
-	imx25_flexcan_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-#ifdef CONFIG_SOC_IMX35
-const struct imx_flexcan_data imx35_flexcan_data[] __initconst = {
-#define imx35_flexcan_data_entry(_id, _hwid)				\
-	imx_flexcan_data_entry(MX35, _id, _hwid, SZ_16K)
-	imx35_flexcan_data_entry(0, 1),
-	imx35_flexcan_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX35 */
-
-struct platform_device *__init imx_add_flexcan(
-		const struct imx_flexcan_data *data,
-		const struct flexcan_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return imx_add_platform_device("flexcan", data->id,
-			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
deleted file mode 100644
index 848038f..0000000
--- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <linux/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_fsl_usb2_udc_data_entry_single(soc)				\
-	{								\
-		.iobase = soc ## _USB_OTG_BASE_ADDR,			\
-		.irq = soc ## _INT_USB_OTG,				\
-	}
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data __initconst =
-	imx_fsl_usb2_udc_data_entry_single(MX25);
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_fsl_usb2_udc_data imx27_fsl_usb2_udc_data __initconst =
-	imx_fsl_usb2_udc_data_entry_single(MX27);
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-#ifdef CONFIG_SOC_IMX31
-const struct imx_fsl_usb2_udc_data imx31_fsl_usb2_udc_data __initconst =
-	imx_fsl_usb2_udc_data_entry_single(MX31);
-#endif /* ifdef CONFIG_SOC_IMX31 */
-
-#ifdef CONFIG_SOC_IMX35
-const struct imx_fsl_usb2_udc_data imx35_fsl_usb2_udc_data __initconst =
-	imx_fsl_usb2_udc_data_entry_single(MX35);
-#endif /* ifdef CONFIG_SOC_IMX35 */
-
-#ifdef CONFIG_SOC_IMX51
-const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data __initconst =
-	imx_fsl_usb2_udc_data_entry_single(MX51);
-#endif
-
-struct platform_device *__init imx_add_fsl_usb2_udc(
-		const struct imx_fsl_usb2_udc_data *data,
-		const struct fsl_usb2_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + SZ_512 - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-	return imx_add_platform_device_dmamask("fsl-usb2-udc", -1,
-			res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-gpio-mxc.c b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
deleted file mode 100644
index a7919a2..0000000
--- a/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2011 Linaro Limited
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/devices-common.h>
-
-struct platform_device *__init mxc_register_gpio(char *name, int id,
-	resource_size_t iobase, resource_size_t iosize, int irq, int irq_high)
-{
-	struct resource res[] = {
-		{
-			.start = iobase,
-			.end = iobase + iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = irq,
-			.end = irq,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = irq_high,
-			.end = irq_high,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return platform_device_register_resndata(&mxc_aips_bus,
-			name, id, res, ARRAY_SIZE(res), NULL, 0);
-}
diff --git a/arch/arm/plat-mxc/devices/platform-gpio_keys.c b/arch/arm/plat-mxc/devices/platform-gpio_keys.c
deleted file mode 100644
index 1c53a53..0000000
--- a/arch/arm/plat-mxc/devices/platform-gpio_keys.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA  02110-1301, USA.
- */
-#include <asm/sizes.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-struct platform_device *__init imx_add_gpio_keys(
-		const struct gpio_keys_platform_data *pdata)
-{
-	return imx_add_platform_device("gpio-keys", -1, NULL,
-		 0, pdata, sizeof(*pdata));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-dma.c b/arch/arm/plat-mxc/devices/platform-imx-dma.c
deleted file mode 100644
index 7fa7e9c..0000000
--- a/arch/arm/plat-mxc/devices/platform-imx-dma.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/devices-common.h>
-
-struct platform_device __init __maybe_unused *imx_add_imx_dma(void)
-{
-	return platform_device_register_resndata(&mxc_ahb_bus,
-			"imx-dma", -1, NULL, 0, NULL, 0);
-}
-
-struct platform_device __init __maybe_unused *imx_add_imx_sdma(char *name,
-	resource_size_t iobase, int irq, struct sdma_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = iobase,
-			.end = iobase + SZ_16K - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = irq,
-			.end = irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return platform_device_register_resndata(&mxc_ahb_bus, name,
-			-1, res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-fb.c b/arch/arm/plat-mxc/devices/platform-imx-fb.c
deleted file mode 100644
index 2b0b5e0..0000000
--- a/arch/arm/plat-mxc/devices/platform-imx-fb.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <linux/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_imx_fb_data_entry_single(soc, _size)			\
-	{								\
-		.iobase = soc ## _LCDC_BASE_ADDR,			\
-		.iosize = _size,					\
-		.irq = soc ## _INT_LCDC,				\
-	}
-
-#ifdef CONFIG_SOC_IMX1
-const struct imx_imx_fb_data imx1_imx_fb_data __initconst =
-	imx_imx_fb_data_entry_single(MX1, SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX1 */
-
-#ifdef CONFIG_SOC_IMX21
-const struct imx_imx_fb_data imx21_imx_fb_data __initconst =
-	imx_imx_fb_data_entry_single(MX21, SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX21 */
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_imx_fb_data imx25_imx_fb_data __initconst =
-	imx_imx_fb_data_entry_single(MX25, SZ_16K);
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_imx_fb_data imx27_imx_fb_data __initconst =
-	imx_imx_fb_data_entry_single(MX27, SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-struct platform_device *__init imx_add_imx_fb(
-		const struct imx_imx_fb_data *data,
-		const struct imx_fb_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-	return imx_add_platform_device_dmamask("imx-fb", 0,
-			res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-i2c.c b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
deleted file mode 100644
index 19ad580..0000000
--- a/arch/arm/plat-mxc/devices/platform-imx-i2c.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_imx_i2c_data_entry_single(soc, _id, _hwid, _size)		\
-	{								\
-		.id = _id,						\
-		.iobase = soc ## _I2C ## _hwid ## _BASE_ADDR,		\
-		.iosize = _size,					\
-		.irq = soc ## _INT_I2C ## _hwid,			\
-	}
-
-#define imx_imx_i2c_data_entry(soc, _id, _hwid, _size)			\
-	[_id] = imx_imx_i2c_data_entry_single(soc, _id, _hwid, _size)
-
-#ifdef CONFIG_SOC_IMX1
-const struct imx_imx_i2c_data imx1_imx_i2c_data __initconst =
-	imx_imx_i2c_data_entry_single(MX1, 0, , SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX1 */
-
-#ifdef CONFIG_SOC_IMX21
-const struct imx_imx_i2c_data imx21_imx_i2c_data __initconst =
-	imx_imx_i2c_data_entry_single(MX21, 0, , SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX21 */
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_imx_i2c_data imx25_imx_i2c_data[] __initconst = {
-#define imx25_imx_i2c_data_entry(_id, _hwid)				\
-	imx_imx_i2c_data_entry(MX25, _id, _hwid, SZ_16K)
-	imx25_imx_i2c_data_entry(0, 1),
-	imx25_imx_i2c_data_entry(1, 2),
-	imx25_imx_i2c_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_imx_i2c_data imx27_imx_i2c_data[] __initconst = {
-#define imx27_imx_i2c_data_entry(_id, _hwid)				\
-	imx_imx_i2c_data_entry(MX27, _id, _hwid, SZ_4K)
-	imx27_imx_i2c_data_entry(0, 1),
-	imx27_imx_i2c_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-#ifdef CONFIG_SOC_IMX31
-const struct imx_imx_i2c_data imx31_imx_i2c_data[] __initconst = {
-#define imx31_imx_i2c_data_entry(_id, _hwid)				\
-	imx_imx_i2c_data_entry(MX31, _id, _hwid, SZ_4K)
-	imx31_imx_i2c_data_entry(0, 1),
-	imx31_imx_i2c_data_entry(1, 2),
-	imx31_imx_i2c_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX31 */
-
-#ifdef CONFIG_SOC_IMX35
-const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst = {
-#define imx35_imx_i2c_data_entry(_id, _hwid)				\
-	imx_imx_i2c_data_entry(MX35, _id, _hwid, SZ_4K)
-	imx35_imx_i2c_data_entry(0, 1),
-	imx35_imx_i2c_data_entry(1, 2),
-	imx35_imx_i2c_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX35 */
-
-#ifdef CONFIG_SOC_IMX50
-const struct imx_imx_i2c_data imx50_imx_i2c_data[] __initconst = {
-#define imx50_imx_i2c_data_entry(_id, _hwid)				\
-	imx_imx_i2c_data_entry(MX50, _id, _hwid, SZ_4K)
-	imx50_imx_i2c_data_entry(0, 1),
-	imx50_imx_i2c_data_entry(1, 2),
-	imx50_imx_i2c_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX51
-const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = {
-#define imx51_imx_i2c_data_entry(_id, _hwid)				\
-	imx_imx_i2c_data_entry(MX51, _id, _hwid, SZ_4K)
-	imx51_imx_i2c_data_entry(0, 1),
-	imx51_imx_i2c_data_entry(1, 2),
-	{
-		.id = 2,
-		.iobase = MX51_HSI2C_DMA_BASE_ADDR,
-		.iosize = SZ_16K,
-		.irq = MX51_INT_HS_I2C,
-	},
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_imx_i2c_data imx53_imx_i2c_data[] __initconst = {
-#define imx53_imx_i2c_data_entry(_id, _hwid)				\
-	imx_imx_i2c_data_entry(MX53, _id, _hwid, SZ_4K)
-	imx53_imx_i2c_data_entry(0, 1),
-	imx53_imx_i2c_data_entry(1, 2),
-	imx53_imx_i2c_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
-struct platform_device *__init imx_add_imx_i2c(
-		const struct imx_imx_i2c_data *data,
-		const struct imxi2c_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return imx_add_platform_device("imx-i2c", data->id,
-			res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-keypad.c b/arch/arm/plat-mxc/devices/platform-imx-keypad.c
deleted file mode 100644
index 479c3e9..0000000
--- a/arch/arm/plat-mxc/devices/platform-imx-keypad.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_imx_keypad_data_entry_single(soc, _size)			\
-	{								\
-		.iobase = soc ## _KPP_BASE_ADDR,			\
-		.iosize = _size,					\
-		.irq = soc ## _INT_KPP,					\
-	}
-
-#ifdef CONFIG_SOC_IMX21
-const struct imx_imx_keypad_data imx21_imx_keypad_data __initconst =
-	imx_imx_keypad_data_entry_single(MX21, SZ_16);
-#endif /* ifdef CONFIG_SOC_IMX21 */
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_imx_keypad_data imx25_imx_keypad_data __initconst =
-	imx_imx_keypad_data_entry_single(MX25, SZ_16K);
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_imx_keypad_data imx27_imx_keypad_data __initconst =
-	imx_imx_keypad_data_entry_single(MX27, SZ_16);
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-#ifdef CONFIG_SOC_IMX31
-const struct imx_imx_keypad_data imx31_imx_keypad_data __initconst =
-	imx_imx_keypad_data_entry_single(MX31, SZ_16);
-#endif /* ifdef CONFIG_SOC_IMX31 */
-
-#ifdef CONFIG_SOC_IMX35
-const struct imx_imx_keypad_data imx35_imx_keypad_data __initconst =
-	imx_imx_keypad_data_entry_single(MX35, SZ_16);
-#endif /* ifdef CONFIG_SOC_IMX35 */
-
-#ifdef CONFIG_SOC_IMX51
-const struct imx_imx_keypad_data imx51_imx_keypad_data __initconst =
-	imx_imx_keypad_data_entry_single(MX51, SZ_16);
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_imx_keypad_data imx53_imx_keypad_data __initconst =
-	imx_imx_keypad_data_entry_single(MX53, SZ_16);
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
-struct platform_device *__init imx_add_imx_keypad(
-		const struct imx_imx_keypad_data *data,
-		const struct matrix_keymap_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return imx_add_platform_device("imx-keypad", -1,
-			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-ssi.c b/arch/arm/plat-mxc/devices/platform-imx-ssi.c
deleted file mode 100644
index 21c6f30..0000000
--- a/arch/arm/plat-mxc/devices/platform-imx-ssi.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_imx_ssi_data_entry(soc, _id, _hwid, _size)			\
-	[_id] = {							\
-		.id = _id,						\
-		.iobase = soc ## _SSI ## _hwid ## _BASE_ADDR,		\
-		.iosize = _size,					\
-		.irq = soc ## _INT_SSI ## _hwid,			\
-		.dmatx0 = soc ## _DMA_REQ_SSI ## _hwid ## _TX0,		\
-		.dmarx0 = soc ## _DMA_REQ_SSI ## _hwid ## _RX0,		\
-		.dmatx1 = soc ## _DMA_REQ_SSI ## _hwid ## _TX1,		\
-		.dmarx1 = soc ## _DMA_REQ_SSI ## _hwid ## _RX1,		\
-	}
-
-#ifdef CONFIG_SOC_IMX21
-const struct imx_imx_ssi_data imx21_imx_ssi_data[] __initconst = {
-#define imx21_imx_ssi_data_entry(_id, _hwid)				\
-	imx_imx_ssi_data_entry(MX21, _id, _hwid, SZ_4K)
-	imx21_imx_ssi_data_entry(0, 1),
-	imx21_imx_ssi_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX21 */
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_imx_ssi_data imx25_imx_ssi_data[] __initconst = {
-#define imx25_imx_ssi_data_entry(_id, _hwid)				\
-	imx_imx_ssi_data_entry(MX25, _id, _hwid, SZ_4K)
-	imx25_imx_ssi_data_entry(0, 1),
-	imx25_imx_ssi_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_imx_ssi_data imx27_imx_ssi_data[] __initconst = {
-#define imx27_imx_ssi_data_entry(_id, _hwid)				\
-	imx_imx_ssi_data_entry(MX27, _id, _hwid, SZ_4K)
-	imx27_imx_ssi_data_entry(0, 1),
-	imx27_imx_ssi_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-#ifdef CONFIG_SOC_IMX31
-const struct imx_imx_ssi_data imx31_imx_ssi_data[] __initconst = {
-#define imx31_imx_ssi_data_entry(_id, _hwid)				\
-	imx_imx_ssi_data_entry(MX31, _id, _hwid, SZ_4K)
-	imx31_imx_ssi_data_entry(0, 1),
-	imx31_imx_ssi_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX31 */
-
-#ifdef CONFIG_SOC_IMX35
-const struct imx_imx_ssi_data imx35_imx_ssi_data[] __initconst = {
-#define imx35_imx_ssi_data_entry(_id, _hwid)				\
-	imx_imx_ssi_data_entry(MX35, _id, _hwid, SZ_4K)
-	imx35_imx_ssi_data_entry(0, 1),
-	imx35_imx_ssi_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX35 */
-
-#ifdef CONFIG_SOC_IMX51
-const struct imx_imx_ssi_data imx51_imx_ssi_data[] __initconst = {
-#define imx51_imx_ssi_data_entry(_id, _hwid)				\
-	imx_imx_ssi_data_entry(MX51, _id, _hwid, SZ_16K)
-	imx51_imx_ssi_data_entry(0, 1),
-	imx51_imx_ssi_data_entry(1, 2),
-	imx51_imx_ssi_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_imx_ssi_data imx53_imx_ssi_data[] __initconst = {
-#define imx53_imx_ssi_data_entry(_id, _hwid)				\
-	imx_imx_ssi_data_entry(MX53, _id, _hwid, SZ_16K)
-	imx53_imx_ssi_data_entry(0, 1),
-	imx53_imx_ssi_data_entry(1, 2),
-	imx53_imx_ssi_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
-struct platform_device *__init imx_add_imx_ssi(
-		const struct imx_imx_ssi_data *data,
-		const struct imx_ssi_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-#define DMARES(_name) {							\
-	.name = #_name,							\
-	.start = data->dma ## _name,					\
-	.end = data->dma ## _name,					\
-	.flags = IORESOURCE_DMA,					\
-}
-		DMARES(tx0),
-		DMARES(rx0),
-		DMARES(tx1),
-		DMARES(rx1),
-	};
-
-	return imx_add_platform_device("imx-ssi", data->id,
-			res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-uart.c b/arch/arm/plat-mxc/devices/platform-imx-uart.c
deleted file mode 100644
index d390f00..0000000
--- a/arch/arm/plat-mxc/devices/platform-imx-uart.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_imx_uart_3irq_data_entry(soc, _id, _hwid, _size)		\
-	[_id] = {							\
-		.id = _id,						\
-		.iobase = soc ## _UART ## _hwid ## _BASE_ADDR,		\
-		.iosize = _size,					\
-		.irqrx = soc ## _INT_UART ## _hwid ## RX,		\
-		.irqtx = soc ## _INT_UART ## _hwid ## TX,		\
-		.irqrts = soc ## _INT_UART ## _hwid ## RTS,		\
-	}
-
-#define imx_imx_uart_1irq_data_entry(soc, _id, _hwid, _size)		\
-	[_id] = {							\
-		.id = _id,						\
-		.iobase = soc ## _UART ## _hwid ## _BASE_ADDR,		\
-		.iosize = _size,					\
-		.irq = soc ## _INT_UART ## _hwid,			\
-	}
-
-#ifdef CONFIG_SOC_IMX1
-const struct imx_imx_uart_3irq_data imx1_imx_uart_data[] __initconst = {
-#define imx1_imx_uart_data_entry(_id, _hwid)				\
-	imx_imx_uart_3irq_data_entry(MX1, _id, _hwid, 0xd0)
-	imx1_imx_uart_data_entry(0, 1),
-	imx1_imx_uart_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX1 */
-
-#ifdef CONFIG_SOC_IMX21
-const struct imx_imx_uart_1irq_data imx21_imx_uart_data[] __initconst = {
-#define imx21_imx_uart_data_entry(_id, _hwid)				\
-	imx_imx_uart_1irq_data_entry(MX21, _id, _hwid, SZ_4K)
-	imx21_imx_uart_data_entry(0, 1),
-	imx21_imx_uart_data_entry(1, 2),
-	imx21_imx_uart_data_entry(2, 3),
-	imx21_imx_uart_data_entry(3, 4),
-};
-#endif
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_imx_uart_1irq_data imx25_imx_uart_data[] __initconst = {
-#define imx25_imx_uart_data_entry(_id, _hwid)				\
-	imx_imx_uart_1irq_data_entry(MX25, _id, _hwid, SZ_16K)
-	imx25_imx_uart_data_entry(0, 1),
-	imx25_imx_uart_data_entry(1, 2),
-	imx25_imx_uart_data_entry(2, 3),
-	imx25_imx_uart_data_entry(3, 4),
-	imx25_imx_uart_data_entry(4, 5),
-};
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_imx_uart_1irq_data imx27_imx_uart_data[] __initconst = {
-#define imx27_imx_uart_data_entry(_id, _hwid)				\
-	imx_imx_uart_1irq_data_entry(MX27, _id, _hwid, SZ_4K)
-	imx27_imx_uart_data_entry(0, 1),
-	imx27_imx_uart_data_entry(1, 2),
-	imx27_imx_uart_data_entry(2, 3),
-	imx27_imx_uart_data_entry(3, 4),
-	imx27_imx_uart_data_entry(4, 5),
-	imx27_imx_uart_data_entry(5, 6),
-};
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-#ifdef CONFIG_SOC_IMX31
-const struct imx_imx_uart_1irq_data imx31_imx_uart_data[] __initconst = {
-#define imx31_imx_uart_data_entry(_id, _hwid)				\
-	imx_imx_uart_1irq_data_entry(MX31, _id, _hwid, SZ_4K)
-	imx31_imx_uart_data_entry(0, 1),
-	imx31_imx_uart_data_entry(1, 2),
-	imx31_imx_uart_data_entry(2, 3),
-	imx31_imx_uart_data_entry(3, 4),
-	imx31_imx_uart_data_entry(4, 5),
-};
-#endif /* ifdef CONFIG_SOC_IMX31 */
-
-#ifdef CONFIG_SOC_IMX35
-const struct imx_imx_uart_1irq_data imx35_imx_uart_data[] __initconst = {
-#define imx35_imx_uart_data_entry(_id, _hwid)				\
-	imx_imx_uart_1irq_data_entry(MX35, _id, _hwid, SZ_16K)
-	imx35_imx_uart_data_entry(0, 1),
-	imx35_imx_uart_data_entry(1, 2),
-	imx35_imx_uart_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX35 */
-
-#ifdef CONFIG_SOC_IMX50
-const struct imx_imx_uart_1irq_data imx50_imx_uart_data[] __initconst = {
-#define imx50_imx_uart_data_entry(_id, _hwid)				\
-	imx_imx_uart_1irq_data_entry(MX50, _id, _hwid, SZ_4K)
-	imx50_imx_uart_data_entry(0, 1),
-	imx50_imx_uart_data_entry(1, 2),
-	imx50_imx_uart_data_entry(2, 3),
-	imx50_imx_uart_data_entry(3, 4),
-	imx50_imx_uart_data_entry(4, 5),
-};
-#endif /* ifdef CONFIG_SOC_IMX50 */
-
-#ifdef CONFIG_SOC_IMX51
-const struct imx_imx_uart_1irq_data imx51_imx_uart_data[] __initconst = {
-#define imx51_imx_uart_data_entry(_id, _hwid)				\
-	imx_imx_uart_1irq_data_entry(MX51, _id, _hwid, SZ_4K)
-	imx51_imx_uart_data_entry(0, 1),
-	imx51_imx_uart_data_entry(1, 2),
-	imx51_imx_uart_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_imx_uart_1irq_data imx53_imx_uart_data[] __initconst = {
-#define imx53_imx_uart_data_entry(_id, _hwid)				\
-	imx_imx_uart_1irq_data_entry(MX53, _id, _hwid, SZ_4K)
-	imx53_imx_uart_data_entry(0, 1),
-	imx53_imx_uart_data_entry(1, 2),
-	imx53_imx_uart_data_entry(2, 3),
-	imx53_imx_uart_data_entry(3, 4),
-	imx53_imx_uart_data_entry(4, 5),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
-struct platform_device *__init imx_add_imx_uart_3irq(
-		const struct imx_imx_uart_3irq_data *data,
-		const struct imxuart_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irqrx,
-			.end = data->irqrx,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->irqtx,
-			.end = data->irqtx,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->irqrts,
-			.end = data->irqrx,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return imx_add_platform_device("imx1-uart", data->id, res,
-			ARRAY_SIZE(res), pdata, sizeof(*pdata));
-}
-
-struct platform_device *__init imx_add_imx_uart_1irq(
-		const struct imx_imx_uart_1irq_data *data,
-		const struct imxuart_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	/* i.mx21 type uart runs on all i.mx except i.mx1 */
-	return imx_add_platform_device("imx21-uart", data->id,
-			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-imx2-wdt.c b/arch/arm/plat-mxc/devices/platform-imx2-wdt.c
deleted file mode 100644
index 5e07ef2..0000000
--- a/arch/arm/plat-mxc/devices/platform-imx2-wdt.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <asm/sizes.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_imx2_wdt_data_entry_single(soc, _id, _hwid, _size)		\
-	{								\
-		.id = _id,						\
-		.iobase = soc ## _WDOG ## _hwid ## _BASE_ADDR,		\
-		.iosize = _size,					\
-	}
-#define imx_imx2_wdt_data_entry(soc, _id, _hwid, _size)			\
-	[_id] = imx_imx2_wdt_data_entry_single(soc, _id, _hwid, _size)
-
-#ifdef CONFIG_SOC_IMX21
-const struct imx_imx2_wdt_data imx21_imx2_wdt_data __initconst =
-	imx_imx2_wdt_data_entry_single(MX21, 0, , SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX21 */
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_imx2_wdt_data imx25_imx2_wdt_data __initconst =
-	imx_imx2_wdt_data_entry_single(MX25, 0, , SZ_16K);
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_imx2_wdt_data imx27_imx2_wdt_data __initconst =
-	imx_imx2_wdt_data_entry_single(MX27, 0, , SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-#ifdef CONFIG_SOC_IMX31
-const struct imx_imx2_wdt_data imx31_imx2_wdt_data __initconst =
-	imx_imx2_wdt_data_entry_single(MX31, 0, , SZ_16K);
-#endif /* ifdef CONFIG_SOC_IMX31 */
-
-#ifdef CONFIG_SOC_IMX35
-const struct imx_imx2_wdt_data imx35_imx2_wdt_data __initconst =
-	imx_imx2_wdt_data_entry_single(MX35, 0, , SZ_16K);
-#endif /* ifdef CONFIG_SOC_IMX35 */
-
-#ifdef CONFIG_SOC_IMX51
-const struct imx_imx2_wdt_data imx51_imx2_wdt_data[] __initconst = {
-#define imx51_imx2_wdt_data_entry(_id, _hwid)				\
-	imx_imx2_wdt_data_entry(MX51, _id, _hwid, SZ_16K)
-	imx51_imx2_wdt_data_entry(0, 1),
-	imx51_imx2_wdt_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_imx2_wdt_data imx53_imx2_wdt_data[] __initconst = {
-#define imx53_imx2_wdt_data_entry(_id, _hwid)				\
-	imx_imx2_wdt_data_entry(MX53, _id, _hwid, SZ_16K)
-	imx53_imx2_wdt_data_entry(0, 1),
-	imx53_imx2_wdt_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
-struct platform_device *__init imx_add_imx2_wdt(
-		const struct imx_imx2_wdt_data *data)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		},
-	};
-	return imx_add_platform_device("imx2-wdt", data->id,
-			res, ARRAY_SIZE(res), NULL, 0);
-}
diff --git a/arch/arm/plat-mxc/devices/platform-imx21-hcd.c b/arch/arm/plat-mxc/devices/platform-imx21-hcd.c
deleted file mode 100644
index 5770a42..0000000
--- a/arch/arm/plat-mxc/devices/platform-imx21-hcd.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_imx21_hcd_data_entry_single(soc)				\
-	{								\
-		.iobase = soc ## _USBOTG_BASE_ADDR,			\
-		.irq = soc ## _INT_USBHOST,				\
-	}
-
-#ifdef CONFIG_SOC_IMX21
-const struct imx_imx21_hcd_data imx21_imx21_hcd_data __initconst =
-	imx_imx21_hcd_data_entry_single(MX21);
-#endif /* ifdef CONFIG_SOC_IMX21 */
-
-struct platform_device *__init imx_add_imx21_hcd(
-		const struct imx_imx21_hcd_data *data,
-		const struct mx21_usbh_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + SZ_8K - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-	return imx_add_platform_device_dmamask("imx21-hcd", 0,
-			res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-imx27-coda.c b/arch/arm/plat-mxc/devices/platform-imx27-coda.c
deleted file mode 100644
index 8b12aac..0000000
--- a/arch/arm/plat-mxc/devices/platform-imx27-coda.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2012 Vista Silicon
- * Javier Martin <javier.martin@vista-silicon.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 <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_imx27_coda_data imx27_coda_data __initconst = {
-	.iobase = MX27_VPU_BASE_ADDR,
-	.iosize = SZ_512,
-	.irq = MX27_INT_VPU,
-};
-#endif
-
-struct platform_device *__init imx_add_imx27_coda(
-		const struct imx_imx27_coda_data *data)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-	return imx_add_platform_device_dmamask("coda-imx27", 0, res, 2, NULL,
-					0, DMA_BIT_MASK(32));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-imx_udc.c b/arch/arm/plat-mxc/devices/platform-imx_udc.c
deleted file mode 100644
index 6fd675d..0000000
--- a/arch/arm/plat-mxc/devices/platform-imx_udc.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_imx_udc_data_entry_single(soc, _size)			\
-	{								\
-		.iobase = soc ## _USBD_BASE_ADDR,			\
-		.iosize = _size,					\
-		.irq0 = soc ## _INT_USBD0,				\
-		.irq1 = soc ## _INT_USBD1,				\
-		.irq2 = soc ## _INT_USBD2,				\
-		.irq3 = soc ## _INT_USBD3,				\
-		.irq4 = soc ## _INT_USBD4,				\
-		.irq5 = soc ## _INT_USBD5,				\
-		.irq6 = soc ## _INT_USBD6,				\
-	}
-
-#define imx_imx_udc_data_entry(soc, _size)				\
-	[_id] = imx_imx_udc_data_entry_single(soc, _size)
-
-#ifdef CONFIG_SOC_IMX1
-const struct imx_imx_udc_data imx1_imx_udc_data __initconst =
-	imx_imx_udc_data_entry_single(MX1, SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX1 */
-
-struct platform_device *__init imx_add_imx_udc(
-		const struct imx_imx_udc_data *data,
-		const struct imxusb_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq0,
-			.end = data->irq0,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->irq1,
-			.end = data->irq1,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->irq2,
-			.end = data->irq2,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->irq3,
-			.end = data->irq3,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->irq4,
-			.end = data->irq4,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->irq5,
-			.end = data->irq5,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->irq6,
-			.end = data->irq6,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return imx_add_platform_device("imx_udc", 0,
-			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-imxdi_rtc.c b/arch/arm/plat-mxc/devices/platform-imxdi_rtc.c
deleted file mode 100644
index 805336f..0000000
--- a/arch/arm/plat-mxc/devices/platform-imxdi_rtc.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <asm/sizes.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_imxdi_rtc_data_entry_single(soc)				\
-	{								\
-		.iobase = soc ## _DRYICE_BASE_ADDR,			\
-		.irq = soc ## _INT_DRYICE,				\
-	}
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_imxdi_rtc_data imx25_imxdi_rtc_data __initconst =
-	imx_imxdi_rtc_data_entry_single(MX25);
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-struct platform_device *__init imx_add_imxdi_rtc(
-		const struct imx_imxdi_rtc_data *data)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + SZ_16K - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return imx_add_platform_device("imxdi_rtc", 0,
-			res, ARRAY_SIZE(res), NULL, 0);
-}
diff --git a/arch/arm/plat-mxc/devices/platform-ipu-core.c b/arch/arm/plat-mxc/devices/platform-ipu-core.c
deleted file mode 100644
index d1e33cc..0000000
--- a/arch/arm/plat-mxc/devices/platform-ipu-core.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2011 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/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_ipu_core_entry_single(soc)					\
-{									\
-	.iobase = soc ## _IPU_CTRL_BASE_ADDR,				\
-	.synirq = soc ## _INT_IPU_SYN,					\
-	.errirq = soc ## _INT_IPU_ERR,					\
-}
-
-#ifdef CONFIG_SOC_IMX31
-const struct imx_ipu_core_data imx31_ipu_core_data __initconst =
-	imx_ipu_core_entry_single(MX31);
-#endif
-
-#ifdef CONFIG_SOC_IMX35
-const struct imx_ipu_core_data imx35_ipu_core_data __initconst =
-	imx_ipu_core_entry_single(MX35);
-#endif
-
-static struct platform_device *imx_ipu_coredev __initdata;
-
-struct platform_device *__init imx_add_ipu_core(
-		const struct imx_ipu_core_data *data)
-{
-	/* The resource order is important! */
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + 0x5f,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->iobase + 0x88,
-			.end = data->iobase + 0xb3,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->synirq,
-			.end = data->synirq,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->errirq,
-			.end = data->errirq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return imx_ipu_coredev = imx_add_platform_device("ipu-core", -1,
-			res, ARRAY_SIZE(res), NULL, 0);
-}
-
-struct platform_device *__init imx_alloc_mx3_camera(
-		const struct imx_ipu_core_data *data,
-		const struct mx3_camera_pdata *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase + 0x60,
-			.end = data->iobase + 0x87,
-			.flags = IORESOURCE_MEM,
-		},
-	};
-	int ret = -ENOMEM;
-	struct platform_device *pdev;
-
-	if (IS_ERR_OR_NULL(imx_ipu_coredev))
-		return ERR_PTR(-ENODEV);
-
-	pdev = platform_device_alloc("mx3-camera", 0);
-	if (!pdev)
-		goto err;
-
-	pdev->dev.dma_mask = kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
-	if (!pdev->dev.dma_mask)
-		goto err;
-
-	*pdev->dev.dma_mask = DMA_BIT_MASK(32);
-	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-
-	ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
-	if (ret)
-		goto err;
-
-	if (pdata) {
-		struct mx3_camera_pdata *copied_pdata;
-
-		ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
-		if (ret) {
-err:
-			kfree(pdev->dev.dma_mask);
-			platform_device_put(pdev);
-			return ERR_PTR(-ENODEV);
-		}
-		copied_pdata = dev_get_platdata(&pdev->dev);
-		copied_pdata->dma_dev = &imx_ipu_coredev->dev;
-	}
-
-	return pdev;
-}
-
-struct platform_device *__init imx_add_mx3_sdc_fb(
-		const struct imx_ipu_core_data *data,
-		struct mx3fb_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase + 0xb4,
-			.end = data->iobase + 0x1bf,
-			.flags = IORESOURCE_MEM,
-		},
-	};
-
-	if (IS_ERR_OR_NULL(imx_ipu_coredev))
-		return ERR_PTR(-ENODEV);
-
-	pdata->dma_dev = &imx_ipu_coredev->dev;
-
-	return imx_add_platform_device_dmamask("mx3_sdc_fb", -1,
-			res, ARRAY_SIZE(res), pdata, sizeof(*pdata),
-			DMA_BIT_MASK(32));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-mx1-camera.c b/arch/arm/plat-mxc/devices/platform-mx1-camera.c
deleted file mode 100644
index edcc581..0000000
--- a/arch/arm/plat-mxc/devices/platform-mx1-camera.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_mx1_camera_data_entry_single(soc, _size)			\
-	{								\
-		.iobase = soc ## _CSI ## _BASE_ADDR,			\
-		.iosize = _size,					\
-		.irq = soc ## _INT_CSI,					\
-	}
-
-#ifdef CONFIG_SOC_IMX1
-const struct imx_mx1_camera_data imx1_mx1_camera_data __initconst =
-	imx_mx1_camera_data_entry_single(MX1, 10);
-#endif /* ifdef CONFIG_SOC_IMX1 */
-
-struct platform_device *__init imx_add_mx1_camera(
-		const struct imx_mx1_camera_data *data,
-		const struct mx1_camera_pdata *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-	return imx_add_platform_device_dmamask("mx1-camera", 0,
-			res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-mx2-camera.c b/arch/arm/plat-mxc/devices/platform-mx2-camera.c
deleted file mode 100644
index 11eace9..0000000
--- a/arch/arm/plat-mxc/devices/platform-mx2-camera.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_mx2_camera_data_entry_single(soc)				\
-	{								\
-		.iobasecsi = soc ## _CSI_BASE_ADDR,			\
-		.iosizecsi = SZ_4K,					\
-		.irqcsi = soc ## _INT_CSI,				\
-	}
-#define imx_mx2_camera_data_entry_single_emma(soc)			\
-	{								\
-		.iobasecsi = soc ## _CSI_BASE_ADDR,			\
-		.iosizecsi = SZ_32,					\
-		.irqcsi = soc ## _INT_CSI,				\
-		.iobaseemmaprp = soc ## _EMMAPRP_BASE_ADDR,		\
-		.iosizeemmaprp = SZ_32,					\
-		.irqemmaprp = soc ## _INT_EMMAPRP,			\
-	}
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_mx2_camera_data imx25_mx2_camera_data __initconst =
-	imx_mx2_camera_data_entry_single(MX25);
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_mx2_camera_data imx27_mx2_camera_data __initconst =
-	imx_mx2_camera_data_entry_single_emma(MX27);
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-struct platform_device *__init imx_add_mx2_camera(
-		const struct imx_mx2_camera_data *data,
-		const struct mx2_camera_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobasecsi,
-			.end = data->iobasecsi + data->iosizecsi - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irqcsi,
-			.end = data->irqcsi,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->iobaseemmaprp,
-			.end = data->iobaseemmaprp + data->iosizeemmaprp - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irqemmaprp,
-			.end = data->irqemmaprp,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-	return imx_add_platform_device_dmamask("mx2-camera", 0,
-			res, data->iobaseemmaprp ? 4 : 2,
-			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
-}
-
-struct platform_device *__init imx_add_mx2_emmaprp(
-		const struct imx_mx2_camera_data *data)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobaseemmaprp,
-			.end = data->iobaseemmaprp + data->iosizeemmaprp - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irqemmaprp,
-			.end = data->irqemmaprp,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-	return imx_add_platform_device_dmamask("m2m-emmaprp", 0,
-			res, 2, NULL, 0, DMA_BIT_MASK(32));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-mx2-emma.c b/arch/arm/plat-mxc/devices/platform-mx2-emma.c
new file mode 100644
index 0000000..508404d
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-mx2-emma.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_mx2_emmaprp_data_entry_single(soc)				\
+	{								\
+		.iobase = soc ## _EMMAPRP_BASE_ADDR,			\
+		.iosize = SZ_32,					\
+		.irq = soc ## _INT_EMMAPRP,				\
+	}
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_mx2_emma_data imx27_mx2_emmaprp_data __initconst =
+	imx_mx2_emmaprp_data_entry_single(MX27);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+struct platform_device *__init imx_add_mx2_emmaprp(
+		const struct imx_mx2_emma_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	return imx_add_platform_device_dmamask("m2m-emmaprp", 0,
+			res, 2, NULL, 0, DMA_BIT_MASK(32));
+}
diff --git a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
deleted file mode 100644
index 35851d8..0000000
--- a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <linux/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_mxc_ehci_data_entry_single(soc, _id, hs)			\
-	{								\
-		.id = _id,						\
-		.iobase = soc ## _USB_ ## hs ## _BASE_ADDR,		\
-		.irq = soc ## _INT_USB_ ## hs,				\
-	}
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_mxc_ehci_data imx25_mxc_ehci_otg_data __initconst =
-	imx_mxc_ehci_data_entry_single(MX25, 0, OTG);
-const struct imx_mxc_ehci_data imx25_mxc_ehci_hs_data __initconst =
-	imx_mxc_ehci_data_entry_single(MX25, 1, HS);
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_mxc_ehci_data imx27_mxc_ehci_otg_data __initconst =
-	imx_mxc_ehci_data_entry_single(MX27, 0, OTG);
-const struct imx_mxc_ehci_data imx27_mxc_ehci_hs_data[] __initconst = {
-	imx_mxc_ehci_data_entry_single(MX27, 1, HS1),
-	imx_mxc_ehci_data_entry_single(MX27, 2, HS2),
-};
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-#ifdef CONFIG_SOC_IMX31
-const struct imx_mxc_ehci_data imx31_mxc_ehci_otg_data __initconst =
-	imx_mxc_ehci_data_entry_single(MX31, 0, OTG);
-const struct imx_mxc_ehci_data imx31_mxc_ehci_hs_data[] __initconst = {
-	imx_mxc_ehci_data_entry_single(MX31, 1, HS1),
-	imx_mxc_ehci_data_entry_single(MX31, 2, HS2),
-};
-#endif /* ifdef CONFIG_SOC_IMX31 */
-
-#ifdef CONFIG_SOC_IMX35
-const struct imx_mxc_ehci_data imx35_mxc_ehci_otg_data __initconst =
-	imx_mxc_ehci_data_entry_single(MX35, 0, OTG);
-const struct imx_mxc_ehci_data imx35_mxc_ehci_hs_data __initconst =
-	imx_mxc_ehci_data_entry_single(MX35, 1, HS);
-#endif /* ifdef CONFIG_SOC_IMX35 */
-
-#ifdef CONFIG_SOC_IMX51
-const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data __initconst =
-	imx_mxc_ehci_data_entry_single(MX51, 0, OTG);
-const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[] __initconst = {
-	imx_mxc_ehci_data_entry_single(MX51, 1, HS1),
-	imx_mxc_ehci_data_entry_single(MX51, 2, HS2),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-struct platform_device *__init imx_add_mxc_ehci(
-		const struct imx_mxc_ehci_data *data,
-		const struct mxc_usbh_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + SZ_512 - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-	return imx_add_platform_device_dmamask("mxc-ehci", data->id,
-			res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-mxc-mmc.c b/arch/arm/plat-mxc/devices/platform-mxc-mmc.c
deleted file mode 100644
index e7b920b..0000000
--- a/arch/arm/plat-mxc/devices/platform-mxc-mmc.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <linux/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_mxc_mmc_data_entry_single(soc, _id, _hwid, _size)		\
-	{								\
-		.id = _id,						\
-		.iobase = soc ## _SDHC ## _hwid ## _BASE_ADDR,		\
-		.iosize = _size,					\
-		.irq = soc ## _INT_SDHC ## _hwid,			\
-		.dmareq = soc ## _DMA_REQ_SDHC ## _hwid,		\
-	}
-#define imx_mxc_mmc_data_entry(soc, _id, _hwid, _size)			\
-	[_id] = imx_mxc_mmc_data_entry_single(soc, _id, _hwid, _size)
-
-#ifdef CONFIG_SOC_IMX21
-const struct imx_mxc_mmc_data imx21_mxc_mmc_data[] __initconst = {
-#define imx21_mxc_mmc_data_entry(_id, _hwid)				\
-	imx_mxc_mmc_data_entry(MX21, _id, _hwid, SZ_4K)
-	imx21_mxc_mmc_data_entry(0, 1),
-	imx21_mxc_mmc_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX21 */
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_mxc_mmc_data imx27_mxc_mmc_data[] __initconst = {
-#define imx27_mxc_mmc_data_entry(_id, _hwid)				\
-	imx_mxc_mmc_data_entry(MX27, _id, _hwid, SZ_4K)
-	imx27_mxc_mmc_data_entry(0, 1),
-	imx27_mxc_mmc_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-#ifdef CONFIG_SOC_IMX31
-const struct imx_mxc_mmc_data imx31_mxc_mmc_data[] __initconst = {
-#define imx31_mxc_mmc_data_entry(_id, _hwid)				\
-	imx_mxc_mmc_data_entry(MX31, _id, _hwid, SZ_16K)
-	imx31_mxc_mmc_data_entry(0, 1),
-	imx31_mxc_mmc_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX31 */
-
-struct platform_device *__init imx_add_mxc_mmc(
-		const struct imx_mxc_mmc_data *data,
-		const struct imxmmc_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->dmareq,
-			.end = data->dmareq,
-			.flags = IORESOURCE_DMA,
-		},
-	};
-	return imx_add_platform_device_dmamask("mxc-mmc", data->id,
-			res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-mxc_nand.c b/arch/arm/plat-mxc/devices/platform-mxc_nand.c
deleted file mode 100644
index 95b75cc..0000000
--- a/arch/arm/plat-mxc/devices/platform-mxc_nand.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <asm/sizes.h>
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_mxc_nand_data_entry_single(soc, _size)			\
-	{								\
-		.iobase = soc ## _NFC_BASE_ADDR,			\
-		.iosize = _size,					\
-		.irq = soc ## _INT_NFC					\
-	}
-
-#define imx_mxc_nandv3_data_entry_single(soc, _size)			\
-	{								\
-		.id = -1,						\
-		.iobase = soc ## _NFC_BASE_ADDR,			\
-		.iosize = _size,					\
-		.axibase = soc ## _NFC_AXI_BASE_ADDR,			\
-		.irq = soc ## _INT_NFC					\
-	}
-
-#ifdef CONFIG_SOC_IMX21
-const struct imx_mxc_nand_data imx21_mxc_nand_data __initconst =
-	imx_mxc_nand_data_entry_single(MX21, SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX21 */
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_mxc_nand_data imx25_mxc_nand_data __initconst =
-	imx_mxc_nand_data_entry_single(MX25, SZ_8K);
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_mxc_nand_data imx27_mxc_nand_data __initconst =
-	imx_mxc_nand_data_entry_single(MX27, SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-#ifdef CONFIG_SOC_IMX31
-const struct imx_mxc_nand_data imx31_mxc_nand_data __initconst =
-	imx_mxc_nand_data_entry_single(MX31, SZ_4K);
-#endif
-
-#ifdef CONFIG_SOC_IMX35
-const struct imx_mxc_nand_data imx35_mxc_nand_data __initconst =
-	imx_mxc_nand_data_entry_single(MX35, SZ_8K);
-#endif
-
-#ifdef CONFIG_SOC_IMX51
-const struct imx_mxc_nand_data imx51_mxc_nand_data __initconst =
-	imx_mxc_nandv3_data_entry_single(MX51, SZ_16K);
-#endif
-
-struct platform_device *__init imx_add_mxc_nand(
-		const struct imx_mxc_nand_data *data,
-		const struct mxc_nand_platform_data *pdata)
-{
-	/* AXI has to come first, that's how the mxc_nand driver expect it */
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->axibase,
-			.end = data->axibase + SZ_16K - 1,
-			.flags = IORESOURCE_MEM,
-		},
-	};
-	return imx_add_platform_device("mxc_nand", data->id,
-			res, ARRAY_SIZE(res) - !data->axibase,
-			pdata, sizeof(*pdata));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-mxc_pwm.c b/arch/arm/plat-mxc/devices/platform-mxc_pwm.c
deleted file mode 100644
index b0c4ae2..0000000
--- a/arch/arm/plat-mxc/devices/platform-mxc_pwm.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_mxc_pwm_data_entry_single(soc, _id, _hwid, _size)		\
-	{								\
-		.id = _id,						\
-		.iobase = soc ## _PWM ## _hwid ## _BASE_ADDR,		\
-		.iosize = _size,					\
-		.irq = soc ## _INT_PWM ## _hwid,			\
-	}
-#define imx_mxc_pwm_data_entry(soc, _id, _hwid, _size)			\
-	[_id] = imx_mxc_pwm_data_entry_single(soc, _id, _hwid, _size)
-
-#ifdef CONFIG_SOC_IMX21
-const struct imx_mxc_pwm_data imx21_mxc_pwm_data __initconst =
-	imx_mxc_pwm_data_entry_single(MX21, 0, , SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX21 */
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_mxc_pwm_data imx25_mxc_pwm_data[] __initconst = {
-#define imx25_mxc_pwm_data_entry(_id, _hwid)				\
-	imx_mxc_pwm_data_entry(MX25, _id, _hwid, SZ_16K)
-	imx25_mxc_pwm_data_entry(0, 1),
-	imx25_mxc_pwm_data_entry(1, 2),
-	imx25_mxc_pwm_data_entry(2, 3),
-	imx25_mxc_pwm_data_entry(3, 4),
-};
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_mxc_pwm_data imx27_mxc_pwm_data __initconst =
-	imx_mxc_pwm_data_entry_single(MX27, 0, , SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-#ifdef CONFIG_SOC_IMX51
-const struct imx_mxc_pwm_data imx51_mxc_pwm_data[] __initconst = {
-#define imx51_mxc_pwm_data_entry(_id, _hwid)				\
-	imx_mxc_pwm_data_entry(MX51, _id, _hwid, SZ_16K)
-	imx51_mxc_pwm_data_entry(0, 1),
-	imx51_mxc_pwm_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-struct platform_device *__init imx_add_mxc_pwm(
-		const struct imx_mxc_pwm_data *data)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return imx_add_platform_device("mxc_pwm", data->id,
-			res, ARRAY_SIZE(res), NULL, 0);
-}
diff --git a/arch/arm/plat-mxc/devices/platform-mxc_rnga.c b/arch/arm/plat-mxc/devices/platform-mxc_rnga.c
deleted file mode 100644
index b4b7612..0000000
--- a/arch/arm/plat-mxc/devices/platform-mxc_rnga.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-struct imx_mxc_rnga_data {
-	resource_size_t iobase;
-};
-
-#define imx_mxc_rnga_data_entry_single(soc)				\
-	{								\
-		.iobase = soc ## _RNGA_BASE_ADDR,			\
-	}
-
-#ifdef CONFIG_SOC_IMX31
-static const struct imx_mxc_rnga_data imx31_mxc_rnga_data __initconst =
-	imx_mxc_rnga_data_entry_single(MX31);
-#endif /* ifdef CONFIG_SOC_IMX31 */
-
-static struct platform_device *__init imx_add_mxc_rnga(
-		const struct imx_mxc_rnga_data *data)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + SZ_16K - 1,
-			.flags = IORESOURCE_MEM,
-		},
-	};
-	return imx_add_platform_device("mxc_rnga", -1,
-			res, ARRAY_SIZE(res), NULL, 0);
-}
-
-static int __init imxXX_add_mxc_rnga(void)
-{
-	struct platform_device *ret;
-
-#if defined(CONFIG_SOC_IMX31)
-	if (cpu_is_mx31())
-		ret = imx_add_mxc_rnga(&imx31_mxc_rnga_data);
-	else
-#endif /* if defined(CONFIG_SOC_IMX31) */
-		ret = ERR_PTR(-ENODEV);
-
-	if (IS_ERR(ret))
-		return PTR_ERR(ret);
-
-	return 0;
-}
-arch_initcall(imxXX_add_mxc_rnga);
diff --git a/arch/arm/plat-mxc/devices/platform-mxc_rtc.c b/arch/arm/plat-mxc/devices/platform-mxc_rtc.c
deleted file mode 100644
index a5c9ad5..0000000
--- a/arch/arm/plat-mxc/devices/platform-mxc_rtc.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_mxc_rtc_data_entry_single(soc)				\
-	{								\
-		.iobase = soc ## _RTC_BASE_ADDR,			\
-		.irq = soc ## _INT_RTC,					\
-	}
-
-#ifdef CONFIG_SOC_IMX31
-const struct imx_mxc_rtc_data imx31_mxc_rtc_data __initconst =
-	imx_mxc_rtc_data_entry_single(MX31);
-#endif /* ifdef CONFIG_SOC_IMX31 */
-
-#ifdef CONFIG_SOC_IMX35
-const struct imx_mxc_rtc_data imx35_mxc_rtc_data __initconst =
-	imx_mxc_rtc_data_entry_single(MX35);
-#endif /* ifdef CONFIG_SOC_IMX35 */
-
-struct platform_device *__init imx_add_mxc_rtc(
-		const struct imx_mxc_rtc_data *data)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + SZ_16K - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return imx_add_platform_device("mxc_rtc", -1,
-			res, ARRAY_SIZE(res), NULL, 0);
-}
diff --git a/arch/arm/plat-mxc/devices/platform-mxc_w1.c b/arch/arm/plat-mxc/devices/platform-mxc_w1.c
deleted file mode 100644
index 96fa5ea..0000000
--- a/arch/arm/plat-mxc/devices/platform-mxc_w1.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_mxc_w1_data_entry_single(soc)				\
-	{								\
-		.iobase = soc ## _OWIRE_BASE_ADDR,			\
-	}
-
-#ifdef CONFIG_SOC_IMX21
-const struct imx_mxc_w1_data imx21_mxc_w1_data __initconst =
-	imx_mxc_w1_data_entry_single(MX21);
-#endif /* ifdef CONFIG_SOC_IMX21 */
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_mxc_w1_data imx27_mxc_w1_data __initconst =
-	imx_mxc_w1_data_entry_single(MX27);
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-#ifdef CONFIG_SOC_IMX31
-const struct imx_mxc_w1_data imx31_mxc_w1_data __initconst =
-	imx_mxc_w1_data_entry_single(MX31);
-#endif /* ifdef CONFIG_SOC_IMX31 */
-
-#ifdef CONFIG_SOC_IMX35
-const struct imx_mxc_w1_data imx35_mxc_w1_data __initconst =
-	imx_mxc_w1_data_entry_single(MX35);
-#endif /* ifdef CONFIG_SOC_IMX35 */
-
-struct platform_device *__init imx_add_mxc_w1(
-		const struct imx_mxc_w1_data *data)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + SZ_4K - 1,
-			.flags = IORESOURCE_MEM,
-		},
-	};
-
-	return imx_add_platform_device("mxc_w1", 0,
-			res, ARRAY_SIZE(res), NULL, 0);
-}
diff --git a/arch/arm/plat-mxc/devices/platform-pata_imx.c b/arch/arm/plat-mxc/devices/platform-pata_imx.c
deleted file mode 100644
index 70e2f2a..0000000
--- a/arch/arm/plat-mxc/devices/platform-pata_imx.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_pata_imx_data_entry_single(soc, _size)			\
-	{								\
-		.iobase = soc ## _ATA_BASE_ADDR,			\
-		.iosize = _size,					\
-		.irq = soc ## _INT_ATA,					\
-	}
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_pata_imx_data imx27_pata_imx_data __initconst =
-	imx_pata_imx_data_entry_single(MX27, SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-#ifdef CONFIG_SOC_IMX31
-const struct imx_pata_imx_data imx31_pata_imx_data __initconst =
-	imx_pata_imx_data_entry_single(MX31, SZ_16K);
-#endif /* ifdef CONFIG_SOC_IMX31 */
-
-#ifdef CONFIG_SOC_IMX35
-const struct imx_pata_imx_data imx35_pata_imx_data __initconst =
-	imx_pata_imx_data_entry_single(MX35, SZ_16K);
-#endif /* ifdef CONFIG_SOC_IMX35 */
-
-#ifdef CONFIG_SOC_IMX51
-const struct imx_pata_imx_data imx51_pata_imx_data __initconst =
-	imx_pata_imx_data_entry_single(MX51, SZ_16K);
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_pata_imx_data imx53_pata_imx_data __initconst =
-	imx_pata_imx_data_entry_single(MX53, SZ_16K);
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
-struct platform_device *__init imx_add_pata_imx(
-		const struct imx_pata_imx_data *data)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		},
-		{
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-	return imx_add_platform_device("pata_imx", -1,
-			res, ARRAY_SIZE(res), NULL, 0);
-}
-
diff --git a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
deleted file mode 100644
index 3793e47..0000000
--- a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix, Wolfram Sang <w.sang@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-#include <linux/platform_data/mmc-esdhc-imx.h>
-
-#define imx_sdhci_esdhc_imx_data_entry_single(soc, _devid, _id, hwid) \
-	{								\
-		.devid = _devid,					\
-		.id = _id,						\
-		.iobase = soc ## _ESDHC ## hwid ## _BASE_ADDR,	\
-		.irq = soc ## _INT_ESDHC ## hwid,			\
-	}
-
-#define imx_sdhci_esdhc_imx_data_entry(soc, devid, id, hwid)	\
-	[id] = imx_sdhci_esdhc_imx_data_entry_single(soc, devid, id, hwid)
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_sdhci_esdhc_imx_data
-imx25_sdhci_esdhc_imx_data[] __initconst = {
-#define imx25_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
-	imx_sdhci_esdhc_imx_data_entry(MX25, "sdhci-esdhc-imx25", _id, _hwid)
-	imx25_sdhci_esdhc_imx_data_entry(0, 1),
-	imx25_sdhci_esdhc_imx_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-#ifdef CONFIG_SOC_IMX35
-const struct imx_sdhci_esdhc_imx_data
-imx35_sdhci_esdhc_imx_data[] __initconst = {
-#define imx35_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
-	imx_sdhci_esdhc_imx_data_entry(MX35, "sdhci-esdhc-imx35", _id, _hwid)
-	imx35_sdhci_esdhc_imx_data_entry(0, 1),
-	imx35_sdhci_esdhc_imx_data_entry(1, 2),
-	imx35_sdhci_esdhc_imx_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX35 */
-
-#ifdef CONFIG_SOC_IMX51
-const struct imx_sdhci_esdhc_imx_data
-imx51_sdhci_esdhc_imx_data[] __initconst = {
-#define imx51_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
-	imx_sdhci_esdhc_imx_data_entry(MX51, "sdhci-esdhc-imx51", _id, _hwid)
-	imx51_sdhci_esdhc_imx_data_entry(0, 1),
-	imx51_sdhci_esdhc_imx_data_entry(1, 2),
-	imx51_sdhci_esdhc_imx_data_entry(2, 3),
-	imx51_sdhci_esdhc_imx_data_entry(3, 4),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_sdhci_esdhc_imx_data
-imx53_sdhci_esdhc_imx_data[] __initconst = {
-#define imx53_sdhci_esdhc_imx_data_entry(_id, _hwid)			\
-	imx_sdhci_esdhc_imx_data_entry(MX53, "sdhci-esdhc-imx53", _id, _hwid)
-	imx53_sdhci_esdhc_imx_data_entry(0, 1),
-	imx53_sdhci_esdhc_imx_data_entry(1, 2),
-	imx53_sdhci_esdhc_imx_data_entry(2, 3),
-	imx53_sdhci_esdhc_imx_data_entry(3, 4),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
-static const struct esdhc_platform_data default_esdhc_pdata __initconst = {
-	.wp_type = ESDHC_WP_NONE,
-	.cd_type = ESDHC_CD_NONE,
-};
-
-struct platform_device *__init imx_add_sdhci_esdhc_imx(
-		const struct imx_sdhci_esdhc_imx_data *data,
-		const struct esdhc_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + SZ_16K - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	/*
-	 * If machine does not provide pdata, use the default one
-	 * which means no WP/CD support
-	 */
-	if (!pdata)
-		pdata = &default_esdhc_pdata;
-
-	return imx_add_platform_device(data->devid, data->id, res,
-			ARRAY_SIZE(res), pdata, sizeof(*pdata));
-}
diff --git a/arch/arm/plat-mxc/devices/platform-spi_imx.c b/arch/arm/plat-mxc/devices/platform-spi_imx.c
deleted file mode 100644
index 9c50c14..0000000
--- a/arch/arm/plat-mxc/devices/platform-spi_imx.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/hardware.h>
-#include <mach/devices-common.h>
-
-#define imx_spi_imx_data_entry_single(soc, type, _devid, _id, hwid, _size) \
-	{								\
-		.devid = _devid,					\
-		.id = _id,						\
-		.iobase = soc ## _ ## type ## hwid ## _BASE_ADDR,	\
-		.iosize = _size,					\
-		.irq = soc ## _INT_ ## type ## hwid,			\
-	}
-
-#define imx_spi_imx_data_entry(soc, type, devid, id, hwid, size)	\
-	[id] = imx_spi_imx_data_entry_single(soc, type, devid, id, hwid, size)
-
-#ifdef CONFIG_SOC_IMX1
-const struct imx_spi_imx_data imx1_cspi_data[] __initconst = {
-#define imx1_cspi_data_entry(_id, _hwid) \
-	imx_spi_imx_data_entry(MX1, CSPI, "imx1-cspi", _id, _hwid, SZ_4K)
-	imx1_cspi_data_entry(0, 1),
-	imx1_cspi_data_entry(1, 2),
-};
-#endif
-
-#ifdef CONFIG_SOC_IMX21
-const struct imx_spi_imx_data imx21_cspi_data[] __initconst = {
-#define imx21_cspi_data_entry(_id, _hwid)                            \
-	imx_spi_imx_data_entry(MX21, CSPI, "imx21-cspi", _id, _hwid, SZ_4K)
-	imx21_cspi_data_entry(0, 1),
-	imx21_cspi_data_entry(1, 2),
-};
-#endif
-
-#ifdef CONFIG_SOC_IMX25
-/* i.mx25 has the i.mx35 type cspi */
-const struct imx_spi_imx_data imx25_cspi_data[] __initconst = {
-#define imx25_cspi_data_entry(_id, _hwid)				\
-	imx_spi_imx_data_entry(MX25, CSPI, "imx35-cspi", _id, _hwid, SZ_16K)
-	imx25_cspi_data_entry(0, 1),
-	imx25_cspi_data_entry(1, 2),
-	imx25_cspi_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-#ifdef CONFIG_SOC_IMX27
-const struct imx_spi_imx_data imx27_cspi_data[] __initconst = {
-#define imx27_cspi_data_entry(_id, _hwid)				\
-	imx_spi_imx_data_entry(MX27, CSPI, "imx27-cspi", _id, _hwid, SZ_4K)
-	imx27_cspi_data_entry(0, 1),
-	imx27_cspi_data_entry(1, 2),
-	imx27_cspi_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX27 */
-
-#ifdef CONFIG_SOC_IMX31
-const struct imx_spi_imx_data imx31_cspi_data[] __initconst = {
-#define imx31_cspi_data_entry(_id, _hwid)				\
-	imx_spi_imx_data_entry(MX31, CSPI, "imx31-cspi", _id, _hwid, SZ_4K)
-	imx31_cspi_data_entry(0, 1),
-	imx31_cspi_data_entry(1, 2),
-	imx31_cspi_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX31 */
-
-#ifdef CONFIG_SOC_IMX35
-const struct imx_spi_imx_data imx35_cspi_data[] __initconst = {
-#define imx35_cspi_data_entry(_id, _hwid)                           \
-	imx_spi_imx_data_entry(MX35, CSPI, "imx35-cspi", _id, _hwid, SZ_4K)
-	imx35_cspi_data_entry(0, 1),
-	imx35_cspi_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX35 */
-
-#ifdef CONFIG_SOC_IMX51
-/* i.mx51 has the i.mx35 type cspi */
-const struct imx_spi_imx_data imx51_cspi_data __initconst =
-	imx_spi_imx_data_entry_single(MX51, CSPI, "imx35-cspi", 2, , SZ_4K);
-
-const struct imx_spi_imx_data imx51_ecspi_data[] __initconst = {
-#define imx51_ecspi_data_entry(_id, _hwid)				\
-	imx_spi_imx_data_entry(MX51, ECSPI, "imx51-ecspi", _id, _hwid, SZ_4K)
-	imx51_ecspi_data_entry(0, 1),
-	imx51_ecspi_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-/* i.mx53 has the i.mx35 type cspi */
-const struct imx_spi_imx_data imx53_cspi_data __initconst =
-	imx_spi_imx_data_entry_single(MX53, CSPI, "imx35-cspi", 2, , SZ_4K);
-
-/* i.mx53 has the i.mx51 type ecspi */
-const struct imx_spi_imx_data imx53_ecspi_data[] __initconst = {
-#define imx53_ecspi_data_entry(_id, _hwid)				\
-	imx_spi_imx_data_entry(MX53, ECSPI, "imx51-ecspi", _id, _hwid, SZ_4K)
-	imx53_ecspi_data_entry(0, 1),
-	imx53_ecspi_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
-struct platform_device *__init imx_add_spi_imx(
-		const struct imx_spi_imx_data *data,
-		const struct spi_imx_master *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return imx_add_platform_device(data->devid, data->id,
-			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
-}
diff --git a/arch/arm/plat-mxc/epit.c b/arch/arm/plat-mxc/epit.c
deleted file mode 100644
index 88726f4..0000000
--- a/arch/arm/plat-mxc/epit.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- *  linux/arch/arm/plat-mxc/epit.c
- *
- *  Copyright (C) 2010 Sascha Hauer <s.hauer@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#define EPITCR		0x00
-#define EPITSR		0x04
-#define EPITLR		0x08
-#define EPITCMPR	0x0c
-#define EPITCNR		0x10
-
-#define EPITCR_EN			(1 << 0)
-#define EPITCR_ENMOD			(1 << 1)
-#define EPITCR_OCIEN			(1 << 2)
-#define EPITCR_RLD			(1 << 3)
-#define EPITCR_PRESC(x)			(((x) & 0xfff) << 4)
-#define EPITCR_SWR			(1 << 16)
-#define EPITCR_IOVW			(1 << 17)
-#define EPITCR_DBGEN			(1 << 18)
-#define EPITCR_WAITEN			(1 << 19)
-#define EPITCR_RES			(1 << 20)
-#define EPITCR_STOPEN			(1 << 21)
-#define EPITCR_OM_DISCON		(0 << 22)
-#define EPITCR_OM_TOGGLE		(1 << 22)
-#define EPITCR_OM_CLEAR			(2 << 22)
-#define EPITCR_OM_SET			(3 << 22)
-#define EPITCR_CLKSRC_OFF		(0 << 24)
-#define EPITCR_CLKSRC_PERIPHERAL	(1 << 24)
-#define EPITCR_CLKSRC_REF_HIGH		(1 << 24)
-#define EPITCR_CLKSRC_REF_LOW		(3 << 24)
-
-#define EPITSR_OCIF			(1 << 0)
-
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/clockchips.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <mach/hardware.h>
-#include <asm/mach/time.h>
-#include <mach/common.h>
-
-static struct clock_event_device clockevent_epit;
-static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
-
-static void __iomem *timer_base;
-
-static inline void epit_irq_disable(void)
-{
-	u32 val;
-
-	val = __raw_readl(timer_base + EPITCR);
-	val &= ~EPITCR_OCIEN;
-	__raw_writel(val, timer_base + EPITCR);
-}
-
-static inline void epit_irq_enable(void)
-{
-	u32 val;
-
-	val = __raw_readl(timer_base + EPITCR);
-	val |= EPITCR_OCIEN;
-	__raw_writel(val, timer_base + EPITCR);
-}
-
-static void epit_irq_acknowledge(void)
-{
-	__raw_writel(EPITSR_OCIF, timer_base + EPITSR);
-}
-
-static int __init epit_clocksource_init(struct clk *timer_clk)
-{
-	unsigned int c = clk_get_rate(timer_clk);
-
-	return clocksource_mmio_init(timer_base + EPITCNR, "epit", c, 200, 32,
-			clocksource_mmio_readl_down);
-}
-
-/* clock event */
-
-static int epit_set_next_event(unsigned long evt,
-			      struct clock_event_device *unused)
-{
-	unsigned long tcmp;
-
-	tcmp = __raw_readl(timer_base + EPITCNR);
-
-	__raw_writel(tcmp - evt, timer_base + EPITCMPR);
-
-	return 0;
-}
-
-static void epit_set_mode(enum clock_event_mode mode,
-				struct clock_event_device *evt)
-{
-	unsigned long flags;
-
-	/*
-	 * The timer interrupt generation is disabled at least
-	 * for enough time to call epit_set_next_event()
-	 */
-	local_irq_save(flags);
-
-	/* Disable interrupt in GPT module */
-	epit_irq_disable();
-
-	if (mode != clockevent_mode) {
-		/* Set event time into far-far future */
-
-		/* Clear pending interrupt */
-		epit_irq_acknowledge();
-	}
-
-	/* Remember timer mode */
-	clockevent_mode = mode;
-	local_irq_restore(flags);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		printk(KERN_ERR "epit_set_mode: Periodic mode is not "
-				"supported for i.MX EPIT\n");
-		break;
-	case CLOCK_EVT_MODE_ONESHOT:
-	/*
-	 * Do not put overhead of interrupt enable/disable into
-	 * epit_set_next_event(), the core has about 4 minutes
-	 * to call epit_set_next_event() or shutdown clock after
-	 * mode switching
-	 */
-		local_irq_save(flags);
-		epit_irq_enable();
-		local_irq_restore(flags);
-		break;
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_RESUME:
-		/* Left event sources disabled, no more interrupts appear */
-		break;
-	}
-}
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t epit_timer_interrupt(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = &clockevent_epit;
-
-	epit_irq_acknowledge();
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction epit_timer_irq = {
-	.name		= "i.MX EPIT Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= epit_timer_interrupt,
-};
-
-static struct clock_event_device clockevent_epit = {
-	.name		= "epit",
-	.features	= CLOCK_EVT_FEAT_ONESHOT,
-	.shift		= 32,
-	.set_mode	= epit_set_mode,
-	.set_next_event	= epit_set_next_event,
-	.rating		= 200,
-};
-
-static int __init epit_clockevent_init(struct clk *timer_clk)
-{
-	unsigned int c = clk_get_rate(timer_clk);
-
-	clockevent_epit.mult = div_sc(c, NSEC_PER_SEC,
-					clockevent_epit.shift);
-	clockevent_epit.max_delta_ns =
-			clockevent_delta2ns(0xfffffffe, &clockevent_epit);
-	clockevent_epit.min_delta_ns =
-			clockevent_delta2ns(0x800, &clockevent_epit);
-
-	clockevent_epit.cpumask = cpumask_of(0);
-
-	clockevents_register_device(&clockevent_epit);
-
-	return 0;
-}
-
-void __init epit_timer_init(void __iomem *base, int irq)
-{
-	struct clk *timer_clk;
-
-	timer_clk = clk_get_sys("imx-epit.0", NULL);
-	if (IS_ERR(timer_clk)) {
-		pr_err("i.MX epit: unable to get clk\n");
-		return;
-	}
-
-	clk_prepare_enable(timer_clk);
-
-	timer_base = base;
-
-	/*
-	 * Initialise to a known state (all timers off, and timing reset)
-	 */
-	__raw_writel(0x0, timer_base + EPITCR);
-
-	__raw_writel(0xffffffff, timer_base + EPITLR);
-	__raw_writel(EPITCR_EN | EPITCR_CLKSRC_REF_HIGH | EPITCR_WAITEN,
-			timer_base + EPITCR);
-
-	/* init and register the timer to the framework */
-	epit_clocksource_init(timer_clk);
-	epit_clockevent_init(timer_clk);
-
-	/* Make irqs happen */
-	setup_irq(irq, &epit_timer_irq);
-}
diff --git a/arch/arm/plat-mxc/include/mach/3ds_debugboard.h b/arch/arm/plat-mxc/include/mach/3ds_debugboard.h
deleted file mode 100644
index 9fd6cb3..0000000
--- a/arch/arm/plat-mxc/include/mach/3ds_debugboard.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __ASM_ARCH_MXC_3DS_DB_H__
-#define __ASM_ARCH_MXC_3DS_DB_H__
-
-extern int __init mxc_expio_init(u32 base, u32 intr_gpio);
-
-#endif /* __ASM_ARCH_MXC_3DS_DB_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/board-mx31lilly.h b/arch/arm/plat-mxc/include/mach/board-mx31lilly.h
deleted file mode 100644
index 0df71bf..0000000
--- a/arch/arm/plat-mxc/include/mach/board-mx31lilly.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
- *
- * Based on code for mobots boards,
- *   Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef __ASM_ARCH_MXC_BOARD_MX31LILLY_H__
-#define __ASM_ARCH_MXC_BOARD_MX31LILLY_H__
-
-#ifndef __ASSEMBLY__
-
-enum mx31lilly_boards {
-	MX31LILLY_NOBOARD	= 0,
-	MX31LILLY_DB		= 1,
-};
-
-/*
- * This CPU module needs a baseboard to work. After basic initializing
- * its own devices, it calls the baseboard's init function.
- */
-
-extern void mx31lilly_db_init(void);
-
-#endif
-
-#endif /* __ASM_ARCH_MXC_BOARD_MX31LILLY_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/board-mx31lite.h b/arch/arm/plat-mxc/include/mach/board-mx31lite.h
deleted file mode 100644
index c1ad0ae8..0000000
--- a/arch/arm/plat-mxc/include/mach/board-mx31lite.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
- *
- * Based on code for mobots boards,
- *   Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef __ASM_ARCH_MXC_BOARD_MX31LITE_H__
-#define __ASM_ARCH_MXC_BOARD_MX31LITE_H__
-
-#ifndef __ASSEMBLY__
-
-enum mx31lite_boards {
-	MX31LITE_NOBOARD	= 0,
-	MX31LITE_DB		= 1,
-};
-
-/*
- * This CPU module needs a baseboard to work. After basic initializing
- * its own devices, it calls the baseboard's init function.
- */
-
-extern void mx31lite_db_init(void);
-
-#endif
-
-#endif /* __ASM_ARCH_MXC_BOARD_MX31LITE_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/board-mx31moboard.h b/arch/arm/plat-mxc/include/mach/board-mx31moboard.h
deleted file mode 100644
index de14543..0000000
--- a/arch/arm/plat-mxc/include/mach/board-mx31moboard.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef __ASM_ARCH_MXC_BOARD_MX31MOBOARD_H__
-#define __ASM_ARCH_MXC_BOARD_MX31MOBOARD_H__
-
-#ifndef __ASSEMBLY__
-
-enum mx31moboard_boards {
-	MX31NOBOARD	= 0,
-	MX31DEVBOARD	= 1,
-	MX31MARXBOT	= 2,
-	MX31SMARTBOT	= 3,
-	MX31EYEBOT	= 4,
-};
-
-/*
- * This CPU module needs a baseboard to work. After basic initializing
- * its own devices, it calls the baseboard's init function.
- */
-
-extern void mx31moboard_devboard_init(void);
-extern void mx31moboard_marxbot_init(void);
-extern void mx31moboard_smartbot_init(int board);
-
-#endif
-
-#endif /* __ASM_ARCH_MXC_BOARD_MX31MOBOARD_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/board-pcm038.h b/arch/arm/plat-mxc/include/mach/board-pcm038.h
deleted file mode 100644
index 6f371e3..0000000
--- a/arch/arm/plat-mxc/include/mach/board-pcm038.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef __ASM_ARCH_MXC_BOARD_PCM038_H__
-#define __ASM_ARCH_MXC_BOARD_PCM038_H__
-
-#ifndef __ASSEMBLY__
-/*
- * This CPU module needs a baseboard to work. After basic initializing
- * its own devices, it calls the baseboard's init function.
- * TODO: Add your own baseboard init function and call it from
- * inside pcm038_init().
- *
- * This example here is for the development board. Refer pcm970-baseboard.c
- */
-
-extern void pcm970_baseboard_init(void);
-
-#endif
-
-#endif /* __ASM_ARCH_MXC_BOARD_PCM038_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
deleted file mode 100644
index ead9018..0000000
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_MXC_COMMON_H__
-#define __ASM_ARCH_MXC_COMMON_H__
-
-struct platform_device;
-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 mx50_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 imx50_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 mx50_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 imx50_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,
-			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 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 int mx6q_clocks_init(void);
-extern struct platform_device *mxc_register_gpio(char *name, int id,
-	resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);
-extern void mxc_set_cpu_type(unsigned int type);
-extern void mxc_restart(char, const char *);
-extern void mxc_arch_reset_init(void __iomem *);
-extern int mx53_revision(void);
-extern int mx53_display_revision(void);
-extern void imx_set_aips(void __iomem *);
-
-enum mxc_cpu_pwr_mode {
-	WAIT_CLOCKED,		/* wfi only */
-	WAIT_UNCLOCKED,		/* WAIT */
-	WAIT_UNCLOCKED_POWER_OFF,	/* WAIT + SRPG */
-	STOP_POWER_ON,		/* just STOP */
-	STOP_POWER_OFF,		/* STOP + SRPG */
-};
-
-enum mx3_cpu_pwr_mode {
-	MX3_RUN,
-	MX3_WAIT,
-	MX3_DOZE,
-	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 avic_handle_irq(struct pt_regs *);
-void tzic_handle_irq(struct pt_regs *);
-
-#define imx1_handle_irq avic_handle_irq
-#define imx21_handle_irq avic_handle_irq
-#define imx25_handle_irq avic_handle_irq
-#define imx27_handle_irq avic_handle_irq
-#define imx31_handle_irq avic_handle_irq
-#define imx35_handle_irq avic_handle_irq
-#define imx50_handle_irq tzic_handle_irq
-#define imx51_handle_irq tzic_handle_irq
-#define imx53_handle_irq tzic_handle_irq
-#define imx6q_handle_irq gic_handle_irq
-
-extern void imx_enable_cpu(int cpu, bool enable);
-extern void imx_set_cpu_jump(int cpu, void *jump_addr);
-#ifdef CONFIG_DEBUG_LL
-extern void imx_lluart_map_io(void);
-#else
-static inline void imx_lluart_map_io(void) {}
-#endif
-extern void v7_cpu_resume(void);
-extern u32 *pl310_get_save_ptr(void);
-#ifdef CONFIG_SMP
-extern void v7_secondary_startup(void);
-extern void imx_scu_map_io(void);
-extern void imx_smp_prepare(void);
-#else
-static inline void imx_scu_map_io(void) {}
-static inline void imx_smp_prepare(void) {}
-#endif
-extern void imx_enable_cpu(int cpu, bool enable);
-extern void imx_set_cpu_jump(int cpu, void *jump_addr);
-extern void imx_src_init(void);
-extern void imx_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 int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
-extern void imx6q_clock_map_io(void);
-
-extern void imx_cpu_die(unsigned int cpu);
-
-#ifdef CONFIG_PM
-extern void imx6q_pm_init(void);
-extern void imx51_pm_init(void);
-extern void imx53_pm_init(void);
-#else
-static inline void imx6q_pm_init(void) {}
-static inline void imx51_pm_init(void) {}
-static inline void imx53_pm_init(void) {}
-#endif
-
-#ifdef CONFIG_NEON
-extern int mx51_neon_fixup(void);
-#else
-static inline int mx51_neon_fixup(void) { return 0; }
-#endif
-
-extern struct smp_operations imx_smp_ops;
-
-#endif
diff --git a/arch/arm/plat-mxc/include/mach/cpuidle.h b/arch/arm/plat-mxc/include/mach/cpuidle.h
deleted file mode 100644
index bc932d1..0000000
--- a/arch/arm/plat-mxc/include/mach/cpuidle.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2012 Freescale Semiconductor, Inc.
- * Copyright 2012 Linaro Ltd.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/cpuidle.h>
-
-#ifdef CONFIG_CPU_IDLE
-extern int imx_cpuidle_init(struct cpuidle_driver *drv);
-#else
-static inline int imx_cpuidle_init(struct cpuidle_driver *drv)
-{
-	return -ENODEV;
-}
-#endif
diff --git a/arch/arm/plat-mxc/include/mach/debug-macro.S b/arch/arm/plat-mxc/include/mach/debug-macro.S
deleted file mode 100644
index 761e45f..0000000
--- a/arch/arm/plat-mxc/include/mach/debug-macro.S
+++ /dev/null
@@ -1,51 +0,0 @@
-/* arch/arm/mach-imx/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-#include <mach/hardware.h>
-
-#ifdef CONFIG_DEBUG_IMX1_UART
-#define UART_PADDR	MX1_UART1_BASE_ADDR
-#elif defined (CONFIG_DEBUG_IMX25_UART)
-#define UART_PADDR	MX25_UART1_BASE_ADDR
-#elif defined (CONFIG_DEBUG_IMX21_IMX27_UART)
-#define UART_PADDR	MX2x_UART1_BASE_ADDR
-#elif defined (CONFIG_DEBUG_IMX31_IMX35_UART)
-#define UART_PADDR	MX3x_UART1_BASE_ADDR
-#elif defined (CONFIG_DEBUG_IMX51_UART)
-#define UART_PADDR	MX51_UART1_BASE_ADDR
-#elif defined (CONFIG_DEBUG_IMX50_IMX53_UART)
-#define UART_PADDR	MX53_UART1_BASE_ADDR
-#elif defined (CONFIG_DEBUG_IMX6Q_UART2)
-#define UART_PADDR	MX6Q_UART2_BASE_ADDR
-#elif defined (CONFIG_DEBUG_IMX6Q_UART4)
-#define UART_PADDR	MX6Q_UART4_BASE_ADDR
-#endif
-
-#define UART_VADDR	IMX_IO_ADDRESS(UART_PADDR)
-
-		.macro	addruart, rp, rv, tmp
-		ldr	\rp, =UART_PADDR	@ physical
-		ldr	\rv, =UART_VADDR	@ virtual
-		.endm
-
-		.macro	senduart,rd,rx
-		str	\rd, [\rx, #0x40]	@ TXDATA
-		.endm
-
-		.macro	waituart,rd,rx
-		.endm
-
-		.macro	busyuart,rd,rx
-1002:		ldr	\rd, [\rx, #0x98]	@ SR2
-		tst	\rd, #1 << 3		@ TXDC
-		beq	1002b			@ wait until transmit done
-		.endm
diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h
deleted file mode 100644
index eaf79d2..0000000
--- a/arch/arm/plat-mxc/include/mach/devices-common.h
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/platform_data/dma-imx-sdma.h>
-
-extern struct device mxc_aips_bus;
-extern struct device mxc_ahb_bus;
-
-static inline struct platform_device *imx_add_platform_device_dmamask(
-		const char *name, int id,
-		const struct resource *res, unsigned int num_resources,
-		const void *data, size_t size_data, u64 dmamask)
-{
-	struct platform_device_info pdevinfo = {
-		.name = name,
-		.id = id,
-		.res = res,
-		.num_res = num_resources,
-		.data = data,
-		.size_data = size_data,
-		.dma_mask = dmamask,
-	};
-	return platform_device_register_full(&pdevinfo);
-}
-
-static inline struct platform_device *imx_add_platform_device(
-		const char *name, int id,
-		const struct resource *res, unsigned int num_resources,
-		const void *data, size_t size_data)
-{
-	return imx_add_platform_device_dmamask(
-			name, id, res, num_resources, data, size_data, 0);
-}
-
-#include <linux/fec.h>
-struct imx_fec_data {
-	const char *devid;
-	resource_size_t iobase;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_fec(
-		const struct imx_fec_data *data,
-		const struct fec_platform_data *pdata);
-
-#include <linux/can/platform/flexcan.h>
-struct imx_flexcan_data {
-	int id;
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_flexcan(
-		const struct imx_flexcan_data *data,
-		const struct flexcan_platform_data *pdata);
-
-#include <linux/fsl_devices.h>
-struct imx_fsl_usb2_udc_data {
-	resource_size_t iobase;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_fsl_usb2_udc(
-		const struct imx_fsl_usb2_udc_data *data,
-		const struct fsl_usb2_platform_data *pdata);
-
-#include <linux/gpio_keys.h>
-struct platform_device *__init imx_add_gpio_keys(
-		const struct gpio_keys_platform_data *pdata);
-
-#include <linux/platform_data/usb-mx2.h>
-struct imx_imx21_hcd_data {
-	resource_size_t iobase;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_imx21_hcd(
-		const struct imx_imx21_hcd_data *data,
-		const struct mx21_usbh_platform_data *pdata);
-
-struct imx_imx27_coda_data {
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_imx27_coda(
-		const struct imx_imx27_coda_data *data);
-
-struct imx_imx2_wdt_data {
-	int id;
-	resource_size_t iobase;
-	resource_size_t iosize;
-};
-struct platform_device *__init imx_add_imx2_wdt(
-		const struct imx_imx2_wdt_data *data);
-
-struct imx_imxdi_rtc_data {
-	resource_size_t iobase;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_imxdi_rtc(
-		const struct imx_imxdi_rtc_data *data);
-
-#include <linux/platform_data/video-imxfb.h>
-struct imx_imx_fb_data {
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_imx_fb(
-		const struct imx_imx_fb_data *data,
-		const struct imx_fb_platform_data *pdata);
-
-#include <linux/platform_data/i2c-imx.h>
-struct imx_imx_i2c_data {
-	int id;
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_imx_i2c(
-		const struct imx_imx_i2c_data *data,
-		const struct imxi2c_platform_data *pdata);
-
-#include <linux/input/matrix_keypad.h>
-struct imx_imx_keypad_data {
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_imx_keypad(
-		const struct imx_imx_keypad_data *data,
-		const struct matrix_keymap_data *pdata);
-
-#include <linux/platform_data/asoc-imx-ssi.h>
-struct imx_imx_ssi_data {
-	int id;
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq;
-	resource_size_t dmatx0;
-	resource_size_t dmarx0;
-	resource_size_t dmatx1;
-	resource_size_t dmarx1;
-};
-struct platform_device *__init imx_add_imx_ssi(
-		const struct imx_imx_ssi_data *data,
-		const struct imx_ssi_platform_data *pdata);
-
-#include <linux/platform_data/serial-imx.h>
-struct imx_imx_uart_3irq_data {
-	int id;
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irqrx;
-	resource_size_t irqtx;
-	resource_size_t irqrts;
-};
-struct platform_device *__init imx_add_imx_uart_3irq(
-		const struct imx_imx_uart_3irq_data *data,
-		const struct imxuart_platform_data *pdata);
-
-struct imx_imx_uart_1irq_data {
-	int id;
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_imx_uart_1irq(
-		const struct imx_imx_uart_1irq_data *data,
-		const struct imxuart_platform_data *pdata);
-
-#include <linux/platform_data/usb-imx_udc.h>
-struct imx_imx_udc_data {
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq0;
-	resource_size_t irq1;
-	resource_size_t irq2;
-	resource_size_t irq3;
-	resource_size_t irq4;
-	resource_size_t irq5;
-	resource_size_t irq6;
-};
-struct platform_device *__init imx_add_imx_udc(
-		const struct imx_imx_udc_data *data,
-		const struct imxusb_platform_data *pdata);
-
-#include <linux/platform_data/video-mx3fb.h>
-#include <linux/platform_data/camera-mx3.h>
-struct imx_ipu_core_data {
-	resource_size_t iobase;
-	resource_size_t synirq;
-	resource_size_t errirq;
-};
-struct platform_device *__init imx_add_ipu_core(
-		const struct imx_ipu_core_data *data);
-struct platform_device *__init imx_alloc_mx3_camera(
-		const struct imx_ipu_core_data *data,
-		const struct mx3_camera_pdata *pdata);
-struct platform_device *__init imx_add_mx3_sdc_fb(
-		const struct imx_ipu_core_data *data,
-		struct mx3fb_platform_data *pdata);
-
-#include <linux/platform_data/camera-mx1.h>
-struct imx_mx1_camera_data {
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_mx1_camera(
-		const struct imx_mx1_camera_data *data,
-		const struct mx1_camera_pdata *pdata);
-
-#include <linux/platform_data/camera-mx2.h>
-struct imx_mx2_camera_data {
-	resource_size_t iobasecsi;
-	resource_size_t iosizecsi;
-	resource_size_t irqcsi;
-	resource_size_t iobaseemmaprp;
-	resource_size_t iosizeemmaprp;
-	resource_size_t irqemmaprp;
-};
-struct platform_device *__init imx_add_mx2_camera(
-		const struct imx_mx2_camera_data *data,
-		const struct mx2_camera_platform_data *pdata);
-struct platform_device *__init imx_add_mx2_emmaprp(
-		const struct imx_mx2_camera_data *data);
-
-#include <linux/platform_data/usb-ehci-mxc.h>
-struct imx_mxc_ehci_data {
-	int id;
-	resource_size_t iobase;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_mxc_ehci(
-		const struct imx_mxc_ehci_data *data,
-		const struct mxc_usbh_platform_data *pdata);
-
-#include <linux/platform_data/mmc-mxcmmc.h>
-struct imx_mxc_mmc_data {
-	int id;
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq;
-	resource_size_t dmareq;
-};
-struct platform_device *__init imx_add_mxc_mmc(
-		const struct imx_mxc_mmc_data *data,
-		const struct imxmmc_platform_data *pdata);
-
-#include <linux/platform_data/mtd-mxc_nand.h>
-struct imx_mxc_nand_data {
-	/*
-	 * id is traditionally 0, but -1 is more appropriate.  We use -1 for new
-	 * machines but don't change existing devices as the nand device usually
-	 * appears in the kernel command line to pass its partitioning.
-	 */
-	int id;
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t axibase;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_mxc_nand(
-		const struct imx_mxc_nand_data *data,
-		const struct mxc_nand_platform_data *pdata);
-
-struct imx_pata_imx_data {
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_pata_imx(
-		const struct imx_pata_imx_data *data);
-
-struct imx_mxc_pwm_data {
-	int id;
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_mxc_pwm(
-		const struct imx_mxc_pwm_data *data);
-
-/* mxc_rtc */
-struct imx_mxc_rtc_data {
-	resource_size_t iobase;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_mxc_rtc(
-		const struct imx_mxc_rtc_data *data);
-
-/* mxc_w1 */
-struct imx_mxc_w1_data {
-	resource_size_t iobase;
-};
-struct platform_device *__init imx_add_mxc_w1(
-		const struct imx_mxc_w1_data *data);
-
-#include <linux/platform_data/mmc-esdhc-imx.h>
-struct imx_sdhci_esdhc_imx_data {
-	const char *devid;
-	int id;
-	resource_size_t iobase;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_sdhci_esdhc_imx(
-		const struct imx_sdhci_esdhc_imx_data *data,
-		const struct esdhc_platform_data *pdata);
-
-#include <linux/platform_data/spi-imx.h>
-struct imx_spi_imx_data {
-	const char *devid;
-	int id;
-	resource_size_t iobase;
-	resource_size_t iosize;
-	int irq;
-};
-struct platform_device *__init imx_add_spi_imx(
-		const struct imx_spi_imx_data *data,
-		const struct spi_imx_master *pdata);
-
-struct platform_device *imx_add_imx_dma(void);
-struct platform_device *imx_add_imx_sdma(char *name,
-	resource_size_t iobase, int irq, struct sdma_platform_data *pdata);
-
-#include <linux/ahci_platform.h>
-struct imx_ahci_imx_data {
-	const char *devid;
-	resource_size_t iobase;
-	resource_size_t irq;
-};
-struct platform_device *__init imx_add_ahci_imx(
-		const struct imx_ahci_imx_data *data,
-		const struct ahci_platform_data *pdata);
diff --git a/arch/arm/plat-mxc/include/mach/eukrea-baseboards.h b/arch/arm/plat-mxc/include/mach/eukrea-baseboards.h
deleted file mode 100644
index a21d331..0000000
--- a/arch/arm/plat-mxc/include/mach/eukrea-baseboards.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2010 Eric Benard - eric@eukrea.com
- *
- * Based on board-pcm038.h which is :
- * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef __MACH_EUKREA_BASEBOARDS_H__
-#define __MACH_EUKREA_BASEBOARDS_H__
-
-#ifndef __ASSEMBLY__
-/*
- * This CPU module needs a baseboard to work. After basic initializing
- * its own devices, it calls baseboard's init function.
- * TODO: Add your own baseboard init function and call it from
- * inside eukrea_cpuimx25_init() eukrea_cpuimx27_init()
- * eukrea_cpuimx35_init() eukrea_cpuimx51_init()
- * or eukrea_cpuimx51sd_init().
- *
- * This example here is for the development board. Refer
- * mach-mx25/eukrea_mbimxsd-baseboard.c for cpuimx25
- * mach-imx/eukrea_mbimx27-baseboard.c for cpuimx27
- * mach-mx3/eukrea_mbimxsd-baseboard.c for cpuimx35
- * mach-mx5/eukrea_mbimx51-baseboard.c for cpuimx51
- * mach-mx5/eukrea_mbimxsd-baseboard.c for cpuimx51sd
- */
-
-extern void eukrea_mbimxsd25_baseboard_init(void);
-extern void eukrea_mbimx27_baseboard_init(void);
-extern void eukrea_mbimxsd35_baseboard_init(void);
-extern void eukrea_mbimx51_baseboard_init(void);
-extern void eukrea_mbimxsd51_baseboard_init(void);
-
-#endif
-
-#endif /* __MACH_EUKREA_BASEBOARDS_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h
deleted file mode 100644
index ebf1065..0000000
--- a/arch/arm/plat-mxc/include/mach/hardware.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- */
-
-#ifndef __ASM_ARCH_MXC_HARDWARE_H__
-#define __ASM_ARCH_MXC_HARDWARE_H__
-
-#include <asm/sizes.h>
-
-#define addr_in_module(addr, mod) \
-	((unsigned long)(addr) - mod ## _BASE_ADDR < mod ## _SIZE)
-
-#define IMX_IO_P2V_MODULE(addr, module)					\
-	(((addr) - module ## _BASE_ADDR) < module ## _SIZE ?		\
-	 (addr) - (module ## _BASE_ADDR) + (module ## _BASE_ADDR_VIRT) : 0)
-
-/*
- * This is rather complicated for humans and ugly to verify, but for a machine
- * it's OK.  Still more as it is usually only applied to constants.  The upsides
- * on using this approach are:
- *
- *  - same mapping on all i.MX machines
- *  - works for assembler, too
- *  - no need to nurture #defines for virtual addresses
- *
- * The downside it, it's hard to verify (but I have a script for that).
- *
- * Obviously this needs to be injective for each SoC.  In general it maps the
- * whole address space to [0xf4000000, 0xf5ffffff].  So [0xf6000000,0xfeffffff]
- * is free for per-machine use (e.g. KZM_ARM11_01 uses 64MiB there).
- *
- * It applies the following mappings for the different SoCs:
- *
- * mx1:
- *	IO	0x00200000+0x100000	->	0xf4000000+0x100000
- * mx21:
- *	AIPI	0x10000000+0x100000	->	0xf4400000+0x100000
- *	SAHB1	0x80000000+0x100000	->	0xf5000000+0x100000
- *	X_MEMC	0xdf000000+0x004000	->	0xf5f00000+0x004000
- * mx25:
- *	AIPS1	0x43f00000+0x100000	->	0xf5300000+0x100000
- *	AIPS2	0x53f00000+0x100000	->	0xf5700000+0x100000
- *	AVIC	0x68000000+0x100000	->	0xf5800000+0x100000
- * mx27:
- *	AIPI	0x10000000+0x100000	->	0xf4400000+0x100000
- *	SAHB1	0x80000000+0x100000	->	0xf5000000+0x100000
- *	X_MEMC	0xd8000000+0x100000	->	0xf5c00000+0x100000
- * mx31:
- *	AIPS1	0x43f00000+0x100000	->	0xf5300000+0x100000
- *	AIPS2	0x53f00000+0x100000	->	0xf5700000+0x100000
- *	AVIC	0x68000000+0x100000	->	0xf5800000+0x100000
- *	X_MEMC	0xb8000000+0x010000	->	0xf5c00000+0x010000
- *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
- * mx35:
- *	AIPS1	0x43f00000+0x100000	->	0xf5300000+0x100000
- *	AIPS2	0x53f00000+0x100000	->	0xf5700000+0x100000
- *	AVIC	0x68000000+0x100000	->	0xf5800000+0x100000
- *	X_MEMC	0xb8000000+0x010000	->	0xf5c00000+0x010000
- *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
- * mx50:
- *	TZIC	0x0fffc000+0x004000	->	0xf4bfc000+0x004000
- *	AIPS1	0x53f00000+0x100000	->	0xf5700000+0x100000
- *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
- *	AIPS2	0x63f00000+0x100000	->	0xf5300000+0x100000
- * mx51:
- *	TZIC	0x0fffc000+0x004000	->	0xf4bfc000+0x004000
- *	IRAM	0x1ffe0000+0x020000	->	0xf4fe0000+0x020000
- *	DEBUG	0x60000000+0x100000	->	0xf5000000+0x100000
- *	SPBA0	0x70000000+0x100000	->	0xf5400000+0x100000
- *	AIPS1	0x73f00000+0x100000	->	0xf5700000+0x100000
- *	AIPS2	0x83f00000+0x100000	->	0xf5300000+0x100000
- * mx53:
- *	TZIC	0x0fffc000+0x004000	->	0xf4bfc000+0x004000
- *	DEBUG	0x40000000+0x100000	->	0xf5000000+0x100000
- *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
- *	AIPS1	0x53f00000+0x100000	->	0xf5700000+0x100000
- *	AIPS2	0x63f00000+0x100000	->	0xf5300000+0x100000
- * mx6q:
- *	SCU	0x00a00000+0x004000	->	0xf4000000+0x004000
- *	CCM	0x020c4000+0x004000	->	0xf42c4000+0x004000
- *	ANATOP	0x020c8000+0x004000	->	0xf42c8000+0x004000
- *	UART4	0x021f0000+0x004000	->	0xf42f0000+0x004000
- */
-#define IMX_IO_P2V(x)	(						\
-			(((x) & 0x80000000) >> 7) |			\
-			(0xf4000000 +					\
-			(((x) & 0x50000000) >> 6) +			\
-			(((x) & 0x0b000000) >> 4) +			\
-			(((x) & 0x000fffff))))
-
-#define IMX_IO_ADDRESS(x)	IOMEM(IMX_IO_P2V(x))
-
-#include <mach/mxc.h>
-
-#include <mach/mx6q.h>
-#include <mach/mx50.h>
-#include <mach/mx51.h>
-#include <mach/mx53.h>
-#include <mach/mx3x.h>
-#include <mach/mx31.h>
-#include <mach/mx35.h>
-#include <mach/mx2x.h>
-#include <mach/mx21.h>
-#include <mach/mx27.h>
-#include <mach/mx1.h>
-#include <mach/mx25.h>
-
-#define imx_map_entry(soc, name, _type)	{				\
-	.virtual = soc ## _IO_P2V(soc ## _ ## name ## _BASE_ADDR),	\
-	.pfn = __phys_to_pfn(soc ## _ ## name ## _BASE_ADDR),		\
-	.length = soc ## _ ## name ## _SIZE,				\
-	.type = _type,							\
-}
-
-/* There's a off-by-one betweem the gpio bank number and the gpiochip */
-/* range e.g. GPIO_1_5 is gpio 5 under linux */
-#define IMX_GPIO_NR(bank, nr)		(((bank) - 1) * 32 + (nr))
-
-#endif /* __ASM_ARCH_MXC_HARDWARE_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iim.h b/arch/arm/plat-mxc/include/mach/iim.h
deleted file mode 100644
index 315bffa..0000000
--- a/arch/arm/plat-mxc/include/mach/iim.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- */
-
-#ifndef __ASM_ARCH_MXC_IIM_H__
-#define __ASM_ARCH_MXC_IIM_H__
-
-/* Register offsets */
-#define MXC_IIMSTAT             0x0000
-#define MXC_IIMSTATM            0x0004
-#define MXC_IIMERR              0x0008
-#define MXC_IIMEMASK            0x000C
-#define MXC_IIMFCTL             0x0010
-#define MXC_IIMUA               0x0014
-#define MXC_IIMLA               0x0018
-#define MXC_IIMSDAT             0x001C
-#define MXC_IIMPREV             0x0020
-#define MXC_IIMSREV             0x0024
-#define MXC_IIMPRG_P            0x0028
-#define MXC_IIMSCS0             0x002C
-#define MXC_IIMSCS1             0x0030
-#define MXC_IIMSCS2             0x0034
-#define MXC_IIMSCS3             0x0038
-#define MXC_IIMFBAC0            0x0800
-#define MXC_IIMJAC              0x0804
-#define MXC_IIMHWV1             0x0808
-#define MXC_IIMHWV2             0x080C
-#define MXC_IIMHAB0             0x0810
-#define MXC_IIMHAB1             0x0814
-/* Definitions for i.MX27 TO2 */
-#define MXC_IIMMAC              0x0814
-#define MXC_IIMPREV_FUSE        0x0818
-#define MXC_IIMSREV_FUSE        0x081C
-#define MXC_IIMSJC_CHALL_0      0x0820
-#define MXC_IIMSJC_CHALL_7      0x083C
-#define MXC_IIMFB0UC17          0x0840
-#define MXC_IIMFB0UC255         0x0BFC
-#define MXC_IIMFBAC1            0x0C00
-/* Definitions for i.MX27 TO2 */
-#define MXC_IIMSUID             0x0C04
-#define MXC_IIMKEY0             0x0C04
-#define MXC_IIMKEY20            0x0C54
-#define MXC_IIMSJC_RESP_0       0x0C58
-#define MXC_IIMSJC_RESP_7       0x0C74
-#define MXC_IIMFB1UC30          0x0C78
-#define MXC_IIMFB1UC255         0x0FFC
-
-/* Bit definitions */
-
-#define MXC_IIMHWV1_WLOCK               (0x1 << 7)
-#define MXC_IIMHWV1_MCU_ENDIAN          (0x1 << 6)
-#define MXC_IIMHWV1_DSP_ENDIAN          (0x1 << 5)
-#define MXC_IIMHWV1_BOOT_INT            (0x1 << 4)
-#define MXC_IIMHWV1_SCC_DISABLE         (0x1 << 3)
-#define MXC_IIMHWV1_HANTRO_DISABLE      (0x1 << 2)
-#define MXC_IIMHWV1_MEMSTICK_DIS        (0x1 << 1)
-
-#define MXC_IIMHWV2_WLOCK               (0x1 << 7)
-#define MXC_IIMHWV2_BP_SDMA             (0x1 << 6)
-#define MXC_IIMHWV2_SCM_DCM             (0x1 << 5)
-
-#endif /* __ASM_ARCH_MXC_IIM_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx1.h b/arch/arm/plat-mxc/include/mach/iomux-mx1.h
deleted file mode 100644
index 6b1507c..0000000
--- a/arch/arm/plat-mxc/include/mach/iomux-mx1.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-#ifndef __MACH_IOMUX_MX1_H__
-#define __MACH_IOMUX_MX1_H__
-
-#include <mach/iomux-v1.h>
-
-#define PA0_AIN_SPI2_CLK	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 0)
-#define PA0_AF_ETMTRACESYNC	(GPIO_PORTA | GPIO_AF | 0)
-#define PA1_AOUT_SPI2_RXD	(GPIO_PORTA | GPIO_AOUT | GPIO_IN | 1)
-#define PA1_PF_TIN		(GPIO_PORTA | GPIO_PF | 1)
-#define PA2_PF_PWM0		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 2)
-#define PA3_PF_CSI_MCLK		(GPIO_PORTA | GPIO_PF | 3)
-#define PA4_PF_CSI_D0		(GPIO_PORTA | GPIO_PF | 4)
-#define PA5_PF_CSI_D1		(GPIO_PORTA | GPIO_PF | 5)
-#define PA6_PF_CSI_D2		(GPIO_PORTA | GPIO_PF | 6)
-#define PA7_PF_CSI_D3		(GPIO_PORTA | GPIO_PF | 7)
-#define PA8_PF_CSI_D4		(GPIO_PORTA | GPIO_PF | 8)
-#define PA9_PF_CSI_D5		(GPIO_PORTA | GPIO_PF | 9)
-#define PA10_PF_CSI_D6		(GPIO_PORTA | GPIO_PF | 10)
-#define PA11_PF_CSI_D7		(GPIO_PORTA | GPIO_PF | 11)
-#define PA12_PF_CSI_VSYNC	(GPIO_PORTA | GPIO_PF | 12)
-#define PA13_PF_CSI_HSYNC	(GPIO_PORTA | GPIO_PF | 13)
-#define PA14_PF_CSI_PIXCLK	(GPIO_PORTA | GPIO_PF | 14)
-#define PA15_PF_I2C_SDA		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 15)
-#define PA16_PF_I2C_SCL		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 16)
-#define PA17_AF_ETMTRACEPKT4	(GPIO_PORTA | GPIO_AF | 17)
-#define PA17_AIN_SPI2_SS	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 17)
-#define PA18_AF_ETMTRACEPKT5	(GPIO_PORTA | GPIO_AF | 18)
-#define PA19_AF_ETMTRACEPKT6	(GPIO_PORTA | GPIO_AF | 19)
-#define PA20_AF_ETMTRACEPKT7	(GPIO_PORTA | GPIO_AF | 20)
-#define PA21_PF_A0		(GPIO_PORTA | GPIO_PF | 21)
-#define PA22_PF_CS4		(GPIO_PORTA | GPIO_PF | 22)
-#define PA23_PF_CS5		(GPIO_PORTA | GPIO_PF | 23)
-#define PA24_PF_A16		(GPIO_PORTA | GPIO_PF | 24)
-#define PA24_AF_ETMTRACEPKT0	(GPIO_PORTA | GPIO_AF | 24)
-#define PA25_PF_A17		(GPIO_PORTA | GPIO_PF | 25)
-#define PA25_AF_ETMTRACEPKT1	(GPIO_PORTA | GPIO_AF | 25)
-#define PA26_PF_A18		(GPIO_PORTA | GPIO_PF | 26)
-#define PA26_AF_ETMTRACEPKT2	(GPIO_PORTA | GPIO_AF | 26)
-#define PA27_PF_A19		(GPIO_PORTA | GPIO_PF | 27)
-#define PA27_AF_ETMTRACEPKT3	(GPIO_PORTA | GPIO_AF | 27)
-#define PA28_PF_A20		(GPIO_PORTA | GPIO_PF | 28)
-#define PA28_AF_ETMPIPESTAT0	(GPIO_PORTA | GPIO_AF | 28)
-#define PA29_PF_A21		(GPIO_PORTA | GPIO_PF | 29)
-#define PA29_AF_ETMPIPESTAT1	(GPIO_PORTA | GPIO_AF | 29)
-#define PA30_PF_A22		(GPIO_PORTA | GPIO_PF | 30)
-#define PA30_AF_ETMPIPESTAT2	(GPIO_PORTA | GPIO_AF | 30)
-#define PA31_PF_A23		(GPIO_PORTA | GPIO_PF | 31)
-#define PA31_AF_ETMTRACECLK	(GPIO_PORTA | GPIO_AF | 31)
-#define PB8_PF_SD_DAT0		(GPIO_PORTB | GPIO_PF | GPIO_PUEN | 8)
-#define PB8_AF_MS_PIO		(GPIO_PORTB | GPIO_AF | 8)
-#define PB9_PF_SD_DAT1		(GPIO_PORTB | GPIO_PF | GPIO_PUEN | 9)
-#define PB9_AF_MS_PI1		(GPIO_PORTB | GPIO_AF | 9)
-#define PB10_PF_SD_DAT2		(GPIO_PORTB | GPIO_PF | GPIO_PUEN | 10)
-#define PB10_AF_MS_SCLKI	(GPIO_PORTB | GPIO_AF | 10)
-#define PB11_PF_SD_DAT3		(GPIO_PORTB | GPIO_PF | 11)
-#define PB11_AF_MS_SDIO		(GPIO_PORTB | GPIO_AF | 11)
-#define PB12_PF_SD_CLK		(GPIO_PORTB | GPIO_PF | 12)
-#define PB12_AF_MS_SCLK0	(GPIO_PORTB | GPIO_AF | 12)
-#define PB13_PF_SD_CMD		(GPIO_PORTB | GPIO_PF | GPIO_PUEN | 13)
-#define PB13_AF_MS_BS		(GPIO_PORTB | GPIO_AF | 13)
-#define PB14_AF_SSI_RXFS	(GPIO_PORTB | GPIO_AF | 14)
-#define PB15_AF_SSI_RXCLK	(GPIO_PORTB | GPIO_AF | 15)
-#define PB16_AF_SSI_RXDAT	(GPIO_PORTB | GPIO_AF | GPIO_IN | 16)
-#define PB17_AF_SSI_TXDAT	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 17)
-#define PB18_AF_SSI_TXFS	(GPIO_PORTB | GPIO_AF | 18)
-#define PB19_AF_SSI_TXCLK	(GPIO_PORTB | GPIO_AF | 19)
-#define PB20_PF_USBD_AFE	(GPIO_PORTB | GPIO_PF | 20)
-#define PB21_PF_USBD_OE		(GPIO_PORTB | GPIO_PF | 21)
-#define PB22_PF_USBD_RCV	(GPIO_PORTB | GPIO_PF | 22)
-#define PB23_PF_USBD_SUSPND	(GPIO_PORTB | GPIO_PF | 23)
-#define PB24_PF_USBD_VP		(GPIO_PORTB | GPIO_PF | 24)
-#define PB25_PF_USBD_VM		(GPIO_PORTB | GPIO_PF | 25)
-#define PB26_PF_USBD_VPO	(GPIO_PORTB | GPIO_PF | 26)
-#define PB27_PF_USBD_VMO	(GPIO_PORTB | GPIO_PF | 27)
-#define PB28_PF_UART2_CTS	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 28)
-#define PB29_PF_UART2_RTS	(GPIO_PORTB | GPIO_PF | GPIO_IN | 29)
-#define PB30_PF_UART2_TXD	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 30)
-#define PB31_PF_UART2_RXD	(GPIO_PORTB | GPIO_PF | GPIO_IN | 31)
-#define PC3_PF_SSI_RXFS		(GPIO_PORTC | GPIO_PF | 3)
-#define PC4_PF_SSI_RXCLK	(GPIO_PORTC | GPIO_PF | 4)
-#define PC5_PF_SSI_RXDAT	(GPIO_PORTC | GPIO_PF | GPIO_IN | 5)
-#define PC6_PF_SSI_TXDAT	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 6)
-#define PC7_PF_SSI_TXFS		(GPIO_PORTC | GPIO_PF | 7)
-#define PC8_PF_SSI_TXCLK	(GPIO_PORTC | GPIO_PF | 8)
-#define PC9_PF_UART1_CTS	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 9)
-#define PC10_PF_UART1_RTS	(GPIO_PORTC | GPIO_PF | GPIO_IN | 10)
-#define PC11_PF_UART1_TXD	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 11)
-#define PC12_PF_UART1_RXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 12)
-#define PC13_PF_SPI1_SPI_RDY	(GPIO_PORTC | GPIO_PF | 13)
-#define PC14_PF_SPI1_SCLK	(GPIO_PORTC | GPIO_PF | 14)
-#define PC15_PF_SPI1_SS		(GPIO_PORTC | GPIO_PF | 15)
-#define PC16_PF_SPI1_MISO	(GPIO_PORTC | GPIO_PF | 16)
-#define PC17_PF_SPI1_MOSI	(GPIO_PORTC | GPIO_PF | 17)
-#define PC24_BIN_UART3_RI	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 24)
-#define PC25_BIN_UART3_DSR	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 25)
-#define PC26_AOUT_UART3_DTR	(GPIO_PORTC | GPIO_AOUT | GPIO_IN | 26)
-#define PC27_BIN_UART3_DCD	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 27)
-#define PC28_BIN_UART3_CTS	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 28)
-#define PC29_AOUT_UART3_RTS	(GPIO_PORTC | GPIO_AOUT | GPIO_IN | 29)
-#define PC30_BIN_UART3_TX	(GPIO_PORTC | GPIO_BIN | 30)
-#define PC31_AOUT_UART3_RX	(GPIO_PORTC | GPIO_AOUT | GPIO_IN | 31)
-#define PD6_PF_LSCLK		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 6)
-#define PD7_PF_REV		(GPIO_PORTD | GPIO_PF | 7)
-#define PD7_AF_UART2_DTR	(GPIO_PORTD | GPIO_AF | GPIO_IN | 7)
-#define PD7_AIN_SPI2_SCLK	(GPIO_PORTD | GPIO_AIN | 7)
-#define PD8_PF_CLS		(GPIO_PORTD | GPIO_PF | 8)
-#define PD8_AF_UART2_DCD	(GPIO_PORTD | GPIO_AF | GPIO_OUT | 8)
-#define PD8_AIN_SPI2_SS		(GPIO_PORTD | GPIO_AIN | 8)
-#define PD9_PF_PS		(GPIO_PORTD | GPIO_PF | 9)
-#define PD9_AF_UART2_RI		(GPIO_PORTD | GPIO_AF | GPIO_OUT | 9)
-#define PD9_AOUT_SPI2_RXD	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 9)
-#define PD10_PF_SPL_SPR		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 10)
-#define PD10_AF_UART2_DSR	(GPIO_PORTD | GPIO_AF | GPIO_OUT | 10)
-#define PD10_AIN_SPI2_TXD	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 10)
-#define PD11_PF_CONTRAST	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 11)
-#define PD12_PF_ACD_OE		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 12)
-#define PD13_PF_LP_HSYNC	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 13)
-#define PD14_PF_FLM_VSYNC	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 14)
-#define PD15_PF_LD0		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 15)
-#define PD16_PF_LD1		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 16)
-#define PD17_PF_LD2		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 17)
-#define PD18_PF_LD3		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 18)
-#define PD19_PF_LD4		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 19)
-#define PD20_PF_LD5		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 20)
-#define PD21_PF_LD6		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 21)
-#define PD22_PF_LD7		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 22)
-#define PD23_PF_LD8		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 23)
-#define PD24_PF_LD9		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 24)
-#define PD25_PF_LD10		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 25)
-#define PD26_PF_LD11		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 26)
-#define PD27_PF_LD12		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 27)
-#define PD28_PF_LD13		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 28)
-#define PD29_PF_LD14		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 29)
-#define PD30_PF_LD15		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 30)
-#define PD31_PF_TMR2OUT		(GPIO_PORTD | GPIO_PF | 31)
-#define PD31_BIN_SPI2_TXD	(GPIO_PORTD | GPIO_BIN | 31)
-
-#endif /* ifndef __MACH_IOMUX_MX1_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx21.h b/arch/arm/plat-mxc/include/mach/iomux-mx21.h
deleted file mode 100644
index 1495dfd..0000000
--- a/arch/arm/plat-mxc/include/mach/iomux-mx21.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-#ifndef __MACH_IOMUX_MX21_H__
-#define __MACH_IOMUX_MX21_H__
-
-#include <mach/iomux-mx2x.h>
-#include <mach/iomux-v1.h>
-
-/* Primary GPIO pin functions */
-
-#define PB22_PF_USBH1_BYP	(GPIO_PORTB | GPIO_PF | 22)
-#define PB25_PF_USBH1_ON	(GPIO_PORTB | GPIO_PF | 25)
-#define PC5_PF_USBOTG_SDA	(GPIO_PORTC | GPIO_PF | 5)
-#define PC6_PF_USBOTG_SCL	(GPIO_PORTC | GPIO_PF | 6)
-#define PC7_PF_USBOTG_ON	(GPIO_PORTC | GPIO_PF | 7)
-#define PC8_PF_USBOTG_FS	(GPIO_PORTC | GPIO_PF | 8)
-#define PC9_PF_USBOTG_OE	(GPIO_PORTC | GPIO_PF | 9)
-#define PC10_PF_USBOTG_TXDM	(GPIO_PORTC | GPIO_PF | 10)
-#define PC11_PF_USBOTG_TXDP	(GPIO_PORTC | GPIO_PF | 11)
-#define PC12_PF_USBOTG_RXDM	(GPIO_PORTC | GPIO_PF | 12)
-#define PC13_PF_USBOTG_RXDP	(GPIO_PORTC | GPIO_PF | 13)
-#define PC16_PF_SAP_FS		(GPIO_PORTC | GPIO_PF | 16)
-#define PC17_PF_SAP_RXD		(GPIO_PORTC | GPIO_PF | 17)
-#define PC18_PF_SAP_TXD		(GPIO_PORTC | GPIO_PF | 18)
-#define PC19_PF_SAP_CLK		(GPIO_PORTC | GPIO_PF | 19)
-#define PE0_PF_TEST_WB2		(GPIO_PORTE | GPIO_PF | 0)
-#define PE1_PF_TEST_WB1		(GPIO_PORTE | GPIO_PF | 1)
-#define PE2_PF_TEST_WB0		(GPIO_PORTE | GPIO_PF | 2)
-#define PF1_PF_NFCE		(GPIO_PORTF | GPIO_PF | 1)
-#define PF3_PF_NFCLE		(GPIO_PORTF | GPIO_PF | 3)
-#define PF7_PF_NFIO0		(GPIO_PORTF | GPIO_PF | 7)
-#define PF8_PF_NFIO1		(GPIO_PORTF | GPIO_PF | 8)
-#define PF9_PF_NFIO2		(GPIO_PORTF | GPIO_PF | 9)
-#define PF10_PF_NFIO3		(GPIO_PORTF | GPIO_PF | 10)
-#define PF11_PF_NFIO4		(GPIO_PORTF | GPIO_PF | 11)
-#define PF12_PF_NFIO5		(GPIO_PORTF | GPIO_PF | 12)
-#define PF13_PF_NFIO6		(GPIO_PORTF | GPIO_PF | 13)
-#define PF14_PF_NFIO7		(GPIO_PORTF | GPIO_PF | 14)
-#define PF16_PF_RES		(GPIO_PORTF | GPIO_PF | 16)
-
-/* Alternate GPIO pin functions */
-
-#define PA5_AF_BMI_CLK_CS	(GPIO_PORTA | GPIO_AF | 5)
-#define PA6_AF_BMI_D0		(GPIO_PORTA | GPIO_AF | 6)
-#define PA7_AF_BMI_D1		(GPIO_PORTA | GPIO_AF | 7)
-#define PA8_AF_BMI_D2		(GPIO_PORTA | GPIO_AF | 8)
-#define PA9_AF_BMI_D3		(GPIO_PORTA | GPIO_AF | 9)
-#define PA10_AF_BMI_D4		(GPIO_PORTA | GPIO_AF | 10)
-#define PA11_AF_BMI_D5		(GPIO_PORTA | GPIO_AF | 11)
-#define PA12_AF_BMI_D6		(GPIO_PORTA | GPIO_AF | 12)
-#define PA13_AF_BMI_D7		(GPIO_PORTA | GPIO_AF | 13)
-#define PA14_AF_BMI_D8		(GPIO_PORTA | GPIO_AF | 14)
-#define PA15_AF_BMI_D9		(GPIO_PORTA | GPIO_AF | 15)
-#define PA16_AF_BMI_D10		(GPIO_PORTA | GPIO_AF | 16)
-#define PA17_AF_BMI_D11		(GPIO_PORTA | GPIO_AF | 17)
-#define PA18_AF_BMI_D12		(GPIO_PORTA | GPIO_AF | 18)
-#define PA19_AF_BMI_D13		(GPIO_PORTA | GPIO_AF | 19)
-#define PA20_AF_BMI_D14		(GPIO_PORTA | GPIO_AF | 20)
-#define PA21_AF_BMI_D15		(GPIO_PORTA | GPIO_AF | 21)
-#define PA22_AF_BMI_READ_REQ	(GPIO_PORTA | GPIO_AF | 22)
-#define PA23_AF_BMI_WRITE	(GPIO_PORTA | GPIO_AF | 23)
-#define PA29_AF_BMI_RX_FULL	(GPIO_PORTA | GPIO_AF | 29)
-#define PA30_AF_BMI_READ	(GPIO_PORTA | GPIO_AF | 30)
-
-/* AIN GPIO pin functions */
-
-#define PC14_AIN_SYS_CLK	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 14)
-#define PD21_AIN_USBH2_FS	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 21)
-#define PD22_AIN_USBH2_OE	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 22)
-#define PD23_AIN_USBH2_TXDM	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 23)
-#define PD24_AIN_USBH2_TXDP	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 24)
-#define PE8_AIN_IR_TXD		(GPIO_PORTE | GPIO_AIN | GPIO_OUT | 8)
-#define PF0_AIN_PC_RST		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 0)
-#define PF1_AIN_PC_CE1		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 1)
-#define PF2_AIN_PC_CE2		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 2)
-#define PF3_AIN_PC_POE		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 3)
-#define PF4_AIN_PC_OE		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 4)
-#define PF5_AIN_PC_RW		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 5)
-
-/* BIN GPIO pin functions */
-
-#define PC14_BIN_SYS_CLK	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 14)
-#define PD27_BIN_EXT_DMA_GRANT	(GPIO_PORTD | GPIO_BIN | GPIO_OUT | 27)
-
-/* CIN GPIO pin functions */
-
-#define PB26_CIN_USBH1_RXDAT	(GPIO_PORTB | GPIO_CIN | GPIO_OUT | 26)
-
-/* AOUT GPIO pin functions */
-
-#define PA29_AOUT_BMI_WAIT	(GPIO_PORTA | GPIO_AOUT | GPIO_IN | 29)
-#define PD19_AOUT_USBH2_RXDM	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 19)
-#define PD20_AOUT_USBH2_RXDP	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 20)
-#define PD25_AOUT_EXT_DMAREQ	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 25)
-#define PD26_AOUT_USBOTG_RXDAT	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 26)
-#define PE9_AOUT_IR_RXD		(GPIO_PORTE | GPIO_AOUT | GPIO_IN | 9)
-#define PF6_AOUT_PC_BVD2	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 6)
-#define PF7_AOUT_PC_BVD1	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 7)
-#define PF8_AOUT_PC_VS2		(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 8)
-#define PF9_AOUT_PC_VS1		(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 9)
-#define PF10_AOUT_PC_WP		(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 10)
-#define PF11_AOUT_PC_READY	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 11)
-#define PF12_AOUT_PC_WAIT	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 12)
-#define PF13_AOUT_PC_CD2	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 13)
-#define PF14_AOUT_PC_CD1	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 14)
-
-#endif /* ifndef __MACH_IOMUX_MX21_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx25.h b/arch/arm/plat-mxc/include/mach/iomux-mx25.h
deleted file mode 100644
index c61ec0f..0000000
--- a/arch/arm/plat-mxc/include/mach/iomux-mx25.h
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * arch/arm/plat-mxc/include/mach/iomux-mx25.h
- *
- * Copyright (C) 2009 by Lothar Wassmann <LW@KARO-electronics.de>
- *
- * based on arch/arm/mach-mx25/mx25_pins.h
- *    Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
- * and
- * arch/arm/plat-mxc/include/mach/iomux-mx35.h
- *    Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH <armlinux@phytec.de>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#ifndef __MACH_IOMUX_MX25_H__
-#define __MACH_IOMUX_MX25_H__
-
-#include <mach/iomux-v3.h>
-
-/*
- * IOMUX/PAD Bit field definitions
- */
-
-#define MX25_PAD_A10__A10		IOMUX_PAD(0x000, 0x008, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A10__GPIO_4_0		IOMUX_PAD(0x000, 0x008, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A13__A13		IOMUX_PAD(0x22C, 0x00c, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A13__GPIO_4_1		IOMUX_PAD(0x22C, 0x00c, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A14__A14		IOMUX_PAD(0x230, 0x010, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A14__GPIO_2_0		IOMUX_PAD(0x230, 0x010, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A15__A15		IOMUX_PAD(0x234, 0x014, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A15__GPIO_2_1		IOMUX_PAD(0x234, 0x014, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A16__A16		IOMUX_PAD(0x000, 0x018, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A16__GPIO_2_2		IOMUX_PAD(0x000, 0x018, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A17__A17		IOMUX_PAD(0x238, 0x01c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A17__GPIO_2_3		IOMUX_PAD(0x238, 0x01c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A18__A18		IOMUX_PAD(0x23c, 0x020, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A18__GPIO_2_4		IOMUX_PAD(0x23c, 0x020, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A18__FEC_COL		IOMUX_PAD(0x23c, 0x020, 0x17, 0x504, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A19__A19		IOMUX_PAD(0x240, 0x024, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A19__FEC_RX_ER		IOMUX_PAD(0x240, 0x024, 0x17, 0x518, 0, NO_PAD_CTRL)
-#define MX25_PAD_A19__GPIO_2_5		IOMUX_PAD(0x240, 0x024, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A20__A20		IOMUX_PAD(0x244, 0x028, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A20__GPIO_2_6		IOMUX_PAD(0x244, 0x028, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A20__FEC_RDATA2	IOMUX_PAD(0x244, 0x028, 0x17, 0x50c, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A21__A21		IOMUX_PAD(0x248, 0x02c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A21__GPIO_2_7		IOMUX_PAD(0x248, 0x02c, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A21__FEC_RDATA3	IOMUX_PAD(0x248, 0x02c, 0x17, 0x510, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A22__A22		IOMUX_PAD(0x000, 0x030, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A22__GPIO_2_8		IOMUX_PAD(0x000, 0x030, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A23__A23		IOMUX_PAD(0x24c, 0x034, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A23__GPIO_2_9		IOMUX_PAD(0x24c, 0x034, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A24__A24		IOMUX_PAD(0x250, 0x038, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A24__GPIO_2_10		IOMUX_PAD(0x250, 0x038, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A24__FEC_RX_CLK	IOMUX_PAD(0x250, 0x038, 0x17, 0x514, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A25__A25		IOMUX_PAD(0x254, 0x03c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A25__GPIO_2_11		IOMUX_PAD(0x254, 0x03c, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A25__FEC_CRS		IOMUX_PAD(0x254, 0x03c, 0x17, 0x508, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_EB0__EB0		IOMUX_PAD(0x258, 0x040, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_EB0__AUD4_TXD		IOMUX_PAD(0x258, 0x040, 0x14, 0x464, 0, NO_PAD_CTRL)
-#define MX25_PAD_EB0__GPIO_2_12		IOMUX_PAD(0x258, 0x040, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_EB1__EB1		IOMUX_PAD(0x25c, 0x044, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_EB1__AUD4_RXD		IOMUX_PAD(0x25c, 0x044, 0x14, 0x460, 0, NO_PAD_CTRL)
-#define MX25_PAD_EB1__GPIO_2_13		IOMUX_PAD(0x25c, 0x044, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_OE__OE			IOMUX_PAD(0x260, 0x048, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_OE__AUD4_TXC		IOMUX_PAD(0x260, 0x048, 0x14, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_OE__GPIO_2_14		IOMUX_PAD(0x260, 0x048, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CS0__CS0		IOMUX_PAD(0x000, 0x04c, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS0__GPIO_4_2		IOMUX_PAD(0x000, 0x04c, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CS1__CS1		IOMUX_PAD(0x000, 0x050, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS1__NF_CE3		IOMUX_PAD(0x000, 0x050, 0x01, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS1__GPIO_4_3		IOMUX_PAD(0x000, 0x050, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CS4__CS4		IOMUX_PAD(0x264, 0x054, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS4__NF_CE1		IOMUX_PAD(0x264, 0x054, 0x01, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS4__UART5_CTS		IOMUX_PAD(0x264, 0x054, 0x13, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS4__GPIO_3_20		IOMUX_PAD(0x264, 0x054, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CS5__CS5		IOMUX_PAD(0x268, 0x058, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS5__NF_CE2		IOMUX_PAD(0x268, 0x058, 0x01, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS5__UART5_RTS		IOMUX_PAD(0x268, 0x058, 0x13, 0x574, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS5__GPIO_3_21		IOMUX_PAD(0x268, 0x058, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_NF_CE0__NF_CE0		IOMUX_PAD(0x26c, 0x05c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_NF_CE0__GPIO_3_22	IOMUX_PAD(0x26c, 0x05c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_ECB__ECB		IOMUX_PAD(0x270, 0x060, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_ECB__UART5_TXD_MUX	IOMUX_PAD(0x270, 0x060, 0x13, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_ECB__GPIO_3_23		IOMUX_PAD(0x270, 0x060, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LBA__LBA		IOMUX_PAD(0x274, 0x064, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_LBA__UART5_RXD_MUX	IOMUX_PAD(0x274, 0x064, 0x13, 0x578, 0, NO_PAD_CTRL)
-#define MX25_PAD_LBA__GPIO_3_24		IOMUX_PAD(0x274, 0x064, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_BCLK__BCLK		IOMUX_PAD(0x000, 0x068, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_BCLK__GPIO_4_4		IOMUX_PAD(0x000, 0x068, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_RW__RW			IOMUX_PAD(0x278, 0x06c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_RW__AUD4_TXFS		IOMUX_PAD(0x278, 0x06c, 0x14, 0x474, 0, NO_PAD_CTRL)
-#define MX25_PAD_RW__GPIO_3_25		IOMUX_PAD(0x278, 0x06c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_NFWE_B__NFWE_B		IOMUX_PAD(0x000, 0x070, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_NFWE_B__GPIO_3_26	IOMUX_PAD(0x000, 0x070, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_NFRE_B__NFRE_B		IOMUX_PAD(0x000, 0x074, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_NFRE_B__GPIO_3_27	IOMUX_PAD(0x000, 0x074, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_NFALE__NFALE		IOMUX_PAD(0x000, 0x078, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_NFALE__GPIO_3_28	IOMUX_PAD(0x000, 0x078, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_NFCLE__NFCLE		IOMUX_PAD(0x000, 0x07c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_NFCLE__GPIO_3_29	IOMUX_PAD(0x000, 0x07c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_NFWP_B__NFWP_B		IOMUX_PAD(0x000, 0x080, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_NFWP_B__GPIO_3_30	IOMUX_PAD(0x000, 0x080, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_NFRB__NFRB		IOMUX_PAD(0x27c, 0x084, 0x10, 0, 0, PAD_CTL_PKE)
-#define MX25_PAD_NFRB__GPIO_3_31	IOMUX_PAD(0x27c, 0x084, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D15__D15		IOMUX_PAD(0x280, 0x088, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D15__LD16		IOMUX_PAD(0x280, 0x088, 0x01, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_D15__GPIO_4_5		IOMUX_PAD(0x280, 0x088, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D14__D14		IOMUX_PAD(0x284, 0x08c, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D14__LD17		IOMUX_PAD(0x284, 0x08c, 0x01, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_D14__GPIO_4_6		IOMUX_PAD(0x284, 0x08c, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D13__D13		IOMUX_PAD(0x288, 0x090, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D13__LD18		IOMUX_PAD(0x288, 0x090, 0x01, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_D13__GPIO_4_7		IOMUX_PAD(0x288, 0x090, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D12__D12		IOMUX_PAD(0x28c, 0x094, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D12__GPIO_4_8		IOMUX_PAD(0x28c, 0x094, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D11__D11		IOMUX_PAD(0x290, 0x098, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D11__GPIO_4_9		IOMUX_PAD(0x290, 0x098, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D10__D10		IOMUX_PAD(0x294, 0x09c, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D10__GPIO_4_10		IOMUX_PAD(0x294, 0x09c, 0x05, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D10__USBOTG_OC		IOMUX_PAD(0x294, 0x09c, 0x06, 0x57c, 0, PAD_CTL_PUS_100K_UP)
-
-#define MX25_PAD_D9__D9			IOMUX_PAD(0x298, 0x0a0, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D9__GPIO_4_11		IOMUX_PAD(0x298, 0x0a0, 0x05, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D9__USBH2_PWR		IOMUX_PAD(0x298, 0x0a0, 0x06, 0, 0, PAD_CTL_PKE)
-
-#define MX25_PAD_D8__D8			IOMUX_PAD(0x29c, 0x0a4, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D8__GPIO_4_12		IOMUX_PAD(0x29c, 0x0a4, 0x05, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D8__USBH2_OC		IOMUX_PAD(0x29c, 0x0a4, 0x06, 0x580, 0, PAD_CTL_PUS_100K_UP)
-
-#define MX25_PAD_D7__D7			IOMUX_PAD(0x2a0, 0x0a8, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D7__GPIO_4_13		IOMUX_PAD(0x2a0, 0x0a8, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D6__D6			IOMUX_PAD(0x2a4, 0x0ac, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D6__GPIO_4_14		IOMUX_PAD(0x2a4, 0x0ac, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D5__D5			IOMUX_PAD(0x2a8, 0x0b0, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D5__GPIO_4_15		IOMUX_PAD(0x2a8, 0x0b0, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D4__D4			IOMUX_PAD(0x2ac, 0x0b4, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D4__GPIO_4_16		IOMUX_PAD(0x2ac, 0x0b4, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D3__D3			IOMUX_PAD(0x2b0, 0x0b8, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D3__GPIO_4_17		IOMUX_PAD(0x2b0, 0x0b8, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D2__D2			IOMUX_PAD(0x2b4, 0x0bc, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D2__GPIO_4_18		IOMUX_PAD(0x2b4, 0x0bc, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D1__D1			IOMUX_PAD(0x2b8, 0x0c0, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D1__GPIO_4_19		IOMUX_PAD(0x2b8, 0x0c0, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D0__D0			IOMUX_PAD(0x2bc, 0x0c4, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D0__GPIO_4_20		IOMUX_PAD(0x2bc, 0x0c4, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD0__LD0		IOMUX_PAD(0x2c0, 0x0c8, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD0__CSI_D0		IOMUX_PAD(0x2c0, 0x0c8, 0x12, 0x488, 0, NO_PAD_CTRL)
-#define MX25_PAD_LD0__GPIO_2_15		IOMUX_PAD(0x2c0, 0x0c8, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD1__LD1		IOMUX_PAD(0x2c4, 0x0cc, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD1__CSI_D1		IOMUX_PAD(0x2c4, 0x0cc, 0x12, 0x48c, 0, NO_PAD_CTRL)
-#define MX25_PAD_LD1__GPIO_2_16		IOMUX_PAD(0x2c4, 0x0cc, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD2__LD2		IOMUX_PAD(0x2c8, 0x0d0, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD2__GPIO_2_17		IOMUX_PAD(0x2c8, 0x0d0, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD3__LD3		IOMUX_PAD(0x2cc, 0x0d4, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD3__GPIO_2_18		IOMUX_PAD(0x2cc, 0x0d4, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD4__LD4		IOMUX_PAD(0x2d0, 0x0d8, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD4__GPIO_2_19		IOMUX_PAD(0x2d0, 0x0d8, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD5__LD5		IOMUX_PAD(0x2d4, 0x0dc, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD5__GPIO_1_19		IOMUX_PAD(0x2d4, 0x0dc, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD6__LD6		IOMUX_PAD(0x2d8, 0x0e0, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD6__GPIO_1_20		IOMUX_PAD(0x2d8, 0x0e0, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD7__LD7		IOMUX_PAD(0x2dc, 0x0e4, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD7__GPIO_1_21		IOMUX_PAD(0x2dc, 0x0e4, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD8__LD8		IOMUX_PAD(0x2e0, 0x0e8, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD8__FEC_TX_ERR	IOMUX_PAD(0x2e0, 0x0e8, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD9__LD9		IOMUX_PAD(0x2e4, 0x0ec, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD9__FEC_COL		IOMUX_PAD(0x2e4, 0x0ec, 0x15, 0x504, 1, NO_PAD_CTRL)
-
-#define MX25_PAD_LD10__LD10		IOMUX_PAD(0x2e8, 0x0f0, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD10__FEC_RX_ER	IOMUX_PAD(0x2e8, 0x0f0, 0x15, 0x518, 1, NO_PAD_CTRL)
-
-#define MX25_PAD_LD11__LD11		IOMUX_PAD(0x2ec, 0x0f4, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD11__FEC_RDATA2	IOMUX_PAD(0x2ec, 0x0f4, 0x15, 0x50c, 1, NO_PAD_CTRL)
-
-#define MX25_PAD_LD12__LD12		IOMUX_PAD(0x2f0, 0x0f8, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD12__FEC_RDATA3	IOMUX_PAD(0x2f0, 0x0f8, 0x15, 0x510, 1, NO_PAD_CTRL)
-
-#define MX25_PAD_LD13__LD13		IOMUX_PAD(0x2f4, 0x0fc, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD13__FEC_TDATA2	IOMUX_PAD(0x2f4, 0x0fc, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD14__LD14		IOMUX_PAD(0x2f8, 0x100, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD14__FEC_TDATA3	IOMUX_PAD(0x2f8, 0x100, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD15__LD15		IOMUX_PAD(0x2fc, 0x104, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD15__FEC_RX_CLK	IOMUX_PAD(0x2fc, 0x104, 0x15, 0x514, 1, NO_PAD_CTRL)
-
-#define MX25_PAD_HSYNC__HSYNC		IOMUX_PAD(0x300, 0x108, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_HSYNC__GPIO_1_22	IOMUX_PAD(0x300, 0x108, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_VSYNC__VSYNC		IOMUX_PAD(0x304, 0x10c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_VSYNC__GPIO_1_23	IOMUX_PAD(0x304, 0x10c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LSCLK__LSCLK		IOMUX_PAD(0x308, 0x110, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_LSCLK__GPIO_1_24	IOMUX_PAD(0x308, 0x110, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_OE_ACD__OE_ACD		IOMUX_PAD(0x30c, 0x114, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_OE_ACD__GPIO_1_25	IOMUX_PAD(0x30c, 0x114, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CONTRAST__CONTRAST	IOMUX_PAD(0x310, 0x118, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CONTRAST__PWM4_PWMO	IOMUX_PAD(0x310, 0x118, 0x14, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CONTRAST__FEC_CRS	IOMUX_PAD(0x310, 0x118, 0x15, 0x508, 1, NO_PAD_CTRL)
-
-#define MX25_PAD_PWM__PWM		IOMUX_PAD(0x314, 0x11c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_PWM__GPIO_1_26		IOMUX_PAD(0x314, 0x11c, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_PWM__USBH2_OC		IOMUX_PAD(0x314, 0x11c, 0x16, 0x580, 1, PAD_CTL_PUS_100K_UP)
-
-#define MX25_PAD_CSI_D2__CSI_D2		IOMUX_PAD(0x318, 0x120, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D2__UART5_RXD_MUX	IOMUX_PAD(0x318, 0x120, 0x11, 0x578, 1, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D2__GPIO_1_27	IOMUX_PAD(0x318, 0x120, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D2__CSPI3_MOSI	IOMUX_PAD(0x318, 0x120, 0x17, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_D3__CSI_D3		IOMUX_PAD(0x31c, 0x124, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D3__GPIO_1_28	IOMUX_PAD(0x31c, 0x124, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D3__CSPI3_MISO	IOMUX_PAD(0x31c, 0x124, 0x17, 0x4b4, 1, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_D4__CSI_D4		IOMUX_PAD(0x320, 0x128, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D4__UART5_RTS	IOMUX_PAD(0x320, 0x128, 0x11, 0x574, 1, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D4__GPIO_1_29	IOMUX_PAD(0x320, 0x128, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D4__CSPI3_SCLK	IOMUX_PAD(0x320, 0x128, 0x17, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_D5__CSI_D5		IOMUX_PAD(0x324, 0x12c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D5__GPIO_1_30	IOMUX_PAD(0x324, 0x12c, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D5__CSPI3_RDY	IOMUX_PAD(0x324, 0x12c, 0x17, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_D6__CSI_D6		IOMUX_PAD(0x328, 0x130, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D6__GPIO_1_31	IOMUX_PAD(0x328, 0x130, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_D7__CSI_D7		IOMUX_PAD(0x32c, 0x134, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D7__GPIO_1_6	IOMUX_PAD(0x32c, 0x134, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_D8__CSI_D8		IOMUX_PAD(0x330, 0x138, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D8__GPIO_1_7	IOMUX_PAD(0x330, 0x138, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_D9__CSI_D9		IOMUX_PAD(0x334, 0x13c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D9__GPIO_4_21	IOMUX_PAD(0x334, 0x13c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_MCLK__CSI_MCLK	IOMUX_PAD(0x338, 0x140, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_MCLK__GPIO_1_8	IOMUX_PAD(0x338, 0x140, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_VSYNC__CSI_VSYNC	IOMUX_PAD(0x33c, 0x144, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_VSYNC__GPIO_1_9	IOMUX_PAD(0x33c, 0x144, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_HSYNC__CSI_HSYNC	IOMUX_PAD(0x340, 0x148, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_HSYNC__GPIO_1_10	IOMUX_PAD(0x340, 0x148, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_PIXCLK__CSI_PIXCLK	IOMUX_PAD(0x344, 0x14c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_PIXCLK__GPIO_1_11	IOMUX_PAD(0x344, 0x14c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_I2C1_CLK__I2C1_CLK	IOMUX_PAD(0x348, 0x150, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_I2C1_CLK__GPIO_1_12	IOMUX_PAD(0x348, 0x150, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_I2C1_DAT__I2C1_DAT	IOMUX_PAD(0x34c, 0x154, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_I2C1_DAT__GPIO_1_13	IOMUX_PAD(0x34c, 0x154, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSPI1_MOSI__CSPI1_MOSI	IOMUX_PAD(0x350, 0x158, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSPI1_MOSI__GPIO_1_14	IOMUX_PAD(0x350, 0x158, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSPI1_MISO__CSPI1_MISO	IOMUX_PAD(0x354, 0x15c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSPI1_MISO__GPIO_1_15	IOMUX_PAD(0x354, 0x15c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSPI1_SS0__CSPI1_SS0	IOMUX_PAD(0x358, 0x160, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSPI1_SS0__GPIO_1_16	IOMUX_PAD(0x358, 0x160, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSPI1_SS1__CSPI1_SS1	IOMUX_PAD(0x35c, 0x164, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSPI1_SS1__GPIO_1_17	IOMUX_PAD(0x35c, 0x164, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSPI1_SCLK__CSPI1_SCLK	IOMUX_PAD(0x360, 0x168, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSPI1_SCLK__GPIO_1_18	IOMUX_PAD(0x360, 0x168, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSPI1_RDY__CSPI1_RDY	IOMUX_PAD(0x364, 0x16c, 0x10, 0, 0, PAD_CTL_PKE)
-#define MX25_PAD_CSPI1_RDY__GPIO_2_22	IOMUX_PAD(0x364, 0x16c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UART1_RXD__UART1_RXD	IOMUX_PAD(0x368, 0x170, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN)
-#define MX25_PAD_UART1_RXD__GPIO_4_22	IOMUX_PAD(0x368, 0x170, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UART1_TXD__UART1_TXD	IOMUX_PAD(0x36c, 0x174, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_UART1_TXD__GPIO_4_23	IOMUX_PAD(0x36c, 0x174, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UART1_RTS__UART1_RTS	IOMUX_PAD(0x370, 0x178, 0x10, 0, 0, PAD_CTL_PUS_100K_UP)
-#define MX25_PAD_UART1_RTS__CSI_D0	IOMUX_PAD(0x370, 0x178, 0x11, 0x488, 1, NO_PAD_CTRL)
-#define MX25_PAD_UART1_RTS__GPIO_4_24	IOMUX_PAD(0x370, 0x178, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UART1_CTS__UART1_CTS	IOMUX_PAD(0x374, 0x17c, 0x10, 0, 0, PAD_CTL_PUS_100K_UP)
-#define MX25_PAD_UART1_CTS__CSI_D1	IOMUX_PAD(0x374, 0x17c, 0x11, 0x48c, 1, NO_PAD_CTRL)
-#define MX25_PAD_UART1_CTS__GPIO_4_25	IOMUX_PAD(0x374, 0x17c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UART2_RXD__UART2_RXD	IOMUX_PAD(0x378, 0x180, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_UART2_RXD__GPIO_4_26	IOMUX_PAD(0x378, 0x180, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UART2_TXD__UART2_TXD	IOMUX_PAD(0x37c, 0x184, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_UART2_TXD__GPIO_4_27	IOMUX_PAD(0x37c, 0x184, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UART2_RTS__UART2_RTS	IOMUX_PAD(0x380, 0x188, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_UART2_RTS__FEC_COL	IOMUX_PAD(0x380, 0x188, 0x12, 0x504, 2, NO_PAD_CTRL)
-#define MX25_PAD_UART2_RTS__GPIO_4_28	IOMUX_PAD(0x380, 0x188, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UART2_CTS__FEC_RX_ER	IOMUX_PAD(0x384, 0x18c, 0x12, 0x518, 2, NO_PAD_CTRL)
-#define MX25_PAD_UART2_CTS__UART2_CTS	IOMUX_PAD(0x384, 0x18c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_UART2_CTS__GPIO_4_29	IOMUX_PAD(0x384, 0x18c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_SD1_CMD__SD1_CMD	IOMUX_PAD(0x388, 0x190, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
-#define MX25_PAD_SD1_CMD__FEC_RDATA2	IOMUX_PAD(0x388, 0x190, 0x12, 0x50c, 2, NO_PAD_CTRL)
-#define MX25_PAD_SD1_CMD__GPIO_2_23	IOMUX_PAD(0x388, 0x190, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_SD1_CLK__SD1_CLK	IOMUX_PAD(0x38c, 0x194, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
-#define MX25_PAD_SD1_CLK__FEC_RDATA3	IOMUX_PAD(0x38c, 0x194, 0x12, 0x510, 2, NO_PAD_CTRL)
-#define MX25_PAD_SD1_CLK__GPIO_2_24	IOMUX_PAD(0x38c, 0x194, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_SD1_DATA0__SD1_DATA0	IOMUX_PAD(0x390, 0x198, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
-#define MX25_PAD_SD1_DATA0__GPIO_2_25	IOMUX_PAD(0x390, 0x198, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_SD1_DATA1__SD1_DATA1	IOMUX_PAD(0x394, 0x19c, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
-#define MX25_PAD_SD1_DATA1__AUD7_RXD	IOMUX_PAD(0x394, 0x19c, 0x13, 0x478, 0, NO_PAD_CTRL)
-#define MX25_PAD_SD1_DATA1__GPIO_2_26	IOMUX_PAD(0x394, 0x19c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_SD1_DATA2__SD1_DATA2	IOMUX_PAD(0x398, 0x1a0, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
-#define MX25_PAD_SD1_DATA2__FEC_RX_CLK	IOMUX_PAD(0x398, 0x1a0, 0x15, 0x514, 2, NO_PAD_CTRL)
-#define MX25_PAD_SD1_DATA2__GPIO_2_27	IOMUX_PAD(0x398, 0x1a0, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_SD1_DATA3__SD1_DATA3	IOMUX_PAD(0x39c, 0x1a4, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
-#define MX25_PAD_SD1_DATA3__FEC_CRS	IOMUX_PAD(0x39c, 0x1a4, 0x10, 0x508, 2, NO_PAD_CTRL)
-#define MX25_PAD_SD1_DATA3__GPIO_2_28	IOMUX_PAD(0x39c, 0x1a4, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define KPP_CTL_ROW	(PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
-#define KPP_CTL_COL	(PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP | PAD_CTL_ODE)
-
-#define MX25_PAD_KPP_ROW0__KPP_ROW0	IOMUX_PAD(0x3a0, 0x1a8, 0x10, 0, 0, KPP_CTL_ROW)
-#define MX25_PAD_KPP_ROW0__GPIO_2_29	IOMUX_PAD(0x3a0, 0x1a8, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_KPP_ROW1__KPP_ROW1	IOMUX_PAD(0x3a4, 0x1ac, 0x10, 0, 0, KPP_CTL_ROW)
-#define MX25_PAD_KPP_ROW1__GPIO_2_30	IOMUX_PAD(0x3a4, 0x1ac, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_KPP_ROW2__KPP_ROW2	IOMUX_PAD(0x3a8, 0x1b0, 0x10, 0, 0, KPP_CTL_ROW)
-#define MX25_PAD_KPP_ROW2__CSI_D0	IOMUX_PAD(0x3a8, 0x1b0, 0x13, 0x488, 2, NO_PAD_CTRL)
-#define MX25_PAD_KPP_ROW2__GPIO_2_31	IOMUX_PAD(0x3a8, 0x1b0, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_KPP_ROW3__KPP_ROW3	IOMUX_PAD(0x3ac, 0x1b4, 0x10, 0, 0, KPP_CTL_ROW)
-#define MX25_PAD_KPP_ROW3__CSI_LD1	IOMUX_PAD(0x3ac, 0x1b4, 0x13, 0x48c, 2, NO_PAD_CTRL)
-#define MX25_PAD_KPP_ROW3__GPIO_3_0	IOMUX_PAD(0x3ac, 0x1b4, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_KPP_COL0__KPP_COL0	IOMUX_PAD(0x3b0, 0x1b8, 0x10, 0, 0, KPP_CTL_COL)
-#define MX25_PAD_KPP_COL0__UART4_RXD_MUX IOMUX_PAD(0x3b0, 0x1b8, 0x11, 0x570, 1, NO_PAD_CTRL)
-#define MX25_PAD_KPP_COL0__AUD5_TXD	IOMUX_PAD(0x3b0, 0x1b8, 0x12, 0, 0, PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
-#define MX25_PAD_KPP_COL0__GPIO_3_1	IOMUX_PAD(0x3b0, 0x1b8, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_KPP_COL1__KPP_COL1	IOMUX_PAD(0x3b4, 0x1bc, 0x10, 0, 0, KPP_CTL_COL)
-#define MX25_PAD_KPP_COL1__UART4_TXD_MUX IOMUX_PAD(0x3b4, 0x1bc, 0x11, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_KPP_COL1__AUD5_RXD	IOMUX_PAD(0x3b4, 0x1bc, 0x12, 0, 0, PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
-#define MX25_PAD_KPP_COL1__GPIO_3_2	IOMUX_PAD(0x3b4, 0x1bc, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_KPP_COL2__KPP_COL2	IOMUX_PAD(0x3b8, 0x1c0, 0x10, 0, 0, KPP_CTL_COL)
-#define MX25_PAD_KPP_COL2__UART4_RTS	IOMUX_PAD(0x3b8, 0x1c0, 0x11, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_KPP_COL2__AUD5_TXC	IOMUX_PAD(0x3b8, 0x1c0, 0x12, 0, 0, PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
-#define MX25_PAD_KPP_COL2__GPIO_3_3	IOMUX_PAD(0x3b8, 0x1c0, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_KPP_COL3__KPP_COL3	IOMUX_PAD(0x3bc, 0x1c4, 0x10, 0, 0, KPP_CTL_COL)
-#define MX25_PAD_KPP_COL3__UART4_CTS	IOMUX_PAD(0x3bc, 0x1c4, 0x11, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_KPP_COL3__AUD5_TXFS	IOMUX_PAD(0x3bc, 0x1c4, 0x12, 0, 0, PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
-#define MX25_PAD_KPP_COL3__GPIO_3_4	IOMUX_PAD(0x3bc, 0x1c4, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_MDC__FEC_MDC	IOMUX_PAD(0x3c0, 0x1c8, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_FEC_MDC__AUD4_TXD	IOMUX_PAD(0x3c0, 0x1c8, 0x12, 0x464, 1, NO_PAD_CTRL)
-#define MX25_PAD_FEC_MDC__GPIO_3_5	IOMUX_PAD(0x3c0, 0x1c8, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_MDIO__FEC_MDIO	IOMUX_PAD(0x3c4, 0x1cc, 0x10, 0, 0, PAD_CTL_HYS | PAD_CTL_PUS_22K_UP)
-#define MX25_PAD_FEC_MDIO__AUD4_RXD	IOMUX_PAD(0x3c4, 0x1cc, 0x12, 0x460, 1, NO_PAD_CTRL)
-#define MX25_PAD_FEC_MDIO__GPIO_3_6	IOMUX_PAD(0x3c4, 0x1cc, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_TDATA0__FEC_TDATA0	IOMUX_PAD(0x3c8, 0x1d0, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_FEC_TDATA0__GPIO_3_7	IOMUX_PAD(0x3c8, 0x1d0, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_TDATA1__FEC_TDATA1	IOMUX_PAD(0x3cc, 0x1d4, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_FEC_TDATA1__AUD4_TXFS	IOMUX_PAD(0x3cc, 0x1d4, 0x12, 0x474, 1, NO_PAD_CTRL)
-#define MX25_PAD_FEC_TDATA1__GPIO_3_8	IOMUX_PAD(0x3cc, 0x1d4, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_TX_EN__FEC_TX_EN	IOMUX_PAD(0x3d0, 0x1d8, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_FEC_TX_EN__GPIO_3_9   	IOMUX_PAD(0x3d0, 0x1d8, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_RDATA0__FEC_RDATA0	IOMUX_PAD(0x3d4, 0x1dc, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTRL)
-#define MX25_PAD_FEC_RDATA0__GPIO_3_10	IOMUX_PAD(0x3d4, 0x1dc, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_RDATA1__FEC_RDATA1	IOMUX_PAD(0x3d8, 0x1e0, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTRL)
-#define MX25_PAD_FEC_RDATA1__GPIO_3_11	IOMUX_PAD(0x3d8, 0x1e0, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_RX_DV__FEC_RX_DV	IOMUX_PAD(0x3dc, 0x1e4, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTRL)
-#define MX25_PAD_FEC_RX_DV__CAN2_RX	IOMUX_PAD(0x3dc, 0x1e4, 0x14, 0x484, 0, PAD_CTL_PUS_22K_UP)
-#define MX25_PAD_FEC_RX_DV__GPIO_3_12	IOMUX_PAD(0x3dc, 0x1e4, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_TX_CLK__FEC_TX_CLK	IOMUX_PAD(0x3e0, 0x1e8, 0x10, 0, 0, PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN)
-#define MX25_PAD_FEC_TX_CLK__GPIO_3_13	IOMUX_PAD(0x3e0, 0x1e8, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_RTCK__RTCK		IOMUX_PAD(0x3e4, 0x1ec, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_RTCK__OWIRE		IOMUX_PAD(0x3e4, 0x1ec, 0x11, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_RTCK__GPIO_3_14	IOMUX_PAD(0x3e4, 0x1ec, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_DE_B__DE_B		IOMUX_PAD(0x3ec, 0x1f0, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_DE_B__GPIO_2_20	IOMUX_PAD(0x3ec, 0x1f0, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_TDO__TDO		IOMUX_PAD(0x3e8, 0x000, 0x00, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_GPIO_A__GPIO_A		IOMUX_PAD(0x3f0, 0x1f4, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_GPIO_A__CAN1_TX	IOMUX_PAD(0x3f0, 0x1f4, 0x16, 0, 0, PAD_CTL_PUS_22K_UP)
-#define MX25_PAD_GPIO_A__USBOTG_PWR	IOMUX_PAD(0x3f0, 0x1f4, 0x12, 0, 0, PAD_CTL_PKE)
-
-#define MX25_PAD_GPIO_B__GPIO_B		IOMUX_PAD(0x3f4, 0x1f8, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_GPIO_B__CAN1_RX	IOMUX_PAD(0x3f4, 0x1f8, 0x16, 0x480, 1, PAD_CTL_PUS_22K_UP)
-#define MX25_PAD_GPIO_B__USBOTG_OC	IOMUX_PAD(0x3f4, 0x1f8, 0x12, 0x57c, 1, PAD_CTL_PUS_100K_UP)
-
-#define MX25_PAD_GPIO_C__GPIO_C		IOMUX_PAD(0x3f8, 0x1fc, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_GPIO_C__CAN2_TX	IOMUX_PAD(0x3f8, 0x1fc, 0x16, 0, 0, PAD_CTL_PUS_22K_UP)
-
-#define MX25_PAD_GPIO_D__GPIO_D		IOMUX_PAD(0x3fc, 0x200, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_GPIO_E__LD16		IOMUX_PAD(0x400, 0x204, 0x02, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_GPIO_D__CAN2_RX	IOMUX_PAD(0x3fc, 0x200, 0x16, 0x484, 1, PAD_CTL_PUS_22K_UP)
-
-#define MX25_PAD_GPIO_E__GPIO_E		IOMUX_PAD(0x400, 0x204, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_GPIO_F__LD17		IOMUX_PAD(0x404, 0x208, 0x02, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_GPIO_E__AUD7_TXD	IOMUX_PAD(0x400, 0x204, 0x14, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_GPIO_F__GPIO_F		IOMUX_PAD(0x404, 0x208, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_GPIO_F__AUD7_TXC	IOMUX_PAD(0x404, 0x208, 0x14, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_EXT_ARMCLK__EXT_ARMCLK	IOMUX_PAD(0x000, 0x20c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_EXT_ARMCLK__GPIO_3_15	IOMUX_PAD(0x000, 0x20c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UPLL_BYPCLK__UPLL_BYPCLK IOMUX_PAD(0x000, 0x210, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_UPLL_BYPCLK__GPIO_3_16	IOMUX_PAD(0x000, 0x210, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_VSTBY_REQ__VSTBY_REQ	IOMUX_PAD(0x408, 0x214, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_VSTBY_REQ__AUD7_TXFS	IOMUX_PAD(0x408, 0x214, 0x14, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_VSTBY_REQ__GPIO_3_17	IOMUX_PAD(0x408, 0x214, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_VSTBY_ACK__VSTBY_ACK	IOMUX_PAD(0x40c, 0x218, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_VSTBY_ACK__GPIO_3_18	IOMUX_PAD(0x40c, 0x218, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_POWER_FAIL__POWER_FAIL	IOMUX_PAD(0x410, 0x21c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_POWER_FAIL__AUD7_RXD	IOMUX_PAD(0x410, 0x21c, 0x14, 0x478, 1, NO_PAD_CTRL)
-#define MX25_PAD_POWER_FAIL__GPIO_3_19	IOMUX_PAD(0x410, 0x21c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CLKO__CLKO		IOMUX_PAD(0x414, 0x220, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CLKO__GPIO_2_21	IOMUX_PAD(0x414, 0x220, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_BOOT_MODE0__BOOT_MODE0	IOMUX_PAD(0x000, 0x224, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_BOOT_MODE0__GPIO_4_30	IOMUX_PAD(0x000, 0x224, 0x05, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_BOOT_MODE1__BOOT_MODE1	IOMUX_PAD(0x000, 0x228, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_BOOT_MODE1__GPIO_4_31	IOMUX_PAD(0x000, 0x228, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CTL_GRP_DVS_MISC	IOMUX_PAD(0x418, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_FEC	IOMUX_PAD(0x41c, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DVS_JTAG	IOMUX_PAD(0x420, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_NFC	IOMUX_PAD(0x424, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_CSI	IOMUX_PAD(0x428, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_WEIM	IOMUX_PAD(0x42c, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_DDR	IOMUX_PAD(0x430, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DVS_CRM	IOMUX_PAD(0x434, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_KPP	IOMUX_PAD(0x438, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_SDHC1	IOMUX_PAD(0x43c, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_LCD	IOMUX_PAD(0x440, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_UART	IOMUX_PAD(0x444, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DVS_NFC	IOMUX_PAD(0x448, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DVS_CSI	IOMUX_PAD(0x44c, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_CSPI1	IOMUX_PAD(0x450, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DDRTYPE	IOMUX_PAD(0x454, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DVS_SDHC1	IOMUX_PAD(0x458, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DVS_LCD	IOMUX_PAD(0x45c, 0x000, 0, 0, 0, NO_PAD_CTRL)
-
-#endif /* __MACH_IOMUX_MX25_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx27.h b/arch/arm/plat-mxc/include/mach/iomux-mx27.h
deleted file mode 100644
index d9f9a6e..0000000
--- a/arch/arm/plat-mxc/include/mach/iomux-mx27.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
- * Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-#ifndef __MACH_IOMUX_MX27_H__
-#define __MACH_IOMUX_MX27_H__
-
-#include <mach/iomux-mx2x.h>
-#include <mach/iomux-v1.h>
-
-/* Primary GPIO pin functions */
-
-#define PA0_PF_USBH2_CLK	(GPIO_PORTA | GPIO_PF | 0)
-#define PA1_PF_USBH2_DIR	(GPIO_PORTA | GPIO_PF | 1)
-#define PA2_PF_USBH2_DATA7	(GPIO_PORTA | GPIO_PF | 2)
-#define PA3_PF_USBH2_NXT	(GPIO_PORTA | GPIO_PF | 3)
-#define PA4_PF_USBH2_STP	(GPIO_PORTA | GPIO_PF | 4)
-#define PB22_PF_USBH1_SUSP	(GPIO_PORTB | GPIO_PF | 22)
-#define PB25_PF_USBH1_RCV	(GPIO_PORTB | GPIO_PF | 25)
-#define PC5_PF_I2C2_SDA		(GPIO_PORTC | GPIO_PF | GPIO_IN | 5)
-#define PC6_PF_I2C2_SCL		(GPIO_PORTC | GPIO_PF | GPIO_IN | 6)
-#define PC7_PF_USBOTG_DATA5	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 7)
-#define PC8_PF_USBOTG_DATA6	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 8)
-#define PC9_PF_USBOTG_DATA0	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 9)
-#define PC10_PF_USBOTG_DATA2	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 10)
-#define PC11_PF_USBOTG_DATA1	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 11)
-#define PC12_PF_USBOTG_DATA4	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 12)
-#define PC13_PF_USBOTG_DATA3	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 13)
-#define PC16_PF_SSI4_FS		(GPIO_PORTC | GPIO_PF | GPIO_IN | 16)
-#define PC17_PF_SSI4_RXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 17)
-#define PC18_PF_SSI4_TXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 18)
-#define PC19_PF_SSI4_CLK	(GPIO_PORTC | GPIO_PF | GPIO_IN | 19)
-#define PD0_PF_SD3_CMD		(GPIO_PORTD | GPIO_PF | 0)
-#define PD1_PF_SD3_CLK		(GPIO_PORTD | GPIO_PF | 1)
-#define PD2_PF_ATA_DATA0	(GPIO_PORTD | GPIO_PF | 2)
-#define PD3_PF_ATA_DATA1	(GPIO_PORTD | GPIO_PF | 3)
-#define PD4_PF_ATA_DATA2	(GPIO_PORTD | GPIO_PF | 4)
-#define PD5_PF_ATA_DATA3	(GPIO_PORTD | GPIO_PF | 5)
-#define PD6_PF_ATA_DATA4	(GPIO_PORTD | GPIO_PF | 6)
-#define PD7_PF_ATA_DATA5	(GPIO_PORTD | GPIO_PF | 7)
-#define PD8_PF_ATA_DATA6	(GPIO_PORTD | GPIO_PF | 8)
-#define PD9_PF_ATA_DATA7	(GPIO_PORTD | GPIO_PF | 9)
-#define PD10_PF_ATA_DATA8	(GPIO_PORTD | GPIO_PF | 10)
-#define PD11_PF_ATA_DATA9	(GPIO_PORTD | GPIO_PF | 11)
-#define PD12_PF_ATA_DATA10	(GPIO_PORTD | GPIO_PF | 12)
-#define PD13_PF_ATA_DATA11	(GPIO_PORTD | GPIO_PF | 13)
-#define PD14_PF_ATA_DATA12	(GPIO_PORTD | GPIO_PF | 14)
-#define PD15_PF_ATA_DATA13	(GPIO_PORTD | GPIO_PF | 15)
-#define PD16_PF_ATA_DATA14	(GPIO_PORTD | GPIO_PF | 16)
-#define PE0_PF_USBOTG_NXT	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 0)
-#define PE1_PF_USBOTG_STP	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 1)
-#define PE2_PF_USBOTG_DIR	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 2)
-#define PE24_PF_USBOTG_CLK	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 24)
-#define PE25_PF_USBOTG_DATA7	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 25)
-#define PF1_PF_NFCLE		(GPIO_PORTF | GPIO_PF | 1)
-#define PF3_PF_NFCE		(GPIO_PORTF | GPIO_PF | 3)
-#define PF7_PF_PC_POE		(GPIO_PORTF | GPIO_PF | 7)
-#define PF8_PF_PC_RW		(GPIO_PORTF | GPIO_PF | 8)
-#define PF9_PF_PC_IOIS16	(GPIO_PORTF | GPIO_PF | 9)
-#define PF10_PF_PC_RST		(GPIO_PORTF | GPIO_PF | 10)
-#define PF11_PF_PC_BVD2		(GPIO_PORTF | GPIO_PF | 11)
-#define PF12_PF_PC_BVD1		(GPIO_PORTF | GPIO_PF | 12)
-#define PF13_PF_PC_VS2		(GPIO_PORTF | GPIO_PF | 13)
-#define PF14_PF_PC_VS1		(GPIO_PORTF | GPIO_PF | 14)
-#define PF16_PF_PC_PWRON	(GPIO_PORTF | GPIO_PF | 16)
-#define PF17_PF_PC_READY	(GPIO_PORTF | GPIO_PF | 17)
-#define PF18_PF_PC_WAIT		(GPIO_PORTF | GPIO_PF | 18)
-#define PF19_PF_PC_CD2		(GPIO_PORTF | GPIO_PF | 19)
-#define PF20_PF_PC_CD1		(GPIO_PORTF | GPIO_PF | 20)
-#define PF23_PF_ATA_DATA15	(GPIO_PORTF | GPIO_PF | 23)
-
-/* Alternate GPIO pin functions */
-
-#define PB4_AF_MSHC_DATA0	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 4)
-#define PB5_AF_MSHC_DATA1	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 5)
-#define PB6_AF_MSHC_DATA2	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 6)
-#define PB7_AF_MSHC_DATA4	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 7)
-#define PB8_AF_MSHC_BS		(GPIO_PORTB | GPIO_AF | GPIO_OUT | 8)
-#define PB9_AF_MSHC_SCLK	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 9)
-#define PB10_AF_UART6_TXD	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 10)
-#define PB11_AF_UART6_RXD	(GPIO_PORTB | GPIO_AF | GPIO_IN | 11)
-#define PB12_AF_UART6_CTS	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 12)
-#define PB13_AF_UART6_RTS	(GPIO_PORTB | GPIO_AF | GPIO_IN | 13)
-#define PB18_AF_UART5_TXD	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 18)
-#define PB19_AF_UART5_RXD	(GPIO_PORTB | GPIO_AF | GPIO_IN | 19)
-#define PB20_AF_UART5_CTS	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 20)
-#define PB21_AF_UART5_RTS	(GPIO_PORTB | GPIO_AF | GPIO_IN | 21)
-#define PC8_AF_FEC_MDIO		(GPIO_PORTC | GPIO_AF | GPIO_IN | 8)
-#define PC24_AF_GPT5_TOUT	(GPIO_PORTC | GPIO_AF | 24)
-#define PC25_AF_GPT5_TIN	(GPIO_PORTC | GPIO_AF | 25)
-#define PC26_AF_GPT4_TOUT	(GPIO_PORTC | GPIO_AF | 26)
-#define PC27_AF_GPT4_TIN	(GPIO_PORTC | GPIO_AF | 27)
-#define PD1_AF_ETMTRACE_PKT15	(GPIO_PORTD | GPIO_AF | 1)
-#define PD6_AF_ETMTRACE_PKT14	(GPIO_PORTD | GPIO_AF | 6)
-#define PD7_AF_ETMTRACE_PKT13	(GPIO_PORTD | GPIO_AF | 7)
-#define PD9_AF_ETMTRACE_PKT12	(GPIO_PORTD | GPIO_AF | 9)
-#define PD2_AF_SD3_D0		(GPIO_PORTD | GPIO_AF | 2)
-#define PD3_AF_SD3_D1		(GPIO_PORTD | GPIO_AF | 3)
-#define PD4_AF_SD3_D2		(GPIO_PORTD | GPIO_AF | 4)
-#define PD5_AF_SD3_D3		(GPIO_PORTD | GPIO_AF | 5)
-#define PD8_AF_FEC_MDIO		(GPIO_PORTD | GPIO_AF | GPIO_IN | 8)
-#define PD10_AF_ETMTRACE_PKT11	(GPIO_PORTD | GPIO_AF | 10)
-#define PD11_AF_ETMTRACE_PKT10	(GPIO_PORTD | GPIO_AF | 11)
-#define PD12_AF_ETMTRACE_PKT9	(GPIO_PORTD | GPIO_AF | 12)
-#define PD13_AF_ETMTRACE_PKT8	(GPIO_PORTD | GPIO_AF | 13)
-#define PD14_AF_ETMTRACE_PKT7	(GPIO_PORTD | GPIO_AF | 14)
-#define PD15_AF_ETMTRACE_PKT6	(GPIO_PORTD | GPIO_AF | 15)
-#define PD16_AF_ETMTRACE_PKT5	(GPIO_PORTD | GPIO_AF | 16)
-#define PF1_AF_ETMTRACE_PKT0	(GPIO_PORTF | GPIO_AF | 1)
-#define PF3_AF_ETMTRACE_PKT2	(GPIO_PORTF | GPIO_AF | 3)
-#define PF5_AF_ETMPIPESTAT11	(GPIO_PORTF | GPIO_AF | 5)
-#define PF7_AF_ATA_BUFFER_EN	(GPIO_PORTF | GPIO_AF | 7)
-#define PF8_AF_ATA_IORDY	(GPIO_PORTF | GPIO_AF | 8)
-#define PF9_AF_ATA_INTRQ	(GPIO_PORTF | GPIO_AF | 9)
-#define PF10_AF_ATA_RESET	(GPIO_PORTF | GPIO_AF | 10)
-#define PF11_AF_ATA_DMACK	(GPIO_PORTF | GPIO_AF | 11)
-#define PF12_AF_ATA_DMAREQ	(GPIO_PORTF | GPIO_AF | 12)
-#define PF13_AF_ATA_DA0		(GPIO_PORTF | GPIO_AF | 13)
-#define PF14_AF_ATA_DA1		(GPIO_PORTF | GPIO_AF | 14)
-#define PF15_AF_ETMTRACE_SYNC	(GPIO_PORTF | GPIO_AF | 15)
-#define PF16_AF_ATA_DA2		(GPIO_PORTF | GPIO_AF | 16)
-#define PF17_AF_ATA_CS0		(GPIO_PORTF | GPIO_AF | 17)
-#define PF18_AF_ATA_CS1		(GPIO_PORTF | GPIO_AF | 18)
-#define PF19_AF_ATA_DIOW	(GPIO_PORTF | GPIO_AF | 19)
-#define PF20_AF_ATA_DIOR	(GPIO_PORTF | GPIO_AF | 20)
-#define PF22_AF_ETMTRACE_CLK	(GPIO_PORTF | GPIO_AF | 22)
-#define PF23_AF_ETMTRACE_PKT4	(GPIO_PORTF | GPIO_AF | 23)
-
-/* AIN GPIO pin functions */
-
-#define PC14_AIN_SSI1_MCLK	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 14)
-#define PC15_AIN_GPT6_TOUT	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 15)
-#define PD0_AIN_FEC_TXD0	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 0)
-#define PD1_AIN_FEC_TXD1	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 1)
-#define PD2_AIN_FEC_TXD2	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 2)
-#define PD3_AIN_FEC_TXD3	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 3)
-#define PD9_AIN_FEC_MDC		(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 9)
-#define PD16_AIN_FEC_TX_ER	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 16)
-#define PD27_AIN_EXT_DMA_GRANT	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 27)
-#define PF23_AIN_FEC_TX_EN	(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 23)
-
-/* BIN GPIO pin functions */
-
-#define PC14_BIN_SSI2_MCLK	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 14)
-
-/* CIN GPIO pin functions */
-
-#define PD2_CIN_SLCDC1_DAT0	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 2)
-#define PD3_CIN_SLCDC1_DAT1	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 3)
-#define PD4_CIN_SLCDC1_DAT2	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 4)
-#define PD5_CIN_SLCDC1_DAT3	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 5)
-#define PD6_CIN_SLCDC1_DAT4	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 6)
-#define PD7_CIN_SLCDC1_DAT5	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 7)
-#define PD8_CIN_SLCDC1_DAT6	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 8)
-#define PD9_CIN_SLCDC1_DAT7	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 9)
-#define PD10_CIN_SLCDC1_DAT8	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 10)
-#define PD11_CIN_SLCDC1_DAT9	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 11)
-#define PD12_CIN_SLCDC1_DAT10	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 12)
-#define PD13_CIN_SLCDC1_DAT11	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 13)
-#define PD14_CIN_SLCDC1_DAT12	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 14)
-#define PD15_CIN_SLCDC1_DAT13	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 15)
-#define PD16_CIN_SLCDC1_DAT14	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 16)
-#define PD23_CIN_SLCDC1_DAT15	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 23)
-#define PF27_CIN_EXT_DMA_GRANT	(GPIO_PORTF | GPIO_CIN | GPIO_OUT | 27)
-/* LCDC_TESTx on PBxx omitted, because it's not clear what they do */
-
-/* AOUT GPIO pin functions */
-
-#define PC14_AOUT_GPT6_TIN	(GPIO_PORTC | GPIO_AOUT | GPIO_IN | 14)
-#define PD4_AOUT_FEC_RX_ER	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 4)
-#define PD5_AOUT_FEC_RXD1	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 5)
-#define PD6_AOUT_FEC_RXD2	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 6)
-#define PD7_AOUT_FEC_RXD3	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 7)
-#define PD10_AOUT_FEC_CRS	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 10)
-#define PD11_AOUT_FEC_TX_CLK	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 11)
-#define PD12_AOUT_FEC_RXD0	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 12)
-#define PD13_AOUT_FEC_RX_DV	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 13)
-#define PD14_AOUT_FEC_RX_CLK	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 14)
-#define PD15_AOUT_FEC_COL	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 15)
-
-/* BOUT GPIO pin functions */
-
-#define PC17_BOUT_PC_IOIS16	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 17)
-#define PC18_BOUT_PC_BVD2	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 18)
-#define PC19_BOUT_PC_BVD1	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 19)
-#define PC28_BOUT_PC_BVD2	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 28)
-#define PC29_BOUT_PC_VS1	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 29)
-#define PC30_BOUT_PC_READY	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 30)
-#define PC31_BOUT_PC_WAIT	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 31)
-
-#endif /* __MACH_IOMUX_MX27_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx2x.h b/arch/arm/plat-mxc/include/mach/iomux-mx2x.h
deleted file mode 100644
index 7a9b20a..0000000
--- a/arch/arm/plat-mxc/include/mach/iomux-mx2x.h
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
- * Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-#ifndef __MACH_IOMUX_MX2x_H__
-#define __MACH_IOMUX_MX2x_H__
-
-/* Primary GPIO pin functions */
-
-#define PA5_PF_LSCLK		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 5)
-#define PA6_PF_LD0		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 6)
-#define PA7_PF_LD1		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 7)
-#define PA8_PF_LD2		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 8)
-#define PA9_PF_LD3		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 9)
-#define PA10_PF_LD4		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 10)
-#define PA11_PF_LD5		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 11)
-#define PA12_PF_LD6		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 12)
-#define PA13_PF_LD7		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 13)
-#define PA14_PF_LD8		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 14)
-#define PA15_PF_LD9		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 15)
-#define PA16_PF_LD10		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 16)
-#define PA17_PF_LD11		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 17)
-#define PA18_PF_LD12		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 18)
-#define PA19_PF_LD13		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 19)
-#define PA20_PF_LD14		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 20)
-#define PA21_PF_LD15		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 21)
-#define PA22_PF_LD16		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 22)
-#define PA23_PF_LD17		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 23)
-#define PA24_PF_REV		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 24)
-#define PA25_PF_CLS		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 25)
-#define PA26_PF_PS		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 26)
-#define PA27_PF_SPL_SPR		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 27)
-#define PA28_PF_HSYNC		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 28)
-#define PA29_PF_VSYNC		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 29)
-#define PA30_PF_CONTRAST	(GPIO_PORTA | GPIO_PF | GPIO_OUT | 30)
-#define PA31_PF_OE_ACD		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 31)
-#define PB4_PF_SD2_D0		(GPIO_PORTB | GPIO_PF | 4)
-#define PB5_PF_SD2_D1		(GPIO_PORTB | GPIO_PF | 5)
-#define PB6_PF_SD2_D2		(GPIO_PORTB | GPIO_PF | 6)
-#define PB7_PF_SD2_D3		(GPIO_PORTB | GPIO_PF | 7)
-#define PB8_PF_SD2_CMD		(GPIO_PORTB | GPIO_PF | 8)
-#define PB9_PF_SD2_CLK		(GPIO_PORTB | GPIO_PF | 9)
-#define PB10_PF_CSI_D0		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 10)
-#define PB11_PF_CSI_D1		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 11)
-#define PB12_PF_CSI_D2		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 12)
-#define PB13_PF_CSI_D3		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 13)
-#define PB14_PF_CSI_D4		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 14)
-#define PB15_PF_CSI_MCLK	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 15)
-#define PB16_PF_CSI_PIXCLK	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 16)
-#define PB17_PF_CSI_D5		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 17)
-#define PB18_PF_CSI_D6		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 18)
-#define PB19_PF_CSI_D7		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 19)
-#define PB20_PF_CSI_VSYNC	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 20)
-#define PB21_PF_CSI_HSYNC	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 21)
-#define PB23_PF_USB_PWR		(GPIO_PORTB | GPIO_PF | 23)
-#define PB24_PF_USB_OC		(GPIO_PORTB | GPIO_PF | 24)
-#define PB26_PF_USBH1_FS	(GPIO_PORTB | GPIO_PF | 26)
-#define PB27_PF_USBH1_OE	(GPIO_PORTB | GPIO_PF | 27)
-#define PB28_PF_USBH1_TXDM	(GPIO_PORTB | GPIO_PF | 28)
-#define PB29_PF_USBH1_TXDP	(GPIO_PORTB | GPIO_PF | 29)
-#define PB30_PF_USBH1_RXDM	(GPIO_PORTB | GPIO_PF | 30)
-#define PB31_PF_USBH1_RXDP	(GPIO_PORTB | GPIO_PF | 31)
-#define PC14_PF_TOUT		(GPIO_PORTC | GPIO_PF | 14)
-#define PC15_PF_TIN		(GPIO_PORTC | GPIO_PF | 15)
-#define PC20_PF_SSI1_FS		(GPIO_PORTC | GPIO_PF | GPIO_IN | 20)
-#define PC21_PF_SSI1_RXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 21)
-#define PC22_PF_SSI1_TXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 22)
-#define PC23_PF_SSI1_CLK	(GPIO_PORTC | GPIO_PF | GPIO_IN | 23)
-#define PC24_PF_SSI2_FS		(GPIO_PORTC | GPIO_PF | GPIO_IN | 24)
-#define PC25_PF_SSI2_RXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 25)
-#define PC26_PF_SSI2_TXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 26)
-#define PC27_PF_SSI2_CLK	(GPIO_PORTC | GPIO_PF | GPIO_IN | 27)
-#define PC28_PF_SSI3_FS		(GPIO_PORTC | GPIO_PF | GPIO_IN | 28)
-#define PC29_PF_SSI3_RXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 29)
-#define PC30_PF_SSI3_TXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 30)
-#define PC31_PF_SSI3_CLK	(GPIO_PORTC | GPIO_PF | GPIO_IN | 31)
-#define PD17_PF_I2C_DATA	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 17)
-#define PD18_PF_I2C_CLK		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 18)
-#define PD19_PF_CSPI2_SS2	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 19)
-#define PD20_PF_CSPI2_SS1	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 20)
-#define PD21_PF_CSPI2_SS0	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 21)
-#define PD22_PF_CSPI2_SCLK	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 22)
-#define PD23_PF_CSPI2_MISO	(GPIO_PORTD | GPIO_PF | GPIO_IN | 23)
-#define PD24_PF_CSPI2_MOSI	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 24)
-#define PD25_PF_CSPI1_RDY	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 25)
-#define PD26_PF_CSPI1_SS2	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 26)
-#define PD27_PF_CSPI1_SS1	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 27)
-#define PD28_PF_CSPI1_SS0	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 28)
-#define PD29_PF_CSPI1_SCLK	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 29)
-#define PD30_PF_CSPI1_MISO	(GPIO_PORTD | GPIO_PF | GPIO_IN | 30)
-#define PD31_PF_CSPI1_MOSI	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 31)
-#define PE3_PF_UART2_CTS	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 3)
-#define PE4_PF_UART2_RTS	(GPIO_PORTE | GPIO_PF | GPIO_IN | 4)
-#define PE5_PF_PWMO		(GPIO_PORTE | GPIO_PF | 5)
-#define PE6_PF_UART2_TXD	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 6)
-#define PE7_PF_UART2_RXD	(GPIO_PORTE | GPIO_PF | GPIO_IN | 7)
-#define PE8_PF_UART3_TXD	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 8)
-#define PE9_PF_UART3_RXD	(GPIO_PORTE | GPIO_PF | GPIO_IN | 9)
-#define PE10_PF_UART3_CTS	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 10)
-#define PE11_PF_UART3_RTS	(GPIO_PORTE | GPIO_PF | GPIO_IN | 11)
-#define PE12_PF_UART1_TXD	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 12)
-#define PE13_PF_UART1_RXD	(GPIO_PORTE | GPIO_PF | GPIO_IN | 13)
-#define PE14_PF_UART1_CTS	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 14)
-#define PE15_PF_UART1_RTS	(GPIO_PORTE | GPIO_PF | GPIO_IN | 15)
-#define PE16_PF_RTCK		(GPIO_PORTE | GPIO_PF | GPIO_OUT | 16)
-#define PE17_PF_RESET_OUT	(GPIO_PORTE | GPIO_PF | 17)
-#define PE18_PF_SD1_D0		(GPIO_PORTE | GPIO_PF | 18)
-#define PE19_PF_SD1_D1		(GPIO_PORTE | GPIO_PF | 19)
-#define PE20_PF_SD1_D2		(GPIO_PORTE | GPIO_PF | 20)
-#define PE21_PF_SD1_D3		(GPIO_PORTE | GPIO_PF | 21)
-#define PE22_PF_SD1_CMD		(GPIO_PORTE | GPIO_PF | 22)
-#define PE23_PF_SD1_CLK		(GPIO_PORTE | GPIO_PF | 23)
-#define PF0_PF_NRFB		(GPIO_PORTF | GPIO_PF | 0)
-#define PF2_PF_NFWP		(GPIO_PORTF | GPIO_PF | 2)
-#define PF4_PF_NFALE		(GPIO_PORTF | GPIO_PF | 4)
-#define PF5_PF_NFRE		(GPIO_PORTF | GPIO_PF | 5)
-#define PF6_PF_NFWE		(GPIO_PORTF | GPIO_PF | 6)
-#define PF15_PF_CLKO		(GPIO_PORTF | GPIO_PF | 15)
-#define PF21_PF_CS4		(GPIO_PORTF | GPIO_PF | 21)
-#define PF22_PF_CS5		(GPIO_PORTF | GPIO_PF | 22)
-
-/* Alternate GPIO pin functions */
-
-#define PB26_AF_UART4_RTS	(GPIO_PORTB | GPIO_AF | GPIO_IN | 26)
-#define PB28_AF_UART4_TXD	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 28)
-#define PB29_AF_UART4_CTS	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 29)
-#define PB31_AF_UART4_RXD	(GPIO_PORTB | GPIO_AF | GPIO_IN | 31)
-#define PC28_AF_SLCDC2_D0	(GPIO_PORTC | GPIO_AF | 28)
-#define PC29_AF_SLCDC2_RS	(GPIO_PORTC | GPIO_AF | 29)
-#define PC30_AF_SLCDC2_CS	(GPIO_PORTC | GPIO_AF | 30)
-#define PC31_AF_SLCDC2_CLK	(GPIO_PORTC | GPIO_AF | 31)
-#define PD19_AF_USBH2_DATA4	(GPIO_PORTD | GPIO_AF | 19)
-#define PD20_AF_USBH2_DATA3	(GPIO_PORTD | GPIO_AF | 20)
-#define PD21_AF_USBH2_DATA6	(GPIO_PORTD | GPIO_AF | 21)
-#define PD22_AF_USBH2_DATA0	(GPIO_PORTD | GPIO_AF | 22)
-#define PD23_AF_USBH2_DATA2	(GPIO_PORTD | GPIO_AF | 23)
-#define PD24_AF_USBH2_DATA1	(GPIO_PORTD | GPIO_AF | 24)
-#define PD26_AF_USBH2_DATA5	(GPIO_PORTD | GPIO_AF | 26)
-#define PE0_AF_KP_COL6		(GPIO_PORTE | GPIO_AF | 0)
-#define PE1_AF_KP_ROW6		(GPIO_PORTE | GPIO_AF | 1)
-#define PE2_AF_KP_ROW7		(GPIO_PORTE | GPIO_AF | 2)
-#define PE3_AF_KP_COL7		(GPIO_PORTE | GPIO_AF | 3)
-#define PE4_AF_KP_ROW7		(GPIO_PORTE | GPIO_AF | 4)
-#define PE6_AF_KP_COL6		(GPIO_PORTE | GPIO_AF | 6)
-#define PE7_AF_KP_ROW6		(GPIO_PORTE | GPIO_AF | 7)
-#define PE16_AF_OWIRE		(GPIO_PORTE | GPIO_AF | 16)
-#define PE18_AF_CSPI3_MISO	(GPIO_PORTE | GPIO_AF | GPIO_IN | 18)
-#define PE21_AF_CSPI3_SS	(GPIO_PORTE | GPIO_AF | GPIO_OUT | 21)
-#define PE22_AF_CSPI3_MOSI	(GPIO_PORTE | GPIO_AF | GPIO_OUT | 22)
-#define PE23_AF_CSPI3_SCLK	(GPIO_PORTE | GPIO_AF | GPIO_OUT | 23)
-
-/* AIN GPIO pin functions */
-
-#define PA6_AIN_SLCDC1_DAT0	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 6)
-#define PA7_AIN_SLCDC1_DAT1	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 7)
-#define PA8_AIN_SLCDC1_DAT2	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 8)
-#define PA0_AIN_SLCDC1_DAT3	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 0)
-#define PA11_AIN_SLCDC1_DAT5	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 11)
-#define PA13_AIN_SLCDC1_DAT7	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 13)
-#define PA15_AIN_SLCDC1_DAT9	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 15)
-#define PA17_AIN_SLCDC1_DAT11	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 17)
-#define PA19_AIN_SLCDC1_DAT13	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 19)
-#define PA21_AIN_SLCDC1_DAT15	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 21)
-#define PA22_AIN_EXT_DMAGRANT	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 22)
-#define PA24_AIN_SLCDC1_D0	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 24)
-#define PA25_AIN_SLCDC1_RS	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 25)
-#define PA26_AIN_SLCDC1_CS	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 26)
-#define PA27_AIN_SLCDC1_CLK	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 27)
-#define PB6_AIN_SLCDC1_D0	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 6)
-#define PB7_AIN_SLCDC1_RS	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 7)
-#define PB8_AIN_SLCDC1_CS	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 8)
-#define PB9_AIN_SLCDC1_CLK	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 9)
-#define PB25_AIN_SLCDC1_DAT0	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 25)
-#define PB26_AIN_SLCDC1_DAT1	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 26)
-#define PB27_AIN_SLCDC1_DAT2	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 27)
-#define PB28_AIN_SLCDC1_DAT3	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 28)
-#define PB29_AIN_SLCDC1_DAT4	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 29)
-#define PB30_AIN_SLCDC1_DAT5	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 30)
-#define PB31_AIN_SLCDC1_DAT6	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 31)
-#define PC5_AIN_SLCDC1_DAT7	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 5)
-#define PC6_AIN_SLCDC1_DAT8	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 6)
-#define PC7_AIN_SLCDC1_DAT9	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 7)
-#define PC8_AIN_SLCDC1_DAT10	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 8)
-#define PC9_AIN_SLCDC1_DAT11	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 9)
-#define PC10_AIN_SLCDC1_DAT12	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 10)
-#define PC11_AIN_SLCDC1_DAT13	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 11)
-#define PC12_AIN_SLCDC1_DAT14	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 12)
-#define PC13_AIN_SLCDC1_DAT15	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 13)
-#define PE5_AIN_PC_SPKOUT	(GPIO_PORTE | GPIO_AIN | GPIO_OUT | 5)
-
-/* BIN GPIO pin functions */
-
-#define PE5_BIN_TOUT2		(GPIO_PORTE | GPIO_BIN | GPIO_OUT | 5)
-
-/* CIN GPIO pin functions */
-
-#define PA14_CIN_SLCDC1_DAT0	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 14)
-#define PA15_CIN_SLCDC1_DAT1	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 15)
-#define PA16_CIN_SLCDC1_DAT2	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 16)
-#define PA17_CIN_SLCDC1_DAT3	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 17)
-#define PA18_CIN_SLCDC1_DAT4	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 18)
-#define PA19_CIN_SLCDC1_DAT5	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 19)
-#define PA20_CIN_SLCDC1_DAT6	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 20)
-#define PA21_CIN_SLCDC1_DAT7	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 21)
-#define PB30_CIN_UART4_CTS	(GPIO_PORTB | GPIO_CIN | GPIO_OUT | 30)
-#define PE5_CIN_TOUT3		(GPIO_PORTE | GPIO_CIN | GPIO_OUT | 5)
-
-/* AOUT GPIO pin functions */
-
-#define PB29_AOUT_UART4_RXD	(GPIO_PORTB | GPIO_AOUT | GPIO_IN | 29)
-#define PB31_AOUT_UART4_RTS	(GPIO_PORTB | GPIO_AOUT | GPIO_IN | 31)
-#define PC8_AOUT_USBOTG_TXR_INT (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 8)
-#define PC15_AOUT_WKGD		(GPIO_PORTC | GPIO_AOUT | GPIO_IN | 15)
-#define PF21_AOUT_DTACK		(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 21)
-
-#endif /* ifndef __MACH_IOMUX_MX2x_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx3.h b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
deleted file mode 100644
index f79f78a..0000000
--- a/arch/arm/plat-mxc/include/mach/iomux-mx3.h
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-#ifndef __MACH_IOMUX_MX3_H__
-#define __MACH_IOMUX_MX3_H__
-
-#include <linux/types.h>
-/*
- * various IOMUX output functions
- */
-
-#define	IOMUX_OCONFIG_GPIO (0 << 4)	/* used as GPIO */
-#define	IOMUX_OCONFIG_FUNC (1 << 4)	/* used as function */
-#define	IOMUX_OCONFIG_ALT1 (2 << 4)	/* used as alternate function 1 */
-#define	IOMUX_OCONFIG_ALT2 (3 << 4)	/* used as alternate function 2 */
-#define	IOMUX_OCONFIG_ALT3 (4 << 4)	/* used as alternate function 3 */
-#define	IOMUX_OCONFIG_ALT4 (5 << 4)	/* used as alternate function 4 */
-#define	IOMUX_OCONFIG_ALT5 (6 << 4)	/* used as alternate function 5 */
-#define	IOMUX_OCONFIG_ALT6 (7 << 4)	/* used as alternate function 6 */
-#define	IOMUX_ICONFIG_NONE  0		/* not configured for input */
-#define	IOMUX_ICONFIG_GPIO  1		/* used as GPIO */
-#define	IOMUX_ICONFIG_FUNC  2		/* used as function */
-#define	IOMUX_ICONFIG_ALT1  4		/* used as alternate function 1 */
-#define	IOMUX_ICONFIG_ALT2  8		/* used as alternate function 2 */
-
-#define IOMUX_CONFIG_GPIO (IOMUX_OCONFIG_GPIO | IOMUX_ICONFIG_GPIO)
-#define IOMUX_CONFIG_FUNC (IOMUX_OCONFIG_FUNC | IOMUX_ICONFIG_FUNC)
-#define IOMUX_CONFIG_ALT1 (IOMUX_OCONFIG_ALT1 | IOMUX_ICONFIG_ALT1)
-#define IOMUX_CONFIG_ALT2 (IOMUX_OCONFIG_ALT2 | IOMUX_ICONFIG_ALT2)
-
-/*
- * various IOMUX pad functions
- */
-enum iomux_pad_config {
-	PAD_CTL_NOLOOPBACK	= 0x0 << 9,
-	PAD_CTL_LOOPBACK	= 0x1 << 9,
-	PAD_CTL_PKE_NONE	= 0x0 << 8,
-	PAD_CTL_PKE_ENABLE	= 0x1 << 8,
-	PAD_CTL_PUE_KEEPER	= 0x0 << 7,
-	PAD_CTL_PUE_PUD		= 0x1 << 7,
-	PAD_CTL_100K_PD		= 0x0 << 5,
-	PAD_CTL_100K_PU		= 0x1 << 5,
-	PAD_CTL_47K_PU		= 0x2 << 5,
-	PAD_CTL_22K_PU		= 0x3 << 5,
-	PAD_CTL_HYS_CMOS	= 0x0 << 4,
-	PAD_CTL_HYS_SCHMITZ	= 0x1 << 4,
-	PAD_CTL_ODE_CMOS	= 0x0 << 3,
-	PAD_CTL_ODE_OpenDrain	= 0x1 << 3,
-	PAD_CTL_DRV_NORMAL	= 0x0 << 1,
-	PAD_CTL_DRV_HIGH	= 0x1 << 1,
-	PAD_CTL_DRV_MAX		= 0x2 << 1,
-	PAD_CTL_SRE_SLOW	= 0x0 << 0,
-	PAD_CTL_SRE_FAST	= 0x1 << 0
-};
-
-/*
- * various IOMUX general purpose functions
- */
-enum iomux_gp_func {
-	MUX_PGP_FIRI			= 1 << 0,
-	MUX_DDR_MODE			= 1 << 1,
-	MUX_PGP_CSPI_BB			= 1 << 2,
-	MUX_PGP_ATA_1			= 1 << 3,
-	MUX_PGP_ATA_2			= 1 << 4,
-	MUX_PGP_ATA_3			= 1 << 5,
-	MUX_PGP_ATA_4			= 1 << 6,
-	MUX_PGP_ATA_5			= 1 << 7,
-	MUX_PGP_ATA_6			= 1 << 8,
-	MUX_PGP_ATA_7			= 1 << 9,
-	MUX_PGP_ATA_8			= 1 << 10,
-	MUX_PGP_UH2			= 1 << 11,
-	MUX_SDCTL_CSD0_SEL		= 1 << 12,
-	MUX_SDCTL_CSD1_SEL		= 1 << 13,
-	MUX_CSPI1_UART3			= 1 << 14,
-	MUX_EXTDMAREQ2_MBX_SEL		= 1 << 15,
-	MUX_TAMPER_DETECT_EN		= 1 << 16,
-	MUX_PGP_USB_4WIRE		= 1 << 17,
-	MUX_PGP_USB_COMMON		= 1 << 18,
-	MUX_SDHC_MEMSTICK1		= 1 << 19,
-	MUX_SDHC_MEMSTICK2		= 1 << 20,
-	MUX_PGP_SPLL_BYP		= 1 << 21,
-	MUX_PGP_UPLL_BYP		= 1 << 22,
-	MUX_PGP_MSHC1_CLK_SEL		= 1 << 23,
-	MUX_PGP_MSHC2_CLK_SEL		= 1 << 24,
-	MUX_CSPI3_UART5_SEL		= 1 << 25,
-	MUX_PGP_ATA_9			= 1 << 26,
-	MUX_PGP_USB_SUSPEND		= 1 << 27,
-	MUX_PGP_USB_OTG_LOOPBACK	= 1 << 28,
-	MUX_PGP_USB_HS1_LOOPBACK	= 1 << 29,
-	MUX_PGP_USB_HS2_LOOPBACK	= 1 << 30,
-	MUX_CLKO_DDR_MODE		= 1 << 31,
-};
-
-/*
- * setups a single pin:
- * 	- reserves the pin so that it is not claimed by another driver
- * 	- setups the iomux according to the configuration
- * 	- if the pin is configured as a GPIO, we claim it through kernel gpiolib
- */
-int mxc_iomux_alloc_pin(unsigned int pin, const char *label);
-/*
- * setups mutliple pins
- * convenient way to call the above function with tables
- */
-int mxc_iomux_setup_multiple_pins(const unsigned int *pin_list, unsigned count,
-		const char *label);
-
-/*
- * releases a single pin:
- * 	- make it available for a future use by another driver
- * 	- frees the GPIO if the pin was configured as GPIO
- * 	- DOES NOT reconfigure the IOMUX in its reset state
- */
-void mxc_iomux_release_pin(unsigned int pin);
-/*
- * releases multiple pins
- * convenvient way to call the above function with tables
- */
-void mxc_iomux_release_multiple_pins(const unsigned int *pin_list, int count);
-
-/*
- * This function enables/disables the general purpose function for a particular
- * signal.
- */
-void mxc_iomux_set_gpr(enum iomux_gp_func, bool en);
-
-/*
- * This function only configures the iomux hardware.
- * It is called by the setup functions and should not be called directly anymore.
- * It is here visible for backward compatibility
- */
-int mxc_iomux_mode(unsigned int pin_mode);
-
-#define IOMUX_PADNUM_MASK	0x1ff
-#define IOMUX_GPIONUM_SHIFT	9
-#define IOMUX_GPIONUM_MASK	(0xff << IOMUX_GPIONUM_SHIFT)
-#define IOMUX_MODE_SHIFT	17
-#define IOMUX_MODE_MASK	(0xff << IOMUX_MODE_SHIFT)
-
-#define IOMUX_PIN(gpionum, padnum) \
-	(((gpionum << IOMUX_GPIONUM_SHIFT) & IOMUX_GPIONUM_MASK) | \
-	 (padnum & IOMUX_PADNUM_MASK))
-
-#define IOMUX_MODE(pin, mode) (pin | mode << IOMUX_MODE_SHIFT)
-
-#define IOMUX_TO_GPIO(iomux_pin) \
-	((iomux_pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT)
-
-/*
- * This enumeration is constructed based on the Section
- * "sw_pad_ctl & sw_mux_ctl details" of the MX31 IC Spec. Each enumerated
- * value is constructed based on the rules described above.
- */
-
-enum iomux_pins {
-	MX31_PIN_TTM_PAD	= IOMUX_PIN(0xff,   0),
-	MX31_PIN_CSPI3_SPI_RDY	= IOMUX_PIN(0xff,   1),
-	MX31_PIN_CSPI3_SCLK	= IOMUX_PIN(0xff,   2),
-	MX31_PIN_CSPI3_MISO	= IOMUX_PIN(0xff,   3),
-	MX31_PIN_CSPI3_MOSI	= IOMUX_PIN(0xff,   4),
-	MX31_PIN_CLKSS		= IOMUX_PIN(0xff,   5),
-	MX31_PIN_CE_CONTROL	= IOMUX_PIN(0xff,   6),
-	MX31_PIN_ATA_RESET_B	= IOMUX_PIN(95,     7),
-	MX31_PIN_ATA_DMACK	= IOMUX_PIN(94,     8),
-	MX31_PIN_ATA_DIOW	= IOMUX_PIN(93,     9),
-	MX31_PIN_ATA_DIOR	= IOMUX_PIN(92,    10),
-	MX31_PIN_ATA_CS1	= IOMUX_PIN(91,    11),
-	MX31_PIN_ATA_CS0	= IOMUX_PIN(90,    12),
-	MX31_PIN_SD1_DATA3	= IOMUX_PIN(63,    13),
-	MX31_PIN_SD1_DATA2	= IOMUX_PIN(62,    14),
-	MX31_PIN_SD1_DATA1	= IOMUX_PIN(61,    15),
-	MX31_PIN_SD1_DATA0	= IOMUX_PIN(60,    16),
-	MX31_PIN_SD1_CLK	= IOMUX_PIN(59,    17),
-	MX31_PIN_SD1_CMD	= IOMUX_PIN(58,    18),
-	MX31_PIN_D3_SPL		= IOMUX_PIN(0xff,  19),
-	MX31_PIN_D3_CLS		= IOMUX_PIN(0xff,  20),
-	MX31_PIN_D3_REV		= IOMUX_PIN(0xff,  21),
-	MX31_PIN_CONTRAST	= IOMUX_PIN(0xff,  22),
-	MX31_PIN_VSYNC3		= IOMUX_PIN(0xff,  23),
-	MX31_PIN_READ		= IOMUX_PIN(0xff,  24),
-	MX31_PIN_WRITE		= IOMUX_PIN(0xff,  25),
-	MX31_PIN_PAR_RS		= IOMUX_PIN(0xff,  26),
-	MX31_PIN_SER_RS		= IOMUX_PIN(89,    27),
-	MX31_PIN_LCS1		= IOMUX_PIN(88,    28),
-	MX31_PIN_LCS0		= IOMUX_PIN(87,    29),
-	MX31_PIN_SD_D_CLK	= IOMUX_PIN(86,    30),
-	MX31_PIN_SD_D_IO	= IOMUX_PIN(85,    31),
-	MX31_PIN_SD_D_I		= IOMUX_PIN(84,    32),
-	MX31_PIN_DRDY0		= IOMUX_PIN(0xff,  33),
-	MX31_PIN_FPSHIFT	= IOMUX_PIN(0xff,  34),
-	MX31_PIN_HSYNC		= IOMUX_PIN(0xff,  35),
-	MX31_PIN_VSYNC0		= IOMUX_PIN(0xff,  36),
-	MX31_PIN_LD17		= IOMUX_PIN(0xff,  37),
-	MX31_PIN_LD16		= IOMUX_PIN(0xff,  38),
-	MX31_PIN_LD15		= IOMUX_PIN(0xff,  39),
-	MX31_PIN_LD14		= IOMUX_PIN(0xff,  40),
-	MX31_PIN_LD13		= IOMUX_PIN(0xff,  41),
-	MX31_PIN_LD12		= IOMUX_PIN(0xff,  42),
-	MX31_PIN_LD11		= IOMUX_PIN(0xff,  43),
-	MX31_PIN_LD10		= IOMUX_PIN(0xff,  44),
-	MX31_PIN_LD9		= IOMUX_PIN(0xff,  45),
-	MX31_PIN_LD8		= IOMUX_PIN(0xff,  46),
-	MX31_PIN_LD7		= IOMUX_PIN(0xff,  47),
-	MX31_PIN_LD6		= IOMUX_PIN(0xff,  48),
-	MX31_PIN_LD5		= IOMUX_PIN(0xff,  49),
-	MX31_PIN_LD4		= IOMUX_PIN(0xff,  50),
-	MX31_PIN_LD3		= IOMUX_PIN(0xff,  51),
-	MX31_PIN_LD2		= IOMUX_PIN(0xff,  52),
-	MX31_PIN_LD1		= IOMUX_PIN(0xff,  53),
-	MX31_PIN_LD0		= IOMUX_PIN(0xff,  54),
-	MX31_PIN_USBH2_DATA1	= IOMUX_PIN(0xff,  55),
-	MX31_PIN_USBH2_DATA0	= IOMUX_PIN(0xff,  56),
-	MX31_PIN_USBH2_NXT	= IOMUX_PIN(0xff,  57),
-	MX31_PIN_USBH2_STP	= IOMUX_PIN(0xff,  58),
-	MX31_PIN_USBH2_DIR	= IOMUX_PIN(0xff,  59),
-	MX31_PIN_USBH2_CLK	= IOMUX_PIN(0xff,  60),
-	MX31_PIN_USBOTG_DATA7	= IOMUX_PIN(0xff,  61),
-	MX31_PIN_USBOTG_DATA6	= IOMUX_PIN(0xff,  62),
-	MX31_PIN_USBOTG_DATA5	= IOMUX_PIN(0xff,  63),
-	MX31_PIN_USBOTG_DATA4	= IOMUX_PIN(0xff,  64),
-	MX31_PIN_USBOTG_DATA3	= IOMUX_PIN(0xff,  65),
-	MX31_PIN_USBOTG_DATA2	= IOMUX_PIN(0xff,  66),
-	MX31_PIN_USBOTG_DATA1	= IOMUX_PIN(0xff,  67),
-	MX31_PIN_USBOTG_DATA0	= IOMUX_PIN(0xff,  68),
-	MX31_PIN_USBOTG_NXT	= IOMUX_PIN(0xff,  69),
-	MX31_PIN_USBOTG_STP	= IOMUX_PIN(0xff,  70),
-	MX31_PIN_USBOTG_DIR	= IOMUX_PIN(0xff,  71),
-	MX31_PIN_USBOTG_CLK	= IOMUX_PIN(0xff,  72),
-	MX31_PIN_USB_BYP	= IOMUX_PIN(31,    73),
-	MX31_PIN_USB_OC		= IOMUX_PIN(30,    74),
-	MX31_PIN_USB_PWR	= IOMUX_PIN(29,    75),
-	MX31_PIN_SJC_MOD	= IOMUX_PIN(0xff,  76),
-	MX31_PIN_DE_B		= IOMUX_PIN(0xff,  77),
-	MX31_PIN_TRSTB		= IOMUX_PIN(0xff,  78),
-	MX31_PIN_TDO		= IOMUX_PIN(0xff,  79),
-	MX31_PIN_TDI		= IOMUX_PIN(0xff,  80),
-	MX31_PIN_TMS		= IOMUX_PIN(0xff,  81),
-	MX31_PIN_TCK		= IOMUX_PIN(0xff,  82),
-	MX31_PIN_RTCK		= IOMUX_PIN(0xff,  83),
-	MX31_PIN_KEY_COL7	= IOMUX_PIN(57,    84),
-	MX31_PIN_KEY_COL6	= IOMUX_PIN(56,    85),
-	MX31_PIN_KEY_COL5	= IOMUX_PIN(55,    86),
-	MX31_PIN_KEY_COL4	= IOMUX_PIN(54,    87),
-	MX31_PIN_KEY_COL3	= IOMUX_PIN(0xff,  88),
-	MX31_PIN_KEY_COL2	= IOMUX_PIN(0xff,  89),
-	MX31_PIN_KEY_COL1	= IOMUX_PIN(0xff,  90),
-	MX31_PIN_KEY_COL0	= IOMUX_PIN(0xff,  91),
-	MX31_PIN_KEY_ROW7	= IOMUX_PIN(53,    92),
-	MX31_PIN_KEY_ROW6	= IOMUX_PIN(52,    93),
-	MX31_PIN_KEY_ROW5	= IOMUX_PIN(51,    94),
-	MX31_PIN_KEY_ROW4	= IOMUX_PIN(50,    95),
-	MX31_PIN_KEY_ROW3	= IOMUX_PIN(0xff,  96),
-	MX31_PIN_KEY_ROW2	= IOMUX_PIN(0xff,  97),
-	MX31_PIN_KEY_ROW1	= IOMUX_PIN(0xff,  98),
-	MX31_PIN_KEY_ROW0	= IOMUX_PIN(0xff,  99),
-	MX31_PIN_BATT_LINE	= IOMUX_PIN(49,   100),
-	MX31_PIN_CTS2		= IOMUX_PIN(0xff, 101),
-	MX31_PIN_RTS2		= IOMUX_PIN(0xff, 102),
-	MX31_PIN_TXD2		= IOMUX_PIN(28,   103),
-	MX31_PIN_RXD2		= IOMUX_PIN(27,   104),
-	MX31_PIN_DTR_DCE2	= IOMUX_PIN(48,   105),
-	MX31_PIN_DCD_DTE1	= IOMUX_PIN(47,   106),
-	MX31_PIN_RI_DTE1	= IOMUX_PIN(46,   107),
-	MX31_PIN_DSR_DTE1	= IOMUX_PIN(45,   108),
-	MX31_PIN_DTR_DTE1	= IOMUX_PIN(44,   109),
-	MX31_PIN_DCD_DCE1	= IOMUX_PIN(43,   110),
-	MX31_PIN_RI_DCE1	= IOMUX_PIN(42,   111),
-	MX31_PIN_DSR_DCE1	= IOMUX_PIN(41,   112),
-	MX31_PIN_DTR_DCE1	= IOMUX_PIN(40,   113),
-	MX31_PIN_CTS1		= IOMUX_PIN(39,   114),
-	MX31_PIN_RTS1		= IOMUX_PIN(38,   115),
-	MX31_PIN_TXD1		= IOMUX_PIN(37,   116),
-	MX31_PIN_RXD1		= IOMUX_PIN(36,   117),
-	MX31_PIN_CSPI2_SPI_RDY	= IOMUX_PIN(0xff, 118),
-	MX31_PIN_CSPI2_SCLK	= IOMUX_PIN(0xff, 119),
-	MX31_PIN_CSPI2_SS2	= IOMUX_PIN(0xff, 120),
-	MX31_PIN_CSPI2_SS1	= IOMUX_PIN(0xff, 121),
-	MX31_PIN_CSPI2_SS0	= IOMUX_PIN(0xff, 122),
-	MX31_PIN_CSPI2_MISO	= IOMUX_PIN(0xff, 123),
-	MX31_PIN_CSPI2_MOSI	= IOMUX_PIN(0xff, 124),
-	MX31_PIN_CSPI1_SPI_RDY	= IOMUX_PIN(0xff, 125),
-	MX31_PIN_CSPI1_SCLK	= IOMUX_PIN(0xff, 126),
-	MX31_PIN_CSPI1_SS2	= IOMUX_PIN(0xff, 127),
-	MX31_PIN_CSPI1_SS1	= IOMUX_PIN(0xff, 128),
-	MX31_PIN_CSPI1_SS0	= IOMUX_PIN(0xff, 129),
-	MX31_PIN_CSPI1_MISO	= IOMUX_PIN(0xff, 130),
-	MX31_PIN_CSPI1_MOSI	= IOMUX_PIN(0xff, 131),
-	MX31_PIN_SFS6		= IOMUX_PIN(26,   132),
-	MX31_PIN_SCK6		= IOMUX_PIN(25,   133),
-	MX31_PIN_SRXD6		= IOMUX_PIN(24,   134),
-	MX31_PIN_STXD6		= IOMUX_PIN(23,   135),
-	MX31_PIN_SFS5		= IOMUX_PIN(0xff, 136),
-	MX31_PIN_SCK5		= IOMUX_PIN(0xff, 137),
-	MX31_PIN_SRXD5		= IOMUX_PIN(22,   138),
-	MX31_PIN_STXD5		= IOMUX_PIN(21,   139),
-	MX31_PIN_SFS4		= IOMUX_PIN(0xff, 140),
-	MX31_PIN_SCK4		= IOMUX_PIN(0xff, 141),
-	MX31_PIN_SRXD4		= IOMUX_PIN(20,   142),
-	MX31_PIN_STXD4		= IOMUX_PIN(19,   143),
-	MX31_PIN_SFS3		= IOMUX_PIN(0xff, 144),
-	MX31_PIN_SCK3		= IOMUX_PIN(0xff, 145),
-	MX31_PIN_SRXD3		= IOMUX_PIN(18,   146),
-	MX31_PIN_STXD3		= IOMUX_PIN(17,   147),
-	MX31_PIN_I2C_DAT	= IOMUX_PIN(0xff, 148),
-	MX31_PIN_I2C_CLK	= IOMUX_PIN(0xff, 149),
-	MX31_PIN_CSI_PIXCLK	= IOMUX_PIN(83,   150),
-	MX31_PIN_CSI_HSYNC	= IOMUX_PIN(82,   151),
-	MX31_PIN_CSI_VSYNC	= IOMUX_PIN(81,   152),
-	MX31_PIN_CSI_MCLK	= IOMUX_PIN(80,   153),
-	MX31_PIN_CSI_D15	= IOMUX_PIN(79,   154),
-	MX31_PIN_CSI_D14	= IOMUX_PIN(78,   155),
-	MX31_PIN_CSI_D13	= IOMUX_PIN(77,   156),
-	MX31_PIN_CSI_D12	= IOMUX_PIN(76,   157),
-	MX31_PIN_CSI_D11	= IOMUX_PIN(75,   158),
-	MX31_PIN_CSI_D10	= IOMUX_PIN(74,   159),
-	MX31_PIN_CSI_D9		= IOMUX_PIN(73,   160),
-	MX31_PIN_CSI_D8		= IOMUX_PIN(72,   161),
-	MX31_PIN_CSI_D7		= IOMUX_PIN(71,   162),
-	MX31_PIN_CSI_D6		= IOMUX_PIN(70,   163),
-	MX31_PIN_CSI_D5		= IOMUX_PIN(69,   164),
-	MX31_PIN_CSI_D4		= IOMUX_PIN(68,   165),
-	MX31_PIN_M_GRANT	= IOMUX_PIN(0xff, 166),
-	MX31_PIN_M_REQUEST	= IOMUX_PIN(0xff, 167),
-	MX31_PIN_PC_POE		= IOMUX_PIN(0xff, 168),
-	MX31_PIN_PC_RW_B	= IOMUX_PIN(0xff, 169),
-	MX31_PIN_IOIS16		= IOMUX_PIN(0xff, 170),
-	MX31_PIN_PC_RST		= IOMUX_PIN(0xff, 171),
-	MX31_PIN_PC_BVD2	= IOMUX_PIN(0xff, 172),
-	MX31_PIN_PC_BVD1	= IOMUX_PIN(0xff, 173),
-	MX31_PIN_PC_VS2		= IOMUX_PIN(0xff, 174),
-	MX31_PIN_PC_VS1		= IOMUX_PIN(0xff, 175),
-	MX31_PIN_PC_PWRON	= IOMUX_PIN(0xff, 176),
-	MX31_PIN_PC_READY	= IOMUX_PIN(0xff, 177),
-	MX31_PIN_PC_WAIT_B	= IOMUX_PIN(0xff, 178),
-	MX31_PIN_PC_CD2_B	= IOMUX_PIN(0xff, 179),
-	MX31_PIN_PC_CD1_B	= IOMUX_PIN(0xff, 180),
-	MX31_PIN_D0		= IOMUX_PIN(0xff, 181),
-	MX31_PIN_D1		= IOMUX_PIN(0xff, 182),
-	MX31_PIN_D2		= IOMUX_PIN(0xff, 183),
-	MX31_PIN_D3		= IOMUX_PIN(0xff, 184),
-	MX31_PIN_D4		= IOMUX_PIN(0xff, 185),
-	MX31_PIN_D5		= IOMUX_PIN(0xff, 186),
-	MX31_PIN_D6		= IOMUX_PIN(0xff, 187),
-	MX31_PIN_D7		= IOMUX_PIN(0xff, 188),
-	MX31_PIN_D8		= IOMUX_PIN(0xff, 189),
-	MX31_PIN_D9		= IOMUX_PIN(0xff, 190),
-	MX31_PIN_D10		= IOMUX_PIN(0xff, 191),
-	MX31_PIN_D11		= IOMUX_PIN(0xff, 192),
-	MX31_PIN_D12		= IOMUX_PIN(0xff, 193),
-	MX31_PIN_D13		= IOMUX_PIN(0xff, 194),
-	MX31_PIN_D14		= IOMUX_PIN(0xff, 195),
-	MX31_PIN_D15		= IOMUX_PIN(0xff, 196),
-	MX31_PIN_NFRB		= IOMUX_PIN(16,   197),
-	MX31_PIN_NFCE_B		= IOMUX_PIN(15,   198),
-	MX31_PIN_NFWP_B		= IOMUX_PIN(14,   199),
-	MX31_PIN_NFCLE		= IOMUX_PIN(13,   200),
-	MX31_PIN_NFALE		= IOMUX_PIN(12,   201),
-	MX31_PIN_NFRE_B		= IOMUX_PIN(11,   202),
-	MX31_PIN_NFWE_B		= IOMUX_PIN(10,   203),
-	MX31_PIN_SDQS3		= IOMUX_PIN(0xff, 204),
-	MX31_PIN_SDQS2		= IOMUX_PIN(0xff, 205),
-	MX31_PIN_SDQS1		= IOMUX_PIN(0xff, 206),
-	MX31_PIN_SDQS0		= IOMUX_PIN(0xff, 207),
-	MX31_PIN_SDCLK_B	= IOMUX_PIN(0xff, 208),
-	MX31_PIN_SDCLK		= IOMUX_PIN(0xff, 209),
-	MX31_PIN_SDCKE1		= IOMUX_PIN(0xff, 210),
-	MX31_PIN_SDCKE0		= IOMUX_PIN(0xff, 211),
-	MX31_PIN_SDWE		= IOMUX_PIN(0xff, 212),
-	MX31_PIN_CAS		= IOMUX_PIN(0xff, 213),
-	MX31_PIN_RAS		= IOMUX_PIN(0xff, 214),
-	MX31_PIN_RW		= IOMUX_PIN(0xff, 215),
-	MX31_PIN_BCLK		= IOMUX_PIN(0xff, 216),
-	MX31_PIN_LBA		= IOMUX_PIN(0xff, 217),
-	MX31_PIN_ECB		= IOMUX_PIN(0xff, 218),
-	MX31_PIN_CS5		= IOMUX_PIN(0xff, 219),
-	MX31_PIN_CS4		= IOMUX_PIN(0xff, 220),
-	MX31_PIN_CS3		= IOMUX_PIN(0xff, 221),
-	MX31_PIN_CS2		= IOMUX_PIN(0xff, 222),
-	MX31_PIN_CS1		= IOMUX_PIN(0xff, 223),
-	MX31_PIN_CS0		= IOMUX_PIN(0xff, 224),
-	MX31_PIN_OE		= IOMUX_PIN(0xff, 225),
-	MX31_PIN_EB1		= IOMUX_PIN(0xff, 226),
-	MX31_PIN_EB0		= IOMUX_PIN(0xff, 227),
-	MX31_PIN_DQM3		= IOMUX_PIN(0xff, 228),
-	MX31_PIN_DQM2		= IOMUX_PIN(0xff, 229),
-	MX31_PIN_DQM1		= IOMUX_PIN(0xff, 230),
-	MX31_PIN_DQM0		= IOMUX_PIN(0xff, 231),
-	MX31_PIN_SD31		= IOMUX_PIN(0xff, 232),
-	MX31_PIN_SD30		= IOMUX_PIN(0xff, 233),
-	MX31_PIN_SD29		= IOMUX_PIN(0xff, 234),
-	MX31_PIN_SD28		= IOMUX_PIN(0xff, 235),
-	MX31_PIN_SD27		= IOMUX_PIN(0xff, 236),
-	MX31_PIN_SD26		= IOMUX_PIN(0xff, 237),
-	MX31_PIN_SD25		= IOMUX_PIN(0xff, 238),
-	MX31_PIN_SD24		= IOMUX_PIN(0xff, 239),
-	MX31_PIN_SD23		= IOMUX_PIN(0xff, 240),
-	MX31_PIN_SD22		= IOMUX_PIN(0xff, 241),
-	MX31_PIN_SD21		= IOMUX_PIN(0xff, 242),
-	MX31_PIN_SD20		= IOMUX_PIN(0xff, 243),
-	MX31_PIN_SD19		= IOMUX_PIN(0xff, 244),
-	MX31_PIN_SD18		= IOMUX_PIN(0xff, 245),
-	MX31_PIN_SD17		= IOMUX_PIN(0xff, 246),
-	MX31_PIN_SD16		= IOMUX_PIN(0xff, 247),
-	MX31_PIN_SD15		= IOMUX_PIN(0xff, 248),
-	MX31_PIN_SD14		= IOMUX_PIN(0xff, 249),
-	MX31_PIN_SD13		= IOMUX_PIN(0xff, 250),
-	MX31_PIN_SD12		= IOMUX_PIN(0xff, 251),
-	MX31_PIN_SD11		= IOMUX_PIN(0xff, 252),
-	MX31_PIN_SD10		= IOMUX_PIN(0xff, 253),
-	MX31_PIN_SD9		= IOMUX_PIN(0xff, 254),
-	MX31_PIN_SD8		= IOMUX_PIN(0xff, 255),
-	MX31_PIN_SD7		= IOMUX_PIN(0xff, 256),
-	MX31_PIN_SD6		= IOMUX_PIN(0xff, 257),
-	MX31_PIN_SD5		= IOMUX_PIN(0xff, 258),
-	MX31_PIN_SD4		= IOMUX_PIN(0xff, 259),
-	MX31_PIN_SD3		= IOMUX_PIN(0xff, 260),
-	MX31_PIN_SD2		= IOMUX_PIN(0xff, 261),
-	MX31_PIN_SD1		= IOMUX_PIN(0xff, 262),
-	MX31_PIN_SD0		= IOMUX_PIN(0xff, 263),
-	MX31_PIN_SDBA0		= IOMUX_PIN(0xff, 264),
-	MX31_PIN_SDBA1		= IOMUX_PIN(0xff, 265),
-	MX31_PIN_A25		= IOMUX_PIN(0xff, 266),
-	MX31_PIN_A24		= IOMUX_PIN(0xff, 267),
-	MX31_PIN_A23		= IOMUX_PIN(0xff, 268),
-	MX31_PIN_A22		= IOMUX_PIN(0xff, 269),
-	MX31_PIN_A21		= IOMUX_PIN(0xff, 270),
-	MX31_PIN_A20		= IOMUX_PIN(0xff, 271),
-	MX31_PIN_A19		= IOMUX_PIN(0xff, 272),
-	MX31_PIN_A18		= IOMUX_PIN(0xff, 273),
-	MX31_PIN_A17		= IOMUX_PIN(0xff, 274),
-	MX31_PIN_A16		= IOMUX_PIN(0xff, 275),
-	MX31_PIN_A14		= IOMUX_PIN(0xff, 276),
-	MX31_PIN_A15		= IOMUX_PIN(0xff, 277),
-	MX31_PIN_A13		= IOMUX_PIN(0xff, 278),
-	MX31_PIN_A12		= IOMUX_PIN(0xff, 279),
-	MX31_PIN_A11		= IOMUX_PIN(0xff, 280),
-	MX31_PIN_MA10		= IOMUX_PIN(0xff, 281),
-	MX31_PIN_A10		= IOMUX_PIN(0xff, 282),
-	MX31_PIN_A9		= IOMUX_PIN(0xff, 283),
-	MX31_PIN_A8		= IOMUX_PIN(0xff, 284),
-	MX31_PIN_A7		= IOMUX_PIN(0xff, 285),
-	MX31_PIN_A6		= IOMUX_PIN(0xff, 286),
-	MX31_PIN_A5		= IOMUX_PIN(0xff, 287),
-	MX31_PIN_A4		= IOMUX_PIN(0xff, 288),
-	MX31_PIN_A3		= IOMUX_PIN(0xff, 289),
-	MX31_PIN_A2		= IOMUX_PIN(0xff, 290),
-	MX31_PIN_A1		= IOMUX_PIN(0xff, 291),
-	MX31_PIN_A0		= IOMUX_PIN(0xff, 292),
-	MX31_PIN_VPG1		= IOMUX_PIN(0xff, 293),
-	MX31_PIN_VPG0		= IOMUX_PIN(0xff, 294),
-	MX31_PIN_DVFS1		= IOMUX_PIN(0xff, 295),
-	MX31_PIN_DVFS0		= IOMUX_PIN(0xff, 296),
-	MX31_PIN_VSTBY		= IOMUX_PIN(0xff, 297),
-	MX31_PIN_POWER_FAIL	= IOMUX_PIN(0xff, 298),
-	MX31_PIN_CKIL		= IOMUX_PIN(0xff, 299),
-	MX31_PIN_BOOT_MODE4	= IOMUX_PIN(0xff, 300),
-	MX31_PIN_BOOT_MODE3	= IOMUX_PIN(0xff, 301),
-	MX31_PIN_BOOT_MODE2	= IOMUX_PIN(0xff, 302),
-	MX31_PIN_BOOT_MODE1	= IOMUX_PIN(0xff, 303),
-	MX31_PIN_BOOT_MODE0	= IOMUX_PIN(0xff, 304),
-	MX31_PIN_CLKO		= IOMUX_PIN(0xff, 305),
-	MX31_PIN_POR_B		= IOMUX_PIN(0xff, 306),
-	MX31_PIN_RESET_IN_B	= IOMUX_PIN(0xff, 307),
-	MX31_PIN_CKIH		= IOMUX_PIN(0xff, 308),
-	MX31_PIN_SIMPD0		= IOMUX_PIN(35,   309),
-	MX31_PIN_SRX0		= IOMUX_PIN(34,   310),
-	MX31_PIN_STX0		= IOMUX_PIN(33,   311),
-	MX31_PIN_SVEN0		= IOMUX_PIN(32,   312),
-	MX31_PIN_SRST0		= IOMUX_PIN(67,   313),
-	MX31_PIN_SCLK0		= IOMUX_PIN(66,   314),
-	MX31_PIN_GPIO3_1	= IOMUX_PIN(65,   315),
-	MX31_PIN_GPIO3_0	= IOMUX_PIN(64,   316),
-	MX31_PIN_GPIO1_6	= IOMUX_PIN( 6,   317),
-	MX31_PIN_GPIO1_5	= IOMUX_PIN( 5,   318),
-	MX31_PIN_GPIO1_4	= IOMUX_PIN( 4,   319),
-	MX31_PIN_GPIO1_3	= IOMUX_PIN( 3,   320),
-	MX31_PIN_GPIO1_2	= IOMUX_PIN( 2,   321),
-	MX31_PIN_GPIO1_1	= IOMUX_PIN( 1,   322),
-	MX31_PIN_GPIO1_0	= IOMUX_PIN( 0,   323),
-	MX31_PIN_PWMO		= IOMUX_PIN( 9,   324),
-	MX31_PIN_WATCHDOG_RST	= IOMUX_PIN(0xff, 325),
-	MX31_PIN_COMPARE	= IOMUX_PIN( 8,   326),
-	MX31_PIN_CAPTURE	= IOMUX_PIN( 7,   327),
-};
-
-#define PIN_MAX 327
-#define NB_PORTS 12 /* NB_PINS/32, we chose 32 pins per "PORT" */
-
-/*
- * Convenience values for use with mxc_iomux_mode()
- *
- * Format here is MX31_PIN_(pin name)__(function)
- */
-#define MX31_PIN_CSPI3_MOSI__RXD3	IOMUX_MODE(MX31_PIN_CSPI3_MOSI, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI3_MISO__TXD3	IOMUX_MODE(MX31_PIN_CSPI3_MISO, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI3_SCLK__RTS3	IOMUX_MODE(MX31_PIN_CSPI3_SCLK, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI3_SPI_RDY__CTS3	IOMUX_MODE(MX31_PIN_CSPI3_SPI_RDY, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CTS1__CTS1		IOMUX_MODE(MX31_PIN_CTS1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_RTS1__RTS1		IOMUX_MODE(MX31_PIN_RTS1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_RTS1__SFS		IOMUX_MODE(MX31_PIN_RTS1, IOMUX_CONFIG_ALT2)
-#define MX31_PIN_TXD1__TXD1		IOMUX_MODE(MX31_PIN_TXD1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_TXD1__SCK		IOMUX_MODE(MX31_PIN_TXD1, IOMUX_CONFIG_ALT2)
-#define MX31_PIN_RXD1__RXD1		IOMUX_MODE(MX31_PIN_RXD1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_RXD1__STXDA		IOMUX_MODE(MX31_PIN_RXD1, IOMUX_CONFIG_ALT2)
-#define MX31_PIN_DCD_DCE1__DCD_DCE1	IOMUX_MODE(MX31_PIN_DCD_DCE1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_RI_DCE1__RI_DCE1	IOMUX_MODE(MX31_PIN_RI_DCE1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_DSR_DCE1__DSR_DCE1	IOMUX_MODE(MX31_PIN_DSR_DCE1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_DTR_DCE1__DTR_DCE1	IOMUX_MODE(MX31_PIN_DTR_DCE1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_DTR_DCE1__SRXDA	IOMUX_MODE(MX31_PIN_DTR_DCE1, IOMUX_CONFIG_ALT2)
-#define MX31_PIN_CTS2__CTS2		IOMUX_MODE(MX31_PIN_CTS2, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_RTS2__RTS2		IOMUX_MODE(MX31_PIN_RTS2, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_TXD2__TXD2		IOMUX_MODE(MX31_PIN_TXD2, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_RXD2__RXD2		IOMUX_MODE(MX31_PIN_RXD2, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_DCD_DTE1__DCD_DTE2	IOMUX_MODE(MX31_PIN_DCD_DTE1, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_RI_DTE1__RI_DTE2	IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_DSR_DTE1__DSR_DTE2	IOMUX_MODE(MX31_PIN_DSR_DTE1, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_DTR_DTE1__DTR_DTE2	IOMUX_MODE(MX31_PIN_DTR_DTE1, IOMUX_OCONFIG_ALT3 | IOMUX_ICONFIG_NONE)
-#define MX31_PIN_PC_RST__CTS5		IOMUX_MODE(MX31_PIN_PC_RST, IOMUX_CONFIG_ALT2)
-#define MX31_PIN_PC_VS2__RTS5		IOMUX_MODE(MX31_PIN_PC_VS2, IOMUX_CONFIG_ALT2)
-#define MX31_PIN_PC_BVD2__TXD5		IOMUX_MODE(MX31_PIN_PC_BVD2, IOMUX_CONFIG_ALT2)
-#define MX31_PIN_PC_BVD1__RXD5		IOMUX_MODE(MX31_PIN_PC_BVD1, IOMUX_CONFIG_ALT2)
-#define MX31_PIN_CSPI1_MOSI__MOSI	IOMUX_MODE(MX31_PIN_CSPI1_MOSI, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI1_MISO__MISO	IOMUX_MODE(MX31_PIN_CSPI1_MISO, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI1_SCLK__SCLK	IOMUX_MODE(MX31_PIN_CSPI1_SCLK, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI1_SPI_RDY__SPI_RDY	IOMUX_MODE(MX31_PIN_CSPI1_SPI_RDY, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI1_SS0__SS0		IOMUX_MODE(MX31_PIN_CSPI1_SS0, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI1_SS1__SS1		IOMUX_MODE(MX31_PIN_CSPI1_SS1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI1_SS2__SS2		IOMUX_MODE(MX31_PIN_CSPI1_SS2, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI2_MOSI__MOSI	IOMUX_MODE(MX31_PIN_CSPI2_MOSI, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI2_MOSI__SCL	IOMUX_MODE(MX31_PIN_CSPI2_MOSI, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI2_MISO__MISO	IOMUX_MODE(MX31_PIN_CSPI2_MISO, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI2_MISO__SDA	IOMUX_MODE(MX31_PIN_CSPI2_MISO, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI2_SCLK__SCLK	IOMUX_MODE(MX31_PIN_CSPI2_SCLK, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI2_SPI_RDY__SPI_RDY	IOMUX_MODE(MX31_PIN_CSPI2_SPI_RDY, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI2_SS0__SS0		IOMUX_MODE(MX31_PIN_CSPI2_SS0, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI2_SS1__SS1		IOMUX_MODE(MX31_PIN_CSPI2_SS1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI2_SS2__SS2		IOMUX_MODE(MX31_PIN_CSPI2_SS2, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI3_MOSI__MOSI	IOMUX_MODE(MX31_PIN_CSPI3_MOSI, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI3_MISO__MISO	IOMUX_MODE(MX31_PIN_CSPI3_MISO, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI3_SCLK__SCLK	IOMUX_MODE(MX31_PIN_CSPI3_SCLK, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI3_SPI_RDY__SPI_RDY	IOMUX_MODE(MX31_PIN_CSPI3_SPI_RDY, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_BATT_LINE__OWIRE	IOMUX_MODE(MX31_PIN_BATT_LINE, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CS4__CS4		IOMUX_MODE(MX31_PIN_CS4, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SD1_DATA3__SD1_DATA3	IOMUX_MODE(MX31_PIN_SD1_DATA3, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SD1_DATA2__SD1_DATA2	IOMUX_MODE(MX31_PIN_SD1_DATA2, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SD1_DATA1__SD1_DATA1	IOMUX_MODE(MX31_PIN_SD1_DATA1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SD1_DATA0__SD1_DATA0	IOMUX_MODE(MX31_PIN_SD1_DATA0, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SD1_CLK__SD1_CLK	IOMUX_MODE(MX31_PIN_SD1_CLK, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SD1_CMD__SD1_CMD	IOMUX_MODE(MX31_PIN_SD1_CMD, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_ATA_CS0__GPIO3_26	IOMUX_MODE(MX31_PIN_ATA_CS0, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_ATA_CS1__GPIO3_27	IOMUX_MODE(MX31_PIN_ATA_CS1, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_PC_PWRON__SD2_DATA3	IOMUX_MODE(MX31_PIN_PC_PWRON, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_PC_VS1__SD2_DATA2	IOMUX_MODE(MX31_PIN_PC_VS1, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_PC_READY__SD2_DATA1	IOMUX_MODE(MX31_PIN_PC_READY, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_PC_WAIT_B__SD2_DATA0	IOMUX_MODE(MX31_PIN_PC_WAIT_B, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_PC_CD2_B__SD2_CLK	IOMUX_MODE(MX31_PIN_PC_CD2_B, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_PC_CD1_B__SD2_CMD	IOMUX_MODE(MX31_PIN_PC_CD1_B, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_ATA_DIOR__GPIO3_28	IOMUX_MODE(MX31_PIN_ATA_DIOR, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_ATA_DIOW__GPIO3_29	IOMUX_MODE(MX31_PIN_ATA_DIOW, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_LD0__LD0		IOMUX_MODE(MX31_PIN_LD0, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD1__LD1		IOMUX_MODE(MX31_PIN_LD1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD2__LD2		IOMUX_MODE(MX31_PIN_LD2, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD3__LD3		IOMUX_MODE(MX31_PIN_LD3, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD4__LD4		IOMUX_MODE(MX31_PIN_LD4, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD5__LD5		IOMUX_MODE(MX31_PIN_LD5, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD6__LD6		IOMUX_MODE(MX31_PIN_LD6, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD7__LD7		IOMUX_MODE(MX31_PIN_LD7, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD8__LD8		IOMUX_MODE(MX31_PIN_LD8, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD9__LD9		IOMUX_MODE(MX31_PIN_LD9, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD10__LD10		IOMUX_MODE(MX31_PIN_LD10, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD11__LD11		IOMUX_MODE(MX31_PIN_LD11, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD12__LD12		IOMUX_MODE(MX31_PIN_LD12, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD13__LD13		IOMUX_MODE(MX31_PIN_LD13, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD14__LD14		IOMUX_MODE(MX31_PIN_LD14, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD15__LD15		IOMUX_MODE(MX31_PIN_LD15, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD16__LD16		IOMUX_MODE(MX31_PIN_LD16, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LD17__LD17		IOMUX_MODE(MX31_PIN_LD17, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_VSYNC3__VSYNC3		IOMUX_MODE(MX31_PIN_VSYNC3, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_HSYNC__HSYNC		IOMUX_MODE(MX31_PIN_HSYNC, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_FPSHIFT__FPSHIFT	IOMUX_MODE(MX31_PIN_FPSHIFT, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_DRDY0__DRDY0		IOMUX_MODE(MX31_PIN_DRDY0, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_D3_REV__D3_REV		IOMUX_MODE(MX31_PIN_D3_REV, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CONTRAST__CONTRAST	IOMUX_MODE(MX31_PIN_CONTRAST, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_D3_SPL__D3_SPL		IOMUX_MODE(MX31_PIN_D3_SPL, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_D3_CLS__D3_CLS		IOMUX_MODE(MX31_PIN_D3_CLS, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_LCS0__GPI03_23		IOMUX_MODE(MX31_PIN_LCS0, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_GPIO1_1__GPIO          IOMUX_MODE(MX31_PIN_GPIO1_1, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_I2C_CLK__SCL		IOMUX_MODE(MX31_PIN_I2C_CLK, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_I2C_DAT__SDA		IOMUX_MODE(MX31_PIN_I2C_DAT, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_DCD_DTE1__I2C2_SDA	IOMUX_MODE(MX31_PIN_DCD_DTE1, IOMUX_CONFIG_ALT2)
-#define MX31_PIN_RI_DTE1__I2C2_SCL	IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_ALT2)
-#define MX31_PIN_CSPI2_SS2__I2C3_SDA	IOMUX_MODE(MX31_PIN_CSPI2_SS2, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI2_SCLK__I2C3_SCL	IOMUX_MODE(MX31_PIN_CSPI2_SCLK, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSI_D4__CSI_D4		IOMUX_MODE(MX31_PIN_CSI_D4, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D5__CSI_D5		IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D6__CSI_D6		IOMUX_MODE(MX31_PIN_CSI_D6, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D7__CSI_D7		IOMUX_MODE(MX31_PIN_CSI_D7, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D8__CSI_D8		IOMUX_MODE(MX31_PIN_CSI_D8, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D9__CSI_D9		IOMUX_MODE(MX31_PIN_CSI_D9, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D10__CSI_D10	IOMUX_MODE(MX31_PIN_CSI_D10, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D11__CSI_D11	IOMUX_MODE(MX31_PIN_CSI_D11, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D12__CSI_D12	IOMUX_MODE(MX31_PIN_CSI_D12, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D13__CSI_D13	IOMUX_MODE(MX31_PIN_CSI_D13, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D14__CSI_D14	IOMUX_MODE(MX31_PIN_CSI_D14, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D15__CSI_D15	IOMUX_MODE(MX31_PIN_CSI_D15, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_HSYNC__CSI_HSYNC	IOMUX_MODE(MX31_PIN_CSI_HSYNC, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_MCLK__CSI_MCLK	IOMUX_MODE(MX31_PIN_CSI_MCLK, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_PIXCLK__CSI_PIXCLK	IOMUX_MODE(MX31_PIN_CSI_PIXCLK, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_VSYNC__CSI_VSYNC	IOMUX_MODE(MX31_PIN_CSI_VSYNC, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_GPIO3_0__GPIO3_0	IOMUX_MODE(MX31_PIN_GPIO3_0, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_GPIO3_1__GPIO3_1	IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_TXD2__GPIO1_28		IOMUX_MODE(MX31_PIN_TXD2, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_CSI_D4__GPIO3_4	IOMUX_MODE(MX31_PIN_CSI_D4, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_CSI_D5__GPIO3_5	IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_USBOTG_DATA0__USBOTG_DATA0	IOMUX_MODE(MX31_PIN_USBOTG_DATA0, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_DATA1__USBOTG_DATA1	IOMUX_MODE(MX31_PIN_USBOTG_DATA1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_DATA2__USBOTG_DATA2	IOMUX_MODE(MX31_PIN_USBOTG_DATA2, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_DATA3__USBOTG_DATA3	IOMUX_MODE(MX31_PIN_USBOTG_DATA3, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_DATA4__USBOTG_DATA4	IOMUX_MODE(MX31_PIN_USBOTG_DATA4, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_DATA5__USBOTG_DATA5	IOMUX_MODE(MX31_PIN_USBOTG_DATA5, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_DATA6__USBOTG_DATA6	IOMUX_MODE(MX31_PIN_USBOTG_DATA6, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_DATA7__USBOTG_DATA7	IOMUX_MODE(MX31_PIN_USBOTG_DATA7, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_CLK__USBOTG_CLK		IOMUX_MODE(MX31_PIN_USBOTG_CLK, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_DIR__USBOTG_DIR		IOMUX_MODE(MX31_PIN_USBOTG_DIR, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_NXT__USBOTG_NXT		IOMUX_MODE(MX31_PIN_USBOTG_NXT, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_STP__USBOTG_STP		IOMUX_MODE(MX31_PIN_USBOTG_STP, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI1_MOSI__USBH1_RXDM		IOMUX_MODE(MX31_PIN_CSPI1_MOSI, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI1_MISO__USBH1_RXDP		IOMUX_MODE(MX31_PIN_CSPI1_MISO, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI1_SS0__USBH1_TXDM		IOMUX_MODE(MX31_PIN_CSPI1_SS0, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI1_SS1__USBH1_TXDP		IOMUX_MODE(MX31_PIN_CSPI1_SS1, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI1_SS2__USBH1_RCV		IOMUX_MODE(MX31_PIN_CSPI1_SS2, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI1_SCLK__USBH1_OEB		IOMUX_MODE(MX31_PIN_CSPI1_SCLK, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI1_SPI_RDY__USBH1_FS	IOMUX_MODE(MX31_PIN_CSPI1_SPI_RDY, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_SFS6__USBH1_SUSPEND	IOMUX_MODE(MX31_PIN_SFS6, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_NFRE_B__GPIO1_11	IOMUX_MODE(MX31_PIN_NFRE_B, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_NFALE__GPIO1_12	IOMUX_MODE(MX31_PIN_NFALE, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_USBH2_DATA0__USBH2_DATA0	IOMUX_MODE(MX31_PIN_USBH2_DATA0, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBH2_DATA1__USBH2_DATA1	IOMUX_MODE(MX31_PIN_USBH2_DATA1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_STXD3__USBH2_DATA2	IOMUX_MODE(MX31_PIN_STXD3, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SRXD3__USBH2_DATA3	IOMUX_MODE(MX31_PIN_SRXD3, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SCK3__USBH2_DATA4	IOMUX_MODE(MX31_PIN_SCK3, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SFS3__USBH2_DATA5	IOMUX_MODE(MX31_PIN_SFS3, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_STXD6__USBH2_DATA6	IOMUX_MODE(MX31_PIN_STXD6, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SRXD6__USBH2_DATA7	IOMUX_MODE(MX31_PIN_SRXD6, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBH2_CLK__USBH2_CLK		IOMUX_MODE(MX31_PIN_USBH2_CLK, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBH2_DIR__USBH2_DIR		IOMUX_MODE(MX31_PIN_USBH2_DIR, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBH2_NXT__USBH2_NXT		IOMUX_MODE(MX31_PIN_USBH2_NXT, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBH2_STP__USBH2_STP		IOMUX_MODE(MX31_PIN_USBH2_STP, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SCK6__GPIO1_25		IOMUX_MODE(MX31_PIN_SCK6, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_USB_OC__GPIO1_30	IOMUX_MODE(MX31_PIN_USB_OC, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_I2C_DAT__I2C1_SDA	IOMUX_MODE(MX31_PIN_I2C_DAT, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_I2C_CLK__I2C1_SCL	IOMUX_MODE(MX31_PIN_I2C_CLK, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_DCD_DTE1__I2C2_SDA	IOMUX_MODE(MX31_PIN_DCD_DTE1, IOMUX_CONFIG_ALT2)
-#define MX31_PIN_RI_DTE1__I2C2_SCL	IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_ALT2)
-#define MX31_PIN_ATA_CS0__GPIO3_26	IOMUX_MODE(MX31_PIN_ATA_CS0, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_ATA_CS1__GPIO3_27	IOMUX_MODE(MX31_PIN_ATA_CS1, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_PC_PWRON__SD2_DATA3	IOMUX_MODE(MX31_PIN_PC_PWRON, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_PC_VS1__SD2_DATA2	IOMUX_MODE(MX31_PIN_PC_VS1, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_PC_READY__SD2_DATA1	IOMUX_MODE(MX31_PIN_PC_READY, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_PC_WAIT_B__SD2_DATA0	IOMUX_MODE(MX31_PIN_PC_WAIT_B, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_PC_CD2_B__SD2_CLK	IOMUX_MODE(MX31_PIN_PC_CD2_B, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_PC_CD1_B__SD2_CMD	IOMUX_MODE(MX31_PIN_PC_CD1_B, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_ATA_DIOR__GPIO3_28	IOMUX_MODE(MX31_PIN_ATA_DIOR, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_ATA_DIOW__GPIO3_29	IOMUX_MODE(MX31_PIN_ATA_DIOW, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_CSI_D4__CSI_D4		IOMUX_MODE(MX31_PIN_CSI_D4, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D5__CSI_D5		IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D6__CSI_D6		IOMUX_MODE(MX31_PIN_CSI_D6, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D7__CSI_D7		IOMUX_MODE(MX31_PIN_CSI_D7, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D8__CSI_D8		IOMUX_MODE(MX31_PIN_CSI_D8, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D9__CSI_D9		IOMUX_MODE(MX31_PIN_CSI_D9, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D10__CSI_D10	IOMUX_MODE(MX31_PIN_CSI_D10, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D11__CSI_D11	IOMUX_MODE(MX31_PIN_CSI_D11, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D12__CSI_D12	IOMUX_MODE(MX31_PIN_CSI_D12, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D13__CSI_D13	IOMUX_MODE(MX31_PIN_CSI_D13, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D14__CSI_D14	IOMUX_MODE(MX31_PIN_CSI_D14, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_D15__CSI_D15	IOMUX_MODE(MX31_PIN_CSI_D15, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_HSYNC__CSI_HSYNC	IOMUX_MODE(MX31_PIN_CSI_HSYNC, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_MCLK__CSI_MCLK	IOMUX_MODE(MX31_PIN_CSI_MCLK, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_PIXCLK__CSI_PIXCLK	IOMUX_MODE(MX31_PIN_CSI_PIXCLK, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSI_VSYNC__CSI_VSYNC	IOMUX_MODE(MX31_PIN_CSI_VSYNC, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_GPIO3_0__GPIO3_0	IOMUX_MODE(MX31_PIN_GPIO3_0, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_GPIO3_1__GPIO3_1	IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_TXD2__GPIO1_28		IOMUX_MODE(MX31_PIN_TXD2, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_GPIO1_0__GPIO1_0	IOMUX_MODE(MX31_PIN_GPIO1_0, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_SVEN0__GPIO2_0		IOMUX_MODE(MX31_PIN_SVEN0, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_STX0__GPIO2_1		IOMUX_MODE(MX31_PIN_STX0, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_SRX0__GPIO2_2		IOMUX_MODE(MX31_PIN_SRX0, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_SIMPD0__GPIO2_3	IOMUX_MODE(MX31_PIN_SIMPD0, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_DTR_DCE1__GPIO2_8	IOMUX_MODE(MX31_PIN_DTR_DCE1, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_DSR_DCE1__GPIO2_9	IOMUX_MODE(MX31_PIN_DSR_DCE1, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_RI_DCE1__GPIO2_10	IOMUX_MODE(MX31_PIN_RI_DCE1, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_DCD_DCE1__GPIO2_11	IOMUX_MODE(MX31_PIN_DCD_DCE1, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_STXD5__GPIO1_21	IOMUX_MODE(MX31_PIN_STXD5, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_SRXD5__GPIO1_22	IOMUX_MODE(MX31_PIN_SRXD5, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_GPIO1_3__GPIO1_3	IOMUX_MODE(MX31_PIN_GPIO1_3, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_CSPI2_SS1__CSPI3_SS1	IOMUX_MODE(MX31_PIN_CSPI2_SS1, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_RTS1__GPIO2_6		IOMUX_MODE(MX31_PIN_RTS1, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_CTS1__GPIO2_7		IOMUX_MODE(MX31_PIN_CTS1, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_LCS0__GPIO3_23		IOMUX_MODE(MX31_PIN_LCS0, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_STXD4__STXD4		IOMUX_MODE(MX31_PIN_STXD4, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SRXD4__SRXD4		IOMUX_MODE(MX31_PIN_SRXD4, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SCK4__SCK4		IOMUX_MODE(MX31_PIN_SCK4, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SFS4__SFS4		IOMUX_MODE(MX31_PIN_SFS4, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_STXD5__STXD5		IOMUX_MODE(MX31_PIN_STXD5, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SRXD5__SRXD5		IOMUX_MODE(MX31_PIN_SRXD5, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SCK5__SCK5		IOMUX_MODE(MX31_PIN_SCK5, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_SFS5__SFS5		IOMUX_MODE(MX31_PIN_SFS5, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_KEY_ROW0_KEY_ROW0	IOMUX_MODE(MX31_PIN_KEY_ROW0, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_KEY_ROW1_KEY_ROW1	IOMUX_MODE(MX31_PIN_KEY_ROW1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_KEY_ROW2_KEY_ROW2	IOMUX_MODE(MX31_PIN_KEY_ROW2, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_KEY_ROW3_KEY_ROW3	IOMUX_MODE(MX31_PIN_KEY_ROW3, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_KEY_ROW4_KEY_ROW4	IOMUX_MODE(MX31_PIN_KEY_ROW4, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_KEY_ROW4_GPIO		IOMUX_MODE(MX31_PIN_KEY_ROW4, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_KEY_ROW5_KEY_ROW5	IOMUX_MODE(MX31_PIN_KEY_ROW5, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_KEY_ROW6_KEY_ROW6	IOMUX_MODE(MX31_PIN_KEY_ROW6, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_KEY_ROW7_KEY_ROW7	IOMUX_MODE(MX31_PIN_KEY_ROW7, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_KEY_COL0_KEY_COL0	IOMUX_MODE(MX31_PIN_KEY_COL0, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_KEY_COL1_KEY_COL1	IOMUX_MODE(MX31_PIN_KEY_COL1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_KEY_COL2_KEY_COL2	IOMUX_MODE(MX31_PIN_KEY_COL2, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_KEY_COL3_KEY_COL3	IOMUX_MODE(MX31_PIN_KEY_COL3, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_KEY_COL4_KEY_COL4	IOMUX_MODE(MX31_PIN_KEY_COL4, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_KEY_COL5_KEY_COL5	IOMUX_MODE(MX31_PIN_KEY_COL5, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_KEY_COL6_KEY_COL6	IOMUX_MODE(MX31_PIN_KEY_COL6, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_KEY_COL7_KEY_COL7	IOMUX_MODE(MX31_PIN_KEY_COL7, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_WATCHDOG_RST__WATCHDOG_RST	IOMUX_MODE(MX31_PIN_WATCHDOG_RST, IOMUX_CONFIG_FUNC)
-
-
-/*
- * XXX: The SS0, SS1, SS2, SS3 lines of spi3 are multiplexed with cspi2_ss0,
- * cspi2_ss1, cspi1_ss0 cspi1_ss1
- */
-
-/*
- * This function configures the pad value for a IOMUX pin.
- */
-void mxc_iomux_set_pad(enum iomux_pins, u32);
-
-#endif /* ifndef __MACH_IOMUX_MX3_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx35.h b/arch/arm/plat-mxc/include/mach/iomux-mx35.h
deleted file mode 100644
index 3117c18..0000000
--- a/arch/arm/plat-mxc/include/mach/iomux-mx35.h
+++ /dev/null
@@ -1,1267 +0,0 @@
-/*
- * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH <armlinux@phytec.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option, NO_PAD_CTRL) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef __MACH_IOMUX_MX35_H__
-#define __MACH_IOMUX_MX35_H__
-
-#include <mach/iomux-v3.h>
-
-/*
- * The naming convention for the pad modes is MX35_PAD_<padname>__<padmode>
- * If <padname> or <padmode> refers to a GPIO, it is named
- * GPIO_<unit>_<num> see also iomux-v3.h
- */
-
-/*									  PAD    MUX   ALT INPSE PATH */
-#define MX35_PAD_CAPTURE__GPT_CAPIN1				IOMUX_PAD(0x328, 0x004, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CAPTURE__GPT_CMPOUT2				IOMUX_PAD(0x328, 0x004, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CAPTURE__CSPI2_SS1				IOMUX_PAD(0x328, 0x004, 2, 0x7f4, 0, NO_PAD_CTRL)
-#define MX35_PAD_CAPTURE__EPIT1_EPITO				IOMUX_PAD(0x328, 0x004, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CAPTURE__CCM_CLK32K				IOMUX_PAD(0x328, 0x004, 4, 0x7d0, 0, NO_PAD_CTRL)
-#define MX35_PAD_CAPTURE__GPIO1_4				IOMUX_PAD(0x328, 0x004, 5, 0x850, 0, NO_PAD_CTRL)
-
-#define MX35_PAD_COMPARE__GPT_CMPOUT1				IOMUX_PAD(0x32c, 0x008, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_COMPARE__GPT_CAPIN2				IOMUX_PAD(0x32c, 0x008, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_COMPARE__GPT_CMPOUT3				IOMUX_PAD(0x32c, 0x008, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_COMPARE__EPIT2_EPITO				IOMUX_PAD(0x32c, 0x008, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_COMPARE__GPIO1_5				IOMUX_PAD(0x32c, 0x008, 5, 0x854, 0, NO_PAD_CTRL)
-#define MX35_PAD_COMPARE__SDMA_EXTDMA_2				IOMUX_PAD(0x32c, 0x008, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_WDOG_RST__WDOG_WDOG_B				IOMUX_PAD(0x330, 0x00c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_WDOG_RST__IPU_FLASH_STROBE			IOMUX_PAD(0x330, 0x00c, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_WDOG_RST__GPIO1_6				IOMUX_PAD(0x330, 0x00c, 5, 0x858, 0, NO_PAD_CTRL)
-
-#define MX35_PAD_GPIO1_0__GPIO1_0				IOMUX_PAD(0x334, 0x010, 0, 0x82c, 0, NO_PAD_CTRL)
-#define MX35_PAD_GPIO1_0__CCM_PMIC_RDY				IOMUX_PAD(0x334, 0x010, 1, 0x7d4, 0, NO_PAD_CTRL)
-#define MX35_PAD_GPIO1_0__OWIRE_LINE				IOMUX_PAD(0x334, 0x010, 2, 0x990, 0, NO_PAD_CTRL)
-#define MX35_PAD_GPIO1_0__SDMA_EXTDMA_0				IOMUX_PAD(0x334, 0x010, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_GPIO1_1__GPIO1_1				IOMUX_PAD(0x338, 0x014, 0, 0x838, 0, NO_PAD_CTRL)
-#define MX35_PAD_GPIO1_1__PWM_PWMO				IOMUX_PAD(0x338, 0x014, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_GPIO1_1__CSPI1_SS2				IOMUX_PAD(0x338, 0x014, 3, 0x7d8, 0, NO_PAD_CTRL)
-#define MX35_PAD_GPIO1_1__SCC_TAMPER_DETECT			IOMUX_PAD(0x338, 0x014, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_GPIO1_1__SDMA_EXTDMA_1				IOMUX_PAD(0x338, 0x014, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_GPIO2_0__GPIO2_0				IOMUX_PAD(0x33c, 0x018, 0, 0x868, 0, NO_PAD_CTRL)
-#define MX35_PAD_GPIO2_0__USB_TOP_USBOTG_CLK			IOMUX_PAD(0x33c, 0x018, 1, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_GPIO3_0__GPIO3_0				IOMUX_PAD(0x340, 0x01c, 0, 0x8e8, 0, NO_PAD_CTRL)
-#define MX35_PAD_GPIO3_0__USB_TOP_USBH2_CLK			IOMUX_PAD(0x340, 0x01c, 1, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_RESET_IN_B__CCM_RESET_IN_B			IOMUX_PAD(0x344, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_POR_B__CCM_POR_B				IOMUX_PAD(0x348, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CLKO__CCM_CLKO					IOMUX_PAD(0x34c, 0x020, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CLKO__GPIO1_8					IOMUX_PAD(0x34c, 0x020, 5, 0x860, 0, NO_PAD_CTRL)
-
-#define MX35_PAD_BOOT_MODE0__CCM_BOOT_MODE_0			IOMUX_PAD(0x350, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_BOOT_MODE1__CCM_BOOT_MODE_1			IOMUX_PAD(0x354, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CLK_MODE0__CCM_CLK_MODE_0			IOMUX_PAD(0x358, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CLK_MODE1__CCM_CLK_MODE_1			IOMUX_PAD(0x35c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_POWER_FAIL__CCM_DSM_WAKEUP_INT_26		IOMUX_PAD(0x360, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_VSTBY__CCM_VSTBY				IOMUX_PAD(0x364, 0x024, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_VSTBY__GPIO1_7					IOMUX_PAD(0x364, 0x024, 5, 0x85c, 0, NO_PAD_CTRL)
-
-#define MX35_PAD_A0__EMI_EIM_DA_L_0				IOMUX_PAD(0x368, 0x028, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A1__EMI_EIM_DA_L_1				IOMUX_PAD(0x36c, 0x02c, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A2__EMI_EIM_DA_L_2				IOMUX_PAD(0x370, 0x030, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A3__EMI_EIM_DA_L_3				IOMUX_PAD(0x374, 0x034, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A4__EMI_EIM_DA_L_4				IOMUX_PAD(0x378, 0x038, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A5__EMI_EIM_DA_L_5				IOMUX_PAD(0x37c, 0x03c, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A6__EMI_EIM_DA_L_6				IOMUX_PAD(0x380, 0x040, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A7__EMI_EIM_DA_L_7				IOMUX_PAD(0x384, 0x044, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A8__EMI_EIM_DA_H_8				IOMUX_PAD(0x388, 0x048, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A9__EMI_EIM_DA_H_9				IOMUX_PAD(0x38c, 0x04c, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A10__EMI_EIM_DA_H_10				IOMUX_PAD(0x390, 0x050, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_MA10__EMI_MA10					IOMUX_PAD(0x394, 0x054, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A11__EMI_EIM_DA_H_11				IOMUX_PAD(0x398, 0x058, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A12__EMI_EIM_DA_H_12				IOMUX_PAD(0x39c, 0x05c, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A13__EMI_EIM_DA_H_13				IOMUX_PAD(0x3a0, 0x060, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A14__EMI_EIM_DA_H2_14				IOMUX_PAD(0x3a4, 0x064, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A15__EMI_EIM_DA_H2_15				IOMUX_PAD(0x3a8, 0x068, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A16__EMI_EIM_A_16				IOMUX_PAD(0x3ac, 0x06c, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A17__EMI_EIM_A_17				IOMUX_PAD(0x3b0, 0x070, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A18__EMI_EIM_A_18				IOMUX_PAD(0x3b4, 0x074, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A19__EMI_EIM_A_19				IOMUX_PAD(0x3b8, 0x078, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A20__EMI_EIM_A_20				IOMUX_PAD(0x3bc, 0x07c, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A21__EMI_EIM_A_21				IOMUX_PAD(0x3c0, 0x080, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A22__EMI_EIM_A_22				IOMUX_PAD(0x3c4, 0x084, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A23__EMI_EIM_A_23				IOMUX_PAD(0x3c8, 0x088, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A24__EMI_EIM_A_24				IOMUX_PAD(0x3cc, 0x08c, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_A25__EMI_EIM_A_25				IOMUX_PAD(0x3d0, 0x090, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SDBA1__EMI_EIM_SDBA1				IOMUX_PAD(0x3d4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SDBA0__EMI_EIM_SDBA0				IOMUX_PAD(0x3d8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD0__EMI_DRAM_D_0				IOMUX_PAD(0x3dc, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD1__EMI_DRAM_D_1				IOMUX_PAD(0x3e0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD2__EMI_DRAM_D_2				IOMUX_PAD(0x3e4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD3__EMI_DRAM_D_3				IOMUX_PAD(0x3e8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD4__EMI_DRAM_D_4				IOMUX_PAD(0x3ec, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD5__EMI_DRAM_D_5				IOMUX_PAD(0x3f0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD6__EMI_DRAM_D_6				IOMUX_PAD(0x3f4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD7__EMI_DRAM_D_7				IOMUX_PAD(0x3f8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD8__EMI_DRAM_D_8				IOMUX_PAD(0x3fc, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD9__EMI_DRAM_D_9				IOMUX_PAD(0x400, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD10__EMI_DRAM_D_10				IOMUX_PAD(0x404, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD11__EMI_DRAM_D_11				IOMUX_PAD(0x408, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD12__EMI_DRAM_D_12				IOMUX_PAD(0x40c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD13__EMI_DRAM_D_13				IOMUX_PAD(0x410, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD14__EMI_DRAM_D_14				IOMUX_PAD(0x414, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD15__EMI_DRAM_D_15				IOMUX_PAD(0x418, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD16__EMI_DRAM_D_16				IOMUX_PAD(0x41c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD17__EMI_DRAM_D_17				IOMUX_PAD(0x420, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD18__EMI_DRAM_D_18				IOMUX_PAD(0x424, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD19__EMI_DRAM_D_19				IOMUX_PAD(0x428, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD20__EMI_DRAM_D_20				IOMUX_PAD(0x42c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD21__EMI_DRAM_D_21				IOMUX_PAD(0x430, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD22__EMI_DRAM_D_22				IOMUX_PAD(0x434, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD23__EMI_DRAM_D_23				IOMUX_PAD(0x438, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD24__EMI_DRAM_D_24				IOMUX_PAD(0x43c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD25__EMI_DRAM_D_25				IOMUX_PAD(0x440, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD26__EMI_DRAM_D_26				IOMUX_PAD(0x444, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD27__EMI_DRAM_D_27				IOMUX_PAD(0x448, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD28__EMI_DRAM_D_28				IOMUX_PAD(0x44c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD29__EMI_DRAM_D_29				IOMUX_PAD(0x450, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD30__EMI_DRAM_D_30				IOMUX_PAD(0x454, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD31__EMI_DRAM_D_31				IOMUX_PAD(0x458, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_DQM0__EMI_DRAM_DQM_0				IOMUX_PAD(0x45c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_DQM1__EMI_DRAM_DQM_1				IOMUX_PAD(0x460, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_DQM2__EMI_DRAM_DQM_2				IOMUX_PAD(0x464, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_DQM3__EMI_DRAM_DQM_3				IOMUX_PAD(0x468, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_EB0__EMI_EIM_EB0_B				IOMUX_PAD(0x46c, 0x094, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_EB1__EMI_EIM_EB1_B				IOMUX_PAD(0x470, 0x098, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_OE__EMI_EIM_OE					IOMUX_PAD(0x474, 0x09c, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CS0__EMI_EIM_CS0				IOMUX_PAD(0x478, 0x0a0, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CS1__EMI_EIM_CS1				IOMUX_PAD(0x47c, 0x0a4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CS1__EMI_NANDF_CE3				IOMUX_PAD(0x47c, 0x0a4, 3, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CS2__EMI_EIM_CS2				IOMUX_PAD(0x480, 0x0a8, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CS3__EMI_EIM_CS3				IOMUX_PAD(0x484, 0x0ac, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CS4__EMI_EIM_CS4				IOMUX_PAD(0x488, 0x0b0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CS4__EMI_DTACK_B				IOMUX_PAD(0x488, 0x0b0, 1, 0x800, 0, NO_PAD_CTRL)
-#define MX35_PAD_CS4__EMI_NANDF_CE1				IOMUX_PAD(0x488, 0x0b0, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CS4__GPIO1_20					IOMUX_PAD(0x488, 0x0b0, 5, 0x83c, 0, NO_PAD_CTRL)
-
-#define MX35_PAD_CS5__EMI_EIM_CS5				IOMUX_PAD(0x48c, 0x0b4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CS5__CSPI2_SS2					IOMUX_PAD(0x48c, 0x0b4, 1, 0x7f8, 0, NO_PAD_CTRL)
-#define MX35_PAD_CS5__CSPI1_SS2					IOMUX_PAD(0x48c, 0x0b4, 2, 0x7d8, 1, NO_PAD_CTRL)
-#define MX35_PAD_CS5__EMI_NANDF_CE2				IOMUX_PAD(0x48c, 0x0b4, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CS5__GPIO1_21					IOMUX_PAD(0x48c, 0x0b4, 5, 0x840, 0, NO_PAD_CTRL)
-
-#define MX35_PAD_NF_CE0__EMI_NANDF_CE0				IOMUX_PAD(0x490, 0x0b8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_NF_CE0__GPIO1_22				IOMUX_PAD(0x490, 0x0b8, 5, 0x844, 0, NO_PAD_CTRL)
-
-#define MX35_PAD_ECB__EMI_EIM_ECB				IOMUX_PAD(0x494, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LBA__EMI_EIM_LBA				IOMUX_PAD(0x498, 0x0bc, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_BCLK__EMI_EIM_BCLK				IOMUX_PAD(0x49c, 0x0c0, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_RW__EMI_EIM_RW					IOMUX_PAD(0x4a0, 0x0c4, 0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_RAS__EMI_DRAM_RAS				IOMUX_PAD(0x4a4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CAS__EMI_DRAM_CAS				IOMUX_PAD(0x4a8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SDWE__EMI_DRAM_SDWE				IOMUX_PAD(0x4ac, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SDCKE0__EMI_DRAM_SDCKE_0			IOMUX_PAD(0x4b0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SDCKE1__EMI_DRAM_SDCKE_1			IOMUX_PAD(0x4b4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SDCLK__EMI_DRAM_SDCLK				IOMUX_PAD(0x4b8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SDQS0__EMI_DRAM_SDQS_0				IOMUX_PAD(0x4bc, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SDQS1__EMI_DRAM_SDQS_1				IOMUX_PAD(0x4c0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SDQS2__EMI_DRAM_SDQS_2				IOMUX_PAD(0x4c4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SDQS3__EMI_DRAM_SDQS_3				IOMUX_PAD(0x4c8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_NFWE_B__EMI_NANDF_WE_B				IOMUX_PAD(0x4cc, 0x0c8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_NFWE_B__USB_TOP_USBH2_DATA_3			IOMUX_PAD(0x4cc, 0x0c8, 1, 0x9d8, 0, NO_PAD_CTRL)
-#define MX35_PAD_NFWE_B__IPU_DISPB_D0_VSYNC			IOMUX_PAD(0x4cc, 0x0c8, 2, 0x924, 0, NO_PAD_CTRL)
-#define MX35_PAD_NFWE_B__GPIO2_18				IOMUX_PAD(0x4cc, 0x0c8, 5, 0x88c, 0, NO_PAD_CTRL)
-#define MX35_PAD_NFWE_B__ARM11P_TOP_TRACE_0			IOMUX_PAD(0x4cc, 0x0c8, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_NFRE_B__EMI_NANDF_RE_B				IOMUX_PAD(0x4d0, 0x0cc, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_NFRE_B__USB_TOP_USBH2_DIR			IOMUX_PAD(0x4d0, 0x0cc, 1, 0x9ec, 0, NO_PAD_CTRL)
-#define MX35_PAD_NFRE_B__IPU_DISPB_BCLK				IOMUX_PAD(0x4d0, 0x0cc, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_NFRE_B__GPIO2_19				IOMUX_PAD(0x4d0, 0x0cc, 5, 0x890, 0, NO_PAD_CTRL)
-#define MX35_PAD_NFRE_B__ARM11P_TOP_TRACE_1			IOMUX_PAD(0x4d0, 0x0cc, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_NFALE__EMI_NANDF_ALE				IOMUX_PAD(0x4d4, 0x0d0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_NFALE__USB_TOP_USBH2_STP			IOMUX_PAD(0x4d4, 0x0d0, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_NFALE__IPU_DISPB_CS0				IOMUX_PAD(0x4d4, 0x0d0, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_NFALE__GPIO2_20				IOMUX_PAD(0x4d4, 0x0d0, 5, 0x898, 0, NO_PAD_CTRL)
-#define MX35_PAD_NFALE__ARM11P_TOP_TRACE_2			IOMUX_PAD(0x4d4, 0x0d0, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_NFCLE__EMI_NANDF_CLE				IOMUX_PAD(0x4d8, 0x0d4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_NFCLE__USB_TOP_USBH2_NXT			IOMUX_PAD(0x4d8, 0x0d4, 1, 0x9f0, 0, NO_PAD_CTRL)
-#define MX35_PAD_NFCLE__IPU_DISPB_PAR_RS			IOMUX_PAD(0x4d8, 0x0d4, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_NFCLE__GPIO2_21				IOMUX_PAD(0x4d8, 0x0d4, 5, 0x89c, 0, NO_PAD_CTRL)
-#define MX35_PAD_NFCLE__ARM11P_TOP_TRACE_3			IOMUX_PAD(0x4d8, 0x0d4, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_NFWP_B__EMI_NANDF_WP_B				IOMUX_PAD(0x4dc, 0x0d8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_NFWP_B__USB_TOP_USBH2_DATA_7			IOMUX_PAD(0x4dc, 0x0d8, 1, 0x9e8, 0, NO_PAD_CTRL)
-#define MX35_PAD_NFWP_B__IPU_DISPB_WR				IOMUX_PAD(0x4dc, 0x0d8, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_NFWP_B__GPIO2_22				IOMUX_PAD(0x4dc, 0x0d8, 5, 0x8a0, 0, NO_PAD_CTRL)
-#define MX35_PAD_NFWP_B__ARM11P_TOP_TRCTL			IOMUX_PAD(0x4dc, 0x0d8, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_NFRB__EMI_NANDF_RB				IOMUX_PAD(0x4e0, 0x0dc, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_NFRB__IPU_DISPB_RD				IOMUX_PAD(0x4e0, 0x0dc, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_NFRB__GPIO2_23					IOMUX_PAD(0x4e0, 0x0dc, 5, 0x8a4, 0, NO_PAD_CTRL)
-#define MX35_PAD_NFRB__ARM11P_TOP_TRCLK				IOMUX_PAD(0x4e0, 0x0dc, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D15__EMI_EIM_D_15				IOMUX_PAD(0x4e4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D14__EMI_EIM_D_14				IOMUX_PAD(0x4e8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D13__EMI_EIM_D_13				IOMUX_PAD(0x4ec, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D12__EMI_EIM_D_12				IOMUX_PAD(0x4f0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D11__EMI_EIM_D_11				IOMUX_PAD(0x4f4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D10__EMI_EIM_D_10				IOMUX_PAD(0x4f8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D9__EMI_EIM_D_9				IOMUX_PAD(0x4fc, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D8__EMI_EIM_D_8				IOMUX_PAD(0x500, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D7__EMI_EIM_D_7				IOMUX_PAD(0x504, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D6__EMI_EIM_D_6				IOMUX_PAD(0x508, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D5__EMI_EIM_D_5				IOMUX_PAD(0x50c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D4__EMI_EIM_D_4				IOMUX_PAD(0x510, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D3__EMI_EIM_D_3				IOMUX_PAD(0x514, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D2__EMI_EIM_D_2				IOMUX_PAD(0x518, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D1__EMI_EIM_D_1				IOMUX_PAD(0x51c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D0__EMI_EIM_D_0				IOMUX_PAD(0x520, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSI_D8__IPU_CSI_D_8				IOMUX_PAD(0x524, 0x0e0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D8__KPP_COL_0				IOMUX_PAD(0x524, 0x0e0, 1, 0x950, 0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D8__GPIO1_20				IOMUX_PAD(0x524, 0x0e0, 5, 0x83c, 1, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D8__ARM11P_TOP_EVNTBUS_13			IOMUX_PAD(0x524, 0x0e0, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSI_D9__IPU_CSI_D_9				IOMUX_PAD(0x528, 0x0e4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D9__KPP_COL_1				IOMUX_PAD(0x528, 0x0e4, 1, 0x954, 0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D9__GPIO1_21				IOMUX_PAD(0x528, 0x0e4, 5, 0x840, 1, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D9__ARM11P_TOP_EVNTBUS_14			IOMUX_PAD(0x528, 0x0e4, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSI_D10__IPU_CSI_D_10				IOMUX_PAD(0x52c, 0x0e8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D10__KPP_COL_2				IOMUX_PAD(0x52c, 0x0e8, 1, 0x958, 0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D10__GPIO1_22				IOMUX_PAD(0x52c, 0x0e8, 5, 0x844, 1, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D10__ARM11P_TOP_EVNTBUS_15			IOMUX_PAD(0x52c, 0x0e8, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSI_D11__IPU_CSI_D_11				IOMUX_PAD(0x530, 0x0ec, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D11__KPP_COL_3				IOMUX_PAD(0x530, 0x0ec, 1, 0x95c, 0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D11__GPIO1_23				IOMUX_PAD(0x530, 0x0ec, 5, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSI_D12__IPU_CSI_D_12				IOMUX_PAD(0x534, 0x0f0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D12__KPP_ROW_0				IOMUX_PAD(0x534, 0x0f0, 1, 0x970, 0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D12__GPIO1_24				IOMUX_PAD(0x534, 0x0f0, 5, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSI_D13__IPU_CSI_D_13				IOMUX_PAD(0x538, 0x0f4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D13__KPP_ROW_1				IOMUX_PAD(0x538, 0x0f4, 1, 0x974, 0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D13__GPIO1_25				IOMUX_PAD(0x538, 0x0f4, 5, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSI_D14__IPU_CSI_D_14				IOMUX_PAD(0x53c, 0x0f8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D14__KPP_ROW_2				IOMUX_PAD(0x53c, 0x0f8, 1, 0x978, 0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D14__GPIO1_26				IOMUX_PAD(0x53c, 0x0f8, 5, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSI_D15__IPU_CSI_D_15				IOMUX_PAD(0x540, 0x0fc, 0, 0x97c, 0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D15__KPP_ROW_3				IOMUX_PAD(0x540, 0x0fc, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_D15__GPIO1_27				IOMUX_PAD(0x540, 0x0fc, 5, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSI_MCLK__IPU_CSI_MCLK				IOMUX_PAD(0x544, 0x100, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_MCLK__GPIO1_28				IOMUX_PAD(0x544, 0x100, 5, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSI_VSYNC__IPU_CSI_VSYNC			IOMUX_PAD(0x548, 0x104, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_VSYNC__GPIO1_29				IOMUX_PAD(0x548, 0x104, 5, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSI_HSYNC__IPU_CSI_HSYNC			IOMUX_PAD(0x54c, 0x108, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_HSYNC__GPIO1_30				IOMUX_PAD(0x54c, 0x108, 5, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSI_PIXCLK__IPU_CSI_PIXCLK			IOMUX_PAD(0x550, 0x10c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSI_PIXCLK__GPIO1_31				IOMUX_PAD(0x550, 0x10c, 5, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_I2C1_CLK__I2C1_SCL				IOMUX_PAD(0x554, 0x110, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_I2C1_CLK__GPIO2_24				IOMUX_PAD(0x554, 0x110, 5, 0x8a8, 0, NO_PAD_CTRL)
-#define MX35_PAD_I2C1_CLK__CCM_USB_BYP_CLK			IOMUX_PAD(0x554, 0x110, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_I2C1_DAT__I2C1_SDA				IOMUX_PAD(0x558, 0x114, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_I2C1_DAT__GPIO2_25				IOMUX_PAD(0x558, 0x114, 5, 0x8ac, 0, NO_PAD_CTRL)
-
-#define MX35_PAD_I2C2_CLK__I2C2_SCL				IOMUX_PAD(0x55c, 0x118, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_I2C2_CLK__CAN1_TXCAN				IOMUX_PAD(0x55c, 0x118, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_I2C2_CLK__USB_TOP_USBH2_PWR			IOMUX_PAD(0x55c, 0x118, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_I2C2_CLK__GPIO2_26				IOMUX_PAD(0x55c, 0x118, 5, 0x8b0, 0, NO_PAD_CTRL)
-#define MX35_PAD_I2C2_CLK__SDMA_DEBUG_BUS_DEVICE_2		IOMUX_PAD(0x55c, 0x118, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_I2C2_DAT__I2C2_SDA				IOMUX_PAD(0x560, 0x11c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_I2C2_DAT__CAN1_RXCAN				IOMUX_PAD(0x560, 0x11c, 1, 0x7c8, 0, NO_PAD_CTRL)
-#define MX35_PAD_I2C2_DAT__USB_TOP_USBH2_OC			IOMUX_PAD(0x560, 0x11c, 2, 0x9f4, 0, NO_PAD_CTRL)
-#define MX35_PAD_I2C2_DAT__GPIO2_27				IOMUX_PAD(0x560, 0x11c, 5, 0x8b4, 0, NO_PAD_CTRL)
-#define MX35_PAD_I2C2_DAT__SDMA_DEBUG_BUS_DEVICE_3		IOMUX_PAD(0x560, 0x11c, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_STXD4__AUDMUX_AUD4_TXD				IOMUX_PAD(0x564, 0x120, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_STXD4__GPIO2_28				IOMUX_PAD(0x564, 0x120, 5, 0x8b8, 0, NO_PAD_CTRL)
-#define MX35_PAD_STXD4__ARM11P_TOP_ARM_COREASID0		IOMUX_PAD(0x564, 0x120, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SRXD4__AUDMUX_AUD4_RXD				IOMUX_PAD(0x568, 0x124, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SRXD4__GPIO2_29				IOMUX_PAD(0x568, 0x124, 5, 0x8bc, 0, NO_PAD_CTRL)
-#define MX35_PAD_SRXD4__ARM11P_TOP_ARM_COREASID1		IOMUX_PAD(0x568, 0x124, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SCK4__AUDMUX_AUD4_TXC				IOMUX_PAD(0x56c, 0x128, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SCK4__GPIO2_30					IOMUX_PAD(0x56c, 0x128, 5, 0x8c4, 0, NO_PAD_CTRL)
-#define MX35_PAD_SCK4__ARM11P_TOP_ARM_COREASID2			IOMUX_PAD(0x56c, 0x128, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS			IOMUX_PAD(0x570, 0x12c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_STXFS4__GPIO2_31				IOMUX_PAD(0x570, 0x12c, 5, 0x8c8, 0, NO_PAD_CTRL)
-#define MX35_PAD_STXFS4__ARM11P_TOP_ARM_COREASID3		IOMUX_PAD(0x570, 0x12c, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_STXD5__AUDMUX_AUD5_TXD				IOMUX_PAD(0x574, 0x130, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_STXD5__SPDIF_SPDIF_OUT1			IOMUX_PAD(0x574, 0x130, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_STXD5__CSPI2_MOSI				IOMUX_PAD(0x574, 0x130, 2, 0x7ec, 0, NO_PAD_CTRL)
-#define MX35_PAD_STXD5__GPIO1_0					IOMUX_PAD(0x574, 0x130, 5, 0x82c, 1, NO_PAD_CTRL)
-#define MX35_PAD_STXD5__ARM11P_TOP_ARM_COREASID4		IOMUX_PAD(0x574, 0x130, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SRXD5__AUDMUX_AUD5_RXD				IOMUX_PAD(0x578, 0x134, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SRXD5__SPDIF_SPDIF_IN1				IOMUX_PAD(0x578, 0x134, 1, 0x998, 0, NO_PAD_CTRL)
-#define MX35_PAD_SRXD5__CSPI2_MISO				IOMUX_PAD(0x578, 0x134, 2, 0x7e8, 0, NO_PAD_CTRL)
-#define MX35_PAD_SRXD5__GPIO1_1					IOMUX_PAD(0x578, 0x134, 5, 0x838, 1, NO_PAD_CTRL)
-#define MX35_PAD_SRXD5__ARM11P_TOP_ARM_COREASID5		IOMUX_PAD(0x578, 0x134, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SCK5__AUDMUX_AUD5_TXC				IOMUX_PAD(0x57c, 0x138, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SCK5__SPDIF_SPDIF_EXTCLK			IOMUX_PAD(0x57c, 0x138, 1, 0x994, 0, NO_PAD_CTRL)
-#define MX35_PAD_SCK5__CSPI2_SCLK				IOMUX_PAD(0x57c, 0x138, 2, 0x7e0, 0, NO_PAD_CTRL)
-#define MX35_PAD_SCK5__GPIO1_2					IOMUX_PAD(0x57c, 0x138, 5, 0x848, 0, NO_PAD_CTRL)
-#define MX35_PAD_SCK5__ARM11P_TOP_ARM_COREASID6			IOMUX_PAD(0x57c, 0x138, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_STXFS5__AUDMUX_AUD5_TXFS			IOMUX_PAD(0x580, 0x13c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_STXFS5__CSPI2_RDY				IOMUX_PAD(0x580, 0x13c, 2, 0x7e4, 0, NO_PAD_CTRL)
-#define MX35_PAD_STXFS5__GPIO1_3				IOMUX_PAD(0x580, 0x13c, 5, 0x84c, 0, NO_PAD_CTRL)
-#define MX35_PAD_STXFS5__ARM11P_TOP_ARM_COREASID7		IOMUX_PAD(0x580, 0x13c, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SCKR__ESAI_SCKR				IOMUX_PAD(0x584, 0x140, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SCKR__GPIO1_4					IOMUX_PAD(0x584, 0x140, 5, 0x850, 1, NO_PAD_CTRL)
-#define MX35_PAD_SCKR__ARM11P_TOP_EVNTBUS_10			IOMUX_PAD(0x584, 0x140, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FSR__ESAI_FSR					IOMUX_PAD(0x588, 0x144, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FSR__GPIO1_5					IOMUX_PAD(0x588, 0x144, 5, 0x854, 1, NO_PAD_CTRL)
-#define MX35_PAD_FSR__ARM11P_TOP_EVNTBUS_11			IOMUX_PAD(0x588, 0x144, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_HCKR__ESAI_HCKR				IOMUX_PAD(0x58c, 0x148, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_HCKR__AUDMUX_AUD5_RXFS				IOMUX_PAD(0x58c, 0x148, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_HCKR__CSPI2_SS0				IOMUX_PAD(0x58c, 0x148, 2, 0x7f0, 0, NO_PAD_CTRL)
-#define MX35_PAD_HCKR__IPU_FLASH_STROBE				IOMUX_PAD(0x58c, 0x148, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_HCKR__GPIO1_6					IOMUX_PAD(0x58c, 0x148, 5, 0x858, 1, NO_PAD_CTRL)
-#define MX35_PAD_HCKR__ARM11P_TOP_EVNTBUS_12			IOMUX_PAD(0x58c, 0x148, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SCKT__ESAI_SCKT				IOMUX_PAD(0x590, 0x14c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SCKT__GPIO1_7					IOMUX_PAD(0x590, 0x14c, 5, 0x85c, 1, NO_PAD_CTRL)
-#define MX35_PAD_SCKT__IPU_CSI_D_0				IOMUX_PAD(0x590, 0x14c, 6, 0x930, 0, NO_PAD_CTRL)
-#define MX35_PAD_SCKT__KPP_ROW_2				IOMUX_PAD(0x590, 0x14c, 7, 0x978, 1, NO_PAD_CTRL)
-
-#define MX35_PAD_FST__ESAI_FST					IOMUX_PAD(0x594, 0x150, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FST__GPIO1_8					IOMUX_PAD(0x594, 0x150, 5, 0x860, 1, NO_PAD_CTRL)
-#define MX35_PAD_FST__IPU_CSI_D_1				IOMUX_PAD(0x594, 0x150, 6, 0x934, 0, NO_PAD_CTRL)
-#define MX35_PAD_FST__KPP_ROW_3					IOMUX_PAD(0x594, 0x150, 7, 0x97c, 1, NO_PAD_CTRL)
-
-#define MX35_PAD_HCKT__ESAI_HCKT				IOMUX_PAD(0x598, 0x154, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_HCKT__AUDMUX_AUD5_RXC				IOMUX_PAD(0x598, 0x154, 1, 0x7a8, 0, NO_PAD_CTRL)
-#define MX35_PAD_HCKT__GPIO1_9					IOMUX_PAD(0x598, 0x154, 5, 0x864, 0, NO_PAD_CTRL)
-#define MX35_PAD_HCKT__IPU_CSI_D_2				IOMUX_PAD(0x598, 0x154, 6, 0x938, 0, NO_PAD_CTRL)
-#define MX35_PAD_HCKT__KPP_COL_3				IOMUX_PAD(0x598, 0x154, 7, 0x95c, 1, NO_PAD_CTRL)
-
-#define MX35_PAD_TX5_RX0__ESAI_TX5_RX0				IOMUX_PAD(0x59c, 0x158, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX5_RX0__AUDMUX_AUD4_RXC			IOMUX_PAD(0x59c, 0x158, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX5_RX0__CSPI2_SS2				IOMUX_PAD(0x59c, 0x158, 2, 0x7f8, 1, NO_PAD_CTRL)
-#define MX35_PAD_TX5_RX0__CAN2_TXCAN				IOMUX_PAD(0x59c, 0x158, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX5_RX0__UART2_DTR				IOMUX_PAD(0x59c, 0x158, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX5_RX0__GPIO1_10				IOMUX_PAD(0x59c, 0x158, 5, 0x830, 0, NO_PAD_CTRL)
-#define MX35_PAD_TX5_RX0__EMI_M3IF_CHOSEN_MASTER_0		IOMUX_PAD(0x59c, 0x158, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_TX4_RX1__ESAI_TX4_RX1				IOMUX_PAD(0x5a0, 0x15c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX4_RX1__AUDMUX_AUD4_RXFS			IOMUX_PAD(0x5a0, 0x15c, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX4_RX1__CSPI2_SS3				IOMUX_PAD(0x5a0, 0x15c, 2, 0x7fc, 0, NO_PAD_CTRL)
-#define MX35_PAD_TX4_RX1__CAN2_RXCAN				IOMUX_PAD(0x5a0, 0x15c, 3, 0x7cc, 0, NO_PAD_CTRL)
-#define MX35_PAD_TX4_RX1__UART2_DSR				IOMUX_PAD(0x5a0, 0x15c, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX4_RX1__GPIO1_11				IOMUX_PAD(0x5a0, 0x15c, 5, 0x834, 0, NO_PAD_CTRL)
-#define MX35_PAD_TX4_RX1__IPU_CSI_D_3				IOMUX_PAD(0x5a0, 0x15c, 6, 0x93c, 0, NO_PAD_CTRL)
-#define MX35_PAD_TX4_RX1__KPP_ROW_0				IOMUX_PAD(0x5a0, 0x15c, 7, 0x970, 1, NO_PAD_CTRL)
-
-#define MX35_PAD_TX3_RX2__ESAI_TX3_RX2				IOMUX_PAD(0x5a4, 0x160, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX3_RX2__I2C3_SCL				IOMUX_PAD(0x5a4, 0x160, 1, 0x91c, 0, NO_PAD_CTRL)
-#define MX35_PAD_TX3_RX2__EMI_NANDF_CE1				IOMUX_PAD(0x5a4, 0x160, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX3_RX2__GPIO1_12				IOMUX_PAD(0x5a4, 0x160, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX3_RX2__IPU_CSI_D_4				IOMUX_PAD(0x5a4, 0x160, 6, 0x940, 0, NO_PAD_CTRL)
-#define MX35_PAD_TX3_RX2__KPP_ROW_1				IOMUX_PAD(0x5a4, 0x160, 7, 0x974, 1, NO_PAD_CTRL)
-
-#define MX35_PAD_TX2_RX3__ESAI_TX2_RX3				IOMUX_PAD(0x5a8, 0x164, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX2_RX3__I2C3_SDA				IOMUX_PAD(0x5a8, 0x164, 1, 0x920, 0, NO_PAD_CTRL)
-#define MX35_PAD_TX2_RX3__EMI_NANDF_CE2				IOMUX_PAD(0x5a8, 0x164, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX2_RX3__GPIO1_13				IOMUX_PAD(0x5a8, 0x164, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX2_RX3__IPU_CSI_D_5				IOMUX_PAD(0x5a8, 0x164, 6, 0x944, 0, NO_PAD_CTRL)
-#define MX35_PAD_TX2_RX3__KPP_COL_0				IOMUX_PAD(0x5a8, 0x164, 7, 0x950, 1, NO_PAD_CTRL)
-
-#define MX35_PAD_TX1__ESAI_TX1					IOMUX_PAD(0x5ac, 0x168, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX1__CCM_PMIC_RDY				IOMUX_PAD(0x5ac, 0x168, 1, 0x7d4, 1, NO_PAD_CTRL)
-#define MX35_PAD_TX1__CSPI1_SS2					IOMUX_PAD(0x5ac, 0x168, 2, 0x7d8, 2, NO_PAD_CTRL)
-#define MX35_PAD_TX1__EMI_NANDF_CE3				IOMUX_PAD(0x5ac, 0x168, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX1__UART2_RI					IOMUX_PAD(0x5ac, 0x168, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX1__GPIO1_14					IOMUX_PAD(0x5ac, 0x168, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX1__IPU_CSI_D_6				IOMUX_PAD(0x5ac, 0x168, 6, 0x948, 0, NO_PAD_CTRL)
-#define MX35_PAD_TX1__KPP_COL_1					IOMUX_PAD(0x5ac, 0x168, 7, 0x954, 1, NO_PAD_CTRL)
-
-#define MX35_PAD_TX0__ESAI_TX0					IOMUX_PAD(0x5b0, 0x16c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX0__SPDIF_SPDIF_EXTCLK			IOMUX_PAD(0x5b0, 0x16c, 1, 0x994, 1, NO_PAD_CTRL)
-#define MX35_PAD_TX0__CSPI1_SS3					IOMUX_PAD(0x5b0, 0x16c, 2, 0x7dc, 0, NO_PAD_CTRL)
-#define MX35_PAD_TX0__EMI_DTACK_B				IOMUX_PAD(0x5b0, 0x16c, 3, 0x800, 1, NO_PAD_CTRL)
-#define MX35_PAD_TX0__UART2_DCD					IOMUX_PAD(0x5b0, 0x16c, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX0__GPIO1_15					IOMUX_PAD(0x5b0, 0x16c, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TX0__IPU_CSI_D_7				IOMUX_PAD(0x5b0, 0x16c, 6, 0x94c, 0, NO_PAD_CTRL)
-#define MX35_PAD_TX0__KPP_COL_2					IOMUX_PAD(0x5b0, 0x16c, 7, 0x958, 1, NO_PAD_CTRL)
-
-#define MX35_PAD_CSPI1_MOSI__CSPI1_MOSI				IOMUX_PAD(0x5b4, 0x170, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_MOSI__GPIO1_16				IOMUX_PAD(0x5b4, 0x170, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_MOSI__ECT_CTI_TRIG_OUT1_2		IOMUX_PAD(0x5b4, 0x170, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSPI1_MISO__CSPI1_MISO				IOMUX_PAD(0x5b8, 0x174, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_MISO__GPIO1_17				IOMUX_PAD(0x5b8, 0x174, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_MISO__ECT_CTI_TRIG_OUT1_3		IOMUX_PAD(0x5b8, 0x174, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSPI1_SS0__CSPI1_SS0				IOMUX_PAD(0x5bc, 0x178, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_SS0__OWIRE_LINE				IOMUX_PAD(0x5bc, 0x178, 1, 0x990, 1, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_SS0__CSPI2_SS3				IOMUX_PAD(0x5bc, 0x178, 2, 0x7fc, 1, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_SS0__GPIO1_18				IOMUX_PAD(0x5bc, 0x178, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_SS0__ECT_CTI_TRIG_OUT1_4			IOMUX_PAD(0x5bc, 0x178, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSPI1_SS1__CSPI1_SS1				IOMUX_PAD(0x5c0, 0x17c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_SS1__PWM_PWMO				IOMUX_PAD(0x5c0, 0x17c, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_SS1__CCM_CLK32K				IOMUX_PAD(0x5c0, 0x17c, 2, 0x7d0, 1, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_SS1__GPIO1_19				IOMUX_PAD(0x5c0, 0x17c, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_SS1__IPU_DIAGB_29			IOMUX_PAD(0x5c0, 0x17c, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_SS1__ECT_CTI_TRIG_OUT1_5			IOMUX_PAD(0x5c0, 0x17c, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSPI1_SCLK__CSPI1_SCLK				IOMUX_PAD(0x5c4, 0x180, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_SCLK__GPIO3_4				IOMUX_PAD(0x5c4, 0x180, 5, 0x904, 0, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_SCLK__IPU_DIAGB_30			IOMUX_PAD(0x5c4, 0x180, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_SCLK__EMI_M3IF_CHOSEN_MASTER_1		IOMUX_PAD(0x5c4, 0x180, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CSPI1_SPI_RDY__CSPI1_RDY			IOMUX_PAD(0x5c8, 0x184, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_SPI_RDY__GPIO3_5				IOMUX_PAD(0x5c8, 0x184, 5, 0x908, 0, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_SPI_RDY__IPU_DIAGB_31			IOMUX_PAD(0x5c8, 0x184, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CSPI1_SPI_RDY__EMI_M3IF_CHOSEN_MASTER_2	IOMUX_PAD(0x5c8, 0x184, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_RXD1__UART1_RXD_MUX				IOMUX_PAD(0x5cc, 0x188, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_RXD1__CSPI2_MOSI				IOMUX_PAD(0x5cc, 0x188, 1, 0x7ec, 1, NO_PAD_CTRL)
-#define MX35_PAD_RXD1__KPP_COL_4				IOMUX_PAD(0x5cc, 0x188, 4, 0x960, 0, NO_PAD_CTRL)
-#define MX35_PAD_RXD1__GPIO3_6					IOMUX_PAD(0x5cc, 0x188, 5, 0x90c, 0, NO_PAD_CTRL)
-#define MX35_PAD_RXD1__ARM11P_TOP_EVNTBUS_16			IOMUX_PAD(0x5cc, 0x188, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_TXD1__UART1_TXD_MUX				IOMUX_PAD(0x5d0, 0x18c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TXD1__CSPI2_MISO				IOMUX_PAD(0x5d0, 0x18c, 1, 0x7e8, 1, NO_PAD_CTRL)
-#define MX35_PAD_TXD1__KPP_COL_5				IOMUX_PAD(0x5d0, 0x18c, 4, 0x964, 0, NO_PAD_CTRL)
-#define MX35_PAD_TXD1__GPIO3_7					IOMUX_PAD(0x5d0, 0x18c, 5, 0x910, 0, NO_PAD_CTRL)
-#define MX35_PAD_TXD1__ARM11P_TOP_EVNTBUS_17			IOMUX_PAD(0x5d0, 0x18c, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_RTS1__UART1_RTS				IOMUX_PAD(0x5d4, 0x190, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_RTS1__CSPI2_SCLK				IOMUX_PAD(0x5d4, 0x190, 1, 0x7e0, 1, NO_PAD_CTRL)
-#define MX35_PAD_RTS1__I2C3_SCL					IOMUX_PAD(0x5d4, 0x190, 2, 0x91c, 1, NO_PAD_CTRL)
-#define MX35_PAD_RTS1__IPU_CSI_D_0				IOMUX_PAD(0x5d4, 0x190, 3, 0x930, 1, NO_PAD_CTRL)
-#define MX35_PAD_RTS1__KPP_COL_6				IOMUX_PAD(0x5d4, 0x190, 4, 0x968, 0, NO_PAD_CTRL)
-#define MX35_PAD_RTS1__GPIO3_8					IOMUX_PAD(0x5d4, 0x190, 5, 0x914, 0, NO_PAD_CTRL)
-#define MX35_PAD_RTS1__EMI_NANDF_CE1				IOMUX_PAD(0x5d4, 0x190, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_RTS1__ARM11P_TOP_EVNTBUS_18			IOMUX_PAD(0x5d4, 0x190, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CTS1__UART1_CTS				IOMUX_PAD(0x5d8, 0x194, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CTS1__CSPI2_RDY				IOMUX_PAD(0x5d8, 0x194, 1, 0x7e4, 1, NO_PAD_CTRL)
-#define MX35_PAD_CTS1__I2C3_SDA					IOMUX_PAD(0x5d8, 0x194, 2, 0x920, 1, NO_PAD_CTRL)
-#define MX35_PAD_CTS1__IPU_CSI_D_1				IOMUX_PAD(0x5d8, 0x194, 3, 0x934, 1, NO_PAD_CTRL)
-#define MX35_PAD_CTS1__KPP_COL_7				IOMUX_PAD(0x5d8, 0x194, 4, 0x96c, 0, NO_PAD_CTRL)
-#define MX35_PAD_CTS1__GPIO3_9					IOMUX_PAD(0x5d8, 0x194, 5, 0x918, 0, NO_PAD_CTRL)
-#define MX35_PAD_CTS1__EMI_NANDF_CE2				IOMUX_PAD(0x5d8, 0x194, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CTS1__ARM11P_TOP_EVNTBUS_19			IOMUX_PAD(0x5d8, 0x194, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_RXD2__UART2_RXD_MUX				IOMUX_PAD(0x5dc, 0x198, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_RXD2__KPP_ROW_4				IOMUX_PAD(0x5dc, 0x198, 4, 0x980, 0, NO_PAD_CTRL)
-#define MX35_PAD_RXD2__GPIO3_10					IOMUX_PAD(0x5dc, 0x198, 5, 0x8ec, 0, NO_PAD_CTRL)
-
-#define MX35_PAD_TXD2__UART2_TXD_MUX				IOMUX_PAD(0x5e0, 0x19c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_TXD2__SPDIF_SPDIF_EXTCLK			IOMUX_PAD(0x5e0, 0x19c, 1, 0x994, 2, NO_PAD_CTRL)
-#define MX35_PAD_TXD2__KPP_ROW_5				IOMUX_PAD(0x5e0, 0x19c, 4, 0x984, 0, NO_PAD_CTRL)
-#define MX35_PAD_TXD2__GPIO3_11					IOMUX_PAD(0x5e0, 0x19c, 5, 0x8f0, 0, NO_PAD_CTRL)
-
-#define MX35_PAD_RTS2__UART2_RTS				IOMUX_PAD(0x5e4, 0x1a0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_RTS2__SPDIF_SPDIF_IN1				IOMUX_PAD(0x5e4, 0x1a0, 1, 0x998, 1, NO_PAD_CTRL)
-#define MX35_PAD_RTS2__CAN2_RXCAN				IOMUX_PAD(0x5e4, 0x1a0, 2, 0x7cc, 1, NO_PAD_CTRL)
-#define MX35_PAD_RTS2__IPU_CSI_D_2				IOMUX_PAD(0x5e4, 0x1a0, 3, 0x938, 1, NO_PAD_CTRL)
-#define MX35_PAD_RTS2__KPP_ROW_6				IOMUX_PAD(0x5e4, 0x1a0, 4, 0x988, 0, NO_PAD_CTRL)
-#define MX35_PAD_RTS2__GPIO3_12					IOMUX_PAD(0x5e4, 0x1a0, 5, 0x8f4, 0, NO_PAD_CTRL)
-#define MX35_PAD_RTS2__AUDMUX_AUD5_RXC				IOMUX_PAD(0x5e4, 0x1a0, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_RTS2__UART3_RXD_MUX				IOMUX_PAD(0x5e4, 0x1a0, 7, 0x9a0, 0, NO_PAD_CTRL)
-
-#define MX35_PAD_CTS2__UART2_CTS				IOMUX_PAD(0x5e8, 0x1a4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CTS2__SPDIF_SPDIF_OUT1				IOMUX_PAD(0x5e8, 0x1a4, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CTS2__CAN2_TXCAN				IOMUX_PAD(0x5e8, 0x1a4, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CTS2__IPU_CSI_D_3				IOMUX_PAD(0x5e8, 0x1a4, 3, 0x93c, 1, NO_PAD_CTRL)
-#define MX35_PAD_CTS2__KPP_ROW_7				IOMUX_PAD(0x5e8, 0x1a4, 4, 0x98c, 0, NO_PAD_CTRL)
-#define MX35_PAD_CTS2__GPIO3_13					IOMUX_PAD(0x5e8, 0x1a4, 5, 0x8f8, 0, NO_PAD_CTRL)
-#define MX35_PAD_CTS2__AUDMUX_AUD5_RXFS				IOMUX_PAD(0x5e8, 0x1a4, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CTS2__UART3_TXD_MUX				IOMUX_PAD(0x5e8, 0x1a4, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_RTCK__ARM11P_TOP_RTCK				IOMUX_PAD(0x5ec, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_TCK__SJC_TCK					IOMUX_PAD(0x5f0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_TMS__SJC_TMS					IOMUX_PAD(0x5f4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_TDI__SJC_TDI					IOMUX_PAD(0x5f8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_TDO__SJC_TDO					IOMUX_PAD(0x5fc, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_TRSTB__SJC_TRSTB				IOMUX_PAD(0x600, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_DE_B__SJC_DE_B					IOMUX_PAD(0x604, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SJC_MOD__SJC_MOD				IOMUX_PAD(0x608, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_USBOTG_PWR__USB_TOP_USBOTG_PWR			IOMUX_PAD(0x60c, 0x1a8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_USBOTG_PWR__USB_TOP_USBH2_PWR			IOMUX_PAD(0x60c, 0x1a8, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_USBOTG_PWR__GPIO3_14				IOMUX_PAD(0x60c, 0x1a8, 5, 0x8fc, 0, NO_PAD_CTRL)
-
-#define MX35_PAD_USBOTG_OC__USB_TOP_USBOTG_OC			IOMUX_PAD(0x610, 0x1ac, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_USBOTG_OC__USB_TOP_USBH2_OC			IOMUX_PAD(0x610, 0x1ac, 1, 0x9f4, 1, NO_PAD_CTRL)
-#define MX35_PAD_USBOTG_OC__GPIO3_15				IOMUX_PAD(0x610, 0x1ac, 5, 0x900, 0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD0__IPU_DISPB_DAT_0				IOMUX_PAD(0x614, 0x1b0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD0__GPIO2_0					IOMUX_PAD(0x614, 0x1b0, 5, 0x868, 1, NO_PAD_CTRL)
-#define MX35_PAD_LD0__SDMA_SDMA_DEBUG_PC_0			IOMUX_PAD(0x614, 0x1b0, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD1__IPU_DISPB_DAT_1				IOMUX_PAD(0x618, 0x1b4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD1__GPIO2_1					IOMUX_PAD(0x618, 0x1b4, 5, 0x894, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD1__SDMA_SDMA_DEBUG_PC_1			IOMUX_PAD(0x618, 0x1b4, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD2__IPU_DISPB_DAT_2				IOMUX_PAD(0x61c, 0x1b8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD2__GPIO2_2					IOMUX_PAD(0x61c, 0x1b8, 5, 0x8c0, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD2__SDMA_SDMA_DEBUG_PC_2			IOMUX_PAD(0x61c, 0x1b8, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD3__IPU_DISPB_DAT_3				IOMUX_PAD(0x620, 0x1bc, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD3__GPIO2_3					IOMUX_PAD(0x620, 0x1bc, 5, 0x8cc, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD3__SDMA_SDMA_DEBUG_PC_3			IOMUX_PAD(0x620, 0x1bc, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD4__IPU_DISPB_DAT_4				IOMUX_PAD(0x624, 0x1c0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD4__GPIO2_4					IOMUX_PAD(0x624, 0x1c0, 5, 0x8d0, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD4__SDMA_SDMA_DEBUG_PC_4			IOMUX_PAD(0x624, 0x1c0, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD5__IPU_DISPB_DAT_5				IOMUX_PAD(0x628, 0x1c4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD5__GPIO2_5					IOMUX_PAD(0x628, 0x1c4, 5, 0x8d4, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD5__SDMA_SDMA_DEBUG_PC_5			IOMUX_PAD(0x628, 0x1c4, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD6__IPU_DISPB_DAT_6				IOMUX_PAD(0x62c, 0x1c8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD6__GPIO2_6					IOMUX_PAD(0x62c, 0x1c8, 5, 0x8d8, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD6__SDMA_SDMA_DEBUG_PC_6			IOMUX_PAD(0x62c, 0x1c8, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD7__IPU_DISPB_DAT_7				IOMUX_PAD(0x630, 0x1cc, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD7__GPIO2_7					IOMUX_PAD(0x630, 0x1cc, 5, 0x8dc, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD7__SDMA_SDMA_DEBUG_PC_7			IOMUX_PAD(0x630, 0x1cc, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD8__IPU_DISPB_DAT_8				IOMUX_PAD(0x634, 0x1d0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD8__GPIO2_8					IOMUX_PAD(0x634, 0x1d0, 5, 0x8e0, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD8__SDMA_SDMA_DEBUG_PC_8			IOMUX_PAD(0x634, 0x1d0, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD9__IPU_DISPB_DAT_9				IOMUX_PAD(0x638, 0x1d4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD9__GPIO2_9					IOMUX_PAD(0x638, 0x1d4, 5, 0x8e4, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD9__SDMA_SDMA_DEBUG_PC_9			IOMUX_PAD(0x638, 0x1d4, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD10__IPU_DISPB_DAT_10				IOMUX_PAD(0x63c, 0x1d8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD10__GPIO2_10					IOMUX_PAD(0x63c, 0x1d8, 5, 0x86c, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD10__SDMA_SDMA_DEBUG_PC_10			IOMUX_PAD(0x63c, 0x1d8, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD11__IPU_DISPB_DAT_11				IOMUX_PAD(0x640, 0x1dc, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD11__GPIO2_11					IOMUX_PAD(0x640, 0x1dc, 5, 0x870, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD11__SDMA_SDMA_DEBUG_PC_11			IOMUX_PAD(0x640, 0x1dc, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD11__ARM11P_TOP_TRACE_4			IOMUX_PAD(0x640, 0x1dc, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD12__IPU_DISPB_DAT_12				IOMUX_PAD(0x644, 0x1e0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD12__GPIO2_12					IOMUX_PAD(0x644, 0x1e0, 5, 0x874, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD12__SDMA_SDMA_DEBUG_PC_12			IOMUX_PAD(0x644, 0x1e0, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD12__ARM11P_TOP_TRACE_5			IOMUX_PAD(0x644, 0x1e0, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD13__IPU_DISPB_DAT_13				IOMUX_PAD(0x648, 0x1e4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD13__GPIO2_13					IOMUX_PAD(0x648, 0x1e4, 5, 0x878, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD13__SDMA_SDMA_DEBUG_PC_13			IOMUX_PAD(0x648, 0x1e4, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD13__ARM11P_TOP_TRACE_6			IOMUX_PAD(0x648, 0x1e4, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD14__IPU_DISPB_DAT_14				IOMUX_PAD(0x64c, 0x1e8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD14__GPIO2_14					IOMUX_PAD(0x64c, 0x1e8, 5, 0x87c, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD14__SDMA_SDMA_DEBUG_EVENT_CHANNEL_0		IOMUX_PAD(0x64c, 0x1e8, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD14__ARM11P_TOP_TRACE_7			IOMUX_PAD(0x64c, 0x1e8, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD15__IPU_DISPB_DAT_15				IOMUX_PAD(0x650, 0x1ec, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD15__GPIO2_15					IOMUX_PAD(0x650, 0x1ec, 5, 0x880, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD15__SDMA_SDMA_DEBUG_EVENT_CHANNEL_1		IOMUX_PAD(0x650, 0x1ec, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD15__ARM11P_TOP_TRACE_8			IOMUX_PAD(0x650, 0x1ec, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD16__IPU_DISPB_DAT_16				IOMUX_PAD(0x654, 0x1f0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD16__IPU_DISPB_D12_VSYNC			IOMUX_PAD(0x654, 0x1f0, 2, 0x928, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD16__GPIO2_16					IOMUX_PAD(0x654, 0x1f0, 5, 0x884, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD16__SDMA_SDMA_DEBUG_EVENT_CHANNEL_2		IOMUX_PAD(0x654, 0x1f0, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD16__ARM11P_TOP_TRACE_9			IOMUX_PAD(0x654, 0x1f0, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD17__IPU_DISPB_DAT_17				IOMUX_PAD(0x658, 0x1f4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD17__IPU_DISPB_CS2				IOMUX_PAD(0x658, 0x1f4, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD17__GPIO2_17					IOMUX_PAD(0x658, 0x1f4, 5, 0x888, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD17__SDMA_SDMA_DEBUG_EVENT_CHANNEL_3		IOMUX_PAD(0x658, 0x1f4, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD17__ARM11P_TOP_TRACE_10			IOMUX_PAD(0x658, 0x1f4, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD18__IPU_DISPB_DAT_18				IOMUX_PAD(0x65c, 0x1f8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD18__IPU_DISPB_D0_VSYNC			IOMUX_PAD(0x65c, 0x1f8, 1, 0x924, 1, NO_PAD_CTRL)
-#define MX35_PAD_LD18__IPU_DISPB_D12_VSYNC			IOMUX_PAD(0x65c, 0x1f8, 2, 0x928, 1, NO_PAD_CTRL)
-#define MX35_PAD_LD18__ESDHC3_CMD				IOMUX_PAD(0x65c, 0x1f8, 3, 0x818, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD18__USB_TOP_USBOTG_DATA_3			IOMUX_PAD(0x65c, 0x1f8, 4, 0x9b0, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD18__GPIO3_24					IOMUX_PAD(0x65c, 0x1f8, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD18__SDMA_SDMA_DEBUG_EVENT_CHANNEL_4		IOMUX_PAD(0x65c, 0x1f8, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD18__ARM11P_TOP_TRACE_11			IOMUX_PAD(0x65c, 0x1f8, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD19__IPU_DISPB_DAT_19				IOMUX_PAD(0x660, 0x1fc, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD19__IPU_DISPB_BCLK				IOMUX_PAD(0x660, 0x1fc, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD19__IPU_DISPB_CS1				IOMUX_PAD(0x660, 0x1fc, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD19__ESDHC3_CLK				IOMUX_PAD(0x660, 0x1fc, 3, 0x814, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD19__USB_TOP_USBOTG_DIR			IOMUX_PAD(0x660, 0x1fc, 4, 0x9c4, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD19__GPIO3_25					IOMUX_PAD(0x660, 0x1fc, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD19__SDMA_SDMA_DEBUG_EVENT_CHANNEL_5		IOMUX_PAD(0x660, 0x1fc, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD19__ARM11P_TOP_TRACE_12			IOMUX_PAD(0x660, 0x1fc, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD20__IPU_DISPB_DAT_20				IOMUX_PAD(0x664, 0x200, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD20__IPU_DISPB_CS0				IOMUX_PAD(0x664, 0x200, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD20__IPU_DISPB_SD_CLK				IOMUX_PAD(0x664, 0x200, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD20__ESDHC3_DAT0				IOMUX_PAD(0x664, 0x200, 3, 0x81c, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD20__GPIO3_26					IOMUX_PAD(0x664, 0x200, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD20__SDMA_SDMA_DEBUG_CORE_STATUS_3		IOMUX_PAD(0x664, 0x200, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD20__ARM11P_TOP_TRACE_13			IOMUX_PAD(0x664, 0x200, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD21__IPU_DISPB_DAT_21				IOMUX_PAD(0x668, 0x204, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD21__IPU_DISPB_PAR_RS				IOMUX_PAD(0x668, 0x204, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD21__IPU_DISPB_SER_RS				IOMUX_PAD(0x668, 0x204, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD21__ESDHC3_DAT1				IOMUX_PAD(0x668, 0x204, 3, 0x820, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD21__USB_TOP_USBOTG_STP			IOMUX_PAD(0x668, 0x204, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD21__GPIO3_27					IOMUX_PAD(0x668, 0x204, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD21__SDMA_DEBUG_EVENT_CHANNEL_SEL		IOMUX_PAD(0x668, 0x204, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD21__ARM11P_TOP_TRACE_14			IOMUX_PAD(0x668, 0x204, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD22__IPU_DISPB_DAT_22				IOMUX_PAD(0x66c, 0x208, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD22__IPU_DISPB_WR				IOMUX_PAD(0x66c, 0x208, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD22__IPU_DISPB_SD_D_I				IOMUX_PAD(0x66c, 0x208, 2, 0x92c, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD22__ESDHC3_DAT2				IOMUX_PAD(0x66c, 0x208, 3, 0x824, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD22__USB_TOP_USBOTG_NXT			IOMUX_PAD(0x66c, 0x208, 4, 0x9c8, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD22__GPIO3_28					IOMUX_PAD(0x66c, 0x208, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD22__SDMA_DEBUG_BUS_ERROR			IOMUX_PAD(0x66c, 0x208, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD22__ARM11P_TOP_TRCTL				IOMUX_PAD(0x66c, 0x208, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_LD23__IPU_DISPB_DAT_23				IOMUX_PAD(0x670, 0x20c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD23__IPU_DISPB_RD				IOMUX_PAD(0x670, 0x20c, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD23__IPU_DISPB_SD_D_IO			IOMUX_PAD(0x670, 0x20c, 2, 0x92c, 1, NO_PAD_CTRL)
-#define MX35_PAD_LD23__ESDHC3_DAT3				IOMUX_PAD(0x670, 0x20c, 3, 0x828, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD23__USB_TOP_USBOTG_DATA_7			IOMUX_PAD(0x670, 0x20c, 4, 0x9c0, 0, NO_PAD_CTRL)
-#define MX35_PAD_LD23__GPIO3_29					IOMUX_PAD(0x670, 0x20c, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD23__SDMA_DEBUG_MATCHED_DMBUS			IOMUX_PAD(0x670, 0x20c, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_LD23__ARM11P_TOP_TRCLK				IOMUX_PAD(0x670, 0x20c, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D3_HSYNC__IPU_DISPB_D3_HSYNC			IOMUX_PAD(0x674, 0x210, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_HSYNC__IPU_DISPB_SD_D_IO			IOMUX_PAD(0x674, 0x210, 2, 0x92c, 2, NO_PAD_CTRL)
-#define MX35_PAD_D3_HSYNC__GPIO3_30				IOMUX_PAD(0x674, 0x210, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_HSYNC__SDMA_DEBUG_RTBUFFER_WRITE		IOMUX_PAD(0x674, 0x210, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_HSYNC__ARM11P_TOP_TRACE_15			IOMUX_PAD(0x674, 0x210, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D3_FPSHIFT__IPU_DISPB_D3_CLK			IOMUX_PAD(0x678, 0x214, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_FPSHIFT__IPU_DISPB_SD_CLK			IOMUX_PAD(0x678, 0x214, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_FPSHIFT__GPIO3_31				IOMUX_PAD(0x678, 0x214, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_FPSHIFT__SDMA_SDMA_DEBUG_CORE_STATUS_0	IOMUX_PAD(0x678, 0x214, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_FPSHIFT__ARM11P_TOP_TRACE_16		IOMUX_PAD(0x678, 0x214, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D3_DRDY__IPU_DISPB_D3_DRDY			IOMUX_PAD(0x67c, 0x218, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_DRDY__IPU_DISPB_SD_D_O			IOMUX_PAD(0x67c, 0x218, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_DRDY__GPIO1_0				IOMUX_PAD(0x67c, 0x218, 5, 0x82c, 2, NO_PAD_CTRL)
-#define MX35_PAD_D3_DRDY__SDMA_SDMA_DEBUG_CORE_STATUS_1		IOMUX_PAD(0x67c, 0x218, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_DRDY__ARM11P_TOP_TRACE_17			IOMUX_PAD(0x67c, 0x218, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_CONTRAST__IPU_DISPB_CONTR			IOMUX_PAD(0x680, 0x21c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CONTRAST__GPIO1_1				IOMUX_PAD(0x680, 0x21c, 5, 0x838, 2, NO_PAD_CTRL)
-#define MX35_PAD_CONTRAST__SDMA_SDMA_DEBUG_CORE_STATUS_2	IOMUX_PAD(0x680, 0x21c, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_CONTRAST__ARM11P_TOP_TRACE_18			IOMUX_PAD(0x680, 0x21c, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D3_VSYNC__IPU_DISPB_D3_VSYNC			IOMUX_PAD(0x684, 0x220, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_VSYNC__IPU_DISPB_CS1			IOMUX_PAD(0x684, 0x220, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_VSYNC__GPIO1_2				IOMUX_PAD(0x684, 0x220, 5, 0x848, 1, NO_PAD_CTRL)
-#define MX35_PAD_D3_VSYNC__SDMA_DEBUG_YIELD			IOMUX_PAD(0x684, 0x220, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_VSYNC__ARM11P_TOP_TRACE_19			IOMUX_PAD(0x684, 0x220, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D3_REV__IPU_DISPB_D3_REV			IOMUX_PAD(0x688, 0x224, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_REV__IPU_DISPB_SER_RS			IOMUX_PAD(0x688, 0x224, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_REV__GPIO1_3				IOMUX_PAD(0x688, 0x224, 5, 0x84c, 1, NO_PAD_CTRL)
-#define MX35_PAD_D3_REV__SDMA_DEBUG_BUS_RWB			IOMUX_PAD(0x688, 0x224, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_REV__ARM11P_TOP_TRACE_20			IOMUX_PAD(0x688, 0x224, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D3_CLS__IPU_DISPB_D3_CLS			IOMUX_PAD(0x68c, 0x228, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_CLS__IPU_DISPB_CS2				IOMUX_PAD(0x68c, 0x228, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_CLS__GPIO1_4				IOMUX_PAD(0x68c, 0x228, 5, 0x850, 2, NO_PAD_CTRL)
-#define MX35_PAD_D3_CLS__SDMA_DEBUG_BUS_DEVICE_0		IOMUX_PAD(0x68c, 0x228, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_CLS__ARM11P_TOP_TRACE_21			IOMUX_PAD(0x68c, 0x228, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_D3_SPL__IPU_DISPB_D3_SPL			IOMUX_PAD(0x690, 0x22c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_SPL__IPU_DISPB_D12_VSYNC			IOMUX_PAD(0x690, 0x22c, 2, 0x928, 2, NO_PAD_CTRL)
-#define MX35_PAD_D3_SPL__GPIO1_5				IOMUX_PAD(0x690, 0x22c, 5, 0x854, 2, NO_PAD_CTRL)
-#define MX35_PAD_D3_SPL__SDMA_DEBUG_BUS_DEVICE_1		IOMUX_PAD(0x690, 0x22c, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_D3_SPL__ARM11P_TOP_TRACE_22			IOMUX_PAD(0x690, 0x22c, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD1_CMD__ESDHC1_CMD				IOMUX_PAD(0x694, 0x230, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_CMD__MSHC_SCLK				IOMUX_PAD(0x694, 0x230, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_CMD__IPU_DISPB_D0_VSYNC			IOMUX_PAD(0x694, 0x230, 3, 0x924, 2, NO_PAD_CTRL)
-#define MX35_PAD_SD1_CMD__USB_TOP_USBOTG_DATA_4			IOMUX_PAD(0x694, 0x230, 4, 0x9b4, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_CMD__GPIO1_6				IOMUX_PAD(0x694, 0x230, 5, 0x858, 2, NO_PAD_CTRL)
-#define MX35_PAD_SD1_CMD__ARM11P_TOP_TRCTL			IOMUX_PAD(0x694, 0x230, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD1_CLK__ESDHC1_CLK				IOMUX_PAD(0x698, 0x234, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_CLK__MSHC_BS				IOMUX_PAD(0x698, 0x234, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_CLK__IPU_DISPB_BCLK			IOMUX_PAD(0x698, 0x234, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_CLK__USB_TOP_USBOTG_DATA_5			IOMUX_PAD(0x698, 0x234, 4, 0x9b8, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_CLK__GPIO1_7				IOMUX_PAD(0x698, 0x234, 5, 0x85c, 2, NO_PAD_CTRL)
-#define MX35_PAD_SD1_CLK__ARM11P_TOP_TRCLK			IOMUX_PAD(0x698, 0x234, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD1_DATA0__ESDHC1_DAT0				IOMUX_PAD(0x69c, 0x238, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA0__MSHC_DATA_0				IOMUX_PAD(0x69c, 0x238, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA0__IPU_DISPB_CS0			IOMUX_PAD(0x69c, 0x238, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA0__USB_TOP_USBOTG_DATA_6		IOMUX_PAD(0x69c, 0x238, 4, 0x9bc, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA0__GPIO1_8				IOMUX_PAD(0x69c, 0x238, 5, 0x860, 2, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA0__ARM11P_TOP_TRACE_23			IOMUX_PAD(0x69c, 0x238, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD1_DATA1__ESDHC1_DAT1				IOMUX_PAD(0x6a0, 0x23c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA1__MSHC_DATA_1				IOMUX_PAD(0x6a0, 0x23c, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA1__IPU_DISPB_PAR_RS			IOMUX_PAD(0x6a0, 0x23c, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA1__USB_TOP_USBOTG_DATA_0		IOMUX_PAD(0x6a0, 0x23c, 4, 0x9a4, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA1__GPIO1_9				IOMUX_PAD(0x6a0, 0x23c, 5, 0x864, 1, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA1__ARM11P_TOP_TRACE_24			IOMUX_PAD(0x6a0, 0x23c, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD1_DATA2__ESDHC1_DAT2				IOMUX_PAD(0x6a4, 0x240, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA2__MSHC_DATA_2				IOMUX_PAD(0x6a4, 0x240, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA2__IPU_DISPB_WR			IOMUX_PAD(0x6a4, 0x240, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA2__USB_TOP_USBOTG_DATA_1		IOMUX_PAD(0x6a4, 0x240, 4, 0x9a8, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA2__GPIO1_10				IOMUX_PAD(0x6a4, 0x240, 5, 0x830, 1, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA2__ARM11P_TOP_TRACE_25			IOMUX_PAD(0x6a4, 0x240, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD1_DATA3__ESDHC1_DAT3				IOMUX_PAD(0x6a8, 0x244, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA3__MSHC_DATA_3				IOMUX_PAD(0x6a8, 0x244, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA3__IPU_DISPB_RD			IOMUX_PAD(0x6a8, 0x244, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA3__USB_TOP_USBOTG_DATA_2		IOMUX_PAD(0x6a8, 0x244, 4, 0x9ac, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA3__GPIO1_11				IOMUX_PAD(0x6a8, 0x244, 5, 0x834, 1, NO_PAD_CTRL)
-#define MX35_PAD_SD1_DATA3__ARM11P_TOP_TRACE_26			IOMUX_PAD(0x6a8, 0x244, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD2_CMD__ESDHC2_CMD				IOMUX_PAD(0x6ac, 0x248, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_CMD__I2C3_SCL				IOMUX_PAD(0x6ac, 0x248, 1, 0x91c, 2, NO_PAD_CTRL)
-#define MX35_PAD_SD2_CMD__ESDHC1_DAT4				IOMUX_PAD(0x6ac, 0x248, 2, 0x804, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_CMD__IPU_CSI_D_2				IOMUX_PAD(0x6ac, 0x248, 3, 0x938, 2, NO_PAD_CTRL)
-#define MX35_PAD_SD2_CMD__USB_TOP_USBH2_DATA_4			IOMUX_PAD(0x6ac, 0x248, 4, 0x9dc, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_CMD__GPIO2_0				IOMUX_PAD(0x6ac, 0x248, 5, 0x868, 2, NO_PAD_CTRL)
-#define MX35_PAD_SD2_CMD__SPDIF_SPDIF_OUT1			IOMUX_PAD(0x6ac, 0x248, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_CMD__IPU_DISPB_D12_VSYNC			IOMUX_PAD(0x6ac, 0x248, 7, 0x928, 3, NO_PAD_CTRL)
-
-#define MX35_PAD_SD2_CLK__ESDHC2_CLK				IOMUX_PAD(0x6b0, 0x24c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_CLK__I2C3_SDA				IOMUX_PAD(0x6b0, 0x24c, 1, 0x920, 2, NO_PAD_CTRL)
-#define MX35_PAD_SD2_CLK__ESDHC1_DAT5				IOMUX_PAD(0x6b0, 0x24c, 2, 0x808, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_CLK__IPU_CSI_D_3				IOMUX_PAD(0x6b0, 0x24c, 3, 0x93c, 2, NO_PAD_CTRL)
-#define MX35_PAD_SD2_CLK__USB_TOP_USBH2_DATA_5			IOMUX_PAD(0x6b0, 0x24c, 4, 0x9e0, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_CLK__GPIO2_1				IOMUX_PAD(0x6b0, 0x24c, 5, 0x894, 1, NO_PAD_CTRL)
-#define MX35_PAD_SD2_CLK__SPDIF_SPDIF_IN1			IOMUX_PAD(0x6b0, 0x24c, 6, 0x998, 2, NO_PAD_CTRL)
-#define MX35_PAD_SD2_CLK__IPU_DISPB_CS2				IOMUX_PAD(0x6b0, 0x24c, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_SD2_DATA0__ESDHC2_DAT0				IOMUX_PAD(0x6b4, 0x250, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA0__UART3_RXD_MUX			IOMUX_PAD(0x6b4, 0x250, 1, 0x9a0, 1, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA0__ESDHC1_DAT6				IOMUX_PAD(0x6b4, 0x250, 2, 0x80c, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA0__IPU_CSI_D_4				IOMUX_PAD(0x6b4, 0x250, 3, 0x940, 1, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA0__USB_TOP_USBH2_DATA_6		IOMUX_PAD(0x6b4, 0x250, 4, 0x9e4, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA0__GPIO2_2				IOMUX_PAD(0x6b4, 0x250, 5, 0x8c0, 1, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA0__SPDIF_SPDIF_EXTCLK			IOMUX_PAD(0x6b4, 0x250, 6, 0x994, 3, NO_PAD_CTRL)
-
-#define MX35_PAD_SD2_DATA1__ESDHC2_DAT1				IOMUX_PAD(0x6b8, 0x254, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA1__UART3_TXD_MUX			IOMUX_PAD(0x6b8, 0x254, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA1__ESDHC1_DAT7				IOMUX_PAD(0x6b8, 0x254, 2, 0x810, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA1__IPU_CSI_D_5				IOMUX_PAD(0x6b8, 0x254, 3, 0x944, 1, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA1__USB_TOP_USBH2_DATA_0		IOMUX_PAD(0x6b8, 0x254, 4, 0x9cc, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA1__GPIO2_3				IOMUX_PAD(0x6b8, 0x254, 5, 0x8cc, 1, NO_PAD_CTRL)
-
-#define MX35_PAD_SD2_DATA2__ESDHC2_DAT2				IOMUX_PAD(0x6bc, 0x258, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA2__UART3_RTS				IOMUX_PAD(0x6bc, 0x258, 1, 0x99c, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA2__CAN1_RXCAN				IOMUX_PAD(0x6bc, 0x258, 2, 0x7c8, 1, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA2__IPU_CSI_D_6				IOMUX_PAD(0x6bc, 0x258, 3, 0x948, 1, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA2__USB_TOP_USBH2_DATA_1		IOMUX_PAD(0x6bc, 0x258, 4, 0x9d0, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA2__GPIO2_4				IOMUX_PAD(0x6bc, 0x258, 5, 0x8d0, 1, NO_PAD_CTRL)
-
-#define MX35_PAD_SD2_DATA3__ESDHC2_DAT3				IOMUX_PAD(0x6c0, 0x25c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA3__UART3_CTS				IOMUX_PAD(0x6c0, 0x25c, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA3__CAN1_TXCAN				IOMUX_PAD(0x6c0, 0x25c, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA3__IPU_CSI_D_7				IOMUX_PAD(0x6c0, 0x25c, 3, 0x94c, 1, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA3__USB_TOP_USBH2_DATA_2		IOMUX_PAD(0x6c0, 0x25c, 4, 0x9d4, 0, NO_PAD_CTRL)
-#define MX35_PAD_SD2_DATA3__GPIO2_5				IOMUX_PAD(0x6c0, 0x25c, 5, 0x8d4, 1, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_CS0__ATA_CS0				IOMUX_PAD(0x6c4, 0x260, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_CS0__CSPI1_SS3				IOMUX_PAD(0x6c4, 0x260, 1, 0x7dc, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_CS0__IPU_DISPB_CS1				IOMUX_PAD(0x6c4, 0x260, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_CS0__GPIO2_6				IOMUX_PAD(0x6c4, 0x260, 5, 0x8d8, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_CS0__IPU_DIAGB_0				IOMUX_PAD(0x6c4, 0x260, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_CS0__ARM11P_TOP_MAX1_HMASTER_0		IOMUX_PAD(0x6c4, 0x260, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_CS1__ATA_CS1				IOMUX_PAD(0x6c8, 0x264, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_CS1__IPU_DISPB_CS2				IOMUX_PAD(0x6c8, 0x264, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_CS1__CSPI2_SS0				IOMUX_PAD(0x6c8, 0x264, 4, 0x7f0, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_CS1__GPIO2_7				IOMUX_PAD(0x6c8, 0x264, 5, 0x8dc, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_CS1__IPU_DIAGB_1				IOMUX_PAD(0x6c8, 0x264, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_CS1__ARM11P_TOP_MAX1_HMASTER_1		IOMUX_PAD(0x6c8, 0x264, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DIOR__ATA_DIOR				IOMUX_PAD(0x6cc, 0x268, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DIOR__ESDHC3_DAT0				IOMUX_PAD(0x6cc, 0x268, 1, 0x81c, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DIOR__USB_TOP_USBOTG_DIR			IOMUX_PAD(0x6cc, 0x268, 2, 0x9c4, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DIOR__IPU_DISPB_BE0			IOMUX_PAD(0x6cc, 0x268, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DIOR__CSPI2_SS1				IOMUX_PAD(0x6cc, 0x268, 4, 0x7f4, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DIOR__GPIO2_8				IOMUX_PAD(0x6cc, 0x268, 5, 0x8e0, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DIOR__IPU_DIAGB_2				IOMUX_PAD(0x6cc, 0x268, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DIOR__ARM11P_TOP_MAX1_HMASTER_2		IOMUX_PAD(0x6cc, 0x268, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DIOW__ATA_DIOW				IOMUX_PAD(0x6d0, 0x26c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DIOW__ESDHC3_DAT1				IOMUX_PAD(0x6d0, 0x26c, 1, 0x820, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DIOW__USB_TOP_USBOTG_STP			IOMUX_PAD(0x6d0, 0x26c, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DIOW__IPU_DISPB_BE1			IOMUX_PAD(0x6d0, 0x26c, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DIOW__CSPI2_MOSI				IOMUX_PAD(0x6d0, 0x26c, 4, 0x7ec, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DIOW__GPIO2_9				IOMUX_PAD(0x6d0, 0x26c, 5, 0x8e4, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DIOW__IPU_DIAGB_3				IOMUX_PAD(0x6d0, 0x26c, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DIOW__ARM11P_TOP_MAX1_HMASTER_3		IOMUX_PAD(0x6d0, 0x26c, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DMACK__ATA_DMACK				IOMUX_PAD(0x6d4, 0x270, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DMACK__ESDHC3_DAT2				IOMUX_PAD(0x6d4, 0x270, 1, 0x824, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DMACK__USB_TOP_USBOTG_NXT			IOMUX_PAD(0x6d4, 0x270, 2, 0x9c8, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DMACK__CSPI2_MISO				IOMUX_PAD(0x6d4, 0x270, 4, 0x7e8, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DMACK__GPIO2_10				IOMUX_PAD(0x6d4, 0x270, 5, 0x86c, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DMACK__IPU_DIAGB_4				IOMUX_PAD(0x6d4, 0x270, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DMACK__ARM11P_TOP_MAX0_HMASTER_0		IOMUX_PAD(0x6d4, 0x270, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_RESET_B__ATA_RESET_B			IOMUX_PAD(0x6d8, 0x274, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_RESET_B__ESDHC3_DAT3			IOMUX_PAD(0x6d8, 0x274, 1, 0x828, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_RESET_B__USB_TOP_USBOTG_DATA_0		IOMUX_PAD(0x6d8, 0x274, 2, 0x9a4, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_RESET_B__IPU_DISPB_SD_D_O			IOMUX_PAD(0x6d8, 0x274, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_RESET_B__CSPI2_RDY				IOMUX_PAD(0x6d8, 0x274, 4, 0x7e4, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_RESET_B__GPIO2_11				IOMUX_PAD(0x6d8, 0x274, 5, 0x870, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_RESET_B__IPU_DIAGB_5			IOMUX_PAD(0x6d8, 0x274, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_RESET_B__ARM11P_TOP_MAX0_HMASTER_1		IOMUX_PAD(0x6d8, 0x274, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_IORDY__ATA_IORDY				IOMUX_PAD(0x6dc, 0x278, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_IORDY__ESDHC3_DAT4				IOMUX_PAD(0x6dc, 0x278, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_IORDY__USB_TOP_USBOTG_DATA_1		IOMUX_PAD(0x6dc, 0x278, 2, 0x9a8, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_IORDY__IPU_DISPB_SD_D_IO			IOMUX_PAD(0x6dc, 0x278, 3, 0x92c, 3, NO_PAD_CTRL)
-#define MX35_PAD_ATA_IORDY__ESDHC2_DAT4				IOMUX_PAD(0x6dc, 0x278, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_IORDY__GPIO2_12				IOMUX_PAD(0x6dc, 0x278, 5, 0x874, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_IORDY__IPU_DIAGB_6				IOMUX_PAD(0x6dc, 0x278, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_IORDY__ARM11P_TOP_MAX0_HMASTER_2		IOMUX_PAD(0x6dc, 0x278, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DATA0__ATA_DATA_0				IOMUX_PAD(0x6e0, 0x27c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA0__ESDHC3_DAT5				IOMUX_PAD(0x6e0, 0x27c, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA0__USB_TOP_USBOTG_DATA_2		IOMUX_PAD(0x6e0, 0x27c, 2, 0x9ac, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA0__IPU_DISPB_D12_VSYNC			IOMUX_PAD(0x6e0, 0x27c, 3, 0x928, 4, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA0__ESDHC2_DAT5				IOMUX_PAD(0x6e0, 0x27c, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA0__GPIO2_13				IOMUX_PAD(0x6e0, 0x27c, 5, 0x878, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA0__IPU_DIAGB_7				IOMUX_PAD(0x6e0, 0x27c, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA0__ARM11P_TOP_MAX0_HMASTER_3		IOMUX_PAD(0x6e0, 0x27c, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DATA1__ATA_DATA_1				IOMUX_PAD(0x6e4, 0x280, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA1__ESDHC3_DAT6				IOMUX_PAD(0x6e4, 0x280, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA1__USB_TOP_USBOTG_DATA_3		IOMUX_PAD(0x6e4, 0x280, 2, 0x9b0, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA1__IPU_DISPB_SD_CLK			IOMUX_PAD(0x6e4, 0x280, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA1__ESDHC2_DAT6				IOMUX_PAD(0x6e4, 0x280, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA1__GPIO2_14				IOMUX_PAD(0x6e4, 0x280, 5, 0x87c, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA1__IPU_DIAGB_8				IOMUX_PAD(0x6e4, 0x280, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA1__ARM11P_TOP_TRACE_27			IOMUX_PAD(0x6e4, 0x280, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DATA2__ATA_DATA_2				IOMUX_PAD(0x6e8, 0x284, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA2__ESDHC3_DAT7				IOMUX_PAD(0x6e8, 0x284, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA2__USB_TOP_USBOTG_DATA_4		IOMUX_PAD(0x6e8, 0x284, 2, 0x9b4, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA2__IPU_DISPB_SER_RS			IOMUX_PAD(0x6e8, 0x284, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA2__ESDHC2_DAT7				IOMUX_PAD(0x6e8, 0x284, 4, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA2__GPIO2_15				IOMUX_PAD(0x6e8, 0x284, 5, 0x880, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA2__IPU_DIAGB_9				IOMUX_PAD(0x6e8, 0x284, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA2__ARM11P_TOP_TRACE_28			IOMUX_PAD(0x6e8, 0x284, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DATA3__ATA_DATA_3				IOMUX_PAD(0x6ec, 0x288, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA3__ESDHC3_CLK				IOMUX_PAD(0x6ec, 0x288, 1, 0x814, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA3__USB_TOP_USBOTG_DATA_5		IOMUX_PAD(0x6ec, 0x288, 2, 0x9b8, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA3__CSPI2_SCLK				IOMUX_PAD(0x6ec, 0x288, 4, 0x7e0, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA3__GPIO2_16				IOMUX_PAD(0x6ec, 0x288, 5, 0x884, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA3__IPU_DIAGB_10			IOMUX_PAD(0x6ec, 0x288, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA3__ARM11P_TOP_TRACE_29			IOMUX_PAD(0x6ec, 0x288, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DATA4__ATA_DATA_4				IOMUX_PAD(0x6f0, 0x28c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA4__ESDHC3_CMD				IOMUX_PAD(0x6f0, 0x28c, 1, 0x818, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA4__USB_TOP_USBOTG_DATA_6		IOMUX_PAD(0x6f0, 0x28c, 2, 0x9bc, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA4__GPIO2_17				IOMUX_PAD(0x6f0, 0x28c, 5, 0x888, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA4__IPU_DIAGB_11			IOMUX_PAD(0x6f0, 0x28c, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA4__ARM11P_TOP_TRACE_30			IOMUX_PAD(0x6f0, 0x28c, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DATA5__ATA_DATA_5				IOMUX_PAD(0x6f4, 0x290, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA5__USB_TOP_USBOTG_DATA_7		IOMUX_PAD(0x6f4, 0x290, 2, 0x9c0, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA5__GPIO2_18				IOMUX_PAD(0x6f4, 0x290, 5, 0x88c, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA5__IPU_DIAGB_12			IOMUX_PAD(0x6f4, 0x290, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA5__ARM11P_TOP_TRACE_31			IOMUX_PAD(0x6f4, 0x290, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DATA6__ATA_DATA_6				IOMUX_PAD(0x6f8, 0x294, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA6__CAN1_TXCAN				IOMUX_PAD(0x6f8, 0x294, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA6__UART1_DTR				IOMUX_PAD(0x6f8, 0x294, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA6__AUDMUX_AUD6_TXD			IOMUX_PAD(0x6f8, 0x294, 3, 0x7b4, 0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA6__GPIO2_19				IOMUX_PAD(0x6f8, 0x294, 5, 0x890, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA6__IPU_DIAGB_13			IOMUX_PAD(0x6f8, 0x294, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DATA7__ATA_DATA_7				IOMUX_PAD(0x6fc, 0x298, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA7__CAN1_RXCAN				IOMUX_PAD(0x6fc, 0x298, 1, 0x7c8, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA7__UART1_DSR				IOMUX_PAD(0x6fc, 0x298, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA7__AUDMUX_AUD6_RXD			IOMUX_PAD(0x6fc, 0x298, 3, 0x7b0, 0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA7__GPIO2_20				IOMUX_PAD(0x6fc, 0x298, 5, 0x898, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA7__IPU_DIAGB_14			IOMUX_PAD(0x6fc, 0x298, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DATA8__ATA_DATA_8				IOMUX_PAD(0x700, 0x29c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA8__UART3_RTS				IOMUX_PAD(0x700, 0x29c, 1, 0x99c, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA8__UART1_RI				IOMUX_PAD(0x700, 0x29c, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA8__AUDMUX_AUD6_TXC			IOMUX_PAD(0x700, 0x29c, 3, 0x7c0, 0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA8__GPIO2_21				IOMUX_PAD(0x700, 0x29c, 5, 0x89c, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA8__IPU_DIAGB_15			IOMUX_PAD(0x700, 0x29c, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DATA9__ATA_DATA_9				IOMUX_PAD(0x704, 0x2a0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA9__UART3_CTS				IOMUX_PAD(0x704, 0x2a0, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA9__UART1_DCD				IOMUX_PAD(0x704, 0x2a0, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA9__AUDMUX_AUD6_TXFS			IOMUX_PAD(0x704, 0x2a0, 3, 0x7c4, 0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA9__GPIO2_22				IOMUX_PAD(0x704, 0x2a0, 5, 0x8a0, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA9__IPU_DIAGB_16			IOMUX_PAD(0x704, 0x2a0, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DATA10__ATA_DATA_10			IOMUX_PAD(0x708, 0x2a4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA10__UART3_RXD_MUX			IOMUX_PAD(0x708, 0x2a4, 1, 0x9a0, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA10__AUDMUX_AUD6_RXC			IOMUX_PAD(0x708, 0x2a4, 3, 0x7b8, 0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA10__GPIO2_23				IOMUX_PAD(0x708, 0x2a4, 5, 0x8a4, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA10__IPU_DIAGB_17			IOMUX_PAD(0x708, 0x2a4, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DATA11__ATA_DATA_11			IOMUX_PAD(0x70c, 0x2a8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA11__UART3_TXD_MUX			IOMUX_PAD(0x70c, 0x2a8, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA11__AUDMUX_AUD6_RXFS			IOMUX_PAD(0x70c, 0x2a8, 3, 0x7bc, 0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA11__GPIO2_24				IOMUX_PAD(0x70c, 0x2a8, 5, 0x8a8, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA11__IPU_DIAGB_18			IOMUX_PAD(0x70c, 0x2a8, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DATA12__ATA_DATA_12			IOMUX_PAD(0x710, 0x2ac, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA12__I2C3_SCL				IOMUX_PAD(0x710, 0x2ac, 1, 0x91c, 3, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA12__GPIO2_25				IOMUX_PAD(0x710, 0x2ac, 5, 0x8ac, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA12__IPU_DIAGB_19			IOMUX_PAD(0x710, 0x2ac, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DATA13__ATA_DATA_13			IOMUX_PAD(0x714, 0x2b0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA13__I2C3_SDA				IOMUX_PAD(0x714, 0x2b0, 1, 0x920, 3, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA13__GPIO2_26				IOMUX_PAD(0x714, 0x2b0, 5, 0x8b0, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA13__IPU_DIAGB_20			IOMUX_PAD(0x714, 0x2b0, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DATA14__ATA_DATA_14			IOMUX_PAD(0x718, 0x2b4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA14__IPU_CSI_D_0			IOMUX_PAD(0x718, 0x2b4, 1, 0x930, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA14__KPP_ROW_0				IOMUX_PAD(0x718, 0x2b4, 3, 0x970, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA14__GPIO2_27				IOMUX_PAD(0x718, 0x2b4, 5, 0x8b4, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA14__IPU_DIAGB_21			IOMUX_PAD(0x718, 0x2b4, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DATA15__ATA_DATA_15			IOMUX_PAD(0x71c, 0x2b8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA15__IPU_CSI_D_1			IOMUX_PAD(0x71c, 0x2b8, 1, 0x934, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA15__KPP_ROW_1				IOMUX_PAD(0x71c, 0x2b8, 3, 0x974, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA15__GPIO2_28				IOMUX_PAD(0x71c, 0x2b8, 5, 0x8b8, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA15__IPU_DIAGB_22			IOMUX_PAD(0x71c, 0x2b8, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_INTRQ__ATA_INTRQ				IOMUX_PAD(0x720, 0x2bc, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_INTRQ__IPU_CSI_D_2				IOMUX_PAD(0x720, 0x2bc, 1, 0x938, 3, NO_PAD_CTRL)
-#define MX35_PAD_ATA_INTRQ__KPP_ROW_2				IOMUX_PAD(0x720, 0x2bc, 3, 0x978, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_INTRQ__GPIO2_29				IOMUX_PAD(0x720, 0x2bc, 5, 0x8bc, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_INTRQ__IPU_DIAGB_23			IOMUX_PAD(0x720, 0x2bc, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_BUFF_EN__ATA_BUFFER_EN			IOMUX_PAD(0x724, 0x2c0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_BUFF_EN__IPU_CSI_D_3			IOMUX_PAD(0x724, 0x2c0, 1, 0x93c, 3, NO_PAD_CTRL)
-#define MX35_PAD_ATA_BUFF_EN__KPP_ROW_3				IOMUX_PAD(0x724, 0x2c0, 3, 0x97c, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_BUFF_EN__GPIO2_30				IOMUX_PAD(0x724, 0x2c0, 5, 0x8c4, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_BUFF_EN__IPU_DIAGB_24			IOMUX_PAD(0x724, 0x2c0, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DMARQ__ATA_DMARQ				IOMUX_PAD(0x728, 0x2c4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DMARQ__IPU_CSI_D_4				IOMUX_PAD(0x728, 0x2c4, 1, 0x940, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DMARQ__KPP_COL_0				IOMUX_PAD(0x728, 0x2c4, 3, 0x950, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DMARQ__GPIO2_31				IOMUX_PAD(0x728, 0x2c4, 5, 0x8c8, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DMARQ__IPU_DIAGB_25			IOMUX_PAD(0x728, 0x2c4, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DMARQ__ECT_CTI_TRIG_IN1_4			IOMUX_PAD(0x728, 0x2c4, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DA0__ATA_DA_0				IOMUX_PAD(0x72c, 0x2c8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DA0__IPU_CSI_D_5				IOMUX_PAD(0x72c, 0x2c8, 1, 0x944, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DA0__KPP_COL_1				IOMUX_PAD(0x72c, 0x2c8, 3, 0x954, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DA0__GPIO3_0				IOMUX_PAD(0x72c, 0x2c8, 5, 0x8e8, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DA0__IPU_DIAGB_26				IOMUX_PAD(0x72c, 0x2c8, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DA0__ECT_CTI_TRIG_IN1_5			IOMUX_PAD(0x72c, 0x2c8, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DA1__ATA_DA_1				IOMUX_PAD(0x730, 0x2cc, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DA1__IPU_CSI_D_6				IOMUX_PAD(0x730, 0x2cc, 1, 0x948, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DA1__KPP_COL_2				IOMUX_PAD(0x730, 0x2cc, 3, 0x958, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DA1__GPIO3_1				IOMUX_PAD(0x730, 0x2cc, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DA1__IPU_DIAGB_27				IOMUX_PAD(0x730, 0x2cc, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DA1__ECT_CTI_TRIG_IN1_6			IOMUX_PAD(0x730, 0x2cc, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_ATA_DA2__ATA_DA_2				IOMUX_PAD(0x734, 0x2d0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DA2__IPU_CSI_D_7				IOMUX_PAD(0x734, 0x2d0, 1, 0x94c, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DA2__KPP_COL_3				IOMUX_PAD(0x734, 0x2d0, 3, 0x95c, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DA2__GPIO3_2				IOMUX_PAD(0x734, 0x2d0, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DA2__IPU_DIAGB_28				IOMUX_PAD(0x734, 0x2d0, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DA2__ECT_CTI_TRIG_IN1_7			IOMUX_PAD(0x734, 0x2d0, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_MLB_CLK__MLB_MLBCLK				IOMUX_PAD(0x738, 0x2d4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_MLB_CLK__GPIO3_3				IOMUX_PAD(0x738, 0x2d4, 5, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_MLB_DAT__MLB_MLBDAT				IOMUX_PAD(0x73c, 0x2d8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_MLB_DAT__GPIO3_4				IOMUX_PAD(0x73c, 0x2d8, 5, 0x904, 1, NO_PAD_CTRL)
-
-#define MX35_PAD_MLB_SIG__MLB_MLBSIG				IOMUX_PAD(0x740, 0x2dc, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_MLB_SIG__GPIO3_5				IOMUX_PAD(0x740, 0x2dc, 5, 0x908, 1, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_TX_CLK__FEC_TX_CLK				IOMUX_PAD(0x744, 0x2e0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_CLK__ESDHC1_DAT4			IOMUX_PAD(0x744, 0x2e0, 1, 0x804, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_CLK__UART3_RXD_MUX			IOMUX_PAD(0x744, 0x2e0, 2, 0x9a0, 3, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_CLK__USB_TOP_USBH2_DIR			IOMUX_PAD(0x744, 0x2e0, 3, 0x9ec, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_CLK__CSPI2_MOSI				IOMUX_PAD(0x744, 0x2e0, 4, 0x7ec, 3, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_CLK__GPIO3_6				IOMUX_PAD(0x744, 0x2e0, 5, 0x90c, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_CLK__IPU_DISPB_D12_VSYNC		IOMUX_PAD(0x744, 0x2e0, 6, 0x928, 5, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_CLK__ARM11P_TOP_EVNTBUS_0		IOMUX_PAD(0x744, 0x2e0, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_RX_CLK__FEC_RX_CLK				IOMUX_PAD(0x748, 0x2e4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_CLK__ESDHC1_DAT5			IOMUX_PAD(0x748, 0x2e4, 1, 0x808, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_CLK__UART3_TXD_MUX			IOMUX_PAD(0x748, 0x2e4, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_CLK__USB_TOP_USBH2_STP			IOMUX_PAD(0x748, 0x2e4, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_CLK__CSPI2_MISO				IOMUX_PAD(0x748, 0x2e4, 4, 0x7e8, 3, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_CLK__GPIO3_7				IOMUX_PAD(0x748, 0x2e4, 5, 0x910, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_CLK__IPU_DISPB_SD_D_I			IOMUX_PAD(0x748, 0x2e4, 6, 0x92c, 4, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_CLK__ARM11P_TOP_EVNTBUS_1		IOMUX_PAD(0x748, 0x2e4, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_RX_DV__FEC_RX_DV				IOMUX_PAD(0x74c, 0x2e8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_DV__ESDHC1_DAT6				IOMUX_PAD(0x74c, 0x2e8, 1, 0x80c, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_DV__UART3_RTS				IOMUX_PAD(0x74c, 0x2e8, 2, 0x99c, 2, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_DV__USB_TOP_USBH2_NXT			IOMUX_PAD(0x74c, 0x2e8, 3, 0x9f0, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_DV__CSPI2_SCLK				IOMUX_PAD(0x74c, 0x2e8, 4, 0x7e0, 3, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_DV__GPIO3_8				IOMUX_PAD(0x74c, 0x2e8, 5, 0x914, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_DV__IPU_DISPB_SD_CLK			IOMUX_PAD(0x74c, 0x2e8, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_DV__ARM11P_TOP_EVNTBUS_2		IOMUX_PAD(0x74c, 0x2e8, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_COL__FEC_COL				IOMUX_PAD(0x750, 0x2ec, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_COL__ESDHC1_DAT7				IOMUX_PAD(0x750, 0x2ec, 1, 0x810, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_COL__UART3_CTS				IOMUX_PAD(0x750, 0x2ec, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_COL__USB_TOP_USBH2_DATA_0			IOMUX_PAD(0x750, 0x2ec, 3, 0x9cc, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_COL__CSPI2_RDY				IOMUX_PAD(0x750, 0x2ec, 4, 0x7e4, 3, NO_PAD_CTRL)
-#define MX35_PAD_FEC_COL__GPIO3_9				IOMUX_PAD(0x750, 0x2ec, 5, 0x918, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_COL__IPU_DISPB_SER_RS			IOMUX_PAD(0x750, 0x2ec, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_COL__ARM11P_TOP_EVNTBUS_3			IOMUX_PAD(0x750, 0x2ec, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_RDATA0__FEC_RDATA_0			IOMUX_PAD(0x754, 0x2f0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA0__PWM_PWMO				IOMUX_PAD(0x754, 0x2f0, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA0__UART3_DTR				IOMUX_PAD(0x754, 0x2f0, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA0__USB_TOP_USBH2_DATA_1		IOMUX_PAD(0x754, 0x2f0, 3, 0x9d0, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA0__CSPI2_SS0				IOMUX_PAD(0x754, 0x2f0, 4, 0x7f0, 2, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA0__GPIO3_10				IOMUX_PAD(0x754, 0x2f0, 5, 0x8ec, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA0__IPU_DISPB_CS1			IOMUX_PAD(0x754, 0x2f0, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA0__ARM11P_TOP_EVNTBUS_4		IOMUX_PAD(0x754, 0x2f0, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_TDATA0__FEC_TDATA_0			IOMUX_PAD(0x758, 0x2f4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA0__SPDIF_SPDIF_OUT1			IOMUX_PAD(0x758, 0x2f4, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA0__UART3_DSR				IOMUX_PAD(0x758, 0x2f4, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA0__USB_TOP_USBH2_DATA_2		IOMUX_PAD(0x758, 0x2f4, 3, 0x9d4, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA0__CSPI2_SS1				IOMUX_PAD(0x758, 0x2f4, 4, 0x7f4, 2, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA0__GPIO3_11				IOMUX_PAD(0x758, 0x2f4, 5, 0x8f0, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA0__IPU_DISPB_CS0			IOMUX_PAD(0x758, 0x2f4, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA0__ARM11P_TOP_EVNTBUS_5		IOMUX_PAD(0x758, 0x2f4, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_TX_EN__FEC_TX_EN				IOMUX_PAD(0x75c, 0x2f8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_EN__SPDIF_SPDIF_IN1			IOMUX_PAD(0x75c, 0x2f8, 1, 0x998, 3, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_EN__UART3_RI				IOMUX_PAD(0x75c, 0x2f8, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_EN__USB_TOP_USBH2_DATA_3		IOMUX_PAD(0x75c, 0x2f8, 3, 0x9d8, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_EN__GPIO3_12				IOMUX_PAD(0x75c, 0x2f8, 5, 0x8f4, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_EN__IPU_DISPB_PAR_RS			IOMUX_PAD(0x75c, 0x2f8, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_EN__ARM11P_TOP_EVNTBUS_6		IOMUX_PAD(0x75c, 0x2f8, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_MDC__FEC_MDC				IOMUX_PAD(0x760, 0x2fc, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_MDC__CAN2_TXCAN				IOMUX_PAD(0x760, 0x2fc, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_MDC__UART3_DCD				IOMUX_PAD(0x760, 0x2fc, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_MDC__USB_TOP_USBH2_DATA_4			IOMUX_PAD(0x760, 0x2fc, 3, 0x9dc, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_MDC__GPIO3_13				IOMUX_PAD(0x760, 0x2fc, 5, 0x8f8, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_MDC__IPU_DISPB_WR				IOMUX_PAD(0x760, 0x2fc, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_MDC__ARM11P_TOP_EVNTBUS_7			IOMUX_PAD(0x760, 0x2fc, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_MDIO__FEC_MDIO				IOMUX_PAD(0x764, 0x300, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_MDIO__CAN2_RXCAN				IOMUX_PAD(0x764, 0x300, 1, 0x7cc, 2, NO_PAD_CTRL)
-#define MX35_PAD_FEC_MDIO__USB_TOP_USBH2_DATA_5			IOMUX_PAD(0x764, 0x300, 3, 0x9e0, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_MDIO__GPIO3_14				IOMUX_PAD(0x764, 0x300, 5, 0x8fc, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_MDIO__IPU_DISPB_RD				IOMUX_PAD(0x764, 0x300, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_MDIO__ARM11P_TOP_EVNTBUS_8			IOMUX_PAD(0x764, 0x300, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_TX_ERR__FEC_TX_ERR				IOMUX_PAD(0x768, 0x304, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_ERR__OWIRE_LINE				IOMUX_PAD(0x768, 0x304, 1, 0x990, 2, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_ERR__SPDIF_SPDIF_EXTCLK			IOMUX_PAD(0x768, 0x304, 2, 0x994, 4, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_ERR__USB_TOP_USBH2_DATA_6		IOMUX_PAD(0x768, 0x304, 3, 0x9e4, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_ERR__GPIO3_15				IOMUX_PAD(0x768, 0x304, 5, 0x900, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_ERR__IPU_DISPB_D0_VSYNC			IOMUX_PAD(0x768, 0x304, 6, 0x924, 3, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TX_ERR__ARM11P_TOP_EVNTBUS_9		IOMUX_PAD(0x768, 0x304, 7, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_RX_ERR__FEC_RX_ERR				IOMUX_PAD(0x76c, 0x308, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_ERR__IPU_CSI_D_0			IOMUX_PAD(0x76c, 0x308, 1, 0x930, 3, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_ERR__USB_TOP_USBH2_DATA_7		IOMUX_PAD(0x76c, 0x308, 3, 0x9e8, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_ERR__KPP_COL_4				IOMUX_PAD(0x76c, 0x308, 4, 0x960, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_ERR__GPIO3_16				IOMUX_PAD(0x76c, 0x308, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RX_ERR__IPU_DISPB_SD_D_IO			IOMUX_PAD(0x76c, 0x308, 6, 0x92c, 5, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_CRS__FEC_CRS				IOMUX_PAD(0x770, 0x30c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_CRS__IPU_CSI_D_1				IOMUX_PAD(0x770, 0x30c, 1, 0x934, 3, NO_PAD_CTRL)
-#define MX35_PAD_FEC_CRS__USB_TOP_USBH2_PWR			IOMUX_PAD(0x770, 0x30c, 3, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_CRS__KPP_COL_5				IOMUX_PAD(0x770, 0x30c, 4, 0x964, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_CRS__GPIO3_17				IOMUX_PAD(0x770, 0x30c, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_CRS__IPU_FLASH_STROBE			IOMUX_PAD(0x770, 0x30c, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_RDATA1__FEC_RDATA_1			IOMUX_PAD(0x774, 0x310, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA1__IPU_CSI_D_2			IOMUX_PAD(0x774, 0x310, 1, 0x938, 4, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA1__AUDMUX_AUD6_RXC			IOMUX_PAD(0x774, 0x310, 2, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA1__USB_TOP_USBH2_OC			IOMUX_PAD(0x774, 0x310, 3, 0x9f4, 2, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA1__KPP_COL_6				IOMUX_PAD(0x774, 0x310, 4, 0x968, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA1__GPIO3_18				IOMUX_PAD(0x774, 0x310, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA1__IPU_DISPB_BE0			IOMUX_PAD(0x774, 0x310, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_TDATA1__FEC_TDATA_1			IOMUX_PAD(0x778, 0x314, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA1__IPU_CSI_D_3			IOMUX_PAD(0x778, 0x314, 1, 0x93c, 4, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA1__AUDMUX_AUD6_RXFS			IOMUX_PAD(0x778, 0x314, 2, 0x7bc, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA1__KPP_COL_7				IOMUX_PAD(0x778, 0x314, 4, 0x96c, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA1__GPIO3_19				IOMUX_PAD(0x778, 0x314, 5, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA1__IPU_DISPB_BE1			IOMUX_PAD(0x778, 0x314, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_RDATA2__FEC_RDATA_2			IOMUX_PAD(0x77c, 0x318, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA2__IPU_CSI_D_4			IOMUX_PAD(0x77c, 0x318, 1, 0x940, 3, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA2__AUDMUX_AUD6_TXD			IOMUX_PAD(0x77c, 0x318, 2, 0x7b4, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA2__KPP_ROW_4				IOMUX_PAD(0x77c, 0x318, 4, 0x980, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA2__GPIO3_20				IOMUX_PAD(0x77c, 0x318, 5, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_TDATA2__FEC_TDATA_2			IOMUX_PAD(0x780, 0x31c, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA2__IPU_CSI_D_5			IOMUX_PAD(0x780, 0x31c, 1, 0x944, 3, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA2__AUDMUX_AUD6_RXD			IOMUX_PAD(0x780, 0x31c, 2, 0x7b0, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA2__KPP_ROW_5				IOMUX_PAD(0x780, 0x31c, 4, 0x984, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA2__GPIO3_21				IOMUX_PAD(0x780, 0x31c, 5, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_RDATA3__FEC_RDATA_3			IOMUX_PAD(0x784, 0x320, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA3__IPU_CSI_D_6			IOMUX_PAD(0x784, 0x320, 1, 0x948, 3, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA3__AUDMUX_AUD6_TXC			IOMUX_PAD(0x784, 0x320, 2, 0x7c0, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA3__KPP_ROW_6				IOMUX_PAD(0x784, 0x320, 4, 0x988, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_RDATA3__GPIO3_22				IOMUX_PAD(0x784, 0x320, 6, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_FEC_TDATA3__FEC_TDATA_3			IOMUX_PAD(0x788, 0x324, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA3__IPU_CSI_D_7			IOMUX_PAD(0x788, 0x324, 1, 0x94c, 3, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA3__AUDMUX_AUD6_TXFS			IOMUX_PAD(0x788, 0x324, 2, 0x7c4, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA3__KPP_ROW_7				IOMUX_PAD(0x788, 0x324, 4, 0x98c, 1, NO_PAD_CTRL)
-#define MX35_PAD_FEC_TDATA3__GPIO3_23				IOMUX_PAD(0x788, 0x324, 5, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_EXT_ARMCLK__CCM_EXT_ARMCLK			IOMUX_PAD(0x78c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-#define MX35_PAD_TEST_MODE__TCU_TEST_MODE			IOMUX_PAD(0x790, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
-
-
-#endif /* __MACH_IOMUX_MX35_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx50.h b/arch/arm/plat-mxc/include/mach/iomux-mx50.h
deleted file mode 100644
index 98e7fd0..0000000
--- a/arch/arm/plat-mxc/include/mach/iomux-mx50.h
+++ /dev/null
@@ -1,977 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef __MACH_IOMUX_MX50_H__
-#define __MACH_IOMUX_MX50_H__
-
-#include <mach/iomux-v3.h>
-
-#define MX50_ELCDIF_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
-
-#define MX50_SD_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
-					PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_HIGH)
-
-#define MX50_UART_PAD_CTRL	(PAD_CTL_DSE_HIGH | PAD_CTL_PKE)
-
-#define MX50_I2C_PAD_CTRL	(PAD_CTL_ODE | PAD_CTL_DSE_HIGH | \
-					PAD_CTL_PUS_100K_UP | PAD_CTL_HYS)
-
-#define MX50_USB_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE | \
-					PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP)
-
-#define MX50_FEC_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
-					PAD_CTL_PUS_22K_UP | PAD_CTL_ODE | \
-					PAD_CTL_DSE_HIGH)
-
-#define MX50_OWIRE_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
-					PAD_CTL_PUS_100K_UP | PAD_CTL_ODE | \
-					PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST)
-
-#define MX50_KEYPAD_CTRL        (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
-					PAD_CTL_PUS_100K_UP | PAD_CTL_DSE_HIGH)
-
-#define MX50_CSPI_SS_PAD	(PAD_CTL_PKE | PAD_CTL_PUE | \
-					PAD_CTL_PUS_22K_UP | PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_KEY_COL0__KEY_COL0	IOMUX_PAD(0x2CC, 0x20, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_COL0__GPIO_4_0	IOMUX_PAD(0x2CC, 0x20, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_COL0__NANDF_CLE	IOMUX_PAD(0x2CC, 0x20, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_KEY_ROW0__KEY_ROW0	IOMUX_PAD(0x2D0, 0x24, 0, 0x0, 0, MX50_KEYPAD_CTRL)
-#define MX50_PAD_KEY_ROW0__GPIO_4_1	IOMUX_PAD(0x2D0, 0x24, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_ROW0__NANDF_ALE	IOMUX_PAD(0x2D0, 0x24, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_KEY_COL1__KEY_COL1	IOMUX_PAD(0x2D4, 0x28, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_COL1__GPIO_4_2	IOMUX_PAD(0x2D4, 0x28, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_COL1__NANDF_CE0	IOMUX_PAD(0x2D4, 0x28, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_KEY_ROW1__KEY_ROW1	IOMUX_PAD(0x2D8, 0x2C, 0, 0x0, 0, MX50_KEYPAD_CTRL)
-#define MX50_PAD_KEY_ROW1__GPIO_4_3	IOMUX_PAD(0x2D8, 0x2C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_ROW1__NANDF_CE1	IOMUX_PAD(0x2D8, 0x2C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_KEY_COL2__KEY_COL2	IOMUX_PAD(0x2DC, 0x30, 0, 0x0, 0, MX50_KEYPAD_CTRL)
-#define MX50_PAD_KEY_COL2__GPIO_4_4	IOMUX_PAD(0x2DC, 0x30, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_COL2__NANDF_CE2	IOMUX_PAD(0x2DC, 0x30, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_KEY_ROW2__KEY_ROW2	IOMUX_PAD(0x2E0, 0x34, 0, 0x0, 0, MX50_KEYPAD_CTRL)
-#define MX50_PAD_KEY_ROW2__GPIO_4_5	IOMUX_PAD(0x2E0, 0x34, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_ROW2__NANDF_CE3	IOMUX_PAD(0x2E0, 0x34, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_KEY_COL3__KEY_COL3	IOMUX_PAD(0x2E4, 0x38, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_COL3__GPIO_4_6	IOMUX_PAD(0x2E4, 0x38, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_COL3__NANDF_READY	IOMUX_PAD(0x2E4, 0x38, 2, 0x7b4, 0, PAD_CTL_PKE | \
-							PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
-#define MX50_PAD_KEY_COL3__SDMA_EXT0	IOMUX_PAD(0x2E4, 0x38, 6, 0x7b8, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_KEY_ROW3__KEY_ROW3	IOMUX_PAD(0x2E8, 0x3C, 0, 0x0, 0, MX50_KEYPAD_CTRL)
-#define MX50_PAD_KEY_ROW3__GPIO_4_7	IOMUX_PAD(0x2E8, 0x3C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_ROW3__NANDF_DQS	IOMUX_PAD(0x2E8, 0x3C, 2, 0x7b0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_KEY_ROW3__SDMA_EXT1	IOMUX_PAD(0x2E8, 0x3C, 6, 0x7bc, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_I2C1_SCL__I2C1_SCL	IOMUX_PAD(0x2EC, 0x40, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX50_I2C_PAD_CTRL)
-#define MX50_PAD_I2C1_SCL__GPIO_6_18	IOMUX_PAD(0x2EC, 0x40, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C1_SCL__UART2_TXD	IOMUX_PAD(0x2EC, 0x40, 2, 0x0, 0, MX50_UART_PAD_CTRL)
-
-#define MX50_PAD_I2C1_SDA__I2C1_SDA	IOMUX_PAD(0x2F0, 0x44, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX50_I2C_PAD_CTRL)
-#define MX50_PAD_I2C1_SDA__GPIO_6_19	IOMUX_PAD(0x2F0, 0x44, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C1_SDA__UART2_RXD	IOMUX_PAD(0x2F0, 0x44, 2, 0x7cc, 1, MX50_UART_PAD_CTRL)
-
-#define MX50_PAD_I2C2_SCL__I2C2_SCL	IOMUX_PAD(0x2F4, 0x48, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX50_I2C_PAD_CTRL)
-#define MX50_PAD_I2C2_SCL__GPIO_6_20	IOMUX_PAD(0x2F4, 0x48, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C2_SCL__UART2_CTS	IOMUX_PAD(0x2F4, 0x48, 2, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_I2C2_SCL__DCDC_OK	IOMUX_PAD(0x2F4, 0x48, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_I2C2_SDA__I2C2_SDA	IOMUX_PAD(0x2F8, 0x4C, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX50_I2C_PAD_CTRL)
-#define MX50_PAD_I2C2_SDA__GPIO_6_21	IOMUX_PAD(0x2F8, 0x4C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C2_SDA__UART2_RTS	IOMUX_PAD(0x2F8, 0x4C, 2, 0x7c8, 1, MX50_UART_PAD_CTRL)
-#define MX50_PAD_I2C2_SDA__PWRSTABLE	IOMUX_PAD(0x2F8, 0x4C, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_I2C3_SCL__I2C3_SCL	IOMUX_PAD(0x2FC, 0x50, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX50_I2C_PAD_CTRL)
-#define MX50_PAD_I2C3_SCL__GPIO_6_22	IOMUX_PAD(0x2FC, 0x50, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C3_SCL__FEC_MDC	IOMUX_PAD(0x2FC, 0x50, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_I2C3_SCL__PMIC_RDY	IOMUX_PAD(0x2FC, 0x50, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C3_SCL__GPT_CAPIN1	IOMUX_PAD(0x2FC, 0x50, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C3_SCL__USBOTG_OC	IOMUX_PAD(0x2FC, 0x50, 7, 0x7E8, 0, MX50_USB_PAD_CTRL)
-
-#define MX50_PAD_I2C3_SDA__I2C3_SDA	IOMUX_PAD(0x300, 0x54, IOMUX_CONFIG_SION, 0x0, 0, \
-								MX50_I2C_PAD_CTRL)
-#define MX50_PAD_I2C3_SDA__GPIO_6_23	IOMUX_PAD(0x300, 0x54, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C3_SDA__FEC_MDIO	IOMUX_PAD(0x300, 0x54, 2, 0x774, 0, MX50_FEC_PAD_CTRL)
-#define MX50_PAD_I2C3_SDA__PWRFAIL_INT	IOMUX_PAD(0x300, 0x54, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C3_SDA__ALARM_DEB	IOMUX_PAD(0x300, 0x54, 4, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C3_SDA__GPT_CAPIN1	IOMUX_PAD(0x300, 0x54, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C3_SDA__USBOTG_PWR	IOMUX_PAD(0x300, 0x54, 7, 0x0, 0, \
-							PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_PWM1__PWM1_PWMO	IOMUX_PAD(0x304, 0x58, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_PWM1__GPIO_6_24	IOMUX_PAD(0x304, 0x58, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_PWM1__USBOTG_OC	IOMUX_PAD(0x304, 0x58, 2, 0x7E8, 1, MX50_USB_PAD_CTRL)
-#define MX50_PAD_PWM1__GPT_CMPOUT1	IOMUX_PAD(0x304, 0x58, 5, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PWM2__PWM2_PWMO	IOMUX_PAD(0x308, 0x5C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_PWM2__GPIO_6_25	IOMUX_PAD(0x308, 0x5C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_PWM2__USBOTG_PWR	IOMUX_PAD(0x308, 0x5C, 2, 0x0, 0, \
-							PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
-#define MX50_PAD_PWM2__DCDC_PWM		IOMUX_PAD(0x308, 0x5C, 4, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_PWM2__GPT_CMPOUT2	IOMUX_PAD(0x308, 0x5C, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_PWM2__ANY_PU_RST	IOMUX_PAD(0x308, 0x5C, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_OWIRE__OWIRE		IOMUX_PAD(0x30C, 0x60, 0, 0x0, 0, MX50_OWIRE_PAD_CTRL)
-#define MX50_PAD_OWIRE__GPIO_6_26	IOMUX_PAD(0x30C, 0x60, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_OWIRE__USBH1_OC	IOMUX_PAD(0x30C, 0x60, 2, 0x0, 0, MX50_USB_PAD_CTRL)
-#define MX50_PAD_OWIRE__SSI_EXT1_CLK	IOMUX_PAD(0x30C, 0x60, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_OWIRE__EPDC_PWRIRQ	IOMUX_PAD(0x30C, 0x60, 4, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_OWIRE__GPT_CMPOUT3	IOMUX_PAD(0x30C, 0x60, 5, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPITO__EPITO		IOMUX_PAD(0x310, 0x64, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPITO__GPIO_6_27	IOMUX_PAD(0x310, 0x64, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPITO__USBH1_PWR	IOMUX_PAD(0x310, 0x64, 2, 0x0, 0, \
-							PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
-#define MX50_PAD_EPITO__SSI_EXT2_CLK	IOMUX_PAD(0x310, 0x64, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPITO__TOG_EN		IOMUX_PAD(0x310, 0x64, 4, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPITO__GPT_CLKIN	IOMUX_PAD(0x310, 0x64, 5, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_WDOG__WDOG		IOMUX_PAD(0x314, 0x68, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_WDOG__GPIO_6_28	IOMUX_PAD(0x314, 0x68, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_WDOG__WDOG_RST		IOMUX_PAD(0x314, 0x68, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_WDOG__XTAL32K		IOMUX_PAD(0x314, 0x68, 6, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SSI_TXFS__SSI_TXFS	IOMUX_PAD(0x318, 0x6C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_TXFS__GPIO_6_0	IOMUX_PAD(0x318, 0x6C, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SSI_TXC__SSI_TXC	IOMUX_PAD(0x31C, 0x70, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_TXC__GPIO_6_1	IOMUX_PAD(0x31C, 0x70, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SSI_TXD__SSI_TXD	IOMUX_PAD(0x320, 0x74, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_TXD__GPIO_6_2	IOMUX_PAD(0x320, 0x74, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_TXD__CSPI_RDY	IOMUX_PAD(0x320, 0x74, 4, 0x6e8, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SSI_RXD__SSI_RXD	IOMUX_PAD(0x324, 0x78, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXD__GPIO_6_3	IOMUX_PAD(0x324, 0x78, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXD__CSPI_SS3	IOMUX_PAD(0x324, 0x78, 4, 0x6f4, 0, MX50_CSPI_SS_PAD)
-
-#define MX50_PAD_SSI_RXFS__AUD3_RXFS	IOMUX_PAD(0x328, 0x7C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXFS__GPIO_6_4	IOMUX_PAD(0x328, 0x7C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXFS__UART5_TXD	IOMUX_PAD(0x328, 0x7C, 2, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_SSI_RXFS__WEIM_D6	IOMUX_PAD(0x328, 0x7C, 3, 0x804, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXFS__CSPI_SS2	IOMUX_PAD(0x328, 0x7C, 4, 0x6f0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_SSI_RXFS__FEC_COL	IOMUX_PAD(0x328, 0x7C, 5, 0x770, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SSI_RXFS__FEC_MDC	IOMUX_PAD(0x328, 0x7C, 6, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_SSI_RXC__AUD3_RXC	IOMUX_PAD(0x32C, 0x80, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXC__GPIO_6_5	IOMUX_PAD(0x32C, 0x80, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXC__UART5_RXD	IOMUX_PAD(0x32C, 0x80, 2, 0x7e4, 1, MX50_UART_PAD_CTRL)
-#define MX50_PAD_SSI_RXC__WEIM_D7	IOMUX_PAD(0x32C, 0x80, 3, 0x808, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXC__CSPI_SS1	IOMUX_PAD(0x32C, 0x80, 4, 0x6ec, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_SSI_RXC__FEC_RX_CLK	IOMUX_PAD(0x32C, 0x80, 5, 0x780, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXC__FEC_MDIO	IOMUX_PAD(0x32C, 0x80, 6, 0x774, 1, MX50_FEC_PAD_CTRL)
-
-#define MX50_PAD_UART1_TXD__UART1_TXD	IOMUX_PAD(0x330, 0x84, 0, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART1_TXD__GPIO_6_6	IOMUX_PAD(0x330, 0x84, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_UART1_RXD__UART1_RXD	IOMUX_PAD(0x334, 0x88, 0, 0x7c4, 1, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART1_RXD__GPIO_6_7	IOMUX_PAD(0x334, 0x88, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_UART1_CTS__UART1_CTS	IOMUX_PAD(0x338, 0x8C, 0, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART1_CTS__GPIO_6_8	IOMUX_PAD(0x338, 0x8C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART1_CTS__UART5_TXD	IOMUX_PAD(0x338, 0x8C, 2, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART1_CTS__SD4_D4	IOMUX_PAD(0x338, 0x8C, 4, 0x760, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART1_CTS__SD4_CMD	IOMUX_PAD(0x338, 0x8C, 5, 0x74c, 0, MX50_SD_PAD_CTRL)
-
-#define MX50_PAD_UART1_RTS__UART1_RTS	IOMUX_PAD(0x33C, 0x90, 0, 0x7c0, 1, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART1_RTS__GPIO_6_9	IOMUX_PAD(0x33C, 0x90, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART1_RTS__UART5_RXD	IOMUX_PAD(0x33C, 0x90, 2, 0x7e4, 3, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART1_RTS__SD4_D5	IOMUX_PAD(0x33C, 0x90, 4, 0x764, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART1_RTS__SD4_CLK	IOMUX_PAD(0x33C, 0x90, 5, 0x748, 0, MX50_SD_PAD_CTRL)
-
-#define MX50_PAD_UART2_TXD__UART2_TXD	IOMUX_PAD(0x340, 0x94, 0, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART2_TXD__GPIO_6_10	IOMUX_PAD(0x340, 0x94, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART2_TXD__SD4_D6	IOMUX_PAD(0x340, 0x94, 4, 0x768, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART2_TXD__SD4_D4	IOMUX_PAD(0x340, 0x94, 5, 0x760, 1, MX50_SD_PAD_CTRL)
-
-#define MX50_PAD_UART2_RXD__UART2_RXD	IOMUX_PAD(0x344, 0x98, 0, 0x7cc, 3, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART2_RXD__GPIO_6_11	IOMUX_PAD(0x344, 0x98, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART2_RXD__SD4_D7	IOMUX_PAD(0x344, 0x98, 4, 0x76c, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART2_RXD__SD4_D5	IOMUX_PAD(0x344, 0x98, 5, 0x764, 1, MX50_SD_PAD_CTRL)
-
-#define MX50_PAD_UART2_CTS__UART2_CTS	IOMUX_PAD(0x348, 0x9C, 0, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART2_CTS__GPIO_6_12	IOMUX_PAD(0x348, 0x9C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART2_CTS__SD4_CMD	IOMUX_PAD(0x348, 0x9C, 4, 0x74c, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART2_CTS__SD4_D6	IOMUX_PAD(0x348, 0x9C, 5, 0x768, 1, MX50_SD_PAD_CTRL)
-
-#define MX50_PAD_UART2_RTS__UART2_RTS	IOMUX_PAD(0x34C, 0xA0, 0, 0x7c8, 3, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART2_RTS__GPIO_6_13	IOMUX_PAD(0x34C, 0xA0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART2_RTS__SD4_CLK	IOMUX_PAD(0x34C, 0xA0, 4, 0x748, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART2_RTS__SD4_D7	IOMUX_PAD(0x34C, 0xA0, 5, 0x76c, 1, MX50_SD_PAD_CTRL)
-
-#define MX50_PAD_UART3_TXD__UART3_TXD	IOMUX_PAD(0x350, 0xA4, 0, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART3_TXD__GPIO_6_14	IOMUX_PAD(0x350, 0xA4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART3_TXD__SD1_D4	IOMUX_PAD(0x350, 0xA4, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART3_TXD__SD4_D0	IOMUX_PAD(0x350, 0xA4, 4, 0x750, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART3_TXD__SD2_WP	IOMUX_PAD(0x350, 0xA4, 5, 0x744, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART3_TXD__WEIM_D12	IOMUX_PAD(0x350, 0xA4, 6, 0x81c, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_UART3_RXD__UART3_RXD	IOMUX_PAD(0x354, 0xA8, 0, 0x7d4, 1, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART3_RXD__GPIO_6_15	IOMUX_PAD(0x354, 0xA8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART3_RXD__SD1_D5	IOMUX_PAD(0x354, 0xA8, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART3_RXD__SD4_D1	IOMUX_PAD(0x354, 0xA8, 4, 0x754, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART3_RXD__SD2_CD	IOMUX_PAD(0x354, 0xA8, 5, 0x740, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART3_RXD__WEIM_D13	IOMUX_PAD(0x354, 0xA8, 6, 0x820, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_UART4_TXD__UART4_TXD	IOMUX_PAD(0x358, 0xAC, 0, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART4_TXD__GPIO_6_16	IOMUX_PAD(0x358, 0xAC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART4_TXD__UART3_CTS	IOMUX_PAD(0x358, 0xAC, 2, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART4_TXD__SD1_D6	IOMUX_PAD(0x358, 0xAC, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART4_TXD__SD4_D2	IOMUX_PAD(0x358, 0xAC, 4, 0x758, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART4_TXD__SD2_LCTL	IOMUX_PAD(0x358, 0xAC, 5, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART4_TXD__WEIM_D14	IOMUX_PAD(0x358, 0xAC, 6, 0x824, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_UART4_RXD__UART4_RXD	IOMUX_PAD(0x35C, 0xB0, 0, 0x7dc, 1, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART4_RXD__GPIO_6_17	IOMUX_PAD(0x35C, 0xB0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART4_RXD__UART3_RTS	IOMUX_PAD(0x35C, 0xB0, 2, 0x7d0, 1, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART4_RXD__SD1_D7	IOMUX_PAD(0x35C, 0xB0, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART4_RXD__SD4_D3	IOMUX_PAD(0x35C, 0xB0, 4, 0x75c, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART4_RXD__SD1_LCTL	IOMUX_PAD(0x35C, 0xB0, 5, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART4_RXD__WEIM_D15	IOMUX_PAD(0x35C, 0xB0, 6, 0x828, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_CSPI_SCLK__CSPI_SCLK	IOMUX_PAD(0x360, 0xB4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_CSPI_SCLK__GPIO_4_8	IOMUX_PAD(0x360, 0xB4, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_CSPI_MOSI__CSPI_MOSI	IOMUX_PAD(0x364, 0xB8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_CSPI_MOSI__GPIO_4_9	IOMUX_PAD(0x364, 0xB8, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_CSPI_MISO__CSPI_MISO	IOMUX_PAD(0x368, 0xBC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_CSPI_MISO__GPIO_4_10	IOMUX_PAD(0x368, 0xBC, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_CSPI_SS0__CSPI_SS0	IOMUX_PAD(0x36C, 0xC0, 0, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_CSPI_SS0__GPIO_4_11	IOMUX_PAD(0x36C, 0xC0, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_ECSPI1_SCLK__ECSPI1_SCLK	IOMUX_PAD(0x370, 0xC4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_SCLK__GPIO_4_12		IOMUX_PAD(0x370, 0xC4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_SCLK__CSPI_RDY		IOMUX_PAD(0x370, 0xC4, 2, 0x6e8, 1, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_SCLK__ECSPI2_RDY	IOMUX_PAD(0x370, 0xC4, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_SCLK__UART3_RTS		IOMUX_PAD(0x370, 0xC4, 4, 0x7d0, 2, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI1_SCLK__EPDC_SDCE6	IOMUX_PAD(0x370, 0xC4, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_SCLK__WEIM_D8		IOMUX_PAD(0x370, 0xC4, 7, 0x80c, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_ECSPI1_MOSI__ECSPI1_MOSI	IOMUX_PAD(0x374, 0xC8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_MOSI__GPIO_4_13		IOMUX_PAD(0x374, 0xC8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_MOSI__CSPI_SS1		IOMUX_PAD(0x374, 0xC8, 2, 0x6ec, 1, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_MOSI__ECSPI2_SS1	IOMUX_PAD(0x374, 0xC8, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_MOSI__UART3_CTS		IOMUX_PAD(0x374, 0xC8, 4, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI1_MOSI__EPDC_SDCE7	IOMUX_PAD(0x374, 0xC8, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_MOSI__WEIM_D9		IOMUX_PAD(0x374, 0xC8, 7, 0x810, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_ECSPI1_MISO__ECSPI1_MISO	IOMUX_PAD(0x378, 0xCC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_MISO__GPIO_4_14		IOMUX_PAD(0x378, 0xCC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_MISO__CSPI_SS2		IOMUX_PAD(0x378, 0xCC, 2, 0x6f0, 1, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_MISO__ECSPI2_SS2	IOMUX_PAD(0x378, 0xCC, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_MISO__UART4_RTS		IOMUX_PAD(0x378, 0xCC, 4, 0x7d8, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI1_MISO__EPDC_SDCE8	IOMUX_PAD(0x378, 0xCC, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_MISO__WEIM_D10		IOMUX_PAD(0x378, 0xCC, 7, 0x814, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_ECSPI1_SS0__ECSPI1_SS0		IOMUX_PAD(0x37C, 0xD0, 0, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_SS0__GPIO_4_15		IOMUX_PAD(0x37C, 0xD0, 1, 0x0, 0, PAD_CTL_PUS_100K_UP)
-#define MX50_PAD_ECSPI1_SS0__CSPI_SS3		IOMUX_PAD(0x37C, 0xD0, 2, 0x6f4, 1, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_SS0__ECSPI2_SS3		IOMUX_PAD(0x37C, 0xD0, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_SS0__UART4_CTS		IOMUX_PAD(0x37C, 0xD0, 4, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI1_SS0__EPDC_SDCE9		IOMUX_PAD(0x37C, 0xD0, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_SS0__WEIM_D11		IOMUX_PAD(0x37C, 0xD0, 7, 0x818, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_ECSPI2_SCLK__ECSPI2_SCLK	IOMUX_PAD(0x380, 0xD4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SCLK__GPIO_4_16		IOMUX_PAD(0x380, 0xD4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SCLK__ELCDIF_WR		IOMUX_PAD(0x380, 0xD4, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SCLK__ECSPI1_RDY	IOMUX_PAD(0x380, 0xD4, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SCLK__UART5_RTS		IOMUX_PAD(0x380, 0xD4, 4, 0x7e0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SCLK__ELCDIF_DOTCLK	IOMUX_PAD(0x380, 0xD4, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SCLK__NANDF_CEN4	IOMUX_PAD(0x380, 0xD4, 6, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SCLK__WEIM_D8		IOMUX_PAD(0x380, 0xD4, 7, 0x80c, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_ECSPI2_MOSI__ECSPI2_MOSI	IOMUX_PAD(0x384, 0xD8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MOSI__GPIO_4_17		IOMUX_PAD(0x384, 0xD8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MOSI__ELCDIF_RD		IOMUX_PAD(0x384, 0xD8, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MOSI__ECSPI1_SS1	IOMUX_PAD(0x384, 0xD8, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI2_MOSI__UART5_CTS		IOMUX_PAD(0x384, 0xD8, 4, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MOSI__ELCDIF_EN		IOMUX_PAD(0x384, 0xD8, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MOSI__NANDF_CEN5	IOMUX_PAD(0x384, 0xD8, 6, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MOSI__WEIM_D9		IOMUX_PAD(0x384, 0xD8, 7, 0x810, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_ECSPI2_MISO__ECSPI2_MISO	IOMUX_PAD(0x388, 0xDC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MISO__GPIO_4_18		IOMUX_PAD(0x388, 0xDC, 1, 0x0, 0, PAD_CTL_PUS_100K_UP)
-#define MX50_PAD_ECSPI2_MISO__ELCDIF_RS		IOMUX_PAD(0x388, 0xDC, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MISO__ECSPI1_SS2	IOMUX_PAD(0x388, 0xDC, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI2_MISO__UART5_TXD		IOMUX_PAD(0x388, 0xDC, 4, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MISO__ELCDIF_VSYNC	IOMUX_PAD(0x388, 0xDC, 5, 0x73c, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MISO__NANDF_CEN6	IOMUX_PAD(0x388, 0xDC, 6, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MISO__WEIM_D10		IOMUX_PAD(0x388, 0xDC, 7, 0x814, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_ECSPI2_SS0__ECSPI2_SS0		IOMUX_PAD(0x38C, 0xE0, 0, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI2_SS0__GPIO_4_19		IOMUX_PAD(0x38C, 0xE0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SS0__ELCDIF_CS		IOMUX_PAD(0x38C, 0xE0, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SS0__ECSPI1_SS3		IOMUX_PAD(0x38C, 0xE0, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI2_SS0__UART5_RXD		IOMUX_PAD(0x38C, 0xE0, 4, 0x7e4, 5, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SS0__ELCDIF_HSYNC	IOMUX_PAD(0x38C, 0xE0, 5, 0x6f8, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SS0__NANDF_CEN7		IOMUX_PAD(0x38C, 0xE0, 6, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SS0__WEIM_D11		IOMUX_PAD(0x38C, 0xE0, 7, 0x818, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_SD1_CLK__SD1_CLK	IOMUX_PAD(0x390, 0xE4, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD1_CLK__GPIO_5_0	IOMUX_PAD(0x390, 0xE4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD1_CLK__CLKO		IOMUX_PAD(0x390, 0xE4, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD1_CMD__SD1_CMD	IOMUX_PAD(0x394, 0xE8, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD1_CMD__GPIO_5_1	IOMUX_PAD(0x394, 0xE8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD1_CMD__CLKO2		IOMUX_PAD(0x394, 0xE8, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD1_D0__SD1_D0		IOMUX_PAD(0x398, 0xEC, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD1_D0__GPIO_5_2	IOMUX_PAD(0x398, 0xEC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD1_D0__PLL1_BYP	IOMUX_PAD(0x398, 0xEC, 7, 0x6dc, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD1_D1__SD1_D1		IOMUX_PAD(0x39C, 0xF0, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD1_D1__GPIO_5_3	IOMUX_PAD(0x39C, 0xF0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD1_D1__PLL2_BYP	IOMUX_PAD(0x39C, 0xF0, 7, 0x6e0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD1_D2__SD1_D2		IOMUX_PAD(0x3A0, 0xF4, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD1_D2__GPIO_5_4	IOMUX_PAD(0x3A0, 0xF4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD1_D2__PLL3_BYP	IOMUX_PAD(0x3A0, 0xF4, 7, 0x6e4, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD1_D3__SD1_D3		IOMUX_PAD(0x3A4, 0xF8, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD1_D3__GPIO_5_5	IOMUX_PAD(0x3A4, 0xF8, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_CLK__SD2_CLK	IOMUX_PAD(0x3A8, 0xFC, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_CLK__GPIO_5_6	IOMUX_PAD(0x3A8, 0xFC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_CLK__MSHC_SCLK	IOMUX_PAD(0x3A8, 0xFC, 2, 0x0, 0, MX50_SD_PAD_CTRL)
-
-#define MX50_PAD_SD2_CMD__SD2_CMD	IOMUX_PAD(0x3AC, 0x100, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_CMD__GPIO_5_7	IOMUX_PAD(0x3AC, 0x100, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_CMD__MSHC_BS	IOMUX_PAD(0x3AC, 0x100, 2, 0x0, 0, MX50_SD_PAD_CTRL)
-
-#define MX50_PAD_SD2_D0__SD2_D0		IOMUX_PAD(0x3B0, 0x104, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D0__GPIO_5_8	IOMUX_PAD(0x3B0, 0x104, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D0__MSHC_D0	IOMUX_PAD(0x3B0, 0x104, 2, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D0__KEY_COL4	IOMUX_PAD(0x3B0, 0x104, 3, 0x790, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_D1__SD2_D1		IOMUX_PAD(0x3B4, 0x108, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D1__GPIO_5_9	IOMUX_PAD(0x3B4, 0x108, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D1__MSHC_D1	IOMUX_PAD(0x3B4, 0x108, 2, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D1__KEY_ROW4	IOMUX_PAD(0x3B4, 0x108, 3, 0x7a0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_D2__SD2_D2		IOMUX_PAD(0x3B8, 0x10C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D2__GPIO_5_10	IOMUX_PAD(0x3B8, 0x10C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D2__MSHC_D2	IOMUX_PAD(0x3B8, 0x10C, 2, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D2__KEY_COL5	IOMUX_PAD(0x3B8, 0x10C, 3, 0x794, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_D3__SD2_D3		IOMUX_PAD(0x3BC, 0x110, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D3__GPIO_5_11	IOMUX_PAD(0x3BC, 0x110, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D3__MSHC_D3	IOMUX_PAD(0x3BC, 0x110, 2, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D3__KEY_ROW5	IOMUX_PAD(0x3BC, 0x110, 3, 0x7a4, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_D4__SD2_D4		IOMUX_PAD(0x3C0, 0x114, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D4__GPIO_5_12	IOMUX_PAD(0x3C0, 0x114, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D4__AUD4_RXFS	IOMUX_PAD(0x3C0, 0x114, 2, 0x6d0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D4__KEY_COL6	IOMUX_PAD(0x3C0, 0x114, 3, 0x798, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D4__WEIM_D0	IOMUX_PAD(0x3C0, 0x114, 4, 0x7ec, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D4__CCM_OUT0	IOMUX_PAD(0x3C0, 0x114, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_D5__SD2_D5		IOMUX_PAD(0x3C4, 0x118, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D5__GPIO_5_13	IOMUX_PAD(0x3C4, 0x118, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D5__AUD4_RXC	IOMUX_PAD(0x3C4, 0x118, 2, 0x6cc, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D5__KEY_ROW6	IOMUX_PAD(0x3C4, 0x118, 3, 0x7a8, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D5__WEIM_D1	IOMUX_PAD(0x3C4, 0x118, 4, 0x7f0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D5__CCM_OUT1	IOMUX_PAD(0x3C4, 0x118, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_D6__SD2_D6		IOMUX_PAD(0x3C8, 0x11C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D6__GPIO_5_14	IOMUX_PAD(0x3C8, 0x11C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D6__AUD4_RXD	IOMUX_PAD(0x3C8, 0x11C, 2, 0x6c4, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D6__KEY_COL7	IOMUX_PAD(0x3C8, 0x11C, 3, 0x79c, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D6__WEIM_D2	IOMUX_PAD(0x3C8, 0x11C, 4, 0x7f4, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D6__CCM_OUT2	IOMUX_PAD(0x3C8, 0x11C, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_D7__SD2_D7		IOMUX_PAD(0x3CC, 0x120, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D7__GPIO_5_15	IOMUX_PAD(0x3CC, 0x120, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D7__AUD4_TXFS	IOMUX_PAD(0x3CC, 0x120, 2, 0x6d8, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D7__KEY_ROW7	IOMUX_PAD(0x3CC, 0x120, 3, 0x7ac, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D7__WEIM_D3	IOMUX_PAD(0x3CC, 0x120, 4, 0x7f8, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D7__CCM_STOP	IOMUX_PAD(0x3CC, 0x120, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_WP__SD2_WP		IOMUX_PAD(0x3D0, 0x124, 0, 0x744, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_WP__GPIO_5_16	IOMUX_PAD(0x3D0, 0x124, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_WP__AUD4_TXD	IOMUX_PAD(0x3D0, 0x124, 2, 0x6c8, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_WP__WEIM_D4	IOMUX_PAD(0x3D0, 0x124, 4, 0x7fc, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_WP__CCM_WAIT	IOMUX_PAD(0x3D0, 0x124, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_CD__SD2_CD		IOMUX_PAD(0x3D4, 0x128, 0, 0x740, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_CD__GPIO_5_17	IOMUX_PAD(0x3D4, 0x128, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_CD__AUD4_TXC	IOMUX_PAD(0x3D4, 0x128, 2, 0x6d4, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_CD__WEIM_D5	IOMUX_PAD(0x3D4, 0x128, 4, 0x800, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_CD__CCM_REF_EN	IOMUX_PAD(0x3D4, 0x128, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_ON_REQ__PMIC_ON_REQ	IOMUX_PAD(0x3D8, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_STBY_REQ__PMIC_STBY_REQ	IOMUX_PAD(0x3DC, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_PORT_B__PMIC_PORT_B	IOMUX_PAD(0x3E0, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_BOOT_MODE1__PMIC_BOOT_MODE1	IOMUX_PAD(0x3E4, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_RESET_IN_B__PMIC_RESET_IN_B	IOMUX_PAD(0x3E8, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_BOOT_MODE0__PMIC_BOOT_MODE0	IOMUX_PAD(0x3EC, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_TEST_MODE__PMIC_TEST_MODE	IOMUX_PAD(0x3F0, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_JTAG_TMS__PMIC_JTAG_TMS	IOMUX_PAD(0x3F4, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_JTAG_MOD__PMIC_JTAG_MOD	IOMUX_PAD(0x3F8, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_JTAG_TRSTB__PMIC_JTAG_TRSTB	IOMUX_PAD(0x3FC, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_JTAG_TDI__PMIC_JTAG_TDI	IOMUX_PAD(0x400, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_JTAG_TCK__PMIC_JTAG_TCK	IOMUX_PAD(0x404, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_JTAG_TDO__PMIC_JTAG_TDO	IOMUX_PAD(0x408, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D0__DISP_D0	IOMUX_PAD(0x40C, 0x12C, 0, 0x6fc, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D0__GPIO_2_0	IOMUX_PAD(0x40C, 0x12C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D0__FEC_TXCLK	IOMUX_PAD(0x40C, 0x12C, 2, 0x78c, 0, PAD_CTL_HYS | PAD_CTL_PKE)
-
-#define MX50_PAD_DISP_D1__DISP_D1	IOMUX_PAD(0x410, 0x130, 0, 0x700, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D1__GPIO_2_1	IOMUX_PAD(0x410, 0x130, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D1__FEC_RX_ER	IOMUX_PAD(0x410, 0x130, 2, 0x788, 0, PAD_CTL_HYS | PAD_CTL_PKE)
-#define MX50_PAD_DISP_D1__WEIM_A17	IOMUX_PAD(0x410, 0x130, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D2__DISP_D2	IOMUX_PAD(0x414, 0x134, 0, 0x704, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D2__GPIO_2_2	IOMUX_PAD(0x414, 0x134, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D2__FEC_RX_DV	IOMUX_PAD(0x414, 0x134, 2, 0x784, 0, PAD_CTL_HYS | PAD_CTL_PKE)
-#define MX50_PAD_DISP_D2__WEIM_A18	IOMUX_PAD(0x414, 0x134, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D3__DISP_D3	IOMUX_PAD(0x418, 0x138, 0, 0x708, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D3__GPIO_2_3	IOMUX_PAD(0x418, 0x138, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D3__FEC_RXD1	IOMUX_PAD(0x418, 0x138, 2, 0x77C, 0, PAD_CTL_HYS | PAD_CTL_PKE)
-#define MX50_PAD_DISP_D3__WEIM_A19	IOMUX_PAD(0x418, 0x138, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D3__FEC_COL	IOMUX_PAD(0x418, 0x138, 4, 0x770, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D4__DISP_D4	IOMUX_PAD(0x41C, 0x13C, 0, 0x70c, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D4__GPIO_2_4	IOMUX_PAD(0x41C, 0x13C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D4__FEC_RXD0	IOMUX_PAD(0x41C, 0x13C, 2, 0x778, 0, PAD_CTL_HYS | PAD_CTL_PKE)
-#define MX50_PAD_DISP_D4__WEIM_A20	IOMUX_PAD(0x41C, 0x13C, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D5__DISP_D5	IOMUX_PAD(0x420, 0x140, 0, 0x710, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D5__GPIO_2_5	IOMUX_PAD(0x420, 0x140, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D5__FEC_TX_EN	IOMUX_PAD(0x420, 0x140, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_DISP_D5__WEIM_A21	IOMUX_PAD(0x420, 0x140, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D6__DISP_D6	IOMUX_PAD(0x424, 0x144, 0, 0x714, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D6__GPIO_2_6	IOMUX_PAD(0x424, 0x144, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D6__FEC_TXD1	IOMUX_PAD(0x424, 0x144, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_DISP_D6__WEIM_A22	IOMUX_PAD(0x424, 0x144, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D6__FEC_RX_CLK	IOMUX_PAD(0x424, 0x144, 4, 0x780, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D7__DISP_D7	IOMUX_PAD(0x428, 0x148, 0, 0x718, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D7__GPIO_2_7	IOMUX_PAD(0x428, 0x148, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D7__FEC_TXD0	IOMUX_PAD(0x428, 0x148, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_DISP_D7__WEIM_A23	IOMUX_PAD(0x428, 0x148, 3, 0x0, 0, NO_PAD_CTRL)
-
-
-#define MX50_PAD_DISP_WR__ELCDIF_WR	IOMUX_PAD(0x42C, 0x14C, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_WR__GPIO_2_16	IOMUX_PAD(0x42C, 0x14C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_WR__ELCDIF_PIXCLK	IOMUX_PAD(0x42C, 0x14C, 2, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_WR__WEIM_A24	IOMUX_PAD(0x42C, 0x14C, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_RD__ELCDIF_RD	IOMUX_PAD(0x430, 0x150, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_RD__GPIO_2_19	IOMUX_PAD(0x430, 0x150, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_RD__ELCDIF_EN	IOMUX_PAD(0x430, 0x150, 2, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_RD__WEIM_A25	IOMUX_PAD(0x430, 0x150, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_RS__ELCDIF_RS	IOMUX_PAD(0x434, 0x154, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_RS__GPIO_2_17	IOMUX_PAD(0x434, 0x154, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_RS__ELCDIF_VSYNC	IOMUX_PAD(0x434, 0x154, 2, 0x73c, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_RS__WEIM_A26	IOMUX_PAD(0x434, 0x154, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_CS__ELCDIF_CS	IOMUX_PAD(0x438, 0x158, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_CS__GPIO_2_21	IOMUX_PAD(0x438, 0x158, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_CS__ELCDIF_HSYNC	IOMUX_PAD(0x438, 0x158, 2, 0x6f8, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_CS__WEIM_A27	IOMUX_PAD(0x438, 0x158, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_CS__WEIM_CS3	IOMUX_PAD(0x438, 0x158, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_BUSY__ELCDIF_HSYNC	IOMUX_PAD(0x43C, 0x15C, 0, 0x6f8, 2, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_BUSY__GPIO_2_18		IOMUX_PAD(0x43C, 0x15C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_BUSY__WEIM_CS3		IOMUX_PAD(0x43C, 0x15C, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_RESET__ELCDIF_RST	IOMUX_PAD(0x440, 0x160, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_RESET__GPIO_2_20	IOMUX_PAD(0x440, 0x160, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_RESET__WEIM_CS3	IOMUX_PAD(0x440, 0x160, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_CMD__SD3_CMD	IOMUX_PAD(0x444, 0x164, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_CMD__GPIO_5_18	IOMUX_PAD(0x444, 0x164, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_CMD__NANDF_WRN	IOMUX_PAD(0x444, 0x164, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_CMD__SSP_CMD	IOMUX_PAD(0x444, 0x164, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_CLK__SD3_CLK	IOMUX_PAD(0x448, 0x168, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_CLK__GPIO_5_19	IOMUX_PAD(0x448, 0x168, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_CLK__NANDF_RDN	IOMUX_PAD(0x448, 0x168, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_CLK__SSP_CLK	IOMUX_PAD(0x448, 0x168, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_D0__SD3_D0		IOMUX_PAD(0x44C, 0x16C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_D0__GPIO_5_20	IOMUX_PAD(0x44C, 0x16C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_D0__NANDF_D4	IOMUX_PAD(0x44C, 0x16C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_D0__SSP_D0		IOMUX_PAD(0x44C, 0x16C, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD3_D0__PLL1_BYP	IOMUX_PAD(0x44C, 0x16C, 7, 0x6dc, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_D1__SD3_D1		IOMUX_PAD(0x450, 0x170, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_D1__GPIO_5_21	IOMUX_PAD(0x450, 0x170, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_D1__NANDF_D5	IOMUX_PAD(0x450, 0x170, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_D1__PLL2_BYP	IOMUX_PAD(0x450, 0x170, 7, 0x6e0, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_D2__SD3_D2		IOMUX_PAD(0x454, 0x174, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_D2__GPIO_5_22	IOMUX_PAD(0x454, 0x174, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_D2__NANDF_D6	IOMUX_PAD(0x454, 0x174, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_D2__SSP_D2		IOMUX_PAD(0x454, 0x174, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD3_D2__PLL3_BYP	IOMUX_PAD(0x454, 0x174, 7, 0x6e4, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_D3__SD3_D3		IOMUX_PAD(0x458, 0x178, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_D3__GPIO_5_23	IOMUX_PAD(0x458, 0x178, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_D3__NANDF_D7	IOMUX_PAD(0x458, 0x178, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_D3__SSP_D3		IOMUX_PAD(0x458, 0x178, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_D4__SD3_D4		IOMUX_PAD(0x45C, 0x17C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_D4__GPIO_5_24	IOMUX_PAD(0x45C, 0x17C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_D4__NANDF_D0	IOMUX_PAD(0x45C, 0x17C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_D4__SSP_D4		IOMUX_PAD(0x45C, 0x17C, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_D5__SD3_D5		IOMUX_PAD(0x460, 0x180, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_D5__GPIO_5_25	IOMUX_PAD(0x460, 0x180, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_D5__NANDF_D1	IOMUX_PAD(0x460, 0x180, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_D5__SSP_D5		IOMUX_PAD(0x460, 0x180, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_D6__SD3_D6		IOMUX_PAD(0x464, 0x184, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_D6__GPIO_5_26	IOMUX_PAD(0x464, 0x184, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_D6__NANDF_D2	IOMUX_PAD(0x464, 0x184, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_D6__SSP_D6		IOMUX_PAD(0x464, 0x184, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_D7__SD3_D7		IOMUX_PAD(0x468, 0x188, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_D7__GPIO_5_27	IOMUX_PAD(0x468, 0x188, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_D7__NANDF_D3	IOMUX_PAD(0x468, 0x188, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_D7__SSP_D7		IOMUX_PAD(0x468, 0x188, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_WP__SD3_WP		IOMUX_PAD(0x46C, 0x18C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_WP__GPIO_5_28	IOMUX_PAD(0x46C, 0x18C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_WP__NANDF_RESETN	IOMUX_PAD(0x46C, 0x18C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_WP__SSP_CD		IOMUX_PAD(0x46C, 0x18C, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD3_WP__SD4_LCTL	IOMUX_PAD(0x46C, 0x18C, 4, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_WP__WEIM_CS3	IOMUX_PAD(0x46C, 0x18C, 5, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D8__DISP_D8	IOMUX_PAD(0x470, 0x190, 0, 0x71c, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D8__GPIO_2_8	IOMUX_PAD(0x470, 0x190, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D8__NANDF_CLE	IOMUX_PAD(0x470, 0x190, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D8__SD1_LCTL	IOMUX_PAD(0x470, 0x190, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D8__SD4_CMD	IOMUX_PAD(0x470, 0x190, 4, 0x74c, 2, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D8__KEY_COL4	IOMUX_PAD(0x470, 0x190, 5, 0x790, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D8__FEC_TX_CLK	IOMUX_PAD(0x470, 0x190, 6, 0x78c, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D9__DISP_D9	IOMUX_PAD(0x474, 0x194, 0, 0x720, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D9__GPIO_2_9	IOMUX_PAD(0x474, 0x194, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D9__NANDF_ALE	IOMUX_PAD(0x474, 0x194, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D9__SD2_LCTL	IOMUX_PAD(0x474, 0x194, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D9__SD4_CLK	IOMUX_PAD(0x474, 0x194, 4, 0x748, 2, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D9__KEY_ROW4	IOMUX_PAD(0x474, 0x194, 5, 0x7a0, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D9__FEC_RX_ER	IOMUX_PAD(0x474, 0x194, 6, 0x788, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D10__DISP_D10	IOMUX_PAD(0x478, 0x198, 0, 0x724, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D10__GPIO_2_10	IOMUX_PAD(0x478, 0x198, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D10__NANDF_CEN0	IOMUX_PAD(0x478, 0x198, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D10__SD3_LCTL	IOMUX_PAD(0x478, 0x198, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D10__SD4_D0	IOMUX_PAD(0x478, 0x198, 4, 0x750, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D10__KEY_COL5	IOMUX_PAD(0x478, 0x198, 5, 0x794, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D10__FEC_RX_DV	IOMUX_PAD(0x478, 0x198, 6, 0x784, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D11__DISP_D11	IOMUX_PAD(0x47C, 0x19C, 0, 0x728, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D11__GPIO_2_11	IOMUX_PAD(0x47C, 0x19C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D11__NANDF_CEN1	IOMUX_PAD(0x47C, 0x19C, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D11__SD4_D1	IOMUX_PAD(0x47C, 0x19C, 4, 0x754, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D11__KEY_ROW5	IOMUX_PAD(0x47C, 0x19C, 5, 0x7a4, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D11__FEC_RDAT1	IOMUX_PAD(0x47C, 0x19C, 6, 0x77c, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D12__DISP_D12	IOMUX_PAD(0x480, 0x1A0, 0, 0x72c, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D12__GPIO_2_12	IOMUX_PAD(0x480, 0x1A0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D12__NANDF_CEN2	IOMUX_PAD(0x480, 0x1A0, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D12__SD1_CD	IOMUX_PAD(0x480, 0x1A0, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D12__SD4_D2	IOMUX_PAD(0x480, 0x1A0, 4, 0x758, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D12__KEY_COL6	IOMUX_PAD(0x480, 0x1A0, 5, 0x798, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D12__FEC_RDAT0	IOMUX_PAD(0x480, 0x1A0, 6, 0x778, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D13__DISP_D13	IOMUX_PAD(0x484, 0x1A4, 0, 0x730, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D13__GPIO_2_13	IOMUX_PAD(0x484, 0x1A4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D13__NANDF_CEN3	IOMUX_PAD(0x484, 0x1A4, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D13__SD3_CD	IOMUX_PAD(0x484, 0x1A4, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D13__SD4_D3	IOMUX_PAD(0x484, 0x1A4, 4, 0x75c, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D13__KEY_ROW6	IOMUX_PAD(0x484, 0x1A4, 5, 0x7a8, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D13__FEC_TX_EN	IOMUX_PAD(0x484, 0x1A4, 6, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D14__DISP_D14	IOMUX_PAD(0x488, 0x1A8, 0, 0x734, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D14__GPIO_2_14	IOMUX_PAD(0x488, 0x1A8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D14__NANDF_RDY0	IOMUX_PAD(0x488, 0x1A8, 2, 0x7b4, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D14__SD1_WP	IOMUX_PAD(0x488, 0x1A8, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D14__SD4_WP	IOMUX_PAD(0x488, 0x1A8, 4, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D14__KEY_COL7	IOMUX_PAD(0x488, 0x1A8, 5, 0x79c, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D14__FEC_TDAT1	IOMUX_PAD(0x488, 0x1A8, 6, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D15__DISP_D15	IOMUX_PAD(0x48C, 0x1AC, 0, 0x738, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D15__GPIO_2_15	IOMUX_PAD(0x48C, 0x1AC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D15__NANDF_DQS	IOMUX_PAD(0x48C, 0x1AC, 2, 0x7b0, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D15__SD3_RST	IOMUX_PAD(0x48C, 0x1AC, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D15__SD4_CD	IOMUX_PAD(0x48C, 0x1AC, 4, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D15__KEY_ROW7	IOMUX_PAD(0x48C, 0x1AC, 5, 0x7ac, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D15__FEC_TDAT0	IOMUX_PAD(0x48C, 0x1AC, 6, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D0__EPDC_D0	IOMUX_PAD(0x54C, 0x1B0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D0__GPIO_3_0	IOMUX_PAD(0x54C, 0x1B0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D0__WEIM_D0	IOMUX_PAD(0x54C, 0x1B0, 2, 0x7ec, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D0__ELCDIF_RS	IOMUX_PAD(0x54C, 0x1B0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_D0__ELCDIF_PIXCLK	IOMUX_PAD(0x54C, 0x1B0, 4, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D1__EPDC_D1	IOMUX_PAD(0x550, 0x1B4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D1__GPIO_3_1	IOMUX_PAD(0x550, 0x1B4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D1__WEIM_D1	IOMUX_PAD(0x550, 0x1B4, 2, 0x7f0, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D1__ELCDIF_CS	IOMUX_PAD(0x550, 0x1B4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_D1__ELCDIF_EN	IOMUX_PAD(0x550, 0x1B4, 4, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D2__EPDC_D2	IOMUX_PAD(0x554, 0x1B8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D2__GPIO_3_2	IOMUX_PAD(0x554, 0x1B8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D2__WEIM_D2	IOMUX_PAD(0x554, 0x1B8, 2, 0x7f4, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D2__ELCDIF_WR	IOMUX_PAD(0x554, 0x1B8, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_D2__ELCDIF_VSYNC	IOMUX_PAD(0x554, 0x1B8, 4, 0x73c, 2, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D3__EPDC_D3	IOMUX_PAD(0x558, 0x1BC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D3__GPIO_3_3	IOMUX_PAD(0x558, 0x1BC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D3__WEIM_D3	IOMUX_PAD(0x558, 0x1BC, 2, 0x7f8, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D3__ELCDIF_RD	IOMUX_PAD(0x558, 0x1BC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_D3__ELCDIF_HSYNC	IOMUX_PAD(0x558, 0x1BC, 4, 0x6f8, 3, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D4__EPDC_D4	IOMUX_PAD(0x55C, 0x1C0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D4__GPIO_3_4	IOMUX_PAD(0x55C, 0x1C0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D4__WEIM_D4	IOMUX_PAD(0x55C, 0x1C0, 2, 0x7fc, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D5__EPDC_D5	IOMUX_PAD(0x560, 0x1C4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D5__GPIO_3_5	IOMUX_PAD(0x560, 0x1C4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D5__WEIM_D5	IOMUX_PAD(0x560, 0x1C4, 2, 0x800, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D6__EPDC_D6	IOMUX_PAD(0x564, 0x1C8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D6__GPIO_3_6	IOMUX_PAD(0x564, 0x1C8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D6__WEIM_D6	IOMUX_PAD(0x564, 0x1C8, 2, 0x804, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D7__EPDC_D7	IOMUX_PAD(0x568, 0x1CC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D7__GPIO_3_7	IOMUX_PAD(0x568, 0x1CC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D7__WEIM_D7	IOMUX_PAD(0x568, 0x1CC, 2, 0x808, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D8__EPDC_D8	IOMUX_PAD(0x56C, 0x1D0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D8__GPIO_3_8	IOMUX_PAD(0x56C, 0x1D0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D8__WEIM_D8	IOMUX_PAD(0x56C, 0x1D0, 2, 0x80c, 2, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D8__ELCDIF_D24	IOMUX_PAD(0x56C, 0x1D0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D9__EPDC_D9	IOMUX_PAD(0x570, 0x1D4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D9__GPIO_3_9	IOMUX_PAD(0x570, 0x1D4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D9__WEIM_D9	IOMUX_PAD(0x570, 0x1D4, 2, 0x810, 2, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D9__ELCDIF_D25	IOMUX_PAD(0x570, 0x1D4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D10__EPDC_D10	IOMUX_PAD(0x574, 0x1D8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D10__GPIO_3_10	IOMUX_PAD(0x574, 0x1D8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D10__WEIM_D10	IOMUX_PAD(0x574, 0x1D8, 2, 0x814, 2, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D10__ELCDIF_D26	IOMUX_PAD(0x574, 0x1D8, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D11__EPDC_D11	IOMUX_PAD(0x578, 0x1DC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D11__GPIO_3_11	IOMUX_PAD(0x578, 0x1DC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D11__WEIM_D11	IOMUX_PAD(0x578, 0x1DC, 2, 0x818, 2, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D11__ELCDIF_D27	IOMUX_PAD(0x578, 0x1DC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D12__EPDC_D12	IOMUX_PAD(0x57C, 0x1E0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D12__GPIO_3_12	IOMUX_PAD(0x57C, 0x1E0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D12__WEIM_D12	IOMUX_PAD(0x57C, 0x1E0, 2, 0x81c, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D12__ELCDIF_D28	IOMUX_PAD(0x57C, 0x1E0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D13__EPDC_D13	IOMUX_PAD(0x580, 0x1E4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D13__GPIO_3_13	IOMUX_PAD(0x580, 0x1E4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D13__WEIM_D13	IOMUX_PAD(0x580, 0x1E4, 2, 0x820, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D13__ELCDIF_D29	IOMUX_PAD(0x580, 0x1E4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D14__EPDC_D14	IOMUX_PAD(0x584, 0x1E8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D14__GPIO_3_14	IOMUX_PAD(0x584, 0x1E8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D14__WEIM_D14	IOMUX_PAD(0x584, 0x1E8, 2, 0x824, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D14__ELCDIF_D30	IOMUX_PAD(0x584, 0x1E8, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_D14__AUD6_TXD	IOMUX_PAD(0x584, 0x1E8, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D15__EPDC_D15	IOMUX_PAD(0x588, 0x1EC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D15__GPIO_3_15	IOMUX_PAD(0x588, 0x1EC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D15__WEIM_D15	IOMUX_PAD(0x588, 0x1EC, 2, 0x828, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D15__ELCDIF_D31	IOMUX_PAD(0x588, 0x1EC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_D15__AUD6_TXC	IOMUX_PAD(0x588, 0x1EC, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_GDCLK__EPDC_GDCLK	IOMUX_PAD(0x58C, 0x1F0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDCLK__GPIO_3_16	IOMUX_PAD(0x58C, 0x1F0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDCLK__WEIM_D16	IOMUX_PAD(0x58C, 0x1F0, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDCLK__ELCDIF_D16	IOMUX_PAD(0x58C, 0x1F0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_GDCLK__AUD6_TXFS	IOMUX_PAD(0x58C, 0x1F0, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_GDSP__EPDC_GDSP	IOMUX_PAD(0x590, 0x1F4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDSP__GPIO_3_17	IOMUX_PAD(0x590, 0x1F4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDSP__WEIM_D17	IOMUX_PAD(0x590, 0x1F4, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDSP__ELCDIF_D17	IOMUX_PAD(0x590, 0x1F4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_GDSP__AUD6_RXD	IOMUX_PAD(0x590, 0x1F4, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_GDOE__EPDC_GDOE	IOMUX_PAD(0x594, 0x1F8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDOE__GPIO_3_18	IOMUX_PAD(0x594, 0x1F8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDOE__WEIM_D18	IOMUX_PAD(0x594, 0x1F8, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDOE__ELCDIF_D18	IOMUX_PAD(0x594, 0x1F8, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_GDOE__AUD6_RXC	IOMUX_PAD(0x594, 0x1F8, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_GDRL__EPDC_GDRL	IOMUX_PAD(0x598, 0x1FC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDRL__GPIO_3_19	IOMUX_PAD(0x598, 0x1FC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDRL__WEIM_D19	IOMUX_PAD(0x598, 0x1FC, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDRL__ELCDIF_D19	IOMUX_PAD(0x598, 0x1FC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_GDRL__AUD6_RXFS	IOMUX_PAD(0x598, 0x1FC, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDCLK__EPDC_SDCLK	IOMUX_PAD(0x59C, 0x200, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCLK__GPIO_3_20	IOMUX_PAD(0x59C, 0x200, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCLK__WEIM_D20	IOMUX_PAD(0x59C, 0x200, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCLK__ELCDIF_D20	IOMUX_PAD(0x59C, 0x200, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCLK__AUD5_TXD	IOMUX_PAD(0x59C, 0x200, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDOEZ__EPDC_SDOEZ	IOMUX_PAD(0x5A0, 0x204, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOEZ__GPIO_3_21	IOMUX_PAD(0x5A0, 0x204, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOEZ__WEIM_D21	IOMUX_PAD(0x5A0, 0x204, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOEZ__ELCDIF_D21	IOMUX_PAD(0x5A0, 0x204, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOEZ__AUD5_TXC	IOMUX_PAD(0x5A0, 0x204, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDOED__EPDC_SDOED	IOMUX_PAD(0x5A4, 0x208, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOED__GPIO_3_22	IOMUX_PAD(0x5A4, 0x208, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOED__WEIM_D22	IOMUX_PAD(0x5A4, 0x208, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOED__ELCDIF_D22	IOMUX_PAD(0x5A4, 0x208, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOED__AUD5_TXFS	IOMUX_PAD(0x5A4, 0x208, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDOE__EPDC_SDOE	IOMUX_PAD(0x5A8, 0x20C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOE__GPIO_3_23	IOMUX_PAD(0x5A8, 0x20C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOE__WEIM_D23	IOMUX_PAD(0x5A8, 0x20C, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOE__ELCDIF_D23	IOMUX_PAD(0x5A8, 0x20C, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOE__AUD5_RXD	IOMUX_PAD(0x5A8, 0x20C, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDLE__EPDC_SDLE	IOMUX_PAD(0x5AC, 0x210, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDLE__GPIO_3_24	IOMUX_PAD(0x5AC, 0x210, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDLE__WEIM_D24	IOMUX_PAD(0x5AC, 0x210, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDLE__ELCDIF_D8	IOMUX_PAD(0x5AC, 0x210, 3, 0x71c, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_SDLE__AUD5_RXC	IOMUX_PAD(0x5AC, 0x210, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDCLKN__EPDC_SDCLKN	IOMUX_PAD(0x5B0, 0x214, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCLKN__GPIO_3_25		IOMUX_PAD(0x5B0, 0x214, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCLKN__WEIM_D25		IOMUX_PAD(0x5B0, 0x214, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCLKN__ELCDIF_D9		IOMUX_PAD(0x5B0, 0x214, 3, 0x720, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCLKN__AUD5_RXFS		IOMUX_PAD(0x5B0, 0x214, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDSHR__EPDC_SDSHR	IOMUX_PAD(0x5B4, 0x218, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDSHR__GPIO_3_26	IOMUX_PAD(0x5B4, 0x218, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDSHR__WEIM_D26	IOMUX_PAD(0x5B4, 0x218, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDSHR__ELCDIF_D10	IOMUX_PAD(0x5B4, 0x218, 3, 0x724, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_SDSHR__AUD4_TXD	IOMUX_PAD(0x5B4, 0x218, 4, 0x6c8, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_PWRCOM__EPDC_PWRCOM	IOMUX_PAD(0x5B8, 0x21C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCOM__GPIO_3_27		IOMUX_PAD(0x5B8, 0x21C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCOM__WEIM_D27		IOMUX_PAD(0x5B8, 0x21C, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCOM__ELCDIF_D11	IOMUX_PAD(0x5B8, 0x21C, 3, 0x728, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCOM__AUD4_TXC		IOMUX_PAD(0x5B8, 0x21C, 4, 0x6d4, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_PWRSTAT__EPDC_PWRSTAT	IOMUX_PAD(0x5BC, 0x220, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRSTAT__GPIO_3_28	IOMUX_PAD(0x5BC, 0x220, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRSTAT__WEIM_D28		IOMUX_PAD(0x5BC, 0x220, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRSTAT__ELCDIF_D12	IOMUX_PAD(0x5BC, 0x220, 3, 0x72c, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRSTAT__AUD4_TXFS	IOMUX_PAD(0x5BC, 0x220, 4, 0x6d8, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_PWRCTRL0__EPDC_PWRCTRL0	IOMUX_PAD(0x5C0, 0x224, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL0__GPIO_3_29	IOMUX_PAD(0x5C0, 0x224, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL0__WEIM_D29	IOMUX_PAD(0x5C0, 0x224, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL0__ELCDIF_D13	IOMUX_PAD(0x5C0, 0x224, 3, 0x730, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL0__AUD4_RXD	IOMUX_PAD(0x5C0, 0x224, 4, 0x6c4, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_PWRCTRL1__EPDC_PWRCTRL1	IOMUX_PAD(0x5C4, 0x228, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL1__GPIO_3_30	IOMUX_PAD(0x5C4, 0x228, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL1__WEIM_D30	IOMUX_PAD(0x5C4, 0x228, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL1__ELCDIF_D14	IOMUX_PAD(0x5C4, 0x228, 3, 0x734, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL1__AUD4_RXC	IOMUX_PAD(0x5C4, 0x228, 4, 0x6cc, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_PWRCTRL2__EPDC_PWRCTRL2	IOMUX_PAD(0x5C8, 0x22C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL2__GPIO_3_31	IOMUX_PAD(0x5C8, 0x22C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL2__WEIM_D31	IOMUX_PAD(0x5C8, 0x22C, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL2__ELCDIF_D15	IOMUX_PAD(0x5C8, 0x22C, 3, 0x738, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL2__AUD4_RXFS	IOMUX_PAD(0x5C8, 0x22C, 4, 0x6d0, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL2__SDMA_EXT0	IOMUX_PAD(0x5C8, 0x22C, 6, 0x7b8, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_PWRCTRL3__PWRCTRL3	IOMUX_PAD(0x5CC, 0x230, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL3__GPIO_4_20	IOMUX_PAD(0x5CC, 0x230, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL3__WEIM_EB2	IOMUX_PAD(0x5CC, 0x230, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL3__SDMA_EXT1	IOMUX_PAD(0x5CC, 0x230, 6, 0x7bc, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_VCOM0__EPDC_VCOM0	IOMUX_PAD(0x5D0, 0x234, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_VCOM0__GPIO_4_21	IOMUX_PAD(0x5D0, 0x234, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_VCOM0__WEIM_EB3	IOMUX_PAD(0x5D0, 0x234, 2, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_VCOM1__EPDC_VCOM1	IOMUX_PAD(0x5D4, 0x238, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_VCOM1__GPIO_4_22	IOMUX_PAD(0x5D4, 0x238, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_VCOM1__WEIM_CS3	IOMUX_PAD(0x5D4, 0x238, 2, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_BDR0__EPDC_BDR0	IOMUX_PAD(0x5D8, 0x23C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_BDR0__GPIO_4_23	IOMUX_PAD(0x5D8, 0x23C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_BDR0__ELCDIF_D7	IOMUX_PAD(0x5D8, 0x23C, 3, 0x718, 1, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_BDR1__EPDC_BDR1	IOMUX_PAD(0x5DC, 0x240, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_BDR1__GPIO_4_24	IOMUX_PAD(0x5DC, 0x240, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_BDR1__ELCDIF_D6	IOMUX_PAD(0x5DC, 0x240, 3, 0x714, 1, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDCE0__EPDC_SDCE0	IOMUX_PAD(0x5E0, 0x244, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE0__GPIO_4_25	IOMUX_PAD(0x5E0, 0x244, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE0__ELCDIF_D5	IOMUX_PAD(0x5E0, 0x244, 3, 0x710, 1, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDCE1__EPDC_SDCE1	IOMUX_PAD(0x5E4, 0x248, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE1__GPIO_4_26	IOMUX_PAD(0x5E4, 0x248, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE1__ELCDIF_D4	IOMUX_PAD(0x5E4, 0x248, 2, 0x70c, 1, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDCE2__EPDC_SDCE2		IOMUX_PAD(0x5E8, 0x24C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE2__GPIO_4_27		IOMUX_PAD(0x5E8, 0x24C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE2__ELCDIF_DAT3	IOMUX_PAD(0x5E8, 0x24C, 3, 0x708, 1, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDCE3__EPDC_SDCE3	IOMUX_PAD(0x5EC, 0x250, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE3__GPIO_4_28	IOMUX_PAD(0x5EC, 0x250, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE3__ELCDIF_D2	IOMUX_PAD(0x5EC, 0x250, 3, 0x704, 1, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDCE4__EPDC_SDCE4	IOMUX_PAD(0x5F0, 0x254, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE4__GPIO_4_29	IOMUX_PAD(0x5F0, 0x254, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE4__ELCDIF_D1	IOMUX_PAD(0x5F0, 0x254, 3, 0x700, 1, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDCE5__EPDC_SDCE5	IOMUX_PAD(0x5F4, 0x258, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE5__GPIO_4_30	IOMUX_PAD(0x5F4, 0x258, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE5__ELCDIF_D0	IOMUX_PAD(0x5F4, 0x258, 3, 0x6fc, 1, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EIM_DA0__WEIM_A0	IOMUX_PAD(0x5F8, 0x25C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA0__GPIO_1_0	IOMUX_PAD(0x5F8, 0x25C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA0__KEY_COL4	IOMUX_PAD(0x5f8, 0x25C, 3, 0x790, 2, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_DA1__WEIM_A1	IOMUX_PAD(0x5FC, 0x260, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA1__GPIO_1_1	IOMUX_PAD(0x5FC, 0x260, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA1__KEY_ROW4	IOMUX_PAD(0x5fc, 0x260, 3, 0x7a0, 2, MX50_KEYPAD_CTRL)
-
-#define MX50_PAD_EIM_DA2__WEIM_A2	IOMUX_PAD(0x600, 0x264, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA2__GPIO_1_2	IOMUX_PAD(0x600, 0x264, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA2__KEY_COL5	IOMUX_PAD(0x600, 0x264, 3, 0x794, 2, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_DA3__WEIM_A3	IOMUX_PAD(0x604, 0x268, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA3__GPIO_1_3	IOMUX_PAD(0x604, 0x268, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA3__KEY_ROW5	IOMUX_PAD(0x604, 0x268, 3, 0x7a4, 2, MX50_KEYPAD_CTRL)
-
-#define MX50_PAD_EIM_DA4__WEIM_A4	IOMUX_PAD(0x608, 0x26C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA4__GPIO_1_4	IOMUX_PAD(0x608, 0x26C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA4__KEY_COL6	IOMUX_PAD(0x608, 0x26C, 3, 0x798, 2, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_DA5__WEIM_A5	IOMUX_PAD(0x60C, 0x270, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA5__GPIO_1_5	IOMUX_PAD(0x60C, 0x270, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA5__KEY_ROW6	IOMUX_PAD(0x60C, 0x270, 3, 0x7a8, 2, MX50_KEYPAD_CTRL)
-
-#define MX50_PAD_EIM_DA6__WEIM_A6	IOMUX_PAD(0x610, 0x274, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA6__GPIO_1_6	IOMUX_PAD(0x610, 0x274, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA6__KEY_COL7	IOMUX_PAD(0x610, 0x274, 3, 0x79c, 2, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_DA7__WEIM_A7	IOMUX_PAD(0x614, 0x278, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA7__GPIO_1_7	IOMUX_PAD(0x614, 0x278, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA7__KEY_ROW7	IOMUX_PAD(0x614, 0x278, 3, 0x7ac, 2, MX50_KEYPAD_CTRL)
-
-#define MX50_PAD_EIM_DA8__WEIM_A8	IOMUX_PAD(0x618, 0x27C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA8__GPIO_1_8	IOMUX_PAD(0x618, 0x27C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_EIM_DA8__NANDF_CLE	IOMUX_PAD(0x618, 0x27C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_EIM_DA9__WEIM_A9	IOMUX_PAD(0x61C, 0x280, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA9__GPIO_1_9	IOMUX_PAD(0x61C, 0x280, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_EIM_DA9__NANDF_ALE	IOMUX_PAD(0x61C, 0x280, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_EIM_DA10__WEIM_A10	IOMUX_PAD(0x620, 0x284, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA10__GPIO_1_10	IOMUX_PAD(0x620, 0x284, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_EIM_DA10__NANDF_CE0	IOMUX_PAD(0x620, 0x284, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_EIM_DA11__WEIM_A11	IOMUX_PAD(0x624, 0x288, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA11__GPIO_1_11	IOMUX_PAD(0x624, 0x288, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_EIM_DA11__NANDF_CE1	IOMUX_PAD(0x624, 0x288, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_EIM_DA12__WEIM_A12	IOMUX_PAD(0x628, 0x28C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA12__GPIO_1_12	IOMUX_PAD(0x628, 0x28C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_EIM_DA12__NANDF_CE2	IOMUX_PAD(0x628, 0x28C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_EIM_DA12__EPDC_SDCE6	IOMUX_PAD(0x628, 0x28C, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_DA13__WEIM_A13	IOMUX_PAD(0x62C, 0x290, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA13__GPIO_1_13	IOMUX_PAD(0x62C, 0x290, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_EIM_DA13__NANDF_CE3	IOMUX_PAD(0x62C, 0x290, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PIN_EIM_DA13__EPDC_SDCE7	IOMUX_PAD(0x62C, 0x290, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_DA14__WEIM_A14	IOMUX_PAD(0x630, 0x294, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA14__GPIO_1_14	IOMUX_PAD(0x630, 0x294, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA14__NANDF_READY	IOMUX_PAD(0x630, 0x294, 2, 0x7B4, 2, PAD_CTL_PKE | \
-							PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
-#define MX50_PAD_EIM_DA14__EPDC_SDCE8	IOMUX_PAD(0x630, 0x294, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_DA15__WEIM_A15	IOMUX_PAD(0x634, 0x298, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA15__GPIO_1_15	IOMUX_PAD(0x634, 0x298, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_EIM_DA15__NANDF_DQS	IOMUX_PAD(0x634, 0x298, 2, 0x7B0, 2, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_EIM_DA15__EPDC_SDCE9	IOMUX_PAD(0x634, 0x298, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_CS2__WEIM_CS2	IOMUX_PAD(0x638, 0x29C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_CS2__GPIO_1_16	IOMUX_PAD(0x638, 0x29C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_CS2__WEIM_A27	IOMUX_PAD(0x638, 0x29C, 2, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_CS1__WEIM_CS1	IOMUX_PAD(0x63C, 0x2A0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_CS1__GPIO_1_17	IOMUX_PAD(0x63C, 0x2A0, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_CS0__WEIM_CS0	IOMUX_PAD(0x640, 0x2A4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_CS0__GPIO_1_18	IOMUX_PAD(0x640, 0x2A4, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_EB0__WEIM_EB0	IOMUX_PAD(0x644, 0x2A8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_EB0__GPIO_1_19	IOMUX_PAD(0x644, 0x2A8, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_EB1__WEIM_EB1	IOMUX_PAD(0x648, 0x2AC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_EB1__GPIO_1_20	IOMUX_PAD(0x648, 0x2AC, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_WAIT__WEIM_WAIT	IOMUX_PAD(0x64C, 0x2B0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_WAIT__GPIO_1_21	IOMUX_PAD(0x64C, 0x2B0, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_BCLK__WEIM_BCLK	IOMUX_PAD(0x650, 0x2B4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_BCLK__GPIO_1_22	IOMUX_PAD(0x650, 0x2B4, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_RDY__WEIM_RDY	IOMUX_PAD(0x654, 0x2B8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_RDY__GPIO_1_23	IOMUX_PAD(0x654, 0x2B8, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_OE__WEIM_OE	IOMUX_PAD(0x658, 0x2BC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_OE__GPIO_1_24	IOMUX_PAD(0x658, 0x2BC, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_RW__WEIM_RW	IOMUX_PAD(0x65C, 0x2C0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_RW__GPIO_1_25	IOMUX_PAD(0x65C, 0x2C0, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_LBA__WEIM_LBA	IOMUX_PAD(0x660, 0x2C4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_LBA__GPIO_1_26	IOMUX_PAD(0x660, 0x2C4, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_CRE__WEIM_CRE	IOMUX_PAD(0x664, 0x2C8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_CRE__GPIO_1_27	IOMUX_PAD(0x664, 0x2C8, 1, 0x0, 0, NO_PAD_CTRL)
-
-#endif /* __MACH_IOMUX_MX50_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
deleted file mode 100644
index 2623e7a..0000000
--- a/arch/arm/plat-mxc/include/mach/iomux-mx51.h
+++ /dev/null
@@ -1,827 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __MACH_IOMUX_MX51_H__
-#define __MACH_IOMUX_MX51_H__
-
-#include <mach/iomux-v3.h>
-#define __NA_	0x000
-
-
-/* Pad control groupings */
-#define MX51_UART_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_DSE_HIGH | \
-				PAD_CTL_HYS | PAD_CTL_SRE_FAST)
-#define MX51_I2C_PAD_CTRL	(PAD_CTL_SRE_FAST | PAD_CTL_ODE | \
-				PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP | \
-				PAD_CTL_HYS)
-#define MX51_ESDHC_PAD_CTRL	(PAD_CTL_SRE_FAST | PAD_CTL_ODE | \
-				PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP | \
-				PAD_CTL_HYS)
-#define MX51_USBH1_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_SRE_FAST | \
-				PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP | \
-				PAD_CTL_HYS | PAD_CTL_PUE)
-#define MX51_ECSPI_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_HYS | \
-				PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST)
-#define MX51_SDHCI_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \
-				PAD_CTL_PUS_47K_UP | PAD_CTL_PUE | \
-				PAD_CTL_SRE_FAST | PAD_CTL_DVS)
-#define MX51_GPIO_PAD_CTRL	(PAD_CTL_DSE_HIGH | PAD_CTL_PKE | PAD_CTL_SRE_FAST)
-
-#define MX51_PAD_CTRL_2		(PAD_CTL_PKE | PAD_CTL_HYS)
-#define MX51_PAD_CTRL_3		(PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
-#define MX51_PAD_CTRL_4		(PAD_CTL_PKE | PAD_CTL_DVS | PAD_CTL_HYS)
-#define MX51_PAD_CTRL_5		(PAD_CTL_DVS | PAD_CTL_DSE_HIGH)
-
-/*
- * The naming convention for the pad modes is MX51_PAD_<padname>__<padmode>
- * If <padname> or <padmode> refers to a GPIO, it is named GPIO<unit>_<num>
- * See also iomux-v3.h
- */
-
-/* Raw pin modes without pad control */
-/*							  PAD    MUX ALT INPSE PATH PADCTRL */
-
-/* The same pins as above but with the default pad control values applied */
-#define MX51_PAD_EIM_D16__AUD4_RXFS		IOMUX_PAD(0x3f0, 0x05c, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D16__AUD5_TXD		IOMUX_PAD(0x3f0, 0x05c, 7, 0x8d8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D16__EIM_D16		IOMUX_PAD(0x3f0, 0x05c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D16__GPIO2_0		IOMUX_PAD(0x3f0, 0x05c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D16__I2C1_SDA		IOMUX_PAD(0x3f0, 0x05c, 0x14, 0x9b4, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_EIM_D16__UART2_CTS		IOMUX_PAD(0x3f0, 0x05c, 3, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D16__USBH2_DATA0		IOMUX_PAD(0x3f0, 0x05c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D17__AUD5_RXD		IOMUX_PAD(0x3f4, 0x060, 7, 0x8d4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D17__EIM_D17		IOMUX_PAD(0x3f4, 0x060, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D17__GPIO2_1		IOMUX_PAD(0x3f4, 0x060, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D17__UART2_RXD		IOMUX_PAD(0x3f4, 0x060, 3, 0x9ec, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D17__UART3_CTS		IOMUX_PAD(0x3f4, 0x060, 4, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D17__USBH2_DATA1		IOMUX_PAD(0x3f4, 0x060, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D18__AUD5_TXC		IOMUX_PAD(0x3f8, 0x064, 7, 0x8e4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D18__EIM_D18		IOMUX_PAD(0x3f8, 0x064, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D18__GPIO2_2		IOMUX_PAD(0x3f8, 0x064, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D18__UART2_TXD		IOMUX_PAD(0x3f8, 0x064, 3, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D18__UART3_RTS		IOMUX_PAD(0x3f8, 0x064, 4, 0x9f0, 1, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D18__USBH2_DATA2		IOMUX_PAD(0x3f8, 0x064, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__AUD4_RXC		IOMUX_PAD(0x3fc, 0x068, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__AUD5_TXFS		IOMUX_PAD(0x3fc, 0x068, 7, 0x8e8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__EIM_D19		IOMUX_PAD(0x3fc, 0x068, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__GPIO2_3		IOMUX_PAD(0x3fc, 0x068, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__I2C1_SCL		IOMUX_PAD(0x3fc, 0x068, 0x14, 0x9b0, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_EIM_D19__UART2_RTS		IOMUX_PAD(0x3fc, 0x068, 3, 0x9e8, 1, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D19__USBH2_DATA3		IOMUX_PAD(0x3fc, 0x068, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D20__AUD4_TXD		IOMUX_PAD(0x400, 0x06c, 5, 0x8c8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D20__EIM_D20		IOMUX_PAD(0x400, 0x06c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D20__GPIO2_4		IOMUX_PAD(0x400, 0x06c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D20__SRTC_ALARM_DEB	IOMUX_PAD(0x400, 0x06c, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D20__USBH2_DATA4		IOMUX_PAD(0x400, 0x06c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D21__AUD4_RXD		IOMUX_PAD(0x404, 0x070, 5, 0x8c4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D21__EIM_D21		IOMUX_PAD(0x404, 0x070, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D21__GPIO2_5		IOMUX_PAD(0x404, 0x070, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D21__SRTC_ALARM_DEB	IOMUX_PAD(0x404, 0x070, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D21__USBH2_DATA5		IOMUX_PAD(0x404, 0x070, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D22__AUD4_TXC		IOMUX_PAD(0x408, 0x074, 5, 0x8cc, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D22__EIM_D22		IOMUX_PAD(0x408, 0x074, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D22__GPIO2_6		IOMUX_PAD(0x408, 0x074, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D22__USBH2_DATA6		IOMUX_PAD(0x408, 0x074, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D23__AUD4_TXFS		IOMUX_PAD(0x40c, 0x078, 5, 0x8d0, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D23__EIM_D23		IOMUX_PAD(0x40c, 0x078, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D23__GPIO2_7		IOMUX_PAD(0x40c, 0x078, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D23__SPDIF_OUT1		IOMUX_PAD(0x40c, 0x078, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D23__USBH2_DATA7		IOMUX_PAD(0x40c, 0x078, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D24__AUD6_RXFS		IOMUX_PAD(0x410, 0x07c, 5, 0x8f8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D24__EIM_D24		IOMUX_PAD(0x410, 0x07c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D24__GPIO2_8		IOMUX_PAD(0x410, 0x07c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D24__I2C2_SDA		IOMUX_PAD(0x410, 0x07c, 0x14, 0x9bc, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_EIM_D24__UART3_CTS		IOMUX_PAD(0x410, 0x07c, 3, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D24__USBOTG_DATA0		IOMUX_PAD(0x410, 0x07c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D25__EIM_D25		IOMUX_PAD(0x414, 0x080, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D25__KEY_COL6		IOMUX_PAD(0x414, 0x080, 1, 0x9c8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D25__UART2_CTS		IOMUX_PAD(0x414, 0x080, 4, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D25__UART3_RXD		IOMUX_PAD(0x414, 0x080, 3, 0x9f4, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D25__USBOTG_DATA1		IOMUX_PAD(0x414, 0x080, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D25__GPT_CMPOUT1		IOMUX_PAD(0x414, 0x080, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D26__EIM_D26		IOMUX_PAD(0x418, 0x084, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D26__KEY_COL7		IOMUX_PAD(0x418, 0x084, 1, 0x9cc, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D26__UART2_RTS		IOMUX_PAD(0x418, 0x084, 4, 0x9e8, 3, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D26__UART3_TXD		IOMUX_PAD(0x418, 0x084, 3, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D26__USBOTG_DATA2		IOMUX_PAD(0x418, 0x084, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D26__GPT_CMPOUT2		IOMUX_PAD(0x418, 0x084, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D27__AUD6_RXC		IOMUX_PAD(0x41c, 0x088, 5, 0x8f4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D27__EIM_D27		IOMUX_PAD(0x41c, 0x088, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D27__GPIO2_9		IOMUX_PAD(0x41c, 0x088, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D27__I2C2_SCL		IOMUX_PAD(0x41c, 0x088, 0x14, 0x9b8, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_EIM_D27__UART3_RTS		IOMUX_PAD(0x41c, 0x088, 3, 0x9f0, 3, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D27__USBOTG_DATA3		IOMUX_PAD(0x41c, 0x088, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D28__AUD6_TXD		IOMUX_PAD(0x420, 0x08c, 5, 0x8f0, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D28__EIM_D28		IOMUX_PAD(0x420, 0x08c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D28__KEY_ROW4		IOMUX_PAD(0x420, 0x08c, 1, 0x9d0, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D28__USBOTG_DATA4		IOMUX_PAD(0x420, 0x08c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D29__AUD6_RXD		IOMUX_PAD(0x424, 0x090, 5, 0x8ec, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D29__EIM_D29		IOMUX_PAD(0x424, 0x090, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D29__KEY_ROW5		IOMUX_PAD(0x424, 0x090, 1, 0x9d4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D29__USBOTG_DATA5		IOMUX_PAD(0x424, 0x090, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D30__AUD6_TXC		IOMUX_PAD(0x428, 0x094, 5, 0x8fc, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D30__EIM_D30		IOMUX_PAD(0x428, 0x094, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D30__KEY_ROW6		IOMUX_PAD(0x428, 0x094, 1, 0x9d8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D30__USBOTG_DATA6		IOMUX_PAD(0x428, 0x094, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D31__AUD6_TXFS		IOMUX_PAD(0x42c, 0x098, 5, 0x900, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D31__EIM_D31		IOMUX_PAD(0x42c, 0x098, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D31__KEY_ROW7		IOMUX_PAD(0x42c, 0x098, 1, 0x9dc, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D31__USBOTG_DATA7		IOMUX_PAD(0x42c, 0x098, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A16__EIM_A16		IOMUX_PAD(0x430, 0x09c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A16__GPIO2_10		IOMUX_PAD(0x430, 0x09c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A16__OSC_FREQ_SEL0		IOMUX_PAD(0x430, 0x09c, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A17__EIM_A17		IOMUX_PAD(0x434, 0x0a0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A17__GPIO2_11		IOMUX_PAD(0x434, 0x0a0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A17__OSC_FREQ_SEL1		IOMUX_PAD(0x434, 0x0a0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A18__BOOT_LPB0		IOMUX_PAD(0x438, 0x0a4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A18__EIM_A18		IOMUX_PAD(0x438, 0x0a4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A18__GPIO2_12		IOMUX_PAD(0x438, 0x0a4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A19__BOOT_LPB1		IOMUX_PAD(0x43c, 0x0a8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A19__EIM_A19		IOMUX_PAD(0x43c, 0x0a8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A19__GPIO2_13		IOMUX_PAD(0x43c, 0x0a8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A20__BOOT_UART_SRC0	IOMUX_PAD(0x440, 0x0ac, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A20__EIM_A20		IOMUX_PAD(0x440, 0x0ac, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A20__GPIO2_14		IOMUX_PAD(0x440, 0x0ac, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A21__BOOT_UART_SRC1	IOMUX_PAD(0x444, 0x0b0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A21__EIM_A21		IOMUX_PAD(0x444, 0x0b0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A21__GPIO2_15		IOMUX_PAD(0x444, 0x0b0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A22__EIM_A22		IOMUX_PAD(0x448, 0x0b4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A22__GPIO2_16		IOMUX_PAD(0x448, 0x0b4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A23__BOOT_HPN_EN		IOMUX_PAD(0x44c, 0x0b8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A23__EIM_A23		IOMUX_PAD(0x44c, 0x0b8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A23__GPIO2_17		IOMUX_PAD(0x44c, 0x0b8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A24__EIM_A24		IOMUX_PAD(0x450, 0x0bc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A24__GPIO2_18		IOMUX_PAD(0x450, 0x0bc, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A24__USBH2_CLK		IOMUX_PAD(0x450, 0x0bc, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A25__DISP1_PIN4		IOMUX_PAD(0x454, 0x0c0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A25__EIM_A25		IOMUX_PAD(0x454, 0x0c0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A25__GPIO2_19		IOMUX_PAD(0x454, 0x0c0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A25__USBH2_DIR		IOMUX_PAD(0x454, 0x0c0, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A26__CSI1_DATA_EN		IOMUX_PAD(0x458, 0x0c4, 5, 0x9a0, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A26__DISP2_EXT_CLK		IOMUX_PAD(0x458, 0x0c4, 6, 0x908, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A26__EIM_A26		IOMUX_PAD(0x458, 0x0c4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A26__GPIO2_20		IOMUX_PAD(0x458, 0x0c4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A26__USBH2_STP		IOMUX_PAD(0x458, 0x0c4, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A27__CSI2_DATA_EN		IOMUX_PAD(0x45c, 0x0c8, 5, 0x99c, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A27__DISP1_PIN1		IOMUX_PAD(0x45c, 0x0c8, 6, 0x9a4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A27__EIM_A27		IOMUX_PAD(0x45c, 0x0c8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A27__GPIO2_21		IOMUX_PAD(0x45c, 0x0c8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A27__USBH2_NXT		IOMUX_PAD(0x45c, 0x0c8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB0__EIM_EB0		IOMUX_PAD(0x460, 0x0cc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB1__EIM_EB1		IOMUX_PAD(0x464, 0x0d0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__AUD5_RXFS		IOMUX_PAD(0x468, 0x0d4, 6, 0x8e0, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__CSI1_D2		IOMUX_PAD(0x468, 0x0d4, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__EIM_EB2		IOMUX_PAD(0x468, 0x0d4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__FEC_MDIO		(IOMUX_PAD(0x468, 0x0d4, 3, 0x954, 0, 0) | \
-		MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP | PAD_CTL_PKE | PAD_CTL_SRE_FAST | \
-		PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS))
-#define MX51_PAD_EIM_EB2__GPIO2_22		IOMUX_PAD(0x468, 0x0d4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__GPT_CMPOUT1		IOMUX_PAD(0x468, 0x0d4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__AUD5_RXC		IOMUX_PAD(0x46c, 0x0d8, 6, 0x8dc, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__CSI1_D3		IOMUX_PAD(0x46c, 0x0d8, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__EIM_EB3		IOMUX_PAD(0x46c, 0x0d8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__FEC_RDATA1		IOMUX_PAD(0x46c, 0x0d8, 3, 0x95c, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__GPIO2_23		IOMUX_PAD(0x46c, 0x0d8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__GPT_CMPOUT2		IOMUX_PAD(0x46c, 0x0d8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_OE__EIM_OE			IOMUX_PAD(0x470, 0x0dc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_OE__GPIO2_24		IOMUX_PAD(0x470, 0x0dc, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS0__EIM_CS0		IOMUX_PAD(0x474, 0x0e0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS0__GPIO2_25		IOMUX_PAD(0x474, 0x0e0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS1__EIM_CS1		IOMUX_PAD(0x478, 0x0e4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS1__GPIO2_26		IOMUX_PAD(0x478, 0x0e4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__AUD5_TXD		IOMUX_PAD(0x47c, 0x0e8, 6, 0x8d8, 1, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__CSI1_D4		IOMUX_PAD(0x47c, 0x0e8, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__EIM_CS2		IOMUX_PAD(0x47c, 0x0e8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__FEC_RDATA2		IOMUX_PAD(0x47c, 0x0e8, 3, 0x960, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__GPIO2_27		IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__USBOTG_STP		IOMUX_PAD(0x47c, 0x0e8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__AUD5_RXD		IOMUX_PAD(0x480, 0x0ec, 6, 0x8d4, 1, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__CSI1_D5		IOMUX_PAD(0x480, 0x0ec, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__EIM_CS3		IOMUX_PAD(0x480, 0x0ec, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__FEC_RDATA3		IOMUX_PAD(0x480, 0x0ec, 3, 0x964, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__GPIO2_28		IOMUX_PAD(0x480, 0x0ec, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__USBOTG_NXT		IOMUX_PAD(0x480, 0x0ec, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS4__AUD5_TXC		IOMUX_PAD(0x484, 0x0f0, 6, 0x8e4, 1, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS4__CSI1_D6		IOMUX_PAD(0x484, 0x0f0, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS4__EIM_CS4		IOMUX_PAD(0x484, 0x0f0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS4__FEC_RX_ER		IOMUX_PAD(0x484, 0x0f0, 3, 0x970, 0, MX51_PAD_CTRL_2)
-#define MX51_PAD_EIM_CS4__GPIO2_29		IOMUX_PAD(0x484, 0x0f0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS4__USBOTG_CLK		IOMUX_PAD(0x484, 0x0f0, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__AUD5_TXFS		IOMUX_PAD(0x488, 0x0f4, 6, 0x8e8, 1, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__CSI1_D7		IOMUX_PAD(0x488, 0x0f4, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__DISP1_EXT_CLK		IOMUX_PAD(0x488, 0x0f4, 4, 0x904, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__EIM_CS5		IOMUX_PAD(0x488, 0x0f4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__FEC_CRS		IOMUX_PAD(0x488, 0x0f4, 3, 0x950, 0, MX51_PAD_CTRL_2)
-#define MX51_PAD_EIM_CS5__GPIO2_30		IOMUX_PAD(0x488, 0x0f4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__USBOTG_DIR		IOMUX_PAD(0x488, 0x0f4, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DTACK__EIM_DTACK		IOMUX_PAD(0x48c, 0x0f8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DTACK__GPIO2_31		IOMUX_PAD(0x48c, 0x0f8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_LBA__EIM_LBA		IOMUX_PAD(0x494, 0x0fc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_LBA__GPIO3_1		IOMUX_PAD(0x494, 0x0fc, 1, 0x978, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CRE__EIM_CRE		IOMUX_PAD(0x4a0, 0x100, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CRE__GPIO3_2		IOMUX_PAD(0x4a0, 0x100, 1, 0x97c, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DRAM_CS1__DRAM_CS1		IOMUX_PAD(0x4d0, 0x104, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DRAM_CS1__CCM_CLKO		IOMUX_PAD(0x4d0, 0x104, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WE_B__GPIO3_3		IOMUX_PAD(0x4e4, 0x108, 3, 0x980, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_WE_B__NANDF_WE_B		IOMUX_PAD(0x4e4, 0x108, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WE_B__PATA_DIOW		IOMUX_PAD(0x4e4, 0x108, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WE_B__SD3_DATA0		IOMUX_PAD(0x4e4, 0x108, 2, 0x93c, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_RE_B__GPIO3_4		IOMUX_PAD(0x4e8, 0x10c, 3, 0x984, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RE_B__NANDF_RE_B		IOMUX_PAD(0x4e8, 0x10c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RE_B__PATA_DIOR		IOMUX_PAD(0x4e8, 0x10c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RE_B__SD3_DATA1		IOMUX_PAD(0x4e8, 0x10c, 2, 0x940, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_ALE__GPIO3_5		IOMUX_PAD(0x4ec, 0x110, 3, 0x988, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_ALE__NANDF_ALE		IOMUX_PAD(0x4ec, 0x110, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_ALE__PATA_BUFFER_EN	IOMUX_PAD(0x4ec, 0x110, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CLE__GPIO3_6		IOMUX_PAD(0x4f0, 0x114, 3, 0x98c, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CLE__NANDF_CLE		IOMUX_PAD(0x4f0, 0x114, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CLE__PATA_RESET_B	IOMUX_PAD(0x4f0, 0x114, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WP_B__GPIO3_7		IOMUX_PAD(0x4f4, 0x118, 3, 0x990, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_WP_B__NANDF_WP_B		IOMUX_PAD(0x4f4, 0x118, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WP_B__PATA_DMACK		IOMUX_PAD(0x4f4, 0x118, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WP_B__SD3_DATA2		IOMUX_PAD(0x4f4, 0x118, 2, 0x944, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB0__ECSPI2_SS1		IOMUX_PAD(0x4f8, 0x11c, 5, 0x930, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB0__GPIO3_8		IOMUX_PAD(0x4f8, 0x11c, 3, 0x994, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB0__NANDF_RB0		IOMUX_PAD(0x4f8, 0x11c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB0__PATA_DMARQ		IOMUX_PAD(0x4f8, 0x11c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB0__SD3_DATA3		IOMUX_PAD(0x4f8, 0x11c, 2, 0x948, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__CSPI_MOSI		IOMUX_PAD(0x4fc, 0x120, 6, 0x91c, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__ECSPI2_RDY		IOMUX_PAD(0x4fc, 0x120, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__GPIO3_9		IOMUX_PAD(0x4fc, 0x120, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__NANDF_RB1		IOMUX_PAD(0x4fc, 0x120, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__PATA_IORDY		IOMUX_PAD(0x4fc, 0x120, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__GPT_CMPOUT2		IOMUX_PAD(0x4fc, 0x120, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__SD4_CMD		IOMUX_PAD(0x4fc, 0x120, 0x15, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__DISP2_WAIT		IOMUX_PAD(0x500, 0x124, 5, 0x9a8, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK		IOMUX_PAD(0x500, 0x124, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__FEC_COL		IOMUX_PAD(0x500, 0x124, 1, 0x94c, 0, MX51_PAD_CTRL_2)
-#define MX51_PAD_NANDF_RB2__GPIO3_10		IOMUX_PAD(0x500, 0x124, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__NANDF_RB2		IOMUX_PAD(0x500, 0x124, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__GPT_CMPOUT3		IOMUX_PAD(0x500, 0x124, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__USBH3_H3_DP		IOMUX_PAD(0x500, 0x124, 0x17, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__USBH3_NXT		IOMUX_PAD(0x500, 0x124, 6, 0xa20, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__DISP1_WAIT		IOMUX_PAD(0x504, 0x128, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__ECSPI2_MISO		IOMUX_PAD(0x504, 0x128, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__FEC_RX_CLK		IOMUX_PAD(0x504, 0x128, 1, 0x968, 0, MX51_PAD_CTRL_2)
-#define MX51_PAD_NANDF_RB3__GPIO3_11		IOMUX_PAD(0x504, 0x128, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__NANDF_RB3		IOMUX_PAD(0x504, 0x128, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__USBH3_CLK		IOMUX_PAD(0x504, 0x128, 6, 0x9f8, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__USBH3_H3_DM		IOMUX_PAD(0x504, 0x128, 0x17, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_NAND__GPIO_NAND		IOMUX_PAD(0x514, 0x12c, 0, 0x998, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_NAND__PATA_INTRQ		IOMUX_PAD(0x514, 0x12c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS0__GPIO3_16		IOMUX_PAD(0x518, 0x130, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS0__NANDF_CS0		IOMUX_PAD(0x518, 0x130, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS1__GPIO3_17		IOMUX_PAD(0x51c, 0x134, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS1__NANDF_CS1		IOMUX_PAD(0x51c, 0x134, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__CSPI_SCLK		IOMUX_PAD(0x520, 0x138, 6, 0x914, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__FEC_TX_ER		IOMUX_PAD(0x520, 0x138, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS2__GPIO3_18		IOMUX_PAD(0x520, 0x138, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__NANDF_CS2		IOMUX_PAD(0x520, 0x138, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__PATA_CS_0		IOMUX_PAD(0x520, 0x138, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__SD4_CLK		IOMUX_PAD(0x520, 0x138, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
-#define MX51_PAD_NANDF_CS2__USBH3_H1_DP		IOMUX_PAD(0x520, 0x138, 0x17, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__FEC_MDC		IOMUX_PAD(0x524, 0x13c, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS3__GPIO3_19		IOMUX_PAD(0x524, 0x13c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__NANDF_CS3		IOMUX_PAD(0x524, 0x13c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__PATA_CS_1		IOMUX_PAD(0x524, 0x13c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__SD4_DAT0		IOMUX_PAD(0x524, 0x13c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__USBH3_H1_DM		IOMUX_PAD(0x524, 0x13c, 0x17, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS4__FEC_TDATA1		IOMUX_PAD(0x528, 0x140, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS4__GPIO3_20		IOMUX_PAD(0x528, 0x140, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS4__NANDF_CS4		IOMUX_PAD(0x528, 0x140, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS4__PATA_DA_0		IOMUX_PAD(0x528, 0x140, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS4__SD4_DAT1		IOMUX_PAD(0x528, 0x140, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS4__USBH3_STP		IOMUX_PAD(0x528, 0x140, 7, 0xa24, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS5__FEC_TDATA2		IOMUX_PAD(0x52c, 0x144, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS5__GPIO3_21		IOMUX_PAD(0x52c, 0x144, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS5__NANDF_CS5		IOMUX_PAD(0x52c, 0x144, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS5__PATA_DA_1		IOMUX_PAD(0x52c, 0x144, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS5__SD4_DAT2		IOMUX_PAD(0x52c, 0x144, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS5__USBH3_DIR		IOMUX_PAD(0x52c, 0x144, 7, 0xa1c, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS6__CSPI_SS3		IOMUX_PAD(0x530, 0x148, 7, 0x928, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS6__FEC_TDATA3		IOMUX_PAD(0x530, 0x148, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS6__GPIO3_22		IOMUX_PAD(0x530, 0x148, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS6__NANDF_CS6		IOMUX_PAD(0x530, 0x148, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS6__PATA_DA_2		IOMUX_PAD(0x530, 0x148, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS6__SD4_DAT3		IOMUX_PAD(0x530, 0x148, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS7__FEC_TX_EN		IOMUX_PAD(0x534, 0x14c, 1, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS7__GPIO3_23		IOMUX_PAD(0x534, 0x14c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS7__NANDF_CS7		IOMUX_PAD(0x534, 0x14c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS7__SD3_CLK		IOMUX_PAD(0x534, 0x14c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
-#define MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0	IOMUX_PAD(0x538, 0x150, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK	IOMUX_PAD(0x538, 0x150, 1, 0x974, 0, MX51_PAD_CTRL_4)
-#define MX51_PAD_NANDF_RDY_INT__GPIO3_24	IOMUX_PAD(0x538, 0x150, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT	IOMUX_PAD(0x538, 0x150, 0, 0x938, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RDY_INT__SD3_CMD		IOMUX_PAD(0x538, 0x150, 0x15, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_D15__ECSPI2_MOSI		IOMUX_PAD(0x53c, 0x154, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_D15__GPIO3_25		IOMUX_PAD(0x53c, 0x154, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D15__NANDF_D15		IOMUX_PAD(0x53c, 0x154, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D15__PATA_DATA15		IOMUX_PAD(0x53c, 0x154, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D15__SD3_DAT7		IOMUX_PAD(0x53c, 0x154, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D14__ECSPI2_SS3		IOMUX_PAD(0x540, 0x158, 2, 0x934, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_D14__GPIO3_26		IOMUX_PAD(0x540, 0x158, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D14__NANDF_D14		IOMUX_PAD(0x540, 0x158, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D14__PATA_DATA14		IOMUX_PAD(0x540, 0x158, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D14__SD3_DAT6		IOMUX_PAD(0x540, 0x158, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D13__ECSPI2_SS2		IOMUX_PAD(0x544, 0x15c, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_D13__GPIO3_27		IOMUX_PAD(0x544, 0x15c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D13__NANDF_D13		IOMUX_PAD(0x544, 0x15c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D13__PATA_DATA13		IOMUX_PAD(0x544, 0x15c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D13__SD3_DAT5		IOMUX_PAD(0x544, 0x15c, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D12__ECSPI2_SS1		IOMUX_PAD(0x548, 0x160, 2, 0x930, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_D12__GPIO3_28		IOMUX_PAD(0x548, 0x160, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D12__NANDF_D12		IOMUX_PAD(0x548, 0x160, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D12__PATA_DATA12		IOMUX_PAD(0x548, 0x160, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D12__SD3_DAT4		IOMUX_PAD(0x548, 0x160, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D11__FEC_RX_DV		IOMUX_PAD(0x54c, 0x164, 2, 0x96c, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D11__GPIO3_29		IOMUX_PAD(0x54c, 0x164, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D11__NANDF_D11		IOMUX_PAD(0x54c, 0x164, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D11__PATA_DATA11		IOMUX_PAD(0x54c, 0x164, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D11__SD3_DATA3		IOMUX_PAD(0x54c, 0x164, 5, 0x948, 1, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D10__GPIO3_30		IOMUX_PAD(0x550, 0x168, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D10__NANDF_D10		IOMUX_PAD(0x550, 0x168, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D10__PATA_DATA10		IOMUX_PAD(0x550, 0x168, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D10__SD3_DATA2		IOMUX_PAD(0x550, 0x168, 5, 0x944, 1, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D9__FEC_RDATA0		IOMUX_PAD(0x554, 0x16c, 0x12, 0x958, 0, MX51_PAD_CTRL_4)
-#define MX51_PAD_NANDF_D9__GPIO3_31		IOMUX_PAD(0x554, 0x16c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D9__NANDF_D9		IOMUX_PAD(0x554, 0x16c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D9__PATA_DATA9		IOMUX_PAD(0x554, 0x16c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D9__SD3_DATA1		IOMUX_PAD(0x554, 0x16c, 5, 0x940, 1, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D8__FEC_TDATA0		IOMUX_PAD(0x558, 0x170, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_D8__GPIO4_0		IOMUX_PAD(0x558, 0x170, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D8__NANDF_D8		IOMUX_PAD(0x558, 0x170, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D8__PATA_DATA8		IOMUX_PAD(0x558, 0x170, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D8__SD3_DATA0		IOMUX_PAD(0x558, 0x170, 5, 0x93c, 1, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D7__GPIO4_1		IOMUX_PAD(0x55c, 0x174, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D7__NANDF_D7		IOMUX_PAD(0x55c, 0x174, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D7__PATA_DATA7		IOMUX_PAD(0x55c, 0x174, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D7__USBH3_DATA0		IOMUX_PAD(0x55c, 0x174, 5, 0x9fc, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D6__GPIO4_2		IOMUX_PAD(0x560, 0x178, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D6__NANDF_D6		IOMUX_PAD(0x560, 0x178, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D6__PATA_DATA6		IOMUX_PAD(0x560, 0x178, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D6__SD4_LCTL		IOMUX_PAD(0x560, 0x178, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D6__USBH3_DATA1		IOMUX_PAD(0x560, 0x178, 5, 0xa00, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D5__GPIO4_3		IOMUX_PAD(0x564, 0x17c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D5__NANDF_D5		IOMUX_PAD(0x564, 0x17c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D5__PATA_DATA5		IOMUX_PAD(0x564, 0x17c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D5__SD4_WP		IOMUX_PAD(0x564, 0x17c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D5__USBH3_DATA2		IOMUX_PAD(0x564, 0x17c, 5, 0xa04, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D4__GPIO4_4		IOMUX_PAD(0x568, 0x180, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D4__NANDF_D4		IOMUX_PAD(0x568, 0x180, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D4__PATA_DATA4		IOMUX_PAD(0x568, 0x180, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D4__SD4_CD		IOMUX_PAD(0x568, 0x180, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D4__USBH3_DATA3		IOMUX_PAD(0x568, 0x180, 5, 0xa08, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D3__GPIO4_5		IOMUX_PAD(0x56c, 0x184, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D3__NANDF_D3		IOMUX_PAD(0x56c, 0x184, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D3__PATA_DATA3		IOMUX_PAD(0x56c, 0x184, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D3__SD4_DAT4		IOMUX_PAD(0x56c, 0x184, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D3__USBH3_DATA4		IOMUX_PAD(0x56c, 0x184, 5, 0xa0c, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D2__GPIO4_6		IOMUX_PAD(0x570, 0x188, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D2__NANDF_D2		IOMUX_PAD(0x570, 0x188, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D2__PATA_DATA2		IOMUX_PAD(0x570, 0x188, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D2__SD4_DAT5		IOMUX_PAD(0x570, 0x188, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D2__USBH3_DATA5		IOMUX_PAD(0x570, 0x188, 5, 0xa10, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D1__GPIO4_7		IOMUX_PAD(0x574, 0x18c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D1__NANDF_D1		IOMUX_PAD(0x574, 0x18c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D1__PATA_DATA1		IOMUX_PAD(0x574, 0x18c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D1__SD4_DAT6		IOMUX_PAD(0x574, 0x18c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D1__USBH3_DATA6		IOMUX_PAD(0x574, 0x18c, 5, 0xa14, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D0__GPIO4_8		IOMUX_PAD(0x578, 0x190, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D0__NANDF_D0		IOMUX_PAD(0x578, 0x190, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D0__PATA_DATA0		IOMUX_PAD(0x578, 0x190, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D0__SD4_DAT7		IOMUX_PAD(0x578, 0x190, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D0__USBH3_DATA7		IOMUX_PAD(0x578, 0x190, 5, 0xa18, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D8__CSI1_D8		IOMUX_PAD(0x57c, 0x194, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D8__GPIO3_12		IOMUX_PAD(0x57c, 0x194, 3, 0x998, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI1_D9__CSI1_D9		IOMUX_PAD(0x580, 0x198, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D9__GPIO3_13		IOMUX_PAD(0x580, 0x198, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI1_D10__CSI1_D10		IOMUX_PAD(0x584, 0x19c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D11__CSI1_D11		IOMUX_PAD(0x588, 0x1a0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D12__CSI1_D12		IOMUX_PAD(0x58c, 0x1a4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D13__CSI1_D13		IOMUX_PAD(0x590, 0x1a8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D14__CSI1_D14		IOMUX_PAD(0x594, 0x1ac, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D15__CSI1_D15		IOMUX_PAD(0x598, 0x1b0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D16__CSI1_D16		IOMUX_PAD(0x59c, 0x1b4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D17__CSI1_D17		IOMUX_PAD(0x5a0, 0x1b8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D18__CSI1_D18		IOMUX_PAD(0x5a4, 0x1bc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D19__CSI1_D19		IOMUX_PAD(0x5a8, 0x1c0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_VSYNC__CSI1_VSYNC		IOMUX_PAD(0x5ac, 0x1c4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_VSYNC__GPIO3_14		IOMUX_PAD(0x5ac, 0x1c4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI1_HSYNC__CSI1_HSYNC		IOMUX_PAD(0x5b0, 0x1c8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_HSYNC__GPIO3_15		IOMUX_PAD(0x5b0, 0x1c8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK	IOMUX_PAD(0x5b4, __NA_, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_MCLK__CSI1_MCLK		IOMUX_PAD(0x5b8, __NA_, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D12__CSI2_D12		IOMUX_PAD(0x5bc, 0x1cc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D12__GPIO4_9		IOMUX_PAD(0x5bc, 0x1cc, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_D13__CSI2_D13		IOMUX_PAD(0x5c0, 0x1d0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D13__GPIO4_10		IOMUX_PAD(0x5c0, 0x1d0, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_D14__CSI2_D14		IOMUX_PAD(0x5c4, 0x1d4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D15__CSI2_D15		IOMUX_PAD(0x5c8, 0x1d8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D16__CSI2_D16		IOMUX_PAD(0x5cc, 0x1dc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D17__CSI2_D17		IOMUX_PAD(0x5d0, 0x1e0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D18__CSI2_D18		IOMUX_PAD(0x5d4, 0x1e4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D18__GPIO4_11		IOMUX_PAD(0x5d4, 0x1e4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_D19__CSI2_D19		IOMUX_PAD(0x5d8, 0x1e8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D19__GPIO4_12		IOMUX_PAD(0x5d8, 0x1e8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_VSYNC__CSI2_VSYNC		IOMUX_PAD(0x5dc, 0x1ec, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_VSYNC__GPIO4_13		IOMUX_PAD(0x5dc, 0x1ec, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_HSYNC__CSI2_HSYNC		IOMUX_PAD(0x5e0, 0x1f0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_HSYNC__GPIO4_14		IOMUX_PAD(0x5e0, 0x1f0, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK	IOMUX_PAD(0x5e4, 0x1f4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_PIXCLK__GPIO4_15		IOMUX_PAD(0x5e4, 0x1f4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_I2C1_CLK__GPIO4_16		IOMUX_PAD(0x5e8, 0x1f8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_I2C1_CLK__I2C1_CLK		IOMUX_PAD(0x5e8, 0x1f8, 0x10, __NA_, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_I2C1_DAT__GPIO4_17		IOMUX_PAD(0x5ec, 0x1fc, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_I2C1_DAT__I2C1_DAT		IOMUX_PAD(0x5ec, 0x1fc, 0x10, __NA_, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_TXD__AUD3_TXD		IOMUX_PAD(0x5f0, 0x200, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_TXD__GPIO4_18		IOMUX_PAD(0x5f0, 0x200, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_RXD__AUD3_RXD		IOMUX_PAD(0x5f4, 0x204, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_RXD__GPIO4_19		IOMUX_PAD(0x5f4, 0x204, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_RXD__UART3_RXD		IOMUX_PAD(0x5f4, 0x204, 1, 0x9f4, 2, MX51_UART_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_CK__AUD3_TXC		IOMUX_PAD(0x5f8, 0x208, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_CK__GPIO4_20		IOMUX_PAD(0x5f8, 0x208, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_FS__AUD3_TXFS		IOMUX_PAD(0x5fc, 0x20c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_FS__GPIO4_21		IOMUX_PAD(0x5fc, 0x20c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_FS__UART3_TXD		IOMUX_PAD(0x5fc, 0x20c, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI	IOMUX_PAD(0x600, 0x210, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_MOSI__GPIO4_22		IOMUX_PAD(0x600, 0x210, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_MOSI__I2C1_SDA		IOMUX_PAD(0x600, 0x210, 0x11, 0x9b4, 1, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_CSPI1_MISO__AUD4_RXD		IOMUX_PAD(0x604, 0x214, 1, 0x8c4, 1, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO	IOMUX_PAD(0x604, 0x214, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_MISO__GPIO4_23		IOMUX_PAD(0x604, 0x214, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS0__AUD4_TXC		IOMUX_PAD(0x608, 0x218, 1, 0x8cc, 1, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0		IOMUX_PAD(0x608, 0x218, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS0__GPIO4_24		IOMUX_PAD(0x608, 0x218, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS1__AUD4_TXD		IOMUX_PAD(0x60c, 0x21c, 1, 0x8c8, 1, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1		IOMUX_PAD(0x60c, 0x21c, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS1__GPIO4_25		IOMUX_PAD(0x60c, 0x21c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_RDY__AUD4_TXFS		IOMUX_PAD(0x610, 0x220, 1, 0x8d0, 1, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY		IOMUX_PAD(0x610, 0x220, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_RDY__GPIO4_26		IOMUX_PAD(0x610, 0x220, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK	IOMUX_PAD(0x614, 0x224, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_SCLK__GPIO4_27		IOMUX_PAD(0x614, 0x224, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SCLK__I2C1_SCL		IOMUX_PAD(0x614, 0x224, 0x11, 0x9b0, 1, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_UART1_RXD__GPIO4_28		IOMUX_PAD(0x618, 0x228, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART1_RXD__UART1_RXD		IOMUX_PAD(0x618, 0x228, 0, 0x9e4, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART1_TXD__GPIO4_29		IOMUX_PAD(0x61c, 0x22c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART1_TXD__PWM2_PWMO		IOMUX_PAD(0x61c, 0x22c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART1_TXD__UART1_TXD		IOMUX_PAD(0x61c, 0x22c, 0, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART1_RTS__GPIO4_30		IOMUX_PAD(0x620, 0x230, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART1_RTS__UART1_RTS		IOMUX_PAD(0x620, 0x230, 0, 0x9e0, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART1_CTS__GPIO4_31		IOMUX_PAD(0x624, 0x234, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART1_CTS__UART1_CTS		IOMUX_PAD(0x624, 0x234, 0, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART2_RXD__FIRI_TXD		IOMUX_PAD(0x628, 0x238, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART2_RXD__GPIO1_20		IOMUX_PAD(0x628, 0x238, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART2_RXD__UART2_RXD		IOMUX_PAD(0x628, 0x238, 0, 0x9ec, 2, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART2_TXD__FIRI_RXD		IOMUX_PAD(0x62c, 0x23c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART2_TXD__GPIO1_21		IOMUX_PAD(0x62c, 0x23c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART2_TXD__UART2_TXD		IOMUX_PAD(0x62c, 0x23c, 0, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART3_RXD__CSI1_D0		IOMUX_PAD(0x630, 0x240, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART3_RXD__GPIO1_22		IOMUX_PAD(0x630, 0x240, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART3_RXD__UART1_DTR		IOMUX_PAD(0x630, 0x240, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART3_RXD__UART3_RXD		IOMUX_PAD(0x630, 0x240, 1, 0x9f4, 4, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART3_TXD__CSI1_D1		IOMUX_PAD(0x634, 0x244, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART3_TXD__GPIO1_23		IOMUX_PAD(0x634, 0x244, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART3_TXD__UART1_DSR		IOMUX_PAD(0x634, 0x244, 0, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART3_TXD__UART3_TXD		IOMUX_PAD(0x634, 0x244, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_OWIRE_LINE__GPIO1_24		IOMUX_PAD(0x638, 0x248, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_OWIRE_LINE__OWIRE_LINE		IOMUX_PAD(0x638, 0x248, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_OWIRE_LINE__SPDIF_OUT		IOMUX_PAD(0x638, 0x248, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_ROW0__KEY_ROW0		IOMUX_PAD(0x63c, 0x24c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_ROW1__KEY_ROW1		IOMUX_PAD(0x640, 0x250, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_ROW2__KEY_ROW2		IOMUX_PAD(0x644, 0x254, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_ROW3__KEY_ROW3		IOMUX_PAD(0x648, 0x258, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL0__KEY_COL0		IOMUX_PAD(0x64c, 0x25c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL0__PLL1_BYP		IOMUX_PAD(0x64c, 0x25c, 7, 0x90c, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL1__KEY_COL1		IOMUX_PAD(0x650, 0x260, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL1__PLL2_BYP		IOMUX_PAD(0x650, 0x260, 7, 0x910, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL2__KEY_COL2		IOMUX_PAD(0x654, 0x264, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL2__PLL3_BYP		IOMUX_PAD(0x654, 0x264, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL3__KEY_COL3		IOMUX_PAD(0x658, 0x268, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__I2C2_SCL		IOMUX_PAD(0x65c, 0x26c, 0x13, 0x9b8, 1, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__KEY_COL4		IOMUX_PAD(0x65c, 0x26c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__SPDIF_OUT1		IOMUX_PAD(0x65c, 0x26c, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__UART1_RI		IOMUX_PAD(0x65c, 0x26c, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__UART3_RTS		IOMUX_PAD(0x65c, 0x26c, 2, 0x9f0, 4, MX51_UART_PAD_CTRL)
-#define MX51_PAD_KEY_COL5__I2C2_SDA		IOMUX_PAD(0x660, 0x270, 0x13, 0x9bc, 1, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_KEY_COL5__KEY_COL5		IOMUX_PAD(0x660, 0x270, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL5__UART1_DCD		IOMUX_PAD(0x660, 0x270, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_KEY_COL5__UART3_CTS		IOMUX_PAD(0x660, 0x270, 2, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_CLK__CSPI_SCLK		IOMUX_PAD(0x678, 0x278, 1, 0x914, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_CLK__GPIO1_25		IOMUX_PAD(0x678, 0x278, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_CLK__I2C2_SCL		IOMUX_PAD(0x678, 0x278, 0x15, 0x9b8, 2, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_USBH1_CLK__USBH1_CLK		IOMUX_PAD(0x678, 0x278, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DIR__CSPI_MOSI		IOMUX_PAD(0x67c, 0x27c, 1, 0x91c, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DIR__GPIO1_26		IOMUX_PAD(0x67c, 0x27c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DIR__I2C2_SDA		IOMUX_PAD(0x67c, 0x27c, 0x15, 0x9bc, 2, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_USBH1_DIR__USBH1_DIR		IOMUX_PAD(0x67c, 0x27c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_STP__CSPI_RDY		IOMUX_PAD(0x680, 0x280, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_STP__GPIO1_27		IOMUX_PAD(0x680, 0x280, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_STP__UART3_RXD		IOMUX_PAD(0x680, 0x280, 5, 0x9f4, 6, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_STP__USBH1_STP		IOMUX_PAD(0x680, 0x280, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_NXT__CSPI_MISO		IOMUX_PAD(0x684, 0x284, 1, 0x918, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_NXT__GPIO1_28		IOMUX_PAD(0x684, 0x284, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_NXT__UART3_TXD		IOMUX_PAD(0x684, 0x284, 5, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_NXT__USBH1_NXT		IOMUX_PAD(0x684, 0x284, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA0__GPIO1_11		IOMUX_PAD(0x688, 0x288, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA0__UART2_CTS		IOMUX_PAD(0x688, 0x288, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA0__USBH1_DATA0	IOMUX_PAD(0x688, 0x288, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA1__GPIO1_12		IOMUX_PAD(0x68c, 0x28c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA1__UART2_RXD		IOMUX_PAD(0x68c, 0x28c, 1, 0x9ec, 4, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA1__USBH1_DATA1	IOMUX_PAD(0x68c, 0x28c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA2__GPIO1_13		IOMUX_PAD(0x690, 0x290, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA2__UART2_TXD		IOMUX_PAD(0x690, 0x290, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA2__USBH1_DATA2	IOMUX_PAD(0x690, 0x290, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA3__GPIO1_14		IOMUX_PAD(0x694, 0x294, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA3__UART2_RTS		IOMUX_PAD(0x694, 0x294, 1, 0x9e8, 5, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA3__USBH1_DATA3	IOMUX_PAD(0x694, 0x294, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA4__CSPI_SS0		IOMUX_PAD(0x698, 0x298, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA4__GPIO1_15		IOMUX_PAD(0x698, 0x298, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA4__USBH1_DATA4	IOMUX_PAD(0x698, 0x298, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA5__CSPI_SS1		IOMUX_PAD(0x69c, 0x29c, 1, 0x920, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA5__GPIO1_16		IOMUX_PAD(0x69c, 0x29c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA5__USBH1_DATA5	IOMUX_PAD(0x69c, 0x29c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA6__CSPI_SS3		IOMUX_PAD(0x6a0, 0x2a0, 1, 0x928, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA6__GPIO1_17		IOMUX_PAD(0x6a0, 0x2a0, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA6__USBH1_DATA6	IOMUX_PAD(0x6a0, 0x2a0, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA7__ECSPI1_SS3	IOMUX_PAD(0x6a4, 0x2a4, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA7__ECSPI2_SS3	IOMUX_PAD(0x6a4, 0x2a4, 5, 0x934, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA7__GPIO1_18		IOMUX_PAD(0x6a4, 0x2a4, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA7__USBH1_DATA7	IOMUX_PAD(0x6a4, 0x2a4, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_DI1_PIN11__DI1_PIN11		IOMUX_PAD(0x6a8, 0x2a8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN11__ECSPI1_SS2		IOMUX_PAD(0x6a8, 0x2a8, 7, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_DI1_PIN11__GPIO3_0		IOMUX_PAD(0x6a8, 0x2a8, 4, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN12__DI1_PIN12		IOMUX_PAD(0x6ac, 0x2ac, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN12__GPIO3_1		IOMUX_PAD(0x6ac, 0x2ac, 4, 0x978, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN13__DI1_PIN13		IOMUX_PAD(0x6b0, 0x2b0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN13__GPIO3_2		IOMUX_PAD(0x6b0, 0x2b0, 4, 0x97c, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DI1_D0_CS__DI1_D0_CS		IOMUX_PAD(0x6b4, 0x2b4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D0_CS__GPIO3_3		IOMUX_PAD(0x6b4, 0x2b4, 4, 0x980, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DI1_D1_CS__DI1_D1_CS		IOMUX_PAD(0x6b8, 0x2b8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D1_CS__DISP1_PIN14		IOMUX_PAD(0x6b8, 0x2b8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D1_CS__DISP1_PIN5		IOMUX_PAD(0x6b8, 0x2b8, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D1_CS__GPIO3_4		IOMUX_PAD(0x6b8, 0x2b8, 4, 0x984, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1	IOMUX_PAD(0x6bc, 0x2bc, 2, 0x9a4, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN	IOMUX_PAD(0x6bc, 0x2bc, 0, 0x9c4, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIN__GPIO3_5	IOMUX_PAD(0x6bc, 0x2bc, 4, 0x988, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6	IOMUX_PAD(0x6c0, 0x2c0, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO	IOMUX_PAD(0x6c0, 0x2c0, 0, 0x9c4, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIO__GPIO3_6	IOMUX_PAD(0x6c0, 0x2c0, 4, 0x98c, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17	IOMUX_PAD(0x6c4, 0x2c4, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7	IOMUX_PAD(0x6c4, 0x2c4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK	IOMUX_PAD(0x6c4, 0x2c4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_CLK__GPIO3_7	IOMUX_PAD(0x6c4, 0x2c4, 4, 0x990, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK	IOMUX_PAD(0x6c8, 0x2c8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN16	IOMUX_PAD(0x6c8, 0x2c8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN8	IOMUX_PAD(0x6c8, 0x2c8, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__GPIO3_8		IOMUX_PAD(0x6c8, 0x2c8, 4, 0x994, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT0__DISP1_DAT0		IOMUX_PAD(0x6cc, 0x2cc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT1__DISP1_DAT1		IOMUX_PAD(0x6d0, 0x2d0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT2__DISP1_DAT2		IOMUX_PAD(0x6d4, 0x2d4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT3__DISP1_DAT3		IOMUX_PAD(0x6d8, 0x2d8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT4__DISP1_DAT4		IOMUX_PAD(0x6dc, 0x2dc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT5__DISP1_DAT5		IOMUX_PAD(0x6e0, 0x2e0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT6__BOOT_USB_SRC	IOMUX_PAD(0x6e4, 0x2e4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT6__DISP1_DAT6		IOMUX_PAD(0x6e4, 0x2e4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG	IOMUX_PAD(0x6e8, 0x2e8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT7__DISP1_DAT7		IOMUX_PAD(0x6e8, 0x2e8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT8__BOOT_SRC0		IOMUX_PAD(0x6ec, 0x2ec, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT8__DISP1_DAT8		IOMUX_PAD(0x6ec, 0x2ec, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT9__BOOT_SRC1		IOMUX_PAD(0x6f0, 0x2f0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT9__DISP1_DAT9		IOMUX_PAD(0x6f0, 0x2f0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE	IOMUX_PAD(0x6f4, 0x2f4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT10__DISP1_DAT10	IOMUX_PAD(0x6f4, 0x2f4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2	IOMUX_PAD(0x6f8, 0x2f8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT11__DISP1_DAT11	IOMUX_PAD(0x6f8, 0x2f8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL	IOMUX_PAD(0x6fc, 0x2fc, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT12__DISP1_DAT12	IOMUX_PAD(0x6fc, 0x2fc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0	IOMUX_PAD(0x700, 0x300, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT13__DISP1_DAT13	IOMUX_PAD(0x700, 0x300, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1	IOMUX_PAD(0x704, 0x304, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT14__DISP1_DAT14	IOMUX_PAD(0x704, 0x304, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH	IOMUX_PAD(0x708, 0x308, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT15__DISP1_DAT15	IOMUX_PAD(0x708, 0x308, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0	IOMUX_PAD(0x70c, 0x30c, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT16__DISP1_DAT16	IOMUX_PAD(0x70c, 0x30c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1	IOMUX_PAD(0x710, 0x310, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT17__DISP1_DAT17	IOMUX_PAD(0x710, 0x310, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0	IOMUX_PAD(0x714, 0x314, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT18__DISP1_DAT18	IOMUX_PAD(0x714, 0x314, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT18__DISP2_PIN11	IOMUX_PAD(0x714, 0x314, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT18__DISP2_PIN5	IOMUX_PAD(0x714, 0x314, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1	IOMUX_PAD(0x718, 0x318, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT19__DISP1_DAT19	IOMUX_PAD(0x718, 0x318, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT19__DISP2_PIN12	IOMUX_PAD(0x718, 0x318, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT19__DISP2_PIN6	IOMUX_PAD(0x718, 0x318, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0	IOMUX_PAD(0x71c, 0x31c, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT20__DISP1_DAT20	IOMUX_PAD(0x71c, 0x31c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT20__DISP2_PIN13	IOMUX_PAD(0x71c, 0x31c, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT20__DISP2_PIN7	IOMUX_PAD(0x71c, 0x31c, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1	IOMUX_PAD(0x720, 0x320, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT21__DISP1_DAT21	IOMUX_PAD(0x720, 0x320, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT21__DISP2_PIN14	IOMUX_PAD(0x720, 0x320, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT21__DISP2_PIN8	IOMUX_PAD(0x720, 0x320, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0	IOMUX_PAD(0x724, 0x324, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT22__DISP1_DAT22	IOMUX_PAD(0x724, 0x324, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT22__DISP2_D0_CS	IOMUX_PAD(0x724, 0x324, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT22__DISP2_DAT16	IOMUX_PAD(0x724, 0x324, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1	IOMUX_PAD(0x728, 0x328, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT23__DISP1_DAT23	IOMUX_PAD(0x728, 0x328, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT23__DISP2_D1_CS	IOMUX_PAD(0x728, 0x328, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT23__DISP2_DAT17	IOMUX_PAD(0x728, 0x328, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT23__DISP2_SER_CS	IOMUX_PAD(0x728, 0x328, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN3__DI1_PIN3		IOMUX_PAD(0x72c, 0x32c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_DISP_CLK__DI1_DISP_CLK	IOMUX_PAD(0x730, __NA_, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN2__DI1_PIN2		IOMUX_PAD(0x734, 0x330, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN15__DI1_PIN15		IOMUX_PAD(0x738, __NA_, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP2__DISP1_SER_CLK		IOMUX_PAD(0x740, 0x338, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP2__DISP2_WAIT		IOMUX_PAD(0x740, 0x338, 2, 0x9a8, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP3__CSI1_DATA_EN		IOMUX_PAD(0x744, 0x33c, 3, 0x9a0, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP3__DISP1_SER_DIO		IOMUX_PAD(0x744, 0x33c, 0, 0x9c0, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP3__FEC_TX_ER		IOMUX_PAD(0x744, 0x33c, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DI2_PIN4__CSI2_DATA_EN		IOMUX_PAD(0x748, 0x340, 3, 0x99c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN4__DI2_PIN4		IOMUX_PAD(0x748, 0x340, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN4__FEC_CRS		IOMUX_PAD(0x748, 0x340, 2, 0x950, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN2__DI2_PIN2		IOMUX_PAD(0x74c, 0x344, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN2__FEC_MDC		IOMUX_PAD(0x74c, 0x344, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DI2_PIN3__DI2_PIN3		IOMUX_PAD(0x750, 0x348, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN3__FEC_MDIO		IOMUX_PAD(0x750, 0x348, 2, 0x954, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK	IOMUX_PAD(0x754, 0x34c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI2_DISP_CLK__FEC_RDATA1	IOMUX_PAD(0x754, 0x34c, 2, 0x95c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP4__DI2_PIN15		IOMUX_PAD(0x758, 0x350, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP4__DISP1_SER_DIN		IOMUX_PAD(0x758, 0x350, 0, 0x9c0, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP4__DISP2_PIN1		IOMUX_PAD(0x758, 0x350, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP4__FEC_RDATA2		IOMUX_PAD(0x758, 0x350, 2, 0x960, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT0__DISP2_DAT0		IOMUX_PAD(0x75c, 0x354, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT0__FEC_RDATA3		IOMUX_PAD(0x75c, 0x354, 2, 0x964, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT0__KEY_COL6		IOMUX_PAD(0x75c, 0x354, 4, 0x9c8, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT0__UART3_RXD		IOMUX_PAD(0x75c, 0x354, 5, 0x9f4, 8, MX51_UART_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT0__USBH3_CLK		IOMUX_PAD(0x75c, 0x354, 3, 0x9f8, 1, MX51_UART_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT1__DISP2_DAT1		IOMUX_PAD(0x760, 0x358, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT1__FEC_RX_ER		IOMUX_PAD(0x760, 0x358, 2, 0x970, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT1__KEY_COL7		IOMUX_PAD(0x760, 0x358, 4, 0x9cc, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT1__UART3_TXD		IOMUX_PAD(0x760, 0x358, 5, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT1__USBH3_DIR		IOMUX_PAD(0x760, 0x358, 3, 0xa1c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT2__DISP2_DAT2		IOMUX_PAD(0x764, 0x35c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT3__DISP2_DAT3		IOMUX_PAD(0x768, 0x360, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT4__DISP2_DAT4		IOMUX_PAD(0x76c, 0x364, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT5__DISP2_DAT5		IOMUX_PAD(0x770, 0x368, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT6__DISP2_DAT6		IOMUX_PAD(0x774, 0x36c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT6__FEC_TDATA1		IOMUX_PAD(0x774, 0x36c, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT6__GPIO1_19		IOMUX_PAD(0x774, 0x36c, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT6__KEY_ROW4		IOMUX_PAD(0x774, 0x36c, 4, 0x9d0, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT6__USBH3_STP		IOMUX_PAD(0x774, 0x36c, 3, 0xa24, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT7__DISP2_DAT7		IOMUX_PAD(0x778, 0x370, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT7__FEC_TDATA2		IOMUX_PAD(0x778, 0x370, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT7__GPIO1_29		IOMUX_PAD(0x778, 0x370, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT7__KEY_ROW5		IOMUX_PAD(0x778, 0x370, 4, 0x9d4, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT7__USBH3_NXT		IOMUX_PAD(0x778, 0x370, 3, 0xa20, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT8__DISP2_DAT8		IOMUX_PAD(0x77c, 0x374, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT8__FEC_TDATA3		IOMUX_PAD(0x77c, 0x374, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT8__GPIO1_30		IOMUX_PAD(0x77c, 0x374, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT8__KEY_ROW6		IOMUX_PAD(0x77c, 0x374, 4, 0x9d8, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT8__USBH3_DATA0	IOMUX_PAD(0x77c, 0x374, 3, 0x9fc, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT9__AUD6_RXC		IOMUX_PAD(0x780, 0x378, 4, 0x8f4, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT9__DISP2_DAT9		IOMUX_PAD(0x780, 0x378, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT9__FEC_TX_EN		IOMUX_PAD(0x780, 0x378, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT9__GPIO1_31		IOMUX_PAD(0x780, 0x378, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT9__USBH3_DATA1	IOMUX_PAD(0x780, 0x378, 3, 0xa00, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT10__DISP2_DAT10	IOMUX_PAD(0x784, 0x37c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT10__DISP2_SER_CS	IOMUX_PAD(0x784, 0x37c, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT10__FEC_COL		IOMUX_PAD(0x784, 0x37c, 2, 0x94c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT10__KEY_ROW7		IOMUX_PAD(0x784, 0x37c, 4, 0x9dc, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT10__USBH3_DATA2	IOMUX_PAD(0x784, 0x37c, 3, 0xa04, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__AUD6_TXD		IOMUX_PAD(0x788, 0x380, 4, 0x8f0, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__DISP2_DAT11	IOMUX_PAD(0x788, 0x380, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__FEC_RX_CLK	IOMUX_PAD(0x788, 0x380, 2, 0x968, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__GPIO1_10		IOMUX_PAD(0x788, 0x380, 7, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__USBH3_DATA3	IOMUX_PAD(0x788, 0x380, 3, 0xa08, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT12__AUD6_RXD		IOMUX_PAD(0x78c, 0x384, 4, 0x8ec, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT12__DISP2_DAT12	IOMUX_PAD(0x78c, 0x384, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT12__FEC_RX_DV		IOMUX_PAD(0x78c, 0x384, 2, 0x96c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT12__USBH3_DATA4	IOMUX_PAD(0x78c, 0x384, 3, 0xa0c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT13__AUD6_TXC		IOMUX_PAD(0x790, 0x388, 4, 0x8fc, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT13__DISP2_DAT13	IOMUX_PAD(0x790, 0x388, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT13__FEC_TX_CLK	IOMUX_PAD(0x790, 0x388, 2, 0x974, 1, MX51_PAD_CTRL_4)
-#define MX51_PAD_DISP2_DAT13__USBH3_DATA5	IOMUX_PAD(0x790, 0x388, 3, 0xa10, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT14__AUD6_TXFS		IOMUX_PAD(0x794, 0x38c, 4, 0x900, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT14__DISP2_DAT14	IOMUX_PAD(0x794, 0x38c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT14__FEC_RDATA0	IOMUX_PAD(0x794, 0x38c, 2, 0x958, 1, MX51_PAD_CTRL_4)
-#define MX51_PAD_DISP2_DAT14__USBH3_DATA6	IOMUX_PAD(0x794, 0x38c, 3, 0xa14, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT15__AUD6_RXFS		IOMUX_PAD(0x798, 0x390, 4, 0x8f8, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT15__DISP1_SER_CS	IOMUX_PAD(0x798, 0x390, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT15__DISP2_DAT15	IOMUX_PAD(0x798, 0x390, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT15__FEC_TDATA0	IOMUX_PAD(0x798, 0x390, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT15__USBH3_DATA7	IOMUX_PAD(0x798, 0x390, 3, 0xa18, 1, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CMD__AUD5_RXFS		IOMUX_PAD(0x79c, 0x394, 1, 0x8e0, 1, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CMD__CSPI_MOSI		IOMUX_PAD(0x79c, 0x394, 2, 0x91c, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CMD__SD1_CMD		IOMUX_PAD(0x79c, 0x394, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD1_CLK__AUD5_RXC		IOMUX_PAD(0x7a0, 0x398, 1, 0x8dc, 1, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CLK__CSPI_SCLK		IOMUX_PAD(0x7a0, 0x398, 2, 0x914, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CLK__SD1_CLK		IOMUX_PAD(0x7a0, 0x398, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
-#define MX51_PAD_SD1_DATA0__AUD5_TXD		IOMUX_PAD(0x7a4, 0x39c, 1, 0x8d8, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA0__CSPI_MISO		IOMUX_PAD(0x7a4, 0x39c, 2, 0x918, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD1_DATA0__SD1_DATA0		IOMUX_PAD(0x7a4, 0x39c, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_EIM_DA0__EIM_DA0		IOMUX_PAD(__NA_, 0x01c, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA1__EIM_DA1		IOMUX_PAD(__NA_, 0x020, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA2__EIM_DA2		IOMUX_PAD(__NA_, 0x024, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA3__EIM_DA3		IOMUX_PAD(__NA_, 0x028, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA1__AUD5_RXD		IOMUX_PAD(0x7a8, 0x3a0, 1, 0x8d4, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA1__SD1_DATA1		IOMUX_PAD(0x7a8, 0x3a0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_EIM_DA4__EIM_DA4		IOMUX_PAD(__NA_, 0x02c, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA5__EIM_DA5		IOMUX_PAD(__NA_, 0x030, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA6__EIM_DA6		IOMUX_PAD(__NA_, 0x034, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA7__EIM_DA7		IOMUX_PAD(__NA_, 0x038, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA2__AUD5_TXC		IOMUX_PAD(0x7ac, 0x3a4, 1, 0x8e4, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA2__SD1_DATA2		IOMUX_PAD(0x7ac, 0x3a4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_EIM_DA10__EIM_DA10		IOMUX_PAD(__NA_, 0x044, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA11__EIM_DA11		IOMUX_PAD(__NA_, 0x048, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA8__EIM_DA8		IOMUX_PAD(__NA_, 0x03c, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA9__EIM_DA9		IOMUX_PAD(__NA_, 0x040, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA3__AUD5_TXFS		IOMUX_PAD(0x7b0, 0x3a8, 1, 0x8e8, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA3__CSPI_SS1		IOMUX_PAD(0x7b0, 0x3a8, 2, 0x920, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD1_DATA3__SD1_DATA3		IOMUX_PAD(0x7b0, 0x3a8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_GPIO1_0__CSPI_SS2		IOMUX_PAD(0x7b4, 0x3ac, 2, 0x924, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_GPIO1_0__GPIO1_0		IOMUX_PAD(0x7b4, 0x3ac, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_0__SD1_CD		IOMUX_PAD(0x7b4, 0x3ac, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
-#define MX51_PAD_GPIO1_1__CSPI_MISO		IOMUX_PAD(0x7b8, 0x3b0, 2, 0x918, 2, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_GPIO1_1__GPIO1_1		IOMUX_PAD(0x7b8, 0x3b0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_1__SD1_WP		IOMUX_PAD(0x7b8, 0x3b0, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
-#define MX51_PAD_EIM_DA12__EIM_DA12		IOMUX_PAD(__NA_, 0x04c, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA13__EIM_DA13		IOMUX_PAD(__NA_, 0x050, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA14__EIM_DA14		IOMUX_PAD(__NA_, 0x054, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA15__EIM_DA15		IOMUX_PAD(__NA_, 0x058, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_CMD__CSPI_MOSI		IOMUX_PAD(0x7bc, 0x3b4, 2, 0x91c, 3, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD2_CMD__I2C1_SCL		IOMUX_PAD(0x7bc, 0x3b4, 0x11, 0x9b0, 2, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_SD2_CMD__SD2_CMD		IOMUX_PAD(0x7bc, 0x3b4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_CLK__CSPI_SCLK		IOMUX_PAD(0x7c0, 0x3b8, 2, 0x914, 3, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD2_CLK__I2C1_SDA		IOMUX_PAD(0x7c0, 0x3b8, 0x11, 0x9b4, 2, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_SD2_CLK__SD2_CLK		IOMUX_PAD(0x7c0, 0x3b8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
-#define MX51_PAD_SD2_DATA0__CSPI_MISO		IOMUX_PAD(0x7c4, 0x3bc, 2, 0x918, 3, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA0__SD1_DAT4		IOMUX_PAD(0x7c4, 0x3bc, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA0__SD2_DATA0		IOMUX_PAD(0x7c4, 0x3bc, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA1__SD1_DAT5		IOMUX_PAD(0x7c8, 0x3c0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA1__SD2_DATA1		IOMUX_PAD(0x7c8, 0x3c0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA1__USBH3_H2_DP		IOMUX_PAD(0x7c8, 0x3c0, 0x12, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA2__SD1_DAT6		IOMUX_PAD(0x7cc, 0x3c4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA2__SD2_DATA2		IOMUX_PAD(0x7cc, 0x3c4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA2__USBH3_H2_DM		IOMUX_PAD(0x7cc, 0x3c4, 0x12, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA3__CSPI_SS2		IOMUX_PAD(0x7d0, 0x3c8, 2, 0x924, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA3__SD1_DAT7		IOMUX_PAD(0x7d0, 0x3c8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA3__SD2_DATA3		IOMUX_PAD(0x7d0, 0x3c8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_GPIO1_2__CCM_OUT_2		IOMUX_PAD(0x7d4, 0x3cc, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_2__GPIO1_2		IOMUX_PAD(0x7d4, 0x3cc, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_2__I2C2_SCL		IOMUX_PAD(0x7d4, 0x3cc, 0x12, 0x9b8, 3, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_GPIO1_2__PLL1_BYP		IOMUX_PAD(0x7d4, 0x3cc, 7, 0x90c, 1, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_2__PWM1_PWMO		IOMUX_PAD(0x7d4, 0x3cc, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__GPIO1_3		IOMUX_PAD(0x7d8, 0x3d0, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__I2C2_SDA		IOMUX_PAD(0x7d8, 0x3d0, 0x12, 0x9bc, 3, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__CCM_CLKO2		IOMUX_PAD(0x7d8, 0x3d0, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__GPT_CLKIN		IOMUX_PAD(0x7d8, 0x3d0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__PLL2_BYP		IOMUX_PAD(0x7d8, 0x3d0, 7, 0x910, 1, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__PWM2_PWMO		IOMUX_PAD(0x7d8, 0x3d0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	IOMUX_PAD(0x7fc, 0x3d4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B	IOMUX_PAD(0x7fc, 0x3d4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_4__DISP2_EXT_CLK		IOMUX_PAD(0x804, 0x3d8, 4, 0x908, 1, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_4__EIM_RDY		IOMUX_PAD(0x804, 0x3d8, 3, 0x938, 1, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_4__GPIO1_4		IOMUX_PAD(0x804, 0x3d8, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_4__WDOG1_WDOG_B		IOMUX_PAD(0x804, 0x3d8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_4__GPT_CAPIN1		IOMUX_PAD(0x804, 0x3d8, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_5__CSI2_MCLK		IOMUX_PAD(0x808, 0x3dc, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_5__DISP2_PIN16		IOMUX_PAD(0x808, 0x3dc, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_5__GPIO1_5		IOMUX_PAD(0x808, 0x3dc, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_5__WDOG2_WDOG_B		IOMUX_PAD(0x808, 0x3dc, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_5__CCM_CLKO		IOMUX_PAD(0x808, 0x3dc, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_6__DISP2_PIN17		IOMUX_PAD(0x80c, 0x3e0, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_6__GPIO1_6		IOMUX_PAD(0x80c, 0x3e0, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_6__REF_EN_B		IOMUX_PAD(0x80c, 0x3e0, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_6__GPT_CAPIN2		IOMUX_PAD(0x80c, 0x3e0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_7__CCM_OUT_0		IOMUX_PAD(0x810, 0x3e4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_7__GPIO1_7		IOMUX_PAD(0x810, 0x3e4, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_7__SD2_WP		IOMUX_PAD(0x810, 0x3e4, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
-#define MX51_PAD_GPIO1_7__SPDIF_OUT1		IOMUX_PAD(0x810, 0x3e4, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_8__CSI2_DATA_EN		IOMUX_PAD(0x814, 0x3e8, 2, 0x99c, 2, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_8__GPIO1_8		IOMUX_PAD(0x814, 0x3e8, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_8__SD2_CD		IOMUX_PAD(0x814, 0x3e8, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
-#define MX51_PAD_GPIO1_8__USBH3_PWR		IOMUX_PAD(0x814, 0x3e8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_8__CCM_CLKO2		IOMUX_PAD(0x814, 0x3e8, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__CCM_OUT_1		IOMUX_PAD(0x818, 0x3ec, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__DISP2_D1_CS		IOMUX_PAD(0x818, 0x3ec, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__DISP2_SER_CS		IOMUX_PAD(0x818, 0x3ec, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__GPIO1_9		IOMUX_PAD(0x818, 0x3ec, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__SD2_LCTL		IOMUX_PAD(0x818, 0x3ec, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__USBH3_OC		IOMUX_PAD(0x818, 0x3ec, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__CCM_CLKO		IOMUX_PAD(0x818, 0x3ec, 4, __NA_, 0, NO_PAD_CTRL)
-
-#endif /* __MACH_IOMUX_MX51_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-v1.h b/arch/arm/plat-mxc/include/mach/iomux-v1.h
deleted file mode 100644
index 02651a4..0000000
--- a/arch/arm/plat-mxc/include/mach/iomux-v1.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
- * Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-#ifndef __MACH_IOMUX_V1_H__
-#define __MACH_IOMUX_V1_H__
-
-/*
-*  GPIO Module and I/O Multiplexer
-*  x = 0..3 for reg_A, reg_B, reg_C, reg_D
-*/
-#define MXC_DDIR(x)	(0x00 + ((x) << 8))
-#define MXC_OCR1(x)	(0x04 + ((x) << 8))
-#define MXC_OCR2(x)	(0x08 + ((x) << 8))
-#define MXC_ICONFA1(x)	(0x0c + ((x) << 8))
-#define MXC_ICONFA2(x)	(0x10 + ((x) << 8))
-#define MXC_ICONFB1(x)	(0x14 + ((x) << 8))
-#define MXC_ICONFB2(x)	(0x18 + ((x) << 8))
-#define MXC_DR(x)	(0x1c + ((x) << 8))
-#define MXC_GIUS(x)	(0x20 + ((x) << 8))
-#define MXC_SSR(x)	(0x24 + ((x) << 8))
-#define MXC_ICR1(x)	(0x28 + ((x) << 8))
-#define MXC_ICR2(x)	(0x2c + ((x) << 8))
-#define MXC_IMR(x)	(0x30 + ((x) << 8))
-#define MXC_ISR(x)	(0x34 + ((x) << 8))
-#define MXC_GPR(x)	(0x38 + ((x) << 8))
-#define MXC_SWR(x)	(0x3c + ((x) << 8))
-#define MXC_PUEN(x)	(0x40 + ((x) << 8))
-
-#define MX1_NUM_GPIO_PORT	4
-#define MX21_NUM_GPIO_PORT	6
-#define MX27_NUM_GPIO_PORT	6
-
-#define GPIO_PIN_MASK 0x1f
-
-#define GPIO_PORT_SHIFT 5
-#define GPIO_PORT_MASK (0x7 << GPIO_PORT_SHIFT)
-
-#define GPIO_PORTA	(0 << GPIO_PORT_SHIFT)
-#define GPIO_PORTB	(1 << GPIO_PORT_SHIFT)
-#define GPIO_PORTC	(2 << GPIO_PORT_SHIFT)
-#define GPIO_PORTD	(3 << GPIO_PORT_SHIFT)
-#define GPIO_PORTE	(4 << GPIO_PORT_SHIFT)
-#define GPIO_PORTF	(5 << GPIO_PORT_SHIFT)
-
-#define GPIO_OUT	(1 << 8)
-#define GPIO_IN		(0 << 8)
-#define GPIO_PUEN	(1 << 9)
-
-#define GPIO_PF		(1 << 10)
-#define GPIO_AF		(1 << 11)
-
-#define GPIO_OCR_SHIFT 12
-#define GPIO_OCR_MASK	(3 << GPIO_OCR_SHIFT)
-#define GPIO_AIN	(0 << GPIO_OCR_SHIFT)
-#define GPIO_BIN	(1 << GPIO_OCR_SHIFT)
-#define GPIO_CIN	(2 << GPIO_OCR_SHIFT)
-#define GPIO_GPIO	(3 << GPIO_OCR_SHIFT)
-
-#define GPIO_AOUT_SHIFT	14
-#define GPIO_AOUT_MASK	(3 << GPIO_AOUT_SHIFT)
-#define GPIO_AOUT	(0 << GPIO_AOUT_SHIFT)
-#define GPIO_AOUT_ISR	(1 << GPIO_AOUT_SHIFT)
-#define GPIO_AOUT_0	(2 << GPIO_AOUT_SHIFT)
-#define GPIO_AOUT_1	(3 << GPIO_AOUT_SHIFT)
-
-#define GPIO_BOUT_SHIFT	16
-#define GPIO_BOUT_MASK	(3 << GPIO_BOUT_SHIFT)
-#define GPIO_BOUT	(0 << GPIO_BOUT_SHIFT)
-#define GPIO_BOUT_ISR	(1 << GPIO_BOUT_SHIFT)
-#define GPIO_BOUT_0	(2 << GPIO_BOUT_SHIFT)
-#define GPIO_BOUT_1	(3 << GPIO_BOUT_SHIFT)
-
-extern int mxc_gpio_mode(int gpio_mode);
-extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
-		const char *label);
-
-extern int imx_iomuxv1_init(void __iomem *base, int numports);
-
-#endif /* __MACH_IOMUX_V1_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-v3.h b/arch/arm/plat-mxc/include/mach/iomux-v3.h
deleted file mode 100644
index 2fa3b54..0000000
--- a/arch/arm/plat-mxc/include/mach/iomux-v3.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
- *			<armlinux@phytec.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef __MACH_IOMUX_V3_H__
-#define __MACH_IOMUX_V3_H__
-
-/*
- *	build IOMUX_PAD structure
- *
- * This iomux scheme is based around pads, which are the physical balls
- * on the processor.
- *
- * - Each pad has a pad control register (IOMUXC_SW_PAD_CTRL_x) which controls
- *   things like driving strength and pullup/pulldown.
- * - Each pad can have but not necessarily does have an output routing register
- *   (IOMUXC_SW_MUX_CTL_PAD_x).
- * - Each pad can have but not necessarily does have an input routing register
- *   (IOMUXC_x_SELECT_INPUT)
- *
- * The three register sets do not have a fixed offset to each other,
- * hence we order this table by pad control registers (which all pads
- * have) and put the optional i/o routing registers into additional
- * fields.
- *
- * The naming convention for the pad modes is MX35_PAD_<padname>__<padmode>
- * If <padname> or <padmode> refers to a GPIO, it is named
- * GPIO_<unit>_<num>
- *
- * IOMUX/PAD Bit field definitions
- *
- * MUX_CTRL_OFS:	    0..11 (12)
- * PAD_CTRL_OFS:	   12..23 (12)
- * SEL_INPUT_OFS:	   24..35 (12)
- * MUX_MODE + SION:	   36..40  (5)
- * PAD_CTRL + NO_PAD_CTRL: 41..57 (17)
- * SEL_INP:		   58..61  (4)
- * reserved:		     63    (1)
-*/
-
-typedef u64 iomux_v3_cfg_t;
-
-#define MUX_CTRL_OFS_SHIFT	0
-#define MUX_CTRL_OFS_MASK	((iomux_v3_cfg_t)0xfff << MUX_CTRL_OFS_SHIFT)
-#define MUX_PAD_CTRL_OFS_SHIFT	12
-#define MUX_PAD_CTRL_OFS_MASK	((iomux_v3_cfg_t)0xfff << MUX_PAD_CTRL_OFS_SHIFT)
-#define MUX_SEL_INPUT_OFS_SHIFT	24
-#define MUX_SEL_INPUT_OFS_MASK	((iomux_v3_cfg_t)0xfff << MUX_SEL_INPUT_OFS_SHIFT)
-
-#define MUX_MODE_SHIFT		36
-#define MUX_MODE_MASK		((iomux_v3_cfg_t)0x1f << MUX_MODE_SHIFT)
-#define MUX_PAD_CTRL_SHIFT	41
-#define MUX_PAD_CTRL_MASK	((iomux_v3_cfg_t)0x1ffff << MUX_PAD_CTRL_SHIFT)
-#define MUX_SEL_INPUT_SHIFT	58
-#define MUX_SEL_INPUT_MASK	((iomux_v3_cfg_t)0xf << MUX_SEL_INPUT_SHIFT)
-
-#define MUX_PAD_CTRL(x)		((iomux_v3_cfg_t)(x) << MUX_PAD_CTRL_SHIFT)
-
-#define IOMUX_PAD(_pad_ctrl_ofs, _mux_ctrl_ofs, _mux_mode, _sel_input_ofs, \
-		_sel_input, _pad_ctrl)					\
-	(((iomux_v3_cfg_t)(_mux_ctrl_ofs) << MUX_CTRL_OFS_SHIFT) |	\
-		((iomux_v3_cfg_t)(_mux_mode) << MUX_MODE_SHIFT) |	\
-		((iomux_v3_cfg_t)(_pad_ctrl_ofs) << MUX_PAD_CTRL_OFS_SHIFT) | \
-		((iomux_v3_cfg_t)(_pad_ctrl) << MUX_PAD_CTRL_SHIFT) |	\
-		((iomux_v3_cfg_t)(_sel_input_ofs) << MUX_SEL_INPUT_OFS_SHIFT) | \
-		((iomux_v3_cfg_t)(_sel_input) << MUX_SEL_INPUT_SHIFT))
-
-#define NEW_PAD_CTRL(cfg, pad)	(((cfg) & ~MUX_PAD_CTRL_MASK) | MUX_PAD_CTRL(pad))
-/*
- * Use to set PAD control
- */
-
-#define NO_PAD_CTRL			(1 << 16)
-#define PAD_CTL_DVS			(1 << 13)
-#define PAD_CTL_HYS			(1 << 8)
-
-#define PAD_CTL_PKE			(1 << 7)
-#define PAD_CTL_PUE			(1 << 6 | PAD_CTL_PKE)
-#define PAD_CTL_PUS_100K_DOWN		(0 << 4 | PAD_CTL_PUE)
-#define PAD_CTL_PUS_47K_UP		(1 << 4 | PAD_CTL_PUE)
-#define PAD_CTL_PUS_100K_UP		(2 << 4 | PAD_CTL_PUE)
-#define PAD_CTL_PUS_22K_UP		(3 << 4 | PAD_CTL_PUE)
-
-#define PAD_CTL_ODE			(1 << 3)
-
-#define PAD_CTL_DSE_LOW			(0 << 1)
-#define PAD_CTL_DSE_MED			(1 << 1)
-#define PAD_CTL_DSE_HIGH		(2 << 1)
-#define PAD_CTL_DSE_MAX			(3 << 1)
-
-#define PAD_CTL_SRE_FAST		(1 << 0)
-#define PAD_CTL_SRE_SLOW		(0 << 0)
-
-#define IOMUX_CONFIG_SION		(0x1 << 4)
-
-#define MX51_NUM_GPIO_PORT	4
-
-#define GPIO_PIN_MASK 0x1f
-
-#define GPIO_PORT_SHIFT 5
-#define GPIO_PORT_MASK (0x7 << GPIO_PORT_SHIFT)
-
-#define GPIO_PORTA	(0 << GPIO_PORT_SHIFT)
-#define GPIO_PORTB	(1 << GPIO_PORT_SHIFT)
-#define GPIO_PORTC	(2 << GPIO_PORT_SHIFT)
-#define GPIO_PORTD	(3 << GPIO_PORT_SHIFT)
-#define GPIO_PORTE	(4 << GPIO_PORT_SHIFT)
-#define GPIO_PORTF	(5 << GPIO_PORT_SHIFT)
-
-/*
- * setups a single pad in the iomuxer
- */
-int mxc_iomux_v3_setup_pad(iomux_v3_cfg_t pad);
-
-/*
- * setups mutliple pads
- * convenient way to call the above function with tables
- */
-int mxc_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count);
-
-/*
- * Initialise the iomux controller
- */
-void mxc_iomux_v3_init(void __iomem *iomux_v3_base);
-
-#endif /* __MACH_IOMUX_V3_H__*/
-
diff --git a/arch/arm/plat-mxc/include/mach/ipu.h b/arch/arm/plat-mxc/include/mach/ipu.h
deleted file mode 100644
index 539e559..0000000
--- a/arch/arm/plat-mxc/include/mach/ipu.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2008
- * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
- *
- * Copyright (C) 2005-2007 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 _IPU_H_
-#define _IPU_H_
-
-#include <linux/types.h>
-#include <linux/dmaengine.h>
-
-/* IPU DMA Controller channel definitions. */
-enum ipu_channel {
-	IDMAC_IC_0 = 0,		/* IC (encoding task) to memory */
-	IDMAC_IC_1 = 1,		/* IC (viewfinder task) to memory */
-	IDMAC_ADC_0 = 1,
-	IDMAC_IC_2 = 2,
-	IDMAC_ADC_1 = 2,
-	IDMAC_IC_3 = 3,
-	IDMAC_IC_4 = 4,
-	IDMAC_IC_5 = 5,
-	IDMAC_IC_6 = 6,
-	IDMAC_IC_7 = 7,		/* IC (sensor data) to memory */
-	IDMAC_IC_8 = 8,
-	IDMAC_IC_9 = 9,
-	IDMAC_IC_10 = 10,
-	IDMAC_IC_11 = 11,
-	IDMAC_IC_12 = 12,
-	IDMAC_IC_13 = 13,
-	IDMAC_SDC_0 = 14,	/* Background synchronous display data */
-	IDMAC_SDC_1 = 15,	/* Foreground data (overlay) */
-	IDMAC_SDC_2 = 16,
-	IDMAC_SDC_3 = 17,
-	IDMAC_ADC_2 = 18,
-	IDMAC_ADC_3 = 19,
-	IDMAC_ADC_4 = 20,
-	IDMAC_ADC_5 = 21,
-	IDMAC_ADC_6 = 22,
-	IDMAC_ADC_7 = 23,
-	IDMAC_PF_0 = 24,
-	IDMAC_PF_1 = 25,
-	IDMAC_PF_2 = 26,
-	IDMAC_PF_3 = 27,
-	IDMAC_PF_4 = 28,
-	IDMAC_PF_5 = 29,
-	IDMAC_PF_6 = 30,
-	IDMAC_PF_7 = 31,
-};
-
-/* Order significant! */
-enum ipu_channel_status {
-	IPU_CHANNEL_FREE,
-	IPU_CHANNEL_INITIALIZED,
-	IPU_CHANNEL_READY,
-	IPU_CHANNEL_ENABLED,
-};
-
-#define IPU_CHANNELS_NUM 32
-
-enum pixel_fmt {
-	/* 1 byte */
-	IPU_PIX_FMT_GENERIC,
-	IPU_PIX_FMT_RGB332,
-	IPU_PIX_FMT_YUV420P,
-	IPU_PIX_FMT_YUV422P,
-	IPU_PIX_FMT_YUV420P2,
-	IPU_PIX_FMT_YVU422P,
-	/* 2 bytes */
-	IPU_PIX_FMT_RGB565,
-	IPU_PIX_FMT_RGB666,
-	IPU_PIX_FMT_BGR666,
-	IPU_PIX_FMT_YUYV,
-	IPU_PIX_FMT_UYVY,
-	/* 3 bytes */
-	IPU_PIX_FMT_RGB24,
-	IPU_PIX_FMT_BGR24,
-	/* 4 bytes */
-	IPU_PIX_FMT_GENERIC_32,
-	IPU_PIX_FMT_RGB32,
-	IPU_PIX_FMT_BGR32,
-	IPU_PIX_FMT_ABGR32,
-	IPU_PIX_FMT_BGRA32,
-	IPU_PIX_FMT_RGBA32,
-};
-
-enum ipu_color_space {
-	IPU_COLORSPACE_RGB,
-	IPU_COLORSPACE_YCBCR,
-	IPU_COLORSPACE_YUV
-};
-
-/*
- * Enumeration of IPU rotation modes
- */
-enum ipu_rotate_mode {
-	/* Note the enum values correspond to BAM value */
-	IPU_ROTATE_NONE = 0,
-	IPU_ROTATE_VERT_FLIP = 1,
-	IPU_ROTATE_HORIZ_FLIP = 2,
-	IPU_ROTATE_180 = 3,
-	IPU_ROTATE_90_RIGHT = 4,
-	IPU_ROTATE_90_RIGHT_VFLIP = 5,
-	IPU_ROTATE_90_RIGHT_HFLIP = 6,
-	IPU_ROTATE_90_LEFT = 7,
-};
-
-/*
- * Enumeration of DI ports for ADC.
- */
-enum display_port {
-	DISP0,
-	DISP1,
-	DISP2,
-	DISP3
-};
-
-struct idmac_video_param {
-	unsigned short		in_width;
-	unsigned short		in_height;
-	uint32_t		in_pixel_fmt;
-	unsigned short		out_width;
-	unsigned short		out_height;
-	uint32_t		out_pixel_fmt;
-	unsigned short		out_stride;
-	bool			graphics_combine_en;
-	bool			global_alpha_en;
-	bool			key_color_en;
-	enum display_port	disp;
-	unsigned short		out_left;
-	unsigned short		out_top;
-};
-
-/*
- * Union of initialization parameters for a logical channel. So far only video
- * parameters are used.
- */
-union ipu_channel_param {
-	struct idmac_video_param video;
-};
-
-struct idmac_tx_desc {
-	struct dma_async_tx_descriptor	txd;
-	struct scatterlist		*sg;	/* scatterlist for this */
-	unsigned int			sg_len;	/* tx-descriptor. */
-	struct list_head		list;
-};
-
-struct idmac_channel {
-	struct dma_chan		dma_chan;
-	dma_cookie_t		completed;	/* last completed cookie	   */
-	union ipu_channel_param	params;
-	enum ipu_channel	link;	/* input channel, linked to the output	   */
-	enum ipu_channel_status	status;
-	void			*client;	/* Only one client per channel	   */
-	unsigned int		n_tx_desc;
-	struct idmac_tx_desc	*desc;		/* allocated tx-descriptors	   */
-	struct scatterlist	*sg[2];	/* scatterlist elements in buffer-0 and -1 */
-	struct list_head	free_list;	/* free tx-descriptors		   */
-	struct list_head	queue;		/* queued tx-descriptors	   */
-	spinlock_t		lock;		/* protects sg[0,1], queue	   */
-	struct mutex		chan_mutex; /* protects status, cookie, free_list  */
-	bool			sec_chan_en;
-	int			active_buffer;
-	unsigned int		eof_irq;
-	char			eof_name[16];	/* EOF IRQ name for request_irq()  */
-};
-
-#define to_tx_desc(tx) container_of(tx, struct idmac_tx_desc, txd)
-#define to_idmac_chan(c) container_of(c, struct idmac_channel, dma_chan)
-
-#endif
diff --git a/arch/arm/plat-mxc/include/mach/iram.h b/arch/arm/plat-mxc/include/mach/iram.h
deleted file mode 100644
index 022690c..0000000
--- a/arch/arm/plat-mxc/include/mach/iram.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-#include <linux/errno.h>
-
-#ifdef CONFIG_IRAM_ALLOC
-
-int __init iram_init(unsigned long base, unsigned long size);
-void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr);
-void iram_free(unsigned long dma_addr, unsigned int size);
-
-#else
-
-static inline int __init iram_init(unsigned long base, unsigned long size)
-{
-	return -ENOMEM;
-}
-
-static inline void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr)
-{
-	return NULL;
-}
-
-static inline void iram_free(unsigned long base, unsigned long size) {}
-
-#endif
diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h
deleted file mode 100644
index d73f5e8..0000000
--- a/arch/arm/plat-mxc/include/mach/irqs.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- *  Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_MXC_IRQS_H__
-#define __ASM_ARCH_MXC_IRQS_H__
-
-extern int imx_irq_set_priority(unsigned char irq, unsigned char prio);
-
-/* all normal IRQs can be FIQs */
-#define FIQ_START	0
-/* switch between IRQ and FIQ */
-extern int mxc_set_irq_fiq(unsigned int irq, unsigned int type);
-
-#endif /* __ASM_ARCH_MXC_IRQS_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx1.h b/arch/arm/plat-mxc/include/mach/mx1.h
deleted file mode 100644
index 45bd31c..0000000
--- a/arch/arm/plat-mxc/include/mach/mx1.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 1997,1998 Russell King
- * Copyright (C) 1999 ARM Limited
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (c) 2008 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 version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __MACH_MX1_H__
-#define __MACH_MX1_H__
-
-/*
- * Memory map
- */
-#define MX1_IO_BASE_ADDR	0x00200000
-#define MX1_IO_SIZE		SZ_1M
-
-#define MX1_CS0_PHYS		0x10000000
-#define MX1_CS0_SIZE		0x02000000
-
-#define MX1_CS1_PHYS		0x12000000
-#define MX1_CS1_SIZE		0x01000000
-
-#define MX1_CS2_PHYS		0x13000000
-#define MX1_CS2_SIZE		0x01000000
-
-#define MX1_CS3_PHYS		0x14000000
-#define MX1_CS3_SIZE		0x01000000
-
-#define MX1_CS4_PHYS		0x15000000
-#define MX1_CS4_SIZE		0x01000000
-
-#define MX1_CS5_PHYS		0x16000000
-#define MX1_CS5_SIZE		0x01000000
-
-/*
- *  Register BASEs, based on OFFSETs
- */
-#define MX1_AIPI1_BASE_ADDR		(0x00000 + MX1_IO_BASE_ADDR)
-#define MX1_WDT_BASE_ADDR		(0x01000 + MX1_IO_BASE_ADDR)
-#define MX1_TIM1_BASE_ADDR		(0x02000 + MX1_IO_BASE_ADDR)
-#define MX1_TIM2_BASE_ADDR		(0x03000 + MX1_IO_BASE_ADDR)
-#define MX1_RTC_BASE_ADDR		(0x04000 + MX1_IO_BASE_ADDR)
-#define MX1_LCDC_BASE_ADDR		(0x05000 + MX1_IO_BASE_ADDR)
-#define MX1_UART1_BASE_ADDR		(0x06000 + MX1_IO_BASE_ADDR)
-#define MX1_UART2_BASE_ADDR		(0x07000 + MX1_IO_BASE_ADDR)
-#define MX1_PWM_BASE_ADDR		(0x08000 + MX1_IO_BASE_ADDR)
-#define MX1_DMA_BASE_ADDR		(0x09000 + MX1_IO_BASE_ADDR)
-#define MX1_AIPI2_BASE_ADDR		(0x10000 + MX1_IO_BASE_ADDR)
-#define MX1_SIM_BASE_ADDR		(0x11000 + MX1_IO_BASE_ADDR)
-#define MX1_USBD_BASE_ADDR		(0x12000 + MX1_IO_BASE_ADDR)
-#define MX1_CSPI1_BASE_ADDR		(0x13000 + MX1_IO_BASE_ADDR)
-#define MX1_MMC_BASE_ADDR		(0x14000 + MX1_IO_BASE_ADDR)
-#define MX1_ASP_BASE_ADDR		(0x15000 + MX1_IO_BASE_ADDR)
-#define MX1_BTA_BASE_ADDR		(0x16000 + MX1_IO_BASE_ADDR)
-#define MX1_I2C_BASE_ADDR		(0x17000 + MX1_IO_BASE_ADDR)
-#define MX1_SSI_BASE_ADDR		(0x18000 + MX1_IO_BASE_ADDR)
-#define MX1_CSPI2_BASE_ADDR		(0x19000 + MX1_IO_BASE_ADDR)
-#define MX1_MSHC_BASE_ADDR		(0x1A000 + MX1_IO_BASE_ADDR)
-#define MX1_CCM_BASE_ADDR		(0x1B000 + MX1_IO_BASE_ADDR)
-#define MX1_SCM_BASE_ADDR		(0x1B804 + MX1_IO_BASE_ADDR)
-#define MX1_GPIO_BASE_ADDR		(0x1C000 + MX1_IO_BASE_ADDR)
-#define MX1_GPIO1_BASE_ADDR		(0x1C000 + MX1_IO_BASE_ADDR)
-#define MX1_GPIO2_BASE_ADDR		(0x1C100 + MX1_IO_BASE_ADDR)
-#define MX1_GPIO3_BASE_ADDR		(0x1C200 + MX1_IO_BASE_ADDR)
-#define MX1_GPIO4_BASE_ADDR		(0x1C300 + MX1_IO_BASE_ADDR)
-#define MX1_EIM_BASE_ADDR		(0x20000 + MX1_IO_BASE_ADDR)
-#define MX1_SDRAMC_BASE_ADDR		(0x21000 + MX1_IO_BASE_ADDR)
-#define MX1_MMA_BASE_ADDR		(0x22000 + MX1_IO_BASE_ADDR)
-#define MX1_AVIC_BASE_ADDR		(0x23000 + MX1_IO_BASE_ADDR)
-#define MX1_CSI_BASE_ADDR		(0x24000 + MX1_IO_BASE_ADDR)
-
-/* macro to get at IO space when running virtually */
-#define MX1_IO_P2V(x)			IMX_IO_P2V(x)
-#define MX1_IO_ADDRESS(x)		IOMEM(MX1_IO_P2V(x))
-
-/* fixed interrput numbers */
-#include <asm/irq.h>
-#define MX1_INT_SOFTINT		(NR_IRQS_LEGACY + 0)
-#define MX1_INT_CSI		(NR_IRQS_LEGACY + 6)
-#define MX1_DSPA_MAC_INT	(NR_IRQS_LEGACY + 7)
-#define MX1_DSPA_INT		(NR_IRQS_LEGACY + 8)
-#define MX1_COMP_INT		(NR_IRQS_LEGACY + 9)
-#define MX1_MSHC_XINT		(NR_IRQS_LEGACY + 10)
-#define MX1_GPIO_INT_PORTA	(NR_IRQS_LEGACY + 11)
-#define MX1_GPIO_INT_PORTB	(NR_IRQS_LEGACY + 12)
-#define MX1_GPIO_INT_PORTC	(NR_IRQS_LEGACY + 13)
-#define MX1_INT_LCDC		(NR_IRQS_LEGACY + 14)
-#define MX1_SIM_INT		(NR_IRQS_LEGACY + 15)
-#define MX1_SIM_DATA_INT	(NR_IRQS_LEGACY + 16)
-#define MX1_RTC_INT		(NR_IRQS_LEGACY + 17)
-#define MX1_RTC_SAMINT		(NR_IRQS_LEGACY + 18)
-#define MX1_INT_UART2PFERR	(NR_IRQS_LEGACY + 19)
-#define MX1_INT_UART2RTS	(NR_IRQS_LEGACY + 20)
-#define MX1_INT_UART2DTR	(NR_IRQS_LEGACY + 21)
-#define MX1_INT_UART2UARTC	(NR_IRQS_LEGACY + 22)
-#define MX1_INT_UART2TX		(NR_IRQS_LEGACY + 23)
-#define MX1_INT_UART2RX		(NR_IRQS_LEGACY + 24)
-#define MX1_INT_UART1PFERR	(NR_IRQS_LEGACY + 25)
-#define MX1_INT_UART1RTS	(NR_IRQS_LEGACY + 26)
-#define MX1_INT_UART1DTR	(NR_IRQS_LEGACY + 27)
-#define MX1_INT_UART1UARTC	(NR_IRQS_LEGACY + 28)
-#define MX1_INT_UART1TX		(NR_IRQS_LEGACY + 29)
-#define MX1_INT_UART1RX		(NR_IRQS_LEGACY + 30)
-#define MX1_VOICE_DAC_INT	(NR_IRQS_LEGACY + 31)
-#define MX1_VOICE_ADC_INT	(NR_IRQS_LEGACY + 32)
-#define MX1_PEN_DATA_INT	(NR_IRQS_LEGACY + 33)
-#define MX1_PWM_INT		(NR_IRQS_LEGACY + 34)
-#define MX1_SDHC_INT		(NR_IRQS_LEGACY + 35)
-#define MX1_INT_I2C		(NR_IRQS_LEGACY + 39)
-#define MX1_INT_CSPI2		(NR_IRQS_LEGACY + 40)
-#define MX1_INT_CSPI1		(NR_IRQS_LEGACY + 41)
-#define MX1_SSI_TX_INT		(NR_IRQS_LEGACY + 42)
-#define MX1_SSI_TX_ERR_INT	(NR_IRQS_LEGACY + 43)
-#define MX1_SSI_RX_INT		(NR_IRQS_LEGACY + 44)
-#define MX1_SSI_RX_ERR_INT	(NR_IRQS_LEGACY + 45)
-#define MX1_TOUCH_INT		(NR_IRQS_LEGACY + 46)
-#define MX1_INT_USBD0		(NR_IRQS_LEGACY + 47)
-#define MX1_INT_USBD1		(NR_IRQS_LEGACY + 48)
-#define MX1_INT_USBD2		(NR_IRQS_LEGACY + 49)
-#define MX1_INT_USBD3		(NR_IRQS_LEGACY + 50)
-#define MX1_INT_USBD4		(NR_IRQS_LEGACY + 51)
-#define MX1_INT_USBD5		(NR_IRQS_LEGACY + 52)
-#define MX1_INT_USBD6		(NR_IRQS_LEGACY + 53)
-#define MX1_BTSYS_INT		(NR_IRQS_LEGACY + 55)
-#define MX1_BTTIM_INT		(NR_IRQS_LEGACY + 56)
-#define MX1_BTWUI_INT		(NR_IRQS_LEGACY + 57)
-#define MX1_TIM2_INT		(NR_IRQS_LEGACY + 58)
-#define MX1_TIM1_INT		(NR_IRQS_LEGACY + 59)
-#define MX1_DMA_ERR		(NR_IRQS_LEGACY + 60)
-#define MX1_DMA_INT		(NR_IRQS_LEGACY + 61)
-#define MX1_GPIO_INT_PORTD	(NR_IRQS_LEGACY + 62)
-#define MX1_WDT_INT		(NR_IRQS_LEGACY + 63)
-
-/* DMA */
-#define MX1_DMA_REQ_UART3_T		2
-#define MX1_DMA_REQ_UART3_R		3
-#define MX1_DMA_REQ_SSI2_T		4
-#define MX1_DMA_REQ_SSI2_R		5
-#define MX1_DMA_REQ_CSI_STAT		6
-#define MX1_DMA_REQ_CSI_R		7
-#define MX1_DMA_REQ_MSHC		8
-#define MX1_DMA_REQ_DSPA_DCT_DOUT	9
-#define MX1_DMA_REQ_DSPA_DCT_DIN	10
-#define MX1_DMA_REQ_DSPA_MAC		11
-#define MX1_DMA_REQ_EXT			12
-#define MX1_DMA_REQ_SDHC		13
-#define MX1_DMA_REQ_SPI1_R		14
-#define MX1_DMA_REQ_SPI1_T		15
-#define MX1_DMA_REQ_SSI_T		16
-#define MX1_DMA_REQ_SSI_R		17
-#define MX1_DMA_REQ_ASP_DAC		18
-#define MX1_DMA_REQ_ASP_ADC		19
-#define MX1_DMA_REQ_USP_EP(x)		(20 + (x))
-#define MX1_DMA_REQ_SPI2_R		26
-#define MX1_DMA_REQ_SPI2_T		27
-#define MX1_DMA_REQ_UART2_T		28
-#define MX1_DMA_REQ_UART2_R		29
-#define MX1_DMA_REQ_UART1_T		30
-#define MX1_DMA_REQ_UART1_R		31
-
-/*
- * This doesn't depend on IMX_NEEDS_DEPRECATED_SYMBOLS
- * to not break drivers/usb/gadget/imx_udc.  Should go
- * away after this driver uses the new name.
- */
-#define USBD_INT0		MX1_INT_USBD0
-
-#endif /* ifndef __MACH_MX1_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx21.h b/arch/arm/plat-mxc/include/mach/mx21.h
deleted file mode 100644
index 468738a..0000000
--- a/arch/arm/plat-mxc/include/mach/mx21.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- * Copyright 2009 Holger Schurig, hs4233@mail.mn-solutions.de
- *
- * This contains i.MX21-specific hardware definitions. For those
- * hardware pieces that are common between i.MX21 and i.MX27, have a
- * look at mx2x.h.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- */
-
-#ifndef __MACH_MX21_H__
-#define __MACH_MX21_H__
-
-#define MX21_AIPI_BASE_ADDR		0x10000000
-#define MX21_AIPI_SIZE			SZ_1M
-#define MX21_DMA_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x01000)
-#define MX21_WDOG_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x02000)
-#define MX21_GPT1_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x03000)
-#define MX21_GPT2_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x04000)
-#define MX21_GPT3_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x05000)
-#define MX21_PWM_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x06000)
-#define MX21_RTC_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x07000)
-#define MX21_KPP_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x08000)
-#define MX21_OWIRE_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x09000)
-#define MX21_UART1_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x0a000)
-#define MX21_UART2_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x0b000)
-#define MX21_UART3_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x0c000)
-#define MX21_UART4_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x0d000)
-#define MX21_CSPI1_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x0e000)
-#define MX21_CSPI2_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x0f000)
-#define MX21_SSI1_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x10000)
-#define MX21_SSI2_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x11000)
-#define MX21_I2C_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x12000)
-#define MX21_SDHC1_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x13000)
-#define MX21_SDHC2_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x14000)
-#define MX21_GPIO_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x15000)
-#define MX21_GPIO1_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x000)
-#define MX21_GPIO2_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x100)
-#define MX21_GPIO3_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x200)
-#define MX21_GPIO4_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x300)
-#define MX21_GPIO5_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x400)
-#define MX21_GPIO6_BASE_ADDR			(MX21_GPIO_BASE_ADDR + 0x500)
-#define MX21_AUDMUX_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x16000)
-#define MX21_CSPI3_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x17000)
-#define MX21_LCDC_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x21000)
-#define MX21_SLCDC_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x22000)
-#define MX21_USBOTG_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x24000)
-#define MX21_EMMA_PP_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x26000)
-#define MX21_EMMA_PRP_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x26400)
-#define MX21_CCM_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x27000)
-#define MX21_SYSCTRL_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x27800)
-#define MX21_JAM_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x3e000)
-#define MX21_MAX_BASE_ADDR			(MX21_AIPI_BASE_ADDR + 0x3f000)
-
-#define MX21_AVIC_BASE_ADDR		0x10040000
-
-#define MX21_SAHB1_BASE_ADDR		0x80000000
-#define MX21_SAHB1_SIZE			SZ_1M
-#define MX21_CSI_BASE_ADDR			(MX2x_SAHB1_BASE_ADDR + 0x0000)
-
-/* Memory regions and CS */
-#define MX21_SDRAM_BASE_ADDR		0xc0000000
-#define MX21_CSD1_BASE_ADDR		0xc4000000
-
-#define MX21_CS0_BASE_ADDR		0xc8000000
-#define MX21_CS1_BASE_ADDR		0xcc000000
-#define MX21_CS2_BASE_ADDR		0xd0000000
-#define MX21_CS3_BASE_ADDR		0xd1000000
-#define MX21_CS4_BASE_ADDR		0xd2000000
-#define MX21_PCMCIA_MEM_BASE_ADDR	0xd4000000
-#define MX21_CS5_BASE_ADDR		0xdd000000
-
-/* NAND, SDRAM, WEIM etc controllers */
-#define MX21_X_MEMC_BASE_ADDR		0xdf000000
-#define MX21_X_MEMC_SIZE		SZ_256K
-
-#define MX21_SDRAMC_BASE_ADDR		(MX21_X_MEMC_BASE_ADDR + 0x0000)
-#define MX21_EIM_BASE_ADDR		(MX21_X_MEMC_BASE_ADDR + 0x1000)
-#define MX21_PCMCIA_CTL_BASE_ADDR	(MX21_X_MEMC_BASE_ADDR + 0x2000)
-#define MX21_NFC_BASE_ADDR		(MX21_X_MEMC_BASE_ADDR + 0x3000)
-
-#define MX21_IRAM_BASE_ADDR		0xffffe800	/* internal ram */
-
-#define MX21_IO_P2V(x)			IMX_IO_P2V(x)
-#define MX21_IO_ADDRESS(x)		IOMEM(MX21_IO_P2V(x))
-
-/* fixed interrupt numbers */
-#include <asm/irq.h>
-#define MX21_INT_CSPI3		(NR_IRQS_LEGACY + 6)
-#define MX21_INT_GPIO		(NR_IRQS_LEGACY + 8)
-#define MX21_INT_FIRI		(NR_IRQS_LEGACY + 9)
-#define MX21_INT_SDHC2		(NR_IRQS_LEGACY + 10)
-#define MX21_INT_SDHC1		(NR_IRQS_LEGACY + 11)
-#define MX21_INT_I2C		(NR_IRQS_LEGACY + 12)
-#define MX21_INT_SSI2		(NR_IRQS_LEGACY + 13)
-#define MX21_INT_SSI1		(NR_IRQS_LEGACY + 14)
-#define MX21_INT_CSPI2		(NR_IRQS_LEGACY + 15)
-#define MX21_INT_CSPI1		(NR_IRQS_LEGACY + 16)
-#define MX21_INT_UART4		(NR_IRQS_LEGACY + 17)
-#define MX21_INT_UART3		(NR_IRQS_LEGACY + 18)
-#define MX21_INT_UART2		(NR_IRQS_LEGACY + 19)
-#define MX21_INT_UART1		(NR_IRQS_LEGACY + 20)
-#define MX21_INT_KPP		(NR_IRQS_LEGACY + 21)
-#define MX21_INT_RTC		(NR_IRQS_LEGACY + 22)
-#define MX21_INT_PWM		(NR_IRQS_LEGACY + 23)
-#define MX21_INT_GPT3		(NR_IRQS_LEGACY + 24)
-#define MX21_INT_GPT2		(NR_IRQS_LEGACY + 25)
-#define MX21_INT_GPT1		(NR_IRQS_LEGACY + 26)
-#define MX21_INT_WDOG		(NR_IRQS_LEGACY + 27)
-#define MX21_INT_PCMCIA		(NR_IRQS_LEGACY + 28)
-#define MX21_INT_NFC		(NR_IRQS_LEGACY + 29)
-#define MX21_INT_BMI		(NR_IRQS_LEGACY + 30)
-#define MX21_INT_CSI		(NR_IRQS_LEGACY + 31)
-#define MX21_INT_DMACH0		(NR_IRQS_LEGACY + 32)
-#define MX21_INT_DMACH1		(NR_IRQS_LEGACY + 33)
-#define MX21_INT_DMACH2		(NR_IRQS_LEGACY + 34)
-#define MX21_INT_DMACH3		(NR_IRQS_LEGACY + 35)
-#define MX21_INT_DMACH4		(NR_IRQS_LEGACY + 36)
-#define MX21_INT_DMACH5		(NR_IRQS_LEGACY + 37)
-#define MX21_INT_DMACH6		(NR_IRQS_LEGACY + 38)
-#define MX21_INT_DMACH7		(NR_IRQS_LEGACY + 39)
-#define MX21_INT_DMACH8		(NR_IRQS_LEGACY + 40)
-#define MX21_INT_DMACH9		(NR_IRQS_LEGACY + 41)
-#define MX21_INT_DMACH10	(NR_IRQS_LEGACY + 42)
-#define MX21_INT_DMACH11	(NR_IRQS_LEGACY + 43)
-#define MX21_INT_DMACH12	(NR_IRQS_LEGACY + 44)
-#define MX21_INT_DMACH13	(NR_IRQS_LEGACY + 45)
-#define MX21_INT_DMACH14	(NR_IRQS_LEGACY + 46)
-#define MX21_INT_DMACH15	(NR_IRQS_LEGACY + 47)
-#define MX21_INT_EMMAENC	(NR_IRQS_LEGACY + 49)
-#define MX21_INT_EMMADEC	(NR_IRQS_LEGACY + 50)
-#define MX21_INT_EMMAPRP	(NR_IRQS_LEGACY + 51)
-#define MX21_INT_EMMAPP		(NR_IRQS_LEGACY + 52)
-#define MX21_INT_USBWKUP	(NR_IRQS_LEGACY + 53)
-#define MX21_INT_USBDMA		(NR_IRQS_LEGACY + 54)
-#define MX21_INT_USBHOST	(NR_IRQS_LEGACY + 55)
-#define MX21_INT_USBFUNC	(NR_IRQS_LEGACY + 56)
-#define MX21_INT_USBMNP		(NR_IRQS_LEGACY + 57)
-#define MX21_INT_USBCTRL	(NR_IRQS_LEGACY + 58)
-#define MX21_INT_SLCDC		(NR_IRQS_LEGACY + 60)
-#define MX21_INT_LCDC		(NR_IRQS_LEGACY + 61)
-
-/* fixed DMA request numbers */
-#define MX21_DMA_REQ_CSPI3_RX	1
-#define MX21_DMA_REQ_CSPI3_TX	2
-#define MX21_DMA_REQ_EXT	3
-#define MX21_DMA_REQ_FIRI_RX	4
-#define MX21_DMA_REQ_SDHC2	6
-#define MX21_DMA_REQ_SDHC1	7
-#define MX21_DMA_REQ_SSI2_RX0	8
-#define MX21_DMA_REQ_SSI2_TX0	9
-#define MX21_DMA_REQ_SSI2_RX1	10
-#define MX21_DMA_REQ_SSI2_TX1	11
-#define MX21_DMA_REQ_SSI1_RX0	12
-#define MX21_DMA_REQ_SSI1_TX0	13
-#define MX21_DMA_REQ_SSI1_RX1	14
-#define MX21_DMA_REQ_SSI1_TX1	15
-#define MX21_DMA_REQ_CSPI2_RX	16
-#define MX21_DMA_REQ_CSPI2_TX	17
-#define MX21_DMA_REQ_CSPI1_RX	18
-#define MX21_DMA_REQ_CSPI1_TX	19
-#define MX21_DMA_REQ_UART4_RX	20
-#define MX21_DMA_REQ_UART4_TX	21
-#define MX21_DMA_REQ_UART3_RX	22
-#define MX21_DMA_REQ_UART3_TX	23
-#define MX21_DMA_REQ_UART2_RX	24
-#define MX21_DMA_REQ_UART2_TX	25
-#define MX21_DMA_REQ_UART1_RX	26
-#define MX21_DMA_REQ_UART1_TX	27
-#define MX21_DMA_REQ_BMI_TX	28
-#define MX21_DMA_REQ_BMI_RX	29
-#define MX21_DMA_REQ_CSI_STAT	30
-#define MX21_DMA_REQ_CSI_RX	31
-
-#endif /* ifndef __MACH_MX21_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx25.h b/arch/arm/plat-mxc/include/mach/mx25.h
deleted file mode 100644
index ec46640..0000000
--- a/arch/arm/plat-mxc/include/mach/mx25.h
+++ /dev/null
@@ -1,117 +0,0 @@
-#ifndef __MACH_MX25_H__
-#define __MACH_MX25_H__
-
-#define MX25_AIPS1_BASE_ADDR		0x43f00000
-#define MX25_AIPS1_SIZE			SZ_1M
-#define MX25_AIPS2_BASE_ADDR		0x53f00000
-#define MX25_AIPS2_SIZE			SZ_1M
-#define MX25_AVIC_BASE_ADDR		0x68000000
-#define MX25_AVIC_SIZE			SZ_1M
-
-#define MX25_I2C1_BASE_ADDR		(MX25_AIPS1_BASE_ADDR + 0x80000)
-#define MX25_I2C3_BASE_ADDR		(MX25_AIPS1_BASE_ADDR + 0x84000)
-#define MX25_CAN1_BASE_ADDR		(MX25_AIPS1_BASE_ADDR + 0x88000)
-#define MX25_CAN2_BASE_ADDR		(MX25_AIPS1_BASE_ADDR + 0x8c000)
-#define MX25_I2C2_BASE_ADDR		(MX25_AIPS1_BASE_ADDR + 0x98000)
-#define MX25_CSPI1_BASE_ADDR		(MX25_AIPS1_BASE_ADDR + 0xa4000)
-#define MX25_IOMUXC_BASE_ADDR		(MX25_AIPS1_BASE_ADDR + 0xac000)
-
-#define MX25_CRM_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0x80000)
-#define MX25_GPT1_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0x90000)
-#define MX25_GPIO4_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0x9c000)
-#define MX25_PWM2_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xa0000)
-#define MX25_GPIO3_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xa4000)
-#define MX25_PWM3_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xa8000)
-#define MX25_PWM4_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xc8000)
-#define MX25_GPIO1_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xcc000)
-#define MX25_GPIO2_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xd0000)
-#define MX25_WDOG_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xdc000)
-#define MX25_PWM1_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xe0000)
-
-#define MX25_UART1_BASE_ADDR		0x43f90000
-#define MX25_UART2_BASE_ADDR		0x43f94000
-#define MX25_AUDMUX_BASE_ADDR		0x43fb0000
-#define MX25_UART3_BASE_ADDR		0x5000c000
-#define MX25_UART4_BASE_ADDR		0x50008000
-#define MX25_UART5_BASE_ADDR		0x5002c000
-
-#define MX25_CSPI3_BASE_ADDR		0x50004000
-#define MX25_CSPI2_BASE_ADDR		0x50010000
-#define MX25_FEC_BASE_ADDR		0x50038000
-#define MX25_SSI2_BASE_ADDR		0x50014000
-#define MX25_SSI1_BASE_ADDR		0x50034000
-#define MX25_NFC_BASE_ADDR		0xbb000000
-#define MX25_IIM_BASE_ADDR		0x53ff0000
-#define MX25_DRYICE_BASE_ADDR		0x53ffc000
-#define MX25_ESDHC1_BASE_ADDR		0x53fb4000
-#define MX25_ESDHC2_BASE_ADDR		0x53fb8000
-#define MX25_LCDC_BASE_ADDR		0x53fbc000
-#define MX25_KPP_BASE_ADDR		0x43fa8000
-#define MX25_SDMA_BASE_ADDR		0x53fd4000
-#define MX25_USB_BASE_ADDR		0x53ff4000
-#define MX25_USB_OTG_BASE_ADDR			(MX25_USB_BASE_ADDR + 0x0000)
-/*
- * The reference manual (IMX25RM, Rev. 1, 06/2009) specifies an offset of 0x200
- * for the host controller.  Early documentation drafts specified 0x400 and
- * Freescale internal sources confirm only the latter value to work.
- */
-#define MX25_USB_HS_BASE_ADDR			(MX25_USB_BASE_ADDR + 0x0400)
-#define MX25_CSI_BASE_ADDR		0x53ff8000
-
-#define MX25_IO_P2V(x)			IMX_IO_P2V(x)
-#define MX25_IO_ADDRESS(x)		IOMEM(MX25_IO_P2V(x))
-
-/*
- * Interrupt numbers
- */
-#include <asm/irq.h>
-#define MX25_INT_CSPI3		(NR_IRQS_LEGACY + 0)
-#define MX25_INT_I2C1		(NR_IRQS_LEGACY + 3)
-#define MX25_INT_I2C2		(NR_IRQS_LEGACY + 4)
-#define MX25_INT_UART4		(NR_IRQS_LEGACY + 5)
-#define MX25_INT_ESDHC2		(NR_IRQS_LEGACY + 8)
-#define MX25_INT_ESDHC1		(NR_IRQS_LEGACY + 9)
-#define MX25_INT_I2C3		(NR_IRQS_LEGACY + 10)
-#define MX25_INT_SSI2		(NR_IRQS_LEGACY + 11)
-#define MX25_INT_SSI1		(NR_IRQS_LEGACY + 12)
-#define MX25_INT_CSPI2		(NR_IRQS_LEGACY + 13)
-#define MX25_INT_CSPI1		(NR_IRQS_LEGACY + 14)
-#define MX25_INT_GPIO3		(NR_IRQS_LEGACY + 16)
-#define MX25_INT_CSI		(NR_IRQS_LEGACY + 17)
-#define MX25_INT_UART3		(NR_IRQS_LEGACY + 18)
-#define MX25_INT_GPIO4		(NR_IRQS_LEGACY + 23)
-#define MX25_INT_KPP		(NR_IRQS_LEGACY + 24)
-#define MX25_INT_DRYICE		(NR_IRQS_LEGACY + 25)
-#define MX25_INT_PWM1		(NR_IRQS_LEGACY + 26)
-#define MX25_INT_UART2		(NR_IRQS_LEGACY + 32)
-#define MX25_INT_NFC		(NR_IRQS_LEGACY + 33)
-#define MX25_INT_SDMA		(NR_IRQS_LEGACY + 34)
-#define MX25_INT_USB_HS		(NR_IRQS_LEGACY + 35)
-#define MX25_INT_PWM2		(NR_IRQS_LEGACY + 36)
-#define MX25_INT_USB_OTG	(NR_IRQS_LEGACY + 37)
-#define MX25_INT_LCDC		(NR_IRQS_LEGACY + 39)
-#define MX25_INT_UART5		(NR_IRQS_LEGACY + 40)
-#define MX25_INT_PWM3		(NR_IRQS_LEGACY + 41)
-#define MX25_INT_PWM4		(NR_IRQS_LEGACY + 42)
-#define MX25_INT_CAN1		(NR_IRQS_LEGACY + 43)
-#define MX25_INT_CAN2		(NR_IRQS_LEGACY + 44)
-#define MX25_INT_UART1		(NR_IRQS_LEGACY + 45)
-#define MX25_INT_GPIO2		(NR_IRQS_LEGACY + 51)
-#define MX25_INT_GPIO1		(NR_IRQS_LEGACY + 52)
-#define MX25_INT_GPT1		(NR_IRQS_LEGACY + 54)
-#define MX25_INT_FEC		(NR_IRQS_LEGACY + 57)
-
-#define MX25_DMA_REQ_SSI2_RX1	22
-#define MX25_DMA_REQ_SSI2_TX1	23
-#define MX25_DMA_REQ_SSI2_RX0	24
-#define MX25_DMA_REQ_SSI2_TX0	25
-#define MX25_DMA_REQ_SSI1_RX1	26
-#define MX25_DMA_REQ_SSI1_TX1	27
-#define MX25_DMA_REQ_SSI1_RX0	28
-#define MX25_DMA_REQ_SSI1_TX0	29
-
-#ifndef __ASSEMBLY__
-extern int mx25_revision(void);
-#endif
-
-#endif /* ifndef __MACH_MX25_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx27.h b/arch/arm/plat-mxc/include/mach/mx27.h
deleted file mode 100644
index e074616..0000000
--- a/arch/arm/plat-mxc/include/mach/mx27.h
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * This contains i.MX27-specific hardware definitions. For those
- * hardware pieces that are common between i.MX21 and i.MX27, have a
- * look at mx2x.h.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- */
-
-#ifndef __MACH_MX27_H__
-#define __MACH_MX27_H__
-
-#define MX27_AIPI_BASE_ADDR		0x10000000
-#define MX27_AIPI_SIZE			SZ_1M
-#define MX27_DMA_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x01000)
-#define MX27_WDOG_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x02000)
-#define MX27_GPT1_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x03000)
-#define MX27_GPT2_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x04000)
-#define MX27_GPT3_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x05000)
-#define MX27_PWM_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x06000)
-#define MX27_RTC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x07000)
-#define MX27_KPP_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x08000)
-#define MX27_OWIRE_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x09000)
-#define MX27_UART1_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x0a000)
-#define MX27_UART2_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x0b000)
-#define MX27_UART3_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x0c000)
-#define MX27_UART4_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x0d000)
-#define MX27_CSPI1_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x0e000)
-#define MX27_CSPI2_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x0f000)
-#define MX27_SSI1_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x10000)
-#define MX27_SSI2_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x11000)
-#define MX27_I2C1_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x12000)
-#define MX27_SDHC1_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x13000)
-#define MX27_SDHC2_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x14000)
-#define MX27_GPIO_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x15000)
-#define MX27_GPIO1_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x000)
-#define MX27_GPIO2_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x100)
-#define MX27_GPIO3_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x200)
-#define MX27_GPIO4_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x300)
-#define MX27_GPIO5_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x400)
-#define MX27_GPIO6_BASE_ADDR			(MX27_GPIO_BASE_ADDR + 0x500)
-#define MX27_AUDMUX_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x16000)
-#define MX27_CSPI3_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x17000)
-#define MX27_MSHC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x18000)
-#define MX27_GPT4_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x19000)
-#define MX27_GPT5_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x1a000)
-#define MX27_UART5_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x1b000)
-#define MX27_UART6_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x1c000)
-#define MX27_I2C2_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x1d000)
-#define MX27_SDHC3_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x1e000)
-#define MX27_GPT6_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x1f000)
-#define MX27_LCDC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x21000)
-#define MX27_SLCDC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x22000)
-#define MX27_VPU_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x23000)
-#define MX27_USB_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x24000)
-#define MX27_USB_OTG_BASE_ADDR			(MX27_USB_BASE_ADDR + 0x0000)
-#define MX27_USB_HS1_BASE_ADDR			(MX27_USB_BASE_ADDR + 0x0200)
-#define MX27_USB_HS2_BASE_ADDR			(MX27_USB_BASE_ADDR + 0x0400)
-#define MX27_SAHARA_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x25000)
-#define MX27_EMMAPP_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x26000)
-#define MX27_EMMAPRP_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x26400)
-#define MX27_CCM_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x27000)
-#define MX27_SYSCTRL_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x27800)
-#define MX27_IIM_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x28000)
-#define MX27_RTIC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x2a000)
-#define MX27_FEC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x2b000)
-#define MX27_SCC_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x2c000)
-#define MX27_ETB_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x3b000)
-#define MX27_ETB_RAM_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x3c000)
-#define MX27_JAM_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x3e000)
-#define MX27_MAX_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x3f000)
-
-#define MX27_AVIC_BASE_ADDR		0x10040000
-
-/* ROM patch */
-#define MX27_ROMP_BASE_ADDR		0x10041000
-
-#define MX27_SAHB1_BASE_ADDR		0x80000000
-#define MX27_SAHB1_SIZE			SZ_1M
-#define MX27_CSI_BASE_ADDR			(MX27_SAHB1_BASE_ADDR + 0x0000)
-#define MX27_ATA_BASE_ADDR			(MX27_SAHB1_BASE_ADDR + 0x1000)
-
-/* Memory regions and CS */
-#define MX27_SDRAM_BASE_ADDR		0xa0000000
-#define MX27_CSD1_BASE_ADDR		0xb0000000
-
-#define MX27_CS0_BASE_ADDR		0xc0000000
-#define MX27_CS1_BASE_ADDR		0xc8000000
-#define MX27_CS2_BASE_ADDR		0xd0000000
-#define MX27_CS3_BASE_ADDR		0xd2000000
-#define MX27_CS4_BASE_ADDR		0xd4000000
-#define MX27_CS5_BASE_ADDR		0xd6000000
-
-/* NAND, SDRAM, WEIM, M3IF, EMI controllers */
-#define MX27_X_MEMC_BASE_ADDR		0xd8000000
-#define MX27_X_MEMC_SIZE		SZ_1M
-#define MX27_NFC_BASE_ADDR			(MX27_X_MEMC_BASE_ADDR)
-#define MX27_SDRAMC_BASE_ADDR			(MX27_X_MEMC_BASE_ADDR + 0x1000)
-#define MX27_WEIM_BASE_ADDR			(MX27_X_MEMC_BASE_ADDR + 0x2000)
-#define MX27_M3IF_BASE_ADDR			(MX27_X_MEMC_BASE_ADDR + 0x3000)
-#define MX27_PCMCIA_CTL_BASE_ADDR		(MX27_X_MEMC_BASE_ADDR + 0x4000)
-
-#define MX27_WEIM_CSCRx_BASE_ADDR(cs)	(MX27_WEIM_BASE_ADDR + (cs) * 0x10)
-#define MX27_WEIM_CSCRxU(cs)			(MX27_WEIM_CSCRx_BASE_ADDR(cs))
-#define MX27_WEIM_CSCRxL(cs)			(MX27_WEIM_CSCRx_BASE_ADDR(cs) + 0x4)
-#define MX27_WEIM_CSCRxA(cs)			(MX27_WEIM_CSCRx_BASE_ADDR(cs) + 0x8)
-
-#define MX27_PCMCIA_MEM_BASE_ADDR	0xdc000000
-
-/* IRAM */
-#define MX27_IRAM_BASE_ADDR		0xffff4c00	/* internal ram */
-
-#define MX27_IO_P2V(x)			IMX_IO_P2V(x)
-#define MX27_IO_ADDRESS(x)		IOMEM(MX27_IO_P2V(x))
-
-/* fixed interrupt numbers */
-#include <asm/irq.h>
-#define MX27_INT_I2C2		(NR_IRQS_LEGACY + 1)
-#define MX27_INT_GPT6		(NR_IRQS_LEGACY + 2)
-#define MX27_INT_GPT5		(NR_IRQS_LEGACY + 3)
-#define MX27_INT_GPT4		(NR_IRQS_LEGACY + 4)
-#define MX27_INT_RTIC		(NR_IRQS_LEGACY + 5)
-#define MX27_INT_CSPI3		(NR_IRQS_LEGACY + 6)
-#define MX27_INT_SDHC		(NR_IRQS_LEGACY + 7)
-#define MX27_INT_GPIO		(NR_IRQS_LEGACY + 8)
-#define MX27_INT_SDHC3		(NR_IRQS_LEGACY + 9)
-#define MX27_INT_SDHC2		(NR_IRQS_LEGACY + 10)
-#define MX27_INT_SDHC1		(NR_IRQS_LEGACY + 11)
-#define MX27_INT_I2C1		(NR_IRQS_LEGACY + 12)
-#define MX27_INT_SSI2		(NR_IRQS_LEGACY + 13)
-#define MX27_INT_SSI1		(NR_IRQS_LEGACY + 14)
-#define MX27_INT_CSPI2		(NR_IRQS_LEGACY + 15)
-#define MX27_INT_CSPI1		(NR_IRQS_LEGACY + 16)
-#define MX27_INT_UART4		(NR_IRQS_LEGACY + 17)
-#define MX27_INT_UART3		(NR_IRQS_LEGACY + 18)
-#define MX27_INT_UART2		(NR_IRQS_LEGACY + 19)
-#define MX27_INT_UART1		(NR_IRQS_LEGACY + 20)
-#define MX27_INT_KPP		(NR_IRQS_LEGACY + 21)
-#define MX27_INT_RTC		(NR_IRQS_LEGACY + 22)
-#define MX27_INT_PWM		(NR_IRQS_LEGACY + 23)
-#define MX27_INT_GPT3		(NR_IRQS_LEGACY + 24)
-#define MX27_INT_GPT2		(NR_IRQS_LEGACY + 25)
-#define MX27_INT_GPT1		(NR_IRQS_LEGACY + 26)
-#define MX27_INT_WDOG		(NR_IRQS_LEGACY + 27)
-#define MX27_INT_PCMCIA		(NR_IRQS_LEGACY + 28)
-#define MX27_INT_NFC		(NR_IRQS_LEGACY + 29)
-#define MX27_INT_ATA		(NR_IRQS_LEGACY + 30)
-#define MX27_INT_CSI		(NR_IRQS_LEGACY + 31)
-#define MX27_INT_DMACH0		(NR_IRQS_LEGACY + 32)
-#define MX27_INT_DMACH1		(NR_IRQS_LEGACY + 33)
-#define MX27_INT_DMACH2		(NR_IRQS_LEGACY + 34)
-#define MX27_INT_DMACH3		(NR_IRQS_LEGACY + 35)
-#define MX27_INT_DMACH4		(NR_IRQS_LEGACY + 36)
-#define MX27_INT_DMACH5		(NR_IRQS_LEGACY + 37)
-#define MX27_INT_DMACH6		(NR_IRQS_LEGACY + 38)
-#define MX27_INT_DMACH7		(NR_IRQS_LEGACY + 39)
-#define MX27_INT_DMACH8		(NR_IRQS_LEGACY + 40)
-#define MX27_INT_DMACH9		(NR_IRQS_LEGACY + 41)
-#define MX27_INT_DMACH10	(NR_IRQS_LEGACY + 42)
-#define MX27_INT_DMACH11	(NR_IRQS_LEGACY + 43)
-#define MX27_INT_DMACH12	(NR_IRQS_LEGACY + 44)
-#define MX27_INT_DMACH13	(NR_IRQS_LEGACY + 45)
-#define MX27_INT_DMACH14	(NR_IRQS_LEGACY + 46)
-#define MX27_INT_DMACH15	(NR_IRQS_LEGACY + 47)
-#define MX27_INT_UART6		(NR_IRQS_LEGACY + 48)
-#define MX27_INT_UART5		(NR_IRQS_LEGACY + 49)
-#define MX27_INT_FEC		(NR_IRQS_LEGACY + 50)
-#define MX27_INT_EMMAPRP	(NR_IRQS_LEGACY + 51)
-#define MX27_INT_EMMAPP		(NR_IRQS_LEGACY + 52)
-#define MX27_INT_VPU		(NR_IRQS_LEGACY + 53)
-#define MX27_INT_USB_HS1	(NR_IRQS_LEGACY + 54)
-#define MX27_INT_USB_HS2	(NR_IRQS_LEGACY + 55)
-#define MX27_INT_USB_OTG	(NR_IRQS_LEGACY + 56)
-#define MX27_INT_SCC_SMN	(NR_IRQS_LEGACY + 57)
-#define MX27_INT_SCC_SCM	(NR_IRQS_LEGACY + 58)
-#define MX27_INT_SAHARA		(NR_IRQS_LEGACY + 59)
-#define MX27_INT_SLCDC		(NR_IRQS_LEGACY + 60)
-#define MX27_INT_LCDC		(NR_IRQS_LEGACY + 61)
-#define MX27_INT_IIM		(NR_IRQS_LEGACY + 62)
-#define MX27_INT_CCM		(NR_IRQS_LEGACY + 63)
-
-/* fixed DMA request numbers */
-#define MX27_DMA_REQ_CSPI3_RX	1
-#define MX27_DMA_REQ_CSPI3_TX	2
-#define MX27_DMA_REQ_EXT	3
-#define MX27_DMA_REQ_MSHC	4
-#define MX27_DMA_REQ_SDHC2	6
-#define MX27_DMA_REQ_SDHC1	7
-#define MX27_DMA_REQ_SSI2_RX0	8
-#define MX27_DMA_REQ_SSI2_TX0	9
-#define MX27_DMA_REQ_SSI2_RX1	10
-#define MX27_DMA_REQ_SSI2_TX1	11
-#define MX27_DMA_REQ_SSI1_RX0	12
-#define MX27_DMA_REQ_SSI1_TX0	13
-#define MX27_DMA_REQ_SSI1_RX1	14
-#define MX27_DMA_REQ_SSI1_TX1	15
-#define MX27_DMA_REQ_CSPI2_RX	16
-#define MX27_DMA_REQ_CSPI2_TX	17
-#define MX27_DMA_REQ_CSPI1_RX	18
-#define MX27_DMA_REQ_CSPI1_TX	19
-#define MX27_DMA_REQ_UART4_RX	20
-#define MX27_DMA_REQ_UART4_TX	21
-#define MX27_DMA_REQ_UART3_RX	22
-#define MX27_DMA_REQ_UART3_TX	23
-#define MX27_DMA_REQ_UART2_RX	24
-#define MX27_DMA_REQ_UART2_TX	25
-#define MX27_DMA_REQ_UART1_RX	26
-#define MX27_DMA_REQ_UART1_TX	27
-#define MX27_DMA_REQ_ATA_TX	28
-#define MX27_DMA_REQ_ATA_RCV	29
-#define MX27_DMA_REQ_CSI_STAT	30
-#define MX27_DMA_REQ_CSI_RX	31
-#define MX27_DMA_REQ_UART5_TX	32
-#define MX27_DMA_REQ_UART5_RX	33
-#define MX27_DMA_REQ_UART6_TX	34
-#define MX27_DMA_REQ_UART6_RX	35
-#define MX27_DMA_REQ_SDHC3	36
-#define MX27_DMA_REQ_NFC	37
-
-#ifndef __ASSEMBLY__
-extern int mx27_revision(void);
-#endif
-
-#endif /* ifndef __MACH_MX27_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx2x.h b/arch/arm/plat-mxc/include/mach/mx2x.h
deleted file mode 100644
index 11642f5..0000000
--- a/arch/arm/plat-mxc/include/mach/mx2x.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * This contains hardware definitions that are common between i.MX21 and
- * i.MX27.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- */
-
-#ifndef __MACH_MX2x_H__
-#define __MACH_MX2x_H__
-
-/* The following addresses are common between i.MX21 and i.MX27 */
-
-/* Register offsets */
-#define MX2x_AIPI_BASE_ADDR		0x10000000
-#define MX2x_AIPI_SIZE			SZ_1M
-#define MX2x_DMA_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x01000)
-#define MX2x_WDOG_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x02000)
-#define MX2x_GPT1_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x03000)
-#define MX2x_GPT2_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x04000)
-#define MX2x_GPT3_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x05000)
-#define MX2x_PWM_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x06000)
-#define MX2x_RTC_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x07000)
-#define MX2x_KPP_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x08000)
-#define MX2x_OWIRE_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x09000)
-#define MX2x_UART1_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x0a000)
-#define MX2x_UART2_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x0b000)
-#define MX2x_UART3_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x0c000)
-#define MX2x_UART4_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x0d000)
-#define MX2x_CSPI1_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x0e000)
-#define MX2x_CSPI2_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x0f000)
-#define MX2x_SSI1_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x10000)
-#define MX2x_SSI2_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x11000)
-#define MX2x_I2C_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x12000)
-#define MX2x_SDHC1_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x13000)
-#define MX2x_SDHC2_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x14000)
-#define MX2x_GPIO_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x15000)
-#define MX2x_AUDMUX_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x16000)
-#define MX2x_CSPI3_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x17000)
-#define MX2x_LCDC_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x21000)
-#define MX2x_SLCDC_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x22000)
-#define MX2x_USBOTG_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x24000)
-#define MX2x_EMMA_PP_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x26000)
-#define MX2x_EMMA_PRP_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x26400)
-#define MX2x_CCM_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x27000)
-#define MX2x_SYSCTRL_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x27800)
-#define MX2x_JAM_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x3e000)
-#define MX2x_MAX_BASE_ADDR			(MX2x_AIPI_BASE_ADDR + 0x3f000)
-
-#define MX2x_AVIC_BASE_ADDR		0x10040000
-
-#define MX2x_SAHB1_BASE_ADDR		0x80000000
-#define MX2x_SAHB1_SIZE			SZ_1M
-#define MX2x_CSI_BASE_ADDR			(MX2x_SAHB1_BASE_ADDR + 0x0000)
-
-/* fixed interrupt numbers */
-#include <asm/irq.h>
-#define MX2x_INT_CSPI3		(NR_IRQS_LEGACY + 6)
-#define MX2x_INT_GPIO		(NR_IRQS_LEGACY + 8)
-#define MX2x_INT_SDHC2		(NR_IRQS_LEGACY + 10)
-#define MX2x_INT_SDHC1		(NR_IRQS_LEGACY + 11)
-#define MX2x_INT_I2C		(NR_IRQS_LEGACY + 12)
-#define MX2x_INT_SSI2		(NR_IRQS_LEGACY + 13)
-#define MX2x_INT_SSI1		(NR_IRQS_LEGACY + 14)
-#define MX2x_INT_CSPI2		(NR_IRQS_LEGACY + 15)
-#define MX2x_INT_CSPI1		(NR_IRQS_LEGACY + 16)
-#define MX2x_INT_UART4		(NR_IRQS_LEGACY + 17)
-#define MX2x_INT_UART3		(NR_IRQS_LEGACY + 18)
-#define MX2x_INT_UART2		(NR_IRQS_LEGACY + 19)
-#define MX2x_INT_UART1		(NR_IRQS_LEGACY + 20)
-#define MX2x_INT_KPP		(NR_IRQS_LEGACY + 21)
-#define MX2x_INT_RTC		(NR_IRQS_LEGACY + 22)
-#define MX2x_INT_PWM		(NR_IRQS_LEGACY + 23)
-#define MX2x_INT_GPT3		(NR_IRQS_LEGACY + 24)
-#define MX2x_INT_GPT2		(NR_IRQS_LEGACY + 25)
-#define MX2x_INT_GPT1		(NR_IRQS_LEGACY + 26)
-#define MX2x_INT_WDOG		(NR_IRQS_LEGACY + 27)
-#define MX2x_INT_PCMCIA		(NR_IRQS_LEGACY + 28)
-#define MX2x_INT_NANDFC		(NR_IRQS_LEGACY + 29)
-#define MX2x_INT_CSI		(NR_IRQS_LEGACY + 31)
-#define MX2x_INT_DMACH0		(NR_IRQS_LEGACY + 32)
-#define MX2x_INT_DMACH1		(NR_IRQS_LEGACY + 33)
-#define MX2x_INT_DMACH2		(NR_IRQS_LEGACY + 34)
-#define MX2x_INT_DMACH3		(NR_IRQS_LEGACY + 35)
-#define MX2x_INT_DMACH4		(NR_IRQS_LEGACY + 36)
-#define MX2x_INT_DMACH5		(NR_IRQS_LEGACY + 37)
-#define MX2x_INT_DMACH6		(NR_IRQS_LEGACY + 38)
-#define MX2x_INT_DMACH7		(NR_IRQS_LEGACY + 39)
-#define MX2x_INT_DMACH8		(NR_IRQS_LEGACY + 40)
-#define MX2x_INT_DMACH9		(NR_IRQS_LEGACY + 41)
-#define MX2x_INT_DMACH10	(NR_IRQS_LEGACY + 42)
-#define MX2x_INT_DMACH11	(NR_IRQS_LEGACY + 43)
-#define MX2x_INT_DMACH12	(NR_IRQS_LEGACY + 44)
-#define MX2x_INT_DMACH13	(NR_IRQS_LEGACY + 45)
-#define MX2x_INT_DMACH14	(NR_IRQS_LEGACY + 46)
-#define MX2x_INT_DMACH15	(NR_IRQS_LEGACY + 47)
-#define MX2x_INT_EMMAPRP	(NR_IRQS_LEGACY + 51)
-#define MX2x_INT_EMMAPP		(NR_IRQS_LEGACY + 52)
-#define MX2x_INT_SLCDC		(NR_IRQS_LEGACY + 60)
-#define MX2x_INT_LCDC		(NR_IRQS_LEGACY + 61)
-
-/* fixed DMA request numbers */
-#define MX2x_DMA_REQ_CSPI3_RX	1
-#define MX2x_DMA_REQ_CSPI3_TX	2
-#define MX2x_DMA_REQ_EXT	3
-#define MX2x_DMA_REQ_SDHC2	6
-#define MX2x_DMA_REQ_SDHC1	7
-#define MX2x_DMA_REQ_SSI2_RX0	8
-#define MX2x_DMA_REQ_SSI2_TX0	9
-#define MX2x_DMA_REQ_SSI2_RX1	10
-#define MX2x_DMA_REQ_SSI2_TX1	11
-#define MX2x_DMA_REQ_SSI1_RX0	12
-#define MX2x_DMA_REQ_SSI1_TX0	13
-#define MX2x_DMA_REQ_SSI1_RX1	14
-#define MX2x_DMA_REQ_SSI1_TX1	15
-#define MX2x_DMA_REQ_CSPI2_RX	16
-#define MX2x_DMA_REQ_CSPI2_TX	17
-#define MX2x_DMA_REQ_CSPI1_RX	18
-#define MX2x_DMA_REQ_CSPI1_TX	19
-#define MX2x_DMA_REQ_UART4_RX	20
-#define MX2x_DMA_REQ_UART4_TX	21
-#define MX2x_DMA_REQ_UART3_RX	22
-#define MX2x_DMA_REQ_UART3_TX	23
-#define MX2x_DMA_REQ_UART2_RX	24
-#define MX2x_DMA_REQ_UART2_TX	25
-#define MX2x_DMA_REQ_UART1_RX	26
-#define MX2x_DMA_REQ_UART1_TX	27
-#define MX2x_DMA_REQ_CSI_STAT	30
-#define MX2x_DMA_REQ_CSI_RX	31
-
-#endif /* ifndef __MACH_MX2x_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx31.h b/arch/arm/plat-mxc/include/mach/mx31.h
deleted file mode 100644
index ee9b1f9..0000000
--- a/arch/arm/plat-mxc/include/mach/mx31.h
+++ /dev/null
@@ -1,196 +0,0 @@
-#ifndef __MACH_MX31_H__
-#define __MACH_MX31_H__
-
-/*
- * IRAM
- */
-#define MX31_IRAM_BASE_ADDR		0x1ffc0000	/* internal ram */
-#define MX31_IRAM_SIZE			SZ_16K
-
-#define MX31_L2CC_BASE_ADDR		0x30000000
-#define MX31_L2CC_SIZE			SZ_1M
-
-#define MX31_AIPS1_BASE_ADDR		0x43f00000
-#define MX31_AIPS1_SIZE			SZ_1M
-#define MX31_MAX_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x04000)
-#define MX31_EVTMON_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x08000)
-#define MX31_CLKCTL_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x0c000)
-#define MX31_ETB_SLOT4_BASE_ADDR		(MX31_AIPS1_BASE_ADDR + 0x10000)
-#define MX31_ETB_SLOT5_BASE_ADDR		(MX31_AIPS1_BASE_ADDR + 0x14000)
-#define MX31_ECT_CTIO_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x18000)
-#define MX31_I2C1_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x80000)
-#define MX31_I2C3_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x84000)
-#define MX31_USB_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x88000)
-#define MX31_USB_OTG_BASE_ADDR			(MX31_USB_BASE_ADDR + 0x0000)
-#define MX31_USB_HS1_BASE_ADDR			(MX31_USB_BASE_ADDR + 0x0200)
-#define MX31_USB_HS2_BASE_ADDR			(MX31_USB_BASE_ADDR + 0x0400)
-#define MX31_ATA_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x8c000)
-#define MX31_UART1_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x90000)
-#define MX31_UART2_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x94000)
-#define MX31_I2C2_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x98000)
-#define MX31_OWIRE_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0x9c000)
-#define MX31_SSI1_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xa0000)
-#define MX31_CSPI1_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xa4000)
-#define MX31_KPP_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xa8000)
-#define MX31_IOMUXC_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xac000)
-#define MX31_UART4_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xb0000)
-#define MX31_UART5_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xb4000)
-#define MX31_ECT_IP1_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xb8000)
-#define MX31_ECT_IP2_BASE_ADDR			(MX31_AIPS1_BASE_ADDR + 0xbc000)
-
-#define MX31_SPBA0_BASE_ADDR		0x50000000
-#define MX31_SPBA0_SIZE			SZ_1M
-#define MX31_SDHC1_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x04000)
-#define MX31_SDHC2_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x08000)
-#define MX31_UART3_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x0c000)
-#define MX31_CSPI2_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x10000)
-#define MX31_SSI2_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x14000)
-#define MX31_SIM1_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x18000)
-#define MX31_IIM_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x1c000)
-#define MX31_ATA_DMA_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x20000)
-#define MX31_MSHC1_BASE_ADDR			(MX31_SPBA0_BASE_ADDR + 0x24000)
-#define MX31_SPBA_CTRL_BASE_ADDR		(MX31_SPBA0_BASE_ADDR + 0x3c000)
-
-#define MX31_AIPS2_BASE_ADDR		0x53f00000
-#define MX31_AIPS2_SIZE			SZ_1M
-#define MX31_CCM_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0x80000)
-#define MX31_CSPI3_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0x84000)
-#define MX31_FIRI_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0x8c000)
-#define MX31_GPT1_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0x90000)
-#define MX31_EPIT1_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0x94000)
-#define MX31_EPIT2_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0x98000)
-#define MX31_GPIO3_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xa4000)
-#define MX31_SCC_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xac000)
-#define MX31_SCM_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xae000)
-#define MX31_SMN_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xaf000)
-#define MX31_RNGA_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xb0000)
-#define MX31_IPU_CTRL_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xc0000)
-#define MX31_AUDMUX_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xc4000)
-#define MX31_MPEG4_ENC_BASE_ADDR		(MX31_AIPS2_BASE_ADDR + 0xc8000)
-#define MX31_GPIO1_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xcc000)
-#define MX31_GPIO2_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xd0000)
-#define MX31_SDMA_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xd4000)
-#define MX31_RTC_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xd8000)
-#define MX31_WDOG_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xdc000)
-#define MX31_PWM_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xe0000)
-#define MX31_RTIC_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xec000)
-
-#define MX31_ROMP_BASE_ADDR		0x60000000
-#define MX31_ROMP_BASE_ADDR_VIRT	IOMEM(0xfc500000)
-#define MX31_ROMP_SIZE			SZ_1M
-
-#define MX31_AVIC_BASE_ADDR		0x68000000
-#define MX31_AVIC_SIZE			SZ_1M
-
-#define MX31_IPU_MEM_BASE_ADDR		0x70000000
-#define MX31_CSD0_BASE_ADDR		0x80000000
-#define MX31_CSD1_BASE_ADDR		0x90000000
-
-#define MX31_CS0_BASE_ADDR		0xa0000000
-#define MX31_CS1_BASE_ADDR		0xa8000000
-#define MX31_CS2_BASE_ADDR		0xb0000000
-#define MX31_CS3_BASE_ADDR		0xb2000000
-
-#define MX31_CS4_BASE_ADDR		0xb4000000
-#define MX31_CS4_BASE_ADDR_VIRT		IOMEM(0xf6000000)
-#define MX31_CS4_SIZE			SZ_32M
-
-#define MX31_CS5_BASE_ADDR		0xb6000000
-#define MX31_CS5_BASE_ADDR_VIRT		IOMEM(0xf8000000)
-#define MX31_CS5_SIZE			SZ_32M
-
-#define MX31_X_MEMC_BASE_ADDR		0xb8000000
-#define MX31_X_MEMC_SIZE		SZ_64K
-#define MX31_NFC_BASE_ADDR			(MX31_X_MEMC_BASE_ADDR + 0x0000)
-#define MX31_ESDCTL_BASE_ADDR			(MX31_X_MEMC_BASE_ADDR + 0x1000)
-#define MX31_WEIM_BASE_ADDR			(MX31_X_MEMC_BASE_ADDR + 0x2000)
-#define MX31_M3IF_BASE_ADDR			(MX31_X_MEMC_BASE_ADDR + 0x3000)
-#define MX31_EMI_CTL_BASE_ADDR			(MX31_X_MEMC_BASE_ADDR + 0x4000)
-#define MX31_PCMCIA_CTL_BASE_ADDR		MX31_EMI_CTL_BASE_ADDR
-
-#define MX31_WEIM_CSCRx_BASE_ADDR(cs)	(MX31_WEIM_BASE_ADDR + (cs) * 0x10)
-#define MX31_WEIM_CSCRxU(cs)			(MX31_WEIM_CSCRx_BASE_ADDR(cs))
-#define MX31_WEIM_CSCRxL(cs)			(MX31_WEIM_CSCRx_BASE_ADDR(cs) + 0x4)
-#define MX31_WEIM_CSCRxA(cs)			(MX31_WEIM_CSCRx_BASE_ADDR(cs) + 0x8)
-
-#define MX31_PCMCIA_MEM_BASE_ADDR	0xbc000000
-
-#define MX31_IO_P2V(x)			IMX_IO_P2V(x)
-#define MX31_IO_ADDRESS(x)		IOMEM(MX31_IO_P2V(x))
-
-/*
- * Interrupt numbers
- */
-#include <asm/irq.h>
-#define MX31_INT_I2C3		(NR_IRQS_LEGACY + 3)
-#define MX31_INT_I2C2		(NR_IRQS_LEGACY + 4)
-#define MX31_INT_MPEG4_ENCODER	(NR_IRQS_LEGACY + 5)
-#define MX31_INT_RTIC		(NR_IRQS_LEGACY + 6)
-#define MX31_INT_FIRI		(NR_IRQS_LEGACY + 7)
-#define MX31_INT_SDHC2		(NR_IRQS_LEGACY + 8)
-#define MX31_INT_SDHC1		(NR_IRQS_LEGACY + 9)
-#define MX31_INT_I2C1		(NR_IRQS_LEGACY + 10)
-#define MX31_INT_SSI2		(NR_IRQS_LEGACY + 11)
-#define MX31_INT_SSI1		(NR_IRQS_LEGACY + 12)
-#define MX31_INT_CSPI2		(NR_IRQS_LEGACY + 13)
-#define MX31_INT_CSPI1		(NR_IRQS_LEGACY + 14)
-#define MX31_INT_ATA		(NR_IRQS_LEGACY + 15)
-#define MX31_INT_MBX		(NR_IRQS_LEGACY + 16)
-#define MX31_INT_CSPI3		(NR_IRQS_LEGACY + 17)
-#define MX31_INT_UART3		(NR_IRQS_LEGACY + 18)
-#define MX31_INT_IIM		(NR_IRQS_LEGACY + 19)
-#define MX31_INT_SIM2		(NR_IRQS_LEGACY + 20)
-#define MX31_INT_SIM1		(NR_IRQS_LEGACY + 21)
-#define MX31_INT_RNGA		(NR_IRQS_LEGACY + 22)
-#define MX31_INT_EVTMON		(NR_IRQS_LEGACY + 23)
-#define MX31_INT_KPP		(NR_IRQS_LEGACY + 24)
-#define MX31_INT_RTC		(NR_IRQS_LEGACY + 25)
-#define MX31_INT_PWM		(NR_IRQS_LEGACY + 26)
-#define MX31_INT_EPIT2		(NR_IRQS_LEGACY + 27)
-#define MX31_INT_EPIT1		(NR_IRQS_LEGACY + 28)
-#define MX31_INT_GPT		(NR_IRQS_LEGACY + 29)
-#define MX31_INT_POWER_FAIL	(NR_IRQS_LEGACY + 30)
-#define MX31_INT_CCM_DVFS	(NR_IRQS_LEGACY + 31)
-#define MX31_INT_UART2		(NR_IRQS_LEGACY + 32)
-#define MX31_INT_NFC		(NR_IRQS_LEGACY + 33)
-#define MX31_INT_SDMA		(NR_IRQS_LEGACY + 34)
-#define MX31_INT_USB_HS1	(NR_IRQS_LEGACY + 35)
-#define MX31_INT_USB_HS2	(NR_IRQS_LEGACY + 36)
-#define MX31_INT_USB_OTG	(NR_IRQS_LEGACY + 37)
-#define MX31_INT_MSHC1		(NR_IRQS_LEGACY + 39)
-#define MX31_INT_MSHC2		(NR_IRQS_LEGACY + 40)
-#define MX31_INT_IPU_ERR	(NR_IRQS_LEGACY + 41)
-#define MX31_INT_IPU_SYN	(NR_IRQS_LEGACY + 42)
-#define MX31_INT_UART1		(NR_IRQS_LEGACY + 45)
-#define MX31_INT_UART4		(NR_IRQS_LEGACY + 46)
-#define MX31_INT_UART5		(NR_IRQS_LEGACY + 47)
-#define MX31_INT_ECT		(NR_IRQS_LEGACY + 48)
-#define MX31_INT_SCC_SCM	(NR_IRQS_LEGACY + 49)
-#define MX31_INT_SCC_SMN	(NR_IRQS_LEGACY + 50)
-#define MX31_INT_GPIO2		(NR_IRQS_LEGACY + 51)
-#define MX31_INT_GPIO1		(NR_IRQS_LEGACY + 52)
-#define MX31_INT_CCM		(NR_IRQS_LEGACY + 53)
-#define MX31_INT_PCMCIA		(NR_IRQS_LEGACY + 54)
-#define MX31_INT_WDOG		(NR_IRQS_LEGACY + 55)
-#define MX31_INT_GPIO3		(NR_IRQS_LEGACY + 56)
-#define MX31_INT_EXT_POWER	(NR_IRQS_LEGACY + 58)
-#define MX31_INT_EXT_TEMPER	(NR_IRQS_LEGACY + 59)
-#define MX31_INT_EXT_SENSOR60	(NR_IRQS_LEGACY + 60)
-#define MX31_INT_EXT_SENSOR61	(NR_IRQS_LEGACY + 61)
-#define MX31_INT_EXT_WDOG	(NR_IRQS_LEGACY + 62)
-#define MX31_INT_EXT_TV		(NR_IRQS_LEGACY + 63)
-
-#define MX31_DMA_REQ_SDHC1	20
-#define MX31_DMA_REQ_SDHC2	21
-#define MX31_DMA_REQ_SSI2_RX1	22
-#define MX31_DMA_REQ_SSI2_TX1	23
-#define MX31_DMA_REQ_SSI2_RX0	24
-#define MX31_DMA_REQ_SSI2_TX0	25
-#define MX31_DMA_REQ_SSI1_RX1	26
-#define MX31_DMA_REQ_SSI1_TX1	27
-#define MX31_DMA_REQ_SSI1_RX0	28
-#define MX31_DMA_REQ_SSI1_TX0	29
-
-#define MX31_PROD_SIGNATURE		0x1	/* For MX31 */
-
-#endif /* ifndef __MACH_MX31_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx35.h b/arch/arm/plat-mxc/include/mach/mx35.h
deleted file mode 100644
index 2af5d3a..0000000
--- a/arch/arm/plat-mxc/include/mach/mx35.h
+++ /dev/null
@@ -1,190 +0,0 @@
-#ifndef __MACH_MX35_H__
-#define __MACH_MX35_H__
-
-/*
- * IRAM
- */
-#define MX35_IRAM_BASE_ADDR		0x10000000	/* internal ram */
-#define MX35_IRAM_SIZE			SZ_128K
-
-#define MX35_L2CC_BASE_ADDR		0x30000000
-#define MX35_L2CC_SIZE			SZ_1M
-
-#define MX35_AIPS1_BASE_ADDR		0x43f00000
-#define MX35_AIPS1_SIZE			SZ_1M
-#define MX35_MAX_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x04000)
-#define MX35_EVTMON_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x08000)
-#define MX35_CLKCTL_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x0c000)
-#define MX35_ETB_SLOT4_BASE_ADDR		(MX35_AIPS1_BASE_ADDR + 0x10000)
-#define MX35_ETB_SLOT5_BASE_ADDR		(MX35_AIPS1_BASE_ADDR + 0x14000)
-#define MX35_ECT_CTIO_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x18000)
-#define MX35_I2C1_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x80000)
-#define MX35_I2C3_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x84000)
-#define MX35_UART1_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x90000)
-#define MX35_UART2_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x94000)
-#define MX35_I2C2_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x98000)
-#define MX35_OWIRE_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0x9c000)
-#define MX35_SSI1_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0xa0000)
-#define MX35_CSPI1_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0xa4000)
-#define MX35_KPP_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0xa8000)
-#define MX35_IOMUXC_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0xac000)
-#define MX35_ECT_IP1_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0xb8000)
-#define MX35_ECT_IP2_BASE_ADDR			(MX35_AIPS1_BASE_ADDR + 0xbc000)
-
-#define MX35_SPBA0_BASE_ADDR		0x50000000
-#define MX35_SPBA0_SIZE			SZ_1M
-#define MX35_UART3_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x0c000)
-#define MX35_CSPI2_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x10000)
-#define MX35_SSI2_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x14000)
-#define MX35_ATA_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x20000)
-#define MX35_MSHC1_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x24000)
-#define MX35_FEC_BASE_ADDR		0x50038000
-#define MX35_SPBA_CTRL_BASE_ADDR		(MX35_SPBA0_BASE_ADDR + 0x3c000)
-
-#define MX35_AIPS2_BASE_ADDR		0x53f00000
-#define MX35_AIPS2_SIZE			SZ_1M
-#define MX35_CCM_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0x80000)
-#define MX35_GPT1_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0x90000)
-#define MX35_EPIT1_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0x94000)
-#define MX35_EPIT2_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0x98000)
-#define MX35_GPIO3_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xa4000)
-#define MX35_SCC_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xac000)
-#define MX35_RNGA_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xb0000)
-#define MX35_ESDHC1_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xb4000)
-#define MX35_ESDHC2_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xb8000)
-#define MX35_ESDHC3_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xbc000)
-#define MX35_IPU_CTRL_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xc0000)
-#define MX35_AUDMUX_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xc4000)
-#define MX35_GPIO1_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xcc000)
-#define MX35_GPIO2_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xd0000)
-#define MX35_SDMA_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xd4000)
-#define MX35_RTC_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xd8000)
-#define MX35_WDOG_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xdc000)
-#define MX35_PWM_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xe0000)
-#define MX35_CAN1_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xe4000)
-#define MX35_CAN2_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xe8000)
-#define MX35_RTIC_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xec000)
-#define MX35_IIM_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xf0000)
-#define MX35_USB_BASE_ADDR			(MX35_AIPS2_BASE_ADDR + 0xf4000)
-#define MX35_USB_OTG_BASE_ADDR			(MX35_USB_BASE_ADDR + 0x0000)
-/*
- * The Reference Manual (IMX35RM, Rev. 2, 3/2009) claims an offset of 0x200 for
- * HS.  When host support was implemented only a preliminary document was
- * available, which told 0x400.  This works fine.
- */
-#define MX35_USB_HS_BASE_ADDR			(MX35_USB_BASE_ADDR + 0x0400)
-
-#define MX35_ROMP_BASE_ADDR		0x60000000
-#define MX35_ROMP_SIZE			SZ_1M
-
-#define MX35_AVIC_BASE_ADDR		0x68000000
-#define MX35_AVIC_SIZE			SZ_1M
-
-/*
- * Memory regions and CS
- */
-#define MX35_IPU_MEM_BASE_ADDR		0x70000000
-#define MX35_CSD0_BASE_ADDR		0x80000000
-#define MX35_CSD1_BASE_ADDR		0x90000000
-
-#define MX35_CS0_BASE_ADDR		0xa0000000
-#define MX35_CS1_BASE_ADDR		0xa8000000
-#define MX35_CS2_BASE_ADDR		0xb0000000
-#define MX35_CS3_BASE_ADDR		0xb2000000
-
-#define MX35_CS4_BASE_ADDR		0xb4000000
-#define MX35_CS4_BASE_ADDR_VIRT		0xf6000000
-#define MX35_CS4_SIZE			SZ_32M
-
-#define MX35_CS5_BASE_ADDR		0xb6000000
-#define MX35_CS5_BASE_ADDR_VIRT		0xf8000000
-#define MX35_CS5_SIZE			SZ_32M
-
-/*
- * NAND, SDRAM, WEIM, M3IF, EMI controllers
- */
-#define MX35_X_MEMC_BASE_ADDR		0xb8000000
-#define MX35_X_MEMC_SIZE		SZ_64K
-#define MX35_ESDCTL_BASE_ADDR			(MX35_X_MEMC_BASE_ADDR + 0x1000)
-#define MX35_WEIM_BASE_ADDR			(MX35_X_MEMC_BASE_ADDR + 0x2000)
-#define MX35_M3IF_BASE_ADDR			(MX35_X_MEMC_BASE_ADDR + 0x3000)
-#define MX35_EMI_CTL_BASE_ADDR			(MX35_X_MEMC_BASE_ADDR + 0x4000)
-#define MX35_PCMCIA_CTL_BASE_ADDR		MX35_EMI_CTL_BASE_ADDR
-
-#define MX35_NFC_BASE_ADDR		0xbb000000
-#define MX35_PCMCIA_MEM_BASE_ADDR	0xbc000000
-
-#define MX35_IO_P2V(x)			IMX_IO_P2V(x)
-#define MX35_IO_ADDRESS(x)		IOMEM(MX35_IO_P2V(x))
-
-/*
- * Interrupt numbers
- */
-#include <asm/irq.h>
-#define MX35_INT_OWIRE		(NR_IRQS_LEGACY + 2)
-#define MX35_INT_I2C3		(NR_IRQS_LEGACY + 3)
-#define MX35_INT_I2C2		(NR_IRQS_LEGACY + 4)
-#define MX35_INT_RTIC		(NR_IRQS_LEGACY + 6)
-#define MX35_INT_ESDHC1		(NR_IRQS_LEGACY + 7)
-#define MX35_INT_ESDHC2		(NR_IRQS_LEGACY + 8)
-#define MX35_INT_ESDHC3		(NR_IRQS_LEGACY + 9)
-#define MX35_INT_I2C1		(NR_IRQS_LEGACY + 10)
-#define MX35_INT_SSI1		(NR_IRQS_LEGACY + 11)
-#define MX35_INT_SSI2		(NR_IRQS_LEGACY + 12)
-#define MX35_INT_CSPI2		(NR_IRQS_LEGACY + 13)
-#define MX35_INT_CSPI1		(NR_IRQS_LEGACY + 14)
-#define MX35_INT_ATA		(NR_IRQS_LEGACY + 15)
-#define MX35_INT_GPU2D		(NR_IRQS_LEGACY + 16)
-#define MX35_INT_ASRC		(NR_IRQS_LEGACY + 17)
-#define MX35_INT_UART3		(NR_IRQS_LEGACY + 18)
-#define MX35_INT_IIM		(NR_IRQS_LEGACY + 19)
-#define MX35_INT_RNGA		(NR_IRQS_LEGACY + 22)
-#define MX35_INT_EVTMON		(NR_IRQS_LEGACY + 23)
-#define MX35_INT_KPP		(NR_IRQS_LEGACY + 24)
-#define MX35_INT_RTC		(NR_IRQS_LEGACY + 25)
-#define MX35_INT_PWM		(NR_IRQS_LEGACY + 26)
-#define MX35_INT_EPIT2		(NR_IRQS_LEGACY + 27)
-#define MX35_INT_EPIT1		(NR_IRQS_LEGACY + 28)
-#define MX35_INT_GPT		(NR_IRQS_LEGACY + 29)
-#define MX35_INT_POWER_FAIL	(NR_IRQS_LEGACY + 30)
-#define MX35_INT_UART2		(NR_IRQS_LEGACY + 32)
-#define MX35_INT_NFC		(NR_IRQS_LEGACY + 33)
-#define MX35_INT_SDMA		(NR_IRQS_LEGACY + 34)
-#define MX35_INT_USB_HS		(NR_IRQS_LEGACY + 35)
-#define MX35_INT_USB_OTG	(NR_IRQS_LEGACY + 37)
-#define MX35_INT_MSHC1		(NR_IRQS_LEGACY + 39)
-#define MX35_INT_ESAI		(NR_IRQS_LEGACY + 40)
-#define MX35_INT_IPU_ERR	(NR_IRQS_LEGACY + 41)
-#define MX35_INT_IPU_SYN	(NR_IRQS_LEGACY + 42)
-#define MX35_INT_CAN1		(NR_IRQS_LEGACY + 43)
-#define MX35_INT_CAN2		(NR_IRQS_LEGACY + 44)
-#define MX35_INT_UART1		(NR_IRQS_LEGACY + 45)
-#define MX35_INT_MLB		(NR_IRQS_LEGACY + 46)
-#define MX35_INT_SPDIF		(NR_IRQS_LEGACY + 47)
-#define MX35_INT_ECT		(NR_IRQS_LEGACY + 48)
-#define MX35_INT_SCC_SCM	(NR_IRQS_LEGACY + 49)
-#define MX35_INT_SCC_SMN	(NR_IRQS_LEGACY + 50)
-#define MX35_INT_GPIO2		(NR_IRQS_LEGACY + 51)
-#define MX35_INT_GPIO1		(NR_IRQS_LEGACY + 52)
-#define MX35_INT_WDOG		(NR_IRQS_LEGACY + 55)
-#define MX35_INT_GPIO3		(NR_IRQS_LEGACY + 56)
-#define MX35_INT_FEC		(NR_IRQS_LEGACY + 57)
-#define MX35_INT_EXT_POWER	(NR_IRQS_LEGACY + 58)
-#define MX35_INT_EXT_TEMPER	(NR_IRQS_LEGACY + 59)
-#define MX35_INT_EXT_SENSOR60	(NR_IRQS_LEGACY + 60)
-#define MX35_INT_EXT_SENSOR61	(NR_IRQS_LEGACY + 61)
-#define MX35_INT_EXT_WDOG	(NR_IRQS_LEGACY + 62)
-#define MX35_INT_EXT_TV		(NR_IRQS_LEGACY + 63)
-
-#define MX35_DMA_REQ_SSI2_RX1   22
-#define MX35_DMA_REQ_SSI2_TX1   23
-#define MX35_DMA_REQ_SSI2_RX0   24
-#define MX35_DMA_REQ_SSI2_TX0   25
-#define MX35_DMA_REQ_SSI1_RX1   26
-#define MX35_DMA_REQ_SSI1_TX1   27
-#define MX35_DMA_REQ_SSI1_RX0   28
-#define MX35_DMA_REQ_SSI1_TX0   29
-
-#define MX35_PROD_SIGNATURE		0x1	/* For MX31 */
-
-#endif /* ifndef __MACH_MX35_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx3x.h b/arch/arm/plat-mxc/include/mach/mx3x.h
deleted file mode 100644
index 96fb4fb..0000000
--- a/arch/arm/plat-mxc/include/mach/mx3x.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __MACH_MX3x_H__
-#define __MACH_MX3x_H__
-
-/*
- * MX31 memory map:
- *
- * Virt		Phys		Size	What
- * ---------------------------------------------------------------------------
- * FC000000	43F00000	1M	AIPS 1
- * FC100000	50000000	1M	SPBA
- * FC200000	53F00000	1M	AIPS 2
- * FC500000	60000000	128M	ROMPATCH
- * FC400000	68000000	128M	AVIC
- *         	70000000	256M	IPU (MAX M2)
- *         	80000000	256M	CSD0 SDRAM/DDR
- *         	90000000	256M	CSD1 SDRAM/DDR
- *         	A0000000	128M	CS0 Flash
- *         	A8000000	128M	CS1 Flash
- *         	B0000000	32M	CS2
- *         	B2000000	32M	CS3
- * F4000000	B4000000	32M	CS4
- *         	B6000000	32M	CS5
- * FC320000	B8000000	64K	NAND, SDRAM, WEIM, M3IF, EMI controllers
- *         	C0000000	64M	PCMCIA/CF
- */
-
-/*
- * L2CC
- */
-#define MX3x_L2CC_BASE_ADDR		0x30000000
-#define MX3x_L2CC_SIZE			SZ_1M
-
-/*
- * AIPS 1
- */
-#define MX3x_AIPS1_BASE_ADDR		0x43f00000
-#define MX3x_AIPS1_SIZE			SZ_1M
-#define MX3x_MAX_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x04000)
-#define MX3x_EVTMON_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x08000)
-#define MX3x_CLKCTL_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x0c000)
-#define MX3x_ETB_SLOT4_BASE_ADDR		(MX3x_AIPS1_BASE_ADDR + 0x10000)
-#define MX3x_ETB_SLOT5_BASE_ADDR		(MX3x_AIPS1_BASE_ADDR + 0x14000)
-#define MX3x_ECT_CTIO_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x18000)
-#define MX3x_I2C_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x80000)
-#define MX3x_I2C3_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x84000)
-#define MX3x_UART1_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x90000)
-#define MX3x_UART2_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x94000)
-#define MX3x_I2C2_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x98000)
-#define MX3x_OWIRE_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0x9c000)
-#define MX3x_SSI1_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0xa0000)
-#define MX3x_CSPI1_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0xa4000)
-#define MX3x_KPP_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0xa8000)
-#define MX3x_IOMUXC_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0xac000)
-#define MX3x_ECT_IP1_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0xb8000)
-#define MX3x_ECT_IP2_BASE_ADDR			(MX3x_AIPS1_BASE_ADDR + 0xbc000)
-
-/*
- * SPBA global module enabled #0
- */
-#define MX3x_SPBA0_BASE_ADDR		0x50000000
-#define MX3x_SPBA0_SIZE			SZ_1M
-#define MX3x_UART3_BASE_ADDR			(MX3x_SPBA0_BASE_ADDR + 0x0c000)
-#define MX3x_CSPI2_BASE_ADDR			(MX3x_SPBA0_BASE_ADDR + 0x10000)
-#define MX3x_SSI2_BASE_ADDR			(MX3x_SPBA0_BASE_ADDR + 0x14000)
-#define MX3x_ATA_DMA_BASE_ADDR			(MX3x_SPBA0_BASE_ADDR + 0x20000)
-#define MX3x_MSHC1_BASE_ADDR			(MX3x_SPBA0_BASE_ADDR + 0x24000)
-#define MX3x_SPBA_CTRL_BASE_ADDR		(MX3x_SPBA0_BASE_ADDR + 0x3c000)
-
-/*
- * AIPS 2
- */
-#define MX3x_AIPS2_BASE_ADDR		0x53f00000
-#define MX3x_AIPS2_SIZE			SZ_1M
-#define MX3x_CCM_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0x80000)
-#define MX3x_GPT1_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0x90000)
-#define MX3x_EPIT1_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0x94000)
-#define MX3x_EPIT2_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0x98000)
-#define MX3x_GPIO3_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xa4000)
-#define MX3x_SCC_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xac000)
-#define MX3x_RNGA_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xb0000)
-#define MX3x_IPU_CTRL_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xc0000)
-#define MX3x_AUDMUX_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xc4000)
-#define MX3x_GPIO1_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xcc000)
-#define MX3x_GPIO2_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xd0000)
-#define MX3x_SDMA_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xd4000)
-#define MX3x_RTC_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xd8000)
-#define MX3x_WDOG_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xdc000)
-#define MX3x_PWM_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xe0000)
-#define MX3x_RTIC_BASE_ADDR			(MX3x_AIPS2_BASE_ADDR + 0xec000)
-
-/*
- * ROMP and AVIC
- */
-#define MX3x_ROMP_BASE_ADDR		0x60000000
-#define MX3x_ROMP_SIZE			SZ_1M
-
-#define MX3x_AVIC_BASE_ADDR		0x68000000
-#define MX3x_AVIC_SIZE			SZ_1M
-
-/*
- * Memory regions and CS
- */
-#define MX3x_IPU_MEM_BASE_ADDR		0x70000000
-#define MX3x_CSD0_BASE_ADDR		0x80000000
-#define MX3x_CSD1_BASE_ADDR		0x90000000
-
-#define MX3x_CS0_BASE_ADDR		0xa0000000
-#define MX3x_CS1_BASE_ADDR		0xa8000000
-#define MX3x_CS2_BASE_ADDR		0xb0000000
-#define MX3x_CS3_BASE_ADDR		0xb2000000
-
-#define MX3x_CS4_BASE_ADDR		0xb4000000
-#define MX3x_CS4_BASE_ADDR_VIRT		0xf6000000
-#define MX3x_CS4_SIZE			SZ_32M
-
-#define MX3x_CS5_BASE_ADDR		0xb6000000
-#define MX3x_CS5_BASE_ADDR_VIRT		0xf8000000
-#define MX3x_CS5_SIZE			SZ_32M
-
-/*
- * NAND, SDRAM, WEIM, M3IF, EMI controllers
- */
-#define MX3x_X_MEMC_BASE_ADDR		0xb8000000
-#define MX3x_X_MEMC_SIZE		SZ_64K
-#define MX3x_ESDCTL_BASE_ADDR			(MX3x_X_MEMC_BASE_ADDR + 0x1000)
-#define MX3x_WEIM_BASE_ADDR			(MX3x_X_MEMC_BASE_ADDR + 0x2000)
-#define MX3x_M3IF_BASE_ADDR			(MX3x_X_MEMC_BASE_ADDR + 0x3000)
-#define MX3x_EMI_CTL_BASE_ADDR			(MX3x_X_MEMC_BASE_ADDR + 0x4000)
-#define MX3x_PCMCIA_CTL_BASE_ADDR		MX3x_EMI_CTL_BASE_ADDR
-
-#define MX3x_PCMCIA_MEM_BASE_ADDR	0xbc000000
-
-/*
- * Interrupt numbers
- */
-#include <asm/irq.h>
-#define MX3x_INT_I2C3		(NR_IRQS_LEGACY + 3)
-#define MX3x_INT_I2C2		(NR_IRQS_LEGACY + 4)
-#define MX3x_INT_RTIC		(NR_IRQS_LEGACY + 6)
-#define MX3x_INT_I2C		(NR_IRQS_LEGACY + 10)
-#define MX3x_INT_CSPI2		(NR_IRQS_LEGACY + 13)
-#define MX3x_INT_CSPI1		(NR_IRQS_LEGACY + 14)
-#define MX3x_INT_ATA		(NR_IRQS_LEGACY + 15)
-#define MX3x_INT_UART3		(NR_IRQS_LEGACY + 18)
-#define MX3x_INT_IIM		(NR_IRQS_LEGACY + 19)
-#define MX3x_INT_RNGA		(NR_IRQS_LEGACY + 22)
-#define MX3x_INT_EVTMON		(NR_IRQS_LEGACY + 23)
-#define MX3x_INT_KPP		(NR_IRQS_LEGACY + 24)
-#define MX3x_INT_RTC		(NR_IRQS_LEGACY + 25)
-#define MX3x_INT_PWM		(NR_IRQS_LEGACY + 26)
-#define MX3x_INT_EPIT2		(NR_IRQS_LEGACY + 27)
-#define MX3x_INT_EPIT1		(NR_IRQS_LEGACY + 28)
-#define MX3x_INT_GPT		(NR_IRQS_LEGACY + 29)
-#define MX3x_INT_POWER_FAIL	(NR_IRQS_LEGACY + 30)
-#define MX3x_INT_UART2		(NR_IRQS_LEGACY + 32)
-#define MX3x_INT_NANDFC		(NR_IRQS_LEGACY + 33)
-#define MX3x_INT_SDMA		(NR_IRQS_LEGACY + 34)
-#define MX3x_INT_MSHC1		(NR_IRQS_LEGACY + 39)
-#define MX3x_INT_IPU_ERR	(NR_IRQS_LEGACY + 41)
-#define MX3x_INT_IPU_SYN	(NR_IRQS_LEGACY + 42)
-#define MX3x_INT_UART1		(NR_IRQS_LEGACY + 45)
-#define MX3x_INT_ECT		(NR_IRQS_LEGACY + 48)
-#define MX3x_INT_SCC_SCM	(NR_IRQS_LEGACY + 49)
-#define MX3x_INT_SCC_SMN	(NR_IRQS_LEGACY + 50)
-#define MX3x_INT_GPIO2		(NR_IRQS_LEGACY + 51)
-#define MX3x_INT_GPIO1		(NR_IRQS_LEGACY + 52)
-#define MX3x_INT_WDOG		(NR_IRQS_LEGACY + 55)
-#define MX3x_INT_GPIO3		(NR_IRQS_LEGACY + 56)
-#define MX3x_INT_EXT_POWER	(NR_IRQS_LEGACY + 58)
-#define MX3x_INT_EXT_TEMPER	(NR_IRQS_LEGACY + 59)
-#define MX3x_INT_EXT_SENSOR60	(NR_IRQS_LEGACY + 60)
-#define MX3x_INT_EXT_SENSOR61	(NR_IRQS_LEGACY + 61)
-#define MX3x_INT_EXT_WDOG	(NR_IRQS_LEGACY + 62)
-#define MX3x_INT_EXT_TV		(NR_IRQS_LEGACY + 63)
-
-#define MX3x_PROD_SIGNATURE		0x1	/* For MX31 */
-
-/* Mandatory defines used globally */
-
-#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
-extern int mx35_revision(void);
-extern int mx31_revision(void);
-#endif
-
-#endif /* ifndef __MACH_MX3x_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx50.h b/arch/arm/plat-mxc/include/mach/mx50.h
deleted file mode 100644
index 09ac19c..0000000
--- a/arch/arm/plat-mxc/include/mach/mx50.h
+++ /dev/null
@@ -1,290 +0,0 @@
-#ifndef __MACH_MX50_H__
-#define __MACH_MX50_H__
-
-/*
- * IROM
- */
-#define MX50_IROM_BASE_ADDR		0x0
-#define MX50_IROM_SIZE			SZ_64K
-
-/* TZIC */
-#define MX50_TZIC_BASE_ADDR		0x0fffc000
-#define MX50_TZIC_SIZE			SZ_16K
-
-/*
- * IRAM
- */
-#define MX50_IRAM_BASE_ADDR	0xf8000000	/* internal ram */
-#define MX50_IRAM_PARTITIONS	16
-#define MX50_IRAM_SIZE		(MX50_IRAM_PARTITIONS * SZ_8K)	/* 128KB */
-
-/*
- * Databahn
- */
-#define MX50_DATABAHN_BASE_ADDR			0x14000000
-
-/*
- * Graphics Memory of GPU
- */
-#define MX50_GPU2D_BASE_ADDR		0x20000000
-
-#define MX50_DEBUG_BASE_ADDR		0x40000000
-#define MX50_DEBUG_SIZE			SZ_1M
-#define MX50_ETB_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00001000)
-#define MX50_ETM_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00002000)
-#define MX50_TPIU_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00003000)
-#define MX50_CTI0_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00004000)
-#define MX50_CTI1_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00005000)
-#define MX50_CTI2_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00006000)
-#define MX50_CTI3_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00007000)
-#define MX50_CORTEX_DBG_BASE_ADDR	(MX50_DEBUG_BASE_ADDR + 0x00008000)
-
-#define MX50_APBHDMA_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01000000)
-#define MX50_OCOTP_CTRL_BASE_ADDR	(MX50_DEBUG_BASE_ADDR + 0x01002000)
-#define MX50_DIGCTL_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01004000)
-#define MX50_GPMI_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01006000)
-#define MX50_BCH_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01008000)
-#define MX50_ELCDIF_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x0100a000)
-#define MX50_EPXP_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x0100c000)
-#define MX50_DCP_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x0100e000)
-#define MX50_EPDC_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01010000)
-#define MX50_QOSC_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01012000)
-#define MX50_PERFMON_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01014000)
-#define MX50_SSP_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01016000)
-#define MX50_ANATOP_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01018000)
-#define MX50_NIC_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x08000000)
-
-/*
- * SPBA global module enabled #0
- */
-#define MX50_SPBA0_BASE_ADDR		0x50000000
-#define MX50_SPBA0_SIZE			SZ_1M
-
-#define MX50_MMC_SDHC1_BASE_ADDR	(MX50_SPBA0_BASE_ADDR + 0x00004000)
-#define MX50_MMC_SDHC2_BASE_ADDR	(MX50_SPBA0_BASE_ADDR + 0x00008000)
-#define MX50_UART3_BASE_ADDR		(MX50_SPBA0_BASE_ADDR + 0x0000c000)
-#define MX50_CSPI1_BASE_ADDR		(MX50_SPBA0_BASE_ADDR + 0x00010000)
-#define MX50_SSI2_BASE_ADDR		(MX50_SPBA0_BASE_ADDR + 0x00014000)
-#define MX50_MMC_SDHC3_BASE_ADDR	(MX50_SPBA0_BASE_ADDR + 0x00020000)
-#define MX50_MMC_SDHC4_BASE_ADDR	(MX50_SPBA0_BASE_ADDR + 0x00024000)
-
-/*
- * AIPS 1
- */
-#define MX50_AIPS1_BASE_ADDR	0x53f00000
-#define MX50_AIPS1_SIZE		SZ_1M
-
-#define MX50_OTG_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00080000)
-#define MX50_GPIO1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00084000)
-#define MX50_GPIO2_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00088000)
-#define MX50_GPIO3_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x0008c000)
-#define MX50_GPIO4_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00090000)
-#define MX50_KPP_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00094000)
-#define MX50_WDOG_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00098000)
-#define MX50_GPT1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000a0000)
-#define MX50_SRTC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000a4000)
-#define MX50_IOMUXC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000a8000)
-#define MX50_EPIT1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000ac000)
-#define MX50_PWM1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000b4000)
-#define MX50_PWM2_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000b8000)
-#define MX50_UART1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000bc000)
-#define MX50_UART2_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000c0000)
-#define MX50_SRC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000d0000)
-#define MX50_CCM_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000d4000)
-#define MX50_GPC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000d8000)
-#define MX50_GPIO5_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000dc000)
-#define MX50_GPIO6_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000e0000)
-#define MX50_I2C3_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000ec000)
-#define MX50_UART4_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000f0000)
-
-#define MX50_MSHC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000f4000)
-#define MX50_RNGB_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000f8000)
-
-/*
- * AIPS 2
- */
-#define MX50_AIPS2_BASE_ADDR	0x63f00000
-#define MX50_AIPS2_SIZE		SZ_1M
-
-#define MX50_PLL1_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00080000)
-#define MX50_PLL2_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00084000)
-#define MX50_PLL3_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00088000)
-#define MX50_UART5_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00090000)
-#define MX50_AHBMAX_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00094000)
-#define MX50_ARM_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000a0000)
-#define MX50_OWIRE_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000a4000)
-#define MX50_CSPI2_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000ac000)
-#define MX50_SDMA_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000b0000)
-#define MX50_ROMCP_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000b8000)
-#define MX50_CSPI3_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000c0000)
-#define MX50_I2C2_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000c4000)
-#define MX50_I2C1_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000c8000)
-#define MX50_SSI1_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000cc000)
-#define MX50_AUDMUX_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000d0000)
-#define MX50_WEIM_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000d8000)
-#define MX50_FEC_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000ec000)
-
-/*
- * Memory regions and CS
- */
-#define MX50_CSD0_BASE_ADDR		0x70000000
-#define MX50_CSD1_BASE_ADDR		0xb0000000
-#define MX50_CS0_BASE_ADDR		0xf0000000
-
-#define MX50_IO_P2V(x)			IMX_IO_P2V(x)
-#define MX50_IO_ADDRESS(x)		IOMEM(MX50_IO_P2V(x))
-
-/*
- * defines for SPBA modules
- */
-#define MX50_SPBA_SDHC1		0x04
-#define MX50_SPBA_SDHC2		0x08
-#define MX50_SPBA_UART3		0x0c
-#define MX50_SPBA_CSPI1		0x10
-#define MX50_SPBA_SSI2		0x14
-#define MX50_SPBA_SDHC3		0x20
-#define MX50_SPBA_SDHC4		0x24
-#define MX50_SPBA_SPDIF		0x28
-#define MX50_SPBA_ATA		0x30
-#define MX50_SPBA_SLIM		0x34
-#define MX50_SPBA_HSI2C		0x38
-#define MX50_SPBA_CTRL		0x3c
-
-/*
- * DMA request assignments
- */
-#define MX50_DMA_REQ_GPC		1
-#define MX50_DMA_REQ_ATA_UART4_RX	2
-#define MX50_DMA_REQ_ATA_UART4_TX	3
-#define MX50_DMA_REQ_CSPI1_RX		6
-#define MX50_DMA_REQ_CSPI1_TX		7
-#define MX50_DMA_REQ_CSPI2_RX		8
-#define MX50_DMA_REQ_CSPI2_TX		9
-#define MX50_DMA_REQ_I2C3_SDHC3		10
-#define MX50_DMA_REQ_SDHC4		11
-#define MX50_DMA_REQ_UART2_FIRI_RX	12
-#define MX50_DMA_REQ_UART2_FIRI_TX	13
-#define MX50_DMA_REQ_EXT0		14
-#define MX50_DMA_REQ_EXT1		15
-#define MX50_DMA_REQ_UART5_RX		16
-#define MX50_DMA_REQ_UART5_TX		17
-#define MX50_DMA_REQ_UART1_RX		18
-#define MX50_DMA_REQ_UART1_TX		19
-#define MX50_DMA_REQ_I2C1_SDHC1		20
-#define MX50_DMA_REQ_I2C2_SDHC2		21
-#define MX50_DMA_REQ_SSI2_RX2		22
-#define MX50_DMA_REQ_SSI2_TX2		23
-#define MX50_DMA_REQ_SSI2_RX1		24
-#define MX50_DMA_REQ_SSI2_TX1		25
-#define MX50_DMA_REQ_SSI1_RX2		26
-#define MX50_DMA_REQ_SSI1_TX2		27
-#define MX50_DMA_REQ_SSI1_RX1		28
-#define MX50_DMA_REQ_SSI1_TX1		29
-#define MX50_DMA_REQ_CSPI_RX		38
-#define MX50_DMA_REQ_CSPI_TX		39
-#define MX50_DMA_REQ_UART3_RX		42
-#define MX50_DMA_REQ_UART3_TX		43
-
-/*
- * Interrupt numbers
- */
-#include <asm/irq.h>
-#define MX50_INT_MMC_SDHC1	(NR_IRQS_LEGACY + 1)
-#define MX50_INT_MMC_SDHC2	(NR_IRQS_LEGACY + 2)
-#define MX50_INT_MMC_SDHC3	(NR_IRQS_LEGACY + 3)
-#define MX50_INT_MMC_SDHC4	(NR_IRQS_LEGACY + 4)
-#define MX50_INT_DAP		(NR_IRQS_LEGACY + 5)
-#define MX50_INT_SDMA		(NR_IRQS_LEGACY + 6)
-#define MX50_INT_IOMUX		(NR_IRQS_LEGACY + 7)
-#define MX50_INT_UART4		(NR_IRQS_LEGACY + 13)
-#define MX50_INT_USB_H1		(NR_IRQS_LEGACY + 14)
-#define MX50_INT_USB_OTG	(NR_IRQS_LEGACY + 18)
-#define MX50_INT_DATABAHN	(NR_IRQS_LEGACY + 19)
-#define MX50_INT_ELCDIF		(NR_IRQS_LEGACY + 20)
-#define MX50_INT_EPXP		(NR_IRQS_LEGACY + 21)
-#define MX50_INT_SRTC_NTZ	(NR_IRQS_LEGACY + 24)
-#define MX50_INT_SRTC_TZ	(NR_IRQS_LEGACY + 25)
-#define MX50_INT_EPDC		(NR_IRQS_LEGACY + 27)
-#define MX50_INT_NIC		(NR_IRQS_LEGACY + 28)
-#define MX50_INT_SSI1		(NR_IRQS_LEGACY + 29)
-#define MX50_INT_SSI2		(NR_IRQS_LEGACY + 30)
-#define MX50_INT_UART1		(NR_IRQS_LEGACY + 31)
-#define MX50_INT_UART2		(NR_IRQS_LEGACY + 32)
-#define MX50_INT_UART3		(NR_IRQS_LEGACY + 33)
-#define MX50_INT_RESV34		(NR_IRQS_LEGACY + 34)
-#define MX50_INT_RESV35		(NR_IRQS_LEGACY + 35)
-#define MX50_INT_CSPI1		(NR_IRQS_LEGACY + 36)
-#define MX50_INT_CSPI2		(NR_IRQS_LEGACY + 37)
-#define MX50_INT_CSPI		(NR_IRQS_LEGACY + 38)
-#define MX50_INT_GPT		(NR_IRQS_LEGACY + 39)
-#define MX50_INT_EPIT1		(NR_IRQS_LEGACY + 40)
-#define MX50_INT_GPIO1_INT7	(NR_IRQS_LEGACY + 42)
-#define MX50_INT_GPIO1_INT6	(NR_IRQS_LEGACY + 43)
-#define MX50_INT_GPIO1_INT5	(NR_IRQS_LEGACY + 44)
-#define MX50_INT_GPIO1_INT4	(NR_IRQS_LEGACY + 45)
-#define MX50_INT_GPIO1_INT3	(NR_IRQS_LEGACY + 46)
-#define MX50_INT_GPIO1_INT2	(NR_IRQS_LEGACY + 47)
-#define MX50_INT_GPIO1_INT1	(NR_IRQS_LEGACY + 48)
-#define MX50_INT_GPIO1_INT0	(NR_IRQS_LEGACY + 49)
-#define MX50_INT_GPIO1_LOW	(NR_IRQS_LEGACY + 50)
-#define MX50_INT_GPIO1_HIGH	(NR_IRQS_LEGACY + 51)
-#define MX50_INT_GPIO2_LOW	(NR_IRQS_LEGACY + 52)
-#define MX50_INT_GPIO2_HIGH	(NR_IRQS_LEGACY + 53)
-#define MX50_INT_GPIO3_LOW	(NR_IRQS_LEGACY + 54)
-#define MX50_INT_GPIO3_HIGH	(NR_IRQS_LEGACY + 55)
-#define MX50_INT_GPIO4_LOW	(NR_IRQS_LEGACY + 56)
-#define MX50_INT_GPIO4_HIGH	(NR_IRQS_LEGACY + 57)
-#define MX50_INT_WDOG1		(NR_IRQS_LEGACY + 58)
-#define MX50_INT_KPP		(NR_IRQS_LEGACY + 60)
-#define MX50_INT_PWM1		(NR_IRQS_LEGACY + 61)
-#define MX50_INT_I2C1		(NR_IRQS_LEGACY + 62)
-#define MX50_INT_I2C2		(NR_IRQS_LEGACY + 63)
-#define MX50_INT_I2C3		(NR_IRQS_LEGACY + 64)
-#define MX50_INT_RESV65		(NR_IRQS_LEGACY + 65)
-#define MX50_INT_DCDC		(NR_IRQS_LEGACY + 66)
-#define MX50_INT_THERMAL_ALARM	(NR_IRQS_LEGACY + 67)
-#define MX50_INT_ANA3		(NR_IRQS_LEGACY + 68)
-#define MX50_INT_ANA4		(NR_IRQS_LEGACY + 69)
-#define MX50_INT_CCM1		(NR_IRQS_LEGACY + 71)
-#define MX50_INT_CCM2		(NR_IRQS_LEGACY + 72)
-#define MX50_INT_GPC1		(NR_IRQS_LEGACY + 73)
-#define MX50_INT_GPC2		(NR_IRQS_LEGACY + 74)
-#define MX50_INT_SRC		(NR_IRQS_LEGACY + 75)
-#define MX50_INT_NM		(NR_IRQS_LEGACY + 76)
-#define MX50_INT_PMU		(NR_IRQS_LEGACY + 77)
-#define MX50_INT_CTI_IRQ	(NR_IRQS_LEGACY + 78)
-#define MX50_INT_CTI1_TG0	(NR_IRQS_LEGACY + 79)
-#define MX50_INT_CTI1_TG1	(NR_IRQS_LEGACY + 80)
-#define MX50_INT_GPU2_IRQ	(NR_IRQS_LEGACY + 84)
-#define MX50_INT_GPU2_BUSY	(NR_IRQS_LEGACY + 85)
-#define MX50_INT_UART5		(NR_IRQS_LEGACY + 86)
-#define MX50_INT_FEC		(NR_IRQS_LEGACY + 87)
-#define MX50_INT_OWIRE		(NR_IRQS_LEGACY + 88)
-#define MX50_INT_CTI1_TG2	(NR_IRQS_LEGACY + 89)
-#define MX50_INT_SJC		(NR_IRQS_LEGACY + 90)
-#define MX50_INT_DCP_CHAN1_3	(NR_IRQS_LEGACY + 91)
-#define MX50_INT_DCP_CHAN0	(NR_IRQS_LEGACY + 92)
-#define MX50_INT_PWM2		(NR_IRQS_LEGACY + 94)
-#define MX50_INT_RNGB		(NR_IRQS_LEGACY + 97)
-#define MX50_INT_CTI1_TG3	(NR_IRQS_LEGACY + 98)
-#define MX50_INT_RAWNAND_BCH	(NR_IRQS_LEGACY + 100)
-#define MX50_INT_RAWNAND_GPMI	(NR_IRQS_LEGACY + 102)
-#define MX50_INT_GPIO5_LOW	(NR_IRQS_LEGACY + 103)
-#define MX50_INT_GPIO5_HIGH	(NR_IRQS_LEGACY + 104)
-#define MX50_INT_GPIO6_LOW	(NR_IRQS_LEGACY + 105)
-#define MX50_INT_GPIO6_HIGH	(NR_IRQS_LEGACY + 106)
-#define MX50_INT_MSHC		(NR_IRQS_LEGACY + 109)
-#define MX50_INT_APBHDMA_CHAN0	(NR_IRQS_LEGACY + 110)
-#define MX50_INT_APBHDMA_CHAN1	(NR_IRQS_LEGACY + 111)
-#define MX50_INT_APBHDMA_CHAN2	(NR_IRQS_LEGACY + 112)
-#define MX50_INT_APBHDMA_CHAN3	(NR_IRQS_LEGACY + 113)
-#define MX50_INT_APBHDMA_CHAN4	(NR_IRQS_LEGACY + 114)
-#define MX50_INT_APBHDMA_CHAN5	(NR_IRQS_LEGACY + 115)
-#define MX50_INT_APBHDMA_CHAN6	(NR_IRQS_LEGACY + 116)
-#define MX50_INT_APBHDMA_CHAN7	(NR_IRQS_LEGACY + 117)
-
-#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
-extern int mx50_revision(void);
-#endif
-
-#endif /* ifndef __MACH_MX50_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx51.h b/arch/arm/plat-mxc/include/mach/mx51.h
deleted file mode 100644
index af844f7..0000000
--- a/arch/arm/plat-mxc/include/mach/mx51.h
+++ /dev/null
@@ -1,346 +0,0 @@
-#ifndef __MACH_MX51_H__
-#define __MACH_MX51_H__
-
-/*
- * IROM
- */
-#define MX51_IROM_BASE_ADDR		0x0
-#define MX51_IROM_SIZE			SZ_64K
-
-/*
- * IRAM
- */
-#define MX51_IRAM_BASE_ADDR		0x1ffe0000	/* internal ram */
-#define MX51_IRAM_PARTITIONS		16
-#define MX51_IRAM_SIZE		(MX51_IRAM_PARTITIONS * SZ_8K)	/* 128KB */
-
-#define MX51_GPU_BASE_ADDR		0x20000000
-#define MX51_GPU_CTRL_BASE_ADDR		0x30000000
-#define MX51_IPU_CTRL_BASE_ADDR		0x40000000
-
-/*
- * SPBA global module enabled #0
- */
-#define MX51_SPBA0_BASE_ADDR		0x70000000
-#define MX51_SPBA0_SIZE			SZ_1M
-
-#define MX51_ESDHC1_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x04000)
-#define MX51_ESDHC2_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x08000)
-#define MX51_UART3_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x0c000)
-#define MX51_ECSPI1_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x10000)
-#define MX51_SSI2_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x14000)
-#define MX51_ESDHC3_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x20000)
-#define MX51_ESDHC4_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x24000)
-#define MX51_SPDIF_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x28000)
-#define MX51_ATA_DMA_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x30000)
-#define MX51_SLIM_DMA_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x34000)
-#define MX51_HSI2C_DMA_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x38000)
-#define MX51_SPBA_CTRL_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x3c000)
-
-/*
- * AIPS 1
- */
-#define MX51_AIPS1_BASE_ADDR		0x73f00000
-#define MX51_AIPS1_SIZE			SZ_1M
-
-#define MX51_USB_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x80000)
-#define MX51_USB_OTG_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0000)
-#define MX51_USB_HS1_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0200)
-#define MX51_USB_HS2_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0400)
-#define MX51_GPIO1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x84000)
-#define MX51_GPIO2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x88000)
-#define MX51_GPIO3_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x8c000)
-#define MX51_GPIO4_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x90000)
-#define MX51_KPP_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x94000)
-#define MX51_WDOG1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x98000)
-#define MX51_WDOG2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x9c000)
-#define MX51_GPT1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xa0000)
-#define MX51_SRTC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xa4000)
-#define MX51_IOMUXC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xa8000)
-#define MX51_EPIT1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xac000)
-#define MX51_EPIT2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xb0000)
-#define MX51_PWM1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xb4000)
-#define MX51_PWM2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xb8000)
-#define MX51_UART1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xbc000)
-#define MX51_UART2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xc0000)
-#define MX51_SRC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xd0000)
-#define MX51_CCM_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xd4000)
-#define MX51_GPC_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0xd8000)
-
-/*
- * AIPS 2
- */
-#define MX51_AIPS2_BASE_ADDR		0x83f00000
-#define MX51_AIPS2_SIZE			SZ_1M
-
-#define MX51_PLL1_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x80000)
-#define MX51_PLL2_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x84000)
-#define MX51_PLL3_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x88000)
-#define MX51_AHBMAX_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x94000)
-#define MX51_IIM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x98000)
-#define MX51_CSU_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0x9c000)
-#define MX51_ARM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xa0000)
-#define MX51_OWIRE_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xa4000)
-#define MX51_FIRI_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xa8000)
-#define MX51_ECSPI2_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xac000)
-#define MX51_SDMA_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xb0000)
-#define MX51_SCC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xb4000)
-#define MX51_ROMCP_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xb8000)
-#define MX51_RTIC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xbc000)
-#define MX51_CSPI_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xc0000)
-#define MX51_I2C2_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xc4000)
-#define MX51_I2C1_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xc8000)
-#define MX51_SSI1_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xcc000)
-#define MX51_AUDMUX_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xd0000)
-#define MX51_M4IF_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xd8000)
-#define MX51_ESDCTL_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xd9000)
-#define MX51_WEIM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xda000)
-#define MX51_NFC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xdb000)
-#define MX51_EMI_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xdbf00)
-#define MX51_MIPI_HSC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xdc000)
-#define MX51_ATA_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xe0000)
-#define MX51_SIM_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xe4000)
-#define MX51_SSI3_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xe8000)
-#define MX51_FEC_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xec000)
-#define MX51_TVE_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xf0000)
-#define MX51_VPU_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xf4000)
-#define MX51_SAHARA_BASE_ADDR		(MX51_AIPS2_BASE_ADDR + 0xf8000)
-
-#define MX51_CSD0_BASE_ADDR		0x90000000
-#define MX51_CSD1_BASE_ADDR		0xa0000000
-#define MX51_CS0_BASE_ADDR		0xb0000000
-#define MX51_CS1_BASE_ADDR		0xb8000000
-#define MX51_CS2_BASE_ADDR		0xc0000000
-#define MX51_CS3_BASE_ADDR		0xc8000000
-#define MX51_CS4_BASE_ADDR		0xcc000000
-#define MX51_CS5_BASE_ADDR		0xce000000
-
-/*
- * NFC
- */
-#define MX51_NFC_AXI_BASE_ADDR		0xcfff0000	/* NAND flash AXI */
-#define MX51_NFC_AXI_SIZE		SZ_64K
-
-#define MX51_GPU2D_BASE_ADDR		0xd0000000
-#define MX51_TZIC_BASE_ADDR		0xe0000000
-#define MX51_TZIC_SIZE			SZ_16K
-
-#define MX51_IO_P2V(x)			IMX_IO_P2V(x)
-#define MX51_IO_ADDRESS(x)		IOMEM(MX51_IO_P2V(x))
-
-/*
- * defines for SPBA modules
- */
-#define MX51_SPBA_SDHC1	0x04
-#define MX51_SPBA_SDHC2	0x08
-#define MX51_SPBA_UART3	0x0c
-#define MX51_SPBA_CSPI1	0x10
-#define MX51_SPBA_SSI2	0x14
-#define MX51_SPBA_SDHC3	0x20
-#define MX51_SPBA_SDHC4	0x24
-#define MX51_SPBA_SPDIF	0x28
-#define MX51_SPBA_ATA	0x30
-#define MX51_SPBA_SLIM	0x34
-#define MX51_SPBA_HSI2C	0x38
-#define MX51_SPBA_CTRL	0x3c
-
-/*
- * Defines for modules using static and dynamic DMA channels
- */
-#define MX51_MXC_DMA_CHANNEL_IRAM	30
-#define MX51_MXC_DMA_CHANNEL_SPDIF_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART1_RX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART1_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART2_RX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART2_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART3_RX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART3_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_MMC1	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_MMC2	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_SSI1_RX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_SSI1_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_SSI2_RX	MXC_DMA_DYNAMIC_CHANNEL
-#ifdef CONFIG_SDMA_IRAM
-#define MX51_MXC_DMA_CHANNEL_SSI2_TX	(MX51_MXC_DMA_CHANNEL_IRAM + 1)
-#else				/*CONFIG_SDMA_IRAM */
-#define MX51_MXC_DMA_CHANNEL_SSI2_TX	MXC_DMA_DYNAMIC_CHANNEL
-#endif				/*CONFIG_SDMA_IRAM */
-#define MX51_MXC_DMA_CHANNEL_CSPI1_RX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_CSPI1_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_CSPI2_RX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_CSPI2_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_CSPI3_RX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_CSPI3_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_ATA_RX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_ATA_TX	MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_MEMORY	MXC_DMA_DYNAMIC_CHANNEL
-
-#define MX51_IS_MEM_DEVICE_NONSHARED(x)		0
-
-/*
- * DMA request assignments
- */
-#define MX51_DMA_REQ_VPU		0
-#define MX51_DMA_REQ_GPC		1
-#define MX51_DMA_REQ_ATA_RX		2
-#define MX51_DMA_REQ_ATA_TX		3
-#define MX51_DMA_REQ_ATA_TX_END		4
-#define MX51_DMA_REQ_SLIM_B		5
-#define MX51_DMA_REQ_CSPI1_RX		6
-#define MX51_DMA_REQ_CSPI1_TX		7
-#define MX51_DMA_REQ_CSPI2_RX		8
-#define MX51_DMA_REQ_CSPI2_TX		9
-#define MX51_DMA_REQ_HS_I2C_TX		10
-#define MX51_DMA_REQ_HS_I2C_RX		11
-#define MX51_DMA_REQ_FIRI_RX		12
-#define MX51_DMA_REQ_FIRI_TX		13
-#define MX51_DMA_REQ_EXTREQ1		14
-#define MX51_DMA_REQ_GPU		15
-#define MX51_DMA_REQ_UART2_RX		16
-#define MX51_DMA_REQ_UART2_TX		17
-#define MX51_DMA_REQ_UART1_RX		18
-#define MX51_DMA_REQ_UART1_TX		19
-#define MX51_DMA_REQ_SDHC1		20
-#define MX51_DMA_REQ_SDHC2		21
-#define MX51_DMA_REQ_SSI2_RX1		22
-#define MX51_DMA_REQ_SSI2_TX1		23
-#define MX51_DMA_REQ_SSI2_RX0		24
-#define MX51_DMA_REQ_SSI2_TX0		25
-#define MX51_DMA_REQ_SSI1_RX1		26
-#define MX51_DMA_REQ_SSI1_TX1		27
-#define MX51_DMA_REQ_SSI1_RX0		28
-#define MX51_DMA_REQ_SSI1_TX0		29
-#define MX51_DMA_REQ_EMI_RD		30
-#define MX51_DMA_REQ_CTI2_0		31
-#define MX51_DMA_REQ_EMI_WR		32
-#define MX51_DMA_REQ_CTI2_1		33
-#define MX51_DMA_REQ_EPIT2		34
-#define MX51_DMA_REQ_SSI3_RX1		35
-#define MX51_DMA_REQ_IPU		36
-#define MX51_DMA_REQ_SSI3_TX1		37
-#define MX51_DMA_REQ_CSPI_RX		38
-#define MX51_DMA_REQ_CSPI_TX		39
-#define MX51_DMA_REQ_SDHC3		40
-#define MX51_DMA_REQ_SDHC4		41
-#define MX51_DMA_REQ_SLIM_B_TX		42
-#define MX51_DMA_REQ_UART3_RX		43
-#define MX51_DMA_REQ_UART3_TX		44
-#define MX51_DMA_REQ_SPDIF		45
-#define MX51_DMA_REQ_SSI3_RX0		46
-#define MX51_DMA_REQ_SSI3_TX0		47
-
-/*
- * Interrupt numbers
- */
-#include <asm/irq.h>
-#define MX51_INT_BASE			(NR_IRQS_LEGACY + 0)
-#define MX51_INT_RESV0			(NR_IRQS_LEGACY + 0)
-#define MX51_INT_ESDHC1			(NR_IRQS_LEGACY + 1)
-#define MX51_INT_ESDHC2			(NR_IRQS_LEGACY + 2)
-#define MX51_INT_ESDHC3			(NR_IRQS_LEGACY + 3)
-#define MX51_INT_ESDHC4			(NR_IRQS_LEGACY + 4)
-#define MX51_INT_RESV5			(NR_IRQS_LEGACY + 5)
-#define MX51_INT_SDMA			(NR_IRQS_LEGACY + 6)
-#define MX51_INT_IOMUX			(NR_IRQS_LEGACY + 7)
-#define MX51_INT_NFC			(NR_IRQS_LEGACY + 8)
-#define MX51_INT_VPU			(NR_IRQS_LEGACY + 9)
-#define MX51_INT_IPU_ERR		(NR_IRQS_LEGACY + 10)
-#define MX51_INT_IPU_SYN		(NR_IRQS_LEGACY + 11)
-#define MX51_INT_GPU			(NR_IRQS_LEGACY + 12)
-#define MX51_INT_RESV13			(NR_IRQS_LEGACY + 13)
-#define MX51_INT_USB_HS1		(NR_IRQS_LEGACY + 14)
-#define MX51_INT_EMI			(NR_IRQS_LEGACY + 15)
-#define MX51_INT_USB_HS2		(NR_IRQS_LEGACY + 16)
-#define MX51_INT_USB_HS3		(NR_IRQS_LEGACY + 17)
-#define MX51_INT_USB_OTG		(NR_IRQS_LEGACY + 18)
-#define MX51_INT_SAHARA_H0		(NR_IRQS_LEGACY + 19)
-#define MX51_INT_SAHARA_H1		(NR_IRQS_LEGACY + 20)
-#define MX51_INT_SCC_SMN		(NR_IRQS_LEGACY + 21)
-#define MX51_INT_SCC_STZ		(NR_IRQS_LEGACY + 22)
-#define MX51_INT_SCC_SCM		(NR_IRQS_LEGACY + 23)
-#define MX51_INT_SRTC_NTZ		(NR_IRQS_LEGACY + 24)
-#define MX51_INT_SRTC_TZ		(NR_IRQS_LEGACY + 25)
-#define MX51_INT_RTIC			(NR_IRQS_LEGACY + 26)
-#define MX51_INT_CSU			(NR_IRQS_LEGACY + 27)
-#define MX51_INT_SLIM_B			(NR_IRQS_LEGACY + 28)
-#define MX51_INT_SSI1			(NR_IRQS_LEGACY + 29)
-#define MX51_INT_SSI2			(NR_IRQS_LEGACY + 30)
-#define MX51_INT_UART1			(NR_IRQS_LEGACY + 31)
-#define MX51_INT_UART2			(NR_IRQS_LEGACY + 32)
-#define MX51_INT_UART3			(NR_IRQS_LEGACY + 33)
-#define MX51_INT_RESV34			(NR_IRQS_LEGACY + 34)
-#define MX51_INT_RESV35			(NR_IRQS_LEGACY + 35)
-#define MX51_INT_ECSPI1			(NR_IRQS_LEGACY + 36)
-#define MX51_INT_ECSPI2			(NR_IRQS_LEGACY + 37)
-#define MX51_INT_CSPI			(NR_IRQS_LEGACY + 38)
-#define MX51_INT_GPT			(NR_IRQS_LEGACY + 39)
-#define MX51_INT_EPIT1			(NR_IRQS_LEGACY + 40)
-#define MX51_INT_EPIT2			(NR_IRQS_LEGACY + 41)
-#define MX51_INT_GPIO1_INT7		(NR_IRQS_LEGACY + 42)
-#define MX51_INT_GPIO1_INT6		(NR_IRQS_LEGACY + 43)
-#define MX51_INT_GPIO1_INT5		(NR_IRQS_LEGACY + 44)
-#define MX51_INT_GPIO1_INT4		(NR_IRQS_LEGACY + 45)
-#define MX51_INT_GPIO1_INT3		(NR_IRQS_LEGACY + 46)
-#define MX51_INT_GPIO1_INT2		(NR_IRQS_LEGACY + 47)
-#define MX51_INT_GPIO1_INT1		(NR_IRQS_LEGACY + 48)
-#define MX51_INT_GPIO1_INT0		(NR_IRQS_LEGACY + 49)
-#define MX51_INT_GPIO1_LOW		(NR_IRQS_LEGACY + 50)
-#define MX51_INT_GPIO1_HIGH		(NR_IRQS_LEGACY + 51)
-#define MX51_INT_GPIO2_LOW		(NR_IRQS_LEGACY + 52)
-#define MX51_INT_GPIO2_HIGH		(NR_IRQS_LEGACY + 53)
-#define MX51_INT_GPIO3_LOW		(NR_IRQS_LEGACY + 54)
-#define MX51_INT_GPIO3_HIGH		(NR_IRQS_LEGACY + 55)
-#define MX51_INT_GPIO4_LOW		(NR_IRQS_LEGACY + 56)
-#define MX51_INT_GPIO4_HIGH		(NR_IRQS_LEGACY + 57)
-#define MX51_INT_WDOG1			(NR_IRQS_LEGACY + 58)
-#define MX51_INT_WDOG2			(NR_IRQS_LEGACY + 59)
-#define MX51_INT_KPP			(NR_IRQS_LEGACY + 60)
-#define MX51_INT_PWM1			(NR_IRQS_LEGACY + 61)
-#define MX51_INT_I2C1			(NR_IRQS_LEGACY + 62)
-#define MX51_INT_I2C2			(NR_IRQS_LEGACY + 63)
-#define MX51_INT_HS_I2C			(NR_IRQS_LEGACY + 64)
-#define MX51_INT_RESV65			(NR_IRQS_LEGACY + 65)
-#define MX51_INT_RESV66			(NR_IRQS_LEGACY + 66)
-#define MX51_INT_SIM_IPB		(NR_IRQS_LEGACY + 67)
-#define MX51_INT_SIM_DAT		(NR_IRQS_LEGACY + 68)
-#define MX51_INT_IIM			(NR_IRQS_LEGACY + 69)
-#define MX51_INT_ATA			(NR_IRQS_LEGACY + 70)
-#define MX51_INT_CCM1			(NR_IRQS_LEGACY + 71)
-#define MX51_INT_CCM2			(NR_IRQS_LEGACY + 72)
-#define MX51_INT_GPC1			(NR_IRQS_LEGACY + 73)
-#define MX51_INT_GPC2			(NR_IRQS_LEGACY + 74)
-#define MX51_INT_SRC			(NR_IRQS_LEGACY + 75)
-#define MX51_INT_NM			(NR_IRQS_LEGACY + 76)
-#define MX51_INT_PMU			(NR_IRQS_LEGACY + 77)
-#define MX51_INT_CTI_IRQ		(NR_IRQS_LEGACY + 78)
-#define MX51_INT_CTI1_TG0		(NR_IRQS_LEGACY + 79)
-#define MX51_INT_CTI1_TG1		(NR_IRQS_LEGACY + 80)
-#define MX51_INT_MCG_ERR		(NR_IRQS_LEGACY + 81)
-#define MX51_INT_MCG_TMR		(NR_IRQS_LEGACY + 82)
-#define MX51_INT_MCG_FUNC		(NR_IRQS_LEGACY + 83)
-#define MX51_INT_GPU2_IRQ		(NR_IRQS_LEGACY + 84)
-#define MX51_INT_GPU2_BUSY		(NR_IRQS_LEGACY + 85)
-#define MX51_INT_RESV86			(NR_IRQS_LEGACY + 86)
-#define MX51_INT_FEC			(NR_IRQS_LEGACY + 87)
-#define MX51_INT_OWIRE			(NR_IRQS_LEGACY + 88)
-#define MX51_INT_CTI1_TG2		(NR_IRQS_LEGACY + 89)
-#define MX51_INT_SJC			(NR_IRQS_LEGACY + 90)
-#define MX51_INT_SPDIF			(NR_IRQS_LEGACY + 91)
-#define MX51_INT_TVE			(NR_IRQS_LEGACY + 92)
-#define MX51_INT_FIRI			(NR_IRQS_LEGACY + 93)
-#define MX51_INT_PWM2			(NR_IRQS_LEGACY + 94)
-#define MX51_INT_SLIM_EXP		(NR_IRQS_LEGACY + 95)
-#define MX51_INT_SSI3			(NR_IRQS_LEGACY + 96)
-#define MX51_INT_EMI_BOOT		(NR_IRQS_LEGACY + 97)
-#define MX51_INT_CTI1_TG3		(NR_IRQS_LEGACY + 98)
-#define MX51_INT_SMC_RX			(NR_IRQS_LEGACY + 99)
-#define MX51_INT_VPU_IDLE		(NR_IRQS_LEGACY + 100)
-#define MX51_INT_EMI_NFC		(NR_IRQS_LEGACY + 101)
-#define MX51_INT_GPU_IDLE		(NR_IRQS_LEGACY + 102)
-
-#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
-extern int mx51_revision(void);
-extern void mx51_display_revision(void);
-#endif
-
-#endif	/* ifndef __MACH_MX51_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx53.h b/arch/arm/plat-mxc/include/mach/mx53.h
deleted file mode 100644
index f829d1c..0000000
--- a/arch/arm/plat-mxc/include/mach/mx53.h
+++ /dev/null
@@ -1,342 +0,0 @@
-#ifndef __MACH_MX53_H__
-#define __MACH_MX53_H__
-
-/*
- * IROM
- */
-#define MX53_IROM_BASE_ADDR		0x0
-#define MX53_IROM_SIZE			SZ_64K
-
-/* TZIC */
-#define MX53_TZIC_BASE_ADDR		0x0FFFC000
-#define MX53_TZIC_SIZE			SZ_16K
-
-/*
- * AHCI SATA
- */
-#define MX53_SATA_BASE_ADDR		0x10000000
-
-/*
- * NFC
- */
-#define MX53_NFC_AXI_BASE_ADDR	0xF7FF0000	/* NAND flash AXI */
-#define MX53_NFC_AXI_SIZE		SZ_64K
-
-/*
- * IRAM
- */
-#define MX53_IRAM_BASE_ADDR	0xF8000000	/* internal ram */
-#define MX53_IRAM_PARTITIONS	16
-#define MX53_IRAM_SIZE		(MX53_IRAM_PARTITIONS * SZ_8K)	/* 128KB */
-
-/*
- * Graphics Memory of GPU
- */
-#define MX53_IPU_CTRL_BASE_ADDR	0x18000000
-#define MX53_GPU2D_BASE_ADDR		0x20000000
-#define MX53_GPU_BASE_ADDR		0x30000000
-#define MX53_GPU_GMEM_BASE_ADDR	0xF8020000
-
-#define MX53_DEBUG_BASE_ADDR		0x40000000
-#define MX53_DEBUG_SIZE		SZ_1M
-#define MX53_ETB_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00001000)
-#define MX53_ETM_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00002000)
-#define MX53_TPIU_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00003000)
-#define MX53_CTI0_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00004000)
-#define MX53_CTI1_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00005000)
-#define MX53_CTI2_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00006000)
-#define MX53_CTI3_BASE_ADDR		(MX53_DEBUG_BASE_ADDR + 0x00007000)
-#define MX53_CORTEX_DBG_BASE_ADDR	(MX53_DEBUG_BASE_ADDR + 0x00008000)
-
-/*
- * SPBA global module enabled #0
- */
-#define MX53_SPBA0_BASE_ADDR		0x50000000
-#define MX53_SPBA0_SIZE		SZ_1M
-
-#define MX53_ESDHC1_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00004000)
-#define MX53_ESDHC2_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00008000)
-#define MX53_UART3_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x0000C000)
-#define MX53_ECSPI1_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x00010000)
-#define MX53_SSI2_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x00014000)
-#define MX53_ESDHC3_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00020000)
-#define MX53_ESDHC4_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00024000)
-#define MX53_SPDIF_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x00028000)
-#define MX53_ASRC_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x0002C000)
-#define MX53_ATA_DMA_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00030000)
-#define MX53_SLIM_DMA_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00034000)
-#define MX53_HSI2C_DMA_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00038000)
-#define MX53_SPBA_CTRL_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x0003C000)
-
-/*
- * AIPS 1
- */
-#define MX53_AIPS1_BASE_ADDR	0x53F00000
-#define MX53_AIPS1_SIZE		SZ_1M
-
-#define MX53_OTG_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00080000)
-#define MX53_GPIO1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00084000)
-#define MX53_GPIO2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00088000)
-#define MX53_GPIO3_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x0008C000)
-#define MX53_GPIO4_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00090000)
-#define MX53_KPP_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00094000)
-#define MX53_WDOG1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00098000)
-#define MX53_WDOG2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x0009C000)
-#define MX53_GPT1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000A0000)
-#define MX53_SRTC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000A4000)
-#define MX53_IOMUXC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000A8000)
-#define MX53_EPIT1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000AC000)
-#define MX53_EPIT2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000B0000)
-#define MX53_PWM1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000B4000)
-#define MX53_PWM2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000B8000)
-#define MX53_UART1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000BC000)
-#define MX53_UART2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000C0000)
-#define MX53_SRC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000D0000)
-#define MX53_CCM_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000D4000)
-#define MX53_GPC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000D8000)
-#define MX53_GPIO5_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000DC000)
-#define MX53_GPIO6_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000E0000)
-#define MX53_GPIO7_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000E4000)
-#define MX53_ATA_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000E8000)
-#define MX53_I2C3_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000EC000)
-#define MX53_UART4_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000F0000)
-
-/*
- * AIPS 2
- */
-#define MX53_AIPS2_BASE_ADDR		0x63F00000
-#define MX53_AIPS2_SIZE			SZ_1M
-
-#define MX53_PLL1_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00080000)
-#define MX53_PLL2_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00084000)
-#define MX53_PLL3_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00088000)
-#define MX53_PLL4_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x0008C000)
-#define MX53_UART5_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00090000)
-#define MX53_AHBMAX_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00094000)
-#define MX53_IIM_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x00098000)
-#define MX53_CSU_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x0009C000)
-#define MX53_ARM_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000A0000)
-#define MX53_OWIRE_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000A4000)
-#define MX53_FIRI_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000A8000)
-#define MX53_ECSPI2_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000AC000)
-#define MX53_SDMA_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000B0000)
-#define MX53_SCC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000B4000)
-#define MX53_ROMCP_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000B8000)
-#define MX53_RTIC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000BC000)
-#define MX53_CSPI_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000C0000)
-#define MX53_I2C2_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000C4000)
-#define MX53_I2C1_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000C8000)
-#define MX53_SSI1_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000CC000)
-#define MX53_AUDMUX_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000D0000)
-#define MX53_RTC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000D4000)
-#define MX53_M4IF_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000D8000)
-#define MX53_ESDCTL_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000D9000)
-#define MX53_WEIM_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000DA000)
-#define MX53_NFC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000DB000)
-#define MX53_EMI_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000DBF00)
-#define MX53_MIPI_HSC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000DC000)
-#define MX53_MLB_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000E4000)
-#define MX53_SSI3_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000E8000)
-#define MX53_FEC_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000EC000)
-#define MX53_TVE_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000F0000)
-#define MX53_VPU_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000F4000)
-#define MX53_SAHARA_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000F8000)
-#define MX53_PTP_BASE_ADDR	(MX53_AIPS2_BASE_ADDR + 0x000FC000)
-
-/*
- * Memory regions and CS
- */
-#define MX53_CSD0_BASE_ADDR		0x70000000
-#define MX53_CSD1_BASE_ADDR		0xB0000000
-#define MX53_CS0_BASE_ADDR		0xF0000000
-#define MX53_CS1_32MB_BASE_ADDR	0xF2000000
-#define MX53_CS1_64MB_BASE_ADDR		0xF4000000
-#define MX53_CS2_64MB_BASE_ADDR		0xF4000000
-#define MX53_CS2_96MB_BASE_ADDR		0xF6000000
-#define MX53_CS3_BASE_ADDR		0xF6000000
-
-#define MX53_IO_P2V(x)			IMX_IO_P2V(x)
-#define MX53_IO_ADDRESS(x)		IOMEM(MX53_IO_P2V(x))
-
-/*
- * defines for SPBA modules
- */
-#define MX53_SPBA_SDHC1	0x04
-#define MX53_SPBA_SDHC2	0x08
-#define MX53_SPBA_UART3	0x0C
-#define MX53_SPBA_CSPI1	0x10
-#define MX53_SPBA_SSI2		0x14
-#define MX53_SPBA_SDHC3	0x20
-#define MX53_SPBA_SDHC4	0x24
-#define MX53_SPBA_SPDIF	0x28
-#define MX53_SPBA_ATA		0x30
-#define MX53_SPBA_SLIM		0x34
-#define MX53_SPBA_HSI2C	0x38
-#define MX53_SPBA_CTRL		0x3C
-
-/*
- * DMA request assignments
- */
-#define MX53_DMA_REQ_SSI3_TX0		47
-#define MX53_DMA_REQ_SSI3_RX0		46
-#define MX53_DMA_REQ_SSI3_TX1		45
-#define MX53_DMA_REQ_SSI3_RX1		44
-#define MX53_DMA_REQ_UART3_TX	43
-#define MX53_DMA_REQ_UART3_RX	42
-#define MX53_DMA_REQ_ESAI_TX		41
-#define MX53_DMA_REQ_ESAI_RX		40
-#define MX53_DMA_REQ_CSPI_TX		39
-#define MX53_DMA_REQ_CSPI_RX		38
-#define MX53_DMA_REQ_ASRC_DMA6	37
-#define MX53_DMA_REQ_ASRC_DMA5	36
-#define MX53_DMA_REQ_ASRC_DMA4	35
-#define MX53_DMA_REQ_ASRC_DMA3	34
-#define MX53_DMA_REQ_ASRC_DMA2	33
-#define MX53_DMA_REQ_ASRC_DMA1	32
-#define MX53_DMA_REQ_EMI_WR		31
-#define MX53_DMA_REQ_EMI_RD		30
-#define MX53_DMA_REQ_SSI1_TX0		29
-#define MX53_DMA_REQ_SSI1_RX0		28
-#define MX53_DMA_REQ_SSI1_TX1		27
-#define MX53_DMA_REQ_SSI1_RX1		26
-#define MX53_DMA_REQ_SSI2_TX0		25
-#define MX53_DMA_REQ_SSI2_RX0		24
-#define MX53_DMA_REQ_SSI2_TX1		23
-#define MX53_DMA_REQ_SSI2_RX1		22
-#define MX53_DMA_REQ_I2C2_SDHC2	21
-#define MX53_DMA_REQ_I2C1_SDHC1	20
-#define MX53_DMA_REQ_UART1_TX	19
-#define MX53_DMA_REQ_UART1_RX	18
-#define MX53_DMA_REQ_UART5_TX	17
-#define MX53_DMA_REQ_UART5_RX	16
-#define MX53_DMA_REQ_SPDIF_TX		15
-#define MX53_DMA_REQ_SPDIF_RX		14
-#define MX53_DMA_REQ_UART2_FIRI_TX	13
-#define MX53_DMA_REQ_UART2_FIRI_RX	12
-#define MX53_DMA_REQ_SDHC4		11
-#define MX53_DMA_REQ_I2C3_SDHC3	10
-#define MX53_DMA_REQ_CSPI2_TX		9
-#define MX53_DMA_REQ_CSPI2_RX		8
-#define MX53_DMA_REQ_CSPI1_TX		7
-#define MX53_DMA_REQ_CSPI1_RX		6
-#define MX53_DMA_REQ_IPU		5
-#define MX53_DMA_REQ_ATA_TX_END	4
-#define MX53_DMA_REQ_ATA_UART4_TX	3
-#define MX53_DMA_REQ_ATA_UART4_RX	2
-#define MX53_DMA_REQ_GPC		1
-#define MX53_DMA_REQ_VPU		0
-
-/*
- * Interrupt numbers
- */
-#include <asm/irq.h>
-#define MX53_INT_RESV0		(NR_IRQS_LEGACY + 0)
-#define MX53_INT_ESDHC1		(NR_IRQS_LEGACY + 1)
-#define MX53_INT_ESDHC2		(NR_IRQS_LEGACY + 2)
-#define MX53_INT_ESDHC3		(NR_IRQS_LEGACY + 3)
-#define MX53_INT_ESDHC4		(NR_IRQS_LEGACY + 4)
-#define MX53_INT_DAP		(NR_IRQS_LEGACY + 5)
-#define MX53_INT_SDMA		(NR_IRQS_LEGACY + 6)
-#define MX53_INT_IOMUX		(NR_IRQS_LEGACY + 7)
-#define MX53_INT_NFC		(NR_IRQS_LEGACY + 8)
-#define MX53_INT_VPU		(NR_IRQS_LEGACY + 9)
-#define MX53_INT_IPU_ERR	(NR_IRQS_LEGACY + 10)
-#define MX53_INT_IPU_SYN	(NR_IRQS_LEGACY + 11)
-#define MX53_INT_GPU		(NR_IRQS_LEGACY + 12)
-#define MX53_INT_UART4		(NR_IRQS_LEGACY + 13)
-#define MX53_INT_USB_H1		(NR_IRQS_LEGACY + 14)
-#define MX53_INT_EMI		(NR_IRQS_LEGACY + 15)
-#define MX53_INT_USB_H2		(NR_IRQS_LEGACY + 16)
-#define MX53_INT_USB_H3		(NR_IRQS_LEGACY + 17)
-#define MX53_INT_USB_OTG	(NR_IRQS_LEGACY + 18)
-#define MX53_INT_SAHARA_H0	(NR_IRQS_LEGACY + 19)
-#define MX53_INT_SAHARA_H1	(NR_IRQS_LEGACY + 20)
-#define MX53_INT_SCC_SMN	(NR_IRQS_LEGACY + 21)
-#define MX53_INT_SCC_STZ	(NR_IRQS_LEGACY + 22)
-#define MX53_INT_SCC_SCM	(NR_IRQS_LEGACY + 23)
-#define MX53_INT_SRTC_NTZ	(NR_IRQS_LEGACY + 24)
-#define MX53_INT_SRTC_TZ	(NR_IRQS_LEGACY + 25)
-#define MX53_INT_RTIC		(NR_IRQS_LEGACY + 26)
-#define MX53_INT_CSU		(NR_IRQS_LEGACY + 27)
-#define MX53_INT_SATA		(NR_IRQS_LEGACY + 28)
-#define MX53_INT_SSI1		(NR_IRQS_LEGACY + 29)
-#define MX53_INT_SSI2		(NR_IRQS_LEGACY + 30)
-#define MX53_INT_UART1		(NR_IRQS_LEGACY + 31)
-#define MX53_INT_UART2		(NR_IRQS_LEGACY + 32)
-#define MX53_INT_UART3		(NR_IRQS_LEGACY + 33)
-#define MX53_INT_RTC		(NR_IRQS_LEGACY + 34)
-#define MX53_INT_PTP		(NR_IRQS_LEGACY + 35)
-#define MX53_INT_ECSPI1		(NR_IRQS_LEGACY + 36)
-#define MX53_INT_ECSPI2		(NR_IRQS_LEGACY + 37)
-#define MX53_INT_CSPI		(NR_IRQS_LEGACY + 38)
-#define MX53_INT_GPT		(NR_IRQS_LEGACY + 39)
-#define MX53_INT_EPIT1		(NR_IRQS_LEGACY + 40)
-#define MX53_INT_EPIT2		(NR_IRQS_LEGACY + 41)
-#define MX53_INT_GPIO1_INT7	(NR_IRQS_LEGACY + 42)
-#define MX53_INT_GPIO1_INT6	(NR_IRQS_LEGACY + 43)
-#define MX53_INT_GPIO1_INT5	(NR_IRQS_LEGACY + 44)
-#define MX53_INT_GPIO1_INT4	(NR_IRQS_LEGACY + 45)
-#define MX53_INT_GPIO1_INT3	(NR_IRQS_LEGACY + 46)
-#define MX53_INT_GPIO1_INT2	(NR_IRQS_LEGACY + 47)
-#define MX53_INT_GPIO1_INT1	(NR_IRQS_LEGACY + 48)
-#define MX53_INT_GPIO1_INT0	(NR_IRQS_LEGACY + 49)
-#define MX53_INT_GPIO1_LOW	(NR_IRQS_LEGACY + 50)
-#define MX53_INT_GPIO1_HIGH	(NR_IRQS_LEGACY + 51)
-#define MX53_INT_GPIO2_LOW	(NR_IRQS_LEGACY + 52)
-#define MX53_INT_GPIO2_HIGH	(NR_IRQS_LEGACY + 53)
-#define MX53_INT_GPIO3_LOW	(NR_IRQS_LEGACY + 54)
-#define MX53_INT_GPIO3_HIGH	(NR_IRQS_LEGACY + 55)
-#define MX53_INT_GPIO4_LOW	(NR_IRQS_LEGACY + 56)
-#define MX53_INT_GPIO4_HIGH	(NR_IRQS_LEGACY + 57)
-#define MX53_INT_WDOG1		(NR_IRQS_LEGACY + 58)
-#define MX53_INT_WDOG2		(NR_IRQS_LEGACY + 59)
-#define MX53_INT_KPP		(NR_IRQS_LEGACY + 60)
-#define MX53_INT_PWM1		(NR_IRQS_LEGACY + 61)
-#define MX53_INT_I2C1		(NR_IRQS_LEGACY + 62)
-#define MX53_INT_I2C2		(NR_IRQS_LEGACY + 63)
-#define MX53_INT_I2C3		(NR_IRQS_LEGACY + 64)
-#define MX53_INT_MLB		(NR_IRQS_LEGACY + 65)
-#define MX53_INT_ASRC		(NR_IRQS_LEGACY + 66)
-#define MX53_INT_SPDIF		(NR_IRQS_LEGACY + 67)
-#define MX53_INT_SIM_DAT	(NR_IRQS_LEGACY + 68)
-#define MX53_INT_IIM		(NR_IRQS_LEGACY + 69)
-#define MX53_INT_ATA		(NR_IRQS_LEGACY + 70)
-#define MX53_INT_CCM1		(NR_IRQS_LEGACY + 71)
-#define MX53_INT_CCM2		(NR_IRQS_LEGACY + 72)
-#define MX53_INT_GPC1		(NR_IRQS_LEGACY + 73)
-#define MX53_INT_GPC2		(NR_IRQS_LEGACY + 74)
-#define MX53_INT_SRC		(NR_IRQS_LEGACY + 75)
-#define MX53_INT_NM		(NR_IRQS_LEGACY + 76)
-#define MX53_INT_PMU		(NR_IRQS_LEGACY + 77)
-#define MX53_INT_CTI_IRQ	(NR_IRQS_LEGACY + 78)
-#define MX53_INT_CTI1_TG0	(NR_IRQS_LEGACY + 79)
-#define MX53_INT_CTI1_TG1	(NR_IRQS_LEGACY + 80)
-#define MX53_INT_ESAI		(NR_IRQS_LEGACY + 81)
-#define MX53_INT_CAN1		(NR_IRQS_LEGACY + 82)
-#define MX53_INT_CAN2		(NR_IRQS_LEGACY + 83)
-#define MX53_INT_GPU2_IRQ	(NR_IRQS_LEGACY + 84)
-#define MX53_INT_GPU2_BUSY	(NR_IRQS_LEGACY + 85)
-#define MX53_INT_UART5		(NR_IRQS_LEGACY + 86)
-#define MX53_INT_FEC		(NR_IRQS_LEGACY + 87)
-#define MX53_INT_OWIRE		(NR_IRQS_LEGACY + 88)
-#define MX53_INT_CTI1_TG2	(NR_IRQS_LEGACY + 89)
-#define MX53_INT_SJC		(NR_IRQS_LEGACY + 90)
-#define MX53_INT_TVE		(NR_IRQS_LEGACY + 92)
-#define MX53_INT_FIRI		(NR_IRQS_LEGACY + 93)
-#define MX53_INT_PWM2		(NR_IRQS_LEGACY + 94)
-#define MX53_INT_SLIM_EXP	(NR_IRQS_LEGACY + 95)
-#define MX53_INT_SSI3		(NR_IRQS_LEGACY + 96)
-#define MX53_INT_EMI_BOOT	(NR_IRQS_LEGACY + 97)
-#define MX53_INT_CTI1_TG3	(NR_IRQS_LEGACY + 98)
-#define MX53_INT_SMC_RX		(NR_IRQS_LEGACY + 99)
-#define MX53_INT_VPU_IDLE	(NR_IRQS_LEGACY + 100)
-#define MX53_INT_EMI_NFC	(NR_IRQS_LEGACY + 101)
-#define MX53_INT_GPU_IDLE	(NR_IRQS_LEGACY + 102)
-#define MX53_INT_GPIO5_LOW	(NR_IRQS_LEGACY + 103)
-#define MX53_INT_GPIO5_HIGH	(NR_IRQS_LEGACY + 104)
-#define MX53_INT_GPIO6_LOW	(NR_IRQS_LEGACY + 105)
-#define MX53_INT_GPIO6_HIGH	(NR_IRQS_LEGACY + 106)
-#define MX53_INT_GPIO7_LOW	(NR_IRQS_LEGACY + 107)
-#define MX53_INT_GPIO7_HIGH	(NR_IRQS_LEGACY + 108)
-
-#endif /* ifndef __MACH_MX53_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx6q.h b/arch/arm/plat-mxc/include/mach/mx6q.h
deleted file mode 100644
index f7e7dba..0000000
--- a/arch/arm/plat-mxc/include/mach/mx6q.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2011 Linaro Ltd.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __MACH_MX6Q_H__
-#define __MACH_MX6Q_H__
-
-#define MX6Q_IO_P2V(x)			IMX_IO_P2V(x)
-#define MX6Q_IO_ADDRESS(x)		IOMEM(MX6Q_IO_P2V(x))
-
-/*
- * The following are the blocks that need to be statically mapped.
- * For other blocks, the base address really should be retrieved from
- * device tree.
- */
-#define MX6Q_SCU_BASE_ADDR		0x00a00000
-#define MX6Q_SCU_SIZE			0x1000
-#define MX6Q_CCM_BASE_ADDR		0x020c4000
-#define MX6Q_CCM_SIZE			0x4000
-#define MX6Q_ANATOP_BASE_ADDR		0x020c8000
-#define MX6Q_ANATOP_SIZE		0x1000
-#define MX6Q_UART2_BASE_ADDR		0x021e8000
-#define MX6Q_UART2_SIZE			0x4000
-#define MX6Q_UART4_BASE_ADDR		0x021f0000
-#define MX6Q_UART4_SIZE			0x4000
-
-#endif	/* __MACH_MX6Q_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
deleted file mode 100644
index d782983..0000000
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright 2004-2007, 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef __ASM_ARCH_MXC_H__
-#define __ASM_ARCH_MXC_H__
-
-#include <linux/types.h>
-
-#ifndef __ASM_ARCH_MXC_HARDWARE_H__
-#error "Do not include directly."
-#endif
-
-#define MXC_CPU_MX1		1
-#define MXC_CPU_MX21		21
-#define MXC_CPU_MX25		25
-#define MXC_CPU_MX27		27
-#define MXC_CPU_MX31		31
-#define MXC_CPU_MX35		35
-#define MXC_CPU_MX50		50
-#define MXC_CPU_MX51		51
-#define MXC_CPU_MX53		53
-
-#define IMX_CHIP_REVISION_1_0		0x10
-#define IMX_CHIP_REVISION_1_1		0x11
-#define IMX_CHIP_REVISION_1_2		0x12
-#define IMX_CHIP_REVISION_1_3		0x13
-#define IMX_CHIP_REVISION_2_0		0x20
-#define IMX_CHIP_REVISION_2_1		0x21
-#define IMX_CHIP_REVISION_2_2		0x22
-#define IMX_CHIP_REVISION_2_3		0x23
-#define IMX_CHIP_REVISION_3_0		0x30
-#define IMX_CHIP_REVISION_3_1		0x31
-#define IMX_CHIP_REVISION_3_2		0x32
-#define IMX_CHIP_REVISION_3_3		0x33
-#define IMX_CHIP_REVISION_UNKNOWN	0xff
-
-#ifndef __ASSEMBLY__
-extern unsigned int __mxc_cpu_type;
-#endif
-
-#ifdef CONFIG_SOC_IMX1
-# ifdef mxc_cpu_type
-#  undef mxc_cpu_type
-#  define mxc_cpu_type __mxc_cpu_type
-# else
-#  define mxc_cpu_type MXC_CPU_MX1
-# endif
-# define cpu_is_mx1()		(mxc_cpu_type == MXC_CPU_MX1)
-#else
-# define cpu_is_mx1()		(0)
-#endif
-
-#ifdef CONFIG_SOC_IMX21
-# ifdef mxc_cpu_type
-#  undef mxc_cpu_type
-#  define mxc_cpu_type __mxc_cpu_type
-# else
-#  define mxc_cpu_type MXC_CPU_MX21
-# endif
-# define cpu_is_mx21()		(mxc_cpu_type == MXC_CPU_MX21)
-#else
-# define cpu_is_mx21()		(0)
-#endif
-
-#ifdef CONFIG_SOC_IMX25
-# ifdef mxc_cpu_type
-#  undef mxc_cpu_type
-#  define mxc_cpu_type __mxc_cpu_type
-# else
-#  define mxc_cpu_type MXC_CPU_MX25
-# endif
-# define cpu_is_mx25()		(mxc_cpu_type == MXC_CPU_MX25)
-#else
-# define cpu_is_mx25()		(0)
-#endif
-
-#ifdef CONFIG_SOC_IMX27
-# ifdef mxc_cpu_type
-#  undef mxc_cpu_type
-#  define mxc_cpu_type __mxc_cpu_type
-# else
-#  define mxc_cpu_type MXC_CPU_MX27
-# endif
-# define cpu_is_mx27()		(mxc_cpu_type == MXC_CPU_MX27)
-#else
-# define cpu_is_mx27()		(0)
-#endif
-
-#ifdef CONFIG_SOC_IMX31
-# ifdef mxc_cpu_type
-#  undef mxc_cpu_type
-#  define mxc_cpu_type __mxc_cpu_type
-# else
-#  define mxc_cpu_type MXC_CPU_MX31
-# endif
-# define cpu_is_mx31()		(mxc_cpu_type == MXC_CPU_MX31)
-#else
-# define cpu_is_mx31()		(0)
-#endif
-
-#ifdef CONFIG_SOC_IMX35
-# ifdef mxc_cpu_type
-#  undef mxc_cpu_type
-#  define mxc_cpu_type __mxc_cpu_type
-# else
-#  define mxc_cpu_type MXC_CPU_MX35
-# endif
-# define cpu_is_mx35()		(mxc_cpu_type == MXC_CPU_MX35)
-#else
-# define cpu_is_mx35()		(0)
-#endif
-
-#ifdef CONFIG_SOC_IMX50
-# ifdef mxc_cpu_type
-#  undef mxc_cpu_type
-#  define mxc_cpu_type __mxc_cpu_type
-# else
-#  define mxc_cpu_type MXC_CPU_MX50
-# endif
-# define cpu_is_mx50()		(mxc_cpu_type == MXC_CPU_MX50)
-#else
-# define cpu_is_mx50()		(0)
-#endif
-
-#ifdef CONFIG_SOC_IMX51
-# ifdef mxc_cpu_type
-#  undef mxc_cpu_type
-#  define mxc_cpu_type __mxc_cpu_type
-# else
-#  define mxc_cpu_type MXC_CPU_MX51
-# endif
-# define cpu_is_mx51()		(mxc_cpu_type == MXC_CPU_MX51)
-#else
-# define cpu_is_mx51()		(0)
-#endif
-
-#ifdef CONFIG_SOC_IMX53
-# ifdef mxc_cpu_type
-#  undef mxc_cpu_type
-#  define mxc_cpu_type __mxc_cpu_type
-# else
-#  define mxc_cpu_type MXC_CPU_MX53
-# endif
-# define cpu_is_mx53()		(mxc_cpu_type == MXC_CPU_MX53)
-#else
-# define cpu_is_mx53()		(0)
-#endif
-
-#ifndef __ASSEMBLY__
-
-struct cpu_op {
-	u32 cpu_rate;
-};
-
-int tzic_enable_wake(void);
-
-extern struct cpu_op *(*get_cpu_op)(int *op);
-#endif
-
-#define cpu_is_mx3()	(cpu_is_mx31() || cpu_is_mx35())
-#define cpu_is_mx2()	(cpu_is_mx21() || cpu_is_mx27())
-
-#endif /*  __ASM_ARCH_MXC_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/timex.h b/arch/arm/plat-mxc/include/mach/timex.h
deleted file mode 100644
index 10343d1..0000000
--- a/arch/arm/plat-mxc/include/mach/timex.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- *  Copyright (C) 1999 ARM Limited
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ASM_ARCH_MXC_TIMEX_H__
-#define __ASM_ARCH_MXC_TIMEX_H__
-
-/* Bogus value */
-#define CLOCK_TICK_RATE	12345678
-
-#endif				/* __ASM_ARCH_MXC_TIMEX_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/ulpi.h b/arch/arm/plat-mxc/include/mach/ulpi.h
deleted file mode 100644
index 42bdaca..0000000
--- a/arch/arm/plat-mxc/include/mach/ulpi.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __MACH_ULPI_H
-#define __MACH_ULPI_H
-
-#ifdef CONFIG_USB_ULPI
-struct usb_phy *imx_otg_ulpi_create(unsigned int flags);
-#else
-static inline struct usb_phy *imx_otg_ulpi_create(unsigned int flags)
-{
-	return NULL;
-}
-#endif
-
-extern struct usb_phy_io_ops mxc_ulpi_access_ops;
-
-#endif /* __MACH_ULPI_H */
-
diff --git a/arch/arm/plat-mxc/include/mach/uncompress.h b/arch/arm/plat-mxc/include/mach/uncompress.h
deleted file mode 100644
index 477971b..0000000
--- a/arch/arm/plat-mxc/include/mach/uncompress.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- *  arch/arm/plat-mxc/include/mach/uncompress.h
- *
- *  Copyright (C) 1999 ARM Limited
- *  Copyright (C) Shane Nay (shane@minirl.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef __ASM_ARCH_MXC_UNCOMPRESS_H__
-#define __ASM_ARCH_MXC_UNCOMPRESS_H__
-
-#define __MXC_BOOT_UNCOMPRESS
-
-#include <asm/mach-types.h>
-
-unsigned long uart_base;
-
-#define UART(x) (*(volatile unsigned long *)(uart_base + (x)))
-
-#define USR2 0x98
-#define USR2_TXFE (1<<14)
-#define TXR  0x40
-#define UCR1 0x80
-#define UCR1_UARTEN 1
-
-/*
- * The following code assumes the serial port has already been
- * initialized by the bootloader.  We search for the first enabled
- * port in the most probable order.  If you didn't setup a port in
- * your bootloader then nothing will appear (which might be desired).
- *
- * This does not append a newline
- */
-
-static void putc(int ch)
-{
-	if (!uart_base)
-		return;
-	if (!(UART(UCR1) & UCR1_UARTEN))
-		return;
-
-	while (!(UART(USR2) & USR2_TXFE))
-		barrier();
-
-	UART(TXR) = ch;
-}
-
-static inline void flush(void)
-{
-}
-
-#define MX1_UART1_BASE_ADDR	0x00206000
-#define MX25_UART1_BASE_ADDR	0x43f90000
-#define MX2X_UART1_BASE_ADDR	0x1000a000
-#define MX3X_UART1_BASE_ADDR	0x43F90000
-#define MX3X_UART2_BASE_ADDR	0x43F94000
-#define MX3X_UART5_BASE_ADDR	0x43FB4000
-#define MX51_UART1_BASE_ADDR	0x73fbc000
-#define MX50_UART1_BASE_ADDR	0x53fbc000
-#define MX53_UART1_BASE_ADDR	0x53fbc000
-
-static __inline__ void __arch_decomp_setup(unsigned long arch_id)
-{
-	switch (arch_id) {
-	case MACH_TYPE_MX1ADS:
-	case MACH_TYPE_SCB9328:
-		uart_base = MX1_UART1_BASE_ADDR;
-		break;
-	case MACH_TYPE_MX25_3DS:
-		uart_base = MX25_UART1_BASE_ADDR;
-		break;
-	case MACH_TYPE_IMX27LITE:
-	case MACH_TYPE_MX27_3DS:
-	case MACH_TYPE_MX27ADS:
-	case MACH_TYPE_PCM038:
-	case MACH_TYPE_MX21ADS:
-	case MACH_TYPE_PCA100:
-	case MACH_TYPE_MXT_TD60:
-	case MACH_TYPE_IMX27IPCAM:
-		uart_base = MX2X_UART1_BASE_ADDR;
-		break;
-	case MACH_TYPE_MX31LITE:
-	case MACH_TYPE_ARMADILLO5X0:
-	case MACH_TYPE_MX31MOBOARD:
-	case MACH_TYPE_QONG:
-	case MACH_TYPE_MX31_3DS:
-	case MACH_TYPE_PCM037:
-	case MACH_TYPE_MX31ADS:
-	case MACH_TYPE_MX35_3DS:
-	case MACH_TYPE_PCM043:
-	case MACH_TYPE_LILLY1131:
-	case MACH_TYPE_VPR200:
-	case MACH_TYPE_EUKREA_CPUIMX35SD:
-		uart_base = MX3X_UART1_BASE_ADDR;
-		break;
-	case MACH_TYPE_MAGX_ZN5:
-		uart_base = MX3X_UART2_BASE_ADDR;
-		break;
-	case MACH_TYPE_BUG:
-		uart_base = MX3X_UART5_BASE_ADDR;
-		break;
-	case MACH_TYPE_MX51_BABBAGE:
-	case MACH_TYPE_EUKREA_CPUIMX51SD:
-	case MACH_TYPE_MX51_3DS:
-		uart_base = MX51_UART1_BASE_ADDR;
-		break;
-	case MACH_TYPE_MX50_RDP:
-		uart_base = MX50_UART1_BASE_ADDR;
-		break;
-	case MACH_TYPE_MX53_EVK:
-	case MACH_TYPE_MX53_LOCO:
-	case MACH_TYPE_MX53_SMD:
-	case MACH_TYPE_MX53_ARD:
-		uart_base = MX53_UART1_BASE_ADDR;
-		break;
-	default:
-		break;
-	}
-}
-
-#define arch_decomp_setup()	__arch_decomp_setup(arch_id)
-#define arch_decomp_wdog()
-
-#endif				/* __ASM_ARCH_MXC_UNCOMPRESS_H__ */
diff --git a/arch/arm/plat-mxc/iomux-v1.c b/arch/arm/plat-mxc/iomux-v1.c
deleted file mode 100644
index 1f73963..0000000
--- a/arch/arm/plat-mxc/iomux-v1.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * arch/arm/plat-mxc/iomux-v1.c
- *
- * Copyright (C) 2004 Sascha Hauer, Synertronixx GmbH
- * Copyright (C) 2009 Uwe Kleine-Koenig, Pengutronix
- *
- * Common code for i.MX1, i.MX21 and i.MX27
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/gpio.h>
-
-#include <mach/hardware.h>
-#include <asm/mach/map.h>
-#include <mach/iomux-v1.h>
-
-static void __iomem *imx_iomuxv1_baseaddr;
-static unsigned imx_iomuxv1_numports;
-
-static inline unsigned long imx_iomuxv1_readl(unsigned offset)
-{
-	return __raw_readl(imx_iomuxv1_baseaddr + offset);
-}
-
-static inline void imx_iomuxv1_writel(unsigned long val, unsigned offset)
-{
-	__raw_writel(val, imx_iomuxv1_baseaddr + offset);
-}
-
-static inline void imx_iomuxv1_rmwl(unsigned offset,
-		unsigned long mask, unsigned long value)
-{
-	unsigned long reg = imx_iomuxv1_readl(offset);
-
-	reg &= ~mask;
-	reg |= value;
-
-	imx_iomuxv1_writel(reg, offset);
-}
-
-static inline void imx_iomuxv1_set_puen(
-		unsigned int port, unsigned int pin, int on)
-{
-	unsigned long mask = 1 << pin;
-
-	imx_iomuxv1_rmwl(MXC_PUEN(port), mask, on ? mask : 0);
-}
-
-static inline void imx_iomuxv1_set_ddir(
-		unsigned int port, unsigned int pin, int out)
-{
-	unsigned long mask = 1 << pin;
-
-	imx_iomuxv1_rmwl(MXC_DDIR(port), mask, out ? mask : 0);
-}
-
-static inline void imx_iomuxv1_set_gpr(
-		unsigned int port, unsigned int pin, int af)
-{
-	unsigned long mask = 1 << pin;
-
-	imx_iomuxv1_rmwl(MXC_GPR(port), mask, af ? mask : 0);
-}
-
-static inline void imx_iomuxv1_set_gius(
-		unsigned int port, unsigned int pin, int inuse)
-{
-	unsigned long mask = 1 << pin;
-
-	imx_iomuxv1_rmwl(MXC_GIUS(port), mask, inuse ? mask : 0);
-}
-
-static inline void imx_iomuxv1_set_ocr(
-		unsigned int port, unsigned int pin, unsigned int ocr)
-{
-	unsigned long shift = (pin & 0xf) << 1;
-	unsigned long mask = 3 << shift;
-	unsigned long value = ocr << shift;
-	unsigned long offset = pin < 16 ? MXC_OCR1(port) : MXC_OCR2(port);
-
-	imx_iomuxv1_rmwl(offset, mask, value);
-}
-
-static inline void imx_iomuxv1_set_iconfa(
-		unsigned int port, unsigned int pin, unsigned int aout)
-{
-	unsigned long shift = (pin & 0xf) << 1;
-	unsigned long mask = 3 << shift;
-	unsigned long value = aout << shift;
-	unsigned long offset = pin < 16 ? MXC_ICONFA1(port) : MXC_ICONFA2(port);
-
-	imx_iomuxv1_rmwl(offset, mask, value);
-}
-
-static inline void imx_iomuxv1_set_iconfb(
-		unsigned int port, unsigned int pin, unsigned int bout)
-{
-	unsigned long shift = (pin & 0xf) << 1;
-	unsigned long mask = 3 << shift;
-	unsigned long value = bout << shift;
-	unsigned long offset = pin < 16 ? MXC_ICONFB1(port) : MXC_ICONFB2(port);
-
-	imx_iomuxv1_rmwl(offset, mask, value);
-}
-
-int mxc_gpio_mode(int gpio_mode)
-{
-	unsigned int pin = gpio_mode & GPIO_PIN_MASK;
-	unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
-	unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT;
-	unsigned int aout = (gpio_mode >> GPIO_AOUT_SHIFT) & 3;
-	unsigned int bout = (gpio_mode >> GPIO_BOUT_SHIFT) & 3;
-
-	if (port >= imx_iomuxv1_numports)
-		return -EINVAL;
-
-	/* Pullup enable */
-	imx_iomuxv1_set_puen(port, pin, gpio_mode & GPIO_PUEN);
-
-	/* Data direction */
-	imx_iomuxv1_set_ddir(port, pin, gpio_mode & GPIO_OUT);
-
-	/* Primary / alternate function */
-	imx_iomuxv1_set_gpr(port, pin, gpio_mode & GPIO_AF);
-
-	/* use as gpio? */
-	imx_iomuxv1_set_gius(port, pin, !(gpio_mode & (GPIO_PF | GPIO_AF)));
-
-	imx_iomuxv1_set_ocr(port, pin, ocr);
-
-	imx_iomuxv1_set_iconfa(port, pin, aout);
-
-	imx_iomuxv1_set_iconfb(port, pin, bout);
-
-	return 0;
-}
-EXPORT_SYMBOL(mxc_gpio_mode);
-
-static int imx_iomuxv1_setup_multiple(const int *list, unsigned count)
-{
-	size_t i;
-	int ret = 0;
-
-	for (i = 0; i < count; ++i) {
-		ret = mxc_gpio_mode(list[i]);
-
-		if (ret)
-			return ret;
-	}
-
-	return ret;
-}
-
-int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
-		const char *label)
-{
-	int ret;
-
-	ret = imx_iomuxv1_setup_multiple(pin_list, count);
-	return ret;
-}
-EXPORT_SYMBOL(mxc_gpio_setup_multiple_pins);
-
-int __init imx_iomuxv1_init(void __iomem *base, int numports)
-{
-	imx_iomuxv1_baseaddr = base;
-	imx_iomuxv1_numports = numports;
-
-	return 0;
-}
diff --git a/arch/arm/plat-mxc/iomux-v3.c b/arch/arm/plat-mxc/iomux-v3.c
deleted file mode 100644
index 99a9cdb..0000000
--- a/arch/arm/plat-mxc/iomux-v3.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
- * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
- *                       <armlinux@phytec.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/gpio.h>
-
-#include <mach/hardware.h>
-#include <asm/mach/map.h>
-#include <mach/iomux-v3.h>
-
-static void __iomem *base;
-
-/*
- * configures a single pad in the iomuxer
- */
-int mxc_iomux_v3_setup_pad(iomux_v3_cfg_t pad)
-{
-	u32 mux_ctrl_ofs = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT;
-	u32 mux_mode = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT;
-	u32 sel_input_ofs = (pad & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT;
-	u32 sel_input = (pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT;
-	u32 pad_ctrl_ofs = (pad & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT;
-	u32 pad_ctrl = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT;
-
-	if (mux_ctrl_ofs)
-		__raw_writel(mux_mode, base + mux_ctrl_ofs);
-
-	if (sel_input_ofs)
-		__raw_writel(sel_input, base + sel_input_ofs);
-
-	if (!(pad_ctrl & NO_PAD_CTRL) && pad_ctrl_ofs)
-		__raw_writel(pad_ctrl, base + pad_ctrl_ofs);
-
-	return 0;
-}
-EXPORT_SYMBOL(mxc_iomux_v3_setup_pad);
-
-int mxc_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count)
-{
-	iomux_v3_cfg_t *p = pad_list;
-	int i;
-	int ret;
-
-	for (i = 0; i < count; i++) {
-		ret = mxc_iomux_v3_setup_pad(*p);
-		if (ret)
-			return ret;
-		p++;
-	}
-	return 0;
-}
-EXPORT_SYMBOL(mxc_iomux_v3_setup_multiple_pads);
-
-void mxc_iomux_v3_init(void __iomem *iomux_v3_base)
-{
-	base = iomux_v3_base;
-}
diff --git a/arch/arm/plat-mxc/iram_alloc.c b/arch/arm/plat-mxc/iram_alloc.c
deleted file mode 100644
index 074c386..0000000
--- a/arch/arm/plat-mxc/iram_alloc.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/genalloc.h>
-#include <mach/iram.h>
-
-static unsigned long iram_phys_base;
-static void __iomem *iram_virt_base;
-static struct gen_pool *iram_pool;
-
-static inline void __iomem *iram_phys_to_virt(unsigned long p)
-{
-	return iram_virt_base + (p - iram_phys_base);
-}
-
-void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr)
-{
-	if (!iram_pool)
-		return NULL;
-
-	*dma_addr = gen_pool_alloc(iram_pool, size);
-	pr_debug("iram alloc - %dB@0x%lX\n", size, *dma_addr);
-	if (!*dma_addr)
-		return NULL;
-	return iram_phys_to_virt(*dma_addr);
-}
-EXPORT_SYMBOL(iram_alloc);
-
-void iram_free(unsigned long addr, unsigned int size)
-{
-	if (!iram_pool)
-		return;
-
-	gen_pool_free(iram_pool, addr, size);
-}
-EXPORT_SYMBOL(iram_free);
-
-int __init iram_init(unsigned long base, unsigned long size)
-{
-	iram_phys_base = base;
-
-	iram_pool = gen_pool_create(PAGE_SHIFT, -1);
-	if (!iram_pool)
-		return -ENOMEM;
-
-	gen_pool_add(iram_pool, base, size, -1);
-	iram_virt_base = ioremap(iram_phys_base, size);
-	if (!iram_virt_base)
-		return -EIO;
-
-	pr_debug("i.MX IRAM pool: %ld KB@0x%p\n", size / 1024, iram_virt_base);
-	return 0;
-}
diff --git a/arch/arm/plat-mxc/irq-common.c b/arch/arm/plat-mxc/irq-common.c
deleted file mode 100644
index b6e1145..0000000
--- a/arch/arm/plat-mxc/irq-common.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) BitBox Ltd 2010
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/irq.h>
-
-#include "irq-common.h"
-
-int imx_irq_set_priority(unsigned char irq, unsigned char prio)
-{
-	struct irq_chip_generic *gc;
-	struct mxc_extra_irq *exirq;
-	int ret;
-
-	ret = -ENOSYS;
-
-	gc = irq_get_chip_data(irq);
-	if (gc && gc->private) {
-		exirq = gc->private;
-		if (exirq->set_priority)
-			ret = exirq->set_priority(irq, prio);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(imx_irq_set_priority);
-
-int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
-{
-	struct irq_chip_generic *gc;
-	struct mxc_extra_irq *exirq;
-	int ret;
-
-	ret = -ENOSYS;
-
-	gc = irq_get_chip_data(irq);
-	if (gc && gc->private) {
-		exirq = gc->private;
-		if (exirq->set_irq_fiq)
-			ret = exirq->set_irq_fiq(irq, type);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(mxc_set_irq_fiq);
diff --git a/arch/arm/plat-mxc/irq-common.h b/arch/arm/plat-mxc/irq-common.h
deleted file mode 100644
index 6ccb3a1..0000000
--- a/arch/arm/plat-mxc/irq-common.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) BitBox Ltd 2010
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- */
-
-#ifndef __PLAT_MXC_IRQ_COMMON_H__
-#define __PLAT_MXC_IRQ_COMMON_H__
-
-struct mxc_extra_irq
-{
-	int (*set_priority)(unsigned char irq, unsigned char prio);
-	int (*set_irq_fiq)(unsigned int irq, unsigned int type);
-};
-
-#endif
diff --git a/arch/arm/plat-mxc/ssi-fiq-ksym.c b/arch/arm/plat-mxc/ssi-fiq-ksym.c
deleted file mode 100644
index 792090f..0000000
--- a/arch/arm/plat-mxc/ssi-fiq-ksym.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Exported ksyms for the SSI FIQ handler
- *
- * Copyright (C) 2009, Sascha Hauer <s.hauer@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/module.h>
-
-#include <linux/platform_data/asoc-imx-ssi.h>
-
-EXPORT_SYMBOL(imx_ssi_fiq_tx_buffer);
-EXPORT_SYMBOL(imx_ssi_fiq_rx_buffer);
-EXPORT_SYMBOL(imx_ssi_fiq_start);
-EXPORT_SYMBOL(imx_ssi_fiq_end);
-EXPORT_SYMBOL(imx_ssi_fiq_base);
-
diff --git a/arch/arm/plat-mxc/ssi-fiq.S b/arch/arm/plat-mxc/ssi-fiq.S
deleted file mode 100644
index a8b93c5..0000000
--- a/arch/arm/plat-mxc/ssi-fiq.S
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- *  Copyright (C) 2009 Sascha Hauer <s.hauer@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/linkage.h>
-#include <asm/assembler.h>
-
-/*
- * r8  = bit 0-15: tx offset, bit 16-31: tx buffer size
- * r9  = bit 0-15: rx offset, bit 16-31: rx buffer size
- */
-
-#define SSI_STX0	0x00
-#define SSI_SRX0	0x08
-#define SSI_SISR	0x14
-#define SSI_SIER	0x18
-#define SSI_SACNT	0x38
-
-#define SSI_SACNT_AC97EN	(1 << 0)
-
-#define SSI_SIER_TFE0_EN	(1 << 0)
-#define SSI_SISR_TFE0		(1 << 0)
-#define SSI_SISR_RFF0		(1 << 2)
-#define SSI_SIER_RFF0_EN	(1 << 2)
-
-		.text
-		.global	imx_ssi_fiq_start
-		.global	imx_ssi_fiq_end
-		.global imx_ssi_fiq_base
-		.global imx_ssi_fiq_rx_buffer
-		.global imx_ssi_fiq_tx_buffer
-
-/*
- * imx_ssi_fiq_start is _intentionally_ not marked as a function symbol
- * using ENDPROC().  imx_ssi_fiq_start and imx_ssi_fiq_end are used to
- * mark the function body so that it can be copied to the FIQ vector in
- * the vectors page.  imx_ssi_fiq_start should only be called as the result
- * of an FIQ: calling it directly will not work.
- */
-imx_ssi_fiq_start:
-		ldr r12, .L_imx_ssi_fiq_base
-
-		/* TX */
-		ldr r13, .L_imx_ssi_fiq_tx_buffer
-
-		/* shall we send? */
-		ldr r11, [r12, #SSI_SIER]
-		tst r11, #SSI_SIER_TFE0_EN
-		beq 1f
-
-		/* TX FIFO empty? */
-		ldr r11, [r12, #SSI_SISR]
-		tst r11, #SSI_SISR_TFE0
-		beq 1f
-
-		mov r10, #0x10000
-		sub r10, #1
-		and r10, r10, r8	/* r10: current buffer offset */
-
-		add r13, r13, r10
-
-		ldrh r11, [r13]
-		strh r11, [r12, #SSI_STX0]
-
-		ldrh r11, [r13, #2]
-		strh r11, [r12, #SSI_STX0]
-
-		ldrh r11, [r13, #4]
-		strh r11, [r12, #SSI_STX0]
-
-		ldrh r11, [r13, #6]
-		strh r11, [r12, #SSI_STX0]
-
-		add r10, #8
-		lsr r11, r8, #16	/* r11: buffer size */
-		cmp r10, r11
-		lslgt r8, r11, #16
-		addle r8, #8
-1:
-		/* RX */
-
-		/* shall we receive? */
-		ldr r11, [r12, #SSI_SIER]
-		tst r11, #SSI_SIER_RFF0_EN
-		beq 1f
-
-		/* RX FIFO full? */
-		ldr r11, [r12, #SSI_SISR]
-		tst r11, #SSI_SISR_RFF0
-		beq 1f
-
-		ldr r13, .L_imx_ssi_fiq_rx_buffer
-
-		mov r10, #0x10000
-		sub r10, #1
-		and r10, r10, r9	/* r10: current buffer offset */
-
-		add r13, r13, r10
-
-		ldr r11, [r12, #SSI_SACNT]
-		tst r11, #SSI_SACNT_AC97EN
-
-		ldr r11, [r12, #SSI_SRX0]
-		strh r11, [r13]
-
-		ldr r11, [r12, #SSI_SRX0]
-		strh r11, [r13, #2]
-
-		/* dummy read to skip slot 12 */
-		ldrne r11, [r12, #SSI_SRX0]
-
-		ldr r11, [r12, #SSI_SRX0]
-		strh r11, [r13, #4]
-
-		ldr r11, [r12, #SSI_SRX0]
-		strh r11, [r13, #6]
-
-		/* dummy read to skip slot 12 */
-		ldrne r11, [r12, #SSI_SRX0]
-
-		add r10, #8
-		lsr r11, r9, #16	/* r11: buffer size */
-		cmp r10, r11
-		lslgt r9, r11, #16
-		addle r9, #8
-
-1:
-		@ return from FIQ
-		subs	pc, lr, #4
-
-		.align
-.L_imx_ssi_fiq_base:
-imx_ssi_fiq_base:
-		.word 0x0
-.L_imx_ssi_fiq_rx_buffer:
-imx_ssi_fiq_rx_buffer:
-		.word 0x0
-.L_imx_ssi_fiq_tx_buffer:
-imx_ssi_fiq_tx_buffer:
-		.word 0x0
-.L_imx_ssi_fiq_end:
-imx_ssi_fiq_end:
-
diff --git a/arch/arm/plat-mxc/system.c b/arch/arm/plat-mxc/system.c
deleted file mode 100644
index 3da78cf..0000000
--- a/arch/arm/plat-mxc/system.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 1999 ARM Limited
- * Copyright (C) 2000 Deep Blue Solutions Ltd
- * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <asm/system_misc.h>
-#include <asm/proc-fns.h>
-#include <asm/mach-types.h>
-
-static void __iomem *wdog_base;
-
-/*
- * Reset the system. It is called by machine_restart().
- */
-void mxc_restart(char mode, const char *cmd)
-{
-	unsigned int wcr_enable;
-
-	if (cpu_is_mx1()) {
-		wcr_enable = (1 << 0);
-	} else {
-		struct clk *clk;
-
-		clk = clk_get_sys("imx2-wdt.0", NULL);
-		if (!IS_ERR(clk))
-			clk_prepare_enable(clk);
-		wcr_enable = (1 << 2);
-	}
-
-	/* Assert SRS signal */
-	__raw_writew(wcr_enable, wdog_base);
-
-	/* wait for reset to assert... */
-	mdelay(500);
-
-	printk(KERN_ERR "Watchdog reset failed to assert reset\n");
-
-	/* delay to allow the serial port to show the message */
-	mdelay(50);
-
-	/* we'll take a jump through zero as a poor second */
-	soft_restart(0);
-}
-
-void mxc_arch_reset_init(void __iomem *base)
-{
-	wdog_base = base;
-}
diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c
deleted file mode 100644
index a17abcf..0000000
--- a/arch/arm/plat-mxc/time.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- *  linux/arch/arm/plat-mxc/time.c
- *
- *  Copyright (C) 2000-2001 Deep Blue Solutions
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *  Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com)
- *  Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/clockchips.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <mach/hardware.h>
-#include <asm/sched_clock.h>
-#include <asm/mach/time.h>
-#include <mach/common.h>
-
-/*
- * There are 2 versions of the timer hardware on Freescale MXC hardware.
- * Version 1: MX1/MXL, MX21, MX27.
- * Version 2: MX25, MX31, MX35, MX37, MX51
- */
-
-/* defines common for all i.MX */
-#define MXC_TCTL		0x00
-#define MXC_TCTL_TEN		(1 << 0) /* Enable module */
-#define MXC_TPRER		0x04
-
-/* MX1, MX21, MX27 */
-#define MX1_2_TCTL_CLK_PCLK1	(1 << 1)
-#define MX1_2_TCTL_IRQEN	(1 << 4)
-#define MX1_2_TCTL_FRR		(1 << 8)
-#define MX1_2_TCMP		0x08
-#define MX1_2_TCN		0x10
-#define MX1_2_TSTAT		0x14
-
-/* MX21, MX27 */
-#define MX2_TSTAT_CAPT		(1 << 1)
-#define MX2_TSTAT_COMP		(1 << 0)
-
-/* MX31, MX35, MX25, MX5 */
-#define V2_TCTL_WAITEN		(1 << 3) /* Wait enable mode */
-#define V2_TCTL_CLK_IPG		(1 << 6)
-#define V2_TCTL_CLK_PER		(2 << 6)
-#define V2_TCTL_FRR		(1 << 9)
-#define V2_IR			0x0c
-#define V2_TSTAT		0x08
-#define V2_TSTAT_OF1		(1 << 0)
-#define V2_TCN			0x24
-#define V2_TCMP			0x10
-
-#define timer_is_v1()	(cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
-#define timer_is_v2()	(!timer_is_v1())
-
-static struct clock_event_device clockevent_mxc;
-static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
-
-static void __iomem *timer_base;
-
-static inline void gpt_irq_disable(void)
-{
-	unsigned int tmp;
-
-	if (timer_is_v2())
-		__raw_writel(0, timer_base + V2_IR);
-	else {
-		tmp = __raw_readl(timer_base + MXC_TCTL);
-		__raw_writel(tmp & ~MX1_2_TCTL_IRQEN, timer_base + MXC_TCTL);
-	}
-}
-
-static inline void gpt_irq_enable(void)
-{
-	if (timer_is_v2())
-		__raw_writel(1<<0, timer_base + V2_IR);
-	else {
-		__raw_writel(__raw_readl(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
-			timer_base + MXC_TCTL);
-	}
-}
-
-static void gpt_irq_acknowledge(void)
-{
-	if (timer_is_v1()) {
-		if (cpu_is_mx1())
-			__raw_writel(0, timer_base + MX1_2_TSTAT);
-		else
-			__raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP,
-				timer_base + MX1_2_TSTAT);
-	} else if (timer_is_v2())
-		__raw_writel(V2_TSTAT_OF1, timer_base + V2_TSTAT);
-}
-
-static void __iomem *sched_clock_reg;
-
-static u32 notrace mxc_read_sched_clock(void)
-{
-	return sched_clock_reg ? __raw_readl(sched_clock_reg) : 0;
-}
-
-static int __init mxc_clocksource_init(struct clk *timer_clk)
-{
-	unsigned int c = clk_get_rate(timer_clk);
-	void __iomem *reg = timer_base + (timer_is_v2() ? V2_TCN : MX1_2_TCN);
-
-	sched_clock_reg = reg;
-
-	setup_sched_clock(mxc_read_sched_clock, 32, c);
-	return clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32,
-			clocksource_mmio_readl_up);
-}
-
-/* clock event */
-
-static int mx1_2_set_next_event(unsigned long evt,
-			      struct clock_event_device *unused)
-{
-	unsigned long tcmp;
-
-	tcmp = __raw_readl(timer_base + MX1_2_TCN) + evt;
-
-	__raw_writel(tcmp, timer_base + MX1_2_TCMP);
-
-	return (int)(tcmp - __raw_readl(timer_base + MX1_2_TCN)) < 0 ?
-				-ETIME : 0;
-}
-
-static int v2_set_next_event(unsigned long evt,
-			      struct clock_event_device *unused)
-{
-	unsigned long tcmp;
-
-	tcmp = __raw_readl(timer_base + V2_TCN) + evt;
-
-	__raw_writel(tcmp, timer_base + V2_TCMP);
-
-	return (int)(tcmp - __raw_readl(timer_base + V2_TCN)) < 0 ?
-				-ETIME : 0;
-}
-
-#ifdef DEBUG
-static const char *clock_event_mode_label[] = {
-	[CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
-	[CLOCK_EVT_MODE_ONESHOT]  = "CLOCK_EVT_MODE_ONESHOT",
-	[CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
-	[CLOCK_EVT_MODE_UNUSED]   = "CLOCK_EVT_MODE_UNUSED",
-	[CLOCK_EVT_MODE_RESUME]   = "CLOCK_EVT_MODE_RESUME",
-};
-#endif /* DEBUG */
-
-static void mxc_set_mode(enum clock_event_mode mode,
-				struct clock_event_device *evt)
-{
-	unsigned long flags;
-
-	/*
-	 * The timer interrupt generation is disabled at least
-	 * for enough time to call mxc_set_next_event()
-	 */
-	local_irq_save(flags);
-
-	/* Disable interrupt in GPT module */
-	gpt_irq_disable();
-
-	if (mode != clockevent_mode) {
-		/* Set event time into far-far future */
-		if (timer_is_v2())
-			__raw_writel(__raw_readl(timer_base + V2_TCN) - 3,
-					timer_base + V2_TCMP);
-		else
-			__raw_writel(__raw_readl(timer_base + MX1_2_TCN) - 3,
-					timer_base + MX1_2_TCMP);
-
-		/* Clear pending interrupt */
-		gpt_irq_acknowledge();
-	}
-
-#ifdef DEBUG
-	printk(KERN_INFO "mxc_set_mode: changing mode from %s to %s\n",
-		clock_event_mode_label[clockevent_mode],
-		clock_event_mode_label[mode]);
-#endif /* DEBUG */
-
-	/* Remember timer mode */
-	clockevent_mode = mode;
-	local_irq_restore(flags);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		printk(KERN_ERR"mxc_set_mode: Periodic mode is not "
-				"supported for i.MX\n");
-		break;
-	case CLOCK_EVT_MODE_ONESHOT:
-	/*
-	 * Do not put overhead of interrupt enable/disable into
-	 * mxc_set_next_event(), the core has about 4 minutes
-	 * to call mxc_set_next_event() or shutdown clock after
-	 * mode switching
-	 */
-		local_irq_save(flags);
-		gpt_irq_enable();
-		local_irq_restore(flags);
-		break;
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_RESUME:
-		/* Left event sources disabled, no more interrupts appear */
-		break;
-	}
-}
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = &clockevent_mxc;
-	uint32_t tstat;
-
-	if (timer_is_v2())
-		tstat = __raw_readl(timer_base + V2_TSTAT);
-	else
-		tstat = __raw_readl(timer_base + MX1_2_TSTAT);
-
-	gpt_irq_acknowledge();
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction mxc_timer_irq = {
-	.name		= "i.MX Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= mxc_timer_interrupt,
-};
-
-static struct clock_event_device clockevent_mxc = {
-	.name		= "mxc_timer1",
-	.features	= CLOCK_EVT_FEAT_ONESHOT,
-	.shift		= 32,
-	.set_mode	= mxc_set_mode,
-	.set_next_event	= mx1_2_set_next_event,
-	.rating		= 200,
-};
-
-static int __init mxc_clockevent_init(struct clk *timer_clk)
-{
-	unsigned int c = clk_get_rate(timer_clk);
-
-	if (timer_is_v2())
-		clockevent_mxc.set_next_event = v2_set_next_event;
-
-	clockevent_mxc.mult = div_sc(c, NSEC_PER_SEC,
-					clockevent_mxc.shift);
-	clockevent_mxc.max_delta_ns =
-			clockevent_delta2ns(0xfffffffe, &clockevent_mxc);
-	clockevent_mxc.min_delta_ns =
-			clockevent_delta2ns(0xff, &clockevent_mxc);
-
-	clockevent_mxc.cpumask = cpumask_of(0);
-
-	clockevents_register_device(&clockevent_mxc);
-
-	return 0;
-}
-
-void __init mxc_timer_init(void __iomem *base, int irq)
-{
-	uint32_t tctl_val;
-	struct clk *timer_clk;
-	struct clk *timer_ipg_clk;
-
-	timer_clk = clk_get_sys("imx-gpt.0", "per");
-	if (IS_ERR(timer_clk)) {
-		pr_err("i.MX timer: unable to get clk\n");
-		return;
-	}
-
-	timer_ipg_clk = clk_get_sys("imx-gpt.0", "ipg");
-	if (!IS_ERR(timer_ipg_clk))
-		clk_prepare_enable(timer_ipg_clk);
-
-	clk_prepare_enable(timer_clk);
-
-	timer_base = base;
-
-	/*
-	 * Initialise to a known state (all timers off, and timing reset)
-	 */
-
-	__raw_writel(0, timer_base + MXC_TCTL);
-	__raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
-
-	if (timer_is_v2())
-		tctl_val = V2_TCTL_CLK_PER | V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
-	else
-		tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
-
-	__raw_writel(tctl_val, timer_base + MXC_TCTL);
-
-	/* init and register the timer to the framework */
-	mxc_clocksource_init(timer_clk);
-	mxc_clockevent_init(timer_clk);
-
-	/* Make irqs happen */
-	setup_irq(irq, &mxc_timer_irq);
-}
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
deleted file mode 100644
index 3ed1adb..0000000
--- a/arch/arm/plat-mxc/tzic.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C)2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/irqdomain.h>
-#include <linux/of.h>
-
-#include <asm/mach/irq.h>
-#include <asm/exception.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-
-#include "irq-common.h"
-
-/*
- *****************************************
- * TZIC Registers                        *
- *****************************************
- */
-
-#define TZIC_INTCNTL	0x0000	/* Control register */
-#define TZIC_INTTYPE	0x0004	/* Controller Type register */
-#define TZIC_IMPID	0x0008	/* Distributor Implementer Identification */
-#define TZIC_PRIOMASK	0x000C	/* Priority Mask Reg */
-#define TZIC_SYNCCTRL	0x0010	/* Synchronizer Control register */
-#define TZIC_DSMINT	0x0014	/* DSM interrupt Holdoffregister */
-#define TZIC_INTSEC0(i)	(0x0080 + ((i) << 2)) /* Interrupt Security Reg 0 */
-#define TZIC_ENSET0(i)	(0x0100 + ((i) << 2)) /* Enable Set Reg 0 */
-#define TZIC_ENCLEAR0(i) (0x0180 + ((i) << 2)) /* Enable Clear Reg 0 */
-#define TZIC_SRCSET0	0x0200	/* Source Set Register 0 */
-#define TZIC_SRCCLAR0	0x0280	/* Source Clear Register 0 */
-#define TZIC_PRIORITY0	0x0400	/* Priority Register 0 */
-#define TZIC_PND0	0x0D00	/* Pending Register 0 */
-#define TZIC_HIPND(i)	(0x0D80+ ((i) << 2))	/* High Priority Pending Register */
-#define TZIC_WAKEUP0(i)	(0x0E00 + ((i) << 2))	/* Wakeup Config Register */
-#define TZIC_SWINT	0x0F00	/* Software Interrupt Rigger Register */
-#define TZIC_ID0	0x0FD0	/* Indentification Register 0 */
-
-void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */
-static struct irq_domain *domain;
-
-#define TZIC_NUM_IRQS 128
-
-#ifdef CONFIG_FIQ
-static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
-{
-	unsigned int index, mask, value;
-
-	index = irq >> 5;
-	if (unlikely(index >= 4))
-		return -EINVAL;
-	mask = 1U << (irq & 0x1F);
-
-	value = __raw_readl(tzic_base + TZIC_INTSEC0(index)) | mask;
-	if (type)
-		value &= ~mask;
-	__raw_writel(value, tzic_base + TZIC_INTSEC0(index));
-
-	return 0;
-}
-#else
-#define tzic_set_irq_fiq NULL
-#endif
-
-#ifdef CONFIG_PM
-static void tzic_irq_suspend(struct irq_data *d)
-{
-	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-	int idx = d->hwirq >> 5;
-
-	__raw_writel(gc->wake_active, tzic_base + TZIC_WAKEUP0(idx));
-}
-
-static void tzic_irq_resume(struct irq_data *d)
-{
-	int idx = d->hwirq >> 5;
-
-	__raw_writel(__raw_readl(tzic_base + TZIC_ENSET0(idx)),
-		     tzic_base + TZIC_WAKEUP0(idx));
-}
-
-#else
-#define tzic_irq_suspend NULL
-#define tzic_irq_resume NULL
-#endif
-
-static struct mxc_extra_irq tzic_extra_irq = {
-#ifdef CONFIG_FIQ
-	.set_irq_fiq = tzic_set_irq_fiq,
-#endif
-};
-
-static __init void tzic_init_gc(int idx, unsigned int irq_start)
-{
-	struct irq_chip_generic *gc;
-	struct irq_chip_type *ct;
-
-	gc = irq_alloc_generic_chip("tzic", 1, irq_start, tzic_base,
-				    handle_level_irq);
-	gc->private = &tzic_extra_irq;
-	gc->wake_enabled = IRQ_MSK(32);
-
-	ct = gc->chip_types;
-	ct->chip.irq_mask = irq_gc_mask_disable_reg;
-	ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
-	ct->chip.irq_set_wake = irq_gc_set_wake;
-	ct->chip.irq_suspend = tzic_irq_suspend;
-	ct->chip.irq_resume = tzic_irq_resume;
-	ct->regs.disable = TZIC_ENCLEAR0(idx);
-	ct->regs.enable = TZIC_ENSET0(idx);
-
-	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
-}
-
-asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
-{
-	u32 stat;
-	int i, irqofs, handled;
-
-	do {
-		handled = 0;
-
-		for (i = 0; i < 4; i++) {
-			stat = __raw_readl(tzic_base + TZIC_HIPND(i)) &
-				__raw_readl(tzic_base + TZIC_INTSEC0(i));
-
-			while (stat) {
-				handled = 1;
-				irqofs = fls(stat) - 1;
-				handle_IRQ(irq_find_mapping(domain,
-						irqofs + i * 32), regs);
-				stat &= ~(1 << irqofs);
-			}
-		}
-	} while (handled);
-}
-
-/*
- * This function initializes the TZIC hardware and disables all the
- * interrupts. It registers the interrupt enable and disable functions
- * to the kernel for each interrupt source.
- */
-void __init tzic_init_irq(void __iomem *irqbase)
-{
-	struct device_node *np;
-	int irq_base;
-	int i;
-
-	tzic_base = irqbase;
-	/* put the TZIC into the reset value with
-	 * all interrupts disabled
-	 */
-	i = __raw_readl(tzic_base + TZIC_INTCNTL);
-
-	__raw_writel(0x80010001, tzic_base + TZIC_INTCNTL);
-	__raw_writel(0x1f, tzic_base + TZIC_PRIOMASK);
-	__raw_writel(0x02, tzic_base + TZIC_SYNCCTRL);
-
-	for (i = 0; i < 4; i++)
-		__raw_writel(0xFFFFFFFF, tzic_base + TZIC_INTSEC0(i));
-
-	/* disable all interrupts */
-	for (i = 0; i < 4; i++)
-		__raw_writel(0xFFFFFFFF, tzic_base + TZIC_ENCLEAR0(i));
-
-	/* all IRQ no FIQ Warning :: No selection */
-
-	irq_base = irq_alloc_descs(-1, 0, TZIC_NUM_IRQS, numa_node_id());
-	WARN_ON(irq_base < 0);
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,tzic");
-	domain = irq_domain_add_legacy(np, TZIC_NUM_IRQS, irq_base, 0,
-				       &irq_domain_simple_ops, NULL);
-	WARN_ON(!domain);
-
-	for (i = 0; i < 4; i++, irq_base += 32)
-		tzic_init_gc(i, irq_base);
-
-#ifdef CONFIG_FIQ
-	/* Initialize FIQ */
-	init_FIQ(FIQ_START);
-#endif
-
-	pr_info("TrustZone Interrupt Controller (TZIC) initialized\n");
-}
-
-/**
- * tzic_enable_wake() - enable wakeup interrupt
- *
- * @return			0 if successful; non-zero otherwise
- *
- * This function provides an interrupt synchronization point that is required
- * by tzic enabled platforms before entering imx specific low power modes (ie,
- * those low power modes beyond the WAIT_CLOCKED basic ARM WFI only mode).
- */
-int tzic_enable_wake(void)
-{
-	unsigned int i;
-
-	__raw_writel(1, tzic_base + TZIC_DSMINT);
-	if (unlikely(__raw_readl(tzic_base + TZIC_DSMINT) == 0))
-		return -EAGAIN;
-
-	for (i = 0; i < 4; i++)
-		__raw_writel(__raw_readl(tzic_base + TZIC_ENSET0(i)),
-			     tzic_base + TZIC_WAKEUP0(i));
-
-	return 0;
-}
diff --git a/arch/arm/plat-mxc/ulpi.c b/arch/arm/plat-mxc/ulpi.c
deleted file mode 100644
index d296342..0000000
--- a/arch/arm/plat-mxc/ulpi.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
- * Copyright 2009 Daniel Mack <daniel@caiaq.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-
-#include <mach/ulpi.h>
-
-/* ULPIVIEW register bits */
-#define ULPIVW_WU		(1 << 31)	/* Wakeup */
-#define ULPIVW_RUN		(1 << 30)	/* read/write run */
-#define ULPIVW_WRITE		(1 << 29)	/* 0 = read  1 = write */
-#define ULPIVW_SS		(1 << 27)	/* SyncState */
-#define ULPIVW_PORT_MASK	0x07	/* Port field */
-#define ULPIVW_PORT_SHIFT	24
-#define ULPIVW_ADDR_MASK	0xff	/* data address field */
-#define ULPIVW_ADDR_SHIFT	16
-#define ULPIVW_RDATA_MASK	0xff	/* read data field */
-#define ULPIVW_RDATA_SHIFT	8
-#define ULPIVW_WDATA_MASK	0xff	/* write data field */
-#define ULPIVW_WDATA_SHIFT	0
-
-static int ulpi_poll(void __iomem *view, u32 bit)
-{
-	int timeout = 10000;
-
-	while (timeout--) {
-		u32 data = __raw_readl(view);
-
-		if (!(data & bit))
-			return 0;
-
-		cpu_relax();
-	};
-
-	printk(KERN_WARNING "timeout polling for ULPI device\n");
-
-	return -ETIMEDOUT;
-}
-
-static int ulpi_read(struct usb_phy *otg, u32 reg)
-{
-	int ret;
-	void __iomem *view = otg->io_priv;
-
-	/* make sure interface is running */
-	if (!(__raw_readl(view) & ULPIVW_SS)) {
-		__raw_writel(ULPIVW_WU, view);
-
-		/* wait for wakeup */
-		ret = ulpi_poll(view, ULPIVW_WU);
-		if (ret)
-			return ret;
-	}
-
-	/* read the register */
-	__raw_writel((ULPIVW_RUN | (reg << ULPIVW_ADDR_SHIFT)), view);
-
-	/* wait for completion */
-	ret = ulpi_poll(view, ULPIVW_RUN);
-	if (ret)
-		return ret;
-
-	return (__raw_readl(view) >> ULPIVW_RDATA_SHIFT) & ULPIVW_RDATA_MASK;
-}
-
-static int ulpi_write(struct usb_phy *otg, u32 val, u32 reg)
-{
-	int ret;
-	void __iomem *view = otg->io_priv;
-
-	/* make sure the interface is running */
-	if (!(__raw_readl(view) & ULPIVW_SS)) {
-		__raw_writel(ULPIVW_WU, view);
-		/* wait for wakeup */
-		ret = ulpi_poll(view, ULPIVW_WU);
-		if (ret)
-			return ret;
-	}
-
-	__raw_writel((ULPIVW_RUN | ULPIVW_WRITE |
-		      (reg << ULPIVW_ADDR_SHIFT) |
-		      ((val & ULPIVW_WDATA_MASK) << ULPIVW_WDATA_SHIFT)), view);
-
-	/* wait for completion */
-	return ulpi_poll(view, ULPIVW_RUN);
-}
-
-struct usb_phy_io_ops mxc_ulpi_access_ops = {
-	.read	= ulpi_read,
-	.write	= ulpi_write,
-};
-EXPORT_SYMBOL_GPL(mxc_ulpi_access_ops);
-
-struct usb_phy *imx_otg_ulpi_create(unsigned int flags)
-{
-	return otg_ulpi_create(&mxc_ulpi_access_ops, flags);
-}
diff --git a/arch/arm/plat-nomadik/Kconfig b/arch/arm/plat-nomadik/Kconfig
deleted file mode 100644
index 19f55ca..0000000
--- a/arch/arm/plat-nomadik/Kconfig
+++ /dev/null
@@ -1,29 +0,0 @@
-# We keep common IP's here for Nomadik and other similar
-# familiy of processors from ST-Ericsson. At the moment we have
-# just MTU, others to follow soon.
-
-config PLAT_NOMADIK
-	bool
-	depends on ARCH_NOMADIK || ARCH_U8500
-	default y
-	select CLKSRC_MMIO
-	help
-	  Common platform code for Nomadik and other ST-Ericsson
-	  platforms.
-
-if PLAT_NOMADIK
-
-config HAS_MTU
-	bool
-	help
-	  Support for Multi Timer Unit. MTU provides access
-	  to multiple interrupt generating programmable
-	  32-bit free running decrementing counters.
-
-config NOMADIK_MTU_SCHED_CLOCK
-	bool
-	depends on HAS_MTU
-	help
-	  Use the Multi Timer Unit as the sched_clock.
-
-endif
diff --git a/arch/arm/plat-nomadik/Makefile b/arch/arm/plat-nomadik/Makefile
deleted file mode 100644
index 37c7cdd..0000000
--- a/arch/arm/plat-nomadik/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# arch/arm/plat-nomadik/Makefile
-# Copyright 2009 ST-Ericsson
-# Licensed under GPLv2
-
-obj-$(CONFIG_HAS_MTU)	+= timer.o
diff --git a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
deleted file mode 100644
index c08a54d..0000000
--- a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Structures and registers for GPIO access in the Nomadik SoC
- *
- * Copyright (C) 2008 STMicroelectronics
- *     Author: Prafulla WADASKAR <prafulla.wadaskar@st.com>
- * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __PLAT_NOMADIK_GPIO
-#define __PLAT_NOMADIK_GPIO
-
-/*
- * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
- * the "gpio" namespace for generic and cross-machine functions
- */
-
-/* Register in the logic block */
-#define NMK_GPIO_DAT	0x00
-#define NMK_GPIO_DATS	0x04
-#define NMK_GPIO_DATC	0x08
-#define NMK_GPIO_PDIS	0x0c
-#define NMK_GPIO_DIR	0x10
-#define NMK_GPIO_DIRS	0x14
-#define NMK_GPIO_DIRC	0x18
-#define NMK_GPIO_SLPC	0x1c
-#define NMK_GPIO_AFSLA	0x20
-#define NMK_GPIO_AFSLB	0x24
-#define NMK_GPIO_LOWEMI	0x28
-
-#define NMK_GPIO_RIMSC	0x40
-#define NMK_GPIO_FIMSC	0x44
-#define NMK_GPIO_IS	0x48
-#define NMK_GPIO_IC	0x4c
-#define NMK_GPIO_RWIMSC	0x50
-#define NMK_GPIO_FWIMSC	0x54
-#define NMK_GPIO_WKS	0x58
-
-/* Alternate functions: function C is set in hw by setting both A and B */
-#define NMK_GPIO_ALT_GPIO	0
-#define NMK_GPIO_ALT_A	1
-#define NMK_GPIO_ALT_B	2
-#define NMK_GPIO_ALT_C	(NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
-
-#define NMK_GPIO_ALT_CX_SHIFT 2
-#define NMK_GPIO_ALT_C1	((1<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C2	((2<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C3	((3<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C4	((4<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-
-/* Pull up/down values */
-enum nmk_gpio_pull {
-	NMK_GPIO_PULL_NONE,
-	NMK_GPIO_PULL_UP,
-	NMK_GPIO_PULL_DOWN,
-};
-
-/* Sleep mode */
-enum nmk_gpio_slpm {
-	NMK_GPIO_SLPM_INPUT,
-	NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
-	NMK_GPIO_SLPM_NOCHANGE,
-	NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
-};
-
-extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
-extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
-#ifdef CONFIG_PINCTRL_NOMADIK
-extern int nmk_gpio_set_mode(int gpio, int gpio_mode);
-#else
-static inline int nmk_gpio_set_mode(int gpio, int gpio_mode)
-{
-	return -ENODEV;
-}
-#endif
-extern int nmk_gpio_get_mode(int gpio);
-
-extern void nmk_gpio_wakeups_suspend(void);
-extern void nmk_gpio_wakeups_resume(void);
-
-extern void nmk_gpio_clocks_enable(void);
-extern void nmk_gpio_clocks_disable(void);
-
-extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
-
-/*
- * Platform data to register a block: only the initial gpio/irq number.
- */
-struct nmk_gpio_platform_data {
-	char *name;
-	int first_gpio;
-	int first_irq;
-	int num_gpio;
-	u32 (*get_secondary_status)(unsigned int bank);
-	void (*set_ioforce)(bool enable);
-	bool supports_sleepmode;
-};
-
-#endif /* __PLAT_NOMADIK_GPIO */
diff --git a/arch/arm/plat-nomadik/include/plat/mtu.h b/arch/arm/plat-nomadik/include/plat/mtu.h
deleted file mode 100644
index 582641f..0000000
--- a/arch/arm/plat-nomadik/include/plat/mtu.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __PLAT_MTU_H
-#define __PLAT_MTU_H
-
-void nmdk_timer_init(void __iomem *base);
-void nmdk_clkevt_reset(void);
-void nmdk_clksrc_reset(void);
-
-#endif /* __PLAT_MTU_H */
-
diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h
deleted file mode 100644
index 3b8ec60..0000000
--- a/arch/arm/plat-nomadik/include/plat/pincfg.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License terms: GNU General Public License, version 2
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- *
- * Based on arch/arm/mach-pxa/include/mach/mfp.h:
- *   Copyright (C) 2007 Marvell International Ltd.
- *   eric miao <eric.miao@marvell.com>
- */
-
-#ifndef __PLAT_PINCFG_H
-#define __PLAT_PINCFG_H
-
-/*
- * pin configurations are represented by 32-bit integers:
- *
- *	bit  0.. 8 - Pin Number (512 Pins Maximum)
- *	bit  9..10 - Alternate Function Selection
- *	bit 11..12 - Pull up/down state
- *	bit     13 - Sleep mode behaviour
- *	bit     14 - Direction
- *	bit     15 - Value (if output)
- *	bit 16..18 - SLPM pull up/down state
- *	bit 19..20 - SLPM direction
- *	bit 21..22 - SLPM Value (if output)
- *	bit 23..25 - PDIS value (if input)
- *	bit	26 - Gpio mode
- *	bit	27 - Sleep mode
- *
- * to facilitate the definition, the following macros are provided
- *
- * PIN_CFG_DEFAULT - default config (0):
- *		     pull up/down = disabled
- *		     sleep mode = input/wakeup
- *		     direction = input
- *		     value = low
- *		     SLPM direction = same as normal
- *		     SLPM pull = same as normal
- *		     SLPM value = same as normal
- *
- * PIN_CFG	   - default config with alternate function
- */
-
-typedef unsigned long pin_cfg_t;
-
-#define PIN_NUM_MASK		0x1ff
-#define PIN_NUM(x)		((x) & PIN_NUM_MASK)
-
-#define PIN_ALT_SHIFT		9
-#define PIN_ALT_MASK		(0x3 << PIN_ALT_SHIFT)
-#define PIN_ALT(x)		(((x) & PIN_ALT_MASK) >> PIN_ALT_SHIFT)
-#define PIN_GPIO		(NMK_GPIO_ALT_GPIO << PIN_ALT_SHIFT)
-#define PIN_ALT_A		(NMK_GPIO_ALT_A << PIN_ALT_SHIFT)
-#define PIN_ALT_B		(NMK_GPIO_ALT_B << PIN_ALT_SHIFT)
-#define PIN_ALT_C		(NMK_GPIO_ALT_C << PIN_ALT_SHIFT)
-
-#define PIN_PULL_SHIFT		11
-#define PIN_PULL_MASK		(0x3 << PIN_PULL_SHIFT)
-#define PIN_PULL(x)		(((x) & PIN_PULL_MASK) >> PIN_PULL_SHIFT)
-#define PIN_PULL_NONE		(NMK_GPIO_PULL_NONE << PIN_PULL_SHIFT)
-#define PIN_PULL_UP		(NMK_GPIO_PULL_UP << PIN_PULL_SHIFT)
-#define PIN_PULL_DOWN		(NMK_GPIO_PULL_DOWN << PIN_PULL_SHIFT)
-
-#define PIN_SLPM_SHIFT		13
-#define PIN_SLPM_MASK		(0x1 << PIN_SLPM_SHIFT)
-#define PIN_SLPM(x)		(((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT)
-#define PIN_SLPM_MAKE_INPUT	(NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT)
-#define PIN_SLPM_NOCHANGE	(NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT)
-/* These two replace the above in DB8500v2+ */
-#define PIN_SLPM_WAKEUP_ENABLE	(NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT)
-#define PIN_SLPM_WAKEUP_DISABLE	(NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT)
-#define PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP PIN_SLPM_WAKEUP_DISABLE
-
-#define PIN_SLPM_GPIO  PIN_SLPM_WAKEUP_ENABLE /* In SLPM, pin is a gpio */
-#define PIN_SLPM_ALTFUNC PIN_SLPM_WAKEUP_DISABLE /* In SLPM, pin is altfunc */
-
-#define PIN_DIR_SHIFT		14
-#define PIN_DIR_MASK		(0x1 << PIN_DIR_SHIFT)
-#define PIN_DIR(x)		(((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT)
-#define PIN_DIR_INPUT		(0 << PIN_DIR_SHIFT)
-#define PIN_DIR_OUTPUT		(1 << PIN_DIR_SHIFT)
-
-#define PIN_VAL_SHIFT		15
-#define PIN_VAL_MASK		(0x1 << PIN_VAL_SHIFT)
-#define PIN_VAL(x)		(((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT)
-#define PIN_VAL_LOW		(0 << PIN_VAL_SHIFT)
-#define PIN_VAL_HIGH		(1 << PIN_VAL_SHIFT)
-
-#define PIN_SLPM_PULL_SHIFT	16
-#define PIN_SLPM_PULL_MASK	(0x7 << PIN_SLPM_PULL_SHIFT)
-#define PIN_SLPM_PULL(x)	\
-	(((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT)
-#define PIN_SLPM_PULL_NONE	\
-	((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT)
-#define PIN_SLPM_PULL_UP	\
-	((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT)
-#define PIN_SLPM_PULL_DOWN	\
-	((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT)
-
-#define PIN_SLPM_DIR_SHIFT	19
-#define PIN_SLPM_DIR_MASK	(0x3 << PIN_SLPM_DIR_SHIFT)
-#define PIN_SLPM_DIR(x)		\
-	(((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT)
-#define PIN_SLPM_DIR_INPUT	((1 + 0) << PIN_SLPM_DIR_SHIFT)
-#define PIN_SLPM_DIR_OUTPUT	((1 + 1) << PIN_SLPM_DIR_SHIFT)
-
-#define PIN_SLPM_VAL_SHIFT	21
-#define PIN_SLPM_VAL_MASK	(0x3 << PIN_SLPM_VAL_SHIFT)
-#define PIN_SLPM_VAL(x)		\
-	(((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT)
-#define PIN_SLPM_VAL_LOW	((1 + 0) << PIN_SLPM_VAL_SHIFT)
-#define PIN_SLPM_VAL_HIGH	((1 + 1) << PIN_SLPM_VAL_SHIFT)
-
-#define PIN_SLPM_PDIS_SHIFT		23
-#define PIN_SLPM_PDIS_MASK		(0x3 << PIN_SLPM_PDIS_SHIFT)
-#define PIN_SLPM_PDIS(x)	\
-	(((x) & PIN_SLPM_PDIS_MASK) >> PIN_SLPM_PDIS_SHIFT)
-#define PIN_SLPM_PDIS_NO_CHANGE		(0 << PIN_SLPM_PDIS_SHIFT)
-#define PIN_SLPM_PDIS_DISABLED		(1 << PIN_SLPM_PDIS_SHIFT)
-#define PIN_SLPM_PDIS_ENABLED		(2 << PIN_SLPM_PDIS_SHIFT)
-
-#define PIN_LOWEMI_SHIFT	25
-#define PIN_LOWEMI_MASK		(0x1 << PIN_LOWEMI_SHIFT)
-#define PIN_LOWEMI(x)		(((x) & PIN_LOWEMI_MASK) >> PIN_LOWEMI_SHIFT)
-#define PIN_LOWEMI_DISABLED	(0 << PIN_LOWEMI_SHIFT)
-#define PIN_LOWEMI_ENABLED	(1 << PIN_LOWEMI_SHIFT)
-
-#define PIN_GPIOMODE_SHIFT	26
-#define PIN_GPIOMODE_MASK	(0x1 << PIN_GPIOMODE_SHIFT)
-#define PIN_GPIOMODE(x)		(((x) & PIN_GPIOMODE_MASK) >> PIN_GPIOMODE_SHIFT)
-#define PIN_GPIOMODE_DISABLED	(0 << PIN_GPIOMODE_SHIFT)
-#define PIN_GPIOMODE_ENABLED	(1 << PIN_GPIOMODE_SHIFT)
-
-#define PIN_SLEEPMODE_SHIFT	27
-#define PIN_SLEEPMODE_MASK	(0x1 << PIN_SLEEPMODE_SHIFT)
-#define PIN_SLEEPMODE(x)	(((x) & PIN_SLEEPMODE_MASK) >> PIN_SLEEPMODE_SHIFT)
-#define PIN_SLEEPMODE_DISABLED	(0 << PIN_SLEEPMODE_SHIFT)
-#define PIN_SLEEPMODE_ENABLED	(1 << PIN_SLEEPMODE_SHIFT)
-
-
-/* Shortcuts.  Use these instead of separate DIR, PULL, and VAL.  */
-#define PIN_INPUT_PULLDOWN	(PIN_DIR_INPUT | PIN_PULL_DOWN)
-#define PIN_INPUT_PULLUP	(PIN_DIR_INPUT | PIN_PULL_UP)
-#define PIN_INPUT_NOPULL	(PIN_DIR_INPUT | PIN_PULL_NONE)
-#define PIN_OUTPUT_LOW		(PIN_DIR_OUTPUT | PIN_VAL_LOW)
-#define PIN_OUTPUT_HIGH		(PIN_DIR_OUTPUT | PIN_VAL_HIGH)
-
-#define PIN_SLPM_INPUT_PULLDOWN	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN)
-#define PIN_SLPM_INPUT_PULLUP	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP)
-#define PIN_SLPM_INPUT_NOPULL	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE)
-#define PIN_SLPM_OUTPUT_LOW	(PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW)
-#define PIN_SLPM_OUTPUT_HIGH	(PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH)
-
-#define PIN_CFG_DEFAULT		(0)
-
-#define PIN_CFG(num, alt)		\
-	(PIN_CFG_DEFAULT |\
-	 (PIN_NUM(num) | PIN_##alt))
-
-#define PIN_CFG_INPUT(num, alt, pull)		\
-	(PIN_CFG_DEFAULT |\
-	 (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull))
-
-#define PIN_CFG_OUTPUT(num, alt, val)		\
-	(PIN_CFG_DEFAULT |\
-	 (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
-
-extern int nmk_config_pin(pin_cfg_t cfg, bool sleep);
-extern int nmk_config_pins(pin_cfg_t *cfgs, int num);
-extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num);
-
-#endif
diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h
deleted file mode 100644
index 9ff93b0..0000000
--- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2007-2010
- * Author: Per Forlin <per.forlin@stericsson.com> for ST-Ericsson
- * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
- * License terms: GNU General Public License (GPL) version 2
- */
-
-
-#ifndef STE_DMA40_H
-#define STE_DMA40_H
-
-#include <linux/dmaengine.h>
-#include <linux/scatterlist.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-
-/*
- * Maxium size for a single dma descriptor
- * Size is limited to 16 bits.
- * Size is in the units of addr-widths (1,2,4,8 bytes)
- * Larger transfers will be split up to multiple linked desc
- */
-#define STEDMA40_MAX_SEG_SIZE 0xFFFF
-
-/* dev types for memcpy */
-#define STEDMA40_DEV_DST_MEMORY (-1)
-#define	STEDMA40_DEV_SRC_MEMORY (-1)
-
-enum stedma40_mode {
-	STEDMA40_MODE_LOGICAL = 0,
-	STEDMA40_MODE_PHYSICAL,
-	STEDMA40_MODE_OPERATION,
-};
-
-enum stedma40_mode_opt {
-	STEDMA40_PCHAN_BASIC_MODE = 0,
-	STEDMA40_LCHAN_SRC_LOG_DST_LOG = 0,
-	STEDMA40_PCHAN_MODULO_MODE,
-	STEDMA40_PCHAN_DOUBLE_DST_MODE,
-	STEDMA40_LCHAN_SRC_PHY_DST_LOG,
-	STEDMA40_LCHAN_SRC_LOG_DST_PHY,
-};
-
-#define STEDMA40_ESIZE_8_BIT  0x0
-#define STEDMA40_ESIZE_16_BIT 0x1
-#define STEDMA40_ESIZE_32_BIT 0x2
-#define STEDMA40_ESIZE_64_BIT 0x3
-
-/* The value 4 indicates that PEN-reg shall be set to 0 */
-#define STEDMA40_PSIZE_PHY_1  0x4
-#define STEDMA40_PSIZE_PHY_2  0x0
-#define STEDMA40_PSIZE_PHY_4  0x1
-#define STEDMA40_PSIZE_PHY_8  0x2
-#define STEDMA40_PSIZE_PHY_16 0x3
-
-/*
- * The number of elements differ in logical and
- * physical mode
- */
-#define STEDMA40_PSIZE_LOG_1  STEDMA40_PSIZE_PHY_2
-#define STEDMA40_PSIZE_LOG_4  STEDMA40_PSIZE_PHY_4
-#define STEDMA40_PSIZE_LOG_8  STEDMA40_PSIZE_PHY_8
-#define STEDMA40_PSIZE_LOG_16 STEDMA40_PSIZE_PHY_16
-
-/* Maximum number of possible physical channels */
-#define STEDMA40_MAX_PHYS 32
-
-enum stedma40_flow_ctrl {
-	STEDMA40_NO_FLOW_CTRL,
-	STEDMA40_FLOW_CTRL,
-};
-
-enum stedma40_periph_data_width {
-	STEDMA40_BYTE_WIDTH = STEDMA40_ESIZE_8_BIT,
-	STEDMA40_HALFWORD_WIDTH = STEDMA40_ESIZE_16_BIT,
-	STEDMA40_WORD_WIDTH = STEDMA40_ESIZE_32_BIT,
-	STEDMA40_DOUBLEWORD_WIDTH = STEDMA40_ESIZE_64_BIT
-};
-
-enum stedma40_xfer_dir {
-	STEDMA40_MEM_TO_MEM = 1,
-	STEDMA40_MEM_TO_PERIPH,
-	STEDMA40_PERIPH_TO_MEM,
-	STEDMA40_PERIPH_TO_PERIPH
-};
-
-
-/**
- * struct stedma40_chan_cfg - dst/src channel configuration
- *
- * @big_endian: true if the src/dst should be read as big endian
- * @data_width: Data width of the src/dst hardware
- * @p_size: Burst size
- * @flow_ctrl: Flow control on/off.
- */
-struct stedma40_half_channel_info {
-	bool big_endian;
-	enum stedma40_periph_data_width data_width;
-	int psize;
-	enum stedma40_flow_ctrl flow_ctrl;
-};
-
-/**
- * struct stedma40_chan_cfg - Structure to be filled by client drivers.
- *
- * @dir: MEM 2 MEM, PERIPH 2 MEM , MEM 2 PERIPH, PERIPH 2 PERIPH
- * @high_priority: true if high-priority
- * @realtime: true if realtime mode is to be enabled.  Only available on DMA40
- * version 3+, i.e DB8500v2+
- * @mode: channel mode: physical, logical, or operation
- * @mode_opt: options for the chosen channel mode
- * @src_dev_type: Src device type
- * @dst_dev_type: Dst device type
- * @src_info: Parameters for dst half channel
- * @dst_info: Parameters for dst half channel
- * @use_fixed_channel: if true, use physical channel specified by phy_channel
- * @phy_channel: physical channel to use, only if use_fixed_channel is true
- *
- * This structure has to be filled by the client drivers.
- * It is recommended to do all dma configurations for clients in the machine.
- *
- */
-struct stedma40_chan_cfg {
-	enum stedma40_xfer_dir			 dir;
-	bool					 high_priority;
-	bool					 realtime;
-	enum stedma40_mode			 mode;
-	enum stedma40_mode_opt			 mode_opt;
-	int					 src_dev_type;
-	int					 dst_dev_type;
-	struct stedma40_half_channel_info	 src_info;
-	struct stedma40_half_channel_info	 dst_info;
-
-	bool					 use_fixed_channel;
-	int					 phy_channel;
-};
-
-/**
- * struct stedma40_platform_data - Configuration struct for the dma device.
- *
- * @dev_len: length of dev_tx and dev_rx
- * @dev_tx: mapping between destination event line and io address
- * @dev_rx: mapping between source event line and io address
- * @memcpy: list of memcpy event lines
- * @memcpy_len: length of memcpy
- * @memcpy_conf_phy: default configuration of physical channel memcpy
- * @memcpy_conf_log: default configuration of logical channel memcpy
- * @disabled_channels: A vector, ending with -1, that marks physical channels
- * that are for different reasons not available for the driver.
- */
-struct stedma40_platform_data {
-	u32				 dev_len;
-	const dma_addr_t		*dev_tx;
-	const dma_addr_t		*dev_rx;
-	int				*memcpy;
-	u32				 memcpy_len;
-	struct stedma40_chan_cfg	*memcpy_conf_phy;
-	struct stedma40_chan_cfg	*memcpy_conf_log;
-	int				 disabled_channels[STEDMA40_MAX_PHYS];
-	bool				 use_esram_lcla;
-};
-
-#ifdef CONFIG_STE_DMA40
-
-/**
- * stedma40_filter() - Provides stedma40_chan_cfg to the
- * ste_dma40 dma driver via the dmaengine framework.
- * does some checking of what's provided.
- *
- * Never directly called by client. It used by dmaengine.
- * @chan: dmaengine handle.
- * @data: Must be of type: struct stedma40_chan_cfg and is
- * the configuration of the framework.
- *
- *
- */
-
-bool stedma40_filter(struct dma_chan *chan, void *data);
-
-/**
- * stedma40_slave_mem() - Transfers a raw data buffer to or from a slave
- * (=device)
- *
- * @chan: dmaengine handle
- * @addr: source or destination physicall address.
- * @size: bytes to transfer
- * @direction: direction of transfer
- * @flags: is actually enum dma_ctrl_flags. See dmaengine.h
- */
-
-static inline struct
-dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan,
-					    dma_addr_t addr,
-					    unsigned int size,
-					    enum dma_transfer_direction direction,
-					    unsigned long flags)
-{
-	struct scatterlist sg;
-	sg_init_table(&sg, 1);
-	sg.dma_address = addr;
-	sg.length = size;
-
-	return dmaengine_prep_slave_sg(chan, &sg, 1, direction, flags);
-}
-
-#else
-static inline bool stedma40_filter(struct dma_chan *chan, void *data)
-{
-	return false;
-}
-
-static inline struct
-dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan,
-					    dma_addr_t addr,
-					    unsigned int size,
-					    enum dma_transfer_direction direction,
-					    unsigned long flags)
-{
-	return NULL;
-}
-#endif
-
-#endif
diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c
deleted file mode 100644
index 9222e55..0000000
--- a/arch/arm/plat-nomadik/timer.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- *  linux/arch/arm/plat-nomadik/timer.c
- *
- * Copyright (C) 2008 STMicroelectronics
- * Copyright (C) 2010 Alessandro Rubini
- * Copyright (C) 2010 Linus Walleij for ST-Ericsson
- *
- * This program is free software; you can redistribute 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/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/clockchips.h>
-#include <linux/clk.h>
-#include <linux/jiffies.h>
-#include <linux/err.h>
-#include <asm/mach/time.h>
-#include <asm/sched_clock.h>
-
-/*
- * The MTU device hosts four different counters, with 4 set of
- * registers. These are register names.
- */
-
-#define MTU_IMSC	0x00	/* Interrupt mask set/clear */
-#define MTU_RIS		0x04	/* Raw interrupt status */
-#define MTU_MIS		0x08	/* Masked interrupt status */
-#define MTU_ICR		0x0C	/* Interrupt clear register */
-
-/* per-timer registers take 0..3 as argument */
-#define MTU_LR(x)	(0x10 + 0x10 * (x) + 0x00)	/* Load value */
-#define MTU_VAL(x)	(0x10 + 0x10 * (x) + 0x04)	/* Current value */
-#define MTU_CR(x)	(0x10 + 0x10 * (x) + 0x08)	/* Control reg */
-#define MTU_BGLR(x)	(0x10 + 0x10 * (x) + 0x0c)	/* At next overflow */
-
-/* bits for the control register */
-#define MTU_CRn_ENA		0x80
-#define MTU_CRn_PERIODIC	0x40	/* if 0 = free-running */
-#define MTU_CRn_PRESCALE_MASK	0x0c
-#define MTU_CRn_PRESCALE_1		0x00
-#define MTU_CRn_PRESCALE_16		0x04
-#define MTU_CRn_PRESCALE_256		0x08
-#define MTU_CRn_32BITS		0x02
-#define MTU_CRn_ONESHOT		0x01	/* if 0 = wraps reloading from BGLR*/
-
-/* Other registers are usual amba/primecell registers, currently not used */
-#define MTU_ITCR	0xff0
-#define MTU_ITOP	0xff4
-
-#define MTU_PERIPH_ID0	0xfe0
-#define MTU_PERIPH_ID1	0xfe4
-#define MTU_PERIPH_ID2	0xfe8
-#define MTU_PERIPH_ID3	0xfeC
-
-#define MTU_PCELL0	0xff0
-#define MTU_PCELL1	0xff4
-#define MTU_PCELL2	0xff8
-#define MTU_PCELL3	0xffC
-
-static void __iomem *mtu_base;
-static bool clkevt_periodic;
-static u32 clk_prescale;
-static u32 nmdk_cycle;		/* write-once */
-
-#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
-/*
- * Override the global weak sched_clock symbol with this
- * local implementation which uses the clocksource to get some
- * better resolution when scheduling the kernel.
- */
-static u32 notrace nomadik_read_sched_clock(void)
-{
-	if (unlikely(!mtu_base))
-		return 0;
-
-	return -readl(mtu_base + MTU_VAL(0));
-}
-#endif
-
-/* Clockevent device: use one-shot mode */
-static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev)
-{
-	writel(1 << 1, mtu_base + MTU_IMSC);
-	writel(evt, mtu_base + MTU_LR(1));
-	/* Load highest value, enable device, enable interrupts */
-	writel(MTU_CRn_ONESHOT | clk_prescale |
-	       MTU_CRn_32BITS | MTU_CRn_ENA,
-	       mtu_base + MTU_CR(1));
-
-	return 0;
-}
-
-void nmdk_clkevt_reset(void)
-{
-	if (clkevt_periodic) {
-		/* Timer: configure load and background-load, and fire it up */
-		writel(nmdk_cycle, mtu_base + MTU_LR(1));
-		writel(nmdk_cycle, mtu_base + MTU_BGLR(1));
-
-		writel(MTU_CRn_PERIODIC | clk_prescale |
-		       MTU_CRn_32BITS | MTU_CRn_ENA,
-		       mtu_base + MTU_CR(1));
-		writel(1 << 1, mtu_base + MTU_IMSC);
-	} else {
-		/* Generate an interrupt to start the clockevent again */
-		(void) nmdk_clkevt_next(nmdk_cycle, NULL);
-	}
-}
-
-static void nmdk_clkevt_mode(enum clock_event_mode mode,
-			     struct clock_event_device *dev)
-{
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		clkevt_periodic = true;
-		nmdk_clkevt_reset();
-		break;
-	case CLOCK_EVT_MODE_ONESHOT:
-		clkevt_periodic = false;
-		break;
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_UNUSED:
-		writel(0, mtu_base + MTU_IMSC);
-		/* disable timer */
-		writel(0, mtu_base + MTU_CR(1));
-		/* load some high default value */
-		writel(0xffffffff, mtu_base + MTU_LR(1));
-		break;
-	case CLOCK_EVT_MODE_RESUME:
-		break;
-	}
-}
-
-static struct clock_event_device nmdk_clkevt = {
-	.name		= "mtu_1",
-	.features	= CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
-	.rating		= 200,
-	.set_mode	= nmdk_clkevt_mode,
-	.set_next_event	= nmdk_clkevt_next,
-};
-
-/*
- * IRQ Handler for timer 1 of the MTU block.
- */
-static irqreturn_t nmdk_timer_interrupt(int irq, void *dev_id)
-{
-	struct clock_event_device *evdev = dev_id;
-
-	writel(1 << 1, mtu_base + MTU_ICR); /* Interrupt clear reg */
-	evdev->event_handler(evdev);
-	return IRQ_HANDLED;
-}
-
-static struct irqaction nmdk_timer_irq = {
-	.name		= "Nomadik Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER,
-	.handler	= nmdk_timer_interrupt,
-	.dev_id		= &nmdk_clkevt,
-};
-
-void nmdk_clksrc_reset(void)
-{
-	/* Disable */
-	writel(0, mtu_base + MTU_CR(0));
-
-	/* ClockSource: configure load and background-load, and fire it up */
-	writel(nmdk_cycle, mtu_base + MTU_LR(0));
-	writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
-
-	writel(clk_prescale | MTU_CRn_32BITS | MTU_CRn_ENA,
-	       mtu_base + MTU_CR(0));
-}
-
-void __init nmdk_timer_init(void __iomem *base)
-{
-	unsigned long rate;
-	struct clk *clk0;
-
-	mtu_base = base;
-	clk0 = clk_get_sys("mtu0", NULL);
-	BUG_ON(IS_ERR(clk0));
-	BUG_ON(clk_prepare(clk0) < 0);
-	BUG_ON(clk_enable(clk0) < 0);
-
-	/*
-	 * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz
-	 * for ux500.
-	 * Use a divide-by-16 counter if the tick rate is more than 32MHz.
-	 * At 32 MHz, the timer (with 32 bit counter) can be programmed
-	 * to wake-up at a max 127s a head in time. Dividing a 2.4 MHz timer
-	 * with 16 gives too low timer resolution.
-	 */
-	rate = clk_get_rate(clk0);
-	if (rate > 32000000) {
-		rate /= 16;
-		clk_prescale = MTU_CRn_PRESCALE_16;
-	} else {
-		clk_prescale = MTU_CRn_PRESCALE_1;
-	}
-
-	nmdk_cycle = (rate + HZ/2) / HZ;
-
-
-	/* Timer 0 is the free running clocksource */
-	nmdk_clksrc_reset();
-
-	if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0",
-			rate, 200, 32, clocksource_mmio_readl_down))
-		pr_err("timer: failed to initialize clock source %s\n",
-		       "mtu_0");
-
-#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
-	setup_sched_clock(nomadik_read_sched_clock, 32, rate);
-#endif
-
-	/* Timer 1 is used for events, register irq and clockevents */
-	setup_irq(IRQ_MTU0, &nmdk_timer_irq);
-	nmdk_clkevt.cpumask = cpumask_of(0);
-	clockevents_config_and_register(&nmdk_clkevt, rate, 2, 0xffffffffU);
-}
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index dacaee0..8d88584 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -3,13 +3,12 @@
 #
 
 # Common support
-obj-y := common.o sram.o clock.o dma.o fb.o counter_32k.o
+obj-y := sram.o dma.o fb.o counter_32k.o
 obj-m :=
 obj-n :=
 obj-  :=
 
 # omap_device support (OMAP2+ only at the moment)
-obj-$(CONFIG_ARCH_OMAP2PLUS) += omap_device.o
 
 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
 obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
@@ -20,4 +19,3 @@ obj-y += $(i2c-omap-m) $(i2c-omap-y)
 # OMAP mailbox framework
 obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
 
-obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
deleted file mode 100644
index 9d7ac20..0000000
--- a/arch/arm/plat-omap/clock.c
+++ /dev/null
@@ -1,544 +0,0 @@
-/*
- *  linux/arch/arm/plat-omap/clock.c
- *
- *  Copyright (C) 2004 - 2008 Nokia corporation
- *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
- *
- *  Modified for omap shared clock framework by Tony Lindgren <tony@atomide.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/list.h>
-#include <linux/errno.h>
-#include <linux/export.h>
-#include <linux/err.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/cpufreq.h>
-#include <linux/io.h>
-
-#include <plat/clock.h>
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-static DEFINE_SPINLOCK(clockfw_lock);
-
-static struct clk_functions *arch_clock;
-
-/*
- * Standard clock functions defined in include/linux/clk.h
- */
-
-int clk_enable(struct clk *clk)
-{
-	unsigned long flags;
-	int ret;
-
-	if (clk == NULL || IS_ERR(clk))
-		return -EINVAL;
-
-	if (!arch_clock || !arch_clock->clk_enable)
-		return -EINVAL;
-
-	spin_lock_irqsave(&clockfw_lock, flags);
-	ret = arch_clock->clk_enable(clk);
-	spin_unlock_irqrestore(&clockfw_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-	unsigned long flags;
-
-	if (clk == NULL || IS_ERR(clk))
-		return;
-
-	if (!arch_clock || !arch_clock->clk_disable)
-		return;
-
-	spin_lock_irqsave(&clockfw_lock, flags);
-	if (clk->usecount == 0) {
-		pr_err("Trying disable clock %s with 0 usecount\n",
-		       clk->name);
-		WARN_ON(1);
-		goto out;
-	}
-
-	arch_clock->clk_disable(clk);
-
-out:
-	spin_unlock_irqrestore(&clockfw_lock, flags);
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	unsigned long flags;
-	unsigned long ret;
-
-	if (clk == NULL || IS_ERR(clk))
-		return 0;
-
-	spin_lock_irqsave(&clockfw_lock, flags);
-	ret = clk->rate;
-	spin_unlock_irqrestore(&clockfw_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-/*
- * Optional clock functions defined in include/linux/clk.h
- */
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned long flags;
-	long ret;
-
-	if (clk == NULL || IS_ERR(clk))
-		return 0;
-
-	if (!arch_clock || !arch_clock->clk_round_rate)
-		return 0;
-
-	spin_lock_irqsave(&clockfw_lock, flags);
-	ret = arch_clock->clk_round_rate(clk, rate);
-	spin_unlock_irqrestore(&clockfw_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_round_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned long flags;
-	int ret = -EINVAL;
-
-	if (clk == NULL || IS_ERR(clk))
-		return ret;
-
-	if (!arch_clock || !arch_clock->clk_set_rate)
-		return ret;
-
-	spin_lock_irqsave(&clockfw_lock, flags);
-	ret = arch_clock->clk_set_rate(clk, rate);
-	if (ret == 0)
-		propagate_rate(clk);
-	spin_unlock_irqrestore(&clockfw_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-	unsigned long flags;
-	int ret = -EINVAL;
-
-	if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
-		return ret;
-
-	if (!arch_clock || !arch_clock->clk_set_parent)
-		return ret;
-
-	spin_lock_irqsave(&clockfw_lock, flags);
-	if (clk->usecount == 0) {
-		ret = arch_clock->clk_set_parent(clk, parent);
-		if (ret == 0)
-			propagate_rate(clk);
-	} else
-		ret = -EBUSY;
-	spin_unlock_irqrestore(&clockfw_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_set_parent);
-
-struct clk *clk_get_parent(struct clk *clk)
-{
-	return clk->parent;
-}
-EXPORT_SYMBOL(clk_get_parent);
-
-/*
- * OMAP specific clock functions shared between omap1 and omap2
- */
-
-int __initdata mpurate;
-
-/*
- * By default we use the rate set by the bootloader.
- * You can override this with mpurate= cmdline option.
- */
-static int __init omap_clk_setup(char *str)
-{
-	get_option(&str, &mpurate);
-
-	if (!mpurate)
-		return 1;
-
-	if (mpurate < 1000)
-		mpurate *= 1000000;
-
-	return 1;
-}
-__setup("mpurate=", omap_clk_setup);
-
-/* Used for clocks that always have same value as the parent clock */
-unsigned long followparent_recalc(struct clk *clk)
-{
-	return clk->parent->rate;
-}
-
-/*
- * Used for clocks that have the same value as the parent clock,
- * divided by some factor
- */
-unsigned long omap_fixed_divisor_recalc(struct clk *clk)
-{
-	WARN_ON(!clk->fixed_div);
-
-	return clk->parent->rate / clk->fixed_div;
-}
-
-void clk_reparent(struct clk *child, struct clk *parent)
-{
-	list_del_init(&child->sibling);
-	if (parent)
-		list_add(&child->sibling, &parent->children);
-	child->parent = parent;
-
-	/* now do the debugfs renaming to reattach the child
-	   to the proper parent */
-}
-
-/* Propagate rate to children */
-void propagate_rate(struct clk *tclk)
-{
-	struct clk *clkp;
-
-	list_for_each_entry(clkp, &tclk->children, sibling) {
-		if (clkp->recalc)
-			clkp->rate = clkp->recalc(clkp);
-		propagate_rate(clkp);
-	}
-}
-
-static LIST_HEAD(root_clks);
-
-/**
- * recalculate_root_clocks - recalculate and propagate all root clocks
- *
- * Recalculates all root clocks (clocks with no parent), which if the
- * clock's .recalc is set correctly, should also propagate their rates.
- * Called at init.
- */
-void recalculate_root_clocks(void)
-{
-	struct clk *clkp;
-
-	list_for_each_entry(clkp, &root_clks, sibling) {
-		if (clkp->recalc)
-			clkp->rate = clkp->recalc(clkp);
-		propagate_rate(clkp);
-	}
-}
-
-/**
- * clk_preinit - initialize any fields in the struct clk before clk init
- * @clk: struct clk * to initialize
- *
- * Initialize any struct clk fields needed before normal clk initialization
- * can run.  No return value.
- */
-void clk_preinit(struct clk *clk)
-{
-	INIT_LIST_HEAD(&clk->children);
-}
-
-int clk_register(struct clk *clk)
-{
-	if (clk == NULL || IS_ERR(clk))
-		return -EINVAL;
-
-	/*
-	 * trap out already registered clocks
-	 */
-	if (clk->node.next || clk->node.prev)
-		return 0;
-
-	mutex_lock(&clocks_mutex);
-	if (clk->parent)
-		list_add(&clk->sibling, &clk->parent->children);
-	else
-		list_add(&clk->sibling, &root_clks);
-
-	list_add(&clk->node, &clocks);
-	if (clk->init)
-		clk->init(clk);
-	mutex_unlock(&clocks_mutex);
-
-	return 0;
-}
-EXPORT_SYMBOL(clk_register);
-
-void clk_unregister(struct clk *clk)
-{
-	if (clk == NULL || IS_ERR(clk))
-		return;
-
-	mutex_lock(&clocks_mutex);
-	list_del(&clk->sibling);
-	list_del(&clk->node);
-	mutex_unlock(&clocks_mutex);
-}
-EXPORT_SYMBOL(clk_unregister);
-
-void clk_enable_init_clocks(void)
-{
-	struct clk *clkp;
-
-	list_for_each_entry(clkp, &clocks, node) {
-		if (clkp->flags & ENABLE_ON_INIT)
-			clk_enable(clkp);
-	}
-}
-
-int omap_clk_enable_autoidle_all(void)
-{
-	struct clk *c;
-	unsigned long flags;
-
-	spin_lock_irqsave(&clockfw_lock, flags);
-
-	list_for_each_entry(c, &clocks, node)
-		if (c->ops->allow_idle)
-			c->ops->allow_idle(c);
-
-	spin_unlock_irqrestore(&clockfw_lock, flags);
-
-	return 0;
-}
-
-int omap_clk_disable_autoidle_all(void)
-{
-	struct clk *c;
-	unsigned long flags;
-
-	spin_lock_irqsave(&clockfw_lock, flags);
-
-	list_for_each_entry(c, &clocks, node)
-		if (c->ops->deny_idle)
-			c->ops->deny_idle(c);
-
-	spin_unlock_irqrestore(&clockfw_lock, flags);
-
-	return 0;
-}
-
-/*
- * Low level helpers
- */
-static int clkll_enable_null(struct clk *clk)
-{
-	return 0;
-}
-
-static void clkll_disable_null(struct clk *clk)
-{
-}
-
-const struct clkops clkops_null = {
-	.enable		= clkll_enable_null,
-	.disable	= clkll_disable_null,
-};
-
-/*
- * Dummy clock
- *
- * Used for clock aliases that are needed on some OMAPs, but not others
- */
-struct clk dummy_ck = {
-	.name	= "dummy",
-	.ops	= &clkops_null,
-};
-
-/*
- *
- */
-
-#ifdef CONFIG_OMAP_RESET_CLOCKS
-/*
- * Disable any unused clocks left on by the bootloader
- */
-static int __init clk_disable_unused(void)
-{
-	struct clk *ck;
-	unsigned long flags;
-
-	if (!arch_clock || !arch_clock->clk_disable_unused)
-		return 0;
-
-	pr_info("clock: disabling unused clocks to save power\n");
-
-	spin_lock_irqsave(&clockfw_lock, flags);
-	list_for_each_entry(ck, &clocks, node) {
-		if (ck->ops == &clkops_null)
-			continue;
-
-		if (ck->usecount > 0 || !ck->enable_reg)
-			continue;
-
-		arch_clock->clk_disable_unused(ck);
-	}
-	spin_unlock_irqrestore(&clockfw_lock, flags);
-
-	return 0;
-}
-late_initcall(clk_disable_unused);
-late_initcall(omap_clk_enable_autoidle_all);
-#endif
-
-int __init clk_init(struct clk_functions * custom_clocks)
-{
-	if (!custom_clocks) {
-		pr_err("No custom clock functions registered\n");
-		BUG();
-	}
-
-	arch_clock = custom_clocks;
-
-	return 0;
-}
-
-#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
-/*
- *	debugfs support to trace clock tree hierarchy and attributes
- */
-
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-static struct dentry *clk_debugfs_root;
-
-static int clk_dbg_show_summary(struct seq_file *s, void *unused)
-{
-	struct clk *c;
-	struct clk *pa;
-
-	mutex_lock(&clocks_mutex);
-	seq_printf(s, "%-30s %-30s %-10s %s\n",
-		"clock-name", "parent-name", "rate", "use-count");
-
-	list_for_each_entry(c, &clocks, node) {
-		pa = c->parent;
-		seq_printf(s, "%-30s %-30s %-10lu %d\n",
-			c->name, pa ? pa->name : "none", c->rate, c->usecount);
-	}
-	mutex_unlock(&clocks_mutex);
-
-	return 0;
-}
-
-static int clk_dbg_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, clk_dbg_show_summary, inode->i_private);
-}
-
-static const struct file_operations debug_clock_fops = {
-	.open           = clk_dbg_open,
-	.read           = seq_read,
-	.llseek         = seq_lseek,
-	.release        = single_release,
-};
-
-static int clk_debugfs_register_one(struct clk *c)
-{
-	int err;
-	struct dentry *d;
-	struct clk *pa = c->parent;
-
-	d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root);
-	if (!d)
-		return -ENOMEM;
-	c->dent = d;
-
-	d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount);
-	if (!d) {
-		err = -ENOMEM;
-		goto err_out;
-	}
-	d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
-	if (!d) {
-		err = -ENOMEM;
-		goto err_out;
-	}
-	d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
-	if (!d) {
-		err = -ENOMEM;
-		goto err_out;
-	}
-	return 0;
-
-err_out:
-	debugfs_remove_recursive(c->dent);
-	return err;
-}
-
-static int clk_debugfs_register(struct clk *c)
-{
-	int err;
-	struct clk *pa = c->parent;
-
-	if (pa && !pa->dent) {
-		err = clk_debugfs_register(pa);
-		if (err)
-			return err;
-	}
-
-	if (!c->dent) {
-		err = clk_debugfs_register_one(c);
-		if (err)
-			return err;
-	}
-	return 0;
-}
-
-static int __init clk_debugfs_init(void)
-{
-	struct clk *c;
-	struct dentry *d;
-	int err;
-
-	d = debugfs_create_dir("clock", NULL);
-	if (!d)
-		return -ENOMEM;
-	clk_debugfs_root = d;
-
-	list_for_each_entry(c, &clocks, node) {
-		err = clk_debugfs_register(c);
-		if (err)
-			goto err_out;
-	}
-
-	d = debugfs_create_file("summary", S_IRUGO,
-		d, NULL, &debug_clock_fops);
-	if (!d)
-		return -ENOMEM;
-
-	return 0;
-err_out:
-	debugfs_remove_recursive(clk_debugfs_root);
-	return err;
-}
-late_initcall(clk_debugfs_init);
-
-#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
deleted file mode 100644
index 111315a..0000000
--- a/arch/arm/plat-omap/common.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * linux/arch/arm/plat-omap/common.c
- *
- * Code common to all OMAP machines.
- * The file is created by Tony Lindgren <tony@atomide.com>
- *
- * Copyright (C) 2009 Texas Instruments
- * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/dma-mapping.h>
-
-#include <plat/common.h>
-#include <plat/vram.h>
-#include <linux/platform_data/dsp-omap.h>
-#include <plat/dma.h>
-
-#include <plat/omap-secure.h>
-
-void __init omap_reserve(void)
-{
-	omap_vram_reserve_sdram_memblock();
-	omap_dsp_reserve_sdram_memblock();
-	omap_secure_ram_reserve_memblock();
-	omap_barrier_reserve_memblock();
-}
-
-void __init omap_init_consistent_dma_size(void)
-{
-#ifdef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE
-	init_consistent_dma_size(CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE << 20);
-#endif
-}
-
-/*
- * Stub function for OMAP2 so that common files
- * continue to build when custom builds are used
- */
-int __weak omap_secure_ram_reserve_memblock(void)
-{
-	return 0;
-}
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
index 87ba8dd..f3771cd 100644
--- a/arch/arm/plat-omap/counter_32k.c
+++ b/arch/arm/plat-omap/counter_32k.c
@@ -22,9 +22,6 @@
 #include <asm/mach/time.h>
 #include <asm/sched_clock.h>
 
-#include <plat/common.h>
-#include <plat/clock.h>
-
 /* OMAP2_32KSYNCNT_CR_OFF: offset of 32ksync counter register */
 #define OMAP2_32KSYNCNT_REV_OFF		0x0
 #define OMAP2_32KSYNCNT_REV_SCHEME	(0x3 << 30)
diff --git a/arch/arm/plat-omap/debug-devices.c b/arch/arm/plat-omap/debug-devices.c
index 5a4678e..a609e21 100644
--- a/arch/arm/plat-omap/debug-devices.c
+++ b/arch/arm/plat-omap/debug-devices.c
@@ -15,8 +15,7 @@
 #include <linux/io.h>
 #include <linux/smc91x.h>
 
-#include <mach/hardware.h>
-#include "../mach-omap2/debug-devices.h"
+#include <plat/debug-devices.h>
 
 /* Many OMAP development platforms reuse the same "debug board"; these
  * platforms include H2, H3, H4, and Perseus2.
diff --git a/arch/arm/plat-omap/debug-leds.c b/arch/arm/plat-omap/debug-leds.c
index ea29bbe..aa7ebc6 100644
--- a/arch/arm/plat-omap/debug-leds.c
+++ b/arch/arm/plat-omap/debug-leds.c
@@ -17,16 +17,33 @@
 #include <linux/platform_data/gpio-omap.h>
 #include <linux/slab.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 
-#include <plat/fpga.h>
-
 /* Many OMAP development platforms reuse the same "debug board"; these
  * platforms include H2, H3, H4, and Perseus2.  There are 16 LEDs on the
  * debug board (all green), accessed through FPGA registers.
  */
 
+/* NOTE:  most boards don't have a static mapping for the FPGA ... */
+struct h2p2_dbg_fpga {
+	/* offset 0x00 */
+	u16		smc91x[8];
+	/* offset 0x10 */
+	u16		fpga_rev;
+	u16		board_rev;
+	u16		gpio_outputs;
+	u16		leds;
+	/* offset 0x18 */
+	u16		misc_inputs;
+	u16		lan_status;
+	u16		lan_reset;
+	u16		reserved0;
+	/* offset 0x20 */
+	u16		ps2_data;
+	u16		ps2_ctrl;
+	/* plus also 4 rs232 ports ... */
+};
+
 static struct h2p2_dbg_fpga __iomem *fpga;
 
 static u16 fpga_led_state;
@@ -94,7 +111,7 @@ static int fpga_probe(struct platform_device *pdev)
 	if (!iomem)
 		return -ENODEV;
 
-	fpga = ioremap(iomem->start, H2P2_DBG_FPGA_SIZE);
+	fpga = ioremap(iomem->start, resource_size(iomem));
 	__raw_writew(0xff, &fpga->leds);
 
 	for (i = 0; i < ARRAY_SIZE(dbg_leds); i++) {
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index c76ed8b..c288b76 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -36,9 +36,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 
-#include <plat/cpu.h>
-#include <plat/dma.h>
-#include <plat/tc.h>
+#include <plat-omap/dma-omap.h>
 
 /*
  * MAX_LOGICAL_DMA_CH_COUNT: the maximum number of logical DMA
@@ -175,12 +173,13 @@ static inline void set_gdma_dev(int req, int dev)
 #define omap_writel(val, reg)	do {} while (0)
 #endif
 
+#ifdef CONFIG_ARCH_OMAP1
 void omap_set_dma_priority(int lch, int dst_port, int priority)
 {
 	unsigned long reg;
 	u32 l;
 
-	if (cpu_class_is_omap1()) {
+	if (dma_omap1()) {
 		switch (dst_port) {
 		case OMAP_DMA_PORT_OCP_T1:	/* FFFECC00 */
 			reg = OMAP_TC_OCPT1_PRIOR;
@@ -203,18 +202,22 @@ void omap_set_dma_priority(int lch, int dst_port, int priority)
 		l |= (priority & 0xf) << 8;
 		omap_writel(l, reg);
 	}
+}
+#endif
 
-	if (cpu_class_is_omap2()) {
-		u32 ccr;
+#ifdef CONFIG_ARCH_OMAP2PLUS
+void omap_set_dma_priority(int lch, int dst_port, int priority)
+{
+	u32 ccr;
 
-		ccr = p->dma_read(CCR, lch);
-		if (priority)
-			ccr |= (1 << 6);
-		else
-			ccr &= ~(1 << 6);
-		p->dma_write(ccr, CCR, lch);
-	}
+	ccr = p->dma_read(CCR, lch);
+	if (priority)
+		ccr |= (1 << 6);
+	else
+		ccr &= ~(1 << 6);
+	p->dma_write(ccr, CCR, lch);
 }
+#endif
 EXPORT_SYMBOL(omap_set_dma_priority);
 
 void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
@@ -228,7 +231,7 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
 	l |= data_type;
 	p->dma_write(l, CSDP, lch);
 
-	if (cpu_class_is_omap1()) {
+	if (dma_omap1()) {
 		u16 ccr;
 
 		ccr = p->dma_read(CCR, lch);
@@ -244,7 +247,7 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
 		p->dma_write(ccr, CCR2, lch);
 	}
 
-	if (cpu_class_is_omap2() && dma_trigger) {
+	if (dma_omap2plus() && dma_trigger) {
 		u32 val;
 
 		val = p->dma_read(CCR, lch);
@@ -284,7 +287,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
 {
 	BUG_ON(omap_dma_in_1510_mode());
 
-	if (cpu_class_is_omap1()) {
+	if (dma_omap1()) {
 		u16 w;
 
 		w = p->dma_read(CCR2, lch);
@@ -314,7 +317,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
 		p->dma_write(w, LCH_CTRL, lch);
 	}
 
-	if (cpu_class_is_omap2()) {
+	if (dma_omap2plus()) {
 		u32 val;
 
 		val = p->dma_read(CCR, lch);
@@ -342,7 +345,7 @@ EXPORT_SYMBOL(omap_set_dma_color_mode);
 
 void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
 {
-	if (cpu_class_is_omap2()) {
+	if (dma_omap2plus()) {
 		u32 csdp;
 
 		csdp = p->dma_read(CSDP, lch);
@@ -355,7 +358,7 @@ EXPORT_SYMBOL(omap_set_dma_write_mode);
 
 void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode)
 {
-	if (cpu_class_is_omap1() && !cpu_is_omap15xx()) {
+	if (dma_omap1() && !dma_omap15xx()) {
 		u32 l;
 
 		l = p->dma_read(LCH_CTRL, lch);
@@ -373,7 +376,7 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode,
 {
 	u32 l;
 
-	if (cpu_class_is_omap1()) {
+	if (dma_omap1()) {
 		u16 w;
 
 		w = p->dma_read(CSDP, lch);
@@ -415,7 +418,7 @@ EXPORT_SYMBOL(omap_set_dma_params);
 
 void omap_set_dma_src_index(int lch, int eidx, int fidx)
 {
-	if (cpu_class_is_omap2())
+	if (dma_omap2plus())
 		return;
 
 	p->dma_write(eidx, CSEI, lch);
@@ -447,13 +450,13 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 	case OMAP_DMA_DATA_BURST_DIS:
 		break;
 	case OMAP_DMA_DATA_BURST_4:
-		if (cpu_class_is_omap2())
+		if (dma_omap2plus())
 			burst = 0x1;
 		else
 			burst = 0x2;
 		break;
 	case OMAP_DMA_DATA_BURST_8:
-		if (cpu_class_is_omap2()) {
+		if (dma_omap2plus()) {
 			burst = 0x2;
 			break;
 		}
@@ -463,7 +466,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 		 * fall through
 		 */
 	case OMAP_DMA_DATA_BURST_16:
-		if (cpu_class_is_omap2()) {
+		if (dma_omap2plus()) {
 			burst = 0x3;
 			break;
 		}
@@ -487,7 +490,7 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
 {
 	u32 l;
 
-	if (cpu_class_is_omap1()) {
+	if (dma_omap1()) {
 		l = p->dma_read(CSDP, lch);
 		l &= ~(0x1f << 9);
 		l |= dest_port << 9;
@@ -508,7 +511,7 @@ EXPORT_SYMBOL(omap_set_dma_dest_params);
 
 void omap_set_dma_dest_index(int lch, int eidx, int fidx)
 {
-	if (cpu_class_is_omap2())
+	if (dma_omap2plus())
 		return;
 
 	p->dma_write(eidx, CDEI, lch);
@@ -540,19 +543,19 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 	case OMAP_DMA_DATA_BURST_DIS:
 		break;
 	case OMAP_DMA_DATA_BURST_4:
-		if (cpu_class_is_omap2())
+		if (dma_omap2plus())
 			burst = 0x1;
 		else
 			burst = 0x2;
 		break;
 	case OMAP_DMA_DATA_BURST_8:
-		if (cpu_class_is_omap2())
+		if (dma_omap2plus())
 			burst = 0x2;
 		else
 			burst = 0x3;
 		break;
 	case OMAP_DMA_DATA_BURST_16:
-		if (cpu_class_is_omap2()) {
+		if (dma_omap2plus()) {
 			burst = 0x3;
 			break;
 		}
@@ -573,7 +576,7 @@ EXPORT_SYMBOL(omap_set_dma_dest_burst_mode);
 static inline void omap_enable_channel_irq(int lch)
 {
 	/* Clear CSR */
-	if (cpu_class_is_omap1())
+	if (dma_omap1())
 		p->dma_read(CSR, lch);
 	else
 		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
@@ -587,7 +590,7 @@ static inline void omap_disable_channel_irq(int lch)
 	/* disable channel interrupts */
 	p->dma_write(0, CICR, lch);
 	/* Clear CSR */
-	if (cpu_class_is_omap1())
+	if (dma_omap1())
 		p->dma_read(CSR, lch);
 	else
 		p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
@@ -611,7 +614,7 @@ static inline void enable_lnk(int lch)
 
 	l = p->dma_read(CLNK_CTRL, lch);
 
-	if (cpu_class_is_omap1())
+	if (dma_omap1())
 		l &= ~(1 << 14);
 
 	/* Set the ENABLE_LNK bits */
@@ -619,7 +622,7 @@ static inline void enable_lnk(int lch)
 		l = dma_chan[lch].next_lch | (1 << 15);
 
 #ifndef CONFIG_ARCH_OMAP1
-	if (cpu_class_is_omap2())
+	if (dma_omap2plus())
 		if (dma_chan[lch].next_linked_ch != -1)
 			l = dma_chan[lch].next_linked_ch | (1 << 15);
 #endif
@@ -636,12 +639,12 @@ static inline void disable_lnk(int lch)
 	/* Disable interrupts */
 	omap_disable_channel_irq(lch);
 
-	if (cpu_class_is_omap1()) {
+	if (dma_omap1()) {
 		/* Set the STOP_LNK bit */
 		l |= 1 << 14;
 	}
 
-	if (cpu_class_is_omap2()) {
+	if (dma_omap2plus()) {
 		/* Clear the ENABLE_LNK bit */
 		l &= ~(1 << 15);
 	}
@@ -655,7 +658,7 @@ static inline void omap2_enable_irq_lch(int lch)
 	u32 val;
 	unsigned long flags;
 
-	if (!cpu_class_is_omap2())
+	if (dma_omap1())
 		return;
 
 	spin_lock_irqsave(&dma_chan_lock, flags);
@@ -673,7 +676,7 @@ static inline void omap2_disable_irq_lch(int lch)
 	u32 val;
 	unsigned long flags;
 
-	if (!cpu_class_is_omap2())
+	if (dma_omap1())
 		return;
 
 	spin_lock_irqsave(&dma_chan_lock, flags);
@@ -712,7 +715,7 @@ int omap_request_dma(int dev_id, const char *dev_name,
 	if (p->clear_lch_regs)
 		p->clear_lch_regs(free_ch);
 
-	if (cpu_class_is_omap2())
+	if (dma_omap2plus())
 		omap_clear_dma(free_ch);
 
 	spin_unlock_irqrestore(&dma_chan_lock, flags);
@@ -723,7 +726,7 @@ int omap_request_dma(int dev_id, const char *dev_name,
 	chan->flags = 0;
 
 #ifndef CONFIG_ARCH_OMAP1
-	if (cpu_class_is_omap2()) {
+	if (dma_omap2plus()) {
 		chan->chain_id = -1;
 		chan->next_linked_ch = -1;
 	}
@@ -731,13 +734,13 @@ int omap_request_dma(int dev_id, const char *dev_name,
 
 	chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
 
-	if (cpu_class_is_omap1())
+	if (dma_omap1())
 		chan->enabled_irqs |= OMAP1_DMA_TOUT_IRQ;
-	else if (cpu_class_is_omap2())
+	else if (dma_omap2plus())
 		chan->enabled_irqs |= OMAP2_DMA_MISALIGNED_ERR_IRQ |
 			OMAP2_DMA_TRANS_ERR_IRQ;
 
-	if (cpu_is_omap16xx()) {
+	if (dma_omap16xx()) {
 		/* If the sync device is set, configure it dynamically. */
 		if (dev_id != 0) {
 			set_gdma_dev(free_ch + 1, dev_id);
@@ -748,11 +751,11 @@ int omap_request_dma(int dev_id, const char *dev_name,
 		 * id.
 		 */
 		p->dma_write(dev_id | (1 << 10), CCR, free_ch);
-	} else if (cpu_is_omap7xx() || cpu_is_omap15xx()) {
+	} else if (dma_omap1()) {
 		p->dma_write(dev_id, CCR, free_ch);
 	}
 
-	if (cpu_class_is_omap2()) {
+	if (dma_omap2plus()) {
 		omap_enable_channel_irq(free_ch);
 		omap2_enable_irq_lch(free_ch);
 	}
@@ -774,7 +777,7 @@ void omap_free_dma(int lch)
 	}
 
 	/* Disable interrupt for logical channel */
-	if (cpu_class_is_omap2())
+	if (dma_omap2plus())
 		omap2_disable_irq_lch(lch);
 
 	/* Disable all DMA interrupts for the channel. */
@@ -784,7 +787,7 @@ void omap_free_dma(int lch)
 	p->dma_write(0, CCR, lch);
 
 	/* Clear registers */
-	if (cpu_class_is_omap2())
+	if (dma_omap2plus())
 		omap_clear_dma(lch);
 
 	spin_lock_irqsave(&dma_chan_lock, flags);
@@ -810,7 +813,7 @@ omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
 {
 	u32 reg;
 
-	if (!cpu_class_is_omap2()) {
+	if (dma_omap1()) {
 		printk(KERN_ERR "FIXME: no %s on 15xx/16xx\n", __func__);
 		return;
 	}
@@ -849,7 +852,7 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio,
 	}
 	l = p->dma_read(CCR, lch);
 	l &= ~((1 << 6) | (1 << 26));
-	if (cpu_class_is_omap2() && !cpu_is_omap242x())
+	if (d->dev_caps & IS_RW_PRIORITY)
 		l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26);
 	else
 		l |= ((read_prio & 0x1) << 6);
@@ -882,7 +885,7 @@ void omap_start_dma(int lch)
 	 * The CPC/CDAC register needs to be initialized to zero
 	 * before starting dma transfer.
 	 */
-	if (cpu_is_omap15xx())
+	if (dma_omap15xx())
 		p->dma_write(0, CPC, lch);
 	else
 		p->dma_write(0, CDAC, lch);
@@ -1045,7 +1048,7 @@ dma_addr_t omap_get_dma_src_pos(int lch)
 {
 	dma_addr_t offset = 0;
 
-	if (cpu_is_omap15xx())
+	if (dma_omap15xx())
 		offset = p->dma_read(CPC, lch);
 	else
 		offset = p->dma_read(CSAC, lch);
@@ -1053,7 +1056,7 @@ dma_addr_t omap_get_dma_src_pos(int lch)
 	if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0)
 		offset = p->dma_read(CSAC, lch);
 
-	if (!cpu_is_omap15xx()) {
+	if (!dma_omap15xx()) {
 		/*
 		 * CDAC == 0 indicates that the DMA transfer on the channel has
 		 * not been started (no data has been transferred so far).
@@ -1065,7 +1068,7 @@ dma_addr_t omap_get_dma_src_pos(int lch)
 			offset = p->dma_read(CSSA, lch);
 	}
 
-	if (cpu_class_is_omap1())
+	if (dma_omap1())
 		offset |= (p->dma_read(CSSA, lch) & 0xFFFF0000);
 
 	return offset;
@@ -1084,7 +1087,7 @@ dma_addr_t omap_get_dma_dst_pos(int lch)
 {
 	dma_addr_t offset = 0;
 
-	if (cpu_is_omap15xx())
+	if (dma_omap15xx())
 		offset = p->dma_read(CPC, lch);
 	else
 		offset = p->dma_read(CDAC, lch);
@@ -1093,7 +1096,7 @@ dma_addr_t omap_get_dma_dst_pos(int lch)
 	 * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
 	 * read before the DMA controller finished disabling the channel.
 	 */
-	if (!cpu_is_omap15xx() && offset == 0) {
+	if (!dma_omap15xx() && offset == 0) {
 		offset = p->dma_read(CDAC, lch);
 		/*
 		 * CDAC == 0 indicates that the DMA transfer on the channel has
@@ -1104,7 +1107,7 @@ dma_addr_t omap_get_dma_dst_pos(int lch)
 			offset = p->dma_read(CDSA, lch);
 	}
 
-	if (cpu_class_is_omap1())
+	if (dma_omap1())
 		offset |= (p->dma_read(CDSA, lch) & 0xFFFF0000);
 
 	return offset;
@@ -1121,7 +1124,7 @@ int omap_dma_running(void)
 {
 	int lch;
 
-	if (cpu_class_is_omap1())
+	if (dma_omap1())
 		if (omap_lcd_dma_running())
 			return 1;
 
@@ -2024,7 +2027,7 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 	dma_chan		= d->chan;
 	enable_1510_mode	= d->dev_caps & ENABLE_1510_MODE;
 
-	if (cpu_class_is_omap2()) {
+	if (dma_omap2plus()) {
 		dma_linked_lch = kzalloc(sizeof(struct dma_link_info) *
 						dma_lch_count, GFP_KERNEL);
 		if (!dma_linked_lch) {
@@ -2036,7 +2039,7 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 	spin_lock_init(&dma_chan_lock);
 	for (ch = 0; ch < dma_chan_count; ch++) {
 		omap_clear_dma(ch);
-		if (cpu_class_is_omap2())
+		if (dma_omap2plus())
 			omap2_disable_irq_lch(ch);
 
 		dma_chan[ch].dev_id = -1;
@@ -2045,7 +2048,7 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 		if (ch >= 6 && enable_1510_mode)
 			continue;
 
-		if (cpu_class_is_omap1()) {
+		if (dma_omap1()) {
 			/*
 			 * request_irq() doesn't like dev_id (ie. ch) being
 			 * zero, so we have to kludge around this.
@@ -2070,11 +2073,11 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (cpu_class_is_omap2() && !cpu_is_omap242x())
+	if (d->dev_caps & IS_RW_PRIORITY)
 		omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE,
 				DMA_DEFAULT_FIFO_DEPTH, 0);
 
-	if (cpu_class_is_omap2()) {
+	if (dma_omap2plus()) {
 		strcpy(irq_name, "0");
 		dma_irq = platform_get_irq_byname(pdev, irq_name);
 		if (dma_irq < 0) {
@@ -2089,9 +2092,8 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 		}
 	}
 
-	/* reserve dma channels 0 and 1 in high security devices */
-	if (cpu_is_omap34xx() &&
-		(omap_type() != OMAP2_DEVICE_TYPE_GP)) {
+	/* reserve dma channels 0 and 1 in high security devices on 34xx */
+	if (d->dev_caps & HS_CHANNELS_RESERVED) {
 		pr_info("Reserving DMA channels 0 and 1 for HS ROM code\n");
 		dma_chan[0].dev_id = 0;
 		dma_chan[1].dev_id = 1;
@@ -2118,7 +2120,7 @@ static int __devexit omap_system_dma_remove(struct platform_device *pdev)
 {
 	int dma_irq;
 
-	if (cpu_class_is_omap2()) {
+	if (dma_omap2plus()) {
 		char irq_name[4];
 		strcpy(irq_name, "0");
 		dma_irq = platform_get_irq_byname(pdev, irq_name);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 938b50a..9deeb30 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -35,16 +35,16 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <plat/dmtimer.h>
-#include <plat/omap-pm.h>
-
-#include <mach/hardware.h>
 
 static u32 omap_reserved_systimers;
 static LIST_HEAD(omap_timer_list);
@@ -84,10 +84,6 @@ static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
 
 static void omap_timer_restore_context(struct omap_dm_timer *timer)
 {
-	if (timer->revision == 1)
-		__raw_writel(timer->context.tistat, timer->sys_stat);
-
-	__raw_writel(timer->context.tisr, timer->irq_stat);
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
 				timer->context.twer);
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
@@ -122,21 +118,13 @@ static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
 
 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
 {
-	omap_dm_timer_enable(timer);
-	if (timer->pdev->id != 1) {
-		omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
-		omap_dm_timer_wait_for_reset(timer);
-	}
-
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
+	omap_dm_timer_wait_for_reset(timer);
 	__omap_dm_timer_reset(timer, 0, 0);
-	omap_dm_timer_disable(timer);
-	timer->posted = 1;
 }
 
 int omap_dm_timer_prepare(struct omap_dm_timer *timer)
 {
-	int ret;
-
 	/*
 	 * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
 	 * do not call clk_get() for these devices.
@@ -150,13 +138,15 @@ int omap_dm_timer_prepare(struct omap_dm_timer *timer)
 		}
 	}
 
+	omap_dm_timer_enable(timer);
+
 	if (timer->capability & OMAP_TIMER_NEEDS_RESET)
 		omap_dm_timer_reset(timer);
 
-	ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
+	__omap_dm_timer_enable_posted(timer);
+	omap_dm_timer_disable(timer);
 
-	timer->posted = 1;
-	return ret;
+	return omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
 }
 
 static inline u32 omap_dm_timer_reserved_systimer(int id)
@@ -212,6 +202,13 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id)
 	unsigned long flags;
 	int ret = 0;
 
+	/* Requesting timer by ID is not supported when device tree is used */
+	if (of_have_populated_dt()) {
+		pr_warn("%s: Please use omap_dm_timer_request_by_cap()\n",
+			__func__);
+		return NULL;
+	}
+
 	spin_lock_irqsave(&dm_timer_lock, flags);
 	list_for_each_entry(t, &omap_timer_list, node) {
 		if (t->pdev->id == id && !t->reserved) {
@@ -237,6 +234,58 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id)
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
 
+/**
+ * omap_dm_timer_request_by_cap - Request a timer by capability
+ * @cap:	Bit mask of capabilities to match
+ *
+ * Find a timer based upon capabilities bit mask. Callers of this function
+ * should use the definitions found in the plat/dmtimer.h file under the
+ * comment "timer capabilities used in hwmod database". Returns pointer to
+ * timer handle on success and a NULL pointer on failure.
+ */
+struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap)
+{
+	struct omap_dm_timer *timer = NULL, *t;
+	unsigned long flags;
+
+	if (!cap)
+		return NULL;
+
+	spin_lock_irqsave(&dm_timer_lock, flags);
+	list_for_each_entry(t, &omap_timer_list, node) {
+		if ((!t->reserved) && ((t->capability & cap) == cap)) {
+			/*
+			 * If timer is not NULL, we have already found one timer
+			 * but it was not an exact match because it had more
+			 * capabilites that what was required. Therefore,
+			 * unreserve the last timer found and see if this one
+			 * is a better match.
+			 */
+			if (timer)
+				timer->reserved = 0;
+
+			timer = t;
+			timer->reserved = 1;
+
+			/* Exit loop early if we find an exact match */
+			if (t->capability == cap)
+				break;
+		}
+	}
+	spin_unlock_irqrestore(&dm_timer_lock, flags);
+
+	if (timer && omap_dm_timer_prepare(timer)) {
+		timer->reserved = 0;
+		timer = NULL;
+	}
+
+	if (!timer)
+		pr_debug("%s: timer request failed!\n", __func__);
+
+	return timer;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap);
+
 int omap_dm_timer_free(struct omap_dm_timer *timer)
 {
 	if (unlikely(!timer))
@@ -271,7 +320,7 @@ int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
 EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
 
 #if defined(CONFIG_ARCH_OMAP1)
-
+#include <mach/hardware.h>
 /**
  * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
  * @inputmask: current value of idlect mask
@@ -348,7 +397,8 @@ int omap_dm_timer_start(struct omap_dm_timer *timer)
 	omap_dm_timer_enable(timer);
 
 	if (!(timer->capability & OMAP_TIMER_ALWON)) {
-		if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) !=
+		if (timer->get_context_loss_count &&
+			timer->get_context_loss_count(&timer->pdev->dev) !=
 				timer->ctx_loss_count)
 			omap_timer_restore_context(timer);
 	}
@@ -377,9 +427,11 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer)
 
 	__omap_dm_timer_stop(timer, timer->posted, rate);
 
-	if (!(timer->capability & OMAP_TIMER_ALWON))
-		timer->ctx_loss_count =
-			omap_pm_get_dev_context_loss_count(&timer->pdev->dev);
+	if (!(timer->capability & OMAP_TIMER_ALWON)) {
+		if (timer->get_context_loss_count)
+			timer->ctx_loss_count =
+				timer->get_context_loss_count(&timer->pdev->dev);
+	}
 
 	/*
 	 * Since the register values are computed and written within
@@ -388,7 +440,6 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer)
 	 */
 	timer->context.tclr =
 			omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
-	timer->context.tisr = __raw_readl(timer->irq_stat);
 	omap_dm_timer_disable(timer);
 	return 0;
 }
@@ -398,7 +449,7 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 {
 	int ret;
 	char *parent_name = NULL;
-	struct clk *fclk, *parent;
+	struct clk *parent;
 	struct dmtimer_platform_data *pdata;
 
 	if (unlikely(!timer))
@@ -414,14 +465,11 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 	 * use the clock framework to set the parent clock. To be removed
 	 * once OMAP1 migrated to using clock framework for dmtimers
 	 */
-	if (pdata->set_timer_src)
+	if (pdata && pdata->set_timer_src)
 		return pdata->set_timer_src(timer->pdev, source);
 
-	fclk = clk_get(&timer->pdev->dev, "fck");
-	if (IS_ERR_OR_NULL(fclk)) {
-		pr_err("%s: fck not found\n", __func__);
+	if (!timer->fclk)
 		return -EINVAL;
-	}
 
 	switch (source) {
 	case OMAP_TIMER_SRC_SYS_CLK:
@@ -440,18 +488,15 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 	parent = clk_get(&timer->pdev->dev, parent_name);
 	if (IS_ERR_OR_NULL(parent)) {
 		pr_err("%s: %s not found\n", __func__, parent_name);
-		ret = -EINVAL;
-		goto out;
+		return -EINVAL;
 	}
 
-	ret = clk_set_parent(fclk, parent);
+	ret = clk_set_parent(timer->fclk, parent);
 	if (IS_ERR_VALUE(ret))
 		pr_err("%s: failed to set %s as parent\n", __func__,
 			parent_name);
 
 	clk_put(parent);
-out:
-	clk_put(fclk);
 
 	return ret;
 }
@@ -495,7 +540,8 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
 	omap_dm_timer_enable(timer);
 
 	if (!(timer->capability & OMAP_TIMER_ALWON)) {
-		if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) !=
+		if (timer->get_context_loss_count &&
+			timer->get_context_loss_count(&timer->pdev->dev) !=
 				timer->ctx_loss_count)
 			omap_timer_restore_context(timer);
 	}
@@ -533,8 +579,8 @@ int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
 		l |= OMAP_TIMER_CTRL_CE;
 	else
 		l &= ~OMAP_TIMER_CTRL_CE;
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 
 	/* Save the context */
 	timer->context.tclr = l;
@@ -610,6 +656,37 @@ int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
 
+/**
+ * omap_dm_timer_set_int_disable - disable timer interrupts
+ * @timer:	pointer to timer handle
+ * @mask:	bit mask of interrupts to be disabled
+ *
+ * Disables the specified timer interrupts for a timer.
+ */
+int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
+{
+	u32 l = mask;
+
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
+
+	if (timer->revision == 1)
+		l = __raw_readl(timer->irq_ena) & ~mask;
+
+	__raw_writel(l, timer->irq_dis);
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask;
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l);
+
+	/* Save the context */
+	timer->context.tier &= ~mask;
+	timer->context.twer &= ~mask;
+	omap_dm_timer_disable(timer);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_disable);
+
 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
 {
 	unsigned int l;
@@ -631,8 +708,7 @@ int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
 		return -EINVAL;
 
 	__omap_dm_timer_write_status(timer, value);
-	/* Save the context */
-	timer->context.tisr = value;
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
@@ -695,7 +771,7 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
 
-	if (!pdata) {
+	if (!pdata && !dev->of_node) {
 		dev_err(dev, "%s: no platform data.\n", __func__);
 		return -ENODEV;
 	}
@@ -724,11 +800,25 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	timer->id = pdev->id;
+	if (dev->of_node) {
+		if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))
+			timer->capability |= OMAP_TIMER_ALWON;
+		if (of_find_property(dev->of_node, "ti,timer-dsp", NULL))
+			timer->capability |= OMAP_TIMER_HAS_DSP_IRQ;
+		if (of_find_property(dev->of_node, "ti,timer-pwm", NULL))
+			timer->capability |= OMAP_TIMER_HAS_PWM;
+		if (of_find_property(dev->of_node, "ti,timer-secure", NULL))
+			timer->capability |= OMAP_TIMER_SECURE;
+	} else {
+		timer->id = pdev->id;
+		timer->errata = pdata->timer_errata;
+		timer->capability = pdata->timer_capability;
+		timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
+		timer->get_context_loss_count = pdata->get_context_loss_count;
+	}
+
 	timer->irq = irq->start;
-	timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
 	timer->pdev = pdev;
-	timer->capability = pdata->timer_capability;
 
 	/* Skip pm_runtime_enable for OMAP1 */
 	if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
@@ -768,7 +858,8 @@ static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
 
 	spin_lock_irqsave(&dm_timer_lock, flags);
 	list_for_each_entry(timer, &omap_timer_list, node)
-		if (timer->pdev->id == pdev->id) {
+		if (!strcmp(dev_name(&timer->pdev->dev),
+			    dev_name(&pdev->dev))) {
 			list_del(&timer->node);
 			ret = 0;
 			break;
@@ -778,11 +869,18 @@ static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
 	return ret;
 }
 
+static const struct of_device_id omap_timer_match[] = {
+	{ .compatible = "ti,omap2-timer", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, omap_timer_match);
+
 static struct platform_driver omap_dm_timer_driver = {
 	.probe  = omap_dm_timer_probe,
 	.remove = __devexit_p(omap_dm_timer_remove),
 	.driver = {
 		.name   = "omap_timer",
+		.of_match_table = of_match_ptr(omap_timer_match),
 	},
 };
 
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
index bcbb9d5..a3367b7 100644
--- a/arch/arm/plat-omap/fb.c
+++ b/arch/arm/plat-omap/fb.c
@@ -29,10 +29,71 @@
 #include <linux/memblock.h>
 #include <linux/io.h>
 #include <linux/omapfb.h>
+#include <linux/dma-mapping.h>
 
-#include <mach/hardware.h>
 #include <asm/mach/map.h>
 
+#include <plat/cpu.h>
+
+#ifdef CONFIG_OMAP2_VRFB
+
+/*
+ * The first memory resource is the register region for VRFB,
+ * the rest are VRFB virtual memory areas for each VRFB context.
+ */
+
+static const struct resource omap2_vrfb_resources[] = {
+	DEFINE_RES_MEM_NAMED(0x68008000u, 0x40, "vrfb-regs"),
+	DEFINE_RES_MEM_NAMED(0x70000000u, 0x4000000, "vrfb-area-0"),
+	DEFINE_RES_MEM_NAMED(0x74000000u, 0x4000000, "vrfb-area-1"),
+	DEFINE_RES_MEM_NAMED(0x78000000u, 0x4000000, "vrfb-area-2"),
+	DEFINE_RES_MEM_NAMED(0x7c000000u, 0x4000000, "vrfb-area-3"),
+};
+
+static const struct resource omap3_vrfb_resources[] = {
+	DEFINE_RES_MEM_NAMED(0x6C000180u, 0xc0, "vrfb-regs"),
+	DEFINE_RES_MEM_NAMED(0x70000000u, 0x4000000, "vrfb-area-0"),
+	DEFINE_RES_MEM_NAMED(0x74000000u, 0x4000000, "vrfb-area-1"),
+	DEFINE_RES_MEM_NAMED(0x78000000u, 0x4000000, "vrfb-area-2"),
+	DEFINE_RES_MEM_NAMED(0x7c000000u, 0x4000000, "vrfb-area-3"),
+	DEFINE_RES_MEM_NAMED(0xe0000000u, 0x4000000, "vrfb-area-4"),
+	DEFINE_RES_MEM_NAMED(0xe4000000u, 0x4000000, "vrfb-area-5"),
+	DEFINE_RES_MEM_NAMED(0xe8000000u, 0x4000000, "vrfb-area-6"),
+	DEFINE_RES_MEM_NAMED(0xec000000u, 0x4000000, "vrfb-area-7"),
+	DEFINE_RES_MEM_NAMED(0xf0000000u, 0x4000000, "vrfb-area-8"),
+	DEFINE_RES_MEM_NAMED(0xf4000000u, 0x4000000, "vrfb-area-9"),
+	DEFINE_RES_MEM_NAMED(0xf8000000u, 0x4000000, "vrfb-area-10"),
+	DEFINE_RES_MEM_NAMED(0xfc000000u, 0x4000000, "vrfb-area-11"),
+};
+
+static int __init omap_init_vrfb(void)
+{
+	struct platform_device *pdev;
+	const struct resource *res;
+	unsigned int num_res;
+
+	if (cpu_is_omap24xx()) {
+		res = omap2_vrfb_resources;
+		num_res = ARRAY_SIZE(omap2_vrfb_resources);
+	} else if (cpu_is_omap34xx()) {
+		res = omap3_vrfb_resources;
+		num_res = ARRAY_SIZE(omap3_vrfb_resources);
+	} else {
+		return 0;
+	}
+
+	pdev = platform_device_register_resndata(NULL, "omapvrfb", -1,
+			res, num_res, NULL, 0);
+
+	if (IS_ERR(pdev))
+		return PTR_ERR(pdev);
+	else
+		return 0;
+}
+
+arch_initcall(omap_init_vrfb);
+#endif
+
 #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
 
 static bool omapfb_lcd_configured;
@@ -45,7 +106,7 @@ static struct platform_device omap_fb_device = {
 	.id		= -1,
 	.dev = {
 		.dma_mask		= &omap_fb_dma_mask,
-		.coherent_dma_mask	= ~(u32)0,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
 		.platform_data		= &omapfb_config,
 	},
 	.num_resources = 0,
@@ -81,7 +142,7 @@ static struct platform_device omap_fb_device = {
 	.id		= -1,
 	.dev = {
 		.dma_mask		= &omap_fb_dma_mask,
-		.coherent_dma_mask	= ~(u32)0,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
 		.platform_data		= &omapfb_config,
 	},
 	.num_resources = 0,
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index 6013831..f9df624 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -31,176 +31,13 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 
-#include <mach/irqs.h>
 #include <plat/i2c.h>
-#include <plat/omap-pm.h>
-#include <plat/omap_device.h>
 
-#define OMAP_I2C_SIZE		0x3f
-#define OMAP1_I2C_BASE		0xfffb3800
-#define OMAP1_INT_I2C		(32 + 4)
-
-static const char name[] = "omap_i2c";
-
-#define I2C_RESOURCE_BUILDER(base, irq)			\
-	{						\
-		.start	= (base),			\
-		.end	= (base) + OMAP_I2C_SIZE,	\
-		.flags	= IORESOURCE_MEM,		\
-	},						\
-	{						\
-		.start	= (irq),			\
-		.flags	= IORESOURCE_IRQ,		\
-	},
-
-static struct resource i2c_resources[][2] = {
-	{ I2C_RESOURCE_BUILDER(0, 0) },
-};
-
-#define I2C_DEV_BUILDER(bus_id, res, data)		\
-	{						\
-		.id	= (bus_id),			\
-		.name	= name,				\
-		.num_resources	= ARRAY_SIZE(res),	\
-		.resource	= (res),		\
-		.dev		= {			\
-			.platform_data	= (data),	\
-		},					\
-	}
-
-#define MAX_OMAP_I2C_HWMOD_NAME_LEN	16
 #define OMAP_I2C_MAX_CONTROLLERS 4
 static struct omap_i2c_bus_platform_data i2c_pdata[OMAP_I2C_MAX_CONTROLLERS];
-static struct platform_device omap_i2c_devices[] = {
-	I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_pdata[0]),
-};
 
 #define OMAP_I2C_CMDLINE_SETUP	(BIT(31))
 
-static int __init omap_i2c_nr_ports(void)
-{
-	int ports = 0;
-
-	if (cpu_class_is_omap1())
-		ports = 1;
-	else if (cpu_is_omap24xx())
-		ports = 2;
-	else if (cpu_is_omap34xx())
-		ports = 3;
-	else if (cpu_is_omap44xx())
-		ports = 4;
-
-	return ports;
-}
-
-static inline int omap1_i2c_add_bus(int bus_id)
-{
-	struct platform_device *pdev;
-	struct omap_i2c_bus_platform_data *pdata;
-	struct resource *res;
-
-	omap1_i2c_mux_pins(bus_id);
-
-	pdev = &omap_i2c_devices[bus_id - 1];
-	res = pdev->resource;
-	res[0].start = OMAP1_I2C_BASE;
-	res[0].end = res[0].start + OMAP_I2C_SIZE;
-	res[1].start = OMAP1_INT_I2C;
-	pdata = &i2c_pdata[bus_id - 1];
-
-	/* all OMAP1 have IP version 1 register set */
-	pdata->rev = OMAP_I2C_IP_VERSION_1;
-
-	/* all OMAP1 I2C are implemented like this */
-	pdata->flags = OMAP_I2C_FLAG_NO_FIFO |
-		       OMAP_I2C_FLAG_SIMPLE_CLOCK |
-		       OMAP_I2C_FLAG_16BIT_DATA_REG |
-		       OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK;
-
-	/* how the cpu bus is wired up differs for 7xx only */
-
-	if (cpu_is_omap7xx())
-		pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_1;
-	else
-		pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_2;
-
-	return platform_device_register(pdev);
-}
-
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-/*
- * XXX This function is a temporary compatibility wrapper - only
- * needed until the I2C driver can be converted to call
- * omap_pm_set_max_dev_wakeup_lat() and handle a return code.
- */
-static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
-{
-	omap_pm_set_max_mpu_wakeup_lat(dev, t);
-}
-
-static inline int omap2_i2c_add_bus(int bus_id)
-{
-	int l;
-	struct omap_hwmod *oh;
-	struct platform_device *pdev;
-	char oh_name[MAX_OMAP_I2C_HWMOD_NAME_LEN];
-	struct omap_i2c_bus_platform_data *pdata;
-	struct omap_i2c_dev_attr *dev_attr;
-
-	omap2_i2c_mux_pins(bus_id);
-
-	l = snprintf(oh_name, MAX_OMAP_I2C_HWMOD_NAME_LEN, "i2c%d", bus_id);
-	WARN(l >= MAX_OMAP_I2C_HWMOD_NAME_LEN,
-		"String buffer overflow in I2C%d device setup\n", bus_id);
-	oh = omap_hwmod_lookup(oh_name);
-	if (!oh) {
-			pr_err("Could not look up %s\n", oh_name);
-			return -EEXIST;
-	}
-
-	pdata = &i2c_pdata[bus_id - 1];
-	/*
-	 * pass the hwmod class's CPU-specific knowledge of I2C IP revision in
-	 * use, and functionality implementation flags, up to the OMAP I2C
-	 * driver via platform data
-	 */
-	pdata->rev = oh->class->rev;
-
-	dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr;
-	pdata->flags = dev_attr->flags;
-
-	/*
-	 * When waiting for completion of a i2c transfer, we need to
-	 * set a wake up latency constraint for the MPU. This is to
-	 * ensure quick enough wakeup from idle, when transfer
-	 * completes.
-	 * Only omap3 has support for constraints
-	 */
-	if (cpu_is_omap34xx())
-		pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
-	pdev = omap_device_build(name, bus_id, oh, pdata,
-			sizeof(struct omap_i2c_bus_platform_data),
-			NULL, 0, 0);
-	WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", name);
-
-	return PTR_RET(pdev);
-}
-#else
-static inline int omap2_i2c_add_bus(int bus_id)
-{
-	return 0;
-}
-#endif
-
-static int __init omap_i2c_add_bus(int bus_id)
-{
-	if (cpu_class_is_omap1())
-		return omap1_i2c_add_bus(bus_id);
-	else
-		return omap2_i2c_add_bus(bus_id);
-}
-
 /**
  * omap_i2c_bus_setup - Process command line options for the I2C bus speed
  * @str: String of options
@@ -214,12 +51,11 @@ static int __init omap_i2c_add_bus(int bus_id)
  */
 static int __init omap_i2c_bus_setup(char *str)
 {
-	int ports;
 	int ints[3];
 
-	ports = omap_i2c_nr_ports();
 	get_options(str, 3, ints);
-	if (ints[0] < 2 || ints[1] < 1 || ints[1] > ports)
+	if (ints[0] < 2 || ints[1] < 1 ||
+			ints[1] > OMAP_I2C_MAX_CONTROLLERS)
 		return 0;
 	i2c_pdata[ints[1] - 1].clkrate = ints[2];
 	i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP;
@@ -239,7 +75,7 @@ static int __init omap_register_i2c_bus_cmdline(void)
 	for (i = 0; i < ARRAY_SIZE(i2c_pdata); i++)
 		if (i2c_pdata[i].clkrate & OMAP_I2C_CMDLINE_SETUP) {
 			i2c_pdata[i].clkrate &= ~OMAP_I2C_CMDLINE_SETUP;
-			err = omap_i2c_add_bus(i + 1);
+			err = omap_i2c_add_bus(&i2c_pdata[i], i + 1);
 			if (err)
 				goto out;
 		}
@@ -264,7 +100,7 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
 {
 	int err;
 
-	BUG_ON(bus_id < 1 || bus_id > omap_i2c_nr_ports());
+	BUG_ON(bus_id < 1 || bus_id > OMAP_I2C_MAX_CONTROLLERS);
 
 	if (info) {
 		err = i2c_register_board_info(bus_id, info, len);
@@ -277,5 +113,5 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
 
 	i2c_pdata[bus_id - 1].clkrate &= ~OMAP_I2C_CMDLINE_SETUP;
 
-	return omap_i2c_add_bus(bus_id);
+	return omap_i2c_add_bus(&i2c_pdata[bus_id - 1], bus_id);
 }
diff --git a/arch/arm/plat-omap/include/plat-omap/dma-omap.h b/arch/arm/plat-omap/include/plat-omap/dma-omap.h
new file mode 100644
index 0000000..6f506ba
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat-omap/dma-omap.h
@@ -0,0 +1,377 @@
+/*
+ *  OMAP DMA handling defines and function
+ *
+ *  Copyright (C) 2003 Nokia Corporation
+ *  Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#include <linux/platform_device.h>
+
+#define INT_DMA_LCD			25
+
+#define OMAP1_DMA_TOUT_IRQ		(1 << 0)
+#define OMAP_DMA_DROP_IRQ		(1 << 1)
+#define OMAP_DMA_HALF_IRQ		(1 << 2)
+#define OMAP_DMA_FRAME_IRQ		(1 << 3)
+#define OMAP_DMA_LAST_IRQ		(1 << 4)
+#define OMAP_DMA_BLOCK_IRQ		(1 << 5)
+#define OMAP1_DMA_SYNC_IRQ		(1 << 6)
+#define OMAP2_DMA_PKT_IRQ		(1 << 7)
+#define OMAP2_DMA_TRANS_ERR_IRQ		(1 << 8)
+#define OMAP2_DMA_SECURE_ERR_IRQ	(1 << 9)
+#define OMAP2_DMA_SUPERVISOR_ERR_IRQ	(1 << 10)
+#define OMAP2_DMA_MISALIGNED_ERR_IRQ	(1 << 11)
+
+#define OMAP_DMA_CCR_EN			(1 << 7)
+#define OMAP_DMA_CCR_RD_ACTIVE		(1 << 9)
+#define OMAP_DMA_CCR_WR_ACTIVE		(1 << 10)
+#define OMAP_DMA_CCR_SEL_SRC_DST_SYNC	(1 << 24)
+#define OMAP_DMA_CCR_BUFFERING_DISABLE	(1 << 25)
+
+#define OMAP_DMA_DATA_TYPE_S8		0x00
+#define OMAP_DMA_DATA_TYPE_S16		0x01
+#define OMAP_DMA_DATA_TYPE_S32		0x02
+
+#define OMAP_DMA_SYNC_ELEMENT		0x00
+#define OMAP_DMA_SYNC_FRAME		0x01
+#define OMAP_DMA_SYNC_BLOCK		0x02
+#define OMAP_DMA_SYNC_PACKET		0x03
+
+#define OMAP_DMA_DST_SYNC_PREFETCH	0x02
+#define OMAP_DMA_SRC_SYNC		0x01
+#define OMAP_DMA_DST_SYNC		0x00
+
+#define OMAP_DMA_PORT_EMIFF		0x00
+#define OMAP_DMA_PORT_EMIFS		0x01
+#define OMAP_DMA_PORT_OCP_T1		0x02
+#define OMAP_DMA_PORT_TIPB		0x03
+#define OMAP_DMA_PORT_OCP_T2		0x04
+#define OMAP_DMA_PORT_MPUI		0x05
+
+#define OMAP_DMA_AMODE_CONSTANT		0x00
+#define OMAP_DMA_AMODE_POST_INC		0x01
+#define OMAP_DMA_AMODE_SINGLE_IDX	0x02
+#define OMAP_DMA_AMODE_DOUBLE_IDX	0x03
+
+#define DMA_DEFAULT_FIFO_DEPTH		0x10
+#define DMA_DEFAULT_ARB_RATE		0x01
+/* Pass THREAD_RESERVE ORed with THREAD_FIFO for tparams */
+#define DMA_THREAD_RESERVE_NORM		(0x00 << 12) /* Def */
+#define DMA_THREAD_RESERVE_ONET		(0x01 << 12)
+#define DMA_THREAD_RESERVE_TWOT		(0x02 << 12)
+#define DMA_THREAD_RESERVE_THREET	(0x03 << 12)
+#define DMA_THREAD_FIFO_NONE		(0x00 << 14) /* Def */
+#define DMA_THREAD_FIFO_75		(0x01 << 14)
+#define DMA_THREAD_FIFO_25		(0x02 << 14)
+#define DMA_THREAD_FIFO_50		(0x03 << 14)
+
+/* DMA4_OCP_SYSCONFIG bits */
+#define DMA_SYSCONFIG_MIDLEMODE_MASK		(3 << 12)
+#define DMA_SYSCONFIG_CLOCKACTIVITY_MASK	(3 << 8)
+#define DMA_SYSCONFIG_EMUFREE			(1 << 5)
+#define DMA_SYSCONFIG_SIDLEMODE_MASK		(3 << 3)
+#define DMA_SYSCONFIG_SOFTRESET			(1 << 2)
+#define DMA_SYSCONFIG_AUTOIDLE			(1 << 0)
+
+#define DMA_SYSCONFIG_MIDLEMODE(n)		((n) << 12)
+#define DMA_SYSCONFIG_SIDLEMODE(n)		((n) << 3)
+
+#define DMA_IDLEMODE_SMARTIDLE			0x2
+#define DMA_IDLEMODE_NO_IDLE			0x1
+#define DMA_IDLEMODE_FORCE_IDLE			0x0
+
+/* Chaining modes*/
+#ifndef CONFIG_ARCH_OMAP1
+#define OMAP_DMA_STATIC_CHAIN		0x1
+#define OMAP_DMA_DYNAMIC_CHAIN		0x2
+#define OMAP_DMA_CHAIN_ACTIVE		0x1
+#define OMAP_DMA_CHAIN_INACTIVE		0x0
+#endif
+
+#define DMA_CH_PRIO_HIGH		0x1
+#define DMA_CH_PRIO_LOW			0x0 /* Def */
+
+/* Errata handling */
+#define IS_DMA_ERRATA(id)		(errata & (id))
+#define SET_DMA_ERRATA(id)		(errata |= (id))
+
+#define DMA_ERRATA_IFRAME_BUFFERING	BIT(0x0)
+#define DMA_ERRATA_PARALLEL_CHANNELS	BIT(0x1)
+#define DMA_ERRATA_i378			BIT(0x2)
+#define DMA_ERRATA_i541			BIT(0x3)
+#define DMA_ERRATA_i88			BIT(0x4)
+#define DMA_ERRATA_3_3			BIT(0x5)
+#define DMA_ROMCODE_BUG			BIT(0x6)
+
+/* Attributes for OMAP DMA Contrller */
+#define DMA_LINKED_LCH			BIT(0x0)
+#define GLOBAL_PRIORITY			BIT(0x1)
+#define RESERVE_CHANNEL			BIT(0x2)
+#define IS_CSSA_32			BIT(0x3)
+#define IS_CDSA_32			BIT(0x4)
+#define IS_RW_PRIORITY			BIT(0x5)
+#define ENABLE_1510_MODE		BIT(0x6)
+#define SRC_PORT			BIT(0x7)
+#define DST_PORT			BIT(0x8)
+#define SRC_INDEX			BIT(0x9)
+#define DST_INDEX			BIT(0xa)
+#define IS_BURST_ONLY4			BIT(0xb)
+#define CLEAR_CSR_ON_READ		BIT(0xc)
+#define IS_WORD_16			BIT(0xd)
+#define ENABLE_16XX_MODE		BIT(0xe)
+#define HS_CHANNELS_RESERVED		BIT(0xf)
+
+/* Defines for DMA Capabilities */
+#define DMA_HAS_TRANSPARENT_CAPS	(0x1 << 18)
+#define DMA_HAS_CONSTANT_FILL_CAPS	(0x1 << 19)
+#define DMA_HAS_DESCRIPTOR_CAPS		(0x3 << 20)
+
+enum omap_reg_offsets {
+
+GCR,		GSCR,		GRST1,		HW_ID,
+PCH2_ID,	PCH0_ID,	PCH1_ID,	PCHG_ID,
+PCHD_ID,	CAPS_0,		CAPS_1,		CAPS_2,
+CAPS_3,		CAPS_4,		PCH2_SR,	PCH0_SR,
+PCH1_SR,	PCHD_SR,	REVISION,	IRQSTATUS_L0,
+IRQSTATUS_L1,	IRQSTATUS_L2,	IRQSTATUS_L3,	IRQENABLE_L0,
+IRQENABLE_L1,	IRQENABLE_L2,	IRQENABLE_L3,	SYSSTATUS,
+OCP_SYSCONFIG,
+
+/* omap1+ specific */
+CPC, CCR2, LCH_CTRL,
+
+/* Common registers for all omap's */
+CSDP,		CCR,		CICR,		CSR,
+CEN,		CFN,		CSFI,		CSEI,
+CSAC,		CDAC,		CDEI,
+CDFI,		CLNK_CTRL,
+
+/* Channel specific registers */
+CSSA,		CDSA,		COLOR,
+CCEN,		CCFN,
+
+/* omap3630 and omap4 specific */
+CDP,		CNDP,		CCDN,
+
+};
+
+enum omap_dma_burst_mode {
+	OMAP_DMA_DATA_BURST_DIS = 0,
+	OMAP_DMA_DATA_BURST_4,
+	OMAP_DMA_DATA_BURST_8,
+	OMAP_DMA_DATA_BURST_16,
+};
+
+enum end_type {
+	OMAP_DMA_LITTLE_ENDIAN = 0,
+	OMAP_DMA_BIG_ENDIAN
+};
+
+enum omap_dma_color_mode {
+	OMAP_DMA_COLOR_DIS = 0,
+	OMAP_DMA_CONSTANT_FILL,
+	OMAP_DMA_TRANSPARENT_COPY
+};
+
+enum omap_dma_write_mode {
+	OMAP_DMA_WRITE_NON_POSTED = 0,
+	OMAP_DMA_WRITE_POSTED,
+	OMAP_DMA_WRITE_LAST_NON_POSTED
+};
+
+enum omap_dma_channel_mode {
+	OMAP_DMA_LCH_2D = 0,
+	OMAP_DMA_LCH_G,
+	OMAP_DMA_LCH_P,
+	OMAP_DMA_LCH_PD
+};
+
+struct omap_dma_channel_params {
+	int data_type;		/* data type 8,16,32 */
+	int elem_count;		/* number of elements in a frame */
+	int frame_count;	/* number of frames in a element */
+
+	int src_port;		/* Only on OMAP1 REVISIT: Is this needed? */
+	int src_amode;		/* constant, post increment, indexed,
+					double indexed */
+	unsigned long src_start;	/* source address : physical */
+	int src_ei;		/* source element index */
+	int src_fi;		/* source frame index */
+
+	int dst_port;		/* Only on OMAP1 REVISIT: Is this needed? */
+	int dst_amode;		/* constant, post increment, indexed,
+					double indexed */
+	unsigned long dst_start;	/* source address : physical */
+	int dst_ei;		/* source element index */
+	int dst_fi;		/* source frame index */
+
+	int trigger;		/* trigger attached if the channel is
+					synchronized */
+	int sync_mode;		/* sycn on element, frame , block or packet */
+	int src_or_dst_synch;	/* source synch(1) or destination synch(0) */
+
+	int ie;			/* interrupt enabled */
+
+	unsigned char read_prio;/* read priority */
+	unsigned char write_prio;/* write priority */
+
+#ifndef CONFIG_ARCH_OMAP1
+	enum omap_dma_burst_mode burst_mode; /* Burst mode 4/8/16 words */
+#endif
+};
+
+struct omap_dma_lch {
+	int next_lch;
+	int dev_id;
+	u16 saved_csr;
+	u16 enabled_irqs;
+	const char *dev_name;
+	void (*callback)(int lch, u16 ch_status, void *data);
+	void *data;
+	long flags;
+	/* required for Dynamic chaining */
+	int prev_linked_ch;
+	int next_linked_ch;
+	int state;
+	int chain_id;
+	int status;
+};
+
+struct omap_dma_dev_attr {
+	u32 dev_caps;
+	u16 lch_count;
+	u16 chan_count;
+	struct omap_dma_lch *chan;
+};
+
+/* System DMA platform data structure */
+struct omap_system_dma_plat_info {
+	struct omap_dma_dev_attr *dma_attr;
+	u32 errata;
+	void (*disable_irq_lch)(int lch);
+	void (*show_dma_caps)(void);
+	void (*clear_lch_regs)(int lch);
+	void (*clear_dma)(int lch);
+	void (*dma_write)(u32 val, int reg, int lch);
+	u32 (*dma_read)(int reg, int lch);
+};
+
+#ifdef CONFIG_ARCH_OMAP2PLUS
+#define dma_omap2plus()	1
+#else
+#define dma_omap2plus()	0
+#endif
+#define dma_omap1()	(!dma_omap2plus())
+#define dma_omap15xx()	((dma_omap1() && (d->dev_caps & ENABLE_1510_MODE)))
+#define dma_omap16xx()	((dma_omap1() && (d->dev_caps & ENABLE_16XX_MODE)))
+
+extern void omap_set_dma_priority(int lch, int dst_port, int priority);
+extern int omap_request_dma(int dev_id, const char *dev_name,
+			void (*callback)(int lch, u16 ch_status, void *data),
+			void *data, int *dma_ch);
+extern void omap_enable_dma_irq(int ch, u16 irq_bits);
+extern void omap_disable_dma_irq(int ch, u16 irq_bits);
+extern void omap_free_dma(int ch);
+extern void omap_start_dma(int lch);
+extern void omap_stop_dma(int lch);
+extern void omap_set_dma_transfer_params(int lch, int data_type,
+					 int elem_count, int frame_count,
+					 int sync_mode,
+					 int dma_trigger, int src_or_dst_synch);
+extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode,
+				    u32 color);
+extern void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode);
+extern void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode);
+
+extern void omap_set_dma_src_params(int lch, int src_port, int src_amode,
+				    unsigned long src_start,
+				    int src_ei, int src_fi);
+extern void omap_set_dma_src_index(int lch, int eidx, int fidx);
+extern void omap_set_dma_src_data_pack(int lch, int enable);
+extern void omap_set_dma_src_burst_mode(int lch,
+					enum omap_dma_burst_mode burst_mode);
+
+extern void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
+				     unsigned long dest_start,
+				     int dst_ei, int dst_fi);
+extern void omap_set_dma_dest_index(int lch, int eidx, int fidx);
+extern void omap_set_dma_dest_data_pack(int lch, int enable);
+extern void omap_set_dma_dest_burst_mode(int lch,
+					 enum omap_dma_burst_mode burst_mode);
+
+extern void omap_set_dma_params(int lch,
+				struct omap_dma_channel_params *params);
+
+extern void omap_dma_link_lch(int lch_head, int lch_queue);
+extern void omap_dma_unlink_lch(int lch_head, int lch_queue);
+
+extern int omap_set_dma_callback(int lch,
+			void (*callback)(int lch, u16 ch_status, void *data),
+			void *data);
+extern dma_addr_t omap_get_dma_src_pos(int lch);
+extern dma_addr_t omap_get_dma_dst_pos(int lch);
+extern void omap_clear_dma(int lch);
+extern int omap_get_dma_active_status(int lch);
+extern int omap_dma_running(void);
+extern void omap_dma_set_global_params(int arb_rate, int max_fifo_depth,
+				       int tparams);
+extern int omap_dma_set_prio_lch(int lch, unsigned char read_prio,
+				 unsigned char write_prio);
+extern void omap_set_dma_dst_endian_type(int lch, enum end_type etype);
+extern void omap_set_dma_src_endian_type(int lch, enum end_type etype);
+extern int omap_get_dma_index(int lch, int *ei, int *fi);
+
+void omap_dma_global_context_save(void);
+void omap_dma_global_context_restore(void);
+
+extern void omap_dma_disable_irq(int lch);
+
+/* Chaining APIs */
+#ifndef CONFIG_ARCH_OMAP1
+extern int omap_request_dma_chain(int dev_id, const char *dev_name,
+				  void (*callback) (int lch, u16 ch_status,
+						    void *data),
+				  int *chain_id, int no_of_chans,
+				  int chain_mode,
+				  struct omap_dma_channel_params params);
+extern int omap_free_dma_chain(int chain_id);
+extern int omap_dma_chain_a_transfer(int chain_id, int src_start,
+				     int dest_start, int elem_count,
+				     int frame_count, void *callbk_data);
+extern int omap_start_dma_chain_transfers(int chain_id);
+extern int omap_stop_dma_chain_transfers(int chain_id);
+extern int omap_get_dma_chain_index(int chain_id, int *ei, int *fi);
+extern int omap_get_dma_chain_dst_pos(int chain_id);
+extern int omap_get_dma_chain_src_pos(int chain_id);
+
+extern int omap_modify_dma_chain_params(int chain_id,
+					struct omap_dma_channel_params params);
+extern int omap_dma_chain_status(int chain_id);
+#endif
+
+#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_FB_OMAP)
+#include <mach/lcd_dma.h>
+#else
+static inline int omap_lcd_dma_running(void)
+{
+	return 0;
+}
+#endif
+
+#endif /* __ASM_ARCH_DMA_H */
diff --git a/arch/arm/plat-omap/include/plat/clkdev_omap.h b/arch/arm/plat-omap/include/plat/clkdev_omap.h
deleted file mode 100644
index 025d85a..0000000
--- a/arch/arm/plat-omap/include/plat/clkdev_omap.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * clkdev <-> OMAP integration
- *
- * Russell King <linux@arm.linux.org.uk>
- *
- */
-
-#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H
-#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H
-
-#include <linux/clkdev.h>
-
-struct omap_clk {
-	u16				cpu;
-	struct clk_lookup		lk;
-};
-
-#define CLK(dev, con, ck, cp) 		\
-	{				\
-		 .cpu = cp,		\
-		.lk = {			\
-			.dev_id = dev,	\
-			.con_id = con,	\
-			.clk = ck,	\
-		},			\
-	}
-
-/* Platform flags for the clkdev-OMAP integration code */
-#define CK_310		(1 << 0)
-#define CK_7XX		(1 << 1)	/* 7xx, 850 */
-#define CK_1510		(1 << 2)
-#define CK_16XX		(1 << 3)	/* 16xx, 17xx, 5912 */
-#define CK_242X		(1 << 4)
-#define CK_243X		(1 << 5)	/* 243x, 253x */
-#define CK_3430ES1	(1 << 6)	/* 34xxES1 only */
-#define CK_3430ES2PLUS	(1 << 7)	/* 34xxES2, ES3, non-Sitara 35xx only */
-#define CK_AM35XX	(1 << 9)	/* Sitara AM35xx */
-#define CK_36XX		(1 << 10)	/* 36xx/37xx-specific clocks */
-#define CK_443X		(1 << 11)
-#define CK_TI816X	(1 << 12)
-#define CK_446X		(1 << 13)
-#define CK_AM33XX	(1 << 14)	/* AM33xx specific clocks */
-#define CK_1710		(1 << 15)	/* 1710 extra for rate selection */
-
-
-#define CK_34XX		(CK_3430ES1 | CK_3430ES2PLUS)
-#define CK_3XXX		(CK_34XX | CK_AM35XX | CK_36XX)
-
-
-#endif
-
diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h
deleted file mode 100644
index e2e2d04..0000000
--- a/arch/arm/plat-omap/include/plat/clock.h
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * OMAP clock: data structure definitions, function prototypes, shared macros
- *
- * Copyright (C) 2004-2005, 2008-2010 Nokia Corporation
- * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
- * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ARCH_ARM_OMAP_CLOCK_H
-#define __ARCH_ARM_OMAP_CLOCK_H
-
-#include <linux/list.h>
-
-struct module;
-struct clk;
-struct clockdomain;
-
-/* Temporary, needed during the common clock framework conversion */
-#define __clk_get_name(clk)	(clk->name)
-#define __clk_get_parent(clk)	(clk->parent)
-#define __clk_get_rate(clk)	(clk->rate)
-
-/**
- * struct clkops - some clock function pointers
- * @enable: fn ptr that enables the current clock in hardware
- * @disable: fn ptr that enables the current clock in hardware
- * @find_idlest: function returning the IDLEST register for the clock's IP blk
- * @find_companion: function returning the "companion" clk reg for the clock
- * @allow_idle: fn ptr that enables autoidle for the current clock in hardware
- * @deny_idle: fn ptr that disables autoidle for the current clock in hardware
- *
- * A "companion" clk is an accompanying clock to the one being queried
- * that must be enabled for the IP module connected to the clock to
- * become accessible by the hardware.  Neither @find_idlest nor
- * @find_companion should be needed; that information is IP
- * block-specific; the hwmod code has been created to handle this, but
- * until hwmod data is ready and drivers have been converted to use PM
- * runtime calls in place of clk_enable()/clk_disable(), @find_idlest and
- * @find_companion must, unfortunately, remain.
- */
-struct clkops {
-	int			(*enable)(struct clk *);
-	void			(*disable)(struct clk *);
-	void			(*find_idlest)(struct clk *, void __iomem **,
-					       u8 *, u8 *);
-	void			(*find_companion)(struct clk *, void __iomem **,
-						  u8 *);
-	void			(*allow_idle)(struct clk *);
-	void			(*deny_idle)(struct clk *);
-};
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-
-/* struct clksel_rate.flags possibilities */
-#define RATE_IN_242X		(1 << 0)
-#define RATE_IN_243X		(1 << 1)
-#define RATE_IN_3430ES1		(1 << 2)	/* 3430ES1 rates only */
-#define RATE_IN_3430ES2PLUS	(1 << 3)	/* 3430 ES >= 2 rates only */
-#define RATE_IN_36XX		(1 << 4)
-#define RATE_IN_4430		(1 << 5)
-#define RATE_IN_TI816X		(1 << 6)
-#define RATE_IN_4460		(1 << 7)
-#define RATE_IN_AM33XX		(1 << 8)
-#define RATE_IN_TI814X		(1 << 9)
-
-#define RATE_IN_24XX		(RATE_IN_242X | RATE_IN_243X)
-#define RATE_IN_34XX		(RATE_IN_3430ES1 | RATE_IN_3430ES2PLUS)
-#define RATE_IN_3XXX		(RATE_IN_34XX | RATE_IN_36XX)
-#define RATE_IN_44XX		(RATE_IN_4430 | RATE_IN_4460)
-
-/* RATE_IN_3430ES2PLUS_36XX includes 34xx/35xx with ES >=2, and all 36xx/37xx */
-#define RATE_IN_3430ES2PLUS_36XX	(RATE_IN_3430ES2PLUS | RATE_IN_36XX)
-
-
-/**
- * struct clksel_rate - register bitfield values corresponding to clk divisors
- * @val: register bitfield value (shifted to bit 0)
- * @div: clock divisor corresponding to @val
- * @flags: (see "struct clksel_rate.flags possibilities" above)
- *
- * @val should match the value of a read from struct clk.clksel_reg
- * AND'ed with struct clk.clksel_mask, shifted right to bit 0.
- *
- * @div is the divisor that should be applied to the parent clock's rate
- * to produce the current clock's rate.
- */
-struct clksel_rate {
-	u32			val;
-	u8			div;
-	u16			flags;
-};
-
-/**
- * struct clksel - available parent clocks, and a pointer to their divisors
- * @parent: struct clk * to a possible parent clock
- * @rates: available divisors for this parent clock
- *
- * A struct clksel is always associated with one or more struct clks
- * and one or more struct clksel_rates.
- */
-struct clksel {
-	struct clk		 *parent;
-	const struct clksel_rate *rates;
-};
-
-/**
- * struct dpll_data - DPLL registers and integration data
- * @mult_div1_reg: register containing the DPLL M and N bitfields
- * @mult_mask: mask of the DPLL M bitfield in @mult_div1_reg
- * @div1_mask: mask of the DPLL N bitfield in @mult_div1_reg
- * @clk_bypass: struct clk pointer to the clock's bypass clock input
- * @clk_ref: struct clk pointer to the clock's reference clock input
- * @control_reg: register containing the DPLL mode bitfield
- * @enable_mask: mask of the DPLL mode bitfield in @control_reg
- * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate()
- * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate()
- * @max_multiplier: maximum valid non-bypass multiplier value (actual)
- * @last_rounded_n: cache of the last N result of omap2_dpll_round_rate()
- * @min_divider: minimum valid non-bypass divider value (actual)
- * @max_divider: maximum valid non-bypass divider value (actual)
- * @modes: possible values of @enable_mask
- * @autoidle_reg: register containing the DPLL autoidle mode bitfield
- * @idlest_reg: register containing the DPLL idle status bitfield
- * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg
- * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg
- * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg
- * @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg
- * @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs
- * @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs
- * @flags: DPLL type/features (see below)
- *
- * Possible values for @flags:
- * DPLL_J_TYPE: "J-type DPLL" (only some 36xx, 4xxx DPLLs)
- *
- * @freqsel_mask is only used on the OMAP34xx family and AM35xx.
- *
- * XXX Some DPLLs have multiple bypass inputs, so it's not technically
- * correct to only have one @clk_bypass pointer.
- *
- * XXX The runtime-variable fields (@last_rounded_rate, @last_rounded_m,
- * @last_rounded_n) should be separated from the runtime-fixed fields
- * and placed into a different structure, so that the runtime-fixed data
- * can be placed into read-only space.
- */
-struct dpll_data {
-	void __iomem		*mult_div1_reg;
-	u32			mult_mask;
-	u32			div1_mask;
-	struct clk		*clk_bypass;
-	struct clk		*clk_ref;
-	void __iomem		*control_reg;
-	u32			enable_mask;
-	unsigned long		last_rounded_rate;
-	u16			last_rounded_m;
-	u16			max_multiplier;
-	u8			last_rounded_n;
-	u8			min_divider;
-	u16			max_divider;
-	u8			modes;
-	void __iomem		*autoidle_reg;
-	void __iomem		*idlest_reg;
-	u32			autoidle_mask;
-	u32			freqsel_mask;
-	u32			idlest_mask;
-	u32			dco_mask;
-	u32			sddiv_mask;
-	u8			auto_recal_bit;
-	u8			recal_en_bit;
-	u8			recal_st_bit;
-	u8			flags;
-};
-
-#endif
-
-/*
- * struct clk.flags possibilities
- *
- * XXX document the rest of the clock flags here
- *
- * CLOCK_CLKOUTX2: (OMAP4 only) DPLL CLKOUT and CLKOUTX2 GATE_CTRL
- *     bits share the same register.  This flag allows the
- *     omap4_dpllmx*() code to determine which GATE_CTRL bit field
- *     should be used.  This is a temporary solution - a better approach
- *     would be to associate clock type-specific data with the clock,
- *     similar to the struct dpll_data approach.
- */
-#define ENABLE_REG_32BIT	(1 << 0)	/* Use 32-bit access */
-#define CLOCK_IDLE_CONTROL	(1 << 1)
-#define CLOCK_NO_IDLE_PARENT	(1 << 2)
-#define ENABLE_ON_INIT		(1 << 3)	/* Enable upon framework init */
-#define INVERT_ENABLE		(1 << 4)	/* 0 enables, 1 disables */
-#define CLOCK_CLKOUTX2		(1 << 5)
-
-/**
- * struct clk - OMAP struct clk
- * @node: list_head connecting this clock into the full clock list
- * @ops: struct clkops * for this clock
- * @name: the name of the clock in the hardware (used in hwmod data and debug)
- * @parent: pointer to this clock's parent struct clk
- * @children: list_head connecting to the child clks' @sibling list_heads
- * @sibling: list_head connecting this clk to its parent clk's @children
- * @rate: current clock rate
- * @enable_reg: register to write to enable the clock (see @enable_bit)
- * @recalc: fn ptr that returns the clock's current rate
- * @set_rate: fn ptr that can change the clock's current rate
- * @round_rate: fn ptr that can round the clock's current rate
- * @init: fn ptr to do clock-specific initialization
- * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
- * @usecount: number of users that have requested this clock to be enabled
- * @fixed_div: when > 0, this clock's rate is its parent's rate / @fixed_div
- * @flags: see "struct clk.flags possibilities" above
- * @clksel_reg: for clksel clks, register va containing src/divisor select
- * @clksel_mask: bitmask in @clksel_reg for the src/divisor selector
- * @clksel: for clksel clks, pointer to struct clksel for this clock
- * @dpll_data: for DPLLs, pointer to struct dpll_data for this clock
- * @clkdm_name: clockdomain name that this clock is contained in
- * @clkdm: pointer to struct clockdomain, resolved from @clkdm_name at runtime
- * @rate_offset: bitshift for rate selection bitfield (OMAP1 only)
- * @src_offset: bitshift for source selection bitfield (OMAP1 only)
- *
- * XXX @rate_offset, @src_offset should probably be removed and OMAP1
- * clock code converted to use clksel.
- *
- * XXX @usecount is poorly named.  It should be "enable_count" or
- * something similar.  "users" in the description refers to kernel
- * code (core code or drivers) that have called clk_enable() and not
- * yet called clk_disable(); the usecount of parent clocks is also
- * incremented by the clock code when clk_enable() is called on child
- * clocks and decremented by the clock code when clk_disable() is
- * called on child clocks.
- *
- * XXX @clkdm, @usecount, @children, @sibling should be marked for
- * internal use only.
- *
- * @children and @sibling are used to optimize parent-to-child clock
- * tree traversals.  (child-to-parent traversals use @parent.)
- *
- * XXX The notion of the clock's current rate probably needs to be
- * separated from the clock's target rate.
- */
-struct clk {
-	struct list_head	node;
-	const struct clkops	*ops;
-	const char		*name;
-	struct clk		*parent;
-	struct list_head	children;
-	struct list_head	sibling;	/* node for children */
-	unsigned long		rate;
-	void __iomem		*enable_reg;
-	unsigned long		(*recalc)(struct clk *);
-	int			(*set_rate)(struct clk *, unsigned long);
-	long			(*round_rate)(struct clk *, unsigned long);
-	void			(*init)(struct clk *);
-	u8			enable_bit;
-	s8			usecount;
-	u8			fixed_div;
-	u8			flags;
-#ifdef CONFIG_ARCH_OMAP2PLUS
-	void __iomem		*clksel_reg;
-	u32			clksel_mask;
-	const struct clksel	*clksel;
-	struct dpll_data	*dpll_data;
-	const char		*clkdm_name;
-	struct clockdomain	*clkdm;
-#else
-	u8			rate_offset;
-	u8			src_offset;
-#endif
-#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
-	struct dentry		*dent;	/* For visible tree hierarchy */
-#endif
-};
-
-struct clk_functions {
-	int		(*clk_enable)(struct clk *clk);
-	void		(*clk_disable)(struct clk *clk);
-	long		(*clk_round_rate)(struct clk *clk, unsigned long rate);
-	int		(*clk_set_rate)(struct clk *clk, unsigned long rate);
-	int		(*clk_set_parent)(struct clk *clk, struct clk *parent);
-	void		(*clk_allow_idle)(struct clk *clk);
-	void		(*clk_deny_idle)(struct clk *clk);
-	void		(*clk_disable_unused)(struct clk *clk);
-};
-
-extern int mpurate;
-
-extern int clk_init(struct clk_functions *custom_clocks);
-extern void clk_preinit(struct clk *clk);
-extern int clk_register(struct clk *clk);
-extern void clk_reparent(struct clk *child, struct clk *parent);
-extern void clk_unregister(struct clk *clk);
-extern void propagate_rate(struct clk *clk);
-extern void recalculate_root_clocks(void);
-extern unsigned long followparent_recalc(struct clk *clk);
-extern void clk_enable_init_clocks(void);
-unsigned long omap_fixed_divisor_recalc(struct clk *clk);
-extern struct clk *omap_clk_get_by_name(const char *name);
-extern int omap_clk_enable_autoidle_all(void);
-extern int omap_clk_disable_autoidle_all(void);
-
-extern const struct clkops clkops_null;
-
-extern struct clk dummy_ck;
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h
deleted file mode 100644
index d1cb6f5..0000000
--- a/arch/arm/plat-omap/include/plat/common.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/common.h
- *
- * Header for code common to all OMAP machines.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR 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.
- *
- * You should have received a copy of the  GNU General Public License along
- * with this program; if not, write  to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ARCH_ARM_MACH_OMAP_COMMON_H
-#define __ARCH_ARM_MACH_OMAP_COMMON_H
-
-#include <plat/i2c.h>
-#include <plat/omap_hwmod.h>
-
-extern int __init omap_init_clocksource_32k(void __iomem *vbase);
-
-extern void __init omap_check_revision(void);
-
-extern void omap_reserve(void);
-extern int omap_dss_reset(struct omap_hwmod *);
-
-void omap_sram_init(void);
-
-#endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
diff --git a/arch/arm/plat-omap/include/plat/counter-32k.h b/arch/arm/plat-omap/include/plat/counter-32k.h
new file mode 100644
index 0000000..da000d4
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/counter-32k.h
@@ -0,0 +1 @@
+int omap_init_clocksource_32k(void __iomem *vbase);
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index 67da857..b4516ab 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -1,6 +1,4 @@
 /*
- * arch/arm/plat-omap/include/mach/cpu.h
- *
  * OMAP cpu type detection
  *
  * Copyright (C) 2004, 2008 Nokia Corporation
@@ -30,470 +28,12 @@
 #ifndef __ASM_ARCH_OMAP_CPU_H
 #define __ASM_ARCH_OMAP_CPU_H
 
-#ifndef __ASSEMBLY__
-
-#include <linux/bitops.h>
-#include <plat/multi.h>
-
-/*
- * Omap device type i.e. EMU/HS/TST/GP/BAD
- */
-#define OMAP2_DEVICE_TYPE_TEST		0
-#define OMAP2_DEVICE_TYPE_EMU		1
-#define OMAP2_DEVICE_TYPE_SEC		2
-#define OMAP2_DEVICE_TYPE_GP		3
-#define OMAP2_DEVICE_TYPE_BAD		4
-
-int omap_type(void);
-
-/*
- * omap_rev bits:
- * CPU id bits	(0730, 1510, 1710, 2422...)	[31:16]
- * CPU revision	(See _REV_ defined in cpu.h)	[15:08]
- * CPU class bits (15xx, 16xx, 24xx, 34xx...)	[07:00]
- */
-unsigned int omap_rev(void);
-
-/*
- * Get the CPU revision for OMAP devices
- */
-#define GET_OMAP_REVISION()	((omap_rev() >> 8) & 0xff)
-
-/*
- * Macros to group OMAP into cpu classes.
- * These can be used in most places.
- * cpu_is_omap7xx():	True for OMAP730, OMAP850
- * cpu_is_omap15xx():	True for OMAP1510, OMAP5910 and OMAP310
- * cpu_is_omap16xx():	True for OMAP1610, OMAP5912 and OMAP1710
- * cpu_is_omap24xx():	True for OMAP2420, OMAP2422, OMAP2423, OMAP2430
- * cpu_is_omap242x():	True for OMAP2420, OMAP2422, OMAP2423
- * cpu_is_omap243x():	True for OMAP2430
- * cpu_is_omap343x():	True for OMAP3430
- * cpu_is_omap443x():	True for OMAP4430
- * cpu_is_omap446x():	True for OMAP4460
- * cpu_is_omap447x():	True for OMAP4470
- * soc_is_omap543x():	True for OMAP5430, OMAP5432
- */
-#define GET_OMAP_CLASS	(omap_rev() & 0xff)
-
-#define IS_OMAP_CLASS(class, id)			\
-static inline int is_omap ##class (void)		\
-{							\
-	return (GET_OMAP_CLASS == (id)) ? 1 : 0;	\
-}
-
-#define GET_AM_CLASS	((omap_rev() >> 24) & 0xff)
-
-#define IS_AM_CLASS(class, id)				\
-static inline int is_am ##class (void)			\
-{							\
-	return (GET_AM_CLASS == (id)) ? 1 : 0;		\
-}
-
-#define GET_TI_CLASS	((omap_rev() >> 24) & 0xff)
-
-#define IS_TI_CLASS(class, id)			\
-static inline int is_ti ##class (void)		\
-{							\
-	return (GET_TI_CLASS == (id)) ? 1 : 0;	\
-}
-
-#define GET_OMAP_SUBCLASS	((omap_rev() >> 20) & 0x0fff)
-
-#define IS_OMAP_SUBCLASS(subclass, id)			\
-static inline int is_omap ##subclass (void)		\
-{							\
-	return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;	\
-}
-
-#define IS_TI_SUBCLASS(subclass, id)			\
-static inline int is_ti ##subclass (void)		\
-{							\
-	return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;	\
-}
-
-#define IS_AM_SUBCLASS(subclass, id)			\
-static inline int is_am ##subclass (void)		\
-{							\
-	return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;	\
-}
-
-IS_OMAP_CLASS(7xx, 0x07)
-IS_OMAP_CLASS(15xx, 0x15)
-IS_OMAP_CLASS(16xx, 0x16)
-IS_OMAP_CLASS(24xx, 0x24)
-IS_OMAP_CLASS(34xx, 0x34)
-IS_OMAP_CLASS(44xx, 0x44)
-IS_AM_CLASS(35xx, 0x35)
-IS_OMAP_CLASS(54xx, 0x54)
-IS_AM_CLASS(33xx, 0x33)
-
-IS_TI_CLASS(81xx, 0x81)
-
-IS_OMAP_SUBCLASS(242x, 0x242)
-IS_OMAP_SUBCLASS(243x, 0x243)
-IS_OMAP_SUBCLASS(343x, 0x343)
-IS_OMAP_SUBCLASS(363x, 0x363)
-IS_OMAP_SUBCLASS(443x, 0x443)
-IS_OMAP_SUBCLASS(446x, 0x446)
-IS_OMAP_SUBCLASS(447x, 0x447)
-IS_OMAP_SUBCLASS(543x, 0x543)
-
-IS_TI_SUBCLASS(816x, 0x816)
-IS_TI_SUBCLASS(814x, 0x814)
-IS_AM_SUBCLASS(335x, 0x335)
-
-#define cpu_is_omap7xx()		0
-#define cpu_is_omap15xx()		0
-#define cpu_is_omap16xx()		0
-#define cpu_is_omap24xx()		0
-#define cpu_is_omap242x()		0
-#define cpu_is_omap243x()		0
-#define cpu_is_omap34xx()		0
-#define cpu_is_omap343x()		0
-#define cpu_is_ti81xx()			0
-#define cpu_is_ti816x()			0
-#define cpu_is_ti814x()			0
-#define soc_is_am35xx()			0
-#define soc_is_am33xx()			0
-#define soc_is_am335x()			0
-#define cpu_is_omap44xx()		0
-#define cpu_is_omap443x()		0
-#define cpu_is_omap446x()		0
-#define cpu_is_omap447x()		0
-#define soc_is_omap54xx()		0
-#define soc_is_omap543x()		0
-
-#if defined(MULTI_OMAP1)
-# if defined(CONFIG_ARCH_OMAP730)
-#  undef  cpu_is_omap7xx
-#  define cpu_is_omap7xx()		is_omap7xx()
-# endif
-# if defined(CONFIG_ARCH_OMAP850)
-#  undef  cpu_is_omap7xx
-#  define cpu_is_omap7xx()		is_omap7xx()
-# endif
-# if defined(CONFIG_ARCH_OMAP15XX)
-#  undef  cpu_is_omap15xx
-#  define cpu_is_omap15xx()		is_omap15xx()
-# endif
-# if defined(CONFIG_ARCH_OMAP16XX)
-#  undef  cpu_is_omap16xx
-#  define cpu_is_omap16xx()		is_omap16xx()
-# endif
-#else
-# if defined(CONFIG_ARCH_OMAP730)
-#  undef  cpu_is_omap7xx
-#  define cpu_is_omap7xx()		1
-# endif
-# if defined(CONFIG_ARCH_OMAP850)
-#  undef  cpu_is_omap7xx
-#  define cpu_is_omap7xx()		1
-# endif
-# if defined(CONFIG_ARCH_OMAP15XX)
-#  undef  cpu_is_omap15xx
-#  define cpu_is_omap15xx()		1
-# endif
-# if defined(CONFIG_ARCH_OMAP16XX)
-#  undef  cpu_is_omap16xx
-#  define cpu_is_omap16xx()		1
-# endif
-#endif
-
-#if defined(MULTI_OMAP2)
-# if defined(CONFIG_ARCH_OMAP2)
-#  undef  cpu_is_omap24xx
-#  define cpu_is_omap24xx()		is_omap24xx()
-# endif
-# if defined (CONFIG_SOC_OMAP2420)
-#  undef  cpu_is_omap242x
-#  define cpu_is_omap242x()		is_omap242x()
-# endif
-# if defined (CONFIG_SOC_OMAP2430)
-#  undef  cpu_is_omap243x
-#  define cpu_is_omap243x()		is_omap243x()
-# endif
-# if defined(CONFIG_ARCH_OMAP3)
-#  undef  cpu_is_omap34xx
-#  undef  cpu_is_omap343x
-#  define cpu_is_omap34xx()		is_omap34xx()
-#  define cpu_is_omap343x()		is_omap343x()
-# endif
-#else
-# if defined(CONFIG_ARCH_OMAP2)
-#  undef  cpu_is_omap24xx
-#  define cpu_is_omap24xx()		1
-# endif
-# if defined(CONFIG_SOC_OMAP2420)
-#  undef  cpu_is_omap242x
-#  define cpu_is_omap242x()		1
-# endif
-# if defined(CONFIG_SOC_OMAP2430)
-#  undef  cpu_is_omap243x
-#  define cpu_is_omap243x()		1
-# endif
-# if defined(CONFIG_ARCH_OMAP3)
-#  undef  cpu_is_omap34xx
-#  define cpu_is_omap34xx()		1
-# endif
-# if defined(CONFIG_SOC_OMAP3430)
-#  undef  cpu_is_omap343x
-#  define cpu_is_omap343x()		1
-# endif
-#endif
-
-/*
- * Macros to detect individual cpu types.
- * These are only rarely needed.
- * cpu_is_omap310():	True for OMAP310
- * cpu_is_omap1510():	True for OMAP1510
- * cpu_is_omap1610():	True for OMAP1610
- * cpu_is_omap1611():	True for OMAP1611
- * cpu_is_omap5912():	True for OMAP5912
- * cpu_is_omap1621():	True for OMAP1621
- * cpu_is_omap1710():	True for OMAP1710
- * cpu_is_omap2420():	True for OMAP2420
- * cpu_is_omap2422():	True for OMAP2422
- * cpu_is_omap2423():	True for OMAP2423
- * cpu_is_omap2430():	True for OMAP2430
- * cpu_is_omap3430():	True for OMAP3430
- */
-#define GET_OMAP_TYPE	((omap_rev() >> 16) & 0xffff)
-
-#define IS_OMAP_TYPE(type, id)				\
-static inline int is_omap ##type (void)			\
-{							\
-	return (GET_OMAP_TYPE == (id)) ? 1 : 0;		\
-}
-
-IS_OMAP_TYPE(310, 0x0310)
-IS_OMAP_TYPE(1510, 0x1510)
-IS_OMAP_TYPE(1610, 0x1610)
-IS_OMAP_TYPE(1611, 0x1611)
-IS_OMAP_TYPE(5912, 0x1611)
-IS_OMAP_TYPE(1621, 0x1621)
-IS_OMAP_TYPE(1710, 0x1710)
-IS_OMAP_TYPE(2420, 0x2420)
-IS_OMAP_TYPE(2422, 0x2422)
-IS_OMAP_TYPE(2423, 0x2423)
-IS_OMAP_TYPE(2430, 0x2430)
-IS_OMAP_TYPE(3430, 0x3430)
-
-#define cpu_is_omap310()		0
-#define cpu_is_omap1510()		0
-#define cpu_is_omap1610()		0
-#define cpu_is_omap5912()		0
-#define cpu_is_omap1611()		0
-#define cpu_is_omap1621()		0
-#define cpu_is_omap1710()		0
-#define cpu_is_omap2420()		0
-#define cpu_is_omap2422()		0
-#define cpu_is_omap2423()		0
-#define cpu_is_omap2430()		0
-#define cpu_is_omap3430()		0
-#define cpu_is_omap3630()		0
-#define soc_is_omap5430()		0
-
-/*
- * Whether we have MULTI_OMAP1 or not, we still need to distinguish
- * between 310 vs. 1510 and 1611B/5912 vs. 1710.
- */
-
-#if defined(CONFIG_ARCH_OMAP15XX)
-# undef  cpu_is_omap310
-# undef  cpu_is_omap1510
-# define cpu_is_omap310()		is_omap310()
-# define cpu_is_omap1510()		is_omap1510()
-#endif
-
-#if defined(CONFIG_ARCH_OMAP16XX)
-# undef  cpu_is_omap1610
-# undef  cpu_is_omap1611
-# undef  cpu_is_omap5912
-# undef  cpu_is_omap1621
-# undef  cpu_is_omap1710
-# define cpu_is_omap1610()		is_omap1610()
-# define cpu_is_omap1611()		is_omap1611()
-# define cpu_is_omap5912()		is_omap5912()
-# define cpu_is_omap1621()		is_omap1621()
-# define cpu_is_omap1710()		is_omap1710()
-#endif
-
-#if defined(CONFIG_ARCH_OMAP2)
-# undef  cpu_is_omap2420
-# undef  cpu_is_omap2422
-# undef  cpu_is_omap2423
-# undef  cpu_is_omap2430
-# define cpu_is_omap2420()		is_omap2420()
-# define cpu_is_omap2422()		is_omap2422()
-# define cpu_is_omap2423()		is_omap2423()
-# define cpu_is_omap2430()		is_omap2430()
-#endif
-
-#if defined(CONFIG_ARCH_OMAP3)
-# undef cpu_is_omap3430
-# undef cpu_is_ti81xx
-# undef cpu_is_ti816x
-# undef cpu_is_ti814x
-# undef soc_is_am35xx
-# define cpu_is_omap3430()		is_omap3430()
-# undef cpu_is_omap3630
-# define cpu_is_omap3630()		is_omap363x()
-# define cpu_is_ti81xx()		is_ti81xx()
-# define cpu_is_ti816x()		is_ti816x()
-# define cpu_is_ti814x()		is_ti814x()
-# define soc_is_am35xx()		is_am35xx()
+#ifdef CONFIG_ARCH_OMAP1
+#include <mach/soc.h>
 #endif
 
-# if defined(CONFIG_SOC_AM33XX)
-# undef soc_is_am33xx
-# undef soc_is_am335x
-# define soc_is_am33xx()		is_am33xx()
-# define soc_is_am335x()		is_am335x()
+#ifdef CONFIG_ARCH_OMAP2PLUS
+#include "../../mach-omap2/soc.h"
 #endif
 
-# if defined(CONFIG_ARCH_OMAP4)
-# undef cpu_is_omap44xx
-# undef cpu_is_omap443x
-# undef cpu_is_omap446x
-# undef cpu_is_omap447x
-# define cpu_is_omap44xx()		is_omap44xx()
-# define cpu_is_omap443x()		is_omap443x()
-# define cpu_is_omap446x()		is_omap446x()
-# define cpu_is_omap447x()		is_omap447x()
-# endif
-
-# if defined(CONFIG_SOC_OMAP5)
-# undef soc_is_omap54xx
-# undef soc_is_omap543x
-# define soc_is_omap54xx()		is_omap54xx()
-# define soc_is_omap543x()		is_omap543x()
-#endif
-
-/* Macros to detect if we have OMAP1 or OMAP2 */
-#define cpu_class_is_omap1()	(cpu_is_omap7xx() || cpu_is_omap15xx() || \
-				cpu_is_omap16xx())
-#define cpu_class_is_omap2()	(cpu_is_omap24xx() || cpu_is_omap34xx() || \
-				cpu_is_omap44xx() || soc_is_omap54xx() || \
-				soc_is_am33xx())
-
-/* Various silicon revisions for omap2 */
-#define OMAP242X_CLASS		0x24200024
-#define OMAP2420_REV_ES1_0	OMAP242X_CLASS
-#define OMAP2420_REV_ES2_0	(OMAP242X_CLASS | (0x1 << 8))
-
-#define OMAP243X_CLASS		0x24300024
-#define OMAP2430_REV_ES1_0	OMAP243X_CLASS
-
-#define OMAP343X_CLASS		0x34300034
-#define OMAP3430_REV_ES1_0	OMAP343X_CLASS
-#define OMAP3430_REV_ES2_0	(OMAP343X_CLASS | (0x1 << 8))
-#define OMAP3430_REV_ES2_1	(OMAP343X_CLASS | (0x2 << 8))
-#define OMAP3430_REV_ES3_0	(OMAP343X_CLASS | (0x3 << 8))
-#define OMAP3430_REV_ES3_1	(OMAP343X_CLASS | (0x4 << 8))
-#define OMAP3430_REV_ES3_1_2	(OMAP343X_CLASS | (0x5 << 8))
-
-#define OMAP363X_CLASS		0x36300034
-#define OMAP3630_REV_ES1_0	OMAP363X_CLASS
-#define OMAP3630_REV_ES1_1	(OMAP363X_CLASS | (0x1 << 8))
-#define OMAP3630_REV_ES1_2	(OMAP363X_CLASS | (0x2 << 8))
-
-#define TI816X_CLASS		0x81600034
-#define TI8168_REV_ES1_0	TI816X_CLASS
-#define TI8168_REV_ES1_1	(TI816X_CLASS | (0x1 << 8))
-
-#define TI814X_CLASS		0x81400034
-#define TI8148_REV_ES1_0	TI814X_CLASS
-#define TI8148_REV_ES2_0	(TI814X_CLASS | (0x1 << 8))
-#define TI8148_REV_ES2_1	(TI814X_CLASS | (0x2 << 8))
-
-#define AM35XX_CLASS		0x35170034
-#define AM35XX_REV_ES1_0	AM35XX_CLASS
-#define AM35XX_REV_ES1_1	(AM35XX_CLASS | (0x1 << 8))
-
-#define AM335X_CLASS		0x33500033
-#define AM335X_REV_ES1_0	AM335X_CLASS
-
-#define OMAP443X_CLASS		0x44300044
-#define OMAP4430_REV_ES1_0	(OMAP443X_CLASS | (0x10 << 8))
-#define OMAP4430_REV_ES2_0	(OMAP443X_CLASS | (0x20 << 8))
-#define OMAP4430_REV_ES2_1	(OMAP443X_CLASS | (0x21 << 8))
-#define OMAP4430_REV_ES2_2	(OMAP443X_CLASS | (0x22 << 8))
-#define OMAP4430_REV_ES2_3	(OMAP443X_CLASS | (0x23 << 8))
-
-#define OMAP446X_CLASS		0x44600044
-#define OMAP4460_REV_ES1_0	(OMAP446X_CLASS | (0x10 << 8))
-#define OMAP4460_REV_ES1_1	(OMAP446X_CLASS | (0x11 << 8))
-
-#define OMAP447X_CLASS		0x44700044
-#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 OMAP5432_REV_ES1_0	(OMAP54XX_CLASS | (0x32 << 16) | (0x10 << 8))
-
-void omap2xxx_check_revision(void);
-void omap3xxx_check_revision(void);
-void omap4xxx_check_revision(void);
-void omap5xxx_check_revision(void);
-void omap3xxx_check_features(void);
-void ti81xx_check_features(void);
-void omap4xxx_check_features(void);
-
-/*
- * Runtime detection of OMAP3 features
- *
- * OMAP3_HAS_IO_CHAIN_CTRL: Some later members of the OMAP3 chip
- *    family have OS-level control over the I/O chain clock.  This is
- *    to avoid a window during which wakeups could potentially be lost
- *    during powerdomain transitions.  If this bit is set, it
- *    indicates that the chip does support OS-level control of this
- *    feature.
- */
-extern u32 omap_features;
-
-#define OMAP3_HAS_L2CACHE		BIT(0)
-#define OMAP3_HAS_IVA			BIT(1)
-#define OMAP3_HAS_SGX			BIT(2)
-#define OMAP3_HAS_NEON			BIT(3)
-#define OMAP3_HAS_ISP			BIT(4)
-#define OMAP3_HAS_192MHZ_CLK		BIT(5)
-#define OMAP3_HAS_IO_WAKEUP		BIT(6)
-#define OMAP3_HAS_SDRC			BIT(7)
-#define OMAP3_HAS_IO_CHAIN_CTRL		BIT(8)
-#define OMAP4_HAS_MPU_1GHZ		BIT(9)
-#define OMAP4_HAS_MPU_1_2GHZ		BIT(10)
-#define OMAP4_HAS_MPU_1_5GHZ		BIT(11)
-
-
-#define OMAP3_HAS_FEATURE(feat,flag)			\
-static inline unsigned int omap3_has_ ##feat(void)	\
-{							\
-	return omap_features & OMAP3_HAS_ ##flag;	\
-}							\
-
-OMAP3_HAS_FEATURE(l2cache, L2CACHE)
-OMAP3_HAS_FEATURE(sgx, SGX)
-OMAP3_HAS_FEATURE(iva, IVA)
-OMAP3_HAS_FEATURE(neon, NEON)
-OMAP3_HAS_FEATURE(isp, ISP)
-OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
-OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
-OMAP3_HAS_FEATURE(sdrc, SDRC)
-OMAP3_HAS_FEATURE(io_chain_ctrl, IO_CHAIN_CTRL)
-
-/*
- * Runtime detection of OMAP4 features
- */
-#define OMAP4_HAS_FEATURE(feat, flag)			\
-static inline unsigned int omap4_has_ ##feat(void)	\
-{							\
-	return omap_features & OMAP4_HAS_ ##flag;	\
-}							\
-
-OMAP4_HAS_FEATURE(mpu_1ghz, MPU_1GHZ)
-OMAP4_HAS_FEATURE(mpu_1_2ghz, MPU_1_2GHZ)
-OMAP4_HAS_FEATURE(mpu_1_5ghz, MPU_1_5GHZ)
-
-#endif	/* __ASSEMBLY__ */
 #endif
diff --git a/arch/arm/plat-omap/include/plat/debug-devices.h b/arch/arm/plat-omap/include/plat/debug-devices.h
new file mode 100644
index 0000000..8fc4287
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/debug-devices.h
@@ -0,0 +1,2 @@
+/* for TI reference platforms sharing the same debug card */
+extern int debug_card_init(u32 addr, unsigned gpio);
diff --git a/arch/arm/plat-omap/include/plat/dma-44xx.h b/arch/arm/plat-omap/include/plat/dma-44xx.h
deleted file mode 100644
index 1f767cb..0000000
--- a/arch/arm/plat-omap/include/plat/dma-44xx.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * OMAP4 SDMA channel definitions
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- * Copyright (C) 2009-2010 Nokia Corporation
- *
- * Santosh Shilimkar (santosh.shilimkar@ti.com)
- * Benoit Cousson (b-cousson@ti.com)
- * Paul Walmsley (paul@pwsan.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ARCH_ARM_MACH_OMAP2_OMAP44XX_DMA_H
-#define __ARCH_ARM_MACH_OMAP2_OMAP44XX_DMA_H
-
-#define OMAP44XX_DMA_SYS_REQ0			2
-#define OMAP44XX_DMA_SYS_REQ1			3
-#define OMAP44XX_DMA_GPMC			4
-#define OMAP44XX_DMA_DSS_DISPC_REQ		6
-#define OMAP44XX_DMA_SYS_REQ2			7
-#define OMAP44XX_DMA_MCASP1_AXEVT		8
-#define OMAP44XX_DMA_ISS_REQ1			9
-#define OMAP44XX_DMA_ISS_REQ2			10
-#define OMAP44XX_DMA_MCASP1_AREVT		11
-#define OMAP44XX_DMA_ISS_REQ3			12
-#define OMAP44XX_DMA_ISS_REQ4			13
-#define OMAP44XX_DMA_DSS_RFBI_REQ		14
-#define OMAP44XX_DMA_SPI3_TX0			15
-#define OMAP44XX_DMA_SPI3_RX0			16
-#define OMAP44XX_DMA_MCBSP2_TX			17
-#define OMAP44XX_DMA_MCBSP2_RX			18
-#define OMAP44XX_DMA_MCBSP3_TX			19
-#define OMAP44XX_DMA_MCBSP3_RX			20
-#define OMAP44XX_DMA_C2C_SSCM_GPO0		21
-#define OMAP44XX_DMA_C2C_SSCM_GPO1		22
-#define OMAP44XX_DMA_SPI3_TX1			23
-#define OMAP44XX_DMA_SPI3_RX1			24
-#define OMAP44XX_DMA_I2C3_TX			25
-#define OMAP44XX_DMA_I2C3_RX			26
-#define OMAP44XX_DMA_I2C1_TX			27
-#define OMAP44XX_DMA_I2C1_RX			28
-#define OMAP44XX_DMA_I2C2_TX			29
-#define OMAP44XX_DMA_I2C2_RX			30
-#define OMAP44XX_DMA_MCBSP4_TX			31
-#define OMAP44XX_DMA_MCBSP4_RX			32
-#define OMAP44XX_DMA_MCBSP1_TX			33
-#define OMAP44XX_DMA_MCBSP1_RX			34
-#define OMAP44XX_DMA_SPI1_TX0			35
-#define OMAP44XX_DMA_SPI1_RX0			36
-#define OMAP44XX_DMA_SPI1_TX1			37
-#define OMAP44XX_DMA_SPI1_RX1			38
-#define OMAP44XX_DMA_SPI1_TX2			39
-#define OMAP44XX_DMA_SPI1_RX2			40
-#define OMAP44XX_DMA_SPI1_TX3			41
-#define OMAP44XX_DMA_SPI1_RX3			42
-#define OMAP44XX_DMA_SPI2_TX0			43
-#define OMAP44XX_DMA_SPI2_RX0			44
-#define OMAP44XX_DMA_SPI2_TX1			45
-#define OMAP44XX_DMA_SPI2_RX1			46
-#define OMAP44XX_DMA_MMC2_TX			47
-#define OMAP44XX_DMA_MMC2_RX			48
-#define OMAP44XX_DMA_UART1_TX			49
-#define OMAP44XX_DMA_UART1_RX			50
-#define OMAP44XX_DMA_UART2_TX			51
-#define OMAP44XX_DMA_UART2_RX			52
-#define OMAP44XX_DMA_UART3_TX			53
-#define OMAP44XX_DMA_UART3_RX			54
-#define OMAP44XX_DMA_UART4_TX			55
-#define OMAP44XX_DMA_UART4_RX			56
-#define OMAP44XX_DMA_MMC4_TX			57
-#define OMAP44XX_DMA_MMC4_RX			58
-#define OMAP44XX_DMA_MMC5_TX			59
-#define OMAP44XX_DMA_MMC5_RX			60
-#define OMAP44XX_DMA_MMC1_TX			61
-#define OMAP44XX_DMA_MMC1_RX			62
-#define OMAP44XX_DMA_SYS_REQ3			64
-#define OMAP44XX_DMA_MCPDM_UP			65
-#define OMAP44XX_DMA_MCPDM_DL			66
-#define OMAP44XX_DMA_DMIC_REQ			67
-#define OMAP44XX_DMA_C2C_SSCM_GPO2		68
-#define OMAP44XX_DMA_C2C_SSCM_GPO3		69
-#define OMAP44XX_DMA_SPI4_TX0			70
-#define OMAP44XX_DMA_SPI4_RX0			71
-#define OMAP44XX_DMA_DSS_DSI1_REQ0		72
-#define OMAP44XX_DMA_DSS_DSI1_REQ1		73
-#define OMAP44XX_DMA_DSS_DSI1_REQ2		74
-#define OMAP44XX_DMA_DSS_DSI1_REQ3		75
-#define OMAP44XX_DMA_DSS_HDMI_REQ		76
-#define OMAP44XX_DMA_MMC3_TX			77
-#define OMAP44XX_DMA_MMC3_RX			78
-#define OMAP44XX_DMA_USIM_TX			79
-#define OMAP44XX_DMA_USIM_RX			80
-#define OMAP44XX_DMA_DSS_DSI2_REQ0		81
-#define OMAP44XX_DMA_DSS_DSI2_REQ1		82
-#define OMAP44XX_DMA_DSS_DSI2_REQ2		83
-#define OMAP44XX_DMA_DSS_DSI2_REQ3		84
-#define OMAP44XX_DMA_SLIMBUS1_TX0		85
-#define OMAP44XX_DMA_SLIMBUS1_TX1		86
-#define OMAP44XX_DMA_SLIMBUS1_TX2		87
-#define OMAP44XX_DMA_SLIMBUS1_TX3		88
-#define OMAP44XX_DMA_SLIMBUS1_RX0		89
-#define OMAP44XX_DMA_SLIMBUS1_RX1		90
-#define OMAP44XX_DMA_SLIMBUS1_RX2		91
-#define OMAP44XX_DMA_SLIMBUS1_RX3		92
-#define OMAP44XX_DMA_SLIMBUS2_TX0		93
-#define OMAP44XX_DMA_SLIMBUS2_TX1		94
-#define OMAP44XX_DMA_SLIMBUS2_TX2		95
-#define OMAP44XX_DMA_SLIMBUS2_TX3		96
-#define OMAP44XX_DMA_SLIMBUS2_RX0		97
-#define OMAP44XX_DMA_SLIMBUS2_RX1		98
-#define OMAP44XX_DMA_SLIMBUS2_RX2		99
-#define OMAP44XX_DMA_SLIMBUS2_RX3		100
-#define OMAP44XX_DMA_ABE_REQ_0			101
-#define OMAP44XX_DMA_ABE_REQ_1			102
-#define OMAP44XX_DMA_ABE_REQ_2			103
-#define OMAP44XX_DMA_ABE_REQ_3			104
-#define OMAP44XX_DMA_ABE_REQ_4			105
-#define OMAP44XX_DMA_ABE_REQ_5			106
-#define OMAP44XX_DMA_ABE_REQ_6			107
-#define OMAP44XX_DMA_ABE_REQ_7			108
-#define OMAP44XX_DMA_AES1_P_CTX_IN_REQ		109
-#define OMAP44XX_DMA_AES1_P_DATA_IN_REQ		110
-#define OMAP44XX_DMA_AES1_P_DATA_OUT_REQ	111
-#define OMAP44XX_DMA_AES2_P_CTX_IN_REQ		112
-#define OMAP44XX_DMA_AES2_P_DATA_IN_REQ		113
-#define OMAP44XX_DMA_AES2_P_DATA_OUT_REQ	114
-#define OMAP44XX_DMA_DES_P_CTX_IN_REQ		115
-#define OMAP44XX_DMA_DES_P_DATA_IN_REQ		116
-#define OMAP44XX_DMA_DES_P_DATA_OUT_REQ		117
-#define OMAP44XX_DMA_SHA2_CTXIN_P		118
-#define OMAP44XX_DMA_SHA2_DIN_P			119
-#define OMAP44XX_DMA_SHA2_CTXOUT_P		120
-#define OMAP44XX_DMA_AES1_P_CONTEXT_OUT_REQ	121
-#define OMAP44XX_DMA_AES2_P_CONTEXT_OUT_REQ	122
-#define OMAP44XX_DMA_I2C4_TX			124
-#define OMAP44XX_DMA_I2C4_RX			125
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
deleted file mode 100644
index 0a87b05..0000000
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ /dev/null
@@ -1,546 +0,0 @@
-/*
- *  arch/arm/plat-omap/include/mach/dma.h
- *
- *  Copyright (C) 2003 Nokia Corporation
- *  Author: Juha Yrjölä <juha.yrjola@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You 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_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#include <linux/platform_device.h>
-
-/*
- * TODO: These dma channel defines should go away once all
- * the omap drivers hwmod adapted.
- */
-
-/* Move omap4 specific defines to dma-44xx.h */
-#include "dma-44xx.h"
-
-#define INT_DMA_LCD			25
-
-/* DMA channels for omap1 */
-#define OMAP_DMA_NO_DEVICE		0
-#define OMAP_DMA_MCSI1_TX		1
-#define OMAP_DMA_MCSI1_RX		2
-#define OMAP_DMA_I2C_RX			3
-#define OMAP_DMA_I2C_TX			4
-#define OMAP_DMA_EXT_NDMA_REQ		5
-#define OMAP_DMA_EXT_NDMA_REQ2		6
-#define OMAP_DMA_UWIRE_TX		7
-#define OMAP_DMA_MCBSP1_TX		8
-#define OMAP_DMA_MCBSP1_RX		9
-#define OMAP_DMA_MCBSP3_TX		10
-#define OMAP_DMA_MCBSP3_RX		11
-#define OMAP_DMA_UART1_TX		12
-#define OMAP_DMA_UART1_RX		13
-#define OMAP_DMA_UART2_TX		14
-#define OMAP_DMA_UART2_RX		15
-#define OMAP_DMA_MCBSP2_TX		16
-#define OMAP_DMA_MCBSP2_RX		17
-#define OMAP_DMA_UART3_TX		18
-#define OMAP_DMA_UART3_RX		19
-#define OMAP_DMA_CAMERA_IF_RX		20
-#define OMAP_DMA_MMC_TX			21
-#define OMAP_DMA_MMC_RX			22
-#define OMAP_DMA_NAND			23
-#define OMAP_DMA_IRQ_LCD_LINE		24
-#define OMAP_DMA_MEMORY_STICK		25
-#define OMAP_DMA_USB_W2FC_RX0		26
-#define OMAP_DMA_USB_W2FC_RX1		27
-#define OMAP_DMA_USB_W2FC_RX2		28
-#define OMAP_DMA_USB_W2FC_TX0		29
-#define OMAP_DMA_USB_W2FC_TX1		30
-#define OMAP_DMA_USB_W2FC_TX2		31
-
-/* These are only for 1610 */
-#define OMAP_DMA_CRYPTO_DES_IN		32
-#define OMAP_DMA_SPI_TX			33
-#define OMAP_DMA_SPI_RX			34
-#define OMAP_DMA_CRYPTO_HASH		35
-#define OMAP_DMA_CCP_ATTN		36
-#define OMAP_DMA_CCP_FIFO_NOT_EMPTY	37
-#define OMAP_DMA_CMT_APE_TX_CHAN_0	38
-#define OMAP_DMA_CMT_APE_RV_CHAN_0	39
-#define OMAP_DMA_CMT_APE_TX_CHAN_1	40
-#define OMAP_DMA_CMT_APE_RV_CHAN_1	41
-#define OMAP_DMA_CMT_APE_TX_CHAN_2	42
-#define OMAP_DMA_CMT_APE_RV_CHAN_2	43
-#define OMAP_DMA_CMT_APE_TX_CHAN_3	44
-#define OMAP_DMA_CMT_APE_RV_CHAN_3	45
-#define OMAP_DMA_CMT_APE_TX_CHAN_4	46
-#define OMAP_DMA_CMT_APE_RV_CHAN_4	47
-#define OMAP_DMA_CMT_APE_TX_CHAN_5	48
-#define OMAP_DMA_CMT_APE_RV_CHAN_5	49
-#define OMAP_DMA_CMT_APE_TX_CHAN_6	50
-#define OMAP_DMA_CMT_APE_RV_CHAN_6	51
-#define OMAP_DMA_CMT_APE_TX_CHAN_7	52
-#define OMAP_DMA_CMT_APE_RV_CHAN_7	53
-#define OMAP_DMA_MMC2_TX		54
-#define OMAP_DMA_MMC2_RX		55
-#define OMAP_DMA_CRYPTO_DES_OUT		56
-
-/* DMA channels for 24xx */
-#define OMAP24XX_DMA_NO_DEVICE		0
-#define OMAP24XX_DMA_XTI_DMA		1	/* S_DMA_0 */
-#define OMAP24XX_DMA_EXT_DMAREQ0	2	/* S_DMA_1 */
-#define OMAP24XX_DMA_EXT_DMAREQ1	3	/* S_DMA_2 */
-#define OMAP24XX_DMA_GPMC		4	/* S_DMA_3 */
-#define OMAP24XX_DMA_GFX		5	/* S_DMA_4 */
-#define OMAP24XX_DMA_DSS		6	/* S_DMA_5 */
-#define OMAP242X_DMA_VLYNQ_TX		7	/* S_DMA_6 */
-#define OMAP24XX_DMA_EXT_DMAREQ2	7	/* S_DMA_6 */
-#define OMAP24XX_DMA_CWT		8	/* S_DMA_7 */
-#define OMAP24XX_DMA_AES_TX		9	/* S_DMA_8 */
-#define OMAP24XX_DMA_AES_RX		10	/* S_DMA_9 */
-#define OMAP24XX_DMA_DES_TX		11	/* S_DMA_10 */
-#define OMAP24XX_DMA_DES_RX		12	/* S_DMA_11 */
-#define OMAP24XX_DMA_SHA1MD5_RX		13	/* S_DMA_12 */
-#define OMAP34XX_DMA_SHA2MD5_RX		13	/* S_DMA_12 */
-#define OMAP242X_DMA_EXT_DMAREQ2	14	/* S_DMA_13 */
-#define OMAP242X_DMA_EXT_DMAREQ3	15	/* S_DMA_14 */
-#define OMAP242X_DMA_EXT_DMAREQ4	16	/* S_DMA_15 */
-#define OMAP242X_DMA_EAC_AC_RD		17	/* S_DMA_16 */
-#define OMAP242X_DMA_EAC_AC_WR		18	/* S_DMA_17 */
-#define OMAP242X_DMA_EAC_MD_UL_RD	19	/* S_DMA_18 */
-#define OMAP242X_DMA_EAC_MD_UL_WR	20	/* S_DMA_19 */
-#define OMAP242X_DMA_EAC_MD_DL_RD	21	/* S_DMA_20 */
-#define OMAP242X_DMA_EAC_MD_DL_WR	22	/* S_DMA_21 */
-#define OMAP242X_DMA_EAC_BT_UL_RD	23	/* S_DMA_22 */
-#define OMAP242X_DMA_EAC_BT_UL_WR	24	/* S_DMA_23 */
-#define OMAP242X_DMA_EAC_BT_DL_RD	25	/* S_DMA_24 */
-#define OMAP242X_DMA_EAC_BT_DL_WR	26	/* S_DMA_25 */
-#define OMAP243X_DMA_EXT_DMAREQ3	14	/* S_DMA_13 */
-#define OMAP24XX_DMA_SPI3_TX0		15	/* S_DMA_14 */
-#define OMAP24XX_DMA_SPI3_RX0		16	/* S_DMA_15 */
-#define OMAP24XX_DMA_MCBSP3_TX		17	/* S_DMA_16 */
-#define OMAP24XX_DMA_MCBSP3_RX		18	/* S_DMA_17 */
-#define OMAP24XX_DMA_MCBSP4_TX		19	/* S_DMA_18 */
-#define OMAP24XX_DMA_MCBSP4_RX		20	/* S_DMA_19 */
-#define OMAP24XX_DMA_MCBSP5_TX		21	/* S_DMA_20 */
-#define OMAP24XX_DMA_MCBSP5_RX		22	/* S_DMA_21 */
-#define OMAP24XX_DMA_SPI3_TX1		23	/* S_DMA_22 */
-#define OMAP24XX_DMA_SPI3_RX1		24	/* S_DMA_23 */
-#define OMAP243X_DMA_EXT_DMAREQ4	25	/* S_DMA_24 */
-#define OMAP243X_DMA_EXT_DMAREQ5	26	/* S_DMA_25 */
-#define OMAP34XX_DMA_I2C3_TX		25	/* S_DMA_24 */
-#define OMAP34XX_DMA_I2C3_RX		26	/* S_DMA_25 */
-#define OMAP24XX_DMA_I2C1_TX		27	/* S_DMA_26 */
-#define OMAP24XX_DMA_I2C1_RX		28	/* S_DMA_27 */
-#define OMAP24XX_DMA_I2C2_TX		29	/* S_DMA_28 */
-#define OMAP24XX_DMA_I2C2_RX		30	/* S_DMA_29 */
-#define OMAP24XX_DMA_MCBSP1_TX		31	/* S_DMA_30 */
-#define OMAP24XX_DMA_MCBSP1_RX		32	/* S_DMA_31 */
-#define OMAP24XX_DMA_MCBSP2_TX		33	/* S_DMA_32 */
-#define OMAP24XX_DMA_MCBSP2_RX		34	/* S_DMA_33 */
-#define OMAP24XX_DMA_SPI1_TX0		35	/* S_DMA_34 */
-#define OMAP24XX_DMA_SPI1_RX0		36	/* S_DMA_35 */
-#define OMAP24XX_DMA_SPI1_TX1		37	/* S_DMA_36 */
-#define OMAP24XX_DMA_SPI1_RX1		38	/* S_DMA_37 */
-#define OMAP24XX_DMA_SPI1_TX2		39	/* S_DMA_38 */
-#define OMAP24XX_DMA_SPI1_RX2		40	/* S_DMA_39 */
-#define OMAP24XX_DMA_SPI1_TX3		41	/* S_DMA_40 */
-#define OMAP24XX_DMA_SPI1_RX3		42	/* S_DMA_41 */
-#define OMAP24XX_DMA_SPI2_TX0		43	/* S_DMA_42 */
-#define OMAP24XX_DMA_SPI2_RX0		44	/* S_DMA_43 */
-#define OMAP24XX_DMA_SPI2_TX1		45	/* S_DMA_44 */
-#define OMAP24XX_DMA_SPI2_RX1		46	/* S_DMA_45 */
-#define OMAP24XX_DMA_MMC2_TX		47	/* S_DMA_46 */
-#define OMAP24XX_DMA_MMC2_RX		48	/* S_DMA_47 */
-#define OMAP24XX_DMA_UART1_TX		49	/* S_DMA_48 */
-#define OMAP24XX_DMA_UART1_RX		50	/* S_DMA_49 */
-#define OMAP24XX_DMA_UART2_TX		51	/* S_DMA_50 */
-#define OMAP24XX_DMA_UART2_RX		52	/* S_DMA_51 */
-#define OMAP24XX_DMA_UART3_TX		53	/* S_DMA_52 */
-#define OMAP24XX_DMA_UART3_RX		54	/* S_DMA_53 */
-#define OMAP24XX_DMA_USB_W2FC_TX0	55	/* S_DMA_54 */
-#define OMAP24XX_DMA_USB_W2FC_RX0	56	/* S_DMA_55 */
-#define OMAP24XX_DMA_USB_W2FC_TX1	57	/* S_DMA_56 */
-#define OMAP24XX_DMA_USB_W2FC_RX1	58	/* S_DMA_57 */
-#define OMAP24XX_DMA_USB_W2FC_TX2	59	/* S_DMA_58 */
-#define OMAP24XX_DMA_USB_W2FC_RX2	60	/* S_DMA_59 */
-#define OMAP24XX_DMA_MMC1_TX		61	/* S_DMA_60 */
-#define OMAP24XX_DMA_MMC1_RX		62	/* S_DMA_61 */
-#define OMAP24XX_DMA_MS			63	/* S_DMA_62 */
-#define OMAP242X_DMA_EXT_DMAREQ5	64	/* S_DMA_63 */
-#define OMAP243X_DMA_EXT_DMAREQ6	64	/* S_DMA_63 */
-#define OMAP34XX_DMA_EXT_DMAREQ3	64	/* S_DMA_63 */
-#define OMAP34XX_DMA_AES2_TX		65	/* S_DMA_64 */
-#define OMAP34XX_DMA_AES2_RX		66	/* S_DMA_65 */
-#define OMAP34XX_DMA_DES2_TX		67	/* S_DMA_66 */
-#define OMAP34XX_DMA_DES2_RX		68	/* S_DMA_67 */
-#define OMAP34XX_DMA_SHA1MD5_RX		69	/* S_DMA_68 */
-#define OMAP34XX_DMA_SPI4_TX0		70	/* S_DMA_69 */
-#define OMAP34XX_DMA_SPI4_RX0		71	/* S_DMA_70 */
-#define OMAP34XX_DSS_DMA0		72	/* S_DMA_71 */
-#define OMAP34XX_DSS_DMA1		73	/* S_DMA_72 */
-#define OMAP34XX_DSS_DMA2		74	/* S_DMA_73 */
-#define OMAP34XX_DSS_DMA3		75	/* S_DMA_74 */
-#define OMAP34XX_DMA_MMC3_TX		77	/* S_DMA_76 */
-#define OMAP34XX_DMA_MMC3_RX		78	/* S_DMA_77 */
-#define OMAP34XX_DMA_USIM_TX		79	/* S_DMA_78 */
-#define OMAP34XX_DMA_USIM_RX		80	/* S_DMA_79 */
-
-#define OMAP36XX_DMA_UART4_TX		81	/* S_DMA_80 */
-#define OMAP36XX_DMA_UART4_RX		82	/* S_DMA_81 */
-
-/* Only for AM35xx */
-#define AM35XX_DMA_UART4_TX		54
-#define AM35XX_DMA_UART4_RX		55
-
-/*----------------------------------------------------------------------------*/
-
-#define OMAP1_DMA_TOUT_IRQ		(1 << 0)
-#define OMAP_DMA_DROP_IRQ		(1 << 1)
-#define OMAP_DMA_HALF_IRQ		(1 << 2)
-#define OMAP_DMA_FRAME_IRQ		(1 << 3)
-#define OMAP_DMA_LAST_IRQ		(1 << 4)
-#define OMAP_DMA_BLOCK_IRQ		(1 << 5)
-#define OMAP1_DMA_SYNC_IRQ		(1 << 6)
-#define OMAP2_DMA_PKT_IRQ		(1 << 7)
-#define OMAP2_DMA_TRANS_ERR_IRQ		(1 << 8)
-#define OMAP2_DMA_SECURE_ERR_IRQ	(1 << 9)
-#define OMAP2_DMA_SUPERVISOR_ERR_IRQ	(1 << 10)
-#define OMAP2_DMA_MISALIGNED_ERR_IRQ	(1 << 11)
-
-#define OMAP_DMA_CCR_EN			(1 << 7)
-#define OMAP_DMA_CCR_RD_ACTIVE		(1 << 9)
-#define OMAP_DMA_CCR_WR_ACTIVE		(1 << 10)
-#define OMAP_DMA_CCR_SEL_SRC_DST_SYNC	(1 << 24)
-#define OMAP_DMA_CCR_BUFFERING_DISABLE	(1 << 25)
-
-#define OMAP_DMA_DATA_TYPE_S8		0x00
-#define OMAP_DMA_DATA_TYPE_S16		0x01
-#define OMAP_DMA_DATA_TYPE_S32		0x02
-
-#define OMAP_DMA_SYNC_ELEMENT		0x00
-#define OMAP_DMA_SYNC_FRAME		0x01
-#define OMAP_DMA_SYNC_BLOCK		0x02
-#define OMAP_DMA_SYNC_PACKET		0x03
-
-#define OMAP_DMA_DST_SYNC_PREFETCH	0x02
-#define OMAP_DMA_SRC_SYNC		0x01
-#define OMAP_DMA_DST_SYNC		0x00
-
-#define OMAP_DMA_PORT_EMIFF		0x00
-#define OMAP_DMA_PORT_EMIFS		0x01
-#define OMAP_DMA_PORT_OCP_T1		0x02
-#define OMAP_DMA_PORT_TIPB		0x03
-#define OMAP_DMA_PORT_OCP_T2		0x04
-#define OMAP_DMA_PORT_MPUI		0x05
-
-#define OMAP_DMA_AMODE_CONSTANT		0x00
-#define OMAP_DMA_AMODE_POST_INC		0x01
-#define OMAP_DMA_AMODE_SINGLE_IDX	0x02
-#define OMAP_DMA_AMODE_DOUBLE_IDX	0x03
-
-#define DMA_DEFAULT_FIFO_DEPTH		0x10
-#define DMA_DEFAULT_ARB_RATE		0x01
-/* Pass THREAD_RESERVE ORed with THREAD_FIFO for tparams */
-#define DMA_THREAD_RESERVE_NORM		(0x00 << 12) /* Def */
-#define DMA_THREAD_RESERVE_ONET		(0x01 << 12)
-#define DMA_THREAD_RESERVE_TWOT		(0x02 << 12)
-#define DMA_THREAD_RESERVE_THREET	(0x03 << 12)
-#define DMA_THREAD_FIFO_NONE		(0x00 << 14) /* Def */
-#define DMA_THREAD_FIFO_75		(0x01 << 14)
-#define DMA_THREAD_FIFO_25		(0x02 << 14)
-#define DMA_THREAD_FIFO_50		(0x03 << 14)
-
-/* DMA4_OCP_SYSCONFIG bits */
-#define DMA_SYSCONFIG_MIDLEMODE_MASK		(3 << 12)
-#define DMA_SYSCONFIG_CLOCKACTIVITY_MASK	(3 << 8)
-#define DMA_SYSCONFIG_EMUFREE			(1 << 5)
-#define DMA_SYSCONFIG_SIDLEMODE_MASK		(3 << 3)
-#define DMA_SYSCONFIG_SOFTRESET			(1 << 2)
-#define DMA_SYSCONFIG_AUTOIDLE			(1 << 0)
-
-#define DMA_SYSCONFIG_MIDLEMODE(n)		((n) << 12)
-#define DMA_SYSCONFIG_SIDLEMODE(n)		((n) << 3)
-
-#define DMA_IDLEMODE_SMARTIDLE			0x2
-#define DMA_IDLEMODE_NO_IDLE			0x1
-#define DMA_IDLEMODE_FORCE_IDLE			0x0
-
-/* Chaining modes*/
-#ifndef CONFIG_ARCH_OMAP1
-#define OMAP_DMA_STATIC_CHAIN		0x1
-#define OMAP_DMA_DYNAMIC_CHAIN		0x2
-#define OMAP_DMA_CHAIN_ACTIVE		0x1
-#define OMAP_DMA_CHAIN_INACTIVE		0x0
-#endif
-
-#define DMA_CH_PRIO_HIGH		0x1
-#define DMA_CH_PRIO_LOW			0x0 /* Def */
-
-/* Errata handling */
-#define IS_DMA_ERRATA(id)		(errata & (id))
-#define SET_DMA_ERRATA(id)		(errata |= (id))
-
-#define DMA_ERRATA_IFRAME_BUFFERING	BIT(0x0)
-#define DMA_ERRATA_PARALLEL_CHANNELS	BIT(0x1)
-#define DMA_ERRATA_i378			BIT(0x2)
-#define DMA_ERRATA_i541			BIT(0x3)
-#define DMA_ERRATA_i88			BIT(0x4)
-#define DMA_ERRATA_3_3			BIT(0x5)
-#define DMA_ROMCODE_BUG			BIT(0x6)
-
-/* Attributes for OMAP DMA Contrller */
-#define DMA_LINKED_LCH			BIT(0x0)
-#define GLOBAL_PRIORITY			BIT(0x1)
-#define RESERVE_CHANNEL			BIT(0x2)
-#define IS_CSSA_32			BIT(0x3)
-#define IS_CDSA_32			BIT(0x4)
-#define IS_RW_PRIORITY			BIT(0x5)
-#define ENABLE_1510_MODE		BIT(0x6)
-#define SRC_PORT			BIT(0x7)
-#define DST_PORT			BIT(0x8)
-#define SRC_INDEX			BIT(0x9)
-#define DST_INDEX			BIT(0xA)
-#define IS_BURST_ONLY4			BIT(0xB)
-#define CLEAR_CSR_ON_READ		BIT(0xC)
-#define IS_WORD_16			BIT(0xD)
-
-/* Defines for DMA Capabilities */
-#define DMA_HAS_TRANSPARENT_CAPS	(0x1 << 18)
-#define DMA_HAS_CONSTANT_FILL_CAPS	(0x1 << 19)
-#define DMA_HAS_DESCRIPTOR_CAPS		(0x3 << 20)
-
-enum omap_reg_offsets {
-
-GCR,		GSCR,		GRST1,		HW_ID,
-PCH2_ID,	PCH0_ID,	PCH1_ID,	PCHG_ID,
-PCHD_ID,	CAPS_0,		CAPS_1,		CAPS_2,
-CAPS_3,		CAPS_4,		PCH2_SR,	PCH0_SR,
-PCH1_SR,	PCHD_SR,	REVISION,	IRQSTATUS_L0,
-IRQSTATUS_L1,	IRQSTATUS_L2,	IRQSTATUS_L3,	IRQENABLE_L0,
-IRQENABLE_L1,	IRQENABLE_L2,	IRQENABLE_L3,	SYSSTATUS,
-OCP_SYSCONFIG,
-
-/* omap1+ specific */
-CPC, CCR2, LCH_CTRL,
-
-/* Common registers for all omap's */
-CSDP,		CCR,		CICR,		CSR,
-CEN,		CFN,		CSFI,		CSEI,
-CSAC,		CDAC,		CDEI,
-CDFI,		CLNK_CTRL,
-
-/* Channel specific registers */
-CSSA,		CDSA,		COLOR,
-CCEN,		CCFN,
-
-/* omap3630 and omap4 specific */
-CDP,		CNDP,		CCDN,
-
-};
-
-enum omap_dma_burst_mode {
-	OMAP_DMA_DATA_BURST_DIS = 0,
-	OMAP_DMA_DATA_BURST_4,
-	OMAP_DMA_DATA_BURST_8,
-	OMAP_DMA_DATA_BURST_16,
-};
-
-enum end_type {
-	OMAP_DMA_LITTLE_ENDIAN = 0,
-	OMAP_DMA_BIG_ENDIAN
-};
-
-enum omap_dma_color_mode {
-	OMAP_DMA_COLOR_DIS = 0,
-	OMAP_DMA_CONSTANT_FILL,
-	OMAP_DMA_TRANSPARENT_COPY
-};
-
-enum omap_dma_write_mode {
-	OMAP_DMA_WRITE_NON_POSTED = 0,
-	OMAP_DMA_WRITE_POSTED,
-	OMAP_DMA_WRITE_LAST_NON_POSTED
-};
-
-enum omap_dma_channel_mode {
-	OMAP_DMA_LCH_2D = 0,
-	OMAP_DMA_LCH_G,
-	OMAP_DMA_LCH_P,
-	OMAP_DMA_LCH_PD
-};
-
-struct omap_dma_channel_params {
-	int data_type;		/* data type 8,16,32 */
-	int elem_count;		/* number of elements in a frame */
-	int frame_count;	/* number of frames in a element */
-
-	int src_port;		/* Only on OMAP1 REVISIT: Is this needed? */
-	int src_amode;		/* constant, post increment, indexed,
-					double indexed */
-	unsigned long src_start;	/* source address : physical */
-	int src_ei;		/* source element index */
-	int src_fi;		/* source frame index */
-
-	int dst_port;		/* Only on OMAP1 REVISIT: Is this needed? */
-	int dst_amode;		/* constant, post increment, indexed,
-					double indexed */
-	unsigned long dst_start;	/* source address : physical */
-	int dst_ei;		/* source element index */
-	int dst_fi;		/* source frame index */
-
-	int trigger;		/* trigger attached if the channel is
-					synchronized */
-	int sync_mode;		/* sycn on element, frame , block or packet */
-	int src_or_dst_synch;	/* source synch(1) or destination synch(0) */
-
-	int ie;			/* interrupt enabled */
-
-	unsigned char read_prio;/* read priority */
-	unsigned char write_prio;/* write priority */
-
-#ifndef CONFIG_ARCH_OMAP1
-	enum omap_dma_burst_mode burst_mode; /* Burst mode 4/8/16 words */
-#endif
-};
-
-struct omap_dma_lch {
-	int next_lch;
-	int dev_id;
-	u16 saved_csr;
-	u16 enabled_irqs;
-	const char *dev_name;
-	void (*callback)(int lch, u16 ch_status, void *data);
-	void *data;
-	long flags;
-	/* required for Dynamic chaining */
-	int prev_linked_ch;
-	int next_linked_ch;
-	int state;
-	int chain_id;
-	int status;
-};
-
-struct omap_dma_dev_attr {
-	u32 dev_caps;
-	u16 lch_count;
-	u16 chan_count;
-	struct omap_dma_lch *chan;
-};
-
-/* System DMA platform data structure */
-struct omap_system_dma_plat_info {
-	struct omap_dma_dev_attr *dma_attr;
-	u32 errata;
-	void (*disable_irq_lch)(int lch);
-	void (*show_dma_caps)(void);
-	void (*clear_lch_regs)(int lch);
-	void (*clear_dma)(int lch);
-	void (*dma_write)(u32 val, int reg, int lch);
-	u32 (*dma_read)(int reg, int lch);
-};
-
-extern void __init omap_init_consistent_dma_size(void);
-extern void omap_set_dma_priority(int lch, int dst_port, int priority);
-extern int omap_request_dma(int dev_id, const char *dev_name,
-			void (*callback)(int lch, u16 ch_status, void *data),
-			void *data, int *dma_ch);
-extern void omap_enable_dma_irq(int ch, u16 irq_bits);
-extern void omap_disable_dma_irq(int ch, u16 irq_bits);
-extern void omap_free_dma(int ch);
-extern void omap_start_dma(int lch);
-extern void omap_stop_dma(int lch);
-extern void omap_set_dma_transfer_params(int lch, int data_type,
-					 int elem_count, int frame_count,
-					 int sync_mode,
-					 int dma_trigger, int src_or_dst_synch);
-extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode,
-				    u32 color);
-extern void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode);
-extern void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode);
-
-extern void omap_set_dma_src_params(int lch, int src_port, int src_amode,
-				    unsigned long src_start,
-				    int src_ei, int src_fi);
-extern void omap_set_dma_src_index(int lch, int eidx, int fidx);
-extern void omap_set_dma_src_data_pack(int lch, int enable);
-extern void omap_set_dma_src_burst_mode(int lch,
-					enum omap_dma_burst_mode burst_mode);
-
-extern void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
-				     unsigned long dest_start,
-				     int dst_ei, int dst_fi);
-extern void omap_set_dma_dest_index(int lch, int eidx, int fidx);
-extern void omap_set_dma_dest_data_pack(int lch, int enable);
-extern void omap_set_dma_dest_burst_mode(int lch,
-					 enum omap_dma_burst_mode burst_mode);
-
-extern void omap_set_dma_params(int lch,
-				struct omap_dma_channel_params *params);
-
-extern void omap_dma_link_lch(int lch_head, int lch_queue);
-extern void omap_dma_unlink_lch(int lch_head, int lch_queue);
-
-extern int omap_set_dma_callback(int lch,
-			void (*callback)(int lch, u16 ch_status, void *data),
-			void *data);
-extern dma_addr_t omap_get_dma_src_pos(int lch);
-extern dma_addr_t omap_get_dma_dst_pos(int lch);
-extern void omap_clear_dma(int lch);
-extern int omap_get_dma_active_status(int lch);
-extern int omap_dma_running(void);
-extern void omap_dma_set_global_params(int arb_rate, int max_fifo_depth,
-				       int tparams);
-extern int omap_dma_set_prio_lch(int lch, unsigned char read_prio,
-				 unsigned char write_prio);
-extern void omap_set_dma_dst_endian_type(int lch, enum end_type etype);
-extern void omap_set_dma_src_endian_type(int lch, enum end_type etype);
-extern int omap_get_dma_index(int lch, int *ei, int *fi);
-
-void omap_dma_global_context_save(void);
-void omap_dma_global_context_restore(void);
-
-extern void omap_dma_disable_irq(int lch);
-
-/* Chaining APIs */
-#ifndef CONFIG_ARCH_OMAP1
-extern int omap_request_dma_chain(int dev_id, const char *dev_name,
-				  void (*callback) (int lch, u16 ch_status,
-						    void *data),
-				  int *chain_id, int no_of_chans,
-				  int chain_mode,
-				  struct omap_dma_channel_params params);
-extern int omap_free_dma_chain(int chain_id);
-extern int omap_dma_chain_a_transfer(int chain_id, int src_start,
-				     int dest_start, int elem_count,
-				     int frame_count, void *callbk_data);
-extern int omap_start_dma_chain_transfers(int chain_id);
-extern int omap_stop_dma_chain_transfers(int chain_id);
-extern int omap_get_dma_chain_index(int chain_id, int *ei, int *fi);
-extern int omap_get_dma_chain_dst_pos(int chain_id);
-extern int omap_get_dma_chain_src_pos(int chain_id);
-
-extern int omap_modify_dma_chain_params(int chain_id,
-					struct omap_dma_channel_params params);
-extern int omap_dma_chain_status(int chain_id);
-#endif
-
-#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_FB_OMAP)
-#include <mach/lcd_dma.h>
-#else
-static inline int omap_lcd_dma_running(void)
-{
-	return 0;
-}
-#endif
-
-#endif /* __ASM_ARCH_DMA_H */
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 85868e9..05a36e1 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -32,7 +32,6 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
@@ -55,6 +54,10 @@
 #define OMAP_TIMER_TRIGGER_OVERFLOW		0x01
 #define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE	0x02
 
+/* posted mode types */
+#define OMAP_TIMER_NONPOSTED			0x00
+#define OMAP_TIMER_POSTED			0x01
+
 /* timer capabilities used in hwmod database */
 #define OMAP_TIMER_SECURE				0x80000000
 #define OMAP_TIMER_ALWON				0x40000000
@@ -62,6 +65,16 @@
 #define OMAP_TIMER_NEEDS_RESET				0x10000000
 #define OMAP_TIMER_HAS_DSP_IRQ				0x08000000
 
+/*
+ * timer errata flags
+ *
+ * Errata i103/i767 impacts all OMAP3/4/5 devices including AM33xx. This
+ * errata prevents us from using posted mode on these devices, unless the
+ * timer counter register is never read. For more details please refer to
+ * the OMAP3/4/5 errata documents.
+ */
+#define OMAP_TIMER_ERRATA_I103_I767			0x80000000
+
 struct omap_timer_capability_dev_attr {
 	u32 timer_capability;
 };
@@ -70,8 +83,6 @@ struct omap_dm_timer;
 
 struct timer_regs {
 	u32 tidr;
-	u32 tistat;
-	u32 tisr;
 	u32 tier;
 	u32 twer;
 	u32 tclr;
@@ -93,12 +104,15 @@ struct timer_regs {
 struct dmtimer_platform_data {
 	/* set_timer_src - Only used for OMAP1 devices */
 	int (*set_timer_src)(struct platform_device *pdev, int source);
+	u32 timer_errata;
 	u32 timer_capability;
+	int (*get_context_loss_count)(struct device *);
 };
 
 int omap_dm_timer_reserve_systimer(int id);
 struct omap_dm_timer *omap_dm_timer_request(void);
 struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
+struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap);
 int omap_dm_timer_free(struct omap_dm_timer *timer);
 void omap_dm_timer_enable(struct omap_dm_timer *timer);
 void omap_dm_timer_disable(struct omap_dm_timer *timer);
@@ -120,6 +134,7 @@ int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, i
 int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
 
 int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask);
 
 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
 int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
@@ -263,9 +278,11 @@ struct omap_dm_timer {
 	unsigned reserved:1;
 	unsigned posted:1;
 	struct timer_regs context;
+	int (*get_context_loss_count)(struct device *);
 	int ctx_loss_count;
 	int revision;
 	u32 capability;
+	u32 errata;
 	struct platform_device *pdev;
 	struct list_head node;
 };
@@ -304,7 +321,7 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
 				OMAP_TIMER_V1_SYS_STAT_OFFSET;
 		timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET;
 		timer->irq_ena = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
-		timer->irq_dis = NULL;
+		timer->irq_dis = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
 		timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET;
 		timer->func_base = timer->io_base;
 	} else {
@@ -337,28 +354,46 @@ static inline void __omap_dm_timer_reset(struct omap_dm_timer *timer,
 		l |= 1 << 2;
 
 	__raw_writel(l, timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
-
-	/* Match hardware reset default of posted mode */
-	__omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
-					OMAP_TIMER_CTRL_POSTED, 0);
 }
 
-static inline int __omap_dm_timer_set_source(struct clk *timer_fck,
-						struct clk *parent)
+/*
+ * __omap_dm_timer_enable_posted - enables write posted mode
+ * @timer:      pointer to timer instance handle
+ *
+ * Enables the write posted mode for the timer. When posted mode is enabled
+ * writes to certain timer registers are immediately acknowledged by the
+ * internal bus and hence prevents stalling the CPU waiting for the write to
+ * complete. Enabling this feature can improve performance for writing to the
+ * timer registers.
+ */
+static inline void __omap_dm_timer_enable_posted(struct omap_dm_timer *timer)
 {
-	int ret;
+	if (timer->posted)
+		return;
 
-	clk_disable(timer_fck);
-	ret = clk_set_parent(timer_fck, parent);
-	clk_enable(timer_fck);
+	if (timer->errata & OMAP_TIMER_ERRATA_I103_I767)
+		return;
 
-	/*
-	 * When the functional clock disappears, too quick writes seem
-	 * to cause an abort. XXX Is this still necessary?
-	 */
-	__delay(300000);
+	__omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
+			      OMAP_TIMER_CTRL_POSTED, 0);
+	timer->context.tsicr = OMAP_TIMER_CTRL_POSTED;
+	timer->posted = OMAP_TIMER_POSTED;
+}
 
-	return ret;
+/**
+ * __omap_dm_timer_override_errata - override errata flags for a timer
+ * @timer:      pointer to timer handle
+ * @errata:	errata flags to be ignored
+ *
+ * For a given timer, override a timer errata by clearing the flags
+ * specified by the errata argument. A specific erratum should only be
+ * overridden for a timer if the timer is used in such a way the erratum
+ * has no impact.
+ */
+static inline void __omap_dm_timer_override_errata(struct omap_dm_timer *timer,
+						   u32 errata)
+{
+	timer->errata &= ~errata;
 }
 
 static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer,
diff --git a/arch/arm/plat-omap/include/plat/fpga.h b/arch/arm/plat-omap/include/plat/fpga.h
deleted file mode 100644
index bd3c632..0000000
--- a/arch/arm/plat-omap/include/plat/fpga.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/fpga.h
- *
- * Interrupt handler for OMAP-1510 FPGA
- *
- * Copyright (C) 2001 RidgeRun, Inc.
- * Author: Greg Lonnon <glonnon@ridgerun.com>
- *
- * Copyright (C) 2002 MontaVista Software, Inc.
- *
- * Separated FPGA interrupts from innovator1510.c and cleaned up for 2.6
- * Copyright (C) 2004 Nokia Corporation by Tony Lindrgen <tony@atomide.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_OMAP_FPGA_H
-#define __ASM_ARCH_OMAP_FPGA_H
-
-extern void omap1510_fpga_init_irq(void);
-
-#define fpga_read(reg)			__raw_readb(reg)
-#define fpga_write(val, reg)		__raw_writeb(val, reg)
-
-/*
- * ---------------------------------------------------------------------------
- *  H2/P2 Debug board FPGA
- * ---------------------------------------------------------------------------
- */
-/* maps in the FPGA registers and the ETHR registers */
-#define H2P2_DBG_FPGA_BASE		0xE8000000		/* VA */
-#define H2P2_DBG_FPGA_SIZE		SZ_4K			/* SIZE */
-#define H2P2_DBG_FPGA_START		0x04000000		/* PA */
-
-#define H2P2_DBG_FPGA_ETHR_START	(H2P2_DBG_FPGA_START + 0x300)
-#define H2P2_DBG_FPGA_FPGA_REV		IOMEM(H2P2_DBG_FPGA_BASE + 0x10)	/* FPGA Revision */
-#define H2P2_DBG_FPGA_BOARD_REV		IOMEM(H2P2_DBG_FPGA_BASE + 0x12)	/* Board Revision */
-#define H2P2_DBG_FPGA_GPIO		IOMEM(H2P2_DBG_FPGA_BASE + 0x14)	/* GPIO outputs */
-#define H2P2_DBG_FPGA_LEDS		IOMEM(H2P2_DBG_FPGA_BASE + 0x16)	/* LEDs outputs */
-#define H2P2_DBG_FPGA_MISC_INPUTS	IOMEM(H2P2_DBG_FPGA_BASE + 0x18)	/* Misc inputs */
-#define H2P2_DBG_FPGA_LAN_STATUS	IOMEM(H2P2_DBG_FPGA_BASE + 0x1A)	/* LAN Status line */
-#define H2P2_DBG_FPGA_LAN_RESET		IOMEM(H2P2_DBG_FPGA_BASE + 0x1C)	/* LAN Reset line */
-
-/* NOTE:  most boards don't have a static mapping for the FPGA ... */
-struct h2p2_dbg_fpga {
-	/* offset 0x00 */
-	u16		smc91x[8];
-	/* offset 0x10 */
-	u16		fpga_rev;
-	u16		board_rev;
-	u16		gpio_outputs;
-	u16		leds;
-	/* offset 0x18 */
-	u16		misc_inputs;
-	u16		lan_status;
-	u16		lan_reset;
-	u16		reserved0;
-	/* offset 0x20 */
-	u16		ps2_data;
-	u16		ps2_ctrl;
-	/* plus also 4 rs232 ports ... */
-};
-
-/* LEDs definition on debug board (16 LEDs, all physically green) */
-#define H2P2_DBG_FPGA_LED_GREEN		(1 << 15)
-#define H2P2_DBG_FPGA_LED_AMBER		(1 << 14)
-#define H2P2_DBG_FPGA_LED_RED		(1 << 13)
-#define H2P2_DBG_FPGA_LED_BLUE		(1 << 12)
-/*  cpu0 load-meter LEDs */
-#define H2P2_DBG_FPGA_LOAD_METER	(1 << 0)	// A bit of fun on our board ...
-#define H2P2_DBG_FPGA_LOAD_METER_SIZE	11
-#define H2P2_DBG_FPGA_LOAD_METER_MASK	((1 << H2P2_DBG_FPGA_LOAD_METER_SIZE) - 1)
-
-#define H2P2_DBG_FPGA_P2_LED_TIMER		(1 << 0)
-#define H2P2_DBG_FPGA_P2_LED_IDLE		(1 << 1)
-
-/*
- * ---------------------------------------------------------------------------
- *  OMAP-1510 FPGA
- * ---------------------------------------------------------------------------
- */
-#define OMAP1510_FPGA_BASE		0xE8000000		/* VA */
-#define OMAP1510_FPGA_SIZE		SZ_4K
-#define OMAP1510_FPGA_START		0x08000000		/* PA */
-
-/* Revision */
-#define OMAP1510_FPGA_REV_LOW			IOMEM(OMAP1510_FPGA_BASE + 0x0)
-#define OMAP1510_FPGA_REV_HIGH			IOMEM(OMAP1510_FPGA_BASE + 0x1)
-
-#define OMAP1510_FPGA_LCD_PANEL_CONTROL		IOMEM(OMAP1510_FPGA_BASE + 0x2)
-#define OMAP1510_FPGA_LED_DIGIT			IOMEM(OMAP1510_FPGA_BASE + 0x3)
-#define INNOVATOR_FPGA_HID_SPI			IOMEM(OMAP1510_FPGA_BASE + 0x4)
-#define OMAP1510_FPGA_POWER			IOMEM(OMAP1510_FPGA_BASE + 0x5)
-
-/* Interrupt status */
-#define OMAP1510_FPGA_ISR_LO			IOMEM(OMAP1510_FPGA_BASE + 0x6)
-#define OMAP1510_FPGA_ISR_HI			IOMEM(OMAP1510_FPGA_BASE + 0x7)
-
-/* Interrupt mask */
-#define OMAP1510_FPGA_IMR_LO			IOMEM(OMAP1510_FPGA_BASE + 0x8)
-#define OMAP1510_FPGA_IMR_HI			IOMEM(OMAP1510_FPGA_BASE + 0x9)
-
-/* Reset registers */
-#define OMAP1510_FPGA_HOST_RESET		IOMEM(OMAP1510_FPGA_BASE + 0xa)
-#define OMAP1510_FPGA_RST			IOMEM(OMAP1510_FPGA_BASE + 0xb)
-
-#define OMAP1510_FPGA_AUDIO			IOMEM(OMAP1510_FPGA_BASE + 0xc)
-#define OMAP1510_FPGA_DIP			IOMEM(OMAP1510_FPGA_BASE + 0xe)
-#define OMAP1510_FPGA_FPGA_IO			IOMEM(OMAP1510_FPGA_BASE + 0xf)
-#define OMAP1510_FPGA_UART1			IOMEM(OMAP1510_FPGA_BASE + 0x14)
-#define OMAP1510_FPGA_UART2			IOMEM(OMAP1510_FPGA_BASE + 0x15)
-#define OMAP1510_FPGA_OMAP1510_STATUS		IOMEM(OMAP1510_FPGA_BASE + 0x16)
-#define OMAP1510_FPGA_BOARD_REV			IOMEM(OMAP1510_FPGA_BASE + 0x18)
-#define OMAP1510P1_PPT_DATA			IOMEM(OMAP1510_FPGA_BASE + 0x100)
-#define OMAP1510P1_PPT_STATUS			IOMEM(OMAP1510_FPGA_BASE + 0x101)
-#define OMAP1510P1_PPT_CONTROL			IOMEM(OMAP1510_FPGA_BASE + 0x102)
-
-#define OMAP1510_FPGA_TOUCHSCREEN		IOMEM(OMAP1510_FPGA_BASE + 0x204)
-
-#define INNOVATOR_FPGA_INFO			IOMEM(OMAP1510_FPGA_BASE + 0x205)
-#define INNOVATOR_FPGA_LCD_BRIGHT_LO		IOMEM(OMAP1510_FPGA_BASE + 0x206)
-#define INNOVATOR_FPGA_LCD_BRIGHT_HI		IOMEM(OMAP1510_FPGA_BASE + 0x207)
-#define INNOVATOR_FPGA_LED_GRN_LO		IOMEM(OMAP1510_FPGA_BASE + 0x208)
-#define INNOVATOR_FPGA_LED_GRN_HI		IOMEM(OMAP1510_FPGA_BASE + 0x209)
-#define INNOVATOR_FPGA_LED_RED_LO		IOMEM(OMAP1510_FPGA_BASE + 0x20a)
-#define INNOVATOR_FPGA_LED_RED_HI		IOMEM(OMAP1510_FPGA_BASE + 0x20b)
-#define INNOVATOR_FPGA_CAM_USB_CONTROL		IOMEM(OMAP1510_FPGA_BASE + 0x20c)
-#define INNOVATOR_FPGA_EXP_CONTROL		IOMEM(OMAP1510_FPGA_BASE + 0x20d)
-#define INNOVATOR_FPGA_ISR2			IOMEM(OMAP1510_FPGA_BASE + 0x20e)
-#define INNOVATOR_FPGA_IMR2			IOMEM(OMAP1510_FPGA_BASE + 0x210)
-
-#define OMAP1510_FPGA_ETHR_START		(OMAP1510_FPGA_START + 0x300)
-
-/*
- * Power up Giga UART driver, turn on HID clock.
- * Turn off BT power, since we're not using it and it
- * draws power.
- */
-#define OMAP1510_FPGA_RESET_VALUE		0x42
-
-#define OMAP1510_FPGA_PCR_IF_PD0		(1 << 7)
-#define OMAP1510_FPGA_PCR_COM2_EN		(1 << 6)
-#define OMAP1510_FPGA_PCR_COM1_EN		(1 << 5)
-#define OMAP1510_FPGA_PCR_EXP_PD0		(1 << 4)
-#define OMAP1510_FPGA_PCR_EXP_PD1		(1 << 3)
-#define OMAP1510_FPGA_PCR_48MHZ_CLK		(1 << 2)
-#define OMAP1510_FPGA_PCR_4MHZ_CLK		(1 << 1)
-#define OMAP1510_FPGA_PCR_RSRVD_BIT0		(1 << 0)
-
-/*
- * Innovator/OMAP1510 FPGA HID register bit definitions
- */
-#define OMAP1510_FPGA_HID_SCLK	(1<<0)	/* output */
-#define OMAP1510_FPGA_HID_MOSI	(1<<1)	/* output */
-#define OMAP1510_FPGA_HID_nSS	(1<<2)	/* output 0/1 chip idle/select */
-#define OMAP1510_FPGA_HID_nHSUS	(1<<3)	/* output 0/1 host active/suspended */
-#define OMAP1510_FPGA_HID_MISO	(1<<4)	/* input */
-#define OMAP1510_FPGA_HID_ATN	(1<<5)	/* input  0/1 chip idle/ATN */
-#define OMAP1510_FPGA_HID_rsrvd	(1<<6)
-#define OMAP1510_FPGA_HID_RESETn (1<<7)	/* output - 0/1 USAR reset/run */
-
-/* The FPGA IRQ is cascaded through GPIO_13 */
-#define OMAP1510_INT_FPGA		(IH_GPIO_BASE + 13)
-
-/* IRQ Numbers for interrupts muxed through the FPGA */
-#define OMAP1510_INT_FPGA_ATN		(OMAP_FPGA_IRQ_BASE + 0)
-#define OMAP1510_INT_FPGA_ACK		(OMAP_FPGA_IRQ_BASE + 1)
-#define OMAP1510_INT_FPGA2		(OMAP_FPGA_IRQ_BASE + 2)
-#define OMAP1510_INT_FPGA3		(OMAP_FPGA_IRQ_BASE + 3)
-#define OMAP1510_INT_FPGA4		(OMAP_FPGA_IRQ_BASE + 4)
-#define OMAP1510_INT_FPGA5		(OMAP_FPGA_IRQ_BASE + 5)
-#define OMAP1510_INT_FPGA6		(OMAP_FPGA_IRQ_BASE + 6)
-#define OMAP1510_INT_FPGA7		(OMAP_FPGA_IRQ_BASE + 7)
-#define OMAP1510_INT_FPGA8		(OMAP_FPGA_IRQ_BASE + 8)
-#define OMAP1510_INT_FPGA9		(OMAP_FPGA_IRQ_BASE + 9)
-#define OMAP1510_INT_FPGA10		(OMAP_FPGA_IRQ_BASE + 10)
-#define OMAP1510_INT_FPGA11		(OMAP_FPGA_IRQ_BASE + 11)
-#define OMAP1510_INT_FPGA12		(OMAP_FPGA_IRQ_BASE + 12)
-#define OMAP1510_INT_ETHER		(OMAP_FPGA_IRQ_BASE + 13)
-#define OMAP1510_INT_FPGAUART1		(OMAP_FPGA_IRQ_BASE + 14)
-#define OMAP1510_INT_FPGAUART2		(OMAP_FPGA_IRQ_BASE + 15)
-#define OMAP1510_INT_FPGA_TS		(OMAP_FPGA_IRQ_BASE + 16)
-#define OMAP1510_INT_FPGA17		(OMAP_FPGA_IRQ_BASE + 17)
-#define OMAP1510_INT_FPGA_CAM		(OMAP_FPGA_IRQ_BASE + 18)
-#define OMAP1510_INT_FPGA_RTC_A		(OMAP_FPGA_IRQ_BASE + 19)
-#define OMAP1510_INT_FPGA_RTC_B		(OMAP_FPGA_IRQ_BASE + 20)
-#define OMAP1510_INT_FPGA_CD		(OMAP_FPGA_IRQ_BASE + 21)
-#define OMAP1510_INT_FPGA22		(OMAP_FPGA_IRQ_BASE + 22)
-#define OMAP1510_INT_FPGA23		(OMAP_FPGA_IRQ_BASE + 23)
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
deleted file mode 100644
index 2e6e259..0000000
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * General-Purpose Memory Controller for OMAP2
- *
- * Copyright (C) 2005-2006 Nokia 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.
- */
-
-#ifndef __OMAP2_GPMC_H
-#define __OMAP2_GPMC_H
-
-/* Maximum Number of Chip Selects */
-#define GPMC_CS_NUM		8
-
-#define GPMC_CS_CONFIG1		0x00
-#define GPMC_CS_CONFIG2		0x04
-#define GPMC_CS_CONFIG3		0x08
-#define GPMC_CS_CONFIG4		0x0c
-#define GPMC_CS_CONFIG5		0x10
-#define GPMC_CS_CONFIG6		0x14
-#define GPMC_CS_CONFIG7		0x18
-#define GPMC_CS_NAND_COMMAND	0x1c
-#define GPMC_CS_NAND_ADDRESS	0x20
-#define GPMC_CS_NAND_DATA	0x24
-
-/* Control Commands */
-#define GPMC_CONFIG_RDY_BSY	0x00000001
-#define GPMC_CONFIG_DEV_SIZE	0x00000002
-#define GPMC_CONFIG_DEV_TYPE	0x00000003
-#define GPMC_SET_IRQ_STATUS	0x00000004
-#define GPMC_CONFIG_WP		0x00000005
-
-#define GPMC_GET_IRQ_STATUS	0x00000006
-#define GPMC_PREFETCH_FIFO_CNT	0x00000007 /* bytes available in FIFO for r/w */
-#define GPMC_PREFETCH_COUNT	0x00000008 /* remaining bytes to be read/write*/
-#define GPMC_STATUS_BUFFER	0x00000009 /* 1: buffer is available to write */
-
-#define GPMC_NAND_COMMAND	0x0000000a
-#define GPMC_NAND_ADDRESS	0x0000000b
-#define GPMC_NAND_DATA		0x0000000c
-
-#define GPMC_ENABLE_IRQ		0x0000000d
-
-/* ECC commands */
-#define GPMC_ECC_READ		0 /* Reset Hardware ECC for read */
-#define GPMC_ECC_WRITE		1 /* Reset Hardware ECC for write */
-#define GPMC_ECC_READSYN	2 /* Reset before syndrom is read back */
-
-#define GPMC_CONFIG1_WRAPBURST_SUPP     (1 << 31)
-#define GPMC_CONFIG1_READMULTIPLE_SUPP  (1 << 30)
-#define GPMC_CONFIG1_READTYPE_ASYNC     (0 << 29)
-#define GPMC_CONFIG1_READTYPE_SYNC      (1 << 29)
-#define GPMC_CONFIG1_WRITEMULTIPLE_SUPP (1 << 28)
-#define GPMC_CONFIG1_WRITETYPE_ASYNC    (0 << 27)
-#define GPMC_CONFIG1_WRITETYPE_SYNC     (1 << 27)
-#define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25)
-#define GPMC_CONFIG1_PAGE_LEN(val)      ((val & 3) << 23)
-#define GPMC_CONFIG1_WAIT_READ_MON      (1 << 22)
-#define GPMC_CONFIG1_WAIT_WRITE_MON     (1 << 21)
-#define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18)
-#define GPMC_CONFIG1_WAIT_PIN_SEL(val)  ((val & 3) << 16)
-#define GPMC_CONFIG1_DEVICESIZE(val)    ((val & 3) << 12)
-#define GPMC_CONFIG1_DEVICESIZE_16      GPMC_CONFIG1_DEVICESIZE(1)
-#define GPMC_CONFIG1_DEVICETYPE(val)    ((val & 3) << 10)
-#define GPMC_CONFIG1_DEVICETYPE_NOR     GPMC_CONFIG1_DEVICETYPE(0)
-#define GPMC_CONFIG1_MUXADDDATA         (1 << 9)
-#define GPMC_CONFIG1_TIME_PARA_GRAN     (1 << 4)
-#define GPMC_CONFIG1_FCLK_DIV(val)      (val & 3)
-#define GPMC_CONFIG1_FCLK_DIV2          (GPMC_CONFIG1_FCLK_DIV(1))
-#define GPMC_CONFIG1_FCLK_DIV3          (GPMC_CONFIG1_FCLK_DIV(2))
-#define GPMC_CONFIG1_FCLK_DIV4          (GPMC_CONFIG1_FCLK_DIV(3))
-#define GPMC_CONFIG7_CSVALID		(1 << 6)
-
-#define GPMC_DEVICETYPE_NOR		0
-#define GPMC_DEVICETYPE_NAND		2
-#define GPMC_CONFIG_WRITEPROTECT	0x00000010
-#define GPMC_STATUS_BUFF_EMPTY		0x00000001
-#define WR_RD_PIN_MONITORING		0x00600000
-#define GPMC_PREFETCH_STATUS_FIFO_CNT(val)	((val >> 24) & 0x7F)
-#define GPMC_PREFETCH_STATUS_COUNT(val)	(val & 0x00003fff)
-#define GPMC_IRQ_FIFOEVENTENABLE	0x01
-#define GPMC_IRQ_COUNT_EVENT		0x02
-
-#define PREFETCH_FIFOTHRESHOLD_MAX	0x40
-#define PREFETCH_FIFOTHRESHOLD(val)	((val) << 8)
-
-enum omap_ecc {
-		/* 1-bit ecc: stored at end of spare area */
-	OMAP_ECC_HAMMING_CODE_DEFAULT = 0, /* Default, s/w method */
-	OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */
-		/* 1-bit ecc: stored at beginning of spare area as romcode */
-	OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */
-	OMAP_ECC_BCH4_CODE_HW, /* 4-bit BCH ecc code */
-	OMAP_ECC_BCH8_CODE_HW, /* 8-bit BCH ecc code */
-};
-
-/*
- * Note that all values in this struct are in nanoseconds except sync_clk
- * (which is in picoseconds), while the register values are in gpmc_fck cycles.
- */
-struct gpmc_timings {
-	/* Minimum clock period for synchronous mode (in picoseconds) */
-	u32 sync_clk;
-
-	/* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */
-	u16 cs_on;		/* Assertion time */
-	u16 cs_rd_off;		/* Read deassertion time */
-	u16 cs_wr_off;		/* Write deassertion time */
-
-	/* ADV signal timings corresponding to GPMC_CONFIG3 */
-	u16 adv_on;		/* Assertion time */
-	u16 adv_rd_off;		/* Read deassertion time */
-	u16 adv_wr_off;		/* Write deassertion time */
-
-	/* WE signals timings corresponding to GPMC_CONFIG4 */
-	u16 we_on;		/* WE assertion time */
-	u16 we_off;		/* WE deassertion time */
-
-	/* OE signals timings corresponding to GPMC_CONFIG4 */
-	u16 oe_on;		/* OE assertion time */
-	u16 oe_off;		/* OE deassertion time */
-
-	/* Access time and cycle time timings corresponding to GPMC_CONFIG5 */
-	u16 page_burst_access;	/* Multiple access word delay */
-	u16 access;		/* Start-cycle to first data valid delay */
-	u16 rd_cycle;		/* Total read cycle time */
-	u16 wr_cycle;		/* Total write cycle time */
-
-	/* The following are only on OMAP3430 */
-	u16 wr_access;		/* WRACCESSTIME */
-	u16 wr_data_mux_bus;	/* WRDATAONADMUXBUS */
-};
-
-struct gpmc_nand_regs {
-	void __iomem	*gpmc_status;
-	void __iomem	*gpmc_nand_command;
-	void __iomem	*gpmc_nand_address;
-	void __iomem	*gpmc_nand_data;
-	void __iomem	*gpmc_prefetch_config1;
-	void __iomem	*gpmc_prefetch_config2;
-	void __iomem	*gpmc_prefetch_control;
-	void __iomem	*gpmc_prefetch_status;
-	void __iomem	*gpmc_ecc_config;
-	void __iomem	*gpmc_ecc_control;
-	void __iomem	*gpmc_ecc_size_config;
-	void __iomem	*gpmc_ecc1_result;
-	void __iomem	*gpmc_bch_result0;
-};
-
-extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
-extern int gpmc_get_client_irq(unsigned irq_config);
-
-extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
-extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);
-extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
-extern unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns);
-extern unsigned long gpmc_get_fclk_period(void);
-
-extern void gpmc_cs_write_reg(int cs, int idx, u32 val);
-extern u32 gpmc_cs_read_reg(int cs, int idx);
-extern int gpmc_cs_calc_divider(int cs, unsigned int sync_clk);
-extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
-extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
-extern void gpmc_cs_free(int cs);
-extern int gpmc_cs_set_reserved(int cs, int reserved);
-extern int gpmc_cs_reserved(int cs);
-extern int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
-					unsigned int u32_count, int is_write);
-extern int gpmc_prefetch_reset(int cs);
-extern void omap3_gpmc_save_context(void);
-extern void omap3_gpmc_restore_context(void);
-extern int gpmc_read_status(int cmd);
-extern int gpmc_cs_configure(int cs, int cmd, int wval);
-extern int gpmc_nand_read(int cs, int cmd);
-extern int gpmc_nand_write(int cs, int cmd, int wval);
-
-int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size);
-int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code);
-
-#ifdef CONFIG_ARCH_OMAP3
-int gpmc_init_hwecc_bch(int cs, int nsectors, int nerrors);
-int gpmc_enable_hwecc_bch(int cs, int mode, int dev_width, int nsectors,
-			  int nerrors);
-int gpmc_calculate_ecc_bch4(int cs, const u_char *dat, u_char *ecc);
-int gpmc_calculate_ecc_bch8(int cs, const u_char *dat, u_char *ecc);
-#endif /* CONFIG_ARCH_OMAP3 */
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/i2c.h b/arch/arm/plat-omap/include/plat/i2c.h
index 7c22b9e..7a9028c 100644
--- a/arch/arm/plat-omap/include/plat/i2c.h
+++ b/arch/arm/plat-omap/include/plat/i2c.h
@@ -18,11 +18,15 @@
  * 02110-1301 USA
  *
  */
-#ifndef __ASM__ARCH_OMAP_I2C_H
-#define __ASM__ARCH_OMAP_I2C_H
 
-#include <linux/i2c.h>
-#include <linux/i2c-omap.h>
+#ifndef __PLAT_OMAP_I2C_H
+#define __PLAT_OMAP_I2C_H
+
+struct i2c_board_info;
+struct omap_i2c_bus_platform_data;
+
+int omap_i2c_add_bus(struct omap_i2c_bus_platform_data *i2c_pdata,
+			int bus_id);
 
 #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
 extern int omap_register_i2c_bus(int bus_id, u32 clkrate,
@@ -37,23 +41,7 @@ static inline int omap_register_i2c_bus(int bus_id, u32 clkrate,
 }
 #endif
 
-/**
- * i2c_dev_attr - OMAP I2C controller device attributes for omap_hwmod
- * @fifo_depth: total controller FIFO size (in bytes)
- * @flags: differences in hardware support capability
- *
- * @fifo_depth represents what exists on the hardware, not what is
- * actually configured at runtime by the device driver.
- */
-struct omap_i2c_dev_attr {
-	u8	fifo_depth;
-	u32	flags;
-};
-
-void __init omap1_i2c_mux_pins(int bus_id);
-void __init omap2_i2c_mux_pins(int bus_id);
-
 struct omap_hwmod;
 int omap_i2c_reset(struct omap_hwmod *oh);
 
-#endif /* __ASM__ARCH_OMAP_I2C_H */
+#endif /* __PLAT_OMAP_I2C_H */
diff --git a/arch/arm/plat-omap/include/plat/led.h b/arch/arm/plat-omap/include/plat/led.h
deleted file mode 100644
index 25e451e..0000000
--- a/arch/arm/plat-omap/include/plat/led.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *  arch/arm/plat-omap/include/mach/led.h
- *
- *  Copyright (C) 2006 Samsung Electronics
- *  Kyungmin Park <kyungmin.park@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 ASMARM_ARCH_LED_H
-#define ASMARM_ARCH_LED_H
-
-struct omap_led_config {
-	struct led_classdev	cdev;
-	s16			gpio;
-};
-
-struct omap_led_platform_data {
-	s16			nr_leds;
-	struct omap_led_config	*leds;
-};
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/menelaus.h b/arch/arm/plat-omap/include/plat/menelaus.h
deleted file mode 100644
index 4a970ec..0000000
--- a/arch/arm/plat-omap/include/plat/menelaus.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/menelaus.h
- *
- * Functions to access Menelaus power management chip
- */
-
-#ifndef __ASM_ARCH_MENELAUS_H
-#define __ASM_ARCH_MENELAUS_H
-
-struct device;
-
-struct menelaus_platform_data {
-	int (* late_init)(struct device *dev);
-};
-
-extern int menelaus_register_mmc_callback(void (*callback)(void *data, u8 card_mask),
-					  void *data);
-extern void menelaus_unregister_mmc_callback(void);
-extern int menelaus_set_mmc_opendrain(int slot, int enable);
-extern int menelaus_set_mmc_slot(int slot, int enable, int power, int cd_on);
-
-extern int menelaus_set_vmem(unsigned int mV);
-extern int menelaus_set_vio(unsigned int mV);
-extern int menelaus_set_vmmc(unsigned int mV);
-extern int menelaus_set_vaux(unsigned int mV);
-extern int menelaus_set_vdcdc(int dcdc, unsigned int mV);
-extern int menelaus_set_slot_sel(int enable);
-extern int menelaus_get_slot_pin_states(void);
-extern int menelaus_set_vcore_sw(unsigned int mV);
-extern int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV);
-
-#define EN_VPLL_SLEEP	(1 << 7)
-#define EN_VMMC_SLEEP	(1 << 6)
-#define EN_VAUX_SLEEP	(1 << 5)
-#define EN_VIO_SLEEP	(1 << 4)
-#define EN_VMEM_SLEEP	(1 << 3)
-#define EN_DC3_SLEEP	(1 << 2)
-#define EN_DC2_SLEEP	(1 << 1)
-#define EN_VC_SLEEP	(1 << 0)
-
-extern int menelaus_set_regulator_sleep(int enable, u32 val);
-
-#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_MENELAUS)
-#define omap_has_menelaus()	1
-#else
-#define omap_has_menelaus()	0
-#endif
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
deleted file mode 100644
index 8b4e4f2..0000000
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * MMC definitions for OMAP2
- *
- * Copyright (C) 2006 Nokia 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.
- */
-
-#ifndef __OMAP2_MMC_H
-#define __OMAP2_MMC_H
-
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/mmc/host.h>
-
-#include <plat/omap_hwmod.h>
-
-#define OMAP15XX_NR_MMC		1
-#define OMAP16XX_NR_MMC		2
-#define OMAP1_MMC_SIZE		0x080
-#define OMAP1_MMC1_BASE		0xfffb7800
-#define OMAP1_MMC2_BASE		0xfffb7c00	/* omap16xx only */
-
-#define OMAP24XX_NR_MMC		2
-#define OMAP2420_MMC_SIZE	OMAP1_MMC_SIZE
-#define OMAP2_MMC1_BASE		0x4809c000
-
-#define OMAP4_MMC_REG_OFFSET	0x100
-
-#define OMAP_MMC_MAX_SLOTS	2
-
-/*
- * struct omap_mmc_dev_attr.flags possibilities
- *
- * OMAP_HSMMC_SUPPORTS_DUAL_VOLT: Some HSMMC controller instances can
- *    operate with either 1.8Vdc or 3.0Vdc card voltages; this flag
- *    should be set if this is the case.  See for example Section 22.5.3
- *    "MMC/SD/SDIO1 Bus Voltage Selection" of the OMAP34xx Multimedia
- *    Device Silicon Revision 3.1.x Revision ZR (July 2011) (SWPU223R).
- *
- * OMAP_HSMMC_BROKEN_MULTIBLOCK_READ: Multiple-block read transfers
- *    don't work correctly on some MMC controller instances on some
- *    OMAP3 SoCs; this flag should be set if this is the case.  See
- *    for example Advisory 2.1.1.128 "MMC: Multiple Block Read
- *    Operation Issue" in _OMAP3530/3525/3515/3503 Silicon Errata_
- *    Revision F (October 2010) (SPRZ278F).
- */
-#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT		BIT(0)
-#define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ	BIT(1)
-
-struct omap_mmc_dev_attr {
-	u8 flags;
-};
-
-struct omap_mmc_platform_data {
-	/* back-link to device */
-	struct device *dev;
-
-	/* number of slots per controller */
-	unsigned nr_slots:2;
-
-	/* set if your board has components or wiring that limits the
-	 * maximum frequency on the MMC bus */
-	unsigned int max_freq;
-
-	/* switch the bus to a new slot */
-	int (*switch_slot)(struct device *dev, int slot);
-	/* initialize board-specific MMC functionality, can be NULL if
-	 * not supported */
-	int (*init)(struct device *dev);
-	void (*cleanup)(struct device *dev);
-	void (*shutdown)(struct device *dev);
-
-	/* To handle board related suspend/resume functionality for MMC */
-	int (*suspend)(struct device *dev, int slot);
-	int (*resume)(struct device *dev, int slot);
-
-	/* Return context loss count due to PM states changing */
-	int (*get_context_loss_count)(struct device *dev);
-
-	/* Integrating attributes from the omap_hwmod layer */
-	u8 controller_flags;
-
-	/* Register offset deviation */
-	u16 reg_offset;
-
-	struct omap_mmc_slot_data {
-
-		/*
-		 * 4/8 wires and any additional host capabilities
-		 * need to OR'd all capabilities (ref. linux/mmc/host.h)
-		 */
-		u8  wires;	/* Used for the MMC driver on omap1 and 2420 */
-		u32 caps;	/* Used for the MMC driver on 2430 and later */
-		u32 pm_caps;	/* PM capabilities of the mmc */
-
-		/*
-		 * nomux means "standard" muxing is wrong on this board, and
-		 * that board-specific code handled it before common init logic.
-		 */
-		unsigned nomux:1;
-
-		/* switch pin can be for card detect (default) or card cover */
-		unsigned cover:1;
-
-		/* use the internal clock */
-		unsigned internal_clock:1;
-
-		/* nonremovable e.g. eMMC */
-		unsigned nonremovable:1;
-
-		/* Try to sleep or power off when possible */
-		unsigned power_saving:1;
-
-		/* If using power_saving and the MMC power is not to go off */
-		unsigned no_off:1;
-
-		/* eMMC does not handle power off when not in sleep state */
-		unsigned no_regulator_off_init:1;
-
-		/* Regulator off remapped to sleep */
-		unsigned vcc_aux_disable_is_sleep:1;
-
-		/* we can put the features above into this variable */
-#define HSMMC_HAS_PBIAS		(1 << 0)
-#define HSMMC_HAS_UPDATED_RESET	(1 << 1)
-		unsigned features;
-
-		int switch_pin;			/* gpio (card detect) */
-		int gpio_wp;			/* gpio (write protect) */
-
-		int (*set_bus_mode)(struct device *dev, int slot, int bus_mode);
-		int (*set_power)(struct device *dev, int slot,
-				 int power_on, int vdd);
-		int (*get_ro)(struct device *dev, int slot);
-		void (*remux)(struct device *dev, int slot, int power_on);
-		/* Call back before enabling / disabling regulators */
-		void (*before_set_reg)(struct device *dev, int slot,
-				       int power_on, int vdd);
-		/* Call back after enabling / disabling regulators */
-		void (*after_set_reg)(struct device *dev, int slot,
-				      int power_on, int vdd);
-		/* if we have special card, init it using this callback */
-		void (*init_card)(struct mmc_card *card);
-
-		/* return MMC cover switch state, can be NULL if not supported.
-		 *
-		 * possible return values:
-		 *   0 - closed
-		 *   1 - open
-		 */
-		int (*get_cover_state)(struct device *dev, int slot);
-
-		const char *name;
-		u32 ocr_mask;
-
-		/* Card detection IRQs */
-		int card_detect_irq;
-		int (*card_detect)(struct device *dev, int slot);
-
-		unsigned int ban_openended:1;
-
-	} slots[OMAP_MMC_MAX_SLOTS];
-};
-
-/* called from board-specific card detection service routine */
-extern void omap_mmc_notify_cover_event(struct device *dev, int slot,
-					int is_closed);
-
-#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
-void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
-				int nr_controllers);
-void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data);
-#else
-static inline void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
-				int nr_controllers)
-{
-}
-static inline void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data)
-{
-}
-#endif
-
-extern int omap_msdi_reset(struct omap_hwmod *oh);
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/multi.h b/arch/arm/plat-omap/include/plat/multi.h
deleted file mode 100644
index 324d31b..0000000
--- a/arch/arm/plat-omap/include/plat/multi.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Support for compiling in multiple OMAP processors
- *
- * Copyright (C) 2010 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifndef __PLAT_OMAP_MULTI_H
-#define __PLAT_OMAP_MULTI_H
-
-/*
- * Test if multicore OMAP support is needed
- */
-#undef MULTI_OMAP1
-#undef MULTI_OMAP2
-#undef OMAP_NAME
-
-#ifdef CONFIG_ARCH_OMAP730
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP1
-#  define MULTI_OMAP1
-# else
-#  define OMAP_NAME omap730
-# endif
-#endif
-#ifdef CONFIG_ARCH_OMAP850
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP1
-#  define MULTI_OMAP1
-# else
-#  define OMAP_NAME omap850
-# endif
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP1
-#  define MULTI_OMAP1
-# else
-#  define OMAP_NAME omap1510
-# endif
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP1
-#  define MULTI_OMAP1
-# else
-#  define OMAP_NAME omap16xx
-# endif
-#endif
-#ifdef CONFIG_ARCH_OMAP2PLUS
-# if (defined(OMAP_NAME) || defined(MULTI_OMAP1))
-#  error "OMAP1 and OMAP2PLUS can't be selected at the same time"
-# endif
-#endif
-#ifdef CONFIG_SOC_OMAP2420
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP2
-#  define MULTI_OMAP2
-# else
-#  define OMAP_NAME omap2420
-# endif
-#endif
-#ifdef CONFIG_SOC_OMAP2430
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP2
-#  define MULTI_OMAP2
-# else
-#  define OMAP_NAME omap2430
-# endif
-#endif
-#ifdef CONFIG_ARCH_OMAP3
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP2
-#  define MULTI_OMAP2
-# else
-#  define OMAP_NAME omap3
-# endif
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP2
-#  define MULTI_OMAP2
-# else
-#  define OMAP_NAME omap4
-# endif
-#endif
-
-#ifdef CONFIG_SOC_OMAP5
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP2
-#  define MULTI_OMAP2
-# else
-#  define OMAP_NAME omap5
-# endif
-#endif
-
-#ifdef CONFIG_SOC_AM33XX
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP2
-#  define MULTI_OMAP2
-# else
-#  define OMAP_NAME am33xx
-# endif
-#endif
-
-#endif	/* __PLAT_OMAP_MULTI_H */
diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h
deleted file mode 100644
index 67faa7b..0000000
--- a/arch/arm/plat-omap/include/plat/omap-pm.h
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * omap-pm.h - OMAP power management interface
- *
- * Copyright (C) 2008-2010 Texas Instruments, Inc.
- * Copyright (C) 2008-2010 Nokia Corporation
- * Paul Walmsley
- *
- * Interface developed by (in alphabetical order): Karthik Dasu, Jouni
- * Högander, Tony Lindgren, Rajendra Nayak, Sakari Poussa,
- * Veeramanikandan Raju, Anand Sawant, Igor Stoppa, Paul Walmsley,
- * Richard Woodruff
- */
-
-#ifndef ASM_ARM_ARCH_OMAP_OMAP_PM_H
-#define ASM_ARM_ARCH_OMAP_OMAP_PM_H
-
-#include <linux/device.h>
-#include <linux/cpufreq.h>
-#include <linux/clk.h>
-#include <linux/opp.h>
-
-/*
- * agent_id values for use with omap_pm_set_min_bus_tput():
- *
- * OCP_INITIATOR_AGENT is only valid for devices that can act as
- * initiators -- it represents the device's L3 interconnect
- * connection.  OCP_TARGET_AGENT represents the device's L4
- * interconnect connection.
- */
-#define OCP_TARGET_AGENT		1
-#define OCP_INITIATOR_AGENT		2
-
-/**
- * omap_pm_if_early_init - OMAP PM init code called before clock fw init
- * @mpu_opp_table: array ptr to struct omap_opp for MPU
- * @dsp_opp_table: array ptr to struct omap_opp for DSP
- * @l3_opp_table : array ptr to struct omap_opp for CORE
- *
- * Initialize anything that must be configured before the clock
- * framework starts.  The "_if_" is to avoid name collisions with the
- * PM idle-loop code.
- */
-int __init omap_pm_if_early_init(void);
-
-/**
- * omap_pm_if_init - OMAP PM init code called after clock fw init
- *
- * The main initialization code.  OPP tables are passed in here.  The
- * "_if_" is to avoid name collisions with the PM idle-loop code.
- */
-int __init omap_pm_if_init(void);
-
-/**
- * omap_pm_if_exit - OMAP PM exit code
- *
- * Exit code; currently unused.  The "_if_" is to avoid name
- * collisions with the PM idle-loop code.
- */
-void omap_pm_if_exit(void);
-
-/*
- * Device-driver-originated constraints (via board-*.c files, platform_data)
- */
-
-
-/**
- * omap_pm_set_max_mpu_wakeup_lat - set the maximum MPU wakeup latency
- * @dev: struct device * requesting the constraint
- * @t: maximum MPU wakeup latency in microseconds
- *
- * Request that the maximum interrupt latency for the MPU to be no
- * greater than @t microseconds. "Interrupt latency" in this case is
- * defined as the elapsed time from the occurrence of a hardware or
- * timer interrupt to the time when the device driver's interrupt
- * service routine has been entered by the MPU.
- *
- * It is intended that underlying PM code will use this information to
- * determine what power state to put the MPU powerdomain into, and
- * possibly the CORE powerdomain as well, since interrupt handling
- * code currently runs from SDRAM.  Advanced PM or board*.c code may
- * also configure interrupt controller priorities, OCP bus priorities,
- * CPU speed(s), etc.
- *
- * This function will not affect device wakeup latency, e.g., time
- * elapsed from when a device driver enables a hardware device with
- * clk_enable(), to when the device is ready for register access or
- * other use.  To control this device wakeup latency, use
- * omap_pm_set_max_dev_wakeup_lat()
- *
- * Multiple calls to omap_pm_set_max_mpu_wakeup_lat() will replace the
- * previous t value.  To remove the latency target for the MPU, call
- * with t = -1.
- *
- * XXX This constraint will be deprecated soon in favor of the more
- * general omap_pm_set_max_dev_wakeup_lat()
- *
- * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
- * is not satisfiable, or 0 upon success.
- */
-int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t);
-
-
-/**
- * omap_pm_set_min_bus_tput - set minimum bus throughput needed by device
- * @dev: struct device * requesting the constraint
- * @tbus_id: interconnect to operate on (OCP_{INITIATOR,TARGET}_AGENT)
- * @r: minimum throughput (in KiB/s)
- *
- * Request that the minimum data throughput on the OCP interconnect
- * attached to device @dev interconnect agent @tbus_id be no less
- * than @r KiB/s.
- *
- * It is expected that the OMAP PM or bus code will use this
- * information to set the interconnect clock to run at the lowest
- * possible speed that satisfies all current system users.  The PM or
- * bus code will adjust the estimate based on its model of the bus, so
- * device driver authors should attempt to specify an accurate
- * quantity for their device use case, and let the PM or bus code
- * overestimate the numbers as necessary to handle request/response
- * latency, other competing users on the system, etc.  On OMAP2/3, if
- * a driver requests a minimum L4 interconnect speed constraint, the
- * code will also need to add an minimum L3 interconnect speed
- * constraint,
- *
- * Multiple calls to omap_pm_set_min_bus_tput() will replace the
- * previous rate value for this device.  To remove the interconnect
- * throughput restriction for this device, call with r = 0.
- *
- * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
- * is not satisfiable, or 0 upon success.
- */
-int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r);
-
-
-/**
- * omap_pm_set_max_dev_wakeup_lat - set the maximum device enable latency
- * @req_dev: struct device * requesting the constraint, or NULL if none
- * @dev: struct device * to set the constraint one
- * @t: maximum device wakeup latency in microseconds
- *
- * Request that the maximum amount of time necessary for a device @dev
- * to become accessible after its clocks are enabled should be no
- * greater than @t microseconds.  Specifically, this represents the
- * time from when a device driver enables device clocks with
- * clk_enable(), to when the register reads and writes on the device
- * will succeed.  This function should be called before clk_disable()
- * is called, since the power state transition decision may be made
- * during clk_disable().
- *
- * It is intended that underlying PM code will use this information to
- * determine what power state to put the powerdomain enclosing this
- * device into.
- *
- * Multiple calls to omap_pm_set_max_dev_wakeup_lat() will replace the
- * previous wakeup latency values for this device.  To remove the
- * wakeup latency restriction for this device, call with t = -1.
- *
- * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
- * is not satisfiable, or 0 upon success.
- */
-int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev,
-				   long t);
-
-
-/**
- * omap_pm_set_max_sdma_lat - set the maximum system DMA transfer start latency
- * @dev: struct device *
- * @t: maximum DMA transfer start latency in microseconds
- *
- * Request that the maximum system DMA transfer start latency for this
- * device 'dev' should be no greater than 't' microseconds.  "DMA
- * transfer start latency" here is defined as the elapsed time from
- * when a device (e.g., McBSP) requests that a system DMA transfer
- * start or continue, to the time at which data starts to flow into
- * that device from the system DMA controller.
- *
- * It is intended that underlying PM code will use this information to
- * determine what power state to put the CORE powerdomain into.
- *
- * Since system DMA transfers may not involve the MPU, this function
- * will not affect MPU wakeup latency.  Use set_max_cpu_lat() to do
- * so.  Similarly, this function will not affect device wakeup latency
- * -- use set_max_dev_wakeup_lat() to affect that.
- *
- * Multiple calls to set_max_sdma_lat() will replace the previous t
- * value for this device.  To remove the maximum DMA latency for this
- * device, call with t = -1.
- *
- * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
- * is not satisfiable, or 0 upon success.
- */
-int omap_pm_set_max_sdma_lat(struct device *dev, long t);
-
-
-/**
- * omap_pm_set_min_clk_rate - set minimum clock rate requested by @dev
- * @dev: struct device * requesting the constraint
- * @clk: struct clk * to set the minimum rate constraint on
- * @r: minimum rate in Hz
- *
- * Request that the minimum clock rate on the device @dev's clk @clk
- * be no less than @r Hz.
- *
- * It is expected that the OMAP PM code will use this information to
- * find an OPP or clock setting that will satisfy this clock rate
- * constraint, along with any other applicable system constraints on
- * the clock rate or corresponding voltage, etc.
- *
- * omap_pm_set_min_clk_rate() differs from the clock code's
- * clk_set_rate() in that it considers other constraints before taking
- * any hardware action, and may change a system OPP rather than just a
- * clock rate.  clk_set_rate() is intended to be a low-level
- * interface.
- *
- * omap_pm_set_min_clk_rate() is easily open to abuse.  A better API
- * would be something like "omap_pm_set_min_dev_performance()";
- * however, there is no easily-generalizable concept of performance
- * that applies to all devices.  Only a device (and possibly the
- * device subsystem) has both the subsystem-specific knowledge, and
- * the hardware IP block-specific knowledge, to translate a constraint
- * on "touchscreen sampling accuracy" or "number of pixels or polygons
- * rendered per second" to a clock rate.  This translation can be
- * dependent on the hardware IP block's revision, or firmware version,
- * and the driver is the only code on the system that has this
- * information and can know how to translate that into a clock rate.
- *
- * The intended use-case for this function is for userspace or other
- * kernel code to communicate a particular performance requirement to
- * a subsystem; then for the subsystem to communicate that requirement
- * to something that is meaningful to the device driver; then for the
- * device driver to convert that requirement to a clock rate, and to
- * then call omap_pm_set_min_clk_rate().
- *
- * Users of this function (such as device drivers) should not simply
- * call this function with some high clock rate to ensure "high
- * performance."  Rather, the device driver should take a performance
- * constraint from its subsystem, such as "render at least X polygons
- * per second," and use some formula or table to convert that into a
- * clock rate constraint given the hardware type and hardware
- * revision.  Device drivers or subsystems should not assume that they
- * know how to make a power/performance tradeoff - some device use
- * cases may tolerate a lower-fidelity device function for lower power
- * consumption; others may demand a higher-fidelity device function,
- * no matter what the power consumption.
- *
- * Multiple calls to omap_pm_set_min_clk_rate() will replace the
- * previous rate value for the device @dev.  To remove the minimum clock
- * rate constraint for the device, call with r = 0.
- *
- * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
- * is not satisfiable, or 0 upon success.
- */
-int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r);
-
-/*
- * DSP Bridge-specific constraints
- */
-
-/**
- * omap_pm_dsp_get_opp_table - get OPP->DSP clock frequency table
- *
- * Intended for use by DSPBridge.  Returns an array of OPP->DSP clock
- * frequency entries.  The final item in the array should have .rate =
- * .opp_id = 0.
- */
-const struct omap_opp *omap_pm_dsp_get_opp_table(void);
-
-/**
- * omap_pm_dsp_set_min_opp - receive desired OPP target ID from DSP Bridge
- * @opp_id: target DSP OPP ID
- *
- * Set a minimum OPP ID for the DSP.  This is intended to be called
- * only from the DSP Bridge MPU-side driver.  Unfortunately, the only
- * information that code receives from the DSP/BIOS load estimator is the
- * target OPP ID; hence, this interface.  No return value.
- */
-void omap_pm_dsp_set_min_opp(u8 opp_id);
-
-/**
- * omap_pm_dsp_get_opp - report the current DSP OPP ID
- *
- * Report the current OPP for the DSP.  Since on OMAP3, the DSP and
- * MPU share a single voltage domain, the OPP ID returned back may
- * represent a higher DSP speed than the OPP requested via
- * omap_pm_dsp_set_min_opp().
- *
- * Returns the current VDD1 OPP ID, or 0 upon error.
- */
-u8 omap_pm_dsp_get_opp(void);
-
-
-/*
- * CPUFreq-originated constraint
- *
- * In the future, this should be handled by custom OPP clocktype
- * functions.
- */
-
-/**
- * omap_pm_cpu_get_freq_table - return a cpufreq_frequency_table array ptr
- *
- * Provide a frequency table usable by CPUFreq for the current chip/board.
- * Returns a pointer to a struct cpufreq_frequency_table array or NULL
- * upon error.
- */
-struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void);
-
-/**
- * omap_pm_cpu_set_freq - set the current minimum MPU frequency
- * @f: MPU frequency in Hz
- *
- * Set the current minimum CPU frequency.  The actual CPU frequency
- * used could end up higher if the DSP requested a higher OPP.
- * Intended to be called by plat-omap/cpu_omap.c:omap_target().  No
- * return value.
- */
-void omap_pm_cpu_set_freq(unsigned long f);
-
-/**
- * omap_pm_cpu_get_freq - report the current CPU frequency
- *
- * Returns the current MPU frequency, or 0 upon error.
- */
-unsigned long omap_pm_cpu_get_freq(void);
-
-
-/*
- * Device context loss tracking
- */
-
-/**
- * omap_pm_get_dev_context_loss_count - return count of times dev has lost ctx
- * @dev: struct device *
- *
- * This function returns the number of times that the device @dev has
- * lost its internal context.  This generally occurs on a powerdomain
- * transition to OFF.  Drivers use this as an optimization to avoid restoring
- * context if the device hasn't lost it.  To use, drivers should initially
- * call this in their context save functions and store the result.  Early in
- * the driver's context restore function, the driver should call this function
- * again, and compare the result to the stored counter.  If they differ, the
- * driver must restore device context.   If the number of context losses
- * exceeds the maximum positive integer, the function will wrap to 0 and
- * continue counting.  Returns the number of context losses for this device,
- * or negative value upon error.
- */
-int omap_pm_get_dev_context_loss_count(struct device *dev);
-
-void omap_pm_enable_off_mode(void);
-void omap_pm_disable_off_mode(void);
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/omap-secure.h b/arch/arm/plat-omap/include/plat/omap-secure.h
deleted file mode 100644
index 0e4acd2..0000000
--- a/arch/arm/plat-omap/include/plat/omap-secure.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __OMAP_SECURE_H__
-#define __OMAP_SECURE_H__
-
-#include <linux/types.h>
-
-extern int omap_secure_ram_reserve_memblock(void);
-
-#ifdef CONFIG_OMAP4_ERRATA_I688
-extern int omap_barrier_reserve_memblock(void);
-#else
-static inline void omap_barrier_reserve_memblock(void)
-{ }
-#endif
-#endif /* __OMAP_SECURE_H__ */
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 1957a85..ff9b0aa 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -30,35 +30,6 @@
  */
 #define OMAP_SERIAL_NAME	"ttyO"
 
-#define OMAP_MODE13X_SPEED	230400
-
-#define OMAP_UART_SCR_TX_EMPTY	0x08
-
-/* WER = 0x7F
- * Enable module level wakeup in WER reg
- */
-#define OMAP_UART_WER_MOD_WKUP	0X7F
-
-/* Enable XON/XOFF flow control on output */
-#define OMAP_UART_SW_TX		0x04
-
-/* Enable XON/XOFF flow control on input */
-#define OMAP_UART_SW_RX		0x04
-
-#define OMAP_UART_SYSC_RESET	0X07
-#define OMAP_UART_TCR_TRIG	0X0F
-#define OMAP_UART_SW_CLR	0XF0
-#define OMAP_UART_FIFO_CLR	0X06
-
-#define OMAP_UART_DMA_CH_FREE	-1
-
-#define OMAP_MAX_HSUART_PORTS	6
-
-#define MSR_SAVE_FLAGS		UART_MSR_ANY_DELTA
-
-#define UART_ERRATA_i202_MDR1_ACCESS	BIT(0)
-#define UART_ERRATA_i291_DMA_FORCEIDLE	BIT(1)
-
 struct omap_uart_port_info {
 	bool			dma_enabled;	/* To specify DMA Mode */
 	unsigned int		uartclk;	/* UART clock rate */
@@ -77,30 +48,4 @@ struct omap_uart_port_info {
 	void (*enable_wakeup)(struct device *, bool);
 };
 
-struct uart_omap_dma {
-	u8			uart_dma_tx;
-	u8			uart_dma_rx;
-	int			rx_dma_channel;
-	int			tx_dma_channel;
-	dma_addr_t		rx_buf_dma_phys;
-	dma_addr_t		tx_buf_dma_phys;
-	unsigned int		uart_base;
-	/*
-	 * Buffer for rx dma.It is not required for tx because the buffer
-	 * comes from port structure.
-	 */
-	unsigned char		*rx_buf;
-	unsigned int		prev_rx_dma_pos;
-	int			tx_buf_size;
-	int			tx_dma_used;
-	int			rx_dma_used;
-	spinlock_t		tx_lock;
-	spinlock_t		rx_lock;
-	/* timer to poll activity on rx dma */
-	struct timer_list	rx_timer;
-	unsigned int		rx_buf_size;
-	unsigned int		rx_poll_rate;
-	unsigned int		rx_timeout;
-};
-
 #endif /* __OMAP_SERIAL_H__ */
diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
deleted file mode 100644
index 106f506..0000000
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * omap_device headers
- *
- * Copyright (C) 2009 Nokia Corporation
- * Paul Walmsley
- *
- * Developed in collaboration with (alphabetical order): Benoit
- * Cousson, Kevin Hilman, Tony Lindgren, Rajendra Nayak, Vikram
- * Pandita, Sakari Poussa, Anand Sawant, Santosh Shilimkar, Richard
- * Woodruff
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Eventually this type of functionality should either be
- * a) implemented via arch-specific pointers in platform_device
- * or
- * b) implemented as a proper omap_bus/omap_device in Linux, no more
- *    platform_device
- *
- * omap_device differs from omap_hwmod in that it includes external
- * (e.g., board- and system-level) integration details.  omap_hwmod
- * stores hardware data that is invariant for a given OMAP chip.
- *
- * To do:
- * - GPIO integration
- * - regulator integration
- *
- */
-#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_DEVICE_H
-#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_DEVICE_H
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-#include <plat/omap_hwmod.h>
-
-extern struct dev_pm_domain omap_device_pm_domain;
-
-/* omap_device._state values */
-#define OMAP_DEVICE_STATE_UNKNOWN	0
-#define OMAP_DEVICE_STATE_ENABLED	1
-#define OMAP_DEVICE_STATE_IDLE		2
-#define OMAP_DEVICE_STATE_SHUTDOWN	3
-
-/* omap_device.flags values */
-#define OMAP_DEVICE_SUSPENDED BIT(0)
-#define OMAP_DEVICE_NO_IDLE_ON_SUSPEND BIT(1)
-
-/**
- * struct omap_device - omap_device wrapper for platform_devices
- * @pdev: platform_device
- * @hwmods: (one .. many per omap_device)
- * @hwmods_cnt: ARRAY_SIZE() of @hwmods
- * @pm_lats: ptr to an omap_device_pm_latency table
- * @pm_lats_cnt: ARRAY_SIZE() of what is passed to @pm_lats
- * @pm_lat_level: array index of the last odpl entry executed - -1 if never
- * @dev_wakeup_lat: dev wakeup latency in nanoseconds
- * @_dev_wakeup_lat_limit: dev wakeup latency limit in nsec - set by OMAP PM
- * @_state: one of OMAP_DEVICE_STATE_* (see above)
- * @flags: device flags
- * @_driver_status: one of BUS_NOTIFY_*_DRIVER from <linux/device.h>
- *
- * Integrates omap_hwmod data into Linux platform_device.
- *
- * Field names beginning with underscores are for the internal use of
- * the omap_device code.
- *
- */
-struct omap_device {
-	struct platform_device		*pdev;
-	struct omap_hwmod		**hwmods;
-	struct omap_device_pm_latency	*pm_lats;
-	u32				dev_wakeup_lat;
-	u32				_dev_wakeup_lat_limit;
-	unsigned long			_driver_status;
-	u8				pm_lats_cnt;
-	s8				pm_lat_level;
-	u8				hwmods_cnt;
-	u8				_state;
-	u8                              flags;
-};
-
-/* Device driver interface (call via platform_data fn ptrs) */
-
-int omap_device_enable(struct platform_device *pdev);
-int omap_device_idle(struct platform_device *pdev);
-int omap_device_shutdown(struct platform_device *pdev);
-
-/* Core code interface */
-
-struct platform_device *omap_device_build(const char *pdev_name, int pdev_id,
-				      struct omap_hwmod *oh, void *pdata,
-				      int pdata_len,
-				      struct omap_device_pm_latency *pm_lats,
-				      int pm_lats_cnt, int is_early_device);
-
-struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
-					 struct omap_hwmod **oh, int oh_cnt,
-					 void *pdata, int pdata_len,
-					 struct omap_device_pm_latency *pm_lats,
-					 int pm_lats_cnt, int is_early_device);
-
-struct omap_device *omap_device_alloc(struct platform_device *pdev,
-				      struct omap_hwmod **ohs, int oh_cnt,
-				      struct omap_device_pm_latency *pm_lats,
-				      int pm_lats_cnt);
-void omap_device_delete(struct omap_device *od);
-int omap_device_register(struct platform_device *pdev);
-
-void __iomem *omap_device_get_rt_va(struct omap_device *od);
-struct device *omap_device_get_by_hwmod_name(const char *oh_name);
-
-/* OMAP PM interface */
-int omap_device_align_pm_lat(struct platform_device *pdev,
-			     u32 new_wakeup_lat_limit);
-struct powerdomain *omap_device_get_pwrdm(struct omap_device *od);
-int omap_device_get_context_loss_count(struct platform_device *pdev);
-
-/* Other */
-
-int omap_device_assert_hardreset(struct platform_device *pdev,
-				 const char *name);
-int omap_device_deassert_hardreset(struct platform_device *pdev,
-				 const char *name);
-int omap_device_idle_hwmods(struct omap_device *od);
-int omap_device_enable_hwmods(struct omap_device *od);
-
-int omap_device_disable_clocks(struct omap_device *od);
-int omap_device_enable_clocks(struct omap_device *od);
-
-/*
- * Entries should be kept in latency order ascending
- *
- * deact_lat is the maximum number of microseconds required to complete
- * deactivate_func() at the device's slowest OPP.
- *
- * act_lat is the maximum number of microseconds required to complete
- * activate_func() at the device's slowest OPP.
- *
- * This will result in some suboptimal power management decisions at fast
- * OPPs, but avoids having to recompute all device power management decisions
- * if the system shifts from a fast OPP to a slow OPP (in order to meet
- * latency requirements).
- *
- * XXX should deactivate_func/activate_func() take platform_device pointers
- * rather than omap_device pointers?
- */
-struct omap_device_pm_latency {
-	u32 deactivate_lat;
-	u32 deactivate_lat_worst;
-	int (*deactivate_func)(struct omap_device *od);
-	u32 activate_lat;
-	u32 activate_lat_worst;
-	int (*activate_func)(struct omap_device *od);
-	u32 flags;
-};
-
-#define OMAP_DEVICE_LATENCY_AUTO_ADJUST BIT(1)
-
-/* Get omap_device pointer from platform_device pointer */
-static inline struct omap_device *to_omap_device(struct platform_device *pdev)
-{
-	return pdev ? pdev->archdata.od : NULL;
-}
-
-static inline
-void omap_device_disable_idle_on_suspend(struct platform_device *pdev)
-{
-	struct omap_device *od = to_omap_device(pdev);
-
-	od->flags |= OMAP_DEVICE_NO_IDLE_ON_SUSPEND;
-}
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
deleted file mode 100644
index 1db0294..0000000
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ /dev/null
@@ -1,682 +0,0 @@
-/*
- * omap_hwmod macros, structures
- *
- * Copyright (C) 2009-2011 Nokia Corporation
- * Copyright (C) 2012 Texas Instruments, Inc.
- * Paul Walmsley
- *
- * Created in collaboration with (alphabetical order): Benoît Cousson,
- * Kevin Hilman, Tony Lindgren, Rajendra Nayak, Vikram Pandita, Sakari
- * Poussa, Anand Sawant, Santosh Shilimkar, Richard Woodruff
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * These headers and macros are used to define OMAP on-chip module
- * data and their integration with other OMAP modules and Linux.
- * Copious documentation and references can also be found in the
- * omap_hwmod code, in arch/arm/mach-omap2/omap_hwmod.c (as of this
- * writing).
- *
- * To do:
- * - add interconnect error log structures
- * - add pinmuxing
- * - init_conn_id_bit (CONNID_BIT_VECTOR)
- * - implement default hwmod SMS/SDRC flags?
- * - move Linux-specific data ("non-ROM data") out
- *
- */
-#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
-#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/ioport.h>
-#include <linux/spinlock.h>
-#include <plat/cpu.h>
-
-struct omap_device;
-
-extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type1;
-extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
-extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type3;
-
-/*
- * OCP SYSCONFIG bit shifts/masks TYPE1. These are for IPs compliant
- * with the original PRCM protocol defined for OMAP2420
- */
-#define SYSC_TYPE1_MIDLEMODE_SHIFT	12
-#define SYSC_TYPE1_MIDLEMODE_MASK	(0x3 << SYSC_TYPE1_MIDLEMODE_SHIFT)
-#define SYSC_TYPE1_CLOCKACTIVITY_SHIFT	8
-#define SYSC_TYPE1_CLOCKACTIVITY_MASK	(0x3 << SYSC_TYPE1_CLOCKACTIVITY_SHIFT)
-#define SYSC_TYPE1_SIDLEMODE_SHIFT	3
-#define SYSC_TYPE1_SIDLEMODE_MASK	(0x3 << SYSC_TYPE1_SIDLEMODE_SHIFT)
-#define SYSC_TYPE1_ENAWAKEUP_SHIFT	2
-#define SYSC_TYPE1_ENAWAKEUP_MASK	(1 << SYSC_TYPE1_ENAWAKEUP_SHIFT)
-#define SYSC_TYPE1_SOFTRESET_SHIFT	1
-#define SYSC_TYPE1_SOFTRESET_MASK	(1 << SYSC_TYPE1_SOFTRESET_SHIFT)
-#define SYSC_TYPE1_AUTOIDLE_SHIFT	0
-#define SYSC_TYPE1_AUTOIDLE_MASK	(1 << SYSC_TYPE1_AUTOIDLE_SHIFT)
-
-/*
- * OCP SYSCONFIG bit shifts/masks TYPE2. These are for IPs compliant
- * with the new PRCM protocol defined for new OMAP4 IPs.
- */
-#define SYSC_TYPE2_SOFTRESET_SHIFT	0
-#define SYSC_TYPE2_SOFTRESET_MASK	(1 << SYSC_TYPE2_SOFTRESET_SHIFT)
-#define SYSC_TYPE2_SIDLEMODE_SHIFT	2
-#define SYSC_TYPE2_SIDLEMODE_MASK	(0x3 << SYSC_TYPE2_SIDLEMODE_SHIFT)
-#define SYSC_TYPE2_MIDLEMODE_SHIFT	4
-#define SYSC_TYPE2_MIDLEMODE_MASK	(0x3 << SYSC_TYPE2_MIDLEMODE_SHIFT)
-#define SYSC_TYPE2_DMADISABLE_SHIFT	16
-#define SYSC_TYPE2_DMADISABLE_MASK	(0x1 << SYSC_TYPE2_DMADISABLE_SHIFT)
-
-/*
- * OCP SYSCONFIG bit shifts/masks TYPE3.
- * This is applicable for some IPs present in AM33XX
- */
-#define SYSC_TYPE3_SIDLEMODE_SHIFT	0
-#define SYSC_TYPE3_SIDLEMODE_MASK	(0x3 << SYSC_TYPE3_SIDLEMODE_SHIFT)
-#define SYSC_TYPE3_MIDLEMODE_SHIFT	2
-#define SYSC_TYPE3_MIDLEMODE_MASK	(0x3 << SYSC_TYPE3_MIDLEMODE_SHIFT)
-
-/* OCP SYSSTATUS bit shifts/masks */
-#define SYSS_RESETDONE_SHIFT		0
-#define SYSS_RESETDONE_MASK		(1 << SYSS_RESETDONE_SHIFT)
-
-/* Master standby/slave idle mode flags */
-#define HWMOD_IDLEMODE_FORCE		(1 << 0)
-#define HWMOD_IDLEMODE_NO		(1 << 1)
-#define HWMOD_IDLEMODE_SMART		(1 << 2)
-#define HWMOD_IDLEMODE_SMART_WKUP	(1 << 3)
-
-/* modulemode control type (SW or HW) */
-#define MODULEMODE_HWCTRL		1
-#define MODULEMODE_SWCTRL		2
-
-
-/**
- * struct omap_hwmod_mux_info - hwmod specific mux configuration
- * @pads:              array of omap_device_pad entries
- * @nr_pads:           number of omap_device_pad entries
- *
- * Note that this is currently built during init as needed.
- */
-struct omap_hwmod_mux_info {
-	int				nr_pads;
-	struct omap_device_pad		*pads;
-	int				nr_pads_dynamic;
-	struct omap_device_pad		**pads_dynamic;
-	int				*irqs;
-	bool				enabled;
-};
-
-/**
- * struct omap_hwmod_irq_info - MPU IRQs used by the hwmod
- * @name: name of the IRQ channel (module local name)
- * @irq: IRQ channel ID (should be non-negative except -1 = terminator)
- *
- * @name should be something short, e.g., "tx" or "rx".  It is for use
- * by platform_get_resource_byname().  It is defined locally to the
- * hwmod.
- */
-struct omap_hwmod_irq_info {
-	const char	*name;
-	s16		irq;
-};
-
-/**
- * struct omap_hwmod_dma_info - DMA channels used by the hwmod
- * @name: name of the DMA channel (module local name)
- * @dma_req: DMA request ID (should be non-negative except -1 = terminator)
- *
- * @name should be something short, e.g., "tx" or "rx".  It is for use
- * by platform_get_resource_byname().  It is defined locally to the
- * hwmod.
- */
-struct omap_hwmod_dma_info {
-	const char	*name;
-	s16		dma_req;
-};
-
-/**
- * struct omap_hwmod_rst_info - IPs reset lines use by hwmod
- * @name: name of the reset line (module local name)
- * @rst_shift: Offset of the reset bit
- * @st_shift: Offset of the reset status bit (OMAP2/3 only)
- *
- * @name should be something short, e.g., "cpu0" or "rst". It is defined
- * locally to the hwmod.
- */
-struct omap_hwmod_rst_info {
-	const char	*name;
-	u8		rst_shift;
-	u8		st_shift;
-};
-
-/**
- * struct omap_hwmod_opt_clk - optional clocks used by this hwmod
- * @role: "sys", "32k", "tv", etc -- for use in clk_get()
- * @clk: opt clock: OMAP clock name
- * @_clk: pointer to the struct clk (filled in at runtime)
- *
- * The module's interface clock and main functional clock should not
- * be added as optional clocks.
- */
-struct omap_hwmod_opt_clk {
-	const char	*role;
-	const char	*clk;
-	struct clk	*_clk;
-};
-
-
-/* omap_hwmod_omap2_firewall.flags bits */
-#define OMAP_FIREWALL_L3		(1 << 0)
-#define OMAP_FIREWALL_L4		(1 << 1)
-
-/**
- * struct omap_hwmod_omap2_firewall - OMAP2/3 device firewall data
- * @l3_perm_bit: bit shift for L3_PM_*_PERMISSION_*
- * @l4_fw_region: L4 firewall region ID
- * @l4_prot_group: L4 protection group ID
- * @flags: (see omap_hwmod_omap2_firewall.flags macros above)
- */
-struct omap_hwmod_omap2_firewall {
-	u8 l3_perm_bit;
-	u8 l4_fw_region;
-	u8 l4_prot_group;
-	u8 flags;
-};
-
-
-/*
- * omap_hwmod_addr_space.flags bits
- *
- * ADDR_MAP_ON_INIT: Map this address space during omap_hwmod init.
- * ADDR_TYPE_RT: Address space contains module register target data.
- */
-#define ADDR_MAP_ON_INIT	(1 << 0)	/* XXX does not belong */
-#define ADDR_TYPE_RT		(1 << 1)
-
-/**
- * struct omap_hwmod_addr_space - address space handled by the hwmod
- * @name: name of the address space
- * @pa_start: starting physical address
- * @pa_end: ending physical address
- * @flags: (see omap_hwmod_addr_space.flags macros above)
- *
- * Address space doesn't necessarily follow physical interconnect
- * structure.  GPMC is one example.
- */
-struct omap_hwmod_addr_space {
-	const char *name;
-	u32 pa_start;
-	u32 pa_end;
-	u8 flags;
-};
-
-
-/*
- * omap_hwmod_ocp_if.user bits: these indicate the initiators that use this
- * interface to interact with the hwmod.  Used to add sleep dependencies
- * when the module is enabled or disabled.
- */
-#define OCP_USER_MPU			(1 << 0)
-#define OCP_USER_SDMA			(1 << 1)
-#define OCP_USER_DSP			(1 << 2)
-#define OCP_USER_IVA			(1 << 3)
-
-/* omap_hwmod_ocp_if.flags bits */
-#define OCPIF_SWSUP_IDLE		(1 << 0)
-#define OCPIF_CAN_BURST			(1 << 1)
-
-/* omap_hwmod_ocp_if._int_flags possibilities */
-#define _OCPIF_INT_FLAGS_REGISTERED	(1 << 0)
-
-
-/**
- * struct omap_hwmod_ocp_if - OCP interface data
- * @master: struct omap_hwmod that initiates OCP transactions on this link
- * @slave: struct omap_hwmod that responds to OCP transactions on this link
- * @addr: address space associated with this link
- * @clk: interface clock: OMAP clock name
- * @_clk: pointer to the interface struct clk (filled in at runtime)
- * @fw: interface firewall data
- * @width: OCP data width
- * @user: initiators using this interface (see OCP_USER_* macros above)
- * @flags: OCP interface flags (see OCPIF_* macros above)
- * @_int_flags: internal flags (see _OCPIF_INT_FLAGS* macros above)
- *
- * It may also be useful to add a tag_cnt field for OCP2.x devices.
- *
- * Parameter names beginning with an underscore are managed internally by
- * the omap_hwmod code and should not be set during initialization.
- */
-struct omap_hwmod_ocp_if {
-	struct omap_hwmod		*master;
-	struct omap_hwmod		*slave;
-	struct omap_hwmod_addr_space	*addr;
-	const char			*clk;
-	struct clk			*_clk;
-	union {
-		struct omap_hwmod_omap2_firewall omap2;
-	}				fw;
-	u8				width;
-	u8				user;
-	u8				flags;
-	u8				_int_flags;
-};
-
-
-/* Macros for use in struct omap_hwmod_sysconfig */
-
-/* Flags for use in omap_hwmod_sysconfig.idlemodes */
-#define MASTER_STANDBY_SHIFT	4
-#define SLAVE_IDLE_SHIFT	0
-#define SIDLE_FORCE		(HWMOD_IDLEMODE_FORCE << SLAVE_IDLE_SHIFT)
-#define SIDLE_NO		(HWMOD_IDLEMODE_NO << SLAVE_IDLE_SHIFT)
-#define SIDLE_SMART		(HWMOD_IDLEMODE_SMART << SLAVE_IDLE_SHIFT)
-#define SIDLE_SMART_WKUP	(HWMOD_IDLEMODE_SMART_WKUP << SLAVE_IDLE_SHIFT)
-#define MSTANDBY_FORCE		(HWMOD_IDLEMODE_FORCE << MASTER_STANDBY_SHIFT)
-#define MSTANDBY_NO		(HWMOD_IDLEMODE_NO << MASTER_STANDBY_SHIFT)
-#define MSTANDBY_SMART		(HWMOD_IDLEMODE_SMART << MASTER_STANDBY_SHIFT)
-#define MSTANDBY_SMART_WKUP	(HWMOD_IDLEMODE_SMART_WKUP << MASTER_STANDBY_SHIFT)
-
-/* omap_hwmod_sysconfig.sysc_flags capability flags */
-#define SYSC_HAS_AUTOIDLE	(1 << 0)
-#define SYSC_HAS_SOFTRESET	(1 << 1)
-#define SYSC_HAS_ENAWAKEUP	(1 << 2)
-#define SYSC_HAS_EMUFREE	(1 << 3)
-#define SYSC_HAS_CLOCKACTIVITY	(1 << 4)
-#define SYSC_HAS_SIDLEMODE	(1 << 5)
-#define SYSC_HAS_MIDLEMODE	(1 << 6)
-#define SYSS_HAS_RESET_STATUS	(1 << 7)
-#define SYSC_NO_CACHE		(1 << 8)  /* XXX SW flag, belongs elsewhere */
-#define SYSC_HAS_RESET_STATUS	(1 << 9)
-#define SYSC_HAS_DMADISABLE	(1 << 10)
-
-/* omap_hwmod_sysconfig.clockact flags */
-#define CLOCKACT_TEST_BOTH	0x0
-#define CLOCKACT_TEST_MAIN	0x1
-#define CLOCKACT_TEST_ICLK	0x2
-#define CLOCKACT_TEST_NONE	0x3
-
-/**
- * struct omap_hwmod_sysc_fields - hwmod OCP_SYSCONFIG register field offsets.
- * @midle_shift: Offset of the midle bit
- * @clkact_shift: Offset of the clockactivity bit
- * @sidle_shift: Offset of the sidle bit
- * @enwkup_shift: Offset of the enawakeup bit
- * @srst_shift: Offset of the softreset bit
- * @autoidle_shift: Offset of the autoidle bit
- * @dmadisable_shift: Offset of the dmadisable bit
- */
-struct omap_hwmod_sysc_fields {
-	u8 midle_shift;
-	u8 clkact_shift;
-	u8 sidle_shift;
-	u8 enwkup_shift;
-	u8 srst_shift;
-	u8 autoidle_shift;
-	u8 dmadisable_shift;
-};
-
-/**
- * struct omap_hwmod_class_sysconfig - hwmod class OCP_SYS* data
- * @rev_offs: IP block revision register offset (from module base addr)
- * @sysc_offs: OCP_SYSCONFIG register offset (from module base addr)
- * @syss_offs: OCP_SYSSTATUS register offset (from module base addr)
- * @srst_udelay: Delay needed after doing a softreset in usecs
- * @idlemodes: One or more of {SIDLE,MSTANDBY}_{OFF,FORCE,SMART}
- * @sysc_flags: SYS{C,S}_HAS* flags indicating SYSCONFIG bits supported
- * @clockact: the default value of the module CLOCKACTIVITY bits
- *
- * @clockact describes to the module which clocks are likely to be
- * disabled when the PRCM issues its idle request to the module.  Some
- * modules have separate clockdomains for the interface clock and main
- * functional clock, and can check whether they should acknowledge the
- * idle request based on the internal module functionality that has
- * been associated with the clocks marked in @clockact.  This field is
- * only used if HWMOD_SET_DEFAULT_CLOCKACT is set (see below)
- *
- * @sysc_fields: structure containing the offset positions of various bits in
- * SYSCONFIG register. This can be populated using omap_hwmod_sysc_type1 or
- * omap_hwmod_sysc_type2 defined in omap_hwmod_common_data.c depending on
- * whether the device ip is compliant with the original PRCM protocol
- * defined for OMAP2420 or the new PRCM protocol for new OMAP4 IPs.
- * If the device follows a different scheme for the sysconfig register ,
- * then this field has to be populated with the correct offset structure.
- */
-struct omap_hwmod_class_sysconfig {
-	u32 rev_offs;
-	u32 sysc_offs;
-	u32 syss_offs;
-	u16 sysc_flags;
-	struct omap_hwmod_sysc_fields *sysc_fields;
-	u8 srst_udelay;
-	u8 idlemodes;
-	u8 clockact;
-};
-
-/**
- * struct omap_hwmod_omap2_prcm - OMAP2/3-specific PRCM data
- * @module_offs: PRCM submodule offset from the start of the PRM/CM
- * @prcm_reg_id: PRCM register ID (e.g., 3 for CM_AUTOIDLE3)
- * @module_bit: register bit shift for AUTOIDLE, WKST, WKEN, GRPSEL regs
- * @idlest_reg_id: IDLEST register ID (e.g., 3 for CM_IDLEST3)
- * @idlest_idle_bit: register bit shift for CM_IDLEST slave idle bit
- * @idlest_stdby_bit: register bit shift for CM_IDLEST master standby bit
- *
- * @prcm_reg_id and @module_bit are specific to the AUTOIDLE, WKST,
- * WKEN, GRPSEL registers.  In an ideal world, no extra information
- * would be needed for IDLEST information, but alas, there are some
- * exceptions, so @idlest_reg_id, @idlest_idle_bit, @idlest_stdby_bit
- * are needed for the IDLEST registers (c.f. 2430 I2CHS, 3430 USBHOST)
- */
-struct omap_hwmod_omap2_prcm {
-	s16 module_offs;
-	u8 prcm_reg_id;
-	u8 module_bit;
-	u8 idlest_reg_id;
-	u8 idlest_idle_bit;
-	u8 idlest_stdby_bit;
-};
-
-/*
- * Possible values for struct omap_hwmod_omap4_prcm.flags
- *
- * HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT: Some IP blocks don't have a PRCM
- *     module-level context loss register associated with them; this
- *     flag bit should be set in those cases
- */
-#define HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT		(1 << 0)
-
-/**
- * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
- * @clkctrl_reg: PRCM address of the clock control register
- * @rstctrl_reg: address of the XXX_RSTCTRL register located in the PRM
- * @lostcontext_mask: bitmask for selecting bits from RM_*_CONTEXT register
- * @rstst_reg: (AM33XX only) address of the XXX_RSTST register in the PRM
- * @submodule_wkdep_bit: bit shift of the WKDEP range
- * @flags: PRCM register capabilities for this IP block
- *
- * If @lostcontext_mask is not defined, context loss check code uses
- * whole register without masking. @lostcontext_mask should only be
- * defined in cases where @context_offs register is shared by two or
- * more hwmods.
- */
-struct omap_hwmod_omap4_prcm {
-	u16		clkctrl_offs;
-	u16		rstctrl_offs;
-	u16		rstst_offs;
-	u16		context_offs;
-	u32		lostcontext_mask;
-	u8		submodule_wkdep_bit;
-	u8		modulemode;
-	u8		flags;
-};
-
-
-/*
- * omap_hwmod.flags definitions
- *
- * HWMOD_SWSUP_SIDLE: omap_hwmod code should manually bring module in and out
- *     of idle, rather than relying on module smart-idle
- * HWMOD_SWSUP_MSTDBY: omap_hwmod code should manually bring module in and out
- *     of standby, rather than relying on module smart-standby
- * HWMOD_INIT_NO_RESET: don't reset this module at boot - important for
- *     SDRAM controller, etc. XXX probably belongs outside the main hwmod file
- *     XXX Should be HWMOD_SETUP_NO_RESET
- * HWMOD_INIT_NO_IDLE: don't idle this module at boot - important for SDRAM
- *     controller, etc. XXX probably belongs outside the main hwmod file
- *     XXX Should be HWMOD_SETUP_NO_IDLE
- * HWMOD_NO_OCP_AUTOIDLE: disable module autoidle (OCP_SYSCONFIG.AUTOIDLE)
- *     when module is enabled, rather than the default, which is to
- *     enable autoidle
- * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup
- * HWMOD_NO_IDLEST: this module does not have idle status - this is the case
- *     only for few initiator modules on OMAP2 & 3.
- * HWMOD_CONTROL_OPT_CLKS_IN_RESET: Enable all optional clocks during reset.
- *     This is needed for devices like DSS that require optional clocks enabled
- *     in order to complete the reset. Optional clocks will be disabled
- *     again after the reset.
- * HWMOD_16BIT_REG: Module has 16bit registers
- * HWMOD_EXT_OPT_MAIN_CLK: The only main functional clock source for
- *     this IP block comes from an off-chip source and is not always
- *     enabled.  This prevents the hwmod code from being able to
- *     enable and reset the IP block early.  XXX Eventually it should
- *     be possible to query the clock framework for this information.
- */
-#define HWMOD_SWSUP_SIDLE			(1 << 0)
-#define HWMOD_SWSUP_MSTANDBY			(1 << 1)
-#define HWMOD_INIT_NO_RESET			(1 << 2)
-#define HWMOD_INIT_NO_IDLE			(1 << 3)
-#define HWMOD_NO_OCP_AUTOIDLE			(1 << 4)
-#define HWMOD_SET_DEFAULT_CLOCKACT		(1 << 5)
-#define HWMOD_NO_IDLEST				(1 << 6)
-#define HWMOD_CONTROL_OPT_CLKS_IN_RESET		(1 << 7)
-#define HWMOD_16BIT_REG				(1 << 8)
-#define HWMOD_EXT_OPT_MAIN_CLK			(1 << 9)
-
-/*
- * omap_hwmod._int_flags definitions
- * These are for internal use only and are managed by the omap_hwmod code.
- *
- * _HWMOD_NO_MPU_PORT: no path exists for the MPU to write to this module
- * _HWMOD_WAKEUP_ENABLED: set when the omap_hwmod code has enabled ENAWAKEUP
- * _HWMOD_SYSCONFIG_LOADED: set when the OCP_SYSCONFIG value has been cached
- * _HWMOD_SKIP_ENABLE: set if hwmod enabled during init (HWMOD_INIT_NO_IDLE) -
- *     causes the first call to _enable() to only update the pinmux
- */
-#define _HWMOD_NO_MPU_PORT			(1 << 0)
-#define _HWMOD_WAKEUP_ENABLED			(1 << 1)
-#define _HWMOD_SYSCONFIG_LOADED			(1 << 2)
-#define _HWMOD_SKIP_ENABLE			(1 << 3)
-
-/*
- * omap_hwmod._state definitions
- *
- * INITIALIZED: reset (optionally), initialized, enabled, disabled
- *              (optionally)
- *
- *
- */
-#define _HWMOD_STATE_UNKNOWN			0
-#define _HWMOD_STATE_REGISTERED			1
-#define _HWMOD_STATE_CLKS_INITED		2
-#define _HWMOD_STATE_INITIALIZED		3
-#define _HWMOD_STATE_ENABLED			4
-#define _HWMOD_STATE_IDLE			5
-#define _HWMOD_STATE_DISABLED			6
-
-/**
- * struct omap_hwmod_class - the type of an IP block
- * @name: name of the hwmod_class
- * @sysc: device SYSCONFIG/SYSSTATUS register data
- * @rev: revision of the IP class
- * @pre_shutdown: ptr to fn to be executed immediately prior to device shutdown
- * @reset: ptr to fn to be executed in place of the standard hwmod reset fn
- *
- * Represent the class of a OMAP hardware "modules" (e.g. timer,
- * smartreflex, gpio, uart...)
- *
- * @pre_shutdown is a function that will be run immediately before
- * hwmod clocks are disabled, etc.  It is intended for use for hwmods
- * like the MPU watchdog, which cannot be disabled with the standard
- * omap_hwmod_shutdown().  The function should return 0 upon success,
- * or some negative error upon failure.  Returning an error will cause
- * omap_hwmod_shutdown() to abort the device shutdown and return an
- * error.
- *
- * If @reset is defined, then the function it points to will be
- * executed in place of the standard hwmod _reset() code in
- * mach-omap2/omap_hwmod.c.  This is needed for IP blocks which have
- * unusual reset sequences - usually processor IP blocks like the IVA.
- */
-struct omap_hwmod_class {
-	const char				*name;
-	struct omap_hwmod_class_sysconfig	*sysc;
-	u32					rev;
-	int					(*pre_shutdown)(struct omap_hwmod *oh);
-	int					(*reset)(struct omap_hwmod *oh);
-};
-
-/**
- * struct omap_hwmod_link - internal structure linking hwmods with ocp_ifs
- * @ocp_if: OCP interface structure record pointer
- * @node: list_head pointing to next struct omap_hwmod_link in a list
- */
-struct omap_hwmod_link {
-	struct omap_hwmod_ocp_if	*ocp_if;
-	struct list_head		node;
-};
-
-/**
- * struct omap_hwmod - integration data for OMAP hardware "modules" (IP blocks)
- * @name: name of the hwmod
- * @class: struct omap_hwmod_class * to the class of this hwmod
- * @od: struct omap_device currently associated with this hwmod (internal use)
- * @mpu_irqs: ptr to an array of MPU IRQs
- * @sdma_reqs: ptr to an array of System DMA request IDs
- * @prcm: PRCM data pertaining to this hwmod
- * @main_clk: main clock: OMAP clock name
- * @_clk: pointer to the main struct clk (filled in at runtime)
- * @opt_clks: other device clocks that drivers can request (0..*)
- * @voltdm: pointer to voltage domain (filled in at runtime)
- * @dev_attr: arbitrary device attributes that can be passed to the driver
- * @_sysc_cache: internal-use hwmod flags
- * @_mpu_rt_va: cached register target start address (internal use)
- * @_mpu_port: cached MPU register target slave (internal use)
- * @opt_clks_cnt: number of @opt_clks
- * @master_cnt: number of @master entries
- * @slaves_cnt: number of @slave entries
- * @response_lat: device OCP response latency (in interface clock cycles)
- * @_int_flags: internal-use hwmod flags
- * @_state: internal-use hwmod state
- * @_postsetup_state: internal-use state to leave the hwmod in after _setup()
- * @flags: hwmod flags (documented below)
- * @_lock: spinlock serializing operations on this hwmod
- * @node: list node for hwmod list (internal use)
- *
- * @main_clk refers to this module's "main clock," which for our
- * purposes is defined as "the functional clock needed for register
- * accesses to complete."  Modules may not have a main clock if the
- * interface clock also serves as a main clock.
- *
- * Parameter names beginning with an underscore are managed internally by
- * the omap_hwmod code and should not be set during initialization.
- *
- * @masters and @slaves are now deprecated.
- */
-struct omap_hwmod {
-	const char			*name;
-	struct omap_hwmod_class		*class;
-	struct omap_device		*od;
-	struct omap_hwmod_mux_info	*mux;
-	struct omap_hwmod_irq_info	*mpu_irqs;
-	struct omap_hwmod_dma_info	*sdma_reqs;
-	struct omap_hwmod_rst_info	*rst_lines;
-	union {
-		struct omap_hwmod_omap2_prcm omap2;
-		struct omap_hwmod_omap4_prcm omap4;
-	}				prcm;
-	const char			*main_clk;
-	struct clk			*_clk;
-	struct omap_hwmod_opt_clk	*opt_clks;
-	char				*clkdm_name;
-	struct clockdomain		*clkdm;
-	struct list_head		master_ports; /* connect to *_IA */
-	struct list_head		slave_ports; /* connect to *_TA */
-	void				*dev_attr;
-	u32				_sysc_cache;
-	void __iomem			*_mpu_rt_va;
-	spinlock_t			_lock;
-	struct list_head		node;
-	struct omap_hwmod_ocp_if	*_mpu_port;
-	u16				flags;
-	u8				response_lat;
-	u8				rst_lines_cnt;
-	u8				opt_clks_cnt;
-	u8				masters_cnt;
-	u8				slaves_cnt;
-	u8				hwmods_cnt;
-	u8				_int_flags;
-	u8				_state;
-	u8				_postsetup_state;
-};
-
-struct omap_hwmod *omap_hwmod_lookup(const char *name);
-int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
-			void *data);
-
-int __init omap_hwmod_setup_one(const char *name);
-
-int omap_hwmod_enable(struct omap_hwmod *oh);
-int omap_hwmod_idle(struct omap_hwmod *oh);
-int omap_hwmod_shutdown(struct omap_hwmod *oh);
-
-int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name);
-int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name);
-int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name);
-
-int omap_hwmod_enable_clocks(struct omap_hwmod *oh);
-int omap_hwmod_disable_clocks(struct omap_hwmod *oh);
-
-int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode);
-int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle);
-
-int omap_hwmod_reset(struct omap_hwmod *oh);
-void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
-
-void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs);
-u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs);
-int omap_hwmod_softreset(struct omap_hwmod *oh);
-
-int omap_hwmod_count_resources(struct omap_hwmod *oh);
-int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
-int omap_hwmod_fill_dma_resources(struct omap_hwmod *oh, struct resource *res);
-int omap_hwmod_get_resource_byname(struct omap_hwmod *oh, unsigned int type,
-				   const char *name, struct resource *res);
-
-struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh);
-void __iomem *omap_hwmod_get_mpu_rt_va(struct omap_hwmod *oh);
-
-int omap_hwmod_add_initiator_dep(struct omap_hwmod *oh,
-				 struct omap_hwmod *init_oh);
-int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh,
-				 struct omap_hwmod *init_oh);
-
-int omap_hwmod_enable_wakeup(struct omap_hwmod *oh);
-int omap_hwmod_disable_wakeup(struct omap_hwmod *oh);
-
-int omap_hwmod_for_each_by_class(const char *classname,
-				 int (*fn)(struct omap_hwmod *oh,
-					   void *user),
-				 void *user);
-
-int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);
-int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
-
-int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
-
-int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx);
-
-extern void __init omap_hwmod_init(void);
-
-const char *omap_hwmod_get_main_clk(struct omap_hwmod *oh);
-
-/*
- * Chip variant-specific hwmod init routines - XXX should be converted
- * to use initcalls once the initial boot ordering is straightened out
- */
-extern int omap2420_hwmod_init(void);
-extern int omap2430_hwmod_init(void);
-extern int omap3xxx_hwmod_init(void);
-extern int omap44xx_hwmod_init(void);
-extern int am33xx_hwmod_init(void);
-
-extern int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois);
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h
deleted file mode 100644
index 267f43b..0000000
--- a/arch/arm/plat-omap/include/plat/prcm.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/prcm.h
- *
- * Access definations for use in OMAP24XX clock and power management
- *
- * Copyright (C) 2005 Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * XXX This file is deprecated.  The PRCM is an OMAP2+-only subsystem,
- * so this file doesn't belong in plat-omap/include/plat.  Please
- * do not add anything new to this file.
- */
-
-#ifndef __ASM_ARM_ARCH_OMAP_PRCM_H
-#define __ASM_ARM_ARCH_OMAP_PRCM_H
-
-u32 omap_prcm_get_reset_sources(void);
-int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
-			 const char *name);
-
-#endif
-
-
-
diff --git a/arch/arm/plat-omap/include/plat/sdrc.h b/arch/arm/plat-omap/include/plat/sdrc.h
deleted file mode 100644
index 36d6a76..0000000
--- a/arch/arm/plat-omap/include/plat/sdrc.h
+++ /dev/null
@@ -1,164 +0,0 @@
-#ifndef ____ASM_ARCH_SDRC_H
-#define ____ASM_ARCH_SDRC_H
-
-/*
- * OMAP2/3 SDRC/SMS register definitions
- *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2008 Nokia Corporation
- *
- * Tony Lindgren
- * Paul Walmsley
- * Richard Woodruff
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-
-/* SDRC register offsets - read/write with sdrc_{read,write}_reg() */
-
-#define SDRC_SYSCONFIG		0x010
-#define SDRC_CS_CFG		0x040
-#define SDRC_SHARING		0x044
-#define SDRC_ERR_TYPE		0x04C
-#define SDRC_DLLA_CTRL		0x060
-#define SDRC_DLLA_STATUS	0x064
-#define SDRC_DLLB_CTRL		0x068
-#define SDRC_DLLB_STATUS	0x06C
-#define SDRC_POWER		0x070
-#define SDRC_MCFG_0		0x080
-#define SDRC_MR_0		0x084
-#define SDRC_EMR2_0		0x08c
-#define SDRC_ACTIM_CTRL_A_0	0x09c
-#define SDRC_ACTIM_CTRL_B_0	0x0a0
-#define SDRC_RFR_CTRL_0		0x0a4
-#define SDRC_MANUAL_0		0x0a8
-#define SDRC_MCFG_1		0x0B0
-#define SDRC_MR_1		0x0B4
-#define SDRC_EMR2_1		0x0BC
-#define SDRC_ACTIM_CTRL_A_1	0x0C4
-#define SDRC_ACTIM_CTRL_B_1	0x0C8
-#define SDRC_RFR_CTRL_1		0x0D4
-#define SDRC_MANUAL_1		0x0D8
-
-#define SDRC_POWER_AUTOCOUNT_SHIFT	8
-#define SDRC_POWER_AUTOCOUNT_MASK	(0xffff << SDRC_POWER_AUTOCOUNT_SHIFT)
-#define SDRC_POWER_CLKCTRL_SHIFT	4
-#define SDRC_POWER_CLKCTRL_MASK		(0x3 << SDRC_POWER_CLKCTRL_SHIFT)
-#define SDRC_SELF_REFRESH_ON_AUTOCOUNT	(0x2 << SDRC_POWER_CLKCTRL_SHIFT)
-
-/*
- * These values represent the number of memory clock cycles between
- * autorefresh initiation.  They assume 1 refresh per 64 ms (JEDEC), 8192
- * rows per device, and include a subtraction of a 50 cycle window in the
- * event that the autorefresh command is delayed due to other SDRC activity.
- * The '| 1' sets the ARE field to send one autorefresh when the autorefresh
- * counter reaches 0.
- *
- * These represent optimal values for common parts, it won't work for all.
- * As long as you scale down, most parameters are still work, they just
- * become sub-optimal. The RFR value goes in the opposite direction. If you
- * don't adjust it down as your clock period increases the refresh interval
- * will not be met. Setting all parameters for complete worst case may work,
- * but may cut memory performance by 2x. Due to errata the DLLs need to be
- * unlocked and their value needs run time calibration.	A dynamic call is
- * need for that as no single right value exists acorss production samples.
- *
- * Only the FULL speed values are given. Current code is such that rate
- * changes must be made at DPLLoutx2. The actual value adjustment for low
- * frequency operation will be handled by omap_set_performance()
- *
- * By having the boot loader boot up in the fastest L4 speed available likely
- * will result in something which you can switch between.
- */
-#define SDRC_RFR_CTRL_165MHz	(0x00044c00 | 1)
-#define SDRC_RFR_CTRL_133MHz	(0x0003de00 | 1)
-#define SDRC_RFR_CTRL_100MHz	(0x0002da01 | 1)
-#define SDRC_RFR_CTRL_110MHz	(0x0002da01 | 1) /* Need to calc */
-#define SDRC_RFR_CTRL_BYPASS	(0x00005000 | 1) /* Need to calc */
-
-
-/*
- * SMS register access
- */
-
-#define OMAP242X_SMS_REGADDR(reg)					\
-		(void __iomem *)OMAP2_L3_IO_ADDRESS(OMAP2420_SMS_BASE + reg)
-#define OMAP243X_SMS_REGADDR(reg)					\
-		(void __iomem *)OMAP2_L3_IO_ADDRESS(OMAP243X_SMS_BASE + reg)
-#define OMAP343X_SMS_REGADDR(reg)					\
-		(void __iomem *)OMAP2_L3_IO_ADDRESS(OMAP343X_SMS_BASE + reg)
-
-/* SMS register offsets - read/write with sms_{read,write}_reg() */
-
-#define SMS_SYSCONFIG			0x010
-#define SMS_ROT_CONTROL(context)	(0x180 + 0x10 * context)
-#define SMS_ROT_SIZE(context)		(0x184 + 0x10 * context)
-#define SMS_ROT_PHYSICAL_BA(context)	(0x188 + 0x10 * context)
-/* REVISIT: fill in other SMS registers here */
-
-
-#ifndef __ASSEMBLER__
-
-/**
- * struct omap_sdrc_params - SDRC parameters for a given SDRC clock rate
- * @rate: SDRC clock rate (in Hz)
- * @actim_ctrla: Value to program to SDRC_ACTIM_CTRLA for this rate
- * @actim_ctrlb: Value to program to SDRC_ACTIM_CTRLB for this rate
- * @rfr_ctrl: Value to program to SDRC_RFR_CTRL for this rate
- * @mr: Value to program to SDRC_MR for this rate
- *
- * This structure holds a pre-computed set of register values for the
- * SDRC for a given SDRC clock rate and SDRAM chip.  These are
- * intended to be pre-computed and specified in an array in the board-*.c
- * files.  The structure is keyed off the 'rate' field.
- */
-struct omap_sdrc_params {
-	unsigned long rate;
-	u32 actim_ctrla;
-	u32 actim_ctrlb;
-	u32 rfr_ctrl;
-	u32 mr;
-};
-
-#ifdef CONFIG_SOC_HAS_OMAP2_SDRC
-void omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
-			    struct omap_sdrc_params *sdrc_cs1);
-#else
-static inline void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
-					  struct omap_sdrc_params *sdrc_cs1) {};
-#endif
-
-int omap2_sdrc_get_params(unsigned long r,
-			  struct omap_sdrc_params **sdrc_cs0,
-			  struct omap_sdrc_params **sdrc_cs1);
-void omap2_sms_save_context(void);
-void omap2_sms_restore_context(void);
-
-void omap2_sms_write_rot_control(u32 val, unsigned ctx);
-void omap2_sms_write_rot_size(u32 val, unsigned ctx);
-void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx);
-
-#ifdef CONFIG_ARCH_OMAP2
-
-struct memory_timings {
-	u32 m_type;		/* ddr = 1, sdr = 0 */
-	u32 dll_mode;		/* use lock mode = 1, unlock mode = 0 */
-	u32 slow_dll_ctrl;	/* unlock mode, dll value for slow speed */
-	u32 fast_dll_ctrl;	/* unlock mode, dll value for fast speed */
-	u32 base_cs;		/* base chip select to use for calculations */
-};
-
-extern void omap2xxx_sdrc_init_params(u32 force_lock_to_unlock_mode);
-struct omap_sdrc_params *rx51_get_sdram_timings(void);
-
-u32 omap2xxx_sdrc_dll_is_unlocked(void);
-u32 omap2xxx_sdrc_reprogram(u32 level, u32 force);
-
-#endif  /* CONFIG_ARCH_OMAP2 */
-
-#endif  /* __ASSEMBLER__ */
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h
deleted file mode 100644
index 65fce44..0000000
--- a/arch/arm/plat-omap/include/plat/serial.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/serial.h
- *
- * Copyright (C) 2009 Texas Instruments
- * Added OMAP4 support- Santosh Shilimkar <santosh.shilimkar@ti.com>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ASM_ARCH_SERIAL_H
-#define __ASM_ARCH_SERIAL_H
-
-#include <linux/init.h>
-
-/*
- * Memory entry used for the DEBUG_LL UART configuration, relative to
- * start of RAM. See also uncompress.h and debug-macro.S.
- *
- * Note that using a memory location for storing the UART configuration
- * has at least two limitations:
- *
- * 1. Kernel uncompress code cannot overlap OMAP_UART_INFO as the
- *    uncompress code could then partially overwrite itself
- * 2. We assume printascii is called at least once before paging_init,
- *    and addruart has a chance to read OMAP_UART_INFO
- */
-#define OMAP_UART_INFO_OFS	0x3ffc
-
-/* OMAP1 serial ports */
-#define OMAP1_UART1_BASE	0xfffb0000
-#define OMAP1_UART2_BASE	0xfffb0800
-#define OMAP1_UART3_BASE	0xfffb9800
-
-/* OMAP2 serial ports */
-#define OMAP2_UART1_BASE	0x4806a000
-#define OMAP2_UART2_BASE	0x4806c000
-#define OMAP2_UART3_BASE	0x4806e000
-
-/* OMAP3 serial ports */
-#define OMAP3_UART1_BASE	OMAP2_UART1_BASE
-#define OMAP3_UART2_BASE	OMAP2_UART2_BASE
-#define OMAP3_UART3_BASE	0x49020000
-#define OMAP3_UART4_BASE	0x49042000	/* Only on 36xx */
-#define OMAP3_UART4_AM35XX_BASE	0x4809E000	/* Only on AM35xx */
-
-/* OMAP4 serial ports */
-#define OMAP4_UART1_BASE	OMAP2_UART1_BASE
-#define OMAP4_UART2_BASE	OMAP2_UART2_BASE
-#define OMAP4_UART3_BASE	0x48020000
-#define OMAP4_UART4_BASE	0x4806e000
-
-/* TI81XX serial ports */
-#define TI81XX_UART1_BASE	0x48020000
-#define TI81XX_UART2_BASE	0x48022000
-#define TI81XX_UART3_BASE	0x48024000
-
-/* AM3505/3517 UART4 */
-#define AM35XX_UART4_BASE	0x4809E000	/* Only on AM3505/3517 */
-
-/* AM33XX serial port */
-#define AM33XX_UART1_BASE	0x44E09000
-
-/* OMAP5 serial ports */
-#define OMAP5_UART1_BASE	OMAP2_UART1_BASE
-#define OMAP5_UART2_BASE	OMAP2_UART2_BASE
-#define OMAP5_UART3_BASE	OMAP4_UART3_BASE
-#define OMAP5_UART4_BASE	OMAP4_UART4_BASE
-#define OMAP5_UART5_BASE	0x48066000
-#define OMAP5_UART6_BASE	0x48068000
-
-/* External port on Zoom2/3 */
-#define ZOOM_UART_BASE		0x10000000
-#define ZOOM_UART_VIRT		0xfa400000
-
-#define OMAP_PORT_SHIFT		2
-#define OMAP7XX_PORT_SHIFT	0
-#define ZOOM_PORT_SHIFT		1
-
-#define OMAP1510_BASE_BAUD	(12000000/16)
-#define OMAP16XX_BASE_BAUD	(48000000/16)
-#define OMAP24XX_BASE_BAUD	(48000000/16)
-
-/*
- * DEBUG_LL port encoding stored into the UART1 scratchpad register by
- * decomp_setup in uncompress.h
- */
-#define OMAP1UART1		11
-#define OMAP1UART2		12
-#define OMAP1UART3		13
-#define OMAP2UART1		21
-#define OMAP2UART2		22
-#define OMAP2UART3		23
-#define OMAP3UART1		OMAP2UART1
-#define OMAP3UART2		OMAP2UART2
-#define OMAP3UART3		33
-#define OMAP3UART4		34		/* Only on 36xx */
-#define OMAP4UART1		OMAP2UART1
-#define OMAP4UART2		OMAP2UART2
-#define OMAP4UART3		43
-#define OMAP4UART4		44
-#define TI81XXUART1		81
-#define TI81XXUART2		82
-#define TI81XXUART3		83
-#define AM33XXUART1		84
-#define OMAP5UART3		OMAP4UART3
-#define OMAP5UART4		OMAP4UART4
-#define ZOOM_UART		95		/* Only on zoom2/3 */
-
-/* This is only used by 8250.c for omap1510 */
-#define is_omap_port(pt)	({int __ret = 0;			\
-			if ((pt)->port.mapbase == OMAP1_UART1_BASE ||	\
-			    (pt)->port.mapbase == OMAP1_UART2_BASE ||	\
-			    (pt)->port.mapbase == OMAP1_UART3_BASE)	\
-				__ret = 1;				\
-			__ret;						\
-			})
-
-#ifndef __ASSEMBLER__
-
-struct omap_board_data;
-struct omap_uart_port_info;
-
-extern void omap_serial_init(void);
-extern void omap_serial_board_init(struct omap_uart_port_info *platform_data);
-extern void omap_serial_init_port(struct omap_board_data *bdata,
-		struct omap_uart_port_info *platform_data);
-#endif
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/sram.h b/arch/arm/plat-omap/include/plat/sram.h
index 227ae26..ba45250 100644
--- a/arch/arm/plat-omap/include/plat/sram.h
+++ b/arch/arm/plat-omap/include/plat/sram.h
@@ -1,18 +1,8 @@
-/*
- * arch/arm/plat-omap/include/mach/sram.h
- *
- * Interface for functions that need to be run in internal SRAM
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
+int omap_sram_init(void);
 
-#ifndef __ARCH_ARM_OMAP_SRAM_H
-#define __ARCH_ARM_OMAP_SRAM_H
-
-#ifndef __ASSEMBLY__
-#include <asm/fncpy.h>
+void omap_map_sram(unsigned long start, unsigned long size,
+			unsigned long skip, int cached);
+void omap_sram_reset(void);
 
 extern void *omap_sram_push_address(unsigned long size);
 
@@ -24,82 +14,3 @@ extern void *omap_sram_push_address(unsigned long size);
 		_res = fncpy(_sram_address, &(funcp), size);	\
 	_res;							\
 })
-
-extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
-
-extern void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
-				u32 base_cs, u32 force_unlock);
-extern void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
-				      u32 mem_type);
-extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
-
-extern u32 omap3_configure_core_dpll(
-			u32 m2, u32 unlock_dll, u32 f, u32 inc,
-			u32 sdrc_rfr_ctrl_0, u32 sdrc_actim_ctrl_a_0,
-			u32 sdrc_actim_ctrl_b_0, u32 sdrc_mr_0,
-			u32 sdrc_rfr_ctrl_1, u32 sdrc_actim_ctrl_a_1,
-			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
-extern void omap3_sram_restore_context(void);
-
-/* Do not use these */
-extern void omap1_sram_reprogram_clock(u32 ckctl, u32 dpllctl);
-extern unsigned long omap1_sram_reprogram_clock_sz;
-
-extern void omap24xx_sram_reprogram_clock(u32 ckctl, u32 dpllctl);
-extern unsigned long omap24xx_sram_reprogram_clock_sz;
-
-extern void omap242x_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
-						u32 base_cs, u32 force_unlock);
-extern unsigned long omap242x_sram_ddr_init_sz;
-
-extern u32 omap242x_sram_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val,
-						int bypass);
-extern unsigned long omap242x_sram_set_prcm_sz;
-
-extern void omap242x_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
-						u32 mem_type);
-extern unsigned long omap242x_sram_reprogram_sdrc_sz;
-
-
-extern void omap243x_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
-						u32 base_cs, u32 force_unlock);
-extern unsigned long omap243x_sram_ddr_init_sz;
-
-extern u32 omap243x_sram_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val,
-						int bypass);
-extern unsigned long omap243x_sram_set_prcm_sz;
-
-extern void omap243x_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
-						u32 mem_type);
-extern unsigned long omap243x_sram_reprogram_sdrc_sz;
-
-extern u32 omap3_sram_configure_core_dpll(
-			u32 m2, u32 unlock_dll, u32 f, u32 inc,
-			u32 sdrc_rfr_ctrl_0, u32 sdrc_actim_ctrl_a_0,
-			u32 sdrc_actim_ctrl_b_0, u32 sdrc_mr_0,
-			u32 sdrc_rfr_ctrl_1, u32 sdrc_actim_ctrl_a_1,
-			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
-extern unsigned long omap3_sram_configure_core_dpll_sz;
-
-#ifdef CONFIG_PM
-extern void omap_push_sram_idle(void);
-#else
-static inline void omap_push_sram_idle(void) {}
-#endif /* CONFIG_PM */
-
-#endif /* __ASSEMBLY__ */
-
-/*
- * OMAP2+: define the SRAM PA addresses.
- * Used by the SRAM management code and the idle sleep code.
- */
-#define OMAP2_SRAM_PA		0x40200000
-#define OMAP3_SRAM_PA           0x40200000
-#ifdef CONFIG_OMAP4_ERRATA_I688
-#define OMAP4_SRAM_PA		0x40304000
-#define OMAP4_SRAM_VA		0xfe404000
-#else
-#define OMAP4_SRAM_PA		0x40300000
-#endif
-#define AM33XX_SRAM_PA		0x40300000
-#endif
diff --git a/arch/arm/plat-omap/include/plat/tc.h b/arch/arm/plat-omap/include/plat/tc.h
deleted file mode 100644
index 1b4b2da..0000000
--- a/arch/arm/plat-omap/include/plat/tc.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/tc.h
- *
- * OMAP Traffic Controller
- *
- * Copyright (C) 2004 Nokia Corporation
- * Author: Imre Deak <imre.deak@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You 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_TC_H
-#define __ASM_ARCH_TC_H
-
-#define TCMIF_BASE		0xfffecc00
-#define OMAP_TC_OCPT1_PRIOR	(TCMIF_BASE + 0x00)
-#define OMAP_TC_EMIFS_PRIOR	(TCMIF_BASE + 0x04)
-#define OMAP_TC_EMIFF_PRIOR	(TCMIF_BASE + 0x08)
-#define EMIFS_CONFIG		(TCMIF_BASE + 0x0c)
-#define EMIFS_CS0_CONFIG	(TCMIF_BASE + 0x10)
-#define EMIFS_CS1_CONFIG	(TCMIF_BASE + 0x14)
-#define EMIFS_CS2_CONFIG	(TCMIF_BASE + 0x18)
-#define EMIFS_CS3_CONFIG	(TCMIF_BASE + 0x1c)
-#define EMIFF_SDRAM_CONFIG	(TCMIF_BASE + 0x20)
-#define EMIFF_MRS		(TCMIF_BASE + 0x24)
-#define TC_TIMEOUT1		(TCMIF_BASE + 0x28)
-#define TC_TIMEOUT2		(TCMIF_BASE + 0x2c)
-#define TC_TIMEOUT3		(TCMIF_BASE + 0x30)
-#define TC_ENDIANISM		(TCMIF_BASE + 0x34)
-#define EMIFF_SDRAM_CONFIG_2	(TCMIF_BASE + 0x3c)
-#define EMIF_CFG_DYNAMIC_WS	(TCMIF_BASE + 0x40)
-#define EMIFS_ACS0		(TCMIF_BASE + 0x50)
-#define EMIFS_ACS1		(TCMIF_BASE + 0x54)
-#define EMIFS_ACS2		(TCMIF_BASE + 0x58)
-#define EMIFS_ACS3		(TCMIF_BASE + 0x5c)
-#define OMAP_TC_OCPT2_PRIOR	(TCMIF_BASE + 0xd0)
-
-/* external EMIFS chipselect regions */
-#define	OMAP_CS0_PHYS		0x00000000
-#define	OMAP_CS0_SIZE		SZ_64M
-
-#define	OMAP_CS1_PHYS		0x04000000
-#define	OMAP_CS1_SIZE		SZ_64M
-
-#define	OMAP_CS1A_PHYS		OMAP_CS1_PHYS
-#define	OMAP_CS1A_SIZE		SZ_32M
-
-#define	OMAP_CS1B_PHYS		(OMAP_CS1A_PHYS + OMAP_CS1A_SIZE)
-#define	OMAP_CS1B_SIZE		SZ_32M
-
-#define	OMAP_CS2_PHYS		0x08000000
-#define	OMAP_CS2_SIZE		SZ_64M
-
-#define	OMAP_CS2A_PHYS		OMAP_CS2_PHYS
-#define	OMAP_CS2A_SIZE		SZ_32M
-
-#define	OMAP_CS2B_PHYS		(OMAP_CS2A_PHYS + OMAP_CS2A_SIZE)
-#define	OMAP_CS2B_SIZE		SZ_32M
-
-#define	OMAP_CS3_PHYS		0x0c000000
-#define	OMAP_CS3_SIZE		SZ_64M
-
-#ifndef	__ASSEMBLER__
-
-/* EMIF Slow Interface Configuration Register */
-#define OMAP_EMIFS_CONFIG_FR		(1 << 4)
-#define OMAP_EMIFS_CONFIG_PDE		(1 << 3)
-#define OMAP_EMIFS_CONFIG_PWD_EN	(1 << 2)
-#define OMAP_EMIFS_CONFIG_BM		(1 << 1)
-#define OMAP_EMIFS_CONFIG_WP		(1 << 0)
-
-#define EMIFS_CCS(n)		(EMIFS_CS0_CONFIG + (4 * (n)))
-#define EMIFS_ACS(n)		(EMIFS_ACS0 + (4 * (n)))
-
-#endif	/* __ASSEMBLER__ */
-
-#endif	/* __ASM_ARCH_TC_H */
diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h
deleted file mode 100644
index 7f7b112..0000000
--- a/arch/arm/plat-omap/include/plat/uncompress.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/uncompress.h
- *
- * Serial port stubs for kernel decompress status messages
- *
- * Initially based on:
- * linux-2.4.15-rmk1-dsplinux1.6/arch/arm/plat-omap/include/mach1510/uncompress.h
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: Greg Lonnon <glonnon@ridgerun.com>
- *
- * Rewritten by:
- * Author: <source@mvista.com>
- * 2004 (c) MontaVista Software, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#include <linux/types.h>
-#include <linux/serial_reg.h>
-
-#include <asm/memory.h>
-#include <asm/mach-types.h>
-
-#include <plat/serial.h>
-
-#define MDR1_MODE_MASK			0x07
-
-volatile u8 *uart_base;
-int uart_shift;
-
-/*
- * Store the DEBUG_LL uart number into memory.
- * See also debug-macro.S, and serial.c for related code.
- */
-static void set_omap_uart_info(unsigned char port)
-{
-	/*
-	 * Get address of some.bss variable and round it down
-	 * a la CONFIG_AUTO_ZRELADDR.
-	 */
-	u32 ram_start = (u32)&uart_shift & 0xf8000000;
-	u32 *uart_info = (u32 *)(ram_start + OMAP_UART_INFO_OFS);
-	*uart_info = port;
-}
-
-static void putc(int c)
-{
-	if (!uart_base)
-		return;
-
-	/* Check for UART 16x mode */
-	if ((uart_base[UART_OMAP_MDR1 << uart_shift] & MDR1_MODE_MASK) != 0)
-		return;
-
-	while (!(uart_base[UART_LSR << uart_shift] & UART_LSR_THRE))
-		barrier();
-	uart_base[UART_TX << uart_shift] = c;
-}
-
-static inline void flush(void)
-{
-}
-
-/*
- * Macros to configure UART1 and debug UART
- */
-#define _DEBUG_LL_ENTRY(mach, dbg_uart, dbg_shft, dbg_id)		\
-	if (machine_is_##mach()) {					\
-		uart_base = (volatile u8 *)(dbg_uart);			\
-		uart_shift = (dbg_shft);				\
-		port = (dbg_id);					\
-		set_omap_uart_info(port);				\
-		break;							\
-	}
-
-#define DEBUG_LL_OMAP7XX(p, mach)					\
-	_DEBUG_LL_ENTRY(mach, OMAP1_UART##p##_BASE, OMAP7XX_PORT_SHIFT,	\
-		OMAP1UART##p)
-
-#define DEBUG_LL_OMAP1(p, mach)						\
-	_DEBUG_LL_ENTRY(mach, OMAP1_UART##p##_BASE, OMAP_PORT_SHIFT,	\
-		OMAP1UART##p)
-
-#define DEBUG_LL_OMAP2(p, mach)						\
-	_DEBUG_LL_ENTRY(mach, OMAP2_UART##p##_BASE, OMAP_PORT_SHIFT,	\
-		OMAP2UART##p)
-
-#define DEBUG_LL_OMAP3(p, mach)						\
-	_DEBUG_LL_ENTRY(mach, OMAP3_UART##p##_BASE, OMAP_PORT_SHIFT,	\
-		OMAP3UART##p)
-
-#define DEBUG_LL_OMAP4(p, mach)						\
-	_DEBUG_LL_ENTRY(mach, OMAP4_UART##p##_BASE, OMAP_PORT_SHIFT,	\
-		OMAP4UART##p)
-
-#define DEBUG_LL_OMAP5(p, mach)						\
-	_DEBUG_LL_ENTRY(mach, OMAP5_UART##p##_BASE, OMAP_PORT_SHIFT,	\
-		OMAP5UART##p)
-/* Zoom2/3 shift is different for UART1 and external port */
-#define DEBUG_LL_ZOOM(mach)						\
-	_DEBUG_LL_ENTRY(mach, ZOOM_UART_BASE, ZOOM_PORT_SHIFT, ZOOM_UART)
-
-#define DEBUG_LL_TI81XX(p, mach)					\
-	_DEBUG_LL_ENTRY(mach, TI81XX_UART##p##_BASE, OMAP_PORT_SHIFT,	\
-		TI81XXUART##p)
-
-#define DEBUG_LL_AM33XX(p, mach)					\
-	_DEBUG_LL_ENTRY(mach, AM33XX_UART##p##_BASE, OMAP_PORT_SHIFT,	\
-		AM33XXUART##p)
-
-static inline void arch_decomp_setup(void)
-{
-	int port = 0;
-
-	/*
-	 * Initialize the port based on the machine ID from the bootloader.
-	 * Note that we're using macros here instead of switch statement
-	 * as machine_is functions are optimized out for the boards that
-	 * are not selected.
-	 */
-	do {
-		/* omap7xx/8xx based boards using UART1 with shift 0 */
-		DEBUG_LL_OMAP7XX(1, herald);
-		DEBUG_LL_OMAP7XX(1, omap_perseus2);
-
-		/* omap15xx/16xx based boards using UART1 */
-		DEBUG_LL_OMAP1(1, ams_delta);
-		DEBUG_LL_OMAP1(1, nokia770);
-		DEBUG_LL_OMAP1(1, omap_h2);
-		DEBUG_LL_OMAP1(1, omap_h3);
-		DEBUG_LL_OMAP1(1, omap_innovator);
-		DEBUG_LL_OMAP1(1, omap_osk);
-		DEBUG_LL_OMAP1(1, omap_palmte);
-		DEBUG_LL_OMAP1(1, omap_palmz71);
-
-		/* omap15xx/16xx based boards using UART2 */
-		DEBUG_LL_OMAP1(2, omap_palmtt);
-
-		/* omap15xx/16xx based boards using UART3 */
-		DEBUG_LL_OMAP1(3, sx1);
-
-		/* omap2 based boards using UART1 */
-		DEBUG_LL_OMAP2(1, omap_2430sdp);
-		DEBUG_LL_OMAP2(1, omap_apollon);
-		DEBUG_LL_OMAP2(1, omap_h4);
-
-		/* omap2 based boards using UART3 */
-		DEBUG_LL_OMAP2(3, nokia_n800);
-		DEBUG_LL_OMAP2(3, nokia_n810);
-		DEBUG_LL_OMAP2(3, nokia_n810_wimax);
-
-		/* omap3 based boards using UART1 */
-		DEBUG_LL_OMAP2(1, omap3evm);
-		DEBUG_LL_OMAP3(1, omap_3430sdp);
-		DEBUG_LL_OMAP3(1, omap_3630sdp);
-		DEBUG_LL_OMAP3(1, omap3530_lv_som);
-		DEBUG_LL_OMAP3(1, omap3_torpedo);
-
-		/* omap3 based boards using UART3 */
-		DEBUG_LL_OMAP3(3, cm_t35);
-		DEBUG_LL_OMAP3(3, cm_t3517);
-		DEBUG_LL_OMAP3(3, cm_t3730);
-		DEBUG_LL_OMAP3(3, craneboard);
-		DEBUG_LL_OMAP3(3, devkit8000);
-		DEBUG_LL_OMAP3(3, igep0020);
-		DEBUG_LL_OMAP3(3, igep0030);
-		DEBUG_LL_OMAP3(3, nokia_rm680);
-		DEBUG_LL_OMAP3(3, nokia_rm696);
-		DEBUG_LL_OMAP3(3, nokia_rx51);
-		DEBUG_LL_OMAP3(3, omap3517evm);
-		DEBUG_LL_OMAP3(3, omap3_beagle);
-		DEBUG_LL_OMAP3(3, omap3_pandora);
-		DEBUG_LL_OMAP3(3, omap_ldp);
-		DEBUG_LL_OMAP3(3, overo);
-		DEBUG_LL_OMAP3(3, touchbook);
-
-		/* omap4 based boards using UART3 */
-		DEBUG_LL_OMAP4(3, omap_4430sdp);
-		DEBUG_LL_OMAP4(3, omap4_panda);
-
-		/* omap5 based boards using UART3 */
-		DEBUG_LL_OMAP5(3, omap5_sevm);
-
-		/* zoom2/3 external uart */
-		DEBUG_LL_ZOOM(omap_zoom2);
-		DEBUG_LL_ZOOM(omap_zoom3);
-
-		/* TI8168 base boards using UART3 */
-		DEBUG_LL_TI81XX(3, ti8168evm);
-
-		/* TI8148 base boards using UART1 */
-		DEBUG_LL_TI81XX(1, ti8148evm);
-
-		/* AM33XX base boards using UART1 */
-		DEBUG_LL_AM33XX(1, am335xevm);
-	} while (0);
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_wdog()
diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
deleted file mode 100644
index 87ee140..0000000
--- a/arch/arm/plat-omap/include/plat/usb.h
+++ /dev/null
@@ -1,179 +0,0 @@
-// include/asm-arm/mach-omap/usb.h
-
-#ifndef	__ASM_ARCH_OMAP_USB_H
-#define	__ASM_ARCH_OMAP_USB_H
-
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/usb/musb.h>
-
-#define OMAP3_HS_USB_PORTS	3
-
-enum usbhs_omap_port_mode {
-	OMAP_USBHS_PORT_MODE_UNUSED,
-	OMAP_EHCI_PORT_MODE_PHY,
-	OMAP_EHCI_PORT_MODE_TLL,
-	OMAP_EHCI_PORT_MODE_HSIC,
-	OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0,
-	OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM,
-	OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0,
-	OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM,
-	OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0,
-	OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM,
-	OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0,
-	OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM,
-	OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0,
-	OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM
-};
-
-struct usbhs_omap_board_data {
-	enum usbhs_omap_port_mode	port_mode[OMAP3_HS_USB_PORTS];
-
-	/* have to be valid if phy_reset is true and portx is in phy mode */
-	int	reset_gpio_port[OMAP3_HS_USB_PORTS];
-
-	/* Set this to true for ES2.x silicon */
-	unsigned			es2_compatibility:1;
-
-	unsigned			phy_reset:1;
-
-	/*
-	 * Regulators for USB PHYs.
-	 * Each PHY can have a separate regulator.
-	 */
-	struct regulator		*regulator[OMAP3_HS_USB_PORTS];
-};
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-
-struct ehci_hcd_omap_platform_data {
-	enum usbhs_omap_port_mode	port_mode[OMAP3_HS_USB_PORTS];
-	int				reset_gpio_port[OMAP3_HS_USB_PORTS];
-	struct regulator		*regulator[OMAP3_HS_USB_PORTS];
-	unsigned			phy_reset:1;
-};
-
-struct ohci_hcd_omap_platform_data {
-	enum usbhs_omap_port_mode	port_mode[OMAP3_HS_USB_PORTS];
-	unsigned			es2_compatibility:1;
-};
-
-struct usbhs_omap_platform_data {
-	enum usbhs_omap_port_mode		port_mode[OMAP3_HS_USB_PORTS];
-
-	struct ehci_hcd_omap_platform_data	*ehci_data;
-	struct ohci_hcd_omap_platform_data	*ohci_data;
-};
-
-struct usbtll_omap_platform_data {
-	enum usbhs_omap_port_mode		port_mode[OMAP3_HS_USB_PORTS];
-};
-/*-------------------------------------------------------------------------*/
-
-struct omap_musb_board_data {
-	u8	interface_type;
-	u8	mode;
-	u16	power;
-	unsigned extvbus:1;
-	void	(*set_phy_power)(u8 on);
-	void	(*clear_irq)(void);
-	void	(*set_mode)(u8 mode);
-	void	(*reset)(void);
-};
-
-enum musb_interface    {MUSB_INTERFACE_ULPI, MUSB_INTERFACE_UTMI};
-
-extern void usb_musb_init(struct omap_musb_board_data *board_data);
-
-extern void usbhs_init(const struct usbhs_omap_board_data *pdata);
-extern int omap_tll_enable(void);
-extern int omap_tll_disable(void);
-
-extern int omap4430_phy_power(struct device *dev, int ID, int on);
-extern int omap4430_phy_set_clk(struct device *dev, int on);
-extern int omap4430_phy_init(struct device *dev);
-extern int omap4430_phy_exit(struct device *dev);
-extern int omap4430_phy_suspend(struct device *dev, int suspend);
-
-#endif
-
-extern void am35x_musb_reset(void);
-extern void am35x_musb_phy_power(u8 on);
-extern void am35x_musb_clear_irq(void);
-extern void am35x_set_mode(u8 musb_mode);
-extern void ti81xx_musb_phy_power(u8 on);
-
-/* AM35x */
-/* USB 2.0 PHY Control */
-#define CONF2_PHY_GPIOMODE	(1 << 23)
-#define CONF2_OTGMODE		(3 << 14)
-#define CONF2_NO_OVERRIDE	(0 << 14)
-#define CONF2_FORCE_HOST	(1 << 14)
-#define CONF2_FORCE_DEVICE	(2 << 14)
-#define CONF2_FORCE_HOST_VBUS_LOW (3 << 14)
-#define CONF2_SESENDEN		(1 << 13)
-#define CONF2_VBDTCTEN		(1 << 12)
-#define CONF2_REFFREQ_24MHZ	(2 << 8)
-#define CONF2_REFFREQ_26MHZ	(7 << 8)
-#define CONF2_REFFREQ_13MHZ	(6 << 8)
-#define CONF2_REFFREQ		(0xf << 8)
-#define CONF2_PHYCLKGD		(1 << 7)
-#define CONF2_VBUSSENSE		(1 << 6)
-#define CONF2_PHY_PLLON		(1 << 5)
-#define CONF2_RESET		(1 << 4)
-#define CONF2_PHYPWRDN		(1 << 3)
-#define CONF2_OTGPWRDN		(1 << 2)
-#define CONF2_DATPOL		(1 << 1)
-
-/* TI81XX specific definitions */
-#define USBCTRL0	0x620
-#define USBSTAT0	0x624
-
-/* TI816X PHY controls bits */
-#define TI816X_USBPHY0_NORMAL_MODE	(1 << 0)
-#define TI816X_USBPHY_REFCLK_OSC	(1 << 8)
-
-/* TI814X PHY controls bits */
-#define USBPHY_CM_PWRDN		(1 << 0)
-#define USBPHY_OTG_PWRDN	(1 << 1)
-#define USBPHY_CHGDET_DIS	(1 << 2)
-#define USBPHY_CHGDET_RSTRT	(1 << 3)
-#define USBPHY_SRCONDM		(1 << 4)
-#define USBPHY_SINKONDP		(1 << 5)
-#define USBPHY_CHGISINK_EN	(1 << 6)
-#define USBPHY_CHGVSRC_EN	(1 << 7)
-#define USBPHY_DMPULLUP		(1 << 8)
-#define USBPHY_DPPULLUP		(1 << 9)
-#define USBPHY_CDET_EXTCTL	(1 << 10)
-#define USBPHY_GPIO_MODE	(1 << 12)
-#define USBPHY_DPOPBUFCTL	(1 << 13)
-#define USBPHY_DMOPBUFCTL	(1 << 14)
-#define USBPHY_DPINPUT		(1 << 15)
-#define USBPHY_DMINPUT		(1 << 16)
-#define USBPHY_DPGPIO_PD	(1 << 17)
-#define USBPHY_DMGPIO_PD	(1 << 18)
-#define USBPHY_OTGVDET_EN	(1 << 19)
-#define USBPHY_OTGSESSEND_EN	(1 << 20)
-#define USBPHY_DATA_POLARITY	(1 << 23)
-
-#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_USB)
-u32 omap1_usb0_init(unsigned nwires, unsigned is_device);
-u32 omap1_usb1_init(unsigned nwires);
-u32 omap1_usb2_init(unsigned nwires, unsigned alt_pingroup);
-#else
-static inline u32 omap1_usb0_init(unsigned nwires, unsigned is_device)
-{
-	return 0;
-}
-static inline u32 omap1_usb1_init(unsigned nwires)
-{
-	return 0;
-
-}
-static inline u32 omap1_usb2_init(unsigned nwires, unsigned alt_pingroup)
-{
-	return 0;
-}
-#endif
-
-#endif	/* __ASM_ARCH_OMAP_USB_H */
diff --git a/arch/arm/plat-omap/include/plat/vram.h b/arch/arm/plat-omap/include/plat/vram.h
deleted file mode 100644
index 4d65b7d..0000000
--- a/arch/arm/plat-omap/include/plat/vram.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * VRAM manager for OMAP
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#ifndef __OMAP_VRAM_H__
-#define __OMAP_VRAM_H__
-
-#include <linux/types.h>
-
-extern int omap_vram_add_region(unsigned long paddr, size_t size);
-extern int omap_vram_free(unsigned long paddr, size_t size);
-extern int omap_vram_alloc(size_t size, unsigned long *paddr);
-extern int omap_vram_reserve(unsigned long paddr, size_t size);
-extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram,
-		unsigned long *largest_free_block);
-
-#ifdef CONFIG_OMAP2_VRAM
-extern void omap_vram_set_sdram_vram(u32 size, u32 start);
-
-extern void omap_vram_reserve_sdram_memblock(void);
-#else
-static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { }
-
-static inline void omap_vram_reserve_sdram_memblock(void) { }
-#endif
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/vrfb.h b/arch/arm/plat-omap/include/plat/vrfb.h
deleted file mode 100644
index 3792bde..0000000
--- a/arch/arm/plat-omap/include/plat/vrfb.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * VRFB Rotation Engine
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#ifndef __OMAP_VRFB_H__
-#define __OMAP_VRFB_H__
-
-#define OMAP_VRFB_LINE_LEN 2048
-
-struct vrfb {
-	u8 context;
-	void __iomem *vaddr[4];
-	unsigned long paddr[4];
-	u16 xres;
-	u16 yres;
-	u16 xoffset;
-	u16 yoffset;
-	u8 bytespp;
-	bool yuv_mode;
-};
-
-#ifdef CONFIG_OMAP2_VRFB
-extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
-extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
-extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
-		u8 bytespp);
-extern u32 omap_vrfb_min_phys_size(u16 width, u16 height, u8 bytespp);
-extern u16 omap_vrfb_max_height(u32 phys_size, u16 width, u8 bytespp);
-extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
-		u16 width, u16 height,
-		unsigned bytespp, bool yuv_mode);
-extern int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot);
-extern void omap_vrfb_restore_context(void);
-
-#else
-static inline int omap_vrfb_request_ctx(struct vrfb *vrfb) { return 0; }
-static inline void omap_vrfb_release_ctx(struct vrfb *vrfb) {}
-static inline void omap_vrfb_adjust_size(u16 *width, u16 *height,
-		u8 bytespp) {}
-static inline u32 omap_vrfb_min_phys_size(u16 width, u16 height, u8 bytespp)
-		{ return 0; }
-static inline u16 omap_vrfb_max_height(u32 phys_size, u16 width, u8 bytespp)
-		{ return 0; }
-static inline void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
-		u16 width, u16 height, unsigned bytespp, bool yuv_mode) {}
-static inline int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot)
-		{ return 0; }
-static inline void omap_vrfb_restore_context(void) {}
-#endif
-#endif /* __VRFB_H */
diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c
deleted file mode 100644
index 9722f41..0000000
--- a/arch/arm/plat-omap/omap-pm-noop.c
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * omap-pm-noop.c - OMAP power management interface - dummy version
- *
- * This code implements the OMAP power management interface to
- * drivers, CPUIdle, CPUFreq, and DSP Bridge.  It is strictly for
- * debug/demonstration use, as it does nothing but printk() whenever a
- * function is called (when DEBUG is defined, below)
- *
- * Copyright (C) 2008-2009 Texas Instruments, Inc.
- * Copyright (C) 2008-2009 Nokia Corporation
- * Paul Walmsley
- *
- * Interface developed by (in alphabetical order):
- * Karthik Dasu, Tony Lindgren, Rajendra Nayak, Sakari Poussa, Veeramanikandan
- * Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, Richard Woodruff
- */
-
-#undef DEBUG
-
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-
-/* Interface documentation is in mach/omap-pm.h */
-#include <plat/omap-pm.h>
-#include <plat/omap_device.h>
-
-static bool off_mode_enabled;
-static int dummy_context_loss_counter;
-
-/*
- * Device-driver-originated constraints (via board-*.c files)
- */
-
-int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t)
-{
-	if (!dev || t < -1) {
-		WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
-		return -EINVAL;
-	}
-
-	if (t == -1)
-		pr_debug("OMAP PM: remove max MPU wakeup latency constraint: dev %s\n",
-			 dev_name(dev));
-	else
-		pr_debug("OMAP PM: add max MPU wakeup latency constraint: dev %s, t = %ld usec\n",
-			 dev_name(dev), t);
-
-	/*
-	 * For current Linux, this needs to map the MPU to a
-	 * powerdomain, then go through the list of current max lat
-	 * constraints on the MPU and find the smallest.  If
-	 * the latency constraint has changed, the code should
-	 * recompute the state to enter for the next powerdomain
-	 * state.
-	 *
-	 * TI CDP code can call constraint_set here.
-	 */
-
-	return 0;
-}
-
-int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r)
-{
-	if (!dev || (agent_id != OCP_INITIATOR_AGENT &&
-	    agent_id != OCP_TARGET_AGENT)) {
-		WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
-		return -EINVAL;
-	}
-
-	if (r == 0)
-		pr_debug("OMAP PM: remove min bus tput constraint: dev %s for agent_id %d\n",
-			 dev_name(dev), agent_id);
-	else
-		pr_debug("OMAP PM: add min bus tput constraint: dev %s for agent_id %d: rate %ld KiB\n",
-			 dev_name(dev), agent_id, r);
-
-	/*
-	 * This code should model the interconnect and compute the
-	 * required clock frequency, convert that to a VDD2 OPP ID, then
-	 * set the VDD2 OPP appropriately.
-	 *
-	 * TI CDP code can call constraint_set here on the VDD2 OPP.
-	 */
-
-	return 0;
-}
-
-int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev,
-				   long t)
-{
-	if (!req_dev || !dev || t < -1) {
-		WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
-		return -EINVAL;
-	}
-
-	if (t == -1)
-		pr_debug("OMAP PM: remove max device latency constraint: dev %s\n",
-			 dev_name(dev));
-	else
-		pr_debug("OMAP PM: add max device latency constraint: dev %s, t = %ld usec\n",
-			 dev_name(dev), t);
-
-	/*
-	 * For current Linux, this needs to map the device to a
-	 * powerdomain, then go through the list of current max lat
-	 * constraints on that powerdomain and find the smallest.  If
-	 * the latency constraint has changed, the code should
-	 * recompute the state to enter for the next powerdomain
-	 * state.  Conceivably, this code should also determine
-	 * whether to actually disable the device clocks or not,
-	 * depending on how long it takes to re-enable the clocks.
-	 *
-	 * TI CDP code can call constraint_set here.
-	 */
-
-	return 0;
-}
-
-int omap_pm_set_max_sdma_lat(struct device *dev, long t)
-{
-	if (!dev || t < -1) {
-		WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
-		return -EINVAL;
-	}
-
-	if (t == -1)
-		pr_debug("OMAP PM: remove max DMA latency constraint: dev %s\n",
-			 dev_name(dev));
-	else
-		pr_debug("OMAP PM: add max DMA latency constraint: dev %s, t = %ld usec\n",
-			 dev_name(dev), t);
-
-	/*
-	 * For current Linux PM QOS params, this code should scan the
-	 * list of maximum CPU and DMA latencies and select the
-	 * smallest, then set cpu_dma_latency pm_qos_param
-	 * accordingly.
-	 *
-	 * For future Linux PM QOS params, with separate CPU and DMA
-	 * latency params, this code should just set the dma_latency param.
-	 *
-	 * TI CDP code can call constraint_set here.
-	 */
-
-	return 0;
-}
-
-int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r)
-{
-	if (!dev || !c || r < 0) {
-		WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
-		return -EINVAL;
-	}
-
-	if (r == 0)
-		pr_debug("OMAP PM: remove min clk rate constraint: dev %s\n",
-			 dev_name(dev));
-	else
-		pr_debug("OMAP PM: add min clk rate constraint: dev %s, rate = %ld Hz\n",
-			 dev_name(dev), r);
-
-	/*
-	 * Code in a real implementation should keep track of these
-	 * constraints on the clock, and determine the highest minimum
-	 * clock rate.  It should iterate over each OPP and determine
-	 * whether the OPP will result in a clock rate that would
-	 * satisfy this constraint (and any other PM constraint in effect
-	 * at that time).  Once it finds the lowest-voltage OPP that
-	 * meets those conditions, it should switch to it, or return
-	 * an error if the code is not capable of doing so.
-	 */
-
-	return 0;
-}
-
-/*
- * DSP Bridge-specific constraints
- */
-
-const struct omap_opp *omap_pm_dsp_get_opp_table(void)
-{
-	pr_debug("OMAP PM: DSP request for OPP table\n");
-
-	/*
-	 * Return DSP frequency table here:  The final item in the
-	 * array should have .rate = .opp_id = 0.
-	 */
-
-	return NULL;
-}
-
-void omap_pm_dsp_set_min_opp(u8 opp_id)
-{
-	if (opp_id == 0) {
-		WARN_ON(1);
-		return;
-	}
-
-	pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id);
-
-	/*
-	 *
-	 * For l-o dev tree, our VDD1 clk is keyed on OPP ID, so we
-	 * can just test to see which is higher, the CPU's desired OPP
-	 * ID or the DSP's desired OPP ID, and use whichever is
-	 * highest.
-	 *
-	 * In CDP12.14+, the VDD1 OPP custom clock that controls the DSP
-	 * rate is keyed on MPU speed, not the OPP ID.  So we need to
-	 * map the OPP ID to the MPU speed for use with clk_set_rate()
-	 * if it is higher than the current OPP clock rate.
-	 *
-	 */
-}
-
-
-u8 omap_pm_dsp_get_opp(void)
-{
-	pr_debug("OMAP PM: DSP requests current DSP OPP ID\n");
-
-	/*
-	 * For l-o dev tree, call clk_get_rate() on VDD1 OPP clock
-	 *
-	 * CDP12.14+:
-	 * Call clk_get_rate() on the OPP custom clock, map that to an
-	 * OPP ID using the tables defined in board-*.c/chip-*.c files.
-	 */
-
-	return 0;
-}
-
-/*
- * CPUFreq-originated constraint
- *
- * In the future, this should be handled by custom OPP clocktype
- * functions.
- */
-
-struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void)
-{
-	pr_debug("OMAP PM: CPUFreq request for frequency table\n");
-
-	/*
-	 * Return CPUFreq frequency table here: loop over
-	 * all VDD1 clkrates, pull out the mpu_ck frequencies, build
-	 * table
-	 */
-
-	return NULL;
-}
-
-void omap_pm_cpu_set_freq(unsigned long f)
-{
-	if (f == 0) {
-		WARN_ON(1);
-		return;
-	}
-
-	pr_debug("OMAP PM: CPUFreq requests CPU frequency to be set to %lu\n",
-		 f);
-
-	/*
-	 * For l-o dev tree, determine whether MPU freq or DSP OPP id
-	 * freq is higher.  Find the OPP ID corresponding to the
-	 * higher frequency.  Call clk_round_rate() and clk_set_rate()
-	 * on the OPP custom clock.
-	 *
-	 * CDP should just be able to set the VDD1 OPP clock rate here.
-	 */
-}
-
-unsigned long omap_pm_cpu_get_freq(void)
-{
-	pr_debug("OMAP PM: CPUFreq requests current CPU frequency\n");
-
-	/*
-	 * Call clk_get_rate() on the mpu_ck.
-	 */
-
-	return 0;
-}
-
-/**
- * omap_pm_enable_off_mode - notify OMAP PM that off-mode is enabled
- *
- * Intended for use only by OMAP PM core code to notify this layer
- * that off mode has been enabled.
- */
-void omap_pm_enable_off_mode(void)
-{
-	off_mode_enabled = true;
-}
-
-/**
- * omap_pm_disable_off_mode - notify OMAP PM that off-mode is disabled
- *
- * Intended for use only by OMAP PM core code to notify this layer
- * that off mode has been disabled.
- */
-void omap_pm_disable_off_mode(void)
-{
-	off_mode_enabled = false;
-}
-
-/*
- * Device context loss tracking
- */
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-
-int omap_pm_get_dev_context_loss_count(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	int count;
-
-	if (WARN_ON(!dev))
-		return -ENODEV;
-
-	if (dev->pm_domain == &omap_device_pm_domain) {
-		count = omap_device_get_context_loss_count(pdev);
-	} else {
-		WARN_ONCE(off_mode_enabled, "omap_pm: using dummy context loss counter; device %s should be converted to omap_device",
-			  dev_name(dev));
-
-		count = dummy_context_loss_counter;
-
-		if (off_mode_enabled) {
-			count++;
-			/*
-			 * Context loss count has to be a non-negative value.
-			 * Clear the sign bit to get a value range from 0 to
-			 * INT_MAX.
-			 */
-			count &= INT_MAX;
-			dummy_context_loss_counter = count;
-		}
-	}
-
-	pr_debug("OMAP PM: context loss count for dev %s = %d\n",
-		 dev_name(dev), count);
-
-	return count;
-}
-
-#else
-
-int omap_pm_get_dev_context_loss_count(struct device *dev)
-{
-	return dummy_context_loss_counter;
-}
-
-#endif
-
-/* Should be called before clk framework init */
-int __init omap_pm_if_early_init(void)
-{
-	return 0;
-}
-
-/* Must be called after clock framework is initialized */
-int __init omap_pm_if_init(void)
-{
-	return 0;
-}
-
-void omap_pm_if_exit(void)
-{
-	/* Deallocate CPUFreq frequency table here */
-}
-
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
deleted file mode 100644
index 7a7d1f2..0000000
--- a/arch/arm/plat-omap/omap_device.c
+++ /dev/null
@@ -1,1278 +0,0 @@
-/*
- * omap_device implementation
- *
- * Copyright (C) 2009-2010 Nokia Corporation
- * Paul Walmsley, Kevin Hilman
- *
- * Developed in collaboration with (alphabetical order): Benoit
- * Cousson, Thara Gopinath, Tony Lindgren, Rajendra Nayak, Vikram
- * Pandita, Sakari Poussa, Anand Sawant, Santosh Shilimkar, Richard
- * Woodruff
- *
- * This program is free software; you can 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 code provides a consistent interface for OMAP device drivers
- * to control power management and interconnect properties of their
- * devices.
- *
- * In the medium- to long-term, this code should either be
- * a) implemented via arch-specific pointers in platform_data
- * or
- * b) implemented as a proper omap_bus/omap_device in Linux, no more
- *    platform_data func pointers
- *
- *
- * Guidelines for usage by driver authors:
- *
- * 1. These functions are intended to be used by device drivers via
- * function pointers in struct platform_data.  As an example,
- * omap_device_enable() should be passed to the driver as
- *
- * struct foo_driver_platform_data {
- * ...
- *      int (*device_enable)(struct platform_device *pdev);
- * ...
- * }
- *
- * Note that the generic "device_enable" name is used, rather than
- * "omap_device_enable".  This is so other architectures can pass in their
- * own enable/disable functions here.
- *
- * This should be populated during device setup:
- *
- * ...
- * pdata->device_enable = omap_device_enable;
- * ...
- *
- * 2. Drivers should first check to ensure the function pointer is not null
- * before calling it, as in:
- *
- * if (pdata->device_enable)
- *     pdata->device_enable(pdev);
- *
- * This allows other architectures that don't use similar device_enable()/
- * device_shutdown() functions to execute normally.
- *
- * ...
- *
- * Suggested usage by device drivers:
- *
- * During device initialization:
- * device_enable()
- *
- * During device idle:
- * (save remaining device context if necessary)
- * device_idle();
- *
- * During device resume:
- * device_enable();
- * (restore context if necessary)
- *
- * During device shutdown:
- * device_shutdown()
- * (device must be reinitialized at this point to use it again)
- *
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
-#include <linux/pm_runtime.h>
-#include <linux/of.h>
-#include <linux/notifier.h>
-
-#include <plat/omap_device.h>
-#include <plat/omap_hwmod.h>
-#include <plat/clock.h>
-
-/* These parameters are passed to _omap_device_{de,}activate() */
-#define USE_WAKEUP_LAT			0
-#define IGNORE_WAKEUP_LAT		1
-
-static int omap_early_device_register(struct platform_device *pdev);
-
-static struct omap_device_pm_latency omap_default_latency[] = {
-	{
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	}
-};
-
-/* Private functions */
-
-/**
- * _omap_device_activate - increase device readiness
- * @od: struct omap_device *
- * @ignore_lat: increase to latency target (0) or full readiness (1)?
- *
- * Increase readiness of omap_device @od (thus decreasing device
- * wakeup latency, but consuming more power).  If @ignore_lat is
- * IGNORE_WAKEUP_LAT, make the omap_device fully active.  Otherwise,
- * if @ignore_lat is USE_WAKEUP_LAT, and the device's maximum wakeup
- * latency is greater than the requested maximum wakeup latency, step
- * backwards in the omap_device_pm_latency table to ensure the
- * device's maximum wakeup latency is less than or equal to the
- * requested maximum wakeup latency.  Returns 0.
- */
-static int _omap_device_activate(struct omap_device *od, u8 ignore_lat)
-{
-	struct timespec a, b, c;
-
-	dev_dbg(&od->pdev->dev, "omap_device: activating\n");
-
-	while (od->pm_lat_level > 0) {
-		struct omap_device_pm_latency *odpl;
-		unsigned long long act_lat = 0;
-
-		od->pm_lat_level--;
-
-		odpl = od->pm_lats + od->pm_lat_level;
-
-		if (!ignore_lat &&
-		    (od->dev_wakeup_lat <= od->_dev_wakeup_lat_limit))
-			break;
-
-		read_persistent_clock(&a);
-
-		/* XXX check return code */
-		odpl->activate_func(od);
-
-		read_persistent_clock(&b);
-
-		c = timespec_sub(b, a);
-		act_lat = timespec_to_ns(&c);
-
-		dev_dbg(&od->pdev->dev,
-			"omap_device: pm_lat %d: activate: elapsed time %llu nsec\n",
-			od->pm_lat_level, act_lat);
-
-		if (act_lat > odpl->activate_lat) {
-			odpl->activate_lat_worst = act_lat;
-			if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
-				odpl->activate_lat = act_lat;
-				dev_dbg(&od->pdev->dev,
-					"new worst case activate latency %d: %llu\n",
-					od->pm_lat_level, act_lat);
-			} else
-				dev_warn(&od->pdev->dev,
-					 "activate latency %d higher than expected. (%llu > %d)\n",
-					 od->pm_lat_level, act_lat,
-					 odpl->activate_lat);
-		}
-
-		od->dev_wakeup_lat -= odpl->activate_lat;
-	}
-
-	return 0;
-}
-
-/**
- * _omap_device_deactivate - decrease device readiness
- * @od: struct omap_device *
- * @ignore_lat: decrease to latency target (0) or full inactivity (1)?
- *
- * Decrease readiness of omap_device @od (thus increasing device
- * wakeup latency, but conserving power).  If @ignore_lat is
- * IGNORE_WAKEUP_LAT, make the omap_device fully inactive.  Otherwise,
- * if @ignore_lat is USE_WAKEUP_LAT, and the device's maximum wakeup
- * latency is less than the requested maximum wakeup latency, step
- * forwards in the omap_device_pm_latency table to ensure the device's
- * maximum wakeup latency is less than or equal to the requested
- * maximum wakeup latency.  Returns 0.
- */
-static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
-{
-	struct timespec a, b, c;
-
-	dev_dbg(&od->pdev->dev, "omap_device: deactivating\n");
-
-	while (od->pm_lat_level < od->pm_lats_cnt) {
-		struct omap_device_pm_latency *odpl;
-		unsigned long long deact_lat = 0;
-
-		odpl = od->pm_lats + od->pm_lat_level;
-
-		if (!ignore_lat &&
-		    ((od->dev_wakeup_lat + odpl->activate_lat) >
-		     od->_dev_wakeup_lat_limit))
-			break;
-
-		read_persistent_clock(&a);
-
-		/* XXX check return code */
-		odpl->deactivate_func(od);
-
-		read_persistent_clock(&b);
-
-		c = timespec_sub(b, a);
-		deact_lat = timespec_to_ns(&c);
-
-		dev_dbg(&od->pdev->dev,
-			"omap_device: pm_lat %d: deactivate: elapsed time %llu nsec\n",
-			od->pm_lat_level, deact_lat);
-
-		if (deact_lat > odpl->deactivate_lat) {
-			odpl->deactivate_lat_worst = deact_lat;
-			if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
-				odpl->deactivate_lat = deact_lat;
-				dev_dbg(&od->pdev->dev,
-					"new worst case deactivate latency %d: %llu\n",
-					od->pm_lat_level, deact_lat);
-			} else
-				dev_warn(&od->pdev->dev,
-					 "deactivate latency %d higher than expected. (%llu > %d)\n",
-					 od->pm_lat_level, deact_lat,
-					 odpl->deactivate_lat);
-		}
-
-		od->dev_wakeup_lat += odpl->activate_lat;
-
-		od->pm_lat_level++;
-	}
-
-	return 0;
-}
-
-static void _add_clkdev(struct omap_device *od, const char *clk_alias,
-		       const char *clk_name)
-{
-	struct clk *r;
-	struct clk_lookup *l;
-
-	if (!clk_alias || !clk_name)
-		return;
-
-	dev_dbg(&od->pdev->dev, "Creating %s -> %s\n", clk_alias, clk_name);
-
-	r = clk_get_sys(dev_name(&od->pdev->dev), clk_alias);
-	if (!IS_ERR(r)) {
-		dev_warn(&od->pdev->dev,
-			 "alias %s already exists\n", clk_alias);
-		clk_put(r);
-		return;
-	}
-
-	r = clk_get(NULL, clk_name);
-	if (IS_ERR(r)) {
-		dev_err(&od->pdev->dev,
-			"clk_get for %s failed\n", clk_name);
-		return;
-	}
-
-	l = clkdev_alloc(r, clk_alias, dev_name(&od->pdev->dev));
-	if (!l) {
-		dev_err(&od->pdev->dev,
-			"clkdev_alloc for %s failed\n", clk_alias);
-		return;
-	}
-
-	clkdev_add(l);
-}
-
-/**
- * _add_hwmod_clocks_clkdev - Add clkdev entry for hwmod optional clocks
- * and main clock
- * @od: struct omap_device *od
- * @oh: struct omap_hwmod *oh
- *
- * For the main clock and every optional clock present per hwmod per
- * omap_device, this function adds an entry in the clkdev table of the
- * form <dev-id=dev_name, con-id=role> if it does not exist already.
- *
- * The function is called from inside omap_device_build_ss(), after
- * omap_device_register.
- *
- * This allows drivers to get a pointer to its optional clocks based on its role
- * by calling clk_get(<dev*>, <role>).
- * In the case of the main clock, a "fck" alias is used.
- *
- * No return value.
- */
-static void _add_hwmod_clocks_clkdev(struct omap_device *od,
-				     struct omap_hwmod *oh)
-{
-	int i;
-
-	_add_clkdev(od, "fck", oh->main_clk);
-
-	for (i = 0; i < oh->opt_clks_cnt; i++)
-		_add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk);
-}
-
-
-/**
- * omap_device_build_from_dt - build an omap_device with multiple hwmods
- * @pdev_name: name of the platform_device driver to use
- * @pdev_id: this platform_device's connection ID
- * @oh: ptr to the single omap_hwmod that backs this omap_device
- * @pdata: platform_data ptr to associate with the platform_device
- * @pdata_len: amount of memory pointed to by @pdata
- * @pm_lats: pointer to a omap_device_pm_latency array for this device
- * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
- * @is_early_device: should the device be registered as an early device or not
- *
- * Function for building an omap_device already registered from device-tree
- *
- * Returns 0 or PTR_ERR() on error.
- */
-static int omap_device_build_from_dt(struct platform_device *pdev)
-{
-	struct omap_hwmod **hwmods;
-	struct omap_device *od;
-	struct omap_hwmod *oh;
-	struct device_node *node = pdev->dev.of_node;
-	const char *oh_name;
-	int oh_cnt, i, ret = 0;
-
-	oh_cnt = of_property_count_strings(node, "ti,hwmods");
-	if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
-		dev_dbg(&pdev->dev, "No 'hwmods' to build omap_device\n");
-		return -ENODEV;
-	}
-
-	hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
-	if (!hwmods) {
-		ret = -ENOMEM;
-		goto odbfd_exit;
-	}
-
-	for (i = 0; i < oh_cnt; i++) {
-		of_property_read_string_index(node, "ti,hwmods", i, &oh_name);
-		oh = omap_hwmod_lookup(oh_name);
-		if (!oh) {
-			dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n",
-				oh_name);
-			ret = -EINVAL;
-			goto odbfd_exit1;
-		}
-		hwmods[i] = oh;
-	}
-
-	od = omap_device_alloc(pdev, hwmods, oh_cnt, NULL, 0);
-	if (!od) {
-		dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
-			oh_name);
-		ret = PTR_ERR(od);
-		goto odbfd_exit1;
-	}
-
-	/* Fix up missing resource names */
-	for (i = 0; i < pdev->num_resources; i++) {
-		struct resource *r = &pdev->resource[i];
-
-		if (r->name == NULL)
-			r->name = dev_name(&pdev->dev);
-	}
-
-	if (of_get_property(node, "ti,no_idle_on_suspend", NULL))
-		omap_device_disable_idle_on_suspend(pdev);
-
-	pdev->dev.pm_domain = &omap_device_pm_domain;
-
-odbfd_exit1:
-	kfree(hwmods);
-odbfd_exit:
-	return ret;
-}
-
-static int _omap_device_notifier_call(struct notifier_block *nb,
-				      unsigned long event, void *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct omap_device *od;
-
-	switch (event) {
-	case BUS_NOTIFY_DEL_DEVICE:
-		if (pdev->archdata.od)
-			omap_device_delete(pdev->archdata.od);
-		break;
-	case BUS_NOTIFY_ADD_DEVICE:
-		if (pdev->dev.of_node)
-			omap_device_build_from_dt(pdev);
-		/* fall through */
-	default:
-		od = to_omap_device(pdev);
-		if (od)
-			od->_driver_status = event;
-	}
-
-	return NOTIFY_DONE;
-}
-
-
-/* Public functions for use by core code */
-
-/**
- * omap_device_get_context_loss_count - get lost context count
- * @od: struct omap_device *
- *
- * Using the primary hwmod, query the context loss count for this
- * device.
- *
- * Callers should consider context for this device lost any time this
- * function returns a value different than the value the caller got
- * the last time it called this function.
- *
- * If any hwmods exist for the omap_device assoiated with @pdev,
- * return the context loss counter for that hwmod, otherwise return
- * zero.
- */
-int omap_device_get_context_loss_count(struct platform_device *pdev)
-{
-	struct omap_device *od;
-	u32 ret = 0;
-
-	od = to_omap_device(pdev);
-
-	if (od->hwmods_cnt)
-		ret = omap_hwmod_get_context_loss_count(od->hwmods[0]);
-
-	return ret;
-}
-
-/**
- * omap_device_count_resources - count number of struct resource entries needed
- * @od: struct omap_device *
- *
- * Count the number of struct resource entries needed for this
- * omap_device @od.  Used by omap_device_build_ss() to determine how
- * much memory to allocate before calling
- * omap_device_fill_resources().  Returns the count.
- */
-static int omap_device_count_resources(struct omap_device *od)
-{
-	int c = 0;
-	int i;
-
-	for (i = 0; i < od->hwmods_cnt; i++)
-		c += omap_hwmod_count_resources(od->hwmods[i]);
-
-	pr_debug("omap_device: %s: counted %d total resources across %d hwmods\n",
-		 od->pdev->name, c, od->hwmods_cnt);
-
-	return c;
-}
-
-/**
- * omap_device_fill_resources - fill in array of struct resource
- * @od: struct omap_device *
- * @res: pointer to an array of struct resource to be filled in
- *
- * Populate one or more empty struct resource pointed to by @res with
- * the resource data for this omap_device @od.  Used by
- * omap_device_build_ss() after calling omap_device_count_resources().
- * Ideally this function would not be needed at all.  If omap_device
- * replaces platform_device, then we can specify our own
- * get_resource()/ get_irq()/etc functions that use the underlying
- * omap_hwmod information.  Or if platform_device is extended to use
- * subarchitecture-specific function pointers, the various
- * platform_device functions can simply call omap_device internal
- * functions to get device resources.  Hacking around the existing
- * platform_device code wastes memory.  Returns 0.
- */
-static int omap_device_fill_resources(struct omap_device *od,
-				      struct resource *res)
-{
-	int i, r;
-
-	for (i = 0; i < od->hwmods_cnt; i++) {
-		r = omap_hwmod_fill_resources(od->hwmods[i], res);
-		res += r;
-	}
-
-	return 0;
-}
-
-/**
- * _od_fill_dma_resources - fill in array of struct resource with dma resources
- * @od: struct omap_device *
- * @res: pointer to an array of struct resource to be filled in
- *
- * Populate one or more empty struct resource pointed to by @res with
- * the dma resource data for this omap_device @od.  Used by
- * omap_device_alloc() after calling omap_device_count_resources().
- *
- * Ideally this function would not be needed at all.  If we have
- * mechanism to get dma resources from DT.
- *
- * Returns 0.
- */
-static int _od_fill_dma_resources(struct omap_device *od,
-				      struct resource *res)
-{
-	int i, r;
-
-	for (i = 0; i < od->hwmods_cnt; i++) {
-		r = omap_hwmod_fill_dma_resources(od->hwmods[i], res);
-		res += r;
-	}
-
-	return 0;
-}
-
-/**
- * omap_device_alloc - allocate an omap_device
- * @pdev: platform_device that will be included in this omap_device
- * @oh: ptr to the single omap_hwmod that backs this omap_device
- * @pdata: platform_data ptr to associate with the platform_device
- * @pdata_len: amount of memory pointed to by @pdata
- * @pm_lats: pointer to a omap_device_pm_latency array for this device
- * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
- *
- * Convenience function for allocating an omap_device structure and filling
- * hwmods, resources and pm_latency attributes.
- *
- * Returns an struct omap_device pointer or ERR_PTR() on error;
- */
-struct omap_device *omap_device_alloc(struct platform_device *pdev,
-					struct omap_hwmod **ohs, int oh_cnt,
-					struct omap_device_pm_latency *pm_lats,
-					int pm_lats_cnt)
-{
-	int ret = -ENOMEM;
-	struct omap_device *od;
-	struct resource *res = NULL;
-	int i, res_count;
-	struct omap_hwmod **hwmods;
-
-	od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
-	if (!od) {
-		ret = -ENOMEM;
-		goto oda_exit1;
-	}
-	od->hwmods_cnt = oh_cnt;
-
-	hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
-	if (!hwmods)
-		goto oda_exit2;
-
-	od->hwmods = hwmods;
-	od->pdev = pdev;
-
-	res_count = omap_device_count_resources(od);
-	/*
-	 * DT Boot:
-	 *   OF framework will construct the resource structure (currently
-	 *   does for MEM & IRQ resource) and we should respect/use these
-	 *   resources, killing hwmod dependency.
-	 *   If pdev->num_resources > 0, we assume that MEM & IRQ resources
-	 *   have been allocated by OF layer already (through DTB).
-	 *
-	 * Non-DT Boot:
-	 *   Here, pdev->num_resources = 0, and we should get all the
-	 *   resources from hwmod.
-	 *
-	 * TODO: Once DMA resource is available from OF layer, we should
-	 *   kill filling any resources from hwmod.
-	 */
-	if (res_count > pdev->num_resources) {
-		/* Allocate resources memory to account for new resources */
-		res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
-		if (!res)
-			goto oda_exit3;
-
-		/*
-		 * If pdev->num_resources > 0, then assume that,
-		 * MEM and IRQ resources will only come from DT and only
-		 * fill DMA resource from hwmod layer.
-		 */
-		if (pdev->num_resources && pdev->resource) {
-			dev_dbg(&pdev->dev, "%s(): resources already allocated %d\n",
-				__func__, res_count);
-			memcpy(res, pdev->resource,
-			       sizeof(struct resource) * pdev->num_resources);
-			_od_fill_dma_resources(od, &res[pdev->num_resources]);
-		} else {
-			dev_dbg(&pdev->dev, "%s(): using resources from hwmod %d\n",
-				__func__, res_count);
-			omap_device_fill_resources(od, res);
-		}
-
-		ret = platform_device_add_resources(pdev, res, res_count);
-		kfree(res);
-
-		if (ret)
-			goto oda_exit3;
-	}
-
-	if (!pm_lats) {
-		pm_lats = omap_default_latency;
-		pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
-	}
-
-	od->pm_lats_cnt = pm_lats_cnt;
-	od->pm_lats = kmemdup(pm_lats,
-			sizeof(struct omap_device_pm_latency) * pm_lats_cnt,
-			GFP_KERNEL);
-	if (!od->pm_lats)
-		goto oda_exit3;
-
-	pdev->archdata.od = od;
-
-	for (i = 0; i < oh_cnt; i++) {
-		hwmods[i]->od = od;
-		_add_hwmod_clocks_clkdev(od, hwmods[i]);
-	}
-
-	return od;
-
-oda_exit3:
-	kfree(hwmods);
-oda_exit2:
-	kfree(od);
-oda_exit1:
-	dev_err(&pdev->dev, "omap_device: build failed (%d)\n", ret);
-
-	return ERR_PTR(ret);
-}
-
-void omap_device_delete(struct omap_device *od)
-{
-	if (!od)
-		return;
-
-	od->pdev->archdata.od = NULL;
-	kfree(od->pm_lats);
-	kfree(od->hwmods);
-	kfree(od);
-}
-
-/**
- * omap_device_build - build and register an omap_device with one omap_hwmod
- * @pdev_name: name of the platform_device driver to use
- * @pdev_id: this platform_device's connection ID
- * @oh: ptr to the single omap_hwmod that backs this omap_device
- * @pdata: platform_data ptr to associate with the platform_device
- * @pdata_len: amount of memory pointed to by @pdata
- * @pm_lats: pointer to a omap_device_pm_latency array for this device
- * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
- * @is_early_device: should the device be registered as an early device or not
- *
- * Convenience function for building and registering a single
- * omap_device record, which in turn builds and registers a
- * platform_device record.  See omap_device_build_ss() for more
- * information.  Returns ERR_PTR(-EINVAL) if @oh is NULL; otherwise,
- * passes along the return value of omap_device_build_ss().
- */
-struct platform_device __init *omap_device_build(const char *pdev_name, int pdev_id,
-				      struct omap_hwmod *oh, void *pdata,
-				      int pdata_len,
-				      struct omap_device_pm_latency *pm_lats,
-				      int pm_lats_cnt, int is_early_device)
-{
-	struct omap_hwmod *ohs[] = { oh };
-
-	if (!oh)
-		return ERR_PTR(-EINVAL);
-
-	return omap_device_build_ss(pdev_name, pdev_id, ohs, 1, pdata,
-				    pdata_len, pm_lats, pm_lats_cnt,
-				    is_early_device);
-}
-
-/**
- * omap_device_build_ss - build and register an omap_device with multiple hwmods
- * @pdev_name: name of the platform_device driver to use
- * @pdev_id: this platform_device's connection ID
- * @oh: ptr to the single omap_hwmod that backs this omap_device
- * @pdata: platform_data ptr to associate with the platform_device
- * @pdata_len: amount of memory pointed to by @pdata
- * @pm_lats: pointer to a omap_device_pm_latency array for this device
- * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
- * @is_early_device: should the device be registered as an early device or not
- *
- * Convenience function for building and registering an omap_device
- * subsystem record.  Subsystem records consist of multiple
- * omap_hwmods.  This function in turn builds and registers a
- * platform_device record.  Returns an ERR_PTR() on error, or passes
- * along the return value of omap_device_register().
- */
-struct platform_device __init *omap_device_build_ss(const char *pdev_name, int pdev_id,
-					 struct omap_hwmod **ohs, int oh_cnt,
-					 void *pdata, int pdata_len,
-					 struct omap_device_pm_latency *pm_lats,
-					 int pm_lats_cnt, int is_early_device)
-{
-	int ret = -ENOMEM;
-	struct platform_device *pdev;
-	struct omap_device *od;
-
-	if (!ohs || oh_cnt == 0 || !pdev_name)
-		return ERR_PTR(-EINVAL);
-
-	if (!pdata && pdata_len > 0)
-		return ERR_PTR(-EINVAL);
-
-	pdev = platform_device_alloc(pdev_name, pdev_id);
-	if (!pdev) {
-		ret = -ENOMEM;
-		goto odbs_exit;
-	}
-
-	/* Set the dev_name early to allow dev_xxx in omap_device_alloc */
-	if (pdev->id != -1)
-		dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
-	else
-		dev_set_name(&pdev->dev, "%s", pdev->name);
-
-	od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt);
-	if (IS_ERR(od))
-		goto odbs_exit1;
-
-	ret = platform_device_add_data(pdev, pdata, pdata_len);
-	if (ret)
-		goto odbs_exit2;
-
-	if (is_early_device)
-		ret = omap_early_device_register(pdev);
-	else
-		ret = omap_device_register(pdev);
-	if (ret)
-		goto odbs_exit2;
-
-	return pdev;
-
-odbs_exit2:
-	omap_device_delete(od);
-odbs_exit1:
-	platform_device_put(pdev);
-odbs_exit:
-
-	pr_err("omap_device: %s: build failed (%d)\n", pdev_name, ret);
-
-	return ERR_PTR(ret);
-}
-
-/**
- * omap_early_device_register - register an omap_device as an early platform
- * device.
- * @od: struct omap_device * to register
- *
- * Register the omap_device structure.  This currently just calls
- * platform_early_add_device() on the underlying platform_device.
- * Returns 0 by default.
- */
-static int __init omap_early_device_register(struct platform_device *pdev)
-{
-	struct platform_device *devices[1];
-
-	devices[0] = pdev;
-	early_platform_add_devices(devices, 1);
-	return 0;
-}
-
-#ifdef CONFIG_PM_RUNTIME
-static int _od_runtime_suspend(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	int ret;
-
-	ret = pm_generic_runtime_suspend(dev);
-
-	if (!ret)
-		omap_device_idle(pdev);
-
-	return ret;
-}
-
-static int _od_runtime_idle(struct device *dev)
-{
-	return pm_generic_runtime_idle(dev);
-}
-
-static int _od_runtime_resume(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-
-	omap_device_enable(pdev);
-
-	return pm_generic_runtime_resume(dev);
-}
-#endif
-
-#ifdef CONFIG_SUSPEND
-static int _od_suspend_noirq(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct omap_device *od = to_omap_device(pdev);
-	int ret;
-
-	/* Don't attempt late suspend on a driver that is not bound */
-	if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER)
-		return 0;
-
-	ret = pm_generic_suspend_noirq(dev);
-
-	if (!ret && !pm_runtime_status_suspended(dev)) {
-		if (pm_generic_runtime_suspend(dev) == 0) {
-			if (!(od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND))
-				omap_device_idle(pdev);
-			od->flags |= OMAP_DEVICE_SUSPENDED;
-		}
-	}
-
-	return ret;
-}
-
-static int _od_resume_noirq(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct omap_device *od = to_omap_device(pdev);
-
-	if ((od->flags & OMAP_DEVICE_SUSPENDED) &&
-	    !pm_runtime_status_suspended(dev)) {
-		od->flags &= ~OMAP_DEVICE_SUSPENDED;
-		if (!(od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND))
-			omap_device_enable(pdev);
-		pm_generic_runtime_resume(dev);
-	}
-
-	return pm_generic_resume_noirq(dev);
-}
-#else
-#define _od_suspend_noirq NULL
-#define _od_resume_noirq NULL
-#endif
-
-struct dev_pm_domain omap_device_pm_domain = {
-	.ops = {
-		SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
-				   _od_runtime_idle)
-		USE_PLATFORM_PM_SLEEP_OPS
-		.suspend_noirq = _od_suspend_noirq,
-		.resume_noirq = _od_resume_noirq,
-	}
-};
-
-/**
- * omap_device_register - register an omap_device with one omap_hwmod
- * @od: struct omap_device * to register
- *
- * Register the omap_device structure.  This currently just calls
- * platform_device_register() on the underlying platform_device.
- * Returns the return value of platform_device_register().
- */
-int omap_device_register(struct platform_device *pdev)
-{
-	pr_debug("omap_device: %s: registering\n", pdev->name);
-
-	pdev->dev.pm_domain = &omap_device_pm_domain;
-	return platform_device_add(pdev);
-}
-
-
-/* Public functions for use by device drivers through struct platform_data */
-
-/**
- * omap_device_enable - fully activate an omap_device
- * @od: struct omap_device * to activate
- *
- * Do whatever is necessary for the hwmods underlying omap_device @od
- * to be accessible and ready to operate.  This generally involves
- * enabling clocks, setting SYSCONFIG registers; and in the future may
- * involve remuxing pins.  Device drivers should call this function
- * (through platform_data function pointers) where they would normally
- * enable clocks, etc.  Returns -EINVAL if called when the omap_device
- * is already enabled, or passes along the return value of
- * _omap_device_activate().
- */
-int omap_device_enable(struct platform_device *pdev)
-{
-	int ret;
-	struct omap_device *od;
-
-	od = to_omap_device(pdev);
-
-	if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
-		dev_warn(&pdev->dev,
-			 "omap_device: %s() called from invalid state %d\n",
-			 __func__, od->_state);
-		return -EINVAL;
-	}
-
-	/* Enable everything if we're enabling this device from scratch */
-	if (od->_state == OMAP_DEVICE_STATE_UNKNOWN)
-		od->pm_lat_level = od->pm_lats_cnt;
-
-	ret = _omap_device_activate(od, IGNORE_WAKEUP_LAT);
-
-	od->dev_wakeup_lat = 0;
-	od->_dev_wakeup_lat_limit = UINT_MAX;
-	od->_state = OMAP_DEVICE_STATE_ENABLED;
-
-	return ret;
-}
-
-/**
- * omap_device_idle - idle an omap_device
- * @od: struct omap_device * to idle
- *
- * Idle omap_device @od by calling as many .deactivate_func() entries
- * in the omap_device's pm_lats table as is possible without exceeding
- * the device's maximum wakeup latency limit, pm_lat_limit.  Device
- * drivers should call this function (through platform_data function
- * pointers) where they would normally disable clocks after operations
- * complete, etc..  Returns -EINVAL if the omap_device is not
- * currently enabled, or passes along the return value of
- * _omap_device_deactivate().
- */
-int omap_device_idle(struct platform_device *pdev)
-{
-	int ret;
-	struct omap_device *od;
-
-	od = to_omap_device(pdev);
-
-	if (od->_state != OMAP_DEVICE_STATE_ENABLED) {
-		dev_warn(&pdev->dev,
-			 "omap_device: %s() called from invalid state %d\n",
-			 __func__, od->_state);
-		return -EINVAL;
-	}
-
-	ret = _omap_device_deactivate(od, USE_WAKEUP_LAT);
-
-	od->_state = OMAP_DEVICE_STATE_IDLE;
-
-	return ret;
-}
-
-/**
- * omap_device_shutdown - shut down an omap_device
- * @od: struct omap_device * to shut down
- *
- * Shut down omap_device @od by calling all .deactivate_func() entries
- * in the omap_device's pm_lats table and then shutting down all of
- * the underlying omap_hwmods.  Used when a device is being "removed"
- * or a device driver is being unloaded.  Returns -EINVAL if the
- * omap_device is not currently enabled or idle, or passes along the
- * return value of _omap_device_deactivate().
- */
-int omap_device_shutdown(struct platform_device *pdev)
-{
-	int ret, i;
-	struct omap_device *od;
-
-	od = to_omap_device(pdev);
-
-	if (od->_state != OMAP_DEVICE_STATE_ENABLED &&
-	    od->_state != OMAP_DEVICE_STATE_IDLE) {
-		dev_warn(&pdev->dev,
-			 "omap_device: %s() called from invalid state %d\n",
-			 __func__, od->_state);
-		return -EINVAL;
-	}
-
-	ret = _omap_device_deactivate(od, IGNORE_WAKEUP_LAT);
-
-	for (i = 0; i < od->hwmods_cnt; i++)
-		omap_hwmod_shutdown(od->hwmods[i]);
-
-	od->_state = OMAP_DEVICE_STATE_SHUTDOWN;
-
-	return ret;
-}
-
-/**
- * omap_device_assert_hardreset - set a device's hardreset line
- * @pdev: struct platform_device * to reset
- * @name: const char * name of the reset line
- *
- * Set the hardreset line identified by @name on the IP blocks
- * associated with the hwmods backing the platform_device @pdev.  All
- * of the hwmods associated with @pdev must have the same hardreset
- * line linked to them for this to work.  Passes along the return value
- * of omap_hwmod_assert_hardreset() in the event of any failure, or
- * returns 0 upon success.
- */
-int omap_device_assert_hardreset(struct platform_device *pdev, const char *name)
-{
-	struct omap_device *od = to_omap_device(pdev);
-	int ret = 0;
-	int i;
-
-	for (i = 0; i < od->hwmods_cnt; i++) {
-		ret = omap_hwmod_assert_hardreset(od->hwmods[i], name);
-		if (ret)
-			break;
-	}
-
-	return ret;
-}
-
-/**
- * omap_device_deassert_hardreset - release a device's hardreset line
- * @pdev: struct platform_device * to reset
- * @name: const char * name of the reset line
- *
- * Release the hardreset line identified by @name on the IP blocks
- * associated with the hwmods backing the platform_device @pdev.  All
- * of the hwmods associated with @pdev must have the same hardreset
- * line linked to them for this to work.  Passes along the return
- * value of omap_hwmod_deassert_hardreset() in the event of any
- * failure, or returns 0 upon success.
- */
-int omap_device_deassert_hardreset(struct platform_device *pdev,
-				   const char *name)
-{
-	struct omap_device *od = to_omap_device(pdev);
-	int ret = 0;
-	int i;
-
-	for (i = 0; i < od->hwmods_cnt; i++) {
-		ret = omap_hwmod_deassert_hardreset(od->hwmods[i], name);
-		if (ret)
-			break;
-	}
-
-	return ret;
-}
-
-/**
- * omap_device_align_pm_lat - activate/deactivate device to match wakeup lat lim
- * @od: struct omap_device *
- *
- * When a device's maximum wakeup latency limit changes, call some of
- * the .activate_func or .deactivate_func function pointers in the
- * omap_device's pm_lats array to ensure that the device's maximum
- * wakeup latency is less than or equal to the new latency limit.
- * Intended to be called by OMAP PM code whenever a device's maximum
- * wakeup latency limit changes (e.g., via
- * omap_pm_set_dev_wakeup_lat()).  Returns 0 if nothing needs to be
- * done (e.g., if the omap_device is not currently idle, or if the
- * wakeup latency is already current with the new limit) or passes
- * along the return value of _omap_device_deactivate() or
- * _omap_device_activate().
- */
-int omap_device_align_pm_lat(struct platform_device *pdev,
-			     u32 new_wakeup_lat_limit)
-{
-	int ret = -EINVAL;
-	struct omap_device *od;
-
-	od = to_omap_device(pdev);
-
-	if (new_wakeup_lat_limit == od->dev_wakeup_lat)
-		return 0;
-
-	od->_dev_wakeup_lat_limit = new_wakeup_lat_limit;
-
-	if (od->_state != OMAP_DEVICE_STATE_IDLE)
-		return 0;
-	else if (new_wakeup_lat_limit > od->dev_wakeup_lat)
-		ret = _omap_device_deactivate(od, USE_WAKEUP_LAT);
-	else if (new_wakeup_lat_limit < od->dev_wakeup_lat)
-		ret = _omap_device_activate(od, USE_WAKEUP_LAT);
-
-	return ret;
-}
-
-/**
- * omap_device_get_pwrdm - return the powerdomain * associated with @od
- * @od: struct omap_device *
- *
- * Return the powerdomain associated with the first underlying
- * omap_hwmod for this omap_device.  Intended for use by core OMAP PM
- * code.  Returns NULL on error or a struct powerdomain * upon
- * success.
- */
-struct powerdomain *omap_device_get_pwrdm(struct omap_device *od)
-{
-	/*
-	 * XXX Assumes that all omap_hwmod powerdomains are identical.
-	 * This may not necessarily be true.  There should be a sanity
-	 * check in here to WARN() if any difference appears.
-	 */
-	if (!od->hwmods_cnt)
-		return NULL;
-
-	return omap_hwmod_get_pwrdm(od->hwmods[0]);
-}
-
-/**
- * omap_device_get_mpu_rt_va - return the MPU's virtual addr for the hwmod base
- * @od: struct omap_device *
- *
- * Return the MPU's virtual address for the base of the hwmod, from
- * the ioremap() that the hwmod code does.  Only valid if there is one
- * hwmod associated with this device.  Returns NULL if there are zero
- * or more than one hwmods associated with this omap_device;
- * otherwise, passes along the return value from
- * omap_hwmod_get_mpu_rt_va().
- */
-void __iomem *omap_device_get_rt_va(struct omap_device *od)
-{
-	if (od->hwmods_cnt != 1)
-		return NULL;
-
-	return omap_hwmod_get_mpu_rt_va(od->hwmods[0]);
-}
-
-/**
- * omap_device_get_by_hwmod_name() - convert a hwmod name to
- * device pointer.
- * @oh_name: name of the hwmod device
- *
- * Returns back a struct device * pointer associated with a hwmod
- * device represented by a hwmod_name
- */
-struct device *omap_device_get_by_hwmod_name(const char *oh_name)
-{
-	struct omap_hwmod *oh;
-
-	if (!oh_name) {
-		WARN(1, "%s: no hwmod name!\n", __func__);
-		return ERR_PTR(-EINVAL);
-	}
-
-	oh = omap_hwmod_lookup(oh_name);
-	if (IS_ERR_OR_NULL(oh)) {
-		WARN(1, "%s: no hwmod for %s\n", __func__,
-			oh_name);
-		return ERR_PTR(oh ? PTR_ERR(oh) : -ENODEV);
-	}
-	if (IS_ERR_OR_NULL(oh->od)) {
-		WARN(1, "%s: no omap_device for %s\n", __func__,
-			oh_name);
-		return ERR_PTR(oh->od ? PTR_ERR(oh->od) : -ENODEV);
-	}
-
-	if (IS_ERR_OR_NULL(oh->od->pdev))
-		return ERR_PTR(oh->od->pdev ? PTR_ERR(oh->od->pdev) : -ENODEV);
-
-	return &oh->od->pdev->dev;
-}
-EXPORT_SYMBOL(omap_device_get_by_hwmod_name);
-
-/*
- * Public functions intended for use in omap_device_pm_latency
- * .activate_func and .deactivate_func function pointers
- */
-
-/**
- * omap_device_enable_hwmods - call omap_hwmod_enable() on all hwmods
- * @od: struct omap_device *od
- *
- * Enable all underlying hwmods.  Returns 0.
- */
-int omap_device_enable_hwmods(struct omap_device *od)
-{
-	int i;
-
-	for (i = 0; i < od->hwmods_cnt; i++)
-		omap_hwmod_enable(od->hwmods[i]);
-
-	/* XXX pass along return value here? */
-	return 0;
-}
-
-/**
- * omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods
- * @od: struct omap_device *od
- *
- * Idle all underlying hwmods.  Returns 0.
- */
-int omap_device_idle_hwmods(struct omap_device *od)
-{
-	int i;
-
-	for (i = 0; i < od->hwmods_cnt; i++)
-		omap_hwmod_idle(od->hwmods[i]);
-
-	/* XXX pass along return value here? */
-	return 0;
-}
-
-/**
- * omap_device_disable_clocks - disable all main and interface clocks
- * @od: struct omap_device *od
- *
- * Disable the main functional clock and interface clock for all of the
- * omap_hwmods associated with the omap_device.  Returns 0.
- */
-int omap_device_disable_clocks(struct omap_device *od)
-{
-	int i;
-
-	for (i = 0; i < od->hwmods_cnt; i++)
-		omap_hwmod_disable_clocks(od->hwmods[i]);
-
-	/* XXX pass along return value here? */
-	return 0;
-}
-
-/**
- * omap_device_enable_clocks - enable all main and interface clocks
- * @od: struct omap_device *od
- *
- * Enable the main functional clock and interface clock for all of the
- * omap_hwmods associated with the omap_device.  Returns 0.
- */
-int omap_device_enable_clocks(struct omap_device *od)
-{
-	int i;
-
-	for (i = 0; i < od->hwmods_cnt; i++)
-		omap_hwmod_enable_clocks(od->hwmods[i]);
-
-	/* XXX pass along return value here? */
-	return 0;
-}
-
-static struct notifier_block platform_nb = {
-	.notifier_call = _omap_device_notifier_call,
-};
-
-static int __init omap_device_init(void)
-{
-	bus_register_notifier(&platform_bus_type, &platform_nb);
-	return 0;
-}
-core_initcall(omap_device_init);
-
-/**
- * omap_device_late_idle - idle devices without drivers
- * @dev: struct device * associated with omap_device
- * @data: unused
- *
- * Check the driver bound status of this device, and idle it
- * if there is no driver attached.
- */
-static int __init omap_device_late_idle(struct device *dev, void *data)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct omap_device *od = to_omap_device(pdev);
-
-	if (!od)
-		return 0;
-
-	/*
-	 * If omap_device state is enabled, but has no driver bound,
-	 * idle it.
-	 */
-	if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
-		if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
-			dev_warn(dev, "%s: enabled but no driver.  Idling\n",
-				 __func__);
-			omap_device_idle(pdev);
-		}
-	}
-
-	return 0;
-}
-
-static int __init omap_device_late_init(void)
-{
-	bus_for_each_dev(&platform_bus_type, NULL, NULL, omap_device_late_idle);
-	return 0;
-}
-late_initcall(omap_device_late_init);
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 28acb38..743fc28 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -20,198 +20,20 @@
 #include <linux/init.h>
 #include <linux/io.h>
 
+#include <asm/fncpy.h>
 #include <asm/tlb.h>
 #include <asm/cacheflush.h>
 
 #include <asm/mach/map.h>
 
-#include <plat/sram.h>
-#include <plat/cpu.h>
-
-#include "sram.h"
-
-/* XXX These "sideways" includes will disappear when sram.c becomes a driver */
-#include "../mach-omap2/iomap.h"
-#include "../mach-omap2/prm2xxx_3xxx.h"
-#include "../mach-omap2/sdrc.h"
-
-#define OMAP1_SRAM_PA		0x20000000
-#define OMAP2_SRAM_PUB_PA	(OMAP2_SRAM_PA + 0xf800)
-#define OMAP3_SRAM_PUB_PA       (OMAP3_SRAM_PA + 0x8000)
-#ifdef CONFIG_OMAP4_ERRATA_I688
-#define OMAP4_SRAM_PUB_PA	OMAP4_SRAM_PA
-#else
-#define OMAP4_SRAM_PUB_PA	(OMAP4_SRAM_PA + 0x4000)
-#endif
-#define OMAP5_SRAM_PA		0x40300000
-
-#if defined(CONFIG_ARCH_OMAP2PLUS)
-#define SRAM_BOOTLOADER_SZ	0x00
-#else
-#define SRAM_BOOTLOADER_SZ	0x80
-#endif
-
-#define OMAP24XX_VA_REQINFOPERM0	OMAP2_L3_IO_ADDRESS(0x68005048)
-#define OMAP24XX_VA_READPERM0		OMAP2_L3_IO_ADDRESS(0x68005050)
-#define OMAP24XX_VA_WRITEPERM0		OMAP2_L3_IO_ADDRESS(0x68005058)
-
-#define OMAP34XX_VA_REQINFOPERM0	OMAP2_L3_IO_ADDRESS(0x68012848)
-#define OMAP34XX_VA_READPERM0		OMAP2_L3_IO_ADDRESS(0x68012850)
-#define OMAP34XX_VA_WRITEPERM0		OMAP2_L3_IO_ADDRESS(0x68012858)
-#define OMAP34XX_VA_ADDR_MATCH2		OMAP2_L3_IO_ADDRESS(0x68012880)
-#define OMAP34XX_VA_SMS_RG_ATT0		OMAP2_L3_IO_ADDRESS(0x6C000048)
-
-#define GP_DEVICE		0x300
-
 #define ROUND_DOWN(value,boundary)	((value) & (~((boundary)-1)))
 
-static unsigned long omap_sram_start;
 static void __iomem *omap_sram_base;
 static unsigned long omap_sram_skip;
 static unsigned long omap_sram_size;
 static void __iomem *omap_sram_ceil;
 
 /*
- * Depending on the target RAMFS firewall setup, the public usable amount of
- * SRAM varies.  The default accessible size for all device types is 2k. A GP
- * device allows ARM11 but not other initiators for full size. This
- * functionality seems ok until some nice security API happens.
- */
-static int is_sram_locked(void)
-{
-	if (OMAP2_DEVICE_TYPE_GP == omap_type()) {
-		/* RAMFW: R/W access to all initiators for all qualifier sets */
-		if (cpu_is_omap242x()) {
-			__raw_writel(0xFF, OMAP24XX_VA_REQINFOPERM0); /* all q-vects */
-			__raw_writel(0xCFDE, OMAP24XX_VA_READPERM0);  /* all i-read */
-			__raw_writel(0xCFDE, OMAP24XX_VA_WRITEPERM0); /* all i-write */
-		}
-		if (cpu_is_omap34xx()) {
-			__raw_writel(0xFFFF, OMAP34XX_VA_REQINFOPERM0); /* all q-vects */
-			__raw_writel(0xFFFF, OMAP34XX_VA_READPERM0);  /* all i-read */
-			__raw_writel(0xFFFF, OMAP34XX_VA_WRITEPERM0); /* all i-write */
-			__raw_writel(0x0, OMAP34XX_VA_ADDR_MATCH2);
-			__raw_writel(0xFFFFFFFF, OMAP34XX_VA_SMS_RG_ATT0);
-		}
-		return 0;
-	} else
-		return 1; /* assume locked with no PPA or security driver */
-}
-
-/*
- * The amount of SRAM depends on the core type.
- * Note that we cannot try to test for SRAM here because writes
- * to secure SRAM will hang the system. Also the SRAM is not
- * yet mapped at this point.
- */
-static void __init omap_detect_sram(void)
-{
-	omap_sram_skip = SRAM_BOOTLOADER_SZ;
-	if (cpu_class_is_omap2()) {
-		if (is_sram_locked()) {
-			if (cpu_is_omap34xx()) {
-				omap_sram_start = OMAP3_SRAM_PUB_PA;
-				if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) ||
-				    (omap_type() == OMAP2_DEVICE_TYPE_SEC)) {
-					omap_sram_size = 0x7000; /* 28K */
-					omap_sram_skip += SZ_16K;
-				} else {
-					omap_sram_size = 0x8000; /* 32K */
-				}
-			} else if (cpu_is_omap44xx()) {
-				omap_sram_start = OMAP4_SRAM_PUB_PA;
-				omap_sram_size = 0xa000; /* 40K */
-			} else if (soc_is_omap54xx()) {
-				omap_sram_start = OMAP5_SRAM_PA;
-				omap_sram_size = SZ_128K; /* 128KB */
-			} else {
-				omap_sram_start = OMAP2_SRAM_PUB_PA;
-				omap_sram_size = 0x800; /* 2K */
-			}
-		} else {
-			if (soc_is_am33xx()) {
-				omap_sram_start = AM33XX_SRAM_PA;
-				omap_sram_size = 0x10000; /* 64K */
-			} else if (cpu_is_omap34xx()) {
-				omap_sram_start = OMAP3_SRAM_PA;
-				omap_sram_size = 0x10000; /* 64K */
-			} else if (cpu_is_omap44xx()) {
-				omap_sram_start = OMAP4_SRAM_PA;
-				omap_sram_size = 0xe000; /* 56K */
-			} else if (soc_is_omap54xx()) {
-				omap_sram_start = OMAP5_SRAM_PA;
-				omap_sram_size = SZ_128K; /* 128KB */
-			} else {
-				omap_sram_start = OMAP2_SRAM_PA;
-				if (cpu_is_omap242x())
-					omap_sram_size = 0xa0000; /* 640K */
-				else if (cpu_is_omap243x())
-					omap_sram_size = 0x10000; /* 64K */
-			}
-		}
-	} else {
-		omap_sram_start = OMAP1_SRAM_PA;
-
-		if (cpu_is_omap7xx())
-			omap_sram_size = 0x32000;	/* 200K */
-		else if (cpu_is_omap15xx())
-			omap_sram_size = 0x30000;	/* 192K */
-		else if (cpu_is_omap1610() || cpu_is_omap1611() ||
-				cpu_is_omap1621() || cpu_is_omap1710())
-			omap_sram_size = 0x4000;	/* 16K */
-		else {
-			pr_err("Could not detect SRAM size\n");
-			omap_sram_size = 0x4000;
-		}
-	}
-}
-
-/*
- * Note that we cannot use ioremap for SRAM, as clock init needs SRAM early.
- */
-static void __init omap_map_sram(void)
-{
-	int cached = 1;
-
-	if (omap_sram_size == 0)
-		return;
-
-#ifdef CONFIG_OMAP4_ERRATA_I688
-	if (cpu_is_omap44xx()) {
-		omap_sram_start += PAGE_SIZE;
-		omap_sram_size -= SZ_16K;
-	}
-#endif
-	if (cpu_is_omap34xx()) {
-		/*
-		 * SRAM must be marked as non-cached on OMAP3 since the
-		 * CORE DPLL M2 divider change code (in SRAM) runs with the
-		 * SDRAM controller disabled, and if it is marked cached,
-		 * the ARM may attempt to write cache lines back to SDRAM
-		 * which will cause the system to hang.
-		 */
-		cached = 0;
-	}
-
-	omap_sram_start = ROUND_DOWN(omap_sram_start, PAGE_SIZE);
-	omap_sram_base = __arm_ioremap_exec(omap_sram_start, omap_sram_size,
-						cached);
-	if (!omap_sram_base) {
-		pr_err("SRAM: Could not map\n");
-		return;
-	}
-
-	omap_sram_ceil = omap_sram_base + omap_sram_size;
-
-	/*
-	 * Looks like we need to preserve some bootloader code at the
-	 * beginning of SRAM for jumping to flash for reboot to work...
-	 */
-	memset_io(omap_sram_base + omap_sram_skip, 0,
-		  omap_sram_size - omap_sram_skip);
-}
-
-/*
  * Memory allocator for SRAM: calculates the new ceiling address
  * for pushing a function using the fncpy API.
  *
@@ -236,171 +58,39 @@ void *omap_sram_push_address(unsigned long size)
 	return (void *)omap_sram_ceil;
 }
 
-#ifdef CONFIG_ARCH_OMAP1
-
-static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl);
-
-void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl)
-{
-	BUG_ON(!_omap_sram_reprogram_clock);
-	/* On 730, bit 13 must always be 1 */
-	if (cpu_is_omap7xx())
-		ckctl |= 0x2000;
-	_omap_sram_reprogram_clock(dpllctl, ckctl);
-}
-
-static int __init omap1_sram_init(void)
-{
-	_omap_sram_reprogram_clock =
-			omap_sram_push(omap1_sram_reprogram_clock,
-					omap1_sram_reprogram_clock_sz);
-
-	return 0;
-}
-
-#else
-#define omap1_sram_init()	do {} while (0)
-#endif
-
-#if defined(CONFIG_ARCH_OMAP2)
-
-static void (*_omap2_sram_ddr_init)(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
-			      u32 base_cs, u32 force_unlock);
-
-void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
-		   u32 base_cs, u32 force_unlock)
-{
-	BUG_ON(!_omap2_sram_ddr_init);
-	_omap2_sram_ddr_init(slow_dll_ctrl, fast_dll_ctrl,
-			     base_cs, force_unlock);
-}
-
-static void (*_omap2_sram_reprogram_sdrc)(u32 perf_level, u32 dll_val,
-					  u32 mem_type);
-
-void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, u32 mem_type)
-{
-	BUG_ON(!_omap2_sram_reprogram_sdrc);
-	_omap2_sram_reprogram_sdrc(perf_level, dll_val, mem_type);
-}
-
-static u32 (*_omap2_set_prcm)(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
-
-u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass)
-{
-	BUG_ON(!_omap2_set_prcm);
-	return _omap2_set_prcm(dpll_ctrl_val, sdrc_rfr_val, bypass);
-}
-#endif
-
-#ifdef CONFIG_SOC_OMAP2420
-static int __init omap242x_sram_init(void)
-{
-	_omap2_sram_ddr_init = omap_sram_push(omap242x_sram_ddr_init,
-					omap242x_sram_ddr_init_sz);
-
-	_omap2_sram_reprogram_sdrc = omap_sram_push(omap242x_sram_reprogram_sdrc,
-					    omap242x_sram_reprogram_sdrc_sz);
-
-	_omap2_set_prcm = omap_sram_push(omap242x_sram_set_prcm,
-					 omap242x_sram_set_prcm_sz);
-
-	return 0;
-}
-#else
-static inline int omap242x_sram_init(void)
-{
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_SOC_OMAP2430
-static int __init omap243x_sram_init(void)
-{
-	_omap2_sram_ddr_init = omap_sram_push(omap243x_sram_ddr_init,
-					omap243x_sram_ddr_init_sz);
-
-	_omap2_sram_reprogram_sdrc = omap_sram_push(omap243x_sram_reprogram_sdrc,
-					    omap243x_sram_reprogram_sdrc_sz);
-
-	_omap2_set_prcm = omap_sram_push(omap243x_sram_set_prcm,
-					 omap243x_sram_set_prcm_sz);
-
-	return 0;
-}
-#else
-static inline int omap243x_sram_init(void)
-{
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_ARCH_OMAP3
-
-static u32 (*_omap3_sram_configure_core_dpll)(
-			u32 m2, u32 unlock_dll, u32 f, u32 inc,
-			u32 sdrc_rfr_ctrl_0, u32 sdrc_actim_ctrl_a_0,
-			u32 sdrc_actim_ctrl_b_0, u32 sdrc_mr_0,
-			u32 sdrc_rfr_ctrl_1, u32 sdrc_actim_ctrl_a_1,
-			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
-
-u32 omap3_configure_core_dpll(u32 m2, u32 unlock_dll, u32 f, u32 inc,
-			u32 sdrc_rfr_ctrl_0, u32 sdrc_actim_ctrl_a_0,
-			u32 sdrc_actim_ctrl_b_0, u32 sdrc_mr_0,
-			u32 sdrc_rfr_ctrl_1, u32 sdrc_actim_ctrl_a_1,
-			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1)
-{
-	BUG_ON(!_omap3_sram_configure_core_dpll);
-	return _omap3_sram_configure_core_dpll(
-			m2, unlock_dll, f, inc,
-			sdrc_rfr_ctrl_0, sdrc_actim_ctrl_a_0,
-			sdrc_actim_ctrl_b_0, sdrc_mr_0,
-			sdrc_rfr_ctrl_1, sdrc_actim_ctrl_a_1,
-			sdrc_actim_ctrl_b_1, sdrc_mr_1);
-}
-
-void omap3_sram_restore_context(void)
+/*
+ * The SRAM context is lost during off-idle and stack
+ * needs to be reset.
+ */
+void omap_sram_reset(void)
 {
 	omap_sram_ceil = omap_sram_base + omap_sram_size;
-
-	_omap3_sram_configure_core_dpll =
-		omap_sram_push(omap3_sram_configure_core_dpll,
-			       omap3_sram_configure_core_dpll_sz);
-	omap_push_sram_idle();
 }
 
-static inline int omap34xx_sram_init(void)
-{
-	omap3_sram_restore_context();
-	return 0;
-}
-#else
-static inline int omap34xx_sram_init(void)
-{
-	return 0;
-}
-#endif /* CONFIG_ARCH_OMAP3 */
-
-static inline int am33xx_sram_init(void)
+/*
+ * Note that we cannot use ioremap for SRAM, as clock init needs SRAM early.
+ */
+void __init omap_map_sram(unsigned long start, unsigned long size,
+				 unsigned long skip, int cached)
 {
-	return 0;
-}
+	if (size == 0)
+		return;
 
-int __init omap_sram_init(void)
-{
-	omap_detect_sram();
-	omap_map_sram();
+	start = ROUND_DOWN(start, PAGE_SIZE);
+	omap_sram_size = size;
+	omap_sram_skip = skip;
+	omap_sram_base = __arm_ioremap_exec(start, size, cached);
+	if (!omap_sram_base) {
+		pr_err("SRAM: Could not map\n");
+		return;
+	}
 
-	if (!(cpu_class_is_omap2()))
-		omap1_sram_init();
-	else if (cpu_is_omap242x())
-		omap242x_sram_init();
-	else if (cpu_is_omap2430())
-		omap243x_sram_init();
-	else if (soc_is_am33xx())
-		am33xx_sram_init();
-	else if (cpu_is_omap34xx())
-		omap34xx_sram_init();
+	omap_sram_reset();
 
-	return 0;
+	/*
+	 * Looks like we need to preserve some bootloader code at the
+	 * beginning of SRAM for jumping to flash for reboot to work...
+	 */
+	memset_io(omap_sram_base + omap_sram_skip, 0,
+		  omap_sram_size - omap_sram_skip);
 }
diff --git a/arch/arm/plat-omap/sram.h b/arch/arm/plat-omap/sram.h
deleted file mode 100644
index 29b43ef..0000000
--- a/arch/arm/plat-omap/sram.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __PLAT_OMAP_SRAM_H__
-#define __PLAT_OMAP_SRAM_H__
-
-extern int __init omap_sram_init(void);
-
-#endif /* __PLAT_OMAP_SRAM_H__ */
diff --git a/arch/arm/plat-orion/irq.c b/arch/arm/plat-orion/irq.c
index 1867944..8db0b98 100644
--- a/arch/arm/plat-orion/irq.c
+++ b/arch/arm/plat-orion/irq.c
@@ -41,7 +41,7 @@ void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr)
 static int __init orion_add_irq_domain(struct device_node *np,
 				       struct device_node *interrupt_parent)
 {
-	int i = 0, irq_gpio;
+	int i = 0;
 	void __iomem *base;
 
 	do {
@@ -54,10 +54,6 @@ static int __init orion_add_irq_domain(struct device_node *np,
 
 	irq_domain_add_legacy(np, i * 32, 0, 0,
 			      &irq_domain_simple_ops, NULL);
-
-	irq_gpio = i * 32;
-	orion_gpio_of_init(irq_gpio);
-
 	return 0;
 }
 
diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile
index af8e484..1fc9419 100644
--- a/arch/arm/plat-pxa/Makefile
+++ b/arch/arm/plat-pxa/Makefile
@@ -5,7 +5,6 @@
 obj-y	:= dma.o
 
 obj-$(CONFIG_PXA3xx)		+= mfp.o
-obj-$(CONFIG_PXA95x)		+= mfp.o
 obj-$(CONFIG_ARCH_MMP)		+= mfp.o
 
 obj-$(CONFIG_PXA_SSP)		+= ssp.o
diff --git a/arch/arm/plat-pxa/include/plat/mfp.h b/arch/arm/plat-pxa/include/plat/mfp.h
index 5c79c29..10bc4f3 100644
--- a/arch/arm/plat-pxa/include/plat/mfp.h
+++ b/arch/arm/plat-pxa/include/plat/mfp.h
@@ -423,7 +423,7 @@ typedef unsigned long mfp_cfg_t;
 	((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DS_MASK | MFP_LPM_STATE_MASK)) |\
 	 (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_##drv | MFP_LPM_##lpm))
 
-#if defined(CONFIG_PXA3xx) || defined(CONFIG_PXA95x) || defined(CONFIG_ARCH_MMP)
+#if defined(CONFIG_PXA3xx) || defined(CONFIG_ARCH_MMP)
 /*
  * each MFP pin will have a MFPR register, since the offset of the
  * register varies between processors, the processor specific code
@@ -470,6 +470,6 @@ void mfp_write(int mfp, unsigned long mfpr_val);
 void mfp_config(unsigned long *mfp_cfgs, int num);
 void mfp_config_run(void);
 void mfp_config_lpm(void);
-#endif /* CONFIG_PXA3xx || CONFIG_PXA95x || CONFIG_ARCH_MMP */
+#endif /* CONFIG_PXA3xx || CONFIG_ARCH_MMP */
 
 #endif /* __ASM_PLAT_MFP_H */
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index db98e70..ba3e76c 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -325,7 +325,7 @@ static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
 
 	chan->state = S3C2410_DMA_RUNNING;
 
-	/* check wether there is anything to load, and if not, see
+	/* check whether there is anything to load, and if not, see
 	 * if we can find anything to load
 	 */
 
@@ -473,12 +473,13 @@ int s3c2410_dma_enqueue(enum dma_ch channel, void *id,
 		pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
 			 chan->number, __func__, buf);
 
-		if (chan->end == NULL)
+		if (chan->end == NULL) {
 			pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
 				 chan->number, __func__, chan);
-
-		chan->end->next = buf;
-		chan->end = buf;
+		} else {
+			chan->end->next = buf;
+			chan->end = buf;
+		}
 	}
 
 	/* if necessary, update the next buffer field */
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 59401e1..a9d5216 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -414,6 +414,11 @@ config S5P_SETUP_MIPIPHY
 	help
 	  Compile in common setup code for MIPI-CSIS and MIPI-DSIM devices
 
+config S3C_SETUP_CAMIF
+	bool
+	help
+	  Compile in common setup code for S3C CAMIF devices
+
 # DMA
 
 config S3C_DMA
@@ -502,5 +507,6 @@ config DEBUG_S3C_UART
 	default "0" if DEBUG_S3C_UART0
 	default "1" if DEBUG_S3C_UART1
 	default "2" if DEBUG_S3C_UART2
+	default "3" if DEBUG_S3C_UART3
 
 endif
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 9e40e8d..3a7c64d 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_S5P_DEV_UART)	+= s5p-dev-uart.o
 
 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/adc.c b/arch/arm/plat-samsung/adc.c
index b1e05cc..37542c2 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c
@@ -344,7 +344,7 @@ static int s3c_adc_probe(struct platform_device *pdev)
 	int ret;
 	unsigned tmp;
 
-	adc = kzalloc(sizeof(struct adc_device), GFP_KERNEL);
+	adc = devm_kzalloc(dev, sizeof(struct adc_device), GFP_KERNEL);
 	if (adc == NULL) {
 		dev_err(dev, "failed to allocate adc_device\n");
 		return -ENOMEM;
@@ -355,50 +355,46 @@ static int s3c_adc_probe(struct platform_device *pdev)
 	adc->pdev = pdev;
 	adc->prescale = S3C2410_ADCCON_PRSCVL(49);
 
-	adc->vdd = regulator_get(dev, "vdd");
+	adc->vdd = devm_regulator_get(dev, "vdd");
 	if (IS_ERR(adc->vdd)) {
 		dev_err(dev, "operating without regulator \"vdd\" .\n");
-		ret = PTR_ERR(adc->vdd);
-		goto err_alloc;
+		return PTR_ERR(adc->vdd);
 	}
 
 	adc->irq = platform_get_irq(pdev, 1);
 	if (adc->irq <= 0) {
 		dev_err(dev, "failed to get adc irq\n");
-		ret = -ENOENT;
-		goto err_reg;
+		return -ENOENT;
 	}
 
-	ret = request_irq(adc->irq, s3c_adc_irq, 0, dev_name(dev), adc);
+	ret = devm_request_irq(dev, adc->irq, s3c_adc_irq, 0, dev_name(dev),
+				adc);
 	if (ret < 0) {
 		dev_err(dev, "failed to attach adc irq\n");
-		goto err_reg;
+		return ret;
 	}
 
-	adc->clk = clk_get(dev, "adc");
+	adc->clk = devm_clk_get(dev, "adc");
 	if (IS_ERR(adc->clk)) {
 		dev_err(dev, "failed to get adc clock\n");
-		ret = PTR_ERR(adc->clk);
-		goto err_irq;
+		return PTR_ERR(adc->clk);
 	}
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!regs) {
 		dev_err(dev, "failed to find registers\n");
-		ret = -ENXIO;
-		goto err_clk;
+		return -ENXIO;
 	}
 
-	adc->regs = ioremap(regs->start, resource_size(regs));
+	adc->regs = devm_request_and_ioremap(dev, regs);
 	if (!adc->regs) {
 		dev_err(dev, "failed to map registers\n");
-		ret = -ENXIO;
-		goto err_clk;
+		return -ENXIO;
 	}
 
 	ret = regulator_enable(adc->vdd);
 	if (ret)
-		goto err_ioremap;
+		return ret;
 
 	clk_enable(adc->clk);
 
@@ -418,32 +414,14 @@ static int s3c_adc_probe(struct platform_device *pdev)
 	adc_dev = adc;
 
 	return 0;
-
- err_ioremap:
-	iounmap(adc->regs);
- err_clk:
-	clk_put(adc->clk);
-
- err_irq:
-	free_irq(adc->irq, adc);
- err_reg:
-	regulator_put(adc->vdd);
- err_alloc:
-	kfree(adc);
-	return ret;
 }
 
 static int __devexit s3c_adc_remove(struct platform_device *pdev)
 {
 	struct adc_device *adc = platform_get_drvdata(pdev);
 
-	iounmap(adc->regs);
-	free_irq(adc->irq, adc);
 	clk_disable(adc->clk);
 	regulator_disable(adc->vdd);
-	regulator_put(adc->vdd);
-	clk_put(adc->clk);
-	kfree(adc);
 
 	return 0;
 }
diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c
index 012bbd0..47c9fad 100644
--- a/arch/arm/plat-samsung/clock.c
+++ b/arch/arm/plat-samsung/clock.c
@@ -389,6 +389,72 @@ int __init s3c24xx_register_baseclocks(unsigned long xtal)
 
 static struct dentry *clk_debugfs_root;
 
+static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
+{
+	struct clk *child;
+	const char *state;
+	char buf[255] = { 0 };
+	int n = 0;
+
+	if (c->name)
+		n = snprintf(buf, sizeof(buf) - 1, "%s", c->name);
+
+	if (c->devname)
+		n += snprintf(buf + n, sizeof(buf) - 1 - n, ":%s", c->devname);
+
+	state = (c->usage > 0) ? "on" : "off";
+
+	seq_printf(s, "%*s%-*s %-6s %-3d %-10lu\n",
+		   level * 3 + 1, "",
+		   50 - level * 3, buf,
+		   state, c->usage, clk_get_rate(c));
+
+	list_for_each_entry(child, &clocks, list) {
+		if (child->parent != c)
+			continue;
+
+		clock_tree_show_one(s, child, level + 1);
+	}
+}
+
+static int clock_tree_show(struct seq_file *s, void *data)
+{
+	struct clk *c;
+	unsigned long flags;
+
+	seq_printf(s, " clock state ref rate\n");
+	seq_printf(s, "----------------------------------------------------\n");
+
+	spin_lock_irqsave(&clocks_lock, flags);
+
+	list_for_each_entry(c, &clocks, list)
+		if (c->parent == NULL)
+			clock_tree_show_one(s, c, 0);
+
+	spin_unlock_irqrestore(&clocks_lock, flags);
+	return 0;
+}
+
+static int clock_tree_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, clock_tree_show, inode->i_private);
+}
+
+static const struct file_operations clock_tree_fops = {
+	.open		= clock_tree_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int clock_rate_show(void *data, u64 *val)
+{
+	struct clk *c = data;
+	*val = clk_get_rate(c);
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_rate_show, NULL, "%llu\n");
+
 static int clk_debugfs_register_one(struct clk *c)
 {
 	int err;
@@ -411,7 +477,7 @@ static int clk_debugfs_register_one(struct clk *c)
 		goto err_out;
 	}
 
-	d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
+	d = debugfs_create_file("rate", S_IRUGO, c->dent, c, &clock_rate_fops);
 	if (!d) {
 		err = -ENOMEM;
 		goto err_out;
@@ -446,13 +512,18 @@ static int __init clk_debugfs_init(void)
 {
 	struct clk *c;
 	struct dentry *d;
-	int err;
+	int err = -ENOMEM;
 
 	d = debugfs_create_dir("clock", NULL);
 	if (!d)
 		return -ENOMEM;
 	clk_debugfs_root = d;
 
+	d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL,
+				 &clock_tree_fops);
+	if (!d)
+		goto err_out;
+
 	list_for_each_entry(c, &clocks, list) {
 		err = clk_debugfs_register(c);
 		if (err)
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index 03f654d..bc50b20 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -486,11 +486,7 @@ static struct resource s3c_i2c0_resource[] = {
 
 struct platform_device s3c_device_i2c0 = {
 	.name		= "s3c2410-i2c",
-#ifdef CONFIG_S3C_DEV_I2C1
 	.id		= 0,
-#else
-	.id		= -1,
-#endif
 	.num_resources	= ARRAY_SIZE(s3c_i2c0_resource),
 	.resource	= s3c_i2c0_resource,
 };
@@ -933,6 +929,7 @@ struct platform_device s5p_device_mfc_r = {
 		.coherent_dma_mask	= DMA_BIT_MASK(32),
 	},
 };
+
 #endif /* CONFIG_S5P_DEV_MFC */
 
 /* MIPI CSIS */
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index ace4451..e0072ce 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -43,6 +43,7 @@ extern unsigned long samsung_cpu_id;
 #define EXYNOS4_CPU_MASK	0xFFFE0000
 
 #define EXYNOS5250_SOC_ID	0x43520000
+#define EXYNOS5440_SOC_ID	0x54400000
 #define EXYNOS5_SOC_MASK	0xFFFFF000
 
 #define IS_SAMSUNG_CPU(name, id, mask)		\
@@ -62,6 +63,7 @@ IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK)
 IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK)
 IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK)
 IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS5_SOC_MASK)
+IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS5_SOC_MASK)
 
 #if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \
     defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2440) || \
@@ -130,6 +132,12 @@ IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS5_SOC_MASK)
 # define soc_is_exynos5250()	0
 #endif
 
+#if defined(CONFIG_SOC_EXYNOS5440)
+# define soc_is_exynos5440()	is_samsung_exynos5440()
+#else
+# define soc_is_exynos5440()	0
+#endif
+
 #define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
 
 #ifndef KHZ
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index 5da4b4f..f53beba 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -123,7 +123,6 @@ extern struct platform_device s5pv210_device_spdif;
 
 extern struct platform_device exynos4_device_ac97;
 extern struct platform_device exynos4_device_ahci;
-extern struct platform_device exynos4_device_dwmci;
 extern struct platform_device exynos4_device_i2s0;
 extern struct platform_device exynos4_device_i2s1;
 extern struct platform_device exynos4_device_i2s2;
@@ -133,8 +132,6 @@ extern struct platform_device exynos4_device_pcm1;
 extern struct platform_device exynos4_device_pcm2;
 extern struct platform_device exynos4_device_spdif;
 
-extern struct platform_device exynos_device_drm;
-
 extern struct platform_device samsung_asoc_dma;
 extern struct platform_device samsung_asoc_idma;
 extern struct platform_device samsung_device_keypad;
diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h
index 1fe6917..dfd8b7a 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-core.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-core.h
@@ -48,6 +48,7 @@ struct samsung_gpio_cfg;
  * @config: special function and pull-resistor control information.
  * @lock: Lock for exclusive access to this gpio bank.
  * @pm_save: Save information for suspend/resume support.
+ * @bitmap_gpio_int: Bitmap for representing GPIO interrupt or not.
  *
  * This wrapper provides the necessary information for the Samsung
  * specific gpios being registered with gpiolib.
@@ -71,6 +72,7 @@ struct samsung_gpio_chip {
 #ifdef CONFIG_PM
 	u32			pm_save[4];
 #endif
+	u32			bitmap_gpio_int;
 };
 
 static inline struct samsung_gpio_chip *to_samsung_gpio(struct gpio_chip *gpc)
diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h
index c2d7bda..038aa96 100644
--- a/arch/arm/plat-samsung/include/plat/map-s5p.h
+++ b/arch/arm/plat-samsung/include/plat/map-s5p.h
@@ -40,6 +40,8 @@
 #define S5P_VA_GIC_CPU		S3C_ADDR(0x02810000)
 #define S5P_VA_GIC_DIST		S3C_ADDR(0x02820000)
 
+#define S5P_VA_AUDSS		S3C_ADDR(0x02830000)
+
 #define VA_VIC(x)		(S3C_VA_IRQ + ((x) * 0x10000))
 #define VA_VIC0			VA_VIC(0)
 #define VA_VIC1			VA_VIC(1)
diff --git a/arch/arm/plat-samsung/include/plat/mfc.h b/arch/arm/plat-samsung/include/plat/mfc.h
index ac13227..e6d7c42 100644
--- a/arch/arm/plat-samsung/include/plat/mfc.h
+++ b/arch/arm/plat-samsung/include/plat/mfc.h
@@ -10,6 +10,14 @@
 #ifndef __PLAT_SAMSUNG_MFC_H
 #define __PLAT_SAMSUNG_MFC_H __FILE__
 
+struct s5p_mfc_dt_meminfo {
+	unsigned long	loff;
+	unsigned long	lsize;
+	unsigned long	roff;
+	unsigned long	rsize;
+	char		*compatible;
+};
+
 /**
  * s5p_mfc_reserve_mem - function to early reserve memory for MFC driver
  * @rbase:	base address for MFC 'right' memory interface
@@ -24,4 +32,7 @@
 void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
 				phys_addr_t lbase, unsigned int lsize);
 
+int __init s5p_fdt_find_mfc_mem(unsigned long node, const char *uname,
+				int depth, void *data);
+
 #endif /* __PLAT_SAMSUNG_MFC_H */
diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h
index 61fc537..887a0c9 100644
--- a/arch/arm/plat-samsung/include/plat/pm.h
+++ b/arch/arm/plat-samsung/include/plat/pm.h
@@ -107,10 +107,12 @@ extern void s3c_pm_do_restore(struct sleep_save *ptr, int count);
 extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count);
 
 #ifdef CONFIG_PM
+extern int s3c_irq_wake(struct irq_data *data, unsigned int state);
 extern int s3c_irqext_wake(struct irq_data *data, unsigned int state);
 extern int s3c24xx_irq_suspend(void);
 extern void s3c24xx_irq_resume(void);
 #else
+#define s3c_irq_wake NULL
 #define s3c_irqext_wake NULL
 #define s3c24xx_irq_suspend NULL
 #define s3c24xx_irq_resume  NULL
diff --git a/arch/arm/plat-samsung/s5p-dev-mfc.c b/arch/arm/plat-samsung/s5p-dev-mfc.c
index ad60894..5ec104b 100644
--- a/arch/arm/plat-samsung/s5p-dev-mfc.c
+++ b/arch/arm/plat-samsung/s5p-dev-mfc.c
@@ -14,6 +14,8 @@
 #include <linux/dma-mapping.h>
 #include <linux/memblock.h>
 #include <linux/ioport.h>
+#include <linux/of_fdt.h>
+#include <linux/of.h>
 
 #include <mach/map.h>
 #include <plat/devs.h>
@@ -69,3 +71,35 @@ static int __init s5p_mfc_memory_init(void)
 	return 0;
 }
 device_initcall(s5p_mfc_memory_init);
+
+#ifdef CONFIG_OF
+int __init s5p_fdt_find_mfc_mem(unsigned long node, const char *uname,
+				int depth, void *data)
+{
+	__be32 *prop;
+	unsigned long len;
+	struct s5p_mfc_dt_meminfo *mfc_mem = data;
+
+	if (!data)
+		return 0;
+
+	if (!of_flat_dt_is_compatible(node, mfc_mem->compatible))
+		return 0;
+
+	prop = of_get_flat_dt_prop(node, "samsung,mfc-l", &len);
+	if (!prop || (len != 2 * sizeof(unsigned long)))
+		return 0;
+
+	mfc_mem->loff = be32_to_cpu(prop[0]);
+	mfc_mem->lsize = be32_to_cpu(prop[1]);
+
+	prop = of_get_flat_dt_prop(node, "samsung,mfc-r", &len);
+	if (!prop || (len != 2 * sizeof(unsigned long)))
+		return 0;
+
+	mfc_mem->roff = be32_to_cpu(prop[0]);
+	mfc_mem->rsize = be32_to_cpu(prop[1]);
+
+	return 1;
+}
+#endif
diff --git a/arch/arm/plat-samsung/s5p-irq-gpioint.c b/arch/arm/plat-samsung/s5p-irq-gpioint.c
index 23557d3..bae5613 100644
--- a/arch/arm/plat-samsung/s5p-irq-gpioint.c
+++ b/arch/arm/plat-samsung/s5p-irq-gpioint.c
@@ -185,7 +185,7 @@ int __init s5p_register_gpio_interrupt(int pin)
 
 	/* check if the group has been already registered */
 	if (my_chip->irq_base)
-		return my_chip->irq_base + offset;
+		goto success;
 
 	/* register gpio group */
 	ret = s5p_gpioint_add(my_chip);
@@ -193,9 +193,13 @@ int __init s5p_register_gpio_interrupt(int pin)
 		my_chip->chip.to_irq = samsung_gpiolib_to_irq;
 		printk(KERN_INFO "Registered interrupt support for gpio group %d.\n",
 		       group);
-		return my_chip->irq_base + offset;
+		goto success;
 	}
 	return ret;
+success:
+	my_chip->bitmap_gpio_int |= BIT(offset);
+
+	return my_chip->irq_base + offset;
 }
 
 int __init s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups)
diff --git a/arch/arm/plat-samsung/setup-camif.c b/arch/arm/plat-samsung/setup-camif.c
new file mode 100644
index 0000000..e01bf76
--- /dev/null
+++ b/arch/arm/plat-samsung/setup-camif.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2012 Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
+ *
+ * Helper functions for S3C24XX/S3C64XX SoC series CAMIF driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/gpio.h>
+#include <plat/gpio-cfg.h>
+
+/* Number of camera port pins, without FIELD */
+#define S3C_CAMIF_NUM_GPIOS	13
+
+/* Default camera port configuration helpers. */
+
+static void camif_get_gpios(int *gpio_start, int *gpio_reset)
+{
+#ifdef CONFIG_ARCH_S3C24XX
+	*gpio_start = S3C2410_GPJ(0);
+	*gpio_reset = S3C2410_GPJ(12);
+#else
+	/* s3c64xx */
+	*gpio_start = S3C64XX_GPF(0);
+	*gpio_reset = S3C64XX_GPF(3);
+#endif
+}
+
+int s3c_camif_gpio_get(void)
+{
+	int gpio_start, gpio_reset;
+	int ret, i;
+
+	camif_get_gpios(&gpio_start, &gpio_reset);
+
+	for (i = 0; i < S3C_CAMIF_NUM_GPIOS; i++) {
+		int gpio = gpio_start + i;
+
+		if (gpio == gpio_reset)
+			continue;
+
+		ret = gpio_request(gpio, "camif");
+		if (!ret)
+			ret = s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		if (ret) {
+			pr_err("failed to configure GPIO %d\n", gpio);
+			for (--i; i >= 0; i--)
+				gpio_free(gpio--);
+			return ret;
+		}
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+	}
+
+	return 0;
+}
+
+void s3c_camif_gpio_put(void)
+{
+	int i, gpio_start, gpio_reset;
+
+	camif_get_gpios(&gpio_start, &gpio_reset);
+
+	for (i = 0; i < S3C_CAMIF_NUM_GPIOS; i++) {
+		int gpio = gpio_start + i;
+		if (gpio != gpio_reset)
+			gpio_free(gpio);
+	}
+}
diff --git a/arch/arm/plat-spear/Kconfig b/arch/arm/plat-spear/Kconfig
index f8db7b2..87dbd81 100644
--- a/arch/arm/plat-spear/Kconfig
+++ b/arch/arm/plat-spear/Kconfig
@@ -12,6 +12,7 @@ config ARCH_SPEAR13XX
 	bool "ST SPEAr13xx with Device Tree"
 	select ARM_GIC
 	select CPU_V7
+	select GPIO_SPEAR_SPICS
 	select HAVE_SMP
 	select MIGHT_HAVE_CACHE_L2X0
 	select PINCTRL
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
index 2607bd0..01e8853 100644
--- a/arch/arm/plat-spear/Makefile
+++ b/arch/arm/plat-spear/Makefile
@@ -5,5 +5,5 @@
 # Common support
 obj-y	:= restart.o time.o
 
-obj-$(CONFIG_ARCH_SPEAR3XX)	+= pl080.o shirq.o
+obj-$(CONFIG_ARCH_SPEAR3XX)	+= pl080.o
 obj-$(CONFIG_ARCH_SPEAR6XX)	+= pl080.o
diff --git a/arch/arm/plat-spear/include/plat/shirq.h b/arch/arm/plat-spear/include/plat/shirq.h
deleted file mode 100644
index 88a7fbd..0000000
--- a/arch/arm/plat-spear/include/plat/shirq.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/shirq.h
- *
- * SPEAr platform shared irq layer header file
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __PLAT_SHIRQ_H
-#define __PLAT_SHIRQ_H
-
-#include <linux/irq.h>
-#include <linux/types.h>
-
-/*
- * struct shirq_dev_config: shared irq device configuration
- *
- * virq: virtual irq number of device
- * enb_mask: enable mask of device
- * status_mask: status mask of device
- * clear_mask: clear mask of device
- */
-struct shirq_dev_config {
-	u32 virq;
-	u32 enb_mask;
-	u32 status_mask;
-	u32 clear_mask;
-};
-
-/*
- * struct shirq_regs: shared irq register configuration
- *
- * base: base address of shared irq register
- * enb_reg: enable register offset
- * reset_to_enb: val 1 indicates, we need to clear bit for enabling interrupt
- * status_reg: status register offset
- * status_reg_mask: status register valid mask
- * clear_reg: clear register offset
- * reset_to_clear: val 1 indicates, we need to clear bit for clearing interrupt
- */
-struct shirq_regs {
-	void __iomem *base;
-	u32 enb_reg;
-	u32 reset_to_enb;
-	u32 status_reg;
-	u32 status_reg_mask;
-	u32 clear_reg;
-	u32 reset_to_clear;
-};
-
-/*
- * struct spear_shirq: shared irq structure
- *
- * irq: hardware irq number
- * dev_config: array of device config structures which are using "irq" line
- * dev_count: size of dev_config array
- * regs: register configuration for shared irq block
- */
-struct spear_shirq {
-	u32 irq;
-	struct shirq_dev_config *dev_config;
-	u32 dev_count;
-	struct shirq_regs regs;
-};
-
-int spear_shirq_register(struct spear_shirq *shirq);
-
-#endif /* __PLAT_SHIRQ_H */
diff --git a/arch/arm/plat-spear/shirq.c b/arch/arm/plat-spear/shirq.c
deleted file mode 100644
index 853e891..0000000
--- a/arch/arm/plat-spear/shirq.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * arch/arm/plat-spear/shirq.c
- *
- * SPEAr platform shared irq layer source file
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/spinlock.h>
-#include <plat/shirq.h>
-
-struct spear_shirq *shirq;
-static DEFINE_SPINLOCK(lock);
-
-static void shirq_irq_mask(struct irq_data *d)
-{
-	struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
-	u32 val, id = d->irq - shirq->dev_config[0].virq;
-	unsigned long flags;
-
-	if ((shirq->regs.enb_reg == -1) || shirq->dev_config[id].enb_mask == -1)
-		return;
-
-	spin_lock_irqsave(&lock, flags);
-	val = readl(shirq->regs.base + shirq->regs.enb_reg);
-	if (shirq->regs.reset_to_enb)
-		val |= shirq->dev_config[id].enb_mask;
-	else
-		val &= ~(shirq->dev_config[id].enb_mask);
-	writel(val, shirq->regs.base + shirq->regs.enb_reg);
-	spin_unlock_irqrestore(&lock, flags);
-}
-
-static void shirq_irq_unmask(struct irq_data *d)
-{
-	struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
-	u32 val, id = d->irq - shirq->dev_config[0].virq;
-	unsigned long flags;
-
-	if ((shirq->regs.enb_reg == -1) || shirq->dev_config[id].enb_mask == -1)
-		return;
-
-	spin_lock_irqsave(&lock, flags);
-	val = readl(shirq->regs.base + shirq->regs.enb_reg);
-	if (shirq->regs.reset_to_enb)
-		val &= ~(shirq->dev_config[id].enb_mask);
-	else
-		val |= shirq->dev_config[id].enb_mask;
-	writel(val, shirq->regs.base + shirq->regs.enb_reg);
-	spin_unlock_irqrestore(&lock, flags);
-}
-
-static struct irq_chip shirq_chip = {
-	.name		= "spear_shirq",
-	.irq_ack	= shirq_irq_mask,
-	.irq_mask	= shirq_irq_mask,
-	.irq_unmask	= shirq_irq_unmask,
-};
-
-static void shirq_handler(unsigned irq, struct irq_desc *desc)
-{
-	u32 i, val, mask;
-	struct spear_shirq *shirq = irq_get_handler_data(irq);
-
-	desc->irq_data.chip->irq_ack(&desc->irq_data);
-	while ((val = readl(shirq->regs.base + shirq->regs.status_reg) &
-				shirq->regs.status_reg_mask)) {
-		for (i = 0; (i < shirq->dev_count) && val; i++) {
-			if (!(shirq->dev_config[i].status_mask & val))
-				continue;
-
-			generic_handle_irq(shirq->dev_config[i].virq);
-
-			/* clear interrupt */
-			val &= ~shirq->dev_config[i].status_mask;
-			if ((shirq->regs.clear_reg == -1) ||
-					shirq->dev_config[i].clear_mask == -1)
-				continue;
-			mask = readl(shirq->regs.base + shirq->regs.clear_reg);
-			if (shirq->regs.reset_to_clear)
-				mask &= ~shirq->dev_config[i].clear_mask;
-			else
-				mask |= shirq->dev_config[i].clear_mask;
-			writel(mask, shirq->regs.base + shirq->regs.clear_reg);
-		}
-	}
-	desc->irq_data.chip->irq_unmask(&desc->irq_data);
-}
-
-int spear_shirq_register(struct spear_shirq *shirq)
-{
-	int i;
-
-	if (!shirq || !shirq->dev_config || !shirq->regs.base)
-		return -EFAULT;
-
-	if (!shirq->dev_count)
-		return -EINVAL;
-
-	irq_set_chained_handler(shirq->irq, shirq_handler);
-	for (i = 0; i < shirq->dev_count; i++) {
-		irq_set_chip_and_handler(shirq->dev_config[i].virq,
-					 &shirq_chip, handle_simple_irq);
-		set_irq_flags(shirq->dev_config[i].virq, IRQF_VALID);
-		irq_set_chip_data(shirq->dev_config[i].virq, shirq);
-	}
-
-	irq_set_handler_data(shirq->irq, shirq);
-	return 0;
-}
diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig
index 2a4ae8a..2c4332b 100644
--- a/arch/arm/plat-versatile/Kconfig
+++ b/arch/arm/plat-versatile/Kconfig
@@ -6,20 +6,11 @@ config PLAT_VERSATILE_CLOCK
 config PLAT_VERSATILE_CLCD
 	bool
 
-config PLAT_VERSATILE_FPGA_IRQ
-	bool
-	select IRQ_DOMAIN
-
-config PLAT_VERSATILE_FPGA_IRQ_NR
-       int
-       default 4
-       depends on PLAT_VERSATILE_FPGA_IRQ
-
 config PLAT_VERSATILE_LEDS
 	def_bool y if NEW_LEDS
 	depends on ARCH_REALVIEW || ARCH_VERSATILE
 	select LEDS_CLASS
-	select LEDS_TRIGGER
+	select LEDS_TRIGGERS
 
 config PLAT_VERSATILE_SCHED_CLOCK
 	def_bool y
diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile
index 74cfd94..f88d448 100644
--- a/arch/arm/plat-versatile/Makefile
+++ b/arch/arm/plat-versatile/Makefile
@@ -2,7 +2,6 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
 
 obj-$(CONFIG_PLAT_VERSATILE_CLOCK) += clock.o
 obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o
-obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o
 obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o
 obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o
 obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff --git a/arch/arm/plat-versatile/fpga-irq.c b/arch/arm/plat-versatile/fpga-irq.c
deleted file mode 100644
index 091ae10..0000000
--- a/arch/arm/plat-versatile/fpga-irq.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- *  Support for Versatile FPGA-based IRQ controllers
- */
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/irqdomain.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-
-#include <asm/exception.h>
-#include <asm/mach/irq.h>
-#include <plat/fpga-irq.h>
-
-#define IRQ_STATUS		0x00
-#define IRQ_RAW_STATUS		0x04
-#define IRQ_ENABLE_SET		0x08
-#define IRQ_ENABLE_CLEAR	0x0c
-#define INT_SOFT_SET		0x10
-#define INT_SOFT_CLEAR		0x14
-#define FIQ_STATUS		0x20
-#define FIQ_RAW_STATUS		0x24
-#define FIQ_ENABLE		0x28
-#define FIQ_ENABLE_SET		0x28
-#define FIQ_ENABLE_CLEAR	0x2C
-
-/**
- * struct fpga_irq_data - irq data container for the FPGA IRQ controller
- * @base: memory offset in virtual memory
- * @chip: chip container for this instance
- * @domain: IRQ domain for this instance
- * @valid: mask for valid IRQs on this controller
- * @used_irqs: number of active IRQs on this controller
- */
-struct fpga_irq_data {
-	void __iomem *base;
-	struct irq_chip chip;
-	u32 valid;
-	struct irq_domain *domain;
-	u8 used_irqs;
-};
-
-/* we cannot allocate memory when the controllers are initially registered */
-static struct fpga_irq_data fpga_irq_devices[CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR];
-static int fpga_irq_id;
-
-static void fpga_irq_mask(struct irq_data *d)
-{
-	struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
-	u32 mask = 1 << d->hwirq;
-
-	writel(mask, f->base + IRQ_ENABLE_CLEAR);
-}
-
-static void fpga_irq_unmask(struct irq_data *d)
-{
-	struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
-	u32 mask = 1 << d->hwirq;
-
-	writel(mask, f->base + IRQ_ENABLE_SET);
-}
-
-static void fpga_irq_handle(unsigned int irq, struct irq_desc *desc)
-{
-	struct fpga_irq_data *f = irq_desc_get_handler_data(desc);
-	u32 status = readl(f->base + IRQ_STATUS);
-
-	if (status == 0) {
-		do_bad_IRQ(irq, desc);
-		return;
-	}
-
-	do {
-		irq = ffs(status) - 1;
-		status &= ~(1 << irq);
-		generic_handle_irq(irq_find_mapping(f->domain, irq));
-	} while (status);
-}
-
-/*
- * Handle each interrupt in a single FPGA IRQ controller.  Returns non-zero
- * if we've handled at least one interrupt.  This does a single read of the
- * status register and handles all interrupts in order from LSB first.
- */
-static int handle_one_fpga(struct fpga_irq_data *f, struct pt_regs *regs)
-{
-	int handled = 0;
-	int irq;
-	u32 status;
-
-	while ((status  = readl(f->base + IRQ_STATUS))) {
-		irq = ffs(status) - 1;
-		handle_IRQ(irq_find_mapping(f->domain, irq), regs);
-		handled = 1;
-	}
-
-	return handled;
-}
-
-/*
- * Keep iterating over all registered FPGA IRQ controllers until there are
- * no pending interrupts.
- */
-asmlinkage void __exception_irq_entry fpga_handle_irq(struct pt_regs *regs)
-{
-	int i, handled;
-
-	do {
-		for (i = 0, handled = 0; i < fpga_irq_id; ++i)
-			handled |= handle_one_fpga(&fpga_irq_devices[i], regs);
-	} while (handled);
-}
-
-static int fpga_irqdomain_map(struct irq_domain *d, unsigned int irq,
-		irq_hw_number_t hwirq)
-{
-	struct fpga_irq_data *f = d->host_data;
-
-	/* Skip invalid IRQs, only register handlers for the real ones */
-	if (!(f->valid & (1 << hwirq)))
-		return -ENOTSUPP;
-	irq_set_chip_data(irq, f);
-	irq_set_chip_and_handler(irq, &f->chip,
-				handle_level_irq);
-	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	f->used_irqs++;
-	return 0;
-}
-
-static struct irq_domain_ops fpga_irqdomain_ops = {
-	.map = fpga_irqdomain_map,
-	.xlate = irq_domain_xlate_onetwocell,
-};
-
-static __init struct fpga_irq_data *
-fpga_irq_prep_struct(void __iomem *base, const char *name, u32 valid) {
-	struct fpga_irq_data *f;
-
-	if (fpga_irq_id >= ARRAY_SIZE(fpga_irq_devices)) {
-		printk(KERN_ERR "%s: too few FPGA IRQ controllers, increase CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR\n", __func__);
-		return NULL;
-	}
-	f = &fpga_irq_devices[fpga_irq_id];
-	f->base = base;
-	f->chip.name = name;
-	f->chip.irq_ack = fpga_irq_mask;
-	f->chip.irq_mask = fpga_irq_mask;
-	f->chip.irq_unmask = fpga_irq_unmask;
-	f->valid = valid;
-	fpga_irq_id++;
-
-	return f;
-}
-
-void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
-			  int parent_irq, u32 valid, struct device_node *node)
-{
-	struct fpga_irq_data *f;
-
-	f = fpga_irq_prep_struct(base, name, valid);
-	if (!f)
-		return;
-
-	if (parent_irq != -1) {
-		irq_set_handler_data(parent_irq, f);
-		irq_set_chained_handler(parent_irq, fpga_irq_handle);
-	}
-
-	f->domain = irq_domain_add_legacy(node, fls(valid), irq_start, 0,
-					  &fpga_irqdomain_ops, f);
-	pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n",
-		fpga_irq_id, name, base, f->used_irqs);
-}
-
-#ifdef CONFIG_OF
-int __init fpga_irq_of_init(struct device_node *node,
-			    struct device_node *parent)
-{
-	struct fpga_irq_data *f;
-	void __iomem *base;
-	u32 clear_mask;
-	u32 valid_mask;
-
-	if (WARN_ON(!node))
-		return -ENODEV;
-
-	base = of_iomap(node, 0);
-	WARN(!base, "unable to map fpga irq registers\n");
-
-	if (of_property_read_u32(node, "clear-mask", &clear_mask))
-		clear_mask = 0;
-
-	if (of_property_read_u32(node, "valid-mask", &valid_mask))
-		valid_mask = 0;
-
-	f = fpga_irq_prep_struct(base, node->name, valid_mask);
-	if (!f)
-		return -ENOMEM;
-
-	writel(clear_mask, base + IRQ_ENABLE_CLEAR);
-	writel(clear_mask, base + FIQ_ENABLE_CLEAR);
-
-	f->domain = irq_domain_add_linear(node, fls(valid_mask), &fpga_irqdomain_ops, f);
-	f->used_irqs = hweight32(valid_mask);
-
-	pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n",
-		fpga_irq_id, node->name, base, f->used_irqs);
-	return 0;
-}
-#endif
diff --git a/arch/arm/plat-versatile/include/plat/fpga-irq.h b/arch/arm/plat-versatile/include/plat/fpga-irq.h
deleted file mode 100644
index 1fac965..0000000
--- a/arch/arm/plat-versatile/include/plat/fpga-irq.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef PLAT_FPGA_IRQ_H
-#define PLAT_FPGA_IRQ_H
-
-struct device_node;
-struct pt_regs;
-
-void fpga_handle_irq(struct pt_regs *regs);
-void fpga_irq_init(void __iomem *, const char *, int, int, u32,
-		struct device_node *node);
-int fpga_irq_of_init(struct device_node *node,
-		     struct device_node *parent);
-
-#endif
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index f576092..d4b23f4 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -8,6 +8,8 @@
 #include <xen/features.h>
 #include <xen/platform_pci.h>
 #include <xen/xenbus.h>
+#include <xen/page.h>
+#include <xen/xen-ops.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
 #include <linux/interrupt.h>
@@ -17,6 +19,8 @@
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 
+#include <linux/mm.h>
+
 struct start_info _xen_start_info;
 struct start_info *xen_start_info = &_xen_start_info;
 EXPORT_SYMBOL_GPL(xen_start_info);
@@ -29,6 +33,10 @@ struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info;
 
 DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
 
+/* These are unused until we support booting "pre-ballooned" */
+unsigned long xen_released_pages;
+struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata;
+
 /* TODO: to be removed */
 __read_mostly int xen_have_vector_callback;
 EXPORT_SYMBOL_GPL(xen_have_vector_callback);
@@ -38,15 +46,106 @@ EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
 
 static __read_mostly int xen_events_irq = -1;
 
+/* map fgmfn of domid to lpfn in the current domain */
+static int map_foreign_page(unsigned long lpfn, unsigned long fgmfn,
+			    unsigned int domid)
+{
+	int rc;
+	struct xen_add_to_physmap_range xatp = {
+		.domid = DOMID_SELF,
+		.foreign_domid = domid,
+		.size = 1,
+		.space = XENMAPSPACE_gmfn_foreign,
+	};
+	xen_ulong_t idx = fgmfn;
+	xen_pfn_t gpfn = lpfn;
+
+	set_xen_guest_handle(xatp.idxs, &idx);
+	set_xen_guest_handle(xatp.gpfns, &gpfn);
+
+	rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp);
+	if (rc) {
+		pr_warn("Failed to map pfn to mfn rc:%d pfn:%lx mfn:%lx\n",
+			rc, lpfn, fgmfn);
+		return 1;
+	}
+	return 0;
+}
+
+struct remap_data {
+	xen_pfn_t fgmfn; /* foreign domain's gmfn */
+	pgprot_t prot;
+	domid_t  domid;
+	struct vm_area_struct *vma;
+	int index;
+	struct page **pages;
+	struct xen_remap_mfn_info *info;
+};
+
+static int remap_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr,
+			void *data)
+{
+	struct remap_data *info = data;
+	struct page *page = info->pages[info->index++];
+	unsigned long pfn = page_to_pfn(page);
+	pte_t pte = pfn_pte(pfn, info->prot);
+
+	if (map_foreign_page(pfn, info->fgmfn, info->domid))
+		return -EFAULT;
+	set_pte_at(info->vma->vm_mm, addr, ptep, pte);
+
+	return 0;
+}
+
 int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
 			       unsigned long addr,
-			       unsigned long mfn, int nr,
-			       pgprot_t prot, unsigned domid)
+			       xen_pfn_t mfn, int nr,
+			       pgprot_t prot, unsigned domid,
+			       struct page **pages)
 {
-	return -ENOSYS;
+	int err;
+	struct remap_data data;
+
+	/* TBD: Batching, current sole caller only does page at a time */
+	if (nr > 1)
+		return -EINVAL;
+
+	data.fgmfn = mfn;
+	data.prot = prot;
+	data.domid = domid;
+	data.vma = vma;
+	data.index = 0;
+	data.pages = pages;
+	err = apply_to_page_range(vma->vm_mm, addr, nr << PAGE_SHIFT,
+				  remap_pte_fn, &data);
+	return err;
 }
 EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);
 
+int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
+			       int nr, struct page **pages)
+{
+	int i;
+
+	for (i = 0; i < nr; i++) {
+		struct xen_remove_from_physmap xrp;
+		unsigned long rc, pfn;
+
+		pfn = page_to_pfn(pages[i]);
+
+		xrp.domid = DOMID_SELF;
+		xrp.gpfn = pfn;
+		rc = HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrp);
+		if (rc) {
+			pr_warn("Failed to unmap pfn:%lx rc:%ld\n",
+				pfn, rc);
+			return rc;
+		}
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range);
+
 /*
  * see Documentation/devicetree/bindings/arm/xen.txt for the
  * documentation of the Xen Device Tree format.
@@ -149,24 +248,6 @@ static int __init xen_init_events(void)
 }
 postcore_initcall(xen_init_events);
 
-/* XXX: only until balloon is properly working */
-int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem)
-{
-	*pages = alloc_pages(highmem ? GFP_HIGHUSER : GFP_KERNEL,
-			get_order(nr_pages));
-	if (*pages == NULL)
-		return -ENOMEM;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(alloc_xenballooned_pages);
-
-void free_xenballooned_pages(int nr_pages, struct page **pages)
-{
-	kfree(*pages);
-	*pages = NULL;
-}
-EXPORT_SYMBOL_GPL(free_xenballooned_pages);
-
 /* In the hypervisor.S file. */
 EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op);
 EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op);
@@ -176,4 +257,4 @@ EXPORT_SYMBOL_GPL(HYPERVISOR_sched_op);
 EXPORT_SYMBOL_GPL(HYPERVISOR_hvm_op);
 EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op);
 EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op);
-EXPORT_SYMBOL_GPL(privcmd_call);
+EXPORT_SYMBOL_GPL(privcmd_call);
\ No newline at end of file
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 15ac18a..6c6ab08 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2,11 +2,14 @@ config ARM64
 	def_bool y
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
+	select COMMON_CLK
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_HARDIRQS_NO_DEPRECATED
 	select GENERIC_IOMAP
 	select GENERIC_IRQ_PROBE
 	select GENERIC_IRQ_SHOW
+	select GENERIC_KERNEL_EXECVE
+	select GENERIC_KERNEL_THREAD
 	select GENERIC_SMP_IDLE_THREAD
 	select GENERIC_TIME_VSYSCALL
 	select HARDIRQS_SW_RESEND
@@ -31,6 +34,7 @@ config ARM64
 	select RTC_LIB
 	select SPARSE_IRQ
 	select SYSCTL_EXCEPTION_TRACE
+	select CLONE_BACKWARDS
 	help
 	  ARM 64-bit (AArch64) Linux support.
 
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index a581a22..14a9d5a 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -3,6 +3,7 @@
 generic-y += bug.h
 generic-y += bugs.h
 generic-y += checksum.h
+generic-y += clkdev.h
 generic-y += cputime.h
 generic-y += current.h
 generic-y += delay.h
@@ -43,6 +44,7 @@ generic-y += swab.h
 generic-y += termbits.h
 generic-y += termios.h
 generic-y += topology.h
+generic-y += trace_clock.h
 generic-y += types.h
 generic-y += unaligned.h
 generic-y += user.h
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h
index aa3132a..3300cbd 100644
--- a/arch/arm64/include/asm/cacheflush.h
+++ b/arch/arm64/include/asm/cacheflush.h
@@ -70,13 +70,20 @@
  *		- size   - region size
  */
 extern void flush_cache_all(void);
-extern void flush_cache_mm(struct mm_struct *mm);
 extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
-extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn);
 extern void flush_icache_range(unsigned long start, unsigned long end);
 extern void __flush_dcache_area(void *addr, size_t len);
 extern void __flush_cache_user_range(unsigned long start, unsigned long end);
 
+static inline void flush_cache_mm(struct mm_struct *mm)
+{
+}
+
+static inline void flush_cache_page(struct vm_area_struct *vma,
+				    unsigned long user_addr, unsigned long pfn)
+{
+}
+
 /*
  * Copy user data from/to a page which is mapped into a different
  * processes address space.  Really, we want to allow our "user
diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
index 538f4b4..9947768 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -50,6 +50,7 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr)
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dev_addr)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
+	debug_dma_mapping_error(dev, dev_addr);
 	return ops->mapping_error(dev, dev_addr);
 }
 
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 77f696c..ab239b2 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -128,11 +128,6 @@ unsigned long get_wchan(struct task_struct *p);
 extern struct task_struct *cpu_switch_to(struct task_struct *prev,
 					 struct task_struct *next);
 
-/*
- * Create a new kernel thread
- */
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 #define task_pt_regs(p) \
 	((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
 
diff --git a/arch/arm64/include/asm/syscalls.h b/arch/arm64/include/asm/syscalls.h
index 09ff335..a1b00cd 100644
--- a/arch/arm64/include/asm/syscalls.h
+++ b/arch/arm64/include/asm/syscalls.h
@@ -23,18 +23,16 @@
 /*
  * System call wrappers implemented in kernel/entry.S.
  */
-asmlinkage long sys_execve_wrapper(const char __user *filename,
-				   const char __user *const __user *argv,
-				   const char __user *const __user *envp);
-asmlinkage long sys_clone_wrapper(unsigned long clone_flags,
-				  unsigned long newsp,
-				  void __user *parent_tid,
-				  unsigned long tls_val,
-				  void __user *child_tid);
 asmlinkage long sys_rt_sigreturn_wrapper(void);
 asmlinkage long sys_sigaltstack_wrapper(const stack_t __user *uss,
 					stack_t __user *uoss);
 
+/*
+ * AArch64 sys_clone implementation has a different prototype than the generic
+ * one (additional TLS value argument).
+ */
+#define sys_clone	sys_clone
+
 #include <asm-generic/syscalls.h>
 
 #endif	/* __ASM_SYSCALLS_H */
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 68aff28..76fb7dd 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -20,9 +20,14 @@
 #define __ARCH_WANT_SYS_GETPGRP
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_NICE
+#define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_COMPAT_SYS_SENDFILE
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_VFORK
 #endif
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index 6d909fa..30127cb 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -23,7 +23,7 @@
 
 __SYSCALL(0,   sys_restart_syscall)
 __SYSCALL(1,   sys_exit)
-__SYSCALL(2,   compat_sys_fork_wrapper)
+__SYSCALL(2,   sys_fork)
 __SYSCALL(3,   sys_read)
 __SYSCALL(4,   sys_write)
 __SYSCALL(5,   compat_sys_open)
@@ -32,7 +32,7 @@ __SYSCALL(7,   sys_ni_syscall)			/* 7 was sys_waitpid */
 __SYSCALL(8,   sys_creat)
 __SYSCALL(9,   sys_link)
 __SYSCALL(10,  sys_unlink)
-__SYSCALL(11,  compat_sys_execve_wrapper)
+__SYSCALL(11,  compat_sys_execve)
 __SYSCALL(12,  sys_chdir)
 __SYSCALL(13,  sys_ni_syscall)			/* 13 was sys_time */
 __SYSCALL(14,  sys_mknod)
@@ -141,7 +141,7 @@ __SYSCALL(116, compat_sys_sysinfo)
 __SYSCALL(117, sys_ni_syscall)			/* 117 was sys_ipc */
 __SYSCALL(118, sys_fsync)
 __SYSCALL(119, compat_sys_sigreturn_wrapper)
-__SYSCALL(120, compat_sys_clone_wrapper)
+__SYSCALL(120, sys_clone)
 __SYSCALL(121, sys_setdomainname)
 __SYSCALL(122, sys_newuname)
 __SYSCALL(123, sys_ni_syscall)			/* 123 was sys_modify_ldt */
@@ -211,7 +211,7 @@ __SYSCALL(186, compat_sys_sigaltstack_wrapper)
 __SYSCALL(187, compat_sys_sendfile)
 __SYSCALL(188, sys_ni_syscall)			/* 188 reserved */
 __SYSCALL(189, sys_ni_syscall)			/* 189 reserved */
-__SYSCALL(190, compat_sys_vfork_wrapper)
+__SYSCALL(190, sys_vfork)
 __SYSCALL(191, compat_sys_getrlimit)		/* SuS compliant getrlimit */
 __SYSCALL(192, sys_mmap_pgoff)
 __SYSCALL(193, compat_sys_truncate64_wrapper)
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index a6f3f7d..cbfa4d2 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -594,7 +594,7 @@ work_resched:
 /*
  * "slow" syscall return path.
  */
-ENTRY(ret_to_user)
+ret_to_user:
 	disable_irq				// disable interrupts
 	ldr	x1, [tsk, #TI_FLAGS]
 	and	x2, x1, #_TIF_WORK_MASK
@@ -611,7 +611,10 @@ ENDPROC(ret_to_user)
  */
 ENTRY(ret_from_fork)
 	bl	schedule_tail
-	get_thread_info tsk
+	cbz	x19, 1f				// not a kernel thread
+	mov	x0, x20
+	blr	x19
+1:	get_thread_info tsk
 	b	ret_to_user
 ENDPROC(ret_from_fork)
 
@@ -673,16 +676,6 @@ __sys_trace_return:
 /*
  * Special system call wrappers.
  */
-ENTRY(sys_execve_wrapper)
-	mov	x3, sp
-	b	sys_execve
-ENDPROC(sys_execve_wrapper)
-
-ENTRY(sys_clone_wrapper)
-	mov	x5, sp
-	b	sys_clone
-ENDPROC(sys_clone_wrapper)
-
 ENTRY(sys_rt_sigreturn_wrapper)
 	mov	x0, sp
 	b	sys_rt_sigreturn
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index e04cebd..cb0956b 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -234,33 +234,46 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 asmlinkage void ret_from_fork(void) asm("ret_from_fork");
 
 int copy_thread(unsigned long clone_flags, unsigned long stack_start,
-		unsigned long stk_sz, struct task_struct *p,
-		struct pt_regs *regs)
+		unsigned long stk_sz, struct task_struct *p)
 {
 	struct pt_regs *childregs = task_pt_regs(p);
 	unsigned long tls = p->thread.tp_value;
 
-	*childregs = *regs;
-	childregs->regs[0] = 0;
+	memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
 
-	if (is_compat_thread(task_thread_info(p)))
-		childregs->compat_sp = stack_start;
-	else {
+	if (likely(!(p->flags & PF_KTHREAD))) {
+		*childregs = *current_pt_regs();
+		childregs->regs[0] = 0;
+		if (is_compat_thread(task_thread_info(p))) {
+			if (stack_start)
+				childregs->compat_sp = stack_start;
+		} else {
+			/*
+			 * Read the current TLS pointer from tpidr_el0 as it may be
+			 * out-of-sync with the saved value.
+			 */
+			asm("mrs %0, tpidr_el0" : "=r" (tls));
+			if (stack_start) {
+				/* 16-byte aligned stack mandatory on AArch64 */
+				if (stack_start & 15)
+					return -EINVAL;
+				childregs->sp = stack_start;
+			}
+		}
 		/*
-		 * Read the current TLS pointer from tpidr_el0 as it may be
-		 * out-of-sync with the saved value.
+		 * If a TLS pointer was passed to clone (4th argument), use it
+		 * for the new thread.
 		 */
-		asm("mrs %0, tpidr_el0" : "=r" (tls));
-		childregs->sp = stack_start;
+		if (clone_flags & CLONE_SETTLS)
+			tls = childregs->regs[3];
+	} else {
+		memset(childregs, 0, sizeof(struct pt_regs));
+		childregs->pstate = PSR_MODE_EL1h;
+		p->thread.cpu_context.x19 = stack_start;
+		p->thread.cpu_context.x20 = stk_sz;
 	}
-
-	memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
-	p->thread.cpu_context.sp = (unsigned long)childregs;
 	p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
-
-	/* If a TLS pointer was passed to clone, use that for the new thread. */
-	if (clone_flags & CLONE_SETTLS)
-		tls = regs->regs[3];
+	p->thread.cpu_context.sp = (unsigned long)childregs;
 	p->thread.tp_value = tls;
 
 	ptrace_hw_copy_thread(p);
@@ -309,43 +322,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
 	return last;
 }
 
-/*
- * Shuffle the argument into the correct register before calling the
- * thread function.  x1 is the thread argument, x2 is the pointer to
- * the thread function, and x3 points to the exit function.
- */
-extern void kernel_thread_helper(void);
-asm(	".section .text\n"
-"	.align\n"
-"	.type	kernel_thread_helper, #function\n"
-"kernel_thread_helper:\n"
-"	mov	x0, x1\n"
-"	mov	x30, x3\n"
-"	br	x2\n"
-"	.size	kernel_thread_helper, . - kernel_thread_helper\n"
-"	.previous");
-
-#define kernel_thread_exit	do_exit
-
-/*
- * Create a kernel thread.
- */
-pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-
-	regs.regs[1] = (unsigned long)arg;
-	regs.regs[2] = (unsigned long)fn;
-	regs.regs[3] = (unsigned long)kernel_thread_exit;
-	regs.pc = (unsigned long)kernel_thread_helper;
-	regs.pstate = PSR_MODE_EL1h;
-
-	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 unsigned long get_wchan(struct task_struct *p)
 {
 	struct stackframe frame;
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 8807ba2..abd7563 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -41,6 +41,8 @@
 struct rt_sigframe {
 	struct siginfo info;
 	struct ucontext uc;
+	u64 fp;
+	u64 lr;
 };
 
 static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
@@ -175,6 +177,10 @@ static int setup_sigframe(struct rt_sigframe __user *sf,
 	struct aux_context __user *aux =
 		(struct aux_context __user *)sf->uc.uc_mcontext.__reserved;
 
+	/* set up the stack frame for unwinding */
+	__put_user_error(regs->regs[29], &sf->fp, err);
+	__put_user_error(regs->regs[30], &sf->lr, err);
+
 	for (i = 0; i < 31; i++)
 		__put_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i],
 				 err);
@@ -196,11 +202,11 @@ static int setup_sigframe(struct rt_sigframe __user *sf,
 	return err;
 }
 
-static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
-				 int framesize)
+static struct rt_sigframe __user *get_sigframe(struct k_sigaction *ka,
+					       struct pt_regs *regs)
 {
 	unsigned long sp, sp_top;
-	void __user *frame;
+	struct rt_sigframe __user *frame;
 
 	sp = sp_top = regs->sp;
 
@@ -210,11 +216,8 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
 	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
 		sp = sp_top = current->sas_ss_sp + current->sas_ss_size;
 
-	/* room for stack frame (FP, LR) */
-	sp -= 16;
-
-	sp = (sp - framesize) & ~15;
-	frame = (void __user *)sp;
+	sp = (sp - sizeof(struct rt_sigframe)) & ~15;
+	frame = (struct rt_sigframe __user *)sp;
 
 	/*
 	 * Check that we can actually write to the signal frame.
@@ -225,20 +228,14 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
 	return frame;
 }
 
-static int setup_return(struct pt_regs *regs, struct k_sigaction *ka,
-			void __user *frame, int usig)
+static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+			 void __user *frame, int usig)
 {
-	int err = 0;
 	__sigrestore_t sigtramp;
-	unsigned long __user *sp = (unsigned long __user *)regs->sp;
-
-	/* set up the stack frame */
-	__put_user_error(regs->regs[29], sp - 2, err);
-	__put_user_error(regs->regs[30], sp - 1, err);
 
 	regs->regs[0] = usig;
-	regs->regs[29] = regs->sp - 16;
 	regs->sp = (unsigned long)frame;
+	regs->regs[29] = regs->sp + offsetof(struct rt_sigframe, fp);
 	regs->pc = (unsigned long)ka->sa.sa_handler;
 
 	if (ka->sa.sa_flags & SA_RESTORER)
@@ -247,8 +244,6 @@ static int setup_return(struct pt_regs *regs, struct k_sigaction *ka,
 		sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp);
 
 	regs->regs[30] = (unsigned long)sigtramp;
-
-	return err;
 }
 
 static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
@@ -258,7 +253,7 @@ static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
 	stack_t stack;
 	int err = 0;
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ka, regs);
 	if (!frame)
 		return 1;
 
@@ -272,13 +267,13 @@ static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
 	err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack));
 
 	err |= setup_sigframe(frame, regs, set);
-	if (err == 0)
-		err = setup_return(regs, ka, frame, usig);
-
-	if (err == 0 && ka->sa.sa_flags & SA_SIGINFO) {
-		err |= copy_siginfo_to_user(&frame->info, info);
-		regs->regs[1] = (unsigned long)&frame->info;
-		regs->regs[2] = (unsigned long)&frame->uc;
+	if (err == 0) {
+		setup_return(regs, ka, frame, usig);
+		if (ka->sa.sa_flags & SA_SIGINFO) {
+			err |= copy_siginfo_to_user(&frame->info, info);
+			regs->regs[1] = (unsigned long)&frame->info;
+			regs->regs[2] = (unsigned long)&frame->uc;
+		}
 	}
 
 	return err;
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 4654824..a4db3d2 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -578,9 +578,9 @@ badframe:
 	return 0;
 }
 
-static inline void __user *compat_get_sigframe(struct k_sigaction *ka,
-					       struct pt_regs *regs,
-					       int framesize)
+static void __user *compat_get_sigframe(struct k_sigaction *ka,
+					struct pt_regs *regs,
+					int framesize)
 {
 	compat_ulong_t sp = regs->compat_sp;
 	void __user *frame;
@@ -605,9 +605,9 @@ static inline void __user *compat_get_sigframe(struct k_sigaction *ka,
 	return frame;
 }
 
-static int compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka,
-			       compat_ulong_t __user *rc, void __user *frame,
-			       int usig)
+static void compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+				compat_ulong_t __user *rc, void __user *frame,
+				int usig)
 {
 	compat_ulong_t handler = ptr_to_compat(ka->sa.sa_handler);
 	compat_ulong_t retcode;
@@ -643,8 +643,6 @@ static int compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka,
 	regs->compat_lr	= retcode;
 	regs->pc	= handler;
 	regs->pstate	= spsr;
-
-	return 0;
 }
 
 static int compat_setup_sigframe(struct compat_sigframe __user *sf,
@@ -714,11 +712,9 @@ int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
 	err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack));
 
 	err |= compat_setup_sigframe(&frame->sig, regs, set);
-	if (err == 0)
-		err = compat_setup_return(regs, ka, frame->sig.retcode, frame,
-					  usig);
 
 	if (err == 0) {
+		compat_setup_return(regs, ka, frame->sig.retcode, frame, usig);
 		regs->regs[1] = (compat_ulong_t)(unsigned long)&frame->info;
 		regs->regs[2] = (compat_ulong_t)(unsigned long)&frame->sig.uc;
 	}
@@ -741,7 +737,7 @@ int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
 
 	err |= compat_setup_sigframe(frame, regs, set);
 	if (err == 0)
-		err = compat_setup_return(regs, ka, frame->retcode, frame, usig);
+		compat_setup_return(regs, ka, frame->retcode, frame, usig);
 
 	return err;
 }
diff --git a/arch/arm64/kernel/sys.c b/arch/arm64/kernel/sys.c
index b120df3..8292a9b 100644
--- a/arch/arm64/kernel/sys.c
+++ b/arch/arm64/kernel/sys.c
@@ -26,85 +26,6 @@
 #include <linux/slab.h>
 #include <linux/syscalls.h>
 
-/*
- * Clone a task - this clones the calling program thread.
- */
-asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
-			  int __user *parent_tidptr, unsigned long tls_val,
-			  int __user *child_tidptr, struct pt_regs *regs)
-{
-	if (!newsp)
-		newsp = regs->sp;
-	/* 16-byte aligned stack mandatory on AArch64 */
-	if (newsp & 15)
-		return -EINVAL;
-	return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
-}
-
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage long sys_execve(const char __user *filenamei,
-			   const char __user *const __user *argv,
-			   const char __user *const __user *envp,
-			   struct pt_regs *regs)
-{
-	long error;
-	struct filename *filename;
-
-	filename = getname(filenamei);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-	error = do_execve(filename->name, argv, envp, regs);
-	putname(filename);
-out:
-	return error;
-}
-
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	struct pt_regs regs;
-	int ret;
-
-	memset(&regs, 0, sizeof(struct pt_regs));
-	ret = do_execve(filename,
-			(const char __user *const __user *)argv,
-			(const char __user *const __user *)envp, &regs);
-	if (ret < 0)
-		goto out;
-
-	/*
-	 * Save argc to the register structure for userspace.
-	 */
-	regs.regs[0] = ret;
-
-	/*
-	 * We were successful.  We won't be returning to our caller, but
-	 * instead to user space by manipulating the kernel stack.
-	 */
-	asm(	"add	x0, %0, %1\n\t"
-		"mov	x1, %2\n\t"
-		"mov	x2, %3\n\t"
-		"bl	memmove\n\t"	/* copy regs to top of stack */
-		"mov	x27, #0\n\t"	/* not a syscall */
-		"mov	x28, %0\n\t"	/* thread structure */
-		"mov	sp, x0\n\t"	/* reposition stack pointer */
-		"b	ret_to_user"
-		:
-		: "r" (current_thread_info()),
-		  "Ir" (THREAD_START_SP - sizeof(regs)),
-		  "r" (&regs),
-		  "Ir" (sizeof(regs))
-		: "x0", "x1", "x2", "x27", "x28", "x30", "memory");
-
- out:
-	return ret;
-}
-EXPORT_SYMBOL(kernel_execve);
-
 asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
 			 unsigned long prot, unsigned long flags,
 			 unsigned long fd, off_t off)
@@ -118,8 +39,6 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
 /*
  * Wrappers to pass the pt_regs argument.
  */
-#define sys_execve		sys_execve_wrapper
-#define sys_clone		sys_clone_wrapper
 #define sys_rt_sigreturn	sys_rt_sigreturn_wrapper
 #define sys_sigaltstack		sys_sigaltstack_wrapper
 
diff --git a/arch/arm64/kernel/sys32.S b/arch/arm64/kernel/sys32.S
index 54c4aec..7ef59e9 100644
--- a/arch/arm64/kernel/sys32.S
+++ b/arch/arm64/kernel/sys32.S
@@ -26,25 +26,6 @@
 /*
  * System call wrappers for the AArch32 compatibility layer.
  */
-compat_sys_fork_wrapper:
-	mov	x0, sp
-	b	compat_sys_fork
-ENDPROC(compat_sys_fork_wrapper)
-
-compat_sys_vfork_wrapper:
-	mov	x0, sp
-	b	compat_sys_vfork
-ENDPROC(compat_sys_vfork_wrapper)
-
-compat_sys_execve_wrapper:
-	mov	x3, sp
-	b	compat_sys_execve
-ENDPROC(compat_sys_execve_wrapper)
-
-compat_sys_clone_wrapper:
-	mov	x5, sp
-	b	compat_sys_clone
-ENDPROC(compat_sys_clone_wrapper)
 
 compat_sys_sigreturn_wrapper:
 	mov	x0, sp
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c
index 906e3bd..26e9c4e 100644
--- a/arch/arm64/kernel/sys_compat.c
+++ b/arch/arm64/kernel/sys_compat.c
@@ -28,60 +28,6 @@
 #include <asm/cacheflush.h>
 #include <asm/unistd32.h>
 
-asmlinkage int compat_sys_fork(struct pt_regs *regs)
-{
-	return do_fork(SIGCHLD, regs->compat_sp, regs, 0, NULL, NULL);
-}
-
-asmlinkage int compat_sys_clone(unsigned long clone_flags, unsigned long newsp,
-			  int __user *parent_tidptr, int tls_val,
-			  int __user *child_tidptr, struct pt_regs *regs)
-{
-	if (!newsp)
-		newsp = regs->compat_sp;
-
-	return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
-}
-
-asmlinkage int compat_sys_vfork(struct pt_regs *regs)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->compat_sp,
-		       regs, 0, NULL, NULL);
-}
-
-asmlinkage int compat_sys_execve(const char __user *filenamei,
-				 compat_uptr_t argv, compat_uptr_t envp,
-				 struct pt_regs *regs)
-{
-	int error;
-	struct filename *filename;
-
-	filename = getname(filenamei);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-	error = compat_do_execve(filename->name, compat_ptr(argv),
-					compat_ptr(envp), regs);
-	putname(filename);
-out:
-	return error;
-}
-
-asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid,
-						struct compat_timespec __user *interval)
-{
-	struct timespec t;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-
-	set_fs(KERNEL_DS);
-	ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
-	set_fs(old_fs);
-	if (put_compat_timespec(&t, interval))
-		return -EFAULT;
-	return ret;
-}
-
 static inline void
 do_compat_cache_op(unsigned long start, unsigned long end, int flags)
 {
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 1909a69..afadae6 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -36,6 +36,8 @@
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 
+static const char *fault_name(unsigned int esr);
+
 /*
  * Dump out the page tables associated with 'addr' in mm 'mm'.
  */
@@ -112,8 +114,9 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
 	struct siginfo si;
 
 	if (show_unhandled_signals) {
-		pr_info("%s[%d]: unhandled page fault (%d) at 0x%08lx, code 0x%03x\n",
-			tsk->comm, task_pid_nr(tsk), sig, addr, esr);
+		pr_info("%s[%d]: unhandled %s (%d) at 0x%08lx, esr 0x%03x\n",
+			tsk->comm, task_pid_nr(tsk), fault_name(esr), sig,
+			addr, esr);
 		show_pte(tsk->mm, addr);
 		show_regs(regs);
 	}
@@ -450,6 +453,12 @@ static struct fault_info {
 	{ do_bad,		SIGBUS,  0,		"unknown 63"			},
 };
 
+static const char *fault_name(unsigned int esr)
+{
+	const struct fault_info *inf = fault_info + (esr & 63);
+	return inf->name;
+}
+
 /*
  * Dispatch a data abort to the relevant handler.
  */
diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
index c144adb..88611c3 100644
--- a/arch/arm64/mm/flush.c
+++ b/arch/arm64/mm/flush.c
@@ -27,10 +27,6 @@
 
 #include "mm.h"
 
-void flush_cache_mm(struct mm_struct *mm)
-{
-}
-
 void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
 		       unsigned long end)
 {
@@ -38,11 +34,6 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
 		__flush_icache_all();
 }
 
-void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr,
-		      unsigned long pfn)
-{
-}
-
 static void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
 				unsigned long uaddr, void *kaddr,
 				unsigned long len)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 4cd2893..800aac3 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -79,8 +79,8 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
 
 #ifdef CONFIG_ZONE_DMA32
 	/* 4GB maximum for 32-bit only capable devices */
-	max_dma32 = min(max, MAX_DMA32_PFN);
-	zone_size[ZONE_DMA32] = max(min, max_dma32) - min;
+	max_dma32 = max(min, min(max, MAX_DMA32_PFN));
+	zone_size[ZONE_DMA32] = max_dma32 - min;
 #endif
 	zone_size[ZONE_NORMAL] = max - max_dma32;
 
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index 06e73bf..e40c9bd 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -17,6 +17,8 @@ config AVR32
 	select GENERIC_CLOCKEVENTS
 	select HAVE_MOD_ARCH_SPECIFIC
 	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
 	help
 	  AVR32 is a high-performance 32-bit RISC microprocessor core,
 	  designed for cost-sensitive embedded applications, with particular
@@ -80,7 +82,6 @@ config PLATFORM_AT32AP
 	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_ALLOCATOR
 	select HAVE_FB_ATMEL
-	select HAVE_NET_MACB
 
 #
 # CPU types
@@ -193,9 +194,6 @@ source "kernel/Kconfig.preempt"
 config QUICKLIST
 	def_bool y
 
-config HAVE_ARCH_BOOTMEM
-	def_bool n
-
 config ARCH_HAVE_MEMORY_PRESENT
 	def_bool n
 
diff --git a/arch/avr32/configs/atngw100_defconfig b/arch/avr32/configs/atngw100_defconfig
index a06bfcc..f4025db 100644
--- a/arch/avr32/configs/atngw100_defconfig
+++ b/arch/avr32/configs/atngw100_defconfig
@@ -109,7 +109,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
diff --git a/arch/avr32/configs/atngw100_evklcd100_defconfig b/arch/avr32/configs/atngw100_evklcd100_defconfig
index d8f1fe8..c76a49b 100644
--- a/arch/avr32/configs/atngw100_evklcd100_defconfig
+++ b/arch/avr32/configs/atngw100_evklcd100_defconfig
@@ -125,7 +125,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
diff --git a/arch/avr32/configs/atngw100_evklcd101_defconfig b/arch/avr32/configs/atngw100_evklcd101_defconfig
index d4c5b19..2d8ab08 100644
--- a/arch/avr32/configs/atngw100_evklcd101_defconfig
+++ b/arch/avr32/configs/atngw100_evklcd101_defconfig
@@ -124,7 +124,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
diff --git a/arch/avr32/configs/atngw100_mrmt_defconfig b/arch/avr32/configs/atngw100_mrmt_defconfig
index 77ca4f9..b189e0c 100644
--- a/arch/avr32/configs/atngw100_mrmt_defconfig
+++ b/arch/avr32/configs/atngw100_mrmt_defconfig
@@ -99,7 +99,7 @@ CONFIG_SND_ATMEL_AC97C=m
 # CONFIG_SND_SPI is not set
 CONFIG_USB_GADGET=m
 CONFIG_USB_GADGET_DEBUG_FILES=y
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 CONFIG_MMC_ATMELMCI=y
diff --git a/arch/avr32/configs/atngw100mkii_defconfig b/arch/avr32/configs/atngw100mkii_defconfig
index 6e0dca4..2e4de42 100644
--- a/arch/avr32/configs/atngw100mkii_defconfig
+++ b/arch/avr32/configs/atngw100mkii_defconfig
@@ -111,7 +111,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
diff --git a/arch/avr32/configs/atngw100mkii_evklcd100_defconfig b/arch/avr32/configs/atngw100mkii_evklcd100_defconfig
index 7f2a344..fad3cd2 100644
--- a/arch/avr32/configs/atngw100mkii_evklcd100_defconfig
+++ b/arch/avr32/configs/atngw100mkii_evklcd100_defconfig
@@ -128,7 +128,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
diff --git a/arch/avr32/configs/atngw100mkii_evklcd101_defconfig b/arch/avr32/configs/atngw100mkii_evklcd101_defconfig
index 085eeba..2998623 100644
--- a/arch/avr32/configs/atngw100mkii_evklcd101_defconfig
+++ b/arch/avr32/configs/atngw100mkii_evklcd101_defconfig
@@ -127,7 +127,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig
index d1a887e..a582465 100644
--- a/arch/avr32/configs/atstk1002_defconfig
+++ b/arch/avr32/configs/atstk1002_defconfig
@@ -126,7 +126,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
diff --git a/arch/avr32/configs/atstk1003_defconfig b/arch/avr32/configs/atstk1003_defconfig
index 956f281..57a79df 100644
--- a/arch/avr32/configs/atstk1003_defconfig
+++ b/arch/avr32/configs/atstk1003_defconfig
@@ -105,7 +105,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
diff --git a/arch/avr32/configs/atstk1004_defconfig b/arch/avr32/configs/atstk1004_defconfig
index 40c69f3..1a49bd8 100644
--- a/arch/avr32/configs/atstk1004_defconfig
+++ b/arch/avr32/configs/atstk1004_defconfig
@@ -104,7 +104,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
diff --git a/arch/avr32/configs/atstk1006_defconfig b/arch/avr32/configs/atstk1006_defconfig
index 511eb8a..206a1b6 100644
--- a/arch/avr32/configs/atstk1006_defconfig
+++ b/arch/avr32/configs/atstk1006_defconfig
@@ -129,7 +129,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
diff --git a/arch/avr32/configs/favr-32_defconfig b/arch/avr32/configs/favr-32_defconfig
index 19973b0..0421498 100644
--- a/arch/avr32/configs/favr-32_defconfig
+++ b/arch/avr32/configs/favr-32_defconfig
@@ -117,7 +117,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
diff --git a/arch/avr32/configs/hammerhead_defconfig b/arch/avr32/configs/hammerhead_defconfig
index 6f45681..82f24eb 100644
--- a/arch/avr32/configs/hammerhead_defconfig
+++ b/arch/avr32/configs/hammerhead_defconfig
@@ -127,7 +127,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=m
 CONFIG_MMC_ATMELMCI=m
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 4807ded..4dd4f78 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -1,3 +1,4 @@
 
 generic-y	+= clkdev.h
 generic-y	+= exec.h
+generic-y	+= trace_clock.h
diff --git a/arch/avr32/include/asm/mach/serial_at91.h b/arch/avr32/include/asm/mach/serial_at91.h
deleted file mode 100644
index 55b317a..0000000
--- a/arch/avr32/include/asm/mach/serial_at91.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *  linux/include/asm-arm/mach/serial_at91.h
- *
- *  Based on serial_sa1100.h  by Nicolas Pitre
- *
- *  Copyright (C) 2002 ATMEL Rousset
- *
- *  Low level machine dependent UART functions.
- */
-
-struct uart_port;
-
-/*
- * This is a temporary structure for registering these
- * functions; it is intended to be discarded after boot.
- */
-struct atmel_port_fns {
-	void	(*set_mctrl)(struct uart_port *, u_int);
-	u_int	(*get_mctrl)(struct uart_port *);
-	void	(*enable_ms)(struct uart_port *);
-	void	(*pm)(struct uart_port *, u_int, u_int);
-	int	(*set_wake)(struct uart_port *, u_int);
-	int	(*open)(struct uart_port *);
-	void	(*close)(struct uart_port *);
-};
-
-#if defined(CONFIG_SERIAL_ATMEL)
-void atmel_register_uart_fns(struct atmel_port_fns *fns);
-#else
-#define atmel_register_uart_fns(fns) do { } while (0)
-#endif
-
-
diff --git a/arch/avr32/include/asm/processor.h b/arch/avr32/include/asm/processor.h
index 87d8bac..48d71c5 100644
--- a/arch/avr32/include/asm/processor.h
+++ b/arch/avr32/include/asm/processor.h
@@ -142,9 +142,6 @@ struct task_struct;
 /* Free all resources held by a thread */
 extern void release_thread(struct task_struct *);
 
-/* Create a kernel thread without removing it from tasklists */
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 /* Return saved PC of a blocked thread */
 #define thread_saved_pc(tsk)    ((tsk)->thread.cpu_context.pc)
 
diff --git a/arch/avr32/include/asm/signal.h b/arch/avr32/include/asm/signal.h
index 4d502fd..9326d18 100644
--- a/arch/avr32/include/asm/signal.h
+++ b/arch/avr32/include/asm/signal.h
@@ -37,6 +37,4 @@ struct k_sigaction {
 #include <asm/sigcontext.h>
 #undef __HAVE_ARCH_SIG_BITOPS
 
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
 #endif
diff --git a/arch/avr32/include/asm/unistd.h b/arch/avr32/include/asm/unistd.h
index 157b4bd..f05a980 100644
--- a/arch/avr32/include/asm/unistd.h
+++ b/arch/avr32/include/asm/unistd.h
@@ -39,6 +39,10 @@
 #define __ARCH_WANT_SYS_GETPGRP
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_CLONE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/avr32/include/uapi/asm/socket.h b/arch/avr32/include/uapi/asm/socket.h
index a473f8c..486df68 100644
--- a/arch/avr32/include/uapi/asm/socket.h
+++ b/arch/avr32/include/uapi/asm/socket.h
@@ -40,6 +40,7 @@
 /* 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
diff --git a/arch/avr32/kernel/Makefile b/arch/avr32/kernel/Makefile
index 9e2c465..119a2e4 100644
--- a/arch/avr32/kernel/Makefile
+++ b/arch/avr32/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y				:= head.o vmlinux.lds
 obj-$(CONFIG_SUBARCH_AVR32B)	+= entry-avr32b.o
 obj-y				+= syscall_table.o syscall-stubs.o irq.o
 obj-y				+= setup.o traps.o ocd.o ptrace.o
-obj-y				+= signal.o sys_avr32.o process.o time.o
+obj-y				+= signal.o process.o time.o
 obj-y				+= switch_to.o cpu.o
 obj-$(CONFIG_MODULES)		+= module.o avr32_ksyms.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index df28841..9899d3c 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -251,13 +251,15 @@ syscall_badsys:
 	.global ret_from_fork
 ret_from_fork:
 	call   schedule_tail
+	mov	r12, 0
+	rjmp	syscall_return
 
-	/* check for syscall tracing */
-	get_thread_info r0
-	ld.w	r1, r0[TI_flags]
-	andl	r1, _TIF_ALLWORK_MASK, COH
-	brne	syscall_exit_work
-	rjmp    syscall_exit_cont
+	.global ret_from_kernel_thread
+ret_from_kernel_thread:
+	call   schedule_tail
+	mov	r12, r0
+	mov	lr, r2	/* syscall_return */
+	mov	pc, r1
 
 syscall_trace_enter:
 	pushm	r8-r12
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c
index 1bb0a8a..fd78f58 100644
--- a/arch/avr32/kernel/process.c
+++ b/arch/avr32/kernel/process.c
@@ -69,44 +69,6 @@ void machine_restart(char *cmd)
 }
 
 /*
- * PC is actually discarded when returning from a system call -- the
- * return address must be stored in LR. This function will make sure
- * LR points to do_exit before starting the thread.
- *
- * Also, when returning from fork(), r12 is 0, so we must copy the
- * argument as well.
- *
- *  r0 : The argument to the main thread function
- *  r1 : The address of do_exit
- *  r2 : The address of the main thread function
- */
-asmlinkage extern void kernel_thread_helper(void);
-__asm__("	.type	kernel_thread_helper, @function\n"
-	"kernel_thread_helper:\n"
-	"	mov	r12, r0\n"
-	"	mov	lr, r2\n"
-	"	mov	pc, r1\n"
-	"	.size	kernel_thread_helper, . - kernel_thread_helper");
-
-int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-
-	regs.r0 = (unsigned long)arg;
-	regs.r1 = (unsigned long)fn;
-	regs.r2 = (unsigned long)do_exit;
-	regs.lr = (unsigned long)kernel_thread_helper;
-	regs.pc = (unsigned long)kernel_thread_helper;
-	regs.sr = MODE_SUPERVISOR;
-
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
-		       0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
-/*
  * Free current thread data structures etc
  */
 void exit_thread(void)
@@ -332,26 +294,32 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 }
 
 asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
+asmlinkage void syscall_return(void);
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-		unsigned long unused,
-		struct task_struct *p, struct pt_regs *regs)
+		unsigned long arg,
+		struct task_struct *p)
 {
-	struct pt_regs *childregs;
-
-	childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)task_stack_page(p))) - 1;
-	*childregs = *regs;
-
-	if (user_mode(regs))
-		childregs->sp = usp;
-	else
-		childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
-
-	childregs->r12 = 0; /* Set return value for child */
+	struct pt_regs *childregs = task_pt_regs(p);
+
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		memset(childregs, 0, sizeof(struct pt_regs));
+		p->thread.cpu_context.r0 = arg;
+		p->thread.cpu_context.r1 = usp; /* fn */
+		p->thread.cpu_context.r2 = syscall_return;
+		p->thread.cpu_context.pc = (unsigned long)ret_from_kernel_thread;
+		childregs->sr = MODE_SUPERVISOR;
+	} else {
+		*childregs = *current_pt_regs();
+		if (usp)
+			childregs->sp = usp;
+		childregs->r12 = 0; /* Set return value for child */
+		p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
+	}
 
 	p->thread.cpu_context.sr = MODE_SUPERVISOR | SR_GM;
 	p->thread.cpu_context.ksp = (unsigned long)childregs;
-	p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
 
 	clear_tsk_thread_flag(p, TIF_DEBUG);
 	if ((clone_flags & CLONE_PTRACE) && test_thread_flag(TIF_DEBUG))
@@ -360,49 +328,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	return 0;
 }
 
-/* r12-r8 are dummy parameters to force the compiler to use the stack */
-asmlinkage int sys_fork(struct pt_regs *regs)
-{
-	return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
-}
-
-asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
-		void __user *parent_tidptr, void __user *child_tidptr,
-		struct pt_regs *regs)
-{
-	if (!newsp)
-		newsp = regs->sp;
-	return do_fork(clone_flags, newsp, regs, 0, parent_tidptr,
-			child_tidptr);
-}
-
-asmlinkage int sys_vfork(struct pt_regs *regs)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs,
-		       0, NULL, NULL);
-}
-
-asmlinkage int sys_execve(const char __user *ufilename,
-			  const char __user *const __user *uargv,
-			  const char __user *const __user *uenvp,
-			  struct pt_regs *regs)
-{
-	int error;
-	struct filename *filename;
-
-	filename = getname(ufilename);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-
-	error = do_execve(filename->name, uargv, uenvp, regs);
-	putname(filename);
-
-out:
-	return error;
-}
-
-
 /*
  * This function is supposed to answer the question "who called
  * schedule()?"
diff --git a/arch/avr32/kernel/sys_avr32.c b/arch/avr32/kernel/sys_avr32.c
deleted file mode 100644
index 62635a0..0000000
--- a/arch/avr32/kernel/sys_avr32.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2004-2006 Atmel 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/unistd.h>
-
-int kernel_execve(const char *file,
-		  const char *const *argv,
-		  const char *const *envp)
-{
-	register long scno asm("r8") = __NR_execve;
-	register long sc1 asm("r12") = (long)file;
-	register long sc2 asm("r11") = (long)argv;
-	register long sc3 asm("r10") = (long)envp;
-
-	asm volatile("scall"
-		     : "=r"(sc1)
-		     : "r"(scno), "0"(sc1), "r"(sc2), "r"(sc3)
-		     : "cc", "memory");
-	return sc1;
-}
diff --git a/arch/avr32/kernel/syscall-stubs.S b/arch/avr32/kernel/syscall-stubs.S
index 0447a3e..275aab9 100644
--- a/arch/avr32/kernel/syscall-stubs.S
+++ b/arch/avr32/kernel/syscall-stubs.S
@@ -32,30 +32,6 @@ __sys_rt_sigreturn:
 	mov	r12, sp
 	rjmp	sys_rt_sigreturn
 
-	.global	__sys_fork
-	.type	__sys_fork,@function
-__sys_fork:
-	mov	r12, sp
-	rjmp	sys_fork
-
-	.global	__sys_clone
-	.type	__sys_clone,@function
-__sys_clone:
-	mov	r8, sp
-	rjmp	sys_clone
-
-	.global	__sys_vfork
-	.type	__sys_vfork,@function
-__sys_vfork:
-	mov	r12, sp
-	rjmp	sys_vfork
-
-	.global	__sys_execve
-	.type	__sys_execve,@function
-__sys_execve:
-	mov	r9, sp
-	rjmp	sys_execve
-
 	.global	__sys_mmap2
 	.type	__sys_mmap2,@function
 __sys_mmap2:
diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S
index 6eba535..f27bb87 100644
--- a/arch/avr32/kernel/syscall_table.S
+++ b/arch/avr32/kernel/syscall_table.S
@@ -15,7 +15,7 @@
 sys_call_table:
 	.long	sys_restart_syscall
 	.long	sys_exit
-	.long	__sys_fork
+	.long	sys_fork
 	.long	sys_read
 	.long	sys_write
 	.long	sys_open		/* 5 */
@@ -24,7 +24,7 @@ sys_call_table:
 	.long	sys_creat
 	.long	sys_link
 	.long	sys_unlink		/* 10 */
-	.long	__sys_execve
+	.long	sys_execve
 	.long	sys_chdir
 	.long	sys_time
 	.long	sys_mknod
@@ -57,7 +57,7 @@ sys_call_table:
 	.long	sys_dup
 	.long	sys_pipe
 	.long	sys_times
-	.long	__sys_clone
+	.long	sys_clone
 	.long	sys_brk			/* 45 */
 	.long	sys_setgid
 	.long	sys_getgid
@@ -127,7 +127,7 @@ sys_call_table:
 	.long	sys_newuname
 	.long	sys_adjtimex
 	.long	sys_mprotect
-	.long	__sys_vfork
+	.long	sys_vfork
 	.long	sys_init_module		/* 115 */
 	.long	sys_delete_module
 	.long	sys_quotactl
diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h
index 70742ec..d485b03 100644
--- a/arch/avr32/mach-at32ap/include/mach/board.h
+++ b/arch/avr32/mach-at32ap/include/mach/board.h
@@ -26,7 +26,6 @@ static inline void __deprecated at32_add_system_devices(void)
 
 }
 
-#define ATMEL_MAX_UART	4
 extern struct platform_device *atmel_default_console_device;
 
 /* Flags for selecting USART extra pins */
@@ -34,13 +33,6 @@ extern struct platform_device *atmel_default_console_device;
 #define	ATMEL_USART_CTS		0x02
 #define	ATMEL_USART_CLK		0x04
 
-struct atmel_uart_data {
-	int		num;		/* port num */
-	short		use_dma_tx;	/* use transmit DMA? */
-	short		use_dma_rx;	/* use receive DMA? */
-	void __iomem	*regs;		/* virtual base address, if any */
-	struct serial_rs485	rs485;		/* rs485 settings */
-};
 void at32_map_usart(unsigned int hw_id, unsigned int line, int flags);
 struct platform_device *at32_add_device_usart(unsigned int id);
 
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index b6f3ad5..ab9ff40 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -45,6 +45,8 @@ config BLACKFIN
 	select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS
 	select HAVE_MOD_ARCH_SPECIFIC
 	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
 
 config GENERIC_CSUM
 	def_bool y
diff --git a/arch/blackfin/configs/CM-BF527_defconfig b/arch/blackfin/configs/CM-BF527_defconfig
index c280a50..f59c80e 100644
--- a/arch/blackfin/configs/CM-BF527_defconfig
+++ b/arch/blackfin/configs/CM-BF527_defconfig
@@ -106,7 +106,7 @@ CONFIG_MUSB_PIO_ONLY=y
 CONFIG_USB_STORAGE=m
 CONFIG_USB_GADGET=m
 CONFIG_USB_ETH=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_RTC_CLASS=y
diff --git a/arch/blackfin/configs/CM-BF548_defconfig b/arch/blackfin/configs/CM-BF548_defconfig
index 349922b..e961483 100644
--- a/arch/blackfin/configs/CM-BF548_defconfig
+++ b/arch/blackfin/configs/CM-BF548_defconfig
@@ -107,7 +107,7 @@ CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_MMC=m
diff --git a/arch/blackfin/configs/CM-BF561_defconfig b/arch/blackfin/configs/CM-BF561_defconfig
index 0456dea..24936b9 100644
--- a/arch/blackfin/configs/CM-BF561_defconfig
+++ b/arch/blackfin/configs/CM-BF561_defconfig
@@ -83,7 +83,7 @@ CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_USB_GADGET=m
 CONFIG_USB_ETH=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_MMC=y
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 5a0625a..127826f 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -1,4 +1,3 @@
-include include/asm-generic/Kbuild.asm
 
 generic-y += auxvec.h
 generic-y += bitsperlong.h
@@ -17,6 +16,7 @@ generic-y += ipcbuf.h
 generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += kmap_types.h
+generic-y += kvm_para.h
 generic-y += local64.h
 generic-y += local.h
 generic-y += mman.h
@@ -38,12 +38,9 @@ generic-y += statfs.h
 generic-y += termbits.h
 generic-y += termios.h
 generic-y += topology.h
+generic-y += trace_clock.h
 generic-y += types.h
 generic-y += ucontext.h
 generic-y += unaligned.h
 generic-y += user.h
 generic-y += xor.h
-
-header-y += bfin_sport.h
-header-y += cachectl.h
-header-y += fixed_code.h
diff --git a/arch/blackfin/include/asm/bfin_sport.h b/arch/blackfin/include/asm/bfin_sport.h
index f8907ea..50b9dfd 100644
--- a/arch/blackfin/include/asm/bfin_sport.h
+++ b/arch/blackfin/include/asm/bfin_sport.h
@@ -5,65 +5,12 @@
  *
  * Licensed under the GPL-2 or later.
  */
-
 #ifndef __BFIN_SPORT_H__
 #define __BFIN_SPORT_H__
 
-/* Sport mode: it can be set to TDM, i2s or others */
-#define NORM_MODE	0x0
-#define TDM_MODE	0x1
-#define I2S_MODE	0x2
-#define NDSO_MODE	0x3
-
-/* Data format, normal, a-law or u-law */
-#define NORM_FORMAT	0x0
-#define ALAW_FORMAT	0x2
-#define ULAW_FORMAT	0x3
-
-/* Function driver which use sport must initialize the structure */
-struct sport_config {
-	/* TDM (multichannels), I2S or other mode */
-	unsigned int mode:3;
-	unsigned int polled;	/* use poll instead of irq when set */
-
-	/* if TDM mode is selected, channels must be set */
-	int channels;	/* Must be in 8 units */
-	unsigned int frame_delay:4;	/* Delay between frame sync pulse and first bit */
-
-	/* I2S mode */
-	unsigned int right_first:1;	/* Right stereo channel first */
-
-	/* In mormal mode, the following item need to be set */
-	unsigned int lsb_first:1;	/* order of transmit or receive data */
-	unsigned int fsync:1;	/* Frame sync required */
-	unsigned int data_indep:1;	/* data independent frame sync generated */
-	unsigned int act_low:1;	/* Active low TFS */
-	unsigned int late_fsync:1;	/* Late frame sync */
-	unsigned int tckfe:1;
-	unsigned int sec_en:1;	/* Secondary side enabled */
-
-	/* Choose clock source */
-	unsigned int int_clk:1;	/* Internal or external clock */
-
-	/* If external clock is used, the following fields are ignored */
-	int serial_clk;
-	int fsync_clk;
-
-	unsigned int data_format:2;	/* Normal, u-law or a-law */
-
-	int word_len;		/* How length of the word in bits, 3-32 bits */
-	int dma_enabled;
-};
-
-/* Userspace interface */
-#define SPORT_IOC_MAGIC		'P'
-#define SPORT_IOC_CONFIG	_IOWR('P', 0x01, struct sport_config)
-#define SPORT_IOC_GET_SYSTEMCLOCK         _IOR('P', 0x02, unsigned long)
-#define SPORT_IOC_SET_BAUDRATE            _IOW('P', 0x03, unsigned long)
-
-#ifdef __KERNEL__
 
 #include <linux/types.h>
+#include <uapi/asm/bfin_sport.h>
 
 /*
  * All Blackfin system MMRs are padded to 32bits even if the register
@@ -122,76 +69,3 @@ struct bfin_snd_platform_data {
 })
 
 #endif
-
-/* SPORT_TCR1 Masks */
-#define TSPEN		0x0001	/* TX enable */
-#define ITCLK		0x0002	/* Internal TX Clock Select */
-#define TDTYPE		0x000C	/* TX Data Formatting Select */
-#define DTYPE_NORM	0x0000	/* Data Format Normal */
-#define DTYPE_ULAW	0x0008	/* Compand Using u-Law */
-#define DTYPE_ALAW	0x000C	/* Compand Using A-Law */
-#define TLSBIT		0x0010	/* TX Bit Order */
-#define ITFS		0x0200	/* Internal TX Frame Sync Select */
-#define TFSR		0x0400	/* TX Frame Sync Required Select */
-#define DITFS		0x0800	/* Data Independent TX Frame Sync Select */
-#define LTFS		0x1000	/* Low TX Frame Sync Select */
-#define LATFS		0x2000	/* Late TX Frame Sync Select */
-#define TCKFE		0x4000	/* TX Clock Falling Edge Select */
-
-/* SPORT_TCR2 Masks */
-#define SLEN		0x001F	/* SPORT TX Word Length (2 - 31) */
-#define DP_SLEN(x)	BFIN_DEPOSIT(SLEN, x)
-#define EX_SLEN(x)	BFIN_EXTRACT(SLEN, x)
-#define TXSE		0x0100	/* TX Secondary Enable */
-#define TSFSE		0x0200	/* TX Stereo Frame Sync Enable */
-#define TRFST		0x0400	/* TX Right-First Data Order */
-
-/* SPORT_RCR1 Masks */
-#define RSPEN		0x0001	/* RX enable */
-#define IRCLK		0x0002	/* Internal RX Clock Select */
-#define RDTYPE		0x000C	/* RX Data Formatting Select */
-/* DTYPE_* defined above */
-#define RLSBIT		0x0010	/* RX Bit Order */
-#define IRFS		0x0200	/* Internal RX Frame Sync Select */
-#define RFSR		0x0400	/* RX Frame Sync Required Select */
-#define LRFS		0x1000	/* Low RX Frame Sync Select */
-#define LARFS		0x2000	/* Late RX Frame Sync Select */
-#define RCKFE		0x4000	/* RX Clock Falling Edge Select */
-
-/* SPORT_RCR2 Masks */
-/* SLEN defined above */
-#define RXSE		0x0100	/* RX Secondary Enable */
-#define RSFSE		0x0200	/* RX Stereo Frame Sync Enable */
-#define RRFST		0x0400	/* Right-First Data Order */
-
-/* SPORT_STAT Masks */
-#define RXNE		0x0001	/* RX FIFO Not Empty Status */
-#define RUVF		0x0002	/* RX Underflow Status */
-#define ROVF		0x0004	/* RX Overflow Status */
-#define TXF		0x0008	/* TX FIFO Full Status */
-#define TUVF		0x0010	/* TX Underflow Status */
-#define TOVF		0x0020	/* TX Overflow Status */
-#define TXHRE		0x0040	/* TX Hold Register Empty */
-
-/* SPORT_MCMC1 Masks */
-#define SP_WOFF		0x03FF	/* Multichannel Window Offset Field */
-#define DP_SP_WOFF(x)	BFIN_DEPOSIT(SP_WOFF, x)
-#define EX_SP_WOFF(x)	BFIN_EXTRACT(SP_WOFF, x)
-#define SP_WSIZE	0xF000	/* Multichannel Window Size Field */
-#define DP_SP_WSIZE(x)	BFIN_DEPOSIT(SP_WSIZE, x)
-#define EX_SP_WSIZE(x)	BFIN_EXTRACT(SP_WSIZE, x)
-
-/* SPORT_MCMC2 Masks */
-#define MCCRM		0x0003	/* Multichannel Clock Recovery Mode */
-#define REC_BYPASS	0x0000	/* Bypass Mode (No Clock Recovery) */
-#define REC_2FROM4	0x0002	/* Recover 2 MHz Clock from 4 MHz Clock */
-#define REC_8FROM16	0x0003	/* Recover 8 MHz Clock from 16 MHz Clock */
-#define MCDTXPE		0x0004	/* Multichannel DMA Transmit Packing */
-#define MCDRXPE		0x0008	/* Multichannel DMA Receive Packing */
-#define MCMEN		0x0010	/* Multichannel Frame Mode Enable */
-#define FSDR		0x0080	/* Multichannel Frame Sync to Data Relationship */
-#define MFD		0xF000	/* Multichannel Frame Delay */
-#define DP_MFD(x)	BFIN_DEPOSIT(MFD, x)
-#define EX_MFD(x)	BFIN_EXTRACT(MFD, x)
-
-#endif
diff --git a/arch/blackfin/include/asm/bfin_twi.h b/arch/blackfin/include/asm/bfin_twi.h
index f4a0727..90c3c00 100644
--- a/arch/blackfin/include/asm/bfin_twi.h
+++ b/arch/blackfin/include/asm/bfin_twi.h
@@ -61,7 +61,7 @@ struct bfin_twi_iface {
 	int			cur_msg;
 	u16			saved_clkdiv;
 	u16			saved_control;
-	struct bfin_twi_regs	*regs_base;
+	struct bfin_twi_regs __iomem *regs_base;
 };
 
 #define DEFINE_TWI_REG(reg_name, reg) \
diff --git a/arch/blackfin/include/asm/byteorder.h b/arch/blackfin/include/asm/byteorder.h
deleted file mode 100644
index 9558416..0000000
--- a/arch/blackfin/include/asm/byteorder.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/byteorder/little_endian.h>
diff --git a/arch/blackfin/include/asm/cachectl.h b/arch/blackfin/include/asm/cachectl.h
deleted file mode 100644
index 03255df..0000000
--- a/arch/blackfin/include/asm/cachectl.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * based on the mips/cachectl.h
- *
- * Copyright 2010 Analog Devices Inc.
- * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
- *
- * Licensed under the GPL-2 or later.
- */
-
-#ifndef	_ASM_CACHECTL
-#define	_ASM_CACHECTL
-
-/*
- * Options for cacheflush system call
- */
-#define	ICACHE	(1<<0)		/* flush instruction cache        */
-#define	DCACHE	(1<<1)		/* writeback and flush data cache */
-#define	BCACHE	(ICACHE|DCACHE)	/* flush both caches              */
-
-#endif	/* _ASM_CACHECTL */
diff --git a/arch/blackfin/include/asm/fcntl.h b/arch/blackfin/include/asm/fcntl.h
deleted file mode 100644
index 251c911..0000000
--- a/arch/blackfin/include/asm/fcntl.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2004-2008 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#ifndef _BFIN_FCNTL_H
-#define _BFIN_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
diff --git a/arch/blackfin/include/asm/fixed_code.h b/arch/blackfin/include/asm/fixed_code.h
index 5395088..bc330f0 100644
--- a/arch/blackfin/include/asm/fixed_code.h
+++ b/arch/blackfin/include/asm/fixed_code.h
@@ -6,11 +6,11 @@
  *
  * Licensed under the GPL-2 or later.
  */
-
 #ifndef __BFIN_ASM_FIXED_CODE_H__
 #define __BFIN_ASM_FIXED_CODE_H__
 
-#ifdef __KERNEL__
+#include <uapi/asm/fixed_code.h>
+
 #ifndef __ASSEMBLY__
 #include <linux/linkage.h>
 #include <linux/ptrace.h>
@@ -28,29 +28,3 @@ extern void safe_user_instruction(void);
 extern void sigreturn_stub(void);
 #endif
 #endif
-
-#ifndef CONFIG_PHY_RAM_BASE_ADDRESS
-#define CONFIG_PHY_RAM_BASE_ADDRESS	0x0
-#endif
-
-#define FIXED_CODE_START	(CONFIG_PHY_RAM_BASE_ADDRESS + 0x400)
-
-#define SIGRETURN_STUB		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x400)
-
-#define ATOMIC_SEQS_START	(CONFIG_PHY_RAM_BASE_ADDRESS + 0x410)
-
-#define ATOMIC_XCHG32		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x410)
-#define ATOMIC_CAS32		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x420)
-#define ATOMIC_ADD32		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x430)
-#define ATOMIC_SUB32		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x440)
-#define ATOMIC_IOR32		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x450)
-#define ATOMIC_AND32		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x460)
-#define ATOMIC_XOR32		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x470)
-
-#define ATOMIC_SEQS_END		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x480)
-
-#define SAFE_USER_INSTRUCTION   (CONFIG_PHY_RAM_BASE_ADDRESS + 0x480)
-
-#define FIXED_CODE_END		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x490)
-
-#endif
diff --git a/arch/blackfin/include/asm/ioctls.h b/arch/blackfin/include/asm/ioctls.h
deleted file mode 100644
index eca8d75..0000000
--- a/arch/blackfin/include/asm/ioctls.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ARCH_BFIN_IOCTLS_H__
-#define __ARCH_BFIN_IOCTLS_H__
-
-#define FIOQSIZE	0x545E
-#include <asm-generic/ioctls.h>
-
-#endif
diff --git a/arch/blackfin/include/asm/kvm_para.h b/arch/blackfin/include/asm/kvm_para.h
deleted file mode 100644
index 14fab8f..0000000
--- a/arch/blackfin/include/asm/kvm_para.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
diff --git a/arch/blackfin/include/asm/pgtable.h b/arch/blackfin/include/asm/pgtable.h
index dcca3e6..b866392 100644
--- a/arch/blackfin/include/asm/pgtable.h
+++ b/arch/blackfin/include/asm/pgtable.h
@@ -83,8 +83,6 @@ PTE_BIT_FUNC(mkyoung, |= _PAGE_ACCESSED);
 #define ZERO_PAGE(vaddr)	virt_to_page(empty_zero_page)
 extern char empty_zero_page[];
 
-extern unsigned int kobjsize(const void *objp);
-
 #define swapper_pg_dir ((pgd_t *) 0)
 /*
  * No page table caches to initialise.
diff --git a/arch/blackfin/include/asm/poll.h b/arch/blackfin/include/asm/poll.h
deleted file mode 100644
index 072d896..0000000
--- a/arch/blackfin/include/asm/poll.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2004-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- *
- */
-
-#ifndef __BFIN_POLL_H
-#define __BFIN_POLL_H
-
-#define POLLWRNORM	4 /* POLLOUT */
-#define POLLWRBAND	256
-
-#include <asm-generic/poll.h>
-
-#endif
diff --git a/arch/blackfin/include/asm/posix_types.h b/arch/blackfin/include/asm/posix_types.h
deleted file mode 100644
index 1bd3436..0000000
--- a/arch/blackfin/include/asm/posix_types.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2004-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#ifndef __ARCH_BFIN_POSIX_TYPES_H
-#define __ARCH_BFIN_POSIX_TYPES_H
-
-typedef unsigned short __kernel_mode_t;
-#define __kernel_mode_t __kernel_mode_t
-
-typedef unsigned int __kernel_ipc_pid_t;
-#define __kernel_ipc_pid_t __kernel_ipc_pid_t
-
-typedef unsigned long __kernel_size_t;
-typedef long __kernel_ssize_t;
-typedef int __kernel_ptrdiff_t;
-#define __kernel_size_t __kernel_size_t
-
-typedef unsigned short __kernel_old_uid_t;
-typedef unsigned short __kernel_old_gid_t;
-#define __kernel_old_uid_t __kernel_old_uid_t
-
-typedef unsigned short __kernel_old_dev_t;
-#define __kernel_old_dev_t __kernel_old_dev_t
-
-#include <asm-generic/posix_types.h>
-
-#endif
diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h
index 4ef7cfe..d0e72e9 100644
--- a/arch/blackfin/include/asm/processor.h
+++ b/arch/blackfin/include/asm/processor.h
@@ -75,8 +75,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-extern int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags);
-
 /*
  * Free current thread data structures etc..
  */
diff --git a/arch/blackfin/include/asm/ptrace.h b/arch/blackfin/include/asm/ptrace.h
index 10d8641..14ea933 100644
--- a/arch/blackfin/include/asm/ptrace.h
+++ b/arch/blackfin/include/asm/ptrace.h
@@ -3,102 +3,13 @@
  *
  * Licensed under the GPL-2 or later.
  */
-
 #ifndef _BFIN_PTRACE_H
 #define _BFIN_PTRACE_H
 
-/*
- * GCC defines register number like this:
- * -----------------------------
- *       0 - 7 are data registers R0-R7
- *       8 - 15 are address registers P0-P7
- *      16 - 31 dsp registers I/B/L0 -- I/B/L3 & M0--M3
- *      32 - 33 A registers A0 & A1
- *      34 -    status register
- * -----------------------------
- *
- * We follows above, except:
- *      32-33 --- Low 32-bit of A0&1
- *      34-35 --- High 8-bit of A0&1
- */
+#include <uapi/asm/ptrace.h>
 
 #ifndef __ASSEMBLY__
 
-struct task_struct;
-
-/* this struct defines the way the registers are stored on the
-   stack during a system call. */
-
-struct pt_regs {
-	long orig_pc;
-	long ipend;
-	long seqstat;
-	long rete;
-	long retn;
-	long retx;
-	long pc;		/* PC == RETI */
-	long rets;
-	long reserved;		/* Used as scratch during system calls */
-	long astat;
-	long lb1;
-	long lb0;
-	long lt1;
-	long lt0;
-	long lc1;
-	long lc0;
-	long a1w;
-	long a1x;
-	long a0w;
-	long a0x;
-	long b3;
-	long b2;
-	long b1;
-	long b0;
-	long l3;
-	long l2;
-	long l1;
-	long l0;
-	long m3;
-	long m2;
-	long m1;
-	long m0;
-	long i3;
-	long i2;
-	long i1;
-	long i0;
-	long usp;
-	long fp;
-	long p5;
-	long p4;
-	long p3;
-	long p2;
-	long p1;
-	long p0;
-	long r7;
-	long r6;
-	long r5;
-	long r4;
-	long r3;
-	long r2;
-	long r1;
-	long r0;
-	long orig_r0;
-	long orig_p0;
-	long syscfg;
-};
-
-/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
-#define PTRACE_GETREGS            12
-#define PTRACE_SETREGS            13	/* ptrace signal  */
-
-#define PTRACE_GETFDPIC           31	/* get the ELF fdpic loadmap address */
-#define PTRACE_GETFDPIC_EXEC       0	/* [addr] request the executable loadmap */
-#define PTRACE_GETFDPIC_INTERP     1	/* [addr] request the interpreter loadmap */
-
-#define PS_S  (0x0002)
-
-#ifdef __KERNEL__
-
 /* user_mode returns true if only one bit is set in IPEND, other than the
    master interrupt enable.  */
 #define user_mode(regs) (!(((regs)->ipend & ~0x10) & (((regs)->ipend & ~0x10) - 1)))
@@ -126,75 +37,5 @@ extern int is_user_addr_valid(struct task_struct *child,
 
 #include <asm-generic/ptrace.h>
 
-#endif  /*  __KERNEL__  */
-
 #endif				/* __ASSEMBLY__ */
-
-/*
- * Offsets used by 'ptrace' system call interface.
- */
-
-#define PT_R0 204
-#define PT_R1 200
-#define PT_R2 196
-#define PT_R3 192
-#define PT_R4 188
-#define PT_R5 184
-#define PT_R6 180
-#define PT_R7 176
-#define PT_P0 172
-#define PT_P1 168
-#define PT_P2 164
-#define PT_P3 160
-#define PT_P4 156
-#define PT_P5 152
-#define PT_FP 148
-#define PT_USP 144
-#define PT_I0 140
-#define PT_I1 136
-#define PT_I2 132
-#define PT_I3 128
-#define PT_M0 124
-#define PT_M1 120
-#define PT_M2 116
-#define PT_M3 112
-#define PT_L0 108
-#define PT_L1 104
-#define PT_L2 100
-#define PT_L3 96
-#define PT_B0 92
-#define PT_B1 88
-#define PT_B2 84
-#define PT_B3 80
-#define PT_A0X 76
-#define PT_A0W 72
-#define PT_A1X 68
-#define PT_A1W 64
-#define PT_LC0 60
-#define PT_LC1 56
-#define PT_LT0 52
-#define PT_LT1 48
-#define PT_LB0 44
-#define PT_LB1 40
-#define PT_ASTAT 36
-#define PT_RESERVED 32
-#define PT_RETS 28
-#define PT_PC 24
-#define PT_RETX 20
-#define PT_RETN 16
-#define PT_RETE 12
-#define PT_SEQSTAT 8
-#define PT_IPEND 4
-
-#define PT_ORIG_R0 208
-#define PT_ORIG_P0 212
-#define PT_SYSCFG 216
-#define PT_TEXT_ADDR 220
-#define PT_TEXT_END_ADDR 224
-#define PT_DATA_ADDR 228
-#define PT_FDPIC_EXEC 232
-#define PT_FDPIC_INTERP 236
-
-#define PT_LAST_PSEUDO PT_FDPIC_INTERP
-
 #endif				/* _BFIN_PTRACE_H */
diff --git a/arch/blackfin/include/asm/sigcontext.h b/arch/blackfin/include/asm/sigcontext.h
deleted file mode 100644
index 906bdc1..0000000
--- a/arch/blackfin/include/asm/sigcontext.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2004-2008 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#ifndef _ASM_BLACKFIN_SIGCONTEXT_H
-#define _ASM_BLACKFIN_SIGCONTEXT_H
-
-/* Add new entries at the end of the structure only.  */
-struct sigcontext {
-	unsigned long sc_r0;
-	unsigned long sc_r1;
-	unsigned long sc_r2;
-	unsigned long sc_r3;
-	unsigned long sc_r4;
-	unsigned long sc_r5;
-	unsigned long sc_r6;
-	unsigned long sc_r7;
-	unsigned long sc_p0;
-	unsigned long sc_p1;
-	unsigned long sc_p2;
-	unsigned long sc_p3;
-	unsigned long sc_p4;
-	unsigned long sc_p5;
-	unsigned long sc_usp;
-	unsigned long sc_a0w;
-	unsigned long sc_a1w;
-	unsigned long sc_a0x;
-	unsigned long sc_a1x;
-	unsigned long sc_astat;
-	unsigned long sc_rets;
-	unsigned long sc_pc;
-	unsigned long sc_retx;
-	unsigned long sc_fp;
-	unsigned long sc_i0;
-	unsigned long sc_i1;
-	unsigned long sc_i2;
-	unsigned long sc_i3;
-	unsigned long sc_m0;
-	unsigned long sc_m1;
-	unsigned long sc_m2;
-	unsigned long sc_m3;
-	unsigned long sc_l0;
-	unsigned long sc_l1;
-	unsigned long sc_l2;
-	unsigned long sc_l3;
-	unsigned long sc_b0;
-	unsigned long sc_b1;
-	unsigned long sc_b2;
-	unsigned long sc_b3;
-	unsigned long sc_lc0;
-	unsigned long sc_lc1;
-	unsigned long sc_lt0;
-	unsigned long sc_lt1;
-	unsigned long sc_lb0;
-	unsigned long sc_lb1;
-	unsigned long sc_seqstat;
-};
-
-#endif
diff --git a/arch/blackfin/include/asm/siginfo.h b/arch/blackfin/include/asm/siginfo.h
deleted file mode 100644
index 3e81306..0000000
--- a/arch/blackfin/include/asm/siginfo.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2004-2008 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#ifndef _BFIN_SIGINFO_H
-#define _BFIN_SIGINFO_H
-
-#include <linux/types.h>
-#include <asm-generic/siginfo.h>
-
-#define UID16_SIGINFO_COMPAT_NEEDED
-
-#define si_uid16	_sifields._kill._uid
-
-#define ILL_ILLPARAOP	(__SI_FAULT|2)	/* illegal opcode combine ********** */
-#define ILL_ILLEXCPT	(__SI_FAULT|4)	/* unrecoverable exception ********** */
-#define ILL_CPLB_VI	(__SI_FAULT|9)	/* D/I CPLB protect violation ******** */
-#define ILL_CPLB_MISS	(__SI_FAULT|10)	/* D/I CPLB miss ******** */
-#define ILL_CPLB_MULHIT	(__SI_FAULT|11)	/* D/I CPLB multiple hit ******** */
-
-/*
- * SIGBUS si_codes
- */
-#define BUS_OPFETCH	(__SI_FAULT|4)	/* error from instruction fetch ******** */
-
-/*
- * SIGTRAP si_codes
- */
-#define TRAP_STEP	(__SI_FAULT|1)	/* single-step breakpoint************* */
-#define TRAP_TRACEFLOW	(__SI_FAULT|2)	/* trace buffer overflow ************* */
-#define TRAP_WATCHPT	(__SI_FAULT|3)	/* watchpoint match      ************* */
-#define TRAP_ILLTRAP	(__SI_FAULT|4)	/* illegal trap          ************* */
-
-/*
- * SIGSEGV si_codes
- */
-#define SEGV_STACKFLOW	(__SI_FAULT|3)	/* stack overflow */
-
-#endif
diff --git a/arch/blackfin/include/asm/signal.h b/arch/blackfin/include/asm/signal.h
deleted file mode 100644
index 77a3bf3..0000000
--- a/arch/blackfin/include/asm/signal.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _BLACKFIN_SIGNAL_H
-#define _BLACKFIN_SIGNAL_H
-
-#define SA_RESTORER 0x04000000
-#include <asm-generic/signal.h>
-
-#endif
diff --git a/arch/blackfin/include/asm/stat.h b/arch/blackfin/include/asm/stat.h
deleted file mode 100644
index 2e27665..0000000
--- a/arch/blackfin/include/asm/stat.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
- */
-
-#ifndef _BFIN_STAT_H
-#define _BFIN_STAT_H
-
-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[4];
-
-#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 __pad2[4];
-
-	long long st_size;
-	unsigned long st_blksize;
-
-	long 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				/* _BFIN_STAT_H */
diff --git a/arch/blackfin/include/asm/swab.h b/arch/blackfin/include/asm/swab.h
deleted file mode 100644
index 89de650..0000000
--- a/arch/blackfin/include/asm/swab.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#ifndef _BLACKFIN_SWAB_H
-#define _BLACKFIN_SWAB_H
-
-#include <linux/types.h>
-#include <asm-generic/swab.h>
-
-#ifdef __GNUC__
-
-static __inline__ __attribute_const__ __u32 __arch_swahb32(__u32 xx)
-{
-	__u32 tmp;
-	__asm__("%1 = %0 >> 8 (V);\n\t"
-		"%0 = %0 << 8 (V);\n\t"
-		"%0 = %0 | %1;\n\t"
-		: "+d"(xx), "=&d"(tmp));
-	return xx;
-}
-#define __arch_swahb32 __arch_swahb32
-
-static __inline__ __attribute_const__ __u32 __arch_swahw32(__u32 xx)
-{
-	__u32 rv;
-	__asm__("%0 = PACK(%1.L, %1.H);\n\t": "=d"(rv): "d"(xx));
-	return rv;
-}
-#define __arch_swahw32 __arch_swahw32
-
-static __inline__ __attribute_const__ __u32 __arch_swab32(__u32 xx)
-{
-	return __arch_swahb32(__arch_swahw32(xx));
-}
-#define __arch_swab32 __arch_swab32
-
-static __inline__ __attribute_const__ __u16 __arch_swab16(__u16 xx)
-{
-	__u32 xw = xx;
-	__asm__("%0 <<= 8;\n	%0.L = %0.L + %0.H (NS);\n": "+d"(xw));
-	return (__u16)xw;
-}
-#define __arch_swab16 __arch_swab16
-
-#endif /* __GNUC__ */
-
-#endif				/* _BLACKFIN_SWAB_H */
diff --git a/arch/blackfin/include/asm/uaccess.h b/arch/blackfin/include/asm/uaccess.h
index 5cc1115..461bb54 100644
--- a/arch/blackfin/include/asm/uaccess.h
+++ b/arch/blackfin/include/asm/uaccess.h
@@ -34,23 +34,6 @@ static inline void set_fs(mm_segment_t fs)
 
 #define access_ok(type, addr, size) _access_ok((unsigned long)(addr), (size))
 
-static inline int is_in_rom(unsigned long addr)
-{
-	/*
-	 * What we are really trying to do is determine if addr is
-	 * in an allocated kernel memory region. If not then assume
-	 * we cannot free it or otherwise de-allocate it. Ideally
-	 * we could restrict this to really being in a ROM or flash,
-	 * but that would need to be done on a board by board basis,
-	 * not globally.
-	 */
-	if ((addr < _ramstart) || (addr >= _ramend))
-		return (1);
-
-	/* Default case, not in ROM */
-	return (0);
-}
-
 /*
  * The fs value determines whether argument validity checking should be
  * performed or not.  If get_fs() == USER_DS, checking is performed, with
@@ -89,7 +72,7 @@ struct exception_table_entry {
 	({							\
 		int _err = 0;					\
 		typeof(*(p)) _x = (x);				\
-		typeof(*(p)) *_p = (p);				\
+		typeof(*(p)) __user *_p = (p);				\
 		if (!access_ok(VERIFY_WRITE, _p, sizeof(*(_p)))) {\
 			_err = -EFAULT;				\
 		}						\
@@ -108,8 +91,8 @@ struct exception_table_entry {
 			long _xl, _xh;				\
 			_xl = ((long *)&_x)[0];			\
 			_xh = ((long *)&_x)[1];			\
-			__put_user_asm(_xl, ((long *)_p)+0, );	\
-			__put_user_asm(_xh, ((long *)_p)+1, );	\
+			__put_user_asm(_xl, ((long __user *)_p)+0, );	\
+			__put_user_asm(_xh, ((long __user *)_p)+1, );	\
 		} break;					\
 		default:					\
 			_err = __put_user_bad();		\
@@ -136,7 +119,7 @@ static inline int bad_user_access_length(void)
  * aliasing issues.
  */
 
-#define __ptr(x) ((unsigned long *)(x))
+#define __ptr(x) ((unsigned long __force *)(x))
 
 #define __put_user_asm(x,p,bhw)				\
 	__asm__ (#bhw"[%1] = %0;\n\t"			\
@@ -216,12 +199,12 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
  */
 
 static inline long __must_check
-strncpy_from_user(char *dst, const char *src, long count)
+strncpy_from_user(char *dst, const char __user *src, long count)
 {
 	char *tmp;
 	if (!access_ok(VERIFY_READ, src, 1))
 		return -EFAULT;
-	strncpy(dst, src, count);
+	strncpy(dst, (const char __force *)src, count);
 	for (tmp = dst; *tmp && count > 0; tmp++, count--) ;
 	return (tmp - dst);
 }
@@ -237,18 +220,18 @@ strncpy_from_user(char *dst, const char *src, long count)
  * On exception, returns 0.
  * If the string is too long, returns a value greater than n.
  */
-static inline long __must_check strnlen_user(const char *src, long n)
+static inline long __must_check strnlen_user(const char __user *src, long n)
 {
 	if (!access_ok(VERIFY_READ, src, 1))
 		return 0;
-	return strnlen(src, n) + 1;
+	return strnlen((const char __force *)src, n) + 1;
 }
 
-static inline long __must_check strlen_user(const char *src)
+static inline long __must_check strlen_user(const char __user *src)
 {
 	if (!access_ok(VERIFY_READ, src, 1))
 		return 0;
-	return strlen(src) + 1;
+	return strlen((const char __force *)src) + 1;
 }
 
 /*
@@ -256,11 +239,11 @@ static inline long __must_check strlen_user(const char *src)
  */
 
 static inline unsigned long __must_check
-__clear_user(void *to, unsigned long n)
+__clear_user(void __user *to, unsigned long n)
 {
 	if (!access_ok(VERIFY_WRITE, to, n))
 		return n;
-	memset(to, 0, n);
+	memset((void __force *)to, 0, n);
 	return 0;
 }
 
diff --git a/arch/blackfin/include/asm/unistd.h b/arch/blackfin/include/asm/unistd.h
index 5b2a074..821434f 100644
--- a/arch/blackfin/include/asm/unistd.h
+++ b/arch/blackfin/include/asm/unistd.h
@@ -3,437 +3,11 @@
  *
  * Licensed under the GPL-2 or later.
  */
-
 #ifndef __ASM_BFIN_UNISTD_H
 #define __ASM_BFIN_UNISTD_H
-/*
- * This file contains the system call numbers.
- */
-#define __NR_restart_syscall	  0
-#define __NR_exit		  1
-				/* 2 __NR_fork not supported on nommu */
-#define __NR_read		  3
-#define __NR_write		  4
-#define __NR_open		  5
-#define __NR_close		  6
-				/* 7 __NR_waitpid obsolete */
-#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_chown		 16
-				/* 17 __NR_break obsolete */
-				/* 18 __NR_oldstat obsolete */
-#define __NR_lseek		 19
-#define __NR_getpid		 20
-#define __NR_mount		 21
-				/* 22 __NR_umount obsolete */
-#define __NR_setuid		 23
-#define __NR_getuid		 24
-#define __NR_stime		 25
-#define __NR_ptrace		 26
-#define __NR_alarm		 27
-				/* 28 __NR_oldfstat obsolete */
-#define __NR_pause		 29
-				/* 30 __NR_utime obsolete */
-				/* 31 __NR_stty obsolete */
-				/* 32 __NR_gtty obsolete */
-#define __NR_access		 33
-#define __NR_nice		 34
-				/* 35 __NR_ftime obsolete */
-#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
-				/* 44 __NR_prof obsolete */
-#define __NR_brk		 45
-#define __NR_setgid		 46
-#define __NR_getgid		 47
-				/* 48 __NR_signal obsolete */
-#define __NR_geteuid		 49
-#define __NR_getegid		 50
-#define __NR_acct		 51
-#define __NR_umount2		 52
-				/* 53 __NR_lock obsolete */
-#define __NR_ioctl		 54
-#define __NR_fcntl		 55
-				/* 56 __NR_mpx obsolete */
-#define __NR_setpgid		 57
-				/* 58 __NR_ulimit obsolete */
-				/* 59 __NR_oldolduname obsolete */
-#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
-				/* 67 __NR_sigaction obsolete */
-#define __NR_sgetmask		 68
-#define __NR_ssetmask		 69
-#define __NR_setreuid		 70
-#define __NR_setregid		 71
-				/* 72 __NR_sigsuspend obsolete */
-				/* 73 __NR_sigpending obsolete */
-#define __NR_sethostname	 74
-#define __NR_setrlimit		 75
-				/* 76 __NR_old_getrlimit obsolete */
-#define __NR_getrusage		 77
-#define __NR_gettimeofday	 78
-#define __NR_settimeofday	 79
-#define __NR_getgroups		 80
-#define __NR_setgroups		 81
-				/* 82 __NR_select obsolete */
-#define __NR_symlink		 83
-				/* 84 __NR_oldlstat obsolete */
-#define __NR_readlink		 85
-				/* 86 __NR_uselib obsolete */
-				/* 87 __NR_swapon obsolete */
-#define __NR_reboot		 88
-				/* 89 __NR_readdir obsolete */
-				/* 90 __NR_mmap obsolete */
-#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
-				/* 98 __NR_profil obsolete */
-#define __NR_statfs		 99
-#define __NR_fstatfs		100
-				/* 101 __NR_ioperm */
-				/* 102 __NR_socketcall obsolete */
-#define __NR_syslog		103
-#define __NR_setitimer		104
-#define __NR_getitimer		105
-#define __NR_stat		106
-#define __NR_lstat		107
-#define __NR_fstat		108
-				/* 109 __NR_olduname obsolete */
-				/* 110 __NR_iopl obsolete */
-#define __NR_vhangup		111
-				/* 112 __NR_idle obsolete */
-				/* 113 __NR_vm86old */
-#define __NR_wait4		114
-				/* 115 __NR_swapoff obsolete */
-#define __NR_sysinfo		116
-				/* 117 __NR_ipc oboslete */
-#define __NR_fsync		118
-				/* 119 __NR_sigreturn obsolete */
-#define __NR_clone		120
-#define __NR_setdomainname	121
-#define __NR_uname		122
-				/* 123 __NR_modify_ldt obsolete */
-#define __NR_adjtimex		124
-#define __NR_mprotect		125
-				/* 126 __NR_sigprocmask obsolete */
-				/* 127 __NR_create_module obsolete */
-#define __NR_init_module	128
-#define __NR_delete_module	129
-				/* 130 __NR_get_kernel_syms obsolete */
-#define __NR_quotactl		131
-#define __NR_getpgid		132
-#define __NR_fchdir		133
-#define __NR_bdflush		134
-				/* 135 was sysfs */
-#define __NR_personality	136
-				/* 137 __NR_afs_syscall */
-#define __NR_setfsuid		138
-#define __NR_setfsgid		139
-#define __NR__llseek		140
-#define __NR_getdents		141
-				/* 142 __NR__newselect obsolete */
-#define __NR_flock		143
-				/* 144 __NR_msync obsolete */
-#define __NR_readv		145
-#define __NR_writev		146
-#define __NR_getsid		147
-#define __NR_fdatasync		148
-#define __NR__sysctl		149
-				/* 150 __NR_mlock */
-				/* 151 __NR_munlock */
-				/* 152 __NR_mlockall */
-				/* 153 __NR_munlockall */
-#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
-				/* 166 __NR_vm86 */
-				/* 167 __NR_query_module */
-				/* 168 __NR_poll */
-#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_pread		180
-#define __NR_pwrite		181
-#define __NR_lchown		182
-#define __NR_getcwd		183
-#define __NR_capget		184
-#define __NR_capset		185
-#define __NR_sigaltstack	186
-#define __NR_sendfile		187
-				/* 188 __NR_getpmsg */
-				/* 189 __NR_putpmsg */
-#define __NR_vfork		190
-#define __NR_getrlimit		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_chown32		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_lchown32		212
-#define __NR_setuid32		213
-#define __NR_setgid32		214
-#define __NR_setfsuid32		215
-#define __NR_setfsgid32		216
-#define __NR_pivot_root		217
-				/* 218 __NR_mincore */
-				/* 219 __NR_madvise */
-#define __NR_getdents64		220
-#define __NR_fcntl64		221
-				/* 222 reserved for TUX */
-				/* 223 reserved for TUX */
-#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
-				/* 243 __NR_set_thread_area */
-				/* 244 __NR_get_thread_area */
-#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
-				/* 250 __NR_alloc_hugepages */
-				/* 251 __NR_free_hugepages */
-#define __NR_exit_group		252
-#define __NR_lookup_dcookie     253
-#define __NR_bfin_spinlock      254
-
-#define __NR_epoll_create	255
-#define __NR_epoll_ctl		256
-#define __NR_epoll_wait		257
-				/* 258 __NR_remap_file_pages */
-#define __NR_set_tid_address	259
-#define __NR_timer_create	260
-#define __NR_timer_settime	261
-#define __NR_timer_gettime	262
-#define __NR_timer_getoverrun	263
-#define __NR_timer_delete	264
-#define __NR_clock_settime	265
-#define __NR_clock_gettime	266
-#define __NR_clock_getres	267
-#define __NR_clock_nanosleep	268
-#define __NR_statfs64		269
-#define __NR_fstatfs64		270
-#define __NR_tgkill		271
-#define __NR_utimes		272
-#define __NR_fadvise64_64	273
-				/* 274 __NR_vserver */
-				/* 275 __NR_mbind */
-				/* 276 __NR_get_mempolicy */
-				/* 277 __NR_set_mempolicy */
-#define __NR_mq_open 		278
-#define __NR_mq_unlink		279
-#define __NR_mq_timedsend	280
-#define __NR_mq_timedreceive	281
-#define __NR_mq_notify		282
-#define __NR_mq_getsetattr	283
-#define __NR_kexec_load		284
-#define __NR_waitid		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
-				/* 294 __NR_migrate_pages */
-#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
-
-/* Blackfin private syscalls */
-#define __NR_sram_alloc		311
-#define __NR_sram_free		312
-#define __NR_dma_memcpy		313
-
-/* socket syscalls */
-#define __NR_accept		314
-#define __NR_bind		315
-#define __NR_connect		316
-#define __NR_getpeername	317
-#define __NR_getsockname	318
-#define __NR_getsockopt		319
-#define __NR_listen		320
-#define __NR_recv		321
-#define __NR_recvfrom		322
-#define __NR_recvmsg		323
-#define __NR_send		324
-#define __NR_sendmsg		325
-#define __NR_sendto		326
-#define __NR_setsockopt		327
-#define __NR_shutdown		328
-#define __NR_socket		329
-#define __NR_socketpair		330
-
-/* sysv ipc syscalls */
-#define __NR_semctl		331
-#define __NR_semget		332
-#define __NR_semop		333
-#define __NR_msgctl		334
-#define __NR_msgget		335
-#define __NR_msgrcv		336
-#define __NR_msgsnd		337
-#define __NR_shmat		338
-#define __NR_shmctl		339
-#define __NR_shmdt		340
-#define __NR_shmget		341
 
-#define __NR_splice		342
-#define __NR_sync_file_range	343
-#define __NR_tee		344
-#define __NR_vmsplice		345
+#include <uapi/asm/unistd.h>
 
-#define __NR_epoll_pwait	346
-#define __NR_utimensat		347
-#define __NR_signalfd		348
-#define __NR_timerfd_create	349
-#define __NR_eventfd		350
-#define __NR_pread64		351
-#define __NR_pwrite64		352
-#define __NR_fadvise64		353
-#define __NR_set_robust_list	354
-#define __NR_get_robust_list	355
-#define __NR_fallocate		356
-#define __NR_semtimedop		357
-#define __NR_timerfd_settime	358
-#define __NR_timerfd_gettime	359
-#define __NR_signalfd4		360
-#define __NR_eventfd2		361
-#define __NR_epoll_create1	362
-#define __NR_dup3		363
-#define __NR_pipe2		364
-#define __NR_inotify_init1	365
-#define __NR_preadv		366
-#define __NR_pwritev		367
-#define __NR_rt_tgsigqueueinfo	368
-#define __NR_perf_event_open	369
-#define __NR_recvmmsg		370
-#define __NR_fanotify_init	371
-#define __NR_fanotify_mark	372
-#define __NR_prlimit64		373
-#define __NR_cacheflush		374
-#define __NR_name_to_handle_at	375
-#define __NR_open_by_handle_at	376
-#define __NR_clock_adjtime	377
-#define __NR_syncfs		378
-#define __NR_setns		379
-#define __NR_sendmmsg		380
-#define __NR_process_vm_readv	381
-#define __NR_process_vm_writev	382
-
-#define __NR_syscall		383
-#define NR_syscalls		__NR_syscall
-
-/* Old optional stuff no one actually uses */
-#define __IGNORE_sysfs
-#define __IGNORE_uselib
-
-/* Implement the newer interfaces */
-#define __IGNORE_mmap
-#define __IGNORE_poll
-#define __IGNORE_select
-#define __IGNORE_utime
-
-/* Not relevant on no-mmu */
-#define __IGNORE_swapon
-#define __IGNORE_swapoff
-#define __IGNORE_msync
-#define __IGNORE_mlock
-#define __IGNORE_munlock
-#define __IGNORE_mlockall
-#define __IGNORE_munlockall
-#define __IGNORE_mincore
-#define __IGNORE_madvise
-#define __IGNORE_remap_file_pages
-#define __IGNORE_mbind
-#define __IGNORE_get_mempolicy
-#define __IGNORE_set_mempolicy
-#define __IGNORE_migrate_pages
-#define __IGNORE_move_pages
-#define __IGNORE_getcpu
-
-#ifdef __KERNEL__
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
@@ -446,6 +20,7 @@
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
 
 /*
  * "Conditional" syscalls
@@ -455,6 +30,4 @@
  */
 #define cond_syscall(x) asm(".weak\t_" #x "\n\t.set\t_" #x ",_sys_ni_syscall");
 
-#endif	/* __KERNEL__ */
-
 #endif				/* __ASM_BFIN_UNISTD_H */
diff --git a/arch/blackfin/include/uapi/asm/Kbuild b/arch/blackfin/include/uapi/asm/Kbuild
index baebb3d..0bd28f7 100644
--- a/arch/blackfin/include/uapi/asm/Kbuild
+++ b/arch/blackfin/include/uapi/asm/Kbuild
@@ -1,3 +1,19 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += bfin_sport.h
+header-y += byteorder.h
+header-y += cachectl.h
+header-y += fcntl.h
+header-y += fixed_code.h
+header-y += ioctls.h
+header-y += kvm_para.h
+header-y += poll.h
+header-y += posix_types.h
+header-y += ptrace.h
+header-y += sigcontext.h
+header-y += siginfo.h
+header-y += signal.h
+header-y += stat.h
+header-y += swab.h
+header-y += unistd.h
diff --git a/arch/blackfin/include/uapi/asm/bfin_sport.h b/arch/blackfin/include/uapi/asm/bfin_sport.h
new file mode 100644
index 0000000..c086de8
--- /dev/null
+++ b/arch/blackfin/include/uapi/asm/bfin_sport.h
@@ -0,0 +1,136 @@
+/*
+ * bfin_sport.h - interface to Blackfin SPORTs
+ *
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _UAPI__BFIN_SPORT_H__
+#define _UAPI__BFIN_SPORT_H__
+
+/* Sport mode: it can be set to TDM, i2s or others */
+#define NORM_MODE	0x0
+#define TDM_MODE	0x1
+#define I2S_MODE	0x2
+#define NDSO_MODE	0x3
+
+/* Data format, normal, a-law or u-law */
+#define NORM_FORMAT	0x0
+#define ALAW_FORMAT	0x2
+#define ULAW_FORMAT	0x3
+
+/* Function driver which use sport must initialize the structure */
+struct sport_config {
+	/* TDM (multichannels), I2S or other mode */
+	unsigned int mode:3;
+	unsigned int polled;	/* use poll instead of irq when set */
+
+	/* if TDM mode is selected, channels must be set */
+	int channels;	/* Must be in 8 units */
+	unsigned int frame_delay:4;	/* Delay between frame sync pulse and first bit */
+
+	/* I2S mode */
+	unsigned int right_first:1;	/* Right stereo channel first */
+
+	/* In mormal mode, the following item need to be set */
+	unsigned int lsb_first:1;	/* order of transmit or receive data */
+	unsigned int fsync:1;	/* Frame sync required */
+	unsigned int data_indep:1;	/* data independent frame sync generated */
+	unsigned int act_low:1;	/* Active low TFS */
+	unsigned int late_fsync:1;	/* Late frame sync */
+	unsigned int tckfe:1;
+	unsigned int sec_en:1;	/* Secondary side enabled */
+
+	/* Choose clock source */
+	unsigned int int_clk:1;	/* Internal or external clock */
+
+	/* If external clock is used, the following fields are ignored */
+	int serial_clk;
+	int fsync_clk;
+
+	unsigned int data_format:2;	/* Normal, u-law or a-law */
+
+	int word_len;		/* How length of the word in bits, 3-32 bits */
+	int dma_enabled;
+};
+
+/* Userspace interface */
+#define SPORT_IOC_MAGIC		'P'
+#define SPORT_IOC_CONFIG	_IOWR('P', 0x01, struct sport_config)
+#define SPORT_IOC_GET_SYSTEMCLOCK         _IOR('P', 0x02, unsigned long)
+#define SPORT_IOC_SET_BAUDRATE            _IOW('P', 0x03, unsigned long)
+
+
+/* SPORT_TCR1 Masks */
+#define TSPEN		0x0001	/* TX enable */
+#define ITCLK		0x0002	/* Internal TX Clock Select */
+#define TDTYPE		0x000C	/* TX Data Formatting Select */
+#define DTYPE_NORM	0x0000	/* Data Format Normal */
+#define DTYPE_ULAW	0x0008	/* Compand Using u-Law */
+#define DTYPE_ALAW	0x000C	/* Compand Using A-Law */
+#define TLSBIT		0x0010	/* TX Bit Order */
+#define ITFS		0x0200	/* Internal TX Frame Sync Select */
+#define TFSR		0x0400	/* TX Frame Sync Required Select */
+#define DITFS		0x0800	/* Data Independent TX Frame Sync Select */
+#define LTFS		0x1000	/* Low TX Frame Sync Select */
+#define LATFS		0x2000	/* Late TX Frame Sync Select */
+#define TCKFE		0x4000	/* TX Clock Falling Edge Select */
+
+/* SPORT_TCR2 Masks */
+#define SLEN		0x001F	/* SPORT TX Word Length (2 - 31) */
+#define DP_SLEN(x)	BFIN_DEPOSIT(SLEN, x)
+#define EX_SLEN(x)	BFIN_EXTRACT(SLEN, x)
+#define TXSE		0x0100	/* TX Secondary Enable */
+#define TSFSE		0x0200	/* TX Stereo Frame Sync Enable */
+#define TRFST		0x0400	/* TX Right-First Data Order */
+
+/* SPORT_RCR1 Masks */
+#define RSPEN		0x0001	/* RX enable */
+#define IRCLK		0x0002	/* Internal RX Clock Select */
+#define RDTYPE		0x000C	/* RX Data Formatting Select */
+/* DTYPE_* defined above */
+#define RLSBIT		0x0010	/* RX Bit Order */
+#define IRFS		0x0200	/* Internal RX Frame Sync Select */
+#define RFSR		0x0400	/* RX Frame Sync Required Select */
+#define LRFS		0x1000	/* Low RX Frame Sync Select */
+#define LARFS		0x2000	/* Late RX Frame Sync Select */
+#define RCKFE		0x4000	/* RX Clock Falling Edge Select */
+
+/* SPORT_RCR2 Masks */
+/* SLEN defined above */
+#define RXSE		0x0100	/* RX Secondary Enable */
+#define RSFSE		0x0200	/* RX Stereo Frame Sync Enable */
+#define RRFST		0x0400	/* Right-First Data Order */
+
+/* SPORT_STAT Masks */
+#define RXNE		0x0001	/* RX FIFO Not Empty Status */
+#define RUVF		0x0002	/* RX Underflow Status */
+#define ROVF		0x0004	/* RX Overflow Status */
+#define TXF		0x0008	/* TX FIFO Full Status */
+#define TUVF		0x0010	/* TX Underflow Status */
+#define TOVF		0x0020	/* TX Overflow Status */
+#define TXHRE		0x0040	/* TX Hold Register Empty */
+
+/* SPORT_MCMC1 Masks */
+#define SP_WOFF		0x03FF	/* Multichannel Window Offset Field */
+#define DP_SP_WOFF(x)	BFIN_DEPOSIT(SP_WOFF, x)
+#define EX_SP_WOFF(x)	BFIN_EXTRACT(SP_WOFF, x)
+#define SP_WSIZE	0xF000	/* Multichannel Window Size Field */
+#define DP_SP_WSIZE(x)	BFIN_DEPOSIT(SP_WSIZE, x)
+#define EX_SP_WSIZE(x)	BFIN_EXTRACT(SP_WSIZE, x)
+
+/* SPORT_MCMC2 Masks */
+#define MCCRM		0x0003	/* Multichannel Clock Recovery Mode */
+#define REC_BYPASS	0x0000	/* Bypass Mode (No Clock Recovery) */
+#define REC_2FROM4	0x0002	/* Recover 2 MHz Clock from 4 MHz Clock */
+#define REC_8FROM16	0x0003	/* Recover 8 MHz Clock from 16 MHz Clock */
+#define MCDTXPE		0x0004	/* Multichannel DMA Transmit Packing */
+#define MCDRXPE		0x0008	/* Multichannel DMA Receive Packing */
+#define MCMEN		0x0010	/* Multichannel Frame Mode Enable */
+#define FSDR		0x0080	/* Multichannel Frame Sync to Data Relationship */
+#define MFD		0xF000	/* Multichannel Frame Delay */
+#define DP_MFD(x)	BFIN_DEPOSIT(MFD, x)
+#define EX_MFD(x)	BFIN_EXTRACT(MFD, x)
+
+#endif /* _UAPI__BFIN_SPORT_H__ */
diff --git a/arch/blackfin/include/uapi/asm/byteorder.h b/arch/blackfin/include/uapi/asm/byteorder.h
new file mode 100644
index 0000000..9558416
--- /dev/null
+++ b/arch/blackfin/include/uapi/asm/byteorder.h
@@ -0,0 +1 @@
+#include <linux/byteorder/little_endian.h>
diff --git a/arch/blackfin/include/uapi/asm/cachectl.h b/arch/blackfin/include/uapi/asm/cachectl.h
new file mode 100644
index 0000000..03255df
--- /dev/null
+++ b/arch/blackfin/include/uapi/asm/cachectl.h
@@ -0,0 +1,20 @@
+/*
+ * based on the mips/cachectl.h
+ *
+ * Copyright 2010 Analog Devices Inc.
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef	_ASM_CACHECTL
+#define	_ASM_CACHECTL
+
+/*
+ * Options for cacheflush system call
+ */
+#define	ICACHE	(1<<0)		/* flush instruction cache        */
+#define	DCACHE	(1<<1)		/* writeback and flush data cache */
+#define	BCACHE	(ICACHE|DCACHE)	/* flush both caches              */
+
+#endif	/* _ASM_CACHECTL */
diff --git a/arch/blackfin/include/uapi/asm/fcntl.h b/arch/blackfin/include/uapi/asm/fcntl.h
new file mode 100644
index 0000000..251c911
--- /dev/null
+++ b/arch/blackfin/include/uapi/asm/fcntl.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _BFIN_FCNTL_H
+#define _BFIN_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
diff --git a/arch/blackfin/include/uapi/asm/fixed_code.h b/arch/blackfin/include/uapi/asm/fixed_code.h
new file mode 100644
index 0000000..3bef1dc
--- /dev/null
+++ b/arch/blackfin/include/uapi/asm/fixed_code.h
@@ -0,0 +1,38 @@
+/*
+ * This file defines the fixed addresses where userspace programs
+ * can find atomic code sequences.
+ *
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _UAPI__BFIN_ASM_FIXED_CODE_H__
+#define _UAPI__BFIN_ASM_FIXED_CODE_H__
+
+
+#ifndef CONFIG_PHY_RAM_BASE_ADDRESS
+#define CONFIG_PHY_RAM_BASE_ADDRESS	0x0
+#endif
+
+#define FIXED_CODE_START	(CONFIG_PHY_RAM_BASE_ADDRESS + 0x400)
+
+#define SIGRETURN_STUB		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x400)
+
+#define ATOMIC_SEQS_START	(CONFIG_PHY_RAM_BASE_ADDRESS + 0x410)
+
+#define ATOMIC_XCHG32		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x410)
+#define ATOMIC_CAS32		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x420)
+#define ATOMIC_ADD32		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x430)
+#define ATOMIC_SUB32		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x440)
+#define ATOMIC_IOR32		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x450)
+#define ATOMIC_AND32		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x460)
+#define ATOMIC_XOR32		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x470)
+
+#define ATOMIC_SEQS_END		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x480)
+
+#define SAFE_USER_INSTRUCTION   (CONFIG_PHY_RAM_BASE_ADDRESS + 0x480)
+
+#define FIXED_CODE_END		(CONFIG_PHY_RAM_BASE_ADDRESS + 0x490)
+
+#endif /* _UAPI__BFIN_ASM_FIXED_CODE_H__ */
diff --git a/arch/blackfin/include/uapi/asm/ioctls.h b/arch/blackfin/include/uapi/asm/ioctls.h
new file mode 100644
index 0000000..eca8d75
--- /dev/null
+++ b/arch/blackfin/include/uapi/asm/ioctls.h
@@ -0,0 +1,7 @@
+#ifndef __ARCH_BFIN_IOCTLS_H__
+#define __ARCH_BFIN_IOCTLS_H__
+
+#define FIOQSIZE	0x545E
+#include <asm-generic/ioctls.h>
+
+#endif
diff --git a/arch/blackfin/include/uapi/asm/poll.h b/arch/blackfin/include/uapi/asm/poll.h
new file mode 100644
index 0000000..072d896
--- /dev/null
+++ b/arch/blackfin/include/uapi/asm/poll.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ *
+ */
+
+#ifndef __BFIN_POLL_H
+#define __BFIN_POLL_H
+
+#define POLLWRNORM	4 /* POLLOUT */
+#define POLLWRBAND	256
+
+#include <asm-generic/poll.h>
+
+#endif
diff --git a/arch/blackfin/include/uapi/asm/posix_types.h b/arch/blackfin/include/uapi/asm/posix_types.h
new file mode 100644
index 0000000..1bd3436
--- /dev/null
+++ b/arch/blackfin/include/uapi/asm/posix_types.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __ARCH_BFIN_POSIX_TYPES_H
+#define __ARCH_BFIN_POSIX_TYPES_H
+
+typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
+typedef unsigned int __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
+typedef unsigned long __kernel_size_t;
+typedef long __kernel_ssize_t;
+typedef int __kernel_ptrdiff_t;
+#define __kernel_size_t __kernel_size_t
+
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+#define __kernel_old_uid_t __kernel_old_uid_t
+
+typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
+
+#include <asm-generic/posix_types.h>
+
+#endif
diff --git a/arch/blackfin/include/uapi/asm/ptrace.h b/arch/blackfin/include/uapi/asm/ptrace.h
new file mode 100644
index 0000000..fd48bd0
--- /dev/null
+++ b/arch/blackfin/include/uapi/asm/ptrace.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _UAPI_BFIN_PTRACE_H
+#define _UAPI_BFIN_PTRACE_H
+
+/*
+ * GCC defines register number like this:
+ * -----------------------------
+ *       0 - 7 are data registers R0-R7
+ *       8 - 15 are address registers P0-P7
+ *      16 - 31 dsp registers I/B/L0 -- I/B/L3 & M0--M3
+ *      32 - 33 A registers A0 & A1
+ *      34 -    status register
+ * -----------------------------
+ *
+ * We follows above, except:
+ *      32-33 --- Low 32-bit of A0&1
+ *      34-35 --- High 8-bit of A0&1
+ */
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+
+/* this struct defines the way the registers are stored on the
+   stack during a system call. */
+
+struct pt_regs {
+	long orig_pc;
+	long ipend;
+	long seqstat;
+	long rete;
+	long retn;
+	long retx;
+	long pc;		/* PC == RETI */
+	long rets;
+	long reserved;		/* Used as scratch during system calls */
+	long astat;
+	long lb1;
+	long lb0;
+	long lt1;
+	long lt0;
+	long lc1;
+	long lc0;
+	long a1w;
+	long a1x;
+	long a0w;
+	long a0x;
+	long b3;
+	long b2;
+	long b1;
+	long b0;
+	long l3;
+	long l2;
+	long l1;
+	long l0;
+	long m3;
+	long m2;
+	long m1;
+	long m0;
+	long i3;
+	long i2;
+	long i1;
+	long i0;
+	long usp;
+	long fp;
+	long p5;
+	long p4;
+	long p3;
+	long p2;
+	long p1;
+	long p0;
+	long r7;
+	long r6;
+	long r5;
+	long r4;
+	long r3;
+	long r2;
+	long r1;
+	long r0;
+	long orig_r0;
+	long orig_p0;
+	long syscfg;
+};
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13	/* ptrace signal  */
+
+#define PTRACE_GETFDPIC           31	/* get the ELF fdpic loadmap address */
+#define PTRACE_GETFDPIC_EXEC       0	/* [addr] request the executable loadmap */
+#define PTRACE_GETFDPIC_INTERP     1	/* [addr] request the interpreter loadmap */
+
+#define PS_S  (0x0002)
+
+
+#endif				/* __ASSEMBLY__ */
+
+/*
+ * Offsets used by 'ptrace' system call interface.
+ */
+
+#define PT_R0 204
+#define PT_R1 200
+#define PT_R2 196
+#define PT_R3 192
+#define PT_R4 188
+#define PT_R5 184
+#define PT_R6 180
+#define PT_R7 176
+#define PT_P0 172
+#define PT_P1 168
+#define PT_P2 164
+#define PT_P3 160
+#define PT_P4 156
+#define PT_P5 152
+#define PT_FP 148
+#define PT_USP 144
+#define PT_I0 140
+#define PT_I1 136
+#define PT_I2 132
+#define PT_I3 128
+#define PT_M0 124
+#define PT_M1 120
+#define PT_M2 116
+#define PT_M3 112
+#define PT_L0 108
+#define PT_L1 104
+#define PT_L2 100
+#define PT_L3 96
+#define PT_B0 92
+#define PT_B1 88
+#define PT_B2 84
+#define PT_B3 80
+#define PT_A0X 76
+#define PT_A0W 72
+#define PT_A1X 68
+#define PT_A1W 64
+#define PT_LC0 60
+#define PT_LC1 56
+#define PT_LT0 52
+#define PT_LT1 48
+#define PT_LB0 44
+#define PT_LB1 40
+#define PT_ASTAT 36
+#define PT_RESERVED 32
+#define PT_RETS 28
+#define PT_PC 24
+#define PT_RETX 20
+#define PT_RETN 16
+#define PT_RETE 12
+#define PT_SEQSTAT 8
+#define PT_IPEND 4
+
+#define PT_ORIG_R0 208
+#define PT_ORIG_P0 212
+#define PT_SYSCFG 216
+#define PT_TEXT_ADDR 220
+#define PT_TEXT_END_ADDR 224
+#define PT_DATA_ADDR 228
+#define PT_FDPIC_EXEC 232
+#define PT_FDPIC_INTERP 236
+
+#define PT_LAST_PSEUDO PT_FDPIC_INTERP
+
+#endif /* _UAPI_BFIN_PTRACE_H */
diff --git a/arch/blackfin/include/uapi/asm/sigcontext.h b/arch/blackfin/include/uapi/asm/sigcontext.h
new file mode 100644
index 0000000..906bdc1
--- /dev/null
+++ b/arch/blackfin/include/uapi/asm/sigcontext.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _ASM_BLACKFIN_SIGCONTEXT_H
+#define _ASM_BLACKFIN_SIGCONTEXT_H
+
+/* Add new entries at the end of the structure only.  */
+struct sigcontext {
+	unsigned long sc_r0;
+	unsigned long sc_r1;
+	unsigned long sc_r2;
+	unsigned long sc_r3;
+	unsigned long sc_r4;
+	unsigned long sc_r5;
+	unsigned long sc_r6;
+	unsigned long sc_r7;
+	unsigned long sc_p0;
+	unsigned long sc_p1;
+	unsigned long sc_p2;
+	unsigned long sc_p3;
+	unsigned long sc_p4;
+	unsigned long sc_p5;
+	unsigned long sc_usp;
+	unsigned long sc_a0w;
+	unsigned long sc_a1w;
+	unsigned long sc_a0x;
+	unsigned long sc_a1x;
+	unsigned long sc_astat;
+	unsigned long sc_rets;
+	unsigned long sc_pc;
+	unsigned long sc_retx;
+	unsigned long sc_fp;
+	unsigned long sc_i0;
+	unsigned long sc_i1;
+	unsigned long sc_i2;
+	unsigned long sc_i3;
+	unsigned long sc_m0;
+	unsigned long sc_m1;
+	unsigned long sc_m2;
+	unsigned long sc_m3;
+	unsigned long sc_l0;
+	unsigned long sc_l1;
+	unsigned long sc_l2;
+	unsigned long sc_l3;
+	unsigned long sc_b0;
+	unsigned long sc_b1;
+	unsigned long sc_b2;
+	unsigned long sc_b3;
+	unsigned long sc_lc0;
+	unsigned long sc_lc1;
+	unsigned long sc_lt0;
+	unsigned long sc_lt1;
+	unsigned long sc_lb0;
+	unsigned long sc_lb1;
+	unsigned long sc_seqstat;
+};
+
+#endif
diff --git a/arch/blackfin/include/uapi/asm/siginfo.h b/arch/blackfin/include/uapi/asm/siginfo.h
new file mode 100644
index 0000000..3e81306
--- /dev/null
+++ b/arch/blackfin/include/uapi/asm/siginfo.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _BFIN_SIGINFO_H
+#define _BFIN_SIGINFO_H
+
+#include <linux/types.h>
+#include <asm-generic/siginfo.h>
+
+#define UID16_SIGINFO_COMPAT_NEEDED
+
+#define si_uid16	_sifields._kill._uid
+
+#define ILL_ILLPARAOP	(__SI_FAULT|2)	/* illegal opcode combine ********** */
+#define ILL_ILLEXCPT	(__SI_FAULT|4)	/* unrecoverable exception ********** */
+#define ILL_CPLB_VI	(__SI_FAULT|9)	/* D/I CPLB protect violation ******** */
+#define ILL_CPLB_MISS	(__SI_FAULT|10)	/* D/I CPLB miss ******** */
+#define ILL_CPLB_MULHIT	(__SI_FAULT|11)	/* D/I CPLB multiple hit ******** */
+
+/*
+ * SIGBUS si_codes
+ */
+#define BUS_OPFETCH	(__SI_FAULT|4)	/* error from instruction fetch ******** */
+
+/*
+ * SIGTRAP si_codes
+ */
+#define TRAP_STEP	(__SI_FAULT|1)	/* single-step breakpoint************* */
+#define TRAP_TRACEFLOW	(__SI_FAULT|2)	/* trace buffer overflow ************* */
+#define TRAP_WATCHPT	(__SI_FAULT|3)	/* watchpoint match      ************* */
+#define TRAP_ILLTRAP	(__SI_FAULT|4)	/* illegal trap          ************* */
+
+/*
+ * SIGSEGV si_codes
+ */
+#define SEGV_STACKFLOW	(__SI_FAULT|3)	/* stack overflow */
+
+#endif
diff --git a/arch/blackfin/include/uapi/asm/signal.h b/arch/blackfin/include/uapi/asm/signal.h
new file mode 100644
index 0000000..77a3bf3
--- /dev/null
+++ b/arch/blackfin/include/uapi/asm/signal.h
@@ -0,0 +1,7 @@
+#ifndef _BLACKFIN_SIGNAL_H
+#define _BLACKFIN_SIGNAL_H
+
+#define SA_RESTORER 0x04000000
+#include <asm-generic/signal.h>
+
+#endif
diff --git a/arch/blackfin/include/uapi/asm/stat.h b/arch/blackfin/include/uapi/asm/stat.h
new file mode 100644
index 0000000..2e27665
--- /dev/null
+++ b/arch/blackfin/include/uapi/asm/stat.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef _BFIN_STAT_H
+#define _BFIN_STAT_H
+
+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[4];
+
+#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 __pad2[4];
+
+	long long st_size;
+	unsigned long st_blksize;
+
+	long 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				/* _BFIN_STAT_H */
diff --git a/arch/blackfin/include/uapi/asm/swab.h b/arch/blackfin/include/uapi/asm/swab.h
new file mode 100644
index 0000000..89de650
--- /dev/null
+++ b/arch/blackfin/include/uapi/asm/swab.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _BLACKFIN_SWAB_H
+#define _BLACKFIN_SWAB_H
+
+#include <linux/types.h>
+#include <asm-generic/swab.h>
+
+#ifdef __GNUC__
+
+static __inline__ __attribute_const__ __u32 __arch_swahb32(__u32 xx)
+{
+	__u32 tmp;
+	__asm__("%1 = %0 >> 8 (V);\n\t"
+		"%0 = %0 << 8 (V);\n\t"
+		"%0 = %0 | %1;\n\t"
+		: "+d"(xx), "=&d"(tmp));
+	return xx;
+}
+#define __arch_swahb32 __arch_swahb32
+
+static __inline__ __attribute_const__ __u32 __arch_swahw32(__u32 xx)
+{
+	__u32 rv;
+	__asm__("%0 = PACK(%1.L, %1.H);\n\t": "=d"(rv): "d"(xx));
+	return rv;
+}
+#define __arch_swahw32 __arch_swahw32
+
+static __inline__ __attribute_const__ __u32 __arch_swab32(__u32 xx)
+{
+	return __arch_swahb32(__arch_swahw32(xx));
+}
+#define __arch_swab32 __arch_swab32
+
+static __inline__ __attribute_const__ __u16 __arch_swab16(__u16 xx)
+{
+	__u32 xw = xx;
+	__asm__("%0 <<= 8;\n	%0.L = %0.L + %0.H (NS);\n": "+d"(xw));
+	return (__u16)xw;
+}
+#define __arch_swab16 __arch_swab16
+
+#endif /* __GNUC__ */
+
+#endif				/* _BLACKFIN_SWAB_H */
diff --git a/arch/blackfin/include/uapi/asm/unistd.h b/arch/blackfin/include/uapi/asm/unistd.h
new file mode 100644
index 0000000..a451164
--- /dev/null
+++ b/arch/blackfin/include/uapi/asm/unistd.h
@@ -0,0 +1,437 @@
+/*
+ * Copyright 2004-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _UAPI__ASM_BFIN_UNISTD_H
+#define _UAPI__ASM_BFIN_UNISTD_H
+/*
+ * This file contains the system call numbers.
+ */
+#define __NR_restart_syscall	  0
+#define __NR_exit		  1
+				/* 2 __NR_fork not supported on nommu */
+#define __NR_read		  3
+#define __NR_write		  4
+#define __NR_open		  5
+#define __NR_close		  6
+				/* 7 __NR_waitpid obsolete */
+#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_chown		 16
+				/* 17 __NR_break obsolete */
+				/* 18 __NR_oldstat obsolete */
+#define __NR_lseek		 19
+#define __NR_getpid		 20
+#define __NR_mount		 21
+				/* 22 __NR_umount obsolete */
+#define __NR_setuid		 23
+#define __NR_getuid		 24
+#define __NR_stime		 25
+#define __NR_ptrace		 26
+#define __NR_alarm		 27
+				/* 28 __NR_oldfstat obsolete */
+#define __NR_pause		 29
+				/* 30 __NR_utime obsolete */
+				/* 31 __NR_stty obsolete */
+				/* 32 __NR_gtty obsolete */
+#define __NR_access		 33
+#define __NR_nice		 34
+				/* 35 __NR_ftime obsolete */
+#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
+				/* 44 __NR_prof obsolete */
+#define __NR_brk		 45
+#define __NR_setgid		 46
+#define __NR_getgid		 47
+				/* 48 __NR_signal obsolete */
+#define __NR_geteuid		 49
+#define __NR_getegid		 50
+#define __NR_acct		 51
+#define __NR_umount2		 52
+				/* 53 __NR_lock obsolete */
+#define __NR_ioctl		 54
+#define __NR_fcntl		 55
+				/* 56 __NR_mpx obsolete */
+#define __NR_setpgid		 57
+				/* 58 __NR_ulimit obsolete */
+				/* 59 __NR_oldolduname obsolete */
+#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
+				/* 67 __NR_sigaction obsolete */
+#define __NR_sgetmask		 68
+#define __NR_ssetmask		 69
+#define __NR_setreuid		 70
+#define __NR_setregid		 71
+				/* 72 __NR_sigsuspend obsolete */
+				/* 73 __NR_sigpending obsolete */
+#define __NR_sethostname	 74
+#define __NR_setrlimit		 75
+				/* 76 __NR_old_getrlimit obsolete */
+#define __NR_getrusage		 77
+#define __NR_gettimeofday	 78
+#define __NR_settimeofday	 79
+#define __NR_getgroups		 80
+#define __NR_setgroups		 81
+				/* 82 __NR_select obsolete */
+#define __NR_symlink		 83
+				/* 84 __NR_oldlstat obsolete */
+#define __NR_readlink		 85
+				/* 86 __NR_uselib obsolete */
+				/* 87 __NR_swapon obsolete */
+#define __NR_reboot		 88
+				/* 89 __NR_readdir obsolete */
+				/* 90 __NR_mmap obsolete */
+#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
+				/* 98 __NR_profil obsolete */
+#define __NR_statfs		 99
+#define __NR_fstatfs		100
+				/* 101 __NR_ioperm */
+				/* 102 __NR_socketcall obsolete */
+#define __NR_syslog		103
+#define __NR_setitimer		104
+#define __NR_getitimer		105
+#define __NR_stat		106
+#define __NR_lstat		107
+#define __NR_fstat		108
+				/* 109 __NR_olduname obsolete */
+				/* 110 __NR_iopl obsolete */
+#define __NR_vhangup		111
+				/* 112 __NR_idle obsolete */
+				/* 113 __NR_vm86old */
+#define __NR_wait4		114
+				/* 115 __NR_swapoff obsolete */
+#define __NR_sysinfo		116
+				/* 117 __NR_ipc oboslete */
+#define __NR_fsync		118
+				/* 119 __NR_sigreturn obsolete */
+#define __NR_clone		120
+#define __NR_setdomainname	121
+#define __NR_uname		122
+				/* 123 __NR_modify_ldt obsolete */
+#define __NR_adjtimex		124
+#define __NR_mprotect		125
+				/* 126 __NR_sigprocmask obsolete */
+				/* 127 __NR_create_module obsolete */
+#define __NR_init_module	128
+#define __NR_delete_module	129
+				/* 130 __NR_get_kernel_syms obsolete */
+#define __NR_quotactl		131
+#define __NR_getpgid		132
+#define __NR_fchdir		133
+#define __NR_bdflush		134
+				/* 135 was sysfs */
+#define __NR_personality	136
+				/* 137 __NR_afs_syscall */
+#define __NR_setfsuid		138
+#define __NR_setfsgid		139
+#define __NR__llseek		140
+#define __NR_getdents		141
+				/* 142 __NR__newselect obsolete */
+#define __NR_flock		143
+				/* 144 __NR_msync obsolete */
+#define __NR_readv		145
+#define __NR_writev		146
+#define __NR_getsid		147
+#define __NR_fdatasync		148
+#define __NR__sysctl		149
+				/* 150 __NR_mlock */
+				/* 151 __NR_munlock */
+				/* 152 __NR_mlockall */
+				/* 153 __NR_munlockall */
+#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
+				/* 166 __NR_vm86 */
+				/* 167 __NR_query_module */
+				/* 168 __NR_poll */
+#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_pread		180
+#define __NR_pwrite		181
+#define __NR_lchown		182
+#define __NR_getcwd		183
+#define __NR_capget		184
+#define __NR_capset		185
+#define __NR_sigaltstack	186
+#define __NR_sendfile		187
+				/* 188 __NR_getpmsg */
+				/* 189 __NR_putpmsg */
+#define __NR_vfork		190
+#define __NR_getrlimit		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_chown32		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_lchown32		212
+#define __NR_setuid32		213
+#define __NR_setgid32		214
+#define __NR_setfsuid32		215
+#define __NR_setfsgid32		216
+#define __NR_pivot_root		217
+				/* 218 __NR_mincore */
+				/* 219 __NR_madvise */
+#define __NR_getdents64		220
+#define __NR_fcntl64		221
+				/* 222 reserved for TUX */
+				/* 223 reserved for TUX */
+#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
+				/* 243 __NR_set_thread_area */
+				/* 244 __NR_get_thread_area */
+#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
+				/* 250 __NR_alloc_hugepages */
+				/* 251 __NR_free_hugepages */
+#define __NR_exit_group		252
+#define __NR_lookup_dcookie     253
+#define __NR_bfin_spinlock      254
+
+#define __NR_epoll_create	255
+#define __NR_epoll_ctl		256
+#define __NR_epoll_wait		257
+				/* 258 __NR_remap_file_pages */
+#define __NR_set_tid_address	259
+#define __NR_timer_create	260
+#define __NR_timer_settime	261
+#define __NR_timer_gettime	262
+#define __NR_timer_getoverrun	263
+#define __NR_timer_delete	264
+#define __NR_clock_settime	265
+#define __NR_clock_gettime	266
+#define __NR_clock_getres	267
+#define __NR_clock_nanosleep	268
+#define __NR_statfs64		269
+#define __NR_fstatfs64		270
+#define __NR_tgkill		271
+#define __NR_utimes		272
+#define __NR_fadvise64_64	273
+				/* 274 __NR_vserver */
+				/* 275 __NR_mbind */
+				/* 276 __NR_get_mempolicy */
+				/* 277 __NR_set_mempolicy */
+#define __NR_mq_open 		278
+#define __NR_mq_unlink		279
+#define __NR_mq_timedsend	280
+#define __NR_mq_timedreceive	281
+#define __NR_mq_notify		282
+#define __NR_mq_getsetattr	283
+#define __NR_kexec_load		284
+#define __NR_waitid		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
+				/* 294 __NR_migrate_pages */
+#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
+
+/* Blackfin private syscalls */
+#define __NR_sram_alloc		311
+#define __NR_sram_free		312
+#define __NR_dma_memcpy		313
+
+/* socket syscalls */
+#define __NR_accept		314
+#define __NR_bind		315
+#define __NR_connect		316
+#define __NR_getpeername	317
+#define __NR_getsockname	318
+#define __NR_getsockopt		319
+#define __NR_listen		320
+#define __NR_recv		321
+#define __NR_recvfrom		322
+#define __NR_recvmsg		323
+#define __NR_send		324
+#define __NR_sendmsg		325
+#define __NR_sendto		326
+#define __NR_setsockopt		327
+#define __NR_shutdown		328
+#define __NR_socket		329
+#define __NR_socketpair		330
+
+/* sysv ipc syscalls */
+#define __NR_semctl		331
+#define __NR_semget		332
+#define __NR_semop		333
+#define __NR_msgctl		334
+#define __NR_msgget		335
+#define __NR_msgrcv		336
+#define __NR_msgsnd		337
+#define __NR_shmat		338
+#define __NR_shmctl		339
+#define __NR_shmdt		340
+#define __NR_shmget		341
+
+#define __NR_splice		342
+#define __NR_sync_file_range	343
+#define __NR_tee		344
+#define __NR_vmsplice		345
+
+#define __NR_epoll_pwait	346
+#define __NR_utimensat		347
+#define __NR_signalfd		348
+#define __NR_timerfd_create	349
+#define __NR_eventfd		350
+#define __NR_pread64		351
+#define __NR_pwrite64		352
+#define __NR_fadvise64		353
+#define __NR_set_robust_list	354
+#define __NR_get_robust_list	355
+#define __NR_fallocate		356
+#define __NR_semtimedop		357
+#define __NR_timerfd_settime	358
+#define __NR_timerfd_gettime	359
+#define __NR_signalfd4		360
+#define __NR_eventfd2		361
+#define __NR_epoll_create1	362
+#define __NR_dup3		363
+#define __NR_pipe2		364
+#define __NR_inotify_init1	365
+#define __NR_preadv		366
+#define __NR_pwritev		367
+#define __NR_rt_tgsigqueueinfo	368
+#define __NR_perf_event_open	369
+#define __NR_recvmmsg		370
+#define __NR_fanotify_init	371
+#define __NR_fanotify_mark	372
+#define __NR_prlimit64		373
+#define __NR_cacheflush		374
+#define __NR_name_to_handle_at	375
+#define __NR_open_by_handle_at	376
+#define __NR_clock_adjtime	377
+#define __NR_syncfs		378
+#define __NR_setns		379
+#define __NR_sendmmsg		380
+#define __NR_process_vm_readv	381
+#define __NR_process_vm_writev	382
+
+#define __NR_syscall		383
+#define NR_syscalls		__NR_syscall
+
+/* Old optional stuff no one actually uses */
+#define __IGNORE_sysfs
+#define __IGNORE_uselib
+
+/* Implement the newer interfaces */
+#define __IGNORE_mmap
+#define __IGNORE_poll
+#define __IGNORE_select
+#define __IGNORE_utime
+
+/* Not relevant on no-mmu */
+#define __IGNORE_swapon
+#define __IGNORE_swapoff
+#define __IGNORE_msync
+#define __IGNORE_mlock
+#define __IGNORE_munlock
+#define __IGNORE_mlockall
+#define __IGNORE_munlockall
+#define __IGNORE_mincore
+#define __IGNORE_madvise
+#define __IGNORE_remap_file_pages
+#define __IGNORE_mbind
+#define __IGNORE_get_mempolicy
+#define __IGNORE_set_mempolicy
+#define __IGNORE_migrate_pages
+#define __IGNORE_move_pages
+#define __IGNORE_getcpu
+
+
+#endif /* _UAPI__ASM_BFIN_UNISTD_H */
diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S
index f33792c..78f4f63 100644
--- a/arch/blackfin/kernel/entry.S
+++ b/arch/blackfin/kernel/entry.S
@@ -46,22 +46,16 @@ ENTRY(_ret_from_fork)
 	SP += -12;
 	pseudo_long_call _schedule_tail, p5;
 	SP += 12;
-	r0 = [sp + PT_IPEND];
-	cc = bittst(r0,1);
-	if cc jump .Lin_kernel;
+	p1 = [sp++];
+	r0 = [sp++];
+	cc = p1 == 0;
+	if cc jump .Lfork;
+	sp += -12;
+	call (p1);
+	sp += 12;
+.Lfork:
 	RESTORE_CONTEXT
 	rti;
-.Lin_kernel:
-	bitclr(r0,1);
-	[sp + PT_IPEND] = r0;
-	/* do a 'fake' RTI by jumping to [RETI]
-	 * to avoid clearing supervisor mode in child
-	 */
-	r0 = [sp + PT_PC];
-	[sp + PT_P0] = r0;
-
-	RESTORE_ALL_SYS
-	jump (p0);
 ENDPROC(_ret_from_fork)
 
 ENTRY(_sys_vfork)
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index bb1cc72..c3bf07b 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -102,40 +102,6 @@ void cpu_idle(void)
 }
 
 /*
- * This gets run with P1 containing the
- * function to call, and R1 containing
- * the "args".  Note P0 is clobbered on the way here.
- */
-void kernel_thread_helper(void);
-__asm__(".section .text\n"
-	".align 4\n"
-	"_kernel_thread_helper:\n\t"
-	"\tsp += -12;\n\t"
-	"\tr0 = r1;\n\t" "\tcall (p1);\n\t" "\tcall _do_exit;\n" ".previous");
-
-/*
- * Create a kernel thread.
- */
-pid_t kernel_thread(int (*fn) (void *), void *arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-
-	regs.r1 = (unsigned long)arg;
-	regs.p1 = (unsigned long)fn;
-	regs.pc = (unsigned long)kernel_thread_helper;
-	regs.orig_p0 = -1;
-	/* Set bit 2 to tell ret_from_fork we should be returning to kernel
-	   mode.  */
-	regs.ipend = 0x8002;
-	__asm__ __volatile__("%0 = syscfg;":"=da"(regs.syscfg):);
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL,
-		       NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
-/*
  * Do necessary setup to start up a newly executed thread.
  *
  * pass the data segment into user programs if it exists,
@@ -163,7 +129,7 @@ void flush_thread(void)
 
 asmlinkage int bfin_vfork(struct pt_regs *regs)
 {
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL,
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), 0, NULL,
 		       NULL);
 }
 
@@ -184,47 +150,40 @@ asmlinkage int bfin_clone(struct pt_regs *regs)
 		newsp = rdusp();
 	else
 		newsp -= 12;
-	return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
+	return do_fork(clone_flags, newsp, 0, NULL, NULL);
 }
 
 int
 copy_thread(unsigned long clone_flags,
 	    unsigned long usp, unsigned long topstk,
-	    struct task_struct *p, struct pt_regs *regs)
+	    struct task_struct *p)
 {
 	struct pt_regs *childregs;
+	unsigned long *v;
 
 	childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
-	*childregs = *regs;
-	childregs->r0 = 0;
+	v = ((unsigned long *)childregs) - 2;
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		memset(childregs, 0, sizeof(struct pt_regs));
+		v[0] = usp;
+		v[1] = topstk;
+		childregs->orig_p0 = -1;
+		childregs->ipend = 0x8000;
+		__asm__ __volatile__("%0 = syscfg;":"=da"(childregs->syscfg):);
+		p->thread.usp = 0;
+	} else {
+		*childregs = *current_pt_regs();
+		childregs->r0 = 0;
+		p->thread.usp = usp;
+		v[0] = v[1] = 0;
+	}
 
-	p->thread.usp = usp;
-	p->thread.ksp = (unsigned long)childregs;
+	p->thread.ksp = (unsigned long)v;
 	p->thread.pc = (unsigned long)ret_from_fork;
 
 	return 0;
 }
 
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char __user *name,
-			  const char __user *const __user *argv,
-			  const char __user *const __user *envp)
-{
-	int error;
-	struct filename *filename;
-	struct pt_regs *regs = (struct pt_regs *)((&name) + 6);
-
-	filename = getname(name);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		return error;
-	error = do_execve(filename->name, argv, envp, regs);
-	putname(filename);
-	return error;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
 	unsigned long fp, pc;
diff --git a/arch/blackfin/mach-common/dpmc.c b/arch/blackfin/mach-common/dpmc.c
index f5685a4..978bb40 100644
--- a/arch/blackfin/mach-common/dpmc.c
+++ b/arch/blackfin/mach-common/dpmc.c
@@ -157,24 +157,7 @@ struct platform_driver bfin_dpmc_device_driver = {
 		.name = DRIVER_NAME,
 	}
 };
-
-/**
- *	bfin_dpmc_init - Init driver
- */
-static int __init bfin_dpmc_init(void)
-{
-	return platform_driver_register(&bfin_dpmc_device_driver);
-}
-module_init(bfin_dpmc_init);
-
-/**
- *	bfin_dpmc_exit - break down driver
- */
-static void __exit bfin_dpmc_exit(void)
-{
-	platform_driver_unregister(&bfin_dpmc_device_driver);
-}
-module_exit(bfin_dpmc_exit);
+module_platform_driver(bfin_dpmc_device_driver);
 
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 MODULE_DESCRIPTION("cpu power management driver for Blackfin");
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index 1c3d2c5..4a38c68 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -530,61 +530,6 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
 	jump .Lsyscall_really_exit;
 ENDPROC(_trap)
 
-ENTRY(_kernel_execve)
-	link SIZEOF_PTREGS;
-	p0 = sp;
-	r3 = SIZEOF_PTREGS / 4;
-	r4 = 0(x);
-.Lclear_regs:
-	[p0++] = r4;
-	r3 += -1;
-	cc = r3 == 0;
-	if !cc jump .Lclear_regs (bp);
-
-	p0 = sp;
-	sp += -16;
-	[sp + 12] = p0;
-	pseudo_long_call _do_execve, p5;
-	SP += 16;
-	cc = r0 == 0;
-	if ! cc jump .Lexecve_failed;
-	/* Success.  Copy our temporary pt_regs to the top of the kernel
-	 * stack and do a normal exception return.
-	 */
-	r1 = sp;
-	r0 = (-KERNEL_STACK_SIZE) (x);
-	r1 = r1 & r0;
-	p2 = r1;
-	p3 = [p2];
-	r0 = KERNEL_STACK_SIZE - 4 (z);
-	p1 = r0;
-	p1 = p1 + p2;
-
-	p0 = fp;
-	r4 = [p0--];
-	r3 = SIZEOF_PTREGS / 4;
-.Lcopy_regs:
-	r4 = [p0--];
-	[p1--] = r4;
-	r3 += -1;
-	cc = r3 == 0;
-	if ! cc jump .Lcopy_regs (bp);
-
-	r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z);
-	p1 = r0;
-	p1 = p1 + p2;
-	sp = p1;
-	r0 = syscfg;
-	[SP + PT_SYSCFG] = r0;
-	[p3 + (TASK_THREAD + THREAD_KSP)] = sp;
-
-	RESTORE_CONTEXT;
-	rti;
-.Lexecve_failed:
-	unlink;
-	rts;
-ENDPROC(_kernel_execve)
-
 ENTRY(_system_call)
 	/* Store IPEND */
 	p2.l = lo(IPEND);
diff --git a/arch/blackfin/mm/sram-alloc.c b/arch/blackfin/mm/sram-alloc.c
index 342e378..1f3b3ef 100644
--- a/arch/blackfin/mm/sram-alloc.c
+++ b/arch/blackfin/mm/sram-alloc.c
@@ -191,7 +191,7 @@ static irqreturn_t l2_ecc_err(int irq, void *dev_id)
 {
 	int status;
 
-	printk(KERN_ERR "L2 ecc error happend\n");
+	printk(KERN_ERR "L2 ecc error happened\n");
 	status = bfin_read32(L2CTL0_STAT);
 	if (status & 0x1)
 		printk(KERN_ERR "Core channel error type:0x%x, addr:0x%x\n",
diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig
index aee1b56..66eab37 100644
--- a/arch/c6x/Kconfig
+++ b/arch/c6x/Kconfig
@@ -18,6 +18,7 @@ config C6X
 	select OF_EARLY_FLATTREE
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
 	select MODULES_USE_ELF_RELA
 
 config MMU
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 112a496..eae7b59 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -49,6 +49,7 @@ generic-y += termbits.h
 generic-y += termios.h
 generic-y += tlbflush.h
 generic-y += topology.h
+generic-y += trace_clock.h
 generic-y += types.h
 generic-y += ucontext.h
 generic-y += user.h
diff --git a/arch/c6x/include/asm/dma-mapping.h b/arch/c6x/include/asm/dma-mapping.h
index 03579fd..3c69406 100644
--- a/arch/c6x/include/asm/dma-mapping.h
+++ b/arch/c6x/include/asm/dma-mapping.h
@@ -32,6 +32,7 @@ static inline int dma_set_mask(struct device *dev, u64 dma_mask)
  */
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
+	debug_dma_mapping_error(dev, dma_addr);
 	return dma_addr == ~0;
 }
 
diff --git a/arch/c6x/include/asm/setup.h b/arch/c6x/include/asm/setup.h
new file mode 100644
index 0000000..ecead15
--- /dev/null
+++ b/arch/c6x/include/asm/setup.h
@@ -0,0 +1,33 @@
+/*
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2009, 2010 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.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_C6X_SETUP_H
+#define _ASM_C6X_SETUP_H
+
+#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;
+extern unsigned long ram_end;
+
+extern int c6x_num_cores;
+extern unsigned int c6x_silicon_rev;
+extern unsigned int c6x_devstat;
+extern unsigned char c6x_fuse_mac[6];
+
+extern void machine_init(unsigned long dt_ptr);
+extern void time_init(void);
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASM_C6X_SETUP_H */
diff --git a/arch/c6x/include/asm/syscalls.h b/arch/c6x/include/asm/syscalls.h
index e7b8991..73b49ec 100644
--- a/arch/c6x/include/asm/syscalls.h
+++ b/arch/c6x/include/asm/syscalls.h
@@ -43,8 +43,6 @@ extern int sys_cache_sync(unsigned long s, unsigned long e);
 
 struct pt_regs;
 
-extern asmlinkage long sys_c6x_clone(struct pt_regs *regs);
-
 #include <asm-generic/syscalls.h>
 
 #endif /* __ASM_C6X_SYSCALLS_H */
diff --git a/arch/c6x/include/uapi/asm/Kbuild b/arch/c6x/include/uapi/asm/Kbuild
index c312b42..e9bc2b2 100644
--- a/arch/c6x/include/uapi/asm/Kbuild
+++ b/arch/c6x/include/uapi/asm/Kbuild
@@ -1,6 +1,8 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+generic-y += kvm_para.h
+
 header-y += byteorder.h
 header-y += kvm_para.h
 header-y += ptrace.h
diff --git a/arch/c6x/include/uapi/asm/kvm_para.h b/arch/c6x/include/uapi/asm/kvm_para.h
deleted file mode 100644
index 14fab8f..0000000
--- a/arch/c6x/include/uapi/asm/kvm_para.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
diff --git a/arch/c6x/include/uapi/asm/setup.h b/arch/c6x/include/uapi/asm/setup.h
index a01e318..ad9ac97 100644
--- a/arch/c6x/include/uapi/asm/setup.h
+++ b/arch/c6x/include/uapi/asm/setup.h
@@ -1,33 +1,6 @@
-/*
- *  Port on Texas Instruments TMS320C6x architecture
- *
- *  Copyright (C) 2004, 2009, 2010 2011 Texas Instruments Incorporated
- *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.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_C6X_SETUP_H
-#define _ASM_C6X_SETUP_H
+#ifndef _UAPI_ASM_C6X_SETUP_H
+#define _UAPI_ASM_C6X_SETUP_H
 
 #define COMMAND_LINE_SIZE   1024
 
-#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;
-extern unsigned long ram_end;
-
-extern int c6x_num_cores;
-extern unsigned int c6x_silicon_rev;
-extern unsigned int c6x_devstat;
-extern unsigned char c6x_fuse_mac[6];
-
-extern void machine_init(unsigned long dt_ptr);
-extern void time_init(void);
-
-#endif /* !__ASSEMBLY__ */
-#endif /* _ASM_C6X_SETUP_H */
+#endif /* _UAPI_ASM_C6X_SETUP_H */
diff --git a/arch/c6x/include/uapi/asm/unistd.h b/arch/c6x/include/uapi/asm/unistd.h
index 4ff747d..f3987a8 100644
--- a/arch/c6x/include/uapi/asm/unistd.h
+++ b/arch/c6x/include/uapi/asm/unistd.h
@@ -14,8 +14,8 @@
  *   more details.
  */
 
-#define __ARCH_WANT_KERNEL_EXECVE
 #define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_CLONE
 
 /* Use the standard ABI for syscalls. */
 #include <asm-generic/unistd.h>
diff --git a/arch/c6x/kernel/entry.S b/arch/c6x/kernel/entry.S
index 5449c36..5239057 100644
--- a/arch/c6x/kernel/entry.S
+++ b/arch/c6x/kernel/entry.S
@@ -277,6 +277,8 @@ work_rescheduled:
  [A1]	BNOP	.S1	work_resched,5
 
 work_notifysig:
+	;; enable interrupts for do_notify_resume()
+	UNMASK_INT B2
 	B	.S2	do_notify_resume
 	LDW	.D2T1	*+SP(REGS__END+8),A6 ; syscall flag
 	ADDKPC	.S2	resume_userspace,B3,1
@@ -413,22 +415,11 @@ ENTRY(ret_from_kernel_thread)
 0:
 	B	.S2	B10		   /* call fn */
 	LDW	.D2T1	*+SP(REGS_A1+8),A4 /* get arg */
-	MVKL	.S2	sys_exit,B11
-	MVKH	.S2	sys_exit,B11
-	ADDKPC	.S2	0f,B3,1
-0:
-	BNOP	.S2	B11,5	/* jump to sys_exit */
+	ADDKPC	.S2	ret_from_fork_2,B3,3
 ENDPROC(ret_from_kernel_thread)
 
-ENTRY(ret_from_kernel_execve)
-	GET_THREAD_INFO A12
-	BNOP	.S2	syscall_exit,4
-	ADD	.D2X	A4,-8,SP
-ENDPROC(ret_from_kernel_execve)
-
 	;;
-	;; These are the interrupt handlers, responsible for calling __do_IRQ()
-	;; int6 is used for syscalls (see _system_call entry)
+	;; These are the interrupt handlers, responsible for calling c6x_do_IRQ()
 	;;
 	.macro SAVE_ALL_INT
 	SAVE_ALL IRP,ITSR
@@ -623,18 +614,6 @@ ENDPROC(sys_sigaltstack)
 	;; Special system calls
 	;; return address is in B3
 	;;
-ENTRY(sys_clone)
-	ADD	.D1X	SP,8,A4
-#ifdef CONFIG_C6X_BIG_KERNEL
- ||	MVKL	.S1	sys_c6x_clone,A0
-	MVKH	.S1	sys_c6x_clone,A0
-	BNOP	.S2X	A0,5
-#else
- ||	B	.S2	sys_c6x_clone
-	NOP	5
-#endif
-ENDPROC(sys_clone)
-
 ENTRY(sys_rt_sigreturn)
 	ADD	.D1X	SP,8,A4
 #ifdef CONFIG_C6X_BIG_KERNEL
diff --git a/arch/c6x/kernel/process.c b/arch/c6x/kernel/process.c
index 2770d9a..6434df4 100644
--- a/arch/c6x/kernel/process.c
+++ b/arch/c6x/kernel/process.c
@@ -112,22 +112,6 @@ void exit_thread(void)
 {
 }
 
-SYSCALL_DEFINE1(c6x_clone, struct pt_regs *, regs)
-{
-	unsigned long clone_flags;
-	unsigned long newsp;
-
-	/* syscall puts clone_flags in A4 and usp in B4 */
-	clone_flags = regs->orig_a4;
-	if (regs->b4)
-		newsp = regs->b4;
-	else
-		newsp = regs->sp;
-
-	return do_fork(clone_flags, newsp, regs, 0, (int __user *)regs->a6,
-		       (int __user *)regs->b6);
-}
-
 /*
  * Do necessary setup to start up a newly executed thread.
  */
@@ -155,13 +139,13 @@ void start_thread(struct pt_regs *regs, unsigned int pc, unsigned long usp)
  */
 int copy_thread(unsigned long clone_flags, unsigned long usp,
 		unsigned long ustk_size,
-		struct task_struct *p, struct pt_regs *regs)
+		struct task_struct *p)
 {
 	struct pt_regs *childregs;
 
 	childregs = task_pt_regs(p);
 
-	if (!regs) {
+	if (unlikely(p->flags & PF_KTHREAD)) {
 		/* case of  __kernel_thread: we return to supervisor space */
 		memset(childregs, 0, sizeof(struct pt_regs));
 		childregs->sp = (unsigned long)(childregs + 1);
@@ -170,8 +154,9 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 		childregs->a1 = ustk_size;	/* argument */
 	} else {
 		/* Otherwise use the given stack */
-		*childregs = *regs;
-		childregs->sp = usp;
+		*childregs = *current_pt_regs();
+		if (usp)
+			childregs->sp = usp;
 		p->thread.pc = (unsigned long) ret_from_fork;
 	}
 
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index a672444..0cac6a4 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -49,6 +49,9 @@ config CRIS
 	select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32
 	select GENERIC_CMOS_UPDATE
 	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
+	select CLONE_BACKWARDS2
 
 config HZ
 	int
diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S
index 592fbe9..897bba6 100644
--- a/arch/cris/arch-v10/kernel/entry.S
+++ b/arch/cris/arch-v10/kernel/entry.S
@@ -35,6 +35,7 @@
 	.globl system_call
 	.globl ret_from_intr
 	.globl ret_from_fork
+	.globl ret_from_kernel_thread
 	.globl resume
 	.globl multiple_interrupt
 	.globl hwbreakpoint
@@ -81,7 +82,14 @@ ret_from_fork:
 	jsr schedule_tail
 	ba  ret_from_sys_call
 	nop
-		
+
+ret_from_kernel_thread:
+	jsr schedule_tail
+	move.d	$r2, $r10	; argument is here
+	jsr	$r1		; call the payload
+	moveq	0, $r9		; no syscall restarts, TYVM...
+	ba  ret_from_sys_call
+
 ret_from_intr:
 	;; check for resched if preemptive kernel or if we're going back to user-mode 
 	;; this test matches the user_regs(regs) macro
@@ -586,13 +594,6 @@ _ugdb_handle_breakpoint:
 	ba	do_sigtrap		; SIGTRAP the offending process. 
 	pop	$dccr			; Restore dccr in delay slot.
 
-	.global kernel_execve
-kernel_execve:
-	move.d __NR_execve, $r9
-	break 13
-	ret
-	nop
-
 	.data
 
 hw_bp_trigs:
diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c
index 15ac715..b101875 100644
--- a/arch/cris/arch-v10/kernel/process.c
+++ b/arch/cris/arch-v10/kernel/process.c
@@ -17,6 +17,7 @@
 #include <arch/svinto.h>
 #include <linux/init.h>
 #include <arch/system.h>
+#include <linux/ptrace.h>
 
 #ifdef CONFIG_ETRAX_GPIO
 void etrax_gpio_wake_up_check(void); /* drivers/gpio.c */
@@ -81,31 +82,6 @@ unsigned long thread_saved_pc(struct task_struct *t)
 	return task_pt_regs(t)->irp;
 }
 
-static void kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg)
-{
-  fn(arg);
-  do_exit(-1); /* Should never be called, return bad exit value */
-}
-
-/*
- * Create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-
-        /* Don't use r10 since that is set to 0 in copy_thread */
-	regs.r11 = (unsigned long)fn;
-	regs.r12 = (unsigned long)arg;
-	regs.irp = (unsigned long)kernel_thread_helper;
-	regs.dccr = 1 << I_DCCR_BITNR;
-
-	/* Ok, create the new process.. */
-        return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-
 /* setup the child's kernel stack with a pt_regs and switch_stack on it.
  * it will be un-nested during _resume and _ret_from_sys_call when the
  * new thread is scheduled.
@@ -115,29 +91,34 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
  *
  */
 asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-		unsigned long unused,
-		struct task_struct *p, struct pt_regs *regs)
+		unsigned long arg, struct task_struct *p)
 {
-	struct pt_regs * childregs;
-	struct switch_stack *swstack;
+	struct pt_regs *childregs = task_pt_regs(p);
+	struct switch_stack *swstack = ((struct switch_stack *)childregs) - 1;
 	
 	/* put the pt_regs structure at the end of the new kernel stack page and fix it up
 	 * remember that the task_struct doubles as the kernel stack for the task
 	 */
 
-	childregs = task_pt_regs(p);
-        
-	*childregs = *regs;  /* struct copy of pt_regs */
-        
-        p->set_child_tid = p->clear_child_tid = NULL;
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		memset(swstack, 0,
+			sizeof(struct switch_stack) + sizeof(struct pt_regs));
+		swstack->r1 = usp;
+		swstack->r2 = arg;
+		childregs->dccr = 1 << I_DCCR_BITNR;
+		swstack->return_ip = (unsigned long) ret_from_kernel_thread;
+		p->thread.ksp = (unsigned long) swstack;
+		p->thread.usp = 0;
+		return 0;
+	}
+	*childregs = *current_pt_regs();  /* struct copy of pt_regs */
 
         childregs->r10 = 0;  /* child returns 0 after a fork/clone */
-	
-	/* put the switch stack right below the pt_regs */
 
-	swstack = ((struct switch_stack *)childregs) - 1;
+	/* put the switch stack right below the pt_regs */
 
 	swstack->r9 = 0; /* parameter to ret_from_sys_call, 0 == dont restart the syscall */
 
@@ -147,7 +128,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	
 	/* fix the user-mode stackpointer */
 
-	p->thread.usp = usp;	
+	p->thread.usp = usp ?: rdusp();
 
 	/* and the kernel-mode one */
 
@@ -161,70 +142,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	return 0;
 }
 
-/* 
- * Be aware of the "magic" 7th argument in the four system-calls below.
- * They need the latest stackframe, which is put as the 7th argument by
- * entry.S. The previous arguments are dummies or actually used, but need
- * to be defined to reach the 7th argument.
- *
- * N.B.: Another method to get the stackframe is to use current_regs(). But
- * it returns the latest stack-frame stacked when going from _user mode_ and
- * some of these (at least sys_clone) are called from kernel-mode sometimes
- * (for example during kernel_thread, above) and thus cannot use it. Thus,
- * to be sure not to get any surprises, we use the method for the other calls
- * as well.
- */
-
-asmlinkage int sys_fork(long r10, long r11, long r12, long r13, long mof, long srp,
-			struct pt_regs *regs)
-{
-	return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
-}
-
-/* if newusp is 0, we just grab the old usp */
-/* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */
-asmlinkage int sys_clone(unsigned long newusp, unsigned long flags,
-			 int* parent_tid, int* child_tid, long mof, long srp,
-			 struct pt_regs *regs)
-{
-	if (!newusp)
-		newusp = rdusp();
-	return do_fork(flags, newusp, regs, 0, parent_tid, child_tid);
-}
-
-/* vfork is a system call in i386 because of register-pressure - maybe
- * we can remove it and handle it in libc but we put it here until then.
- */
-
-asmlinkage int sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp,
-			 struct pt_regs *regs)
-{
-        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
-}
-
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char *fname,
-			  const char *const *argv,
-			  const char *const *envp,
-			  long r13, long mof, long srp, 
-			  struct pt_regs *regs)
-{
-	int error;
-	struct filename *filename;
-
-	filename = getname(fname);
-	error = PTR_ERR(filename);
-
-	if (IS_ERR(filename))
-	        goto out;
-	error = do_execve(filename->name, argv, envp, regs);
-	putname(filename);
- out:
-	return error;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
 #if 0
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index de43aad..af4a486 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -680,7 +680,7 @@ config ETRAX_SPI_MMC_BOARD
 
 config SPI_ETRAX_SSER
 	tristate
-	depends on SPI_MASTER && ETRAX_ARCH_V32 && EXPERIMENTAL
+	depends on SPI_MASTER && ETRAX_ARCH_V32
 	select SPI_BITBANG
 	help
 	  This enables using an synchronous serial (sser) port as a
@@ -689,7 +689,7 @@ config SPI_ETRAX_SSER
 
 config SPI_ETRAX_GPIO
 	tristate
-	depends on SPI_MASTER && ETRAX_ARCH_V32 && EXPERIMENTAL
+	depends on SPI_MASTER && ETRAX_ARCH_V32
 	select SPI_BITBANG
 	help
 	  This enables using GPIO pins port as a SPI master controller
diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S
index c3ea469..faa6441 100644
--- a/arch/cris/arch-v32/kernel/entry.S
+++ b/arch/cris/arch-v32/kernel/entry.S
@@ -31,6 +31,7 @@
 	.globl system_call
 	.globl ret_from_intr
 	.globl ret_from_fork
+	.globl ret_from_kernel_thread
 	.globl resume
 	.globl multiple_interrupt
 	.globl nmi_interrupt
@@ -84,6 +85,18 @@ ret_from_fork:
 	nop
 	.size	ret_from_fork, . - ret_from_fork
 
+	.type	ret_from_kernel_thread,@function
+ret_from_kernel_thread:
+	jsr schedule_tail
+	nop
+	move.d	$r2, $r10
+	jsr	$r1
+	nop
+	moveq	0, $r9			; no syscall restarts, TYVM...
+	ba  ret_from_sys_call
+	nop
+	.size	ret_from_kernel_thread, . - ret_from_kernel_thread
+
 	.type	ret_from_intr,@function
 ret_from_intr:
 	;; Check for resched if preemptive kernel, or if we're going back to
@@ -531,15 +544,6 @@ _ugdb_handle_exception:
 	ba	do_sigtrap		; SIGTRAP the offending process.
 	move.d	[$sp+], $r0		; Restore R0 in delay slot.
 
-	.global kernel_execve
-	.type	kernel_execve,@function
-kernel_execve:
-	move.d __NR_execve, $r9
-	break 13
-	ret
-	nop
-	.size	kernel_execve, . - kernel_execve
-
 	.data
 
 	.section .rodata,"a"
diff --git a/arch/cris/arch-v32/kernel/process.c b/arch/cris/arch-v32/kernel/process.c
index 4e99922..2b23ef0 100644
--- a/arch/cris/arch-v32/kernel/process.c
+++ b/arch/cris/arch-v32/kernel/process.c
@@ -16,6 +16,7 @@
 #include <hwregs/reg_map.h>
 #include <hwregs/timer_defs.h>
 #include <hwregs/intr_vect_defs.h>
+#include <linux/ptrace.h>
 
 extern void stop_watchdog(void);
 
@@ -94,31 +95,6 @@ unsigned long thread_saved_pc(struct task_struct *t)
 	return task_pt_regs(t)->erp;
 }
 
-static void
-kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg)
-{
-	fn(arg);
-	do_exit(-1); /* Should never be called, return bad exit value. */
-}
-
-/* Create a kernel thread. */
-int
-kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-
-        /* Don't use r10 since that is set to 0 in copy_thread. */
-	regs.r11 = (unsigned long) fn;
-	regs.r12 = (unsigned long) arg;
-	regs.erp = (unsigned long) kernel_thread_helper;
-	regs.ccs = 1 << (I_CCS_BITNR + CCS_SHIFT);
-
-	/* Create the new process. */
-        return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-
 /*
  * Setup the child's kernel stack with a pt_regs and call switch_stack() on it.
  * It will be unnested during _resume and _ret_from_sys_call when the new thread
@@ -129,34 +105,42 @@ kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
  */
 
 extern asmlinkage void ret_from_fork(void);
+extern asmlinkage void ret_from_kernel_thread(void);
 
 int
 copy_thread(unsigned long clone_flags, unsigned long usp,
-	unsigned long unused,
-	struct task_struct *p, struct pt_regs *regs)
+	unsigned long arg, struct task_struct *p)
 {
-	struct pt_regs *childregs;
-	struct switch_stack *swstack;
+	struct pt_regs *childregs = task_pt_regs(p);
+	struct switch_stack *swstack = ((struct switch_stack *) childregs) - 1;
 
 	/*
 	 * Put the pt_regs structure at the end of the new kernel stack page and
 	 * fix it up. Note: the task_struct doubles as the kernel stack for the
 	 * task.
 	 */
-	childregs = task_pt_regs(p);
-	*childregs = *regs;	/* Struct copy of pt_regs. */
-        p->set_child_tid = p->clear_child_tid = NULL;
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		memset(swstack, 0,
+			sizeof(struct switch_stack) + sizeof(struct pt_regs));
+		swstack->r1 = usp;
+		swstack->r2 = arg;
+		childregs->ccs = 1 << (I_CCS_BITNR + CCS_SHIFT);
+		swstack->return_ip = (unsigned long) ret_from_kernel_thread;
+		p->thread.ksp = (unsigned long) swstack;
+		p->thread.usp = 0;
+		return 0;
+	}
+	*childregs = *current_pt_regs();	/* Struct copy of pt_regs. */
         childregs->r10 = 0;	/* Child returns 0 after a fork/clone. */
 
 	/* Set a new TLS ?
 	 * The TLS is in $mof because it is the 5th argument to sys_clone.
 	 */
 	if (p->mm && (clone_flags & CLONE_SETTLS)) {
-		task_thread_info(p)->tls = regs->mof;
+		task_thread_info(p)->tls = childregs->mof;
 	}
 
 	/* Put the switch stack right below the pt_regs. */
-	swstack = ((struct switch_stack *) childregs) - 1;
 
 	/* Parameter to ret_from_sys_call. 0 is don't restart the syscall. */
 	swstack->r9 = 0;
@@ -168,76 +152,12 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
 	swstack->return_ip = (unsigned long) ret_from_fork;
 
 	/* Fix the user-mode and kernel-mode stackpointer. */
-	p->thread.usp = usp;
+	p->thread.usp = usp ?: rdusp();
 	p->thread.ksp = (unsigned long) swstack;
 
 	return 0;
 }
 
-/*
- * Be aware of the "magic" 7th argument in the four system-calls below.
- * They need the latest stackframe, which is put as the 7th argument by
- * entry.S. The previous arguments are dummies or actually used, but need
- * to be defined to reach the 7th argument.
- *
- * N.B.: Another method to get the stackframe is to use current_regs(). But
- * it returns the latest stack-frame stacked when going from _user mode_ and
- * some of these (at least sys_clone) are called from kernel-mode sometimes
- * (for example during kernel_thread, above) and thus cannot use it. Thus,
- * to be sure not to get any surprises, we use the method for the other calls
- * as well.
- */
-asmlinkage int
-sys_fork(long r10, long r11, long r12, long r13, long mof, long srp,
-	struct pt_regs *regs)
-{
-	return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
-}
-
-/* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */
-asmlinkage int
-sys_clone(unsigned long newusp, unsigned long flags, int *parent_tid, int *child_tid,
-	unsigned long tls, long srp, struct pt_regs *regs)
-{
-	if (!newusp)
-		newusp = rdusp();
-
-	return do_fork(flags, newusp, regs, 0, parent_tid, child_tid);
-}
-
-/*
- * vfork is a system call in i386 because of register-pressure - maybe
- * we can remove it and handle it in libc but we put it here until then.
- */
-asmlinkage int
-sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp,
-	struct pt_regs *regs)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
-}
-
-/* sys_execve() executes a new program. */
-asmlinkage int
-sys_execve(const char *fname,
-	   const char *const *argv,
-	   const char *const *envp, long r13, long mof, long srp,
-	   struct pt_regs *regs)
-{
-	int error;
-	struct filename *filename;
-
-	filename = getname(fname);
-	error = PTR_ERR(filename);
-
-	if (IS_ERR(filename))
-	        goto out;
-
-	error = do_execve(filename->name, argv, envp, regs);
-	putname(filename);
- out:
-	return error;
-}
-
 unsigned long
 get_wchan(struct task_struct *p)
 {
diff --git a/arch/cris/include/arch-v10/arch/Kbuild b/arch/cris/include/arch-v10/arch/Kbuild
index 7a192e1..1f0fc7a 100644
--- a/arch/cris/include/arch-v10/arch/Kbuild
+++ b/arch/cris/include/arch-v10/arch/Kbuild
@@ -1,4 +1 @@
-header-y += user.h
-header-y += svinto.h
-header-y += sv_addr_ag.h
-header-y += sv_addr.agh
+# CRISv10 arch
diff --git a/arch/cris/include/arch-v10/arch/irq.h b/arch/cris/include/arch-v10/arch/irq.h
index 7d34594..ca2675a 100644
--- a/arch/cris/include/arch-v10/arch/irq.h
+++ b/arch/cris/include/arch-v10/arch/irq.h
@@ -142,7 +142,7 @@ __asm__ ( \
  * it here, we would not get the multiple_irq at all.
  *
  * The non-blocking here is based on the knowledge that the timer interrupt is 
- * registred as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not
+ * registered as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not
  * be an sti() before the timer irq handler is run to acknowledge the interrupt.
  */
 
diff --git a/arch/cris/include/arch-v10/arch/sv_addr.agh b/arch/cris/include/arch-v10/arch/sv_addr.agh
deleted file mode 100644
index 6ac3a7b..0000000
--- a/arch/cris/include/arch-v10/arch/sv_addr.agh
+++ /dev/null
@@ -1,7306 +0,0 @@
-/*
-!* This file was automatically generated by /n/asic/bin/reg_macro_gen
-!* from the file `/n/asic/projects/etrax_ng/doc/work/etrax_ng_regs.rd'.
-!* Editing within this file is thus not recommended,
-!* make the changes in `/n/asic/projects/etrax_ng/doc/work/etrax_ng_regs.rd' instead.
-!*/
-
-
-/*
-!* Bus interface configuration registers
-!*/
-
-#define R_WAITSTATES (IO_TYPECAST_UDWORD 0xb0000000)
-#define R_WAITSTATES__pcs4_7_zw__BITNR 30
-#define R_WAITSTATES__pcs4_7_zw__WIDTH 2
-#define R_WAITSTATES__pcs4_7_ew__BITNR 28
-#define R_WAITSTATES__pcs4_7_ew__WIDTH 2
-#define R_WAITSTATES__pcs4_7_lw__BITNR 24
-#define R_WAITSTATES__pcs4_7_lw__WIDTH 4
-#define R_WAITSTATES__pcs0_3_zw__BITNR 22
-#define R_WAITSTATES__pcs0_3_zw__WIDTH 2
-#define R_WAITSTATES__pcs0_3_ew__BITNR 20
-#define R_WAITSTATES__pcs0_3_ew__WIDTH 2
-#define R_WAITSTATES__pcs0_3_lw__BITNR 16
-#define R_WAITSTATES__pcs0_3_lw__WIDTH 4
-#define R_WAITSTATES__sram_zw__BITNR 14
-#define R_WAITSTATES__sram_zw__WIDTH 2
-#define R_WAITSTATES__sram_ew__BITNR 12
-#define R_WAITSTATES__sram_ew__WIDTH 2
-#define R_WAITSTATES__sram_lw__BITNR 8
-#define R_WAITSTATES__sram_lw__WIDTH 4
-#define R_WAITSTATES__flash_zw__BITNR 6
-#define R_WAITSTATES__flash_zw__WIDTH 2
-#define R_WAITSTATES__flash_ew__BITNR 4
-#define R_WAITSTATES__flash_ew__WIDTH 2
-#define R_WAITSTATES__flash_lw__BITNR 0
-#define R_WAITSTATES__flash_lw__WIDTH 4
-
-#define R_BUS_CONFIG (IO_TYPECAST_UDWORD 0xb0000004)
-#define R_BUS_CONFIG__sram_type__BITNR 9
-#define R_BUS_CONFIG__sram_type__WIDTH 1
-#define R_BUS_CONFIG__sram_type__cwe 1
-#define R_BUS_CONFIG__sram_type__bwe 0
-#define R_BUS_CONFIG__dma_burst__BITNR 8
-#define R_BUS_CONFIG__dma_burst__WIDTH 1
-#define R_BUS_CONFIG__dma_burst__burst16 1
-#define R_BUS_CONFIG__dma_burst__burst32 0
-#define R_BUS_CONFIG__pcs4_7_wr__BITNR 7
-#define R_BUS_CONFIG__pcs4_7_wr__WIDTH 1
-#define R_BUS_CONFIG__pcs4_7_wr__ext 1
-#define R_BUS_CONFIG__pcs4_7_wr__norm 0
-#define R_BUS_CONFIG__pcs0_3_wr__BITNR 6
-#define R_BUS_CONFIG__pcs0_3_wr__WIDTH 1
-#define R_BUS_CONFIG__pcs0_3_wr__ext 1
-#define R_BUS_CONFIG__pcs0_3_wr__norm 0
-#define R_BUS_CONFIG__sram_wr__BITNR 5
-#define R_BUS_CONFIG__sram_wr__WIDTH 1
-#define R_BUS_CONFIG__sram_wr__ext 1
-#define R_BUS_CONFIG__sram_wr__norm 0
-#define R_BUS_CONFIG__flash_wr__BITNR 4
-#define R_BUS_CONFIG__flash_wr__WIDTH 1
-#define R_BUS_CONFIG__flash_wr__ext 1
-#define R_BUS_CONFIG__flash_wr__norm 0
-#define R_BUS_CONFIG__pcs4_7_bw__BITNR 3
-#define R_BUS_CONFIG__pcs4_7_bw__WIDTH 1
-#define R_BUS_CONFIG__pcs4_7_bw__bw32 1
-#define R_BUS_CONFIG__pcs4_7_bw__bw16 0
-#define R_BUS_CONFIG__pcs0_3_bw__BITNR 2
-#define R_BUS_CONFIG__pcs0_3_bw__WIDTH 1
-#define R_BUS_CONFIG__pcs0_3_bw__bw32 1
-#define R_BUS_CONFIG__pcs0_3_bw__bw16 0
-#define R_BUS_CONFIG__sram_bw__BITNR 1
-#define R_BUS_CONFIG__sram_bw__WIDTH 1
-#define R_BUS_CONFIG__sram_bw__bw32 1
-#define R_BUS_CONFIG__sram_bw__bw16 0
-#define R_BUS_CONFIG__flash_bw__BITNR 0
-#define R_BUS_CONFIG__flash_bw__WIDTH 1
-#define R_BUS_CONFIG__flash_bw__bw32 1
-#define R_BUS_CONFIG__flash_bw__bw16 0
-
-#define R_BUS_STATUS (IO_TYPECAST_RO_UDWORD 0xb0000004)
-#define R_BUS_STATUS__pll_lock_tm__BITNR 5
-#define R_BUS_STATUS__pll_lock_tm__WIDTH 1
-#define R_BUS_STATUS__pll_lock_tm__expired 0
-#define R_BUS_STATUS__pll_lock_tm__counting 1
-#define R_BUS_STATUS__both_faults__BITNR 4
-#define R_BUS_STATUS__both_faults__WIDTH 1
-#define R_BUS_STATUS__both_faults__no 0
-#define R_BUS_STATUS__both_faults__yes 1
-#define R_BUS_STATUS__bsen___BITNR 3
-#define R_BUS_STATUS__bsen___WIDTH 1
-#define R_BUS_STATUS__bsen___enable 0
-#define R_BUS_STATUS__bsen___disable 1
-#define R_BUS_STATUS__boot__BITNR 1
-#define R_BUS_STATUS__boot__WIDTH 2
-#define R_BUS_STATUS__boot__uncached 0
-#define R_BUS_STATUS__boot__serial 1
-#define R_BUS_STATUS__boot__network 2
-#define R_BUS_STATUS__boot__parallel 3
-#define R_BUS_STATUS__flashw__BITNR 0
-#define R_BUS_STATUS__flashw__WIDTH 1
-#define R_BUS_STATUS__flashw__bw32 1
-#define R_BUS_STATUS__flashw__bw16 0
-
-#define R_DRAM_TIMING (IO_TYPECAST_UDWORD 0xb0000008)
-#define R_DRAM_TIMING__sdram__BITNR 31
-#define R_DRAM_TIMING__sdram__WIDTH 1
-#define R_DRAM_TIMING__sdram__enable 1
-#define R_DRAM_TIMING__sdram__disable 0
-#define R_DRAM_TIMING__ref__BITNR 14
-#define R_DRAM_TIMING__ref__WIDTH 2
-#define R_DRAM_TIMING__ref__e52us 0
-#define R_DRAM_TIMING__ref__e13us 1
-#define R_DRAM_TIMING__ref__e8700ns 2
-#define R_DRAM_TIMING__ref__disable 3
-#define R_DRAM_TIMING__rp__BITNR 12
-#define R_DRAM_TIMING__rp__WIDTH 2
-#define R_DRAM_TIMING__rs__BITNR 10
-#define R_DRAM_TIMING__rs__WIDTH 2
-#define R_DRAM_TIMING__rh__BITNR 8
-#define R_DRAM_TIMING__rh__WIDTH 2
-#define R_DRAM_TIMING__w__BITNR 7
-#define R_DRAM_TIMING__w__WIDTH 1
-#define R_DRAM_TIMING__w__norm 0
-#define R_DRAM_TIMING__w__ext 1
-#define R_DRAM_TIMING__c__BITNR 6
-#define R_DRAM_TIMING__c__WIDTH 1
-#define R_DRAM_TIMING__c__norm 0
-#define R_DRAM_TIMING__c__ext 1
-#define R_DRAM_TIMING__cz__BITNR 4
-#define R_DRAM_TIMING__cz__WIDTH 2
-#define R_DRAM_TIMING__cp__BITNR 2
-#define R_DRAM_TIMING__cp__WIDTH 2
-#define R_DRAM_TIMING__cw__BITNR 0
-#define R_DRAM_TIMING__cw__WIDTH 2
-
-#define R_SDRAM_TIMING (IO_TYPECAST_UDWORD 0xb0000008)
-#define R_SDRAM_TIMING__sdram__BITNR 31
-#define R_SDRAM_TIMING__sdram__WIDTH 1
-#define R_SDRAM_TIMING__sdram__enable 1
-#define R_SDRAM_TIMING__sdram__disable 0
-#define R_SDRAM_TIMING__mrs_data__BITNR 16
-#define R_SDRAM_TIMING__mrs_data__WIDTH 15
-#define R_SDRAM_TIMING__ref__BITNR 14
-#define R_SDRAM_TIMING__ref__WIDTH 2
-#define R_SDRAM_TIMING__ref__e52us 0
-#define R_SDRAM_TIMING__ref__e13us 1
-#define R_SDRAM_TIMING__ref__e6500ns 2
-#define R_SDRAM_TIMING__ref__disable 3
-#define R_SDRAM_TIMING__ddr__BITNR 13
-#define R_SDRAM_TIMING__ddr__WIDTH 1
-#define R_SDRAM_TIMING__ddr__on 1
-#define R_SDRAM_TIMING__ddr__off 0
-#define R_SDRAM_TIMING__clk100__BITNR 12
-#define R_SDRAM_TIMING__clk100__WIDTH 1
-#define R_SDRAM_TIMING__clk100__on 1
-#define R_SDRAM_TIMING__clk100__off 0
-#define R_SDRAM_TIMING__ps__BITNR 11
-#define R_SDRAM_TIMING__ps__WIDTH 1
-#define R_SDRAM_TIMING__ps__on 1
-#define R_SDRAM_TIMING__ps__off 0
-#define R_SDRAM_TIMING__cmd__BITNR 9
-#define R_SDRAM_TIMING__cmd__WIDTH 2
-#define R_SDRAM_TIMING__cmd__pre 3
-#define R_SDRAM_TIMING__cmd__ref 2
-#define R_SDRAM_TIMING__cmd__mrs 1
-#define R_SDRAM_TIMING__cmd__nop 0
-#define R_SDRAM_TIMING__pde__BITNR 8
-#define R_SDRAM_TIMING__pde__WIDTH 1
-#define R_SDRAM_TIMING__rc__BITNR 6
-#define R_SDRAM_TIMING__rc__WIDTH 2
-#define R_SDRAM_TIMING__rp__BITNR 4
-#define R_SDRAM_TIMING__rp__WIDTH 2
-#define R_SDRAM_TIMING__rcd__BITNR 2
-#define R_SDRAM_TIMING__rcd__WIDTH 2
-#define R_SDRAM_TIMING__cl__BITNR 0
-#define R_SDRAM_TIMING__cl__WIDTH 2
-
-#define R_DRAM_CONFIG (IO_TYPECAST_UDWORD 0xb000000c)
-#define R_DRAM_CONFIG__wmm1__BITNR 31
-#define R_DRAM_CONFIG__wmm1__WIDTH 1
-#define R_DRAM_CONFIG__wmm1__wmm 1
-#define R_DRAM_CONFIG__wmm1__norm 0
-#define R_DRAM_CONFIG__wmm0__BITNR 30
-#define R_DRAM_CONFIG__wmm0__WIDTH 1
-#define R_DRAM_CONFIG__wmm0__wmm 1
-#define R_DRAM_CONFIG__wmm0__norm 0
-#define R_DRAM_CONFIG__sh1__BITNR 27
-#define R_DRAM_CONFIG__sh1__WIDTH 3
-#define R_DRAM_CONFIG__sh0__BITNR 24
-#define R_DRAM_CONFIG__sh0__WIDTH 3
-#define R_DRAM_CONFIG__w__BITNR 23
-#define R_DRAM_CONFIG__w__WIDTH 1
-#define R_DRAM_CONFIG__w__bw16 0
-#define R_DRAM_CONFIG__w__bw32 1
-#define R_DRAM_CONFIG__c__BITNR 22
-#define R_DRAM_CONFIG__c__WIDTH 1
-#define R_DRAM_CONFIG__c__byte 0
-#define R_DRAM_CONFIG__c__bank 1
-#define R_DRAM_CONFIG__e__BITNR 21
-#define R_DRAM_CONFIG__e__WIDTH 1
-#define R_DRAM_CONFIG__e__fast 0
-#define R_DRAM_CONFIG__e__edo 1
-#define R_DRAM_CONFIG__group_sel__BITNR 16
-#define R_DRAM_CONFIG__group_sel__WIDTH 5
-#define R_DRAM_CONFIG__group_sel__grp0 0
-#define R_DRAM_CONFIG__group_sel__grp1 1
-#define R_DRAM_CONFIG__group_sel__bit9 9
-#define R_DRAM_CONFIG__group_sel__bit10 10
-#define R_DRAM_CONFIG__group_sel__bit11 11
-#define R_DRAM_CONFIG__group_sel__bit12 12
-#define R_DRAM_CONFIG__group_sel__bit13 13
-#define R_DRAM_CONFIG__group_sel__bit14 14
-#define R_DRAM_CONFIG__group_sel__bit15 15
-#define R_DRAM_CONFIG__group_sel__bit16 16
-#define R_DRAM_CONFIG__group_sel__bit17 17
-#define R_DRAM_CONFIG__group_sel__bit18 18
-#define R_DRAM_CONFIG__group_sel__bit19 19
-#define R_DRAM_CONFIG__group_sel__bit20 20
-#define R_DRAM_CONFIG__group_sel__bit21 21
-#define R_DRAM_CONFIG__group_sel__bit22 22
-#define R_DRAM_CONFIG__group_sel__bit23 23
-#define R_DRAM_CONFIG__group_sel__bit24 24
-#define R_DRAM_CONFIG__group_sel__bit25 25
-#define R_DRAM_CONFIG__group_sel__bit26 26
-#define R_DRAM_CONFIG__group_sel__bit27 27
-#define R_DRAM_CONFIG__group_sel__bit28 28
-#define R_DRAM_CONFIG__group_sel__bit29 29
-#define R_DRAM_CONFIG__ca1__BITNR 13
-#define R_DRAM_CONFIG__ca1__WIDTH 3
-#define R_DRAM_CONFIG__bank23sel__BITNR 8
-#define R_DRAM_CONFIG__bank23sel__WIDTH 5
-#define R_DRAM_CONFIG__bank23sel__bank0 0
-#define R_DRAM_CONFIG__bank23sel__bank1 1
-#define R_DRAM_CONFIG__bank23sel__bit9 9
-#define R_DRAM_CONFIG__bank23sel__bit10 10
-#define R_DRAM_CONFIG__bank23sel__bit11 11
-#define R_DRAM_CONFIG__bank23sel__bit12 12
-#define R_DRAM_CONFIG__bank23sel__bit13 13
-#define R_DRAM_CONFIG__bank23sel__bit14 14
-#define R_DRAM_CONFIG__bank23sel__bit15 15
-#define R_DRAM_CONFIG__bank23sel__bit16 16
-#define R_DRAM_CONFIG__bank23sel__bit17 17
-#define R_DRAM_CONFIG__bank23sel__bit18 18
-#define R_DRAM_CONFIG__bank23sel__bit19 19
-#define R_DRAM_CONFIG__bank23sel__bit20 20
-#define R_DRAM_CONFIG__bank23sel__bit21 21
-#define R_DRAM_CONFIG__bank23sel__bit22 22
-#define R_DRAM_CONFIG__bank23sel__bit23 23
-#define R_DRAM_CONFIG__bank23sel__bit24 24
-#define R_DRAM_CONFIG__bank23sel__bit25 25
-#define R_DRAM_CONFIG__bank23sel__bit26 26
-#define R_DRAM_CONFIG__bank23sel__bit27 27
-#define R_DRAM_CONFIG__bank23sel__bit28 28
-#define R_DRAM_CONFIG__bank23sel__bit29 29
-#define R_DRAM_CONFIG__ca0__BITNR 5
-#define R_DRAM_CONFIG__ca0__WIDTH 3
-#define R_DRAM_CONFIG__bank01sel__BITNR 0
-#define R_DRAM_CONFIG__bank01sel__WIDTH 5
-#define R_DRAM_CONFIG__bank01sel__bank0 0
-#define R_DRAM_CONFIG__bank01sel__bank1 1
-#define R_DRAM_CONFIG__bank01sel__bit9 9
-#define R_DRAM_CONFIG__bank01sel__bit10 10
-#define R_DRAM_CONFIG__bank01sel__bit11 11
-#define R_DRAM_CONFIG__bank01sel__bit12 12
-#define R_DRAM_CONFIG__bank01sel__bit13 13
-#define R_DRAM_CONFIG__bank01sel__bit14 14
-#define R_DRAM_CONFIG__bank01sel__bit15 15
-#define R_DRAM_CONFIG__bank01sel__bit16 16
-#define R_DRAM_CONFIG__bank01sel__bit17 17
-#define R_DRAM_CONFIG__bank01sel__bit18 18
-#define R_DRAM_CONFIG__bank01sel__bit19 19
-#define R_DRAM_CONFIG__bank01sel__bit20 20
-#define R_DRAM_CONFIG__bank01sel__bit21 21
-#define R_DRAM_CONFIG__bank01sel__bit22 22
-#define R_DRAM_CONFIG__bank01sel__bit23 23
-#define R_DRAM_CONFIG__bank01sel__bit24 24
-#define R_DRAM_CONFIG__bank01sel__bit25 25
-#define R_DRAM_CONFIG__bank01sel__bit26 26
-#define R_DRAM_CONFIG__bank01sel__bit27 27
-#define R_DRAM_CONFIG__bank01sel__bit28 28
-#define R_DRAM_CONFIG__bank01sel__bit29 29
-
-#define R_SDRAM_CONFIG (IO_TYPECAST_UDWORD 0xb000000c)
-#define R_SDRAM_CONFIG__wmm1__BITNR 31
-#define R_SDRAM_CONFIG__wmm1__WIDTH 1
-#define R_SDRAM_CONFIG__wmm1__wmm 1
-#define R_SDRAM_CONFIG__wmm1__norm 0
-#define R_SDRAM_CONFIG__wmm0__BITNR 30
-#define R_SDRAM_CONFIG__wmm0__WIDTH 1
-#define R_SDRAM_CONFIG__wmm0__wmm 1
-#define R_SDRAM_CONFIG__wmm0__norm 0
-#define R_SDRAM_CONFIG__sh1__BITNR 27
-#define R_SDRAM_CONFIG__sh1__WIDTH 3
-#define R_SDRAM_CONFIG__sh0__BITNR 24
-#define R_SDRAM_CONFIG__sh0__WIDTH 3
-#define R_SDRAM_CONFIG__w__BITNR 23
-#define R_SDRAM_CONFIG__w__WIDTH 1
-#define R_SDRAM_CONFIG__w__bw16 0
-#define R_SDRAM_CONFIG__w__bw32 1
-#define R_SDRAM_CONFIG__type1__BITNR 22
-#define R_SDRAM_CONFIG__type1__WIDTH 1
-#define R_SDRAM_CONFIG__type1__bank2 0
-#define R_SDRAM_CONFIG__type1__bank4 1
-#define R_SDRAM_CONFIG__type0__BITNR 21
-#define R_SDRAM_CONFIG__type0__WIDTH 1
-#define R_SDRAM_CONFIG__type0__bank2 0
-#define R_SDRAM_CONFIG__type0__bank4 1
-#define R_SDRAM_CONFIG__group_sel__BITNR 16
-#define R_SDRAM_CONFIG__group_sel__WIDTH 5
-#define R_SDRAM_CONFIG__group_sel__grp0 0
-#define R_SDRAM_CONFIG__group_sel__grp1 1
-#define R_SDRAM_CONFIG__group_sel__bit9 9
-#define R_SDRAM_CONFIG__group_sel__bit10 10
-#define R_SDRAM_CONFIG__group_sel__bit11 11
-#define R_SDRAM_CONFIG__group_sel__bit12 12
-#define R_SDRAM_CONFIG__group_sel__bit13 13
-#define R_SDRAM_CONFIG__group_sel__bit14 14
-#define R_SDRAM_CONFIG__group_sel__bit15 15
-#define R_SDRAM_CONFIG__group_sel__bit16 16
-#define R_SDRAM_CONFIG__group_sel__bit17 17
-#define R_SDRAM_CONFIG__group_sel__bit18 18
-#define R_SDRAM_CONFIG__group_sel__bit19 19
-#define R_SDRAM_CONFIG__group_sel__bit20 20
-#define R_SDRAM_CONFIG__group_sel__bit21 21
-#define R_SDRAM_CONFIG__group_sel__bit22 22
-#define R_SDRAM_CONFIG__group_sel__bit23 23
-#define R_SDRAM_CONFIG__group_sel__bit24 24
-#define R_SDRAM_CONFIG__group_sel__bit25 25
-#define R_SDRAM_CONFIG__group_sel__bit26 26
-#define R_SDRAM_CONFIG__group_sel__bit27 27
-#define R_SDRAM_CONFIG__group_sel__bit28 28
-#define R_SDRAM_CONFIG__group_sel__bit29 29
-#define R_SDRAM_CONFIG__ca1__BITNR 13
-#define R_SDRAM_CONFIG__ca1__WIDTH 3
-#define R_SDRAM_CONFIG__bank_sel1__BITNR 8
-#define R_SDRAM_CONFIG__bank_sel1__WIDTH 5
-#define R_SDRAM_CONFIG__bank_sel1__bit9 9
-#define R_SDRAM_CONFIG__bank_sel1__bit10 10
-#define R_SDRAM_CONFIG__bank_sel1__bit11 11
-#define R_SDRAM_CONFIG__bank_sel1__bit12 12
-#define R_SDRAM_CONFIG__bank_sel1__bit13 13
-#define R_SDRAM_CONFIG__bank_sel1__bit14 14
-#define R_SDRAM_CONFIG__bank_sel1__bit15 15
-#define R_SDRAM_CONFIG__bank_sel1__bit16 16
-#define R_SDRAM_CONFIG__bank_sel1__bit17 17
-#define R_SDRAM_CONFIG__bank_sel1__bit18 18
-#define R_SDRAM_CONFIG__bank_sel1__bit19 19
-#define R_SDRAM_CONFIG__bank_sel1__bit20 20
-#define R_SDRAM_CONFIG__bank_sel1__bit21 21
-#define R_SDRAM_CONFIG__bank_sel1__bit22 22
-#define R_SDRAM_CONFIG__bank_sel1__bit23 23
-#define R_SDRAM_CONFIG__bank_sel1__bit24 24
-#define R_SDRAM_CONFIG__bank_sel1__bit25 25
-#define R_SDRAM_CONFIG__bank_sel1__bit26 26
-#define R_SDRAM_CONFIG__bank_sel1__bit27 27
-#define R_SDRAM_CONFIG__bank_sel1__bit28 28
-#define R_SDRAM_CONFIG__bank_sel1__bit29 29
-#define R_SDRAM_CONFIG__ca0__BITNR 5
-#define R_SDRAM_CONFIG__ca0__WIDTH 3
-#define R_SDRAM_CONFIG__bank_sel0__BITNR 0
-#define R_SDRAM_CONFIG__bank_sel0__WIDTH 5
-#define R_SDRAM_CONFIG__bank_sel0__bit9 9
-#define R_SDRAM_CONFIG__bank_sel0__bit10 10
-#define R_SDRAM_CONFIG__bank_sel0__bit11 11
-#define R_SDRAM_CONFIG__bank_sel0__bit12 12
-#define R_SDRAM_CONFIG__bank_sel0__bit13 13
-#define R_SDRAM_CONFIG__bank_sel0__bit14 14
-#define R_SDRAM_CONFIG__bank_sel0__bit15 15
-#define R_SDRAM_CONFIG__bank_sel0__bit16 16
-#define R_SDRAM_CONFIG__bank_sel0__bit17 17
-#define R_SDRAM_CONFIG__bank_sel0__bit18 18
-#define R_SDRAM_CONFIG__bank_sel0__bit19 19
-#define R_SDRAM_CONFIG__bank_sel0__bit20 20
-#define R_SDRAM_CONFIG__bank_sel0__bit21 21
-#define R_SDRAM_CONFIG__bank_sel0__bit22 22
-#define R_SDRAM_CONFIG__bank_sel0__bit23 23
-#define R_SDRAM_CONFIG__bank_sel0__bit24 24
-#define R_SDRAM_CONFIG__bank_sel0__bit25 25
-#define R_SDRAM_CONFIG__bank_sel0__bit26 26
-#define R_SDRAM_CONFIG__bank_sel0__bit27 27
-#define R_SDRAM_CONFIG__bank_sel0__bit28 28
-#define R_SDRAM_CONFIG__bank_sel0__bit29 29
-
-/*
-!* External DMA registers
-!*/
-
-#define R_EXT_DMA_0_CMD (IO_TYPECAST_UDWORD 0xb0000010)
-#define R_EXT_DMA_0_CMD__cnt__BITNR 23
-#define R_EXT_DMA_0_CMD__cnt__WIDTH 1
-#define R_EXT_DMA_0_CMD__cnt__enable 1
-#define R_EXT_DMA_0_CMD__cnt__disable 0
-#define R_EXT_DMA_0_CMD__rqpol__BITNR 22
-#define R_EXT_DMA_0_CMD__rqpol__WIDTH 1
-#define R_EXT_DMA_0_CMD__rqpol__ahigh 0
-#define R_EXT_DMA_0_CMD__rqpol__alow 1
-#define R_EXT_DMA_0_CMD__apol__BITNR 21
-#define R_EXT_DMA_0_CMD__apol__WIDTH 1
-#define R_EXT_DMA_0_CMD__apol__ahigh 0
-#define R_EXT_DMA_0_CMD__apol__alow 1
-#define R_EXT_DMA_0_CMD__rq_ack__BITNR 20
-#define R_EXT_DMA_0_CMD__rq_ack__WIDTH 1
-#define R_EXT_DMA_0_CMD__rq_ack__burst 0
-#define R_EXT_DMA_0_CMD__rq_ack__handsh 1
-#define R_EXT_DMA_0_CMD__wid__BITNR 18
-#define R_EXT_DMA_0_CMD__wid__WIDTH 2
-#define R_EXT_DMA_0_CMD__wid__byte 0
-#define R_EXT_DMA_0_CMD__wid__word 1
-#define R_EXT_DMA_0_CMD__wid__dword 2
-#define R_EXT_DMA_0_CMD__dir__BITNR 17
-#define R_EXT_DMA_0_CMD__dir__WIDTH 1
-#define R_EXT_DMA_0_CMD__dir__input 0
-#define R_EXT_DMA_0_CMD__dir__output 1
-#define R_EXT_DMA_0_CMD__run__BITNR 16
-#define R_EXT_DMA_0_CMD__run__WIDTH 1
-#define R_EXT_DMA_0_CMD__run__start 1
-#define R_EXT_DMA_0_CMD__run__stop 0
-#define R_EXT_DMA_0_CMD__trf_count__BITNR 0
-#define R_EXT_DMA_0_CMD__trf_count__WIDTH 16
-
-#define R_EXT_DMA_0_STAT (IO_TYPECAST_RO_UDWORD 0xb0000010)
-#define R_EXT_DMA_0_STAT__run__BITNR 16
-#define R_EXT_DMA_0_STAT__run__WIDTH 1
-#define R_EXT_DMA_0_STAT__run__start 1
-#define R_EXT_DMA_0_STAT__run__stop 0
-#define R_EXT_DMA_0_STAT__trf_count__BITNR 0
-#define R_EXT_DMA_0_STAT__trf_count__WIDTH 16
-
-#define R_EXT_DMA_0_ADDR (IO_TYPECAST_UDWORD 0xb0000014)
-#define R_EXT_DMA_0_ADDR__ext0_addr__BITNR 2
-#define R_EXT_DMA_0_ADDR__ext0_addr__WIDTH 28
-
-#define R_EXT_DMA_1_CMD (IO_TYPECAST_UDWORD 0xb0000018)
-#define R_EXT_DMA_1_CMD__cnt__BITNR 23
-#define R_EXT_DMA_1_CMD__cnt__WIDTH 1
-#define R_EXT_DMA_1_CMD__cnt__enable 1
-#define R_EXT_DMA_1_CMD__cnt__disable 0
-#define R_EXT_DMA_1_CMD__rqpol__BITNR 22
-#define R_EXT_DMA_1_CMD__rqpol__WIDTH 1
-#define R_EXT_DMA_1_CMD__rqpol__ahigh 0
-#define R_EXT_DMA_1_CMD__rqpol__alow 1
-#define R_EXT_DMA_1_CMD__apol__BITNR 21
-#define R_EXT_DMA_1_CMD__apol__WIDTH 1
-#define R_EXT_DMA_1_CMD__apol__ahigh 0
-#define R_EXT_DMA_1_CMD__apol__alow 1
-#define R_EXT_DMA_1_CMD__rq_ack__BITNR 20
-#define R_EXT_DMA_1_CMD__rq_ack__WIDTH 1
-#define R_EXT_DMA_1_CMD__rq_ack__burst 0
-#define R_EXT_DMA_1_CMD__rq_ack__handsh 1
-#define R_EXT_DMA_1_CMD__wid__BITNR 18
-#define R_EXT_DMA_1_CMD__wid__WIDTH 2
-#define R_EXT_DMA_1_CMD__wid__byte 0
-#define R_EXT_DMA_1_CMD__wid__word 1
-#define R_EXT_DMA_1_CMD__wid__dword 2
-#define R_EXT_DMA_1_CMD__dir__BITNR 17
-#define R_EXT_DMA_1_CMD__dir__WIDTH 1
-#define R_EXT_DMA_1_CMD__dir__input 0
-#define R_EXT_DMA_1_CMD__dir__output 1
-#define R_EXT_DMA_1_CMD__run__BITNR 16
-#define R_EXT_DMA_1_CMD__run__WIDTH 1
-#define R_EXT_DMA_1_CMD__run__start 1
-#define R_EXT_DMA_1_CMD__run__stop 0
-#define R_EXT_DMA_1_CMD__trf_count__BITNR 0
-#define R_EXT_DMA_1_CMD__trf_count__WIDTH 16
-
-#define R_EXT_DMA_1_STAT (IO_TYPECAST_RO_UDWORD 0xb0000018)
-#define R_EXT_DMA_1_STAT__run__BITNR 16
-#define R_EXT_DMA_1_STAT__run__WIDTH 1
-#define R_EXT_DMA_1_STAT__run__start 1
-#define R_EXT_DMA_1_STAT__run__stop 0
-#define R_EXT_DMA_1_STAT__trf_count__BITNR 0
-#define R_EXT_DMA_1_STAT__trf_count__WIDTH 16
-
-#define R_EXT_DMA_1_ADDR (IO_TYPECAST_UDWORD 0xb000001c)
-#define R_EXT_DMA_1_ADDR__ext0_addr__BITNR 2
-#define R_EXT_DMA_1_ADDR__ext0_addr__WIDTH 28
-
-/*
-!* Timer registers
-!*/
-
-#define R_TIMER_CTRL (IO_TYPECAST_UDWORD 0xb0000020)
-#define R_TIMER_CTRL__timerdiv1__BITNR 24
-#define R_TIMER_CTRL__timerdiv1__WIDTH 8
-#define R_TIMER_CTRL__timerdiv0__BITNR 16
-#define R_TIMER_CTRL__timerdiv0__WIDTH 8
-#define R_TIMER_CTRL__presc_timer1__BITNR 15
-#define R_TIMER_CTRL__presc_timer1__WIDTH 1
-#define R_TIMER_CTRL__presc_timer1__normal 0
-#define R_TIMER_CTRL__presc_timer1__prescale 1
-#define R_TIMER_CTRL__i1__BITNR 14
-#define R_TIMER_CTRL__i1__WIDTH 1
-#define R_TIMER_CTRL__i1__clr 1
-#define R_TIMER_CTRL__i1__nop 0
-#define R_TIMER_CTRL__tm1__BITNR 12
-#define R_TIMER_CTRL__tm1__WIDTH 2
-#define R_TIMER_CTRL__tm1__stop_ld 0
-#define R_TIMER_CTRL__tm1__freeze 1
-#define R_TIMER_CTRL__tm1__run 2
-#define R_TIMER_CTRL__tm1__reserved 3
-#define R_TIMER_CTRL__clksel1__BITNR 8
-#define R_TIMER_CTRL__clksel1__WIDTH 4
-#define R_TIMER_CTRL__clksel1__c300Hz 0
-#define R_TIMER_CTRL__clksel1__c600Hz 1
-#define R_TIMER_CTRL__clksel1__c1200Hz 2
-#define R_TIMER_CTRL__clksel1__c2400Hz 3
-#define R_TIMER_CTRL__clksel1__c4800Hz 4
-#define R_TIMER_CTRL__clksel1__c9600Hz 5
-#define R_TIMER_CTRL__clksel1__c19k2Hz 6
-#define R_TIMER_CTRL__clksel1__c38k4Hz 7
-#define R_TIMER_CTRL__clksel1__c57k6Hz 8
-#define R_TIMER_CTRL__clksel1__c115k2Hz 9
-#define R_TIMER_CTRL__clksel1__c230k4Hz 10
-#define R_TIMER_CTRL__clksel1__c460k8Hz 11
-#define R_TIMER_CTRL__clksel1__c921k6Hz 12
-#define R_TIMER_CTRL__clksel1__c1843k2Hz 13
-#define R_TIMER_CTRL__clksel1__c6250kHz 14
-#define R_TIMER_CTRL__clksel1__cascade0 15
-#define R_TIMER_CTRL__presc_ext__BITNR 7
-#define R_TIMER_CTRL__presc_ext__WIDTH 1
-#define R_TIMER_CTRL__presc_ext__prescale 0
-#define R_TIMER_CTRL__presc_ext__external 1
-#define R_TIMER_CTRL__i0__BITNR 6
-#define R_TIMER_CTRL__i0__WIDTH 1
-#define R_TIMER_CTRL__i0__clr 1
-#define R_TIMER_CTRL__i0__nop 0
-#define R_TIMER_CTRL__tm0__BITNR 4
-#define R_TIMER_CTRL__tm0__WIDTH 2
-#define R_TIMER_CTRL__tm0__stop_ld 0
-#define R_TIMER_CTRL__tm0__freeze 1
-#define R_TIMER_CTRL__tm0__run 2
-#define R_TIMER_CTRL__tm0__reserved 3
-#define R_TIMER_CTRL__clksel0__BITNR 0
-#define R_TIMER_CTRL__clksel0__WIDTH 4
-#define R_TIMER_CTRL__clksel0__c300Hz 0
-#define R_TIMER_CTRL__clksel0__c600Hz 1
-#define R_TIMER_CTRL__clksel0__c1200Hz 2
-#define R_TIMER_CTRL__clksel0__c2400Hz 3
-#define R_TIMER_CTRL__clksel0__c4800Hz 4
-#define R_TIMER_CTRL__clksel0__c9600Hz 5
-#define R_TIMER_CTRL__clksel0__c19k2Hz 6
-#define R_TIMER_CTRL__clksel0__c38k4Hz 7
-#define R_TIMER_CTRL__clksel0__c57k6Hz 8
-#define R_TIMER_CTRL__clksel0__c115k2Hz 9
-#define R_TIMER_CTRL__clksel0__c230k4Hz 10
-#define R_TIMER_CTRL__clksel0__c460k8Hz 11
-#define R_TIMER_CTRL__clksel0__c921k6Hz 12
-#define R_TIMER_CTRL__clksel0__c1843k2Hz 13
-#define R_TIMER_CTRL__clksel0__c6250kHz 14
-#define R_TIMER_CTRL__clksel0__flexible 15
-
-#define R_TIMER_DATA (IO_TYPECAST_RO_UDWORD 0xb0000020)
-#define R_TIMER_DATA__timer1__BITNR 24
-#define R_TIMER_DATA__timer1__WIDTH 8
-#define R_TIMER_DATA__timer0__BITNR 16
-#define R_TIMER_DATA__timer0__WIDTH 8
-#define R_TIMER_DATA__clkdiv_high__BITNR 8
-#define R_TIMER_DATA__clkdiv_high__WIDTH 8
-#define R_TIMER_DATA__clkdiv_low__BITNR 0
-#define R_TIMER_DATA__clkdiv_low__WIDTH 8
-
-#define R_TIMER01_DATA (IO_TYPECAST_RO_UWORD 0xb0000022)
-#define R_TIMER01_DATA__count__BITNR 0
-#define R_TIMER01_DATA__count__WIDTH 16
-
-#define R_TIMER0_DATA (IO_TYPECAST_RO_BYTE 0xb0000022)
-#define R_TIMER0_DATA__count__BITNR 0
-#define R_TIMER0_DATA__count__WIDTH 8
-
-#define R_TIMER1_DATA (IO_TYPECAST_RO_BYTE 0xb0000023)
-#define R_TIMER1_DATA__count__BITNR 0
-#define R_TIMER1_DATA__count__WIDTH 8
-
-#define R_WATCHDOG (IO_TYPECAST_UDWORD 0xb0000024)
-#define R_WATCHDOG__key__BITNR 1
-#define R_WATCHDOG__key__WIDTH 3
-#define R_WATCHDOG__enable__BITNR 0
-#define R_WATCHDOG__enable__WIDTH 1
-#define R_WATCHDOG__enable__stop 0
-#define R_WATCHDOG__enable__start 1
-
-#define R_CLOCK_PRESCALE (IO_TYPECAST_UDWORD 0xb00000f0)
-#define R_CLOCK_PRESCALE__ser_presc__BITNR 16
-#define R_CLOCK_PRESCALE__ser_presc__WIDTH 16
-#define R_CLOCK_PRESCALE__tim_presc__BITNR 0
-#define R_CLOCK_PRESCALE__tim_presc__WIDTH 16
-
-#define R_SERIAL_PRESCALE (IO_TYPECAST_UWORD 0xb00000f2)
-#define R_SERIAL_PRESCALE__ser_presc__BITNR 0
-#define R_SERIAL_PRESCALE__ser_presc__WIDTH 16
-
-#define R_TIMER_PRESCALE (IO_TYPECAST_UWORD 0xb00000f0)
-#define R_TIMER_PRESCALE__tim_presc__BITNR 0
-#define R_TIMER_PRESCALE__tim_presc__WIDTH 16
-
-#define R_PRESCALE_STATUS (IO_TYPECAST_RO_UDWORD 0xb00000f0)
-#define R_PRESCALE_STATUS__ser_status__BITNR 16
-#define R_PRESCALE_STATUS__ser_status__WIDTH 16
-#define R_PRESCALE_STATUS__tim_status__BITNR 0
-#define R_PRESCALE_STATUS__tim_status__WIDTH 16
-
-#define R_SER_PRESC_STATUS (IO_TYPECAST_RO_UWORD 0xb00000f2)
-#define R_SER_PRESC_STATUS__ser_status__BITNR 0
-#define R_SER_PRESC_STATUS__ser_status__WIDTH 16
-
-#define R_TIM_PRESC_STATUS (IO_TYPECAST_RO_UWORD 0xb00000f0)
-#define R_TIM_PRESC_STATUS__tim_status__BITNR 0
-#define R_TIM_PRESC_STATUS__tim_status__WIDTH 16
-
-#define R_SYNC_SERIAL_PRESCALE (IO_TYPECAST_UDWORD 0xb00000f4)
-#define R_SYNC_SERIAL_PRESCALE__clk_sel_u3__BITNR 23
-#define R_SYNC_SERIAL_PRESCALE__clk_sel_u3__WIDTH 1
-#define R_SYNC_SERIAL_PRESCALE__clk_sel_u3__codec 0
-#define R_SYNC_SERIAL_PRESCALE__clk_sel_u3__baudrate 1
-#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u3__BITNR 22
-#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u3__WIDTH 1
-#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u3__external 0
-#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u3__internal 1
-#define R_SYNC_SERIAL_PRESCALE__clk_sel_u1__BITNR 21
-#define R_SYNC_SERIAL_PRESCALE__clk_sel_u1__WIDTH 1
-#define R_SYNC_SERIAL_PRESCALE__clk_sel_u1__codec 0
-#define R_SYNC_SERIAL_PRESCALE__clk_sel_u1__baudrate 1
-#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u1__BITNR 20
-#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u1__WIDTH 1
-#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u1__external 0
-#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u1__internal 1
-#define R_SYNC_SERIAL_PRESCALE__prescaler__BITNR 16
-#define R_SYNC_SERIAL_PRESCALE__prescaler__WIDTH 3
-#define R_SYNC_SERIAL_PRESCALE__prescaler__div1 0
-#define R_SYNC_SERIAL_PRESCALE__prescaler__div2 1
-#define R_SYNC_SERIAL_PRESCALE__prescaler__div4 2
-#define R_SYNC_SERIAL_PRESCALE__prescaler__div8 3
-#define R_SYNC_SERIAL_PRESCALE__prescaler__div16 4
-#define R_SYNC_SERIAL_PRESCALE__prescaler__div32 5
-#define R_SYNC_SERIAL_PRESCALE__prescaler__div64 6
-#define R_SYNC_SERIAL_PRESCALE__prescaler__div128 7
-#define R_SYNC_SERIAL_PRESCALE__warp_mode__BITNR 15
-#define R_SYNC_SERIAL_PRESCALE__warp_mode__WIDTH 1
-#define R_SYNC_SERIAL_PRESCALE__warp_mode__normal 0
-#define R_SYNC_SERIAL_PRESCALE__warp_mode__enabled 1
-#define R_SYNC_SERIAL_PRESCALE__frame_rate__BITNR 11
-#define R_SYNC_SERIAL_PRESCALE__frame_rate__WIDTH 4
-#define R_SYNC_SERIAL_PRESCALE__word_rate__BITNR 0
-#define R_SYNC_SERIAL_PRESCALE__word_rate__WIDTH 10
-
-/*
-!* Shared RAM interface registers
-!*/
-
-#define R_SHARED_RAM_CONFIG (IO_TYPECAST_UDWORD 0xb0000040)
-#define R_SHARED_RAM_CONFIG__width__BITNR 3
-#define R_SHARED_RAM_CONFIG__width__WIDTH 1
-#define R_SHARED_RAM_CONFIG__width__byte 0
-#define R_SHARED_RAM_CONFIG__width__word 1
-#define R_SHARED_RAM_CONFIG__enable__BITNR 2
-#define R_SHARED_RAM_CONFIG__enable__WIDTH 1
-#define R_SHARED_RAM_CONFIG__enable__yes 1
-#define R_SHARED_RAM_CONFIG__enable__no 0
-#define R_SHARED_RAM_CONFIG__pint__BITNR 1
-#define R_SHARED_RAM_CONFIG__pint__WIDTH 1
-#define R_SHARED_RAM_CONFIG__pint__int 1
-#define R_SHARED_RAM_CONFIG__pint__nop 0
-#define R_SHARED_RAM_CONFIG__clri__BITNR 0
-#define R_SHARED_RAM_CONFIG__clri__WIDTH 1
-#define R_SHARED_RAM_CONFIG__clri__clr 1
-#define R_SHARED_RAM_CONFIG__clri__nop 0
-
-#define R_SHARED_RAM_ADDR (IO_TYPECAST_UDWORD 0xb0000044)
-#define R_SHARED_RAM_ADDR__base_addr__BITNR 8
-#define R_SHARED_RAM_ADDR__base_addr__WIDTH 22
-
-/*
-!* General config registers
-!*/
-
-#define R_GEN_CONFIG (IO_TYPECAST_UDWORD 0xb000002c)
-#define R_GEN_CONFIG__par_w__BITNR 31
-#define R_GEN_CONFIG__par_w__WIDTH 1
-#define R_GEN_CONFIG__par_w__select 1
-#define R_GEN_CONFIG__par_w__disable 0
-#define R_GEN_CONFIG__usb2__BITNR 30
-#define R_GEN_CONFIG__usb2__WIDTH 1
-#define R_GEN_CONFIG__usb2__select 1
-#define R_GEN_CONFIG__usb2__disable 0
-#define R_GEN_CONFIG__usb1__BITNR 29
-#define R_GEN_CONFIG__usb1__WIDTH 1
-#define R_GEN_CONFIG__usb1__select 1
-#define R_GEN_CONFIG__usb1__disable 0
-#define R_GEN_CONFIG__g24dir__BITNR 27
-#define R_GEN_CONFIG__g24dir__WIDTH 1
-#define R_GEN_CONFIG__g24dir__in 0
-#define R_GEN_CONFIG__g24dir__out 1
-#define R_GEN_CONFIG__g16_23dir__BITNR 26
-#define R_GEN_CONFIG__g16_23dir__WIDTH 1
-#define R_GEN_CONFIG__g16_23dir__in 0
-#define R_GEN_CONFIG__g16_23dir__out 1
-#define R_GEN_CONFIG__g8_15dir__BITNR 25
-#define R_GEN_CONFIG__g8_15dir__WIDTH 1
-#define R_GEN_CONFIG__g8_15dir__in 0
-#define R_GEN_CONFIG__g8_15dir__out 1
-#define R_GEN_CONFIG__g0dir__BITNR 24
-#define R_GEN_CONFIG__g0dir__WIDTH 1
-#define R_GEN_CONFIG__g0dir__in 0
-#define R_GEN_CONFIG__g0dir__out 1
-#define R_GEN_CONFIG__dma9__BITNR 23
-#define R_GEN_CONFIG__dma9__WIDTH 1
-#define R_GEN_CONFIG__dma9__usb 0
-#define R_GEN_CONFIG__dma9__serial1 1
-#define R_GEN_CONFIG__dma8__BITNR 22
-#define R_GEN_CONFIG__dma8__WIDTH 1
-#define R_GEN_CONFIG__dma8__usb 0
-#define R_GEN_CONFIG__dma8__serial1 1
-#define R_GEN_CONFIG__dma7__BITNR 20
-#define R_GEN_CONFIG__dma7__WIDTH 2
-#define R_GEN_CONFIG__dma7__unused 0
-#define R_GEN_CONFIG__dma7__serial0 1
-#define R_GEN_CONFIG__dma7__extdma1 2
-#define R_GEN_CONFIG__dma7__intdma6 3
-#define R_GEN_CONFIG__dma6__BITNR 18
-#define R_GEN_CONFIG__dma6__WIDTH 2
-#define R_GEN_CONFIG__dma6__unused 0
-#define R_GEN_CONFIG__dma6__serial0 1
-#define R_GEN_CONFIG__dma6__extdma1 2
-#define R_GEN_CONFIG__dma6__intdma7 3
-#define R_GEN_CONFIG__dma5__BITNR 16
-#define R_GEN_CONFIG__dma5__WIDTH 2
-#define R_GEN_CONFIG__dma5__par1 0
-#define R_GEN_CONFIG__dma5__scsi1 1
-#define R_GEN_CONFIG__dma5__serial3 2
-#define R_GEN_CONFIG__dma5__extdma0 3
-#define R_GEN_CONFIG__dma4__BITNR 14
-#define R_GEN_CONFIG__dma4__WIDTH 2
-#define R_GEN_CONFIG__dma4__par1 0
-#define R_GEN_CONFIG__dma4__scsi1 1
-#define R_GEN_CONFIG__dma4__serial3 2
-#define R_GEN_CONFIG__dma4__extdma0 3
-#define R_GEN_CONFIG__dma3__BITNR 12
-#define R_GEN_CONFIG__dma3__WIDTH 2
-#define R_GEN_CONFIG__dma3__par0 0
-#define R_GEN_CONFIG__dma3__scsi0 1
-#define R_GEN_CONFIG__dma3__serial2 2
-#define R_GEN_CONFIG__dma3__ata 3
-#define R_GEN_CONFIG__dma2__BITNR 10
-#define R_GEN_CONFIG__dma2__WIDTH 2
-#define R_GEN_CONFIG__dma2__par0 0
-#define R_GEN_CONFIG__dma2__scsi0 1
-#define R_GEN_CONFIG__dma2__serial2 2
-#define R_GEN_CONFIG__dma2__ata 3
-#define R_GEN_CONFIG__mio_w__BITNR 9
-#define R_GEN_CONFIG__mio_w__WIDTH 1
-#define R_GEN_CONFIG__mio_w__select 1
-#define R_GEN_CONFIG__mio_w__disable 0
-#define R_GEN_CONFIG__ser3__BITNR 8
-#define R_GEN_CONFIG__ser3__WIDTH 1
-#define R_GEN_CONFIG__ser3__select 1
-#define R_GEN_CONFIG__ser3__disable 0
-#define R_GEN_CONFIG__par1__BITNR 7
-#define R_GEN_CONFIG__par1__WIDTH 1
-#define R_GEN_CONFIG__par1__select 1
-#define R_GEN_CONFIG__par1__disable 0
-#define R_GEN_CONFIG__scsi0w__BITNR 6
-#define R_GEN_CONFIG__scsi0w__WIDTH 1
-#define R_GEN_CONFIG__scsi0w__select 1
-#define R_GEN_CONFIG__scsi0w__disable 0
-#define R_GEN_CONFIG__scsi1__BITNR 5
-#define R_GEN_CONFIG__scsi1__WIDTH 1
-#define R_GEN_CONFIG__scsi1__select 1
-#define R_GEN_CONFIG__scsi1__disable 0
-#define R_GEN_CONFIG__mio__BITNR 4
-#define R_GEN_CONFIG__mio__WIDTH 1
-#define R_GEN_CONFIG__mio__select 1
-#define R_GEN_CONFIG__mio__disable 0
-#define R_GEN_CONFIG__ser2__BITNR 3
-#define R_GEN_CONFIG__ser2__WIDTH 1
-#define R_GEN_CONFIG__ser2__select 1
-#define R_GEN_CONFIG__ser2__disable 0
-#define R_GEN_CONFIG__par0__BITNR 2
-#define R_GEN_CONFIG__par0__WIDTH 1
-#define R_GEN_CONFIG__par0__select 1
-#define R_GEN_CONFIG__par0__disable 0
-#define R_GEN_CONFIG__ata__BITNR 1
-#define R_GEN_CONFIG__ata__WIDTH 1
-#define R_GEN_CONFIG__ata__select 1
-#define R_GEN_CONFIG__ata__disable 0
-#define R_GEN_CONFIG__scsi0__BITNR 0
-#define R_GEN_CONFIG__scsi0__WIDTH 1
-#define R_GEN_CONFIG__scsi0__select 1
-#define R_GEN_CONFIG__scsi0__disable 0
-
-#define R_GEN_CONFIG_II (IO_TYPECAST_UDWORD 0xb0000034)
-#define R_GEN_CONFIG_II__sermode3__BITNR 6
-#define R_GEN_CONFIG_II__sermode3__WIDTH 1
-#define R_GEN_CONFIG_II__sermode3__async 0
-#define R_GEN_CONFIG_II__sermode3__sync 1
-#define R_GEN_CONFIG_II__sermode1__BITNR 4
-#define R_GEN_CONFIG_II__sermode1__WIDTH 1
-#define R_GEN_CONFIG_II__sermode1__async 0
-#define R_GEN_CONFIG_II__sermode1__sync 1
-#define R_GEN_CONFIG_II__ext_clk__BITNR 2
-#define R_GEN_CONFIG_II__ext_clk__WIDTH 1
-#define R_GEN_CONFIG_II__ext_clk__select 1
-#define R_GEN_CONFIG_II__ext_clk__disable 0
-#define R_GEN_CONFIG_II__ser2__BITNR 1
-#define R_GEN_CONFIG_II__ser2__WIDTH 1
-#define R_GEN_CONFIG_II__ser2__select 1
-#define R_GEN_CONFIG_II__ser2__disable 0
-#define R_GEN_CONFIG_II__ser3__BITNR 0
-#define R_GEN_CONFIG_II__ser3__WIDTH 1
-#define R_GEN_CONFIG_II__ser3__select 1
-#define R_GEN_CONFIG_II__ser3__disable 0
-
-#define R_PORT_G_DATA (IO_TYPECAST_UDWORD 0xb0000028)
-#define R_PORT_G_DATA__data__BITNR 0
-#define R_PORT_G_DATA__data__WIDTH 32
-
-/*
-!* General port configuration registers
-!*/
-
-#define R_PORT_PA_SET (IO_TYPECAST_UDWORD 0xb0000030)
-#define R_PORT_PA_SET__dir7__BITNR 15
-#define R_PORT_PA_SET__dir7__WIDTH 1
-#define R_PORT_PA_SET__dir7__input 0
-#define R_PORT_PA_SET__dir7__output 1
-#define R_PORT_PA_SET__dir6__BITNR 14
-#define R_PORT_PA_SET__dir6__WIDTH 1
-#define R_PORT_PA_SET__dir6__input 0
-#define R_PORT_PA_SET__dir6__output 1
-#define R_PORT_PA_SET__dir5__BITNR 13
-#define R_PORT_PA_SET__dir5__WIDTH 1
-#define R_PORT_PA_SET__dir5__input 0
-#define R_PORT_PA_SET__dir5__output 1
-#define R_PORT_PA_SET__dir4__BITNR 12
-#define R_PORT_PA_SET__dir4__WIDTH 1
-#define R_PORT_PA_SET__dir4__input 0
-#define R_PORT_PA_SET__dir4__output 1
-#define R_PORT_PA_SET__dir3__BITNR 11
-#define R_PORT_PA_SET__dir3__WIDTH 1
-#define R_PORT_PA_SET__dir3__input 0
-#define R_PORT_PA_SET__dir3__output 1
-#define R_PORT_PA_SET__dir2__BITNR 10
-#define R_PORT_PA_SET__dir2__WIDTH 1
-#define R_PORT_PA_SET__dir2__input 0
-#define R_PORT_PA_SET__dir2__output 1
-#define R_PORT_PA_SET__dir1__BITNR 9
-#define R_PORT_PA_SET__dir1__WIDTH 1
-#define R_PORT_PA_SET__dir1__input 0
-#define R_PORT_PA_SET__dir1__output 1
-#define R_PORT_PA_SET__dir0__BITNR 8
-#define R_PORT_PA_SET__dir0__WIDTH 1
-#define R_PORT_PA_SET__dir0__input 0
-#define R_PORT_PA_SET__dir0__output 1
-#define R_PORT_PA_SET__data_out__BITNR 0
-#define R_PORT_PA_SET__data_out__WIDTH 8
-
-#define R_PORT_PA_DATA (IO_TYPECAST_BYTE 0xb0000030)
-#define R_PORT_PA_DATA__data_out__BITNR 0
-#define R_PORT_PA_DATA__data_out__WIDTH 8
-
-#define R_PORT_PA_DIR (IO_TYPECAST_BYTE 0xb0000031)
-#define R_PORT_PA_DIR__dir7__BITNR 7
-#define R_PORT_PA_DIR__dir7__WIDTH 1
-#define R_PORT_PA_DIR__dir7__input 0
-#define R_PORT_PA_DIR__dir7__output 1
-#define R_PORT_PA_DIR__dir6__BITNR 6
-#define R_PORT_PA_DIR__dir6__WIDTH 1
-#define R_PORT_PA_DIR__dir6__input 0
-#define R_PORT_PA_DIR__dir6__output 1
-#define R_PORT_PA_DIR__dir5__BITNR 5
-#define R_PORT_PA_DIR__dir5__WIDTH 1
-#define R_PORT_PA_DIR__dir5__input 0
-#define R_PORT_PA_DIR__dir5__output 1
-#define R_PORT_PA_DIR__dir4__BITNR 4
-#define R_PORT_PA_DIR__dir4__WIDTH 1
-#define R_PORT_PA_DIR__dir4__input 0
-#define R_PORT_PA_DIR__dir4__output 1
-#define R_PORT_PA_DIR__dir3__BITNR 3
-#define R_PORT_PA_DIR__dir3__WIDTH 1
-#define R_PORT_PA_DIR__dir3__input 0
-#define R_PORT_PA_DIR__dir3__output 1
-#define R_PORT_PA_DIR__dir2__BITNR 2
-#define R_PORT_PA_DIR__dir2__WIDTH 1
-#define R_PORT_PA_DIR__dir2__input 0
-#define R_PORT_PA_DIR__dir2__output 1
-#define R_PORT_PA_DIR__dir1__BITNR 1
-#define R_PORT_PA_DIR__dir1__WIDTH 1
-#define R_PORT_PA_DIR__dir1__input 0
-#define R_PORT_PA_DIR__dir1__output 1
-#define R_PORT_PA_DIR__dir0__BITNR 0
-#define R_PORT_PA_DIR__dir0__WIDTH 1
-#define R_PORT_PA_DIR__dir0__input 0
-#define R_PORT_PA_DIR__dir0__output 1
-
-#define R_PORT_PA_READ (IO_TYPECAST_RO_UDWORD 0xb0000030)
-#define R_PORT_PA_READ__data_in__BITNR 0
-#define R_PORT_PA_READ__data_in__WIDTH 8
-
-#define R_PORT_PB_SET (IO_TYPECAST_UDWORD 0xb0000038)
-#define R_PORT_PB_SET__syncser3__BITNR 29
-#define R_PORT_PB_SET__syncser3__WIDTH 1
-#define R_PORT_PB_SET__syncser3__port_cs 0
-#define R_PORT_PB_SET__syncser3__ss3extra 1
-#define R_PORT_PB_SET__syncser1__BITNR 28
-#define R_PORT_PB_SET__syncser1__WIDTH 1
-#define R_PORT_PB_SET__syncser1__port_cs 0
-#define R_PORT_PB_SET__syncser1__ss1extra 1
-#define R_PORT_PB_SET__i2c_en__BITNR 27
-#define R_PORT_PB_SET__i2c_en__WIDTH 1
-#define R_PORT_PB_SET__i2c_en__off 0
-#define R_PORT_PB_SET__i2c_en__on 1
-#define R_PORT_PB_SET__i2c_d__BITNR 26
-#define R_PORT_PB_SET__i2c_d__WIDTH 1
-#define R_PORT_PB_SET__i2c_clk__BITNR 25
-#define R_PORT_PB_SET__i2c_clk__WIDTH 1
-#define R_PORT_PB_SET__i2c_oe___BITNR 24
-#define R_PORT_PB_SET__i2c_oe___WIDTH 1
-#define R_PORT_PB_SET__i2c_oe___enable 0
-#define R_PORT_PB_SET__i2c_oe___disable 1
-#define R_PORT_PB_SET__cs7__BITNR 23
-#define R_PORT_PB_SET__cs7__WIDTH 1
-#define R_PORT_PB_SET__cs7__port 0
-#define R_PORT_PB_SET__cs7__cs 1
-#define R_PORT_PB_SET__cs6__BITNR 22
-#define R_PORT_PB_SET__cs6__WIDTH 1
-#define R_PORT_PB_SET__cs6__port 0
-#define R_PORT_PB_SET__cs6__cs 1
-#define R_PORT_PB_SET__cs5__BITNR 21
-#define R_PORT_PB_SET__cs5__WIDTH 1
-#define R_PORT_PB_SET__cs5__port 0
-#define R_PORT_PB_SET__cs5__cs 1
-#define R_PORT_PB_SET__cs4__BITNR 20
-#define R_PORT_PB_SET__cs4__WIDTH 1
-#define R_PORT_PB_SET__cs4__port 0
-#define R_PORT_PB_SET__cs4__cs 1
-#define R_PORT_PB_SET__cs3__BITNR 19
-#define R_PORT_PB_SET__cs3__WIDTH 1
-#define R_PORT_PB_SET__cs3__port 0
-#define R_PORT_PB_SET__cs3__cs 1
-#define R_PORT_PB_SET__cs2__BITNR 18
-#define R_PORT_PB_SET__cs2__WIDTH 1
-#define R_PORT_PB_SET__cs2__port 0
-#define R_PORT_PB_SET__cs2__cs 1
-#define R_PORT_PB_SET__scsi1__BITNR 17
-#define R_PORT_PB_SET__scsi1__WIDTH 1
-#define R_PORT_PB_SET__scsi1__port_cs 0
-#define R_PORT_PB_SET__scsi1__enph 1
-#define R_PORT_PB_SET__scsi0__BITNR 16
-#define R_PORT_PB_SET__scsi0__WIDTH 1
-#define R_PORT_PB_SET__scsi0__port_cs 0
-#define R_PORT_PB_SET__scsi0__enph 1
-#define R_PORT_PB_SET__dir7__BITNR 15
-#define R_PORT_PB_SET__dir7__WIDTH 1
-#define R_PORT_PB_SET__dir7__input 0
-#define R_PORT_PB_SET__dir7__output 1
-#define R_PORT_PB_SET__dir6__BITNR 14
-#define R_PORT_PB_SET__dir6__WIDTH 1
-#define R_PORT_PB_SET__dir6__input 0
-#define R_PORT_PB_SET__dir6__output 1
-#define R_PORT_PB_SET__dir5__BITNR 13
-#define R_PORT_PB_SET__dir5__WIDTH 1
-#define R_PORT_PB_SET__dir5__input 0
-#define R_PORT_PB_SET__dir5__output 1
-#define R_PORT_PB_SET__dir4__BITNR 12
-#define R_PORT_PB_SET__dir4__WIDTH 1
-#define R_PORT_PB_SET__dir4__input 0
-#define R_PORT_PB_SET__dir4__output 1
-#define R_PORT_PB_SET__dir3__BITNR 11
-#define R_PORT_PB_SET__dir3__WIDTH 1
-#define R_PORT_PB_SET__dir3__input 0
-#define R_PORT_PB_SET__dir3__output 1
-#define R_PORT_PB_SET__dir2__BITNR 10
-#define R_PORT_PB_SET__dir2__WIDTH 1
-#define R_PORT_PB_SET__dir2__input 0
-#define R_PORT_PB_SET__dir2__output 1
-#define R_PORT_PB_SET__dir1__BITNR 9
-#define R_PORT_PB_SET__dir1__WIDTH 1
-#define R_PORT_PB_SET__dir1__input 0
-#define R_PORT_PB_SET__dir1__output 1
-#define R_PORT_PB_SET__dir0__BITNR 8
-#define R_PORT_PB_SET__dir0__WIDTH 1
-#define R_PORT_PB_SET__dir0__input 0
-#define R_PORT_PB_SET__dir0__output 1
-#define R_PORT_PB_SET__data_out__BITNR 0
-#define R_PORT_PB_SET__data_out__WIDTH 8
-
-#define R_PORT_PB_DATA (IO_TYPECAST_BYTE 0xb0000038)
-#define R_PORT_PB_DATA__data_out__BITNR 0
-#define R_PORT_PB_DATA__data_out__WIDTH 8
-
-#define R_PORT_PB_DIR (IO_TYPECAST_BYTE 0xb0000039)
-#define R_PORT_PB_DIR__dir7__BITNR 7
-#define R_PORT_PB_DIR__dir7__WIDTH 1
-#define R_PORT_PB_DIR__dir7__input 0
-#define R_PORT_PB_DIR__dir7__output 1
-#define R_PORT_PB_DIR__dir6__BITNR 6
-#define R_PORT_PB_DIR__dir6__WIDTH 1
-#define R_PORT_PB_DIR__dir6__input 0
-#define R_PORT_PB_DIR__dir6__output 1
-#define R_PORT_PB_DIR__dir5__BITNR 5
-#define R_PORT_PB_DIR__dir5__WIDTH 1
-#define R_PORT_PB_DIR__dir5__input 0
-#define R_PORT_PB_DIR__dir5__output 1
-#define R_PORT_PB_DIR__dir4__BITNR 4
-#define R_PORT_PB_DIR__dir4__WIDTH 1
-#define R_PORT_PB_DIR__dir4__input 0
-#define R_PORT_PB_DIR__dir4__output 1
-#define R_PORT_PB_DIR__dir3__BITNR 3
-#define R_PORT_PB_DIR__dir3__WIDTH 1
-#define R_PORT_PB_DIR__dir3__input 0
-#define R_PORT_PB_DIR__dir3__output 1
-#define R_PORT_PB_DIR__dir2__BITNR 2
-#define R_PORT_PB_DIR__dir2__WIDTH 1
-#define R_PORT_PB_DIR__dir2__input 0
-#define R_PORT_PB_DIR__dir2__output 1
-#define R_PORT_PB_DIR__dir1__BITNR 1
-#define R_PORT_PB_DIR__dir1__WIDTH 1
-#define R_PORT_PB_DIR__dir1__input 0
-#define R_PORT_PB_DIR__dir1__output 1
-#define R_PORT_PB_DIR__dir0__BITNR 0
-#define R_PORT_PB_DIR__dir0__WIDTH 1
-#define R_PORT_PB_DIR__dir0__input 0
-#define R_PORT_PB_DIR__dir0__output 1
-
-#define R_PORT_PB_CONFIG (IO_TYPECAST_BYTE 0xb000003a)
-#define R_PORT_PB_CONFIG__cs7__BITNR 7
-#define R_PORT_PB_CONFIG__cs7__WIDTH 1
-#define R_PORT_PB_CONFIG__cs7__port 0
-#define R_PORT_PB_CONFIG__cs7__cs 1
-#define R_PORT_PB_CONFIG__cs6__BITNR 6
-#define R_PORT_PB_CONFIG__cs6__WIDTH 1
-#define R_PORT_PB_CONFIG__cs6__port 0
-#define R_PORT_PB_CONFIG__cs6__cs 1
-#define R_PORT_PB_CONFIG__cs5__BITNR 5
-#define R_PORT_PB_CONFIG__cs5__WIDTH 1
-#define R_PORT_PB_CONFIG__cs5__port 0
-#define R_PORT_PB_CONFIG__cs5__cs 1
-#define R_PORT_PB_CONFIG__cs4__BITNR 4
-#define R_PORT_PB_CONFIG__cs4__WIDTH 1
-#define R_PORT_PB_CONFIG__cs4__port 0
-#define R_PORT_PB_CONFIG__cs4__cs 1
-#define R_PORT_PB_CONFIG__cs3__BITNR 3
-#define R_PORT_PB_CONFIG__cs3__WIDTH 1
-#define R_PORT_PB_CONFIG__cs3__port 0
-#define R_PORT_PB_CONFIG__cs3__cs 1
-#define R_PORT_PB_CONFIG__cs2__BITNR 2
-#define R_PORT_PB_CONFIG__cs2__WIDTH 1
-#define R_PORT_PB_CONFIG__cs2__port 0
-#define R_PORT_PB_CONFIG__cs2__cs 1
-#define R_PORT_PB_CONFIG__scsi1__BITNR 1
-#define R_PORT_PB_CONFIG__scsi1__WIDTH 1
-#define R_PORT_PB_CONFIG__scsi1__port_cs 0
-#define R_PORT_PB_CONFIG__scsi1__enph 1
-#define R_PORT_PB_CONFIG__scsi0__BITNR 0
-#define R_PORT_PB_CONFIG__scsi0__WIDTH 1
-#define R_PORT_PB_CONFIG__scsi0__port_cs 0
-#define R_PORT_PB_CONFIG__scsi0__enph 1
-
-#define R_PORT_PB_I2C (IO_TYPECAST_BYTE 0xb000003b)
-#define R_PORT_PB_I2C__syncser3__BITNR 5
-#define R_PORT_PB_I2C__syncser3__WIDTH 1
-#define R_PORT_PB_I2C__syncser3__port_cs 0
-#define R_PORT_PB_I2C__syncser3__ss3extra 1
-#define R_PORT_PB_I2C__syncser1__BITNR 4
-#define R_PORT_PB_I2C__syncser1__WIDTH 1
-#define R_PORT_PB_I2C__syncser1__port_cs 0
-#define R_PORT_PB_I2C__syncser1__ss1extra 1
-#define R_PORT_PB_I2C__i2c_en__BITNR 3
-#define R_PORT_PB_I2C__i2c_en__WIDTH 1
-#define R_PORT_PB_I2C__i2c_en__off 0
-#define R_PORT_PB_I2C__i2c_en__on 1
-#define R_PORT_PB_I2C__i2c_d__BITNR 2
-#define R_PORT_PB_I2C__i2c_d__WIDTH 1
-#define R_PORT_PB_I2C__i2c_clk__BITNR 1
-#define R_PORT_PB_I2C__i2c_clk__WIDTH 1
-#define R_PORT_PB_I2C__i2c_oe___BITNR 0
-#define R_PORT_PB_I2C__i2c_oe___WIDTH 1
-#define R_PORT_PB_I2C__i2c_oe___enable 0
-#define R_PORT_PB_I2C__i2c_oe___disable 1
-
-#define R_PORT_PB_READ (IO_TYPECAST_RO_UDWORD 0xb0000038)
-#define R_PORT_PB_READ__data_in__BITNR 0
-#define R_PORT_PB_READ__data_in__WIDTH 8
-
-/*
-!* Serial port registers
-!*/
-
-#define R_SERIAL0_CTRL (IO_TYPECAST_UDWORD 0xb0000060)
-#define R_SERIAL0_CTRL__tr_baud__BITNR 28
-#define R_SERIAL0_CTRL__tr_baud__WIDTH 4
-#define R_SERIAL0_CTRL__tr_baud__c300Hz 0
-#define R_SERIAL0_CTRL__tr_baud__c600Hz 1
-#define R_SERIAL0_CTRL__tr_baud__c1200Hz 2
-#define R_SERIAL0_CTRL__tr_baud__c2400Hz 3
-#define R_SERIAL0_CTRL__tr_baud__c4800Hz 4
-#define R_SERIAL0_CTRL__tr_baud__c9600Hz 5
-#define R_SERIAL0_CTRL__tr_baud__c19k2Hz 6
-#define R_SERIAL0_CTRL__tr_baud__c38k4Hz 7
-#define R_SERIAL0_CTRL__tr_baud__c57k6Hz 8
-#define R_SERIAL0_CTRL__tr_baud__c115k2Hz 9
-#define R_SERIAL0_CTRL__tr_baud__c230k4Hz 10
-#define R_SERIAL0_CTRL__tr_baud__c460k8Hz 11
-#define R_SERIAL0_CTRL__tr_baud__c921k6Hz 12
-#define R_SERIAL0_CTRL__tr_baud__c1843k2Hz 13
-#define R_SERIAL0_CTRL__tr_baud__c6250kHz 14
-#define R_SERIAL0_CTRL__tr_baud__reserved 15
-#define R_SERIAL0_CTRL__rec_baud__BITNR 24
-#define R_SERIAL0_CTRL__rec_baud__WIDTH 4
-#define R_SERIAL0_CTRL__rec_baud__c300Hz 0
-#define R_SERIAL0_CTRL__rec_baud__c600Hz 1
-#define R_SERIAL0_CTRL__rec_baud__c1200Hz 2
-#define R_SERIAL0_CTRL__rec_baud__c2400Hz 3
-#define R_SERIAL0_CTRL__rec_baud__c4800Hz 4
-#define R_SERIAL0_CTRL__rec_baud__c9600Hz 5
-#define R_SERIAL0_CTRL__rec_baud__c19k2Hz 6
-#define R_SERIAL0_CTRL__rec_baud__c38k4Hz 7
-#define R_SERIAL0_CTRL__rec_baud__c57k6Hz 8
-#define R_SERIAL0_CTRL__rec_baud__c115k2Hz 9
-#define R_SERIAL0_CTRL__rec_baud__c230k4Hz 10
-#define R_SERIAL0_CTRL__rec_baud__c460k8Hz 11
-#define R_SERIAL0_CTRL__rec_baud__c921k6Hz 12
-#define R_SERIAL0_CTRL__rec_baud__c1843k2Hz 13
-#define R_SERIAL0_CTRL__rec_baud__c6250kHz 14
-#define R_SERIAL0_CTRL__rec_baud__reserved 15
-#define R_SERIAL0_CTRL__dma_err__BITNR 23
-#define R_SERIAL0_CTRL__dma_err__WIDTH 1
-#define R_SERIAL0_CTRL__dma_err__stop 0
-#define R_SERIAL0_CTRL__dma_err__ignore 1
-#define R_SERIAL0_CTRL__rec_enable__BITNR 22
-#define R_SERIAL0_CTRL__rec_enable__WIDTH 1
-#define R_SERIAL0_CTRL__rec_enable__disable 0
-#define R_SERIAL0_CTRL__rec_enable__enable 1
-#define R_SERIAL0_CTRL__rts___BITNR 21
-#define R_SERIAL0_CTRL__rts___WIDTH 1
-#define R_SERIAL0_CTRL__rts___active 0
-#define R_SERIAL0_CTRL__rts___inactive 1
-#define R_SERIAL0_CTRL__sampling__BITNR 20
-#define R_SERIAL0_CTRL__sampling__WIDTH 1
-#define R_SERIAL0_CTRL__sampling__middle 0
-#define R_SERIAL0_CTRL__sampling__majority 1
-#define R_SERIAL0_CTRL__rec_stick_par__BITNR 19
-#define R_SERIAL0_CTRL__rec_stick_par__WIDTH 1
-#define R_SERIAL0_CTRL__rec_stick_par__normal 0
-#define R_SERIAL0_CTRL__rec_stick_par__stick 1
-#define R_SERIAL0_CTRL__rec_par__BITNR 18
-#define R_SERIAL0_CTRL__rec_par__WIDTH 1
-#define R_SERIAL0_CTRL__rec_par__even 0
-#define R_SERIAL0_CTRL__rec_par__odd 1
-#define R_SERIAL0_CTRL__rec_par_en__BITNR 17
-#define R_SERIAL0_CTRL__rec_par_en__WIDTH 1
-#define R_SERIAL0_CTRL__rec_par_en__disable 0
-#define R_SERIAL0_CTRL__rec_par_en__enable 1
-#define R_SERIAL0_CTRL__rec_bitnr__BITNR 16
-#define R_SERIAL0_CTRL__rec_bitnr__WIDTH 1
-#define R_SERIAL0_CTRL__rec_bitnr__rec_8bit 0
-#define R_SERIAL0_CTRL__rec_bitnr__rec_7bit 1
-#define R_SERIAL0_CTRL__txd__BITNR 15
-#define R_SERIAL0_CTRL__txd__WIDTH 1
-#define R_SERIAL0_CTRL__tr_enable__BITNR 14
-#define R_SERIAL0_CTRL__tr_enable__WIDTH 1
-#define R_SERIAL0_CTRL__tr_enable__disable 0
-#define R_SERIAL0_CTRL__tr_enable__enable 1
-#define R_SERIAL0_CTRL__auto_cts__BITNR 13
-#define R_SERIAL0_CTRL__auto_cts__WIDTH 1
-#define R_SERIAL0_CTRL__auto_cts__disabled 0
-#define R_SERIAL0_CTRL__auto_cts__active 1
-#define R_SERIAL0_CTRL__stop_bits__BITNR 12
-#define R_SERIAL0_CTRL__stop_bits__WIDTH 1
-#define R_SERIAL0_CTRL__stop_bits__one_bit 0
-#define R_SERIAL0_CTRL__stop_bits__two_bits 1
-#define R_SERIAL0_CTRL__tr_stick_par__BITNR 11
-#define R_SERIAL0_CTRL__tr_stick_par__WIDTH 1
-#define R_SERIAL0_CTRL__tr_stick_par__normal 0
-#define R_SERIAL0_CTRL__tr_stick_par__stick 1
-#define R_SERIAL0_CTRL__tr_par__BITNR 10
-#define R_SERIAL0_CTRL__tr_par__WIDTH 1
-#define R_SERIAL0_CTRL__tr_par__even 0
-#define R_SERIAL0_CTRL__tr_par__odd 1
-#define R_SERIAL0_CTRL__tr_par_en__BITNR 9
-#define R_SERIAL0_CTRL__tr_par_en__WIDTH 1
-#define R_SERIAL0_CTRL__tr_par_en__disable 0
-#define R_SERIAL0_CTRL__tr_par_en__enable 1
-#define R_SERIAL0_CTRL__tr_bitnr__BITNR 8
-#define R_SERIAL0_CTRL__tr_bitnr__WIDTH 1
-#define R_SERIAL0_CTRL__tr_bitnr__tr_8bit 0
-#define R_SERIAL0_CTRL__tr_bitnr__tr_7bit 1
-#define R_SERIAL0_CTRL__data_out__BITNR 0
-#define R_SERIAL0_CTRL__data_out__WIDTH 8
-
-#define R_SERIAL0_BAUD (IO_TYPECAST_BYTE 0xb0000063)
-#define R_SERIAL0_BAUD__tr_baud__BITNR 4
-#define R_SERIAL0_BAUD__tr_baud__WIDTH 4
-#define R_SERIAL0_BAUD__tr_baud__c300Hz 0
-#define R_SERIAL0_BAUD__tr_baud__c600Hz 1
-#define R_SERIAL0_BAUD__tr_baud__c1200Hz 2
-#define R_SERIAL0_BAUD__tr_baud__c2400Hz 3
-#define R_SERIAL0_BAUD__tr_baud__c4800Hz 4
-#define R_SERIAL0_BAUD__tr_baud__c9600Hz 5
-#define R_SERIAL0_BAUD__tr_baud__c19k2Hz 6
-#define R_SERIAL0_BAUD__tr_baud__c38k4Hz 7
-#define R_SERIAL0_BAUD__tr_baud__c57k6Hz 8
-#define R_SERIAL0_BAUD__tr_baud__c115k2Hz 9
-#define R_SERIAL0_BAUD__tr_baud__c230k4Hz 10
-#define R_SERIAL0_BAUD__tr_baud__c460k8Hz 11
-#define R_SERIAL0_BAUD__tr_baud__c921k6Hz 12
-#define R_SERIAL0_BAUD__tr_baud__c1843k2Hz 13
-#define R_SERIAL0_BAUD__tr_baud__c6250kHz 14
-#define R_SERIAL0_BAUD__tr_baud__reserved 15
-#define R_SERIAL0_BAUD__rec_baud__BITNR 0
-#define R_SERIAL0_BAUD__rec_baud__WIDTH 4
-#define R_SERIAL0_BAUD__rec_baud__c300Hz 0
-#define R_SERIAL0_BAUD__rec_baud__c600Hz 1
-#define R_SERIAL0_BAUD__rec_baud__c1200Hz 2
-#define R_SERIAL0_BAUD__rec_baud__c2400Hz 3
-#define R_SERIAL0_BAUD__rec_baud__c4800Hz 4
-#define R_SERIAL0_BAUD__rec_baud__c9600Hz 5
-#define R_SERIAL0_BAUD__rec_baud__c19k2Hz 6
-#define R_SERIAL0_BAUD__rec_baud__c38k4Hz 7
-#define R_SERIAL0_BAUD__rec_baud__c57k6Hz 8
-#define R_SERIAL0_BAUD__rec_baud__c115k2Hz 9
-#define R_SERIAL0_BAUD__rec_baud__c230k4Hz 10
-#define R_SERIAL0_BAUD__rec_baud__c460k8Hz 11
-#define R_SERIAL0_BAUD__rec_baud__c921k6Hz 12
-#define R_SERIAL0_BAUD__rec_baud__c1843k2Hz 13
-#define R_SERIAL0_BAUD__rec_baud__c6250kHz 14
-#define R_SERIAL0_BAUD__rec_baud__reserved 15
-
-#define R_SERIAL0_REC_CTRL (IO_TYPECAST_BYTE 0xb0000062)
-#define R_SERIAL0_REC_CTRL__dma_err__BITNR 7
-#define R_SERIAL0_REC_CTRL__dma_err__WIDTH 1
-#define R_SERIAL0_REC_CTRL__dma_err__stop 0
-#define R_SERIAL0_REC_CTRL__dma_err__ignore 1
-#define R_SERIAL0_REC_CTRL__rec_enable__BITNR 6
-#define R_SERIAL0_REC_CTRL__rec_enable__WIDTH 1
-#define R_SERIAL0_REC_CTRL__rec_enable__disable 0
-#define R_SERIAL0_REC_CTRL__rec_enable__enable 1
-#define R_SERIAL0_REC_CTRL__rts___BITNR 5
-#define R_SERIAL0_REC_CTRL__rts___WIDTH 1
-#define R_SERIAL0_REC_CTRL__rts___active 0
-#define R_SERIAL0_REC_CTRL__rts___inactive 1
-#define R_SERIAL0_REC_CTRL__sampling__BITNR 4
-#define R_SERIAL0_REC_CTRL__sampling__WIDTH 1
-#define R_SERIAL0_REC_CTRL__sampling__middle 0
-#define R_SERIAL0_REC_CTRL__sampling__majority 1
-#define R_SERIAL0_REC_CTRL__rec_stick_par__BITNR 3
-#define R_SERIAL0_REC_CTRL__rec_stick_par__WIDTH 1
-#define R_SERIAL0_REC_CTRL__rec_stick_par__normal 0
-#define R_SERIAL0_REC_CTRL__rec_stick_par__stick 1
-#define R_SERIAL0_REC_CTRL__rec_par__BITNR 2
-#define R_SERIAL0_REC_CTRL__rec_par__WIDTH 1
-#define R_SERIAL0_REC_CTRL__rec_par__even 0
-#define R_SERIAL0_REC_CTRL__rec_par__odd 1
-#define R_SERIAL0_REC_CTRL__rec_par_en__BITNR 1
-#define R_SERIAL0_REC_CTRL__rec_par_en__WIDTH 1
-#define R_SERIAL0_REC_CTRL__rec_par_en__disable 0
-#define R_SERIAL0_REC_CTRL__rec_par_en__enable 1
-#define R_SERIAL0_REC_CTRL__rec_bitnr__BITNR 0
-#define R_SERIAL0_REC_CTRL__rec_bitnr__WIDTH 1
-#define R_SERIAL0_REC_CTRL__rec_bitnr__rec_8bit 0
-#define R_SERIAL0_REC_CTRL__rec_bitnr__rec_7bit 1
-
-#define R_SERIAL0_TR_CTRL (IO_TYPECAST_BYTE 0xb0000061)
-#define R_SERIAL0_TR_CTRL__txd__BITNR 7
-#define R_SERIAL0_TR_CTRL__txd__WIDTH 1
-#define R_SERIAL0_TR_CTRL__tr_enable__BITNR 6
-#define R_SERIAL0_TR_CTRL__tr_enable__WIDTH 1
-#define R_SERIAL0_TR_CTRL__tr_enable__disable 0
-#define R_SERIAL0_TR_CTRL__tr_enable__enable 1
-#define R_SERIAL0_TR_CTRL__auto_cts__BITNR 5
-#define R_SERIAL0_TR_CTRL__auto_cts__WIDTH 1
-#define R_SERIAL0_TR_CTRL__auto_cts__disabled 0
-#define R_SERIAL0_TR_CTRL__auto_cts__active 1
-#define R_SERIAL0_TR_CTRL__stop_bits__BITNR 4
-#define R_SERIAL0_TR_CTRL__stop_bits__WIDTH 1
-#define R_SERIAL0_TR_CTRL__stop_bits__one_bit 0
-#define R_SERIAL0_TR_CTRL__stop_bits__two_bits 1
-#define R_SERIAL0_TR_CTRL__tr_stick_par__BITNR 3
-#define R_SERIAL0_TR_CTRL__tr_stick_par__WIDTH 1
-#define R_SERIAL0_TR_CTRL__tr_stick_par__normal 0
-#define R_SERIAL0_TR_CTRL__tr_stick_par__stick 1
-#define R_SERIAL0_TR_CTRL__tr_par__BITNR 2
-#define R_SERIAL0_TR_CTRL__tr_par__WIDTH 1
-#define R_SERIAL0_TR_CTRL__tr_par__even 0
-#define R_SERIAL0_TR_CTRL__tr_par__odd 1
-#define R_SERIAL0_TR_CTRL__tr_par_en__BITNR 1
-#define R_SERIAL0_TR_CTRL__tr_par_en__WIDTH 1
-#define R_SERIAL0_TR_CTRL__tr_par_en__disable 0
-#define R_SERIAL0_TR_CTRL__tr_par_en__enable 1
-#define R_SERIAL0_TR_CTRL__tr_bitnr__BITNR 0
-#define R_SERIAL0_TR_CTRL__tr_bitnr__WIDTH 1
-#define R_SERIAL0_TR_CTRL__tr_bitnr__tr_8bit 0
-#define R_SERIAL0_TR_CTRL__tr_bitnr__tr_7bit 1
-
-#define R_SERIAL0_TR_DATA (IO_TYPECAST_BYTE 0xb0000060)
-#define R_SERIAL0_TR_DATA__data_out__BITNR 0
-#define R_SERIAL0_TR_DATA__data_out__WIDTH 8
-
-#define R_SERIAL0_READ (IO_TYPECAST_RO_UDWORD 0xb0000060)
-#define R_SERIAL0_READ__xoff_detect__BITNR 15
-#define R_SERIAL0_READ__xoff_detect__WIDTH 1
-#define R_SERIAL0_READ__xoff_detect__no_xoff 0
-#define R_SERIAL0_READ__xoff_detect__xoff 1
-#define R_SERIAL0_READ__cts___BITNR 14
-#define R_SERIAL0_READ__cts___WIDTH 1
-#define R_SERIAL0_READ__cts___active 0
-#define R_SERIAL0_READ__cts___inactive 1
-#define R_SERIAL0_READ__tr_ready__BITNR 13
-#define R_SERIAL0_READ__tr_ready__WIDTH 1
-#define R_SERIAL0_READ__tr_ready__full 0
-#define R_SERIAL0_READ__tr_ready__ready 1
-#define R_SERIAL0_READ__rxd__BITNR 12
-#define R_SERIAL0_READ__rxd__WIDTH 1
-#define R_SERIAL0_READ__overrun__BITNR 11
-#define R_SERIAL0_READ__overrun__WIDTH 1
-#define R_SERIAL0_READ__overrun__no 0
-#define R_SERIAL0_READ__overrun__yes 1
-#define R_SERIAL0_READ__par_err__BITNR 10
-#define R_SERIAL0_READ__par_err__WIDTH 1
-#define R_SERIAL0_READ__par_err__no 0
-#define R_SERIAL0_READ__par_err__yes 1
-#define R_SERIAL0_READ__framing_err__BITNR 9
-#define R_SERIAL0_READ__framing_err__WIDTH 1
-#define R_SERIAL0_READ__framing_err__no 0
-#define R_SERIAL0_READ__framing_err__yes 1
-#define R_SERIAL0_READ__data_avail__BITNR 8
-#define R_SERIAL0_READ__data_avail__WIDTH 1
-#define R_SERIAL0_READ__data_avail__no 0
-#define R_SERIAL0_READ__data_avail__yes 1
-#define R_SERIAL0_READ__data_in__BITNR 0
-#define R_SERIAL0_READ__data_in__WIDTH 8
-
-#define R_SERIAL0_STATUS (IO_TYPECAST_RO_BYTE 0xb0000061)
-#define R_SERIAL0_STATUS__xoff_detect__BITNR 7
-#define R_SERIAL0_STATUS__xoff_detect__WIDTH 1
-#define R_SERIAL0_STATUS__xoff_detect__no_xoff 0
-#define R_SERIAL0_STATUS__xoff_detect__xoff 1
-#define R_SERIAL0_STATUS__cts___BITNR 6
-#define R_SERIAL0_STATUS__cts___WIDTH 1
-#define R_SERIAL0_STATUS__cts___active 0
-#define R_SERIAL0_STATUS__cts___inactive 1
-#define R_SERIAL0_STATUS__tr_ready__BITNR 5
-#define R_SERIAL0_STATUS__tr_ready__WIDTH 1
-#define R_SERIAL0_STATUS__tr_ready__full 0
-#define R_SERIAL0_STATUS__tr_ready__ready 1
-#define R_SERIAL0_STATUS__rxd__BITNR 4
-#define R_SERIAL0_STATUS__rxd__WIDTH 1
-#define R_SERIAL0_STATUS__overrun__BITNR 3
-#define R_SERIAL0_STATUS__overrun__WIDTH 1
-#define R_SERIAL0_STATUS__overrun__no 0
-#define R_SERIAL0_STATUS__overrun__yes 1
-#define R_SERIAL0_STATUS__par_err__BITNR 2
-#define R_SERIAL0_STATUS__par_err__WIDTH 1
-#define R_SERIAL0_STATUS__par_err__no 0
-#define R_SERIAL0_STATUS__par_err__yes 1
-#define R_SERIAL0_STATUS__framing_err__BITNR 1
-#define R_SERIAL0_STATUS__framing_err__WIDTH 1
-#define R_SERIAL0_STATUS__framing_err__no 0
-#define R_SERIAL0_STATUS__framing_err__yes 1
-#define R_SERIAL0_STATUS__data_avail__BITNR 0
-#define R_SERIAL0_STATUS__data_avail__WIDTH 1
-#define R_SERIAL0_STATUS__data_avail__no 0
-#define R_SERIAL0_STATUS__data_avail__yes 1
-
-#define R_SERIAL0_REC_DATA (IO_TYPECAST_RO_BYTE 0xb0000060)
-#define R_SERIAL0_REC_DATA__data_in__BITNR 0
-#define R_SERIAL0_REC_DATA__data_in__WIDTH 8
-
-#define R_SERIAL0_XOFF (IO_TYPECAST_UDWORD 0xb0000064)
-#define R_SERIAL0_XOFF__tx_stop__BITNR 9
-#define R_SERIAL0_XOFF__tx_stop__WIDTH 1
-#define R_SERIAL0_XOFF__tx_stop__enable 0
-#define R_SERIAL0_XOFF__tx_stop__stop 1
-#define R_SERIAL0_XOFF__auto_xoff__BITNR 8
-#define R_SERIAL0_XOFF__auto_xoff__WIDTH 1
-#define R_SERIAL0_XOFF__auto_xoff__disable 0
-#define R_SERIAL0_XOFF__auto_xoff__enable 1
-#define R_SERIAL0_XOFF__xoff_char__BITNR 0
-#define R_SERIAL0_XOFF__xoff_char__WIDTH 8
-
-#define R_SERIAL1_CTRL (IO_TYPECAST_UDWORD 0xb0000068)
-#define R_SERIAL1_CTRL__tr_baud__BITNR 28
-#define R_SERIAL1_CTRL__tr_baud__WIDTH 4
-#define R_SERIAL1_CTRL__tr_baud__c300Hz 0
-#define R_SERIAL1_CTRL__tr_baud__c600Hz 1
-#define R_SERIAL1_CTRL__tr_baud__c1200Hz 2
-#define R_SERIAL1_CTRL__tr_baud__c2400Hz 3
-#define R_SERIAL1_CTRL__tr_baud__c4800Hz 4
-#define R_SERIAL1_CTRL__tr_baud__c9600Hz 5
-#define R_SERIAL1_CTRL__tr_baud__c19k2Hz 6
-#define R_SERIAL1_CTRL__tr_baud__c38k4Hz 7
-#define R_SERIAL1_CTRL__tr_baud__c57k6Hz 8
-#define R_SERIAL1_CTRL__tr_baud__c115k2Hz 9
-#define R_SERIAL1_CTRL__tr_baud__c230k4Hz 10
-#define R_SERIAL1_CTRL__tr_baud__c460k8Hz 11
-#define R_SERIAL1_CTRL__tr_baud__c921k6Hz 12
-#define R_SERIAL1_CTRL__tr_baud__c1843k2Hz 13
-#define R_SERIAL1_CTRL__tr_baud__c6250kHz 14
-#define R_SERIAL1_CTRL__tr_baud__reserved 15
-#define R_SERIAL1_CTRL__rec_baud__BITNR 24
-#define R_SERIAL1_CTRL__rec_baud__WIDTH 4
-#define R_SERIAL1_CTRL__rec_baud__c300Hz 0
-#define R_SERIAL1_CTRL__rec_baud__c600Hz 1
-#define R_SERIAL1_CTRL__rec_baud__c1200Hz 2
-#define R_SERIAL1_CTRL__rec_baud__c2400Hz 3
-#define R_SERIAL1_CTRL__rec_baud__c4800Hz 4
-#define R_SERIAL1_CTRL__rec_baud__c9600Hz 5
-#define R_SERIAL1_CTRL__rec_baud__c19k2Hz 6
-#define R_SERIAL1_CTRL__rec_baud__c38k4Hz 7
-#define R_SERIAL1_CTRL__rec_baud__c57k6Hz 8
-#define R_SERIAL1_CTRL__rec_baud__c115k2Hz 9
-#define R_SERIAL1_CTRL__rec_baud__c230k4Hz 10
-#define R_SERIAL1_CTRL__rec_baud__c460k8Hz 11
-#define R_SERIAL1_CTRL__rec_baud__c921k6Hz 12
-#define R_SERIAL1_CTRL__rec_baud__c1843k2Hz 13
-#define R_SERIAL1_CTRL__rec_baud__c6250kHz 14
-#define R_SERIAL1_CTRL__rec_baud__reserved 15
-#define R_SERIAL1_CTRL__dma_err__BITNR 23
-#define R_SERIAL1_CTRL__dma_err__WIDTH 1
-#define R_SERIAL1_CTRL__dma_err__stop 0
-#define R_SERIAL1_CTRL__dma_err__ignore 1
-#define R_SERIAL1_CTRL__rec_enable__BITNR 22
-#define R_SERIAL1_CTRL__rec_enable__WIDTH 1
-#define R_SERIAL1_CTRL__rec_enable__disable 0
-#define R_SERIAL1_CTRL__rec_enable__enable 1
-#define R_SERIAL1_CTRL__rts___BITNR 21
-#define R_SERIAL1_CTRL__rts___WIDTH 1
-#define R_SERIAL1_CTRL__rts___active 0
-#define R_SERIAL1_CTRL__rts___inactive 1
-#define R_SERIAL1_CTRL__sampling__BITNR 20
-#define R_SERIAL1_CTRL__sampling__WIDTH 1
-#define R_SERIAL1_CTRL__sampling__middle 0
-#define R_SERIAL1_CTRL__sampling__majority 1
-#define R_SERIAL1_CTRL__rec_stick_par__BITNR 19
-#define R_SERIAL1_CTRL__rec_stick_par__WIDTH 1
-#define R_SERIAL1_CTRL__rec_stick_par__normal 0
-#define R_SERIAL1_CTRL__rec_stick_par__stick 1
-#define R_SERIAL1_CTRL__rec_par__BITNR 18
-#define R_SERIAL1_CTRL__rec_par__WIDTH 1
-#define R_SERIAL1_CTRL__rec_par__even 0
-#define R_SERIAL1_CTRL__rec_par__odd 1
-#define R_SERIAL1_CTRL__rec_par_en__BITNR 17
-#define R_SERIAL1_CTRL__rec_par_en__WIDTH 1
-#define R_SERIAL1_CTRL__rec_par_en__disable 0
-#define R_SERIAL1_CTRL__rec_par_en__enable 1
-#define R_SERIAL1_CTRL__rec_bitnr__BITNR 16
-#define R_SERIAL1_CTRL__rec_bitnr__WIDTH 1
-#define R_SERIAL1_CTRL__rec_bitnr__rec_8bit 0
-#define R_SERIAL1_CTRL__rec_bitnr__rec_7bit 1
-#define R_SERIAL1_CTRL__txd__BITNR 15
-#define R_SERIAL1_CTRL__txd__WIDTH 1
-#define R_SERIAL1_CTRL__tr_enable__BITNR 14
-#define R_SERIAL1_CTRL__tr_enable__WIDTH 1
-#define R_SERIAL1_CTRL__tr_enable__disable 0
-#define R_SERIAL1_CTRL__tr_enable__enable 1
-#define R_SERIAL1_CTRL__auto_cts__BITNR 13
-#define R_SERIAL1_CTRL__auto_cts__WIDTH 1
-#define R_SERIAL1_CTRL__auto_cts__disabled 0
-#define R_SERIAL1_CTRL__auto_cts__active 1
-#define R_SERIAL1_CTRL__stop_bits__BITNR 12
-#define R_SERIAL1_CTRL__stop_bits__WIDTH 1
-#define R_SERIAL1_CTRL__stop_bits__one_bit 0
-#define R_SERIAL1_CTRL__stop_bits__two_bits 1
-#define R_SERIAL1_CTRL__tr_stick_par__BITNR 11
-#define R_SERIAL1_CTRL__tr_stick_par__WIDTH 1
-#define R_SERIAL1_CTRL__tr_stick_par__normal 0
-#define R_SERIAL1_CTRL__tr_stick_par__stick 1
-#define R_SERIAL1_CTRL__tr_par__BITNR 10
-#define R_SERIAL1_CTRL__tr_par__WIDTH 1
-#define R_SERIAL1_CTRL__tr_par__even 0
-#define R_SERIAL1_CTRL__tr_par__odd 1
-#define R_SERIAL1_CTRL__tr_par_en__BITNR 9
-#define R_SERIAL1_CTRL__tr_par_en__WIDTH 1
-#define R_SERIAL1_CTRL__tr_par_en__disable 0
-#define R_SERIAL1_CTRL__tr_par_en__enable 1
-#define R_SERIAL1_CTRL__tr_bitnr__BITNR 8
-#define R_SERIAL1_CTRL__tr_bitnr__WIDTH 1
-#define R_SERIAL1_CTRL__tr_bitnr__tr_8bit 0
-#define R_SERIAL1_CTRL__tr_bitnr__tr_7bit 1
-#define R_SERIAL1_CTRL__data_out__BITNR 0
-#define R_SERIAL1_CTRL__data_out__WIDTH 8
-
-#define R_SERIAL1_BAUD (IO_TYPECAST_BYTE 0xb000006b)
-#define R_SERIAL1_BAUD__tr_baud__BITNR 4
-#define R_SERIAL1_BAUD__tr_baud__WIDTH 4
-#define R_SERIAL1_BAUD__tr_baud__c300Hz 0
-#define R_SERIAL1_BAUD__tr_baud__c600Hz 1
-#define R_SERIAL1_BAUD__tr_baud__c1200Hz 2
-#define R_SERIAL1_BAUD__tr_baud__c2400Hz 3
-#define R_SERIAL1_BAUD__tr_baud__c4800Hz 4
-#define R_SERIAL1_BAUD__tr_baud__c9600Hz 5
-#define R_SERIAL1_BAUD__tr_baud__c19k2Hz 6
-#define R_SERIAL1_BAUD__tr_baud__c38k4Hz 7
-#define R_SERIAL1_BAUD__tr_baud__c57k6Hz 8
-#define R_SERIAL1_BAUD__tr_baud__c115k2Hz 9
-#define R_SERIAL1_BAUD__tr_baud__c230k4Hz 10
-#define R_SERIAL1_BAUD__tr_baud__c460k8Hz 11
-#define R_SERIAL1_BAUD__tr_baud__c921k6Hz 12
-#define R_SERIAL1_BAUD__tr_baud__c1843k2Hz 13
-#define R_SERIAL1_BAUD__tr_baud__c6250kHz 14
-#define R_SERIAL1_BAUD__tr_baud__reserved 15
-#define R_SERIAL1_BAUD__rec_baud__BITNR 0
-#define R_SERIAL1_BAUD__rec_baud__WIDTH 4
-#define R_SERIAL1_BAUD__rec_baud__c300Hz 0
-#define R_SERIAL1_BAUD__rec_baud__c600Hz 1
-#define R_SERIAL1_BAUD__rec_baud__c1200Hz 2
-#define R_SERIAL1_BAUD__rec_baud__c2400Hz 3
-#define R_SERIAL1_BAUD__rec_baud__c4800Hz 4
-#define R_SERIAL1_BAUD__rec_baud__c9600Hz 5
-#define R_SERIAL1_BAUD__rec_baud__c19k2Hz 6
-#define R_SERIAL1_BAUD__rec_baud__c38k4Hz 7
-#define R_SERIAL1_BAUD__rec_baud__c57k6Hz 8
-#define R_SERIAL1_BAUD__rec_baud__c115k2Hz 9
-#define R_SERIAL1_BAUD__rec_baud__c230k4Hz 10
-#define R_SERIAL1_BAUD__rec_baud__c460k8Hz 11
-#define R_SERIAL1_BAUD__rec_baud__c921k6Hz 12
-#define R_SERIAL1_BAUD__rec_baud__c1843k2Hz 13
-#define R_SERIAL1_BAUD__rec_baud__c6250kHz 14
-#define R_SERIAL1_BAUD__rec_baud__reserved 15
-
-#define R_SERIAL1_REC_CTRL (IO_TYPECAST_BYTE 0xb000006a)
-#define R_SERIAL1_REC_CTRL__dma_err__BITNR 7
-#define R_SERIAL1_REC_CTRL__dma_err__WIDTH 1
-#define R_SERIAL1_REC_CTRL__dma_err__stop 0
-#define R_SERIAL1_REC_CTRL__dma_err__ignore 1
-#define R_SERIAL1_REC_CTRL__rec_enable__BITNR 6
-#define R_SERIAL1_REC_CTRL__rec_enable__WIDTH 1
-#define R_SERIAL1_REC_CTRL__rec_enable__disable 0
-#define R_SERIAL1_REC_CTRL__rec_enable__enable 1
-#define R_SERIAL1_REC_CTRL__rts___BITNR 5
-#define R_SERIAL1_REC_CTRL__rts___WIDTH 1
-#define R_SERIAL1_REC_CTRL__rts___active 0
-#define R_SERIAL1_REC_CTRL__rts___inactive 1
-#define R_SERIAL1_REC_CTRL__sampling__BITNR 4
-#define R_SERIAL1_REC_CTRL__sampling__WIDTH 1
-#define R_SERIAL1_REC_CTRL__sampling__middle 0
-#define R_SERIAL1_REC_CTRL__sampling__majority 1
-#define R_SERIAL1_REC_CTRL__rec_stick_par__BITNR 3
-#define R_SERIAL1_REC_CTRL__rec_stick_par__WIDTH 1
-#define R_SERIAL1_REC_CTRL__rec_stick_par__normal 0
-#define R_SERIAL1_REC_CTRL__rec_stick_par__stick 1
-#define R_SERIAL1_REC_CTRL__rec_par__BITNR 2
-#define R_SERIAL1_REC_CTRL__rec_par__WIDTH 1
-#define R_SERIAL1_REC_CTRL__rec_par__even 0
-#define R_SERIAL1_REC_CTRL__rec_par__odd 1
-#define R_SERIAL1_REC_CTRL__rec_par_en__BITNR 1
-#define R_SERIAL1_REC_CTRL__rec_par_en__WIDTH 1
-#define R_SERIAL1_REC_CTRL__rec_par_en__disable 0
-#define R_SERIAL1_REC_CTRL__rec_par_en__enable 1
-#define R_SERIAL1_REC_CTRL__rec_bitnr__BITNR 0
-#define R_SERIAL1_REC_CTRL__rec_bitnr__WIDTH 1
-#define R_SERIAL1_REC_CTRL__rec_bitnr__rec_8bit 0
-#define R_SERIAL1_REC_CTRL__rec_bitnr__rec_7bit 1
-
-#define R_SERIAL1_TR_CTRL (IO_TYPECAST_BYTE 0xb0000069)
-#define R_SERIAL1_TR_CTRL__txd__BITNR 7
-#define R_SERIAL1_TR_CTRL__txd__WIDTH 1
-#define R_SERIAL1_TR_CTRL__tr_enable__BITNR 6
-#define R_SERIAL1_TR_CTRL__tr_enable__WIDTH 1
-#define R_SERIAL1_TR_CTRL__tr_enable__disable 0
-#define R_SERIAL1_TR_CTRL__tr_enable__enable 1
-#define R_SERIAL1_TR_CTRL__auto_cts__BITNR 5
-#define R_SERIAL1_TR_CTRL__auto_cts__WIDTH 1
-#define R_SERIAL1_TR_CTRL__auto_cts__disabled 0
-#define R_SERIAL1_TR_CTRL__auto_cts__active 1
-#define R_SERIAL1_TR_CTRL__stop_bits__BITNR 4
-#define R_SERIAL1_TR_CTRL__stop_bits__WIDTH 1
-#define R_SERIAL1_TR_CTRL__stop_bits__one_bit 0
-#define R_SERIAL1_TR_CTRL__stop_bits__two_bits 1
-#define R_SERIAL1_TR_CTRL__tr_stick_par__BITNR 3
-#define R_SERIAL1_TR_CTRL__tr_stick_par__WIDTH 1
-#define R_SERIAL1_TR_CTRL__tr_stick_par__normal 0
-#define R_SERIAL1_TR_CTRL__tr_stick_par__stick 1
-#define R_SERIAL1_TR_CTRL__tr_par__BITNR 2
-#define R_SERIAL1_TR_CTRL__tr_par__WIDTH 1
-#define R_SERIAL1_TR_CTRL__tr_par__even 0
-#define R_SERIAL1_TR_CTRL__tr_par__odd 1
-#define R_SERIAL1_TR_CTRL__tr_par_en__BITNR 1
-#define R_SERIAL1_TR_CTRL__tr_par_en__WIDTH 1
-#define R_SERIAL1_TR_CTRL__tr_par_en__disable 0
-#define R_SERIAL1_TR_CTRL__tr_par_en__enable 1
-#define R_SERIAL1_TR_CTRL__tr_bitnr__BITNR 0
-#define R_SERIAL1_TR_CTRL__tr_bitnr__WIDTH 1
-#define R_SERIAL1_TR_CTRL__tr_bitnr__tr_8bit 0
-#define R_SERIAL1_TR_CTRL__tr_bitnr__tr_7bit 1
-
-#define R_SERIAL1_TR_DATA (IO_TYPECAST_BYTE 0xb0000068)
-#define R_SERIAL1_TR_DATA__data_out__BITNR 0
-#define R_SERIAL1_TR_DATA__data_out__WIDTH 8
-
-#define R_SERIAL1_READ (IO_TYPECAST_RO_UDWORD 0xb0000068)
-#define R_SERIAL1_READ__xoff_detect__BITNR 15
-#define R_SERIAL1_READ__xoff_detect__WIDTH 1
-#define R_SERIAL1_READ__xoff_detect__no_xoff 0
-#define R_SERIAL1_READ__xoff_detect__xoff 1
-#define R_SERIAL1_READ__cts___BITNR 14
-#define R_SERIAL1_READ__cts___WIDTH 1
-#define R_SERIAL1_READ__cts___active 0
-#define R_SERIAL1_READ__cts___inactive 1
-#define R_SERIAL1_READ__tr_ready__BITNR 13
-#define R_SERIAL1_READ__tr_ready__WIDTH 1
-#define R_SERIAL1_READ__tr_ready__full 0
-#define R_SERIAL1_READ__tr_ready__ready 1
-#define R_SERIAL1_READ__rxd__BITNR 12
-#define R_SERIAL1_READ__rxd__WIDTH 1
-#define R_SERIAL1_READ__overrun__BITNR 11
-#define R_SERIAL1_READ__overrun__WIDTH 1
-#define R_SERIAL1_READ__overrun__no 0
-#define R_SERIAL1_READ__overrun__yes 1
-#define R_SERIAL1_READ__par_err__BITNR 10
-#define R_SERIAL1_READ__par_err__WIDTH 1
-#define R_SERIAL1_READ__par_err__no 0
-#define R_SERIAL1_READ__par_err__yes 1
-#define R_SERIAL1_READ__framing_err__BITNR 9
-#define R_SERIAL1_READ__framing_err__WIDTH 1
-#define R_SERIAL1_READ__framing_err__no 0
-#define R_SERIAL1_READ__framing_err__yes 1
-#define R_SERIAL1_READ__data_avail__BITNR 8
-#define R_SERIAL1_READ__data_avail__WIDTH 1
-#define R_SERIAL1_READ__data_avail__no 0
-#define R_SERIAL1_READ__data_avail__yes 1
-#define R_SERIAL1_READ__data_in__BITNR 0
-#define R_SERIAL1_READ__data_in__WIDTH 8
-
-#define R_SERIAL1_STATUS (IO_TYPECAST_RO_BYTE 0xb0000069)
-#define R_SERIAL1_STATUS__xoff_detect__BITNR 7
-#define R_SERIAL1_STATUS__xoff_detect__WIDTH 1
-#define R_SERIAL1_STATUS__xoff_detect__no_xoff 0
-#define R_SERIAL1_STATUS__xoff_detect__xoff 1
-#define R_SERIAL1_STATUS__cts___BITNR 6
-#define R_SERIAL1_STATUS__cts___WIDTH 1
-#define R_SERIAL1_STATUS__cts___active 0
-#define R_SERIAL1_STATUS__cts___inactive 1
-#define R_SERIAL1_STATUS__tr_ready__BITNR 5
-#define R_SERIAL1_STATUS__tr_ready__WIDTH 1
-#define R_SERIAL1_STATUS__tr_ready__full 0
-#define R_SERIAL1_STATUS__tr_ready__ready 1
-#define R_SERIAL1_STATUS__rxd__BITNR 4
-#define R_SERIAL1_STATUS__rxd__WIDTH 1
-#define R_SERIAL1_STATUS__overrun__BITNR 3
-#define R_SERIAL1_STATUS__overrun__WIDTH 1
-#define R_SERIAL1_STATUS__overrun__no 0
-#define R_SERIAL1_STATUS__overrun__yes 1
-#define R_SERIAL1_STATUS__par_err__BITNR 2
-#define R_SERIAL1_STATUS__par_err__WIDTH 1
-#define R_SERIAL1_STATUS__par_err__no 0
-#define R_SERIAL1_STATUS__par_err__yes 1
-#define R_SERIAL1_STATUS__framing_err__BITNR 1
-#define R_SERIAL1_STATUS__framing_err__WIDTH 1
-#define R_SERIAL1_STATUS__framing_err__no 0
-#define R_SERIAL1_STATUS__framing_err__yes 1
-#define R_SERIAL1_STATUS__data_avail__BITNR 0
-#define R_SERIAL1_STATUS__data_avail__WIDTH 1
-#define R_SERIAL1_STATUS__data_avail__no 0
-#define R_SERIAL1_STATUS__data_avail__yes 1
-
-#define R_SERIAL1_REC_DATA (IO_TYPECAST_RO_BYTE 0xb0000068)
-#define R_SERIAL1_REC_DATA__data_in__BITNR 0
-#define R_SERIAL1_REC_DATA__data_in__WIDTH 8
-
-#define R_SERIAL1_XOFF (IO_TYPECAST_UDWORD 0xb000006c)
-#define R_SERIAL1_XOFF__tx_stop__BITNR 9
-#define R_SERIAL1_XOFF__tx_stop__WIDTH 1
-#define R_SERIAL1_XOFF__tx_stop__enable 0
-#define R_SERIAL1_XOFF__tx_stop__stop 1
-#define R_SERIAL1_XOFF__auto_xoff__BITNR 8
-#define R_SERIAL1_XOFF__auto_xoff__WIDTH 1
-#define R_SERIAL1_XOFF__auto_xoff__disable 0
-#define R_SERIAL1_XOFF__auto_xoff__enable 1
-#define R_SERIAL1_XOFF__xoff_char__BITNR 0
-#define R_SERIAL1_XOFF__xoff_char__WIDTH 8
-
-#define R_SERIAL2_CTRL (IO_TYPECAST_UDWORD 0xb0000070)
-#define R_SERIAL2_CTRL__tr_baud__BITNR 28
-#define R_SERIAL2_CTRL__tr_baud__WIDTH 4
-#define R_SERIAL2_CTRL__tr_baud__c300Hz 0
-#define R_SERIAL2_CTRL__tr_baud__c600Hz 1
-#define R_SERIAL2_CTRL__tr_baud__c1200Hz 2
-#define R_SERIAL2_CTRL__tr_baud__c2400Hz 3
-#define R_SERIAL2_CTRL__tr_baud__c4800Hz 4
-#define R_SERIAL2_CTRL__tr_baud__c9600Hz 5
-#define R_SERIAL2_CTRL__tr_baud__c19k2Hz 6
-#define R_SERIAL2_CTRL__tr_baud__c38k4Hz 7
-#define R_SERIAL2_CTRL__tr_baud__c57k6Hz 8
-#define R_SERIAL2_CTRL__tr_baud__c115k2Hz 9
-#define R_SERIAL2_CTRL__tr_baud__c230k4Hz 10
-#define R_SERIAL2_CTRL__tr_baud__c460k8Hz 11
-#define R_SERIAL2_CTRL__tr_baud__c921k6Hz 12
-#define R_SERIAL2_CTRL__tr_baud__c1843k2Hz 13
-#define R_SERIAL2_CTRL__tr_baud__c6250kHz 14
-#define R_SERIAL2_CTRL__tr_baud__reserved 15
-#define R_SERIAL2_CTRL__rec_baud__BITNR 24
-#define R_SERIAL2_CTRL__rec_baud__WIDTH 4
-#define R_SERIAL2_CTRL__rec_baud__c300Hz 0
-#define R_SERIAL2_CTRL__rec_baud__c600Hz 1
-#define R_SERIAL2_CTRL__rec_baud__c1200Hz 2
-#define R_SERIAL2_CTRL__rec_baud__c2400Hz 3
-#define R_SERIAL2_CTRL__rec_baud__c4800Hz 4
-#define R_SERIAL2_CTRL__rec_baud__c9600Hz 5
-#define R_SERIAL2_CTRL__rec_baud__c19k2Hz 6
-#define R_SERIAL2_CTRL__rec_baud__c38k4Hz 7
-#define R_SERIAL2_CTRL__rec_baud__c57k6Hz 8
-#define R_SERIAL2_CTRL__rec_baud__c115k2Hz 9
-#define R_SERIAL2_CTRL__rec_baud__c230k4Hz 10
-#define R_SERIAL2_CTRL__rec_baud__c460k8Hz 11
-#define R_SERIAL2_CTRL__rec_baud__c921k6Hz 12
-#define R_SERIAL2_CTRL__rec_baud__c1843k2Hz 13
-#define R_SERIAL2_CTRL__rec_baud__c6250kHz 14
-#define R_SERIAL2_CTRL__rec_baud__reserved 15
-#define R_SERIAL2_CTRL__dma_err__BITNR 23
-#define R_SERIAL2_CTRL__dma_err__WIDTH 1
-#define R_SERIAL2_CTRL__dma_err__stop 0
-#define R_SERIAL2_CTRL__dma_err__ignore 1
-#define R_SERIAL2_CTRL__rec_enable__BITNR 22
-#define R_SERIAL2_CTRL__rec_enable__WIDTH 1
-#define R_SERIAL2_CTRL__rec_enable__disable 0
-#define R_SERIAL2_CTRL__rec_enable__enable 1
-#define R_SERIAL2_CTRL__rts___BITNR 21
-#define R_SERIAL2_CTRL__rts___WIDTH 1
-#define R_SERIAL2_CTRL__rts___active 0
-#define R_SERIAL2_CTRL__rts___inactive 1
-#define R_SERIAL2_CTRL__sampling__BITNR 20
-#define R_SERIAL2_CTRL__sampling__WIDTH 1
-#define R_SERIAL2_CTRL__sampling__middle 0
-#define R_SERIAL2_CTRL__sampling__majority 1
-#define R_SERIAL2_CTRL__rec_stick_par__BITNR 19
-#define R_SERIAL2_CTRL__rec_stick_par__WIDTH 1
-#define R_SERIAL2_CTRL__rec_stick_par__normal 0
-#define R_SERIAL2_CTRL__rec_stick_par__stick 1
-#define R_SERIAL2_CTRL__rec_par__BITNR 18
-#define R_SERIAL2_CTRL__rec_par__WIDTH 1
-#define R_SERIAL2_CTRL__rec_par__even 0
-#define R_SERIAL2_CTRL__rec_par__odd 1
-#define R_SERIAL2_CTRL__rec_par_en__BITNR 17
-#define R_SERIAL2_CTRL__rec_par_en__WIDTH 1
-#define R_SERIAL2_CTRL__rec_par_en__disable 0
-#define R_SERIAL2_CTRL__rec_par_en__enable 1
-#define R_SERIAL2_CTRL__rec_bitnr__BITNR 16
-#define R_SERIAL2_CTRL__rec_bitnr__WIDTH 1
-#define R_SERIAL2_CTRL__rec_bitnr__rec_8bit 0
-#define R_SERIAL2_CTRL__rec_bitnr__rec_7bit 1
-#define R_SERIAL2_CTRL__txd__BITNR 15
-#define R_SERIAL2_CTRL__txd__WIDTH 1
-#define R_SERIAL2_CTRL__tr_enable__BITNR 14
-#define R_SERIAL2_CTRL__tr_enable__WIDTH 1
-#define R_SERIAL2_CTRL__tr_enable__disable 0
-#define R_SERIAL2_CTRL__tr_enable__enable 1
-#define R_SERIAL2_CTRL__auto_cts__BITNR 13
-#define R_SERIAL2_CTRL__auto_cts__WIDTH 1
-#define R_SERIAL2_CTRL__auto_cts__disabled 0
-#define R_SERIAL2_CTRL__auto_cts__active 1
-#define R_SERIAL2_CTRL__stop_bits__BITNR 12
-#define R_SERIAL2_CTRL__stop_bits__WIDTH 1
-#define R_SERIAL2_CTRL__stop_bits__one_bit 0
-#define R_SERIAL2_CTRL__stop_bits__two_bits 1
-#define R_SERIAL2_CTRL__tr_stick_par__BITNR 11
-#define R_SERIAL2_CTRL__tr_stick_par__WIDTH 1
-#define R_SERIAL2_CTRL__tr_stick_par__normal 0
-#define R_SERIAL2_CTRL__tr_stick_par__stick 1
-#define R_SERIAL2_CTRL__tr_par__BITNR 10
-#define R_SERIAL2_CTRL__tr_par__WIDTH 1
-#define R_SERIAL2_CTRL__tr_par__even 0
-#define R_SERIAL2_CTRL__tr_par__odd 1
-#define R_SERIAL2_CTRL__tr_par_en__BITNR 9
-#define R_SERIAL2_CTRL__tr_par_en__WIDTH 1
-#define R_SERIAL2_CTRL__tr_par_en__disable 0
-#define R_SERIAL2_CTRL__tr_par_en__enable 1
-#define R_SERIAL2_CTRL__tr_bitnr__BITNR 8
-#define R_SERIAL2_CTRL__tr_bitnr__WIDTH 1
-#define R_SERIAL2_CTRL__tr_bitnr__tr_8bit 0
-#define R_SERIAL2_CTRL__tr_bitnr__tr_7bit 1
-#define R_SERIAL2_CTRL__data_out__BITNR 0
-#define R_SERIAL2_CTRL__data_out__WIDTH 8
-
-#define R_SERIAL2_BAUD (IO_TYPECAST_BYTE 0xb0000073)
-#define R_SERIAL2_BAUD__tr_baud__BITNR 4
-#define R_SERIAL2_BAUD__tr_baud__WIDTH 4
-#define R_SERIAL2_BAUD__tr_baud__c300Hz 0
-#define R_SERIAL2_BAUD__tr_baud__c600Hz 1
-#define R_SERIAL2_BAUD__tr_baud__c1200Hz 2
-#define R_SERIAL2_BAUD__tr_baud__c2400Hz 3
-#define R_SERIAL2_BAUD__tr_baud__c4800Hz 4
-#define R_SERIAL2_BAUD__tr_baud__c9600Hz 5
-#define R_SERIAL2_BAUD__tr_baud__c19k2Hz 6
-#define R_SERIAL2_BAUD__tr_baud__c38k4Hz 7
-#define R_SERIAL2_BAUD__tr_baud__c57k6Hz 8
-#define R_SERIAL2_BAUD__tr_baud__c115k2Hz 9
-#define R_SERIAL2_BAUD__tr_baud__c230k4Hz 10
-#define R_SERIAL2_BAUD__tr_baud__c460k8Hz 11
-#define R_SERIAL2_BAUD__tr_baud__c921k6Hz 12
-#define R_SERIAL2_BAUD__tr_baud__c1843k2Hz 13
-#define R_SERIAL2_BAUD__tr_baud__c6250kHz 14
-#define R_SERIAL2_BAUD__tr_baud__reserved 15
-#define R_SERIAL2_BAUD__rec_baud__BITNR 0
-#define R_SERIAL2_BAUD__rec_baud__WIDTH 4
-#define R_SERIAL2_BAUD__rec_baud__c300Hz 0
-#define R_SERIAL2_BAUD__rec_baud__c600Hz 1
-#define R_SERIAL2_BAUD__rec_baud__c1200Hz 2
-#define R_SERIAL2_BAUD__rec_baud__c2400Hz 3
-#define R_SERIAL2_BAUD__rec_baud__c4800Hz 4
-#define R_SERIAL2_BAUD__rec_baud__c9600Hz 5
-#define R_SERIAL2_BAUD__rec_baud__c19k2Hz 6
-#define R_SERIAL2_BAUD__rec_baud__c38k4Hz 7
-#define R_SERIAL2_BAUD__rec_baud__c57k6Hz 8
-#define R_SERIAL2_BAUD__rec_baud__c115k2Hz 9
-#define R_SERIAL2_BAUD__rec_baud__c230k4Hz 10
-#define R_SERIAL2_BAUD__rec_baud__c460k8Hz 11
-#define R_SERIAL2_BAUD__rec_baud__c921k6Hz 12
-#define R_SERIAL2_BAUD__rec_baud__c1843k2Hz 13
-#define R_SERIAL2_BAUD__rec_baud__c6250kHz 14
-#define R_SERIAL2_BAUD__rec_baud__reserved 15
-
-#define R_SERIAL2_REC_CTRL (IO_TYPECAST_BYTE 0xb0000072)
-#define R_SERIAL2_REC_CTRL__dma_err__BITNR 7
-#define R_SERIAL2_REC_CTRL__dma_err__WIDTH 1
-#define R_SERIAL2_REC_CTRL__dma_err__stop 0
-#define R_SERIAL2_REC_CTRL__dma_err__ignore 1
-#define R_SERIAL2_REC_CTRL__rec_enable__BITNR 6
-#define R_SERIAL2_REC_CTRL__rec_enable__WIDTH 1
-#define R_SERIAL2_REC_CTRL__rec_enable__disable 0
-#define R_SERIAL2_REC_CTRL__rec_enable__enable 1
-#define R_SERIAL2_REC_CTRL__rts___BITNR 5
-#define R_SERIAL2_REC_CTRL__rts___WIDTH 1
-#define R_SERIAL2_REC_CTRL__rts___active 0
-#define R_SERIAL2_REC_CTRL__rts___inactive 1
-#define R_SERIAL2_REC_CTRL__sampling__BITNR 4
-#define R_SERIAL2_REC_CTRL__sampling__WIDTH 1
-#define R_SERIAL2_REC_CTRL__sampling__middle 0
-#define R_SERIAL2_REC_CTRL__sampling__majority 1
-#define R_SERIAL2_REC_CTRL__rec_stick_par__BITNR 3
-#define R_SERIAL2_REC_CTRL__rec_stick_par__WIDTH 1
-#define R_SERIAL2_REC_CTRL__rec_stick_par__normal 0
-#define R_SERIAL2_REC_CTRL__rec_stick_par__stick 1
-#define R_SERIAL2_REC_CTRL__rec_par__BITNR 2
-#define R_SERIAL2_REC_CTRL__rec_par__WIDTH 1
-#define R_SERIAL2_REC_CTRL__rec_par__even 0
-#define R_SERIAL2_REC_CTRL__rec_par__odd 1
-#define R_SERIAL2_REC_CTRL__rec_par_en__BITNR 1
-#define R_SERIAL2_REC_CTRL__rec_par_en__WIDTH 1
-#define R_SERIAL2_REC_CTRL__rec_par_en__disable 0
-#define R_SERIAL2_REC_CTRL__rec_par_en__enable 1
-#define R_SERIAL2_REC_CTRL__rec_bitnr__BITNR 0
-#define R_SERIAL2_REC_CTRL__rec_bitnr__WIDTH 1
-#define R_SERIAL2_REC_CTRL__rec_bitnr__rec_8bit 0
-#define R_SERIAL2_REC_CTRL__rec_bitnr__rec_7bit 1
-
-#define R_SERIAL2_TR_CTRL (IO_TYPECAST_BYTE 0xb0000071)
-#define R_SERIAL2_TR_CTRL__txd__BITNR 7
-#define R_SERIAL2_TR_CTRL__txd__WIDTH 1
-#define R_SERIAL2_TR_CTRL__tr_enable__BITNR 6
-#define R_SERIAL2_TR_CTRL__tr_enable__WIDTH 1
-#define R_SERIAL2_TR_CTRL__tr_enable__disable 0
-#define R_SERIAL2_TR_CTRL__tr_enable__enable 1
-#define R_SERIAL2_TR_CTRL__auto_cts__BITNR 5
-#define R_SERIAL2_TR_CTRL__auto_cts__WIDTH 1
-#define R_SERIAL2_TR_CTRL__auto_cts__disabled 0
-#define R_SERIAL2_TR_CTRL__auto_cts__active 1
-#define R_SERIAL2_TR_CTRL__stop_bits__BITNR 4
-#define R_SERIAL2_TR_CTRL__stop_bits__WIDTH 1
-#define R_SERIAL2_TR_CTRL__stop_bits__one_bit 0
-#define R_SERIAL2_TR_CTRL__stop_bits__two_bits 1
-#define R_SERIAL2_TR_CTRL__tr_stick_par__BITNR 3
-#define R_SERIAL2_TR_CTRL__tr_stick_par__WIDTH 1
-#define R_SERIAL2_TR_CTRL__tr_stick_par__normal 0
-#define R_SERIAL2_TR_CTRL__tr_stick_par__stick 1
-#define R_SERIAL2_TR_CTRL__tr_par__BITNR 2
-#define R_SERIAL2_TR_CTRL__tr_par__WIDTH 1
-#define R_SERIAL2_TR_CTRL__tr_par__even 0
-#define R_SERIAL2_TR_CTRL__tr_par__odd 1
-#define R_SERIAL2_TR_CTRL__tr_par_en__BITNR 1
-#define R_SERIAL2_TR_CTRL__tr_par_en__WIDTH 1
-#define R_SERIAL2_TR_CTRL__tr_par_en__disable 0
-#define R_SERIAL2_TR_CTRL__tr_par_en__enable 1
-#define R_SERIAL2_TR_CTRL__tr_bitnr__BITNR 0
-#define R_SERIAL2_TR_CTRL__tr_bitnr__WIDTH 1
-#define R_SERIAL2_TR_CTRL__tr_bitnr__tr_8bit 0
-#define R_SERIAL2_TR_CTRL__tr_bitnr__tr_7bit 1
-
-#define R_SERIAL2_TR_DATA (IO_TYPECAST_BYTE 0xb0000070)
-#define R_SERIAL2_TR_DATA__data_out__BITNR 0
-#define R_SERIAL2_TR_DATA__data_out__WIDTH 8
-
-#define R_SERIAL2_READ (IO_TYPECAST_RO_UDWORD 0xb0000070)
-#define R_SERIAL2_READ__xoff_detect__BITNR 15
-#define R_SERIAL2_READ__xoff_detect__WIDTH 1
-#define R_SERIAL2_READ__xoff_detect__no_xoff 0
-#define R_SERIAL2_READ__xoff_detect__xoff 1
-#define R_SERIAL2_READ__cts___BITNR 14
-#define R_SERIAL2_READ__cts___WIDTH 1
-#define R_SERIAL2_READ__cts___active 0
-#define R_SERIAL2_READ__cts___inactive 1
-#define R_SERIAL2_READ__tr_ready__BITNR 13
-#define R_SERIAL2_READ__tr_ready__WIDTH 1
-#define R_SERIAL2_READ__tr_ready__full 0
-#define R_SERIAL2_READ__tr_ready__ready 1
-#define R_SERIAL2_READ__rxd__BITNR 12
-#define R_SERIAL2_READ__rxd__WIDTH 1
-#define R_SERIAL2_READ__overrun__BITNR 11
-#define R_SERIAL2_READ__overrun__WIDTH 1
-#define R_SERIAL2_READ__overrun__no 0
-#define R_SERIAL2_READ__overrun__yes 1
-#define R_SERIAL2_READ__par_err__BITNR 10
-#define R_SERIAL2_READ__par_err__WIDTH 1
-#define R_SERIAL2_READ__par_err__no 0
-#define R_SERIAL2_READ__par_err__yes 1
-#define R_SERIAL2_READ__framing_err__BITNR 9
-#define R_SERIAL2_READ__framing_err__WIDTH 1
-#define R_SERIAL2_READ__framing_err__no 0
-#define R_SERIAL2_READ__framing_err__yes 1
-#define R_SERIAL2_READ__data_avail__BITNR 8
-#define R_SERIAL2_READ__data_avail__WIDTH 1
-#define R_SERIAL2_READ__data_avail__no 0
-#define R_SERIAL2_READ__data_avail__yes 1
-#define R_SERIAL2_READ__data_in__BITNR 0
-#define R_SERIAL2_READ__data_in__WIDTH 8
-
-#define R_SERIAL2_STATUS (IO_TYPECAST_RO_BYTE 0xb0000071)
-#define R_SERIAL2_STATUS__xoff_detect__BITNR 7
-#define R_SERIAL2_STATUS__xoff_detect__WIDTH 1
-#define R_SERIAL2_STATUS__xoff_detect__no_xoff 0
-#define R_SERIAL2_STATUS__xoff_detect__xoff 1
-#define R_SERIAL2_STATUS__cts___BITNR 6
-#define R_SERIAL2_STATUS__cts___WIDTH 1
-#define R_SERIAL2_STATUS__cts___active 0
-#define R_SERIAL2_STATUS__cts___inactive 1
-#define R_SERIAL2_STATUS__tr_ready__BITNR 5
-#define R_SERIAL2_STATUS__tr_ready__WIDTH 1
-#define R_SERIAL2_STATUS__tr_ready__full 0
-#define R_SERIAL2_STATUS__tr_ready__ready 1
-#define R_SERIAL2_STATUS__rxd__BITNR 4
-#define R_SERIAL2_STATUS__rxd__WIDTH 1
-#define R_SERIAL2_STATUS__overrun__BITNR 3
-#define R_SERIAL2_STATUS__overrun__WIDTH 1
-#define R_SERIAL2_STATUS__overrun__no 0
-#define R_SERIAL2_STATUS__overrun__yes 1
-#define R_SERIAL2_STATUS__par_err__BITNR 2
-#define R_SERIAL2_STATUS__par_err__WIDTH 1
-#define R_SERIAL2_STATUS__par_err__no 0
-#define R_SERIAL2_STATUS__par_err__yes 1
-#define R_SERIAL2_STATUS__framing_err__BITNR 1
-#define R_SERIAL2_STATUS__framing_err__WIDTH 1
-#define R_SERIAL2_STATUS__framing_err__no 0
-#define R_SERIAL2_STATUS__framing_err__yes 1
-#define R_SERIAL2_STATUS__data_avail__BITNR 0
-#define R_SERIAL2_STATUS__data_avail__WIDTH 1
-#define R_SERIAL2_STATUS__data_avail__no 0
-#define R_SERIAL2_STATUS__data_avail__yes 1
-
-#define R_SERIAL2_REC_DATA (IO_TYPECAST_RO_BYTE 0xb0000070)
-#define R_SERIAL2_REC_DATA__data_in__BITNR 0
-#define R_SERIAL2_REC_DATA__data_in__WIDTH 8
-
-#define R_SERIAL2_XOFF (IO_TYPECAST_UDWORD 0xb0000074)
-#define R_SERIAL2_XOFF__tx_stop__BITNR 9
-#define R_SERIAL2_XOFF__tx_stop__WIDTH 1
-#define R_SERIAL2_XOFF__tx_stop__enable 0
-#define R_SERIAL2_XOFF__tx_stop__stop 1
-#define R_SERIAL2_XOFF__auto_xoff__BITNR 8
-#define R_SERIAL2_XOFF__auto_xoff__WIDTH 1
-#define R_SERIAL2_XOFF__auto_xoff__disable 0
-#define R_SERIAL2_XOFF__auto_xoff__enable 1
-#define R_SERIAL2_XOFF__xoff_char__BITNR 0
-#define R_SERIAL2_XOFF__xoff_char__WIDTH 8
-
-#define R_SERIAL3_CTRL (IO_TYPECAST_UDWORD 0xb0000078)
-#define R_SERIAL3_CTRL__tr_baud__BITNR 28
-#define R_SERIAL3_CTRL__tr_baud__WIDTH 4
-#define R_SERIAL3_CTRL__tr_baud__c300Hz 0
-#define R_SERIAL3_CTRL__tr_baud__c600Hz 1
-#define R_SERIAL3_CTRL__tr_baud__c1200Hz 2
-#define R_SERIAL3_CTRL__tr_baud__c2400Hz 3
-#define R_SERIAL3_CTRL__tr_baud__c4800Hz 4
-#define R_SERIAL3_CTRL__tr_baud__c9600Hz 5
-#define R_SERIAL3_CTRL__tr_baud__c19k2Hz 6
-#define R_SERIAL3_CTRL__tr_baud__c38k4Hz 7
-#define R_SERIAL3_CTRL__tr_baud__c57k6Hz 8
-#define R_SERIAL3_CTRL__tr_baud__c115k2Hz 9
-#define R_SERIAL3_CTRL__tr_baud__c230k4Hz 10
-#define R_SERIAL3_CTRL__tr_baud__c460k8Hz 11
-#define R_SERIAL3_CTRL__tr_baud__c921k6Hz 12
-#define R_SERIAL3_CTRL__tr_baud__c1843k2Hz 13
-#define R_SERIAL3_CTRL__tr_baud__c6250kHz 14
-#define R_SERIAL3_CTRL__tr_baud__reserved 15
-#define R_SERIAL3_CTRL__rec_baud__BITNR 24
-#define R_SERIAL3_CTRL__rec_baud__WIDTH 4
-#define R_SERIAL3_CTRL__rec_baud__c300Hz 0
-#define R_SERIAL3_CTRL__rec_baud__c600Hz 1
-#define R_SERIAL3_CTRL__rec_baud__c1200Hz 2
-#define R_SERIAL3_CTRL__rec_baud__c2400Hz 3
-#define R_SERIAL3_CTRL__rec_baud__c4800Hz 4
-#define R_SERIAL3_CTRL__rec_baud__c9600Hz 5
-#define R_SERIAL3_CTRL__rec_baud__c19k2Hz 6
-#define R_SERIAL3_CTRL__rec_baud__c38k4Hz 7
-#define R_SERIAL3_CTRL__rec_baud__c57k6Hz 8
-#define R_SERIAL3_CTRL__rec_baud__c115k2Hz 9
-#define R_SERIAL3_CTRL__rec_baud__c230k4Hz 10
-#define R_SERIAL3_CTRL__rec_baud__c460k8Hz 11
-#define R_SERIAL3_CTRL__rec_baud__c921k6Hz 12
-#define R_SERIAL3_CTRL__rec_baud__c1843k2Hz 13
-#define R_SERIAL3_CTRL__rec_baud__c6250kHz 14
-#define R_SERIAL3_CTRL__rec_baud__reserved 15
-#define R_SERIAL3_CTRL__dma_err__BITNR 23
-#define R_SERIAL3_CTRL__dma_err__WIDTH 1
-#define R_SERIAL3_CTRL__dma_err__stop 0
-#define R_SERIAL3_CTRL__dma_err__ignore 1
-#define R_SERIAL3_CTRL__rec_enable__BITNR 22
-#define R_SERIAL3_CTRL__rec_enable__WIDTH 1
-#define R_SERIAL3_CTRL__rec_enable__disable 0
-#define R_SERIAL3_CTRL__rec_enable__enable 1
-#define R_SERIAL3_CTRL__rts___BITNR 21
-#define R_SERIAL3_CTRL__rts___WIDTH 1
-#define R_SERIAL3_CTRL__rts___active 0
-#define R_SERIAL3_CTRL__rts___inactive 1
-#define R_SERIAL3_CTRL__sampling__BITNR 20
-#define R_SERIAL3_CTRL__sampling__WIDTH 1
-#define R_SERIAL3_CTRL__sampling__middle 0
-#define R_SERIAL3_CTRL__sampling__majority 1
-#define R_SERIAL3_CTRL__rec_stick_par__BITNR 19
-#define R_SERIAL3_CTRL__rec_stick_par__WIDTH 1
-#define R_SERIAL3_CTRL__rec_stick_par__normal 0
-#define R_SERIAL3_CTRL__rec_stick_par__stick 1
-#define R_SERIAL3_CTRL__rec_par__BITNR 18
-#define R_SERIAL3_CTRL__rec_par__WIDTH 1
-#define R_SERIAL3_CTRL__rec_par__even 0
-#define R_SERIAL3_CTRL__rec_par__odd 1
-#define R_SERIAL3_CTRL__rec_par_en__BITNR 17
-#define R_SERIAL3_CTRL__rec_par_en__WIDTH 1
-#define R_SERIAL3_CTRL__rec_par_en__disable 0
-#define R_SERIAL3_CTRL__rec_par_en__enable 1
-#define R_SERIAL3_CTRL__rec_bitnr__BITNR 16
-#define R_SERIAL3_CTRL__rec_bitnr__WIDTH 1
-#define R_SERIAL3_CTRL__rec_bitnr__rec_8bit 0
-#define R_SERIAL3_CTRL__rec_bitnr__rec_7bit 1
-#define R_SERIAL3_CTRL__txd__BITNR 15
-#define R_SERIAL3_CTRL__txd__WIDTH 1
-#define R_SERIAL3_CTRL__tr_enable__BITNR 14
-#define R_SERIAL3_CTRL__tr_enable__WIDTH 1
-#define R_SERIAL3_CTRL__tr_enable__disable 0
-#define R_SERIAL3_CTRL__tr_enable__enable 1
-#define R_SERIAL3_CTRL__auto_cts__BITNR 13
-#define R_SERIAL3_CTRL__auto_cts__WIDTH 1
-#define R_SERIAL3_CTRL__auto_cts__disabled 0
-#define R_SERIAL3_CTRL__auto_cts__active 1
-#define R_SERIAL3_CTRL__stop_bits__BITNR 12
-#define R_SERIAL3_CTRL__stop_bits__WIDTH 1
-#define R_SERIAL3_CTRL__stop_bits__one_bit 0
-#define R_SERIAL3_CTRL__stop_bits__two_bits 1
-#define R_SERIAL3_CTRL__tr_stick_par__BITNR 11
-#define R_SERIAL3_CTRL__tr_stick_par__WIDTH 1
-#define R_SERIAL3_CTRL__tr_stick_par__normal 0
-#define R_SERIAL3_CTRL__tr_stick_par__stick 1
-#define R_SERIAL3_CTRL__tr_par__BITNR 10
-#define R_SERIAL3_CTRL__tr_par__WIDTH 1
-#define R_SERIAL3_CTRL__tr_par__even 0
-#define R_SERIAL3_CTRL__tr_par__odd 1
-#define R_SERIAL3_CTRL__tr_par_en__BITNR 9
-#define R_SERIAL3_CTRL__tr_par_en__WIDTH 1
-#define R_SERIAL3_CTRL__tr_par_en__disable 0
-#define R_SERIAL3_CTRL__tr_par_en__enable 1
-#define R_SERIAL3_CTRL__tr_bitnr__BITNR 8
-#define R_SERIAL3_CTRL__tr_bitnr__WIDTH 1
-#define R_SERIAL3_CTRL__tr_bitnr__tr_8bit 0
-#define R_SERIAL3_CTRL__tr_bitnr__tr_7bit 1
-#define R_SERIAL3_CTRL__data_out__BITNR 0
-#define R_SERIAL3_CTRL__data_out__WIDTH 8
-
-#define R_SERIAL3_BAUD (IO_TYPECAST_BYTE 0xb000007b)
-#define R_SERIAL3_BAUD__tr_baud__BITNR 4
-#define R_SERIAL3_BAUD__tr_baud__WIDTH 4
-#define R_SERIAL3_BAUD__tr_baud__c300Hz 0
-#define R_SERIAL3_BAUD__tr_baud__c600Hz 1
-#define R_SERIAL3_BAUD__tr_baud__c1200Hz 2
-#define R_SERIAL3_BAUD__tr_baud__c2400Hz 3
-#define R_SERIAL3_BAUD__tr_baud__c4800Hz 4
-#define R_SERIAL3_BAUD__tr_baud__c9600Hz 5
-#define R_SERIAL3_BAUD__tr_baud__c19k2Hz 6
-#define R_SERIAL3_BAUD__tr_baud__c38k4Hz 7
-#define R_SERIAL3_BAUD__tr_baud__c57k6Hz 8
-#define R_SERIAL3_BAUD__tr_baud__c115k2Hz 9
-#define R_SERIAL3_BAUD__tr_baud__c230k4Hz 10
-#define R_SERIAL3_BAUD__tr_baud__c460k8Hz 11
-#define R_SERIAL3_BAUD__tr_baud__c921k6Hz 12
-#define R_SERIAL3_BAUD__tr_baud__c1843k2Hz 13
-#define R_SERIAL3_BAUD__tr_baud__c6250kHz 14
-#define R_SERIAL3_BAUD__tr_baud__reserved 15
-#define R_SERIAL3_BAUD__rec_baud__BITNR 0
-#define R_SERIAL3_BAUD__rec_baud__WIDTH 4
-#define R_SERIAL3_BAUD__rec_baud__c300Hz 0
-#define R_SERIAL3_BAUD__rec_baud__c600Hz 1
-#define R_SERIAL3_BAUD__rec_baud__c1200Hz 2
-#define R_SERIAL3_BAUD__rec_baud__c2400Hz 3
-#define R_SERIAL3_BAUD__rec_baud__c4800Hz 4
-#define R_SERIAL3_BAUD__rec_baud__c9600Hz 5
-#define R_SERIAL3_BAUD__rec_baud__c19k2Hz 6
-#define R_SERIAL3_BAUD__rec_baud__c38k4Hz 7
-#define R_SERIAL3_BAUD__rec_baud__c57k6Hz 8
-#define R_SERIAL3_BAUD__rec_baud__c115k2Hz 9
-#define R_SERIAL3_BAUD__rec_baud__c230k4Hz 10
-#define R_SERIAL3_BAUD__rec_baud__c460k8Hz 11
-#define R_SERIAL3_BAUD__rec_baud__c921k6Hz 12
-#define R_SERIAL3_BAUD__rec_baud__c1843k2Hz 13
-#define R_SERIAL3_BAUD__rec_baud__c6250kHz 14
-#define R_SERIAL3_BAUD__rec_baud__reserved 15
-
-#define R_SERIAL3_REC_CTRL (IO_TYPECAST_BYTE 0xb000007a)
-#define R_SERIAL3_REC_CTRL__dma_err__BITNR 7
-#define R_SERIAL3_REC_CTRL__dma_err__WIDTH 1
-#define R_SERIAL3_REC_CTRL__dma_err__stop 0
-#define R_SERIAL3_REC_CTRL__dma_err__ignore 1
-#define R_SERIAL3_REC_CTRL__rec_enable__BITNR 6
-#define R_SERIAL3_REC_CTRL__rec_enable__WIDTH 1
-#define R_SERIAL3_REC_CTRL__rec_enable__disable 0
-#define R_SERIAL3_REC_CTRL__rec_enable__enable 1
-#define R_SERIAL3_REC_CTRL__rts___BITNR 5
-#define R_SERIAL3_REC_CTRL__rts___WIDTH 1
-#define R_SERIAL3_REC_CTRL__rts___active 0
-#define R_SERIAL3_REC_CTRL__rts___inactive 1
-#define R_SERIAL3_REC_CTRL__sampling__BITNR 4
-#define R_SERIAL3_REC_CTRL__sampling__WIDTH 1
-#define R_SERIAL3_REC_CTRL__sampling__middle 0
-#define R_SERIAL3_REC_CTRL__sampling__majority 1
-#define R_SERIAL3_REC_CTRL__rec_stick_par__BITNR 3
-#define R_SERIAL3_REC_CTRL__rec_stick_par__WIDTH 1
-#define R_SERIAL3_REC_CTRL__rec_stick_par__normal 0
-#define R_SERIAL3_REC_CTRL__rec_stick_par__stick 1
-#define R_SERIAL3_REC_CTRL__rec_par__BITNR 2
-#define R_SERIAL3_REC_CTRL__rec_par__WIDTH 1
-#define R_SERIAL3_REC_CTRL__rec_par__even 0
-#define R_SERIAL3_REC_CTRL__rec_par__odd 1
-#define R_SERIAL3_REC_CTRL__rec_par_en__BITNR 1
-#define R_SERIAL3_REC_CTRL__rec_par_en__WIDTH 1
-#define R_SERIAL3_REC_CTRL__rec_par_en__disable 0
-#define R_SERIAL3_REC_CTRL__rec_par_en__enable 1
-#define R_SERIAL3_REC_CTRL__rec_bitnr__BITNR 0
-#define R_SERIAL3_REC_CTRL__rec_bitnr__WIDTH 1
-#define R_SERIAL3_REC_CTRL__rec_bitnr__rec_8bit 0
-#define R_SERIAL3_REC_CTRL__rec_bitnr__rec_7bit 1
-
-#define R_SERIAL3_TR_CTRL (IO_TYPECAST_BYTE 0xb0000079)
-#define R_SERIAL3_TR_CTRL__txd__BITNR 7
-#define R_SERIAL3_TR_CTRL__txd__WIDTH 1
-#define R_SERIAL3_TR_CTRL__tr_enable__BITNR 6
-#define R_SERIAL3_TR_CTRL__tr_enable__WIDTH 1
-#define R_SERIAL3_TR_CTRL__tr_enable__disable 0
-#define R_SERIAL3_TR_CTRL__tr_enable__enable 1
-#define R_SERIAL3_TR_CTRL__auto_cts__BITNR 5
-#define R_SERIAL3_TR_CTRL__auto_cts__WIDTH 1
-#define R_SERIAL3_TR_CTRL__auto_cts__disabled 0
-#define R_SERIAL3_TR_CTRL__auto_cts__active 1
-#define R_SERIAL3_TR_CTRL__stop_bits__BITNR 4
-#define R_SERIAL3_TR_CTRL__stop_bits__WIDTH 1
-#define R_SERIAL3_TR_CTRL__stop_bits__one_bit 0
-#define R_SERIAL3_TR_CTRL__stop_bits__two_bits 1
-#define R_SERIAL3_TR_CTRL__tr_stick_par__BITNR 3
-#define R_SERIAL3_TR_CTRL__tr_stick_par__WIDTH 1
-#define R_SERIAL3_TR_CTRL__tr_stick_par__normal 0
-#define R_SERIAL3_TR_CTRL__tr_stick_par__stick 1
-#define R_SERIAL3_TR_CTRL__tr_par__BITNR 2
-#define R_SERIAL3_TR_CTRL__tr_par__WIDTH 1
-#define R_SERIAL3_TR_CTRL__tr_par__even 0
-#define R_SERIAL3_TR_CTRL__tr_par__odd 1
-#define R_SERIAL3_TR_CTRL__tr_par_en__BITNR 1
-#define R_SERIAL3_TR_CTRL__tr_par_en__WIDTH 1
-#define R_SERIAL3_TR_CTRL__tr_par_en__disable 0
-#define R_SERIAL3_TR_CTRL__tr_par_en__enable 1
-#define R_SERIAL3_TR_CTRL__tr_bitnr__BITNR 0
-#define R_SERIAL3_TR_CTRL__tr_bitnr__WIDTH 1
-#define R_SERIAL3_TR_CTRL__tr_bitnr__tr_8bit 0
-#define R_SERIAL3_TR_CTRL__tr_bitnr__tr_7bit 1
-
-#define R_SERIAL3_TR_DATA (IO_TYPECAST_BYTE 0xb0000078)
-#define R_SERIAL3_TR_DATA__data_out__BITNR 0
-#define R_SERIAL3_TR_DATA__data_out__WIDTH 8
-
-#define R_SERIAL3_READ (IO_TYPECAST_RO_UDWORD 0xb0000078)
-#define R_SERIAL3_READ__xoff_detect__BITNR 15
-#define R_SERIAL3_READ__xoff_detect__WIDTH 1
-#define R_SERIAL3_READ__xoff_detect__no_xoff 0
-#define R_SERIAL3_READ__xoff_detect__xoff 1
-#define R_SERIAL3_READ__cts___BITNR 14
-#define R_SERIAL3_READ__cts___WIDTH 1
-#define R_SERIAL3_READ__cts___active 0
-#define R_SERIAL3_READ__cts___inactive 1
-#define R_SERIAL3_READ__tr_ready__BITNR 13
-#define R_SERIAL3_READ__tr_ready__WIDTH 1
-#define R_SERIAL3_READ__tr_ready__full 0
-#define R_SERIAL3_READ__tr_ready__ready 1
-#define R_SERIAL3_READ__rxd__BITNR 12
-#define R_SERIAL3_READ__rxd__WIDTH 1
-#define R_SERIAL3_READ__overrun__BITNR 11
-#define R_SERIAL3_READ__overrun__WIDTH 1
-#define R_SERIAL3_READ__overrun__no 0
-#define R_SERIAL3_READ__overrun__yes 1
-#define R_SERIAL3_READ__par_err__BITNR 10
-#define R_SERIAL3_READ__par_err__WIDTH 1
-#define R_SERIAL3_READ__par_err__no 0
-#define R_SERIAL3_READ__par_err__yes 1
-#define R_SERIAL3_READ__framing_err__BITNR 9
-#define R_SERIAL3_READ__framing_err__WIDTH 1
-#define R_SERIAL3_READ__framing_err__no 0
-#define R_SERIAL3_READ__framing_err__yes 1
-#define R_SERIAL3_READ__data_avail__BITNR 8
-#define R_SERIAL3_READ__data_avail__WIDTH 1
-#define R_SERIAL3_READ__data_avail__no 0
-#define R_SERIAL3_READ__data_avail__yes 1
-#define R_SERIAL3_READ__data_in__BITNR 0
-#define R_SERIAL3_READ__data_in__WIDTH 8
-
-#define R_SERIAL3_STATUS (IO_TYPECAST_RO_BYTE 0xb0000079)
-#define R_SERIAL3_STATUS__xoff_detect__BITNR 7
-#define R_SERIAL3_STATUS__xoff_detect__WIDTH 1
-#define R_SERIAL3_STATUS__xoff_detect__no_xoff 0
-#define R_SERIAL3_STATUS__xoff_detect__xoff 1
-#define R_SERIAL3_STATUS__cts___BITNR 6
-#define R_SERIAL3_STATUS__cts___WIDTH 1
-#define R_SERIAL3_STATUS__cts___active 0
-#define R_SERIAL3_STATUS__cts___inactive 1
-#define R_SERIAL3_STATUS__tr_ready__BITNR 5
-#define R_SERIAL3_STATUS__tr_ready__WIDTH 1
-#define R_SERIAL3_STATUS__tr_ready__full 0
-#define R_SERIAL3_STATUS__tr_ready__ready 1
-#define R_SERIAL3_STATUS__rxd__BITNR 4
-#define R_SERIAL3_STATUS__rxd__WIDTH 1
-#define R_SERIAL3_STATUS__overrun__BITNR 3
-#define R_SERIAL3_STATUS__overrun__WIDTH 1
-#define R_SERIAL3_STATUS__overrun__no 0
-#define R_SERIAL3_STATUS__overrun__yes 1
-#define R_SERIAL3_STATUS__par_err__BITNR 2
-#define R_SERIAL3_STATUS__par_err__WIDTH 1
-#define R_SERIAL3_STATUS__par_err__no 0
-#define R_SERIAL3_STATUS__par_err__yes 1
-#define R_SERIAL3_STATUS__framing_err__BITNR 1
-#define R_SERIAL3_STATUS__framing_err__WIDTH 1
-#define R_SERIAL3_STATUS__framing_err__no 0
-#define R_SERIAL3_STATUS__framing_err__yes 1
-#define R_SERIAL3_STATUS__data_avail__BITNR 0
-#define R_SERIAL3_STATUS__data_avail__WIDTH 1
-#define R_SERIAL3_STATUS__data_avail__no 0
-#define R_SERIAL3_STATUS__data_avail__yes 1
-
-#define R_SERIAL3_REC_DATA (IO_TYPECAST_RO_BYTE 0xb0000078)
-#define R_SERIAL3_REC_DATA__data_in__BITNR 0
-#define R_SERIAL3_REC_DATA__data_in__WIDTH 8
-
-#define R_SERIAL3_XOFF (IO_TYPECAST_UDWORD 0xb000007c)
-#define R_SERIAL3_XOFF__tx_stop__BITNR 9
-#define R_SERIAL3_XOFF__tx_stop__WIDTH 1
-#define R_SERIAL3_XOFF__tx_stop__enable 0
-#define R_SERIAL3_XOFF__tx_stop__stop 1
-#define R_SERIAL3_XOFF__auto_xoff__BITNR 8
-#define R_SERIAL3_XOFF__auto_xoff__WIDTH 1
-#define R_SERIAL3_XOFF__auto_xoff__disable 0
-#define R_SERIAL3_XOFF__auto_xoff__enable 1
-#define R_SERIAL3_XOFF__xoff_char__BITNR 0
-#define R_SERIAL3_XOFF__xoff_char__WIDTH 8
-
-#define R_ALT_SER_BAUDRATE (IO_TYPECAST_UDWORD 0xb000005c)
-#define R_ALT_SER_BAUDRATE__ser3_tr__BITNR 28
-#define R_ALT_SER_BAUDRATE__ser3_tr__WIDTH 2
-#define R_ALT_SER_BAUDRATE__ser3_tr__normal 0
-#define R_ALT_SER_BAUDRATE__ser3_tr__prescale 1
-#define R_ALT_SER_BAUDRATE__ser3_tr__extern 2
-#define R_ALT_SER_BAUDRATE__ser3_tr__timer 3
-#define R_ALT_SER_BAUDRATE__ser3_rec__BITNR 24
-#define R_ALT_SER_BAUDRATE__ser3_rec__WIDTH 2
-#define R_ALT_SER_BAUDRATE__ser3_rec__normal 0
-#define R_ALT_SER_BAUDRATE__ser3_rec__prescale 1
-#define R_ALT_SER_BAUDRATE__ser3_rec__extern 2
-#define R_ALT_SER_BAUDRATE__ser3_rec__timer 3
-#define R_ALT_SER_BAUDRATE__ser2_tr__BITNR 20
-#define R_ALT_SER_BAUDRATE__ser2_tr__WIDTH 2
-#define R_ALT_SER_BAUDRATE__ser2_tr__normal 0
-#define R_ALT_SER_BAUDRATE__ser2_tr__prescale 1
-#define R_ALT_SER_BAUDRATE__ser2_tr__extern 2
-#define R_ALT_SER_BAUDRATE__ser2_tr__timer 3
-#define R_ALT_SER_BAUDRATE__ser2_rec__BITNR 16
-#define R_ALT_SER_BAUDRATE__ser2_rec__WIDTH 2
-#define R_ALT_SER_BAUDRATE__ser2_rec__normal 0
-#define R_ALT_SER_BAUDRATE__ser2_rec__prescale 1
-#define R_ALT_SER_BAUDRATE__ser2_rec__extern 2
-#define R_ALT_SER_BAUDRATE__ser2_rec__timer 3
-#define R_ALT_SER_BAUDRATE__ser1_tr__BITNR 12
-#define R_ALT_SER_BAUDRATE__ser1_tr__WIDTH 2
-#define R_ALT_SER_BAUDRATE__ser1_tr__normal 0
-#define R_ALT_SER_BAUDRATE__ser1_tr__prescale 1
-#define R_ALT_SER_BAUDRATE__ser1_tr__extern 2
-#define R_ALT_SER_BAUDRATE__ser1_tr__timer 3
-#define R_ALT_SER_BAUDRATE__ser1_rec__BITNR 8
-#define R_ALT_SER_BAUDRATE__ser1_rec__WIDTH 2
-#define R_ALT_SER_BAUDRATE__ser1_rec__normal 0
-#define R_ALT_SER_BAUDRATE__ser1_rec__prescale 1
-#define R_ALT_SER_BAUDRATE__ser1_rec__extern 2
-#define R_ALT_SER_BAUDRATE__ser1_rec__timer 3
-#define R_ALT_SER_BAUDRATE__ser0_tr__BITNR 4
-#define R_ALT_SER_BAUDRATE__ser0_tr__WIDTH 2
-#define R_ALT_SER_BAUDRATE__ser0_tr__normal 0
-#define R_ALT_SER_BAUDRATE__ser0_tr__prescale 1
-#define R_ALT_SER_BAUDRATE__ser0_tr__extern 2
-#define R_ALT_SER_BAUDRATE__ser0_tr__timer 3
-#define R_ALT_SER_BAUDRATE__ser0_rec__BITNR 0
-#define R_ALT_SER_BAUDRATE__ser0_rec__WIDTH 2
-#define R_ALT_SER_BAUDRATE__ser0_rec__normal 0
-#define R_ALT_SER_BAUDRATE__ser0_rec__prescale 1
-#define R_ALT_SER_BAUDRATE__ser0_rec__extern 2
-#define R_ALT_SER_BAUDRATE__ser0_rec__timer 3
-
-/*
-!* Network interface registers
-!*/
-
-#define R_NETWORK_SA_0 (IO_TYPECAST_UDWORD 0xb0000080)
-#define R_NETWORK_SA_0__ma0_low__BITNR 0
-#define R_NETWORK_SA_0__ma0_low__WIDTH 32
-
-#define R_NETWORK_SA_1 (IO_TYPECAST_UDWORD 0xb0000084)
-#define R_NETWORK_SA_1__ma1_low__BITNR 16
-#define R_NETWORK_SA_1__ma1_low__WIDTH 16
-#define R_NETWORK_SA_1__ma0_high__BITNR 0
-#define R_NETWORK_SA_1__ma0_high__WIDTH 16
-
-#define R_NETWORK_SA_2 (IO_TYPECAST_UDWORD 0xb0000088)
-#define R_NETWORK_SA_2__ma1_high__BITNR 0
-#define R_NETWORK_SA_2__ma1_high__WIDTH 32
-
-#define R_NETWORK_GA_0 (IO_TYPECAST_UDWORD 0xb000008c)
-#define R_NETWORK_GA_0__ga_low__BITNR 0
-#define R_NETWORK_GA_0__ga_low__WIDTH 32
-
-#define R_NETWORK_GA_1 (IO_TYPECAST_UDWORD 0xb0000090)
-#define R_NETWORK_GA_1__ga_high__BITNR 0
-#define R_NETWORK_GA_1__ga_high__WIDTH 32
-
-#define R_NETWORK_REC_CONFIG (IO_TYPECAST_UDWORD 0xb0000094)
-#define R_NETWORK_REC_CONFIG__max_size__BITNR 10
-#define R_NETWORK_REC_CONFIG__max_size__WIDTH 1
-#define R_NETWORK_REC_CONFIG__max_size__size1518 0
-#define R_NETWORK_REC_CONFIG__max_size__size1522 1
-#define R_NETWORK_REC_CONFIG__duplex__BITNR 9
-#define R_NETWORK_REC_CONFIG__duplex__WIDTH 1
-#define R_NETWORK_REC_CONFIG__duplex__full 1
-#define R_NETWORK_REC_CONFIG__duplex__half 0
-#define R_NETWORK_REC_CONFIG__bad_crc__BITNR 8
-#define R_NETWORK_REC_CONFIG__bad_crc__WIDTH 1
-#define R_NETWORK_REC_CONFIG__bad_crc__receive 1
-#define R_NETWORK_REC_CONFIG__bad_crc__discard 0
-#define R_NETWORK_REC_CONFIG__oversize__BITNR 7
-#define R_NETWORK_REC_CONFIG__oversize__WIDTH 1
-#define R_NETWORK_REC_CONFIG__oversize__receive 1
-#define R_NETWORK_REC_CONFIG__oversize__discard 0
-#define R_NETWORK_REC_CONFIG__undersize__BITNR 6
-#define R_NETWORK_REC_CONFIG__undersize__WIDTH 1
-#define R_NETWORK_REC_CONFIG__undersize__receive 1
-#define R_NETWORK_REC_CONFIG__undersize__discard 0
-#define R_NETWORK_REC_CONFIG__all_roots__BITNR 5
-#define R_NETWORK_REC_CONFIG__all_roots__WIDTH 1
-#define R_NETWORK_REC_CONFIG__all_roots__receive 1
-#define R_NETWORK_REC_CONFIG__all_roots__discard 0
-#define R_NETWORK_REC_CONFIG__tr_broadcast__BITNR 4
-#define R_NETWORK_REC_CONFIG__tr_broadcast__WIDTH 1
-#define R_NETWORK_REC_CONFIG__tr_broadcast__receive 1
-#define R_NETWORK_REC_CONFIG__tr_broadcast__discard 0
-#define R_NETWORK_REC_CONFIG__broadcast__BITNR 3
-#define R_NETWORK_REC_CONFIG__broadcast__WIDTH 1
-#define R_NETWORK_REC_CONFIG__broadcast__receive 1
-#define R_NETWORK_REC_CONFIG__broadcast__discard 0
-#define R_NETWORK_REC_CONFIG__individual__BITNR 2
-#define R_NETWORK_REC_CONFIG__individual__WIDTH 1
-#define R_NETWORK_REC_CONFIG__individual__receive 1
-#define R_NETWORK_REC_CONFIG__individual__discard 0
-#define R_NETWORK_REC_CONFIG__ma1__BITNR 1
-#define R_NETWORK_REC_CONFIG__ma1__WIDTH 1
-#define R_NETWORK_REC_CONFIG__ma1__enable 1
-#define R_NETWORK_REC_CONFIG__ma1__disable 0
-#define R_NETWORK_REC_CONFIG__ma0__BITNR 0
-#define R_NETWORK_REC_CONFIG__ma0__WIDTH 1
-#define R_NETWORK_REC_CONFIG__ma0__enable 1
-#define R_NETWORK_REC_CONFIG__ma0__disable 0
-
-#define R_NETWORK_GEN_CONFIG (IO_TYPECAST_UDWORD 0xb0000098)
-#define R_NETWORK_GEN_CONFIG__loopback__BITNR 5
-#define R_NETWORK_GEN_CONFIG__loopback__WIDTH 1
-#define R_NETWORK_GEN_CONFIG__loopback__on 1
-#define R_NETWORK_GEN_CONFIG__loopback__off 0
-#define R_NETWORK_GEN_CONFIG__frame__BITNR 4
-#define R_NETWORK_GEN_CONFIG__frame__WIDTH 1
-#define R_NETWORK_GEN_CONFIG__frame__tokenr 1
-#define R_NETWORK_GEN_CONFIG__frame__ether 0
-#define R_NETWORK_GEN_CONFIG__vg__BITNR 3
-#define R_NETWORK_GEN_CONFIG__vg__WIDTH 1
-#define R_NETWORK_GEN_CONFIG__vg__on 1
-#define R_NETWORK_GEN_CONFIG__vg__off 0
-#define R_NETWORK_GEN_CONFIG__phy__BITNR 1
-#define R_NETWORK_GEN_CONFIG__phy__WIDTH 2
-#define R_NETWORK_GEN_CONFIG__phy__sni 0
-#define R_NETWORK_GEN_CONFIG__phy__mii_clk 1
-#define R_NETWORK_GEN_CONFIG__phy__mii_err 2
-#define R_NETWORK_GEN_CONFIG__phy__mii_req 3
-#define R_NETWORK_GEN_CONFIG__enable__BITNR 0
-#define R_NETWORK_GEN_CONFIG__enable__WIDTH 1
-#define R_NETWORK_GEN_CONFIG__enable__on 1
-#define R_NETWORK_GEN_CONFIG__enable__off 0
-
-#define R_NETWORK_TR_CTRL (IO_TYPECAST_UDWORD 0xb000009c)
-#define R_NETWORK_TR_CTRL__clr_error__BITNR 8
-#define R_NETWORK_TR_CTRL__clr_error__WIDTH 1
-#define R_NETWORK_TR_CTRL__clr_error__clr 1
-#define R_NETWORK_TR_CTRL__clr_error__nop 0
-#define R_NETWORK_TR_CTRL__delay__BITNR 5
-#define R_NETWORK_TR_CTRL__delay__WIDTH 1
-#define R_NETWORK_TR_CTRL__delay__d2us 1
-#define R_NETWORK_TR_CTRL__delay__none 0
-#define R_NETWORK_TR_CTRL__cancel__BITNR 4
-#define R_NETWORK_TR_CTRL__cancel__WIDTH 1
-#define R_NETWORK_TR_CTRL__cancel__do 1
-#define R_NETWORK_TR_CTRL__cancel__dont 0
-#define R_NETWORK_TR_CTRL__cd__BITNR 3
-#define R_NETWORK_TR_CTRL__cd__WIDTH 1
-#define R_NETWORK_TR_CTRL__cd__enable 0
-#define R_NETWORK_TR_CTRL__cd__disable 1
-#define R_NETWORK_TR_CTRL__cd__ack_col 0
-#define R_NETWORK_TR_CTRL__cd__ack_crs 1
-#define R_NETWORK_TR_CTRL__retry__BITNR 2
-#define R_NETWORK_TR_CTRL__retry__WIDTH 1
-#define R_NETWORK_TR_CTRL__retry__enable 0
-#define R_NETWORK_TR_CTRL__retry__disable 1
-#define R_NETWORK_TR_CTRL__pad__BITNR 1
-#define R_NETWORK_TR_CTRL__pad__WIDTH 1
-#define R_NETWORK_TR_CTRL__pad__enable 1
-#define R_NETWORK_TR_CTRL__pad__disable 0
-#define R_NETWORK_TR_CTRL__crc__BITNR 0
-#define R_NETWORK_TR_CTRL__crc__WIDTH 1
-#define R_NETWORK_TR_CTRL__crc__enable 0
-#define R_NETWORK_TR_CTRL__crc__disable 1
-
-#define R_NETWORK_MGM_CTRL (IO_TYPECAST_UDWORD 0xb00000a0)
-#define R_NETWORK_MGM_CTRL__txd_pins__BITNR 4
-#define R_NETWORK_MGM_CTRL__txd_pins__WIDTH 4
-#define R_NETWORK_MGM_CTRL__txer_pin__BITNR 3
-#define R_NETWORK_MGM_CTRL__txer_pin__WIDTH 1
-#define R_NETWORK_MGM_CTRL__mdck__BITNR 2
-#define R_NETWORK_MGM_CTRL__mdck__WIDTH 1
-#define R_NETWORK_MGM_CTRL__mdoe__BITNR 1
-#define R_NETWORK_MGM_CTRL__mdoe__WIDTH 1
-#define R_NETWORK_MGM_CTRL__mdoe__enable 1
-#define R_NETWORK_MGM_CTRL__mdoe__disable 0
-#define R_NETWORK_MGM_CTRL__mdio__BITNR 0
-#define R_NETWORK_MGM_CTRL__mdio__WIDTH 1
-
-#define R_NETWORK_STAT (IO_TYPECAST_RO_UDWORD 0xb00000a0)
-#define R_NETWORK_STAT__rxd_pins__BITNR 4
-#define R_NETWORK_STAT__rxd_pins__WIDTH 4
-#define R_NETWORK_STAT__rxer__BITNR 3
-#define R_NETWORK_STAT__rxer__WIDTH 1
-#define R_NETWORK_STAT__underrun__BITNR 2
-#define R_NETWORK_STAT__underrun__WIDTH 1
-#define R_NETWORK_STAT__underrun__yes 1
-#define R_NETWORK_STAT__underrun__no 0
-#define R_NETWORK_STAT__exc_col__BITNR 1
-#define R_NETWORK_STAT__exc_col__WIDTH 1
-#define R_NETWORK_STAT__exc_col__yes 1
-#define R_NETWORK_STAT__exc_col__no 0
-#define R_NETWORK_STAT__mdio__BITNR 0
-#define R_NETWORK_STAT__mdio__WIDTH 1
-
-#define R_REC_COUNTERS (IO_TYPECAST_RO_UDWORD 0xb00000a4)
-#define R_REC_COUNTERS__congestion__BITNR 24
-#define R_REC_COUNTERS__congestion__WIDTH 8
-#define R_REC_COUNTERS__oversize__BITNR 16
-#define R_REC_COUNTERS__oversize__WIDTH 8
-#define R_REC_COUNTERS__alignment_error__BITNR 8
-#define R_REC_COUNTERS__alignment_error__WIDTH 8
-#define R_REC_COUNTERS__crc_error__BITNR 0
-#define R_REC_COUNTERS__crc_error__WIDTH 8
-
-#define R_TR_COUNTERS (IO_TYPECAST_RO_UDWORD 0xb00000a8)
-#define R_TR_COUNTERS__deferred__BITNR 24
-#define R_TR_COUNTERS__deferred__WIDTH 8
-#define R_TR_COUNTERS__late_col__BITNR 16
-#define R_TR_COUNTERS__late_col__WIDTH 8
-#define R_TR_COUNTERS__multiple_col__BITNR 8
-#define R_TR_COUNTERS__multiple_col__WIDTH 8
-#define R_TR_COUNTERS__single_col__BITNR 0
-#define R_TR_COUNTERS__single_col__WIDTH 8
-
-#define R_PHY_COUNTERS (IO_TYPECAST_RO_UDWORD 0xb00000ac)
-#define R_PHY_COUNTERS__sqe_test_error__BITNR 8
-#define R_PHY_COUNTERS__sqe_test_error__WIDTH 8
-#define R_PHY_COUNTERS__carrier_loss__BITNR 0
-#define R_PHY_COUNTERS__carrier_loss__WIDTH 8
-
-/*
-!* Parallel printer port registers
-!*/
-
-#define R_PAR0_CTRL_DATA (IO_TYPECAST_UDWORD 0xb0000040)
-#define R_PAR0_CTRL_DATA__peri_int__BITNR 24
-#define R_PAR0_CTRL_DATA__peri_int__WIDTH 1
-#define R_PAR0_CTRL_DATA__peri_int__ack 1
-#define R_PAR0_CTRL_DATA__peri_int__nop 0
-#define R_PAR0_CTRL_DATA__oe__BITNR 20
-#define R_PAR0_CTRL_DATA__oe__WIDTH 1
-#define R_PAR0_CTRL_DATA__oe__enable 1
-#define R_PAR0_CTRL_DATA__oe__disable 0
-#define R_PAR0_CTRL_DATA__seli__BITNR 19
-#define R_PAR0_CTRL_DATA__seli__WIDTH 1
-#define R_PAR0_CTRL_DATA__seli__active 1
-#define R_PAR0_CTRL_DATA__seli__inactive 0
-#define R_PAR0_CTRL_DATA__autofd__BITNR 18
-#define R_PAR0_CTRL_DATA__autofd__WIDTH 1
-#define R_PAR0_CTRL_DATA__autofd__active 1
-#define R_PAR0_CTRL_DATA__autofd__inactive 0
-#define R_PAR0_CTRL_DATA__strb__BITNR 17
-#define R_PAR0_CTRL_DATA__strb__WIDTH 1
-#define R_PAR0_CTRL_DATA__strb__active 1
-#define R_PAR0_CTRL_DATA__strb__inactive 0
-#define R_PAR0_CTRL_DATA__init__BITNR 16
-#define R_PAR0_CTRL_DATA__init__WIDTH 1
-#define R_PAR0_CTRL_DATA__init__active 1
-#define R_PAR0_CTRL_DATA__init__inactive 0
-#define R_PAR0_CTRL_DATA__ecp_cmd__BITNR 8
-#define R_PAR0_CTRL_DATA__ecp_cmd__WIDTH 1
-#define R_PAR0_CTRL_DATA__ecp_cmd__command 1
-#define R_PAR0_CTRL_DATA__ecp_cmd__data 0
-#define R_PAR0_CTRL_DATA__data__BITNR 0
-#define R_PAR0_CTRL_DATA__data__WIDTH 8
-
-#define R_PAR0_CTRL (IO_TYPECAST_BYTE 0xb0000042)
-#define R_PAR0_CTRL__ctrl__BITNR 0
-#define R_PAR0_CTRL__ctrl__WIDTH 5
-
-#define R_PAR0_STATUS_DATA (IO_TYPECAST_RO_UDWORD 0xb0000040)
-#define R_PAR0_STATUS_DATA__mode__BITNR 29
-#define R_PAR0_STATUS_DATA__mode__WIDTH 3
-#define R_PAR0_STATUS_DATA__mode__manual 0
-#define R_PAR0_STATUS_DATA__mode__centronics 1
-#define R_PAR0_STATUS_DATA__mode__fastbyte 2
-#define R_PAR0_STATUS_DATA__mode__nibble 3
-#define R_PAR0_STATUS_DATA__mode__byte 4
-#define R_PAR0_STATUS_DATA__mode__ecp_fwd 5
-#define R_PAR0_STATUS_DATA__mode__ecp_rev 6
-#define R_PAR0_STATUS_DATA__mode__off 7
-#define R_PAR0_STATUS_DATA__mode__epp_wr1 5
-#define R_PAR0_STATUS_DATA__mode__epp_wr2 6
-#define R_PAR0_STATUS_DATA__mode__epp_wr3 7
-#define R_PAR0_STATUS_DATA__mode__epp_rd 0
-#define R_PAR0_STATUS_DATA__perr__BITNR 28
-#define R_PAR0_STATUS_DATA__perr__WIDTH 1
-#define R_PAR0_STATUS_DATA__perr__active 1
-#define R_PAR0_STATUS_DATA__perr__inactive 0
-#define R_PAR0_STATUS_DATA__ack__BITNR 27
-#define R_PAR0_STATUS_DATA__ack__WIDTH 1
-#define R_PAR0_STATUS_DATA__ack__active 0
-#define R_PAR0_STATUS_DATA__ack__inactive 1
-#define R_PAR0_STATUS_DATA__busy__BITNR 26
-#define R_PAR0_STATUS_DATA__busy__WIDTH 1
-#define R_PAR0_STATUS_DATA__busy__active 1
-#define R_PAR0_STATUS_DATA__busy__inactive 0
-#define R_PAR0_STATUS_DATA__fault__BITNR 25
-#define R_PAR0_STATUS_DATA__fault__WIDTH 1
-#define R_PAR0_STATUS_DATA__fault__active 0
-#define R_PAR0_STATUS_DATA__fault__inactive 1
-#define R_PAR0_STATUS_DATA__sel__BITNR 24
-#define R_PAR0_STATUS_DATA__sel__WIDTH 1
-#define R_PAR0_STATUS_DATA__sel__active 1
-#define R_PAR0_STATUS_DATA__sel__inactive 0
-#define R_PAR0_STATUS_DATA__ext_mode__BITNR 23
-#define R_PAR0_STATUS_DATA__ext_mode__WIDTH 1
-#define R_PAR0_STATUS_DATA__ext_mode__enable 1
-#define R_PAR0_STATUS_DATA__ext_mode__disable 0
-#define R_PAR0_STATUS_DATA__ecp_16__BITNR 22
-#define R_PAR0_STATUS_DATA__ecp_16__WIDTH 1
-#define R_PAR0_STATUS_DATA__ecp_16__active 1
-#define R_PAR0_STATUS_DATA__ecp_16__inactive 0
-#define R_PAR0_STATUS_DATA__tr_rdy__BITNR 17
-#define R_PAR0_STATUS_DATA__tr_rdy__WIDTH 1
-#define R_PAR0_STATUS_DATA__tr_rdy__ready 1
-#define R_PAR0_STATUS_DATA__tr_rdy__busy 0
-#define R_PAR0_STATUS_DATA__dav__BITNR 16
-#define R_PAR0_STATUS_DATA__dav__WIDTH 1
-#define R_PAR0_STATUS_DATA__dav__data 1
-#define R_PAR0_STATUS_DATA__dav__nodata 0
-#define R_PAR0_STATUS_DATA__ecp_cmd__BITNR 8
-#define R_PAR0_STATUS_DATA__ecp_cmd__WIDTH 1
-#define R_PAR0_STATUS_DATA__ecp_cmd__command 1
-#define R_PAR0_STATUS_DATA__ecp_cmd__data 0
-#define R_PAR0_STATUS_DATA__data__BITNR 0
-#define R_PAR0_STATUS_DATA__data__WIDTH 8
-
-#define R_PAR0_STATUS (IO_TYPECAST_RO_UWORD 0xb0000042)
-#define R_PAR0_STATUS__mode__BITNR 13
-#define R_PAR0_STATUS__mode__WIDTH 3
-#define R_PAR0_STATUS__mode__manual 0
-#define R_PAR0_STATUS__mode__centronics 1
-#define R_PAR0_STATUS__mode__fastbyte 2
-#define R_PAR0_STATUS__mode__nibble 3
-#define R_PAR0_STATUS__mode__byte 4
-#define R_PAR0_STATUS__mode__ecp_fwd 5
-#define R_PAR0_STATUS__mode__ecp_rev 6
-#define R_PAR0_STATUS__mode__off 7
-#define R_PAR0_STATUS__mode__epp_wr1 5
-#define R_PAR0_STATUS__mode__epp_wr2 6
-#define R_PAR0_STATUS__mode__epp_wr3 7
-#define R_PAR0_STATUS__mode__epp_rd 0
-#define R_PAR0_STATUS__perr__BITNR 12
-#define R_PAR0_STATUS__perr__WIDTH 1
-#define R_PAR0_STATUS__perr__active 1
-#define R_PAR0_STATUS__perr__inactive 0
-#define R_PAR0_STATUS__ack__BITNR 11
-#define R_PAR0_STATUS__ack__WIDTH 1
-#define R_PAR0_STATUS__ack__active 0
-#define R_PAR0_STATUS__ack__inactive 1
-#define R_PAR0_STATUS__busy__BITNR 10
-#define R_PAR0_STATUS__busy__WIDTH 1
-#define R_PAR0_STATUS__busy__active 1
-#define R_PAR0_STATUS__busy__inactive 0
-#define R_PAR0_STATUS__fault__BITNR 9
-#define R_PAR0_STATUS__fault__WIDTH 1
-#define R_PAR0_STATUS__fault__active 0
-#define R_PAR0_STATUS__fault__inactive 1
-#define R_PAR0_STATUS__sel__BITNR 8
-#define R_PAR0_STATUS__sel__WIDTH 1
-#define R_PAR0_STATUS__sel__active 1
-#define R_PAR0_STATUS__sel__inactive 0
-#define R_PAR0_STATUS__ext_mode__BITNR 7
-#define R_PAR0_STATUS__ext_mode__WIDTH 1
-#define R_PAR0_STATUS__ext_mode__enable 1
-#define R_PAR0_STATUS__ext_mode__disable 0
-#define R_PAR0_STATUS__ecp_16__BITNR 6
-#define R_PAR0_STATUS__ecp_16__WIDTH 1
-#define R_PAR0_STATUS__ecp_16__active 1
-#define R_PAR0_STATUS__ecp_16__inactive 0
-#define R_PAR0_STATUS__tr_rdy__BITNR 1
-#define R_PAR0_STATUS__tr_rdy__WIDTH 1
-#define R_PAR0_STATUS__tr_rdy__ready 1
-#define R_PAR0_STATUS__tr_rdy__busy 0
-#define R_PAR0_STATUS__dav__BITNR 0
-#define R_PAR0_STATUS__dav__WIDTH 1
-#define R_PAR0_STATUS__dav__data 1
-#define R_PAR0_STATUS__dav__nodata 0
-
-#define R_PAR_ECP16_DATA (IO_TYPECAST_UWORD 0xb0000040)
-#define R_PAR_ECP16_DATA__data__BITNR 0
-#define R_PAR_ECP16_DATA__data__WIDTH 16
-
-#define R_PAR0_CONFIG (IO_TYPECAST_UDWORD 0xb0000044)
-#define R_PAR0_CONFIG__ioe__BITNR 25
-#define R_PAR0_CONFIG__ioe__WIDTH 1
-#define R_PAR0_CONFIG__ioe__inv 1
-#define R_PAR0_CONFIG__ioe__noninv 0
-#define R_PAR0_CONFIG__iseli__BITNR 24
-#define R_PAR0_CONFIG__iseli__WIDTH 1
-#define R_PAR0_CONFIG__iseli__inv 1
-#define R_PAR0_CONFIG__iseli__noninv 0
-#define R_PAR0_CONFIG__iautofd__BITNR 23
-#define R_PAR0_CONFIG__iautofd__WIDTH 1
-#define R_PAR0_CONFIG__iautofd__inv 1
-#define R_PAR0_CONFIG__iautofd__noninv 0
-#define R_PAR0_CONFIG__istrb__BITNR 22
-#define R_PAR0_CONFIG__istrb__WIDTH 1
-#define R_PAR0_CONFIG__istrb__inv 1
-#define R_PAR0_CONFIG__istrb__noninv 0
-#define R_PAR0_CONFIG__iinit__BITNR 21
-#define R_PAR0_CONFIG__iinit__WIDTH 1
-#define R_PAR0_CONFIG__iinit__inv 1
-#define R_PAR0_CONFIG__iinit__noninv 0
-#define R_PAR0_CONFIG__iperr__BITNR 20
-#define R_PAR0_CONFIG__iperr__WIDTH 1
-#define R_PAR0_CONFIG__iperr__inv 1
-#define R_PAR0_CONFIG__iperr__noninv 0
-#define R_PAR0_CONFIG__iack__BITNR 19
-#define R_PAR0_CONFIG__iack__WIDTH 1
-#define R_PAR0_CONFIG__iack__inv 1
-#define R_PAR0_CONFIG__iack__noninv 0
-#define R_PAR0_CONFIG__ibusy__BITNR 18
-#define R_PAR0_CONFIG__ibusy__WIDTH 1
-#define R_PAR0_CONFIG__ibusy__inv 1
-#define R_PAR0_CONFIG__ibusy__noninv 0
-#define R_PAR0_CONFIG__ifault__BITNR 17
-#define R_PAR0_CONFIG__ifault__WIDTH 1
-#define R_PAR0_CONFIG__ifault__inv 1
-#define R_PAR0_CONFIG__ifault__noninv 0
-#define R_PAR0_CONFIG__isel__BITNR 16
-#define R_PAR0_CONFIG__isel__WIDTH 1
-#define R_PAR0_CONFIG__isel__inv 1
-#define R_PAR0_CONFIG__isel__noninv 0
-#define R_PAR0_CONFIG__ext_mode__BITNR 11
-#define R_PAR0_CONFIG__ext_mode__WIDTH 1
-#define R_PAR0_CONFIG__ext_mode__enable 1
-#define R_PAR0_CONFIG__ext_mode__disable 0
-#define R_PAR0_CONFIG__wide__BITNR 10
-#define R_PAR0_CONFIG__wide__WIDTH 1
-#define R_PAR0_CONFIG__wide__enable 1
-#define R_PAR0_CONFIG__wide__disable 0
-#define R_PAR0_CONFIG__dma__BITNR 9
-#define R_PAR0_CONFIG__dma__WIDTH 1
-#define R_PAR0_CONFIG__dma__enable 1
-#define R_PAR0_CONFIG__dma__disable 0
-#define R_PAR0_CONFIG__rle_in__BITNR 8
-#define R_PAR0_CONFIG__rle_in__WIDTH 1
-#define R_PAR0_CONFIG__rle_in__enable 1
-#define R_PAR0_CONFIG__rle_in__disable 0
-#define R_PAR0_CONFIG__rle_out__BITNR 7
-#define R_PAR0_CONFIG__rle_out__WIDTH 1
-#define R_PAR0_CONFIG__rle_out__enable 1
-#define R_PAR0_CONFIG__rle_out__disable 0
-#define R_PAR0_CONFIG__enable__BITNR 6
-#define R_PAR0_CONFIG__enable__WIDTH 1
-#define R_PAR0_CONFIG__enable__on 1
-#define R_PAR0_CONFIG__enable__reset 0
-#define R_PAR0_CONFIG__force__BITNR 5
-#define R_PAR0_CONFIG__force__WIDTH 1
-#define R_PAR0_CONFIG__force__on 1
-#define R_PAR0_CONFIG__force__off 0
-#define R_PAR0_CONFIG__ign_ack__BITNR 4
-#define R_PAR0_CONFIG__ign_ack__WIDTH 1
-#define R_PAR0_CONFIG__ign_ack__ignore 1
-#define R_PAR0_CONFIG__ign_ack__wait 0
-#define R_PAR0_CONFIG__oe_ack__BITNR 3
-#define R_PAR0_CONFIG__oe_ack__WIDTH 1
-#define R_PAR0_CONFIG__oe_ack__wait_oe 1
-#define R_PAR0_CONFIG__oe_ack__dont_wait 0
-#define R_PAR0_CONFIG__oe_ack__epp_addr 1
-#define R_PAR0_CONFIG__oe_ack__epp_data 0
-#define R_PAR0_CONFIG__epp_addr_data__BITNR 3
-#define R_PAR0_CONFIG__epp_addr_data__WIDTH 1
-#define R_PAR0_CONFIG__epp_addr_data__wait_oe 1
-#define R_PAR0_CONFIG__epp_addr_data__dont_wait 0
-#define R_PAR0_CONFIG__epp_addr_data__epp_addr 1
-#define R_PAR0_CONFIG__epp_addr_data__epp_data 0
-#define R_PAR0_CONFIG__mode__BITNR 0
-#define R_PAR0_CONFIG__mode__WIDTH 3
-#define R_PAR0_CONFIG__mode__manual 0
-#define R_PAR0_CONFIG__mode__centronics 1
-#define R_PAR0_CONFIG__mode__fastbyte 2
-#define R_PAR0_CONFIG__mode__nibble 3
-#define R_PAR0_CONFIG__mode__byte 4
-#define R_PAR0_CONFIG__mode__ecp_fwd 5
-#define R_PAR0_CONFIG__mode__ecp_rev 6
-#define R_PAR0_CONFIG__mode__off 7
-#define R_PAR0_CONFIG__mode__epp_wr1 5
-#define R_PAR0_CONFIG__mode__epp_wr2 6
-#define R_PAR0_CONFIG__mode__epp_wr3 7
-#define R_PAR0_CONFIG__mode__epp_rd 0
-
-#define R_PAR0_DELAY (IO_TYPECAST_UDWORD 0xb0000048)
-#define R_PAR0_DELAY__fine_hold__BITNR 21
-#define R_PAR0_DELAY__fine_hold__WIDTH 3
-#define R_PAR0_DELAY__hold__BITNR 16
-#define R_PAR0_DELAY__hold__WIDTH 5
-#define R_PAR0_DELAY__fine_strb__BITNR 13
-#define R_PAR0_DELAY__fine_strb__WIDTH 3
-#define R_PAR0_DELAY__strobe__BITNR 8
-#define R_PAR0_DELAY__strobe__WIDTH 5
-#define R_PAR0_DELAY__fine_setup__BITNR 5
-#define R_PAR0_DELAY__fine_setup__WIDTH 3
-#define R_PAR0_DELAY__setup__BITNR 0
-#define R_PAR0_DELAY__setup__WIDTH 5
-
-#define R_PAR1_CTRL_DATA (IO_TYPECAST_UDWORD 0xb0000050)
-#define R_PAR1_CTRL_DATA__peri_int__BITNR 24
-#define R_PAR1_CTRL_DATA__peri_int__WIDTH 1
-#define R_PAR1_CTRL_DATA__peri_int__ack 1
-#define R_PAR1_CTRL_DATA__peri_int__nop 0
-#define R_PAR1_CTRL_DATA__oe__BITNR 20
-#define R_PAR1_CTRL_DATA__oe__WIDTH 1
-#define R_PAR1_CTRL_DATA__oe__enable 1
-#define R_PAR1_CTRL_DATA__oe__disable 0
-#define R_PAR1_CTRL_DATA__seli__BITNR 19
-#define R_PAR1_CTRL_DATA__seli__WIDTH 1
-#define R_PAR1_CTRL_DATA__seli__active 1
-#define R_PAR1_CTRL_DATA__seli__inactive 0
-#define R_PAR1_CTRL_DATA__autofd__BITNR 18
-#define R_PAR1_CTRL_DATA__autofd__WIDTH 1
-#define R_PAR1_CTRL_DATA__autofd__active 1
-#define R_PAR1_CTRL_DATA__autofd__inactive 0
-#define R_PAR1_CTRL_DATA__strb__BITNR 17
-#define R_PAR1_CTRL_DATA__strb__WIDTH 1
-#define R_PAR1_CTRL_DATA__strb__active 1
-#define R_PAR1_CTRL_DATA__strb__inactive 0
-#define R_PAR1_CTRL_DATA__init__BITNR 16
-#define R_PAR1_CTRL_DATA__init__WIDTH 1
-#define R_PAR1_CTRL_DATA__init__active 1
-#define R_PAR1_CTRL_DATA__init__inactive 0
-#define R_PAR1_CTRL_DATA__ecp_cmd__BITNR 8
-#define R_PAR1_CTRL_DATA__ecp_cmd__WIDTH 1
-#define R_PAR1_CTRL_DATA__ecp_cmd__command 1
-#define R_PAR1_CTRL_DATA__ecp_cmd__data 0
-#define R_PAR1_CTRL_DATA__data__BITNR 0
-#define R_PAR1_CTRL_DATA__data__WIDTH 8
-
-#define R_PAR1_CTRL (IO_TYPECAST_BYTE 0xb0000052)
-#define R_PAR1_CTRL__ctrl__BITNR 0
-#define R_PAR1_CTRL__ctrl__WIDTH 5
-
-#define R_PAR1_STATUS_DATA (IO_TYPECAST_RO_UDWORD 0xb0000050)
-#define R_PAR1_STATUS_DATA__mode__BITNR 29
-#define R_PAR1_STATUS_DATA__mode__WIDTH 3
-#define R_PAR1_STATUS_DATA__mode__manual 0
-#define R_PAR1_STATUS_DATA__mode__centronics 1
-#define R_PAR1_STATUS_DATA__mode__fastbyte 2
-#define R_PAR1_STATUS_DATA__mode__nibble 3
-#define R_PAR1_STATUS_DATA__mode__byte 4
-#define R_PAR1_STATUS_DATA__mode__ecp_fwd 5
-#define R_PAR1_STATUS_DATA__mode__ecp_rev 6
-#define R_PAR1_STATUS_DATA__mode__off 7
-#define R_PAR1_STATUS_DATA__mode__epp_wr1 5
-#define R_PAR1_STATUS_DATA__mode__epp_wr2 6
-#define R_PAR1_STATUS_DATA__mode__epp_wr3 7
-#define R_PAR1_STATUS_DATA__mode__epp_rd 0
-#define R_PAR1_STATUS_DATA__perr__BITNR 28
-#define R_PAR1_STATUS_DATA__perr__WIDTH 1
-#define R_PAR1_STATUS_DATA__perr__active 1
-#define R_PAR1_STATUS_DATA__perr__inactive 0
-#define R_PAR1_STATUS_DATA__ack__BITNR 27
-#define R_PAR1_STATUS_DATA__ack__WIDTH 1
-#define R_PAR1_STATUS_DATA__ack__active 0
-#define R_PAR1_STATUS_DATA__ack__inactive 1
-#define R_PAR1_STATUS_DATA__busy__BITNR 26
-#define R_PAR1_STATUS_DATA__busy__WIDTH 1
-#define R_PAR1_STATUS_DATA__busy__active 1
-#define R_PAR1_STATUS_DATA__busy__inactive 0
-#define R_PAR1_STATUS_DATA__fault__BITNR 25
-#define R_PAR1_STATUS_DATA__fault__WIDTH 1
-#define R_PAR1_STATUS_DATA__fault__active 0
-#define R_PAR1_STATUS_DATA__fault__inactive 1
-#define R_PAR1_STATUS_DATA__sel__BITNR 24
-#define R_PAR1_STATUS_DATA__sel__WIDTH 1
-#define R_PAR1_STATUS_DATA__sel__active 1
-#define R_PAR1_STATUS_DATA__sel__inactive 0
-#define R_PAR1_STATUS_DATA__ext_mode__BITNR 23
-#define R_PAR1_STATUS_DATA__ext_mode__WIDTH 1
-#define R_PAR1_STATUS_DATA__ext_mode__enable 1
-#define R_PAR1_STATUS_DATA__ext_mode__disable 0
-#define R_PAR1_STATUS_DATA__tr_rdy__BITNR 17
-#define R_PAR1_STATUS_DATA__tr_rdy__WIDTH 1
-#define R_PAR1_STATUS_DATA__tr_rdy__ready 1
-#define R_PAR1_STATUS_DATA__tr_rdy__busy 0
-#define R_PAR1_STATUS_DATA__dav__BITNR 16
-#define R_PAR1_STATUS_DATA__dav__WIDTH 1
-#define R_PAR1_STATUS_DATA__dav__data 1
-#define R_PAR1_STATUS_DATA__dav__nodata 0
-#define R_PAR1_STATUS_DATA__ecp_cmd__BITNR 8
-#define R_PAR1_STATUS_DATA__ecp_cmd__WIDTH 1
-#define R_PAR1_STATUS_DATA__ecp_cmd__command 1
-#define R_PAR1_STATUS_DATA__ecp_cmd__data 0
-#define R_PAR1_STATUS_DATA__data__BITNR 0
-#define R_PAR1_STATUS_DATA__data__WIDTH 8
-
-#define R_PAR1_STATUS (IO_TYPECAST_RO_UWORD 0xb0000052)
-#define R_PAR1_STATUS__mode__BITNR 13
-#define R_PAR1_STATUS__mode__WIDTH 3
-#define R_PAR1_STATUS__mode__manual 0
-#define R_PAR1_STATUS__mode__centronics 1
-#define R_PAR1_STATUS__mode__fastbyte 2
-#define R_PAR1_STATUS__mode__nibble 3
-#define R_PAR1_STATUS__mode__byte 4
-#define R_PAR1_STATUS__mode__ecp_fwd 5
-#define R_PAR1_STATUS__mode__ecp_rev 6
-#define R_PAR1_STATUS__mode__off 7
-#define R_PAR1_STATUS__mode__epp_wr1 5
-#define R_PAR1_STATUS__mode__epp_wr2 6
-#define R_PAR1_STATUS__mode__epp_wr3 7
-#define R_PAR1_STATUS__mode__epp_rd 0
-#define R_PAR1_STATUS__perr__BITNR 12
-#define R_PAR1_STATUS__perr__WIDTH 1
-#define R_PAR1_STATUS__perr__active 1
-#define R_PAR1_STATUS__perr__inactive 0
-#define R_PAR1_STATUS__ack__BITNR 11
-#define R_PAR1_STATUS__ack__WIDTH 1
-#define R_PAR1_STATUS__ack__active 0
-#define R_PAR1_STATUS__ack__inactive 1
-#define R_PAR1_STATUS__busy__BITNR 10
-#define R_PAR1_STATUS__busy__WIDTH 1
-#define R_PAR1_STATUS__busy__active 1
-#define R_PAR1_STATUS__busy__inactive 0
-#define R_PAR1_STATUS__fault__BITNR 9
-#define R_PAR1_STATUS__fault__WIDTH 1
-#define R_PAR1_STATUS__fault__active 0
-#define R_PAR1_STATUS__fault__inactive 1
-#define R_PAR1_STATUS__sel__BITNR 8
-#define R_PAR1_STATUS__sel__WIDTH 1
-#define R_PAR1_STATUS__sel__active 1
-#define R_PAR1_STATUS__sel__inactive 0
-#define R_PAR1_STATUS__ext_mode__BITNR 7
-#define R_PAR1_STATUS__ext_mode__WIDTH 1
-#define R_PAR1_STATUS__ext_mode__enable 1
-#define R_PAR1_STATUS__ext_mode__disable 0
-#define R_PAR1_STATUS__tr_rdy__BITNR 1
-#define R_PAR1_STATUS__tr_rdy__WIDTH 1
-#define R_PAR1_STATUS__tr_rdy__ready 1
-#define R_PAR1_STATUS__tr_rdy__busy 0
-#define R_PAR1_STATUS__dav__BITNR 0
-#define R_PAR1_STATUS__dav__WIDTH 1
-#define R_PAR1_STATUS__dav__data 1
-#define R_PAR1_STATUS__dav__nodata 0
-
-#define R_PAR1_CONFIG (IO_TYPECAST_UDWORD 0xb0000054)
-#define R_PAR1_CONFIG__ioe__BITNR 25
-#define R_PAR1_CONFIG__ioe__WIDTH 1
-#define R_PAR1_CONFIG__ioe__inv 1
-#define R_PAR1_CONFIG__ioe__noninv 0
-#define R_PAR1_CONFIG__iseli__BITNR 24
-#define R_PAR1_CONFIG__iseli__WIDTH 1
-#define R_PAR1_CONFIG__iseli__inv 1
-#define R_PAR1_CONFIG__iseli__noninv 0
-#define R_PAR1_CONFIG__iautofd__BITNR 23
-#define R_PAR1_CONFIG__iautofd__WIDTH 1
-#define R_PAR1_CONFIG__iautofd__inv 1
-#define R_PAR1_CONFIG__iautofd__noninv 0
-#define R_PAR1_CONFIG__istrb__BITNR 22
-#define R_PAR1_CONFIG__istrb__WIDTH 1
-#define R_PAR1_CONFIG__istrb__inv 1
-#define R_PAR1_CONFIG__istrb__noninv 0
-#define R_PAR1_CONFIG__iinit__BITNR 21
-#define R_PAR1_CONFIG__iinit__WIDTH 1
-#define R_PAR1_CONFIG__iinit__inv 1
-#define R_PAR1_CONFIG__iinit__noninv 0
-#define R_PAR1_CONFIG__iperr__BITNR 20
-#define R_PAR1_CONFIG__iperr__WIDTH 1
-#define R_PAR1_CONFIG__iperr__inv 1
-#define R_PAR1_CONFIG__iperr__noninv 0
-#define R_PAR1_CONFIG__iack__BITNR 19
-#define R_PAR1_CONFIG__iack__WIDTH 1
-#define R_PAR1_CONFIG__iack__inv 1
-#define R_PAR1_CONFIG__iack__noninv 0
-#define R_PAR1_CONFIG__ibusy__BITNR 18
-#define R_PAR1_CONFIG__ibusy__WIDTH 1
-#define R_PAR1_CONFIG__ibusy__inv 1
-#define R_PAR1_CONFIG__ibusy__noninv 0
-#define R_PAR1_CONFIG__ifault__BITNR 17
-#define R_PAR1_CONFIG__ifault__WIDTH 1
-#define R_PAR1_CONFIG__ifault__inv 1
-#define R_PAR1_CONFIG__ifault__noninv 0
-#define R_PAR1_CONFIG__isel__BITNR 16
-#define R_PAR1_CONFIG__isel__WIDTH 1
-#define R_PAR1_CONFIG__isel__inv 1
-#define R_PAR1_CONFIG__isel__noninv 0
-#define R_PAR1_CONFIG__ext_mode__BITNR 11
-#define R_PAR1_CONFIG__ext_mode__WIDTH 1
-#define R_PAR1_CONFIG__ext_mode__enable 1
-#define R_PAR1_CONFIG__ext_mode__disable 0
-#define R_PAR1_CONFIG__dma__BITNR 9
-#define R_PAR1_CONFIG__dma__WIDTH 1
-#define R_PAR1_CONFIG__dma__enable 1
-#define R_PAR1_CONFIG__dma__disable 0
-#define R_PAR1_CONFIG__rle_in__BITNR 8
-#define R_PAR1_CONFIG__rle_in__WIDTH 1
-#define R_PAR1_CONFIG__rle_in__enable 1
-#define R_PAR1_CONFIG__rle_in__disable 0
-#define R_PAR1_CONFIG__rle_out__BITNR 7
-#define R_PAR1_CONFIG__rle_out__WIDTH 1
-#define R_PAR1_CONFIG__rle_out__enable 1
-#define R_PAR1_CONFIG__rle_out__disable 0
-#define R_PAR1_CONFIG__enable__BITNR 6
-#define R_PAR1_CONFIG__enable__WIDTH 1
-#define R_PAR1_CONFIG__enable__on 1
-#define R_PAR1_CONFIG__enable__reset 0
-#define R_PAR1_CONFIG__force__BITNR 5
-#define R_PAR1_CONFIG__force__WIDTH 1
-#define R_PAR1_CONFIG__force__on 1
-#define R_PAR1_CONFIG__force__off 0
-#define R_PAR1_CONFIG__ign_ack__BITNR 4
-#define R_PAR1_CONFIG__ign_ack__WIDTH 1
-#define R_PAR1_CONFIG__ign_ack__ignore 1
-#define R_PAR1_CONFIG__ign_ack__wait 0
-#define R_PAR1_CONFIG__oe_ack__BITNR 3
-#define R_PAR1_CONFIG__oe_ack__WIDTH 1
-#define R_PAR1_CONFIG__oe_ack__wait_oe 1
-#define R_PAR1_CONFIG__oe_ack__dont_wait 0
-#define R_PAR1_CONFIG__oe_ack__epp_addr 1
-#define R_PAR1_CONFIG__oe_ack__epp_data 0
-#define R_PAR1_CONFIG__epp_addr_data__BITNR 3
-#define R_PAR1_CONFIG__epp_addr_data__WIDTH 1
-#define R_PAR1_CONFIG__epp_addr_data__wait_oe 1
-#define R_PAR1_CONFIG__epp_addr_data__dont_wait 0
-#define R_PAR1_CONFIG__epp_addr_data__epp_addr 1
-#define R_PAR1_CONFIG__epp_addr_data__epp_data 0
-#define R_PAR1_CONFIG__mode__BITNR 0
-#define R_PAR1_CONFIG__mode__WIDTH 3
-#define R_PAR1_CONFIG__mode__manual 0
-#define R_PAR1_CONFIG__mode__centronics 1
-#define R_PAR1_CONFIG__mode__fastbyte 2
-#define R_PAR1_CONFIG__mode__nibble 3
-#define R_PAR1_CONFIG__mode__byte 4
-#define R_PAR1_CONFIG__mode__ecp_fwd 5
-#define R_PAR1_CONFIG__mode__ecp_rev 6
-#define R_PAR1_CONFIG__mode__off 7
-#define R_PAR1_CONFIG__mode__epp_wr1 5
-#define R_PAR1_CONFIG__mode__epp_wr2 6
-#define R_PAR1_CONFIG__mode__epp_wr3 7
-#define R_PAR1_CONFIG__mode__epp_rd 0
-
-#define R_PAR1_DELAY (IO_TYPECAST_UDWORD 0xb0000058)
-#define R_PAR1_DELAY__fine_hold__BITNR 21
-#define R_PAR1_DELAY__fine_hold__WIDTH 3
-#define R_PAR1_DELAY__hold__BITNR 16
-#define R_PAR1_DELAY__hold__WIDTH 5
-#define R_PAR1_DELAY__fine_strb__BITNR 13
-#define R_PAR1_DELAY__fine_strb__WIDTH 3
-#define R_PAR1_DELAY__strobe__BITNR 8
-#define R_PAR1_DELAY__strobe__WIDTH 5
-#define R_PAR1_DELAY__fine_setup__BITNR 5
-#define R_PAR1_DELAY__fine_setup__WIDTH 3
-#define R_PAR1_DELAY__setup__BITNR 0
-#define R_PAR1_DELAY__setup__WIDTH 5
-
-/*
-!* ATA interface registers
-!*/
-
-#define R_ATA_CTRL_DATA (IO_TYPECAST_UDWORD 0xb0000040)
-#define R_ATA_CTRL_DATA__sel__BITNR 30
-#define R_ATA_CTRL_DATA__sel__WIDTH 2
-#define R_ATA_CTRL_DATA__cs1__BITNR 29
-#define R_ATA_CTRL_DATA__cs1__WIDTH 1
-#define R_ATA_CTRL_DATA__cs1__active 1
-#define R_ATA_CTRL_DATA__cs1__inactive 0
-#define R_ATA_CTRL_DATA__cs0__BITNR 28
-#define R_ATA_CTRL_DATA__cs0__WIDTH 1
-#define R_ATA_CTRL_DATA__cs0__active 1
-#define R_ATA_CTRL_DATA__cs0__inactive 0
-#define R_ATA_CTRL_DATA__addr__BITNR 25
-#define R_ATA_CTRL_DATA__addr__WIDTH 3
-#define R_ATA_CTRL_DATA__rw__BITNR 24
-#define R_ATA_CTRL_DATA__rw__WIDTH 1
-#define R_ATA_CTRL_DATA__rw__read 1
-#define R_ATA_CTRL_DATA__rw__write 0
-#define R_ATA_CTRL_DATA__src_dst__BITNR 23
-#define R_ATA_CTRL_DATA__src_dst__WIDTH 1
-#define R_ATA_CTRL_DATA__src_dst__dma 1
-#define R_ATA_CTRL_DATA__src_dst__register 0
-#define R_ATA_CTRL_DATA__handsh__BITNR 22
-#define R_ATA_CTRL_DATA__handsh__WIDTH 1
-#define R_ATA_CTRL_DATA__handsh__dma 1
-#define R_ATA_CTRL_DATA__handsh__pio 0
-#define R_ATA_CTRL_DATA__multi__BITNR 21
-#define R_ATA_CTRL_DATA__multi__WIDTH 1
-#define R_ATA_CTRL_DATA__multi__on 1
-#define R_ATA_CTRL_DATA__multi__off 0
-#define R_ATA_CTRL_DATA__dma_size__BITNR 20
-#define R_ATA_CTRL_DATA__dma_size__WIDTH 1
-#define R_ATA_CTRL_DATA__dma_size__byte 1
-#define R_ATA_CTRL_DATA__dma_size__word 0
-#define R_ATA_CTRL_DATA__data__BITNR 0
-#define R_ATA_CTRL_DATA__data__WIDTH 16
-
-#define R_ATA_STATUS_DATA (IO_TYPECAST_RO_UDWORD 0xb0000040)
-#define R_ATA_STATUS_DATA__busy__BITNR 18
-#define R_ATA_STATUS_DATA__busy__WIDTH 1
-#define R_ATA_STATUS_DATA__busy__yes 1
-#define R_ATA_STATUS_DATA__busy__no 0
-#define R_ATA_STATUS_DATA__tr_rdy__BITNR 17
-#define R_ATA_STATUS_DATA__tr_rdy__WIDTH 1
-#define R_ATA_STATUS_DATA__tr_rdy__ready 1
-#define R_ATA_STATUS_DATA__tr_rdy__busy 0
-#define R_ATA_STATUS_DATA__dav__BITNR 16
-#define R_ATA_STATUS_DATA__dav__WIDTH 1
-#define R_ATA_STATUS_DATA__dav__data 1
-#define R_ATA_STATUS_DATA__dav__nodata 0
-#define R_ATA_STATUS_DATA__data__BITNR 0
-#define R_ATA_STATUS_DATA__data__WIDTH 16
-
-#define R_ATA_CONFIG (IO_TYPECAST_UDWORD 0xb0000044)
-#define R_ATA_CONFIG__enable__BITNR 25
-#define R_ATA_CONFIG__enable__WIDTH 1
-#define R_ATA_CONFIG__enable__on 1
-#define R_ATA_CONFIG__enable__off 0
-#define R_ATA_CONFIG__dma_strobe__BITNR 20
-#define R_ATA_CONFIG__dma_strobe__WIDTH 5
-#define R_ATA_CONFIG__dma_hold__BITNR 15
-#define R_ATA_CONFIG__dma_hold__WIDTH 5
-#define R_ATA_CONFIG__pio_setup__BITNR 10
-#define R_ATA_CONFIG__pio_setup__WIDTH 5
-#define R_ATA_CONFIG__pio_strobe__BITNR 5
-#define R_ATA_CONFIG__pio_strobe__WIDTH 5
-#define R_ATA_CONFIG__pio_hold__BITNR 0
-#define R_ATA_CONFIG__pio_hold__WIDTH 5
-
-#define R_ATA_TRANSFER_CNT (IO_TYPECAST_UDWORD 0xb0000048)
-#define R_ATA_TRANSFER_CNT__count__BITNR 0
-#define R_ATA_TRANSFER_CNT__count__WIDTH 17
-
-/*
-!* SCSI registers
-!*/
-
-#define R_SCSI0_CTRL (IO_TYPECAST_UDWORD 0xb0000044)
-#define R_SCSI0_CTRL__id_type__BITNR 31
-#define R_SCSI0_CTRL__id_type__WIDTH 1
-#define R_SCSI0_CTRL__id_type__software 1
-#define R_SCSI0_CTRL__id_type__hardware 0
-#define R_SCSI0_CTRL__sel_timeout__BITNR 24
-#define R_SCSI0_CTRL__sel_timeout__WIDTH 7
-#define R_SCSI0_CTRL__synch_per__BITNR 16
-#define R_SCSI0_CTRL__synch_per__WIDTH 8
-#define R_SCSI0_CTRL__rst__BITNR 15
-#define R_SCSI0_CTRL__rst__WIDTH 1
-#define R_SCSI0_CTRL__rst__yes 1
-#define R_SCSI0_CTRL__rst__no 0
-#define R_SCSI0_CTRL__atn__BITNR 14
-#define R_SCSI0_CTRL__atn__WIDTH 1
-#define R_SCSI0_CTRL__atn__yes 1
-#define R_SCSI0_CTRL__atn__no 0
-#define R_SCSI0_CTRL__my_id__BITNR 9
-#define R_SCSI0_CTRL__my_id__WIDTH 4
-#define R_SCSI0_CTRL__target_id__BITNR 4
-#define R_SCSI0_CTRL__target_id__WIDTH 4
-#define R_SCSI0_CTRL__fast_20__BITNR 3
-#define R_SCSI0_CTRL__fast_20__WIDTH 1
-#define R_SCSI0_CTRL__fast_20__yes 1
-#define R_SCSI0_CTRL__fast_20__no 0
-#define R_SCSI0_CTRL__bus_width__BITNR 2
-#define R_SCSI0_CTRL__bus_width__WIDTH 1
-#define R_SCSI0_CTRL__bus_width__wide 1
-#define R_SCSI0_CTRL__bus_width__narrow 0
-#define R_SCSI0_CTRL__synch__BITNR 1
-#define R_SCSI0_CTRL__synch__WIDTH 1
-#define R_SCSI0_CTRL__synch__synch 1
-#define R_SCSI0_CTRL__synch__asynch 0
-#define R_SCSI0_CTRL__enable__BITNR 0
-#define R_SCSI0_CTRL__enable__WIDTH 1
-#define R_SCSI0_CTRL__enable__on 1
-#define R_SCSI0_CTRL__enable__off 0
-
-#define R_SCSI0_CMD_DATA (IO_TYPECAST_UDWORD 0xb0000040)
-#define R_SCSI0_CMD_DATA__parity_in__BITNR 26
-#define R_SCSI0_CMD_DATA__parity_in__WIDTH 1
-#define R_SCSI0_CMD_DATA__parity_in__on 0
-#define R_SCSI0_CMD_DATA__parity_in__off 1
-#define R_SCSI0_CMD_DATA__skip__BITNR 25
-#define R_SCSI0_CMD_DATA__skip__WIDTH 1
-#define R_SCSI0_CMD_DATA__skip__on 1
-#define R_SCSI0_CMD_DATA__skip__off 0
-#define R_SCSI0_CMD_DATA__clr_status__BITNR 24
-#define R_SCSI0_CMD_DATA__clr_status__WIDTH 1
-#define R_SCSI0_CMD_DATA__clr_status__yes 1
-#define R_SCSI0_CMD_DATA__clr_status__nop 0
-#define R_SCSI0_CMD_DATA__asynch_setup__BITNR 20
-#define R_SCSI0_CMD_DATA__asynch_setup__WIDTH 4
-#define R_SCSI0_CMD_DATA__command__BITNR 16
-#define R_SCSI0_CMD_DATA__command__WIDTH 4
-#define R_SCSI0_CMD_DATA__command__full_din_1 0
-#define R_SCSI0_CMD_DATA__command__full_dout_1 1
-#define R_SCSI0_CMD_DATA__command__full_stat_1 2
-#define R_SCSI0_CMD_DATA__command__resel_din 3
-#define R_SCSI0_CMD_DATA__command__resel_dout 4
-#define R_SCSI0_CMD_DATA__command__resel_stat 5
-#define R_SCSI0_CMD_DATA__command__arb_only 6
-#define R_SCSI0_CMD_DATA__command__full_din_3 8
-#define R_SCSI0_CMD_DATA__command__full_dout_3 9
-#define R_SCSI0_CMD_DATA__command__full_stat_3 10
-#define R_SCSI0_CMD_DATA__command__man_data_in 11
-#define R_SCSI0_CMD_DATA__command__man_data_out 12
-#define R_SCSI0_CMD_DATA__command__man_rat 13
-#define R_SCSI0_CMD_DATA__data_out__BITNR 0
-#define R_SCSI0_CMD_DATA__data_out__WIDTH 16
-
-#define R_SCSI0_DATA (IO_TYPECAST_UWORD 0xb0000040)
-#define R_SCSI0_DATA__data_out__BITNR 0
-#define R_SCSI0_DATA__data_out__WIDTH 16
-
-#define R_SCSI0_CMD (IO_TYPECAST_BYTE 0xb0000042)
-#define R_SCSI0_CMD__asynch_setup__BITNR 4
-#define R_SCSI0_CMD__asynch_setup__WIDTH 4
-#define R_SCSI0_CMD__command__BITNR 0
-#define R_SCSI0_CMD__command__WIDTH 4
-#define R_SCSI0_CMD__command__full_din_1 0
-#define R_SCSI0_CMD__command__full_dout_1 1
-#define R_SCSI0_CMD__command__full_stat_1 2
-#define R_SCSI0_CMD__command__resel_din 3
-#define R_SCSI0_CMD__command__resel_dout 4
-#define R_SCSI0_CMD__command__resel_stat 5
-#define R_SCSI0_CMD__command__arb_only 6
-#define R_SCSI0_CMD__command__full_din_3 8
-#define R_SCSI0_CMD__command__full_dout_3 9
-#define R_SCSI0_CMD__command__full_stat_3 10
-#define R_SCSI0_CMD__command__man_data_in 11
-#define R_SCSI0_CMD__command__man_data_out 12
-#define R_SCSI0_CMD__command__man_rat 13
-
-#define R_SCSI0_STATUS_CTRL (IO_TYPECAST_BYTE 0xb0000043)
-#define R_SCSI0_STATUS_CTRL__parity_in__BITNR 2
-#define R_SCSI0_STATUS_CTRL__parity_in__WIDTH 1
-#define R_SCSI0_STATUS_CTRL__parity_in__on 0
-#define R_SCSI0_STATUS_CTRL__parity_in__off 1
-#define R_SCSI0_STATUS_CTRL__skip__BITNR 1
-#define R_SCSI0_STATUS_CTRL__skip__WIDTH 1
-#define R_SCSI0_STATUS_CTRL__skip__on 1
-#define R_SCSI0_STATUS_CTRL__skip__off 0
-#define R_SCSI0_STATUS_CTRL__clr_status__BITNR 0
-#define R_SCSI0_STATUS_CTRL__clr_status__WIDTH 1
-#define R_SCSI0_STATUS_CTRL__clr_status__yes 1
-#define R_SCSI0_STATUS_CTRL__clr_status__nop 0
-
-#define R_SCSI0_STATUS (IO_TYPECAST_RO_UDWORD 0xb0000048)
-#define R_SCSI0_STATUS__tst_arb_won__BITNR 23
-#define R_SCSI0_STATUS__tst_arb_won__WIDTH 1
-#define R_SCSI0_STATUS__tst_resel__BITNR 22
-#define R_SCSI0_STATUS__tst_resel__WIDTH 1
-#define R_SCSI0_STATUS__parity_error__BITNR 21
-#define R_SCSI0_STATUS__parity_error__WIDTH 1
-#define R_SCSI0_STATUS__bus_reset__BITNR 20
-#define R_SCSI0_STATUS__bus_reset__WIDTH 1
-#define R_SCSI0_STATUS__bus_reset__yes 1
-#define R_SCSI0_STATUS__bus_reset__no 0
-#define R_SCSI0_STATUS__resel_target__BITNR 15
-#define R_SCSI0_STATUS__resel_target__WIDTH 4
-#define R_SCSI0_STATUS__resel__BITNR 14
-#define R_SCSI0_STATUS__resel__WIDTH 1
-#define R_SCSI0_STATUS__resel__yes 1
-#define R_SCSI0_STATUS__resel__no 0
-#define R_SCSI0_STATUS__curr_phase__BITNR 11
-#define R_SCSI0_STATUS__curr_phase__WIDTH 3
-#define R_SCSI0_STATUS__curr_phase__ph_undef 0
-#define R_SCSI0_STATUS__curr_phase__ph_msg_in 7
-#define R_SCSI0_STATUS__curr_phase__ph_msg_out 6
-#define R_SCSI0_STATUS__curr_phase__ph_status 3
-#define R_SCSI0_STATUS__curr_phase__ph_command 2
-#define R_SCSI0_STATUS__curr_phase__ph_data_in 5
-#define R_SCSI0_STATUS__curr_phase__ph_data_out 4
-#define R_SCSI0_STATUS__curr_phase__ph_resel 1
-#define R_SCSI0_STATUS__last_seq_step__BITNR 6
-#define R_SCSI0_STATUS__last_seq_step__WIDTH 5
-#define R_SCSI0_STATUS__last_seq_step__st_bus_free 24
-#define R_SCSI0_STATUS__last_seq_step__st_arbitrate 8
-#define R_SCSI0_STATUS__last_seq_step__st_resel_req 29
-#define R_SCSI0_STATUS__last_seq_step__st_msg_1 2
-#define R_SCSI0_STATUS__last_seq_step__st_manual 28
-#define R_SCSI0_STATUS__last_seq_step__st_transf_cmd 30
-#define R_SCSI0_STATUS__last_seq_step__st_msg_2 6
-#define R_SCSI0_STATUS__last_seq_step__st_msg_3 22
-#define R_SCSI0_STATUS__last_seq_step__st_answer 3
-#define R_SCSI0_STATUS__last_seq_step__st_synch_din_perr 1
-#define R_SCSI0_STATUS__last_seq_step__st_transfer_done 15
-#define R_SCSI0_STATUS__last_seq_step__st_synch_dout 0
-#define R_SCSI0_STATUS__last_seq_step__st_asynch_dout 25
-#define R_SCSI0_STATUS__last_seq_step__st_synch_din 13
-#define R_SCSI0_STATUS__last_seq_step__st_asynch_din 9
-#define R_SCSI0_STATUS__last_seq_step__st_synch_dout_ack 4
-#define R_SCSI0_STATUS__last_seq_step__st_synch_din_ack 12
-#define R_SCSI0_STATUS__last_seq_step__st_synch_din_ack_perr 5
-#define R_SCSI0_STATUS__last_seq_step__st_asynch_dout_end 11
-#define R_SCSI0_STATUS__last_seq_step__st_iwr 27
-#define R_SCSI0_STATUS__last_seq_step__st_wait_free_disc 21
-#define R_SCSI0_STATUS__last_seq_step__st_sdp_disc 7
-#define R_SCSI0_STATUS__last_seq_step__st_cc 31
-#define R_SCSI0_STATUS__last_seq_step__st_iwr_good 14
-#define R_SCSI0_STATUS__last_seq_step__st_iwr_cc 23
-#define R_SCSI0_STATUS__last_seq_step__st_wait_free_iwr_cc 17
-#define R_SCSI0_STATUS__last_seq_step__st_wait_free_cc 20
-#define R_SCSI0_STATUS__last_seq_step__st_wait_free_sdp_disc 16
-#define R_SCSI0_STATUS__last_seq_step__st_manual_req 10
-#define R_SCSI0_STATUS__last_seq_step__st_manual_din_prot 18
-#define R_SCSI0_STATUS__valid_status__BITNR 5
-#define R_SCSI0_STATUS__valid_status__WIDTH 1
-#define R_SCSI0_STATUS__valid_status__yes 1
-#define R_SCSI0_STATUS__valid_status__no 0
-#define R_SCSI0_STATUS__seq_status__BITNR 0
-#define R_SCSI0_STATUS__seq_status__WIDTH 5
-#define R_SCSI0_STATUS__seq_status__info_seq_complete 0
-#define R_SCSI0_STATUS__seq_status__info_parity_error 1
-#define R_SCSI0_STATUS__seq_status__info_unhandled_msg_in 2
-#define R_SCSI0_STATUS__seq_status__info_unexp_ph_change 3
-#define R_SCSI0_STATUS__seq_status__info_arb_lost 4
-#define R_SCSI0_STATUS__seq_status__info_sel_timeout 5
-#define R_SCSI0_STATUS__seq_status__info_unexp_bf 6
-#define R_SCSI0_STATUS__seq_status__info_illegal_op 7
-#define R_SCSI0_STATUS__seq_status__info_rec_recvd 8
-#define R_SCSI0_STATUS__seq_status__info_reselected 9
-#define R_SCSI0_STATUS__seq_status__info_unhandled_status 10
-#define R_SCSI0_STATUS__seq_status__info_bus_reset 11
-#define R_SCSI0_STATUS__seq_status__info_illegal_bf 12
-#define R_SCSI0_STATUS__seq_status__info_bus_free 13
-
-#define R_SCSI0_DATA_IN (IO_TYPECAST_RO_UWORD 0xb0000040)
-#define R_SCSI0_DATA_IN__data_in__BITNR 0
-#define R_SCSI0_DATA_IN__data_in__WIDTH 16
-
-#define R_SCSI1_CTRL (IO_TYPECAST_UDWORD 0xb0000054)
-#define R_SCSI1_CTRL__id_type__BITNR 31
-#define R_SCSI1_CTRL__id_type__WIDTH 1
-#define R_SCSI1_CTRL__id_type__software 1
-#define R_SCSI1_CTRL__id_type__hardware 0
-#define R_SCSI1_CTRL__sel_timeout__BITNR 24
-#define R_SCSI1_CTRL__sel_timeout__WIDTH 7
-#define R_SCSI1_CTRL__synch_per__BITNR 16
-#define R_SCSI1_CTRL__synch_per__WIDTH 8
-#define R_SCSI1_CTRL__rst__BITNR 15
-#define R_SCSI1_CTRL__rst__WIDTH 1
-#define R_SCSI1_CTRL__rst__yes 1
-#define R_SCSI1_CTRL__rst__no 0
-#define R_SCSI1_CTRL__atn__BITNR 14
-#define R_SCSI1_CTRL__atn__WIDTH 1
-#define R_SCSI1_CTRL__atn__yes 1
-#define R_SCSI1_CTRL__atn__no 0
-#define R_SCSI1_CTRL__my_id__BITNR 9
-#define R_SCSI1_CTRL__my_id__WIDTH 4
-#define R_SCSI1_CTRL__target_id__BITNR 4
-#define R_SCSI1_CTRL__target_id__WIDTH 4
-#define R_SCSI1_CTRL__fast_20__BITNR 3
-#define R_SCSI1_CTRL__fast_20__WIDTH 1
-#define R_SCSI1_CTRL__fast_20__yes 1
-#define R_SCSI1_CTRL__fast_20__no 0
-#define R_SCSI1_CTRL__bus_width__BITNR 2
-#define R_SCSI1_CTRL__bus_width__WIDTH 1
-#define R_SCSI1_CTRL__bus_width__wide 1
-#define R_SCSI1_CTRL__bus_width__narrow 0
-#define R_SCSI1_CTRL__synch__BITNR 1
-#define R_SCSI1_CTRL__synch__WIDTH 1
-#define R_SCSI1_CTRL__synch__synch 1
-#define R_SCSI1_CTRL__synch__asynch 0
-#define R_SCSI1_CTRL__enable__BITNR 0
-#define R_SCSI1_CTRL__enable__WIDTH 1
-#define R_SCSI1_CTRL__enable__on 1
-#define R_SCSI1_CTRL__enable__off 0
-
-#define R_SCSI1_CMD_DATA (IO_TYPECAST_UDWORD 0xb0000050)
-#define R_SCSI1_CMD_DATA__parity_in__BITNR 26
-#define R_SCSI1_CMD_DATA__parity_in__WIDTH 1
-#define R_SCSI1_CMD_DATA__parity_in__on 0
-#define R_SCSI1_CMD_DATA__parity_in__off 1
-#define R_SCSI1_CMD_DATA__skip__BITNR 25
-#define R_SCSI1_CMD_DATA__skip__WIDTH 1
-#define R_SCSI1_CMD_DATA__skip__on 1
-#define R_SCSI1_CMD_DATA__skip__off 0
-#define R_SCSI1_CMD_DATA__clr_status__BITNR 24
-#define R_SCSI1_CMD_DATA__clr_status__WIDTH 1
-#define R_SCSI1_CMD_DATA__clr_status__yes 1
-#define R_SCSI1_CMD_DATA__clr_status__nop 0
-#define R_SCSI1_CMD_DATA__asynch_setup__BITNR 20
-#define R_SCSI1_CMD_DATA__asynch_setup__WIDTH 4
-#define R_SCSI1_CMD_DATA__command__BITNR 16
-#define R_SCSI1_CMD_DATA__command__WIDTH 4
-#define R_SCSI1_CMD_DATA__command__full_din_1 0
-#define R_SCSI1_CMD_DATA__command__full_dout_1 1
-#define R_SCSI1_CMD_DATA__command__full_stat_1 2
-#define R_SCSI1_CMD_DATA__command__resel_din 3
-#define R_SCSI1_CMD_DATA__command__resel_dout 4
-#define R_SCSI1_CMD_DATA__command__resel_stat 5
-#define R_SCSI1_CMD_DATA__command__arb_only 6
-#define R_SCSI1_CMD_DATA__command__full_din_3 8
-#define R_SCSI1_CMD_DATA__command__full_dout_3 9
-#define R_SCSI1_CMD_DATA__command__full_stat_3 10
-#define R_SCSI1_CMD_DATA__command__man_data_in 11
-#define R_SCSI1_CMD_DATA__command__man_data_out 12
-#define R_SCSI1_CMD_DATA__command__man_rat 13
-#define R_SCSI1_CMD_DATA__data_out__BITNR 0
-#define R_SCSI1_CMD_DATA__data_out__WIDTH 16
-
-#define R_SCSI1_DATA (IO_TYPECAST_UWORD 0xb0000050)
-#define R_SCSI1_DATA__data_out__BITNR 0
-#define R_SCSI1_DATA__data_out__WIDTH 16
-
-#define R_SCSI1_CMD (IO_TYPECAST_BYTE 0xb0000052)
-#define R_SCSI1_CMD__asynch_setup__BITNR 4
-#define R_SCSI1_CMD__asynch_setup__WIDTH 4
-#define R_SCSI1_CMD__command__BITNR 0
-#define R_SCSI1_CMD__command__WIDTH 4
-#define R_SCSI1_CMD__command__full_din_1 0
-#define R_SCSI1_CMD__command__full_dout_1 1
-#define R_SCSI1_CMD__command__full_stat_1 2
-#define R_SCSI1_CMD__command__resel_din 3
-#define R_SCSI1_CMD__command__resel_dout 4
-#define R_SCSI1_CMD__command__resel_stat 5
-#define R_SCSI1_CMD__command__arb_only 6
-#define R_SCSI1_CMD__command__full_din_3 8
-#define R_SCSI1_CMD__command__full_dout_3 9
-#define R_SCSI1_CMD__command__full_stat_3 10
-#define R_SCSI1_CMD__command__man_data_in 11
-#define R_SCSI1_CMD__command__man_data_out 12
-#define R_SCSI1_CMD__command__man_rat 13
-
-#define R_SCSI1_STATUS_CTRL (IO_TYPECAST_BYTE 0xb0000053)
-#define R_SCSI1_STATUS_CTRL__parity_in__BITNR 2
-#define R_SCSI1_STATUS_CTRL__parity_in__WIDTH 1
-#define R_SCSI1_STATUS_CTRL__parity_in__on 0
-#define R_SCSI1_STATUS_CTRL__parity_in__off 1
-#define R_SCSI1_STATUS_CTRL__skip__BITNR 1
-#define R_SCSI1_STATUS_CTRL__skip__WIDTH 1
-#define R_SCSI1_STATUS_CTRL__skip__on 1
-#define R_SCSI1_STATUS_CTRL__skip__off 0
-#define R_SCSI1_STATUS_CTRL__clr_status__BITNR 0
-#define R_SCSI1_STATUS_CTRL__clr_status__WIDTH 1
-#define R_SCSI1_STATUS_CTRL__clr_status__yes 1
-#define R_SCSI1_STATUS_CTRL__clr_status__nop 0
-
-#define R_SCSI1_STATUS (IO_TYPECAST_RO_UDWORD 0xb0000058)
-#define R_SCSI1_STATUS__tst_arb_won__BITNR 23
-#define R_SCSI1_STATUS__tst_arb_won__WIDTH 1
-#define R_SCSI1_STATUS__tst_resel__BITNR 22
-#define R_SCSI1_STATUS__tst_resel__WIDTH 1
-#define R_SCSI1_STATUS__parity_error__BITNR 21
-#define R_SCSI1_STATUS__parity_error__WIDTH 1
-#define R_SCSI1_STATUS__bus_reset__BITNR 20
-#define R_SCSI1_STATUS__bus_reset__WIDTH 1
-#define R_SCSI1_STATUS__bus_reset__yes 1
-#define R_SCSI1_STATUS__bus_reset__no 0
-#define R_SCSI1_STATUS__resel_target__BITNR 15
-#define R_SCSI1_STATUS__resel_target__WIDTH 4
-#define R_SCSI1_STATUS__resel__BITNR 14
-#define R_SCSI1_STATUS__resel__WIDTH 1
-#define R_SCSI1_STATUS__resel__yes 1
-#define R_SCSI1_STATUS__resel__no 0
-#define R_SCSI1_STATUS__curr_phase__BITNR 11
-#define R_SCSI1_STATUS__curr_phase__WIDTH 3
-#define R_SCSI1_STATUS__curr_phase__ph_undef 0
-#define R_SCSI1_STATUS__curr_phase__ph_msg_in 7
-#define R_SCSI1_STATUS__curr_phase__ph_msg_out 6
-#define R_SCSI1_STATUS__curr_phase__ph_status 3
-#define R_SCSI1_STATUS__curr_phase__ph_command 2
-#define R_SCSI1_STATUS__curr_phase__ph_data_in 5
-#define R_SCSI1_STATUS__curr_phase__ph_data_out 4
-#define R_SCSI1_STATUS__curr_phase__ph_resel 1
-#define R_SCSI1_STATUS__last_seq_step__BITNR 6
-#define R_SCSI1_STATUS__last_seq_step__WIDTH 5
-#define R_SCSI1_STATUS__last_seq_step__st_bus_free 24
-#define R_SCSI1_STATUS__last_seq_step__st_arbitrate 8
-#define R_SCSI1_STATUS__last_seq_step__st_resel_req 29
-#define R_SCSI1_STATUS__last_seq_step__st_msg_1 2
-#define R_SCSI1_STATUS__last_seq_step__st_manual 28
-#define R_SCSI1_STATUS__last_seq_step__st_transf_cmd 30
-#define R_SCSI1_STATUS__last_seq_step__st_msg_2 6
-#define R_SCSI1_STATUS__last_seq_step__st_msg_3 22
-#define R_SCSI1_STATUS__last_seq_step__st_answer 3
-#define R_SCSI1_STATUS__last_seq_step__st_synch_din_perr 1
-#define R_SCSI1_STATUS__last_seq_step__st_transfer_done 15
-#define R_SCSI1_STATUS__last_seq_step__st_synch_dout 0
-#define R_SCSI1_STATUS__last_seq_step__st_asynch_dout 25
-#define R_SCSI1_STATUS__last_seq_step__st_synch_din 13
-#define R_SCSI1_STATUS__last_seq_step__st_asynch_din 9
-#define R_SCSI1_STATUS__last_seq_step__st_synch_dout_ack 4
-#define R_SCSI1_STATUS__last_seq_step__st_synch_din_ack 12
-#define R_SCSI1_STATUS__last_seq_step__st_synch_din_ack_perr 5
-#define R_SCSI1_STATUS__last_seq_step__st_asynch_dout_end 11
-#define R_SCSI1_STATUS__last_seq_step__st_iwr 27
-#define R_SCSI1_STATUS__last_seq_step__st_wait_free_disc 21
-#define R_SCSI1_STATUS__last_seq_step__st_sdp_disc 7
-#define R_SCSI1_STATUS__last_seq_step__st_cc 31
-#define R_SCSI1_STATUS__last_seq_step__st_iwr_good 14
-#define R_SCSI1_STATUS__last_seq_step__st_iwr_cc 23
-#define R_SCSI1_STATUS__last_seq_step__st_wait_free_iwr_cc 17
-#define R_SCSI1_STATUS__last_seq_step__st_wait_free_cc 20
-#define R_SCSI1_STATUS__last_seq_step__st_wait_free_sdp_disc 16
-#define R_SCSI1_STATUS__last_seq_step__st_manual_req 10
-#define R_SCSI1_STATUS__last_seq_step__st_manual_din_prot 18
-#define R_SCSI1_STATUS__valid_status__BITNR 5
-#define R_SCSI1_STATUS__valid_status__WIDTH 1
-#define R_SCSI1_STATUS__valid_status__yes 1
-#define R_SCSI1_STATUS__valid_status__no 0
-#define R_SCSI1_STATUS__seq_status__BITNR 0
-#define R_SCSI1_STATUS__seq_status__WIDTH 5
-#define R_SCSI1_STATUS__seq_status__info_seq_complete 0
-#define R_SCSI1_STATUS__seq_status__info_parity_error 1
-#define R_SCSI1_STATUS__seq_status__info_unhandled_msg_in 2
-#define R_SCSI1_STATUS__seq_status__info_unexp_ph_change 3
-#define R_SCSI1_STATUS__seq_status__info_arb_lost 4
-#define R_SCSI1_STATUS__seq_status__info_sel_timeout 5
-#define R_SCSI1_STATUS__seq_status__info_unexp_bf 6
-#define R_SCSI1_STATUS__seq_status__info_illegal_op 7
-#define R_SCSI1_STATUS__seq_status__info_rec_recvd 8
-#define R_SCSI1_STATUS__seq_status__info_reselected 9
-#define R_SCSI1_STATUS__seq_status__info_unhandled_status 10
-#define R_SCSI1_STATUS__seq_status__info_bus_reset 11
-#define R_SCSI1_STATUS__seq_status__info_illegal_bf 12
-#define R_SCSI1_STATUS__seq_status__info_bus_free 13
-
-#define R_SCSI1_DATA_IN (IO_TYPECAST_RO_UWORD 0xb0000050)
-#define R_SCSI1_DATA_IN__data_in__BITNR 0
-#define R_SCSI1_DATA_IN__data_in__WIDTH 16
-
-/*
-!* Interrupt mask and status registers
-!*/
-
-#define R_IRQ_MASK0_RD (IO_TYPECAST_RO_UDWORD 0xb00000c0)
-#define R_IRQ_MASK0_RD__nmi_pin__BITNR 31
-#define R_IRQ_MASK0_RD__nmi_pin__WIDTH 1
-#define R_IRQ_MASK0_RD__nmi_pin__active 1
-#define R_IRQ_MASK0_RD__nmi_pin__inactive 0
-#define R_IRQ_MASK0_RD__watchdog_nmi__BITNR 30
-#define R_IRQ_MASK0_RD__watchdog_nmi__WIDTH 1
-#define R_IRQ_MASK0_RD__watchdog_nmi__active 1
-#define R_IRQ_MASK0_RD__watchdog_nmi__inactive 0
-#define R_IRQ_MASK0_RD__sqe_test_error__BITNR 29
-#define R_IRQ_MASK0_RD__sqe_test_error__WIDTH 1
-#define R_IRQ_MASK0_RD__sqe_test_error__active 1
-#define R_IRQ_MASK0_RD__sqe_test_error__inactive 0
-#define R_IRQ_MASK0_RD__carrier_loss__BITNR 28
-#define R_IRQ_MASK0_RD__carrier_loss__WIDTH 1
-#define R_IRQ_MASK0_RD__carrier_loss__active 1
-#define R_IRQ_MASK0_RD__carrier_loss__inactive 0
-#define R_IRQ_MASK0_RD__deferred__BITNR 27
-#define R_IRQ_MASK0_RD__deferred__WIDTH 1
-#define R_IRQ_MASK0_RD__deferred__active 1
-#define R_IRQ_MASK0_RD__deferred__inactive 0
-#define R_IRQ_MASK0_RD__late_col__BITNR 26
-#define R_IRQ_MASK0_RD__late_col__WIDTH 1
-#define R_IRQ_MASK0_RD__late_col__active 1
-#define R_IRQ_MASK0_RD__late_col__inactive 0
-#define R_IRQ_MASK0_RD__multiple_col__BITNR 25
-#define R_IRQ_MASK0_RD__multiple_col__WIDTH 1
-#define R_IRQ_MASK0_RD__multiple_col__active 1
-#define R_IRQ_MASK0_RD__multiple_col__inactive 0
-#define R_IRQ_MASK0_RD__single_col__BITNR 24
-#define R_IRQ_MASK0_RD__single_col__WIDTH 1
-#define R_IRQ_MASK0_RD__single_col__active 1
-#define R_IRQ_MASK0_RD__single_col__inactive 0
-#define R_IRQ_MASK0_RD__congestion__BITNR 23
-#define R_IRQ_MASK0_RD__congestion__WIDTH 1
-#define R_IRQ_MASK0_RD__congestion__active 1
-#define R_IRQ_MASK0_RD__congestion__inactive 0
-#define R_IRQ_MASK0_RD__oversize__BITNR 22
-#define R_IRQ_MASK0_RD__oversize__WIDTH 1
-#define R_IRQ_MASK0_RD__oversize__active 1
-#define R_IRQ_MASK0_RD__oversize__inactive 0
-#define R_IRQ_MASK0_RD__alignment_error__BITNR 21
-#define R_IRQ_MASK0_RD__alignment_error__WIDTH 1
-#define R_IRQ_MASK0_RD__alignment_error__active 1
-#define R_IRQ_MASK0_RD__alignment_error__inactive 0
-#define R_IRQ_MASK0_RD__crc_error__BITNR 20
-#define R_IRQ_MASK0_RD__crc_error__WIDTH 1
-#define R_IRQ_MASK0_RD__crc_error__active 1
-#define R_IRQ_MASK0_RD__crc_error__inactive 0
-#define R_IRQ_MASK0_RD__overrun__BITNR 19
-#define R_IRQ_MASK0_RD__overrun__WIDTH 1
-#define R_IRQ_MASK0_RD__overrun__active 1
-#define R_IRQ_MASK0_RD__overrun__inactive 0
-#define R_IRQ_MASK0_RD__underrun__BITNR 18
-#define R_IRQ_MASK0_RD__underrun__WIDTH 1
-#define R_IRQ_MASK0_RD__underrun__active 1
-#define R_IRQ_MASK0_RD__underrun__inactive 0
-#define R_IRQ_MASK0_RD__excessive_col__BITNR 17
-#define R_IRQ_MASK0_RD__excessive_col__WIDTH 1
-#define R_IRQ_MASK0_RD__excessive_col__active 1
-#define R_IRQ_MASK0_RD__excessive_col__inactive 0
-#define R_IRQ_MASK0_RD__mdio__BITNR 16
-#define R_IRQ_MASK0_RD__mdio__WIDTH 1
-#define R_IRQ_MASK0_RD__mdio__active 1
-#define R_IRQ_MASK0_RD__mdio__inactive 0
-#define R_IRQ_MASK0_RD__ata_drq3__BITNR 15
-#define R_IRQ_MASK0_RD__ata_drq3__WIDTH 1
-#define R_IRQ_MASK0_RD__ata_drq3__active 1
-#define R_IRQ_MASK0_RD__ata_drq3__inactive 0
-#define R_IRQ_MASK0_RD__ata_drq2__BITNR 14
-#define R_IRQ_MASK0_RD__ata_drq2__WIDTH 1
-#define R_IRQ_MASK0_RD__ata_drq2__active 1
-#define R_IRQ_MASK0_RD__ata_drq2__inactive 0
-#define R_IRQ_MASK0_RD__ata_drq1__BITNR 13
-#define R_IRQ_MASK0_RD__ata_drq1__WIDTH 1
-#define R_IRQ_MASK0_RD__ata_drq1__active 1
-#define R_IRQ_MASK0_RD__ata_drq1__inactive 0
-#define R_IRQ_MASK0_RD__ata_drq0__BITNR 12
-#define R_IRQ_MASK0_RD__ata_drq0__WIDTH 1
-#define R_IRQ_MASK0_RD__ata_drq0__active 1
-#define R_IRQ_MASK0_RD__ata_drq0__inactive 0
-#define R_IRQ_MASK0_RD__par0_ecp_cmd__BITNR 11
-#define R_IRQ_MASK0_RD__par0_ecp_cmd__WIDTH 1
-#define R_IRQ_MASK0_RD__par0_ecp_cmd__active 1
-#define R_IRQ_MASK0_RD__par0_ecp_cmd__inactive 0
-#define R_IRQ_MASK0_RD__ata_irq3__BITNR 11
-#define R_IRQ_MASK0_RD__ata_irq3__WIDTH 1
-#define R_IRQ_MASK0_RD__ata_irq3__active 1
-#define R_IRQ_MASK0_RD__ata_irq3__inactive 0
-#define R_IRQ_MASK0_RD__par0_peri__BITNR 10
-#define R_IRQ_MASK0_RD__par0_peri__WIDTH 1
-#define R_IRQ_MASK0_RD__par0_peri__active 1
-#define R_IRQ_MASK0_RD__par0_peri__inactive 0
-#define R_IRQ_MASK0_RD__ata_irq2__BITNR 10
-#define R_IRQ_MASK0_RD__ata_irq2__WIDTH 1
-#define R_IRQ_MASK0_RD__ata_irq2__active 1
-#define R_IRQ_MASK0_RD__ata_irq2__inactive 0
-#define R_IRQ_MASK0_RD__par0_data__BITNR 9
-#define R_IRQ_MASK0_RD__par0_data__WIDTH 1
-#define R_IRQ_MASK0_RD__par0_data__active 1
-#define R_IRQ_MASK0_RD__par0_data__inactive 0
-#define R_IRQ_MASK0_RD__ata_irq1__BITNR 9
-#define R_IRQ_MASK0_RD__ata_irq1__WIDTH 1
-#define R_IRQ_MASK0_RD__ata_irq1__active 1
-#define R_IRQ_MASK0_RD__ata_irq1__inactive 0
-#define R_IRQ_MASK0_RD__par0_ready__BITNR 8
-#define R_IRQ_MASK0_RD__par0_ready__WIDTH 1
-#define R_IRQ_MASK0_RD__par0_ready__active 1
-#define R_IRQ_MASK0_RD__par0_ready__inactive 0
-#define R_IRQ_MASK0_RD__ata_irq0__BITNR 8
-#define R_IRQ_MASK0_RD__ata_irq0__WIDTH 1
-#define R_IRQ_MASK0_RD__ata_irq0__active 1
-#define R_IRQ_MASK0_RD__ata_irq0__inactive 0
-#define R_IRQ_MASK0_RD__mio__BITNR 8
-#define R_IRQ_MASK0_RD__mio__WIDTH 1
-#define R_IRQ_MASK0_RD__mio__active 1
-#define R_IRQ_MASK0_RD__mio__inactive 0
-#define R_IRQ_MASK0_RD__scsi0__BITNR 8
-#define R_IRQ_MASK0_RD__scsi0__WIDTH 1
-#define R_IRQ_MASK0_RD__scsi0__active 1
-#define R_IRQ_MASK0_RD__scsi0__inactive 0
-#define R_IRQ_MASK0_RD__ata_dmaend__BITNR 7
-#define R_IRQ_MASK0_RD__ata_dmaend__WIDTH 1
-#define R_IRQ_MASK0_RD__ata_dmaend__active 1
-#define R_IRQ_MASK0_RD__ata_dmaend__inactive 0
-#define R_IRQ_MASK0_RD__irq_ext_vector_nr__BITNR 5
-#define R_IRQ_MASK0_RD__irq_ext_vector_nr__WIDTH 1
-#define R_IRQ_MASK0_RD__irq_ext_vector_nr__active 1
-#define R_IRQ_MASK0_RD__irq_ext_vector_nr__inactive 0
-#define R_IRQ_MASK0_RD__irq_int_vector_nr__BITNR 4
-#define R_IRQ_MASK0_RD__irq_int_vector_nr__WIDTH 1
-#define R_IRQ_MASK0_RD__irq_int_vector_nr__active 1
-#define R_IRQ_MASK0_RD__irq_int_vector_nr__inactive 0
-#define R_IRQ_MASK0_RD__ext_dma1__BITNR 3
-#define R_IRQ_MASK0_RD__ext_dma1__WIDTH 1
-#define R_IRQ_MASK0_RD__ext_dma1__active 1
-#define R_IRQ_MASK0_RD__ext_dma1__inactive 0
-#define R_IRQ_MASK0_RD__ext_dma0__BITNR 2
-#define R_IRQ_MASK0_RD__ext_dma0__WIDTH 1
-#define R_IRQ_MASK0_RD__ext_dma0__active 1
-#define R_IRQ_MASK0_RD__ext_dma0__inactive 0
-#define R_IRQ_MASK0_RD__timer1__BITNR 1
-#define R_IRQ_MASK0_RD__timer1__WIDTH 1
-#define R_IRQ_MASK0_RD__timer1__active 1
-#define R_IRQ_MASK0_RD__timer1__inactive 0
-#define R_IRQ_MASK0_RD__timer0__BITNR 0
-#define R_IRQ_MASK0_RD__timer0__WIDTH 1
-#define R_IRQ_MASK0_RD__timer0__active 1
-#define R_IRQ_MASK0_RD__timer0__inactive 0
-
-#define R_IRQ_MASK0_CLR (IO_TYPECAST_UDWORD 0xb00000c0)
-#define R_IRQ_MASK0_CLR__nmi_pin__BITNR 31
-#define R_IRQ_MASK0_CLR__nmi_pin__WIDTH 1
-#define R_IRQ_MASK0_CLR__nmi_pin__clr 1
-#define R_IRQ_MASK0_CLR__nmi_pin__nop 0
-#define R_IRQ_MASK0_CLR__watchdog_nmi__BITNR 30
-#define R_IRQ_MASK0_CLR__watchdog_nmi__WIDTH 1
-#define R_IRQ_MASK0_CLR__watchdog_nmi__clr 1
-#define R_IRQ_MASK0_CLR__watchdog_nmi__nop 0
-#define R_IRQ_MASK0_CLR__sqe_test_error__BITNR 29
-#define R_IRQ_MASK0_CLR__sqe_test_error__WIDTH 1
-#define R_IRQ_MASK0_CLR__sqe_test_error__clr 1
-#define R_IRQ_MASK0_CLR__sqe_test_error__nop 0
-#define R_IRQ_MASK0_CLR__carrier_loss__BITNR 28
-#define R_IRQ_MASK0_CLR__carrier_loss__WIDTH 1
-#define R_IRQ_MASK0_CLR__carrier_loss__clr 1
-#define R_IRQ_MASK0_CLR__carrier_loss__nop 0
-#define R_IRQ_MASK0_CLR__deferred__BITNR 27
-#define R_IRQ_MASK0_CLR__deferred__WIDTH 1
-#define R_IRQ_MASK0_CLR__deferred__clr 1
-#define R_IRQ_MASK0_CLR__deferred__nop 0
-#define R_IRQ_MASK0_CLR__late_col__BITNR 26
-#define R_IRQ_MASK0_CLR__late_col__WIDTH 1
-#define R_IRQ_MASK0_CLR__late_col__clr 1
-#define R_IRQ_MASK0_CLR__late_col__nop 0
-#define R_IRQ_MASK0_CLR__multiple_col__BITNR 25
-#define R_IRQ_MASK0_CLR__multiple_col__WIDTH 1
-#define R_IRQ_MASK0_CLR__multiple_col__clr 1
-#define R_IRQ_MASK0_CLR__multiple_col__nop 0
-#define R_IRQ_MASK0_CLR__single_col__BITNR 24
-#define R_IRQ_MASK0_CLR__single_col__WIDTH 1
-#define R_IRQ_MASK0_CLR__single_col__clr 1
-#define R_IRQ_MASK0_CLR__single_col__nop 0
-#define R_IRQ_MASK0_CLR__congestion__BITNR 23
-#define R_IRQ_MASK0_CLR__congestion__WIDTH 1
-#define R_IRQ_MASK0_CLR__congestion__clr 1
-#define R_IRQ_MASK0_CLR__congestion__nop 0
-#define R_IRQ_MASK0_CLR__oversize__BITNR 22
-#define R_IRQ_MASK0_CLR__oversize__WIDTH 1
-#define R_IRQ_MASK0_CLR__oversize__clr 1
-#define R_IRQ_MASK0_CLR__oversize__nop 0
-#define R_IRQ_MASK0_CLR__alignment_error__BITNR 21
-#define R_IRQ_MASK0_CLR__alignment_error__WIDTH 1
-#define R_IRQ_MASK0_CLR__alignment_error__clr 1
-#define R_IRQ_MASK0_CLR__alignment_error__nop 0
-#define R_IRQ_MASK0_CLR__crc_error__BITNR 20
-#define R_IRQ_MASK0_CLR__crc_error__WIDTH 1
-#define R_IRQ_MASK0_CLR__crc_error__clr 1
-#define R_IRQ_MASK0_CLR__crc_error__nop 0
-#define R_IRQ_MASK0_CLR__overrun__BITNR 19
-#define R_IRQ_MASK0_CLR__overrun__WIDTH 1
-#define R_IRQ_MASK0_CLR__overrun__clr 1
-#define R_IRQ_MASK0_CLR__overrun__nop 0
-#define R_IRQ_MASK0_CLR__underrun__BITNR 18
-#define R_IRQ_MASK0_CLR__underrun__WIDTH 1
-#define R_IRQ_MASK0_CLR__underrun__clr 1
-#define R_IRQ_MASK0_CLR__underrun__nop 0
-#define R_IRQ_MASK0_CLR__excessive_col__BITNR 17
-#define R_IRQ_MASK0_CLR__excessive_col__WIDTH 1
-#define R_IRQ_MASK0_CLR__excessive_col__clr 1
-#define R_IRQ_MASK0_CLR__excessive_col__nop 0
-#define R_IRQ_MASK0_CLR__mdio__BITNR 16
-#define R_IRQ_MASK0_CLR__mdio__WIDTH 1
-#define R_IRQ_MASK0_CLR__mdio__clr 1
-#define R_IRQ_MASK0_CLR__mdio__nop 0
-#define R_IRQ_MASK0_CLR__ata_drq3__BITNR 15
-#define R_IRQ_MASK0_CLR__ata_drq3__WIDTH 1
-#define R_IRQ_MASK0_CLR__ata_drq3__clr 1
-#define R_IRQ_MASK0_CLR__ata_drq3__nop 0
-#define R_IRQ_MASK0_CLR__ata_drq2__BITNR 14
-#define R_IRQ_MASK0_CLR__ata_drq2__WIDTH 1
-#define R_IRQ_MASK0_CLR__ata_drq2__clr 1
-#define R_IRQ_MASK0_CLR__ata_drq2__nop 0
-#define R_IRQ_MASK0_CLR__ata_drq1__BITNR 13
-#define R_IRQ_MASK0_CLR__ata_drq1__WIDTH 1
-#define R_IRQ_MASK0_CLR__ata_drq1__clr 1
-#define R_IRQ_MASK0_CLR__ata_drq1__nop 0
-#define R_IRQ_MASK0_CLR__ata_drq0__BITNR 12
-#define R_IRQ_MASK0_CLR__ata_drq0__WIDTH 1
-#define R_IRQ_MASK0_CLR__ata_drq0__clr 1
-#define R_IRQ_MASK0_CLR__ata_drq0__nop 0
-#define R_IRQ_MASK0_CLR__par0_ecp_cmd__BITNR 11
-#define R_IRQ_MASK0_CLR__par0_ecp_cmd__WIDTH 1
-#define R_IRQ_MASK0_CLR__par0_ecp_cmd__clr 1
-#define R_IRQ_MASK0_CLR__par0_ecp_cmd__nop 0
-#define R_IRQ_MASK0_CLR__ata_irq3__BITNR 11
-#define R_IRQ_MASK0_CLR__ata_irq3__WIDTH 1
-#define R_IRQ_MASK0_CLR__ata_irq3__clr 1
-#define R_IRQ_MASK0_CLR__ata_irq3__nop 0
-#define R_IRQ_MASK0_CLR__par0_peri__BITNR 10
-#define R_IRQ_MASK0_CLR__par0_peri__WIDTH 1
-#define R_IRQ_MASK0_CLR__par0_peri__clr 1
-#define R_IRQ_MASK0_CLR__par0_peri__nop 0
-#define R_IRQ_MASK0_CLR__ata_irq2__BITNR 10
-#define R_IRQ_MASK0_CLR__ata_irq2__WIDTH 1
-#define R_IRQ_MASK0_CLR__ata_irq2__clr 1
-#define R_IRQ_MASK0_CLR__ata_irq2__nop 0
-#define R_IRQ_MASK0_CLR__par0_data__BITNR 9
-#define R_IRQ_MASK0_CLR__par0_data__WIDTH 1
-#define R_IRQ_MASK0_CLR__par0_data__clr 1
-#define R_IRQ_MASK0_CLR__par0_data__nop 0
-#define R_IRQ_MASK0_CLR__ata_irq1__BITNR 9
-#define R_IRQ_MASK0_CLR__ata_irq1__WIDTH 1
-#define R_IRQ_MASK0_CLR__ata_irq1__clr 1
-#define R_IRQ_MASK0_CLR__ata_irq1__nop 0
-#define R_IRQ_MASK0_CLR__par0_ready__BITNR 8
-#define R_IRQ_MASK0_CLR__par0_ready__WIDTH 1
-#define R_IRQ_MASK0_CLR__par0_ready__clr 1
-#define R_IRQ_MASK0_CLR__par0_ready__nop 0
-#define R_IRQ_MASK0_CLR__ata_irq0__BITNR 8
-#define R_IRQ_MASK0_CLR__ata_irq0__WIDTH 1
-#define R_IRQ_MASK0_CLR__ata_irq0__clr 1
-#define R_IRQ_MASK0_CLR__ata_irq0__nop 0
-#define R_IRQ_MASK0_CLR__mio__BITNR 8
-#define R_IRQ_MASK0_CLR__mio__WIDTH 1
-#define R_IRQ_MASK0_CLR__mio__clr 1
-#define R_IRQ_MASK0_CLR__mio__nop 0
-#define R_IRQ_MASK0_CLR__scsi0__BITNR 8
-#define R_IRQ_MASK0_CLR__scsi0__WIDTH 1
-#define R_IRQ_MASK0_CLR__scsi0__clr 1
-#define R_IRQ_MASK0_CLR__scsi0__nop 0
-#define R_IRQ_MASK0_CLR__ata_dmaend__BITNR 7
-#define R_IRQ_MASK0_CLR__ata_dmaend__WIDTH 1
-#define R_IRQ_MASK0_CLR__ata_dmaend__clr 1
-#define R_IRQ_MASK0_CLR__ata_dmaend__nop 0
-#define R_IRQ_MASK0_CLR__irq_ext_vector_nr__BITNR 5
-#define R_IRQ_MASK0_CLR__irq_ext_vector_nr__WIDTH 1
-#define R_IRQ_MASK0_CLR__irq_ext_vector_nr__clr 1
-#define R_IRQ_MASK0_CLR__irq_ext_vector_nr__nop 0
-#define R_IRQ_MASK0_CLR__irq_int_vector_nr__BITNR 4
-#define R_IRQ_MASK0_CLR__irq_int_vector_nr__WIDTH 1
-#define R_IRQ_MASK0_CLR__irq_int_vector_nr__clr 1
-#define R_IRQ_MASK0_CLR__irq_int_vector_nr__nop 0
-#define R_IRQ_MASK0_CLR__ext_dma1__BITNR 3
-#define R_IRQ_MASK0_CLR__ext_dma1__WIDTH 1
-#define R_IRQ_MASK0_CLR__ext_dma1__clr 1
-#define R_IRQ_MASK0_CLR__ext_dma1__nop 0
-#define R_IRQ_MASK0_CLR__ext_dma0__BITNR 2
-#define R_IRQ_MASK0_CLR__ext_dma0__WIDTH 1
-#define R_IRQ_MASK0_CLR__ext_dma0__clr 1
-#define R_IRQ_MASK0_CLR__ext_dma0__nop 0
-#define R_IRQ_MASK0_CLR__timer1__BITNR 1
-#define R_IRQ_MASK0_CLR__timer1__WIDTH 1
-#define R_IRQ_MASK0_CLR__timer1__clr 1
-#define R_IRQ_MASK0_CLR__timer1__nop 0
-#define R_IRQ_MASK0_CLR__timer0__BITNR 0
-#define R_IRQ_MASK0_CLR__timer0__WIDTH 1
-#define R_IRQ_MASK0_CLR__timer0__clr 1
-#define R_IRQ_MASK0_CLR__timer0__nop 0
-
-#define R_IRQ_READ0 (IO_TYPECAST_RO_UDWORD 0xb00000c4)
-#define R_IRQ_READ0__nmi_pin__BITNR 31
-#define R_IRQ_READ0__nmi_pin__WIDTH 1
-#define R_IRQ_READ0__nmi_pin__active 1
-#define R_IRQ_READ0__nmi_pin__inactive 0
-#define R_IRQ_READ0__watchdog_nmi__BITNR 30
-#define R_IRQ_READ0__watchdog_nmi__WIDTH 1
-#define R_IRQ_READ0__watchdog_nmi__active 1
-#define R_IRQ_READ0__watchdog_nmi__inactive 0
-#define R_IRQ_READ0__sqe_test_error__BITNR 29
-#define R_IRQ_READ0__sqe_test_error__WIDTH 1
-#define R_IRQ_READ0__sqe_test_error__active 1
-#define R_IRQ_READ0__sqe_test_error__inactive 0
-#define R_IRQ_READ0__carrier_loss__BITNR 28
-#define R_IRQ_READ0__carrier_loss__WIDTH 1
-#define R_IRQ_READ0__carrier_loss__active 1
-#define R_IRQ_READ0__carrier_loss__inactive 0
-#define R_IRQ_READ0__deferred__BITNR 27
-#define R_IRQ_READ0__deferred__WIDTH 1
-#define R_IRQ_READ0__deferred__active 1
-#define R_IRQ_READ0__deferred__inactive 0
-#define R_IRQ_READ0__late_col__BITNR 26
-#define R_IRQ_READ0__late_col__WIDTH 1
-#define R_IRQ_READ0__late_col__active 1
-#define R_IRQ_READ0__late_col__inactive 0
-#define R_IRQ_READ0__multiple_col__BITNR 25
-#define R_IRQ_READ0__multiple_col__WIDTH 1
-#define R_IRQ_READ0__multiple_col__active 1
-#define R_IRQ_READ0__multiple_col__inactive 0
-#define R_IRQ_READ0__single_col__BITNR 24
-#define R_IRQ_READ0__single_col__WIDTH 1
-#define R_IRQ_READ0__single_col__active 1
-#define R_IRQ_READ0__single_col__inactive 0
-#define R_IRQ_READ0__congestion__BITNR 23
-#define R_IRQ_READ0__congestion__WIDTH 1
-#define R_IRQ_READ0__congestion__active 1
-#define R_IRQ_READ0__congestion__inactive 0
-#define R_IRQ_READ0__oversize__BITNR 22
-#define R_IRQ_READ0__oversize__WIDTH 1
-#define R_IRQ_READ0__oversize__active 1
-#define R_IRQ_READ0__oversize__inactive 0
-#define R_IRQ_READ0__alignment_error__BITNR 21
-#define R_IRQ_READ0__alignment_error__WIDTH 1
-#define R_IRQ_READ0__alignment_error__active 1
-#define R_IRQ_READ0__alignment_error__inactive 0
-#define R_IRQ_READ0__crc_error__BITNR 20
-#define R_IRQ_READ0__crc_error__WIDTH 1
-#define R_IRQ_READ0__crc_error__active 1
-#define R_IRQ_READ0__crc_error__inactive 0
-#define R_IRQ_READ0__overrun__BITNR 19
-#define R_IRQ_READ0__overrun__WIDTH 1
-#define R_IRQ_READ0__overrun__active 1
-#define R_IRQ_READ0__overrun__inactive 0
-#define R_IRQ_READ0__underrun__BITNR 18
-#define R_IRQ_READ0__underrun__WIDTH 1
-#define R_IRQ_READ0__underrun__active 1
-#define R_IRQ_READ0__underrun__inactive 0
-#define R_IRQ_READ0__excessive_col__BITNR 17
-#define R_IRQ_READ0__excessive_col__WIDTH 1
-#define R_IRQ_READ0__excessive_col__active 1
-#define R_IRQ_READ0__excessive_col__inactive 0
-#define R_IRQ_READ0__mdio__BITNR 16
-#define R_IRQ_READ0__mdio__WIDTH 1
-#define R_IRQ_READ0__mdio__active 1
-#define R_IRQ_READ0__mdio__inactive 0
-#define R_IRQ_READ0__ata_drq3__BITNR 15
-#define R_IRQ_READ0__ata_drq3__WIDTH 1
-#define R_IRQ_READ0__ata_drq3__active 1
-#define R_IRQ_READ0__ata_drq3__inactive 0
-#define R_IRQ_READ0__ata_drq2__BITNR 14
-#define R_IRQ_READ0__ata_drq2__WIDTH 1
-#define R_IRQ_READ0__ata_drq2__active 1
-#define R_IRQ_READ0__ata_drq2__inactive 0
-#define R_IRQ_READ0__ata_drq1__BITNR 13
-#define R_IRQ_READ0__ata_drq1__WIDTH 1
-#define R_IRQ_READ0__ata_drq1__active 1
-#define R_IRQ_READ0__ata_drq1__inactive 0
-#define R_IRQ_READ0__ata_drq0__BITNR 12
-#define R_IRQ_READ0__ata_drq0__WIDTH 1
-#define R_IRQ_READ0__ata_drq0__active 1
-#define R_IRQ_READ0__ata_drq0__inactive 0
-#define R_IRQ_READ0__par0_ecp_cmd__BITNR 11
-#define R_IRQ_READ0__par0_ecp_cmd__WIDTH 1
-#define R_IRQ_READ0__par0_ecp_cmd__active 1
-#define R_IRQ_READ0__par0_ecp_cmd__inactive 0
-#define R_IRQ_READ0__ata_irq3__BITNR 11
-#define R_IRQ_READ0__ata_irq3__WIDTH 1
-#define R_IRQ_READ0__ata_irq3__active 1
-#define R_IRQ_READ0__ata_irq3__inactive 0
-#define R_IRQ_READ0__par0_peri__BITNR 10
-#define R_IRQ_READ0__par0_peri__WIDTH 1
-#define R_IRQ_READ0__par0_peri__active 1
-#define R_IRQ_READ0__par0_peri__inactive 0
-#define R_IRQ_READ0__ata_irq2__BITNR 10
-#define R_IRQ_READ0__ata_irq2__WIDTH 1
-#define R_IRQ_READ0__ata_irq2__active 1
-#define R_IRQ_READ0__ata_irq2__inactive 0
-#define R_IRQ_READ0__par0_data__BITNR 9
-#define R_IRQ_READ0__par0_data__WIDTH 1
-#define R_IRQ_READ0__par0_data__active 1
-#define R_IRQ_READ0__par0_data__inactive 0
-#define R_IRQ_READ0__ata_irq1__BITNR 9
-#define R_IRQ_READ0__ata_irq1__WIDTH 1
-#define R_IRQ_READ0__ata_irq1__active 1
-#define R_IRQ_READ0__ata_irq1__inactive 0
-#define R_IRQ_READ0__par0_ready__BITNR 8
-#define R_IRQ_READ0__par0_ready__WIDTH 1
-#define R_IRQ_READ0__par0_ready__active 1
-#define R_IRQ_READ0__par0_ready__inactive 0
-#define R_IRQ_READ0__ata_irq0__BITNR 8
-#define R_IRQ_READ0__ata_irq0__WIDTH 1
-#define R_IRQ_READ0__ata_irq0__active 1
-#define R_IRQ_READ0__ata_irq0__inactive 0
-#define R_IRQ_READ0__mio__BITNR 8
-#define R_IRQ_READ0__mio__WIDTH 1
-#define R_IRQ_READ0__mio__active 1
-#define R_IRQ_READ0__mio__inactive 0
-#define R_IRQ_READ0__scsi0__BITNR 8
-#define R_IRQ_READ0__scsi0__WIDTH 1
-#define R_IRQ_READ0__scsi0__active 1
-#define R_IRQ_READ0__scsi0__inactive 0
-#define R_IRQ_READ0__ata_dmaend__BITNR 7
-#define R_IRQ_READ0__ata_dmaend__WIDTH 1
-#define R_IRQ_READ0__ata_dmaend__active 1
-#define R_IRQ_READ0__ata_dmaend__inactive 0
-#define R_IRQ_READ0__irq_ext_vector_nr__BITNR 5
-#define R_IRQ_READ0__irq_ext_vector_nr__WIDTH 1
-#define R_IRQ_READ0__irq_ext_vector_nr__active 1
-#define R_IRQ_READ0__irq_ext_vector_nr__inactive 0
-#define R_IRQ_READ0__irq_int_vector_nr__BITNR 4
-#define R_IRQ_READ0__irq_int_vector_nr__WIDTH 1
-#define R_IRQ_READ0__irq_int_vector_nr__active 1
-#define R_IRQ_READ0__irq_int_vector_nr__inactive 0
-#define R_IRQ_READ0__ext_dma1__BITNR 3
-#define R_IRQ_READ0__ext_dma1__WIDTH 1
-#define R_IRQ_READ0__ext_dma1__active 1
-#define R_IRQ_READ0__ext_dma1__inactive 0
-#define R_IRQ_READ0__ext_dma0__BITNR 2
-#define R_IRQ_READ0__ext_dma0__WIDTH 1
-#define R_IRQ_READ0__ext_dma0__active 1
-#define R_IRQ_READ0__ext_dma0__inactive 0
-#define R_IRQ_READ0__timer1__BITNR 1
-#define R_IRQ_READ0__timer1__WIDTH 1
-#define R_IRQ_READ0__timer1__active 1
-#define R_IRQ_READ0__timer1__inactive 0
-#define R_IRQ_READ0__timer0__BITNR 0
-#define R_IRQ_READ0__timer0__WIDTH 1
-#define R_IRQ_READ0__timer0__active 1
-#define R_IRQ_READ0__timer0__inactive 0
-
-#define R_IRQ_MASK0_SET (IO_TYPECAST_UDWORD 0xb00000c4)
-#define R_IRQ_MASK0_SET__nmi_pin__BITNR 31
-#define R_IRQ_MASK0_SET__nmi_pin__WIDTH 1
-#define R_IRQ_MASK0_SET__nmi_pin__set 1
-#define R_IRQ_MASK0_SET__nmi_pin__nop 0
-#define R_IRQ_MASK0_SET__watchdog_nmi__BITNR 30
-#define R_IRQ_MASK0_SET__watchdog_nmi__WIDTH 1
-#define R_IRQ_MASK0_SET__watchdog_nmi__set 1
-#define R_IRQ_MASK0_SET__watchdog_nmi__nop 0
-#define R_IRQ_MASK0_SET__sqe_test_error__BITNR 29
-#define R_IRQ_MASK0_SET__sqe_test_error__WIDTH 1
-#define R_IRQ_MASK0_SET__sqe_test_error__set 1
-#define R_IRQ_MASK0_SET__sqe_test_error__nop 0
-#define R_IRQ_MASK0_SET__carrier_loss__BITNR 28
-#define R_IRQ_MASK0_SET__carrier_loss__WIDTH 1
-#define R_IRQ_MASK0_SET__carrier_loss__set 1
-#define R_IRQ_MASK0_SET__carrier_loss__nop 0
-#define R_IRQ_MASK0_SET__deferred__BITNR 27
-#define R_IRQ_MASK0_SET__deferred__WIDTH 1
-#define R_IRQ_MASK0_SET__deferred__set 1
-#define R_IRQ_MASK0_SET__deferred__nop 0
-#define R_IRQ_MASK0_SET__late_col__BITNR 26
-#define R_IRQ_MASK0_SET__late_col__WIDTH 1
-#define R_IRQ_MASK0_SET__late_col__set 1
-#define R_IRQ_MASK0_SET__late_col__nop 0
-#define R_IRQ_MASK0_SET__multiple_col__BITNR 25
-#define R_IRQ_MASK0_SET__multiple_col__WIDTH 1
-#define R_IRQ_MASK0_SET__multiple_col__set 1
-#define R_IRQ_MASK0_SET__multiple_col__nop 0
-#define R_IRQ_MASK0_SET__single_col__BITNR 24
-#define R_IRQ_MASK0_SET__single_col__WIDTH 1
-#define R_IRQ_MASK0_SET__single_col__set 1
-#define R_IRQ_MASK0_SET__single_col__nop 0
-#define R_IRQ_MASK0_SET__congestion__BITNR 23
-#define R_IRQ_MASK0_SET__congestion__WIDTH 1
-#define R_IRQ_MASK0_SET__congestion__set 1
-#define R_IRQ_MASK0_SET__congestion__nop 0
-#define R_IRQ_MASK0_SET__oversize__BITNR 22
-#define R_IRQ_MASK0_SET__oversize__WIDTH 1
-#define R_IRQ_MASK0_SET__oversize__set 1
-#define R_IRQ_MASK0_SET__oversize__nop 0
-#define R_IRQ_MASK0_SET__alignment_error__BITNR 21
-#define R_IRQ_MASK0_SET__alignment_error__WIDTH 1
-#define R_IRQ_MASK0_SET__alignment_error__set 1
-#define R_IRQ_MASK0_SET__alignment_error__nop 0
-#define R_IRQ_MASK0_SET__crc_error__BITNR 20
-#define R_IRQ_MASK0_SET__crc_error__WIDTH 1
-#define R_IRQ_MASK0_SET__crc_error__set 1
-#define R_IRQ_MASK0_SET__crc_error__nop 0
-#define R_IRQ_MASK0_SET__overrun__BITNR 19
-#define R_IRQ_MASK0_SET__overrun__WIDTH 1
-#define R_IRQ_MASK0_SET__overrun__set 1
-#define R_IRQ_MASK0_SET__overrun__nop 0
-#define R_IRQ_MASK0_SET__underrun__BITNR 18
-#define R_IRQ_MASK0_SET__underrun__WIDTH 1
-#define R_IRQ_MASK0_SET__underrun__set 1
-#define R_IRQ_MASK0_SET__underrun__nop 0
-#define R_IRQ_MASK0_SET__excessive_col__BITNR 17
-#define R_IRQ_MASK0_SET__excessive_col__WIDTH 1
-#define R_IRQ_MASK0_SET__excessive_col__set 1
-#define R_IRQ_MASK0_SET__excessive_col__nop 0
-#define R_IRQ_MASK0_SET__mdio__BITNR 16
-#define R_IRQ_MASK0_SET__mdio__WIDTH 1
-#define R_IRQ_MASK0_SET__mdio__set 1
-#define R_IRQ_MASK0_SET__mdio__nop 0
-#define R_IRQ_MASK0_SET__ata_drq3__BITNR 15
-#define R_IRQ_MASK0_SET__ata_drq3__WIDTH 1
-#define R_IRQ_MASK0_SET__ata_drq3__set 1
-#define R_IRQ_MASK0_SET__ata_drq3__nop 0
-#define R_IRQ_MASK0_SET__ata_drq2__BITNR 14
-#define R_IRQ_MASK0_SET__ata_drq2__WIDTH 1
-#define R_IRQ_MASK0_SET__ata_drq2__set 1
-#define R_IRQ_MASK0_SET__ata_drq2__nop 0
-#define R_IRQ_MASK0_SET__ata_drq1__BITNR 13
-#define R_IRQ_MASK0_SET__ata_drq1__WIDTH 1
-#define R_IRQ_MASK0_SET__ata_drq1__set 1
-#define R_IRQ_MASK0_SET__ata_drq1__nop 0
-#define R_IRQ_MASK0_SET__ata_drq0__BITNR 12
-#define R_IRQ_MASK0_SET__ata_drq0__WIDTH 1
-#define R_IRQ_MASK0_SET__ata_drq0__set 1
-#define R_IRQ_MASK0_SET__ata_drq0__nop 0
-#define R_IRQ_MASK0_SET__par0_ecp_cmd__BITNR 11
-#define R_IRQ_MASK0_SET__par0_ecp_cmd__WIDTH 1
-#define R_IRQ_MASK0_SET__par0_ecp_cmd__set 1
-#define R_IRQ_MASK0_SET__par0_ecp_cmd__nop 0
-#define R_IRQ_MASK0_SET__ata_irq3__BITNR 11
-#define R_IRQ_MASK0_SET__ata_irq3__WIDTH 1
-#define R_IRQ_MASK0_SET__ata_irq3__set 1
-#define R_IRQ_MASK0_SET__ata_irq3__nop 0
-#define R_IRQ_MASK0_SET__par0_peri__BITNR 10
-#define R_IRQ_MASK0_SET__par0_peri__WIDTH 1
-#define R_IRQ_MASK0_SET__par0_peri__set 1
-#define R_IRQ_MASK0_SET__par0_peri__nop 0
-#define R_IRQ_MASK0_SET__ata_irq2__BITNR 10
-#define R_IRQ_MASK0_SET__ata_irq2__WIDTH 1
-#define R_IRQ_MASK0_SET__ata_irq2__set 1
-#define R_IRQ_MASK0_SET__ata_irq2__nop 0
-#define R_IRQ_MASK0_SET__par0_data__BITNR 9
-#define R_IRQ_MASK0_SET__par0_data__WIDTH 1
-#define R_IRQ_MASK0_SET__par0_data__set 1
-#define R_IRQ_MASK0_SET__par0_data__nop 0
-#define R_IRQ_MASK0_SET__ata_irq1__BITNR 9
-#define R_IRQ_MASK0_SET__ata_irq1__WIDTH 1
-#define R_IRQ_MASK0_SET__ata_irq1__set 1
-#define R_IRQ_MASK0_SET__ata_irq1__nop 0
-#define R_IRQ_MASK0_SET__par0_ready__BITNR 8
-#define R_IRQ_MASK0_SET__par0_ready__WIDTH 1
-#define R_IRQ_MASK0_SET__par0_ready__set 1
-#define R_IRQ_MASK0_SET__par0_ready__nop 0
-#define R_IRQ_MASK0_SET__ata_irq0__BITNR 8
-#define R_IRQ_MASK0_SET__ata_irq0__WIDTH 1
-#define R_IRQ_MASK0_SET__ata_irq0__set 1
-#define R_IRQ_MASK0_SET__ata_irq0__nop 0
-#define R_IRQ_MASK0_SET__mio__BITNR 8
-#define R_IRQ_MASK0_SET__mio__WIDTH 1
-#define R_IRQ_MASK0_SET__mio__set 1
-#define R_IRQ_MASK0_SET__mio__nop 0
-#define R_IRQ_MASK0_SET__scsi0__BITNR 8
-#define R_IRQ_MASK0_SET__scsi0__WIDTH 1
-#define R_IRQ_MASK0_SET__scsi0__set 1
-#define R_IRQ_MASK0_SET__scsi0__nop 0
-#define R_IRQ_MASK0_SET__ata_dmaend__BITNR 7
-#define R_IRQ_MASK0_SET__ata_dmaend__WIDTH 1
-#define R_IRQ_MASK0_SET__ata_dmaend__set 1
-#define R_IRQ_MASK0_SET__ata_dmaend__nop 0
-#define R_IRQ_MASK0_SET__irq_ext_vector_nr__BITNR 5
-#define R_IRQ_MASK0_SET__irq_ext_vector_nr__WIDTH 1
-#define R_IRQ_MASK0_SET__irq_ext_vector_nr__set 1
-#define R_IRQ_MASK0_SET__irq_ext_vector_nr__nop 0
-#define R_IRQ_MASK0_SET__irq_int_vector_nr__BITNR 4
-#define R_IRQ_MASK0_SET__irq_int_vector_nr__WIDTH 1
-#define R_IRQ_MASK0_SET__irq_int_vector_nr__set 1
-#define R_IRQ_MASK0_SET__irq_int_vector_nr__nop 0
-#define R_IRQ_MASK0_SET__ext_dma1__BITNR 3
-#define R_IRQ_MASK0_SET__ext_dma1__WIDTH 1
-#define R_IRQ_MASK0_SET__ext_dma1__set 1
-#define R_IRQ_MASK0_SET__ext_dma1__nop 0
-#define R_IRQ_MASK0_SET__ext_dma0__BITNR 2
-#define R_IRQ_MASK0_SET__ext_dma0__WIDTH 1
-#define R_IRQ_MASK0_SET__ext_dma0__set 1
-#define R_IRQ_MASK0_SET__ext_dma0__nop 0
-#define R_IRQ_MASK0_SET__timer1__BITNR 1
-#define R_IRQ_MASK0_SET__timer1__WIDTH 1
-#define R_IRQ_MASK0_SET__timer1__set 1
-#define R_IRQ_MASK0_SET__timer1__nop 0
-#define R_IRQ_MASK0_SET__timer0__BITNR 0
-#define R_IRQ_MASK0_SET__timer0__WIDTH 1
-#define R_IRQ_MASK0_SET__timer0__set 1
-#define R_IRQ_MASK0_SET__timer0__nop 0
-
-#define R_IRQ_MASK1_RD (IO_TYPECAST_RO_UDWORD 0xb00000c8)
-#define R_IRQ_MASK1_RD__sw_int7__BITNR 31
-#define R_IRQ_MASK1_RD__sw_int7__WIDTH 1
-#define R_IRQ_MASK1_RD__sw_int7__active 1
-#define R_IRQ_MASK1_RD__sw_int7__inactive 0
-#define R_IRQ_MASK1_RD__sw_int6__BITNR 30
-#define R_IRQ_MASK1_RD__sw_int6__WIDTH 1
-#define R_IRQ_MASK1_RD__sw_int6__active 1
-#define R_IRQ_MASK1_RD__sw_int6__inactive 0
-#define R_IRQ_MASK1_RD__sw_int5__BITNR 29
-#define R_IRQ_MASK1_RD__sw_int5__WIDTH 1
-#define R_IRQ_MASK1_RD__sw_int5__active 1
-#define R_IRQ_MASK1_RD__sw_int5__inactive 0
-#define R_IRQ_MASK1_RD__sw_int4__BITNR 28
-#define R_IRQ_MASK1_RD__sw_int4__WIDTH 1
-#define R_IRQ_MASK1_RD__sw_int4__active 1
-#define R_IRQ_MASK1_RD__sw_int4__inactive 0
-#define R_IRQ_MASK1_RD__sw_int3__BITNR 27
-#define R_IRQ_MASK1_RD__sw_int3__WIDTH 1
-#define R_IRQ_MASK1_RD__sw_int3__active 1
-#define R_IRQ_MASK1_RD__sw_int3__inactive 0
-#define R_IRQ_MASK1_RD__sw_int2__BITNR 26
-#define R_IRQ_MASK1_RD__sw_int2__WIDTH 1
-#define R_IRQ_MASK1_RD__sw_int2__active 1
-#define R_IRQ_MASK1_RD__sw_int2__inactive 0
-#define R_IRQ_MASK1_RD__sw_int1__BITNR 25
-#define R_IRQ_MASK1_RD__sw_int1__WIDTH 1
-#define R_IRQ_MASK1_RD__sw_int1__active 1
-#define R_IRQ_MASK1_RD__sw_int1__inactive 0
-#define R_IRQ_MASK1_RD__sw_int0__BITNR 24
-#define R_IRQ_MASK1_RD__sw_int0__WIDTH 1
-#define R_IRQ_MASK1_RD__sw_int0__active 1
-#define R_IRQ_MASK1_RD__sw_int0__inactive 0
-#define R_IRQ_MASK1_RD__par1_ecp_cmd__BITNR 19
-#define R_IRQ_MASK1_RD__par1_ecp_cmd__WIDTH 1
-#define R_IRQ_MASK1_RD__par1_ecp_cmd__active 1
-#define R_IRQ_MASK1_RD__par1_ecp_cmd__inactive 0
-#define R_IRQ_MASK1_RD__par1_peri__BITNR 18
-#define R_IRQ_MASK1_RD__par1_peri__WIDTH 1
-#define R_IRQ_MASK1_RD__par1_peri__active 1
-#define R_IRQ_MASK1_RD__par1_peri__inactive 0
-#define R_IRQ_MASK1_RD__par1_data__BITNR 17
-#define R_IRQ_MASK1_RD__par1_data__WIDTH 1
-#define R_IRQ_MASK1_RD__par1_data__active 1
-#define R_IRQ_MASK1_RD__par1_data__inactive 0
-#define R_IRQ_MASK1_RD__par1_ready__BITNR 16
-#define R_IRQ_MASK1_RD__par1_ready__WIDTH 1
-#define R_IRQ_MASK1_RD__par1_ready__active 1
-#define R_IRQ_MASK1_RD__par1_ready__inactive 0
-#define R_IRQ_MASK1_RD__scsi1__BITNR 16
-#define R_IRQ_MASK1_RD__scsi1__WIDTH 1
-#define R_IRQ_MASK1_RD__scsi1__active 1
-#define R_IRQ_MASK1_RD__scsi1__inactive 0
-#define R_IRQ_MASK1_RD__ser3_ready__BITNR 15
-#define R_IRQ_MASK1_RD__ser3_ready__WIDTH 1
-#define R_IRQ_MASK1_RD__ser3_ready__active 1
-#define R_IRQ_MASK1_RD__ser3_ready__inactive 0
-#define R_IRQ_MASK1_RD__ser3_data__BITNR 14
-#define R_IRQ_MASK1_RD__ser3_data__WIDTH 1
-#define R_IRQ_MASK1_RD__ser3_data__active 1
-#define R_IRQ_MASK1_RD__ser3_data__inactive 0
-#define R_IRQ_MASK1_RD__ser2_ready__BITNR 13
-#define R_IRQ_MASK1_RD__ser2_ready__WIDTH 1
-#define R_IRQ_MASK1_RD__ser2_ready__active 1
-#define R_IRQ_MASK1_RD__ser2_ready__inactive 0
-#define R_IRQ_MASK1_RD__ser2_data__BITNR 12
-#define R_IRQ_MASK1_RD__ser2_data__WIDTH 1
-#define R_IRQ_MASK1_RD__ser2_data__active 1
-#define R_IRQ_MASK1_RD__ser2_data__inactive 0
-#define R_IRQ_MASK1_RD__ser1_ready__BITNR 11
-#define R_IRQ_MASK1_RD__ser1_ready__WIDTH 1
-#define R_IRQ_MASK1_RD__ser1_ready__active 1
-#define R_IRQ_MASK1_RD__ser1_ready__inactive 0
-#define R_IRQ_MASK1_RD__ser1_data__BITNR 10
-#define R_IRQ_MASK1_RD__ser1_data__WIDTH 1
-#define R_IRQ_MASK1_RD__ser1_data__active 1
-#define R_IRQ_MASK1_RD__ser1_data__inactive 0
-#define R_IRQ_MASK1_RD__ser0_ready__BITNR 9
-#define R_IRQ_MASK1_RD__ser0_ready__WIDTH 1
-#define R_IRQ_MASK1_RD__ser0_ready__active 1
-#define R_IRQ_MASK1_RD__ser0_ready__inactive 0
-#define R_IRQ_MASK1_RD__ser0_data__BITNR 8
-#define R_IRQ_MASK1_RD__ser0_data__WIDTH 1
-#define R_IRQ_MASK1_RD__ser0_data__active 1
-#define R_IRQ_MASK1_RD__ser0_data__inactive 0
-#define R_IRQ_MASK1_RD__pa7__BITNR 7
-#define R_IRQ_MASK1_RD__pa7__WIDTH 1
-#define R_IRQ_MASK1_RD__pa7__active 1
-#define R_IRQ_MASK1_RD__pa7__inactive 0
-#define R_IRQ_MASK1_RD__pa6__BITNR 6
-#define R_IRQ_MASK1_RD__pa6__WIDTH 1
-#define R_IRQ_MASK1_RD__pa6__active 1
-#define R_IRQ_MASK1_RD__pa6__inactive 0
-#define R_IRQ_MASK1_RD__pa5__BITNR 5
-#define R_IRQ_MASK1_RD__pa5__WIDTH 1
-#define R_IRQ_MASK1_RD__pa5__active 1
-#define R_IRQ_MASK1_RD__pa5__inactive 0
-#define R_IRQ_MASK1_RD__pa4__BITNR 4
-#define R_IRQ_MASK1_RD__pa4__WIDTH 1
-#define R_IRQ_MASK1_RD__pa4__active 1
-#define R_IRQ_MASK1_RD__pa4__inactive 0
-#define R_IRQ_MASK1_RD__pa3__BITNR 3
-#define R_IRQ_MASK1_RD__pa3__WIDTH 1
-#define R_IRQ_MASK1_RD__pa3__active 1
-#define R_IRQ_MASK1_RD__pa3__inactive 0
-#define R_IRQ_MASK1_RD__pa2__BITNR 2
-#define R_IRQ_MASK1_RD__pa2__WIDTH 1
-#define R_IRQ_MASK1_RD__pa2__active 1
-#define R_IRQ_MASK1_RD__pa2__inactive 0
-#define R_IRQ_MASK1_RD__pa1__BITNR 1
-#define R_IRQ_MASK1_RD__pa1__WIDTH 1
-#define R_IRQ_MASK1_RD__pa1__active 1
-#define R_IRQ_MASK1_RD__pa1__inactive 0
-#define R_IRQ_MASK1_RD__pa0__BITNR 0
-#define R_IRQ_MASK1_RD__pa0__WIDTH 1
-#define R_IRQ_MASK1_RD__pa0__active 1
-#define R_IRQ_MASK1_RD__pa0__inactive 0
-
-#define R_IRQ_MASK1_CLR (IO_TYPECAST_UDWORD 0xb00000c8)
-#define R_IRQ_MASK1_CLR__sw_int7__BITNR 31
-#define R_IRQ_MASK1_CLR__sw_int7__WIDTH 1
-#define R_IRQ_MASK1_CLR__sw_int7__clr 1
-#define R_IRQ_MASK1_CLR__sw_int7__nop 0
-#define R_IRQ_MASK1_CLR__sw_int6__BITNR 30
-#define R_IRQ_MASK1_CLR__sw_int6__WIDTH 1
-#define R_IRQ_MASK1_CLR__sw_int6__clr 1
-#define R_IRQ_MASK1_CLR__sw_int6__nop 0
-#define R_IRQ_MASK1_CLR__sw_int5__BITNR 29
-#define R_IRQ_MASK1_CLR__sw_int5__WIDTH 1
-#define R_IRQ_MASK1_CLR__sw_int5__clr 1
-#define R_IRQ_MASK1_CLR__sw_int5__nop 0
-#define R_IRQ_MASK1_CLR__sw_int4__BITNR 28
-#define R_IRQ_MASK1_CLR__sw_int4__WIDTH 1
-#define R_IRQ_MASK1_CLR__sw_int4__clr 1
-#define R_IRQ_MASK1_CLR__sw_int4__nop 0
-#define R_IRQ_MASK1_CLR__sw_int3__BITNR 27
-#define R_IRQ_MASK1_CLR__sw_int3__WIDTH 1
-#define R_IRQ_MASK1_CLR__sw_int3__clr 1
-#define R_IRQ_MASK1_CLR__sw_int3__nop 0
-#define R_IRQ_MASK1_CLR__sw_int2__BITNR 26
-#define R_IRQ_MASK1_CLR__sw_int2__WIDTH 1
-#define R_IRQ_MASK1_CLR__sw_int2__clr 1
-#define R_IRQ_MASK1_CLR__sw_int2__nop 0
-#define R_IRQ_MASK1_CLR__sw_int1__BITNR 25
-#define R_IRQ_MASK1_CLR__sw_int1__WIDTH 1
-#define R_IRQ_MASK1_CLR__sw_int1__clr 1
-#define R_IRQ_MASK1_CLR__sw_int1__nop 0
-#define R_IRQ_MASK1_CLR__sw_int0__BITNR 24
-#define R_IRQ_MASK1_CLR__sw_int0__WIDTH 1
-#define R_IRQ_MASK1_CLR__sw_int0__clr 1
-#define R_IRQ_MASK1_CLR__sw_int0__nop 0
-#define R_IRQ_MASK1_CLR__par1_ecp_cmd__BITNR 19
-#define R_IRQ_MASK1_CLR__par1_ecp_cmd__WIDTH 1
-#define R_IRQ_MASK1_CLR__par1_ecp_cmd__clr 1
-#define R_IRQ_MASK1_CLR__par1_ecp_cmd__nop 0
-#define R_IRQ_MASK1_CLR__par1_peri__BITNR 18
-#define R_IRQ_MASK1_CLR__par1_peri__WIDTH 1
-#define R_IRQ_MASK1_CLR__par1_peri__clr 1
-#define R_IRQ_MASK1_CLR__par1_peri__nop 0
-#define R_IRQ_MASK1_CLR__par1_data__BITNR 17
-#define R_IRQ_MASK1_CLR__par1_data__WIDTH 1
-#define R_IRQ_MASK1_CLR__par1_data__clr 1
-#define R_IRQ_MASK1_CLR__par1_data__nop 0
-#define R_IRQ_MASK1_CLR__par1_ready__BITNR 16
-#define R_IRQ_MASK1_CLR__par1_ready__WIDTH 1
-#define R_IRQ_MASK1_CLR__par1_ready__clr 1
-#define R_IRQ_MASK1_CLR__par1_ready__nop 0
-#define R_IRQ_MASK1_CLR__scsi1__BITNR 16
-#define R_IRQ_MASK1_CLR__scsi1__WIDTH 1
-#define R_IRQ_MASK1_CLR__scsi1__clr 1
-#define R_IRQ_MASK1_CLR__scsi1__nop 0
-#define R_IRQ_MASK1_CLR__ser3_ready__BITNR 15
-#define R_IRQ_MASK1_CLR__ser3_ready__WIDTH 1
-#define R_IRQ_MASK1_CLR__ser3_ready__clr 1
-#define R_IRQ_MASK1_CLR__ser3_ready__nop 0
-#define R_IRQ_MASK1_CLR__ser3_data__BITNR 14
-#define R_IRQ_MASK1_CLR__ser3_data__WIDTH 1
-#define R_IRQ_MASK1_CLR__ser3_data__clr 1
-#define R_IRQ_MASK1_CLR__ser3_data__nop 0
-#define R_IRQ_MASK1_CLR__ser2_ready__BITNR 13
-#define R_IRQ_MASK1_CLR__ser2_ready__WIDTH 1
-#define R_IRQ_MASK1_CLR__ser2_ready__clr 1
-#define R_IRQ_MASK1_CLR__ser2_ready__nop 0
-#define R_IRQ_MASK1_CLR__ser2_data__BITNR 12
-#define R_IRQ_MASK1_CLR__ser2_data__WIDTH 1
-#define R_IRQ_MASK1_CLR__ser2_data__clr 1
-#define R_IRQ_MASK1_CLR__ser2_data__nop 0
-#define R_IRQ_MASK1_CLR__ser1_ready__BITNR 11
-#define R_IRQ_MASK1_CLR__ser1_ready__WIDTH 1
-#define R_IRQ_MASK1_CLR__ser1_ready__clr 1
-#define R_IRQ_MASK1_CLR__ser1_ready__nop 0
-#define R_IRQ_MASK1_CLR__ser1_data__BITNR 10
-#define R_IRQ_MASK1_CLR__ser1_data__WIDTH 1
-#define R_IRQ_MASK1_CLR__ser1_data__clr 1
-#define R_IRQ_MASK1_CLR__ser1_data__nop 0
-#define R_IRQ_MASK1_CLR__ser0_ready__BITNR 9
-#define R_IRQ_MASK1_CLR__ser0_ready__WIDTH 1
-#define R_IRQ_MASK1_CLR__ser0_ready__clr 1
-#define R_IRQ_MASK1_CLR__ser0_ready__nop 0
-#define R_IRQ_MASK1_CLR__ser0_data__BITNR 8
-#define R_IRQ_MASK1_CLR__ser0_data__WIDTH 1
-#define R_IRQ_MASK1_CLR__ser0_data__clr 1
-#define R_IRQ_MASK1_CLR__ser0_data__nop 0
-#define R_IRQ_MASK1_CLR__pa7__BITNR 7
-#define R_IRQ_MASK1_CLR__pa7__WIDTH 1
-#define R_IRQ_MASK1_CLR__pa7__clr 1
-#define R_IRQ_MASK1_CLR__pa7__nop 0
-#define R_IRQ_MASK1_CLR__pa6__BITNR 6
-#define R_IRQ_MASK1_CLR__pa6__WIDTH 1
-#define R_IRQ_MASK1_CLR__pa6__clr 1
-#define R_IRQ_MASK1_CLR__pa6__nop 0
-#define R_IRQ_MASK1_CLR__pa5__BITNR 5
-#define R_IRQ_MASK1_CLR__pa5__WIDTH 1
-#define R_IRQ_MASK1_CLR__pa5__clr 1
-#define R_IRQ_MASK1_CLR__pa5__nop 0
-#define R_IRQ_MASK1_CLR__pa4__BITNR 4
-#define R_IRQ_MASK1_CLR__pa4__WIDTH 1
-#define R_IRQ_MASK1_CLR__pa4__clr 1
-#define R_IRQ_MASK1_CLR__pa4__nop 0
-#define R_IRQ_MASK1_CLR__pa3__BITNR 3
-#define R_IRQ_MASK1_CLR__pa3__WIDTH 1
-#define R_IRQ_MASK1_CLR__pa3__clr 1
-#define R_IRQ_MASK1_CLR__pa3__nop 0
-#define R_IRQ_MASK1_CLR__pa2__BITNR 2
-#define R_IRQ_MASK1_CLR__pa2__WIDTH 1
-#define R_IRQ_MASK1_CLR__pa2__clr 1
-#define R_IRQ_MASK1_CLR__pa2__nop 0
-#define R_IRQ_MASK1_CLR__pa1__BITNR 1
-#define R_IRQ_MASK1_CLR__pa1__WIDTH 1
-#define R_IRQ_MASK1_CLR__pa1__clr 1
-#define R_IRQ_MASK1_CLR__pa1__nop 0
-#define R_IRQ_MASK1_CLR__pa0__BITNR 0
-#define R_IRQ_MASK1_CLR__pa0__WIDTH 1
-#define R_IRQ_MASK1_CLR__pa0__clr 1
-#define R_IRQ_MASK1_CLR__pa0__nop 0
-
-#define R_IRQ_READ1 (IO_TYPECAST_RO_UDWORD 0xb00000cc)
-#define R_IRQ_READ1__sw_int7__BITNR 31
-#define R_IRQ_READ1__sw_int7__WIDTH 1
-#define R_IRQ_READ1__sw_int7__active 1
-#define R_IRQ_READ1__sw_int7__inactive 0
-#define R_IRQ_READ1__sw_int6__BITNR 30
-#define R_IRQ_READ1__sw_int6__WIDTH 1
-#define R_IRQ_READ1__sw_int6__active 1
-#define R_IRQ_READ1__sw_int6__inactive 0
-#define R_IRQ_READ1__sw_int5__BITNR 29
-#define R_IRQ_READ1__sw_int5__WIDTH 1
-#define R_IRQ_READ1__sw_int5__active 1
-#define R_IRQ_READ1__sw_int5__inactive 0
-#define R_IRQ_READ1__sw_int4__BITNR 28
-#define R_IRQ_READ1__sw_int4__WIDTH 1
-#define R_IRQ_READ1__sw_int4__active 1
-#define R_IRQ_READ1__sw_int4__inactive 0
-#define R_IRQ_READ1__sw_int3__BITNR 27
-#define R_IRQ_READ1__sw_int3__WIDTH 1
-#define R_IRQ_READ1__sw_int3__active 1
-#define R_IRQ_READ1__sw_int3__inactive 0
-#define R_IRQ_READ1__sw_int2__BITNR 26
-#define R_IRQ_READ1__sw_int2__WIDTH 1
-#define R_IRQ_READ1__sw_int2__active 1
-#define R_IRQ_READ1__sw_int2__inactive 0
-#define R_IRQ_READ1__sw_int1__BITNR 25
-#define R_IRQ_READ1__sw_int1__WIDTH 1
-#define R_IRQ_READ1__sw_int1__active 1
-#define R_IRQ_READ1__sw_int1__inactive 0
-#define R_IRQ_READ1__sw_int0__BITNR 24
-#define R_IRQ_READ1__sw_int0__WIDTH 1
-#define R_IRQ_READ1__sw_int0__active 1
-#define R_IRQ_READ1__sw_int0__inactive 0
-#define R_IRQ_READ1__par1_ecp_cmd__BITNR 19
-#define R_IRQ_READ1__par1_ecp_cmd__WIDTH 1
-#define R_IRQ_READ1__par1_ecp_cmd__active 1
-#define R_IRQ_READ1__par1_ecp_cmd__inactive 0
-#define R_IRQ_READ1__par1_peri__BITNR 18
-#define R_IRQ_READ1__par1_peri__WIDTH 1
-#define R_IRQ_READ1__par1_peri__active 1
-#define R_IRQ_READ1__par1_peri__inactive 0
-#define R_IRQ_READ1__par1_data__BITNR 17
-#define R_IRQ_READ1__par1_data__WIDTH 1
-#define R_IRQ_READ1__par1_data__active 1
-#define R_IRQ_READ1__par1_data__inactive 0
-#define R_IRQ_READ1__par1_ready__BITNR 16
-#define R_IRQ_READ1__par1_ready__WIDTH 1
-#define R_IRQ_READ1__par1_ready__active 1
-#define R_IRQ_READ1__par1_ready__inactive 0
-#define R_IRQ_READ1__scsi1__BITNR 16
-#define R_IRQ_READ1__scsi1__WIDTH 1
-#define R_IRQ_READ1__scsi1__active 1
-#define R_IRQ_READ1__scsi1__inactive 0
-#define R_IRQ_READ1__ser3_ready__BITNR 15
-#define R_IRQ_READ1__ser3_ready__WIDTH 1
-#define R_IRQ_READ1__ser3_ready__active 1
-#define R_IRQ_READ1__ser3_ready__inactive 0
-#define R_IRQ_READ1__ser3_data__BITNR 14
-#define R_IRQ_READ1__ser3_data__WIDTH 1
-#define R_IRQ_READ1__ser3_data__active 1
-#define R_IRQ_READ1__ser3_data__inactive 0
-#define R_IRQ_READ1__ser2_ready__BITNR 13
-#define R_IRQ_READ1__ser2_ready__WIDTH 1
-#define R_IRQ_READ1__ser2_ready__active 1
-#define R_IRQ_READ1__ser2_ready__inactive 0
-#define R_IRQ_READ1__ser2_data__BITNR 12
-#define R_IRQ_READ1__ser2_data__WIDTH 1
-#define R_IRQ_READ1__ser2_data__active 1
-#define R_IRQ_READ1__ser2_data__inactive 0
-#define R_IRQ_READ1__ser1_ready__BITNR 11
-#define R_IRQ_READ1__ser1_ready__WIDTH 1
-#define R_IRQ_READ1__ser1_ready__active 1
-#define R_IRQ_READ1__ser1_ready__inactive 0
-#define R_IRQ_READ1__ser1_data__BITNR 10
-#define R_IRQ_READ1__ser1_data__WIDTH 1
-#define R_IRQ_READ1__ser1_data__active 1
-#define R_IRQ_READ1__ser1_data__inactive 0
-#define R_IRQ_READ1__ser0_ready__BITNR 9
-#define R_IRQ_READ1__ser0_ready__WIDTH 1
-#define R_IRQ_READ1__ser0_ready__active 1
-#define R_IRQ_READ1__ser0_ready__inactive 0
-#define R_IRQ_READ1__ser0_data__BITNR 8
-#define R_IRQ_READ1__ser0_data__WIDTH 1
-#define R_IRQ_READ1__ser0_data__active 1
-#define R_IRQ_READ1__ser0_data__inactive 0
-#define R_IRQ_READ1__pa7__BITNR 7
-#define R_IRQ_READ1__pa7__WIDTH 1
-#define R_IRQ_READ1__pa7__active 1
-#define R_IRQ_READ1__pa7__inactive 0
-#define R_IRQ_READ1__pa6__BITNR 6
-#define R_IRQ_READ1__pa6__WIDTH 1
-#define R_IRQ_READ1__pa6__active 1
-#define R_IRQ_READ1__pa6__inactive 0
-#define R_IRQ_READ1__pa5__BITNR 5
-#define R_IRQ_READ1__pa5__WIDTH 1
-#define R_IRQ_READ1__pa5__active 1
-#define R_IRQ_READ1__pa5__inactive 0
-#define R_IRQ_READ1__pa4__BITNR 4
-#define R_IRQ_READ1__pa4__WIDTH 1
-#define R_IRQ_READ1__pa4__active 1
-#define R_IRQ_READ1__pa4__inactive 0
-#define R_IRQ_READ1__pa3__BITNR 3
-#define R_IRQ_READ1__pa3__WIDTH 1
-#define R_IRQ_READ1__pa3__active 1
-#define R_IRQ_READ1__pa3__inactive 0
-#define R_IRQ_READ1__pa2__BITNR 2
-#define R_IRQ_READ1__pa2__WIDTH 1
-#define R_IRQ_READ1__pa2__active 1
-#define R_IRQ_READ1__pa2__inactive 0
-#define R_IRQ_READ1__pa1__BITNR 1
-#define R_IRQ_READ1__pa1__WIDTH 1
-#define R_IRQ_READ1__pa1__active 1
-#define R_IRQ_READ1__pa1__inactive 0
-#define R_IRQ_READ1__pa0__BITNR 0
-#define R_IRQ_READ1__pa0__WIDTH 1
-#define R_IRQ_READ1__pa0__active 1
-#define R_IRQ_READ1__pa0__inactive 0
-
-#define R_IRQ_MASK1_SET (IO_TYPECAST_UDWORD 0xb00000cc)
-#define R_IRQ_MASK1_SET__sw_int7__BITNR 31
-#define R_IRQ_MASK1_SET__sw_int7__WIDTH 1
-#define R_IRQ_MASK1_SET__sw_int7__set 1
-#define R_IRQ_MASK1_SET__sw_int7__nop 0
-#define R_IRQ_MASK1_SET__sw_int6__BITNR 30
-#define R_IRQ_MASK1_SET__sw_int6__WIDTH 1
-#define R_IRQ_MASK1_SET__sw_int6__set 1
-#define R_IRQ_MASK1_SET__sw_int6__nop 0
-#define R_IRQ_MASK1_SET__sw_int5__BITNR 29
-#define R_IRQ_MASK1_SET__sw_int5__WIDTH 1
-#define R_IRQ_MASK1_SET__sw_int5__set 1
-#define R_IRQ_MASK1_SET__sw_int5__nop 0
-#define R_IRQ_MASK1_SET__sw_int4__BITNR 28
-#define R_IRQ_MASK1_SET__sw_int4__WIDTH 1
-#define R_IRQ_MASK1_SET__sw_int4__set 1
-#define R_IRQ_MASK1_SET__sw_int4__nop 0
-#define R_IRQ_MASK1_SET__sw_int3__BITNR 27
-#define R_IRQ_MASK1_SET__sw_int3__WIDTH 1
-#define R_IRQ_MASK1_SET__sw_int3__set 1
-#define R_IRQ_MASK1_SET__sw_int3__nop 0
-#define R_IRQ_MASK1_SET__sw_int2__BITNR 26
-#define R_IRQ_MASK1_SET__sw_int2__WIDTH 1
-#define R_IRQ_MASK1_SET__sw_int2__set 1
-#define R_IRQ_MASK1_SET__sw_int2__nop 0
-#define R_IRQ_MASK1_SET__sw_int1__BITNR 25
-#define R_IRQ_MASK1_SET__sw_int1__WIDTH 1
-#define R_IRQ_MASK1_SET__sw_int1__set 1
-#define R_IRQ_MASK1_SET__sw_int1__nop 0
-#define R_IRQ_MASK1_SET__sw_int0__BITNR 24
-#define R_IRQ_MASK1_SET__sw_int0__WIDTH 1
-#define R_IRQ_MASK1_SET__sw_int0__set 1
-#define R_IRQ_MASK1_SET__sw_int0__nop 0
-#define R_IRQ_MASK1_SET__par1_ecp_cmd__BITNR 19
-#define R_IRQ_MASK1_SET__par1_ecp_cmd__WIDTH 1
-#define R_IRQ_MASK1_SET__par1_ecp_cmd__set 1
-#define R_IRQ_MASK1_SET__par1_ecp_cmd__nop 0
-#define R_IRQ_MASK1_SET__par1_peri__BITNR 18
-#define R_IRQ_MASK1_SET__par1_peri__WIDTH 1
-#define R_IRQ_MASK1_SET__par1_peri__set 1
-#define R_IRQ_MASK1_SET__par1_peri__nop 0
-#define R_IRQ_MASK1_SET__par1_data__BITNR 17
-#define R_IRQ_MASK1_SET__par1_data__WIDTH 1
-#define R_IRQ_MASK1_SET__par1_data__set 1
-#define R_IRQ_MASK1_SET__par1_data__nop 0
-#define R_IRQ_MASK1_SET__par1_ready__BITNR 16
-#define R_IRQ_MASK1_SET__par1_ready__WIDTH 1
-#define R_IRQ_MASK1_SET__par1_ready__set 1
-#define R_IRQ_MASK1_SET__par1_ready__nop 0
-#define R_IRQ_MASK1_SET__scsi1__BITNR 16
-#define R_IRQ_MASK1_SET__scsi1__WIDTH 1
-#define R_IRQ_MASK1_SET__scsi1__set 1
-#define R_IRQ_MASK1_SET__scsi1__nop 0
-#define R_IRQ_MASK1_SET__ser3_ready__BITNR 15
-#define R_IRQ_MASK1_SET__ser3_ready__WIDTH 1
-#define R_IRQ_MASK1_SET__ser3_ready__set 1
-#define R_IRQ_MASK1_SET__ser3_ready__nop 0
-#define R_IRQ_MASK1_SET__ser3_data__BITNR 14
-#define R_IRQ_MASK1_SET__ser3_data__WIDTH 1
-#define R_IRQ_MASK1_SET__ser3_data__set 1
-#define R_IRQ_MASK1_SET__ser3_data__nop 0
-#define R_IRQ_MASK1_SET__ser2_ready__BITNR 13
-#define R_IRQ_MASK1_SET__ser2_ready__WIDTH 1
-#define R_IRQ_MASK1_SET__ser2_ready__set 1
-#define R_IRQ_MASK1_SET__ser2_ready__nop 0
-#define R_IRQ_MASK1_SET__ser2_data__BITNR 12
-#define R_IRQ_MASK1_SET__ser2_data__WIDTH 1
-#define R_IRQ_MASK1_SET__ser2_data__set 1
-#define R_IRQ_MASK1_SET__ser2_data__nop 0
-#define R_IRQ_MASK1_SET__ser1_ready__BITNR 11
-#define R_IRQ_MASK1_SET__ser1_ready__WIDTH 1
-#define R_IRQ_MASK1_SET__ser1_ready__set 1
-#define R_IRQ_MASK1_SET__ser1_ready__nop 0
-#define R_IRQ_MASK1_SET__ser1_data__BITNR 10
-#define R_IRQ_MASK1_SET__ser1_data__WIDTH 1
-#define R_IRQ_MASK1_SET__ser1_data__set 1
-#define R_IRQ_MASK1_SET__ser1_data__nop 0
-#define R_IRQ_MASK1_SET__ser0_ready__BITNR 9
-#define R_IRQ_MASK1_SET__ser0_ready__WIDTH 1
-#define R_IRQ_MASK1_SET__ser0_ready__set 1
-#define R_IRQ_MASK1_SET__ser0_ready__nop 0
-#define R_IRQ_MASK1_SET__ser0_data__BITNR 8
-#define R_IRQ_MASK1_SET__ser0_data__WIDTH 1
-#define R_IRQ_MASK1_SET__ser0_data__set 1
-#define R_IRQ_MASK1_SET__ser0_data__nop 0
-#define R_IRQ_MASK1_SET__pa7__BITNR 7
-#define R_IRQ_MASK1_SET__pa7__WIDTH 1
-#define R_IRQ_MASK1_SET__pa7__set 1
-#define R_IRQ_MASK1_SET__pa7__nop 0
-#define R_IRQ_MASK1_SET__pa6__BITNR 6
-#define R_IRQ_MASK1_SET__pa6__WIDTH 1
-#define R_IRQ_MASK1_SET__pa6__set 1
-#define R_IRQ_MASK1_SET__pa6__nop 0
-#define R_IRQ_MASK1_SET__pa5__BITNR 5
-#define R_IRQ_MASK1_SET__pa5__WIDTH 1
-#define R_IRQ_MASK1_SET__pa5__set 1
-#define R_IRQ_MASK1_SET__pa5__nop 0
-#define R_IRQ_MASK1_SET__pa4__BITNR 4
-#define R_IRQ_MASK1_SET__pa4__WIDTH 1
-#define R_IRQ_MASK1_SET__pa4__set 1
-#define R_IRQ_MASK1_SET__pa4__nop 0
-#define R_IRQ_MASK1_SET__pa3__BITNR 3
-#define R_IRQ_MASK1_SET__pa3__WIDTH 1
-#define R_IRQ_MASK1_SET__pa3__set 1
-#define R_IRQ_MASK1_SET__pa3__nop 0
-#define R_IRQ_MASK1_SET__pa2__BITNR 2
-#define R_IRQ_MASK1_SET__pa2__WIDTH 1
-#define R_IRQ_MASK1_SET__pa2__set 1
-#define R_IRQ_MASK1_SET__pa2__nop 0
-#define R_IRQ_MASK1_SET__pa1__BITNR 1
-#define R_IRQ_MASK1_SET__pa1__WIDTH 1
-#define R_IRQ_MASK1_SET__pa1__set 1
-#define R_IRQ_MASK1_SET__pa1__nop 0
-#define R_IRQ_MASK1_SET__pa0__BITNR 0
-#define R_IRQ_MASK1_SET__pa0__WIDTH 1
-#define R_IRQ_MASK1_SET__pa0__set 1
-#define R_IRQ_MASK1_SET__pa0__nop 0
-
-#define R_IRQ_MASK2_RD (IO_TYPECAST_RO_UDWORD 0xb00000d0)
-#define R_IRQ_MASK2_RD__dma8_sub3_descr__BITNR 23
-#define R_IRQ_MASK2_RD__dma8_sub3_descr__WIDTH 1
-#define R_IRQ_MASK2_RD__dma8_sub3_descr__active 1
-#define R_IRQ_MASK2_RD__dma8_sub3_descr__inactive 0
-#define R_IRQ_MASK2_RD__dma8_sub2_descr__BITNR 22
-#define R_IRQ_MASK2_RD__dma8_sub2_descr__WIDTH 1
-#define R_IRQ_MASK2_RD__dma8_sub2_descr__active 1
-#define R_IRQ_MASK2_RD__dma8_sub2_descr__inactive 0
-#define R_IRQ_MASK2_RD__dma8_sub1_descr__BITNR 21
-#define R_IRQ_MASK2_RD__dma8_sub1_descr__WIDTH 1
-#define R_IRQ_MASK2_RD__dma8_sub1_descr__active 1
-#define R_IRQ_MASK2_RD__dma8_sub1_descr__inactive 0
-#define R_IRQ_MASK2_RD__dma8_sub0_descr__BITNR 20
-#define R_IRQ_MASK2_RD__dma8_sub0_descr__WIDTH 1
-#define R_IRQ_MASK2_RD__dma8_sub0_descr__active 1
-#define R_IRQ_MASK2_RD__dma8_sub0_descr__inactive 0
-#define R_IRQ_MASK2_RD__dma9_eop__BITNR 19
-#define R_IRQ_MASK2_RD__dma9_eop__WIDTH 1
-#define R_IRQ_MASK2_RD__dma9_eop__active 1
-#define R_IRQ_MASK2_RD__dma9_eop__inactive 0
-#define R_IRQ_MASK2_RD__dma9_descr__BITNR 18
-#define R_IRQ_MASK2_RD__dma9_descr__WIDTH 1
-#define R_IRQ_MASK2_RD__dma9_descr__active 1
-#define R_IRQ_MASK2_RD__dma9_descr__inactive 0
-#define R_IRQ_MASK2_RD__dma8_eop__BITNR 17
-#define R_IRQ_MASK2_RD__dma8_eop__WIDTH 1
-#define R_IRQ_MASK2_RD__dma8_eop__active 1
-#define R_IRQ_MASK2_RD__dma8_eop__inactive 0
-#define R_IRQ_MASK2_RD__dma8_descr__BITNR 16
-#define R_IRQ_MASK2_RD__dma8_descr__WIDTH 1
-#define R_IRQ_MASK2_RD__dma8_descr__active 1
-#define R_IRQ_MASK2_RD__dma8_descr__inactive 0
-#define R_IRQ_MASK2_RD__dma7_eop__BITNR 15
-#define R_IRQ_MASK2_RD__dma7_eop__WIDTH 1
-#define R_IRQ_MASK2_RD__dma7_eop__active 1
-#define R_IRQ_MASK2_RD__dma7_eop__inactive 0
-#define R_IRQ_MASK2_RD__dma7_descr__BITNR 14
-#define R_IRQ_MASK2_RD__dma7_descr__WIDTH 1
-#define R_IRQ_MASK2_RD__dma7_descr__active 1
-#define R_IRQ_MASK2_RD__dma7_descr__inactive 0
-#define R_IRQ_MASK2_RD__dma6_eop__BITNR 13
-#define R_IRQ_MASK2_RD__dma6_eop__WIDTH 1
-#define R_IRQ_MASK2_RD__dma6_eop__active 1
-#define R_IRQ_MASK2_RD__dma6_eop__inactive 0
-#define R_IRQ_MASK2_RD__dma6_descr__BITNR 12
-#define R_IRQ_MASK2_RD__dma6_descr__WIDTH 1
-#define R_IRQ_MASK2_RD__dma6_descr__active 1
-#define R_IRQ_MASK2_RD__dma6_descr__inactive 0
-#define R_IRQ_MASK2_RD__dma5_eop__BITNR 11
-#define R_IRQ_MASK2_RD__dma5_eop__WIDTH 1
-#define R_IRQ_MASK2_RD__dma5_eop__active 1
-#define R_IRQ_MASK2_RD__dma5_eop__inactive 0
-#define R_IRQ_MASK2_RD__dma5_descr__BITNR 10
-#define R_IRQ_MASK2_RD__dma5_descr__WIDTH 1
-#define R_IRQ_MASK2_RD__dma5_descr__active 1
-#define R_IRQ_MASK2_RD__dma5_descr__inactive 0
-#define R_IRQ_MASK2_RD__dma4_eop__BITNR 9
-#define R_IRQ_MASK2_RD__dma4_eop__WIDTH 1
-#define R_IRQ_MASK2_RD__dma4_eop__active 1
-#define R_IRQ_MASK2_RD__dma4_eop__inactive 0
-#define R_IRQ_MASK2_RD__dma4_descr__BITNR 8
-#define R_IRQ_MASK2_RD__dma4_descr__WIDTH 1
-#define R_IRQ_MASK2_RD__dma4_descr__active 1
-#define R_IRQ_MASK2_RD__dma4_descr__inactive 0
-#define R_IRQ_MASK2_RD__dma3_eop__BITNR 7
-#define R_IRQ_MASK2_RD__dma3_eop__WIDTH 1
-#define R_IRQ_MASK2_RD__dma3_eop__active 1
-#define R_IRQ_MASK2_RD__dma3_eop__inactive 0
-#define R_IRQ_MASK2_RD__dma3_descr__BITNR 6
-#define R_IRQ_MASK2_RD__dma3_descr__WIDTH 1
-#define R_IRQ_MASK2_RD__dma3_descr__active 1
-#define R_IRQ_MASK2_RD__dma3_descr__inactive 0
-#define R_IRQ_MASK2_RD__dma2_eop__BITNR 5
-#define R_IRQ_MASK2_RD__dma2_eop__WIDTH 1
-#define R_IRQ_MASK2_RD__dma2_eop__active 1
-#define R_IRQ_MASK2_RD__dma2_eop__inactive 0
-#define R_IRQ_MASK2_RD__dma2_descr__BITNR 4
-#define R_IRQ_MASK2_RD__dma2_descr__WIDTH 1
-#define R_IRQ_MASK2_RD__dma2_descr__active 1
-#define R_IRQ_MASK2_RD__dma2_descr__inactive 0
-#define R_IRQ_MASK2_RD__dma1_eop__BITNR 3
-#define R_IRQ_MASK2_RD__dma1_eop__WIDTH 1
-#define R_IRQ_MASK2_RD__dma1_eop__active 1
-#define R_IRQ_MASK2_RD__dma1_eop__inactive 0
-#define R_IRQ_MASK2_RD__dma1_descr__BITNR 2
-#define R_IRQ_MASK2_RD__dma1_descr__WIDTH 1
-#define R_IRQ_MASK2_RD__dma1_descr__active 1
-#define R_IRQ_MASK2_RD__dma1_descr__inactive 0
-#define R_IRQ_MASK2_RD__dma0_eop__BITNR 1
-#define R_IRQ_MASK2_RD__dma0_eop__WIDTH 1
-#define R_IRQ_MASK2_RD__dma0_eop__active 1
-#define R_IRQ_MASK2_RD__dma0_eop__inactive 0
-#define R_IRQ_MASK2_RD__dma0_descr__BITNR 0
-#define R_IRQ_MASK2_RD__dma0_descr__WIDTH 1
-#define R_IRQ_MASK2_RD__dma0_descr__active 1
-#define R_IRQ_MASK2_RD__dma0_descr__inactive 0
-
-#define R_IRQ_MASK2_CLR (IO_TYPECAST_UDWORD 0xb00000d0)
-#define R_IRQ_MASK2_CLR__dma8_sub3_descr__BITNR 23
-#define R_IRQ_MASK2_CLR__dma8_sub3_descr__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma8_sub3_descr__clr 1
-#define R_IRQ_MASK2_CLR__dma8_sub3_descr__nop 0
-#define R_IRQ_MASK2_CLR__dma8_sub2_descr__BITNR 22
-#define R_IRQ_MASK2_CLR__dma8_sub2_descr__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma8_sub2_descr__clr 1
-#define R_IRQ_MASK2_CLR__dma8_sub2_descr__nop 0
-#define R_IRQ_MASK2_CLR__dma8_sub1_descr__BITNR 21
-#define R_IRQ_MASK2_CLR__dma8_sub1_descr__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma8_sub1_descr__clr 1
-#define R_IRQ_MASK2_CLR__dma8_sub1_descr__nop 0
-#define R_IRQ_MASK2_CLR__dma8_sub0_descr__BITNR 20
-#define R_IRQ_MASK2_CLR__dma8_sub0_descr__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma8_sub0_descr__clr 1
-#define R_IRQ_MASK2_CLR__dma8_sub0_descr__nop 0
-#define R_IRQ_MASK2_CLR__dma9_eop__BITNR 19
-#define R_IRQ_MASK2_CLR__dma9_eop__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma9_eop__clr 1
-#define R_IRQ_MASK2_CLR__dma9_eop__nop 0
-#define R_IRQ_MASK2_CLR__dma9_descr__BITNR 18
-#define R_IRQ_MASK2_CLR__dma9_descr__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma9_descr__clr 1
-#define R_IRQ_MASK2_CLR__dma9_descr__nop 0
-#define R_IRQ_MASK2_CLR__dma8_eop__BITNR 17
-#define R_IRQ_MASK2_CLR__dma8_eop__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma8_eop__clr 1
-#define R_IRQ_MASK2_CLR__dma8_eop__nop 0
-#define R_IRQ_MASK2_CLR__dma8_descr__BITNR 16
-#define R_IRQ_MASK2_CLR__dma8_descr__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma8_descr__clr 1
-#define R_IRQ_MASK2_CLR__dma8_descr__nop 0
-#define R_IRQ_MASK2_CLR__dma7_eop__BITNR 15
-#define R_IRQ_MASK2_CLR__dma7_eop__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma7_eop__clr 1
-#define R_IRQ_MASK2_CLR__dma7_eop__nop 0
-#define R_IRQ_MASK2_CLR__dma7_descr__BITNR 14
-#define R_IRQ_MASK2_CLR__dma7_descr__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma7_descr__clr 1
-#define R_IRQ_MASK2_CLR__dma7_descr__nop 0
-#define R_IRQ_MASK2_CLR__dma6_eop__BITNR 13
-#define R_IRQ_MASK2_CLR__dma6_eop__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma6_eop__clr 1
-#define R_IRQ_MASK2_CLR__dma6_eop__nop 0
-#define R_IRQ_MASK2_CLR__dma6_descr__BITNR 12
-#define R_IRQ_MASK2_CLR__dma6_descr__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma6_descr__clr 1
-#define R_IRQ_MASK2_CLR__dma6_descr__nop 0
-#define R_IRQ_MASK2_CLR__dma5_eop__BITNR 11
-#define R_IRQ_MASK2_CLR__dma5_eop__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma5_eop__clr 1
-#define R_IRQ_MASK2_CLR__dma5_eop__nop 0
-#define R_IRQ_MASK2_CLR__dma5_descr__BITNR 10
-#define R_IRQ_MASK2_CLR__dma5_descr__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma5_descr__clr 1
-#define R_IRQ_MASK2_CLR__dma5_descr__nop 0
-#define R_IRQ_MASK2_CLR__dma4_eop__BITNR 9
-#define R_IRQ_MASK2_CLR__dma4_eop__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma4_eop__clr 1
-#define R_IRQ_MASK2_CLR__dma4_eop__nop 0
-#define R_IRQ_MASK2_CLR__dma4_descr__BITNR 8
-#define R_IRQ_MASK2_CLR__dma4_descr__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma4_descr__clr 1
-#define R_IRQ_MASK2_CLR__dma4_descr__nop 0
-#define R_IRQ_MASK2_CLR__dma3_eop__BITNR 7
-#define R_IRQ_MASK2_CLR__dma3_eop__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma3_eop__clr 1
-#define R_IRQ_MASK2_CLR__dma3_eop__nop 0
-#define R_IRQ_MASK2_CLR__dma3_descr__BITNR 6
-#define R_IRQ_MASK2_CLR__dma3_descr__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma3_descr__clr 1
-#define R_IRQ_MASK2_CLR__dma3_descr__nop 0
-#define R_IRQ_MASK2_CLR__dma2_eop__BITNR 5
-#define R_IRQ_MASK2_CLR__dma2_eop__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma2_eop__clr 1
-#define R_IRQ_MASK2_CLR__dma2_eop__nop 0
-#define R_IRQ_MASK2_CLR__dma2_descr__BITNR 4
-#define R_IRQ_MASK2_CLR__dma2_descr__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma2_descr__clr 1
-#define R_IRQ_MASK2_CLR__dma2_descr__nop 0
-#define R_IRQ_MASK2_CLR__dma1_eop__BITNR 3
-#define R_IRQ_MASK2_CLR__dma1_eop__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma1_eop__clr 1
-#define R_IRQ_MASK2_CLR__dma1_eop__nop 0
-#define R_IRQ_MASK2_CLR__dma1_descr__BITNR 2
-#define R_IRQ_MASK2_CLR__dma1_descr__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma1_descr__clr 1
-#define R_IRQ_MASK2_CLR__dma1_descr__nop 0
-#define R_IRQ_MASK2_CLR__dma0_eop__BITNR 1
-#define R_IRQ_MASK2_CLR__dma0_eop__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma0_eop__clr 1
-#define R_IRQ_MASK2_CLR__dma0_eop__nop 0
-#define R_IRQ_MASK2_CLR__dma0_descr__BITNR 0
-#define R_IRQ_MASK2_CLR__dma0_descr__WIDTH 1
-#define R_IRQ_MASK2_CLR__dma0_descr__clr 1
-#define R_IRQ_MASK2_CLR__dma0_descr__nop 0
-
-#define R_IRQ_READ2 (IO_TYPECAST_RO_UDWORD 0xb00000d4)
-#define R_IRQ_READ2__dma8_sub3_descr__BITNR 23
-#define R_IRQ_READ2__dma8_sub3_descr__WIDTH 1
-#define R_IRQ_READ2__dma8_sub3_descr__active 1
-#define R_IRQ_READ2__dma8_sub3_descr__inactive 0
-#define R_IRQ_READ2__dma8_sub2_descr__BITNR 22
-#define R_IRQ_READ2__dma8_sub2_descr__WIDTH 1
-#define R_IRQ_READ2__dma8_sub2_descr__active 1
-#define R_IRQ_READ2__dma8_sub2_descr__inactive 0
-#define R_IRQ_READ2__dma8_sub1_descr__BITNR 21
-#define R_IRQ_READ2__dma8_sub1_descr__WIDTH 1
-#define R_IRQ_READ2__dma8_sub1_descr__active 1
-#define R_IRQ_READ2__dma8_sub1_descr__inactive 0
-#define R_IRQ_READ2__dma8_sub0_descr__BITNR 20
-#define R_IRQ_READ2__dma8_sub0_descr__WIDTH 1
-#define R_IRQ_READ2__dma8_sub0_descr__active 1
-#define R_IRQ_READ2__dma8_sub0_descr__inactive 0
-#define R_IRQ_READ2__dma9_eop__BITNR 19
-#define R_IRQ_READ2__dma9_eop__WIDTH 1
-#define R_IRQ_READ2__dma9_eop__active 1
-#define R_IRQ_READ2__dma9_eop__inactive 0
-#define R_IRQ_READ2__dma9_descr__BITNR 18
-#define R_IRQ_READ2__dma9_descr__WIDTH 1
-#define R_IRQ_READ2__dma9_descr__active 1
-#define R_IRQ_READ2__dma9_descr__inactive 0
-#define R_IRQ_READ2__dma8_eop__BITNR 17
-#define R_IRQ_READ2__dma8_eop__WIDTH 1
-#define R_IRQ_READ2__dma8_eop__active 1
-#define R_IRQ_READ2__dma8_eop__inactive 0
-#define R_IRQ_READ2__dma8_descr__BITNR 16
-#define R_IRQ_READ2__dma8_descr__WIDTH 1
-#define R_IRQ_READ2__dma8_descr__active 1
-#define R_IRQ_READ2__dma8_descr__inactive 0
-#define R_IRQ_READ2__dma7_eop__BITNR 15
-#define R_IRQ_READ2__dma7_eop__WIDTH 1
-#define R_IRQ_READ2__dma7_eop__active 1
-#define R_IRQ_READ2__dma7_eop__inactive 0
-#define R_IRQ_READ2__dma7_descr__BITNR 14
-#define R_IRQ_READ2__dma7_descr__WIDTH 1
-#define R_IRQ_READ2__dma7_descr__active 1
-#define R_IRQ_READ2__dma7_descr__inactive 0
-#define R_IRQ_READ2__dma6_eop__BITNR 13
-#define R_IRQ_READ2__dma6_eop__WIDTH 1
-#define R_IRQ_READ2__dma6_eop__active 1
-#define R_IRQ_READ2__dma6_eop__inactive 0
-#define R_IRQ_READ2__dma6_descr__BITNR 12
-#define R_IRQ_READ2__dma6_descr__WIDTH 1
-#define R_IRQ_READ2__dma6_descr__active 1
-#define R_IRQ_READ2__dma6_descr__inactive 0
-#define R_IRQ_READ2__dma5_eop__BITNR 11
-#define R_IRQ_READ2__dma5_eop__WIDTH 1
-#define R_IRQ_READ2__dma5_eop__active 1
-#define R_IRQ_READ2__dma5_eop__inactive 0
-#define R_IRQ_READ2__dma5_descr__BITNR 10
-#define R_IRQ_READ2__dma5_descr__WIDTH 1
-#define R_IRQ_READ2__dma5_descr__active 1
-#define R_IRQ_READ2__dma5_descr__inactive 0
-#define R_IRQ_READ2__dma4_eop__BITNR 9
-#define R_IRQ_READ2__dma4_eop__WIDTH 1
-#define R_IRQ_READ2__dma4_eop__active 1
-#define R_IRQ_READ2__dma4_eop__inactive 0
-#define R_IRQ_READ2__dma4_descr__BITNR 8
-#define R_IRQ_READ2__dma4_descr__WIDTH 1
-#define R_IRQ_READ2__dma4_descr__active 1
-#define R_IRQ_READ2__dma4_descr__inactive 0
-#define R_IRQ_READ2__dma3_eop__BITNR 7
-#define R_IRQ_READ2__dma3_eop__WIDTH 1
-#define R_IRQ_READ2__dma3_eop__active 1
-#define R_IRQ_READ2__dma3_eop__inactive 0
-#define R_IRQ_READ2__dma3_descr__BITNR 6
-#define R_IRQ_READ2__dma3_descr__WIDTH 1
-#define R_IRQ_READ2__dma3_descr__active 1
-#define R_IRQ_READ2__dma3_descr__inactive 0
-#define R_IRQ_READ2__dma2_eop__BITNR 5
-#define R_IRQ_READ2__dma2_eop__WIDTH 1
-#define R_IRQ_READ2__dma2_eop__active 1
-#define R_IRQ_READ2__dma2_eop__inactive 0
-#define R_IRQ_READ2__dma2_descr__BITNR 4
-#define R_IRQ_READ2__dma2_descr__WIDTH 1
-#define R_IRQ_READ2__dma2_descr__active 1
-#define R_IRQ_READ2__dma2_descr__inactive 0
-#define R_IRQ_READ2__dma1_eop__BITNR 3
-#define R_IRQ_READ2__dma1_eop__WIDTH 1
-#define R_IRQ_READ2__dma1_eop__active 1
-#define R_IRQ_READ2__dma1_eop__inactive 0
-#define R_IRQ_READ2__dma1_descr__BITNR 2
-#define R_IRQ_READ2__dma1_descr__WIDTH 1
-#define R_IRQ_READ2__dma1_descr__active 1
-#define R_IRQ_READ2__dma1_descr__inactive 0
-#define R_IRQ_READ2__dma0_eop__BITNR 1
-#define R_IRQ_READ2__dma0_eop__WIDTH 1
-#define R_IRQ_READ2__dma0_eop__active 1
-#define R_IRQ_READ2__dma0_eop__inactive 0
-#define R_IRQ_READ2__dma0_descr__BITNR 0
-#define R_IRQ_READ2__dma0_descr__WIDTH 1
-#define R_IRQ_READ2__dma0_descr__active 1
-#define R_IRQ_READ2__dma0_descr__inactive 0
-
-#define R_IRQ_MASK2_SET (IO_TYPECAST_UDWORD 0xb00000d4)
-#define R_IRQ_MASK2_SET__dma8_sub3_descr__BITNR 23
-#define R_IRQ_MASK2_SET__dma8_sub3_descr__WIDTH 1
-#define R_IRQ_MASK2_SET__dma8_sub3_descr__set 1
-#define R_IRQ_MASK2_SET__dma8_sub3_descr__nop 0
-#define R_IRQ_MASK2_SET__dma8_sub2_descr__BITNR 22
-#define R_IRQ_MASK2_SET__dma8_sub2_descr__WIDTH 1
-#define R_IRQ_MASK2_SET__dma8_sub2_descr__set 1
-#define R_IRQ_MASK2_SET__dma8_sub2_descr__nop 0
-#define R_IRQ_MASK2_SET__dma8_sub1_descr__BITNR 21
-#define R_IRQ_MASK2_SET__dma8_sub1_descr__WIDTH 1
-#define R_IRQ_MASK2_SET__dma8_sub1_descr__set 1
-#define R_IRQ_MASK2_SET__dma8_sub1_descr__nop 0
-#define R_IRQ_MASK2_SET__dma8_sub0_descr__BITNR 20
-#define R_IRQ_MASK2_SET__dma8_sub0_descr__WIDTH 1
-#define R_IRQ_MASK2_SET__dma8_sub0_descr__set 1
-#define R_IRQ_MASK2_SET__dma8_sub0_descr__nop 0
-#define R_IRQ_MASK2_SET__dma9_eop__BITNR 19
-#define R_IRQ_MASK2_SET__dma9_eop__WIDTH 1
-#define R_IRQ_MASK2_SET__dma9_eop__set 1
-#define R_IRQ_MASK2_SET__dma9_eop__nop 0
-#define R_IRQ_MASK2_SET__dma9_descr__BITNR 18
-#define R_IRQ_MASK2_SET__dma9_descr__WIDTH 1
-#define R_IRQ_MASK2_SET__dma9_descr__set 1
-#define R_IRQ_MASK2_SET__dma9_descr__nop 0
-#define R_IRQ_MASK2_SET__dma8_eop__BITNR 17
-#define R_IRQ_MASK2_SET__dma8_eop__WIDTH 1
-#define R_IRQ_MASK2_SET__dma8_eop__set 1
-#define R_IRQ_MASK2_SET__dma8_eop__nop 0
-#define R_IRQ_MASK2_SET__dma8_descr__BITNR 16
-#define R_IRQ_MASK2_SET__dma8_descr__WIDTH 1
-#define R_IRQ_MASK2_SET__dma8_descr__set 1
-#define R_IRQ_MASK2_SET__dma8_descr__nop 0
-#define R_IRQ_MASK2_SET__dma7_eop__BITNR 15
-#define R_IRQ_MASK2_SET__dma7_eop__WIDTH 1
-#define R_IRQ_MASK2_SET__dma7_eop__set 1
-#define R_IRQ_MASK2_SET__dma7_eop__nop 0
-#define R_IRQ_MASK2_SET__dma7_descr__BITNR 14
-#define R_IRQ_MASK2_SET__dma7_descr__WIDTH 1
-#define R_IRQ_MASK2_SET__dma7_descr__set 1
-#define R_IRQ_MASK2_SET__dma7_descr__nop 0
-#define R_IRQ_MASK2_SET__dma6_eop__BITNR 13
-#define R_IRQ_MASK2_SET__dma6_eop__WIDTH 1
-#define R_IRQ_MASK2_SET__dma6_eop__set 1
-#define R_IRQ_MASK2_SET__dma6_eop__nop 0
-#define R_IRQ_MASK2_SET__dma6_descr__BITNR 12
-#define R_IRQ_MASK2_SET__dma6_descr__WIDTH 1
-#define R_IRQ_MASK2_SET__dma6_descr__set 1
-#define R_IRQ_MASK2_SET__dma6_descr__nop 0
-#define R_IRQ_MASK2_SET__dma5_eop__BITNR 11
-#define R_IRQ_MASK2_SET__dma5_eop__WIDTH 1
-#define R_IRQ_MASK2_SET__dma5_eop__set 1
-#define R_IRQ_MASK2_SET__dma5_eop__nop 0
-#define R_IRQ_MASK2_SET__dma5_descr__BITNR 10
-#define R_IRQ_MASK2_SET__dma5_descr__WIDTH 1
-#define R_IRQ_MASK2_SET__dma5_descr__set 1
-#define R_IRQ_MASK2_SET__dma5_descr__nop 0
-#define R_IRQ_MASK2_SET__dma4_eop__BITNR 9
-#define R_IRQ_MASK2_SET__dma4_eop__WIDTH 1
-#define R_IRQ_MASK2_SET__dma4_eop__set 1
-#define R_IRQ_MASK2_SET__dma4_eop__nop 0
-#define R_IRQ_MASK2_SET__dma4_descr__BITNR 8
-#define R_IRQ_MASK2_SET__dma4_descr__WIDTH 1
-#define R_IRQ_MASK2_SET__dma4_descr__set 1
-#define R_IRQ_MASK2_SET__dma4_descr__nop 0
-#define R_IRQ_MASK2_SET__dma3_eop__BITNR 7
-#define R_IRQ_MASK2_SET__dma3_eop__WIDTH 1
-#define R_IRQ_MASK2_SET__dma3_eop__set 1
-#define R_IRQ_MASK2_SET__dma3_eop__nop 0
-#define R_IRQ_MASK2_SET__dma3_descr__BITNR 6
-#define R_IRQ_MASK2_SET__dma3_descr__WIDTH 1
-#define R_IRQ_MASK2_SET__dma3_descr__set 1
-#define R_IRQ_MASK2_SET__dma3_descr__nop 0
-#define R_IRQ_MASK2_SET__dma2_eop__BITNR 5
-#define R_IRQ_MASK2_SET__dma2_eop__WIDTH 1
-#define R_IRQ_MASK2_SET__dma2_eop__set 1
-#define R_IRQ_MASK2_SET__dma2_eop__nop 0
-#define R_IRQ_MASK2_SET__dma2_descr__BITNR 4
-#define R_IRQ_MASK2_SET__dma2_descr__WIDTH 1
-#define R_IRQ_MASK2_SET__dma2_descr__set 1
-#define R_IRQ_MASK2_SET__dma2_descr__nop 0
-#define R_IRQ_MASK2_SET__dma1_eop__BITNR 3
-#define R_IRQ_MASK2_SET__dma1_eop__WIDTH 1
-#define R_IRQ_MASK2_SET__dma1_eop__set 1
-#define R_IRQ_MASK2_SET__dma1_eop__nop 0
-#define R_IRQ_MASK2_SET__dma1_descr__BITNR 2
-#define R_IRQ_MASK2_SET__dma1_descr__WIDTH 1
-#define R_IRQ_MASK2_SET__dma1_descr__set 1
-#define R_IRQ_MASK2_SET__dma1_descr__nop 0
-#define R_IRQ_MASK2_SET__dma0_eop__BITNR 1
-#define R_IRQ_MASK2_SET__dma0_eop__WIDTH 1
-#define R_IRQ_MASK2_SET__dma0_eop__set 1
-#define R_IRQ_MASK2_SET__dma0_eop__nop 0
-#define R_IRQ_MASK2_SET__dma0_descr__BITNR 0
-#define R_IRQ_MASK2_SET__dma0_descr__WIDTH 1
-#define R_IRQ_MASK2_SET__dma0_descr__set 1
-#define R_IRQ_MASK2_SET__dma0_descr__nop 0
-
-#define R_VECT_MASK_RD (IO_TYPECAST_RO_UDWORD 0xb00000d8)
-#define R_VECT_MASK_RD__usb__BITNR 31
-#define R_VECT_MASK_RD__usb__WIDTH 1
-#define R_VECT_MASK_RD__usb__active 1
-#define R_VECT_MASK_RD__usb__inactive 0
-#define R_VECT_MASK_RD__dma9__BITNR 25
-#define R_VECT_MASK_RD__dma9__WIDTH 1
-#define R_VECT_MASK_RD__dma9__active 1
-#define R_VECT_MASK_RD__dma9__inactive 0
-#define R_VECT_MASK_RD__dma8__BITNR 24
-#define R_VECT_MASK_RD__dma8__WIDTH 1
-#define R_VECT_MASK_RD__dma8__active 1
-#define R_VECT_MASK_RD__dma8__inactive 0
-#define R_VECT_MASK_RD__dma7__BITNR 23
-#define R_VECT_MASK_RD__dma7__WIDTH 1
-#define R_VECT_MASK_RD__dma7__active 1
-#define R_VECT_MASK_RD__dma7__inactive 0
-#define R_VECT_MASK_RD__dma6__BITNR 22
-#define R_VECT_MASK_RD__dma6__WIDTH 1
-#define R_VECT_MASK_RD__dma6__active 1
-#define R_VECT_MASK_RD__dma6__inactive 0
-#define R_VECT_MASK_RD__dma5__BITNR 21
-#define R_VECT_MASK_RD__dma5__WIDTH 1
-#define R_VECT_MASK_RD__dma5__active 1
-#define R_VECT_MASK_RD__dma5__inactive 0
-#define R_VECT_MASK_RD__dma4__BITNR 20
-#define R_VECT_MASK_RD__dma4__WIDTH 1
-#define R_VECT_MASK_RD__dma4__active 1
-#define R_VECT_MASK_RD__dma4__inactive 0
-#define R_VECT_MASK_RD__dma3__BITNR 19
-#define R_VECT_MASK_RD__dma3__WIDTH 1
-#define R_VECT_MASK_RD__dma3__active 1
-#define R_VECT_MASK_RD__dma3__inactive 0
-#define R_VECT_MASK_RD__dma2__BITNR 18
-#define R_VECT_MASK_RD__dma2__WIDTH 1
-#define R_VECT_MASK_RD__dma2__active 1
-#define R_VECT_MASK_RD__dma2__inactive 0
-#define R_VECT_MASK_RD__dma1__BITNR 17
-#define R_VECT_MASK_RD__dma1__WIDTH 1
-#define R_VECT_MASK_RD__dma1__active 1
-#define R_VECT_MASK_RD__dma1__inactive 0
-#define R_VECT_MASK_RD__dma0__BITNR 16
-#define R_VECT_MASK_RD__dma0__WIDTH 1
-#define R_VECT_MASK_RD__dma0__active 1
-#define R_VECT_MASK_RD__dma0__inactive 0
-#define R_VECT_MASK_RD__ext_dma1__BITNR 13
-#define R_VECT_MASK_RD__ext_dma1__WIDTH 1
-#define R_VECT_MASK_RD__ext_dma1__active 1
-#define R_VECT_MASK_RD__ext_dma1__inactive 0
-#define R_VECT_MASK_RD__ext_dma0__BITNR 12
-#define R_VECT_MASK_RD__ext_dma0__WIDTH 1
-#define R_VECT_MASK_RD__ext_dma0__active 1
-#define R_VECT_MASK_RD__ext_dma0__inactive 0
-#define R_VECT_MASK_RD__pa__BITNR 11
-#define R_VECT_MASK_RD__pa__WIDTH 1
-#define R_VECT_MASK_RD__pa__active 1
-#define R_VECT_MASK_RD__pa__inactive 0
-#define R_VECT_MASK_RD__irq_intnr__BITNR 10
-#define R_VECT_MASK_RD__irq_intnr__WIDTH 1
-#define R_VECT_MASK_RD__irq_intnr__active 1
-#define R_VECT_MASK_RD__irq_intnr__inactive 0
-#define R_VECT_MASK_RD__sw__BITNR 9
-#define R_VECT_MASK_RD__sw__WIDTH 1
-#define R_VECT_MASK_RD__sw__active 1
-#define R_VECT_MASK_RD__sw__inactive 0
-#define R_VECT_MASK_RD__serial__BITNR 8
-#define R_VECT_MASK_RD__serial__WIDTH 1
-#define R_VECT_MASK_RD__serial__active 1
-#define R_VECT_MASK_RD__serial__inactive 0
-#define R_VECT_MASK_RD__snmp__BITNR 7
-#define R_VECT_MASK_RD__snmp__WIDTH 1
-#define R_VECT_MASK_RD__snmp__active 1
-#define R_VECT_MASK_RD__snmp__inactive 0
-#define R_VECT_MASK_RD__network__BITNR 6
-#define R_VECT_MASK_RD__network__WIDTH 1
-#define R_VECT_MASK_RD__network__active 1
-#define R_VECT_MASK_RD__network__inactive 0
-#define R_VECT_MASK_RD__scsi1__BITNR 5
-#define R_VECT_MASK_RD__scsi1__WIDTH 1
-#define R_VECT_MASK_RD__scsi1__active 1
-#define R_VECT_MASK_RD__scsi1__inactive 0
-#define R_VECT_MASK_RD__par1__BITNR 5
-#define R_VECT_MASK_RD__par1__WIDTH 1
-#define R_VECT_MASK_RD__par1__active 1
-#define R_VECT_MASK_RD__par1__inactive 0
-#define R_VECT_MASK_RD__scsi0__BITNR 4
-#define R_VECT_MASK_RD__scsi0__WIDTH 1
-#define R_VECT_MASK_RD__scsi0__active 1
-#define R_VECT_MASK_RD__scsi0__inactive 0
-#define R_VECT_MASK_RD__par0__BITNR 4
-#define R_VECT_MASK_RD__par0__WIDTH 1
-#define R_VECT_MASK_RD__par0__active 1
-#define R_VECT_MASK_RD__par0__inactive 0
-#define R_VECT_MASK_RD__ata__BITNR 4
-#define R_VECT_MASK_RD__ata__WIDTH 1
-#define R_VECT_MASK_RD__ata__active 1
-#define R_VECT_MASK_RD__ata__inactive 0
-#define R_VECT_MASK_RD__mio__BITNR 4
-#define R_VECT_MASK_RD__mio__WIDTH 1
-#define R_VECT_MASK_RD__mio__active 1
-#define R_VECT_MASK_RD__mio__inactive 0
-#define R_VECT_MASK_RD__timer1__BITNR 3
-#define R_VECT_MASK_RD__timer1__WIDTH 1
-#define R_VECT_MASK_RD__timer1__active 1
-#define R_VECT_MASK_RD__timer1__inactive 0
-#define R_VECT_MASK_RD__timer0__BITNR 2
-#define R_VECT_MASK_RD__timer0__WIDTH 1
-#define R_VECT_MASK_RD__timer0__active 1
-#define R_VECT_MASK_RD__timer0__inactive 0
-#define R_VECT_MASK_RD__nmi__BITNR 1
-#define R_VECT_MASK_RD__nmi__WIDTH 1
-#define R_VECT_MASK_RD__nmi__active 1
-#define R_VECT_MASK_RD__nmi__inactive 0
-#define R_VECT_MASK_RD__some__BITNR 0
-#define R_VECT_MASK_RD__some__WIDTH 1
-#define R_VECT_MASK_RD__some__active 1
-#define R_VECT_MASK_RD__some__inactive 0
-
-#define R_VECT_MASK_CLR (IO_TYPECAST_UDWORD 0xb00000d8)
-#define R_VECT_MASK_CLR__usb__BITNR 31
-#define R_VECT_MASK_CLR__usb__WIDTH 1
-#define R_VECT_MASK_CLR__usb__clr 1
-#define R_VECT_MASK_CLR__usb__nop 0
-#define R_VECT_MASK_CLR__dma9__BITNR 25
-#define R_VECT_MASK_CLR__dma9__WIDTH 1
-#define R_VECT_MASK_CLR__dma9__clr 1
-#define R_VECT_MASK_CLR__dma9__nop 0
-#define R_VECT_MASK_CLR__dma8__BITNR 24
-#define R_VECT_MASK_CLR__dma8__WIDTH 1
-#define R_VECT_MASK_CLR__dma8__clr 1
-#define R_VECT_MASK_CLR__dma8__nop 0
-#define R_VECT_MASK_CLR__dma7__BITNR 23
-#define R_VECT_MASK_CLR__dma7__WIDTH 1
-#define R_VECT_MASK_CLR__dma7__clr 1
-#define R_VECT_MASK_CLR__dma7__nop 0
-#define R_VECT_MASK_CLR__dma6__BITNR 22
-#define R_VECT_MASK_CLR__dma6__WIDTH 1
-#define R_VECT_MASK_CLR__dma6__clr 1
-#define R_VECT_MASK_CLR__dma6__nop 0
-#define R_VECT_MASK_CLR__dma5__BITNR 21
-#define R_VECT_MASK_CLR__dma5__WIDTH 1
-#define R_VECT_MASK_CLR__dma5__clr 1
-#define R_VECT_MASK_CLR__dma5__nop 0
-#define R_VECT_MASK_CLR__dma4__BITNR 20
-#define R_VECT_MASK_CLR__dma4__WIDTH 1
-#define R_VECT_MASK_CLR__dma4__clr 1
-#define R_VECT_MASK_CLR__dma4__nop 0
-#define R_VECT_MASK_CLR__dma3__BITNR 19
-#define R_VECT_MASK_CLR__dma3__WIDTH 1
-#define R_VECT_MASK_CLR__dma3__clr 1
-#define R_VECT_MASK_CLR__dma3__nop 0
-#define R_VECT_MASK_CLR__dma2__BITNR 18
-#define R_VECT_MASK_CLR__dma2__WIDTH 1
-#define R_VECT_MASK_CLR__dma2__clr 1
-#define R_VECT_MASK_CLR__dma2__nop 0
-#define R_VECT_MASK_CLR__dma1__BITNR 17
-#define R_VECT_MASK_CLR__dma1__WIDTH 1
-#define R_VECT_MASK_CLR__dma1__clr 1
-#define R_VECT_MASK_CLR__dma1__nop 0
-#define R_VECT_MASK_CLR__dma0__BITNR 16
-#define R_VECT_MASK_CLR__dma0__WIDTH 1
-#define R_VECT_MASK_CLR__dma0__clr 1
-#define R_VECT_MASK_CLR__dma0__nop 0
-#define R_VECT_MASK_CLR__ext_dma1__BITNR 13
-#define R_VECT_MASK_CLR__ext_dma1__WIDTH 1
-#define R_VECT_MASK_CLR__ext_dma1__clr 1
-#define R_VECT_MASK_CLR__ext_dma1__nop 0
-#define R_VECT_MASK_CLR__ext_dma0__BITNR 12
-#define R_VECT_MASK_CLR__ext_dma0__WIDTH 1
-#define R_VECT_MASK_CLR__ext_dma0__clr 1
-#define R_VECT_MASK_CLR__ext_dma0__nop 0
-#define R_VECT_MASK_CLR__pa__BITNR 11
-#define R_VECT_MASK_CLR__pa__WIDTH 1
-#define R_VECT_MASK_CLR__pa__clr 1
-#define R_VECT_MASK_CLR__pa__nop 0
-#define R_VECT_MASK_CLR__irq_intnr__BITNR 10
-#define R_VECT_MASK_CLR__irq_intnr__WIDTH 1
-#define R_VECT_MASK_CLR__irq_intnr__clr 1
-#define R_VECT_MASK_CLR__irq_intnr__nop 0
-#define R_VECT_MASK_CLR__sw__BITNR 9
-#define R_VECT_MASK_CLR__sw__WIDTH 1
-#define R_VECT_MASK_CLR__sw__clr 1
-#define R_VECT_MASK_CLR__sw__nop 0
-#define R_VECT_MASK_CLR__serial__BITNR 8
-#define R_VECT_MASK_CLR__serial__WIDTH 1
-#define R_VECT_MASK_CLR__serial__clr 1
-#define R_VECT_MASK_CLR__serial__nop 0
-#define R_VECT_MASK_CLR__snmp__BITNR 7
-#define R_VECT_MASK_CLR__snmp__WIDTH 1
-#define R_VECT_MASK_CLR__snmp__clr 1
-#define R_VECT_MASK_CLR__snmp__nop 0
-#define R_VECT_MASK_CLR__network__BITNR 6
-#define R_VECT_MASK_CLR__network__WIDTH 1
-#define R_VECT_MASK_CLR__network__clr 1
-#define R_VECT_MASK_CLR__network__nop 0
-#define R_VECT_MASK_CLR__scsi1__BITNR 5
-#define R_VECT_MASK_CLR__scsi1__WIDTH 1
-#define R_VECT_MASK_CLR__scsi1__clr 1
-#define R_VECT_MASK_CLR__scsi1__nop 0
-#define R_VECT_MASK_CLR__par1__BITNR 5
-#define R_VECT_MASK_CLR__par1__WIDTH 1
-#define R_VECT_MASK_CLR__par1__clr 1
-#define R_VECT_MASK_CLR__par1__nop 0
-#define R_VECT_MASK_CLR__scsi0__BITNR 4
-#define R_VECT_MASK_CLR__scsi0__WIDTH 1
-#define R_VECT_MASK_CLR__scsi0__clr 1
-#define R_VECT_MASK_CLR__scsi0__nop 0
-#define R_VECT_MASK_CLR__par0__BITNR 4
-#define R_VECT_MASK_CLR__par0__WIDTH 1
-#define R_VECT_MASK_CLR__par0__clr 1
-#define R_VECT_MASK_CLR__par0__nop 0
-#define R_VECT_MASK_CLR__ata__BITNR 4
-#define R_VECT_MASK_CLR__ata__WIDTH 1
-#define R_VECT_MASK_CLR__ata__clr 1
-#define R_VECT_MASK_CLR__ata__nop 0
-#define R_VECT_MASK_CLR__mio__BITNR 4
-#define R_VECT_MASK_CLR__mio__WIDTH 1
-#define R_VECT_MASK_CLR__mio__clr 1
-#define R_VECT_MASK_CLR__mio__nop 0
-#define R_VECT_MASK_CLR__timer1__BITNR 3
-#define R_VECT_MASK_CLR__timer1__WIDTH 1
-#define R_VECT_MASK_CLR__timer1__clr 1
-#define R_VECT_MASK_CLR__timer1__nop 0
-#define R_VECT_MASK_CLR__timer0__BITNR 2
-#define R_VECT_MASK_CLR__timer0__WIDTH 1
-#define R_VECT_MASK_CLR__timer0__clr 1
-#define R_VECT_MASK_CLR__timer0__nop 0
-#define R_VECT_MASK_CLR__nmi__BITNR 1
-#define R_VECT_MASK_CLR__nmi__WIDTH 1
-#define R_VECT_MASK_CLR__nmi__clr 1
-#define R_VECT_MASK_CLR__nmi__nop 0
-#define R_VECT_MASK_CLR__some__BITNR 0
-#define R_VECT_MASK_CLR__some__WIDTH 1
-#define R_VECT_MASK_CLR__some__clr 1
-#define R_VECT_MASK_CLR__some__nop 0
-
-#define R_VECT_READ (IO_TYPECAST_RO_UDWORD 0xb00000dc)
-#define R_VECT_READ__usb__BITNR 31
-#define R_VECT_READ__usb__WIDTH 1
-#define R_VECT_READ__usb__active 1
-#define R_VECT_READ__usb__inactive 0
-#define R_VECT_READ__dma9__BITNR 25
-#define R_VECT_READ__dma9__WIDTH 1
-#define R_VECT_READ__dma9__active 1
-#define R_VECT_READ__dma9__inactive 0
-#define R_VECT_READ__dma8__BITNR 24
-#define R_VECT_READ__dma8__WIDTH 1
-#define R_VECT_READ__dma8__active 1
-#define R_VECT_READ__dma8__inactive 0
-#define R_VECT_READ__dma7__BITNR 23
-#define R_VECT_READ__dma7__WIDTH 1
-#define R_VECT_READ__dma7__active 1
-#define R_VECT_READ__dma7__inactive 0
-#define R_VECT_READ__dma6__BITNR 22
-#define R_VECT_READ__dma6__WIDTH 1
-#define R_VECT_READ__dma6__active 1
-#define R_VECT_READ__dma6__inactive 0
-#define R_VECT_READ__dma5__BITNR 21
-#define R_VECT_READ__dma5__WIDTH 1
-#define R_VECT_READ__dma5__active 1
-#define R_VECT_READ__dma5__inactive 0
-#define R_VECT_READ__dma4__BITNR 20
-#define R_VECT_READ__dma4__WIDTH 1
-#define R_VECT_READ__dma4__active 1
-#define R_VECT_READ__dma4__inactive 0
-#define R_VECT_READ__dma3__BITNR 19
-#define R_VECT_READ__dma3__WIDTH 1
-#define R_VECT_READ__dma3__active 1
-#define R_VECT_READ__dma3__inactive 0
-#define R_VECT_READ__dma2__BITNR 18
-#define R_VECT_READ__dma2__WIDTH 1
-#define R_VECT_READ__dma2__active 1
-#define R_VECT_READ__dma2__inactive 0
-#define R_VECT_READ__dma1__BITNR 17
-#define R_VECT_READ__dma1__WIDTH 1
-#define R_VECT_READ__dma1__active 1
-#define R_VECT_READ__dma1__inactive 0
-#define R_VECT_READ__dma0__BITNR 16
-#define R_VECT_READ__dma0__WIDTH 1
-#define R_VECT_READ__dma0__active 1
-#define R_VECT_READ__dma0__inactive 0
-#define R_VECT_READ__ext_dma1__BITNR 13
-#define R_VECT_READ__ext_dma1__WIDTH 1
-#define R_VECT_READ__ext_dma1__active 1
-#define R_VECT_READ__ext_dma1__inactive 0
-#define R_VECT_READ__ext_dma0__BITNR 12
-#define R_VECT_READ__ext_dma0__WIDTH 1
-#define R_VECT_READ__ext_dma0__active 1
-#define R_VECT_READ__ext_dma0__inactive 0
-#define R_VECT_READ__pa__BITNR 11
-#define R_VECT_READ__pa__WIDTH 1
-#define R_VECT_READ__pa__active 1
-#define R_VECT_READ__pa__inactive 0
-#define R_VECT_READ__irq_intnr__BITNR 10
-#define R_VECT_READ__irq_intnr__WIDTH 1
-#define R_VECT_READ__irq_intnr__active 1
-#define R_VECT_READ__irq_intnr__inactive 0
-#define R_VECT_READ__sw__BITNR 9
-#define R_VECT_READ__sw__WIDTH 1
-#define R_VECT_READ__sw__active 1
-#define R_VECT_READ__sw__inactive 0
-#define R_VECT_READ__serial__BITNR 8
-#define R_VECT_READ__serial__WIDTH 1
-#define R_VECT_READ__serial__active 1
-#define R_VECT_READ__serial__inactive 0
-#define R_VECT_READ__snmp__BITNR 7
-#define R_VECT_READ__snmp__WIDTH 1
-#define R_VECT_READ__snmp__active 1
-#define R_VECT_READ__snmp__inactive 0
-#define R_VECT_READ__network__BITNR 6
-#define R_VECT_READ__network__WIDTH 1
-#define R_VECT_READ__network__active 1
-#define R_VECT_READ__network__inactive 0
-#define R_VECT_READ__scsi1__BITNR 5
-#define R_VECT_READ__scsi1__WIDTH 1
-#define R_VECT_READ__scsi1__active 1
-#define R_VECT_READ__scsi1__inactive 0
-#define R_VECT_READ__par1__BITNR 5
-#define R_VECT_READ__par1__WIDTH 1
-#define R_VECT_READ__par1__active 1
-#define R_VECT_READ__par1__inactive 0
-#define R_VECT_READ__scsi0__BITNR 4
-#define R_VECT_READ__scsi0__WIDTH 1
-#define R_VECT_READ__scsi0__active 1
-#define R_VECT_READ__scsi0__inactive 0
-#define R_VECT_READ__par0__BITNR 4
-#define R_VECT_READ__par0__WIDTH 1
-#define R_VECT_READ__par0__active 1
-#define R_VECT_READ__par0__inactive 0
-#define R_VECT_READ__ata__BITNR 4
-#define R_VECT_READ__ata__WIDTH 1
-#define R_VECT_READ__ata__active 1
-#define R_VECT_READ__ata__inactive 0
-#define R_VECT_READ__mio__BITNR 4
-#define R_VECT_READ__mio__WIDTH 1
-#define R_VECT_READ__mio__active 1
-#define R_VECT_READ__mio__inactive 0
-#define R_VECT_READ__timer1__BITNR 3
-#define R_VECT_READ__timer1__WIDTH 1
-#define R_VECT_READ__timer1__active 1
-#define R_VECT_READ__timer1__inactive 0
-#define R_VECT_READ__timer0__BITNR 2
-#define R_VECT_READ__timer0__WIDTH 1
-#define R_VECT_READ__timer0__active 1
-#define R_VECT_READ__timer0__inactive 0
-#define R_VECT_READ__nmi__BITNR 1
-#define R_VECT_READ__nmi__WIDTH 1
-#define R_VECT_READ__nmi__active 1
-#define R_VECT_READ__nmi__inactive 0
-#define R_VECT_READ__some__BITNR 0
-#define R_VECT_READ__some__WIDTH 1
-#define R_VECT_READ__some__active 1
-#define R_VECT_READ__some__inactive 0
-
-#define R_VECT_MASK_SET (IO_TYPECAST_UDWORD 0xb00000dc)
-#define R_VECT_MASK_SET__usb__BITNR 31
-#define R_VECT_MASK_SET__usb__WIDTH 1
-#define R_VECT_MASK_SET__usb__set 1
-#define R_VECT_MASK_SET__usb__nop 0
-#define R_VECT_MASK_SET__dma9__BITNR 25
-#define R_VECT_MASK_SET__dma9__WIDTH 1
-#define R_VECT_MASK_SET__dma9__set 1
-#define R_VECT_MASK_SET__dma9__nop 0
-#define R_VECT_MASK_SET__dma8__BITNR 24
-#define R_VECT_MASK_SET__dma8__WIDTH 1
-#define R_VECT_MASK_SET__dma8__set 1
-#define R_VECT_MASK_SET__dma8__nop 0
-#define R_VECT_MASK_SET__dma7__BITNR 23
-#define R_VECT_MASK_SET__dma7__WIDTH 1
-#define R_VECT_MASK_SET__dma7__set 1
-#define R_VECT_MASK_SET__dma7__nop 0
-#define R_VECT_MASK_SET__dma6__BITNR 22
-#define R_VECT_MASK_SET__dma6__WIDTH 1
-#define R_VECT_MASK_SET__dma6__set 1
-#define R_VECT_MASK_SET__dma6__nop 0
-#define R_VECT_MASK_SET__dma5__BITNR 21
-#define R_VECT_MASK_SET__dma5__WIDTH 1
-#define R_VECT_MASK_SET__dma5__set 1
-#define R_VECT_MASK_SET__dma5__nop 0
-#define R_VECT_MASK_SET__dma4__BITNR 20
-#define R_VECT_MASK_SET__dma4__WIDTH 1
-#define R_VECT_MASK_SET__dma4__set 1
-#define R_VECT_MASK_SET__dma4__nop 0
-#define R_VECT_MASK_SET__dma3__BITNR 19
-#define R_VECT_MASK_SET__dma3__WIDTH 1
-#define R_VECT_MASK_SET__dma3__set 1
-#define R_VECT_MASK_SET__dma3__nop 0
-#define R_VECT_MASK_SET__dma2__BITNR 18
-#define R_VECT_MASK_SET__dma2__WIDTH 1
-#define R_VECT_MASK_SET__dma2__set 1
-#define R_VECT_MASK_SET__dma2__nop 0
-#define R_VECT_MASK_SET__dma1__BITNR 17
-#define R_VECT_MASK_SET__dma1__WIDTH 1
-#define R_VECT_MASK_SET__dma1__set 1
-#define R_VECT_MASK_SET__dma1__nop 0
-#define R_VECT_MASK_SET__dma0__BITNR 16
-#define R_VECT_MASK_SET__dma0__WIDTH 1
-#define R_VECT_MASK_SET__dma0__set 1
-#define R_VECT_MASK_SET__dma0__nop 0
-#define R_VECT_MASK_SET__ext_dma1__BITNR 13
-#define R_VECT_MASK_SET__ext_dma1__WIDTH 1
-#define R_VECT_MASK_SET__ext_dma1__set 1
-#define R_VECT_MASK_SET__ext_dma1__nop 0
-#define R_VECT_MASK_SET__ext_dma0__BITNR 12
-#define R_VECT_MASK_SET__ext_dma0__WIDTH 1
-#define R_VECT_MASK_SET__ext_dma0__set 1
-#define R_VECT_MASK_SET__ext_dma0__nop 0
-#define R_VECT_MASK_SET__pa__BITNR 11
-#define R_VECT_MASK_SET__pa__WIDTH 1
-#define R_VECT_MASK_SET__pa__set 1
-#define R_VECT_MASK_SET__pa__nop 0
-#define R_VECT_MASK_SET__irq_intnr__BITNR 10
-#define R_VECT_MASK_SET__irq_intnr__WIDTH 1
-#define R_VECT_MASK_SET__irq_intnr__set 1
-#define R_VECT_MASK_SET__irq_intnr__nop 0
-#define R_VECT_MASK_SET__sw__BITNR 9
-#define R_VECT_MASK_SET__sw__WIDTH 1
-#define R_VECT_MASK_SET__sw__set 1
-#define R_VECT_MASK_SET__sw__nop 0
-#define R_VECT_MASK_SET__serial__BITNR 8
-#define R_VECT_MASK_SET__serial__WIDTH 1
-#define R_VECT_MASK_SET__serial__set 1
-#define R_VECT_MASK_SET__serial__nop 0
-#define R_VECT_MASK_SET__snmp__BITNR 7
-#define R_VECT_MASK_SET__snmp__WIDTH 1
-#define R_VECT_MASK_SET__snmp__set 1
-#define R_VECT_MASK_SET__snmp__nop 0
-#define R_VECT_MASK_SET__network__BITNR 6
-#define R_VECT_MASK_SET__network__WIDTH 1
-#define R_VECT_MASK_SET__network__set 1
-#define R_VECT_MASK_SET__network__nop 0
-#define R_VECT_MASK_SET__scsi1__BITNR 5
-#define R_VECT_MASK_SET__scsi1__WIDTH 1
-#define R_VECT_MASK_SET__scsi1__set 1
-#define R_VECT_MASK_SET__scsi1__nop 0
-#define R_VECT_MASK_SET__par1__BITNR 5
-#define R_VECT_MASK_SET__par1__WIDTH 1
-#define R_VECT_MASK_SET__par1__set 1
-#define R_VECT_MASK_SET__par1__nop 0
-#define R_VECT_MASK_SET__scsi0__BITNR 4
-#define R_VECT_MASK_SET__scsi0__WIDTH 1
-#define R_VECT_MASK_SET__scsi0__set 1
-#define R_VECT_MASK_SET__scsi0__nop 0
-#define R_VECT_MASK_SET__par0__BITNR 4
-#define R_VECT_MASK_SET__par0__WIDTH 1
-#define R_VECT_MASK_SET__par0__set 1
-#define R_VECT_MASK_SET__par0__nop 0
-#define R_VECT_MASK_SET__ata__BITNR 4
-#define R_VECT_MASK_SET__ata__WIDTH 1
-#define R_VECT_MASK_SET__ata__set 1
-#define R_VECT_MASK_SET__ata__nop 0
-#define R_VECT_MASK_SET__mio__BITNR 4
-#define R_VECT_MASK_SET__mio__WIDTH 1
-#define R_VECT_MASK_SET__mio__set 1
-#define R_VECT_MASK_SET__mio__nop 0
-#define R_VECT_MASK_SET__timer1__BITNR 3
-#define R_VECT_MASK_SET__timer1__WIDTH 1
-#define R_VECT_MASK_SET__timer1__set 1
-#define R_VECT_MASK_SET__timer1__nop 0
-#define R_VECT_MASK_SET__timer0__BITNR 2
-#define R_VECT_MASK_SET__timer0__WIDTH 1
-#define R_VECT_MASK_SET__timer0__set 1
-#define R_VECT_MASK_SET__timer0__nop 0
-#define R_VECT_MASK_SET__nmi__BITNR 1
-#define R_VECT_MASK_SET__nmi__WIDTH 1
-#define R_VECT_MASK_SET__nmi__set 1
-#define R_VECT_MASK_SET__nmi__nop 0
-#define R_VECT_MASK_SET__some__BITNR 0
-#define R_VECT_MASK_SET__some__WIDTH 1
-#define R_VECT_MASK_SET__some__set 1
-#define R_VECT_MASK_SET__some__nop 0
-
-/*
-!* DMA registers
-!*/
-
-#define R_SET_EOP (IO_TYPECAST_UDWORD 0xb000003c)
-#define R_SET_EOP__ch9_eop__BITNR 3
-#define R_SET_EOP__ch9_eop__WIDTH 1
-#define R_SET_EOP__ch9_eop__set 1
-#define R_SET_EOP__ch9_eop__nop 0
-#define R_SET_EOP__ch7_eop__BITNR 2
-#define R_SET_EOP__ch7_eop__WIDTH 1
-#define R_SET_EOP__ch7_eop__set 1
-#define R_SET_EOP__ch7_eop__nop 0
-#define R_SET_EOP__ch5_eop__BITNR 1
-#define R_SET_EOP__ch5_eop__WIDTH 1
-#define R_SET_EOP__ch5_eop__set 1
-#define R_SET_EOP__ch5_eop__nop 0
-#define R_SET_EOP__ch3_eop__BITNR 0
-#define R_SET_EOP__ch3_eop__WIDTH 1
-#define R_SET_EOP__ch3_eop__set 1
-#define R_SET_EOP__ch3_eop__nop 0
-
-#define R_DMA_CH0_HWSW (IO_TYPECAST_UDWORD 0xb0000100)
-#define R_DMA_CH0_HWSW__hw__BITNR 16
-#define R_DMA_CH0_HWSW__hw__WIDTH 16
-#define R_DMA_CH0_HWSW__sw__BITNR 0
-#define R_DMA_CH0_HWSW__sw__WIDTH 16
-
-#define R_DMA_CH0_DESCR (IO_TYPECAST_UDWORD 0xb000010c)
-#define R_DMA_CH0_DESCR__descr__BITNR 0
-#define R_DMA_CH0_DESCR__descr__WIDTH 32
-
-#define R_DMA_CH0_NEXT (IO_TYPECAST_UDWORD 0xb0000104)
-#define R_DMA_CH0_NEXT__next__BITNR 0
-#define R_DMA_CH0_NEXT__next__WIDTH 32
-
-#define R_DMA_CH0_BUF (IO_TYPECAST_UDWORD 0xb0000108)
-#define R_DMA_CH0_BUF__buf__BITNR 0
-#define R_DMA_CH0_BUF__buf__WIDTH 32
-
-#define R_DMA_CH0_FIRST (IO_TYPECAST_UDWORD 0xb00001a0)
-#define R_DMA_CH0_FIRST__first__BITNR 0
-#define R_DMA_CH0_FIRST__first__WIDTH 32
-
-#define R_DMA_CH0_CMD (IO_TYPECAST_BYTE 0xb00001d0)
-#define R_DMA_CH0_CMD__cmd__BITNR 0
-#define R_DMA_CH0_CMD__cmd__WIDTH 3
-#define R_DMA_CH0_CMD__cmd__hold 0
-#define R_DMA_CH0_CMD__cmd__start 1
-#define R_DMA_CH0_CMD__cmd__restart 3
-#define R_DMA_CH0_CMD__cmd__continue 3
-#define R_DMA_CH0_CMD__cmd__reset 4
-
-#define R_DMA_CH0_CLR_INTR (IO_TYPECAST_BYTE 0xb00001d1)
-#define R_DMA_CH0_CLR_INTR__clr_eop__BITNR 1
-#define R_DMA_CH0_CLR_INTR__clr_eop__WIDTH 1
-#define R_DMA_CH0_CLR_INTR__clr_eop__do 1
-#define R_DMA_CH0_CLR_INTR__clr_eop__dont 0
-#define R_DMA_CH0_CLR_INTR__clr_descr__BITNR 0
-#define R_DMA_CH0_CLR_INTR__clr_descr__WIDTH 1
-#define R_DMA_CH0_CLR_INTR__clr_descr__do 1
-#define R_DMA_CH0_CLR_INTR__clr_descr__dont 0
-
-#define R_DMA_CH0_STATUS (IO_TYPECAST_RO_BYTE 0xb00001d2)
-#define R_DMA_CH0_STATUS__avail__BITNR 0
-#define R_DMA_CH0_STATUS__avail__WIDTH 7
-
-#define R_DMA_CH1_HWSW (IO_TYPECAST_UDWORD 0xb0000110)
-#define R_DMA_CH1_HWSW__hw__BITNR 16
-#define R_DMA_CH1_HWSW__hw__WIDTH 16
-#define R_DMA_CH1_HWSW__sw__BITNR 0
-#define R_DMA_CH1_HWSW__sw__WIDTH 16
-
-#define R_DMA_CH1_DESCR (IO_TYPECAST_UDWORD 0xb000011c)
-#define R_DMA_CH1_DESCR__descr__BITNR 0
-#define R_DMA_CH1_DESCR__descr__WIDTH 32
-
-#define R_DMA_CH1_NEXT (IO_TYPECAST_UDWORD 0xb0000114)
-#define R_DMA_CH1_NEXT__next__BITNR 0
-#define R_DMA_CH1_NEXT__next__WIDTH 32
-
-#define R_DMA_CH1_BUF (IO_TYPECAST_UDWORD 0xb0000118)
-#define R_DMA_CH1_BUF__buf__BITNR 0
-#define R_DMA_CH1_BUF__buf__WIDTH 32
-
-#define R_DMA_CH1_FIRST (IO_TYPECAST_UDWORD 0xb00001a4)
-#define R_DMA_CH1_FIRST__first__BITNR 0
-#define R_DMA_CH1_FIRST__first__WIDTH 32
-
-#define R_DMA_CH1_CMD (IO_TYPECAST_BYTE 0xb00001d4)
-#define R_DMA_CH1_CMD__cmd__BITNR 0
-#define R_DMA_CH1_CMD__cmd__WIDTH 3
-#define R_DMA_CH1_CMD__cmd__hold 0
-#define R_DMA_CH1_CMD__cmd__start 1
-#define R_DMA_CH1_CMD__cmd__restart 3
-#define R_DMA_CH1_CMD__cmd__continue 3
-#define R_DMA_CH1_CMD__cmd__reset 4
-
-#define R_DMA_CH1_CLR_INTR (IO_TYPECAST_BYTE 0xb00001d5)
-#define R_DMA_CH1_CLR_INTR__clr_eop__BITNR 1
-#define R_DMA_CH1_CLR_INTR__clr_eop__WIDTH 1
-#define R_DMA_CH1_CLR_INTR__clr_eop__do 1
-#define R_DMA_CH1_CLR_INTR__clr_eop__dont 0
-#define R_DMA_CH1_CLR_INTR__clr_descr__BITNR 0
-#define R_DMA_CH1_CLR_INTR__clr_descr__WIDTH 1
-#define R_DMA_CH1_CLR_INTR__clr_descr__do 1
-#define R_DMA_CH1_CLR_INTR__clr_descr__dont 0
-
-#define R_DMA_CH1_STATUS (IO_TYPECAST_RO_BYTE 0xb00001d6)
-#define R_DMA_CH1_STATUS__avail__BITNR 0
-#define R_DMA_CH1_STATUS__avail__WIDTH 7
-
-#define R_DMA_CH2_HWSW (IO_TYPECAST_UDWORD 0xb0000120)
-#define R_DMA_CH2_HWSW__hw__BITNR 16
-#define R_DMA_CH2_HWSW__hw__WIDTH 16
-#define R_DMA_CH2_HWSW__sw__BITNR 0
-#define R_DMA_CH2_HWSW__sw__WIDTH 16
-
-#define R_DMA_CH2_DESCR (IO_TYPECAST_UDWORD 0xb000012c)
-#define R_DMA_CH2_DESCR__descr__BITNR 0
-#define R_DMA_CH2_DESCR__descr__WIDTH 32
-
-#define R_DMA_CH2_NEXT (IO_TYPECAST_UDWORD 0xb0000124)
-#define R_DMA_CH2_NEXT__next__BITNR 0
-#define R_DMA_CH2_NEXT__next__WIDTH 32
-
-#define R_DMA_CH2_BUF (IO_TYPECAST_UDWORD 0xb0000128)
-#define R_DMA_CH2_BUF__buf__BITNR 0
-#define R_DMA_CH2_BUF__buf__WIDTH 32
-
-#define R_DMA_CH2_FIRST (IO_TYPECAST_UDWORD 0xb00001a8)
-#define R_DMA_CH2_FIRST__first__BITNR 0
-#define R_DMA_CH2_FIRST__first__WIDTH 32
-
-#define R_DMA_CH2_CMD (IO_TYPECAST_BYTE 0xb00001d8)
-#define R_DMA_CH2_CMD__cmd__BITNR 0
-#define R_DMA_CH2_CMD__cmd__WIDTH 3
-#define R_DMA_CH2_CMD__cmd__hold 0
-#define R_DMA_CH2_CMD__cmd__start 1
-#define R_DMA_CH2_CMD__cmd__restart 3
-#define R_DMA_CH2_CMD__cmd__continue 3
-#define R_DMA_CH2_CMD__cmd__reset 4
-
-#define R_DMA_CH2_CLR_INTR (IO_TYPECAST_BYTE 0xb00001d9)
-#define R_DMA_CH2_CLR_INTR__clr_eop__BITNR 1
-#define R_DMA_CH2_CLR_INTR__clr_eop__WIDTH 1
-#define R_DMA_CH2_CLR_INTR__clr_eop__do 1
-#define R_DMA_CH2_CLR_INTR__clr_eop__dont 0
-#define R_DMA_CH2_CLR_INTR__clr_descr__BITNR 0
-#define R_DMA_CH2_CLR_INTR__clr_descr__WIDTH 1
-#define R_DMA_CH2_CLR_INTR__clr_descr__do 1
-#define R_DMA_CH2_CLR_INTR__clr_descr__dont 0
-
-#define R_DMA_CH2_STATUS (IO_TYPECAST_RO_BYTE 0xb00001da)
-#define R_DMA_CH2_STATUS__avail__BITNR 0
-#define R_DMA_CH2_STATUS__avail__WIDTH 7
-
-#define R_DMA_CH3_HWSW (IO_TYPECAST_UDWORD 0xb0000130)
-#define R_DMA_CH3_HWSW__hw__BITNR 16
-#define R_DMA_CH3_HWSW__hw__WIDTH 16
-#define R_DMA_CH3_HWSW__sw__BITNR 0
-#define R_DMA_CH3_HWSW__sw__WIDTH 16
-
-#define R_DMA_CH3_DESCR (IO_TYPECAST_UDWORD 0xb000013c)
-#define R_DMA_CH3_DESCR__descr__BITNR 0
-#define R_DMA_CH3_DESCR__descr__WIDTH 32
-
-#define R_DMA_CH3_NEXT (IO_TYPECAST_UDWORD 0xb0000134)
-#define R_DMA_CH3_NEXT__next__BITNR 0
-#define R_DMA_CH3_NEXT__next__WIDTH 32
-
-#define R_DMA_CH3_BUF (IO_TYPECAST_UDWORD 0xb0000138)
-#define R_DMA_CH3_BUF__buf__BITNR 0
-#define R_DMA_CH3_BUF__buf__WIDTH 32
-
-#define R_DMA_CH3_FIRST (IO_TYPECAST_UDWORD 0xb00001ac)
-#define R_DMA_CH3_FIRST__first__BITNR 0
-#define R_DMA_CH3_FIRST__first__WIDTH 32
-
-#define R_DMA_CH3_CMD (IO_TYPECAST_BYTE 0xb00001dc)
-#define R_DMA_CH3_CMD__cmd__BITNR 0
-#define R_DMA_CH3_CMD__cmd__WIDTH 3
-#define R_DMA_CH3_CMD__cmd__hold 0
-#define R_DMA_CH3_CMD__cmd__start 1
-#define R_DMA_CH3_CMD__cmd__restart 3
-#define R_DMA_CH3_CMD__cmd__continue 3
-#define R_DMA_CH3_CMD__cmd__reset 4
-
-#define R_DMA_CH3_CLR_INTR (IO_TYPECAST_BYTE 0xb00001dd)
-#define R_DMA_CH3_CLR_INTR__clr_eop__BITNR 1
-#define R_DMA_CH3_CLR_INTR__clr_eop__WIDTH 1
-#define R_DMA_CH3_CLR_INTR__clr_eop__do 1
-#define R_DMA_CH3_CLR_INTR__clr_eop__dont 0
-#define R_DMA_CH3_CLR_INTR__clr_descr__BITNR 0
-#define R_DMA_CH3_CLR_INTR__clr_descr__WIDTH 1
-#define R_DMA_CH3_CLR_INTR__clr_descr__do 1
-#define R_DMA_CH3_CLR_INTR__clr_descr__dont 0
-
-#define R_DMA_CH3_STATUS (IO_TYPECAST_RO_BYTE 0xb00001de)
-#define R_DMA_CH3_STATUS__avail__BITNR 0
-#define R_DMA_CH3_STATUS__avail__WIDTH 7
-
-#define R_DMA_CH4_HWSW (IO_TYPECAST_UDWORD 0xb0000140)
-#define R_DMA_CH4_HWSW__hw__BITNR 16
-#define R_DMA_CH4_HWSW__hw__WIDTH 16
-#define R_DMA_CH4_HWSW__sw__BITNR 0
-#define R_DMA_CH4_HWSW__sw__WIDTH 16
-
-#define R_DMA_CH4_DESCR (IO_TYPECAST_UDWORD 0xb000014c)
-#define R_DMA_CH4_DESCR__descr__BITNR 0
-#define R_DMA_CH4_DESCR__descr__WIDTH 32
-
-#define R_DMA_CH4_NEXT (IO_TYPECAST_UDWORD 0xb0000144)
-#define R_DMA_CH4_NEXT__next__BITNR 0
-#define R_DMA_CH4_NEXT__next__WIDTH 32
-
-#define R_DMA_CH4_BUF (IO_TYPECAST_UDWORD 0xb0000148)
-#define R_DMA_CH4_BUF__buf__BITNR 0
-#define R_DMA_CH4_BUF__buf__WIDTH 32
-
-#define R_DMA_CH4_FIRST (IO_TYPECAST_UDWORD 0xb00001b0)
-#define R_DMA_CH4_FIRST__first__BITNR 0
-#define R_DMA_CH4_FIRST__first__WIDTH 32
-
-#define R_DMA_CH4_CMD (IO_TYPECAST_BYTE 0xb00001e0)
-#define R_DMA_CH4_CMD__cmd__BITNR 0
-#define R_DMA_CH4_CMD__cmd__WIDTH 3
-#define R_DMA_CH4_CMD__cmd__hold 0
-#define R_DMA_CH4_CMD__cmd__start 1
-#define R_DMA_CH4_CMD__cmd__restart 3
-#define R_DMA_CH4_CMD__cmd__continue 3
-#define R_DMA_CH4_CMD__cmd__reset 4
-
-#define R_DMA_CH4_CLR_INTR (IO_TYPECAST_BYTE 0xb00001e1)
-#define R_DMA_CH4_CLR_INTR__clr_eop__BITNR 1
-#define R_DMA_CH4_CLR_INTR__clr_eop__WIDTH 1
-#define R_DMA_CH4_CLR_INTR__clr_eop__do 1
-#define R_DMA_CH4_CLR_INTR__clr_eop__dont 0
-#define R_DMA_CH4_CLR_INTR__clr_descr__BITNR 0
-#define R_DMA_CH4_CLR_INTR__clr_descr__WIDTH 1
-#define R_DMA_CH4_CLR_INTR__clr_descr__do 1
-#define R_DMA_CH4_CLR_INTR__clr_descr__dont 0
-
-#define R_DMA_CH4_STATUS (IO_TYPECAST_RO_BYTE 0xb00001e2)
-#define R_DMA_CH4_STATUS__avail__BITNR 0
-#define R_DMA_CH4_STATUS__avail__WIDTH 7
-
-#define R_DMA_CH5_HWSW (IO_TYPECAST_UDWORD 0xb0000150)
-#define R_DMA_CH5_HWSW__hw__BITNR 16
-#define R_DMA_CH5_HWSW__hw__WIDTH 16
-#define R_DMA_CH5_HWSW__sw__BITNR 0
-#define R_DMA_CH5_HWSW__sw__WIDTH 16
-
-#define R_DMA_CH5_DESCR (IO_TYPECAST_UDWORD 0xb000015c)
-#define R_DMA_CH5_DESCR__descr__BITNR 0
-#define R_DMA_CH5_DESCR__descr__WIDTH 32
-
-#define R_DMA_CH5_NEXT (IO_TYPECAST_UDWORD 0xb0000154)
-#define R_DMA_CH5_NEXT__next__BITNR 0
-#define R_DMA_CH5_NEXT__next__WIDTH 32
-
-#define R_DMA_CH5_BUF (IO_TYPECAST_UDWORD 0xb0000158)
-#define R_DMA_CH5_BUF__buf__BITNR 0
-#define R_DMA_CH5_BUF__buf__WIDTH 32
-
-#define R_DMA_CH5_FIRST (IO_TYPECAST_UDWORD 0xb00001b4)
-#define R_DMA_CH5_FIRST__first__BITNR 0
-#define R_DMA_CH5_FIRST__first__WIDTH 32
-
-#define R_DMA_CH5_CMD (IO_TYPECAST_BYTE 0xb00001e4)
-#define R_DMA_CH5_CMD__cmd__BITNR 0
-#define R_DMA_CH5_CMD__cmd__WIDTH 3
-#define R_DMA_CH5_CMD__cmd__hold 0
-#define R_DMA_CH5_CMD__cmd__start 1
-#define R_DMA_CH5_CMD__cmd__restart 3
-#define R_DMA_CH5_CMD__cmd__continue 3
-#define R_DMA_CH5_CMD__cmd__reset 4
-
-#define R_DMA_CH5_CLR_INTR (IO_TYPECAST_BYTE 0xb00001e5)
-#define R_DMA_CH5_CLR_INTR__clr_eop__BITNR 1
-#define R_DMA_CH5_CLR_INTR__clr_eop__WIDTH 1
-#define R_DMA_CH5_CLR_INTR__clr_eop__do 1
-#define R_DMA_CH5_CLR_INTR__clr_eop__dont 0
-#define R_DMA_CH5_CLR_INTR__clr_descr__BITNR 0
-#define R_DMA_CH5_CLR_INTR__clr_descr__WIDTH 1
-#define R_DMA_CH5_CLR_INTR__clr_descr__do 1
-#define R_DMA_CH5_CLR_INTR__clr_descr__dont 0
-
-#define R_DMA_CH5_STATUS (IO_TYPECAST_RO_BYTE 0xb00001e6)
-#define R_DMA_CH5_STATUS__avail__BITNR 0
-#define R_DMA_CH5_STATUS__avail__WIDTH 7
-
-#define R_DMA_CH6_HWSW (IO_TYPECAST_UDWORD 0xb0000160)
-#define R_DMA_CH6_HWSW__hw__BITNR 16
-#define R_DMA_CH6_HWSW__hw__WIDTH 16
-#define R_DMA_CH6_HWSW__sw__BITNR 0
-#define R_DMA_CH6_HWSW__sw__WIDTH 16
-
-#define R_DMA_CH6_DESCR (IO_TYPECAST_UDWORD 0xb000016c)
-#define R_DMA_CH6_DESCR__descr__BITNR 0
-#define R_DMA_CH6_DESCR__descr__WIDTH 32
-
-#define R_DMA_CH6_NEXT (IO_TYPECAST_UDWORD 0xb0000164)
-#define R_DMA_CH6_NEXT__next__BITNR 0
-#define R_DMA_CH6_NEXT__next__WIDTH 32
-
-#define R_DMA_CH6_BUF (IO_TYPECAST_UDWORD 0xb0000168)
-#define R_DMA_CH6_BUF__buf__BITNR 0
-#define R_DMA_CH6_BUF__buf__WIDTH 32
-
-#define R_DMA_CH6_FIRST (IO_TYPECAST_UDWORD 0xb00001b8)
-#define R_DMA_CH6_FIRST__first__BITNR 0
-#define R_DMA_CH6_FIRST__first__WIDTH 32
-
-#define R_DMA_CH6_CMD (IO_TYPECAST_BYTE 0xb00001e8)
-#define R_DMA_CH6_CMD__cmd__BITNR 0
-#define R_DMA_CH6_CMD__cmd__WIDTH 3
-#define R_DMA_CH6_CMD__cmd__hold 0
-#define R_DMA_CH6_CMD__cmd__start 1
-#define R_DMA_CH6_CMD__cmd__restart 3
-#define R_DMA_CH6_CMD__cmd__continue 3
-#define R_DMA_CH6_CMD__cmd__reset 4
-
-#define R_DMA_CH6_CLR_INTR (IO_TYPECAST_BYTE 0xb00001e9)
-#define R_DMA_CH6_CLR_INTR__clr_eop__BITNR 1
-#define R_DMA_CH6_CLR_INTR__clr_eop__WIDTH 1
-#define R_DMA_CH6_CLR_INTR__clr_eop__do 1
-#define R_DMA_CH6_CLR_INTR__clr_eop__dont 0
-#define R_DMA_CH6_CLR_INTR__clr_descr__BITNR 0
-#define R_DMA_CH6_CLR_INTR__clr_descr__WIDTH 1
-#define R_DMA_CH6_CLR_INTR__clr_descr__do 1
-#define R_DMA_CH6_CLR_INTR__clr_descr__dont 0
-
-#define R_DMA_CH6_STATUS (IO_TYPECAST_RO_BYTE 0xb00001ea)
-#define R_DMA_CH6_STATUS__avail__BITNR 0
-#define R_DMA_CH6_STATUS__avail__WIDTH 7
-
-#define R_DMA_CH7_HWSW (IO_TYPECAST_UDWORD 0xb0000170)
-#define R_DMA_CH7_HWSW__hw__BITNR 16
-#define R_DMA_CH7_HWSW__hw__WIDTH 16
-#define R_DMA_CH7_HWSW__sw__BITNR 0
-#define R_DMA_CH7_HWSW__sw__WIDTH 16
-
-#define R_DMA_CH7_DESCR (IO_TYPECAST_UDWORD 0xb000017c)
-#define R_DMA_CH7_DESCR__descr__BITNR 0
-#define R_DMA_CH7_DESCR__descr__WIDTH 32
-
-#define R_DMA_CH7_NEXT (IO_TYPECAST_UDWORD 0xb0000174)
-#define R_DMA_CH7_NEXT__next__BITNR 0
-#define R_DMA_CH7_NEXT__next__WIDTH 32
-
-#define R_DMA_CH7_BUF (IO_TYPECAST_UDWORD 0xb0000178)
-#define R_DMA_CH7_BUF__buf__BITNR 0
-#define R_DMA_CH7_BUF__buf__WIDTH 32
-
-#define R_DMA_CH7_FIRST (IO_TYPECAST_UDWORD 0xb00001bc)
-#define R_DMA_CH7_FIRST__first__BITNR 0
-#define R_DMA_CH7_FIRST__first__WIDTH 32
-
-#define R_DMA_CH7_CMD (IO_TYPECAST_BYTE 0xb00001ec)
-#define R_DMA_CH7_CMD__cmd__BITNR 0
-#define R_DMA_CH7_CMD__cmd__WIDTH 3
-#define R_DMA_CH7_CMD__cmd__hold 0
-#define R_DMA_CH7_CMD__cmd__start 1
-#define R_DMA_CH7_CMD__cmd__restart 3
-#define R_DMA_CH7_CMD__cmd__continue 3
-#define R_DMA_CH7_CMD__cmd__reset 4
-
-#define R_DMA_CH7_CLR_INTR (IO_TYPECAST_BYTE 0xb00001ed)
-#define R_DMA_CH7_CLR_INTR__clr_eop__BITNR 1
-#define R_DMA_CH7_CLR_INTR__clr_eop__WIDTH 1
-#define R_DMA_CH7_CLR_INTR__clr_eop__do 1
-#define R_DMA_CH7_CLR_INTR__clr_eop__dont 0
-#define R_DMA_CH7_CLR_INTR__clr_descr__BITNR 0
-#define R_DMA_CH7_CLR_INTR__clr_descr__WIDTH 1
-#define R_DMA_CH7_CLR_INTR__clr_descr__do 1
-#define R_DMA_CH7_CLR_INTR__clr_descr__dont 0
-
-#define R_DMA_CH7_STATUS (IO_TYPECAST_RO_BYTE 0xb00001ee)
-#define R_DMA_CH7_STATUS__avail__BITNR 0
-#define R_DMA_CH7_STATUS__avail__WIDTH 7
-
-#define R_DMA_CH8_HWSW (IO_TYPECAST_UDWORD 0xb0000180)
-#define R_DMA_CH8_HWSW__hw__BITNR 16
-#define R_DMA_CH8_HWSW__hw__WIDTH 16
-#define R_DMA_CH8_HWSW__sw__BITNR 0
-#define R_DMA_CH8_HWSW__sw__WIDTH 16
-
-#define R_DMA_CH8_DESCR (IO_TYPECAST_UDWORD 0xb000018c)
-#define R_DMA_CH8_DESCR__descr__BITNR 0
-#define R_DMA_CH8_DESCR__descr__WIDTH 32
-
-#define R_DMA_CH8_NEXT (IO_TYPECAST_UDWORD 0xb0000184)
-#define R_DMA_CH8_NEXT__next__BITNR 0
-#define R_DMA_CH8_NEXT__next__WIDTH 32
-
-#define R_DMA_CH8_BUF (IO_TYPECAST_UDWORD 0xb0000188)
-#define R_DMA_CH8_BUF__buf__BITNR 0
-#define R_DMA_CH8_BUF__buf__WIDTH 32
-
-#define R_DMA_CH8_FIRST (IO_TYPECAST_UDWORD 0xb00001c0)
-#define R_DMA_CH8_FIRST__first__BITNR 0
-#define R_DMA_CH8_FIRST__first__WIDTH 32
-
-#define R_DMA_CH8_CMD (IO_TYPECAST_BYTE 0xb00001f0)
-#define R_DMA_CH8_CMD__cmd__BITNR 0
-#define R_DMA_CH8_CMD__cmd__WIDTH 3
-#define R_DMA_CH8_CMD__cmd__hold 0
-#define R_DMA_CH8_CMD__cmd__start 1
-#define R_DMA_CH8_CMD__cmd__restart 3
-#define R_DMA_CH8_CMD__cmd__continue 3
-#define R_DMA_CH8_CMD__cmd__reset 4
-
-#define R_DMA_CH8_CLR_INTR (IO_TYPECAST_BYTE 0xb00001f1)
-#define R_DMA_CH8_CLR_INTR__clr_eop__BITNR 1
-#define R_DMA_CH8_CLR_INTR__clr_eop__WIDTH 1
-#define R_DMA_CH8_CLR_INTR__clr_eop__do 1
-#define R_DMA_CH8_CLR_INTR__clr_eop__dont 0
-#define R_DMA_CH8_CLR_INTR__clr_descr__BITNR 0
-#define R_DMA_CH8_CLR_INTR__clr_descr__WIDTH 1
-#define R_DMA_CH8_CLR_INTR__clr_descr__do 1
-#define R_DMA_CH8_CLR_INTR__clr_descr__dont 0
-
-#define R_DMA_CH8_STATUS (IO_TYPECAST_RO_BYTE 0xb00001f2)
-#define R_DMA_CH8_STATUS__avail__BITNR 0
-#define R_DMA_CH8_STATUS__avail__WIDTH 7
-
-#define R_DMA_CH8_SUB (IO_TYPECAST_UDWORD 0xb000018c)
-#define R_DMA_CH8_SUB__sub__BITNR 0
-#define R_DMA_CH8_SUB__sub__WIDTH 32
-
-#define R_DMA_CH8_NEP (IO_TYPECAST_UDWORD 0xb00001c0)
-#define R_DMA_CH8_NEP__nep__BITNR 0
-#define R_DMA_CH8_NEP__nep__WIDTH 32
-
-#define R_DMA_CH8_SUB0_EP (IO_TYPECAST_UDWORD 0xb00001c8)
-#define R_DMA_CH8_SUB0_EP__ep__BITNR 0
-#define R_DMA_CH8_SUB0_EP__ep__WIDTH 32
-
-#define R_DMA_CH8_SUB0_CMD (IO_TYPECAST_BYTE 0xb00001d3)
-#define R_DMA_CH8_SUB0_CMD__cmd__BITNR 0
-#define R_DMA_CH8_SUB0_CMD__cmd__WIDTH 1
-#define R_DMA_CH8_SUB0_CMD__cmd__stop 0
-#define R_DMA_CH8_SUB0_CMD__cmd__start 1
-
-#define R_DMA_CH8_SUB0_CLR_INTR (IO_TYPECAST_BYTE 0xb00001e3)
-#define R_DMA_CH8_SUB0_CLR_INTR__clr_descr__BITNR 0
-#define R_DMA_CH8_SUB0_CLR_INTR__clr_descr__WIDTH 1
-#define R_DMA_CH8_SUB0_CLR_INTR__clr_descr__dont 0
-#define R_DMA_CH8_SUB0_CLR_INTR__clr_descr__do 1
-
-#define R_DMA_CH8_SUB1_EP (IO_TYPECAST_UDWORD 0xb00001cc)
-#define R_DMA_CH8_SUB1_EP__ep__BITNR 0
-#define R_DMA_CH8_SUB1_EP__ep__WIDTH 32
-
-#define R_DMA_CH8_SUB1_CMD (IO_TYPECAST_BYTE 0xb00001d7)
-#define R_DMA_CH8_SUB1_CMD__cmd__BITNR 0
-#define R_DMA_CH8_SUB1_CMD__cmd__WIDTH 1
-#define R_DMA_CH8_SUB1_CMD__cmd__stop 0
-#define R_DMA_CH8_SUB1_CMD__cmd__start 1
-
-#define R_DMA_CH8_SUB1_CLR_INTR (IO_TYPECAST_BYTE 0xb00001e7)
-#define R_DMA_CH8_SUB1_CLR_INTR__clr_descr__BITNR 0
-#define R_DMA_CH8_SUB1_CLR_INTR__clr_descr__WIDTH 1
-#define R_DMA_CH8_SUB1_CLR_INTR__clr_descr__dont 0
-#define R_DMA_CH8_SUB1_CLR_INTR__clr_descr__do 1
-
-#define R_DMA_CH8_SUB2_EP (IO_TYPECAST_UDWORD 0xb00001f8)
-#define R_DMA_CH8_SUB2_EP__ep__BITNR 0
-#define R_DMA_CH8_SUB2_EP__ep__WIDTH 32
-
-#define R_DMA_CH8_SUB2_CMD (IO_TYPECAST_BYTE 0xb00001db)
-#define R_DMA_CH8_SUB2_CMD__cmd__BITNR 0
-#define R_DMA_CH8_SUB2_CMD__cmd__WIDTH 1
-#define R_DMA_CH8_SUB2_CMD__cmd__stop 0
-#define R_DMA_CH8_SUB2_CMD__cmd__start 1
-
-#define R_DMA_CH8_SUB2_CLR_INTR (IO_TYPECAST_BYTE 0xb00001eb)
-#define R_DMA_CH8_SUB2_CLR_INTR__clr_descr__BITNR 0
-#define R_DMA_CH8_SUB2_CLR_INTR__clr_descr__WIDTH 1
-#define R_DMA_CH8_SUB2_CLR_INTR__clr_descr__dont 0
-#define R_DMA_CH8_SUB2_CLR_INTR__clr_descr__do 1
-
-#define R_DMA_CH8_SUB3_EP (IO_TYPECAST_UDWORD 0xb00001fc)
-#define R_DMA_CH8_SUB3_EP__ep__BITNR 0
-#define R_DMA_CH8_SUB3_EP__ep__WIDTH 32
-
-#define R_DMA_CH8_SUB3_CMD (IO_TYPECAST_BYTE 0xb00001df)
-#define R_DMA_CH8_SUB3_CMD__cmd__BITNR 0
-#define R_DMA_CH8_SUB3_CMD__cmd__WIDTH 1
-#define R_DMA_CH8_SUB3_CMD__cmd__stop 0
-#define R_DMA_CH8_SUB3_CMD__cmd__start 1
-
-#define R_DMA_CH8_SUB3_CLR_INTR (IO_TYPECAST_BYTE 0xb00001ef)
-#define R_DMA_CH8_SUB3_CLR_INTR__clr_descr__BITNR 0
-#define R_DMA_CH8_SUB3_CLR_INTR__clr_descr__WIDTH 1
-#define R_DMA_CH8_SUB3_CLR_INTR__clr_descr__dont 0
-#define R_DMA_CH8_SUB3_CLR_INTR__clr_descr__do 1
-
-#define R_DMA_CH9_HWSW (IO_TYPECAST_UDWORD 0xb0000190)
-#define R_DMA_CH9_HWSW__hw__BITNR 16
-#define R_DMA_CH9_HWSW__hw__WIDTH 16
-#define R_DMA_CH9_HWSW__sw__BITNR 0
-#define R_DMA_CH9_HWSW__sw__WIDTH 16
-
-#define R_DMA_CH9_DESCR (IO_TYPECAST_UDWORD 0xb000019c)
-#define R_DMA_CH9_DESCR__descr__BITNR 0
-#define R_DMA_CH9_DESCR__descr__WIDTH 32
-
-#define R_DMA_CH9_NEXT (IO_TYPECAST_UDWORD 0xb0000194)
-#define R_DMA_CH9_NEXT__next__BITNR 0
-#define R_DMA_CH9_NEXT__next__WIDTH 32
-
-#define R_DMA_CH9_BUF (IO_TYPECAST_UDWORD 0xb0000198)
-#define R_DMA_CH9_BUF__buf__BITNR 0
-#define R_DMA_CH9_BUF__buf__WIDTH 32
-
-#define R_DMA_CH9_FIRST (IO_TYPECAST_UDWORD 0xb00001c4)
-#define R_DMA_CH9_FIRST__first__BITNR 0
-#define R_DMA_CH9_FIRST__first__WIDTH 32
-
-#define R_DMA_CH9_CMD (IO_TYPECAST_BYTE 0xb00001f4)
-#define R_DMA_CH9_CMD__cmd__BITNR 0
-#define R_DMA_CH9_CMD__cmd__WIDTH 3
-#define R_DMA_CH9_CMD__cmd__hold 0
-#define R_DMA_CH9_CMD__cmd__start 1
-#define R_DMA_CH9_CMD__cmd__restart 3
-#define R_DMA_CH9_CMD__cmd__continue 3
-#define R_DMA_CH9_CMD__cmd__reset 4
-
-#define R_DMA_CH9_CLR_INTR (IO_TYPECAST_BYTE 0xb00001f5)
-#define R_DMA_CH9_CLR_INTR__clr_eop__BITNR 1
-#define R_DMA_CH9_CLR_INTR__clr_eop__WIDTH 1
-#define R_DMA_CH9_CLR_INTR__clr_eop__do 1
-#define R_DMA_CH9_CLR_INTR__clr_eop__dont 0
-#define R_DMA_CH9_CLR_INTR__clr_descr__BITNR 0
-#define R_DMA_CH9_CLR_INTR__clr_descr__WIDTH 1
-#define R_DMA_CH9_CLR_INTR__clr_descr__do 1
-#define R_DMA_CH9_CLR_INTR__clr_descr__dont 0
-
-#define R_DMA_CH9_STATUS (IO_TYPECAST_RO_BYTE 0xb00001f6)
-#define R_DMA_CH9_STATUS__avail__BITNR 0
-#define R_DMA_CH9_STATUS__avail__WIDTH 7
-
-/*
-!* Test mode registers
-!*/
-
-#define R_TEST_MODE (IO_TYPECAST_UDWORD 0xb00000fc)
-#define R_TEST_MODE__single_step__BITNR 19
-#define R_TEST_MODE__single_step__WIDTH 1
-#define R_TEST_MODE__single_step__on 1
-#define R_TEST_MODE__single_step__off 0
-#define R_TEST_MODE__step_wr__BITNR 18
-#define R_TEST_MODE__step_wr__WIDTH 1
-#define R_TEST_MODE__step_wr__on 1
-#define R_TEST_MODE__step_wr__off 0
-#define R_TEST_MODE__step_rd__BITNR 17
-#define R_TEST_MODE__step_rd__WIDTH 1
-#define R_TEST_MODE__step_rd__on 1
-#define R_TEST_MODE__step_rd__off 0
-#define R_TEST_MODE__step_fetch__BITNR 16
-#define R_TEST_MODE__step_fetch__WIDTH 1
-#define R_TEST_MODE__step_fetch__on 1
-#define R_TEST_MODE__step_fetch__off 0
-#define R_TEST_MODE__mmu_test__BITNR 12
-#define R_TEST_MODE__mmu_test__WIDTH 1
-#define R_TEST_MODE__mmu_test__on 1
-#define R_TEST_MODE__mmu_test__off 0
-#define R_TEST_MODE__usb_test__BITNR 11
-#define R_TEST_MODE__usb_test__WIDTH 1
-#define R_TEST_MODE__usb_test__on 1
-#define R_TEST_MODE__usb_test__off 0
-#define R_TEST_MODE__scsi_timer_test__BITNR 10
-#define R_TEST_MODE__scsi_timer_test__WIDTH 1
-#define R_TEST_MODE__scsi_timer_test__on 1
-#define R_TEST_MODE__scsi_timer_test__off 0
-#define R_TEST_MODE__backoff__BITNR 9
-#define R_TEST_MODE__backoff__WIDTH 1
-#define R_TEST_MODE__backoff__on 1
-#define R_TEST_MODE__backoff__off 0
-#define R_TEST_MODE__snmp_test__BITNR 8
-#define R_TEST_MODE__snmp_test__WIDTH 1
-#define R_TEST_MODE__snmp_test__on 1
-#define R_TEST_MODE__snmp_test__off 0
-#define R_TEST_MODE__snmp_inc__BITNR 7
-#define R_TEST_MODE__snmp_inc__WIDTH 1
-#define R_TEST_MODE__snmp_inc__do 1
-#define R_TEST_MODE__snmp_inc__dont 0
-#define R_TEST_MODE__ser_loop__BITNR 6
-#define R_TEST_MODE__ser_loop__WIDTH 1
-#define R_TEST_MODE__ser_loop__on 1
-#define R_TEST_MODE__ser_loop__off 0
-#define R_TEST_MODE__baudrate__BITNR 5
-#define R_TEST_MODE__baudrate__WIDTH 1
-#define R_TEST_MODE__baudrate__on 1
-#define R_TEST_MODE__baudrate__off 0
-#define R_TEST_MODE__timer__BITNR 3
-#define R_TEST_MODE__timer__WIDTH 2
-#define R_TEST_MODE__timer__off 0
-#define R_TEST_MODE__timer__even 1
-#define R_TEST_MODE__timer__odd 2
-#define R_TEST_MODE__timer__all 3
-#define R_TEST_MODE__cache_test__BITNR 2
-#define R_TEST_MODE__cache_test__WIDTH 1
-#define R_TEST_MODE__cache_test__normal 0
-#define R_TEST_MODE__cache_test__test 1
-#define R_TEST_MODE__tag_test__BITNR 1
-#define R_TEST_MODE__tag_test__WIDTH 1
-#define R_TEST_MODE__tag_test__normal 0
-#define R_TEST_MODE__tag_test__test 1
-#define R_TEST_MODE__cache_enable__BITNR 0
-#define R_TEST_MODE__cache_enable__WIDTH 1
-#define R_TEST_MODE__cache_enable__enable 1
-#define R_TEST_MODE__cache_enable__disable 0
-
-#define R_SINGLE_STEP (IO_TYPECAST_BYTE 0xb00000fe)
-#define R_SINGLE_STEP__single_step__BITNR 3
-#define R_SINGLE_STEP__single_step__WIDTH 1
-#define R_SINGLE_STEP__single_step__on 1
-#define R_SINGLE_STEP__single_step__off 0
-#define R_SINGLE_STEP__step_wr__BITNR 2
-#define R_SINGLE_STEP__step_wr__WIDTH 1
-#define R_SINGLE_STEP__step_wr__on 1
-#define R_SINGLE_STEP__step_wr__off 0
-#define R_SINGLE_STEP__step_rd__BITNR 1
-#define R_SINGLE_STEP__step_rd__WIDTH 1
-#define R_SINGLE_STEP__step_rd__on 1
-#define R_SINGLE_STEP__step_rd__off 0
-#define R_SINGLE_STEP__step_fetch__BITNR 0
-#define R_SINGLE_STEP__step_fetch__WIDTH 1
-#define R_SINGLE_STEP__step_fetch__on 1
-#define R_SINGLE_STEP__step_fetch__off 0
-
-/*
-!* USB interface control registers
-!*/
-
-#define R_USB_REVISION (IO_TYPECAST_RO_BYTE 0xb0000200)
-#define R_USB_REVISION__major__BITNR 4
-#define R_USB_REVISION__major__WIDTH 4
-#define R_USB_REVISION__minor__BITNR 0
-#define R_USB_REVISION__minor__WIDTH 4
-
-#define R_USB_COMMAND (IO_TYPECAST_BYTE 0xb0000201)
-#define R_USB_COMMAND__port_sel__BITNR 6
-#define R_USB_COMMAND__port_sel__WIDTH 2
-#define R_USB_COMMAND__port_sel__nop 0
-#define R_USB_COMMAND__port_sel__port1 1
-#define R_USB_COMMAND__port_sel__port2 2
-#define R_USB_COMMAND__port_sel__both 3
-#define R_USB_COMMAND__port_cmd__BITNR 4
-#define R_USB_COMMAND__port_cmd__WIDTH 2
-#define R_USB_COMMAND__port_cmd__reset 0
-#define R_USB_COMMAND__port_cmd__disable 1
-#define R_USB_COMMAND__port_cmd__suspend 2
-#define R_USB_COMMAND__port_cmd__resume 3
-#define R_USB_COMMAND__busy__BITNR 3
-#define R_USB_COMMAND__busy__WIDTH 1
-#define R_USB_COMMAND__busy__no 0
-#define R_USB_COMMAND__busy__yes 1
-#define R_USB_COMMAND__ctrl_cmd__BITNR 0
-#define R_USB_COMMAND__ctrl_cmd__WIDTH 3
-#define R_USB_COMMAND__ctrl_cmd__nop 0
-#define R_USB_COMMAND__ctrl_cmd__reset 1
-#define R_USB_COMMAND__ctrl_cmd__deconfig 2
-#define R_USB_COMMAND__ctrl_cmd__host_config 3
-#define R_USB_COMMAND__ctrl_cmd__dev_config 4
-#define R_USB_COMMAND__ctrl_cmd__host_nop 5
-#define R_USB_COMMAND__ctrl_cmd__host_run 6
-#define R_USB_COMMAND__ctrl_cmd__host_stop 7
-
-#define R_USB_COMMAND_DEV (IO_TYPECAST_BYTE 0xb0000201)
-#define R_USB_COMMAND_DEV__port_sel__BITNR 6
-#define R_USB_COMMAND_DEV__port_sel__WIDTH 2
-#define R_USB_COMMAND_DEV__port_sel__nop 0
-#define R_USB_COMMAND_DEV__port_sel__dummy1 1
-#define R_USB_COMMAND_DEV__port_sel__dummy2 2
-#define R_USB_COMMAND_DEV__port_sel__any 3
-#define R_USB_COMMAND_DEV__port_cmd__BITNR 4
-#define R_USB_COMMAND_DEV__port_cmd__WIDTH 2
-#define R_USB_COMMAND_DEV__port_cmd__active 0
-#define R_USB_COMMAND_DEV__port_cmd__passive 1
-#define R_USB_COMMAND_DEV__port_cmd__nop 2
-#define R_USB_COMMAND_DEV__port_cmd__wakeup 3
-#define R_USB_COMMAND_DEV__busy__BITNR 3
-#define R_USB_COMMAND_DEV__busy__WIDTH 1
-#define R_USB_COMMAND_DEV__busy__no 0
-#define R_USB_COMMAND_DEV__busy__yes 1
-#define R_USB_COMMAND_DEV__ctrl_cmd__BITNR 0
-#define R_USB_COMMAND_DEV__ctrl_cmd__WIDTH 3
-#define R_USB_COMMAND_DEV__ctrl_cmd__nop 0
-#define R_USB_COMMAND_DEV__ctrl_cmd__reset 1
-#define R_USB_COMMAND_DEV__ctrl_cmd__deconfig 2
-#define R_USB_COMMAND_DEV__ctrl_cmd__host_config 3
-#define R_USB_COMMAND_DEV__ctrl_cmd__dev_config 4
-#define R_USB_COMMAND_DEV__ctrl_cmd__dev_active 5
-#define R_USB_COMMAND_DEV__ctrl_cmd__dev_passive 6
-#define R_USB_COMMAND_DEV__ctrl_cmd__dev_nop 7
-
-#define R_USB_STATUS (IO_TYPECAST_RO_BYTE 0xb0000202)
-#define R_USB_STATUS__ourun__BITNR 5
-#define R_USB_STATUS__ourun__WIDTH 1
-#define R_USB_STATUS__ourun__no 0
-#define R_USB_STATUS__ourun__yes 1
-#define R_USB_STATUS__perror__BITNR 4
-#define R_USB_STATUS__perror__WIDTH 1
-#define R_USB_STATUS__perror__no 0
-#define R_USB_STATUS__perror__yes 1
-#define R_USB_STATUS__device_mode__BITNR 3
-#define R_USB_STATUS__device_mode__WIDTH 1
-#define R_USB_STATUS__device_mode__no 0
-#define R_USB_STATUS__device_mode__yes 1
-#define R_USB_STATUS__host_mode__BITNR 2
-#define R_USB_STATUS__host_mode__WIDTH 1
-#define R_USB_STATUS__host_mode__no 0
-#define R_USB_STATUS__host_mode__yes 1
-#define R_USB_STATUS__started__BITNR 1
-#define R_USB_STATUS__started__WIDTH 1
-#define R_USB_STATUS__started__no 0
-#define R_USB_STATUS__started__yes 1
-#define R_USB_STATUS__running__BITNR 0
-#define R_USB_STATUS__running__WIDTH 1
-#define R_USB_STATUS__running__no 0
-#define R_USB_STATUS__running__yes 1
-
-#define R_USB_IRQ_MASK_SET (IO_TYPECAST_UWORD 0xb0000204)
-#define R_USB_IRQ_MASK_SET__iso_eof__BITNR 13
-#define R_USB_IRQ_MASK_SET__iso_eof__WIDTH 1
-#define R_USB_IRQ_MASK_SET__iso_eof__nop 0
-#define R_USB_IRQ_MASK_SET__iso_eof__set 1
-#define R_USB_IRQ_MASK_SET__intr_eof__BITNR 12
-#define R_USB_IRQ_MASK_SET__intr_eof__WIDTH 1
-#define R_USB_IRQ_MASK_SET__intr_eof__nop 0
-#define R_USB_IRQ_MASK_SET__intr_eof__set 1
-#define R_USB_IRQ_MASK_SET__iso_eot__BITNR 11
-#define R_USB_IRQ_MASK_SET__iso_eot__WIDTH 1
-#define R_USB_IRQ_MASK_SET__iso_eot__nop 0
-#define R_USB_IRQ_MASK_SET__iso_eot__set 1
-#define R_USB_IRQ_MASK_SET__intr_eot__BITNR 10
-#define R_USB_IRQ_MASK_SET__intr_eot__WIDTH 1
-#define R_USB_IRQ_MASK_SET__intr_eot__nop 0
-#define R_USB_IRQ_MASK_SET__intr_eot__set 1
-#define R_USB_IRQ_MASK_SET__ctl_eot__BITNR 9
-#define R_USB_IRQ_MASK_SET__ctl_eot__WIDTH 1
-#define R_USB_IRQ_MASK_SET__ctl_eot__nop 0
-#define R_USB_IRQ_MASK_SET__ctl_eot__set 1
-#define R_USB_IRQ_MASK_SET__bulk_eot__BITNR 8
-#define R_USB_IRQ_MASK_SET__bulk_eot__WIDTH 1
-#define R_USB_IRQ_MASK_SET__bulk_eot__nop 0
-#define R_USB_IRQ_MASK_SET__bulk_eot__set 1
-#define R_USB_IRQ_MASK_SET__epid_attn__BITNR 3
-#define R_USB_IRQ_MASK_SET__epid_attn__WIDTH 1
-#define R_USB_IRQ_MASK_SET__epid_attn__nop 0
-#define R_USB_IRQ_MASK_SET__epid_attn__set 1
-#define R_USB_IRQ_MASK_SET__sof__BITNR 2
-#define R_USB_IRQ_MASK_SET__sof__WIDTH 1
-#define R_USB_IRQ_MASK_SET__sof__nop 0
-#define R_USB_IRQ_MASK_SET__sof__set 1
-#define R_USB_IRQ_MASK_SET__port_status__BITNR 1
-#define R_USB_IRQ_MASK_SET__port_status__WIDTH 1
-#define R_USB_IRQ_MASK_SET__port_status__nop 0
-#define R_USB_IRQ_MASK_SET__port_status__set 1
-#define R_USB_IRQ_MASK_SET__ctl_status__BITNR 0
-#define R_USB_IRQ_MASK_SET__ctl_status__WIDTH 1
-#define R_USB_IRQ_MASK_SET__ctl_status__nop 0
-#define R_USB_IRQ_MASK_SET__ctl_status__set 1
-
-#define R_USB_IRQ_MASK_READ (IO_TYPECAST_RO_UWORD 0xb0000204)
-#define R_USB_IRQ_MASK_READ__iso_eof__BITNR 13
-#define R_USB_IRQ_MASK_READ__iso_eof__WIDTH 1
-#define R_USB_IRQ_MASK_READ__iso_eof__no_pend 0
-#define R_USB_IRQ_MASK_READ__iso_eof__pend 1
-#define R_USB_IRQ_MASK_READ__intr_eof__BITNR 12
-#define R_USB_IRQ_MASK_READ__intr_eof__WIDTH 1
-#define R_USB_IRQ_MASK_READ__intr_eof__no_pend 0
-#define R_USB_IRQ_MASK_READ__intr_eof__pend 1
-#define R_USB_IRQ_MASK_READ__iso_eot__BITNR 11
-#define R_USB_IRQ_MASK_READ__iso_eot__WIDTH 1
-#define R_USB_IRQ_MASK_READ__iso_eot__no_pend 0
-#define R_USB_IRQ_MASK_READ__iso_eot__pend 1
-#define R_USB_IRQ_MASK_READ__intr_eot__BITNR 10
-#define R_USB_IRQ_MASK_READ__intr_eot__WIDTH 1
-#define R_USB_IRQ_MASK_READ__intr_eot__no_pend 0
-#define R_USB_IRQ_MASK_READ__intr_eot__pend 1
-#define R_USB_IRQ_MASK_READ__ctl_eot__BITNR 9
-#define R_USB_IRQ_MASK_READ__ctl_eot__WIDTH 1
-#define R_USB_IRQ_MASK_READ__ctl_eot__no_pend 0
-#define R_USB_IRQ_MASK_READ__ctl_eot__pend 1
-#define R_USB_IRQ_MASK_READ__bulk_eot__BITNR 8
-#define R_USB_IRQ_MASK_READ__bulk_eot__WIDTH 1
-#define R_USB_IRQ_MASK_READ__bulk_eot__no_pend 0
-#define R_USB_IRQ_MASK_READ__bulk_eot__pend 1
-#define R_USB_IRQ_MASK_READ__epid_attn__BITNR 3
-#define R_USB_IRQ_MASK_READ__epid_attn__WIDTH 1
-#define R_USB_IRQ_MASK_READ__epid_attn__no_pend 0
-#define R_USB_IRQ_MASK_READ__epid_attn__pend 1
-#define R_USB_IRQ_MASK_READ__sof__BITNR 2
-#define R_USB_IRQ_MASK_READ__sof__WIDTH 1
-#define R_USB_IRQ_MASK_READ__sof__no_pend 0
-#define R_USB_IRQ_MASK_READ__sof__pend 1
-#define R_USB_IRQ_MASK_READ__port_status__BITNR 1
-#define R_USB_IRQ_MASK_READ__port_status__WIDTH 1
-#define R_USB_IRQ_MASK_READ__port_status__no_pend 0
-#define R_USB_IRQ_MASK_READ__port_status__pend 1
-#define R_USB_IRQ_MASK_READ__ctl_status__BITNR 0
-#define R_USB_IRQ_MASK_READ__ctl_status__WIDTH 1
-#define R_USB_IRQ_MASK_READ__ctl_status__no_pend 0
-#define R_USB_IRQ_MASK_READ__ctl_status__pend 1
-
-#define R_USB_IRQ_MASK_CLR (IO_TYPECAST_UWORD 0xb0000206)
-#define R_USB_IRQ_MASK_CLR__iso_eof__BITNR 13
-#define R_USB_IRQ_MASK_CLR__iso_eof__WIDTH 1
-#define R_USB_IRQ_MASK_CLR__iso_eof__nop 0
-#define R_USB_IRQ_MASK_CLR__iso_eof__clr 1
-#define R_USB_IRQ_MASK_CLR__intr_eof__BITNR 12
-#define R_USB_IRQ_MASK_CLR__intr_eof__WIDTH 1
-#define R_USB_IRQ_MASK_CLR__intr_eof__nop 0
-#define R_USB_IRQ_MASK_CLR__intr_eof__clr 1
-#define R_USB_IRQ_MASK_CLR__iso_eot__BITNR 11
-#define R_USB_IRQ_MASK_CLR__iso_eot__WIDTH 1
-#define R_USB_IRQ_MASK_CLR__iso_eot__nop 0
-#define R_USB_IRQ_MASK_CLR__iso_eot__clr 1
-#define R_USB_IRQ_MASK_CLR__intr_eot__BITNR 10
-#define R_USB_IRQ_MASK_CLR__intr_eot__WIDTH 1
-#define R_USB_IRQ_MASK_CLR__intr_eot__nop 0
-#define R_USB_IRQ_MASK_CLR__intr_eot__clr 1
-#define R_USB_IRQ_MASK_CLR__ctl_eot__BITNR 9
-#define R_USB_IRQ_MASK_CLR__ctl_eot__WIDTH 1
-#define R_USB_IRQ_MASK_CLR__ctl_eot__nop 0
-#define R_USB_IRQ_MASK_CLR__ctl_eot__clr 1
-#define R_USB_IRQ_MASK_CLR__bulk_eot__BITNR 8
-#define R_USB_IRQ_MASK_CLR__bulk_eot__WIDTH 1
-#define R_USB_IRQ_MASK_CLR__bulk_eot__nop 0
-#define R_USB_IRQ_MASK_CLR__bulk_eot__clr 1
-#define R_USB_IRQ_MASK_CLR__epid_attn__BITNR 3
-#define R_USB_IRQ_MASK_CLR__epid_attn__WIDTH 1
-#define R_USB_IRQ_MASK_CLR__epid_attn__nop 0
-#define R_USB_IRQ_MASK_CLR__epid_attn__clr 1
-#define R_USB_IRQ_MASK_CLR__sof__BITNR 2
-#define R_USB_IRQ_MASK_CLR__sof__WIDTH 1
-#define R_USB_IRQ_MASK_CLR__sof__nop 0
-#define R_USB_IRQ_MASK_CLR__sof__clr 1
-#define R_USB_IRQ_MASK_CLR__port_status__BITNR 1
-#define R_USB_IRQ_MASK_CLR__port_status__WIDTH 1
-#define R_USB_IRQ_MASK_CLR__port_status__nop 0
-#define R_USB_IRQ_MASK_CLR__port_status__clr 1
-#define R_USB_IRQ_MASK_CLR__ctl_status__BITNR 0
-#define R_USB_IRQ_MASK_CLR__ctl_status__WIDTH 1
-#define R_USB_IRQ_MASK_CLR__ctl_status__nop 0
-#define R_USB_IRQ_MASK_CLR__ctl_status__clr 1
-
-#define R_USB_IRQ_READ (IO_TYPECAST_RO_UWORD 0xb0000206)
-#define R_USB_IRQ_READ__iso_eof__BITNR 13
-#define R_USB_IRQ_READ__iso_eof__WIDTH 1
-#define R_USB_IRQ_READ__iso_eof__no_pend 0
-#define R_USB_IRQ_READ__iso_eof__pend 1
-#define R_USB_IRQ_READ__intr_eof__BITNR 12
-#define R_USB_IRQ_READ__intr_eof__WIDTH 1
-#define R_USB_IRQ_READ__intr_eof__no_pend 0
-#define R_USB_IRQ_READ__intr_eof__pend 1
-#define R_USB_IRQ_READ__iso_eot__BITNR 11
-#define R_USB_IRQ_READ__iso_eot__WIDTH 1
-#define R_USB_IRQ_READ__iso_eot__no_pend 0
-#define R_USB_IRQ_READ__iso_eot__pend 1
-#define R_USB_IRQ_READ__intr_eot__BITNR 10
-#define R_USB_IRQ_READ__intr_eot__WIDTH 1
-#define R_USB_IRQ_READ__intr_eot__no_pend 0
-#define R_USB_IRQ_READ__intr_eot__pend 1
-#define R_USB_IRQ_READ__ctl_eot__BITNR 9
-#define R_USB_IRQ_READ__ctl_eot__WIDTH 1
-#define R_USB_IRQ_READ__ctl_eot__no_pend 0
-#define R_USB_IRQ_READ__ctl_eot__pend 1
-#define R_USB_IRQ_READ__bulk_eot__BITNR 8
-#define R_USB_IRQ_READ__bulk_eot__WIDTH 1
-#define R_USB_IRQ_READ__bulk_eot__no_pend 0
-#define R_USB_IRQ_READ__bulk_eot__pend 1
-#define R_USB_IRQ_READ__epid_attn__BITNR 3
-#define R_USB_IRQ_READ__epid_attn__WIDTH 1
-#define R_USB_IRQ_READ__epid_attn__no_pend 0
-#define R_USB_IRQ_READ__epid_attn__pend 1
-#define R_USB_IRQ_READ__sof__BITNR 2
-#define R_USB_IRQ_READ__sof__WIDTH 1
-#define R_USB_IRQ_READ__sof__no_pend 0
-#define R_USB_IRQ_READ__sof__pend 1
-#define R_USB_IRQ_READ__port_status__BITNR 1
-#define R_USB_IRQ_READ__port_status__WIDTH 1
-#define R_USB_IRQ_READ__port_status__no_pend 0
-#define R_USB_IRQ_READ__port_status__pend 1
-#define R_USB_IRQ_READ__ctl_status__BITNR 0
-#define R_USB_IRQ_READ__ctl_status__WIDTH 1
-#define R_USB_IRQ_READ__ctl_status__no_pend 0
-#define R_USB_IRQ_READ__ctl_status__pend 1
-
-#define R_USB_IRQ_MASK_SET_DEV (IO_TYPECAST_UWORD 0xb0000204)
-#define R_USB_IRQ_MASK_SET_DEV__out_eot__BITNR 12
-#define R_USB_IRQ_MASK_SET_DEV__out_eot__WIDTH 1
-#define R_USB_IRQ_MASK_SET_DEV__out_eot__nop 0
-#define R_USB_IRQ_MASK_SET_DEV__out_eot__set 1
-#define R_USB_IRQ_MASK_SET_DEV__ep3_in_eot__BITNR 11
-#define R_USB_IRQ_MASK_SET_DEV__ep3_in_eot__WIDTH 1
-#define R_USB_IRQ_MASK_SET_DEV__ep3_in_eot__nop 0
-#define R_USB_IRQ_MASK_SET_DEV__ep3_in_eot__set 1
-#define R_USB_IRQ_MASK_SET_DEV__ep2_in_eot__BITNR 10
-#define R_USB_IRQ_MASK_SET_DEV__ep2_in_eot__WIDTH 1
-#define R_USB_IRQ_MASK_SET_DEV__ep2_in_eot__nop 0
-#define R_USB_IRQ_MASK_SET_DEV__ep2_in_eot__set 1
-#define R_USB_IRQ_MASK_SET_DEV__ep1_in_eot__BITNR 9
-#define R_USB_IRQ_MASK_SET_DEV__ep1_in_eot__WIDTH 1
-#define R_USB_IRQ_MASK_SET_DEV__ep1_in_eot__nop 0
-#define R_USB_IRQ_MASK_SET_DEV__ep1_in_eot__set 1
-#define R_USB_IRQ_MASK_SET_DEV__ep0_in_eot__BITNR 8
-#define R_USB_IRQ_MASK_SET_DEV__ep0_in_eot__WIDTH 1
-#define R_USB_IRQ_MASK_SET_DEV__ep0_in_eot__nop 0
-#define R_USB_IRQ_MASK_SET_DEV__ep0_in_eot__set 1
-#define R_USB_IRQ_MASK_SET_DEV__epid_attn__BITNR 3
-#define R_USB_IRQ_MASK_SET_DEV__epid_attn__WIDTH 1
-#define R_USB_IRQ_MASK_SET_DEV__epid_attn__nop 0
-#define R_USB_IRQ_MASK_SET_DEV__epid_attn__set 1
-#define R_USB_IRQ_MASK_SET_DEV__sof__BITNR 2
-#define R_USB_IRQ_MASK_SET_DEV__sof__WIDTH 1
-#define R_USB_IRQ_MASK_SET_DEV__sof__nop 0
-#define R_USB_IRQ_MASK_SET_DEV__sof__set 1
-#define R_USB_IRQ_MASK_SET_DEV__port_status__BITNR 1
-#define R_USB_IRQ_MASK_SET_DEV__port_status__WIDTH 1
-#define R_USB_IRQ_MASK_SET_DEV__port_status__nop 0
-#define R_USB_IRQ_MASK_SET_DEV__port_status__set 1
-#define R_USB_IRQ_MASK_SET_DEV__ctl_status__BITNR 0
-#define R_USB_IRQ_MASK_SET_DEV__ctl_status__WIDTH 1
-#define R_USB_IRQ_MASK_SET_DEV__ctl_status__nop 0
-#define R_USB_IRQ_MASK_SET_DEV__ctl_status__set 1
-
-#define R_USB_IRQ_MASK_READ_DEV (IO_TYPECAST_RO_UWORD 0xb0000204)
-#define R_USB_IRQ_MASK_READ_DEV__out_eot__BITNR 12
-#define R_USB_IRQ_MASK_READ_DEV__out_eot__WIDTH 1
-#define R_USB_IRQ_MASK_READ_DEV__out_eot__no_pend 0
-#define R_USB_IRQ_MASK_READ_DEV__out_eot__pend 1
-#define R_USB_IRQ_MASK_READ_DEV__ep3_in_eot__BITNR 11
-#define R_USB_IRQ_MASK_READ_DEV__ep3_in_eot__WIDTH 1
-#define R_USB_IRQ_MASK_READ_DEV__ep3_in_eot__no_pend 0
-#define R_USB_IRQ_MASK_READ_DEV__ep3_in_eot__pend 1
-#define R_USB_IRQ_MASK_READ_DEV__ep2_in_eot__BITNR 10
-#define R_USB_IRQ_MASK_READ_DEV__ep2_in_eot__WIDTH 1
-#define R_USB_IRQ_MASK_READ_DEV__ep2_in_eot__no_pend 0
-#define R_USB_IRQ_MASK_READ_DEV__ep2_in_eot__pend 1
-#define R_USB_IRQ_MASK_READ_DEV__ep1_in_eot__BITNR 9
-#define R_USB_IRQ_MASK_READ_DEV__ep1_in_eot__WIDTH 1
-#define R_USB_IRQ_MASK_READ_DEV__ep1_in_eot__no_pend 0
-#define R_USB_IRQ_MASK_READ_DEV__ep1_in_eot__pend 1
-#define R_USB_IRQ_MASK_READ_DEV__ep0_in_eot__BITNR 8
-#define R_USB_IRQ_MASK_READ_DEV__ep0_in_eot__WIDTH 1
-#define R_USB_IRQ_MASK_READ_DEV__ep0_in_eot__no_pend 0
-#define R_USB_IRQ_MASK_READ_DEV__ep0_in_eot__pend 1
-#define R_USB_IRQ_MASK_READ_DEV__epid_attn__BITNR 3
-#define R_USB_IRQ_MASK_READ_DEV__epid_attn__WIDTH 1
-#define R_USB_IRQ_MASK_READ_DEV__epid_attn__no_pend 0
-#define R_USB_IRQ_MASK_READ_DEV__epid_attn__pend 1
-#define R_USB_IRQ_MASK_READ_DEV__sof__BITNR 2
-#define R_USB_IRQ_MASK_READ_DEV__sof__WIDTH 1
-#define R_USB_IRQ_MASK_READ_DEV__sof__no_pend 0
-#define R_USB_IRQ_MASK_READ_DEV__sof__pend 1
-#define R_USB_IRQ_MASK_READ_DEV__port_status__BITNR 1
-#define R_USB_IRQ_MASK_READ_DEV__port_status__WIDTH 1
-#define R_USB_IRQ_MASK_READ_DEV__port_status__no_pend 0
-#define R_USB_IRQ_MASK_READ_DEV__port_status__pend 1
-#define R_USB_IRQ_MASK_READ_DEV__ctl_status__BITNR 0
-#define R_USB_IRQ_MASK_READ_DEV__ctl_status__WIDTH 1
-#define R_USB_IRQ_MASK_READ_DEV__ctl_status__no_pend 0
-#define R_USB_IRQ_MASK_READ_DEV__ctl_status__pend 1
-
-#define R_USB_IRQ_MASK_CLR_DEV (IO_TYPECAST_UWORD 0xb0000206)
-#define R_USB_IRQ_MASK_CLR_DEV__out_eot__BITNR 12
-#define R_USB_IRQ_MASK_CLR_DEV__out_eot__WIDTH 1
-#define R_USB_IRQ_MASK_CLR_DEV__out_eot__nop 0
-#define R_USB_IRQ_MASK_CLR_DEV__out_eot__clr 1
-#define R_USB_IRQ_MASK_CLR_DEV__ep3_in_eot__BITNR 11
-#define R_USB_IRQ_MASK_CLR_DEV__ep3_in_eot__WIDTH 1
-#define R_USB_IRQ_MASK_CLR_DEV__ep3_in_eot__nop 0
-#define R_USB_IRQ_MASK_CLR_DEV__ep3_in_eot__clr 1
-#define R_USB_IRQ_MASK_CLR_DEV__ep2_in_eot__BITNR 10
-#define R_USB_IRQ_MASK_CLR_DEV__ep2_in_eot__WIDTH 1
-#define R_USB_IRQ_MASK_CLR_DEV__ep2_in_eot__nop 0
-#define R_USB_IRQ_MASK_CLR_DEV__ep2_in_eot__clr 1
-#define R_USB_IRQ_MASK_CLR_DEV__ep1_in_eot__BITNR 9
-#define R_USB_IRQ_MASK_CLR_DEV__ep1_in_eot__WIDTH 1
-#define R_USB_IRQ_MASK_CLR_DEV__ep1_in_eot__nop 0
-#define R_USB_IRQ_MASK_CLR_DEV__ep1_in_eot__clr 1
-#define R_USB_IRQ_MASK_CLR_DEV__ep0_in_eot__BITNR 8
-#define R_USB_IRQ_MASK_CLR_DEV__ep0_in_eot__WIDTH 1
-#define R_USB_IRQ_MASK_CLR_DEV__ep0_in_eot__nop 0
-#define R_USB_IRQ_MASK_CLR_DEV__ep0_in_eot__clr 1
-#define R_USB_IRQ_MASK_CLR_DEV__epid_attn__BITNR 3
-#define R_USB_IRQ_MASK_CLR_DEV__epid_attn__WIDTH 1
-#define R_USB_IRQ_MASK_CLR_DEV__epid_attn__nop 0
-#define R_USB_IRQ_MASK_CLR_DEV__epid_attn__clr 1
-#define R_USB_IRQ_MASK_CLR_DEV__sof__BITNR 2
-#define R_USB_IRQ_MASK_CLR_DEV__sof__WIDTH 1
-#define R_USB_IRQ_MASK_CLR_DEV__sof__nop 0
-#define R_USB_IRQ_MASK_CLR_DEV__sof__clr 1
-#define R_USB_IRQ_MASK_CLR_DEV__port_status__BITNR 1
-#define R_USB_IRQ_MASK_CLR_DEV__port_status__WIDTH 1
-#define R_USB_IRQ_MASK_CLR_DEV__port_status__nop 0
-#define R_USB_IRQ_MASK_CLR_DEV__port_status__clr 1
-#define R_USB_IRQ_MASK_CLR_DEV__ctl_status__BITNR 0
-#define R_USB_IRQ_MASK_CLR_DEV__ctl_status__WIDTH 1
-#define R_USB_IRQ_MASK_CLR_DEV__ctl_status__nop 0
-#define R_USB_IRQ_MASK_CLR_DEV__ctl_status__clr 1
-
-#define R_USB_IRQ_READ_DEV (IO_TYPECAST_RO_UWORD 0xb0000206)
-#define R_USB_IRQ_READ_DEV__out_eot__BITNR 12
-#define R_USB_IRQ_READ_DEV__out_eot__WIDTH 1
-#define R_USB_IRQ_READ_DEV__out_eot__no_pend 0
-#define R_USB_IRQ_READ_DEV__out_eot__pend 1
-#define R_USB_IRQ_READ_DEV__ep3_in_eot__BITNR 11
-#define R_USB_IRQ_READ_DEV__ep3_in_eot__WIDTH 1
-#define R_USB_IRQ_READ_DEV__ep3_in_eot__no_pend 0
-#define R_USB_IRQ_READ_DEV__ep3_in_eot__pend 1
-#define R_USB_IRQ_READ_DEV__ep2_in_eot__BITNR 10
-#define R_USB_IRQ_READ_DEV__ep2_in_eot__WIDTH 1
-#define R_USB_IRQ_READ_DEV__ep2_in_eot__no_pend 0
-#define R_USB_IRQ_READ_DEV__ep2_in_eot__pend 1
-#define R_USB_IRQ_READ_DEV__ep1_in_eot__BITNR 9
-#define R_USB_IRQ_READ_DEV__ep1_in_eot__WIDTH 1
-#define R_USB_IRQ_READ_DEV__ep1_in_eot__no_pend 0
-#define R_USB_IRQ_READ_DEV__ep1_in_eot__pend 1
-#define R_USB_IRQ_READ_DEV__ep0_in_eot__BITNR 8
-#define R_USB_IRQ_READ_DEV__ep0_in_eot__WIDTH 1
-#define R_USB_IRQ_READ_DEV__ep0_in_eot__no_pend 0
-#define R_USB_IRQ_READ_DEV__ep0_in_eot__pend 1
-#define R_USB_IRQ_READ_DEV__epid_attn__BITNR 3
-#define R_USB_IRQ_READ_DEV__epid_attn__WIDTH 1
-#define R_USB_IRQ_READ_DEV__epid_attn__no_pend 0
-#define R_USB_IRQ_READ_DEV__epid_attn__pend 1
-#define R_USB_IRQ_READ_DEV__sof__BITNR 2
-#define R_USB_IRQ_READ_DEV__sof__WIDTH 1
-#define R_USB_IRQ_READ_DEV__sof__no_pend 0
-#define R_USB_IRQ_READ_DEV__sof__pend 1
-#define R_USB_IRQ_READ_DEV__port_status__BITNR 1
-#define R_USB_IRQ_READ_DEV__port_status__WIDTH 1
-#define R_USB_IRQ_READ_DEV__port_status__no_pend 0
-#define R_USB_IRQ_READ_DEV__port_status__pend 1
-#define R_USB_IRQ_READ_DEV__ctl_status__BITNR 0
-#define R_USB_IRQ_READ_DEV__ctl_status__WIDTH 1
-#define R_USB_IRQ_READ_DEV__ctl_status__no_pend 0
-#define R_USB_IRQ_READ_DEV__ctl_status__pend 1
-
-#define R_USB_FM_NUMBER (IO_TYPECAST_UDWORD 0xb000020c)
-#define R_USB_FM_NUMBER__value__BITNR 0
-#define R_USB_FM_NUMBER__value__WIDTH 32
-
-#define R_USB_FM_INTERVAL (IO_TYPECAST_UWORD 0xb0000210)
-#define R_USB_FM_INTERVAL__fixed__BITNR 6
-#define R_USB_FM_INTERVAL__fixed__WIDTH 8
-#define R_USB_FM_INTERVAL__adj__BITNR 0
-#define R_USB_FM_INTERVAL__adj__WIDTH 6
-
-#define R_USB_FM_REMAINING (IO_TYPECAST_RO_UWORD 0xb0000212)
-#define R_USB_FM_REMAINING__value__BITNR 0
-#define R_USB_FM_REMAINING__value__WIDTH 14
-
-#define R_USB_FM_PSTART (IO_TYPECAST_UWORD 0xb0000214)
-#define R_USB_FM_PSTART__value__BITNR 0
-#define R_USB_FM_PSTART__value__WIDTH 14
-
-#define R_USB_RH_STATUS (IO_TYPECAST_RO_BYTE 0xb0000203)
-#define R_USB_RH_STATUS__babble2__BITNR 7
-#define R_USB_RH_STATUS__babble2__WIDTH 1
-#define R_USB_RH_STATUS__babble2__no 0
-#define R_USB_RH_STATUS__babble2__yes 1
-#define R_USB_RH_STATUS__babble1__BITNR 6
-#define R_USB_RH_STATUS__babble1__WIDTH 1
-#define R_USB_RH_STATUS__babble1__no 0
-#define R_USB_RH_STATUS__babble1__yes 1
-#define R_USB_RH_STATUS__bus1__BITNR 4
-#define R_USB_RH_STATUS__bus1__WIDTH 2
-#define R_USB_RH_STATUS__bus1__SE0 0
-#define R_USB_RH_STATUS__bus1__Diff0 1
-#define R_USB_RH_STATUS__bus1__Diff1 2
-#define R_USB_RH_STATUS__bus1__SE1 3
-#define R_USB_RH_STATUS__bus2__BITNR 2
-#define R_USB_RH_STATUS__bus2__WIDTH 2
-#define R_USB_RH_STATUS__bus2__SE0 0
-#define R_USB_RH_STATUS__bus2__Diff0 1
-#define R_USB_RH_STATUS__bus2__Diff1 2
-#define R_USB_RH_STATUS__bus2__SE1 3
-#define R_USB_RH_STATUS__nports__BITNR 0
-#define R_USB_RH_STATUS__nports__WIDTH 2
-
-#define R_USB_RH_PORT_STATUS_1 (IO_TYPECAST_RO_UWORD 0xb0000218)
-#define R_USB_RH_PORT_STATUS_1__speed__BITNR 9
-#define R_USB_RH_PORT_STATUS_1__speed__WIDTH 1
-#define R_USB_RH_PORT_STATUS_1__speed__full 0
-#define R_USB_RH_PORT_STATUS_1__speed__low 1
-#define R_USB_RH_PORT_STATUS_1__power__BITNR 8
-#define R_USB_RH_PORT_STATUS_1__power__WIDTH 1
-#define R_USB_RH_PORT_STATUS_1__reset__BITNR 4
-#define R_USB_RH_PORT_STATUS_1__reset__WIDTH 1
-#define R_USB_RH_PORT_STATUS_1__reset__no 0
-#define R_USB_RH_PORT_STATUS_1__reset__yes 1
-#define R_USB_RH_PORT_STATUS_1__overcurrent__BITNR 3
-#define R_USB_RH_PORT_STATUS_1__overcurrent__WIDTH 1
-#define R_USB_RH_PORT_STATUS_1__overcurrent__no 0
-#define R_USB_RH_PORT_STATUS_1__overcurrent__yes 1
-#define R_USB_RH_PORT_STATUS_1__suspended__BITNR 2
-#define R_USB_RH_PORT_STATUS_1__suspended__WIDTH 1
-#define R_USB_RH_PORT_STATUS_1__suspended__no 0
-#define R_USB_RH_PORT_STATUS_1__suspended__yes 1
-#define R_USB_RH_PORT_STATUS_1__enabled__BITNR 1
-#define R_USB_RH_PORT_STATUS_1__enabled__WIDTH 1
-#define R_USB_RH_PORT_STATUS_1__enabled__no 0
-#define R_USB_RH_PORT_STATUS_1__enabled__yes 1
-#define R_USB_RH_PORT_STATUS_1__connected__BITNR 0
-#define R_USB_RH_PORT_STATUS_1__connected__WIDTH 1
-#define R_USB_RH_PORT_STATUS_1__connected__no 0
-#define R_USB_RH_PORT_STATUS_1__connected__yes 1
-
-#define R_USB_RH_PORT_STATUS_2 (IO_TYPECAST_RO_UWORD 0xb000021a)
-#define R_USB_RH_PORT_STATUS_2__speed__BITNR 9
-#define R_USB_RH_PORT_STATUS_2__speed__WIDTH 1
-#define R_USB_RH_PORT_STATUS_2__speed__full 0
-#define R_USB_RH_PORT_STATUS_2__speed__low 1
-#define R_USB_RH_PORT_STATUS_2__power__BITNR 8
-#define R_USB_RH_PORT_STATUS_2__power__WIDTH 1
-#define R_USB_RH_PORT_STATUS_2__reset__BITNR 4
-#define R_USB_RH_PORT_STATUS_2__reset__WIDTH 1
-#define R_USB_RH_PORT_STATUS_2__reset__no 0
-#define R_USB_RH_PORT_STATUS_2__reset__yes 1
-#define R_USB_RH_PORT_STATUS_2__overcurrent__BITNR 3
-#define R_USB_RH_PORT_STATUS_2__overcurrent__WIDTH 1
-#define R_USB_RH_PORT_STATUS_2__overcurrent__no 0
-#define R_USB_RH_PORT_STATUS_2__overcurrent__yes 1
-#define R_USB_RH_PORT_STATUS_2__suspended__BITNR 2
-#define R_USB_RH_PORT_STATUS_2__suspended__WIDTH 1
-#define R_USB_RH_PORT_STATUS_2__suspended__no 0
-#define R_USB_RH_PORT_STATUS_2__suspended__yes 1
-#define R_USB_RH_PORT_STATUS_2__enabled__BITNR 1
-#define R_USB_RH_PORT_STATUS_2__enabled__WIDTH 1
-#define R_USB_RH_PORT_STATUS_2__enabled__no 0
-#define R_USB_RH_PORT_STATUS_2__enabled__yes 1
-#define R_USB_RH_PORT_STATUS_2__connected__BITNR 0
-#define R_USB_RH_PORT_STATUS_2__connected__WIDTH 1
-#define R_USB_RH_PORT_STATUS_2__connected__no 0
-#define R_USB_RH_PORT_STATUS_2__connected__yes 1
-
-#define R_USB_EPT_INDEX (IO_TYPECAST_BYTE 0xb0000208)
-#define R_USB_EPT_INDEX__value__BITNR 0
-#define R_USB_EPT_INDEX__value__WIDTH 5
-
-#define R_USB_EPT_DATA (IO_TYPECAST_UDWORD 0xb000021c)
-#define R_USB_EPT_DATA__valid__BITNR 31
-#define R_USB_EPT_DATA__valid__WIDTH 1
-#define R_USB_EPT_DATA__valid__no 0
-#define R_USB_EPT_DATA__valid__yes 1
-#define R_USB_EPT_DATA__hold__BITNR 30
-#define R_USB_EPT_DATA__hold__WIDTH 1
-#define R_USB_EPT_DATA__hold__no 0
-#define R_USB_EPT_DATA__hold__yes 1
-#define R_USB_EPT_DATA__error_count_in__BITNR 28
-#define R_USB_EPT_DATA__error_count_in__WIDTH 2
-#define R_USB_EPT_DATA__t_in__BITNR 27
-#define R_USB_EPT_DATA__t_in__WIDTH 1
-#define R_USB_EPT_DATA__low_speed__BITNR 26
-#define R_USB_EPT_DATA__low_speed__WIDTH 1
-#define R_USB_EPT_DATA__low_speed__no 0
-#define R_USB_EPT_DATA__low_speed__yes 1
-#define R_USB_EPT_DATA__port__BITNR 24
-#define R_USB_EPT_DATA__port__WIDTH 2
-#define R_USB_EPT_DATA__port__any 0
-#define R_USB_EPT_DATA__port__p1 1
-#define R_USB_EPT_DATA__port__p2 2
-#define R_USB_EPT_DATA__port__undef 3
-#define R_USB_EPT_DATA__error_code__BITNR 22
-#define R_USB_EPT_DATA__error_code__WIDTH 2
-#define R_USB_EPT_DATA__error_code__no_error 0
-#define R_USB_EPT_DATA__error_code__stall 1
-#define R_USB_EPT_DATA__error_code__bus_error 2
-#define R_USB_EPT_DATA__error_code__buffer_error 3
-#define R_USB_EPT_DATA__t_out__BITNR 21
-#define R_USB_EPT_DATA__t_out__WIDTH 1
-#define R_USB_EPT_DATA__error_count_out__BITNR 19
-#define R_USB_EPT_DATA__error_count_out__WIDTH 2
-#define R_USB_EPT_DATA__max_len__BITNR 11
-#define R_USB_EPT_DATA__max_len__WIDTH 7
-#define R_USB_EPT_DATA__ep__BITNR 7
-#define R_USB_EPT_DATA__ep__WIDTH 4
-#define R_USB_EPT_DATA__dev__BITNR 0
-#define R_USB_EPT_DATA__dev__WIDTH 7
-
-#define R_USB_EPT_DATA_ISO (IO_TYPECAST_UDWORD 0xb000021c)
-#define R_USB_EPT_DATA_ISO__valid__BITNR 31
-#define R_USB_EPT_DATA_ISO__valid__WIDTH 1
-#define R_USB_EPT_DATA_ISO__valid__no 0
-#define R_USB_EPT_DATA_ISO__valid__yes 1
-#define R_USB_EPT_DATA_ISO__port__BITNR 24
-#define R_USB_EPT_DATA_ISO__port__WIDTH 2
-#define R_USB_EPT_DATA_ISO__port__any 0
-#define R_USB_EPT_DATA_ISO__port__p1 1
-#define R_USB_EPT_DATA_ISO__port__p2 2
-#define R_USB_EPT_DATA_ISO__port__undef 3
-#define R_USB_EPT_DATA_ISO__error_code__BITNR 22
-#define R_USB_EPT_DATA_ISO__error_code__WIDTH 2
-#define R_USB_EPT_DATA_ISO__error_code__no_error 0
-#define R_USB_EPT_DATA_ISO__error_code__stall 1
-#define R_USB_EPT_DATA_ISO__error_code__bus_error 2
-#define R_USB_EPT_DATA_ISO__error_code__TBD3 3
-#define R_USB_EPT_DATA_ISO__max_len__BITNR 11
-#define R_USB_EPT_DATA_ISO__max_len__WIDTH 10
-#define R_USB_EPT_DATA_ISO__ep__BITNR 7
-#define R_USB_EPT_DATA_ISO__ep__WIDTH 4
-#define R_USB_EPT_DATA_ISO__dev__BITNR 0
-#define R_USB_EPT_DATA_ISO__dev__WIDTH 7
-
-#define R_USB_EPT_DATA_DEV (IO_TYPECAST_UDWORD 0xb000021c)
-#define R_USB_EPT_DATA_DEV__valid__BITNR 31
-#define R_USB_EPT_DATA_DEV__valid__WIDTH 1
-#define R_USB_EPT_DATA_DEV__valid__no 0
-#define R_USB_EPT_DATA_DEV__valid__yes 1
-#define R_USB_EPT_DATA_DEV__hold__BITNR 30
-#define R_USB_EPT_DATA_DEV__hold__WIDTH 1
-#define R_USB_EPT_DATA_DEV__hold__no 0
-#define R_USB_EPT_DATA_DEV__hold__yes 1
-#define R_USB_EPT_DATA_DEV__stall__BITNR 29
-#define R_USB_EPT_DATA_DEV__stall__WIDTH 1
-#define R_USB_EPT_DATA_DEV__stall__no 0
-#define R_USB_EPT_DATA_DEV__stall__yes 1
-#define R_USB_EPT_DATA_DEV__iso_resp__BITNR 28
-#define R_USB_EPT_DATA_DEV__iso_resp__WIDTH 1
-#define R_USB_EPT_DATA_DEV__iso_resp__quiet 0
-#define R_USB_EPT_DATA_DEV__iso_resp__yes 1
-#define R_USB_EPT_DATA_DEV__ctrl__BITNR 27
-#define R_USB_EPT_DATA_DEV__ctrl__WIDTH 1
-#define R_USB_EPT_DATA_DEV__ctrl__no 0
-#define R_USB_EPT_DATA_DEV__ctrl__yes 1
-#define R_USB_EPT_DATA_DEV__iso__BITNR 26
-#define R_USB_EPT_DATA_DEV__iso__WIDTH 1
-#define R_USB_EPT_DATA_DEV__iso__no 0
-#define R_USB_EPT_DATA_DEV__iso__yes 1
-#define R_USB_EPT_DATA_DEV__port__BITNR 24
-#define R_USB_EPT_DATA_DEV__port__WIDTH 2
-#define R_USB_EPT_DATA_DEV__control_phase__BITNR 22
-#define R_USB_EPT_DATA_DEV__control_phase__WIDTH 1
-#define R_USB_EPT_DATA_DEV__t__BITNR 21
-#define R_USB_EPT_DATA_DEV__t__WIDTH 1
-#define R_USB_EPT_DATA_DEV__max_len__BITNR 11
-#define R_USB_EPT_DATA_DEV__max_len__WIDTH 10
-#define R_USB_EPT_DATA_DEV__ep__BITNR 7
-#define R_USB_EPT_DATA_DEV__ep__WIDTH 4
-#define R_USB_EPT_DATA_DEV__dev__BITNR 0
-#define R_USB_EPT_DATA_DEV__dev__WIDTH 7
-
-#define R_USB_SNMP_TERROR (IO_TYPECAST_UDWORD 0xb0000220)
-#define R_USB_SNMP_TERROR__value__BITNR 0
-#define R_USB_SNMP_TERROR__value__WIDTH 32
-
-#define R_USB_EPID_ATTN (IO_TYPECAST_RO_UDWORD 0xb0000224)
-#define R_USB_EPID_ATTN__value__BITNR 0
-#define R_USB_EPID_ATTN__value__WIDTH 32
-
-#define R_USB_PORT1_DISABLE (IO_TYPECAST_BYTE 0xb000006a)
-#define R_USB_PORT1_DISABLE__disable__BITNR 0
-#define R_USB_PORT1_DISABLE__disable__WIDTH 1
-#define R_USB_PORT1_DISABLE__disable__yes 0
-#define R_USB_PORT1_DISABLE__disable__no 1
-
-#define R_USB_PORT2_DISABLE (IO_TYPECAST_BYTE 0xb0000052)
-#define R_USB_PORT2_DISABLE__disable__BITNR 0
-#define R_USB_PORT2_DISABLE__disable__WIDTH 1
-#define R_USB_PORT2_DISABLE__disable__yes 0
-#define R_USB_PORT2_DISABLE__disable__no 1
-
-/*
-!* MMU registers
-!*/
-
-#define R_MMU_CONFIG (IO_TYPECAST_UDWORD 0xb0000240)
-#define R_MMU_CONFIG__mmu_enable__BITNR 31
-#define R_MMU_CONFIG__mmu_enable__WIDTH 1
-#define R_MMU_CONFIG__mmu_enable__enable 1
-#define R_MMU_CONFIG__mmu_enable__disable 0
-#define R_MMU_CONFIG__inv_excp__BITNR 18
-#define R_MMU_CONFIG__inv_excp__WIDTH 1
-#define R_MMU_CONFIG__inv_excp__enable 1
-#define R_MMU_CONFIG__inv_excp__disable 0
-#define R_MMU_CONFIG__acc_excp__BITNR 17
-#define R_MMU_CONFIG__acc_excp__WIDTH 1
-#define R_MMU_CONFIG__acc_excp__enable 1
-#define R_MMU_CONFIG__acc_excp__disable 0
-#define R_MMU_CONFIG__we_excp__BITNR 16
-#define R_MMU_CONFIG__we_excp__WIDTH 1
-#define R_MMU_CONFIG__we_excp__enable 1
-#define R_MMU_CONFIG__we_excp__disable 0
-#define R_MMU_CONFIG__seg_f__BITNR 15
-#define R_MMU_CONFIG__seg_f__WIDTH 1
-#define R_MMU_CONFIG__seg_f__seg 1
-#define R_MMU_CONFIG__seg_f__page 0
-#define R_MMU_CONFIG__seg_e__BITNR 14
-#define R_MMU_CONFIG__seg_e__WIDTH 1
-#define R_MMU_CONFIG__seg_e__seg 1
-#define R_MMU_CONFIG__seg_e__page 0
-#define R_MMU_CONFIG__seg_d__BITNR 13
-#define R_MMU_CONFIG__seg_d__WIDTH 1
-#define R_MMU_CONFIG__seg_d__seg 1
-#define R_MMU_CONFIG__seg_d__page 0
-#define R_MMU_CONFIG__seg_c__BITNR 12
-#define R_MMU_CONFIG__seg_c__WIDTH 1
-#define R_MMU_CONFIG__seg_c__seg 1
-#define R_MMU_CONFIG__seg_c__page 0
-#define R_MMU_CONFIG__seg_b__BITNR 11
-#define R_MMU_CONFIG__seg_b__WIDTH 1
-#define R_MMU_CONFIG__seg_b__seg 1
-#define R_MMU_CONFIG__seg_b__page 0
-#define R_MMU_CONFIG__seg_a__BITNR 10
-#define R_MMU_CONFIG__seg_a__WIDTH 1
-#define R_MMU_CONFIG__seg_a__seg 1
-#define R_MMU_CONFIG__seg_a__page 0
-#define R_MMU_CONFIG__seg_9__BITNR 9
-#define R_MMU_CONFIG__seg_9__WIDTH 1
-#define R_MMU_CONFIG__seg_9__seg 1
-#define R_MMU_CONFIG__seg_9__page 0
-#define R_MMU_CONFIG__seg_8__BITNR 8
-#define R_MMU_CONFIG__seg_8__WIDTH 1
-#define R_MMU_CONFIG__seg_8__seg 1
-#define R_MMU_CONFIG__seg_8__page 0
-#define R_MMU_CONFIG__seg_7__BITNR 7
-#define R_MMU_CONFIG__seg_7__WIDTH 1
-#define R_MMU_CONFIG__seg_7__seg 1
-#define R_MMU_CONFIG__seg_7__page 0
-#define R_MMU_CONFIG__seg_6__BITNR 6
-#define R_MMU_CONFIG__seg_6__WIDTH 1
-#define R_MMU_CONFIG__seg_6__seg 1
-#define R_MMU_CONFIG__seg_6__page 0
-#define R_MMU_CONFIG__seg_5__BITNR 5
-#define R_MMU_CONFIG__seg_5__WIDTH 1
-#define R_MMU_CONFIG__seg_5__seg 1
-#define R_MMU_CONFIG__seg_5__page 0
-#define R_MMU_CONFIG__seg_4__BITNR 4
-#define R_MMU_CONFIG__seg_4__WIDTH 1
-#define R_MMU_CONFIG__seg_4__seg 1
-#define R_MMU_CONFIG__seg_4__page 0
-#define R_MMU_CONFIG__seg_3__BITNR 3
-#define R_MMU_CONFIG__seg_3__WIDTH 1
-#define R_MMU_CONFIG__seg_3__seg 1
-#define R_MMU_CONFIG__seg_3__page 0
-#define R_MMU_CONFIG__seg_2__BITNR 2
-#define R_MMU_CONFIG__seg_2__WIDTH 1
-#define R_MMU_CONFIG__seg_2__seg 1
-#define R_MMU_CONFIG__seg_2__page 0
-#define R_MMU_CONFIG__seg_1__BITNR 1
-#define R_MMU_CONFIG__seg_1__WIDTH 1
-#define R_MMU_CONFIG__seg_1__seg 1
-#define R_MMU_CONFIG__seg_1__page 0
-#define R_MMU_CONFIG__seg_0__BITNR 0
-#define R_MMU_CONFIG__seg_0__WIDTH 1
-#define R_MMU_CONFIG__seg_0__seg 1
-#define R_MMU_CONFIG__seg_0__page 0
-
-#define R_MMU_KSEG (IO_TYPECAST_UWORD 0xb0000240)
-#define R_MMU_KSEG__seg_f__BITNR 15
-#define R_MMU_KSEG__seg_f__WIDTH 1
-#define R_MMU_KSEG__seg_f__seg 1
-#define R_MMU_KSEG__seg_f__page 0
-#define R_MMU_KSEG__seg_e__BITNR 14
-#define R_MMU_KSEG__seg_e__WIDTH 1
-#define R_MMU_KSEG__seg_e__seg 1
-#define R_MMU_KSEG__seg_e__page 0
-#define R_MMU_KSEG__seg_d__BITNR 13
-#define R_MMU_KSEG__seg_d__WIDTH 1
-#define R_MMU_KSEG__seg_d__seg 1
-#define R_MMU_KSEG__seg_d__page 0
-#define R_MMU_KSEG__seg_c__BITNR 12
-#define R_MMU_KSEG__seg_c__WIDTH 1
-#define R_MMU_KSEG__seg_c__seg 1
-#define R_MMU_KSEG__seg_c__page 0
-#define R_MMU_KSEG__seg_b__BITNR 11
-#define R_MMU_KSEG__seg_b__WIDTH 1
-#define R_MMU_KSEG__seg_b__seg 1
-#define R_MMU_KSEG__seg_b__page 0
-#define R_MMU_KSEG__seg_a__BITNR 10
-#define R_MMU_KSEG__seg_a__WIDTH 1
-#define R_MMU_KSEG__seg_a__seg 1
-#define R_MMU_KSEG__seg_a__page 0
-#define R_MMU_KSEG__seg_9__BITNR 9
-#define R_MMU_KSEG__seg_9__WIDTH 1
-#define R_MMU_KSEG__seg_9__seg 1
-#define R_MMU_KSEG__seg_9__page 0
-#define R_MMU_KSEG__seg_8__BITNR 8
-#define R_MMU_KSEG__seg_8__WIDTH 1
-#define R_MMU_KSEG__seg_8__seg 1
-#define R_MMU_KSEG__seg_8__page 0
-#define R_MMU_KSEG__seg_7__BITNR 7
-#define R_MMU_KSEG__seg_7__WIDTH 1
-#define R_MMU_KSEG__seg_7__seg 1
-#define R_MMU_KSEG__seg_7__page 0
-#define R_MMU_KSEG__seg_6__BITNR 6
-#define R_MMU_KSEG__seg_6__WIDTH 1
-#define R_MMU_KSEG__seg_6__seg 1
-#define R_MMU_KSEG__seg_6__page 0
-#define R_MMU_KSEG__seg_5__BITNR 5
-#define R_MMU_KSEG__seg_5__WIDTH 1
-#define R_MMU_KSEG__seg_5__seg 1
-#define R_MMU_KSEG__seg_5__page 0
-#define R_MMU_KSEG__seg_4__BITNR 4
-#define R_MMU_KSEG__seg_4__WIDTH 1
-#define R_MMU_KSEG__seg_4__seg 1
-#define R_MMU_KSEG__seg_4__page 0
-#define R_MMU_KSEG__seg_3__BITNR 3
-#define R_MMU_KSEG__seg_3__WIDTH 1
-#define R_MMU_KSEG__seg_3__seg 1
-#define R_MMU_KSEG__seg_3__page 0
-#define R_MMU_KSEG__seg_2__BITNR 2
-#define R_MMU_KSEG__seg_2__WIDTH 1
-#define R_MMU_KSEG__seg_2__seg 1
-#define R_MMU_KSEG__seg_2__page 0
-#define R_MMU_KSEG__seg_1__BITNR 1
-#define R_MMU_KSEG__seg_1__WIDTH 1
-#define R_MMU_KSEG__seg_1__seg 1
-#define R_MMU_KSEG__seg_1__page 0
-#define R_MMU_KSEG__seg_0__BITNR 0
-#define R_MMU_KSEG__seg_0__WIDTH 1
-#define R_MMU_KSEG__seg_0__seg 1
-#define R_MMU_KSEG__seg_0__page 0
-
-#define R_MMU_CTRL (IO_TYPECAST_BYTE 0xb0000242)
-#define R_MMU_CTRL__inv_excp__BITNR 2
-#define R_MMU_CTRL__inv_excp__WIDTH 1
-#define R_MMU_CTRL__inv_excp__enable 1
-#define R_MMU_CTRL__inv_excp__disable 0
-#define R_MMU_CTRL__acc_excp__BITNR 1
-#define R_MMU_CTRL__acc_excp__WIDTH 1
-#define R_MMU_CTRL__acc_excp__enable 1
-#define R_MMU_CTRL__acc_excp__disable 0
-#define R_MMU_CTRL__we_excp__BITNR 0
-#define R_MMU_CTRL__we_excp__WIDTH 1
-#define R_MMU_CTRL__we_excp__enable 1
-#define R_MMU_CTRL__we_excp__disable 0
-
-#define R_MMU_ENABLE (IO_TYPECAST_BYTE 0xb0000243)
-#define R_MMU_ENABLE__mmu_enable__BITNR 7
-#define R_MMU_ENABLE__mmu_enable__WIDTH 1
-#define R_MMU_ENABLE__mmu_enable__enable 1
-#define R_MMU_ENABLE__mmu_enable__disable 0
-
-#define R_MMU_KBASE_LO (IO_TYPECAST_UDWORD 0xb0000244)
-#define R_MMU_KBASE_LO__base_7__BITNR 28
-#define R_MMU_KBASE_LO__base_7__WIDTH 4
-#define R_MMU_KBASE_LO__base_6__BITNR 24
-#define R_MMU_KBASE_LO__base_6__WIDTH 4
-#define R_MMU_KBASE_LO__base_5__BITNR 20
-#define R_MMU_KBASE_LO__base_5__WIDTH 4
-#define R_MMU_KBASE_LO__base_4__BITNR 16
-#define R_MMU_KBASE_LO__base_4__WIDTH 4
-#define R_MMU_KBASE_LO__base_3__BITNR 12
-#define R_MMU_KBASE_LO__base_3__WIDTH 4
-#define R_MMU_KBASE_LO__base_2__BITNR 8
-#define R_MMU_KBASE_LO__base_2__WIDTH 4
-#define R_MMU_KBASE_LO__base_1__BITNR 4
-#define R_MMU_KBASE_LO__base_1__WIDTH 4
-#define R_MMU_KBASE_LO__base_0__BITNR 0
-#define R_MMU_KBASE_LO__base_0__WIDTH 4
-
-#define R_MMU_KBASE_HI (IO_TYPECAST_UDWORD 0xb0000248)
-#define R_MMU_KBASE_HI__base_f__BITNR 28
-#define R_MMU_KBASE_HI__base_f__WIDTH 4
-#define R_MMU_KBASE_HI__base_e__BITNR 24
-#define R_MMU_KBASE_HI__base_e__WIDTH 4
-#define R_MMU_KBASE_HI__base_d__BITNR 20
-#define R_MMU_KBASE_HI__base_d__WIDTH 4
-#define R_MMU_KBASE_HI__base_c__BITNR 16
-#define R_MMU_KBASE_HI__base_c__WIDTH 4
-#define R_MMU_KBASE_HI__base_b__BITNR 12
-#define R_MMU_KBASE_HI__base_b__WIDTH 4
-#define R_MMU_KBASE_HI__base_a__BITNR 8
-#define R_MMU_KBASE_HI__base_a__WIDTH 4
-#define R_MMU_KBASE_HI__base_9__BITNR 4
-#define R_MMU_KBASE_HI__base_9__WIDTH 4
-#define R_MMU_KBASE_HI__base_8__BITNR 0
-#define R_MMU_KBASE_HI__base_8__WIDTH 4
-
-#define R_MMU_CONTEXT (IO_TYPECAST_BYTE 0xb000024c)
-#define R_MMU_CONTEXT__page_id__BITNR 0
-#define R_MMU_CONTEXT__page_id__WIDTH 6
-
-#define R_MMU_CAUSE (IO_TYPECAST_RO_UDWORD 0xb0000250)
-#define R_MMU_CAUSE__vpn__BITNR 13
-#define R_MMU_CAUSE__vpn__WIDTH 19
-#define R_MMU_CAUSE__miss_excp__BITNR 12
-#define R_MMU_CAUSE__miss_excp__WIDTH 1
-#define R_MMU_CAUSE__miss_excp__yes 1
-#define R_MMU_CAUSE__miss_excp__no 0
-#define R_MMU_CAUSE__inv_excp__BITNR 11
-#define R_MMU_CAUSE__inv_excp__WIDTH 1
-#define R_MMU_CAUSE__inv_excp__yes 1
-#define R_MMU_CAUSE__inv_excp__no 0
-#define R_MMU_CAUSE__acc_excp__BITNR 10
-#define R_MMU_CAUSE__acc_excp__WIDTH 1
-#define R_MMU_CAUSE__acc_excp__yes 1
-#define R_MMU_CAUSE__acc_excp__no 0
-#define R_MMU_CAUSE__we_excp__BITNR 9
-#define R_MMU_CAUSE__we_excp__WIDTH 1
-#define R_MMU_CAUSE__we_excp__yes 1
-#define R_MMU_CAUSE__we_excp__no 0
-#define R_MMU_CAUSE__wr_rd__BITNR 8
-#define R_MMU_CAUSE__wr_rd__WIDTH 1
-#define R_MMU_CAUSE__wr_rd__write 1
-#define R_MMU_CAUSE__wr_rd__read 0
-#define R_MMU_CAUSE__page_id__BITNR 0
-#define R_MMU_CAUSE__page_id__WIDTH 6
-
-#define R_TLB_SELECT (IO_TYPECAST_BYTE 0xb0000254)
-#define R_TLB_SELECT__index__BITNR 0
-#define R_TLB_SELECT__index__WIDTH 6
-
-#define R_TLB_LO (IO_TYPECAST_UDWORD 0xb0000258)
-#define R_TLB_LO__pfn__BITNR 13
-#define R_TLB_LO__pfn__WIDTH 19
-#define R_TLB_LO__global__BITNR 3
-#define R_TLB_LO__global__WIDTH 1
-#define R_TLB_LO__global__yes 1
-#define R_TLB_LO__global__no 0
-#define R_TLB_LO__valid__BITNR 2
-#define R_TLB_LO__valid__WIDTH 1
-#define R_TLB_LO__valid__yes 1
-#define R_TLB_LO__valid__no 0
-#define R_TLB_LO__kernel__BITNR 1
-#define R_TLB_LO__kernel__WIDTH 1
-#define R_TLB_LO__kernel__yes 1
-#define R_TLB_LO__kernel__no 0
-#define R_TLB_LO__we__BITNR 0
-#define R_TLB_LO__we__WIDTH 1
-#define R_TLB_LO__we__yes 1
-#define R_TLB_LO__we__no 0
-
-#define R_TLB_HI (IO_TYPECAST_UDWORD 0xb000025c)
-#define R_TLB_HI__vpn__BITNR 13
-#define R_TLB_HI__vpn__WIDTH 19
-#define R_TLB_HI__page_id__BITNR 0
-#define R_TLB_HI__page_id__WIDTH 6
-
-/*
-!* Syncrounous serial port registers
-!*/
-
-#define R_SYNC_SERIAL1_REC_DATA (IO_TYPECAST_RO_UDWORD 0xb000006c)
-#define R_SYNC_SERIAL1_REC_DATA__data_in__BITNR 0
-#define R_SYNC_SERIAL1_REC_DATA__data_in__WIDTH 32
-
-#define R_SYNC_SERIAL1_REC_WORD (IO_TYPECAST_RO_UWORD 0xb000006c)
-#define R_SYNC_SERIAL1_REC_WORD__data_in__BITNR 0
-#define R_SYNC_SERIAL1_REC_WORD__data_in__WIDTH 16
-
-#define R_SYNC_SERIAL1_REC_BYTE (IO_TYPECAST_RO_BYTE 0xb000006c)
-#define R_SYNC_SERIAL1_REC_BYTE__data_in__BITNR 0
-#define R_SYNC_SERIAL1_REC_BYTE__data_in__WIDTH 8
-
-#define R_SYNC_SERIAL1_STATUS (IO_TYPECAST_RO_UDWORD 0xb0000068)
-#define R_SYNC_SERIAL1_STATUS__rec_status__BITNR 15
-#define R_SYNC_SERIAL1_STATUS__rec_status__WIDTH 1
-#define R_SYNC_SERIAL1_STATUS__rec_status__running 0
-#define R_SYNC_SERIAL1_STATUS__rec_status__idle 1
-#define R_SYNC_SERIAL1_STATUS__tr_empty__BITNR 14
-#define R_SYNC_SERIAL1_STATUS__tr_empty__WIDTH 1
-#define R_SYNC_SERIAL1_STATUS__tr_empty__empty 1
-#define R_SYNC_SERIAL1_STATUS__tr_empty__not_empty 0
-#define R_SYNC_SERIAL1_STATUS__tr_ready__BITNR 13
-#define R_SYNC_SERIAL1_STATUS__tr_ready__WIDTH 1
-#define R_SYNC_SERIAL1_STATUS__tr_ready__full 0
-#define R_SYNC_SERIAL1_STATUS__tr_ready__ready 1
-#define R_SYNC_SERIAL1_STATUS__pin_1__BITNR 12
-#define R_SYNC_SERIAL1_STATUS__pin_1__WIDTH 1
-#define R_SYNC_SERIAL1_STATUS__pin_1__low 0
-#define R_SYNC_SERIAL1_STATUS__pin_1__high 1
-#define R_SYNC_SERIAL1_STATUS__pin_0__BITNR 11
-#define R_SYNC_SERIAL1_STATUS__pin_0__WIDTH 1
-#define R_SYNC_SERIAL1_STATUS__pin_0__low 0
-#define R_SYNC_SERIAL1_STATUS__pin_0__high 1
-#define R_SYNC_SERIAL1_STATUS__underflow__BITNR 10
-#define R_SYNC_SERIAL1_STATUS__underflow__WIDTH 1
-#define R_SYNC_SERIAL1_STATUS__underflow__no 0
-#define R_SYNC_SERIAL1_STATUS__underflow__yes 1
-#define R_SYNC_SERIAL1_STATUS__overrun__BITNR 9
-#define R_SYNC_SERIAL1_STATUS__overrun__WIDTH 1
-#define R_SYNC_SERIAL1_STATUS__overrun__no 0
-#define R_SYNC_SERIAL1_STATUS__overrun__yes 1
-#define R_SYNC_SERIAL1_STATUS__data_avail__BITNR 8
-#define R_SYNC_SERIAL1_STATUS__data_avail__WIDTH 1
-#define R_SYNC_SERIAL1_STATUS__data_avail__no 0
-#define R_SYNC_SERIAL1_STATUS__data_avail__yes 1
-#define R_SYNC_SERIAL1_STATUS__data__BITNR 0
-#define R_SYNC_SERIAL1_STATUS__data__WIDTH 8
-
-#define R_SYNC_SERIAL1_TR_DATA (IO_TYPECAST_UDWORD 0xb000006c)
-#define R_SYNC_SERIAL1_TR_DATA__data_out__BITNR 0
-#define R_SYNC_SERIAL1_TR_DATA__data_out__WIDTH 32
-
-#define R_SYNC_SERIAL1_TR_WORD (IO_TYPECAST_UWORD 0xb000006c)
-#define R_SYNC_SERIAL1_TR_WORD__data_out__BITNR 0
-#define R_SYNC_SERIAL1_TR_WORD__data_out__WIDTH 16
-
-#define R_SYNC_SERIAL1_TR_BYTE (IO_TYPECAST_BYTE 0xb000006c)
-#define R_SYNC_SERIAL1_TR_BYTE__data_out__BITNR 0
-#define R_SYNC_SERIAL1_TR_BYTE__data_out__WIDTH 8
-
-#define R_SYNC_SERIAL1_CTRL (IO_TYPECAST_UDWORD 0xb0000068)
-#define R_SYNC_SERIAL1_CTRL__tr_baud__BITNR 28
-#define R_SYNC_SERIAL1_CTRL__tr_baud__WIDTH 4
-#define R_SYNC_SERIAL1_CTRL__tr_baud__c150Hz 0
-#define R_SYNC_SERIAL1_CTRL__tr_baud__c300Hz 1
-#define R_SYNC_SERIAL1_CTRL__tr_baud__c600Hz 2
-#define R_SYNC_SERIAL1_CTRL__tr_baud__c1200Hz 3
-#define R_SYNC_SERIAL1_CTRL__tr_baud__c2400Hz 4
-#define R_SYNC_SERIAL1_CTRL__tr_baud__c4800Hz 5
-#define R_SYNC_SERIAL1_CTRL__tr_baud__c9600Hz 6
-#define R_SYNC_SERIAL1_CTRL__tr_baud__c19k2Hz 7
-#define R_SYNC_SERIAL1_CTRL__tr_baud__c28k8Hz 8
-#define R_SYNC_SERIAL1_CTRL__tr_baud__c57k6Hz 9
-#define R_SYNC_SERIAL1_CTRL__tr_baud__c115k2Hz 10
-#define R_SYNC_SERIAL1_CTRL__tr_baud__c230k4Hz 11
-#define R_SYNC_SERIAL1_CTRL__tr_baud__c460k8Hz 12
-#define R_SYNC_SERIAL1_CTRL__tr_baud__c921k6Hz 13
-#define R_SYNC_SERIAL1_CTRL__tr_baud__c3125kHz 14
-#define R_SYNC_SERIAL1_CTRL__tr_baud__reserved 15
-#define R_SYNC_SERIAL1_CTRL__dma_enable__BITNR 27
-#define R_SYNC_SERIAL1_CTRL__dma_enable__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__dma_enable__on 1
-#define R_SYNC_SERIAL1_CTRL__dma_enable__off 0
-#define R_SYNC_SERIAL1_CTRL__mode__BITNR 24
-#define R_SYNC_SERIAL1_CTRL__mode__WIDTH 3
-#define R_SYNC_SERIAL1_CTRL__mode__master_output 0
-#define R_SYNC_SERIAL1_CTRL__mode__slave_output 1
-#define R_SYNC_SERIAL1_CTRL__mode__master_input 2
-#define R_SYNC_SERIAL1_CTRL__mode__slave_input 3
-#define R_SYNC_SERIAL1_CTRL__mode__master_bidir 4
-#define R_SYNC_SERIAL1_CTRL__mode__slave_bidir 5
-#define R_SYNC_SERIAL1_CTRL__error__BITNR 23
-#define R_SYNC_SERIAL1_CTRL__error__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__error__normal 0
-#define R_SYNC_SERIAL1_CTRL__error__ignore 1
-#define R_SYNC_SERIAL1_CTRL__rec_enable__BITNR 22
-#define R_SYNC_SERIAL1_CTRL__rec_enable__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__rec_enable__disable 0
-#define R_SYNC_SERIAL1_CTRL__rec_enable__enable 1
-#define R_SYNC_SERIAL1_CTRL__f_synctype__BITNR 21
-#define R_SYNC_SERIAL1_CTRL__f_synctype__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__f_synctype__normal 0
-#define R_SYNC_SERIAL1_CTRL__f_synctype__early 1
-#define R_SYNC_SERIAL1_CTRL__f_syncsize__BITNR 19
-#define R_SYNC_SERIAL1_CTRL__f_syncsize__WIDTH 2
-#define R_SYNC_SERIAL1_CTRL__f_syncsize__bit 0
-#define R_SYNC_SERIAL1_CTRL__f_syncsize__word 1
-#define R_SYNC_SERIAL1_CTRL__f_syncsize__extended 2
-#define R_SYNC_SERIAL1_CTRL__f_syncsize__reserved 3
-#define R_SYNC_SERIAL1_CTRL__f_sync__BITNR 18
-#define R_SYNC_SERIAL1_CTRL__f_sync__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__f_sync__on 0
-#define R_SYNC_SERIAL1_CTRL__f_sync__off 1
-#define R_SYNC_SERIAL1_CTRL__clk_mode__BITNR 17
-#define R_SYNC_SERIAL1_CTRL__clk_mode__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__clk_mode__normal 0
-#define R_SYNC_SERIAL1_CTRL__clk_mode__gated 1
-#define R_SYNC_SERIAL1_CTRL__clk_halt__BITNR 16
-#define R_SYNC_SERIAL1_CTRL__clk_halt__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__clk_halt__running 0
-#define R_SYNC_SERIAL1_CTRL__clk_halt__stopped 1
-#define R_SYNC_SERIAL1_CTRL__bitorder__BITNR 15
-#define R_SYNC_SERIAL1_CTRL__bitorder__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__bitorder__lsb 0
-#define R_SYNC_SERIAL1_CTRL__bitorder__msb 1
-#define R_SYNC_SERIAL1_CTRL__tr_enable__BITNR 14
-#define R_SYNC_SERIAL1_CTRL__tr_enable__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__tr_enable__disable 0
-#define R_SYNC_SERIAL1_CTRL__tr_enable__enable 1
-#define R_SYNC_SERIAL1_CTRL__wordsize__BITNR 11
-#define R_SYNC_SERIAL1_CTRL__wordsize__WIDTH 3
-#define R_SYNC_SERIAL1_CTRL__wordsize__size8bit 0
-#define R_SYNC_SERIAL1_CTRL__wordsize__size12bit 1
-#define R_SYNC_SERIAL1_CTRL__wordsize__size16bit 2
-#define R_SYNC_SERIAL1_CTRL__wordsize__size24bit 3
-#define R_SYNC_SERIAL1_CTRL__wordsize__size32bit 4
-#define R_SYNC_SERIAL1_CTRL__buf_empty__BITNR 10
-#define R_SYNC_SERIAL1_CTRL__buf_empty__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__buf_empty__lmt_8 0
-#define R_SYNC_SERIAL1_CTRL__buf_empty__lmt_0 1
-#define R_SYNC_SERIAL1_CTRL__buf_full__BITNR 9
-#define R_SYNC_SERIAL1_CTRL__buf_full__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__buf_full__lmt_32 0
-#define R_SYNC_SERIAL1_CTRL__buf_full__lmt_8 1
-#define R_SYNC_SERIAL1_CTRL__flow_ctrl__BITNR 8
-#define R_SYNC_SERIAL1_CTRL__flow_ctrl__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__flow_ctrl__disabled 0
-#define R_SYNC_SERIAL1_CTRL__flow_ctrl__enabled 1
-#define R_SYNC_SERIAL1_CTRL__clk_polarity__BITNR 6
-#define R_SYNC_SERIAL1_CTRL__clk_polarity__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__clk_polarity__pos 0
-#define R_SYNC_SERIAL1_CTRL__clk_polarity__neg 1
-#define R_SYNC_SERIAL1_CTRL__frame_polarity__BITNR 5
-#define R_SYNC_SERIAL1_CTRL__frame_polarity__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__frame_polarity__normal 0
-#define R_SYNC_SERIAL1_CTRL__frame_polarity__inverted 1
-#define R_SYNC_SERIAL1_CTRL__status_polarity__BITNR 4
-#define R_SYNC_SERIAL1_CTRL__status_polarity__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__status_polarity__normal 0
-#define R_SYNC_SERIAL1_CTRL__status_polarity__inverted 1
-#define R_SYNC_SERIAL1_CTRL__clk_driver__BITNR 3
-#define R_SYNC_SERIAL1_CTRL__clk_driver__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__clk_driver__normal 0
-#define R_SYNC_SERIAL1_CTRL__clk_driver__inverted 1
-#define R_SYNC_SERIAL1_CTRL__frame_driver__BITNR 2
-#define R_SYNC_SERIAL1_CTRL__frame_driver__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__frame_driver__normal 0
-#define R_SYNC_SERIAL1_CTRL__frame_driver__inverted 1
-#define R_SYNC_SERIAL1_CTRL__status_driver__BITNR 1
-#define R_SYNC_SERIAL1_CTRL__status_driver__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__status_driver__normal 0
-#define R_SYNC_SERIAL1_CTRL__status_driver__inverted 1
-#define R_SYNC_SERIAL1_CTRL__def_out0__BITNR 0
-#define R_SYNC_SERIAL1_CTRL__def_out0__WIDTH 1
-#define R_SYNC_SERIAL1_CTRL__def_out0__high 1
-#define R_SYNC_SERIAL1_CTRL__def_out0__low 0
-
-#define R_SYNC_SERIAL3_REC_DATA (IO_TYPECAST_RO_UDWORD 0xb000007c)
-#define R_SYNC_SERIAL3_REC_DATA__data_in__BITNR 0
-#define R_SYNC_SERIAL3_REC_DATA__data_in__WIDTH 32
-
-#define R_SYNC_SERIAL3_REC_WORD (IO_TYPECAST_RO_UWORD 0xb000007c)
-#define R_SYNC_SERIAL3_REC_WORD__data_in__BITNR 0
-#define R_SYNC_SERIAL3_REC_WORD__data_in__WIDTH 16
-
-#define R_SYNC_SERIAL3_REC_BYTE (IO_TYPECAST_RO_BYTE 0xb000007c)
-#define R_SYNC_SERIAL3_REC_BYTE__data_in__BITNR 0
-#define R_SYNC_SERIAL3_REC_BYTE__data_in__WIDTH 8
-
-#define R_SYNC_SERIAL3_STATUS (IO_TYPECAST_RO_UDWORD 0xb0000078)
-#define R_SYNC_SERIAL3_STATUS__rec_status__BITNR 15
-#define R_SYNC_SERIAL3_STATUS__rec_status__WIDTH 1
-#define R_SYNC_SERIAL3_STATUS__rec_status__running 0
-#define R_SYNC_SERIAL3_STATUS__rec_status__idle 1
-#define R_SYNC_SERIAL3_STATUS__tr_empty__BITNR 14
-#define R_SYNC_SERIAL3_STATUS__tr_empty__WIDTH 1
-#define R_SYNC_SERIAL3_STATUS__tr_empty__empty 1
-#define R_SYNC_SERIAL3_STATUS__tr_empty__not_empty 0
-#define R_SYNC_SERIAL3_STATUS__tr_ready__BITNR 13
-#define R_SYNC_SERIAL3_STATUS__tr_ready__WIDTH 1
-#define R_SYNC_SERIAL3_STATUS__tr_ready__full 0
-#define R_SYNC_SERIAL3_STATUS__tr_ready__ready 1
-#define R_SYNC_SERIAL3_STATUS__pin_1__BITNR 12
-#define R_SYNC_SERIAL3_STATUS__pin_1__WIDTH 1
-#define R_SYNC_SERIAL3_STATUS__pin_1__low 0
-#define R_SYNC_SERIAL3_STATUS__pin_1__high 1
-#define R_SYNC_SERIAL3_STATUS__pin_0__BITNR 11
-#define R_SYNC_SERIAL3_STATUS__pin_0__WIDTH 1
-#define R_SYNC_SERIAL3_STATUS__pin_0__low 0
-#define R_SYNC_SERIAL3_STATUS__pin_0__high 1
-#define R_SYNC_SERIAL3_STATUS__underflow__BITNR 10
-#define R_SYNC_SERIAL3_STATUS__underflow__WIDTH 1
-#define R_SYNC_SERIAL3_STATUS__underflow__no 0
-#define R_SYNC_SERIAL3_STATUS__underflow__yes 1
-#define R_SYNC_SERIAL3_STATUS__overrun__BITNR 9
-#define R_SYNC_SERIAL3_STATUS__overrun__WIDTH 1
-#define R_SYNC_SERIAL3_STATUS__overrun__no 0
-#define R_SYNC_SERIAL3_STATUS__overrun__yes 1
-#define R_SYNC_SERIAL3_STATUS__data_avail__BITNR 8
-#define R_SYNC_SERIAL3_STATUS__data_avail__WIDTH 1
-#define R_SYNC_SERIAL3_STATUS__data_avail__no 0
-#define R_SYNC_SERIAL3_STATUS__data_avail__yes 1
-#define R_SYNC_SERIAL3_STATUS__data__BITNR 0
-#define R_SYNC_SERIAL3_STATUS__data__WIDTH 8
-
-#define R_SYNC_SERIAL3_TR_DATA (IO_TYPECAST_UDWORD 0xb000007c)
-#define R_SYNC_SERIAL3_TR_DATA__data_out__BITNR 0
-#define R_SYNC_SERIAL3_TR_DATA__data_out__WIDTH 32
-
-#define R_SYNC_SERIAL3_TR_WORD (IO_TYPECAST_UWORD 0xb000007c)
-#define R_SYNC_SERIAL3_TR_WORD__data_out__BITNR 0
-#define R_SYNC_SERIAL3_TR_WORD__data_out__WIDTH 16
-
-#define R_SYNC_SERIAL3_TR_BYTE (IO_TYPECAST_BYTE 0xb000007c)
-#define R_SYNC_SERIAL3_TR_BYTE__data_out__BITNR 0
-#define R_SYNC_SERIAL3_TR_BYTE__data_out__WIDTH 8
-
-#define R_SYNC_SERIAL3_CTRL (IO_TYPECAST_UDWORD 0xb0000078)
-#define R_SYNC_SERIAL3_CTRL__tr_baud__BITNR 28
-#define R_SYNC_SERIAL3_CTRL__tr_baud__WIDTH 4
-#define R_SYNC_SERIAL3_CTRL__tr_baud__c150Hz 0
-#define R_SYNC_SERIAL3_CTRL__tr_baud__c300Hz 1
-#define R_SYNC_SERIAL3_CTRL__tr_baud__c600Hz 2
-#define R_SYNC_SERIAL3_CTRL__tr_baud__c1200Hz 3
-#define R_SYNC_SERIAL3_CTRL__tr_baud__c2400Hz 4
-#define R_SYNC_SERIAL3_CTRL__tr_baud__c4800Hz 5
-#define R_SYNC_SERIAL3_CTRL__tr_baud__c9600Hz 6
-#define R_SYNC_SERIAL3_CTRL__tr_baud__c19k2Hz 7
-#define R_SYNC_SERIAL3_CTRL__tr_baud__c28k8Hz 8
-#define R_SYNC_SERIAL3_CTRL__tr_baud__c57k6Hz 9
-#define R_SYNC_SERIAL3_CTRL__tr_baud__c115k2Hz 10
-#define R_SYNC_SERIAL3_CTRL__tr_baud__c230k4Hz 11
-#define R_SYNC_SERIAL3_CTRL__tr_baud__c460k8Hz 12
-#define R_SYNC_SERIAL3_CTRL__tr_baud__c921k6Hz 13
-#define R_SYNC_SERIAL3_CTRL__tr_baud__c3125kHz 14
-#define R_SYNC_SERIAL3_CTRL__tr_baud__reserved 15
-#define R_SYNC_SERIAL3_CTRL__dma_enable__BITNR 27
-#define R_SYNC_SERIAL3_CTRL__dma_enable__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__dma_enable__on 1
-#define R_SYNC_SERIAL3_CTRL__dma_enable__off 0
-#define R_SYNC_SERIAL3_CTRL__mode__BITNR 24
-#define R_SYNC_SERIAL3_CTRL__mode__WIDTH 3
-#define R_SYNC_SERIAL3_CTRL__mode__master_output 0
-#define R_SYNC_SERIAL3_CTRL__mode__slave_output 1
-#define R_SYNC_SERIAL3_CTRL__mode__master_input 2
-#define R_SYNC_SERIAL3_CTRL__mode__slave_input 3
-#define R_SYNC_SERIAL3_CTRL__mode__master_bidir 4
-#define R_SYNC_SERIAL3_CTRL__mode__slave_bidir 5
-#define R_SYNC_SERIAL3_CTRL__error__BITNR 23
-#define R_SYNC_SERIAL3_CTRL__error__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__error__normal 0
-#define R_SYNC_SERIAL3_CTRL__error__ignore 1
-#define R_SYNC_SERIAL3_CTRL__rec_enable__BITNR 22
-#define R_SYNC_SERIAL3_CTRL__rec_enable__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__rec_enable__disable 0
-#define R_SYNC_SERIAL3_CTRL__rec_enable__enable 1
-#define R_SYNC_SERIAL3_CTRL__f_synctype__BITNR 21
-#define R_SYNC_SERIAL3_CTRL__f_synctype__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__f_synctype__normal 0
-#define R_SYNC_SERIAL3_CTRL__f_synctype__early 1
-#define R_SYNC_SERIAL3_CTRL__f_syncsize__BITNR 19
-#define R_SYNC_SERIAL3_CTRL__f_syncsize__WIDTH 2
-#define R_SYNC_SERIAL3_CTRL__f_syncsize__bit 0
-#define R_SYNC_SERIAL3_CTRL__f_syncsize__word 1
-#define R_SYNC_SERIAL3_CTRL__f_syncsize__extended 2
-#define R_SYNC_SERIAL3_CTRL__f_syncsize__reserved 3
-#define R_SYNC_SERIAL3_CTRL__f_sync__BITNR 18
-#define R_SYNC_SERIAL3_CTRL__f_sync__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__f_sync__on 0
-#define R_SYNC_SERIAL3_CTRL__f_sync__off 1
-#define R_SYNC_SERIAL3_CTRL__clk_mode__BITNR 17
-#define R_SYNC_SERIAL3_CTRL__clk_mode__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__clk_mode__normal 0
-#define R_SYNC_SERIAL3_CTRL__clk_mode__gated 1
-#define R_SYNC_SERIAL3_CTRL__clk_halt__BITNR 16
-#define R_SYNC_SERIAL3_CTRL__clk_halt__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__clk_halt__running 0
-#define R_SYNC_SERIAL3_CTRL__clk_halt__stopped 1
-#define R_SYNC_SERIAL3_CTRL__bitorder__BITNR 15
-#define R_SYNC_SERIAL3_CTRL__bitorder__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__bitorder__lsb 0
-#define R_SYNC_SERIAL3_CTRL__bitorder__msb 1
-#define R_SYNC_SERIAL3_CTRL__tr_enable__BITNR 14
-#define R_SYNC_SERIAL3_CTRL__tr_enable__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__tr_enable__disable 0
-#define R_SYNC_SERIAL3_CTRL__tr_enable__enable 1
-#define R_SYNC_SERIAL3_CTRL__wordsize__BITNR 11
-#define R_SYNC_SERIAL3_CTRL__wordsize__WIDTH 3
-#define R_SYNC_SERIAL3_CTRL__wordsize__size8bit 0
-#define R_SYNC_SERIAL3_CTRL__wordsize__size12bit 1
-#define R_SYNC_SERIAL3_CTRL__wordsize__size16bit 2
-#define R_SYNC_SERIAL3_CTRL__wordsize__size24bit 3
-#define R_SYNC_SERIAL3_CTRL__wordsize__size32bit 4
-#define R_SYNC_SERIAL3_CTRL__buf_empty__BITNR 10
-#define R_SYNC_SERIAL3_CTRL__buf_empty__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__buf_empty__lmt_8 0
-#define R_SYNC_SERIAL3_CTRL__buf_empty__lmt_0 1
-#define R_SYNC_SERIAL3_CTRL__buf_full__BITNR 9
-#define R_SYNC_SERIAL3_CTRL__buf_full__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__buf_full__lmt_32 0
-#define R_SYNC_SERIAL3_CTRL__buf_full__lmt_8 1
-#define R_SYNC_SERIAL3_CTRL__flow_ctrl__BITNR 8
-#define R_SYNC_SERIAL3_CTRL__flow_ctrl__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__flow_ctrl__disabled 0
-#define R_SYNC_SERIAL3_CTRL__flow_ctrl__enabled 1
-#define R_SYNC_SERIAL3_CTRL__clk_polarity__BITNR 6
-#define R_SYNC_SERIAL3_CTRL__clk_polarity__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__clk_polarity__pos 0
-#define R_SYNC_SERIAL3_CTRL__clk_polarity__neg 1
-#define R_SYNC_SERIAL3_CTRL__frame_polarity__BITNR 5
-#define R_SYNC_SERIAL3_CTRL__frame_polarity__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__frame_polarity__normal 0
-#define R_SYNC_SERIAL3_CTRL__frame_polarity__inverted 1
-#define R_SYNC_SERIAL3_CTRL__status_polarity__BITNR 4
-#define R_SYNC_SERIAL3_CTRL__status_polarity__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__status_polarity__normal 0
-#define R_SYNC_SERIAL3_CTRL__status_polarity__inverted 1
-#define R_SYNC_SERIAL3_CTRL__clk_driver__BITNR 3
-#define R_SYNC_SERIAL3_CTRL__clk_driver__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__clk_driver__normal 0
-#define R_SYNC_SERIAL3_CTRL__clk_driver__inverted 1
-#define R_SYNC_SERIAL3_CTRL__frame_driver__BITNR 2
-#define R_SYNC_SERIAL3_CTRL__frame_driver__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__frame_driver__normal 0
-#define R_SYNC_SERIAL3_CTRL__frame_driver__inverted 1
-#define R_SYNC_SERIAL3_CTRL__status_driver__BITNR 1
-#define R_SYNC_SERIAL3_CTRL__status_driver__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__status_driver__normal 0
-#define R_SYNC_SERIAL3_CTRL__status_driver__inverted 1
-#define R_SYNC_SERIAL3_CTRL__def_out0__BITNR 0
-#define R_SYNC_SERIAL3_CTRL__def_out0__WIDTH 1
-#define R_SYNC_SERIAL3_CTRL__def_out0__high 1
-#define R_SYNC_SERIAL3_CTRL__def_out0__low 0
-
diff --git a/arch/cris/include/arch-v10/arch/sv_addr_ag.h b/arch/cris/include/arch-v10/arch/sv_addr_ag.h
deleted file mode 100644
index 5517f04..0000000
--- a/arch/cris/include/arch-v10/arch/sv_addr_ag.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*!**************************************************************************
-*!                                                            
-*! MACROS:
-*!   IO_MASK(reg,field)
-*!   IO_STATE(reg,field,state)
-*!   IO_EXTRACT(reg,field,val)
-*!   IO_STATE_VALUE(reg,field,state)
-*!   IO_BITNR(reg,field)
-*!   IO_WIDTH(reg,field)
-*!   IO_FIELD(reg,field,val)
-*!   IO_RD(reg)
-*!   All moderegister addresses and fields of these.
-*!
-*!**************************************************************************/
-
-#ifndef __sv_addr_ag_h__
-#define __sv_addr_ag_h__
-
-
-#define __test_sv_addr__ 0
-
-/*------------------------------------------------------------
-!* General macros to manipulate moderegisters.
-!*-----------------------------------------------------------*/
-
-/* IO_MASK returns a mask for a specified bitfield in a register.
-   Note that this macro doesn't work when field width is 32 bits. */
-#define IO_MASK(reg, field) IO_MASK_ (reg##_, field##_)
-#define IO_MASK_(reg_, field_) \
-    ( ( ( 1 << reg_##_##field_##_WIDTH ) - 1 ) << reg_##_##field_##_BITNR )
-
-/* IO_STATE returns a constant corresponding to a one of the symbolic
-   states that the bitfield can have. (Shifted to correct position)  */
-#define IO_STATE(reg, field, state) IO_STATE_ (reg##_, field##_, _##state)
-#define IO_STATE_(reg_, field_, _state) \
-    ( reg_##_##field_##_state << reg_##_##field_##_BITNR )
-
-/* IO_EXTRACT returns the masked and shifted value corresponding to the
-   bitfield can have. */
-#define IO_EXTRACT(reg, field, val) IO_EXTRACT_ (reg##_, field##_, val)
-#define IO_EXTRACT_(reg_, field_, val) ( (( ( ( 1 << reg_##_##field_##_WIDTH ) \
-     - 1 ) << reg_##_##field_##_BITNR ) & (val)) >> reg_##_##field_##_BITNR )
-
-/* IO_STATE_VALUE returns a constant corresponding to a one of the symbolic
-   states that the bitfield can have. (Not shifted)  */
-#define IO_STATE_VALUE(reg, field, state) \
-    IO_STATE_VALUE_ (reg##_, field##_, _##state)
-#define IO_STATE_VALUE_(reg_, field_, _state) ( reg_##_##field_##_state )
-
-/* IO_FIELD shifts the val parameter to be aligned with the bitfield
-   specified. */
-#define IO_FIELD(reg, field, val) IO_FIELD_ (reg##_, field##_, val)
-#define IO_FIELD_(reg_, field_, val) ((val) << reg_##_##field_##_BITNR)
-
-/* IO_BITNR returns the starting bitnumber of a bitfield. Bit 0 is
-   LSB and the returned bitnumber is LSB of the field. */
-#define IO_BITNR(reg, field) IO_BITNR_ (reg##_, field##_)
-#define IO_BITNR_(reg_, field_) (reg_##_##field_##_BITNR)
-
-/* IO_WIDTH returns the width, in bits, of a bitfield. */
-#define IO_WIDTH(reg, field) IO_WIDTH_ (reg##_, field##_)
-#define IO_WIDTH_(reg_, field_) (reg_##_##field_##_WIDTH)
-
-/*--- Obsolete. Kept for backw compatibility. ---*/
-/* Reads (or writes) a byte/uword/udword from the specified mode
-   register. */
-#define IO_RD(reg) (*(volatile u32*)(reg))
-#define IO_RD_B(reg) (*(volatile u8*)(reg))
-#define IO_RD_W(reg) (*(volatile u16*)(reg))
-#define IO_RD_D(reg) (*(volatile u32*)(reg))
-
-/*------------------------------------------------------------
-!* Start addresses of the different memory areas.
-!*-----------------------------------------------------------*/
-
-#define MEM_CSE0_START (0x00000000)
-#define MEM_CSE0_SIZE (0x04000000)
-#define MEM_CSE1_START (0x04000000)
-#define MEM_CSE1_SIZE (0x04000000)
-#define MEM_CSR0_START (0x08000000)
-#define MEM_CSR1_START (0x0c000000)
-#define MEM_CSP0_START (0x10000000)
-#define MEM_CSP1_START (0x14000000)
-#define MEM_CSP2_START (0x18000000)
-#define MEM_CSP3_START (0x1c000000)
-#define MEM_CSP4_START (0x20000000)
-#define MEM_CSP5_START (0x24000000)
-#define MEM_CSP6_START (0x28000000)
-#define MEM_CSP7_START (0x2c000000)
-#define MEM_DRAM_START (0x40000000)
-
-#define MEM_NON_CACHEABLE (0x80000000)
-
-/*------------------------------------------------------------
-!* Type casts used in mode register macros, making pointer
-!* dereferencing possible. Empty in assembler.
-!*-----------------------------------------------------------*/
-
-#ifndef __ASSEMBLER__
-# define  IO_TYPECAST_UDWORD  (volatile u32*)
-# define  IO_TYPECAST_RO_UDWORD  (const volatile u32*)
-# define  IO_TYPECAST_UWORD  (volatile u16*)
-# define  IO_TYPECAST_RO_UWORD  (const volatile u16*)
-# define  IO_TYPECAST_BYTE  (volatile u8*)
-# define  IO_TYPECAST_RO_BYTE  (const volatile u8*)
-#else
-# define  IO_TYPECAST_UDWORD
-# define  IO_TYPECAST_RO_UDWORD
-# define  IO_TYPECAST_UWORD
-# define  IO_TYPECAST_RO_UWORD
-# define  IO_TYPECAST_BYTE
-# define  IO_TYPECAST_RO_BYTE
-#endif
-
-/*------------------------------------------------------------*/
-
-#include <arch/sv_addr.agh>
-
-#if __test_sv_addr__
-/* IO_MASK( R_BUS_CONFIG , CE ) */
-IO_MASK( R_WAITSTATES , SRAM_WS )
-IO_MASK( R_TEST , W32 )
-
-IO_STATE( R_BUS_CONFIG, CE, DISABLE )
-IO_STATE( R_BUS_CONFIG, CE, ENABLE )
-
-IO_STATE( R_DRAM_TIMING, REF, IVAL2 )
-
-IO_MASK( R_DRAM_TIMING, REF )
-
-IO_MASK( R_EXT_DMA_0_STAT, TFR_COUNT ) >> IO_BITNR( R_EXT_DMA_0_STAT, TFR_COUNT )
-
-IO_RD(R_EXT_DMA_0_STAT) & IO_MASK( R_EXT_DMA_0_STAT, S ) 
-   == IO_STATE( R_EXT_DMA_0_STAT, S, STARTED )
-#endif
-
-
-#endif  /* ifndef __sv_addr_ag_h__ */
-
diff --git a/arch/cris/include/arch-v10/arch/svinto.h b/arch/cris/include/arch-v10/arch/svinto.h
deleted file mode 100644
index da5c152..0000000
--- a/arch/cris/include/arch-v10/arch/svinto.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef _ASM_CRIS_SVINTO_H
-#define _ASM_CRIS_SVINTO_H
-
-#include <arch/sv_addr_ag.h>
-
-extern unsigned int genconfig_shadow; /* defined and set in head.S */
-
-/* dma stuff */
-
-enum {                          /* Available in:  */
-	d_eol      = (1 << 0),  /* flags          */
-	d_eop      = (1 << 1),  /* flags & status */
-	d_wait     = (1 << 2),  /* flags          */
-	d_int      = (1 << 3),  /* flags          */
-	d_txerr    = (1 << 4),  /* flags          */
-	d_stop     = (1 << 4),  /*         status */
-	d_ecp      = (1 << 4),  /* flags & status */
-	d_pri      = (1 << 5),  /* flags & status */
-	d_alignerr = (1 << 6),  /*         status */
-	d_crcerr   = (1 << 7)   /*         status */
-};
-
-/* Do remember that DMA does not go through the MMU and needs
- * a real physical address, not an address virtually mapped or
- * paged. Therefore the buf/next ptrs below are unsigned long instead
- * of void * to give a warning if you try to put a pointer directly
- * to them instead of going through virt_to_phys/phys_to_virt.
- */
-
-typedef struct etrax_dma_descr {
-	unsigned short sw_len;                /* 0-1 */
-	unsigned short ctrl;                  /* 2-3 */
-	unsigned long  next;                  /* 4-7 */
-	unsigned long  buf;                   /* 8-11 */
-	unsigned short hw_len;                /* 12-13 */
-	unsigned char  status;                /* 14 */
-	unsigned char  fifo_len;              /* 15 */
-} etrax_dma_descr;
-
-
-/* Use this for constant numbers only */
-#define RESET_DMA_NUM( n ) \
-  *R_DMA_CH##n##_CMD = IO_STATE( R_DMA_CH0_CMD, cmd, reset )
-
-/* Use this for constant numbers or symbols, 
- * having two macros makes it possible to use constant expressions. 
- */
-#define RESET_DMA( n ) RESET_DMA_NUM( n )
-
-
-/* Use this for constant numbers only */
-#define WAIT_DMA_NUM( n ) \
-  while( (*R_DMA_CH##n##_CMD & IO_MASK( R_DMA_CH0_CMD, cmd )) != \
-         IO_STATE( R_DMA_CH0_CMD, cmd, hold ) )
-
-/* Use this for constant numbers or symbols 
- * having two macros makes it possible to use constant expressions. 
- */
-#define WAIT_DMA( n ) WAIT_DMA_NUM( n )
-
-extern void prepare_rx_descriptor(struct etrax_dma_descr *desc);
-extern void flush_etrax_cache(void);
-
-#endif
diff --git a/arch/cris/include/arch-v10/arch/user.h b/arch/cris/include/arch-v10/arch/user.h
deleted file mode 100644
index 9303ea7..0000000
--- a/arch/cris/include/arch-v10/arch/user.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef __ASM_CRIS_ARCH_USER_H
-#define __ASM_CRIS_ARCH_USER_H
-
-/* User mode registers, used for core dumps. In order to keep ELF_NGREG
-   sensible we let all registers be 32 bits. The csr registers are included
-   for future use. */
-struct user_regs_struct {
-        unsigned long r0;       /* General registers. */
-        unsigned long r1;
-        unsigned long r2;
-        unsigned long r3;
-        unsigned long r4;
-        unsigned long r5;
-        unsigned long r6;
-        unsigned long r7;
-        unsigned long r8;
-        unsigned long r9;
-        unsigned long r10;
-        unsigned long r11;
-        unsigned long r12;
-        unsigned long r13;
-        unsigned long sp;       /* Stack pointer. */
-        unsigned long pc;       /* Program counter. */
-        unsigned long p0;       /* Constant zero (only 8 bits). */
-        unsigned long vr;       /* Version register (only 8 bits). */
-        unsigned long p2;       /* Reserved. */
-        unsigned long p3;       /* Reserved. */
-        unsigned long p4;       /* Constant zero (only 16 bits). */
-        unsigned long ccr;      /* Condition code register (only 16 bits). */
-        unsigned long p6;       /* Reserved. */
-        unsigned long mof;      /* Multiply overflow register. */
-        unsigned long p8;       /* Constant zero. */
-        unsigned long ibr;      /* Not accessible. */
-        unsigned long irp;      /* Not accessible. */
-        unsigned long srp;      /* Subroutine return pointer. */
-        unsigned long bar;      /* Not accessible. */
-        unsigned long dccr;     /* Dword condition code register. */
-        unsigned long brp;      /* Not accessible. */
-        unsigned long usp;      /* User-mode stack pointer. Same as sp when 
-                                   in user mode. */
-        unsigned long csrinstr; /* Internal status registers. */
-        unsigned long csraddr;
-        unsigned long csrdata;
-};
-
-#endif
diff --git a/arch/cris/include/arch-v32/arch/Kbuild b/arch/cris/include/arch-v32/arch/Kbuild
index 35f2fc4..2fd65c7 100644
--- a/arch/cris/include/arch-v32/arch/Kbuild
+++ b/arch/cris/include/arch-v32/arch/Kbuild
@@ -1,2 +1 @@
-header-y += user.h
-header-y += cryptocop.h
+# CRISv32 arch
diff --git a/arch/cris/include/arch-v32/arch/cryptocop.h b/arch/cris/include/arch-v32/arch/cryptocop.h
index e1cd83d..716e434 100644
--- a/arch/cris/include/arch-v32/arch/cryptocop.h
+++ b/arch/cris/include/arch-v32/arch/cryptocop.h
@@ -2,124 +2,12 @@
  * The device /dev/cryptocop is accessible using this driver using
  * CRYPTOCOP_MAJOR (254) and minor number 0.
  */
-
 #ifndef CRYPTOCOP_H
 #define CRYPTOCOP_H
 
-#include <linux/uio.h>
-
-
-#define CRYPTOCOP_SESSION_ID_NONE (0)
-
-typedef unsigned long long int cryptocop_session_id;
-
-/* cryptocop ioctls */
-#define ETRAXCRYPTOCOP_IOCTYPE         (250)
-
-#define CRYPTOCOP_IO_CREATE_SESSION    _IOWR(ETRAXCRYPTOCOP_IOCTYPE, 1, struct strcop_session_op)
-#define CRYPTOCOP_IO_CLOSE_SESSION     _IOW(ETRAXCRYPTOCOP_IOCTYPE, 2, struct strcop_session_op)
-#define CRYPTOCOP_IO_PROCESS_OP        _IOWR(ETRAXCRYPTOCOP_IOCTYPE, 3, struct strcop_crypto_op)
-#define CRYPTOCOP_IO_MAXNR             (3)
-
-typedef enum {
-	cryptocop_cipher_des = 0,
-	cryptocop_cipher_3des = 1,
-	cryptocop_cipher_aes = 2,
-	cryptocop_cipher_m2m = 3, /* mem2mem is essentially a NULL cipher with blocklength=1 */
-	cryptocop_cipher_none
-} cryptocop_cipher_type;
-
-typedef enum {
-	cryptocop_digest_sha1 = 0,
-	cryptocop_digest_md5 = 1,
-	cryptocop_digest_none
-} cryptocop_digest_type;
-
-typedef enum {
-	cryptocop_csum_le = 0,
-	cryptocop_csum_be = 1,
-	cryptocop_csum_none
-} cryptocop_csum_type;
-
-typedef enum {
-	cryptocop_cipher_mode_ecb = 0,
-	cryptocop_cipher_mode_cbc,
-	cryptocop_cipher_mode_none
-} cryptocop_cipher_mode;
-
-typedef enum {
-	cryptocop_3des_eee = 0,
-	cryptocop_3des_eed = 1,
-	cryptocop_3des_ede = 2,
-	cryptocop_3des_edd = 3,
-	cryptocop_3des_dee = 4,
-	cryptocop_3des_ded = 5,
-	cryptocop_3des_dde = 6,
-	cryptocop_3des_ddd = 7
-} cryptocop_3des_mode;
-
-/* Usermode accessible (ioctl) operations. */
-struct strcop_session_op{
-	cryptocop_session_id    ses_id;
-
-	cryptocop_cipher_type   cipher; /* AES, DES, 3DES, m2m, none */
-
-	cryptocop_cipher_mode   cmode; /* ECB, CBC, none */
-	cryptocop_3des_mode     des3_mode;
-
-	cryptocop_digest_type   digest; /* MD5, SHA1, none */
-
-	cryptocop_csum_type     csum;   /* BE, LE, none */
-
-	unsigned char           *key;
-	size_t                  keylen;
-};
-
-#define CRYPTOCOP_CSUM_LENGTH         (2)
-#define CRYPTOCOP_MAX_DIGEST_LENGTH   (20)  /* SHA-1 20, MD5 16 */
-#define CRYPTOCOP_MAX_IV_LENGTH       (16)  /* (3)DES==8, AES == 16 */
-#define CRYPTOCOP_MAX_KEY_LENGTH      (32)
-
-struct strcop_crypto_op{
-	cryptocop_session_id ses_id;
-
-	/* Indata. */
-	unsigned char            *indata;
-	size_t                   inlen; /* Total indata length. */
-
-	/* Cipher configuration. */
-	unsigned char            do_cipher:1;
-	unsigned char            decrypt:1; /* 1 == decrypt, 0 == encrypt */
-	unsigned char            cipher_explicit:1;
-	size_t                   cipher_start;
-	size_t                   cipher_len;
-	/* cipher_iv is used if do_cipher and cipher_explicit and the cipher
-	   mode is CBC.  The length is controlled by the type of cipher,
-	   e.g. DES/3DES 8 octets and AES 16 octets. */
-	unsigned char            cipher_iv[CRYPTOCOP_MAX_IV_LENGTH];
-	/* Outdata. */
-	unsigned char            *cipher_outdata;
-	size_t                   cipher_outlen;
-
-	/* digest configuration. */
-	unsigned char            do_digest:1;
-	size_t                   digest_start;
-	size_t                   digest_len;
-	/* Outdata.  The actual length is determined by the type of the digest. */
-	unsigned char            digest[CRYPTOCOP_MAX_DIGEST_LENGTH];
-
-	/* Checksum configuration. */
-	unsigned char            do_csum:1;
-	size_t                   csum_start;
-	size_t                   csum_len;
-	/* Outdata. */
-	unsigned char            csum[CRYPTOCOP_CSUM_LENGTH];
-};
+#include <uapi/arch-v32/arch/cryptocop.h>
 
 
-
-#ifdef __KERNEL__
-
 /********** The API to use from inside the kernel. ************/
 
 #include <arch/hwregs/dma.h>
@@ -267,6 +155,4 @@ int cryptocop_job_queue_insert_crypto(struct cryptocop_operation *operation);
 
 int cryptocop_job_queue_insert_user_job(struct cryptocop_operation *operation);
 
-#endif /* __KERNEL__ */
-
 #endif /* CRYPTOCOP_H */
diff --git a/arch/cris/include/arch-v32/arch/irq.h b/arch/cris/include/arch-v32/arch/irq.h
index b31e998..fe3cdd2 100644
--- a/arch/cris/include/arch-v32/arch/irq.h
+++ b/arch/cris/include/arch-v32/arch/irq.h
@@ -103,7 +103,7 @@ __asm__ (				\
  * if we had BLOCK'edit here, we would not get the multiple_irq at all.
  *
  * The non-blocking here is based on the knowledge that the timer interrupt is
- * registred as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not
+ * registered as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not
  * be an sti() before the timer irq handler is run to acknowledge the interrupt.
  */
 #define BUILD_TIMER_IRQ(nr, mask) 	\
diff --git a/arch/cris/include/arch-v32/arch/spinlock.h b/arch/cris/include/arch-v32/arch/spinlock.h
index f171a66..f132755 100644
--- a/arch/cris/include/arch-v32/arch/spinlock.h
+++ b/arch/cris/include/arch-v32/arch/spinlock.h
@@ -118,7 +118,7 @@ static  inline int arch_write_trylock(arch_rwlock_t *rw)
 		ret = 1;
 	}
 	arch_spin_unlock(&rw->slock);
-	return 1;
+	return ret;
 }
 
 #define _raw_read_lock_flags(lock, flags) _raw_read_lock(lock)
diff --git a/arch/cris/include/arch-v32/arch/user.h b/arch/cris/include/arch-v32/arch/user.h
deleted file mode 100644
index 03fa1f3..0000000
--- a/arch/cris/include/arch-v32/arch/user.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef _ASM_CRIS_ARCH_USER_H
-#define _ASM_CRIS_ARCH_USER_H
-
-/* User-mode register used for core dumps. */
-
-struct user_regs_struct {
-	unsigned long r0;	/* General registers. */
-	unsigned long r1;
-	unsigned long r2;
-	unsigned long r3;
-	unsigned long r4;
-	unsigned long r5;
-	unsigned long r6;
-	unsigned long r7;
-	unsigned long r8;
-	unsigned long r9;
-	unsigned long r10;
-	unsigned long r11;
-	unsigned long r12;
-	unsigned long r13;
-	unsigned long sp;	/* R14, Stack pointer. */
-	unsigned long acr;	/* R15, Address calculation register. */
-	unsigned long bz;	/* P0, Constant zero (8-bits). */
-	unsigned long vr;	/* P1, Version register (8-bits). */
-	unsigned long pid;	/* P2, Process ID (8-bits). */
-	unsigned long srs;	/* P3, Support register select (8-bits). */
-	unsigned long wz;	/* P4, Constant zero (16-bits). */
-	unsigned long exs;	/* P5, Exception status. */
-	unsigned long eda;	/* P6, Exception data address. */
-	unsigned long mof;	/* P7, Multiply overflow regiter. */
-	unsigned long dz;	/* P8, Constant zero (32-bits). */
-	unsigned long ebp;	/* P9, Exception base pointer. */
-	unsigned long erp;	/* P10, Exception return pointer. */
-	unsigned long srp;	/* P11, Subroutine return pointer. */
-	unsigned long nrp;	/* P12, NMI return pointer. */
-	unsigned long ccs;	/* P13, Condition code stack. */
-	unsigned long usp;	/* P14, User mode stack pointer. */
-	unsigned long spc;	/* P15, Single step PC. */
-};
-
-#endif /* _ASM_CRIS_ARCH_USER_H */
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 6d43a95..f1e79ed 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -1,13 +1,9 @@
-include include/asm-generic/Kbuild.asm
 
 header-y += arch-v10/
 header-y += arch-v32/
 
-header-y += ethernet.h
-header-y += etraxgpio.h
-header-y += rs485.h
-header-y += sync_serial.h
 
 generic-y += clkdev.h
 generic-y += exec.h
 generic-y += module.h
+generic-y += trace_clock.h
diff --git a/arch/cris/include/asm/auxvec.h b/arch/cris/include/asm/auxvec.h
deleted file mode 100644
index cb30b01..0000000
--- a/arch/cris/include/asm/auxvec.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __ASMCRIS_AUXVEC_H
-#define __ASMCRIS_AUXVEC_H
-
-#endif
diff --git a/arch/cris/include/asm/bitsperlong.h b/arch/cris/include/asm/bitsperlong.h
deleted file mode 100644
index 6dc0bb0..0000000
--- a/arch/cris/include/asm/bitsperlong.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/bitsperlong.h>
diff --git a/arch/cris/include/asm/byteorder.h b/arch/cris/include/asm/byteorder.h
deleted file mode 100644
index bcd1897..0000000
--- a/arch/cris/include/asm/byteorder.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _CRIS_BYTEORDER_H
-#define _CRIS_BYTEORDER_H
-
-#include <linux/byteorder/little_endian.h>
-
-#endif
-
-
diff --git a/arch/cris/include/asm/errno.h b/arch/cris/include/asm/errno.h
deleted file mode 100644
index 2bf5eb5..0000000
--- a/arch/cris/include/asm/errno.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _CRIS_ERRNO_H
-#define _CRIS_ERRNO_H
-
-#include <asm-generic/errno.h>
-
-#endif
diff --git a/arch/cris/include/asm/ethernet.h b/arch/cris/include/asm/ethernet.h
deleted file mode 100644
index 4d58652..0000000
--- a/arch/cris/include/asm/ethernet.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*  
- * ioctl defines for ethernet driver
- *
- * Copyright (c) 2001 Axis Communications AB
- * 
- * Author: Mikael Starvik 
- *
- */
-
-#ifndef _CRIS_ETHERNET_H
-#define _CRIS_ETHERNET_H
-#define SET_ETH_SPEED_AUTO      SIOCDEVPRIVATE          /* Auto neg speed */
-#define SET_ETH_SPEED_10        SIOCDEVPRIVATE+1        /* 10 Mbps */
-#define SET_ETH_SPEED_100       SIOCDEVPRIVATE+2        /* 100 Mbps. */
-#define SET_ETH_DUPLEX_AUTO     SIOCDEVPRIVATE+3        /* Auto neg duplex */
-#define SET_ETH_DUPLEX_HALF     SIOCDEVPRIVATE+4        /* Full duplex */
-#define SET_ETH_DUPLEX_FULL     SIOCDEVPRIVATE+5        /* Half duplex */
-#define SET_ETH_ENABLE_LEDS     SIOCDEVPRIVATE+6        /* Enable net LEDs */
-#define SET_ETH_DISABLE_LEDS    SIOCDEVPRIVATE+7        /* Disable net LEDs */
-#define SET_ETH_AUTONEG         SIOCDEVPRIVATE+8
-#endif /* _CRIS_ETHERNET_H */
diff --git a/arch/cris/include/asm/etraxgpio.h b/arch/cris/include/asm/etraxgpio.h
deleted file mode 100644
index 461c089..0000000
--- a/arch/cris/include/asm/etraxgpio.h
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * The following devices are accessible using this driver using
- * GPIO_MAJOR (120) and a couple of minor numbers.
- *
- * For ETRAX 100LX (CONFIG_ETRAX_ARCH_V10):
- * /dev/gpioa  minor 0, 8 bit GPIO, each bit can change direction
- * /dev/gpiob  minor 1, 8 bit GPIO, each bit can change direction
- * /dev/leds   minor 2, Access to leds depending on kernelconfig
- * /dev/gpiog  minor 3
- *       g0dir, g8_15dir, g16_23dir, g24 dir configurable in R_GEN_CONFIG
- *       g1-g7 and g25-g31 is both input and outputs but on different pins
- *       Also note that some bits change pins depending on what interfaces
- *       are enabled.
- *
- * For ETRAX FS (CONFIG_ETRAXFS):
- * /dev/gpioa  minor 0,  8 bit GPIO, each bit can change direction
- * /dev/gpiob  minor 1, 18 bit GPIO, each bit can change direction
- * /dev/gpioc  minor 3, 18 bit GPIO, each bit can change direction
- * /dev/gpiod  minor 4, 18 bit GPIO, each bit can change direction
- * /dev/gpioe  minor 5, 18 bit GPIO, each bit can change direction
- * /dev/leds   minor 2, Access to leds depending on kernelconfig
- *
- * For ARTPEC-3 (CONFIG_CRIS_MACH_ARTPEC3):
- * /dev/gpioa  minor 0, 32 bit GPIO, each bit can change direction
- * /dev/gpiob  minor 1, 32 bit GPIO, each bit can change direction
- * /dev/gpioc  minor 3, 16 bit GPIO, each bit can change direction
- * /dev/gpiod  minor 4, 32 bit GPIO, input only
- * /dev/leds   minor 2, Access to leds depending on kernelconfig
- * /dev/pwm0   minor 16, PWM channel 0 on PA30
- * /dev/pwm1   minor 17, PWM channel 1 on PA31
- * /dev/pwm2   minor 18, PWM channel 2 on PB26
- * /dev/ppwm   minor 19, PPWM channel
- *
- */
-#ifndef _ASM_ETRAXGPIO_H
-#define _ASM_ETRAXGPIO_H
-
-#define GPIO_MINOR_FIRST 0
-
-#define ETRAXGPIO_IOCTYPE 43
-
-/* etraxgpio _IOC_TYPE, bits 8 to 15 in ioctl cmd */
-#ifdef CONFIG_ETRAX_ARCH_V10
-#define GPIO_MINOR_A 0
-#define GPIO_MINOR_B 1
-#define GPIO_MINOR_LEDS 2
-#define GPIO_MINOR_G 3
-#define GPIO_MINOR_LAST 3
-#define GPIO_MINOR_LAST_REAL GPIO_MINOR_LAST
-#endif
-
-#ifdef CONFIG_ETRAXFS
-#define GPIO_MINOR_A 0
-#define GPIO_MINOR_B 1
-#define GPIO_MINOR_LEDS 2
-#define GPIO_MINOR_C 3
-#define GPIO_MINOR_D 4
-#define GPIO_MINOR_E 5
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
-#define GPIO_MINOR_V 6
-#define GPIO_MINOR_LAST 6
-#else
-#define GPIO_MINOR_LAST 5
-#endif
-#define GPIO_MINOR_LAST_REAL GPIO_MINOR_LAST
-#endif
-
-#ifdef CONFIG_CRIS_MACH_ARTPEC3
-#define GPIO_MINOR_A 0
-#define GPIO_MINOR_B 1
-#define GPIO_MINOR_LEDS 2
-#define GPIO_MINOR_C 3
-#define GPIO_MINOR_D 4
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
-#define GPIO_MINOR_V 6
-#define GPIO_MINOR_LAST 6
-#else
-#define GPIO_MINOR_LAST 4
-#endif
-#define GPIO_MINOR_FIRST_PWM 16
-#define GPIO_MINOR_PWM0 (GPIO_MINOR_FIRST_PWM+0)
-#define GPIO_MINOR_PWM1 (GPIO_MINOR_FIRST_PWM+1)
-#define GPIO_MINOR_PWM2 (GPIO_MINOR_FIRST_PWM+2)
-#define GPIO_MINOR_PPWM (GPIO_MINOR_FIRST_PWM+3)
-#define GPIO_MINOR_LAST_PWM GPIO_MINOR_PPWM
-#define GPIO_MINOR_LAST_REAL GPIO_MINOR_LAST_PWM
-#endif
-
-
-
-/* supported ioctl _IOC_NR's */
-
-#define IO_READBITS  0x1  /* read and return current port bits (obsolete) */
-#define IO_SETBITS   0x2  /* set the bits marked by 1 in the argument */
-#define IO_CLRBITS   0x3  /* clear the bits marked by 1 in the argument */
-
-/* the alarm is waited for by select() */
-
-#define IO_HIGHALARM 0x4  /* set alarm on high for bits marked by 1 */
-#define IO_LOWALARM  0x5  /* set alarm on low for bits marked by 1 */
-#define IO_CLRALARM  0x6  /* clear alarm for bits marked by 1 */
-
-/* LED ioctl */
-#define IO_LEDACTIVE_SET 0x7 /* set active led
-                              * 0=off, 1=green, 2=red, 3=yellow */
-
-/* GPIO direction ioctl's */
-#define IO_READDIR    0x8  /* Read direction 0=input 1=output  (obsolete) */
-#define IO_SETINPUT   0x9  /* Set direction for bits set, 0=unchanged 1=input,
-                              returns mask with current inputs (obsolete) */
-#define IO_SETOUTPUT  0xA  /* Set direction for bits set, 0=unchanged 1=output,
-                              returns mask with current outputs (obsolete)*/
-
-/* LED ioctl extended */
-#define IO_LED_SETBIT 0xB
-#define IO_LED_CLRBIT 0xC
-
-/* SHUTDOWN ioctl */
-#define IO_SHUTDOWN   0xD
-#define IO_GET_PWR_BT 0xE
-
-/* Bit toggling in driver settings */
-/* bit set in low byte0 is CLK mask (0x00FF),
-   bit set in byte1 is DATA mask    (0xFF00)
-   msb, data_mask[7:0] , clk_mask[7:0]
- */
-#define IO_CFG_WRITE_MODE 0xF
-#define IO_CFG_WRITE_MODE_VALUE(msb, data_mask, clk_mask) \
-	( (((msb)&1) << 16) | (((data_mask) &0xFF) << 8) | ((clk_mask) & 0xFF) )
-
-/* The following 4 ioctl's take a pointer as argument and handles
- * 32 bit ports (port G) properly.
- * These replaces IO_READBITS,IO_SETINPUT AND IO_SETOUTPUT
- */
-#define IO_READ_INBITS   0x10 /* *arg is result of reading the input pins */
-#define IO_READ_OUTBITS  0x11 /* *arg is result of reading the output shadow */
-#define IO_SETGET_INPUT  0x12 /* bits set in *arg is set to input, */
-			      /* *arg updated with current input pins. */
-#define IO_SETGET_OUTPUT 0x13 /* bits set in *arg is set to output, */
-			      /* *arg updated with current output pins. */
-
-/* The following ioctl's are applicable to the PWM channels only */
-
-#define IO_PWM_SET_MODE     0x20
-
-enum io_pwm_mode {
-	PWM_OFF = 0,		/* disabled, deallocated */
-	PWM_STANDARD = 1,	/* 390 kHz, duty cycle 0..255/256 */
-	PWM_FAST = 2,		/* variable freq, w/ 10ns active pulse len */
-	PWM_VARFREQ = 3,	/* individually configurable high/low periods */
-	PWM_SOFT = 4		/* software generated */
-};
-
-struct io_pwm_set_mode {
-	enum io_pwm_mode mode;
-};
-
-/* Only for mode PWM_VARFREQ. Period lo/high set in increments of 10ns
- * from 10ns (value = 0) to 81920ns (value = 8191)
- * (Resulting frequencies range from 50 MHz (10ns + 10ns) down to
- * 6.1 kHz (81920ns + 81920ns) at 50% duty cycle, to 12.2 kHz at min/max duty
- * cycle (81920 + 10ns or 10ns + 81920ns, respectively).)
- */
-#define IO_PWM_SET_PERIOD   0x21
-
-struct io_pwm_set_period {
-	unsigned int lo;		/* 0..8191 */
-	unsigned int hi;		/* 0..8191 */
-};
-
-/* Only for modes PWM_STANDARD and PWM_FAST.
- * For PWM_STANDARD, set duty cycle of 390 kHz PWM output signal, from
- * 0 (value = 0) to 255/256 (value = 255).
- * For PWM_FAST, set duty cycle of PWM output signal from
- * 0% (value = 0) to 100% (value = 255). Output signal in this mode
- * is a 10ns pulse surrounded by a high or low level depending on duty
- * cycle (except for 0% and 100% which result in a constant output).
- * Resulting output frequency varies from 50 MHz at 50% duty cycle,
- * down to 390 kHz at min/max duty cycle.
- */
-#define IO_PWM_SET_DUTY     0x22
-
-struct io_pwm_set_duty {
-	int duty;		/* 0..255 */
-};
-
-/* Returns information about the latest PWM pulse.
- * lo: Length of the latest low period, in units of 10ns.
- * hi: Length of the latest high period, in units of 10ns.
- * cnt: Time since last detected edge, in units of 10ns.
- *
- * The input source to PWM is decied by IO_PWM_SET_INPUT_SRC.
- *
- * NOTE: All PWM devices is connected to the same input source.
- */
-#define IO_PWM_GET_PERIOD   0x23
-
-struct io_pwm_get_period {
-	unsigned int lo;
-	unsigned int hi;
-	unsigned int cnt;
-};
-
-/* Sets the input source for the PWM input. For the src value see the
- * register description for gio:rw_pwm_in_cfg.
- *
- * NOTE: All PWM devices is connected to the same input source.
- */
-#define IO_PWM_SET_INPUT_SRC   0x24
-struct io_pwm_set_input_src {
-	unsigned int src;	/* 0..7 */
-};
-
-/* Sets the duty cycles in steps of 1/256, 0 = 0%, 255 = 100% duty cycle */
-#define IO_PPWM_SET_DUTY     0x25
-
-struct io_ppwm_set_duty {
-	int duty;		/* 0..255 */
-};
-
-/* Configuraton struct for the IO_PWMCLK_SET_CONFIG ioctl to configure
- * PWM capable gpio pins:
- */
-#define IO_PWMCLK_SETGET_CONFIG 0x26
-struct gpio_pwmclk_conf {
-  unsigned int gpiopin; /* The pin number based on the opened device */
-  unsigned int baseclk; /* The base clock to use, or sw will select one close*/
-  unsigned int low;     /* The number of low periods of the baseclk */
-  unsigned int high;    /* The number of high periods of the baseclk */
-};
-
-/* Examples:
- * To get a symmetric 12 MHz clock without knowing anything about the hardware:
- * baseclk = 12000000, low = 0, high = 0
- * To just get info of current setting:
- * baseclk = 0, low = 0, high = 0, the values will be updated by driver.
- */
-
-#endif
diff --git a/arch/cris/include/asm/fcntl.h b/arch/cris/include/asm/fcntl.h
deleted file mode 100644
index 46ab12d..0000000
--- a/arch/cris/include/asm/fcntl.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/fcntl.h>
diff --git a/arch/cris/include/asm/io.h b/arch/cris/include/asm/io.h
index 32567bc..ac12ae2 100644
--- a/arch/cris/include/asm/io.h
+++ b/arch/cris/include/asm/io.h
@@ -133,12 +133,39 @@ static inline void writel(unsigned int b, volatile void __iomem *addr)
 #define insb(port,addr,count) (cris_iops ? cris_iops->read_io(port,addr,1,count) : 0)
 #define insw(port,addr,count) (cris_iops ? cris_iops->read_io(port,addr,2,count) : 0)
 #define insl(port,addr,count) (cris_iops ? cris_iops->read_io(port,addr,4,count) : 0)
-#define outb(data,port) if (cris_iops) cris_iops->write_io(port,(void*)(unsigned)data,1,1)
-#define outw(data,port) if (cris_iops) cris_iops->write_io(port,(void*)(unsigned)data,2,1)
-#define outl(data,port) if (cris_iops) cris_iops->write_io(port,(void*)(unsigned)data,4,1)
-#define outsb(port,addr,count) if(cris_iops) cris_iops->write_io(port,(void*)addr,1,count)
-#define outsw(port,addr,count) if(cris_iops) cris_iops->write_io(port,(void*)addr,2,count)
-#define outsl(port,addr,count) if(cris_iops) cris_iops->write_io(port,(void*)addr,3,count)
+static inline void outb(unsigned char data, unsigned int port)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *) &data, 1, 1);
+}
+static inline void outw(unsigned short data, unsigned int port)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *) &data, 2, 1);
+}
+static inline void outl(unsigned int data, unsigned int port)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *) &data, 4, 1);
+}
+static inline void outsb(unsigned int port, const void *addr,
+			 unsigned long count)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *)addr, 1, count);
+}
+static inline void outsw(unsigned int port, const void *addr,
+			 unsigned long count)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *)addr, 2, count);
+}
+static inline void outsl(unsigned int port, const void *addr,
+			 unsigned long count)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *)addr, 4, count);
+}
 
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
diff --git a/arch/cris/include/asm/ioctl.h b/arch/cris/include/asm/ioctl.h
deleted file mode 100644
index b279fe0..0000000
--- a/arch/cris/include/asm/ioctl.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff --git a/arch/cris/include/asm/ioctls.h b/arch/cris/include/asm/ioctls.h
deleted file mode 100644
index 488fbb3..0000000
--- a/arch/cris/include/asm/ioctls.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __ARCH_CRIS_IOCTLS_H__
-#define __ARCH_CRIS_IOCTLS_H__
-
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERSETRS485	0x5461  /* enable rs-485 (deprecated) */
-#define TIOCSERWRRS485	0x5462  /* write rs-485 */
-#define TIOCSRS485	0x5463  /* enable rs-485 */
-
-#include <asm-generic/ioctls.h>
-
-#endif
diff --git a/arch/cris/include/asm/ipcbuf.h b/arch/cris/include/asm/ipcbuf.h
deleted file mode 100644
index 84c7e51..0000000
--- a/arch/cris/include/asm/ipcbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipcbuf.h>
diff --git a/arch/cris/include/asm/mman.h b/arch/cris/include/asm/mman.h
deleted file mode 100644
index 8eebf89..0000000
--- a/arch/cris/include/asm/mman.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/mman.h>
diff --git a/arch/cris/include/asm/msgbuf.h b/arch/cris/include/asm/msgbuf.h
deleted file mode 100644
index ada63df..0000000
--- a/arch/cris/include/asm/msgbuf.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef _CRIS_MSGBUF_H
-#define _CRIS_MSGBUF_H
-
-/* verbatim copy of asm-i386 version */
-
-/* 
- * The msqid64_ds structure for CRIS 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 /* _CRIS_MSGBUF_H */
diff --git a/arch/cris/include/asm/param.h b/arch/cris/include/asm/param.h
deleted file mode 100644
index 484fcf8..0000000
--- a/arch/cris/include/asm/param.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _ASMCRIS_PARAM_H
-#define _ASMCRIS_PARAM_H
-
-/* Currently we assume that HZ=100 is good for CRIS. */
-
-#define EXEC_PAGESIZE	8192
-
-#include <asm-generic/param.h>
-
-#endif /* _ASMCRIS_PARAM_H */
diff --git a/arch/cris/include/asm/poll.h b/arch/cris/include/asm/poll.h
deleted file mode 100644
index c98509d..0000000
--- a/arch/cris/include/asm/poll.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/poll.h>
diff --git a/arch/cris/include/asm/posix_types.h b/arch/cris/include/asm/posix_types.h
deleted file mode 100644
index ce4e517..0000000
--- a/arch/cris/include/asm/posix_types.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* $Id: posix_types.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $ */
-
-/* We cheat a bit and use our C-coded bitops functions from asm/bitops.h */
-/* I guess we should write these in assembler because they are used often. */
-
-#ifndef __ARCH_CRIS_POSIX_TYPES_H
-#define __ARCH_CRIS_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 __SIZE_TYPE__	__kernel_size_t;
-typedef long		__kernel_ssize_t;
-typedef int		__kernel_ptrdiff_t;
-#define __kernel_size_t __kernel_size_t
-
-typedef unsigned short	__kernel_old_dev_t;
-#define __kernel_old_dev_t __kernel_old_dev_t
-
-#include <asm-generic/posix_types.h>
-
-#endif /* __ARCH_CRIS_POSIX_TYPES_H */
diff --git a/arch/cris/include/asm/processor.h b/arch/cris/include/asm/processor.h
index ef4e1bc..675823f 100644
--- a/arch/cris/include/asm/processor.h
+++ b/arch/cris/include/asm/processor.h
@@ -49,8 +49,6 @@ struct task_struct;
 #define task_pt_regs(task) user_regs(task_thread_info(task))
 #define current_regs() task_pt_regs(current)
 
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 unsigned long get_wchan(struct task_struct *p);
 
 #define KSTK_ESP(tsk)   ((tsk) == current ? rdusp() : (tsk)->thread.usp)
diff --git a/arch/cris/include/asm/ptrace.h b/arch/cris/include/asm/ptrace.h
index 6618893..2de84d7 100644
--- a/arch/cris/include/asm/ptrace.h
+++ b/arch/cris/include/asm/ptrace.h
@@ -1,9 +1,8 @@
 #ifndef _CRIS_PTRACE_H
 #define _CRIS_PTRACE_H
 
-#include <arch/ptrace.h>
+#include <uapi/asm/ptrace.h>
 
-#ifdef __KERNEL__
 
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
 #define PTRACE_GETREGS            12
@@ -11,6 +10,4 @@
 
 #define profile_pc(regs) instruction_pointer(regs)
 
-#endif /* __KERNEL__ */
-
 #endif /* _CRIS_PTRACE_H */
diff --git a/arch/cris/include/asm/resource.h b/arch/cris/include/asm/resource.h
deleted file mode 100644
index b5d2944..0000000
--- a/arch/cris/include/asm/resource.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _CRIS_RESOURCE_H
-#define _CRIS_RESOURCE_H
-
-#include <asm-generic/resource.h>
-
-#endif
diff --git a/arch/cris/include/asm/rs485.h b/arch/cris/include/asm/rs485.h
deleted file mode 100644
index ad40f9f..0000000
--- a/arch/cris/include/asm/rs485.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* RS-485 structures */
-
-/* Used with ioctl() TIOCSERSETRS485 for backward compatibility!
- * XXX: Do not use it for new code!
- */
-struct rs485_control {
-        unsigned short rts_on_send;
-        unsigned short rts_after_sent;
-        unsigned long delay_rts_before_send;
-        unsigned short enabled;
-};
-
-/* Used with ioctl() TIOCSERWRRS485 */
-struct rs485_write {
-        unsigned short outc_size;
-        unsigned char *outc;
-};
-
diff --git a/arch/cris/include/asm/sembuf.h b/arch/cris/include/asm/sembuf.h
deleted file mode 100644
index 7fed984..0000000
--- a/arch/cris/include/asm/sembuf.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _CRIS_SEMBUF_H
-#define _CRIS_SEMBUF_H
-
-/* 
- * The semid64_ds structure for CRIS 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 /* _CRIS_SEMBUF_H */
diff --git a/arch/cris/include/asm/setup.h b/arch/cris/include/asm/setup.h
deleted file mode 100644
index b907286..0000000
--- a/arch/cris/include/asm/setup.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _CRIS_SETUP_H
-#define _CRIS_SETUP_H
-
-#define COMMAND_LINE_SIZE	256
-
-#endif
diff --git a/arch/cris/include/asm/shmbuf.h b/arch/cris/include/asm/shmbuf.h
deleted file mode 100644
index 3239e3f..0000000
--- a/arch/cris/include/asm/shmbuf.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef _CRIS_SHMBUF_H
-#define _CRIS_SHMBUF_H
-
-/* 
- * The shmid64_ds structure for CRIS architecture (same as for i386)
- * 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 /* _CRIS_SHMBUF_H */
diff --git a/arch/cris/include/asm/sigcontext.h b/arch/cris/include/asm/sigcontext.h
deleted file mode 100644
index a1d634e..0000000
--- a/arch/cris/include/asm/sigcontext.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* $Id: sigcontext.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $ */
-
-#ifndef _ASM_CRIS_SIGCONTEXT_H
-#define _ASM_CRIS_SIGCONTEXT_H
-
-#include <asm/ptrace.h>
-
-/* This struct is saved by setup_frame in signal.c, to keep the current context while
-   a signal handler is executed. It's restored by sys_sigreturn.
-   
-   To keep things simple, we use pt_regs here even though normally you just specify
-   the list of regs to save. Then we can use copy_from_user on the entire regs instead
-   of a bunch of get_user's as well...
-
-*/
-
-struct sigcontext {
-	struct pt_regs regs;  /* needs to be first */
-	unsigned long oldmask;
-	unsigned long usp;    /* usp before stacking this gunk on it */
-};
-
-#endif
-
diff --git a/arch/cris/include/asm/siginfo.h b/arch/cris/include/asm/siginfo.h
deleted file mode 100644
index c1cd6d1..0000000
--- a/arch/cris/include/asm/siginfo.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _CRIS_SIGINFO_H
-#define _CRIS_SIGINFO_H
-
-#include <asm-generic/siginfo.h>
-
-#endif
diff --git a/arch/cris/include/asm/signal.h b/arch/cris/include/asm/signal.h
index ea6af9a..c0cb1fd 100644
--- a/arch/cris/include/asm/signal.h
+++ b/arch/cris/include/asm/signal.h
@@ -1,12 +1,8 @@
 #ifndef _ASM_CRIS_SIGNAL_H
 #define _ASM_CRIS_SIGNAL_H
 
-#include <linux/types.h>
+#include <uapi/asm/signal.h>
 
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-
-#ifdef __KERNEL__
 /* Most things should be clean enough to redefine this at will, if care
    is taken to make libc match.  */
 
@@ -20,95 +16,6 @@ typedef struct {
 	unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
-#else
-/* 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	0x00000001u
-#define SA_NOCLDWAIT	0x00000002u
-#define SA_SIGINFO	0x00000004u
-#define SA_ONSTACK	0x08000000u
-#define SA_RESTART	0x10000000u
-#define SA_NODEFER	0x40000000u
-#define SA_RESETHAND	0x80000000u
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
-#define SA_RESTORER	0x04000000
-
-/* 
- * sigaltstack controls
- */
-#define SS_ONSTACK	1
-#define SS_DISABLE	2
-
-#define MINSIGSTKSZ	2048
-#define SIGSTKSZ	8192
-
-#include <asm-generic/signal-defs.h>
-
-#ifdef __KERNEL__
 struct old_sigaction {
 	__sighandler_t sa_handler;
 	old_sigset_t sa_mask;
@@ -126,38 +33,6 @@ struct sigaction {
 struct k_sigaction {
 	struct sigaction sa;
 };
-#else
-/* 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;
-
-#ifdef __KERNEL__
 #include <asm/sigcontext.h>
 
-/* here we could define asm-optimized sigaddset, sigdelset etc. operations. 
- * if we don't, generic ones are used from linux/signal.h
- */
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
-#endif /* __KERNEL__ */
-
 #endif
diff --git a/arch/cris/include/asm/socket.h b/arch/cris/include/asm/socket.h
deleted file mode 100644
index ae52825..0000000
--- a/arch/cris/include/asm/socket.h
+++ /dev/null
@@ -1,76 +0,0 @@
-#ifndef _ASM_SOCKET_H
-#define _ASM_SOCKET_H
-
-/* almost the same as asm-i386/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
-/* To add :#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_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
-
-#endif /* _ASM_SOCKET_H */
-
-
diff --git a/arch/cris/include/asm/sockios.h b/arch/cris/include/asm/sockios.h
deleted file mode 100644
index cfe7bfe..0000000
--- a/arch/cris/include/asm/sockios.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ARCH_CRIS_SOCKIOS__
-#define __ARCH_CRIS_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
diff --git a/arch/cris/include/asm/stat.h b/arch/cris/include/asm/stat.h
deleted file mode 100644
index 9e558cc..0000000
--- a/arch/cris/include/asm/stat.h
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef _CRIS_STAT_H
-#define _CRIS_STAT_H
-
-/* Keep this a verbatim copy of i386 version; tweak CRIS-specific bits in
-   the kernel if necessary.  */
-
-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;
-};
-
-#define STAT_HAVE_NSEC 1
-
-struct stat {
-	unsigned long  st_dev;
-	unsigned long  st_ino;
-	unsigned short st_mode;
-	unsigned short st_nlink;
-	unsigned short st_uid;
-	unsigned short st_gid;
-	unsigned long  st_rdev;
-	unsigned long  st_size;
-	unsigned long  st_blksize;
-	unsigned long  st_blocks;
-	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  __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	__pad0[4];
-
-#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[4];
-
-	long long	st_size;
-	unsigned long	st_blksize;
-
-	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
-	unsigned long	__pad4;		/* future possible st_blocks high bits */
-
-	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;	/* will be high 32 bits of ctime someday */
-
-	unsigned long long	st_ino;
-};
-
-#endif
diff --git a/arch/cris/include/asm/statfs.h b/arch/cris/include/asm/statfs.h
deleted file mode 100644
index fdaf921..0000000
--- a/arch/cris/include/asm/statfs.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _CRIS_STATFS_H
-#define _CRIS_STATFS_H
-
-#include <asm-generic/statfs.h>
-
-#endif
diff --git a/arch/cris/include/asm/swab.h b/arch/cris/include/asm/swab.h
index 80668e8..991b6ac 100644
--- a/arch/cris/include/asm/swab.h
+++ b/arch/cris/include/asm/swab.h
@@ -1,8 +1,7 @@
 #ifndef _CRIS_SWAB_H
 #define _CRIS_SWAB_H
 
-#ifdef __KERNEL__
 #include <arch/swab.h>
-#endif /* __KERNEL__ */
+#include <uapi/asm/swab.h>
 
 #endif /* _CRIS_SWAB_H */
diff --git a/arch/cris/include/asm/sync_serial.h b/arch/cris/include/asm/sync_serial.h
deleted file mode 100644
index 7f827fe..0000000
--- a/arch/cris/include/asm/sync_serial.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * ioctl defines for synchronous serial port driver
- *
- * Copyright (c) 2001-2003 Axis Communications AB
- *
- * Author: Mikael Starvik
- *
- */
-
-#ifndef SYNC_SERIAL_H
-#define SYNC_SERIAL_H
-
-#include <linux/ioctl.h>
-
-#define SSP_SPEED      _IOR('S', 0, unsigned int)
-#define SSP_MODE       _IOR('S', 1, unsigned int)
-#define SSP_FRAME_SYNC _IOR('S', 2, unsigned int)
-#define SSP_IPOLARITY  _IOR('S', 3, unsigned int)
-#define SSP_OPOLARITY  _IOR('S', 4, unsigned int)
-#define SSP_SPI        _IOR('S', 5, unsigned int)
-#define SSP_INBUFCHUNK _IOR('S', 6, unsigned int)
-#define SSP_INPUT      _IOR('S', 7, unsigned int)
-
-/* Values for SSP_SPEED */
-#define SSP150        0
-#define SSP300        1
-#define SSP600        2
-#define SSP1200       3
-#define SSP2400       4
-#define SSP4800       5
-#define SSP9600       6
-#define SSP19200      7
-#define SSP28800      8
-#define SSP57600      9
-#define SSP115200    10
-#define SSP230400    11
-#define SSP460800    12
-#define SSP921600    13
-#define SSP3125000   14
-#define CODEC        15
-#define CODEC_f32768 16
-
-#define FREQ_4MHz   0
-#define FREQ_2MHz   1
-#define FREQ_1MHz   2
-#define FREQ_512kHz 3
-#define FREQ_256kHz 4
-#define FREQ_128kHz 5
-#define FREQ_64kHz  6
-#define FREQ_32kHz  7
-/* FREQ_* with values where bit (value & 0x10) is set are */
-/* used for CODEC_f32768 */
-#define FREQ_4096kHz 16 /* CODEC_f32768 */
-
-/* Used by application to set CODEC divider, word rate and frame rate */
-#define CODEC_VAL(freq, clk_per_sync, sync_per_frame) \
-	((CODEC + ((freq & 0x10) >> 4)) | (freq << 8) | \
-		   (clk_per_sync << 16) | (sync_per_frame << 28))
-
-/* Used by driver to extract speed */
-#define GET_SPEED(x) (x & 0xff)
-#define GET_FREQ(x) ((x & 0xff00) >> 8)
-#define GET_WORD_RATE(x) (((x & 0x0fff0000) >> 16) - 1)
-#define GET_FRAME_RATE(x) (((x & 0xf0000000) >> 28) - 1)
-
-/* Values for SSP_MODE */
-#define MASTER_OUTPUT 0
-#define SLAVE_OUTPUT  1
-#define MASTER_INPUT  2
-#define SLAVE_INPUT   3
-#define MASTER_BIDIR  4
-#define SLAVE_BIDIR   5
-
-/* Values for SSP_FRAME_SYNC */
-#define NORMAL_SYNC                1
-#define EARLY_SYNC                 2
-#define SECOND_WORD_SYNC     0x40000
-#define LATE_SYNC            0x80000
-
-#define BIT_SYNC                   4
-#define WORD_SYNC                  8
-#define EXTENDED_SYNC           0x10
-
-#define SYNC_OFF                0x20
-#define SYNC_ON                 0x40
-#define WORD_SIZE_8             0x80
-#define WORD_SIZE_12           0x100
-#define WORD_SIZE_16           0x200
-#define WORD_SIZE_24           0x400
-#define WORD_SIZE_32           0x800
-#define BIT_ORDER_LSB         0x1000
-#define BIT_ORDER_MSB         0x2000
-#define FLOW_CONTROL_ENABLE   0x4000
-#define FLOW_CONTROL_DISABLE  0x8000
-#define CLOCK_GATED          0x10000
-#define CLOCK_NOT_GATED      0x20000
-
-/* Values for SSP_IPOLARITY and SSP_OPOLARITY */
-#define CLOCK_NORMAL         1
-#define CLOCK_INVERT         2
-#define CLOCK_INEGEDGE       CLOCK_NORMAL
-#define CLOCK_IPOSEDGE       CLOCK_INVERT
-#define FRAME_NORMAL         4
-#define FRAME_INVERT         8
-#define STATUS_NORMAL      0x10
-#define STATUS_INVERT      0x20
-
-/* Values for SSP_SPI */
-#define SPI_MASTER           0
-#define SPI_SLAVE            1
-
-/* Values for SSP_INBUFCHUNK */
-/* plain integer with the size of DMA chunks */
-
-/* To ensure that the timestamps are aligned with the data being read
- * the read length MUST be a multiple of the length of the DMA buffers.
- *
- * Use a multiple of SSP_INPUT_CHUNK_SIZE defined below.
- */
-#define SSP_INPUT_CHUNK_SIZE  256
-
-/* Request struct to pass through the ioctl interface to read
- * data with timestamps.
- */
-struct ssp_request {
-	char __user *buf;	/* Where to put the data. */
-	size_t len;		/* Size of buf. MUST be a multiple of */
-				/* SSP_INPUT_CHUNK_SIZE! */
-	struct timespec ts;	/* The time the data was sampled. */
-};
-
-#endif
diff --git a/arch/cris/include/asm/termbits.h b/arch/cris/include/asm/termbits.h
deleted file mode 100644
index 1c43bc8..0000000
--- a/arch/cris/include/asm/termbits.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/* $Id: termbits.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $ */
-
-#ifndef __ARCH_ETRAX100_TERMBITS_H__
-#define __ARCH_ETRAX100_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 */
-/*
- *     3             2            1
- *    10 987 654 321 098 765 432 109 876 543 210
- *                             |           | ||| CBAUD
- *                                         obaud    
- *
- *                                       ||CSIZE
- *
- *                                     |CSTOP
- *                                    |CREAD
- *                                   |CPARENB
- *
- *                                 |CPARODD 
- *                                |HUPCL
- *                               |CLOCAL
- *                             |CBAUDEX
- *    10 987 654 321 098 765 432 109 876 543 210
- *        |           || ||   CIBAUD, IBSHIFT=16
- *                    ibaud
- *     |CMSPAR
- *    | CRTSCTS
- *       x x xxx xxx x     x xx Free bits
- */
-
-#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
-
-/* Unsupported rates, but needed to avoid compile error. */
-#define   B500000 0010005
-#define   B576000 0010006
-#define  B1000000 0010010
-#define  B1152000 0010011
-#define  B1500000 0010012
-#define  B2000000 0010013
-#define  B2500000 0010014
-#define  B3000000 0010015
-#define  B3500000 0010016
-#define  B4000000 0010017
-
-/* etrax supports these additional three baud rates */
-#define  B921600   0010005
-#define  B1843200  0010006
-#define  B6250000  0010007
-/* ETRAX FS supports this as well */
-#define  B12500000 0010010
-#define CIBAUD	  002003600000	/* input baud rate (used in v32) */
-/* The values for CIBAUD bits are the same as the values for CBAUD and CBAUDEX
- * shifted left IBSHIFT bits.
- */
-#define IBSHIFT   16
-#define CMSPAR    010000000000 /* mark or space (stick) parity - PARODD=space*/
-#define CRTSCTS	  020000000000		/* flow control */
-
-/* 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
diff --git a/arch/cris/include/asm/termios.h b/arch/cris/include/asm/termios.h
index 1265109..1991cd9e 100644
--- a/arch/cris/include/asm/termios.h
+++ b/arch/cris/include/asm/termios.h
@@ -1,47 +1,8 @@
 #ifndef _CRIS_TERMIOS_H
 #define _CRIS_TERMIOS_H
 
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-#include <asm/rs485.h>
-#include <linux/serial.h>
+#include <uapi/asm/termios.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 */
-
-#ifdef __KERNEL__
 
 /*	intr=^C		quit=^\		erase=del	kill=^U
 	eof=^D		vtime=\0	vmin=\1		sxtc=\0
@@ -87,6 +48,4 @@ struct termio {
 #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	/* __KERNEL__ */
-
 #endif	/* _CRIS_TERMIOS_H */
diff --git a/arch/cris/include/asm/types.h b/arch/cris/include/asm/types.h
index adaf827..a3cac77 100644
--- a/arch/cris/include/asm/types.h
+++ b/arch/cris/include/asm/types.h
@@ -1,15 +1,12 @@
 #ifndef _ETRAX_TYPES_H
 #define _ETRAX_TYPES_H
 
-#include <asm-generic/int-ll64.h>
+#include <uapi/asm/types.h>
 
 /*
  * These aren't exported outside the kernel to avoid name space clashes
  */
-#ifdef __KERNEL__
 
 #define BITS_PER_LONG 32
 
-#endif /* __KERNEL__ */
-
 #endif
diff --git a/arch/cris/include/asm/unistd.h b/arch/cris/include/asm/unistd.h
index 51873a4..89680f9 100644
--- a/arch/cris/include/asm/unistd.h
+++ b/arch/cris/include/asm/unistd.h
@@ -1,347 +1,8 @@
 #ifndef _ASM_CRIS_UNISTD_H_
 #define _ASM_CRIS_UNISTD_H_
 
-/*
- * This file contains the system call numbers, and stub macros for libc.
- */
-
-#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_vm86		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_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	/* SuS compliant getrlimit */
-#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_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_utimensat		320
-#define __NR_signalfd		321
-#define __NR_timerfd_create	322
-#define __NR_eventfd		323
-#define __NR_fallocate		324
-#define __NR_timerfd_settime	325
-#define __NR_timerfd_gettime	326
-#define __NR_signalfd4		327
-#define __NR_eventfd2		328
-#define __NR_epoll_create1	329
-#define __NR_dup3		330
-#define __NR_pipe2		331
-#define __NR_inotify_init1	332
-#define __NR_preadv		333
-#define __NR_pwritev		334
-#define __NR_setns		335
+#include <uapi/asm/unistd.h>
 
-#ifdef __KERNEL__
 
 #define NR_syscalls 336
 
@@ -371,6 +32,10 @@
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_CLONE
 
 /*
  * "Conditional" syscalls
@@ -380,5 +45,4 @@
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_CRIS_UNISTD_H_ */
diff --git a/arch/cris/include/uapi/arch-v10/arch/Kbuild b/arch/cris/include/uapi/arch-v10/arch/Kbuild
index aafaa5a..9048c87 100644
--- a/arch/cris/include/uapi/arch-v10/arch/Kbuild
+++ b/arch/cris/include/uapi/arch-v10/arch/Kbuild
@@ -1 +1,5 @@
 # UAPI Header export list
+header-y += sv_addr.agh
+header-y += sv_addr_ag.h
+header-y += svinto.h
+header-y += user.h
diff --git a/arch/cris/include/uapi/arch-v10/arch/sv_addr.agh b/arch/cris/include/uapi/arch-v10/arch/sv_addr.agh
new file mode 100644
index 0000000..6ac3a7b
--- /dev/null
+++ b/arch/cris/include/uapi/arch-v10/arch/sv_addr.agh
@@ -0,0 +1,7306 @@
+/*
+!* This file was automatically generated by /n/asic/bin/reg_macro_gen
+!* from the file `/n/asic/projects/etrax_ng/doc/work/etrax_ng_regs.rd'.
+!* Editing within this file is thus not recommended,
+!* make the changes in `/n/asic/projects/etrax_ng/doc/work/etrax_ng_regs.rd' instead.
+!*/
+
+
+/*
+!* Bus interface configuration registers
+!*/
+
+#define R_WAITSTATES (IO_TYPECAST_UDWORD 0xb0000000)
+#define R_WAITSTATES__pcs4_7_zw__BITNR 30
+#define R_WAITSTATES__pcs4_7_zw__WIDTH 2
+#define R_WAITSTATES__pcs4_7_ew__BITNR 28
+#define R_WAITSTATES__pcs4_7_ew__WIDTH 2
+#define R_WAITSTATES__pcs4_7_lw__BITNR 24
+#define R_WAITSTATES__pcs4_7_lw__WIDTH 4
+#define R_WAITSTATES__pcs0_3_zw__BITNR 22
+#define R_WAITSTATES__pcs0_3_zw__WIDTH 2
+#define R_WAITSTATES__pcs0_3_ew__BITNR 20
+#define R_WAITSTATES__pcs0_3_ew__WIDTH 2
+#define R_WAITSTATES__pcs0_3_lw__BITNR 16
+#define R_WAITSTATES__pcs0_3_lw__WIDTH 4
+#define R_WAITSTATES__sram_zw__BITNR 14
+#define R_WAITSTATES__sram_zw__WIDTH 2
+#define R_WAITSTATES__sram_ew__BITNR 12
+#define R_WAITSTATES__sram_ew__WIDTH 2
+#define R_WAITSTATES__sram_lw__BITNR 8
+#define R_WAITSTATES__sram_lw__WIDTH 4
+#define R_WAITSTATES__flash_zw__BITNR 6
+#define R_WAITSTATES__flash_zw__WIDTH 2
+#define R_WAITSTATES__flash_ew__BITNR 4
+#define R_WAITSTATES__flash_ew__WIDTH 2
+#define R_WAITSTATES__flash_lw__BITNR 0
+#define R_WAITSTATES__flash_lw__WIDTH 4
+
+#define R_BUS_CONFIG (IO_TYPECAST_UDWORD 0xb0000004)
+#define R_BUS_CONFIG__sram_type__BITNR 9
+#define R_BUS_CONFIG__sram_type__WIDTH 1
+#define R_BUS_CONFIG__sram_type__cwe 1
+#define R_BUS_CONFIG__sram_type__bwe 0
+#define R_BUS_CONFIG__dma_burst__BITNR 8
+#define R_BUS_CONFIG__dma_burst__WIDTH 1
+#define R_BUS_CONFIG__dma_burst__burst16 1
+#define R_BUS_CONFIG__dma_burst__burst32 0
+#define R_BUS_CONFIG__pcs4_7_wr__BITNR 7
+#define R_BUS_CONFIG__pcs4_7_wr__WIDTH 1
+#define R_BUS_CONFIG__pcs4_7_wr__ext 1
+#define R_BUS_CONFIG__pcs4_7_wr__norm 0
+#define R_BUS_CONFIG__pcs0_3_wr__BITNR 6
+#define R_BUS_CONFIG__pcs0_3_wr__WIDTH 1
+#define R_BUS_CONFIG__pcs0_3_wr__ext 1
+#define R_BUS_CONFIG__pcs0_3_wr__norm 0
+#define R_BUS_CONFIG__sram_wr__BITNR 5
+#define R_BUS_CONFIG__sram_wr__WIDTH 1
+#define R_BUS_CONFIG__sram_wr__ext 1
+#define R_BUS_CONFIG__sram_wr__norm 0
+#define R_BUS_CONFIG__flash_wr__BITNR 4
+#define R_BUS_CONFIG__flash_wr__WIDTH 1
+#define R_BUS_CONFIG__flash_wr__ext 1
+#define R_BUS_CONFIG__flash_wr__norm 0
+#define R_BUS_CONFIG__pcs4_7_bw__BITNR 3
+#define R_BUS_CONFIG__pcs4_7_bw__WIDTH 1
+#define R_BUS_CONFIG__pcs4_7_bw__bw32 1
+#define R_BUS_CONFIG__pcs4_7_bw__bw16 0
+#define R_BUS_CONFIG__pcs0_3_bw__BITNR 2
+#define R_BUS_CONFIG__pcs0_3_bw__WIDTH 1
+#define R_BUS_CONFIG__pcs0_3_bw__bw32 1
+#define R_BUS_CONFIG__pcs0_3_bw__bw16 0
+#define R_BUS_CONFIG__sram_bw__BITNR 1
+#define R_BUS_CONFIG__sram_bw__WIDTH 1
+#define R_BUS_CONFIG__sram_bw__bw32 1
+#define R_BUS_CONFIG__sram_bw__bw16 0
+#define R_BUS_CONFIG__flash_bw__BITNR 0
+#define R_BUS_CONFIG__flash_bw__WIDTH 1
+#define R_BUS_CONFIG__flash_bw__bw32 1
+#define R_BUS_CONFIG__flash_bw__bw16 0
+
+#define R_BUS_STATUS (IO_TYPECAST_RO_UDWORD 0xb0000004)
+#define R_BUS_STATUS__pll_lock_tm__BITNR 5
+#define R_BUS_STATUS__pll_lock_tm__WIDTH 1
+#define R_BUS_STATUS__pll_lock_tm__expired 0
+#define R_BUS_STATUS__pll_lock_tm__counting 1
+#define R_BUS_STATUS__both_faults__BITNR 4
+#define R_BUS_STATUS__both_faults__WIDTH 1
+#define R_BUS_STATUS__both_faults__no 0
+#define R_BUS_STATUS__both_faults__yes 1
+#define R_BUS_STATUS__bsen___BITNR 3
+#define R_BUS_STATUS__bsen___WIDTH 1
+#define R_BUS_STATUS__bsen___enable 0
+#define R_BUS_STATUS__bsen___disable 1
+#define R_BUS_STATUS__boot__BITNR 1
+#define R_BUS_STATUS__boot__WIDTH 2
+#define R_BUS_STATUS__boot__uncached 0
+#define R_BUS_STATUS__boot__serial 1
+#define R_BUS_STATUS__boot__network 2
+#define R_BUS_STATUS__boot__parallel 3
+#define R_BUS_STATUS__flashw__BITNR 0
+#define R_BUS_STATUS__flashw__WIDTH 1
+#define R_BUS_STATUS__flashw__bw32 1
+#define R_BUS_STATUS__flashw__bw16 0
+
+#define R_DRAM_TIMING (IO_TYPECAST_UDWORD 0xb0000008)
+#define R_DRAM_TIMING__sdram__BITNR 31
+#define R_DRAM_TIMING__sdram__WIDTH 1
+#define R_DRAM_TIMING__sdram__enable 1
+#define R_DRAM_TIMING__sdram__disable 0
+#define R_DRAM_TIMING__ref__BITNR 14
+#define R_DRAM_TIMING__ref__WIDTH 2
+#define R_DRAM_TIMING__ref__e52us 0
+#define R_DRAM_TIMING__ref__e13us 1
+#define R_DRAM_TIMING__ref__e8700ns 2
+#define R_DRAM_TIMING__ref__disable 3
+#define R_DRAM_TIMING__rp__BITNR 12
+#define R_DRAM_TIMING__rp__WIDTH 2
+#define R_DRAM_TIMING__rs__BITNR 10
+#define R_DRAM_TIMING__rs__WIDTH 2
+#define R_DRAM_TIMING__rh__BITNR 8
+#define R_DRAM_TIMING__rh__WIDTH 2
+#define R_DRAM_TIMING__w__BITNR 7
+#define R_DRAM_TIMING__w__WIDTH 1
+#define R_DRAM_TIMING__w__norm 0
+#define R_DRAM_TIMING__w__ext 1
+#define R_DRAM_TIMING__c__BITNR 6
+#define R_DRAM_TIMING__c__WIDTH 1
+#define R_DRAM_TIMING__c__norm 0
+#define R_DRAM_TIMING__c__ext 1
+#define R_DRAM_TIMING__cz__BITNR 4
+#define R_DRAM_TIMING__cz__WIDTH 2
+#define R_DRAM_TIMING__cp__BITNR 2
+#define R_DRAM_TIMING__cp__WIDTH 2
+#define R_DRAM_TIMING__cw__BITNR 0
+#define R_DRAM_TIMING__cw__WIDTH 2
+
+#define R_SDRAM_TIMING (IO_TYPECAST_UDWORD 0xb0000008)
+#define R_SDRAM_TIMING__sdram__BITNR 31
+#define R_SDRAM_TIMING__sdram__WIDTH 1
+#define R_SDRAM_TIMING__sdram__enable 1
+#define R_SDRAM_TIMING__sdram__disable 0
+#define R_SDRAM_TIMING__mrs_data__BITNR 16
+#define R_SDRAM_TIMING__mrs_data__WIDTH 15
+#define R_SDRAM_TIMING__ref__BITNR 14
+#define R_SDRAM_TIMING__ref__WIDTH 2
+#define R_SDRAM_TIMING__ref__e52us 0
+#define R_SDRAM_TIMING__ref__e13us 1
+#define R_SDRAM_TIMING__ref__e6500ns 2
+#define R_SDRAM_TIMING__ref__disable 3
+#define R_SDRAM_TIMING__ddr__BITNR 13
+#define R_SDRAM_TIMING__ddr__WIDTH 1
+#define R_SDRAM_TIMING__ddr__on 1
+#define R_SDRAM_TIMING__ddr__off 0
+#define R_SDRAM_TIMING__clk100__BITNR 12
+#define R_SDRAM_TIMING__clk100__WIDTH 1
+#define R_SDRAM_TIMING__clk100__on 1
+#define R_SDRAM_TIMING__clk100__off 0
+#define R_SDRAM_TIMING__ps__BITNR 11
+#define R_SDRAM_TIMING__ps__WIDTH 1
+#define R_SDRAM_TIMING__ps__on 1
+#define R_SDRAM_TIMING__ps__off 0
+#define R_SDRAM_TIMING__cmd__BITNR 9
+#define R_SDRAM_TIMING__cmd__WIDTH 2
+#define R_SDRAM_TIMING__cmd__pre 3
+#define R_SDRAM_TIMING__cmd__ref 2
+#define R_SDRAM_TIMING__cmd__mrs 1
+#define R_SDRAM_TIMING__cmd__nop 0
+#define R_SDRAM_TIMING__pde__BITNR 8
+#define R_SDRAM_TIMING__pde__WIDTH 1
+#define R_SDRAM_TIMING__rc__BITNR 6
+#define R_SDRAM_TIMING__rc__WIDTH 2
+#define R_SDRAM_TIMING__rp__BITNR 4
+#define R_SDRAM_TIMING__rp__WIDTH 2
+#define R_SDRAM_TIMING__rcd__BITNR 2
+#define R_SDRAM_TIMING__rcd__WIDTH 2
+#define R_SDRAM_TIMING__cl__BITNR 0
+#define R_SDRAM_TIMING__cl__WIDTH 2
+
+#define R_DRAM_CONFIG (IO_TYPECAST_UDWORD 0xb000000c)
+#define R_DRAM_CONFIG__wmm1__BITNR 31
+#define R_DRAM_CONFIG__wmm1__WIDTH 1
+#define R_DRAM_CONFIG__wmm1__wmm 1
+#define R_DRAM_CONFIG__wmm1__norm 0
+#define R_DRAM_CONFIG__wmm0__BITNR 30
+#define R_DRAM_CONFIG__wmm0__WIDTH 1
+#define R_DRAM_CONFIG__wmm0__wmm 1
+#define R_DRAM_CONFIG__wmm0__norm 0
+#define R_DRAM_CONFIG__sh1__BITNR 27
+#define R_DRAM_CONFIG__sh1__WIDTH 3
+#define R_DRAM_CONFIG__sh0__BITNR 24
+#define R_DRAM_CONFIG__sh0__WIDTH 3
+#define R_DRAM_CONFIG__w__BITNR 23
+#define R_DRAM_CONFIG__w__WIDTH 1
+#define R_DRAM_CONFIG__w__bw16 0
+#define R_DRAM_CONFIG__w__bw32 1
+#define R_DRAM_CONFIG__c__BITNR 22
+#define R_DRAM_CONFIG__c__WIDTH 1
+#define R_DRAM_CONFIG__c__byte 0
+#define R_DRAM_CONFIG__c__bank 1
+#define R_DRAM_CONFIG__e__BITNR 21
+#define R_DRAM_CONFIG__e__WIDTH 1
+#define R_DRAM_CONFIG__e__fast 0
+#define R_DRAM_CONFIG__e__edo 1
+#define R_DRAM_CONFIG__group_sel__BITNR 16
+#define R_DRAM_CONFIG__group_sel__WIDTH 5
+#define R_DRAM_CONFIG__group_sel__grp0 0
+#define R_DRAM_CONFIG__group_sel__grp1 1
+#define R_DRAM_CONFIG__group_sel__bit9 9
+#define R_DRAM_CONFIG__group_sel__bit10 10
+#define R_DRAM_CONFIG__group_sel__bit11 11
+#define R_DRAM_CONFIG__group_sel__bit12 12
+#define R_DRAM_CONFIG__group_sel__bit13 13
+#define R_DRAM_CONFIG__group_sel__bit14 14
+#define R_DRAM_CONFIG__group_sel__bit15 15
+#define R_DRAM_CONFIG__group_sel__bit16 16
+#define R_DRAM_CONFIG__group_sel__bit17 17
+#define R_DRAM_CONFIG__group_sel__bit18 18
+#define R_DRAM_CONFIG__group_sel__bit19 19
+#define R_DRAM_CONFIG__group_sel__bit20 20
+#define R_DRAM_CONFIG__group_sel__bit21 21
+#define R_DRAM_CONFIG__group_sel__bit22 22
+#define R_DRAM_CONFIG__group_sel__bit23 23
+#define R_DRAM_CONFIG__group_sel__bit24 24
+#define R_DRAM_CONFIG__group_sel__bit25 25
+#define R_DRAM_CONFIG__group_sel__bit26 26
+#define R_DRAM_CONFIG__group_sel__bit27 27
+#define R_DRAM_CONFIG__group_sel__bit28 28
+#define R_DRAM_CONFIG__group_sel__bit29 29
+#define R_DRAM_CONFIG__ca1__BITNR 13
+#define R_DRAM_CONFIG__ca1__WIDTH 3
+#define R_DRAM_CONFIG__bank23sel__BITNR 8
+#define R_DRAM_CONFIG__bank23sel__WIDTH 5
+#define R_DRAM_CONFIG__bank23sel__bank0 0
+#define R_DRAM_CONFIG__bank23sel__bank1 1
+#define R_DRAM_CONFIG__bank23sel__bit9 9
+#define R_DRAM_CONFIG__bank23sel__bit10 10
+#define R_DRAM_CONFIG__bank23sel__bit11 11
+#define R_DRAM_CONFIG__bank23sel__bit12 12
+#define R_DRAM_CONFIG__bank23sel__bit13 13
+#define R_DRAM_CONFIG__bank23sel__bit14 14
+#define R_DRAM_CONFIG__bank23sel__bit15 15
+#define R_DRAM_CONFIG__bank23sel__bit16 16
+#define R_DRAM_CONFIG__bank23sel__bit17 17
+#define R_DRAM_CONFIG__bank23sel__bit18 18
+#define R_DRAM_CONFIG__bank23sel__bit19 19
+#define R_DRAM_CONFIG__bank23sel__bit20 20
+#define R_DRAM_CONFIG__bank23sel__bit21 21
+#define R_DRAM_CONFIG__bank23sel__bit22 22
+#define R_DRAM_CONFIG__bank23sel__bit23 23
+#define R_DRAM_CONFIG__bank23sel__bit24 24
+#define R_DRAM_CONFIG__bank23sel__bit25 25
+#define R_DRAM_CONFIG__bank23sel__bit26 26
+#define R_DRAM_CONFIG__bank23sel__bit27 27
+#define R_DRAM_CONFIG__bank23sel__bit28 28
+#define R_DRAM_CONFIG__bank23sel__bit29 29
+#define R_DRAM_CONFIG__ca0__BITNR 5
+#define R_DRAM_CONFIG__ca0__WIDTH 3
+#define R_DRAM_CONFIG__bank01sel__BITNR 0
+#define R_DRAM_CONFIG__bank01sel__WIDTH 5
+#define R_DRAM_CONFIG__bank01sel__bank0 0
+#define R_DRAM_CONFIG__bank01sel__bank1 1
+#define R_DRAM_CONFIG__bank01sel__bit9 9
+#define R_DRAM_CONFIG__bank01sel__bit10 10
+#define R_DRAM_CONFIG__bank01sel__bit11 11
+#define R_DRAM_CONFIG__bank01sel__bit12 12
+#define R_DRAM_CONFIG__bank01sel__bit13 13
+#define R_DRAM_CONFIG__bank01sel__bit14 14
+#define R_DRAM_CONFIG__bank01sel__bit15 15
+#define R_DRAM_CONFIG__bank01sel__bit16 16
+#define R_DRAM_CONFIG__bank01sel__bit17 17
+#define R_DRAM_CONFIG__bank01sel__bit18 18
+#define R_DRAM_CONFIG__bank01sel__bit19 19
+#define R_DRAM_CONFIG__bank01sel__bit20 20
+#define R_DRAM_CONFIG__bank01sel__bit21 21
+#define R_DRAM_CONFIG__bank01sel__bit22 22
+#define R_DRAM_CONFIG__bank01sel__bit23 23
+#define R_DRAM_CONFIG__bank01sel__bit24 24
+#define R_DRAM_CONFIG__bank01sel__bit25 25
+#define R_DRAM_CONFIG__bank01sel__bit26 26
+#define R_DRAM_CONFIG__bank01sel__bit27 27
+#define R_DRAM_CONFIG__bank01sel__bit28 28
+#define R_DRAM_CONFIG__bank01sel__bit29 29
+
+#define R_SDRAM_CONFIG (IO_TYPECAST_UDWORD 0xb000000c)
+#define R_SDRAM_CONFIG__wmm1__BITNR 31
+#define R_SDRAM_CONFIG__wmm1__WIDTH 1
+#define R_SDRAM_CONFIG__wmm1__wmm 1
+#define R_SDRAM_CONFIG__wmm1__norm 0
+#define R_SDRAM_CONFIG__wmm0__BITNR 30
+#define R_SDRAM_CONFIG__wmm0__WIDTH 1
+#define R_SDRAM_CONFIG__wmm0__wmm 1
+#define R_SDRAM_CONFIG__wmm0__norm 0
+#define R_SDRAM_CONFIG__sh1__BITNR 27
+#define R_SDRAM_CONFIG__sh1__WIDTH 3
+#define R_SDRAM_CONFIG__sh0__BITNR 24
+#define R_SDRAM_CONFIG__sh0__WIDTH 3
+#define R_SDRAM_CONFIG__w__BITNR 23
+#define R_SDRAM_CONFIG__w__WIDTH 1
+#define R_SDRAM_CONFIG__w__bw16 0
+#define R_SDRAM_CONFIG__w__bw32 1
+#define R_SDRAM_CONFIG__type1__BITNR 22
+#define R_SDRAM_CONFIG__type1__WIDTH 1
+#define R_SDRAM_CONFIG__type1__bank2 0
+#define R_SDRAM_CONFIG__type1__bank4 1
+#define R_SDRAM_CONFIG__type0__BITNR 21
+#define R_SDRAM_CONFIG__type0__WIDTH 1
+#define R_SDRAM_CONFIG__type0__bank2 0
+#define R_SDRAM_CONFIG__type0__bank4 1
+#define R_SDRAM_CONFIG__group_sel__BITNR 16
+#define R_SDRAM_CONFIG__group_sel__WIDTH 5
+#define R_SDRAM_CONFIG__group_sel__grp0 0
+#define R_SDRAM_CONFIG__group_sel__grp1 1
+#define R_SDRAM_CONFIG__group_sel__bit9 9
+#define R_SDRAM_CONFIG__group_sel__bit10 10
+#define R_SDRAM_CONFIG__group_sel__bit11 11
+#define R_SDRAM_CONFIG__group_sel__bit12 12
+#define R_SDRAM_CONFIG__group_sel__bit13 13
+#define R_SDRAM_CONFIG__group_sel__bit14 14
+#define R_SDRAM_CONFIG__group_sel__bit15 15
+#define R_SDRAM_CONFIG__group_sel__bit16 16
+#define R_SDRAM_CONFIG__group_sel__bit17 17
+#define R_SDRAM_CONFIG__group_sel__bit18 18
+#define R_SDRAM_CONFIG__group_sel__bit19 19
+#define R_SDRAM_CONFIG__group_sel__bit20 20
+#define R_SDRAM_CONFIG__group_sel__bit21 21
+#define R_SDRAM_CONFIG__group_sel__bit22 22
+#define R_SDRAM_CONFIG__group_sel__bit23 23
+#define R_SDRAM_CONFIG__group_sel__bit24 24
+#define R_SDRAM_CONFIG__group_sel__bit25 25
+#define R_SDRAM_CONFIG__group_sel__bit26 26
+#define R_SDRAM_CONFIG__group_sel__bit27 27
+#define R_SDRAM_CONFIG__group_sel__bit28 28
+#define R_SDRAM_CONFIG__group_sel__bit29 29
+#define R_SDRAM_CONFIG__ca1__BITNR 13
+#define R_SDRAM_CONFIG__ca1__WIDTH 3
+#define R_SDRAM_CONFIG__bank_sel1__BITNR 8
+#define R_SDRAM_CONFIG__bank_sel1__WIDTH 5
+#define R_SDRAM_CONFIG__bank_sel1__bit9 9
+#define R_SDRAM_CONFIG__bank_sel1__bit10 10
+#define R_SDRAM_CONFIG__bank_sel1__bit11 11
+#define R_SDRAM_CONFIG__bank_sel1__bit12 12
+#define R_SDRAM_CONFIG__bank_sel1__bit13 13
+#define R_SDRAM_CONFIG__bank_sel1__bit14 14
+#define R_SDRAM_CONFIG__bank_sel1__bit15 15
+#define R_SDRAM_CONFIG__bank_sel1__bit16 16
+#define R_SDRAM_CONFIG__bank_sel1__bit17 17
+#define R_SDRAM_CONFIG__bank_sel1__bit18 18
+#define R_SDRAM_CONFIG__bank_sel1__bit19 19
+#define R_SDRAM_CONFIG__bank_sel1__bit20 20
+#define R_SDRAM_CONFIG__bank_sel1__bit21 21
+#define R_SDRAM_CONFIG__bank_sel1__bit22 22
+#define R_SDRAM_CONFIG__bank_sel1__bit23 23
+#define R_SDRAM_CONFIG__bank_sel1__bit24 24
+#define R_SDRAM_CONFIG__bank_sel1__bit25 25
+#define R_SDRAM_CONFIG__bank_sel1__bit26 26
+#define R_SDRAM_CONFIG__bank_sel1__bit27 27
+#define R_SDRAM_CONFIG__bank_sel1__bit28 28
+#define R_SDRAM_CONFIG__bank_sel1__bit29 29
+#define R_SDRAM_CONFIG__ca0__BITNR 5
+#define R_SDRAM_CONFIG__ca0__WIDTH 3
+#define R_SDRAM_CONFIG__bank_sel0__BITNR 0
+#define R_SDRAM_CONFIG__bank_sel0__WIDTH 5
+#define R_SDRAM_CONFIG__bank_sel0__bit9 9
+#define R_SDRAM_CONFIG__bank_sel0__bit10 10
+#define R_SDRAM_CONFIG__bank_sel0__bit11 11
+#define R_SDRAM_CONFIG__bank_sel0__bit12 12
+#define R_SDRAM_CONFIG__bank_sel0__bit13 13
+#define R_SDRAM_CONFIG__bank_sel0__bit14 14
+#define R_SDRAM_CONFIG__bank_sel0__bit15 15
+#define R_SDRAM_CONFIG__bank_sel0__bit16 16
+#define R_SDRAM_CONFIG__bank_sel0__bit17 17
+#define R_SDRAM_CONFIG__bank_sel0__bit18 18
+#define R_SDRAM_CONFIG__bank_sel0__bit19 19
+#define R_SDRAM_CONFIG__bank_sel0__bit20 20
+#define R_SDRAM_CONFIG__bank_sel0__bit21 21
+#define R_SDRAM_CONFIG__bank_sel0__bit22 22
+#define R_SDRAM_CONFIG__bank_sel0__bit23 23
+#define R_SDRAM_CONFIG__bank_sel0__bit24 24
+#define R_SDRAM_CONFIG__bank_sel0__bit25 25
+#define R_SDRAM_CONFIG__bank_sel0__bit26 26
+#define R_SDRAM_CONFIG__bank_sel0__bit27 27
+#define R_SDRAM_CONFIG__bank_sel0__bit28 28
+#define R_SDRAM_CONFIG__bank_sel0__bit29 29
+
+/*
+!* External DMA registers
+!*/
+
+#define R_EXT_DMA_0_CMD (IO_TYPECAST_UDWORD 0xb0000010)
+#define R_EXT_DMA_0_CMD__cnt__BITNR 23
+#define R_EXT_DMA_0_CMD__cnt__WIDTH 1
+#define R_EXT_DMA_0_CMD__cnt__enable 1
+#define R_EXT_DMA_0_CMD__cnt__disable 0
+#define R_EXT_DMA_0_CMD__rqpol__BITNR 22
+#define R_EXT_DMA_0_CMD__rqpol__WIDTH 1
+#define R_EXT_DMA_0_CMD__rqpol__ahigh 0
+#define R_EXT_DMA_0_CMD__rqpol__alow 1
+#define R_EXT_DMA_0_CMD__apol__BITNR 21
+#define R_EXT_DMA_0_CMD__apol__WIDTH 1
+#define R_EXT_DMA_0_CMD__apol__ahigh 0
+#define R_EXT_DMA_0_CMD__apol__alow 1
+#define R_EXT_DMA_0_CMD__rq_ack__BITNR 20
+#define R_EXT_DMA_0_CMD__rq_ack__WIDTH 1
+#define R_EXT_DMA_0_CMD__rq_ack__burst 0
+#define R_EXT_DMA_0_CMD__rq_ack__handsh 1
+#define R_EXT_DMA_0_CMD__wid__BITNR 18
+#define R_EXT_DMA_0_CMD__wid__WIDTH 2
+#define R_EXT_DMA_0_CMD__wid__byte 0
+#define R_EXT_DMA_0_CMD__wid__word 1
+#define R_EXT_DMA_0_CMD__wid__dword 2
+#define R_EXT_DMA_0_CMD__dir__BITNR 17
+#define R_EXT_DMA_0_CMD__dir__WIDTH 1
+#define R_EXT_DMA_0_CMD__dir__input 0
+#define R_EXT_DMA_0_CMD__dir__output 1
+#define R_EXT_DMA_0_CMD__run__BITNR 16
+#define R_EXT_DMA_0_CMD__run__WIDTH 1
+#define R_EXT_DMA_0_CMD__run__start 1
+#define R_EXT_DMA_0_CMD__run__stop 0
+#define R_EXT_DMA_0_CMD__trf_count__BITNR 0
+#define R_EXT_DMA_0_CMD__trf_count__WIDTH 16
+
+#define R_EXT_DMA_0_STAT (IO_TYPECAST_RO_UDWORD 0xb0000010)
+#define R_EXT_DMA_0_STAT__run__BITNR 16
+#define R_EXT_DMA_0_STAT__run__WIDTH 1
+#define R_EXT_DMA_0_STAT__run__start 1
+#define R_EXT_DMA_0_STAT__run__stop 0
+#define R_EXT_DMA_0_STAT__trf_count__BITNR 0
+#define R_EXT_DMA_0_STAT__trf_count__WIDTH 16
+
+#define R_EXT_DMA_0_ADDR (IO_TYPECAST_UDWORD 0xb0000014)
+#define R_EXT_DMA_0_ADDR__ext0_addr__BITNR 2
+#define R_EXT_DMA_0_ADDR__ext0_addr__WIDTH 28
+
+#define R_EXT_DMA_1_CMD (IO_TYPECAST_UDWORD 0xb0000018)
+#define R_EXT_DMA_1_CMD__cnt__BITNR 23
+#define R_EXT_DMA_1_CMD__cnt__WIDTH 1
+#define R_EXT_DMA_1_CMD__cnt__enable 1
+#define R_EXT_DMA_1_CMD__cnt__disable 0
+#define R_EXT_DMA_1_CMD__rqpol__BITNR 22
+#define R_EXT_DMA_1_CMD__rqpol__WIDTH 1
+#define R_EXT_DMA_1_CMD__rqpol__ahigh 0
+#define R_EXT_DMA_1_CMD__rqpol__alow 1
+#define R_EXT_DMA_1_CMD__apol__BITNR 21
+#define R_EXT_DMA_1_CMD__apol__WIDTH 1
+#define R_EXT_DMA_1_CMD__apol__ahigh 0
+#define R_EXT_DMA_1_CMD__apol__alow 1
+#define R_EXT_DMA_1_CMD__rq_ack__BITNR 20
+#define R_EXT_DMA_1_CMD__rq_ack__WIDTH 1
+#define R_EXT_DMA_1_CMD__rq_ack__burst 0
+#define R_EXT_DMA_1_CMD__rq_ack__handsh 1
+#define R_EXT_DMA_1_CMD__wid__BITNR 18
+#define R_EXT_DMA_1_CMD__wid__WIDTH 2
+#define R_EXT_DMA_1_CMD__wid__byte 0
+#define R_EXT_DMA_1_CMD__wid__word 1
+#define R_EXT_DMA_1_CMD__wid__dword 2
+#define R_EXT_DMA_1_CMD__dir__BITNR 17
+#define R_EXT_DMA_1_CMD__dir__WIDTH 1
+#define R_EXT_DMA_1_CMD__dir__input 0
+#define R_EXT_DMA_1_CMD__dir__output 1
+#define R_EXT_DMA_1_CMD__run__BITNR 16
+#define R_EXT_DMA_1_CMD__run__WIDTH 1
+#define R_EXT_DMA_1_CMD__run__start 1
+#define R_EXT_DMA_1_CMD__run__stop 0
+#define R_EXT_DMA_1_CMD__trf_count__BITNR 0
+#define R_EXT_DMA_1_CMD__trf_count__WIDTH 16
+
+#define R_EXT_DMA_1_STAT (IO_TYPECAST_RO_UDWORD 0xb0000018)
+#define R_EXT_DMA_1_STAT__run__BITNR 16
+#define R_EXT_DMA_1_STAT__run__WIDTH 1
+#define R_EXT_DMA_1_STAT__run__start 1
+#define R_EXT_DMA_1_STAT__run__stop 0
+#define R_EXT_DMA_1_STAT__trf_count__BITNR 0
+#define R_EXT_DMA_1_STAT__trf_count__WIDTH 16
+
+#define R_EXT_DMA_1_ADDR (IO_TYPECAST_UDWORD 0xb000001c)
+#define R_EXT_DMA_1_ADDR__ext0_addr__BITNR 2
+#define R_EXT_DMA_1_ADDR__ext0_addr__WIDTH 28
+
+/*
+!* Timer registers
+!*/
+
+#define R_TIMER_CTRL (IO_TYPECAST_UDWORD 0xb0000020)
+#define R_TIMER_CTRL__timerdiv1__BITNR 24
+#define R_TIMER_CTRL__timerdiv1__WIDTH 8
+#define R_TIMER_CTRL__timerdiv0__BITNR 16
+#define R_TIMER_CTRL__timerdiv0__WIDTH 8
+#define R_TIMER_CTRL__presc_timer1__BITNR 15
+#define R_TIMER_CTRL__presc_timer1__WIDTH 1
+#define R_TIMER_CTRL__presc_timer1__normal 0
+#define R_TIMER_CTRL__presc_timer1__prescale 1
+#define R_TIMER_CTRL__i1__BITNR 14
+#define R_TIMER_CTRL__i1__WIDTH 1
+#define R_TIMER_CTRL__i1__clr 1
+#define R_TIMER_CTRL__i1__nop 0
+#define R_TIMER_CTRL__tm1__BITNR 12
+#define R_TIMER_CTRL__tm1__WIDTH 2
+#define R_TIMER_CTRL__tm1__stop_ld 0
+#define R_TIMER_CTRL__tm1__freeze 1
+#define R_TIMER_CTRL__tm1__run 2
+#define R_TIMER_CTRL__tm1__reserved 3
+#define R_TIMER_CTRL__clksel1__BITNR 8
+#define R_TIMER_CTRL__clksel1__WIDTH 4
+#define R_TIMER_CTRL__clksel1__c300Hz 0
+#define R_TIMER_CTRL__clksel1__c600Hz 1
+#define R_TIMER_CTRL__clksel1__c1200Hz 2
+#define R_TIMER_CTRL__clksel1__c2400Hz 3
+#define R_TIMER_CTRL__clksel1__c4800Hz 4
+#define R_TIMER_CTRL__clksel1__c9600Hz 5
+#define R_TIMER_CTRL__clksel1__c19k2Hz 6
+#define R_TIMER_CTRL__clksel1__c38k4Hz 7
+#define R_TIMER_CTRL__clksel1__c57k6Hz 8
+#define R_TIMER_CTRL__clksel1__c115k2Hz 9
+#define R_TIMER_CTRL__clksel1__c230k4Hz 10
+#define R_TIMER_CTRL__clksel1__c460k8Hz 11
+#define R_TIMER_CTRL__clksel1__c921k6Hz 12
+#define R_TIMER_CTRL__clksel1__c1843k2Hz 13
+#define R_TIMER_CTRL__clksel1__c6250kHz 14
+#define R_TIMER_CTRL__clksel1__cascade0 15
+#define R_TIMER_CTRL__presc_ext__BITNR 7
+#define R_TIMER_CTRL__presc_ext__WIDTH 1
+#define R_TIMER_CTRL__presc_ext__prescale 0
+#define R_TIMER_CTRL__presc_ext__external 1
+#define R_TIMER_CTRL__i0__BITNR 6
+#define R_TIMER_CTRL__i0__WIDTH 1
+#define R_TIMER_CTRL__i0__clr 1
+#define R_TIMER_CTRL__i0__nop 0
+#define R_TIMER_CTRL__tm0__BITNR 4
+#define R_TIMER_CTRL__tm0__WIDTH 2
+#define R_TIMER_CTRL__tm0__stop_ld 0
+#define R_TIMER_CTRL__tm0__freeze 1
+#define R_TIMER_CTRL__tm0__run 2
+#define R_TIMER_CTRL__tm0__reserved 3
+#define R_TIMER_CTRL__clksel0__BITNR 0
+#define R_TIMER_CTRL__clksel0__WIDTH 4
+#define R_TIMER_CTRL__clksel0__c300Hz 0
+#define R_TIMER_CTRL__clksel0__c600Hz 1
+#define R_TIMER_CTRL__clksel0__c1200Hz 2
+#define R_TIMER_CTRL__clksel0__c2400Hz 3
+#define R_TIMER_CTRL__clksel0__c4800Hz 4
+#define R_TIMER_CTRL__clksel0__c9600Hz 5
+#define R_TIMER_CTRL__clksel0__c19k2Hz 6
+#define R_TIMER_CTRL__clksel0__c38k4Hz 7
+#define R_TIMER_CTRL__clksel0__c57k6Hz 8
+#define R_TIMER_CTRL__clksel0__c115k2Hz 9
+#define R_TIMER_CTRL__clksel0__c230k4Hz 10
+#define R_TIMER_CTRL__clksel0__c460k8Hz 11
+#define R_TIMER_CTRL__clksel0__c921k6Hz 12
+#define R_TIMER_CTRL__clksel0__c1843k2Hz 13
+#define R_TIMER_CTRL__clksel0__c6250kHz 14
+#define R_TIMER_CTRL__clksel0__flexible 15
+
+#define R_TIMER_DATA (IO_TYPECAST_RO_UDWORD 0xb0000020)
+#define R_TIMER_DATA__timer1__BITNR 24
+#define R_TIMER_DATA__timer1__WIDTH 8
+#define R_TIMER_DATA__timer0__BITNR 16
+#define R_TIMER_DATA__timer0__WIDTH 8
+#define R_TIMER_DATA__clkdiv_high__BITNR 8
+#define R_TIMER_DATA__clkdiv_high__WIDTH 8
+#define R_TIMER_DATA__clkdiv_low__BITNR 0
+#define R_TIMER_DATA__clkdiv_low__WIDTH 8
+
+#define R_TIMER01_DATA (IO_TYPECAST_RO_UWORD 0xb0000022)
+#define R_TIMER01_DATA__count__BITNR 0
+#define R_TIMER01_DATA__count__WIDTH 16
+
+#define R_TIMER0_DATA (IO_TYPECAST_RO_BYTE 0xb0000022)
+#define R_TIMER0_DATA__count__BITNR 0
+#define R_TIMER0_DATA__count__WIDTH 8
+
+#define R_TIMER1_DATA (IO_TYPECAST_RO_BYTE 0xb0000023)
+#define R_TIMER1_DATA__count__BITNR 0
+#define R_TIMER1_DATA__count__WIDTH 8
+
+#define R_WATCHDOG (IO_TYPECAST_UDWORD 0xb0000024)
+#define R_WATCHDOG__key__BITNR 1
+#define R_WATCHDOG__key__WIDTH 3
+#define R_WATCHDOG__enable__BITNR 0
+#define R_WATCHDOG__enable__WIDTH 1
+#define R_WATCHDOG__enable__stop 0
+#define R_WATCHDOG__enable__start 1
+
+#define R_CLOCK_PRESCALE (IO_TYPECAST_UDWORD 0xb00000f0)
+#define R_CLOCK_PRESCALE__ser_presc__BITNR 16
+#define R_CLOCK_PRESCALE__ser_presc__WIDTH 16
+#define R_CLOCK_PRESCALE__tim_presc__BITNR 0
+#define R_CLOCK_PRESCALE__tim_presc__WIDTH 16
+
+#define R_SERIAL_PRESCALE (IO_TYPECAST_UWORD 0xb00000f2)
+#define R_SERIAL_PRESCALE__ser_presc__BITNR 0
+#define R_SERIAL_PRESCALE__ser_presc__WIDTH 16
+
+#define R_TIMER_PRESCALE (IO_TYPECAST_UWORD 0xb00000f0)
+#define R_TIMER_PRESCALE__tim_presc__BITNR 0
+#define R_TIMER_PRESCALE__tim_presc__WIDTH 16
+
+#define R_PRESCALE_STATUS (IO_TYPECAST_RO_UDWORD 0xb00000f0)
+#define R_PRESCALE_STATUS__ser_status__BITNR 16
+#define R_PRESCALE_STATUS__ser_status__WIDTH 16
+#define R_PRESCALE_STATUS__tim_status__BITNR 0
+#define R_PRESCALE_STATUS__tim_status__WIDTH 16
+
+#define R_SER_PRESC_STATUS (IO_TYPECAST_RO_UWORD 0xb00000f2)
+#define R_SER_PRESC_STATUS__ser_status__BITNR 0
+#define R_SER_PRESC_STATUS__ser_status__WIDTH 16
+
+#define R_TIM_PRESC_STATUS (IO_TYPECAST_RO_UWORD 0xb00000f0)
+#define R_TIM_PRESC_STATUS__tim_status__BITNR 0
+#define R_TIM_PRESC_STATUS__tim_status__WIDTH 16
+
+#define R_SYNC_SERIAL_PRESCALE (IO_TYPECAST_UDWORD 0xb00000f4)
+#define R_SYNC_SERIAL_PRESCALE__clk_sel_u3__BITNR 23
+#define R_SYNC_SERIAL_PRESCALE__clk_sel_u3__WIDTH 1
+#define R_SYNC_SERIAL_PRESCALE__clk_sel_u3__codec 0
+#define R_SYNC_SERIAL_PRESCALE__clk_sel_u3__baudrate 1
+#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u3__BITNR 22
+#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u3__WIDTH 1
+#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u3__external 0
+#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u3__internal 1
+#define R_SYNC_SERIAL_PRESCALE__clk_sel_u1__BITNR 21
+#define R_SYNC_SERIAL_PRESCALE__clk_sel_u1__WIDTH 1
+#define R_SYNC_SERIAL_PRESCALE__clk_sel_u1__codec 0
+#define R_SYNC_SERIAL_PRESCALE__clk_sel_u1__baudrate 1
+#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u1__BITNR 20
+#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u1__WIDTH 1
+#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u1__external 0
+#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u1__internal 1
+#define R_SYNC_SERIAL_PRESCALE__prescaler__BITNR 16
+#define R_SYNC_SERIAL_PRESCALE__prescaler__WIDTH 3
+#define R_SYNC_SERIAL_PRESCALE__prescaler__div1 0
+#define R_SYNC_SERIAL_PRESCALE__prescaler__div2 1
+#define R_SYNC_SERIAL_PRESCALE__prescaler__div4 2
+#define R_SYNC_SERIAL_PRESCALE__prescaler__div8 3
+#define R_SYNC_SERIAL_PRESCALE__prescaler__div16 4
+#define R_SYNC_SERIAL_PRESCALE__prescaler__div32 5
+#define R_SYNC_SERIAL_PRESCALE__prescaler__div64 6
+#define R_SYNC_SERIAL_PRESCALE__prescaler__div128 7
+#define R_SYNC_SERIAL_PRESCALE__warp_mode__BITNR 15
+#define R_SYNC_SERIAL_PRESCALE__warp_mode__WIDTH 1
+#define R_SYNC_SERIAL_PRESCALE__warp_mode__normal 0
+#define R_SYNC_SERIAL_PRESCALE__warp_mode__enabled 1
+#define R_SYNC_SERIAL_PRESCALE__frame_rate__BITNR 11
+#define R_SYNC_SERIAL_PRESCALE__frame_rate__WIDTH 4
+#define R_SYNC_SERIAL_PRESCALE__word_rate__BITNR 0
+#define R_SYNC_SERIAL_PRESCALE__word_rate__WIDTH 10
+
+/*
+!* Shared RAM interface registers
+!*/
+
+#define R_SHARED_RAM_CONFIG (IO_TYPECAST_UDWORD 0xb0000040)
+#define R_SHARED_RAM_CONFIG__width__BITNR 3
+#define R_SHARED_RAM_CONFIG__width__WIDTH 1
+#define R_SHARED_RAM_CONFIG__width__byte 0
+#define R_SHARED_RAM_CONFIG__width__word 1
+#define R_SHARED_RAM_CONFIG__enable__BITNR 2
+#define R_SHARED_RAM_CONFIG__enable__WIDTH 1
+#define R_SHARED_RAM_CONFIG__enable__yes 1
+#define R_SHARED_RAM_CONFIG__enable__no 0
+#define R_SHARED_RAM_CONFIG__pint__BITNR 1
+#define R_SHARED_RAM_CONFIG__pint__WIDTH 1
+#define R_SHARED_RAM_CONFIG__pint__int 1
+#define R_SHARED_RAM_CONFIG__pint__nop 0
+#define R_SHARED_RAM_CONFIG__clri__BITNR 0
+#define R_SHARED_RAM_CONFIG__clri__WIDTH 1
+#define R_SHARED_RAM_CONFIG__clri__clr 1
+#define R_SHARED_RAM_CONFIG__clri__nop 0
+
+#define R_SHARED_RAM_ADDR (IO_TYPECAST_UDWORD 0xb0000044)
+#define R_SHARED_RAM_ADDR__base_addr__BITNR 8
+#define R_SHARED_RAM_ADDR__base_addr__WIDTH 22
+
+/*
+!* General config registers
+!*/
+
+#define R_GEN_CONFIG (IO_TYPECAST_UDWORD 0xb000002c)
+#define R_GEN_CONFIG__par_w__BITNR 31
+#define R_GEN_CONFIG__par_w__WIDTH 1
+#define R_GEN_CONFIG__par_w__select 1
+#define R_GEN_CONFIG__par_w__disable 0
+#define R_GEN_CONFIG__usb2__BITNR 30
+#define R_GEN_CONFIG__usb2__WIDTH 1
+#define R_GEN_CONFIG__usb2__select 1
+#define R_GEN_CONFIG__usb2__disable 0
+#define R_GEN_CONFIG__usb1__BITNR 29
+#define R_GEN_CONFIG__usb1__WIDTH 1
+#define R_GEN_CONFIG__usb1__select 1
+#define R_GEN_CONFIG__usb1__disable 0
+#define R_GEN_CONFIG__g24dir__BITNR 27
+#define R_GEN_CONFIG__g24dir__WIDTH 1
+#define R_GEN_CONFIG__g24dir__in 0
+#define R_GEN_CONFIG__g24dir__out 1
+#define R_GEN_CONFIG__g16_23dir__BITNR 26
+#define R_GEN_CONFIG__g16_23dir__WIDTH 1
+#define R_GEN_CONFIG__g16_23dir__in 0
+#define R_GEN_CONFIG__g16_23dir__out 1
+#define R_GEN_CONFIG__g8_15dir__BITNR 25
+#define R_GEN_CONFIG__g8_15dir__WIDTH 1
+#define R_GEN_CONFIG__g8_15dir__in 0
+#define R_GEN_CONFIG__g8_15dir__out 1
+#define R_GEN_CONFIG__g0dir__BITNR 24
+#define R_GEN_CONFIG__g0dir__WIDTH 1
+#define R_GEN_CONFIG__g0dir__in 0
+#define R_GEN_CONFIG__g0dir__out 1
+#define R_GEN_CONFIG__dma9__BITNR 23
+#define R_GEN_CONFIG__dma9__WIDTH 1
+#define R_GEN_CONFIG__dma9__usb 0
+#define R_GEN_CONFIG__dma9__serial1 1
+#define R_GEN_CONFIG__dma8__BITNR 22
+#define R_GEN_CONFIG__dma8__WIDTH 1
+#define R_GEN_CONFIG__dma8__usb 0
+#define R_GEN_CONFIG__dma8__serial1 1
+#define R_GEN_CONFIG__dma7__BITNR 20
+#define R_GEN_CONFIG__dma7__WIDTH 2
+#define R_GEN_CONFIG__dma7__unused 0
+#define R_GEN_CONFIG__dma7__serial0 1
+#define R_GEN_CONFIG__dma7__extdma1 2
+#define R_GEN_CONFIG__dma7__intdma6 3
+#define R_GEN_CONFIG__dma6__BITNR 18
+#define R_GEN_CONFIG__dma6__WIDTH 2
+#define R_GEN_CONFIG__dma6__unused 0
+#define R_GEN_CONFIG__dma6__serial0 1
+#define R_GEN_CONFIG__dma6__extdma1 2
+#define R_GEN_CONFIG__dma6__intdma7 3
+#define R_GEN_CONFIG__dma5__BITNR 16
+#define R_GEN_CONFIG__dma5__WIDTH 2
+#define R_GEN_CONFIG__dma5__par1 0
+#define R_GEN_CONFIG__dma5__scsi1 1
+#define R_GEN_CONFIG__dma5__serial3 2
+#define R_GEN_CONFIG__dma5__extdma0 3
+#define R_GEN_CONFIG__dma4__BITNR 14
+#define R_GEN_CONFIG__dma4__WIDTH 2
+#define R_GEN_CONFIG__dma4__par1 0
+#define R_GEN_CONFIG__dma4__scsi1 1
+#define R_GEN_CONFIG__dma4__serial3 2
+#define R_GEN_CONFIG__dma4__extdma0 3
+#define R_GEN_CONFIG__dma3__BITNR 12
+#define R_GEN_CONFIG__dma3__WIDTH 2
+#define R_GEN_CONFIG__dma3__par0 0
+#define R_GEN_CONFIG__dma3__scsi0 1
+#define R_GEN_CONFIG__dma3__serial2 2
+#define R_GEN_CONFIG__dma3__ata 3
+#define R_GEN_CONFIG__dma2__BITNR 10
+#define R_GEN_CONFIG__dma2__WIDTH 2
+#define R_GEN_CONFIG__dma2__par0 0
+#define R_GEN_CONFIG__dma2__scsi0 1
+#define R_GEN_CONFIG__dma2__serial2 2
+#define R_GEN_CONFIG__dma2__ata 3
+#define R_GEN_CONFIG__mio_w__BITNR 9
+#define R_GEN_CONFIG__mio_w__WIDTH 1
+#define R_GEN_CONFIG__mio_w__select 1
+#define R_GEN_CONFIG__mio_w__disable 0
+#define R_GEN_CONFIG__ser3__BITNR 8
+#define R_GEN_CONFIG__ser3__WIDTH 1
+#define R_GEN_CONFIG__ser3__select 1
+#define R_GEN_CONFIG__ser3__disable 0
+#define R_GEN_CONFIG__par1__BITNR 7
+#define R_GEN_CONFIG__par1__WIDTH 1
+#define R_GEN_CONFIG__par1__select 1
+#define R_GEN_CONFIG__par1__disable 0
+#define R_GEN_CONFIG__scsi0w__BITNR 6
+#define R_GEN_CONFIG__scsi0w__WIDTH 1
+#define R_GEN_CONFIG__scsi0w__select 1
+#define R_GEN_CONFIG__scsi0w__disable 0
+#define R_GEN_CONFIG__scsi1__BITNR 5
+#define R_GEN_CONFIG__scsi1__WIDTH 1
+#define R_GEN_CONFIG__scsi1__select 1
+#define R_GEN_CONFIG__scsi1__disable 0
+#define R_GEN_CONFIG__mio__BITNR 4
+#define R_GEN_CONFIG__mio__WIDTH 1
+#define R_GEN_CONFIG__mio__select 1
+#define R_GEN_CONFIG__mio__disable 0
+#define R_GEN_CONFIG__ser2__BITNR 3
+#define R_GEN_CONFIG__ser2__WIDTH 1
+#define R_GEN_CONFIG__ser2__select 1
+#define R_GEN_CONFIG__ser2__disable 0
+#define R_GEN_CONFIG__par0__BITNR 2
+#define R_GEN_CONFIG__par0__WIDTH 1
+#define R_GEN_CONFIG__par0__select 1
+#define R_GEN_CONFIG__par0__disable 0
+#define R_GEN_CONFIG__ata__BITNR 1
+#define R_GEN_CONFIG__ata__WIDTH 1
+#define R_GEN_CONFIG__ata__select 1
+#define R_GEN_CONFIG__ata__disable 0
+#define R_GEN_CONFIG__scsi0__BITNR 0
+#define R_GEN_CONFIG__scsi0__WIDTH 1
+#define R_GEN_CONFIG__scsi0__select 1
+#define R_GEN_CONFIG__scsi0__disable 0
+
+#define R_GEN_CONFIG_II (IO_TYPECAST_UDWORD 0xb0000034)
+#define R_GEN_CONFIG_II__sermode3__BITNR 6
+#define R_GEN_CONFIG_II__sermode3__WIDTH 1
+#define R_GEN_CONFIG_II__sermode3__async 0
+#define R_GEN_CONFIG_II__sermode3__sync 1
+#define R_GEN_CONFIG_II__sermode1__BITNR 4
+#define R_GEN_CONFIG_II__sermode1__WIDTH 1
+#define R_GEN_CONFIG_II__sermode1__async 0
+#define R_GEN_CONFIG_II__sermode1__sync 1
+#define R_GEN_CONFIG_II__ext_clk__BITNR 2
+#define R_GEN_CONFIG_II__ext_clk__WIDTH 1
+#define R_GEN_CONFIG_II__ext_clk__select 1
+#define R_GEN_CONFIG_II__ext_clk__disable 0
+#define R_GEN_CONFIG_II__ser2__BITNR 1
+#define R_GEN_CONFIG_II__ser2__WIDTH 1
+#define R_GEN_CONFIG_II__ser2__select 1
+#define R_GEN_CONFIG_II__ser2__disable 0
+#define R_GEN_CONFIG_II__ser3__BITNR 0
+#define R_GEN_CONFIG_II__ser3__WIDTH 1
+#define R_GEN_CONFIG_II__ser3__select 1
+#define R_GEN_CONFIG_II__ser3__disable 0
+
+#define R_PORT_G_DATA (IO_TYPECAST_UDWORD 0xb0000028)
+#define R_PORT_G_DATA__data__BITNR 0
+#define R_PORT_G_DATA__data__WIDTH 32
+
+/*
+!* General port configuration registers
+!*/
+
+#define R_PORT_PA_SET (IO_TYPECAST_UDWORD 0xb0000030)
+#define R_PORT_PA_SET__dir7__BITNR 15
+#define R_PORT_PA_SET__dir7__WIDTH 1
+#define R_PORT_PA_SET__dir7__input 0
+#define R_PORT_PA_SET__dir7__output 1
+#define R_PORT_PA_SET__dir6__BITNR 14
+#define R_PORT_PA_SET__dir6__WIDTH 1
+#define R_PORT_PA_SET__dir6__input 0
+#define R_PORT_PA_SET__dir6__output 1
+#define R_PORT_PA_SET__dir5__BITNR 13
+#define R_PORT_PA_SET__dir5__WIDTH 1
+#define R_PORT_PA_SET__dir5__input 0
+#define R_PORT_PA_SET__dir5__output 1
+#define R_PORT_PA_SET__dir4__BITNR 12
+#define R_PORT_PA_SET__dir4__WIDTH 1
+#define R_PORT_PA_SET__dir4__input 0
+#define R_PORT_PA_SET__dir4__output 1
+#define R_PORT_PA_SET__dir3__BITNR 11
+#define R_PORT_PA_SET__dir3__WIDTH 1
+#define R_PORT_PA_SET__dir3__input 0
+#define R_PORT_PA_SET__dir3__output 1
+#define R_PORT_PA_SET__dir2__BITNR 10
+#define R_PORT_PA_SET__dir2__WIDTH 1
+#define R_PORT_PA_SET__dir2__input 0
+#define R_PORT_PA_SET__dir2__output 1
+#define R_PORT_PA_SET__dir1__BITNR 9
+#define R_PORT_PA_SET__dir1__WIDTH 1
+#define R_PORT_PA_SET__dir1__input 0
+#define R_PORT_PA_SET__dir1__output 1
+#define R_PORT_PA_SET__dir0__BITNR 8
+#define R_PORT_PA_SET__dir0__WIDTH 1
+#define R_PORT_PA_SET__dir0__input 0
+#define R_PORT_PA_SET__dir0__output 1
+#define R_PORT_PA_SET__data_out__BITNR 0
+#define R_PORT_PA_SET__data_out__WIDTH 8
+
+#define R_PORT_PA_DATA (IO_TYPECAST_BYTE 0xb0000030)
+#define R_PORT_PA_DATA__data_out__BITNR 0
+#define R_PORT_PA_DATA__data_out__WIDTH 8
+
+#define R_PORT_PA_DIR (IO_TYPECAST_BYTE 0xb0000031)
+#define R_PORT_PA_DIR__dir7__BITNR 7
+#define R_PORT_PA_DIR__dir7__WIDTH 1
+#define R_PORT_PA_DIR__dir7__input 0
+#define R_PORT_PA_DIR__dir7__output 1
+#define R_PORT_PA_DIR__dir6__BITNR 6
+#define R_PORT_PA_DIR__dir6__WIDTH 1
+#define R_PORT_PA_DIR__dir6__input 0
+#define R_PORT_PA_DIR__dir6__output 1
+#define R_PORT_PA_DIR__dir5__BITNR 5
+#define R_PORT_PA_DIR__dir5__WIDTH 1
+#define R_PORT_PA_DIR__dir5__input 0
+#define R_PORT_PA_DIR__dir5__output 1
+#define R_PORT_PA_DIR__dir4__BITNR 4
+#define R_PORT_PA_DIR__dir4__WIDTH 1
+#define R_PORT_PA_DIR__dir4__input 0
+#define R_PORT_PA_DIR__dir4__output 1
+#define R_PORT_PA_DIR__dir3__BITNR 3
+#define R_PORT_PA_DIR__dir3__WIDTH 1
+#define R_PORT_PA_DIR__dir3__input 0
+#define R_PORT_PA_DIR__dir3__output 1
+#define R_PORT_PA_DIR__dir2__BITNR 2
+#define R_PORT_PA_DIR__dir2__WIDTH 1
+#define R_PORT_PA_DIR__dir2__input 0
+#define R_PORT_PA_DIR__dir2__output 1
+#define R_PORT_PA_DIR__dir1__BITNR 1
+#define R_PORT_PA_DIR__dir1__WIDTH 1
+#define R_PORT_PA_DIR__dir1__input 0
+#define R_PORT_PA_DIR__dir1__output 1
+#define R_PORT_PA_DIR__dir0__BITNR 0
+#define R_PORT_PA_DIR__dir0__WIDTH 1
+#define R_PORT_PA_DIR__dir0__input 0
+#define R_PORT_PA_DIR__dir0__output 1
+
+#define R_PORT_PA_READ (IO_TYPECAST_RO_UDWORD 0xb0000030)
+#define R_PORT_PA_READ__data_in__BITNR 0
+#define R_PORT_PA_READ__data_in__WIDTH 8
+
+#define R_PORT_PB_SET (IO_TYPECAST_UDWORD 0xb0000038)
+#define R_PORT_PB_SET__syncser3__BITNR 29
+#define R_PORT_PB_SET__syncser3__WIDTH 1
+#define R_PORT_PB_SET__syncser3__port_cs 0
+#define R_PORT_PB_SET__syncser3__ss3extra 1
+#define R_PORT_PB_SET__syncser1__BITNR 28
+#define R_PORT_PB_SET__syncser1__WIDTH 1
+#define R_PORT_PB_SET__syncser1__port_cs 0
+#define R_PORT_PB_SET__syncser1__ss1extra 1
+#define R_PORT_PB_SET__i2c_en__BITNR 27
+#define R_PORT_PB_SET__i2c_en__WIDTH 1
+#define R_PORT_PB_SET__i2c_en__off 0
+#define R_PORT_PB_SET__i2c_en__on 1
+#define R_PORT_PB_SET__i2c_d__BITNR 26
+#define R_PORT_PB_SET__i2c_d__WIDTH 1
+#define R_PORT_PB_SET__i2c_clk__BITNR 25
+#define R_PORT_PB_SET__i2c_clk__WIDTH 1
+#define R_PORT_PB_SET__i2c_oe___BITNR 24
+#define R_PORT_PB_SET__i2c_oe___WIDTH 1
+#define R_PORT_PB_SET__i2c_oe___enable 0
+#define R_PORT_PB_SET__i2c_oe___disable 1
+#define R_PORT_PB_SET__cs7__BITNR 23
+#define R_PORT_PB_SET__cs7__WIDTH 1
+#define R_PORT_PB_SET__cs7__port 0
+#define R_PORT_PB_SET__cs7__cs 1
+#define R_PORT_PB_SET__cs6__BITNR 22
+#define R_PORT_PB_SET__cs6__WIDTH 1
+#define R_PORT_PB_SET__cs6__port 0
+#define R_PORT_PB_SET__cs6__cs 1
+#define R_PORT_PB_SET__cs5__BITNR 21
+#define R_PORT_PB_SET__cs5__WIDTH 1
+#define R_PORT_PB_SET__cs5__port 0
+#define R_PORT_PB_SET__cs5__cs 1
+#define R_PORT_PB_SET__cs4__BITNR 20
+#define R_PORT_PB_SET__cs4__WIDTH 1
+#define R_PORT_PB_SET__cs4__port 0
+#define R_PORT_PB_SET__cs4__cs 1
+#define R_PORT_PB_SET__cs3__BITNR 19
+#define R_PORT_PB_SET__cs3__WIDTH 1
+#define R_PORT_PB_SET__cs3__port 0
+#define R_PORT_PB_SET__cs3__cs 1
+#define R_PORT_PB_SET__cs2__BITNR 18
+#define R_PORT_PB_SET__cs2__WIDTH 1
+#define R_PORT_PB_SET__cs2__port 0
+#define R_PORT_PB_SET__cs2__cs 1
+#define R_PORT_PB_SET__scsi1__BITNR 17
+#define R_PORT_PB_SET__scsi1__WIDTH 1
+#define R_PORT_PB_SET__scsi1__port_cs 0
+#define R_PORT_PB_SET__scsi1__enph 1
+#define R_PORT_PB_SET__scsi0__BITNR 16
+#define R_PORT_PB_SET__scsi0__WIDTH 1
+#define R_PORT_PB_SET__scsi0__port_cs 0
+#define R_PORT_PB_SET__scsi0__enph 1
+#define R_PORT_PB_SET__dir7__BITNR 15
+#define R_PORT_PB_SET__dir7__WIDTH 1
+#define R_PORT_PB_SET__dir7__input 0
+#define R_PORT_PB_SET__dir7__output 1
+#define R_PORT_PB_SET__dir6__BITNR 14
+#define R_PORT_PB_SET__dir6__WIDTH 1
+#define R_PORT_PB_SET__dir6__input 0
+#define R_PORT_PB_SET__dir6__output 1
+#define R_PORT_PB_SET__dir5__BITNR 13
+#define R_PORT_PB_SET__dir5__WIDTH 1
+#define R_PORT_PB_SET__dir5__input 0
+#define R_PORT_PB_SET__dir5__output 1
+#define R_PORT_PB_SET__dir4__BITNR 12
+#define R_PORT_PB_SET__dir4__WIDTH 1
+#define R_PORT_PB_SET__dir4__input 0
+#define R_PORT_PB_SET__dir4__output 1
+#define R_PORT_PB_SET__dir3__BITNR 11
+#define R_PORT_PB_SET__dir3__WIDTH 1
+#define R_PORT_PB_SET__dir3__input 0
+#define R_PORT_PB_SET__dir3__output 1
+#define R_PORT_PB_SET__dir2__BITNR 10
+#define R_PORT_PB_SET__dir2__WIDTH 1
+#define R_PORT_PB_SET__dir2__input 0
+#define R_PORT_PB_SET__dir2__output 1
+#define R_PORT_PB_SET__dir1__BITNR 9
+#define R_PORT_PB_SET__dir1__WIDTH 1
+#define R_PORT_PB_SET__dir1__input 0
+#define R_PORT_PB_SET__dir1__output 1
+#define R_PORT_PB_SET__dir0__BITNR 8
+#define R_PORT_PB_SET__dir0__WIDTH 1
+#define R_PORT_PB_SET__dir0__input 0
+#define R_PORT_PB_SET__dir0__output 1
+#define R_PORT_PB_SET__data_out__BITNR 0
+#define R_PORT_PB_SET__data_out__WIDTH 8
+
+#define R_PORT_PB_DATA (IO_TYPECAST_BYTE 0xb0000038)
+#define R_PORT_PB_DATA__data_out__BITNR 0
+#define R_PORT_PB_DATA__data_out__WIDTH 8
+
+#define R_PORT_PB_DIR (IO_TYPECAST_BYTE 0xb0000039)
+#define R_PORT_PB_DIR__dir7__BITNR 7
+#define R_PORT_PB_DIR__dir7__WIDTH 1
+#define R_PORT_PB_DIR__dir7__input 0
+#define R_PORT_PB_DIR__dir7__output 1
+#define R_PORT_PB_DIR__dir6__BITNR 6
+#define R_PORT_PB_DIR__dir6__WIDTH 1
+#define R_PORT_PB_DIR__dir6__input 0
+#define R_PORT_PB_DIR__dir6__output 1
+#define R_PORT_PB_DIR__dir5__BITNR 5
+#define R_PORT_PB_DIR__dir5__WIDTH 1
+#define R_PORT_PB_DIR__dir5__input 0
+#define R_PORT_PB_DIR__dir5__output 1
+#define R_PORT_PB_DIR__dir4__BITNR 4
+#define R_PORT_PB_DIR__dir4__WIDTH 1
+#define R_PORT_PB_DIR__dir4__input 0
+#define R_PORT_PB_DIR__dir4__output 1
+#define R_PORT_PB_DIR__dir3__BITNR 3
+#define R_PORT_PB_DIR__dir3__WIDTH 1
+#define R_PORT_PB_DIR__dir3__input 0
+#define R_PORT_PB_DIR__dir3__output 1
+#define R_PORT_PB_DIR__dir2__BITNR 2
+#define R_PORT_PB_DIR__dir2__WIDTH 1
+#define R_PORT_PB_DIR__dir2__input 0
+#define R_PORT_PB_DIR__dir2__output 1
+#define R_PORT_PB_DIR__dir1__BITNR 1
+#define R_PORT_PB_DIR__dir1__WIDTH 1
+#define R_PORT_PB_DIR__dir1__input 0
+#define R_PORT_PB_DIR__dir1__output 1
+#define R_PORT_PB_DIR__dir0__BITNR 0
+#define R_PORT_PB_DIR__dir0__WIDTH 1
+#define R_PORT_PB_DIR__dir0__input 0
+#define R_PORT_PB_DIR__dir0__output 1
+
+#define R_PORT_PB_CONFIG (IO_TYPECAST_BYTE 0xb000003a)
+#define R_PORT_PB_CONFIG__cs7__BITNR 7
+#define R_PORT_PB_CONFIG__cs7__WIDTH 1
+#define R_PORT_PB_CONFIG__cs7__port 0
+#define R_PORT_PB_CONFIG__cs7__cs 1
+#define R_PORT_PB_CONFIG__cs6__BITNR 6
+#define R_PORT_PB_CONFIG__cs6__WIDTH 1
+#define R_PORT_PB_CONFIG__cs6__port 0
+#define R_PORT_PB_CONFIG__cs6__cs 1
+#define R_PORT_PB_CONFIG__cs5__BITNR 5
+#define R_PORT_PB_CONFIG__cs5__WIDTH 1
+#define R_PORT_PB_CONFIG__cs5__port 0
+#define R_PORT_PB_CONFIG__cs5__cs 1
+#define R_PORT_PB_CONFIG__cs4__BITNR 4
+#define R_PORT_PB_CONFIG__cs4__WIDTH 1
+#define R_PORT_PB_CONFIG__cs4__port 0
+#define R_PORT_PB_CONFIG__cs4__cs 1
+#define R_PORT_PB_CONFIG__cs3__BITNR 3
+#define R_PORT_PB_CONFIG__cs3__WIDTH 1
+#define R_PORT_PB_CONFIG__cs3__port 0
+#define R_PORT_PB_CONFIG__cs3__cs 1
+#define R_PORT_PB_CONFIG__cs2__BITNR 2
+#define R_PORT_PB_CONFIG__cs2__WIDTH 1
+#define R_PORT_PB_CONFIG__cs2__port 0
+#define R_PORT_PB_CONFIG__cs2__cs 1
+#define R_PORT_PB_CONFIG__scsi1__BITNR 1
+#define R_PORT_PB_CONFIG__scsi1__WIDTH 1
+#define R_PORT_PB_CONFIG__scsi1__port_cs 0
+#define R_PORT_PB_CONFIG__scsi1__enph 1
+#define R_PORT_PB_CONFIG__scsi0__BITNR 0
+#define R_PORT_PB_CONFIG__scsi0__WIDTH 1
+#define R_PORT_PB_CONFIG__scsi0__port_cs 0
+#define R_PORT_PB_CONFIG__scsi0__enph 1
+
+#define R_PORT_PB_I2C (IO_TYPECAST_BYTE 0xb000003b)
+#define R_PORT_PB_I2C__syncser3__BITNR 5
+#define R_PORT_PB_I2C__syncser3__WIDTH 1
+#define R_PORT_PB_I2C__syncser3__port_cs 0
+#define R_PORT_PB_I2C__syncser3__ss3extra 1
+#define R_PORT_PB_I2C__syncser1__BITNR 4
+#define R_PORT_PB_I2C__syncser1__WIDTH 1
+#define R_PORT_PB_I2C__syncser1__port_cs 0
+#define R_PORT_PB_I2C__syncser1__ss1extra 1
+#define R_PORT_PB_I2C__i2c_en__BITNR 3
+#define R_PORT_PB_I2C__i2c_en__WIDTH 1
+#define R_PORT_PB_I2C__i2c_en__off 0
+#define R_PORT_PB_I2C__i2c_en__on 1
+#define R_PORT_PB_I2C__i2c_d__BITNR 2
+#define R_PORT_PB_I2C__i2c_d__WIDTH 1
+#define R_PORT_PB_I2C__i2c_clk__BITNR 1
+#define R_PORT_PB_I2C__i2c_clk__WIDTH 1
+#define R_PORT_PB_I2C__i2c_oe___BITNR 0
+#define R_PORT_PB_I2C__i2c_oe___WIDTH 1
+#define R_PORT_PB_I2C__i2c_oe___enable 0
+#define R_PORT_PB_I2C__i2c_oe___disable 1
+
+#define R_PORT_PB_READ (IO_TYPECAST_RO_UDWORD 0xb0000038)
+#define R_PORT_PB_READ__data_in__BITNR 0
+#define R_PORT_PB_READ__data_in__WIDTH 8
+
+/*
+!* Serial port registers
+!*/
+
+#define R_SERIAL0_CTRL (IO_TYPECAST_UDWORD 0xb0000060)
+#define R_SERIAL0_CTRL__tr_baud__BITNR 28
+#define R_SERIAL0_CTRL__tr_baud__WIDTH 4
+#define R_SERIAL0_CTRL__tr_baud__c300Hz 0
+#define R_SERIAL0_CTRL__tr_baud__c600Hz 1
+#define R_SERIAL0_CTRL__tr_baud__c1200Hz 2
+#define R_SERIAL0_CTRL__tr_baud__c2400Hz 3
+#define R_SERIAL0_CTRL__tr_baud__c4800Hz 4
+#define R_SERIAL0_CTRL__tr_baud__c9600Hz 5
+#define R_SERIAL0_CTRL__tr_baud__c19k2Hz 6
+#define R_SERIAL0_CTRL__tr_baud__c38k4Hz 7
+#define R_SERIAL0_CTRL__tr_baud__c57k6Hz 8
+#define R_SERIAL0_CTRL__tr_baud__c115k2Hz 9
+#define R_SERIAL0_CTRL__tr_baud__c230k4Hz 10
+#define R_SERIAL0_CTRL__tr_baud__c460k8Hz 11
+#define R_SERIAL0_CTRL__tr_baud__c921k6Hz 12
+#define R_SERIAL0_CTRL__tr_baud__c1843k2Hz 13
+#define R_SERIAL0_CTRL__tr_baud__c6250kHz 14
+#define R_SERIAL0_CTRL__tr_baud__reserved 15
+#define R_SERIAL0_CTRL__rec_baud__BITNR 24
+#define R_SERIAL0_CTRL__rec_baud__WIDTH 4
+#define R_SERIAL0_CTRL__rec_baud__c300Hz 0
+#define R_SERIAL0_CTRL__rec_baud__c600Hz 1
+#define R_SERIAL0_CTRL__rec_baud__c1200Hz 2
+#define R_SERIAL0_CTRL__rec_baud__c2400Hz 3
+#define R_SERIAL0_CTRL__rec_baud__c4800Hz 4
+#define R_SERIAL0_CTRL__rec_baud__c9600Hz 5
+#define R_SERIAL0_CTRL__rec_baud__c19k2Hz 6
+#define R_SERIAL0_CTRL__rec_baud__c38k4Hz 7
+#define R_SERIAL0_CTRL__rec_baud__c57k6Hz 8
+#define R_SERIAL0_CTRL__rec_baud__c115k2Hz 9
+#define R_SERIAL0_CTRL__rec_baud__c230k4Hz 10
+#define R_SERIAL0_CTRL__rec_baud__c460k8Hz 11
+#define R_SERIAL0_CTRL__rec_baud__c921k6Hz 12
+#define R_SERIAL0_CTRL__rec_baud__c1843k2Hz 13
+#define R_SERIAL0_CTRL__rec_baud__c6250kHz 14
+#define R_SERIAL0_CTRL__rec_baud__reserved 15
+#define R_SERIAL0_CTRL__dma_err__BITNR 23
+#define R_SERIAL0_CTRL__dma_err__WIDTH 1
+#define R_SERIAL0_CTRL__dma_err__stop 0
+#define R_SERIAL0_CTRL__dma_err__ignore 1
+#define R_SERIAL0_CTRL__rec_enable__BITNR 22
+#define R_SERIAL0_CTRL__rec_enable__WIDTH 1
+#define R_SERIAL0_CTRL__rec_enable__disable 0
+#define R_SERIAL0_CTRL__rec_enable__enable 1
+#define R_SERIAL0_CTRL__rts___BITNR 21
+#define R_SERIAL0_CTRL__rts___WIDTH 1
+#define R_SERIAL0_CTRL__rts___active 0
+#define R_SERIAL0_CTRL__rts___inactive 1
+#define R_SERIAL0_CTRL__sampling__BITNR 20
+#define R_SERIAL0_CTRL__sampling__WIDTH 1
+#define R_SERIAL0_CTRL__sampling__middle 0
+#define R_SERIAL0_CTRL__sampling__majority 1
+#define R_SERIAL0_CTRL__rec_stick_par__BITNR 19
+#define R_SERIAL0_CTRL__rec_stick_par__WIDTH 1
+#define R_SERIAL0_CTRL__rec_stick_par__normal 0
+#define R_SERIAL0_CTRL__rec_stick_par__stick 1
+#define R_SERIAL0_CTRL__rec_par__BITNR 18
+#define R_SERIAL0_CTRL__rec_par__WIDTH 1
+#define R_SERIAL0_CTRL__rec_par__even 0
+#define R_SERIAL0_CTRL__rec_par__odd 1
+#define R_SERIAL0_CTRL__rec_par_en__BITNR 17
+#define R_SERIAL0_CTRL__rec_par_en__WIDTH 1
+#define R_SERIAL0_CTRL__rec_par_en__disable 0
+#define R_SERIAL0_CTRL__rec_par_en__enable 1
+#define R_SERIAL0_CTRL__rec_bitnr__BITNR 16
+#define R_SERIAL0_CTRL__rec_bitnr__WIDTH 1
+#define R_SERIAL0_CTRL__rec_bitnr__rec_8bit 0
+#define R_SERIAL0_CTRL__rec_bitnr__rec_7bit 1
+#define R_SERIAL0_CTRL__txd__BITNR 15
+#define R_SERIAL0_CTRL__txd__WIDTH 1
+#define R_SERIAL0_CTRL__tr_enable__BITNR 14
+#define R_SERIAL0_CTRL__tr_enable__WIDTH 1
+#define R_SERIAL0_CTRL__tr_enable__disable 0
+#define R_SERIAL0_CTRL__tr_enable__enable 1
+#define R_SERIAL0_CTRL__auto_cts__BITNR 13
+#define R_SERIAL0_CTRL__auto_cts__WIDTH 1
+#define R_SERIAL0_CTRL__auto_cts__disabled 0
+#define R_SERIAL0_CTRL__auto_cts__active 1
+#define R_SERIAL0_CTRL__stop_bits__BITNR 12
+#define R_SERIAL0_CTRL__stop_bits__WIDTH 1
+#define R_SERIAL0_CTRL__stop_bits__one_bit 0
+#define R_SERIAL0_CTRL__stop_bits__two_bits 1
+#define R_SERIAL0_CTRL__tr_stick_par__BITNR 11
+#define R_SERIAL0_CTRL__tr_stick_par__WIDTH 1
+#define R_SERIAL0_CTRL__tr_stick_par__normal 0
+#define R_SERIAL0_CTRL__tr_stick_par__stick 1
+#define R_SERIAL0_CTRL__tr_par__BITNR 10
+#define R_SERIAL0_CTRL__tr_par__WIDTH 1
+#define R_SERIAL0_CTRL__tr_par__even 0
+#define R_SERIAL0_CTRL__tr_par__odd 1
+#define R_SERIAL0_CTRL__tr_par_en__BITNR 9
+#define R_SERIAL0_CTRL__tr_par_en__WIDTH 1
+#define R_SERIAL0_CTRL__tr_par_en__disable 0
+#define R_SERIAL0_CTRL__tr_par_en__enable 1
+#define R_SERIAL0_CTRL__tr_bitnr__BITNR 8
+#define R_SERIAL0_CTRL__tr_bitnr__WIDTH 1
+#define R_SERIAL0_CTRL__tr_bitnr__tr_8bit 0
+#define R_SERIAL0_CTRL__tr_bitnr__tr_7bit 1
+#define R_SERIAL0_CTRL__data_out__BITNR 0
+#define R_SERIAL0_CTRL__data_out__WIDTH 8
+
+#define R_SERIAL0_BAUD (IO_TYPECAST_BYTE 0xb0000063)
+#define R_SERIAL0_BAUD__tr_baud__BITNR 4
+#define R_SERIAL0_BAUD__tr_baud__WIDTH 4
+#define R_SERIAL0_BAUD__tr_baud__c300Hz 0
+#define R_SERIAL0_BAUD__tr_baud__c600Hz 1
+#define R_SERIAL0_BAUD__tr_baud__c1200Hz 2
+#define R_SERIAL0_BAUD__tr_baud__c2400Hz 3
+#define R_SERIAL0_BAUD__tr_baud__c4800Hz 4
+#define R_SERIAL0_BAUD__tr_baud__c9600Hz 5
+#define R_SERIAL0_BAUD__tr_baud__c19k2Hz 6
+#define R_SERIAL0_BAUD__tr_baud__c38k4Hz 7
+#define R_SERIAL0_BAUD__tr_baud__c57k6Hz 8
+#define R_SERIAL0_BAUD__tr_baud__c115k2Hz 9
+#define R_SERIAL0_BAUD__tr_baud__c230k4Hz 10
+#define R_SERIAL0_BAUD__tr_baud__c460k8Hz 11
+#define R_SERIAL0_BAUD__tr_baud__c921k6Hz 12
+#define R_SERIAL0_BAUD__tr_baud__c1843k2Hz 13
+#define R_SERIAL0_BAUD__tr_baud__c6250kHz 14
+#define R_SERIAL0_BAUD__tr_baud__reserved 15
+#define R_SERIAL0_BAUD__rec_baud__BITNR 0
+#define R_SERIAL0_BAUD__rec_baud__WIDTH 4
+#define R_SERIAL0_BAUD__rec_baud__c300Hz 0
+#define R_SERIAL0_BAUD__rec_baud__c600Hz 1
+#define R_SERIAL0_BAUD__rec_baud__c1200Hz 2
+#define R_SERIAL0_BAUD__rec_baud__c2400Hz 3
+#define R_SERIAL0_BAUD__rec_baud__c4800Hz 4
+#define R_SERIAL0_BAUD__rec_baud__c9600Hz 5
+#define R_SERIAL0_BAUD__rec_baud__c19k2Hz 6
+#define R_SERIAL0_BAUD__rec_baud__c38k4Hz 7
+#define R_SERIAL0_BAUD__rec_baud__c57k6Hz 8
+#define R_SERIAL0_BAUD__rec_baud__c115k2Hz 9
+#define R_SERIAL0_BAUD__rec_baud__c230k4Hz 10
+#define R_SERIAL0_BAUD__rec_baud__c460k8Hz 11
+#define R_SERIAL0_BAUD__rec_baud__c921k6Hz 12
+#define R_SERIAL0_BAUD__rec_baud__c1843k2Hz 13
+#define R_SERIAL0_BAUD__rec_baud__c6250kHz 14
+#define R_SERIAL0_BAUD__rec_baud__reserved 15
+
+#define R_SERIAL0_REC_CTRL (IO_TYPECAST_BYTE 0xb0000062)
+#define R_SERIAL0_REC_CTRL__dma_err__BITNR 7
+#define R_SERIAL0_REC_CTRL__dma_err__WIDTH 1
+#define R_SERIAL0_REC_CTRL__dma_err__stop 0
+#define R_SERIAL0_REC_CTRL__dma_err__ignore 1
+#define R_SERIAL0_REC_CTRL__rec_enable__BITNR 6
+#define R_SERIAL0_REC_CTRL__rec_enable__WIDTH 1
+#define R_SERIAL0_REC_CTRL__rec_enable__disable 0
+#define R_SERIAL0_REC_CTRL__rec_enable__enable 1
+#define R_SERIAL0_REC_CTRL__rts___BITNR 5
+#define R_SERIAL0_REC_CTRL__rts___WIDTH 1
+#define R_SERIAL0_REC_CTRL__rts___active 0
+#define R_SERIAL0_REC_CTRL__rts___inactive 1
+#define R_SERIAL0_REC_CTRL__sampling__BITNR 4
+#define R_SERIAL0_REC_CTRL__sampling__WIDTH 1
+#define R_SERIAL0_REC_CTRL__sampling__middle 0
+#define R_SERIAL0_REC_CTRL__sampling__majority 1
+#define R_SERIAL0_REC_CTRL__rec_stick_par__BITNR 3
+#define R_SERIAL0_REC_CTRL__rec_stick_par__WIDTH 1
+#define R_SERIAL0_REC_CTRL__rec_stick_par__normal 0
+#define R_SERIAL0_REC_CTRL__rec_stick_par__stick 1
+#define R_SERIAL0_REC_CTRL__rec_par__BITNR 2
+#define R_SERIAL0_REC_CTRL__rec_par__WIDTH 1
+#define R_SERIAL0_REC_CTRL__rec_par__even 0
+#define R_SERIAL0_REC_CTRL__rec_par__odd 1
+#define R_SERIAL0_REC_CTRL__rec_par_en__BITNR 1
+#define R_SERIAL0_REC_CTRL__rec_par_en__WIDTH 1
+#define R_SERIAL0_REC_CTRL__rec_par_en__disable 0
+#define R_SERIAL0_REC_CTRL__rec_par_en__enable 1
+#define R_SERIAL0_REC_CTRL__rec_bitnr__BITNR 0
+#define R_SERIAL0_REC_CTRL__rec_bitnr__WIDTH 1
+#define R_SERIAL0_REC_CTRL__rec_bitnr__rec_8bit 0
+#define R_SERIAL0_REC_CTRL__rec_bitnr__rec_7bit 1
+
+#define R_SERIAL0_TR_CTRL (IO_TYPECAST_BYTE 0xb0000061)
+#define R_SERIAL0_TR_CTRL__txd__BITNR 7
+#define R_SERIAL0_TR_CTRL__txd__WIDTH 1
+#define R_SERIAL0_TR_CTRL__tr_enable__BITNR 6
+#define R_SERIAL0_TR_CTRL__tr_enable__WIDTH 1
+#define R_SERIAL0_TR_CTRL__tr_enable__disable 0
+#define R_SERIAL0_TR_CTRL__tr_enable__enable 1
+#define R_SERIAL0_TR_CTRL__auto_cts__BITNR 5
+#define R_SERIAL0_TR_CTRL__auto_cts__WIDTH 1
+#define R_SERIAL0_TR_CTRL__auto_cts__disabled 0
+#define R_SERIAL0_TR_CTRL__auto_cts__active 1
+#define R_SERIAL0_TR_CTRL__stop_bits__BITNR 4
+#define R_SERIAL0_TR_CTRL__stop_bits__WIDTH 1
+#define R_SERIAL0_TR_CTRL__stop_bits__one_bit 0
+#define R_SERIAL0_TR_CTRL__stop_bits__two_bits 1
+#define R_SERIAL0_TR_CTRL__tr_stick_par__BITNR 3
+#define R_SERIAL0_TR_CTRL__tr_stick_par__WIDTH 1
+#define R_SERIAL0_TR_CTRL__tr_stick_par__normal 0
+#define R_SERIAL0_TR_CTRL__tr_stick_par__stick 1
+#define R_SERIAL0_TR_CTRL__tr_par__BITNR 2
+#define R_SERIAL0_TR_CTRL__tr_par__WIDTH 1
+#define R_SERIAL0_TR_CTRL__tr_par__even 0
+#define R_SERIAL0_TR_CTRL__tr_par__odd 1
+#define R_SERIAL0_TR_CTRL__tr_par_en__BITNR 1
+#define R_SERIAL0_TR_CTRL__tr_par_en__WIDTH 1
+#define R_SERIAL0_TR_CTRL__tr_par_en__disable 0
+#define R_SERIAL0_TR_CTRL__tr_par_en__enable 1
+#define R_SERIAL0_TR_CTRL__tr_bitnr__BITNR 0
+#define R_SERIAL0_TR_CTRL__tr_bitnr__WIDTH 1
+#define R_SERIAL0_TR_CTRL__tr_bitnr__tr_8bit 0
+#define R_SERIAL0_TR_CTRL__tr_bitnr__tr_7bit 1
+
+#define R_SERIAL0_TR_DATA (IO_TYPECAST_BYTE 0xb0000060)
+#define R_SERIAL0_TR_DATA__data_out__BITNR 0
+#define R_SERIAL0_TR_DATA__data_out__WIDTH 8
+
+#define R_SERIAL0_READ (IO_TYPECAST_RO_UDWORD 0xb0000060)
+#define R_SERIAL0_READ__xoff_detect__BITNR 15
+#define R_SERIAL0_READ__xoff_detect__WIDTH 1
+#define R_SERIAL0_READ__xoff_detect__no_xoff 0
+#define R_SERIAL0_READ__xoff_detect__xoff 1
+#define R_SERIAL0_READ__cts___BITNR 14
+#define R_SERIAL0_READ__cts___WIDTH 1
+#define R_SERIAL0_READ__cts___active 0
+#define R_SERIAL0_READ__cts___inactive 1
+#define R_SERIAL0_READ__tr_ready__BITNR 13
+#define R_SERIAL0_READ__tr_ready__WIDTH 1
+#define R_SERIAL0_READ__tr_ready__full 0
+#define R_SERIAL0_READ__tr_ready__ready 1
+#define R_SERIAL0_READ__rxd__BITNR 12
+#define R_SERIAL0_READ__rxd__WIDTH 1
+#define R_SERIAL0_READ__overrun__BITNR 11
+#define R_SERIAL0_READ__overrun__WIDTH 1
+#define R_SERIAL0_READ__overrun__no 0
+#define R_SERIAL0_READ__overrun__yes 1
+#define R_SERIAL0_READ__par_err__BITNR 10
+#define R_SERIAL0_READ__par_err__WIDTH 1
+#define R_SERIAL0_READ__par_err__no 0
+#define R_SERIAL0_READ__par_err__yes 1
+#define R_SERIAL0_READ__framing_err__BITNR 9
+#define R_SERIAL0_READ__framing_err__WIDTH 1
+#define R_SERIAL0_READ__framing_err__no 0
+#define R_SERIAL0_READ__framing_err__yes 1
+#define R_SERIAL0_READ__data_avail__BITNR 8
+#define R_SERIAL0_READ__data_avail__WIDTH 1
+#define R_SERIAL0_READ__data_avail__no 0
+#define R_SERIAL0_READ__data_avail__yes 1
+#define R_SERIAL0_READ__data_in__BITNR 0
+#define R_SERIAL0_READ__data_in__WIDTH 8
+
+#define R_SERIAL0_STATUS (IO_TYPECAST_RO_BYTE 0xb0000061)
+#define R_SERIAL0_STATUS__xoff_detect__BITNR 7
+#define R_SERIAL0_STATUS__xoff_detect__WIDTH 1
+#define R_SERIAL0_STATUS__xoff_detect__no_xoff 0
+#define R_SERIAL0_STATUS__xoff_detect__xoff 1
+#define R_SERIAL0_STATUS__cts___BITNR 6
+#define R_SERIAL0_STATUS__cts___WIDTH 1
+#define R_SERIAL0_STATUS__cts___active 0
+#define R_SERIAL0_STATUS__cts___inactive 1
+#define R_SERIAL0_STATUS__tr_ready__BITNR 5
+#define R_SERIAL0_STATUS__tr_ready__WIDTH 1
+#define R_SERIAL0_STATUS__tr_ready__full 0
+#define R_SERIAL0_STATUS__tr_ready__ready 1
+#define R_SERIAL0_STATUS__rxd__BITNR 4
+#define R_SERIAL0_STATUS__rxd__WIDTH 1
+#define R_SERIAL0_STATUS__overrun__BITNR 3
+#define R_SERIAL0_STATUS__overrun__WIDTH 1
+#define R_SERIAL0_STATUS__overrun__no 0
+#define R_SERIAL0_STATUS__overrun__yes 1
+#define R_SERIAL0_STATUS__par_err__BITNR 2
+#define R_SERIAL0_STATUS__par_err__WIDTH 1
+#define R_SERIAL0_STATUS__par_err__no 0
+#define R_SERIAL0_STATUS__par_err__yes 1
+#define R_SERIAL0_STATUS__framing_err__BITNR 1
+#define R_SERIAL0_STATUS__framing_err__WIDTH 1
+#define R_SERIAL0_STATUS__framing_err__no 0
+#define R_SERIAL0_STATUS__framing_err__yes 1
+#define R_SERIAL0_STATUS__data_avail__BITNR 0
+#define R_SERIAL0_STATUS__data_avail__WIDTH 1
+#define R_SERIAL0_STATUS__data_avail__no 0
+#define R_SERIAL0_STATUS__data_avail__yes 1
+
+#define R_SERIAL0_REC_DATA (IO_TYPECAST_RO_BYTE 0xb0000060)
+#define R_SERIAL0_REC_DATA__data_in__BITNR 0
+#define R_SERIAL0_REC_DATA__data_in__WIDTH 8
+
+#define R_SERIAL0_XOFF (IO_TYPECAST_UDWORD 0xb0000064)
+#define R_SERIAL0_XOFF__tx_stop__BITNR 9
+#define R_SERIAL0_XOFF__tx_stop__WIDTH 1
+#define R_SERIAL0_XOFF__tx_stop__enable 0
+#define R_SERIAL0_XOFF__tx_stop__stop 1
+#define R_SERIAL0_XOFF__auto_xoff__BITNR 8
+#define R_SERIAL0_XOFF__auto_xoff__WIDTH 1
+#define R_SERIAL0_XOFF__auto_xoff__disable 0
+#define R_SERIAL0_XOFF__auto_xoff__enable 1
+#define R_SERIAL0_XOFF__xoff_char__BITNR 0
+#define R_SERIAL0_XOFF__xoff_char__WIDTH 8
+
+#define R_SERIAL1_CTRL (IO_TYPECAST_UDWORD 0xb0000068)
+#define R_SERIAL1_CTRL__tr_baud__BITNR 28
+#define R_SERIAL1_CTRL__tr_baud__WIDTH 4
+#define R_SERIAL1_CTRL__tr_baud__c300Hz 0
+#define R_SERIAL1_CTRL__tr_baud__c600Hz 1
+#define R_SERIAL1_CTRL__tr_baud__c1200Hz 2
+#define R_SERIAL1_CTRL__tr_baud__c2400Hz 3
+#define R_SERIAL1_CTRL__tr_baud__c4800Hz 4
+#define R_SERIAL1_CTRL__tr_baud__c9600Hz 5
+#define R_SERIAL1_CTRL__tr_baud__c19k2Hz 6
+#define R_SERIAL1_CTRL__tr_baud__c38k4Hz 7
+#define R_SERIAL1_CTRL__tr_baud__c57k6Hz 8
+#define R_SERIAL1_CTRL__tr_baud__c115k2Hz 9
+#define R_SERIAL1_CTRL__tr_baud__c230k4Hz 10
+#define R_SERIAL1_CTRL__tr_baud__c460k8Hz 11
+#define R_SERIAL1_CTRL__tr_baud__c921k6Hz 12
+#define R_SERIAL1_CTRL__tr_baud__c1843k2Hz 13
+#define R_SERIAL1_CTRL__tr_baud__c6250kHz 14
+#define R_SERIAL1_CTRL__tr_baud__reserved 15
+#define R_SERIAL1_CTRL__rec_baud__BITNR 24
+#define R_SERIAL1_CTRL__rec_baud__WIDTH 4
+#define R_SERIAL1_CTRL__rec_baud__c300Hz 0
+#define R_SERIAL1_CTRL__rec_baud__c600Hz 1
+#define R_SERIAL1_CTRL__rec_baud__c1200Hz 2
+#define R_SERIAL1_CTRL__rec_baud__c2400Hz 3
+#define R_SERIAL1_CTRL__rec_baud__c4800Hz 4
+#define R_SERIAL1_CTRL__rec_baud__c9600Hz 5
+#define R_SERIAL1_CTRL__rec_baud__c19k2Hz 6
+#define R_SERIAL1_CTRL__rec_baud__c38k4Hz 7
+#define R_SERIAL1_CTRL__rec_baud__c57k6Hz 8
+#define R_SERIAL1_CTRL__rec_baud__c115k2Hz 9
+#define R_SERIAL1_CTRL__rec_baud__c230k4Hz 10
+#define R_SERIAL1_CTRL__rec_baud__c460k8Hz 11
+#define R_SERIAL1_CTRL__rec_baud__c921k6Hz 12
+#define R_SERIAL1_CTRL__rec_baud__c1843k2Hz 13
+#define R_SERIAL1_CTRL__rec_baud__c6250kHz 14
+#define R_SERIAL1_CTRL__rec_baud__reserved 15
+#define R_SERIAL1_CTRL__dma_err__BITNR 23
+#define R_SERIAL1_CTRL__dma_err__WIDTH 1
+#define R_SERIAL1_CTRL__dma_err__stop 0
+#define R_SERIAL1_CTRL__dma_err__ignore 1
+#define R_SERIAL1_CTRL__rec_enable__BITNR 22
+#define R_SERIAL1_CTRL__rec_enable__WIDTH 1
+#define R_SERIAL1_CTRL__rec_enable__disable 0
+#define R_SERIAL1_CTRL__rec_enable__enable 1
+#define R_SERIAL1_CTRL__rts___BITNR 21
+#define R_SERIAL1_CTRL__rts___WIDTH 1
+#define R_SERIAL1_CTRL__rts___active 0
+#define R_SERIAL1_CTRL__rts___inactive 1
+#define R_SERIAL1_CTRL__sampling__BITNR 20
+#define R_SERIAL1_CTRL__sampling__WIDTH 1
+#define R_SERIAL1_CTRL__sampling__middle 0
+#define R_SERIAL1_CTRL__sampling__majority 1
+#define R_SERIAL1_CTRL__rec_stick_par__BITNR 19
+#define R_SERIAL1_CTRL__rec_stick_par__WIDTH 1
+#define R_SERIAL1_CTRL__rec_stick_par__normal 0
+#define R_SERIAL1_CTRL__rec_stick_par__stick 1
+#define R_SERIAL1_CTRL__rec_par__BITNR 18
+#define R_SERIAL1_CTRL__rec_par__WIDTH 1
+#define R_SERIAL1_CTRL__rec_par__even 0
+#define R_SERIAL1_CTRL__rec_par__odd 1
+#define R_SERIAL1_CTRL__rec_par_en__BITNR 17
+#define R_SERIAL1_CTRL__rec_par_en__WIDTH 1
+#define R_SERIAL1_CTRL__rec_par_en__disable 0
+#define R_SERIAL1_CTRL__rec_par_en__enable 1
+#define R_SERIAL1_CTRL__rec_bitnr__BITNR 16
+#define R_SERIAL1_CTRL__rec_bitnr__WIDTH 1
+#define R_SERIAL1_CTRL__rec_bitnr__rec_8bit 0
+#define R_SERIAL1_CTRL__rec_bitnr__rec_7bit 1
+#define R_SERIAL1_CTRL__txd__BITNR 15
+#define R_SERIAL1_CTRL__txd__WIDTH 1
+#define R_SERIAL1_CTRL__tr_enable__BITNR 14
+#define R_SERIAL1_CTRL__tr_enable__WIDTH 1
+#define R_SERIAL1_CTRL__tr_enable__disable 0
+#define R_SERIAL1_CTRL__tr_enable__enable 1
+#define R_SERIAL1_CTRL__auto_cts__BITNR 13
+#define R_SERIAL1_CTRL__auto_cts__WIDTH 1
+#define R_SERIAL1_CTRL__auto_cts__disabled 0
+#define R_SERIAL1_CTRL__auto_cts__active 1
+#define R_SERIAL1_CTRL__stop_bits__BITNR 12
+#define R_SERIAL1_CTRL__stop_bits__WIDTH 1
+#define R_SERIAL1_CTRL__stop_bits__one_bit 0
+#define R_SERIAL1_CTRL__stop_bits__two_bits 1
+#define R_SERIAL1_CTRL__tr_stick_par__BITNR 11
+#define R_SERIAL1_CTRL__tr_stick_par__WIDTH 1
+#define R_SERIAL1_CTRL__tr_stick_par__normal 0
+#define R_SERIAL1_CTRL__tr_stick_par__stick 1
+#define R_SERIAL1_CTRL__tr_par__BITNR 10
+#define R_SERIAL1_CTRL__tr_par__WIDTH 1
+#define R_SERIAL1_CTRL__tr_par__even 0
+#define R_SERIAL1_CTRL__tr_par__odd 1
+#define R_SERIAL1_CTRL__tr_par_en__BITNR 9
+#define R_SERIAL1_CTRL__tr_par_en__WIDTH 1
+#define R_SERIAL1_CTRL__tr_par_en__disable 0
+#define R_SERIAL1_CTRL__tr_par_en__enable 1
+#define R_SERIAL1_CTRL__tr_bitnr__BITNR 8
+#define R_SERIAL1_CTRL__tr_bitnr__WIDTH 1
+#define R_SERIAL1_CTRL__tr_bitnr__tr_8bit 0
+#define R_SERIAL1_CTRL__tr_bitnr__tr_7bit 1
+#define R_SERIAL1_CTRL__data_out__BITNR 0
+#define R_SERIAL1_CTRL__data_out__WIDTH 8
+
+#define R_SERIAL1_BAUD (IO_TYPECAST_BYTE 0xb000006b)
+#define R_SERIAL1_BAUD__tr_baud__BITNR 4
+#define R_SERIAL1_BAUD__tr_baud__WIDTH 4
+#define R_SERIAL1_BAUD__tr_baud__c300Hz 0
+#define R_SERIAL1_BAUD__tr_baud__c600Hz 1
+#define R_SERIAL1_BAUD__tr_baud__c1200Hz 2
+#define R_SERIAL1_BAUD__tr_baud__c2400Hz 3
+#define R_SERIAL1_BAUD__tr_baud__c4800Hz 4
+#define R_SERIAL1_BAUD__tr_baud__c9600Hz 5
+#define R_SERIAL1_BAUD__tr_baud__c19k2Hz 6
+#define R_SERIAL1_BAUD__tr_baud__c38k4Hz 7
+#define R_SERIAL1_BAUD__tr_baud__c57k6Hz 8
+#define R_SERIAL1_BAUD__tr_baud__c115k2Hz 9
+#define R_SERIAL1_BAUD__tr_baud__c230k4Hz 10
+#define R_SERIAL1_BAUD__tr_baud__c460k8Hz 11
+#define R_SERIAL1_BAUD__tr_baud__c921k6Hz 12
+#define R_SERIAL1_BAUD__tr_baud__c1843k2Hz 13
+#define R_SERIAL1_BAUD__tr_baud__c6250kHz 14
+#define R_SERIAL1_BAUD__tr_baud__reserved 15
+#define R_SERIAL1_BAUD__rec_baud__BITNR 0
+#define R_SERIAL1_BAUD__rec_baud__WIDTH 4
+#define R_SERIAL1_BAUD__rec_baud__c300Hz 0
+#define R_SERIAL1_BAUD__rec_baud__c600Hz 1
+#define R_SERIAL1_BAUD__rec_baud__c1200Hz 2
+#define R_SERIAL1_BAUD__rec_baud__c2400Hz 3
+#define R_SERIAL1_BAUD__rec_baud__c4800Hz 4
+#define R_SERIAL1_BAUD__rec_baud__c9600Hz 5
+#define R_SERIAL1_BAUD__rec_baud__c19k2Hz 6
+#define R_SERIAL1_BAUD__rec_baud__c38k4Hz 7
+#define R_SERIAL1_BAUD__rec_baud__c57k6Hz 8
+#define R_SERIAL1_BAUD__rec_baud__c115k2Hz 9
+#define R_SERIAL1_BAUD__rec_baud__c230k4Hz 10
+#define R_SERIAL1_BAUD__rec_baud__c460k8Hz 11
+#define R_SERIAL1_BAUD__rec_baud__c921k6Hz 12
+#define R_SERIAL1_BAUD__rec_baud__c1843k2Hz 13
+#define R_SERIAL1_BAUD__rec_baud__c6250kHz 14
+#define R_SERIAL1_BAUD__rec_baud__reserved 15
+
+#define R_SERIAL1_REC_CTRL (IO_TYPECAST_BYTE 0xb000006a)
+#define R_SERIAL1_REC_CTRL__dma_err__BITNR 7
+#define R_SERIAL1_REC_CTRL__dma_err__WIDTH 1
+#define R_SERIAL1_REC_CTRL__dma_err__stop 0
+#define R_SERIAL1_REC_CTRL__dma_err__ignore 1
+#define R_SERIAL1_REC_CTRL__rec_enable__BITNR 6
+#define R_SERIAL1_REC_CTRL__rec_enable__WIDTH 1
+#define R_SERIAL1_REC_CTRL__rec_enable__disable 0
+#define R_SERIAL1_REC_CTRL__rec_enable__enable 1
+#define R_SERIAL1_REC_CTRL__rts___BITNR 5
+#define R_SERIAL1_REC_CTRL__rts___WIDTH 1
+#define R_SERIAL1_REC_CTRL__rts___active 0
+#define R_SERIAL1_REC_CTRL__rts___inactive 1
+#define R_SERIAL1_REC_CTRL__sampling__BITNR 4
+#define R_SERIAL1_REC_CTRL__sampling__WIDTH 1
+#define R_SERIAL1_REC_CTRL__sampling__middle 0
+#define R_SERIAL1_REC_CTRL__sampling__majority 1
+#define R_SERIAL1_REC_CTRL__rec_stick_par__BITNR 3
+#define R_SERIAL1_REC_CTRL__rec_stick_par__WIDTH 1
+#define R_SERIAL1_REC_CTRL__rec_stick_par__normal 0
+#define R_SERIAL1_REC_CTRL__rec_stick_par__stick 1
+#define R_SERIAL1_REC_CTRL__rec_par__BITNR 2
+#define R_SERIAL1_REC_CTRL__rec_par__WIDTH 1
+#define R_SERIAL1_REC_CTRL__rec_par__even 0
+#define R_SERIAL1_REC_CTRL__rec_par__odd 1
+#define R_SERIAL1_REC_CTRL__rec_par_en__BITNR 1
+#define R_SERIAL1_REC_CTRL__rec_par_en__WIDTH 1
+#define R_SERIAL1_REC_CTRL__rec_par_en__disable 0
+#define R_SERIAL1_REC_CTRL__rec_par_en__enable 1
+#define R_SERIAL1_REC_CTRL__rec_bitnr__BITNR 0
+#define R_SERIAL1_REC_CTRL__rec_bitnr__WIDTH 1
+#define R_SERIAL1_REC_CTRL__rec_bitnr__rec_8bit 0
+#define R_SERIAL1_REC_CTRL__rec_bitnr__rec_7bit 1
+
+#define R_SERIAL1_TR_CTRL (IO_TYPECAST_BYTE 0xb0000069)
+#define R_SERIAL1_TR_CTRL__txd__BITNR 7
+#define R_SERIAL1_TR_CTRL__txd__WIDTH 1
+#define R_SERIAL1_TR_CTRL__tr_enable__BITNR 6
+#define R_SERIAL1_TR_CTRL__tr_enable__WIDTH 1
+#define R_SERIAL1_TR_CTRL__tr_enable__disable 0
+#define R_SERIAL1_TR_CTRL__tr_enable__enable 1
+#define R_SERIAL1_TR_CTRL__auto_cts__BITNR 5
+#define R_SERIAL1_TR_CTRL__auto_cts__WIDTH 1
+#define R_SERIAL1_TR_CTRL__auto_cts__disabled 0
+#define R_SERIAL1_TR_CTRL__auto_cts__active 1
+#define R_SERIAL1_TR_CTRL__stop_bits__BITNR 4
+#define R_SERIAL1_TR_CTRL__stop_bits__WIDTH 1
+#define R_SERIAL1_TR_CTRL__stop_bits__one_bit 0
+#define R_SERIAL1_TR_CTRL__stop_bits__two_bits 1
+#define R_SERIAL1_TR_CTRL__tr_stick_par__BITNR 3
+#define R_SERIAL1_TR_CTRL__tr_stick_par__WIDTH 1
+#define R_SERIAL1_TR_CTRL__tr_stick_par__normal 0
+#define R_SERIAL1_TR_CTRL__tr_stick_par__stick 1
+#define R_SERIAL1_TR_CTRL__tr_par__BITNR 2
+#define R_SERIAL1_TR_CTRL__tr_par__WIDTH 1
+#define R_SERIAL1_TR_CTRL__tr_par__even 0
+#define R_SERIAL1_TR_CTRL__tr_par__odd 1
+#define R_SERIAL1_TR_CTRL__tr_par_en__BITNR 1
+#define R_SERIAL1_TR_CTRL__tr_par_en__WIDTH 1
+#define R_SERIAL1_TR_CTRL__tr_par_en__disable 0
+#define R_SERIAL1_TR_CTRL__tr_par_en__enable 1
+#define R_SERIAL1_TR_CTRL__tr_bitnr__BITNR 0
+#define R_SERIAL1_TR_CTRL__tr_bitnr__WIDTH 1
+#define R_SERIAL1_TR_CTRL__tr_bitnr__tr_8bit 0
+#define R_SERIAL1_TR_CTRL__tr_bitnr__tr_7bit 1
+
+#define R_SERIAL1_TR_DATA (IO_TYPECAST_BYTE 0xb0000068)
+#define R_SERIAL1_TR_DATA__data_out__BITNR 0
+#define R_SERIAL1_TR_DATA__data_out__WIDTH 8
+
+#define R_SERIAL1_READ (IO_TYPECAST_RO_UDWORD 0xb0000068)
+#define R_SERIAL1_READ__xoff_detect__BITNR 15
+#define R_SERIAL1_READ__xoff_detect__WIDTH 1
+#define R_SERIAL1_READ__xoff_detect__no_xoff 0
+#define R_SERIAL1_READ__xoff_detect__xoff 1
+#define R_SERIAL1_READ__cts___BITNR 14
+#define R_SERIAL1_READ__cts___WIDTH 1
+#define R_SERIAL1_READ__cts___active 0
+#define R_SERIAL1_READ__cts___inactive 1
+#define R_SERIAL1_READ__tr_ready__BITNR 13
+#define R_SERIAL1_READ__tr_ready__WIDTH 1
+#define R_SERIAL1_READ__tr_ready__full 0
+#define R_SERIAL1_READ__tr_ready__ready 1
+#define R_SERIAL1_READ__rxd__BITNR 12
+#define R_SERIAL1_READ__rxd__WIDTH 1
+#define R_SERIAL1_READ__overrun__BITNR 11
+#define R_SERIAL1_READ__overrun__WIDTH 1
+#define R_SERIAL1_READ__overrun__no 0
+#define R_SERIAL1_READ__overrun__yes 1
+#define R_SERIAL1_READ__par_err__BITNR 10
+#define R_SERIAL1_READ__par_err__WIDTH 1
+#define R_SERIAL1_READ__par_err__no 0
+#define R_SERIAL1_READ__par_err__yes 1
+#define R_SERIAL1_READ__framing_err__BITNR 9
+#define R_SERIAL1_READ__framing_err__WIDTH 1
+#define R_SERIAL1_READ__framing_err__no 0
+#define R_SERIAL1_READ__framing_err__yes 1
+#define R_SERIAL1_READ__data_avail__BITNR 8
+#define R_SERIAL1_READ__data_avail__WIDTH 1
+#define R_SERIAL1_READ__data_avail__no 0
+#define R_SERIAL1_READ__data_avail__yes 1
+#define R_SERIAL1_READ__data_in__BITNR 0
+#define R_SERIAL1_READ__data_in__WIDTH 8
+
+#define R_SERIAL1_STATUS (IO_TYPECAST_RO_BYTE 0xb0000069)
+#define R_SERIAL1_STATUS__xoff_detect__BITNR 7
+#define R_SERIAL1_STATUS__xoff_detect__WIDTH 1
+#define R_SERIAL1_STATUS__xoff_detect__no_xoff 0
+#define R_SERIAL1_STATUS__xoff_detect__xoff 1
+#define R_SERIAL1_STATUS__cts___BITNR 6
+#define R_SERIAL1_STATUS__cts___WIDTH 1
+#define R_SERIAL1_STATUS__cts___active 0
+#define R_SERIAL1_STATUS__cts___inactive 1
+#define R_SERIAL1_STATUS__tr_ready__BITNR 5
+#define R_SERIAL1_STATUS__tr_ready__WIDTH 1
+#define R_SERIAL1_STATUS__tr_ready__full 0
+#define R_SERIAL1_STATUS__tr_ready__ready 1
+#define R_SERIAL1_STATUS__rxd__BITNR 4
+#define R_SERIAL1_STATUS__rxd__WIDTH 1
+#define R_SERIAL1_STATUS__overrun__BITNR 3
+#define R_SERIAL1_STATUS__overrun__WIDTH 1
+#define R_SERIAL1_STATUS__overrun__no 0
+#define R_SERIAL1_STATUS__overrun__yes 1
+#define R_SERIAL1_STATUS__par_err__BITNR 2
+#define R_SERIAL1_STATUS__par_err__WIDTH 1
+#define R_SERIAL1_STATUS__par_err__no 0
+#define R_SERIAL1_STATUS__par_err__yes 1
+#define R_SERIAL1_STATUS__framing_err__BITNR 1
+#define R_SERIAL1_STATUS__framing_err__WIDTH 1
+#define R_SERIAL1_STATUS__framing_err__no 0
+#define R_SERIAL1_STATUS__framing_err__yes 1
+#define R_SERIAL1_STATUS__data_avail__BITNR 0
+#define R_SERIAL1_STATUS__data_avail__WIDTH 1
+#define R_SERIAL1_STATUS__data_avail__no 0
+#define R_SERIAL1_STATUS__data_avail__yes 1
+
+#define R_SERIAL1_REC_DATA (IO_TYPECAST_RO_BYTE 0xb0000068)
+#define R_SERIAL1_REC_DATA__data_in__BITNR 0
+#define R_SERIAL1_REC_DATA__data_in__WIDTH 8
+
+#define R_SERIAL1_XOFF (IO_TYPECAST_UDWORD 0xb000006c)
+#define R_SERIAL1_XOFF__tx_stop__BITNR 9
+#define R_SERIAL1_XOFF__tx_stop__WIDTH 1
+#define R_SERIAL1_XOFF__tx_stop__enable 0
+#define R_SERIAL1_XOFF__tx_stop__stop 1
+#define R_SERIAL1_XOFF__auto_xoff__BITNR 8
+#define R_SERIAL1_XOFF__auto_xoff__WIDTH 1
+#define R_SERIAL1_XOFF__auto_xoff__disable 0
+#define R_SERIAL1_XOFF__auto_xoff__enable 1
+#define R_SERIAL1_XOFF__xoff_char__BITNR 0
+#define R_SERIAL1_XOFF__xoff_char__WIDTH 8
+
+#define R_SERIAL2_CTRL (IO_TYPECAST_UDWORD 0xb0000070)
+#define R_SERIAL2_CTRL__tr_baud__BITNR 28
+#define R_SERIAL2_CTRL__tr_baud__WIDTH 4
+#define R_SERIAL2_CTRL__tr_baud__c300Hz 0
+#define R_SERIAL2_CTRL__tr_baud__c600Hz 1
+#define R_SERIAL2_CTRL__tr_baud__c1200Hz 2
+#define R_SERIAL2_CTRL__tr_baud__c2400Hz 3
+#define R_SERIAL2_CTRL__tr_baud__c4800Hz 4
+#define R_SERIAL2_CTRL__tr_baud__c9600Hz 5
+#define R_SERIAL2_CTRL__tr_baud__c19k2Hz 6
+#define R_SERIAL2_CTRL__tr_baud__c38k4Hz 7
+#define R_SERIAL2_CTRL__tr_baud__c57k6Hz 8
+#define R_SERIAL2_CTRL__tr_baud__c115k2Hz 9
+#define R_SERIAL2_CTRL__tr_baud__c230k4Hz 10
+#define R_SERIAL2_CTRL__tr_baud__c460k8Hz 11
+#define R_SERIAL2_CTRL__tr_baud__c921k6Hz 12
+#define R_SERIAL2_CTRL__tr_baud__c1843k2Hz 13
+#define R_SERIAL2_CTRL__tr_baud__c6250kHz 14
+#define R_SERIAL2_CTRL__tr_baud__reserved 15
+#define R_SERIAL2_CTRL__rec_baud__BITNR 24
+#define R_SERIAL2_CTRL__rec_baud__WIDTH 4
+#define R_SERIAL2_CTRL__rec_baud__c300Hz 0
+#define R_SERIAL2_CTRL__rec_baud__c600Hz 1
+#define R_SERIAL2_CTRL__rec_baud__c1200Hz 2
+#define R_SERIAL2_CTRL__rec_baud__c2400Hz 3
+#define R_SERIAL2_CTRL__rec_baud__c4800Hz 4
+#define R_SERIAL2_CTRL__rec_baud__c9600Hz 5
+#define R_SERIAL2_CTRL__rec_baud__c19k2Hz 6
+#define R_SERIAL2_CTRL__rec_baud__c38k4Hz 7
+#define R_SERIAL2_CTRL__rec_baud__c57k6Hz 8
+#define R_SERIAL2_CTRL__rec_baud__c115k2Hz 9
+#define R_SERIAL2_CTRL__rec_baud__c230k4Hz 10
+#define R_SERIAL2_CTRL__rec_baud__c460k8Hz 11
+#define R_SERIAL2_CTRL__rec_baud__c921k6Hz 12
+#define R_SERIAL2_CTRL__rec_baud__c1843k2Hz 13
+#define R_SERIAL2_CTRL__rec_baud__c6250kHz 14
+#define R_SERIAL2_CTRL__rec_baud__reserved 15
+#define R_SERIAL2_CTRL__dma_err__BITNR 23
+#define R_SERIAL2_CTRL__dma_err__WIDTH 1
+#define R_SERIAL2_CTRL__dma_err__stop 0
+#define R_SERIAL2_CTRL__dma_err__ignore 1
+#define R_SERIAL2_CTRL__rec_enable__BITNR 22
+#define R_SERIAL2_CTRL__rec_enable__WIDTH 1
+#define R_SERIAL2_CTRL__rec_enable__disable 0
+#define R_SERIAL2_CTRL__rec_enable__enable 1
+#define R_SERIAL2_CTRL__rts___BITNR 21
+#define R_SERIAL2_CTRL__rts___WIDTH 1
+#define R_SERIAL2_CTRL__rts___active 0
+#define R_SERIAL2_CTRL__rts___inactive 1
+#define R_SERIAL2_CTRL__sampling__BITNR 20
+#define R_SERIAL2_CTRL__sampling__WIDTH 1
+#define R_SERIAL2_CTRL__sampling__middle 0
+#define R_SERIAL2_CTRL__sampling__majority 1
+#define R_SERIAL2_CTRL__rec_stick_par__BITNR 19
+#define R_SERIAL2_CTRL__rec_stick_par__WIDTH 1
+#define R_SERIAL2_CTRL__rec_stick_par__normal 0
+#define R_SERIAL2_CTRL__rec_stick_par__stick 1
+#define R_SERIAL2_CTRL__rec_par__BITNR 18
+#define R_SERIAL2_CTRL__rec_par__WIDTH 1
+#define R_SERIAL2_CTRL__rec_par__even 0
+#define R_SERIAL2_CTRL__rec_par__odd 1
+#define R_SERIAL2_CTRL__rec_par_en__BITNR 17
+#define R_SERIAL2_CTRL__rec_par_en__WIDTH 1
+#define R_SERIAL2_CTRL__rec_par_en__disable 0
+#define R_SERIAL2_CTRL__rec_par_en__enable 1
+#define R_SERIAL2_CTRL__rec_bitnr__BITNR 16
+#define R_SERIAL2_CTRL__rec_bitnr__WIDTH 1
+#define R_SERIAL2_CTRL__rec_bitnr__rec_8bit 0
+#define R_SERIAL2_CTRL__rec_bitnr__rec_7bit 1
+#define R_SERIAL2_CTRL__txd__BITNR 15
+#define R_SERIAL2_CTRL__txd__WIDTH 1
+#define R_SERIAL2_CTRL__tr_enable__BITNR 14
+#define R_SERIAL2_CTRL__tr_enable__WIDTH 1
+#define R_SERIAL2_CTRL__tr_enable__disable 0
+#define R_SERIAL2_CTRL__tr_enable__enable 1
+#define R_SERIAL2_CTRL__auto_cts__BITNR 13
+#define R_SERIAL2_CTRL__auto_cts__WIDTH 1
+#define R_SERIAL2_CTRL__auto_cts__disabled 0
+#define R_SERIAL2_CTRL__auto_cts__active 1
+#define R_SERIAL2_CTRL__stop_bits__BITNR 12
+#define R_SERIAL2_CTRL__stop_bits__WIDTH 1
+#define R_SERIAL2_CTRL__stop_bits__one_bit 0
+#define R_SERIAL2_CTRL__stop_bits__two_bits 1
+#define R_SERIAL2_CTRL__tr_stick_par__BITNR 11
+#define R_SERIAL2_CTRL__tr_stick_par__WIDTH 1
+#define R_SERIAL2_CTRL__tr_stick_par__normal 0
+#define R_SERIAL2_CTRL__tr_stick_par__stick 1
+#define R_SERIAL2_CTRL__tr_par__BITNR 10
+#define R_SERIAL2_CTRL__tr_par__WIDTH 1
+#define R_SERIAL2_CTRL__tr_par__even 0
+#define R_SERIAL2_CTRL__tr_par__odd 1
+#define R_SERIAL2_CTRL__tr_par_en__BITNR 9
+#define R_SERIAL2_CTRL__tr_par_en__WIDTH 1
+#define R_SERIAL2_CTRL__tr_par_en__disable 0
+#define R_SERIAL2_CTRL__tr_par_en__enable 1
+#define R_SERIAL2_CTRL__tr_bitnr__BITNR 8
+#define R_SERIAL2_CTRL__tr_bitnr__WIDTH 1
+#define R_SERIAL2_CTRL__tr_bitnr__tr_8bit 0
+#define R_SERIAL2_CTRL__tr_bitnr__tr_7bit 1
+#define R_SERIAL2_CTRL__data_out__BITNR 0
+#define R_SERIAL2_CTRL__data_out__WIDTH 8
+
+#define R_SERIAL2_BAUD (IO_TYPECAST_BYTE 0xb0000073)
+#define R_SERIAL2_BAUD__tr_baud__BITNR 4
+#define R_SERIAL2_BAUD__tr_baud__WIDTH 4
+#define R_SERIAL2_BAUD__tr_baud__c300Hz 0
+#define R_SERIAL2_BAUD__tr_baud__c600Hz 1
+#define R_SERIAL2_BAUD__tr_baud__c1200Hz 2
+#define R_SERIAL2_BAUD__tr_baud__c2400Hz 3
+#define R_SERIAL2_BAUD__tr_baud__c4800Hz 4
+#define R_SERIAL2_BAUD__tr_baud__c9600Hz 5
+#define R_SERIAL2_BAUD__tr_baud__c19k2Hz 6
+#define R_SERIAL2_BAUD__tr_baud__c38k4Hz 7
+#define R_SERIAL2_BAUD__tr_baud__c57k6Hz 8
+#define R_SERIAL2_BAUD__tr_baud__c115k2Hz 9
+#define R_SERIAL2_BAUD__tr_baud__c230k4Hz 10
+#define R_SERIAL2_BAUD__tr_baud__c460k8Hz 11
+#define R_SERIAL2_BAUD__tr_baud__c921k6Hz 12
+#define R_SERIAL2_BAUD__tr_baud__c1843k2Hz 13
+#define R_SERIAL2_BAUD__tr_baud__c6250kHz 14
+#define R_SERIAL2_BAUD__tr_baud__reserved 15
+#define R_SERIAL2_BAUD__rec_baud__BITNR 0
+#define R_SERIAL2_BAUD__rec_baud__WIDTH 4
+#define R_SERIAL2_BAUD__rec_baud__c300Hz 0
+#define R_SERIAL2_BAUD__rec_baud__c600Hz 1
+#define R_SERIAL2_BAUD__rec_baud__c1200Hz 2
+#define R_SERIAL2_BAUD__rec_baud__c2400Hz 3
+#define R_SERIAL2_BAUD__rec_baud__c4800Hz 4
+#define R_SERIAL2_BAUD__rec_baud__c9600Hz 5
+#define R_SERIAL2_BAUD__rec_baud__c19k2Hz 6
+#define R_SERIAL2_BAUD__rec_baud__c38k4Hz 7
+#define R_SERIAL2_BAUD__rec_baud__c57k6Hz 8
+#define R_SERIAL2_BAUD__rec_baud__c115k2Hz 9
+#define R_SERIAL2_BAUD__rec_baud__c230k4Hz 10
+#define R_SERIAL2_BAUD__rec_baud__c460k8Hz 11
+#define R_SERIAL2_BAUD__rec_baud__c921k6Hz 12
+#define R_SERIAL2_BAUD__rec_baud__c1843k2Hz 13
+#define R_SERIAL2_BAUD__rec_baud__c6250kHz 14
+#define R_SERIAL2_BAUD__rec_baud__reserved 15
+
+#define R_SERIAL2_REC_CTRL (IO_TYPECAST_BYTE 0xb0000072)
+#define R_SERIAL2_REC_CTRL__dma_err__BITNR 7
+#define R_SERIAL2_REC_CTRL__dma_err__WIDTH 1
+#define R_SERIAL2_REC_CTRL__dma_err__stop 0
+#define R_SERIAL2_REC_CTRL__dma_err__ignore 1
+#define R_SERIAL2_REC_CTRL__rec_enable__BITNR 6
+#define R_SERIAL2_REC_CTRL__rec_enable__WIDTH 1
+#define R_SERIAL2_REC_CTRL__rec_enable__disable 0
+#define R_SERIAL2_REC_CTRL__rec_enable__enable 1
+#define R_SERIAL2_REC_CTRL__rts___BITNR 5
+#define R_SERIAL2_REC_CTRL__rts___WIDTH 1
+#define R_SERIAL2_REC_CTRL__rts___active 0
+#define R_SERIAL2_REC_CTRL__rts___inactive 1
+#define R_SERIAL2_REC_CTRL__sampling__BITNR 4
+#define R_SERIAL2_REC_CTRL__sampling__WIDTH 1
+#define R_SERIAL2_REC_CTRL__sampling__middle 0
+#define R_SERIAL2_REC_CTRL__sampling__majority 1
+#define R_SERIAL2_REC_CTRL__rec_stick_par__BITNR 3
+#define R_SERIAL2_REC_CTRL__rec_stick_par__WIDTH 1
+#define R_SERIAL2_REC_CTRL__rec_stick_par__normal 0
+#define R_SERIAL2_REC_CTRL__rec_stick_par__stick 1
+#define R_SERIAL2_REC_CTRL__rec_par__BITNR 2
+#define R_SERIAL2_REC_CTRL__rec_par__WIDTH 1
+#define R_SERIAL2_REC_CTRL__rec_par__even 0
+#define R_SERIAL2_REC_CTRL__rec_par__odd 1
+#define R_SERIAL2_REC_CTRL__rec_par_en__BITNR 1
+#define R_SERIAL2_REC_CTRL__rec_par_en__WIDTH 1
+#define R_SERIAL2_REC_CTRL__rec_par_en__disable 0
+#define R_SERIAL2_REC_CTRL__rec_par_en__enable 1
+#define R_SERIAL2_REC_CTRL__rec_bitnr__BITNR 0
+#define R_SERIAL2_REC_CTRL__rec_bitnr__WIDTH 1
+#define R_SERIAL2_REC_CTRL__rec_bitnr__rec_8bit 0
+#define R_SERIAL2_REC_CTRL__rec_bitnr__rec_7bit 1
+
+#define R_SERIAL2_TR_CTRL (IO_TYPECAST_BYTE 0xb0000071)
+#define R_SERIAL2_TR_CTRL__txd__BITNR 7
+#define R_SERIAL2_TR_CTRL__txd__WIDTH 1
+#define R_SERIAL2_TR_CTRL__tr_enable__BITNR 6
+#define R_SERIAL2_TR_CTRL__tr_enable__WIDTH 1
+#define R_SERIAL2_TR_CTRL__tr_enable__disable 0
+#define R_SERIAL2_TR_CTRL__tr_enable__enable 1
+#define R_SERIAL2_TR_CTRL__auto_cts__BITNR 5
+#define R_SERIAL2_TR_CTRL__auto_cts__WIDTH 1
+#define R_SERIAL2_TR_CTRL__auto_cts__disabled 0
+#define R_SERIAL2_TR_CTRL__auto_cts__active 1
+#define R_SERIAL2_TR_CTRL__stop_bits__BITNR 4
+#define R_SERIAL2_TR_CTRL__stop_bits__WIDTH 1
+#define R_SERIAL2_TR_CTRL__stop_bits__one_bit 0
+#define R_SERIAL2_TR_CTRL__stop_bits__two_bits 1
+#define R_SERIAL2_TR_CTRL__tr_stick_par__BITNR 3
+#define R_SERIAL2_TR_CTRL__tr_stick_par__WIDTH 1
+#define R_SERIAL2_TR_CTRL__tr_stick_par__normal 0
+#define R_SERIAL2_TR_CTRL__tr_stick_par__stick 1
+#define R_SERIAL2_TR_CTRL__tr_par__BITNR 2
+#define R_SERIAL2_TR_CTRL__tr_par__WIDTH 1
+#define R_SERIAL2_TR_CTRL__tr_par__even 0
+#define R_SERIAL2_TR_CTRL__tr_par__odd 1
+#define R_SERIAL2_TR_CTRL__tr_par_en__BITNR 1
+#define R_SERIAL2_TR_CTRL__tr_par_en__WIDTH 1
+#define R_SERIAL2_TR_CTRL__tr_par_en__disable 0
+#define R_SERIAL2_TR_CTRL__tr_par_en__enable 1
+#define R_SERIAL2_TR_CTRL__tr_bitnr__BITNR 0
+#define R_SERIAL2_TR_CTRL__tr_bitnr__WIDTH 1
+#define R_SERIAL2_TR_CTRL__tr_bitnr__tr_8bit 0
+#define R_SERIAL2_TR_CTRL__tr_bitnr__tr_7bit 1
+
+#define R_SERIAL2_TR_DATA (IO_TYPECAST_BYTE 0xb0000070)
+#define R_SERIAL2_TR_DATA__data_out__BITNR 0
+#define R_SERIAL2_TR_DATA__data_out__WIDTH 8
+
+#define R_SERIAL2_READ (IO_TYPECAST_RO_UDWORD 0xb0000070)
+#define R_SERIAL2_READ__xoff_detect__BITNR 15
+#define R_SERIAL2_READ__xoff_detect__WIDTH 1
+#define R_SERIAL2_READ__xoff_detect__no_xoff 0
+#define R_SERIAL2_READ__xoff_detect__xoff 1
+#define R_SERIAL2_READ__cts___BITNR 14
+#define R_SERIAL2_READ__cts___WIDTH 1
+#define R_SERIAL2_READ__cts___active 0
+#define R_SERIAL2_READ__cts___inactive 1
+#define R_SERIAL2_READ__tr_ready__BITNR 13
+#define R_SERIAL2_READ__tr_ready__WIDTH 1
+#define R_SERIAL2_READ__tr_ready__full 0
+#define R_SERIAL2_READ__tr_ready__ready 1
+#define R_SERIAL2_READ__rxd__BITNR 12
+#define R_SERIAL2_READ__rxd__WIDTH 1
+#define R_SERIAL2_READ__overrun__BITNR 11
+#define R_SERIAL2_READ__overrun__WIDTH 1
+#define R_SERIAL2_READ__overrun__no 0
+#define R_SERIAL2_READ__overrun__yes 1
+#define R_SERIAL2_READ__par_err__BITNR 10
+#define R_SERIAL2_READ__par_err__WIDTH 1
+#define R_SERIAL2_READ__par_err__no 0
+#define R_SERIAL2_READ__par_err__yes 1
+#define R_SERIAL2_READ__framing_err__BITNR 9
+#define R_SERIAL2_READ__framing_err__WIDTH 1
+#define R_SERIAL2_READ__framing_err__no 0
+#define R_SERIAL2_READ__framing_err__yes 1
+#define R_SERIAL2_READ__data_avail__BITNR 8
+#define R_SERIAL2_READ__data_avail__WIDTH 1
+#define R_SERIAL2_READ__data_avail__no 0
+#define R_SERIAL2_READ__data_avail__yes 1
+#define R_SERIAL2_READ__data_in__BITNR 0
+#define R_SERIAL2_READ__data_in__WIDTH 8
+
+#define R_SERIAL2_STATUS (IO_TYPECAST_RO_BYTE 0xb0000071)
+#define R_SERIAL2_STATUS__xoff_detect__BITNR 7
+#define R_SERIAL2_STATUS__xoff_detect__WIDTH 1
+#define R_SERIAL2_STATUS__xoff_detect__no_xoff 0
+#define R_SERIAL2_STATUS__xoff_detect__xoff 1
+#define R_SERIAL2_STATUS__cts___BITNR 6
+#define R_SERIAL2_STATUS__cts___WIDTH 1
+#define R_SERIAL2_STATUS__cts___active 0
+#define R_SERIAL2_STATUS__cts___inactive 1
+#define R_SERIAL2_STATUS__tr_ready__BITNR 5
+#define R_SERIAL2_STATUS__tr_ready__WIDTH 1
+#define R_SERIAL2_STATUS__tr_ready__full 0
+#define R_SERIAL2_STATUS__tr_ready__ready 1
+#define R_SERIAL2_STATUS__rxd__BITNR 4
+#define R_SERIAL2_STATUS__rxd__WIDTH 1
+#define R_SERIAL2_STATUS__overrun__BITNR 3
+#define R_SERIAL2_STATUS__overrun__WIDTH 1
+#define R_SERIAL2_STATUS__overrun__no 0
+#define R_SERIAL2_STATUS__overrun__yes 1
+#define R_SERIAL2_STATUS__par_err__BITNR 2
+#define R_SERIAL2_STATUS__par_err__WIDTH 1
+#define R_SERIAL2_STATUS__par_err__no 0
+#define R_SERIAL2_STATUS__par_err__yes 1
+#define R_SERIAL2_STATUS__framing_err__BITNR 1
+#define R_SERIAL2_STATUS__framing_err__WIDTH 1
+#define R_SERIAL2_STATUS__framing_err__no 0
+#define R_SERIAL2_STATUS__framing_err__yes 1
+#define R_SERIAL2_STATUS__data_avail__BITNR 0
+#define R_SERIAL2_STATUS__data_avail__WIDTH 1
+#define R_SERIAL2_STATUS__data_avail__no 0
+#define R_SERIAL2_STATUS__data_avail__yes 1
+
+#define R_SERIAL2_REC_DATA (IO_TYPECAST_RO_BYTE 0xb0000070)
+#define R_SERIAL2_REC_DATA__data_in__BITNR 0
+#define R_SERIAL2_REC_DATA__data_in__WIDTH 8
+
+#define R_SERIAL2_XOFF (IO_TYPECAST_UDWORD 0xb0000074)
+#define R_SERIAL2_XOFF__tx_stop__BITNR 9
+#define R_SERIAL2_XOFF__tx_stop__WIDTH 1
+#define R_SERIAL2_XOFF__tx_stop__enable 0
+#define R_SERIAL2_XOFF__tx_stop__stop 1
+#define R_SERIAL2_XOFF__auto_xoff__BITNR 8
+#define R_SERIAL2_XOFF__auto_xoff__WIDTH 1
+#define R_SERIAL2_XOFF__auto_xoff__disable 0
+#define R_SERIAL2_XOFF__auto_xoff__enable 1
+#define R_SERIAL2_XOFF__xoff_char__BITNR 0
+#define R_SERIAL2_XOFF__xoff_char__WIDTH 8
+
+#define R_SERIAL3_CTRL (IO_TYPECAST_UDWORD 0xb0000078)
+#define R_SERIAL3_CTRL__tr_baud__BITNR 28
+#define R_SERIAL3_CTRL__tr_baud__WIDTH 4
+#define R_SERIAL3_CTRL__tr_baud__c300Hz 0
+#define R_SERIAL3_CTRL__tr_baud__c600Hz 1
+#define R_SERIAL3_CTRL__tr_baud__c1200Hz 2
+#define R_SERIAL3_CTRL__tr_baud__c2400Hz 3
+#define R_SERIAL3_CTRL__tr_baud__c4800Hz 4
+#define R_SERIAL3_CTRL__tr_baud__c9600Hz 5
+#define R_SERIAL3_CTRL__tr_baud__c19k2Hz 6
+#define R_SERIAL3_CTRL__tr_baud__c38k4Hz 7
+#define R_SERIAL3_CTRL__tr_baud__c57k6Hz 8
+#define R_SERIAL3_CTRL__tr_baud__c115k2Hz 9
+#define R_SERIAL3_CTRL__tr_baud__c230k4Hz 10
+#define R_SERIAL3_CTRL__tr_baud__c460k8Hz 11
+#define R_SERIAL3_CTRL__tr_baud__c921k6Hz 12
+#define R_SERIAL3_CTRL__tr_baud__c1843k2Hz 13
+#define R_SERIAL3_CTRL__tr_baud__c6250kHz 14
+#define R_SERIAL3_CTRL__tr_baud__reserved 15
+#define R_SERIAL3_CTRL__rec_baud__BITNR 24
+#define R_SERIAL3_CTRL__rec_baud__WIDTH 4
+#define R_SERIAL3_CTRL__rec_baud__c300Hz 0
+#define R_SERIAL3_CTRL__rec_baud__c600Hz 1
+#define R_SERIAL3_CTRL__rec_baud__c1200Hz 2
+#define R_SERIAL3_CTRL__rec_baud__c2400Hz 3
+#define R_SERIAL3_CTRL__rec_baud__c4800Hz 4
+#define R_SERIAL3_CTRL__rec_baud__c9600Hz 5
+#define R_SERIAL3_CTRL__rec_baud__c19k2Hz 6
+#define R_SERIAL3_CTRL__rec_baud__c38k4Hz 7
+#define R_SERIAL3_CTRL__rec_baud__c57k6Hz 8
+#define R_SERIAL3_CTRL__rec_baud__c115k2Hz 9
+#define R_SERIAL3_CTRL__rec_baud__c230k4Hz 10
+#define R_SERIAL3_CTRL__rec_baud__c460k8Hz 11
+#define R_SERIAL3_CTRL__rec_baud__c921k6Hz 12
+#define R_SERIAL3_CTRL__rec_baud__c1843k2Hz 13
+#define R_SERIAL3_CTRL__rec_baud__c6250kHz 14
+#define R_SERIAL3_CTRL__rec_baud__reserved 15
+#define R_SERIAL3_CTRL__dma_err__BITNR 23
+#define R_SERIAL3_CTRL__dma_err__WIDTH 1
+#define R_SERIAL3_CTRL__dma_err__stop 0
+#define R_SERIAL3_CTRL__dma_err__ignore 1
+#define R_SERIAL3_CTRL__rec_enable__BITNR 22
+#define R_SERIAL3_CTRL__rec_enable__WIDTH 1
+#define R_SERIAL3_CTRL__rec_enable__disable 0
+#define R_SERIAL3_CTRL__rec_enable__enable 1
+#define R_SERIAL3_CTRL__rts___BITNR 21
+#define R_SERIAL3_CTRL__rts___WIDTH 1
+#define R_SERIAL3_CTRL__rts___active 0
+#define R_SERIAL3_CTRL__rts___inactive 1
+#define R_SERIAL3_CTRL__sampling__BITNR 20
+#define R_SERIAL3_CTRL__sampling__WIDTH 1
+#define R_SERIAL3_CTRL__sampling__middle 0
+#define R_SERIAL3_CTRL__sampling__majority 1
+#define R_SERIAL3_CTRL__rec_stick_par__BITNR 19
+#define R_SERIAL3_CTRL__rec_stick_par__WIDTH 1
+#define R_SERIAL3_CTRL__rec_stick_par__normal 0
+#define R_SERIAL3_CTRL__rec_stick_par__stick 1
+#define R_SERIAL3_CTRL__rec_par__BITNR 18
+#define R_SERIAL3_CTRL__rec_par__WIDTH 1
+#define R_SERIAL3_CTRL__rec_par__even 0
+#define R_SERIAL3_CTRL__rec_par__odd 1
+#define R_SERIAL3_CTRL__rec_par_en__BITNR 17
+#define R_SERIAL3_CTRL__rec_par_en__WIDTH 1
+#define R_SERIAL3_CTRL__rec_par_en__disable 0
+#define R_SERIAL3_CTRL__rec_par_en__enable 1
+#define R_SERIAL3_CTRL__rec_bitnr__BITNR 16
+#define R_SERIAL3_CTRL__rec_bitnr__WIDTH 1
+#define R_SERIAL3_CTRL__rec_bitnr__rec_8bit 0
+#define R_SERIAL3_CTRL__rec_bitnr__rec_7bit 1
+#define R_SERIAL3_CTRL__txd__BITNR 15
+#define R_SERIAL3_CTRL__txd__WIDTH 1
+#define R_SERIAL3_CTRL__tr_enable__BITNR 14
+#define R_SERIAL3_CTRL__tr_enable__WIDTH 1
+#define R_SERIAL3_CTRL__tr_enable__disable 0
+#define R_SERIAL3_CTRL__tr_enable__enable 1
+#define R_SERIAL3_CTRL__auto_cts__BITNR 13
+#define R_SERIAL3_CTRL__auto_cts__WIDTH 1
+#define R_SERIAL3_CTRL__auto_cts__disabled 0
+#define R_SERIAL3_CTRL__auto_cts__active 1
+#define R_SERIAL3_CTRL__stop_bits__BITNR 12
+#define R_SERIAL3_CTRL__stop_bits__WIDTH 1
+#define R_SERIAL3_CTRL__stop_bits__one_bit 0
+#define R_SERIAL3_CTRL__stop_bits__two_bits 1
+#define R_SERIAL3_CTRL__tr_stick_par__BITNR 11
+#define R_SERIAL3_CTRL__tr_stick_par__WIDTH 1
+#define R_SERIAL3_CTRL__tr_stick_par__normal 0
+#define R_SERIAL3_CTRL__tr_stick_par__stick 1
+#define R_SERIAL3_CTRL__tr_par__BITNR 10
+#define R_SERIAL3_CTRL__tr_par__WIDTH 1
+#define R_SERIAL3_CTRL__tr_par__even 0
+#define R_SERIAL3_CTRL__tr_par__odd 1
+#define R_SERIAL3_CTRL__tr_par_en__BITNR 9
+#define R_SERIAL3_CTRL__tr_par_en__WIDTH 1
+#define R_SERIAL3_CTRL__tr_par_en__disable 0
+#define R_SERIAL3_CTRL__tr_par_en__enable 1
+#define R_SERIAL3_CTRL__tr_bitnr__BITNR 8
+#define R_SERIAL3_CTRL__tr_bitnr__WIDTH 1
+#define R_SERIAL3_CTRL__tr_bitnr__tr_8bit 0
+#define R_SERIAL3_CTRL__tr_bitnr__tr_7bit 1
+#define R_SERIAL3_CTRL__data_out__BITNR 0
+#define R_SERIAL3_CTRL__data_out__WIDTH 8
+
+#define R_SERIAL3_BAUD (IO_TYPECAST_BYTE 0xb000007b)
+#define R_SERIAL3_BAUD__tr_baud__BITNR 4
+#define R_SERIAL3_BAUD__tr_baud__WIDTH 4
+#define R_SERIAL3_BAUD__tr_baud__c300Hz 0
+#define R_SERIAL3_BAUD__tr_baud__c600Hz 1
+#define R_SERIAL3_BAUD__tr_baud__c1200Hz 2
+#define R_SERIAL3_BAUD__tr_baud__c2400Hz 3
+#define R_SERIAL3_BAUD__tr_baud__c4800Hz 4
+#define R_SERIAL3_BAUD__tr_baud__c9600Hz 5
+#define R_SERIAL3_BAUD__tr_baud__c19k2Hz 6
+#define R_SERIAL3_BAUD__tr_baud__c38k4Hz 7
+#define R_SERIAL3_BAUD__tr_baud__c57k6Hz 8
+#define R_SERIAL3_BAUD__tr_baud__c115k2Hz 9
+#define R_SERIAL3_BAUD__tr_baud__c230k4Hz 10
+#define R_SERIAL3_BAUD__tr_baud__c460k8Hz 11
+#define R_SERIAL3_BAUD__tr_baud__c921k6Hz 12
+#define R_SERIAL3_BAUD__tr_baud__c1843k2Hz 13
+#define R_SERIAL3_BAUD__tr_baud__c6250kHz 14
+#define R_SERIAL3_BAUD__tr_baud__reserved 15
+#define R_SERIAL3_BAUD__rec_baud__BITNR 0
+#define R_SERIAL3_BAUD__rec_baud__WIDTH 4
+#define R_SERIAL3_BAUD__rec_baud__c300Hz 0
+#define R_SERIAL3_BAUD__rec_baud__c600Hz 1
+#define R_SERIAL3_BAUD__rec_baud__c1200Hz 2
+#define R_SERIAL3_BAUD__rec_baud__c2400Hz 3
+#define R_SERIAL3_BAUD__rec_baud__c4800Hz 4
+#define R_SERIAL3_BAUD__rec_baud__c9600Hz 5
+#define R_SERIAL3_BAUD__rec_baud__c19k2Hz 6
+#define R_SERIAL3_BAUD__rec_baud__c38k4Hz 7
+#define R_SERIAL3_BAUD__rec_baud__c57k6Hz 8
+#define R_SERIAL3_BAUD__rec_baud__c115k2Hz 9
+#define R_SERIAL3_BAUD__rec_baud__c230k4Hz 10
+#define R_SERIAL3_BAUD__rec_baud__c460k8Hz 11
+#define R_SERIAL3_BAUD__rec_baud__c921k6Hz 12
+#define R_SERIAL3_BAUD__rec_baud__c1843k2Hz 13
+#define R_SERIAL3_BAUD__rec_baud__c6250kHz 14
+#define R_SERIAL3_BAUD__rec_baud__reserved 15
+
+#define R_SERIAL3_REC_CTRL (IO_TYPECAST_BYTE 0xb000007a)
+#define R_SERIAL3_REC_CTRL__dma_err__BITNR 7
+#define R_SERIAL3_REC_CTRL__dma_err__WIDTH 1
+#define R_SERIAL3_REC_CTRL__dma_err__stop 0
+#define R_SERIAL3_REC_CTRL__dma_err__ignore 1
+#define R_SERIAL3_REC_CTRL__rec_enable__BITNR 6
+#define R_SERIAL3_REC_CTRL__rec_enable__WIDTH 1
+#define R_SERIAL3_REC_CTRL__rec_enable__disable 0
+#define R_SERIAL3_REC_CTRL__rec_enable__enable 1
+#define R_SERIAL3_REC_CTRL__rts___BITNR 5
+#define R_SERIAL3_REC_CTRL__rts___WIDTH 1
+#define R_SERIAL3_REC_CTRL__rts___active 0
+#define R_SERIAL3_REC_CTRL__rts___inactive 1
+#define R_SERIAL3_REC_CTRL__sampling__BITNR 4
+#define R_SERIAL3_REC_CTRL__sampling__WIDTH 1
+#define R_SERIAL3_REC_CTRL__sampling__middle 0
+#define R_SERIAL3_REC_CTRL__sampling__majority 1
+#define R_SERIAL3_REC_CTRL__rec_stick_par__BITNR 3
+#define R_SERIAL3_REC_CTRL__rec_stick_par__WIDTH 1
+#define R_SERIAL3_REC_CTRL__rec_stick_par__normal 0
+#define R_SERIAL3_REC_CTRL__rec_stick_par__stick 1
+#define R_SERIAL3_REC_CTRL__rec_par__BITNR 2
+#define R_SERIAL3_REC_CTRL__rec_par__WIDTH 1
+#define R_SERIAL3_REC_CTRL__rec_par__even 0
+#define R_SERIAL3_REC_CTRL__rec_par__odd 1
+#define R_SERIAL3_REC_CTRL__rec_par_en__BITNR 1
+#define R_SERIAL3_REC_CTRL__rec_par_en__WIDTH 1
+#define R_SERIAL3_REC_CTRL__rec_par_en__disable 0
+#define R_SERIAL3_REC_CTRL__rec_par_en__enable 1
+#define R_SERIAL3_REC_CTRL__rec_bitnr__BITNR 0
+#define R_SERIAL3_REC_CTRL__rec_bitnr__WIDTH 1
+#define R_SERIAL3_REC_CTRL__rec_bitnr__rec_8bit 0
+#define R_SERIAL3_REC_CTRL__rec_bitnr__rec_7bit 1
+
+#define R_SERIAL3_TR_CTRL (IO_TYPECAST_BYTE 0xb0000079)
+#define R_SERIAL3_TR_CTRL__txd__BITNR 7
+#define R_SERIAL3_TR_CTRL__txd__WIDTH 1
+#define R_SERIAL3_TR_CTRL__tr_enable__BITNR 6
+#define R_SERIAL3_TR_CTRL__tr_enable__WIDTH 1
+#define R_SERIAL3_TR_CTRL__tr_enable__disable 0
+#define R_SERIAL3_TR_CTRL__tr_enable__enable 1
+#define R_SERIAL3_TR_CTRL__auto_cts__BITNR 5
+#define R_SERIAL3_TR_CTRL__auto_cts__WIDTH 1
+#define R_SERIAL3_TR_CTRL__auto_cts__disabled 0
+#define R_SERIAL3_TR_CTRL__auto_cts__active 1
+#define R_SERIAL3_TR_CTRL__stop_bits__BITNR 4
+#define R_SERIAL3_TR_CTRL__stop_bits__WIDTH 1
+#define R_SERIAL3_TR_CTRL__stop_bits__one_bit 0
+#define R_SERIAL3_TR_CTRL__stop_bits__two_bits 1
+#define R_SERIAL3_TR_CTRL__tr_stick_par__BITNR 3
+#define R_SERIAL3_TR_CTRL__tr_stick_par__WIDTH 1
+#define R_SERIAL3_TR_CTRL__tr_stick_par__normal 0
+#define R_SERIAL3_TR_CTRL__tr_stick_par__stick 1
+#define R_SERIAL3_TR_CTRL__tr_par__BITNR 2
+#define R_SERIAL3_TR_CTRL__tr_par__WIDTH 1
+#define R_SERIAL3_TR_CTRL__tr_par__even 0
+#define R_SERIAL3_TR_CTRL__tr_par__odd 1
+#define R_SERIAL3_TR_CTRL__tr_par_en__BITNR 1
+#define R_SERIAL3_TR_CTRL__tr_par_en__WIDTH 1
+#define R_SERIAL3_TR_CTRL__tr_par_en__disable 0
+#define R_SERIAL3_TR_CTRL__tr_par_en__enable 1
+#define R_SERIAL3_TR_CTRL__tr_bitnr__BITNR 0
+#define R_SERIAL3_TR_CTRL__tr_bitnr__WIDTH 1
+#define R_SERIAL3_TR_CTRL__tr_bitnr__tr_8bit 0
+#define R_SERIAL3_TR_CTRL__tr_bitnr__tr_7bit 1
+
+#define R_SERIAL3_TR_DATA (IO_TYPECAST_BYTE 0xb0000078)
+#define R_SERIAL3_TR_DATA__data_out__BITNR 0
+#define R_SERIAL3_TR_DATA__data_out__WIDTH 8
+
+#define R_SERIAL3_READ (IO_TYPECAST_RO_UDWORD 0xb0000078)
+#define R_SERIAL3_READ__xoff_detect__BITNR 15
+#define R_SERIAL3_READ__xoff_detect__WIDTH 1
+#define R_SERIAL3_READ__xoff_detect__no_xoff 0
+#define R_SERIAL3_READ__xoff_detect__xoff 1
+#define R_SERIAL3_READ__cts___BITNR 14
+#define R_SERIAL3_READ__cts___WIDTH 1
+#define R_SERIAL3_READ__cts___active 0
+#define R_SERIAL3_READ__cts___inactive 1
+#define R_SERIAL3_READ__tr_ready__BITNR 13
+#define R_SERIAL3_READ__tr_ready__WIDTH 1
+#define R_SERIAL3_READ__tr_ready__full 0
+#define R_SERIAL3_READ__tr_ready__ready 1
+#define R_SERIAL3_READ__rxd__BITNR 12
+#define R_SERIAL3_READ__rxd__WIDTH 1
+#define R_SERIAL3_READ__overrun__BITNR 11
+#define R_SERIAL3_READ__overrun__WIDTH 1
+#define R_SERIAL3_READ__overrun__no 0
+#define R_SERIAL3_READ__overrun__yes 1
+#define R_SERIAL3_READ__par_err__BITNR 10
+#define R_SERIAL3_READ__par_err__WIDTH 1
+#define R_SERIAL3_READ__par_err__no 0
+#define R_SERIAL3_READ__par_err__yes 1
+#define R_SERIAL3_READ__framing_err__BITNR 9
+#define R_SERIAL3_READ__framing_err__WIDTH 1
+#define R_SERIAL3_READ__framing_err__no 0
+#define R_SERIAL3_READ__framing_err__yes 1
+#define R_SERIAL3_READ__data_avail__BITNR 8
+#define R_SERIAL3_READ__data_avail__WIDTH 1
+#define R_SERIAL3_READ__data_avail__no 0
+#define R_SERIAL3_READ__data_avail__yes 1
+#define R_SERIAL3_READ__data_in__BITNR 0
+#define R_SERIAL3_READ__data_in__WIDTH 8
+
+#define R_SERIAL3_STATUS (IO_TYPECAST_RO_BYTE 0xb0000079)
+#define R_SERIAL3_STATUS__xoff_detect__BITNR 7
+#define R_SERIAL3_STATUS__xoff_detect__WIDTH 1
+#define R_SERIAL3_STATUS__xoff_detect__no_xoff 0
+#define R_SERIAL3_STATUS__xoff_detect__xoff 1
+#define R_SERIAL3_STATUS__cts___BITNR 6
+#define R_SERIAL3_STATUS__cts___WIDTH 1
+#define R_SERIAL3_STATUS__cts___active 0
+#define R_SERIAL3_STATUS__cts___inactive 1
+#define R_SERIAL3_STATUS__tr_ready__BITNR 5
+#define R_SERIAL3_STATUS__tr_ready__WIDTH 1
+#define R_SERIAL3_STATUS__tr_ready__full 0
+#define R_SERIAL3_STATUS__tr_ready__ready 1
+#define R_SERIAL3_STATUS__rxd__BITNR 4
+#define R_SERIAL3_STATUS__rxd__WIDTH 1
+#define R_SERIAL3_STATUS__overrun__BITNR 3
+#define R_SERIAL3_STATUS__overrun__WIDTH 1
+#define R_SERIAL3_STATUS__overrun__no 0
+#define R_SERIAL3_STATUS__overrun__yes 1
+#define R_SERIAL3_STATUS__par_err__BITNR 2
+#define R_SERIAL3_STATUS__par_err__WIDTH 1
+#define R_SERIAL3_STATUS__par_err__no 0
+#define R_SERIAL3_STATUS__par_err__yes 1
+#define R_SERIAL3_STATUS__framing_err__BITNR 1
+#define R_SERIAL3_STATUS__framing_err__WIDTH 1
+#define R_SERIAL3_STATUS__framing_err__no 0
+#define R_SERIAL3_STATUS__framing_err__yes 1
+#define R_SERIAL3_STATUS__data_avail__BITNR 0
+#define R_SERIAL3_STATUS__data_avail__WIDTH 1
+#define R_SERIAL3_STATUS__data_avail__no 0
+#define R_SERIAL3_STATUS__data_avail__yes 1
+
+#define R_SERIAL3_REC_DATA (IO_TYPECAST_RO_BYTE 0xb0000078)
+#define R_SERIAL3_REC_DATA__data_in__BITNR 0
+#define R_SERIAL3_REC_DATA__data_in__WIDTH 8
+
+#define R_SERIAL3_XOFF (IO_TYPECAST_UDWORD 0xb000007c)
+#define R_SERIAL3_XOFF__tx_stop__BITNR 9
+#define R_SERIAL3_XOFF__tx_stop__WIDTH 1
+#define R_SERIAL3_XOFF__tx_stop__enable 0
+#define R_SERIAL3_XOFF__tx_stop__stop 1
+#define R_SERIAL3_XOFF__auto_xoff__BITNR 8
+#define R_SERIAL3_XOFF__auto_xoff__WIDTH 1
+#define R_SERIAL3_XOFF__auto_xoff__disable 0
+#define R_SERIAL3_XOFF__auto_xoff__enable 1
+#define R_SERIAL3_XOFF__xoff_char__BITNR 0
+#define R_SERIAL3_XOFF__xoff_char__WIDTH 8
+
+#define R_ALT_SER_BAUDRATE (IO_TYPECAST_UDWORD 0xb000005c)
+#define R_ALT_SER_BAUDRATE__ser3_tr__BITNR 28
+#define R_ALT_SER_BAUDRATE__ser3_tr__WIDTH 2
+#define R_ALT_SER_BAUDRATE__ser3_tr__normal 0
+#define R_ALT_SER_BAUDRATE__ser3_tr__prescale 1
+#define R_ALT_SER_BAUDRATE__ser3_tr__extern 2
+#define R_ALT_SER_BAUDRATE__ser3_tr__timer 3
+#define R_ALT_SER_BAUDRATE__ser3_rec__BITNR 24
+#define R_ALT_SER_BAUDRATE__ser3_rec__WIDTH 2
+#define R_ALT_SER_BAUDRATE__ser3_rec__normal 0
+#define R_ALT_SER_BAUDRATE__ser3_rec__prescale 1
+#define R_ALT_SER_BAUDRATE__ser3_rec__extern 2
+#define R_ALT_SER_BAUDRATE__ser3_rec__timer 3
+#define R_ALT_SER_BAUDRATE__ser2_tr__BITNR 20
+#define R_ALT_SER_BAUDRATE__ser2_tr__WIDTH 2
+#define R_ALT_SER_BAUDRATE__ser2_tr__normal 0
+#define R_ALT_SER_BAUDRATE__ser2_tr__prescale 1
+#define R_ALT_SER_BAUDRATE__ser2_tr__extern 2
+#define R_ALT_SER_BAUDRATE__ser2_tr__timer 3
+#define R_ALT_SER_BAUDRATE__ser2_rec__BITNR 16
+#define R_ALT_SER_BAUDRATE__ser2_rec__WIDTH 2
+#define R_ALT_SER_BAUDRATE__ser2_rec__normal 0
+#define R_ALT_SER_BAUDRATE__ser2_rec__prescale 1
+#define R_ALT_SER_BAUDRATE__ser2_rec__extern 2
+#define R_ALT_SER_BAUDRATE__ser2_rec__timer 3
+#define R_ALT_SER_BAUDRATE__ser1_tr__BITNR 12
+#define R_ALT_SER_BAUDRATE__ser1_tr__WIDTH 2
+#define R_ALT_SER_BAUDRATE__ser1_tr__normal 0
+#define R_ALT_SER_BAUDRATE__ser1_tr__prescale 1
+#define R_ALT_SER_BAUDRATE__ser1_tr__extern 2
+#define R_ALT_SER_BAUDRATE__ser1_tr__timer 3
+#define R_ALT_SER_BAUDRATE__ser1_rec__BITNR 8
+#define R_ALT_SER_BAUDRATE__ser1_rec__WIDTH 2
+#define R_ALT_SER_BAUDRATE__ser1_rec__normal 0
+#define R_ALT_SER_BAUDRATE__ser1_rec__prescale 1
+#define R_ALT_SER_BAUDRATE__ser1_rec__extern 2
+#define R_ALT_SER_BAUDRATE__ser1_rec__timer 3
+#define R_ALT_SER_BAUDRATE__ser0_tr__BITNR 4
+#define R_ALT_SER_BAUDRATE__ser0_tr__WIDTH 2
+#define R_ALT_SER_BAUDRATE__ser0_tr__normal 0
+#define R_ALT_SER_BAUDRATE__ser0_tr__prescale 1
+#define R_ALT_SER_BAUDRATE__ser0_tr__extern 2
+#define R_ALT_SER_BAUDRATE__ser0_tr__timer 3
+#define R_ALT_SER_BAUDRATE__ser0_rec__BITNR 0
+#define R_ALT_SER_BAUDRATE__ser0_rec__WIDTH 2
+#define R_ALT_SER_BAUDRATE__ser0_rec__normal 0
+#define R_ALT_SER_BAUDRATE__ser0_rec__prescale 1
+#define R_ALT_SER_BAUDRATE__ser0_rec__extern 2
+#define R_ALT_SER_BAUDRATE__ser0_rec__timer 3
+
+/*
+!* Network interface registers
+!*/
+
+#define R_NETWORK_SA_0 (IO_TYPECAST_UDWORD 0xb0000080)
+#define R_NETWORK_SA_0__ma0_low__BITNR 0
+#define R_NETWORK_SA_0__ma0_low__WIDTH 32
+
+#define R_NETWORK_SA_1 (IO_TYPECAST_UDWORD 0xb0000084)
+#define R_NETWORK_SA_1__ma1_low__BITNR 16
+#define R_NETWORK_SA_1__ma1_low__WIDTH 16
+#define R_NETWORK_SA_1__ma0_high__BITNR 0
+#define R_NETWORK_SA_1__ma0_high__WIDTH 16
+
+#define R_NETWORK_SA_2 (IO_TYPECAST_UDWORD 0xb0000088)
+#define R_NETWORK_SA_2__ma1_high__BITNR 0
+#define R_NETWORK_SA_2__ma1_high__WIDTH 32
+
+#define R_NETWORK_GA_0 (IO_TYPECAST_UDWORD 0xb000008c)
+#define R_NETWORK_GA_0__ga_low__BITNR 0
+#define R_NETWORK_GA_0__ga_low__WIDTH 32
+
+#define R_NETWORK_GA_1 (IO_TYPECAST_UDWORD 0xb0000090)
+#define R_NETWORK_GA_1__ga_high__BITNR 0
+#define R_NETWORK_GA_1__ga_high__WIDTH 32
+
+#define R_NETWORK_REC_CONFIG (IO_TYPECAST_UDWORD 0xb0000094)
+#define R_NETWORK_REC_CONFIG__max_size__BITNR 10
+#define R_NETWORK_REC_CONFIG__max_size__WIDTH 1
+#define R_NETWORK_REC_CONFIG__max_size__size1518 0
+#define R_NETWORK_REC_CONFIG__max_size__size1522 1
+#define R_NETWORK_REC_CONFIG__duplex__BITNR 9
+#define R_NETWORK_REC_CONFIG__duplex__WIDTH 1
+#define R_NETWORK_REC_CONFIG__duplex__full 1
+#define R_NETWORK_REC_CONFIG__duplex__half 0
+#define R_NETWORK_REC_CONFIG__bad_crc__BITNR 8
+#define R_NETWORK_REC_CONFIG__bad_crc__WIDTH 1
+#define R_NETWORK_REC_CONFIG__bad_crc__receive 1
+#define R_NETWORK_REC_CONFIG__bad_crc__discard 0
+#define R_NETWORK_REC_CONFIG__oversize__BITNR 7
+#define R_NETWORK_REC_CONFIG__oversize__WIDTH 1
+#define R_NETWORK_REC_CONFIG__oversize__receive 1
+#define R_NETWORK_REC_CONFIG__oversize__discard 0
+#define R_NETWORK_REC_CONFIG__undersize__BITNR 6
+#define R_NETWORK_REC_CONFIG__undersize__WIDTH 1
+#define R_NETWORK_REC_CONFIG__undersize__receive 1
+#define R_NETWORK_REC_CONFIG__undersize__discard 0
+#define R_NETWORK_REC_CONFIG__all_roots__BITNR 5
+#define R_NETWORK_REC_CONFIG__all_roots__WIDTH 1
+#define R_NETWORK_REC_CONFIG__all_roots__receive 1
+#define R_NETWORK_REC_CONFIG__all_roots__discard 0
+#define R_NETWORK_REC_CONFIG__tr_broadcast__BITNR 4
+#define R_NETWORK_REC_CONFIG__tr_broadcast__WIDTH 1
+#define R_NETWORK_REC_CONFIG__tr_broadcast__receive 1
+#define R_NETWORK_REC_CONFIG__tr_broadcast__discard 0
+#define R_NETWORK_REC_CONFIG__broadcast__BITNR 3
+#define R_NETWORK_REC_CONFIG__broadcast__WIDTH 1
+#define R_NETWORK_REC_CONFIG__broadcast__receive 1
+#define R_NETWORK_REC_CONFIG__broadcast__discard 0
+#define R_NETWORK_REC_CONFIG__individual__BITNR 2
+#define R_NETWORK_REC_CONFIG__individual__WIDTH 1
+#define R_NETWORK_REC_CONFIG__individual__receive 1
+#define R_NETWORK_REC_CONFIG__individual__discard 0
+#define R_NETWORK_REC_CONFIG__ma1__BITNR 1
+#define R_NETWORK_REC_CONFIG__ma1__WIDTH 1
+#define R_NETWORK_REC_CONFIG__ma1__enable 1
+#define R_NETWORK_REC_CONFIG__ma1__disable 0
+#define R_NETWORK_REC_CONFIG__ma0__BITNR 0
+#define R_NETWORK_REC_CONFIG__ma0__WIDTH 1
+#define R_NETWORK_REC_CONFIG__ma0__enable 1
+#define R_NETWORK_REC_CONFIG__ma0__disable 0
+
+#define R_NETWORK_GEN_CONFIG (IO_TYPECAST_UDWORD 0xb0000098)
+#define R_NETWORK_GEN_CONFIG__loopback__BITNR 5
+#define R_NETWORK_GEN_CONFIG__loopback__WIDTH 1
+#define R_NETWORK_GEN_CONFIG__loopback__on 1
+#define R_NETWORK_GEN_CONFIG__loopback__off 0
+#define R_NETWORK_GEN_CONFIG__frame__BITNR 4
+#define R_NETWORK_GEN_CONFIG__frame__WIDTH 1
+#define R_NETWORK_GEN_CONFIG__frame__tokenr 1
+#define R_NETWORK_GEN_CONFIG__frame__ether 0
+#define R_NETWORK_GEN_CONFIG__vg__BITNR 3
+#define R_NETWORK_GEN_CONFIG__vg__WIDTH 1
+#define R_NETWORK_GEN_CONFIG__vg__on 1
+#define R_NETWORK_GEN_CONFIG__vg__off 0
+#define R_NETWORK_GEN_CONFIG__phy__BITNR 1
+#define R_NETWORK_GEN_CONFIG__phy__WIDTH 2
+#define R_NETWORK_GEN_CONFIG__phy__sni 0
+#define R_NETWORK_GEN_CONFIG__phy__mii_clk 1
+#define R_NETWORK_GEN_CONFIG__phy__mii_err 2
+#define R_NETWORK_GEN_CONFIG__phy__mii_req 3
+#define R_NETWORK_GEN_CONFIG__enable__BITNR 0
+#define R_NETWORK_GEN_CONFIG__enable__WIDTH 1
+#define R_NETWORK_GEN_CONFIG__enable__on 1
+#define R_NETWORK_GEN_CONFIG__enable__off 0
+
+#define R_NETWORK_TR_CTRL (IO_TYPECAST_UDWORD 0xb000009c)
+#define R_NETWORK_TR_CTRL__clr_error__BITNR 8
+#define R_NETWORK_TR_CTRL__clr_error__WIDTH 1
+#define R_NETWORK_TR_CTRL__clr_error__clr 1
+#define R_NETWORK_TR_CTRL__clr_error__nop 0
+#define R_NETWORK_TR_CTRL__delay__BITNR 5
+#define R_NETWORK_TR_CTRL__delay__WIDTH 1
+#define R_NETWORK_TR_CTRL__delay__d2us 1
+#define R_NETWORK_TR_CTRL__delay__none 0
+#define R_NETWORK_TR_CTRL__cancel__BITNR 4
+#define R_NETWORK_TR_CTRL__cancel__WIDTH 1
+#define R_NETWORK_TR_CTRL__cancel__do 1
+#define R_NETWORK_TR_CTRL__cancel__dont 0
+#define R_NETWORK_TR_CTRL__cd__BITNR 3
+#define R_NETWORK_TR_CTRL__cd__WIDTH 1
+#define R_NETWORK_TR_CTRL__cd__enable 0
+#define R_NETWORK_TR_CTRL__cd__disable 1
+#define R_NETWORK_TR_CTRL__cd__ack_col 0
+#define R_NETWORK_TR_CTRL__cd__ack_crs 1
+#define R_NETWORK_TR_CTRL__retry__BITNR 2
+#define R_NETWORK_TR_CTRL__retry__WIDTH 1
+#define R_NETWORK_TR_CTRL__retry__enable 0
+#define R_NETWORK_TR_CTRL__retry__disable 1
+#define R_NETWORK_TR_CTRL__pad__BITNR 1
+#define R_NETWORK_TR_CTRL__pad__WIDTH 1
+#define R_NETWORK_TR_CTRL__pad__enable 1
+#define R_NETWORK_TR_CTRL__pad__disable 0
+#define R_NETWORK_TR_CTRL__crc__BITNR 0
+#define R_NETWORK_TR_CTRL__crc__WIDTH 1
+#define R_NETWORK_TR_CTRL__crc__enable 0
+#define R_NETWORK_TR_CTRL__crc__disable 1
+
+#define R_NETWORK_MGM_CTRL (IO_TYPECAST_UDWORD 0xb00000a0)
+#define R_NETWORK_MGM_CTRL__txd_pins__BITNR 4
+#define R_NETWORK_MGM_CTRL__txd_pins__WIDTH 4
+#define R_NETWORK_MGM_CTRL__txer_pin__BITNR 3
+#define R_NETWORK_MGM_CTRL__txer_pin__WIDTH 1
+#define R_NETWORK_MGM_CTRL__mdck__BITNR 2
+#define R_NETWORK_MGM_CTRL__mdck__WIDTH 1
+#define R_NETWORK_MGM_CTRL__mdoe__BITNR 1
+#define R_NETWORK_MGM_CTRL__mdoe__WIDTH 1
+#define R_NETWORK_MGM_CTRL__mdoe__enable 1
+#define R_NETWORK_MGM_CTRL__mdoe__disable 0
+#define R_NETWORK_MGM_CTRL__mdio__BITNR 0
+#define R_NETWORK_MGM_CTRL__mdio__WIDTH 1
+
+#define R_NETWORK_STAT (IO_TYPECAST_RO_UDWORD 0xb00000a0)
+#define R_NETWORK_STAT__rxd_pins__BITNR 4
+#define R_NETWORK_STAT__rxd_pins__WIDTH 4
+#define R_NETWORK_STAT__rxer__BITNR 3
+#define R_NETWORK_STAT__rxer__WIDTH 1
+#define R_NETWORK_STAT__underrun__BITNR 2
+#define R_NETWORK_STAT__underrun__WIDTH 1
+#define R_NETWORK_STAT__underrun__yes 1
+#define R_NETWORK_STAT__underrun__no 0
+#define R_NETWORK_STAT__exc_col__BITNR 1
+#define R_NETWORK_STAT__exc_col__WIDTH 1
+#define R_NETWORK_STAT__exc_col__yes 1
+#define R_NETWORK_STAT__exc_col__no 0
+#define R_NETWORK_STAT__mdio__BITNR 0
+#define R_NETWORK_STAT__mdio__WIDTH 1
+
+#define R_REC_COUNTERS (IO_TYPECAST_RO_UDWORD 0xb00000a4)
+#define R_REC_COUNTERS__congestion__BITNR 24
+#define R_REC_COUNTERS__congestion__WIDTH 8
+#define R_REC_COUNTERS__oversize__BITNR 16
+#define R_REC_COUNTERS__oversize__WIDTH 8
+#define R_REC_COUNTERS__alignment_error__BITNR 8
+#define R_REC_COUNTERS__alignment_error__WIDTH 8
+#define R_REC_COUNTERS__crc_error__BITNR 0
+#define R_REC_COUNTERS__crc_error__WIDTH 8
+
+#define R_TR_COUNTERS (IO_TYPECAST_RO_UDWORD 0xb00000a8)
+#define R_TR_COUNTERS__deferred__BITNR 24
+#define R_TR_COUNTERS__deferred__WIDTH 8
+#define R_TR_COUNTERS__late_col__BITNR 16
+#define R_TR_COUNTERS__late_col__WIDTH 8
+#define R_TR_COUNTERS__multiple_col__BITNR 8
+#define R_TR_COUNTERS__multiple_col__WIDTH 8
+#define R_TR_COUNTERS__single_col__BITNR 0
+#define R_TR_COUNTERS__single_col__WIDTH 8
+
+#define R_PHY_COUNTERS (IO_TYPECAST_RO_UDWORD 0xb00000ac)
+#define R_PHY_COUNTERS__sqe_test_error__BITNR 8
+#define R_PHY_COUNTERS__sqe_test_error__WIDTH 8
+#define R_PHY_COUNTERS__carrier_loss__BITNR 0
+#define R_PHY_COUNTERS__carrier_loss__WIDTH 8
+
+/*
+!* Parallel printer port registers
+!*/
+
+#define R_PAR0_CTRL_DATA (IO_TYPECAST_UDWORD 0xb0000040)
+#define R_PAR0_CTRL_DATA__peri_int__BITNR 24
+#define R_PAR0_CTRL_DATA__peri_int__WIDTH 1
+#define R_PAR0_CTRL_DATA__peri_int__ack 1
+#define R_PAR0_CTRL_DATA__peri_int__nop 0
+#define R_PAR0_CTRL_DATA__oe__BITNR 20
+#define R_PAR0_CTRL_DATA__oe__WIDTH 1
+#define R_PAR0_CTRL_DATA__oe__enable 1
+#define R_PAR0_CTRL_DATA__oe__disable 0
+#define R_PAR0_CTRL_DATA__seli__BITNR 19
+#define R_PAR0_CTRL_DATA__seli__WIDTH 1
+#define R_PAR0_CTRL_DATA__seli__active 1
+#define R_PAR0_CTRL_DATA__seli__inactive 0
+#define R_PAR0_CTRL_DATA__autofd__BITNR 18
+#define R_PAR0_CTRL_DATA__autofd__WIDTH 1
+#define R_PAR0_CTRL_DATA__autofd__active 1
+#define R_PAR0_CTRL_DATA__autofd__inactive 0
+#define R_PAR0_CTRL_DATA__strb__BITNR 17
+#define R_PAR0_CTRL_DATA__strb__WIDTH 1
+#define R_PAR0_CTRL_DATA__strb__active 1
+#define R_PAR0_CTRL_DATA__strb__inactive 0
+#define R_PAR0_CTRL_DATA__init__BITNR 16
+#define R_PAR0_CTRL_DATA__init__WIDTH 1
+#define R_PAR0_CTRL_DATA__init__active 1
+#define R_PAR0_CTRL_DATA__init__inactive 0
+#define R_PAR0_CTRL_DATA__ecp_cmd__BITNR 8
+#define R_PAR0_CTRL_DATA__ecp_cmd__WIDTH 1
+#define R_PAR0_CTRL_DATA__ecp_cmd__command 1
+#define R_PAR0_CTRL_DATA__ecp_cmd__data 0
+#define R_PAR0_CTRL_DATA__data__BITNR 0
+#define R_PAR0_CTRL_DATA__data__WIDTH 8
+
+#define R_PAR0_CTRL (IO_TYPECAST_BYTE 0xb0000042)
+#define R_PAR0_CTRL__ctrl__BITNR 0
+#define R_PAR0_CTRL__ctrl__WIDTH 5
+
+#define R_PAR0_STATUS_DATA (IO_TYPECAST_RO_UDWORD 0xb0000040)
+#define R_PAR0_STATUS_DATA__mode__BITNR 29
+#define R_PAR0_STATUS_DATA__mode__WIDTH 3
+#define R_PAR0_STATUS_DATA__mode__manual 0
+#define R_PAR0_STATUS_DATA__mode__centronics 1
+#define R_PAR0_STATUS_DATA__mode__fastbyte 2
+#define R_PAR0_STATUS_DATA__mode__nibble 3
+#define R_PAR0_STATUS_DATA__mode__byte 4
+#define R_PAR0_STATUS_DATA__mode__ecp_fwd 5
+#define R_PAR0_STATUS_DATA__mode__ecp_rev 6
+#define R_PAR0_STATUS_DATA__mode__off 7
+#define R_PAR0_STATUS_DATA__mode__epp_wr1 5
+#define R_PAR0_STATUS_DATA__mode__epp_wr2 6
+#define R_PAR0_STATUS_DATA__mode__epp_wr3 7
+#define R_PAR0_STATUS_DATA__mode__epp_rd 0
+#define R_PAR0_STATUS_DATA__perr__BITNR 28
+#define R_PAR0_STATUS_DATA__perr__WIDTH 1
+#define R_PAR0_STATUS_DATA__perr__active 1
+#define R_PAR0_STATUS_DATA__perr__inactive 0
+#define R_PAR0_STATUS_DATA__ack__BITNR 27
+#define R_PAR0_STATUS_DATA__ack__WIDTH 1
+#define R_PAR0_STATUS_DATA__ack__active 0
+#define R_PAR0_STATUS_DATA__ack__inactive 1
+#define R_PAR0_STATUS_DATA__busy__BITNR 26
+#define R_PAR0_STATUS_DATA__busy__WIDTH 1
+#define R_PAR0_STATUS_DATA__busy__active 1
+#define R_PAR0_STATUS_DATA__busy__inactive 0
+#define R_PAR0_STATUS_DATA__fault__BITNR 25
+#define R_PAR0_STATUS_DATA__fault__WIDTH 1
+#define R_PAR0_STATUS_DATA__fault__active 0
+#define R_PAR0_STATUS_DATA__fault__inactive 1
+#define R_PAR0_STATUS_DATA__sel__BITNR 24
+#define R_PAR0_STATUS_DATA__sel__WIDTH 1
+#define R_PAR0_STATUS_DATA__sel__active 1
+#define R_PAR0_STATUS_DATA__sel__inactive 0
+#define R_PAR0_STATUS_DATA__ext_mode__BITNR 23
+#define R_PAR0_STATUS_DATA__ext_mode__WIDTH 1
+#define R_PAR0_STATUS_DATA__ext_mode__enable 1
+#define R_PAR0_STATUS_DATA__ext_mode__disable 0
+#define R_PAR0_STATUS_DATA__ecp_16__BITNR 22
+#define R_PAR0_STATUS_DATA__ecp_16__WIDTH 1
+#define R_PAR0_STATUS_DATA__ecp_16__active 1
+#define R_PAR0_STATUS_DATA__ecp_16__inactive 0
+#define R_PAR0_STATUS_DATA__tr_rdy__BITNR 17
+#define R_PAR0_STATUS_DATA__tr_rdy__WIDTH 1
+#define R_PAR0_STATUS_DATA__tr_rdy__ready 1
+#define R_PAR0_STATUS_DATA__tr_rdy__busy 0
+#define R_PAR0_STATUS_DATA__dav__BITNR 16
+#define R_PAR0_STATUS_DATA__dav__WIDTH 1
+#define R_PAR0_STATUS_DATA__dav__data 1
+#define R_PAR0_STATUS_DATA__dav__nodata 0
+#define R_PAR0_STATUS_DATA__ecp_cmd__BITNR 8
+#define R_PAR0_STATUS_DATA__ecp_cmd__WIDTH 1
+#define R_PAR0_STATUS_DATA__ecp_cmd__command 1
+#define R_PAR0_STATUS_DATA__ecp_cmd__data 0
+#define R_PAR0_STATUS_DATA__data__BITNR 0
+#define R_PAR0_STATUS_DATA__data__WIDTH 8
+
+#define R_PAR0_STATUS (IO_TYPECAST_RO_UWORD 0xb0000042)
+#define R_PAR0_STATUS__mode__BITNR 13
+#define R_PAR0_STATUS__mode__WIDTH 3
+#define R_PAR0_STATUS__mode__manual 0
+#define R_PAR0_STATUS__mode__centronics 1
+#define R_PAR0_STATUS__mode__fastbyte 2
+#define R_PAR0_STATUS__mode__nibble 3
+#define R_PAR0_STATUS__mode__byte 4
+#define R_PAR0_STATUS__mode__ecp_fwd 5
+#define R_PAR0_STATUS__mode__ecp_rev 6
+#define R_PAR0_STATUS__mode__off 7
+#define R_PAR0_STATUS__mode__epp_wr1 5
+#define R_PAR0_STATUS__mode__epp_wr2 6
+#define R_PAR0_STATUS__mode__epp_wr3 7
+#define R_PAR0_STATUS__mode__epp_rd 0
+#define R_PAR0_STATUS__perr__BITNR 12
+#define R_PAR0_STATUS__perr__WIDTH 1
+#define R_PAR0_STATUS__perr__active 1
+#define R_PAR0_STATUS__perr__inactive 0
+#define R_PAR0_STATUS__ack__BITNR 11
+#define R_PAR0_STATUS__ack__WIDTH 1
+#define R_PAR0_STATUS__ack__active 0
+#define R_PAR0_STATUS__ack__inactive 1
+#define R_PAR0_STATUS__busy__BITNR 10
+#define R_PAR0_STATUS__busy__WIDTH 1
+#define R_PAR0_STATUS__busy__active 1
+#define R_PAR0_STATUS__busy__inactive 0
+#define R_PAR0_STATUS__fault__BITNR 9
+#define R_PAR0_STATUS__fault__WIDTH 1
+#define R_PAR0_STATUS__fault__active 0
+#define R_PAR0_STATUS__fault__inactive 1
+#define R_PAR0_STATUS__sel__BITNR 8
+#define R_PAR0_STATUS__sel__WIDTH 1
+#define R_PAR0_STATUS__sel__active 1
+#define R_PAR0_STATUS__sel__inactive 0
+#define R_PAR0_STATUS__ext_mode__BITNR 7
+#define R_PAR0_STATUS__ext_mode__WIDTH 1
+#define R_PAR0_STATUS__ext_mode__enable 1
+#define R_PAR0_STATUS__ext_mode__disable 0
+#define R_PAR0_STATUS__ecp_16__BITNR 6
+#define R_PAR0_STATUS__ecp_16__WIDTH 1
+#define R_PAR0_STATUS__ecp_16__active 1
+#define R_PAR0_STATUS__ecp_16__inactive 0
+#define R_PAR0_STATUS__tr_rdy__BITNR 1
+#define R_PAR0_STATUS__tr_rdy__WIDTH 1
+#define R_PAR0_STATUS__tr_rdy__ready 1
+#define R_PAR0_STATUS__tr_rdy__busy 0
+#define R_PAR0_STATUS__dav__BITNR 0
+#define R_PAR0_STATUS__dav__WIDTH 1
+#define R_PAR0_STATUS__dav__data 1
+#define R_PAR0_STATUS__dav__nodata 0
+
+#define R_PAR_ECP16_DATA (IO_TYPECAST_UWORD 0xb0000040)
+#define R_PAR_ECP16_DATA__data__BITNR 0
+#define R_PAR_ECP16_DATA__data__WIDTH 16
+
+#define R_PAR0_CONFIG (IO_TYPECAST_UDWORD 0xb0000044)
+#define R_PAR0_CONFIG__ioe__BITNR 25
+#define R_PAR0_CONFIG__ioe__WIDTH 1
+#define R_PAR0_CONFIG__ioe__inv 1
+#define R_PAR0_CONFIG__ioe__noninv 0
+#define R_PAR0_CONFIG__iseli__BITNR 24
+#define R_PAR0_CONFIG__iseli__WIDTH 1
+#define R_PAR0_CONFIG__iseli__inv 1
+#define R_PAR0_CONFIG__iseli__noninv 0
+#define R_PAR0_CONFIG__iautofd__BITNR 23
+#define R_PAR0_CONFIG__iautofd__WIDTH 1
+#define R_PAR0_CONFIG__iautofd__inv 1
+#define R_PAR0_CONFIG__iautofd__noninv 0
+#define R_PAR0_CONFIG__istrb__BITNR 22
+#define R_PAR0_CONFIG__istrb__WIDTH 1
+#define R_PAR0_CONFIG__istrb__inv 1
+#define R_PAR0_CONFIG__istrb__noninv 0
+#define R_PAR0_CONFIG__iinit__BITNR 21
+#define R_PAR0_CONFIG__iinit__WIDTH 1
+#define R_PAR0_CONFIG__iinit__inv 1
+#define R_PAR0_CONFIG__iinit__noninv 0
+#define R_PAR0_CONFIG__iperr__BITNR 20
+#define R_PAR0_CONFIG__iperr__WIDTH 1
+#define R_PAR0_CONFIG__iperr__inv 1
+#define R_PAR0_CONFIG__iperr__noninv 0
+#define R_PAR0_CONFIG__iack__BITNR 19
+#define R_PAR0_CONFIG__iack__WIDTH 1
+#define R_PAR0_CONFIG__iack__inv 1
+#define R_PAR0_CONFIG__iack__noninv 0
+#define R_PAR0_CONFIG__ibusy__BITNR 18
+#define R_PAR0_CONFIG__ibusy__WIDTH 1
+#define R_PAR0_CONFIG__ibusy__inv 1
+#define R_PAR0_CONFIG__ibusy__noninv 0
+#define R_PAR0_CONFIG__ifault__BITNR 17
+#define R_PAR0_CONFIG__ifault__WIDTH 1
+#define R_PAR0_CONFIG__ifault__inv 1
+#define R_PAR0_CONFIG__ifault__noninv 0
+#define R_PAR0_CONFIG__isel__BITNR 16
+#define R_PAR0_CONFIG__isel__WIDTH 1
+#define R_PAR0_CONFIG__isel__inv 1
+#define R_PAR0_CONFIG__isel__noninv 0
+#define R_PAR0_CONFIG__ext_mode__BITNR 11
+#define R_PAR0_CONFIG__ext_mode__WIDTH 1
+#define R_PAR0_CONFIG__ext_mode__enable 1
+#define R_PAR0_CONFIG__ext_mode__disable 0
+#define R_PAR0_CONFIG__wide__BITNR 10
+#define R_PAR0_CONFIG__wide__WIDTH 1
+#define R_PAR0_CONFIG__wide__enable 1
+#define R_PAR0_CONFIG__wide__disable 0
+#define R_PAR0_CONFIG__dma__BITNR 9
+#define R_PAR0_CONFIG__dma__WIDTH 1
+#define R_PAR0_CONFIG__dma__enable 1
+#define R_PAR0_CONFIG__dma__disable 0
+#define R_PAR0_CONFIG__rle_in__BITNR 8
+#define R_PAR0_CONFIG__rle_in__WIDTH 1
+#define R_PAR0_CONFIG__rle_in__enable 1
+#define R_PAR0_CONFIG__rle_in__disable 0
+#define R_PAR0_CONFIG__rle_out__BITNR 7
+#define R_PAR0_CONFIG__rle_out__WIDTH 1
+#define R_PAR0_CONFIG__rle_out__enable 1
+#define R_PAR0_CONFIG__rle_out__disable 0
+#define R_PAR0_CONFIG__enable__BITNR 6
+#define R_PAR0_CONFIG__enable__WIDTH 1
+#define R_PAR0_CONFIG__enable__on 1
+#define R_PAR0_CONFIG__enable__reset 0
+#define R_PAR0_CONFIG__force__BITNR 5
+#define R_PAR0_CONFIG__force__WIDTH 1
+#define R_PAR0_CONFIG__force__on 1
+#define R_PAR0_CONFIG__force__off 0
+#define R_PAR0_CONFIG__ign_ack__BITNR 4
+#define R_PAR0_CONFIG__ign_ack__WIDTH 1
+#define R_PAR0_CONFIG__ign_ack__ignore 1
+#define R_PAR0_CONFIG__ign_ack__wait 0
+#define R_PAR0_CONFIG__oe_ack__BITNR 3
+#define R_PAR0_CONFIG__oe_ack__WIDTH 1
+#define R_PAR0_CONFIG__oe_ack__wait_oe 1
+#define R_PAR0_CONFIG__oe_ack__dont_wait 0
+#define R_PAR0_CONFIG__oe_ack__epp_addr 1
+#define R_PAR0_CONFIG__oe_ack__epp_data 0
+#define R_PAR0_CONFIG__epp_addr_data__BITNR 3
+#define R_PAR0_CONFIG__epp_addr_data__WIDTH 1
+#define R_PAR0_CONFIG__epp_addr_data__wait_oe 1
+#define R_PAR0_CONFIG__epp_addr_data__dont_wait 0
+#define R_PAR0_CONFIG__epp_addr_data__epp_addr 1
+#define R_PAR0_CONFIG__epp_addr_data__epp_data 0
+#define R_PAR0_CONFIG__mode__BITNR 0
+#define R_PAR0_CONFIG__mode__WIDTH 3
+#define R_PAR0_CONFIG__mode__manual 0
+#define R_PAR0_CONFIG__mode__centronics 1
+#define R_PAR0_CONFIG__mode__fastbyte 2
+#define R_PAR0_CONFIG__mode__nibble 3
+#define R_PAR0_CONFIG__mode__byte 4
+#define R_PAR0_CONFIG__mode__ecp_fwd 5
+#define R_PAR0_CONFIG__mode__ecp_rev 6
+#define R_PAR0_CONFIG__mode__off 7
+#define R_PAR0_CONFIG__mode__epp_wr1 5
+#define R_PAR0_CONFIG__mode__epp_wr2 6
+#define R_PAR0_CONFIG__mode__epp_wr3 7
+#define R_PAR0_CONFIG__mode__epp_rd 0
+
+#define R_PAR0_DELAY (IO_TYPECAST_UDWORD 0xb0000048)
+#define R_PAR0_DELAY__fine_hold__BITNR 21
+#define R_PAR0_DELAY__fine_hold__WIDTH 3
+#define R_PAR0_DELAY__hold__BITNR 16
+#define R_PAR0_DELAY__hold__WIDTH 5
+#define R_PAR0_DELAY__fine_strb__BITNR 13
+#define R_PAR0_DELAY__fine_strb__WIDTH 3
+#define R_PAR0_DELAY__strobe__BITNR 8
+#define R_PAR0_DELAY__strobe__WIDTH 5
+#define R_PAR0_DELAY__fine_setup__BITNR 5
+#define R_PAR0_DELAY__fine_setup__WIDTH 3
+#define R_PAR0_DELAY__setup__BITNR 0
+#define R_PAR0_DELAY__setup__WIDTH 5
+
+#define R_PAR1_CTRL_DATA (IO_TYPECAST_UDWORD 0xb0000050)
+#define R_PAR1_CTRL_DATA__peri_int__BITNR 24
+#define R_PAR1_CTRL_DATA__peri_int__WIDTH 1
+#define R_PAR1_CTRL_DATA__peri_int__ack 1
+#define R_PAR1_CTRL_DATA__peri_int__nop 0
+#define R_PAR1_CTRL_DATA__oe__BITNR 20
+#define R_PAR1_CTRL_DATA__oe__WIDTH 1
+#define R_PAR1_CTRL_DATA__oe__enable 1
+#define R_PAR1_CTRL_DATA__oe__disable 0
+#define R_PAR1_CTRL_DATA__seli__BITNR 19
+#define R_PAR1_CTRL_DATA__seli__WIDTH 1
+#define R_PAR1_CTRL_DATA__seli__active 1
+#define R_PAR1_CTRL_DATA__seli__inactive 0
+#define R_PAR1_CTRL_DATA__autofd__BITNR 18
+#define R_PAR1_CTRL_DATA__autofd__WIDTH 1
+#define R_PAR1_CTRL_DATA__autofd__active 1
+#define R_PAR1_CTRL_DATA__autofd__inactive 0
+#define R_PAR1_CTRL_DATA__strb__BITNR 17
+#define R_PAR1_CTRL_DATA__strb__WIDTH 1
+#define R_PAR1_CTRL_DATA__strb__active 1
+#define R_PAR1_CTRL_DATA__strb__inactive 0
+#define R_PAR1_CTRL_DATA__init__BITNR 16
+#define R_PAR1_CTRL_DATA__init__WIDTH 1
+#define R_PAR1_CTRL_DATA__init__active 1
+#define R_PAR1_CTRL_DATA__init__inactive 0
+#define R_PAR1_CTRL_DATA__ecp_cmd__BITNR 8
+#define R_PAR1_CTRL_DATA__ecp_cmd__WIDTH 1
+#define R_PAR1_CTRL_DATA__ecp_cmd__command 1
+#define R_PAR1_CTRL_DATA__ecp_cmd__data 0
+#define R_PAR1_CTRL_DATA__data__BITNR 0
+#define R_PAR1_CTRL_DATA__data__WIDTH 8
+
+#define R_PAR1_CTRL (IO_TYPECAST_BYTE 0xb0000052)
+#define R_PAR1_CTRL__ctrl__BITNR 0
+#define R_PAR1_CTRL__ctrl__WIDTH 5
+
+#define R_PAR1_STATUS_DATA (IO_TYPECAST_RO_UDWORD 0xb0000050)
+#define R_PAR1_STATUS_DATA__mode__BITNR 29
+#define R_PAR1_STATUS_DATA__mode__WIDTH 3
+#define R_PAR1_STATUS_DATA__mode__manual 0
+#define R_PAR1_STATUS_DATA__mode__centronics 1
+#define R_PAR1_STATUS_DATA__mode__fastbyte 2
+#define R_PAR1_STATUS_DATA__mode__nibble 3
+#define R_PAR1_STATUS_DATA__mode__byte 4
+#define R_PAR1_STATUS_DATA__mode__ecp_fwd 5
+#define R_PAR1_STATUS_DATA__mode__ecp_rev 6
+#define R_PAR1_STATUS_DATA__mode__off 7
+#define R_PAR1_STATUS_DATA__mode__epp_wr1 5
+#define R_PAR1_STATUS_DATA__mode__epp_wr2 6
+#define R_PAR1_STATUS_DATA__mode__epp_wr3 7
+#define R_PAR1_STATUS_DATA__mode__epp_rd 0
+#define R_PAR1_STATUS_DATA__perr__BITNR 28
+#define R_PAR1_STATUS_DATA__perr__WIDTH 1
+#define R_PAR1_STATUS_DATA__perr__active 1
+#define R_PAR1_STATUS_DATA__perr__inactive 0
+#define R_PAR1_STATUS_DATA__ack__BITNR 27
+#define R_PAR1_STATUS_DATA__ack__WIDTH 1
+#define R_PAR1_STATUS_DATA__ack__active 0
+#define R_PAR1_STATUS_DATA__ack__inactive 1
+#define R_PAR1_STATUS_DATA__busy__BITNR 26
+#define R_PAR1_STATUS_DATA__busy__WIDTH 1
+#define R_PAR1_STATUS_DATA__busy__active 1
+#define R_PAR1_STATUS_DATA__busy__inactive 0
+#define R_PAR1_STATUS_DATA__fault__BITNR 25
+#define R_PAR1_STATUS_DATA__fault__WIDTH 1
+#define R_PAR1_STATUS_DATA__fault__active 0
+#define R_PAR1_STATUS_DATA__fault__inactive 1
+#define R_PAR1_STATUS_DATA__sel__BITNR 24
+#define R_PAR1_STATUS_DATA__sel__WIDTH 1
+#define R_PAR1_STATUS_DATA__sel__active 1
+#define R_PAR1_STATUS_DATA__sel__inactive 0
+#define R_PAR1_STATUS_DATA__ext_mode__BITNR 23
+#define R_PAR1_STATUS_DATA__ext_mode__WIDTH 1
+#define R_PAR1_STATUS_DATA__ext_mode__enable 1
+#define R_PAR1_STATUS_DATA__ext_mode__disable 0
+#define R_PAR1_STATUS_DATA__tr_rdy__BITNR 17
+#define R_PAR1_STATUS_DATA__tr_rdy__WIDTH 1
+#define R_PAR1_STATUS_DATA__tr_rdy__ready 1
+#define R_PAR1_STATUS_DATA__tr_rdy__busy 0
+#define R_PAR1_STATUS_DATA__dav__BITNR 16
+#define R_PAR1_STATUS_DATA__dav__WIDTH 1
+#define R_PAR1_STATUS_DATA__dav__data 1
+#define R_PAR1_STATUS_DATA__dav__nodata 0
+#define R_PAR1_STATUS_DATA__ecp_cmd__BITNR 8
+#define R_PAR1_STATUS_DATA__ecp_cmd__WIDTH 1
+#define R_PAR1_STATUS_DATA__ecp_cmd__command 1
+#define R_PAR1_STATUS_DATA__ecp_cmd__data 0
+#define R_PAR1_STATUS_DATA__data__BITNR 0
+#define R_PAR1_STATUS_DATA__data__WIDTH 8
+
+#define R_PAR1_STATUS (IO_TYPECAST_RO_UWORD 0xb0000052)
+#define R_PAR1_STATUS__mode__BITNR 13
+#define R_PAR1_STATUS__mode__WIDTH 3
+#define R_PAR1_STATUS__mode__manual 0
+#define R_PAR1_STATUS__mode__centronics 1
+#define R_PAR1_STATUS__mode__fastbyte 2
+#define R_PAR1_STATUS__mode__nibble 3
+#define R_PAR1_STATUS__mode__byte 4
+#define R_PAR1_STATUS__mode__ecp_fwd 5
+#define R_PAR1_STATUS__mode__ecp_rev 6
+#define R_PAR1_STATUS__mode__off 7
+#define R_PAR1_STATUS__mode__epp_wr1 5
+#define R_PAR1_STATUS__mode__epp_wr2 6
+#define R_PAR1_STATUS__mode__epp_wr3 7
+#define R_PAR1_STATUS__mode__epp_rd 0
+#define R_PAR1_STATUS__perr__BITNR 12
+#define R_PAR1_STATUS__perr__WIDTH 1
+#define R_PAR1_STATUS__perr__active 1
+#define R_PAR1_STATUS__perr__inactive 0
+#define R_PAR1_STATUS__ack__BITNR 11
+#define R_PAR1_STATUS__ack__WIDTH 1
+#define R_PAR1_STATUS__ack__active 0
+#define R_PAR1_STATUS__ack__inactive 1
+#define R_PAR1_STATUS__busy__BITNR 10
+#define R_PAR1_STATUS__busy__WIDTH 1
+#define R_PAR1_STATUS__busy__active 1
+#define R_PAR1_STATUS__busy__inactive 0
+#define R_PAR1_STATUS__fault__BITNR 9
+#define R_PAR1_STATUS__fault__WIDTH 1
+#define R_PAR1_STATUS__fault__active 0
+#define R_PAR1_STATUS__fault__inactive 1
+#define R_PAR1_STATUS__sel__BITNR 8
+#define R_PAR1_STATUS__sel__WIDTH 1
+#define R_PAR1_STATUS__sel__active 1
+#define R_PAR1_STATUS__sel__inactive 0
+#define R_PAR1_STATUS__ext_mode__BITNR 7
+#define R_PAR1_STATUS__ext_mode__WIDTH 1
+#define R_PAR1_STATUS__ext_mode__enable 1
+#define R_PAR1_STATUS__ext_mode__disable 0
+#define R_PAR1_STATUS__tr_rdy__BITNR 1
+#define R_PAR1_STATUS__tr_rdy__WIDTH 1
+#define R_PAR1_STATUS__tr_rdy__ready 1
+#define R_PAR1_STATUS__tr_rdy__busy 0
+#define R_PAR1_STATUS__dav__BITNR 0
+#define R_PAR1_STATUS__dav__WIDTH 1
+#define R_PAR1_STATUS__dav__data 1
+#define R_PAR1_STATUS__dav__nodata 0
+
+#define R_PAR1_CONFIG (IO_TYPECAST_UDWORD 0xb0000054)
+#define R_PAR1_CONFIG__ioe__BITNR 25
+#define R_PAR1_CONFIG__ioe__WIDTH 1
+#define R_PAR1_CONFIG__ioe__inv 1
+#define R_PAR1_CONFIG__ioe__noninv 0
+#define R_PAR1_CONFIG__iseli__BITNR 24
+#define R_PAR1_CONFIG__iseli__WIDTH 1
+#define R_PAR1_CONFIG__iseli__inv 1
+#define R_PAR1_CONFIG__iseli__noninv 0
+#define R_PAR1_CONFIG__iautofd__BITNR 23
+#define R_PAR1_CONFIG__iautofd__WIDTH 1
+#define R_PAR1_CONFIG__iautofd__inv 1
+#define R_PAR1_CONFIG__iautofd__noninv 0
+#define R_PAR1_CONFIG__istrb__BITNR 22
+#define R_PAR1_CONFIG__istrb__WIDTH 1
+#define R_PAR1_CONFIG__istrb__inv 1
+#define R_PAR1_CONFIG__istrb__noninv 0
+#define R_PAR1_CONFIG__iinit__BITNR 21
+#define R_PAR1_CONFIG__iinit__WIDTH 1
+#define R_PAR1_CONFIG__iinit__inv 1
+#define R_PAR1_CONFIG__iinit__noninv 0
+#define R_PAR1_CONFIG__iperr__BITNR 20
+#define R_PAR1_CONFIG__iperr__WIDTH 1
+#define R_PAR1_CONFIG__iperr__inv 1
+#define R_PAR1_CONFIG__iperr__noninv 0
+#define R_PAR1_CONFIG__iack__BITNR 19
+#define R_PAR1_CONFIG__iack__WIDTH 1
+#define R_PAR1_CONFIG__iack__inv 1
+#define R_PAR1_CONFIG__iack__noninv 0
+#define R_PAR1_CONFIG__ibusy__BITNR 18
+#define R_PAR1_CONFIG__ibusy__WIDTH 1
+#define R_PAR1_CONFIG__ibusy__inv 1
+#define R_PAR1_CONFIG__ibusy__noninv 0
+#define R_PAR1_CONFIG__ifault__BITNR 17
+#define R_PAR1_CONFIG__ifault__WIDTH 1
+#define R_PAR1_CONFIG__ifault__inv 1
+#define R_PAR1_CONFIG__ifault__noninv 0
+#define R_PAR1_CONFIG__isel__BITNR 16
+#define R_PAR1_CONFIG__isel__WIDTH 1
+#define R_PAR1_CONFIG__isel__inv 1
+#define R_PAR1_CONFIG__isel__noninv 0
+#define R_PAR1_CONFIG__ext_mode__BITNR 11
+#define R_PAR1_CONFIG__ext_mode__WIDTH 1
+#define R_PAR1_CONFIG__ext_mode__enable 1
+#define R_PAR1_CONFIG__ext_mode__disable 0
+#define R_PAR1_CONFIG__dma__BITNR 9
+#define R_PAR1_CONFIG__dma__WIDTH 1
+#define R_PAR1_CONFIG__dma__enable 1
+#define R_PAR1_CONFIG__dma__disable 0
+#define R_PAR1_CONFIG__rle_in__BITNR 8
+#define R_PAR1_CONFIG__rle_in__WIDTH 1
+#define R_PAR1_CONFIG__rle_in__enable 1
+#define R_PAR1_CONFIG__rle_in__disable 0
+#define R_PAR1_CONFIG__rle_out__BITNR 7
+#define R_PAR1_CONFIG__rle_out__WIDTH 1
+#define R_PAR1_CONFIG__rle_out__enable 1
+#define R_PAR1_CONFIG__rle_out__disable 0
+#define R_PAR1_CONFIG__enable__BITNR 6
+#define R_PAR1_CONFIG__enable__WIDTH 1
+#define R_PAR1_CONFIG__enable__on 1
+#define R_PAR1_CONFIG__enable__reset 0
+#define R_PAR1_CONFIG__force__BITNR 5
+#define R_PAR1_CONFIG__force__WIDTH 1
+#define R_PAR1_CONFIG__force__on 1
+#define R_PAR1_CONFIG__force__off 0
+#define R_PAR1_CONFIG__ign_ack__BITNR 4
+#define R_PAR1_CONFIG__ign_ack__WIDTH 1
+#define R_PAR1_CONFIG__ign_ack__ignore 1
+#define R_PAR1_CONFIG__ign_ack__wait 0
+#define R_PAR1_CONFIG__oe_ack__BITNR 3
+#define R_PAR1_CONFIG__oe_ack__WIDTH 1
+#define R_PAR1_CONFIG__oe_ack__wait_oe 1
+#define R_PAR1_CONFIG__oe_ack__dont_wait 0
+#define R_PAR1_CONFIG__oe_ack__epp_addr 1
+#define R_PAR1_CONFIG__oe_ack__epp_data 0
+#define R_PAR1_CONFIG__epp_addr_data__BITNR 3
+#define R_PAR1_CONFIG__epp_addr_data__WIDTH 1
+#define R_PAR1_CONFIG__epp_addr_data__wait_oe 1
+#define R_PAR1_CONFIG__epp_addr_data__dont_wait 0
+#define R_PAR1_CONFIG__epp_addr_data__epp_addr 1
+#define R_PAR1_CONFIG__epp_addr_data__epp_data 0
+#define R_PAR1_CONFIG__mode__BITNR 0
+#define R_PAR1_CONFIG__mode__WIDTH 3
+#define R_PAR1_CONFIG__mode__manual 0
+#define R_PAR1_CONFIG__mode__centronics 1
+#define R_PAR1_CONFIG__mode__fastbyte 2
+#define R_PAR1_CONFIG__mode__nibble 3
+#define R_PAR1_CONFIG__mode__byte 4
+#define R_PAR1_CONFIG__mode__ecp_fwd 5
+#define R_PAR1_CONFIG__mode__ecp_rev 6
+#define R_PAR1_CONFIG__mode__off 7
+#define R_PAR1_CONFIG__mode__epp_wr1 5
+#define R_PAR1_CONFIG__mode__epp_wr2 6
+#define R_PAR1_CONFIG__mode__epp_wr3 7
+#define R_PAR1_CONFIG__mode__epp_rd 0
+
+#define R_PAR1_DELAY (IO_TYPECAST_UDWORD 0xb0000058)
+#define R_PAR1_DELAY__fine_hold__BITNR 21
+#define R_PAR1_DELAY__fine_hold__WIDTH 3
+#define R_PAR1_DELAY__hold__BITNR 16
+#define R_PAR1_DELAY__hold__WIDTH 5
+#define R_PAR1_DELAY__fine_strb__BITNR 13
+#define R_PAR1_DELAY__fine_strb__WIDTH 3
+#define R_PAR1_DELAY__strobe__BITNR 8
+#define R_PAR1_DELAY__strobe__WIDTH 5
+#define R_PAR1_DELAY__fine_setup__BITNR 5
+#define R_PAR1_DELAY__fine_setup__WIDTH 3
+#define R_PAR1_DELAY__setup__BITNR 0
+#define R_PAR1_DELAY__setup__WIDTH 5
+
+/*
+!* ATA interface registers
+!*/
+
+#define R_ATA_CTRL_DATA (IO_TYPECAST_UDWORD 0xb0000040)
+#define R_ATA_CTRL_DATA__sel__BITNR 30
+#define R_ATA_CTRL_DATA__sel__WIDTH 2
+#define R_ATA_CTRL_DATA__cs1__BITNR 29
+#define R_ATA_CTRL_DATA__cs1__WIDTH 1
+#define R_ATA_CTRL_DATA__cs1__active 1
+#define R_ATA_CTRL_DATA__cs1__inactive 0
+#define R_ATA_CTRL_DATA__cs0__BITNR 28
+#define R_ATA_CTRL_DATA__cs0__WIDTH 1
+#define R_ATA_CTRL_DATA__cs0__active 1
+#define R_ATA_CTRL_DATA__cs0__inactive 0
+#define R_ATA_CTRL_DATA__addr__BITNR 25
+#define R_ATA_CTRL_DATA__addr__WIDTH 3
+#define R_ATA_CTRL_DATA__rw__BITNR 24
+#define R_ATA_CTRL_DATA__rw__WIDTH 1
+#define R_ATA_CTRL_DATA__rw__read 1
+#define R_ATA_CTRL_DATA__rw__write 0
+#define R_ATA_CTRL_DATA__src_dst__BITNR 23
+#define R_ATA_CTRL_DATA__src_dst__WIDTH 1
+#define R_ATA_CTRL_DATA__src_dst__dma 1
+#define R_ATA_CTRL_DATA__src_dst__register 0
+#define R_ATA_CTRL_DATA__handsh__BITNR 22
+#define R_ATA_CTRL_DATA__handsh__WIDTH 1
+#define R_ATA_CTRL_DATA__handsh__dma 1
+#define R_ATA_CTRL_DATA__handsh__pio 0
+#define R_ATA_CTRL_DATA__multi__BITNR 21
+#define R_ATA_CTRL_DATA__multi__WIDTH 1
+#define R_ATA_CTRL_DATA__multi__on 1
+#define R_ATA_CTRL_DATA__multi__off 0
+#define R_ATA_CTRL_DATA__dma_size__BITNR 20
+#define R_ATA_CTRL_DATA__dma_size__WIDTH 1
+#define R_ATA_CTRL_DATA__dma_size__byte 1
+#define R_ATA_CTRL_DATA__dma_size__word 0
+#define R_ATA_CTRL_DATA__data__BITNR 0
+#define R_ATA_CTRL_DATA__data__WIDTH 16
+
+#define R_ATA_STATUS_DATA (IO_TYPECAST_RO_UDWORD 0xb0000040)
+#define R_ATA_STATUS_DATA__busy__BITNR 18
+#define R_ATA_STATUS_DATA__busy__WIDTH 1
+#define R_ATA_STATUS_DATA__busy__yes 1
+#define R_ATA_STATUS_DATA__busy__no 0
+#define R_ATA_STATUS_DATA__tr_rdy__BITNR 17
+#define R_ATA_STATUS_DATA__tr_rdy__WIDTH 1
+#define R_ATA_STATUS_DATA__tr_rdy__ready 1
+#define R_ATA_STATUS_DATA__tr_rdy__busy 0
+#define R_ATA_STATUS_DATA__dav__BITNR 16
+#define R_ATA_STATUS_DATA__dav__WIDTH 1
+#define R_ATA_STATUS_DATA__dav__data 1
+#define R_ATA_STATUS_DATA__dav__nodata 0
+#define R_ATA_STATUS_DATA__data__BITNR 0
+#define R_ATA_STATUS_DATA__data__WIDTH 16
+
+#define R_ATA_CONFIG (IO_TYPECAST_UDWORD 0xb0000044)
+#define R_ATA_CONFIG__enable__BITNR 25
+#define R_ATA_CONFIG__enable__WIDTH 1
+#define R_ATA_CONFIG__enable__on 1
+#define R_ATA_CONFIG__enable__off 0
+#define R_ATA_CONFIG__dma_strobe__BITNR 20
+#define R_ATA_CONFIG__dma_strobe__WIDTH 5
+#define R_ATA_CONFIG__dma_hold__BITNR 15
+#define R_ATA_CONFIG__dma_hold__WIDTH 5
+#define R_ATA_CONFIG__pio_setup__BITNR 10
+#define R_ATA_CONFIG__pio_setup__WIDTH 5
+#define R_ATA_CONFIG__pio_strobe__BITNR 5
+#define R_ATA_CONFIG__pio_strobe__WIDTH 5
+#define R_ATA_CONFIG__pio_hold__BITNR 0
+#define R_ATA_CONFIG__pio_hold__WIDTH 5
+
+#define R_ATA_TRANSFER_CNT (IO_TYPECAST_UDWORD 0xb0000048)
+#define R_ATA_TRANSFER_CNT__count__BITNR 0
+#define R_ATA_TRANSFER_CNT__count__WIDTH 17
+
+/*
+!* SCSI registers
+!*/
+
+#define R_SCSI0_CTRL (IO_TYPECAST_UDWORD 0xb0000044)
+#define R_SCSI0_CTRL__id_type__BITNR 31
+#define R_SCSI0_CTRL__id_type__WIDTH 1
+#define R_SCSI0_CTRL__id_type__software 1
+#define R_SCSI0_CTRL__id_type__hardware 0
+#define R_SCSI0_CTRL__sel_timeout__BITNR 24
+#define R_SCSI0_CTRL__sel_timeout__WIDTH 7
+#define R_SCSI0_CTRL__synch_per__BITNR 16
+#define R_SCSI0_CTRL__synch_per__WIDTH 8
+#define R_SCSI0_CTRL__rst__BITNR 15
+#define R_SCSI0_CTRL__rst__WIDTH 1
+#define R_SCSI0_CTRL__rst__yes 1
+#define R_SCSI0_CTRL__rst__no 0
+#define R_SCSI0_CTRL__atn__BITNR 14
+#define R_SCSI0_CTRL__atn__WIDTH 1
+#define R_SCSI0_CTRL__atn__yes 1
+#define R_SCSI0_CTRL__atn__no 0
+#define R_SCSI0_CTRL__my_id__BITNR 9
+#define R_SCSI0_CTRL__my_id__WIDTH 4
+#define R_SCSI0_CTRL__target_id__BITNR 4
+#define R_SCSI0_CTRL__target_id__WIDTH 4
+#define R_SCSI0_CTRL__fast_20__BITNR 3
+#define R_SCSI0_CTRL__fast_20__WIDTH 1
+#define R_SCSI0_CTRL__fast_20__yes 1
+#define R_SCSI0_CTRL__fast_20__no 0
+#define R_SCSI0_CTRL__bus_width__BITNR 2
+#define R_SCSI0_CTRL__bus_width__WIDTH 1
+#define R_SCSI0_CTRL__bus_width__wide 1
+#define R_SCSI0_CTRL__bus_width__narrow 0
+#define R_SCSI0_CTRL__synch__BITNR 1
+#define R_SCSI0_CTRL__synch__WIDTH 1
+#define R_SCSI0_CTRL__synch__synch 1
+#define R_SCSI0_CTRL__synch__asynch 0
+#define R_SCSI0_CTRL__enable__BITNR 0
+#define R_SCSI0_CTRL__enable__WIDTH 1
+#define R_SCSI0_CTRL__enable__on 1
+#define R_SCSI0_CTRL__enable__off 0
+
+#define R_SCSI0_CMD_DATA (IO_TYPECAST_UDWORD 0xb0000040)
+#define R_SCSI0_CMD_DATA__parity_in__BITNR 26
+#define R_SCSI0_CMD_DATA__parity_in__WIDTH 1
+#define R_SCSI0_CMD_DATA__parity_in__on 0
+#define R_SCSI0_CMD_DATA__parity_in__off 1
+#define R_SCSI0_CMD_DATA__skip__BITNR 25
+#define R_SCSI0_CMD_DATA__skip__WIDTH 1
+#define R_SCSI0_CMD_DATA__skip__on 1
+#define R_SCSI0_CMD_DATA__skip__off 0
+#define R_SCSI0_CMD_DATA__clr_status__BITNR 24
+#define R_SCSI0_CMD_DATA__clr_status__WIDTH 1
+#define R_SCSI0_CMD_DATA__clr_status__yes 1
+#define R_SCSI0_CMD_DATA__clr_status__nop 0
+#define R_SCSI0_CMD_DATA__asynch_setup__BITNR 20
+#define R_SCSI0_CMD_DATA__asynch_setup__WIDTH 4
+#define R_SCSI0_CMD_DATA__command__BITNR 16
+#define R_SCSI0_CMD_DATA__command__WIDTH 4
+#define R_SCSI0_CMD_DATA__command__full_din_1 0
+#define R_SCSI0_CMD_DATA__command__full_dout_1 1
+#define R_SCSI0_CMD_DATA__command__full_stat_1 2
+#define R_SCSI0_CMD_DATA__command__resel_din 3
+#define R_SCSI0_CMD_DATA__command__resel_dout 4
+#define R_SCSI0_CMD_DATA__command__resel_stat 5
+#define R_SCSI0_CMD_DATA__command__arb_only 6
+#define R_SCSI0_CMD_DATA__command__full_din_3 8
+#define R_SCSI0_CMD_DATA__command__full_dout_3 9
+#define R_SCSI0_CMD_DATA__command__full_stat_3 10
+#define R_SCSI0_CMD_DATA__command__man_data_in 11
+#define R_SCSI0_CMD_DATA__command__man_data_out 12
+#define R_SCSI0_CMD_DATA__command__man_rat 13
+#define R_SCSI0_CMD_DATA__data_out__BITNR 0
+#define R_SCSI0_CMD_DATA__data_out__WIDTH 16
+
+#define R_SCSI0_DATA (IO_TYPECAST_UWORD 0xb0000040)
+#define R_SCSI0_DATA__data_out__BITNR 0
+#define R_SCSI0_DATA__data_out__WIDTH 16
+
+#define R_SCSI0_CMD (IO_TYPECAST_BYTE 0xb0000042)
+#define R_SCSI0_CMD__asynch_setup__BITNR 4
+#define R_SCSI0_CMD__asynch_setup__WIDTH 4
+#define R_SCSI0_CMD__command__BITNR 0
+#define R_SCSI0_CMD__command__WIDTH 4
+#define R_SCSI0_CMD__command__full_din_1 0
+#define R_SCSI0_CMD__command__full_dout_1 1
+#define R_SCSI0_CMD__command__full_stat_1 2
+#define R_SCSI0_CMD__command__resel_din 3
+#define R_SCSI0_CMD__command__resel_dout 4
+#define R_SCSI0_CMD__command__resel_stat 5
+#define R_SCSI0_CMD__command__arb_only 6
+#define R_SCSI0_CMD__command__full_din_3 8
+#define R_SCSI0_CMD__command__full_dout_3 9
+#define R_SCSI0_CMD__command__full_stat_3 10
+#define R_SCSI0_CMD__command__man_data_in 11
+#define R_SCSI0_CMD__command__man_data_out 12
+#define R_SCSI0_CMD__command__man_rat 13
+
+#define R_SCSI0_STATUS_CTRL (IO_TYPECAST_BYTE 0xb0000043)
+#define R_SCSI0_STATUS_CTRL__parity_in__BITNR 2
+#define R_SCSI0_STATUS_CTRL__parity_in__WIDTH 1
+#define R_SCSI0_STATUS_CTRL__parity_in__on 0
+#define R_SCSI0_STATUS_CTRL__parity_in__off 1
+#define R_SCSI0_STATUS_CTRL__skip__BITNR 1
+#define R_SCSI0_STATUS_CTRL__skip__WIDTH 1
+#define R_SCSI0_STATUS_CTRL__skip__on 1
+#define R_SCSI0_STATUS_CTRL__skip__off 0
+#define R_SCSI0_STATUS_CTRL__clr_status__BITNR 0
+#define R_SCSI0_STATUS_CTRL__clr_status__WIDTH 1
+#define R_SCSI0_STATUS_CTRL__clr_status__yes 1
+#define R_SCSI0_STATUS_CTRL__clr_status__nop 0
+
+#define R_SCSI0_STATUS (IO_TYPECAST_RO_UDWORD 0xb0000048)
+#define R_SCSI0_STATUS__tst_arb_won__BITNR 23
+#define R_SCSI0_STATUS__tst_arb_won__WIDTH 1
+#define R_SCSI0_STATUS__tst_resel__BITNR 22
+#define R_SCSI0_STATUS__tst_resel__WIDTH 1
+#define R_SCSI0_STATUS__parity_error__BITNR 21
+#define R_SCSI0_STATUS__parity_error__WIDTH 1
+#define R_SCSI0_STATUS__bus_reset__BITNR 20
+#define R_SCSI0_STATUS__bus_reset__WIDTH 1
+#define R_SCSI0_STATUS__bus_reset__yes 1
+#define R_SCSI0_STATUS__bus_reset__no 0
+#define R_SCSI0_STATUS__resel_target__BITNR 15
+#define R_SCSI0_STATUS__resel_target__WIDTH 4
+#define R_SCSI0_STATUS__resel__BITNR 14
+#define R_SCSI0_STATUS__resel__WIDTH 1
+#define R_SCSI0_STATUS__resel__yes 1
+#define R_SCSI0_STATUS__resel__no 0
+#define R_SCSI0_STATUS__curr_phase__BITNR 11
+#define R_SCSI0_STATUS__curr_phase__WIDTH 3
+#define R_SCSI0_STATUS__curr_phase__ph_undef 0
+#define R_SCSI0_STATUS__curr_phase__ph_msg_in 7
+#define R_SCSI0_STATUS__curr_phase__ph_msg_out 6
+#define R_SCSI0_STATUS__curr_phase__ph_status 3
+#define R_SCSI0_STATUS__curr_phase__ph_command 2
+#define R_SCSI0_STATUS__curr_phase__ph_data_in 5
+#define R_SCSI0_STATUS__curr_phase__ph_data_out 4
+#define R_SCSI0_STATUS__curr_phase__ph_resel 1
+#define R_SCSI0_STATUS__last_seq_step__BITNR 6
+#define R_SCSI0_STATUS__last_seq_step__WIDTH 5
+#define R_SCSI0_STATUS__last_seq_step__st_bus_free 24
+#define R_SCSI0_STATUS__last_seq_step__st_arbitrate 8
+#define R_SCSI0_STATUS__last_seq_step__st_resel_req 29
+#define R_SCSI0_STATUS__last_seq_step__st_msg_1 2
+#define R_SCSI0_STATUS__last_seq_step__st_manual 28
+#define R_SCSI0_STATUS__last_seq_step__st_transf_cmd 30
+#define R_SCSI0_STATUS__last_seq_step__st_msg_2 6
+#define R_SCSI0_STATUS__last_seq_step__st_msg_3 22
+#define R_SCSI0_STATUS__last_seq_step__st_answer 3
+#define R_SCSI0_STATUS__last_seq_step__st_synch_din_perr 1
+#define R_SCSI0_STATUS__last_seq_step__st_transfer_done 15
+#define R_SCSI0_STATUS__last_seq_step__st_synch_dout 0
+#define R_SCSI0_STATUS__last_seq_step__st_asynch_dout 25
+#define R_SCSI0_STATUS__last_seq_step__st_synch_din 13
+#define R_SCSI0_STATUS__last_seq_step__st_asynch_din 9
+#define R_SCSI0_STATUS__last_seq_step__st_synch_dout_ack 4
+#define R_SCSI0_STATUS__last_seq_step__st_synch_din_ack 12
+#define R_SCSI0_STATUS__last_seq_step__st_synch_din_ack_perr 5
+#define R_SCSI0_STATUS__last_seq_step__st_asynch_dout_end 11
+#define R_SCSI0_STATUS__last_seq_step__st_iwr 27
+#define R_SCSI0_STATUS__last_seq_step__st_wait_free_disc 21
+#define R_SCSI0_STATUS__last_seq_step__st_sdp_disc 7
+#define R_SCSI0_STATUS__last_seq_step__st_cc 31
+#define R_SCSI0_STATUS__last_seq_step__st_iwr_good 14
+#define R_SCSI0_STATUS__last_seq_step__st_iwr_cc 23
+#define R_SCSI0_STATUS__last_seq_step__st_wait_free_iwr_cc 17
+#define R_SCSI0_STATUS__last_seq_step__st_wait_free_cc 20
+#define R_SCSI0_STATUS__last_seq_step__st_wait_free_sdp_disc 16
+#define R_SCSI0_STATUS__last_seq_step__st_manual_req 10
+#define R_SCSI0_STATUS__last_seq_step__st_manual_din_prot 18
+#define R_SCSI0_STATUS__valid_status__BITNR 5
+#define R_SCSI0_STATUS__valid_status__WIDTH 1
+#define R_SCSI0_STATUS__valid_status__yes 1
+#define R_SCSI0_STATUS__valid_status__no 0
+#define R_SCSI0_STATUS__seq_status__BITNR 0
+#define R_SCSI0_STATUS__seq_status__WIDTH 5
+#define R_SCSI0_STATUS__seq_status__info_seq_complete 0
+#define R_SCSI0_STATUS__seq_status__info_parity_error 1
+#define R_SCSI0_STATUS__seq_status__info_unhandled_msg_in 2
+#define R_SCSI0_STATUS__seq_status__info_unexp_ph_change 3
+#define R_SCSI0_STATUS__seq_status__info_arb_lost 4
+#define R_SCSI0_STATUS__seq_status__info_sel_timeout 5
+#define R_SCSI0_STATUS__seq_status__info_unexp_bf 6
+#define R_SCSI0_STATUS__seq_status__info_illegal_op 7
+#define R_SCSI0_STATUS__seq_status__info_rec_recvd 8
+#define R_SCSI0_STATUS__seq_status__info_reselected 9
+#define R_SCSI0_STATUS__seq_status__info_unhandled_status 10
+#define R_SCSI0_STATUS__seq_status__info_bus_reset 11
+#define R_SCSI0_STATUS__seq_status__info_illegal_bf 12
+#define R_SCSI0_STATUS__seq_status__info_bus_free 13
+
+#define R_SCSI0_DATA_IN (IO_TYPECAST_RO_UWORD 0xb0000040)
+#define R_SCSI0_DATA_IN__data_in__BITNR 0
+#define R_SCSI0_DATA_IN__data_in__WIDTH 16
+
+#define R_SCSI1_CTRL (IO_TYPECAST_UDWORD 0xb0000054)
+#define R_SCSI1_CTRL__id_type__BITNR 31
+#define R_SCSI1_CTRL__id_type__WIDTH 1
+#define R_SCSI1_CTRL__id_type__software 1
+#define R_SCSI1_CTRL__id_type__hardware 0
+#define R_SCSI1_CTRL__sel_timeout__BITNR 24
+#define R_SCSI1_CTRL__sel_timeout__WIDTH 7
+#define R_SCSI1_CTRL__synch_per__BITNR 16
+#define R_SCSI1_CTRL__synch_per__WIDTH 8
+#define R_SCSI1_CTRL__rst__BITNR 15
+#define R_SCSI1_CTRL__rst__WIDTH 1
+#define R_SCSI1_CTRL__rst__yes 1
+#define R_SCSI1_CTRL__rst__no 0
+#define R_SCSI1_CTRL__atn__BITNR 14
+#define R_SCSI1_CTRL__atn__WIDTH 1
+#define R_SCSI1_CTRL__atn__yes 1
+#define R_SCSI1_CTRL__atn__no 0
+#define R_SCSI1_CTRL__my_id__BITNR 9
+#define R_SCSI1_CTRL__my_id__WIDTH 4
+#define R_SCSI1_CTRL__target_id__BITNR 4
+#define R_SCSI1_CTRL__target_id__WIDTH 4
+#define R_SCSI1_CTRL__fast_20__BITNR 3
+#define R_SCSI1_CTRL__fast_20__WIDTH 1
+#define R_SCSI1_CTRL__fast_20__yes 1
+#define R_SCSI1_CTRL__fast_20__no 0
+#define R_SCSI1_CTRL__bus_width__BITNR 2
+#define R_SCSI1_CTRL__bus_width__WIDTH 1
+#define R_SCSI1_CTRL__bus_width__wide 1
+#define R_SCSI1_CTRL__bus_width__narrow 0
+#define R_SCSI1_CTRL__synch__BITNR 1
+#define R_SCSI1_CTRL__synch__WIDTH 1
+#define R_SCSI1_CTRL__synch__synch 1
+#define R_SCSI1_CTRL__synch__asynch 0
+#define R_SCSI1_CTRL__enable__BITNR 0
+#define R_SCSI1_CTRL__enable__WIDTH 1
+#define R_SCSI1_CTRL__enable__on 1
+#define R_SCSI1_CTRL__enable__off 0
+
+#define R_SCSI1_CMD_DATA (IO_TYPECAST_UDWORD 0xb0000050)
+#define R_SCSI1_CMD_DATA__parity_in__BITNR 26
+#define R_SCSI1_CMD_DATA__parity_in__WIDTH 1
+#define R_SCSI1_CMD_DATA__parity_in__on 0
+#define R_SCSI1_CMD_DATA__parity_in__off 1
+#define R_SCSI1_CMD_DATA__skip__BITNR 25
+#define R_SCSI1_CMD_DATA__skip__WIDTH 1
+#define R_SCSI1_CMD_DATA__skip__on 1
+#define R_SCSI1_CMD_DATA__skip__off 0
+#define R_SCSI1_CMD_DATA__clr_status__BITNR 24
+#define R_SCSI1_CMD_DATA__clr_status__WIDTH 1
+#define R_SCSI1_CMD_DATA__clr_status__yes 1
+#define R_SCSI1_CMD_DATA__clr_status__nop 0
+#define R_SCSI1_CMD_DATA__asynch_setup__BITNR 20
+#define R_SCSI1_CMD_DATA__asynch_setup__WIDTH 4
+#define R_SCSI1_CMD_DATA__command__BITNR 16
+#define R_SCSI1_CMD_DATA__command__WIDTH 4
+#define R_SCSI1_CMD_DATA__command__full_din_1 0
+#define R_SCSI1_CMD_DATA__command__full_dout_1 1
+#define R_SCSI1_CMD_DATA__command__full_stat_1 2
+#define R_SCSI1_CMD_DATA__command__resel_din 3
+#define R_SCSI1_CMD_DATA__command__resel_dout 4
+#define R_SCSI1_CMD_DATA__command__resel_stat 5
+#define R_SCSI1_CMD_DATA__command__arb_only 6
+#define R_SCSI1_CMD_DATA__command__full_din_3 8
+#define R_SCSI1_CMD_DATA__command__full_dout_3 9
+#define R_SCSI1_CMD_DATA__command__full_stat_3 10
+#define R_SCSI1_CMD_DATA__command__man_data_in 11
+#define R_SCSI1_CMD_DATA__command__man_data_out 12
+#define R_SCSI1_CMD_DATA__command__man_rat 13
+#define R_SCSI1_CMD_DATA__data_out__BITNR 0
+#define R_SCSI1_CMD_DATA__data_out__WIDTH 16
+
+#define R_SCSI1_DATA (IO_TYPECAST_UWORD 0xb0000050)
+#define R_SCSI1_DATA__data_out__BITNR 0
+#define R_SCSI1_DATA__data_out__WIDTH 16
+
+#define R_SCSI1_CMD (IO_TYPECAST_BYTE 0xb0000052)
+#define R_SCSI1_CMD__asynch_setup__BITNR 4
+#define R_SCSI1_CMD__asynch_setup__WIDTH 4
+#define R_SCSI1_CMD__command__BITNR 0
+#define R_SCSI1_CMD__command__WIDTH 4
+#define R_SCSI1_CMD__command__full_din_1 0
+#define R_SCSI1_CMD__command__full_dout_1 1
+#define R_SCSI1_CMD__command__full_stat_1 2
+#define R_SCSI1_CMD__command__resel_din 3
+#define R_SCSI1_CMD__command__resel_dout 4
+#define R_SCSI1_CMD__command__resel_stat 5
+#define R_SCSI1_CMD__command__arb_only 6
+#define R_SCSI1_CMD__command__full_din_3 8
+#define R_SCSI1_CMD__command__full_dout_3 9
+#define R_SCSI1_CMD__command__full_stat_3 10
+#define R_SCSI1_CMD__command__man_data_in 11
+#define R_SCSI1_CMD__command__man_data_out 12
+#define R_SCSI1_CMD__command__man_rat 13
+
+#define R_SCSI1_STATUS_CTRL (IO_TYPECAST_BYTE 0xb0000053)
+#define R_SCSI1_STATUS_CTRL__parity_in__BITNR 2
+#define R_SCSI1_STATUS_CTRL__parity_in__WIDTH 1
+#define R_SCSI1_STATUS_CTRL__parity_in__on 0
+#define R_SCSI1_STATUS_CTRL__parity_in__off 1
+#define R_SCSI1_STATUS_CTRL__skip__BITNR 1
+#define R_SCSI1_STATUS_CTRL__skip__WIDTH 1
+#define R_SCSI1_STATUS_CTRL__skip__on 1
+#define R_SCSI1_STATUS_CTRL__skip__off 0
+#define R_SCSI1_STATUS_CTRL__clr_status__BITNR 0
+#define R_SCSI1_STATUS_CTRL__clr_status__WIDTH 1
+#define R_SCSI1_STATUS_CTRL__clr_status__yes 1
+#define R_SCSI1_STATUS_CTRL__clr_status__nop 0
+
+#define R_SCSI1_STATUS (IO_TYPECAST_RO_UDWORD 0xb0000058)
+#define R_SCSI1_STATUS__tst_arb_won__BITNR 23
+#define R_SCSI1_STATUS__tst_arb_won__WIDTH 1
+#define R_SCSI1_STATUS__tst_resel__BITNR 22
+#define R_SCSI1_STATUS__tst_resel__WIDTH 1
+#define R_SCSI1_STATUS__parity_error__BITNR 21
+#define R_SCSI1_STATUS__parity_error__WIDTH 1
+#define R_SCSI1_STATUS__bus_reset__BITNR 20
+#define R_SCSI1_STATUS__bus_reset__WIDTH 1
+#define R_SCSI1_STATUS__bus_reset__yes 1
+#define R_SCSI1_STATUS__bus_reset__no 0
+#define R_SCSI1_STATUS__resel_target__BITNR 15
+#define R_SCSI1_STATUS__resel_target__WIDTH 4
+#define R_SCSI1_STATUS__resel__BITNR 14
+#define R_SCSI1_STATUS__resel__WIDTH 1
+#define R_SCSI1_STATUS__resel__yes 1
+#define R_SCSI1_STATUS__resel__no 0
+#define R_SCSI1_STATUS__curr_phase__BITNR 11
+#define R_SCSI1_STATUS__curr_phase__WIDTH 3
+#define R_SCSI1_STATUS__curr_phase__ph_undef 0
+#define R_SCSI1_STATUS__curr_phase__ph_msg_in 7
+#define R_SCSI1_STATUS__curr_phase__ph_msg_out 6
+#define R_SCSI1_STATUS__curr_phase__ph_status 3
+#define R_SCSI1_STATUS__curr_phase__ph_command 2
+#define R_SCSI1_STATUS__curr_phase__ph_data_in 5
+#define R_SCSI1_STATUS__curr_phase__ph_data_out 4
+#define R_SCSI1_STATUS__curr_phase__ph_resel 1
+#define R_SCSI1_STATUS__last_seq_step__BITNR 6
+#define R_SCSI1_STATUS__last_seq_step__WIDTH 5
+#define R_SCSI1_STATUS__last_seq_step__st_bus_free 24
+#define R_SCSI1_STATUS__last_seq_step__st_arbitrate 8
+#define R_SCSI1_STATUS__last_seq_step__st_resel_req 29
+#define R_SCSI1_STATUS__last_seq_step__st_msg_1 2
+#define R_SCSI1_STATUS__last_seq_step__st_manual 28
+#define R_SCSI1_STATUS__last_seq_step__st_transf_cmd 30
+#define R_SCSI1_STATUS__last_seq_step__st_msg_2 6
+#define R_SCSI1_STATUS__last_seq_step__st_msg_3 22
+#define R_SCSI1_STATUS__last_seq_step__st_answer 3
+#define R_SCSI1_STATUS__last_seq_step__st_synch_din_perr 1
+#define R_SCSI1_STATUS__last_seq_step__st_transfer_done 15
+#define R_SCSI1_STATUS__last_seq_step__st_synch_dout 0
+#define R_SCSI1_STATUS__last_seq_step__st_asynch_dout 25
+#define R_SCSI1_STATUS__last_seq_step__st_synch_din 13
+#define R_SCSI1_STATUS__last_seq_step__st_asynch_din 9
+#define R_SCSI1_STATUS__last_seq_step__st_synch_dout_ack 4
+#define R_SCSI1_STATUS__last_seq_step__st_synch_din_ack 12
+#define R_SCSI1_STATUS__last_seq_step__st_synch_din_ack_perr 5
+#define R_SCSI1_STATUS__last_seq_step__st_asynch_dout_end 11
+#define R_SCSI1_STATUS__last_seq_step__st_iwr 27
+#define R_SCSI1_STATUS__last_seq_step__st_wait_free_disc 21
+#define R_SCSI1_STATUS__last_seq_step__st_sdp_disc 7
+#define R_SCSI1_STATUS__last_seq_step__st_cc 31
+#define R_SCSI1_STATUS__last_seq_step__st_iwr_good 14
+#define R_SCSI1_STATUS__last_seq_step__st_iwr_cc 23
+#define R_SCSI1_STATUS__last_seq_step__st_wait_free_iwr_cc 17
+#define R_SCSI1_STATUS__last_seq_step__st_wait_free_cc 20
+#define R_SCSI1_STATUS__last_seq_step__st_wait_free_sdp_disc 16
+#define R_SCSI1_STATUS__last_seq_step__st_manual_req 10
+#define R_SCSI1_STATUS__last_seq_step__st_manual_din_prot 18
+#define R_SCSI1_STATUS__valid_status__BITNR 5
+#define R_SCSI1_STATUS__valid_status__WIDTH 1
+#define R_SCSI1_STATUS__valid_status__yes 1
+#define R_SCSI1_STATUS__valid_status__no 0
+#define R_SCSI1_STATUS__seq_status__BITNR 0
+#define R_SCSI1_STATUS__seq_status__WIDTH 5
+#define R_SCSI1_STATUS__seq_status__info_seq_complete 0
+#define R_SCSI1_STATUS__seq_status__info_parity_error 1
+#define R_SCSI1_STATUS__seq_status__info_unhandled_msg_in 2
+#define R_SCSI1_STATUS__seq_status__info_unexp_ph_change 3
+#define R_SCSI1_STATUS__seq_status__info_arb_lost 4
+#define R_SCSI1_STATUS__seq_status__info_sel_timeout 5
+#define R_SCSI1_STATUS__seq_status__info_unexp_bf 6
+#define R_SCSI1_STATUS__seq_status__info_illegal_op 7
+#define R_SCSI1_STATUS__seq_status__info_rec_recvd 8
+#define R_SCSI1_STATUS__seq_status__info_reselected 9
+#define R_SCSI1_STATUS__seq_status__info_unhandled_status 10
+#define R_SCSI1_STATUS__seq_status__info_bus_reset 11
+#define R_SCSI1_STATUS__seq_status__info_illegal_bf 12
+#define R_SCSI1_STATUS__seq_status__info_bus_free 13
+
+#define R_SCSI1_DATA_IN (IO_TYPECAST_RO_UWORD 0xb0000050)
+#define R_SCSI1_DATA_IN__data_in__BITNR 0
+#define R_SCSI1_DATA_IN__data_in__WIDTH 16
+
+/*
+!* Interrupt mask and status registers
+!*/
+
+#define R_IRQ_MASK0_RD (IO_TYPECAST_RO_UDWORD 0xb00000c0)
+#define R_IRQ_MASK0_RD__nmi_pin__BITNR 31
+#define R_IRQ_MASK0_RD__nmi_pin__WIDTH 1
+#define R_IRQ_MASK0_RD__nmi_pin__active 1
+#define R_IRQ_MASK0_RD__nmi_pin__inactive 0
+#define R_IRQ_MASK0_RD__watchdog_nmi__BITNR 30
+#define R_IRQ_MASK0_RD__watchdog_nmi__WIDTH 1
+#define R_IRQ_MASK0_RD__watchdog_nmi__active 1
+#define R_IRQ_MASK0_RD__watchdog_nmi__inactive 0
+#define R_IRQ_MASK0_RD__sqe_test_error__BITNR 29
+#define R_IRQ_MASK0_RD__sqe_test_error__WIDTH 1
+#define R_IRQ_MASK0_RD__sqe_test_error__active 1
+#define R_IRQ_MASK0_RD__sqe_test_error__inactive 0
+#define R_IRQ_MASK0_RD__carrier_loss__BITNR 28
+#define R_IRQ_MASK0_RD__carrier_loss__WIDTH 1
+#define R_IRQ_MASK0_RD__carrier_loss__active 1
+#define R_IRQ_MASK0_RD__carrier_loss__inactive 0
+#define R_IRQ_MASK0_RD__deferred__BITNR 27
+#define R_IRQ_MASK0_RD__deferred__WIDTH 1
+#define R_IRQ_MASK0_RD__deferred__active 1
+#define R_IRQ_MASK0_RD__deferred__inactive 0
+#define R_IRQ_MASK0_RD__late_col__BITNR 26
+#define R_IRQ_MASK0_RD__late_col__WIDTH 1
+#define R_IRQ_MASK0_RD__late_col__active 1
+#define R_IRQ_MASK0_RD__late_col__inactive 0
+#define R_IRQ_MASK0_RD__multiple_col__BITNR 25
+#define R_IRQ_MASK0_RD__multiple_col__WIDTH 1
+#define R_IRQ_MASK0_RD__multiple_col__active 1
+#define R_IRQ_MASK0_RD__multiple_col__inactive 0
+#define R_IRQ_MASK0_RD__single_col__BITNR 24
+#define R_IRQ_MASK0_RD__single_col__WIDTH 1
+#define R_IRQ_MASK0_RD__single_col__active 1
+#define R_IRQ_MASK0_RD__single_col__inactive 0
+#define R_IRQ_MASK0_RD__congestion__BITNR 23
+#define R_IRQ_MASK0_RD__congestion__WIDTH 1
+#define R_IRQ_MASK0_RD__congestion__active 1
+#define R_IRQ_MASK0_RD__congestion__inactive 0
+#define R_IRQ_MASK0_RD__oversize__BITNR 22
+#define R_IRQ_MASK0_RD__oversize__WIDTH 1
+#define R_IRQ_MASK0_RD__oversize__active 1
+#define R_IRQ_MASK0_RD__oversize__inactive 0
+#define R_IRQ_MASK0_RD__alignment_error__BITNR 21
+#define R_IRQ_MASK0_RD__alignment_error__WIDTH 1
+#define R_IRQ_MASK0_RD__alignment_error__active 1
+#define R_IRQ_MASK0_RD__alignment_error__inactive 0
+#define R_IRQ_MASK0_RD__crc_error__BITNR 20
+#define R_IRQ_MASK0_RD__crc_error__WIDTH 1
+#define R_IRQ_MASK0_RD__crc_error__active 1
+#define R_IRQ_MASK0_RD__crc_error__inactive 0
+#define R_IRQ_MASK0_RD__overrun__BITNR 19
+#define R_IRQ_MASK0_RD__overrun__WIDTH 1
+#define R_IRQ_MASK0_RD__overrun__active 1
+#define R_IRQ_MASK0_RD__overrun__inactive 0
+#define R_IRQ_MASK0_RD__underrun__BITNR 18
+#define R_IRQ_MASK0_RD__underrun__WIDTH 1
+#define R_IRQ_MASK0_RD__underrun__active 1
+#define R_IRQ_MASK0_RD__underrun__inactive 0
+#define R_IRQ_MASK0_RD__excessive_col__BITNR 17
+#define R_IRQ_MASK0_RD__excessive_col__WIDTH 1
+#define R_IRQ_MASK0_RD__excessive_col__active 1
+#define R_IRQ_MASK0_RD__excessive_col__inactive 0
+#define R_IRQ_MASK0_RD__mdio__BITNR 16
+#define R_IRQ_MASK0_RD__mdio__WIDTH 1
+#define R_IRQ_MASK0_RD__mdio__active 1
+#define R_IRQ_MASK0_RD__mdio__inactive 0
+#define R_IRQ_MASK0_RD__ata_drq3__BITNR 15
+#define R_IRQ_MASK0_RD__ata_drq3__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_drq3__active 1
+#define R_IRQ_MASK0_RD__ata_drq3__inactive 0
+#define R_IRQ_MASK0_RD__ata_drq2__BITNR 14
+#define R_IRQ_MASK0_RD__ata_drq2__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_drq2__active 1
+#define R_IRQ_MASK0_RD__ata_drq2__inactive 0
+#define R_IRQ_MASK0_RD__ata_drq1__BITNR 13
+#define R_IRQ_MASK0_RD__ata_drq1__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_drq1__active 1
+#define R_IRQ_MASK0_RD__ata_drq1__inactive 0
+#define R_IRQ_MASK0_RD__ata_drq0__BITNR 12
+#define R_IRQ_MASK0_RD__ata_drq0__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_drq0__active 1
+#define R_IRQ_MASK0_RD__ata_drq0__inactive 0
+#define R_IRQ_MASK0_RD__par0_ecp_cmd__BITNR 11
+#define R_IRQ_MASK0_RD__par0_ecp_cmd__WIDTH 1
+#define R_IRQ_MASK0_RD__par0_ecp_cmd__active 1
+#define R_IRQ_MASK0_RD__par0_ecp_cmd__inactive 0
+#define R_IRQ_MASK0_RD__ata_irq3__BITNR 11
+#define R_IRQ_MASK0_RD__ata_irq3__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_irq3__active 1
+#define R_IRQ_MASK0_RD__ata_irq3__inactive 0
+#define R_IRQ_MASK0_RD__par0_peri__BITNR 10
+#define R_IRQ_MASK0_RD__par0_peri__WIDTH 1
+#define R_IRQ_MASK0_RD__par0_peri__active 1
+#define R_IRQ_MASK0_RD__par0_peri__inactive 0
+#define R_IRQ_MASK0_RD__ata_irq2__BITNR 10
+#define R_IRQ_MASK0_RD__ata_irq2__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_irq2__active 1
+#define R_IRQ_MASK0_RD__ata_irq2__inactive 0
+#define R_IRQ_MASK0_RD__par0_data__BITNR 9
+#define R_IRQ_MASK0_RD__par0_data__WIDTH 1
+#define R_IRQ_MASK0_RD__par0_data__active 1
+#define R_IRQ_MASK0_RD__par0_data__inactive 0
+#define R_IRQ_MASK0_RD__ata_irq1__BITNR 9
+#define R_IRQ_MASK0_RD__ata_irq1__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_irq1__active 1
+#define R_IRQ_MASK0_RD__ata_irq1__inactive 0
+#define R_IRQ_MASK0_RD__par0_ready__BITNR 8
+#define R_IRQ_MASK0_RD__par0_ready__WIDTH 1
+#define R_IRQ_MASK0_RD__par0_ready__active 1
+#define R_IRQ_MASK0_RD__par0_ready__inactive 0
+#define R_IRQ_MASK0_RD__ata_irq0__BITNR 8
+#define R_IRQ_MASK0_RD__ata_irq0__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_irq0__active 1
+#define R_IRQ_MASK0_RD__ata_irq0__inactive 0
+#define R_IRQ_MASK0_RD__mio__BITNR 8
+#define R_IRQ_MASK0_RD__mio__WIDTH 1
+#define R_IRQ_MASK0_RD__mio__active 1
+#define R_IRQ_MASK0_RD__mio__inactive 0
+#define R_IRQ_MASK0_RD__scsi0__BITNR 8
+#define R_IRQ_MASK0_RD__scsi0__WIDTH 1
+#define R_IRQ_MASK0_RD__scsi0__active 1
+#define R_IRQ_MASK0_RD__scsi0__inactive 0
+#define R_IRQ_MASK0_RD__ata_dmaend__BITNR 7
+#define R_IRQ_MASK0_RD__ata_dmaend__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_dmaend__active 1
+#define R_IRQ_MASK0_RD__ata_dmaend__inactive 0
+#define R_IRQ_MASK0_RD__irq_ext_vector_nr__BITNR 5
+#define R_IRQ_MASK0_RD__irq_ext_vector_nr__WIDTH 1
+#define R_IRQ_MASK0_RD__irq_ext_vector_nr__active 1
+#define R_IRQ_MASK0_RD__irq_ext_vector_nr__inactive 0
+#define R_IRQ_MASK0_RD__irq_int_vector_nr__BITNR 4
+#define R_IRQ_MASK0_RD__irq_int_vector_nr__WIDTH 1
+#define R_IRQ_MASK0_RD__irq_int_vector_nr__active 1
+#define R_IRQ_MASK0_RD__irq_int_vector_nr__inactive 0
+#define R_IRQ_MASK0_RD__ext_dma1__BITNR 3
+#define R_IRQ_MASK0_RD__ext_dma1__WIDTH 1
+#define R_IRQ_MASK0_RD__ext_dma1__active 1
+#define R_IRQ_MASK0_RD__ext_dma1__inactive 0
+#define R_IRQ_MASK0_RD__ext_dma0__BITNR 2
+#define R_IRQ_MASK0_RD__ext_dma0__WIDTH 1
+#define R_IRQ_MASK0_RD__ext_dma0__active 1
+#define R_IRQ_MASK0_RD__ext_dma0__inactive 0
+#define R_IRQ_MASK0_RD__timer1__BITNR 1
+#define R_IRQ_MASK0_RD__timer1__WIDTH 1
+#define R_IRQ_MASK0_RD__timer1__active 1
+#define R_IRQ_MASK0_RD__timer1__inactive 0
+#define R_IRQ_MASK0_RD__timer0__BITNR 0
+#define R_IRQ_MASK0_RD__timer0__WIDTH 1
+#define R_IRQ_MASK0_RD__timer0__active 1
+#define R_IRQ_MASK0_RD__timer0__inactive 0
+
+#define R_IRQ_MASK0_CLR (IO_TYPECAST_UDWORD 0xb00000c0)
+#define R_IRQ_MASK0_CLR__nmi_pin__BITNR 31
+#define R_IRQ_MASK0_CLR__nmi_pin__WIDTH 1
+#define R_IRQ_MASK0_CLR__nmi_pin__clr 1
+#define R_IRQ_MASK0_CLR__nmi_pin__nop 0
+#define R_IRQ_MASK0_CLR__watchdog_nmi__BITNR 30
+#define R_IRQ_MASK0_CLR__watchdog_nmi__WIDTH 1
+#define R_IRQ_MASK0_CLR__watchdog_nmi__clr 1
+#define R_IRQ_MASK0_CLR__watchdog_nmi__nop 0
+#define R_IRQ_MASK0_CLR__sqe_test_error__BITNR 29
+#define R_IRQ_MASK0_CLR__sqe_test_error__WIDTH 1
+#define R_IRQ_MASK0_CLR__sqe_test_error__clr 1
+#define R_IRQ_MASK0_CLR__sqe_test_error__nop 0
+#define R_IRQ_MASK0_CLR__carrier_loss__BITNR 28
+#define R_IRQ_MASK0_CLR__carrier_loss__WIDTH 1
+#define R_IRQ_MASK0_CLR__carrier_loss__clr 1
+#define R_IRQ_MASK0_CLR__carrier_loss__nop 0
+#define R_IRQ_MASK0_CLR__deferred__BITNR 27
+#define R_IRQ_MASK0_CLR__deferred__WIDTH 1
+#define R_IRQ_MASK0_CLR__deferred__clr 1
+#define R_IRQ_MASK0_CLR__deferred__nop 0
+#define R_IRQ_MASK0_CLR__late_col__BITNR 26
+#define R_IRQ_MASK0_CLR__late_col__WIDTH 1
+#define R_IRQ_MASK0_CLR__late_col__clr 1
+#define R_IRQ_MASK0_CLR__late_col__nop 0
+#define R_IRQ_MASK0_CLR__multiple_col__BITNR 25
+#define R_IRQ_MASK0_CLR__multiple_col__WIDTH 1
+#define R_IRQ_MASK0_CLR__multiple_col__clr 1
+#define R_IRQ_MASK0_CLR__multiple_col__nop 0
+#define R_IRQ_MASK0_CLR__single_col__BITNR 24
+#define R_IRQ_MASK0_CLR__single_col__WIDTH 1
+#define R_IRQ_MASK0_CLR__single_col__clr 1
+#define R_IRQ_MASK0_CLR__single_col__nop 0
+#define R_IRQ_MASK0_CLR__congestion__BITNR 23
+#define R_IRQ_MASK0_CLR__congestion__WIDTH 1
+#define R_IRQ_MASK0_CLR__congestion__clr 1
+#define R_IRQ_MASK0_CLR__congestion__nop 0
+#define R_IRQ_MASK0_CLR__oversize__BITNR 22
+#define R_IRQ_MASK0_CLR__oversize__WIDTH 1
+#define R_IRQ_MASK0_CLR__oversize__clr 1
+#define R_IRQ_MASK0_CLR__oversize__nop 0
+#define R_IRQ_MASK0_CLR__alignment_error__BITNR 21
+#define R_IRQ_MASK0_CLR__alignment_error__WIDTH 1
+#define R_IRQ_MASK0_CLR__alignment_error__clr 1
+#define R_IRQ_MASK0_CLR__alignment_error__nop 0
+#define R_IRQ_MASK0_CLR__crc_error__BITNR 20
+#define R_IRQ_MASK0_CLR__crc_error__WIDTH 1
+#define R_IRQ_MASK0_CLR__crc_error__clr 1
+#define R_IRQ_MASK0_CLR__crc_error__nop 0
+#define R_IRQ_MASK0_CLR__overrun__BITNR 19
+#define R_IRQ_MASK0_CLR__overrun__WIDTH 1
+#define R_IRQ_MASK0_CLR__overrun__clr 1
+#define R_IRQ_MASK0_CLR__overrun__nop 0
+#define R_IRQ_MASK0_CLR__underrun__BITNR 18
+#define R_IRQ_MASK0_CLR__underrun__WIDTH 1
+#define R_IRQ_MASK0_CLR__underrun__clr 1
+#define R_IRQ_MASK0_CLR__underrun__nop 0
+#define R_IRQ_MASK0_CLR__excessive_col__BITNR 17
+#define R_IRQ_MASK0_CLR__excessive_col__WIDTH 1
+#define R_IRQ_MASK0_CLR__excessive_col__clr 1
+#define R_IRQ_MASK0_CLR__excessive_col__nop 0
+#define R_IRQ_MASK0_CLR__mdio__BITNR 16
+#define R_IRQ_MASK0_CLR__mdio__WIDTH 1
+#define R_IRQ_MASK0_CLR__mdio__clr 1
+#define R_IRQ_MASK0_CLR__mdio__nop 0
+#define R_IRQ_MASK0_CLR__ata_drq3__BITNR 15
+#define R_IRQ_MASK0_CLR__ata_drq3__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_drq3__clr 1
+#define R_IRQ_MASK0_CLR__ata_drq3__nop 0
+#define R_IRQ_MASK0_CLR__ata_drq2__BITNR 14
+#define R_IRQ_MASK0_CLR__ata_drq2__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_drq2__clr 1
+#define R_IRQ_MASK0_CLR__ata_drq2__nop 0
+#define R_IRQ_MASK0_CLR__ata_drq1__BITNR 13
+#define R_IRQ_MASK0_CLR__ata_drq1__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_drq1__clr 1
+#define R_IRQ_MASK0_CLR__ata_drq1__nop 0
+#define R_IRQ_MASK0_CLR__ata_drq0__BITNR 12
+#define R_IRQ_MASK0_CLR__ata_drq0__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_drq0__clr 1
+#define R_IRQ_MASK0_CLR__ata_drq0__nop 0
+#define R_IRQ_MASK0_CLR__par0_ecp_cmd__BITNR 11
+#define R_IRQ_MASK0_CLR__par0_ecp_cmd__WIDTH 1
+#define R_IRQ_MASK0_CLR__par0_ecp_cmd__clr 1
+#define R_IRQ_MASK0_CLR__par0_ecp_cmd__nop 0
+#define R_IRQ_MASK0_CLR__ata_irq3__BITNR 11
+#define R_IRQ_MASK0_CLR__ata_irq3__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_irq3__clr 1
+#define R_IRQ_MASK0_CLR__ata_irq3__nop 0
+#define R_IRQ_MASK0_CLR__par0_peri__BITNR 10
+#define R_IRQ_MASK0_CLR__par0_peri__WIDTH 1
+#define R_IRQ_MASK0_CLR__par0_peri__clr 1
+#define R_IRQ_MASK0_CLR__par0_peri__nop 0
+#define R_IRQ_MASK0_CLR__ata_irq2__BITNR 10
+#define R_IRQ_MASK0_CLR__ata_irq2__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_irq2__clr 1
+#define R_IRQ_MASK0_CLR__ata_irq2__nop 0
+#define R_IRQ_MASK0_CLR__par0_data__BITNR 9
+#define R_IRQ_MASK0_CLR__par0_data__WIDTH 1
+#define R_IRQ_MASK0_CLR__par0_data__clr 1
+#define R_IRQ_MASK0_CLR__par0_data__nop 0
+#define R_IRQ_MASK0_CLR__ata_irq1__BITNR 9
+#define R_IRQ_MASK0_CLR__ata_irq1__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_irq1__clr 1
+#define R_IRQ_MASK0_CLR__ata_irq1__nop 0
+#define R_IRQ_MASK0_CLR__par0_ready__BITNR 8
+#define R_IRQ_MASK0_CLR__par0_ready__WIDTH 1
+#define R_IRQ_MASK0_CLR__par0_ready__clr 1
+#define R_IRQ_MASK0_CLR__par0_ready__nop 0
+#define R_IRQ_MASK0_CLR__ata_irq0__BITNR 8
+#define R_IRQ_MASK0_CLR__ata_irq0__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_irq0__clr 1
+#define R_IRQ_MASK0_CLR__ata_irq0__nop 0
+#define R_IRQ_MASK0_CLR__mio__BITNR 8
+#define R_IRQ_MASK0_CLR__mio__WIDTH 1
+#define R_IRQ_MASK0_CLR__mio__clr 1
+#define R_IRQ_MASK0_CLR__mio__nop 0
+#define R_IRQ_MASK0_CLR__scsi0__BITNR 8
+#define R_IRQ_MASK0_CLR__scsi0__WIDTH 1
+#define R_IRQ_MASK0_CLR__scsi0__clr 1
+#define R_IRQ_MASK0_CLR__scsi0__nop 0
+#define R_IRQ_MASK0_CLR__ata_dmaend__BITNR 7
+#define R_IRQ_MASK0_CLR__ata_dmaend__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_dmaend__clr 1
+#define R_IRQ_MASK0_CLR__ata_dmaend__nop 0
+#define R_IRQ_MASK0_CLR__irq_ext_vector_nr__BITNR 5
+#define R_IRQ_MASK0_CLR__irq_ext_vector_nr__WIDTH 1
+#define R_IRQ_MASK0_CLR__irq_ext_vector_nr__clr 1
+#define R_IRQ_MASK0_CLR__irq_ext_vector_nr__nop 0
+#define R_IRQ_MASK0_CLR__irq_int_vector_nr__BITNR 4
+#define R_IRQ_MASK0_CLR__irq_int_vector_nr__WIDTH 1
+#define R_IRQ_MASK0_CLR__irq_int_vector_nr__clr 1
+#define R_IRQ_MASK0_CLR__irq_int_vector_nr__nop 0
+#define R_IRQ_MASK0_CLR__ext_dma1__BITNR 3
+#define R_IRQ_MASK0_CLR__ext_dma1__WIDTH 1
+#define R_IRQ_MASK0_CLR__ext_dma1__clr 1
+#define R_IRQ_MASK0_CLR__ext_dma1__nop 0
+#define R_IRQ_MASK0_CLR__ext_dma0__BITNR 2
+#define R_IRQ_MASK0_CLR__ext_dma0__WIDTH 1
+#define R_IRQ_MASK0_CLR__ext_dma0__clr 1
+#define R_IRQ_MASK0_CLR__ext_dma0__nop 0
+#define R_IRQ_MASK0_CLR__timer1__BITNR 1
+#define R_IRQ_MASK0_CLR__timer1__WIDTH 1
+#define R_IRQ_MASK0_CLR__timer1__clr 1
+#define R_IRQ_MASK0_CLR__timer1__nop 0
+#define R_IRQ_MASK0_CLR__timer0__BITNR 0
+#define R_IRQ_MASK0_CLR__timer0__WIDTH 1
+#define R_IRQ_MASK0_CLR__timer0__clr 1
+#define R_IRQ_MASK0_CLR__timer0__nop 0
+
+#define R_IRQ_READ0 (IO_TYPECAST_RO_UDWORD 0xb00000c4)
+#define R_IRQ_READ0__nmi_pin__BITNR 31
+#define R_IRQ_READ0__nmi_pin__WIDTH 1
+#define R_IRQ_READ0__nmi_pin__active 1
+#define R_IRQ_READ0__nmi_pin__inactive 0
+#define R_IRQ_READ0__watchdog_nmi__BITNR 30
+#define R_IRQ_READ0__watchdog_nmi__WIDTH 1
+#define R_IRQ_READ0__watchdog_nmi__active 1
+#define R_IRQ_READ0__watchdog_nmi__inactive 0
+#define R_IRQ_READ0__sqe_test_error__BITNR 29
+#define R_IRQ_READ0__sqe_test_error__WIDTH 1
+#define R_IRQ_READ0__sqe_test_error__active 1
+#define R_IRQ_READ0__sqe_test_error__inactive 0
+#define R_IRQ_READ0__carrier_loss__BITNR 28
+#define R_IRQ_READ0__carrier_loss__WIDTH 1
+#define R_IRQ_READ0__carrier_loss__active 1
+#define R_IRQ_READ0__carrier_loss__inactive 0
+#define R_IRQ_READ0__deferred__BITNR 27
+#define R_IRQ_READ0__deferred__WIDTH 1
+#define R_IRQ_READ0__deferred__active 1
+#define R_IRQ_READ0__deferred__inactive 0
+#define R_IRQ_READ0__late_col__BITNR 26
+#define R_IRQ_READ0__late_col__WIDTH 1
+#define R_IRQ_READ0__late_col__active 1
+#define R_IRQ_READ0__late_col__inactive 0
+#define R_IRQ_READ0__multiple_col__BITNR 25
+#define R_IRQ_READ0__multiple_col__WIDTH 1
+#define R_IRQ_READ0__multiple_col__active 1
+#define R_IRQ_READ0__multiple_col__inactive 0
+#define R_IRQ_READ0__single_col__BITNR 24
+#define R_IRQ_READ0__single_col__WIDTH 1
+#define R_IRQ_READ0__single_col__active 1
+#define R_IRQ_READ0__single_col__inactive 0
+#define R_IRQ_READ0__congestion__BITNR 23
+#define R_IRQ_READ0__congestion__WIDTH 1
+#define R_IRQ_READ0__congestion__active 1
+#define R_IRQ_READ0__congestion__inactive 0
+#define R_IRQ_READ0__oversize__BITNR 22
+#define R_IRQ_READ0__oversize__WIDTH 1
+#define R_IRQ_READ0__oversize__active 1
+#define R_IRQ_READ0__oversize__inactive 0
+#define R_IRQ_READ0__alignment_error__BITNR 21
+#define R_IRQ_READ0__alignment_error__WIDTH 1
+#define R_IRQ_READ0__alignment_error__active 1
+#define R_IRQ_READ0__alignment_error__inactive 0
+#define R_IRQ_READ0__crc_error__BITNR 20
+#define R_IRQ_READ0__crc_error__WIDTH 1
+#define R_IRQ_READ0__crc_error__active 1
+#define R_IRQ_READ0__crc_error__inactive 0
+#define R_IRQ_READ0__overrun__BITNR 19
+#define R_IRQ_READ0__overrun__WIDTH 1
+#define R_IRQ_READ0__overrun__active 1
+#define R_IRQ_READ0__overrun__inactive 0
+#define R_IRQ_READ0__underrun__BITNR 18
+#define R_IRQ_READ0__underrun__WIDTH 1
+#define R_IRQ_READ0__underrun__active 1
+#define R_IRQ_READ0__underrun__inactive 0
+#define R_IRQ_READ0__excessive_col__BITNR 17
+#define R_IRQ_READ0__excessive_col__WIDTH 1
+#define R_IRQ_READ0__excessive_col__active 1
+#define R_IRQ_READ0__excessive_col__inactive 0
+#define R_IRQ_READ0__mdio__BITNR 16
+#define R_IRQ_READ0__mdio__WIDTH 1
+#define R_IRQ_READ0__mdio__active 1
+#define R_IRQ_READ0__mdio__inactive 0
+#define R_IRQ_READ0__ata_drq3__BITNR 15
+#define R_IRQ_READ0__ata_drq3__WIDTH 1
+#define R_IRQ_READ0__ata_drq3__active 1
+#define R_IRQ_READ0__ata_drq3__inactive 0
+#define R_IRQ_READ0__ata_drq2__BITNR 14
+#define R_IRQ_READ0__ata_drq2__WIDTH 1
+#define R_IRQ_READ0__ata_drq2__active 1
+#define R_IRQ_READ0__ata_drq2__inactive 0
+#define R_IRQ_READ0__ata_drq1__BITNR 13
+#define R_IRQ_READ0__ata_drq1__WIDTH 1
+#define R_IRQ_READ0__ata_drq1__active 1
+#define R_IRQ_READ0__ata_drq1__inactive 0
+#define R_IRQ_READ0__ata_drq0__BITNR 12
+#define R_IRQ_READ0__ata_drq0__WIDTH 1
+#define R_IRQ_READ0__ata_drq0__active 1
+#define R_IRQ_READ0__ata_drq0__inactive 0
+#define R_IRQ_READ0__par0_ecp_cmd__BITNR 11
+#define R_IRQ_READ0__par0_ecp_cmd__WIDTH 1
+#define R_IRQ_READ0__par0_ecp_cmd__active 1
+#define R_IRQ_READ0__par0_ecp_cmd__inactive 0
+#define R_IRQ_READ0__ata_irq3__BITNR 11
+#define R_IRQ_READ0__ata_irq3__WIDTH 1
+#define R_IRQ_READ0__ata_irq3__active 1
+#define R_IRQ_READ0__ata_irq3__inactive 0
+#define R_IRQ_READ0__par0_peri__BITNR 10
+#define R_IRQ_READ0__par0_peri__WIDTH 1
+#define R_IRQ_READ0__par0_peri__active 1
+#define R_IRQ_READ0__par0_peri__inactive 0
+#define R_IRQ_READ0__ata_irq2__BITNR 10
+#define R_IRQ_READ0__ata_irq2__WIDTH 1
+#define R_IRQ_READ0__ata_irq2__active 1
+#define R_IRQ_READ0__ata_irq2__inactive 0
+#define R_IRQ_READ0__par0_data__BITNR 9
+#define R_IRQ_READ0__par0_data__WIDTH 1
+#define R_IRQ_READ0__par0_data__active 1
+#define R_IRQ_READ0__par0_data__inactive 0
+#define R_IRQ_READ0__ata_irq1__BITNR 9
+#define R_IRQ_READ0__ata_irq1__WIDTH 1
+#define R_IRQ_READ0__ata_irq1__active 1
+#define R_IRQ_READ0__ata_irq1__inactive 0
+#define R_IRQ_READ0__par0_ready__BITNR 8
+#define R_IRQ_READ0__par0_ready__WIDTH 1
+#define R_IRQ_READ0__par0_ready__active 1
+#define R_IRQ_READ0__par0_ready__inactive 0
+#define R_IRQ_READ0__ata_irq0__BITNR 8
+#define R_IRQ_READ0__ata_irq0__WIDTH 1
+#define R_IRQ_READ0__ata_irq0__active 1
+#define R_IRQ_READ0__ata_irq0__inactive 0
+#define R_IRQ_READ0__mio__BITNR 8
+#define R_IRQ_READ0__mio__WIDTH 1
+#define R_IRQ_READ0__mio__active 1
+#define R_IRQ_READ0__mio__inactive 0
+#define R_IRQ_READ0__scsi0__BITNR 8
+#define R_IRQ_READ0__scsi0__WIDTH 1
+#define R_IRQ_READ0__scsi0__active 1
+#define R_IRQ_READ0__scsi0__inactive 0
+#define R_IRQ_READ0__ata_dmaend__BITNR 7
+#define R_IRQ_READ0__ata_dmaend__WIDTH 1
+#define R_IRQ_READ0__ata_dmaend__active 1
+#define R_IRQ_READ0__ata_dmaend__inactive 0
+#define R_IRQ_READ0__irq_ext_vector_nr__BITNR 5
+#define R_IRQ_READ0__irq_ext_vector_nr__WIDTH 1
+#define R_IRQ_READ0__irq_ext_vector_nr__active 1
+#define R_IRQ_READ0__irq_ext_vector_nr__inactive 0
+#define R_IRQ_READ0__irq_int_vector_nr__BITNR 4
+#define R_IRQ_READ0__irq_int_vector_nr__WIDTH 1
+#define R_IRQ_READ0__irq_int_vector_nr__active 1
+#define R_IRQ_READ0__irq_int_vector_nr__inactive 0
+#define R_IRQ_READ0__ext_dma1__BITNR 3
+#define R_IRQ_READ0__ext_dma1__WIDTH 1
+#define R_IRQ_READ0__ext_dma1__active 1
+#define R_IRQ_READ0__ext_dma1__inactive 0
+#define R_IRQ_READ0__ext_dma0__BITNR 2
+#define R_IRQ_READ0__ext_dma0__WIDTH 1
+#define R_IRQ_READ0__ext_dma0__active 1
+#define R_IRQ_READ0__ext_dma0__inactive 0
+#define R_IRQ_READ0__timer1__BITNR 1
+#define R_IRQ_READ0__timer1__WIDTH 1
+#define R_IRQ_READ0__timer1__active 1
+#define R_IRQ_READ0__timer1__inactive 0
+#define R_IRQ_READ0__timer0__BITNR 0
+#define R_IRQ_READ0__timer0__WIDTH 1
+#define R_IRQ_READ0__timer0__active 1
+#define R_IRQ_READ0__timer0__inactive 0
+
+#define R_IRQ_MASK0_SET (IO_TYPECAST_UDWORD 0xb00000c4)
+#define R_IRQ_MASK0_SET__nmi_pin__BITNR 31
+#define R_IRQ_MASK0_SET__nmi_pin__WIDTH 1
+#define R_IRQ_MASK0_SET__nmi_pin__set 1
+#define R_IRQ_MASK0_SET__nmi_pin__nop 0
+#define R_IRQ_MASK0_SET__watchdog_nmi__BITNR 30
+#define R_IRQ_MASK0_SET__watchdog_nmi__WIDTH 1
+#define R_IRQ_MASK0_SET__watchdog_nmi__set 1
+#define R_IRQ_MASK0_SET__watchdog_nmi__nop 0
+#define R_IRQ_MASK0_SET__sqe_test_error__BITNR 29
+#define R_IRQ_MASK0_SET__sqe_test_error__WIDTH 1
+#define R_IRQ_MASK0_SET__sqe_test_error__set 1
+#define R_IRQ_MASK0_SET__sqe_test_error__nop 0
+#define R_IRQ_MASK0_SET__carrier_loss__BITNR 28
+#define R_IRQ_MASK0_SET__carrier_loss__WIDTH 1
+#define R_IRQ_MASK0_SET__carrier_loss__set 1
+#define R_IRQ_MASK0_SET__carrier_loss__nop 0
+#define R_IRQ_MASK0_SET__deferred__BITNR 27
+#define R_IRQ_MASK0_SET__deferred__WIDTH 1
+#define R_IRQ_MASK0_SET__deferred__set 1
+#define R_IRQ_MASK0_SET__deferred__nop 0
+#define R_IRQ_MASK0_SET__late_col__BITNR 26
+#define R_IRQ_MASK0_SET__late_col__WIDTH 1
+#define R_IRQ_MASK0_SET__late_col__set 1
+#define R_IRQ_MASK0_SET__late_col__nop 0
+#define R_IRQ_MASK0_SET__multiple_col__BITNR 25
+#define R_IRQ_MASK0_SET__multiple_col__WIDTH 1
+#define R_IRQ_MASK0_SET__multiple_col__set 1
+#define R_IRQ_MASK0_SET__multiple_col__nop 0
+#define R_IRQ_MASK0_SET__single_col__BITNR 24
+#define R_IRQ_MASK0_SET__single_col__WIDTH 1
+#define R_IRQ_MASK0_SET__single_col__set 1
+#define R_IRQ_MASK0_SET__single_col__nop 0
+#define R_IRQ_MASK0_SET__congestion__BITNR 23
+#define R_IRQ_MASK0_SET__congestion__WIDTH 1
+#define R_IRQ_MASK0_SET__congestion__set 1
+#define R_IRQ_MASK0_SET__congestion__nop 0
+#define R_IRQ_MASK0_SET__oversize__BITNR 22
+#define R_IRQ_MASK0_SET__oversize__WIDTH 1
+#define R_IRQ_MASK0_SET__oversize__set 1
+#define R_IRQ_MASK0_SET__oversize__nop 0
+#define R_IRQ_MASK0_SET__alignment_error__BITNR 21
+#define R_IRQ_MASK0_SET__alignment_error__WIDTH 1
+#define R_IRQ_MASK0_SET__alignment_error__set 1
+#define R_IRQ_MASK0_SET__alignment_error__nop 0
+#define R_IRQ_MASK0_SET__crc_error__BITNR 20
+#define R_IRQ_MASK0_SET__crc_error__WIDTH 1
+#define R_IRQ_MASK0_SET__crc_error__set 1
+#define R_IRQ_MASK0_SET__crc_error__nop 0
+#define R_IRQ_MASK0_SET__overrun__BITNR 19
+#define R_IRQ_MASK0_SET__overrun__WIDTH 1
+#define R_IRQ_MASK0_SET__overrun__set 1
+#define R_IRQ_MASK0_SET__overrun__nop 0
+#define R_IRQ_MASK0_SET__underrun__BITNR 18
+#define R_IRQ_MASK0_SET__underrun__WIDTH 1
+#define R_IRQ_MASK0_SET__underrun__set 1
+#define R_IRQ_MASK0_SET__underrun__nop 0
+#define R_IRQ_MASK0_SET__excessive_col__BITNR 17
+#define R_IRQ_MASK0_SET__excessive_col__WIDTH 1
+#define R_IRQ_MASK0_SET__excessive_col__set 1
+#define R_IRQ_MASK0_SET__excessive_col__nop 0
+#define R_IRQ_MASK0_SET__mdio__BITNR 16
+#define R_IRQ_MASK0_SET__mdio__WIDTH 1
+#define R_IRQ_MASK0_SET__mdio__set 1
+#define R_IRQ_MASK0_SET__mdio__nop 0
+#define R_IRQ_MASK0_SET__ata_drq3__BITNR 15
+#define R_IRQ_MASK0_SET__ata_drq3__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_drq3__set 1
+#define R_IRQ_MASK0_SET__ata_drq3__nop 0
+#define R_IRQ_MASK0_SET__ata_drq2__BITNR 14
+#define R_IRQ_MASK0_SET__ata_drq2__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_drq2__set 1
+#define R_IRQ_MASK0_SET__ata_drq2__nop 0
+#define R_IRQ_MASK0_SET__ata_drq1__BITNR 13
+#define R_IRQ_MASK0_SET__ata_drq1__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_drq1__set 1
+#define R_IRQ_MASK0_SET__ata_drq1__nop 0
+#define R_IRQ_MASK0_SET__ata_drq0__BITNR 12
+#define R_IRQ_MASK0_SET__ata_drq0__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_drq0__set 1
+#define R_IRQ_MASK0_SET__ata_drq0__nop 0
+#define R_IRQ_MASK0_SET__par0_ecp_cmd__BITNR 11
+#define R_IRQ_MASK0_SET__par0_ecp_cmd__WIDTH 1
+#define R_IRQ_MASK0_SET__par0_ecp_cmd__set 1
+#define R_IRQ_MASK0_SET__par0_ecp_cmd__nop 0
+#define R_IRQ_MASK0_SET__ata_irq3__BITNR 11
+#define R_IRQ_MASK0_SET__ata_irq3__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_irq3__set 1
+#define R_IRQ_MASK0_SET__ata_irq3__nop 0
+#define R_IRQ_MASK0_SET__par0_peri__BITNR 10
+#define R_IRQ_MASK0_SET__par0_peri__WIDTH 1
+#define R_IRQ_MASK0_SET__par0_peri__set 1
+#define R_IRQ_MASK0_SET__par0_peri__nop 0
+#define R_IRQ_MASK0_SET__ata_irq2__BITNR 10
+#define R_IRQ_MASK0_SET__ata_irq2__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_irq2__set 1
+#define R_IRQ_MASK0_SET__ata_irq2__nop 0
+#define R_IRQ_MASK0_SET__par0_data__BITNR 9
+#define R_IRQ_MASK0_SET__par0_data__WIDTH 1
+#define R_IRQ_MASK0_SET__par0_data__set 1
+#define R_IRQ_MASK0_SET__par0_data__nop 0
+#define R_IRQ_MASK0_SET__ata_irq1__BITNR 9
+#define R_IRQ_MASK0_SET__ata_irq1__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_irq1__set 1
+#define R_IRQ_MASK0_SET__ata_irq1__nop 0
+#define R_IRQ_MASK0_SET__par0_ready__BITNR 8
+#define R_IRQ_MASK0_SET__par0_ready__WIDTH 1
+#define R_IRQ_MASK0_SET__par0_ready__set 1
+#define R_IRQ_MASK0_SET__par0_ready__nop 0
+#define R_IRQ_MASK0_SET__ata_irq0__BITNR 8
+#define R_IRQ_MASK0_SET__ata_irq0__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_irq0__set 1
+#define R_IRQ_MASK0_SET__ata_irq0__nop 0
+#define R_IRQ_MASK0_SET__mio__BITNR 8
+#define R_IRQ_MASK0_SET__mio__WIDTH 1
+#define R_IRQ_MASK0_SET__mio__set 1
+#define R_IRQ_MASK0_SET__mio__nop 0
+#define R_IRQ_MASK0_SET__scsi0__BITNR 8
+#define R_IRQ_MASK0_SET__scsi0__WIDTH 1
+#define R_IRQ_MASK0_SET__scsi0__set 1
+#define R_IRQ_MASK0_SET__scsi0__nop 0
+#define R_IRQ_MASK0_SET__ata_dmaend__BITNR 7
+#define R_IRQ_MASK0_SET__ata_dmaend__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_dmaend__set 1
+#define R_IRQ_MASK0_SET__ata_dmaend__nop 0
+#define R_IRQ_MASK0_SET__irq_ext_vector_nr__BITNR 5
+#define R_IRQ_MASK0_SET__irq_ext_vector_nr__WIDTH 1
+#define R_IRQ_MASK0_SET__irq_ext_vector_nr__set 1
+#define R_IRQ_MASK0_SET__irq_ext_vector_nr__nop 0
+#define R_IRQ_MASK0_SET__irq_int_vector_nr__BITNR 4
+#define R_IRQ_MASK0_SET__irq_int_vector_nr__WIDTH 1
+#define R_IRQ_MASK0_SET__irq_int_vector_nr__set 1
+#define R_IRQ_MASK0_SET__irq_int_vector_nr__nop 0
+#define R_IRQ_MASK0_SET__ext_dma1__BITNR 3
+#define R_IRQ_MASK0_SET__ext_dma1__WIDTH 1
+#define R_IRQ_MASK0_SET__ext_dma1__set 1
+#define R_IRQ_MASK0_SET__ext_dma1__nop 0
+#define R_IRQ_MASK0_SET__ext_dma0__BITNR 2
+#define R_IRQ_MASK0_SET__ext_dma0__WIDTH 1
+#define R_IRQ_MASK0_SET__ext_dma0__set 1
+#define R_IRQ_MASK0_SET__ext_dma0__nop 0
+#define R_IRQ_MASK0_SET__timer1__BITNR 1
+#define R_IRQ_MASK0_SET__timer1__WIDTH 1
+#define R_IRQ_MASK0_SET__timer1__set 1
+#define R_IRQ_MASK0_SET__timer1__nop 0
+#define R_IRQ_MASK0_SET__timer0__BITNR 0
+#define R_IRQ_MASK0_SET__timer0__WIDTH 1
+#define R_IRQ_MASK0_SET__timer0__set 1
+#define R_IRQ_MASK0_SET__timer0__nop 0
+
+#define R_IRQ_MASK1_RD (IO_TYPECAST_RO_UDWORD 0xb00000c8)
+#define R_IRQ_MASK1_RD__sw_int7__BITNR 31
+#define R_IRQ_MASK1_RD__sw_int7__WIDTH 1
+#define R_IRQ_MASK1_RD__sw_int7__active 1
+#define R_IRQ_MASK1_RD__sw_int7__inactive 0
+#define R_IRQ_MASK1_RD__sw_int6__BITNR 30
+#define R_IRQ_MASK1_RD__sw_int6__WIDTH 1
+#define R_IRQ_MASK1_RD__sw_int6__active 1
+#define R_IRQ_MASK1_RD__sw_int6__inactive 0
+#define R_IRQ_MASK1_RD__sw_int5__BITNR 29
+#define R_IRQ_MASK1_RD__sw_int5__WIDTH 1
+#define R_IRQ_MASK1_RD__sw_int5__active 1
+#define R_IRQ_MASK1_RD__sw_int5__inactive 0
+#define R_IRQ_MASK1_RD__sw_int4__BITNR 28
+#define R_IRQ_MASK1_RD__sw_int4__WIDTH 1
+#define R_IRQ_MASK1_RD__sw_int4__active 1
+#define R_IRQ_MASK1_RD__sw_int4__inactive 0
+#define R_IRQ_MASK1_RD__sw_int3__BITNR 27
+#define R_IRQ_MASK1_RD__sw_int3__WIDTH 1
+#define R_IRQ_MASK1_RD__sw_int3__active 1
+#define R_IRQ_MASK1_RD__sw_int3__inactive 0
+#define R_IRQ_MASK1_RD__sw_int2__BITNR 26
+#define R_IRQ_MASK1_RD__sw_int2__WIDTH 1
+#define R_IRQ_MASK1_RD__sw_int2__active 1
+#define R_IRQ_MASK1_RD__sw_int2__inactive 0
+#define R_IRQ_MASK1_RD__sw_int1__BITNR 25
+#define R_IRQ_MASK1_RD__sw_int1__WIDTH 1
+#define R_IRQ_MASK1_RD__sw_int1__active 1
+#define R_IRQ_MASK1_RD__sw_int1__inactive 0
+#define R_IRQ_MASK1_RD__sw_int0__BITNR 24
+#define R_IRQ_MASK1_RD__sw_int0__WIDTH 1
+#define R_IRQ_MASK1_RD__sw_int0__active 1
+#define R_IRQ_MASK1_RD__sw_int0__inactive 0
+#define R_IRQ_MASK1_RD__par1_ecp_cmd__BITNR 19
+#define R_IRQ_MASK1_RD__par1_ecp_cmd__WIDTH 1
+#define R_IRQ_MASK1_RD__par1_ecp_cmd__active 1
+#define R_IRQ_MASK1_RD__par1_ecp_cmd__inactive 0
+#define R_IRQ_MASK1_RD__par1_peri__BITNR 18
+#define R_IRQ_MASK1_RD__par1_peri__WIDTH 1
+#define R_IRQ_MASK1_RD__par1_peri__active 1
+#define R_IRQ_MASK1_RD__par1_peri__inactive 0
+#define R_IRQ_MASK1_RD__par1_data__BITNR 17
+#define R_IRQ_MASK1_RD__par1_data__WIDTH 1
+#define R_IRQ_MASK1_RD__par1_data__active 1
+#define R_IRQ_MASK1_RD__par1_data__inactive 0
+#define R_IRQ_MASK1_RD__par1_ready__BITNR 16
+#define R_IRQ_MASK1_RD__par1_ready__WIDTH 1
+#define R_IRQ_MASK1_RD__par1_ready__active 1
+#define R_IRQ_MASK1_RD__par1_ready__inactive 0
+#define R_IRQ_MASK1_RD__scsi1__BITNR 16
+#define R_IRQ_MASK1_RD__scsi1__WIDTH 1
+#define R_IRQ_MASK1_RD__scsi1__active 1
+#define R_IRQ_MASK1_RD__scsi1__inactive 0
+#define R_IRQ_MASK1_RD__ser3_ready__BITNR 15
+#define R_IRQ_MASK1_RD__ser3_ready__WIDTH 1
+#define R_IRQ_MASK1_RD__ser3_ready__active 1
+#define R_IRQ_MASK1_RD__ser3_ready__inactive 0
+#define R_IRQ_MASK1_RD__ser3_data__BITNR 14
+#define R_IRQ_MASK1_RD__ser3_data__WIDTH 1
+#define R_IRQ_MASK1_RD__ser3_data__active 1
+#define R_IRQ_MASK1_RD__ser3_data__inactive 0
+#define R_IRQ_MASK1_RD__ser2_ready__BITNR 13
+#define R_IRQ_MASK1_RD__ser2_ready__WIDTH 1
+#define R_IRQ_MASK1_RD__ser2_ready__active 1
+#define R_IRQ_MASK1_RD__ser2_ready__inactive 0
+#define R_IRQ_MASK1_RD__ser2_data__BITNR 12
+#define R_IRQ_MASK1_RD__ser2_data__WIDTH 1
+#define R_IRQ_MASK1_RD__ser2_data__active 1
+#define R_IRQ_MASK1_RD__ser2_data__inactive 0
+#define R_IRQ_MASK1_RD__ser1_ready__BITNR 11
+#define R_IRQ_MASK1_RD__ser1_ready__WIDTH 1
+#define R_IRQ_MASK1_RD__ser1_ready__active 1
+#define R_IRQ_MASK1_RD__ser1_ready__inactive 0
+#define R_IRQ_MASK1_RD__ser1_data__BITNR 10
+#define R_IRQ_MASK1_RD__ser1_data__WIDTH 1
+#define R_IRQ_MASK1_RD__ser1_data__active 1
+#define R_IRQ_MASK1_RD__ser1_data__inactive 0
+#define R_IRQ_MASK1_RD__ser0_ready__BITNR 9
+#define R_IRQ_MASK1_RD__ser0_ready__WIDTH 1
+#define R_IRQ_MASK1_RD__ser0_ready__active 1
+#define R_IRQ_MASK1_RD__ser0_ready__inactive 0
+#define R_IRQ_MASK1_RD__ser0_data__BITNR 8
+#define R_IRQ_MASK1_RD__ser0_data__WIDTH 1
+#define R_IRQ_MASK1_RD__ser0_data__active 1
+#define R_IRQ_MASK1_RD__ser0_data__inactive 0
+#define R_IRQ_MASK1_RD__pa7__BITNR 7
+#define R_IRQ_MASK1_RD__pa7__WIDTH 1
+#define R_IRQ_MASK1_RD__pa7__active 1
+#define R_IRQ_MASK1_RD__pa7__inactive 0
+#define R_IRQ_MASK1_RD__pa6__BITNR 6
+#define R_IRQ_MASK1_RD__pa6__WIDTH 1
+#define R_IRQ_MASK1_RD__pa6__active 1
+#define R_IRQ_MASK1_RD__pa6__inactive 0
+#define R_IRQ_MASK1_RD__pa5__BITNR 5
+#define R_IRQ_MASK1_RD__pa5__WIDTH 1
+#define R_IRQ_MASK1_RD__pa5__active 1
+#define R_IRQ_MASK1_RD__pa5__inactive 0
+#define R_IRQ_MASK1_RD__pa4__BITNR 4
+#define R_IRQ_MASK1_RD__pa4__WIDTH 1
+#define R_IRQ_MASK1_RD__pa4__active 1
+#define R_IRQ_MASK1_RD__pa4__inactive 0
+#define R_IRQ_MASK1_RD__pa3__BITNR 3
+#define R_IRQ_MASK1_RD__pa3__WIDTH 1
+#define R_IRQ_MASK1_RD__pa3__active 1
+#define R_IRQ_MASK1_RD__pa3__inactive 0
+#define R_IRQ_MASK1_RD__pa2__BITNR 2
+#define R_IRQ_MASK1_RD__pa2__WIDTH 1
+#define R_IRQ_MASK1_RD__pa2__active 1
+#define R_IRQ_MASK1_RD__pa2__inactive 0
+#define R_IRQ_MASK1_RD__pa1__BITNR 1
+#define R_IRQ_MASK1_RD__pa1__WIDTH 1
+#define R_IRQ_MASK1_RD__pa1__active 1
+#define R_IRQ_MASK1_RD__pa1__inactive 0
+#define R_IRQ_MASK1_RD__pa0__BITNR 0
+#define R_IRQ_MASK1_RD__pa0__WIDTH 1
+#define R_IRQ_MASK1_RD__pa0__active 1
+#define R_IRQ_MASK1_RD__pa0__inactive 0
+
+#define R_IRQ_MASK1_CLR (IO_TYPECAST_UDWORD 0xb00000c8)
+#define R_IRQ_MASK1_CLR__sw_int7__BITNR 31
+#define R_IRQ_MASK1_CLR__sw_int7__WIDTH 1
+#define R_IRQ_MASK1_CLR__sw_int7__clr 1
+#define R_IRQ_MASK1_CLR__sw_int7__nop 0
+#define R_IRQ_MASK1_CLR__sw_int6__BITNR 30
+#define R_IRQ_MASK1_CLR__sw_int6__WIDTH 1
+#define R_IRQ_MASK1_CLR__sw_int6__clr 1
+#define R_IRQ_MASK1_CLR__sw_int6__nop 0
+#define R_IRQ_MASK1_CLR__sw_int5__BITNR 29
+#define R_IRQ_MASK1_CLR__sw_int5__WIDTH 1
+#define R_IRQ_MASK1_CLR__sw_int5__clr 1
+#define R_IRQ_MASK1_CLR__sw_int5__nop 0
+#define R_IRQ_MASK1_CLR__sw_int4__BITNR 28
+#define R_IRQ_MASK1_CLR__sw_int4__WIDTH 1
+#define R_IRQ_MASK1_CLR__sw_int4__clr 1
+#define R_IRQ_MASK1_CLR__sw_int4__nop 0
+#define R_IRQ_MASK1_CLR__sw_int3__BITNR 27
+#define R_IRQ_MASK1_CLR__sw_int3__WIDTH 1
+#define R_IRQ_MASK1_CLR__sw_int3__clr 1
+#define R_IRQ_MASK1_CLR__sw_int3__nop 0
+#define R_IRQ_MASK1_CLR__sw_int2__BITNR 26
+#define R_IRQ_MASK1_CLR__sw_int2__WIDTH 1
+#define R_IRQ_MASK1_CLR__sw_int2__clr 1
+#define R_IRQ_MASK1_CLR__sw_int2__nop 0
+#define R_IRQ_MASK1_CLR__sw_int1__BITNR 25
+#define R_IRQ_MASK1_CLR__sw_int1__WIDTH 1
+#define R_IRQ_MASK1_CLR__sw_int1__clr 1
+#define R_IRQ_MASK1_CLR__sw_int1__nop 0
+#define R_IRQ_MASK1_CLR__sw_int0__BITNR 24
+#define R_IRQ_MASK1_CLR__sw_int0__WIDTH 1
+#define R_IRQ_MASK1_CLR__sw_int0__clr 1
+#define R_IRQ_MASK1_CLR__sw_int0__nop 0
+#define R_IRQ_MASK1_CLR__par1_ecp_cmd__BITNR 19
+#define R_IRQ_MASK1_CLR__par1_ecp_cmd__WIDTH 1
+#define R_IRQ_MASK1_CLR__par1_ecp_cmd__clr 1
+#define R_IRQ_MASK1_CLR__par1_ecp_cmd__nop 0
+#define R_IRQ_MASK1_CLR__par1_peri__BITNR 18
+#define R_IRQ_MASK1_CLR__par1_peri__WIDTH 1
+#define R_IRQ_MASK1_CLR__par1_peri__clr 1
+#define R_IRQ_MASK1_CLR__par1_peri__nop 0
+#define R_IRQ_MASK1_CLR__par1_data__BITNR 17
+#define R_IRQ_MASK1_CLR__par1_data__WIDTH 1
+#define R_IRQ_MASK1_CLR__par1_data__clr 1
+#define R_IRQ_MASK1_CLR__par1_data__nop 0
+#define R_IRQ_MASK1_CLR__par1_ready__BITNR 16
+#define R_IRQ_MASK1_CLR__par1_ready__WIDTH 1
+#define R_IRQ_MASK1_CLR__par1_ready__clr 1
+#define R_IRQ_MASK1_CLR__par1_ready__nop 0
+#define R_IRQ_MASK1_CLR__scsi1__BITNR 16
+#define R_IRQ_MASK1_CLR__scsi1__WIDTH 1
+#define R_IRQ_MASK1_CLR__scsi1__clr 1
+#define R_IRQ_MASK1_CLR__scsi1__nop 0
+#define R_IRQ_MASK1_CLR__ser3_ready__BITNR 15
+#define R_IRQ_MASK1_CLR__ser3_ready__WIDTH 1
+#define R_IRQ_MASK1_CLR__ser3_ready__clr 1
+#define R_IRQ_MASK1_CLR__ser3_ready__nop 0
+#define R_IRQ_MASK1_CLR__ser3_data__BITNR 14
+#define R_IRQ_MASK1_CLR__ser3_data__WIDTH 1
+#define R_IRQ_MASK1_CLR__ser3_data__clr 1
+#define R_IRQ_MASK1_CLR__ser3_data__nop 0
+#define R_IRQ_MASK1_CLR__ser2_ready__BITNR 13
+#define R_IRQ_MASK1_CLR__ser2_ready__WIDTH 1
+#define R_IRQ_MASK1_CLR__ser2_ready__clr 1
+#define R_IRQ_MASK1_CLR__ser2_ready__nop 0
+#define R_IRQ_MASK1_CLR__ser2_data__BITNR 12
+#define R_IRQ_MASK1_CLR__ser2_data__WIDTH 1
+#define R_IRQ_MASK1_CLR__ser2_data__clr 1
+#define R_IRQ_MASK1_CLR__ser2_data__nop 0
+#define R_IRQ_MASK1_CLR__ser1_ready__BITNR 11
+#define R_IRQ_MASK1_CLR__ser1_ready__WIDTH 1
+#define R_IRQ_MASK1_CLR__ser1_ready__clr 1
+#define R_IRQ_MASK1_CLR__ser1_ready__nop 0
+#define R_IRQ_MASK1_CLR__ser1_data__BITNR 10
+#define R_IRQ_MASK1_CLR__ser1_data__WIDTH 1
+#define R_IRQ_MASK1_CLR__ser1_data__clr 1
+#define R_IRQ_MASK1_CLR__ser1_data__nop 0
+#define R_IRQ_MASK1_CLR__ser0_ready__BITNR 9
+#define R_IRQ_MASK1_CLR__ser0_ready__WIDTH 1
+#define R_IRQ_MASK1_CLR__ser0_ready__clr 1
+#define R_IRQ_MASK1_CLR__ser0_ready__nop 0
+#define R_IRQ_MASK1_CLR__ser0_data__BITNR 8
+#define R_IRQ_MASK1_CLR__ser0_data__WIDTH 1
+#define R_IRQ_MASK1_CLR__ser0_data__clr 1
+#define R_IRQ_MASK1_CLR__ser0_data__nop 0
+#define R_IRQ_MASK1_CLR__pa7__BITNR 7
+#define R_IRQ_MASK1_CLR__pa7__WIDTH 1
+#define R_IRQ_MASK1_CLR__pa7__clr 1
+#define R_IRQ_MASK1_CLR__pa7__nop 0
+#define R_IRQ_MASK1_CLR__pa6__BITNR 6
+#define R_IRQ_MASK1_CLR__pa6__WIDTH 1
+#define R_IRQ_MASK1_CLR__pa6__clr 1
+#define R_IRQ_MASK1_CLR__pa6__nop 0
+#define R_IRQ_MASK1_CLR__pa5__BITNR 5
+#define R_IRQ_MASK1_CLR__pa5__WIDTH 1
+#define R_IRQ_MASK1_CLR__pa5__clr 1
+#define R_IRQ_MASK1_CLR__pa5__nop 0
+#define R_IRQ_MASK1_CLR__pa4__BITNR 4
+#define R_IRQ_MASK1_CLR__pa4__WIDTH 1
+#define R_IRQ_MASK1_CLR__pa4__clr 1
+#define R_IRQ_MASK1_CLR__pa4__nop 0
+#define R_IRQ_MASK1_CLR__pa3__BITNR 3
+#define R_IRQ_MASK1_CLR__pa3__WIDTH 1
+#define R_IRQ_MASK1_CLR__pa3__clr 1
+#define R_IRQ_MASK1_CLR__pa3__nop 0
+#define R_IRQ_MASK1_CLR__pa2__BITNR 2
+#define R_IRQ_MASK1_CLR__pa2__WIDTH 1
+#define R_IRQ_MASK1_CLR__pa2__clr 1
+#define R_IRQ_MASK1_CLR__pa2__nop 0
+#define R_IRQ_MASK1_CLR__pa1__BITNR 1
+#define R_IRQ_MASK1_CLR__pa1__WIDTH 1
+#define R_IRQ_MASK1_CLR__pa1__clr 1
+#define R_IRQ_MASK1_CLR__pa1__nop 0
+#define R_IRQ_MASK1_CLR__pa0__BITNR 0
+#define R_IRQ_MASK1_CLR__pa0__WIDTH 1
+#define R_IRQ_MASK1_CLR__pa0__clr 1
+#define R_IRQ_MASK1_CLR__pa0__nop 0
+
+#define R_IRQ_READ1 (IO_TYPECAST_RO_UDWORD 0xb00000cc)
+#define R_IRQ_READ1__sw_int7__BITNR 31
+#define R_IRQ_READ1__sw_int7__WIDTH 1
+#define R_IRQ_READ1__sw_int7__active 1
+#define R_IRQ_READ1__sw_int7__inactive 0
+#define R_IRQ_READ1__sw_int6__BITNR 30
+#define R_IRQ_READ1__sw_int6__WIDTH 1
+#define R_IRQ_READ1__sw_int6__active 1
+#define R_IRQ_READ1__sw_int6__inactive 0
+#define R_IRQ_READ1__sw_int5__BITNR 29
+#define R_IRQ_READ1__sw_int5__WIDTH 1
+#define R_IRQ_READ1__sw_int5__active 1
+#define R_IRQ_READ1__sw_int5__inactive 0
+#define R_IRQ_READ1__sw_int4__BITNR 28
+#define R_IRQ_READ1__sw_int4__WIDTH 1
+#define R_IRQ_READ1__sw_int4__active 1
+#define R_IRQ_READ1__sw_int4__inactive 0
+#define R_IRQ_READ1__sw_int3__BITNR 27
+#define R_IRQ_READ1__sw_int3__WIDTH 1
+#define R_IRQ_READ1__sw_int3__active 1
+#define R_IRQ_READ1__sw_int3__inactive 0
+#define R_IRQ_READ1__sw_int2__BITNR 26
+#define R_IRQ_READ1__sw_int2__WIDTH 1
+#define R_IRQ_READ1__sw_int2__active 1
+#define R_IRQ_READ1__sw_int2__inactive 0
+#define R_IRQ_READ1__sw_int1__BITNR 25
+#define R_IRQ_READ1__sw_int1__WIDTH 1
+#define R_IRQ_READ1__sw_int1__active 1
+#define R_IRQ_READ1__sw_int1__inactive 0
+#define R_IRQ_READ1__sw_int0__BITNR 24
+#define R_IRQ_READ1__sw_int0__WIDTH 1
+#define R_IRQ_READ1__sw_int0__active 1
+#define R_IRQ_READ1__sw_int0__inactive 0
+#define R_IRQ_READ1__par1_ecp_cmd__BITNR 19
+#define R_IRQ_READ1__par1_ecp_cmd__WIDTH 1
+#define R_IRQ_READ1__par1_ecp_cmd__active 1
+#define R_IRQ_READ1__par1_ecp_cmd__inactive 0
+#define R_IRQ_READ1__par1_peri__BITNR 18
+#define R_IRQ_READ1__par1_peri__WIDTH 1
+#define R_IRQ_READ1__par1_peri__active 1
+#define R_IRQ_READ1__par1_peri__inactive 0
+#define R_IRQ_READ1__par1_data__BITNR 17
+#define R_IRQ_READ1__par1_data__WIDTH 1
+#define R_IRQ_READ1__par1_data__active 1
+#define R_IRQ_READ1__par1_data__inactive 0
+#define R_IRQ_READ1__par1_ready__BITNR 16
+#define R_IRQ_READ1__par1_ready__WIDTH 1
+#define R_IRQ_READ1__par1_ready__active 1
+#define R_IRQ_READ1__par1_ready__inactive 0
+#define R_IRQ_READ1__scsi1__BITNR 16
+#define R_IRQ_READ1__scsi1__WIDTH 1
+#define R_IRQ_READ1__scsi1__active 1
+#define R_IRQ_READ1__scsi1__inactive 0
+#define R_IRQ_READ1__ser3_ready__BITNR 15
+#define R_IRQ_READ1__ser3_ready__WIDTH 1
+#define R_IRQ_READ1__ser3_ready__active 1
+#define R_IRQ_READ1__ser3_ready__inactive 0
+#define R_IRQ_READ1__ser3_data__BITNR 14
+#define R_IRQ_READ1__ser3_data__WIDTH 1
+#define R_IRQ_READ1__ser3_data__active 1
+#define R_IRQ_READ1__ser3_data__inactive 0
+#define R_IRQ_READ1__ser2_ready__BITNR 13
+#define R_IRQ_READ1__ser2_ready__WIDTH 1
+#define R_IRQ_READ1__ser2_ready__active 1
+#define R_IRQ_READ1__ser2_ready__inactive 0
+#define R_IRQ_READ1__ser2_data__BITNR 12
+#define R_IRQ_READ1__ser2_data__WIDTH 1
+#define R_IRQ_READ1__ser2_data__active 1
+#define R_IRQ_READ1__ser2_data__inactive 0
+#define R_IRQ_READ1__ser1_ready__BITNR 11
+#define R_IRQ_READ1__ser1_ready__WIDTH 1
+#define R_IRQ_READ1__ser1_ready__active 1
+#define R_IRQ_READ1__ser1_ready__inactive 0
+#define R_IRQ_READ1__ser1_data__BITNR 10
+#define R_IRQ_READ1__ser1_data__WIDTH 1
+#define R_IRQ_READ1__ser1_data__active 1
+#define R_IRQ_READ1__ser1_data__inactive 0
+#define R_IRQ_READ1__ser0_ready__BITNR 9
+#define R_IRQ_READ1__ser0_ready__WIDTH 1
+#define R_IRQ_READ1__ser0_ready__active 1
+#define R_IRQ_READ1__ser0_ready__inactive 0
+#define R_IRQ_READ1__ser0_data__BITNR 8
+#define R_IRQ_READ1__ser0_data__WIDTH 1
+#define R_IRQ_READ1__ser0_data__active 1
+#define R_IRQ_READ1__ser0_data__inactive 0
+#define R_IRQ_READ1__pa7__BITNR 7
+#define R_IRQ_READ1__pa7__WIDTH 1
+#define R_IRQ_READ1__pa7__active 1
+#define R_IRQ_READ1__pa7__inactive 0
+#define R_IRQ_READ1__pa6__BITNR 6
+#define R_IRQ_READ1__pa6__WIDTH 1
+#define R_IRQ_READ1__pa6__active 1
+#define R_IRQ_READ1__pa6__inactive 0
+#define R_IRQ_READ1__pa5__BITNR 5
+#define R_IRQ_READ1__pa5__WIDTH 1
+#define R_IRQ_READ1__pa5__active 1
+#define R_IRQ_READ1__pa5__inactive 0
+#define R_IRQ_READ1__pa4__BITNR 4
+#define R_IRQ_READ1__pa4__WIDTH 1
+#define R_IRQ_READ1__pa4__active 1
+#define R_IRQ_READ1__pa4__inactive 0
+#define R_IRQ_READ1__pa3__BITNR 3
+#define R_IRQ_READ1__pa3__WIDTH 1
+#define R_IRQ_READ1__pa3__active 1
+#define R_IRQ_READ1__pa3__inactive 0
+#define R_IRQ_READ1__pa2__BITNR 2
+#define R_IRQ_READ1__pa2__WIDTH 1
+#define R_IRQ_READ1__pa2__active 1
+#define R_IRQ_READ1__pa2__inactive 0
+#define R_IRQ_READ1__pa1__BITNR 1
+#define R_IRQ_READ1__pa1__WIDTH 1
+#define R_IRQ_READ1__pa1__active 1
+#define R_IRQ_READ1__pa1__inactive 0
+#define R_IRQ_READ1__pa0__BITNR 0
+#define R_IRQ_READ1__pa0__WIDTH 1
+#define R_IRQ_READ1__pa0__active 1
+#define R_IRQ_READ1__pa0__inactive 0
+
+#define R_IRQ_MASK1_SET (IO_TYPECAST_UDWORD 0xb00000cc)
+#define R_IRQ_MASK1_SET__sw_int7__BITNR 31
+#define R_IRQ_MASK1_SET__sw_int7__WIDTH 1
+#define R_IRQ_MASK1_SET__sw_int7__set 1
+#define R_IRQ_MASK1_SET__sw_int7__nop 0
+#define R_IRQ_MASK1_SET__sw_int6__BITNR 30
+#define R_IRQ_MASK1_SET__sw_int6__WIDTH 1
+#define R_IRQ_MASK1_SET__sw_int6__set 1
+#define R_IRQ_MASK1_SET__sw_int6__nop 0
+#define R_IRQ_MASK1_SET__sw_int5__BITNR 29
+#define R_IRQ_MASK1_SET__sw_int5__WIDTH 1
+#define R_IRQ_MASK1_SET__sw_int5__set 1
+#define R_IRQ_MASK1_SET__sw_int5__nop 0
+#define R_IRQ_MASK1_SET__sw_int4__BITNR 28
+#define R_IRQ_MASK1_SET__sw_int4__WIDTH 1
+#define R_IRQ_MASK1_SET__sw_int4__set 1
+#define R_IRQ_MASK1_SET__sw_int4__nop 0
+#define R_IRQ_MASK1_SET__sw_int3__BITNR 27
+#define R_IRQ_MASK1_SET__sw_int3__WIDTH 1
+#define R_IRQ_MASK1_SET__sw_int3__set 1
+#define R_IRQ_MASK1_SET__sw_int3__nop 0
+#define R_IRQ_MASK1_SET__sw_int2__BITNR 26
+#define R_IRQ_MASK1_SET__sw_int2__WIDTH 1
+#define R_IRQ_MASK1_SET__sw_int2__set 1
+#define R_IRQ_MASK1_SET__sw_int2__nop 0
+#define R_IRQ_MASK1_SET__sw_int1__BITNR 25
+#define R_IRQ_MASK1_SET__sw_int1__WIDTH 1
+#define R_IRQ_MASK1_SET__sw_int1__set 1
+#define R_IRQ_MASK1_SET__sw_int1__nop 0
+#define R_IRQ_MASK1_SET__sw_int0__BITNR 24
+#define R_IRQ_MASK1_SET__sw_int0__WIDTH 1
+#define R_IRQ_MASK1_SET__sw_int0__set 1
+#define R_IRQ_MASK1_SET__sw_int0__nop 0
+#define R_IRQ_MASK1_SET__par1_ecp_cmd__BITNR 19
+#define R_IRQ_MASK1_SET__par1_ecp_cmd__WIDTH 1
+#define R_IRQ_MASK1_SET__par1_ecp_cmd__set 1
+#define R_IRQ_MASK1_SET__par1_ecp_cmd__nop 0
+#define R_IRQ_MASK1_SET__par1_peri__BITNR 18
+#define R_IRQ_MASK1_SET__par1_peri__WIDTH 1
+#define R_IRQ_MASK1_SET__par1_peri__set 1
+#define R_IRQ_MASK1_SET__par1_peri__nop 0
+#define R_IRQ_MASK1_SET__par1_data__BITNR 17
+#define R_IRQ_MASK1_SET__par1_data__WIDTH 1
+#define R_IRQ_MASK1_SET__par1_data__set 1
+#define R_IRQ_MASK1_SET__par1_data__nop 0
+#define R_IRQ_MASK1_SET__par1_ready__BITNR 16
+#define R_IRQ_MASK1_SET__par1_ready__WIDTH 1
+#define R_IRQ_MASK1_SET__par1_ready__set 1
+#define R_IRQ_MASK1_SET__par1_ready__nop 0
+#define R_IRQ_MASK1_SET__scsi1__BITNR 16
+#define R_IRQ_MASK1_SET__scsi1__WIDTH 1
+#define R_IRQ_MASK1_SET__scsi1__set 1
+#define R_IRQ_MASK1_SET__scsi1__nop 0
+#define R_IRQ_MASK1_SET__ser3_ready__BITNR 15
+#define R_IRQ_MASK1_SET__ser3_ready__WIDTH 1
+#define R_IRQ_MASK1_SET__ser3_ready__set 1
+#define R_IRQ_MASK1_SET__ser3_ready__nop 0
+#define R_IRQ_MASK1_SET__ser3_data__BITNR 14
+#define R_IRQ_MASK1_SET__ser3_data__WIDTH 1
+#define R_IRQ_MASK1_SET__ser3_data__set 1
+#define R_IRQ_MASK1_SET__ser3_data__nop 0
+#define R_IRQ_MASK1_SET__ser2_ready__BITNR 13
+#define R_IRQ_MASK1_SET__ser2_ready__WIDTH 1
+#define R_IRQ_MASK1_SET__ser2_ready__set 1
+#define R_IRQ_MASK1_SET__ser2_ready__nop 0
+#define R_IRQ_MASK1_SET__ser2_data__BITNR 12
+#define R_IRQ_MASK1_SET__ser2_data__WIDTH 1
+#define R_IRQ_MASK1_SET__ser2_data__set 1
+#define R_IRQ_MASK1_SET__ser2_data__nop 0
+#define R_IRQ_MASK1_SET__ser1_ready__BITNR 11
+#define R_IRQ_MASK1_SET__ser1_ready__WIDTH 1
+#define R_IRQ_MASK1_SET__ser1_ready__set 1
+#define R_IRQ_MASK1_SET__ser1_ready__nop 0
+#define R_IRQ_MASK1_SET__ser1_data__BITNR 10
+#define R_IRQ_MASK1_SET__ser1_data__WIDTH 1
+#define R_IRQ_MASK1_SET__ser1_data__set 1
+#define R_IRQ_MASK1_SET__ser1_data__nop 0
+#define R_IRQ_MASK1_SET__ser0_ready__BITNR 9
+#define R_IRQ_MASK1_SET__ser0_ready__WIDTH 1
+#define R_IRQ_MASK1_SET__ser0_ready__set 1
+#define R_IRQ_MASK1_SET__ser0_ready__nop 0
+#define R_IRQ_MASK1_SET__ser0_data__BITNR 8
+#define R_IRQ_MASK1_SET__ser0_data__WIDTH 1
+#define R_IRQ_MASK1_SET__ser0_data__set 1
+#define R_IRQ_MASK1_SET__ser0_data__nop 0
+#define R_IRQ_MASK1_SET__pa7__BITNR 7
+#define R_IRQ_MASK1_SET__pa7__WIDTH 1
+#define R_IRQ_MASK1_SET__pa7__set 1
+#define R_IRQ_MASK1_SET__pa7__nop 0
+#define R_IRQ_MASK1_SET__pa6__BITNR 6
+#define R_IRQ_MASK1_SET__pa6__WIDTH 1
+#define R_IRQ_MASK1_SET__pa6__set 1
+#define R_IRQ_MASK1_SET__pa6__nop 0
+#define R_IRQ_MASK1_SET__pa5__BITNR 5
+#define R_IRQ_MASK1_SET__pa5__WIDTH 1
+#define R_IRQ_MASK1_SET__pa5__set 1
+#define R_IRQ_MASK1_SET__pa5__nop 0
+#define R_IRQ_MASK1_SET__pa4__BITNR 4
+#define R_IRQ_MASK1_SET__pa4__WIDTH 1
+#define R_IRQ_MASK1_SET__pa4__set 1
+#define R_IRQ_MASK1_SET__pa4__nop 0
+#define R_IRQ_MASK1_SET__pa3__BITNR 3
+#define R_IRQ_MASK1_SET__pa3__WIDTH 1
+#define R_IRQ_MASK1_SET__pa3__set 1
+#define R_IRQ_MASK1_SET__pa3__nop 0
+#define R_IRQ_MASK1_SET__pa2__BITNR 2
+#define R_IRQ_MASK1_SET__pa2__WIDTH 1
+#define R_IRQ_MASK1_SET__pa2__set 1
+#define R_IRQ_MASK1_SET__pa2__nop 0
+#define R_IRQ_MASK1_SET__pa1__BITNR 1
+#define R_IRQ_MASK1_SET__pa1__WIDTH 1
+#define R_IRQ_MASK1_SET__pa1__set 1
+#define R_IRQ_MASK1_SET__pa1__nop 0
+#define R_IRQ_MASK1_SET__pa0__BITNR 0
+#define R_IRQ_MASK1_SET__pa0__WIDTH 1
+#define R_IRQ_MASK1_SET__pa0__set 1
+#define R_IRQ_MASK1_SET__pa0__nop 0
+
+#define R_IRQ_MASK2_RD (IO_TYPECAST_RO_UDWORD 0xb00000d0)
+#define R_IRQ_MASK2_RD__dma8_sub3_descr__BITNR 23
+#define R_IRQ_MASK2_RD__dma8_sub3_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma8_sub3_descr__active 1
+#define R_IRQ_MASK2_RD__dma8_sub3_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma8_sub2_descr__BITNR 22
+#define R_IRQ_MASK2_RD__dma8_sub2_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma8_sub2_descr__active 1
+#define R_IRQ_MASK2_RD__dma8_sub2_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma8_sub1_descr__BITNR 21
+#define R_IRQ_MASK2_RD__dma8_sub1_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma8_sub1_descr__active 1
+#define R_IRQ_MASK2_RD__dma8_sub1_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma8_sub0_descr__BITNR 20
+#define R_IRQ_MASK2_RD__dma8_sub0_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma8_sub0_descr__active 1
+#define R_IRQ_MASK2_RD__dma8_sub0_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma9_eop__BITNR 19
+#define R_IRQ_MASK2_RD__dma9_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma9_eop__active 1
+#define R_IRQ_MASK2_RD__dma9_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma9_descr__BITNR 18
+#define R_IRQ_MASK2_RD__dma9_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma9_descr__active 1
+#define R_IRQ_MASK2_RD__dma9_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma8_eop__BITNR 17
+#define R_IRQ_MASK2_RD__dma8_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma8_eop__active 1
+#define R_IRQ_MASK2_RD__dma8_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma8_descr__BITNR 16
+#define R_IRQ_MASK2_RD__dma8_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma8_descr__active 1
+#define R_IRQ_MASK2_RD__dma8_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma7_eop__BITNR 15
+#define R_IRQ_MASK2_RD__dma7_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma7_eop__active 1
+#define R_IRQ_MASK2_RD__dma7_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma7_descr__BITNR 14
+#define R_IRQ_MASK2_RD__dma7_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma7_descr__active 1
+#define R_IRQ_MASK2_RD__dma7_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma6_eop__BITNR 13
+#define R_IRQ_MASK2_RD__dma6_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma6_eop__active 1
+#define R_IRQ_MASK2_RD__dma6_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma6_descr__BITNR 12
+#define R_IRQ_MASK2_RD__dma6_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma6_descr__active 1
+#define R_IRQ_MASK2_RD__dma6_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma5_eop__BITNR 11
+#define R_IRQ_MASK2_RD__dma5_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma5_eop__active 1
+#define R_IRQ_MASK2_RD__dma5_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma5_descr__BITNR 10
+#define R_IRQ_MASK2_RD__dma5_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma5_descr__active 1
+#define R_IRQ_MASK2_RD__dma5_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma4_eop__BITNR 9
+#define R_IRQ_MASK2_RD__dma4_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma4_eop__active 1
+#define R_IRQ_MASK2_RD__dma4_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma4_descr__BITNR 8
+#define R_IRQ_MASK2_RD__dma4_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma4_descr__active 1
+#define R_IRQ_MASK2_RD__dma4_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma3_eop__BITNR 7
+#define R_IRQ_MASK2_RD__dma3_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma3_eop__active 1
+#define R_IRQ_MASK2_RD__dma3_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma3_descr__BITNR 6
+#define R_IRQ_MASK2_RD__dma3_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma3_descr__active 1
+#define R_IRQ_MASK2_RD__dma3_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma2_eop__BITNR 5
+#define R_IRQ_MASK2_RD__dma2_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma2_eop__active 1
+#define R_IRQ_MASK2_RD__dma2_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma2_descr__BITNR 4
+#define R_IRQ_MASK2_RD__dma2_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma2_descr__active 1
+#define R_IRQ_MASK2_RD__dma2_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma1_eop__BITNR 3
+#define R_IRQ_MASK2_RD__dma1_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma1_eop__active 1
+#define R_IRQ_MASK2_RD__dma1_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma1_descr__BITNR 2
+#define R_IRQ_MASK2_RD__dma1_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma1_descr__active 1
+#define R_IRQ_MASK2_RD__dma1_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma0_eop__BITNR 1
+#define R_IRQ_MASK2_RD__dma0_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma0_eop__active 1
+#define R_IRQ_MASK2_RD__dma0_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma0_descr__BITNR 0
+#define R_IRQ_MASK2_RD__dma0_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma0_descr__active 1
+#define R_IRQ_MASK2_RD__dma0_descr__inactive 0
+
+#define R_IRQ_MASK2_CLR (IO_TYPECAST_UDWORD 0xb00000d0)
+#define R_IRQ_MASK2_CLR__dma8_sub3_descr__BITNR 23
+#define R_IRQ_MASK2_CLR__dma8_sub3_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma8_sub3_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma8_sub3_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma8_sub2_descr__BITNR 22
+#define R_IRQ_MASK2_CLR__dma8_sub2_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma8_sub2_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma8_sub2_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma8_sub1_descr__BITNR 21
+#define R_IRQ_MASK2_CLR__dma8_sub1_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma8_sub1_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma8_sub1_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma8_sub0_descr__BITNR 20
+#define R_IRQ_MASK2_CLR__dma8_sub0_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma8_sub0_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma8_sub0_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma9_eop__BITNR 19
+#define R_IRQ_MASK2_CLR__dma9_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma9_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma9_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma9_descr__BITNR 18
+#define R_IRQ_MASK2_CLR__dma9_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma9_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma9_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma8_eop__BITNR 17
+#define R_IRQ_MASK2_CLR__dma8_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma8_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma8_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma8_descr__BITNR 16
+#define R_IRQ_MASK2_CLR__dma8_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma8_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma8_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma7_eop__BITNR 15
+#define R_IRQ_MASK2_CLR__dma7_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma7_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma7_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma7_descr__BITNR 14
+#define R_IRQ_MASK2_CLR__dma7_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma7_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma7_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma6_eop__BITNR 13
+#define R_IRQ_MASK2_CLR__dma6_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma6_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma6_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma6_descr__BITNR 12
+#define R_IRQ_MASK2_CLR__dma6_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma6_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma6_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma5_eop__BITNR 11
+#define R_IRQ_MASK2_CLR__dma5_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma5_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma5_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma5_descr__BITNR 10
+#define R_IRQ_MASK2_CLR__dma5_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma5_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma5_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma4_eop__BITNR 9
+#define R_IRQ_MASK2_CLR__dma4_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma4_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma4_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma4_descr__BITNR 8
+#define R_IRQ_MASK2_CLR__dma4_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma4_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma4_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma3_eop__BITNR 7
+#define R_IRQ_MASK2_CLR__dma3_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma3_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma3_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma3_descr__BITNR 6
+#define R_IRQ_MASK2_CLR__dma3_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma3_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma3_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma2_eop__BITNR 5
+#define R_IRQ_MASK2_CLR__dma2_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma2_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma2_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma2_descr__BITNR 4
+#define R_IRQ_MASK2_CLR__dma2_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma2_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma2_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma1_eop__BITNR 3
+#define R_IRQ_MASK2_CLR__dma1_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma1_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma1_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma1_descr__BITNR 2
+#define R_IRQ_MASK2_CLR__dma1_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma1_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma1_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma0_eop__BITNR 1
+#define R_IRQ_MASK2_CLR__dma0_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma0_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma0_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma0_descr__BITNR 0
+#define R_IRQ_MASK2_CLR__dma0_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma0_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma0_descr__nop 0
+
+#define R_IRQ_READ2 (IO_TYPECAST_RO_UDWORD 0xb00000d4)
+#define R_IRQ_READ2__dma8_sub3_descr__BITNR 23
+#define R_IRQ_READ2__dma8_sub3_descr__WIDTH 1
+#define R_IRQ_READ2__dma8_sub3_descr__active 1
+#define R_IRQ_READ2__dma8_sub3_descr__inactive 0
+#define R_IRQ_READ2__dma8_sub2_descr__BITNR 22
+#define R_IRQ_READ2__dma8_sub2_descr__WIDTH 1
+#define R_IRQ_READ2__dma8_sub2_descr__active 1
+#define R_IRQ_READ2__dma8_sub2_descr__inactive 0
+#define R_IRQ_READ2__dma8_sub1_descr__BITNR 21
+#define R_IRQ_READ2__dma8_sub1_descr__WIDTH 1
+#define R_IRQ_READ2__dma8_sub1_descr__active 1
+#define R_IRQ_READ2__dma8_sub1_descr__inactive 0
+#define R_IRQ_READ2__dma8_sub0_descr__BITNR 20
+#define R_IRQ_READ2__dma8_sub0_descr__WIDTH 1
+#define R_IRQ_READ2__dma8_sub0_descr__active 1
+#define R_IRQ_READ2__dma8_sub0_descr__inactive 0
+#define R_IRQ_READ2__dma9_eop__BITNR 19
+#define R_IRQ_READ2__dma9_eop__WIDTH 1
+#define R_IRQ_READ2__dma9_eop__active 1
+#define R_IRQ_READ2__dma9_eop__inactive 0
+#define R_IRQ_READ2__dma9_descr__BITNR 18
+#define R_IRQ_READ2__dma9_descr__WIDTH 1
+#define R_IRQ_READ2__dma9_descr__active 1
+#define R_IRQ_READ2__dma9_descr__inactive 0
+#define R_IRQ_READ2__dma8_eop__BITNR 17
+#define R_IRQ_READ2__dma8_eop__WIDTH 1
+#define R_IRQ_READ2__dma8_eop__active 1
+#define R_IRQ_READ2__dma8_eop__inactive 0
+#define R_IRQ_READ2__dma8_descr__BITNR 16
+#define R_IRQ_READ2__dma8_descr__WIDTH 1
+#define R_IRQ_READ2__dma8_descr__active 1
+#define R_IRQ_READ2__dma8_descr__inactive 0
+#define R_IRQ_READ2__dma7_eop__BITNR 15
+#define R_IRQ_READ2__dma7_eop__WIDTH 1
+#define R_IRQ_READ2__dma7_eop__active 1
+#define R_IRQ_READ2__dma7_eop__inactive 0
+#define R_IRQ_READ2__dma7_descr__BITNR 14
+#define R_IRQ_READ2__dma7_descr__WIDTH 1
+#define R_IRQ_READ2__dma7_descr__active 1
+#define R_IRQ_READ2__dma7_descr__inactive 0
+#define R_IRQ_READ2__dma6_eop__BITNR 13
+#define R_IRQ_READ2__dma6_eop__WIDTH 1
+#define R_IRQ_READ2__dma6_eop__active 1
+#define R_IRQ_READ2__dma6_eop__inactive 0
+#define R_IRQ_READ2__dma6_descr__BITNR 12
+#define R_IRQ_READ2__dma6_descr__WIDTH 1
+#define R_IRQ_READ2__dma6_descr__active 1
+#define R_IRQ_READ2__dma6_descr__inactive 0
+#define R_IRQ_READ2__dma5_eop__BITNR 11
+#define R_IRQ_READ2__dma5_eop__WIDTH 1
+#define R_IRQ_READ2__dma5_eop__active 1
+#define R_IRQ_READ2__dma5_eop__inactive 0
+#define R_IRQ_READ2__dma5_descr__BITNR 10
+#define R_IRQ_READ2__dma5_descr__WIDTH 1
+#define R_IRQ_READ2__dma5_descr__active 1
+#define R_IRQ_READ2__dma5_descr__inactive 0
+#define R_IRQ_READ2__dma4_eop__BITNR 9
+#define R_IRQ_READ2__dma4_eop__WIDTH 1
+#define R_IRQ_READ2__dma4_eop__active 1
+#define R_IRQ_READ2__dma4_eop__inactive 0
+#define R_IRQ_READ2__dma4_descr__BITNR 8
+#define R_IRQ_READ2__dma4_descr__WIDTH 1
+#define R_IRQ_READ2__dma4_descr__active 1
+#define R_IRQ_READ2__dma4_descr__inactive 0
+#define R_IRQ_READ2__dma3_eop__BITNR 7
+#define R_IRQ_READ2__dma3_eop__WIDTH 1
+#define R_IRQ_READ2__dma3_eop__active 1
+#define R_IRQ_READ2__dma3_eop__inactive 0
+#define R_IRQ_READ2__dma3_descr__BITNR 6
+#define R_IRQ_READ2__dma3_descr__WIDTH 1
+#define R_IRQ_READ2__dma3_descr__active 1
+#define R_IRQ_READ2__dma3_descr__inactive 0
+#define R_IRQ_READ2__dma2_eop__BITNR 5
+#define R_IRQ_READ2__dma2_eop__WIDTH 1
+#define R_IRQ_READ2__dma2_eop__active 1
+#define R_IRQ_READ2__dma2_eop__inactive 0
+#define R_IRQ_READ2__dma2_descr__BITNR 4
+#define R_IRQ_READ2__dma2_descr__WIDTH 1
+#define R_IRQ_READ2__dma2_descr__active 1
+#define R_IRQ_READ2__dma2_descr__inactive 0
+#define R_IRQ_READ2__dma1_eop__BITNR 3
+#define R_IRQ_READ2__dma1_eop__WIDTH 1
+#define R_IRQ_READ2__dma1_eop__active 1
+#define R_IRQ_READ2__dma1_eop__inactive 0
+#define R_IRQ_READ2__dma1_descr__BITNR 2
+#define R_IRQ_READ2__dma1_descr__WIDTH 1
+#define R_IRQ_READ2__dma1_descr__active 1
+#define R_IRQ_READ2__dma1_descr__inactive 0
+#define R_IRQ_READ2__dma0_eop__BITNR 1
+#define R_IRQ_READ2__dma0_eop__WIDTH 1
+#define R_IRQ_READ2__dma0_eop__active 1
+#define R_IRQ_READ2__dma0_eop__inactive 0
+#define R_IRQ_READ2__dma0_descr__BITNR 0
+#define R_IRQ_READ2__dma0_descr__WIDTH 1
+#define R_IRQ_READ2__dma0_descr__active 1
+#define R_IRQ_READ2__dma0_descr__inactive 0
+
+#define R_IRQ_MASK2_SET (IO_TYPECAST_UDWORD 0xb00000d4)
+#define R_IRQ_MASK2_SET__dma8_sub3_descr__BITNR 23
+#define R_IRQ_MASK2_SET__dma8_sub3_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma8_sub3_descr__set 1
+#define R_IRQ_MASK2_SET__dma8_sub3_descr__nop 0
+#define R_IRQ_MASK2_SET__dma8_sub2_descr__BITNR 22
+#define R_IRQ_MASK2_SET__dma8_sub2_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma8_sub2_descr__set 1
+#define R_IRQ_MASK2_SET__dma8_sub2_descr__nop 0
+#define R_IRQ_MASK2_SET__dma8_sub1_descr__BITNR 21
+#define R_IRQ_MASK2_SET__dma8_sub1_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma8_sub1_descr__set 1
+#define R_IRQ_MASK2_SET__dma8_sub1_descr__nop 0
+#define R_IRQ_MASK2_SET__dma8_sub0_descr__BITNR 20
+#define R_IRQ_MASK2_SET__dma8_sub0_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma8_sub0_descr__set 1
+#define R_IRQ_MASK2_SET__dma8_sub0_descr__nop 0
+#define R_IRQ_MASK2_SET__dma9_eop__BITNR 19
+#define R_IRQ_MASK2_SET__dma9_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma9_eop__set 1
+#define R_IRQ_MASK2_SET__dma9_eop__nop 0
+#define R_IRQ_MASK2_SET__dma9_descr__BITNR 18
+#define R_IRQ_MASK2_SET__dma9_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma9_descr__set 1
+#define R_IRQ_MASK2_SET__dma9_descr__nop 0
+#define R_IRQ_MASK2_SET__dma8_eop__BITNR 17
+#define R_IRQ_MASK2_SET__dma8_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma8_eop__set 1
+#define R_IRQ_MASK2_SET__dma8_eop__nop 0
+#define R_IRQ_MASK2_SET__dma8_descr__BITNR 16
+#define R_IRQ_MASK2_SET__dma8_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma8_descr__set 1
+#define R_IRQ_MASK2_SET__dma8_descr__nop 0
+#define R_IRQ_MASK2_SET__dma7_eop__BITNR 15
+#define R_IRQ_MASK2_SET__dma7_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma7_eop__set 1
+#define R_IRQ_MASK2_SET__dma7_eop__nop 0
+#define R_IRQ_MASK2_SET__dma7_descr__BITNR 14
+#define R_IRQ_MASK2_SET__dma7_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma7_descr__set 1
+#define R_IRQ_MASK2_SET__dma7_descr__nop 0
+#define R_IRQ_MASK2_SET__dma6_eop__BITNR 13
+#define R_IRQ_MASK2_SET__dma6_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma6_eop__set 1
+#define R_IRQ_MASK2_SET__dma6_eop__nop 0
+#define R_IRQ_MASK2_SET__dma6_descr__BITNR 12
+#define R_IRQ_MASK2_SET__dma6_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma6_descr__set 1
+#define R_IRQ_MASK2_SET__dma6_descr__nop 0
+#define R_IRQ_MASK2_SET__dma5_eop__BITNR 11
+#define R_IRQ_MASK2_SET__dma5_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma5_eop__set 1
+#define R_IRQ_MASK2_SET__dma5_eop__nop 0
+#define R_IRQ_MASK2_SET__dma5_descr__BITNR 10
+#define R_IRQ_MASK2_SET__dma5_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma5_descr__set 1
+#define R_IRQ_MASK2_SET__dma5_descr__nop 0
+#define R_IRQ_MASK2_SET__dma4_eop__BITNR 9
+#define R_IRQ_MASK2_SET__dma4_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma4_eop__set 1
+#define R_IRQ_MASK2_SET__dma4_eop__nop 0
+#define R_IRQ_MASK2_SET__dma4_descr__BITNR 8
+#define R_IRQ_MASK2_SET__dma4_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma4_descr__set 1
+#define R_IRQ_MASK2_SET__dma4_descr__nop 0
+#define R_IRQ_MASK2_SET__dma3_eop__BITNR 7
+#define R_IRQ_MASK2_SET__dma3_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma3_eop__set 1
+#define R_IRQ_MASK2_SET__dma3_eop__nop 0
+#define R_IRQ_MASK2_SET__dma3_descr__BITNR 6
+#define R_IRQ_MASK2_SET__dma3_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma3_descr__set 1
+#define R_IRQ_MASK2_SET__dma3_descr__nop 0
+#define R_IRQ_MASK2_SET__dma2_eop__BITNR 5
+#define R_IRQ_MASK2_SET__dma2_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma2_eop__set 1
+#define R_IRQ_MASK2_SET__dma2_eop__nop 0
+#define R_IRQ_MASK2_SET__dma2_descr__BITNR 4
+#define R_IRQ_MASK2_SET__dma2_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma2_descr__set 1
+#define R_IRQ_MASK2_SET__dma2_descr__nop 0
+#define R_IRQ_MASK2_SET__dma1_eop__BITNR 3
+#define R_IRQ_MASK2_SET__dma1_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma1_eop__set 1
+#define R_IRQ_MASK2_SET__dma1_eop__nop 0
+#define R_IRQ_MASK2_SET__dma1_descr__BITNR 2
+#define R_IRQ_MASK2_SET__dma1_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma1_descr__set 1
+#define R_IRQ_MASK2_SET__dma1_descr__nop 0
+#define R_IRQ_MASK2_SET__dma0_eop__BITNR 1
+#define R_IRQ_MASK2_SET__dma0_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma0_eop__set 1
+#define R_IRQ_MASK2_SET__dma0_eop__nop 0
+#define R_IRQ_MASK2_SET__dma0_descr__BITNR 0
+#define R_IRQ_MASK2_SET__dma0_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma0_descr__set 1
+#define R_IRQ_MASK2_SET__dma0_descr__nop 0
+
+#define R_VECT_MASK_RD (IO_TYPECAST_RO_UDWORD 0xb00000d8)
+#define R_VECT_MASK_RD__usb__BITNR 31
+#define R_VECT_MASK_RD__usb__WIDTH 1
+#define R_VECT_MASK_RD__usb__active 1
+#define R_VECT_MASK_RD__usb__inactive 0
+#define R_VECT_MASK_RD__dma9__BITNR 25
+#define R_VECT_MASK_RD__dma9__WIDTH 1
+#define R_VECT_MASK_RD__dma9__active 1
+#define R_VECT_MASK_RD__dma9__inactive 0
+#define R_VECT_MASK_RD__dma8__BITNR 24
+#define R_VECT_MASK_RD__dma8__WIDTH 1
+#define R_VECT_MASK_RD__dma8__active 1
+#define R_VECT_MASK_RD__dma8__inactive 0
+#define R_VECT_MASK_RD__dma7__BITNR 23
+#define R_VECT_MASK_RD__dma7__WIDTH 1
+#define R_VECT_MASK_RD__dma7__active 1
+#define R_VECT_MASK_RD__dma7__inactive 0
+#define R_VECT_MASK_RD__dma6__BITNR 22
+#define R_VECT_MASK_RD__dma6__WIDTH 1
+#define R_VECT_MASK_RD__dma6__active 1
+#define R_VECT_MASK_RD__dma6__inactive 0
+#define R_VECT_MASK_RD__dma5__BITNR 21
+#define R_VECT_MASK_RD__dma5__WIDTH 1
+#define R_VECT_MASK_RD__dma5__active 1
+#define R_VECT_MASK_RD__dma5__inactive 0
+#define R_VECT_MASK_RD__dma4__BITNR 20
+#define R_VECT_MASK_RD__dma4__WIDTH 1
+#define R_VECT_MASK_RD__dma4__active 1
+#define R_VECT_MASK_RD__dma4__inactive 0
+#define R_VECT_MASK_RD__dma3__BITNR 19
+#define R_VECT_MASK_RD__dma3__WIDTH 1
+#define R_VECT_MASK_RD__dma3__active 1
+#define R_VECT_MASK_RD__dma3__inactive 0
+#define R_VECT_MASK_RD__dma2__BITNR 18
+#define R_VECT_MASK_RD__dma2__WIDTH 1
+#define R_VECT_MASK_RD__dma2__active 1
+#define R_VECT_MASK_RD__dma2__inactive 0
+#define R_VECT_MASK_RD__dma1__BITNR 17
+#define R_VECT_MASK_RD__dma1__WIDTH 1
+#define R_VECT_MASK_RD__dma1__active 1
+#define R_VECT_MASK_RD__dma1__inactive 0
+#define R_VECT_MASK_RD__dma0__BITNR 16
+#define R_VECT_MASK_RD__dma0__WIDTH 1
+#define R_VECT_MASK_RD__dma0__active 1
+#define R_VECT_MASK_RD__dma0__inactive 0
+#define R_VECT_MASK_RD__ext_dma1__BITNR 13
+#define R_VECT_MASK_RD__ext_dma1__WIDTH 1
+#define R_VECT_MASK_RD__ext_dma1__active 1
+#define R_VECT_MASK_RD__ext_dma1__inactive 0
+#define R_VECT_MASK_RD__ext_dma0__BITNR 12
+#define R_VECT_MASK_RD__ext_dma0__WIDTH 1
+#define R_VECT_MASK_RD__ext_dma0__active 1
+#define R_VECT_MASK_RD__ext_dma0__inactive 0
+#define R_VECT_MASK_RD__pa__BITNR 11
+#define R_VECT_MASK_RD__pa__WIDTH 1
+#define R_VECT_MASK_RD__pa__active 1
+#define R_VECT_MASK_RD__pa__inactive 0
+#define R_VECT_MASK_RD__irq_intnr__BITNR 10
+#define R_VECT_MASK_RD__irq_intnr__WIDTH 1
+#define R_VECT_MASK_RD__irq_intnr__active 1
+#define R_VECT_MASK_RD__irq_intnr__inactive 0
+#define R_VECT_MASK_RD__sw__BITNR 9
+#define R_VECT_MASK_RD__sw__WIDTH 1
+#define R_VECT_MASK_RD__sw__active 1
+#define R_VECT_MASK_RD__sw__inactive 0
+#define R_VECT_MASK_RD__serial__BITNR 8
+#define R_VECT_MASK_RD__serial__WIDTH 1
+#define R_VECT_MASK_RD__serial__active 1
+#define R_VECT_MASK_RD__serial__inactive 0
+#define R_VECT_MASK_RD__snmp__BITNR 7
+#define R_VECT_MASK_RD__snmp__WIDTH 1
+#define R_VECT_MASK_RD__snmp__active 1
+#define R_VECT_MASK_RD__snmp__inactive 0
+#define R_VECT_MASK_RD__network__BITNR 6
+#define R_VECT_MASK_RD__network__WIDTH 1
+#define R_VECT_MASK_RD__network__active 1
+#define R_VECT_MASK_RD__network__inactive 0
+#define R_VECT_MASK_RD__scsi1__BITNR 5
+#define R_VECT_MASK_RD__scsi1__WIDTH 1
+#define R_VECT_MASK_RD__scsi1__active 1
+#define R_VECT_MASK_RD__scsi1__inactive 0
+#define R_VECT_MASK_RD__par1__BITNR 5
+#define R_VECT_MASK_RD__par1__WIDTH 1
+#define R_VECT_MASK_RD__par1__active 1
+#define R_VECT_MASK_RD__par1__inactive 0
+#define R_VECT_MASK_RD__scsi0__BITNR 4
+#define R_VECT_MASK_RD__scsi0__WIDTH 1
+#define R_VECT_MASK_RD__scsi0__active 1
+#define R_VECT_MASK_RD__scsi0__inactive 0
+#define R_VECT_MASK_RD__par0__BITNR 4
+#define R_VECT_MASK_RD__par0__WIDTH 1
+#define R_VECT_MASK_RD__par0__active 1
+#define R_VECT_MASK_RD__par0__inactive 0
+#define R_VECT_MASK_RD__ata__BITNR 4
+#define R_VECT_MASK_RD__ata__WIDTH 1
+#define R_VECT_MASK_RD__ata__active 1
+#define R_VECT_MASK_RD__ata__inactive 0
+#define R_VECT_MASK_RD__mio__BITNR 4
+#define R_VECT_MASK_RD__mio__WIDTH 1
+#define R_VECT_MASK_RD__mio__active 1
+#define R_VECT_MASK_RD__mio__inactive 0
+#define R_VECT_MASK_RD__timer1__BITNR 3
+#define R_VECT_MASK_RD__timer1__WIDTH 1
+#define R_VECT_MASK_RD__timer1__active 1
+#define R_VECT_MASK_RD__timer1__inactive 0
+#define R_VECT_MASK_RD__timer0__BITNR 2
+#define R_VECT_MASK_RD__timer0__WIDTH 1
+#define R_VECT_MASK_RD__timer0__active 1
+#define R_VECT_MASK_RD__timer0__inactive 0
+#define R_VECT_MASK_RD__nmi__BITNR 1
+#define R_VECT_MASK_RD__nmi__WIDTH 1
+#define R_VECT_MASK_RD__nmi__active 1
+#define R_VECT_MASK_RD__nmi__inactive 0
+#define R_VECT_MASK_RD__some__BITNR 0
+#define R_VECT_MASK_RD__some__WIDTH 1
+#define R_VECT_MASK_RD__some__active 1
+#define R_VECT_MASK_RD__some__inactive 0
+
+#define R_VECT_MASK_CLR (IO_TYPECAST_UDWORD 0xb00000d8)
+#define R_VECT_MASK_CLR__usb__BITNR 31
+#define R_VECT_MASK_CLR__usb__WIDTH 1
+#define R_VECT_MASK_CLR__usb__clr 1
+#define R_VECT_MASK_CLR__usb__nop 0
+#define R_VECT_MASK_CLR__dma9__BITNR 25
+#define R_VECT_MASK_CLR__dma9__WIDTH 1
+#define R_VECT_MASK_CLR__dma9__clr 1
+#define R_VECT_MASK_CLR__dma9__nop 0
+#define R_VECT_MASK_CLR__dma8__BITNR 24
+#define R_VECT_MASK_CLR__dma8__WIDTH 1
+#define R_VECT_MASK_CLR__dma8__clr 1
+#define R_VECT_MASK_CLR__dma8__nop 0
+#define R_VECT_MASK_CLR__dma7__BITNR 23
+#define R_VECT_MASK_CLR__dma7__WIDTH 1
+#define R_VECT_MASK_CLR__dma7__clr 1
+#define R_VECT_MASK_CLR__dma7__nop 0
+#define R_VECT_MASK_CLR__dma6__BITNR 22
+#define R_VECT_MASK_CLR__dma6__WIDTH 1
+#define R_VECT_MASK_CLR__dma6__clr 1
+#define R_VECT_MASK_CLR__dma6__nop 0
+#define R_VECT_MASK_CLR__dma5__BITNR 21
+#define R_VECT_MASK_CLR__dma5__WIDTH 1
+#define R_VECT_MASK_CLR__dma5__clr 1
+#define R_VECT_MASK_CLR__dma5__nop 0
+#define R_VECT_MASK_CLR__dma4__BITNR 20
+#define R_VECT_MASK_CLR__dma4__WIDTH 1
+#define R_VECT_MASK_CLR__dma4__clr 1
+#define R_VECT_MASK_CLR__dma4__nop 0
+#define R_VECT_MASK_CLR__dma3__BITNR 19
+#define R_VECT_MASK_CLR__dma3__WIDTH 1
+#define R_VECT_MASK_CLR__dma3__clr 1
+#define R_VECT_MASK_CLR__dma3__nop 0
+#define R_VECT_MASK_CLR__dma2__BITNR 18
+#define R_VECT_MASK_CLR__dma2__WIDTH 1
+#define R_VECT_MASK_CLR__dma2__clr 1
+#define R_VECT_MASK_CLR__dma2__nop 0
+#define R_VECT_MASK_CLR__dma1__BITNR 17
+#define R_VECT_MASK_CLR__dma1__WIDTH 1
+#define R_VECT_MASK_CLR__dma1__clr 1
+#define R_VECT_MASK_CLR__dma1__nop 0
+#define R_VECT_MASK_CLR__dma0__BITNR 16
+#define R_VECT_MASK_CLR__dma0__WIDTH 1
+#define R_VECT_MASK_CLR__dma0__clr 1
+#define R_VECT_MASK_CLR__dma0__nop 0
+#define R_VECT_MASK_CLR__ext_dma1__BITNR 13
+#define R_VECT_MASK_CLR__ext_dma1__WIDTH 1
+#define R_VECT_MASK_CLR__ext_dma1__clr 1
+#define R_VECT_MASK_CLR__ext_dma1__nop 0
+#define R_VECT_MASK_CLR__ext_dma0__BITNR 12
+#define R_VECT_MASK_CLR__ext_dma0__WIDTH 1
+#define R_VECT_MASK_CLR__ext_dma0__clr 1
+#define R_VECT_MASK_CLR__ext_dma0__nop 0
+#define R_VECT_MASK_CLR__pa__BITNR 11
+#define R_VECT_MASK_CLR__pa__WIDTH 1
+#define R_VECT_MASK_CLR__pa__clr 1
+#define R_VECT_MASK_CLR__pa__nop 0
+#define R_VECT_MASK_CLR__irq_intnr__BITNR 10
+#define R_VECT_MASK_CLR__irq_intnr__WIDTH 1
+#define R_VECT_MASK_CLR__irq_intnr__clr 1
+#define R_VECT_MASK_CLR__irq_intnr__nop 0
+#define R_VECT_MASK_CLR__sw__BITNR 9
+#define R_VECT_MASK_CLR__sw__WIDTH 1
+#define R_VECT_MASK_CLR__sw__clr 1
+#define R_VECT_MASK_CLR__sw__nop 0
+#define R_VECT_MASK_CLR__serial__BITNR 8
+#define R_VECT_MASK_CLR__serial__WIDTH 1
+#define R_VECT_MASK_CLR__serial__clr 1
+#define R_VECT_MASK_CLR__serial__nop 0
+#define R_VECT_MASK_CLR__snmp__BITNR 7
+#define R_VECT_MASK_CLR__snmp__WIDTH 1
+#define R_VECT_MASK_CLR__snmp__clr 1
+#define R_VECT_MASK_CLR__snmp__nop 0
+#define R_VECT_MASK_CLR__network__BITNR 6
+#define R_VECT_MASK_CLR__network__WIDTH 1
+#define R_VECT_MASK_CLR__network__clr 1
+#define R_VECT_MASK_CLR__network__nop 0
+#define R_VECT_MASK_CLR__scsi1__BITNR 5
+#define R_VECT_MASK_CLR__scsi1__WIDTH 1
+#define R_VECT_MASK_CLR__scsi1__clr 1
+#define R_VECT_MASK_CLR__scsi1__nop 0
+#define R_VECT_MASK_CLR__par1__BITNR 5
+#define R_VECT_MASK_CLR__par1__WIDTH 1
+#define R_VECT_MASK_CLR__par1__clr 1
+#define R_VECT_MASK_CLR__par1__nop 0
+#define R_VECT_MASK_CLR__scsi0__BITNR 4
+#define R_VECT_MASK_CLR__scsi0__WIDTH 1
+#define R_VECT_MASK_CLR__scsi0__clr 1
+#define R_VECT_MASK_CLR__scsi0__nop 0
+#define R_VECT_MASK_CLR__par0__BITNR 4
+#define R_VECT_MASK_CLR__par0__WIDTH 1
+#define R_VECT_MASK_CLR__par0__clr 1
+#define R_VECT_MASK_CLR__par0__nop 0
+#define R_VECT_MASK_CLR__ata__BITNR 4
+#define R_VECT_MASK_CLR__ata__WIDTH 1
+#define R_VECT_MASK_CLR__ata__clr 1
+#define R_VECT_MASK_CLR__ata__nop 0
+#define R_VECT_MASK_CLR__mio__BITNR 4
+#define R_VECT_MASK_CLR__mio__WIDTH 1
+#define R_VECT_MASK_CLR__mio__clr 1
+#define R_VECT_MASK_CLR__mio__nop 0
+#define R_VECT_MASK_CLR__timer1__BITNR 3
+#define R_VECT_MASK_CLR__timer1__WIDTH 1
+#define R_VECT_MASK_CLR__timer1__clr 1
+#define R_VECT_MASK_CLR__timer1__nop 0
+#define R_VECT_MASK_CLR__timer0__BITNR 2
+#define R_VECT_MASK_CLR__timer0__WIDTH 1
+#define R_VECT_MASK_CLR__timer0__clr 1
+#define R_VECT_MASK_CLR__timer0__nop 0
+#define R_VECT_MASK_CLR__nmi__BITNR 1
+#define R_VECT_MASK_CLR__nmi__WIDTH 1
+#define R_VECT_MASK_CLR__nmi__clr 1
+#define R_VECT_MASK_CLR__nmi__nop 0
+#define R_VECT_MASK_CLR__some__BITNR 0
+#define R_VECT_MASK_CLR__some__WIDTH 1
+#define R_VECT_MASK_CLR__some__clr 1
+#define R_VECT_MASK_CLR__some__nop 0
+
+#define R_VECT_READ (IO_TYPECAST_RO_UDWORD 0xb00000dc)
+#define R_VECT_READ__usb__BITNR 31
+#define R_VECT_READ__usb__WIDTH 1
+#define R_VECT_READ__usb__active 1
+#define R_VECT_READ__usb__inactive 0
+#define R_VECT_READ__dma9__BITNR 25
+#define R_VECT_READ__dma9__WIDTH 1
+#define R_VECT_READ__dma9__active 1
+#define R_VECT_READ__dma9__inactive 0
+#define R_VECT_READ__dma8__BITNR 24
+#define R_VECT_READ__dma8__WIDTH 1
+#define R_VECT_READ__dma8__active 1
+#define R_VECT_READ__dma8__inactive 0
+#define R_VECT_READ__dma7__BITNR 23
+#define R_VECT_READ__dma7__WIDTH 1
+#define R_VECT_READ__dma7__active 1
+#define R_VECT_READ__dma7__inactive 0
+#define R_VECT_READ__dma6__BITNR 22
+#define R_VECT_READ__dma6__WIDTH 1
+#define R_VECT_READ__dma6__active 1
+#define R_VECT_READ__dma6__inactive 0
+#define R_VECT_READ__dma5__BITNR 21
+#define R_VECT_READ__dma5__WIDTH 1
+#define R_VECT_READ__dma5__active 1
+#define R_VECT_READ__dma5__inactive 0
+#define R_VECT_READ__dma4__BITNR 20
+#define R_VECT_READ__dma4__WIDTH 1
+#define R_VECT_READ__dma4__active 1
+#define R_VECT_READ__dma4__inactive 0
+#define R_VECT_READ__dma3__BITNR 19
+#define R_VECT_READ__dma3__WIDTH 1
+#define R_VECT_READ__dma3__active 1
+#define R_VECT_READ__dma3__inactive 0
+#define R_VECT_READ__dma2__BITNR 18
+#define R_VECT_READ__dma2__WIDTH 1
+#define R_VECT_READ__dma2__active 1
+#define R_VECT_READ__dma2__inactive 0
+#define R_VECT_READ__dma1__BITNR 17
+#define R_VECT_READ__dma1__WIDTH 1
+#define R_VECT_READ__dma1__active 1
+#define R_VECT_READ__dma1__inactive 0
+#define R_VECT_READ__dma0__BITNR 16
+#define R_VECT_READ__dma0__WIDTH 1
+#define R_VECT_READ__dma0__active 1
+#define R_VECT_READ__dma0__inactive 0
+#define R_VECT_READ__ext_dma1__BITNR 13
+#define R_VECT_READ__ext_dma1__WIDTH 1
+#define R_VECT_READ__ext_dma1__active 1
+#define R_VECT_READ__ext_dma1__inactive 0
+#define R_VECT_READ__ext_dma0__BITNR 12
+#define R_VECT_READ__ext_dma0__WIDTH 1
+#define R_VECT_READ__ext_dma0__active 1
+#define R_VECT_READ__ext_dma0__inactive 0
+#define R_VECT_READ__pa__BITNR 11
+#define R_VECT_READ__pa__WIDTH 1
+#define R_VECT_READ__pa__active 1
+#define R_VECT_READ__pa__inactive 0
+#define R_VECT_READ__irq_intnr__BITNR 10
+#define R_VECT_READ__irq_intnr__WIDTH 1
+#define R_VECT_READ__irq_intnr__active 1
+#define R_VECT_READ__irq_intnr__inactive 0
+#define R_VECT_READ__sw__BITNR 9
+#define R_VECT_READ__sw__WIDTH 1
+#define R_VECT_READ__sw__active 1
+#define R_VECT_READ__sw__inactive 0
+#define R_VECT_READ__serial__BITNR 8
+#define R_VECT_READ__serial__WIDTH 1
+#define R_VECT_READ__serial__active 1
+#define R_VECT_READ__serial__inactive 0
+#define R_VECT_READ__snmp__BITNR 7
+#define R_VECT_READ__snmp__WIDTH 1
+#define R_VECT_READ__snmp__active 1
+#define R_VECT_READ__snmp__inactive 0
+#define R_VECT_READ__network__BITNR 6
+#define R_VECT_READ__network__WIDTH 1
+#define R_VECT_READ__network__active 1
+#define R_VECT_READ__network__inactive 0
+#define R_VECT_READ__scsi1__BITNR 5
+#define R_VECT_READ__scsi1__WIDTH 1
+#define R_VECT_READ__scsi1__active 1
+#define R_VECT_READ__scsi1__inactive 0
+#define R_VECT_READ__par1__BITNR 5
+#define R_VECT_READ__par1__WIDTH 1
+#define R_VECT_READ__par1__active 1
+#define R_VECT_READ__par1__inactive 0
+#define R_VECT_READ__scsi0__BITNR 4
+#define R_VECT_READ__scsi0__WIDTH 1
+#define R_VECT_READ__scsi0__active 1
+#define R_VECT_READ__scsi0__inactive 0
+#define R_VECT_READ__par0__BITNR 4
+#define R_VECT_READ__par0__WIDTH 1
+#define R_VECT_READ__par0__active 1
+#define R_VECT_READ__par0__inactive 0
+#define R_VECT_READ__ata__BITNR 4
+#define R_VECT_READ__ata__WIDTH 1
+#define R_VECT_READ__ata__active 1
+#define R_VECT_READ__ata__inactive 0
+#define R_VECT_READ__mio__BITNR 4
+#define R_VECT_READ__mio__WIDTH 1
+#define R_VECT_READ__mio__active 1
+#define R_VECT_READ__mio__inactive 0
+#define R_VECT_READ__timer1__BITNR 3
+#define R_VECT_READ__timer1__WIDTH 1
+#define R_VECT_READ__timer1__active 1
+#define R_VECT_READ__timer1__inactive 0
+#define R_VECT_READ__timer0__BITNR 2
+#define R_VECT_READ__timer0__WIDTH 1
+#define R_VECT_READ__timer0__active 1
+#define R_VECT_READ__timer0__inactive 0
+#define R_VECT_READ__nmi__BITNR 1
+#define R_VECT_READ__nmi__WIDTH 1
+#define R_VECT_READ__nmi__active 1
+#define R_VECT_READ__nmi__inactive 0
+#define R_VECT_READ__some__BITNR 0
+#define R_VECT_READ__some__WIDTH 1
+#define R_VECT_READ__some__active 1
+#define R_VECT_READ__some__inactive 0
+
+#define R_VECT_MASK_SET (IO_TYPECAST_UDWORD 0xb00000dc)
+#define R_VECT_MASK_SET__usb__BITNR 31
+#define R_VECT_MASK_SET__usb__WIDTH 1
+#define R_VECT_MASK_SET__usb__set 1
+#define R_VECT_MASK_SET__usb__nop 0
+#define R_VECT_MASK_SET__dma9__BITNR 25
+#define R_VECT_MASK_SET__dma9__WIDTH 1
+#define R_VECT_MASK_SET__dma9__set 1
+#define R_VECT_MASK_SET__dma9__nop 0
+#define R_VECT_MASK_SET__dma8__BITNR 24
+#define R_VECT_MASK_SET__dma8__WIDTH 1
+#define R_VECT_MASK_SET__dma8__set 1
+#define R_VECT_MASK_SET__dma8__nop 0
+#define R_VECT_MASK_SET__dma7__BITNR 23
+#define R_VECT_MASK_SET__dma7__WIDTH 1
+#define R_VECT_MASK_SET__dma7__set 1
+#define R_VECT_MASK_SET__dma7__nop 0
+#define R_VECT_MASK_SET__dma6__BITNR 22
+#define R_VECT_MASK_SET__dma6__WIDTH 1
+#define R_VECT_MASK_SET__dma6__set 1
+#define R_VECT_MASK_SET__dma6__nop 0
+#define R_VECT_MASK_SET__dma5__BITNR 21
+#define R_VECT_MASK_SET__dma5__WIDTH 1
+#define R_VECT_MASK_SET__dma5__set 1
+#define R_VECT_MASK_SET__dma5__nop 0
+#define R_VECT_MASK_SET__dma4__BITNR 20
+#define R_VECT_MASK_SET__dma4__WIDTH 1
+#define R_VECT_MASK_SET__dma4__set 1
+#define R_VECT_MASK_SET__dma4__nop 0
+#define R_VECT_MASK_SET__dma3__BITNR 19
+#define R_VECT_MASK_SET__dma3__WIDTH 1
+#define R_VECT_MASK_SET__dma3__set 1
+#define R_VECT_MASK_SET__dma3__nop 0
+#define R_VECT_MASK_SET__dma2__BITNR 18
+#define R_VECT_MASK_SET__dma2__WIDTH 1
+#define R_VECT_MASK_SET__dma2__set 1
+#define R_VECT_MASK_SET__dma2__nop 0
+#define R_VECT_MASK_SET__dma1__BITNR 17
+#define R_VECT_MASK_SET__dma1__WIDTH 1
+#define R_VECT_MASK_SET__dma1__set 1
+#define R_VECT_MASK_SET__dma1__nop 0
+#define R_VECT_MASK_SET__dma0__BITNR 16
+#define R_VECT_MASK_SET__dma0__WIDTH 1
+#define R_VECT_MASK_SET__dma0__set 1
+#define R_VECT_MASK_SET__dma0__nop 0
+#define R_VECT_MASK_SET__ext_dma1__BITNR 13
+#define R_VECT_MASK_SET__ext_dma1__WIDTH 1
+#define R_VECT_MASK_SET__ext_dma1__set 1
+#define R_VECT_MASK_SET__ext_dma1__nop 0
+#define R_VECT_MASK_SET__ext_dma0__BITNR 12
+#define R_VECT_MASK_SET__ext_dma0__WIDTH 1
+#define R_VECT_MASK_SET__ext_dma0__set 1
+#define R_VECT_MASK_SET__ext_dma0__nop 0
+#define R_VECT_MASK_SET__pa__BITNR 11
+#define R_VECT_MASK_SET__pa__WIDTH 1
+#define R_VECT_MASK_SET__pa__set 1
+#define R_VECT_MASK_SET__pa__nop 0
+#define R_VECT_MASK_SET__irq_intnr__BITNR 10
+#define R_VECT_MASK_SET__irq_intnr__WIDTH 1
+#define R_VECT_MASK_SET__irq_intnr__set 1
+#define R_VECT_MASK_SET__irq_intnr__nop 0
+#define R_VECT_MASK_SET__sw__BITNR 9
+#define R_VECT_MASK_SET__sw__WIDTH 1
+#define R_VECT_MASK_SET__sw__set 1
+#define R_VECT_MASK_SET__sw__nop 0
+#define R_VECT_MASK_SET__serial__BITNR 8
+#define R_VECT_MASK_SET__serial__WIDTH 1
+#define R_VECT_MASK_SET__serial__set 1
+#define R_VECT_MASK_SET__serial__nop 0
+#define R_VECT_MASK_SET__snmp__BITNR 7
+#define R_VECT_MASK_SET__snmp__WIDTH 1
+#define R_VECT_MASK_SET__snmp__set 1
+#define R_VECT_MASK_SET__snmp__nop 0
+#define R_VECT_MASK_SET__network__BITNR 6
+#define R_VECT_MASK_SET__network__WIDTH 1
+#define R_VECT_MASK_SET__network__set 1
+#define R_VECT_MASK_SET__network__nop 0
+#define R_VECT_MASK_SET__scsi1__BITNR 5
+#define R_VECT_MASK_SET__scsi1__WIDTH 1
+#define R_VECT_MASK_SET__scsi1__set 1
+#define R_VECT_MASK_SET__scsi1__nop 0
+#define R_VECT_MASK_SET__par1__BITNR 5
+#define R_VECT_MASK_SET__par1__WIDTH 1
+#define R_VECT_MASK_SET__par1__set 1
+#define R_VECT_MASK_SET__par1__nop 0
+#define R_VECT_MASK_SET__scsi0__BITNR 4
+#define R_VECT_MASK_SET__scsi0__WIDTH 1
+#define R_VECT_MASK_SET__scsi0__set 1
+#define R_VECT_MASK_SET__scsi0__nop 0
+#define R_VECT_MASK_SET__par0__BITNR 4
+#define R_VECT_MASK_SET__par0__WIDTH 1
+#define R_VECT_MASK_SET__par0__set 1
+#define R_VECT_MASK_SET__par0__nop 0
+#define R_VECT_MASK_SET__ata__BITNR 4
+#define R_VECT_MASK_SET__ata__WIDTH 1
+#define R_VECT_MASK_SET__ata__set 1
+#define R_VECT_MASK_SET__ata__nop 0
+#define R_VECT_MASK_SET__mio__BITNR 4
+#define R_VECT_MASK_SET__mio__WIDTH 1
+#define R_VECT_MASK_SET__mio__set 1
+#define R_VECT_MASK_SET__mio__nop 0
+#define R_VECT_MASK_SET__timer1__BITNR 3
+#define R_VECT_MASK_SET__timer1__WIDTH 1
+#define R_VECT_MASK_SET__timer1__set 1
+#define R_VECT_MASK_SET__timer1__nop 0
+#define R_VECT_MASK_SET__timer0__BITNR 2
+#define R_VECT_MASK_SET__timer0__WIDTH 1
+#define R_VECT_MASK_SET__timer0__set 1
+#define R_VECT_MASK_SET__timer0__nop 0
+#define R_VECT_MASK_SET__nmi__BITNR 1
+#define R_VECT_MASK_SET__nmi__WIDTH 1
+#define R_VECT_MASK_SET__nmi__set 1
+#define R_VECT_MASK_SET__nmi__nop 0
+#define R_VECT_MASK_SET__some__BITNR 0
+#define R_VECT_MASK_SET__some__WIDTH 1
+#define R_VECT_MASK_SET__some__set 1
+#define R_VECT_MASK_SET__some__nop 0
+
+/*
+!* DMA registers
+!*/
+
+#define R_SET_EOP (IO_TYPECAST_UDWORD 0xb000003c)
+#define R_SET_EOP__ch9_eop__BITNR 3
+#define R_SET_EOP__ch9_eop__WIDTH 1
+#define R_SET_EOP__ch9_eop__set 1
+#define R_SET_EOP__ch9_eop__nop 0
+#define R_SET_EOP__ch7_eop__BITNR 2
+#define R_SET_EOP__ch7_eop__WIDTH 1
+#define R_SET_EOP__ch7_eop__set 1
+#define R_SET_EOP__ch7_eop__nop 0
+#define R_SET_EOP__ch5_eop__BITNR 1
+#define R_SET_EOP__ch5_eop__WIDTH 1
+#define R_SET_EOP__ch5_eop__set 1
+#define R_SET_EOP__ch5_eop__nop 0
+#define R_SET_EOP__ch3_eop__BITNR 0
+#define R_SET_EOP__ch3_eop__WIDTH 1
+#define R_SET_EOP__ch3_eop__set 1
+#define R_SET_EOP__ch3_eop__nop 0
+
+#define R_DMA_CH0_HWSW (IO_TYPECAST_UDWORD 0xb0000100)
+#define R_DMA_CH0_HWSW__hw__BITNR 16
+#define R_DMA_CH0_HWSW__hw__WIDTH 16
+#define R_DMA_CH0_HWSW__sw__BITNR 0
+#define R_DMA_CH0_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH0_DESCR (IO_TYPECAST_UDWORD 0xb000010c)
+#define R_DMA_CH0_DESCR__descr__BITNR 0
+#define R_DMA_CH0_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH0_NEXT (IO_TYPECAST_UDWORD 0xb0000104)
+#define R_DMA_CH0_NEXT__next__BITNR 0
+#define R_DMA_CH0_NEXT__next__WIDTH 32
+
+#define R_DMA_CH0_BUF (IO_TYPECAST_UDWORD 0xb0000108)
+#define R_DMA_CH0_BUF__buf__BITNR 0
+#define R_DMA_CH0_BUF__buf__WIDTH 32
+
+#define R_DMA_CH0_FIRST (IO_TYPECAST_UDWORD 0xb00001a0)
+#define R_DMA_CH0_FIRST__first__BITNR 0
+#define R_DMA_CH0_FIRST__first__WIDTH 32
+
+#define R_DMA_CH0_CMD (IO_TYPECAST_BYTE 0xb00001d0)
+#define R_DMA_CH0_CMD__cmd__BITNR 0
+#define R_DMA_CH0_CMD__cmd__WIDTH 3
+#define R_DMA_CH0_CMD__cmd__hold 0
+#define R_DMA_CH0_CMD__cmd__start 1
+#define R_DMA_CH0_CMD__cmd__restart 3
+#define R_DMA_CH0_CMD__cmd__continue 3
+#define R_DMA_CH0_CMD__cmd__reset 4
+
+#define R_DMA_CH0_CLR_INTR (IO_TYPECAST_BYTE 0xb00001d1)
+#define R_DMA_CH0_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH0_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH0_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH0_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH0_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH0_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH0_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH0_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH0_STATUS (IO_TYPECAST_RO_BYTE 0xb00001d2)
+#define R_DMA_CH0_STATUS__avail__BITNR 0
+#define R_DMA_CH0_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH1_HWSW (IO_TYPECAST_UDWORD 0xb0000110)
+#define R_DMA_CH1_HWSW__hw__BITNR 16
+#define R_DMA_CH1_HWSW__hw__WIDTH 16
+#define R_DMA_CH1_HWSW__sw__BITNR 0
+#define R_DMA_CH1_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH1_DESCR (IO_TYPECAST_UDWORD 0xb000011c)
+#define R_DMA_CH1_DESCR__descr__BITNR 0
+#define R_DMA_CH1_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH1_NEXT (IO_TYPECAST_UDWORD 0xb0000114)
+#define R_DMA_CH1_NEXT__next__BITNR 0
+#define R_DMA_CH1_NEXT__next__WIDTH 32
+
+#define R_DMA_CH1_BUF (IO_TYPECAST_UDWORD 0xb0000118)
+#define R_DMA_CH1_BUF__buf__BITNR 0
+#define R_DMA_CH1_BUF__buf__WIDTH 32
+
+#define R_DMA_CH1_FIRST (IO_TYPECAST_UDWORD 0xb00001a4)
+#define R_DMA_CH1_FIRST__first__BITNR 0
+#define R_DMA_CH1_FIRST__first__WIDTH 32
+
+#define R_DMA_CH1_CMD (IO_TYPECAST_BYTE 0xb00001d4)
+#define R_DMA_CH1_CMD__cmd__BITNR 0
+#define R_DMA_CH1_CMD__cmd__WIDTH 3
+#define R_DMA_CH1_CMD__cmd__hold 0
+#define R_DMA_CH1_CMD__cmd__start 1
+#define R_DMA_CH1_CMD__cmd__restart 3
+#define R_DMA_CH1_CMD__cmd__continue 3
+#define R_DMA_CH1_CMD__cmd__reset 4
+
+#define R_DMA_CH1_CLR_INTR (IO_TYPECAST_BYTE 0xb00001d5)
+#define R_DMA_CH1_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH1_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH1_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH1_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH1_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH1_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH1_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH1_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH1_STATUS (IO_TYPECAST_RO_BYTE 0xb00001d6)
+#define R_DMA_CH1_STATUS__avail__BITNR 0
+#define R_DMA_CH1_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH2_HWSW (IO_TYPECAST_UDWORD 0xb0000120)
+#define R_DMA_CH2_HWSW__hw__BITNR 16
+#define R_DMA_CH2_HWSW__hw__WIDTH 16
+#define R_DMA_CH2_HWSW__sw__BITNR 0
+#define R_DMA_CH2_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH2_DESCR (IO_TYPECAST_UDWORD 0xb000012c)
+#define R_DMA_CH2_DESCR__descr__BITNR 0
+#define R_DMA_CH2_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH2_NEXT (IO_TYPECAST_UDWORD 0xb0000124)
+#define R_DMA_CH2_NEXT__next__BITNR 0
+#define R_DMA_CH2_NEXT__next__WIDTH 32
+
+#define R_DMA_CH2_BUF (IO_TYPECAST_UDWORD 0xb0000128)
+#define R_DMA_CH2_BUF__buf__BITNR 0
+#define R_DMA_CH2_BUF__buf__WIDTH 32
+
+#define R_DMA_CH2_FIRST (IO_TYPECAST_UDWORD 0xb00001a8)
+#define R_DMA_CH2_FIRST__first__BITNR 0
+#define R_DMA_CH2_FIRST__first__WIDTH 32
+
+#define R_DMA_CH2_CMD (IO_TYPECAST_BYTE 0xb00001d8)
+#define R_DMA_CH2_CMD__cmd__BITNR 0
+#define R_DMA_CH2_CMD__cmd__WIDTH 3
+#define R_DMA_CH2_CMD__cmd__hold 0
+#define R_DMA_CH2_CMD__cmd__start 1
+#define R_DMA_CH2_CMD__cmd__restart 3
+#define R_DMA_CH2_CMD__cmd__continue 3
+#define R_DMA_CH2_CMD__cmd__reset 4
+
+#define R_DMA_CH2_CLR_INTR (IO_TYPECAST_BYTE 0xb00001d9)
+#define R_DMA_CH2_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH2_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH2_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH2_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH2_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH2_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH2_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH2_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH2_STATUS (IO_TYPECAST_RO_BYTE 0xb00001da)
+#define R_DMA_CH2_STATUS__avail__BITNR 0
+#define R_DMA_CH2_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH3_HWSW (IO_TYPECAST_UDWORD 0xb0000130)
+#define R_DMA_CH3_HWSW__hw__BITNR 16
+#define R_DMA_CH3_HWSW__hw__WIDTH 16
+#define R_DMA_CH3_HWSW__sw__BITNR 0
+#define R_DMA_CH3_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH3_DESCR (IO_TYPECAST_UDWORD 0xb000013c)
+#define R_DMA_CH3_DESCR__descr__BITNR 0
+#define R_DMA_CH3_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH3_NEXT (IO_TYPECAST_UDWORD 0xb0000134)
+#define R_DMA_CH3_NEXT__next__BITNR 0
+#define R_DMA_CH3_NEXT__next__WIDTH 32
+
+#define R_DMA_CH3_BUF (IO_TYPECAST_UDWORD 0xb0000138)
+#define R_DMA_CH3_BUF__buf__BITNR 0
+#define R_DMA_CH3_BUF__buf__WIDTH 32
+
+#define R_DMA_CH3_FIRST (IO_TYPECAST_UDWORD 0xb00001ac)
+#define R_DMA_CH3_FIRST__first__BITNR 0
+#define R_DMA_CH3_FIRST__first__WIDTH 32
+
+#define R_DMA_CH3_CMD (IO_TYPECAST_BYTE 0xb00001dc)
+#define R_DMA_CH3_CMD__cmd__BITNR 0
+#define R_DMA_CH3_CMD__cmd__WIDTH 3
+#define R_DMA_CH3_CMD__cmd__hold 0
+#define R_DMA_CH3_CMD__cmd__start 1
+#define R_DMA_CH3_CMD__cmd__restart 3
+#define R_DMA_CH3_CMD__cmd__continue 3
+#define R_DMA_CH3_CMD__cmd__reset 4
+
+#define R_DMA_CH3_CLR_INTR (IO_TYPECAST_BYTE 0xb00001dd)
+#define R_DMA_CH3_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH3_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH3_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH3_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH3_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH3_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH3_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH3_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH3_STATUS (IO_TYPECAST_RO_BYTE 0xb00001de)
+#define R_DMA_CH3_STATUS__avail__BITNR 0
+#define R_DMA_CH3_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH4_HWSW (IO_TYPECAST_UDWORD 0xb0000140)
+#define R_DMA_CH4_HWSW__hw__BITNR 16
+#define R_DMA_CH4_HWSW__hw__WIDTH 16
+#define R_DMA_CH4_HWSW__sw__BITNR 0
+#define R_DMA_CH4_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH4_DESCR (IO_TYPECAST_UDWORD 0xb000014c)
+#define R_DMA_CH4_DESCR__descr__BITNR 0
+#define R_DMA_CH4_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH4_NEXT (IO_TYPECAST_UDWORD 0xb0000144)
+#define R_DMA_CH4_NEXT__next__BITNR 0
+#define R_DMA_CH4_NEXT__next__WIDTH 32
+
+#define R_DMA_CH4_BUF (IO_TYPECAST_UDWORD 0xb0000148)
+#define R_DMA_CH4_BUF__buf__BITNR 0
+#define R_DMA_CH4_BUF__buf__WIDTH 32
+
+#define R_DMA_CH4_FIRST (IO_TYPECAST_UDWORD 0xb00001b0)
+#define R_DMA_CH4_FIRST__first__BITNR 0
+#define R_DMA_CH4_FIRST__first__WIDTH 32
+
+#define R_DMA_CH4_CMD (IO_TYPECAST_BYTE 0xb00001e0)
+#define R_DMA_CH4_CMD__cmd__BITNR 0
+#define R_DMA_CH4_CMD__cmd__WIDTH 3
+#define R_DMA_CH4_CMD__cmd__hold 0
+#define R_DMA_CH4_CMD__cmd__start 1
+#define R_DMA_CH4_CMD__cmd__restart 3
+#define R_DMA_CH4_CMD__cmd__continue 3
+#define R_DMA_CH4_CMD__cmd__reset 4
+
+#define R_DMA_CH4_CLR_INTR (IO_TYPECAST_BYTE 0xb00001e1)
+#define R_DMA_CH4_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH4_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH4_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH4_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH4_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH4_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH4_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH4_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH4_STATUS (IO_TYPECAST_RO_BYTE 0xb00001e2)
+#define R_DMA_CH4_STATUS__avail__BITNR 0
+#define R_DMA_CH4_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH5_HWSW (IO_TYPECAST_UDWORD 0xb0000150)
+#define R_DMA_CH5_HWSW__hw__BITNR 16
+#define R_DMA_CH5_HWSW__hw__WIDTH 16
+#define R_DMA_CH5_HWSW__sw__BITNR 0
+#define R_DMA_CH5_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH5_DESCR (IO_TYPECAST_UDWORD 0xb000015c)
+#define R_DMA_CH5_DESCR__descr__BITNR 0
+#define R_DMA_CH5_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH5_NEXT (IO_TYPECAST_UDWORD 0xb0000154)
+#define R_DMA_CH5_NEXT__next__BITNR 0
+#define R_DMA_CH5_NEXT__next__WIDTH 32
+
+#define R_DMA_CH5_BUF (IO_TYPECAST_UDWORD 0xb0000158)
+#define R_DMA_CH5_BUF__buf__BITNR 0
+#define R_DMA_CH5_BUF__buf__WIDTH 32
+
+#define R_DMA_CH5_FIRST (IO_TYPECAST_UDWORD 0xb00001b4)
+#define R_DMA_CH5_FIRST__first__BITNR 0
+#define R_DMA_CH5_FIRST__first__WIDTH 32
+
+#define R_DMA_CH5_CMD (IO_TYPECAST_BYTE 0xb00001e4)
+#define R_DMA_CH5_CMD__cmd__BITNR 0
+#define R_DMA_CH5_CMD__cmd__WIDTH 3
+#define R_DMA_CH5_CMD__cmd__hold 0
+#define R_DMA_CH5_CMD__cmd__start 1
+#define R_DMA_CH5_CMD__cmd__restart 3
+#define R_DMA_CH5_CMD__cmd__continue 3
+#define R_DMA_CH5_CMD__cmd__reset 4
+
+#define R_DMA_CH5_CLR_INTR (IO_TYPECAST_BYTE 0xb00001e5)
+#define R_DMA_CH5_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH5_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH5_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH5_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH5_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH5_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH5_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH5_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH5_STATUS (IO_TYPECAST_RO_BYTE 0xb00001e6)
+#define R_DMA_CH5_STATUS__avail__BITNR 0
+#define R_DMA_CH5_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH6_HWSW (IO_TYPECAST_UDWORD 0xb0000160)
+#define R_DMA_CH6_HWSW__hw__BITNR 16
+#define R_DMA_CH6_HWSW__hw__WIDTH 16
+#define R_DMA_CH6_HWSW__sw__BITNR 0
+#define R_DMA_CH6_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH6_DESCR (IO_TYPECAST_UDWORD 0xb000016c)
+#define R_DMA_CH6_DESCR__descr__BITNR 0
+#define R_DMA_CH6_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH6_NEXT (IO_TYPECAST_UDWORD 0xb0000164)
+#define R_DMA_CH6_NEXT__next__BITNR 0
+#define R_DMA_CH6_NEXT__next__WIDTH 32
+
+#define R_DMA_CH6_BUF (IO_TYPECAST_UDWORD 0xb0000168)
+#define R_DMA_CH6_BUF__buf__BITNR 0
+#define R_DMA_CH6_BUF__buf__WIDTH 32
+
+#define R_DMA_CH6_FIRST (IO_TYPECAST_UDWORD 0xb00001b8)
+#define R_DMA_CH6_FIRST__first__BITNR 0
+#define R_DMA_CH6_FIRST__first__WIDTH 32
+
+#define R_DMA_CH6_CMD (IO_TYPECAST_BYTE 0xb00001e8)
+#define R_DMA_CH6_CMD__cmd__BITNR 0
+#define R_DMA_CH6_CMD__cmd__WIDTH 3
+#define R_DMA_CH6_CMD__cmd__hold 0
+#define R_DMA_CH6_CMD__cmd__start 1
+#define R_DMA_CH6_CMD__cmd__restart 3
+#define R_DMA_CH6_CMD__cmd__continue 3
+#define R_DMA_CH6_CMD__cmd__reset 4
+
+#define R_DMA_CH6_CLR_INTR (IO_TYPECAST_BYTE 0xb00001e9)
+#define R_DMA_CH6_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH6_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH6_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH6_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH6_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH6_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH6_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH6_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH6_STATUS (IO_TYPECAST_RO_BYTE 0xb00001ea)
+#define R_DMA_CH6_STATUS__avail__BITNR 0
+#define R_DMA_CH6_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH7_HWSW (IO_TYPECAST_UDWORD 0xb0000170)
+#define R_DMA_CH7_HWSW__hw__BITNR 16
+#define R_DMA_CH7_HWSW__hw__WIDTH 16
+#define R_DMA_CH7_HWSW__sw__BITNR 0
+#define R_DMA_CH7_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH7_DESCR (IO_TYPECAST_UDWORD 0xb000017c)
+#define R_DMA_CH7_DESCR__descr__BITNR 0
+#define R_DMA_CH7_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH7_NEXT (IO_TYPECAST_UDWORD 0xb0000174)
+#define R_DMA_CH7_NEXT__next__BITNR 0
+#define R_DMA_CH7_NEXT__next__WIDTH 32
+
+#define R_DMA_CH7_BUF (IO_TYPECAST_UDWORD 0xb0000178)
+#define R_DMA_CH7_BUF__buf__BITNR 0
+#define R_DMA_CH7_BUF__buf__WIDTH 32
+
+#define R_DMA_CH7_FIRST (IO_TYPECAST_UDWORD 0xb00001bc)
+#define R_DMA_CH7_FIRST__first__BITNR 0
+#define R_DMA_CH7_FIRST__first__WIDTH 32
+
+#define R_DMA_CH7_CMD (IO_TYPECAST_BYTE 0xb00001ec)
+#define R_DMA_CH7_CMD__cmd__BITNR 0
+#define R_DMA_CH7_CMD__cmd__WIDTH 3
+#define R_DMA_CH7_CMD__cmd__hold 0
+#define R_DMA_CH7_CMD__cmd__start 1
+#define R_DMA_CH7_CMD__cmd__restart 3
+#define R_DMA_CH7_CMD__cmd__continue 3
+#define R_DMA_CH7_CMD__cmd__reset 4
+
+#define R_DMA_CH7_CLR_INTR (IO_TYPECAST_BYTE 0xb00001ed)
+#define R_DMA_CH7_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH7_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH7_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH7_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH7_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH7_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH7_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH7_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH7_STATUS (IO_TYPECAST_RO_BYTE 0xb00001ee)
+#define R_DMA_CH7_STATUS__avail__BITNR 0
+#define R_DMA_CH7_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH8_HWSW (IO_TYPECAST_UDWORD 0xb0000180)
+#define R_DMA_CH8_HWSW__hw__BITNR 16
+#define R_DMA_CH8_HWSW__hw__WIDTH 16
+#define R_DMA_CH8_HWSW__sw__BITNR 0
+#define R_DMA_CH8_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH8_DESCR (IO_TYPECAST_UDWORD 0xb000018c)
+#define R_DMA_CH8_DESCR__descr__BITNR 0
+#define R_DMA_CH8_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH8_NEXT (IO_TYPECAST_UDWORD 0xb0000184)
+#define R_DMA_CH8_NEXT__next__BITNR 0
+#define R_DMA_CH8_NEXT__next__WIDTH 32
+
+#define R_DMA_CH8_BUF (IO_TYPECAST_UDWORD 0xb0000188)
+#define R_DMA_CH8_BUF__buf__BITNR 0
+#define R_DMA_CH8_BUF__buf__WIDTH 32
+
+#define R_DMA_CH8_FIRST (IO_TYPECAST_UDWORD 0xb00001c0)
+#define R_DMA_CH8_FIRST__first__BITNR 0
+#define R_DMA_CH8_FIRST__first__WIDTH 32
+
+#define R_DMA_CH8_CMD (IO_TYPECAST_BYTE 0xb00001f0)
+#define R_DMA_CH8_CMD__cmd__BITNR 0
+#define R_DMA_CH8_CMD__cmd__WIDTH 3
+#define R_DMA_CH8_CMD__cmd__hold 0
+#define R_DMA_CH8_CMD__cmd__start 1
+#define R_DMA_CH8_CMD__cmd__restart 3
+#define R_DMA_CH8_CMD__cmd__continue 3
+#define R_DMA_CH8_CMD__cmd__reset 4
+
+#define R_DMA_CH8_CLR_INTR (IO_TYPECAST_BYTE 0xb00001f1)
+#define R_DMA_CH8_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH8_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH8_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH8_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH8_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH8_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH8_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH8_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH8_STATUS (IO_TYPECAST_RO_BYTE 0xb00001f2)
+#define R_DMA_CH8_STATUS__avail__BITNR 0
+#define R_DMA_CH8_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH8_SUB (IO_TYPECAST_UDWORD 0xb000018c)
+#define R_DMA_CH8_SUB__sub__BITNR 0
+#define R_DMA_CH8_SUB__sub__WIDTH 32
+
+#define R_DMA_CH8_NEP (IO_TYPECAST_UDWORD 0xb00001c0)
+#define R_DMA_CH8_NEP__nep__BITNR 0
+#define R_DMA_CH8_NEP__nep__WIDTH 32
+
+#define R_DMA_CH8_SUB0_EP (IO_TYPECAST_UDWORD 0xb00001c8)
+#define R_DMA_CH8_SUB0_EP__ep__BITNR 0
+#define R_DMA_CH8_SUB0_EP__ep__WIDTH 32
+
+#define R_DMA_CH8_SUB0_CMD (IO_TYPECAST_BYTE 0xb00001d3)
+#define R_DMA_CH8_SUB0_CMD__cmd__BITNR 0
+#define R_DMA_CH8_SUB0_CMD__cmd__WIDTH 1
+#define R_DMA_CH8_SUB0_CMD__cmd__stop 0
+#define R_DMA_CH8_SUB0_CMD__cmd__start 1
+
+#define R_DMA_CH8_SUB0_CLR_INTR (IO_TYPECAST_BYTE 0xb00001e3)
+#define R_DMA_CH8_SUB0_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH8_SUB0_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH8_SUB0_CLR_INTR__clr_descr__dont 0
+#define R_DMA_CH8_SUB0_CLR_INTR__clr_descr__do 1
+
+#define R_DMA_CH8_SUB1_EP (IO_TYPECAST_UDWORD 0xb00001cc)
+#define R_DMA_CH8_SUB1_EP__ep__BITNR 0
+#define R_DMA_CH8_SUB1_EP__ep__WIDTH 32
+
+#define R_DMA_CH8_SUB1_CMD (IO_TYPECAST_BYTE 0xb00001d7)
+#define R_DMA_CH8_SUB1_CMD__cmd__BITNR 0
+#define R_DMA_CH8_SUB1_CMD__cmd__WIDTH 1
+#define R_DMA_CH8_SUB1_CMD__cmd__stop 0
+#define R_DMA_CH8_SUB1_CMD__cmd__start 1
+
+#define R_DMA_CH8_SUB1_CLR_INTR (IO_TYPECAST_BYTE 0xb00001e7)
+#define R_DMA_CH8_SUB1_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH8_SUB1_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH8_SUB1_CLR_INTR__clr_descr__dont 0
+#define R_DMA_CH8_SUB1_CLR_INTR__clr_descr__do 1
+
+#define R_DMA_CH8_SUB2_EP (IO_TYPECAST_UDWORD 0xb00001f8)
+#define R_DMA_CH8_SUB2_EP__ep__BITNR 0
+#define R_DMA_CH8_SUB2_EP__ep__WIDTH 32
+
+#define R_DMA_CH8_SUB2_CMD (IO_TYPECAST_BYTE 0xb00001db)
+#define R_DMA_CH8_SUB2_CMD__cmd__BITNR 0
+#define R_DMA_CH8_SUB2_CMD__cmd__WIDTH 1
+#define R_DMA_CH8_SUB2_CMD__cmd__stop 0
+#define R_DMA_CH8_SUB2_CMD__cmd__start 1
+
+#define R_DMA_CH8_SUB2_CLR_INTR (IO_TYPECAST_BYTE 0xb00001eb)
+#define R_DMA_CH8_SUB2_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH8_SUB2_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH8_SUB2_CLR_INTR__clr_descr__dont 0
+#define R_DMA_CH8_SUB2_CLR_INTR__clr_descr__do 1
+
+#define R_DMA_CH8_SUB3_EP (IO_TYPECAST_UDWORD 0xb00001fc)
+#define R_DMA_CH8_SUB3_EP__ep__BITNR 0
+#define R_DMA_CH8_SUB3_EP__ep__WIDTH 32
+
+#define R_DMA_CH8_SUB3_CMD (IO_TYPECAST_BYTE 0xb00001df)
+#define R_DMA_CH8_SUB3_CMD__cmd__BITNR 0
+#define R_DMA_CH8_SUB3_CMD__cmd__WIDTH 1
+#define R_DMA_CH8_SUB3_CMD__cmd__stop 0
+#define R_DMA_CH8_SUB3_CMD__cmd__start 1
+
+#define R_DMA_CH8_SUB3_CLR_INTR (IO_TYPECAST_BYTE 0xb00001ef)
+#define R_DMA_CH8_SUB3_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH8_SUB3_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH8_SUB3_CLR_INTR__clr_descr__dont 0
+#define R_DMA_CH8_SUB3_CLR_INTR__clr_descr__do 1
+
+#define R_DMA_CH9_HWSW (IO_TYPECAST_UDWORD 0xb0000190)
+#define R_DMA_CH9_HWSW__hw__BITNR 16
+#define R_DMA_CH9_HWSW__hw__WIDTH 16
+#define R_DMA_CH9_HWSW__sw__BITNR 0
+#define R_DMA_CH9_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH9_DESCR (IO_TYPECAST_UDWORD 0xb000019c)
+#define R_DMA_CH9_DESCR__descr__BITNR 0
+#define R_DMA_CH9_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH9_NEXT (IO_TYPECAST_UDWORD 0xb0000194)
+#define R_DMA_CH9_NEXT__next__BITNR 0
+#define R_DMA_CH9_NEXT__next__WIDTH 32
+
+#define R_DMA_CH9_BUF (IO_TYPECAST_UDWORD 0xb0000198)
+#define R_DMA_CH9_BUF__buf__BITNR 0
+#define R_DMA_CH9_BUF__buf__WIDTH 32
+
+#define R_DMA_CH9_FIRST (IO_TYPECAST_UDWORD 0xb00001c4)
+#define R_DMA_CH9_FIRST__first__BITNR 0
+#define R_DMA_CH9_FIRST__first__WIDTH 32
+
+#define R_DMA_CH9_CMD (IO_TYPECAST_BYTE 0xb00001f4)
+#define R_DMA_CH9_CMD__cmd__BITNR 0
+#define R_DMA_CH9_CMD__cmd__WIDTH 3
+#define R_DMA_CH9_CMD__cmd__hold 0
+#define R_DMA_CH9_CMD__cmd__start 1
+#define R_DMA_CH9_CMD__cmd__restart 3
+#define R_DMA_CH9_CMD__cmd__continue 3
+#define R_DMA_CH9_CMD__cmd__reset 4
+
+#define R_DMA_CH9_CLR_INTR (IO_TYPECAST_BYTE 0xb00001f5)
+#define R_DMA_CH9_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH9_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH9_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH9_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH9_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH9_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH9_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH9_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH9_STATUS (IO_TYPECAST_RO_BYTE 0xb00001f6)
+#define R_DMA_CH9_STATUS__avail__BITNR 0
+#define R_DMA_CH9_STATUS__avail__WIDTH 7
+
+/*
+!* Test mode registers
+!*/
+
+#define R_TEST_MODE (IO_TYPECAST_UDWORD 0xb00000fc)
+#define R_TEST_MODE__single_step__BITNR 19
+#define R_TEST_MODE__single_step__WIDTH 1
+#define R_TEST_MODE__single_step__on 1
+#define R_TEST_MODE__single_step__off 0
+#define R_TEST_MODE__step_wr__BITNR 18
+#define R_TEST_MODE__step_wr__WIDTH 1
+#define R_TEST_MODE__step_wr__on 1
+#define R_TEST_MODE__step_wr__off 0
+#define R_TEST_MODE__step_rd__BITNR 17
+#define R_TEST_MODE__step_rd__WIDTH 1
+#define R_TEST_MODE__step_rd__on 1
+#define R_TEST_MODE__step_rd__off 0
+#define R_TEST_MODE__step_fetch__BITNR 16
+#define R_TEST_MODE__step_fetch__WIDTH 1
+#define R_TEST_MODE__step_fetch__on 1
+#define R_TEST_MODE__step_fetch__off 0
+#define R_TEST_MODE__mmu_test__BITNR 12
+#define R_TEST_MODE__mmu_test__WIDTH 1
+#define R_TEST_MODE__mmu_test__on 1
+#define R_TEST_MODE__mmu_test__off 0
+#define R_TEST_MODE__usb_test__BITNR 11
+#define R_TEST_MODE__usb_test__WIDTH 1
+#define R_TEST_MODE__usb_test__on 1
+#define R_TEST_MODE__usb_test__off 0
+#define R_TEST_MODE__scsi_timer_test__BITNR 10
+#define R_TEST_MODE__scsi_timer_test__WIDTH 1
+#define R_TEST_MODE__scsi_timer_test__on 1
+#define R_TEST_MODE__scsi_timer_test__off 0
+#define R_TEST_MODE__backoff__BITNR 9
+#define R_TEST_MODE__backoff__WIDTH 1
+#define R_TEST_MODE__backoff__on 1
+#define R_TEST_MODE__backoff__off 0
+#define R_TEST_MODE__snmp_test__BITNR 8
+#define R_TEST_MODE__snmp_test__WIDTH 1
+#define R_TEST_MODE__snmp_test__on 1
+#define R_TEST_MODE__snmp_test__off 0
+#define R_TEST_MODE__snmp_inc__BITNR 7
+#define R_TEST_MODE__snmp_inc__WIDTH 1
+#define R_TEST_MODE__snmp_inc__do 1
+#define R_TEST_MODE__snmp_inc__dont 0
+#define R_TEST_MODE__ser_loop__BITNR 6
+#define R_TEST_MODE__ser_loop__WIDTH 1
+#define R_TEST_MODE__ser_loop__on 1
+#define R_TEST_MODE__ser_loop__off 0
+#define R_TEST_MODE__baudrate__BITNR 5
+#define R_TEST_MODE__baudrate__WIDTH 1
+#define R_TEST_MODE__baudrate__on 1
+#define R_TEST_MODE__baudrate__off 0
+#define R_TEST_MODE__timer__BITNR 3
+#define R_TEST_MODE__timer__WIDTH 2
+#define R_TEST_MODE__timer__off 0
+#define R_TEST_MODE__timer__even 1
+#define R_TEST_MODE__timer__odd 2
+#define R_TEST_MODE__timer__all 3
+#define R_TEST_MODE__cache_test__BITNR 2
+#define R_TEST_MODE__cache_test__WIDTH 1
+#define R_TEST_MODE__cache_test__normal 0
+#define R_TEST_MODE__cache_test__test 1
+#define R_TEST_MODE__tag_test__BITNR 1
+#define R_TEST_MODE__tag_test__WIDTH 1
+#define R_TEST_MODE__tag_test__normal 0
+#define R_TEST_MODE__tag_test__test 1
+#define R_TEST_MODE__cache_enable__BITNR 0
+#define R_TEST_MODE__cache_enable__WIDTH 1
+#define R_TEST_MODE__cache_enable__enable 1
+#define R_TEST_MODE__cache_enable__disable 0
+
+#define R_SINGLE_STEP (IO_TYPECAST_BYTE 0xb00000fe)
+#define R_SINGLE_STEP__single_step__BITNR 3
+#define R_SINGLE_STEP__single_step__WIDTH 1
+#define R_SINGLE_STEP__single_step__on 1
+#define R_SINGLE_STEP__single_step__off 0
+#define R_SINGLE_STEP__step_wr__BITNR 2
+#define R_SINGLE_STEP__step_wr__WIDTH 1
+#define R_SINGLE_STEP__step_wr__on 1
+#define R_SINGLE_STEP__step_wr__off 0
+#define R_SINGLE_STEP__step_rd__BITNR 1
+#define R_SINGLE_STEP__step_rd__WIDTH 1
+#define R_SINGLE_STEP__step_rd__on 1
+#define R_SINGLE_STEP__step_rd__off 0
+#define R_SINGLE_STEP__step_fetch__BITNR 0
+#define R_SINGLE_STEP__step_fetch__WIDTH 1
+#define R_SINGLE_STEP__step_fetch__on 1
+#define R_SINGLE_STEP__step_fetch__off 0
+
+/*
+!* USB interface control registers
+!*/
+
+#define R_USB_REVISION (IO_TYPECAST_RO_BYTE 0xb0000200)
+#define R_USB_REVISION__major__BITNR 4
+#define R_USB_REVISION__major__WIDTH 4
+#define R_USB_REVISION__minor__BITNR 0
+#define R_USB_REVISION__minor__WIDTH 4
+
+#define R_USB_COMMAND (IO_TYPECAST_BYTE 0xb0000201)
+#define R_USB_COMMAND__port_sel__BITNR 6
+#define R_USB_COMMAND__port_sel__WIDTH 2
+#define R_USB_COMMAND__port_sel__nop 0
+#define R_USB_COMMAND__port_sel__port1 1
+#define R_USB_COMMAND__port_sel__port2 2
+#define R_USB_COMMAND__port_sel__both 3
+#define R_USB_COMMAND__port_cmd__BITNR 4
+#define R_USB_COMMAND__port_cmd__WIDTH 2
+#define R_USB_COMMAND__port_cmd__reset 0
+#define R_USB_COMMAND__port_cmd__disable 1
+#define R_USB_COMMAND__port_cmd__suspend 2
+#define R_USB_COMMAND__port_cmd__resume 3
+#define R_USB_COMMAND__busy__BITNR 3
+#define R_USB_COMMAND__busy__WIDTH 1
+#define R_USB_COMMAND__busy__no 0
+#define R_USB_COMMAND__busy__yes 1
+#define R_USB_COMMAND__ctrl_cmd__BITNR 0
+#define R_USB_COMMAND__ctrl_cmd__WIDTH 3
+#define R_USB_COMMAND__ctrl_cmd__nop 0
+#define R_USB_COMMAND__ctrl_cmd__reset 1
+#define R_USB_COMMAND__ctrl_cmd__deconfig 2
+#define R_USB_COMMAND__ctrl_cmd__host_config 3
+#define R_USB_COMMAND__ctrl_cmd__dev_config 4
+#define R_USB_COMMAND__ctrl_cmd__host_nop 5
+#define R_USB_COMMAND__ctrl_cmd__host_run 6
+#define R_USB_COMMAND__ctrl_cmd__host_stop 7
+
+#define R_USB_COMMAND_DEV (IO_TYPECAST_BYTE 0xb0000201)
+#define R_USB_COMMAND_DEV__port_sel__BITNR 6
+#define R_USB_COMMAND_DEV__port_sel__WIDTH 2
+#define R_USB_COMMAND_DEV__port_sel__nop 0
+#define R_USB_COMMAND_DEV__port_sel__dummy1 1
+#define R_USB_COMMAND_DEV__port_sel__dummy2 2
+#define R_USB_COMMAND_DEV__port_sel__any 3
+#define R_USB_COMMAND_DEV__port_cmd__BITNR 4
+#define R_USB_COMMAND_DEV__port_cmd__WIDTH 2
+#define R_USB_COMMAND_DEV__port_cmd__active 0
+#define R_USB_COMMAND_DEV__port_cmd__passive 1
+#define R_USB_COMMAND_DEV__port_cmd__nop 2
+#define R_USB_COMMAND_DEV__port_cmd__wakeup 3
+#define R_USB_COMMAND_DEV__busy__BITNR 3
+#define R_USB_COMMAND_DEV__busy__WIDTH 1
+#define R_USB_COMMAND_DEV__busy__no 0
+#define R_USB_COMMAND_DEV__busy__yes 1
+#define R_USB_COMMAND_DEV__ctrl_cmd__BITNR 0
+#define R_USB_COMMAND_DEV__ctrl_cmd__WIDTH 3
+#define R_USB_COMMAND_DEV__ctrl_cmd__nop 0
+#define R_USB_COMMAND_DEV__ctrl_cmd__reset 1
+#define R_USB_COMMAND_DEV__ctrl_cmd__deconfig 2
+#define R_USB_COMMAND_DEV__ctrl_cmd__host_config 3
+#define R_USB_COMMAND_DEV__ctrl_cmd__dev_config 4
+#define R_USB_COMMAND_DEV__ctrl_cmd__dev_active 5
+#define R_USB_COMMAND_DEV__ctrl_cmd__dev_passive 6
+#define R_USB_COMMAND_DEV__ctrl_cmd__dev_nop 7
+
+#define R_USB_STATUS (IO_TYPECAST_RO_BYTE 0xb0000202)
+#define R_USB_STATUS__ourun__BITNR 5
+#define R_USB_STATUS__ourun__WIDTH 1
+#define R_USB_STATUS__ourun__no 0
+#define R_USB_STATUS__ourun__yes 1
+#define R_USB_STATUS__perror__BITNR 4
+#define R_USB_STATUS__perror__WIDTH 1
+#define R_USB_STATUS__perror__no 0
+#define R_USB_STATUS__perror__yes 1
+#define R_USB_STATUS__device_mode__BITNR 3
+#define R_USB_STATUS__device_mode__WIDTH 1
+#define R_USB_STATUS__device_mode__no 0
+#define R_USB_STATUS__device_mode__yes 1
+#define R_USB_STATUS__host_mode__BITNR 2
+#define R_USB_STATUS__host_mode__WIDTH 1
+#define R_USB_STATUS__host_mode__no 0
+#define R_USB_STATUS__host_mode__yes 1
+#define R_USB_STATUS__started__BITNR 1
+#define R_USB_STATUS__started__WIDTH 1
+#define R_USB_STATUS__started__no 0
+#define R_USB_STATUS__started__yes 1
+#define R_USB_STATUS__running__BITNR 0
+#define R_USB_STATUS__running__WIDTH 1
+#define R_USB_STATUS__running__no 0
+#define R_USB_STATUS__running__yes 1
+
+#define R_USB_IRQ_MASK_SET (IO_TYPECAST_UWORD 0xb0000204)
+#define R_USB_IRQ_MASK_SET__iso_eof__BITNR 13
+#define R_USB_IRQ_MASK_SET__iso_eof__WIDTH 1
+#define R_USB_IRQ_MASK_SET__iso_eof__nop 0
+#define R_USB_IRQ_MASK_SET__iso_eof__set 1
+#define R_USB_IRQ_MASK_SET__intr_eof__BITNR 12
+#define R_USB_IRQ_MASK_SET__intr_eof__WIDTH 1
+#define R_USB_IRQ_MASK_SET__intr_eof__nop 0
+#define R_USB_IRQ_MASK_SET__intr_eof__set 1
+#define R_USB_IRQ_MASK_SET__iso_eot__BITNR 11
+#define R_USB_IRQ_MASK_SET__iso_eot__WIDTH 1
+#define R_USB_IRQ_MASK_SET__iso_eot__nop 0
+#define R_USB_IRQ_MASK_SET__iso_eot__set 1
+#define R_USB_IRQ_MASK_SET__intr_eot__BITNR 10
+#define R_USB_IRQ_MASK_SET__intr_eot__WIDTH 1
+#define R_USB_IRQ_MASK_SET__intr_eot__nop 0
+#define R_USB_IRQ_MASK_SET__intr_eot__set 1
+#define R_USB_IRQ_MASK_SET__ctl_eot__BITNR 9
+#define R_USB_IRQ_MASK_SET__ctl_eot__WIDTH 1
+#define R_USB_IRQ_MASK_SET__ctl_eot__nop 0
+#define R_USB_IRQ_MASK_SET__ctl_eot__set 1
+#define R_USB_IRQ_MASK_SET__bulk_eot__BITNR 8
+#define R_USB_IRQ_MASK_SET__bulk_eot__WIDTH 1
+#define R_USB_IRQ_MASK_SET__bulk_eot__nop 0
+#define R_USB_IRQ_MASK_SET__bulk_eot__set 1
+#define R_USB_IRQ_MASK_SET__epid_attn__BITNR 3
+#define R_USB_IRQ_MASK_SET__epid_attn__WIDTH 1
+#define R_USB_IRQ_MASK_SET__epid_attn__nop 0
+#define R_USB_IRQ_MASK_SET__epid_attn__set 1
+#define R_USB_IRQ_MASK_SET__sof__BITNR 2
+#define R_USB_IRQ_MASK_SET__sof__WIDTH 1
+#define R_USB_IRQ_MASK_SET__sof__nop 0
+#define R_USB_IRQ_MASK_SET__sof__set 1
+#define R_USB_IRQ_MASK_SET__port_status__BITNR 1
+#define R_USB_IRQ_MASK_SET__port_status__WIDTH 1
+#define R_USB_IRQ_MASK_SET__port_status__nop 0
+#define R_USB_IRQ_MASK_SET__port_status__set 1
+#define R_USB_IRQ_MASK_SET__ctl_status__BITNR 0
+#define R_USB_IRQ_MASK_SET__ctl_status__WIDTH 1
+#define R_USB_IRQ_MASK_SET__ctl_status__nop 0
+#define R_USB_IRQ_MASK_SET__ctl_status__set 1
+
+#define R_USB_IRQ_MASK_READ (IO_TYPECAST_RO_UWORD 0xb0000204)
+#define R_USB_IRQ_MASK_READ__iso_eof__BITNR 13
+#define R_USB_IRQ_MASK_READ__iso_eof__WIDTH 1
+#define R_USB_IRQ_MASK_READ__iso_eof__no_pend 0
+#define R_USB_IRQ_MASK_READ__iso_eof__pend 1
+#define R_USB_IRQ_MASK_READ__intr_eof__BITNR 12
+#define R_USB_IRQ_MASK_READ__intr_eof__WIDTH 1
+#define R_USB_IRQ_MASK_READ__intr_eof__no_pend 0
+#define R_USB_IRQ_MASK_READ__intr_eof__pend 1
+#define R_USB_IRQ_MASK_READ__iso_eot__BITNR 11
+#define R_USB_IRQ_MASK_READ__iso_eot__WIDTH 1
+#define R_USB_IRQ_MASK_READ__iso_eot__no_pend 0
+#define R_USB_IRQ_MASK_READ__iso_eot__pend 1
+#define R_USB_IRQ_MASK_READ__intr_eot__BITNR 10
+#define R_USB_IRQ_MASK_READ__intr_eot__WIDTH 1
+#define R_USB_IRQ_MASK_READ__intr_eot__no_pend 0
+#define R_USB_IRQ_MASK_READ__intr_eot__pend 1
+#define R_USB_IRQ_MASK_READ__ctl_eot__BITNR 9
+#define R_USB_IRQ_MASK_READ__ctl_eot__WIDTH 1
+#define R_USB_IRQ_MASK_READ__ctl_eot__no_pend 0
+#define R_USB_IRQ_MASK_READ__ctl_eot__pend 1
+#define R_USB_IRQ_MASK_READ__bulk_eot__BITNR 8
+#define R_USB_IRQ_MASK_READ__bulk_eot__WIDTH 1
+#define R_USB_IRQ_MASK_READ__bulk_eot__no_pend 0
+#define R_USB_IRQ_MASK_READ__bulk_eot__pend 1
+#define R_USB_IRQ_MASK_READ__epid_attn__BITNR 3
+#define R_USB_IRQ_MASK_READ__epid_attn__WIDTH 1
+#define R_USB_IRQ_MASK_READ__epid_attn__no_pend 0
+#define R_USB_IRQ_MASK_READ__epid_attn__pend 1
+#define R_USB_IRQ_MASK_READ__sof__BITNR 2
+#define R_USB_IRQ_MASK_READ__sof__WIDTH 1
+#define R_USB_IRQ_MASK_READ__sof__no_pend 0
+#define R_USB_IRQ_MASK_READ__sof__pend 1
+#define R_USB_IRQ_MASK_READ__port_status__BITNR 1
+#define R_USB_IRQ_MASK_READ__port_status__WIDTH 1
+#define R_USB_IRQ_MASK_READ__port_status__no_pend 0
+#define R_USB_IRQ_MASK_READ__port_status__pend 1
+#define R_USB_IRQ_MASK_READ__ctl_status__BITNR 0
+#define R_USB_IRQ_MASK_READ__ctl_status__WIDTH 1
+#define R_USB_IRQ_MASK_READ__ctl_status__no_pend 0
+#define R_USB_IRQ_MASK_READ__ctl_status__pend 1
+
+#define R_USB_IRQ_MASK_CLR (IO_TYPECAST_UWORD 0xb0000206)
+#define R_USB_IRQ_MASK_CLR__iso_eof__BITNR 13
+#define R_USB_IRQ_MASK_CLR__iso_eof__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__iso_eof__nop 0
+#define R_USB_IRQ_MASK_CLR__iso_eof__clr 1
+#define R_USB_IRQ_MASK_CLR__intr_eof__BITNR 12
+#define R_USB_IRQ_MASK_CLR__intr_eof__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__intr_eof__nop 0
+#define R_USB_IRQ_MASK_CLR__intr_eof__clr 1
+#define R_USB_IRQ_MASK_CLR__iso_eot__BITNR 11
+#define R_USB_IRQ_MASK_CLR__iso_eot__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__iso_eot__nop 0
+#define R_USB_IRQ_MASK_CLR__iso_eot__clr 1
+#define R_USB_IRQ_MASK_CLR__intr_eot__BITNR 10
+#define R_USB_IRQ_MASK_CLR__intr_eot__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__intr_eot__nop 0
+#define R_USB_IRQ_MASK_CLR__intr_eot__clr 1
+#define R_USB_IRQ_MASK_CLR__ctl_eot__BITNR 9
+#define R_USB_IRQ_MASK_CLR__ctl_eot__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__ctl_eot__nop 0
+#define R_USB_IRQ_MASK_CLR__ctl_eot__clr 1
+#define R_USB_IRQ_MASK_CLR__bulk_eot__BITNR 8
+#define R_USB_IRQ_MASK_CLR__bulk_eot__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__bulk_eot__nop 0
+#define R_USB_IRQ_MASK_CLR__bulk_eot__clr 1
+#define R_USB_IRQ_MASK_CLR__epid_attn__BITNR 3
+#define R_USB_IRQ_MASK_CLR__epid_attn__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__epid_attn__nop 0
+#define R_USB_IRQ_MASK_CLR__epid_attn__clr 1
+#define R_USB_IRQ_MASK_CLR__sof__BITNR 2
+#define R_USB_IRQ_MASK_CLR__sof__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__sof__nop 0
+#define R_USB_IRQ_MASK_CLR__sof__clr 1
+#define R_USB_IRQ_MASK_CLR__port_status__BITNR 1
+#define R_USB_IRQ_MASK_CLR__port_status__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__port_status__nop 0
+#define R_USB_IRQ_MASK_CLR__port_status__clr 1
+#define R_USB_IRQ_MASK_CLR__ctl_status__BITNR 0
+#define R_USB_IRQ_MASK_CLR__ctl_status__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__ctl_status__nop 0
+#define R_USB_IRQ_MASK_CLR__ctl_status__clr 1
+
+#define R_USB_IRQ_READ (IO_TYPECAST_RO_UWORD 0xb0000206)
+#define R_USB_IRQ_READ__iso_eof__BITNR 13
+#define R_USB_IRQ_READ__iso_eof__WIDTH 1
+#define R_USB_IRQ_READ__iso_eof__no_pend 0
+#define R_USB_IRQ_READ__iso_eof__pend 1
+#define R_USB_IRQ_READ__intr_eof__BITNR 12
+#define R_USB_IRQ_READ__intr_eof__WIDTH 1
+#define R_USB_IRQ_READ__intr_eof__no_pend 0
+#define R_USB_IRQ_READ__intr_eof__pend 1
+#define R_USB_IRQ_READ__iso_eot__BITNR 11
+#define R_USB_IRQ_READ__iso_eot__WIDTH 1
+#define R_USB_IRQ_READ__iso_eot__no_pend 0
+#define R_USB_IRQ_READ__iso_eot__pend 1
+#define R_USB_IRQ_READ__intr_eot__BITNR 10
+#define R_USB_IRQ_READ__intr_eot__WIDTH 1
+#define R_USB_IRQ_READ__intr_eot__no_pend 0
+#define R_USB_IRQ_READ__intr_eot__pend 1
+#define R_USB_IRQ_READ__ctl_eot__BITNR 9
+#define R_USB_IRQ_READ__ctl_eot__WIDTH 1
+#define R_USB_IRQ_READ__ctl_eot__no_pend 0
+#define R_USB_IRQ_READ__ctl_eot__pend 1
+#define R_USB_IRQ_READ__bulk_eot__BITNR 8
+#define R_USB_IRQ_READ__bulk_eot__WIDTH 1
+#define R_USB_IRQ_READ__bulk_eot__no_pend 0
+#define R_USB_IRQ_READ__bulk_eot__pend 1
+#define R_USB_IRQ_READ__epid_attn__BITNR 3
+#define R_USB_IRQ_READ__epid_attn__WIDTH 1
+#define R_USB_IRQ_READ__epid_attn__no_pend 0
+#define R_USB_IRQ_READ__epid_attn__pend 1
+#define R_USB_IRQ_READ__sof__BITNR 2
+#define R_USB_IRQ_READ__sof__WIDTH 1
+#define R_USB_IRQ_READ__sof__no_pend 0
+#define R_USB_IRQ_READ__sof__pend 1
+#define R_USB_IRQ_READ__port_status__BITNR 1
+#define R_USB_IRQ_READ__port_status__WIDTH 1
+#define R_USB_IRQ_READ__port_status__no_pend 0
+#define R_USB_IRQ_READ__port_status__pend 1
+#define R_USB_IRQ_READ__ctl_status__BITNR 0
+#define R_USB_IRQ_READ__ctl_status__WIDTH 1
+#define R_USB_IRQ_READ__ctl_status__no_pend 0
+#define R_USB_IRQ_READ__ctl_status__pend 1
+
+#define R_USB_IRQ_MASK_SET_DEV (IO_TYPECAST_UWORD 0xb0000204)
+#define R_USB_IRQ_MASK_SET_DEV__out_eot__BITNR 12
+#define R_USB_IRQ_MASK_SET_DEV__out_eot__WIDTH 1
+#define R_USB_IRQ_MASK_SET_DEV__out_eot__nop 0
+#define R_USB_IRQ_MASK_SET_DEV__out_eot__set 1
+#define R_USB_IRQ_MASK_SET_DEV__ep3_in_eot__BITNR 11
+#define R_USB_IRQ_MASK_SET_DEV__ep3_in_eot__WIDTH 1
+#define R_USB_IRQ_MASK_SET_DEV__ep3_in_eot__nop 0
+#define R_USB_IRQ_MASK_SET_DEV__ep3_in_eot__set 1
+#define R_USB_IRQ_MASK_SET_DEV__ep2_in_eot__BITNR 10
+#define R_USB_IRQ_MASK_SET_DEV__ep2_in_eot__WIDTH 1
+#define R_USB_IRQ_MASK_SET_DEV__ep2_in_eot__nop 0
+#define R_USB_IRQ_MASK_SET_DEV__ep2_in_eot__set 1
+#define R_USB_IRQ_MASK_SET_DEV__ep1_in_eot__BITNR 9
+#define R_USB_IRQ_MASK_SET_DEV__ep1_in_eot__WIDTH 1
+#define R_USB_IRQ_MASK_SET_DEV__ep1_in_eot__nop 0
+#define R_USB_IRQ_MASK_SET_DEV__ep1_in_eot__set 1
+#define R_USB_IRQ_MASK_SET_DEV__ep0_in_eot__BITNR 8
+#define R_USB_IRQ_MASK_SET_DEV__ep0_in_eot__WIDTH 1
+#define R_USB_IRQ_MASK_SET_DEV__ep0_in_eot__nop 0
+#define R_USB_IRQ_MASK_SET_DEV__ep0_in_eot__set 1
+#define R_USB_IRQ_MASK_SET_DEV__epid_attn__BITNR 3
+#define R_USB_IRQ_MASK_SET_DEV__epid_attn__WIDTH 1
+#define R_USB_IRQ_MASK_SET_DEV__epid_attn__nop 0
+#define R_USB_IRQ_MASK_SET_DEV__epid_attn__set 1
+#define R_USB_IRQ_MASK_SET_DEV__sof__BITNR 2
+#define R_USB_IRQ_MASK_SET_DEV__sof__WIDTH 1
+#define R_USB_IRQ_MASK_SET_DEV__sof__nop 0
+#define R_USB_IRQ_MASK_SET_DEV__sof__set 1
+#define R_USB_IRQ_MASK_SET_DEV__port_status__BITNR 1
+#define R_USB_IRQ_MASK_SET_DEV__port_status__WIDTH 1
+#define R_USB_IRQ_MASK_SET_DEV__port_status__nop 0
+#define R_USB_IRQ_MASK_SET_DEV__port_status__set 1
+#define R_USB_IRQ_MASK_SET_DEV__ctl_status__BITNR 0
+#define R_USB_IRQ_MASK_SET_DEV__ctl_status__WIDTH 1
+#define R_USB_IRQ_MASK_SET_DEV__ctl_status__nop 0
+#define R_USB_IRQ_MASK_SET_DEV__ctl_status__set 1
+
+#define R_USB_IRQ_MASK_READ_DEV (IO_TYPECAST_RO_UWORD 0xb0000204)
+#define R_USB_IRQ_MASK_READ_DEV__out_eot__BITNR 12
+#define R_USB_IRQ_MASK_READ_DEV__out_eot__WIDTH 1
+#define R_USB_IRQ_MASK_READ_DEV__out_eot__no_pend 0
+#define R_USB_IRQ_MASK_READ_DEV__out_eot__pend 1
+#define R_USB_IRQ_MASK_READ_DEV__ep3_in_eot__BITNR 11
+#define R_USB_IRQ_MASK_READ_DEV__ep3_in_eot__WIDTH 1
+#define R_USB_IRQ_MASK_READ_DEV__ep3_in_eot__no_pend 0
+#define R_USB_IRQ_MASK_READ_DEV__ep3_in_eot__pend 1
+#define R_USB_IRQ_MASK_READ_DEV__ep2_in_eot__BITNR 10
+#define R_USB_IRQ_MASK_READ_DEV__ep2_in_eot__WIDTH 1
+#define R_USB_IRQ_MASK_READ_DEV__ep2_in_eot__no_pend 0
+#define R_USB_IRQ_MASK_READ_DEV__ep2_in_eot__pend 1
+#define R_USB_IRQ_MASK_READ_DEV__ep1_in_eot__BITNR 9
+#define R_USB_IRQ_MASK_READ_DEV__ep1_in_eot__WIDTH 1
+#define R_USB_IRQ_MASK_READ_DEV__ep1_in_eot__no_pend 0
+#define R_USB_IRQ_MASK_READ_DEV__ep1_in_eot__pend 1
+#define R_USB_IRQ_MASK_READ_DEV__ep0_in_eot__BITNR 8
+#define R_USB_IRQ_MASK_READ_DEV__ep0_in_eot__WIDTH 1
+#define R_USB_IRQ_MASK_READ_DEV__ep0_in_eot__no_pend 0
+#define R_USB_IRQ_MASK_READ_DEV__ep0_in_eot__pend 1
+#define R_USB_IRQ_MASK_READ_DEV__epid_attn__BITNR 3
+#define R_USB_IRQ_MASK_READ_DEV__epid_attn__WIDTH 1
+#define R_USB_IRQ_MASK_READ_DEV__epid_attn__no_pend 0
+#define R_USB_IRQ_MASK_READ_DEV__epid_attn__pend 1
+#define R_USB_IRQ_MASK_READ_DEV__sof__BITNR 2
+#define R_USB_IRQ_MASK_READ_DEV__sof__WIDTH 1
+#define R_USB_IRQ_MASK_READ_DEV__sof__no_pend 0
+#define R_USB_IRQ_MASK_READ_DEV__sof__pend 1
+#define R_USB_IRQ_MASK_READ_DEV__port_status__BITNR 1
+#define R_USB_IRQ_MASK_READ_DEV__port_status__WIDTH 1
+#define R_USB_IRQ_MASK_READ_DEV__port_status__no_pend 0
+#define R_USB_IRQ_MASK_READ_DEV__port_status__pend 1
+#define R_USB_IRQ_MASK_READ_DEV__ctl_status__BITNR 0
+#define R_USB_IRQ_MASK_READ_DEV__ctl_status__WIDTH 1
+#define R_USB_IRQ_MASK_READ_DEV__ctl_status__no_pend 0
+#define R_USB_IRQ_MASK_READ_DEV__ctl_status__pend 1
+
+#define R_USB_IRQ_MASK_CLR_DEV (IO_TYPECAST_UWORD 0xb0000206)
+#define R_USB_IRQ_MASK_CLR_DEV__out_eot__BITNR 12
+#define R_USB_IRQ_MASK_CLR_DEV__out_eot__WIDTH 1
+#define R_USB_IRQ_MASK_CLR_DEV__out_eot__nop 0
+#define R_USB_IRQ_MASK_CLR_DEV__out_eot__clr 1
+#define R_USB_IRQ_MASK_CLR_DEV__ep3_in_eot__BITNR 11
+#define R_USB_IRQ_MASK_CLR_DEV__ep3_in_eot__WIDTH 1
+#define R_USB_IRQ_MASK_CLR_DEV__ep3_in_eot__nop 0
+#define R_USB_IRQ_MASK_CLR_DEV__ep3_in_eot__clr 1
+#define R_USB_IRQ_MASK_CLR_DEV__ep2_in_eot__BITNR 10
+#define R_USB_IRQ_MASK_CLR_DEV__ep2_in_eot__WIDTH 1
+#define R_USB_IRQ_MASK_CLR_DEV__ep2_in_eot__nop 0
+#define R_USB_IRQ_MASK_CLR_DEV__ep2_in_eot__clr 1
+#define R_USB_IRQ_MASK_CLR_DEV__ep1_in_eot__BITNR 9
+#define R_USB_IRQ_MASK_CLR_DEV__ep1_in_eot__WIDTH 1
+#define R_USB_IRQ_MASK_CLR_DEV__ep1_in_eot__nop 0
+#define R_USB_IRQ_MASK_CLR_DEV__ep1_in_eot__clr 1
+#define R_USB_IRQ_MASK_CLR_DEV__ep0_in_eot__BITNR 8
+#define R_USB_IRQ_MASK_CLR_DEV__ep0_in_eot__WIDTH 1
+#define R_USB_IRQ_MASK_CLR_DEV__ep0_in_eot__nop 0
+#define R_USB_IRQ_MASK_CLR_DEV__ep0_in_eot__clr 1
+#define R_USB_IRQ_MASK_CLR_DEV__epid_attn__BITNR 3
+#define R_USB_IRQ_MASK_CLR_DEV__epid_attn__WIDTH 1
+#define R_USB_IRQ_MASK_CLR_DEV__epid_attn__nop 0
+#define R_USB_IRQ_MASK_CLR_DEV__epid_attn__clr 1
+#define R_USB_IRQ_MASK_CLR_DEV__sof__BITNR 2
+#define R_USB_IRQ_MASK_CLR_DEV__sof__WIDTH 1
+#define R_USB_IRQ_MASK_CLR_DEV__sof__nop 0
+#define R_USB_IRQ_MASK_CLR_DEV__sof__clr 1
+#define R_USB_IRQ_MASK_CLR_DEV__port_status__BITNR 1
+#define R_USB_IRQ_MASK_CLR_DEV__port_status__WIDTH 1
+#define R_USB_IRQ_MASK_CLR_DEV__port_status__nop 0
+#define R_USB_IRQ_MASK_CLR_DEV__port_status__clr 1
+#define R_USB_IRQ_MASK_CLR_DEV__ctl_status__BITNR 0
+#define R_USB_IRQ_MASK_CLR_DEV__ctl_status__WIDTH 1
+#define R_USB_IRQ_MASK_CLR_DEV__ctl_status__nop 0
+#define R_USB_IRQ_MASK_CLR_DEV__ctl_status__clr 1
+
+#define R_USB_IRQ_READ_DEV (IO_TYPECAST_RO_UWORD 0xb0000206)
+#define R_USB_IRQ_READ_DEV__out_eot__BITNR 12
+#define R_USB_IRQ_READ_DEV__out_eot__WIDTH 1
+#define R_USB_IRQ_READ_DEV__out_eot__no_pend 0
+#define R_USB_IRQ_READ_DEV__out_eot__pend 1
+#define R_USB_IRQ_READ_DEV__ep3_in_eot__BITNR 11
+#define R_USB_IRQ_READ_DEV__ep3_in_eot__WIDTH 1
+#define R_USB_IRQ_READ_DEV__ep3_in_eot__no_pend 0
+#define R_USB_IRQ_READ_DEV__ep3_in_eot__pend 1
+#define R_USB_IRQ_READ_DEV__ep2_in_eot__BITNR 10
+#define R_USB_IRQ_READ_DEV__ep2_in_eot__WIDTH 1
+#define R_USB_IRQ_READ_DEV__ep2_in_eot__no_pend 0
+#define R_USB_IRQ_READ_DEV__ep2_in_eot__pend 1
+#define R_USB_IRQ_READ_DEV__ep1_in_eot__BITNR 9
+#define R_USB_IRQ_READ_DEV__ep1_in_eot__WIDTH 1
+#define R_USB_IRQ_READ_DEV__ep1_in_eot__no_pend 0
+#define R_USB_IRQ_READ_DEV__ep1_in_eot__pend 1
+#define R_USB_IRQ_READ_DEV__ep0_in_eot__BITNR 8
+#define R_USB_IRQ_READ_DEV__ep0_in_eot__WIDTH 1
+#define R_USB_IRQ_READ_DEV__ep0_in_eot__no_pend 0
+#define R_USB_IRQ_READ_DEV__ep0_in_eot__pend 1
+#define R_USB_IRQ_READ_DEV__epid_attn__BITNR 3
+#define R_USB_IRQ_READ_DEV__epid_attn__WIDTH 1
+#define R_USB_IRQ_READ_DEV__epid_attn__no_pend 0
+#define R_USB_IRQ_READ_DEV__epid_attn__pend 1
+#define R_USB_IRQ_READ_DEV__sof__BITNR 2
+#define R_USB_IRQ_READ_DEV__sof__WIDTH 1
+#define R_USB_IRQ_READ_DEV__sof__no_pend 0
+#define R_USB_IRQ_READ_DEV__sof__pend 1
+#define R_USB_IRQ_READ_DEV__port_status__BITNR 1
+#define R_USB_IRQ_READ_DEV__port_status__WIDTH 1
+#define R_USB_IRQ_READ_DEV__port_status__no_pend 0
+#define R_USB_IRQ_READ_DEV__port_status__pend 1
+#define R_USB_IRQ_READ_DEV__ctl_status__BITNR 0
+#define R_USB_IRQ_READ_DEV__ctl_status__WIDTH 1
+#define R_USB_IRQ_READ_DEV__ctl_status__no_pend 0
+#define R_USB_IRQ_READ_DEV__ctl_status__pend 1
+
+#define R_USB_FM_NUMBER (IO_TYPECAST_UDWORD 0xb000020c)
+#define R_USB_FM_NUMBER__value__BITNR 0
+#define R_USB_FM_NUMBER__value__WIDTH 32
+
+#define R_USB_FM_INTERVAL (IO_TYPECAST_UWORD 0xb0000210)
+#define R_USB_FM_INTERVAL__fixed__BITNR 6
+#define R_USB_FM_INTERVAL__fixed__WIDTH 8
+#define R_USB_FM_INTERVAL__adj__BITNR 0
+#define R_USB_FM_INTERVAL__adj__WIDTH 6
+
+#define R_USB_FM_REMAINING (IO_TYPECAST_RO_UWORD 0xb0000212)
+#define R_USB_FM_REMAINING__value__BITNR 0
+#define R_USB_FM_REMAINING__value__WIDTH 14
+
+#define R_USB_FM_PSTART (IO_TYPECAST_UWORD 0xb0000214)
+#define R_USB_FM_PSTART__value__BITNR 0
+#define R_USB_FM_PSTART__value__WIDTH 14
+
+#define R_USB_RH_STATUS (IO_TYPECAST_RO_BYTE 0xb0000203)
+#define R_USB_RH_STATUS__babble2__BITNR 7
+#define R_USB_RH_STATUS__babble2__WIDTH 1
+#define R_USB_RH_STATUS__babble2__no 0
+#define R_USB_RH_STATUS__babble2__yes 1
+#define R_USB_RH_STATUS__babble1__BITNR 6
+#define R_USB_RH_STATUS__babble1__WIDTH 1
+#define R_USB_RH_STATUS__babble1__no 0
+#define R_USB_RH_STATUS__babble1__yes 1
+#define R_USB_RH_STATUS__bus1__BITNR 4
+#define R_USB_RH_STATUS__bus1__WIDTH 2
+#define R_USB_RH_STATUS__bus1__SE0 0
+#define R_USB_RH_STATUS__bus1__Diff0 1
+#define R_USB_RH_STATUS__bus1__Diff1 2
+#define R_USB_RH_STATUS__bus1__SE1 3
+#define R_USB_RH_STATUS__bus2__BITNR 2
+#define R_USB_RH_STATUS__bus2__WIDTH 2
+#define R_USB_RH_STATUS__bus2__SE0 0
+#define R_USB_RH_STATUS__bus2__Diff0 1
+#define R_USB_RH_STATUS__bus2__Diff1 2
+#define R_USB_RH_STATUS__bus2__SE1 3
+#define R_USB_RH_STATUS__nports__BITNR 0
+#define R_USB_RH_STATUS__nports__WIDTH 2
+
+#define R_USB_RH_PORT_STATUS_1 (IO_TYPECAST_RO_UWORD 0xb0000218)
+#define R_USB_RH_PORT_STATUS_1__speed__BITNR 9
+#define R_USB_RH_PORT_STATUS_1__speed__WIDTH 1
+#define R_USB_RH_PORT_STATUS_1__speed__full 0
+#define R_USB_RH_PORT_STATUS_1__speed__low 1
+#define R_USB_RH_PORT_STATUS_1__power__BITNR 8
+#define R_USB_RH_PORT_STATUS_1__power__WIDTH 1
+#define R_USB_RH_PORT_STATUS_1__reset__BITNR 4
+#define R_USB_RH_PORT_STATUS_1__reset__WIDTH 1
+#define R_USB_RH_PORT_STATUS_1__reset__no 0
+#define R_USB_RH_PORT_STATUS_1__reset__yes 1
+#define R_USB_RH_PORT_STATUS_1__overcurrent__BITNR 3
+#define R_USB_RH_PORT_STATUS_1__overcurrent__WIDTH 1
+#define R_USB_RH_PORT_STATUS_1__overcurrent__no 0
+#define R_USB_RH_PORT_STATUS_1__overcurrent__yes 1
+#define R_USB_RH_PORT_STATUS_1__suspended__BITNR 2
+#define R_USB_RH_PORT_STATUS_1__suspended__WIDTH 1
+#define R_USB_RH_PORT_STATUS_1__suspended__no 0
+#define R_USB_RH_PORT_STATUS_1__suspended__yes 1
+#define R_USB_RH_PORT_STATUS_1__enabled__BITNR 1
+#define R_USB_RH_PORT_STATUS_1__enabled__WIDTH 1
+#define R_USB_RH_PORT_STATUS_1__enabled__no 0
+#define R_USB_RH_PORT_STATUS_1__enabled__yes 1
+#define R_USB_RH_PORT_STATUS_1__connected__BITNR 0
+#define R_USB_RH_PORT_STATUS_1__connected__WIDTH 1
+#define R_USB_RH_PORT_STATUS_1__connected__no 0
+#define R_USB_RH_PORT_STATUS_1__connected__yes 1
+
+#define R_USB_RH_PORT_STATUS_2 (IO_TYPECAST_RO_UWORD 0xb000021a)
+#define R_USB_RH_PORT_STATUS_2__speed__BITNR 9
+#define R_USB_RH_PORT_STATUS_2__speed__WIDTH 1
+#define R_USB_RH_PORT_STATUS_2__speed__full 0
+#define R_USB_RH_PORT_STATUS_2__speed__low 1
+#define R_USB_RH_PORT_STATUS_2__power__BITNR 8
+#define R_USB_RH_PORT_STATUS_2__power__WIDTH 1
+#define R_USB_RH_PORT_STATUS_2__reset__BITNR 4
+#define R_USB_RH_PORT_STATUS_2__reset__WIDTH 1
+#define R_USB_RH_PORT_STATUS_2__reset__no 0
+#define R_USB_RH_PORT_STATUS_2__reset__yes 1
+#define R_USB_RH_PORT_STATUS_2__overcurrent__BITNR 3
+#define R_USB_RH_PORT_STATUS_2__overcurrent__WIDTH 1
+#define R_USB_RH_PORT_STATUS_2__overcurrent__no 0
+#define R_USB_RH_PORT_STATUS_2__overcurrent__yes 1
+#define R_USB_RH_PORT_STATUS_2__suspended__BITNR 2
+#define R_USB_RH_PORT_STATUS_2__suspended__WIDTH 1
+#define R_USB_RH_PORT_STATUS_2__suspended__no 0
+#define R_USB_RH_PORT_STATUS_2__suspended__yes 1
+#define R_USB_RH_PORT_STATUS_2__enabled__BITNR 1
+#define R_USB_RH_PORT_STATUS_2__enabled__WIDTH 1
+#define R_USB_RH_PORT_STATUS_2__enabled__no 0
+#define R_USB_RH_PORT_STATUS_2__enabled__yes 1
+#define R_USB_RH_PORT_STATUS_2__connected__BITNR 0
+#define R_USB_RH_PORT_STATUS_2__connected__WIDTH 1
+#define R_USB_RH_PORT_STATUS_2__connected__no 0
+#define R_USB_RH_PORT_STATUS_2__connected__yes 1
+
+#define R_USB_EPT_INDEX (IO_TYPECAST_BYTE 0xb0000208)
+#define R_USB_EPT_INDEX__value__BITNR 0
+#define R_USB_EPT_INDEX__value__WIDTH 5
+
+#define R_USB_EPT_DATA (IO_TYPECAST_UDWORD 0xb000021c)
+#define R_USB_EPT_DATA__valid__BITNR 31
+#define R_USB_EPT_DATA__valid__WIDTH 1
+#define R_USB_EPT_DATA__valid__no 0
+#define R_USB_EPT_DATA__valid__yes 1
+#define R_USB_EPT_DATA__hold__BITNR 30
+#define R_USB_EPT_DATA__hold__WIDTH 1
+#define R_USB_EPT_DATA__hold__no 0
+#define R_USB_EPT_DATA__hold__yes 1
+#define R_USB_EPT_DATA__error_count_in__BITNR 28
+#define R_USB_EPT_DATA__error_count_in__WIDTH 2
+#define R_USB_EPT_DATA__t_in__BITNR 27
+#define R_USB_EPT_DATA__t_in__WIDTH 1
+#define R_USB_EPT_DATA__low_speed__BITNR 26
+#define R_USB_EPT_DATA__low_speed__WIDTH 1
+#define R_USB_EPT_DATA__low_speed__no 0
+#define R_USB_EPT_DATA__low_speed__yes 1
+#define R_USB_EPT_DATA__port__BITNR 24
+#define R_USB_EPT_DATA__port__WIDTH 2
+#define R_USB_EPT_DATA__port__any 0
+#define R_USB_EPT_DATA__port__p1 1
+#define R_USB_EPT_DATA__port__p2 2
+#define R_USB_EPT_DATA__port__undef 3
+#define R_USB_EPT_DATA__error_code__BITNR 22
+#define R_USB_EPT_DATA__error_code__WIDTH 2
+#define R_USB_EPT_DATA__error_code__no_error 0
+#define R_USB_EPT_DATA__error_code__stall 1
+#define R_USB_EPT_DATA__error_code__bus_error 2
+#define R_USB_EPT_DATA__error_code__buffer_error 3
+#define R_USB_EPT_DATA__t_out__BITNR 21
+#define R_USB_EPT_DATA__t_out__WIDTH 1
+#define R_USB_EPT_DATA__error_count_out__BITNR 19
+#define R_USB_EPT_DATA__error_count_out__WIDTH 2
+#define R_USB_EPT_DATA__max_len__BITNR 11
+#define R_USB_EPT_DATA__max_len__WIDTH 7
+#define R_USB_EPT_DATA__ep__BITNR 7
+#define R_USB_EPT_DATA__ep__WIDTH 4
+#define R_USB_EPT_DATA__dev__BITNR 0
+#define R_USB_EPT_DATA__dev__WIDTH 7
+
+#define R_USB_EPT_DATA_ISO (IO_TYPECAST_UDWORD 0xb000021c)
+#define R_USB_EPT_DATA_ISO__valid__BITNR 31
+#define R_USB_EPT_DATA_ISO__valid__WIDTH 1
+#define R_USB_EPT_DATA_ISO__valid__no 0
+#define R_USB_EPT_DATA_ISO__valid__yes 1
+#define R_USB_EPT_DATA_ISO__port__BITNR 24
+#define R_USB_EPT_DATA_ISO__port__WIDTH 2
+#define R_USB_EPT_DATA_ISO__port__any 0
+#define R_USB_EPT_DATA_ISO__port__p1 1
+#define R_USB_EPT_DATA_ISO__port__p2 2
+#define R_USB_EPT_DATA_ISO__port__undef 3
+#define R_USB_EPT_DATA_ISO__error_code__BITNR 22
+#define R_USB_EPT_DATA_ISO__error_code__WIDTH 2
+#define R_USB_EPT_DATA_ISO__error_code__no_error 0
+#define R_USB_EPT_DATA_ISO__error_code__stall 1
+#define R_USB_EPT_DATA_ISO__error_code__bus_error 2
+#define R_USB_EPT_DATA_ISO__error_code__TBD3 3
+#define R_USB_EPT_DATA_ISO__max_len__BITNR 11
+#define R_USB_EPT_DATA_ISO__max_len__WIDTH 10
+#define R_USB_EPT_DATA_ISO__ep__BITNR 7
+#define R_USB_EPT_DATA_ISO__ep__WIDTH 4
+#define R_USB_EPT_DATA_ISO__dev__BITNR 0
+#define R_USB_EPT_DATA_ISO__dev__WIDTH 7
+
+#define R_USB_EPT_DATA_DEV (IO_TYPECAST_UDWORD 0xb000021c)
+#define R_USB_EPT_DATA_DEV__valid__BITNR 31
+#define R_USB_EPT_DATA_DEV__valid__WIDTH 1
+#define R_USB_EPT_DATA_DEV__valid__no 0
+#define R_USB_EPT_DATA_DEV__valid__yes 1
+#define R_USB_EPT_DATA_DEV__hold__BITNR 30
+#define R_USB_EPT_DATA_DEV__hold__WIDTH 1
+#define R_USB_EPT_DATA_DEV__hold__no 0
+#define R_USB_EPT_DATA_DEV__hold__yes 1
+#define R_USB_EPT_DATA_DEV__stall__BITNR 29
+#define R_USB_EPT_DATA_DEV__stall__WIDTH 1
+#define R_USB_EPT_DATA_DEV__stall__no 0
+#define R_USB_EPT_DATA_DEV__stall__yes 1
+#define R_USB_EPT_DATA_DEV__iso_resp__BITNR 28
+#define R_USB_EPT_DATA_DEV__iso_resp__WIDTH 1
+#define R_USB_EPT_DATA_DEV__iso_resp__quiet 0
+#define R_USB_EPT_DATA_DEV__iso_resp__yes 1
+#define R_USB_EPT_DATA_DEV__ctrl__BITNR 27
+#define R_USB_EPT_DATA_DEV__ctrl__WIDTH 1
+#define R_USB_EPT_DATA_DEV__ctrl__no 0
+#define R_USB_EPT_DATA_DEV__ctrl__yes 1
+#define R_USB_EPT_DATA_DEV__iso__BITNR 26
+#define R_USB_EPT_DATA_DEV__iso__WIDTH 1
+#define R_USB_EPT_DATA_DEV__iso__no 0
+#define R_USB_EPT_DATA_DEV__iso__yes 1
+#define R_USB_EPT_DATA_DEV__port__BITNR 24
+#define R_USB_EPT_DATA_DEV__port__WIDTH 2
+#define R_USB_EPT_DATA_DEV__control_phase__BITNR 22
+#define R_USB_EPT_DATA_DEV__control_phase__WIDTH 1
+#define R_USB_EPT_DATA_DEV__t__BITNR 21
+#define R_USB_EPT_DATA_DEV__t__WIDTH 1
+#define R_USB_EPT_DATA_DEV__max_len__BITNR 11
+#define R_USB_EPT_DATA_DEV__max_len__WIDTH 10
+#define R_USB_EPT_DATA_DEV__ep__BITNR 7
+#define R_USB_EPT_DATA_DEV__ep__WIDTH 4
+#define R_USB_EPT_DATA_DEV__dev__BITNR 0
+#define R_USB_EPT_DATA_DEV__dev__WIDTH 7
+
+#define R_USB_SNMP_TERROR (IO_TYPECAST_UDWORD 0xb0000220)
+#define R_USB_SNMP_TERROR__value__BITNR 0
+#define R_USB_SNMP_TERROR__value__WIDTH 32
+
+#define R_USB_EPID_ATTN (IO_TYPECAST_RO_UDWORD 0xb0000224)
+#define R_USB_EPID_ATTN__value__BITNR 0
+#define R_USB_EPID_ATTN__value__WIDTH 32
+
+#define R_USB_PORT1_DISABLE (IO_TYPECAST_BYTE 0xb000006a)
+#define R_USB_PORT1_DISABLE__disable__BITNR 0
+#define R_USB_PORT1_DISABLE__disable__WIDTH 1
+#define R_USB_PORT1_DISABLE__disable__yes 0
+#define R_USB_PORT1_DISABLE__disable__no 1
+
+#define R_USB_PORT2_DISABLE (IO_TYPECAST_BYTE 0xb0000052)
+#define R_USB_PORT2_DISABLE__disable__BITNR 0
+#define R_USB_PORT2_DISABLE__disable__WIDTH 1
+#define R_USB_PORT2_DISABLE__disable__yes 0
+#define R_USB_PORT2_DISABLE__disable__no 1
+
+/*
+!* MMU registers
+!*/
+
+#define R_MMU_CONFIG (IO_TYPECAST_UDWORD 0xb0000240)
+#define R_MMU_CONFIG__mmu_enable__BITNR 31
+#define R_MMU_CONFIG__mmu_enable__WIDTH 1
+#define R_MMU_CONFIG__mmu_enable__enable 1
+#define R_MMU_CONFIG__mmu_enable__disable 0
+#define R_MMU_CONFIG__inv_excp__BITNR 18
+#define R_MMU_CONFIG__inv_excp__WIDTH 1
+#define R_MMU_CONFIG__inv_excp__enable 1
+#define R_MMU_CONFIG__inv_excp__disable 0
+#define R_MMU_CONFIG__acc_excp__BITNR 17
+#define R_MMU_CONFIG__acc_excp__WIDTH 1
+#define R_MMU_CONFIG__acc_excp__enable 1
+#define R_MMU_CONFIG__acc_excp__disable 0
+#define R_MMU_CONFIG__we_excp__BITNR 16
+#define R_MMU_CONFIG__we_excp__WIDTH 1
+#define R_MMU_CONFIG__we_excp__enable 1
+#define R_MMU_CONFIG__we_excp__disable 0
+#define R_MMU_CONFIG__seg_f__BITNR 15
+#define R_MMU_CONFIG__seg_f__WIDTH 1
+#define R_MMU_CONFIG__seg_f__seg 1
+#define R_MMU_CONFIG__seg_f__page 0
+#define R_MMU_CONFIG__seg_e__BITNR 14
+#define R_MMU_CONFIG__seg_e__WIDTH 1
+#define R_MMU_CONFIG__seg_e__seg 1
+#define R_MMU_CONFIG__seg_e__page 0
+#define R_MMU_CONFIG__seg_d__BITNR 13
+#define R_MMU_CONFIG__seg_d__WIDTH 1
+#define R_MMU_CONFIG__seg_d__seg 1
+#define R_MMU_CONFIG__seg_d__page 0
+#define R_MMU_CONFIG__seg_c__BITNR 12
+#define R_MMU_CONFIG__seg_c__WIDTH 1
+#define R_MMU_CONFIG__seg_c__seg 1
+#define R_MMU_CONFIG__seg_c__page 0
+#define R_MMU_CONFIG__seg_b__BITNR 11
+#define R_MMU_CONFIG__seg_b__WIDTH 1
+#define R_MMU_CONFIG__seg_b__seg 1
+#define R_MMU_CONFIG__seg_b__page 0
+#define R_MMU_CONFIG__seg_a__BITNR 10
+#define R_MMU_CONFIG__seg_a__WIDTH 1
+#define R_MMU_CONFIG__seg_a__seg 1
+#define R_MMU_CONFIG__seg_a__page 0
+#define R_MMU_CONFIG__seg_9__BITNR 9
+#define R_MMU_CONFIG__seg_9__WIDTH 1
+#define R_MMU_CONFIG__seg_9__seg 1
+#define R_MMU_CONFIG__seg_9__page 0
+#define R_MMU_CONFIG__seg_8__BITNR 8
+#define R_MMU_CONFIG__seg_8__WIDTH 1
+#define R_MMU_CONFIG__seg_8__seg 1
+#define R_MMU_CONFIG__seg_8__page 0
+#define R_MMU_CONFIG__seg_7__BITNR 7
+#define R_MMU_CONFIG__seg_7__WIDTH 1
+#define R_MMU_CONFIG__seg_7__seg 1
+#define R_MMU_CONFIG__seg_7__page 0
+#define R_MMU_CONFIG__seg_6__BITNR 6
+#define R_MMU_CONFIG__seg_6__WIDTH 1
+#define R_MMU_CONFIG__seg_6__seg 1
+#define R_MMU_CONFIG__seg_6__page 0
+#define R_MMU_CONFIG__seg_5__BITNR 5
+#define R_MMU_CONFIG__seg_5__WIDTH 1
+#define R_MMU_CONFIG__seg_5__seg 1
+#define R_MMU_CONFIG__seg_5__page 0
+#define R_MMU_CONFIG__seg_4__BITNR 4
+#define R_MMU_CONFIG__seg_4__WIDTH 1
+#define R_MMU_CONFIG__seg_4__seg 1
+#define R_MMU_CONFIG__seg_4__page 0
+#define R_MMU_CONFIG__seg_3__BITNR 3
+#define R_MMU_CONFIG__seg_3__WIDTH 1
+#define R_MMU_CONFIG__seg_3__seg 1
+#define R_MMU_CONFIG__seg_3__page 0
+#define R_MMU_CONFIG__seg_2__BITNR 2
+#define R_MMU_CONFIG__seg_2__WIDTH 1
+#define R_MMU_CONFIG__seg_2__seg 1
+#define R_MMU_CONFIG__seg_2__page 0
+#define R_MMU_CONFIG__seg_1__BITNR 1
+#define R_MMU_CONFIG__seg_1__WIDTH 1
+#define R_MMU_CONFIG__seg_1__seg 1
+#define R_MMU_CONFIG__seg_1__page 0
+#define R_MMU_CONFIG__seg_0__BITNR 0
+#define R_MMU_CONFIG__seg_0__WIDTH 1
+#define R_MMU_CONFIG__seg_0__seg 1
+#define R_MMU_CONFIG__seg_0__page 0
+
+#define R_MMU_KSEG (IO_TYPECAST_UWORD 0xb0000240)
+#define R_MMU_KSEG__seg_f__BITNR 15
+#define R_MMU_KSEG__seg_f__WIDTH 1
+#define R_MMU_KSEG__seg_f__seg 1
+#define R_MMU_KSEG__seg_f__page 0
+#define R_MMU_KSEG__seg_e__BITNR 14
+#define R_MMU_KSEG__seg_e__WIDTH 1
+#define R_MMU_KSEG__seg_e__seg 1
+#define R_MMU_KSEG__seg_e__page 0
+#define R_MMU_KSEG__seg_d__BITNR 13
+#define R_MMU_KSEG__seg_d__WIDTH 1
+#define R_MMU_KSEG__seg_d__seg 1
+#define R_MMU_KSEG__seg_d__page 0
+#define R_MMU_KSEG__seg_c__BITNR 12
+#define R_MMU_KSEG__seg_c__WIDTH 1
+#define R_MMU_KSEG__seg_c__seg 1
+#define R_MMU_KSEG__seg_c__page 0
+#define R_MMU_KSEG__seg_b__BITNR 11
+#define R_MMU_KSEG__seg_b__WIDTH 1
+#define R_MMU_KSEG__seg_b__seg 1
+#define R_MMU_KSEG__seg_b__page 0
+#define R_MMU_KSEG__seg_a__BITNR 10
+#define R_MMU_KSEG__seg_a__WIDTH 1
+#define R_MMU_KSEG__seg_a__seg 1
+#define R_MMU_KSEG__seg_a__page 0
+#define R_MMU_KSEG__seg_9__BITNR 9
+#define R_MMU_KSEG__seg_9__WIDTH 1
+#define R_MMU_KSEG__seg_9__seg 1
+#define R_MMU_KSEG__seg_9__page 0
+#define R_MMU_KSEG__seg_8__BITNR 8
+#define R_MMU_KSEG__seg_8__WIDTH 1
+#define R_MMU_KSEG__seg_8__seg 1
+#define R_MMU_KSEG__seg_8__page 0
+#define R_MMU_KSEG__seg_7__BITNR 7
+#define R_MMU_KSEG__seg_7__WIDTH 1
+#define R_MMU_KSEG__seg_7__seg 1
+#define R_MMU_KSEG__seg_7__page 0
+#define R_MMU_KSEG__seg_6__BITNR 6
+#define R_MMU_KSEG__seg_6__WIDTH 1
+#define R_MMU_KSEG__seg_6__seg 1
+#define R_MMU_KSEG__seg_6__page 0
+#define R_MMU_KSEG__seg_5__BITNR 5
+#define R_MMU_KSEG__seg_5__WIDTH 1
+#define R_MMU_KSEG__seg_5__seg 1
+#define R_MMU_KSEG__seg_5__page 0
+#define R_MMU_KSEG__seg_4__BITNR 4
+#define R_MMU_KSEG__seg_4__WIDTH 1
+#define R_MMU_KSEG__seg_4__seg 1
+#define R_MMU_KSEG__seg_4__page 0
+#define R_MMU_KSEG__seg_3__BITNR 3
+#define R_MMU_KSEG__seg_3__WIDTH 1
+#define R_MMU_KSEG__seg_3__seg 1
+#define R_MMU_KSEG__seg_3__page 0
+#define R_MMU_KSEG__seg_2__BITNR 2
+#define R_MMU_KSEG__seg_2__WIDTH 1
+#define R_MMU_KSEG__seg_2__seg 1
+#define R_MMU_KSEG__seg_2__page 0
+#define R_MMU_KSEG__seg_1__BITNR 1
+#define R_MMU_KSEG__seg_1__WIDTH 1
+#define R_MMU_KSEG__seg_1__seg 1
+#define R_MMU_KSEG__seg_1__page 0
+#define R_MMU_KSEG__seg_0__BITNR 0
+#define R_MMU_KSEG__seg_0__WIDTH 1
+#define R_MMU_KSEG__seg_0__seg 1
+#define R_MMU_KSEG__seg_0__page 0
+
+#define R_MMU_CTRL (IO_TYPECAST_BYTE 0xb0000242)
+#define R_MMU_CTRL__inv_excp__BITNR 2
+#define R_MMU_CTRL__inv_excp__WIDTH 1
+#define R_MMU_CTRL__inv_excp__enable 1
+#define R_MMU_CTRL__inv_excp__disable 0
+#define R_MMU_CTRL__acc_excp__BITNR 1
+#define R_MMU_CTRL__acc_excp__WIDTH 1
+#define R_MMU_CTRL__acc_excp__enable 1
+#define R_MMU_CTRL__acc_excp__disable 0
+#define R_MMU_CTRL__we_excp__BITNR 0
+#define R_MMU_CTRL__we_excp__WIDTH 1
+#define R_MMU_CTRL__we_excp__enable 1
+#define R_MMU_CTRL__we_excp__disable 0
+
+#define R_MMU_ENABLE (IO_TYPECAST_BYTE 0xb0000243)
+#define R_MMU_ENABLE__mmu_enable__BITNR 7
+#define R_MMU_ENABLE__mmu_enable__WIDTH 1
+#define R_MMU_ENABLE__mmu_enable__enable 1
+#define R_MMU_ENABLE__mmu_enable__disable 0
+
+#define R_MMU_KBASE_LO (IO_TYPECAST_UDWORD 0xb0000244)
+#define R_MMU_KBASE_LO__base_7__BITNR 28
+#define R_MMU_KBASE_LO__base_7__WIDTH 4
+#define R_MMU_KBASE_LO__base_6__BITNR 24
+#define R_MMU_KBASE_LO__base_6__WIDTH 4
+#define R_MMU_KBASE_LO__base_5__BITNR 20
+#define R_MMU_KBASE_LO__base_5__WIDTH 4
+#define R_MMU_KBASE_LO__base_4__BITNR 16
+#define R_MMU_KBASE_LO__base_4__WIDTH 4
+#define R_MMU_KBASE_LO__base_3__BITNR 12
+#define R_MMU_KBASE_LO__base_3__WIDTH 4
+#define R_MMU_KBASE_LO__base_2__BITNR 8
+#define R_MMU_KBASE_LO__base_2__WIDTH 4
+#define R_MMU_KBASE_LO__base_1__BITNR 4
+#define R_MMU_KBASE_LO__base_1__WIDTH 4
+#define R_MMU_KBASE_LO__base_0__BITNR 0
+#define R_MMU_KBASE_LO__base_0__WIDTH 4
+
+#define R_MMU_KBASE_HI (IO_TYPECAST_UDWORD 0xb0000248)
+#define R_MMU_KBASE_HI__base_f__BITNR 28
+#define R_MMU_KBASE_HI__base_f__WIDTH 4
+#define R_MMU_KBASE_HI__base_e__BITNR 24
+#define R_MMU_KBASE_HI__base_e__WIDTH 4
+#define R_MMU_KBASE_HI__base_d__BITNR 20
+#define R_MMU_KBASE_HI__base_d__WIDTH 4
+#define R_MMU_KBASE_HI__base_c__BITNR 16
+#define R_MMU_KBASE_HI__base_c__WIDTH 4
+#define R_MMU_KBASE_HI__base_b__BITNR 12
+#define R_MMU_KBASE_HI__base_b__WIDTH 4
+#define R_MMU_KBASE_HI__base_a__BITNR 8
+#define R_MMU_KBASE_HI__base_a__WIDTH 4
+#define R_MMU_KBASE_HI__base_9__BITNR 4
+#define R_MMU_KBASE_HI__base_9__WIDTH 4
+#define R_MMU_KBASE_HI__base_8__BITNR 0
+#define R_MMU_KBASE_HI__base_8__WIDTH 4
+
+#define R_MMU_CONTEXT (IO_TYPECAST_BYTE 0xb000024c)
+#define R_MMU_CONTEXT__page_id__BITNR 0
+#define R_MMU_CONTEXT__page_id__WIDTH 6
+
+#define R_MMU_CAUSE (IO_TYPECAST_RO_UDWORD 0xb0000250)
+#define R_MMU_CAUSE__vpn__BITNR 13
+#define R_MMU_CAUSE__vpn__WIDTH 19
+#define R_MMU_CAUSE__miss_excp__BITNR 12
+#define R_MMU_CAUSE__miss_excp__WIDTH 1
+#define R_MMU_CAUSE__miss_excp__yes 1
+#define R_MMU_CAUSE__miss_excp__no 0
+#define R_MMU_CAUSE__inv_excp__BITNR 11
+#define R_MMU_CAUSE__inv_excp__WIDTH 1
+#define R_MMU_CAUSE__inv_excp__yes 1
+#define R_MMU_CAUSE__inv_excp__no 0
+#define R_MMU_CAUSE__acc_excp__BITNR 10
+#define R_MMU_CAUSE__acc_excp__WIDTH 1
+#define R_MMU_CAUSE__acc_excp__yes 1
+#define R_MMU_CAUSE__acc_excp__no 0
+#define R_MMU_CAUSE__we_excp__BITNR 9
+#define R_MMU_CAUSE__we_excp__WIDTH 1
+#define R_MMU_CAUSE__we_excp__yes 1
+#define R_MMU_CAUSE__we_excp__no 0
+#define R_MMU_CAUSE__wr_rd__BITNR 8
+#define R_MMU_CAUSE__wr_rd__WIDTH 1
+#define R_MMU_CAUSE__wr_rd__write 1
+#define R_MMU_CAUSE__wr_rd__read 0
+#define R_MMU_CAUSE__page_id__BITNR 0
+#define R_MMU_CAUSE__page_id__WIDTH 6
+
+#define R_TLB_SELECT (IO_TYPECAST_BYTE 0xb0000254)
+#define R_TLB_SELECT__index__BITNR 0
+#define R_TLB_SELECT__index__WIDTH 6
+
+#define R_TLB_LO (IO_TYPECAST_UDWORD 0xb0000258)
+#define R_TLB_LO__pfn__BITNR 13
+#define R_TLB_LO__pfn__WIDTH 19
+#define R_TLB_LO__global__BITNR 3
+#define R_TLB_LO__global__WIDTH 1
+#define R_TLB_LO__global__yes 1
+#define R_TLB_LO__global__no 0
+#define R_TLB_LO__valid__BITNR 2
+#define R_TLB_LO__valid__WIDTH 1
+#define R_TLB_LO__valid__yes 1
+#define R_TLB_LO__valid__no 0
+#define R_TLB_LO__kernel__BITNR 1
+#define R_TLB_LO__kernel__WIDTH 1
+#define R_TLB_LO__kernel__yes 1
+#define R_TLB_LO__kernel__no 0
+#define R_TLB_LO__we__BITNR 0
+#define R_TLB_LO__we__WIDTH 1
+#define R_TLB_LO__we__yes 1
+#define R_TLB_LO__we__no 0
+
+#define R_TLB_HI (IO_TYPECAST_UDWORD 0xb000025c)
+#define R_TLB_HI__vpn__BITNR 13
+#define R_TLB_HI__vpn__WIDTH 19
+#define R_TLB_HI__page_id__BITNR 0
+#define R_TLB_HI__page_id__WIDTH 6
+
+/*
+!* Syncrounous serial port registers
+!*/
+
+#define R_SYNC_SERIAL1_REC_DATA (IO_TYPECAST_RO_UDWORD 0xb000006c)
+#define R_SYNC_SERIAL1_REC_DATA__data_in__BITNR 0
+#define R_SYNC_SERIAL1_REC_DATA__data_in__WIDTH 32
+
+#define R_SYNC_SERIAL1_REC_WORD (IO_TYPECAST_RO_UWORD 0xb000006c)
+#define R_SYNC_SERIAL1_REC_WORD__data_in__BITNR 0
+#define R_SYNC_SERIAL1_REC_WORD__data_in__WIDTH 16
+
+#define R_SYNC_SERIAL1_REC_BYTE (IO_TYPECAST_RO_BYTE 0xb000006c)
+#define R_SYNC_SERIAL1_REC_BYTE__data_in__BITNR 0
+#define R_SYNC_SERIAL1_REC_BYTE__data_in__WIDTH 8
+
+#define R_SYNC_SERIAL1_STATUS (IO_TYPECAST_RO_UDWORD 0xb0000068)
+#define R_SYNC_SERIAL1_STATUS__rec_status__BITNR 15
+#define R_SYNC_SERIAL1_STATUS__rec_status__WIDTH 1
+#define R_SYNC_SERIAL1_STATUS__rec_status__running 0
+#define R_SYNC_SERIAL1_STATUS__rec_status__idle 1
+#define R_SYNC_SERIAL1_STATUS__tr_empty__BITNR 14
+#define R_SYNC_SERIAL1_STATUS__tr_empty__WIDTH 1
+#define R_SYNC_SERIAL1_STATUS__tr_empty__empty 1
+#define R_SYNC_SERIAL1_STATUS__tr_empty__not_empty 0
+#define R_SYNC_SERIAL1_STATUS__tr_ready__BITNR 13
+#define R_SYNC_SERIAL1_STATUS__tr_ready__WIDTH 1
+#define R_SYNC_SERIAL1_STATUS__tr_ready__full 0
+#define R_SYNC_SERIAL1_STATUS__tr_ready__ready 1
+#define R_SYNC_SERIAL1_STATUS__pin_1__BITNR 12
+#define R_SYNC_SERIAL1_STATUS__pin_1__WIDTH 1
+#define R_SYNC_SERIAL1_STATUS__pin_1__low 0
+#define R_SYNC_SERIAL1_STATUS__pin_1__high 1
+#define R_SYNC_SERIAL1_STATUS__pin_0__BITNR 11
+#define R_SYNC_SERIAL1_STATUS__pin_0__WIDTH 1
+#define R_SYNC_SERIAL1_STATUS__pin_0__low 0
+#define R_SYNC_SERIAL1_STATUS__pin_0__high 1
+#define R_SYNC_SERIAL1_STATUS__underflow__BITNR 10
+#define R_SYNC_SERIAL1_STATUS__underflow__WIDTH 1
+#define R_SYNC_SERIAL1_STATUS__underflow__no 0
+#define R_SYNC_SERIAL1_STATUS__underflow__yes 1
+#define R_SYNC_SERIAL1_STATUS__overrun__BITNR 9
+#define R_SYNC_SERIAL1_STATUS__overrun__WIDTH 1
+#define R_SYNC_SERIAL1_STATUS__overrun__no 0
+#define R_SYNC_SERIAL1_STATUS__overrun__yes 1
+#define R_SYNC_SERIAL1_STATUS__data_avail__BITNR 8
+#define R_SYNC_SERIAL1_STATUS__data_avail__WIDTH 1
+#define R_SYNC_SERIAL1_STATUS__data_avail__no 0
+#define R_SYNC_SERIAL1_STATUS__data_avail__yes 1
+#define R_SYNC_SERIAL1_STATUS__data__BITNR 0
+#define R_SYNC_SERIAL1_STATUS__data__WIDTH 8
+
+#define R_SYNC_SERIAL1_TR_DATA (IO_TYPECAST_UDWORD 0xb000006c)
+#define R_SYNC_SERIAL1_TR_DATA__data_out__BITNR 0
+#define R_SYNC_SERIAL1_TR_DATA__data_out__WIDTH 32
+
+#define R_SYNC_SERIAL1_TR_WORD (IO_TYPECAST_UWORD 0xb000006c)
+#define R_SYNC_SERIAL1_TR_WORD__data_out__BITNR 0
+#define R_SYNC_SERIAL1_TR_WORD__data_out__WIDTH 16
+
+#define R_SYNC_SERIAL1_TR_BYTE (IO_TYPECAST_BYTE 0xb000006c)
+#define R_SYNC_SERIAL1_TR_BYTE__data_out__BITNR 0
+#define R_SYNC_SERIAL1_TR_BYTE__data_out__WIDTH 8
+
+#define R_SYNC_SERIAL1_CTRL (IO_TYPECAST_UDWORD 0xb0000068)
+#define R_SYNC_SERIAL1_CTRL__tr_baud__BITNR 28
+#define R_SYNC_SERIAL1_CTRL__tr_baud__WIDTH 4
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c150Hz 0
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c300Hz 1
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c600Hz 2
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c1200Hz 3
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c2400Hz 4
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c4800Hz 5
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c9600Hz 6
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c19k2Hz 7
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c28k8Hz 8
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c57k6Hz 9
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c115k2Hz 10
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c230k4Hz 11
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c460k8Hz 12
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c921k6Hz 13
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c3125kHz 14
+#define R_SYNC_SERIAL1_CTRL__tr_baud__reserved 15
+#define R_SYNC_SERIAL1_CTRL__dma_enable__BITNR 27
+#define R_SYNC_SERIAL1_CTRL__dma_enable__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__dma_enable__on 1
+#define R_SYNC_SERIAL1_CTRL__dma_enable__off 0
+#define R_SYNC_SERIAL1_CTRL__mode__BITNR 24
+#define R_SYNC_SERIAL1_CTRL__mode__WIDTH 3
+#define R_SYNC_SERIAL1_CTRL__mode__master_output 0
+#define R_SYNC_SERIAL1_CTRL__mode__slave_output 1
+#define R_SYNC_SERIAL1_CTRL__mode__master_input 2
+#define R_SYNC_SERIAL1_CTRL__mode__slave_input 3
+#define R_SYNC_SERIAL1_CTRL__mode__master_bidir 4
+#define R_SYNC_SERIAL1_CTRL__mode__slave_bidir 5
+#define R_SYNC_SERIAL1_CTRL__error__BITNR 23
+#define R_SYNC_SERIAL1_CTRL__error__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__error__normal 0
+#define R_SYNC_SERIAL1_CTRL__error__ignore 1
+#define R_SYNC_SERIAL1_CTRL__rec_enable__BITNR 22
+#define R_SYNC_SERIAL1_CTRL__rec_enable__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__rec_enable__disable 0
+#define R_SYNC_SERIAL1_CTRL__rec_enable__enable 1
+#define R_SYNC_SERIAL1_CTRL__f_synctype__BITNR 21
+#define R_SYNC_SERIAL1_CTRL__f_synctype__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__f_synctype__normal 0
+#define R_SYNC_SERIAL1_CTRL__f_synctype__early 1
+#define R_SYNC_SERIAL1_CTRL__f_syncsize__BITNR 19
+#define R_SYNC_SERIAL1_CTRL__f_syncsize__WIDTH 2
+#define R_SYNC_SERIAL1_CTRL__f_syncsize__bit 0
+#define R_SYNC_SERIAL1_CTRL__f_syncsize__word 1
+#define R_SYNC_SERIAL1_CTRL__f_syncsize__extended 2
+#define R_SYNC_SERIAL1_CTRL__f_syncsize__reserved 3
+#define R_SYNC_SERIAL1_CTRL__f_sync__BITNR 18
+#define R_SYNC_SERIAL1_CTRL__f_sync__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__f_sync__on 0
+#define R_SYNC_SERIAL1_CTRL__f_sync__off 1
+#define R_SYNC_SERIAL1_CTRL__clk_mode__BITNR 17
+#define R_SYNC_SERIAL1_CTRL__clk_mode__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__clk_mode__normal 0
+#define R_SYNC_SERIAL1_CTRL__clk_mode__gated 1
+#define R_SYNC_SERIAL1_CTRL__clk_halt__BITNR 16
+#define R_SYNC_SERIAL1_CTRL__clk_halt__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__clk_halt__running 0
+#define R_SYNC_SERIAL1_CTRL__clk_halt__stopped 1
+#define R_SYNC_SERIAL1_CTRL__bitorder__BITNR 15
+#define R_SYNC_SERIAL1_CTRL__bitorder__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__bitorder__lsb 0
+#define R_SYNC_SERIAL1_CTRL__bitorder__msb 1
+#define R_SYNC_SERIAL1_CTRL__tr_enable__BITNR 14
+#define R_SYNC_SERIAL1_CTRL__tr_enable__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__tr_enable__disable 0
+#define R_SYNC_SERIAL1_CTRL__tr_enable__enable 1
+#define R_SYNC_SERIAL1_CTRL__wordsize__BITNR 11
+#define R_SYNC_SERIAL1_CTRL__wordsize__WIDTH 3
+#define R_SYNC_SERIAL1_CTRL__wordsize__size8bit 0
+#define R_SYNC_SERIAL1_CTRL__wordsize__size12bit 1
+#define R_SYNC_SERIAL1_CTRL__wordsize__size16bit 2
+#define R_SYNC_SERIAL1_CTRL__wordsize__size24bit 3
+#define R_SYNC_SERIAL1_CTRL__wordsize__size32bit 4
+#define R_SYNC_SERIAL1_CTRL__buf_empty__BITNR 10
+#define R_SYNC_SERIAL1_CTRL__buf_empty__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__buf_empty__lmt_8 0
+#define R_SYNC_SERIAL1_CTRL__buf_empty__lmt_0 1
+#define R_SYNC_SERIAL1_CTRL__buf_full__BITNR 9
+#define R_SYNC_SERIAL1_CTRL__buf_full__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__buf_full__lmt_32 0
+#define R_SYNC_SERIAL1_CTRL__buf_full__lmt_8 1
+#define R_SYNC_SERIAL1_CTRL__flow_ctrl__BITNR 8
+#define R_SYNC_SERIAL1_CTRL__flow_ctrl__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__flow_ctrl__disabled 0
+#define R_SYNC_SERIAL1_CTRL__flow_ctrl__enabled 1
+#define R_SYNC_SERIAL1_CTRL__clk_polarity__BITNR 6
+#define R_SYNC_SERIAL1_CTRL__clk_polarity__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__clk_polarity__pos 0
+#define R_SYNC_SERIAL1_CTRL__clk_polarity__neg 1
+#define R_SYNC_SERIAL1_CTRL__frame_polarity__BITNR 5
+#define R_SYNC_SERIAL1_CTRL__frame_polarity__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__frame_polarity__normal 0
+#define R_SYNC_SERIAL1_CTRL__frame_polarity__inverted 1
+#define R_SYNC_SERIAL1_CTRL__status_polarity__BITNR 4
+#define R_SYNC_SERIAL1_CTRL__status_polarity__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__status_polarity__normal 0
+#define R_SYNC_SERIAL1_CTRL__status_polarity__inverted 1
+#define R_SYNC_SERIAL1_CTRL__clk_driver__BITNR 3
+#define R_SYNC_SERIAL1_CTRL__clk_driver__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__clk_driver__normal 0
+#define R_SYNC_SERIAL1_CTRL__clk_driver__inverted 1
+#define R_SYNC_SERIAL1_CTRL__frame_driver__BITNR 2
+#define R_SYNC_SERIAL1_CTRL__frame_driver__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__frame_driver__normal 0
+#define R_SYNC_SERIAL1_CTRL__frame_driver__inverted 1
+#define R_SYNC_SERIAL1_CTRL__status_driver__BITNR 1
+#define R_SYNC_SERIAL1_CTRL__status_driver__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__status_driver__normal 0
+#define R_SYNC_SERIAL1_CTRL__status_driver__inverted 1
+#define R_SYNC_SERIAL1_CTRL__def_out0__BITNR 0
+#define R_SYNC_SERIAL1_CTRL__def_out0__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__def_out0__high 1
+#define R_SYNC_SERIAL1_CTRL__def_out0__low 0
+
+#define R_SYNC_SERIAL3_REC_DATA (IO_TYPECAST_RO_UDWORD 0xb000007c)
+#define R_SYNC_SERIAL3_REC_DATA__data_in__BITNR 0
+#define R_SYNC_SERIAL3_REC_DATA__data_in__WIDTH 32
+
+#define R_SYNC_SERIAL3_REC_WORD (IO_TYPECAST_RO_UWORD 0xb000007c)
+#define R_SYNC_SERIAL3_REC_WORD__data_in__BITNR 0
+#define R_SYNC_SERIAL3_REC_WORD__data_in__WIDTH 16
+
+#define R_SYNC_SERIAL3_REC_BYTE (IO_TYPECAST_RO_BYTE 0xb000007c)
+#define R_SYNC_SERIAL3_REC_BYTE__data_in__BITNR 0
+#define R_SYNC_SERIAL3_REC_BYTE__data_in__WIDTH 8
+
+#define R_SYNC_SERIAL3_STATUS (IO_TYPECAST_RO_UDWORD 0xb0000078)
+#define R_SYNC_SERIAL3_STATUS__rec_status__BITNR 15
+#define R_SYNC_SERIAL3_STATUS__rec_status__WIDTH 1
+#define R_SYNC_SERIAL3_STATUS__rec_status__running 0
+#define R_SYNC_SERIAL3_STATUS__rec_status__idle 1
+#define R_SYNC_SERIAL3_STATUS__tr_empty__BITNR 14
+#define R_SYNC_SERIAL3_STATUS__tr_empty__WIDTH 1
+#define R_SYNC_SERIAL3_STATUS__tr_empty__empty 1
+#define R_SYNC_SERIAL3_STATUS__tr_empty__not_empty 0
+#define R_SYNC_SERIAL3_STATUS__tr_ready__BITNR 13
+#define R_SYNC_SERIAL3_STATUS__tr_ready__WIDTH 1
+#define R_SYNC_SERIAL3_STATUS__tr_ready__full 0
+#define R_SYNC_SERIAL3_STATUS__tr_ready__ready 1
+#define R_SYNC_SERIAL3_STATUS__pin_1__BITNR 12
+#define R_SYNC_SERIAL3_STATUS__pin_1__WIDTH 1
+#define R_SYNC_SERIAL3_STATUS__pin_1__low 0
+#define R_SYNC_SERIAL3_STATUS__pin_1__high 1
+#define R_SYNC_SERIAL3_STATUS__pin_0__BITNR 11
+#define R_SYNC_SERIAL3_STATUS__pin_0__WIDTH 1
+#define R_SYNC_SERIAL3_STATUS__pin_0__low 0
+#define R_SYNC_SERIAL3_STATUS__pin_0__high 1
+#define R_SYNC_SERIAL3_STATUS__underflow__BITNR 10
+#define R_SYNC_SERIAL3_STATUS__underflow__WIDTH 1
+#define R_SYNC_SERIAL3_STATUS__underflow__no 0
+#define R_SYNC_SERIAL3_STATUS__underflow__yes 1
+#define R_SYNC_SERIAL3_STATUS__overrun__BITNR 9
+#define R_SYNC_SERIAL3_STATUS__overrun__WIDTH 1
+#define R_SYNC_SERIAL3_STATUS__overrun__no 0
+#define R_SYNC_SERIAL3_STATUS__overrun__yes 1
+#define R_SYNC_SERIAL3_STATUS__data_avail__BITNR 8
+#define R_SYNC_SERIAL3_STATUS__data_avail__WIDTH 1
+#define R_SYNC_SERIAL3_STATUS__data_avail__no 0
+#define R_SYNC_SERIAL3_STATUS__data_avail__yes 1
+#define R_SYNC_SERIAL3_STATUS__data__BITNR 0
+#define R_SYNC_SERIAL3_STATUS__data__WIDTH 8
+
+#define R_SYNC_SERIAL3_TR_DATA (IO_TYPECAST_UDWORD 0xb000007c)
+#define R_SYNC_SERIAL3_TR_DATA__data_out__BITNR 0
+#define R_SYNC_SERIAL3_TR_DATA__data_out__WIDTH 32
+
+#define R_SYNC_SERIAL3_TR_WORD (IO_TYPECAST_UWORD 0xb000007c)
+#define R_SYNC_SERIAL3_TR_WORD__data_out__BITNR 0
+#define R_SYNC_SERIAL3_TR_WORD__data_out__WIDTH 16
+
+#define R_SYNC_SERIAL3_TR_BYTE (IO_TYPECAST_BYTE 0xb000007c)
+#define R_SYNC_SERIAL3_TR_BYTE__data_out__BITNR 0
+#define R_SYNC_SERIAL3_TR_BYTE__data_out__WIDTH 8
+
+#define R_SYNC_SERIAL3_CTRL (IO_TYPECAST_UDWORD 0xb0000078)
+#define R_SYNC_SERIAL3_CTRL__tr_baud__BITNR 28
+#define R_SYNC_SERIAL3_CTRL__tr_baud__WIDTH 4
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c150Hz 0
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c300Hz 1
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c600Hz 2
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c1200Hz 3
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c2400Hz 4
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c4800Hz 5
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c9600Hz 6
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c19k2Hz 7
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c28k8Hz 8
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c57k6Hz 9
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c115k2Hz 10
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c230k4Hz 11
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c460k8Hz 12
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c921k6Hz 13
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c3125kHz 14
+#define R_SYNC_SERIAL3_CTRL__tr_baud__reserved 15
+#define R_SYNC_SERIAL3_CTRL__dma_enable__BITNR 27
+#define R_SYNC_SERIAL3_CTRL__dma_enable__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__dma_enable__on 1
+#define R_SYNC_SERIAL3_CTRL__dma_enable__off 0
+#define R_SYNC_SERIAL3_CTRL__mode__BITNR 24
+#define R_SYNC_SERIAL3_CTRL__mode__WIDTH 3
+#define R_SYNC_SERIAL3_CTRL__mode__master_output 0
+#define R_SYNC_SERIAL3_CTRL__mode__slave_output 1
+#define R_SYNC_SERIAL3_CTRL__mode__master_input 2
+#define R_SYNC_SERIAL3_CTRL__mode__slave_input 3
+#define R_SYNC_SERIAL3_CTRL__mode__master_bidir 4
+#define R_SYNC_SERIAL3_CTRL__mode__slave_bidir 5
+#define R_SYNC_SERIAL3_CTRL__error__BITNR 23
+#define R_SYNC_SERIAL3_CTRL__error__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__error__normal 0
+#define R_SYNC_SERIAL3_CTRL__error__ignore 1
+#define R_SYNC_SERIAL3_CTRL__rec_enable__BITNR 22
+#define R_SYNC_SERIAL3_CTRL__rec_enable__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__rec_enable__disable 0
+#define R_SYNC_SERIAL3_CTRL__rec_enable__enable 1
+#define R_SYNC_SERIAL3_CTRL__f_synctype__BITNR 21
+#define R_SYNC_SERIAL3_CTRL__f_synctype__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__f_synctype__normal 0
+#define R_SYNC_SERIAL3_CTRL__f_synctype__early 1
+#define R_SYNC_SERIAL3_CTRL__f_syncsize__BITNR 19
+#define R_SYNC_SERIAL3_CTRL__f_syncsize__WIDTH 2
+#define R_SYNC_SERIAL3_CTRL__f_syncsize__bit 0
+#define R_SYNC_SERIAL3_CTRL__f_syncsize__word 1
+#define R_SYNC_SERIAL3_CTRL__f_syncsize__extended 2
+#define R_SYNC_SERIAL3_CTRL__f_syncsize__reserved 3
+#define R_SYNC_SERIAL3_CTRL__f_sync__BITNR 18
+#define R_SYNC_SERIAL3_CTRL__f_sync__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__f_sync__on 0
+#define R_SYNC_SERIAL3_CTRL__f_sync__off 1
+#define R_SYNC_SERIAL3_CTRL__clk_mode__BITNR 17
+#define R_SYNC_SERIAL3_CTRL__clk_mode__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__clk_mode__normal 0
+#define R_SYNC_SERIAL3_CTRL__clk_mode__gated 1
+#define R_SYNC_SERIAL3_CTRL__clk_halt__BITNR 16
+#define R_SYNC_SERIAL3_CTRL__clk_halt__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__clk_halt__running 0
+#define R_SYNC_SERIAL3_CTRL__clk_halt__stopped 1
+#define R_SYNC_SERIAL3_CTRL__bitorder__BITNR 15
+#define R_SYNC_SERIAL3_CTRL__bitorder__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__bitorder__lsb 0
+#define R_SYNC_SERIAL3_CTRL__bitorder__msb 1
+#define R_SYNC_SERIAL3_CTRL__tr_enable__BITNR 14
+#define R_SYNC_SERIAL3_CTRL__tr_enable__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__tr_enable__disable 0
+#define R_SYNC_SERIAL3_CTRL__tr_enable__enable 1
+#define R_SYNC_SERIAL3_CTRL__wordsize__BITNR 11
+#define R_SYNC_SERIAL3_CTRL__wordsize__WIDTH 3
+#define R_SYNC_SERIAL3_CTRL__wordsize__size8bit 0
+#define R_SYNC_SERIAL3_CTRL__wordsize__size12bit 1
+#define R_SYNC_SERIAL3_CTRL__wordsize__size16bit 2
+#define R_SYNC_SERIAL3_CTRL__wordsize__size24bit 3
+#define R_SYNC_SERIAL3_CTRL__wordsize__size32bit 4
+#define R_SYNC_SERIAL3_CTRL__buf_empty__BITNR 10
+#define R_SYNC_SERIAL3_CTRL__buf_empty__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__buf_empty__lmt_8 0
+#define R_SYNC_SERIAL3_CTRL__buf_empty__lmt_0 1
+#define R_SYNC_SERIAL3_CTRL__buf_full__BITNR 9
+#define R_SYNC_SERIAL3_CTRL__buf_full__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__buf_full__lmt_32 0
+#define R_SYNC_SERIAL3_CTRL__buf_full__lmt_8 1
+#define R_SYNC_SERIAL3_CTRL__flow_ctrl__BITNR 8
+#define R_SYNC_SERIAL3_CTRL__flow_ctrl__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__flow_ctrl__disabled 0
+#define R_SYNC_SERIAL3_CTRL__flow_ctrl__enabled 1
+#define R_SYNC_SERIAL3_CTRL__clk_polarity__BITNR 6
+#define R_SYNC_SERIAL3_CTRL__clk_polarity__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__clk_polarity__pos 0
+#define R_SYNC_SERIAL3_CTRL__clk_polarity__neg 1
+#define R_SYNC_SERIAL3_CTRL__frame_polarity__BITNR 5
+#define R_SYNC_SERIAL3_CTRL__frame_polarity__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__frame_polarity__normal 0
+#define R_SYNC_SERIAL3_CTRL__frame_polarity__inverted 1
+#define R_SYNC_SERIAL3_CTRL__status_polarity__BITNR 4
+#define R_SYNC_SERIAL3_CTRL__status_polarity__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__status_polarity__normal 0
+#define R_SYNC_SERIAL3_CTRL__status_polarity__inverted 1
+#define R_SYNC_SERIAL3_CTRL__clk_driver__BITNR 3
+#define R_SYNC_SERIAL3_CTRL__clk_driver__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__clk_driver__normal 0
+#define R_SYNC_SERIAL3_CTRL__clk_driver__inverted 1
+#define R_SYNC_SERIAL3_CTRL__frame_driver__BITNR 2
+#define R_SYNC_SERIAL3_CTRL__frame_driver__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__frame_driver__normal 0
+#define R_SYNC_SERIAL3_CTRL__frame_driver__inverted 1
+#define R_SYNC_SERIAL3_CTRL__status_driver__BITNR 1
+#define R_SYNC_SERIAL3_CTRL__status_driver__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__status_driver__normal 0
+#define R_SYNC_SERIAL3_CTRL__status_driver__inverted 1
+#define R_SYNC_SERIAL3_CTRL__def_out0__BITNR 0
+#define R_SYNC_SERIAL3_CTRL__def_out0__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__def_out0__high 1
+#define R_SYNC_SERIAL3_CTRL__def_out0__low 0
+
diff --git a/arch/cris/include/uapi/arch-v10/arch/sv_addr_ag.h b/arch/cris/include/uapi/arch-v10/arch/sv_addr_ag.h
new file mode 100644
index 0000000..5517f04
--- /dev/null
+++ b/arch/cris/include/uapi/arch-v10/arch/sv_addr_ag.h
@@ -0,0 +1,139 @@
+/*!**************************************************************************
+*!                                                            
+*! MACROS:
+*!   IO_MASK(reg,field)
+*!   IO_STATE(reg,field,state)
+*!   IO_EXTRACT(reg,field,val)
+*!   IO_STATE_VALUE(reg,field,state)
+*!   IO_BITNR(reg,field)
+*!   IO_WIDTH(reg,field)
+*!   IO_FIELD(reg,field,val)
+*!   IO_RD(reg)
+*!   All moderegister addresses and fields of these.
+*!
+*!**************************************************************************/
+
+#ifndef __sv_addr_ag_h__
+#define __sv_addr_ag_h__
+
+
+#define __test_sv_addr__ 0
+
+/*------------------------------------------------------------
+!* General macros to manipulate moderegisters.
+!*-----------------------------------------------------------*/
+
+/* IO_MASK returns a mask for a specified bitfield in a register.
+   Note that this macro doesn't work when field width is 32 bits. */
+#define IO_MASK(reg, field) IO_MASK_ (reg##_, field##_)
+#define IO_MASK_(reg_, field_) \
+    ( ( ( 1 << reg_##_##field_##_WIDTH ) - 1 ) << reg_##_##field_##_BITNR )
+
+/* IO_STATE returns a constant corresponding to a one of the symbolic
+   states that the bitfield can have. (Shifted to correct position)  */
+#define IO_STATE(reg, field, state) IO_STATE_ (reg##_, field##_, _##state)
+#define IO_STATE_(reg_, field_, _state) \
+    ( reg_##_##field_##_state << reg_##_##field_##_BITNR )
+
+/* IO_EXTRACT returns the masked and shifted value corresponding to the
+   bitfield can have. */
+#define IO_EXTRACT(reg, field, val) IO_EXTRACT_ (reg##_, field##_, val)
+#define IO_EXTRACT_(reg_, field_, val) ( (( ( ( 1 << reg_##_##field_##_WIDTH ) \
+     - 1 ) << reg_##_##field_##_BITNR ) & (val)) >> reg_##_##field_##_BITNR )
+
+/* IO_STATE_VALUE returns a constant corresponding to a one of the symbolic
+   states that the bitfield can have. (Not shifted)  */
+#define IO_STATE_VALUE(reg, field, state) \
+    IO_STATE_VALUE_ (reg##_, field##_, _##state)
+#define IO_STATE_VALUE_(reg_, field_, _state) ( reg_##_##field_##_state )
+
+/* IO_FIELD shifts the val parameter to be aligned with the bitfield
+   specified. */
+#define IO_FIELD(reg, field, val) IO_FIELD_ (reg##_, field##_, val)
+#define IO_FIELD_(reg_, field_, val) ((val) << reg_##_##field_##_BITNR)
+
+/* IO_BITNR returns the starting bitnumber of a bitfield. Bit 0 is
+   LSB and the returned bitnumber is LSB of the field. */
+#define IO_BITNR(reg, field) IO_BITNR_ (reg##_, field##_)
+#define IO_BITNR_(reg_, field_) (reg_##_##field_##_BITNR)
+
+/* IO_WIDTH returns the width, in bits, of a bitfield. */
+#define IO_WIDTH(reg, field) IO_WIDTH_ (reg##_, field##_)
+#define IO_WIDTH_(reg_, field_) (reg_##_##field_##_WIDTH)
+
+/*--- Obsolete. Kept for backw compatibility. ---*/
+/* Reads (or writes) a byte/uword/udword from the specified mode
+   register. */
+#define IO_RD(reg) (*(volatile u32*)(reg))
+#define IO_RD_B(reg) (*(volatile u8*)(reg))
+#define IO_RD_W(reg) (*(volatile u16*)(reg))
+#define IO_RD_D(reg) (*(volatile u32*)(reg))
+
+/*------------------------------------------------------------
+!* Start addresses of the different memory areas.
+!*-----------------------------------------------------------*/
+
+#define MEM_CSE0_START (0x00000000)
+#define MEM_CSE0_SIZE (0x04000000)
+#define MEM_CSE1_START (0x04000000)
+#define MEM_CSE1_SIZE (0x04000000)
+#define MEM_CSR0_START (0x08000000)
+#define MEM_CSR1_START (0x0c000000)
+#define MEM_CSP0_START (0x10000000)
+#define MEM_CSP1_START (0x14000000)
+#define MEM_CSP2_START (0x18000000)
+#define MEM_CSP3_START (0x1c000000)
+#define MEM_CSP4_START (0x20000000)
+#define MEM_CSP5_START (0x24000000)
+#define MEM_CSP6_START (0x28000000)
+#define MEM_CSP7_START (0x2c000000)
+#define MEM_DRAM_START (0x40000000)
+
+#define MEM_NON_CACHEABLE (0x80000000)
+
+/*------------------------------------------------------------
+!* Type casts used in mode register macros, making pointer
+!* dereferencing possible. Empty in assembler.
+!*-----------------------------------------------------------*/
+
+#ifndef __ASSEMBLER__
+# define  IO_TYPECAST_UDWORD  (volatile u32*)
+# define  IO_TYPECAST_RO_UDWORD  (const volatile u32*)
+# define  IO_TYPECAST_UWORD  (volatile u16*)
+# define  IO_TYPECAST_RO_UWORD  (const volatile u16*)
+# define  IO_TYPECAST_BYTE  (volatile u8*)
+# define  IO_TYPECAST_RO_BYTE  (const volatile u8*)
+#else
+# define  IO_TYPECAST_UDWORD
+# define  IO_TYPECAST_RO_UDWORD
+# define  IO_TYPECAST_UWORD
+# define  IO_TYPECAST_RO_UWORD
+# define  IO_TYPECAST_BYTE
+# define  IO_TYPECAST_RO_BYTE
+#endif
+
+/*------------------------------------------------------------*/
+
+#include <arch/sv_addr.agh>
+
+#if __test_sv_addr__
+/* IO_MASK( R_BUS_CONFIG , CE ) */
+IO_MASK( R_WAITSTATES , SRAM_WS )
+IO_MASK( R_TEST , W32 )
+
+IO_STATE( R_BUS_CONFIG, CE, DISABLE )
+IO_STATE( R_BUS_CONFIG, CE, ENABLE )
+
+IO_STATE( R_DRAM_TIMING, REF, IVAL2 )
+
+IO_MASK( R_DRAM_TIMING, REF )
+
+IO_MASK( R_EXT_DMA_0_STAT, TFR_COUNT ) >> IO_BITNR( R_EXT_DMA_0_STAT, TFR_COUNT )
+
+IO_RD(R_EXT_DMA_0_STAT) & IO_MASK( R_EXT_DMA_0_STAT, S ) 
+   == IO_STATE( R_EXT_DMA_0_STAT, S, STARTED )
+#endif
+
+
+#endif  /* ifndef __sv_addr_ag_h__ */
+
diff --git a/arch/cris/include/uapi/arch-v10/arch/svinto.h b/arch/cris/include/uapi/arch-v10/arch/svinto.h
new file mode 100644
index 0000000..da5c152
--- /dev/null
+++ b/arch/cris/include/uapi/arch-v10/arch/svinto.h
@@ -0,0 +1,64 @@
+#ifndef _ASM_CRIS_SVINTO_H
+#define _ASM_CRIS_SVINTO_H
+
+#include <arch/sv_addr_ag.h>
+
+extern unsigned int genconfig_shadow; /* defined and set in head.S */
+
+/* dma stuff */
+
+enum {                          /* Available in:  */
+	d_eol      = (1 << 0),  /* flags          */
+	d_eop      = (1 << 1),  /* flags & status */
+	d_wait     = (1 << 2),  /* flags          */
+	d_int      = (1 << 3),  /* flags          */
+	d_txerr    = (1 << 4),  /* flags          */
+	d_stop     = (1 << 4),  /*         status */
+	d_ecp      = (1 << 4),  /* flags & status */
+	d_pri      = (1 << 5),  /* flags & status */
+	d_alignerr = (1 << 6),  /*         status */
+	d_crcerr   = (1 << 7)   /*         status */
+};
+
+/* Do remember that DMA does not go through the MMU and needs
+ * a real physical address, not an address virtually mapped or
+ * paged. Therefore the buf/next ptrs below are unsigned long instead
+ * of void * to give a warning if you try to put a pointer directly
+ * to them instead of going through virt_to_phys/phys_to_virt.
+ */
+
+typedef struct etrax_dma_descr {
+	unsigned short sw_len;                /* 0-1 */
+	unsigned short ctrl;                  /* 2-3 */
+	unsigned long  next;                  /* 4-7 */
+	unsigned long  buf;                   /* 8-11 */
+	unsigned short hw_len;                /* 12-13 */
+	unsigned char  status;                /* 14 */
+	unsigned char  fifo_len;              /* 15 */
+} etrax_dma_descr;
+
+
+/* Use this for constant numbers only */
+#define RESET_DMA_NUM( n ) \
+  *R_DMA_CH##n##_CMD = IO_STATE( R_DMA_CH0_CMD, cmd, reset )
+
+/* Use this for constant numbers or symbols, 
+ * having two macros makes it possible to use constant expressions. 
+ */
+#define RESET_DMA( n ) RESET_DMA_NUM( n )
+
+
+/* Use this for constant numbers only */
+#define WAIT_DMA_NUM( n ) \
+  while( (*R_DMA_CH##n##_CMD & IO_MASK( R_DMA_CH0_CMD, cmd )) != \
+         IO_STATE( R_DMA_CH0_CMD, cmd, hold ) )
+
+/* Use this for constant numbers or symbols 
+ * having two macros makes it possible to use constant expressions. 
+ */
+#define WAIT_DMA( n ) WAIT_DMA_NUM( n )
+
+extern void prepare_rx_descriptor(struct etrax_dma_descr *desc);
+extern void flush_etrax_cache(void);
+
+#endif
diff --git a/arch/cris/include/uapi/arch-v10/arch/user.h b/arch/cris/include/uapi/arch-v10/arch/user.h
new file mode 100644
index 0000000..9303ea7
--- /dev/null
+++ b/arch/cris/include/uapi/arch-v10/arch/user.h
@@ -0,0 +1,46 @@
+#ifndef __ASM_CRIS_ARCH_USER_H
+#define __ASM_CRIS_ARCH_USER_H
+
+/* User mode registers, used for core dumps. In order to keep ELF_NGREG
+   sensible we let all registers be 32 bits. The csr registers are included
+   for future use. */
+struct user_regs_struct {
+        unsigned long r0;       /* General registers. */
+        unsigned long r1;
+        unsigned long r2;
+        unsigned long r3;
+        unsigned long r4;
+        unsigned long r5;
+        unsigned long r6;
+        unsigned long r7;
+        unsigned long r8;
+        unsigned long r9;
+        unsigned long r10;
+        unsigned long r11;
+        unsigned long r12;
+        unsigned long r13;
+        unsigned long sp;       /* Stack pointer. */
+        unsigned long pc;       /* Program counter. */
+        unsigned long p0;       /* Constant zero (only 8 bits). */
+        unsigned long vr;       /* Version register (only 8 bits). */
+        unsigned long p2;       /* Reserved. */
+        unsigned long p3;       /* Reserved. */
+        unsigned long p4;       /* Constant zero (only 16 bits). */
+        unsigned long ccr;      /* Condition code register (only 16 bits). */
+        unsigned long p6;       /* Reserved. */
+        unsigned long mof;      /* Multiply overflow register. */
+        unsigned long p8;       /* Constant zero. */
+        unsigned long ibr;      /* Not accessible. */
+        unsigned long irp;      /* Not accessible. */
+        unsigned long srp;      /* Subroutine return pointer. */
+        unsigned long bar;      /* Not accessible. */
+        unsigned long dccr;     /* Dword condition code register. */
+        unsigned long brp;      /* Not accessible. */
+        unsigned long usp;      /* User-mode stack pointer. Same as sp when 
+                                   in user mode. */
+        unsigned long csrinstr; /* Internal status registers. */
+        unsigned long csraddr;
+        unsigned long csrdata;
+};
+
+#endif
diff --git a/arch/cris/include/uapi/arch-v32/arch/Kbuild b/arch/cris/include/uapi/arch-v32/arch/Kbuild
index aafaa5a..59efffd 100644
--- a/arch/cris/include/uapi/arch-v32/arch/Kbuild
+++ b/arch/cris/include/uapi/arch-v32/arch/Kbuild
@@ -1 +1,3 @@
 # UAPI Header export list
+header-y += cryptocop.h
+header-y += user.h
diff --git a/arch/cris/include/uapi/arch-v32/arch/cryptocop.h b/arch/cris/include/uapi/arch-v32/arch/cryptocop.h
new file mode 100644
index 0000000..694fd13
--- /dev/null
+++ b/arch/cris/include/uapi/arch-v32/arch/cryptocop.h
@@ -0,0 +1,122 @@
+/*
+ * The device /dev/cryptocop is accessible using this driver using
+ * CRYPTOCOP_MAJOR (254) and minor number 0.
+ */
+
+#ifndef _UAPICRYPTOCOP_H
+#define _UAPICRYPTOCOP_H
+
+#include <linux/uio.h>
+
+
+#define CRYPTOCOP_SESSION_ID_NONE (0)
+
+typedef unsigned long long int cryptocop_session_id;
+
+/* cryptocop ioctls */
+#define ETRAXCRYPTOCOP_IOCTYPE         (250)
+
+#define CRYPTOCOP_IO_CREATE_SESSION    _IOWR(ETRAXCRYPTOCOP_IOCTYPE, 1, struct strcop_session_op)
+#define CRYPTOCOP_IO_CLOSE_SESSION     _IOW(ETRAXCRYPTOCOP_IOCTYPE, 2, struct strcop_session_op)
+#define CRYPTOCOP_IO_PROCESS_OP        _IOWR(ETRAXCRYPTOCOP_IOCTYPE, 3, struct strcop_crypto_op)
+#define CRYPTOCOP_IO_MAXNR             (3)
+
+typedef enum {
+	cryptocop_cipher_des = 0,
+	cryptocop_cipher_3des = 1,
+	cryptocop_cipher_aes = 2,
+	cryptocop_cipher_m2m = 3, /* mem2mem is essentially a NULL cipher with blocklength=1 */
+	cryptocop_cipher_none
+} cryptocop_cipher_type;
+
+typedef enum {
+	cryptocop_digest_sha1 = 0,
+	cryptocop_digest_md5 = 1,
+	cryptocop_digest_none
+} cryptocop_digest_type;
+
+typedef enum {
+	cryptocop_csum_le = 0,
+	cryptocop_csum_be = 1,
+	cryptocop_csum_none
+} cryptocop_csum_type;
+
+typedef enum {
+	cryptocop_cipher_mode_ecb = 0,
+	cryptocop_cipher_mode_cbc,
+	cryptocop_cipher_mode_none
+} cryptocop_cipher_mode;
+
+typedef enum {
+	cryptocop_3des_eee = 0,
+	cryptocop_3des_eed = 1,
+	cryptocop_3des_ede = 2,
+	cryptocop_3des_edd = 3,
+	cryptocop_3des_dee = 4,
+	cryptocop_3des_ded = 5,
+	cryptocop_3des_dde = 6,
+	cryptocop_3des_ddd = 7
+} cryptocop_3des_mode;
+
+/* Usermode accessible (ioctl) operations. */
+struct strcop_session_op{
+	cryptocop_session_id    ses_id;
+
+	cryptocop_cipher_type   cipher; /* AES, DES, 3DES, m2m, none */
+
+	cryptocop_cipher_mode   cmode; /* ECB, CBC, none */
+	cryptocop_3des_mode     des3_mode;
+
+	cryptocop_digest_type   digest; /* MD5, SHA1, none */
+
+	cryptocop_csum_type     csum;   /* BE, LE, none */
+
+	unsigned char           *key;
+	size_t                  keylen;
+};
+
+#define CRYPTOCOP_CSUM_LENGTH         (2)
+#define CRYPTOCOP_MAX_DIGEST_LENGTH   (20)  /* SHA-1 20, MD5 16 */
+#define CRYPTOCOP_MAX_IV_LENGTH       (16)  /* (3)DES==8, AES == 16 */
+#define CRYPTOCOP_MAX_KEY_LENGTH      (32)
+
+struct strcop_crypto_op{
+	cryptocop_session_id ses_id;
+
+	/* Indata. */
+	unsigned char            *indata;
+	size_t                   inlen; /* Total indata length. */
+
+	/* Cipher configuration. */
+	unsigned char            do_cipher:1;
+	unsigned char            decrypt:1; /* 1 == decrypt, 0 == encrypt */
+	unsigned char            cipher_explicit:1;
+	size_t                   cipher_start;
+	size_t                   cipher_len;
+	/* cipher_iv is used if do_cipher and cipher_explicit and the cipher
+	   mode is CBC.  The length is controlled by the type of cipher,
+	   e.g. DES/3DES 8 octets and AES 16 octets. */
+	unsigned char            cipher_iv[CRYPTOCOP_MAX_IV_LENGTH];
+	/* Outdata. */
+	unsigned char            *cipher_outdata;
+	size_t                   cipher_outlen;
+
+	/* digest configuration. */
+	unsigned char            do_digest:1;
+	size_t                   digest_start;
+	size_t                   digest_len;
+	/* Outdata.  The actual length is determined by the type of the digest. */
+	unsigned char            digest[CRYPTOCOP_MAX_DIGEST_LENGTH];
+
+	/* Checksum configuration. */
+	unsigned char            do_csum:1;
+	size_t                   csum_start;
+	size_t                   csum_len;
+	/* Outdata. */
+	unsigned char            csum[CRYPTOCOP_CSUM_LENGTH];
+};
+
+
+
+
+#endif /* _UAPICRYPTOCOP_H */
diff --git a/arch/cris/include/uapi/arch-v32/arch/user.h b/arch/cris/include/uapi/arch-v32/arch/user.h
new file mode 100644
index 0000000..03fa1f3
--- /dev/null
+++ b/arch/cris/include/uapi/arch-v32/arch/user.h
@@ -0,0 +1,41 @@
+#ifndef _ASM_CRIS_ARCH_USER_H
+#define _ASM_CRIS_ARCH_USER_H
+
+/* User-mode register used for core dumps. */
+
+struct user_regs_struct {
+	unsigned long r0;	/* General registers. */
+	unsigned long r1;
+	unsigned long r2;
+	unsigned long r3;
+	unsigned long r4;
+	unsigned long r5;
+	unsigned long r6;
+	unsigned long r7;
+	unsigned long r8;
+	unsigned long r9;
+	unsigned long r10;
+	unsigned long r11;
+	unsigned long r12;
+	unsigned long r13;
+	unsigned long sp;	/* R14, Stack pointer. */
+	unsigned long acr;	/* R15, Address calculation register. */
+	unsigned long bz;	/* P0, Constant zero (8-bits). */
+	unsigned long vr;	/* P1, Version register (8-bits). */
+	unsigned long pid;	/* P2, Process ID (8-bits). */
+	unsigned long srs;	/* P3, Support register select (8-bits). */
+	unsigned long wz;	/* P4, Constant zero (16-bits). */
+	unsigned long exs;	/* P5, Exception status. */
+	unsigned long eda;	/* P6, Exception data address. */
+	unsigned long mof;	/* P7, Multiply overflow regiter. */
+	unsigned long dz;	/* P8, Constant zero (32-bits). */
+	unsigned long ebp;	/* P9, Exception base pointer. */
+	unsigned long erp;	/* P10, Exception return pointer. */
+	unsigned long srp;	/* P11, Subroutine return pointer. */
+	unsigned long nrp;	/* P12, NMI return pointer. */
+	unsigned long ccs;	/* P13, Condition code stack. */
+	unsigned long usp;	/* P14, User mode stack pointer. */
+	unsigned long spc;	/* P15, Single step PC. */
+};
+
+#endif /* _ASM_CRIS_ARCH_USER_H */
diff --git a/arch/cris/include/uapi/asm/Kbuild b/arch/cris/include/uapi/asm/Kbuild
index f50236a..7d47b36 100644
--- a/arch/cris/include/uapi/asm/Kbuild
+++ b/arch/cris/include/uapi/asm/Kbuild
@@ -3,3 +3,37 @@ include include/uapi/asm-generic/Kbuild.asm
 
 header-y += arch-v10/
 header-y += arch-v32/
+header-y += auxvec.h
+header-y += bitsperlong.h
+header-y += byteorder.h
+header-y += errno.h
+header-y += ethernet.h
+header-y += etraxgpio.h
+header-y += fcntl.h
+header-y += ioctl.h
+header-y += ioctls.h
+header-y += ipcbuf.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 += rs485.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 += sync_serial.h
+header-y += termbits.h
+header-y += termios.h
+header-y += types.h
+header-y += unistd.h
diff --git a/arch/cris/include/uapi/asm/auxvec.h b/arch/cris/include/uapi/asm/auxvec.h
new file mode 100644
index 0000000..cb30b01
--- /dev/null
+++ b/arch/cris/include/uapi/asm/auxvec.h
@@ -0,0 +1,4 @@
+#ifndef __ASMCRIS_AUXVEC_H
+#define __ASMCRIS_AUXVEC_H
+
+#endif
diff --git a/arch/cris/include/uapi/asm/bitsperlong.h b/arch/cris/include/uapi/asm/bitsperlong.h
new file mode 100644
index 0000000..6dc0bb0
--- /dev/null
+++ b/arch/cris/include/uapi/asm/bitsperlong.h
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff --git a/arch/cris/include/uapi/asm/byteorder.h b/arch/cris/include/uapi/asm/byteorder.h
new file mode 100644
index 0000000..bcd1897
--- /dev/null
+++ b/arch/cris/include/uapi/asm/byteorder.h
@@ -0,0 +1,8 @@
+#ifndef _CRIS_BYTEORDER_H
+#define _CRIS_BYTEORDER_H
+
+#include <linux/byteorder/little_endian.h>
+
+#endif
+
+
diff --git a/arch/cris/include/uapi/asm/errno.h b/arch/cris/include/uapi/asm/errno.h
new file mode 100644
index 0000000..2bf5eb5
--- /dev/null
+++ b/arch/cris/include/uapi/asm/errno.h
@@ -0,0 +1,6 @@
+#ifndef _CRIS_ERRNO_H
+#define _CRIS_ERRNO_H
+
+#include <asm-generic/errno.h>
+
+#endif
diff --git a/arch/cris/include/uapi/asm/ethernet.h b/arch/cris/include/uapi/asm/ethernet.h
new file mode 100644
index 0000000..4d58652
--- /dev/null
+++ b/arch/cris/include/uapi/asm/ethernet.h
@@ -0,0 +1,21 @@
+/*  
+ * ioctl defines for ethernet driver
+ *
+ * Copyright (c) 2001 Axis Communications AB
+ * 
+ * Author: Mikael Starvik 
+ *
+ */
+
+#ifndef _CRIS_ETHERNET_H
+#define _CRIS_ETHERNET_H
+#define SET_ETH_SPEED_AUTO      SIOCDEVPRIVATE          /* Auto neg speed */
+#define SET_ETH_SPEED_10        SIOCDEVPRIVATE+1        /* 10 Mbps */
+#define SET_ETH_SPEED_100       SIOCDEVPRIVATE+2        /* 100 Mbps. */
+#define SET_ETH_DUPLEX_AUTO     SIOCDEVPRIVATE+3        /* Auto neg duplex */
+#define SET_ETH_DUPLEX_HALF     SIOCDEVPRIVATE+4        /* Full duplex */
+#define SET_ETH_DUPLEX_FULL     SIOCDEVPRIVATE+5        /* Half duplex */
+#define SET_ETH_ENABLE_LEDS     SIOCDEVPRIVATE+6        /* Enable net LEDs */
+#define SET_ETH_DISABLE_LEDS    SIOCDEVPRIVATE+7        /* Disable net LEDs */
+#define SET_ETH_AUTONEG         SIOCDEVPRIVATE+8
+#endif /* _CRIS_ETHERNET_H */
diff --git a/arch/cris/include/uapi/asm/etraxgpio.h b/arch/cris/include/uapi/asm/etraxgpio.h
new file mode 100644
index 0000000..461c089
--- /dev/null
+++ b/arch/cris/include/uapi/asm/etraxgpio.h
@@ -0,0 +1,239 @@
+/*
+ * The following devices are accessible using this driver using
+ * GPIO_MAJOR (120) and a couple of minor numbers.
+ *
+ * For ETRAX 100LX (CONFIG_ETRAX_ARCH_V10):
+ * /dev/gpioa  minor 0, 8 bit GPIO, each bit can change direction
+ * /dev/gpiob  minor 1, 8 bit GPIO, each bit can change direction
+ * /dev/leds   minor 2, Access to leds depending on kernelconfig
+ * /dev/gpiog  minor 3
+ *       g0dir, g8_15dir, g16_23dir, g24 dir configurable in R_GEN_CONFIG
+ *       g1-g7 and g25-g31 is both input and outputs but on different pins
+ *       Also note that some bits change pins depending on what interfaces
+ *       are enabled.
+ *
+ * For ETRAX FS (CONFIG_ETRAXFS):
+ * /dev/gpioa  minor 0,  8 bit GPIO, each bit can change direction
+ * /dev/gpiob  minor 1, 18 bit GPIO, each bit can change direction
+ * /dev/gpioc  minor 3, 18 bit GPIO, each bit can change direction
+ * /dev/gpiod  minor 4, 18 bit GPIO, each bit can change direction
+ * /dev/gpioe  minor 5, 18 bit GPIO, each bit can change direction
+ * /dev/leds   minor 2, Access to leds depending on kernelconfig
+ *
+ * For ARTPEC-3 (CONFIG_CRIS_MACH_ARTPEC3):
+ * /dev/gpioa  minor 0, 32 bit GPIO, each bit can change direction
+ * /dev/gpiob  minor 1, 32 bit GPIO, each bit can change direction
+ * /dev/gpioc  minor 3, 16 bit GPIO, each bit can change direction
+ * /dev/gpiod  minor 4, 32 bit GPIO, input only
+ * /dev/leds   minor 2, Access to leds depending on kernelconfig
+ * /dev/pwm0   minor 16, PWM channel 0 on PA30
+ * /dev/pwm1   minor 17, PWM channel 1 on PA31
+ * /dev/pwm2   minor 18, PWM channel 2 on PB26
+ * /dev/ppwm   minor 19, PPWM channel
+ *
+ */
+#ifndef _ASM_ETRAXGPIO_H
+#define _ASM_ETRAXGPIO_H
+
+#define GPIO_MINOR_FIRST 0
+
+#define ETRAXGPIO_IOCTYPE 43
+
+/* etraxgpio _IOC_TYPE, bits 8 to 15 in ioctl cmd */
+#ifdef CONFIG_ETRAX_ARCH_V10
+#define GPIO_MINOR_A 0
+#define GPIO_MINOR_B 1
+#define GPIO_MINOR_LEDS 2
+#define GPIO_MINOR_G 3
+#define GPIO_MINOR_LAST 3
+#define GPIO_MINOR_LAST_REAL GPIO_MINOR_LAST
+#endif
+
+#ifdef CONFIG_ETRAXFS
+#define GPIO_MINOR_A 0
+#define GPIO_MINOR_B 1
+#define GPIO_MINOR_LEDS 2
+#define GPIO_MINOR_C 3
+#define GPIO_MINOR_D 4
+#define GPIO_MINOR_E 5
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+#define GPIO_MINOR_V 6
+#define GPIO_MINOR_LAST 6
+#else
+#define GPIO_MINOR_LAST 5
+#endif
+#define GPIO_MINOR_LAST_REAL GPIO_MINOR_LAST
+#endif
+
+#ifdef CONFIG_CRIS_MACH_ARTPEC3
+#define GPIO_MINOR_A 0
+#define GPIO_MINOR_B 1
+#define GPIO_MINOR_LEDS 2
+#define GPIO_MINOR_C 3
+#define GPIO_MINOR_D 4
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+#define GPIO_MINOR_V 6
+#define GPIO_MINOR_LAST 6
+#else
+#define GPIO_MINOR_LAST 4
+#endif
+#define GPIO_MINOR_FIRST_PWM 16
+#define GPIO_MINOR_PWM0 (GPIO_MINOR_FIRST_PWM+0)
+#define GPIO_MINOR_PWM1 (GPIO_MINOR_FIRST_PWM+1)
+#define GPIO_MINOR_PWM2 (GPIO_MINOR_FIRST_PWM+2)
+#define GPIO_MINOR_PPWM (GPIO_MINOR_FIRST_PWM+3)
+#define GPIO_MINOR_LAST_PWM GPIO_MINOR_PPWM
+#define GPIO_MINOR_LAST_REAL GPIO_MINOR_LAST_PWM
+#endif
+
+
+
+/* supported ioctl _IOC_NR's */
+
+#define IO_READBITS  0x1  /* read and return current port bits (obsolete) */
+#define IO_SETBITS   0x2  /* set the bits marked by 1 in the argument */
+#define IO_CLRBITS   0x3  /* clear the bits marked by 1 in the argument */
+
+/* the alarm is waited for by select() */
+
+#define IO_HIGHALARM 0x4  /* set alarm on high for bits marked by 1 */
+#define IO_LOWALARM  0x5  /* set alarm on low for bits marked by 1 */
+#define IO_CLRALARM  0x6  /* clear alarm for bits marked by 1 */
+
+/* LED ioctl */
+#define IO_LEDACTIVE_SET 0x7 /* set active led
+                              * 0=off, 1=green, 2=red, 3=yellow */
+
+/* GPIO direction ioctl's */
+#define IO_READDIR    0x8  /* Read direction 0=input 1=output  (obsolete) */
+#define IO_SETINPUT   0x9  /* Set direction for bits set, 0=unchanged 1=input,
+                              returns mask with current inputs (obsolete) */
+#define IO_SETOUTPUT  0xA  /* Set direction for bits set, 0=unchanged 1=output,
+                              returns mask with current outputs (obsolete)*/
+
+/* LED ioctl extended */
+#define IO_LED_SETBIT 0xB
+#define IO_LED_CLRBIT 0xC
+
+/* SHUTDOWN ioctl */
+#define IO_SHUTDOWN   0xD
+#define IO_GET_PWR_BT 0xE
+
+/* Bit toggling in driver settings */
+/* bit set in low byte0 is CLK mask (0x00FF),
+   bit set in byte1 is DATA mask    (0xFF00)
+   msb, data_mask[7:0] , clk_mask[7:0]
+ */
+#define IO_CFG_WRITE_MODE 0xF
+#define IO_CFG_WRITE_MODE_VALUE(msb, data_mask, clk_mask) \
+	( (((msb)&1) << 16) | (((data_mask) &0xFF) << 8) | ((clk_mask) & 0xFF) )
+
+/* The following 4 ioctl's take a pointer as argument and handles
+ * 32 bit ports (port G) properly.
+ * These replaces IO_READBITS,IO_SETINPUT AND IO_SETOUTPUT
+ */
+#define IO_READ_INBITS   0x10 /* *arg is result of reading the input pins */
+#define IO_READ_OUTBITS  0x11 /* *arg is result of reading the output shadow */
+#define IO_SETGET_INPUT  0x12 /* bits set in *arg is set to input, */
+			      /* *arg updated with current input pins. */
+#define IO_SETGET_OUTPUT 0x13 /* bits set in *arg is set to output, */
+			      /* *arg updated with current output pins. */
+
+/* The following ioctl's are applicable to the PWM channels only */
+
+#define IO_PWM_SET_MODE     0x20
+
+enum io_pwm_mode {
+	PWM_OFF = 0,		/* disabled, deallocated */
+	PWM_STANDARD = 1,	/* 390 kHz, duty cycle 0..255/256 */
+	PWM_FAST = 2,		/* variable freq, w/ 10ns active pulse len */
+	PWM_VARFREQ = 3,	/* individually configurable high/low periods */
+	PWM_SOFT = 4		/* software generated */
+};
+
+struct io_pwm_set_mode {
+	enum io_pwm_mode mode;
+};
+
+/* Only for mode PWM_VARFREQ. Period lo/high set in increments of 10ns
+ * from 10ns (value = 0) to 81920ns (value = 8191)
+ * (Resulting frequencies range from 50 MHz (10ns + 10ns) down to
+ * 6.1 kHz (81920ns + 81920ns) at 50% duty cycle, to 12.2 kHz at min/max duty
+ * cycle (81920 + 10ns or 10ns + 81920ns, respectively).)
+ */
+#define IO_PWM_SET_PERIOD   0x21
+
+struct io_pwm_set_period {
+	unsigned int lo;		/* 0..8191 */
+	unsigned int hi;		/* 0..8191 */
+};
+
+/* Only for modes PWM_STANDARD and PWM_FAST.
+ * For PWM_STANDARD, set duty cycle of 390 kHz PWM output signal, from
+ * 0 (value = 0) to 255/256 (value = 255).
+ * For PWM_FAST, set duty cycle of PWM output signal from
+ * 0% (value = 0) to 100% (value = 255). Output signal in this mode
+ * is a 10ns pulse surrounded by a high or low level depending on duty
+ * cycle (except for 0% and 100% which result in a constant output).
+ * Resulting output frequency varies from 50 MHz at 50% duty cycle,
+ * down to 390 kHz at min/max duty cycle.
+ */
+#define IO_PWM_SET_DUTY     0x22
+
+struct io_pwm_set_duty {
+	int duty;		/* 0..255 */
+};
+
+/* Returns information about the latest PWM pulse.
+ * lo: Length of the latest low period, in units of 10ns.
+ * hi: Length of the latest high period, in units of 10ns.
+ * cnt: Time since last detected edge, in units of 10ns.
+ *
+ * The input source to PWM is decied by IO_PWM_SET_INPUT_SRC.
+ *
+ * NOTE: All PWM devices is connected to the same input source.
+ */
+#define IO_PWM_GET_PERIOD   0x23
+
+struct io_pwm_get_period {
+	unsigned int lo;
+	unsigned int hi;
+	unsigned int cnt;
+};
+
+/* Sets the input source for the PWM input. For the src value see the
+ * register description for gio:rw_pwm_in_cfg.
+ *
+ * NOTE: All PWM devices is connected to the same input source.
+ */
+#define IO_PWM_SET_INPUT_SRC   0x24
+struct io_pwm_set_input_src {
+	unsigned int src;	/* 0..7 */
+};
+
+/* Sets the duty cycles in steps of 1/256, 0 = 0%, 255 = 100% duty cycle */
+#define IO_PPWM_SET_DUTY     0x25
+
+struct io_ppwm_set_duty {
+	int duty;		/* 0..255 */
+};
+
+/* Configuraton struct for the IO_PWMCLK_SET_CONFIG ioctl to configure
+ * PWM capable gpio pins:
+ */
+#define IO_PWMCLK_SETGET_CONFIG 0x26
+struct gpio_pwmclk_conf {
+  unsigned int gpiopin; /* The pin number based on the opened device */
+  unsigned int baseclk; /* The base clock to use, or sw will select one close*/
+  unsigned int low;     /* The number of low periods of the baseclk */
+  unsigned int high;    /* The number of high periods of the baseclk */
+};
+
+/* Examples:
+ * To get a symmetric 12 MHz clock without knowing anything about the hardware:
+ * baseclk = 12000000, low = 0, high = 0
+ * To just get info of current setting:
+ * baseclk = 0, low = 0, high = 0, the values will be updated by driver.
+ */
+
+#endif
diff --git a/arch/cris/include/uapi/asm/fcntl.h b/arch/cris/include/uapi/asm/fcntl.h
new file mode 100644
index 0000000..46ab12d
--- /dev/null
+++ b/arch/cris/include/uapi/asm/fcntl.h
@@ -0,0 +1 @@
+#include <asm-generic/fcntl.h>
diff --git a/arch/cris/include/uapi/asm/ioctl.h b/arch/cris/include/uapi/asm/ioctl.h
new file mode 100644
index 0000000..b279fe0
--- /dev/null
+++ b/arch/cris/include/uapi/asm/ioctl.h
@@ -0,0 +1 @@
+#include <asm-generic/ioctl.h>
diff --git a/arch/cris/include/uapi/asm/ioctls.h b/arch/cris/include/uapi/asm/ioctls.h
new file mode 100644
index 0000000..488fbb3
--- /dev/null
+++ b/arch/cris/include/uapi/asm/ioctls.h
@@ -0,0 +1,11 @@
+#ifndef __ARCH_CRIS_IOCTLS_H__
+#define __ARCH_CRIS_IOCTLS_H__
+
+#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
+#define TIOCSERSETRS485	0x5461  /* enable rs-485 (deprecated) */
+#define TIOCSERWRRS485	0x5462  /* write rs-485 */
+#define TIOCSRS485	0x5463  /* enable rs-485 */
+
+#include <asm-generic/ioctls.h>
+
+#endif
diff --git a/arch/cris/include/uapi/asm/ipcbuf.h b/arch/cris/include/uapi/asm/ipcbuf.h
new file mode 100644
index 0000000..84c7e51
--- /dev/null
+++ b/arch/cris/include/uapi/asm/ipcbuf.h
@@ -0,0 +1 @@
+#include <asm-generic/ipcbuf.h>
diff --git a/arch/cris/include/uapi/asm/mman.h b/arch/cris/include/uapi/asm/mman.h
new file mode 100644
index 0000000..8eebf89
--- /dev/null
+++ b/arch/cris/include/uapi/asm/mman.h
@@ -0,0 +1 @@
+#include <asm-generic/mman.h>
diff --git a/arch/cris/include/uapi/asm/msgbuf.h b/arch/cris/include/uapi/asm/msgbuf.h
new file mode 100644
index 0000000..ada63df
--- /dev/null
+++ b/arch/cris/include/uapi/asm/msgbuf.h
@@ -0,0 +1,33 @@
+#ifndef _CRIS_MSGBUF_H
+#define _CRIS_MSGBUF_H
+
+/* verbatim copy of asm-i386 version */
+
+/* 
+ * The msqid64_ds structure for CRIS 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 /* _CRIS_MSGBUF_H */
diff --git a/arch/cris/include/uapi/asm/param.h b/arch/cris/include/uapi/asm/param.h
new file mode 100644
index 0000000..484fcf8
--- /dev/null
+++ b/arch/cris/include/uapi/asm/param.h
@@ -0,0 +1,10 @@
+#ifndef _ASMCRIS_PARAM_H
+#define _ASMCRIS_PARAM_H
+
+/* Currently we assume that HZ=100 is good for CRIS. */
+
+#define EXEC_PAGESIZE	8192
+
+#include <asm-generic/param.h>
+
+#endif /* _ASMCRIS_PARAM_H */
diff --git a/arch/cris/include/uapi/asm/poll.h b/arch/cris/include/uapi/asm/poll.h
new file mode 100644
index 0000000..c98509d
--- /dev/null
+++ b/arch/cris/include/uapi/asm/poll.h
@@ -0,0 +1 @@
+#include <asm-generic/poll.h>
diff --git a/arch/cris/include/uapi/asm/posix_types.h b/arch/cris/include/uapi/asm/posix_types.h
new file mode 100644
index 0000000..ce4e517
--- /dev/null
+++ b/arch/cris/include/uapi/asm/posix_types.h
@@ -0,0 +1,35 @@
+/* $Id: posix_types.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $ */
+
+/* We cheat a bit and use our C-coded bitops functions from asm/bitops.h */
+/* I guess we should write these in assembler because they are used often. */
+
+#ifndef __ARCH_CRIS_POSIX_TYPES_H
+#define __ARCH_CRIS_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 __SIZE_TYPE__	__kernel_size_t;
+typedef long		__kernel_ssize_t;
+typedef int		__kernel_ptrdiff_t;
+#define __kernel_size_t __kernel_size_t
+
+typedef unsigned short	__kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
+
+#include <asm-generic/posix_types.h>
+
+#endif /* __ARCH_CRIS_POSIX_TYPES_H */
diff --git a/arch/cris/include/uapi/asm/ptrace.h b/arch/cris/include/uapi/asm/ptrace.h
new file mode 100644
index 0000000..c689c9b
--- /dev/null
+++ b/arch/cris/include/uapi/asm/ptrace.h
@@ -0,0 +1 @@
+#include <arch/ptrace.h>
diff --git a/arch/cris/include/uapi/asm/resource.h b/arch/cris/include/uapi/asm/resource.h
new file mode 100644
index 0000000..b5d2944
--- /dev/null
+++ b/arch/cris/include/uapi/asm/resource.h
@@ -0,0 +1,6 @@
+#ifndef _CRIS_RESOURCE_H
+#define _CRIS_RESOURCE_H
+
+#include <asm-generic/resource.h>
+
+#endif
diff --git a/arch/cris/include/uapi/asm/rs485.h b/arch/cris/include/uapi/asm/rs485.h
new file mode 100644
index 0000000..ad40f9f
--- /dev/null
+++ b/arch/cris/include/uapi/asm/rs485.h
@@ -0,0 +1,18 @@
+/* RS-485 structures */
+
+/* Used with ioctl() TIOCSERSETRS485 for backward compatibility!
+ * XXX: Do not use it for new code!
+ */
+struct rs485_control {
+        unsigned short rts_on_send;
+        unsigned short rts_after_sent;
+        unsigned long delay_rts_before_send;
+        unsigned short enabled;
+};
+
+/* Used with ioctl() TIOCSERWRRS485 */
+struct rs485_write {
+        unsigned short outc_size;
+        unsigned char *outc;
+};
+
diff --git a/arch/cris/include/uapi/asm/sembuf.h b/arch/cris/include/uapi/asm/sembuf.h
new file mode 100644
index 0000000..7fed984
--- /dev/null
+++ b/arch/cris/include/uapi/asm/sembuf.h
@@ -0,0 +1,25 @@
+#ifndef _CRIS_SEMBUF_H
+#define _CRIS_SEMBUF_H
+
+/* 
+ * The semid64_ds structure for CRIS 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 /* _CRIS_SEMBUF_H */
diff --git a/arch/cris/include/uapi/asm/setup.h b/arch/cris/include/uapi/asm/setup.h
new file mode 100644
index 0000000..b907286
--- /dev/null
+++ b/arch/cris/include/uapi/asm/setup.h
@@ -0,0 +1,6 @@
+#ifndef _CRIS_SETUP_H
+#define _CRIS_SETUP_H
+
+#define COMMAND_LINE_SIZE	256
+
+#endif
diff --git a/arch/cris/include/uapi/asm/shmbuf.h b/arch/cris/include/uapi/asm/shmbuf.h
new file mode 100644
index 0000000..3239e3f
--- /dev/null
+++ b/arch/cris/include/uapi/asm/shmbuf.h
@@ -0,0 +1,42 @@
+#ifndef _CRIS_SHMBUF_H
+#define _CRIS_SHMBUF_H
+
+/* 
+ * The shmid64_ds structure for CRIS architecture (same as for i386)
+ * 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 /* _CRIS_SHMBUF_H */
diff --git a/arch/cris/include/uapi/asm/sigcontext.h b/arch/cris/include/uapi/asm/sigcontext.h
new file mode 100644
index 0000000..a1d634e
--- /dev/null
+++ b/arch/cris/include/uapi/asm/sigcontext.h
@@ -0,0 +1,24 @@
+/* $Id: sigcontext.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $ */
+
+#ifndef _ASM_CRIS_SIGCONTEXT_H
+#define _ASM_CRIS_SIGCONTEXT_H
+
+#include <asm/ptrace.h>
+
+/* This struct is saved by setup_frame in signal.c, to keep the current context while
+   a signal handler is executed. It's restored by sys_sigreturn.
+   
+   To keep things simple, we use pt_regs here even though normally you just specify
+   the list of regs to save. Then we can use copy_from_user on the entire regs instead
+   of a bunch of get_user's as well...
+
+*/
+
+struct sigcontext {
+	struct pt_regs regs;  /* needs to be first */
+	unsigned long oldmask;
+	unsigned long usp;    /* usp before stacking this gunk on it */
+};
+
+#endif
+
diff --git a/arch/cris/include/uapi/asm/siginfo.h b/arch/cris/include/uapi/asm/siginfo.h
new file mode 100644
index 0000000..c1cd6d1
--- /dev/null
+++ b/arch/cris/include/uapi/asm/siginfo.h
@@ -0,0 +1,6 @@
+#ifndef _CRIS_SIGINFO_H
+#define _CRIS_SIGINFO_H
+
+#include <asm-generic/siginfo.h>
+
+#endif
diff --git a/arch/cris/include/uapi/asm/signal.h b/arch/cris/include/uapi/asm/signal.h
new file mode 100644
index 0000000..2162494
--- /dev/null
+++ b/arch/cris/include/uapi/asm/signal.h
@@ -0,0 +1,122 @@
+#ifndef _UAPI_ASM_CRIS_SIGNAL_H
+#define _UAPI_ASM_CRIS_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	0x00000001u
+#define SA_NOCLDWAIT	0x00000002u
+#define SA_SIGINFO	0x00000004u
+#define SA_ONSTACK	0x08000000u
+#define SA_RESTART	0x10000000u
+#define SA_NODEFER	0x40000000u
+#define SA_RESETHAND	0x80000000u
+
+#define SA_NOMASK	SA_NODEFER
+#define SA_ONESHOT	SA_RESETHAND
+
+#define SA_RESTORER	0x04000000
+
+/* 
+ * sigaltstack controls
+ */
+#define SS_ONSTACK	1
+#define SS_DISABLE	2
+
+#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_ASM_CRIS_SIGNAL_H */
diff --git a/arch/cris/include/uapi/asm/socket.h b/arch/cris/include/uapi/asm/socket.h
new file mode 100644
index 0000000..b681b04
--- /dev/null
+++ b/arch/cris/include/uapi/asm/socket.h
@@ -0,0 +1,77 @@
+#ifndef _ASM_SOCKET_H
+#define _ASM_SOCKET_H
+
+/* almost the same as asm-i386/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
+/* To add :#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
+
+#endif /* _ASM_SOCKET_H */
+
+
diff --git a/arch/cris/include/uapi/asm/sockios.h b/arch/cris/include/uapi/asm/sockios.h
new file mode 100644
index 0000000..cfe7bfe
--- /dev/null
+++ b/arch/cris/include/uapi/asm/sockios.h
@@ -0,0 +1,13 @@
+#ifndef __ARCH_CRIS_SOCKIOS__
+#define __ARCH_CRIS_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
diff --git a/arch/cris/include/uapi/asm/stat.h b/arch/cris/include/uapi/asm/stat.h
new file mode 100644
index 0000000..9e558cc
--- /dev/null
+++ b/arch/cris/include/uapi/asm/stat.h
@@ -0,0 +1,81 @@
+#ifndef _CRIS_STAT_H
+#define _CRIS_STAT_H
+
+/* Keep this a verbatim copy of i386 version; tweak CRIS-specific bits in
+   the kernel if necessary.  */
+
+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;
+};
+
+#define STAT_HAVE_NSEC 1
+
+struct stat {
+	unsigned long  st_dev;
+	unsigned long  st_ino;
+	unsigned short st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+	unsigned long  st_rdev;
+	unsigned long  st_size;
+	unsigned long  st_blksize;
+	unsigned long  st_blocks;
+	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  __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	__pad0[4];
+
+#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[4];
+
+	long long	st_size;
+	unsigned long	st_blksize;
+
+	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
+	unsigned long	__pad4;		/* future possible st_blocks high bits */
+
+	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;	/* will be high 32 bits of ctime someday */
+
+	unsigned long long	st_ino;
+};
+
+#endif
diff --git a/arch/cris/include/uapi/asm/statfs.h b/arch/cris/include/uapi/asm/statfs.h
new file mode 100644
index 0000000..fdaf921
--- /dev/null
+++ b/arch/cris/include/uapi/asm/statfs.h
@@ -0,0 +1,6 @@
+#ifndef _CRIS_STATFS_H
+#define _CRIS_STATFS_H
+
+#include <asm-generic/statfs.h>
+
+#endif
diff --git a/arch/cris/include/uapi/asm/swab.h b/arch/cris/include/uapi/asm/swab.h
new file mode 100644
index 0000000..4adf1e9
--- /dev/null
+++ b/arch/cris/include/uapi/asm/swab.h
@@ -0,0 +1,3 @@
+/*
+ * CRIS byte swapping.
+ */
diff --git a/arch/cris/include/uapi/asm/sync_serial.h b/arch/cris/include/uapi/asm/sync_serial.h
new file mode 100644
index 0000000..7f827fe
--- /dev/null
+++ b/arch/cris/include/uapi/asm/sync_serial.h
@@ -0,0 +1,132 @@
+/*
+ * ioctl defines for synchronous serial port driver
+ *
+ * Copyright (c) 2001-2003 Axis Communications AB
+ *
+ * Author: Mikael Starvik
+ *
+ */
+
+#ifndef SYNC_SERIAL_H
+#define SYNC_SERIAL_H
+
+#include <linux/ioctl.h>
+
+#define SSP_SPEED      _IOR('S', 0, unsigned int)
+#define SSP_MODE       _IOR('S', 1, unsigned int)
+#define SSP_FRAME_SYNC _IOR('S', 2, unsigned int)
+#define SSP_IPOLARITY  _IOR('S', 3, unsigned int)
+#define SSP_OPOLARITY  _IOR('S', 4, unsigned int)
+#define SSP_SPI        _IOR('S', 5, unsigned int)
+#define SSP_INBUFCHUNK _IOR('S', 6, unsigned int)
+#define SSP_INPUT      _IOR('S', 7, unsigned int)
+
+/* Values for SSP_SPEED */
+#define SSP150        0
+#define SSP300        1
+#define SSP600        2
+#define SSP1200       3
+#define SSP2400       4
+#define SSP4800       5
+#define SSP9600       6
+#define SSP19200      7
+#define SSP28800      8
+#define SSP57600      9
+#define SSP115200    10
+#define SSP230400    11
+#define SSP460800    12
+#define SSP921600    13
+#define SSP3125000   14
+#define CODEC        15
+#define CODEC_f32768 16
+
+#define FREQ_4MHz   0
+#define FREQ_2MHz   1
+#define FREQ_1MHz   2
+#define FREQ_512kHz 3
+#define FREQ_256kHz 4
+#define FREQ_128kHz 5
+#define FREQ_64kHz  6
+#define FREQ_32kHz  7
+/* FREQ_* with values where bit (value & 0x10) is set are */
+/* used for CODEC_f32768 */
+#define FREQ_4096kHz 16 /* CODEC_f32768 */
+
+/* Used by application to set CODEC divider, word rate and frame rate */
+#define CODEC_VAL(freq, clk_per_sync, sync_per_frame) \
+	((CODEC + ((freq & 0x10) >> 4)) | (freq << 8) | \
+		   (clk_per_sync << 16) | (sync_per_frame << 28))
+
+/* Used by driver to extract speed */
+#define GET_SPEED(x) (x & 0xff)
+#define GET_FREQ(x) ((x & 0xff00) >> 8)
+#define GET_WORD_RATE(x) (((x & 0x0fff0000) >> 16) - 1)
+#define GET_FRAME_RATE(x) (((x & 0xf0000000) >> 28) - 1)
+
+/* Values for SSP_MODE */
+#define MASTER_OUTPUT 0
+#define SLAVE_OUTPUT  1
+#define MASTER_INPUT  2
+#define SLAVE_INPUT   3
+#define MASTER_BIDIR  4
+#define SLAVE_BIDIR   5
+
+/* Values for SSP_FRAME_SYNC */
+#define NORMAL_SYNC                1
+#define EARLY_SYNC                 2
+#define SECOND_WORD_SYNC     0x40000
+#define LATE_SYNC            0x80000
+
+#define BIT_SYNC                   4
+#define WORD_SYNC                  8
+#define EXTENDED_SYNC           0x10
+
+#define SYNC_OFF                0x20
+#define SYNC_ON                 0x40
+#define WORD_SIZE_8             0x80
+#define WORD_SIZE_12           0x100
+#define WORD_SIZE_16           0x200
+#define WORD_SIZE_24           0x400
+#define WORD_SIZE_32           0x800
+#define BIT_ORDER_LSB         0x1000
+#define BIT_ORDER_MSB         0x2000
+#define FLOW_CONTROL_ENABLE   0x4000
+#define FLOW_CONTROL_DISABLE  0x8000
+#define CLOCK_GATED          0x10000
+#define CLOCK_NOT_GATED      0x20000
+
+/* Values for SSP_IPOLARITY and SSP_OPOLARITY */
+#define CLOCK_NORMAL         1
+#define CLOCK_INVERT         2
+#define CLOCK_INEGEDGE       CLOCK_NORMAL
+#define CLOCK_IPOSEDGE       CLOCK_INVERT
+#define FRAME_NORMAL         4
+#define FRAME_INVERT         8
+#define STATUS_NORMAL      0x10
+#define STATUS_INVERT      0x20
+
+/* Values for SSP_SPI */
+#define SPI_MASTER           0
+#define SPI_SLAVE            1
+
+/* Values for SSP_INBUFCHUNK */
+/* plain integer with the size of DMA chunks */
+
+/* To ensure that the timestamps are aligned with the data being read
+ * the read length MUST be a multiple of the length of the DMA buffers.
+ *
+ * Use a multiple of SSP_INPUT_CHUNK_SIZE defined below.
+ */
+#define SSP_INPUT_CHUNK_SIZE  256
+
+/* Request struct to pass through the ioctl interface to read
+ * data with timestamps.
+ */
+struct ssp_request {
+	char __user *buf;	/* Where to put the data. */
+	size_t len;		/* Size of buf. MUST be a multiple of */
+				/* SSP_INPUT_CHUNK_SIZE! */
+	struct timespec ts;	/* The time the data was sampled. */
+};
+
+#endif
diff --git a/arch/cris/include/uapi/asm/termbits.h b/arch/cris/include/uapi/asm/termbits.h
new file mode 100644
index 0000000..1c43bc8
--- /dev/null
+++ b/arch/cris/include/uapi/asm/termbits.h
@@ -0,0 +1,235 @@
+/* $Id: termbits.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $ */
+
+#ifndef __ARCH_ETRAX100_TERMBITS_H__
+#define __ARCH_ETRAX100_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 */
+/*
+ *     3             2            1
+ *    10 987 654 321 098 765 432 109 876 543 210
+ *                             |           | ||| CBAUD
+ *                                         obaud    
+ *
+ *                                       ||CSIZE
+ *
+ *                                     |CSTOP
+ *                                    |CREAD
+ *                                   |CPARENB
+ *
+ *                                 |CPARODD 
+ *                                |HUPCL
+ *                               |CLOCAL
+ *                             |CBAUDEX
+ *    10 987 654 321 098 765 432 109 876 543 210
+ *        |           || ||   CIBAUD, IBSHIFT=16
+ *                    ibaud
+ *     |CMSPAR
+ *    | CRTSCTS
+ *       x x xxx xxx x     x xx Free bits
+ */
+
+#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
+
+/* Unsupported rates, but needed to avoid compile error. */
+#define   B500000 0010005
+#define   B576000 0010006
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
+
+/* etrax supports these additional three baud rates */
+#define  B921600   0010005
+#define  B1843200  0010006
+#define  B6250000  0010007
+/* ETRAX FS supports this as well */
+#define  B12500000 0010010
+#define CIBAUD	  002003600000	/* input baud rate (used in v32) */
+/* The values for CIBAUD bits are the same as the values for CBAUD and CBAUDEX
+ * shifted left IBSHIFT bits.
+ */
+#define IBSHIFT   16
+#define CMSPAR    010000000000 /* mark or space (stick) parity - PARODD=space*/
+#define CRTSCTS	  020000000000		/* flow control */
+
+/* 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
diff --git a/arch/cris/include/uapi/asm/termios.h b/arch/cris/include/uapi/asm/termios.h
new file mode 100644
index 0000000..0a0386a
--- /dev/null
+++ b/arch/cris/include/uapi/asm/termios.h
@@ -0,0 +1,45 @@
+#ifndef _UAPI_CRIS_TERMIOS_H
+#define _UAPI_CRIS_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+#include <asm/rs485.h>
+#include <linux/serial.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_CRIS_TERMIOS_H */
diff --git a/arch/cris/include/uapi/asm/types.h b/arch/cris/include/uapi/asm/types.h
new file mode 100644
index 0000000..9ec9d4c
--- /dev/null
+++ b/arch/cris/include/uapi/asm/types.h
@@ -0,0 +1 @@
+#include <asm-generic/int-ll64.h>
diff --git a/arch/cris/include/uapi/asm/unistd.h b/arch/cris/include/uapi/asm/unistd.h
new file mode 100644
index 0000000..4884289
--- /dev/null
+++ b/arch/cris/include/uapi/asm/unistd.h
@@ -0,0 +1,344 @@
+#ifndef _UAPI_ASM_CRIS_UNISTD_H_
+#define _UAPI_ASM_CRIS_UNISTD_H_
+
+/*
+ * This file contains the system call numbers, and stub macros for libc.
+ */
+
+#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_vm86		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_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	/* SuS compliant getrlimit */
+#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_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_utimensat		320
+#define __NR_signalfd		321
+#define __NR_timerfd_create	322
+#define __NR_eventfd		323
+#define __NR_fallocate		324
+#define __NR_timerfd_settime	325
+#define __NR_timerfd_gettime	326
+#define __NR_signalfd4		327
+#define __NR_eventfd2		328
+#define __NR_epoll_create1	329
+#define __NR_dup3		330
+#define __NR_pipe2		331
+#define __NR_inotify_init1	332
+#define __NR_preadv		333
+#define __NR_pwritev		334
+#define __NR_setns		335
+
+#endif /* _UAPI_ASM_CRIS_UNISTD_H_ */
diff --git a/arch/cris/kernel/asm-offsets.c b/arch/cris/kernel/asm-offsets.c
index dd7b8e9..a5fd88d 100644
--- a/arch/cris/kernel/asm-offsets.c
+++ b/arch/cris/kernel/asm-offsets.c
@@ -1,3 +1,4 @@
+#include <linux/kbuild.h>
 #include <linux/sched.h>
 #include <asm/thread_info.h>
 
@@ -7,11 +8,6 @@
  * and format the required data.
  */
 
-#define DEFINE(sym, val) \
-	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
 #if !defined(CONFIG_ETRAX_ARCH_V10) && !defined(CONFIG_ETRAX_ARCH_V32)
 #error One of ARCH v10 and ARCH v32 must be true!
 #endif
diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c
index 7ac000f..5868cee 100644
--- a/arch/cris/kernel/crisksyms.c
+++ b/arch/cris/kernel/crisksyms.c
@@ -30,7 +30,6 @@ extern void __negdi2(void);
 extern void iounmap(volatile void * __iomem);
 
 /* Platform dependent support */
-EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(get_cmos_time);
 EXPORT_SYMBOL(loops_per_usec);
 
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 4a159da..c5d7670 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -1,3 +1,4 @@
 
 generic-y += clkdev.h
 generic-y += exec.h
+generic-y += trace_clock.h
diff --git a/arch/frv/include/asm/unistd.h b/arch/frv/include/asm/unistd.h
index 2358634..1807d8e 100644
--- a/arch/frv/include/asm/unistd.h
+++ b/arch/frv/include/asm/unistd.h
@@ -30,6 +30,9 @@
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_CLONE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h
index a5b1d7d..871f89b 100644
--- a/arch/frv/include/uapi/asm/socket.h
+++ b/arch/frv/include/uapi/asm/socket.h
@@ -40,6 +40,7 @@
 /* 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
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c
index 7e33215..23916b2 100644
--- a/arch/frv/kernel/process.c
+++ b/arch/frv/kernel/process.c
@@ -139,42 +139,12 @@ inline unsigned long user_stack(const struct pt_regs *regs)
 	return user_mode(regs) ? regs->sp : 0;
 }
 
-asmlinkage int sys_fork(void)
-{
-#ifndef CONFIG_MMU
-	/* fork almost works, enough to trick you into looking elsewhere:-( */
-	return -EINVAL;
-#else
-	return do_fork(SIGCHLD, user_stack(__frame), __frame, 0, NULL, NULL);
-#endif
-}
-
-asmlinkage int sys_vfork(void)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, user_stack(__frame), __frame, 0,
-		       NULL, NULL);
-}
-
-/*****************************************************************************/
-/*
- * clone a process
- * - tlsptr is retrieved by copy_thread()
- */
-asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
-			 int __user *parent_tidptr, int __user *child_tidptr,
-			 int __user *tlsptr)
-{
-	if (!newsp)
-		newsp = user_stack(__frame);
-	return do_fork(clone_flags, newsp, __frame, 0, parent_tidptr, child_tidptr);
-} /* end sys_clone() */
-
 /*
  * set up the kernel stack and exception frames for a new process
  */
 int copy_thread(unsigned long clone_flags,
 		unsigned long usp, unsigned long arg,
-		struct task_struct *p, struct pt_regs *regs)
+		struct task_struct *p)
 {
 	struct pt_regs *childregs;
 
@@ -182,9 +152,7 @@ int copy_thread(unsigned long clone_flags,
 		(task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE);
 
 	/* set up the userspace frame (the only place that the USP is stored) */
-	*childregs = *__kernel_frame0_ptr;
-
-	p->set_child_tid = p->clear_child_tid = NULL;
+	*childregs = *current_pt_regs();
 
 	p->thread.frame	 = childregs;
 	p->thread.curr	 = p;
@@ -193,18 +161,15 @@ int copy_thread(unsigned long clone_flags,
 	p->thread.lr	 = 0;
 	p->thread.frame0 = childregs;
 
-	if (unlikely(!regs)) {
+	if (unlikely(p->flags & PF_KTHREAD)) {
 		childregs->gr9 = usp; /* function */
 		childregs->gr8 = arg;
 		p->thread.pc = (unsigned long) ret_from_kernel_thread;
 		save_user_regs(p->thread.user);
 		return 0;
 	}
-
-	/* set up the userspace frame (the only place that the USP is stored) */
-	*childregs = *regs;
-
-	childregs->sp		= usp;
+	if (usp)
+		childregs->sp = usp;
 	childregs->next_frame	= NULL;
 
 	p->thread.pc = (unsigned long) ret_from_fork;
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 98fabd1..0ae4450 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -3,11 +3,14 @@ config H8300
 	default y
 	select HAVE_IDE
 	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_ATOMIC64
 	select HAVE_UID16
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select GENERIC_IRQ_SHOW
 	select GENERIC_CPU_DEVICES
 	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
 
 config SYMBOL_PREFIX
 	string
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 50bbf38..4bc8ae7 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -3,3 +3,4 @@ include include/asm-generic/Kbuild.asm
 generic-y += clkdev.h
 generic-y += exec.h
 generic-y += module.h
+generic-y += trace_clock.h
diff --git a/arch/h8300/include/asm/processor.h b/arch/h8300/include/asm/processor.h
index 4c9f6f8..4b0ca49 100644
--- a/arch/h8300/include/asm/processor.h
+++ b/arch/h8300/include/asm/processor.h
@@ -107,8 +107,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 /*
  * Free current thread data structures etc..
  */
diff --git a/arch/h8300/include/asm/ptrace.h b/arch/h8300/include/asm/ptrace.h
index d09c440..7468589 100644
--- a/arch/h8300/include/asm/ptrace.h
+++ b/arch/h8300/include/asm/ptrace.h
@@ -60,6 +60,9 @@ struct pt_regs {
 #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)
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _H8300_PTRACE_H */
diff --git a/arch/h8300/include/asm/signal.h b/arch/h8300/include/asm/signal.h
index fd8b66e..c43c0a7 100644
--- a/arch/h8300/include/asm/signal.h
+++ b/arch/h8300/include/asm/signal.h
@@ -154,8 +154,6 @@ typedef struct sigaltstack {
 #include <asm/sigcontext.h>
 #undef __HAVE_ARCH_SIG_BITOPS
 
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
 #endif /* __KERNEL__ */
 
 #endif /* _H8300_SIGNAL_H */
diff --git a/arch/h8300/include/asm/socket.h b/arch/h8300/include/asm/socket.h
index ec4554e..90a2e57 100644
--- a/arch/h8300/include/asm/socket.h
+++ b/arch/h8300/include/asm/socket.h
@@ -40,6 +40,7 @@
 /* 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
diff --git a/arch/h8300/include/asm/unistd.h b/arch/h8300/include/asm/unistd.h
index 5cd8828..c2c2f5c 100644
--- a/arch/h8300/include/asm/unistd.h
+++ b/arch/h8300/include/asm/unistd.h
@@ -356,6 +356,10 @@
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_CLONE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/h8300/kernel/entry.S b/arch/h8300/kernel/entry.S
index ca74316..617a687 100644
--- a/arch/h8300/kernel/entry.S
+++ b/arch/h8300/kernel/entry.S
@@ -158,6 +158,7 @@ INTERRUPTS = 128
 .globl SYMBOL_NAME(system_call)
 .globl SYMBOL_NAME(ret_from_exception)
 .globl SYMBOL_NAME(ret_from_fork)
+.globl SYMBOL_NAME(ret_from_kernel_thread)
 .globl SYMBOL_NAME(ret_from_interrupt)
 .globl SYMBOL_NAME(interrupt_redirect_table)
 .globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp)
@@ -330,6 +331,14 @@ SYMBOL_NAME_LABEL(ret_from_fork)
 	jsr	@SYMBOL_NAME(schedule_tail)
 	jmp	@SYMBOL_NAME(ret_from_exception)
 
+SYMBOL_NAME_LABEL(ret_from_kernel_thread)
+	mov.l	er2,er0
+	jsr	@SYMBOL_NAME(schedule_tail)
+	mov.l	@(LER4:16,sp),er0
+	mov.l	@(LER5:16,sp),er1
+	jsr	@er1
+	jmp	@SYMBOL_NAME(ret_from_exception)
+
 SYMBOL_NAME_LABEL(resume)
 	/*
 	 * Beware - when entering resume, offset of tss is in d1,
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
index 6866bd9..53d7c0e 100644
--- a/arch/h8300/kernel/h8300_ksyms.c
+++ b/arch/h8300/kernel/h8300_ksyms.c
@@ -33,7 +33,6 @@ EXPORT_SYMBOL(strncmp);
 
 EXPORT_SYMBOL(ip_fast_csum);
 
-EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c
index e8dc139..b609f63 100644
--- a/arch/h8300/kernel/process.c
+++ b/arch/h8300/kernel/process.c
@@ -47,6 +47,7 @@ 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..
@@ -122,113 +123,34 @@ void show_regs(struct pt_regs * regs)
 		printk("\n");
 }
 
-/*
- * Create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	long retval;
-	long clone_arg;
-	mm_segment_t fs;
-
-	fs = get_fs();
-	set_fs (KERNEL_DS);
-	clone_arg = flags | CLONE_VM;
-	__asm__("mov.l sp,er3\n\t"
-		"sub.l er2,er2\n\t"
-		"mov.l %2,er1\n\t"
-		"mov.l %1,er0\n\t"
-		"trapa #0\n\t"
-		"cmp.l sp,er3\n\t"
-		"beq 1f\n\t"
-		"mov.l %4,er0\n\t"
-		"mov.l %3,er1\n\t"
-		"jsr @er1\n\t"
-		"mov.l %5,er0\n\t"
-		"trapa #0\n"
-		"1:\n\t"
-		"mov.l er0,%0"
-		:"=r"(retval)
-		:"i"(__NR_clone),"g"(clone_arg),"g"(fn),"g"(arg),"i"(__NR_exit)
-		:"er0","er1","er2","er3");
-	set_fs (fs);
-	return retval;
-}
-
 void flush_thread(void)
 {
 }
 
-/*
- * "h8300_fork()".. By the time we get here, the
- * non-volatile registers have also been saved on the
- * stack. We do some ugly pointer stuff here.. (see
- * also copy_thread)
- */
-
-asmlinkage int h8300_fork(struct pt_regs *regs)
-{
-	return -EINVAL;
-}
-
-asmlinkage int h8300_vfork(struct pt_regs *regs)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
-}
-
-asmlinkage int h8300_clone(struct pt_regs *regs)
-{
-	unsigned long clone_flags;
-	unsigned long newsp;
-
-	/* syscall2 puts clone_flags in er1 and usp in er2 */
-	clone_flags = regs->er1;
-	newsp = regs->er2;
-	if (!newsp)
-		newsp  = rdusp();
-	return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
-
-}
-
 int copy_thread(unsigned long clone_flags,
                 unsigned long usp, unsigned long topstk,
-		 struct task_struct * p, struct pt_regs * regs)
+		 struct task_struct * p)
 {
 	struct pt_regs * childregs;
 
 	childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1;
 
-	*childregs = *regs;
+	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;
+	p->thread.usp = usp ?: rdusp();
 	p->thread.ksp = (unsigned long)childregs;
 
 	return 0;
 }
 
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char *name,
-			  const char *const *argv,
-			  const char *const *envp,
-			  int dummy, ...)
-{
-	int error;
-	struct filename *filename;
-	struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4);
-
-	filename = getname(name);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		return error;
-	error = do_execve(filename->name, argv, envp, regs);
-	putname(filename);
-	return error;
-}
-
 unsigned long thread_saved_pc(struct task_struct *tsk)
 {
 	return ((struct pt_regs *)tsk->thread.esp0)->pc;
diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c
index 4bdc731..bf350cb 100644
--- a/arch/h8300/kernel/sys_h8300.c
+++ b/arch/h8300/kernel/sys_h8300.c
@@ -46,29 +46,3 @@ asmlinkage void syscall_print(void *dummy,...)
                ((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0);
 }
 #endif
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-asmlinkage
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	register long res __asm__("er0");
-	register const char *const *_c __asm__("er3") = envp;
-	register const char *const *_b __asm__("er2") = argv;
-	register const char * _a __asm__("er1") = filename;
-	__asm__ __volatile__ ("mov.l %1,er0\n\t"
-			"trapa	#0\n\t"
-			: "=r" (res)
-			: "g" (__NR_execve),
-			  "g" (_a),
-			  "g" (_b),
-			  "g" (_c)
-			: "cc", "memory");
-	return res;
-}
-
-
diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S
index 9d77e71..b74dd0a 100644
--- a/arch/h8300/kernel/syscalls.S
+++ b/arch/h8300/kernel/syscalls.S
@@ -340,21 +340,12 @@ SYMBOL_NAME_LABEL(sys_call_table)
 	bra	SYMBOL_NAME(syscall_trampoline):8
 	.endm
 
-SYMBOL_NAME_LABEL(sys_clone)	
-	call_sp	h8300_clone
-	
 SYMBOL_NAME_LABEL(sys_sigreturn)
 	call_sp	do_sigreturn
 
 SYMBOL_NAME_LABEL(sys_rt_sigreturn)
 	call_sp	do_rt_sigreturn
 
-SYMBOL_NAME_LABEL(sys_fork)
-	call_sp	h8300_fork
-
-SYMBOL_NAME_LABEL(sys_vfork)
-	call_sp	h8300_vfork
-
 SYMBOL_NAME_LABEL(syscall_trampoline)
 	mov.l	sp,er0
 	jmp	@er6
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
index 0744f7d..e418803 100644
--- a/arch/hexagon/Kconfig
+++ b/arch/hexagon/Kconfig
@@ -31,6 +31,8 @@ config HEXAGON
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_CLOCKEVENTS_BROADCAST
 	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
 	---help---
 	  Qualcomm Hexagon is a processor architecture designed for high
 	  performance and low power across a wide variety of applications.
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 3bfa9b3..bdb54ce 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -48,6 +48,7 @@ generic-y += stat.h
 generic-y += termbits.h
 generic-y += termios.h
 generic-y += topology.h
+generic-y += trace_clock.h
 generic-y += types.h
 generic-y += ucontext.h
 generic-y += unaligned.h
diff --git a/arch/hexagon/include/asm/processor.h b/arch/hexagon/include/asm/processor.h
index a03323a..6dd5d37 100644
--- a/arch/hexagon/include/asm/processor.h
+++ b/arch/hexagon/include/asm/processor.h
@@ -34,7 +34,6 @@
 struct task_struct;
 
 /*  this is defined in arch/process.c  */
-extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 extern unsigned long thread_saved_pc(struct task_struct *tsk);
 
 extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
diff --git a/arch/hexagon/include/asm/syscall.h b/arch/hexagon/include/asm/syscall.h
index fb0e9d4..ec2ce67 100644
--- a/arch/hexagon/include/asm/syscall.h
+++ b/arch/hexagon/include/asm/syscall.h
@@ -25,12 +25,9 @@ typedef long (*syscall_fn)(unsigned long, unsigned long,
 	unsigned long, unsigned long,
 	unsigned long, unsigned long);
 
-asmlinkage int sys_execve(char __user *ufilename, char __user * __user *argv,
-			  char __user * __user *envp);
 asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
 			 unsigned long parent_tidp, unsigned long child_tidp);
 
-#define sys_execve	sys_execve
 #define sys_clone	sys_clone
 
 #include <asm-generic/syscalls.h>
diff --git a/arch/hexagon/include/uapi/asm/ptrace.h b/arch/hexagon/include/uapi/asm/ptrace.h
index 8ef7840..1ffce0c 100644
--- a/arch/hexagon/include/uapi/asm/ptrace.h
+++ b/arch/hexagon/include/uapi/asm/ptrace.h
@@ -32,4 +32,8 @@
 extern int regs_query_register_offset(const char *name);
 extern const char *regs_query_register_name(unsigned int offset);
 
+#define current_pt_regs() \
+	((struct pt_regs *) \
+	 ((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
+
 #endif
diff --git a/arch/hexagon/include/uapi/asm/unistd.h b/arch/hexagon/include/uapi/asm/unistd.h
index 81312d6..2af8153 100644
--- a/arch/hexagon/include/uapi/asm/unistd.h
+++ b/arch/hexagon/include/uapi/asm/unistd.h
@@ -27,5 +27,7 @@
  */
 
 #define sys_mmap2 sys_mmap_pgoff
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_CLONE
 
 #include <asm-generic/unistd.h>
diff --git a/arch/hexagon/kernel/Makefile b/arch/hexagon/kernel/Makefile
index 536aec0..6c19501 100644
--- a/arch/hexagon/kernel/Makefile
+++ b/arch/hexagon/kernel/Makefile
@@ -3,8 +3,7 @@ extra-y := head.o vmlinux.lds
 obj-$(CONFIG_SMP) += smp.o topology.o
 
 obj-y += setup.o irq_cpu.o traps.o syscalltab.o signal.o time.o
-obj-y += process.o syscall.o trampoline.o reset.o ptrace.o
-obj-y += vdso.o
+obj-y += process.o trampoline.o reset.o ptrace.o vdso.o
 
 obj-$(CONFIG_KGDB)    += kgdb.o
 obj-$(CONFIG_MODULES) += module.o hexagon_ksyms.o
diff --git a/arch/hexagon/kernel/process.c b/arch/hexagon/kernel/process.c
index 9f6d741..06ae9ff 100644
--- a/arch/hexagon/kernel/process.c
+++ b/arch/hexagon/kernel/process.c
@@ -26,33 +26,6 @@
 #include <linux/slab.h>
 
 /*
- * Kernel thread creation.  The desired kernel function is "wrapped"
- * in the kernel_thread_helper function, which does cleanup
- * afterwards.
- */
-static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *))
-{
-	do_exit(fn(arg));
-}
-
-int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-	/*
-	 * Yes, we're exploting illicit knowledge of the ABI here.
-	 */
-	regs.r00 = (unsigned long) arg;
-	regs.r01 = (unsigned long) fn;
-	pt_set_elr(&regs, (unsigned long)kernel_thread_helper);
-	pt_set_kmode(&regs);
-
-	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
-/*
  * Program thread launch.  Often defined as a macro in processor.h,
  * but we're shooting for a small footprint and it's not an inner-loop
  * performance-critical operation.
@@ -114,8 +87,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
  * Copy architecture-specific thread state
  */
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-		unsigned long unused, struct task_struct *p,
-		struct pt_regs *regs)
+		unsigned long arg, struct task_struct *p)
 {
 	struct thread_info *ti = task_thread_info(p);
 	struct hexagon_switch_stack *ss;
@@ -125,61 +97,51 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	childregs = (struct pt_regs *) (((unsigned long) ti + THREAD_SIZE) -
 					sizeof(*childregs));
 
-	memcpy(childregs, regs, sizeof(*childregs));
 	ti->regs = childregs;
 
 	/*
 	 * Establish kernel stack pointer and initial PC for new thread
+	 * Note that unlike the usual situation, we do not copy the
+	 * parent's callee-saved here; those are in pt_regs and whatever
+	 * we leave here will be overridden on return to userland.
 	 */
 	ss = (struct hexagon_switch_stack *) ((unsigned long) childregs -
 						    sizeof(*ss));
 	ss->lr = (unsigned long)ret_from_fork;
 	p->thread.switch_sp = ss;
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		memset(childregs, 0, sizeof(struct pt_regs));
+		/* r24 <- fn, r25 <- arg */
+		ss->r2524 = usp | ((u64)arg << 32);
+		pt_set_kmode(childregs);
+		return 0;
+	}
+	memcpy(childregs, current_pt_regs(), sizeof(*childregs));
+	ss->r2524 = 0;
 
-	/* If User mode thread, set pt_reg stack pointer as per parameter */
-	if (user_mode(childregs)) {
+	if (usp)
 		pt_set_rte_sp(childregs, usp);
 
-		/* Child sees zero return value */
-		childregs->r00 = 0;
-
-		/*
-		 * The clone syscall has the C signature:
-		 * int [r0] clone(int flags [r0],
-		 *           void *child_frame [r1],
-		 *           void *parent_tid [r2],
-		 *           void *child_tid [r3],
-		 *           void *thread_control_block [r4]);
-		 * ugp is used to provide TLS support.
-		 */
-		if (clone_flags & CLONE_SETTLS)
-			childregs->ugp = childregs->r04;
-
-		/*
-		 * Parent sees new pid -- not necessary, not even possible at
-		 * this point in the fork process
-		 * Might also want to set things like ti->addr_limit
-		 */
-	} else {
-		/*
-		 * If kernel thread, resume stack is kernel stack base.
-		 * Note that this is pointer arithmetic on pt_regs *
-		 */
-		pt_set_rte_sp(childregs, (unsigned long)(childregs + 1));
-		/*
-		 * We need the current thread_info fast path pointer
-		 * set up in pt_regs.  The register to be used is
-		 * parametric for assembler code, but the mechanism
-		 * doesn't drop neatly into C.  Needs to be fixed.
-		 */
-		childregs->THREADINFO_REG = (unsigned long) ti;
-	}
+	/* Child sees zero return value */
+	childregs->r00 = 0;
+
+	/*
+	 * The clone syscall has the C signature:
+	 * int [r0] clone(int flags [r0],
+	 *           void *child_frame [r1],
+	 *           void *parent_tid [r2],
+	 *           void *child_tid [r3],
+	 *           void *thread_control_block [r4]);
+	 * ugp is used to provide TLS support.
+	 */
+	if (clone_flags & CLONE_SETTLS)
+		childregs->ugp = childregs->r04;
 
 	/*
-	 * thread_info pointer is pulled out of task_struct "stack"
-	 * field on switch_to.
+	 * Parent sees new pid -- not necessary, not even possible at
+	 * this point in the fork process
+	 * Might also want to set things like ti->addr_limit
 	 */
-	p->stack = (void *)ti;
 
 	return 0;
 }
diff --git a/arch/hexagon/kernel/signal.c b/arch/hexagon/kernel/signal.c
index 5047b8b..fe0d137 100644
--- a/arch/hexagon/kernel/signal.c
+++ b/arch/hexagon/kernel/signal.c
@@ -249,14 +249,14 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
  */
 asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
 {
-	struct pt_regs *regs = current_thread_info()->regs;
+	struct pt_regs *regs = current_pt_regs();
 
 	return do_sigaltstack(uss, uoss, regs->r29);
 }
 
 asmlinkage int sys_rt_sigreturn(void)
 {
-	struct pt_regs *regs = current_thread_info()->regs;
+	struct pt_regs *regs = current_pt_regs();
 	struct rt_sigframe __user *frame;
 	sigset_t blocked;
 
diff --git a/arch/hexagon/kernel/syscall.c b/arch/hexagon/kernel/syscall.c
deleted file mode 100644
index 319fa64..0000000
--- a/arch/hexagon/kernel/syscall.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Hexagon system calls
- *
- * Copyright (c) 2010-2011, 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/linkage.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/syscalls.h>
-#include <linux/unistd.h>
-#include <asm/mman.h>
-#include <asm/registers.h>
-
-/*
- * System calls with architecture-specific wrappers.
- * See signal.c for signal-related system call wrappers.
- */
-
-asmlinkage int sys_execve(char __user *ufilename,
-			  const char __user *const __user *argv,
-			  const char __user *const __user *envp)
-{
-	struct pt_regs *pregs = current_thread_info()->regs;
-	struct filename *filename;
-	int retval;
-
-	filename = getname(ufilename);
-	retval = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		return retval;
-
-	retval = do_execve(filename->name, argv, envp, pregs);
-	putname(filename);
-
-	return retval;
-}
-
-asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
-			 unsigned long parent_tidp, unsigned long child_tidp)
-{
-	struct pt_regs *pregs = current_thread_info()->regs;
-
-	if (!newsp)
-		newsp = pregs->SP;
-	return do_fork(clone_flags, newsp, pregs, 0, (int __user *)parent_tidp,
-		       (int __user *)child_tidp);
-}
-
-/*
- * Do a system call from the kernel, so as to have a proper pt_regs
- * and recycle the sys_execvpe infrustructure.
- */
-int kernel_execve(const char *filename,
-		  const char *const argv[], const char *const envp[])
-{
-	register unsigned long __a0 asm("r0") = (unsigned long) filename;
-	register unsigned long __a1 asm("r1") = (unsigned long) argv;
-	register unsigned long __a2 asm("r2") = (unsigned long) envp;
-	int retval;
-
-	__asm__ volatile(
-		"	R6 = #%4;\n"
-		"	trap0(#1);\n"
-		"	%0 = R0;\n"
-		: "=r" (retval)
-		: "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve)
-	);
-
-	return retval;
-}
diff --git a/arch/hexagon/kernel/vm_entry.S b/arch/hexagon/kernel/vm_entry.S
index cd71673..425e50c 100644
--- a/arch/hexagon/kernel/vm_entry.S
+++ b/arch/hexagon/kernel/vm_entry.S
@@ -266,4 +266,8 @@ _K_enter_machcheck:
 	.globl ret_from_fork
 ret_from_fork:
 	call schedule_tail
+	P0 = cmp.eq(R24, #0);
+	if P0 jump return_from_syscall
+	R0 = R25;
+	callr R24
 	jump return_from_syscall
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 3279646..2505b24 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -42,6 +42,8 @@ config IA64
 	select GENERIC_TIME_VSYSCALL_OLD
 	select HAVE_MOD_ARCH_SPECIFIC
 	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
 	default y
 	help
 	  The Itanium Processor Family is Intel's 64-bit successor to
@@ -375,8 +377,8 @@ config NR_CPUS
 	  performance hit.
 
 config HOTPLUG_CPU
-	bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
-	depends on SMP && EXPERIMENTAL
+	bool "Support for hot-pluggable CPUs"
+	depends on SMP
 	select HOTPLUG
 	default n
 	---help---
@@ -555,8 +557,8 @@ config IA64_HP_AML_NFW
 source "drivers/sn/Kconfig"
 
 config KEXEC
-	bool "kexec system call (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
+	bool "kexec system call"
+	depends on !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
 	help
 	  kexec is a system call that implements the ability to shutdown your
 	  current kernel, and to start another kernel.  It is like a reboot
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index ec536e4..fc3924d 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -555,6 +555,7 @@ static int __init simrs_init(void)
 	return 0;
 err_free_tty:
 	put_tty_driver(hp_simserial_driver);
+	tty_port_destroy(&state->port);
 	return retval;
 }
 
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index dd02f09..05b03ec 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -2,3 +2,4 @@
 generic-y += clkdev.h
 generic-y += exec.h
 generic-y += kvm_para.h
+generic-y += trace_clock.h
diff --git a/arch/ia64/include/asm/device.h b/arch/ia64/include/asm/device.h
index d05e78f..f69c32f 100644
--- a/arch/ia64/include/asm/device.h
+++ b/arch/ia64/include/asm/device.h
@@ -7,9 +7,6 @@
 #define _ASM_IA64_DEVICE_H
 
 struct dev_archdata {
-#ifdef CONFIG_ACPI
-	void	*acpi_handle;
-#endif
 #ifdef CONFIG_INTEL_IOMMU
 	void *iommu; /* hook for IOMMU specific extension */
 #endif
diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h
index 4f5e814..cf3ab7e 100644
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/asm/dma-mapping.h
@@ -58,6 +58,7 @@ static inline void dma_free_attrs(struct device *dev, size_t size,
 static inline int dma_mapping_error(struct device *dev, dma_addr_t daddr)
 {
 	struct dma_map_ops *ops = platform_dma_get_ops(dev);
+	debug_dma_mapping_error(dev, daddr);
 	return ops->mapping_error(dev, daddr);
 }
 
diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h
index 2c26321..74a7cc3 100644
--- a/arch/ia64/include/asm/io.h
+++ b/arch/ia64/include/asm/io.h
@@ -90,7 +90,7 @@ phys_to_virt (unsigned long address)
 
 #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
 extern u64 kern_mem_attribute (unsigned long phys_addr, unsigned long size);
-extern int valid_phys_addr_range (unsigned long addr, size_t count); /* efi.c */
+extern int valid_phys_addr_range (phys_addr_t addr, size_t count); /* efi.c */
 extern int valid_mmap_phys_addr_range (unsigned long pfn, size_t count);
 
 /*
diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h
index 944152a..e0a899a 100644
--- a/arch/ia64/include/asm/processor.h
+++ b/arch/ia64/include/asm/processor.h
@@ -340,22 +340,6 @@ struct task_struct;
  */
 #define release_thread(dead_task)
 
-/*
- * This is the mechanism for creating a new kernel thread.
- *
- * NOTE 1: Only a kernel-only process (ie the swapper or direct
- * descendants who haven't done an "execve()") should use this: it
- * will work within a system call from a "real" process, but the
- * process memory space will not be free'd until both the parent and
- * the child have exited.
- *
- * NOTE 2: This MUST NOT be an inlined function.  Otherwise, we get
- * into trouble in init/main.c when the child thread returns to
- * do_basic_setup() and the timing is such that free_initmem() has
- * been called already.
- */
-extern pid_t kernel_thread (int (*fn)(void *), void *arg, unsigned long flags);
-
 /* Get wait channel for task P.  */
 extern unsigned long get_wchan (struct task_struct *p);
 
diff --git a/arch/ia64/include/asm/signal.h b/arch/ia64/include/asm/signal.h
index aecda5b..3a1b20e 100644
--- a/arch/ia64/include/asm/signal.h
+++ b/arch/ia64/include/asm/signal.h
@@ -38,7 +38,5 @@ struct k_sigaction {
 
 #  include <asm/sigcontext.h>
 
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
 # endif /* !__ASSEMBLY__ */
 #endif /* _ASM_IA64_SIGNAL_H */
diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h
index 8b3ff2f..1574bca 100644
--- a/arch/ia64/include/asm/unistd.h
+++ b/arch/ia64/include/asm/unistd.h
@@ -29,6 +29,7 @@
 
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
 
 #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
 
diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h
index 41fc28a..23d6759 100644
--- a/arch/ia64/include/uapi/asm/socket.h
+++ b/arch/ia64/include/uapi/asm/socket.h
@@ -49,6 +49,7 @@
 /* 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
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 44057885..e9682f5 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -633,6 +633,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int triggering, int polarity)
 				      ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE :
 				     IOSAPIC_LEVEL);
 }
+EXPORT_SYMBOL_GPL(acpi_register_gsi);
 
 void acpi_unregister_gsi(u32 gsi)
 {
@@ -644,6 +645,7 @@ void acpi_unregister_gsi(u32 gsi)
 
 	iosapic_unregister_intr(gsi);
 }
+EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
 
 static int __init acpi_parse_fadt(struct acpi_table_header *table)
 {
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index d37bbd4..f034563 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -870,7 +870,7 @@ kern_mem_attribute (unsigned long phys_addr, unsigned long size)
 EXPORT_SYMBOL(kern_mem_attribute);
 
 int
-valid_phys_addr_range (unsigned long phys_addr, unsigned long size)
+valid_phys_addr_range (phys_addr_t phys_addr, unsigned long size)
 {
 	u64 attr;
 
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 1ccbe12..e25b784 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -61,14 +61,13 @@ ENTRY(ia64_execve)
 	 * Allocate 8 input registers since ptrace() may clobber them
 	 */
 	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
-	alloc loc1=ar.pfs,8,2,4,0
+	alloc loc1=ar.pfs,8,2,3,0
 	mov loc0=rp
 	.body
 	mov out0=in0			// filename
 	;;				// stop bit between alloc and call
 	mov out1=in1			// argv
 	mov out2=in2			// envp
-	add out3=16,sp			// regs
 	br.call.sptk.many rp=sys_execve
 .ret0:
 	cmp4.ge p6,p7=r8,r0
@@ -76,7 +75,6 @@ ENTRY(ia64_execve)
 	sxt4 r8=r8			// return 64-bit result
 	;;
 	stf.spill [sp]=f0
-(p6)	cmp.ne pKStk,pUStk=r0,r0	// a successful execve() lands us in user-mode...
 	mov rp=loc0
 (p6)	mov ar.pfs=r0			// clear ar.pfs on success
 (p7)	br.ret.sptk.many rp
@@ -118,13 +116,12 @@ GLOBAL_ENTRY(sys_clone2)
 	mov loc1=r16				// save ar.pfs across do_fork
 	.body
 	mov out1=in1
-	mov out3=in2
+	mov out2=in2
 	tbit.nz p6,p0=in0,CLONE_SETTLS_BIT
-	mov out4=in3	// parent_tidptr: valid only w/CLONE_PARENT_SETTID
+	mov out3=in3	// parent_tidptr: valid only w/CLONE_PARENT_SETTID
 	;;
 (p6)	st8 [r2]=in5				// store TLS in r16 for copy_thread()
-	mov out5=in4	// child_tidptr:  valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID
-	adds out2=IA64_SWITCH_STACK_SIZE+16,sp	// out2 = &regs
+	mov out4=in4	// child_tidptr:  valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID
 	mov out0=in0				// out0 = clone_flags
 	br.call.sptk.many rp=do_fork
 .ret1:	.restore sp
@@ -150,13 +147,12 @@ GLOBAL_ENTRY(sys_clone)
 	mov loc1=r16				// save ar.pfs across do_fork
 	.body
 	mov out1=in1
-	mov out3=16				// stacksize (compensates for 16-byte scratch area)
+	mov out2=16				// stacksize (compensates for 16-byte scratch area)
 	tbit.nz p6,p0=in0,CLONE_SETTLS_BIT
-	mov out4=in2	// parent_tidptr: valid only w/CLONE_PARENT_SETTID
+	mov out3=in2	// parent_tidptr: valid only w/CLONE_PARENT_SETTID
 	;;
 (p6)	st8 [r2]=in4				// store TLS in r13 (tp)
-	mov out5=in3	// child_tidptr:  valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID
-	adds out2=IA64_SWITCH_STACK_SIZE+16,sp	// out2 = &regs
+	mov out4=in3	// child_tidptr:  valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID
 	mov out0=in0				// out0 = clone_flags
 	br.call.sptk.many rp=do_fork
 .ret2:	.restore sp
@@ -484,19 +480,6 @@ GLOBAL_ENTRY(prefetch_stack)
 	br.ret.sptk.many rp
 END(prefetch_stack)
 
-GLOBAL_ENTRY(kernel_execve)
-	rum psr.ac
-	mov r15=__NR_execve			// put syscall number in place
-	break __BREAK_SYSCALL
-	br.ret.sptk.many rp
-END(kernel_execve)
-
-GLOBAL_ENTRY(clone)
-	mov r15=__NR_clone			// put syscall number in place
-	break __BREAK_SYSCALL
-	br.ret.sptk.many rp
-END(clone)
-
 	/*
 	 * Invoke a system call, but do some tracing before and after the call.
 	 * We MUST preserve the current register frame throughout this routine
@@ -600,6 +583,27 @@ GLOBAL_ENTRY(ia64_strace_leave_kernel)
 .ret4:	br.cond.sptk ia64_leave_kernel
 END(ia64_strace_leave_kernel)
 
+ENTRY(call_payload)
+	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(0)
+	/* call the kernel_thread payload; fn is in r4, arg - in r5 */
+	alloc loc1=ar.pfs,0,3,1,0
+	mov loc0=rp
+	mov loc2=gp
+	mov out0=r5		// arg
+	ld8 r14 = [r4], 8	// fn.address
+	;;
+	mov b6 = r14
+	ld8 gp = [r4]		// fn.gp
+	;;
+	br.call.sptk.many rp=b6	// fn(arg)
+.ret12:	mov gp=loc2
+	mov rp=loc0
+	mov ar.pfs=loc1
+	/* ... and if it has returned, we are going to userland */
+	cmp.ne pKStk,pUStk=r0,r0
+	br.ret.sptk.many rp
+END(call_payload)
+
 GLOBAL_ENTRY(ia64_ret_from_clone)
 	PT_REGS_UNWIND_INFO(0)
 {	/*
@@ -616,6 +620,7 @@ GLOBAL_ENTRY(ia64_ret_from_clone)
 	br.call.sptk.many rp=ia64_invoke_schedule_tail
 }
 .ret8:
+(pKStk)	br.call.sptk.many rp=call_payload
 	adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
 	;;
 	ld4 r2=[r2]
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index 629a250..4738ff7 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -1093,19 +1093,6 @@ GLOBAL_ENTRY(cycle_to_cputime)
 END(cycle_to_cputime)
 #endif /* CONFIG_VIRT_CPU_ACCOUNTING */
 
-GLOBAL_ENTRY(start_kernel_thread)
-	.prologue
-	.save rp, r0				// this is the end of the call-chain
-	.body
-	alloc r2 = ar.pfs, 0, 0, 2, 0
-	mov out0 = r9
-	mov out1 = r11;;
-	br.call.sptk.many rp = kernel_thread_helper;;
-	mov out0 = r8
-	br.call.sptk.many rp = sys_exit;;
-1:	br.sptk.few 1b				// not reached
-END(start_kernel_thread)
-
 #ifdef CONFIG_IA64_BRL_EMU
 
 /*
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 35e106f..31360cb 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -393,72 +393,24 @@ ia64_load_extra (struct task_struct *task)
 int
 copy_thread(unsigned long clone_flags,
 	     unsigned long user_stack_base, unsigned long user_stack_size,
-	     struct task_struct *p, struct pt_regs *regs)
+	     struct task_struct *p)
 {
 	extern char ia64_ret_from_clone;
 	struct switch_stack *child_stack, *stack;
 	unsigned long rbs, child_rbs, rbs_size;
 	struct pt_regs *child_ptregs;
+	struct pt_regs *regs = current_pt_regs();
 	int retval = 0;
 
-#ifdef CONFIG_SMP
-	/*
-	 * For SMP idle threads, fork_by_hand() calls do_fork with
-	 * NULL regs.
-	 */
-	if (!regs)
-		return 0;
-#endif
-
-	stack = ((struct switch_stack *) regs) - 1;
-
 	child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1;
 	child_stack = (struct switch_stack *) child_ptregs - 1;
 
-	/* copy parent's switch_stack & pt_regs to child: */
-	memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack));
-
 	rbs = (unsigned long) current + IA64_RBS_OFFSET;
 	child_rbs = (unsigned long) p + IA64_RBS_OFFSET;
-	rbs_size = stack->ar_bspstore - rbs;
-
-	/* copy the parent's register backing store to the child: */
-	memcpy((void *) child_rbs, (void *) rbs, rbs_size);
-
-	if (likely(user_mode(child_ptregs))) {
-		if (clone_flags & CLONE_SETTLS)
-			child_ptregs->r13 = regs->r16;	/* see sys_clone2() in entry.S */
-		if (user_stack_base) {
-			child_ptregs->r12 = user_stack_base + user_stack_size - 16;
-			child_ptregs->ar_bspstore = user_stack_base;
-			child_ptregs->ar_rnat = 0;
-			child_ptregs->loadrs = 0;
-		}
-	} else {
-		/*
-		 * Note: we simply preserve the relative position of
-		 * the stack pointer here.  There is no need to
-		 * allocate a scratch area here, since that will have
-		 * been taken care of by the caller of sys_clone()
-		 * already.
-		 */
-		child_ptregs->r12 = (unsigned long) child_ptregs - 16; /* kernel sp */
-		child_ptregs->r13 = (unsigned long) p;		/* set `current' pointer */
-	}
-	child_stack->ar_bspstore = child_rbs + rbs_size;
-	child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
 
 	/* copy parts of thread_struct: */
 	p->thread.ksp = (unsigned long) child_stack - 16;
 
-	/* stop some PSR bits from being inherited.
-	 * the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
-	 * therefore we must specify them explicitly here and not include them in
-	 * IA64_PSR_BITS_TO_CLEAR.
-	 */
-	child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
-				 & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
-
 	/*
 	 * NOTE: The calling convention considers all floating point
 	 * registers in the high partition (fph) to be scratch.  Since
@@ -480,8 +432,66 @@ copy_thread(unsigned long clone_flags,
 #	define THREAD_FLAGS_TO_SET	0
 	p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR)
 			   | THREAD_FLAGS_TO_SET);
+
 	ia64_drop_fpu(p);	/* don't pick up stale state from a CPU's fph */
 
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		if (unlikely(!user_stack_base)) {
+			/* fork_idle() called us */
+			return 0;
+		}
+		memset(child_stack, 0, sizeof(*child_ptregs) + sizeof(*child_stack));
+		child_stack->r4 = user_stack_base;	/* payload */
+		child_stack->r5 = user_stack_size;	/* argument */
+		/*
+		 * Preserve PSR bits, except for bits 32-34 and 37-45,
+		 * which we can't read.
+		 */
+		child_ptregs->cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN;
+		/* mark as valid, empty frame */
+		child_ptregs->cr_ifs = 1UL << 63;
+		child_stack->ar_fpsr = child_ptregs->ar_fpsr
+			= ia64_getreg(_IA64_REG_AR_FPSR);
+		child_stack->pr = (1 << PRED_KERNEL_STACK);
+		child_stack->ar_bspstore = child_rbs;
+		child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
+
+		/* stop some PSR bits from being inherited.
+		 * the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
+		 * therefore we must specify them explicitly here and not include them in
+		 * IA64_PSR_BITS_TO_CLEAR.
+		 */
+		child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
+				 & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
+
+		return 0;
+	}
+	stack = ((struct switch_stack *) regs) - 1;
+	/* copy parent's switch_stack & pt_regs to child: */
+	memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack));
+
+	/* copy the parent's register backing store to the child: */
+	rbs_size = stack->ar_bspstore - rbs;
+	memcpy((void *) child_rbs, (void *) rbs, rbs_size);
+	if (clone_flags & CLONE_SETTLS)
+		child_ptregs->r13 = regs->r16;	/* see sys_clone2() in entry.S */
+	if (user_stack_base) {
+		child_ptregs->r12 = user_stack_base + user_stack_size - 16;
+		child_ptregs->ar_bspstore = user_stack_base;
+		child_ptregs->ar_rnat = 0;
+		child_ptregs->loadrs = 0;
+	}
+	child_stack->ar_bspstore = child_rbs + rbs_size;
+	child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
+
+	/* stop some PSR bits from being inherited.
+	 * the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
+	 * therefore we must specify them explicitly here and not include them in
+	 * IA64_PSR_BITS_TO_CLEAR.
+	 */
+	child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
+				 & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
+
 #ifdef CONFIG_PERFMON
 	if (current->thread.pfm_context)
 		pfm_inherit(p, child_ptregs);
@@ -608,57 +618,6 @@ dump_fpu (struct pt_regs *pt, elf_fpregset_t dst)
 	return 1;	/* f0-f31 are always valid so we always return 1 */
 }
 
-long
-sys_execve (const char __user *filename,
-	    const char __user *const __user *argv,
-	    const char __user *const __user *envp,
-	    struct pt_regs *regs)
-{
-	struct filename *fname;
-	int error;
-
-	fname = getname(filename);
-	error = PTR_ERR(fname);
-	if (IS_ERR(fname))
-		goto out;
-	error = do_execve(fname->name, argv, envp, regs);
-	putname(fname);
-out:
-	return error;
-}
-
-pid_t
-kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
-{
-	extern void start_kernel_thread (void);
-	unsigned long *helper_fptr = (unsigned long *) &start_kernel_thread;
-	struct {
-		struct switch_stack sw;
-		struct pt_regs pt;
-	} regs;
-
-	memset(&regs, 0, sizeof(regs));
-	regs.pt.cr_iip = helper_fptr[0];	/* set entry point (IP) */
-	regs.pt.r1 = helper_fptr[1];		/* set GP */
-	regs.pt.r9 = (unsigned long) fn;	/* 1st argument */
-	regs.pt.r11 = (unsigned long) arg;	/* 2nd argument */
-	/* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read.  */
-	regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN;
-	regs.pt.cr_ifs = 1UL << 63;		/* mark as valid, empty frame */
-	regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR);
-	regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET;
-	regs.sw.pr = (1 << PRED_KERNEL_STACK);
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs.pt, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
-/* This gets called from kernel_thread() via ia64_invoke_thread_helper().  */
-int
-kernel_thread_helper (int (*fn)(void *), void *arg)
-{
-	return (*fn)(arg);
-}
-
 /*
  * Flush thread state.  This is called when a thread does an execve().
  */
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 963d2db..6a368cb 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -460,11 +460,6 @@ start_secondary (void *unused)
 	return 0;
 }
 
-struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
-{
-	return NULL;
-}
-
 static int __cpuinit
 do_boot_cpu (int sapicid, int cpu, struct task_struct *idle)
 {
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index f638821..5e48503 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -106,9 +106,9 @@ void vtime_task_switch(struct task_struct *prev)
 	struct thread_info *ni = task_thread_info(current);
 
 	if (idle_task(smp_processor_id()) != prev)
-		vtime_account_system(prev);
+		__vtime_account_system(prev);
 	else
-		vtime_account_idle(prev);
+		__vtime_account_idle(prev);
 
 	vtime_account_user(prev);
 
@@ -135,14 +135,14 @@ static cputime_t vtime_delta(struct task_struct *tsk)
 	return delta_stime;
 }
 
-void vtime_account_system(struct task_struct *tsk)
+void __vtime_account_system(struct task_struct *tsk)
 {
 	cputime_t delta = vtime_delta(tsk);
 
 	account_system_time(tsk, 0, delta, delta);
 }
 
-void vtime_account_idle(struct task_struct *tsk)
+void __vtime_account_idle(struct task_struct *tsk)
 {
 	account_idle_time(vtime_delta(tsk));
 }
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index c64460b..dc00b2c 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -275,7 +275,7 @@ static struct attribute * cache_default_attrs[] = {
 #define to_object(k) container_of(k, struct cache_info, kobj)
 #define to_attr(a) container_of(a, struct cache_attr, attr)
 
-static ssize_t cache_show(struct kobject * kobj, struct attribute * attr, char * buf)
+static ssize_t ia64_cache_show(struct kobject * kobj, struct attribute * attr, char * buf)
 {
 	struct cache_attr *fattr = to_attr(attr);
 	struct cache_info *this_leaf = to_object(kobj);
@@ -286,7 +286,7 @@ static ssize_t cache_show(struct kobject * kobj, struct attribute * attr, char *
 }
 
 static const struct sysfs_ops cache_sysfs_ops = {
-	.show   = cache_show
+	.show   = ia64_cache_show
 };
 
 static struct kobj_type cache_ktype = {
diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig
index e794752..2cd225f 100644
--- a/arch/ia64/kvm/Kconfig
+++ b/arch/ia64/kvm/Kconfig
@@ -20,7 +20,7 @@ if VIRTUALIZATION
 config KVM
 	tristate "Kernel-based Virtual Machine (KVM) support"
 	depends on BROKEN
-	depends on HAVE_KVM && MODULES && EXPERIMENTAL
+	depends on HAVE_KVM && MODULES
 	# for device assignment:
 	depends on PCI
 	depends on BROKEN
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 8b3a9c0..8ebf167 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -1,5 +1,5 @@
 /*
- * kvm_ia64.c: Basic KVM suppport On Itanium series processors
+ * kvm_ia64.c: Basic KVM support On Itanium series processors
  *
  *
  * 	Copyright (C) 2007, Intel Corporation.
@@ -1362,11 +1362,9 @@ static void kvm_release_vm_pages(struct kvm *kvm)
 	struct kvm_memslots *slots;
 	struct kvm_memory_slot *memslot;
 	int j;
-	unsigned long base_gfn;
 
 	slots = kvm_memslots(kvm);
 	kvm_for_each_memslot(memslot, slots) {
-		base_gfn = memslot->base_gfn;
 		for (j = 0; j < memslot->npages; j++) {
 			if (memslot->rmap[j])
 				put_page((struct page *)memslot->rmap[j]);
diff --git a/arch/ia64/xen/Kconfig b/arch/ia64/xen/Kconfig
index 515e082..5d8a06b 100644
--- a/arch/ia64/xen/Kconfig
+++ b/arch/ia64/xen/Kconfig
@@ -5,7 +5,7 @@
 config XEN
 	bool "Xen hypervisor support"
 	default y
-	depends on PARAVIRT && MCKINLEY && IA64_PAGE_SIZE_16KB && EXPERIMENTAL
+	depends on PARAVIRT && MCKINLEY && IA64_PAGE_SIZE_16KB
 	select XEN_XENCOMM
 	select NO_IDLE_HZ
 	# followings are required to save/restore.
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index f807721..5183f43 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -15,6 +15,8 @@ config M32R
 	select GENERIC_ATOMIC64
 	select ARCH_USES_GETTIMEOFFSET
 	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
 
 config SBUS
 	bool
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 50bbf38..4bc8ae7 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -3,3 +3,4 @@ include include/asm-generic/Kbuild.asm
 generic-y += clkdev.h
 generic-y += exec.h
 generic-y += module.h
+generic-y += trace_clock.h
diff --git a/arch/m32r/include/asm/processor.h b/arch/m32r/include/asm/processor.h
index da17253..5767367 100644
--- a/arch/m32r/include/asm/processor.h
+++ b/arch/m32r/include/asm/processor.h
@@ -118,11 +118,6 @@ struct mm_struct;
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
-/*
- * create a kernel thread without removing it from tasklists
- */
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 /* Copy and release all segment info associated with a VM */
 extern void copy_segments(struct task_struct *p, struct mm_struct * mm);
 extern void release_segments(struct mm_struct * mm);
diff --git a/arch/m32r/include/asm/ptrace.h b/arch/m32r/include/asm/ptrace.h
index 4313aa6..c4432f1 100644
--- a/arch/m32r/include/asm/ptrace.h
+++ b/arch/m32r/include/asm/ptrace.h
@@ -139,6 +139,8 @@ extern void withdraw_debug_trap(struct pt_regs *regs);
 
 #define task_pt_regs(task) \
         ((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE) - 1)
+#define current_pt_regs() ((struct pt_regs *) \
+	((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
 
 #endif /* __KERNEL */
 
diff --git a/arch/m32r/include/asm/signal.h b/arch/m32r/include/asm/signal.h
index ea5f95e..e4d2e2a 100644
--- a/arch/m32r/include/asm/signal.h
+++ b/arch/m32r/include/asm/signal.h
@@ -149,10 +149,6 @@ typedef struct sigaltstack {
 
 #undef __HAVE_ARCH_SIG_BITOPS
 
-struct pt_regs;
-
-#define ptrace_signal_deliver(regs, cookie)	do { } while (0)
-
 #endif /* __KERNEL__ */
 
 #endif  /* _ASM_M32R_SIGNAL_H */
diff --git a/arch/m32r/include/asm/socket.h b/arch/m32r/include/asm/socket.h
index a15f40b..5e7088a 100644
--- a/arch/m32r/include/asm/socket.h
+++ b/arch/m32r/include/asm/socket.h
@@ -40,6 +40,7 @@
 /* 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
diff --git a/arch/m32r/include/asm/unistd.h b/arch/m32r/include/asm/unistd.h
index d5e66a4..d9e7351 100644
--- a/arch/m32r/include/asm/unistd.h
+++ b/arch/m32r/include/asm/unistd.h
@@ -352,6 +352,10 @@
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_VFORK
 
 #define __IGNORE_lchown
 #define __IGNORE_setuid
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S
index 225412b..0c01543 100644
--- a/arch/m32r/kernel/entry.S
+++ b/arch/m32r/kernel/entry.S
@@ -125,6 +125,15 @@
 	and	\reg, sp
 	.endm
 
+ENTRY(ret_from_kernel_thread)
+	pop	r0
+	bl	schedule_tail
+	GET_THREAD_INFO(r8)
+	ld	r0, R0(r8)
+	ld	r1, R1(r8)
+	jl	r1
+	bra	syscall_exit
+
 ENTRY(ret_from_fork)
 	pop	r0
 	bl	schedule_tail
diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c
index 7005707..b727e69 100644
--- a/arch/m32r/kernel/m32r_ksyms.c
+++ b/arch/m32r/kernel/m32r_ksyms.c
@@ -21,7 +21,6 @@ EXPORT_SYMBOL(boot_cpu_data);
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(kernel_thread);
 
 EXPORT_SYMBOL(strncpy_from_user);
 EXPORT_SYMBOL(__strncpy_from_user);
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
index e736627..765d0f5 100644
--- a/arch/m32r/kernel/process.c
+++ b/arch/m32r/kernel/process.c
@@ -165,41 +165,6 @@ void show_regs(struct pt_regs * regs)
 }
 
 /*
- * Create a kernel thread
- */
-
-/*
- * This is the mechanism for creating a new kernel thread.
- *
- * NOTE! Only a kernel-only process(ie the swapper or direct descendants
- * who haven't done an "execve()") should use this: it will work within
- * a system call from a "real" process, but the process memory space will
- * not be free'd until both the parent and the child have exited.
- */
-static void kernel_thread_helper(void *nouse, int (*fn)(void *), void *arg)
-{
-	fn(arg);
-	do_exit(-1);
-}
-
-int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof (regs));
-	regs.r1 = (unsigned long)fn;
-	regs.r2 = (unsigned long)arg;
-
-	regs.bpc = (unsigned long)kernel_thread_helper;
-
-	regs.psw = M32R_PSW_BIE;
-
-	/* Ok, create the new process. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL,
-		NULL);
-}
-
-/*
  * Free current thread data structures etc..
  */
 void exit_thread(void)
@@ -227,88 +192,31 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long spu,
-	unsigned long unused, struct task_struct *tsk, struct pt_regs *regs)
+	unsigned long arg, struct task_struct *tsk)
 {
 	struct pt_regs *childregs = task_pt_regs(tsk);
 	extern void ret_from_fork(void);
-
-	/* Copy registers */
-	*childregs = *regs;
-
-	childregs->spu = spu;
-	childregs->r0 = 0;	/* Child gets zero as return value */
-	regs->r0 = tsk->pid;
+	extern void ret_from_kernel_thread(void);
+
+	if (unlikely(tsk->flags & PF_KTHREAD)) {
+		memset(childregs, 0, sizeof(struct pt_regs));
+		childregs->psw = M32R_PSW_BIE;
+		childregs->r1 = spu;	/* fn */
+		childregs->r0 = arg;
+		tsk->thread.lr = (unsigned long)ret_from_kernel_thread;
+	} else {
+		/* Copy registers */
+		*childregs = *current_pt_regs();
+		if (spu)
+			childregs->spu = spu;
+		childregs->r0 = 0;	/* Child gets zero as return value */
+		tsk->thread.lr = (unsigned long)ret_from_fork;
+	}
 	tsk->thread.sp = (unsigned long)childregs;
-	tsk->thread.lr = (unsigned long)ret_from_fork;
 
 	return 0;
 }
 
-asmlinkage int sys_fork(unsigned long r0, unsigned long r1, unsigned long r2,
-	unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6,
-	struct pt_regs regs)
-{
-#ifdef CONFIG_MMU
-	return do_fork(SIGCHLD, regs.spu, &regs, 0, NULL, NULL);
-#else
-	return -EINVAL;
-#endif /* CONFIG_MMU */
-}
-
-asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
-			 unsigned long parent_tidptr,
-			 unsigned long child_tidptr,
-			 unsigned long r4, unsigned long r5, unsigned long r6,
-			 struct pt_regs regs)
-{
-	if (!newsp)
-		newsp = regs.spu;
-
-	return do_fork(clone_flags, newsp, &regs, 0,
-		       (int __user *)parent_tidptr, (int __user *)child_tidptr);
-}
-
-/*
- * This is trivial, and on the face of it looks like it
- * could equally well be done in user mode.
- *
- * Not so, for quite unobvious reasons - register pressure.
- * In user mode vfork() cannot have a stack frame, and if
- * done by calling the "clone()" system call directly, you
- * do not have enough call-clobbered registers to hold all
- * the information you need.
- */
-asmlinkage int sys_vfork(unsigned long r0, unsigned long r1, unsigned long r2,
-	unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6,
-	struct pt_regs regs)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.spu, &regs, 0,
-			NULL, NULL);
-}
-
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char __user *ufilename,
-			  const char __user *const __user *uargv,
-			  const char __user *const __user *uenvp,
-			  unsigned long r3, unsigned long r4, unsigned long r5,
-			  unsigned long r6, struct pt_regs regs)
-{
-	int error;
-	struct filename *filename;
-
-	filename = getname(ufilename);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-
-	error = do_execve(filename->name, uargv, uenvp, &regs);
-	putname(filename);
-out:
-	return error;
-}
-
 /*
  * These bracket the sleeping functions..
  */
diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c
index d841fb6..c3fdd63 100644
--- a/arch/m32r/kernel/sys_m32r.c
+++ b/arch/m32r/kernel/sys_m32r.c
@@ -88,24 +88,3 @@ asmlinkage int sys_cachectl(char *addr, int nbytes, int op)
 	/* Not implemented yet. */
 	return -ENOSYS;
 }
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	register long __scno __asm__ ("r7") = __NR_execve;
-	register long __arg3 __asm__ ("r2") = (long)(envp);
-	register long __arg2 __asm__ ("r1") = (long)(argv);
-	register long __res __asm__ ("r0") = (long)(filename);
-	__asm__ __volatile__ (
-		"trap #" SYSCALL_VECTOR "|| nop"
-		: "=r" (__res)
-		: "r" (__scno), "0" (__res), "r" (__arg2),
-			"r" (__arg3)
-		: "memory");
-	return __res;
-}
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index e7c1614..953a7ba 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -16,6 +16,7 @@ config M68K
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE
 	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
 	select HAVE_MOD_ARCH_SPECIFIC
 	select MODULES_USE_ELF_REL
 	select MODULES_USE_ELF_RELA
diff --git a/arch/m68k/Kconfig.bus b/arch/m68k/Kconfig.bus
index ffc0601..93ef034 100644
--- a/arch/m68k/Kconfig.bus
+++ b/arch/m68k/Kconfig.bus
@@ -28,8 +28,8 @@ config ZORRO
 	  Linux use these.
 
 config AMIGA_PCMCIA
-	bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)"
-	depends on AMIGA && EXPERIMENTAL
+	bool "Amiga 1200/600 PCMCIA support"
+	depends on AMIGA
 	help
 	  Include support in the kernel for pcmcia on Amiga 1200 and Amiga
 	  600. If you intend to use pcmcia cards say Y; otherwise say N.
diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu
index c4eb79e..b1cfff8 100644
--- a/arch/m68k/Kconfig.cpu
+++ b/arch/m68k/Kconfig.cpu
@@ -35,7 +35,8 @@ endchoice
 if M68KCLASSIC
 
 config M68000
-	bool
+	bool "MC68000"
+	depends on !MMU
 	select CPU_HAS_NO_BITFIELDS
 	select CPU_HAS_NO_MULDIV64
 	select CPU_HAS_NO_UNALIGNED
@@ -274,9 +275,8 @@ endif # COLDFIRE
 comment "Processor Specific Options"
 
 config M68KFPU_EMU
-	bool "Math emulation support (EXPERIMENTAL)"
+	bool "Math emulation support"
 	depends on MMU
-	depends on EXPERIMENTAL
 	help
 	  At some point in the future, this will cause floating-point math
 	  instructions to be emulated by the kernel on machines that lack a
diff --git a/arch/m68k/Kconfig.debug b/arch/m68k/Kconfig.debug
index 87233ac..fa12283 100644
--- a/arch/m68k/Kconfig.debug
+++ b/arch/m68k/Kconfig.debug
@@ -41,7 +41,7 @@ config NO_KERNEL_MSG
 
 config BDM_DISABLE
 	bool "Disable BDM signals"
-	depends on (EXPERIMENTAL && COLDFIRE)
+	depends on COLDFIRE
 	help
 	  Disable the ColdFire CPU's BDM signals.
 
diff --git a/arch/m68k/Kconfig.devices b/arch/m68k/Kconfig.devices
index 04a3d9b..c4cdfe4 100644
--- a/arch/m68k/Kconfig.devices
+++ b/arch/m68k/Kconfig.devices
@@ -60,8 +60,8 @@ endmenu
 menu "Character devices"
 
 config ATARI_DSP56K
-	tristate "Atari DSP56k support (EXPERIMENTAL)"
-	depends on ATARI && EXPERIMENTAL
+	tristate "Atari DSP56k support"
+	depends on ATARI
 	help
 	  If you want to be able to use the DSP56001 in Falcons, say Y. This
 	  driver is still experimental, and if you don't know what it is, or
@@ -87,7 +87,7 @@ config HPDCA
 
 config HPAPCI
 	tristate "HP APCI serial support"
-	depends on HP300 && SERIAL_8250 && EXPERIMENTAL
+	depends on HP300 && SERIAL_8250
 	help
 	  If you want to use the internal "APCI" serial ports on an HP400
 	  machine, say Y here.
diff --git a/arch/m68k/emu/nfcon.c b/arch/m68k/emu/nfcon.c
index 16d170f..6685bf4 100644
--- a/arch/m68k/emu/nfcon.c
+++ b/arch/m68k/emu/nfcon.c
@@ -120,8 +120,6 @@ static int __init nfcon_init(void)
 {
 	int res;
 
-	tty_port_init(&nfcon_tty_port);
-
 	stderr_id = nf_get_id("NF_STDERR");
 	if (!stderr_id)
 		return -ENODEV;
@@ -130,6 +128,8 @@ static int __init nfcon_init(void)
 	if (!nfcon_tty_driver)
 		return -ENOMEM;
 
+	tty_port_init(&nfcon_tty_port);
+
 	nfcon_tty_driver->driver_name = "nfcon";
 	nfcon_tty_driver->name = "nfcon";
 	nfcon_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
@@ -143,6 +143,7 @@ static int __init nfcon_init(void)
 	if (res) {
 		pr_err("failed to register nfcon tty driver\n");
 		put_tty_driver(nfcon_tty_driver);
+		tty_port_destroy(&nfcon_tty_port);
 		return res;
 	}
 
@@ -157,6 +158,7 @@ static void __exit nfcon_exit(void)
 	unregister_console(&nf_console);
 	tty_unregister_driver(nfcon_tty_driver);
 	put_tty_driver(nfcon_tty_driver);
+	tty_port_destroy(&nfcon_tty_port);
 }
 
 module_init(nfcon_init);
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 88fa3ac..c7933e4 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -7,6 +7,7 @@ generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
 generic-y += futex.h
+generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
 generic-y += irq_regs.h
@@ -21,9 +22,13 @@ generic-y += percpu.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sections.h
+generic-y += shmparam.h
 generic-y += siginfo.h
+generic-y += spinlock.h
 generic-y += statfs.h
+generic-y += termios.h
 generic-y += topology.h
+generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
diff --git a/arch/m68k/include/asm/hw_irq.h b/arch/m68k/include/asm/hw_irq.h
deleted file mode 100644
index eacef09..0000000
--- a/arch/m68k/include/asm/hw_irq.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_M68K_HW_IRQ_H
-#define __ASM_M68K_HW_IRQ_H
-
-/* Dummy include. */
-
-#endif
diff --git a/arch/m68k/include/asm/m5249sim.h b/arch/m68k/include/asm/m5249sim.h
deleted file mode 100644
index fdf45e6..0000000
--- a/arch/m68k/include/asm/m5249sim.h
+++ /dev/null
@@ -1,269 +0,0 @@
-/****************************************************************************/
-
-/*
- *	m5249sim.h -- ColdFire 5249 System Integration Module support.
- *
- *	(C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
- */
-
-/****************************************************************************/
-#ifndef	m5249sim_h
-#define	m5249sim_h
-/****************************************************************************/
-
-#define	CPU_NAME		"COLDFIRE(m5249)"
-#define	CPU_INSTR_PER_JIFFY	3
-#define	MCF_BUSCLK		(MCF_CLK / 2)
-
-#include <asm/m52xxacr.h>
-
-/*
- *	The 5249 has a second MBAR region, define its address.
- */
-#define MCF_MBAR2		0x80000000
-
-/*
- *	Define the 5249 SIM register set addresses.
- */
-#define	MCFSIM_RSR		(MCF_MBAR + 0x00)	/* Reset Status */
-#define	MCFSIM_SYPCR		(MCF_MBAR + 0x01)	/* System Protection */
-#define	MCFSIM_SWIVR		(MCF_MBAR + 0x02)	/* SW Watchdog intr */
-#define	MCFSIM_SWSR		(MCF_MBAR + 0x03)	/* SW Watchdog srv */
-#define	MCFSIM_PAR		(MCF_MBAR + 0x04)	/* Pin Assignment */
-#define	MCFSIM_IRQPAR		(MCF_MBAR + 0x06)	/* Intr Assignment */
-#define	MCFSIM_MPARK		(MCF_MBAR + 0x0C)	/* BUS Master Ctrl */
-#define	MCFSIM_IPR		(MCF_MBAR + 0x40)	/* Interrupt Pending */
-#define	MCFSIM_IMR		(MCF_MBAR + 0x44)	/* Interrupt Mask */
-#define	MCFSIM_AVR		(MCF_MBAR + 0x4b)	/* Autovector Ctrl */
-#define	MCFSIM_ICR0		(MCF_MBAR + 0x4c)	/* Intr Ctrl reg 0 */
-#define	MCFSIM_ICR1		(MCF_MBAR + 0x4d)	/* Intr Ctrl reg 1 */
-#define	MCFSIM_ICR2		(MCF_MBAR + 0x4e)	/* Intr Ctrl reg 2 */
-#define	MCFSIM_ICR3		(MCF_MBAR + 0x4f)	/* Intr Ctrl reg 3 */
-#define	MCFSIM_ICR4		(MCF_MBAR + 0x50)	/* Intr Ctrl reg 4 */
-#define	MCFSIM_ICR5		(MCF_MBAR + 0x51)	/* Intr Ctrl reg 5 */
-#define	MCFSIM_ICR6		(MCF_MBAR + 0x52)	/* Intr Ctrl reg 6 */
-#define	MCFSIM_ICR7		(MCF_MBAR + 0x53)	/* Intr Ctrl reg 7 */
-#define	MCFSIM_ICR8		(MCF_MBAR + 0x54)	/* Intr Ctrl reg 8 */
-#define	MCFSIM_ICR9		(MCF_MBAR + 0x55)	/* Intr Ctrl reg 9 */
-#define	MCFSIM_ICR10		(MCF_MBAR + 0x56)	/* Intr Ctrl reg 10 */
-#define	MCFSIM_ICR11		(MCF_MBAR + 0x57)	/* Intr Ctrl reg 11 */
-
-#define	MCFSIM_CSAR0		(MCF_MBAR + 0x80)	/* CS 0 Address reg */
-#define	MCFSIM_CSMR0		(MCF_MBAR + 0x84)	/* CS 0 Mask reg */
-#define	MCFSIM_CSCR0		(MCF_MBAR + 0x8a)	/* CS 0 Control reg */
-#define	MCFSIM_CSAR1		(MCF_MBAR + 0x8c)	/* CS 1 Address reg */
-#define	MCFSIM_CSMR1		(MCF_MBAR + 0x90)	/* CS 1 Mask reg */
-#define	MCFSIM_CSCR1		(MCF_MBAR + 0x96)	/* CS 1 Control reg */
-#define	MCFSIM_CSAR2		(MCF_MBAR + 0x98)	/* CS 2 Address reg */
-#define	MCFSIM_CSMR2		(MCF_MBAR + 0x9c)	/* CS 2 Mask reg */
-#define	MCFSIM_CSCR2		(MCF_MBAR + 0xa2)	/* CS 2 Control reg */
-#define	MCFSIM_CSAR3		(MCF_MBAR + 0xa4)	/* CS 3 Address reg */
-#define	MCFSIM_CSMR3		(MCF_MBAR + 0xa8)	/* CS 3 Mask reg */
-#define	MCFSIM_CSCR3		(MCF_MBAR + 0xae)	/* CS 3 Control reg */
-
-#define MCFSIM_DCR		(MCF_MBAR + 0x100)	/* DRAM Control */
-#define MCFSIM_DACR0		(MCF_MBAR + 0x108)	/* DRAM 0 Addr/Ctrl */
-#define MCFSIM_DMR0		(MCF_MBAR + 0x10c)	/* DRAM 0 Mask */
-#define MCFSIM_DACR1		(MCF_MBAR + 0x110)	/* DRAM 1 Addr/Ctrl */
-#define MCFSIM_DMR1		(MCF_MBAR + 0x114)	/* DRAM 1 Mask */
-
-/*
- *	Timer module.
- */
-#define MCFTIMER_BASE1		(MCF_MBAR + 0x140)	/* Base of TIMER1 */
-#define MCFTIMER_BASE2		(MCF_MBAR + 0x180)	/* Base of TIMER2 */
-
-/*
- *	UART module.
- */
-#define MCFUART_BASE0		(MCF_MBAR + 0x1c0)	/* Base address UART0 */
-#define MCFUART_BASE1		(MCF_MBAR + 0x200)	/* Base address UART1 */
-
-/*
- *	QSPI module.
- */
-#define	MCFQSPI_BASE		(MCF_MBAR + 0x300)	/* Base address QSPI */
-#define	MCFQSPI_SIZE		0x40			/* Register set size */
-
-#define	MCFQSPI_CS0		29
-#define	MCFQSPI_CS1		24
-#define	MCFQSPI_CS2		21
-#define	MCFQSPI_CS3		22
-
-/*
- *	DMA unit base addresses.
- */
-#define MCFDMA_BASE0		(MCF_MBAR + 0x300)	/* Base address DMA 0 */
-#define MCFDMA_BASE1		(MCF_MBAR + 0x340)	/* Base address DMA 1 */
-#define MCFDMA_BASE2		(MCF_MBAR + 0x380)	/* Base address DMA 2 */
-#define MCFDMA_BASE3		(MCF_MBAR + 0x3C0)	/* Base address DMA 3 */
-
-/*
- *	Some symbol defines for the above...
- */
-#define	MCFSIM_SWDICR		MCFSIM_ICR0	/* Watchdog timer ICR */
-#define	MCFSIM_TIMER1ICR	MCFSIM_ICR1	/* Timer 1 ICR */
-#define	MCFSIM_TIMER2ICR	MCFSIM_ICR2	/* Timer 2 ICR */
-#define	MCFSIM_UART1ICR		MCFSIM_ICR4	/* UART 1 ICR */
-#define	MCFSIM_UART2ICR		MCFSIM_ICR5	/* UART 2 ICR */
-#define	MCFSIM_DMA0ICR		MCFSIM_ICR6	/* DMA 0 ICR */
-#define	MCFSIM_DMA1ICR		MCFSIM_ICR7	/* DMA 1 ICR */
-#define	MCFSIM_DMA2ICR		MCFSIM_ICR8	/* DMA 2 ICR */
-#define	MCFSIM_DMA3ICR		MCFSIM_ICR9	/* DMA 3 ICR */
-#define	MCFSIM_QSPIICR		MCFSIM_ICR10	/* QSPI ICR */
-
-/*
- *	Define system peripheral IRQ usage.
- */
-#define	MCF_IRQ_QSPI		28		/* QSPI, Level 4 */
-#define	MCF_IRQ_TIMER		30		/* Timer0, Level 6 */
-#define	MCF_IRQ_PROFILER	31		/* Timer1, Level 7 */
-
-#define	MCF_IRQ_UART0		73		/* UART0 */
-#define	MCF_IRQ_UART1		74		/* UART1 */
-
-/*
- *	General purpose IO registers (in MBAR2).
- */
-#define	MCFSIM2_GPIOREAD	(MCF_MBAR2 + 0x000)	/* GPIO read values */
-#define	MCFSIM2_GPIOWRITE	(MCF_MBAR2 + 0x004)	/* GPIO write values */
-#define	MCFSIM2_GPIOENABLE	(MCF_MBAR2 + 0x008)	/* GPIO enabled */
-#define	MCFSIM2_GPIOFUNC	(MCF_MBAR2 + 0x00C)	/* GPIO function */
-#define	MCFSIM2_GPIO1READ	(MCF_MBAR2 + 0x0B0)	/* GPIO1 read values */
-#define	MCFSIM2_GPIO1WRITE	(MCF_MBAR2 + 0x0B4)	/* GPIO1 write values */
-#define	MCFSIM2_GPIO1ENABLE	(MCF_MBAR2 + 0x0B8)	/* GPIO1 enabled */
-#define	MCFSIM2_GPIO1FUNC	(MCF_MBAR2 + 0x0BC)	/* GPIO1 function */
-
-#define	MCFSIM2_GPIOINTSTAT	(MCF_MBAR2 + 0xc0)	/* GPIO intr status */
-#define	MCFSIM2_GPIOINTCLEAR	(MCF_MBAR2 + 0xc0)	/* GPIO intr clear */
-#define	MCFSIM2_GPIOINTENABLE	(MCF_MBAR2 + 0xc4)	/* GPIO intr enable */
-
-#define	MCFSIM2_INTLEVEL1	(MCF_MBAR2 + 0x140)	/* Intr level reg 1 */
-#define	MCFSIM2_INTLEVEL2	(MCF_MBAR2 + 0x144)	/* Intr level reg 2 */
-#define	MCFSIM2_INTLEVEL3	(MCF_MBAR2 + 0x148)	/* Intr level reg 3 */
-#define	MCFSIM2_INTLEVEL4	(MCF_MBAR2 + 0x14c)	/* Intr level reg 4 */
-#define	MCFSIM2_INTLEVEL5	(MCF_MBAR2 + 0x150)	/* Intr level reg 5 */
-#define	MCFSIM2_INTLEVEL6	(MCF_MBAR2 + 0x154)	/* Intr level reg 6 */
-#define	MCFSIM2_INTLEVEL7	(MCF_MBAR2 + 0x158)	/* Intr level reg 7 */
-#define	MCFSIM2_INTLEVEL8	(MCF_MBAR2 + 0x15c)	/* Intr level reg 8 */
-
-#define	MCFSIM2_DMAROUTE	(MCF_MBAR2 + 0x188)	/* DMA routing */
-
-#define	MCFSIM2_IDECONFIG1	(MCF_MBAR2 + 0x18c)	/* IDEconfig1 */
-#define	MCFSIM2_IDECONFIG2	(MCF_MBAR2 + 0x190)	/* IDEconfig2 */
-
-/*
- * Define the base interrupt for the second interrupt controller.
- * We set it to 128, out of the way of the base interrupts, and plenty
- * of room for its 64 interrupts.
- */
-#define	MCFINTC2_VECBASE	128
-
-#define	MCFINTC2_GPIOIRQ0	(MCFINTC2_VECBASE + 32)
-#define	MCFINTC2_GPIOIRQ1	(MCFINTC2_VECBASE + 33)
-#define	MCFINTC2_GPIOIRQ2	(MCFINTC2_VECBASE + 34)
-#define	MCFINTC2_GPIOIRQ3	(MCFINTC2_VECBASE + 35)
-#define	MCFINTC2_GPIOIRQ4	(MCFINTC2_VECBASE + 36)
-#define	MCFINTC2_GPIOIRQ5	(MCFINTC2_VECBASE + 37)
-#define	MCFINTC2_GPIOIRQ6	(MCFINTC2_VECBASE + 38)
-#define	MCFINTC2_GPIOIRQ7	(MCFINTC2_VECBASE + 39)
-
-/*
- * Generic GPIO support
- */
-#define MCFGPIO_PIN_MAX		64
-#define MCFGPIO_IRQ_MAX		-1
-#define MCFGPIO_IRQ_VECBASE	-1
-
-/****************************************************************************/
-
-#ifdef __ASSEMBLER__
-
-/*
- *	The M5249C3 board needs a little help getting all its SIM devices
- *	initialized at kernel start time. dBUG doesn't set much up, so
- *	we need to do it manually.
- */
-.macro m5249c3_setup
-	/*
-	 *	Set MBAR1 and MBAR2, just incase they are not set.
-	 */
-	movel	#0x10000001,%a0
-	movec	%a0,%MBAR			/* map MBAR region */
-	subql	#1,%a0				/* get MBAR address in a0 */
-
-	movel	#0x80000001,%a1
-	movec	%a1,#3086			/* map MBAR2 region */
-	subql	#1,%a1				/* get MBAR2 address in a1 */
-
-	/*
-	 *      Move secondary interrupts to their base (128).
-	 */
-	moveb	#MCFINTC2_VECBASE,%d0
-	moveb	%d0,0x16b(%a1)			/* interrupt base register */
-
-	/*
-	 *      Work around broken CSMR0/DRAM vector problem.
-	 */
-	movel	#0x001F0021,%d0			/* disable C/I bit */
-	movel	%d0,0x84(%a0)			/* set CSMR0 */
-
-	/*
-	 *	Disable the PLL firstly. (Who knows what state it is
-	 *	in here!).
-	 */
-	movel	0x180(%a1),%d0			/* get current PLL value */
-	andl	#0xfffffffe,%d0			/* PLL bypass first */
-	movel	%d0,0x180(%a1)			/* set PLL register */
-	nop
-
-#if CONFIG_CLOCK_FREQ == 140000000
-	/*
-	 *	Set initial clock frequency. This assumes M5249C3 board
-	 *	is fitted with 11.2896MHz crystal. It will program the
-	 *	PLL for 140MHz. Lets go fast :-)
-	 */
-	movel	#0x125a40f0,%d0			/* set for 140MHz */
-	movel	%d0,0x180(%a1)			/* set PLL register */
-	orl	#0x1,%d0
-	movel	%d0,0x180(%a1)			/* set PLL register */
-#endif
-
-	/*
-	 *	Setup CS1 for ethernet controller.
-	 *	(Setup as per M5249C3 doco).
-	 */
-	movel  #0xe0000000,%d0			/* CS1 mapped at 0xe0000000 */
-	movel  %d0,0x8c(%a0)
-	movel  #0x001f0021,%d0			/* CS1 size of 1Mb */
-	movel  %d0,0x90(%a0)
-	movew  #0x0080,%d0			/* CS1 = 16bit port, AA */
-	movew  %d0,0x96(%a0)
-
-	/*
-	 *	Setup CS2 for IDE interface.
-	 */
-	movel	#0x50000000,%d0			/* CS2 mapped at 0x50000000 */
-	movel	%d0,0x98(%a0)
-	movel	#0x001f0001,%d0			/* CS2 size of 1MB */
-	movel	%d0,0x9c(%a0)
-	movew	#0x0080,%d0			/* CS2 = 16bit, TA */
-	movew	%d0,0xa2(%a0)
-
-	movel	#0x00107000,%d0			/* IDEconfig1 */
-	movel	%d0,0x18c(%a1)
-	movel	#0x000c0400,%d0			/* IDEconfig2 */
-	movel	%d0,0x190(%a1)
-
-	movel	#0x00080000,%d0			/* GPIO19, IDE reset bit */
-	orl	%d0,0xc(%a1)			/* function GPIO19 */
-	orl	%d0,0x8(%a1)			/* enable GPIO19 as output */
-        orl	%d0,0x4(%a1)			/* de-assert IDE reset */
-.endm
-
-#define	PLATFORM_SETUP	m5249c3_setup
-
-#endif /* __ASSEMBLER__ */
-
-/****************************************************************************/
-#endif	/* m5249sim_h */
diff --git a/arch/m68k/include/asm/m525xsim.h b/arch/m68k/include/asm/m525xsim.h
index acab61c..e33f5bb 100644
--- a/arch/m68k/include/asm/m525xsim.h
+++ b/arch/m68k/include/asm/m525xsim.h
@@ -12,6 +12,11 @@
 #define m525xsim_h
 /****************************************************************************/
 
+/*
+ *	This header supports ColdFire 5249, 5251 and 5253. There are a few
+ *	little differences between them, but most of the peripheral support
+ *	can be used by all of them.
+ */
 #define CPU_NAME		"COLDFIRE(m525x)"
 #define CPU_INSTR_PER_JIFFY	3
 #define MCF_BUSCLK		(MCF_CLK / 2)
@@ -65,6 +70,8 @@
 #define MCFSIM_DCR		(MCF_MBAR + 0x100)	/* DRAM Control */
 #define MCFSIM_DACR0		(MCF_MBAR + 0x108)	/* DRAM 0 Addr/Ctrl */
 #define MCFSIM_DMR0		(MCF_MBAR + 0x10c)	/* DRAM 0 Mask */
+#define MCFSIM_DACR1		(MCF_MBAR + 0x110)	/* DRAM 1 Addr/Ctrl */
+#define MCFSIM_DMR1		(MCF_MBAR + 0x114)	/* DRAM 1 Mask */
 
 /*
  * Secondary Interrupt Controller (in MBAR2)
@@ -101,11 +108,17 @@
 #define MCFQSPI_BASE		(MCF_MBAR + 0x300)	/* Base address QSPI */
 #define MCFQSPI_SIZE		0x40			/* Register set size */
 
-
+#ifdef CONFIG_M5249
+#define MCFQSPI_CS0		29
+#define MCFQSPI_CS1		24
+#define MCFQSPI_CS2		21
+#define MCFQSPI_CS3		22
+#else
 #define MCFQSPI_CS0		15
 #define MCFQSPI_CS1		16
 #define MCFQSPI_CS2		24
 #define MCFQSPI_CS3		28
+#endif
 
 /*
  *	I2C module.
@@ -115,6 +128,7 @@
 
 #define MCFI2C_BASE1		(MCF_MBAR2 + 0x440)	/* Base addreess I2C1 */
 #define MCFI2C_SIZE1		0x20			/* Register set size */
+
 /*
  *	DMA unit base addresses.
  */
@@ -163,6 +177,7 @@
 #define MCF_IRQ_GPIO4		(MCFINTC2_VECBASE + 36)
 #define MCF_IRQ_GPIO5		(MCFINTC2_VECBASE + 37)
 #define MCF_IRQ_GPIO6		(MCFINTC2_VECBASE + 38)
+#define MCF_IRQ_GPIO7		(MCFINTC2_VECBASE + 39)
 
 #define MCF_IRQ_USBWUP		(MCFINTC2_VECBASE + 40)
 #define MCF_IRQ_I2C1		(MCFINTC2_VECBASE + 62)
@@ -183,12 +198,111 @@
 #define MCFSIM2_GPIOINTCLEAR	(MCF_MBAR2 + 0xc0)	/* GPIO intr clear */
 #define MCFSIM2_GPIOINTENABLE	(MCF_MBAR2 + 0xc4)	/* GPIO intr enable */
 
+#define MCFSIM2_DMAROUTE	(MCF_MBAR2 + 0x188)     /* DMA routing */
+#define MCFSIM2_IDECONFIG1	(MCF_MBAR2 + 0x18c)	/* IDEconfig1 */
+#define MCFSIM2_IDECONFIG2	(MCF_MBAR2 + 0x190)	/* IDEconfig2 */
+
 /*
  * Generic GPIO support
  */
 #define MCFGPIO_PIN_MAX		64
+#ifdef CONFIG_M5249
+#define MCFGPIO_IRQ_MAX		-1
+#define MCFGPIO_IRQ_VECBASE	-1
+#else
 #define MCFGPIO_IRQ_MAX		7
 #define MCFGPIO_IRQ_VECBASE	MCF_IRQ_GPIO0
+#endif
+
+/****************************************************************************/
+
+#ifdef __ASSEMBLER__
+#ifdef CONFIG_M5249C3
+/*
+ *	The M5249C3 board needs a little help getting all its SIM devices
+ *	initialized at kernel start time. dBUG doesn't set much up, so
+ *	we need to do it manually.
+ */
+.macro m5249c3_setup
+	/*
+	 *	Set MBAR1 and MBAR2, just incase they are not set.
+	 */
+	movel	#0x10000001,%a0
+	movec	%a0,%MBAR			/* map MBAR region */
+	subql	#1,%a0				/* get MBAR address in a0 */
+
+	movel	#0x80000001,%a1
+	movec	%a1,#3086			/* map MBAR2 region */
+	subql	#1,%a1				/* get MBAR2 address in a1 */
+
+	/*
+	 *      Move secondary interrupts to their base (128).
+	 */
+	moveb	#MCFINTC2_VECBASE,%d0
+	moveb	%d0,0x16b(%a1)			/* interrupt base register */
+
+	/*
+	 *      Work around broken CSMR0/DRAM vector problem.
+	 */
+	movel	#0x001F0021,%d0			/* disable C/I bit */
+	movel	%d0,0x84(%a0)			/* set CSMR0 */
+
+	/*
+	 *	Disable the PLL firstly. (Who knows what state it is
+	 *	in here!).
+	 */
+	movel	0x180(%a1),%d0			/* get current PLL value */
+	andl	#0xfffffffe,%d0			/* PLL bypass first */
+	movel	%d0,0x180(%a1)			/* set PLL register */
+	nop
+
+#if CONFIG_CLOCK_FREQ == 140000000
+	/*
+	 *	Set initial clock frequency. This assumes M5249C3 board
+	 *	is fitted with 11.2896MHz crystal. It will program the
+	 *	PLL for 140MHz. Lets go fast :-)
+	 */
+	movel	#0x125a40f0,%d0			/* set for 140MHz */
+	movel	%d0,0x180(%a1)			/* set PLL register */
+	orl	#0x1,%d0
+	movel	%d0,0x180(%a1)			/* set PLL register */
+#endif
+
+	/*
+	 *	Setup CS1 for ethernet controller.
+	 *	(Setup as per M5249C3 doco).
+	 */
+	movel  #0xe0000000,%d0			/* CS1 mapped at 0xe0000000 */
+	movel  %d0,0x8c(%a0)
+	movel  #0x001f0021,%d0			/* CS1 size of 1Mb */
+	movel  %d0,0x90(%a0)
+	movew  #0x0080,%d0			/* CS1 = 16bit port, AA */
+	movew  %d0,0x96(%a0)
+
+	/*
+	 *	Setup CS2 for IDE interface.
+	 */
+	movel	#0x50000000,%d0			/* CS2 mapped at 0x50000000 */
+	movel	%d0,0x98(%a0)
+	movel	#0x001f0001,%d0			/* CS2 size of 1MB */
+	movel	%d0,0x9c(%a0)
+	movew	#0x0080,%d0			/* CS2 = 16bit, TA */
+	movew	%d0,0xa2(%a0)
+
+	movel	#0x00107000,%d0			/* IDEconfig1 */
+	movel	%d0,0x18c(%a1)
+	movel	#0x000c0400,%d0			/* IDEconfig2 */
+	movel	%d0,0x190(%a1)
+
+	movel	#0x00080000,%d0			/* GPIO19, IDE reset bit */
+	orl	%d0,0xc(%a1)			/* function GPIO19 */
+	orl	%d0,0x8(%a1)			/* enable GPIO19 as output */
+        orl	%d0,0x4(%a1)			/* de-assert IDE reset */
+.endm
+
+#define	PLATFORM_SETUP	m5249c3_setup
 
+#endif /* CONFIG_M5249C3 */
+#endif /* __ASSEMBLER__ */
 /****************************************************************************/
 #endif	/* m525xsim_h */
diff --git a/arch/m68k/include/asm/mcfclk.h b/arch/m68k/include/asm/mcfclk.h
index b676a02..ea4791e 100644
--- a/arch/m68k/include/asm/mcfclk.h
+++ b/arch/m68k/include/asm/mcfclk.h
@@ -8,7 +8,6 @@
 
 struct clk;
 
-#ifdef MCFPM_PPMCR0
 struct clk_ops {
 	void (*enable)(struct clk *);
 	void (*disable)(struct clk *);
@@ -23,6 +22,8 @@ struct clk {
 };
 
 extern struct clk *mcf_clks[];
+
+#ifdef MCFPM_PPMCR0
 extern struct clk_ops clk_ops0;
 #ifdef MCFPM_PPMCR1
 extern struct clk_ops clk_ops1;
@@ -38,6 +39,12 @@ static struct clk __clk_##clk_bank##_##clk_slot = { \
 
 void __clk_init_enabled(struct clk *);
 void __clk_init_disabled(struct clk *);
+#else
+#define DEFINE_CLK(clk_ref, clk_name, clk_rate) \
+        static struct clk clk_##clk_ref = { \
+                .name = clk_name, \
+                .rate = clk_rate, \
+        }
 #endif /* MCFPM_PPMCR0 */
 
 #endif /* mcfclk_h */
diff --git a/arch/m68k/include/asm/mcfsim.h b/arch/m68k/include/asm/mcfsim.h
index 7a83e61..a04fd9b 100644
--- a/arch/m68k/include/asm/mcfsim.h
+++ b/arch/m68k/include/asm/mcfsim.h
@@ -24,10 +24,7 @@
 #elif defined(CONFIG_M523x)
 #include <asm/m523xsim.h>
 #include <asm/mcfintc.h>
-#elif defined(CONFIG_M5249)
-#include <asm/m5249sim.h>
-#include <asm/mcfintc.h>
-#elif defined(CONFIG_M525x)
+#elif defined(CONFIG_M5249) || defined(CONFIG_M525x)
 #include <asm/m525xsim.h>
 #include <asm/mcfintc.h>
 #elif defined(CONFIG_M527x)
diff --git a/arch/m68k/include/asm/page_no.h b/arch/m68k/include/asm/page_no.h
index 9059572..ef20916 100644
--- a/arch/m68k/include/asm/page_no.h
+++ b/arch/m68k/include/asm/page_no.h
@@ -26,7 +26,7 @@ extern unsigned long memory_end;
 #define pfn_to_virt(pfn)	__va((pfn) << 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 page_to_virt(page)	__va(((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET))
 
 #define pfn_to_page(pfn)	virt_to_page(pfn_to_virt(pfn))
 #define page_to_pfn(page)	virt_to_pfn(page_to_virt(page))
diff --git a/arch/m68k/include/asm/shmparam.h b/arch/m68k/include/asm/shmparam.h
deleted file mode 100644
index 558892a..0000000
--- a/arch/m68k/include/asm/shmparam.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _M68K_SHMPARAM_H
-#define _M68K_SHMPARAM_H
-
-#define	SHMLBA PAGE_SIZE		 /* attach addr a multiple of this */
-
-#endif /* _M68K_SHMPARAM_H */
diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h
index 2df26b5..9c8c46b 100644
--- a/arch/m68k/include/asm/signal.h
+++ b/arch/m68k/include/asm/signal.h
@@ -86,11 +86,9 @@ static inline int sigfindinword(unsigned long word)
 
 #endif /* !CONFIG_CPU_HAS_NO_BITFIELDS */
 
-#ifdef __uClinux__
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-#else
-struct pt_regs;
-extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie);
+#ifndef __uClinux__
+extern void ptrace_signal_deliver(void);
+#define ptrace_signal_deliver ptrace_signal_deliver
 #endif /* __uClinux__ */
 
 #endif /* _M68K_SIGNAL_H */
diff --git a/arch/m68k/include/asm/spinlock.h b/arch/m68k/include/asm/spinlock.h
deleted file mode 100644
index 20f46e2..0000000
--- a/arch/m68k/include/asm/spinlock.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __M68K_SPINLOCK_H
-#define __M68K_SPINLOCK_H
-
-#error "m68k doesn't do SMP yet"
-
-#endif
diff --git a/arch/m68k/include/asm/termios.h b/arch/m68k/include/asm/termios.h
deleted file mode 100644
index ad8efb0..0000000
--- a/arch/m68k/include/asm/termios.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef _M68K_TERMIOS_H
-#define _M68K_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 /* _M68K_TERMIOS_H */
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h
index 5fc7f7b..a021d67 100644
--- a/arch/m68k/include/asm/unistd.h
+++ b/arch/m68k/include/asm/unistd.h
@@ -32,7 +32,8 @@
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_SYS_EXECVE
-#define __ARCH_WANT_KERNEL_EXECVE
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_VFORK
 
 /*
  * "Conditional" syscalls
diff --git a/arch/m68k/include/uapi/asm/Kbuild b/arch/m68k/include/uapi/asm/Kbuild
index 972bce1..1fef45a 100644
--- a/arch/m68k/include/uapi/asm/Kbuild
+++ b/arch/m68k/include/uapi/asm/Kbuild
@@ -1,26 +1,27 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+generic-y += auxvec.h
+generic-y += msgbuf.h
+generic-y += sembuf.h
+generic-y += shmbuf.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += termbits.h
+generic-y += termios.h
+
 header-y += a.out.h
-header-y += auxvec.h
 header-y += byteorder.h
 header-y += cachectl.h
 header-y += fcntl.h
 header-y += ioctls.h
-header-y += msgbuf.h
 header-y += param.h
 header-y += poll.h
 header-y += posix_types.h
 header-y += ptrace.h
-header-y += sembuf.h
 header-y += setup.h
-header-y += shmbuf.h
 header-y += sigcontext.h
 header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
 header-y += stat.h
 header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
 header-y += unistd.h
diff --git a/arch/m68k/include/uapi/asm/auxvec.h b/arch/m68k/include/uapi/asm/auxvec.h
deleted file mode 100644
index 844d6d5..0000000
--- a/arch/m68k/include/uapi/asm/auxvec.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __ASMm68k_AUXVEC_H
-#define __ASMm68k_AUXVEC_H
-
-#endif
diff --git a/arch/m68k/include/uapi/asm/msgbuf.h b/arch/m68k/include/uapi/asm/msgbuf.h
deleted file mode 100644
index 243cb79..0000000
--- a/arch/m68k/include/uapi/asm/msgbuf.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _M68K_MSGBUF_H
-#define _M68K_MSGBUF_H
-
-/*
- * The msqid64_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 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 /* _M68K_MSGBUF_H */
diff --git a/arch/m68k/include/uapi/asm/sembuf.h b/arch/m68k/include/uapi/asm/sembuf.h
deleted file mode 100644
index 2308052..0000000
--- a/arch/m68k/include/uapi/asm/sembuf.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _M68K_SEMBUF_H
-#define _M68K_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 /* _M68K_SEMBUF_H */
diff --git a/arch/m68k/include/uapi/asm/shmbuf.h b/arch/m68k/include/uapi/asm/shmbuf.h
deleted file mode 100644
index f8928d6..0000000
--- a/arch/m68k/include/uapi/asm/shmbuf.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef _M68K_SHMBUF_H
-#define _M68K_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 /* _M68K_SHMBUF_H */
diff --git a/arch/m68k/include/uapi/asm/socket.h b/arch/m68k/include/uapi/asm/socket.h
deleted file mode 100644
index d1be684..0000000
--- a/arch/m68k/include/uapi/asm/socket.h
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef _ASM_SOCKET_H
-#define _ASM_SOCKET_H
-
-#include <asm/sockios.h>
-
-/* For setsockopt(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
-/* To add :#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_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
-
-#endif /* _ASM_SOCKET_H */
diff --git a/arch/m68k/include/uapi/asm/sockios.h b/arch/m68k/include/uapi/asm/sockios.h
deleted file mode 100644
index c04a239..0000000
--- a/arch/m68k/include/uapi/asm/sockios.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ARCH_M68K_SOCKIOS__
-#define __ARCH_M68K_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_M68K_SOCKIOS__ */
diff --git a/arch/m68k/include/uapi/asm/termbits.h b/arch/m68k/include/uapi/asm/termbits.h
deleted file mode 100644
index aea1e37..0000000
--- a/arch/m68k/include/uapi/asm/termbits.h
+++ /dev/null
@@ -1,201 +0,0 @@
-#ifndef __ARCH_M68K_TERMBITS_H__
-#define __ARCH_M68K_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_M68K_TERMBITS_H__ */
diff --git a/arch/m68k/include/uapi/asm/termios.h b/arch/m68k/include/uapi/asm/termios.h
deleted file mode 100644
index ce2142c..0000000
--- a/arch/m68k/include/uapi/asm/termios.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef _UAPI_M68K_TERMIOS_H
-#define _UAPI_M68K_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_M68K_TERMIOS_H */
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 946cb01..a78f564 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -44,34 +44,29 @@
 
 .globl system_call, buserr, trap, resume
 .globl sys_call_table
-.globl sys_fork, sys_clone, sys_vfork
+.globl __sys_fork, __sys_clone, __sys_vfork
 .globl ret_from_interrupt, bad_interrupt
 .globl auto_irqhandler_fixup
 .globl user_irqvec_fixup
 
 .text
-ENTRY(sys_fork)
+ENTRY(__sys_fork)
 	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
-	jbsr	m68k_fork
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
+	jbsr	sys_fork
+	lea     %sp@(24),%sp
 	rts
 
-ENTRY(sys_clone)
+ENTRY(__sys_clone)
 	SAVE_SWITCH_STACK
 	pea	%sp@(SWITCH_STACK_SIZE)
 	jbsr	m68k_clone
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
+	lea     %sp@(28),%sp
 	rts
 
-ENTRY(sys_vfork)
+ENTRY(__sys_vfork)
 	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
-	jbsr	m68k_vfork
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
+	jbsr	sys_vfork
+	lea     %sp@(24),%sp
 	rts
 
 ENTRY(sys_sigreturn)
@@ -115,16 +110,9 @@ ENTRY(ret_from_kernel_thread)
 	| a3 contains the kernel thread payload, d7 - its argument
 	movel	%d1,%sp@-
 	jsr	schedule_tail
-	GET_CURRENT(%d0)
 	movel	%d7,(%sp)
 	jsr	%a3@
 	addql	#4,%sp
-	movel	%d0,(%sp)
-	jra	sys_exit
-
-ENTRY(ret_from_kernel_execve)
-	movel	4(%sp), %sp
-	GET_CURRENT(%d0)
 	jra	ret_from_exception
 
 #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU)
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index c51bb17..d538694 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -136,57 +136,35 @@ void flush_thread(void)
 }
 
 /*
- * "m68k_fork()".. By the time we get here, the
- * non-volatile registers have also been saved on the
- * stack. We do some ugly pointer stuff here.. (see
- * also copy_thread)
+ * Why not generic sys_clone, you ask?  m68k passes all arguments on stack.
+ * And we need all registers saved, which means a bunch of stuff pushed
+ * on top of pt_regs, which means that sys_clone() arguments would be
+ * buried.  We could, of course, copy them, but it's too costly for no
+ * good reason - generic clone() would have to copy them *again* for
+ * do_fork() anyway.  So in this case it's actually better to pass pt_regs *
+ * and extract arguments for do_fork() from there.  Eventually we might
+ * go for calling do_fork() directly from the wrapper, but only after we
+ * are finished with do_fork() prototype conversion.
  */
-
-asmlinkage int m68k_fork(struct pt_regs *regs)
-{
-#ifdef CONFIG_MMU
-	return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
-#else
-	return -EINVAL;
-#endif
-}
-
-asmlinkage int m68k_vfork(struct pt_regs *regs)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0,
-		       NULL, NULL);
-}
-
 asmlinkage int m68k_clone(struct pt_regs *regs)
 {
-	unsigned long clone_flags;
-	unsigned long newsp;
-	int __user *parent_tidptr, *child_tidptr;
-
-	/* syscall2 puts clone_flags in d1 and usp in d2 */
-	clone_flags = regs->d1;
-	newsp = regs->d2;
-	parent_tidptr = (int __user *)regs->d3;
-	child_tidptr = (int __user *)regs->d4;
-	if (!newsp)
-		newsp = rdusp();
-	return do_fork(clone_flags, newsp, regs, 0,
-		       parent_tidptr, child_tidptr);
+	/* regs will be equal to current_pt_regs() */
+	return do_fork(regs->d1, regs->d2, 0,
+		       (int __user *)regs->d3, (int __user *)regs->d4);
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-		 unsigned long arg,
-		 struct task_struct * p, struct pt_regs * regs)
+		 unsigned long arg, struct task_struct *p)
 {
-	struct pt_regs * childregs;
-	struct switch_stack *childstack;
+	struct fork_frame {
+		struct switch_stack sw;
+		struct pt_regs regs;
+	} *frame;
 
-	childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
-	childstack = ((struct switch_stack *) childregs) - 1;
+	frame = (struct fork_frame *) (task_stack_page(p) + THREAD_SIZE) - 1;
 
-	p->thread.usp = usp;
-	p->thread.ksp = (unsigned long)childstack;
-	p->thread.esp0 = (unsigned long)childregs;
+	p->thread.ksp = (unsigned long)frame;
+	p->thread.esp0 = (unsigned long)&frame->regs;
 
 	/*
 	 * Must save the current SFC/DFC value, NOT the value when
@@ -194,25 +172,24 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	 */
 	p->thread.fs = get_fs().seg;
 
-	if (unlikely(!regs)) {
+	if (unlikely(p->flags & PF_KTHREAD)) {
 		/* kernel thread */
-		memset(childstack, 0,
-			sizeof(struct switch_stack) + sizeof(struct pt_regs));
-		childregs->sr = PS_S;
-		childstack->a3 = usp; /* function */
-		childstack->d7 = arg;
-		childstack->retpc = (unsigned long)ret_from_kernel_thread;
+		memset(frame, 0, sizeof(struct fork_frame));
+		frame->regs.sr = PS_S;
+		frame->sw.a3 = usp; /* function */
+		frame->sw.d7 = arg;
+		frame->sw.retpc = (unsigned long)ret_from_kernel_thread;
 		p->thread.usp = 0;
 		return 0;
 	}
-	*childregs = *regs;
-	childregs->d0 = 0;
-
-	*childstack = ((struct switch_stack *) regs)[-1];
-	childstack->retpc = (unsigned long)ret_from_fork;
+	memcpy(frame, container_of(current_pt_regs(), struct fork_frame, regs),
+		sizeof(struct fork_frame));
+	frame->regs.d0 = 0;
+	frame->sw.retpc = (unsigned long)ret_from_fork;
+	p->thread.usp = usp ?: rdusp();
 
 	if (clone_flags & CLONE_SETTLS)
-		task_thread_info(p)->tp_value = regs->d5;
+		task_thread_info(p)->tp_value = frame->regs.d5;
 
 #ifdef CONFIG_FPU
 	if (!FPU_IS_EMU) {
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 710a528..9a396cd 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -108,8 +108,9 @@ int handle_kernel_fault(struct pt_regs *regs)
 	return 1;
 }
 
-void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
+void ptrace_signal_deliver(void)
 {
+	struct pt_regs *regs = signal_pt_regs();
 	if (regs->orig_d0 < 0)
 		return;
 	switch (regs->d0) {
diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S
index 4fc2e29..c30da5b 100644
--- a/arch/m68k/kernel/syscalltable.S
+++ b/arch/m68k/kernel/syscalltable.S
@@ -22,7 +22,7 @@ ALIGN
 ENTRY(sys_call_table)
 	.long sys_restart_syscall	/* 0 - old "setup()" system call, used for restarting */
 	.long sys_exit
-	.long sys_fork
+	.long __sys_fork
 	.long sys_read
 	.long sys_write
 	.long sys_open			/* 5 */
@@ -140,7 +140,7 @@ ENTRY(sys_call_table)
 	.long sys_ipc
 	.long sys_fsync
 	.long sys_sigreturn
-	.long sys_clone			/* 120 */
+	.long __sys_clone		/* 120 */
 	.long sys_setdomainname
 	.long sys_newuname
 	.long sys_cacheflush		/* modify_ldt for i386 */
@@ -210,7 +210,7 @@ ENTRY(sys_call_table)
 	.long sys_sendfile
 	.long sys_ni_syscall		/* streams1 */
 	.long sys_ni_syscall		/* streams2 */
-	.long sys_vfork			/* 190 */
+	.long __sys_vfork		/* 190 */
 	.long sys_getrlimit
 	.long sys_mmap2
 	.long sys_truncate64
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 388e5cc..cbc624a 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -506,7 +506,7 @@ static inline void bus_error030 (struct frame *fp)
 		addr -= 2;
 
 	if (buserr_type & SUN3_BUSERR_INVALID) {
-		if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
+		if (!mmu_emu_handle_fault(addr, 1, 0))
 			do_page_fault (&fp->ptregs, addr, 0);
        } else {
 #ifdef DEBUG
diff --git a/arch/m68k/lib/memcpy.c b/arch/m68k/lib/memcpy.c
index 10ca051..c1e2dfb 100644
--- a/arch/m68k/lib/memcpy.c
+++ b/arch/m68k/lib/memcpy.c
@@ -10,7 +10,7 @@
 void *memcpy(void *to, const void *from, size_t n)
 {
 	void *xto = to;
-	size_t temp, temp1;
+	size_t temp;
 
 	if (!n)
 		return xto;
@@ -47,6 +47,7 @@ void *memcpy(void *to, const void *from, size_t n)
 		for (; temp; temp--)
 			*lto++ = *lfrom++;
 #else
+		size_t temp1;
 		asm volatile (
 			"	movel %2,%3\n"
 			"	andw  #7,%3\n"
diff --git a/arch/m68k/math-emu/fp_log.c b/arch/m68k/math-emu/fp_log.c
index 3384a52..0663067 100644
--- a/arch/m68k/math-emu/fp_log.c
+++ b/arch/m68k/math-emu/fp_log.c
@@ -50,7 +50,7 @@ fp_fsqrt(struct fp_ext *dest, struct fp_ext *src)
 	 * sqrt(m*2^e) =
 	 *		 sqrt(2*m) * 2^(p)	, if e = 2*p + 1
 	 *
-	 * So we use the last bit of the exponent to decide wether to
+	 * So we use the last bit of the exponent to decide whether to
 	 * use the m or 2*m.
 	 *
 	 * Since only the fractional part of the mantissa is stored and
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
index 27b5ce0..f0e05bc 100644
--- a/arch/m68k/mm/init.c
+++ b/arch/m68k/mm/init.c
@@ -1,5 +1,225 @@
+/*
+ *  linux/arch/m68k/mm/init.c
+ *
+ *  Copyright (C) 1995  Hamish Macdonald
+ *
+ *  Contains common initialization routines, specific init code moved
+ *  to motorola.c and sun3mmu.c
+ */
+
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/gfp.h>
+
+#include <asm/setup.h>
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#ifdef CONFIG_ATARI
+#include <asm/atari_stram.h>
+#endif
+#include <asm/sections.h>
+#include <asm/tlb.h>
+
+/*
+ * ZERO_PAGE is a special page that is used for zero-initialized
+ * data and COW.
+ */
+void *empty_zero_page;
+EXPORT_SYMBOL(empty_zero_page);
+
 #ifdef CONFIG_MMU
-#include "init_mm.c"
+
+pg_data_t pg_data_map[MAX_NUMNODES];
+EXPORT_SYMBOL(pg_data_map);
+
+int m68k_virt_to_node_shift;
+
+#ifndef CONFIG_SINGLE_MEMORY_CHUNK
+pg_data_t *pg_data_table[65];
+EXPORT_SYMBOL(pg_data_table);
+#endif
+
+void __init m68k_setup_node(int node)
+{
+#ifndef CONFIG_SINGLE_MEMORY_CHUNK
+	struct mem_info *info = m68k_memory + node;
+	int i, end;
+
+	i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
+	end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
+	for (; i <= end; i++) {
+		if (pg_data_table[i])
+			printk("overlap at %u for chunk %u\n", i, node);
+		pg_data_table[i] = pg_data_map + node;
+	}
+#endif
+	pg_data_map[node].bdata = bootmem_node_data + node;
+	node_set_online(node);
+}
+
+extern void init_pointer_table(unsigned long ptable);
+extern pmd_t *zero_pgtable;
+
+#else /* CONFIG_MMU */
+
+/*
+ * 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 of the world.
+	 */
+	unsigned long end_mem = memory_end & PAGE_MASK;
+	unsigned long zones_size[MAX_NR_ZONES] = { 0, };
+
+	high_memory = (void *) end_mem;
+
+	empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
+	memset(empty_zero_page, 0, PAGE_SIZE);
+
+	/*
+	 * Set up SFC/DFC registers (user data space).
+	 */
+	set_fs (USER_DS);
+
+	zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
+	free_area_init(zones_size);
+}
+
+#endif /* CONFIG_MMU */
+
+void free_initmem(void)
+{
+#ifndef CONFIG_MMU_SUN3
+	unsigned long addr;
+
+	addr = (unsigned long) __init_begin;
+	for (; addr < ((unsigned long) __init_end); addr += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(addr));
+		init_page_count(virt_to_page(addr));
+		free_page(addr);
+		totalram_pages++;
+	}
+	pr_notice("Freeing unused kernel memory: %luk freed (0x%x - 0x%x)\n",
+		(addr - (unsigned long) __init_begin) >> 10,
+		(unsigned int) __init_begin, (unsigned int) __init_end);
+#endif /* CONFIG_MMU_SUN3 */
+}
+
+#if defined(CONFIG_MMU) && !defined(CONFIG_COLDFIRE)
+#define VECTORS	&vectors[0]
 #else
-#include "init_no.c"
+#define VECTORS	_ramvec
+#endif
+
+void __init print_memmap(void)
+{
+#define UL(x) ((unsigned long) (x))
+#define MLK(b, t) UL(b), UL(t), (UL(t) - UL(b)) >> 10
+#define MLM(b, t) UL(b), UL(t), (UL(t) - UL(b)) >> 20
+#define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), 1024)
+
+	pr_notice("Virtual kernel memory layout:\n"
+		"    vector  : 0x%08lx - 0x%08lx   (%4ld KiB)\n"
+		"    kmap    : 0x%08lx - 0x%08lx   (%4ld MiB)\n"
+		"    vmalloc : 0x%08lx - 0x%08lx   (%4ld MiB)\n"
+		"    lowmem  : 0x%08lx - 0x%08lx   (%4ld MiB)\n"
+		"      .init : 0x%p" " - 0x%p" "   (%4d KiB)\n"
+		"      .text : 0x%p" " - 0x%p" "   (%4d KiB)\n"
+		"      .data : 0x%p" " - 0x%p" "   (%4d KiB)\n"
+		"      .bss  : 0x%p" " - 0x%p" "   (%4d KiB)\n",
+		MLK(VECTORS, VECTORS + 256),
+		MLM(KMAP_START, KMAP_END),
+		MLM(VMALLOC_START, VMALLOC_END),
+		MLM(PAGE_OFFSET, (unsigned long)high_memory),
+		MLK_ROUNDUP(__init_begin, __init_end),
+		MLK_ROUNDUP(_stext, _etext),
+		MLK_ROUNDUP(_sdata, _edata),
+		MLK_ROUNDUP(__bss_start, __bss_stop));
+}
+
+void __init mem_init(void)
+{
+	pg_data_t *pgdat;
+	int codepages = 0;
+	int datapages = 0;
+	int initpages = 0;
+	int i;
+
+	/* this will put all memory onto the freelists */
+	totalram_pages = num_physpages = 0;
+	for_each_online_pgdat(pgdat) {
+		num_physpages += pgdat->node_present_pages;
+
+		totalram_pages += free_all_bootmem_node(pgdat);
+		for (i = 0; i < pgdat->node_spanned_pages; i++) {
+			struct page *page = pgdat->node_mem_map + i;
+			char *addr = page_to_virt(page);
+
+			if (!PageReserved(page))
+				continue;
+			if (addr >= _text &&
+			    addr < _etext)
+				codepages++;
+			else if (addr >= __init_begin &&
+				 addr < __init_end)
+				initpages++;
+			else
+				datapages++;
+		}
+	}
+
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
+	/* insert pointer tables allocated so far into the tablelist */
+	init_pointer_table((unsigned long)kernel_pg_dir);
+	for (i = 0; i < PTRS_PER_PGD; i++) {
+		if (pgd_present(kernel_pg_dir[i]))
+			init_pointer_table(__pgd_page(kernel_pg_dir[i]));
+	}
+
+	/* insert also pointer table that we used to unmap the zero page */
+	if (zero_pgtable)
+		init_pointer_table((unsigned long)zero_pgtable);
+#endif
+
+	pr_info("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
+	       nr_free_pages() << (PAGE_SHIFT-10),
+	       totalram_pages << (PAGE_SHIFT-10),
+	       codepages << (PAGE_SHIFT-10),
+	       datapages << (PAGE_SHIFT-10),
+	       initpages << (PAGE_SHIFT-10));
+	print_memmap();
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+	int pages = 0;
+	for (; start < end; start += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(start));
+		init_page_count(virt_to_page(start));
+		free_page(start);
+		totalram_pages++;
+		pages++;
+	}
+	pr_notice("Freeing initrd memory: %dk freed\n",
+		pages << (PAGE_SHIFT - 10));
+}
 #endif
diff --git a/arch/m68k/mm/init_mm.c b/arch/m68k/mm/init_mm.c
deleted file mode 100644
index 282f9de..0000000
--- a/arch/m68k/mm/init_mm.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- *  linux/arch/m68k/mm/init.c
- *
- *  Copyright (C) 1995  Hamish Macdonald
- *
- *  Contains common initialization routines, specific init code moved
- *  to motorola.c and sun3mmu.c
- */
-
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/gfp.h>
-
-#include <asm/setup.h>
-#include <asm/uaccess.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm/traps.h>
-#include <asm/machdep.h>
-#include <asm/io.h>
-#ifdef CONFIG_ATARI
-#include <asm/atari_stram.h>
-#endif
-#include <asm/sections.h>
-#include <asm/tlb.h>
-
-pg_data_t pg_data_map[MAX_NUMNODES];
-EXPORT_SYMBOL(pg_data_map);
-
-int m68k_virt_to_node_shift;
-
-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
-pg_data_t *pg_data_table[65];
-EXPORT_SYMBOL(pg_data_table);
-#endif
-
-void __init m68k_setup_node(int node)
-{
-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
-	struct mem_info *info = m68k_memory + node;
-	int i, end;
-
-	i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
-	end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
-	for (; i <= end; i++) {
-		if (pg_data_table[i])
-			printk("overlap at %u for chunk %u\n", i, node);
-		pg_data_table[i] = pg_data_map + node;
-	}
-#endif
-	pg_data_map[node].bdata = bootmem_node_data + node;
-	node_set_online(node);
-}
-
-
-/*
- * ZERO_PAGE is a special page that is used for zero-initialized
- * data and COW.
- */
-
-void *empty_zero_page;
-EXPORT_SYMBOL(empty_zero_page);
-
-extern void init_pointer_table(unsigned long ptable);
-
-/* References to section boundaries */
-
-extern pmd_t *zero_pgtable;
-
-#if defined(CONFIG_MMU) && !defined(CONFIG_COLDFIRE)
-#define VECTORS	&vectors[0]
-#else
-#define VECTORS	_ramvec
-#endif
-
-void __init print_memmap(void)
-{
-#define UL(x) ((unsigned long) (x))
-#define MLK(b, t) UL(b), UL(t), (UL(t) - UL(b)) >> 10
-#define MLM(b, t) UL(b), UL(t), (UL(t) - UL(b)) >> 20
-#define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), 1024)
-
-	pr_notice("Virtual kernel memory layout:\n"
-		"    vector  : 0x%08lx - 0x%08lx   (%4ld KiB)\n"
-		"    kmap    : 0x%08lx - 0x%08lx   (%4ld MiB)\n"
-		"    vmalloc : 0x%08lx - 0x%08lx   (%4ld MiB)\n"
-		"    lowmem  : 0x%08lx - 0x%08lx   (%4ld MiB)\n"
-		"      .init : 0x%p" " - 0x%p" "   (%4d KiB)\n"
-		"      .text : 0x%p" " - 0x%p" "   (%4d KiB)\n"
-		"      .data : 0x%p" " - 0x%p" "   (%4d KiB)\n"
-		"      .bss  : 0x%p" " - 0x%p" "   (%4d KiB)\n",
-		MLK(VECTORS, VECTORS + 256),
-		MLM(KMAP_START, KMAP_END),
-		MLM(VMALLOC_START, VMALLOC_END),
-		MLM(PAGE_OFFSET, (unsigned long)high_memory),
-		MLK_ROUNDUP(__init_begin, __init_end),
-		MLK_ROUNDUP(_stext, _etext),
-		MLK_ROUNDUP(_sdata, _edata),
-		MLK_ROUNDUP(__bss_start, __bss_stop));
-}
-
-void __init mem_init(void)
-{
-	pg_data_t *pgdat;
-	int codepages = 0;
-	int datapages = 0;
-	int initpages = 0;
-	int i;
-
-	/* this will put all memory onto the freelists */
-	totalram_pages = num_physpages = 0;
-	for_each_online_pgdat(pgdat) {
-		num_physpages += pgdat->node_present_pages;
-
-		totalram_pages += free_all_bootmem_node(pgdat);
-		for (i = 0; i < pgdat->node_spanned_pages; i++) {
-			struct page *page = pgdat->node_mem_map + i;
-			char *addr = page_to_virt(page);
-
-			if (!PageReserved(page))
-				continue;
-			if (addr >= _text &&
-			    addr < _etext)
-				codepages++;
-			else if (addr >= __init_begin &&
-				 addr < __init_end)
-				initpages++;
-			else
-				datapages++;
-		}
-	}
-
-#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
-	/* insert pointer tables allocated so far into the tablelist */
-	init_pointer_table((unsigned long)kernel_pg_dir);
-	for (i = 0; i < PTRS_PER_PGD; i++) {
-		if (pgd_present(kernel_pg_dir[i]))
-			init_pointer_table(__pgd_page(kernel_pg_dir[i]));
-	}
-
-	/* insert also pointer table that we used to unmap the zero page */
-	if (zero_pgtable)
-		init_pointer_table((unsigned long)zero_pgtable);
-#endif
-
-	printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
-	       nr_free_pages() << (PAGE_SHIFT-10),
-	       totalram_pages << (PAGE_SHIFT-10),
-	       codepages << (PAGE_SHIFT-10),
-	       datapages << (PAGE_SHIFT-10),
-	       initpages << (PAGE_SHIFT-10));
-	print_memmap();
-}
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-	int pages = 0;
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(start));
-		init_page_count(virt_to_page(start));
-		free_page(start);
-		totalram_pages++;
-		pages++;
-	}
-	printk ("Freeing initrd memory: %dk freed\n", pages);
-}
-#endif
diff --git a/arch/m68k/mm/init_no.c b/arch/m68k/mm/init_no.c
deleted file mode 100644
index 688e366..0000000
--- a/arch/m68k/mm/init_no.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- *  linux/arch/m68knommu/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/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/sections.h>
-#include <asm/segment.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/machdep.h>
-
-/*
- * ZERO_PAGE is a special page that is used for zero-initialized
- * data and COW.
- */
-void *empty_zero_page;
-
-/*
- * 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 of the world.
-	 */
-	unsigned long end_mem   = memory_end & PAGE_MASK;
-	unsigned long zones_size[MAX_NR_ZONES] = {0, };
-
-	empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
-	memset(empty_zero_page, 0, PAGE_SIZE);
-
-	/*
-	 * Set up SFC/DFC registers (user data space).
-	 */
-	set_fs (USER_DS);
-
-	zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
-	free_area_init(zones_size);
-}
-
-void __init mem_init(void)
-{
-	int codek = 0, datak = 0, initk = 0;
-	unsigned long tmp;
-	unsigned long len = _ramend - _rambase;
-	unsigned long start_mem = memory_start; /* DAVIDM - these must start at end of kernel */
-	unsigned long end_mem   = memory_end; /* DAVIDM - this must not include kernel stack at top */
-
-	pr_debug("Mem_init: start=%lx, end=%lx\n", start_mem, end_mem);
-
-	end_mem &= PAGE_MASK;
-	high_memory = (void *) end_mem;
-
-	start_mem = PAGE_ALIGN(start_mem);
-	max_mapnr = num_physpages = (((unsigned long) high_memory) - PAGE_OFFSET) >> PAGE_SHIFT;
-
-	/* this will put all memory onto the freelists */
-	totalram_pages = free_all_bootmem();
-
-	codek = (_etext - _stext) >> 10;
-	datak = (__bss_stop - _sdata) >> 10;
-	initk = (__init_begin - __init_end) >> 10;
-
-	tmp = nr_free_pages() << PAGE_SHIFT;
-	printk(KERN_INFO "Memory available: %luk/%luk RAM, (%dk kernel code, %dk data)\n",
-	       tmp >> 10,
-	       len >> 10,
-	       codek,
-	       datak
-	       );
-}
-
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-	int pages = 0;
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(start));
-		init_page_count(virt_to_page(start));
-		free_page(start);
-		totalram_pages++;
-		pages++;
-	}
-	pr_notice("Freeing initrd memory: %luk freed\n",
-		  pages * (PAGE_SIZE / 1024));
-}
-#endif
-
-void free_initmem(void)
-{
-#ifdef CONFIG_RAMKERNEL
-	unsigned long addr;
-	/*
-	 * The following code should be cool even if these sections
-	 * are not page aligned.
-	 */
-	addr = PAGE_ALIGN((unsigned long) __init_begin);
-	/* next to check that the page we free is not a partial page */
-	for (; addr + PAGE_SIZE < ((unsigned long) __init_end); addr += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(addr));
-		init_page_count(virt_to_page(addr));
-		free_page(addr);
-		totalram_pages++;
-	}
-	pr_notice("Freeing unused kernel memory: %luk freed (0x%x - 0x%x)\n",
-			(addr - PAGE_ALIGN((unsigned long) __init_begin)) >> 10,
-			(int)(PAGE_ALIGN((unsigned long) __init_begin)),
-			(int)(addr - PAGE_SIZE));
-#endif
-}
-
diff --git a/arch/m68k/mm/mcfmmu.c b/arch/m68k/mm/mcfmmu.c
index 875b800..f58fafe 100644
--- a/arch/m68k/mm/mcfmmu.c
+++ b/arch/m68k/mm/mcfmmu.c
@@ -29,10 +29,6 @@ atomic_t nr_free_contexts;
 struct mm_struct *context_mm[LAST_CONTEXT+1];
 extern unsigned long num_pages;
 
-void free_initmem(void)
-{
-}
-
 /*
  * ColdFire paging_init derived from sun3.
  */
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
index 0dafa69..251c543 100644
--- a/arch/m68k/mm/motorola.c
+++ b/arch/m68k/mm/motorola.c
@@ -304,17 +304,3 @@ void __init paging_init(void)
 	}
 }
 
-void free_initmem(void)
-{
-	unsigned long addr;
-
-	addr = (unsigned long)__init_begin;
-	for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
-		virt_to_page(addr)->flags &= ~(1 << PG_reserved);
-		init_page_count(virt_to_page(addr));
-		free_page(addr);
-		totalram_pages++;
-	}
-}
-
-
diff --git a/arch/m68k/mm/sun3mmu.c b/arch/m68k/mm/sun3mmu.c
index e080406..269f811 100644
--- a/arch/m68k/mm/sun3mmu.c
+++ b/arch/m68k/mm/sun3mmu.c
@@ -30,10 +30,6 @@ const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
 
 extern unsigned long num_pages;
 
-void free_initmem(void)
-{
-}
-
 /* For the sun3 we try to follow the i386 paging_init() more closely */
 /* start_mem and end_mem have PAGE_OFFSET added already */
 /* now sets up tables using sun3 PTEs rather than i386 as before. --m */
diff --git a/arch/m68k/platform/coldfire/clk.c b/arch/m68k/platform/coldfire/clk.c
index 9cd13b4..fddfdcc 100644
--- a/arch/m68k/platform/coldfire/clk.c
+++ b/arch/m68k/platform/coldfire/clk.c
@@ -19,37 +19,58 @@
 #include <asm/mcfsim.h>
 #include <asm/mcfclk.h>
 
-/***************************************************************************/
-#ifndef MCFPM_PPMCR0
-struct clk *clk_get(struct device *dev, const char *id)
+static DEFINE_SPINLOCK(clk_lock);
+
+#ifdef MCFPM_PPMCR0
+/*
+ *	For more advanced ColdFire parts that have clocks that can be enabled
+ *	we supply enable/disable functions. These must properly define their
+ *	clocks in their platform specific code.
+ */
+void __clk_init_enabled(struct clk *clk)
 {
-	return NULL;
+	clk->enabled = 1;
+	clk->clk_ops->enable(clk);
 }
-EXPORT_SYMBOL(clk_get);
 
-int clk_enable(struct clk *clk)
+void __clk_init_disabled(struct clk *clk)
 {
-	return 0;
+	clk->enabled = 0;
+	clk->clk_ops->disable(clk);
 }
-EXPORT_SYMBOL(clk_enable);
 
-void clk_disable(struct clk *clk)
+static void __clk_enable0(struct clk *clk)
 {
+	__raw_writeb(clk->slot, MCFPM_PPMCR0);
 }
-EXPORT_SYMBOL(clk_disable);
 
-void clk_put(struct clk *clk)
+static void __clk_disable0(struct clk *clk)
+{
+	__raw_writeb(clk->slot, MCFPM_PPMSR0);
+}
+
+struct clk_ops clk_ops0 = {
+	.enable		= __clk_enable0,
+	.disable	= __clk_disable0,
+};
+
+#ifdef MCFPM_PPMCR1
+static void __clk_enable1(struct clk *clk)
 {
+	__raw_writeb(clk->slot, MCFPM_PPMCR1);
 }
-EXPORT_SYMBOL(clk_put);
 
-unsigned long clk_get_rate(struct clk *clk)
+static void __clk_disable1(struct clk *clk)
 {
-	return MCF_CLK;
+	__raw_writeb(clk->slot, MCFPM_PPMSR1);
 }
-EXPORT_SYMBOL(clk_get_rate);
-#else
-static DEFINE_SPINLOCK(clk_lock);
+
+struct clk_ops clk_ops1 = {
+	.enable		= __clk_enable1,
+	.disable	= __clk_disable1,
+};
+#endif /* MCFPM_PPMCR1 */
+#endif /* MCFPM_PPMCR0 */
 
 struct clk *clk_get(struct device *dev, const char *id)
 {
@@ -101,48 +122,3 @@ unsigned long clk_get_rate(struct clk *clk)
 EXPORT_SYMBOL(clk_get_rate);
 
 /***************************************************************************/
-
-void __clk_init_enabled(struct clk *clk)
-{
-	clk->enabled = 1;
-	clk->clk_ops->enable(clk);
-}
-
-void __clk_init_disabled(struct clk *clk)
-{
-	clk->enabled = 0;
-	clk->clk_ops->disable(clk);
-}
-
-static void __clk_enable0(struct clk *clk)
-{
-	__raw_writeb(clk->slot, MCFPM_PPMCR0);
-}
-
-static void __clk_disable0(struct clk *clk)
-{
-	__raw_writeb(clk->slot, MCFPM_PPMSR0);
-}
-
-struct clk_ops clk_ops0 = {
-	.enable		= __clk_enable0,
-	.disable	= __clk_disable0,
-};
-
-#ifdef MCFPM_PPMCR1
-static void __clk_enable1(struct clk *clk)
-{
-	__raw_writeb(clk->slot, MCFPM_PPMCR1);
-}
-
-static void __clk_disable1(struct clk *clk)
-{
-	__raw_writeb(clk->slot, MCFPM_PPMSR1);
-}
-
-struct clk_ops clk_ops1 = {
-	.enable		= __clk_enable1,
-	.disable	= __clk_disable1,
-};
-#endif /* MCFPM_PPMCR1 */
-#endif /* MCFPM_PPMCR0 */
diff --git a/arch/m68k/platform/coldfire/intc-5249.c b/arch/m68k/platform/coldfire/intc-5249.c
index 0864b83..b0d1641 100644
--- a/arch/m68k/platform/coldfire/intc-5249.c
+++ b/arch/m68k/platform/coldfire/intc-5249.c
@@ -21,7 +21,7 @@ static void intc2_irq_gpio_mask(struct irq_data *d)
 {
 	u32 imr;
 	imr = readl(MCFSIM2_GPIOINTENABLE);
-	imr &= ~(0x1 << (d->irq - MCFINTC2_GPIOIRQ0));
+	imr &= ~(0x1 << (d->irq - MCF_IRQ_GPIO0));
 	writel(imr, MCFSIM2_GPIOINTENABLE);
 }
 
@@ -29,13 +29,13 @@ static void intc2_irq_gpio_unmask(struct irq_data *d)
 {
 	u32 imr;
 	imr = readl(MCFSIM2_GPIOINTENABLE);
-	imr |= (0x1 << (d->irq - MCFINTC2_GPIOIRQ0));
+	imr |= (0x1 << (d->irq - MCF_IRQ_GPIO0));
 	writel(imr, MCFSIM2_GPIOINTENABLE);
 }
 
 static void intc2_irq_gpio_ack(struct irq_data *d)
 {
-	writel(0x1 << (d->irq - MCFINTC2_GPIOIRQ0), MCFSIM2_GPIOINTCLEAR);
+	writel(0x1 << (d->irq - MCF_IRQ_GPIO0), MCFSIM2_GPIOINTCLEAR);
 }
 
 static struct irq_chip intc2_irq_gpio_chip = {
@@ -50,7 +50,7 @@ static int __init mcf_intc2_init(void)
 	int irq;
 
 	/* GPIO interrupt sources */
-	for (irq = MCFINTC2_GPIOIRQ0; (irq <= MCFINTC2_GPIOIRQ7); irq++) {
+	for (irq = MCF_IRQ_GPIO0; (irq <= MCF_IRQ_GPIO7); irq++) {
 		irq_set_chip(irq, &intc2_irq_gpio_chip);
 		irq_set_handler(irq, handle_edge_irq);
 	}
diff --git a/arch/m68k/platform/coldfire/m5206.c b/arch/m68k/platform/coldfire/m5206.c
index 6bfbeeb..0e55f44 100644
--- a/arch/m68k/platform/coldfire/m5206.c
+++ b/arch/m68k/platform/coldfire/m5206.c
@@ -16,6 +16,26 @@
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
+#include <asm/mcfclk.h>
+
+/***************************************************************************/
+
+DEFINE_CLK(pll, "pll.0", MCF_CLK);
+DEFINE_CLK(sys, "sys.0", MCF_BUSCLK);
+DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK);
+DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK);
+DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
+DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
+
+struct clk *mcf_clks[] = {
+	&clk_pll,
+	&clk_sys,
+	&clk_mcftmr0,
+	&clk_mcftmr1,
+	&clk_mcfuart0,
+	&clk_mcfuart1,
+	NULL
+};
 
 /***************************************************************************/
 
diff --git a/arch/m68k/platform/coldfire/m523x.c b/arch/m68k/platform/coldfire/m523x.c
index ff37fe9..2b10e9f 100644
--- a/arch/m68k/platform/coldfire/m523x.c
+++ b/arch/m68k/platform/coldfire/m523x.c
@@ -19,6 +19,34 @@
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
+#include <asm/mcfclk.h>
+
+/***************************************************************************/
+
+DEFINE_CLK(pll, "pll.0", MCF_CLK);
+DEFINE_CLK(sys, "sys.0", MCF_BUSCLK);
+DEFINE_CLK(mcfpit0, "mcfpit.0", MCF_CLK);
+DEFINE_CLK(mcfpit1, "mcfpit.1", MCF_CLK);
+DEFINE_CLK(mcfpit2, "mcfpit.2", MCF_CLK);
+DEFINE_CLK(mcfpit3, "mcfpit.3", MCF_CLK);
+DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
+DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
+DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK);
+DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK);
+
+struct clk *mcf_clks[] = {
+	&clk_pll,
+	&clk_sys,
+	&clk_mcfpit0,
+	&clk_mcfpit1,
+	&clk_mcfpit2,
+	&clk_mcfpit3,
+	&clk_mcfuart0,
+	&clk_mcfuart1,
+	&clk_mcfuart2,
+	&clk_fec0,
+	NULL
+};
 
 /***************************************************************************/
 
diff --git a/arch/m68k/platform/coldfire/m5249.c b/arch/m68k/platform/coldfire/m5249.c
index 23b19cb..c80b5e5 100644
--- a/arch/m68k/platform/coldfire/m5249.c
+++ b/arch/m68k/platform/coldfire/m5249.c
@@ -16,6 +16,26 @@
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
+#include <asm/mcfclk.h>
+
+/***************************************************************************/
+
+DEFINE_CLK(pll, "pll.0", MCF_CLK);
+DEFINE_CLK(sys, "sys.0", MCF_BUSCLK);
+DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK);
+DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK);
+DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
+DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
+
+struct clk *mcf_clks[] = {
+	&clk_pll,
+	&clk_sys,
+	&clk_mcftmr0,
+	&clk_mcftmr1,
+	&clk_mcfuart0,
+	&clk_mcfuart1,
+	NULL
+};
 
 /***************************************************************************/
 
@@ -28,8 +48,8 @@ static struct resource m5249_smc91x_resources[] = {
 		.flags		= IORESOURCE_MEM,
 	},
 	{
-		.start		= MCFINTC2_GPIOIRQ6,
-		.end		= MCFINTC2_GPIOIRQ6,
+		.start		= MCF_IRQ_GPIO6,
+		.end		= MCF_IRQ_GPIO6,
 		.flags		= IORESOURCE_IRQ,
 	},
 };
@@ -75,8 +95,8 @@ static void __init m5249_smc91x_init(void)
 	gpio = readl(MCFSIM2_GPIOINTENABLE);
 	writel(gpio | 0x40, MCFSIM2_GPIOINTENABLE);
 
-	gpio = readl(MCFSIM2_INTLEVEL5);
-	writel(gpio | 0x04000000, MCFSIM2_INTLEVEL5);
+	gpio = readl(MCFINTC2_INTPRI5);
+	writel(gpio | 0x04000000, MCFINTC2_INTPRI5);
 }
 
 #endif /* CONFIG_M5249C3 */
diff --git a/arch/m68k/platform/coldfire/m525x.c b/arch/m68k/platform/coldfire/m525x.c
index fce8f8a..5b9f657 100644
--- a/arch/m68k/platform/coldfire/m525x.c
+++ b/arch/m68k/platform/coldfire/m525x.c
@@ -16,6 +16,26 @@
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
+#include <asm/mcfclk.h>
+
+/***************************************************************************/
+
+DEFINE_CLK(pll, "pll.0", MCF_CLK);
+DEFINE_CLK(sys, "sys.0", MCF_BUSCLK);
+DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK);
+DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK);
+DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
+DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
+
+struct clk *mcf_clks[] = {
+	&clk_pll,
+	&clk_sys,
+	&clk_mcftmr0,
+	&clk_mcftmr1,
+	&clk_mcfuart0,
+	&clk_mcfuart1,
+	NULL
+};
 
 /***************************************************************************/
 
diff --git a/arch/m68k/platform/coldfire/m5272.c b/arch/m68k/platform/coldfire/m5272.c
index 45b246d..a8c5856 100644
--- a/arch/m68k/platform/coldfire/m5272.c
+++ b/arch/m68k/platform/coldfire/m5272.c
@@ -19,6 +19,7 @@
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfuart.h>
+#include <asm/mcfclk.h>
 
 /***************************************************************************/
 
@@ -30,6 +31,31 @@ unsigned char ledbank = 0xff;
 
 /***************************************************************************/
 
+DEFINE_CLK(pll, "pll.0", MCF_CLK);
+DEFINE_CLK(sys, "sys.0", MCF_BUSCLK);
+DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK);
+DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK);
+DEFINE_CLK(mcftmr2, "mcftmr.2", MCF_BUSCLK);
+DEFINE_CLK(mcftmr3, "mcftmr.3", MCF_BUSCLK);
+DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
+DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
+DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK);
+
+struct clk *mcf_clks[] = {
+	&clk_pll,
+	&clk_sys,
+	&clk_mcftmr0,
+	&clk_mcftmr1,
+	&clk_mcftmr2,
+	&clk_mcftmr3,
+	&clk_mcfuart0,
+	&clk_mcfuart1,
+	&clk_fec0,
+	NULL
+};
+
+/***************************************************************************/
+
 static void __init m5272_uarts_init(void)
 {
 	u32 v;
diff --git a/arch/m68k/platform/coldfire/m527x.c b/arch/m68k/platform/coldfire/m527x.c
index 1431ba0..6fbfe90 100644
--- a/arch/m68k/platform/coldfire/m527x.c
+++ b/arch/m68k/platform/coldfire/m527x.c
@@ -20,6 +20,36 @@
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfuart.h>
+#include <asm/mcfclk.h>
+
+/***************************************************************************/
+
+DEFINE_CLK(pll, "pll.0", MCF_CLK);
+DEFINE_CLK(sys, "sys.0", MCF_BUSCLK);
+DEFINE_CLK(mcfpit0, "mcfpit.0", MCF_CLK);
+DEFINE_CLK(mcfpit1, "mcfpit.1", MCF_CLK);
+DEFINE_CLK(mcfpit2, "mcfpit.2", MCF_CLK);
+DEFINE_CLK(mcfpit3, "mcfpit.3", MCF_CLK);
+DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
+DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
+DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK);
+DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK);
+DEFINE_CLK(fec1, "fec.1", MCF_BUSCLK);
+
+struct clk *mcf_clks[] = {
+	&clk_pll,
+	&clk_sys,
+	&clk_mcfpit0,
+	&clk_mcfpit1,
+	&clk_mcfpit2,
+	&clk_mcfpit3,
+	&clk_mcfuart0,
+	&clk_mcfuart1,
+	&clk_mcfuart2,
+	&clk_fec0,
+	&clk_fec1,
+	NULL
+};
 
 /***************************************************************************/
 
diff --git a/arch/m68k/platform/coldfire/m528x.c b/arch/m68k/platform/coldfire/m528x.c
index f9f7e6a..83b7dad 100644
--- a/arch/m68k/platform/coldfire/m528x.c
+++ b/arch/m68k/platform/coldfire/m528x.c
@@ -21,6 +21,34 @@
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfuart.h>
+#include <asm/mcfclk.h>
+
+/***************************************************************************/
+
+DEFINE_CLK(pll, "pll.0", MCF_CLK);
+DEFINE_CLK(sys, "sys.0", MCF_BUSCLK);
+DEFINE_CLK(mcfpit0, "mcfpit.0", MCF_CLK);
+DEFINE_CLK(mcfpit1, "mcfpit.1", MCF_CLK);
+DEFINE_CLK(mcfpit2, "mcfpit.2", MCF_CLK);
+DEFINE_CLK(mcfpit3, "mcfpit.3", MCF_CLK);
+DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
+DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
+DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK);
+DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK);
+
+struct clk *mcf_clks[] = {
+	&clk_pll,
+	&clk_sys,
+	&clk_mcfpit0,
+	&clk_mcfpit1,
+	&clk_mcfpit2,
+	&clk_mcfpit3,
+	&clk_mcfuart0,
+	&clk_mcfuart1,
+	&clk_mcfuart2,
+	&clk_fec0,
+	NULL
+};
 
 /***************************************************************************/
 
diff --git a/arch/m68k/platform/coldfire/m5307.c b/arch/m68k/platform/coldfire/m5307.c
index a568d28..8874353 100644
--- a/arch/m68k/platform/coldfire/m5307.c
+++ b/arch/m68k/platform/coldfire/m5307.c
@@ -17,6 +17,7 @@
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfwdebug.h>
+#include <asm/mcfclk.h>
 
 /***************************************************************************/
 
@@ -28,6 +29,25 @@ unsigned char ledbank = 0xff;
 
 /***************************************************************************/
 
+DEFINE_CLK(pll, "pll.0", MCF_CLK);
+DEFINE_CLK(sys, "sys.0", MCF_BUSCLK);
+DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK);
+DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK);
+DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
+DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
+
+struct clk *mcf_clks[] = {
+	&clk_pll,
+	&clk_sys,
+	&clk_mcftmr0,
+	&clk_mcftmr1,
+	&clk_mcfuart0,
+	&clk_mcfuart1,
+	NULL
+};
+
+/***************************************************************************/
+
 void __init config_BSP(char *commandp, int size)
 {
 #if defined(CONFIG_NETtel) || \
diff --git a/arch/m68k/platform/coldfire/m5407.c b/arch/m68k/platform/coldfire/m5407.c
index bb6c746..2fb3cdb 100644
--- a/arch/m68k/platform/coldfire/m5407.c
+++ b/arch/m68k/platform/coldfire/m5407.c
@@ -16,6 +16,26 @@
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
+#include <asm/mcfclk.h>
+
+/***************************************************************************/
+
+DEFINE_CLK(pll, "pll.0", MCF_CLK);
+DEFINE_CLK(sys, "sys.0", MCF_BUSCLK);
+DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK);
+DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK);
+DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
+DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
+
+struct clk *mcf_clks[] = {
+	&clk_pll,
+	&clk_sys,
+	&clk_mcftmr0,
+	&clk_mcftmr1,
+	&clk_mcfuart0,
+	&clk_mcfuart1,
+	NULL
+};
 
 /***************************************************************************/
 
diff --git a/arch/m68k/platform/coldfire/m54xx.c b/arch/m68k/platform/coldfire/m54xx.c
index b587bf3..952da53 100644
--- a/arch/m68k/platform/coldfire/m54xx.c
+++ b/arch/m68k/platform/coldfire/m54xx.c
@@ -14,19 +14,45 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/mm.h>
+#include <linux/clk.h>
 #include <linux/bootmem.h>
 #include <asm/pgalloc.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/m54xxsim.h>
 #include <asm/mcfuart.h>
+#include <asm/mcfclk.h>
 #include <asm/m54xxgpt.h>
+#include <asm/mcfclk.h>
 #ifdef CONFIG_MMU
 #include <asm/mmu_context.h>
 #endif
 
 /***************************************************************************/
 
+DEFINE_CLK(pll, "pll.0", MCF_CLK);
+DEFINE_CLK(sys, "sys.0", MCF_BUSCLK);
+DEFINE_CLK(mcfslt0, "mcfslt.0", MCF_BUSCLK);
+DEFINE_CLK(mcfslt1, "mcfslt.1", MCF_BUSCLK);
+DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
+DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
+DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK);
+DEFINE_CLK(mcfuart3, "mcfuart.3", MCF_BUSCLK);
+
+struct clk *mcf_clks[] = {
+	&clk_pll,
+	&clk_sys,
+	&clk_mcfslt0,
+	&clk_mcfslt1,
+	&clk_mcfuart0,
+	&clk_mcfuart1,
+	&clk_mcfuart2,
+	&clk_mcfuart3,
+	NULL
+};
+
+/***************************************************************************/
+
 static void __init m54xx_uarts_init(void)
 {
 	/* enable io pins */
diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c
index 78b60f5..6bbca30 100644
--- a/arch/m68k/sun3/sun3ints.c
+++ b/arch/m68k/sun3/sun3ints.c
@@ -66,6 +66,8 @@ static irqreturn_t sun3_int5(int irq, void *dev_id)
 #ifdef CONFIG_SUN3
 	intersil_clear();
 #endif
+	sun3_disable_irq(5);
+	sun3_enable_irq(5);
 #ifdef CONFIG_SUN3
 	intersil_clear();
 #endif
@@ -79,41 +81,18 @@ static irqreturn_t sun3_int5(int irq, void *dev_id)
 
 static irqreturn_t sun3_vec255(int irq, void *dev_id)
 {
-//	intersil_clear();
 	return IRQ_HANDLED;
 }
 
-static void sun3_irq_enable(struct irq_data *data)
-{
-    sun3_enable_irq(data->irq);
-};
-
-static void sun3_irq_disable(struct irq_data *data)
-{
-    sun3_disable_irq(data->irq);
-};
-
-static struct irq_chip sun3_irq_chip = {
-	.name		= "sun3",
-	.irq_startup	= m68k_irq_startup,
-	.irq_shutdown	= m68k_irq_shutdown,
-	.irq_enable	= sun3_irq_enable,
-	.irq_disable	= sun3_irq_disable,
-	.irq_mask	= sun3_irq_disable,
-	.irq_unmask	= sun3_irq_enable,
-};
-
 void __init sun3_init_IRQ(void)
 {
 	*sun3_intreg = 1;
 
-	m68k_setup_irq_controller(&sun3_irq_chip, handle_level_irq, IRQ_AUTO_1,
-				  7);
 	m68k_setup_user_interrupt(VEC_USER, 128);
 
-	if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL))
+	if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "clock", NULL))
 		pr_err("Couldn't register %s interrupt\n", "int5");
-	if (request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL))
+	if (request_irq(IRQ_AUTO_7, sun3_int7, 0, "nmi", NULL))
 		pr_err("Couldn't register %s interrupt\n", "int7");
 	if (request_irq(IRQ_USER+127, sun3_vec255, 0, "vec255", NULL))
 		pr_err("Couldn't register %s interrupt\n", "vec255");
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 4cba743..4bcf891 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -26,6 +26,9 @@ config MICROBLAZE
 	select GENERIC_ATOMIC64
 	select GENERIC_CLOCKEVENTS
 	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
+	select CLONE_BACKWARDS
 
 config SWAP
 	def_bool n
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index 8653072..c5d7670 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -1,5 +1,4 @@
-include include/asm-generic/Kbuild.asm
 
-header-y  += elf.h
 generic-y += clkdev.h
 generic-y += exec.h
+generic-y += trace_clock.h
diff --git a/arch/microblaze/include/asm/auxvec.h b/arch/microblaze/include/asm/auxvec.h
deleted file mode 100644
index 8b13789..0000000
--- a/arch/microblaze/include/asm/auxvec.h
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/arch/microblaze/include/asm/bitsperlong.h b/arch/microblaze/include/asm/bitsperlong.h
deleted file mode 100644
index 6dc0bb0..0000000
--- a/arch/microblaze/include/asm/bitsperlong.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/bitsperlong.h>
diff --git a/arch/microblaze/include/asm/byteorder.h b/arch/microblaze/include/asm/byteorder.h
deleted file mode 100644
index 3190276..0000000
--- a/arch/microblaze/include/asm/byteorder.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _ASM_MICROBLAZE_BYTEORDER_H
-#define _ASM_MICROBLAZE_BYTEORDER_H
-
-#ifdef __MICROBLAZEEL__
-#include <linux/byteorder/little_endian.h>
-#else
-#include <linux/byteorder/big_endian.h>
-#endif
-
-#endif /* _ASM_MICROBLAZE_BYTEORDER_H */
diff --git a/arch/microblaze/include/asm/dma-mapping.h b/arch/microblaze/include/asm/dma-mapping.h
index 01d2282..46460f1 100644
--- a/arch/microblaze/include/asm/dma-mapping.h
+++ b/arch/microblaze/include/asm/dma-mapping.h
@@ -114,6 +114,8 @@ static inline void __dma_sync(unsigned long paddr,
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
+
+	debug_dma_mapping_error(dev, dma_addr);
 	if (ops->mapping_error)
 		return ops->mapping_error(dev, dma_addr);
 
diff --git a/arch/microblaze/include/asm/elf.h b/arch/microblaze/include/asm/elf.h
index 640ddd4..6590244 100644
--- a/arch/microblaze/include/asm/elf.h
+++ b/arch/microblaze/include/asm/elf.h
@@ -7,119 +7,24 @@
  * License. See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #ifndef _ASM_MICROBLAZE_ELF_H
 #define _ASM_MICROBLAZE_ELF_H
 
-/*
- * Note there is no "official" ELF designation for Microblaze.
- * I've snaffled the value from the microblaze binutils source code
- * /binutils/microblaze/include/elf/microblaze.h
- */
-#define EM_MICROBLAZE		189
-#define EM_MICROBLAZE_OLD	0xbaab
-#define ELF_ARCH		EM_MICROBLAZE
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x)	((x)->e_machine == EM_MICROBLAZE \
-				 || (x)->e_machine == EM_MICROBLAZE_OLD)
-
-/*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_CLASS	ELFCLASS32
+#include <uapi/asm/elf.h>
 
 #ifndef __uClinux__
-
-/*
- * ELF register definitions..
- */
-
-#include <asm/ptrace.h>
-#include <asm/byteorder.h>
-
 #ifndef ELF_GREG_T
-#define ELF_GREG_T
-typedef unsigned long elf_greg_t;
 #endif
-
 #ifndef ELF_NGREG
-#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
 #endif
-
 #ifndef ELF_GREGSET_T
-#define ELF_GREGSET_T
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 #endif
-
 #ifndef ELF_FPREGSET_T
-#define ELF_FPREGSET_T
-
-/* TBD */
-#define ELF_NFPREG	33	/* includes fsr */
-typedef unsigned long elf_fpreg_t;
-typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
-
-/* typedef struct user_fpu_struct elf_fpregset_t; */
 #endif
-
-/* 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         (0x08000000)
-
 #ifdef __MICROBLAZEEL__
-#define ELF_DATA	ELFDATA2LSB
 #else
-#define ELF_DATA	ELFDATA2MSB
 #endif
-
-#define ELF_EXEC_PAGESIZE	PAGE_SIZE
-
-
-#define ELF_CORE_COPY_REGS(_dest, _regs)			\
-	memcpy((char *) &_dest, (char *) _regs,		\
-	sizeof(struct pt_regs));
-
-/* This yields a mask that user programs can use to figure out what
- * instruction set this CPU supports.  This could be done in user space,
- * but it's not easy, and we've already done it here.
- */
-#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.
-
- * For the moment, we have only optimizations for the Intel generations,
- * but that could change...
- */
-#define ELF_PLATFORM  (NULL)
-
-/* Added _f parameter. Is this definition correct: TBD */
-#define ELF_PLAT_INIT(_r, _f)				\
-do {							\
-	_r->r1 =  _r->r1 =  _r->r2 =  _r->r3 =		\
-	_r->r4 =  _r->r5 =  _r->r6 =  _r->r7 =		\
-	_r->r8 =  _r->r9 =  _r->r10 = _r->r11 =		\
-	_r->r12 = _r->r13 = _r->r14 = _r->r15 =		\
-	_r->r16 = _r->r17 = _r->r18 = _r->r19 =		\
-	_r->r20 = _r->r21 = _r->r22 = _r->r23 =		\
-	_r->r24 = _r->r25 = _r->r26 = _r->r27 =		\
-	_r->r28 = _r->r29 = _r->r30 = _r->r31 =		\
-	0;						\
-} while (0)
-
-#ifdef __KERNEL__
 #define SET_PERSONALITY(ex) \
 	set_personality(PER_LINUX_32BIT | (current->personality & (~PER_MASK)))
-#endif
-
 #endif /* __uClinux__ */
-
 #endif /* _ASM_MICROBLAZE_ELF_H */
diff --git a/arch/microblaze/include/asm/errno.h b/arch/microblaze/include/asm/errno.h
deleted file mode 100644
index 4c82b50..0000000
--- a/arch/microblaze/include/asm/errno.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/errno.h>
diff --git a/arch/microblaze/include/asm/fcntl.h b/arch/microblaze/include/asm/fcntl.h
deleted file mode 100644
index 46ab12d..0000000
--- a/arch/microblaze/include/asm/fcntl.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/fcntl.h>
diff --git a/arch/microblaze/include/asm/ioctl.h b/arch/microblaze/include/asm/ioctl.h
deleted file mode 100644
index b279fe0..0000000
--- a/arch/microblaze/include/asm/ioctl.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff --git a/arch/microblaze/include/asm/ioctls.h b/arch/microblaze/include/asm/ioctls.h
deleted file mode 100644
index ec34c76..0000000
--- a/arch/microblaze/include/asm/ioctls.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctls.h>
diff --git a/arch/microblaze/include/asm/ipcbuf.h b/arch/microblaze/include/asm/ipcbuf.h
deleted file mode 100644
index 84c7e51..0000000
--- a/arch/microblaze/include/asm/ipcbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipcbuf.h>
diff --git a/arch/microblaze/include/asm/kvm_para.h b/arch/microblaze/include/asm/kvm_para.h
deleted file mode 100644
index 14fab8f..0000000
--- a/arch/microblaze/include/asm/kvm_para.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
diff --git a/arch/microblaze/include/asm/mman.h b/arch/microblaze/include/asm/mman.h
deleted file mode 100644
index 8eebf89..0000000
--- a/arch/microblaze/include/asm/mman.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/mman.h>
diff --git a/arch/microblaze/include/asm/msgbuf.h b/arch/microblaze/include/asm/msgbuf.h
deleted file mode 100644
index 809134c..0000000
--- a/arch/microblaze/include/asm/msgbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/msgbuf.h>
diff --git a/arch/microblaze/include/asm/param.h b/arch/microblaze/include/asm/param.h
deleted file mode 100644
index 965d454..0000000
--- a/arch/microblaze/include/asm/param.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/param.h>
diff --git a/arch/microblaze/include/asm/poll.h b/arch/microblaze/include/asm/poll.h
deleted file mode 100644
index c98509d..0000000
--- a/arch/microblaze/include/asm/poll.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/poll.h>
diff --git a/arch/microblaze/include/asm/posix_types.h b/arch/microblaze/include/asm/posix_types.h
deleted file mode 100644
index 0e15039..0000000
--- a/arch/microblaze/include/asm/posix_types.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _ASM_MICROBLAZE_POSIX_TYPES_H
-#define _ASM_MICROBLAZE_POSIX_TYPES_H
-
-typedef unsigned short	__kernel_mode_t;
-#define __kernel_mode_t __kernel_mode_t
-
-#include <asm-generic/posix_types.h>
-
-#endif /* _ASM_MICROBLAZE_POSIX_TYPES_H */
diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h
index af2bb96..0759153 100644
--- a/arch/microblaze/include/asm/processor.h
+++ b/arch/microblaze/include/asm/processor.h
@@ -31,6 +31,7 @@ extern const struct seq_operations cpuinfo_op;
 void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp);
 
 extern void ret_from_fork(void);
+extern void ret_from_kernel_thread(void);
 
 # endif /* __ASSEMBLY__ */
 
@@ -78,11 +79,6 @@ extern unsigned long thread_saved_pc(struct task_struct *t);
 
 extern unsigned long get_wchan(struct task_struct *p);
 
-/*
- * create a kernel thread without removing it from tasklists
- */
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 # define KSTK_EIP(tsk)	(0)
 # define KSTK_ESP(tsk)	(0)
 
@@ -131,8 +127,6 @@ extern inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 /* Free current thread data structures etc.  */
 static inline void exit_thread(void)
 {
diff --git a/arch/microblaze/include/asm/ptrace.h b/arch/microblaze/include/asm/ptrace.h
index 94e92c8..3732bcf 100644
--- a/arch/microblaze/include/asm/ptrace.h
+++ b/arch/microblaze/include/asm/ptrace.h
@@ -5,56 +5,12 @@
  * License. See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #ifndef _ASM_MICROBLAZE_PTRACE_H
 #define _ASM_MICROBLAZE_PTRACE_H
 
-#ifndef __ASSEMBLY__
-
-typedef unsigned long microblaze_reg_t;
+#include <uapi/asm/ptrace.h>
 
-struct pt_regs {
-	microblaze_reg_t r0;
-	microblaze_reg_t r1;
-	microblaze_reg_t r2;
-	microblaze_reg_t r3;
-	microblaze_reg_t r4;
-	microblaze_reg_t r5;
-	microblaze_reg_t r6;
-	microblaze_reg_t r7;
-	microblaze_reg_t r8;
-	microblaze_reg_t r9;
-	microblaze_reg_t r10;
-	microblaze_reg_t r11;
-	microblaze_reg_t r12;
-	microblaze_reg_t r13;
-	microblaze_reg_t r14;
-	microblaze_reg_t r15;
-	microblaze_reg_t r16;
-	microblaze_reg_t r17;
-	microblaze_reg_t r18;
-	microblaze_reg_t r19;
-	microblaze_reg_t r20;
-	microblaze_reg_t r21;
-	microblaze_reg_t r22;
-	microblaze_reg_t r23;
-	microblaze_reg_t r24;
-	microblaze_reg_t r25;
-	microblaze_reg_t r26;
-	microblaze_reg_t r27;
-	microblaze_reg_t r28;
-	microblaze_reg_t r29;
-	microblaze_reg_t r30;
-	microblaze_reg_t r31;
-	microblaze_reg_t pc;
-	microblaze_reg_t msr;
-	microblaze_reg_t ear;
-	microblaze_reg_t esr;
-	microblaze_reg_t fsr;
-	int pt_mode;
-};
-
-#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
 #define kernel_mode(regs)		((regs)->pt_mode)
 #define user_mode(regs)			(!kernel_mode(regs))
 
@@ -66,19 +22,5 @@ static inline long regs_return_value(struct pt_regs *regs)
 	return regs->r3;
 }
 
-#else /* __KERNEL__ */
-
-/* pt_regs offsets used by gdbserver etc in ptrace syscalls */
-#define PT_GPR(n)	((n) * sizeof(microblaze_reg_t))
-#define PT_PC		(32 * sizeof(microblaze_reg_t))
-#define PT_MSR		(33 * sizeof(microblaze_reg_t))
-#define PT_EAR		(34 * sizeof(microblaze_reg_t))
-#define PT_ESR		(35 * sizeof(microblaze_reg_t))
-#define PT_FSR		(36 * sizeof(microblaze_reg_t))
-#define PT_KERNEL_MODE	(37 * sizeof(microblaze_reg_t))
-
-#endif /* __KERNEL */
-
 #endif /* __ASSEMBLY__ */
-
 #endif /* _ASM_MICROBLAZE_PTRACE_H */
diff --git a/arch/microblaze/include/asm/resource.h b/arch/microblaze/include/asm/resource.h
deleted file mode 100644
index 04bc4db..0000000
--- a/arch/microblaze/include/asm/resource.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/resource.h>
diff --git a/arch/microblaze/include/asm/sembuf.h b/arch/microblaze/include/asm/sembuf.h
deleted file mode 100644
index 7673b83..0000000
--- a/arch/microblaze/include/asm/sembuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/sembuf.h>
diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h
index 0061aa1..0e0b0a5 100644
--- a/arch/microblaze/include/asm/setup.h
+++ b/arch/microblaze/include/asm/setup.h
@@ -7,15 +7,12 @@
  * License. See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #ifndef _ASM_MICROBLAZE_SETUP_H
 #define _ASM_MICROBLAZE_SETUP_H
 
-#define COMMAND_LINE_SIZE	256
+#include <uapi/asm/setup.h>
 
 # ifndef __ASSEMBLY__
-
-#  ifdef __KERNEL__
 extern unsigned int boot_cpuid; /* move to smp.h */
 
 extern char cmd_line[COMMAND_LINE_SIZE];
@@ -53,6 +50,5 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end);
 extern void *alloc_maybe_bootmem(size_t size, gfp_t mask);
 extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
 
-#  endif/* __KERNEL__ */
 # endif /* __ASSEMBLY__ */
 #endif /* _ASM_MICROBLAZE_SETUP_H */
diff --git a/arch/microblaze/include/asm/shmbuf.h b/arch/microblaze/include/asm/shmbuf.h
deleted file mode 100644
index 83c05fc..0000000
--- a/arch/microblaze/include/asm/shmbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/shmbuf.h>
diff --git a/arch/microblaze/include/asm/sigcontext.h b/arch/microblaze/include/asm/sigcontext.h
deleted file mode 100644
index 55873c8..0000000
--- a/arch/microblaze/include/asm/sigcontext.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_SIGCONTEXT_H
-#define _ASM_MICROBLAZE_SIGCONTEXT_H
-
-/* FIXME should be linux/ptrace.h */
-#include <asm/ptrace.h>
-
-struct sigcontext {
-	struct pt_regs regs;
-	unsigned long oldmask;
-};
-
-#endif /* _ASM_MICROBLAZE_SIGCONTEXT_H */
diff --git a/arch/microblaze/include/asm/siginfo.h b/arch/microblaze/include/asm/siginfo.h
deleted file mode 100644
index 0815d29..0000000
--- a/arch/microblaze/include/asm/siginfo.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/siginfo.h>
diff --git a/arch/microblaze/include/asm/signal.h b/arch/microblaze/include/asm/signal.h
deleted file mode 100644
index 7b1573c..0000000
--- a/arch/microblaze/include/asm/signal.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/signal.h>
diff --git a/arch/microblaze/include/asm/socket.h b/arch/microblaze/include/asm/socket.h
deleted file mode 100644
index 6b71384..0000000
--- a/arch/microblaze/include/asm/socket.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/socket.h>
diff --git a/arch/microblaze/include/asm/sockios.h b/arch/microblaze/include/asm/sockios.h
deleted file mode 100644
index def6d47..0000000
--- a/arch/microblaze/include/asm/sockios.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/sockios.h>
diff --git a/arch/microblaze/include/asm/stat.h b/arch/microblaze/include/asm/stat.h
deleted file mode 100644
index 3dc90fa..0000000
--- a/arch/microblaze/include/asm/stat.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/stat.h>
diff --git a/arch/microblaze/include/asm/statfs.h b/arch/microblaze/include/asm/statfs.h
deleted file mode 100644
index 0b91fe1..0000000
--- a/arch/microblaze/include/asm/statfs.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/statfs.h>
diff --git a/arch/microblaze/include/asm/swab.h b/arch/microblaze/include/asm/swab.h
deleted file mode 100644
index 7847e56..0000000
--- a/arch/microblaze/include/asm/swab.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/swab.h>
diff --git a/arch/microblaze/include/asm/termbits.h b/arch/microblaze/include/asm/termbits.h
deleted file mode 100644
index 3935b10..0000000
--- a/arch/microblaze/include/asm/termbits.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/termbits.h>
diff --git a/arch/microblaze/include/asm/termios.h b/arch/microblaze/include/asm/termios.h
deleted file mode 100644
index 280d78a..0000000
--- a/arch/microblaze/include/asm/termios.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/termios.h>
diff --git a/arch/microblaze/include/asm/types.h b/arch/microblaze/include/asm/types.h
deleted file mode 100644
index b9e79bc..0000000
--- a/arch/microblaze/include/asm/types.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/types.h>
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h
index ef25f75..927540d 100644
--- a/arch/microblaze/include/asm/uaccess.h
+++ b/arch/microblaze/include/asm/uaccess.h
@@ -298,11 +298,10 @@ extern long __user_bad(void);
 
 #define __put_user_check(x, ptr, size)					\
 ({									\
-	typeof(*(ptr)) __pu_val;					\
+	typeof(*(ptr)) volatile __pu_val = x;					\
 	typeof(*(ptr)) __user *__pu_addr = (ptr);			\
 	int __pu_err = 0;						\
 									\
-	__pu_val = (x);							\
 	if (access_ok(VERIFY_WRITE, __pu_addr, size)) {			\
 		switch (size) {						\
 		case 1:							\
diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h
index 6985e6e..99e2393 100644
--- a/arch/microblaze/include/asm/unistd.h
+++ b/arch/microblaze/include/asm/unistd.h
@@ -6,398 +6,11 @@
  * License. See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #ifndef _ASM_MICROBLAZE_UNISTD_H
 #define _ASM_MICROBLAZE_UNISTD_H
 
-#define __NR_restart_syscall	0 /* ok */
-#define __NR_exit		1 /* ok */
-#define __NR_fork		2 /* not for no MMU - weird */
-#define __NR_read		3 /* ok */
-#define __NR_write		4 /* ok */
-#define __NR_open		5 /* openat */
-#define __NR_close		6 /* ok */
-#define __NR_waitpid		7 /* waitid */
-#define __NR_creat		8 /* openat */
-#define __NR_link		9 /* linkat */
-#define __NR_unlink		10 /* unlinkat */
-#define __NR_execve		11 /* ok */
-#define __NR_chdir		12 /* ok */
-#define __NR_time		13 /* obsolete -> sys_gettimeofday */
-#define __NR_mknod		14 /* mknodat */
-#define __NR_chmod		15 /* fchmodat */
-#define __NR_lchown		16 /* ok */
-#define __NR_break		17 /* don't know */
-#define __NR_oldstat		18 /* remove */
-#define __NR_lseek		19 /* ok */
-#define __NR_getpid		20 /* ok */
-#define __NR_mount		21 /* ok */
-#define __NR_umount		22 /* ok */  /* use only umount2 */
-#define __NR_setuid		23 /* ok */
-#define __NR_getuid		24 /* ok */
-#define __NR_stime		25 /* obsolete -> sys_settimeofday */
-#define __NR_ptrace		26 /* ok */
-#define __NR_alarm		27 /* obsolete -> sys_setitimer */
-#define __NR_oldfstat		28 /* remove */
-#define __NR_pause		29 /* obsolete -> sys_rt_sigtimedwait */
-#define __NR_utime		30 /* obsolete -> sys_utimesat */
-#define __NR_stty		31 /* remove */
-#define __NR_gtty		32 /* remove */
-#define __NR_access		33 /* faccessat */
-/* can be implemented by sys_setpriority */
-#define __NR_nice		34
-#define __NR_ftime		35 /* remove */
-#define __NR_sync		36 /* ok */
-#define __NR_kill		37 /* ok */
-#define __NR_rename		38 /* renameat */
-#define __NR_mkdir		39 /* mkdirat */
-#define __NR_rmdir		40 /* unlinkat */
-#define __NR_dup		41 /* ok */
-#define __NR_pipe		42 /* ok */
-#define __NR_times		43 /* ok */
-#define __NR_prof		44 /* remove */
-#define __NR_brk		45 /* ok -mmu, nommu specific */
-#define __NR_setgid		46 /* ok */
-#define __NR_getgid		47 /* ok */
-#define __NR_signal		48 /* obsolete -> sys_rt_sigaction */
-#define __NR_geteuid		49 /* ok */
-#define __NR_getegid		50 /* ok */
-#define __NR_acct		51 /* add it and then I can disable it */
-#define __NR_umount2		52 /* remove */
-#define __NR_lock		53 /* remove */
-#define __NR_ioctl		54 /* ok */
-#define __NR_fcntl		55 /* ok -> 64bit version*/
-#define __NR_mpx		56 /* remove */
-#define __NR_setpgid		57 /* ok */
-#define __NR_ulimit		58 /* remove */
-#define __NR_oldolduname	59 /* remove */
-#define __NR_umask		60 /* ok */
-#define __NR_chroot		61 /* ok */
-#define __NR_ustat		62 /* obsolete -> statfs64 */
-#define __NR_dup2		63 /* ok */
-#define __NR_getppid		64 /* ok */
-#define __NR_getpgrp		65 /* obsolete -> sys_getpgid */
-#define __NR_setsid		66 /* ok */
-#define __NR_sigaction		67 /* obsolete -> rt_sigaction */
-#define __NR_sgetmask		68 /* obsolete -> sys_rt_sigprocmask */
-#define __NR_ssetmask		69 /* obsolete ->sys_rt_sigprocmask */
-#define __NR_setreuid		70 /* ok */
-#define __NR_setregid		71 /* ok */
-#define __NR_sigsuspend		72 /* obsolete -> rt_sigsuspend */
-#define __NR_sigpending		73 /* obsolete -> sys_rt_sigpending */
-#define __NR_sethostname	74 /* ok */
-#define __NR_setrlimit		75 /* ok */
-#define __NR_getrlimit		76 /* ok Back compatible 2G limited rlimit */
-#define __NR_getrusage		77 /* ok */
-#define __NR_gettimeofday	78 /* ok */
-#define __NR_settimeofday	79 /* ok */
-#define __NR_getgroups		80 /* ok */
-#define __NR_setgroups		81 /* ok */
-#define __NR_select		82 /* obsolete -> sys_pselect7 */
-#define __NR_symlink		83 /* symlinkat */
-#define __NR_oldlstat		84 /* remove */
-#define __NR_readlink		85 /* obsolete -> sys_readlinkat */
-#define __NR_uselib		86 /* remove */
-#define __NR_swapon		87 /* ok */
-#define __NR_reboot		88 /* ok */
-#define __NR_readdir		89 /* remove ? */
-#define __NR_mmap		90 /* obsolete -> sys_mmap2 */
-#define __NR_munmap		91 /* ok - mmu and nommu */
-#define __NR_truncate		92 /* ok or truncate64 */
-#define __NR_ftruncate		93 /* ok or ftruncate64 */
-#define __NR_fchmod		94 /* ok */
-#define __NR_fchown		95 /* ok */
-#define __NR_getpriority	96 /* ok */
-#define __NR_setpriority	97 /* ok */
-#define __NR_profil		98 /* remove */
-#define __NR_statfs		99 /* ok or statfs64 */
-#define __NR_fstatfs		100  /* ok or fstatfs64 */
-#define __NR_ioperm		101 /* remove */
-#define __NR_socketcall		102 /* remove */
-#define __NR_syslog		103 /* ok */
-#define __NR_setitimer		104 /* ok */
-#define __NR_getitimer		105 /* ok */
-#define __NR_stat		106 /* remove */
-#define __NR_lstat		107 /* remove */
-#define __NR_fstat		108 /* remove */
-#define __NR_olduname		109 /* remove */
-#define __NR_iopl		110 /* remove */
-#define __NR_vhangup		111 /* ok */
-#define __NR_idle		112 /* remove */
-#define __NR_vm86old		113 /* remove */
-#define __NR_wait4		114 /* obsolete -> waitid */
-#define __NR_swapoff		115 /* ok */
-#define __NR_sysinfo		116 /* ok */
-#define __NR_ipc		117 /* remove - direct call */
-#define __NR_fsync		118 /* ok */
-#define __NR_sigreturn		119 /* obsolete -> sys_rt_sigreturn */
-#define __NR_clone		120 /* ok */
-#define __NR_setdomainname	121 /* ok */
-#define __NR_uname		122 /* remove */
-#define __NR_modify_ldt		123 /* remove */
-#define __NR_adjtimex		124 /* ok */
-#define __NR_mprotect		125 /* remove */
-#define __NR_sigprocmask	126 /* obsolete -> sys_rt_sigprocmask */
-#define __NR_create_module	127 /* remove */
-#define __NR_init_module	128 /* ok */
-#define __NR_delete_module	129 /* ok */
-#define __NR_get_kernel_syms	130 /* remove */
-#define __NR_quotactl		131 /* ok */
-#define __NR_getpgid		132 /* ok */
-#define __NR_fchdir		133 /* ok */
-#define __NR_bdflush		134 /* remove */
-#define __NR_sysfs		135 /* needed for busybox */
-#define __NR_personality	136 /* ok */
-#define __NR_afs_syscall	137 /* Syscall for Andrew File System */
-#define __NR_setfsuid		138 /* ok */
-#define __NR_setfsgid		139 /* ok */
-#define __NR__llseek		140 /* remove only lseek */
-#define __NR_getdents		141 /* ok or getdents64 */
-#define __NR__newselect		142 /* remove */
-#define __NR_flock		143 /* ok */
-#define __NR_msync		144 /* remove */
-#define __NR_readv		145 /* ok */
-#define __NR_writev		146 /* ok */
-#define __NR_getsid		147 /* ok */
-#define __NR_fdatasync		148 /* ok */
-#define __NR__sysctl		149 /* remove */
-#define __NR_mlock		150 /* ok - nommu or mmu */
-#define __NR_munlock		151 /* ok - nommu or mmu */
-#define __NR_mlockall		152 /* ok - nommu or mmu */
-#define __NR_munlockall		153 /* ok - nommu or mmu */
-#define __NR_sched_setparam		154 /* ok */
-#define __NR_sched_getparam		155 /* ok */
-#define __NR_sched_setscheduler		156 /* ok */
-#define __NR_sched_getscheduler		157 /* ok */
-#define __NR_sched_yield		158 /* ok */
-#define __NR_sched_get_priority_max	159 /* ok */
-#define __NR_sched_get_priority_min	160 /* ok */
-#define __NR_sched_rr_get_interval	161 /* ok */
-#define __NR_nanosleep		162 /* ok */
-#define __NR_mremap		163 /* ok - nommu or mmu */
-#define __NR_setresuid		164 /* ok */
-#define __NR_getresuid		165 /* ok */
-#define __NR_vm86		166 /* remove */
-#define __NR_query_module	167 /* ok */
-#define __NR_poll		168 /* obsolete -> sys_ppoll */
-#define __NR_nfsservctl		169 /* ok */
-#define __NR_setresgid		170 /* ok */
-#define __NR_getresgid		171 /* ok */
-#define __NR_prctl		172 /* ok */
-#define __NR_rt_sigreturn	173 /* ok */
-#define __NR_rt_sigaction	174 /* ok */
-#define __NR_rt_sigprocmask	175 /* ok */
-#define __NR_rt_sigpending	176 /* ok */
-#define __NR_rt_sigtimedwait	177 /* ok */
-#define __NR_rt_sigqueueinfo	178 /* ok */
-#define __NR_rt_sigsuspend	179 /* ok */
-#define __NR_pread64		180 /* ok */
-#define __NR_pwrite64		181 /* ok */
-#define __NR_chown		182 /* obsolete -> fchownat */
-#define __NR_getcwd		183 /* ok */
-#define __NR_capget		184 /* ok */
-#define __NR_capset		185 /* ok */
-#define __NR_sigaltstack	186 /* remove */
-#define __NR_sendfile		187 /* ok -> exist 64bit version*/
-#define __NR_getpmsg		188 /* remove */
-/* remove - some people actually want streams */
-#define __NR_putpmsg		189
-/* for noMMU - group with clone -> maybe remove */
-#define __NR_vfork		190
-#define __NR_ugetrlimit		191 /* remove - SuS compliant getrlimit */
-#define __NR_mmap2		192 /* ok */
-#define __NR_truncate64		193 /* ok */
-#define __NR_ftruncate64	194 /* ok */
-#define __NR_stat64		195 /* remove _ARCH_WANT_STAT64 */
-#define __NR_lstat64		196 /* remove _ARCH_WANT_STAT64 */
-#define __NR_fstat64		197 /* remove _ARCH_WANT_STAT64 */
-#define __NR_lchown32		198 /* ok - without 32 */
-#define __NR_getuid32		199 /* ok - without 32 */
-#define __NR_getgid32		200 /* ok - without 32 */
-#define __NR_geteuid32		201 /* ok - without 32 */
-#define __NR_getegid32		202 /* ok - without 32 */
-#define __NR_setreuid32		203 /* ok - without 32 */
-#define __NR_setregid32		204 /* ok - without 32 */
-#define __NR_getgroups32	205 /* ok - without 32 */
-#define __NR_setgroups32	206 /* ok - without 32 */
-#define __NR_fchown32		207 /* ok - without 32 */
-#define __NR_setresuid32	208 /* ok - without 32 */
-#define __NR_getresuid32	209 /* ok - without 32 */
-#define __NR_setresgid32	210 /* ok - without 32 */
-#define __NR_getresgid32	211 /* ok - without 32 */
-#define __NR_chown32		212 /* ok - without 32 -obsolete -> fchownat */
-#define __NR_setuid32		213 /* ok - without 32 */
-#define __NR_setgid32		214 /* ok - without 32 */
-#define __NR_setfsuid32		215 /* ok - without 32 */
-#define __NR_setfsgid32		216 /* ok - without 32 */
-#define __NR_pivot_root		217 /* ok */
-#define __NR_mincore		218 /* ok */
-#define __NR_madvise		219 /* ok */
-#define __NR_getdents64		220 /* ok */
-#define __NR_fcntl64		221 /* ok */
-/* 223 is unused */
-#define __NR_gettid		224 /* ok */
-#define __NR_readahead		225 /* ok */
-#define __NR_setxattr		226 /* ok */
-#define __NR_lsetxattr		227 /* ok */
-#define __NR_fsetxattr		228 /* ok */
-#define __NR_getxattr		229 /* ok */
-#define __NR_lgetxattr		230 /* ok */
-#define __NR_fgetxattr		231 /* ok */
-#define __NR_listxattr		232 /* ok */
-#define __NR_llistxattr		233 /* ok */
-#define __NR_flistxattr		234 /* ok */
-#define __NR_removexattr	235 /* ok */
-#define __NR_lremovexattr	236 /* ok */
-#define __NR_fremovexattr	237 /* ok */
-#define __NR_tkill		238 /* ok */
-#define __NR_sendfile64		239 /* ok */
-#define __NR_futex		240 /* ok */
-#define __NR_sched_setaffinity	241 /* ok */
-#define __NR_sched_getaffinity	242 /* ok */
-#define __NR_set_thread_area	243 /* remove */
-#define __NR_get_thread_area	244 /* remove */
-#define __NR_io_setup		245 /* ok */
-#define __NR_io_destroy		246 /* ok */
-#define __NR_io_getevents	247 /* ok */
-#define __NR_io_submit		248 /* ok */
-#define __NR_io_cancel		249 /* ok */
-#define __NR_fadvise64		250 /* remove -> sys_fadvise64_64 */
-/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
-#define __NR_exit_group		252 /* ok */
-#define __NR_lookup_dcookie	253 /* ok */
-#define __NR_epoll_create	254 /* ok */
-#define __NR_epoll_ctl		255 /* ok */
-#define __NR_epoll_wait		256 /* obsolete -> sys_epoll_pwait */
-#define __NR_remap_file_pages	257 /* only for mmu */
-#define __NR_set_tid_address	258 /* ok */
-#define __NR_timer_create	259 /* ok */
-#define __NR_timer_settime	(__NR_timer_create+1) /* 260 */ /* ok */
-#define __NR_timer_gettime	(__NR_timer_create+2) /* 261 */ /* ok */
-#define __NR_timer_getoverrun	(__NR_timer_create+3) /* 262 */ /* ok */
-#define __NR_timer_delete	(__NR_timer_create+4) /* 263 */ /* ok */
-#define __NR_clock_settime	(__NR_timer_create+5) /* 264 */ /* ok */
-#define __NR_clock_gettime	(__NR_timer_create+6) /* 265 */ /* ok */
-#define __NR_clock_getres	(__NR_timer_create+7) /* 266 */ /* ok */
-#define __NR_clock_nanosleep	(__NR_timer_create+8) /* 267 */ /* ok */
-#define __NR_statfs64		268 /* ok */
-#define __NR_fstatfs64		269 /* ok */
-#define __NR_tgkill		270 /* ok */
-#define __NR_utimes		271 /* obsolete -> sys_futimesat */
-#define __NR_fadvise64_64	272 /* ok */
-#define __NR_vserver		273 /* ok */
-#define __NR_mbind		274 /* only for mmu */
-#define __NR_get_mempolicy	275 /* only for mmu */
-#define __NR_set_mempolicy	276 /* only for mmu */
-#define __NR_mq_open		277 /* ok */
-#define __NR_mq_unlink		(__NR_mq_open+1) /* 278 */ /* ok */
-#define __NR_mq_timedsend	(__NR_mq_open+2) /* 279 */ /* ok */
-#define __NR_mq_timedreceive	(__NR_mq_open+3) /* 280 */ /* ok */
-#define __NR_mq_notify		(__NR_mq_open+4) /* 281 */ /* ok */
-#define __NR_mq_getsetattr	(__NR_mq_open+5) /* 282 */ /* ok */
-#define __NR_kexec_load		283 /* ok */
-#define __NR_waitid		284 /* ok */
-/* #define __NR_sys_setaltroot	285 */
-#define __NR_add_key		286 /* ok */
-#define __NR_request_key	287 /* ok */
-#define __NR_keyctl		288 /* ok */
-#define __NR_ioprio_set		289 /* ok */
-#define __NR_ioprio_get		290 /* ok */
-#define __NR_inotify_init	291 /* ok */
-#define __NR_inotify_add_watch	292 /* ok */
-#define __NR_inotify_rm_watch	293 /* ok */
-#define __NR_migrate_pages	294 /* mmu */
-#define __NR_openat		295 /* ok */
-#define __NR_mkdirat		296 /* ok */
-#define __NR_mknodat		297 /* ok */
-#define __NR_fchownat		298 /* ok */
-#define __NR_futimesat		299 /* obsolete -> sys_utimesat */
-#define __NR_fstatat64		300 /* stat64 */
-#define __NR_unlinkat		301 /* ok */
-#define __NR_renameat		302 /* ok */
-#define __NR_linkat		303 /* ok */
-#define __NR_symlinkat		304 /* ok */
-#define __NR_readlinkat		305 /* ok */
-#define __NR_fchmodat		306 /* ok */
-#define __NR_faccessat		307 /* ok */
-#define __NR_pselect6		308 /* obsolete -> sys_pselect7 */
-#define __NR_ppoll		309 /* ok */
-#define __NR_unshare		310 /* ok */
-#define __NR_set_robust_list	311 /* ok */
-#define __NR_get_robust_list	312 /* ok */
-#define __NR_splice		313 /* ok */
-#define __NR_sync_file_range	314 /* ok */
-#define __NR_tee		315 /* ok */
-#define __NR_vmsplice		316 /* ok */
-#define __NR_move_pages		317 /* mmu */
-#define __NR_getcpu		318 /* ok */
-#define __NR_epoll_pwait	319 /* ok */
-#define __NR_utimensat		320 /* ok */
-#define __NR_signalfd		321 /* ok */
-#define __NR_timerfd_create	322 /* ok */
-#define __NR_eventfd		323 /* ok */
-#define __NR_fallocate		324 /* ok */
-#define __NR_semtimedop		325 /* ok - semaphore group */
-#define __NR_timerfd_settime	326 /* ok */
-#define __NR_timerfd_gettime	327 /* ok */
-/* sysv ipc syscalls */
-#define __NR_semctl		328 /* ok */
-#define __NR_semget		329 /* ok */
-#define __NR_semop		330 /* ok */
-#define __NR_msgctl		331 /* ok */
-#define __NR_msgget		332 /* ok */
-#define __NR_msgrcv		333 /* ok */
-#define __NR_msgsnd		334 /* ok */
-#define __NR_shmat		335 /* ok */
-#define __NR_shmctl		336 /* ok */
-#define __NR_shmdt		337 /* ok */
-#define __NR_shmget		338 /* ok */
-
-
-#define __NR_signalfd4		339 /* new */
-#define __NR_eventfd2		340 /* new */
-#define __NR_epoll_create1	341 /* new */
-#define __NR_dup3		342 /* new */
-#define __NR_pipe2		343 /* new */
-#define __NR_inotify_init1	344 /* new */
-#define __NR_socket		345 /* new */
-#define __NR_socketpair		346 /* new */
-#define __NR_bind		347 /* new */
-#define __NR_listen		348 /* new */
-#define __NR_accept		349 /* new */
-#define __NR_connect		350 /* new */
-#define __NR_getsockname	351 /* new */
-#define __NR_getpeername	352 /* new */
-#define __NR_sendto		353 /* new */
-#define __NR_send		354 /* new */
-#define __NR_recvfrom		355 /* new */
-#define __NR_recv		356 /* new */
-#define __NR_setsockopt		357 /* new */
-#define __NR_getsockopt		358 /* new */
-#define __NR_shutdown		359 /* new */
-#define __NR_sendmsg		360 /* new */
-#define __NR_recvmsg		361 /* new */
-#define __NR_accept4		362 /* new */
-#define __NR_preadv		363 /* new */
-#define __NR_pwritev		364 /* new */
-#define __NR_rt_tgsigqueueinfo	365 /* new */
-#define __NR_perf_event_open	366 /* new */
-#define __NR_recvmmsg		367 /* new */
-#define __NR_fanotify_init	368
-#define __NR_fanotify_mark	369
-#define __NR_prlimit64		370
-#define __NR_name_to_handle_at	371
-#define __NR_open_by_handle_at	372
-#define __NR_clock_adjtime	373
-#define __NR_syncfs		374
-#define __NR_setns		375
-#define __NR_sendmmsg		376
-#define __NR_process_vm_readv	377
-#define __NR_process_vm_writev	378
-
-#define __NR_syscalls		379
+#include <uapi/asm/unistd.h>
 
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 /* #define __ARCH_WANT_OLD_READDIR */
@@ -422,6 +35,12 @@
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_VFORK
+#ifdef CONFIG_MMU
+#define __ARCH_WANT_SYS_FORK
+#endif
 
 /*
  * "Conditional" syscalls
@@ -432,5 +51,4 @@
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
 
 #endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
 #endif /* _ASM_MICROBLAZE_UNISTD_H */
diff --git a/arch/microblaze/include/uapi/asm/Kbuild b/arch/microblaze/include/uapi/asm/Kbuild
index baebb3d..6d7d7f4 100644
--- a/arch/microblaze/include/uapi/asm/Kbuild
+++ b/arch/microblaze/include/uapi/asm/Kbuild
@@ -1,3 +1,35 @@
 # 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 += elf.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/microblaze/include/uapi/asm/auxvec.h b/arch/microblaze/include/uapi/asm/auxvec.h
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/auxvec.h
@@ -0,0 +1 @@
+
diff --git a/arch/microblaze/include/uapi/asm/bitsperlong.h b/arch/microblaze/include/uapi/asm/bitsperlong.h
new file mode 100644
index 0000000..6dc0bb0
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/bitsperlong.h
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff --git a/arch/microblaze/include/uapi/asm/byteorder.h b/arch/microblaze/include/uapi/asm/byteorder.h
new file mode 100644
index 0000000..3190276
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/byteorder.h
@@ -0,0 +1,10 @@
+#ifndef _ASM_MICROBLAZE_BYTEORDER_H
+#define _ASM_MICROBLAZE_BYTEORDER_H
+
+#ifdef __MICROBLAZEEL__
+#include <linux/byteorder/little_endian.h>
+#else
+#include <linux/byteorder/big_endian.h>
+#endif
+
+#endif /* _ASM_MICROBLAZE_BYTEORDER_H */
diff --git a/arch/microblaze/include/uapi/asm/elf.h b/arch/microblaze/include/uapi/asm/elf.h
new file mode 100644
index 0000000..7eabd83
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/elf.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * 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 _UAPI_ASM_MICROBLAZE_ELF_H
+#define _UAPI_ASM_MICROBLAZE_ELF_H
+
+/*
+ * Note there is no "official" ELF designation for Microblaze.
+ * I've snaffled the value from the microblaze binutils source code
+ * /binutils/microblaze/include/elf/microblaze.h
+ */
+#define EM_MICROBLAZE		189
+#define EM_MICROBLAZE_OLD	0xbaab
+#define ELF_ARCH		EM_MICROBLAZE
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x)	((x)->e_machine == EM_MICROBLAZE \
+				 || (x)->e_machine == EM_MICROBLAZE_OLD)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS32
+
+#ifndef __uClinux__
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+#include <asm/byteorder.h>
+
+#ifndef ELF_GREG_T
+#define ELF_GREG_T
+typedef unsigned long elf_greg_t;
+#endif
+
+#ifndef ELF_NGREG
+#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
+#endif
+
+#ifndef ELF_GREGSET_T
+#define ELF_GREGSET_T
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+#endif
+
+#ifndef ELF_FPREGSET_T
+#define ELF_FPREGSET_T
+
+/* TBD */
+#define ELF_NFPREG	33	/* includes fsr */
+typedef unsigned long elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+/* typedef struct user_fpu_struct elf_fpregset_t; */
+#endif
+
+/* 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         (0x08000000)
+
+#ifdef __MICROBLAZEEL__
+#define ELF_DATA	ELFDATA2LSB
+#else
+#define ELF_DATA	ELFDATA2MSB
+#endif
+
+#define ELF_EXEC_PAGESIZE	PAGE_SIZE
+
+
+#define ELF_CORE_COPY_REGS(_dest, _regs)			\
+	memcpy((char *) &_dest, (char *) _regs,		\
+	sizeof(struct pt_regs));
+
+/* This yields a mask that user programs can use to figure out what
+ * instruction set this CPU supports.  This could be done in user space,
+ * but it's not easy, and we've already done it here.
+ */
+#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.
+
+ * For the moment, we have only optimizations for the Intel generations,
+ * but that could change...
+ */
+#define ELF_PLATFORM  (NULL)
+
+/* Added _f parameter. Is this definition correct: TBD */
+#define ELF_PLAT_INIT(_r, _f)				\
+do {							\
+	_r->r1 =  _r->r1 =  _r->r2 =  _r->r3 =		\
+	_r->r4 =  _r->r5 =  _r->r6 =  _r->r7 =		\
+	_r->r8 =  _r->r9 =  _r->r10 = _r->r11 =		\
+	_r->r12 = _r->r13 = _r->r14 = _r->r15 =		\
+	_r->r16 = _r->r17 = _r->r18 = _r->r19 =		\
+	_r->r20 = _r->r21 = _r->r22 = _r->r23 =		\
+	_r->r24 = _r->r25 = _r->r26 = _r->r27 =		\
+	_r->r28 = _r->r29 = _r->r30 = _r->r31 =		\
+	0;						\
+} while (0)
+
+
+#endif /* __uClinux__ */
+
+#endif /* _UAPI_ASM_MICROBLAZE_ELF_H */
diff --git a/arch/microblaze/include/uapi/asm/errno.h b/arch/microblaze/include/uapi/asm/errno.h
new file mode 100644
index 0000000..4c82b50
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/errno.h
@@ -0,0 +1 @@
+#include <asm-generic/errno.h>
diff --git a/arch/microblaze/include/uapi/asm/fcntl.h b/arch/microblaze/include/uapi/asm/fcntl.h
new file mode 100644
index 0000000..46ab12d
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/fcntl.h
@@ -0,0 +1 @@
+#include <asm-generic/fcntl.h>
diff --git a/arch/microblaze/include/uapi/asm/ioctl.h b/arch/microblaze/include/uapi/asm/ioctl.h
new file mode 100644
index 0000000..b279fe0
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/ioctl.h
@@ -0,0 +1 @@
+#include <asm-generic/ioctl.h>
diff --git a/arch/microblaze/include/uapi/asm/ioctls.h b/arch/microblaze/include/uapi/asm/ioctls.h
new file mode 100644
index 0000000..ec34c76
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/ioctls.h
@@ -0,0 +1 @@
+#include <asm-generic/ioctls.h>
diff --git a/arch/microblaze/include/uapi/asm/ipcbuf.h b/arch/microblaze/include/uapi/asm/ipcbuf.h
new file mode 100644
index 0000000..84c7e51
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/ipcbuf.h
@@ -0,0 +1 @@
+#include <asm-generic/ipcbuf.h>
diff --git a/arch/microblaze/include/uapi/asm/kvm_para.h b/arch/microblaze/include/uapi/asm/kvm_para.h
new file mode 100644
index 0000000..14fab8f
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/kvm_para.h
@@ -0,0 +1 @@
+#include <asm-generic/kvm_para.h>
diff --git a/arch/microblaze/include/uapi/asm/mman.h b/arch/microblaze/include/uapi/asm/mman.h
new file mode 100644
index 0000000..8eebf89
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/mman.h
@@ -0,0 +1 @@
+#include <asm-generic/mman.h>
diff --git a/arch/microblaze/include/uapi/asm/msgbuf.h b/arch/microblaze/include/uapi/asm/msgbuf.h
new file mode 100644
index 0000000..809134c
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/msgbuf.h
@@ -0,0 +1 @@
+#include <asm-generic/msgbuf.h>
diff --git a/arch/microblaze/include/uapi/asm/param.h b/arch/microblaze/include/uapi/asm/param.h
new file mode 100644
index 0000000..965d454
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/param.h
@@ -0,0 +1 @@
+#include <asm-generic/param.h>
diff --git a/arch/microblaze/include/uapi/asm/poll.h b/arch/microblaze/include/uapi/asm/poll.h
new file mode 100644
index 0000000..c98509d
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/poll.h
@@ -0,0 +1 @@
+#include <asm-generic/poll.h>
diff --git a/arch/microblaze/include/uapi/asm/posix_types.h b/arch/microblaze/include/uapi/asm/posix_types.h
new file mode 100644
index 0000000..0e15039
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/posix_types.h
@@ -0,0 +1,9 @@
+#ifndef _ASM_MICROBLAZE_POSIX_TYPES_H
+#define _ASM_MICROBLAZE_POSIX_TYPES_H
+
+typedef unsigned short	__kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
+#include <asm-generic/posix_types.h>
+
+#endif /* _ASM_MICROBLAZE_POSIX_TYPES_H */
diff --git a/arch/microblaze/include/uapi/asm/ptrace.h b/arch/microblaze/include/uapi/asm/ptrace.h
new file mode 100644
index 0000000..d31238a
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/ptrace.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * 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 _UAPI_ASM_MICROBLAZE_PTRACE_H
+#define _UAPI_ASM_MICROBLAZE_PTRACE_H
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long microblaze_reg_t;
+
+struct pt_regs {
+	microblaze_reg_t r0;
+	microblaze_reg_t r1;
+	microblaze_reg_t r2;
+	microblaze_reg_t r3;
+	microblaze_reg_t r4;
+	microblaze_reg_t r5;
+	microblaze_reg_t r6;
+	microblaze_reg_t r7;
+	microblaze_reg_t r8;
+	microblaze_reg_t r9;
+	microblaze_reg_t r10;
+	microblaze_reg_t r11;
+	microblaze_reg_t r12;
+	microblaze_reg_t r13;
+	microblaze_reg_t r14;
+	microblaze_reg_t r15;
+	microblaze_reg_t r16;
+	microblaze_reg_t r17;
+	microblaze_reg_t r18;
+	microblaze_reg_t r19;
+	microblaze_reg_t r20;
+	microblaze_reg_t r21;
+	microblaze_reg_t r22;
+	microblaze_reg_t r23;
+	microblaze_reg_t r24;
+	microblaze_reg_t r25;
+	microblaze_reg_t r26;
+	microblaze_reg_t r27;
+	microblaze_reg_t r28;
+	microblaze_reg_t r29;
+	microblaze_reg_t r30;
+	microblaze_reg_t r31;
+	microblaze_reg_t pc;
+	microblaze_reg_t msr;
+	microblaze_reg_t ear;
+	microblaze_reg_t esr;
+	microblaze_reg_t fsr;
+	int pt_mode;
+};
+
+#ifndef __KERNEL__
+
+/* pt_regs offsets used by gdbserver etc in ptrace syscalls */
+#define PT_GPR(n)	((n) * sizeof(microblaze_reg_t))
+#define PT_PC		(32 * sizeof(microblaze_reg_t))
+#define PT_MSR		(33 * sizeof(microblaze_reg_t))
+#define PT_EAR		(34 * sizeof(microblaze_reg_t))
+#define PT_ESR		(35 * sizeof(microblaze_reg_t))
+#define PT_FSR		(36 * sizeof(microblaze_reg_t))
+#define PT_KERNEL_MODE	(37 * sizeof(microblaze_reg_t))
+
+#endif /* __KERNEL */
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _UAPI_ASM_MICROBLAZE_PTRACE_H */
diff --git a/arch/microblaze/include/uapi/asm/resource.h b/arch/microblaze/include/uapi/asm/resource.h
new file mode 100644
index 0000000..04bc4db
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/resource.h
@@ -0,0 +1 @@
+#include <asm-generic/resource.h>
diff --git a/arch/microblaze/include/uapi/asm/sembuf.h b/arch/microblaze/include/uapi/asm/sembuf.h
new file mode 100644
index 0000000..7673b83
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/sembuf.h
@@ -0,0 +1 @@
+#include <asm-generic/sembuf.h>
diff --git a/arch/microblaze/include/uapi/asm/setup.h b/arch/microblaze/include/uapi/asm/setup.h
new file mode 100644
index 0000000..76bc2ac
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/setup.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2007-2009 PetaLogix
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * 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 _UAPI_ASM_MICROBLAZE_SETUP_H
+#define _UAPI_ASM_MICROBLAZE_SETUP_H
+
+#define COMMAND_LINE_SIZE	256
+
+# ifndef __ASSEMBLY__
+
+# endif /* __ASSEMBLY__ */
+#endif /* _UAPI_ASM_MICROBLAZE_SETUP_H */
diff --git a/arch/microblaze/include/uapi/asm/shmbuf.h b/arch/microblaze/include/uapi/asm/shmbuf.h
new file mode 100644
index 0000000..83c05fc
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/shmbuf.h
@@ -0,0 +1 @@
+#include <asm-generic/shmbuf.h>
diff --git a/arch/microblaze/include/uapi/asm/sigcontext.h b/arch/microblaze/include/uapi/asm/sigcontext.h
new file mode 100644
index 0000000..55873c8
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/sigcontext.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_SIGCONTEXT_H
+#define _ASM_MICROBLAZE_SIGCONTEXT_H
+
+/* FIXME should be linux/ptrace.h */
+#include <asm/ptrace.h>
+
+struct sigcontext {
+	struct pt_regs regs;
+	unsigned long oldmask;
+};
+
+#endif /* _ASM_MICROBLAZE_SIGCONTEXT_H */
diff --git a/arch/microblaze/include/uapi/asm/siginfo.h b/arch/microblaze/include/uapi/asm/siginfo.h
new file mode 100644
index 0000000..0815d29
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/siginfo.h
@@ -0,0 +1 @@
+#include <asm-generic/siginfo.h>
diff --git a/arch/microblaze/include/uapi/asm/signal.h b/arch/microblaze/include/uapi/asm/signal.h
new file mode 100644
index 0000000..7b1573c
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/signal.h
@@ -0,0 +1 @@
+#include <asm-generic/signal.h>
diff --git a/arch/microblaze/include/uapi/asm/socket.h b/arch/microblaze/include/uapi/asm/socket.h
new file mode 100644
index 0000000..6b71384
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/socket.h
@@ -0,0 +1 @@
+#include <asm-generic/socket.h>
diff --git a/arch/microblaze/include/uapi/asm/sockios.h b/arch/microblaze/include/uapi/asm/sockios.h
new file mode 100644
index 0000000..def6d47
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/sockios.h
@@ -0,0 +1 @@
+#include <asm-generic/sockios.h>
diff --git a/arch/microblaze/include/uapi/asm/stat.h b/arch/microblaze/include/uapi/asm/stat.h
new file mode 100644
index 0000000..3dc90fa
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/stat.h
@@ -0,0 +1 @@
+#include <asm-generic/stat.h>
diff --git a/arch/microblaze/include/uapi/asm/statfs.h b/arch/microblaze/include/uapi/asm/statfs.h
new file mode 100644
index 0000000..0b91fe1
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/statfs.h
@@ -0,0 +1 @@
+#include <asm-generic/statfs.h>
diff --git a/arch/microblaze/include/uapi/asm/swab.h b/arch/microblaze/include/uapi/asm/swab.h
new file mode 100644
index 0000000..7847e56
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/swab.h
@@ -0,0 +1 @@
+#include <asm-generic/swab.h>
diff --git a/arch/microblaze/include/uapi/asm/termbits.h b/arch/microblaze/include/uapi/asm/termbits.h
new file mode 100644
index 0000000..3935b10
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/termbits.h
@@ -0,0 +1 @@
+#include <asm-generic/termbits.h>
diff --git a/arch/microblaze/include/uapi/asm/termios.h b/arch/microblaze/include/uapi/asm/termios.h
new file mode 100644
index 0000000..280d78a
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/termios.h
@@ -0,0 +1 @@
+#include <asm-generic/termios.h>
diff --git a/arch/microblaze/include/uapi/asm/types.h b/arch/microblaze/include/uapi/asm/types.h
new file mode 100644
index 0000000..b9e79bc
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/types.h
@@ -0,0 +1 @@
+#include <asm-generic/types.h>
diff --git a/arch/microblaze/include/uapi/asm/unistd.h b/arch/microblaze/include/uapi/asm/unistd.h
new file mode 100644
index 0000000..bbeaa2d
--- /dev/null
+++ b/arch/microblaze/include/uapi/asm/unistd.h
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2007-2008 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * 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 _UAPI_ASM_MICROBLAZE_UNISTD_H
+#define _UAPI_ASM_MICROBLAZE_UNISTD_H
+
+#define __NR_restart_syscall	0 /* ok */
+#define __NR_exit		1 /* ok */
+#define __NR_fork		2 /* not for no MMU - weird */
+#define __NR_read		3 /* ok */
+#define __NR_write		4 /* ok */
+#define __NR_open		5 /* openat */
+#define __NR_close		6 /* ok */
+#define __NR_waitpid		7 /* waitid */
+#define __NR_creat		8 /* openat */
+#define __NR_link		9 /* linkat */
+#define __NR_unlink		10 /* unlinkat */
+#define __NR_execve		11 /* ok */
+#define __NR_chdir		12 /* ok */
+#define __NR_time		13 /* obsolete -> sys_gettimeofday */
+#define __NR_mknod		14 /* mknodat */
+#define __NR_chmod		15 /* fchmodat */
+#define __NR_lchown		16 /* ok */
+#define __NR_break		17 /* don't know */
+#define __NR_oldstat		18 /* remove */
+#define __NR_lseek		19 /* ok */
+#define __NR_getpid		20 /* ok */
+#define __NR_mount		21 /* ok */
+#define __NR_umount		22 /* ok */  /* use only umount2 */
+#define __NR_setuid		23 /* ok */
+#define __NR_getuid		24 /* ok */
+#define __NR_stime		25 /* obsolete -> sys_settimeofday */
+#define __NR_ptrace		26 /* ok */
+#define __NR_alarm		27 /* obsolete -> sys_setitimer */
+#define __NR_oldfstat		28 /* remove */
+#define __NR_pause		29 /* obsolete -> sys_rt_sigtimedwait */
+#define __NR_utime		30 /* obsolete -> sys_utimesat */
+#define __NR_stty		31 /* remove */
+#define __NR_gtty		32 /* remove */
+#define __NR_access		33 /* faccessat */
+/* can be implemented by sys_setpriority */
+#define __NR_nice		34
+#define __NR_ftime		35 /* remove */
+#define __NR_sync		36 /* ok */
+#define __NR_kill		37 /* ok */
+#define __NR_rename		38 /* renameat */
+#define __NR_mkdir		39 /* mkdirat */
+#define __NR_rmdir		40 /* unlinkat */
+#define __NR_dup		41 /* ok */
+#define __NR_pipe		42 /* ok */
+#define __NR_times		43 /* ok */
+#define __NR_prof		44 /* remove */
+#define __NR_brk		45 /* ok -mmu, nommu specific */
+#define __NR_setgid		46 /* ok */
+#define __NR_getgid		47 /* ok */
+#define __NR_signal		48 /* obsolete -> sys_rt_sigaction */
+#define __NR_geteuid		49 /* ok */
+#define __NR_getegid		50 /* ok */
+#define __NR_acct		51 /* add it and then I can disable it */
+#define __NR_umount2		52 /* remove */
+#define __NR_lock		53 /* remove */
+#define __NR_ioctl		54 /* ok */
+#define __NR_fcntl		55 /* ok -> 64bit version*/
+#define __NR_mpx		56 /* remove */
+#define __NR_setpgid		57 /* ok */
+#define __NR_ulimit		58 /* remove */
+#define __NR_oldolduname	59 /* remove */
+#define __NR_umask		60 /* ok */
+#define __NR_chroot		61 /* ok */
+#define __NR_ustat		62 /* obsolete -> statfs64 */
+#define __NR_dup2		63 /* ok */
+#define __NR_getppid		64 /* ok */
+#define __NR_getpgrp		65 /* obsolete -> sys_getpgid */
+#define __NR_setsid		66 /* ok */
+#define __NR_sigaction		67 /* obsolete -> rt_sigaction */
+#define __NR_sgetmask		68 /* obsolete -> sys_rt_sigprocmask */
+#define __NR_ssetmask		69 /* obsolete ->sys_rt_sigprocmask */
+#define __NR_setreuid		70 /* ok */
+#define __NR_setregid		71 /* ok */
+#define __NR_sigsuspend		72 /* obsolete -> rt_sigsuspend */
+#define __NR_sigpending		73 /* obsolete -> sys_rt_sigpending */
+#define __NR_sethostname	74 /* ok */
+#define __NR_setrlimit		75 /* ok */
+#define __NR_getrlimit		76 /* ok Back compatible 2G limited rlimit */
+#define __NR_getrusage		77 /* ok */
+#define __NR_gettimeofday	78 /* ok */
+#define __NR_settimeofday	79 /* ok */
+#define __NR_getgroups		80 /* ok */
+#define __NR_setgroups		81 /* ok */
+#define __NR_select		82 /* obsolete -> sys_pselect7 */
+#define __NR_symlink		83 /* symlinkat */
+#define __NR_oldlstat		84 /* remove */
+#define __NR_readlink		85 /* obsolete -> sys_readlinkat */
+#define __NR_uselib		86 /* remove */
+#define __NR_swapon		87 /* ok */
+#define __NR_reboot		88 /* ok */
+#define __NR_readdir		89 /* remove ? */
+#define __NR_mmap		90 /* obsolete -> sys_mmap2 */
+#define __NR_munmap		91 /* ok - mmu and nommu */
+#define __NR_truncate		92 /* ok or truncate64 */
+#define __NR_ftruncate		93 /* ok or ftruncate64 */
+#define __NR_fchmod		94 /* ok */
+#define __NR_fchown		95 /* ok */
+#define __NR_getpriority	96 /* ok */
+#define __NR_setpriority	97 /* ok */
+#define __NR_profil		98 /* remove */
+#define __NR_statfs		99 /* ok or statfs64 */
+#define __NR_fstatfs		100  /* ok or fstatfs64 */
+#define __NR_ioperm		101 /* remove */
+#define __NR_socketcall		102 /* remove */
+#define __NR_syslog		103 /* ok */
+#define __NR_setitimer		104 /* ok */
+#define __NR_getitimer		105 /* ok */
+#define __NR_stat		106 /* remove */
+#define __NR_lstat		107 /* remove */
+#define __NR_fstat		108 /* remove */
+#define __NR_olduname		109 /* remove */
+#define __NR_iopl		110 /* remove */
+#define __NR_vhangup		111 /* ok */
+#define __NR_idle		112 /* remove */
+#define __NR_vm86old		113 /* remove */
+#define __NR_wait4		114 /* obsolete -> waitid */
+#define __NR_swapoff		115 /* ok */
+#define __NR_sysinfo		116 /* ok */
+#define __NR_ipc		117 /* remove - direct call */
+#define __NR_fsync		118 /* ok */
+#define __NR_sigreturn		119 /* obsolete -> sys_rt_sigreturn */
+#define __NR_clone		120 /* ok */
+#define __NR_setdomainname	121 /* ok */
+#define __NR_uname		122 /* remove */
+#define __NR_modify_ldt		123 /* remove */
+#define __NR_adjtimex		124 /* ok */
+#define __NR_mprotect		125 /* remove */
+#define __NR_sigprocmask	126 /* obsolete -> sys_rt_sigprocmask */
+#define __NR_create_module	127 /* remove */
+#define __NR_init_module	128 /* ok */
+#define __NR_delete_module	129 /* ok */
+#define __NR_get_kernel_syms	130 /* remove */
+#define __NR_quotactl		131 /* ok */
+#define __NR_getpgid		132 /* ok */
+#define __NR_fchdir		133 /* ok */
+#define __NR_bdflush		134 /* remove */
+#define __NR_sysfs		135 /* needed for busybox */
+#define __NR_personality	136 /* ok */
+#define __NR_afs_syscall	137 /* Syscall for Andrew File System */
+#define __NR_setfsuid		138 /* ok */
+#define __NR_setfsgid		139 /* ok */
+#define __NR__llseek		140 /* remove only lseek */
+#define __NR_getdents		141 /* ok or getdents64 */
+#define __NR__newselect		142 /* remove */
+#define __NR_flock		143 /* ok */
+#define __NR_msync		144 /* remove */
+#define __NR_readv		145 /* ok */
+#define __NR_writev		146 /* ok */
+#define __NR_getsid		147 /* ok */
+#define __NR_fdatasync		148 /* ok */
+#define __NR__sysctl		149 /* remove */
+#define __NR_mlock		150 /* ok - nommu or mmu */
+#define __NR_munlock		151 /* ok - nommu or mmu */
+#define __NR_mlockall		152 /* ok - nommu or mmu */
+#define __NR_munlockall		153 /* ok - nommu or mmu */
+#define __NR_sched_setparam		154 /* ok */
+#define __NR_sched_getparam		155 /* ok */
+#define __NR_sched_setscheduler		156 /* ok */
+#define __NR_sched_getscheduler		157 /* ok */
+#define __NR_sched_yield		158 /* ok */
+#define __NR_sched_get_priority_max	159 /* ok */
+#define __NR_sched_get_priority_min	160 /* ok */
+#define __NR_sched_rr_get_interval	161 /* ok */
+#define __NR_nanosleep		162 /* ok */
+#define __NR_mremap		163 /* ok - nommu or mmu */
+#define __NR_setresuid		164 /* ok */
+#define __NR_getresuid		165 /* ok */
+#define __NR_vm86		166 /* remove */
+#define __NR_query_module	167 /* ok */
+#define __NR_poll		168 /* obsolete -> sys_ppoll */
+#define __NR_nfsservctl		169 /* ok */
+#define __NR_setresgid		170 /* ok */
+#define __NR_getresgid		171 /* ok */
+#define __NR_prctl		172 /* ok */
+#define __NR_rt_sigreturn	173 /* ok */
+#define __NR_rt_sigaction	174 /* ok */
+#define __NR_rt_sigprocmask	175 /* ok */
+#define __NR_rt_sigpending	176 /* ok */
+#define __NR_rt_sigtimedwait	177 /* ok */
+#define __NR_rt_sigqueueinfo	178 /* ok */
+#define __NR_rt_sigsuspend	179 /* ok */
+#define __NR_pread64		180 /* ok */
+#define __NR_pwrite64		181 /* ok */
+#define __NR_chown		182 /* obsolete -> fchownat */
+#define __NR_getcwd		183 /* ok */
+#define __NR_capget		184 /* ok */
+#define __NR_capset		185 /* ok */
+#define __NR_sigaltstack	186 /* remove */
+#define __NR_sendfile		187 /* ok -> exist 64bit version*/
+#define __NR_getpmsg		188 /* remove */
+/* remove - some people actually want streams */
+#define __NR_putpmsg		189
+/* for noMMU - group with clone -> maybe remove */
+#define __NR_vfork		190
+#define __NR_ugetrlimit		191 /* remove - SuS compliant getrlimit */
+#define __NR_mmap2		192 /* ok */
+#define __NR_truncate64		193 /* ok */
+#define __NR_ftruncate64	194 /* ok */
+#define __NR_stat64		195 /* remove _ARCH_WANT_STAT64 */
+#define __NR_lstat64		196 /* remove _ARCH_WANT_STAT64 */
+#define __NR_fstat64		197 /* remove _ARCH_WANT_STAT64 */
+#define __NR_lchown32		198 /* ok - without 32 */
+#define __NR_getuid32		199 /* ok - without 32 */
+#define __NR_getgid32		200 /* ok - without 32 */
+#define __NR_geteuid32		201 /* ok - without 32 */
+#define __NR_getegid32		202 /* ok - without 32 */
+#define __NR_setreuid32		203 /* ok - without 32 */
+#define __NR_setregid32		204 /* ok - without 32 */
+#define __NR_getgroups32	205 /* ok - without 32 */
+#define __NR_setgroups32	206 /* ok - without 32 */
+#define __NR_fchown32		207 /* ok - without 32 */
+#define __NR_setresuid32	208 /* ok - without 32 */
+#define __NR_getresuid32	209 /* ok - without 32 */
+#define __NR_setresgid32	210 /* ok - without 32 */
+#define __NR_getresgid32	211 /* ok - without 32 */
+#define __NR_chown32		212 /* ok - without 32 -obsolete -> fchownat */
+#define __NR_setuid32		213 /* ok - without 32 */
+#define __NR_setgid32		214 /* ok - without 32 */
+#define __NR_setfsuid32		215 /* ok - without 32 */
+#define __NR_setfsgid32		216 /* ok - without 32 */
+#define __NR_pivot_root		217 /* ok */
+#define __NR_mincore		218 /* ok */
+#define __NR_madvise		219 /* ok */
+#define __NR_getdents64		220 /* ok */
+#define __NR_fcntl64		221 /* ok */
+/* 223 is unused */
+#define __NR_gettid		224 /* ok */
+#define __NR_readahead		225 /* ok */
+#define __NR_setxattr		226 /* ok */
+#define __NR_lsetxattr		227 /* ok */
+#define __NR_fsetxattr		228 /* ok */
+#define __NR_getxattr		229 /* ok */
+#define __NR_lgetxattr		230 /* ok */
+#define __NR_fgetxattr		231 /* ok */
+#define __NR_listxattr		232 /* ok */
+#define __NR_llistxattr		233 /* ok */
+#define __NR_flistxattr		234 /* ok */
+#define __NR_removexattr	235 /* ok */
+#define __NR_lremovexattr	236 /* ok */
+#define __NR_fremovexattr	237 /* ok */
+#define __NR_tkill		238 /* ok */
+#define __NR_sendfile64		239 /* ok */
+#define __NR_futex		240 /* ok */
+#define __NR_sched_setaffinity	241 /* ok */
+#define __NR_sched_getaffinity	242 /* ok */
+#define __NR_set_thread_area	243 /* remove */
+#define __NR_get_thread_area	244 /* remove */
+#define __NR_io_setup		245 /* ok */
+#define __NR_io_destroy		246 /* ok */
+#define __NR_io_getevents	247 /* ok */
+#define __NR_io_submit		248 /* ok */
+#define __NR_io_cancel		249 /* ok */
+#define __NR_fadvise64		250 /* remove -> sys_fadvise64_64 */
+/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
+#define __NR_exit_group		252 /* ok */
+#define __NR_lookup_dcookie	253 /* ok */
+#define __NR_epoll_create	254 /* ok */
+#define __NR_epoll_ctl		255 /* ok */
+#define __NR_epoll_wait		256 /* obsolete -> sys_epoll_pwait */
+#define __NR_remap_file_pages	257 /* only for mmu */
+#define __NR_set_tid_address	258 /* ok */
+#define __NR_timer_create	259 /* ok */
+#define __NR_timer_settime	(__NR_timer_create+1) /* 260 */ /* ok */
+#define __NR_timer_gettime	(__NR_timer_create+2) /* 261 */ /* ok */
+#define __NR_timer_getoverrun	(__NR_timer_create+3) /* 262 */ /* ok */
+#define __NR_timer_delete	(__NR_timer_create+4) /* 263 */ /* ok */
+#define __NR_clock_settime	(__NR_timer_create+5) /* 264 */ /* ok */
+#define __NR_clock_gettime	(__NR_timer_create+6) /* 265 */ /* ok */
+#define __NR_clock_getres	(__NR_timer_create+7) /* 266 */ /* ok */
+#define __NR_clock_nanosleep	(__NR_timer_create+8) /* 267 */ /* ok */
+#define __NR_statfs64		268 /* ok */
+#define __NR_fstatfs64		269 /* ok */
+#define __NR_tgkill		270 /* ok */
+#define __NR_utimes		271 /* obsolete -> sys_futimesat */
+#define __NR_fadvise64_64	272 /* ok */
+#define __NR_vserver		273 /* ok */
+#define __NR_mbind		274 /* only for mmu */
+#define __NR_get_mempolicy	275 /* only for mmu */
+#define __NR_set_mempolicy	276 /* only for mmu */
+#define __NR_mq_open		277 /* ok */
+#define __NR_mq_unlink		(__NR_mq_open+1) /* 278 */ /* ok */
+#define __NR_mq_timedsend	(__NR_mq_open+2) /* 279 */ /* ok */
+#define __NR_mq_timedreceive	(__NR_mq_open+3) /* 280 */ /* ok */
+#define __NR_mq_notify		(__NR_mq_open+4) /* 281 */ /* ok */
+#define __NR_mq_getsetattr	(__NR_mq_open+5) /* 282 */ /* ok */
+#define __NR_kexec_load		283 /* ok */
+#define __NR_waitid		284 /* ok */
+/* #define __NR_sys_setaltroot	285 */
+#define __NR_add_key		286 /* ok */
+#define __NR_request_key	287 /* ok */
+#define __NR_keyctl		288 /* ok */
+#define __NR_ioprio_set		289 /* ok */
+#define __NR_ioprio_get		290 /* ok */
+#define __NR_inotify_init	291 /* ok */
+#define __NR_inotify_add_watch	292 /* ok */
+#define __NR_inotify_rm_watch	293 /* ok */
+#define __NR_migrate_pages	294 /* mmu */
+#define __NR_openat		295 /* ok */
+#define __NR_mkdirat		296 /* ok */
+#define __NR_mknodat		297 /* ok */
+#define __NR_fchownat		298 /* ok */
+#define __NR_futimesat		299 /* obsolete -> sys_utimesat */
+#define __NR_fstatat64		300 /* stat64 */
+#define __NR_unlinkat		301 /* ok */
+#define __NR_renameat		302 /* ok */
+#define __NR_linkat		303 /* ok */
+#define __NR_symlinkat		304 /* ok */
+#define __NR_readlinkat		305 /* ok */
+#define __NR_fchmodat		306 /* ok */
+#define __NR_faccessat		307 /* ok */
+#define __NR_pselect6		308 /* obsolete -> sys_pselect7 */
+#define __NR_ppoll		309 /* ok */
+#define __NR_unshare		310 /* ok */
+#define __NR_set_robust_list	311 /* ok */
+#define __NR_get_robust_list	312 /* ok */
+#define __NR_splice		313 /* ok */
+#define __NR_sync_file_range	314 /* ok */
+#define __NR_tee		315 /* ok */
+#define __NR_vmsplice		316 /* ok */
+#define __NR_move_pages		317 /* mmu */
+#define __NR_getcpu		318 /* ok */
+#define __NR_epoll_pwait	319 /* ok */
+#define __NR_utimensat		320 /* ok */
+#define __NR_signalfd		321 /* ok */
+#define __NR_timerfd_create	322 /* ok */
+#define __NR_eventfd		323 /* ok */
+#define __NR_fallocate		324 /* ok */
+#define __NR_semtimedop		325 /* ok - semaphore group */
+#define __NR_timerfd_settime	326 /* ok */
+#define __NR_timerfd_gettime	327 /* ok */
+/* sysv ipc syscalls */
+#define __NR_semctl		328 /* ok */
+#define __NR_semget		329 /* ok */
+#define __NR_semop		330 /* ok */
+#define __NR_msgctl		331 /* ok */
+#define __NR_msgget		332 /* ok */
+#define __NR_msgrcv		333 /* ok */
+#define __NR_msgsnd		334 /* ok */
+#define __NR_shmat		335 /* ok */
+#define __NR_shmctl		336 /* ok */
+#define __NR_shmdt		337 /* ok */
+#define __NR_shmget		338 /* ok */
+
+
+#define __NR_signalfd4		339 /* new */
+#define __NR_eventfd2		340 /* new */
+#define __NR_epoll_create1	341 /* new */
+#define __NR_dup3		342 /* new */
+#define __NR_pipe2		343 /* new */
+#define __NR_inotify_init1	344 /* new */
+#define __NR_socket		345 /* new */
+#define __NR_socketpair		346 /* new */
+#define __NR_bind		347 /* new */
+#define __NR_listen		348 /* new */
+#define __NR_accept		349 /* new */
+#define __NR_connect		350 /* new */
+#define __NR_getsockname	351 /* new */
+#define __NR_getpeername	352 /* new */
+#define __NR_sendto		353 /* new */
+#define __NR_send		354 /* new */
+#define __NR_recvfrom		355 /* new */
+#define __NR_recv		356 /* new */
+#define __NR_setsockopt		357 /* new */
+#define __NR_getsockopt		358 /* new */
+#define __NR_shutdown		359 /* new */
+#define __NR_sendmsg		360 /* new */
+#define __NR_recvmsg		361 /* new */
+#define __NR_accept4		362 /* new */
+#define __NR_preadv		363 /* new */
+#define __NR_pwritev		364 /* new */
+#define __NR_rt_tgsigqueueinfo	365 /* new */
+#define __NR_perf_event_open	366 /* new */
+#define __NR_recvmmsg		367 /* new */
+#define __NR_fanotify_init	368
+#define __NR_fanotify_mark	369
+#define __NR_prlimit64		370
+#define __NR_name_to_handle_at	371
+#define __NR_open_by_handle_at	372
+#define __NR_clock_adjtime	373
+#define __NR_syncfs		374
+#define __NR_setns		375
+#define __NR_sendmmsg		376
+#define __NR_process_vm_readv	377
+#define __NR_process_vm_writev	378
+
+#define __NR_syscalls		379
+
+#endif /* _UAPI_ASM_MICROBLAZE_UNISTD_H */
diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S
index 75c3ea1..70da83a 100644
--- a/arch/microblaze/kernel/entry-nommu.S
+++ b/arch/microblaze/kernel/entry-nommu.S
@@ -465,7 +465,6 @@ ENTRY(_switch_to)
 
 ENTRY(ret_from_fork)
 	addk	r5, r0, r3
-	addk	r6, r0, r1
 	brlid	r15, schedule_tail
 	nop
 	swi	r31, r1, PT_R31		/* save r31 in user context. */
@@ -474,6 +473,14 @@ ENTRY(ret_from_fork)
 	brid	ret_to_user
 	nop
 
+ENTRY(ret_from_kernel_thread)
+	brlid	r15, schedule_tail
+	addk	r5, r0, r3
+	brald	r15, r20
+	addk	r5, r0, r19
+	brid	ret_to_user
+	addk	r3, r0, r0
+
 work_pending:
 	enable_irq
 
@@ -551,18 +558,6 @@ no_work_pending:
 	rtid	r14, 0
 	nop
 
-sys_vfork:
-	brid	microblaze_vfork
-	addk	r5, r1, r0
-
-sys_clone:
-	brid	microblaze_clone
-	addk	r7, r1, r0
-
-sys_execve:
-	brid	microblaze_execve
-	addk	r8, r1, r0
-
 sys_rt_sigreturn_wrapper:
 	brid	sys_rt_sigreturn
 	addk	r5, r1, r0
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S
index 03f7b8c..c217367 100644
--- a/arch/microblaze/kernel/entry.S
+++ b/arch/microblaze/kernel/entry.S
@@ -293,24 +293,6 @@ C_ENTRY(_user_exception):
 	swi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
 	addi	r14, r14, 4	/* return address is 4 byte after call */
 
-	mfs	r1, rmsr
-	nop
-	andi	r1, r1, MSR_UMS
-	bnei	r1, 1f
-
-/* Kernel-mode state save - kernel execve */
-	lwi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
-	tophys(r1,r1);
-
-	addik	r1, r1, -PT_SIZE; /* Make room on the stack. */
-	SAVE_REGS
-
-	swi	r1, r1, PT_MODE; /* pt_regs -> kernel mode */
-	brid	2f;
-	nop;				/* Fill delay slot */
-
-/* User-mode state save.  */
-1:
 	lwi	r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
 	tophys(r1,r1);
 	lwi	r1, r1, TS_THREAD_INFO;	/* get stack from task_struct */
@@ -460,18 +442,6 @@ TRAP_return:		/* Make global symbol for debugging */
 	nop;
 
 
-/* These syscalls need access to the struct pt_regs on the stack, so we
-   implement them in assembly (they're basically all wrappers anyway).  */
-
-C_ENTRY(sys_fork_wrapper):
-	addi	r5, r0, SIGCHLD			/* Arg 0: flags */
-	lwi	r6, r1, PT_R1	/* Arg 1: child SP (use parent's) */
-	addik	r7, r1, 0			/* Arg 2: parent context */
-	add	r8, r0, r0			/* Arg 3: (unused) */
-	add	r9, r0, r0;			/* Arg 4: (unused) */
-	brid	do_fork		/* Do real work (tail-call) */
-	add	r10, r0, r0;			/* Arg 5: (unused) */
-
 /* This the initial entry point for a new child thread, with an appropriate
    stack in place that makes it look the the child is in the middle of an
    syscall.  This function is actually `returned to' from switch_thread
@@ -479,28 +449,19 @@ C_ENTRY(sys_fork_wrapper):
    saved context).  */
 C_ENTRY(ret_from_fork):
 	bralid	r15, schedule_tail; /* ...which is schedule_tail's arg */
-	add	r3, r5, r0;	/* switch_thread returns the prev task */
+	add	r5, r3, r0;	/* switch_thread returns the prev task */
 				/* ( in the delay slot ) */
 	brid	ret_from_trap;	/* Do normal trap return */
 	add	r3, r0, r0;	/* Child's fork call should return 0. */
 
-C_ENTRY(sys_vfork):
-	brid	microblaze_vfork	/* Do real work (tail-call) */
-	addik	r5, r1, 0
-
-C_ENTRY(sys_clone):
-	bnei	r6, 1f;			/* See if child SP arg (arg 1) is 0. */
-	lwi	r6, r1, PT_R1;	/* If so, use paret's stack ptr */
-1:	addik	r7, r1, 0;			/* Arg 2: parent context */
-	lwi     r9, r1, PT_R8;          /* parent tid.  */
-	lwi     r10, r1, PT_R9;         /* child tid.  */
-	/* do_fork will pick up TLS from regs->r10.  */
-	brid	do_fork		/* Do real work (tail-call) */
-	add     r8, r0, r0;             /* Arg 3: (unused) */
-
-C_ENTRY(sys_execve):
-	brid	microblaze_execve;	/* Do real work (tail-call).*/
-	addik	r8, r1, 0;		/* add user context as 4th arg */
+C_ENTRY(ret_from_kernel_thread):
+	bralid	r15, schedule_tail; /* ...which is schedule_tail's arg */
+	add	r5, r3, r0;	/* switch_thread returns the prev task */
+				/* ( in the delay slot ) */
+	brald	r15, r20	/* fn was left in r20 */
+	addk	r5, r0, r19	/* ... and argument - in r19 */
+	brid	ret_from_trap
+	add	r3, r0, r0
 
 C_ENTRY(sys_rt_sigreturn_wrapper):
 	brid	sys_rt_sigreturn	/* Do real work */
diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c
index 1944e00..a5b74f7 100644
--- a/arch/microblaze/kernel/process.c
+++ b/arch/microblaze/kernel/process.c
@@ -13,6 +13,7 @@
 #include <linux/pm.h>
 #include <linux/tick.h>
 #include <linux/bitops.h>
+#include <linux/ptrace.h>
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h> /* for USER_DS macros */
 #include <asm/cacheflush.h>
@@ -119,46 +120,38 @@ void flush_thread(void)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-		unsigned long unused,
-		struct task_struct *p, struct pt_regs *regs)
+		unsigned long arg, struct task_struct *p)
 {
 	struct pt_regs *childregs = task_pt_regs(p);
 	struct thread_info *ti = task_thread_info(p);
 
-	*childregs = *regs;
-	if (user_mode(regs))
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		/* if we're creating a new kernel thread then just zeroing all
+		 * the registers. That's OK for a brand new thread.*/
+		memset(childregs, 0, sizeof(struct pt_regs));
+		memset(&ti->cpu_context, 0, sizeof(struct cpu_context));
+		ti->cpu_context.r1  = (unsigned long)childregs;
+		ti->cpu_context.r20 = (unsigned long)usp; /* fn */
+		ti->cpu_context.r19 = (unsigned long)arg;
+		childregs->pt_mode = 1;
+		local_save_flags(childregs->msr);
+#ifdef CONFIG_MMU
+		ti->cpu_context.msr = childregs->msr & ~MSR_IE;
+#endif
+		ti->cpu_context.r15 = (unsigned long)ret_from_kernel_thread - 8;
+		return 0;
+	}
+	*childregs = *current_pt_regs();
+	if (usp)
 		childregs->r1 = usp;
-	else
-		childregs->r1 = ((unsigned long) ti) + THREAD_SIZE;
 
-#ifndef CONFIG_MMU
 	memset(&ti->cpu_context, 0, sizeof(struct cpu_context));
 	ti->cpu_context.r1 = (unsigned long)childregs;
+#ifndef CONFIG_MMU
 	ti->cpu_context.msr = (unsigned long)childregs->msr;
 #else
+	childregs->msr |= MSR_UMS;
 
-	/* if creating a kernel thread then update the current reg (we don't
-	 * want to use the parent's value when restoring by POP_STATE) */
-	if (kernel_mode(regs))
-		/* save new current on stack to use POP_STATE */
-		childregs->CURRENT_TASK = (unsigned long)p;
-	/* if returning to user then use the parent's value of this register */
-
-	/* if we're creating a new kernel thread then just zeroing all
-	 * the registers. That's OK for a brand new thread.*/
-	/* Pls. note that some of them will be restored in POP_STATE */
-	if (kernel_mode(regs))
-		memset(&ti->cpu_context, 0, sizeof(struct cpu_context));
-	/* if this thread is created for fork/vfork/clone, then we want to
-	 * restore all the parent's context */
-	/* in addition to the registers which will be restored by POP_STATE */
-	else {
-		ti->cpu_context = *(struct cpu_context *)regs;
-		childregs->msr |= MSR_UMS;
-	}
-
-	/* FIXME STATE_SAVE_PT_OFFSET; */
-	ti->cpu_context.r1  = (unsigned long)childregs;
 	/* we should consider the fact that childregs is a copy of the parent
 	 * regs which were saved immediately after entering the kernel state
 	 * before enabling VM. This MSR will be restored in switch_to and
@@ -169,7 +162,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	 * excepting for VM and UMS
 	 * don't touch UMS , CARRY and cache bits
 	 * right now MSR is a copy of parent one */
-	childregs->msr |= MSR_BIP;
 	childregs->msr &= ~MSR_EIP;
 	childregs->msr |= MSR_IE;
 	childregs->msr &= ~MSR_VM;
@@ -209,29 +201,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
 }
 #endif
 
-static void kernel_thread_helper(int (*fn)(void *), void *arg)
-{
-	fn(arg);
-	do_exit(-1);
-}
-
-int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-	/* store them in non-volatile registers */
-	regs.r5 = (unsigned long)fn;
-	regs.r6 = (unsigned long)arg;
-	local_save_flags(regs.msr);
-	regs.pc = (unsigned long)kernel_thread_helper;
-	regs.pt_mode = 1;
-
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
-			&regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL_GPL(kernel_thread);
-
 unsigned long get_wchan(struct task_struct *p)
 {
 /* TBD (used by procfs) */
@@ -246,6 +215,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp)
 	regs->pt_mode = 0;
 #ifdef CONFIG_MMU
 	regs->msr |= MSR_UMS;
+	regs->msr &= ~MSR_VM;
 #endif
 }
 
diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c
index 404c0f2..63647c5 100644
--- a/arch/microblaze/kernel/sys_microblaze.c
+++ b/arch/microblaze/kernel/sys_microblaze.c
@@ -34,38 +34,6 @@
 
 #include <asm/syscalls.h>
 
-asmlinkage long microblaze_vfork(struct pt_regs *regs)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r1,
-						regs, 0, NULL, NULL);
-}
-
-asmlinkage long microblaze_clone(int flags, unsigned long stack,
-							struct pt_regs *regs)
-{
-	if (!stack)
-		stack = regs->r1;
-	return do_fork(flags, stack, regs, 0, NULL, NULL);
-}
-
-asmlinkage long microblaze_execve(const char __user *filenamei,
-				  const char __user *const __user *argv,
-				  const char __user *const __user *envp,
-				  struct pt_regs *regs)
-{
-	int error;
-	struct filename *filename;
-
-	filename = getname(filenamei);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-	error = do_execve(filename->name, argv, envp, regs);
-	putname(filename);
-out:
-	return error;
-}
-
 asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
 			unsigned long prot, unsigned long flags,
 			unsigned long fd, off_t pgoff)
@@ -75,24 +43,3 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
 
 	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT);
 }
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	register const char *__a __asm__("r5") = filename;
-	register const void *__b __asm__("r6") = argv;
-	register const void *__c __asm__("r7") = envp;
-	register unsigned long __syscall __asm__("r12") = __NR_execve;
-	register unsigned long __ret __asm__("r3");
-	__asm__ __volatile__ ("brki r14, 0x8"
-			: "=r" (__ret), "=r" (__syscall)
-			: "1" (__syscall), "r" (__a), "r" (__b), "r" (__c)
-			: "r4", "r8", "r9",
-			"r10", "r11", "r14", "cc", "memory");
-	return __ret;
-}
diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S
index 6a2b294..ff6431e 100644
--- a/arch/microblaze/kernel/syscall_table.S
+++ b/arch/microblaze/kernel/syscall_table.S
@@ -2,11 +2,7 @@ ENTRY(sys_call_table)
 	.long sys_restart_syscall	/* 0 - old "setup()" system call,
 					 * used for restarting */
 	.long sys_exit
-#ifdef CONFIG_MMU
-	.long sys_fork_wrapper
-#else
-	.long sys_ni_syscall
-#endif
+	.long sys_fork
 	.long sys_read
 	.long sys_write
 	.long sys_open			/* 5 */
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 4dbb505..a1c5b99 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -1346,8 +1346,6 @@ void __init pcibios_resource_survey(void)
 	pci_assign_unassigned_resources();
 }
 
-#ifdef CONFIG_HOTPLUG
-
 /* This is used by the PCI hotplug driver to allocate resource
  * of newly plugged busses. We can try to consolidate with the
  * rest of the code later, for now, keep it as-is as our main
@@ -1407,8 +1405,6 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
 }
 EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
 
-#endif /* CONFIG_HOTPLUG */
-
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
 	return pci_enable_resources(dev, mask);
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index dba9390..b196b0f 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -19,6 +19,7 @@ config MIPS
 	select HAVE_KRETPROBES
 	select HAVE_DEBUG_KMEMLEAK
 	select ARCH_BINFMT_ELF_RANDOMIZE_PIE
+	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
 	select RTC_LIB if !MACH_LOONGSON
 	select GENERIC_ATOMIC64 if !64BIT
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
@@ -40,6 +41,8 @@ config MIPS
 	select HAVE_MOD_ARCH_SPECIFIC
 	select MODULES_USE_ELF_REL
 	select MODULES_USE_ELF_RELA if 64BIT
+	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
 
 menu "Machine selection"
 
@@ -105,16 +108,16 @@ config ATH79
 
 config BCM47XX
 	bool "Broadcom BCM47XX based boards"
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select CEVT_R4K
 	select CSRC_R4K
 	select DMA_NONCOHERENT
+	select FW_CFE
 	select HW_HAS_PCI
 	select IRQ_CPU
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
-	select GENERIC_GPIO
 	select SYS_HAS_EARLY_PRINTK
-	select CFE
 	help
 	 Support for BCM47XX based boards
 
@@ -191,8 +194,8 @@ config MACH_DECSTATION
 
 config MACH_JAZZ
 	bool "Jazz family of machines"
-	select ARC
-	select ARC32
+	select FW_ARC
+	select FW_ARC32
 	select ARCH_MAY_HAVE_PC_FDC
 	select CEVT_R4K
 	select CSRC_R4K
@@ -456,8 +459,8 @@ config POWERTV
 
 config SGI_IP22
 	bool "SGI IP22 (Indy/Indigo2)"
-	select ARC
-	select ARC32
+	select FW_ARC
+	select FW_ARC32
 	select BOOT_ELF32
 	select CEVT_R4K
 	select CSRC_R4K
@@ -496,8 +499,8 @@ config SGI_IP22
 
 config SGI_IP27
 	bool "SGI IP27 (Origin200/2000)"
-	select ARC
-	select ARC64
+	select FW_ARC
+	select FW_ARC64
 	select BOOT_ELF64
 	select DEFAULT_SGI_PARTITION
 	select DMA_COHERENT
@@ -517,8 +520,8 @@ config SGI_IP27
 config SGI_IP28
 	bool "SGI IP28 (Indigo2 R10k) (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
-	select ARC
-	select ARC64
+	select FW_ARC
+	select FW_ARC64
 	select BOOT_ELF64
 	select CEVT_R4K
 	select CSRC_R4K
@@ -553,8 +556,8 @@ config SGI_IP28
 
 config SGI_IP32
 	bool "SGI IP32 (O2)"
-	select ARC
-	select ARC32
+	select FW_ARC
+	select FW_ARC32
 	select BOOT_ELF32
 	select CEVT_R4K
 	select CSRC_R4K
@@ -673,7 +676,7 @@ config SIBYTE_BIGSUR
 config SNI_RM
 	bool "SNI RM200/300/400"
 	select ARC if CPU_LITTLE_ENDIAN
-	select ARC32 if CPU_LITTLE_ENDIAN
+	select FW_ARC32 if CPU_LITTLE_ENDIAN
 	select SNIPROM if CPU_BIG_ENDIAN
 	select ARCH_MAY_HAVE_PC_FDC
 	select BOOT_ELF32
@@ -774,6 +777,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD
 	select DMA_COHERENT
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
+	select EDAC_SUPPORT
 	select SYS_SUPPORTS_HOTPLUG_CPU
 	select SYS_HAS_EARLY_PRINTK
 	select SYS_HAS_CPU_CAVIUM_OCTEON
@@ -817,7 +821,7 @@ config NLM_XLR_BOARD
 	select CSRC_R4K
 	select IRQ_CPU
 	select ARCH_SUPPORTS_MSI
-	select ZONE_DMA if 64BIT
+	select ZONE_DMA32 if 64BIT
 	select SYNC_R4K
 	select SYS_HAS_EARLY_PRINTK
 	select USB_ARCH_HAS_OHCI if USB_SUPPORT
@@ -845,7 +849,7 @@ config NLM_XLP_BOARD
 	select CEVT_R4K
 	select CSRC_R4K
 	select IRQ_CPU
-	select ZONE_DMA if 64BIT
+	select ZONE_DMA32 if 64BIT
 	select SYNC_R4K
 	select SYS_HAS_EARLY_PRINTK
 	select USE_OF
@@ -906,7 +910,7 @@ config SCHED_OMIT_FRAME_POINTER
 #
 # Select some configuration options automatically based on user selections.
 #
-config ARC
+config FW_ARC
 	bool
 
 config ARCH_MAY_HAVE_PC_FDC
@@ -961,7 +965,7 @@ config GPIO_TXX9
 	select ARCH_REQUIRE_GPIOLIB
 	bool
 
-config CFE
+config FW_CFE
 	bool
 
 config ARCH_DMA_ADDR_T_64BIT
@@ -1077,6 +1081,9 @@ config SYS_SUPPORTS_HUGETLBFS
 	depends on CPU_SUPPORTS_HUGEPAGES && 64BIT
 	default y
 
+config MIPS_HUGE_TLB_SUPPORT
+	def_bool HUGETLB_PAGE || TRANSPARENT_HUGEPAGE
+
 config IRQ_CPU
 	bool
 
@@ -1183,7 +1190,7 @@ config SGI_HAS_I8042
 config DEFAULT_SGI_PARTITION
 	bool
 
-config ARC32
+config FW_ARC32
 	bool
 
 config SNIPROM
@@ -1216,7 +1223,7 @@ config ARC_PROMLIB
 	depends on MACH_JAZZ || SNI_RM || SGI_IP22 || SGI_IP28 || SGI_IP32
 	default y
 
-config ARC64
+config FW_ARC64
 	bool
 
 config BOOT_ELF64
@@ -1368,6 +1375,7 @@ config CPU_R4X00
 	depends on SYS_HAS_CPU_R4X00
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
+	select CPU_SUPPORTS_HUGEPAGES
 	help
 	  MIPS Technologies R4000-series processors other than 4300, including
 	  the R4000, R4400, R4600, and 4700.
@@ -1378,12 +1386,14 @@ config CPU_TX49XX
 	select CPU_HAS_PREFETCH
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
+	select CPU_SUPPORTS_HUGEPAGES
 
 config CPU_R5000
 	bool "R5000"
 	depends on SYS_HAS_CPU_R5000
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
+	select CPU_SUPPORTS_HUGEPAGES
 	help
 	  MIPS Technologies R5000-series processors other than the Nevada.
 
@@ -1392,6 +1402,7 @@ config CPU_R5432
 	depends on SYS_HAS_CPU_R5432
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
+	select CPU_SUPPORTS_HUGEPAGES
 
 config CPU_R5500
 	bool "R5500"
@@ -1417,6 +1428,7 @@ config CPU_NEVADA
 	depends on SYS_HAS_CPU_NEVADA
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
+	select CPU_SUPPORTS_HUGEPAGES
 	help
 	  QED / PMC-Sierra RM52xx-series ("Nevada") processors.
 
@@ -1437,6 +1449,7 @@ config CPU_R10000
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_HUGEPAGES
 	help
 	  MIPS Technologies R10000-series processors.
 
@@ -1447,6 +1460,7 @@ config CPU_RM7000
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_HUGEPAGES
 
 config CPU_RM9000
 	bool "RM9000"
@@ -1455,6 +1469,7 @@ config CPU_RM9000
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_HUGEPAGES
 	select WEAK_ORDERING
 
 config CPU_SB1
@@ -1463,6 +1478,7 @@ config CPU_SB1
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_HUGEPAGES
 	select WEAK_ORDERING
 
 config CPU_CAVIUM_OCTEON
@@ -1526,9 +1542,9 @@ config CPU_XLR
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_HUGEPAGES
 	select WEAK_ORDERING
 	select WEAK_REORDERING_BEYOND_LLSC
-	select CPU_SUPPORTS_HUGEPAGES
 	help
 	  Netlogic Microsystems XLR/XLS processors.
 
@@ -1542,6 +1558,7 @@ config CPU_XLP
 	select WEAK_ORDERING
 	select WEAK_REORDERING_BEYOND_LLSC
 	select CPU_HAS_PREFETCH
+	select CPU_MIPSR2
 	help
 	  Netlogic Microsystems XLP processors.
 endchoice
@@ -1589,6 +1606,7 @@ config CPU_LOONGSON2
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_HUGEPAGES
 
 config CPU_LOONGSON1
 	bool
@@ -1755,7 +1773,7 @@ config CPU_SUPPORTS_UNCACHED_ACCELERATED
 	bool
 config MIPS_PGD_C0_CONTEXT
 	bool
-	default y if 64BIT && CPU_MIPSR2
+	default y if 64BIT && CPU_MIPSR2 && !CPU_XLP
 
 #
 # Set to y for ptrace access to watch registers.
@@ -2186,7 +2204,7 @@ config NODES_SHIFT
 
 config HW_PERF_EVENTS
 	bool "Enable hardware performance counter support for perf events"
-	depends on PERF_EVENTS && !MIPS_MT_SMTC && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON)
+	depends on PERF_EVENTS && !MIPS_MT_SMTC && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP)
 	default y
 	help
 	  Enable hardware performance counter support for perf events. If
@@ -2364,6 +2382,29 @@ config KEXEC
 	  support.  As of this writing the exact hardware interface is
 	  strongly in flux, so no good recommendation can be made.
 
+config CRASH_DUMP
+	  bool "Kernel crash dumps"
+	  help
+	  Generate crash dump after being started by kexec.
+	  This should be normally only set in special crash dump kernels
+	  which are loaded in the main kernel with kexec-tools into
+	  a specially reserved region and then later executed after
+	  a crash by kdump/kexec. The crash dump kernel must be compiled
+	  to a memory address not used by the main kernel or firmware using
+	  PHYSICAL_START.
+
+config PHYSICAL_START
+	  hex "Physical address where the kernel is loaded"
+	  default "0xffffffff84000000" if 64BIT
+	  default "0x84000000" if 32BIT
+	  depends on CRASH_DUMP
+	  help
+	  This gives the CKSEG0 or KSEG0 address where the kernel is loaded.
+	  If you plan to use kernel for capturing the crash dump change
+	  this value to start of the reserved region (the "X" value as
+	  specified in the "crashkernel=YM@XM" command line boot parameter
+	  passed to the panic-ed kernel).
+
 config SECCOMP
 	bool "Enable seccomp to safely compute untrusted bytecode"
 	depends on PROC_FS
@@ -2570,6 +2611,8 @@ source "net/Kconfig"
 
 source "drivers/Kconfig"
 
+source "drivers/firmware/Kconfig"
+
 source "fs/Kconfig"
 
 source "arch/mips/Kconfig.debug"
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 654b1ad..e1e7012 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -173,9 +173,9 @@ endif
 #
 # Firmware support
 #
-libs-$(CONFIG_ARC)		+= arch/mips/fw/arc/
-libs-$(CONFIG_CFE)		+= arch/mips/fw/cfe/
-libs-$(CONFIG_SNIPROM)		+= arch/mips/fw/sni/
+libs-$(CONFIG_FW_ARC)		+= arch/mips/fw/arc/
+libs-$(CONFIG_FW_CFE)		+= arch/mips/fw/cfe/
+libs-$(CONFIG_FW_SNIPROM)	+= arch/mips/fw/sni/
 libs-y				+= arch/mips/fw/lib/
 
 #
diff --git a/arch/mips/alchemy/common/Makefile b/arch/mips/alchemy/common/Makefile
index 407ebc0..cb83d8d 100644
--- a/arch/mips/alchemy/common/Makefile
+++ b/arch/mips/alchemy/common/Makefile
@@ -6,7 +6,7 @@
 #
 
 obj-y += prom.o time.o clocks.o platform.o power.o setup.o \
-	sleeper.o dma.o dbdma.o vss.o irq.o
+	sleeper.o dma.o dbdma.o vss.o irq.o usb.o
 
 # optional gpiolib support
 ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),)
diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c
index c0f3ce6..7af941d 100644
--- a/arch/mips/alchemy/common/platform.c
+++ b/arch/mips/alchemy/common/platform.c
@@ -17,6 +17,8 @@
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 #include <linux/slab.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
 
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
@@ -122,6 +124,53 @@ static void __init alchemy_setup_uarts(int ctype)
 static u64 alchemy_ohci_dmamask = DMA_BIT_MASK(32);
 static u64 __maybe_unused alchemy_ehci_dmamask = DMA_BIT_MASK(32);
 
+/* Power on callback for the ehci platform driver */
+static int alchemy_ehci_power_on(struct platform_device *pdev)
+{
+	return alchemy_usb_control(ALCHEMY_USB_EHCI0, 1);
+}
+
+/* Power off/suspend callback for the ehci platform driver */
+static void alchemy_ehci_power_off(struct platform_device *pdev)
+{
+	alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
+}
+
+static struct usb_ehci_pdata alchemy_ehci_pdata = {
+	.no_io_watchdog	= 1,
+	.power_on	= alchemy_ehci_power_on,
+	.power_off	= alchemy_ehci_power_off,
+	.power_suspend	= alchemy_ehci_power_off,
+};
+
+/* Power on callback for the ohci platform driver */
+static int alchemy_ohci_power_on(struct platform_device *pdev)
+{
+	int unit;
+
+	unit = (pdev->id == 1) ?
+		ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
+
+	return alchemy_usb_control(unit, 1);
+}
+
+/* Power off/suspend callback for the ohci platform driver */
+static void alchemy_ohci_power_off(struct platform_device *pdev)
+{
+	int unit;
+
+	unit = (pdev->id == 1) ?
+		ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
+
+	alchemy_usb_control(unit, 0);
+}
+
+static struct usb_ohci_pdata alchemy_ohci_pdata = {
+	.power_on		= alchemy_ohci_power_on,
+	.power_off		= alchemy_ohci_power_off,
+	.power_suspend		= alchemy_ohci_power_off,
+};
+
 static unsigned long alchemy_ohci_data[][2] __initdata = {
 	[ALCHEMY_CPU_AU1000] = { AU1000_USB_OHCI_PHYS_ADDR, AU1000_USB_HOST_INT },
 	[ALCHEMY_CPU_AU1500] = { AU1000_USB_OHCI_PHYS_ADDR, AU1500_USB_HOST_INT },
@@ -169,9 +218,10 @@ static void __init alchemy_setup_usb(int ctype)
 	res[1].start = alchemy_ohci_data[ctype][1];
 	res[1].end = res[1].start;
 	res[1].flags = IORESOURCE_IRQ;
-	pdev->name = "au1xxx-ohci";
+	pdev->name = "ohci-platform";
 	pdev->id = 0;
 	pdev->dev.dma_mask = &alchemy_ohci_dmamask;
+	pdev->dev.platform_data = &alchemy_ohci_pdata;
 
 	if (platform_device_register(pdev))
 		printk(KERN_INFO "Alchemy USB: cannot add OHCI0\n");
@@ -188,9 +238,10 @@ static void __init alchemy_setup_usb(int ctype)
 		res[1].start = alchemy_ehci_data[ctype][1];
 		res[1].end = res[1].start;
 		res[1].flags = IORESOURCE_IRQ;
-		pdev->name = "au1xxx-ehci";
+		pdev->name = "ehci-platform";
 		pdev->id = 0;
 		pdev->dev.dma_mask = &alchemy_ehci_dmamask;
+		pdev->dev.platform_data = &alchemy_ehci_pdata;
 
 		if (platform_device_register(pdev))
 			printk(KERN_INFO "Alchemy USB: cannot add EHCI0\n");
@@ -207,9 +258,10 @@ static void __init alchemy_setup_usb(int ctype)
 		res[1].start = AU1300_USB_INT;
 		res[1].end = res[1].start;
 		res[1].flags = IORESOURCE_IRQ;
-		pdev->name = "au1xxx-ohci";
+		pdev->name = "ohci-platform";
 		pdev->id = 1;
 		pdev->dev.dma_mask = &alchemy_ohci_dmamask;
+		pdev->dev.platform_data = &alchemy_ohci_pdata;
 
 		if (platform_device_register(pdev))
 			printk(KERN_INFO "Alchemy USB: cannot add OHCI1\n");
diff --git a/arch/mips/alchemy/common/usb.c b/arch/mips/alchemy/common/usb.c
new file mode 100644
index 0000000..936af83
--- /dev/null
+++ b/arch/mips/alchemy/common/usb.c
@@ -0,0 +1,614 @@
+/*
+ * USB block power/access management abstraction.
+ *
+ * Au1000+: The OHCI block control register is at the far end of the OHCI memory
+ *	    area. Au1550 has OHCI on different base address. No need to handle
+ *	    UDC here.
+ * Au1200:  one register to control access and clocks to O/EHCI, UDC and OTG
+ *	    as well as the PHY for EHCI and UDC.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/syscore_ops.h>
+#include <asm/mach-au1x00/au1000.h>
+
+/* control register offsets */
+#define AU1000_OHCICFG	0x7fffc
+#define AU1550_OHCICFG	0x07ffc
+#define AU1200_USBCFG	0x04
+
+/* Au1000 USB block config bits */
+#define USBHEN_RD	(1 << 4)		/* OHCI reset-done indicator */
+#define USBHEN_CE	(1 << 3)		/* OHCI block clock enable */
+#define USBHEN_E	(1 << 2)		/* OHCI block enable */
+#define USBHEN_C	(1 << 1)		/* OHCI block coherency bit */
+#define USBHEN_BE	(1 << 0)		/* OHCI Big-Endian */
+
+/* Au1200 USB config bits */
+#define USBCFG_PFEN	(1 << 31)		/* prefetch enable (undoc) */
+#define USBCFG_RDCOMB	(1 << 30)		/* read combining (undoc) */
+#define USBCFG_UNKNOWN	(5 << 20)		/* unknown, leave this way */
+#define USBCFG_SSD	(1 << 23)		/* serial short detect en */
+#define USBCFG_PPE	(1 << 19)		/* HS PHY PLL */
+#define USBCFG_UCE	(1 << 18)		/* UDC clock enable */
+#define USBCFG_ECE	(1 << 17)		/* EHCI clock enable */
+#define USBCFG_OCE	(1 << 16)		/* OHCI clock enable */
+#define USBCFG_FLA(x)	(((x) & 0x3f) << 8)
+#define USBCFG_UCAM	(1 << 7)		/* coherent access (undoc) */
+#define USBCFG_GME	(1 << 6)		/* OTG mem access */
+#define USBCFG_DBE	(1 << 5)		/* UDC busmaster enable */
+#define USBCFG_DME	(1 << 4)		/* UDC mem enable */
+#define USBCFG_EBE	(1 << 3)		/* EHCI busmaster enable */
+#define USBCFG_EME	(1 << 2)		/* EHCI mem enable */
+#define USBCFG_OBE	(1 << 1)		/* OHCI busmaster enable */
+#define USBCFG_OME	(1 << 0)		/* OHCI mem enable */
+#define USBCFG_INIT_AU1200	(USBCFG_PFEN | USBCFG_RDCOMB | USBCFG_UNKNOWN |\
+				 USBCFG_SSD | USBCFG_FLA(0x20) | USBCFG_UCAM | \
+				 USBCFG_GME | USBCFG_DBE | USBCFG_DME |	       \
+				 USBCFG_EBE | USBCFG_EME | USBCFG_OBE |	       \
+				 USBCFG_OME)
+
+/* Au1300 USB config registers */
+#define USB_DWC_CTRL1		0x00
+#define USB_DWC_CTRL2		0x04
+#define USB_VBUS_TIMER		0x10
+#define USB_SBUS_CTRL		0x14
+#define USB_MSR_ERR		0x18
+#define USB_DWC_CTRL3		0x1C
+#define USB_DWC_CTRL4		0x20
+#define USB_OTG_STATUS		0x28
+#define USB_DWC_CTRL5		0x2C
+#define USB_DWC_CTRL6		0x30
+#define USB_DWC_CTRL7		0x34
+#define USB_PHY_STATUS		0xC0
+#define USB_INT_STATUS		0xC4
+#define USB_INT_ENABLE		0xC8
+
+#define USB_DWC_CTRL1_OTGD	0x04 /* set to DISable OTG */
+#define USB_DWC_CTRL1_HSTRS	0x02 /* set to ENable EHCI */
+#define USB_DWC_CTRL1_DCRS	0x01 /* set to ENable UDC */
+
+#define USB_DWC_CTRL2_PHY1RS	0x04 /* set to enable PHY1 */
+#define USB_DWC_CTRL2_PHY0RS	0x02 /* set to enable PHY0 */
+#define USB_DWC_CTRL2_PHYRS	0x01 /* set to enable PHY */
+
+#define USB_DWC_CTRL3_OHCI1_CKEN	(1 << 19)
+#define USB_DWC_CTRL3_OHCI0_CKEN	(1 << 18)
+#define USB_DWC_CTRL3_EHCI0_CKEN	(1 << 17)
+#define USB_DWC_CTRL3_OTG0_CKEN		(1 << 16)
+
+#define USB_SBUS_CTRL_SBCA		0x04 /* coherent access */
+
+#define USB_INTEN_FORCE			0x20
+#define USB_INTEN_PHY			0x10
+#define USB_INTEN_UDC			0x08
+#define USB_INTEN_EHCI			0x04
+#define USB_INTEN_OHCI1			0x02
+#define USB_INTEN_OHCI0			0x01
+
+static DEFINE_SPINLOCK(alchemy_usb_lock);
+
+static inline void __au1300_usb_phyctl(void __iomem *base, int enable)
+{
+	unsigned long r, s;
+
+	r = __raw_readl(base + USB_DWC_CTRL2);
+	s = __raw_readl(base + USB_DWC_CTRL3);
+
+	s &= USB_DWC_CTRL3_OHCI1_CKEN | USB_DWC_CTRL3_OHCI0_CKEN |
+		USB_DWC_CTRL3_EHCI0_CKEN | USB_DWC_CTRL3_OTG0_CKEN;
+
+	if (enable) {
+		/* simply enable all PHYs */
+		r |= USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
+		     USB_DWC_CTRL2_PHYRS;
+		__raw_writel(r, base + USB_DWC_CTRL2);
+		wmb();
+	} else if (!s) {
+		/* no USB block active, do disable all PHYs */
+		r &= ~(USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
+		       USB_DWC_CTRL2_PHYRS);
+		__raw_writel(r, base + USB_DWC_CTRL2);
+		wmb();
+	}
+}
+
+static inline void __au1300_ohci_control(void __iomem *base, int enable, int id)
+{
+	unsigned long r;
+
+	if (enable) {
+		__raw_writel(1, base + USB_DWC_CTRL7);  /* start OHCI clock */
+		wmb();
+
+		r = __raw_readl(base + USB_DWC_CTRL3);	/* enable OHCI block */
+		r |= (id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
+			       : USB_DWC_CTRL3_OHCI1_CKEN;
+		__raw_writel(r, base + USB_DWC_CTRL3);
+		wmb();
+
+		__au1300_usb_phyctl(base, enable);	/* power up the PHYs */
+
+		r = __raw_readl(base + USB_INT_ENABLE);
+		r |= (id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1;
+		__raw_writel(r, base + USB_INT_ENABLE);
+		wmb();
+
+		/* reset the OHCI start clock bit */
+		__raw_writel(0, base + USB_DWC_CTRL7);
+		wmb();
+	} else {
+		r = __raw_readl(base + USB_INT_ENABLE);
+		r &= ~((id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1);
+		__raw_writel(r, base + USB_INT_ENABLE);
+		wmb();
+
+		r = __raw_readl(base + USB_DWC_CTRL3);
+		r &= ~((id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
+				 : USB_DWC_CTRL3_OHCI1_CKEN);
+		__raw_writel(r, base + USB_DWC_CTRL3);
+		wmb();
+
+		__au1300_usb_phyctl(base, enable);
+	}
+}
+
+static inline void __au1300_ehci_control(void __iomem *base, int enable)
+{
+	unsigned long r;
+
+	if (enable) {
+		r = __raw_readl(base + USB_DWC_CTRL3);
+		r |= USB_DWC_CTRL3_EHCI0_CKEN;
+		__raw_writel(r, base + USB_DWC_CTRL3);
+		wmb();
+
+		r = __raw_readl(base + USB_DWC_CTRL1);
+		r |= USB_DWC_CTRL1_HSTRS;
+		__raw_writel(r, base + USB_DWC_CTRL1);
+		wmb();
+
+		__au1300_usb_phyctl(base, enable);
+
+		r = __raw_readl(base + USB_INT_ENABLE);
+		r |= USB_INTEN_EHCI;
+		__raw_writel(r, base + USB_INT_ENABLE);
+		wmb();
+	} else {
+		r = __raw_readl(base + USB_INT_ENABLE);
+		r &= ~USB_INTEN_EHCI;
+		__raw_writel(r, base + USB_INT_ENABLE);
+		wmb();
+
+		r = __raw_readl(base + USB_DWC_CTRL1);
+		r &= ~USB_DWC_CTRL1_HSTRS;
+		__raw_writel(r, base + USB_DWC_CTRL1);
+		wmb();
+
+		r = __raw_readl(base + USB_DWC_CTRL3);
+		r &= ~USB_DWC_CTRL3_EHCI0_CKEN;
+		__raw_writel(r, base + USB_DWC_CTRL3);
+		wmb();
+
+		__au1300_usb_phyctl(base, enable);
+	}
+}
+
+static inline void __au1300_udc_control(void __iomem *base, int enable)
+{
+	unsigned long r;
+
+	if (enable) {
+		r = __raw_readl(base + USB_DWC_CTRL1);
+		r |= USB_DWC_CTRL1_DCRS;
+		__raw_writel(r, base + USB_DWC_CTRL1);
+		wmb();
+
+		__au1300_usb_phyctl(base, enable);
+
+		r = __raw_readl(base + USB_INT_ENABLE);
+		r |= USB_INTEN_UDC;
+		__raw_writel(r, base + USB_INT_ENABLE);
+		wmb();
+	} else {
+		r = __raw_readl(base + USB_INT_ENABLE);
+		r &= ~USB_INTEN_UDC;
+		__raw_writel(r, base + USB_INT_ENABLE);
+		wmb();
+
+		r = __raw_readl(base + USB_DWC_CTRL1);
+		r &= ~USB_DWC_CTRL1_DCRS;
+		__raw_writel(r, base + USB_DWC_CTRL1);
+		wmb();
+
+		__au1300_usb_phyctl(base, enable);
+	}
+}
+
+static inline void __au1300_otg_control(void __iomem *base, int enable)
+{
+	unsigned long r;
+	if (enable) {
+		r = __raw_readl(base + USB_DWC_CTRL3);
+		r |= USB_DWC_CTRL3_OTG0_CKEN;
+		__raw_writel(r, base + USB_DWC_CTRL3);
+		wmb();
+
+		r = __raw_readl(base + USB_DWC_CTRL1);
+		r &= ~USB_DWC_CTRL1_OTGD;
+		__raw_writel(r, base + USB_DWC_CTRL1);
+		wmb();
+
+		__au1300_usb_phyctl(base, enable);
+	} else {
+		r = __raw_readl(base + USB_DWC_CTRL1);
+		r |= USB_DWC_CTRL1_OTGD;
+		__raw_writel(r, base + USB_DWC_CTRL1);
+		wmb();
+
+		r = __raw_readl(base + USB_DWC_CTRL3);
+		r &= ~USB_DWC_CTRL3_OTG0_CKEN;
+		__raw_writel(r, base + USB_DWC_CTRL3);
+		wmb();
+
+		__au1300_usb_phyctl(base, enable);
+	}
+}
+
+static inline int au1300_usb_control(int block, int enable)
+{
+	void __iomem *base =
+		(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
+	int ret = 0;
+
+	switch (block) {
+	case ALCHEMY_USB_OHCI0:
+		__au1300_ohci_control(base, enable, 0);
+		break;
+	case ALCHEMY_USB_OHCI1:
+		__au1300_ohci_control(base, enable, 1);
+		break;
+	case ALCHEMY_USB_EHCI0:
+		__au1300_ehci_control(base, enable);
+		break;
+	case ALCHEMY_USB_UDC0:
+		__au1300_udc_control(base, enable);
+		break;
+	case ALCHEMY_USB_OTG0:
+		__au1300_otg_control(base, enable);
+		break;
+	default:
+		ret = -ENODEV;
+	}
+	return ret;
+}
+
+static inline void au1300_usb_init(void)
+{
+	void __iomem *base =
+		(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
+
+	/* set some sane defaults.  Note: we don't fiddle with DWC_CTRL4
+	 * here at all: Port 2 routing (EHCI or UDC) must be set either
+	 * by boot firmware or platform init code; I can't autodetect
+	 * a sane setting.
+	 */
+	__raw_writel(0, base + USB_INT_ENABLE); /* disable all USB irqs */
+	wmb();
+	__raw_writel(0, base + USB_DWC_CTRL3); /* disable all clocks */
+	wmb();
+	__raw_writel(~0, base + USB_MSR_ERR); /* clear all errors */
+	wmb();
+	__raw_writel(~0, base + USB_INT_STATUS); /* clear int status */
+	wmb();
+	/* set coherent access bit */
+	__raw_writel(USB_SBUS_CTRL_SBCA, base + USB_SBUS_CTRL);
+	wmb();
+}
+
+static inline void __au1200_ohci_control(void __iomem *base, int enable)
+{
+	unsigned long r = __raw_readl(base + AU1200_USBCFG);
+	if (enable) {
+		__raw_writel(r | USBCFG_OCE, base + AU1200_USBCFG);
+		wmb();
+		udelay(2000);
+	} else {
+		__raw_writel(r & ~USBCFG_OCE, base + AU1200_USBCFG);
+		wmb();
+		udelay(1000);
+	}
+}
+
+static inline void __au1200_ehci_control(void __iomem *base, int enable)
+{
+	unsigned long r = __raw_readl(base + AU1200_USBCFG);
+	if (enable) {
+		__raw_writel(r | USBCFG_ECE | USBCFG_PPE, base + AU1200_USBCFG);
+		wmb();
+		udelay(1000);
+	} else {
+		if (!(r & USBCFG_UCE))		/* UDC also off? */
+			r &= ~USBCFG_PPE;	/* yes: disable HS PHY PLL */
+		__raw_writel(r & ~USBCFG_ECE, base + AU1200_USBCFG);
+		wmb();
+		udelay(1000);
+	}
+}
+
+static inline void __au1200_udc_control(void __iomem *base, int enable)
+{
+	unsigned long r = __raw_readl(base + AU1200_USBCFG);
+	if (enable) {
+		__raw_writel(r | USBCFG_UCE | USBCFG_PPE, base + AU1200_USBCFG);
+		wmb();
+	} else {
+		if (!(r & USBCFG_ECE))		/* EHCI also off? */
+			r &= ~USBCFG_PPE;	/* yes: disable HS PHY PLL */
+		__raw_writel(r & ~USBCFG_UCE, base + AU1200_USBCFG);
+		wmb();
+	}
+}
+
+static inline int au1200_coherency_bug(void)
+{
+#if defined(CONFIG_DMA_COHERENT)
+	/* Au1200 AB USB does not support coherent memory */
+	if (!(read_c0_prid() & 0xff)) {
+		printk(KERN_INFO "Au1200 USB: this is chip revision AB !!\n");
+		printk(KERN_INFO "Au1200 USB: update your board or re-configure"
+				 " the kernel\n");
+		return -ENODEV;
+	}
+#endif
+	return 0;
+}
+
+static inline int au1200_usb_control(int block, int enable)
+{
+	void __iomem *base =
+			(void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
+	int ret = 0;
+
+	switch (block) {
+	case ALCHEMY_USB_OHCI0:
+		ret = au1200_coherency_bug();
+		if (ret && enable)
+			goto out;
+		__au1200_ohci_control(base, enable);
+		break;
+	case ALCHEMY_USB_UDC0:
+		__au1200_udc_control(base, enable);
+		break;
+	case ALCHEMY_USB_EHCI0:
+		ret = au1200_coherency_bug();
+		if (ret && enable)
+			goto out;
+		__au1200_ehci_control(base, enable);
+		break;
+	default:
+		ret = -ENODEV;
+	}
+out:
+	return ret;
+}
+
+
+/* initialize USB block(s) to a known working state */
+static inline void au1200_usb_init(void)
+{
+	void __iomem *base =
+			(void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
+	__raw_writel(USBCFG_INIT_AU1200, base + AU1200_USBCFG);
+	wmb();
+	udelay(1000);
+}
+
+static inline void au1000_usb_init(unsigned long rb, int reg)
+{
+	void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg);
+	unsigned long r = __raw_readl(base);
+
+#if defined(__BIG_ENDIAN)
+	r |= USBHEN_BE;
+#endif
+	r |= USBHEN_C;
+
+	__raw_writel(r, base);
+	wmb();
+	udelay(1000);
+}
+
+
+static inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg)
+{
+	void __iomem *base = (void __iomem *)KSEG1ADDR(rb);
+	unsigned long r = __raw_readl(base + creg);
+
+	if (enable) {
+		__raw_writel(r | USBHEN_CE, base + creg);
+		wmb();
+		udelay(1000);
+		__raw_writel(r | USBHEN_CE | USBHEN_E, base + creg);
+		wmb();
+		udelay(1000);
+
+		/* wait for reset complete (read reg twice: au1500 erratum) */
+		while (__raw_readl(base + creg),
+			!(__raw_readl(base + creg) & USBHEN_RD))
+			udelay(1000);
+	} else {
+		__raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg);
+		wmb();
+	}
+}
+
+static inline int au1000_usb_control(int block, int enable, unsigned long rb,
+				     int creg)
+{
+	int ret = 0;
+
+	switch (block) {
+	case ALCHEMY_USB_OHCI0:
+		__au1xx0_ohci_control(enable, rb, creg);
+		break;
+	default:
+		ret = -ENODEV;
+	}
+	return ret;
+}
+
+/*
+ * alchemy_usb_control - control Alchemy on-chip USB blocks
+ * @block:	USB block to target
+ * @enable:	set 1 to enable a block, 0 to disable
+ */
+int alchemy_usb_control(int block, int enable)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&alchemy_usb_lock, flags);
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1000:
+	case ALCHEMY_CPU_AU1500:
+	case ALCHEMY_CPU_AU1100:
+		ret = au1000_usb_control(block, enable,
+				AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
+		break;
+	case ALCHEMY_CPU_AU1550:
+		ret = au1000_usb_control(block, enable,
+				AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
+		break;
+	case ALCHEMY_CPU_AU1200:
+		ret = au1200_usb_control(block, enable);
+		break;
+	case ALCHEMY_CPU_AU1300:
+		ret = au1300_usb_control(block, enable);
+		break;
+	default:
+		ret = -ENODEV;
+	}
+	spin_unlock_irqrestore(&alchemy_usb_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(alchemy_usb_control);
+
+
+static unsigned long alchemy_usb_pmdata[2];
+
+static void au1000_usb_pm(unsigned long br, int creg, int susp)
+{
+	void __iomem *base = (void __iomem *)KSEG1ADDR(br);
+
+	if (susp) {
+		alchemy_usb_pmdata[0] = __raw_readl(base + creg);
+		/* There appears to be some undocumented reset register.... */
+		__raw_writel(0, base + 0x04);
+		wmb();
+		__raw_writel(0, base + creg);
+		wmb();
+	} else {
+		__raw_writel(alchemy_usb_pmdata[0], base + creg);
+		wmb();
+	}
+}
+
+static void au1200_usb_pm(int susp)
+{
+	void __iomem *base =
+			(void __iomem *)KSEG1ADDR(AU1200_USB_OTG_PHYS_ADDR);
+	if (susp) {
+		/* save OTG_CAP/MUX registers which indicate port routing */
+		/* FIXME: write an OTG driver to do that */
+		alchemy_usb_pmdata[0] = __raw_readl(base + 0x00);
+		alchemy_usb_pmdata[1] = __raw_readl(base + 0x04);
+	} else {
+		/* restore access to all MMIO areas */
+		au1200_usb_init();
+
+		/* restore OTG_CAP/MUX registers */
+		__raw_writel(alchemy_usb_pmdata[0], base + 0x00);
+		__raw_writel(alchemy_usb_pmdata[1], base + 0x04);
+		wmb();
+	}
+}
+
+static void au1300_usb_pm(int susp)
+{
+	void __iomem *base =
+			(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
+	/* remember Port2 routing */
+	if (susp) {
+		alchemy_usb_pmdata[0] = __raw_readl(base + USB_DWC_CTRL4);
+	} else {
+		au1300_usb_init();
+		__raw_writel(alchemy_usb_pmdata[0], base + USB_DWC_CTRL4);
+		wmb();
+	}
+}
+
+static void alchemy_usb_pm(int susp)
+{
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1000:
+	case ALCHEMY_CPU_AU1500:
+	case ALCHEMY_CPU_AU1100:
+		au1000_usb_pm(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG, susp);
+		break;
+	case ALCHEMY_CPU_AU1550:
+		au1000_usb_pm(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG, susp);
+		break;
+	case ALCHEMY_CPU_AU1200:
+		au1200_usb_pm(susp);
+		break;
+	case ALCHEMY_CPU_AU1300:
+		au1300_usb_pm(susp);
+		break;
+	}
+}
+
+static int alchemy_usb_suspend(void)
+{
+	alchemy_usb_pm(1);
+	return 0;
+}
+
+static void alchemy_usb_resume(void)
+{
+	alchemy_usb_pm(0);
+}
+
+static struct syscore_ops alchemy_usb_pm_ops = {
+	.suspend	= alchemy_usb_suspend,
+	.resume		= alchemy_usb_resume,
+};
+
+static int __init alchemy_usb_init(void)
+{
+	switch (alchemy_get_cputype()) {
+	case ALCHEMY_CPU_AU1000:
+	case ALCHEMY_CPU_AU1500:
+	case ALCHEMY_CPU_AU1100:
+		au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
+		break;
+	case ALCHEMY_CPU_AU1550:
+		au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
+		break;
+	case ALCHEMY_CPU_AU1200:
+		au1200_usb_init();
+		break;
+	case ALCHEMY_CPU_AU1300:
+		au1300_usb_init();
+		break;
+	}
+
+	register_syscore_ops(&alchemy_usb_pm_ops);
+
+	return 0;
+}
+arch_initcall(alchemy_usb_init);
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
index 1bbc24b..7477fd21 100644
--- a/arch/mips/ar7/platform.c
+++ b/arch/mips/ar7/platform.c
@@ -202,8 +202,11 @@ static struct resource physmap_flash_resource = {
 	.end	= 0x107fffff,
 };
 
+static const char *ar7_probe_types[] = { "ar7part", NULL };
+
 static struct physmap_flash_data physmap_flash_data = {
 	.width	= 2,
+	.part_probe_types = ar7_probe_types,
 };
 
 static struct platform_device physmap_flash = {
diff --git a/arch/mips/ath79/dev-usb.c b/arch/mips/ath79/dev-usb.c
index 072bb9b..bd2bc10 100644
--- a/arch/mips/ath79/dev-usb.c
+++ b/arch/mips/ath79/dev-usb.c
@@ -50,13 +50,11 @@ static u64 ath79_ehci_dmamask = DMA_BIT_MASK(32);
 
 static struct usb_ehci_pdata ath79_ehci_pdata_v1 = {
 	.has_synopsys_hc_bug	= 1,
-	.port_power_off		= 1,
 };
 
 static struct usb_ehci_pdata ath79_ehci_pdata_v2 = {
 	.caps_offset		= 0x100,
 	.has_tt			= 1,
-	.port_power_off		= 1,
 };
 
 static struct platform_device ath79_ehci_device = {
diff --git a/arch/mips/bcm47xx/Kconfig b/arch/mips/bcm47xx/Kconfig
index b311be4..d7af29f 100644
--- a/arch/mips/bcm47xx/Kconfig
+++ b/arch/mips/bcm47xx/Kconfig
@@ -9,6 +9,7 @@ config BCM47XX_SSB
 	select SSB_EMBEDDED
 	select SSB_B43_PCI_BRIDGE if PCI
 	select SSB_PCICORE_HOSTMODE if PCI
+	select SSB_DRIVER_GPIO
 	default y
 	help
 	 Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
@@ -23,6 +24,7 @@ config BCM47XX_BCMA
 	select BCMA_DRIVER_MIPS
 	select BCMA_HOST_PCI if PCI
 	select BCMA_DRIVER_PCI_HOSTMODE if PCI
+	select BCMA_DRIVER_GPIO
 	default y
 	help
 	 Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile
index 4389de1..1a3567f 100644
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -3,5 +3,5 @@
 # under Linux.
 #
 
-obj-y 				+= gpio.o irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
+obj-y 				+= irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
 obj-$(CONFIG_BCM47XX_SSB)	+= wgt634u.o
diff --git a/arch/mips/bcm47xx/gpio.c b/arch/mips/bcm47xx/gpio.c
deleted file mode 100644
index 5ebdf62..0000000
--- a/arch/mips/bcm47xx/gpio.c
+++ /dev/null
@@ -1,102 +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.
- *
- * Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
- */
-
-#include <linux/export.h>
-#include <linux/ssb/ssb.h>
-#include <linux/ssb/ssb_driver_chipcommon.h>
-#include <linux/ssb/ssb_driver_extif.h>
-#include <asm/mach-bcm47xx/bcm47xx.h>
-#include <asm/mach-bcm47xx/gpio.h>
-
-#if (BCM47XX_CHIPCO_GPIO_LINES > BCM47XX_EXTIF_GPIO_LINES)
-static DECLARE_BITMAP(gpio_in_use, BCM47XX_CHIPCO_GPIO_LINES);
-#else
-static DECLARE_BITMAP(gpio_in_use, BCM47XX_EXTIF_GPIO_LINES);
-#endif
-
-int gpio_request(unsigned gpio, const char *tag)
-{
-	switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-	case BCM47XX_BUS_TYPE_SSB:
-		if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
-		    ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
-			return -EINVAL;
-
-		if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
-		    ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
-			return -EINVAL;
-
-		if (test_and_set_bit(gpio, gpio_in_use))
-			return -EBUSY;
-
-		return 0;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-	case BCM47XX_BUS_TYPE_BCMA:
-		if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
-			return -EINVAL;
-
-		if (test_and_set_bit(gpio, gpio_in_use))
-			return -EBUSY;
-
-		return 0;
-#endif
-	}
-	return -EINVAL;
-}
-EXPORT_SYMBOL(gpio_request);
-
-void gpio_free(unsigned gpio)
-{
-	switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-	case BCM47XX_BUS_TYPE_SSB:
-		if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
-		    ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
-			return;
-
-		if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
-		    ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
-			return;
-
-		clear_bit(gpio, gpio_in_use);
-		return;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-	case BCM47XX_BUS_TYPE_BCMA:
-		if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
-			return;
-
-		clear_bit(gpio, gpio_in_use);
-		return;
-#endif
-	}
-}
-EXPORT_SYMBOL(gpio_free);
-
-int gpio_to_irq(unsigned gpio)
-{
-	switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-	case BCM47XX_BUS_TYPE_SSB:
-		if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco))
-			return ssb_mips_irq(bcm47xx_bus.ssb.chipco.dev) + 2;
-		else if (ssb_extif_available(&bcm47xx_bus.ssb.extif))
-			return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2;
-		else
-			return -EINVAL;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-	case BCM47XX_BUS_TYPE_BCMA:
-		return bcma_core_mips_irq(bcm47xx_bus.bcma.bus.drv_cc.core) + 2;
-#endif
-	}
-	return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(gpio_to_irq);
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c
index d43ceff..48a4c70 100644
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -43,8 +43,8 @@ static void early_nvram_init(void)
 #ifdef CONFIG_BCM47XX_SSB
 	case BCM47XX_BUS_TYPE_SSB:
 		mcore_ssb = &bcm47xx_bus.ssb.mipscore;
-		base = mcore_ssb->flash_window;
-		lim = mcore_ssb->flash_window_size;
+		base = mcore_ssb->pflash.window;
+		lim = mcore_ssb->pflash.window_size;
 		break;
 #endif
 #ifdef CONFIG_BCM47XX_BCMA
diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c
index f6e9063..8c155af 100644
--- a/arch/mips/bcm47xx/prom.c
+++ b/arch/mips/bcm47xx/prom.c
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
  *  Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
+ *  Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.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
@@ -27,6 +28,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
+#include <linux/smp.h>
 #include <asm/bootinfo.h>
 #include <asm/fw/cfe/cfe_api.h>
 #include <asm/fw/cfe/cfe_error.h>
@@ -127,6 +129,8 @@ static __init void prom_init_mem(void)
 {
 	unsigned long mem;
 	unsigned long max;
+	unsigned long off;
+	struct cpuinfo_mips *c = &current_cpu_data;
 
 	/* Figure out memory size by finding aliases.
 	 *
@@ -143,18 +147,26 @@ static __init void prom_init_mem(void)
 	 * max contains the biggest possible address supported by the platform.
 	 * If the method wants to try something above we assume 128MB ram.
 	 */
-	max = ((unsigned long)(prom_init) | ((128 << 20) - 1));
+	off = (unsigned long)prom_init;
+	max = off | ((128 << 20) - 1);
 	for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
-		if (((unsigned long)(prom_init) + mem) > max) {
+		if ((off + mem) > max) {
 			mem = (128 << 20);
 			printk(KERN_DEBUG "assume 128MB RAM\n");
 			break;
 		}
-		if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==
-		    *(unsigned long *)(prom_init))
+		if (!memcmp(prom_init, prom_init + mem, 32))
 			break;
 	}
 
+	/* Ignoring the last page when ddr size is 128M. Cached
+	 * accesses to last page is causing the processor to prefetch
+	 * using address above 128M stepping out of the ddr address
+	 * space.
+	 */
+	if (c->cputype == CPU_74K && (mem == (128  << 20)))
+		mem -= 0x1000;
+
 	add_memory_region(0, mem, BOOT_MEM_RAM);
 }
 
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index 95bf4d7..4d54b58 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -94,7 +94,7 @@ static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
 		snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
 			 bus->host_pci->bus->number + 1,
 			 PCI_SLOT(bus->host_pci->devfn));
-		bcm47xx_fill_sprom(out, prefix);
+		bcm47xx_fill_sprom(out, prefix, false);
 		return 0;
 	} else {
 		printk(KERN_WARNING "bcm47xx: unable to fill SPROM for given bustype.\n");
@@ -113,7 +113,7 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
 	bcm47xx_fill_ssb_boardinfo(&iv->boardinfo, NULL);
 
 	memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
-	bcm47xx_fill_sprom(&iv->sprom, NULL);
+	bcm47xx_fill_sprom(&iv->sprom, NULL, false);
 
 	if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
 		iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
@@ -165,16 +165,17 @@ static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
 		snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
 			 bus->host_pci->bus->number + 1,
 			 PCI_SLOT(bus->host_pci->devfn));
-		bcm47xx_fill_sprom(out, prefix);
+		bcm47xx_fill_sprom(out, prefix, false);
 		return 0;
 	case BCMA_HOSTTYPE_SOC:
 		memset(out, 0, sizeof(struct ssb_sprom));
-		bcm47xx_fill_sprom_ethernet(out, NULL);
 		core = bcma_find_core(bus, BCMA_CORE_80211);
 		if (core) {
 			snprintf(prefix, sizeof(prefix), "sb/%u/",
 				 core->core_index);
-			bcm47xx_fill_sprom(out, prefix);
+			bcm47xx_fill_sprom(out, prefix, true);
+		} else {
+			bcm47xx_fill_sprom(out, NULL, false);
 		}
 		return 0;
 	default:
diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c
index d3a8897..289cc0a 100644
--- a/arch/mips/bcm47xx/sprom.c
+++ b/arch/mips/bcm47xx/sprom.c
@@ -42,25 +42,39 @@ static void create_key(const char *prefix, const char *postfix,
 		snprintf(buf, len, "%s", name);
 }
 
+static int get_nvram_var(const char *prefix, const char *postfix,
+			 const char *name, char *buf, int len, bool fallback)
+{
+	char key[40];
+	int err;
+
+	create_key(prefix, postfix, name, key, sizeof(key));
+
+	err = nvram_getenv(key, buf, len);
+	if (fallback && err == NVRAM_ERR_ENVNOTFOUND && prefix) {
+		create_key(NULL, postfix, name, key, sizeof(key));
+		err = nvram_getenv(key, buf, len);
+	}
+	return err;
+}
+
 #define NVRAM_READ_VAL(type)						\
 static void nvram_read_ ## type (const char *prefix,			\
 				 const char *postfix, const char *name,	\
-				 type *val, type allset)		\
+				 type *val, type allset, bool fallback)	\
 {									\
 	char buf[100];							\
-	char key[40];							\
 	int err;							\
 	type var;							\
 									\
-	create_key(prefix, postfix, name, key, sizeof(key));		\
-									\
-	err = nvram_getenv(key, buf, sizeof(buf));			\
+	err = get_nvram_var(prefix, postfix, name, buf, sizeof(buf),	\
+			    fallback);					\
 	if (err < 0)							\
 		return;							\
 	err = kstrto ## type (buf, 0, &var);				\
 	if (err) {							\
-		pr_warn("can not parse nvram name %s with value %s"	\
-			" got %i", key, buf, err);			\
+		pr_warn("can not parse nvram name %s%s%s with value %s got %i\n",	\
+			prefix, name, postfix, buf, err);		\
 		return;							\
 	}								\
 	if (allset && var == allset)					\
@@ -76,22 +90,19 @@ NVRAM_READ_VAL(u32)
 #undef NVRAM_READ_VAL
 
 static void nvram_read_u32_2(const char *prefix, const char *name,
-			     u16 *val_lo, u16 *val_hi)
+			     u16 *val_lo, u16 *val_hi, bool fallback)
 {
 	char buf[100];
-	char key[40];
 	int err;
 	u32 val;
 
-	create_key(prefix, NULL, name, key, sizeof(key));
-
-	err = nvram_getenv(key, buf, sizeof(buf));
+	err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
 	if (err < 0)
 		return;
 	err = kstrtou32(buf, 0, &val);
 	if (err) {
-		pr_warn("can not parse nvram name %s with value %s got %i",
-			key, buf, err);
+		pr_warn("can not parse nvram name %s%s with value %s got %i\n",
+			prefix, name, buf, err);
 		return;
 	}
 	*val_lo = (val & 0x0000FFFFU);
@@ -99,22 +110,20 @@ static void nvram_read_u32_2(const char *prefix, const char *name,
 }
 
 static void nvram_read_leddc(const char *prefix, const char *name,
-			     u8 *leddc_on_time, u8 *leddc_off_time)
+			     u8 *leddc_on_time, u8 *leddc_off_time,
+			     bool fallback)
 {
 	char buf[100];
-	char key[40];
 	int err;
 	u32 val;
 
-	create_key(prefix, NULL, name, key, sizeof(key));
-
-	err = nvram_getenv(key, buf, sizeof(buf));
+	err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
 	if (err < 0)
 		return;
 	err = kstrtou32(buf, 0, &val);
 	if (err) {
-		pr_warn("can not parse nvram name %s with value %s got %i",
-			key, buf, err);
+		pr_warn("can not parse nvram name %s%s with value %s got %i\n",
+			prefix, name, buf, err);
 		return;
 	}
 
@@ -126,355 +135,435 @@ static void nvram_read_leddc(const char *prefix, const char *name,
 }
 
 static void nvram_read_macaddr(const char *prefix, const char *name,
-			       u8 (*val)[6])
+			       u8 (*val)[6], bool fallback)
 {
 	char buf[100];
-	char key[40];
 	int err;
 
-	create_key(prefix, NULL, name, key, sizeof(key));
-
-	err = nvram_getenv(key, buf, sizeof(buf));
+	err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
 	if (err < 0)
 		return;
+
 	nvram_parse_macaddr(buf, *val);
 }
 
 static void nvram_read_alpha2(const char *prefix, const char *name,
-			     char (*val)[2])
+			     char (*val)[2], bool fallback)
 {
 	char buf[10];
-	char key[40];
 	int err;
 
-	create_key(prefix, NULL, name, key, sizeof(key));
-
-	err = nvram_getenv(key, buf, sizeof(buf));
+	err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
 	if (err < 0)
 		return;
 	if (buf[0] == '0')
 		return;
 	if (strlen(buf) > 2) {
-		pr_warn("alpha2 is too long %s", buf);
+		pr_warn("alpha2 is too long %s\n", buf);
 		return;
 	}
 	memcpy(val, buf, sizeof(val));
 }
 
 static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom,
-					const char *prefix)
+					const char *prefix, bool fallback)
 {
-	nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0);
-	if (!sprom->board_rev)
-		nvram_read_u16(NULL, NULL, "boardrev", &sprom->board_rev, 0);
-	nvram_read_u16(prefix, NULL, "boardnum", &sprom->board_num, 0);
-	nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff);
-	nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff);
-	nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff);
-	nvram_read_u8(prefix, NULL, "ledbh3", &sprom->gpio3, 0xff);
-	nvram_read_u8(prefix, NULL, "aa2g", &sprom->ant_available_bg, 0);
-	nvram_read_u8(prefix, NULL, "aa5g", &sprom->ant_available_a, 0);
-	nvram_read_s8(prefix, NULL, "ag0", &sprom->antenna_gain.a0, 0);
-	nvram_read_s8(prefix, NULL, "ag1", &sprom->antenna_gain.a1, 0);
-	nvram_read_alpha2(prefix, "ccode", &sprom->alpha2);
+	nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff, fallback);
+	nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff, fallback);
+	nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff, fallback);
+	nvram_read_u8(prefix, NULL, "ledbh3", &sprom->gpio3, 0xff, fallback);
+	nvram_read_u8(prefix, NULL, "aa2g", &sprom->ant_available_bg, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "aa5g", &sprom->ant_available_a, 0,
+		      fallback);
+	nvram_read_s8(prefix, NULL, "ag0", &sprom->antenna_gain.a0, 0,
+		      fallback);
+	nvram_read_s8(prefix, NULL, "ag1", &sprom->antenna_gain.a1, 0,
+		      fallback);
+	nvram_read_alpha2(prefix, "ccode", &sprom->alpha2, fallback);
 }
 
 static void bcm47xx_fill_sprom_r12389(struct ssb_sprom *sprom,
-				      const char *prefix)
+				      const char *prefix, bool fallback)
 {
-	nvram_read_u16(prefix, NULL, "pa0b0", &sprom->pa0b0, 0);
-	nvram_read_u16(prefix, NULL, "pa0b1", &sprom->pa0b1, 0);
-	nvram_read_u16(prefix, NULL, "pa0b2", &sprom->pa0b2, 0);
-	nvram_read_u8(prefix, NULL, "pa0itssit", &sprom->itssi_bg, 0);
-	nvram_read_u8(prefix, NULL, "pa0maxpwr", &sprom->maxpwr_bg, 0);
-	nvram_read_u16(prefix, NULL, "pa1b0", &sprom->pa1b0, 0);
-	nvram_read_u16(prefix, NULL, "pa1b1", &sprom->pa1b1, 0);
-	nvram_read_u16(prefix, NULL, "pa1b2", &sprom->pa1b2, 0);
-	nvram_read_u8(prefix, NULL, "pa1itssit", &sprom->itssi_a, 0);
-	nvram_read_u8(prefix, NULL, "pa1maxpwr", &sprom->maxpwr_a, 0);
+	nvram_read_u16(prefix, NULL, "pa0b0", &sprom->pa0b0, 0, fallback);
+	nvram_read_u16(prefix, NULL, "pa0b1", &sprom->pa0b1, 0, fallback);
+	nvram_read_u16(prefix, NULL, "pa0b2", &sprom->pa0b2, 0, fallback);
+	nvram_read_u8(prefix, NULL, "pa0itssit", &sprom->itssi_bg, 0, fallback);
+	nvram_read_u8(prefix, NULL, "pa0maxpwr", &sprom->maxpwr_bg, 0,
+		      fallback);
+	nvram_read_u16(prefix, NULL, "pa1b0", &sprom->pa1b0, 0, fallback);
+	nvram_read_u16(prefix, NULL, "pa1b1", &sprom->pa1b1, 0, fallback);
+	nvram_read_u16(prefix, NULL, "pa1b2", &sprom->pa1b2, 0, fallback);
+	nvram_read_u8(prefix, NULL, "pa1itssit", &sprom->itssi_a, 0, fallback);
+	nvram_read_u8(prefix, NULL, "pa1maxpwr", &sprom->maxpwr_a, 0, fallback);
 }
 
-static void bcm47xx_fill_sprom_r1(struct ssb_sprom *sprom, const char *prefix)
+static void bcm47xx_fill_sprom_r1(struct ssb_sprom *sprom, const char *prefix,
+				  bool fallback)
 {
-	nvram_read_u16(prefix, NULL, "boardflags", &sprom->boardflags_lo, 0);
-	nvram_read_u8(prefix, NULL, "cc", &sprom->country_code, 0);
+	nvram_read_u16(prefix, NULL, "boardflags", &sprom->boardflags_lo, 0,
+		       fallback);
+	nvram_read_u8(prefix, NULL, "cc", &sprom->country_code, 0, fallback);
 }
 
 static void bcm47xx_fill_sprom_r2389(struct ssb_sprom *sprom,
-				     const char *prefix)
-{
-	nvram_read_u8(prefix, NULL, "opo", &sprom->opo, 0);
-	nvram_read_u16(prefix, NULL, "pa1lob0", &sprom->pa1lob0, 0);
-	nvram_read_u16(prefix, NULL, "pa1lob1", &sprom->pa1lob1, 0);
-	nvram_read_u16(prefix, NULL, "pa1lob2", &sprom->pa1lob2, 0);
-	nvram_read_u16(prefix, NULL, "pa1hib0", &sprom->pa1hib0, 0);
-	nvram_read_u16(prefix, NULL, "pa1hib1", &sprom->pa1hib1, 0);
-	nvram_read_u16(prefix, NULL, "pa1hib2", &sprom->pa1hib2, 0);
-	nvram_read_u8(prefix, NULL, "pa1lomaxpwr", &sprom->maxpwr_al, 0);
-	nvram_read_u8(prefix, NULL, "pa1himaxpwr", &sprom->maxpwr_ah, 0);
-}
-
-static void bcm47xx_fill_sprom_r2(struct ssb_sprom *sprom, const char *prefix)
+				     const char *prefix, bool fallback)
 {
-	nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
-			 &sprom->boardflags_hi);
-	nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
+	nvram_read_u8(prefix, NULL, "opo", &sprom->opo, 0, fallback);
+	nvram_read_u16(prefix, NULL, "pa1lob0", &sprom->pa1lob0, 0, fallback);
+	nvram_read_u16(prefix, NULL, "pa1lob1", &sprom->pa1lob1, 0, fallback);
+	nvram_read_u16(prefix, NULL, "pa1lob2", &sprom->pa1lob2, 0, fallback);
+	nvram_read_u16(prefix, NULL, "pa1hib0", &sprom->pa1hib0, 0, fallback);
+	nvram_read_u16(prefix, NULL, "pa1hib1", &sprom->pa1hib1, 0, fallback);
+	nvram_read_u16(prefix, NULL, "pa1hib2", &sprom->pa1hib2, 0, fallback);
+	nvram_read_u8(prefix, NULL, "pa1lomaxpwr", &sprom->maxpwr_al, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "pa1himaxpwr", &sprom->maxpwr_ah, 0,
+		      fallback);
 }
 
-static void bcm47xx_fill_sprom_r389(struct ssb_sprom *sprom, const char *prefix)
+static void bcm47xx_fill_sprom_r389(struct ssb_sprom *sprom, const char *prefix,
+				    bool fallback)
 {
-	nvram_read_u8(prefix, NULL, "bxa2g", &sprom->bxa2g, 0);
-	nvram_read_u8(prefix, NULL, "rssisav2g", &sprom->rssisav2g, 0);
-	nvram_read_u8(prefix, NULL, "rssismc2g", &sprom->rssismc2g, 0);
-	nvram_read_u8(prefix, NULL, "rssismf2g", &sprom->rssismf2g, 0);
-	nvram_read_u8(prefix, NULL, "bxa5g", &sprom->bxa5g, 0);
-	nvram_read_u8(prefix, NULL, "rssisav5g", &sprom->rssisav5g, 0);
-	nvram_read_u8(prefix, NULL, "rssismc5g", &sprom->rssismc5g, 0);
-	nvram_read_u8(prefix, NULL, "rssismf5g", &sprom->rssismf5g, 0);
-	nvram_read_u8(prefix, NULL, "tri2g", &sprom->tri2g, 0);
-	nvram_read_u8(prefix, NULL, "tri5g", &sprom->tri5g, 0);
-	nvram_read_u8(prefix, NULL, "tri5gl", &sprom->tri5gl, 0);
-	nvram_read_u8(prefix, NULL, "tri5gh", &sprom->tri5gh, 0);
-	nvram_read_s8(prefix, NULL, "rxpo2g", &sprom->rxpo2g, 0);
-	nvram_read_s8(prefix, NULL, "rxpo5g", &sprom->rxpo5g, 0);
+	nvram_read_u8(prefix, NULL, "bxa2g", &sprom->bxa2g, 0, fallback);
+	nvram_read_u8(prefix, NULL, "rssisav2g", &sprom->rssisav2g, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "rssismc2g", &sprom->rssismc2g, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "rssismf2g", &sprom->rssismf2g, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "bxa5g", &sprom->bxa5g, 0, fallback);
+	nvram_read_u8(prefix, NULL, "rssisav5g", &sprom->rssisav5g, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "rssismc5g", &sprom->rssismc5g, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "rssismf5g", &sprom->rssismf5g, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "tri2g", &sprom->tri2g, 0, fallback);
+	nvram_read_u8(prefix, NULL, "tri5g", &sprom->tri5g, 0, fallback);
+	nvram_read_u8(prefix, NULL, "tri5gl", &sprom->tri5gl, 0, fallback);
+	nvram_read_u8(prefix, NULL, "tri5gh", &sprom->tri5gh, 0, fallback);
+	nvram_read_s8(prefix, NULL, "rxpo2g", &sprom->rxpo2g, 0, fallback);
+	nvram_read_s8(prefix, NULL, "rxpo5g", &sprom->rxpo5g, 0, fallback);
 }
 
-static void bcm47xx_fill_sprom_r3(struct ssb_sprom *sprom, const char *prefix)
+static void bcm47xx_fill_sprom_r3(struct ssb_sprom *sprom, const char *prefix,
+				  bool fallback)
 {
-	nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
-			 &sprom->boardflags_hi);
-	nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
-	nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0);
+	nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0, fallback);
 	nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
-			 &sprom->leddc_off_time);
+			 &sprom->leddc_off_time, fallback);
 }
 
 static void bcm47xx_fill_sprom_r4589(struct ssb_sprom *sprom,
-				     const char *prefix)
+				     const char *prefix, bool fallback)
 {
-	nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
-			 &sprom->boardflags_hi);
-	nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo,
-			 &sprom->boardflags2_hi);
-	nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
-	nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0);
-	nvram_read_s8(prefix, NULL, "ag2", &sprom->antenna_gain.a2, 0);
-	nvram_read_s8(prefix, NULL, "ag3", &sprom->antenna_gain.a3, 0);
-	nvram_read_u8(prefix, NULL, "txchain", &sprom->txchain, 0xf);
-	nvram_read_u8(prefix, NULL, "rxchain", &sprom->rxchain, 0xf);
-	nvram_read_u8(prefix, NULL, "antswitch", &sprom->antswitch, 0xff);
+	nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0, fallback);
+	nvram_read_s8(prefix, NULL, "ag2", &sprom->antenna_gain.a2, 0,
+		      fallback);
+	nvram_read_s8(prefix, NULL, "ag3", &sprom->antenna_gain.a3, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "txchain", &sprom->txchain, 0xf, fallback);
+	nvram_read_u8(prefix, NULL, "rxchain", &sprom->rxchain, 0xf, fallback);
+	nvram_read_u8(prefix, NULL, "antswitch", &sprom->antswitch, 0xff,
+		      fallback);
 	nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
-			 &sprom->leddc_off_time);
+			 &sprom->leddc_off_time, fallback);
 }
 
-static void bcm47xx_fill_sprom_r458(struct ssb_sprom *sprom, const char *prefix)
+static void bcm47xx_fill_sprom_r458(struct ssb_sprom *sprom, const char *prefix,
+				    bool fallback)
 {
-	nvram_read_u16(prefix, NULL, "cck2gpo", &sprom->cck2gpo, 0);
-	nvram_read_u32(prefix, NULL, "ofdm2gpo", &sprom->ofdm2gpo, 0);
-	nvram_read_u32(prefix, NULL, "ofdm5gpo", &sprom->ofdm5gpo, 0);
-	nvram_read_u32(prefix, NULL, "ofdm5glpo", &sprom->ofdm5glpo, 0);
-	nvram_read_u32(prefix, NULL, "ofdm5ghpo", &sprom->ofdm5ghpo, 0);
-	nvram_read_u16(prefix, NULL, "cddpo", &sprom->cddpo, 0);
-	nvram_read_u16(prefix, NULL, "stbcpo", &sprom->stbcpo, 0);
-	nvram_read_u16(prefix, NULL, "bw40po", &sprom->bw40po, 0);
-	nvram_read_u16(prefix, NULL, "bwduppo", &sprom->bwduppo, 0);
-	nvram_read_u16(prefix, NULL, "mcs2gpo0", &sprom->mcs2gpo[0], 0);
-	nvram_read_u16(prefix, NULL, "mcs2gpo1", &sprom->mcs2gpo[1], 0);
-	nvram_read_u16(prefix, NULL, "mcs2gpo2", &sprom->mcs2gpo[2], 0);
-	nvram_read_u16(prefix, NULL, "mcs2gpo3", &sprom->mcs2gpo[3], 0);
-	nvram_read_u16(prefix, NULL, "mcs2gpo4", &sprom->mcs2gpo[4], 0);
-	nvram_read_u16(prefix, NULL, "mcs2gpo5", &sprom->mcs2gpo[5], 0);
-	nvram_read_u16(prefix, NULL, "mcs2gpo6", &sprom->mcs2gpo[6], 0);
-	nvram_read_u16(prefix, NULL, "mcs2gpo7", &sprom->mcs2gpo[7], 0);
-	nvram_read_u16(prefix, NULL, "mcs5gpo0", &sprom->mcs5gpo[0], 0);
-	nvram_read_u16(prefix, NULL, "mcs5gpo1", &sprom->mcs5gpo[1], 0);
-	nvram_read_u16(prefix, NULL, "mcs5gpo2", &sprom->mcs5gpo[2], 0);
-	nvram_read_u16(prefix, NULL, "mcs5gpo3", &sprom->mcs5gpo[3], 0);
-	nvram_read_u16(prefix, NULL, "mcs5gpo4", &sprom->mcs5gpo[4], 0);
-	nvram_read_u16(prefix, NULL, "mcs5gpo5", &sprom->mcs5gpo[5], 0);
-	nvram_read_u16(prefix, NULL, "mcs5gpo6", &sprom->mcs5gpo[6], 0);
-	nvram_read_u16(prefix, NULL, "mcs5gpo7", &sprom->mcs5gpo[7], 0);
-	nvram_read_u16(prefix, NULL, "mcs5glpo0", &sprom->mcs5glpo[0], 0);
-	nvram_read_u16(prefix, NULL, "mcs5glpo1", &sprom->mcs5glpo[1], 0);
-	nvram_read_u16(prefix, NULL, "mcs5glpo2", &sprom->mcs5glpo[2], 0);
-	nvram_read_u16(prefix, NULL, "mcs5glpo3", &sprom->mcs5glpo[3], 0);
-	nvram_read_u16(prefix, NULL, "mcs5glpo4", &sprom->mcs5glpo[4], 0);
-	nvram_read_u16(prefix, NULL, "mcs5glpo5", &sprom->mcs5glpo[5], 0);
-	nvram_read_u16(prefix, NULL, "mcs5glpo6", &sprom->mcs5glpo[6], 0);
-	nvram_read_u16(prefix, NULL, "mcs5glpo7", &sprom->mcs5glpo[7], 0);
-	nvram_read_u16(prefix, NULL, "mcs5ghpo0", &sprom->mcs5ghpo[0], 0);
-	nvram_read_u16(prefix, NULL, "mcs5ghpo1", &sprom->mcs5ghpo[1], 0);
-	nvram_read_u16(prefix, NULL, "mcs5ghpo2", &sprom->mcs5ghpo[2], 0);
-	nvram_read_u16(prefix, NULL, "mcs5ghpo3", &sprom->mcs5ghpo[3], 0);
-	nvram_read_u16(prefix, NULL, "mcs5ghpo4", &sprom->mcs5ghpo[4], 0);
-	nvram_read_u16(prefix, NULL, "mcs5ghpo5", &sprom->mcs5ghpo[5], 0);
-	nvram_read_u16(prefix, NULL, "mcs5ghpo6", &sprom->mcs5ghpo[6], 0);
-	nvram_read_u16(prefix, NULL, "mcs5ghpo7", &sprom->mcs5ghpo[7], 0);
+	nvram_read_u16(prefix, NULL, "cck2gpo", &sprom->cck2gpo, 0, fallback);
+	nvram_read_u32(prefix, NULL, "ofdm2gpo", &sprom->ofdm2gpo, 0, fallback);
+	nvram_read_u32(prefix, NULL, "ofdm5gpo", &sprom->ofdm5gpo, 0, fallback);
+	nvram_read_u32(prefix, NULL, "ofdm5glpo", &sprom->ofdm5glpo, 0,
+		       fallback);
+	nvram_read_u32(prefix, NULL, "ofdm5ghpo", &sprom->ofdm5ghpo, 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "cddpo", &sprom->cddpo, 0, fallback);
+	nvram_read_u16(prefix, NULL, "stbcpo", &sprom->stbcpo, 0, fallback);
+	nvram_read_u16(prefix, NULL, "bw40po", &sprom->bw40po, 0, fallback);
+	nvram_read_u16(prefix, NULL, "bwduppo", &sprom->bwduppo, 0, fallback);
+	nvram_read_u16(prefix, NULL, "mcs2gpo0", &sprom->mcs2gpo[0], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs2gpo1", &sprom->mcs2gpo[1], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs2gpo2", &sprom->mcs2gpo[2], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs2gpo3", &sprom->mcs2gpo[3], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs2gpo4", &sprom->mcs2gpo[4], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs2gpo5", &sprom->mcs2gpo[5], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs2gpo6", &sprom->mcs2gpo[6], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs2gpo7", &sprom->mcs2gpo[7], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5gpo0", &sprom->mcs5gpo[0], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5gpo1", &sprom->mcs5gpo[1], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5gpo2", &sprom->mcs5gpo[2], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5gpo3", &sprom->mcs5gpo[3], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5gpo4", &sprom->mcs5gpo[4], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5gpo5", &sprom->mcs5gpo[5], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5gpo6", &sprom->mcs5gpo[6], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5gpo7", &sprom->mcs5gpo[7], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5glpo0", &sprom->mcs5glpo[0], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5glpo1", &sprom->mcs5glpo[1], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5glpo2", &sprom->mcs5glpo[2], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5glpo3", &sprom->mcs5glpo[3], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5glpo4", &sprom->mcs5glpo[4], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5glpo5", &sprom->mcs5glpo[5], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5glpo6", &sprom->mcs5glpo[6], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5glpo7", &sprom->mcs5glpo[7], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5ghpo0", &sprom->mcs5ghpo[0], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5ghpo1", &sprom->mcs5ghpo[1], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5ghpo2", &sprom->mcs5ghpo[2], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5ghpo3", &sprom->mcs5ghpo[3], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5ghpo4", &sprom->mcs5ghpo[4], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5ghpo5", &sprom->mcs5ghpo[5], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5ghpo6", &sprom->mcs5ghpo[6], 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs5ghpo7", &sprom->mcs5ghpo[7], 0,
+		       fallback);
 }
 
-static void bcm47xx_fill_sprom_r45(struct ssb_sprom *sprom, const char *prefix)
+static void bcm47xx_fill_sprom_r45(struct ssb_sprom *sprom, const char *prefix,
+				   bool fallback)
 {
-	nvram_read_u8(prefix, NULL, "txpid2ga0", &sprom->txpid2g[0], 0);
-	nvram_read_u8(prefix, NULL, "txpid2ga1", &sprom->txpid2g[1], 0);
-	nvram_read_u8(prefix, NULL, "txpid2ga2", &sprom->txpid2g[2], 0);
-	nvram_read_u8(prefix, NULL, "txpid2ga3", &sprom->txpid2g[3], 0);
-	nvram_read_u8(prefix, NULL, "txpid5ga0", &sprom->txpid5g[0], 0);
-	nvram_read_u8(prefix, NULL, "txpid5ga1", &sprom->txpid5g[1], 0);
-	nvram_read_u8(prefix, NULL, "txpid5ga2", &sprom->txpid5g[2], 0);
-	nvram_read_u8(prefix, NULL, "txpid5ga3", &sprom->txpid5g[3], 0);
-	nvram_read_u8(prefix, NULL, "txpid5gla0", &sprom->txpid5gl[0], 0);
-	nvram_read_u8(prefix, NULL, "txpid5gla1", &sprom->txpid5gl[1], 0);
-	nvram_read_u8(prefix, NULL, "txpid5gla2", &sprom->txpid5gl[2], 0);
-	nvram_read_u8(prefix, NULL, "txpid5gla3", &sprom->txpid5gl[3], 0);
-	nvram_read_u8(prefix, NULL, "txpid5gha0", &sprom->txpid5gh[0], 0);
-	nvram_read_u8(prefix, NULL, "txpid5gha1", &sprom->txpid5gh[1], 0);
-	nvram_read_u8(prefix, NULL, "txpid5gha2", &sprom->txpid5gh[2], 0);
-	nvram_read_u8(prefix, NULL, "txpid5gha3", &sprom->txpid5gh[3], 0);
+	nvram_read_u8(prefix, NULL, "txpid2ga0", &sprom->txpid2g[0], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "txpid2ga1", &sprom->txpid2g[1], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "txpid2ga2", &sprom->txpid2g[2], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "txpid2ga3", &sprom->txpid2g[3], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "txpid5ga0", &sprom->txpid5g[0], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "txpid5ga1", &sprom->txpid5g[1], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "txpid5ga2", &sprom->txpid5g[2], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "txpid5ga3", &sprom->txpid5g[3], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "txpid5gla0", &sprom->txpid5gl[0], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "txpid5gla1", &sprom->txpid5gl[1], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "txpid5gla2", &sprom->txpid5gl[2], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "txpid5gla3", &sprom->txpid5gl[3], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "txpid5gha0", &sprom->txpid5gh[0], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "txpid5gha1", &sprom->txpid5gh[1], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "txpid5gha2", &sprom->txpid5gh[2], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "txpid5gha3", &sprom->txpid5gh[3], 0,
+		      fallback);
 }
 
-static void bcm47xx_fill_sprom_r89(struct ssb_sprom *sprom, const char *prefix)
+static void bcm47xx_fill_sprom_r89(struct ssb_sprom *sprom, const char *prefix,
+				   bool fallback)
 {
-	nvram_read_u8(prefix, NULL, "tssipos2g", &sprom->fem.ghz2.tssipos, 0);
+	nvram_read_u8(prefix, NULL, "tssipos2g", &sprom->fem.ghz2.tssipos, 0,
+		      fallback);
 	nvram_read_u8(prefix, NULL, "extpagain2g",
-		      &sprom->fem.ghz2.extpa_gain, 0);
+		      &sprom->fem.ghz2.extpa_gain, 0, fallback);
 	nvram_read_u8(prefix, NULL, "pdetrange2g",
-		      &sprom->fem.ghz2.pdet_range, 0);
-	nvram_read_u8(prefix, NULL, "triso2g", &sprom->fem.ghz2.tr_iso, 0);
-	nvram_read_u8(prefix, NULL, "antswctl2g", &sprom->fem.ghz2.antswlut, 0);
-	nvram_read_u8(prefix, NULL, "tssipos5g", &sprom->fem.ghz5.tssipos, 0);
+		      &sprom->fem.ghz2.pdet_range, 0, fallback);
+	nvram_read_u8(prefix, NULL, "triso2g", &sprom->fem.ghz2.tr_iso, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "antswctl2g", &sprom->fem.ghz2.antswlut, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "tssipos5g", &sprom->fem.ghz5.tssipos, 0,
+		      fallback);
 	nvram_read_u8(prefix, NULL, "extpagain5g",
-		      &sprom->fem.ghz5.extpa_gain, 0);
+		      &sprom->fem.ghz5.extpa_gain, 0, fallback);
 	nvram_read_u8(prefix, NULL, "pdetrange5g",
-		      &sprom->fem.ghz5.pdet_range, 0);
-	nvram_read_u8(prefix, NULL, "triso5g", &sprom->fem.ghz5.tr_iso, 0);
-	nvram_read_u8(prefix, NULL, "antswctl5g", &sprom->fem.ghz5.antswlut, 0);
-	nvram_read_u8(prefix, NULL, "tempthresh", &sprom->tempthresh, 0);
-	nvram_read_u8(prefix, NULL, "tempoffset", &sprom->tempoffset, 0);
-	nvram_read_u16(prefix, NULL, "rawtempsense", &sprom->rawtempsense, 0);
-	nvram_read_u8(prefix, NULL, "measpower", &sprom->measpower, 0);
+		      &sprom->fem.ghz5.pdet_range, 0, fallback);
+	nvram_read_u8(prefix, NULL, "triso5g", &sprom->fem.ghz5.tr_iso, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "antswctl5g", &sprom->fem.ghz5.antswlut, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "tempthresh", &sprom->tempthresh, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "tempoffset", &sprom->tempoffset, 0,
+		      fallback);
+	nvram_read_u16(prefix, NULL, "rawtempsense", &sprom->rawtempsense, 0,
+		       fallback);
+	nvram_read_u8(prefix, NULL, "measpower", &sprom->measpower, 0,
+		      fallback);
 	nvram_read_u8(prefix, NULL, "tempsense_slope",
-		      &sprom->tempsense_slope, 0);
-	nvram_read_u8(prefix, NULL, "tempcorrx", &sprom->tempcorrx, 0);
+		      &sprom->tempsense_slope, 0, fallback);
+	nvram_read_u8(prefix, NULL, "tempcorrx", &sprom->tempcorrx, 0,
+		       fallback);
 	nvram_read_u8(prefix, NULL, "tempsense_option",
-		      &sprom->tempsense_option, 0);
+		      &sprom->tempsense_option, 0, fallback);
 	nvram_read_u8(prefix, NULL, "freqoffset_corr",
-		      &sprom->freqoffset_corr, 0);
-	nvram_read_u8(prefix, NULL, "iqcal_swp_dis", &sprom->iqcal_swp_dis, 0);
-	nvram_read_u8(prefix, NULL, "hw_iqcal_en", &sprom->hw_iqcal_en, 0);
-	nvram_read_u8(prefix, NULL, "elna2g", &sprom->elna2g, 0);
-	nvram_read_u8(prefix, NULL, "elna5g", &sprom->elna5g, 0);
+		      &sprom->freqoffset_corr, 0, fallback);
+	nvram_read_u8(prefix, NULL, "iqcal_swp_dis", &sprom->iqcal_swp_dis, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "hw_iqcal_en", &sprom->hw_iqcal_en, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "elna2g", &sprom->elna2g, 0, fallback);
+	nvram_read_u8(prefix, NULL, "elna5g", &sprom->elna5g, 0, fallback);
 	nvram_read_u8(prefix, NULL, "phycal_tempdelta",
-		      &sprom->phycal_tempdelta, 0);
-	nvram_read_u8(prefix, NULL, "temps_period", &sprom->temps_period, 0);
+		      &sprom->phycal_tempdelta, 0, fallback);
+	nvram_read_u8(prefix, NULL, "temps_period", &sprom->temps_period, 0,
+		      fallback);
 	nvram_read_u8(prefix, NULL, "temps_hysteresis",
-		      &sprom->temps_hysteresis, 0);
-	nvram_read_u8(prefix, NULL, "measpower1", &sprom->measpower1, 0);
-	nvram_read_u8(prefix, NULL, "measpower2", &sprom->measpower2, 0);
+		      &sprom->temps_hysteresis, 0, fallback);
+	nvram_read_u8(prefix, NULL, "measpower1", &sprom->measpower1, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "measpower2", &sprom->measpower2, 0,
+		      fallback);
 	nvram_read_u8(prefix, NULL, "rxgainerr2ga0",
-		      &sprom->rxgainerr2ga[0], 0);
+		      &sprom->rxgainerr2ga[0], 0, fallback);
 	nvram_read_u8(prefix, NULL, "rxgainerr2ga1",
-		      &sprom->rxgainerr2ga[1], 0);
+		      &sprom->rxgainerr2ga[1], 0, fallback);
 	nvram_read_u8(prefix, NULL, "rxgainerr2ga2",
-		      &sprom->rxgainerr2ga[2], 0);
+		      &sprom->rxgainerr2ga[2], 0, fallback);
 	nvram_read_u8(prefix, NULL, "rxgainerr5gla0",
-		      &sprom->rxgainerr5gla[0], 0);
+		      &sprom->rxgainerr5gla[0], 0, fallback);
 	nvram_read_u8(prefix, NULL, "rxgainerr5gla1",
-		      &sprom->rxgainerr5gla[1], 0);
+		      &sprom->rxgainerr5gla[1], 0, fallback);
 	nvram_read_u8(prefix, NULL, "rxgainerr5gla2",
-		      &sprom->rxgainerr5gla[2], 0);
+		      &sprom->rxgainerr5gla[2], 0, fallback);
 	nvram_read_u8(prefix, NULL, "rxgainerr5gma0",
-		      &sprom->rxgainerr5gma[0], 0);
+		      &sprom->rxgainerr5gma[0], 0, fallback);
 	nvram_read_u8(prefix, NULL, "rxgainerr5gma1",
-		      &sprom->rxgainerr5gma[1], 0);
+		      &sprom->rxgainerr5gma[1], 0, fallback);
 	nvram_read_u8(prefix, NULL, "rxgainerr5gma2",
-		      &sprom->rxgainerr5gma[2], 0);
+		      &sprom->rxgainerr5gma[2], 0, fallback);
 	nvram_read_u8(prefix, NULL, "rxgainerr5gha0",
-		      &sprom->rxgainerr5gha[0], 0);
+		      &sprom->rxgainerr5gha[0], 0, fallback);
 	nvram_read_u8(prefix, NULL, "rxgainerr5gha1",
-		      &sprom->rxgainerr5gha[1], 0);
+		      &sprom->rxgainerr5gha[1], 0, fallback);
 	nvram_read_u8(prefix, NULL, "rxgainerr5gha2",
-		      &sprom->rxgainerr5gha[2], 0);
+		      &sprom->rxgainerr5gha[2], 0, fallback);
 	nvram_read_u8(prefix, NULL, "rxgainerr5gua0",
-		      &sprom->rxgainerr5gua[0], 0);
+		      &sprom->rxgainerr5gua[0], 0, fallback);
 	nvram_read_u8(prefix, NULL, "rxgainerr5gua1",
-		      &sprom->rxgainerr5gua[1], 0);
+		      &sprom->rxgainerr5gua[1], 0, fallback);
 	nvram_read_u8(prefix, NULL, "rxgainerr5gua2",
-		      &sprom->rxgainerr5gua[2], 0);
-	nvram_read_u8(prefix, NULL, "noiselvl2ga0", &sprom->noiselvl2ga[0], 0);
-	nvram_read_u8(prefix, NULL, "noiselvl2ga1", &sprom->noiselvl2ga[1], 0);
-	nvram_read_u8(prefix, NULL, "noiselvl2ga2", &sprom->noiselvl2ga[2], 0);
+		      &sprom->rxgainerr5gua[2], 0, fallback);
+	nvram_read_u8(prefix, NULL, "noiselvl2ga0", &sprom->noiselvl2ga[0], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "noiselvl2ga1", &sprom->noiselvl2ga[1], 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "noiselvl2ga2", &sprom->noiselvl2ga[2], 0,
+		      fallback);
 	nvram_read_u8(prefix, NULL, "noiselvl5gla0",
-		      &sprom->noiselvl5gla[0], 0);
+		      &sprom->noiselvl5gla[0], 0, fallback);
 	nvram_read_u8(prefix, NULL, "noiselvl5gla1",
-		      &sprom->noiselvl5gla[1], 0);
+		      &sprom->noiselvl5gla[1], 0, fallback);
 	nvram_read_u8(prefix, NULL, "noiselvl5gla2",
-		      &sprom->noiselvl5gla[2], 0);
+		      &sprom->noiselvl5gla[2], 0, fallback);
 	nvram_read_u8(prefix, NULL, "noiselvl5gma0",
-		      &sprom->noiselvl5gma[0], 0);
+		      &sprom->noiselvl5gma[0], 0, fallback);
 	nvram_read_u8(prefix, NULL, "noiselvl5gma1",
-		      &sprom->noiselvl5gma[1], 0);
+		      &sprom->noiselvl5gma[1], 0, fallback);
 	nvram_read_u8(prefix, NULL, "noiselvl5gma2",
-		      &sprom->noiselvl5gma[2], 0);
+		      &sprom->noiselvl5gma[2], 0, fallback);
 	nvram_read_u8(prefix, NULL, "noiselvl5gha0",
-		      &sprom->noiselvl5gha[0], 0);
+		      &sprom->noiselvl5gha[0], 0, fallback);
 	nvram_read_u8(prefix, NULL, "noiselvl5gha1",
-		      &sprom->noiselvl5gha[1], 0);
+		      &sprom->noiselvl5gha[1], 0, fallback);
 	nvram_read_u8(prefix, NULL, "noiselvl5gha2",
-		      &sprom->noiselvl5gha[2], 0);
+		      &sprom->noiselvl5gha[2], 0, fallback);
 	nvram_read_u8(prefix, NULL, "noiselvl5gua0",
-		      &sprom->noiselvl5gua[0], 0);
+		      &sprom->noiselvl5gua[0], 0, fallback);
 	nvram_read_u8(prefix, NULL, "noiselvl5gua1",
-		      &sprom->noiselvl5gua[1], 0);
+		      &sprom->noiselvl5gua[1], 0, fallback);
 	nvram_read_u8(prefix, NULL, "noiselvl5gua2",
-		      &sprom->noiselvl5gua[2], 0);
+		      &sprom->noiselvl5gua[2], 0, fallback);
 	nvram_read_u8(prefix, NULL, "pcieingress_war",
-		      &sprom->pcieingress_war, 0);
+		      &sprom->pcieingress_war, 0, fallback);
 }
 
-static void bcm47xx_fill_sprom_r9(struct ssb_sprom *sprom, const char *prefix)
+static void bcm47xx_fill_sprom_r9(struct ssb_sprom *sprom, const char *prefix,
+				  bool fallback)
 {
-	nvram_read_u16(prefix, NULL, "cckbw202gpo", &sprom->cckbw202gpo, 0);
-	nvram_read_u16(prefix, NULL, "cckbw20ul2gpo", &sprom->cckbw20ul2gpo, 0);
+	nvram_read_u16(prefix, NULL, "cckbw202gpo", &sprom->cckbw202gpo, 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "cckbw20ul2gpo", &sprom->cckbw20ul2gpo, 0,
+		       fallback);
 	nvram_read_u32(prefix, NULL, "legofdmbw202gpo",
-		       &sprom->legofdmbw202gpo, 0);
+		       &sprom->legofdmbw202gpo, 0, fallback);
 	nvram_read_u32(prefix, NULL, "legofdmbw20ul2gpo",
-		       &sprom->legofdmbw20ul2gpo, 0);
+		       &sprom->legofdmbw20ul2gpo, 0, fallback);
 	nvram_read_u32(prefix, NULL, "legofdmbw205glpo",
-		       &sprom->legofdmbw205glpo, 0);
+		       &sprom->legofdmbw205glpo, 0, fallback);
 	nvram_read_u32(prefix, NULL, "legofdmbw20ul5glpo",
-		       &sprom->legofdmbw20ul5glpo, 0);
+		       &sprom->legofdmbw20ul5glpo, 0, fallback);
 	nvram_read_u32(prefix, NULL, "legofdmbw205gmpo",
-		       &sprom->legofdmbw205gmpo, 0);
+		       &sprom->legofdmbw205gmpo, 0, fallback);
 	nvram_read_u32(prefix, NULL, "legofdmbw20ul5gmpo",
-		       &sprom->legofdmbw20ul5gmpo, 0);
+		       &sprom->legofdmbw20ul5gmpo, 0, fallback);
 	nvram_read_u32(prefix, NULL, "legofdmbw205ghpo",
-		       &sprom->legofdmbw205ghpo, 0);
+		       &sprom->legofdmbw205ghpo, 0, fallback);
 	nvram_read_u32(prefix, NULL, "legofdmbw20ul5ghpo",
-		       &sprom->legofdmbw20ul5ghpo, 0);
-	nvram_read_u32(prefix, NULL, "mcsbw202gpo", &sprom->mcsbw202gpo, 0);
-	nvram_read_u32(prefix, NULL, "mcsbw20ul2gpo", &sprom->mcsbw20ul2gpo, 0);
-	nvram_read_u32(prefix, NULL, "mcsbw402gpo", &sprom->mcsbw402gpo, 0);
-	nvram_read_u32(prefix, NULL, "mcsbw205glpo", &sprom->mcsbw205glpo, 0);
+		       &sprom->legofdmbw20ul5ghpo, 0, fallback);
+	nvram_read_u32(prefix, NULL, "mcsbw202gpo", &sprom->mcsbw202gpo, 0,
+		       fallback);
+	nvram_read_u32(prefix, NULL, "mcsbw20ul2gpo", &sprom->mcsbw20ul2gpo, 0,
+		       fallback);
+	nvram_read_u32(prefix, NULL, "mcsbw402gpo", &sprom->mcsbw402gpo, 0,
+		       fallback);
+	nvram_read_u32(prefix, NULL, "mcsbw205glpo", &sprom->mcsbw205glpo, 0,
+		       fallback);
 	nvram_read_u32(prefix, NULL, "mcsbw20ul5glpo",
-		       &sprom->mcsbw20ul5glpo, 0);
-	nvram_read_u32(prefix, NULL, "mcsbw405glpo", &sprom->mcsbw405glpo, 0);
-	nvram_read_u32(prefix, NULL, "mcsbw205gmpo", &sprom->mcsbw205gmpo, 0);
+		       &sprom->mcsbw20ul5glpo, 0, fallback);
+	nvram_read_u32(prefix, NULL, "mcsbw405glpo", &sprom->mcsbw405glpo, 0,
+		       fallback);
+	nvram_read_u32(prefix, NULL, "mcsbw205gmpo", &sprom->mcsbw205gmpo, 0,
+		       fallback);
 	nvram_read_u32(prefix, NULL, "mcsbw20ul5gmpo",
-		       &sprom->mcsbw20ul5gmpo, 0);
-	nvram_read_u32(prefix, NULL, "mcsbw405gmpo", &sprom->mcsbw405gmpo, 0);
-	nvram_read_u32(prefix, NULL, "mcsbw205ghpo", &sprom->mcsbw205ghpo, 0);
+		       &sprom->mcsbw20ul5gmpo, 0, fallback);
+	nvram_read_u32(prefix, NULL, "mcsbw405gmpo", &sprom->mcsbw405gmpo, 0,
+		       fallback);
+	nvram_read_u32(prefix, NULL, "mcsbw205ghpo", &sprom->mcsbw205ghpo, 0,
+		       fallback);
 	nvram_read_u32(prefix, NULL, "mcsbw20ul5ghpo",
-		       &sprom->mcsbw20ul5ghpo, 0);
-	nvram_read_u32(prefix, NULL, "mcsbw405ghpo", &sprom->mcsbw405ghpo, 0);
-	nvram_read_u16(prefix, NULL, "mcs32po", &sprom->mcs32po, 0);
+		       &sprom->mcsbw20ul5ghpo, 0, fallback);
+	nvram_read_u32(prefix, NULL, "mcsbw405ghpo", &sprom->mcsbw405ghpo, 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "mcs32po", &sprom->mcs32po, 0, fallback);
 	nvram_read_u16(prefix, NULL, "legofdm40duppo",
-		       &sprom->legofdm40duppo, 0);
-	nvram_read_u8(prefix, NULL, "sar2g", &sprom->sar2g, 0);
-	nvram_read_u8(prefix, NULL, "sar5g", &sprom->sar5g, 0);
+		       &sprom->legofdm40duppo, 0, fallback);
+	nvram_read_u8(prefix, NULL, "sar2g", &sprom->sar2g, 0, fallback);
+	nvram_read_u8(prefix, NULL, "sar5g", &sprom->sar5g, 0, fallback);
 }
 
 static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,
-					  const char *prefix)
+					  const char *prefix, bool fallback)
 {
 	char postfix[2];
 	int i;
@@ -483,46 +572,46 @@ static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,
 		struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
 		snprintf(postfix, sizeof(postfix), "%i", i);
 		nvram_read_u8(prefix, postfix, "maxp2ga",
-			      &pwr_info->maxpwr_2g, 0);
+			      &pwr_info->maxpwr_2g, 0, fallback);
 		nvram_read_u8(prefix, postfix, "itt2ga",
-			      &pwr_info->itssi_2g, 0);
+			      &pwr_info->itssi_2g, 0, fallback);
 		nvram_read_u8(prefix, postfix, "itt5ga",
-			      &pwr_info->itssi_5g, 0);
+			      &pwr_info->itssi_5g, 0, fallback);
 		nvram_read_u16(prefix, postfix, "pa2gw0a",
-			       &pwr_info->pa_2g[0], 0);
+			       &pwr_info->pa_2g[0], 0, fallback);
 		nvram_read_u16(prefix, postfix, "pa2gw1a",
-			       &pwr_info->pa_2g[1], 0);
+			       &pwr_info->pa_2g[1], 0, fallback);
 		nvram_read_u16(prefix, postfix, "pa2gw2a",
-			       &pwr_info->pa_2g[2], 0);
+			       &pwr_info->pa_2g[2], 0, fallback);
 		nvram_read_u8(prefix, postfix, "maxp5ga",
-			      &pwr_info->maxpwr_5g, 0);
+			      &pwr_info->maxpwr_5g, 0, fallback);
 		nvram_read_u8(prefix, postfix, "maxp5gha",
-			      &pwr_info->maxpwr_5gh, 0);
+			      &pwr_info->maxpwr_5gh, 0, fallback);
 		nvram_read_u8(prefix, postfix, "maxp5gla",
-			      &pwr_info->maxpwr_5gl, 0);
+			      &pwr_info->maxpwr_5gl, 0, fallback);
 		nvram_read_u16(prefix, postfix, "pa5gw0a",
-			       &pwr_info->pa_5g[0], 0);
+			       &pwr_info->pa_5g[0], 0, fallback);
 		nvram_read_u16(prefix, postfix, "pa5gw1a",
-			       &pwr_info->pa_5g[1], 0);
+			       &pwr_info->pa_5g[1], 0, fallback);
 		nvram_read_u16(prefix, postfix, "pa5gw2a",
-			       &pwr_info->pa_5g[2], 0);
+			       &pwr_info->pa_5g[2], 0, fallback);
 		nvram_read_u16(prefix, postfix, "pa5glw0a",
-			       &pwr_info->pa_5gl[0], 0);
+			       &pwr_info->pa_5gl[0], 0, fallback);
 		nvram_read_u16(prefix, postfix, "pa5glw1a",
-			       &pwr_info->pa_5gl[1], 0);
+			       &pwr_info->pa_5gl[1], 0, fallback);
 		nvram_read_u16(prefix, postfix, "pa5glw2a",
-			       &pwr_info->pa_5gl[2], 0);
+			       &pwr_info->pa_5gl[2], 0, fallback);
 		nvram_read_u16(prefix, postfix, "pa5ghw0a",
-			       &pwr_info->pa_5gh[0], 0);
+			       &pwr_info->pa_5gh[0], 0, fallback);
 		nvram_read_u16(prefix, postfix, "pa5ghw1a",
-			       &pwr_info->pa_5gh[1], 0);
+			       &pwr_info->pa_5gh[1], 0, fallback);
 		nvram_read_u16(prefix, postfix, "pa5ghw2a",
-			       &pwr_info->pa_5gh[2], 0);
+			       &pwr_info->pa_5gh[2], 0, fallback);
 	}
 }
 
 static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
-					const char *prefix)
+					const char *prefix, bool fallback)
 {
 	char postfix[2];
 	int i;
@@ -531,91 +620,112 @@ static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
 		struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
 		snprintf(postfix, sizeof(postfix), "%i", i);
 		nvram_read_u16(prefix, postfix, "pa2gw3a",
-			       &pwr_info->pa_2g[3], 0);
+			       &pwr_info->pa_2g[3], 0, fallback);
 		nvram_read_u16(prefix, postfix, "pa5gw3a",
-			       &pwr_info->pa_5g[3], 0);
+			       &pwr_info->pa_5g[3], 0, fallback);
 		nvram_read_u16(prefix, postfix, "pa5glw3a",
-			       &pwr_info->pa_5gl[3], 0);
+			       &pwr_info->pa_5gl[3], 0, fallback);
 		nvram_read_u16(prefix, postfix, "pa5ghw3a",
-			       &pwr_info->pa_5gh[3], 0);
+			       &pwr_info->pa_5gh[3], 0, fallback);
 	}
 }
 
-void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix)
+static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
+					const char *prefix, bool fallback)
 {
-	nvram_read_macaddr(prefix, "et0macaddr", &sprom->et0mac);
-	nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0);
-	nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0);
-
-	nvram_read_macaddr(prefix, "et1macaddr", &sprom->et1mac);
-	nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0);
-	nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0);
+	nvram_read_macaddr(prefix, "et0macaddr", &sprom->et0mac, fallback);
+	nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0,
+		      fallback);
+
+	nvram_read_macaddr(prefix, "et1macaddr", &sprom->et1mac, fallback);
+	nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0,
+		      fallback);
+
+	nvram_read_macaddr(prefix, "macaddr", &sprom->il0mac, fallback);
+	nvram_read_macaddr(prefix, "il0macaddr", &sprom->il0mac, fallback);
+}
 
-	nvram_read_macaddr(prefix, "macaddr", &sprom->il0mac);
-	nvram_read_macaddr(prefix, "il0macaddr", &sprom->il0mac);
+static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix,
+				    bool fallback)
+{
+	nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "boardnum", &sprom->board_num, 0,
+		       fallback);
+	nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0,
+		       fallback);
+	nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
+			 &sprom->boardflags_hi, fallback);
+	nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo,
+			 &sprom->boardflags2_hi, fallback);
 }
 
-void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
+void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,
+			bool fallback)
 {
-	bcm47xx_fill_sprom_ethernet(sprom, prefix);
+	bcm47xx_fill_sprom_ethernet(sprom, prefix, fallback);
+	bcm47xx_fill_board_data(sprom, prefix, fallback);
 
-	nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0);
+	nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0, fallback);
 
 	switch (sprom->revision) {
 	case 1:
-		bcm47xx_fill_sprom_r1234589(sprom, prefix);
-		bcm47xx_fill_sprom_r12389(sprom, prefix);
-		bcm47xx_fill_sprom_r1(sprom, prefix);
+		bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r1(sprom, prefix, fallback);
 		break;
 	case 2:
-		bcm47xx_fill_sprom_r1234589(sprom, prefix);
-		bcm47xx_fill_sprom_r12389(sprom, prefix);
-		bcm47xx_fill_sprom_r2389(sprom, prefix);
-		bcm47xx_fill_sprom_r2(sprom, prefix);
+		bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r2389(sprom, prefix, fallback);
 		break;
 	case 3:
-		bcm47xx_fill_sprom_r1234589(sprom, prefix);
-		bcm47xx_fill_sprom_r12389(sprom, prefix);
-		bcm47xx_fill_sprom_r2389(sprom, prefix);
-		bcm47xx_fill_sprom_r389(sprom, prefix);
-		bcm47xx_fill_sprom_r3(sprom, prefix);
+		bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r2389(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r389(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r3(sprom, prefix, fallback);
 		break;
 	case 4:
 	case 5:
-		bcm47xx_fill_sprom_r1234589(sprom, prefix);
-		bcm47xx_fill_sprom_r4589(sprom, prefix);
-		bcm47xx_fill_sprom_r458(sprom, prefix);
-		bcm47xx_fill_sprom_r45(sprom, prefix);
-		bcm47xx_fill_sprom_path_r4589(sprom, prefix);
-		bcm47xx_fill_sprom_path_r45(sprom, prefix);
+		bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r4589(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r458(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r45(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_path_r45(sprom, prefix, fallback);
 		break;
 	case 8:
-		bcm47xx_fill_sprom_r1234589(sprom, prefix);
-		bcm47xx_fill_sprom_r12389(sprom, prefix);
-		bcm47xx_fill_sprom_r2389(sprom, prefix);
-		bcm47xx_fill_sprom_r389(sprom, prefix);
-		bcm47xx_fill_sprom_r4589(sprom, prefix);
-		bcm47xx_fill_sprom_r458(sprom, prefix);
-		bcm47xx_fill_sprom_r89(sprom, prefix);
-		bcm47xx_fill_sprom_path_r4589(sprom, prefix);
+		bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r2389(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r389(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r4589(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r458(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r89(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);
 		break;
 	case 9:
-		bcm47xx_fill_sprom_r1234589(sprom, prefix);
-		bcm47xx_fill_sprom_r12389(sprom, prefix);
-		bcm47xx_fill_sprom_r2389(sprom, prefix);
-		bcm47xx_fill_sprom_r389(sprom, prefix);
-		bcm47xx_fill_sprom_r4589(sprom, prefix);
-		bcm47xx_fill_sprom_r89(sprom, prefix);
-		bcm47xx_fill_sprom_r9(sprom, prefix);
-		bcm47xx_fill_sprom_path_r4589(sprom, prefix);
+		bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r2389(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r389(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r4589(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r89(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r9(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);
 		break;
 	default:
 		pr_warn("Unsupported SPROM revision %d detected. Will extract"
 			" v1\n", sprom->revision);
 		sprom->revision = 1;
-		bcm47xx_fill_sprom_r1234589(sprom, prefix);
-		bcm47xx_fill_sprom_r12389(sprom, prefix);
-		bcm47xx_fill_sprom_r1(sprom, prefix);
+		bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r12389(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_r1(sprom, prefix, fallback);
 	}
 }
 
@@ -623,11 +733,12 @@ void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
 void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
 				const char *prefix)
 {
-	nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0);
+	nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0,
+		       true);
 	if (!boardinfo->vendor)
 		boardinfo->vendor = SSB_BOARDVENDOR_BCM;
 
-	nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0);
+	nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0, true);
 }
 #endif
 
@@ -635,10 +746,11 @@ void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
 void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo *boardinfo,
 				 const char *prefix)
 {
-	nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0);
+	nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0,
+		       true);
 	if (!boardinfo->vendor)
 		boardinfo->vendor = SSB_BOARDVENDOR_BCM;
 
-	nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0);
+	nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0, true);
 }
 #endif
diff --git a/arch/mips/bcm47xx/wgt634u.c b/arch/mips/bcm47xx/wgt634u.c
index e9f9ec8..e80d585 100644
--- a/arch/mips/bcm47xx/wgt634u.c
+++ b/arch/mips/bcm47xx/wgt634u.c
@@ -156,10 +156,10 @@ static int __init wgt634u_init(void)
 					    SSB_CHIPCO_IRQ_GPIO);
 		}
 
-		wgt634u_flash_data.width = mcore->flash_buswidth;
-		wgt634u_flash_resource.start = mcore->flash_window;
-		wgt634u_flash_resource.end = mcore->flash_window
-					   + mcore->flash_window_size
+		wgt634u_flash_data.width = mcore->pflash.buswidth;
+		wgt634u_flash_resource.start = mcore->pflash.window;
+		wgt634u_flash_resource.end = mcore->pflash.window
+					   + mcore->pflash.window_size
 					   - 1;
 		return platform_add_devices(wgt634u_devices,
 					    ARRAY_SIZE(wgt634u_devices));
diff --git a/arch/mips/bcm63xx/Makefile b/arch/mips/bcm63xx/Makefile
index 9bbb30a..ac28073 100644
--- a/arch/mips/bcm63xx/Makefile
+++ b/arch/mips/bcm63xx/Makefile
@@ -1,6 +1,7 @@
-obj-y		+= clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
-		   dev-dsp.o dev-enet.o dev-flash.o dev-pcmcia.o dev-rng.o \
-		   dev-spi.o dev-uart.o dev-wdt.o dev-usb-usbd.o
+obj-y		+= clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \
+		   setup.o timer.o dev-dsp.o dev-enet.o dev-flash.o \
+		   dev-pcmcia.o dev-rng.o dev-spi.o dev-uart.o dev-wdt.o \
+		   dev-usb-usbd.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 
 obj-y		+= boards/
diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c
index 1cd4d73..73be9b3 100644
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -18,6 +18,7 @@
 #include <bcm63xx_dev_uart.h>
 #include <bcm63xx_regs.h>
 #include <bcm63xx_io.h>
+#include <bcm63xx_nvram.h>
 #include <bcm63xx_dev_pci.h>
 #include <bcm63xx_dev_enet.h>
 #include <bcm63xx_dev_dsp.h>
@@ -29,8 +30,6 @@
 
 #define PFX	"board_bcm963xx: "
 
-static struct bcm963xx_nvram nvram;
-static unsigned int mac_addr_used;
 static struct board_info board;
 
 /*
@@ -716,50 +715,14 @@ const char *board_get_name(void)
 }
 
 /*
- * register & return a new board mac address
- */
-static int board_get_mac_address(u8 *mac)
-{
-	u8 *oui;
-	int count;
-
-	if (mac_addr_used >= nvram.mac_addr_count) {
-		printk(KERN_ERR PFX "not enough mac address\n");
-		return -ENODEV;
-	}
-
-	memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
-	oui = mac + ETH_ALEN/2 - 1;
-	count = mac_addr_used;
-
-	while (count--) {
-		u8 *p = mac + ETH_ALEN - 1;
-
-		do {
-			(*p)++;
-			if (*p != 0)
-				break;
-			p--;
-		} while (p != oui);
-
-		if (p == oui) {
-			printk(KERN_ERR PFX "unable to fetch mac address\n");
-			return -ENODEV;
-		}
-	}
-
-	mac_addr_used++;
-	return 0;
-}
-
-/*
  * early init callback, read nvram data from flash and checksum it
  */
 void __init board_prom_init(void)
 {
-	unsigned int check_len, i;
-	u8 *boot_addr, *cfe, *p;
+	unsigned int i;
+	u8 *boot_addr, *cfe;
 	char cfe_version[32];
+	char *board_name;
 	u32 val;
 
 	/* read base address of boot chip select (0)
@@ -782,27 +745,15 @@ void __init board_prom_init(void)
 		strcpy(cfe_version, "unknown");
 	printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
 
-	/* extract nvram data */
-	memcpy(&nvram, boot_addr + BCM963XX_NVRAM_OFFSET, sizeof(nvram));
-
-	/* check checksum before using data */
-	if (nvram.version <= 4)
-		check_len = offsetof(struct bcm963xx_nvram, checksum_old);
-	else
-		check_len = sizeof(nvram);
-	val = 0;
-	p = (u8 *)&nvram;
-	while (check_len--)
-		val += *p;
-	if (val) {
+	if (bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET)) {
 		printk(KERN_ERR PFX "invalid nvram checksum\n");
 		return;
 	}
 
+	board_name = bcm63xx_nvram_get_name();
 	/* find board by name */
 	for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) {
-		if (strncmp(nvram.name, bcm963xx_boards[i]->name,
-			    sizeof(nvram.name)))
+		if (strncmp(board_name, bcm963xx_boards[i]->name, 16))
 			continue;
 		/* copy, board desc array is marked initdata */
 		memcpy(&board, bcm963xx_boards[i], sizeof(board));
@@ -812,7 +763,7 @@ void __init board_prom_init(void)
 	/* bail out if board is not found, will complain later */
 	if (!board.name[0]) {
 		char name[17];
-		memcpy(name, nvram.name, 16);
+		memcpy(name, board_name, 16);
 		name[16] = 0;
 		printk(KERN_ERR PFX "unknown bcm963xx board: %s\n",
 		       name);
@@ -890,11 +841,11 @@ int __init board_register_devices(void)
 		bcm63xx_pcmcia_register();
 
 	if (board.has_enet0 &&
-	    !board_get_mac_address(board.enet0.mac_addr))
+	    !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
 		bcm63xx_enet_register(0, &board.enet0);
 
 	if (board.has_enet1 &&
-	    !board_get_mac_address(board.enet1.mac_addr))
+	    !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
 		bcm63xx_enet_register(1, &board.enet1);
 
 	if (board.has_usbd)
@@ -907,7 +858,7 @@ int __init board_register_devices(void)
 	 * do this after registering enet devices
 	 */
 #ifdef CONFIG_SSB_PCIHOST
-	if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
+	if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
 		memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
 		memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
 		if (ssb_arch_register_fallback_sprom(
diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c
index dff79ab..b9e948d 100644
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -14,6 +14,7 @@
 #include <bcm63xx_cpu.h>
 #include <bcm63xx_io.h>
 #include <bcm63xx_regs.h>
+#include <bcm63xx_reset.h>
 #include <bcm63xx_clk.h>
 
 static DEFINE_MUTEX(clocks_mutex);
@@ -124,15 +125,10 @@ static void enetsw_set(struct clk *clk, int enable)
 			CKCTL_6368_SWPKT_USB_EN |
 			CKCTL_6368_SWPKT_SAR_EN, enable);
 	if (enable) {
-		u32 val;
-
 		/* reset switch core afer clock change */
-		val = bcm_perf_readl(PERF_SOFTRESET_6368_REG);
-		val &= ~SOFTRESET_6368_ENETSW_MASK;
-		bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
+		bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
 		msleep(10);
-		val |= SOFTRESET_6368_ENETSW_MASK;
-		bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
+		bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
 		msleep(10);
 	}
 }
@@ -222,15 +218,10 @@ static void xtm_set(struct clk *clk, int enable)
 			CKCTL_6368_SWPKT_SAR_EN, enable);
 
 	if (enable) {
-		u32 val;
-
 		/* reset sar core afer clock change */
-		val = bcm_perf_readl(PERF_SOFTRESET_6368_REG);
-		val &= ~SOFTRESET_6368_SAR_MASK;
-		bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
+		bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
 		mdelay(1);
-		val |= SOFTRESET_6368_SAR_MASK;
-		bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
+		bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
 		mdelay(1);
 	}
 }
@@ -253,6 +244,19 @@ static struct clk clk_ipsec = {
 };
 
 /*
+ * PCIe clock
+ */
+
+static void pcie_set(struct clk *clk, int enable)
+{
+	bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
+}
+
+static struct clk clk_pcie = {
+	.set	= pcie_set,
+};
+
+/*
  * Internal peripheral clock
  */
 static struct clk clk_periph = {
@@ -313,6 +317,8 @@ struct clk *clk_get(struct device *dev, const char *id)
 		return &clk_pcm;
 	if (BCMCPU_IS_6368() && !strcmp(id, "ipsec"))
 		return &clk_ipsec;
+	if (BCMCPU_IS_6328() && !strcmp(id, "pcie"))
+		return &clk_pcie;
 	return ERR_PTR(-ENOENT);
 }
 
diff --git a/arch/mips/bcm63xx/nvram.c b/arch/mips/bcm63xx/nvram.c
new file mode 100644
index 0000000..6206116
--- /dev/null
+++ b/arch/mips/bcm63xx/nvram.c
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
+ * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#define pr_fmt(fmt) "bcm63xx_nvram: " fmt
+
+#include <linux/init.h>
+#include <linux/crc32.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/if_ether.h>
+
+#include <bcm63xx_nvram.h>
+
+/*
+ * nvram structure
+ */
+struct bcm963xx_nvram {
+	u32	version;
+	u8	reserved1[256];
+	u8	name[16];
+	u32	main_tp_number;
+	u32	psi_size;
+	u32	mac_addr_count;
+	u8	mac_addr_base[ETH_ALEN];
+	u8	reserved2[2];
+	u32	checksum_old;
+	u8	reserved3[720];
+	u32	checksum_high;
+};
+
+static struct bcm963xx_nvram nvram;
+static int mac_addr_used;
+
+int __init bcm63xx_nvram_init(void *addr)
+{
+	unsigned int check_len;
+	u32 crc, expected_crc;
+
+	/* extract nvram data */
+	memcpy(&nvram, addr, sizeof(nvram));
+
+	/* check checksum before using data */
+	if (nvram.version <= 4) {
+		check_len = offsetof(struct bcm963xx_nvram, reserved3);
+		expected_crc = nvram.checksum_old;
+		nvram.checksum_old = 0;
+	} else {
+		check_len = sizeof(nvram);
+		expected_crc = nvram.checksum_high;
+		nvram.checksum_high = 0;
+	}
+
+	crc = crc32_le(~0, (u8 *)&nvram, check_len);
+
+	if (crc != expected_crc)
+		return -EINVAL;
+
+	return 0;
+}
+
+u8 *bcm63xx_nvram_get_name(void)
+{
+	return nvram.name;
+}
+EXPORT_SYMBOL(bcm63xx_nvram_get_name);
+
+int bcm63xx_nvram_get_mac_address(u8 *mac)
+{
+	u8 *oui;
+	int count;
+
+	if (mac_addr_used >= nvram.mac_addr_count) {
+		pr_err("not enough mac addresses\n");
+		return -ENODEV;
+	}
+
+	memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
+	oui = mac + ETH_ALEN/2 - 1;
+	count = mac_addr_used;
+
+	while (count--) {
+		u8 *p = mac + ETH_ALEN - 1;
+
+		do {
+			(*p)++;
+			if (*p != 0)
+				break;
+			p--;
+		} while (p != oui);
+
+		if (p == oui) {
+			pr_err("unable to fetch mac address\n");
+			return -ENODEV;
+		}
+	}
+
+	mac_addr_used++;
+	return 0;
+}
+EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
diff --git a/arch/mips/bcm63xx/reset.c b/arch/mips/bcm63xx/reset.c
new file mode 100644
index 0000000..68a31bb
--- /dev/null
+++ b/arch/mips/bcm63xx/reset.c
@@ -0,0 +1,223 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_io.h>
+#include <bcm63xx_regs.h>
+#include <bcm63xx_reset.h>
+
+#define __GEN_RESET_BITS_TABLE(__cpu)					\
+	[BCM63XX_RESET_SPI]		= BCM## __cpu ##_RESET_SPI,	\
+	[BCM63XX_RESET_ENET]		= BCM## __cpu ##_RESET_ENET,	\
+	[BCM63XX_RESET_USBH]		= BCM## __cpu ##_RESET_USBH,	\
+	[BCM63XX_RESET_USBD]		= BCM## __cpu ##_RESET_USBD,	\
+	[BCM63XX_RESET_DSL]		= BCM## __cpu ##_RESET_DSL,	\
+	[BCM63XX_RESET_SAR]		= BCM## __cpu ##_RESET_SAR,	\
+	[BCM63XX_RESET_EPHY]		= BCM## __cpu ##_RESET_EPHY,	\
+	[BCM63XX_RESET_ENETSW]		= BCM## __cpu ##_RESET_ENETSW,	\
+	[BCM63XX_RESET_PCM]		= BCM## __cpu ##_RESET_PCM,	\
+	[BCM63XX_RESET_MPI]		= BCM## __cpu ##_RESET_MPI,	\
+	[BCM63XX_RESET_PCIE]		= BCM## __cpu ##_RESET_PCIE,	\
+	[BCM63XX_RESET_PCIE_EXT]	= BCM## __cpu ##_RESET_PCIE_EXT,
+
+#define BCM6328_RESET_SPI	SOFTRESET_6328_SPI_MASK
+#define BCM6328_RESET_ENET	0
+#define BCM6328_RESET_USBH	SOFTRESET_6328_USBH_MASK
+#define BCM6328_RESET_USBD	SOFTRESET_6328_USBS_MASK
+#define BCM6328_RESET_DSL	0
+#define BCM6328_RESET_SAR	SOFTRESET_6328_SAR_MASK
+#define BCM6328_RESET_EPHY	SOFTRESET_6328_EPHY_MASK
+#define BCM6328_RESET_ENETSW	SOFTRESET_6328_ENETSW_MASK
+#define BCM6328_RESET_PCM	SOFTRESET_6328_PCM_MASK
+#define BCM6328_RESET_MPI	0
+#define BCM6328_RESET_PCIE	\
+				(SOFTRESET_6328_PCIE_MASK |		\
+				 SOFTRESET_6328_PCIE_CORE_MASK |	\
+				 SOFTRESET_6328_PCIE_HARD_MASK)
+#define BCM6328_RESET_PCIE_EXT	SOFTRESET_6328_PCIE_EXT_MASK
+
+#define BCM6338_RESET_SPI	SOFTRESET_6338_SPI_MASK
+#define BCM6338_RESET_ENET	SOFTRESET_6338_ENET_MASK
+#define BCM6338_RESET_USBH	SOFTRESET_6338_USBH_MASK
+#define BCM6338_RESET_USBD	SOFTRESET_6338_USBS_MASK
+#define BCM6338_RESET_DSL	SOFTRESET_6338_ADSL_MASK
+#define BCM6338_RESET_SAR	SOFTRESET_6338_SAR_MASK
+#define BCM6338_RESET_EPHY	0
+#define BCM6338_RESET_ENETSW	0
+#define BCM6338_RESET_PCM	0
+#define BCM6338_RESET_MPI	0
+#define BCM6338_RESET_PCIE	0
+#define BCM6338_RESET_PCIE_EXT	0
+
+#define BCM6348_RESET_SPI	SOFTRESET_6348_SPI_MASK
+#define BCM6348_RESET_ENET	SOFTRESET_6348_ENET_MASK
+#define BCM6348_RESET_USBH	SOFTRESET_6348_USBH_MASK
+#define BCM6348_RESET_USBD	SOFTRESET_6348_USBS_MASK
+#define BCM6348_RESET_DSL	SOFTRESET_6348_ADSL_MASK
+#define BCM6348_RESET_SAR	SOFTRESET_6348_SAR_MASK
+#define BCM6348_RESET_EPHY	0
+#define BCM6348_RESET_ENETSW	0
+#define BCM6348_RESET_PCM	0
+#define BCM6348_RESET_MPI	0
+#define BCM6348_RESET_PCIE	0
+#define BCM6348_RESET_PCIE_EXT	0
+
+#define BCM6358_RESET_SPI	SOFTRESET_6358_SPI_MASK
+#define BCM6358_RESET_ENET	SOFTRESET_6358_ENET_MASK
+#define BCM6358_RESET_USBH	SOFTRESET_6358_USBH_MASK
+#define BCM6358_RESET_USBD	0
+#define BCM6358_RESET_DSL	SOFTRESET_6358_ADSL_MASK
+#define BCM6358_RESET_SAR	SOFTRESET_6358_SAR_MASK
+#define BCM6358_RESET_EPHY	SOFTRESET_6358_EPHY_MASK
+#define BCM6358_RESET_ENETSW	0
+#define BCM6358_RESET_PCM	SOFTRESET_6358_PCM_MASK
+#define BCM6358_RESET_MPI	SOFTRESET_6358_MPI_MASK
+#define BCM6358_RESET_PCIE	0
+#define BCM6358_RESET_PCIE_EXT	0
+
+#define BCM6368_RESET_SPI	SOFTRESET_6368_SPI_MASK
+#define BCM6368_RESET_ENET	0
+#define BCM6368_RESET_USBH	SOFTRESET_6368_USBH_MASK
+#define BCM6368_RESET_USBD	SOFTRESET_6368_USBS_MASK
+#define BCM6368_RESET_DSL	0
+#define BCM6368_RESET_SAR	SOFTRESET_6368_SAR_MASK
+#define BCM6368_RESET_EPHY	SOFTRESET_6368_EPHY_MASK
+#define BCM6368_RESET_ENETSW	0
+#define BCM6368_RESET_PCM	SOFTRESET_6368_PCM_MASK
+#define BCM6368_RESET_MPI	SOFTRESET_6368_MPI_MASK
+#define BCM6368_RESET_PCIE	0
+#define BCM6368_RESET_PCIE_EXT	0
+
+#ifdef BCMCPU_RUNTIME_DETECT
+
+/*
+ * core reset bits
+ */
+static const u32 bcm6328_reset_bits[] = {
+	__GEN_RESET_BITS_TABLE(6328)
+};
+
+static const u32 bcm6338_reset_bits[] = {
+	__GEN_RESET_BITS_TABLE(6338)
+};
+
+static const u32 bcm6348_reset_bits[] = {
+	__GEN_RESET_BITS_TABLE(6348)
+};
+
+static const u32 bcm6358_reset_bits[] = {
+	__GEN_RESET_BITS_TABLE(6358)
+};
+
+static const u32 bcm6368_reset_bits[] = {
+	__GEN_RESET_BITS_TABLE(6368)
+};
+
+const u32 *bcm63xx_reset_bits;
+static int reset_reg;
+
+static int __init bcm63xx_reset_bits_init(void)
+{
+	if (BCMCPU_IS_6328()) {
+		reset_reg = PERF_SOFTRESET_6328_REG;
+		bcm63xx_reset_bits = bcm6328_reset_bits;
+	} else if (BCMCPU_IS_6338()) {
+		reset_reg = PERF_SOFTRESET_REG;
+		bcm63xx_reset_bits = bcm6338_reset_bits;
+	} else if (BCMCPU_IS_6348()) {
+		reset_reg = PERF_SOFTRESET_REG;
+		bcm63xx_reset_bits = bcm6348_reset_bits;
+	} else if (BCMCPU_IS_6358()) {
+		reset_reg = PERF_SOFTRESET_6358_REG;
+		bcm63xx_reset_bits = bcm6358_reset_bits;
+	} else if (BCMCPU_IS_6368()) {
+		reset_reg = PERF_SOFTRESET_6368_REG;
+		bcm63xx_reset_bits = bcm6368_reset_bits;
+	}
+
+	return 0;
+}
+#else
+
+#ifdef CONFIG_BCM63XX_CPU_6328
+static const u32 bcm63xx_reset_bits[] = {
+	__GEN_RESET_BITS_TABLE(6328)
+};
+#define reset_reg PERF_SOFTRESET_6328_REG
+#endif
+
+#ifdef CONFIG_BCM63XX_CPU_6338
+static const u32 bcm63xx_reset_bits[] = {
+	__GEN_RESET_BITS_TABLE(6338)
+};
+#define reset_reg PERF_SOFTRESET_REG
+#endif
+
+#ifdef CONFIG_BCM63XX_CPU_6345
+static const u32 bcm63xx_reset_bits[] = { };
+#define reset_reg 0
+#endif
+
+#ifdef CONFIG_BCM63XX_CPU_6348
+static const u32 bcm63xx_reset_bits[] = {
+	__GEN_RESET_BITS_TABLE(6348)
+};
+#define reset_reg PERF_SOFTRESET_REG
+#endif
+
+#ifdef CONFIG_BCM63XX_CPU_6358
+static const u32 bcm63xx_reset_bits[] = {
+	__GEN_RESET_BITS_TABLE(6358)
+};
+#define reset_reg PERF_SOFTRESET_6358_REG
+#endif
+
+#ifdef CONFIG_BCM63XX_CPU_6368
+static const u32 bcm63xx_reset_bits[] = {
+	__GEN_RESET_BITS_TABLE(6368)
+};
+#define reset_reg PERF_SOFTRESET_6368_REG
+#endif
+
+static int __init bcm63xx_reset_bits_init(void) { return 0; }
+#endif
+
+static DEFINE_SPINLOCK(reset_mutex);
+
+static void __bcm63xx_core_set_reset(u32 mask, int enable)
+{
+	unsigned long flags;
+	u32 val;
+
+	if (!mask)
+		return;
+
+	spin_lock_irqsave(&reset_mutex, flags);
+	val = bcm_perf_readl(reset_reg);
+
+	if (enable)
+		val &= ~mask;
+	else
+		val |= mask;
+
+	bcm_perf_writel(val, reset_reg);
+	spin_unlock_irqrestore(&reset_mutex, flags);
+}
+
+void bcm63xx_core_set_reset(enum bcm63xx_core_reset core, int reset)
+{
+	__bcm63xx_core_set_reset(bcm63xx_reset_bits[core], reset);
+}
+EXPORT_SYMBOL(bcm63xx_core_set_reset);
+
+postcore_initcall(bcm63xx_reset_bits_init);
diff --git a/arch/mips/cavium-octeon/flash_setup.c b/arch/mips/cavium-octeon/flash_setup.c
index e44a55b..237e5b1 100644
--- a/arch/mips/cavium-octeon/flash_setup.c
+++ b/arch/mips/cavium-octeon/flash_setup.c
@@ -51,7 +51,8 @@ static int __init flash_init(void)
 		flash_map.name = "phys_mapped_flash";
 		flash_map.phys = region_cfg.s.base << 16;
 		flash_map.size = 0x1fc00000 - flash_map.phys;
-		flash_map.bankwidth = 1;
+		/* 8-bit bus (0 + 1) or 16-bit bus (1 + 1) */
+		flash_map.bankwidth = region_cfg.s.width + 1;
 		flash_map.virt = ioremap(flash_map.phys, flash_map.size);
 		pr_notice("Bootbus flash: Setting flash for %luMB flash at "
 			  "0x%08llx\n", flash_map.size >> 20, flash_map.phys);
diff --git a/arch/mips/cavium-octeon/octeon-memcpy.S b/arch/mips/cavium-octeon/octeon-memcpy.S
index db478db..0ba0eb9 100644
--- a/arch/mips/cavium-octeon/octeon-memcpy.S
+++ b/arch/mips/cavium-octeon/octeon-memcpy.S
@@ -79,11 +79,6 @@
 /*
  * Only on the 64-bit kernel we can made use of 64-bit registers.
  */
-#ifdef CONFIG_64BIT
-#define USE_DOUBLE
-#endif
-
-#ifdef USE_DOUBLE
 
 #define LOAD   ld
 #define LOADL  ldl
@@ -119,26 +114,6 @@
 #define t6	$14
 #define t7	$15
 
-#else
-
-#define LOAD   lw
-#define LOADL  lwl
-#define LOADR  lwr
-#define STOREL swl
-#define STORER swr
-#define STORE  sw
-#define ADD    addu
-#define SUB    subu
-#define SRL    srl
-#define SLL    sll
-#define SRA    sra
-#define SLLV   sllv
-#define SRLV   srlv
-#define NBYTES 4
-#define LOG_NBYTES 2
-
-#endif /* USE_DOUBLE */
-
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
 #define LDFIRST LOADR
 #define LDREST  LOADL
@@ -395,12 +370,10 @@ EXC(	 sb	t0, N(dst), s_exc_p1)
 
 	COPY_BYTE(0)
 	COPY_BYTE(1)
-#ifdef USE_DOUBLE
 	COPY_BYTE(2)
 	COPY_BYTE(3)
 	COPY_BYTE(4)
 	COPY_BYTE(5)
-#endif
 EXC(	lb	t0, NBYTES-2(src), l_exc)
 	SUB	len, len, 1
 	jr	ra
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index 04dd8ff..67aa3b9 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -4,9 +4,11 @@
  * for more details.
  *
  * Copyright (C) 2004-2007 Cavium Networks
- * Copyright (C) 2008 Wind River Systems
+ * Copyright (C) 2008, 2009 Wind River Systems
+ *   written by Ralf Baechle <ralf@linux-mips.org>
  */
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/console.h>
 #include <linux/delay.h>
 #include <linux/export.h>
@@ -664,20 +666,10 @@ void __init plat_mem_setup(void)
 	cvmx_bootmem_lock();
 	while ((boot_mem_map.nr_map < BOOT_MEM_MAP_MAX)
 		&& (total < MAX_MEMORY)) {
-#if defined(CONFIG_64BIT) || defined(CONFIG_64BIT_PHYS_ADDR)
 		memory = cvmx_bootmem_phy_alloc(mem_alloc_size,
 						__pa_symbol(&__init_end), -1,
 						0x100000,
 						CVMX_BOOTMEM_FLAG_NO_LOCKING);
-#elif defined(CONFIG_HIGHMEM)
-		memory = cvmx_bootmem_phy_alloc(mem_alloc_size, 0, 1ull << 31,
-						0x100000,
-						CVMX_BOOTMEM_FLAG_NO_LOCKING);
-#else
-		memory = cvmx_bootmem_phy_alloc(mem_alloc_size, 0, 512 << 20,
-						0x100000,
-						CVMX_BOOTMEM_FLAG_NO_LOCKING);
-#endif
 		if (memory >= 0) {
 			u64 size = mem_alloc_size;
 
@@ -821,3 +813,29 @@ void __init device_tree_init(void)
 	}
 	unflatten_device_tree();
 }
+
+static char *edac_device_names[] = {
+	"co_l2c_edac",
+	"co_lmc_edac",
+	"co_pc_edac",
+};
+
+static int __init edac_devinit(void)
+{
+	struct platform_device *dev;
+	int i, err = 0;
+	char *name;
+
+	for (i = 0; i < ARRAY_SIZE(edac_device_names); i++) {
+		name = edac_device_names[i];
+		dev = platform_device_register_simple(name, -1, NULL, 0);
+		if (IS_ERR(dev)) {
+			pr_err("Registation of %s failed!\n", name);
+			err = PTR_ERR(dev);
+		}
+	}
+
+	return err;
+}
+
+device_initcall(edac_devinit);
diff --git a/arch/mips/configs/ath79_defconfig b/arch/mips/configs/ath79_defconfig
new file mode 100644
index 0000000..ea87d43
--- /dev/null
+++ b/arch/mips/configs/ath79_defconfig
@@ -0,0 +1,111 @@
+CONFIG_ATH79=y
+CONFIG_ATH79_MACH_AP121=y
+CONFIG_ATH79_MACH_AP81=y
+CONFIG_ATH79_MACH_DB120=y
+CONFIG_ATH79_MACH_PB44=y
+CONFIG_ATH79_MACH_UBNT_XM=y
+CONFIG_HZ_100=y
+# CONFIG_SECCOMP is not set
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_GZIP is not set
+CONFIG_RD_LZMA=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_AIO is not set
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_PCI=y
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
+CONFIG_MAC80211_DEBUGFS=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_MTD=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_M25P80=y
+# CONFIG_M25PXX_USE_FAST_READ is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_PACKET_ENGINE is not set
+CONFIG_ATH_COMMON=m
+CONFIG_ATH9K=m
+CONFIG_ATH9K_AHB=y
+CONFIG_INPUT=m
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO_POLLED=m
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_AR933X=y
+CONFIG_SERIAL_AR933X_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_ATH79=y
+CONFIG_SPI_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_PCF857X=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_ATH79_WDT=y
+# CONFIG_VGA_ARB is not set
+# CONFIG_HID is not set
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_PROC_PAGE_MONITOR is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_FTRACE is not set
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRC_ITU_T=m
diff --git a/arch/mips/configs/bcm47xx_defconfig b/arch/mips/configs/bcm47xx_defconfig
index b6fde2b..4ca8e5c 100644
--- a/arch/mips/configs/bcm47xx_defconfig
+++ b/arch/mips/configs/bcm47xx_defconfig
@@ -473,7 +473,7 @@ CONFIG_USB_GADGET_NET2280=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_MIDI_GADGET=m
 CONFIG_LEDS_CLASS=y
diff --git a/arch/mips/configs/cavium_octeon_defconfig b/arch/mips/configs/cavium_octeon_defconfig
index 75165df..014ba4b 100644
--- a/arch/mips/configs/cavium_octeon_defconfig
+++ b/arch/mips/configs/cavium_octeon_defconfig
@@ -1,7 +1,11 @@
 CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD=y
+CONFIG_CAVIUM_CN63XXP1=y
 CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE=2
 CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_TRANSPARENT_HUGEPAGE=y
 CONFIG_SMP=y
+CONFIG_NR_CPUS=32
+CONFIG_HZ_100=y
 CONFIG_PREEMPT=y
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
@@ -11,16 +15,15 @@ CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
-# CONFIG_PCSPKR_PLATFORM is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
 CONFIG_MIPS32_COMPAT=y
 CONFIG_MIPS32_O32=y
 CONFIG_MIPS32_N32=y
@@ -42,22 +45,68 @@ CONFIG_IP_PIMSM_V1=y
 CONFIG_IP_PIMSM_V2=y
 CONFIG_SYN_COOKIES=y
 # CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
+CONFIG_IPV6=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_OF_PARTS is not set
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_SLRAM=y
+CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
-# CONFIG_MISC_DEVICES is not set
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_PATA_OCTEON_CF=y
+CONFIG_SATA_SIL=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-# CONFIG_NETDEV_10000 is not set
+# 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_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_VENDOR_DEC is not set
+# 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_NET_VENDOR_INTEL is not set
+# 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_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_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_TOSHIBA is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_MARVELL_PHY=y
+CONFIG_BROADCOM_PHY=y
+CONFIG_BCM87XX_PHY=y
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -66,24 +115,39 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_OCTEON=y
+CONFIG_SPI=y
+CONFIG_SPI_OCTEON=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 # CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_STAGING=y
+CONFIG_OCTEON_ETHERNET=y
+# CONFIG_NET_VENDOR_SILICOM is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
-# CONFIG_NETWORK_FILESYSTEMS is not set
-CONFIG_NLS=y
+CONFIG_HUGETLBFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_SCHED_DEBUG is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_EARLY_PRINTK is not set
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 CONFIG_CRYPTO_CBC=y
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index 17a36c1..face9d2 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -233,6 +233,7 @@ CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_EHCI_TT_NEWSCHED=y
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_UHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_NEW_LEDS=y
diff --git a/arch/mips/configs/db1235_defconfig b/arch/mips/configs/db1235_defconfig
index c48998f..14752dd 100644
--- a/arch/mips/configs/db1235_defconfig
+++ b/arch/mips/configs/db1235_defconfig
@@ -346,8 +346,10 @@ CONFIG_USB=y
 CONFIG_USB_DYNAMIC_MINORS=y
 CONFIG_USB_SUSPEND=y
 CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_CLKGATE=y
diff --git a/arch/mips/configs/gpr_defconfig b/arch/mips/configs/gpr_defconfig
index 48a40ae..fb64589 100644
--- a/arch/mips/configs/gpr_defconfig
+++ b/arch/mips/configs/gpr_defconfig
@@ -291,6 +291,7 @@ CONFIG_USB_MON=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_STORAGE=m
 CONFIG_USB_LIBUSUAL=y
 CONFIG_USB_SERIAL=y
diff --git a/arch/mips/configs/ls1b_defconfig b/arch/mips/configs/ls1b_defconfig
index 80cff8b..7eb7554 100644
--- a/arch/mips/configs/ls1b_defconfig
+++ b/arch/mips/configs/ls1b_defconfig
@@ -76,6 +76,7 @@ CONFIG_HID_GENERIC=m
 CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
 CONFIG_USB_STORAGE=m
 CONFIG_USB_SERIAL=m
diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig
index 46c61edc..9fa8f16 100644
--- a/arch/mips/configs/mtx1_defconfig
+++ b/arch/mips/configs/mtx1_defconfig
@@ -581,6 +581,7 @@ CONFIG_USB_MON=m
 CONFIG_USB_EHCI_HCD=m
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_UHCI_HCD=m
 CONFIG_USB_U132_HCD=m
 CONFIG_USB_SL811_HCD=m
@@ -661,7 +662,7 @@ CONFIG_USB_GADGET_NET2280=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_MIDI_GADGET=m
 CONFIG_MMC=m
diff --git a/arch/mips/fw/sni/Makefile b/arch/mips/fw/sni/Makefile
index d9740a3..3f01dd3 100644
--- a/arch/mips/fw/sni/Makefile
+++ b/arch/mips/fw/sni/Makefile
@@ -2,4 +2,4 @@
 # Makefile for the SNI prom monitor routines under Linux.
 #
 
-lib-$(CONFIG_SNIPROM)	+= sniprom.o
+lib-$(CONFIG_FW_SNIPROM)	+= sniprom.o
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 533053d..9b54b7a 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -1 +1,2 @@
 # MIPS headers
+generic-y += trace_clock.h
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 52c4e91..90112ad 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -243,9 +243,9 @@ enum cpu_type_enum {
 	 */
 	CPU_R4000PC, CPU_R4000SC, CPU_R4000MC, CPU_R4200, CPU_R4300, CPU_R4310,
 	CPU_R4400PC, CPU_R4400SC, CPU_R4400MC, CPU_R4600, CPU_R4640, CPU_R4650,
-	CPU_R4700, CPU_R5000, CPU_R5000A, CPU_R5500, CPU_NEVADA, CPU_R5432,
-	CPU_R10000, CPU_R12000, CPU_R14000, CPU_VR41XX, CPU_VR4111, CPU_VR4121,
-	CPU_VR4122, CPU_VR4131, CPU_VR4133, CPU_VR4181, CPU_VR4181A, CPU_RM7000,
+	CPU_R4700, CPU_R5000, CPU_R5500, CPU_NEVADA, CPU_R5432, CPU_R10000,
+	CPU_R12000, CPU_R14000, CPU_VR41XX, CPU_VR4111, CPU_VR4121, CPU_VR4122,
+	CPU_VR4131, CPU_VR4133, CPU_VR4181, CPU_VR4181A, CPU_RM7000,
 	CPU_SR71000, CPU_RM9000, CPU_TX49XX,
 
 	/*
diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h
index be39a12..006b43e 100644
--- a/arch/mips/include/asm/dma-mapping.h
+++ b/arch/mips/include/asm/dma-mapping.h
@@ -40,6 +40,8 @@ static inline int dma_supported(struct device *dev, u64 mask)
 static inline int dma_mapping_error(struct device *dev, u64 mask)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
+
+	debug_dma_mapping_error(dev, mask);
 	return ops->mapping_error(dev, mask);
 }
 
diff --git a/arch/mips/include/asm/fw/arc/types.h b/arch/mips/include/asm/fw/arc/types.h
index b9adcd6..2b11f87 100644
--- a/arch/mips/include/asm/fw/arc/types.h
+++ b/arch/mips/include/asm/fw/arc/types.h
@@ -10,7 +10,7 @@
 #define _ASM_ARC_TYPES_H
 
 
-#ifdef CONFIG_ARC32
+#ifdef CONFIG_FW_ARC32
 
 typedef char		CHAR;
 typedef short		SHORT;
@@ -33,9 +33,9 @@ typedef LONG		_PUSHORT;
 typedef LONG		_PULONG;
 typedef LONG		_PVOID;
 
-#endif /* CONFIG_ARC32 */
+#endif /* CONFIG_FW_ARC32 */
 
-#ifdef CONFIG_ARC64
+#ifdef CONFIG_FW_ARC64
 
 typedef char		CHAR;
 typedef short		SHORT;
@@ -57,7 +57,7 @@ typedef USHORT		*_PUSHORT;
 typedef ULONG		*_PULONG;
 typedef VOID		*_PVOID;
 
-#endif /* CONFIG_ARC64  */
+#endif /* CONFIG_FW_ARC64  */
 
 typedef CHAR		*PCHAR;
 typedef SHORT		*PSHORT;
diff --git a/arch/mips/include/asm/kexec.h b/arch/mips/include/asm/kexec.h
index 4314892..ee25ebb 100644
--- a/arch/mips/include/asm/kexec.h
+++ b/arch/mips/include/asm/kexec.h
@@ -9,22 +9,43 @@
 #ifndef _MIPS_KEXEC
 # define _MIPS_KEXEC
 
+#include <asm/stacktrace.h>
+
 /* Maximum physical address we can use pages from */
 #define KEXEC_SOURCE_MEMORY_LIMIT (0x20000000)
 /* Maximum address we can reach in physical address mode */
 #define KEXEC_DESTINATION_MEMORY_LIMIT (0x20000000)
  /* Maximum address we can use for the control code buffer */
 #define KEXEC_CONTROL_MEMORY_LIMIT (0x20000000)
-
-#define KEXEC_CONTROL_PAGE_SIZE 4096
+/* Reserve 3*4096 bytes for board-specific info */
+#define KEXEC_CONTROL_PAGE_SIZE (4096 + 3*4096)
 
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_MIPS
+#define MAX_NOTE_BYTES 1024
 
 static inline void crash_setup_regs(struct pt_regs *newregs,
 				    struct pt_regs *oldregs)
 {
-	/* Dummy implementation for now */
+	if (oldregs)
+		memcpy(newregs, oldregs, sizeof(*newregs));
+	else
+		prepare_frametrace(newregs);
 }
 
+#ifdef CONFIG_KEXEC
+struct kimage;
+extern unsigned long kexec_args[4];
+extern int (*_machine_kexec_prepare)(struct kimage *);
+extern void (*_machine_kexec_shutdown)(void);
+extern void (*_machine_crash_shutdown)(struct pt_regs *regs);
+extern void default_machine_crash_shutdown(struct pt_regs *regs);
+#ifdef CONFIG_SMP
+extern const unsigned char kexec_smp_wait[];
+extern unsigned long secondary_kexec_args[4];
+extern void (*relocated_kexec_smp_wait) (void *);
+extern atomic_t kexec_ready_to_reboot;
+#endif
+#endif
+
 #endif /* !_MIPS_KEXEC */
diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
index 26fdaf4..cc7563b 100644
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
@@ -44,8 +44,8 @@ union bcm47xx_bus {
 extern union bcm47xx_bus bcm47xx_bus;
 extern enum bcm47xx_bus_type bcm47xx_bus_type;
 
-void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix);
-void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix);
+void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,
+			bool fallback);
 
 #ifdef CONFIG_BCM47XX_SSB
 void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
diff --git a/arch/mips/include/asm/mach-bcm47xx/gpio.h b/arch/mips/include/asm/mach-bcm47xx/gpio.h
index 2ef17e8..90daefa 100644
--- a/arch/mips/include/asm/mach-bcm47xx/gpio.h
+++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h
@@ -1,155 +1,17 @@
-/*
- * 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.
- *
- * Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
- */
+#ifndef __ASM_MIPS_MACH_BCM47XX_GPIO_H
+#define __ASM_MIPS_MACH_BCM47XX_GPIO_H
 
-#ifndef __BCM47XX_GPIO_H
-#define __BCM47XX_GPIO_H
+#include <asm-generic/gpio.h>
 
-#include <linux/ssb/ssb_embedded.h>
-#include <linux/bcma/bcma.h>
-#include <asm/mach-bcm47xx/bcm47xx.h>
+#define gpio_get_value __gpio_get_value
+#define gpio_set_value __gpio_set_value
 
-#define BCM47XX_EXTIF_GPIO_LINES	5
-#define BCM47XX_CHIPCO_GPIO_LINES	16
+#define gpio_cansleep __gpio_cansleep
+#define gpio_to_irq __gpio_to_irq
 
-extern int gpio_request(unsigned gpio, const char *label);
-extern void gpio_free(unsigned gpio);
-extern int gpio_to_irq(unsigned gpio);
-
-static inline int gpio_get_value(unsigned gpio)
+static inline int irq_to_gpio(unsigned int irq)
 {
-	switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-	case BCM47XX_BUS_TYPE_SSB:
-		return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio);
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-	case BCM47XX_BUS_TYPE_BCMA:
-		return bcma_chipco_gpio_in(&bcm47xx_bus.bcma.bus.drv_cc,
-					   1 << gpio);
-#endif
-	}
 	return -EINVAL;
 }
 
-#define gpio_get_value_cansleep	gpio_get_value
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-	case BCM47XX_BUS_TYPE_SSB:
-		ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
-			     value ? 1 << gpio : 0);
-		return;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-	case BCM47XX_BUS_TYPE_BCMA:
-		bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
-				     value ? 1 << gpio : 0);
-		return;
 #endif
-	}
-}
-
-#define gpio_set_value_cansleep gpio_set_value
-
-static inline int gpio_cansleep(unsigned gpio)
-{
-	return 0;
-}
-
-static inline int gpio_is_valid(unsigned gpio)
-{
-	return gpio < (BCM47XX_EXTIF_GPIO_LINES + BCM47XX_CHIPCO_GPIO_LINES);
-}
-
-
-static inline int gpio_direction_input(unsigned gpio)
-{
-	switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-	case BCM47XX_BUS_TYPE_SSB:
-		ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0);
-		return 0;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-	case BCM47XX_BUS_TYPE_BCMA:
-		bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
-				       0);
-		return 0;
-#endif
-	}
-	return -EINVAL;
-}
-
-static inline int gpio_direction_output(unsigned gpio, int value)
-{
-	switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-	case BCM47XX_BUS_TYPE_SSB:
-		/* first set the gpio out value */
-		ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio,
-			     value ? 1 << gpio : 0);
-		/* then set the gpio mode */
-		ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio);
-		return 0;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-	case BCM47XX_BUS_TYPE_BCMA:
-		/* first set the gpio out value */
-		bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
-				     value ? 1 << gpio : 0);
-		/* then set the gpio mode */
-		bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio,
-				       1 << gpio);
-		return 0;
-#endif
-	}
-	return -EINVAL;
-}
-
-static inline int gpio_intmask(unsigned gpio, int value)
-{
-	switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-	case BCM47XX_BUS_TYPE_SSB:
-		ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio,
-				 value ? 1 << gpio : 0);
-		return 0;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-	case BCM47XX_BUS_TYPE_BCMA:
-		bcma_chipco_gpio_intmask(&bcm47xx_bus.bcma.bus.drv_cc,
-					 1 << gpio, value ? 1 << gpio : 0);
-		return 0;
-#endif
-	}
-	return -EINVAL;
-}
-
-static inline int gpio_polarity(unsigned gpio, int value)
-{
-	switch (bcm47xx_bus_type) {
-#ifdef CONFIG_BCM47XX_SSB
-	case BCM47XX_BUS_TYPE_SSB:
-		ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio,
-				  value ? 1 << gpio : 0);
-		return 0;
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-	case BCM47XX_BUS_TYPE_BCMA:
-		bcma_chipco_gpio_polarity(&bcm47xx_bus.bcma.bus.drv_cc,
-					  1 << gpio, value ? 1 << gpio : 0);
-		return 0;
-#endif
-	}
-	return -EINVAL;
-}
-
-
-#endif /* __BCM47XX_GPIO_H */
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
new file mode 100644
index 0000000..62d6a3b
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
@@ -0,0 +1,35 @@
+#ifndef BCM63XX_NVRAM_H
+#define BCM63XX_NVRAM_H
+
+#include <linux/types.h>
+
+/**
+ * bcm63xx_nvram_init() - initializes nvram
+ * @nvram:	address of the nvram data
+ *
+ * Initialized the local nvram copy from the target address and checks
+ * its checksum.
+ *
+ * Returns 0 on success.
+ */
+int __init bcm63xx_nvram_init(void *nvram);
+
+/**
+ * bcm63xx_nvram_get_name() - returns the board name according to nvram
+ *
+ * Returns the board name field from nvram. Note that it might not be
+ * null terminated if it is exactly 16 bytes long.
+ */
+u8 *bcm63xx_nvram_get_name(void);
+
+/**
+ * bcm63xx_nvram_get_mac_address() - register & return a new mac address
+ * @mac:	pointer to array for allocated mac
+ *
+ * Registers and returns a mac address from the allocated macs from nvram.
+ *
+ * Returns 0 on success.
+ */
+int bcm63xx_nvram_get_mac_address(u8 *mac);
+
+#endif /* BCM63XX_NVRAM_H */
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
index 12963d0..c3eeb90 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -53,13 +53,18 @@
 					CKCTL_6338_SAR_EN |		\
 					CKCTL_6338_SPI_EN)
 
-#define CKCTL_6345_CPU_EN		(1 << 0)
-#define CKCTL_6345_BUS_EN		(1 << 1)
-#define CKCTL_6345_EBI_EN		(1 << 2)
-#define CKCTL_6345_UART_EN		(1 << 3)
-#define CKCTL_6345_ADSLPHY_EN		(1 << 4)
-#define CKCTL_6345_ENET_EN		(1 << 7)
-#define CKCTL_6345_USBH_EN		(1 << 8)
+/* BCM6345 clock bits are shifted by 16 on the left, because of the test
+ * control register which is 16-bits wide. That way we do not have any
+ * specific BCM6345 code for handling clocks, and writing 0 to the test
+ * control register is fine.
+ */
+#define CKCTL_6345_CPU_EN		(1 << 16)
+#define CKCTL_6345_BUS_EN		(1 << 17)
+#define CKCTL_6345_EBI_EN		(1 << 18)
+#define CKCTL_6345_UART_EN		(1 << 19)
+#define CKCTL_6345_ADSLPHY_EN		(1 << 20)
+#define CKCTL_6345_ENET_EN		(1 << 23)
+#define CKCTL_6345_USBH_EN		(1 << 24)
 
 #define CKCTL_6345_ALL_SAFE_EN		(CKCTL_6345_ENET_EN |	\
 					CKCTL_6345_USBH_EN |	\
@@ -191,6 +196,7 @@
 /* Soft Reset register */
 #define PERF_SOFTRESET_REG		0x28
 #define PERF_SOFTRESET_6328_REG		0x10
+#define PERF_SOFTRESET_6358_REG		0x34
 #define PERF_SOFTRESET_6368_REG		0x10
 
 #define SOFTRESET_6328_SPI_MASK		(1 << 0)
@@ -244,6 +250,15 @@
 				  SOFTRESET_6348_ACLC_MASK |		\
 				  SOFTRESET_6348_ADSLMIPSPLL_MASK)
 
+#define SOFTRESET_6358_SPI_MASK		(1 << 0)
+#define SOFTRESET_6358_ENET_MASK	(1 << 2)
+#define SOFTRESET_6358_MPI_MASK		(1 << 3)
+#define SOFTRESET_6358_EPHY_MASK	(1 << 6)
+#define SOFTRESET_6358_SAR_MASK		(1 << 7)
+#define SOFTRESET_6358_USBH_MASK	(1 << 12)
+#define SOFTRESET_6358_PCM_MASK		(1 << 13)
+#define SOFTRESET_6358_ADSL_MASK	(1 << 14)
+
 #define SOFTRESET_6368_SPI_MASK		(1 << 0)
 #define SOFTRESET_6368_MPI_MASK		(1 << 3)
 #define SOFTRESET_6368_EPHY_MASK	(1 << 6)
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h
new file mode 100644
index 0000000..3a6eb9c
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h
@@ -0,0 +1,21 @@
+#ifndef __BCM63XX_RESET_H
+#define __BCM63XX_RESET_H
+
+enum bcm63xx_core_reset {
+	BCM63XX_RESET_SPI,
+	BCM63XX_RESET_ENET,
+	BCM63XX_RESET_USBH,
+	BCM63XX_RESET_USBD,
+	BCM63XX_RESET_SAR,
+	BCM63XX_RESET_DSL,
+	BCM63XX_RESET_EPHY,
+	BCM63XX_RESET_ENETSW,
+	BCM63XX_RESET_PCM,
+	BCM63XX_RESET_MPI,
+	BCM63XX_RESET_PCIE,
+	BCM63XX_RESET_PCIE_EXT,
+};
+
+void bcm63xx_core_set_reset(enum bcm63xx_core_reset, int reset);
+
+#endif
diff --git a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
index b0dd4bb..682bcf3 100644
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
@@ -15,23 +15,6 @@
 #define BCM963XX_NVRAM_OFFSET		0x580
 
 /*
- * nvram structure
- */
-struct bcm963xx_nvram {
-	u32	version;
-	u8	reserved1[256];
-	u8	name[16];
-	u32	main_tp_number;
-	u32	psi_size;
-	u32	mac_addr_count;
-	u8	mac_addr_base[6];
-	u8	reserved2[2];
-	u32	checksum_old;
-	u8	reserved3[720];
-	u32	checksum_high;
-};
-
-/*
  * board definition
  */
 struct board_info {
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
index 6a2df70..133336b 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -82,6 +82,9 @@ extern __iomem void *ltq_cgu_membase;
 #define LTQ_MPS_BASE_ADDR	(KSEG1 + 0x1F107000)
 #define LTQ_MPS_CHIPID		((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344))
 
+/* allow booting xrx200 phys */
+int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr);
+
 /* request a non-gpio and set the PIO config */
 #define PMU_PPE			 BIT(13)
 extern void ltq_pmu_enable(unsigned int module);
diff --git a/arch/mips/include/asm/mach-loongson1/platform.h b/arch/mips/include/asm/mach-loongson1/platform.h
index 2f17161..718a122 100644
--- a/arch/mips/include/asm/mach-loongson1/platform.h
+++ b/arch/mips/include/asm/mach-loongson1/platform.h
@@ -18,6 +18,7 @@ extern struct platform_device ls1x_eth0_device;
 extern struct platform_device ls1x_ehci_device;
 extern struct platform_device ls1x_rtc_device;
 
-void ls1x_serial_setup(void);
+extern void __init ls1x_clk_init(void);
+extern void __init ls1x_serial_setup(struct platform_device *pdev);
 
 #endif /* __ASM_MACH_LOONGSON1_PLATFORM_H */
diff --git a/arch/mips/include/asm/mach-loongson1/regs-clk.h b/arch/mips/include/asm/mach-loongson1/regs-clk.h
index 8efa7fb..a81fa3d 100644
--- a/arch/mips/include/asm/mach-loongson1/regs-clk.h
+++ b/arch/mips/include/asm/mach-loongson1/regs-clk.h
@@ -20,14 +20,15 @@
 
 /* Clock PLL Divisor Register Bits */
 #define DIV_DC_EN			(0x1 << 31)
-#define DIV_DC				(0x1f << 26)
 #define DIV_CPU_EN			(0x1 << 25)
-#define DIV_CPU				(0x1f << 20)
 #define DIV_DDR_EN			(0x1 << 19)
-#define DIV_DDR				(0x1f << 14)
 
 #define DIV_DC_SHIFT			26
 #define DIV_CPU_SHIFT			20
 #define DIV_DDR_SHIFT			14
 
+#define DIV_DC_WIDTH			5
+#define DIV_CPU_WIDTH			5
+#define DIV_DDR_WIDTH			5
+
 #endif /* __ASM_MACH_LOONGSON1_REGS_CLK_H */
diff --git a/arch/mips/include/asm/mach-netlogic/irq.h b/arch/mips/include/asm/mach-netlogic/irq.h
index b590245..868ed8a 100644
--- a/arch/mips/include/asm/mach-netlogic/irq.h
+++ b/arch/mips/include/asm/mach-netlogic/irq.h
@@ -8,7 +8,9 @@
 #ifndef __ASM_NETLOGIC_IRQ_H
 #define __ASM_NETLOGIC_IRQ_H
 
-#define NR_IRQS			64
+#include <asm/mach-netlogic/multi-node.h>
+#define NR_IRQS			(64 * NLM_NR_NODES)
+
 #define MIPS_CPU_IRQ_BASE	0
 
 #endif /* __ASM_NETLOGIC_IRQ_H */
diff --git a/arch/mips/include/asm/mach-netlogic/multi-node.h b/arch/mips/include/asm/mach-netlogic/multi-node.h
new file mode 100644
index 0000000..d62fc77
--- /dev/null
+++ b/arch/mips/include/asm/mach-netlogic/multi-node.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``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 BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NETLOGIC_MULTI_NODE_H_
+#define _NETLOGIC_MULTI_NODE_H_
+
+#ifndef CONFIG_NLM_MULTINODE
+#define NLM_NR_NODES		1
+#else
+#if defined(CONFIG_NLM_MULTINODE_2)
+#define NLM_NR_NODES		2
+#elif defined(CONFIG_NLM_MULTINODE_4)
+#define NLM_NR_NODES		4
+#else
+#define NLM_NR_NODES		1
+#endif
+#endif
+
+#define NLM_CORES_PER_NODE	8
+#define NLM_THREADS_PER_CORE	4
+#define NLM_CPUS_PER_NODE	(NLM_CORES_PER_NODE * NLM_THREADS_PER_CORE)
+
+#endif
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index eb74289..881b980 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -240,7 +240,7 @@
 #define PM_HUGE_MASK	PM_64M
 #elif defined(CONFIG_PAGE_SIZE_64KB)
 #define PM_HUGE_MASK	PM_256M
-#elif defined(CONFIG_HUGETLB_PAGE)
+#elif defined(CONFIG_MIPS_HUGE_TLB_SUPPORT)
 #error Bad page size configuration for hugetlbfs!
 #endif
 
diff --git a/arch/mips/include/asm/netlogic/common.h b/arch/mips/include/asm/netlogic/common.h
index fdd2f44..42bfd5f 100644
--- a/arch/mips/include/asm/netlogic/common.h
+++ b/arch/mips/include/asm/netlogic/common.h
@@ -45,15 +45,19 @@
 #define	BOOT_NMI_HANDLER	8
 
 #ifndef __ASSEMBLY__
+#include <linux/cpumask.h>
+#include <linux/spinlock.h>
+#include <asm/irq.h>
+#include <asm/mach-netlogic/multi-node.h>
+
 struct irq_desc;
-extern struct plat_smp_ops nlm_smp_ops;
-extern char nlm_reset_entry[], nlm_reset_entry_end[];
 void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc);
 void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc);
-void nlm_smp_irq_init(void);
+void nlm_smp_irq_init(int hwcpuid);
 void nlm_boot_secondary_cpus(void);
-int nlm_wakeup_secondary_cpus(u32 wakeup_mask);
+int nlm_wakeup_secondary_cpus(void);
 void nlm_rmiboot_preboot(void);
+void nlm_percpu_init(int hwcpuid);
 
 static inline void
 nlm_set_nmi_handler(void *handler)
@@ -68,9 +72,42 @@ nlm_set_nmi_handler(void *handler)
  * Misc.
  */
 unsigned int nlm_get_cpu_frequency(void);
+void nlm_node_init(int node);
+extern struct plat_smp_ops nlm_smp_ops;
+extern char nlm_reset_entry[], nlm_reset_entry_end[];
+
+extern unsigned int nlm_threads_per_core;
+extern cpumask_t nlm_cpumask;
+
+struct nlm_soc_info {
+	unsigned long coremask;	/* cores enabled on the soc */
+	unsigned long ebase;
+	uint64_t irqmask;
+	uint64_t sysbase;	/* only for XLP */
+	uint64_t picbase;
+	spinlock_t piclock;
+};
+
+#define	nlm_get_node(i)		(&nlm_nodes[i])
+#ifdef CONFIG_CPU_XLR
+#define	nlm_current_node()	(&nlm_nodes[0])
+#else
+#define nlm_current_node()	(&nlm_nodes[nlm_nodeid()])
+#endif
+
+struct irq_data;
+uint64_t nlm_pci_irqmask(int node);
+void nlm_set_pic_extra_ack(int node, int irq,  void (*xack)(struct irq_data *));
+
+/*
+ * The NR_IRQs is divided between nodes, each of them has a separate irq space
+ */
+static inline int nlm_irq_to_xirq(int node, int irq)
+{
+	return node * NR_IRQS / NLM_NR_NODES + irq;
+}
 
-extern unsigned long nlm_common_ebase;
-extern int nlm_threads_per_core;
-extern uint32_t nlm_cpumask, nlm_coremask;
+extern struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
+extern int nlm_cpu_ready[];
 #endif
 #endif /* _NETLOGIC_COMMON_H_ */
diff --git a/arch/mips/include/asm/netlogic/interrupt.h b/arch/mips/include/asm/netlogic/interrupt.h
index a85aadb..ed5993d 100644
--- a/arch/mips/include/asm/netlogic/interrupt.h
+++ b/arch/mips/include/asm/netlogic/interrupt.h
@@ -39,7 +39,7 @@
 
 #define IRQ_IPI_SMP_FUNCTION	3
 #define IRQ_IPI_SMP_RESCHEDULE	4
-#define IRQ_MSGRING		6
+#define IRQ_FMN			5
 #define IRQ_TIMER		7
 
 #endif
diff --git a/arch/mips/include/asm/netlogic/mips-extns.h b/arch/mips/include/asm/netlogic/mips-extns.h
index 8c53d0b..32ba6d9 100644
--- a/arch/mips/include/asm/netlogic/mips-extns.h
+++ b/arch/mips/include/asm/netlogic/mips-extns.h
@@ -73,4 +73,146 @@ static inline int hard_smp_processor_id(void)
 	return __read_32bit_c0_register($15, 1) & 0x3ff;
 }
 
+static inline int nlm_nodeid(void)
+{
+	return (__read_32bit_c0_register($15, 1) >> 5) & 0x3;
+}
+
+static inline unsigned int nlm_core_id(void)
+{
+	return (read_c0_ebase() & 0x1c) >> 2;
+}
+
+static inline unsigned int nlm_thread_id(void)
+{
+	return read_c0_ebase() & 0x3;
+}
+
+#define __read_64bit_c2_split(source, sel)				\
+({									\
+	unsigned long long __val;					\
+	unsigned long __flags;						\
+									\
+	local_irq_save(__flags);					\
+	if (sel == 0)							\
+		__asm__ __volatile__(					\
+			".set\tmips64\n\t"				\
+			"dmfc2\t%M0, " #source "\n\t"			\
+			"dsll\t%L0, %M0, 32\n\t"			\
+			"dsra\t%M0, %M0, 32\n\t"			\
+			"dsra\t%L0, %L0, 32\n\t"			\
+			".set\tmips0\n\t"				\
+			: "=r" (__val));				\
+	else								\
+		__asm__ __volatile__(					\
+			".set\tmips64\n\t"				\
+			"dmfc2\t%M0, " #source ", " #sel "\n\t"		\
+			"dsll\t%L0, %M0, 32\n\t"			\
+			"dsra\t%M0, %M0, 32\n\t"			\
+			"dsra\t%L0, %L0, 32\n\t"			\
+			".set\tmips0\n\t"				\
+			: "=r" (__val));				\
+	local_irq_restore(__flags);					\
+									\
+	__val;								\
+})
+
+#define __write_64bit_c2_split(source, sel, val)			\
+do {									\
+	unsigned long __flags;						\
+									\
+	local_irq_save(__flags);					\
+	if (sel == 0)							\
+		__asm__ __volatile__(					\
+			".set\tmips64\n\t"				\
+			"dsll\t%L0, %L0, 32\n\t"			\
+			"dsrl\t%L0, %L0, 32\n\t"			\
+			"dsll\t%M0, %M0, 32\n\t"			\
+			"or\t%L0, %L0, %M0\n\t"				\
+			"dmtc2\t%L0, " #source "\n\t"			\
+			".set\tmips0\n\t"				\
+			: : "r" (val));					\
+	else								\
+		__asm__ __volatile__(					\
+			".set\tmips64\n\t"				\
+			"dsll\t%L0, %L0, 32\n\t"			\
+			"dsrl\t%L0, %L0, 32\n\t"			\
+			"dsll\t%M0, %M0, 32\n\t"			\
+			"or\t%L0, %L0, %M0\n\t"				\
+			"dmtc2\t%L0, " #source ", " #sel "\n\t"		\
+			".set\tmips0\n\t"				\
+			: : "r" (val));					\
+	local_irq_restore(__flags);					\
+} while (0)
+
+#define __read_32bit_c2_register(source, sel)				\
+({ uint32_t __res;							\
+	if (sel == 0)							\
+		__asm__ __volatile__(					\
+			".set\tmips32\n\t"				\
+			"mfc2\t%0, " #source "\n\t"			\
+			".set\tmips0\n\t"				\
+			: "=r" (__res));				\
+	else								\
+		__asm__ __volatile__(					\
+			".set\tmips32\n\t"				\
+			"mfc2\t%0, " #source ", " #sel "\n\t"		\
+			".set\tmips0\n\t"				\
+			: "=r" (__res));				\
+	__res;								\
+})
+
+#define __read_64bit_c2_register(source, sel)				\
+({ unsigned long long __res;						\
+	if (sizeof(unsigned long) == 4)					\
+		__res = __read_64bit_c2_split(source, sel);		\
+	else if (sel == 0)						\
+		__asm__ __volatile__(					\
+			".set\tmips64\n\t"				\
+			"dmfc2\t%0, " #source "\n\t"			\
+			".set\tmips0\n\t"				\
+			: "=r" (__res));				\
+	else								\
+		__asm__ __volatile__(					\
+			".set\tmips64\n\t"				\
+			"dmfc2\t%0, " #source ", " #sel "\n\t"		\
+			".set\tmips0\n\t"				\
+			: "=r" (__res));				\
+	__res;								\
+})
+
+#define __write_64bit_c2_register(register, sel, value)			\
+do {									\
+	if (sizeof(unsigned long) == 4)					\
+		__write_64bit_c2_split(register, sel, value);		\
+	else if (sel == 0)						\
+		__asm__ __volatile__(					\
+			".set\tmips64\n\t"				\
+			"dmtc2\t%z0, " #register "\n\t"			\
+			".set\tmips0\n\t"				\
+			: : "Jr" (value));				\
+	else								\
+		__asm__ __volatile__(					\
+			".set\tmips64\n\t"				\
+			"dmtc2\t%z0, " #register ", " #sel "\n\t"	\
+			".set\tmips0\n\t"				\
+			: : "Jr" (value));				\
+} while (0)
+
+#define __write_32bit_c2_register(reg, sel, value)			\
+({									\
+	if (sel == 0)							\
+		__asm__ __volatile__(					\
+			".set\tmips32\n\t"				\
+			"mtc2\t%z0, " #reg "\n\t"			\
+			".set\tmips0\n\t"				\
+			: : "Jr" (value));				\
+	else								\
+		__asm__ __volatile__(                                   \
+			".set\tmips32\n\t"				\
+			"mtc2\t%z0, " #reg ", " #sel "\n\t"		\
+			".set\tmips0\n\t"				\
+			: : "Jr" (value));				\
+})
+
 #endif /*_ASM_NLM_MIPS_EXTS_H */
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h
index ad8b802..b2e53a5 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h
@@ -273,36 +273,16 @@ nlm_pic_read_irt(uint64_t base, int irt_index)
 	return nlm_read_pic_reg(base, PIC_IRT(irt_index));
 }
 
-static inline uint64_t
-nlm_pic_read_control(uint64_t base)
-{
-	return nlm_read_pic_reg(base, PIC_CTRL);
-}
-
-static inline void
-nlm_pic_write_control(uint64_t base, uint64_t control)
-{
-	nlm_write_pic_reg(base, PIC_CTRL, control);
-}
-
-static inline void
-nlm_pic_update_control(uint64_t base, uint64_t control)
-{
-	uint64_t val;
-
-	val = nlm_read_pic_reg(base, PIC_CTRL);
-	nlm_write_pic_reg(base, PIC_CTRL, control | val);
-}
-
 static inline void
 nlm_set_irt_to_cpu(uint64_t base, int irt, int cpu)
 {
 	uint64_t val;
 
 	val = nlm_read_pic_reg(base, PIC_IRT(irt));
-	val |= cpu & 0xf;
-	if (cpu > 15)
-		val |= 1 << 16;
+	/* clear cpuset and mask */
+	val &= ~((0x7ull << 16) | 0xffff);
+	/* set DB, cpuset and cpumask */
+	val |= (1 << 19) | ((cpu >> 4) << 16) | (1 << (cpu & 0xf));
 	nlm_write_pic_reg(base, PIC_IRT(irt), val);
 }
 
@@ -369,7 +349,7 @@ nlm_pic_enable_irt(uint64_t base, int irt)
 static inline void
 nlm_pic_disable_irt(uint64_t base, int irt)
 {
-	uint32_t reg;
+	uint64_t reg;
 
 	reg = nlm_read_pic_reg(base, PIC_IRT(irt));
 	nlm_write_pic_reg(base, PIC_IRT(irt), reg & ~((uint64_t)1 << 31));
@@ -379,15 +359,9 @@ static inline void
 nlm_pic_send_ipi(uint64_t base, int hwt, int irq, int nmi)
 {
 	uint64_t ipi;
-	int	node, ncpu;
-
-	node = hwt / 32;
-	ncpu = hwt & 0x1f;
-	ipi = ((uint64_t)nmi << 31) | (irq << 20) | (node << 17) |
-		(1 << (ncpu & 0xf));
-	if (ncpu > 15)
-		ipi |= 0x10000; /* Setting bit 16 to select cpus 16-31 */
 
+	ipi = (nmi << 31) | (irq << 20);
+	ipi |= ((hwt >> 4) << 16) | (1 << (hwt & 0xf)); /* cpuset and mask */
 	nlm_write_pic_reg(base, PIC_IPI_CTL, ipi);
 }
 
@@ -404,12 +378,10 @@ nlm_pic_ack(uint64_t base, int irt_num)
 static inline void
 nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt)
 {
-	nlm_pic_write_irt_direct(base, irt, 0, 0, 0, irq, 0);
+	nlm_pic_write_irt_direct(base, irt, 0, 0, 0, irq, hwt);
 }
 
-extern uint64_t nlm_pic_base;
 int nlm_irq_to_irt(int irq);
-int nlm_irt_to_irq(int irt);
 
 #endif /* __ASSEMBLY__ */
 #endif /* _NLM_HAL_PIC_H */
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/sys.h b/arch/mips/include/asm/netlogic/xlp-hal/sys.h
index 21432f7..258e8cc 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/sys.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/sys.h
@@ -124,6 +124,5 @@
 #define	nlm_get_sys_pcibase(node) nlm_pcicfg_base(XLP_IO_SYS_OFFSET(node))
 #define	nlm_get_sys_regbase(node) (nlm_get_sys_pcibase(node) + XLP_IO_PCI_HDRSZ)
 
-extern uint64_t nlm_sys_base;
 #endif
 #endif
diff --git a/arch/mips/include/asm/netlogic/xlr/fmn.h b/arch/mips/include/asm/netlogic/xlr/fmn.h
new file mode 100644
index 0000000..68d5167
--- /dev/null
+++ b/arch/mips/include/asm/netlogic/xlr/fmn.h
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``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 BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NLM_FMN_H_
+#define _NLM_FMN_H_
+
+#include <asm/netlogic/mips-extns.h> /* for COP2 access */
+
+/* Station IDs */
+#define	FMN_STNID_CPU0			0x00
+#define	FMN_STNID_CPU1			0x08
+#define	FMN_STNID_CPU2			0x10
+#define	FMN_STNID_CPU3			0x18
+#define	FMN_STNID_CPU4			0x20
+#define	FMN_STNID_CPU5			0x28
+#define	FMN_STNID_CPU6			0x30
+#define	FMN_STNID_CPU7			0x38
+
+#define	FMN_STNID_XGS0_TX		64
+#define	FMN_STNID_XMAC0_00_TX		64
+#define	FMN_STNID_XMAC0_01_TX		65
+#define	FMN_STNID_XMAC0_02_TX		66
+#define	FMN_STNID_XMAC0_03_TX		67
+#define	FMN_STNID_XMAC0_04_TX		68
+#define	FMN_STNID_XMAC0_05_TX		69
+#define	FMN_STNID_XMAC0_06_TX		70
+#define	FMN_STNID_XMAC0_07_TX		71
+#define	FMN_STNID_XMAC0_08_TX		72
+#define	FMN_STNID_XMAC0_09_TX		73
+#define	FMN_STNID_XMAC0_10_TX		74
+#define	FMN_STNID_XMAC0_11_TX		75
+#define	FMN_STNID_XMAC0_12_TX		76
+#define	FMN_STNID_XMAC0_13_TX		77
+#define	FMN_STNID_XMAC0_14_TX		78
+#define	FMN_STNID_XMAC0_15_TX		79
+
+#define	FMN_STNID_XGS1_TX		80
+#define	FMN_STNID_XMAC1_00_TX		80
+#define	FMN_STNID_XMAC1_01_TX		81
+#define	FMN_STNID_XMAC1_02_TX		82
+#define	FMN_STNID_XMAC1_03_TX		83
+#define	FMN_STNID_XMAC1_04_TX		84
+#define	FMN_STNID_XMAC1_05_TX		85
+#define	FMN_STNID_XMAC1_06_TX		86
+#define	FMN_STNID_XMAC1_07_TX		87
+#define	FMN_STNID_XMAC1_08_TX		88
+#define	FMN_STNID_XMAC1_09_TX		89
+#define	FMN_STNID_XMAC1_10_TX		90
+#define	FMN_STNID_XMAC1_11_TX		91
+#define	FMN_STNID_XMAC1_12_TX		92
+#define	FMN_STNID_XMAC1_13_TX		93
+#define	FMN_STNID_XMAC1_14_TX		94
+#define	FMN_STNID_XMAC1_15_TX		95
+
+#define	FMN_STNID_GMAC			96
+#define	FMN_STNID_GMACJFR_0		96
+#define	FMN_STNID_GMACRFR_0		97
+#define	FMN_STNID_GMACTX0		98
+#define	FMN_STNID_GMACTX1		99
+#define	FMN_STNID_GMACTX2		100
+#define	FMN_STNID_GMACTX3		101
+#define	FMN_STNID_GMACJFR_1		102
+#define	FMN_STNID_GMACRFR_1		103
+
+#define	FMN_STNID_DMA			104
+#define	FMN_STNID_DMA_0			104
+#define	FMN_STNID_DMA_1			105
+#define	FMN_STNID_DMA_2			106
+#define	FMN_STNID_DMA_3			107
+
+#define	FMN_STNID_XGS0FR		112
+#define	FMN_STNID_XMAC0JFR		112
+#define	FMN_STNID_XMAC0RFR		113
+
+#define	FMN_STNID_XGS1FR		114
+#define	FMN_STNID_XMAC1JFR		114
+#define	FMN_STNID_XMAC1RFR		115
+#define	FMN_STNID_SEC			120
+#define	FMN_STNID_SEC0			120
+#define	FMN_STNID_SEC1			121
+#define	FMN_STNID_SEC2			122
+#define	FMN_STNID_SEC3			123
+#define	FMN_STNID_PK0			124
+#define	FMN_STNID_SEC_RSA		124
+#define	FMN_STNID_SEC_RSVD0		125
+#define	FMN_STNID_SEC_RSVD1		126
+#define	FMN_STNID_SEC_RSVD2		127
+
+#define	FMN_STNID_GMAC1			80
+#define	FMN_STNID_GMAC1_FR_0		81
+#define	FMN_STNID_GMAC1_TX0		82
+#define	FMN_STNID_GMAC1_TX1		83
+#define	FMN_STNID_GMAC1_TX2		84
+#define	FMN_STNID_GMAC1_TX3		85
+#define	FMN_STNID_GMAC1_FR_1		87
+#define	FMN_STNID_GMAC0			96
+#define	FMN_STNID_GMAC0_FR_0		97
+#define	FMN_STNID_GMAC0_TX0		98
+#define	FMN_STNID_GMAC0_TX1		99
+#define	FMN_STNID_GMAC0_TX2		100
+#define	FMN_STNID_GMAC0_TX3		101
+#define	FMN_STNID_GMAC0_FR_1		103
+#define	FMN_STNID_CMP_0			108
+#define	FMN_STNID_CMP_1			109
+#define	FMN_STNID_CMP_2			110
+#define	FMN_STNID_CMP_3			111
+#define	FMN_STNID_PCIE_0		116
+#define	FMN_STNID_PCIE_1		117
+#define	FMN_STNID_PCIE_2		118
+#define	FMN_STNID_PCIE_3		119
+#define	FMN_STNID_XLS_PK0		121
+
+#define nlm_read_c2_cc0(s)		__read_32bit_c2_register($16, s)
+#define nlm_read_c2_cc1(s)		__read_32bit_c2_register($17, s)
+#define nlm_read_c2_cc2(s)		__read_32bit_c2_register($18, s)
+#define nlm_read_c2_cc3(s)		__read_32bit_c2_register($19, s)
+#define nlm_read_c2_cc4(s)		__read_32bit_c2_register($20, s)
+#define nlm_read_c2_cc5(s)		__read_32bit_c2_register($21, s)
+#define nlm_read_c2_cc6(s)		__read_32bit_c2_register($22, s)
+#define nlm_read_c2_cc7(s)		__read_32bit_c2_register($23, s)
+#define nlm_read_c2_cc8(s)		__read_32bit_c2_register($24, s)
+#define nlm_read_c2_cc9(s)		__read_32bit_c2_register($25, s)
+#define nlm_read_c2_cc10(s)		__read_32bit_c2_register($26, s)
+#define nlm_read_c2_cc11(s)		__read_32bit_c2_register($27, s)
+#define nlm_read_c2_cc12(s)		__read_32bit_c2_register($28, s)
+#define nlm_read_c2_cc13(s)		__read_32bit_c2_register($29, s)
+#define nlm_read_c2_cc14(s)		__read_32bit_c2_register($30, s)
+#define nlm_read_c2_cc15(s)		__read_32bit_c2_register($31, s)
+
+#define nlm_write_c2_cc0(s, v)		__write_32bit_c2_register($16, s, v)
+#define nlm_write_c2_cc1(s, v)		__write_32bit_c2_register($17, s, v)
+#define nlm_write_c2_cc2(s, v)		__write_32bit_c2_register($18, s, v)
+#define nlm_write_c2_cc3(s, v)		__write_32bit_c2_register($19, s, v)
+#define nlm_write_c2_cc4(s, v)		__write_32bit_c2_register($20, s, v)
+#define nlm_write_c2_cc5(s, v)		__write_32bit_c2_register($21, s, v)
+#define nlm_write_c2_cc6(s, v)		__write_32bit_c2_register($22, s, v)
+#define nlm_write_c2_cc7(s, v)		__write_32bit_c2_register($23, s, v)
+#define nlm_write_c2_cc8(s, v)		__write_32bit_c2_register($24, s, v)
+#define nlm_write_c2_cc9(s, v)		__write_32bit_c2_register($25, s, v)
+#define nlm_write_c2_cc10(s, v)		__write_32bit_c2_register($26, s, v)
+#define nlm_write_c2_cc11(s, v)		__write_32bit_c2_register($27, s, v)
+#define nlm_write_c2_cc12(s, v)		__write_32bit_c2_register($28, s, v)
+#define nlm_write_c2_cc13(s, v)		__write_32bit_c2_register($29, s, v)
+#define nlm_write_c2_cc14(s, v)		__write_32bit_c2_register($30, s, v)
+#define nlm_write_c2_cc15(s, v)		__write_32bit_c2_register($31, s, v)
+
+#define	nlm_read_c2_status(sel)		__read_32bit_c2_register($2, 0)
+#define	nlm_read_c2_config()		__read_32bit_c2_register($3, 0)
+#define	nlm_write_c2_config(v)		__write_32bit_c2_register($3, 0, v)
+#define	nlm_read_c2_bucksize(b)		__read_32bit_c2_register($4, b)
+#define	nlm_write_c2_bucksize(b, v)	__write_32bit_c2_register($4, b, v)
+
+#define	nlm_read_c2_rx_msg0()		__read_64bit_c2_register($1, 0)
+#define	nlm_read_c2_rx_msg1()		__read_64bit_c2_register($1, 1)
+#define	nlm_read_c2_rx_msg2()		__read_64bit_c2_register($1, 2)
+#define	nlm_read_c2_rx_msg3()		__read_64bit_c2_register($1, 3)
+
+#define	nlm_write_c2_tx_msg0(v)		__write_64bit_c2_register($0, 0, v)
+#define	nlm_write_c2_tx_msg1(v)		__write_64bit_c2_register($0, 1, v)
+#define	nlm_write_c2_tx_msg2(v)		__write_64bit_c2_register($0, 2, v)
+#define	nlm_write_c2_tx_msg3(v)		__write_64bit_c2_register($0, 3, v)
+
+#define	FMN_STN_RX_QSIZE		256
+#define	FMN_NSTATIONS			128
+#define	FMN_CORE_NBUCKETS		8
+
+static inline void nlm_msgsnd(unsigned int stid)
+{
+	__asm__ volatile (
+	    ".set	push\n"
+	    ".set	noreorder\n"
+	    ".set	noat\n"
+	    "move	$1, %0\n"
+	    "c2		0x10001\n"	/* msgsnd $1 */
+	    ".set	pop\n"
+	    : : "r" (stid) : "$1"
+	);
+}
+
+static inline void nlm_msgld(unsigned int pri)
+{
+	__asm__ volatile (
+	    ".set	push\n"
+	    ".set	noreorder\n"
+	    ".set	noat\n"
+	    "move	$1, %0\n"
+	    "c2		0x10002\n"    /* msgld $1 */
+	    ".set	pop\n"
+	    : : "r" (pri) : "$1"
+	);
+}
+
+static inline void nlm_msgwait(unsigned int mask)
+{
+	__asm__ volatile (
+	    ".set	push\n"
+	    ".set	noreorder\n"
+	    ".set	noat\n"
+	    "move	$8, %0\n"
+	    "c2		0x10003\n"    /* msgwait $1 */
+	    ".set	pop\n"
+	    : : "r" (mask) : "$1"
+	);
+}
+
+/*
+ * Disable interrupts and enable COP2 access
+ */
+static inline uint32_t nlm_cop2_enable(void)
+{
+	uint32_t sr = read_c0_status();
+
+	write_c0_status((sr & ~ST0_IE) | ST0_CU2);
+	return sr;
+}
+
+static inline void nlm_cop2_restore(uint32_t sr)
+{
+	write_c0_status(sr);
+}
+
+static inline void nlm_fmn_setup_intr(int irq, unsigned int tmask)
+{
+	uint32_t config;
+
+	config = (1 << 24)	/* interrupt water mark - 1 msg */
+		| (irq << 16)	/* irq */
+		| (tmask << 8)	/* thread mask */
+		| 0x2;		/* enable watermark intr, disable empty intr */
+	nlm_write_c2_config(config);
+}
+
+struct nlm_fmn_msg {
+	uint64_t msg0;
+	uint64_t msg1;
+	uint64_t msg2;
+	uint64_t msg3;
+};
+
+static inline int nlm_fmn_send(unsigned int size, unsigned int code,
+		unsigned int stid, struct nlm_fmn_msg *msg)
+{
+	unsigned int dest;
+	uint32_t status;
+	int i;
+
+	/*
+	 * Make sure that all the writes pending at the cpu are flushed.
+	 * Any writes pending on CPU will not be see by devices. L1/L2
+	 * caches are coherent with IO, so no cache flush needed.
+	 */
+	__asm __volatile("sync");
+
+	/* Load TX message buffers */
+	nlm_write_c2_tx_msg0(msg->msg0);
+	nlm_write_c2_tx_msg1(msg->msg1);
+	nlm_write_c2_tx_msg2(msg->msg2);
+	nlm_write_c2_tx_msg3(msg->msg3);
+	dest = ((size - 1) << 16) | (code << 8) | stid;
+
+	/*
+	 * Retry a few times on credit fail, this should be a
+	 * transient condition, unless there is a configuration
+	 * failure, or the receiver is stuck.
+	 */
+	for (i = 0; i < 8; i++) {
+		nlm_msgsnd(dest);
+		status = nlm_read_c2_status(0);
+		if ((status & 0x2) == 1)
+			pr_info("Send pending fail!\n");
+		if ((status & 0x4) == 0)
+			return 0;
+	}
+
+	/* If there is a credit failure, return error */
+	return status & 0x06;
+}
+
+static inline int nlm_fmn_receive(int bucket, int *size, int *code, int *stid,
+		struct nlm_fmn_msg *msg)
+{
+	uint32_t status, tmp;
+
+	nlm_msgld(bucket);
+
+	/* wait for load pending to clear */
+	do {
+		status = nlm_read_c2_status(1);
+	} while ((status & 0x08) != 0);
+
+	/* receive error bits */
+	tmp = status & 0x30;
+	if (tmp != 0)
+		return tmp;
+
+	*size = ((status & 0xc0) >> 6) + 1;
+	*code = (status & 0xff00) >> 8;
+	*stid = (status & 0x7f0000) >> 16;
+	msg->msg0 = nlm_read_c2_rx_msg0();
+	msg->msg1 = nlm_read_c2_rx_msg1();
+	msg->msg2 = nlm_read_c2_rx_msg2();
+	msg->msg3 = nlm_read_c2_rx_msg3();
+
+	return 0;
+}
+
+struct xlr_fmn_info {
+	int num_buckets;
+	int start_stn_id;
+	int end_stn_id;
+	int credit_config[128];
+};
+
+struct xlr_board_fmn_config {
+	int bucket_size[128];		/* size of buckets for all stations */
+	struct xlr_fmn_info cpu[8];
+	struct xlr_fmn_info gmac[2];
+	struct xlr_fmn_info dma;
+	struct xlr_fmn_info cmp;
+	struct xlr_fmn_info sae;
+	struct xlr_fmn_info xgmac[2];
+};
+
+extern int nlm_register_fmn_handler(int start, int end,
+	void (*fn)(int, int, int, int, struct nlm_fmn_msg *, void *),
+	void *arg);
+extern void xlr_percpu_fmn_init(void);
+extern void nlm_setup_fmn_irq(void);
+extern void xlr_board_info_setup(void);
+
+extern struct xlr_board_fmn_config xlr_board_fmn_config;
+#endif
diff --git a/arch/mips/include/asm/netlogic/xlr/pic.h b/arch/mips/include/asm/netlogic/xlr/pic.h
index 868013e..9a691b1 100644
--- a/arch/mips/include/asm/netlogic/xlr/pic.h
+++ b/arch/mips/include/asm/netlogic/xlr/pic.h
@@ -258,7 +258,5 @@ nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt)
 	nlm_write_reg(base, PIC_IRT_1(irt),
 		(1 << 30) | (1 << 6) | irq);
 }
-
-extern uint64_t nlm_pic_base;
 #endif
 #endif /* _ASM_NLM_XLR_PIC_H */
diff --git a/arch/mips/include/asm/netlogic/xlr/xlr.h b/arch/mips/include/asm/netlogic/xlr/xlr.h
index ff4a17b..c1667e0 100644
--- a/arch/mips/include/asm/netlogic/xlr/xlr.h
+++ b/arch/mips/include/asm/netlogic/xlr/xlr.h
@@ -51,10 +51,8 @@ static inline unsigned int nlm_chip_is_xls_b(void)
 	return ((prid & 0xf000) == 0x4000);
 }
 
-/*
- *  XLR chip types
- */
- /* The XLS product line has chip versions 0x[48c]? */
+/*  XLR chip types */
+/* The XLS product line has chip versions 0x[48c]? */
 static inline unsigned int nlm_chip_is_xls(void)
 {
 	uint32_t prid = read_c0_prid();
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index da9bd7d..31ab10f 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -31,19 +31,19 @@
 #define PAGE_SHIFT	16
 #endif
 #define PAGE_SIZE	(_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK       (~((1 << PAGE_SHIFT) - 1))
+#define PAGE_MASK       (~(PAGE_SIZE - 1))
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 #define HPAGE_SHIFT	(PAGE_SHIFT + PAGE_SHIFT - 3)
 #define HPAGE_SIZE	(_AC(1,UL) << HPAGE_SHIFT)
 #define HPAGE_MASK	(~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
-#else /* !CONFIG_HUGETLB_PAGE */
+#else /* !CONFIG_MIPS_HUGE_TLB_SUPPORT */
 #define HPAGE_SHIFT	({BUILD_BUG(); 0; })
 #define HPAGE_SIZE	({BUILD_BUG(); 0; })
 #define HPAGE_MASK	({BUILD_BUG(); 0; })
 #define HUGETLB_PAGE_ORDER	({BUILD_BUG(); 0; })
-#endif /* CONFIG_HUGETLB_PAGE */
+#endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */
 
 #ifndef __ASSEMBLY__
 
diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h
index f5b521d..c631910 100644
--- a/arch/mips/include/asm/pgtable-64.h
+++ b/arch/mips/include/asm/pgtable-64.h
@@ -175,7 +175,7 @@ static inline int pmd_none(pmd_t pmd)
 
 static inline int pmd_bad(pmd_t pmd)
 {
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 	/* pmd_huge(pmd) but inline */
 	if (unlikely(pmd_val(pmd) & _PAGE_HUGE))
 		return 0;
diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h
index da4ba49..260c098 100644
--- a/arch/mips/include/asm/pgtable-bits.h
+++ b/arch/mips/include/asm/pgtable-bits.h
@@ -94,7 +94,7 @@
 /* set:pagecache unset:swap */
 #define _PAGE_FILE		(_PAGE_MODIFIED)
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 /* huge tlb page */
 #define _PAGE_HUGE_SHIFT	(_PAGE_MODIFIED_SHIFT + 1)
 #define _PAGE_HUGE		(1 << _PAGE_HUGE_SHIFT)
@@ -103,8 +103,17 @@
 #define _PAGE_HUGE		({BUG(); 1; })  /* Dummy value */
 #endif
 
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
+/* huge tlb page */
+#define _PAGE_SPLITTING_SHIFT	(_PAGE_HUGE_SHIFT + 1)
+#define _PAGE_SPLITTING		(1 << _PAGE_SPLITTING_SHIFT)
+#else
+#define _PAGE_SPLITTING_SHIFT	(_PAGE_HUGE_SHIFT)
+#define _PAGE_SPLITTING		({BUG(); 1; })  /* Dummy value */
+#endif
+
 /* Page cannot be executed */
-#define _PAGE_NO_EXEC_SHIFT	(cpu_has_rixi ? _PAGE_HUGE_SHIFT + 1 : _PAGE_HUGE_SHIFT)
+#define _PAGE_NO_EXEC_SHIFT	(cpu_has_rixi ? _PAGE_SPLITTING_SHIFT + 1 : _PAGE_SPLITTING_SHIFT)
 #define _PAGE_NO_EXEC		({BUG_ON(!cpu_has_rixi); 1 << _PAGE_NO_EXEC_SHIFT; })
 
 /* Page cannot be read */
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index c02158b..252202d 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -8,6 +8,7 @@
 #ifndef _ASM_PGTABLE_H
 #define _ASM_PGTABLE_H
 
+#include <linux/mmzone.h>
 #ifdef CONFIG_32BIT
 #include <asm/pgtable-32.h>
 #endif
@@ -94,7 +95,12 @@ extern void paging_init(void);
  * and a page entry and page directory to the page they refer to.
  */
 #define pmd_phys(pmd)		virt_to_phys((void *)pmd_val(pmd))
-#define pmd_page(pmd)		(pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
+
+#define __pmd_page(pmd)		(pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
+#ifndef CONFIG_TRANSPARENT_HUGEPAGE
+#define pmd_page(pmd)		__pmd_page(pmd)
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE  */
+
 #define pmd_page_vaddr(pmd)	pmd_val(pmd)
 
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
@@ -107,7 +113,6 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
 	ptep->pte_high = pte.pte_high;
 	smp_wmb();
 	ptep->pte_low = pte.pte_low;
-	//printk("pte_high %x pte_low %x\n", ptep->pte_high, ptep->pte_low);
 
 	if (pte.pte_low & _PAGE_GLOBAL) {
 		pte_t *buddy = ptep_buddy(ptep);
@@ -375,6 +380,14 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
 	__update_cache(vma, address, pte);
 }
 
+static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
+	unsigned long address, pmd_t *pmdp)
+{
+	pte_t pte = *(pte_t *)pmdp;
+
+	__update_tlb(vma, address, pte);
+}
+
 #define kern_addr_valid(addr)	(1)
 
 #ifdef CONFIG_64BIT_PHYS_ADDR
@@ -394,6 +407,157 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 #endif
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+extern int has_transparent_hugepage(void);
+
+static inline int pmd_trans_huge(pmd_t pmd)
+{
+	return !!(pmd_val(pmd) & _PAGE_HUGE);
+}
+
+static inline pmd_t pmd_mkhuge(pmd_t pmd)
+{
+	pmd_val(pmd) |= _PAGE_HUGE;
+
+	return pmd;
+}
+
+static inline int pmd_trans_splitting(pmd_t pmd)
+{
+	return !!(pmd_val(pmd) & _PAGE_SPLITTING);
+}
+
+static inline pmd_t pmd_mksplitting(pmd_t pmd)
+{
+	pmd_val(pmd) |= _PAGE_SPLITTING;
+
+	return pmd;
+}
+
+extern void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+		       pmd_t *pmdp, pmd_t pmd);
+
+#define __HAVE_ARCH_PMDP_SPLITTING_FLUSH
+/* Extern to avoid header file madness */
+extern void pmdp_splitting_flush(struct vm_area_struct *vma,
+					unsigned long address,
+					pmd_t *pmdp);
+
+#define __HAVE_ARCH_PMD_WRITE
+static inline int pmd_write(pmd_t pmd)
+{
+	return !!(pmd_val(pmd) & _PAGE_WRITE);
+}
+
+static inline pmd_t pmd_wrprotect(pmd_t pmd)
+{
+	pmd_val(pmd) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
+	return pmd;
+}
+
+static inline pmd_t pmd_mkwrite(pmd_t pmd)
+{
+	pmd_val(pmd) |= _PAGE_WRITE;
+	if (pmd_val(pmd) & _PAGE_MODIFIED)
+		pmd_val(pmd) |= _PAGE_SILENT_WRITE;
+
+	return pmd;
+}
+
+static inline int pmd_dirty(pmd_t pmd)
+{
+	return !!(pmd_val(pmd) & _PAGE_MODIFIED);
+}
+
+static inline pmd_t pmd_mkclean(pmd_t pmd)
+{
+	pmd_val(pmd) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE);
+	return pmd;
+}
+
+static inline pmd_t pmd_mkdirty(pmd_t pmd)
+{
+	pmd_val(pmd) |= _PAGE_MODIFIED;
+	if (pmd_val(pmd) & _PAGE_WRITE)
+		pmd_val(pmd) |= _PAGE_SILENT_WRITE;
+
+	return pmd;
+}
+
+static inline int pmd_young(pmd_t pmd)
+{
+	return !!(pmd_val(pmd) & _PAGE_ACCESSED);
+}
+
+static inline pmd_t pmd_mkold(pmd_t pmd)
+{
+	pmd_val(pmd) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ);
+
+	return pmd;
+}
+
+static inline pmd_t pmd_mkyoung(pmd_t pmd)
+{
+	pmd_val(pmd) |= _PAGE_ACCESSED;
+
+	if (cpu_has_rixi) {
+		if (!(pmd_val(pmd) & _PAGE_NO_READ))
+			pmd_val(pmd) |= _PAGE_SILENT_READ;
+	} else {
+		if (pmd_val(pmd) & _PAGE_READ)
+			pmd_val(pmd) |= _PAGE_SILENT_READ;
+	}
+
+	return pmd;
+}
+
+/* Extern to avoid header file madness */
+extern pmd_t mk_pmd(struct page *page, pgprot_t prot);
+
+static inline unsigned long pmd_pfn(pmd_t pmd)
+{
+	return pmd_val(pmd) >> _PFN_SHIFT;
+}
+
+static inline struct page *pmd_page(pmd_t pmd)
+{
+	if (pmd_trans_huge(pmd))
+		return pfn_to_page(pmd_pfn(pmd));
+
+	return pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT);
+}
+
+static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
+{
+	pmd_val(pmd) = (pmd_val(pmd) & _PAGE_CHG_MASK) | pgprot_val(newprot);
+	return pmd;
+}
+
+static inline pmd_t pmd_mknotpresent(pmd_t pmd)
+{
+	pmd_val(pmd) &= ~(_PAGE_PRESENT | _PAGE_VALID | _PAGE_DIRTY);
+
+	return pmd;
+}
+
+/*
+ * The generic version pmdp_get_and_clear uses a version of pmd_clear() with a
+ * different prototype.
+ */
+#define __HAVE_ARCH_PMDP_GET_AND_CLEAR
+static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
+				       unsigned long address, pmd_t *pmdp)
+{
+	pmd_t old = *pmdp;
+
+	pmd_clear(pmdp);
+
+	return old;
+}
+
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+
 #include <asm-generic/pgtable.h>
 
 /*
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 5e33fab..bd98b50 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -226,8 +226,6 @@ struct thread_struct {
 	unsigned long cp0_badvaddr;	/* Last user fault */
 	unsigned long cp0_baduaddr;	/* Last kernel fault accessing USEG */
 	unsigned long error_code;
-	unsigned long irix_trampoline;  /* Wheee... */
-	unsigned long irix_oldctx;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
     struct octeon_cop2_state cp2 __attribute__ ((__aligned__(128)));
     struct octeon_cvmseg_state cvmseg __attribute__ ((__aligned__(128)));
@@ -297,8 +295,6 @@ struct thread_struct {
 	.cp0_badvaddr		= 0,				\
 	.cp0_baduaddr		= 0,				\
 	.error_code		= 0,				\
-	.irix_trampoline	= 0,				\
-	.irix_oldctx		= 0,				\
 	/*							\
 	 * Cavium Octeon specifics (null if not Octeon)		\
 	 */							\
@@ -310,8 +306,6 @@ struct task_struct;
 /* Free all resources held by a thread. */
 #define release_thread(thread) do { } while(0)
 
-extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 extern unsigned long thread_saved_pc(struct task_struct *tsk);
 
 /*
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index 4f5da94..cec5e12 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -61,4 +61,10 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs)
 		die(str, regs);
 }
 
+#define current_pt_regs()						\
+({									\
+	unsigned long sp = (unsigned long)__builtin_frame_address(0);	\
+	(struct pt_regs *)((sp | (THREAD_SIZE - 1)) + 1 - 32) - 1;	\
+})
+
 #endif /* _ASM_PTRACE_H */
diff --git a/arch/mips/include/asm/sgiarcs.h b/arch/mips/include/asm/sgiarcs.h
index 1493429..3dce7c7 100644
--- a/arch/mips/include/asm/sgiarcs.h
+++ b/arch/mips/include/asm/sgiarcs.h
@@ -366,7 +366,7 @@ struct linux_smonblock {
  * Macros for calling a 32-bit ARC implementation from 64-bit code
  */
 
-#if defined(CONFIG_64BIT) && defined(CONFIG_ARC32)
+#if defined(CONFIG_64BIT) && defined(CONFIG_FW_ARC32)
 
 #define __arc_clobbers							\
 	"$2", "$3" /* ... */, "$8", "$9", "$10", "$11", 			\
@@ -475,10 +475,10 @@ struct linux_smonblock {
 	__res;								\
 })
 
-#endif /* defined(CONFIG_64BIT) && defined(CONFIG_ARC32) */
+#endif /* defined(CONFIG_64BIT) && defined(CONFIG_FW_ARC32) */
 
-#if (defined(CONFIG_32BIT) && defined(CONFIG_ARC32)) ||		\
-    (defined(CONFIG_64BIT) && defined(CONFIG_ARC64))
+#if (defined(CONFIG_32BIT) && defined(CONFIG_FW_ARC32)) ||		\
+    (defined(CONFIG_64BIT) && defined(CONFIG_FW_ARC64))
 
 #define ARC_CALL0(dest)							\
 ({	long __res;							\
diff --git a/arch/mips/include/asm/signal.h b/arch/mips/include/asm/signal.h
index 880240d..cf4a080 100644
--- a/arch/mips/include/asm/signal.h
+++ b/arch/mips/include/asm/signal.h
@@ -21,6 +21,4 @@
 #include <asm/sigcontext.h>
 #include <asm/siginfo.h>
 
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
 #endif /* _ASM_SIGNAL_H */
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index d4fb4d8..f1578f9 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -40,6 +40,8 @@ extern int __cpu_logical_map[NR_CPUS];
 #define SMP_CALL_FUNCTION	0x2
 /* Octeon - Tell another core to flush its icache */
 #define SMP_ICACHE_FLUSH	0x4
+/* Used by kexec crashdump to save all cpu's state */
+#define SMP_DUMP		0x8
 
 extern volatile cpumask_t cpu_callin_map;
 
@@ -91,4 +93,9 @@ static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
 	mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION);
 }
 
+extern void core_send_ipi(int cpu, unsigned int action);
+#if defined(CONFIG_KEXEC)
+extern void (*dump_ipi_function_ptr)(void *);
+void dump_send_ipi(void (*dump_ipi_callback)(void *));
+#endif
 #endif /* __ASM_SMP_H */
diff --git a/arch/mips/include/asm/sparsemem.h b/arch/mips/include/asm/sparsemem.h
index 4461198..65900da 100644
--- a/arch/mips/include/asm/sparsemem.h
+++ b/arch/mips/include/asm/sparsemem.h
@@ -6,7 +6,7 @@
  * SECTION_SIZE_BITS		2^N: how big each section will be
  * MAX_PHYSMEM_BITS		2^N: how much memory we can have in that space
  */
-#if defined(CONFIG_HUGETLB_PAGE) && defined(CONFIG_PAGE_SIZE_64KB)
+#if defined(CONFIG_MIPS_HUGE_TLB_SUPPORT) && defined(CONFIG_PAGE_SIZE_64KB)
 # define SECTION_SIZE_BITS	29
 #else
 # define SECTION_SIZE_BITS	28
diff --git a/arch/mips/include/asm/tlbdebug.h b/arch/mips/include/asm/tlbdebug.h
index bb8f5c2..8957146 100644
--- a/arch/mips/include/asm/tlbdebug.h
+++ b/arch/mips/include/asm/tlbdebug.h
@@ -12,5 +12,6 @@
  * TLB debugging functions:
  */
 extern void dump_tlb_all(void);
+extern void dump_current_addr(unsigned long addr);
 
 #endif /* __ASM_TLBDEBUG_H */
diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h
index 9e47cc1..b306e20 100644
--- a/arch/mips/include/asm/unistd.h
+++ b/arch/mips/include/asm/unistd.h
@@ -20,6 +20,7 @@
 #define __ARCH_OMIT_COMPAT_SYS_GETDENTS64
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_ALARM
+#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_GETHOSTNAME
 #define __ARCH_WANT_SYS_IPC
 #define __ARCH_WANT_SYS_PAUSE
diff --git a/arch/mips/include/uapi/asm/ioctls.h b/arch/mips/include/uapi/asm/ioctls.h
index 92403c3..addd56b 100644
--- a/arch/mips/include/uapi/asm/ioctls.h
+++ b/arch/mips/include/uapi/asm/ioctls.h
@@ -86,6 +86,9 @@
 #define TIOCGDEV	_IOR('T', 0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T', 0x36, int)  /* Generate signal on Pty slave */
 #define TIOCVHANGUP	0x5437
+#define TIOCGPKT	_IOR('T', 0x38, int) /* Get packet mode state */
+#define TIOCGPTLCK	_IOR('T', 0x39, int) /* Get Pty lock state */
+#define TIOCGEXCL	_IOR('T', 0x40, int) /* Get exclusive mode state */
 
 /* I hope the range from 0x5480 on is free ... */
 #define TIOCSCTTY	0x5480		/* become controlling tty */
diff --git a/arch/mips/include/uapi/asm/mman.h b/arch/mips/include/uapi/asm/mman.h
index 46d3da0..9a936ac 100644
--- a/arch/mips/include/uapi/asm/mman.h
+++ b/arch/mips/include/uapi/asm/mman.h
@@ -87,4 +87,15 @@
 /* compatibility flags */
 #define MAP_FILE	0
 
+/*
+ * When MAP_HUGETLB is set bits [26:31] encode the log2 of the huge page size.
+ * This gives us 6 bits, which is enough until someone invents 128 bit address
+ * spaces.
+ *
+ * Assume these are all power of twos.
+ * When 0 use the default page size.
+ */
+#define MAP_HUGE_SHIFT	26
+#define MAP_HUGE_MASK	0x3f
+
 #endif /* _ASM_MMAN_H */
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index c5ed595..17307ab 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -63,6 +63,7 @@ To add: #define SO_REUSEPORT 0x0200	/* Allow local address and port reuse.  */
 /* 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
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 8b28bc4..764597b 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -80,7 +80,8 @@ obj-$(CONFIG_I8253)		+= i8253.o
 
 obj-$(CONFIG_GPIO_TXX9)		+= gpio_txx9.o
 
-obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
+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_SPINLOCK_TEST)	+= spinlock_test.o
 obj-$(CONFIG_MIPS_MACHINE)	+= mips_machine.o
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index 0c4bce4..9690998 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -125,10 +125,6 @@ void output_thread_defines(void)
 	       thread.cp0_baduaddr);
 	OFFSET(THREAD_ECODE, task_struct, \
 	       thread.error_code);
-	OFFSET(THREAD_TRAMP, task_struct, \
-	       thread.irix_trampoline);
-	OFFSET(THREAD_OLDCTX, task_struct, \
-	       thread.irix_oldctx);
 	BLANK();
 }
 
diff --git a/arch/mips/kernel/crash.c b/arch/mips/kernel/crash.c
new file mode 100644
index 0000000..0f53c39
--- /dev/null
+++ b/arch/mips/kernel/crash.c
@@ -0,0 +1,71 @@
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/reboot.h>
+#include <linux/kexec.h>
+#include <linux/bootmem.h>
+#include <linux/crash_dump.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+
+/* This keeps a track of which one is crashing cpu. */
+static int crashing_cpu = -1;
+static cpumask_t cpus_in_crash = CPU_MASK_NONE;
+
+#ifdef CONFIG_SMP
+static void crash_shutdown_secondary(void *ignore)
+{
+	struct pt_regs *regs;
+	int cpu = smp_processor_id();
+
+	regs = task_pt_regs(current);
+
+	if (!cpu_online(cpu))
+		return;
+
+	local_irq_disable();
+	if (!cpu_isset(cpu, cpus_in_crash))
+		crash_save_cpu(regs, cpu);
+	cpu_set(cpu, cpus_in_crash);
+
+	while (!atomic_read(&kexec_ready_to_reboot))
+		cpu_relax();
+	relocated_kexec_smp_wait(NULL);
+	/* NOTREACHED */
+}
+
+static void crash_kexec_prepare_cpus(void)
+{
+	unsigned int msecs;
+
+	unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
+
+	dump_send_ipi(crash_shutdown_secondary);
+	smp_wmb();
+
+	/*
+	 * The crash CPU sends an IPI and wait for other CPUs to
+	 * respond. Delay of at least 10 seconds.
+	 */
+	pr_emerg("Sending IPI to other cpus...\n");
+	msecs = 10000;
+	while ((cpus_weight(cpus_in_crash) < ncpus) && (--msecs > 0)) {
+		cpu_relax();
+		mdelay(1);
+	}
+}
+
+#else /* !defined(CONFIG_SMP)  */
+static void crash_kexec_prepare_cpus(void) {}
+#endif /* !defined(CONFIG_SMP)  */
+
+void default_machine_crash_shutdown(struct pt_regs *regs)
+{
+	local_irq_disable();
+	crashing_cpu = smp_processor_id();
+	crash_save_cpu(regs, crashing_cpu);
+	crash_kexec_prepare_cpus();
+	cpu_set(crashing_cpu, cpus_in_crash);
+}
diff --git a/arch/mips/kernel/crash_dump.c b/arch/mips/kernel/crash_dump.c
new file mode 100644
index 0000000..d9ec389
--- /dev/null
+++ b/arch/mips/kernel/crash_dump.c
@@ -0,0 +1,77 @@
+#include <linux/highmem.h>
+#include <linux/bootmem.h>
+#include <linux/crash_dump.h>
+#include <asm/uaccess.h>
+
+unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+
+static int __init parse_savemaxmem(char *p)
+{
+	if (p)
+		saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1;
+
+	return 1;
+}
+__setup("savemaxmem=", parse_savemaxmem);
+
+
+static void *kdump_buf_page;
+
+/**
+ * copy_oldmem_page - copy one page from "oldmem"
+ * @pfn: page frame number to be copied
+ * @buf: target memory address for the copy; this can be in kernel address
+ *	space or user address space (see @userbuf)
+ * @csize: number of bytes to copy
+ * @offset: offset in bytes into the page (based on pfn) to begin the copy
+ * @userbuf: if set, @buf is in user address space, use copy_to_user(),
+ *	otherwise @buf is in kernel address space, use memcpy().
+ *
+ * Copy a page from "oldmem". For this page, there is no pte mapped
+ * in the current kernel.
+ *
+ * Calling copy_to_user() in atomic context is not desirable. Hence first
+ * copying the data to a pre-allocated kernel page and then copying to user
+ * space in non-atomic context.
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
+			 size_t csize, unsigned long offset, int userbuf)
+{
+	void  *vaddr;
+
+	if (!csize)
+		return 0;
+
+	vaddr = kmap_atomic_pfn(pfn);
+
+	if (!userbuf) {
+		memcpy(buf, (vaddr + offset), csize);
+		kunmap_atomic(vaddr);
+	} else {
+		if (!kdump_buf_page) {
+			pr_warning("Kdump: Kdump buffer page not allocated\n");
+
+			return -EFAULT;
+		}
+		copy_page(kdump_buf_page, vaddr);
+		kunmap_atomic(vaddr);
+		if (copy_to_user(buf, (kdump_buf_page + offset), csize))
+			return -EFAULT;
+	}
+
+	return csize;
+}
+
+static int __init kdump_buf_page_init(void)
+{
+	int ret = 0;
+
+	kdump_buf_page = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!kdump_buf_page) {
+		pr_warning("Kdump: Failed to allocate kdump buffer page\n");
+		ret = -ENOMEM;
+	}
+
+	return ret;
+}
+arch_initcall(kdump_buf_page_init);
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index a6c1332..3320cb4 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -65,6 +65,12 @@ need_resched:
 	b	need_resched
 #endif
 
+FEXPORT(ret_from_kernel_thread)
+	jal	schedule_tail		# a0 = struct task_struct *prev
+	move	a0, s1
+	jal	s0
+	j	syscall_exit
+
 FEXPORT(ret_from_fork)
 	jal	schedule_tail		# a0 = struct task_struct *prev
 
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 3a21ace..7adab86 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -3,7 +3,6 @@
  *
  * Copyright (C) 2000 Silicon Graphics, Inc.
  * Written by Ulf Carlsson (ulfc@engr.sgi.com)
- * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com)
  */
 #include <linux/compiler.h>
 #include <linux/mm.h>
@@ -77,26 +76,6 @@ out:
 	return error;
 }
 
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs)
-{
-	int error;
-	struct filename *filename;
-
-	filename = getname(compat_ptr(regs.regs[4]));
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-	error = compat_do_execve(filename->name, compat_ptr(regs.regs[5]),
-				 compat_ptr(regs.regs[6]), &regs);
-	putname(filename);
-
-out:
-	return error;
-}
-
 #define RLIM_INFINITY32	0x7fffffff
 #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
 
@@ -333,7 +312,7 @@ _sys32_clone(nabi_no_regargs struct pt_regs regs)
 	/* Use __dummy4 instead of getting it off the stack, so that
 	   syscall() works.  */
 	child_tidptr = (int __user *) __dummy4;
-	return do_fork(clone_flags, newsp, &regs, 0,
+	return do_fork(clone_flags, newsp, 0,
 	               parent_tidptr, child_tidptr);
 }
 
diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c
index 85beb9b..992e184 100644
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
@@ -5,7 +5,7 @@
  * This source code is licensed under the GNU General Public License,
  * Version 2.  See the file COPYING for more details.
  */
-
+#include <linux/compiler.h>
 #include <linux/kexec.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
@@ -19,9 +19,19 @@ extern const size_t relocate_new_kernel_size;
 extern unsigned long kexec_start_address;
 extern unsigned long kexec_indirection_page;
 
+int (*_machine_kexec_prepare)(struct kimage *) = NULL;
+void (*_machine_kexec_shutdown)(void) = NULL;
+void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL;
+#ifdef CONFIG_SMP
+void (*relocated_kexec_smp_wait) (void *);
+atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0);
+#endif
+
 int
 machine_kexec_prepare(struct kimage *kimage)
 {
+	if (_machine_kexec_prepare)
+		return _machine_kexec_prepare(kimage);
 	return 0;
 }
 
@@ -33,14 +43,20 @@ machine_kexec_cleanup(struct kimage *kimage)
 void
 machine_shutdown(void)
 {
+	if (_machine_kexec_shutdown)
+		_machine_kexec_shutdown();
 }
 
 void
 machine_crash_shutdown(struct pt_regs *regs)
 {
+	if (_machine_crash_shutdown)
+		_machine_crash_shutdown(regs);
+	else
+		default_machine_crash_shutdown(regs);
 }
 
-typedef void (*noretfun_t)(void) __attribute__((noreturn));
+typedef void (*noretfun_t)(void) __noreturn;
 
 void
 machine_kexec(struct kimage *image)
@@ -52,7 +68,9 @@ machine_kexec(struct kimage *image)
 	reboot_code_buffer =
 	  (unsigned long)page_address(image->control_code_page);
 
-	kexec_start_address = image->start;
+	kexec_start_address =
+		(unsigned long) phys_to_virt(image->start);
+
 	kexec_indirection_page =
 		(unsigned long) phys_to_virt(image->head & PAGE_MASK);
 
@@ -63,7 +81,7 @@ machine_kexec(struct kimage *image)
 	 * The generic kexec code builds a page list with physical
 	 * addresses. they are directly accessible through KSEG0 (or
 	 * CKSEG0 or XPHYS if on 64bit system), hence the
-	 * pys_to_virt() call.
+	 * phys_to_virt() call.
 	 */
 	for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE);
 	     ptr = (entry & IND_INDIRECTION) ?
@@ -81,5 +99,12 @@ machine_kexec(struct kimage *image)
 	printk("Will call new kernel at %08lx\n", image->start);
 	printk("Bye ...\n");
 	__flush_cache_all();
+#ifdef CONFIG_SMP
+	/* All secondary cpus now may jump to kexec_wait cycle */
+	relocated_kexec_smp_wait = reboot_code_buffer +
+		(void *)(kexec_smp_wait - relocate_new_kernel);
+	smp_wmb();
+	atomic_set(&kexec_ready_to_reboot, 1);
+#endif
 	((noretfun_t) reboot_code_buffer)();
 }
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
index 33f63ba..fd814e0 100644
--- a/arch/mips/kernel/mips-mt-fpaff.c
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -50,8 +50,8 @@ static bool check_same_owner(struct task_struct *p)
 
 	rcu_read_lock();
 	pcred = __task_cred(p);
-	match = (cred->euid == pcred->euid ||
-		 cred->euid == pcred->uid);
+	match = (uid_eq(cred->euid, pcred->euid) ||
+		 uid_eq(cred->euid, pcred->uid));
 	rcu_read_unlock();
 	return match;
 }
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index 3fc1691..df1e3e4 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -11,7 +11,7 @@
 #include <linux/interrupt.h>
 #include <linux/export.h>
 #include <asm/checksum.h>
-#include <asm/pgtable.h>
+#include <linux/mm.h>
 #include <asm/uaccess.h>
 #include <asm/ftrace.h>
 
@@ -32,8 +32,6 @@ EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memmove);
 
-EXPORT_SYMBOL(kernel_thread);
-
 /*
  * Functions that operate on entire pages.  Mostly used by memory management.
  */
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index a9b995d..b14c14d 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -840,6 +840,16 @@ static const struct mips_perf_event bmips5000_event_map
 	[PERF_COUNT_HW_BRANCH_MISSES] = { 0x02, CNTR_ODD, T },
 };
 
+static const struct mips_perf_event xlp_event_map[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES] = { 0x01, CNTR_ALL },
+	[PERF_COUNT_HW_INSTRUCTIONS] = { 0x18, CNTR_ALL }, /* PAPI_TOT_INS */
+	[PERF_COUNT_HW_CACHE_REFERENCES] = { 0x04, CNTR_ALL }, /* PAPI_L1_ICA */
+	[PERF_COUNT_HW_CACHE_MISSES] = { 0x07, CNTR_ALL }, /* PAPI_L1_ICM */
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x1b, CNTR_ALL }, /* PAPI_BR_CN */
+	[PERF_COUNT_HW_BRANCH_MISSES] = { 0x1c, CNTR_ALL }, /* PAPI_BR_MSP */
+	[PERF_COUNT_HW_BUS_CYCLES] = { UNSUPPORTED_PERF_EVENT_ID },
+};
+
 /* 24K/34K/1004K cores can share the same cache event map. */
 static const struct mips_perf_event mipsxxcore_cache_map
 				[PERF_COUNT_HW_CACHE_MAX]
@@ -1092,6 +1102,100 @@ static const struct mips_perf_event octeon_cache_map
 },
 };
 
+static const struct mips_perf_event xlp_cache_map
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+[C(L1D)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { 0x31, CNTR_ALL }, /* PAPI_L1_DCR */
+		[C(RESULT_MISS)]	= { 0x30, CNTR_ALL }, /* PAPI_L1_LDM */
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { 0x2f, CNTR_ALL }, /* PAPI_L1_DCW */
+		[C(RESULT_MISS)]	= { 0x2e, CNTR_ALL }, /* PAPI_L1_STM */
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+[C(L1I)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { 0x04, CNTR_ALL }, /* PAPI_L1_ICA */
+		[C(RESULT_MISS)]	= { 0x07, CNTR_ALL }, /* PAPI_L1_ICM */
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+[C(LL)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { 0x35, CNTR_ALL }, /* PAPI_L2_DCR */
+		[C(RESULT_MISS)]	= { 0x37, CNTR_ALL }, /* PAPI_L2_LDM */
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { 0x34, CNTR_ALL }, /* PAPI_L2_DCA */
+		[C(RESULT_MISS)]	= { 0x36, CNTR_ALL }, /* PAPI_L2_DCM */
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+[C(DTLB)] = {
+	/*
+	 * Only general DTLB misses are counted use the same event for
+	 * read and write.
+	 */
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { 0x2d, CNTR_ALL }, /* PAPI_TLB_DM */
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { 0x2d, CNTR_ALL }, /* PAPI_TLB_DM */
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+[C(ITLB)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { 0x08, CNTR_ALL }, /* PAPI_TLB_IM */
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { 0x08, CNTR_ALL }, /* PAPI_TLB_IM */
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+[C(BPU)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { 0x25, CNTR_ALL },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+		[C(RESULT_MISS)]	= { UNSUPPORTED_PERF_EVENT_ID },
+	},
+},
+};
+
 #ifdef CONFIG_MIPS_MT_SMP
 static void check_and_calc_range(struct perf_event *event,
 				 const struct mips_perf_event *pev)
@@ -1444,6 +1548,20 @@ static const struct mips_perf_event *octeon_pmu_map_raw_event(u64 config)
 	return &raw_event;
 }
 
+static const struct mips_perf_event *xlp_pmu_map_raw_event(u64 config)
+{
+	unsigned int raw_id = config & 0xff;
+
+	/* Only 1-63 are defined */
+	if ((raw_id < 0x01) || (raw_id > 0x3f))
+		return ERR_PTR(-EOPNOTSUPP);
+
+	raw_event.cntr_mask = CNTR_ALL;
+	raw_event.event_id = raw_id;
+
+	return &raw_event;
+}
+
 static int __init
 init_hw_perf_events(void)
 {
@@ -1522,6 +1640,12 @@ init_hw_perf_events(void)
 		mipspmu.general_event_map = &bmips5000_event_map;
 		mipspmu.cache_event_map = &bmips5000_cache_map;
 		break;
+	case CPU_XLP:
+		mipspmu.name = "xlp";
+		mipspmu.general_event_map = &xlp_event_map;
+		mipspmu.cache_event_map = &xlp_cache_map;
+		mipspmu.map_raw_event = xlp_pmu_map_raw_event;
+		break;
 	default:
 		pr_cont("Either hardware does not support performance "
 			"counters, or not yet implemented.\n");
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index e9a5fd7..38097652 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -84,6 +84,7 @@ void __noreturn cpu_idle(void)
 }
 
 asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
 
 void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
 {
@@ -113,10 +114,10 @@ void flush_thread(void)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-	unsigned long unused, struct task_struct *p, struct pt_regs *regs)
+	unsigned long arg, struct task_struct *p)
 {
 	struct thread_info *ti = task_thread_info(p);
-	struct pt_regs *childregs;
+	struct pt_regs *childregs, *regs = current_pt_regs();
 	unsigned long childksp;
 	p->set_child_tid = p->clear_child_tid = NULL;
 
@@ -136,19 +137,30 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	childregs = (struct pt_regs *) childksp - 1;
 	/*  Put the stack after the struct pt_regs.  */
 	childksp = (unsigned long) childregs;
+	p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1);
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		unsigned long status = p->thread.cp0_status;
+		memset(childregs, 0, sizeof(struct pt_regs));
+		ti->addr_limit = KERNEL_DS;
+		p->thread.reg16 = usp; /* fn */
+		p->thread.reg17 = arg;
+		p->thread.reg29 = childksp;
+		p->thread.reg31 = (unsigned long) ret_from_kernel_thread;
+#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+		status = (status & ~(ST0_KUP | ST0_IEP | ST0_IEC)) |
+			 ((status & (ST0_KUC | ST0_IEC)) << 2);
+#else
+		status |= ST0_EXL;
+#endif
+		childregs->cp0_status = status;
+		return 0;
+	}
 	*childregs = *regs;
 	childregs->regs[7] = 0;	/* Clear error flag */
-
 	childregs->regs[2] = 0;	/* Child gets zero as return value */
+	childregs->regs[29] = usp;
+	ti->addr_limit = USER_DS;
 
-	if (childregs->cp0_status & ST0_CU0) {
-		childregs->regs[28] = (unsigned long) ti;
-		childregs->regs[29] = childksp;
-		ti->addr_limit = KERNEL_DS;
-	} else {
-		childregs->regs[29] = usp;
-		ti->addr_limit = USER_DS;
-	}
 	p->thread.reg29 = (unsigned long) childregs;
 	p->thread.reg31 = (unsigned long) ret_from_fork;
 
@@ -156,7 +168,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	 * New tasks lose permission to use the fpu. This accelerates context
 	 * switching for most programs since they don't use the fpu.
 	 */
-	p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1);
 	childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
 
 #ifdef CONFIG_MIPS_MT_SMTC
@@ -222,35 +233,6 @@ int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr)
 }
 
 /*
- * Create a kernel thread
- */
-static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *))
-{
-	do_exit(fn(arg));
-}
-
-long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-
-	regs.regs[4] = (unsigned long) arg;
-	regs.regs[5] = (unsigned long) fn;
-	regs.cp0_epc = (unsigned long) kernel_thread_helper;
-	regs.cp0_status = read_c0_status();
-#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
-	regs.cp0_status = (regs.cp0_status & ~(ST0_KUP | ST0_IEP | ST0_IEC)) |
-			  ((regs.cp0_status & (ST0_KUC | ST0_IEC)) << 2);
-#else
-	regs.cp0_status |= ST0_EXL;
-#endif
-
-	/* Ok, create the new process.. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-
-/*
  *
  */
 struct mips_frame_info {
diff --git a/arch/mips/kernel/relocate_kernel.S b/arch/mips/kernel/relocate_kernel.S
index 87481f9..0b10858 100644
--- a/arch/mips/kernel/relocate_kernel.S
+++ b/arch/mips/kernel/relocate_kernel.S
@@ -15,6 +15,11 @@
 #include <asm/addrspace.h>
 
 LEAF(relocate_new_kernel)
+	PTR_L a0,	arg0
+	PTR_L a1,	arg1
+	PTR_L a2,	arg2
+	PTR_L a3,	arg3
+
 	PTR_L		s0, kexec_indirection_page
 	PTR_L		s1, kexec_start_address
 
@@ -26,7 +31,6 @@ process_entry:
 	and		s3, s2, 0x1
 	beq		s3, zero, 1f
 	and		s4, s2, ~0x1	/* store destination addr in s4 */
-	move		a0, s4
 	b		process_entry
 
 1:
@@ -60,10 +64,92 @@ copy_word:
 	b		process_entry
 
 done:
+#ifdef CONFIG_SMP
+	/* kexec_flag reset is signal to other CPUs what kernel
+	   was moved to it's location. Note - we need relocated address
+	   of kexec_flag.  */
+
+	bal		1f
+ 1: 	move		t1,ra;
+	PTR_LA		t2,1b
+	PTR_LA		t0,kexec_flag
+	PTR_SUB		t0,t0,t2;
+	PTR_ADD		t0,t1,t0;
+	LONG_S		zero,(t0)
+#endif
+
+	sync
 	/* jump to kexec_start_address */
 	j		s1
 	END(relocate_new_kernel)
 
+#ifdef CONFIG_SMP
+/*
+ * Other CPUs should wait until code is relocated and
+ * then start at entry (?) point.
+ */
+LEAF(kexec_smp_wait)
+	PTR_L		a0, s_arg0
+	PTR_L		a1, s_arg1
+	PTR_L		a2, s_arg2
+	PTR_L		a3, s_arg3
+	PTR_L		s1, kexec_start_address
+
+	/* Non-relocated address works for args and kexec_start_address ( old
+	 * kernel is not overwritten). But we need relocated address of
+	 * kexec_flag.
+	 */
+
+	bal		1f
+1:	move		t1,ra;
+	PTR_LA		t2,1b
+	PTR_LA		t0,kexec_flag
+	PTR_SUB		t0,t0,t2;
+	PTR_ADD		t0,t1,t0;
+
+1:	LONG_L		s0, (t0)
+	bne		s0, zero,1b
+
+	sync
+	j		s1
+	END(kexec_smp_wait)
+#endif
+
+#ifdef __mips64
+       /* all PTR's must be aligned to 8 byte in 64-bit mode */
+       .align  3
+#endif
+
+/* All parameters to new kernel are passed in registers a0-a3.
+ * kexec_args[0..3] are uses to prepare register values.
+ */
+
+kexec_args:
+	EXPORT(kexec_args)
+arg0:	PTR		0x0
+arg1:	PTR		0x0
+arg2:	PTR		0x0
+arg3:	PTR		0x0
+	.size	kexec_args,PTRSIZE*4
+
+#ifdef CONFIG_SMP
+/*
+ * Secondary CPUs may have different kernel parameters in
+ * their registers a0-a3. secondary_kexec_args[0..3] are used
+ * to prepare register values.
+ */
+secondary_kexec_args:
+	EXPORT(secondary_kexec_args)
+s_arg0:	PTR		0x0
+s_arg1:	PTR		0x0
+s_arg2:	PTR		0x0
+s_arg3:	PTR		0x0
+	.size	secondary_kexec_args,PTRSIZE*4
+kexec_flag:
+	LONG		0x1
+
+#endif
+
 kexec_start_address:
 	EXPORT(kexec_start_address)
 	PTR		0x0
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index f6ba838..42579d2 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -17,12 +17,6 @@
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
 
-/* This duplicates the definition from <linux/sched.h> */
-#define PT_TRACESYS	0x00000002	/* tracing system calls */
-
-/* This duplicates the definition from <asm/signal.h> */
-#define SIGILL		4		/* Illegal instruction (ANSI).  */
-
 #ifndef CONFIG_MIPS32_O32
 /* No O32, so define handle_sys here */
 #define handle_sysn32 handle_sys
@@ -167,7 +161,7 @@ EXPORT(sysn32_call_table)
 	PTR	sys_getsockopt
 	PTR	sys_clone			/* 6055 */
 	PTR	sys_fork
-	PTR	sys32_execve
+	PTR	compat_sys_execve
 	PTR	sys_exit
 	PTR	compat_sys_wait4
 	PTR	sys_kill			/* 6060 */
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 53c2d72..9601be6 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -203,7 +203,7 @@ sys_call_table:
 	PTR	sys_creat
 	PTR	sys_link
 	PTR	sys_unlink			/* 4010 */
-	PTR	sys32_execve
+	PTR	compat_sys_execve
 	PTR	sys_chdir
 	PTR	compat_sys_time
 	PTR	sys_mknod
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 290dc6a..8c41187 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -22,6 +22,7 @@
 #include <linux/console.h>
 #include <linux/pfn.h>
 #include <linux/debugfs.h>
+#include <linux/kexec.h>
 
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
@@ -536,12 +537,64 @@ static void __init arch_mem_init(char **cmdline_p)
 	}
 
 	bootmem_init();
+#ifdef CONFIG_KEXEC
+	if (crashk_res.start != crashk_res.end)
+		reserve_bootmem(crashk_res.start,
+				crashk_res.end - crashk_res.start + 1,
+				BOOTMEM_DEFAULT);
+#endif
 	device_tree_init();
 	sparse_init();
 	plat_swiotlb_setup();
 	paging_init();
 }
 
+#ifdef CONFIG_KEXEC
+static inline unsigned long long get_total_mem(void)
+{
+	unsigned long long total;
+
+	total = max_pfn - min_low_pfn;
+	return total << PAGE_SHIFT;
+}
+
+static void __init mips_parse_crashkernel(void)
+{
+	unsigned long long total_mem;
+	unsigned long long crash_size, crash_base;
+	int ret;
+
+	total_mem = get_total_mem();
+	ret = parse_crashkernel(boot_command_line, total_mem,
+				&crash_size, &crash_base);
+	if (ret != 0 || crash_size <= 0)
+		return;
+
+	crashk_res.start = crash_base;
+	crashk_res.end   = crash_base + crash_size - 1;
+}
+
+static void __init request_crashkernel(struct resource *res)
+{
+	int ret;
+
+	ret = request_resource(res, &crashk_res);
+	if (!ret)
+		pr_info("Reserving %ldMB of memory at %ldMB for crashkernel\n",
+			(unsigned long)((crashk_res.end -
+				crashk_res.start + 1) >> 20),
+			(unsigned long)(crashk_res.start  >> 20));
+}
+#else /* !defined(CONFIG_KEXEC)  */
+static void __init mips_parse_crashkernel(void)
+{
+}
+
+static void __init request_crashkernel(struct resource *res)
+{
+}
+#endif /* !defined(CONFIG_KEXEC)  */
+
 static void __init resource_init(void)
 {
 	int i;
@@ -557,6 +610,8 @@ static void __init resource_init(void)
 	/*
 	 * Request address space for all standard RAM.
 	 */
+	mips_parse_crashkernel();
+
 	for (i = 0; i < boot_mem_map.nr_map; i++) {
 		struct resource *res;
 		unsigned long start, end;
@@ -593,6 +648,7 @@ static void __init resource_init(void)
 		 */
 		request_resource(res, &code_resource);
 		request_resource(res, &data_resource);
+		request_crashkernel(res);
 	}
 }
 
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 0e1a5b8..b6aa770 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -568,17 +568,20 @@ static void do_signal(struct pt_regs *regs)
 	}
 
 	if (regs->regs[0]) {
-		if (regs->regs[2] == ERESTARTNOHAND ||
-		    regs->regs[2] == ERESTARTSYS ||
-		    regs->regs[2] == ERESTARTNOINTR) {
+		switch (regs->regs[2]) {
+		case ERESTARTNOHAND:
+		case ERESTARTSYS:
+		case ERESTARTNOINTR:
 			regs->regs[2] = regs->regs[0];
 			regs->regs[7] = regs->regs[26];
 			regs->cp0_epc -= 4;
-		}
-		if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
+			break;
+
+		case ERESTART_RESTARTBLOCK:
 			regs->regs[2] = current->thread.abi->restart;
 			regs->regs[7] = regs->regs[26];
 			regs->cp0_epc -= 4;
+			break;
 		}
 		regs->regs[0] = 0;	/* Don't deal with this again.  */
 	}
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 9005bf9..494bab1 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -386,3 +386,20 @@ void flush_tlb_one(unsigned long vaddr)
 
 EXPORT_SYMBOL(flush_tlb_page);
 EXPORT_SYMBOL(flush_tlb_one);
+
+#if defined(CONFIG_KEXEC)
+void (*dump_ipi_function_ptr)(void *) = NULL;
+void dump_send_ipi(void (*dump_ipi_callback)(void *))
+{
+	int i;
+	int cpu = smp_processor_id();
+
+	dump_ipi_function_ptr = dump_ipi_callback;
+	smp_mb();
+	for_each_online_cpu(i)
+		if (i != cpu)
+			core_send_ipi(i, SMP_DUMP);
+
+}
+EXPORT_SYMBOL(dump_send_ipi);
+#endif
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 2bd561b..201cb76 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -92,7 +92,7 @@ save_static_function(sys_fork);
 static int __used noinline
 _sys_fork(nabi_no_regargs struct pt_regs regs)
 {
-	return do_fork(SIGCHLD, regs.regs[29], &regs, 0, NULL, NULL);
+	return do_fork(SIGCHLD, regs.regs[29], 0, NULL, NULL);
 }
 
 save_static_function(sys_clone);
@@ -123,32 +123,10 @@ _sys_clone(nabi_no_regargs struct pt_regs regs)
 #else
 	child_tidptr = (int __user *) regs.regs[8];
 #endif
-	return do_fork(clone_flags, newsp, &regs, 0,
+	return do_fork(clone_flags, newsp, 0,
 	               parent_tidptr, child_tidptr);
 }
 
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs)
-{
-	int error;
-	struct filename *filename;
-
-	filename = getname((const char __user *) (long)regs.regs[4]);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-	error = do_execve(filename->name,
-			  (const char __user *const __user *) (long)regs.regs[5],
-	                  (const char __user *const __user *) (long)regs.regs[6],
-			  &regs);
-	putname(filename);
-
-out:
-	return error;
-}
-
 SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
 {
 	struct thread_info *ti = task_thread_info(current);
@@ -313,34 +291,3 @@ asmlinkage void bad_stack(void)
 {
 	do_exit(SIGSEGV);
 }
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	register unsigned long __a0 asm("$4") = (unsigned long) filename;
-	register unsigned long __a1 asm("$5") = (unsigned long) argv;
-	register unsigned long __a2 asm("$6") = (unsigned long) envp;
-	register unsigned long __a3 asm("$7");
-	unsigned long __v0;
-
-	__asm__ volatile ("					\n"
-	"	.set	noreorder				\n"
-	"	li	$2, %5		# __NR_execve		\n"
-	"	syscall						\n"
-	"	move	%0, $2					\n"
-	"	.set	reorder					\n"
-	: "=&r" (__v0), "=r" (__a3)
-	: "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve)
-	: "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24",
-	  "memory");
-
-	if (__a3 == 0)
-		return __v0;
-
-	return -__v0;
-}
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 9be3df1..da0c294 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -13,6 +13,7 @@
  */
 #include <linux/bug.h>
 #include <linux/compiler.h>
+#include <linux/kexec.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -409,6 +410,9 @@ void __noreturn die(const char *str, struct pt_regs *regs)
 		panic("Fatal exception");
 	}
 
+	if (regs && kexec_should_crash(current))
+		crash_kexec(regs);
+
 	do_exit(sig);
 }
 
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
index d84f361..c002191 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -36,4 +36,8 @@ config PCI_LANTIQ
 	bool "PCI Support"
 	depends on SOC_XWAY && PCI
 
+config XRX200_PHY_FW
+	bool "XRX200 PHY firmware loader"
+	depends on SOC_XWAY
+
 endif
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
index 6cfd611..9f9e875 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -87,9 +87,6 @@ void __init device_tree_init(void)
 	reserve_bootmem(base, size, BOOTMEM_DEFAULT);
 
 	unflatten_device_tree();
-
-	/* free the space reserved for the dt blob */
-	free_bootmem(base, size);
 }
 
 void __init prom_init(void)
@@ -119,7 +116,7 @@ int __init plat_of_setup(void)
 		sizeof(of_ids[0].compatible));
 	strncpy(of_ids[1].compatible, "simple-bus",
 		sizeof(of_ids[1].compatible));
-	return of_platform_bus_probe(NULL, of_ids, NULL);
+	return of_platform_populate(NULL, of_ids, NULL, NULL);
 }
 
 arch_initcall(plat_of_setup);
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index 70a58c7..7a13660 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1 +1,3 @@
 obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o
+
+obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o
diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
index 55d2c4f..6453962 100644
--- a/arch/mips/lantiq/xway/dma.c
+++ b/arch/mips/lantiq/xway/dma.c
@@ -25,6 +25,7 @@
 #include <lantiq_soc.h>
 #include <xway_dma.h>
 
+#define LTQ_DMA_ID		0x08
 #define LTQ_DMA_CTRL		0x10
 #define LTQ_DMA_CPOLL		0x14
 #define LTQ_DMA_CS		0x18
@@ -48,7 +49,7 @@
 #define DMA_CLK_DIV4		BIT(6)		/* polling clock divider */
 #define DMA_2W_BURST		BIT(1)		/* 2 word burst length */
 #define DMA_MAX_CHANNEL		20		/* the soc has 20 channels */
-#define DMA_ETOP_ENDIANESS	(0xf << 8) /* endianess swap etop channels */
+#define DMA_ETOP_ENDIANNESS	(0xf << 8) /* endianness swap etop channels */
 #define DMA_WEIGHT	(BIT(17) | BIT(16))	/* default channel wheight */
 
 #define ltq_dma_r32(x)			ltq_r32(ltq_dma_membase + (x))
@@ -191,10 +192,10 @@ ltq_dma_init_port(int p)
 	switch (p) {
 	case DMA_PORT_ETOP:
 		/*
-		 * Tell the DMA engine to swap the endianess of data frames and
+		 * Tell the DMA engine to swap the endianness of data frames and
 		 * drop packets if the channel arbitration fails.
 		 */
-		ltq_dma_w32_mask(0, DMA_ETOP_ENDIANESS | DMA_PDEN,
+		ltq_dma_w32_mask(0, DMA_ETOP_ENDIANNESS | DMA_PDEN,
 			LTQ_DMA_PCTRL);
 		break;
 
@@ -214,6 +215,7 @@ ltq_dma_init(struct platform_device *pdev)
 {
 	struct clk *clk;
 	struct resource *res;
+	unsigned id;
 	int i;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -243,7 +245,12 @@ ltq_dma_init(struct platform_device *pdev)
 		ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
 		ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
 	}
-	dev_info(&pdev->dev, "init done\n");
+
+	id = ltq_dma_r32(LTQ_DMA_ID);
+	dev_info(&pdev->dev,
+		"Init done - hw rev: %X, ports: %d, channels: %d\n",
+		id & 0x1f, (id >> 16) & 0xf, id >> 20);
+
 	return 0;
 }
 
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index 22c55f7..544dbb7 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -28,17 +28,24 @@
 #define RCU_RST_REQ		0x0010
 /* reset status register */
 #define RCU_RST_STAT		0x0014
+/* vr9 gphy registers */
+#define RCU_GFS_ADD0_XRX200	0x0020
+#define RCU_GFS_ADD1_XRX200	0x0068
 
 /* reboot bit */
+#define RCU_RD_GPHY0_XRX200	BIT(31)
 #define RCU_RD_SRST		BIT(30)
+#define RCU_RD_GPHY1_XRX200	BIT(29)
+
 /* reset cause */
 #define RCU_STAT_SHIFT		26
 /* boot selection */
-#define RCU_BOOT_SEL_SHIFT	26
-#define RCU_BOOT_SEL_MASK	0x7
+#define RCU_BOOT_SEL(x)		((x >> 18) & 0x7)
+#define RCU_BOOT_SEL_XRX200(x)	(((x >> 17) & 0xf) | ((x >> 8) & 0x10))
 
 /* remapped base addr of the reset control unit */
 static void __iomem *ltq_rcu_membase;
+static struct device_node *ltq_rcu_np;
 
 /* This function is used by the watchdog driver */
 int ltq_reset_cause(void)
@@ -52,7 +59,41 @@ EXPORT_SYMBOL_GPL(ltq_reset_cause);
 unsigned char ltq_boot_select(void)
 {
 	u32 val = ltq_rcu_r32(RCU_RST_STAT);
-	return (val >> RCU_BOOT_SEL_SHIFT) & RCU_BOOT_SEL_MASK;
+
+	if (of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200"))
+		return RCU_BOOT_SEL_XRX200(val);
+
+	return RCU_BOOT_SEL(val);
+}
+
+/* reset / boot a gphy */
+static struct ltq_xrx200_gphy_reset {
+	u32 rd;
+	u32 addr;
+} xrx200_gphy[] = {
+	{RCU_RD_GPHY0_XRX200, RCU_GFS_ADD0_XRX200},
+	{RCU_RD_GPHY1_XRX200, RCU_GFS_ADD1_XRX200},
+};
+
+/* reset and boot a gphy. these phys only exist on xrx200 SoC */
+int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr)
+{
+	if (!of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200")) {
+		dev_err(dev, "this SoC has no GPHY\n");
+		return -EINVAL;
+	}
+	if (id > 1) {
+		dev_err(dev, "%u is an invalid gphy id\n", id);
+		return -EINVAL;
+	}
+	dev_info(dev, "booting GPHY%u firmware at %X\n", id, dev_addr);
+
+	ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | xrx200_gphy[id].rd,
+			RCU_RST_REQ);
+	ltq_rcu_w32(dev_addr, xrx200_gphy[id].addr);
+	ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~xrx200_gphy[id].rd,
+			RCU_RST_REQ);
+	return 0;
 }
 
 /* reset a io domain for u micro seconds */
@@ -85,14 +126,17 @@ static void ltq_machine_power_off(void)
 static int __init mips_reboot_setup(void)
 {
 	struct resource res;
-	struct device_node *np =
-		of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway");
+
+	ltq_rcu_np = of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway");
+	if (!ltq_rcu_np)
+		ltq_rcu_np = of_find_compatible_node(NULL, NULL,
+							"lantiq,rcu-xrx200");
 
 	/* check if all the reset register range is available */
-	if (!np)
+	if (!ltq_rcu_np)
 		panic("Failed to load reset resources from devicetree");
 
-	if (of_address_to_resource(np, 0, &res))
+	if (of_address_to_resource(ltq_rcu_np, 0, &res))
 		panic("Failed to get rcu memory range");
 
 	if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index 2917b56..3925e66 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -370,6 +370,10 @@ void __init ltq_soc_init(void)
 		clkdev_add_pmu("1d900000.pcie", "pdi", 1, PMU1_PCIE_PDI);
 		clkdev_add_pmu("1d900000.pcie", "ctl", 1, PMU1_PCIE_CTL);
 		clkdev_add_pmu("1d900000.pcie", "ahb", 0, PMU_AHBM | PMU_AHBS);
+		clkdev_add_pmu("1e108000.eth", NULL, 0,
+				PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
+				PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
+				PMU_PPE_QSB | PMU_PPE_TOP);
 	} else if (of_machine_is_compatible("lantiq,ar9")) {
 		clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
 				ltq_ar9_fpi_hz());
diff --git a/arch/mips/lantiq/xway/xrx200_phy_fw.c b/arch/mips/lantiq/xway/xrx200_phy_fw.c
new file mode 100644
index 0000000..fe808bf
--- /dev/null
+++ b/arch/mips/lantiq/xway/xrx200_phy_fw.c
@@ -0,0 +1,97 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/of_platform.h>
+
+#include <lantiq_soc.h>
+
+#define XRX200_GPHY_FW_ALIGN	(16 * 1024)
+
+static dma_addr_t xway_gphy_load(struct platform_device *pdev)
+{
+	const struct firmware *fw;
+	dma_addr_t dev_addr = 0;
+	const char *fw_name;
+	void *fw_addr;
+	size_t size;
+
+	if (of_property_read_string(pdev->dev.of_node, "firmware", &fw_name)) {
+		dev_err(&pdev->dev, "failed to load firmware filename\n");
+		return 0;
+	}
+
+	dev_info(&pdev->dev, "requesting %s\n", fw_name);
+	if (request_firmware(&fw, fw_name, &pdev->dev)) {
+		dev_err(&pdev->dev, "failed to load firmware: %s\n", fw_name);
+		return 0;
+	}
+
+	/*
+	 * GPHY cores need the firmware code in a persistent and contiguous
+	 * memory area with a 16 kB boundary aligned start address
+	 */
+	size = fw->size + XRX200_GPHY_FW_ALIGN;
+
+	fw_addr = dma_alloc_coherent(&pdev->dev, size, &dev_addr, GFP_KERNEL);
+	if (fw_addr) {
+		fw_addr = PTR_ALIGN(fw_addr, XRX200_GPHY_FW_ALIGN);
+		dev_addr = ALIGN(dev_addr, XRX200_GPHY_FW_ALIGN);
+		memcpy(fw_addr, fw->data, fw->size);
+	} else {
+		dev_err(&pdev->dev, "failed to alloc firmware memory\n");
+	}
+
+	release_firmware(fw);
+	return dev_addr;
+}
+
+static int __devinit xway_phy_fw_probe(struct platform_device *pdev)
+{
+	dma_addr_t fw_addr;
+	struct property *pp;
+	unsigned char *phyids;
+	int i, ret = 0;
+
+	fw_addr = xway_gphy_load(pdev);
+	if (!fw_addr)
+		return -EINVAL;
+	pp = of_find_property(pdev->dev.of_node, "phys", NULL);
+	if (!pp)
+		return -ENOENT;
+	phyids = pp->value;
+	for (i = 0; i < pp->length && !ret; i++)
+		ret = xrx200_gphy_boot(&pdev->dev, phyids[i], fw_addr);
+	if (!ret)
+		mdelay(100);
+	return ret;
+}
+
+static const struct of_device_id xway_phy_match[] = {
+	{ .compatible = "lantiq,phy-xrx200" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, xway_phy_match);
+
+static struct platform_driver xway_phy_driver = {
+	.probe = xway_phy_fw_probe,
+	.driver = {
+		.name = "phy-xrx200",
+		.owner = THIS_MODULE,
+		.of_match_table = xway_phy_match,
+	},
+};
+
+module_platform_driver(xway_phy_driver);
+
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_DESCRIPTION("Lantiq XRX200 PHY Firmware Loader");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c
index a99c1d3..2d7a91a 100644
--- a/arch/mips/lib/dump_tlb.c
+++ b/arch/mips/lib/dump_tlb.c
@@ -5,11 +5,14 @@
  * Copyright (C) 1999 by Silicon Graphics, Inc.
  */
 #include <linux/kernel.h>
+#include <linux/hugetlb.h>
 #include <linux/mm.h>
+#include <linux/sched.h>
 
 #include <asm/mipsregs.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/current.h>
 #include <asm/tlbdebug.h>
 
 static inline const char *msk2str(unsigned int mask)
@@ -111,3 +114,47 @@ void dump_tlb_all(void)
 {
 	dump_tlb(0, current_cpu_data.tlbsize - 1);
 }
+
+void dump_current_addr(unsigned long addr)
+{
+	pgd_t *pgdp;
+	pud_t *pudp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	pte_t pte;
+
+	printk("Dumping for address %lx\n", addr);
+	pgdp = pgd_offset(current->mm, addr);
+	printk("pgd %lx\n", pgd_val(*pgdp));
+
+	pudp = pud_offset(pgdp, addr);
+	printk("pud %lx", pud_val(*pudp));
+#ifndef __PAGETABLE_PMD_FOLDED
+	if (pud_val(*pudp) == (unsigned long) invalid_pmd_table) {
+		printk("  (invalid_pmd_table)\n");
+
+		return;
+	}
+#endif
+	printk("\n");
+
+	pmdp = pmd_offset(pudp, addr);
+	printk("pmd  %lx", pmd_val(*pmdp));
+	if (pmd_huge(*pmdp)) {
+		printk("  pmd is huge\n");
+
+		return;
+	}
+	if (pmd_val(*pmdp) == (unsigned long) invalid_pte_table) {
+		printk("  (invalid_pte_table)\n");
+
+		return;
+	}
+	printk("\n");
+
+	ptep = pte_offset_map(pmdp, addr);
+	pte = *ptep;
+	printk("pte %lx\n", pte_val(pte));
+	if (pte_huge(pte))
+		printk("  pte is huge\n");
+}
diff --git a/arch/mips/loongson1/Kconfig b/arch/mips/loongson1/Kconfig
index a9a14d6..fbf75f6 100644
--- a/arch/mips/loongson1/Kconfig
+++ b/arch/mips/loongson1/Kconfig
@@ -15,7 +15,7 @@ config LOONGSON1_LS1B
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_HIGHMEM
 	select SYS_HAS_EARLY_PRINTK
-	select HAVE_CLK
+	select COMMON_CLK
 
 endchoice
 
diff --git a/arch/mips/loongson1/common/clock.c b/arch/mips/loongson1/common/clock.c
index 1bbbbec..07133de 100644
--- a/arch/mips/loongson1/common/clock.c
+++ b/arch/mips/loongson1/common/clock.c
@@ -7,175 +7,22 @@
  * option) any later version.
  */
 
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
 #include <linux/clk.h>
 #include <linux/err.h>
-#include <asm/clock.h>
 #include <asm/time.h>
-
-#include <loongson1.h>
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-struct clk *clk_get(struct device *dev, const char *name)
-{
-	struct clk *c;
-	struct clk *ret = NULL;
-
-	mutex_lock(&clocks_mutex);
-	list_for_each_entry(c, &clocks, node) {
-		if (!strcmp(c->name, name)) {
-			ret = c;
-			break;
-		}
-	}
-	mutex_unlock(&clocks_mutex);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_get);
-
-int clk_enable(struct clk *clk)
-{
-	return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	return clk->rate;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_put);
-
-static void pll_clk_init(struct clk *clk)
-{
-	u32 pll;
-
-	pll = __raw_readl(LS1X_CLK_PLL_FREQ);
-	clk->rate = (12 + (pll & 0x3f)) * 33 / 2
-			+ ((pll >> 8) & 0x3ff) * 33 / 1024 / 2;
-	clk->rate *= 1000000;
-}
-
-static void cpu_clk_init(struct clk *clk)
-{
-	u32 pll, ctrl;
-
-	pll = clk_get_rate(clk->parent);
-	ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_CPU;
-	clk->rate = pll / (ctrl >> DIV_CPU_SHIFT);
-}
-
-static void ddr_clk_init(struct clk *clk)
-{
-	u32 pll, ctrl;
-
-	pll = clk_get_rate(clk->parent);
-	ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_DDR;
-	clk->rate = pll / (ctrl >> DIV_DDR_SHIFT);
-}
-
-static void dc_clk_init(struct clk *clk)
-{
-	u32 pll, ctrl;
-
-	pll = clk_get_rate(clk->parent);
-	ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_DC;
-	clk->rate = pll / (ctrl >> DIV_DC_SHIFT);
-}
-
-static struct clk_ops pll_clk_ops = {
-	.init	= pll_clk_init,
-};
-
-static struct clk_ops cpu_clk_ops = {
-	.init	= cpu_clk_init,
-};
-
-static struct clk_ops ddr_clk_ops = {
-	.init	= ddr_clk_init,
-};
-
-static struct clk_ops dc_clk_ops = {
-	.init	= dc_clk_init,
-};
-
-static struct clk pll_clk = {
-	.name	= "pll",
-	.ops	= &pll_clk_ops,
-};
-
-static struct clk cpu_clk = {
-	.name	= "cpu",
-	.parent = &pll_clk,
-	.ops	= &cpu_clk_ops,
-};
-
-static struct clk ddr_clk = {
-	.name	= "ddr",
-	.parent = &pll_clk,
-	.ops	= &ddr_clk_ops,
-};
-
-static struct clk dc_clk = {
-	.name	= "dc",
-	.parent = &pll_clk,
-	.ops	= &dc_clk_ops,
-};
-
-int clk_register(struct clk *clk)
-{
-	mutex_lock(&clocks_mutex);
-	list_add(&clk->node, &clocks);
-	if (clk->ops->init)
-		clk->ops->init(clk);
-	mutex_unlock(&clocks_mutex);
-
-	return 0;
-}
-EXPORT_SYMBOL(clk_register);
-
-static struct clk *ls1x_clks[] = {
-	&pll_clk,
-	&cpu_clk,
-	&ddr_clk,
-	&dc_clk,
-};
-
-int __init ls1x_clock_init(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(ls1x_clks); i++)
-		clk_register(ls1x_clks[i]);
-
-	return 0;
-}
+#include <platform.h>
 
 void __init plat_time_init(void)
 {
 	struct clk *clk;
 
 	/* Initialize LS1X clocks */
-	ls1x_clock_init();
+	ls1x_clk_init();
 
 	/* setup mips r4k timer */
 	clk = clk_get(NULL, "cpu");
 	if (IS_ERR(clk))
-		panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
+		panic("unable to get cpu clock, err=%ld", PTR_ERR(clk));
 
 	mips_hpt_frequency = clk_get_rate(clk) / 2;
 }
diff --git a/arch/mips/loongson1/common/platform.c b/arch/mips/loongson1/common/platform.c
index e92d59c..69dad4c 100644
--- a/arch/mips/loongson1/common/platform.c
+++ b/arch/mips/loongson1/common/platform.c
@@ -13,6 +13,7 @@
 #include <linux/phy.h>
 #include <linux/serial_8250.h>
 #include <linux/stmmac.h>
+#include <linux/usb/ehci_pdriver.h>
 #include <asm-generic/sizes.h>
 
 #include <loongson1.h>
@@ -42,16 +43,17 @@ struct platform_device ls1x_uart_device = {
 	},
 };
 
-void __init ls1x_serial_setup(void)
+void __init ls1x_serial_setup(struct platform_device *pdev)
 {
 	struct clk *clk;
 	struct plat_serial8250_port *p;
 
-	clk = clk_get(NULL, "dc");
+	clk = clk_get(NULL, pdev->name);
 	if (IS_ERR(clk))
-		panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
+		panic("unable to get %s clock, err=%ld",
+			pdev->name, PTR_ERR(clk));
 
-	for (p = ls1x_serial8250_port; p->flags != 0; ++p)
+	for (p = pdev->dev.platform_data; p->flags != 0; ++p)
 		p->uartclk = clk_get_rate(clk);
 }
 
@@ -70,7 +72,6 @@ static struct resource ls1x_eth0_resources[] = {
 };
 
 static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = {
-	.bus_id		= 0,
 	.phy_mask	= 0,
 };
 
@@ -107,13 +108,17 @@ static struct resource ls1x_ehci_resources[] = {
 	},
 };
 
+static struct usb_ehci_pdata ls1x_ehci_pdata = {
+};
+
 struct platform_device ls1x_ehci_device = {
-	.name		= "ls1x-ehci",
+	.name		= "ehci-platform",
 	.id		= -1,
 	.num_resources	= ARRAY_SIZE(ls1x_ehci_resources),
 	.resource	= ls1x_ehci_resources,
 	.dev		= {
 		.dma_mask = &ls1x_ehci_dmamask,
+		.platform_data = &ls1x_ehci_pdata,
 	},
 };
 
diff --git a/arch/mips/loongson1/ls1b/board.c b/arch/mips/loongson1/ls1b/board.c
index 295b1be..1fbd526 100644
--- a/arch/mips/loongson1/ls1b/board.c
+++ b/arch/mips/loongson1/ls1b/board.c
@@ -9,9 +9,6 @@
 
 #include <platform.h>
 
-#include <linux/serial_8250.h>
-#include <loongson1.h>
-
 static struct platform_device *ls1b_platform_devices[] __initdata = {
 	&ls1x_uart_device,
 	&ls1x_eth0_device,
@@ -23,7 +20,7 @@ static int __init ls1b_platform_init(void)
 {
 	int err;
 
-	ls1x_serial_setup();
+	ls1x_serial_setup(&ls1x_uart_device);
 
 	err = platform_add_devices(ls1b_platform_devices,
 				   ARRAY_SIZE(ls1b_platform_devices));
diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c
index 44e69e7..9f67553 100644
--- a/arch/mips/mm/c-octeon.c
+++ b/arch/mips/mm/c-octeon.c
@@ -5,6 +5,7 @@
  *
  * Copyright (C) 2005-2007 Cavium Networks
  */
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -28,6 +29,7 @@
 #include <asm/octeon/octeon.h>
 
 unsigned long long cache_err_dcache[NR_CPUS];
+EXPORT_SYMBOL_GPL(cache_err_dcache);
 
 /**
  * Octeon automatically flushes the dcache on tlb changes, so
@@ -288,42 +290,42 @@ void __cpuinit octeon_cache_init(void)
  * Handle a cache error exception
  */
 
-static void  cache_parity_error_octeon(int non_recoverable)
+static RAW_NOTIFIER_HEAD(co_cache_error_chain);
+
+int register_co_cache_error_notifier(struct notifier_block *nb)
 {
-	unsigned long coreid = cvmx_get_core_num();
-	uint64_t icache_err = read_octeon_c0_icacheerr();
-
-	pr_err("Cache error exception:\n");
-	pr_err("cp0_errorepc == %lx\n", read_c0_errorepc());
-	if (icache_err & 1) {
-		pr_err("CacheErr (Icache) == %llx\n",
-		       (unsigned long long)icache_err);
-		write_octeon_c0_icacheerr(0);
-	}
-	if (cache_err_dcache[coreid] & 1) {
-		pr_err("CacheErr (Dcache) == %llx\n",
-		       (unsigned long long)cache_err_dcache[coreid]);
-		cache_err_dcache[coreid] = 0;
-	}
+	return raw_notifier_chain_register(&co_cache_error_chain, nb);
+}
+EXPORT_SYMBOL_GPL(register_co_cache_error_notifier);
 
-	if (non_recoverable)
-		panic("Can't handle cache error: nested exception");
+int unregister_co_cache_error_notifier(struct notifier_block *nb)
+{
+	return raw_notifier_chain_unregister(&co_cache_error_chain, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_co_cache_error_notifier);
+
+static inline int co_cache_error_call_notifiers(unsigned long val)
+{
+	return raw_notifier_call_chain(&co_cache_error_chain, val, NULL);
 }
 
 /**
  * Called when the the exception is recoverable
  */
-
 asmlinkage void cache_parity_error_octeon_recoverable(void)
 {
-	cache_parity_error_octeon(0);
+	co_cache_error_call_notifiers(0);
 }
 
 /**
  * Called when the the exception is not recoverable
+ *
+ * The issue not that the cache error exception itself was non-recoverable
+ * but that due to nesting of exception may have lost some state so can't
+ * continue.
  */
-
 asmlinkage void cache_parity_error_octeon_non_recoverable(void)
 {
-	cache_parity_error_octeon(1);
+	co_cache_error_call_notifiers(1);
+	panic("Can't handle cache error: nested exception");
 }
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 4c32ede..1d6fee4 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1348,10 +1348,10 @@ static int __init cca_setup(char *str)
 {
 	get_option(&str, &cca);
 
-	return 1;
+	return 0;
 }
 
-__setup("cca=", cca_setup);
+early_param("cca", cca_setup);
 
 static void __cpuinit coherency_setup(void)
 {
@@ -1401,10 +1401,10 @@ static int __init setcoherentio(char *str)
 {
 	coherentio = 1;
 
-	return 1;
+	return 0;
 }
 
-__setup("coherentio", setcoherentio);
+early_param("coherentio", setcoherentio);
 #endif
 
 static void __cpuinit r4k_cache_error_setup(void)
diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c
index 302d779..d9be754 100644
--- a/arch/mips/mm/mmap.c
+++ b/arch/mips/mm/mmap.c
@@ -45,18 +45,6 @@ static unsigned long mmap_base(unsigned long rnd)
 	return PAGE_ALIGN(TASK_SIZE - gap - rnd);
 }
 
-static inline unsigned long COLOUR_ALIGN_DOWN(unsigned long addr,
-					      unsigned long pgoff)
-{
-	unsigned long base = addr & ~shm_align_mask;
-	unsigned long off = (pgoff << PAGE_SHIFT) & shm_align_mask;
-
-	if (base + off <= addr)
-		return base + off;
-
-	return base - off;
-}
-
 #define COLOUR_ALIGN(addr, pgoff)				\
 	((((addr) + shm_align_mask) & ~shm_align_mask) +	\
 	 (((pgoff) << PAGE_SHIFT) & shm_align_mask))
@@ -71,6 +59,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
 	struct vm_area_struct *vma;
 	unsigned long addr = addr0;
 	int do_color_align;
+	struct vm_unmapped_area_info info;
 
 	if (unlikely(len > TASK_SIZE))
 		return -ENOMEM;
@@ -107,97 +96,31 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
 			return addr;
 	}
 
-	if (dir == UP) {
-		addr = mm->mmap_base;
-		if (do_color_align)
-			addr = COLOUR_ALIGN(addr, pgoff);
-		else
-			addr = PAGE_ALIGN(addr);
+	info.length = len;
+	info.align_mask = do_color_align ? (PAGE_MASK & shm_align_mask) : 0;
+	info.align_offset = pgoff << PAGE_SHIFT;
 
-		for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
-			/* At this point:  (!vma || addr < vma->vm_end). */
-			if (TASK_SIZE - len < addr)
-				return -ENOMEM;
-			if (!vma || addr + len <= vma->vm_start)
-				return addr;
-			addr = vma->vm_end;
-			if (do_color_align)
-				addr = COLOUR_ALIGN(addr, pgoff);
-		 }
-	 } else {
-		/* check if free_area_cache is useful for us */
-		if (len <= mm->cached_hole_size) {
-			mm->cached_hole_size = 0;
-			mm->free_area_cache = mm->mmap_base;
-		}
+	if (dir == DOWN) {
+		info.flags = VM_UNMAPPED_AREA_TOPDOWN;
+		info.low_limit = PAGE_SIZE;
+		info.high_limit = mm->mmap_base;
+		addr = vm_unmapped_area(&info);
+
+		if (!(addr & ~PAGE_MASK))
+			return addr;
 
-		/*
-		 * either no address requested, or the mapping can't fit into
-		 * the requested address hole
-		 */
-		addr = mm->free_area_cache;
-		if (do_color_align) {
-			unsigned long base =
-				COLOUR_ALIGN_DOWN(addr - len, pgoff);
-			addr = base + len;
-		}
-
-		/* make sure it can fit in the remaining address space */
-		if (likely(addr > len)) {
-			vma = find_vma(mm, addr - len);
-			if (!vma || addr <= vma->vm_start) {
-				/* cache the address as a hint for next time */
-				return mm->free_area_cache = addr - len;
-			}
-		}
-
-		if (unlikely(mm->mmap_base < len))
-			goto bottomup;
-
-		addr = mm->mmap_base - len;
-		if (do_color_align)
-			addr = COLOUR_ALIGN_DOWN(addr, pgoff);
-
-		do {
-			/*
-			 * Lookup failure means no vma is above this address,
-			 * else if new region fits below vma->vm_start,
-			 * return with success:
-			 */
-			vma = find_vma(mm, addr);
-			if (likely(!vma || addr + len <= vma->vm_start)) {
-				/* cache the address as a hint for next time */
-				return mm->free_area_cache = addr;
-			}
-
-			/* remember the largest hole we saw so far */
-			if (addr + mm->cached_hole_size < vma->vm_start)
-				mm->cached_hole_size = vma->vm_start - addr;
-
-			/* try just below the current vma->vm_start */
-			addr = vma->vm_start - len;
-			if (do_color_align)
-				addr = COLOUR_ALIGN_DOWN(addr, pgoff);
-		} while (likely(len < vma->vm_start));
-
-bottomup:
 		/*
 		 * A failed mmap() very likely causes application failure,
 		 * so fall back to the bottom-up function here. This scenario
 		 * can happen with large stack limits and large mmap()
 		 * allocations.
 		 */
-		mm->cached_hole_size = ~0UL;
-		mm->free_area_cache = TASK_UNMAPPED_BASE;
-		addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
-		/*
-		 * Restore the topdown base:
-		 */
-		mm->free_area_cache = mm->mmap_base;
-		mm->cached_hole_size = ~0UL;
-
-		return addr;
 	}
+
+	info.flags = 0;
+	info.low_limit = mm->mmap_base;
+	info.high_limit = TASK_SIZE;
+	return vm_unmapped_area(&info);
 }
 
 unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr0,
diff --git a/arch/mips/mm/pgtable-64.c b/arch/mips/mm/pgtable-64.c
index 2540779..ee331bb 100644
--- a/arch/mips/mm/pgtable-64.c
+++ b/arch/mips/mm/pgtable-64.c
@@ -11,6 +11,7 @@
 #include <asm/fixmap.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
 
 void pgd_init(unsigned long page)
 {
@@ -61,6 +62,36 @@ void pmd_init(unsigned long addr, unsigned long pagetable)
 }
 #endif
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+void pmdp_splitting_flush(struct vm_area_struct *vma,
+			 unsigned long address,
+			 pmd_t *pmdp)
+{
+	if (!pmd_trans_splitting(*pmdp)) {
+		pmd_t pmd = pmd_mksplitting(*pmdp);
+		set_pmd_at(vma->vm_mm, address, pmdp, pmd);
+	}
+}
+
+#endif
+
+pmd_t mk_pmd(struct page *page, pgprot_t prot)
+{
+	pmd_t pmd;
+
+	pmd_val(pmd) = (page_to_pfn(page) << _PFN_SHIFT) | pgprot_val(prot);
+
+	return pmd;
+}
+
+void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+		pmd_t *pmdp, pmd_t pmd)
+{
+	*pmdp = pmd;
+	flush_tlb_all();
+}
+
 void __init pagetable_init(void)
 {
 	unsigned long vaddr;
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 4b9b935..94ad86d 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -305,7 +305,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
 	pudp = pud_offset(pgdp, address);
 	pmdp = pmd_offset(pudp, address);
 	idx = read_c0_index();
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 	/* this could be a huge page  */
 	if (pmd_huge(*pmdp)) {
 		unsigned long lo;
@@ -377,6 +377,26 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
 	EXIT_CRITICAL(flags);
 }
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+int __init has_transparent_hugepage(void)
+{
+	unsigned int mask;
+	unsigned long flags;
+
+	ENTER_CRITICAL(flags);
+	write_c0_pagemask(PM_HUGE_MASK);
+	back_to_back_c0_hazard();
+	mask = read_c0_pagemask();
+	write_c0_pagemask(PM_DEFAULT_MASK);
+
+	EXIT_CRITICAL(flags);
+
+	return mask == PM_HUGE_MASK;
+}
+
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE  */
+
 static int __cpuinitdata ntlb;
 static int __init set_ntlb(char *str)
 {
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 2833dcb..80b85a4 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -158,7 +158,7 @@ enum label_id {
 	label_smp_pgtable_change,
 	label_r3000_write_probe_fail,
 	label_large_segbits_fault,
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 	label_tlb_huge_update,
 #endif
 };
@@ -177,13 +177,15 @@ UASM_L_LA(_nopage_tlbm)
 UASM_L_LA(_smp_pgtable_change)
 UASM_L_LA(_r3000_write_probe_fail)
 UASM_L_LA(_large_segbits_fault)
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 UASM_L_LA(_tlb_huge_update)
 #endif
 
 static int __cpuinitdata hazard_instance;
 
-static void uasm_bgezl_hazard(u32 **p, struct uasm_reloc **r, int instance)
+static void __cpuinit uasm_bgezl_hazard(u32 **p,
+					struct uasm_reloc **r,
+					int instance)
 {
 	switch (instance) {
 	case 0 ... 7:
@@ -194,7 +196,9 @@ static void uasm_bgezl_hazard(u32 **p, struct uasm_reloc **r, int instance)
 	}
 }
 
-static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance)
+static void __cpuinit uasm_bgezl_label(struct uasm_label **l,
+				       u32 **p,
+				       int instance)
 {
 	switch (instance) {
 	case 0 ... 7:
@@ -206,19 +210,55 @@ static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance)
 }
 
 /*
- * For debug purposes.
+ * pgtable bits are assigned dynamically depending on processor feature
+ * and statically based on kernel configuration.  This spits out the actual
+ * values the kernel is using.  Required to make sense from disassembled
+ * TLB exception handlers.
  */
-static inline void dump_handler(const u32 *handler, int count)
+static void output_pgtable_bits_defines(void)
+{
+#define pr_define(fmt, ...)					\
+	pr_debug("#define " fmt, ##__VA_ARGS__)
+
+	pr_debug("#include <asm/asm.h>\n");
+	pr_debug("#include <asm/regdef.h>\n");
+	pr_debug("\n");
+
+	pr_define("_PAGE_PRESENT_SHIFT %d\n", _PAGE_PRESENT_SHIFT);
+	pr_define("_PAGE_READ_SHIFT %d\n", _PAGE_READ_SHIFT);
+	pr_define("_PAGE_WRITE_SHIFT %d\n", _PAGE_WRITE_SHIFT);
+	pr_define("_PAGE_ACCESSED_SHIFT %d\n", _PAGE_ACCESSED_SHIFT);
+	pr_define("_PAGE_MODIFIED_SHIFT %d\n", _PAGE_MODIFIED_SHIFT);
+	pr_define("_PAGE_HUGE_SHIFT %d\n", _PAGE_HUGE_SHIFT);
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
+	pr_define("_PAGE_SPLITTING_SHIFT %d\n", _PAGE_SPLITTING_SHIFT);
+#endif
+	if (cpu_has_rixi) {
+		pr_define("_PAGE_NO_EXEC_SHIFT %d\n", _PAGE_NO_EXEC_SHIFT);
+		pr_define("_PAGE_NO_READ_SHIFT %d\n", _PAGE_NO_READ_SHIFT);
+	}
+	pr_define("_PAGE_GLOBAL_SHIFT %d\n", _PAGE_GLOBAL_SHIFT);
+	pr_define("_PAGE_VALID_SHIFT %d\n", _PAGE_VALID_SHIFT);
+	pr_define("_PAGE_DIRTY_SHIFT %d\n", _PAGE_DIRTY_SHIFT);
+	pr_define("_PFN_SHIFT %d\n", _PFN_SHIFT);
+	pr_debug("\n");
+}
+
+static inline void dump_handler(const char *symbol, const u32 *handler, int count)
 {
 	int i;
 
+	pr_debug("LEAF(%s)\n", symbol);
+
 	pr_debug("\t.set push\n");
 	pr_debug("\t.set noreorder\n");
 
 	for (i = 0; i < count; i++)
-		pr_debug("\t%p\t.word 0x%08x\n", &handler[i], handler[i]);
+		pr_debug("\t.word\t0x%08x\t\t# %p\n", handler[i], &handler[i]);
 
-	pr_debug("\t.set pop\n");
+	pr_debug("\t.set\tpop\n");
+
+	pr_debug("\tEND(%s)\n", symbol);
 }
 
 /* The only general purpose registers allowed in TLB handlers. */
@@ -401,7 +441,7 @@ static void __cpuinit build_r3000_tlb_refill_handler(void)
 
 	memcpy((void *)ebase, tlb_handler, 0x80);
 
-	dump_handler((u32 *)ebase, 32);
+	dump_handler("r3000_tlb_refill", (u32 *)ebase, 32);
 }
 #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
 
@@ -443,7 +483,6 @@ static void __cpuinit __maybe_unused build_tlb_probe_entry(u32 **p)
 	case CPU_R4600:
 	case CPU_R4700:
 	case CPU_R5000:
-	case CPU_R5000A:
 	case CPU_NEVADA:
 		uasm_i_nop(p);
 		uasm_i_tlbp(p);
@@ -517,7 +556,6 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
 		break;
 
 	case CPU_R5000:
-	case CPU_R5000A:
 	case CPU_NEVADA:
 		uasm_i_nop(p); /* QED specifies 2 nops hazard */
 		uasm_i_nop(p); /* QED specifies 2 nops hazard */
@@ -629,7 +667,7 @@ static __cpuinit __maybe_unused void build_convert_pte_to_entrylo(u32 **p,
 	}
 }
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 
 static __cpuinit void build_restore_pagemask(u32 **p,
 					     struct uasm_reloc **r,
@@ -755,7 +793,7 @@ static __cpuinit void build_huge_handler_tail(u32 **p,
 	build_huge_update_entries(p, pte, ptr);
 	build_huge_tlb_write_entry(p, l, r, pte, tlb_indexed, 0);
 }
-#endif /* CONFIG_HUGETLB_PAGE */
+#endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */
 
 #ifdef CONFIG_64BIT
 /*
@@ -1200,7 +1238,7 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l,
 	/* Adjust the context during the load latency. */
 	build_adjust_context(p, tmp);
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 	uasm_il_bbit1(p, r, scratch, ilog2(_PAGE_HUGE), label_tlb_huge_update);
 	/*
 	 * The in the LWX case we don't want to do the load in the
@@ -1209,7 +1247,7 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l,
 	 */
 	if (use_lwx_insns())
 		uasm_i_nop(p);
-#endif /* CONFIG_HUGETLB_PAGE */
+#endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */
 
 
 	/* build_update_entries */
@@ -1312,7 +1350,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
 		build_get_pgde32(&p, K0, K1); /* get pgd in K1 */
 #endif
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 		build_is_huge_pte(&p, &r, K0, K1, label_tlb_huge_update);
 #endif
 
@@ -1322,7 +1360,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
 		uasm_l_leave(&l, p);
 		uasm_i_eret(&p); /* return from trap */
 	}
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 	uasm_l_tlb_huge_update(&l, p);
 	build_huge_update_entries(&p, htlb_info.huge_pte, K1);
 	build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random,
@@ -1367,7 +1405,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
 		uasm_copy_handler(relocs, labels, tlb_handler, p, f);
 		final_len = p - tlb_handler;
 	} else {
-#if defined(CONFIG_HUGETLB_PAGE)
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 		const enum label_id ls = label_tlb_huge_update;
 #else
 		const enum label_id ls = label_vmalloc;
@@ -1436,7 +1474,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
 
 	memcpy((void *)ebase, final_handler, 0x100);
 
-	dump_handler((u32 *)ebase, 64);
+	dump_handler("r4000_tlb_refill", (u32 *)ebase, 64);
 }
 
 /*
@@ -1493,7 +1531,8 @@ static void __cpuinit build_r4000_setup_pgd(void)
 	pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n",
 		 (unsigned int)(p - tlbmiss_handler_setup_pgd));
 
-	dump_handler(tlbmiss_handler_setup_pgd,
+	dump_handler("tlbmiss_handler",
+		     tlbmiss_handler_setup_pgd,
 		     ARRAY_SIZE(tlbmiss_handler_setup_pgd));
 }
 #endif
@@ -1763,7 +1802,7 @@ static void __cpuinit build_r3000_tlb_load_handler(void)
 	pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
 		 (unsigned int)(p - handle_tlbl));
 
-	dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl));
+	dump_handler("r3000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl));
 }
 
 static void __cpuinit build_r3000_tlb_store_handler(void)
@@ -1793,7 +1832,7 @@ static void __cpuinit build_r3000_tlb_store_handler(void)
 	pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
 		 (unsigned int)(p - handle_tlbs));
 
-	dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs));
+	dump_handler("r3000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs));
 }
 
 static void __cpuinit build_r3000_tlb_modify_handler(void)
@@ -1823,7 +1862,7 @@ static void __cpuinit build_r3000_tlb_modify_handler(void)
 	pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
 		 (unsigned int)(p - handle_tlbm));
 
-	dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm));
+	dump_handler("r3000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm));
 }
 #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
 
@@ -1842,7 +1881,7 @@ build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l,
 	build_get_pgde32(p, wr.r1, wr.r2); /* get pgd in ptr */
 #endif
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 	/*
 	 * For huge tlb entries, pmd doesn't contain an address but
 	 * instead contains the tlb pte. Check the PAGE_HUGE bit and
@@ -1958,7 +1997,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
 	build_make_valid(&p, &r, wr.r1, wr.r2);
 	build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 	/*
 	 * This is the entry point when build_r4000_tlbchange_handler_head
 	 * spots a huge page.
@@ -2030,7 +2069,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
 	pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
 		 (unsigned int)(p - handle_tlbl));
 
-	dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl));
+	dump_handler("r4000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl));
 }
 
 static void __cpuinit build_r4000_tlb_store_handler(void)
@@ -2051,7 +2090,7 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
 	build_make_write(&p, &r, wr.r1, wr.r2);
 	build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 	/*
 	 * This is the entry point when
 	 * build_r4000_tlbchange_handler_head spots a huge page.
@@ -2077,7 +2116,7 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
 	pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
 		 (unsigned int)(p - handle_tlbs));
 
-	dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs));
+	dump_handler("r4000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs));
 }
 
 static void __cpuinit build_r4000_tlb_modify_handler(void)
@@ -2099,7 +2138,7 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
 	build_make_write(&p, &r, wr.r1, wr.r2);
 	build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
-#ifdef CONFIG_HUGETLB_PAGE
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 	/*
 	 * This is the entry point when
 	 * build_r4000_tlbchange_handler_head spots a huge page.
@@ -2125,7 +2164,7 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
 	pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
 		 (unsigned int)(p - handle_tlbm));
 
-	dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm));
+	dump_handler("r4000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm));
 }
 
 void __cpuinit build_tlb_refill_handler(void)
@@ -2137,6 +2176,8 @@ void __cpuinit build_tlb_refill_handler(void)
 	 */
 	static int run_once = 0;
 
+	output_pgtable_bits_defines();
+
 #ifdef CONFIG_64BIT
 	check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3);
 #endif
diff --git a/arch/mips/netlogic/Kconfig b/arch/mips/netlogic/Kconfig
index 8059eb7..3c05bf9 100644
--- a/arch/mips/netlogic/Kconfig
+++ b/arch/mips/netlogic/Kconfig
@@ -9,6 +9,34 @@ config DT_XLP_EVP
 	  This DTB will be used if the firmware does not pass in a DTB
           pointer to the kernel.  The corresponding DTS file is at
           arch/mips/netlogic/dts/xlp_evp.dts
+
+config NLM_MULTINODE
+	bool "Support for multi-chip boards"
+	depends on NLM_XLP_BOARD
+	default n
+	help
+	  Add support for boards with 2 or 4 XLPs connected over ICI.
+
+if NLM_MULTINODE
+choice
+	prompt "Number of XLPs on the board"
+	default NLM_MULTINODE_2
+	help
+	  In the multi-node case, specify the number of SoCs on the board.
+
+config NLM_MULTINODE_2
+	bool "Dual-XLP board"
+	help
+	  Support boards with upto two XLPs connected over ICI.
+
+config NLM_MULTINODE_4
+	bool "Quad-XLP board"
+	help
+	  Support boards with upto four XLPs connected over ICI.
+
+endchoice
+
+endif
 endif
 
 config NLM_COMMON
diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c
index e52bfcb..00dcc7a 100644
--- a/arch/mips/netlogic/common/irq.c
+++ b/arch/mips/netlogic/common/irq.c
@@ -36,7 +36,6 @@
 #include <linux/init.h>
 #include <linux/linkage.h>
 #include <linux/interrupt.h>
-#include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/irq.h>
@@ -59,68 +58,70 @@
 #elif defined(CONFIG_CPU_XLR)
 #include <asm/netlogic/xlr/iomap.h>
 #include <asm/netlogic/xlr/pic.h>
+#include <asm/netlogic/xlr/fmn.h>
 #else
 #error "Unknown CPU"
 #endif
-/*
- * These are the routines that handle all the low level interrupt stuff.
- * Actions handled here are: initialization of the interrupt map, requesting of
- * interrupt lines by handlers, dispatching if interrupts to handlers, probing
- * for interrupt lines
- */
 
-/* Globals */
-static uint64_t nlm_irq_mask;
-static DEFINE_SPINLOCK(nlm_pic_lock);
+#ifdef CONFIG_SMP
+#define SMP_IRQ_MASK	((1ULL << IRQ_IPI_SMP_FUNCTION) | \
+				 (1ULL << IRQ_IPI_SMP_RESCHEDULE))
+#else
+#define SMP_IRQ_MASK	0
+#endif
+#define PERCPU_IRQ_MASK	(SMP_IRQ_MASK | (1ull << IRQ_TIMER) | \
+				(1ull << IRQ_FMN))
+
+struct nlm_pic_irq {
+	void	(*extra_ack)(struct irq_data *);
+	struct	nlm_soc_info *node;
+	int	picirq;
+	int	irt;
+	int	flags;
+};
 
 static void xlp_pic_enable(struct irq_data *d)
 {
 	unsigned long flags;
-	int irt;
+	struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
 
-	irt = nlm_irq_to_irt(d->irq);
-	if (irt == -1)
-		return;
-	spin_lock_irqsave(&nlm_pic_lock, flags);
-	nlm_pic_enable_irt(nlm_pic_base, irt);
-	spin_unlock_irqrestore(&nlm_pic_lock, flags);
+	BUG_ON(!pd);
+	spin_lock_irqsave(&pd->node->piclock, flags);
+	nlm_pic_enable_irt(pd->node->picbase, pd->irt);
+	spin_unlock_irqrestore(&pd->node->piclock, flags);
 }
 
 static void xlp_pic_disable(struct irq_data *d)
 {
+	struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
 	unsigned long flags;
-	int irt;
 
-	irt = nlm_irq_to_irt(d->irq);
-	if (irt == -1)
-		return;
-	spin_lock_irqsave(&nlm_pic_lock, flags);
-	nlm_pic_disable_irt(nlm_pic_base, irt);
-	spin_unlock_irqrestore(&nlm_pic_lock, flags);
+	BUG_ON(!pd);
+	spin_lock_irqsave(&pd->node->piclock, flags);
+	nlm_pic_disable_irt(pd->node->picbase, pd->irt);
+	spin_unlock_irqrestore(&pd->node->piclock, flags);
 }
 
 static void xlp_pic_mask_ack(struct irq_data *d)
 {
-	uint64_t mask = 1ull << d->irq;
+	struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
+	uint64_t mask = 1ull << pd->picirq;
 
 	write_c0_eirr(mask);            /* ack by writing EIRR */
 }
 
 static void xlp_pic_unmask(struct irq_data *d)
 {
-	void *hd = irq_data_get_irq_handler_data(d);
-	int irt;
+	struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
 
-	irt = nlm_irq_to_irt(d->irq);
-	if (irt == -1)
+	if (!pd)
 		return;
 
-	if (hd) {
-		void (*extra_ack)(void *) = hd;
-		extra_ack(d);
-	}
+	if (pd->extra_ack)
+		pd->extra_ack(d);
+
 	/* Ack is a single write, no need to lock */
-	nlm_pic_ack(nlm_pic_base, irt);
+	nlm_pic_ack(pd->node->picbase, pd->irt);
 }
 
 static struct irq_chip xlp_pic = {
@@ -174,64 +175,108 @@ struct irq_chip nlm_cpu_intr = {
 	.irq_eoi	= cpuintr_ack,
 };
 
-void __init init_nlm_common_irqs(void)
+static void __init nlm_init_percpu_irqs(void)
 {
-	int i, irq, irt;
+	int i;
 
 	for (i = 0; i < PIC_IRT_FIRST_IRQ; i++)
 		irq_set_chip_and_handler(i, &nlm_cpu_intr, handle_percpu_irq);
-
-	for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ ; i++)
-		irq_set_chip_and_handler(i, &xlp_pic, handle_level_irq);
-
 #ifdef CONFIG_SMP
 	irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr,
 			 nlm_smp_function_ipi_handler);
 	irq_set_chip_and_handler(IRQ_IPI_SMP_RESCHEDULE, &nlm_cpu_intr,
 			 nlm_smp_resched_ipi_handler);
-	nlm_irq_mask |=
-	    ((1ULL << IRQ_IPI_SMP_FUNCTION) | (1ULL << IRQ_IPI_SMP_RESCHEDULE));
 #endif
+}
+
+void nlm_setup_pic_irq(int node, int picirq, int irq, int irt)
+{
+	struct nlm_pic_irq *pic_data;
+	int xirq;
+
+	xirq = nlm_irq_to_xirq(node, irq);
+	pic_data = kzalloc(sizeof(*pic_data), GFP_KERNEL);
+	BUG_ON(pic_data == NULL);
+	pic_data->irt = irt;
+	pic_data->picirq = picirq;
+	pic_data->node = nlm_get_node(node);
+	irq_set_chip_and_handler(xirq, &xlp_pic, handle_level_irq);
+	irq_set_handler_data(xirq, pic_data);
+}
+
+void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))
+{
+	struct nlm_pic_irq *pic_data;
+	int xirq;
+
+	xirq = nlm_irq_to_xirq(node, irq);
+	pic_data = irq_get_handler_data(xirq);
+	pic_data->extra_ack = xack;
+}
 
-	for (irq = PIC_IRT_FIRST_IRQ; irq <= PIC_IRT_LAST_IRQ; irq++) {
-		irt = nlm_irq_to_irt(irq);
+static void nlm_init_node_irqs(int node)
+{
+	int i, irt;
+	uint64_t irqmask;
+	struct nlm_soc_info *nodep;
+
+	pr_info("Init IRQ for node %d\n", node);
+	nodep = nlm_get_node(node);
+	irqmask = PERCPU_IRQ_MASK;
+	for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) {
+		irt = nlm_irq_to_irt(i);
 		if (irt == -1)
 			continue;
-		nlm_irq_mask |= (1ULL << irq);
-		nlm_pic_init_irt(nlm_pic_base, irt, irq, 0);
+		nlm_setup_pic_irq(node, i, i, irt);
+		/* set interrupts to first cpu in node */
+		nlm_pic_init_irt(nodep->picbase, irt, i,
+					node * NLM_CPUS_PER_NODE);
+		irqmask |= (1ull << i);
 	}
-
-	nlm_irq_mask |= (1ULL << IRQ_TIMER);
+	nodep->irqmask = irqmask;
 }
 
 void __init arch_init_irq(void)
 {
 	/* Initialize the irq descriptors */
-	init_nlm_common_irqs();
-
-	write_c0_eimr(nlm_irq_mask);
+	nlm_init_percpu_irqs();
+	nlm_init_node_irqs(0);
+	write_c0_eimr(nlm_current_node()->irqmask);
+#if defined(CONFIG_CPU_XLR)
+	nlm_setup_fmn_irq();
+#endif
 }
 
-void __cpuinit nlm_smp_irq_init(void)
+void nlm_smp_irq_init(int hwcpuid)
 {
-	/* set interrupt mask for non-zero cpus */
-	write_c0_eimr(nlm_irq_mask);
+	int node, cpu;
+
+	node = hwcpuid / NLM_CPUS_PER_NODE;
+	cpu  = hwcpuid % NLM_CPUS_PER_NODE;
+
+	if (cpu == 0 && node != 0)
+		nlm_init_node_irqs(node);
+	write_c0_eimr(nlm_current_node()->irqmask);
 }
 
 asmlinkage void plat_irq_dispatch(void)
 {
 	uint64_t eirr;
-	int i;
+	int i, node;
 
+	node = nlm_nodeid();
 	eirr = read_c0_eirr() & read_c0_eimr();
-	if (eirr & (1 << IRQ_TIMER)) {
-		do_IRQ(IRQ_TIMER);
-		return;
-	}
 
 	i = __ilog2_u64(eirr);
 	if (i == -1)
 		return;
 
-	do_IRQ(i);
+	/* per-CPU IRQs don't need translation */
+	if (eirr & PERCPU_IRQ_MASK) {
+		do_IRQ(i);
+		return;
+	}
+
+	/* top level irq handling */
+	do_IRQ(nlm_irq_to_xirq(node, i));
 }
diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index fab316d..a080d9e 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -59,12 +59,17 @@
 
 void nlm_send_ipi_single(int logical_cpu, unsigned int action)
 {
-	int cpu = cpu_logical_map(logical_cpu);
+	int cpu, node;
+	uint64_t picbase;
+
+	cpu = cpu_logical_map(logical_cpu);
+	node = cpu / NLM_CPUS_PER_NODE;
+	picbase = nlm_get_node(node)->picbase;
 
 	if (action & SMP_CALL_FUNCTION)
-		nlm_pic_send_ipi(nlm_pic_base, cpu, IRQ_IPI_SMP_FUNCTION, 0);
+		nlm_pic_send_ipi(picbase, cpu, IRQ_IPI_SMP_FUNCTION, 0);
 	if (action & SMP_RESCHEDULE_YOURSELF)
-		nlm_pic_send_ipi(nlm_pic_base, cpu, IRQ_IPI_SMP_RESCHEDULE, 0);
+		nlm_pic_send_ipi(picbase, cpu, IRQ_IPI_SMP_RESCHEDULE, 0);
 }
 
 void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action)
@@ -96,11 +101,12 @@ void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc)
 void nlm_early_init_secondary(int cpu)
 {
 	change_c0_config(CONF_CM_CMASK, 0x3);
-	write_c0_ebase((uint32_t)nlm_common_ebase);
 #ifdef CONFIG_CPU_XLP
-	if (hard_smp_processor_id() % 4 == 0)
+	/* mmu init, once per core */
+	if (cpu % NLM_THREADS_PER_CORE == 0)
 		xlp_mmu_init();
 #endif
+	write_c0_ebase(nlm_current_node()->ebase);
 }
 
 /*
@@ -108,8 +114,12 @@ void nlm_early_init_secondary(int cpu)
  */
 static void __cpuinit nlm_init_secondary(void)
 {
-	current_cpu_data.core = hard_smp_processor_id() / 4;
-	nlm_smp_irq_init();
+	int hwtid;
+
+	hwtid = hard_smp_processor_id();
+	current_cpu_data.core = hwtid / NLM_THREADS_PER_CORE;
+	nlm_percpu_init(hwtid);
+	nlm_smp_irq_init(hwtid);
 }
 
 void nlm_prepare_cpus(unsigned int max_cpus)
@@ -120,9 +130,6 @@ void nlm_prepare_cpus(unsigned int max_cpus)
 
 void nlm_smp_finish(void)
 {
-#ifdef notyet
-	nlm_common_msgring_cpu_init();
-#endif
 	local_irq_enable();
 }
 
@@ -142,27 +149,27 @@ cpumask_t phys_cpu_present_map;
 
 void nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
 {
-	unsigned long gp = (unsigned long)task_thread_info(idle);
-	unsigned long sp = (unsigned long)__KSTK_TOS(idle);
-	int cpu = cpu_logical_map(logical_cpu);
+	int cpu, node;
 
-	nlm_next_sp = sp;
-	nlm_next_gp = gp;
+	cpu = cpu_logical_map(logical_cpu);
+	node = cpu / NLM_CPUS_PER_NODE;
+	nlm_next_sp = (unsigned long)__KSTK_TOS(idle);
+	nlm_next_gp = (unsigned long)task_thread_info(idle);
 
-	/* barrier */
+	/* barrier for sp/gp store above */
 	__sync();
-	nlm_pic_send_ipi(nlm_pic_base, cpu, 1, 1);
+	nlm_pic_send_ipi(nlm_get_node(node)->picbase, cpu, 1, 1);  /* NMI */
 }
 
 void __init nlm_smp_setup(void)
 {
 	unsigned int boot_cpu;
-	int num_cpus, i;
+	int num_cpus, i, ncore;
 
 	boot_cpu = hard_smp_processor_id();
-	cpus_clear(phys_cpu_present_map);
+	cpumask_clear(&phys_cpu_present_map);
 
-	cpu_set(boot_cpu, phys_cpu_present_map);
+	cpumask_set_cpu(boot_cpu, &phys_cpu_present_map);
 	__cpu_number_map[boot_cpu] = 0;
 	__cpu_logical_map[0] = boot_cpu;
 	set_cpu_possible(0, true);
@@ -174,7 +181,7 @@ void __init nlm_smp_setup(void)
 		 * it is only set for ASPs (see smpboot.S)
 		 */
 		if (nlm_cpu_ready[i]) {
-			cpu_set(i, phys_cpu_present_map);
+			cpumask_set_cpu(i, &phys_cpu_present_map);
 			__cpu_number_map[i] = num_cpus;
 			__cpu_logical_map[num_cpus] = i;
 			set_cpu_possible(num_cpus, true);
@@ -182,20 +189,28 @@ void __init nlm_smp_setup(void)
 		}
 	}
 
+	/* check with the cores we have worken up */
+	for (ncore = 0, i = 0; i < NLM_NR_NODES; i++)
+		ncore += hweight32(nlm_get_node(i)->coremask);
+
 	pr_info("Phys CPU present map: %lx, possible map %lx\n",
-		(unsigned long)phys_cpu_present_map.bits[0],
+		(unsigned long)cpumask_bits(&phys_cpu_present_map)[0],
 		(unsigned long)cpumask_bits(cpu_possible_mask)[0]);
 
-	pr_info("Detected %i Slave CPU(s)\n", num_cpus);
+	pr_info("Detected (%dc%dt) %d Slave CPU(s)\n", ncore,
+		nlm_threads_per_core, num_cpus);
 	nlm_set_nmi_handler(nlm_boot_secondary_cpus);
 }
 
-static int nlm_parse_cpumask(u32 cpu_mask)
+static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
 {
 	uint32_t core0_thr_mask, core_thr_mask;
-	int threadmode, i;
+	int threadmode, i, j;
 
-	core0_thr_mask = cpu_mask & 0xf;
+	core0_thr_mask = 0;
+	for (i = 0; i < NLM_THREADS_PER_CORE; i++)
+		if (cpumask_test_cpu(i, wakeup_mask))
+			core0_thr_mask |= (1 << i);
 	switch (core0_thr_mask) {
 	case 1:
 		nlm_threads_per_core = 1;
@@ -214,25 +229,23 @@ static int nlm_parse_cpumask(u32 cpu_mask)
 	}
 
 	/* Verify other cores CPU masks */
-	nlm_coremask = 1;
-	nlm_cpumask = core0_thr_mask;
-	for (i = 1; i < 8; i++) {
-		core_thr_mask = (cpu_mask >> (i * 4)) & 0xf;
-		if (core_thr_mask) {
-			if (core_thr_mask != core0_thr_mask)
+	for (i = 0; i < NR_CPUS; i += NLM_THREADS_PER_CORE) {
+		core_thr_mask = 0;
+		for (j = 0; j < NLM_THREADS_PER_CORE; j++)
+			if (cpumask_test_cpu(i + j, wakeup_mask))
+				core_thr_mask |= (1 << j);
+		if (core_thr_mask != 0 && core_thr_mask != core0_thr_mask)
 				goto unsupp;
-			nlm_coremask |= 1 << i;
-			nlm_cpumask |= core0_thr_mask << (4 * i);
-		}
 	}
 	return threadmode;
 
 unsupp:
-	panic("Unsupported CPU mask %x\n", cpu_mask);
+	panic("Unsupported CPU mask %lx\n",
+		(unsigned long)cpumask_bits(wakeup_mask)[0]);
 	return 0;
 }
 
-int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask)
+int __cpuinit nlm_wakeup_secondary_cpus(void)
 {
 	unsigned long reset_vec;
 	char *reset_data;
@@ -244,7 +257,7 @@ int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask)
 			(nlm_reset_entry_end - nlm_reset_entry));
 
 	/* verify the mask and setup core config variables */
-	threadmode = nlm_parse_cpumask(wakeup_mask);
+	threadmode = nlm_parse_cpumask(&nlm_cpumask);
 
 	/* Setup CPU init parameters */
 	reset_data = (char *)CKSEG1ADDR(RESET_DATA_PHYS);
diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S
index a13355c..a0b7487 100644
--- a/arch/mips/netlogic/common/smpboot.S
+++ b/arch/mips/netlogic/common/smpboot.S
@@ -61,7 +61,7 @@
 	li	t0, LSU_DEFEATURE
 	mfcr	t1, t0
 
-	lui	t2, 0x4080	/* Enable Unaligned Access, L2HPE */
+	lui	t2, 0xc080	/* SUE, Enable Unaligned Access, L2HPE */
 	or	t1, t1, t2
 #ifdef XLP_AX_WORKAROUND
 	li	t2, ~0xe	/* S1RCM */
@@ -186,7 +186,7 @@ EXPORT(nlm_boot_siblings)
 	* jump to the secondary wait function.
 	*/
 	mfc0	v0, CP0_EBASE, 1
-	andi	v0, 0x7f		/* v0 <- node/core */
+	andi	v0, 0x3ff		/* v0 <- node/core */
 
 	/* Init MMU in the first thread after changing THREAD_MODE
 	 * register (Ax Errata?)
@@ -263,6 +263,8 @@ NESTED(nlm_boot_secondary_cpus, 16, sp)
 	PTR_L	gp, 0(t1)
 
 	/* a0 has the processor id */
+	mfc0	a0, CP0_EBASE, 1
+	andi	a0, 0x3ff		/* a0 <- node/core */
 	PTR_LA	t0, nlm_early_init_secondary
 	jalr	t0
 	nop
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index 6c65ac7..529e747 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -40,23 +40,23 @@
 #include <asm/mipsregs.h>
 #include <asm/time.h>
 
+#include <asm/netlogic/common.h>
 #include <asm/netlogic/haldefs.h>
 #include <asm/netlogic/xlp-hal/iomap.h>
 #include <asm/netlogic/xlp-hal/xlp.h>
 #include <asm/netlogic/xlp-hal/pic.h>
 #include <asm/netlogic/xlp-hal/sys.h>
 
-/* These addresses are computed by the nlm_hal_init() */
-uint64_t nlm_io_base;
-uint64_t nlm_sys_base;
-uint64_t nlm_pic_base;
-
 /* Main initialization */
-void nlm_hal_init(void)
+void nlm_node_init(int node)
 {
-	nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE);
-	nlm_sys_base = nlm_get_sys_regbase(0);	/* node 0 */
-	nlm_pic_base = nlm_get_pic_regbase(0);	/* node 0 */
+	struct nlm_soc_info *nodep;
+
+	nodep = nlm_get_node(node);
+	nodep->sysbase = nlm_get_sys_regbase(node);
+	nodep->picbase = nlm_get_pic_regbase(node);
+	nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
+	spin_lock_init(&nodep->piclock);
 }
 
 int nlm_irq_to_irt(int irq)
@@ -100,52 +100,15 @@ int nlm_irq_to_irt(int irq)
 	}
 }
 
-int nlm_irt_to_irq(int irt)
-{
-	switch (irt) {
-	case PIC_IRT_UART_0_INDEX:
-		return PIC_UART_0_IRQ;
-	case PIC_IRT_UART_1_INDEX:
-		return PIC_UART_1_IRQ;
-	case PIC_IRT_PCIE_LINK_0_INDEX:
-	       return PIC_PCIE_LINK_0_IRQ;
-	case PIC_IRT_PCIE_LINK_1_INDEX:
-	       return PIC_PCIE_LINK_1_IRQ;
-	case PIC_IRT_PCIE_LINK_2_INDEX:
-	       return PIC_PCIE_LINK_2_IRQ;
-	case PIC_IRT_PCIE_LINK_3_INDEX:
-	       return PIC_PCIE_LINK_3_IRQ;
-	case PIC_IRT_EHCI_0_INDEX:
-		return PIC_EHCI_0_IRQ;
-	case PIC_IRT_EHCI_1_INDEX:
-		return PIC_EHCI_1_IRQ;
-	case PIC_IRT_OHCI_0_INDEX:
-		return PIC_OHCI_0_IRQ;
-	case PIC_IRT_OHCI_1_INDEX:
-		return PIC_OHCI_1_IRQ;
-	case PIC_IRT_OHCI_2_INDEX:
-		return PIC_OHCI_2_IRQ;
-	case PIC_IRT_OHCI_3_INDEX:
-		return PIC_OHCI_3_IRQ;
-	case PIC_IRT_MMC_INDEX:
-	       return PIC_MMC_IRQ;
-	case PIC_IRT_I2C_0_INDEX:
-		return PIC_I2C_0_IRQ;
-	case PIC_IRT_I2C_1_INDEX:
-		return PIC_I2C_1_IRQ;
-	default:
-		return -1;
-	}
-}
-
-unsigned int nlm_get_core_frequency(int core)
+unsigned int nlm_get_core_frequency(int node, int core)
 {
 	unsigned int pll_divf, pll_divr, dfs_div, ext_div;
 	unsigned int rstval, dfsval, denom;
-	uint64_t num;
+	uint64_t num, sysbase;
 
-	rstval = nlm_read_sys_reg(nlm_sys_base, SYS_POWER_ON_RESET_CFG);
-	dfsval = nlm_read_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIV_VALUE);
+	sysbase = nlm_get_node(node)->sysbase;
+	rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG);
+	dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE);
 	pll_divf = ((rstval >> 10) & 0x7f) + 1;
 	pll_divr = ((rstval >> 8)  & 0x3) + 1;
 	ext_div  = ((rstval >> 30) & 0x3) + 1;
@@ -159,5 +122,5 @@ unsigned int nlm_get_core_frequency(int core)
 
 unsigned int nlm_get_cpu_frequency(void)
 {
-	return nlm_get_core_frequency(0);
+	return nlm_get_core_frequency(0, 0);
 }
diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c
index d899709..4894d62 100644
--- a/arch/mips/netlogic/xlp/setup.c
+++ b/arch/mips/netlogic/xlp/setup.c
@@ -52,26 +52,40 @@
 #include <asm/netlogic/xlp-hal/xlp.h>
 #include <asm/netlogic/xlp-hal/sys.h>
 
-unsigned long nlm_common_ebase = 0x0;
-
-/* default to uniprocessor */
-uint32_t nlm_coremask = 1, nlm_cpumask  = 1;
-int  nlm_threads_per_core = 1;
+uint64_t nlm_io_base;
+struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
+cpumask_t nlm_cpumask = CPU_MASK_CPU0;
+unsigned int nlm_threads_per_core;
 extern u32 __dtb_start[];
 
 static void nlm_linux_exit(void)
 {
-	nlm_write_sys_reg(nlm_sys_base, SYS_CHIP_RESET, 1);
+	uint64_t sysbase = nlm_get_node(0)->sysbase;
+
+	nlm_write_sys_reg(sysbase, SYS_CHIP_RESET, 1);
 	for ( ; ; )
 		cpu_wait();
 }
 
 void __init plat_mem_setup(void)
 {
+	void *fdtp;
+
 	panic_timeout	= 5;
 	_machine_restart = (void (*)(char *))nlm_linux_exit;
 	_machine_halt	= nlm_linux_exit;
 	pm_power_off	= nlm_linux_exit;
+
+	/*
+	 * If no FDT pointer is passed in, use the built-in FDT.
+	 * device_tree_init() does not handle CKSEG0 pointers in
+	 * 64-bit, so convert pointer.
+	 */
+	fdtp = (void *)(long)fw_arg0;
+	if (!fdtp)
+		fdtp = __dtb_start;
+	fdtp = phys_to_virt(__pa(fdtp));
+	early_init_devtree(fdtp);
 }
 
 const char *get_system_type(void)
@@ -94,27 +108,19 @@ void xlp_mmu_init(void)
 		(13 + (ffz(PM_DEFAULT_MASK >> 13) / 2)));
 }
 
-void __init prom_init(void)
+void nlm_percpu_init(int hwcpuid)
 {
-	void *fdtp;
+}
 
+void __init prom_init(void)
+{
+	nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE);
 	xlp_mmu_init();
-	nlm_hal_init();
-
-	/*
-	 * If no FDT pointer is passed in, use the built-in FDT.
-	 * device_tree_init() does not handle CKSEG0 pointers in
-	 * 64-bit, so convert pointer.
-	 */
-	fdtp = (void *)(long)fw_arg0;
-	if (!fdtp)
-		fdtp = __dtb_start;
-	fdtp = phys_to_virt(__pa(fdtp));
-	early_init_devtree(fdtp);
+	nlm_node_init(0);
 
-	nlm_common_ebase = read_c0_ebase() & (~((1 << 12) - 1));
 #ifdef CONFIG_SMP
-	nlm_wakeup_secondary_cpus(0xffffffff);
+	cpumask_setall(&nlm_cpumask);
+	nlm_wakeup_secondary_cpus();
 
 	/* update TLB size after waking up threads */
 	current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1;
diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c
index 44d923f..cb90106 100644
--- a/arch/mips/netlogic/xlp/wakeup.c
+++ b/arch/mips/netlogic/xlp/wakeup.c
@@ -51,45 +51,72 @@
 #include <asm/netlogic/xlp-hal/xlp.h>
 #include <asm/netlogic/xlp-hal/sys.h>
 
-static void xlp_enable_secondary_cores(void)
+static int xlp_wakeup_core(uint64_t sysbase, int core)
 {
-	uint32_t core, value, coremask, syscoremask;
+	uint32_t coremask, value;
 	int count;
 
-	/* read cores in reset from SYS block */
-	syscoremask = nlm_read_sys_reg(nlm_sys_base, SYS_CPU_RESET);
+	coremask = (1 << core);
 
-	/* update user specified */
-	nlm_coremask = nlm_coremask & (syscoremask | 1);
+	/* Enable CPU clock */
+	value = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL);
+	value &= ~coremask;
+	nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, value);
 
-	for (core = 1; core < 8; core++) {
-		coremask = 1 << core;
-		if ((nlm_coremask & coremask) == 0)
-			continue;
+	/* Remove CPU Reset */
+	value = nlm_read_sys_reg(sysbase, SYS_CPU_RESET);
+	value &= ~coremask;
+	nlm_write_sys_reg(sysbase, SYS_CPU_RESET, value);
 
-		/* Enable CPU clock */
-		value = nlm_read_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIS_CTRL);
-		value &= ~coremask;
-		nlm_write_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIS_CTRL, value);
+	/* Poll for CPU to mark itself coherent */
+	count = 100000;
+	do {
+		value = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE);
+	} while ((value & coremask) != 0 && --count > 0);
 
-		/* Remove CPU Reset */
-		value = nlm_read_sys_reg(nlm_sys_base, SYS_CPU_RESET);
-		value &= ~coremask;
-		nlm_write_sys_reg(nlm_sys_base, SYS_CPU_RESET, value);
+	return count != 0;
+}
+
+static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
+{
+	struct nlm_soc_info *nodep;
+	uint64_t syspcibase;
+	uint32_t syscoremask;
+	int core, n, cpu;
+
+	for (n = 0; n < NLM_NR_NODES; n++) {
+		syspcibase = nlm_get_sys_pcibase(n);
+		if (nlm_read_reg(syspcibase, 0) == 0xffffffff)
+			break;
+
+		/* read cores in reset from SYS and account for boot cpu */
+		nlm_node_init(n);
+		nodep = nlm_get_node(n);
+		syscoremask = nlm_read_sys_reg(nodep->sysbase, SYS_CPU_RESET);
+		if (n == 0)
+			syscoremask |= 1;
+
+		for (core = 0; core < NLM_CORES_PER_NODE; core++) {
+			/* see if the core exists */
+			if ((syscoremask & (1 << core)) == 0)
+				continue;
 
-		/* Poll for CPU to mark itself coherent */
-		count = 100000;
-		do {
-			value = nlm_read_sys_reg(nlm_sys_base,
-			    SYS_CPU_NONCOHERENT_MODE);
-		} while ((value & coremask) != 0 && count-- > 0);
+			/* see if at least the first thread is enabled */
+			cpu = (n * NLM_CORES_PER_NODE + core)
+						* NLM_THREADS_PER_CORE;
+			if (!cpumask_test_cpu(cpu, wakeup_mask))
+				continue;
 
-		if (count == 0)
-			pr_err("Failed to enable core %d\n", core);
+			/* wake up the core */
+			if (xlp_wakeup_core(nodep->sysbase, core))
+				nodep->coremask |= 1u << core;
+			else
+				pr_err("Failed to enable core %d\n", core);
+		}
 	}
 }
 
-void xlp_wakeup_secondary_cpus(void)
+void xlp_wakeup_secondary_cpus()
 {
 	/*
 	 * In case of u-boot, the secondaries are in reset
@@ -98,5 +125,5 @@ void xlp_wakeup_secondary_cpus(void)
 	xlp_boot_core0_siblings();
 
 	/* now get other cores out of reset */
-	xlp_enable_secondary_cores();
+	xlp_enable_secondary_cores(&nlm_cpumask);
 }
diff --git a/arch/mips/netlogic/xlr/Makefile b/arch/mips/netlogic/xlr/Makefile
index c287dea..05902bc 100644
--- a/arch/mips/netlogic/xlr/Makefile
+++ b/arch/mips/netlogic/xlr/Makefile
@@ -1,2 +1,2 @@
-obj-y				+= setup.o platform.o platform-flash.o
-obj-$(CONFIG_SMP)		+= wakeup.o
+obj-y			+=  fmn.o fmn-config.o setup.o platform.o platform-flash.o
+obj-$(CONFIG_SMP)	+= wakeup.o
diff --git a/arch/mips/netlogic/xlr/fmn-config.c b/arch/mips/netlogic/xlr/fmn-config.c
new file mode 100644
index 0000000..bed2cff
--- /dev/null
+++ b/arch/mips/netlogic/xlr/fmn-config.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``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 BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <asm/cpu-info.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/mipsregs.h>
+#include <asm/netlogic/xlr/fmn.h>
+#include <asm/netlogic/xlr/xlr.h>
+#include <asm/netlogic/common.h>
+#include <asm/netlogic/haldefs.h>
+
+struct xlr_board_fmn_config xlr_board_fmn_config;
+
+static void __maybe_unused print_credit_config(struct xlr_fmn_info *fmn_info)
+{
+	int bkt;
+
+	pr_info("Bucket size :\n");
+	pr_info("Station\t: Size\n");
+	for (bkt = 0; bkt < 16; bkt++)
+		pr_info(" %d  %d  %d  %d  %d  %d  %d %d\n",
+			xlr_board_fmn_config.bucket_size[(bkt * 8) + 0],
+			xlr_board_fmn_config.bucket_size[(bkt * 8) + 1],
+			xlr_board_fmn_config.bucket_size[(bkt * 8) + 2],
+			xlr_board_fmn_config.bucket_size[(bkt * 8) + 3],
+			xlr_board_fmn_config.bucket_size[(bkt * 8) + 4],
+			xlr_board_fmn_config.bucket_size[(bkt * 8) + 5],
+			xlr_board_fmn_config.bucket_size[(bkt * 8) + 6],
+			xlr_board_fmn_config.bucket_size[(bkt * 8) + 7]);
+	pr_info("\n");
+
+	pr_info("Credits distribution :\n");
+	pr_info("Station\t: Size\n");
+	for (bkt = 0; bkt < 16; bkt++)
+		pr_info(" %d  %d  %d  %d  %d  %d  %d %d\n",
+			fmn_info->credit_config[(bkt * 8) + 0],
+			fmn_info->credit_config[(bkt * 8) + 1],
+			fmn_info->credit_config[(bkt * 8) + 2],
+			fmn_info->credit_config[(bkt * 8) + 3],
+			fmn_info->credit_config[(bkt * 8) + 4],
+			fmn_info->credit_config[(bkt * 8) + 5],
+			fmn_info->credit_config[(bkt * 8) + 6],
+			fmn_info->credit_config[(bkt * 8) + 7]);
+	pr_info("\n");
+}
+
+static void check_credit_distribution(void)
+{
+	struct xlr_board_fmn_config *cfg = &xlr_board_fmn_config;
+	int bkt, n, total_credits, ncores;
+
+	ncores = hweight32(nlm_current_node()->coremask);
+	for (bkt = 0; bkt < 128; bkt++) {
+		total_credits = 0;
+		for (n = 0; n < ncores; n++)
+			total_credits += cfg->cpu[n].credit_config[bkt];
+		total_credits += cfg->gmac[0].credit_config[bkt];
+		total_credits += cfg->gmac[1].credit_config[bkt];
+		total_credits += cfg->dma.credit_config[bkt];
+		total_credits += cfg->cmp.credit_config[bkt];
+		total_credits += cfg->sae.credit_config[bkt];
+		total_credits += cfg->xgmac[0].credit_config[bkt];
+		total_credits += cfg->xgmac[1].credit_config[bkt];
+		if (total_credits > cfg->bucket_size[bkt])
+			pr_err("ERROR: Bucket %d: credits (%d) > size (%d)\n",
+				bkt, total_credits, cfg->bucket_size[bkt]);
+	}
+	pr_info("Credit distribution complete.\n");
+}
+
+/**
+ * Configure bucket size and credits for a device. 'size' is the size of
+ * the buckets for the device. This size is distributed among all the CPUs
+ * so that all of them can send messages to the device.
+ *
+ * The device is also given 'cpu_credits' to send messages to the CPUs
+ *
+ * @dev_info: FMN information structure for each devices
+ * @start_stn_id: Starting station id of dev_info
+ * @end_stn_id: End station id of dev_info
+ * @num_buckets: Total number of buckets for den_info
+ * @cpu_credits: Allowed credits to cpu for each devices pointing by dev_info
+ * @size: Size of the each buckets in the device station
+ */
+static void setup_fmn_cc(struct xlr_fmn_info *dev_info, int start_stn_id,
+		int end_stn_id, int num_buckets, int cpu_credits, int size)
+{
+	int i, j, num_core, n, credits_per_cpu;
+	struct xlr_fmn_info *cpu = xlr_board_fmn_config.cpu;
+
+	num_core = hweight32(nlm_current_node()->coremask);
+	dev_info->num_buckets	= num_buckets;
+	dev_info->start_stn_id	= start_stn_id;
+	dev_info->end_stn_id	= end_stn_id;
+
+	n = num_core;
+	if (num_core == 3)
+		n = 4;
+
+	for (i = start_stn_id; i <= end_stn_id; i++) {
+		xlr_board_fmn_config.bucket_size[i] = size;
+
+		/* Dividing device credits equally to cpus */
+		credits_per_cpu = size / n;
+		for (j = 0; j < num_core; j++)
+			cpu[j].credit_config[i] = credits_per_cpu;
+
+		/* credits left to distribute */
+		credits_per_cpu = size - (credits_per_cpu * num_core);
+
+		/* distribute the remaining credits (if any), among cores */
+		for (j = 0; (j < num_core) && (credits_per_cpu >= 4); j++) {
+			cpu[j].credit_config[i] += 4;
+			credits_per_cpu -= 4;
+		}
+	}
+
+	/* Distributing cpu per bucket credits to devices */
+	for (i = 0; i < num_core; i++) {
+		for (j = 0; j < FMN_CORE_NBUCKETS; j++)
+			dev_info->credit_config[(i * 8) + j] = cpu_credits;
+	}
+}
+
+/*
+ * Each core has 256 slots and 8 buckets,
+ * Configure the 8 buckets each with 32 slots
+ */
+static void setup_cpu_fmninfo(struct xlr_fmn_info *cpu, int num_core)
+{
+	int i, j;
+
+	for (i = 0; i < num_core; i++) {
+		cpu[i].start_stn_id     = (8 * i);
+		cpu[i].end_stn_id       = (8 * i + 8);
+
+		for (j = cpu[i].start_stn_id; j < cpu[i].end_stn_id; j++)
+			xlr_board_fmn_config.bucket_size[j] = 32;
+	}
+}
+
+/**
+ * Setup the FMN details for each devices according to the device available
+ * in each variant of XLR/XLS processor
+ */
+void xlr_board_info_setup(void)
+{
+	struct xlr_fmn_info *cpu = xlr_board_fmn_config.cpu;
+	struct xlr_fmn_info *gmac = xlr_board_fmn_config.gmac;
+	struct xlr_fmn_info *xgmac = xlr_board_fmn_config.xgmac;
+	struct xlr_fmn_info *dma = &xlr_board_fmn_config.dma;
+	struct xlr_fmn_info *cmp = &xlr_board_fmn_config.cmp;
+	struct xlr_fmn_info *sae = &xlr_board_fmn_config.sae;
+	int processor_id, num_core;
+
+	num_core = hweight32(nlm_current_node()->coremask);
+	processor_id = read_c0_prid() & 0xff00;
+
+	setup_cpu_fmninfo(cpu, num_core);
+	switch (processor_id) {
+	case PRID_IMP_NETLOGIC_XLS104:
+	case PRID_IMP_NETLOGIC_XLS108:
+		setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
+					FMN_STNID_GMAC0_TX3, 8, 16, 32);
+		setup_fmn_cc(dma, FMN_STNID_DMA_0,
+					FMN_STNID_DMA_3, 4, 8, 64);
+		setup_fmn_cc(sae, FMN_STNID_SEC0,
+					FMN_STNID_SEC1, 2, 8, 128);
+		break;
+
+	case PRID_IMP_NETLOGIC_XLS204:
+	case PRID_IMP_NETLOGIC_XLS208:
+		setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
+					FMN_STNID_GMAC0_TX3, 8, 16, 32);
+		setup_fmn_cc(dma, FMN_STNID_DMA_0,
+					FMN_STNID_DMA_3, 4, 8, 64);
+		setup_fmn_cc(sae, FMN_STNID_SEC0,
+					FMN_STNID_SEC1, 2, 8, 128);
+		break;
+
+	case PRID_IMP_NETLOGIC_XLS404:
+	case PRID_IMP_NETLOGIC_XLS408:
+	case PRID_IMP_NETLOGIC_XLS404B:
+	case PRID_IMP_NETLOGIC_XLS408B:
+	case PRID_IMP_NETLOGIC_XLS416B:
+		setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
+					FMN_STNID_GMAC0_TX3, 8, 8, 32);
+		setup_fmn_cc(&gmac[1], FMN_STNID_GMAC1_FR_0,
+					FMN_STNID_GMAC1_TX3, 8, 8, 32);
+		setup_fmn_cc(dma, FMN_STNID_DMA_0,
+					FMN_STNID_DMA_3, 4, 4, 64);
+		setup_fmn_cc(cmp, FMN_STNID_CMP_0,
+					FMN_STNID_CMP_3, 4, 4, 64);
+		setup_fmn_cc(sae, FMN_STNID_SEC0,
+					FMN_STNID_SEC1, 2, 8, 128);
+		break;
+
+	case PRID_IMP_NETLOGIC_XLS412B:
+		setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
+					FMN_STNID_GMAC0_TX3, 8, 8, 32);
+		setup_fmn_cc(&gmac[1], FMN_STNID_GMAC1_FR_0,
+					FMN_STNID_GMAC1_TX3, 8, 8, 32);
+		setup_fmn_cc(dma, FMN_STNID_DMA_0,
+					FMN_STNID_DMA_3, 4, 4, 64);
+		setup_fmn_cc(cmp, FMN_STNID_CMP_0,
+					FMN_STNID_CMP_3, 4, 4, 64);
+		setup_fmn_cc(sae, FMN_STNID_SEC0,
+					FMN_STNID_SEC1, 2, 8, 128);
+		break;
+
+	case PRID_IMP_NETLOGIC_XLR308:
+	case PRID_IMP_NETLOGIC_XLR308C:
+		setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
+					FMN_STNID_GMAC0_TX3, 8, 16, 32);
+		setup_fmn_cc(dma, FMN_STNID_DMA_0,
+					FMN_STNID_DMA_3, 4, 8, 64);
+		setup_fmn_cc(sae, FMN_STNID_SEC0,
+					FMN_STNID_SEC1, 2, 4, 128);
+		break;
+
+	case PRID_IMP_NETLOGIC_XLR532:
+	case PRID_IMP_NETLOGIC_XLR532C:
+	case PRID_IMP_NETLOGIC_XLR516C:
+	case PRID_IMP_NETLOGIC_XLR508C:
+		setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
+					FMN_STNID_GMAC0_TX3, 8, 16, 32);
+		setup_fmn_cc(dma, FMN_STNID_DMA_0,
+					FMN_STNID_DMA_3, 4, 8, 64);
+		setup_fmn_cc(sae, FMN_STNID_SEC0,
+					FMN_STNID_SEC1, 2, 4, 128);
+		break;
+
+	case PRID_IMP_NETLOGIC_XLR732:
+	case PRID_IMP_NETLOGIC_XLR716:
+		setup_fmn_cc(&xgmac[0], FMN_STNID_XMAC0_00_TX,
+					FMN_STNID_XMAC0_15_TX, 8, 0, 32);
+		setup_fmn_cc(&xgmac[1], FMN_STNID_XMAC1_00_TX,
+					FMN_STNID_XMAC1_15_TX, 8, 0, 32);
+		setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
+					FMN_STNID_GMAC0_TX3, 8, 24, 32);
+		setup_fmn_cc(dma, FMN_STNID_DMA_0,
+					FMN_STNID_DMA_3, 4, 4, 64);
+		setup_fmn_cc(sae, FMN_STNID_SEC0,
+					FMN_STNID_SEC1, 2, 4, 128);
+		break;
+	default:
+		pr_err("Unknown CPU with processor ID [%d]\n", processor_id);
+		pr_err("Error: Cannot initialize FMN credits.\n");
+	}
+
+	check_credit_distribution();
+
+#if 0 /* debug */
+	print_credit_config(&cpu[0]);
+	print_credit_config(&gmac[0]);
+#endif
+}
diff --git a/arch/mips/netlogic/xlr/fmn.c b/arch/mips/netlogic/xlr/fmn.c
new file mode 100644
index 0000000..4d74f03
--- /dev/null
+++ b/arch/mips/netlogic/xlr/fmn.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``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 BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/irqreturn.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/mipsregs.h>
+#include <asm/netlogic/interrupt.h>
+#include <asm/netlogic/xlr/fmn.h>
+#include <asm/netlogic/common.h>
+
+#define COP2_CC_INIT_CPU_DEST(dest, conf) \
+do { \
+	nlm_write_c2_cc##dest(0, conf[(dest * 8) + 0]); \
+	nlm_write_c2_cc##dest(1, conf[(dest * 8) + 1]); \
+	nlm_write_c2_cc##dest(2, conf[(dest * 8) + 2]); \
+	nlm_write_c2_cc##dest(3, conf[(dest * 8) + 3]); \
+	nlm_write_c2_cc##dest(4, conf[(dest * 8) + 4]); \
+	nlm_write_c2_cc##dest(5, conf[(dest * 8) + 5]); \
+	nlm_write_c2_cc##dest(6, conf[(dest * 8) + 6]); \
+	nlm_write_c2_cc##dest(7, conf[(dest * 8) + 7]); \
+} while (0)
+
+struct fmn_message_handler {
+	void (*action)(int, int, int, int, struct nlm_fmn_msg *, void *);
+	void *arg;
+} msg_handlers[128];
+
+/*
+ * FMN interrupt handler. We configure the FMN so that any messages in
+ * any of the CPU buckets will trigger an interrupt on the CPU.
+ * The message can be from any device on the FMN (like NAE/SAE/DMA).
+ * The source station id is used to figure out which of the registered
+ * handlers have to be called.
+ */
+static irqreturn_t fmn_message_handler(int irq, void *data)
+{
+	struct fmn_message_handler *hndlr;
+	int bucket, rv;
+	int size = 0, code = 0, src_stnid = 0;
+	struct nlm_fmn_msg msg;
+	uint32_t mflags, bkt_status;
+
+	mflags = nlm_cop2_enable();
+	/* Disable message ring interrupt */
+	nlm_fmn_setup_intr(irq, 0);
+	while (1) {
+		/* 8 bkts per core, [24:31] each bit represents one bucket
+		 * Bit is Zero if bucket is not empty */
+		bkt_status = (nlm_read_c2_status() >> 24) & 0xff;
+		if (bkt_status == 0xff)
+			break;
+		for (bucket = 0; bucket < 8; bucket++) {
+			/* Continue on empty bucket */
+			if (bkt_status & (1 << bucket))
+				continue;
+			rv = nlm_fmn_receive(bucket, &size, &code, &src_stnid,
+						&msg);
+			if (rv != 0)
+				continue;
+
+			hndlr = &msg_handlers[src_stnid];
+			if (hndlr->action == NULL)
+				pr_warn("No msgring handler for stnid %d\n",
+						src_stnid);
+			else {
+				nlm_cop2_restore(mflags);
+				hndlr->action(bucket, src_stnid, size, code,
+					&msg, hndlr->arg);
+				mflags = nlm_cop2_enable();
+			}
+		}
+	};
+	/* Enable message ring intr, to any thread in core */
+	nlm_fmn_setup_intr(irq, (1 << nlm_threads_per_core) - 1);
+	nlm_cop2_restore(mflags);
+	return IRQ_HANDLED;
+}
+
+struct irqaction fmn_irqaction = {
+	.handler = fmn_message_handler,
+	.flags = IRQF_PERCPU,
+	.name = "fmn",
+};
+
+void xlr_percpu_fmn_init(void)
+{
+	struct xlr_fmn_info *cpu_fmn_info;
+	int *bucket_sizes;
+	uint32_t flags;
+	int id;
+
+	BUG_ON(nlm_thread_id() != 0);
+	id = nlm_core_id();
+
+	bucket_sizes = xlr_board_fmn_config.bucket_size;
+	cpu_fmn_info = &xlr_board_fmn_config.cpu[id];
+	flags = nlm_cop2_enable();
+
+	/* Setup bucket sizes for the core. */
+	nlm_write_c2_bucksize(0, bucket_sizes[id * 8 + 0]);
+	nlm_write_c2_bucksize(1, bucket_sizes[id * 8 + 1]);
+	nlm_write_c2_bucksize(2, bucket_sizes[id * 8 + 2]);
+	nlm_write_c2_bucksize(3, bucket_sizes[id * 8 + 3]);
+	nlm_write_c2_bucksize(4, bucket_sizes[id * 8 + 4]);
+	nlm_write_c2_bucksize(5, bucket_sizes[id * 8 + 5]);
+	nlm_write_c2_bucksize(6, bucket_sizes[id * 8 + 6]);
+	nlm_write_c2_bucksize(7, bucket_sizes[id * 8 + 7]);
+
+	/*
+	 * For sending FMN messages, we need credits on the destination
+	 * bucket. Program the credits this core has on the 128 possible
+	 * destination buckets.
+	 * We cannot use a loop here, because the the first argument has
+	 * to be a constant integer value.
+	 */
+	COP2_CC_INIT_CPU_DEST(0, cpu_fmn_info->credit_config);
+	COP2_CC_INIT_CPU_DEST(1, cpu_fmn_info->credit_config);
+	COP2_CC_INIT_CPU_DEST(2, cpu_fmn_info->credit_config);
+	COP2_CC_INIT_CPU_DEST(3, cpu_fmn_info->credit_config);
+	COP2_CC_INIT_CPU_DEST(4, cpu_fmn_info->credit_config);
+	COP2_CC_INIT_CPU_DEST(5, cpu_fmn_info->credit_config);
+	COP2_CC_INIT_CPU_DEST(6, cpu_fmn_info->credit_config);
+	COP2_CC_INIT_CPU_DEST(7, cpu_fmn_info->credit_config);
+	COP2_CC_INIT_CPU_DEST(8, cpu_fmn_info->credit_config);
+	COP2_CC_INIT_CPU_DEST(9, cpu_fmn_info->credit_config);
+	COP2_CC_INIT_CPU_DEST(10, cpu_fmn_info->credit_config);
+	COP2_CC_INIT_CPU_DEST(11, cpu_fmn_info->credit_config);
+	COP2_CC_INIT_CPU_DEST(12, cpu_fmn_info->credit_config);
+	COP2_CC_INIT_CPU_DEST(13, cpu_fmn_info->credit_config);
+	COP2_CC_INIT_CPU_DEST(14, cpu_fmn_info->credit_config);
+	COP2_CC_INIT_CPU_DEST(15, cpu_fmn_info->credit_config);
+
+	/* enable FMN interrupts on this CPU */
+	nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
+	nlm_cop2_restore(flags);
+}
+
+
+/*
+ * Register a FMN message handler with respect to the source station id
+ * @stnid: source station id
+ * @action: Handler function pointer
+ */
+int nlm_register_fmn_handler(int start_stnid, int end_stnid,
+	void (*action)(int, int, int, int, struct nlm_fmn_msg *, void *),
+	void *arg)
+{
+	int sstnid;
+
+	for (sstnid = start_stnid; sstnid <= end_stnid; sstnid++) {
+		msg_handlers[sstnid].arg = arg;
+		smp_wmb();
+		msg_handlers[sstnid].action = action;
+	}
+	pr_debug("Registered FMN msg handler for stnid %d-%d\n",
+			start_stnid, end_stnid);
+	return 0;
+}
+
+void nlm_setup_fmn_irq(void)
+{
+	uint32_t flags;
+
+	/* setup irq only once */
+	setup_irq(IRQ_FMN, &fmn_irqaction);
+
+	flags = nlm_cop2_enable();
+	nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
+	nlm_cop2_restore(flags);
+}
diff --git a/arch/mips/netlogic/xlr/platform.c b/arch/mips/netlogic/xlr/platform.c
index 71b44d8..507230e 100644
--- a/arch/mips/netlogic/xlr/platform.c
+++ b/arch/mips/netlogic/xlr/platform.c
@@ -15,6 +15,8 @@
 #include <linux/serial_8250.h>
 #include <linux/serial_reg.h>
 #include <linux/i2c.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
 
 #include <asm/netlogic/haldefs.h>
 #include <asm/netlogic/xlr/iomap.h>
@@ -123,12 +125,18 @@ static u64 xls_usb_dmamask = ~(u32)0;
 		},							\
 	}
 
+static struct usb_ehci_pdata xls_usb_ehci_pdata = {
+	.caps_offset	= 0,
+};
+
+static struct usb_ohci_pdata xls_usb_ohci_pdata;
+
 static struct platform_device xls_usb_ehci_device =
-			 USB_PLATFORM_DEV("ehci-xls", 0, PIC_USB_IRQ);
+			 USB_PLATFORM_DEV("ehci-platform", 0, PIC_USB_IRQ);
 static struct platform_device xls_usb_ohci_device_0 =
-			 USB_PLATFORM_DEV("ohci-xls-0", 1, PIC_USB_IRQ);
+			 USB_PLATFORM_DEV("ohci-platform", 1, PIC_USB_IRQ);
 static struct platform_device xls_usb_ohci_device_1 =
-			 USB_PLATFORM_DEV("ohci-xls-1", 2, PIC_USB_IRQ);
+			 USB_PLATFORM_DEV("ohci-platform", 2, PIC_USB_IRQ);
 
 static struct platform_device *xls_platform_devices[] = {
 	&xls_usb_ehci_device,
@@ -172,14 +180,17 @@ int xls_platform_usb_init(void)
 	memres = CPHYSADDR((unsigned long)usb_mmio);
 	xls_usb_ehci_device.resource[0].start = memres;
 	xls_usb_ehci_device.resource[0].end = memres + 0x400 - 1;
+	xls_usb_ehci_device.dev.platform_data = &xls_usb_ehci_pdata;
 
 	memres += 0x400;
 	xls_usb_ohci_device_0.resource[0].start = memres;
 	xls_usb_ohci_device_0.resource[0].end = memres + 0x400 - 1;
+	xls_usb_ohci_device_0.dev.platform_data = &xls_usb_ohci_pdata;
 
 	memres += 0x400;
 	xls_usb_ohci_device_1.resource[0].start = memres;
 	xls_usb_ohci_device_1.resource[0].end = memres + 0x400 - 1;
+	xls_usb_ohci_device_1.dev.platform_data = &xls_usb_ohci_pdata;
 
 	return platform_add_devices(xls_platform_devices,
 				ARRAY_SIZE(xls_platform_devices));
diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c
index 81b1d31..4e7f49d 100644
--- a/arch/mips/netlogic/xlr/setup.c
+++ b/arch/mips/netlogic/xlr/setup.c
@@ -49,16 +49,15 @@
 #include <asm/netlogic/xlr/iomap.h>
 #include <asm/netlogic/xlr/pic.h>
 #include <asm/netlogic/xlr/gpio.h>
+#include <asm/netlogic/xlr/fmn.h>
 
 uint64_t nlm_io_base = DEFAULT_NETLOGIC_IO_BASE;
-uint64_t nlm_pic_base;
 struct psb_info nlm_prom_info;
 
-unsigned long nlm_common_ebase = 0x0;
-
 /* default to uniprocessor */
-uint32_t nlm_coremask = 1, nlm_cpumask  = 1;
-int  nlm_threads_per_core = 1;
+unsigned int  nlm_threads_per_core = 1;
+struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
+cpumask_t nlm_cpumask = CPU_MASK_CPU0;
 
 static void __init nlm_early_serial_setup(void)
 {
@@ -113,6 +112,12 @@ void __init prom_free_prom_memory(void)
 	/* Nothing yet */
 }
 
+void nlm_percpu_init(int hwcpuid)
+{
+	if (hwcpuid % 4 == 0)
+		xlr_percpu_fmn_init();
+}
+
 static void __init build_arcs_cmdline(int *argv)
 {
 	int i, remain, len;
@@ -176,9 +181,19 @@ static void prom_add_memory(void)
 	}
 }
 
+static void nlm_init_node(void)
+{
+	struct nlm_soc_info *nodep;
+
+	nodep = nlm_current_node();
+	nodep->picbase = nlm_mmio_base(NETLOGIC_IO_PIC_OFFSET);
+	nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
+	spin_lock_init(&nodep->piclock);
+}
+
 void __init prom_init(void)
 {
-	int *argv, *envp;		/* passed as 32 bit ptrs */
+	int i, *argv, *envp;		/* passed as 32 bit ptrs */
 	struct psb_info *prom_infop;
 
 	/* truncate to 32 bit and sign extend all args */
@@ -187,15 +202,19 @@ void __init prom_init(void)
 	prom_infop = (struct psb_info *)(long)(int)fw_arg3;
 
 	nlm_prom_info = *prom_infop;
-	nlm_pic_base = nlm_mmio_base(NETLOGIC_IO_PIC_OFFSET);
+	nlm_init_node();
 
 	nlm_early_serial_setup();
 	build_arcs_cmdline(argv);
-	nlm_common_ebase = read_c0_ebase() & (~((1 << 12) - 1));
 	prom_add_memory();
 
 #ifdef CONFIG_SMP
-	nlm_wakeup_secondary_cpus(nlm_prom_info.online_cpu_map);
+	for (i = 0; i < 32; i++)
+		if (nlm_prom_info.online_cpu_map & (1 << i))
+			cpumask_set_cpu(i, &nlm_cpumask);
+	nlm_wakeup_secondary_cpus();
 	register_smp_ops(&nlm_smp_ops);
 #endif
+	xlr_board_info_setup();
+	xlr_percpu_fmn_init();
 }
diff --git a/arch/mips/netlogic/xlr/wakeup.c b/arch/mips/netlogic/xlr/wakeup.c
index db5d987..3ebf741 100644
--- a/arch/mips/netlogic/xlr/wakeup.c
+++ b/arch/mips/netlogic/xlr/wakeup.c
@@ -33,6 +33,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/delay.h>
 #include <linux/threads.h>
 
 #include <asm/asm.h>
@@ -50,18 +51,34 @@
 
 int __cpuinit xlr_wakeup_secondary_cpus(void)
 {
-	unsigned int i, boot_cpu;
+	struct nlm_soc_info *nodep;
+	unsigned int i, j, boot_cpu;
 
 	/*
 	 *  In case of RMI boot, hit with NMI to get the cores
 	 *  from bootloader to linux code.
 	 */
+	nodep = nlm_get_node(0);
 	boot_cpu = hard_smp_processor_id();
 	nlm_set_nmi_handler(nlm_rmiboot_preboot);
 	for (i = 0; i < NR_CPUS; i++) {
-		if (i == boot_cpu || (nlm_cpumask & (1u << i)) == 0)
+		if (i == boot_cpu || !cpumask_test_cpu(i, &nlm_cpumask))
 			continue;
-		nlm_pic_send_ipi(nlm_pic_base, i, 1, 1); /* send NMI */
+		nlm_pic_send_ipi(nodep->picbase, i, 1, 1); /* send NMI */
+	}
+
+	/* Fill up the coremask early */
+	nodep->coremask = 1;
+	for (i = 1; i < NLM_CORES_PER_NODE; i++) {
+		for (j = 1000000; j > 0; j--) {
+			if (nlm_cpu_ready[i * NLM_THREADS_PER_CORE])
+				break;
+			udelay(10);
+		}
+		if (j != 0)
+			nodep->coremask |= (1u << i);
+		else
+			pr_err("Failed to wakeup core %d\n", i);
 	}
 
 	return 0;
diff --git a/arch/mips/oprofile/Makefile b/arch/mips/oprofile/Makefile
index 1208c28..65f5237 100644
--- a/arch/mips/oprofile/Makefile
+++ b/arch/mips/oprofile/Makefile
@@ -12,5 +12,6 @@ oprofile-$(CONFIG_CPU_MIPS32)		+= op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_MIPS64)		+= op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_R10000)		+= op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_SB1)		+= op_model_mipsxx.o
+oprofile-$(CONFIG_CPU_XLR)		+= op_model_mipsxx.o
 oprofile-$(CONFIG_CPU_RM9000)		+= op_model_rm9000.o
 oprofile-$(CONFIG_CPU_LOONGSON2)	+= op_model_loongson2.o
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index f80480a..abd5a02 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -91,6 +91,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
 	case CPU_R10000:
 	case CPU_R12000:
 	case CPU_R14000:
+	case CPU_XLR:
 		lmodel = &op_model_mipsxx_ops;
 		break;
 
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 28ea1a4..7862546 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -31,8 +31,22 @@
 
 #define M_COUNTER_OVERFLOW		(1UL      << 31)
 
+/* Netlogic XLR specific, count events in all threads in a core */
+#define M_PERFCTL_COUNT_ALL_THREADS	(1UL      << 13)
+
 static int (*save_perf_irq)(void);
 
+/*
+ * XLR has only one set of counters per core. Designate the
+ * first hardware thread in the core for setup and init.
+ * Skip CPUs with non-zero hardware thread id (4 hwt per core)
+ */
+#ifdef CONFIG_CPU_XLR
+#define oprofile_skip_cpu(c)	((cpu_logical_map(c) & 0x3) != 0)
+#else
+#define oprofile_skip_cpu(c)	0
+#endif
+
 #ifdef CONFIG_MIPS_MT_SMP
 static int cpu_has_mipsmt_pertccounters;
 #define WHAT		(M_TC_EN_VPE | \
@@ -152,6 +166,8 @@ static void mipsxx_reg_setup(struct op_counter_config *ctr)
 			reg.control[i] |= M_PERFCTL_USER;
 		if (ctr[i].exl)
 			reg.control[i] |= M_PERFCTL_EXL;
+		if (current_cpu_type() == CPU_XLR)
+			reg.control[i] |= M_PERFCTL_COUNT_ALL_THREADS;
 		reg.counter[i] = 0x80000000 - ctr[i].count;
 	}
 }
@@ -162,6 +178,9 @@ static void mipsxx_cpu_setup(void *args)
 {
 	unsigned int counters = op_model_mipsxx_ops.num_counters;
 
+	if (oprofile_skip_cpu(smp_processor_id()))
+		return;
+
 	switch (counters) {
 	case 4:
 		w_c0_perfctrl3(0);
@@ -183,6 +202,9 @@ static void mipsxx_cpu_start(void *args)
 {
 	unsigned int counters = op_model_mipsxx_ops.num_counters;
 
+	if (oprofile_skip_cpu(smp_processor_id()))
+		return;
+
 	switch (counters) {
 	case 4:
 		w_c0_perfctrl3(WHAT | reg.control[3]);
@@ -200,6 +222,9 @@ static void mipsxx_cpu_stop(void *args)
 {
 	unsigned int counters = op_model_mipsxx_ops.num_counters;
 
+	if (oprofile_skip_cpu(smp_processor_id()))
+		return;
+
 	switch (counters) {
 	case 4:
 		w_c0_perfctrl3(0);
@@ -372,6 +397,10 @@ static int __init mipsxx_init(void)
 		op_model_mipsxx_ops.cpu_type = "mips/loongson1";
 		break;
 
+	case CPU_XLR:
+		op_model_mipsxx_ops.cpu_type = "mips/xlr";
+		break;
+
 	default:
 		printk(KERN_ERR "Profiling unsupported for this CPU\n");
 
diff --git a/arch/mips/pci/pci-bcm63xx.c b/arch/mips/pci/pci-bcm63xx.c
index 8a48139..ca179b6 100644
--- a/arch/mips/pci/pci-bcm63xx.c
+++ b/arch/mips/pci/pci-bcm63xx.c
@@ -11,8 +11,11 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/clk.h>
 #include <asm/bootinfo.h>
 
+#include <bcm63xx_reset.h>
+
 #include "pci-bcm63xx.h"
 
 /*
@@ -119,41 +122,36 @@ static void __init bcm63xx_reset_pcie(void)
 {
 	u32 val;
 
-	/* enable clock */
-	val = bcm_perf_readl(PERF_CKCTL_REG);
-	val |= CKCTL_6328_PCIE_EN;
-	bcm_perf_writel(val, PERF_CKCTL_REG);
-
 	/* enable SERDES */
 	val = bcm_misc_readl(MISC_SERDES_CTRL_REG);
 	val |= SERDES_PCIE_EN | SERDES_PCIE_EXD_EN;
 	bcm_misc_writel(val, MISC_SERDES_CTRL_REG);
 
 	/* reset the PCIe core */
-	val = bcm_perf_readl(PERF_SOFTRESET_6328_REG);
-
-	val &= ~SOFTRESET_6328_PCIE_MASK;
-	val &= ~SOFTRESET_6328_PCIE_CORE_MASK;
-	val &= ~SOFTRESET_6328_PCIE_HARD_MASK;
-	val &= ~SOFTRESET_6328_PCIE_EXT_MASK;
-	bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
+	bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 1);
+	bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_EXT, 1);
 	mdelay(10);
 
-	val |= SOFTRESET_6328_PCIE_MASK;
-	val |= SOFTRESET_6328_PCIE_CORE_MASK;
-	val |= SOFTRESET_6328_PCIE_HARD_MASK;
-	bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
+	bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 0);
 	mdelay(10);
 
-	val |= SOFTRESET_6328_PCIE_EXT_MASK;
-	bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
+	bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_EXT, 0);
 	mdelay(200);
 }
 
+static struct clk *pcie_clk;
+
 static int __init bcm63xx_register_pcie(void)
 {
 	u32 val;
 
+	/* enable clock */
+	pcie_clk = clk_get(NULL, "pcie");
+	if (IS_ERR_OR_NULL(pcie_clk))
+		return -ENODEV;
+
+	clk_prepare_enable(pcie_clk);
+
 	bcm63xx_reset_pcie();
 
 	/* configure the PCIe bridge */
diff --git a/arch/mips/pci/pci-octeon.c b/arch/mips/pci/pci-octeon.c
index 4b0c347..8eb2ee3 100644
--- a/arch/mips/pci/pci-octeon.c
+++ b/arch/mips/pci/pci-octeon.c
@@ -11,6 +11,7 @@
 #include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/delay.h>
+#include <linux/platform_device.h>
 #include <linux/swiotlb.h>
 
 #include <asm/time.h>
@@ -704,6 +705,9 @@ static int __init octeon_pci_setup(void)
 	 */
 	cvmx_write_csr(CVMX_NPI_PCI_INT_SUM2, -1);
 
+	if (IS_ERR(platform_device_register_simple("co_pci_edac", 0, NULL, 0)))
+		pr_err("Registation of co_pci_edac failed!\n");
+
 	octeon_pci_dma_init();
 
 	return 0;
diff --git a/arch/mips/pci/pci-xlr.c b/arch/mips/pci/pci-xlr.c
index 18af021..0c18ccc 100644
--- a/arch/mips/pci/pci-xlr.c
+++ b/arch/mips/pci/pci-xlr.c
@@ -47,6 +47,7 @@
 
 #include <asm/netlogic/interrupt.h>
 #include <asm/netlogic/haldefs.h>
+#include <asm/netlogic/common.h>
 
 #include <asm/netlogic/xlr/msidef.h>
 #include <asm/netlogic/xlr/iomap.h>
@@ -174,22 +175,9 @@ static struct pci_dev *xls_get_pcie_link(const struct pci_dev *dev)
 	return p ? bus->self : NULL;
 }
 
-static int get_irq_vector(const struct pci_dev *dev)
+static int nlm_pci_link_to_irq(int link)
 {
-	struct pci_dev *lnk;
-
-	if (!nlm_chip_is_xls())
-		return	PIC_PCIX_IRQ;	/* for XLR just one IRQ */
-
-	/*
-	 * For XLS PCIe, there is an IRQ per Link, find out which
-	 * link the device is on to assign interrupts
-	 */
-	lnk = xls_get_pcie_link(dev);
-	if (lnk == NULL)
-		return 0;
-
-	switch	(PCI_SLOT(lnk->devfn)) {
+	switch	(link) {
 	case 0:
 		return PIC_PCIE_LINK0_IRQ;
 	case 1:
@@ -205,10 +193,26 @@ static int get_irq_vector(const struct pci_dev *dev)
 		else
 			return PIC_PCIE_LINK3_IRQ;
 	}
-	WARN(1, "Unexpected devfn %d\n", lnk->devfn);
+	WARN(1, "Unexpected link %d\n", link);
 	return 0;
 }
 
+static int get_irq_vector(const struct pci_dev *dev)
+{
+	struct pci_dev *lnk;
+	int link;
+
+	if (!nlm_chip_is_xls())
+		return	PIC_PCIX_IRQ;	/* for XLR just one IRQ */
+
+	lnk = xls_get_pcie_link(dev);
+	if (lnk == NULL)
+		return 0;
+
+	link = PCI_SLOT(lnk->devfn);
+	return nlm_pci_link_to_irq(link);
+}
+
 #ifdef CONFIG_PCI_MSI
 void destroy_irq(unsigned int irq)
 {
@@ -332,6 +336,9 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
 
 static int __init pcibios_init(void)
 {
+	void (*extra_ack)(struct irq_data *);
+	int link, irq;
+
 	/* PSB assigns PCI resources */
 	pci_set_flags(PCI_PROBE_ONLY);
 	pci_config_base = ioremap(DEFAULT_PCI_CONFIG_BASE, 16 << 20);
@@ -350,27 +357,19 @@ static int __init pcibios_init(void)
 	 * For PCI interrupts, we need to ack the PCI controller too, overload
 	 * irq handler data to do this
 	 */
-	if (nlm_chip_is_xls()) {
-		if (nlm_chip_is_xls_b()) {
-			irq_set_handler_data(PIC_PCIE_LINK0_IRQ,
-							xls_pcie_ack_b);
-			irq_set_handler_data(PIC_PCIE_LINK1_IRQ,
-							xls_pcie_ack_b);
-			irq_set_handler_data(PIC_PCIE_XLSB0_LINK2_IRQ,
-							xls_pcie_ack_b);
-			irq_set_handler_data(PIC_PCIE_XLSB0_LINK3_IRQ,
-							xls_pcie_ack_b);
-		} else {
-			irq_set_handler_data(PIC_PCIE_LINK0_IRQ, xls_pcie_ack);
-			irq_set_handler_data(PIC_PCIE_LINK1_IRQ, xls_pcie_ack);
-			irq_set_handler_data(PIC_PCIE_LINK2_IRQ, xls_pcie_ack);
-			irq_set_handler_data(PIC_PCIE_LINK3_IRQ, xls_pcie_ack);
-		}
-	} else {
+	if (!nlm_chip_is_xls()) {
 		/* XLR PCI controller ACK */
-		irq_set_handler_data(PIC_PCIX_IRQ, xlr_pci_ack);
+		nlm_set_pic_extra_ack(0, PIC_PCIX_IRQ, xlr_pci_ack);
+	} else {
+		if  (nlm_chip_is_xls_b())
+			extra_ack = xls_pcie_ack_b;
+		else
+			extra_ack = xls_pcie_ack;
+		for (link = 0; link < 4; link++) {
+			irq = nlm_pci_link_to_irq(link);
+			nlm_set_pic_extra_ack(0, irq, extra_ack);
+		}
 	}
-
 	return 0;
 }
 
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 04e35bc..4040416 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -313,10 +313,8 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 	}
 }
 
-#ifdef CONFIG_HOTPLUG
 EXPORT_SYMBOL(PCIBIOS_MIN_IO);
 EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
-#endif
 
 int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 			enum pci_mmap_state mmap_state, int write_combine)
diff --git a/arch/mips/pnx8550/common/platform.c b/arch/mips/pnx8550/common/platform.c
index 5264cc0..0a8faea 100644
--- a/arch/mips/pnx8550/common/platform.c
+++ b/arch/mips/pnx8550/common/platform.c
@@ -20,6 +20,7 @@
 #include <linux/serial.h>
 #include <linux/serial_pnx8xxx.h>
 #include <linux/platform_device.h>
+#include <linux/usb/ohci_pdriver.h>
 
 #include <int.h>
 #include <usb.h>
@@ -96,12 +97,40 @@ static u64 ohci_dmamask = DMA_BIT_MASK(32);
 
 static u64 uart_dmamask = DMA_BIT_MASK(32);
 
+static int pnx8550_usb_ohci_power_on(struct platform_device *pdev)
+{
+	/*
+	 * Set register CLK48CTL to enable and 48MHz
+	 */
+	outl(0x00000003, PCI_BASE | 0x0004770c);
+
+	/*
+	 * Set register CLK12CTL to enable and 48MHz
+	 */
+	outl(0x00000003, PCI_BASE | 0x00047710);
+
+	udelay(100);
+
+	return 0;
+}
+
+static void pnx8550_usb_ohci_power_off(struct platform_device *pdev)
+{
+	udelay(10);
+}
+
+static struct usb_ohci_pdata pnx8550_usb_ohci_pdata = {
+	.power_on	= pnx8550_usb_ohci_power_on,
+	.power_off	= pnx8550_usb_ohci_power_off,
+};
+
 static struct platform_device pnx8550_usb_ohci_device = {
-	.name		= "pnx8550-ohci",
+	.name		= "ohci-platform",
 	.id		= -1,
 	.dev = {
 		.dma_mask		= &ohci_dmamask,
 		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &pnx8550_usb_ohci_pdata,
 	},
 	.num_resources	= ARRAY_SIZE(pnx8550_usb_ohci_resources),
 	.resource	= pnx8550_usb_ohci_resources,
diff --git a/arch/mips/sibyte/Kconfig b/arch/mips/sibyte/Kconfig
index 3cd937e..01cc1a7 100644
--- a/arch/mips/sibyte/Kconfig
+++ b/arch/mips/sibyte/Kconfig
@@ -74,7 +74,7 @@ config SIBYTE_SB1xxx_SOC
 	select SWAP_IO_SPACE
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL
-	select CFE
+	select FW_CFE
 	select SYS_HAS_EARLY_PRINTK
 
 choice
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index 413f17f..d6c7bd4 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -15,12 +15,12 @@
 #include <linux/fb.h>
 #include <linux/screen_info.h>
 
-#ifdef CONFIG_ARC
+#ifdef CONFIG_FW_ARC
 #include <asm/fw/arc/types.h>
 #include <asm/sgialib.h>
 #endif
 
-#ifdef CONFIG_SNIPROM
+#ifdef CONFIG_FW_SNIPROM
 #include <asm/mipsprom.h>
 #endif
 
@@ -37,7 +37,7 @@ extern void sni_machine_power_off(void);
 
 static void __init sni_display_setup(void)
 {
-#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) && defined(CONFIG_ARC)
+#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) && defined(CONFIG_FW_ARC)
 	struct screen_info *si = &screen_info;
 	DISPLAY_STATUS *di;
 
@@ -56,7 +56,7 @@ static void __init sni_display_setup(void)
 
 static void __init sni_console_setup(void)
 {
-#ifndef CONFIG_ARC
+#ifndef CONFIG_FW_ARC
 	char *ctype;
 	char *cdev;
 	char *baud;
diff --git a/arch/mips/txx9/generic/pci.c b/arch/mips/txx9/generic/pci.c
index 4efd918..b14ee53 100644
--- a/arch/mips/txx9/generic/pci.c
+++ b/arch/mips/txx9/generic/pci.c
@@ -341,7 +341,7 @@ static void __devinit quirk_slc90e66_ide(struct pci_dev *dev)
 
 static void __devinit tc35815_fixup(struct pci_dev *dev)
 {
-	/* This device may have PM registers but not they are not suported. */
+	/* This device may have PM registers but not they are not supported. */
 	if (dev->pm_cap) {
 		dev_info(&dev->dev, "PM disabled\n");
 		dev->pm_cap = 0;
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
index 04669fa..7247174 100644
--- a/arch/mn10300/Kconfig
+++ b/arch/mn10300/Kconfig
@@ -9,6 +9,7 @@ config MN10300
 	select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
 	select MODULES_USE_ELF_RELA
 
 config AM33_2
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 4a159da..c5d7670 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -1,3 +1,4 @@
 
 generic-y += clkdev.h
 generic-y += exec.h
+generic-y += trace_clock.h
diff --git a/arch/mn10300/include/asm/signal.h b/arch/mn10300/include/asm/signal.h
index f9668ec..d280e97 100644
--- a/arch/mn10300/include/asm/signal.h
+++ b/arch/mn10300/include/asm/signal.h
@@ -45,8 +45,4 @@ struct k_sigaction {
 };
 #include <asm/sigcontext.h>
 
-
-struct pt_regs;
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
 #endif /* _ASM_SIGNAL_H */
diff --git a/arch/mn10300/include/asm/unistd.h b/arch/mn10300/include/asm/unistd.h
index 55bbec1..cabf8ba 100644
--- a/arch/mn10300/include/asm/unistd.h
+++ b/arch/mn10300/include/asm/unistd.h
@@ -44,7 +44,9 @@
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_SYS_EXECVE
-#define __ARCH_WANT_KERNEL_EXECVE
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_CLONE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h
index 820463a..af5366b 100644
--- a/arch/mn10300/include/uapi/asm/socket.h
+++ b/arch/mn10300/include/uapi/asm/socket.h
@@ -40,6 +40,7 @@
 /* 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
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S
index 0c631d3..68fcab8 100644
--- a/arch/mn10300/kernel/entry.S
+++ b/arch/mn10300/kernel/entry.S
@@ -60,13 +60,8 @@ ENTRY(ret_from_kernel_thread)
 	mov	(REG_D0,fp),d0
 	mov	(REG_A0,fp),a0
 	calls	(a0)
-	jmp	sys_exit
-
-ENTRY(ret_from_kernel_execve)
-	add	-12,d0	/* pt_regs -> frame */
-	mov	d0,sp
-	GET_THREAD_INFO a2
 	clr	d0
+	mov	d0,(REG_D0,fp)
 	jmp	syscall_exit
 
 ###############################################################################
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c
index d0c671b..eb09f5a 100644
--- a/arch/mn10300/kernel/process.c
+++ b/arch/mn10300/kernel/process.c
@@ -206,7 +206,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
  */
 int copy_thread(unsigned long clone_flags,
 		unsigned long c_usp, unsigned long ustk_size,
-		struct task_struct *p, struct pt_regs *kregs)
+		struct task_struct *p)
 {
 	struct thread_info *ti = task_thread_info(p);
 	struct pt_regs *c_regs;
@@ -227,7 +227,7 @@ int copy_thread(unsigned long clone_flags,
 	p->thread.wchan	= p->thread.pc;
 	p->thread.usp	= c_usp;
 
-	if (unlikely(!kregs)) {
+	if (unlikely(p->flags & PF_KTHREAD)) {
 		memset(c_regs, 0, sizeof(struct pt_regs));
 		c_regs->a0 = c_usp; /* function */
 		c_regs->d0 = ustk_size; /* argument */
@@ -236,8 +236,9 @@ int copy_thread(unsigned long clone_flags,
 		p->thread.pc	= (unsigned long) ret_from_kernel_thread;
 		return 0;
 	}
-	*c_regs = *kregs;
-	c_regs->sp = c_usp;
+	*c_regs = *current_pt_regs();
+	if (c_usp)
+		c_regs->sp = c_usp;
 	c_regs->epsw &= ~EPSW_FE; /* my FPU */
 
 	/* the new TLS pointer is passed in as arg #5 to sys_clone() */
@@ -249,30 +250,6 @@ int copy_thread(unsigned long clone_flags,
 	return 0;
 }
 
-/*
- * clone a process
- * - tlsptr is retrieved by copy_thread() from current_frame()->d3
- */
-asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
-			  int __user *parent_tidptr, int __user *child_tidptr,
-			  int __user *tlsptr)
-{
-	return do_fork(clone_flags, newsp ?: current_frame()->sp,
-		       current_frame(), 0, parent_tidptr, child_tidptr);
-}
-
-asmlinkage long sys_fork(void)
-{
-	return do_fork(SIGCHLD, current_frame()->sp,
-		       current_frame(), 0, NULL, NULL);
-}
-
-asmlinkage long sys_vfork(void)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, current_frame()->sp,
-		       current_frame(), 0, NULL, NULL);
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
 	return p->thread.wchan;
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index 05f2ba4..e7f1a29 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -22,6 +22,8 @@ config OPENRISC
 	select GENERIC_STRNCPY_FROM_USER
 	select GENERIC_STRNLEN_USER
 	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
 
 config MMU
 	def_bool y
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 78de680..f20d01d 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -32,6 +32,7 @@ generic-y += ipcbuf.h
 generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += kmap_types.h
+generic-y += kvm_para.h
 generic-y += local.h
 generic-y += mman.h
 generic-y += module.h
@@ -60,6 +61,7 @@ generic-y += swab.h
 generic-y += termbits.h
 generic-y += termios.h
 generic-y += topology.h
+generic-y += trace_clock.h
 generic-y += types.h
 generic-y += ucontext.h
 generic-y += user.h
diff --git a/arch/openrisc/include/asm/io.h b/arch/openrisc/include/asm/io.h
index 07f5299..7c69139 100644
--- a/arch/openrisc/include/asm/io.h
+++ b/arch/openrisc/include/asm/io.h
@@ -30,6 +30,7 @@
 #define PIO_MASK		0
 
 #include <asm-generic/io.h>
+#include <asm/pgtable.h>
 
 extern void __iomem *__ioremap(phys_addr_t offset, unsigned long size,
 				pgprot_t prot);
diff --git a/arch/openrisc/include/asm/processor.h b/arch/openrisc/include/asm/processor.h
index 43decdb..3369138 100644
--- a/arch/openrisc/include/asm/processor.h
+++ b/arch/openrisc/include/asm/processor.h
@@ -81,8 +81,6 @@ struct thread_struct {
 #define KSTK_ESP(tsk)   (task_pt_regs(tsk)->sp)
 
 
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
 void release_thread(struct task_struct *);
 unsigned long get_wchan(struct task_struct *p);
diff --git a/arch/openrisc/include/asm/syscalls.h b/arch/openrisc/include/asm/syscalls.h
index 84a978a..8ee8168 100644
--- a/arch/openrisc/include/asm/syscalls.h
+++ b/arch/openrisc/include/asm/syscalls.h
@@ -24,4 +24,11 @@ asmlinkage long sys_or1k_atomic(unsigned long type, unsigned long *v1,
 
 #include <asm-generic/syscalls.h>
 
+asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp,
+			void __user *parent_tid, void __user *child_tid, int tls);
+asmlinkage long __sys_fork(void);
+
+#define sys_clone __sys_clone
+#define sys_fork __sys_fork
+
 #endif /* __ASM_OPENRISC_SYSCALLS_H */
diff --git a/arch/openrisc/include/uapi/asm/kvm_para.h b/arch/openrisc/include/uapi/asm/kvm_para.h
deleted file mode 100644
index 14fab8f..0000000
--- a/arch/openrisc/include/uapi/asm/kvm_para.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
diff --git a/arch/openrisc/include/uapi/asm/unistd.h b/arch/openrisc/include/uapi/asm/unistd.h
index 437bdbb..5082b80 100644
--- a/arch/openrisc/include/uapi/asm/unistd.h
+++ b/arch/openrisc/include/uapi/asm/unistd.h
@@ -20,6 +20,10 @@
 
 #define sys_mmap2 sys_mmap_pgoff
 
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_CLONE
+
 #include <asm-generic/unistd.h>
 
 #define __NR_or1k_atomic __NR_arch_specific_syscall
diff --git a/arch/openrisc/kernel/Makefile b/arch/openrisc/kernel/Makefile
index e1ee0fa..35f92ce 100644
--- a/arch/openrisc/kernel/Makefile
+++ b/arch/openrisc/kernel/Makefile
@@ -5,7 +5,7 @@
 extra-y	:= head.o vmlinux.lds
 
 obj-y	:= setup.o idle.o or32_ksyms.o process.o dma.o \
-	   traps.o time.o irq.o entry.o ptrace.o signal.o sys_or32.o \
+	   traps.o time.o irq.o entry.o ptrace.o signal.o \
 	   sys_call_table.o
 
 obj-$(CONFIG_MODULES)		+= module.o
diff --git a/arch/openrisc/kernel/asm-offsets.c b/arch/openrisc/kernel/asm-offsets.c
index 1a242a0..ddb7368 100644
--- a/arch/openrisc/kernel/asm-offsets.c
+++ b/arch/openrisc/kernel/asm-offsets.c
@@ -34,15 +34,11 @@
 #include <linux/mm.h>
 #include <linux/io.h>
 #include <linux/thread_info.h>
+#include <linux/kbuild.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 
-#define DEFINE(sym, val) \
-		asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
 int main(void)
 {
 	/* offsets into the task_struct */
diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S
index ddfcaa8..5e5b306 100644
--- a/arch/openrisc/kernel/entry.S
+++ b/arch/openrisc/kernel/entry.S
@@ -894,6 +894,16 @@ ENTRY(ret_from_fork)
 	l.jal	schedule_tail
 	 l.nop
 
+	/* Check if we are a kernel thread */
+	l.sfeqi	r20,0
+	l.bf	1f
+	 l.nop
+
+	/* ...we are a kernel thread so invoke the requested callback */
+	l.jalr	r20
+	 l.or	r3,r22,r0
+
+1:
 	/* _syscall_returns expect r11 to contain return value */
 	l.lwz	r11,PT_GPR11(r1)
 
@@ -915,26 +925,6 @@ ENTRY(ret_from_fork)
 	l.j	_syscall_return
 	 l.nop
 
-/* Since syscalls don't save call-clobbered registers, the args to
- * kernel_thread_helper will need to be passed through callee-saved
- * registers and copied to the parameter registers when the thread
- * begins running.
- *
- * See arch/openrisc/kernel/process.c:
- * The args are passed as follows:
- *   arg1 (r3) : passed in r20
- *   arg2 (r4) : passed in r22
- */
-
-ENTRY(_kernel_thread_helper)
-	l.or	r3,r20,r0
-	l.or	r4,r22,r0
-	l.movhi	r31,hi(kernel_thread_helper)
-	l.ori	r31,r31,lo(kernel_thread_helper)
-	l.jr	r31
-	 l.nop
-
-
 /* ========================================================[ switch ] === */
 
 /*
@@ -1044,8 +1034,13 @@ ENTRY(_switch)
 	/* Unwind stack to pre-switch state */
 	l.addi  r1,r1,(INT_FRAME_SIZE)
 
-	/* Return via the link-register back to where we 'came from', where that can be
-	 * either schedule() or return_from_fork()... */
+	/* Return via the link-register back to where we 'came from', where
+	 * that may be either schedule(), ret_from_fork(), or
+	 * ret_from_kernel_thread().  If we are returning to a new thread,
+	 * we are expected to have set up the arg to schedule_tail already,
+	 * hence we do so here unconditionally:
+	 */
+	l.lwz   r3,TI_STACK(r3)		/* Load 'prev' as schedule_tail arg */
 	l.jr	r9
 	 l.nop
 
@@ -1076,22 +1071,18 @@ _fork_save_extra_regs_and_call:
 	l.jr	r29
 	 l.sw    PT_GPR28(r1),r28
 
-ENTRY(sys_clone)
-	l.movhi	r29,hi(_sys_clone)
-	l.ori	r29,r29,lo(_sys_clone)
+ENTRY(__sys_clone)
+	l.movhi	r29,hi(sys_clone)
+	l.ori	r29,r29,lo(sys_clone)
 	l.j	_fork_save_extra_regs_and_call
 	 l.addi	r7,r1,0
 
-ENTRY(sys_fork)
-	l.movhi	r29,hi(_sys_fork)
-	l.ori	r29,r29,lo(_sys_fork)
+ENTRY(__sys_fork)
+	l.movhi	r29,hi(sys_fork)
+	l.ori	r29,r29,lo(sys_fork)
 	l.j	_fork_save_extra_regs_and_call
 	 l.addi	r3,r1,0
 
-ENTRY(sys_execve)
-	l.j	_sys_execve
-	 l.addi	r6,r1,0
-
 ENTRY(sys_sigaltstack)
 	l.j	_sys_sigaltstack
 	 l.addi	r5,r1,0
diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c
index c35f3ab..00c233b 100644
--- a/arch/openrisc/kernel/process.c
+++ b/arch/openrisc/kernel/process.c
@@ -109,66 +109,83 @@ void release_thread(struct task_struct *dead_task)
  */
 extern asmlinkage void ret_from_fork(void);
 
+/*
+ * copy_thread
+ * @clone_flags: flags
+ * @usp: user stack pointer or fn for kernel thread
+ * @arg: arg to fn for kernel thread; always NULL for userspace thread
+ * @p: the newly created task
+ * @regs: CPU context to copy for userspace thread; always NULL for kthread
+ *
+ * At the top of a newly initialized kernel stack are two stacked pt_reg
+ * structures.  The first (topmost) is the userspace context of the thread.
+ * The second is the kernelspace context of the thread.
+ *
+ * A kernel thread will not be returning to userspace, so the topmost pt_regs
+ * struct can be uninitialized; it _does_ need to exist, though, because
+ * a kernel thread can become a userspace thread by doing a kernel_execve, in
+ * which case the topmost context will be initialized and used for 'returning'
+ * to userspace.
+ *
+ * The second pt_reg struct needs to be initialized to 'return' to
+ * ret_from_fork.  A kernel thread will need to set r20 to the address of
+ * a function to call into (with arg in r22); userspace threads need to set
+ * r20 to NULL in which case ret_from_fork will just continue a return to
+ * userspace.
+ *
+ * A kernel thread 'fn' may return; this is effectively what happens when
+ * kernel_execve is called.  In that case, the userspace pt_regs must have
+ * been initialized (which kernel_execve takes care of, see start_thread
+ * below); ret_from_fork will then continue its execution causing the
+ * 'kernel thread' to return to userspace as a userspace thread.
+ */
+
 int
 copy_thread(unsigned long clone_flags, unsigned long usp,
-	    unsigned long unused, struct task_struct *p, struct pt_regs *regs)
+	    unsigned long arg, struct task_struct *p)
 {
-	struct pt_regs *childregs;
+	struct pt_regs *userregs;
 	struct pt_regs *kregs;
 	unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
-	struct thread_info *ti;
 	unsigned long top_of_kernel_stack;
 
 	top_of_kernel_stack = sp;
 
 	p->set_child_tid = p->clear_child_tid = NULL;
 
-	/* Copy registers */
-	/* redzone */
-	sp -= STACK_FRAME_OVERHEAD;
+	/* Locate userspace context on stack... */
+	sp -= STACK_FRAME_OVERHEAD;	/* redzone */
 	sp -= sizeof(struct pt_regs);
-	childregs = (struct pt_regs *)sp;
+	userregs = (struct pt_regs *) sp;
 
-	/* Copy parent registers */
-	*childregs = *regs;
+	/* ...and kernel context */
+	sp -= STACK_FRAME_OVERHEAD;	/* redzone */
+	sp -= sizeof(struct pt_regs);
+	kregs = (struct pt_regs *)sp;
 
-	if ((childregs->sr & SPR_SR_SM) == 1) {
-		/* for kernel thread, set `current_thread_info'
-		 * and stackptr in new task
-		 */
-		childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
-		childregs->gpr[10] = (unsigned long)task_thread_info(p);
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		memset(kregs, 0, sizeof(struct pt_regs));
+		kregs->gpr[20] = usp; /* fn, kernel thread */
+		kregs->gpr[22] = arg;
 	} else {
-		childregs->sp = usp;
-	}
-
-	childregs->gpr[11] = 0;	/* Result from fork() */
+		*userregs = *current_pt_regs();
 
-	/*
-	 * The way this works is that at some point in the future
-	 * some task will call _switch to switch to the new task.
-	 * That will pop off the stack frame created below and start
-	 * the new task running at ret_from_fork.  The new task will
-	 * do some house keeping and then return from the fork or clone
-	 * system call, using the stack frame created above.
-	 */
-	/* redzone */
-	sp -= STACK_FRAME_OVERHEAD;
-	sp -= sizeof(struct pt_regs);
-	kregs = (struct pt_regs *)sp;
+		if (usp)
+			userregs->sp = usp;
+		userregs->gpr[11] = 0;	/* Result from fork() */
 
-	ti = task_thread_info(p);
-	ti->ksp = sp;
+		kregs->gpr[20] = 0;	/* Userspace thread */
+	}
 
-	/* kregs->sp must store the location of the 'pre-switch' kernel stack
-	 * pointer... for a newly forked process, this is simply the top of
-	 * the kernel stack.
+	/*
+	 * _switch wants the kernel stack page in pt_regs->sp so that it
+	 * can restore it to thread_info->ksp... see _switch for details.
 	 */
 	kregs->sp = top_of_kernel_stack;
-	kregs->gpr[3] = (unsigned long)current;	/* arg to schedule_tail */
-	kregs->gpr[10] = (unsigned long)task_thread_info(p);
 	kregs->gpr[9] = (unsigned long)ret_from_fork;
 
+	task_thread_info(p)->ksp = (unsigned long)kregs;
+
 	return 0;
 }
 
@@ -177,16 +194,14 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
  */
 void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
 {
-	unsigned long sr = regs->sr & ~SPR_SR_SM;
+	unsigned long sr = mfspr(SPR_SR) & ~SPR_SR_SM;
 
 	set_fs(USER_DS);
-	memset(regs->gpr, 0, sizeof(regs->gpr));
+	memset(regs, 0, sizeof(struct pt_regs));
 
 	regs->pc = pc;
 	regs->sr = sr;
 	regs->sp = sp;
-
-/*	printk("start thread, ksp = %lx\n", current_thread_info()->ksp);*/
 }
 
 /* Fill in the fpu structure for a core dump.  */
@@ -237,74 +252,9 @@ void dump_elf_thread(elf_greg_t *dest, struct pt_regs* regs)
 	dest[35] = 0;
 }
 
-extern void _kernel_thread_helper(void);
-
-void __noreturn kernel_thread_helper(int (*fn) (void *), void *arg)
-{
-	do_exit(fn(arg));
-}
-
-/*
- * Create a kernel thread.
- */
-int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-
-	regs.gpr[20] = (unsigned long)fn;
-	regs.gpr[22] = (unsigned long)arg;
-	regs.sr = mfspr(SPR_SR);
-	regs.pc = (unsigned long)_kernel_thread_helper;
-
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
-		       0, &regs, 0, NULL, NULL);
-}
-
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage long _sys_execve(const char __user *name,
-			    const char __user * const __user *argv,
-			    const char __user * const __user *envp,
-			    struct pt_regs *regs)
-{
-	int error;
-	struct filename *filename;
-
-	filename = getname(name);
-	error = PTR_ERR(filename);
-
-	if (IS_ERR(filename))
-		goto out;
-
-	error = do_execve(filename->name, argv, envp, regs);
-	putname(filename);
-
-out:
-	return error;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
 	/* TODO */
 
 	return 0;
 }
-
-int kernel_execve(const char *filename, char *const argv[], char *const envp[])
-{
-	register long __res asm("r11") = __NR_execve;
-	register long __a asm("r3") = (long)(filename);
-	register long __b asm("r4") = (long)(argv);
-	register long __c asm("r5") = (long)(envp);
-	__asm__ volatile ("l.sys 1"
-			  : "=r" (__res), "=r"(__a), "=r"(__b), "=r"(__c)
-			  : "0"(__res), "1"(__a), "2"(__b), "3"(__c)
-			  : "r6", "r7", "r8", "r12", "r13", "r15",
-			    "r17", "r19", "r21", "r23", "r25", "r27",
-			    "r29", "r31");
-	__asm__ volatile ("l.nop");
-	return __res;
-}
diff --git a/arch/openrisc/kernel/sys_or32.c b/arch/openrisc/kernel/sys_or32.c
deleted file mode 100644
index 5706008..0000000
--- a/arch/openrisc/kernel/sys_or32.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * OpenRISC sys_or32.c
- *
- * Linux architectural port borrowing liberally from similar works of
- * others.  All original copyrights apply as per the original source
- * declaration.
- *
- * Modifications for the OpenRISC architecture:
- * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
- * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License
- *      as published by the Free Software Foundation; either version
- *      2 of the License, or (at your option) any later version.
- *
- * This file contains various random system calls that
- * have a non-standard calling sequence on some platforms.
- * Since we don't have to do any backwards compatibility, our
- * versions are done in the most "normal" way possible.
- */
-
-#include <linux/errno.h>
-#include <linux/syscalls.h>
-#include <linux/mm.h>
-
-#include <asm/syscalls.h>
-
-/* These are secondary entry points as the primary entry points are defined in
- * entry.S where we add the 'regs' parameter value
- */
-
-asmlinkage long _sys_clone(unsigned long clone_flags, unsigned long newsp,
-			   int __user *parent_tid, int __user *child_tid,
-			   struct pt_regs *regs)
-{
-	long ret;
-
-	/* FIXME: Is alignment necessary? */
-	/* newsp = ALIGN(newsp, 4); */
-
-	if (!newsp)
-		newsp = regs->sp;
-
-	ret = do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
-
-	return ret;
-}
-
-asmlinkage int _sys_fork(struct pt_regs *regs)
-{
-#ifdef CONFIG_MMU
-	return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
-#else
-	return -EINVAL;
-#endif
-}
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 11def45..e688a2b 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -22,6 +22,9 @@ config PARISC
 	select GENERIC_STRNCPY_FROM_USER
 	select HAVE_MOD_ARCH_SPECIFIC
 	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
+	select CLONE_BACKWARDS
 
 	help
 	  The PA-RISC microprocessor is designed by Hewlett-Packard and used
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index bac8deb..ff4c9fa 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -3,3 +3,4 @@ generic-y += word-at-a-time.h auxvec.h user.h cputime.h emergency-restart.h \
 	  segment.h topology.h vga.h device.h percpu.h hw_irq.h mutex.h \
 	  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
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h
index 0e8b7b8..09b54a5 100644
--- a/arch/parisc/include/asm/processor.h
+++ b/arch/parisc/include/asm/processor.h
@@ -326,7 +326,6 @@ struct mm_struct;
 
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm);
 
diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h
index 21abf4f..0fdb3c8 100644
--- a/arch/parisc/include/asm/signal.h
+++ b/arch/parisc/include/asm/signal.h
@@ -34,8 +34,6 @@ struct k_sigaction {
 	struct sigaction sa;
 };
 
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
 #include <asm/sigcontext.h>
 
 #endif /* !__ASSEMBLY */
diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h
index 541639c..1efef41 100644
--- a/arch/parisc/include/asm/unistd.h
+++ b/arch/parisc/include/asm/unistd.h
@@ -163,6 +163,10 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)	\
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_CLONE
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/parisc/include/uapi/asm/ioctls.h b/arch/parisc/include/uapi/asm/ioctls.h
index 054ec06..66719c3 100644
--- a/arch/parisc/include/uapi/asm/ioctls.h
+++ b/arch/parisc/include/uapi/asm/ioctls.h
@@ -55,6 +55,9 @@
 #define TIOCGDEV	_IOR('T',0x32, int)  /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
 #define TIOCVHANGUP	0x5437
+#define TIOCGPKT	_IOR('T', 0x38, int) /* Get packet mode state */
+#define TIOCGPTLCK	_IOR('T', 0x39, int) /* Get Pty lock state */
+#define TIOCGEXCL	_IOR('T', 0x40, int) /* Get exclusive mode state */
 
 #define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
 #define FIOCLEX		0x5451
diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h
index 12219eb..294d251 100644
--- a/arch/parisc/include/uapi/asm/mman.h
+++ b/arch/parisc/include/uapi/asm/mman.h
@@ -70,4 +70,15 @@
 #define MAP_FILE	0
 #define MAP_VARIABLE	0
 
+/*
+ * When MAP_HUGETLB is set bits [26:31] encode the log2 of the huge page size.
+ * This gives us 6 bits, which is enough until someone invents 128 bit address
+ * spaces.
+ *
+ * Assume these are all power of twos.
+ * When 0 use the default page size.
+ */
+#define MAP_HUGE_SHIFT	26
+#define MAP_HUGE_MASK	0x3f
+
 #endif /* __PARISC_MMAN_H__ */
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
index 1b52c2c..d9ff473 100644
--- a/arch/parisc/include/uapi/asm/socket.h
+++ b/arch/parisc/include/uapi/asm/socket.h
@@ -48,6 +48,7 @@
 /* Socket filtering */
 #define SO_ATTACH_FILTER        0x401a
 #define SO_DETACH_FILTER        0x401b
+#define SO_GET_FILTER		SO_ATTACH_FILTER
 
 #define SO_ACCEPTCONN		0x401c
 
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 18670a0..bfb4424 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -708,59 +708,9 @@ ENTRY(end_fault_vector)
 	.import		do_cpu_irq_mask,code
 
 	/*
-	 * r26 = function to be called
-	 * r25 = argument to pass in
-	 * r24 = flags for do_fork()
-	 *
-	 * Kernel threads don't ever return, so they don't need
-	 * a true register context. We just save away the arguments
-	 * for copy_thread/ret_ to properly set up the child.
-	 */
-
-#define CLONE_VM 0x100	/* Must agree with <linux/sched.h> */
-#define CLONE_UNTRACED 0x00800000
-
-	.import do_fork
-ENTRY(__kernel_thread)
-	STREG	%r2, -RP_OFFSET(%r30)
-
-	copy	%r30, %r1
-	ldo	PT_SZ_ALGN(%r30),%r30
-#ifdef CONFIG_64BIT
-	/* Yo, function pointers in wide mode are little structs... -PB */
-	ldd	24(%r26), %r2
-	STREG	%r2, PT_GR27(%r1)	/* Store childs %dp */
-	ldd	16(%r26), %r26
-
-	STREG	%r22, PT_GR22(%r1)	/* save r22 (arg5) */
-	copy	%r0, %r22		/* user_tid */
-#endif
-	STREG	%r26, PT_GR26(%r1)  /* Store function & argument for child */
-	STREG	%r25, PT_GR25(%r1)
-	ldil	L%CLONE_UNTRACED, %r26
-	ldo	CLONE_VM(%r26), %r26   /* Force CLONE_VM since only init_mm */
-	or	%r26, %r24, %r26      /* will have kernel mappings.	 */
-	ldi	1, %r25			/* stack_start, signals kernel thread */
-	stw	%r0, -52(%r30)	     	/* user_tid */
-#ifdef CONFIG_64BIT
-	ldo	-16(%r30),%r29		/* Reference param save area */
-#endif
-	BL	do_fork, %r2
-	copy	%r1, %r24		/* pt_regs */
-
-	/* Parent Returns here */
-
-	LDREG	-PT_SZ_ALGN-RP_OFFSET(%r30), %r2
-	ldo	-PT_SZ_ALGN(%r30), %r30
-	bv	%r0(%r2)
-	nop
-ENDPROC(__kernel_thread)
-
-	/*
 	 * Child Returns here
 	 *
-	 * copy_thread moved args from temp save area set up above
-	 * into task save area.
+	 * copy_thread moved args into task save area.
 	 */
 
 ENTRY(ret_from_kernel_thread)
@@ -769,51 +719,17 @@ ENTRY(ret_from_kernel_thread)
 	BL	schedule_tail, %r2
 	nop
 
-	LDREG	TI_TASK-THREAD_SZ_ALGN(%r30), %r1
+	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
 	LDREG	TASK_PT_GR25(%r1), %r26
 #ifdef CONFIG_64BIT
 	LDREG	TASK_PT_GR27(%r1), %r27
-	LDREG	TASK_PT_GR22(%r1), %r22
 #endif
 	LDREG	TASK_PT_GR26(%r1), %r1
 	ble	0(%sr7, %r1)
 	copy	%r31, %r2
-
-#ifdef CONFIG_64BIT
-	ldo	-16(%r30),%r29		/* Reference param save area */
-	loadgp				/* Thread could have been in a module */
-#endif
-#ifndef CONFIG_64BIT
-	b	sys_exit
-#else
-	load32	sys_exit, %r1
-	bv	%r0(%r1)
-#endif
-	ldi	0, %r26
-ENDPROC(ret_from_kernel_thread)
-
-	.import	sys_execve, code
-ENTRY(__execve)
-	copy	%r2, %r15
-	copy	%r30, %r16
-	ldo	PT_SZ_ALGN(%r30), %r30
-	STREG	%r26, PT_GR26(%r16)
-	STREG	%r25, PT_GR25(%r16)
-	STREG	%r24, PT_GR24(%r16)
-#ifdef CONFIG_64BIT
-	ldo	-16(%r30),%r29		/* Reference param save area */
-#endif
-	BL	sys_execve, %r2
-	copy	%r16, %r26
-
-	cmpib,=,n 0,%r28,intr_return    /* forward */
-
-	/* yes, this will trap and die. */
-	copy	%r15, %r2
-	copy	%r16, %r30
-	bv	%r0(%r2)
+	b	finish_child_return
 	nop
-ENDPROC(__execve)
+ENDPROC(ret_from_kernel_thread)
 
 
 	/*
@@ -1772,151 +1688,36 @@ dtlb_fault:
 	LDREG   PT_GR18(\regs),%r18
 	.endm
 
-ENTRY(sys_fork_wrapper)
+	.macro	fork_like name
+ENTRY(sys_\name\()_wrapper)
 	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
 	ldo	TASK_REGS(%r1),%r1
 	reg_save %r1
-	mfctl	%cr27, %r3
-	STREG	%r3, PT_CR27(%r1)
-
-	STREG	%r2,-RP_OFFSET(%r30)
-	ldo	FRAME_SIZE(%r30),%r30
-#ifdef CONFIG_64BIT
-	ldo	-16(%r30),%r29		/* Reference param save area */
-#endif
-
-	/* These are call-clobbered registers and therefore
-	   also syscall-clobbered (we hope). */
-	STREG	%r2,PT_GR19(%r1)	/* save for child */
-	STREG	%r30,PT_GR21(%r1)
-
-	LDREG	PT_GR30(%r1),%r25
-	copy	%r1,%r24
-	BL	sys_clone,%r2
-	ldi	SIGCHLD,%r26
-
-	LDREG	-RP_OFFSET-FRAME_SIZE(%r30),%r2
-wrapper_exit:
-	ldo	-FRAME_SIZE(%r30),%r30		/* get the stackframe */
-	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
-	ldo	TASK_REGS(%r1),%r1	 /* get pt regs */
-
-	LDREG	PT_CR27(%r1), %r3
-	mtctl	%r3, %cr27
-	reg_restore %r1
+	mfctl	%cr27, %r28
+	b	sys_\name
+	STREG	%r28, PT_CR27(%r1)
+ENDPROC(sys_\name\()_wrapper)
+	.endm
 
-	/* strace expects syscall # to be preserved in r20 */
-	ldi	__NR_fork,%r20
-	bv %r0(%r2)
-	STREG	%r20,PT_GR20(%r1)
-ENDPROC(sys_fork_wrapper)
+fork_like clone
+fork_like fork
+fork_like vfork
 
 	/* Set the return value for the child */
 ENTRY(child_return)
 	BL	schedule_tail, %r2
 	nop
+finish_child_return:
+	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
+	ldo	TASK_REGS(%r1),%r1	 /* get pt regs */
 
-	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1
-	LDREG	TASK_PT_GR19(%r1),%r2
-	b	wrapper_exit
+	LDREG	PT_CR27(%r1), %r3
+	mtctl	%r3, %cr27
+	reg_restore %r1
+	b	syscall_exit
 	copy	%r0,%r28
 ENDPROC(child_return)
 
-
-ENTRY(sys_clone_wrapper)
-	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
-	ldo	TASK_REGS(%r1),%r1	/* get pt regs */
-	reg_save %r1
-	mfctl	%cr27, %r3
-	STREG	%r3, PT_CR27(%r1)
-
-	STREG	%r2,-RP_OFFSET(%r30)
-	ldo	FRAME_SIZE(%r30),%r30
-#ifdef CONFIG_64BIT
-	ldo	-16(%r30),%r29		/* Reference param save area */
-#endif
-
-	/* WARNING - Clobbers r19 and r21, userspace must save these! */
-	STREG	%r2,PT_GR19(%r1)	/* save for child */
-	STREG	%r30,PT_GR21(%r1)
-	BL	sys_clone,%r2
-	copy	%r1,%r24
-
-	b	wrapper_exit
-	LDREG	-RP_OFFSET-FRAME_SIZE(%r30),%r2
-ENDPROC(sys_clone_wrapper)
-
-
-ENTRY(sys_vfork_wrapper)
-	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
-	ldo	TASK_REGS(%r1),%r1	/* get pt regs */
-	reg_save %r1
-	mfctl	%cr27, %r3
-	STREG	%r3, PT_CR27(%r1)
-
-	STREG	%r2,-RP_OFFSET(%r30)
-	ldo	FRAME_SIZE(%r30),%r30
-#ifdef CONFIG_64BIT
-	ldo	-16(%r30),%r29		/* Reference param save area */
-#endif
-
-	STREG	%r2,PT_GR19(%r1)	/* save for child */
-	STREG	%r30,PT_GR21(%r1)
-
-	BL	sys_vfork,%r2
-	copy	%r1,%r26
-
-	b	wrapper_exit
-	LDREG	-RP_OFFSET-FRAME_SIZE(%r30),%r2
-ENDPROC(sys_vfork_wrapper)
-
-	
-	.macro  execve_wrapper execve
-	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
-	ldo	TASK_REGS(%r1),%r1	/* get pt regs */
-
-	/*
-	 * Do we need to save/restore r3-r18 here?
-	 * I don't think so. why would new thread need old
-	 * threads registers?
-	 */
-
-	/* %arg0 - %arg3 are already saved for us. */
-
-	STREG %r2,-RP_OFFSET(%r30)
-	ldo FRAME_SIZE(%r30),%r30
-#ifdef CONFIG_64BIT
-	ldo	-16(%r30),%r29		/* Reference param save area */
-#endif
-	BL \execve,%r2
-	copy %r1,%arg0
-
-	ldo -FRAME_SIZE(%r30),%r30
-	LDREG -RP_OFFSET(%r30),%r2
-
-	/* If exec succeeded we need to load the args */
-
-	ldo -1024(%r0),%r1
-	cmpb,>>= %r28,%r1,error_\execve
-	copy %r2,%r19
-
-error_\execve:
-	bv %r0(%r19)
-	nop
-	.endm
-
-	.import sys_execve
-ENTRY(sys_execve_wrapper)
-	execve_wrapper sys_execve
-ENDPROC(sys_execve_wrapper)
-
-#ifdef CONFIG_64BIT
-	.import sys32_execve
-ENTRY(sys32_execve_wrapper)
-	execve_wrapper sys32_execve
-ENDPROC(sys32_execve_wrapper)
-#endif
-
 ENTRY(sys_rt_sigreturn_wrapper)
 	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26
 	ldo	TASK_REGS(%r26),%r26	/* get pt regs */
diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c
index 8823863..efc5e7d 100644
--- a/arch/parisc/kernel/pdc_cons.c
+++ b/arch/parisc/kernel/pdc_cons.c
@@ -186,13 +186,13 @@ static int __init pdc_console_tty_driver_init(void)
 	printk(KERN_INFO "The PDC console driver is still registered, removing CON_BOOT flag\n");
 	pdc_cons.flags &= ~CON_BOOT;
 
-	tty_port_init(&tty_port);
-
 	pdc_console_tty_driver = alloc_tty_driver(1);
 
 	if (!pdc_console_tty_driver)
 		return -ENOMEM;
 
+	tty_port_init(&tty_port);
+
 	pdc_console_tty_driver->driver_name = "pdc_cons";
 	pdc_console_tty_driver->name = "ttyB";
 	pdc_console_tty_driver->major = MUX_MAJOR;
@@ -207,6 +207,7 @@ static int __init pdc_console_tty_driver_init(void)
 	err = tty_register_driver(pdc_console_tty_driver);
 	if (err) {
 		printk(KERN_ERR "Unable to register the PDC console TTY driver\n");
+		tty_port_destroy(&tty_port);
 		return err;
 	}
 
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index cbc3721..d135072 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -52,6 +52,7 @@
 
 #include <asm/io.h>
 #include <asm/asm-offsets.h>
+#include <asm/assembly.h>
 #include <asm/pdc.h>
 #include <asm/pdc_chassis.h>
 #include <asm/pgalloc.h>
@@ -165,23 +166,6 @@ void (*pm_power_off)(void) = machine_power_off;
 EXPORT_SYMBOL(pm_power_off);
 
 /*
- * Create a kernel thread
- */
-
-extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-
-	/*
-	 * FIXME: Once we are sure we don't need any debug here,
-	 *	  kernel_thread can become a #define.
-	 */
-
-	return __kernel_thread(fn, arg, flags);
-}
-EXPORT_SYMBOL(kernel_thread);
-
-/*
  * Free current thread data structures etc..
  */
 void exit_thread(void)
@@ -218,48 +202,11 @@ int dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *r)
 	return 1;
 }
 
-/* Note that "fork()" is implemented in terms of clone, with
-   parameters (SIGCHLD, regs->gr[30], regs). */
-int
-sys_clone(unsigned long clone_flags, unsigned long usp,
-	  struct pt_regs *regs)
-{
-  	/* Arugments from userspace are:
-	   r26 = Clone flags.
-	   r25 = Child stack.
-	   r24 = parent_tidptr.
-	   r23 = Is the TLS storage descriptor 
-	   r22 = child_tidptr 
-	   
-	   However, these last 3 args are only examined
-	   if the proper flags are set. */
-	int __user *parent_tidptr = (int __user *)regs->gr[24];
-	int __user *child_tidptr  = (int __user *)regs->gr[22];
-
-	/* usp must be word aligned.  This also prevents users from
-	 * passing in the value 1 (which is the signal for a special
-	 * return for a kernel thread) */
-	usp = ALIGN(usp, 4);
-
-	/* A zero value for usp means use the current stack */
-	if (usp == 0)
-	  usp = regs->gr[30];
-
-	return do_fork(clone_flags, usp, regs, 0, parent_tidptr, child_tidptr);
-}
-
-int
-sys_vfork(struct pt_regs *regs)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gr[30], regs, 0, NULL, NULL);
-}
-
 int
 copy_thread(unsigned long clone_flags, unsigned long usp,
-	    unsigned long unused,	/* in ia64 this is "user_stack_size" */
-	    struct task_struct * p, struct pt_regs * pregs)
+	    unsigned long arg, struct task_struct *p)
 {
-	struct pt_regs * cregs = &(p->thread.regs);
+	struct pt_regs *cregs = &(p->thread.regs);
 	void *stack = task_stack_page(p);
 	
 	/* We have to use void * instead of a function pointer, because
@@ -270,48 +217,39 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
 #ifdef CONFIG_HPUX
 	extern void * const hpux_child_return;
 #endif
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		memset(cregs, 0, sizeof(struct pt_regs));
+		if (!usp) /* idle thread */
+			return 0;
 
-	*cregs = *pregs;
-
-	/* Set the return value for the child.  Note that this is not
-           actually restored by the syscall exit path, but we put it
-           here for consistency in case of signals. */
-	cregs->gr[28] = 0; /* child */
-
-	/*
-	 * We need to differentiate between a user fork and a
-	 * kernel fork. We can't use user_mode, because the
-	 * the syscall path doesn't save iaoq. Right now
-	 * We rely on the fact that kernel_thread passes
-	 * in zero for usp.
-	 */
-	if (usp == 1) {
 		/* kernel thread */
-		cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN;
 		/* Must exit via ret_from_kernel_thread in order
 		 * to call schedule_tail()
 		 */
+		cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;
 		cregs->kpc = (unsigned long) &ret_from_kernel_thread;
 		/*
 		 * Copy function and argument to be called from
 		 * ret_from_kernel_thread.
 		 */
 #ifdef CONFIG_64BIT
-		cregs->gr[27] = pregs->gr[27];
+		cregs->gr[27] = ((unsigned long *)usp)[3];
+		cregs->gr[26] = ((unsigned long *)usp)[2];
+#else
+		cregs->gr[26] = usp;
 #endif
-		cregs->gr[26] = pregs->gr[26];
-		cregs->gr[25] = pregs->gr[25];
+		cregs->gr[25] = arg;
 	} else {
 		/* user thread */
-		/*
-		 * Note that the fork wrappers are responsible
-		 * for setting gr[21].
-		 */
-
-		/* Use same stack depth as parent */
-		cregs->ksp = (unsigned long)stack
-			+ (pregs->gr[21] & (THREAD_SIZE - 1));
-		cregs->gr[30] = usp;
+		/* usp must be word aligned.  This also prevents users from
+		 * passing in the value 1 (which is the signal for a special
+		 * return for a kernel thread) */
+		if (usp) {
+			usp = ALIGN(usp, 4);
+			if (likely(usp))
+				cregs->gr[30] = usp;
+		}
+		cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;
 		if (personality(p->personality) == PER_HPUX) {
 #ifdef CONFIG_HPUX
 			cregs->kpc = (unsigned long) &hpux_child_return;
@@ -323,8 +261,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
 		}
 		/* Setup thread TLS area from the 4th parameter in clone */
 		if (clone_flags & CLONE_SETTLS)
-		  cregs->cr27 = pregs->gr[23];
-	
+			cregs->cr27 = cregs->gr[23];
 	}
 
 	return 0;
@@ -335,39 +272,6 @@ unsigned long thread_saved_pc(struct task_struct *t)
 	return t->thread.regs.kpc;
 }
 
-/*
- * sys_execve() executes a new program.
- */
-
-asmlinkage int sys_execve(struct pt_regs *regs)
-{
-	int error;
-	struct filename *filename;
-
-	filename = getname((const char __user *) regs->gr[26]);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-	error = do_execve(filename->name,
-			  (const char __user *const __user *) regs->gr[25],
-			  (const char __user *const __user *) regs->gr[24],
-			  regs);
-	putname(filename);
-out:
-
-	return error;
-}
-
-extern int __execve(const char *filename,
-		    const char *const argv[],
-		    const char *const envp[], struct task_struct *task);
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	return __execve(filename, argv, envp, current);
-}
-
 unsigned long
 get_wchan(struct task_struct *p)
 {
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
index bf5b93a..9cfdaa1 100644
--- a/arch/parisc/kernel/sys_parisc32.c
+++ b/arch/parisc/kernel/sys_parisc32.c
@@ -53,28 +53,6 @@
 #define DBG(x)
 #endif
 
-/*
- * sys32_execve() executes a new program.
- */
-
-asmlinkage int sys32_execve(struct pt_regs *regs)
-{
-	int error;
-	struct filename *filename;
-
-	DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));
-	filename = getname((const char __user *) regs->gr[26]);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-	error = compat_do_execve(filename->name, compat_ptr(regs->gr[25]),
-				 compat_ptr(regs->gr[24]), regs);
-	putname(filename);
-out:
-
-	return error;
-}
-
 asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23,
 	int r22, int r21, int r20)
 {
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 3735abd..cb2da96 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -66,7 +66,7 @@
 	ENTRY_SAME(creat)
 	ENTRY_SAME(link)
 	ENTRY_SAME(unlink)		/* 10 */
-	ENTRY_DIFF(execve_wrapper)
+	ENTRY_COMP(execve)
 	ENTRY_SAME(chdir)
 	/* See comments in kernel/time.c!!! Maybe we don't need this? */
 	ENTRY_COMP(time)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index a902a5c..56bb256 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -87,9 +87,6 @@ config GENERIC_GPIO
 	help
 	  Generic GPIO API support
 
-config ARCH_NO_VIRT_TO_BUS
-	def_bool PPC64
-
 config PPC
 	bool
 	default y
@@ -101,6 +98,7 @@ config PPC
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select SYSCTL_EXCEPTION_TRACE
 	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select ARCH_NO_VIRT_TO_BUS if PPC64
 	select HAVE_IDE
 	select HAVE_IOREMAP_PROT
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
@@ -144,6 +142,8 @@ config PPC
 	select GENERIC_KERNEL_THREAD
 	select HAVE_MOD_ARCH_SPECIFIC
 	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_EXECVE
+	select CLONE_BACKWARDS
 
 config EARLY_PRINTK
 	bool
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 159e94f..b639852 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -181,7 +181,7 @@ $(BOOT_TARGETS2): vmlinux
 bootwrapper_install:
 	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
 
-%.dtb:
+%.dtb: scripts
 	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
 
 define archhelp
diff --git a/arch/powerpc/boot/dts/a3m071.dts b/arch/powerpc/boot/dts/a3m071.dts
new file mode 100644
index 0000000..46b30f2
--- /dev/null
+++ b/arch/powerpc/boot/dts/a3m071.dts
@@ -0,0 +1,153 @@
+/*
+ * a3m071 board Device Tree Source
+ *
+ * Copyright 2012 Stefan Roese <sr@denx.de>
+ *
+ * Copyright (C) 2011 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.de>
+ *
+ * Copyright (C) 2007 Semihalf
+ * Marian Balakowicz <m8@semihalf.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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/ "mpc5200b.dtsi"
+
+/ {
+	model = "anonymous,a3m071";
+	compatible = "anonymous,a3m071";
+
+	soc5200@f0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc5200b-immr";
+		ranges = <0 0xf0000000 0x0000c000>;
+		reg = <0xf0000000 0x00000100>;
+		bus-frequency = <0>; /* From boot loader */
+		system-frequency = <0>; /* From boot loader */
+
+		cdm@200 {
+			fsl,init-ext-48mhz-en = <0x0>;
+			fsl,init-fd-enable = <0x01>;
+			fsl,init-fd-counters = <0x3333>;
+		};
+
+		timer@600 {
+			fsl,has-wdt;
+		};
+
+		spi@f00 {
+			status = "disabled";
+		};
+
+		usb: usb@1000 {
+			status = "disabled";
+		};
+
+		psc@2000 {
+			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+			reg = <0x2000 0x100>;
+			interrupts = <2 1 0>;
+		};
+
+		psc@2200 {
+			status = "disabled";
+		};
+
+		psc@2400 {
+			status = "disabled";
+		};
+
+		psc@2600 {
+			status = "disabled";
+		};
+
+		psc@2800 {
+			status = "disabled";
+		};
+
+		psc@2c00 {		// PSC6
+			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+			reg = <0x2c00 0x100>;
+			interrupts = <2 4 0>;
+		};
+
+		ethernet@3000 {
+			phy-handle = <&phy0>;
+		};
+
+		mdio@3000 {
+			phy0: ethernet-phy@3 {
+				reg = <0x03>;
+			};
+		};
+
+		ata@3a00 {
+			status = "disabled";
+		};
+
+		i2c@3d00 {
+			status = "disabled";
+		};
+
+		i2c@3d40 {
+			rtc@51 {
+				compatible = "epson,pcf8563";
+				reg = <0x51>;
+			};
+		};
+	};
+
+	localbus {
+		compatible = "fsl,mpc5200b-lpb","simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges = <0 0 0xfc000000 0x02000000
+			  3 0 0xe9000000 0x00080000
+			  5 0 0xe8000000 0x00010000>;
+
+		flash@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0 0x0 0x02000000>;
+			compatible = "cfi-flash";
+			bank-width = <2>;
+			partition@0x0 {
+				label = "u-boot";
+				reg = <0x00000000 0x00040000>;
+				read-only;
+			};
+			partition@0x00040000 {
+				label = "env";
+				reg = <0x00040000 0x00020000>;
+			};
+			partition@0x00060000 {
+				label = "dtb";
+				reg = <0x00060000 0x00020000>;
+			};
+			partition@0x00080000 {
+				label = "kernel";
+				reg = <0x00080000 0x00500000>;
+			};
+			partition@0x00580000 {
+				label = "root";
+				reg = <0x00580000 0x00A80000>;
+			};
+		};
+
+		fpga@3,0 {
+			compatible = "anonymous,a3m071-fpga";
+			reg = <3 0x0 0x00080000
+			       5 0x0 0x00010000>;
+			interrupts = <0 0 3>;  /* level low */
+		};
+	};
+
+	pci@f0000d00 {
+		status = "disabled";
+	};
+};
diff --git a/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi
index 64b6abe..5d7205b 100644
--- a/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi
@@ -354,4 +354,5 @@
 /include/ "qoriq-sata2-0.dtsi"
 /include/ "qoriq-sata2-1.dtsi"
 /include/ "qoriq-sec4.2-0.dtsi"
+/include/ "qoriq-raid1.0-0.dtsi"
 };
diff --git a/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi
index 0a198b0..8df47fc 100644
--- a/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi
@@ -73,6 +73,12 @@
 		rtic_c = &rtic_c;
 		rtic_d = &rtic_d;
 		sec_mon = &sec_mon;
+
+		raideng = &raideng;
+		raideng_jr0 = &raideng_jr0;
+		raideng_jr1 = &raideng_jr1;
+		raideng_jr2 = &raideng_jr2;
+		raideng_jr3 = &raideng_jr3;
 	};
 
 	cpus {
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi
new file mode 100644
index 0000000..8d2e8aa
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi
@@ -0,0 +1,85 @@
+/*
+ * QorIQ RAID 1.0 device tree stub [ controller @ offset 0x320000 ]
+ *
+ * Copyright 2012 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.
+ */
+
+raideng: raideng@320000 {
+	compatible = "fsl,raideng-v1.0";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	reg = <0x320000 0x10000>;
+	ranges = <0 0x320000 0x10000>;
+
+	raideng_jq0@1000 {
+		compatible = "fsl,raideng-v1.0-job-queue";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x1000 0x1000>;
+		ranges = <0x0 0x1000 0x1000>;
+
+		raideng_jr0: jr@0 {
+			compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-hp-ring";
+			reg = <0x0 0x400>;
+			interrupts = <139 2 0 0>;
+			interrupt-parent = <&mpic>;
+		};
+
+		raideng_jr1: jr@400 {
+			compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-lp-ring";
+			reg = <0x400 0x400>;
+			interrupts = <140 2 0 0>;
+			interrupt-parent = <&mpic>;
+		};
+	};
+
+	raideng_jq1@2000 {
+		compatible = "fsl,raideng-v1.0-job-queue";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x2000 0x1000>;
+		ranges = <0x0 0x2000 0x1000>;
+
+		raideng_jr2: jr@0 {
+			compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-hp-ring";
+			reg = <0x0 0x400>;
+			interrupts = <141 2 0 0>;
+			interrupt-parent = <&mpic>;
+		};
+
+		raideng_jr3: jr@400 {
+			compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-lp-ring";
+			reg = <0x400 0x400>;
+			interrupts = <142 2 0 0>;
+			interrupt-parent = <&mpic>;
+		};
+	};
+};
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 1f710a3..5b8e1e5 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -2,7 +2,7 @@ CONFIG_PPC64=y
 CONFIG_ALTIVEC=y
 CONFIG_VSX=y
 CONFIG_SMP=y
-CONFIG_NR_CPUS=1024
+CONFIG_NR_CPUS=2048
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index a4fe15e..650757c 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -1,4 +1,4 @@
 
-
 generic-y += clkdev.h
 generic-y += rwsem.h
+generic-y += trace_clock.h
diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
index dc2cf9c..ef918a2 100644
--- a/arch/powerpc/include/asm/bitops.h
+++ b/arch/powerpc/include/asm/bitops.h
@@ -52,8 +52,6 @@
 #define smp_mb__before_clear_bit()	smp_mb()
 #define smp_mb__after_clear_bit()	smp_mb()
 
-#define BITOP_MASK(nr)		(1UL << ((nr) % BITS_PER_LONG))
-#define BITOP_WORD(nr)		((nr) / BITS_PER_LONG)
 #define BITOP_LE_SWIZZLE	((BITS_PER_LONG-1) & ~0x7)
 
 /* Macro for generating the ***_bits() functions */
@@ -83,22 +81,22 @@ DEFINE_BITOP(change_bits, xor, "", "")
 
 static __inline__ void set_bit(int nr, volatile unsigned long *addr)
 {
-	set_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr));
+	set_bits(BIT_MASK(nr), addr + BIT_WORD(nr));
 }
 
 static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
 {
-	clear_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr));
+	clear_bits(BIT_MASK(nr), addr + BIT_WORD(nr));
 }
 
 static __inline__ void clear_bit_unlock(int nr, volatile unsigned long *addr)
 {
-	clear_bits_unlock(BITOP_MASK(nr), addr + BITOP_WORD(nr));
+	clear_bits_unlock(BIT_MASK(nr), addr + BIT_WORD(nr));
 }
 
 static __inline__ void change_bit(int nr, volatile unsigned long *addr)
 {
-	change_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr));
+	change_bits(BIT_MASK(nr), addr + BIT_WORD(nr));
 }
 
 /* Like DEFINE_BITOP(), with changes to the arguments to 'op' and the output
@@ -136,26 +134,26 @@ DEFINE_TESTOP(test_and_change_bits, xor, PPC_ATOMIC_ENTRY_BARRIER,
 static __inline__ int test_and_set_bit(unsigned long nr,
 				       volatile unsigned long *addr)
 {
-	return test_and_set_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)) != 0;
+	return test_and_set_bits(BIT_MASK(nr), addr + BIT_WORD(nr)) != 0;
 }
 
 static __inline__ int test_and_set_bit_lock(unsigned long nr,
 				       volatile unsigned long *addr)
 {
-	return test_and_set_bits_lock(BITOP_MASK(nr),
-				addr + BITOP_WORD(nr)) != 0;
+	return test_and_set_bits_lock(BIT_MASK(nr),
+				addr + BIT_WORD(nr)) != 0;
 }
 
 static __inline__ int test_and_clear_bit(unsigned long nr,
 					 volatile unsigned long *addr)
 {
-	return test_and_clear_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)) != 0;
+	return test_and_clear_bits(BIT_MASK(nr), addr + BIT_WORD(nr)) != 0;
 }
 
 static __inline__ int test_and_change_bit(unsigned long nr,
 					  volatile unsigned long *addr)
 {
-	return test_and_change_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)) != 0;
+	return test_and_change_bits(BIT_MASK(nr), addr + BIT_WORD(nr)) != 0;
 }
 
 #include <asm-generic/bitops/non-atomic.h>
@@ -280,61 +278,8 @@ unsigned long __arch_hweight64(__u64 w);
 #include <asm-generic/bitops/find.h>
 
 /* Little-endian versions */
+#include <asm-generic/bitops/le.h>
 
-static __inline__ int test_bit_le(unsigned long nr,
-				  __const__ void *addr)
-{
-	__const__ unsigned char	*tmp = (__const__ unsigned char *) addr;
-	return (tmp[nr >> 3] >> (nr & 7)) & 1;
-}
-
-static inline void set_bit_le(int nr, void *addr)
-{
-	set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
-}
-
-static inline void clear_bit_le(int nr, void *addr)
-{
-	clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
-}
-
-static inline void __set_bit_le(int nr, void *addr)
-{
-	__set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
-}
-
-static inline void __clear_bit_le(int nr, void *addr)
-{
-	__clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
-}
-
-static inline int test_and_set_bit_le(int nr, void *addr)
-{
-	return test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
-}
-
-static inline int test_and_clear_bit_le(int nr, void *addr)
-{
-	return test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
-}
-
-static inline int __test_and_set_bit_le(int nr, void *addr)
-{
-	return __test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
-}
-
-static inline int __test_and_clear_bit_le(int nr, void *addr)
-{
-	return __test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
-}
-
-#define find_first_zero_bit_le(addr, size) \
-	find_next_zero_bit_le((addr), (size), 0)
-unsigned long find_next_zero_bit_le(const void *addr,
-				    unsigned long size, unsigned long offset);
-
-unsigned long find_next_bit_le(const void *addr,
-				    unsigned long size, unsigned long offset);
 /* Bitmap functions for the ext2 filesystem */
 
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 21a0687..76f81bd 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -401,6 +401,14 @@ extern const char *powerpc_base_platform;
 	    CPU_FTR_DSCR | CPU_FTR_SAO  | CPU_FTR_ASYM_SMT | \
 	    CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
 	    CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY)
+#define CPU_FTRS_POWER8 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
+	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_206 |\
+	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
+	    CPU_FTR_COHERENT_ICACHE | \
+	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
+	    CPU_FTR_DSCR | CPU_FTR_SAO  | \
+	    CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
+	    CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY)
 #define CPU_FTRS_CELL	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -421,8 +429,8 @@ extern const char *powerpc_base_platform;
 #define CPU_FTRS_POSSIBLE	\
 	    (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 |	\
 	    CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_POWER6 |	\
-	    CPU_FTRS_POWER7 | CPU_FTRS_CELL | CPU_FTRS_PA6T |		\
-	    CPU_FTR_VSX)
+	    CPU_FTRS_POWER7 | CPU_FTRS_POWER8 | CPU_FTRS_CELL |		\
+	    CPU_FTRS_PA6T | CPU_FTR_VSX)
 #endif
 #else
 enum {
diff --git a/arch/powerpc/include/asm/dbell.h b/arch/powerpc/include/asm/dbell.h
index 154c067..607e4ee 100644
--- a/arch/powerpc/include/asm/dbell.h
+++ b/arch/powerpc/include/asm/dbell.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2009 Freescale Semicondutor, Inc.
+ * 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
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 7816087..e27e9ad 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -172,6 +172,7 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
 	struct dma_map_ops *dma_ops = get_dma_ops(dev);
 
+	debug_dma_mapping_error(dev, dma_addr);
 	if (dma_ops->mapping_error)
 		return dma_ops->mapping_error(dev, dma_addr);
 
diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h
index bf2c06c..d3d6342 100644
--- a/arch/powerpc/include/asm/epapr_hcalls.h
+++ b/arch/powerpc/include/asm/epapr_hcalls.h
@@ -50,64 +50,13 @@
 #ifndef _EPAPR_HCALLS_H
 #define _EPAPR_HCALLS_H
 
+#include <uapi/asm/epapr_hcalls.h>
+
+#ifndef __ASSEMBLY__
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/byteorder.h>
 
-#define EV_BYTE_CHANNEL_SEND		1
-#define EV_BYTE_CHANNEL_RECEIVE		2
-#define EV_BYTE_CHANNEL_POLL		3
-#define EV_INT_SET_CONFIG		4
-#define EV_INT_GET_CONFIG		5
-#define EV_INT_SET_MASK			6
-#define EV_INT_GET_MASK			7
-#define EV_INT_IACK			9
-#define EV_INT_EOI			10
-#define EV_INT_SEND_IPI			11
-#define EV_INT_SET_TASK_PRIORITY	12
-#define EV_INT_GET_TASK_PRIORITY	13
-#define EV_DOORBELL_SEND		14
-#define EV_MSGSND			15
-#define EV_IDLE				16
-
-/* vendor ID: epapr */
-#define EV_LOCAL_VENDOR_ID		0	/* for private use */
-#define EV_EPAPR_VENDOR_ID		1
-#define EV_FSL_VENDOR_ID		2	/* Freescale Semiconductor */
-#define EV_IBM_VENDOR_ID		3	/* IBM */
-#define EV_GHS_VENDOR_ID		4	/* Green Hills Software */
-#define EV_ENEA_VENDOR_ID		5	/* Enea */
-#define EV_WR_VENDOR_ID			6	/* Wind River Systems */
-#define EV_AMCC_VENDOR_ID		7	/* Applied Micro Circuits */
-#define EV_KVM_VENDOR_ID		42	/* KVM */
-
-/* The max number of bytes that a byte channel can send or receive per call */
-#define EV_BYTE_CHANNEL_MAX_BYTES	16
-
-
-#define _EV_HCALL_TOKEN(id, num) (((id) << 16) | (num))
-#define EV_HCALL_TOKEN(hcall_num) _EV_HCALL_TOKEN(EV_EPAPR_VENDOR_ID, hcall_num)
-
-/* epapr error codes */
-#define EV_EPERM		1	/* Operation not permitted */
-#define EV_ENOENT		2	/*  Entry Not Found */
-#define EV_EIO			3	/* I/O error occured */
-#define EV_EAGAIN		4	/* The operation had insufficient
-					 * resources to complete and should be
-					 * retried
-					 */
-#define EV_ENOMEM		5	/* There was insufficient memory to
-					 * complete the operation */
-#define EV_EFAULT		6	/* Bad guest address */
-#define EV_ENODEV		7	/* No such device */
-#define EV_EINVAL		8	/* An argument supplied to the hcall
-					   was out of range or invalid */
-#define EV_INTERNAL		9	/* An internal error occured */
-#define EV_CONFIG		10	/* A configuration error was detected */
-#define EV_INVALID_STATE	11	/* The object is in an invalid state */
-#define EV_UNIMPLEMENTED	12	/* Unimplemented hypercall */
-#define EV_BUFFER_OVERFLOW	13	/* Caller-supplied buffer too small */
-
 /*
  * Hypercall register clobber list
  *
@@ -193,7 +142,7 @@ static inline unsigned int ev_int_set_config(unsigned int interrupt,
 	r5  = priority;
 	r6  = destination;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6)
 		: : EV_HCALL_CLOBBERS4
 	);
@@ -222,7 +171,7 @@ static inline unsigned int ev_int_get_config(unsigned int interrupt,
 	r11 = EV_HCALL_TOKEN(EV_INT_GET_CONFIG);
 	r3 = interrupt;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5), "=r" (r6)
 		: : EV_HCALL_CLOBBERS4
 	);
@@ -252,7 +201,7 @@ static inline unsigned int ev_int_set_mask(unsigned int interrupt,
 	r3 = interrupt;
 	r4 = mask;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "+r" (r4)
 		: : EV_HCALL_CLOBBERS2
 	);
@@ -277,7 +226,7 @@ static inline unsigned int ev_int_get_mask(unsigned int interrupt,
 	r11 = EV_HCALL_TOKEN(EV_INT_GET_MASK);
 	r3 = interrupt;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "=r" (r4)
 		: : EV_HCALL_CLOBBERS2
 	);
@@ -305,7 +254,7 @@ static inline unsigned int ev_int_eoi(unsigned int interrupt)
 	r11 = EV_HCALL_TOKEN(EV_INT_EOI);
 	r3 = interrupt;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -344,7 +293,7 @@ static inline unsigned int ev_byte_channel_send(unsigned int handle,
 	r7 = be32_to_cpu(p[2]);
 	r8 = be32_to_cpu(p[3]);
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3),
 		  "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7), "+r" (r8)
 		: : EV_HCALL_CLOBBERS6
@@ -383,7 +332,7 @@ static inline unsigned int ev_byte_channel_receive(unsigned int handle,
 	r3 = handle;
 	r4 = *count;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "+r" (r4),
 		  "=r" (r5), "=r" (r6), "=r" (r7), "=r" (r8)
 		: : EV_HCALL_CLOBBERS6
@@ -421,7 +370,7 @@ static inline unsigned int ev_byte_channel_poll(unsigned int handle,
 	r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_POLL);
 	r3 = handle;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5)
 		: : EV_HCALL_CLOBBERS3
 	);
@@ -454,7 +403,7 @@ static inline unsigned int ev_int_iack(unsigned int handle,
 	r11 = EV_HCALL_TOKEN(EV_INT_IACK);
 	r3 = handle;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "=r" (r4)
 		: : EV_HCALL_CLOBBERS2
 	);
@@ -478,7 +427,7 @@ static inline unsigned int ev_doorbell_send(unsigned int handle)
 	r11 = EV_HCALL_TOKEN(EV_DOORBELL_SEND);
 	r3 = handle;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -498,12 +447,12 @@ static inline unsigned int ev_idle(void)
 
 	r11 = EV_HCALL_TOKEN(EV_IDLE);
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "=r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
 
 	return r3;
 }
-
-#endif
+#endif /* !__ASSEMBLY__ */
+#endif /* _EPAPR_HCALLS_H */
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
index a43c147..ad708dd 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -48,6 +48,35 @@
 #define EX_LR		72
 #define EX_CFAR		80
 
+#ifdef CONFIG_RELOCATABLE
+#define EXCEPTION_RELON_PROLOG_PSERIES_1(label, h)			\
+	ld	r12,PACAKBASE(r13);	/* get high part of &label */	\
+	mfspr	r11,SPRN_##h##SRR0;	/* save SRR0 */			\
+	LOAD_HANDLER(r12,label);					\
+	mtlr	r12;							\
+	mfspr	r12,SPRN_##h##SRR1;	/* and SRR1 */			\
+	li	r10,MSR_RI;						\
+	mtmsrd 	r10,1;			/* Set RI (EE=0) */		\
+	blr;
+#else
+/* If not relocatable, we can jump directly -- and save messing with LR */
+#define EXCEPTION_RELON_PROLOG_PSERIES_1(label, h)			\
+	mfspr	r11,SPRN_##h##SRR0;	/* save SRR0 */			\
+	mfspr	r12,SPRN_##h##SRR1;	/* and SRR1 */			\
+	li	r10,MSR_RI;						\
+	mtmsrd 	r10,1;			/* Set RI (EE=0) */		\
+	b	label;
+#endif
+
+/*
+ * As EXCEPTION_PROLOG_PSERIES(), except we've already got relocation on
+ * so no need to rfid.  Save lr in case we're CONFIG_RELOCATABLE, in which
+ * case EXCEPTION_RELON_PROLOG_PSERIES_1 will be using lr.
+ */
+#define EXCEPTION_RELON_PROLOG_PSERIES(area, label, h, extra, vec)	\
+	EXCEPTION_PROLOG_1(area, extra, vec);				\
+	EXCEPTION_RELON_PROLOG_PSERIES_1(label, h)
+
 /*
  * We're short on space and time in the exception prolog, so we can't
  * use the normal SET_REG_IMMEDIATE macro. Normally we just need the
@@ -55,12 +84,29 @@
  * word.
  */
 #define LOAD_HANDLER(reg, label)					\
-	addi	reg,reg,(label)-_stext;	/* virt addr of handler ... */
+	/* Handlers must be within 64K of kbase, which must be 64k aligned */ \
+	ori	reg,reg,(label)-_stext;	/* virt addr of handler ... */
 
 /* Exception register prefixes */
 #define EXC_HV	H
 #define EXC_STD
 
+#if defined(CONFIG_RELOCATABLE)
+/*
+ * If we support interrupts with relocation on AND we're a relocatable
+ * kernel, we need to use LR to get to the 2nd level handler.  So, save/restore
+ * it when required.
+ */
+#define SAVE_LR(reg, area)	mflr	reg ; 	std	reg,area+EX_LR(r13)
+#define GET_LR(reg, area) 			ld	reg,area+EX_LR(r13)
+#define RESTORE_LR(reg, area)	ld	reg,area+EX_LR(r13) ; mtlr reg
+#else
+/* ...else LR is unused and in register. */
+#define SAVE_LR(reg, area)
+#define GET_LR(reg, area) 	mflr	reg
+#define RESTORE_LR(reg, area)
+#endif
+
 #define __EXCEPTION_PROLOG_1(area, extra, vec)				\
 	GET_PACA(r13);							\
 	std	r9,area+EX_R9(r13);	/* save r9 - r12 */		\
@@ -69,6 +115,7 @@
 	mfspr	r10,SPRN_CFAR;						\
 	std	r10,area+EX_CFAR(r13);					\
 	END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66);		\
+	SAVE_LR(r10, area);						\
 	mfcr	r9;							\
 	extra(vec);							\
 	std	r11,area+EX_R11(r13);					\
@@ -169,6 +216,7 @@ do_kvm_##n:								\
 	sth	r1,PACA_TRAP_SAVE(r13);					   \
 	std	r3,area+EX_R3(r13);					   \
 	addi	r3,r13,area;		/* r3 -> where regs are saved*/	   \
+	RESTORE_LR(r1, area);						   \
 	b	bad_stack;						   \
 3:	std	r9,_CCR(r1);		/* save CR in stackframe	*/ \
 	std	r11,_NIP(r1);		/* save SRR0 in stackframe	*/ \
@@ -194,8 +242,8 @@ do_kvm_##n:								\
 	ld	r10,area+EX_CFAR(r13);					   \
 	std	r10,ORIG_GPR3(r1);					   \
 	END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66);		   \
+	GET_LR(r9,area);		/* Get LR, later save to stack	*/ \
 	ld	r2,PACATOC(r13);	/* get kernel TOC into r2	*/ \
-	mflr	r9;			/* save LR in stackframe	*/ \
 	std	r9,_LINK(r1);						   \
 	mfctr	r10;			/* save CTR in stackframe	*/ \
 	std	r10,_CTR(r1);						   \
@@ -232,6 +280,26 @@ label##_hv:						\
 	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common,	\
 				 EXC_HV, KVMTEST, vec)
 
+#define STD_RELON_EXCEPTION_PSERIES(loc, vec, label)	\
+	. = loc;					\
+	.globl label##_relon_pSeries;			\
+label##_relon_pSeries:					\
+	HMT_MEDIUM;					\
+	/* No guest interrupts come through here */	\
+	SET_SCRATCH0(r13);		/* save r13 */	\
+	EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \
+				       EXC_STD, KVMTEST_PR, vec)
+
+#define STD_RELON_EXCEPTION_HV(loc, vec, label)		\
+	. = loc;					\
+	.globl label##_relon_hv;			\
+label##_relon_hv:					\
+	HMT_MEDIUM;					\
+	/* No guest interrupts come through here */	\
+	SET_SCRATCH0(r13);	/* save r13 */		\
+	EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \
+				       EXC_HV, KVMTEST, vec)
+
 /* This associate vector numbers with bits in paca->irq_happened */
 #define SOFTEN_VALUE_0x500	PACA_IRQ_EE
 #define SOFTEN_VALUE_0x502	PACA_IRQ_EE
@@ -257,6 +325,9 @@ label##_hv:						\
 	KVMTEST(vec);							\
 	_SOFTEN_TEST(EXC_STD, vec)
 
+#define SOFTEN_NOTEST_PR(vec)		_SOFTEN_TEST(EXC_STD, vec)
+#define SOFTEN_NOTEST_HV(vec)		_SOFTEN_TEST(EXC_HV, vec)
+
 #define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra)		\
 	HMT_MEDIUM;							\
 	SET_SCRATCH0(r13);    /* save r13 */				\
@@ -279,6 +350,28 @@ label##_hv:								\
 	_MASKABLE_EXCEPTION_PSERIES(vec, label,				\
 				    EXC_HV, SOFTEN_TEST_HV)
 
+#define __MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra)	\
+	HMT_MEDIUM;							\
+	SET_SCRATCH0(r13);    /* save r13 */				\
+	__EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec);		\
+	EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, h);
+#define _MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra)	\
+	__MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra)
+
+#define MASKABLE_RELON_EXCEPTION_PSERIES(loc, vec, label)		\
+	. = loc;							\
+	.globl label##_relon_pSeries;					\
+label##_relon_pSeries:							\
+	_MASKABLE_RELON_EXCEPTION_PSERIES(vec, label,			\
+					  EXC_STD, SOFTEN_NOTEST_PR)
+
+#define MASKABLE_RELON_EXCEPTION_HV(loc, vec, label)			\
+	. = loc;							\
+	.globl label##_relon_hv;					\
+label##_relon_hv:							\
+	_MASKABLE_RELON_EXCEPTION_PSERIES(vec, label,			\
+					  EXC_HV, SOFTEN_NOTEST_HV)
+
 /*
  * Our exception common code can be passed various "additions"
  * to specify the behaviour of interrupts, whether to kick the
diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h
index ad0b751..973cc3b 100644
--- a/arch/powerpc/include/asm/firmware.h
+++ b/arch/powerpc/include/asm/firmware.h
@@ -49,6 +49,7 @@
 #define FW_FEATURE_XCMO		ASM_CONST(0x0000000008000000)
 #define FW_FEATURE_OPAL		ASM_CONST(0x0000000010000000)
 #define FW_FEATURE_OPALv2	ASM_CONST(0x0000000020000000)
+#define FW_FEATURE_SET_MODE	ASM_CONST(0x0000000040000000)
 
 #ifndef __ASSEMBLY__
 
@@ -62,7 +63,8 @@ enum {
 		FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN |
 		FW_FEATURE_BULK_REMOVE | FW_FEATURE_XDABR |
 		FW_FEATURE_MULTITCE | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR |
-		FW_FEATURE_CMO | FW_FEATURE_VPHN | FW_FEATURE_XCMO,
+		FW_FEATURE_CMO | FW_FEATURE_VPHN | FW_FEATURE_XCMO |
+		FW_FEATURE_SET_MODE,
 	FW_FEATURE_PSERIES_ALWAYS = 0,
 	FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2,
 	FW_FEATURE_POWERNV_ALWAYS = 0,
diff --git a/arch/powerpc/include/asm/fsl_gtm.h b/arch/powerpc/include/asm/fsl_gtm.h
index 8e8c9b5..3b05808 100644
--- a/arch/powerpc/include/asm/fsl_gtm.h
+++ b/arch/powerpc/include/asm/fsl_gtm.h
@@ -1,7 +1,7 @@
 /*
  * Freescale General-purpose Timers Module
  *
- * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ * Copyright 2006 Freescale Semiconductor, Inc.
  *               Shlomi Gridish <gridish@freescale.com>
  *               Jerry Huang <Chang-Ming.Huang@freescale.com>
  * Copyright (c) MontaVista Software, Inc. 2008.
diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
index dd5ba2c..77ced0b 100644
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ b/arch/powerpc/include/asm/fsl_guts.h
@@ -71,7 +71,9 @@ struct ccsr_guts {
 	u8	res0c4[0x224 - 0xc4];
 	__be32  iodelay1;	/* 0x.0224 - IO delay control register 1 */
 	__be32  iodelay2;	/* 0x.0228 - IO delay control register 2 */
-	u8	res22c[0x800 - 0x22c];
+	u8	res22c[0x604 - 0x22c];
+	__be32	pamubypenr; 	/* 0x.604 - PAMU bypass enable register */
+	u8	res608[0x800 - 0x608];
 	__be32	clkdvdr;	/* 0x.0800 - Clock Divide Register */
 	u8	res804[0x900 - 0x804];
 	__be32	ircr;		/* 0x.0900 - Infrared Control Register */
diff --git a/arch/powerpc/include/asm/fsl_hcalls.h b/arch/powerpc/include/asm/fsl_hcalls.h
index 922d9b5..3abb583 100644
--- a/arch/powerpc/include/asm/fsl_hcalls.h
+++ b/arch/powerpc/include/asm/fsl_hcalls.h
@@ -96,7 +96,7 @@ static inline unsigned int fh_send_nmi(unsigned int vcpu_mask)
 	r11 = FH_HCALL_TOKEN(FH_SEND_NMI);
 	r3 = vcpu_mask;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -151,7 +151,7 @@ static inline unsigned int fh_partition_get_dtprop(int handle,
 	r9 = (uint32_t)propvalue_addr;
 	r10 = *propvalue_len;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11),
 		  "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7),
 		  "+r" (r8), "+r" (r9), "+r" (r10)
@@ -205,7 +205,7 @@ static inline unsigned int fh_partition_set_dtprop(int handle,
 	r9 = (uint32_t)propvalue_addr;
 	r10 = propvalue_len;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11),
 		  "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7),
 		  "+r" (r8), "+r" (r9), "+r" (r10)
@@ -229,7 +229,7 @@ static inline unsigned int fh_partition_restart(unsigned int partition)
 	r11 = FH_HCALL_TOKEN(FH_PARTITION_RESTART);
 	r3 = partition;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -262,7 +262,7 @@ static inline unsigned int fh_partition_get_status(unsigned int partition,
 	r11 = FH_HCALL_TOKEN(FH_PARTITION_GET_STATUS);
 	r3 = partition;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "=r" (r4)
 		: : EV_HCALL_CLOBBERS2
 	);
@@ -295,7 +295,7 @@ static inline unsigned int fh_partition_start(unsigned int partition,
 	r4 = entry_point;
 	r5 = load;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5)
 		: : EV_HCALL_CLOBBERS3
 	);
@@ -317,7 +317,7 @@ static inline unsigned int fh_partition_stop(unsigned int partition)
 	r11 = FH_HCALL_TOKEN(FH_PARTITION_STOP);
 	r3 = partition;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -376,7 +376,7 @@ static inline unsigned int fh_partition_memcpy(unsigned int source,
 #endif
 	r7 = count;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11),
 		  "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7)
 		: : EV_HCALL_CLOBBERS5
@@ -399,7 +399,7 @@ static inline unsigned int fh_dma_enable(unsigned int liodn)
 	r11 = FH_HCALL_TOKEN(FH_DMA_ENABLE);
 	r3 = liodn;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -421,7 +421,7 @@ static inline unsigned int fh_dma_disable(unsigned int liodn)
 	r11 = FH_HCALL_TOKEN(FH_DMA_DISABLE);
 	r3 = liodn;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -447,7 +447,7 @@ static inline unsigned int fh_vmpic_get_msir(unsigned int interrupt,
 	r11 = FH_HCALL_TOKEN(FH_VMPIC_GET_MSIR);
 	r3 = interrupt;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "=r" (r4)
 		: : EV_HCALL_CLOBBERS2
 	);
@@ -469,7 +469,7 @@ static inline unsigned int fh_system_reset(void)
 
 	r11 = FH_HCALL_TOKEN(FH_SYSTEM_RESET);
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "=r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -506,7 +506,7 @@ static inline unsigned int fh_err_get_info(int queue, uint32_t *bufsize,
 	r6 = addr_lo;
 	r7 = peek;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6),
 		  "+r" (r7)
 		: : EV_HCALL_CLOBBERS5
@@ -542,7 +542,7 @@ static inline unsigned int fh_get_core_state(unsigned int handle,
 	r3 = handle;
 	r4 = vcpu;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "+r" (r4)
 		: : EV_HCALL_CLOBBERS2
 	);
@@ -572,7 +572,7 @@ static inline unsigned int fh_enter_nap(unsigned int handle, unsigned int vcpu)
 	r3 = handle;
 	r4 = vcpu;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "+r" (r4)
 		: : EV_HCALL_CLOBBERS2
 	);
@@ -597,7 +597,7 @@ static inline unsigned int fh_exit_nap(unsigned int handle, unsigned int vcpu)
 	r3 = handle;
 	r4 = vcpu;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "+r" (r4)
 		: : EV_HCALL_CLOBBERS2
 	);
@@ -618,7 +618,7 @@ static inline unsigned int fh_claim_device(unsigned int handle)
 	r11 = FH_HCALL_TOKEN(FH_CLAIM_DEVICE);
 	r3 = handle;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -645,7 +645,7 @@ static inline unsigned int fh_partition_stop_dma(unsigned int handle)
 	r11 = FH_HCALL_TOKEN(FH_PARTITION_STOP_DMA);
 	r3 = handle;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 7a86706..0975e5c 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -267,7 +267,8 @@
 #define H_RANDOM		0x300
 #define H_COP			0x304
 #define H_GET_MPP_X		0x314
-#define MAX_HCALL_OPCODE	H_GET_MPP_X
+#define H_SET_MODE		0x31C
+#define MAX_HCALL_OPCODE	H_SET_MODE
 
 #ifndef __ASSEMBLY__
 
@@ -355,6 +356,26 @@ struct hvcall_mpp_x_data {
 
 int h_get_mpp_x(struct hvcall_mpp_x_data *mpp_x_data);
 
+static inline unsigned int get_longbusy_msecs(int longbusy_rc)
+{
+	switch (longbusy_rc) {
+	case H_LONG_BUSY_ORDER_1_MSEC:
+		return 1;
+	case H_LONG_BUSY_ORDER_10_MSEC:
+		return 10;
+	case H_LONG_BUSY_ORDER_100_MSEC:
+		return 100;
+	case H_LONG_BUSY_ORDER_1_SEC:
+		return 1000;
+	case H_LONG_BUSY_ORDER_10_SEC:
+		return 10000;
+	case H_LONG_BUSY_ORDER_100_SEC:
+		return 100000;
+	default:
+		return 1;
+	}
+}
+
 #ifdef CONFIG_PPC_PSERIES
 extern int CMO_PrPSP;
 extern int CMO_SecPSP;
diff --git a/arch/powerpc/include/asm/immap_qe.h b/arch/powerpc/include/asm/immap_qe.h
index 61e8490..bedbff8 100644
--- a/arch/powerpc/include/asm/immap_qe.h
+++ b/arch/powerpc/include/asm/immap_qe.h
@@ -3,7 +3,7 @@
  * The Internal Memory Map for devices with QE on them. This
  * is the superset of all QE devices (8360, etc.).
 
- * Copyright (C) 2006. Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2006. Freescale Semiconductor, Inc. All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h
index 76fdcfe..aabcdba 100644
--- a/arch/powerpc/include/asm/kvm_asm.h
+++ b/arch/powerpc/include/asm/kvm_asm.h
@@ -118,6 +118,7 @@
 
 #define RESUME_FLAG_NV          (1<<0)  /* Reload guest nonvolatile state? */
 #define RESUME_FLAG_HOST        (1<<1)  /* Resume host? */
+#define RESUME_FLAG_ARCH1	(1<<2)
 
 #define RESUME_GUEST            0
 #define RESUME_GUEST_NV         RESUME_FLAG_NV
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index 7aefdb3..5a56e1c 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -81,6 +81,8 @@ struct kvmppc_vcpu_book3s {
 	u64 sdr1;
 	u64 hior;
 	u64 msr_mask;
+	u64 purr_offset;
+	u64 spurr_offset;
 #ifdef CONFIG_PPC_BOOK3S_32
 	u32 vsid_pool[VSID_POOL_SIZE];
 	u32 vsid_next;
@@ -157,10 +159,14 @@ extern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr,
 extern void kvmppc_unpin_guest_page(struct kvm *kvm, void *addr);
 extern long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 			long pte_index, unsigned long pteh, unsigned long ptel);
-extern long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
-			long pte_index, unsigned long pteh, unsigned long ptel);
+extern long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
+			long pte_index, unsigned long pteh, unsigned long ptel,
+			pgd_t *pgdir, bool realmode, unsigned long *idx_ret);
+extern long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags,
+			unsigned long pte_index, unsigned long avpn,
+			unsigned long *hpret);
 extern long kvmppc_hv_get_dirty_log(struct kvm *kvm,
-			struct kvm_memory_slot *memslot);
+			struct kvm_memory_slot *memslot, unsigned long *map);
 
 extern void kvmppc_entry_trampoline(void);
 extern void kvmppc_hv_entry_trampoline(void);
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index 0dd1d86..38bec1d 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -50,6 +50,15 @@ extern int kvm_hpt_order;		/* order of preallocated HPTs */
 #define HPTE_V_HVLOCK	0x40UL
 #define HPTE_V_ABSENT	0x20UL
 
+/*
+ * We use this bit in the guest_rpte field of the revmap entry
+ * to indicate a modified HPTE.
+ */
+#define HPTE_GR_MODIFIED	(1ul << 62)
+
+/* These bits are reserved in the guest view of the HPTE */
+#define HPTE_GR_RESERVED	HPTE_GR_MODIFIED
+
 static inline long try_lock_hpte(unsigned long *hpte, unsigned long bits)
 {
 	unsigned long tmp, old;
@@ -60,7 +69,7 @@ static inline long try_lock_hpte(unsigned long *hpte, unsigned long bits)
 		     "	ori	%0,%0,%4\n"
 		     "  stdcx.	%0,0,%2\n"
 		     "	beq+	2f\n"
-		     "	li	%1,%3\n"
+		     "	mr	%1,%3\n"
 		     "2:	isync"
 		     : "=&r" (tmp), "=&r" (old)
 		     : "r" (hpte), "r" (bits), "i" (HPTE_V_HVLOCK)
@@ -237,4 +246,26 @@ static inline bool slot_is_aligned(struct kvm_memory_slot *memslot,
 	return !(memslot->base_gfn & mask) && !(memslot->npages & mask);
 }
 
+/*
+ * This works for 4k, 64k and 16M pages on POWER7,
+ * and 4k and 16M pages on PPC970.
+ */
+static inline unsigned long slb_pgsize_encoding(unsigned long psize)
+{
+	unsigned long senc = 0;
+
+	if (psize > 0x1000) {
+		senc = SLB_VSID_L;
+		if (psize == 0x10000)
+			senc |= SLB_VSID_LP_01;
+	}
+	return senc;
+}
+
+static inline int is_vrma_hpte(unsigned long hpte_v)
+{
+	return (hpte_v & ~0xffffffUL) ==
+		(HPTE_V_1TB_SEG | (VRMA_VSID << (40 - 16)));
+}
+
 #endif /* __ASM_KVM_BOOK3S_64_H__ */
diff --git a/arch/powerpc/include/asm/kvm_booke_hv_asm.h b/arch/powerpc/include/asm/kvm_booke_hv_asm.h
index 30a600f..a37a12a 100644
--- a/arch/powerpc/include/asm/kvm_booke_hv_asm.h
+++ b/arch/powerpc/include/asm/kvm_booke_hv_asm.h
@@ -38,9 +38,9 @@
 #ifdef CONFIG_KVM_BOOKE_HV
 BEGIN_FTR_SECTION
 	mtocrf	0x80, r11	/* check MSR[GS] without clobbering reg */
-	bf	3, kvmppc_resume_\intno\()_\srr1
+	bf	3, 1975f
 	b	kvmppc_handler_\intno\()_\srr1
-kvmppc_resume_\intno\()_\srr1:
+1975:
 END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
 #endif
 .endm
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 28e8f5e..62fbd38 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -46,7 +46,7 @@
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 #endif
 
-#ifdef CONFIG_KVM_BOOK3S_64_HV
+#if !defined(CONFIG_KVM_440)
 #include <linux/mmu_notifier.h>
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
@@ -204,7 +204,7 @@ struct revmap_entry {
 };
 
 /*
- * We use the top bit of each memslot->rmap entry as a lock bit,
+ * We use the top bit of each memslot->arch.rmap entry as a lock bit,
  * and bit 32 as a present flag.  The bottom 32 bits are the
  * index in the guest HPT of a HPTE that points to the page.
  */
@@ -215,14 +215,17 @@ struct revmap_entry {
 #define KVMPPC_RMAP_PRESENT	0x100000000ul
 #define KVMPPC_RMAP_INDEX	0xfffffffful
 
-/* Low-order bits in kvm->arch.slot_phys[][] */
+/* Low-order bits in memslot->arch.slot_phys[] */
 #define KVMPPC_PAGE_ORDER_MASK	0x1f
 #define KVMPPC_PAGE_NO_CACHE	HPTE_R_I	/* 0x20 */
 #define KVMPPC_PAGE_WRITETHRU	HPTE_R_W	/* 0x40 */
 #define KVMPPC_GOT_PAGE		0x80
 
 struct kvm_arch_memory_slot {
+#ifdef CONFIG_KVM_BOOK3S_64_HV
 	unsigned long *rmap;
+	unsigned long *slot_phys;
+#endif /* CONFIG_KVM_BOOK3S_64_HV */
 };
 
 struct kvm_arch {
@@ -243,12 +246,12 @@ struct kvm_arch {
 	int using_mmu_notifiers;
 	u32 hpt_order;
 	atomic_t vcpus_running;
+	u32 online_vcores;
 	unsigned long hpt_npte;
 	unsigned long hpt_mask;
+	atomic_t hpte_mod_interest;
 	spinlock_t slot_phys_lock;
-	unsigned long *slot_phys[KVM_MEM_SLOTS_NUM];
-	int slot_npages[KVM_MEM_SLOTS_NUM];
-	unsigned short last_vcpu[NR_CPUS];
+	cpumask_t need_tlb_flush;
 	struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
 	struct kvmppc_linear_info *hpt_li;
 #endif /* CONFIG_KVM_BOOK3S_64_HV */
@@ -273,6 +276,7 @@ struct kvmppc_vcore {
 	int nap_count;
 	int napping_threads;
 	u16 pcpu;
+	u16 last_cpu;
 	u8 vcore_state;
 	u8 in_guest;
 	struct list_head runnable_threads;
@@ -288,9 +292,10 @@ struct kvmppc_vcore {
 
 /* Values for vcore_state */
 #define VCORE_INACTIVE	0
-#define VCORE_RUNNING	1
-#define VCORE_EXITING	2
-#define VCORE_SLEEPING	3
+#define VCORE_SLEEPING	1
+#define VCORE_STARTING	2
+#define VCORE_RUNNING	3
+#define VCORE_EXITING	4
 
 /*
  * Struct used to manage memory for a virtual processor area
@@ -346,6 +351,27 @@ struct kvmppc_slb {
 	bool class	: 1;
 };
 
+# ifdef CONFIG_PPC_FSL_BOOK3E
+#define KVMPPC_BOOKE_IAC_NUM	2
+#define KVMPPC_BOOKE_DAC_NUM	2
+# else
+#define KVMPPC_BOOKE_IAC_NUM	4
+#define KVMPPC_BOOKE_DAC_NUM	2
+# endif
+#define KVMPPC_BOOKE_MAX_IAC	4
+#define KVMPPC_BOOKE_MAX_DAC	2
+
+struct kvmppc_booke_debug_reg {
+	u32 dbcr0;
+	u32 dbcr1;
+	u32 dbcr2;
+#ifdef CONFIG_KVM_E500MC
+	u32 dbcr4;
+#endif
+	u64 iac[KVMPPC_BOOKE_MAX_IAC];
+	u64 dac[KVMPPC_BOOKE_MAX_DAC];
+};
+
 struct kvm_vcpu_arch {
 	ulong host_stack;
 	u32 host_pid;
@@ -440,8 +466,6 @@ struct kvm_vcpu_arch {
 
 	u32 ccr0;
 	u32 ccr1;
-	u32 dbcr0;
-	u32 dbcr1;
 	u32 dbsr;
 
 	u64 mmcr[3];
@@ -471,9 +495,12 @@ struct kvm_vcpu_arch {
 	ulong fault_esr;
 	ulong queued_dear;
 	ulong queued_esr;
+	spinlock_t wdt_lock;
+	struct timer_list wdt_timer;
 	u32 tlbcfg[4];
 	u32 mmucfg;
 	u32 epr;
+	struct kvmppc_booke_debug_reg dbg_reg;
 #endif
 	gpa_t paddr_accessed;
 	gva_t vaddr_accessed;
@@ -486,6 +513,7 @@ struct kvm_vcpu_arch {
 	u8 osi_needed;
 	u8 osi_enabled;
 	u8 papr_enabled;
+	u8 watchdog_enabled;
 	u8 sane;
 	u8 cpu_type;
 	u8 hcall_needed;
@@ -497,7 +525,6 @@ struct kvm_vcpu_arch {
 	u64 dec_jiffies;
 	u64 dec_expires;
 	unsigned long pending_exceptions;
-	u16 last_cpu;
 	u8 ceded;
 	u8 prodded;
 	u32 last_inst;
@@ -534,13 +561,17 @@ struct kvm_vcpu_arch {
 	unsigned long dtl_index;
 	u64 stolen_logged;
 	struct kvmppc_vpa slb_shadow;
+
+	spinlock_t tbacct_lock;
+	u64 busy_stolen;
+	u64 busy_preempt;
 #endif
 };
 
 /* Values for vcpu->arch.state */
-#define KVMPPC_VCPU_STOPPED		0
-#define KVMPPC_VCPU_BUSY_IN_HOST	1
-#define KVMPPC_VCPU_RUNNABLE		2
+#define KVMPPC_VCPU_NOTREADY		0
+#define KVMPPC_VCPU_RUNNABLE		1
+#define KVMPPC_VCPU_BUSY_IN_HOST	2
 
 /* Values for vcpu->arch.io_gpr */
 #define KVM_MMIO_REG_MASK	0x001f
diff --git a/arch/powerpc/include/asm/kvm_para.h b/arch/powerpc/include/asm/kvm_para.h
index 9365860..2b11965 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -21,7 +21,6 @@
 
 #include <uapi/asm/kvm_para.h>
 
-
 #ifdef CONFIG_KVM_GUEST
 
 #include <linux/of.h>
@@ -55,7 +54,7 @@ static unsigned long kvm_hypercall(unsigned long *in,
 				   unsigned long *out,
 				   unsigned long nr)
 {
-	return HC_EV_UNIMPLEMENTED;
+	return EV_UNIMPLEMENTED;
 }
 
 #endif
@@ -66,7 +65,7 @@ static inline long kvm_hypercall0_1(unsigned int nr, unsigned long *r2)
 	unsigned long out[8];
 	unsigned long r;
 
-	r = kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+	r = kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 	*r2 = out[0];
 
 	return r;
@@ -77,7 +76,7 @@ static inline long kvm_hypercall0(unsigned int nr)
 	unsigned long in[8];
 	unsigned long out[8];
 
-	return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+	return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 static inline long kvm_hypercall1(unsigned int nr, unsigned long p1)
@@ -86,7 +85,7 @@ static inline long kvm_hypercall1(unsigned int nr, unsigned long p1)
 	unsigned long out[8];
 
 	in[0] = p1;
-	return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+	return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 static inline long kvm_hypercall2(unsigned int nr, unsigned long p1,
@@ -97,7 +96,7 @@ static inline long kvm_hypercall2(unsigned int nr, unsigned long p1,
 
 	in[0] = p1;
 	in[1] = p2;
-	return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+	return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 static inline long kvm_hypercall3(unsigned int nr, unsigned long p1,
@@ -109,7 +108,7 @@ static inline long kvm_hypercall3(unsigned int nr, unsigned long p1,
 	in[0] = p1;
 	in[1] = p2;
 	in[2] = p3;
-	return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+	return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,
@@ -123,7 +122,7 @@ static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,
 	in[1] = p2;
 	in[2] = p3;
 	in[3] = p4;
-	return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+	return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index e006f0b..1ca31e9 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -28,6 +28,7 @@
 #include <linux/types.h>
 #include <linux/kvm_types.h>
 #include <linux/kvm_host.h>
+#include <linux/bug.h>
 #ifdef CONFIG_PPC_BOOK3S
 #include <asm/kvm_book3s.h>
 #else
@@ -68,6 +69,8 @@ extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu);
 extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb);
 extern void kvmppc_decrementer_func(unsigned long data);
 extern int kvmppc_sanity_check(struct kvm_vcpu *vcpu);
+extern int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu);
+extern void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu);
 
 /* Core-specific hooks */
 
@@ -104,6 +107,7 @@ extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
                                        struct kvm_interrupt *irq);
 extern void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu,
                                          struct kvm_interrupt *irq);
+extern void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu);
 
 extern int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                                   unsigned int op, int *advance);
@@ -111,6 +115,7 @@ extern int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn,
 				     ulong val);
 extern int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn,
 				     ulong *val);
+extern int kvmppc_core_check_requests(struct kvm_vcpu *vcpu);
 
 extern int kvmppc_booke_init(void);
 extern void kvmppc_booke_exit(void);
@@ -139,16 +144,28 @@ extern struct kvmppc_linear_info *kvm_alloc_hpt(void);
 extern void kvm_release_hpt(struct kvmppc_linear_info *li);
 extern int kvmppc_core_init_vm(struct kvm *kvm);
 extern void kvmppc_core_destroy_vm(struct kvm *kvm);
+extern void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
+				     struct kvm_memory_slot *dont);
+extern int kvmppc_core_create_memslot(struct kvm_memory_slot *slot,
+				      unsigned long npages);
 extern int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+				struct kvm_memory_slot *memslot,
 				struct kvm_userspace_memory_region *mem);
 extern void kvmppc_core_commit_memory_region(struct kvm *kvm,
-				struct kvm_userspace_memory_region *mem);
+				struct kvm_userspace_memory_region *mem,
+				struct kvm_memory_slot old);
 extern int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm,
 				      struct kvm_ppc_smmu_info *info);
+extern void kvmppc_core_flush_memslot(struct kvm *kvm,
+				      struct kvm_memory_slot *memslot);
 
 extern int kvmppc_bookehv_init(void);
 extern void kvmppc_bookehv_exit(void);
 
+extern int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu);
+
+extern int kvm_vm_ioctl_get_htab_fd(struct kvm *kvm, struct kvm_get_htab_fd *);
+
 /*
  * Cuts out inst bits with ordering according to spec.
  * That means the leftmost bit is zero. All given bits are included.
@@ -182,6 +199,41 @@ static inline u32 kvmppc_set_field(u64 inst, int msb, int lsb, int value)
 	return r;
 }
 
+union kvmppc_one_reg {
+	u32	wval;
+	u64	dval;
+	vector128 vval;
+	u64	vsxval[2];
+	struct {
+		u64	addr;
+		u64	length;
+	}	vpaval;
+};
+
+#define one_reg_size(id)	\
+	(1ul << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
+
+#define get_reg_val(id, reg)	({		\
+	union kvmppc_one_reg __u;		\
+	switch (one_reg_size(id)) {		\
+	case 4: __u.wval = (reg); break;	\
+	case 8: __u.dval = (reg); break;	\
+	default: BUG();				\
+	}					\
+	__u;					\
+})
+
+
+#define set_reg_val(id, val)	({		\
+	u64 __v;				\
+	switch (one_reg_size(id)) {		\
+	case 4: __v = (val).wval; break;	\
+	case 8: __v = (val).dval; break;	\
+	default: BUG();				\
+	}					\
+	__v;					\
+})
+
 void kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 
@@ -190,6 +242,8 @@ int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 
 int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
 int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
+int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *);
+int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *);
 
 void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid);
 
@@ -230,5 +284,15 @@ static inline void kvmppc_mmu_flush_icache(pfn_t pfn)
 	}
 }
 
+/* Please call after prepare_to_enter. This function puts the lazy ee state
+   back to normal mode, without actually enabling interrupts. */
+static inline void kvmppc_lazy_ee_enable(void)
+{
+#ifdef CONFIG_PPC64
+	/* Only need to enable IRQs by hard enabling them after this */
+	local_paca->irq_happened = 0;
+	local_paca->soft_enabled = 1;
+#endif
+}
 
 #endif /* __POWERPC_KVM_PPC_H__ */
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index c423197..19d9d96 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -166,9 +166,6 @@ struct machdep_calls {
 						unsigned long size,
 						pgprot_t vma_prot);
 
-	/* Idle loop for this platform, leave empty for default idle loop */
-	void		(*idle_loop)(void);
-
 	/*
 	 * Function for waiting for work with reduced power in idle loop;
 	 * called with interrupts disabled.
@@ -320,28 +317,28 @@ static inline void log_error(char *buf, unsigned int err_type, int fatal)
 		ppc_md.log_error(buf, err_type, fatal);
 }
 
-#define __define_machine_initcall(mach,level,fn,id) \
+#define __define_machine_initcall(mach, fn, id) \
 	static int __init __machine_initcall_##mach##_##fn(void) { \
 		if (machine_is(mach)) return fn(); \
 		return 0; \
 	} \
-	__define_initcall(level,__machine_initcall_##mach##_##fn,id);
-
-#define machine_core_initcall(mach,fn)		__define_machine_initcall(mach,"1",fn,1)
-#define machine_core_initcall_sync(mach,fn)	__define_machine_initcall(mach,"1s",fn,1s)
-#define machine_postcore_initcall(mach,fn)	__define_machine_initcall(mach,"2",fn,2)
-#define machine_postcore_initcall_sync(mach,fn)	__define_machine_initcall(mach,"2s",fn,2s)
-#define machine_arch_initcall(mach,fn)		__define_machine_initcall(mach,"3",fn,3)
-#define machine_arch_initcall_sync(mach,fn)	__define_machine_initcall(mach,"3s",fn,3s)
-#define machine_subsys_initcall(mach,fn)	__define_machine_initcall(mach,"4",fn,4)
-#define machine_subsys_initcall_sync(mach,fn)	__define_machine_initcall(mach,"4s",fn,4s)
-#define machine_fs_initcall(mach,fn)		__define_machine_initcall(mach,"5",fn,5)
-#define machine_fs_initcall_sync(mach,fn)	__define_machine_initcall(mach,"5s",fn,5s)
-#define machine_rootfs_initcall(mach,fn)	__define_machine_initcall(mach,"rootfs",fn,rootfs)
-#define machine_device_initcall(mach,fn)	__define_machine_initcall(mach,"6",fn,6)
-#define machine_device_initcall_sync(mach,fn)	__define_machine_initcall(mach,"6s",fn,6s)
-#define machine_late_initcall(mach,fn)		__define_machine_initcall(mach,"7",fn,7)
-#define machine_late_initcall_sync(mach,fn)	__define_machine_initcall(mach,"7s",fn,7s)
+	__define_initcall(__machine_initcall_##mach##_##fn, id);
+
+#define machine_core_initcall(mach, fn)		__define_machine_initcall(mach, fn, 1)
+#define machine_core_initcall_sync(mach, fn)	__define_machine_initcall(mach, fn, 1s)
+#define machine_postcore_initcall(mach, fn)	__define_machine_initcall(mach, fn, 2)
+#define machine_postcore_initcall_sync(mach, fn)	__define_machine_initcall(mach, fn, 2s)
+#define machine_arch_initcall(mach, fn)		__define_machine_initcall(mach, fn, 3)
+#define machine_arch_initcall_sync(mach, fn)	__define_machine_initcall(mach, fn, 3s)
+#define machine_subsys_initcall(mach, fn)	__define_machine_initcall(mach, fn, 4)
+#define machine_subsys_initcall_sync(mach, fn)	__define_machine_initcall(mach, fn, 4s)
+#define machine_fs_initcall(mach, fn)		__define_machine_initcall(mach, fn, 5)
+#define machine_fs_initcall_sync(mach, fn)	__define_machine_initcall(mach, fn, 5s)
+#define machine_rootfs_initcall(mach, fn)	__define_machine_initcall(mach, fn, rootfs)
+#define machine_device_initcall(mach, fn)	__define_machine_initcall(mach, fn, 6)
+#define machine_device_initcall_sync(mach, fn)	__define_machine_initcall(mach, fn, 6s)
+#define machine_late_initcall(mach, fn)		__define_machine_initcall(mach, fn, 7)
+#define machine_late_initcall_sync(mach, fn)	__define_machine_initcall(mach, fn, 7s)
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_MACHDEP_H */
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index 9673f73..2fdb47a 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -121,6 +121,16 @@ extern char initial_stab[];
 #define PP_RXRX 3	/* Supervisor read,       User read */
 #define PP_RXXX	(HPTE_R_PP0 | 2)	/* Supervisor read, user none */
 
+/* Fields for tlbiel instruction in architecture 2.06 */
+#define TLBIEL_INVAL_SEL_MASK	0xc00	/* invalidation selector */
+#define  TLBIEL_INVAL_PAGE	0x000	/* invalidate a single page */
+#define  TLBIEL_INVAL_SET_LPID	0x800	/* invalidate a set for current LPID */
+#define  TLBIEL_INVAL_SET	0xc00	/* invalidate a set for all LPIDs */
+#define TLBIEL_INVAL_SET_MASK	0xfff000	/* set number to inval. */
+#define TLBIEL_INVAL_SET_SHIFT	12
+
+#define POWER7_TLB_SETS		128	/* # sets in POWER7 TLB */
+
 #ifndef __ASSEMBLY__
 
 struct hash_pte {
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index 5e38eed..691fd8a 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -101,6 +101,7 @@
 #define MMU_FTRS_POWER5		MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE
 #define MMU_FTRS_POWER6		MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE
 #define MMU_FTRS_POWER7		MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE
+#define MMU_FTRS_POWER8		MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE
 #define MMU_FTRS_CELL		MMU_FTRS_DEFAULT_HPTE_ARCH_V2 | \
 				MMU_FTR_CI_LARGE_PAGE
 #define MMU_FTRS_PA6T		MMU_FTRS_DEFAULT_HPTE_ARCH_V2 | \
diff --git a/arch/powerpc/include/asm/oprofile_impl.h b/arch/powerpc/include/asm/oprofile_impl.h
index 639dc96..d697b08 100644
--- a/arch/powerpc/include/asm/oprofile_impl.h
+++ b/arch/powerpc/include/asm/oprofile_impl.h
@@ -34,7 +34,7 @@ struct op_system_config {
 	unsigned long mmcra;
 #ifdef CONFIG_OPROFILE_CELL
 	/* Register for oprofile user tool to check cell kernel profiling
-	 * suport.
+	 * support.
 	 */
 	unsigned long cell_support;
 #endif
diff --git a/arch/powerpc/include/asm/pSeries_reconfig.h b/arch/powerpc/include/asm/pSeries_reconfig.h
deleted file mode 100644
index c07edfe..0000000
--- a/arch/powerpc/include/asm/pSeries_reconfig.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef _PPC64_PSERIES_RECONFIG_H
-#define _PPC64_PSERIES_RECONFIG_H
-#ifdef __KERNEL__
-
-#include <linux/notifier.h>
-
-/*
- * Use this API if your code needs to know about OF device nodes being
- * added or removed on pSeries systems.
- */
-
-#define PSERIES_RECONFIG_ADD		0x0001
-#define PSERIES_RECONFIG_REMOVE		0x0002
-#define PSERIES_DRCONF_MEM_ADD		0x0003
-#define PSERIES_DRCONF_MEM_REMOVE	0x0004
-#define PSERIES_UPDATE_PROPERTY		0x0005
-
-/**
- * pSeries_reconfig_notify - Notifier value structure for OFDT property updates
- *
- * @node: Device tree node which owns the property being updated
- * @property: Updated property
- */
-struct pSeries_reconfig_prop_update {
-	struct device_node *node;
-	struct property *property;
-};
-
-#ifdef CONFIG_PPC_PSERIES
-extern int pSeries_reconfig_notifier_register(struct notifier_block *);
-extern void pSeries_reconfig_notifier_unregister(struct notifier_block *);
-extern int pSeries_reconfig_notify(unsigned long action, void *p);
-/* Not the best place to put this, will be fixed when we move some
- * of the rtas suspend-me stuff to pseries */
-extern void pSeries_coalesce_init(void);
-#else /* !CONFIG_PPC_PSERIES */
-static inline int pSeries_reconfig_notifier_register(struct notifier_block *nb)
-{
-	return 0;
-}
-static inline void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) { }
-static inline void pSeries_coalesce_init(void) { }
-#endif /* CONFIG_PPC_PSERIES */
-
-
-#endif /* __KERNEL__ */
-#endif /* _PPC64_PSERIES_RECONFIG_H */
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index 5f73ce6..51fb00a 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2009 Freescale Semicondutor, Inc.
+ * 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
@@ -86,6 +86,7 @@
 #define PPC_INST_DCBA_MASK		0xfc0007fe
 #define PPC_INST_DCBAL			0x7c2005ec
 #define PPC_INST_DCBZL			0x7c2007ec
+#define PPC_INST_ICBT			0x7c00002c
 #define PPC_INST_ISEL			0x7c00001e
 #define PPC_INST_ISEL_MASK		0xfc00003e
 #define PPC_INST_LDARX			0x7c0000a8
@@ -168,9 +169,12 @@
 #define PPC_INST_AND			0x7c000038
 #define PPC_INST_ANDDOT			0x7c000039
 #define PPC_INST_OR			0x7c000378
+#define PPC_INST_XOR			0x7c000278
 #define PPC_INST_ANDI			0x70000000
 #define PPC_INST_ORI			0x60000000
 #define PPC_INST_ORIS			0x64000000
+#define PPC_INST_XORI			0x68000000
+#define PPC_INST_XORIS			0x6c000000
 #define PPC_INST_NEG			0x7c0000d0
 #define PPC_INST_BRANCH			0x48000000
 #define PPC_INST_BRANCH_COND		0x40800000
@@ -198,6 +202,7 @@
 #define __PPC_MB(s)	(((s) & 0x1f) << 6)
 #define __PPC_ME(s)	(((s) & 0x1f) << 1)
 #define __PPC_BI(s)	(((s) & 0x1f) << 16)
+#define __PPC_CT(t)	(((t) & 0x0f) << 21)
 
 /*
  * Only use the larx hint bit on 64bit CPUs. e500v1/v2 based CPUs will treat a
@@ -260,6 +265,8 @@
 					__PPC_RS(t) | __PPC_RA0(a) | __PPC_RB(b))
 #define PPC_SLBFEE_DOT(t, b)	stringify_in_c(.long PPC_INST_SLBFEE | \
 					__PPC_RT(t) | __PPC_RB(b))
+#define PPC_ICBT(c,a,b)		stringify_in_c(.long PPC_INST_ICBT | \
+				       __PPC_CT(c) | __PPC_RA0(a) | __PPC_RB(b))
 /* PASemi instructions */
 #define LBZCIX(t,a,b)		stringify_in_c(.long PPC_INST_LBZCIX | \
 				       __PPC_RT(t) | __PPC_RA(a) | __PPC_RB(b))
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index b5c9190..99c92d5 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -58,6 +58,22 @@ static inline int of_node_to_nid(struct device_node *device) { return 0; }
 
 extern void of_instantiate_rtc(void);
 
+/* The of_drconf_cell struct defines the layout of the LMB array
+ * specified in the device tree property
+ * ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory
+ */
+struct of_drconf_cell {
+	u64	base_addr;
+	u32	drc_index;
+	u32	reserved;
+	u32	aa_index;
+	u32	flags;
+};
+
+#define DRCONF_MEM_ASSIGNED	0x00000008
+#define DRCONF_MEM_AI_INVALID	0x00000040
+#define DRCONF_MEM_RESERVED	0x00000080
+
 /* 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
diff --git a/arch/powerpc/include/asm/pte-hash64-64k.h b/arch/powerpc/include/asm/pte-hash64-64k.h
index eedf427..3e13e23 100644
--- a/arch/powerpc/include/asm/pte-hash64-64k.h
+++ b/arch/powerpc/include/asm/pte-hash64-64k.h
@@ -23,7 +23,7 @@
 
 /* Note the full page bits must be in the same location as for normal
  * 4k pages as the same assembly will be used to insert 64K pages
- * wether the kernel has CONFIG_PPC_64K_PAGES or not
+ * whether the kernel has CONFIG_PPC_64K_PAGES or not
  */
 #define _PAGE_F_SECOND  0x00008000 /* full page: hidx bits */
 #define _PAGE_F_GIX     0x00007000 /* full page: hidx bits */
diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h
index 229571a..32b9bfa 100644
--- a/arch/powerpc/include/asm/qe.h
+++ b/arch/powerpc/include/asm/qe.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
diff --git a/arch/powerpc/include/asm/qe_ic.h b/arch/powerpc/include/asm/qe_ic.h
index f706164..25784cc 100644
--- a/arch/powerpc/include/asm/qe_ic.h
+++ b/arch/powerpc/include/asm/qe_ic.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index d24c141..3d5c9dc 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -249,6 +249,8 @@
 #define   LPCR_RMLS    0x1C000000      /* impl dependent rmo limit sel */
 #define	  LPCR_RMLS_SH	(63-37)
 #define   LPCR_ILE     0x02000000      /* !HV irqs set MSR:LE */
+#define   LPCR_AIL_0	0x00000000	/* MMU off exception offset 0x0 */
+#define   LPCR_AIL_3	0x01800000	/* MMU on exception offset 0xc00...4xxx */
 #define   LPCR_PECE	0x00007000	/* powersave exit cause enable */
 #define     LPCR_PECE0	0x00004000	/* ext. exceptions can cause exit */
 #define     LPCR_PECE1	0x00002000	/* decrementer can cause exit */
@@ -518,6 +520,7 @@
 #define	  SRR1_WS_DEEPER	0x00020000 /* Some resources not maintained */
 #define	  SRR1_WS_DEEP		0x00010000 /* All resources maintained */
 #define   SRR1_PROGFPE		0x00100000 /* Floating Point Enabled */
+#define   SRR1_PROGILL		0x00080000 /* Illegal instruction */
 #define   SRR1_PROGPRIV		0x00040000 /* Privileged instruction */
 #define   SRR1_PROGTRAP		0x00020000 /* Trap */
 #define   SRR1_PROGADDR		0x00010000 /* SRR0 contains subsequent addr */
@@ -1029,6 +1032,7 @@
 #define PVR_970MP	0x0044
 #define PVR_970GX	0x0045
 #define PVR_POWER7p	0x004A
+#define PVR_POWER8	0x004B
 #define PVR_BE		0x0070
 #define PVR_PA6T	0x0090
 
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index 2d916c4..e07e6af 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -539,6 +539,13 @@
 #define TCR_FIE		0x00800000	/* FIT Interrupt Enable */
 #define TCR_ARE		0x00400000	/* Auto Reload Enable */
 
+#ifdef CONFIG_E500
+#define TCR_GET_WP(tcr)  ((((tcr) & 0xC0000000) >> 30) | \
+			      (((tcr) & 0x1E0000) >> 15))
+#else
+#define TCR_GET_WP(tcr)  (((tcr) & 0xC0000000) >> 30)
+#endif
+
 /* Bit definitions for the TSR. */
 #define TSR_ENW		0x80000000	/* Enable Next Watchdog */
 #define TSR_WIS		0x40000000	/* WDT Interrupt Status */
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index 557cff84..aef00c6 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -353,8 +353,13 @@ static inline int page_is_rtas_user_buf(unsigned long pfn)
 		return 1;
 	return 0;
 }
+
+/* Not the best place to put pSeries_coalesce_init, will be fixed when we
+ * move some of the rtas suspend-me stuff to pseries */
+extern void pSeries_coalesce_init(void);
 #else
 static inline int page_is_rtas_user_buf(unsigned long pfn) { return 0;}
+static inline void pSeries_coalesce_init(void) { }
 #endif
 
 extern int call_rtas(const char *, int, int, unsigned long *, ...);
diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h
new file mode 100644
index 0000000..d3ca855
--- /dev/null
+++ b/arch/powerpc/include/asm/setup.h
@@ -0,0 +1,29 @@
+#ifndef _ASM_POWERPC_SETUP_H
+#define _ASM_POWERPC_SETUP_H
+
+#include <uapi/asm/setup.h>
+
+#ifndef __ASSEMBLY__
+extern void ppc_printk_progress(char *s, unsigned short hex);
+
+extern unsigned int rtas_data;
+extern int mem_init_done;	/* set on boot once kmalloc can be called */
+extern int init_bootmem_done;	/* set once bootmem is available */
+extern unsigned long long memory_limit;
+extern unsigned long klimit;
+extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
+
+struct device_node;
+extern void note_scsi_host(struct device_node *, void *);
+
+/* Used in very early kernel initialization. */
+extern unsigned long reloc_offset(void);
+extern unsigned long add_reloc_offset(unsigned long);
+extern void reloc_got2(unsigned long);
+
+#define PTRRELOC(x)	((typeof(x)) add_reloc_offset((unsigned long)(x)))
+
+#endif /* !__ASSEMBLY__ */
+
+#endif	/* _ASM_POWERPC_SETUP_H */
+
diff --git a/arch/powerpc/include/asm/signal.h b/arch/powerpc/include/asm/signal.h
index 189998b..a101637 100644
--- a/arch/powerpc/include/asm/signal.h
+++ b/arch/powerpc/include/asm/signal.h
@@ -3,6 +3,4 @@
 
 #include <uapi/asm/signal.h>
 
-struct pt_regs;
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
 #endif /* _ASM_POWERPC_SIGNAL_H */
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index e807e9d..5a4e437 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -67,6 +67,14 @@ void generic_mach_cpu_die(void);
 void generic_set_cpu_dead(unsigned int cpu);
 void generic_set_cpu_up(unsigned int cpu);
 int generic_check_cpu_restart(unsigned int cpu);
+
+extern void inhibit_secondary_onlining(void);
+extern void uninhibit_secondary_onlining(void);
+
+#else /* HOTPLUG_CPU */
+static inline void inhibit_secondary_onlining(void) {}
+static inline void uninhibit_secondary_onlining(void) {}
+
 #endif
 
 #ifdef CONFIG_PPC64
diff --git a/arch/powerpc/include/asm/smu.h b/arch/powerpc/include/asm/smu.h
index ae20ce1..6e909f3 100644
--- a/arch/powerpc/include/asm/smu.h
+++ b/arch/powerpc/include/asm/smu.h
@@ -132,7 +132,7 @@
   *
   * At this point, the OF driver seems to have a limitation on transfer
   * sizes of 0xd bytes on reads and 0x5 bytes on writes. I do not know
-  * wether this is just an OF limit due to some temporary buffer size
+  * whether this is just an OF limit due to some temporary buffer size
   * or if this is an SMU imposed limit. This driver has the same limitation
   * for now as I use a 0x10 bytes temporary buffer as well
   *
@@ -236,7 +236,7 @@
  *   3 (optional): enable nmi? [0x00 or 0x01]
  *
  * Returns:
- *   If parameter 2 is 0x00 and parameter 3 is not specified, returns wether
+ *   If parameter 2 is 0x00 and parameter 3 is not specified, returns whether
  *   NMI is enabled. Otherwise unknown.
  */
 #define   SMU_CMD_MISC_df_NMI_OPTION		0x04
diff --git a/arch/powerpc/include/asm/syscalls.h b/arch/powerpc/include/asm/syscalls.h
index 329db4e..b5308d3 100644
--- a/arch/powerpc/include/asm/syscalls.h
+++ b/arch/powerpc/include/asm/syscalls.h
@@ -17,15 +17,6 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
 asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len,
 		unsigned long prot, unsigned long flags,
 		unsigned long fd, unsigned long pgoff);
-asmlinkage int sys_clone(unsigned long clone_flags, unsigned long usp,
-		int __user *parent_tidp, void __user *child_threadptr,
-		int __user *child_tidp, int p6, struct pt_regs *regs);
-asmlinkage int sys_fork(unsigned long p1, unsigned long p2,
-		unsigned long p3, unsigned long p4, unsigned long p5,
-		unsigned long p6, struct pt_regs *regs);
-asmlinkage int sys_vfork(unsigned long p1, unsigned long p2,
-		unsigned long p3, unsigned long p4, unsigned long p5,
-		unsigned long p6, struct pt_regs *regs);
 asmlinkage long sys_pipe(int __user *fildes);
 asmlinkage long sys_pipe2(int __user *fildes, int flags);
 asmlinkage long sys_rt_sigaction(int sig,
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h
index 8408387..97909d3b 100644
--- a/arch/powerpc/include/asm/systbl.h
+++ b/arch/powerpc/include/asm/systbl.h
@@ -164,7 +164,7 @@ COMPAT_SYS_SPU(sched_getscheduler)
 SYSCALL_SPU(sched_yield)
 COMPAT_SYS_SPU(sched_get_priority_max)
 COMPAT_SYS_SPU(sched_get_priority_min)
-COMPAT_SYS_SPU(sched_rr_get_interval)
+SYSX_SPU(sys_sched_rr_get_interval,compat_sys_sched_rr_get_interval_wrapper,sys_sched_rr_get_interval)
 COMPAT_SYS_SPU(nanosleep)
 SYSCALL_SPU(mremap)
 SYSCALL_SPU(setresuid)
@@ -356,3 +356,4 @@ COMPAT_SYS_SPU(sendmmsg)
 SYSCALL_SPU(setns)
 COMPAT_SYS(process_vm_readv)
 COMPAT_SYS(process_vm_writev)
+SYSCALL(finit_module)
diff --git a/arch/powerpc/include/asm/ucc.h b/arch/powerpc/include/asm/ucc.h
index 46b09ba..6927ac2 100644
--- a/arch/powerpc/include/asm/ucc.h
+++ b/arch/powerpc/include/asm/ucc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
diff --git a/arch/powerpc/include/asm/ucc_fast.h b/arch/powerpc/include/asm/ucc_fast.h
index 4644c84..72ea9ba 100644
--- a/arch/powerpc/include/asm/ucc_fast.h
+++ b/arch/powerpc/include/asm/ucc_fast.h
@@ -1,7 +1,7 @@
 /*
  * Internal header file for UCC FAST unit routines.
  *
- * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
diff --git a/arch/powerpc/include/asm/ucc_slow.h b/arch/powerpc/include/asm/ucc_slow.h
index cf131ff..c44131e 100644
--- a/arch/powerpc/include/asm/ucc_slow.h
+++ b/arch/powerpc/include/asm/ucc_slow.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h
index b303881..5a7510e 100644
--- a/arch/powerpc/include/asm/udbg.h
+++ b/arch/powerpc/include/asm/udbg.h
@@ -21,7 +21,6 @@ extern int (*udbg_getc_poll)(void);
 
 extern void udbg_puts(const char *s);
 extern int udbg_write(const char *s, int n);
-extern int udbg_read(char *buf, int buflen);
 
 extern void register_early_udbg_console(void);
 extern void udbg_printf(const char *fmt, ...)
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h
index 921dce6..29365e1 100644
--- a/arch/powerpc/include/asm/unistd.h
+++ b/arch/powerpc/include/asm/unistd.h
@@ -12,7 +12,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define __NR_syscalls		353
+#define __NR_syscalls		354
 
 #define __NR__exit __NR_exit
 #define NR_syscalls	__NR_syscalls
@@ -54,9 +54,12 @@
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_SYS_NEWFSTATAT
 #define __ARCH_WANT_COMPAT_SYS_SENDFILE
+#define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL
 #endif
 #define __ARCH_WANT_SYS_EXECVE
-#define __ARCH_WANT_KERNEL_EXECVE
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_CLONE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/powerpc/include/uapi/asm/Kbuild b/arch/powerpc/include/uapi/asm/Kbuild
index a33c3c0..f7bca63 100644
--- a/arch/powerpc/include/uapi/asm/Kbuild
+++ b/arch/powerpc/include/uapi/asm/Kbuild
@@ -7,6 +7,7 @@ header-y += bootx.h
 header-y += byteorder.h
 header-y += cputable.h
 header-y += elf.h
+header-y += epapr_hcalls.h
 header-y += errno.h
 header-y += fcntl.h
 header-y += ioctl.h
diff --git a/arch/powerpc/include/uapi/asm/epapr_hcalls.h b/arch/powerpc/include/uapi/asm/epapr_hcalls.h
new file mode 100644
index 0000000..7f9c74b
--- /dev/null
+++ b/arch/powerpc/include/uapi/asm/epapr_hcalls.h
@@ -0,0 +1,98 @@
+/*
+ * ePAPR hcall interface
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * This file is provided under a dual BSD/GPL license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * 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.
+ */
+
+#ifndef _UAPI_ASM_POWERPC_EPAPR_HCALLS_H
+#define _UAPI_ASM_POWERPC_EPAPR_HCALLS_H
+
+#define EV_BYTE_CHANNEL_SEND		1
+#define EV_BYTE_CHANNEL_RECEIVE		2
+#define EV_BYTE_CHANNEL_POLL		3
+#define EV_INT_SET_CONFIG		4
+#define EV_INT_GET_CONFIG		5
+#define EV_INT_SET_MASK			6
+#define EV_INT_GET_MASK			7
+#define EV_INT_IACK			9
+#define EV_INT_EOI			10
+#define EV_INT_SEND_IPI			11
+#define EV_INT_SET_TASK_PRIORITY	12
+#define EV_INT_GET_TASK_PRIORITY	13
+#define EV_DOORBELL_SEND		14
+#define EV_MSGSND			15
+#define EV_IDLE				16
+
+/* vendor ID: epapr */
+#define EV_LOCAL_VENDOR_ID		0	/* for private use */
+#define EV_EPAPR_VENDOR_ID		1
+#define EV_FSL_VENDOR_ID		2	/* Freescale Semiconductor */
+#define EV_IBM_VENDOR_ID		3	/* IBM */
+#define EV_GHS_VENDOR_ID		4	/* Green Hills Software */
+#define EV_ENEA_VENDOR_ID		5	/* Enea */
+#define EV_WR_VENDOR_ID			6	/* Wind River Systems */
+#define EV_AMCC_VENDOR_ID		7	/* Applied Micro Circuits */
+#define EV_KVM_VENDOR_ID		42	/* KVM */
+
+/* The max number of bytes that a byte channel can send or receive per call */
+#define EV_BYTE_CHANNEL_MAX_BYTES	16
+
+
+#define _EV_HCALL_TOKEN(id, num) (((id) << 16) | (num))
+#define EV_HCALL_TOKEN(hcall_num) _EV_HCALL_TOKEN(EV_EPAPR_VENDOR_ID, hcall_num)
+
+/* epapr return codes */
+#define EV_SUCCESS		0
+#define EV_EPERM		1	/* Operation not permitted */
+#define EV_ENOENT		2	/*  Entry Not Found */
+#define EV_EIO			3	/* I/O error occured */
+#define EV_EAGAIN		4	/* The operation had insufficient
+					 * resources to complete and should be
+					 * retried
+					 */
+#define EV_ENOMEM		5	/* There was insufficient memory to
+					 * complete the operation */
+#define EV_EFAULT		6	/* Bad guest address */
+#define EV_ENODEV		7	/* No such device */
+#define EV_EINVAL		8	/* An argument supplied to the hcall
+					   was out of range or invalid */
+#define EV_INTERNAL		9	/* An internal error occured */
+#define EV_CONFIG		10	/* A configuration error was detected */
+#define EV_INVALID_STATE	11	/* The object is in an invalid state */
+#define EV_UNIMPLEMENTED	12	/* Unimplemented hypercall */
+#define EV_BUFFER_OVERFLOW	13	/* Caller-supplied buffer too small */
+
+#endif /* _UAPI_ASM_POWERPC_EPAPR_HCALLS_H */
diff --git a/arch/powerpc/include/uapi/asm/ioctls.h b/arch/powerpc/include/uapi/asm/ioctls.h
index e9b7887..49a2579 100644
--- a/arch/powerpc/include/uapi/asm/ioctls.h
+++ b/arch/powerpc/include/uapi/asm/ioctls.h
@@ -97,6 +97,9 @@
 #define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
 #define TIOCVHANGUP	0x5437
+#define TIOCGPKT	_IOR('T', 0x38, int) /* Get packet mode state */
+#define TIOCGPTLCK	_IOR('T', 0x39, int) /* Get Pty lock state */
+#define TIOCGEXCL	_IOR('T', 0x40, int) /* Get exclusive mode state */
 
 #define TIOCSERCONFIG	0x5453
 #define TIOCSERGWILD	0x5454
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
index 1bea4d8..514883d 100644
--- a/arch/powerpc/include/uapi/asm/kvm.h
+++ b/arch/powerpc/include/uapi/asm/kvm.h
@@ -221,6 +221,12 @@ struct kvm_sregs {
 
 			__u32 dbsr;	/* KVM_SREGS_E_UPDATE_DBSR */
 			__u32 dbcr[3];
+			/*
+			 * iac/dac registers are 64bit wide, while this API
+			 * interface provides only lower 32 bits on 64 bit
+			 * processors. ONE_REG interface is added for 64bit
+			 * iac/dac registers.
+			 */
 			__u32 iac[4];
 			__u32 dac[2];
 			__u32 dvc[2];
@@ -325,6 +331,84 @@ struct kvm_book3e_206_tlb_params {
 	__u32 reserved[8];
 };
 
+/* For KVM_PPC_GET_HTAB_FD */
+struct kvm_get_htab_fd {
+	__u64	flags;
+	__u64	start_index;
+	__u64	reserved[2];
+};
+
+/* Values for kvm_get_htab_fd.flags */
+#define KVM_GET_HTAB_BOLTED_ONLY	((__u64)0x1)
+#define KVM_GET_HTAB_WRITE		((__u64)0x2)
+
+/*
+ * Data read on the file descriptor is formatted as a series of
+ * records, each consisting of a header followed by a series of
+ * `n_valid' HPTEs (16 bytes each), which are all valid.  Following
+ * those valid HPTEs there are `n_invalid' invalid HPTEs, which
+ * are not represented explicitly in the stream.  The same format
+ * is used for writing.
+ */
+struct kvm_get_htab_header {
+	__u32	index;
+	__u16	n_valid;
+	__u16	n_invalid;
+};
+
 #define KVM_REG_PPC_HIOR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x1)
+#define KVM_REG_PPC_IAC1	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x2)
+#define KVM_REG_PPC_IAC2	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3)
+#define KVM_REG_PPC_IAC3	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x4)
+#define KVM_REG_PPC_IAC4	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x5)
+#define KVM_REG_PPC_DAC1	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x6)
+#define KVM_REG_PPC_DAC2	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x7)
+#define KVM_REG_PPC_DABR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8)
+#define KVM_REG_PPC_DSCR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9)
+#define KVM_REG_PPC_PURR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa)
+#define KVM_REG_PPC_SPURR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb)
+#define KVM_REG_PPC_DAR		(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc)
+#define KVM_REG_PPC_DSISR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd)
+#define KVM_REG_PPC_AMR		(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xe)
+#define KVM_REG_PPC_UAMOR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xf)
+
+#define KVM_REG_PPC_MMCR0	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x10)
+#define KVM_REG_PPC_MMCR1	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x11)
+#define KVM_REG_PPC_MMCRA	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x12)
+
+#define KVM_REG_PPC_PMC1	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x18)
+#define KVM_REG_PPC_PMC2	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x19)
+#define KVM_REG_PPC_PMC3	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1a)
+#define KVM_REG_PPC_PMC4	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1b)
+#define KVM_REG_PPC_PMC5	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1c)
+#define KVM_REG_PPC_PMC6	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1d)
+#define KVM_REG_PPC_PMC7	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1e)
+#define KVM_REG_PPC_PMC8	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1f)
+
+/* 32 floating-point registers */
+#define KVM_REG_PPC_FPR0	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x20)
+#define KVM_REG_PPC_FPR(n)	(KVM_REG_PPC_FPR0 + (n))
+#define KVM_REG_PPC_FPR31	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3f)
+
+/* 32 VMX/Altivec vector registers */
+#define KVM_REG_PPC_VR0		(KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x40)
+#define KVM_REG_PPC_VR(n)	(KVM_REG_PPC_VR0 + (n))
+#define KVM_REG_PPC_VR31	(KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x5f)
+
+/* 32 double-width FP registers for VSX */
+/* High-order halves overlap with FP regs */
+#define KVM_REG_PPC_VSR0	(KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x60)
+#define KVM_REG_PPC_VSR(n)	(KVM_REG_PPC_VSR0 + (n))
+#define KVM_REG_PPC_VSR31	(KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x7f)
+
+/* FP and vector status/control registers */
+#define KVM_REG_PPC_FPSCR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x80)
+#define KVM_REG_PPC_VSCR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x81)
+
+/* Virtual processor areas */
+/* For SLB & DTL, address in high (first) half, length in low half */
+#define KVM_REG_PPC_VPA_ADDR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x82)
+#define KVM_REG_PPC_VPA_SLB	(KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x83)
+#define KVM_REG_PPC_VPA_DTL	(KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x84)
 
 #endif /* __LINUX_KVM_POWERPC_H */
diff --git a/arch/powerpc/include/uapi/asm/kvm_para.h b/arch/powerpc/include/uapi/asm/kvm_para.h
index 5e04383..ed0e025 100644
--- a/arch/powerpc/include/uapi/asm/kvm_para.h
+++ b/arch/powerpc/include/uapi/asm/kvm_para.h
@@ -75,9 +75,10 @@ struct kvm_vcpu_arch_shared {
 };
 
 #define KVM_SC_MAGIC_R0		0x4b564d21 /* "KVM!" */
-#define HC_VENDOR_KVM		(42 << 16)
-#define HC_EV_SUCCESS		0
-#define HC_EV_UNIMPLEMENTED	12
+
+#define KVM_HCALL_TOKEN(num)     _EV_HCALL_TOKEN(EV_KVM_VENDOR_ID, num)
+
+#include <uapi/asm/epapr_hcalls.h>
 
 #define KVM_FEATURE_MAGIC_PAGE	1
 
diff --git a/arch/powerpc/include/uapi/asm/setup.h b/arch/powerpc/include/uapi/asm/setup.h
index 8b9a306..552df83 100644
--- a/arch/powerpc/include/uapi/asm/setup.h
+++ b/arch/powerpc/include/uapi/asm/setup.h
@@ -1,32 +1 @@
-#ifndef _ASM_POWERPC_SETUP_H
-#define _ASM_POWERPC_SETUP_H
-
 #include <asm-generic/setup.h>
-
-#ifndef __ASSEMBLY__
-extern void ppc_printk_progress(char *s, unsigned short hex);
-
-extern unsigned int rtas_data;
-extern int mem_init_done;	/* set on boot once kmalloc can be called */
-extern int init_bootmem_done;	/* set once bootmem is available */
-extern unsigned long long memory_limit;
-extern unsigned long klimit;
-extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
-
-extern void via_cuda_init(void);
-extern void read_rtc_time(void);
-extern void pmac_find_display(void);
-
-struct device_node;
-extern void note_scsi_host(struct device_node *, void *);
-
-/* Used in very early kernel initialization. */
-extern unsigned long reloc_offset(void);
-extern unsigned long add_reloc_offset(unsigned long);
-extern void reloc_got2(unsigned long);
-
-#define PTRRELOC(x)	((typeof(x)) add_reloc_offset((unsigned long)(x)))
-
-#endif /* !__ASSEMBLY__ */
-
-#endif	/* _ASM_POWERPC_SETUP_H */
diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h
index 3d5179b..eb0b186 100644
--- a/arch/powerpc/include/uapi/asm/socket.h
+++ b/arch/powerpc/include/uapi/asm/socket.h
@@ -47,6 +47,7 @@
 /* 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
diff --git a/arch/powerpc/include/uapi/asm/unistd.h b/arch/powerpc/include/uapi/asm/unistd.h
index 380b5d3..8c478c6 100644
--- a/arch/powerpc/include/uapi/asm/unistd.h
+++ b/arch/powerpc/include/uapi/asm/unistd.h
@@ -375,6 +375,7 @@
 #define __NR_setns		350
 #define __NR_process_vm_readv	351
 #define __NR_process_vm_writev	352
+#define __NR_finit_module	353
 
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index cde12f8..8f61934 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -38,7 +38,7 @@ obj-$(CONFIG_PPC64)		+= setup_64.o sys_ppc32.o \
 				   paca.o nvram_64.o firmware.o
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= hw_breakpoint.o
 obj-$(CONFIG_PPC_BOOK3S_64)	+= cpu_setup_ppc970.o cpu_setup_pa6t.o
-obj-$(CONFIG_PPC_BOOK3S_64)	+= cpu_setup_power7.o
+obj-$(CONFIG_PPC_BOOK3S_64)	+= cpu_setup_power.o
 obj64-$(CONFIG_RELOCATABLE)	+= reloc_64.o
 obj-$(CONFIG_PPC_BOOK3E_64)	+= exceptions-64e.o idle_book3e.o
 obj-$(CONFIG_PPC_A2)		+= cpu_setup_a2.o
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 7523539..4e23ba2 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -441,8 +441,7 @@ int main(void)
 	DEFINE(KVM_HOST_LPCR, offsetof(struct kvm, arch.host_lpcr));
 	DEFINE(KVM_HOST_SDR1, offsetof(struct kvm, arch.host_sdr1));
 	DEFINE(KVM_TLBIE_LOCK, offsetof(struct kvm, arch.tlbie_lock));
-	DEFINE(KVM_ONLINE_CPUS, offsetof(struct kvm, online_vcpus.counter));
-	DEFINE(KVM_LAST_VCPU, offsetof(struct kvm, arch.last_vcpu));
+	DEFINE(KVM_NEED_FLUSH, offsetof(struct kvm, arch.need_tlb_flush.bits));
 	DEFINE(KVM_LPCR, offsetof(struct kvm, arch.lpcr));
 	DEFINE(KVM_RMOR, offsetof(struct kvm, arch.rmor));
 	DEFINE(KVM_VRMA_SLB_V, offsetof(struct kvm, arch.vrma_slb_v));
@@ -470,7 +469,6 @@ int main(void)
 	DEFINE(VCPU_SLB, offsetof(struct kvm_vcpu, arch.slb));
 	DEFINE(VCPU_SLB_MAX, offsetof(struct kvm_vcpu, arch.slb_max));
 	DEFINE(VCPU_SLB_NR, offsetof(struct kvm_vcpu, arch.slb_nr));
-	DEFINE(VCPU_LAST_CPU, offsetof(struct kvm_vcpu, arch.last_cpu));
 	DEFINE(VCPU_FAULT_DSISR, offsetof(struct kvm_vcpu, arch.fault_dsisr));
 	DEFINE(VCPU_FAULT_DAR, offsetof(struct kvm_vcpu, arch.fault_dar));
 	DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S
new file mode 100644
index 0000000..57cf140
--- /dev/null
+++ b/arch/powerpc/kernel/cpu_setup_power.S
@@ -0,0 +1,125 @@
+/*
+ * This file contains low level CPU setup functions.
+ *    Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.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 <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/cache.h>
+
+/* Entry: r3 = crap, r4 = ptr to cputable entry
+ *
+ * Note that we can be called twice for pseudo-PVRs
+ */
+_GLOBAL(__setup_cpu_power7)
+	mflr	r11
+	bl	__init_hvmode_206
+	mtlr	r11
+	beqlr
+	li	r0,0
+	mtspr	SPRN_LPID,r0
+	mfspr	r3,SPRN_LPCR
+	bl	__init_LPCR
+	bl	__init_TLB
+	mtlr	r11
+	blr
+
+_GLOBAL(__restore_cpu_power7)
+	mflr	r11
+	mfmsr	r3
+	rldicl.	r0,r3,4,63
+	beqlr
+	li	r0,0
+	mtspr	SPRN_LPID,r0
+	mfspr	r3,SPRN_LPCR
+	bl	__init_LPCR
+	bl	__init_TLB
+	mtlr	r11
+	blr
+
+_GLOBAL(__setup_cpu_power8)
+	mflr	r11
+	bl	__init_hvmode_206
+	mtlr	r11
+	beqlr
+	li	r0,0
+	mtspr	SPRN_LPID,r0
+	mfspr	r3,SPRN_LPCR
+	oris	r3, r3, LPCR_AIL_3@h
+	bl	__init_LPCR
+	bl	__init_TLB
+	mtlr	r11
+	blr
+
+_GLOBAL(__restore_cpu_power8)
+	mflr	r11
+	mfmsr	r3
+	rldicl.	r0,r3,4,63
+	beqlr
+	li	r0,0
+	mtspr	SPRN_LPID,r0
+	mfspr   r3,SPRN_LPCR
+	oris	r3, r3, LPCR_AIL_3@h
+	bl	__init_LPCR
+	bl	__init_TLB
+	mtlr	r11
+	blr
+
+__init_hvmode_206:
+	/* Disable CPU_FTR_HVMODE and exit if MSR:HV is not set */
+	mfmsr	r3
+	rldicl.	r0,r3,4,63
+	bnelr
+	ld	r5,CPU_SPEC_FEATURES(r4)
+	LOAD_REG_IMMEDIATE(r6,CPU_FTR_HVMODE)
+	xor	r5,r5,r6
+	std	r5,CPU_SPEC_FEATURES(r4)
+	blr
+
+__init_LPCR:
+	/* Setup a sane LPCR:
+	 *   Called with initial LPCR in R3
+	 *
+	 *   LPES = 0b01 (HSRR0/1 used for 0x500)
+	 *   PECE = 0b111
+	 *   DPFD = 4
+	 *   HDICE = 0
+	 *   VC = 0b100 (VPM0=1, VPM1=0, ISL=0)
+	 *   VRMASD = 0b10000 (L=1, LP=00)
+	 *
+	 * Other bits untouched for now
+	 */
+	li	r5,1
+	rldimi	r3,r5, LPCR_LPES_SH, 64-LPCR_LPES_SH-2
+	ori	r3,r3,(LPCR_PECE0|LPCR_PECE1|LPCR_PECE2)
+	li	r5,4
+	rldimi	r3,r5, LPCR_DPFD_SH, 64-LPCR_DPFD_SH-3
+	clrrdi	r3,r3,1		/* clear HDICE */
+	li	r5,4
+	rldimi	r3,r5, LPCR_VC_SH, 0
+	li	r5,0x10
+	rldimi	r3,r5, LPCR_VRMASD_SH, 64-LPCR_VRMASD_SH-5
+	mtspr	SPRN_LPCR,r3
+	isync
+	blr
+
+__init_TLB:
+	/* Clear the TLB */
+	li	r6,128
+	mtctr	r6
+	li	r7,0xc00	/* IS field = 0b11 */
+	ptesync
+2:	tlbiel	r7
+	addi	r7,r7,0x1000
+	bdnz	2b
+	ptesync
+1:	blr
diff --git a/arch/powerpc/kernel/cpu_setup_power7.S b/arch/powerpc/kernel/cpu_setup_power7.S
deleted file mode 100644
index 76797c5..0000000
--- a/arch/powerpc/kernel/cpu_setup_power7.S
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * This file contains low level CPU setup functions.
- *    Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.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 <asm/processor.h>
-#include <asm/page.h>
-#include <asm/cputable.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-#include <asm/cache.h>
-
-/* Entry: r3 = crap, r4 = ptr to cputable entry
- *
- * Note that we can be called twice for pseudo-PVRs
- */
-_GLOBAL(__setup_cpu_power7)
-	mflr	r11
-	bl	__init_hvmode_206
-	mtlr	r11
-	beqlr
-	li	r0,0
-	mtspr	SPRN_LPID,r0
-	bl	__init_LPCR
-	bl	__init_TLB
-	mtlr	r11
-	blr
-
-_GLOBAL(__restore_cpu_power7)
-	mflr	r11
-	mfmsr	r3
-	rldicl.	r0,r3,4,63
-	beqlr
-	li	r0,0
-	mtspr	SPRN_LPID,r0
-	bl	__init_LPCR
-	bl	__init_TLB
-	mtlr	r11
-	blr
-
-__init_hvmode_206:
-	/* Disable CPU_FTR_HVMODE and exit if MSR:HV is not set */
-	mfmsr	r3
-	rldicl.	r0,r3,4,63
-	bnelr
-	ld	r5,CPU_SPEC_FEATURES(r4)
-	LOAD_REG_IMMEDIATE(r6,CPU_FTR_HVMODE)
-	xor	r5,r5,r6
-	std	r5,CPU_SPEC_FEATURES(r4)
-	blr
-
-__init_LPCR:
-	/* Setup a sane LPCR:
-	 *
-	 *   LPES = 0b01 (HSRR0/1 used for 0x500)
-	 *   PECE = 0b111
-	 *   DPFD = 4
-	 *   HDICE = 0
-	 *   VC = 0b100 (VPM0=1, VPM1=0, ISL=0)
-	 *   VRMASD = 0b10000 (L=1, LP=00)
-	 *
-	 * Other bits untouched for now
-	 */
-	mfspr	r3,SPRN_LPCR
-	li	r5,1
-	rldimi	r3,r5, LPCR_LPES_SH, 64-LPCR_LPES_SH-2
-	ori	r3,r3,(LPCR_PECE0|LPCR_PECE1|LPCR_PECE2)
-	li	r5,4
-	rldimi	r3,r5, LPCR_DPFD_SH, 64-LPCR_DPFD_SH-3
-	clrrdi	r3,r3,1		/* clear HDICE */
-	li	r5,4
-	rldimi	r3,r5, LPCR_VC_SH, 0
-	li	r5,0x10
-	rldimi	r3,r5, LPCR_VRMASD_SH, 64-LPCR_VRMASD_SH-5
-	mtspr	SPRN_LPCR,r3
-	isync
-	blr
-
-__init_TLB:
-	/* Clear the TLB */
-	li	r6,128
-	mtctr	r6
-	li	r7,0xc00	/* IS field = 0b11 */
-	ptesync
-2:	tlbiel	r7
-	addi	r7,r7,0x1000
-	bdnz	2b
-	ptesync
-1:	blr
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 0514c21..75a3d71 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -68,6 +68,8 @@ extern void __restore_cpu_pa6t(void);
 extern void __restore_cpu_ppc970(void);
 extern void __setup_cpu_power7(unsigned long offset, struct cpu_spec* spec);
 extern void __restore_cpu_power7(void);
+extern void __setup_cpu_power8(unsigned long offset, struct cpu_spec* spec);
+extern void __restore_cpu_power8(void);
 extern void __restore_cpu_a2(void);
 #endif /* CONFIG_PPC64 */
 #if defined(CONFIG_E500)
@@ -94,6 +96,10 @@ extern void __restore_cpu_e5500(void);
 				 PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \
 				 PPC_FEATURE_TRUE_LE | \
 				 PPC_FEATURE_PSERIES_PERFMON_COMPAT)
+#define COMMON_USER_POWER8	(COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_06 |\
+				 PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \
+				 PPC_FEATURE_TRUE_LE | \
+				 PPC_FEATURE_PSERIES_PERFMON_COMPAT)
 #define COMMON_USER_PA6T	(COMMON_USER_PPC64 | PPC_FEATURE_PA6T |\
 				 PPC_FEATURE_TRUE_LE | \
 				 PPC_FEATURE_HAS_ALTIVEC_COMP)
@@ -429,6 +435,21 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.cpu_restore		= __restore_cpu_power7,
 		.platform		= "power7",
 	},
+	{	/* 2.07-compliant processor, i.e. Power8 "architected" mode */
+		.pvr_mask		= 0xffffffff,
+		.pvr_value		= 0x0f000004,
+		.cpu_name		= "POWER8 (architected)",
+		.cpu_features		= CPU_FTRS_POWER8,
+		.cpu_user_features	= COMMON_USER_POWER8,
+		.mmu_features		= MMU_FTRS_POWER8,
+		.icache_bsize		= 128,
+		.dcache_bsize		= 128,
+		.oprofile_type		= PPC_OPROFILE_POWER4,
+		.oprofile_cpu_type	= "ppc64/ibm-compat-v1",
+		.cpu_setup		= __setup_cpu_power8,
+		.cpu_restore		= __restore_cpu_power8,
+		.platform		= "power8",
+	},
 	{	/* Power7 */
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x003f0000,
@@ -463,6 +484,23 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.cpu_restore		= __restore_cpu_power7,
 		.platform		= "power7+",
 	},
+	{	/* Power8 */
+		.pvr_mask		= 0xffff0000,
+		.pvr_value		= 0x004b0000,
+		.cpu_name		= "POWER8 (raw)",
+		.cpu_features		= CPU_FTRS_POWER8,
+		.cpu_user_features	= COMMON_USER_POWER8,
+		.mmu_features		= MMU_FTRS_POWER8,
+		.icache_bsize		= 128,
+		.dcache_bsize		= 128,
+		.num_pmcs		= 6,
+		.pmc_type		= PPC_PMC_IBM,
+		.oprofile_cpu_type	= "ppc64/power8",
+		.oprofile_type		= PPC_OPROFILE_POWER4,
+		.cpu_setup		= __setup_cpu_power8,
+		.cpu_restore		= __restore_cpu_power8,
+		.platform		= "power8",
+	},
 	{	/* Cell Broadband Engine */
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x00700000,
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 9499385..d22e73e 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -444,11 +444,6 @@ ret_from_kernel_thread:
 	PPC440EP_ERR42
 	blrl
 	li	r3,0
-	b	do_exit		# no return
-
-	.globl	__ret_from_kernel_execve
-__ret_from_kernel_execve:
-	addi	r1,r3,-STACK_FRAME_OVERHEAD
 	b	ret_from_syscall
 
 /* Traced system call support */
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 56e0ff0..33c7343 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -373,17 +373,13 @@ _GLOBAL(ret_from_fork)
 _GLOBAL(ret_from_kernel_thread)
 	bl	.schedule_tail
 	REST_NVGPRS(r1)
-	REST_GPR(2,r1)
+	ld	r14, 0(r14)
+	li	r3,0
+	std	r3,0(r1)
 	mtlr	r14
 	mr	r3,r15
 	blrl
 	li	r3,0
-	b	.do_exit	# no return
-
-_GLOBAL(__ret_from_kernel_execve)
-	addi	r1,r3,-STACK_FRAME_OVERHEAD
-	li	r10,1
-	std	r10,SOFTE(r1)
 	b	syscall_exit
 
 	.section	".toc","aw"
diff --git a/arch/powerpc/kernel/epapr_hcalls.S b/arch/powerpc/kernel/epapr_hcalls.S
index 697b390..62c0dc2 100644
--- a/arch/powerpc/kernel/epapr_hcalls.S
+++ b/arch/powerpc/kernel/epapr_hcalls.S
@@ -8,13 +8,41 @@
  */
 
 #include <linux/threads.h>
+#include <asm/epapr_hcalls.h>
 #include <asm/reg.h>
 #include <asm/page.h>
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
+#include <asm/asm-compat.h>
 #include <asm/asm-offsets.h>
 
+/* epapr_ev_idle() was derived from e500_idle() */
+_GLOBAL(epapr_ev_idle)
+	CURRENT_THREAD_INFO(r3, r1)
+	PPC_LL	r4, TI_LOCAL_FLAGS(r3)	/* set napping bit */
+	ori	r4, r4,_TLF_NAPPING	/* so when we take an exception */
+	PPC_STL	r4, TI_LOCAL_FLAGS(r3)	/* it will return to our caller */
+
+	wrteei	1
+
+idle_loop:
+	LOAD_REG_IMMEDIATE(r11, EV_HCALL_TOKEN(EV_IDLE))
+
+.global epapr_ev_idle_start
+epapr_ev_idle_start:
+	li	r3, -1
+	nop
+	nop
+	nop
+
+	/*
+	 * Guard against spurious wakeups from a hypervisor --
+	 * only interrupt will cause us to return to LR due to
+	 * _TLF_NAPPING.
+	 */
+	b	idle_loop
+
 /* Hypercall entry point. Will be patched with device tree instructions. */
 .global epapr_hypercall_start
 epapr_hypercall_start:
diff --git a/arch/powerpc/kernel/epapr_paravirt.c b/arch/powerpc/kernel/epapr_paravirt.c
index 028aeae..f3eab85 100644
--- a/arch/powerpc/kernel/epapr_paravirt.c
+++ b/arch/powerpc/kernel/epapr_paravirt.c
@@ -21,6 +21,10 @@
 #include <asm/epapr_hcalls.h>
 #include <asm/cacheflush.h>
 #include <asm/code-patching.h>
+#include <asm/machdep.h>
+
+extern void epapr_ev_idle(void);
+extern u32 epapr_ev_idle_start[];
 
 bool epapr_paravirt_enabled;
 
@@ -41,8 +45,13 @@ static int __init epapr_paravirt_init(void)
 	if (len % 4 || len > (4 * 4))
 		return -ENODEV;
 
-	for (i = 0; i < (len / 4); i++)
+	for (i = 0; i < (len / 4); i++) {
 		patch_instruction(epapr_hypercall_start + i, insts[i]);
+		patch_instruction(epapr_ev_idle_start + i, insts[i]);
+	}
+
+	if (of_get_property(hyper_node, "has-idle", NULL))
+		ppc_md.power_save = epapr_ev_idle;
 
 	epapr_paravirt_enabled = true;
 
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 10b658a..4665e82 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -19,12 +19,76 @@
 /*
  * We layout physical memory as follows:
  * 0x0000 - 0x00ff : Secondary processor spin code
- * 0x0100 - 0x2fff : pSeries Interrupt prologs
- * 0x3000 - 0x5fff : interrupt support common interrupt prologs
- * 0x6000 - 0x6fff : Initial (CPU0) segment table
+ * 0x0100 - 0x17ff : pSeries Interrupt prologs
+ * 0x1800 - 0x4000 : interrupt support common interrupt prologs
+ * 0x4000 - 0x5fff : pSeries interrupts with IR=1,DR=1
+ * 0x6000 - 0x6fff : more interrupt support including for IR=1,DR=1
  * 0x7000 - 0x7fff : FWNMI data area
- * 0x8000 -        : Early init and support code
+ * 0x8000 - 0x8fff : Initial (CPU0) segment table
+ * 0x9000 -        : Early init and support code
  */
+	/* Syscall routine is used twice, in reloc-off and reloc-on paths */
+#define SYSCALL_PSERIES_1 					\
+BEGIN_FTR_SECTION						\
+	cmpdi	r0,0x1ebe ; 					\
+	beq-	1f ;						\
+END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)				\
+	mr	r9,r13 ;					\
+	GET_PACA(r13) ;						\
+	mfspr	r11,SPRN_SRR0 ;					\
+0:
+
+#define SYSCALL_PSERIES_2_RFID 					\
+	mfspr	r12,SPRN_SRR1 ;					\
+	ld	r10,PACAKBASE(r13) ; 				\
+	LOAD_HANDLER(r10, system_call_entry) ; 			\
+	mtspr	SPRN_SRR0,r10 ; 				\
+	ld	r10,PACAKMSR(r13) ;				\
+	mtspr	SPRN_SRR1,r10 ; 				\
+	rfid ; 							\
+	b	. ;	/* prevent speculative execution */
+
+#define SYSCALL_PSERIES_3					\
+	/* Fast LE/BE switch system call */			\
+1:	mfspr	r12,SPRN_SRR1 ;					\
+	xori	r12,r12,MSR_LE ;				\
+	mtspr	SPRN_SRR1,r12 ;					\
+	rfid ;		/* return to userspace */		\
+	b	. ;						\
+2:	mfspr	r12,SPRN_SRR1 ;					\
+	andi.	r12,r12,MSR_PR ;				\
+	bne	0b ;						\
+	mtspr	SPRN_SRR0,r3 ;					\
+	mtspr	SPRN_SRR1,r4 ;					\
+	mtspr	SPRN_SDR1,r5 ;					\
+	rfid ;							\
+	b	. ;	/* prevent speculative execution */
+
+#if defined(CONFIG_RELOCATABLE)
+	/*
+	 * We can't branch directly; in the direct case we use LR
+	 * and system_call_entry restores LR.  (We thus need to move
+	 * LR to r10 in the RFID case too.)
+	 */
+#define SYSCALL_PSERIES_2_DIRECT				\
+	mflr	r10 ;						\
+	ld	r12,PACAKBASE(r13) ; 				\
+	LOAD_HANDLER(r12, system_call_entry_direct) ;		\
+	mtlr	r12 ;						\
+	mfspr	r12,SPRN_SRR1 ;					\
+	/* Re-use of r13... No spare regs to do this */	\
+	li	r13,MSR_RI ;					\
+	mtmsrd 	r13,1 ;						\
+	GET_PACA(r13) ;	/* get r13 back */			\
+	blr ;
+#else
+	/* We can branch directly */
+#define SYSCALL_PSERIES_2_DIRECT				\
+	mfspr	r12,SPRN_SRR1 ;					\
+	li	r10,MSR_RI ;					\
+	mtmsrd 	r10,1 ;			/* Set RI (EE=0) */	\
+	b	system_call_entry_direct ;
+#endif
 
 /*
  * This is the start of the interrupt handlers for pSeries
@@ -207,31 +271,11 @@ system_call_pSeries:
 	KVMTEST(0xc00)
 	GET_SCRATCH0(r13)
 #endif
-BEGIN_FTR_SECTION
-	cmpdi	r0,0x1ebe
-	beq-	1f
-END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
-	mr	r9,r13
-	GET_PACA(r13)
-	mfspr	r11,SPRN_SRR0
-	mfspr	r12,SPRN_SRR1
-	ld	r10,PACAKBASE(r13)
-	LOAD_HANDLER(r10, system_call_entry)
-	mtspr	SPRN_SRR0,r10
-	ld	r10,PACAKMSR(r13)
-	mtspr	SPRN_SRR1,r10
-	rfid
-	b	.	/* prevent speculative execution */
-
+	SYSCALL_PSERIES_1
+	SYSCALL_PSERIES_2_RFID
+	SYSCALL_PSERIES_3
 	KVM_HANDLER(PACA_EXGEN, EXC_STD, 0xc00)
 
-/* Fast LE/BE switch system call */
-1:	mfspr	r12,SPRN_SRR1
-	xori	r12,r12,MSR_LE
-	mtspr	SPRN_SRR1,r12
-	rfid		/* return to userspace */
-	b	.
-
 	STD_EXCEPTION_PSERIES(0xd00, 0xd00, single_step)
 	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xd00)
 
@@ -276,7 +320,7 @@ vsx_unavailable_pSeries_1:
 	KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_STD, 0x1300)
 
 	. = 0x1500
-	.global denorm_Hypervisor
+	.global denorm_exception_hv
 denorm_exception_hv:
 	HMT_MEDIUM
 	mtspr	SPRN_SPRG_HSCRATCH0,r13
@@ -311,12 +355,14 @@ denorm_exception_hv:
 #ifdef CONFIG_CBE_RAS
 	STD_EXCEPTION_HV(0x1800, 0x1802, cbe_thermal)
 	KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1802)
+#else
+	. = 0x1800
 #endif /* CONFIG_CBE_RAS */
 
-	. = 0x3000
 
 /*** Out of line interrupts support ***/
 
+	.align	7
 	/* moved from 0x200 */
 machine_check_pSeries:
 	.globl machine_check_fwnmi
@@ -575,16 +621,12 @@ slb_miss_user_pseries:
 	b	.				/* prevent spec. execution */
 #endif /* __DISABLED__ */
 
-	.align	7
-	.globl	__end_interrupts
-__end_interrupts:
-
 /*
  * Code from here down to __end_handlers is invoked from the
  * exception prologs above.  Because the prologs assemble the
  * addresses of these handlers using the LOAD_HANDLER macro,
- * which uses an addi instruction, these handlers must be in
- * the first 32k of the kernel image.
+ * which uses an ori instruction, these handlers must be in
+ * the first 64k of the kernel image.
  */
 
 /*** Common interrupt handlers ***/
@@ -613,8 +655,8 @@ machine_check_common:
 	STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)
 	STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception)
 	STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception)
-        STD_EXCEPTION_COMMON(0xe40, emulation_assist, .program_check_exception)
-        STD_EXCEPTION_COMMON(0xe60, hmi_exception, .unknown_exception)
+	STD_EXCEPTION_COMMON(0xe40, emulation_assist, .program_check_exception)
+	STD_EXCEPTION_COMMON(0xe60, hmi_exception, .unknown_exception)
 	STD_EXCEPTION_COMMON_ASYNC(0xf00, performance_monitor, .performance_monitor_exception)
 	STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception)
 	STD_EXCEPTION_COMMON(0x1502, denorm, .unknown_exception)
@@ -629,7 +671,158 @@ machine_check_common:
 	STD_EXCEPTION_COMMON(0x1800, cbe_thermal, .cbe_thermal_exception)
 #endif /* CONFIG_CBE_RAS */
 
+	/*
+	 * Relocation-on interrupts: A subset of the interrupts can be delivered
+	 * with IR=1/DR=1, if AIL==2 and MSR.HV won't be changed by delivering
+	 * it.  Addresses are the same as the original interrupt addresses, but
+	 * offset by 0xc000000000004000.
+	 * It's impossible to receive interrupts below 0x300 via this mechanism.
+	 * KVM: None of these traps are from the guest ; anything that escalated
+	 * to HV=1 from HV=0 is delivered via real mode handlers.
+	 */
+
+	/*
+	 * This uses the standard macro, since the original 0x300 vector
+	 * only has extra guff for STAB-based processors -- which never
+	 * come here.
+	 */
+	STD_RELON_EXCEPTION_PSERIES(0x4300, 0x300, data_access)
+	. = 0x4380
+	.globl data_access_slb_relon_pSeries
+data_access_slb_relon_pSeries:
+	HMT_MEDIUM
+	SET_SCRATCH0(r13)
+	EXCEPTION_PROLOG_1(PACA_EXSLB, NOTEST, 0x380)
+	std	r3,PACA_EXSLB+EX_R3(r13)
+	mfspr	r3,SPRN_DAR
+	mfspr	r12,SPRN_SRR1
+#ifndef CONFIG_RELOCATABLE
+	b	.slb_miss_realmode
+#else
+	/*
+	 * We can't just use a direct branch to .slb_miss_realmode
+	 * because the distance from here to there depends on where
+	 * the kernel ends up being put.
+	 */
+	mfctr	r11
+	ld	r10,PACAKBASE(r13)
+	LOAD_HANDLER(r10, .slb_miss_realmode)
+	mtctr	r10
+	bctr
+#endif
+
+	STD_RELON_EXCEPTION_PSERIES(0x4400, 0x400, instruction_access)
+	. = 0x4480
+	.globl instruction_access_slb_relon_pSeries
+instruction_access_slb_relon_pSeries:
+	HMT_MEDIUM
+	SET_SCRATCH0(r13)
+	EXCEPTION_PROLOG_1(PACA_EXSLB, NOTEST, 0x480)
+	std	r3,PACA_EXSLB+EX_R3(r13)
+	mfspr	r3,SPRN_SRR0		/* SRR0 is faulting address */
+	mfspr	r12,SPRN_SRR1
+#ifndef CONFIG_RELOCATABLE
+	b	.slb_miss_realmode
+#else
+	mfctr	r11
+	ld	r10,PACAKBASE(r13)
+	LOAD_HANDLER(r10, .slb_miss_realmode)
+	mtctr	r10
+	bctr
+#endif
+
+	. = 0x4500
+	.globl hardware_interrupt_relon_pSeries;
+	.globl hardware_interrupt_relon_hv;
+hardware_interrupt_relon_pSeries:
+hardware_interrupt_relon_hv:
+	BEGIN_FTR_SECTION
+		_MASKABLE_RELON_EXCEPTION_PSERIES(0x502, hardware_interrupt, EXC_HV, SOFTEN_TEST_HV)
+	FTR_SECTION_ELSE
+		_MASKABLE_RELON_EXCEPTION_PSERIES(0x500, hardware_interrupt, EXC_STD, SOFTEN_TEST_PR)
+	ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_206)
+	STD_RELON_EXCEPTION_PSERIES(0x4600, 0x600, alignment)
+	STD_RELON_EXCEPTION_PSERIES(0x4700, 0x700, program_check)
+	STD_RELON_EXCEPTION_PSERIES(0x4800, 0x800, fp_unavailable)
+	MASKABLE_RELON_EXCEPTION_PSERIES(0x4900, 0x900, decrementer)
+	STD_RELON_EXCEPTION_HV(0x4980, 0x982, hdecrementer)
+	STD_RELON_EXCEPTION_PSERIES(0x4b00, 0xb00, trap_0b)
+
+	. = 0x4c00
+	.globl system_call_relon_pSeries
+system_call_relon_pSeries:
+	HMT_MEDIUM
+	SYSCALL_PSERIES_1
+	SYSCALL_PSERIES_2_DIRECT
+	SYSCALL_PSERIES_3
+
+	STD_RELON_EXCEPTION_PSERIES(0x4d00, 0xd00, single_step)
+
+	. = 0x4e00
+	b	h_data_storage_relon_hv
+
+	. = 0x4e20
+	b	h_instr_storage_relon_hv
+
+	. = 0x4e40
+	b	emulation_assist_relon_hv
+
+	. = 0x4e50
+	b	hmi_exception_relon_hv
+
+	. = 0x4e60
+	b	hmi_exception_relon_hv
+
+	/* For when we support the doorbell interrupt:
+	STD_RELON_EXCEPTION_HYPERVISOR(0x4e80, 0xe80, doorbell_hyper)
+	*/
+
+performance_monitor_relon_pSeries_1:
+	. = 0x4f00
+	b	performance_monitor_relon_pSeries
+
+altivec_unavailable_relon_pSeries_1:
+	. = 0x4f20
+	b	altivec_unavailable_relon_pSeries
+
+vsx_unavailable_relon_pSeries_1:
+	. = 0x4f40
+	b	vsx_unavailable_relon_pSeries
+
+#ifdef CONFIG_CBE_RAS
+	STD_RELON_EXCEPTION_HV(0x5200, 0x1202, cbe_system_error)
+#endif /* CONFIG_CBE_RAS */
+	STD_RELON_EXCEPTION_PSERIES(0x5300, 0x1300, instruction_breakpoint)
+#ifdef CONFIG_PPC_DENORMALISATION
+	. = 0x5500
+	b	denorm_exception_hv
+#endif
+#ifdef CONFIG_CBE_RAS
+	STD_RELON_EXCEPTION_HV(0x5600, 0x1602, cbe_maintenance)
+#else
+#ifdef CONFIG_HVC_SCOM
+	STD_RELON_EXCEPTION_HV(0x5600, 0x1600, maintence_interrupt)
+	KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1600)
+#endif /* CONFIG_HVC_SCOM */
+#endif /* CONFIG_CBE_RAS */
+	STD_RELON_EXCEPTION_PSERIES(0x5700, 0x1700, altivec_assist)
+#ifdef CONFIG_CBE_RAS
+	STD_RELON_EXCEPTION_HV(0x5800, 0x1802, cbe_thermal)
+#endif /* CONFIG_CBE_RAS */
+
+	/* Other future vectors */
 	.align	7
+	.globl	__end_interrupts
+__end_interrupts:
+
+	.align	7
+system_call_entry_direct:
+#if defined(CONFIG_RELOCATABLE)
+	/* The first level prologue may have used LR to get here, saving
+	 * orig in r10.  To save hacking/ifdeffing common code, restore here.
+	 */
+	mtlr	r10
+#endif
 system_call_entry:
 	b	system_call_common
 
@@ -714,21 +907,21 @@ data_access_common:
 	ld	r3,PACA_EXGEN+EX_DAR(r13)
 	lwz	r4,PACA_EXGEN+EX_DSISR(r13)
 	li	r5,0x300
-	b	.do_hash_page	 	/* Try to handle as hpte fault */
+	b	.do_hash_page		/* Try to handle as hpte fault */
 
 	.align  7
-        .globl  h_data_storage_common
+	.globl  h_data_storage_common
 h_data_storage_common:
-        mfspr   r10,SPRN_HDAR
-        std     r10,PACA_EXGEN+EX_DAR(r13)
-        mfspr   r10,SPRN_HDSISR
-        stw     r10,PACA_EXGEN+EX_DSISR(r13)
-        EXCEPTION_PROLOG_COMMON(0xe00, PACA_EXGEN)
-        bl      .save_nvgprs
+	mfspr   r10,SPRN_HDAR
+	std     r10,PACA_EXGEN+EX_DAR(r13)
+	mfspr   r10,SPRN_HDSISR
+	stw     r10,PACA_EXGEN+EX_DSISR(r13)
+	EXCEPTION_PROLOG_COMMON(0xe00, PACA_EXGEN)
+	bl      .save_nvgprs
 	DISABLE_INTS
-        addi    r3,r1,STACK_FRAME_OVERHEAD
-        bl      .unknown_exception
-        b       .ret_from_except
+	addi    r3,r1,STACK_FRAME_OVERHEAD
+	bl      .unknown_exception
+	b       .ret_from_except
 
 	.align	7
 	.globl instruction_access_common
@@ -741,7 +934,7 @@ instruction_access_common:
 	li	r5,0x400
 	b	.do_hash_page		/* Try to handle as hpte fault */
 
-        STD_EXCEPTION_COMMON(0xe20, h_instr_storage, .unknown_exception)
+	STD_EXCEPTION_COMMON(0xe20, h_instr_storage, .unknown_exception)
 
 /*
  * Here is the common SLB miss user that is used when going to virtual
@@ -1152,6 +1345,21 @@ _GLOBAL(do_stab_bolted)
 	rfid
 	b	.	/* prevent speculative execution */
 
+
+	/* Equivalents to the above handlers for relocation-on interrupt vectors */
+	STD_RELON_EXCEPTION_HV(., 0xe00, h_data_storage)
+	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe00)
+	STD_RELON_EXCEPTION_HV(., 0xe20, h_instr_storage)
+	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe20)
+	STD_RELON_EXCEPTION_HV(., 0xe40, emulation_assist)
+	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe40)
+	STD_RELON_EXCEPTION_HV(., 0xe60, hmi_exception)
+	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe60)
+
+	STD_RELON_EXCEPTION_PSERIES(., 0xf00, performance_monitor)
+	STD_RELON_EXCEPTION_PSERIES(., 0xf20, altivec_unavailable)
+	STD_RELON_EXCEPTION_PSERIES(., 0xf40, vsx_unavailable)
+
 #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 /*
  * Data area reserved for FWNMI option.
@@ -1164,7 +1372,7 @@ fwnmi_data_area:
 	/* pseries and powernv need to keep the whole page from
 	 * 0x7000 to 0x8000 free for use by the firmware
 	 */
-        . = 0x8000
+	. = 0x8000
 #endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
 
 /* Space for CPU0's segment table */
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 58bddee..116f086 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -422,7 +422,7 @@ _STATIC(__after_prom_start)
 	tovirt(r6,r6)			/* on booke, we already run at PAGE_OFFSET */
 #endif
 
-#ifdef CONFIG_CRASH_DUMP
+#ifdef CONFIG_RELOCATABLE
 /*
  * Check if the kernel has to be running as relocatable kernel based on the
  * variable __run_at_load, if it is set the kernel is treated as relocatable
@@ -432,7 +432,8 @@ _STATIC(__after_prom_start)
 	cmplwi	cr0,r7,1
 	bne	3f
 
-	li	r5,__end_interrupts - _stext	/* just copy interrupts */
+	/* just copy interrupts */
+	LOAD_REG_IMMEDIATE(r5, __end_interrupts - _stext)
 	b	5f
 3:
 #endif
@@ -703,6 +704,7 @@ _INIT_STATIC(start_here_multiplatform)
 
 #ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
 	/* Setup OPAL entry */
+	LOAD_REG_ADDR(r11, opal)
 	std	r28,0(r11);
 	std	r29,8(r11);
 #endif
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
index 2099d9a..ea78761 100644
--- a/arch/powerpc/kernel/idle.c
+++ b/arch/powerpc/kernel/idle.c
@@ -55,9 +55,6 @@ __setup("powersave=off", powersave_off);
  */
 void cpu_idle(void)
 {
-	if (ppc_md.idle_loop)
-		ppc_md.idle_loop();	/* doesn't return */
-
 	set_thread_flag(TIF_POLLING_NRFLAG);
 	while (1) {
 		tick_nohz_idle_enter();
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 8226c6c..c862fd7 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -656,7 +656,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
 	struct iommu_pool *p;
 
 	/* number of bytes needed for the bitmap */
-	sz = (tbl->it_size + 7) >> 3;
+	sz = BITS_TO_LONGS(tbl->it_size) * sizeof(unsigned long);
 
 	page = alloc_pages_node(nid, GFP_ATOMIC, get_order(sz));
 	if (!page)
@@ -708,7 +708,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
 
 void iommu_free_table(struct iommu_table *tbl, const char *node_name)
 {
-	unsigned long bitmap_sz, i;
+	unsigned long bitmap_sz;
 	unsigned int order;
 
 	if (!tbl || !tbl->it_map) {
@@ -718,17 +718,11 @@ void iommu_free_table(struct iommu_table *tbl, const char *node_name)
 	}
 
 	/* verify that table contains no entries */
-	/* it_size is in entries, and we're examining 64 at a time */
-	for (i = 0; i < (tbl->it_size/64); i++) {
-		if (tbl->it_map[i] != 0) {
-			printk(KERN_WARNING "%s: Unexpected TCEs for %s\n",
-				__func__, node_name);
-			break;
-		}
-	}
+	if (!bitmap_empty(tbl->it_map, tbl->it_size))
+		pr_warn("%s: Unexpected TCEs for %s\n", __func__, node_name);
 
 	/* calculate bitmap size in bytes */
-	bitmap_sz = (tbl->it_size + 7) / 8;
+	bitmap_sz = BITS_TO_LONGS(tbl->it_size) * sizeof(unsigned long);
 
 	/* free bitmap */
 	order = get_order(bitmap_sz);
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index 867db1d..a61b133 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -419,7 +419,7 @@ static void kvm_map_magic_page(void *data)
 	in[0] = KVM_MAGIC_PAGE;
 	in[1] = KVM_MAGIC_PAGE;
 
-	kvm_hypercall(in, out, HC_VENDOR_KVM | KVM_HC_PPC_MAP_MAGIC_PAGE);
+	kvm_hypercall(in, out, KVM_HCALL_TOKEN(KVM_HC_PPC_MAP_MAGIC_PAGE));
 
 	*features = out[0];
 }
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index bedd12e..0733b05 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -387,7 +387,7 @@ void __init find_legacy_serial_ports(void)
 			of_node_put(parent);
 			continue;
 		}
-		/* Check for known pciclass, and also check wether we have
+		/* Check for known pciclass, and also check whether we have
 		 * a device with child nodes for ports or not
 		 */
 		if (of_device_is_compatible(np, "pciclass,0700") ||
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index fa9f6c7..e1ec57e 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -218,23 +218,23 @@ static void __init export_crashk_values(struct device_node *node)
 	 * be sure what's in them, so remove them. */
 	prop = of_find_property(node, "linux,crashkernel-base", NULL);
 	if (prop)
-		prom_remove_property(node, prop);
+		of_remove_property(node, prop);
 
 	prop = of_find_property(node, "linux,crashkernel-size", NULL);
 	if (prop)
-		prom_remove_property(node, prop);
+		of_remove_property(node, prop);
 
 	if (crashk_res.start != 0) {
-		prom_add_property(node, &crashk_base_prop);
+		of_add_property(node, &crashk_base_prop);
 		crashk_size = resource_size(&crashk_res);
-		prom_add_property(node, &crashk_size_prop);
+		of_add_property(node, &crashk_size_prop);
 	}
 
 	/*
 	 * memory_limit is required by the kexec-tools to limit the
 	 * crash regions to the actual memory used.
 	 */
-	prom_update_property(node, &memory_limit_prop);
+	of_update_property(node, &memory_limit_prop);
 }
 
 static int __init kexec_setup(void)
@@ -249,11 +249,11 @@ static int __init kexec_setup(void)
 	/* remove any stale properties so ours can be found */
 	prop = of_find_property(node, kernel_end_prop.name, NULL);
 	if (prop)
-		prom_remove_property(node, prop);
+		of_remove_property(node, prop);
 
 	/* information needed by userspace when using default_machine_kexec */
 	kernel_end = __pa(_end);
-	prom_add_property(node, &kernel_end_prop);
+	of_add_property(node, &kernel_end_prop);
 
 	export_crashk_values(node);
 
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
index d7f6090..7206701 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -389,14 +389,14 @@ static int __init export_htab_values(void)
 	/* remove any stale propertys so ours can be found */
 	prop = of_find_property(node, htab_base_prop.name, NULL);
 	if (prop)
-		prom_remove_property(node, prop);
+		of_remove_property(node, prop);
 	prop = of_find_property(node, htab_size_prop.name, NULL);
 	if (prop)
-		prom_remove_property(node, prop);
+		of_remove_property(node, prop);
 
 	htab_base = __pa(htab_address);
-	prom_add_property(node, &htab_base_prop);
-	prom_add_property(node, &htab_size_prop);
+	of_add_property(node, &htab_base_prop);
+	of_add_property(node, &htab_size_prop);
 
 	of_node_put(node);
 	return 0;
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index 2049f2d..9db8ec0 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -82,7 +82,7 @@ static int __devinit of_pci_phb_probe(struct platform_device *dev)
 		return -ENXIO;
 
 	/* Claim resources. This might need some rework as well depending
-	 * wether we are doing probe-only or not, like assigning unassigned
+	 * whether we are doing probe-only or not, like assigning unassigned
 	 * resources etc...
 	 */
 	pcibios_claim_one_bus(phb->bus);
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 7f94f76..abc0d08 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1428,8 +1428,6 @@ void __init pcibios_resource_survey(void)
 		ppc_md.pcibios_fixup();
 }
 
-#ifdef CONFIG_HOTPLUG
-
 /* This is used by the PCI hotplug driver to allocate resource
  * of newly plugged busses. We can try to consolidate with the
  * rest of the code later, for now, keep it as-is as our main
@@ -1488,8 +1486,6 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
 }
 EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
 
-#endif /* CONFIG_HOTPLUG */
-
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
 	if (ppc_md.pcibios_enable_device_hook)
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 4b06ec5..64f526a 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -208,7 +208,7 @@ pci_create_OF_bus_map(void)
 		of_prop->name = "pci-OF-bus-map";
 		of_prop->length = 256;
 		of_prop->value = &of_prop[1];
-		prom_add_property(dn, of_prop);
+		of_add_property(dn, of_prop);
 		of_node_put(dn);
 	}
 }
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 4ff190f..2cbe676 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -74,8 +74,6 @@ static int __init pcibios_init(void)
 
 subsys_initcall(pcibios_init);
 
-#ifdef CONFIG_HOTPLUG
-
 int pcibios_unmap_io_space(struct pci_bus *bus)
 {
 	struct pci_controller *hose;
@@ -124,8 +122,6 @@ int pcibios_unmap_io_space(struct pci_bus *bus)
 }
 EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
 
-#endif /* CONFIG_HOTPLUG */
-
 static int __devinit pcibios_map_phb_io_space(struct pci_controller *hose)
 {
 	struct vm_struct *area;
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 19e4288..78b8766 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -43,6 +43,7 @@
 #include <asm/dcr.h>
 #include <asm/ftrace.h>
 #include <asm/switch_to.h>
+#include <asm/epapr_hcalls.h>
 
 #ifdef CONFIG_PPC32
 extern void transfer_to_handler(void);
@@ -191,3 +192,7 @@ EXPORT_SYMBOL(__arch_hweight64);
 #ifdef CONFIG_PPC_BOOK3S_64
 EXPORT_SYMBOL_GPL(mmu_psize_defs);
 #endif
+
+#ifdef CONFIG_EPAPR_PARAVIRT
+EXPORT_SYMBOL(epapr_hypercall_start);
+#endif
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index ba48233..8143067 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -733,8 +733,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-		unsigned long arg, struct task_struct *p,
-		struct pt_regs *regs)
+		unsigned long arg, struct task_struct *p)
 {
 	struct pt_regs *childregs, *kregs;
 	extern void ret_from_fork(void);
@@ -745,25 +744,25 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	/* Copy registers */
 	sp -= sizeof(struct pt_regs);
 	childregs = (struct pt_regs *) sp;
-	if (!regs) {
-		/* for kernel thread, set `current' and stackptr in new task */
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		struct thread_info *ti = (void *)task_stack_page(p);
 		memset(childregs, 0, sizeof(struct pt_regs));
 		childregs->gpr[1] = sp + sizeof(struct pt_regs);
+		childregs->gpr[14] = usp;	/* function */
 #ifdef CONFIG_PPC64
-		childregs->gpr[14] = *(unsigned long *)usp;
-		childregs->gpr[2] = ((unsigned long *)usp)[1],
 		clear_tsk_thread_flag(p, TIF_32BIT);
-#else
-		childregs->gpr[14] = usp;	/* function */
-		childregs->gpr[2] = (unsigned long) p;
+		childregs->softe = 1;
 #endif
 		childregs->gpr[15] = arg;
 		p->thread.regs = NULL;	/* no user register state */
+		ti->flags |= _TIF_RESTOREALL;
 		f = ret_from_kernel_thread;
 	} else {
+		struct pt_regs *regs = current_pt_regs();
 		CHECK_FULL_REGS(regs);
 		*childregs = *regs;
-		childregs->gpr[1] = usp;
+		if (usp)
+			childregs->gpr[1] = usp;
 		p->thread.regs = childregs;
 		childregs->gpr[3] = 0;  /* Result from fork() */
 		if (clone_flags & CLONE_SETTLS) {
@@ -1027,51 +1026,6 @@ int get_unalign_ctl(struct task_struct *tsk, unsigned long adr)
 	return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr);
 }
 
-#define TRUNC_PTR(x)	((typeof(x))(((unsigned long)(x)) & 0xffffffff))
-
-int sys_clone(unsigned long clone_flags, unsigned long usp,
-	      int __user *parent_tidp, void __user *child_threadptr,
-	      int __user *child_tidp, int p6,
-	      struct pt_regs *regs)
-{
-	CHECK_FULL_REGS(regs);
-	if (usp == 0)
-		usp = regs->gpr[1];	/* stack pointer for child */
-#ifdef CONFIG_PPC64
-	if (is_32bit_task()) {
-		parent_tidp = TRUNC_PTR(parent_tidp);
-		child_tidp = TRUNC_PTR(child_tidp);
-	}
-#endif
- 	return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp);
-}
-
-int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3,
-	     unsigned long p4, unsigned long p5, unsigned long p6,
-	     struct pt_regs *regs)
-{
-	CHECK_FULL_REGS(regs);
-	return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);
-}
-
-int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
-	      unsigned long p4, unsigned long p5, unsigned long p6,
-	      struct pt_regs *regs)
-{
-	CHECK_FULL_REGS(regs);
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1],
-			regs, 0, NULL, NULL);
-}
-
-void __ret_from_kernel_execve(struct pt_regs *normal)
-__noreturn;
-
-void ret_from_kernel_execve(struct pt_regs *normal)
-{
-	set_thread_flag(TIF_RESTOREALL);
-	__ret_from_kernel_execve(normal);
-}
-
 static inline int valid_irq_stack(unsigned long sp, struct task_struct *p,
 				  unsigned long nbytes)
 {
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 37725e8..8b6f7a9 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -32,6 +32,7 @@
 #include <linux/debugfs.h>
 #include <linux/irq.h>
 #include <linux/memblock.h>
+#include <linux/of.h>
 
 #include <asm/prom.h>
 #include <asm/rtas.h>
@@ -49,11 +50,11 @@
 #include <asm/btext.h>
 #include <asm/sections.h>
 #include <asm/machdep.h>
-#include <asm/pSeries_reconfig.h>
 #include <asm/pci-bridge.h>
 #include <asm/kexec.h>
 #include <asm/opal.h>
 #include <asm/fadump.h>
+#include <asm/debug.h>
 
 #include <mm/mmu_decl.h>
 
@@ -802,7 +803,7 @@ static int prom_reconfig_notifier(struct notifier_block *nb,
 	int err;
 
 	switch (action) {
-	case PSERIES_RECONFIG_ADD:
+	case OF_RECONFIG_ATTACH_NODE:
 		err = of_finish_dynamic_node(node);
 		if (err < 0)
 			printk(KERN_ERR "finish_node returned %d\n", err);
@@ -821,7 +822,7 @@ static struct notifier_block prom_reconfig_nb = {
 
 static int __init prom_reconfig_setup(void)
 {
-	return pSeries_reconfig_notifier_register(&prom_reconfig_nb);
+	return of_reconfig_notifier_register(&prom_reconfig_nb);
 }
 __initcall(prom_reconfig_setup);
 #endif
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index cb6c123..779f340 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -671,6 +671,7 @@ static void __init early_cmdline_parse(void)
 #define OV1_PPC_2_04		0x08	/* set if we support PowerPC 2.04 */
 #define OV1_PPC_2_05		0x04	/* set if we support PowerPC 2.05 */
 #define OV1_PPC_2_06		0x02	/* set if we support PowerPC 2.06 */
+#define OV1_PPC_2_07		0x01	/* set if we support PowerPC 2.07 */
 
 /* Option vector 2: Open Firmware options supported */
 #define OV2_REAL_MODE		0x20	/* set if we want OF in real mode */
@@ -707,6 +708,7 @@ static void __init early_cmdline_parse(void)
 #define OV5_PFO_HW_RNG		0x80	/* PFO Random Number Generator */
 #define OV5_PFO_HW_842		0x40	/* PFO Compression Accelerator */
 #define OV5_PFO_HW_ENCR		0x20	/* PFO Encryption Accelerator */
+#define OV5_SUB_PROCESSORS	0x01    /* 1,2,or 4 Sub-Processors supported */
 
 /* Option Vector 6: IBM PAPR hints */
 #define OV6_LINUX		0x02	/* Linux is our OS */
@@ -719,6 +721,8 @@ static unsigned char ibm_architecture_vec[] = {
 	W(0xfffe0000), W(0x003a0000),	/* POWER5/POWER5+ */
 	W(0xffff0000), W(0x003e0000),	/* POWER6 */
 	W(0xffff0000), W(0x003f0000),	/* POWER7 */
+	W(0xffff0000), W(0x004b0000),	/* POWER8 */
+	W(0xffffffff), W(0x0f000004),	/* all 2.07-compliant */
 	W(0xffffffff), W(0x0f000003),	/* all 2.06-compliant */
 	W(0xffffffff), W(0x0f000002),	/* all 2.05-compliant */
 	W(0xfffffffe), W(0x0f000001),	/* all 2.04-compliant and earlier */
@@ -728,7 +732,7 @@ static unsigned char ibm_architecture_vec[] = {
 	3 - 2,				/* length */
 	0,				/* don't ignore, don't halt */
 	OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
-	OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06,
+	OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
 
 	/* option vector 2: Open Firmware options supported */
 	34 - 2,				/* length */
@@ -755,7 +759,7 @@ static unsigned char ibm_architecture_vec[] = {
 	OV4_MIN_ENT_CAP,		/* minimum VP entitled capacity */
 
 	/* option vector 5: PAPR/OF options */
-	18 - 2,				/* length */
+	19 - 2,				/* length */
 	0,				/* don't ignore, don't halt */
 	OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
 	OV5_DONATE_DEDICATE_CPU | OV5_MSI,
@@ -769,13 +773,14 @@ static unsigned char ibm_architecture_vec[] = {
 	 * must match by the macro below. Update the definition if
 	 * the structure layout changes.
 	 */
-#define IBM_ARCH_VEC_NRCORES_OFFSET	101
+#define IBM_ARCH_VEC_NRCORES_OFFSET	117
 	W(NR_CPUS),			/* number of cores supported */
 	0,
 	0,
 	0,
 	0,
 	OV5_PFO_HW_RNG | OV5_PFO_HW_ENCR | OV5_PFO_HW_842,
+	OV5_SUB_PROCESSORS,
 	/* option vector 6: IBM PAPR hints */
 	4 - 2,				/* length */
 	0,
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 79d8e56..c497000 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -952,6 +952,10 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
 		arch_bp_generic_fields(data &
 					(DABR_DATA_WRITE | DABR_DATA_READ),
 							&attr.bp_type);
+
+		/* Enable breakpoint */
+		attr.disabled = false;
+
 		ret =  modify_user_hw_breakpoint(bp, &attr);
 		if (ret) {
 			ptrace_put_breakpoints(task);
@@ -1037,7 +1041,7 @@ void ptrace_disable(struct task_struct *child)
 }
 
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
-static long set_intruction_bp(struct task_struct *child,
+static long set_instruction_bp(struct task_struct *child,
 			      struct ppc_hw_breakpoint *bp_info)
 {
 	int slot;
@@ -1338,6 +1342,12 @@ static int set_dac_range(struct task_struct *child,
 static long ppc_set_hwdebug(struct task_struct *child,
 		     struct ppc_hw_breakpoint *bp_info)
 {
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+	int len = 0;
+	struct thread_struct *thread = &(child->thread);
+	struct perf_event *bp;
+	struct perf_event_attr attr;
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
 #ifndef CONFIG_PPC_ADV_DEBUG_REGS
 	unsigned long dabr;
 #endif
@@ -1365,7 +1375,7 @@ static long ppc_set_hwdebug(struct task_struct *child,
 		if ((bp_info->trigger_type != PPC_BREAKPOINT_TRIGGER_EXECUTE) ||
 		    (bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE))
 			return -EINVAL;
-		return set_intruction_bp(child, bp_info);
+		return set_instruction_bp(child, bp_info);
 	}
 	if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT)
 		return set_dac(child, bp_info);
@@ -1381,13 +1391,9 @@ static long ppc_set_hwdebug(struct task_struct *child,
 	 */
 	if ((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0 ||
 	    (bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0 ||
-	    bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT ||
 	    bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE)
 		return -EINVAL;
 
-	if (child->thread.dabr)
-		return -ENOSPC;
-
 	if ((unsigned long)bp_info->addr >= TASK_SIZE)
 		return -EIO;
 
@@ -1397,6 +1403,50 @@ static long ppc_set_hwdebug(struct task_struct *child,
 		dabr |= DABR_DATA_READ;
 	if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
 		dabr |= DABR_DATA_WRITE;
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+	if (ptrace_get_breakpoints(child) < 0)
+		return -ESRCH;
+
+	/*
+	 * Check if the request is for 'range' breakpoints. We can
+	 * support it if range < 8 bytes.
+	 */
+	if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE) {
+		len = bp_info->addr2 - bp_info->addr;
+	} else if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) {
+		ptrace_put_breakpoints(child);
+		return -EINVAL;
+	}
+	bp = thread->ptrace_bps[0];
+	if (bp) {
+		ptrace_put_breakpoints(child);
+		return -ENOSPC;
+	}
+
+	/* Create a new breakpoint request if one doesn't exist already */
+	hw_breakpoint_init(&attr);
+	attr.bp_addr = (unsigned long)bp_info->addr & ~HW_BREAKPOINT_ALIGN;
+	attr.bp_len = len;
+	arch_bp_generic_fields(dabr & (DABR_DATA_WRITE | DABR_DATA_READ),
+								&attr.bp_type);
+
+	thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr,
+					       ptrace_triggered, NULL, child);
+	if (IS_ERR(bp)) {
+		thread->ptrace_bps[0] = NULL;
+		ptrace_put_breakpoints(child);
+		return PTR_ERR(bp);
+	}
+
+	ptrace_put_breakpoints(child);
+	return 1;
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
+
+	if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT)
+		return -EINVAL;
+
+	if (child->thread.dabr)
+		return -ENOSPC;
 
 	child->thread.dabr = dabr;
 	child->thread.dabrx = DABRX_ALL;
@@ -1405,8 +1455,13 @@ static long ppc_set_hwdebug(struct task_struct *child,
 #endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */
 }
 
-static long ppc_del_hwdebug(struct task_struct *child, long addr, long data)
+static long ppc_del_hwdebug(struct task_struct *child, long data)
 {
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+	int ret = 0;
+	struct thread_struct *thread = &(child->thread);
+	struct perf_event *bp;
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
 	int rc;
 
@@ -1426,10 +1481,25 @@ static long ppc_del_hwdebug(struct task_struct *child, long addr, long data)
 #else
 	if (data != 1)
 		return -EINVAL;
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+	if (ptrace_get_breakpoints(child) < 0)
+		return -ESRCH;
+
+	bp = thread->ptrace_bps[0];
+	if (bp) {
+		unregister_hw_breakpoint(bp);
+		thread->ptrace_bps[0] = NULL;
+	} else
+		ret = -ENOENT;
+	ptrace_put_breakpoints(child);
+	return ret;
+#else /* CONFIG_HAVE_HW_BREAKPOINT */
 	if (child->thread.dabr == 0)
 		return -ENOENT;
 
 	child->thread.dabr = 0;
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
 
 	return 0;
 #endif
@@ -1536,7 +1606,11 @@ long arch_ptrace(struct task_struct *child, long request,
 		dbginfo.data_bp_alignment = 4;
 #endif
 		dbginfo.sizeof_condition = 0;
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+		dbginfo.features = PPC_DEBUG_FEATURE_DATA_BP_RANGE;
+#else
 		dbginfo.features = 0;
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
 #endif /* CONFIG_PPC_ADV_DEBUG_REGS */
 
 		if (!access_ok(VERIFY_WRITE, datavp,
@@ -1563,7 +1637,7 @@ long arch_ptrace(struct task_struct *child, long request,
 	}
 
 	case PPC_PTRACE_DELHWDEBUG: {
-		ret = ppc_del_hwdebug(child, addr, data);
+		ret = ppc_del_hwdebug(child, data);
 		break;
 	}
 
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index fcec382..1fd6e7b 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -42,7 +42,6 @@
 #include <asm/time.h>
 #include <asm/mmu.h>
 #include <asm/topology.h>
-#include <asm/pSeries_reconfig.h>
 
 struct rtas_t rtas = {
 	.lock = __ARCH_SPIN_LOCK_UNLOCKED
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index 20b0120..8329190 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -650,10 +650,8 @@ static int initialize_flash_pde_data(const char *rtas_call_name,
 	int token;
 
 	dp->data = kzalloc(buf_size, GFP_KERNEL);
-	if (dp->data == NULL) {
-		remove_flash_pde(dp);
+	if (dp->data == NULL)
 		return -ENOMEM;
-	}
 
 	/*
 	 * This code assumes that the status int is the first member of the
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index efb6a41..6da881b 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -601,6 +601,11 @@ void __init setup_arch(char **cmdline_p)
 
 	kvm_linear_init();
 
+	/* Interrupt code needs to be 64K-aligned */
+	if ((unsigned long)_stext & 0xffff)
+		panic("Kernelbase not 64K-aligned (0x%lx)!\n",
+		      (unsigned long)_stext);
+
 	ppc64_boot_msg(0x15, "Setup Done");
 }
 
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index d183f87..1ca045d 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -83,7 +83,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
 	 * the context). This is very important because we must ensure we
 	 * don't lose the VRSAVE content that may have been set prior to
 	 * the process doing its first vector operation
-	 * Userland shall check AT_HWCAP to know wether it can rely on the
+	 * Userland shall check AT_HWCAP to know whether it can rely on the
 	 * v_regs pointer or not
 	 */
 #ifdef CONFIG_ALTIVEC
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 2b952b5..e5b133e 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -427,6 +427,45 @@ int generic_check_cpu_restart(unsigned int cpu)
 {
 	return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE;
 }
+
+static atomic_t secondary_inhibit_count;
+
+/*
+ * Don't allow secondary CPU threads to come online
+ */
+void inhibit_secondary_onlining(void)
+{
+	/*
+	 * This makes secondary_inhibit_count stable during cpu
+	 * online/offline operations.
+	 */
+	get_online_cpus();
+
+	atomic_inc(&secondary_inhibit_count);
+	put_online_cpus();
+}
+EXPORT_SYMBOL_GPL(inhibit_secondary_onlining);
+
+/*
+ * Allow secondary CPU threads to come online again
+ */
+void uninhibit_secondary_onlining(void)
+{
+	get_online_cpus();
+	atomic_dec(&secondary_inhibit_count);
+	put_online_cpus();
+}
+EXPORT_SYMBOL_GPL(uninhibit_secondary_onlining);
+
+static int secondaries_inhibited(void)
+{
+	return atomic_read(&secondary_inhibit_count);
+}
+
+#else /* HOTPLUG_CPU */
+
+#define secondaries_inhibited()		0
+
 #endif
 
 static void cpu_idle_thread_init(unsigned int cpu, struct task_struct *idle)
@@ -445,6 +484,13 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
 {
 	int rc, c;
 
+	/*
+	 * Don't allow secondary threads to come online if inhibited
+	 */
+	if (threads_per_core > 1 && secondaries_inhibited() &&
+	    cpu % threads_per_core != 0)
+		return -EBUSY;
+
 	if (smp_ops == NULL ||
 	    (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)))
 		return -EINVAL;
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index 9c2ed90..8a93778 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -175,19 +175,10 @@ asmlinkage long compat_sys_prctl(u32 option, u32 arg2, u32 arg3, u32 arg4, u32 a
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
  * and the register representation of a signed int (msr in 64-bit mode) is performed.
  */
-asmlinkage long compat_sys_sched_rr_get_interval(u32 pid, struct compat_timespec __user *interval)
-{
-	struct timespec t;
-	int ret;
-	mm_segment_t old_fs = get_fs ();
-
-	/* The __user pointer cast is valid because of the set_fs() */
-	set_fs (KERNEL_DS);
-	ret = sys_sched_rr_get_interval((int)pid, (struct timespec __user *) &t);
-	set_fs (old_fs);
-	if (put_compat_timespec(&t, interval))
-		return -EFAULT;
-	return ret;
+asmlinkage long compat_sys_sched_rr_get_interval_wrapper(u32 pid,
+							 struct compat_timespec __user *interval)
+{
+	return compat_sys_sched_rr_get_interval((int)pid, interval);
 }
 
 /* Note: it is necessary to treat mode as an unsigned int,
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index cf357a0..3ce1f86 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -607,7 +607,7 @@ static void register_nodes(void)
 
 int sysfs_add_device_to_node(struct device *dev, int nid)
 {
-	struct node *node = &node_devices[nid];
+	struct node *node = node_devices[nid];
 	return sysfs_create_link(&node->dev.kobj, &dev->kobj,
 			kobject_name(&dev->kobj));
 }
@@ -615,7 +615,7 @@ EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
 
 void sysfs_remove_device_from_node(struct device *dev, int nid)
 {
-	struct node *node = &node_devices[nid];
+	struct node *node = node_devices[nid];
 	sysfs_remove_link(&node->dev.kobj, kobject_name(&dev->kobj));
 }
 EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node);
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index ce4cb77..0db456f 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -336,7 +336,7 @@ static u64 vtime_delta(struct task_struct *tsk,
 	return delta;
 }
 
-void vtime_account_system(struct task_struct *tsk)
+void __vtime_account_system(struct task_struct *tsk)
 {
 	u64 delta, sys_scaled, stolen;
 
@@ -346,7 +346,7 @@ void vtime_account_system(struct task_struct *tsk)
 		account_steal_time(stolen);
 }
 
-void vtime_account_idle(struct task_struct *tsk)
+void __vtime_account_idle(struct task_struct *tsk)
 {
 	u64 delta, sys_scaled, stolen;
 
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index c39c1ca..f974849 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -122,29 +122,6 @@ int udbg_write(const char *s, int n)
 	return n - remain;
 }
 
-int udbg_read(char *buf, int buflen)
-{
-	char *p = buf;
-	int i, c;
-
-	if (!udbg_getc)
-		return 0;
-
-	for (i = 0; i < buflen; ++i) {
-		do {
-			c = udbg_getc();
-			if (c == -1 && i == 0)
-				return -1;
-
-		} while (c == 0x11 || c == 0x13);
-		if (c == 0 || c == -1)
-			break;
-		*p++ = c;
-	}
-
-	return i;
-}
-
 #define UDBG_BUFSIZE 256
 void udbg_printf(const char *fmt, ...)
 {
diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c
index 50e7dbc..3d7fd21 100644
--- a/arch/powerpc/kvm/44x.c
+++ b/arch/powerpc/kvm/44x.c
@@ -83,6 +83,7 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
 		vcpu_44x->shadow_refs[i].gtlb_index = -1;
 
 	vcpu->arch.cpu_type = KVM_CPU_440;
+	vcpu->arch.pvr = mfspr(SPRN_PVR);
 
 	return 0;
 }
diff --git a/arch/powerpc/kvm/44x_emulate.c b/arch/powerpc/kvm/44x_emulate.c
index c8c6157..35ec0a8 100644
--- a/arch/powerpc/kvm/44x_emulate.c
+++ b/arch/powerpc/kvm/44x_emulate.c
@@ -27,12 +27,70 @@
 #include "booke.h"
 #include "44x_tlb.h"
 
+#define XOP_MFDCRX  259
 #define XOP_MFDCR   323
+#define XOP_MTDCRX  387
 #define XOP_MTDCR   451
 #define XOP_TLBSX   914
 #define XOP_ICCCI   966
 #define XOP_TLBWE   978
 
+static int emulate_mtdcr(struct kvm_vcpu *vcpu, int rs, int dcrn)
+{
+	/* emulate some access in kernel */
+	switch (dcrn) {
+	case DCRN_CPR0_CONFIG_ADDR:
+		vcpu->arch.cpr0_cfgaddr = kvmppc_get_gpr(vcpu, rs);
+		return EMULATE_DONE;
+	default:
+		vcpu->run->dcr.dcrn = dcrn;
+		vcpu->run->dcr.data = kvmppc_get_gpr(vcpu, rs);
+		vcpu->run->dcr.is_write = 1;
+		vcpu->arch.dcr_is_write = 1;
+		vcpu->arch.dcr_needed = 1;
+		kvmppc_account_exit(vcpu, DCR_EXITS);
+		return EMULATE_DO_DCR;
+	}
+}
+
+static int emulate_mfdcr(struct kvm_vcpu *vcpu, int rt, int dcrn)
+{
+	/* The guest may access CPR0 registers to determine the timebase
+	 * frequency, and it must know the real host frequency because it
+	 * can directly access the timebase registers.
+	 *
+	 * It would be possible to emulate those accesses in userspace,
+	 * but userspace can really only figure out the end frequency.
+	 * We could decompose that into the factors that compute it, but
+	 * that's tricky math, and it's easier to just report the real
+	 * CPR0 values.
+	 */
+	switch (dcrn) {
+	case DCRN_CPR0_CONFIG_ADDR:
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr);
+		break;
+	case DCRN_CPR0_CONFIG_DATA:
+		local_irq_disable();
+		mtdcr(DCRN_CPR0_CONFIG_ADDR,
+			  vcpu->arch.cpr0_cfgaddr);
+		kvmppc_set_gpr(vcpu, rt,
+			       mfdcr(DCRN_CPR0_CONFIG_DATA));
+		local_irq_enable();
+		break;
+	default:
+		vcpu->run->dcr.dcrn = dcrn;
+		vcpu->run->dcr.data =  0;
+		vcpu->run->dcr.is_write = 0;
+		vcpu->arch.dcr_is_write = 0;
+		vcpu->arch.io_gpr = rt;
+		vcpu->arch.dcr_needed = 1;
+		kvmppc_account_exit(vcpu, DCR_EXITS);
+		return EMULATE_DO_DCR;
+	}
+
+	return EMULATE_DONE;
+}
+
 int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                            unsigned int inst, int *advance)
 {
@@ -50,55 +108,21 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
 		switch (get_xop(inst)) {
 
 		case XOP_MFDCR:
-			/* The guest may access CPR0 registers to determine the timebase
-			 * frequency, and it must know the real host frequency because it
-			 * can directly access the timebase registers.
-			 *
-			 * It would be possible to emulate those accesses in userspace,
-			 * but userspace can really only figure out the end frequency.
-			 * We could decompose that into the factors that compute it, but
-			 * that's tricky math, and it's easier to just report the real
-			 * CPR0 values.
-			 */
-			switch (dcrn) {
-			case DCRN_CPR0_CONFIG_ADDR:
-				kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr);
-				break;
-			case DCRN_CPR0_CONFIG_DATA:
-				local_irq_disable();
-				mtdcr(DCRN_CPR0_CONFIG_ADDR,
-					  vcpu->arch.cpr0_cfgaddr);
-				kvmppc_set_gpr(vcpu, rt,
-					       mfdcr(DCRN_CPR0_CONFIG_DATA));
-				local_irq_enable();
-				break;
-			default:
-				run->dcr.dcrn = dcrn;
-				run->dcr.data =  0;
-				run->dcr.is_write = 0;
-				vcpu->arch.io_gpr = rt;
-				vcpu->arch.dcr_needed = 1;
-				kvmppc_account_exit(vcpu, DCR_EXITS);
-				emulated = EMULATE_DO_DCR;
-			}
+			emulated = emulate_mfdcr(vcpu, rt, dcrn);
+			break;
 
+		case XOP_MFDCRX:
+			emulated = emulate_mfdcr(vcpu, rt,
+					kvmppc_get_gpr(vcpu, ra));
 			break;
 
 		case XOP_MTDCR:
-			/* emulate some access in kernel */
-			switch (dcrn) {
-			case DCRN_CPR0_CONFIG_ADDR:
-				vcpu->arch.cpr0_cfgaddr = kvmppc_get_gpr(vcpu, rs);
-				break;
-			default:
-				run->dcr.dcrn = dcrn;
-				run->dcr.data = kvmppc_get_gpr(vcpu, rs);
-				run->dcr.is_write = 1;
-				vcpu->arch.dcr_needed = 1;
-				kvmppc_account_exit(vcpu, DCR_EXITS);
-				emulated = EMULATE_DO_DCR;
-			}
+			emulated = emulate_mtdcr(vcpu, rs, dcrn);
+			break;
 
+		case XOP_MTDCRX:
+			emulated = emulate_mtdcr(vcpu, rs,
+					kvmppc_get_gpr(vcpu, ra));
 			break;
 
 		case XOP_TLBWE:
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index f4dacb9..4730c95 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -20,6 +20,7 @@ config KVM
 	bool
 	select PREEMPT_NOTIFIERS
 	select ANON_INODES
+	select HAVE_KVM_EVENTFD
 
 config KVM_BOOK3S_HANDLER
 	bool
@@ -36,6 +37,7 @@ config KVM_BOOK3S_64_HANDLER
 config KVM_BOOK3S_PR
 	bool
 	select KVM_MMIO
+	select MMU_NOTIFIER
 
 config KVM_BOOK3S_32
 	tristate "KVM support for PowerPC book3s_32 processors"
@@ -123,6 +125,7 @@ config KVM_E500V2
 	depends on EXPERIMENTAL && E500 && !PPC_E500MC
 	select KVM
 	select KVM_MMIO
+	select MMU_NOTIFIER
 	---help---
 	  Support running unmodified E500 guest kernels in virtual machines on
 	  E500v2 host processors.
@@ -138,6 +141,7 @@ config KVM_E500MC
 	select KVM
 	select KVM_MMIO
 	select KVM_BOOKE_HV
+	select MMU_NOTIFIER
 	---help---
 	  Support running unmodified E500MC/E5500 (32-bit) guest kernels in
 	  virtual machines on E500MC/E5500 host processors.
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index c2a0863..1e473d4 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -6,7 +6,8 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
 ccflags-y := -Ivirt/kvm -Iarch/powerpc/kvm
 
-common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
+common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o \
+						eventfd.o)
 
 CFLAGS_44x_tlb.o  := -I.
 CFLAGS_e500_tlb.o := -I.
@@ -72,10 +73,12 @@ kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \
 	book3s_hv_rmhandlers.o \
 	book3s_hv_rm_mmu.o \
 	book3s_64_vio_hv.o \
+	book3s_hv_ras.o \
 	book3s_hv_builtin.o
 
 kvm-book3s_64-module-objs := \
 	../../../virt/kvm/kvm_main.o \
+	../../../virt/kvm/eventfd.o \
 	powerpc.o \
 	emulate.o \
 	book3s.o \
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 3f2a836..a4b6452 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -411,6 +411,15 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 	return 0;
 }
 
+int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu)
+{
+	return 0;
+}
+
+void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu)
+{
+}
+
 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
 	int i;
@@ -476,6 +485,122 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 	return -ENOTSUPP;
 }
 
+int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+	int r;
+	union kvmppc_one_reg val;
+	int size;
+	long int i;
+
+	size = one_reg_size(reg->id);
+	if (size > sizeof(val))
+		return -EINVAL;
+
+	r = kvmppc_get_one_reg(vcpu, reg->id, &val);
+
+	if (r == -EINVAL) {
+		r = 0;
+		switch (reg->id) {
+		case KVM_REG_PPC_DAR:
+			val = get_reg_val(reg->id, vcpu->arch.shared->dar);
+			break;
+		case KVM_REG_PPC_DSISR:
+			val = get_reg_val(reg->id, vcpu->arch.shared->dsisr);
+			break;
+		case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
+			i = reg->id - KVM_REG_PPC_FPR0;
+			val = get_reg_val(reg->id, vcpu->arch.fpr[i]);
+			break;
+		case KVM_REG_PPC_FPSCR:
+			val = get_reg_val(reg->id, vcpu->arch.fpscr);
+			break;
+#ifdef CONFIG_ALTIVEC
+		case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
+			if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+				r = -ENXIO;
+				break;
+			}
+			val.vval = vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0];
+			break;
+		case KVM_REG_PPC_VSCR:
+			if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+				r = -ENXIO;
+				break;
+			}
+			val = get_reg_val(reg->id, vcpu->arch.vscr.u[3]);
+			break;
+#endif /* CONFIG_ALTIVEC */
+		default:
+			r = -EINVAL;
+			break;
+		}
+	}
+	if (r)
+		return r;
+
+	if (copy_to_user((char __user *)(unsigned long)reg->addr, &val, size))
+		r = -EFAULT;
+
+	return r;
+}
+
+int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+	int r;
+	union kvmppc_one_reg val;
+	int size;
+	long int i;
+
+	size = one_reg_size(reg->id);
+	if (size > sizeof(val))
+		return -EINVAL;
+
+	if (copy_from_user(&val, (char __user *)(unsigned long)reg->addr, size))
+		return -EFAULT;
+
+	r = kvmppc_set_one_reg(vcpu, reg->id, &val);
+
+	if (r == -EINVAL) {
+		r = 0;
+		switch (reg->id) {
+		case KVM_REG_PPC_DAR:
+			vcpu->arch.shared->dar = set_reg_val(reg->id, val);
+			break;
+		case KVM_REG_PPC_DSISR:
+			vcpu->arch.shared->dsisr = set_reg_val(reg->id, val);
+			break;
+		case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
+			i = reg->id - KVM_REG_PPC_FPR0;
+			vcpu->arch.fpr[i] = set_reg_val(reg->id, val);
+			break;
+		case KVM_REG_PPC_FPSCR:
+			vcpu->arch.fpscr = set_reg_val(reg->id, val);
+			break;
+#ifdef CONFIG_ALTIVEC
+		case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
+			if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+				r = -ENXIO;
+				break;
+			}
+			vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0] = val.vval;
+			break;
+		case KVM_REG_PPC_VSCR:
+			if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+				r = -ENXIO;
+				break;
+			}
+			vcpu->arch.vscr.u[3] = set_reg_val(reg->id, val);
+			break;
+#endif /* CONFIG_ALTIVEC */
+		default:
+			r = -EINVAL;
+			break;
+		}
+	}
+
+	return r;
+}
+
 int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
                                   struct kvm_translation *tr)
 {
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c
index b0f625a..00e619b 100644
--- a/arch/powerpc/kvm/book3s_32_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_32_mmu_host.c
@@ -155,7 +155,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
 
 	/* Get host physical address for gpa */
 	hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT);
-	if (is_error_pfn(hpaddr)) {
+	if (is_error_noslot_pfn(hpaddr)) {
 		printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n",
 				 orig_pte->eaddr);
 		r = -EINVAL;
@@ -254,6 +254,7 @@ next_pteg:
 
 	kvmppc_mmu_hpte_cache_map(vcpu, pte);
 
+	kvm_release_pfn_clean(hpaddr >> PAGE_SHIFT);
 out:
 	return r;
 }
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c
index 4d72f9e..ead58e3 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_host.c
@@ -93,7 +93,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
 
 	/* Get host physical address for gpa */
 	hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT);
-	if (is_error_pfn(hpaddr)) {
+	if (is_error_noslot_pfn(hpaddr)) {
 		printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", orig_pte->eaddr);
 		r = -EINVAL;
 		goto out;
@@ -171,6 +171,7 @@ map_again:
 
 		kvmppc_mmu_hpte_cache_map(vcpu, pte);
 	}
+	kvm_release_pfn_clean(hpaddr >> PAGE_SHIFT);
 
 out:
 	return r;
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index d95d113..8cc18ab 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -24,6 +24,9 @@
 #include <linux/slab.h>
 #include <linux/hugetlb.h>
 #include <linux/vmalloc.h>
+#include <linux/srcu.h>
+#include <linux/anon_inodes.h>
+#include <linux/file.h>
 
 #include <asm/tlbflush.h>
 #include <asm/kvm_ppc.h>
@@ -40,6 +43,11 @@
 /* Power architecture requires HPT is at least 256kB */
 #define PPC_MIN_HPT_ORDER	18
 
+static long kvmppc_virtmode_do_h_enter(struct kvm *kvm, unsigned long flags,
+				long pte_index, unsigned long pteh,
+				unsigned long ptel, unsigned long *pte_idx_ret);
+static void kvmppc_rmap_reset(struct kvm *kvm);
+
 long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp)
 {
 	unsigned long hpt;
@@ -137,10 +145,11 @@ long kvmppc_alloc_reset_hpt(struct kvm *kvm, u32 *htab_orderp)
 		/* Set the entire HPT to 0, i.e. invalid HPTEs */
 		memset((void *)kvm->arch.hpt_virt, 0, 1ul << order);
 		/*
-		 * Set the whole last_vcpu array to an invalid vcpu number.
-		 * This ensures that each vcpu will flush its TLB on next entry.
+		 * Reset all the reverse-mapping chains for all memslots
 		 */
-		memset(kvm->arch.last_vcpu, 0xff, sizeof(kvm->arch.last_vcpu));
+		kvmppc_rmap_reset(kvm);
+		/* Ensure that each vcpu will flush its TLB on next entry. */
+		cpumask_setall(&kvm->arch.need_tlb_flush);
 		*htab_orderp = order;
 		err = 0;
 	} else {
@@ -184,6 +193,7 @@ void kvmppc_map_vrma(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
 	unsigned long addr, hash;
 	unsigned long psize;
 	unsigned long hp0, hp1;
+	unsigned long idx_ret;
 	long ret;
 	struct kvm *kvm = vcpu->kvm;
 
@@ -215,7 +225,8 @@ void kvmppc_map_vrma(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
 		hash = (hash << 3) + 7;
 		hp_v = hp0 | ((addr >> 16) & ~0x7fUL);
 		hp_r = hp1 | addr;
-		ret = kvmppc_virtmode_h_enter(vcpu, H_EXACT, hash, hp_v, hp_r);
+		ret = kvmppc_virtmode_do_h_enter(kvm, H_EXACT, hash, hp_v, hp_r,
+						 &idx_ret);
 		if (ret != H_SUCCESS) {
 			pr_err("KVM: map_vrma at %lx failed, ret=%ld\n",
 			       addr, ret);
@@ -260,7 +271,7 @@ static void kvmppc_mmu_book3s_64_hv_reset_msr(struct kvm_vcpu *vcpu)
 
 /*
  * This is called to get a reference to a guest page if there isn't
- * one already in the kvm->arch.slot_phys[][] arrays.
+ * one already in the memslot->arch.slot_phys[] array.
  */
 static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
 				  struct kvm_memory_slot *memslot,
@@ -275,7 +286,7 @@ static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
 	struct vm_area_struct *vma;
 	unsigned long pfn, i, npages;
 
-	physp = kvm->arch.slot_phys[memslot->id];
+	physp = memslot->arch.slot_phys;
 	if (!physp)
 		return -EINVAL;
 	if (physp[gfn - memslot->base_gfn])
@@ -353,15 +364,10 @@ static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
 	return err;
 }
 
-/*
- * We come here on a H_ENTER call from the guest when we are not
- * using mmu notifiers and we don't have the requested page pinned
- * already.
- */
-long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
-			long pte_index, unsigned long pteh, unsigned long ptel)
+long kvmppc_virtmode_do_h_enter(struct kvm *kvm, unsigned long flags,
+				long pte_index, unsigned long pteh,
+				unsigned long ptel, unsigned long *pte_idx_ret)
 {
-	struct kvm *kvm = vcpu->kvm;
 	unsigned long psize, gpa, gfn;
 	struct kvm_memory_slot *memslot;
 	long ret;
@@ -389,8 +395,8 @@ long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
  do_insert:
 	/* Protect linux PTE lookup from page table destruction */
 	rcu_read_lock_sched();	/* this disables preemption too */
-	vcpu->arch.pgdir = current->mm->pgd;
-	ret = kvmppc_h_enter(vcpu, flags, pte_index, pteh, ptel);
+	ret = kvmppc_do_h_enter(kvm, flags, pte_index, pteh, ptel,
+				current->mm->pgd, false, pte_idx_ret);
 	rcu_read_unlock_sched();
 	if (ret == H_TOO_HARD) {
 		/* this can't happen */
@@ -401,6 +407,19 @@ long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 
 }
 
+/*
+ * We come here on a H_ENTER call from the guest when we are not
+ * using mmu notifiers and we don't have the requested page pinned
+ * already.
+ */
+long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
+			     long pte_index, unsigned long pteh,
+			     unsigned long ptel)
+{
+	return kvmppc_virtmode_do_h_enter(vcpu->kvm, flags, pte_index,
+					  pteh, ptel, &vcpu->arch.gpr[4]);
+}
+
 static struct kvmppc_slb *kvmppc_mmu_book3s_hv_find_slbe(struct kvm_vcpu *vcpu,
 							 gva_t eaddr)
 {
@@ -570,7 +589,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	struct kvm *kvm = vcpu->kvm;
 	unsigned long *hptep, hpte[3], r;
 	unsigned long mmu_seq, psize, pte_size;
-	unsigned long gfn, hva, pfn;
+	unsigned long gpa, gfn, hva, pfn;
 	struct kvm_memory_slot *memslot;
 	unsigned long *rmap;
 	struct revmap_entry *rev;
@@ -608,15 +627,14 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
 	/* Translate the logical address and get the page */
 	psize = hpte_page_size(hpte[0], r);
-	gfn = hpte_rpn(r, psize);
+	gpa = (r & HPTE_R_RPN & ~(psize - 1)) | (ea & (psize - 1));
+	gfn = gpa >> PAGE_SHIFT;
 	memslot = gfn_to_memslot(kvm, gfn);
 
 	/* No memslot means it's an emulated MMIO region */
-	if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) {
-		unsigned long gpa = (gfn << PAGE_SHIFT) | (ea & (psize - 1));
+	if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
 		return kvmppc_hv_emulate_mmio(run, vcpu, gpa, ea,
 					      dsisr & DSISR_ISSTORE);
-	}
 
 	if (!kvm->arch.using_mmu_notifiers)
 		return -EFAULT;		/* should never get here */
@@ -710,7 +728,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
 	/* Check if we might have been invalidated; let the guest retry if so */
 	ret = RESUME_GUEST;
-	if (mmu_notifier_retry(vcpu, mmu_seq)) {
+	if (mmu_notifier_retry(vcpu->kvm, mmu_seq)) {
 		unlock_rmap(rmap);
 		goto out_unlock;
 	}
@@ -756,6 +774,25 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	goto out_put;
 }
 
+static void kvmppc_rmap_reset(struct kvm *kvm)
+{
+	struct kvm_memslots *slots;
+	struct kvm_memory_slot *memslot;
+	int srcu_idx;
+
+	srcu_idx = srcu_read_lock(&kvm->srcu);
+	slots = kvm->memslots;
+	kvm_for_each_memslot(memslot, slots) {
+		/*
+		 * This assumes it is acceptable to lose reference and
+		 * change bits across a reset.
+		 */
+		memset(memslot->arch.rmap, 0,
+		       memslot->npages * sizeof(*memslot->arch.rmap));
+	}
+	srcu_read_unlock(&kvm->srcu, srcu_idx);
+}
+
 static int kvm_handle_hva_range(struct kvm *kvm,
 				unsigned long start,
 				unsigned long end,
@@ -850,7 +887,8 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
 		psize = hpte_page_size(hptep[0], ptel);
 		if ((hptep[0] & HPTE_V_VALID) &&
 		    hpte_rpn(ptel, psize) == gfn) {
-			hptep[0] |= HPTE_V_ABSENT;
+			if (kvm->arch.using_mmu_notifiers)
+				hptep[0] |= HPTE_V_ABSENT;
 			kvmppc_invalidate_hpte(kvm, hptep, i);
 			/* Harvest R and C */
 			rcbits = hptep[1] & (HPTE_R_R | HPTE_R_C);
@@ -877,6 +915,28 @@ int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
 	return 0;
 }
 
+void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot)
+{
+	unsigned long *rmapp;
+	unsigned long gfn;
+	unsigned long n;
+
+	rmapp = memslot->arch.rmap;
+	gfn = memslot->base_gfn;
+	for (n = memslot->npages; n; --n) {
+		/*
+		 * Testing the present bit without locking is OK because
+		 * the memslot has been marked invalid already, and hence
+		 * no new HPTEs referencing this page can be created,
+		 * thus the present bit can't go from 0 to 1.
+		 */
+		if (*rmapp & KVMPPC_RMAP_PRESENT)
+			kvm_unmap_rmapp(kvm, rmapp, gfn);
+		++rmapp;
+		++gfn;
+	}
+}
+
 static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
 			 unsigned long gfn)
 {
@@ -1030,16 +1090,16 @@ static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long *rmapp)
 	return ret;
 }
 
-long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
+long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot,
+			     unsigned long *map)
 {
 	unsigned long i;
-	unsigned long *rmapp, *map;
+	unsigned long *rmapp;
 
 	preempt_disable();
 	rmapp = memslot->arch.rmap;
-	map = memslot->dirty_bitmap;
 	for (i = 0; i < memslot->npages; ++i) {
-		if (kvm_test_clear_dirty(kvm, rmapp))
+		if (kvm_test_clear_dirty(kvm, rmapp) && map)
 			__set_bit_le(i, map);
 		++rmapp;
 	}
@@ -1057,20 +1117,22 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
 	unsigned long hva, psize, offset;
 	unsigned long pa;
 	unsigned long *physp;
+	int srcu_idx;
 
+	srcu_idx = srcu_read_lock(&kvm->srcu);
 	memslot = gfn_to_memslot(kvm, gfn);
 	if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
-		return NULL;
+		goto err;
 	if (!kvm->arch.using_mmu_notifiers) {
-		physp = kvm->arch.slot_phys[memslot->id];
+		physp = memslot->arch.slot_phys;
 		if (!physp)
-			return NULL;
+			goto err;
 		physp += gfn - memslot->base_gfn;
 		pa = *physp;
 		if (!pa) {
 			if (kvmppc_get_guest_page(kvm, gfn, memslot,
 						  PAGE_SIZE) < 0)
-				return NULL;
+				goto err;
 			pa = *physp;
 		}
 		page = pfn_to_page(pa >> PAGE_SHIFT);
@@ -1079,9 +1141,11 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
 		hva = gfn_to_hva_memslot(memslot, gfn);
 		npages = get_user_pages_fast(hva, 1, 1, pages);
 		if (npages < 1)
-			return NULL;
+			goto err;
 		page = pages[0];
 	}
+	srcu_read_unlock(&kvm->srcu, srcu_idx);
+
 	psize = PAGE_SIZE;
 	if (PageHuge(page)) {
 		page = compound_head(page);
@@ -1091,6 +1155,10 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
 	if (nb_ret)
 		*nb_ret = psize - offset;
 	return page_address(page) + offset;
+
+ err:
+	srcu_read_unlock(&kvm->srcu, srcu_idx);
+	return NULL;
 }
 
 void kvmppc_unpin_guest_page(struct kvm *kvm, void *va)
@@ -1100,6 +1168,348 @@ void kvmppc_unpin_guest_page(struct kvm *kvm, void *va)
 	put_page(page);
 }
 
+/*
+ * Functions for reading and writing the hash table via reads and
+ * writes on a file descriptor.
+ *
+ * Reads return the guest view of the hash table, which has to be
+ * pieced together from the real hash table and the guest_rpte
+ * values in the revmap array.
+ *
+ * On writes, each HPTE written is considered in turn, and if it
+ * is valid, it is written to the HPT as if an H_ENTER with the
+ * exact flag set was done.  When the invalid count is non-zero
+ * in the header written to the stream, the kernel will make
+ * sure that that many HPTEs are invalid, and invalidate them
+ * if not.
+ */
+
+struct kvm_htab_ctx {
+	unsigned long	index;
+	unsigned long	flags;
+	struct kvm	*kvm;
+	int		first_pass;
+};
+
+#define HPTE_SIZE	(2 * sizeof(unsigned long))
+
+static long record_hpte(unsigned long flags, unsigned long *hptp,
+			unsigned long *hpte, struct revmap_entry *revp,
+			int want_valid, int first_pass)
+{
+	unsigned long v, r;
+	int ok = 1;
+	int valid, dirty;
+
+	/* Unmodified entries are uninteresting except on the first pass */
+	dirty = !!(revp->guest_rpte & HPTE_GR_MODIFIED);
+	if (!first_pass && !dirty)
+		return 0;
+
+	valid = 0;
+	if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT)) {
+		valid = 1;
+		if ((flags & KVM_GET_HTAB_BOLTED_ONLY) &&
+		    !(hptp[0] & HPTE_V_BOLTED))
+			valid = 0;
+	}
+	if (valid != want_valid)
+		return 0;
+
+	v = r = 0;
+	if (valid || dirty) {
+		/* lock the HPTE so it's stable and read it */
+		preempt_disable();
+		while (!try_lock_hpte(hptp, HPTE_V_HVLOCK))
+			cpu_relax();
+		v = hptp[0];
+		if (v & HPTE_V_ABSENT) {
+			v &= ~HPTE_V_ABSENT;
+			v |= HPTE_V_VALID;
+		}
+		/* re-evaluate valid and dirty from synchronized HPTE value */
+		valid = !!(v & HPTE_V_VALID);
+		if ((flags & KVM_GET_HTAB_BOLTED_ONLY) && !(v & HPTE_V_BOLTED))
+			valid = 0;
+		r = revp->guest_rpte | (hptp[1] & (HPTE_R_R | HPTE_R_C));
+		dirty = !!(revp->guest_rpte & HPTE_GR_MODIFIED);
+		/* only clear modified if this is the right sort of entry */
+		if (valid == want_valid && dirty) {
+			r &= ~HPTE_GR_MODIFIED;
+			revp->guest_rpte = r;
+		}
+		asm volatile(PPC_RELEASE_BARRIER "" : : : "memory");
+		hptp[0] &= ~HPTE_V_HVLOCK;
+		preempt_enable();
+		if (!(valid == want_valid && (first_pass || dirty)))
+			ok = 0;
+	}
+	hpte[0] = v;
+	hpte[1] = r;
+	return ok;
+}
+
+static ssize_t kvm_htab_read(struct file *file, char __user *buf,
+			     size_t count, loff_t *ppos)
+{
+	struct kvm_htab_ctx *ctx = file->private_data;
+	struct kvm *kvm = ctx->kvm;
+	struct kvm_get_htab_header hdr;
+	unsigned long *hptp;
+	struct revmap_entry *revp;
+	unsigned long i, nb, nw;
+	unsigned long __user *lbuf;
+	struct kvm_get_htab_header __user *hptr;
+	unsigned long flags;
+	int first_pass;
+	unsigned long hpte[2];
+
+	if (!access_ok(VERIFY_WRITE, buf, count))
+		return -EFAULT;
+
+	first_pass = ctx->first_pass;
+	flags = ctx->flags;
+
+	i = ctx->index;
+	hptp = (unsigned long *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
+	revp = kvm->arch.revmap + i;
+	lbuf = (unsigned long __user *)buf;
+
+	nb = 0;
+	while (nb + sizeof(hdr) + HPTE_SIZE < count) {
+		/* Initialize header */
+		hptr = (struct kvm_get_htab_header __user *)buf;
+		hdr.n_valid = 0;
+		hdr.n_invalid = 0;
+		nw = nb;
+		nb += sizeof(hdr);
+		lbuf = (unsigned long __user *)(buf + sizeof(hdr));
+
+		/* Skip uninteresting entries, i.e. clean on not-first pass */
+		if (!first_pass) {
+			while (i < kvm->arch.hpt_npte &&
+			       !(revp->guest_rpte & HPTE_GR_MODIFIED)) {
+				++i;
+				hptp += 2;
+				++revp;
+			}
+		}
+		hdr.index = i;
+
+		/* Grab a series of valid entries */
+		while (i < kvm->arch.hpt_npte &&
+		       hdr.n_valid < 0xffff &&
+		       nb + HPTE_SIZE < count &&
+		       record_hpte(flags, hptp, hpte, revp, 1, first_pass)) {
+			/* valid entry, write it out */
+			++hdr.n_valid;
+			if (__put_user(hpte[0], lbuf) ||
+			    __put_user(hpte[1], lbuf + 1))
+				return -EFAULT;
+			nb += HPTE_SIZE;
+			lbuf += 2;
+			++i;
+			hptp += 2;
+			++revp;
+		}
+		/* Now skip invalid entries while we can */
+		while (i < kvm->arch.hpt_npte &&
+		       hdr.n_invalid < 0xffff &&
+		       record_hpte(flags, hptp, hpte, revp, 0, first_pass)) {
+			/* found an invalid entry */
+			++hdr.n_invalid;
+			++i;
+			hptp += 2;
+			++revp;
+		}
+
+		if (hdr.n_valid || hdr.n_invalid) {
+			/* write back the header */
+			if (__copy_to_user(hptr, &hdr, sizeof(hdr)))
+				return -EFAULT;
+			nw = nb;
+			buf = (char __user *)lbuf;
+		} else {
+			nb = nw;
+		}
+
+		/* Check if we've wrapped around the hash table */
+		if (i >= kvm->arch.hpt_npte) {
+			i = 0;
+			ctx->first_pass = 0;
+			break;
+		}
+	}
+
+	ctx->index = i;
+
+	return nb;
+}
+
+static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
+			      size_t count, loff_t *ppos)
+{
+	struct kvm_htab_ctx *ctx = file->private_data;
+	struct kvm *kvm = ctx->kvm;
+	struct kvm_get_htab_header hdr;
+	unsigned long i, j;
+	unsigned long v, r;
+	unsigned long __user *lbuf;
+	unsigned long *hptp;
+	unsigned long tmp[2];
+	ssize_t nb;
+	long int err, ret;
+	int rma_setup;
+
+	if (!access_ok(VERIFY_READ, buf, count))
+		return -EFAULT;
+
+	/* lock out vcpus from running while we're doing this */
+	mutex_lock(&kvm->lock);
+	rma_setup = kvm->arch.rma_setup_done;
+	if (rma_setup) {
+		kvm->arch.rma_setup_done = 0;	/* temporarily */
+		/* order rma_setup_done vs. vcpus_running */
+		smp_mb();
+		if (atomic_read(&kvm->arch.vcpus_running)) {
+			kvm->arch.rma_setup_done = 1;
+			mutex_unlock(&kvm->lock);
+			return -EBUSY;
+		}
+	}
+
+	err = 0;
+	for (nb = 0; nb + sizeof(hdr) <= count; ) {
+		err = -EFAULT;
+		if (__copy_from_user(&hdr, buf, sizeof(hdr)))
+			break;
+
+		err = 0;
+		if (nb + hdr.n_valid * HPTE_SIZE > count)
+			break;
+
+		nb += sizeof(hdr);
+		buf += sizeof(hdr);
+
+		err = -EINVAL;
+		i = hdr.index;
+		if (i >= kvm->arch.hpt_npte ||
+		    i + hdr.n_valid + hdr.n_invalid > kvm->arch.hpt_npte)
+			break;
+
+		hptp = (unsigned long *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
+		lbuf = (unsigned long __user *)buf;
+		for (j = 0; j < hdr.n_valid; ++j) {
+			err = -EFAULT;
+			if (__get_user(v, lbuf) || __get_user(r, lbuf + 1))
+				goto out;
+			err = -EINVAL;
+			if (!(v & HPTE_V_VALID))
+				goto out;
+			lbuf += 2;
+			nb += HPTE_SIZE;
+
+			if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT))
+				kvmppc_do_h_remove(kvm, 0, i, 0, tmp);
+			err = -EIO;
+			ret = kvmppc_virtmode_do_h_enter(kvm, H_EXACT, i, v, r,
+							 tmp);
+			if (ret != H_SUCCESS) {
+				pr_err("kvm_htab_write ret %ld i=%ld v=%lx "
+				       "r=%lx\n", ret, i, v, r);
+				goto out;
+			}
+			if (!rma_setup && is_vrma_hpte(v)) {
+				unsigned long psize = hpte_page_size(v, r);
+				unsigned long senc = slb_pgsize_encoding(psize);
+				unsigned long lpcr;
+
+				kvm->arch.vrma_slb_v = senc | SLB_VSID_B_1T |
+					(VRMA_VSID << SLB_VSID_SHIFT_1T);
+				lpcr = kvm->arch.lpcr & ~LPCR_VRMASD;
+				lpcr |= senc << (LPCR_VRMASD_SH - 4);
+				kvm->arch.lpcr = lpcr;
+				rma_setup = 1;
+			}
+			++i;
+			hptp += 2;
+		}
+
+		for (j = 0; j < hdr.n_invalid; ++j) {
+			if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT))
+				kvmppc_do_h_remove(kvm, 0, i, 0, tmp);
+			++i;
+			hptp += 2;
+		}
+		err = 0;
+	}
+
+ out:
+	/* Order HPTE updates vs. rma_setup_done */
+	smp_wmb();
+	kvm->arch.rma_setup_done = rma_setup;
+	mutex_unlock(&kvm->lock);
+
+	if (err)
+		return err;
+	return nb;
+}
+
+static int kvm_htab_release(struct inode *inode, struct file *filp)
+{
+	struct kvm_htab_ctx *ctx = filp->private_data;
+
+	filp->private_data = NULL;
+	if (!(ctx->flags & KVM_GET_HTAB_WRITE))
+		atomic_dec(&ctx->kvm->arch.hpte_mod_interest);
+	kvm_put_kvm(ctx->kvm);
+	kfree(ctx);
+	return 0;
+}
+
+static struct file_operations kvm_htab_fops = {
+	.read		= kvm_htab_read,
+	.write		= kvm_htab_write,
+	.llseek		= default_llseek,
+	.release	= kvm_htab_release,
+};
+
+int kvm_vm_ioctl_get_htab_fd(struct kvm *kvm, struct kvm_get_htab_fd *ghf)
+{
+	int ret;
+	struct kvm_htab_ctx *ctx;
+	int rwflag;
+
+	/* reject flags we don't recognize */
+	if (ghf->flags & ~(KVM_GET_HTAB_BOLTED_ONLY | KVM_GET_HTAB_WRITE))
+		return -EINVAL;
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+	kvm_get_kvm(kvm);
+	ctx->kvm = kvm;
+	ctx->index = ghf->start_index;
+	ctx->flags = ghf->flags;
+	ctx->first_pass = 1;
+
+	rwflag = (ghf->flags & KVM_GET_HTAB_WRITE) ? O_WRONLY : O_RDONLY;
+	ret = anon_inode_getfd("kvm-htab", &kvm_htab_fops, ctx, rwflag);
+	if (ret < 0) {
+		kvm_put_kvm(kvm);
+		return ret;
+	}
+
+	if (rwflag == O_RDONLY) {
+		mutex_lock(&kvm->slots_lock);
+		atomic_inc(&kvm->arch.hpte_mod_interest);
+		/* make sure kvmppc_do_h_enter etc. see the increment */
+		synchronize_srcu_expedited(&kvm->srcu);
+		mutex_unlock(&kvm->slots_lock);
+	}
+
+	return ret;
+}
+
 void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu)
 {
 	struct kvmppc_mmu *mmu = &vcpu->arch.mmu;
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index b9a989d..d31a716 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -22,6 +22,7 @@
 #include <asm/kvm_book3s.h>
 #include <asm/reg.h>
 #include <asm/switch_to.h>
+#include <asm/time.h>
 
 #define OP_19_XOP_RFID		18
 #define OP_19_XOP_RFI		50
@@ -395,6 +396,12 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
 		    (mfmsr() & MSR_HV))
 			vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
 		break;
+	case SPRN_PURR:
+		to_book3s(vcpu)->purr_offset = spr_val - get_tb();
+		break;
+	case SPRN_SPURR:
+		to_book3s(vcpu)->spurr_offset = spr_val - get_tb();
+		break;
 	case SPRN_GQR0:
 	case SPRN_GQR1:
 	case SPRN_GQR2:
@@ -412,6 +419,7 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
 	case SPRN_CTRLF:
 	case SPRN_CTRLT:
 	case SPRN_L2CR:
+	case SPRN_DSCR:
 	case SPRN_MMCR0_GEKKO:
 	case SPRN_MMCR1_GEKKO:
 	case SPRN_PMC1_GEKKO:
@@ -483,9 +491,15 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
 		*spr_val = to_book3s(vcpu)->hid[5];
 		break;
 	case SPRN_CFAR:
-	case SPRN_PURR:
+	case SPRN_DSCR:
 		*spr_val = 0;
 		break;
+	case SPRN_PURR:
+		*spr_val = get_tb() + to_book3s(vcpu)->purr_offset;
+		break;
+	case SPRN_SPURR:
+		*spr_val = get_tb() + to_book3s(vcpu)->purr_offset;
+		break;
 	case SPRN_GQR0:
 	case SPRN_GQR1:
 	case SPRN_GQR2:
diff --git a/arch/powerpc/kvm/book3s_exports.c b/arch/powerpc/kvm/book3s_exports.c
index a150817..7057a02 100644
--- a/arch/powerpc/kvm/book3s_exports.c
+++ b/arch/powerpc/kvm/book3s_exports.c
@@ -28,8 +28,5 @@ EXPORT_SYMBOL_GPL(kvmppc_load_up_fpu);
 #ifdef CONFIG_ALTIVEC
 EXPORT_SYMBOL_GPL(kvmppc_load_up_altivec);
 #endif
-#ifdef CONFIG_VSX
-EXPORT_SYMBOL_GPL(kvmppc_load_up_vsx);
-#endif
 #endif
 
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 721d460..71d0c90 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -30,6 +30,7 @@
 #include <linux/cpumask.h>
 #include <linux/spinlock.h>
 #include <linux/page-flags.h>
+#include <linux/srcu.h>
 
 #include <asm/reg.h>
 #include <asm/cputable.h>
@@ -46,6 +47,7 @@
 #include <asm/page.h>
 #include <asm/hvcall.h>
 #include <asm/switch_to.h>
+#include <asm/smp.h>
 #include <linux/gfp.h>
 #include <linux/vmalloc.h>
 #include <linux/highmem.h>
@@ -55,25 +57,77 @@
 /* #define EXIT_DEBUG_SIMPLE */
 /* #define EXIT_DEBUG_INT */
 
+/* Used to indicate that a guest page fault needs to be handled */
+#define RESUME_PAGE_FAULT	(RESUME_GUEST | RESUME_FLAG_ARCH1)
+
+/* Used as a "null" value for timebase values */
+#define TB_NIL	(~(u64)0)
+
 static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
 static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
 
+/*
+ * We use the vcpu_load/put functions to measure stolen time.
+ * Stolen time is counted as time when either the vcpu is able to
+ * run as part of a virtual core, but the task running the vcore
+ * is preempted or sleeping, or when the vcpu needs something done
+ * in the kernel by the task running the vcpu, but that task is
+ * preempted or sleeping.  Those two things have to be counted
+ * separately, since one of the vcpu tasks will take on the job
+ * of running the core, and the other vcpu tasks in the vcore will
+ * sleep waiting for it to do that, but that sleep shouldn't count
+ * as stolen time.
+ *
+ * Hence we accumulate stolen time when the vcpu can run as part of
+ * a vcore using vc->stolen_tb, and the stolen time when the vcpu
+ * needs its task to do other things in the kernel (for example,
+ * service a page fault) in busy_stolen.  We don't accumulate
+ * stolen time for a vcore when it is inactive, or for a vcpu
+ * when it is in state RUNNING or NOTREADY.  NOTREADY is a bit of
+ * a misnomer; it means that the vcpu task is not executing in
+ * the KVM_VCPU_RUN ioctl, i.e. it is in userspace or elsewhere in
+ * the kernel.  We don't have any way of dividing up that time
+ * between time that the vcpu is genuinely stopped, time that
+ * the task is actively working on behalf of the vcpu, and time
+ * that the task is preempted, so we don't count any of it as
+ * stolen.
+ *
+ * Updates to busy_stolen are protected by arch.tbacct_lock;
+ * updates to vc->stolen_tb are protected by the arch.tbacct_lock
+ * of the vcpu that has taken responsibility for running the vcore
+ * (i.e. vc->runner).  The stolen times are measured in units of
+ * timebase ticks.  (Note that the != TB_NIL checks below are
+ * purely defensive; they should never fail.)
+ */
+
 void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
 	struct kvmppc_vcore *vc = vcpu->arch.vcore;
 
-	local_paca->kvm_hstate.kvm_vcpu = vcpu;
-	local_paca->kvm_hstate.kvm_vcore = vc;
-	if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE)
+	spin_lock(&vcpu->arch.tbacct_lock);
+	if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE &&
+	    vc->preempt_tb != TB_NIL) {
 		vc->stolen_tb += mftb() - vc->preempt_tb;
+		vc->preempt_tb = TB_NIL;
+	}
+	if (vcpu->arch.state == KVMPPC_VCPU_BUSY_IN_HOST &&
+	    vcpu->arch.busy_preempt != TB_NIL) {
+		vcpu->arch.busy_stolen += mftb() - vcpu->arch.busy_preempt;
+		vcpu->arch.busy_preempt = TB_NIL;
+	}
+	spin_unlock(&vcpu->arch.tbacct_lock);
 }
 
 void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
 {
 	struct kvmppc_vcore *vc = vcpu->arch.vcore;
 
+	spin_lock(&vcpu->arch.tbacct_lock);
 	if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE)
 		vc->preempt_tb = mftb();
+	if (vcpu->arch.state == KVMPPC_VCPU_BUSY_IN_HOST)
+		vcpu->arch.busy_preempt = mftb();
+	spin_unlock(&vcpu->arch.tbacct_lock);
 }
 
 void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
@@ -142,6 +196,22 @@ static void init_vpa(struct kvm_vcpu *vcpu, struct lppaca *vpa)
 	vpa->yield_count = 1;
 }
 
+static int set_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *v,
+		   unsigned long addr, unsigned long len)
+{
+	/* check address is cacheline aligned */
+	if (addr & (L1_CACHE_BYTES - 1))
+		return -EINVAL;
+	spin_lock(&vcpu->arch.vpa_update_lock);
+	if (v->next_gpa != addr || v->len != len) {
+		v->next_gpa = addr;
+		v->len = addr ? len : 0;
+		v->update_pending = 1;
+	}
+	spin_unlock(&vcpu->arch.vpa_update_lock);
+	return 0;
+}
+
 /* Length for a per-processor buffer is passed in at offset 4 in the buffer */
 struct reg_vpa {
 	u32 dummy;
@@ -317,10 +387,16 @@ static void kvmppc_update_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *vpap)
 
 static void kvmppc_update_vpas(struct kvm_vcpu *vcpu)
 {
+	if (!(vcpu->arch.vpa.update_pending ||
+	      vcpu->arch.slb_shadow.update_pending ||
+	      vcpu->arch.dtl.update_pending))
+		return;
+
 	spin_lock(&vcpu->arch.vpa_update_lock);
 	if (vcpu->arch.vpa.update_pending) {
 		kvmppc_update_vpa(vcpu, &vcpu->arch.vpa);
-		init_vpa(vcpu, vcpu->arch.vpa.pinned_addr);
+		if (vcpu->arch.vpa.pinned_addr)
+			init_vpa(vcpu, vcpu->arch.vpa.pinned_addr);
 	}
 	if (vcpu->arch.dtl.update_pending) {
 		kvmppc_update_vpa(vcpu, &vcpu->arch.dtl);
@@ -332,24 +408,61 @@ static void kvmppc_update_vpas(struct kvm_vcpu *vcpu)
 	spin_unlock(&vcpu->arch.vpa_update_lock);
 }
 
+/*
+ * Return the accumulated stolen time for the vcore up until `now'.
+ * The caller should hold the vcore lock.
+ */
+static u64 vcore_stolen_time(struct kvmppc_vcore *vc, u64 now)
+{
+	u64 p;
+
+	/*
+	 * If we are the task running the vcore, then since we hold
+	 * the vcore lock, we can't be preempted, so stolen_tb/preempt_tb
+	 * can't be updated, so we don't need the tbacct_lock.
+	 * If the vcore is inactive, it can't become active (since we
+	 * hold the vcore lock), so the vcpu load/put functions won't
+	 * update stolen_tb/preempt_tb, and we don't need tbacct_lock.
+	 */
+	if (vc->vcore_state != VCORE_INACTIVE &&
+	    vc->runner->arch.run_task != current) {
+		spin_lock(&vc->runner->arch.tbacct_lock);
+		p = vc->stolen_tb;
+		if (vc->preempt_tb != TB_NIL)
+			p += now - vc->preempt_tb;
+		spin_unlock(&vc->runner->arch.tbacct_lock);
+	} else {
+		p = vc->stolen_tb;
+	}
+	return p;
+}
+
 static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu,
 				    struct kvmppc_vcore *vc)
 {
 	struct dtl_entry *dt;
 	struct lppaca *vpa;
-	unsigned long old_stolen;
+	unsigned long stolen;
+	unsigned long core_stolen;
+	u64 now;
 
 	dt = vcpu->arch.dtl_ptr;
 	vpa = vcpu->arch.vpa.pinned_addr;
-	old_stolen = vcpu->arch.stolen_logged;
-	vcpu->arch.stolen_logged = vc->stolen_tb;
+	now = mftb();
+	core_stolen = vcore_stolen_time(vc, now);
+	stolen = core_stolen - vcpu->arch.stolen_logged;
+	vcpu->arch.stolen_logged = core_stolen;
+	spin_lock(&vcpu->arch.tbacct_lock);
+	stolen += vcpu->arch.busy_stolen;
+	vcpu->arch.busy_stolen = 0;
+	spin_unlock(&vcpu->arch.tbacct_lock);
 	if (!dt || !vpa)
 		return;
 	memset(dt, 0, sizeof(struct dtl_entry));
 	dt->dispatch_reason = 7;
 	dt->processor_id = vc->pcpu + vcpu->arch.ptid;
-	dt->timebase = mftb();
-	dt->enqueue_to_dispatch_time = vc->stolen_tb - old_stolen;
+	dt->timebase = now;
+	dt->enqueue_to_dispatch_time = stolen;
 	dt->srr0 = kvmppc_get_pc(vcpu);
 	dt->srr1 = vcpu->arch.shregs.msr;
 	++dt;
@@ -366,13 +479,16 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
 	unsigned long req = kvmppc_get_gpr(vcpu, 3);
 	unsigned long target, ret = H_SUCCESS;
 	struct kvm_vcpu *tvcpu;
+	int idx;
 
 	switch (req) {
 	case H_ENTER:
+		idx = srcu_read_lock(&vcpu->kvm->srcu);
 		ret = kvmppc_virtmode_h_enter(vcpu, kvmppc_get_gpr(vcpu, 4),
 					      kvmppc_get_gpr(vcpu, 5),
 					      kvmppc_get_gpr(vcpu, 6),
 					      kvmppc_get_gpr(vcpu, 7));
+		srcu_read_unlock(&vcpu->kvm->srcu, idx);
 		break;
 	case H_CEDE:
 		break;
@@ -429,6 +545,17 @@ static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	case BOOK3S_INTERRUPT_PERFMON:
 		r = RESUME_GUEST;
 		break;
+	case BOOK3S_INTERRUPT_MACHINE_CHECK:
+		/*
+		 * Deliver a machine check interrupt to the guest.
+		 * We have to do this, even if the host has handled the
+		 * machine check, because machine checks use SRR0/1 and
+		 * the interrupt might have trashed guest state in them.
+		 */
+		kvmppc_book3s_queue_irqprio(vcpu,
+					    BOOK3S_INTERRUPT_MACHINE_CHECK);
+		r = RESUME_GUEST;
+		break;
 	case BOOK3S_INTERRUPT_PROGRAM:
 	{
 		ulong flags;
@@ -470,12 +597,12 @@ static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	 * have been handled already.
 	 */
 	case BOOK3S_INTERRUPT_H_DATA_STORAGE:
-		r = kvmppc_book3s_hv_page_fault(run, vcpu,
-				vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
+		r = RESUME_PAGE_FAULT;
 		break;
 	case BOOK3S_INTERRUPT_H_INST_STORAGE:
-		r = kvmppc_book3s_hv_page_fault(run, vcpu,
-				kvmppc_get_pc(vcpu), 0);
+		vcpu->arch.fault_dar = kvmppc_get_pc(vcpu);
+		vcpu->arch.fault_dsisr = 0;
+		r = RESUME_PAGE_FAULT;
 		break;
 	/*
 	 * This occurs if the guest executes an illegal instruction.
@@ -535,36 +662,174 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 	return 0;
 }
 
-int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
 {
-	int r = -EINVAL;
+	int r = 0;
+	long int i;
 
-	switch (reg->id) {
+	switch (id) {
 	case KVM_REG_PPC_HIOR:
-		r = put_user(0, (u64 __user *)reg->addr);
+		*val = get_reg_val(id, 0);
+		break;
+	case KVM_REG_PPC_DABR:
+		*val = get_reg_val(id, vcpu->arch.dabr);
+		break;
+	case KVM_REG_PPC_DSCR:
+		*val = get_reg_val(id, vcpu->arch.dscr);
+		break;
+	case KVM_REG_PPC_PURR:
+		*val = get_reg_val(id, vcpu->arch.purr);
+		break;
+	case KVM_REG_PPC_SPURR:
+		*val = get_reg_val(id, vcpu->arch.spurr);
+		break;
+	case KVM_REG_PPC_AMR:
+		*val = get_reg_val(id, vcpu->arch.amr);
+		break;
+	case KVM_REG_PPC_UAMOR:
+		*val = get_reg_val(id, vcpu->arch.uamor);
+		break;
+	case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCRA:
+		i = id - KVM_REG_PPC_MMCR0;
+		*val = get_reg_val(id, vcpu->arch.mmcr[i]);
+		break;
+	case KVM_REG_PPC_PMC1 ... KVM_REG_PPC_PMC8:
+		i = id - KVM_REG_PPC_PMC1;
+		*val = get_reg_val(id, vcpu->arch.pmc[i]);
+		break;
+#ifdef CONFIG_VSX
+	case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
+		if (cpu_has_feature(CPU_FTR_VSX)) {
+			/* VSX => FP reg i is stored in arch.vsr[2*i] */
+			long int i = id - KVM_REG_PPC_FPR0;
+			*val = get_reg_val(id, vcpu->arch.vsr[2 * i]);
+		} else {
+			/* let generic code handle it */
+			r = -EINVAL;
+		}
+		break;
+	case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31:
+		if (cpu_has_feature(CPU_FTR_VSX)) {
+			long int i = id - KVM_REG_PPC_VSR0;
+			val->vsxval[0] = vcpu->arch.vsr[2 * i];
+			val->vsxval[1] = vcpu->arch.vsr[2 * i + 1];
+		} else {
+			r = -ENXIO;
+		}
+		break;
+#endif /* CONFIG_VSX */
+	case KVM_REG_PPC_VPA_ADDR:
+		spin_lock(&vcpu->arch.vpa_update_lock);
+		*val = get_reg_val(id, vcpu->arch.vpa.next_gpa);
+		spin_unlock(&vcpu->arch.vpa_update_lock);
+		break;
+	case KVM_REG_PPC_VPA_SLB:
+		spin_lock(&vcpu->arch.vpa_update_lock);
+		val->vpaval.addr = vcpu->arch.slb_shadow.next_gpa;
+		val->vpaval.length = vcpu->arch.slb_shadow.len;
+		spin_unlock(&vcpu->arch.vpa_update_lock);
+		break;
+	case KVM_REG_PPC_VPA_DTL:
+		spin_lock(&vcpu->arch.vpa_update_lock);
+		val->vpaval.addr = vcpu->arch.dtl.next_gpa;
+		val->vpaval.length = vcpu->arch.dtl.len;
+		spin_unlock(&vcpu->arch.vpa_update_lock);
 		break;
 	default:
+		r = -EINVAL;
 		break;
 	}
 
 	return r;
 }
 
-int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
 {
-	int r = -EINVAL;
+	int r = 0;
+	long int i;
+	unsigned long addr, len;
 
-	switch (reg->id) {
+	switch (id) {
 	case KVM_REG_PPC_HIOR:
-	{
-		u64 hior;
 		/* Only allow this to be set to zero */
-		r = get_user(hior, (u64 __user *)reg->addr);
-		if (!r && (hior != 0))
+		if (set_reg_val(id, *val))
 			r = -EINVAL;
 		break;
-	}
+	case KVM_REG_PPC_DABR:
+		vcpu->arch.dabr = set_reg_val(id, *val);
+		break;
+	case KVM_REG_PPC_DSCR:
+		vcpu->arch.dscr = set_reg_val(id, *val);
+		break;
+	case KVM_REG_PPC_PURR:
+		vcpu->arch.purr = set_reg_val(id, *val);
+		break;
+	case KVM_REG_PPC_SPURR:
+		vcpu->arch.spurr = set_reg_val(id, *val);
+		break;
+	case KVM_REG_PPC_AMR:
+		vcpu->arch.amr = set_reg_val(id, *val);
+		break;
+	case KVM_REG_PPC_UAMOR:
+		vcpu->arch.uamor = set_reg_val(id, *val);
+		break;
+	case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCRA:
+		i = id - KVM_REG_PPC_MMCR0;
+		vcpu->arch.mmcr[i] = set_reg_val(id, *val);
+		break;
+	case KVM_REG_PPC_PMC1 ... KVM_REG_PPC_PMC8:
+		i = id - KVM_REG_PPC_PMC1;
+		vcpu->arch.pmc[i] = set_reg_val(id, *val);
+		break;
+#ifdef CONFIG_VSX
+	case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
+		if (cpu_has_feature(CPU_FTR_VSX)) {
+			/* VSX => FP reg i is stored in arch.vsr[2*i] */
+			long int i = id - KVM_REG_PPC_FPR0;
+			vcpu->arch.vsr[2 * i] = set_reg_val(id, *val);
+		} else {
+			/* let generic code handle it */
+			r = -EINVAL;
+		}
+		break;
+	case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31:
+		if (cpu_has_feature(CPU_FTR_VSX)) {
+			long int i = id - KVM_REG_PPC_VSR0;
+			vcpu->arch.vsr[2 * i] = val->vsxval[0];
+			vcpu->arch.vsr[2 * i + 1] = val->vsxval[1];
+		} else {
+			r = -ENXIO;
+		}
+		break;
+#endif /* CONFIG_VSX */
+	case KVM_REG_PPC_VPA_ADDR:
+		addr = set_reg_val(id, *val);
+		r = -EINVAL;
+		if (!addr && (vcpu->arch.slb_shadow.next_gpa ||
+			      vcpu->arch.dtl.next_gpa))
+			break;
+		r = set_vpa(vcpu, &vcpu->arch.vpa, addr, sizeof(struct lppaca));
+		break;
+	case KVM_REG_PPC_VPA_SLB:
+		addr = val->vpaval.addr;
+		len = val->vpaval.length;
+		r = -EINVAL;
+		if (addr && !vcpu->arch.vpa.next_gpa)
+			break;
+		r = set_vpa(vcpu, &vcpu->arch.slb_shadow, addr, len);
+		break;
+	case KVM_REG_PPC_VPA_DTL:
+		addr = val->vpaval.addr;
+		len = val->vpaval.length;
+		r = -EINVAL;
+		if (addr && (len < sizeof(struct dtl_entry) ||
+			     !vcpu->arch.vpa.next_gpa))
+			break;
+		len -= len % sizeof(struct dtl_entry);
+		r = set_vpa(vcpu, &vcpu->arch.dtl, addr, len);
+		break;
 	default:
+		r = -EINVAL;
 		break;
 	}
 
@@ -599,20 +864,18 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
 		goto free_vcpu;
 
 	vcpu->arch.shared = &vcpu->arch.shregs;
-	vcpu->arch.last_cpu = -1;
 	vcpu->arch.mmcr[0] = MMCR0_FC;
 	vcpu->arch.ctrl = CTRL_RUNLATCH;
 	/* default to host PVR, since we can't spoof it */
 	vcpu->arch.pvr = mfspr(SPRN_PVR);
 	kvmppc_set_pvr(vcpu, vcpu->arch.pvr);
 	spin_lock_init(&vcpu->arch.vpa_update_lock);
+	spin_lock_init(&vcpu->arch.tbacct_lock);
+	vcpu->arch.busy_preempt = TB_NIL;
 
 	kvmppc_mmu_book3s_hv_init(vcpu);
 
-	/*
-	 * We consider the vcpu stopped until we see the first run ioctl for it.
-	 */
-	vcpu->arch.state = KVMPPC_VCPU_STOPPED;
+	vcpu->arch.state = KVMPPC_VCPU_NOTREADY;
 
 	init_waitqueue_head(&vcpu->arch.cpu_run);
 
@@ -624,9 +887,10 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
 			INIT_LIST_HEAD(&vcore->runnable_threads);
 			spin_lock_init(&vcore->lock);
 			init_waitqueue_head(&vcore->wq);
-			vcore->preempt_tb = mftb();
+			vcore->preempt_tb = TB_NIL;
 		}
 		kvm->arch.vcores[core] = vcore;
+		kvm->arch.online_vcores++;
 	}
 	mutex_unlock(&kvm->lock);
 
@@ -637,7 +901,6 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
 	++vcore->num_threads;
 	spin_unlock(&vcore->lock);
 	vcpu->arch.vcore = vcore;
-	vcpu->arch.stolen_logged = vcore->stolen_tb;
 
 	vcpu->arch.cpu_type = KVM_CPU_3S_64;
 	kvmppc_sanity_check(vcpu);
@@ -697,17 +960,18 @@ extern void xics_wake_cpu(int cpu);
 static void kvmppc_remove_runnable(struct kvmppc_vcore *vc,
 				   struct kvm_vcpu *vcpu)
 {
-	struct kvm_vcpu *v;
+	u64 now;
 
 	if (vcpu->arch.state != KVMPPC_VCPU_RUNNABLE)
 		return;
+	spin_lock(&vcpu->arch.tbacct_lock);
+	now = mftb();
+	vcpu->arch.busy_stolen += vcore_stolen_time(vc, now) -
+		vcpu->arch.stolen_logged;
+	vcpu->arch.busy_preempt = now;
 	vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
+	spin_unlock(&vcpu->arch.tbacct_lock);
 	--vc->n_runnable;
-	++vc->n_busy;
-	/* decrement the physical thread id of each following vcpu */
-	v = vcpu;
-	list_for_each_entry_continue(v, &vc->runnable_threads, arch.run_list)
-		--v->arch.ptid;
 	list_del(&vcpu->arch.run_list);
 }
 
@@ -720,6 +984,7 @@ static int kvmppc_grab_hwthread(int cpu)
 
 	/* Ensure the thread won't go into the kernel if it wakes */
 	tpaca->kvm_hstate.hwthread_req = 1;
+	tpaca->kvm_hstate.kvm_vcpu = NULL;
 
 	/*
 	 * If the thread is already executing in the kernel (e.g. handling
@@ -769,7 +1034,6 @@ static void kvmppc_start_thread(struct kvm_vcpu *vcpu)
 	smp_wmb();
 #if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP)
 	if (vcpu->arch.ptid) {
-		kvmppc_grab_hwthread(cpu);
 		xics_wake_cpu(cpu);
 		++vc->n_woken;
 	}
@@ -795,7 +1059,8 @@ static void kvmppc_wait_for_nap(struct kvmppc_vcore *vc)
 
 /*
  * Check that we are on thread 0 and that any other threads in
- * this core are off-line.
+ * this core are off-line.  Then grab the threads so they can't
+ * enter the kernel.
  */
 static int on_primary_thread(void)
 {
@@ -807,6 +1072,17 @@ static int on_primary_thread(void)
 	while (++thr < threads_per_core)
 		if (cpu_online(cpu + thr))
 			return 0;
+
+	/* Grab all hw threads so they can't go into the kernel */
+	for (thr = 1; thr < threads_per_core; ++thr) {
+		if (kvmppc_grab_hwthread(cpu + thr)) {
+			/* Couldn't grab one; let the others go */
+			do {
+				kvmppc_release_hwthread(cpu + thr);
+			} while (--thr > 0);
+			return 0;
+		}
+	}
 	return 1;
 }
 
@@ -814,21 +1090,24 @@ static int on_primary_thread(void)
  * Run a set of guest threads on a physical core.
  * Called with vc->lock held.
  */
-static int kvmppc_run_core(struct kvmppc_vcore *vc)
+static void kvmppc_run_core(struct kvmppc_vcore *vc)
 {
 	struct kvm_vcpu *vcpu, *vcpu0, *vnext;
 	long ret;
 	u64 now;
 	int ptid, i, need_vpa_update;
+	int srcu_idx;
+	struct kvm_vcpu *vcpus_to_update[threads_per_core];
 
 	/* don't start if any threads have a signal pending */
 	need_vpa_update = 0;
 	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
 		if (signal_pending(vcpu->arch.run_task))
-			return 0;
-		need_vpa_update |= vcpu->arch.vpa.update_pending |
-			vcpu->arch.slb_shadow.update_pending |
-			vcpu->arch.dtl.update_pending;
+			return;
+		if (vcpu->arch.vpa.update_pending ||
+		    vcpu->arch.slb_shadow.update_pending ||
+		    vcpu->arch.dtl.update_pending)
+			vcpus_to_update[need_vpa_update++] = vcpu;
 	}
 
 	/*
@@ -838,7 +1117,7 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
 	vc->n_woken = 0;
 	vc->nap_count = 0;
 	vc->entry_exit_count = 0;
-	vc->vcore_state = VCORE_RUNNING;
+	vc->vcore_state = VCORE_STARTING;
 	vc->in_guest = 0;
 	vc->napping_threads = 0;
 
@@ -848,24 +1127,12 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
 	 */
 	if (need_vpa_update) {
 		spin_unlock(&vc->lock);
-		list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
-			kvmppc_update_vpas(vcpu);
+		for (i = 0; i < need_vpa_update; ++i)
+			kvmppc_update_vpas(vcpus_to_update[i]);
 		spin_lock(&vc->lock);
 	}
 
 	/*
-	 * Make sure we are running on thread 0, and that
-	 * secondary threads are offline.
-	 * XXX we should also block attempts to bring any
-	 * secondary threads online.
-	 */
-	if (threads_per_core > 1 && !on_primary_thread()) {
-		list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
-			vcpu->arch.ret = -EBUSY;
-		goto out;
-	}
-
-	/*
 	 * Assign physical thread IDs, first to non-ceded vcpus
 	 * and then to ceded ones.
 	 */
@@ -879,28 +1146,36 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
 		}
 	}
 	if (!vcpu0)
-		return 0;		/* nothing to run */
+		goto out;	/* nothing to run; should never happen */
 	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
 		if (vcpu->arch.ceded)
 			vcpu->arch.ptid = ptid++;
 
-	vc->stolen_tb += mftb() - vc->preempt_tb;
+	/*
+	 * Make sure we are running on thread 0, and that
+	 * secondary threads are offline.
+	 */
+	if (threads_per_core > 1 && !on_primary_thread()) {
+		list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
+			vcpu->arch.ret = -EBUSY;
+		goto out;
+	}
+
 	vc->pcpu = smp_processor_id();
 	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
 		kvmppc_start_thread(vcpu);
 		kvmppc_create_dtl_entry(vcpu, vc);
 	}
-	/* Grab any remaining hw threads so they can't go into the kernel */
-	for (i = ptid; i < threads_per_core; ++i)
-		kvmppc_grab_hwthread(vc->pcpu + i);
 
+	vc->vcore_state = VCORE_RUNNING;
 	preempt_disable();
 	spin_unlock(&vc->lock);
 
 	kvm_guest_enter();
+
+	srcu_idx = srcu_read_lock(&vcpu0->kvm->srcu);
+
 	__kvmppc_vcore_entry(NULL, vcpu0);
-	for (i = 0; i < threads_per_core; ++i)
-		kvmppc_release_hwthread(vc->pcpu + i);
 
 	spin_lock(&vc->lock);
 	/* disable sending of IPIs on virtual external irqs */
@@ -909,10 +1184,14 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
 	/* wait for secondary threads to finish writing their state to memory */
 	if (vc->nap_count < vc->n_woken)
 		kvmppc_wait_for_nap(vc);
+	for (i = 0; i < threads_per_core; ++i)
+		kvmppc_release_hwthread(vc->pcpu + i);
 	/* prevent other vcpu threads from doing kvmppc_start_thread() now */
 	vc->vcore_state = VCORE_EXITING;
 	spin_unlock(&vc->lock);
 
+	srcu_read_unlock(&vcpu0->kvm->srcu, srcu_idx);
+
 	/* make sure updates to secondary vcpu structs are visible now */
 	smp_mb();
 	kvm_guest_exit();
@@ -920,6 +1199,7 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
 	preempt_enable();
 	kvm_resched(vcpu);
 
+	spin_lock(&vc->lock);
 	now = get_tb();
 	list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
 		/* cancel pending dec exception if dec is positive */
@@ -943,10 +1223,8 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
 		}
 	}
 
-	spin_lock(&vc->lock);
  out:
 	vc->vcore_state = VCORE_INACTIVE;
-	vc->preempt_tb = mftb();
 	list_for_each_entry_safe(vcpu, vnext, &vc->runnable_threads,
 				 arch.run_list) {
 		if (vcpu->arch.ret != RESUME_GUEST) {
@@ -954,8 +1232,6 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
 			wake_up(&vcpu->arch.cpu_run);
 		}
 	}
-
-	return 1;
 }
 
 /*
@@ -979,20 +1255,11 @@ static void kvmppc_wait_for_exec(struct kvm_vcpu *vcpu, int wait_state)
 static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
 {
 	DEFINE_WAIT(wait);
-	struct kvm_vcpu *v;
-	int all_idle = 1;
 
 	prepare_to_wait(&vc->wq, &wait, TASK_INTERRUPTIBLE);
 	vc->vcore_state = VCORE_SLEEPING;
 	spin_unlock(&vc->lock);
-	list_for_each_entry(v, &vc->runnable_threads, arch.run_list) {
-		if (!v->arch.ceded || v->arch.pending_exceptions) {
-			all_idle = 0;
-			break;
-		}
-	}
-	if (all_idle)
-		schedule();
+	schedule();
 	finish_wait(&vc->wq, &wait);
 	spin_lock(&vc->lock);
 	vc->vcore_state = VCORE_INACTIVE;
@@ -1001,13 +1268,13 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
 static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
 	int n_ceded;
-	int prev_state;
 	struct kvmppc_vcore *vc;
 	struct kvm_vcpu *v, *vn;
 
 	kvm_run->exit_reason = 0;
 	vcpu->arch.ret = RESUME_GUEST;
 	vcpu->arch.trap = 0;
+	kvmppc_update_vpas(vcpu);
 
 	/*
 	 * Synchronize with other threads in this virtual core
@@ -1017,8 +1284,9 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 	vcpu->arch.ceded = 0;
 	vcpu->arch.run_task = current;
 	vcpu->arch.kvm_run = kvm_run;
-	prev_state = vcpu->arch.state;
+	vcpu->arch.stolen_logged = vcore_stolen_time(vc, mftb());
 	vcpu->arch.state = KVMPPC_VCPU_RUNNABLE;
+	vcpu->arch.busy_preempt = TB_NIL;
 	list_add_tail(&vcpu->arch.run_list, &vc->runnable_threads);
 	++vc->n_runnable;
 
@@ -1027,33 +1295,26 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 	 * If the vcore is already running, we may be able to start
 	 * this thread straight away and have it join in.
 	 */
-	if (prev_state == KVMPPC_VCPU_STOPPED) {
+	if (!signal_pending(current)) {
 		if (vc->vcore_state == VCORE_RUNNING &&
 		    VCORE_EXIT_COUNT(vc) == 0) {
 			vcpu->arch.ptid = vc->n_runnable - 1;
+			kvmppc_create_dtl_entry(vcpu, vc);
 			kvmppc_start_thread(vcpu);
+		} else if (vc->vcore_state == VCORE_SLEEPING) {
+			wake_up(&vc->wq);
 		}
 
-	} else if (prev_state == KVMPPC_VCPU_BUSY_IN_HOST)
-		--vc->n_busy;
+	}
 
 	while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE &&
 	       !signal_pending(current)) {
-		if (vc->n_busy || vc->vcore_state != VCORE_INACTIVE) {
+		if (vc->vcore_state != VCORE_INACTIVE) {
 			spin_unlock(&vc->lock);
 			kvmppc_wait_for_exec(vcpu, TASK_INTERRUPTIBLE);
 			spin_lock(&vc->lock);
 			continue;
 		}
-		vc->runner = vcpu;
-		n_ceded = 0;
-		list_for_each_entry(v, &vc->runnable_threads, arch.run_list)
-			n_ceded += v->arch.ceded;
-		if (n_ceded == vc->n_runnable)
-			kvmppc_vcore_blocked(vc);
-		else
-			kvmppc_run_core(vc);
-
 		list_for_each_entry_safe(v, vn, &vc->runnable_threads,
 					 arch.run_list) {
 			kvmppc_core_prepare_to_enter(v);
@@ -1065,22 +1326,40 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 				wake_up(&v->arch.cpu_run);
 			}
 		}
+		if (!vc->n_runnable || vcpu->arch.state != KVMPPC_VCPU_RUNNABLE)
+			break;
+		vc->runner = vcpu;
+		n_ceded = 0;
+		list_for_each_entry(v, &vc->runnable_threads, arch.run_list)
+			if (!v->arch.pending_exceptions)
+				n_ceded += v->arch.ceded;
+		if (n_ceded == vc->n_runnable)
+			kvmppc_vcore_blocked(vc);
+		else
+			kvmppc_run_core(vc);
 		vc->runner = NULL;
 	}
 
-	if (signal_pending(current)) {
-		if (vc->vcore_state == VCORE_RUNNING ||
-		    vc->vcore_state == VCORE_EXITING) {
-			spin_unlock(&vc->lock);
-			kvmppc_wait_for_exec(vcpu, TASK_UNINTERRUPTIBLE);
-			spin_lock(&vc->lock);
-		}
-		if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE) {
-			kvmppc_remove_runnable(vc, vcpu);
-			vcpu->stat.signal_exits++;
-			kvm_run->exit_reason = KVM_EXIT_INTR;
-			vcpu->arch.ret = -EINTR;
-		}
+	while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE &&
+	       (vc->vcore_state == VCORE_RUNNING ||
+		vc->vcore_state == VCORE_EXITING)) {
+		spin_unlock(&vc->lock);
+		kvmppc_wait_for_exec(vcpu, TASK_UNINTERRUPTIBLE);
+		spin_lock(&vc->lock);
+	}
+
+	if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE) {
+		kvmppc_remove_runnable(vc, vcpu);
+		vcpu->stat.signal_exits++;
+		kvm_run->exit_reason = KVM_EXIT_INTR;
+		vcpu->arch.ret = -EINTR;
+	}
+
+	if (vc->n_runnable && vc->vcore_state == VCORE_INACTIVE) {
+		/* Wake up some vcpu to run the core */
+		v = list_first_entry(&vc->runnable_threads,
+				     struct kvm_vcpu, arch.run_list);
+		wake_up(&v->arch.cpu_run);
 	}
 
 	spin_unlock(&vc->lock);
@@ -1090,6 +1369,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
 {
 	int r;
+	int srcu_idx;
 
 	if (!vcpu->arch.sane) {
 		run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
@@ -1120,6 +1400,7 @@ int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
 	flush_vsx_to_thread(current);
 	vcpu->arch.wqp = &vcpu->arch.vcore->wq;
 	vcpu->arch.pgdir = current->mm->pgd;
+	vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
 
 	do {
 		r = kvmppc_run_vcpu(run, vcpu);
@@ -1128,10 +1409,16 @@ int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
 		    !(vcpu->arch.shregs.msr & MSR_PR)) {
 			r = kvmppc_pseries_do_hcall(vcpu);
 			kvmppc_core_prepare_to_enter(vcpu);
+		} else if (r == RESUME_PAGE_FAULT) {
+			srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
+			r = kvmppc_book3s_hv_page_fault(run, vcpu,
+				vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
+			srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
 		}
 	} while (r == RESUME_GUEST);
 
  out:
+	vcpu->arch.state = KVMPPC_VCPU_NOTREADY;
 	atomic_dec(&vcpu->kvm->arch.vcpus_running);
 	return r;
 }
@@ -1273,7 +1560,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
 	n = kvm_dirty_bitmap_bytes(memslot);
 	memset(memslot->dirty_bitmap, 0, n);
 
-	r = kvmppc_hv_get_dirty_log(kvm, memslot);
+	r = kvmppc_hv_get_dirty_log(kvm, memslot, memslot->dirty_bitmap);
 	if (r)
 		goto out;
 
@@ -1287,67 +1574,88 @@ out:
 	return r;
 }
 
-static unsigned long slb_pgsize_encoding(unsigned long psize)
+static void unpin_slot(struct kvm_memory_slot *memslot)
 {
-	unsigned long senc = 0;
+	unsigned long *physp;
+	unsigned long j, npages, pfn;
+	struct page *page;
 
-	if (psize > 0x1000) {
-		senc = SLB_VSID_L;
-		if (psize == 0x10000)
-			senc |= SLB_VSID_LP_01;
+	physp = memslot->arch.slot_phys;
+	npages = memslot->npages;
+	if (!physp)
+		return;
+	for (j = 0; j < npages; j++) {
+		if (!(physp[j] & KVMPPC_GOT_PAGE))
+			continue;
+		pfn = physp[j] >> PAGE_SHIFT;
+		page = pfn_to_page(pfn);
+		SetPageDirty(page);
+		put_page(page);
+	}
+}
+
+void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
+			      struct kvm_memory_slot *dont)
+{
+	if (!dont || free->arch.rmap != dont->arch.rmap) {
+		vfree(free->arch.rmap);
+		free->arch.rmap = NULL;
+	}
+	if (!dont || free->arch.slot_phys != dont->arch.slot_phys) {
+		unpin_slot(free);
+		vfree(free->arch.slot_phys);
+		free->arch.slot_phys = NULL;
 	}
-	return senc;
+}
+
+int kvmppc_core_create_memslot(struct kvm_memory_slot *slot,
+			       unsigned long npages)
+{
+	slot->arch.rmap = vzalloc(npages * sizeof(*slot->arch.rmap));
+	if (!slot->arch.rmap)
+		return -ENOMEM;
+	slot->arch.slot_phys = NULL;
+
+	return 0;
 }
 
 int kvmppc_core_prepare_memory_region(struct kvm *kvm,
-				struct kvm_userspace_memory_region *mem)
+				      struct kvm_memory_slot *memslot,
+				      struct kvm_userspace_memory_region *mem)
 {
-	unsigned long npages;
 	unsigned long *phys;
 
-	/* Allocate a slot_phys array */
-	phys = kvm->arch.slot_phys[mem->slot];
-	if (!kvm->arch.using_mmu_notifiers && !phys) {
-		npages = mem->memory_size >> PAGE_SHIFT;
-		phys = vzalloc(npages * sizeof(unsigned long));
+	/* Allocate a slot_phys array if needed */
+	phys = memslot->arch.slot_phys;
+	if (!kvm->arch.using_mmu_notifiers && !phys && memslot->npages) {
+		phys = vzalloc(memslot->npages * sizeof(unsigned long));
 		if (!phys)
 			return -ENOMEM;
-		kvm->arch.slot_phys[mem->slot] = phys;
-		kvm->arch.slot_npages[mem->slot] = npages;
+		memslot->arch.slot_phys = phys;
 	}
 
 	return 0;
 }
 
-static void unpin_slot(struct kvm *kvm, int slot_id)
+void kvmppc_core_commit_memory_region(struct kvm *kvm,
+				      struct kvm_userspace_memory_region *mem,
+				      struct kvm_memory_slot old)
 {
-	unsigned long *physp;
-	unsigned long j, npages, pfn;
-	struct page *page;
+	unsigned long npages = mem->memory_size >> PAGE_SHIFT;
+	struct kvm_memory_slot *memslot;
 
-	physp = kvm->arch.slot_phys[slot_id];
-	npages = kvm->arch.slot_npages[slot_id];
-	if (physp) {
-		spin_lock(&kvm->arch.slot_phys_lock);
-		for (j = 0; j < npages; j++) {
-			if (!(physp[j] & KVMPPC_GOT_PAGE))
-				continue;
-			pfn = physp[j] >> PAGE_SHIFT;
-			page = pfn_to_page(pfn);
-			SetPageDirty(page);
-			put_page(page);
-		}
-		kvm->arch.slot_phys[slot_id] = NULL;
-		spin_unlock(&kvm->arch.slot_phys_lock);
-		vfree(physp);
+	if (npages && old.npages) {
+		/*
+		 * If modifying a memslot, reset all the rmap dirty bits.
+		 * If this is a new memslot, we don't need to do anything
+		 * since the rmap array starts out as all zeroes,
+		 * i.e. no pages are dirty.
+		 */
+		memslot = id_to_memslot(kvm->memslots, mem->slot);
+		kvmppc_hv_get_dirty_log(kvm, memslot, NULL);
 	}
 }
 
-void kvmppc_core_commit_memory_region(struct kvm *kvm,
-				struct kvm_userspace_memory_region *mem)
-{
-}
-
 static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
 {
 	int err = 0;
@@ -1362,6 +1670,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
 	unsigned long rmls;
 	unsigned long *physp;
 	unsigned long i, npages;
+	int srcu_idx;
 
 	mutex_lock(&kvm->lock);
 	if (kvm->arch.rma_setup_done)
@@ -1377,12 +1686,13 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
 	}
 
 	/* Look up the memslot for guest physical address 0 */
+	srcu_idx = srcu_read_lock(&kvm->srcu);
 	memslot = gfn_to_memslot(kvm, 0);
 
 	/* We must have some memory at 0 by now */
 	err = -EINVAL;
 	if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
-		goto out;
+		goto out_srcu;
 
 	/* Look up the VMA for the start of this memory slot */
 	hva = memslot->userspace_addr;
@@ -1406,14 +1716,14 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
 		err = -EPERM;
 		if (cpu_has_feature(CPU_FTR_ARCH_201)) {
 			pr_err("KVM: CPU requires an RMO\n");
-			goto out;
+			goto out_srcu;
 		}
 
 		/* We can handle 4k, 64k or 16M pages in the VRMA */
 		err = -EINVAL;
 		if (!(psize == 0x1000 || psize == 0x10000 ||
 		      psize == 0x1000000))
-			goto out;
+			goto out_srcu;
 
 		/* Update VRMASD field in the LPCR */
 		senc = slb_pgsize_encoding(psize);
@@ -1436,7 +1746,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
 		err = -EINVAL;
 		if (rmls < 0) {
 			pr_err("KVM: Can't use RMA of 0x%lx bytes\n", rma_size);
-			goto out;
+			goto out_srcu;
 		}
 		atomic_inc(&ri->use_count);
 		kvm->arch.rma = ri;
@@ -1465,17 +1775,24 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
 		/* Initialize phys addrs of pages in RMO */
 		npages = ri->npages;
 		porder = __ilog2(npages);
-		physp = kvm->arch.slot_phys[memslot->id];
-		spin_lock(&kvm->arch.slot_phys_lock);
-		for (i = 0; i < npages; ++i)
-			physp[i] = ((ri->base_pfn + i) << PAGE_SHIFT) + porder;
-		spin_unlock(&kvm->arch.slot_phys_lock);
+		physp = memslot->arch.slot_phys;
+		if (physp) {
+			if (npages > memslot->npages)
+				npages = memslot->npages;
+			spin_lock(&kvm->arch.slot_phys_lock);
+			for (i = 0; i < npages; ++i)
+				physp[i] = ((ri->base_pfn + i) << PAGE_SHIFT) +
+					porder;
+			spin_unlock(&kvm->arch.slot_phys_lock);
+		}
 	}
 
 	/* Order updates to kvm->arch.lpcr etc. vs. rma_setup_done */
 	smp_wmb();
 	kvm->arch.rma_setup_done = 1;
 	err = 0;
+ out_srcu:
+	srcu_read_unlock(&kvm->srcu, srcu_idx);
  out:
 	mutex_unlock(&kvm->lock);
 	return err;
@@ -1496,6 +1813,13 @@ int kvmppc_core_init_vm(struct kvm *kvm)
 		return -ENOMEM;
 	kvm->arch.lpid = lpid;
 
+	/*
+	 * Since we don't flush the TLB when tearing down a VM,
+	 * and this lpid might have previously been used,
+	 * make sure we flush on each core before running the new VM.
+	 */
+	cpumask_setall(&kvm->arch.need_tlb_flush);
+
 	INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);
 
 	kvm->arch.rma = NULL;
@@ -1523,16 +1847,19 @@ int kvmppc_core_init_vm(struct kvm *kvm)
 
 	kvm->arch.using_mmu_notifiers = !!cpu_has_feature(CPU_FTR_ARCH_206);
 	spin_lock_init(&kvm->arch.slot_phys_lock);
+
+	/*
+	 * Don't allow secondary CPU threads to come online
+	 * while any KVM VMs exist.
+	 */
+	inhibit_secondary_onlining();
+
 	return 0;
 }
 
 void kvmppc_core_destroy_vm(struct kvm *kvm)
 {
-	unsigned long i;
-
-	if (!kvm->arch.using_mmu_notifiers)
-		for (i = 0; i < KVM_MEM_SLOTS_NUM; i++)
-			unpin_slot(kvm, i);
+	uninhibit_secondary_onlining();
 
 	if (kvm->arch.rma) {
 		kvm_release_rma(kvm->arch.rma);
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index fb4eac2..ec0a9e5 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -157,8 +157,8 @@ static void __init kvm_linear_init_one(ulong size, int count, int type)
 	linear_info = alloc_bootmem(count * sizeof(struct kvmppc_linear_info));
 	for (i = 0; i < count; ++i) {
 		linear = alloc_bootmem_align(size, size);
-		pr_info("Allocated KVM %s at %p (%ld MB)\n", typestr, linear,
-			size >> 20);
+		pr_debug("Allocated KVM %s at %p (%ld MB)\n", typestr, linear,
+			 size >> 20);
 		linear_info[i].base_virt = linear;
 		linear_info[i].base_pfn = __pa(linear) >> PAGE_SHIFT;
 		linear_info[i].npages = npages;
diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c
new file mode 100644
index 0000000..35f3cf0
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv_ras.c
@@ -0,0 +1,144 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * Copyright 2012 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <linux/kernel.h>
+#include <asm/opal.h>
+
+/* SRR1 bits for machine check on POWER7 */
+#define SRR1_MC_LDSTERR		(1ul << (63-42))
+#define SRR1_MC_IFETCH_SH	(63-45)
+#define SRR1_MC_IFETCH_MASK	0x7
+#define SRR1_MC_IFETCH_SLBPAR		2	/* SLB parity error */
+#define SRR1_MC_IFETCH_SLBMULTI		3	/* SLB multi-hit */
+#define SRR1_MC_IFETCH_SLBPARMULTI	4	/* SLB parity + multi-hit */
+#define SRR1_MC_IFETCH_TLBMULTI		5	/* I-TLB multi-hit */
+
+/* DSISR bits for machine check on POWER7 */
+#define DSISR_MC_DERAT_MULTI	0x800		/* D-ERAT multi-hit */
+#define DSISR_MC_TLB_MULTI	0x400		/* D-TLB multi-hit */
+#define DSISR_MC_SLB_PARITY	0x100		/* SLB parity error */
+#define DSISR_MC_SLB_MULTI	0x080		/* SLB multi-hit */
+#define DSISR_MC_SLB_PARMULTI	0x040		/* SLB parity + multi-hit */
+
+/* POWER7 SLB flush and reload */
+static void reload_slb(struct kvm_vcpu *vcpu)
+{
+	struct slb_shadow *slb;
+	unsigned long i, n;
+
+	/* First clear out SLB */
+	asm volatile("slbmte %0,%0; slbia" : : "r" (0));
+
+	/* Do they have an SLB shadow buffer registered? */
+	slb = vcpu->arch.slb_shadow.pinned_addr;
+	if (!slb)
+		return;
+
+	/* Sanity check */
+	n = min_t(u32, slb->persistent, SLB_MIN_SIZE);
+	if ((void *) &slb->save_area[n] > vcpu->arch.slb_shadow.pinned_end)
+		return;
+
+	/* Load up the SLB from that */
+	for (i = 0; i < n; ++i) {
+		unsigned long rb = slb->save_area[i].esid;
+		unsigned long rs = slb->save_area[i].vsid;
+
+		rb = (rb & ~0xFFFul) | i;	/* insert entry number */
+		asm volatile("slbmte %0,%1" : : "r" (rs), "r" (rb));
+	}
+}
+
+/* POWER7 TLB flush */
+static void flush_tlb_power7(struct kvm_vcpu *vcpu)
+{
+	unsigned long i, rb;
+
+	rb = TLBIEL_INVAL_SET_LPID;
+	for (i = 0; i < POWER7_TLB_SETS; ++i) {
+		asm volatile("tlbiel %0" : : "r" (rb));
+		rb += 1 << TLBIEL_INVAL_SET_SHIFT;
+	}
+}
+
+/*
+ * On POWER7, see if we can handle a machine check that occurred inside
+ * the guest in real mode, without switching to the host partition.
+ *
+ * Returns: 0 => exit guest, 1 => deliver machine check to guest
+ */
+static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
+{
+	unsigned long srr1 = vcpu->arch.shregs.msr;
+	struct opal_machine_check_event *opal_evt;
+	long handled = 1;
+
+	if (srr1 & SRR1_MC_LDSTERR) {
+		/* error on load/store */
+		unsigned long dsisr = vcpu->arch.shregs.dsisr;
+
+		if (dsisr & (DSISR_MC_SLB_PARMULTI | DSISR_MC_SLB_MULTI |
+			     DSISR_MC_SLB_PARITY | DSISR_MC_DERAT_MULTI)) {
+			/* flush and reload SLB; flushes D-ERAT too */
+			reload_slb(vcpu);
+			dsisr &= ~(DSISR_MC_SLB_PARMULTI | DSISR_MC_SLB_MULTI |
+				   DSISR_MC_SLB_PARITY | DSISR_MC_DERAT_MULTI);
+		}
+		if (dsisr & DSISR_MC_TLB_MULTI) {
+			flush_tlb_power7(vcpu);
+			dsisr &= ~DSISR_MC_TLB_MULTI;
+		}
+		/* Any other errors we don't understand? */
+		if (dsisr & 0xffffffffUL)
+			handled = 0;
+	}
+
+	switch ((srr1 >> SRR1_MC_IFETCH_SH) & SRR1_MC_IFETCH_MASK) {
+	case 0:
+		break;
+	case SRR1_MC_IFETCH_SLBPAR:
+	case SRR1_MC_IFETCH_SLBMULTI:
+	case SRR1_MC_IFETCH_SLBPARMULTI:
+		reload_slb(vcpu);
+		break;
+	case SRR1_MC_IFETCH_TLBMULTI:
+		flush_tlb_power7(vcpu);
+		break;
+	default:
+		handled = 0;
+	}
+
+	/*
+	 * See if OPAL has already handled the condition.
+	 * We assume that if the condition is recovered then OPAL
+	 * will have generated an error log event that we will pick
+	 * up and log later.
+	 */
+	opal_evt = local_paca->opal_mc_evt;
+	if (opal_evt->version == OpalMCE_V1 &&
+	    (opal_evt->severity == OpalMCE_SEV_NO_ERROR ||
+	     opal_evt->disposition == OpalMCE_DISPOSITION_RECOVERED))
+		handled = 1;
+
+	if (handled)
+		opal_evt->in_use = 0;
+
+	return handled;
+}
+
+long kvmppc_realmode_machine_check(struct kvm_vcpu *vcpu)
+{
+	if (cpu_has_feature(CPU_FTR_ARCH_206))
+		return kvmppc_realmode_mc_power7(vcpu);
+
+	return 0;
+}
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index fb0e821..19c93ba 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -35,6 +35,37 @@ static void *real_vmalloc_addr(void *x)
 	return __va(addr);
 }
 
+/* Return 1 if we need to do a global tlbie, 0 if we can use tlbiel */
+static int global_invalidates(struct kvm *kvm, unsigned long flags)
+{
+	int global;
+
+	/*
+	 * If there is only one vcore, and it's currently running,
+	 * we can use tlbiel as long as we mark all other physical
+	 * cores as potentially having stale TLB entries for this lpid.
+	 * If we're not using MMU notifiers, we never take pages away
+	 * from the guest, so we can use tlbiel if requested.
+	 * Otherwise, don't use tlbiel.
+	 */
+	if (kvm->arch.online_vcores == 1 && local_paca->kvm_hstate.kvm_vcore)
+		global = 0;
+	else if (kvm->arch.using_mmu_notifiers)
+		global = 1;
+	else
+		global = !(flags & H_LOCAL);
+
+	if (!global) {
+		/* any other core might now have stale TLB entries... */
+		smp_wmb();
+		cpumask_setall(&kvm->arch.need_tlb_flush);
+		cpumask_clear_cpu(local_paca->kvm_hstate.kvm_vcore->pcpu,
+				  &kvm->arch.need_tlb_flush);
+	}
+
+	return global;
+}
+
 /*
  * Add this HPTE into the chain for the real page.
  * Must be called with the chain locked; it unlocks the chain.
@@ -59,13 +90,24 @@ void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev,
 		head->back = pte_index;
 	} else {
 		rev->forw = rev->back = pte_index;
-		i = pte_index;
+		*rmap = (*rmap & ~KVMPPC_RMAP_INDEX) |
+			pte_index | KVMPPC_RMAP_PRESENT;
 	}
-	smp_wmb();
-	*rmap = i | KVMPPC_RMAP_REFERENCED | KVMPPC_RMAP_PRESENT; /* unlock */
+	unlock_rmap(rmap);
 }
 EXPORT_SYMBOL_GPL(kvmppc_add_revmap_chain);
 
+/*
+ * Note modification of an HPTE; set the HPTE modified bit
+ * if anyone is interested.
+ */
+static inline void note_hpte_modification(struct kvm *kvm,
+					  struct revmap_entry *rev)
+{
+	if (atomic_read(&kvm->arch.hpte_mod_interest))
+		rev->guest_rpte |= HPTE_GR_MODIFIED;
+}
+
 /* Remove this HPTE from the chain for a real page */
 static void remove_revmap_chain(struct kvm *kvm, long pte_index,
 				struct revmap_entry *rev,
@@ -81,7 +123,7 @@ static void remove_revmap_chain(struct kvm *kvm, long pte_index,
 	ptel = rev->guest_rpte |= rcbits;
 	gfn = hpte_rpn(ptel, hpte_page_size(hpte_v, ptel));
 	memslot = __gfn_to_memslot(kvm_memslots(kvm), gfn);
-	if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
+	if (!memslot)
 		return;
 
 	rmap = real_vmalloc_addr(&memslot->arch.rmap[gfn - memslot->base_gfn]);
@@ -103,14 +145,14 @@ static void remove_revmap_chain(struct kvm *kvm, long pte_index,
 	unlock_rmap(rmap);
 }
 
-static pte_t lookup_linux_pte(struct kvm_vcpu *vcpu, unsigned long hva,
+static pte_t lookup_linux_pte(pgd_t *pgdir, unsigned long hva,
 			      int writing, unsigned long *pte_sizep)
 {
 	pte_t *ptep;
 	unsigned long ps = *pte_sizep;
 	unsigned int shift;
 
-	ptep = find_linux_pte_or_hugepte(vcpu->arch.pgdir, hva, &shift);
+	ptep = find_linux_pte_or_hugepte(pgdir, hva, &shift);
 	if (!ptep)
 		return __pte(0);
 	if (shift)
@@ -130,15 +172,15 @@ static inline void unlock_hpte(unsigned long *hpte, unsigned long hpte_v)
 	hpte[0] = hpte_v;
 }
 
-long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
-		    long pte_index, unsigned long pteh, unsigned long ptel)
+long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
+		       long pte_index, unsigned long pteh, unsigned long ptel,
+		       pgd_t *pgdir, bool realmode, unsigned long *pte_idx_ret)
 {
-	struct kvm *kvm = vcpu->kvm;
 	unsigned long i, pa, gpa, gfn, psize;
 	unsigned long slot_fn, hva;
 	unsigned long *hpte;
 	struct revmap_entry *rev;
-	unsigned long g_ptel = ptel;
+	unsigned long g_ptel;
 	struct kvm_memory_slot *memslot;
 	unsigned long *physp, pte_size;
 	unsigned long is_io;
@@ -147,13 +189,14 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 	unsigned int writing;
 	unsigned long mmu_seq;
 	unsigned long rcbits;
-	bool realmode = vcpu->arch.vcore->vcore_state == VCORE_RUNNING;
 
 	psize = hpte_page_size(pteh, ptel);
 	if (!psize)
 		return H_PARAMETER;
 	writing = hpte_is_writable(ptel);
 	pteh &= ~(HPTE_V_HVLOCK | HPTE_V_ABSENT | HPTE_V_VALID);
+	ptel &= ~HPTE_GR_RESERVED;
+	g_ptel = ptel;
 
 	/* used later to detect if we might have been invalidated */
 	mmu_seq = kvm->mmu_notifier_seq;
@@ -183,7 +226,7 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 	rmap = &memslot->arch.rmap[slot_fn];
 
 	if (!kvm->arch.using_mmu_notifiers) {
-		physp = kvm->arch.slot_phys[memslot->id];
+		physp = memslot->arch.slot_phys;
 		if (!physp)
 			return H_PARAMETER;
 		physp += slot_fn;
@@ -201,7 +244,7 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 
 		/* Look up the Linux PTE for the backing page */
 		pte_size = psize;
-		pte = lookup_linux_pte(vcpu, hva, writing, &pte_size);
+		pte = lookup_linux_pte(pgdir, hva, writing, &pte_size);
 		if (pte_present(pte)) {
 			if (writing && !pte_write(pte))
 				/* make the actual HPTE be read-only */
@@ -210,6 +253,7 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 			pa = pte_pfn(pte) << PAGE_SHIFT;
 		}
 	}
+
 	if (pte_size < psize)
 		return H_PARAMETER;
 	if (pa && pte_size > psize)
@@ -287,8 +331,10 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 	rev = &kvm->arch.revmap[pte_index];
 	if (realmode)
 		rev = real_vmalloc_addr(rev);
-	if (rev)
+	if (rev) {
 		rev->guest_rpte = g_ptel;
+		note_hpte_modification(kvm, rev);
+	}
 
 	/* Link HPTE into reverse-map chain */
 	if (pteh & HPTE_V_VALID) {
@@ -297,7 +343,7 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 		lock_rmap(rmap);
 		/* Check for pending invalidations under the rmap chain lock */
 		if (kvm->arch.using_mmu_notifiers &&
-		    mmu_notifier_retry(vcpu, mmu_seq)) {
+		    mmu_notifier_retry(kvm, mmu_seq)) {
 			/* inval in progress, write a non-present HPTE */
 			pteh |= HPTE_V_ABSENT;
 			pteh &= ~HPTE_V_VALID;
@@ -318,10 +364,17 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 	hpte[0] = pteh;
 	asm volatile("ptesync" : : : "memory");
 
-	vcpu->arch.gpr[4] = pte_index;
+	*pte_idx_ret = pte_index;
 	return H_SUCCESS;
 }
-EXPORT_SYMBOL_GPL(kvmppc_h_enter);
+EXPORT_SYMBOL_GPL(kvmppc_do_h_enter);
+
+long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
+		    long pte_index, unsigned long pteh, unsigned long ptel)
+{
+	return kvmppc_do_h_enter(vcpu->kvm, flags, pte_index, pteh, ptel,
+				 vcpu->arch.pgdir, true, &vcpu->arch.gpr[4]);
+}
 
 #define LOCK_TOKEN	(*(u32 *)(&get_paca()->lock_token))
 
@@ -343,11 +396,10 @@ static inline int try_lock_tlbie(unsigned int *lock)
 	return old == 0;
 }
 
-long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
-		     unsigned long pte_index, unsigned long avpn,
-		     unsigned long va)
+long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags,
+			unsigned long pte_index, unsigned long avpn,
+			unsigned long *hpret)
 {
-	struct kvm *kvm = vcpu->kvm;
 	unsigned long *hpte;
 	unsigned long v, r, rb;
 	struct revmap_entry *rev;
@@ -369,7 +421,7 @@ long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
 	if (v & HPTE_V_VALID) {
 		hpte[0] &= ~HPTE_V_VALID;
 		rb = compute_tlbie_rb(v, hpte[1], pte_index);
-		if (!(flags & H_LOCAL) && atomic_read(&kvm->online_vcpus) > 1) {
+		if (global_invalidates(kvm, flags)) {
 			while (!try_lock_tlbie(&kvm->arch.tlbie_lock))
 				cpu_relax();
 			asm volatile("ptesync" : : : "memory");
@@ -385,13 +437,22 @@ long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
 		/* Read PTE low word after tlbie to get final R/C values */
 		remove_revmap_chain(kvm, pte_index, rev, v, hpte[1]);
 	}
-	r = rev->guest_rpte;
+	r = rev->guest_rpte & ~HPTE_GR_RESERVED;
+	note_hpte_modification(kvm, rev);
 	unlock_hpte(hpte, 0);
 
-	vcpu->arch.gpr[4] = v;
-	vcpu->arch.gpr[5] = r;
+	hpret[0] = v;
+	hpret[1] = r;
 	return H_SUCCESS;
 }
+EXPORT_SYMBOL_GPL(kvmppc_do_h_remove);
+
+long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
+		     unsigned long pte_index, unsigned long avpn)
+{
+	return kvmppc_do_h_remove(vcpu->kvm, flags, pte_index, avpn,
+				  &vcpu->arch.gpr[4]);
+}
 
 long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
 {
@@ -459,6 +520,7 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
 
 			args[j] = ((0x80 | flags) << 56) + pte_index;
 			rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
+			note_hpte_modification(kvm, rev);
 
 			if (!(hp[0] & HPTE_V_VALID)) {
 				/* insert R and C bits from PTE */
@@ -534,8 +596,6 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
 		return H_NOT_FOUND;
 	}
 
-	if (atomic_read(&kvm->online_vcpus) == 1)
-		flags |= H_LOCAL;
 	v = hpte[0];
 	bits = (flags << 55) & HPTE_R_PP0;
 	bits |= (flags << 48) & HPTE_R_KEY_HI;
@@ -548,6 +608,7 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
 	if (rev) {
 		r = (rev->guest_rpte & ~mask) | bits;
 		rev->guest_rpte = r;
+		note_hpte_modification(kvm, rev);
 	}
 	r = (hpte[1] & ~mask) | bits;
 
@@ -555,7 +616,7 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
 	if (v & HPTE_V_VALID) {
 		rb = compute_tlbie_rb(v, r, pte_index);
 		hpte[0] = v & ~HPTE_V_VALID;
-		if (!(flags & H_LOCAL)) {
+		if (global_invalidates(kvm, flags)) {
 			while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
 				cpu_relax();
 			asm volatile("ptesync" : : : "memory");
@@ -568,6 +629,28 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
 			asm volatile("tlbiel %0" : : "r" (rb));
 			asm volatile("ptesync" : : : "memory");
 		}
+		/*
+		 * If the host has this page as readonly but the guest
+		 * wants to make it read/write, reduce the permissions.
+		 * Checking the host permissions involves finding the
+		 * memslot and then the Linux PTE for the page.
+		 */
+		if (hpte_is_writable(r) && kvm->arch.using_mmu_notifiers) {
+			unsigned long psize, gfn, hva;
+			struct kvm_memory_slot *memslot;
+			pgd_t *pgdir = vcpu->arch.pgdir;
+			pte_t pte;
+
+			psize = hpte_page_size(v, r);
+			gfn = ((r & HPTE_R_RPN) & ~(psize - 1)) >> PAGE_SHIFT;
+			memslot = __gfn_to_memslot(kvm_memslots(kvm), gfn);
+			if (memslot) {
+				hva = __gfn_to_hva_memslot(memslot, gfn);
+				pte = lookup_linux_pte(pgdir, hva, 1, &psize);
+				if (pte_present(pte) && !pte_write(pte))
+					r = hpte_make_readonly(r);
+			}
+		}
 	}
 	hpte[1] = r;
 	eieio();
@@ -599,8 +682,10 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
 			v &= ~HPTE_V_ABSENT;
 			v |= HPTE_V_VALID;
 		}
-		if (v & HPTE_V_VALID)
+		if (v & HPTE_V_VALID) {
 			r = rev[i].guest_rpte | (r & (HPTE_R_R | HPTE_R_C));
+			r &= ~HPTE_GR_RESERVED;
+		}
 		vcpu->arch.gpr[4 + i * 2] = v;
 		vcpu->arch.gpr[5 + i * 2] = r;
 	}
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 74a24bb..10b6c35 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -27,6 +27,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/exception-64s.h>
 #include <asm/kvm_book3s_asm.h>
+#include <asm/mmu-hash64.h>
 
 /*****************************************************************************
  *                                                                           *
@@ -134,8 +135,11 @@ kvm_start_guest:
 
 27:	/* XXX should handle hypervisor maintenance interrupts etc. here */
 
+	/* reload vcpu pointer after clearing the IPI */
+	ld	r4,HSTATE_KVM_VCPU(r13)
+	cmpdi	r4,0
 	/* if we have no vcpu to run, go back to sleep */
-	beq	cr1,kvm_no_guest
+	beq	kvm_no_guest
 
 	/* were we napping due to cede? */
 	lbz	r0,HSTATE_NAPPING(r13)
@@ -310,7 +314,33 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
 	mtspr	SPRN_SDR1,r6		/* switch to partition page table */
 	mtspr	SPRN_LPID,r7
 	isync
+
+	/* See if we need to flush the TLB */
+	lhz	r6,PACAPACAINDEX(r13)	/* test_bit(cpu, need_tlb_flush) */
+	clrldi	r7,r6,64-6		/* extract bit number (6 bits) */
+	srdi	r6,r6,6			/* doubleword number */
+	sldi	r6,r6,3			/* address offset */
+	add	r6,r6,r9
+	addi	r6,r6,KVM_NEED_FLUSH	/* dword in kvm->arch.need_tlb_flush */
 	li	r0,1
+	sld	r0,r0,r7
+	ld	r7,0(r6)
+	and.	r7,r7,r0
+	beq	22f
+23:	ldarx	r7,0,r6			/* if set, clear the bit */
+	andc	r7,r7,r0
+	stdcx.	r7,0,r6
+	bne	23b
+	li	r6,128			/* and flush the TLB */
+	mtctr	r6
+	li	r7,0x800		/* IS field = 0b10 */
+	ptesync
+28:	tlbiel	r7
+	addi	r7,r7,0x1000
+	bdnz	28b
+	ptesync
+
+22:	li	r0,1
 	stb	r0,VCORE_IN_GUEST(r5)	/* signal secondaries to continue */
 	b	10f
 
@@ -333,36 +363,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
 	mr	r9,r4
 	blt	hdec_soon
 
-	/*
-	 * Invalidate the TLB if we could possibly have stale TLB
-	 * entries for this partition on this core due to the use
-	 * of tlbiel.
-	 * XXX maybe only need this on primary thread?
-	 */
-	ld	r9,VCPU_KVM(r4)		/* pointer to struct kvm */
-	lwz	r5,VCPU_VCPUID(r4)
-	lhz	r6,PACAPACAINDEX(r13)
-	rldimi	r6,r5,0,62		/* XXX map as if threads 1:1 p:v */
-	lhz	r8,VCPU_LAST_CPU(r4)
-	sldi	r7,r6,1			/* see if this is the same vcpu */
-	add	r7,r7,r9		/* as last ran on this pcpu */
-	lhz	r0,KVM_LAST_VCPU(r7)
-	cmpw	r6,r8			/* on the same cpu core as last time? */
-	bne	3f
-	cmpw	r0,r5			/* same vcpu as this core last ran? */
-	beq	1f
-3:	sth	r6,VCPU_LAST_CPU(r4)	/* if not, invalidate partition TLB */
-	sth	r5,KVM_LAST_VCPU(r7)
-	li	r6,128
-	mtctr	r6
-	li	r7,0x800		/* IS field = 0b10 */
-	ptesync
-2:	tlbiel	r7
-	addi	r7,r7,0x1000
-	bdnz	2b
-	ptesync
-1:
-
 	/* Save purr/spurr */
 	mfspr	r5,SPRN_PURR
 	mfspr	r6,SPRN_SPURR
@@ -679,8 +679,7 @@ BEGIN_FTR_SECTION
 1:
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
-nohpte_cont:
-hcall_real_cont:		/* r9 = vcpu, r12 = trap, r13 = paca */
+guest_exit_cont:		/* r9 = vcpu, r12 = trap, r13 = paca */
 	/* Save DEC */
 	mfspr	r5,SPRN_DEC
 	mftb	r6
@@ -701,6 +700,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 	std	r6, VCPU_FAULT_DAR(r9)
 	stw	r7, VCPU_FAULT_DSISR(r9)
 
+	/* See if it is a machine check */
+	cmpwi	r12, BOOK3S_INTERRUPT_MACHINE_CHECK
+	beq	machine_check_realmode
+mc_cont:
+
 	/* Save guest CTRL register, set runlatch to 1 */
 6:	mfspr	r6,SPRN_CTRLF
 	stw	r6,VCPU_CTRL(r9)
@@ -1113,38 +1117,41 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
 	/*
 	 * For external and machine check interrupts, we need
 	 * to call the Linux handler to process the interrupt.
-	 * We do that by jumping to the interrupt vector address
-	 * which we have in r12.  The [h]rfid at the end of the
+	 * We do that by jumping to absolute address 0x500 for
+	 * external interrupts, or the machine_check_fwnmi label
+	 * for machine checks (since firmware might have patched
+	 * the vector area at 0x200).  The [h]rfid at the end of the
 	 * handler will return to the book3s_hv_interrupts.S code.
 	 * For other interrupts we do the rfid to get back
-	 * to the book3s_interrupts.S code here.
+	 * to the book3s_hv_interrupts.S code here.
 	 */
 	ld	r8, HSTATE_VMHANDLER(r13)
 	ld	r7, HSTATE_HOST_MSR(r13)
 
+	cmpwi	cr1, r12, BOOK3S_INTERRUPT_MACHINE_CHECK
 	cmpwi	r12, BOOK3S_INTERRUPT_EXTERNAL
+BEGIN_FTR_SECTION
 	beq	11f
-	cmpwi	r12, BOOK3S_INTERRUPT_MACHINE_CHECK
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
 	/* RFI into the highmem handler, or branch to interrupt handler */
-12:	mfmsr	r6
-	mtctr	r12
+	mfmsr	r6
 	li	r0, MSR_RI
 	andc	r6, r6, r0
 	mtmsrd	r6, 1			/* Clear RI in MSR */
 	mtsrr0	r8
 	mtsrr1	r7
-	beqctr
+	beqa	0x500			/* external interrupt (PPC970) */
+	beq	cr1, 13f		/* machine check */
 	RFI
 
-11:
-BEGIN_FTR_SECTION
-	b	12b
-END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
-	mtspr	SPRN_HSRR0, r8
+	/* On POWER7, we have external interrupts set to use HSRR0/1 */
+11:	mtspr	SPRN_HSRR0, r8
 	mtspr	SPRN_HSRR1, r7
 	ba	0x500
 
+13:	b	machine_check_fwnmi
+
 /*
  * Check whether an HDSI is an HPTE not found fault or something else.
  * If it is an HPTE not found fault that is due to the guest accessing
@@ -1177,7 +1184,7 @@ kvmppc_hdsi:
 	cmpdi	r3, 0			/* retry the instruction */
 	beq	6f
 	cmpdi	r3, -1			/* handle in kernel mode */
-	beq	nohpte_cont
+	beq	guest_exit_cont
 	cmpdi	r3, -2			/* MMIO emulation; need instr word */
 	beq	2f
 
@@ -1191,6 +1198,7 @@ kvmppc_hdsi:
 	li	r10, BOOK3S_INTERRUPT_DATA_STORAGE
 	li	r11, (MSR_ME << 1) | 1	/* synthesize MSR_SF | MSR_ME */
 	rotldi	r11, r11, 63
+fast_interrupt_c_return:
 6:	ld	r7, VCPU_CTR(r9)
 	lwz	r8, VCPU_XER(r9)
 	mtctr	r7
@@ -1223,7 +1231,7 @@ kvmppc_hdsi:
 	/* Unset guest mode. */
 	li	r0, KVM_GUEST_MODE_NONE
 	stb	r0, HSTATE_IN_GUEST(r13)
-	b	nohpte_cont
+	b	guest_exit_cont
 
 /*
  * Similarly for an HISI, reflect it to the guest as an ISI unless
@@ -1249,9 +1257,9 @@ kvmppc_hisi:
 	ld	r11, VCPU_MSR(r9)
 	li	r12, BOOK3S_INTERRUPT_H_INST_STORAGE
 	cmpdi	r3, 0			/* retry the instruction */
-	beq	6f
+	beq	fast_interrupt_c_return
 	cmpdi	r3, -1			/* handle in kernel mode */
-	beq	nohpte_cont
+	beq	guest_exit_cont
 
 	/* Synthesize an ISI for the guest */
 	mr	r11, r3
@@ -1260,12 +1268,7 @@ kvmppc_hisi:
 	li	r10, BOOK3S_INTERRUPT_INST_STORAGE
 	li	r11, (MSR_ME << 1) | 1	/* synthesize MSR_SF | MSR_ME */
 	rotldi	r11, r11, 63
-6:	ld	r7, VCPU_CTR(r9)
-	lwz	r8, VCPU_XER(r9)
-	mtctr	r7
-	mtxer	r8
-	mr	r4, r9
-	b	fast_guest_return
+	b	fast_interrupt_c_return
 
 3:	ld	r6, VCPU_KVM(r9)	/* not relocated, use VRMA */
 	ld	r5, KVM_VRMA_SLB_V(r6)
@@ -1281,14 +1284,14 @@ kvmppc_hisi:
 hcall_try_real_mode:
 	ld	r3,VCPU_GPR(R3)(r9)
 	andi.	r0,r11,MSR_PR
-	bne	hcall_real_cont
+	bne	guest_exit_cont
 	clrrdi	r3,r3,2
 	cmpldi	r3,hcall_real_table_end - hcall_real_table
-	bge	hcall_real_cont
+	bge	guest_exit_cont
 	LOAD_REG_ADDR(r4, hcall_real_table)
 	lwzx	r3,r3,r4
 	cmpwi	r3,0
-	beq	hcall_real_cont
+	beq	guest_exit_cont
 	add	r3,r3,r4
 	mtctr	r3
 	mr	r3,r9		/* get vcpu pointer */
@@ -1309,7 +1312,7 @@ hcall_real_fallback:
 	li	r12,BOOK3S_INTERRUPT_SYSCALL
 	ld	r9, HSTATE_KVM_VCPU(r13)
 
-	b	hcall_real_cont
+	b	guest_exit_cont
 
 	.globl	hcall_real_table
 hcall_real_table:
@@ -1568,6 +1571,21 @@ kvm_cede_exit:
 	li	r3,H_TOO_HARD
 	blr
 
+	/* Try to handle a machine check in real mode */
+machine_check_realmode:
+	mr	r3, r9		/* get vcpu pointer */
+	bl	.kvmppc_realmode_machine_check
+	nop
+	cmpdi	r3, 0		/* continue exiting from guest? */
+	ld	r9, HSTATE_KVM_VCPU(r13)
+	li	r12, BOOK3S_INTERRUPT_MACHINE_CHECK
+	beq	mc_cont
+	/* If not, deliver a machine check.  SRR0/1 are already set */
+	li	r10, BOOK3S_INTERRUPT_MACHINE_CHECK
+	li	r11, (MSR_ME << 1) | 1	/* synthesize MSR_SF | MSR_ME */
+	rotldi	r11, r11, 63
+	b	fast_interrupt_c_return
+
 secondary_too_late:
 	ld	r5,HSTATE_KVM_VCORE(r13)
 	HMT_LOW
@@ -1587,6 +1605,10 @@ secondary_too_late:
 	.endr
 
 secondary_nap:
+	/* Clear our vcpu pointer so we don't come back in early */
+	li	r0, 0
+	std	r0, HSTATE_KVM_VCPU(r13)
+	lwsync
 	/* Clear any pending IPI - assume we're a secondary thread */
 	ld	r5, HSTATE_XICS_PHYS(r13)
 	li	r7, XICS_XIRR
@@ -1612,8 +1634,6 @@ secondary_nap:
 kvm_no_guest:
 	li	r0, KVM_HWTHREAD_IN_NAP
 	stb	r0, HSTATE_HWTHREAD_STATE(r13)
-	li	r0, 0
-	std	r0, HSTATE_KVM_VCPU(r13)
 
 	li	r3, LPCR_PECE0
 	mfspr	r4, SPRN_LPCR
diff --git a/arch/powerpc/kvm/book3s_mmu_hpte.c b/arch/powerpc/kvm/book3s_mmu_hpte.c
index 41cb001..2c86b0d 100644
--- a/arch/powerpc/kvm/book3s_mmu_hpte.c
+++ b/arch/powerpc/kvm/book3s_mmu_hpte.c
@@ -114,11 +114,6 @@ static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
 	hlist_del_init_rcu(&pte->list_vpte);
 	hlist_del_init_rcu(&pte->list_vpte_long);
 
-	if (pte->pte.may_write)
-		kvm_release_pfn_dirty(pte->pfn);
-	else
-		kvm_release_pfn_clean(pte->pfn);
-
 	spin_unlock(&vcpu3s->mmu_lock);
 
 	vcpu3s->hpte_cache_count--;
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 05c28f5..28d38ad 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -52,8 +52,6 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
 #define MSR_USER32 MSR_USER
 #define MSR_USER64 MSR_USER
 #define HW_PAGE_SIZE PAGE_SIZE
-#define __hard_irq_disable local_irq_disable
-#define __hard_irq_enable local_irq_enable
 #endif
 
 void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
@@ -66,7 +64,7 @@ void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 	svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max;
 	svcpu_put(svcpu);
 #endif
-
+	vcpu->cpu = smp_processor_id();
 #ifdef CONFIG_PPC_BOOK3S_32
 	current->thread.kvm_shadow_vcpu = to_book3s(vcpu)->shadow_vcpu;
 #endif
@@ -83,17 +81,71 @@ void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
 	svcpu_put(svcpu);
 #endif
 
-	kvmppc_giveup_ext(vcpu, MSR_FP);
-	kvmppc_giveup_ext(vcpu, MSR_VEC);
-	kvmppc_giveup_ext(vcpu, MSR_VSX);
+	kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX);
+	vcpu->cpu = -1;
+}
+
+int kvmppc_core_check_requests(struct kvm_vcpu *vcpu)
+{
+	int r = 1; /* Indicate we want to get back into the guest */
+
+	/* We misuse TLB_FLUSH to indicate that we want to clear
+	   all shadow cache entries */
+	if (kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu))
+		kvmppc_mmu_pte_flush(vcpu, 0, 0);
+
+	return r;
+}
+
+/************* MMU Notifiers *************/
+
+int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
+{
+	trace_kvm_unmap_hva(hva);
+
+	/*
+	 * Flush all shadow tlb entries everywhere. This is slow, but
+	 * we are 100% sure that we catch the to be unmapped page
+	 */
+	kvm_flush_remote_tlbs(kvm);
+
+	return 0;
+}
+
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+{
+	/* kvm_unmap_hva flushes everything anyways */
+	kvm_unmap_hva(kvm, start);
+
+	return 0;
+}
+
+int kvm_age_hva(struct kvm *kvm, unsigned long hva)
+{
+	/* XXX could be more clever ;) */
+	return 0;
+}
+
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
+{
+	/* XXX could be more clever ;) */
+	return 0;
 }
 
+void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
+{
+	/* The page will get remapped properly on its next fault */
+	kvm_unmap_hva(kvm, hva);
+}
+
+/*****************************************/
+
 static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
 {
 	ulong smsr = vcpu->arch.shared->msr;
 
 	/* Guest MSR values */
-	smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_DE;
+	smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE;
 	/* Process MSR values */
 	smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
 	/* External providers the guest reserved */
@@ -379,10 +431,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
 static inline int get_fpr_index(int i)
 {
-#ifdef CONFIG_VSX
-	i *= 2;
-#endif
-	return i;
+	return i * TS_FPRWIDTH;
 }
 
 /* Give up external provider (FPU, Altivec, VSX) */
@@ -396,41 +445,49 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)
 	u64 *thread_fpr = (u64*)t->fpr;
 	int i;
 
-	if (!(vcpu->arch.guest_owned_ext & msr))
+	/*
+	 * VSX instructions can access FP and vector registers, so if
+	 * we are giving up VSX, make sure we give up FP and VMX as well.
+	 */
+	if (msr & MSR_VSX)
+		msr |= MSR_FP | MSR_VEC;
+
+	msr &= vcpu->arch.guest_owned_ext;
+	if (!msr)
 		return;
 
 #ifdef DEBUG_EXT
 	printk(KERN_INFO "Giving up ext 0x%lx\n", msr);
 #endif
 
-	switch (msr) {
-	case MSR_FP:
+	if (msr & MSR_FP) {
+		/*
+		 * Note that on CPUs with VSX, giveup_fpu stores
+		 * both the traditional FP registers and the added VSX
+		 * registers into thread.fpr[].
+		 */
 		giveup_fpu(current);
 		for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
 			vcpu_fpr[i] = thread_fpr[get_fpr_index(i)];
 
 		vcpu->arch.fpscr = t->fpscr.val;
-		break;
-	case MSR_VEC:
+
+#ifdef CONFIG_VSX
+		if (cpu_has_feature(CPU_FTR_VSX))
+			for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr) / 2; i++)
+				vcpu_vsx[i] = thread_fpr[get_fpr_index(i) + 1];
+#endif
+	}
+
 #ifdef CONFIG_ALTIVEC
+	if (msr & MSR_VEC) {
 		giveup_altivec(current);
 		memcpy(vcpu->arch.vr, t->vr, sizeof(vcpu->arch.vr));
 		vcpu->arch.vscr = t->vscr;
-#endif
-		break;
-	case MSR_VSX:
-#ifdef CONFIG_VSX
-		__giveup_vsx(current);
-		for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr); i++)
-			vcpu_vsx[i] = thread_fpr[get_fpr_index(i) + 1];
-#endif
-		break;
-	default:
-		BUG();
 	}
+#endif
 
-	vcpu->arch.guest_owned_ext &= ~msr;
-	current->thread.regs->msr &= ~msr;
+	vcpu->arch.guest_owned_ext &= ~(msr | MSR_VSX);
 	kvmppc_recalc_shadow_msr(vcpu);
 }
 
@@ -490,47 +547,56 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
 		return RESUME_GUEST;
 	}
 
-	/* We already own the ext */
-	if (vcpu->arch.guest_owned_ext & msr) {
-		return RESUME_GUEST;
+	if (msr == MSR_VSX) {
+		/* No VSX?  Give an illegal instruction interrupt */
+#ifdef CONFIG_VSX
+		if (!cpu_has_feature(CPU_FTR_VSX))
+#endif
+		{
+			kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
+			return RESUME_GUEST;
+		}
+
+		/*
+		 * We have to load up all the FP and VMX registers before
+		 * we can let the guest use VSX instructions.
+		 */
+		msr = MSR_FP | MSR_VEC | MSR_VSX;
 	}
 
+	/* See if we already own all the ext(s) needed */
+	msr &= ~vcpu->arch.guest_owned_ext;
+	if (!msr)
+		return RESUME_GUEST;
+
 #ifdef DEBUG_EXT
 	printk(KERN_INFO "Loading up ext 0x%lx\n", msr);
 #endif
 
 	current->thread.regs->msr |= msr;
 
-	switch (msr) {
-	case MSR_FP:
+	if (msr & MSR_FP) {
 		for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
 			thread_fpr[get_fpr_index(i)] = vcpu_fpr[i];
-
+#ifdef CONFIG_VSX
+		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->fpexc_mode = 0;
 		kvmppc_load_up_fpu();
-		break;
-	case MSR_VEC:
+	}
+
+	if (msr & MSR_VEC) {
 #ifdef CONFIG_ALTIVEC
 		memcpy(t->vr, vcpu->arch.vr, sizeof(vcpu->arch.vr));
 		t->vscr = vcpu->arch.vscr;
 		t->vrsave = -1;
 		kvmppc_load_up_altivec();
 #endif
-		break;
-	case MSR_VSX:
-#ifdef CONFIG_VSX
-		for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr); i++)
-			thread_fpr[get_fpr_index(i) + 1] = vcpu_vsx[i];
-		kvmppc_load_up_vsx();
-#endif
-		break;
-	default:
-		BUG();
 	}
 
 	vcpu->arch.guest_owned_ext |= msr;
-
 	kvmppc_recalc_shadow_msr(vcpu);
 
 	return RESUME_GUEST;
@@ -540,18 +606,18 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        unsigned int exit_nr)
 {
 	int r = RESUME_HOST;
+	int s;
 
 	vcpu->stat.sum_exits++;
 
 	run->exit_reason = KVM_EXIT_UNKNOWN;
 	run->ready_for_interrupt_injection = 1;
 
-	/* We get here with MSR.EE=0, so enable it to be a nice citizen */
-	__hard_irq_enable();
+	/* We get here with MSR.EE=1 */
+
+	trace_kvm_exit(exit_nr, vcpu);
+	kvm_guest_exit();
 
-	trace_kvm_book3s_exit(exit_nr, vcpu);
-	preempt_enable();
-	kvm_resched(vcpu);
 	switch (exit_nr) {
 	case BOOK3S_INTERRUPT_INST_STORAGE:
 	{
@@ -802,7 +868,6 @@ program_interrupt:
 	}
 	}
 
-	preempt_disable();
 	if (!(r & RESUME_HOST)) {
 		/* To avoid clobbering exit_reason, only check for signals if
 		 * we aren't already exiting to userspace for some other
@@ -814,20 +879,13 @@ program_interrupt:
 		 * and if we really did time things so badly, then we just exit
 		 * again due to a host external interrupt.
 		 */
-		__hard_irq_disable();
-		if (signal_pending(current)) {
-			__hard_irq_enable();
-#ifdef EXIT_DEBUG
-			printk(KERN_EMERG "KVM: Going back to host\n");
-#endif
-			vcpu->stat.signal_exits++;
-			run->exit_reason = KVM_EXIT_INTR;
-			r = -EINTR;
+		local_irq_disable();
+		s = kvmppc_prepare_to_enter(vcpu);
+		if (s <= 0) {
+			local_irq_enable();
+			r = s;
 		} else {
-			/* In case an interrupt came in that was triggered
-			 * from userspace (like DEC), we need to check what
-			 * to inject now! */
-			kvmppc_core_prepare_to_enter(vcpu);
+			kvmppc_lazy_ee_enable();
 		}
 	}
 
@@ -899,34 +957,59 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 	return 0;
 }
 
-int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
 {
-	int r = -EINVAL;
+	int r = 0;
 
-	switch (reg->id) {
+	switch (id) {
 	case KVM_REG_PPC_HIOR:
-		r = copy_to_user((u64 __user *)(long)reg->addr,
-				&to_book3s(vcpu)->hior, sizeof(u64));
+		*val = get_reg_val(id, to_book3s(vcpu)->hior);
 		break;
+#ifdef CONFIG_VSX
+	case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31: {
+		long int i = id - KVM_REG_PPC_VSR0;
+
+		if (!cpu_has_feature(CPU_FTR_VSX)) {
+			r = -ENXIO;
+			break;
+		}
+		val->vsxval[0] = vcpu->arch.fpr[i];
+		val->vsxval[1] = vcpu->arch.vsr[i];
+		break;
+	}
+#endif /* CONFIG_VSX */
 	default:
+		r = -EINVAL;
 		break;
 	}
 
 	return r;
 }
 
-int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
 {
-	int r = -EINVAL;
+	int r = 0;
 
-	switch (reg->id) {
+	switch (id) {
 	case KVM_REG_PPC_HIOR:
-		r = copy_from_user(&to_book3s(vcpu)->hior,
-				   (u64 __user *)(long)reg->addr, sizeof(u64));
-		if (!r)
-			to_book3s(vcpu)->hior_explicit = true;
+		to_book3s(vcpu)->hior = set_reg_val(id, *val);
+		to_book3s(vcpu)->hior_explicit = true;
+		break;
+#ifdef CONFIG_VSX
+	case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31: {
+		long int i = id - KVM_REG_PPC_VSR0;
+
+		if (!cpu_has_feature(CPU_FTR_VSX)) {
+			r = -ENXIO;
+			break;
+		}
+		vcpu->arch.fpr[i] = val->vsxval[0];
+		vcpu->arch.vsr[i] = val->vsxval[1];
 		break;
+	}
+#endif /* CONFIG_VSX */
 	default:
+		r = -EINVAL;
 		break;
 	}
 
@@ -1020,8 +1103,6 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 #endif
 	ulong ext_msr;
 
-	preempt_disable();
-
 	/* Check if we can run the vcpu at all */
 	if (!vcpu->arch.sane) {
 		kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
@@ -1029,21 +1110,16 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 		goto out;
 	}
 
-	kvmppc_core_prepare_to_enter(vcpu);
-
 	/*
 	 * Interrupts could be timers for the guest which we have to inject
 	 * again, so let's postpone them until we're in the guest and if we
 	 * really did time things so badly, then we just exit again due to
 	 * a host external interrupt.
 	 */
-	__hard_irq_disable();
-
-	/* No need to go into the guest when all we do is going out */
-	if (signal_pending(current)) {
-		__hard_irq_enable();
-		kvm_run->exit_reason = KVM_EXIT_INTR;
-		ret = -EINTR;
+	local_irq_disable();
+	ret = kvmppc_prepare_to_enter(vcpu);
+	if (ret <= 0) {
+		local_irq_enable();
 		goto out;
 	}
 
@@ -1070,7 +1146,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 	/* Save VSX state in stack */
 	used_vsr = current->thread.used_vsr;
 	if (used_vsr && (current->thread.regs->msr & MSR_VSX))
-			__giveup_vsx(current);
+		__giveup_vsx(current);
 #endif
 
 	/* Remember the MSR with disabled extensions */
@@ -1080,20 +1156,19 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 	if (vcpu->arch.shared->msr & MSR_FP)
 		kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
 
-	kvm_guest_enter();
+	kvmppc_lazy_ee_enable();
 
 	ret = __kvmppc_vcpu_run(kvm_run, vcpu);
 
-	kvm_guest_exit();
-
-	current->thread.regs->msr = ext_msr;
+	/* No need for kvm_guest_exit. It's done in handle_exit.
+	   We also get here with interrupts enabled. */
 
 	/* Make sure we save the guest FPU/Altivec/VSX state */
-	kvmppc_giveup_ext(vcpu, MSR_FP);
-	kvmppc_giveup_ext(vcpu, MSR_VEC);
-	kvmppc_giveup_ext(vcpu, MSR_VSX);
+	kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX);
+
+	current->thread.regs->msr = ext_msr;
 
-	/* Restore FPU state from stack */
+	/* Restore FPU/VSX state from stack */
 	memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr));
 	current->thread.fpscr.val = fpscr;
 	current->thread.fpexc_mode = fpexc_mode;
@@ -1113,7 +1188,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 #endif
 
 out:
-	preempt_enable();
+	vcpu->mode = OUTSIDE_GUEST_MODE;
 	return ret;
 }
 
@@ -1181,14 +1256,31 @@ int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm, struct kvm_ppc_smmu_info *info)
 }
 #endif /* CONFIG_PPC64 */
 
+void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
+			      struct kvm_memory_slot *dont)
+{
+}
+
+int kvmppc_core_create_memslot(struct kvm_memory_slot *slot,
+			       unsigned long npages)
+{
+	return 0;
+}
+
 int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+				      struct kvm_memory_slot *memslot,
 				      struct kvm_userspace_memory_region *mem)
 {
 	return 0;
 }
 
 void kvmppc_core_commit_memory_region(struct kvm *kvm,
-				struct kvm_userspace_memory_region *mem)
+				struct kvm_userspace_memory_region *mem,
+				struct kvm_memory_slot old)
+{
+}
+
+void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot)
 {
 }
 
diff --git a/arch/powerpc/kvm/book3s_rmhandlers.S b/arch/powerpc/kvm/book3s_rmhandlers.S
index 9ecf6e3..8f7633e 100644
--- a/arch/powerpc/kvm/book3s_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_rmhandlers.S
@@ -170,20 +170,21 @@ kvmppc_handler_skip_ins:
  * Call kvmppc_handler_trampoline_enter in real mode
  *
  * On entry, r4 contains the guest shadow MSR
+ * MSR.EE has to be 0 when calling this function
  */
 _GLOBAL(kvmppc_entry_trampoline)
 	mfmsr	r5
 	LOAD_REG_ADDR(r7, kvmppc_handler_trampoline_enter)
 	toreal(r7)
 
-	li	r9, MSR_RI
-	ori	r9, r9, MSR_EE
-	andc	r9, r5, r9	/* Clear EE and RI in MSR value */
 	li	r6, MSR_IR | MSR_DR
-	ori	r6, r6, MSR_EE
-	andc	r6, r5, r6	/* Clear EE, DR and IR in MSR value */
-	MTMSR_EERI(r9)		/* Clear EE and RI in MSR */
-	mtsrr0	r7		/* before we set srr0/1 */
+	andc	r6, r5, r6	/* Clear DR and IR in MSR value */
+	/*
+	 * Set EE in HOST_MSR so that it's enabled when we get into our
+	 * C exit handler function
+	 */
+	ori	r5, r5, MSR_EE
+	mtsrr0	r7
 	mtsrr1	r6
 	RFI
 
@@ -233,8 +234,5 @@ define_load_up(fpu)
 #ifdef CONFIG_ALTIVEC
 define_load_up(altivec)
 #endif
-#ifdef CONFIG_VSX
-define_load_up(vsx)
-#endif
 
 #include "book3s_segment.S"
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index d25a097..3d1f35d 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -39,6 +39,7 @@
 
 #include "timing.h"
 #include "booke.h"
+#include "trace.h"
 
 unsigned long kvmppc_booke_handlers;
 
@@ -62,6 +63,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ "halt_wakeup", VCPU_STAT(halt_wakeup) },
 	{ "doorbell", VCPU_STAT(dbell_exits) },
 	{ "guest doorbell", VCPU_STAT(gdbell_exits) },
+	{ "remote_tlb_flush", VM_STAT(remote_tlb_flush) },
 	{ NULL }
 };
 
@@ -120,6 +122,16 @@ static void kvmppc_vcpu_sync_spe(struct kvm_vcpu *vcpu)
 }
 #endif
 
+static void kvmppc_vcpu_sync_fpu(struct kvm_vcpu *vcpu)
+{
+#if defined(CONFIG_PPC_FPU) && !defined(CONFIG_KVM_BOOKE_HV)
+	/* We always treat the FP bit as enabled from the host
+	   perspective, so only need to adjust the shadow MSR */
+	vcpu->arch.shadow_msr &= ~MSR_FP;
+	vcpu->arch.shadow_msr |= vcpu->arch.shared->msr & MSR_FP;
+#endif
+}
+
 /*
  * Helper function for "full" MSR writes.  No need to call this if only
  * EE/CE/ME/DE/RI are changing.
@@ -136,11 +148,13 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
 
 	kvmppc_mmu_msr_notify(vcpu, old_msr);
 	kvmppc_vcpu_sync_spe(vcpu);
+	kvmppc_vcpu_sync_fpu(vcpu);
 }
 
 static void kvmppc_booke_queue_irqprio(struct kvm_vcpu *vcpu,
                                        unsigned int priority)
 {
+	trace_kvm_booke_queue_irqprio(vcpu, priority);
 	set_bit(priority, &vcpu->arch.pending_exceptions);
 }
 
@@ -206,6 +220,16 @@ void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu,
 	clear_bit(BOOKE_IRQPRIO_EXTERNAL_LEVEL, &vcpu->arch.pending_exceptions);
 }
 
+static void kvmppc_core_queue_watchdog(struct kvm_vcpu *vcpu)
+{
+	kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_WATCHDOG);
+}
+
+static void kvmppc_core_dequeue_watchdog(struct kvm_vcpu *vcpu)
+{
+	clear_bit(BOOKE_IRQPRIO_WATCHDOG, &vcpu->arch.pending_exceptions);
+}
+
 static void set_guest_srr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1)
 {
 #ifdef CONFIG_KVM_BOOKE_HV
@@ -325,6 +349,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
 		msr_mask = MSR_CE | MSR_ME | MSR_DE;
 		int_class = INT_CLASS_NONCRIT;
 		break;
+	case BOOKE_IRQPRIO_WATCHDOG:
 	case BOOKE_IRQPRIO_CRITICAL:
 	case BOOKE_IRQPRIO_DBELL_CRIT:
 		allowed = vcpu->arch.shared->msr & MSR_CE;
@@ -404,12 +429,121 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
 	return allowed;
 }
 
+/*
+ * Return the number of jiffies until the next timeout.  If the timeout is
+ * longer than the NEXT_TIMER_MAX_DELTA, then return NEXT_TIMER_MAX_DELTA
+ * because the larger value can break the timer APIs.
+ */
+static unsigned long watchdog_next_timeout(struct kvm_vcpu *vcpu)
+{
+	u64 tb, wdt_tb, wdt_ticks = 0;
+	u64 nr_jiffies = 0;
+	u32 period = TCR_GET_WP(vcpu->arch.tcr);
+
+	wdt_tb = 1ULL << (63 - period);
+	tb = get_tb();
+	/*
+	 * The watchdog timeout will hapeen when TB bit corresponding
+	 * to watchdog will toggle from 0 to 1.
+	 */
+	if (tb & wdt_tb)
+		wdt_ticks = wdt_tb;
+
+	wdt_ticks += wdt_tb - (tb & (wdt_tb - 1));
+
+	/* Convert timebase ticks to jiffies */
+	nr_jiffies = wdt_ticks;
+
+	if (do_div(nr_jiffies, tb_ticks_per_jiffy))
+		nr_jiffies++;
+
+	return min_t(unsigned long long, nr_jiffies, NEXT_TIMER_MAX_DELTA);
+}
+
+static void arm_next_watchdog(struct kvm_vcpu *vcpu)
+{
+	unsigned long nr_jiffies;
+	unsigned long flags;
+
+	/*
+	 * If TSR_ENW and TSR_WIS are not set then no need to exit to
+	 * userspace, so clear the KVM_REQ_WATCHDOG request.
+	 */
+	if ((vcpu->arch.tsr & (TSR_ENW | TSR_WIS)) != (TSR_ENW | TSR_WIS))
+		clear_bit(KVM_REQ_WATCHDOG, &vcpu->requests);
+
+	spin_lock_irqsave(&vcpu->arch.wdt_lock, flags);
+	nr_jiffies = watchdog_next_timeout(vcpu);
+	/*
+	 * If the number of jiffies of watchdog timer >= NEXT_TIMER_MAX_DELTA
+	 * then do not run the watchdog timer as this can break timer APIs.
+	 */
+	if (nr_jiffies < NEXT_TIMER_MAX_DELTA)
+		mod_timer(&vcpu->arch.wdt_timer, jiffies + nr_jiffies);
+	else
+		del_timer(&vcpu->arch.wdt_timer);
+	spin_unlock_irqrestore(&vcpu->arch.wdt_lock, flags);
+}
+
+void kvmppc_watchdog_func(unsigned long data)
+{
+	struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
+	u32 tsr, new_tsr;
+	int final;
+
+	do {
+		new_tsr = tsr = vcpu->arch.tsr;
+		final = 0;
+
+		/* Time out event */
+		if (tsr & TSR_ENW) {
+			if (tsr & TSR_WIS)
+				final = 1;
+			else
+				new_tsr = tsr | TSR_WIS;
+		} else {
+			new_tsr = tsr | TSR_ENW;
+		}
+	} while (cmpxchg(&vcpu->arch.tsr, tsr, new_tsr) != tsr);
+
+	if (new_tsr & TSR_WIS) {
+		smp_wmb();
+		kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu);
+		kvm_vcpu_kick(vcpu);
+	}
+
+	/*
+	 * If this is final watchdog expiry and some action is required
+	 * then exit to userspace.
+	 */
+	if (final && (vcpu->arch.tcr & TCR_WRC_MASK) &&
+	    vcpu->arch.watchdog_enabled) {
+		smp_wmb();
+		kvm_make_request(KVM_REQ_WATCHDOG, vcpu);
+		kvm_vcpu_kick(vcpu);
+	}
+
+	/*
+	 * Stop running the watchdog timer after final expiration to
+	 * prevent the host from being flooded with timers if the
+	 * guest sets a short period.
+	 * Timers will resume when TSR/TCR is updated next time.
+	 */
+	if (!final)
+		arm_next_watchdog(vcpu);
+}
+
 static void update_timer_ints(struct kvm_vcpu *vcpu)
 {
 	if ((vcpu->arch.tcr & TCR_DIE) && (vcpu->arch.tsr & TSR_DIS))
 		kvmppc_core_queue_dec(vcpu);
 	else
 		kvmppc_core_dequeue_dec(vcpu);
+
+	if ((vcpu->arch.tcr & TCR_WIE) && (vcpu->arch.tsr & TSR_WIS))
+		kvmppc_core_queue_watchdog(vcpu);
+	else
+		kvmppc_core_dequeue_watchdog(vcpu);
 }
 
 static void kvmppc_core_check_exceptions(struct kvm_vcpu *vcpu)
@@ -417,13 +551,6 @@ static void kvmppc_core_check_exceptions(struct kvm_vcpu *vcpu)
 	unsigned long *pending = &vcpu->arch.pending_exceptions;
 	unsigned int priority;
 
-	if (vcpu->requests) {
-		if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu)) {
-			smp_mb();
-			update_timer_ints(vcpu);
-		}
-	}
-
 	priority = __ffs(*pending);
 	while (priority < BOOKE_IRQPRIO_MAX) {
 		if (kvmppc_booke_irqprio_deliver(vcpu, priority))
@@ -459,37 +586,20 @@ int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
 	return r;
 }
 
-/*
- * Common checks before entering the guest world.  Call with interrupts
- * disabled.
- *
- * returns !0 if a signal is pending and check_signal is true
- */
-static int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
+int kvmppc_core_check_requests(struct kvm_vcpu *vcpu)
 {
-	int r = 0;
-
-	WARN_ON_ONCE(!irqs_disabled());
-	while (true) {
-		if (need_resched()) {
-			local_irq_enable();
-			cond_resched();
-			local_irq_disable();
-			continue;
-		}
-
-		if (signal_pending(current)) {
-			r = 1;
-			break;
-		}
+	int r = 1; /* Indicate we want to get back into the guest */
 
-		if (kvmppc_core_prepare_to_enter(vcpu)) {
-			/* interrupts got enabled in between, so we
-			   are back at square 1 */
-			continue;
-		}
+	if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu))
+		update_timer_ints(vcpu);
+#if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC)
+	if (kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu))
+		kvmppc_core_flush_tlb(vcpu);
+#endif
 
-		break;
+	if (kvm_check_request(KVM_REQ_WATCHDOG, vcpu)) {
+		vcpu->run->exit_reason = KVM_EXIT_WATCHDOG;
+		r = 0;
 	}
 
 	return r;
@@ -497,7 +607,7 @@ static int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
 
 int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
-	int ret;
+	int ret, s;
 #ifdef CONFIG_PPC_FPU
 	unsigned int fpscr;
 	int fpexc_mode;
@@ -510,11 +620,13 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 	}
 
 	local_irq_disable();
-	if (kvmppc_prepare_to_enter(vcpu)) {
-		kvm_run->exit_reason = KVM_EXIT_INTR;
-		ret = -EINTR;
+	s = kvmppc_prepare_to_enter(vcpu);
+	if (s <= 0) {
+		local_irq_enable();
+		ret = s;
 		goto out;
 	}
+	kvmppc_lazy_ee_enable();
 
 	kvm_guest_enter();
 
@@ -542,6 +654,9 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 
 	ret = __kvmppc_vcpu_run(kvm_run, vcpu);
 
+	/* No need for kvm_guest_exit. It's done in handle_exit.
+	   We also get here with interrupts enabled. */
+
 #ifdef CONFIG_PPC_FPU
 	kvmppc_save_guest_fp(vcpu);
 
@@ -557,10 +672,8 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 	current->thread.fpexc_mode = fpexc_mode;
 #endif
 
-	kvm_guest_exit();
-
 out:
-	local_irq_enable();
+	vcpu->mode = OUTSIDE_GUEST_MODE;
 	return ret;
 }
 
@@ -668,6 +781,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        unsigned int exit_nr)
 {
 	int r = RESUME_HOST;
+	int s;
 
 	/* update before a new last_exit_type is rewritten */
 	kvmppc_update_timing_stats(vcpu);
@@ -677,6 +791,9 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
 	local_irq_enable();
 
+	trace_kvm_exit(exit_nr, vcpu);
+	kvm_guest_exit();
+
 	run->exit_reason = KVM_EXIT_UNKNOWN;
 	run->ready_for_interrupt_injection = 1;
 
@@ -971,10 +1088,12 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	 */
 	if (!(r & RESUME_HOST)) {
 		local_irq_disable();
-		if (kvmppc_prepare_to_enter(vcpu)) {
-			run->exit_reason = KVM_EXIT_INTR;
-			r = (-EINTR << 2) | RESUME_HOST | (r & RESUME_FLAG_NV);
-			kvmppc_account_exit(vcpu, SIGNAL_EXITS);
+		s = kvmppc_prepare_to_enter(vcpu);
+		if (s <= 0) {
+			local_irq_enable();
+			r = (s << 2) | RESUME_HOST | (r & RESUME_FLAG_NV);
+		} else {
+			kvmppc_lazy_ee_enable();
 		}
 	}
 
@@ -1011,6 +1130,21 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 	return r;
 }
 
+int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu)
+{
+	/* setup watchdog timer once */
+	spin_lock_init(&vcpu->arch.wdt_lock);
+	setup_timer(&vcpu->arch.wdt_timer, kvmppc_watchdog_func,
+		    (unsigned long)vcpu);
+
+	return 0;
+}
+
+void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu)
+{
+	del_timer_sync(&vcpu->arch.wdt_timer);
+}
+
 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
 	int i;
@@ -1106,7 +1240,13 @@ static int set_sregs_base(struct kvm_vcpu *vcpu,
 	}
 
 	if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_TSR) {
+		u32 old_tsr = vcpu->arch.tsr;
+
 		vcpu->arch.tsr = sregs->u.e.tsr;
+
+		if ((old_tsr ^ vcpu->arch.tsr) & (TSR_ENW | TSR_WIS))
+			arm_next_watchdog(vcpu);
+
 		update_timer_ints(vcpu);
 	}
 
@@ -1221,12 +1361,56 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 
 int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 {
-	return -EINVAL;
+	int r = -EINVAL;
+
+	switch (reg->id) {
+	case KVM_REG_PPC_IAC1:
+	case KVM_REG_PPC_IAC2:
+	case KVM_REG_PPC_IAC3:
+	case KVM_REG_PPC_IAC4: {
+		int iac = reg->id - KVM_REG_PPC_IAC1;
+		r = copy_to_user((u64 __user *)(long)reg->addr,
+				 &vcpu->arch.dbg_reg.iac[iac], sizeof(u64));
+		break;
+	}
+	case KVM_REG_PPC_DAC1:
+	case KVM_REG_PPC_DAC2: {
+		int dac = reg->id - KVM_REG_PPC_DAC1;
+		r = copy_to_user((u64 __user *)(long)reg->addr,
+				 &vcpu->arch.dbg_reg.dac[dac], sizeof(u64));
+		break;
+	}
+	default:
+		break;
+	}
+	return r;
 }
 
 int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 {
-	return -EINVAL;
+	int r = -EINVAL;
+
+	switch (reg->id) {
+	case KVM_REG_PPC_IAC1:
+	case KVM_REG_PPC_IAC2:
+	case KVM_REG_PPC_IAC3:
+	case KVM_REG_PPC_IAC4: {
+		int iac = reg->id - KVM_REG_PPC_IAC1;
+		r = copy_from_user(&vcpu->arch.dbg_reg.iac[iac],
+			     (u64 __user *)(long)reg->addr, sizeof(u64));
+		break;
+	}
+	case KVM_REG_PPC_DAC1:
+	case KVM_REG_PPC_DAC2: {
+		int dac = reg->id - KVM_REG_PPC_DAC1;
+		r = copy_from_user(&vcpu->arch.dbg_reg.dac[dac],
+			     (u64 __user *)(long)reg->addr, sizeof(u64));
+		break;
+	}
+	default:
+		break;
+	}
+	return r;
 }
 
 int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
@@ -1253,20 +1437,38 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
 	return -ENOTSUPP;
 }
 
+void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
+			      struct kvm_memory_slot *dont)
+{
+}
+
+int kvmppc_core_create_memslot(struct kvm_memory_slot *slot,
+			       unsigned long npages)
+{
+	return 0;
+}
+
 int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+				      struct kvm_memory_slot *memslot,
 				      struct kvm_userspace_memory_region *mem)
 {
 	return 0;
 }
 
 void kvmppc_core_commit_memory_region(struct kvm *kvm,
-				struct kvm_userspace_memory_region *mem)
+				struct kvm_userspace_memory_region *mem,
+				struct kvm_memory_slot old)
+{
+}
+
+void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot)
 {
 }
 
 void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr)
 {
 	vcpu->arch.tcr = new_tcr;
+	arm_next_watchdog(vcpu);
 	update_timer_ints(vcpu);
 }
 
@@ -1281,6 +1483,14 @@ void kvmppc_set_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits)
 void kvmppc_clr_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits)
 {
 	clear_bits(tsr_bits, &vcpu->arch.tsr);
+
+	/*
+	 * We may have stopped the watchdog due to
+	 * being stuck on final expiration.
+	 */
+	if (tsr_bits & (TSR_ENW | TSR_WIS))
+		arm_next_watchdog(vcpu);
+
 	update_timer_ints(vcpu);
 }
 
@@ -1298,12 +1508,14 @@ void kvmppc_decrementer_func(unsigned long data)
 
 void kvmppc_booke_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
+	vcpu->cpu = smp_processor_id();
 	current->thread.kvm_vcpu = vcpu;
 }
 
 void kvmppc_booke_vcpu_put(struct kvm_vcpu *vcpu)
 {
 	current->thread.kvm_vcpu = NULL;
+	vcpu->cpu = -1;
 }
 
 int __init kvmppc_booke_init(void)
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c
index 12834bb..514790f 100644
--- a/arch/powerpc/kvm/booke_emulate.c
+++ b/arch/powerpc/kvm/booke_emulate.c
@@ -133,10 +133,10 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
 		vcpu->arch.csrr1 = spr_val;
 		break;
 	case SPRN_DBCR0:
-		vcpu->arch.dbcr0 = spr_val;
+		vcpu->arch.dbg_reg.dbcr0 = spr_val;
 		break;
 	case SPRN_DBCR1:
-		vcpu->arch.dbcr1 = spr_val;
+		vcpu->arch.dbg_reg.dbcr1 = spr_val;
 		break;
 	case SPRN_DBSR:
 		vcpu->arch.dbsr &= ~spr_val;
@@ -145,6 +145,14 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
 		kvmppc_clr_tsr_bits(vcpu, spr_val);
 		break;
 	case SPRN_TCR:
+		/*
+		 * WRC is a 2-bit field that is supposed to preserve its
+		 * value once written to non-zero.
+		 */
+		if (vcpu->arch.tcr & TCR_WRC_MASK) {
+			spr_val &= ~TCR_WRC_MASK;
+			spr_val |= vcpu->arch.tcr & TCR_WRC_MASK;
+		}
 		kvmppc_set_tcr(vcpu, spr_val);
 		break;
 
@@ -229,6 +237,9 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
 	case SPRN_IVOR15:
 		vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = spr_val;
 		break;
+	case SPRN_MCSR:
+		vcpu->arch.mcsr &= ~spr_val;
+		break;
 
 	default:
 		emulated = EMULATE_FAIL;
@@ -258,10 +269,10 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
 		*spr_val = vcpu->arch.csrr1;
 		break;
 	case SPRN_DBCR0:
-		*spr_val = vcpu->arch.dbcr0;
+		*spr_val = vcpu->arch.dbg_reg.dbcr0;
 		break;
 	case SPRN_DBCR1:
-		*spr_val = vcpu->arch.dbcr1;
+		*spr_val = vcpu->arch.dbg_reg.dbcr1;
 		break;
 	case SPRN_DBSR:
 		*spr_val = vcpu->arch.dbsr;
@@ -321,6 +332,9 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
 	case SPRN_IVOR15:
 		*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG];
 		break;
+	case SPRN_MCSR:
+		*spr_val = vcpu->arch.mcsr;
+		break;
 
 	default:
 		emulated = EMULATE_FAIL;
diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
index aa8b814..d162286 100644
--- a/arch/powerpc/kvm/e500.h
+++ b/arch/powerpc/kvm/e500.h
@@ -27,8 +27,7 @@
 #define E500_TLB_NUM   2
 
 #define E500_TLB_VALID 1
-#define E500_TLB_DIRTY 2
-#define E500_TLB_BITMAP 4
+#define E500_TLB_BITMAP 2
 
 struct tlbe_ref {
 	pfn_t pfn;
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index ff38b66..6305ee6 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -304,17 +304,13 @@ static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
 	ref->flags = E500_TLB_VALID;
 
 	if (tlbe_is_writable(gtlbe))
-		ref->flags |= E500_TLB_DIRTY;
+		kvm_set_pfn_dirty(pfn);
 }
 
 static inline void kvmppc_e500_ref_release(struct tlbe_ref *ref)
 {
 	if (ref->flags & E500_TLB_VALID) {
-		if (ref->flags & E500_TLB_DIRTY)
-			kvm_release_pfn_dirty(ref->pfn);
-		else
-			kvm_release_pfn_clean(ref->pfn);
-
+		trace_kvm_booke206_ref_release(ref->pfn, ref->flags);
 		ref->flags = 0;
 	}
 }
@@ -357,6 +353,13 @@ static void clear_tlb_refs(struct kvmppc_vcpu_e500 *vcpu_e500)
 	clear_tlb_privs(vcpu_e500);
 }
 
+void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu)
+{
+	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
+	clear_tlb_refs(vcpu_e500);
+	clear_tlb1_bitmap(vcpu_e500);
+}
+
 static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu,
 		unsigned int eaddr, int as)
 {
@@ -521,7 +524,7 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 	if (likely(!pfnmap)) {
 		unsigned long tsize_pages = 1 << (tsize + 10 - PAGE_SHIFT);
 		pfn = gfn_to_pfn_memslot(slot, gfn);
-		if (is_error_pfn(pfn)) {
+		if (is_error_noslot_pfn(pfn)) {
 			printk(KERN_ERR "Couldn't get real page for gfn %lx!\n",
 					(long)gfn);
 			return;
@@ -541,6 +544,9 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 
 	/* Clear i-cache for new pages */
 	kvmppc_mmu_flush_icache(pfn);
+
+	/* Drop refcount on page, so that mmu notifiers can clear it */
+	kvm_release_pfn_clean(pfn);
 }
 
 /* XXX only map the one-one case, for now use TLB0 */
@@ -1039,8 +1045,12 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
 		sesel = 0; /* unused */
 		priv = &vcpu_e500->gtlb_priv[tlbsel][esel];
 
-		kvmppc_e500_setup_stlbe(vcpu, gtlbe, BOOK3E_PAGESZ_4K,
-					&priv->ref, eaddr, &stlbe);
+		/* Only triggers after clear_tlb_refs */
+		if (unlikely(!(priv->ref.flags & E500_TLB_VALID)))
+			kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe);
+		else
+			kvmppc_e500_setup_stlbe(vcpu, gtlbe, BOOK3E_PAGESZ_4K,
+						&priv->ref, eaddr, &stlbe);
 		break;
 
 	case 1: {
@@ -1060,6 +1070,49 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
 	write_stlbe(vcpu_e500, gtlbe, &stlbe, stlbsel, sesel);
 }
 
+/************* MMU Notifiers *************/
+
+int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
+{
+	trace_kvm_unmap_hva(hva);
+
+	/*
+	 * Flush all shadow tlb entries everywhere. This is slow, but
+	 * we are 100% sure that we catch the to be unmapped page
+	 */
+	kvm_flush_remote_tlbs(kvm);
+
+	return 0;
+}
+
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+{
+	/* kvm_unmap_hva flushes everything anyways */
+	kvm_unmap_hva(kvm, start);
+
+	return 0;
+}
+
+int kvm_age_hva(struct kvm *kvm, unsigned long hva)
+{
+	/* XXX could be more clever ;) */
+	return 0;
+}
+
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
+{
+	/* XXX could be more clever ;) */
+	return 0;
+}
+
+void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
+{
+	/* The page will get remapped properly on its next fault */
+	kvm_unmap_hva(kvm, hva);
+}
+
+/*****************************************/
+
 static void free_gtlb(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
 	int i;
@@ -1081,6 +1134,8 @@ static void free_gtlb(struct kvmppc_vcpu_e500 *vcpu_e500)
 		}
 
 		vcpu_e500->num_shared_tlb_pages = 0;
+
+		kfree(vcpu_e500->shared_tlb_pages);
 		vcpu_e500->shared_tlb_pages = NULL;
 	} else {
 		kfree(vcpu_e500->gtlb_arch);
@@ -1178,21 +1233,27 @@ int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
 	}
 
 	virt = vmap(pages, num_pages, VM_MAP, PAGE_KERNEL);
-	if (!virt)
+	if (!virt) {
+		ret = -ENOMEM;
 		goto err_put_page;
+	}
 
 	privs[0] = kzalloc(sizeof(struct tlbe_priv) * params.tlb_sizes[0],
 			   GFP_KERNEL);
 	privs[1] = kzalloc(sizeof(struct tlbe_priv) * params.tlb_sizes[1],
 			   GFP_KERNEL);
 
-	if (!privs[0] || !privs[1])
-		goto err_put_page;
+	if (!privs[0] || !privs[1]) {
+		ret = -ENOMEM;
+		goto err_privs;
+	}
 
 	g2h_bitmap = kzalloc(sizeof(u64) * params.tlb_sizes[1],
 	                     GFP_KERNEL);
-	if (!g2h_bitmap)
-		goto err_put_page;
+	if (!g2h_bitmap) {
+		ret = -ENOMEM;
+		goto err_privs;
+	}
 
 	free_gtlb(vcpu_e500);
 
@@ -1232,10 +1293,11 @@ int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
 	kvmppc_recalc_tlb1map_range(vcpu_e500);
 	return 0;
 
-err_put_page:
+err_privs:
 	kfree(privs[0]);
 	kfree(privs[1]);
 
+err_put_page:
 	for (i = 0; i < num_pages; i++)
 		put_page(pages[i]);
 
@@ -1332,7 +1394,7 @@ int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500)
 	if (!vcpu_e500->gtlb_priv[1])
 		goto err;
 
-	vcpu_e500->g2h_tlb1_map = kzalloc(sizeof(unsigned int) *
+	vcpu_e500->g2h_tlb1_map = kzalloc(sizeof(u64) *
 					  vcpu_e500->gtlb_params[1].entries,
 					  GFP_KERNEL);
 	if (!vcpu_e500->g2h_tlb1_map)
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index ee04aba..b0855e5 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -131,6 +131,125 @@ u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb)
 	return vcpu->arch.dec - jd;
 }
 
+static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
+{
+	enum emulation_result emulated = EMULATE_DONE;
+	ulong spr_val = kvmppc_get_gpr(vcpu, rs);
+
+	switch (sprn) {
+	case SPRN_SRR0:
+		vcpu->arch.shared->srr0 = spr_val;
+		break;
+	case SPRN_SRR1:
+		vcpu->arch.shared->srr1 = spr_val;
+		break;
+
+	/* XXX We need to context-switch the timebase for
+	 * watchdog and FIT. */
+	case SPRN_TBWL: break;
+	case SPRN_TBWU: break;
+
+	case SPRN_MSSSR0: break;
+
+	case SPRN_DEC:
+		vcpu->arch.dec = spr_val;
+		kvmppc_emulate_dec(vcpu);
+		break;
+
+	case SPRN_SPRG0:
+		vcpu->arch.shared->sprg0 = spr_val;
+		break;
+	case SPRN_SPRG1:
+		vcpu->arch.shared->sprg1 = spr_val;
+		break;
+	case SPRN_SPRG2:
+		vcpu->arch.shared->sprg2 = spr_val;
+		break;
+	case SPRN_SPRG3:
+		vcpu->arch.shared->sprg3 = spr_val;
+		break;
+
+	default:
+		emulated = kvmppc_core_emulate_mtspr(vcpu, sprn,
+						     spr_val);
+		if (emulated == EMULATE_FAIL)
+			printk(KERN_INFO "mtspr: unknown spr "
+				"0x%x\n", sprn);
+		break;
+	}
+
+	kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);
+
+	return emulated;
+}
+
+static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
+{
+	enum emulation_result emulated = EMULATE_DONE;
+	ulong spr_val = 0;
+
+	switch (sprn) {
+	case SPRN_SRR0:
+		spr_val = vcpu->arch.shared->srr0;
+		break;
+	case SPRN_SRR1:
+		spr_val = vcpu->arch.shared->srr1;
+		break;
+	case SPRN_PVR:
+		spr_val = vcpu->arch.pvr;
+		break;
+	case SPRN_PIR:
+		spr_val = vcpu->vcpu_id;
+		break;
+	case SPRN_MSSSR0:
+		spr_val = 0;
+		break;
+
+	/* Note: mftb and TBRL/TBWL are user-accessible, so
+	 * the guest can always access the real TB anyways.
+	 * In fact, we probably will never see these traps. */
+	case SPRN_TBWL:
+		spr_val = get_tb() >> 32;
+		break;
+	case SPRN_TBWU:
+		spr_val = get_tb();
+		break;
+
+	case SPRN_SPRG0:
+		spr_val = vcpu->arch.shared->sprg0;
+		break;
+	case SPRN_SPRG1:
+		spr_val = vcpu->arch.shared->sprg1;
+		break;
+	case SPRN_SPRG2:
+		spr_val = vcpu->arch.shared->sprg2;
+		break;
+	case SPRN_SPRG3:
+		spr_val = vcpu->arch.shared->sprg3;
+		break;
+	/* Note: SPRG4-7 are user-readable, so we don't get
+	 * a trap. */
+
+	case SPRN_DEC:
+		spr_val = kvmppc_get_dec(vcpu, get_tb());
+		break;
+	default:
+		emulated = kvmppc_core_emulate_mfspr(vcpu, sprn,
+						     &spr_val);
+		if (unlikely(emulated == EMULATE_FAIL)) {
+			printk(KERN_INFO "mfspr: unknown spr "
+				"0x%x\n", sprn);
+		}
+		break;
+	}
+
+	if (emulated == EMULATE_DONE)
+		kvmppc_set_gpr(vcpu, rt, spr_val);
+	kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);
+
+	return emulated;
+}
+
 /* XXX to do:
  * lhax
  * lhaux
@@ -156,7 +275,6 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
 	int sprn = get_sprn(inst);
 	enum emulation_result emulated = EMULATE_DONE;
 	int advance = 1;
-	ulong spr_val = 0;
 
 	/* this default type might be overwritten by subcategories */
 	kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
@@ -236,62 +354,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
 			break;
 
 		case OP_31_XOP_MFSPR:
-			switch (sprn) {
-			case SPRN_SRR0:
-				spr_val = vcpu->arch.shared->srr0;
-				break;
-			case SPRN_SRR1:
-				spr_val = vcpu->arch.shared->srr1;
-				break;
-			case SPRN_PVR:
-				spr_val = vcpu->arch.pvr;
-				break;
-			case SPRN_PIR:
-				spr_val = vcpu->vcpu_id;
-				break;
-			case SPRN_MSSSR0:
-				spr_val = 0;
-				break;
-
-			/* Note: mftb and TBRL/TBWL are user-accessible, so
-			 * the guest can always access the real TB anyways.
-			 * In fact, we probably will never see these traps. */
-			case SPRN_TBWL:
-				spr_val = get_tb() >> 32;
-				break;
-			case SPRN_TBWU:
-				spr_val = get_tb();
-				break;
-
-			case SPRN_SPRG0:
-				spr_val = vcpu->arch.shared->sprg0;
-				break;
-			case SPRN_SPRG1:
-				spr_val = vcpu->arch.shared->sprg1;
-				break;
-			case SPRN_SPRG2:
-				spr_val = vcpu->arch.shared->sprg2;
-				break;
-			case SPRN_SPRG3:
-				spr_val = vcpu->arch.shared->sprg3;
-				break;
-			/* Note: SPRG4-7 are user-readable, so we don't get
-			 * a trap. */
-
-			case SPRN_DEC:
-				spr_val = kvmppc_get_dec(vcpu, get_tb());
-				break;
-			default:
-				emulated = kvmppc_core_emulate_mfspr(vcpu, sprn,
-								     &spr_val);
-				if (unlikely(emulated == EMULATE_FAIL)) {
-					printk(KERN_INFO "mfspr: unknown spr "
-						"0x%x\n", sprn);
-				}
-				break;
-			}
-			kvmppc_set_gpr(vcpu, rt, spr_val);
-			kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);
+			emulated = kvmppc_emulate_mfspr(vcpu, sprn, rt);
 			break;
 
 		case OP_31_XOP_STHX:
@@ -308,49 +371,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
 			break;
 
 		case OP_31_XOP_MTSPR:
-			spr_val = kvmppc_get_gpr(vcpu, rs);
-			switch (sprn) {
-			case SPRN_SRR0:
-				vcpu->arch.shared->srr0 = spr_val;
-				break;
-			case SPRN_SRR1:
-				vcpu->arch.shared->srr1 = spr_val;
-				break;
-
-			/* XXX We need to context-switch the timebase for
-			 * watchdog and FIT. */
-			case SPRN_TBWL: break;
-			case SPRN_TBWU: break;
-
-			case SPRN_MSSSR0: break;
-
-			case SPRN_DEC:
-				vcpu->arch.dec = spr_val;
-				kvmppc_emulate_dec(vcpu);
-				break;
-
-			case SPRN_SPRG0:
-				vcpu->arch.shared->sprg0 = spr_val;
-				break;
-			case SPRN_SPRG1:
-				vcpu->arch.shared->sprg1 = spr_val;
-				break;
-			case SPRN_SPRG2:
-				vcpu->arch.shared->sprg2 = spr_val;
-				break;
-			case SPRN_SPRG3:
-				vcpu->arch.shared->sprg3 = spr_val;
-				break;
-
-			default:
-				emulated = kvmppc_core_emulate_mtspr(vcpu, sprn,
-								     spr_val);
-				if (emulated == EMULATE_FAIL)
-					printk(KERN_INFO "mtspr: unknown spr "
-						"0x%x\n", sprn);
-				break;
-			}
-			kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);
+			emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs);
 			break;
 
 		case OP_31_XOP_DCBI:
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 4d213b8..d16be2a 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -30,6 +30,7 @@
 #include <asm/kvm_ppc.h>
 #include <asm/tlbflush.h>
 #include <asm/cputhreads.h>
+#include <asm/irqflags.h>
 #include "timing.h"
 #include "../mm/mmu_decl.h"
 
@@ -38,8 +39,7 @@
 
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
 {
-	return !(v->arch.shared->msr & MSR_WE) ||
-	       !!(v->arch.pending_exceptions) ||
+	return !!(v->arch.pending_exceptions) ||
 	       v->requests;
 }
 
@@ -48,6 +48,85 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
 	return 1;
 }
 
+#ifndef CONFIG_KVM_BOOK3S_64_HV
+/*
+ * Common checks before entering the guest world.  Call with interrupts
+ * disabled.
+ *
+ * returns:
+ *
+ * == 1 if we're ready to go into guest state
+ * <= 0 if we need to go back to the host with return value
+ */
+int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
+{
+	int r = 1;
+
+	WARN_ON_ONCE(!irqs_disabled());
+	while (true) {
+		if (need_resched()) {
+			local_irq_enable();
+			cond_resched();
+			local_irq_disable();
+			continue;
+		}
+
+		if (signal_pending(current)) {
+			kvmppc_account_exit(vcpu, SIGNAL_EXITS);
+			vcpu->run->exit_reason = KVM_EXIT_INTR;
+			r = -EINTR;
+			break;
+		}
+
+		vcpu->mode = IN_GUEST_MODE;
+
+		/*
+		 * Reading vcpu->requests must happen after setting vcpu->mode,
+		 * so we don't miss a request because the requester sees
+		 * OUTSIDE_GUEST_MODE and assumes we'll be checking requests
+		 * before next entering the guest (and thus doesn't IPI).
+		 */
+		smp_mb();
+
+		if (vcpu->requests) {
+			/* Make sure we process requests preemptable */
+			local_irq_enable();
+			trace_kvm_check_requests(vcpu);
+			r = kvmppc_core_check_requests(vcpu);
+			local_irq_disable();
+			if (r > 0)
+				continue;
+			break;
+		}
+
+		if (kvmppc_core_prepare_to_enter(vcpu)) {
+			/* interrupts got enabled in between, so we
+			   are back at square 1 */
+			continue;
+		}
+
+#ifdef CONFIG_PPC64
+		/* lazy EE magic */
+		hard_irq_disable();
+		if (lazy_irq_pending()) {
+			/* Got an interrupt in between, try again */
+			local_irq_enable();
+			local_irq_disable();
+			kvm_guest_exit();
+			continue;
+		}
+
+		trace_hardirqs_on();
+#endif
+
+		kvm_guest_enter();
+		break;
+	}
+
+	return r;
+}
+#endif /* CONFIG_KVM_BOOK3S_64_HV */
+
 int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 {
 	int nr = kvmppc_get_gpr(vcpu, 11);
@@ -67,18 +146,18 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 	}
 
 	switch (nr) {
-	case HC_VENDOR_KVM | KVM_HC_PPC_MAP_MAGIC_PAGE:
+	case KVM_HCALL_TOKEN(KVM_HC_PPC_MAP_MAGIC_PAGE):
 	{
 		vcpu->arch.magic_page_pa = param1;
 		vcpu->arch.magic_page_ea = param2;
 
 		r2 = KVM_MAGIC_FEAT_SR | KVM_MAGIC_FEAT_MAS0_TO_SPRG7;
 
-		r = HC_EV_SUCCESS;
+		r = EV_SUCCESS;
 		break;
 	}
-	case HC_VENDOR_KVM | KVM_HC_FEATURES:
-		r = HC_EV_SUCCESS;
+	case KVM_HCALL_TOKEN(KVM_HC_FEATURES):
+		r = EV_SUCCESS;
 #if defined(CONFIG_PPC_BOOK3S) || defined(CONFIG_KVM_E500V2)
 		/* XXX Missing magic page on 44x */
 		r2 |= (1 << KVM_FEATURE_MAGIC_PAGE);
@@ -86,8 +165,13 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 
 		/* Second return value is in r4 */
 		break;
+	case EV_HCALL_TOKEN(EV_IDLE):
+		r = EV_SUCCESS;
+		kvm_vcpu_block(vcpu);
+		clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
+		break;
 	default:
-		r = HC_EV_UNIMPLEMENTED;
+		r = EV_UNIMPLEMENTED;
 		break;
 	}
 
@@ -220,6 +304,7 @@ int kvm_dev_ioctl_check_extension(long ext)
 	switch (ext) {
 #ifdef CONFIG_BOOKE
 	case KVM_CAP_PPC_BOOKE_SREGS:
+	case KVM_CAP_PPC_BOOKE_WATCHDOG:
 #else
 	case KVM_CAP_PPC_SEGSTATE:
 	case KVM_CAP_PPC_HIOR:
@@ -229,6 +314,7 @@ int kvm_dev_ioctl_check_extension(long ext)
 	case KVM_CAP_PPC_IRQ_LEVEL:
 	case KVM_CAP_ENABLE_CAP:
 	case KVM_CAP_ONE_REG:
+	case KVM_CAP_IOEVENTFD:
 		r = 1;
 		break;
 #ifndef CONFIG_KVM_BOOK3S_64_HV
@@ -260,10 +346,22 @@ int kvm_dev_ioctl_check_extension(long ext)
 		if (cpu_has_feature(CPU_FTR_ARCH_201))
 			r = 2;
 		break;
+#endif
 	case KVM_CAP_SYNC_MMU:
+#ifdef CONFIG_KVM_BOOK3S_64_HV
 		r = cpu_has_feature(CPU_FTR_ARCH_206) ? 1 : 0;
+#elif defined(KVM_ARCH_WANT_MMU_NOTIFIER)
+		r = 1;
+#else
+		r = 0;
 		break;
 #endif
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+	case KVM_CAP_PPC_HTAB_FD:
+		r = 1;
+		break;
+#endif
+		break;
 	case KVM_CAP_NR_VCPUS:
 		/*
 		 * Recommending a number of CPUs is somewhat arbitrary; we
@@ -302,19 +400,12 @@ long kvm_arch_dev_ioctl(struct file *filp,
 void kvm_arch_free_memslot(struct kvm_memory_slot *free,
 			   struct kvm_memory_slot *dont)
 {
-	if (!dont || free->arch.rmap != dont->arch.rmap) {
-		vfree(free->arch.rmap);
-		free->arch.rmap = NULL;
-	}
+	kvmppc_core_free_memslot(free, dont);
 }
 
 int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
 {
-	slot->arch.rmap = vzalloc(npages * sizeof(*slot->arch.rmap));
-	if (!slot->arch.rmap)
-		return -ENOMEM;
-
-	return 0;
+	return kvmppc_core_create_memslot(slot, npages);
 }
 
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
@@ -323,7 +414,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
                                    struct kvm_userspace_memory_region *mem,
                                    int user_alloc)
 {
-	return kvmppc_core_prepare_memory_region(kvm, mem);
+	return kvmppc_core_prepare_memory_region(kvm, memslot, mem);
 }
 
 void kvm_arch_commit_memory_region(struct kvm *kvm,
@@ -331,7 +422,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
                struct kvm_memory_slot old,
                int user_alloc)
 {
-	kvmppc_core_commit_memory_region(kvm, mem);
+	kvmppc_core_commit_memory_region(kvm, mem, old);
 }
 
 void kvm_arch_flush_shadow_all(struct kvm *kvm)
@@ -341,6 +432,7 @@ void kvm_arch_flush_shadow_all(struct kvm *kvm)
 void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
 				   struct kvm_memory_slot *slot)
 {
+	kvmppc_core_flush_memslot(kvm, slot);
 }
 
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
@@ -390,6 +482,8 @@ enum hrtimer_restart kvmppc_decrementer_wakeup(struct hrtimer *timer)
 
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
+	int ret;
+
 	hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
 	tasklet_init(&vcpu->arch.tasklet, kvmppc_decrementer_func, (ulong)vcpu);
 	vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup;
@@ -398,13 +492,14 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 #ifdef CONFIG_KVM_EXIT_TIMING
 	mutex_init(&vcpu->arch.exit_timing_lock);
 #endif
-
-	return 0;
+	ret = kvmppc_subarch_vcpu_init(vcpu);
+	return ret;
 }
 
 void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
 {
 	kvmppc_mmu_destroy(vcpu);
+	kvmppc_subarch_vcpu_uninit(vcpu);
 }
 
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
@@ -420,7 +515,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 	mtspr(SPRN_VRSAVE, vcpu->arch.vrsave);
 #endif
 	kvmppc_core_vcpu_load(vcpu, cpu);
-	vcpu->cpu = smp_processor_id();
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -429,7 +523,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 #ifdef CONFIG_BOOKE
 	vcpu->arch.vrsave = mfspr(SPRN_VRSAVE);
 #endif
-	vcpu->cpu = -1;
 }
 
 int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
@@ -527,6 +620,13 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	vcpu->mmio_is_write = 0;
 	vcpu->arch.mmio_sign_extend = 0;
 
+	if (!kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr,
+			     bytes, &run->mmio.data)) {
+		kvmppc_complete_mmio_load(vcpu, run);
+		vcpu->mmio_needed = 0;
+		return EMULATE_DONE;
+	}
+
 	return EMULATE_DO_MMIO;
 }
 
@@ -536,8 +636,8 @@ int kvmppc_handle_loads(struct kvm_run *run, struct kvm_vcpu *vcpu,
 {
 	int r;
 
-	r = kvmppc_handle_load(run, vcpu, rt, bytes, is_bigendian);
 	vcpu->arch.mmio_sign_extend = 1;
+	r = kvmppc_handle_load(run, vcpu, rt, bytes, is_bigendian);
 
 	return r;
 }
@@ -575,6 +675,13 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
 		}
 	}
 
+	if (!kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr,
+			      bytes, &run->mmio.data)) {
+		kvmppc_complete_mmio_load(vcpu, run);
+		vcpu->mmio_needed = 0;
+		return EMULATE_DONE;
+	}
+
 	return EMULATE_DO_MMIO;
 }
 
@@ -649,6 +756,12 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
 		r = 0;
 		vcpu->arch.papr_enabled = true;
 		break;
+#ifdef CONFIG_BOOKE
+	case KVM_CAP_PPC_BOOKE_WATCHDOG:
+		r = 0;
+		vcpu->arch.watchdog_enabled = true;
+		break;
+#endif
 #if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC)
 	case KVM_CAP_SW_TLB: {
 		struct kvm_config_tlb cfg;
@@ -751,9 +864,16 @@ int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
 
 static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo)
 {
+	u32 inst_nop = 0x60000000;
+#ifdef CONFIG_KVM_BOOKE_HV
+	u32 inst_sc1 = 0x44000022;
+	pvinfo->hcall[0] = inst_sc1;
+	pvinfo->hcall[1] = inst_nop;
+	pvinfo->hcall[2] = inst_nop;
+	pvinfo->hcall[3] = inst_nop;
+#else
 	u32 inst_lis = 0x3c000000;
 	u32 inst_ori = 0x60000000;
-	u32 inst_nop = 0x60000000;
 	u32 inst_sc = 0x44000002;
 	u32 inst_imm_mask = 0xffff;
 
@@ -770,6 +890,9 @@ static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo)
 	pvinfo->hcall[1] = inst_ori | (KVM_SC_MAGIC_R0 & inst_imm_mask);
 	pvinfo->hcall[2] = inst_sc;
 	pvinfo->hcall[3] = inst_nop;
+#endif
+
+	pvinfo->flags = KVM_PPC_PVINFO_FLAGS_EV_IDLE;
 
 	return 0;
 }
@@ -832,6 +955,17 @@ long kvm_arch_vm_ioctl(struct file *filp,
 		r = 0;
 		break;
 	}
+
+	case KVM_PPC_GET_HTAB_FD: {
+		struct kvm *kvm = filp->private_data;
+		struct kvm_get_htab_fd ghf;
+
+		r = -EFAULT;
+		if (copy_from_user(&ghf, argp, sizeof(ghf)))
+			break;
+		r = kvm_vm_ioctl_get_htab_fd(kvm, &ghf);
+		break;
+	}
 #endif /* CONFIG_KVM_BOOK3S_64_HV */
 
 #ifdef CONFIG_PPC_BOOK3S_64
diff --git a/arch/powerpc/kvm/trace.h b/arch/powerpc/kvm/trace.h
index ddb6a21..e326489 100644
--- a/arch/powerpc/kvm/trace.h
+++ b/arch/powerpc/kvm/trace.h
@@ -31,6 +31,126 @@ TRACE_EVENT(kvm_ppc_instr,
 		  __entry->inst, __entry->pc, __entry->emulate)
 );
 
+#ifdef CONFIG_PPC_BOOK3S
+#define kvm_trace_symbol_exit \
+	{0x100, "SYSTEM_RESET"}, \
+	{0x200, "MACHINE_CHECK"}, \
+	{0x300, "DATA_STORAGE"}, \
+	{0x380, "DATA_SEGMENT"}, \
+	{0x400, "INST_STORAGE"}, \
+	{0x480, "INST_SEGMENT"}, \
+	{0x500, "EXTERNAL"}, \
+	{0x501, "EXTERNAL_LEVEL"}, \
+	{0x502, "EXTERNAL_HV"}, \
+	{0x600, "ALIGNMENT"}, \
+	{0x700, "PROGRAM"}, \
+	{0x800, "FP_UNAVAIL"}, \
+	{0x900, "DECREMENTER"}, \
+	{0x980, "HV_DECREMENTER"}, \
+	{0xc00, "SYSCALL"}, \
+	{0xd00, "TRACE"}, \
+	{0xe00, "H_DATA_STORAGE"}, \
+	{0xe20, "H_INST_STORAGE"}, \
+	{0xe40, "H_EMUL_ASSIST"}, \
+	{0xf00, "PERFMON"}, \
+	{0xf20, "ALTIVEC"}, \
+	{0xf40, "VSX"}
+#else
+#define kvm_trace_symbol_exit \
+	{0, "CRITICAL"}, \
+	{1, "MACHINE_CHECK"}, \
+	{2, "DATA_STORAGE"}, \
+	{3, "INST_STORAGE"}, \
+	{4, "EXTERNAL"}, \
+	{5, "ALIGNMENT"}, \
+	{6, "PROGRAM"}, \
+	{7, "FP_UNAVAIL"}, \
+	{8, "SYSCALL"}, \
+	{9, "AP_UNAVAIL"}, \
+	{10, "DECREMENTER"}, \
+	{11, "FIT"}, \
+	{12, "WATCHDOG"}, \
+	{13, "DTLB_MISS"}, \
+	{14, "ITLB_MISS"}, \
+	{15, "DEBUG"}, \
+	{32, "SPE_UNAVAIL"}, \
+	{33, "SPE_FP_DATA"}, \
+	{34, "SPE_FP_ROUND"}, \
+	{35, "PERFORMANCE_MONITOR"}, \
+	{36, "DOORBELL"}, \
+	{37, "DOORBELL_CRITICAL"}, \
+	{38, "GUEST_DBELL"}, \
+	{39, "GUEST_DBELL_CRIT"}, \
+	{40, "HV_SYSCALL"}, \
+	{41, "HV_PRIV"}
+#endif
+
+TRACE_EVENT(kvm_exit,
+	TP_PROTO(unsigned int exit_nr, struct kvm_vcpu *vcpu),
+	TP_ARGS(exit_nr, vcpu),
+
+	TP_STRUCT__entry(
+		__field(	unsigned int,	exit_nr		)
+		__field(	unsigned long,	pc		)
+		__field(	unsigned long,	msr		)
+		__field(	unsigned long,	dar		)
+#ifdef CONFIG_KVM_BOOK3S_PR
+		__field(	unsigned long,	srr1		)
+#endif
+		__field(	unsigned long,	last_inst	)
+	),
+
+	TP_fast_assign(
+#ifdef CONFIG_KVM_BOOK3S_PR
+		struct kvmppc_book3s_shadow_vcpu *svcpu;
+#endif
+		__entry->exit_nr	= exit_nr;
+		__entry->pc		= kvmppc_get_pc(vcpu);
+		__entry->dar		= kvmppc_get_fault_dar(vcpu);
+		__entry->msr		= vcpu->arch.shared->msr;
+#ifdef CONFIG_KVM_BOOK3S_PR
+		svcpu = svcpu_get(vcpu);
+		__entry->srr1		= svcpu->shadow_srr1;
+		svcpu_put(svcpu);
+#endif
+		__entry->last_inst	= vcpu->arch.last_inst;
+	),
+
+	TP_printk("exit=%s"
+		" | pc=0x%lx"
+		" | msr=0x%lx"
+		" | dar=0x%lx"
+#ifdef CONFIG_KVM_BOOK3S_PR
+		" | srr1=0x%lx"
+#endif
+		" | last_inst=0x%lx"
+		,
+		__print_symbolic(__entry->exit_nr, kvm_trace_symbol_exit),
+		__entry->pc,
+		__entry->msr,
+		__entry->dar,
+#ifdef CONFIG_KVM_BOOK3S_PR
+		__entry->srr1,
+#endif
+		__entry->last_inst
+		)
+);
+
+TRACE_EVENT(kvm_unmap_hva,
+	TP_PROTO(unsigned long hva),
+	TP_ARGS(hva),
+
+	TP_STRUCT__entry(
+		__field(	unsigned long,	hva		)
+	),
+
+	TP_fast_assign(
+		__entry->hva		= hva;
+	),
+
+	TP_printk("unmap hva 0x%lx\n", __entry->hva)
+);
+
 TRACE_EVENT(kvm_stlb_inval,
 	TP_PROTO(unsigned int stlb_index),
 	TP_ARGS(stlb_index),
@@ -98,41 +218,31 @@ TRACE_EVENT(kvm_gtlb_write,
 		__entry->word1, __entry->word2)
 );
 
-
-/*************************************************************************
- *                         Book3S trace points                           *
- *************************************************************************/
-
-#ifdef CONFIG_KVM_BOOK3S_PR
-
-TRACE_EVENT(kvm_book3s_exit,
-	TP_PROTO(unsigned int exit_nr, struct kvm_vcpu *vcpu),
-	TP_ARGS(exit_nr, vcpu),
+TRACE_EVENT(kvm_check_requests,
+	TP_PROTO(struct kvm_vcpu *vcpu),
+	TP_ARGS(vcpu),
 
 	TP_STRUCT__entry(
-		__field(	unsigned int,	exit_nr		)
-		__field(	unsigned long,	pc		)
-		__field(	unsigned long,	msr		)
-		__field(	unsigned long,	dar		)
-		__field(	unsigned long,	srr1		)
+		__field(	__u32,	cpu_nr		)
+		__field(	__u32,	requests	)
 	),
 
 	TP_fast_assign(
-		struct kvmppc_book3s_shadow_vcpu *svcpu;
-		__entry->exit_nr	= exit_nr;
-		__entry->pc		= kvmppc_get_pc(vcpu);
-		__entry->dar		= kvmppc_get_fault_dar(vcpu);
-		__entry->msr		= vcpu->arch.shared->msr;
-		svcpu = svcpu_get(vcpu);
-		__entry->srr1		= svcpu->shadow_srr1;
-		svcpu_put(svcpu);
+		__entry->cpu_nr		= vcpu->vcpu_id;
+		__entry->requests	= vcpu->requests;
 	),
 
-	TP_printk("exit=0x%x | pc=0x%lx | msr=0x%lx | dar=0x%lx | srr1=0x%lx",
-		  __entry->exit_nr, __entry->pc, __entry->msr, __entry->dar,
-		  __entry->srr1)
+	TP_printk("vcpu=%x requests=%x",
+		__entry->cpu_nr, __entry->requests)
 );
 
+
+/*************************************************************************
+ *                         Book3S trace points                           *
+ *************************************************************************/
+
+#ifdef CONFIG_KVM_BOOK3S_PR
+
 TRACE_EVENT(kvm_book3s_reenter,
 	TP_PROTO(int r, struct kvm_vcpu *vcpu),
 	TP_ARGS(r, vcpu),
@@ -395,6 +505,44 @@ TRACE_EVENT(kvm_booke206_gtlb_write,
 		__entry->mas2, __entry->mas7_3)
 );
 
+TRACE_EVENT(kvm_booke206_ref_release,
+	TP_PROTO(__u64 pfn, __u32 flags),
+	TP_ARGS(pfn, flags),
+
+	TP_STRUCT__entry(
+		__field(	__u64,	pfn		)
+		__field(	__u32,	flags		)
+	),
+
+	TP_fast_assign(
+		__entry->pfn		= pfn;
+		__entry->flags		= flags;
+	),
+
+	TP_printk("pfn=%llx flags=%x",
+		__entry->pfn, __entry->flags)
+);
+
+TRACE_EVENT(kvm_booke_queue_irqprio,
+	TP_PROTO(struct kvm_vcpu *vcpu, unsigned int priority),
+	TP_ARGS(vcpu, priority),
+
+	TP_STRUCT__entry(
+		__field(	__u32,	cpu_nr		)
+		__field(	__u32,	priority		)
+		__field(	unsigned long,	pending		)
+	),
+
+	TP_fast_assign(
+		__entry->cpu_nr		= vcpu->vcpu_id;
+		__entry->priority	= priority;
+		__entry->pending	= vcpu->arch.pending_exceptions;
+	),
+
+	TP_printk("vcpu=%x prio=%x pending=%lx",
+		__entry->cpu_nr, __entry->priority, __entry->pending)
+);
+
 #endif
 
 #endif /* _TRACE_KVM_H */
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 0a6b283..3a8489a 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -113,19 +113,6 @@ static int store_updates_sp(struct pt_regs *regs)
 #define MM_FAULT_CONTINUE	-1
 #define MM_FAULT_ERR(sig)	(sig)
 
-static int out_of_memory(struct pt_regs *regs)
-{
-	/*
-	 * We ran out of memory, or some other thing happened to us that made
-	 * us unable to handle the page fault gracefully.
-	 */
-	up_read(&current->mm->mmap_sem);
-	if (!user_mode(regs))
-		return MM_FAULT_ERR(SIGKILL);
-	pagefault_out_of_memory();
-	return MM_FAULT_RETURN;
-}
-
 static int do_sigbus(struct pt_regs *regs, unsigned long address)
 {
 	siginfo_t info;
@@ -169,8 +156,18 @@ static int mm_fault_error(struct pt_regs *regs, unsigned long addr, int fault)
 		return MM_FAULT_CONTINUE;
 
 	/* Out of memory */
-	if (fault & VM_FAULT_OOM)
-		return out_of_memory(regs);
+	if (fault & VM_FAULT_OOM) {
+		up_read(&current->mm->mmap_sem);
+
+		/*
+		 * We ran out of memory, or some other thing happened to us that
+		 * made us unable to handle the page fault gracefully.
+		 */
+		if (!user_mode(regs))
+			return MM_FAULT_ERR(SIGKILL);
+		pagefault_out_of_memory();
+		return MM_FAULT_RETURN;
+	}
 
 	/* Bus error. x86 handles HWPOISON here, we'll add this if/when
 	 * we support the feature in HW
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 59213cf..bba87ca 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -399,18 +399,6 @@ static unsigned long read_n_cells(int n, const unsigned int **buf)
 	return result;
 }
 
-struct of_drconf_cell {
-	u64	base_addr;
-	u32	drc_index;
-	u32	reserved;
-	u32	aa_index;
-	u32	flags;
-};
-
-#define DRCONF_MEM_ASSIGNED	0x00000008
-#define DRCONF_MEM_AI_INVALID	0x00000040
-#define DRCONF_MEM_RESERVED	0x00000080
-
 /*
  * Read the next memblock list entry from the ibm,dynamic-memory property
  * and return the information in the provided of_drconf_cell structure.
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index 5829d2a..cf9dada 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -722,7 +722,7 @@ void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
 }
 
 /*
- * is_hugepage_only_range() is used by generic code to verify wether
+ * is_hugepage_only_range() is used by generic code to verify whether
  * a normal mmap mapping (non hugetlbfs) is valid on a given area.
  *
  * until the generic code provides a more generic hook and/or starts
diff --git a/arch/powerpc/mm/tlb_nohash_low.S b/arch/powerpc/mm/tlb_nohash_low.S
index fab919f..626ad08 100644
--- a/arch/powerpc/mm/tlb_nohash_low.S
+++ b/arch/powerpc/mm/tlb_nohash_low.S
@@ -191,12 +191,6 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_47x)
 #ifdef CONFIG_PPC_47x
 
 /*
- * 47x variant of icbt
- */
-# define ICBT(CT,RA,RB)	\
-	.long	0x7c00002c | ((CT) << 21) | ((RA) << 16) | ((RB) << 11)
-
-/*
  * _tlbivax_bcast is only on 47x. We don't bother doing a runtime
  * check though, it will blow up soon enough if we mistakenly try
  * to use it on a 440.
@@ -208,8 +202,7 @@ _GLOBAL(_tlbivax_bcast)
 	wrteei	0
 	mtspr	SPRN_MMUCR,r5
 	isync
-/*	tlbivax	0,r3 - use .long to avoid binutils deps */
-	.long 0x7c000624 | (r3 << 11)
+	PPC_TLBIVAX(0, R3)
 	isync
 	eieio
 	tlbsync
@@ -227,11 +220,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_476_DD2)
 	bl	2f
 2:	mflr	r6
 	li	r7,32
-	ICBT(0,r6,r7)		/* touch next cache line */
+	PPC_ICBT(0,R6,R7)		/* touch next cache line */
 	add	r6,r6,r7
-	ICBT(0,r6,r7)		/* touch next cache line */
+	PPC_ICBT(0,R6,R7)		/* touch next cache line */
 	add	r6,r6,r7
-	ICBT(0,r6,r7)		/* touch next cache line */
+	PPC_ICBT(0,R6,R7)		/* touch next cache line */
 	sync
 	nop
 	nop
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 1fc8109..8a5dfaf 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -134,6 +134,12 @@ DECLARE_LOAD_FUNC(sk_load_byte_msh);
 				     ___PPC_RS(a) | IMM_L(i))
 #define PPC_ORIS(d, a, i)	EMIT(PPC_INST_ORIS | ___PPC_RA(d) |	      \
 				     ___PPC_RS(a) | IMM_L(i))
+#define PPC_XOR(d, a, b)	EMIT(PPC_INST_XOR | ___PPC_RA(d) |	      \
+				     ___PPC_RS(a) | ___PPC_RB(b))
+#define PPC_XORI(d, a, i)	EMIT(PPC_INST_XORI | ___PPC_RA(d) |	      \
+				     ___PPC_RS(a) | IMM_L(i))
+#define PPC_XORIS(d, a, i)	EMIT(PPC_INST_XORIS | ___PPC_RA(d) |	      \
+				     ___PPC_RS(a) | IMM_L(i))
 #define PPC_SLW(d, a, s)	EMIT(PPC_INST_SLW | ___PPC_RA(d) |	      \
 				     ___PPC_RS(a) | ___PPC_RB(s))
 #define PPC_SRW(d, a, s)	EMIT(PPC_INST_SRW | ___PPC_RA(d) |	      \
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index dd11306..e834f1e 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -13,6 +13,8 @@
 #include <asm/cacheflush.h>
 #include <linux/netdevice.h>
 #include <linux/filter.h>
+#include <linux/if_vlan.h>
+
 #include "bpf_jit.h"
 
 #ifndef __BIG_ENDIAN
@@ -89,6 +91,8 @@ static void bpf_jit_build_prologue(struct sk_filter *fp, u32 *image,
 	case BPF_S_ANC_IFINDEX:
 	case BPF_S_ANC_MARK:
 	case BPF_S_ANC_RXHASH:
+	case BPF_S_ANC_VLAN_TAG:
+	case BPF_S_ANC_VLAN_TAG_PRESENT:
 	case BPF_S_ANC_CPU:
 	case BPF_S_ANC_QUEUE:
 	case BPF_S_LD_W_ABS:
@@ -232,6 +236,17 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
 			if (K >= 65536)
 				PPC_ORIS(r_A, r_A, IMM_H(K));
 			break;
+		case BPF_S_ANC_ALU_XOR_X:
+		case BPF_S_ALU_XOR_X: /* A ^= X */
+			ctx->seen |= SEEN_XREG;
+			PPC_XOR(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_XOR_K: /* A ^= K */
+			if (IMM_L(K))
+				PPC_XORI(r_A, r_A, IMM_L(K));
+			if (K >= 65536)
+				PPC_XORIS(r_A, r_A, IMM_H(K));
+			break;
 		case BPF_S_ALU_LSH_X: /* A <<= X; */
 			ctx->seen |= SEEN_XREG;
 			PPC_SLW(r_A, r_A, r_X);
@@ -371,6 +386,16 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
 			PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
 							  rxhash));
 			break;
+		case BPF_S_ANC_VLAN_TAG:
+		case BPF_S_ANC_VLAN_TAG_PRESENT:
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
+			PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+							  vlan_tci));
+			if (filter[i].code == BPF_S_ANC_VLAN_TAG)
+				PPC_ANDI(r_A, r_A, VLAN_VID_MASK);
+			else
+				PPC_ANDI(r_A, r_A, VLAN_TAG_PRESENT);
+			break;
 		case BPF_S_ANC_QUEUE:
 			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
 						  queue_mapping) != 2);
diff --git a/arch/powerpc/perf/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c
index 441af08..2ee01e3 100644
--- a/arch/powerpc/perf/power7-pmu.c
+++ b/arch/powerpc/perf/power7-pmu.c
@@ -54,8 +54,10 @@
  * Layout of constraint bits:
  * 6666555555555544444444443333333333222222222211111111110000000000
  * 3210987654321098765432109876543210987654321098765432109876543210
- *                                                 [  ><><><><><><>
- *                                                  NC P6P5P4P3P2P1
+ *                                              < ><  ><><><><><><>
+ *                                              L2  NC P6P5P4P3P2P1
+ *
+ * L2 - 16-18 - Required L2SEL value (select field)
  *
  * NC - number of counters
  *     15: NC error 0x8000
@@ -72,7 +74,7 @@
 static int power7_get_constraint(u64 event, unsigned long *maskp,
 				 unsigned long *valp)
 {
-	int pmc, sh;
+	int pmc, sh, unit;
 	unsigned long mask = 0, value = 0;
 
 	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
@@ -90,6 +92,15 @@ static int power7_get_constraint(u64 event, unsigned long *maskp,
 		mask  |= 0x8000;
 		value |= 0x1000;
 	}
+
+	unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
+	if (unit == 6) {
+		/* L2SEL must be identical across events */
+		int l2sel = (event >> PM_L2SEL_SH) & PM_L2SEL_MSK;
+		mask  |= 0x7 << 16;
+		value |= l2sel << 16;
+	}
+
 	*maskp = mask;
 	*valp = value;
 	return 0;
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index b62508b..c169998 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -2,7 +2,6 @@ config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
 	select FSL_SOC
-	select FB_FSL_DIU
 	select IPIC
 	select PPC_CLOCK
 	select PPC_PCI_CHOICE
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c
index dcef6ad..0a134e0 100644
--- a/arch/powerpc/platforms/512x/mpc5121_ads.c
+++ b/arch/powerpc/platforms/512x/mpc5121_ads.c
@@ -42,7 +42,10 @@ static void __init mpc5121_ads_setup_arch(void)
 	for_each_compatible_node(np, "pci", "fsl,mpc5121-pci")
 		mpc83xx_add_bridge(np);
 #endif
+
+#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
 	mpc512x_setup_diu();
+#endif
 }
 
 static void __init mpc5121_ads_init_IRQ(void)
diff --git a/arch/powerpc/platforms/512x/mpc512x.h b/arch/powerpc/platforms/512x/mpc512x.h
index 1ab6d11..c32b399 100644
--- a/arch/powerpc/platforms/512x/mpc512x.h
+++ b/arch/powerpc/platforms/512x/mpc512x.h
@@ -16,6 +16,13 @@ extern void __init mpc512x_init(void);
 extern int __init mpc5121_clk_init(void);
 void __init mpc512x_declare_of_platform_devices(void);
 extern void mpc512x_restart(char *cmd);
-extern void mpc512x_init_diu(void);
-extern void mpc512x_setup_diu(void);
+
+#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+void mpc512x_init_diu(void);
+void mpc512x_setup_diu(void);
+#else
+#define mpc512x_init_diu NULL
+#define mpc512x_setup_diu NULL
+#endif
+
 #endif				/* __MPC512X_H__ */
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index 1650e09..35f14fd 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -58,6 +58,8 @@ void mpc512x_restart(char *cmd)
 		;
 }
 
+#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+
 struct fsl_diu_shared_fb {
 	u8		gamma[0x300];	/* 32-bit aligned! */
 	struct diu_ad	ad0;		/* 32-bit aligned! */
@@ -66,25 +68,6 @@ struct fsl_diu_shared_fb {
 	bool		in_use;
 };
 
-u32 mpc512x_get_pixel_format(enum fsl_diu_monitor_port port,
-			     unsigned int bits_per_pixel)
-{
-	switch (bits_per_pixel) {
-	case 32:
-		return 0x88883316;
-	case 24:
-		return 0x88082219;
-	case 16:
-		return 0x65053118;
-	}
-	return 0x00000400;
-}
-
-void mpc512x_set_gamma_table(enum fsl_diu_monitor_port port,
-			     char *gamma_table_base)
-{
-}
-
 void mpc512x_set_monitor_port(enum fsl_diu_monitor_port port)
 {
 }
@@ -320,14 +303,14 @@ void __init mpc512x_setup_diu(void)
 		}
 	}
 
-	diu_ops.get_pixel_format	= mpc512x_get_pixel_format;
-	diu_ops.set_gamma_table		= mpc512x_set_gamma_table;
 	diu_ops.set_monitor_port	= mpc512x_set_monitor_port;
 	diu_ops.set_pixel_clock		= mpc512x_set_pixel_clock;
 	diu_ops.valid_monitor_port	= mpc512x_valid_monitor_port;
 	diu_ops.release_bootmem		= mpc512x_release_bootmem;
 }
 
+#endif
+
 void __init mpc512x_init_IRQ(void)
 {
 	struct device_node *np;
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index 448d862..1843bc9 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -4,7 +4,7 @@
  * Written by: Grant Likely <grant.likely@secretlab.ca>
  *
  * Copyright (C) Secret Lab Technologies Ltd. 2006. All rights reserved.
- * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ * Copyright 2006 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Description:
  * This program is free software; you can redistribute  it and/or modify it
diff --git a/arch/powerpc/platforms/52xx/mpc5200_simple.c b/arch/powerpc/platforms/52xx/mpc5200_simple.c
index 9cf3602..792a301 100644
--- a/arch/powerpc/platforms/52xx/mpc5200_simple.c
+++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c
@@ -50,6 +50,7 @@ static void __init mpc5200_simple_setup_arch(void)
 
 /* list of the supported boards */
 static const char *board[] __initdata = {
+	"anonymous,a3m071",
 	"anonymous,a4m072",
 	"anon,charon",
 	"ifm,o2d",
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
index 028470b..a51cb07 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
@@ -526,7 +526,7 @@ EXPORT_SYMBOL(mpc52xx_gpt_timer_period);
 
 #define WDT_IDENTITY	    "mpc52xx watchdog on GPT0"
 
-/* wdt_is_active stores wether or not the /dev/watchdog device is opened */
+/* wdt_is_active stores whether or not the /dev/watchdog device is opened */
 static unsigned long wdt_is_active;
 
 /* wdt-capable gpt */
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
index 2351f9e..16150fa 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
@@ -578,18 +578,4 @@ static struct platform_driver mpc52xx_lpbfifo_driver = {
 	.probe = mpc52xx_lpbfifo_probe,
 	.remove = __devexit_p(mpc52xx_lpbfifo_remove),
 };
-
-/***********************************************************************
- * Module init/exit
- */
-static int __init mpc52xx_lpbfifo_init(void)
-{
-	return platform_driver_register(&mpc52xx_lpbfifo_driver);
-}
-module_init(mpc52xx_lpbfifo_init);
-
-static void __exit mpc52xx_lpbfifo_exit(void)
-{
-	platform_driver_unregister(&mpc52xx_lpbfifo_driver);
-}
-module_exit(mpc52xx_lpbfifo_exit);
+module_platform_driver(mpc52xx_lpbfifo_driver);
diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
index 328d221..74861a7 100644
--- a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
+++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
@@ -16,7 +16,6 @@
 #include <linux/spinlock.h>
 #include <linux/irq.h>
 #include <linux/types.h>
-#include <linux/bootmem.h>
 #include <linux/slab.h>
 
 #include <asm/io.h>
@@ -149,7 +148,7 @@ int __init pq2ads_pci_init_irq(void)
 	priv->regs = of_iomap(np, 0);
 	if (!priv->regs) {
 		printk(KERN_ERR "Cannot map PCI PIC registers.\n");
-		goto out_free_bootmem;
+		goto out_free_kmalloc;
 	}
 
 	/* mask all PCI interrupts */
@@ -171,9 +170,8 @@ int __init pq2ads_pci_init_irq(void)
 
 out_unmap_regs:
 	iounmap(priv->regs);
-out_free_bootmem:
-	free_bootmem((unsigned long)priv,
-	             sizeof(struct pq2ads_pci_pic));
+out_free_kmalloc:
+	kfree(priv);
 	of_node_put(np);
 out_unmap_irq:
 	irq_dispose_mapping(irq);
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index d440435..8d76220 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ * Copyright 2006 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Description:
  * MPC832xE MDS board specific routines.
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index 1b1f6c8..1a26d2f 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ * Copyright 2006 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Author: Li Yang <LeoLi@freescale.com>
  *	   Yin Olivia <Hong-hua.Yin@freescale.com>
diff --git a/arch/powerpc/platforms/83xx/mpc836x_rdk.c b/arch/powerpc/platforms/83xx/mpc836x_rdk.c
index f8769d7..b63b42d 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_rdk.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_rdk.c
@@ -1,7 +1,7 @@
 /*
  * MPC8360E-RDK board file.
  *
- * Copyright (c) 2006  Freescale Semicondutor, Inc.
+ * Copyright (c) 2006  Freescale Semiconductor, Inc.
  * Copyright (c) 2007-2008  MontaVista Software, Inc.
  *
  * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
index eca1f09..9813c81 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
@@ -1,7 +1,7 @@
 /*
  * arch/powerpc/platforms/83xx/mpc837x_rdb.c
  *
- * Copyright (C) 2007 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
  *
  * MPC837x RDB board specific routines
  *
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 8498f73..bd12588 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2010, 2012 Freescale Semicondutor, Inc.
+ * Copyright (C) 2006-2010, 2012 Freescale Semiconductor, Inc.
  * All rights reserved.
  *
  * Author: Andy Fleming <afleming@freescale.com>
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 848a3e9..7328b8d 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -249,7 +249,7 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
 		goto exit;
 	}
 
-	iprop = of_get_property(law_node, "fsl,num-laws", 0);
+	iprop = of_get_property(law_node, "fsl,num-laws", NULL);
 	if (!iprop) {
 		pr_err("p1022ds: LAW node is missing fsl,num-laws property\n");
 		goto exit;
@@ -539,7 +539,7 @@ static void __init p1022_ds_setup_arch(void)
 				};
 
 				/*
-				 * prom_update_property() is called before
+				 * of_update_property() is called before
 				 * kmalloc() is available, so the 'new' object
 				 * should be allocated in the global area.
 				 * The easiest way is to do that is to
@@ -548,7 +548,7 @@ static void __init p1022_ds_setup_arch(void)
 				 */
 				pr_info("p1022ds: disabling %s node",
 					np2->full_name);
-				prom_update_property(np2, &nor_status);
+				of_update_property(np2, &nor_status);
 				of_node_put(np2);
 			}
 
@@ -564,7 +564,7 @@ static void __init p1022_ds_setup_arch(void)
 
 				pr_info("p1022ds: disabling %s node",
 					np2->full_name);
-				prom_update_property(np2, &nand_status);
+				of_update_property(np2, &nand_status);
 				of_node_put(np2);
 			}
 
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 6fcfa12..148c2f2 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -128,6 +128,19 @@ static void __cpuinit smp_85xx_mach_cpu_die(void)
 }
 #endif
 
+static inline void flush_spin_table(void *spin_table)
+{
+	flush_dcache_range((ulong)spin_table,
+		(ulong)spin_table + sizeof(struct epapr_spin_table));
+}
+
+static inline u32 read_spin_table_addr_l(void *spin_table)
+{
+	flush_dcache_range((ulong)spin_table,
+		(ulong)spin_table + sizeof(struct epapr_spin_table));
+	return in_be32(&((struct epapr_spin_table *)spin_table)->addr_l);
+}
+
 static int __cpuinit smp_85xx_kick_cpu(int nr)
 {
 	unsigned long flags;
@@ -161,8 +174,8 @@ static int __cpuinit smp_85xx_kick_cpu(int nr)
 
 	/* Map the spin table */
 	if (ioremappable)
-		spin_table = ioremap(*cpu_rel_addr,
-				sizeof(struct epapr_spin_table));
+		spin_table = ioremap_prot(*cpu_rel_addr,
+			sizeof(struct epapr_spin_table), _PAGE_COHERENT);
 	else
 		spin_table = phys_to_virt(*cpu_rel_addr);
 
@@ -173,7 +186,16 @@ static int __cpuinit smp_85xx_kick_cpu(int nr)
 	generic_set_cpu_up(nr);
 
 	if (system_state == SYSTEM_RUNNING) {
+		/*
+		 * To keep it compatible with old boot program which uses
+		 * cache-inhibit spin table, we need to flush the cache
+		 * before accessing spin table to invalidate any staled data.
+		 * We also need to flush the cache after writing to spin
+		 * table to push data out.
+		 */
+		flush_spin_table(spin_table);
 		out_be32(&spin_table->addr_l, 0);
+		flush_spin_table(spin_table);
 
 		/*
 		 * We don't set the BPTR register here since it already points
@@ -181,9 +203,14 @@ static int __cpuinit smp_85xx_kick_cpu(int nr)
 		 */
 		mpic_reset_core(hw_cpu);
 
-		/* wait until core is ready... */
-		if (!spin_event_timeout(in_be32(&spin_table->addr_l) == 1,
-						10000, 100)) {
+		/*
+		 * wait until core is ready...
+		 * We need to invalidate the stale data, in case the boot
+		 * loader uses a cache-inhibited spin table.
+		 */
+		if (!spin_event_timeout(
+				read_spin_table_addr_l(spin_table) == 1,
+				10000, 100)) {
 			pr_err("%s: timeout waiting for core %d to reset\n",
 							__func__, hw_cpu);
 			ret = -ENOENT;
@@ -194,12 +221,10 @@ static int __cpuinit smp_85xx_kick_cpu(int nr)
 		__secondary_hold_acknowledge = -1;
 	}
 #endif
+	flush_spin_table(spin_table);
 	out_be32(&spin_table->pir, hw_cpu);
 	out_be32(&spin_table->addr_l, __pa(__early_start));
-
-	if (!ioremappable)
-		flush_dcache_range((ulong)spin_table,
-			(ulong)spin_table + sizeof(struct epapr_spin_table));
+	flush_spin_table(spin_table);
 
 	/* Wait a bit for the CPU to ack. */
 	if (!spin_event_timeout(__secondary_hold_acknowledge == hw_cpu,
@@ -213,13 +238,11 @@ out:
 #else
 	smp_generic_kick_cpu(nr);
 
+	flush_spin_table(spin_table);
 	out_be32(&spin_table->pir, hw_cpu);
 	out_be64((u64 *)(&spin_table->addr_h),
 	  __pa((u64)*((unsigned long long *)generic_secondary_smp_init)));
-
-	if (!ioremappable)
-		flush_dcache_range((ulong)spin_table,
-			(ulong)spin_table + sizeof(struct epapr_spin_table));
+	flush_spin_table(spin_table);
 #endif
 
 	local_irq_restore(flags);
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index a817398..04d9d31 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -353,5 +353,7 @@ define_machine(mpc86xx_hpcd) {
 	.time_init		= mpc86xx_time_init,
 	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= udbg_progress,
+#ifdef CONFIG_PCI
 	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
 };
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index e7a896a..48a920d 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -90,6 +90,7 @@ config MPIC
 config PPC_EPAPR_HV_PIC
 	bool
 	default n
+	select EPAPR_PARAVIRT
 
 config MPIC_WEIRD
 	bool
diff --git a/arch/powerpc/platforms/cell/celleb_pci.c b/arch/powerpc/platforms/cell/celleb_pci.c
index abc8af4..1735681 100644
--- a/arch/powerpc/platforms/cell/celleb_pci.c
+++ b/arch/powerpc/platforms/cell/celleb_pci.c
@@ -401,11 +401,11 @@ error:
 	} else {
 		if (config && *config) {
 			size = 256;
-			free_bootmem((unsigned long)(*config), size);
+			free_bootmem(__pa(*config), size);
 		}
 		if (res && *res) {
 			size = sizeof(struct celleb_pci_resource);
-			free_bootmem((unsigned long)(*res), size);
+			free_bootmem(__pa(*res), size);
 		}
 	}
 
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index dca2136..e56bb65 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -728,7 +728,7 @@ static struct cbe_iommu * __init cell_iommu_alloc(struct device_node *np)
 		 nid, np->full_name);
 
 	/* XXX todo: If we can have multiple windows on the same IOMMU, which
-	 * isn't the case today, we probably want here to check wether the
+	 * isn't the case today, we probably want here to check whether the
 	 * iommu for that node is already setup.
 	 * However, there might be issue with getting the size right so let's
 	 * ignore that for now. We might want to completely get rid of the
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index d8b7cc8..8e29944 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -148,7 +148,7 @@ static int spider_set_irq_type(struct irq_data *d, unsigned int type)
 
 	/* Configure the source. One gross hack that was there before and
 	 * that I've kept around is the priority to the BE which I set to
-	 * be the same as the interrupt source number. I don't know wether
+	 * be the same as the interrupt source number. I don't know whether
 	 * that's supposed to make any kind of sense however, we'll have to
 	 * decide that, but for now, I'm not changing the behaviour.
 	 */
@@ -220,7 +220,7 @@ static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc)
 /* For hooking up the cascace we have a problem. Our device-tree is
  * crap and we don't know on which BE iic interrupt we are hooked on at
  * least not the "standard" way. We can reconstitute it based on two
- * informations though: which BE node we are connected to and wether
+ * informations though: which BE node we are connected to and whether
  * we are connected to IOIF0 or IOIF1. Right now, we really only care
  * about the IBM cell blade and we know that its firmware gives us an
  * interrupt-map property which is pretty strange.
@@ -232,7 +232,7 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
 	int imaplen, intsize, unit;
 	struct device_node *iic;
 
-	/* First, we check wether we have a real "interrupts" in the device
+	/* 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;
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 965d381..25db92a 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -1094,7 +1094,7 @@ static int show_spu_loadavg(struct seq_file *s, void *private)
 		LOAD_INT(c), LOAD_FRAC(c),
 		count_active_contexts(),
 		atomic_read(&nr_spu_contexts),
-		current->nsproxy->pid_ns->last_pid);
+		task_active_pid_ns(current)->last_pid);
 	return 0;
 }
 
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c
index 6417119..311b804 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_32.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_32.c
@@ -55,6 +55,7 @@ static unsigned int low_freq;
 static unsigned int hi_freq;
 static unsigned int cur_freq;
 static unsigned int sleep_freq;
+static unsigned long transition_latency;
 
 /*
  * Different models uses different mechanisms to switch the frequency
@@ -403,7 +404,7 @@ static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
 	if (policy->cpu != 0)
 		return -ENODEV;
 
-	policy->cpuinfo.transition_latency	= CPUFREQ_ETERNAL;
+	policy->cpuinfo.transition_latency	= transition_latency;
 	policy->cur = cur_freq;
 
 	cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu);
@@ -658,12 +659,14 @@ static int __init pmac_cpufreq_setup(void)
 	if (!value)
 		goto out;
 	cur_freq = (*value) / 1000;
+	transition_latency = CPUFREQ_ETERNAL;
 
 	/*  Check for 7447A based MacRISC3 */
 	if (of_machine_is_compatible("MacRISC3") &&
 	    of_get_property(cpunode, "dynamic-power-step", NULL) &&
 	    PVR_VER(mfspr(SPRN_PVR)) == 0x8003) {
 		pmac_cpufreq_init_7447A(cpunode);
+		transition_latency = 8000000;
 	/* Check for other MacRISC3 machines */
 	} else if (of_machine_is_compatible("PowerBook3,4") ||
 		   of_machine_is_compatible("PowerBook3,5") ||
diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c
index b0c3777..d588e48 100644
--- a/arch/powerpc/platforms/powermac/pfunc_core.c
+++ b/arch/powerpc/platforms/powermac/pfunc_core.c
@@ -686,7 +686,7 @@ static int pmf_add_functions(struct pmf_device *dev, void *driverdata)
 	int count = 0;
 
 	for (pp = dev->node->properties; pp != 0; pp = pp->next) {
-		char *name;
+		const char *name;
 		if (strncmp(pp->name, PP_PREFIX, plen) != 0)
 			continue;
 		name = pp->name + plen;
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index c4e6305..31036b5 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -529,7 +529,7 @@ static int __init pmac_pic_probe_mpic(void)
 void __init pmac_pic_init(void)
 {
 	/* We configure the OF parsing based on our oldworld vs. newworld
-	 * platform type and wether we were booted by BootX.
+	 * platform type and whether we were booted by BootX.
 	 */
 #ifdef CONFIG_PPC32
 	if (!pmac_newworld)
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 471aa3c..53d052e 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -34,24 +34,12 @@
 #include "powernv.h"
 #include "pci.h"
 
-static int __pe_printk(const char *level, const struct pnv_ioda_pe *pe,
-		       struct va_format *vaf)
-{
-	char pfix[32];
-
-	if (pe->pdev)
-		strlcpy(pfix, dev_name(&pe->pdev->dev), sizeof(pfix));
-	else
-		sprintf(pfix, "%04x:%02x     ",
-			pci_domain_nr(pe->pbus), pe->pbus->number);
-	return printk("pci %s%s: [PE# %.3d] %pV", level, pfix, pe->pe_number, vaf);
-}
-
 #define define_pe_printk_level(func, kern_level)		\
 static int func(const struct pnv_ioda_pe *pe, const char *fmt, ...)	\
 {								\
 	struct va_format vaf;					\
 	va_list args;						\
+	char pfix[32];						\
 	int r;							\
 								\
 	va_start(args, fmt);					\
@@ -59,7 +47,16 @@ static int func(const struct pnv_ioda_pe *pe, const char *fmt, ...)	\
 	vaf.fmt = fmt;						\
 	vaf.va = &args;						\
 								\
-	r = __pe_printk(kern_level, pe, &vaf);			\
+	if (pe->pdev)						\
+		strlcpy(pfix, dev_name(&pe->pdev->dev),		\
+			sizeof(pfix));				\
+	else							\
+		sprintf(pfix, "%04x:%02x     ",			\
+			pci_domain_nr(pe->pbus),		\
+			pe->pbus->number);			\
+	r = printk(kern_level "pci %s: [PE# %.3d] %pV",		\
+		   pfix, pe->pe_number, &vaf);			\
+								\
 	va_end(args);						\
 								\
 	return r;						\
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index 46b7f02..e87c194 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -48,7 +48,7 @@ config PS3_HTAB_SIZE
 	  system will have optimal runtime performance.
 
 config PS3_DYNAMIC_DMA
-	depends on PPC_PS3 && EXPERIMENTAL
+	depends on PPC_PS3
 	bool "PS3 Platform dynamic DMA page table management"
 	default n
 	help
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
index 56d26bc..0978713 100644
--- a/arch/powerpc/platforms/ps3/os-area.c
+++ b/arch/powerpc/platforms/ps3/os-area.c
@@ -280,13 +280,13 @@ static void os_area_set_property(struct device_node *node,
 
 	if (tmp) {
 		pr_debug("%s:%d found %s\n", __func__, __LINE__, prop->name);
-		prom_remove_property(node, tmp);
+		of_remove_property(node, tmp);
 	}
 
-	result = prom_add_property(node, prop);
+	result = of_add_property(node, prop);
 
 	if (result)
-		pr_debug("%s:%d prom_set_property failed\n", __func__,
+		pr_debug("%s:%d of_set_property failed\n", __func__,
 			__LINE__);
 }
 
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index 0f1b706..a1a7b9a 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -13,17 +13,16 @@
 #include <linux/kernel.h>
 #include <linux/kref.h>
 #include <linux/notifier.h>
-#include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <linux/cpu.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 #include "offline_states.h"
 
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/uaccess.h>
 #include <asm/rtas.h>
-#include <asm/pSeries_reconfig.h>
 
 struct cc_workarea {
 	u32	drc_index;
@@ -255,9 +254,6 @@ static struct device_node *derive_parent(const char *path)
 
 int dlpar_attach_node(struct device_node *dn)
 {
-#ifdef CONFIG_PROC_DEVICETREE
-	struct proc_dir_entry *ent;
-#endif
 	int rc;
 
 	of_node_set_flag(dn, OF_DYNAMIC);
@@ -266,44 +262,26 @@ int dlpar_attach_node(struct device_node *dn)
 	if (!dn->parent)
 		return -ENOMEM;
 
-	rc = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, dn);
+	rc = of_attach_node(dn);
 	if (rc) {
 		printk(KERN_ERR "Failed to add device node %s\n",
 		       dn->full_name);
 		return rc;
 	}
 
-	of_attach_node(dn);
-
-#ifdef CONFIG_PROC_DEVICETREE
-	ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde);
-	if (ent)
-		proc_device_tree_add_node(dn, ent);
-#endif
-
 	of_node_put(dn->parent);
 	return 0;
 }
 
 int dlpar_detach_node(struct device_node *dn)
 {
-#ifdef CONFIG_PROC_DEVICETREE
-	struct device_node *parent = dn->parent;
-	struct property *prop = dn->properties;
-
-	while (prop) {
-		remove_proc_entry(prop->name, dn->pde);
-		prop = prop->next;
-	}
+	int rc;
 
-	if (dn->pde)
-		remove_proc_entry(dn->pde->name, parent->pde);
-#endif
+	rc = of_detach_node(dn);
+	if (rc)
+		return rc;
 
-	pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, dn);
-	of_detach_node(dn);
 	of_node_put(dn); /* Must decrement the refcount */
-
 	return 0;
 }
 
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c
index 0b0eff0..7b56118 100644
--- a/arch/powerpc/platforms/pseries/firmware.c
+++ b/arch/powerpc/platforms/pseries/firmware.c
@@ -56,6 +56,7 @@ firmware_features_table[FIRMWARE_MAX_FEATURES] = {
 	{FW_FEATURE_MULTITCE,		"hcall-multi-tce"},
 	{FW_FEATURE_SPLPAR,		"hcall-splpar"},
 	{FW_FEATURE_VPHN,		"hcall-vphn"},
+	{FW_FEATURE_SET_MODE,		"hcall-set-mode"},
 };
 
 /* Build up the firmware features bitmask using the contents of
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 64c97d8..a389562 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -23,12 +23,12 @@
 #include <linux/delay.h>
 #include <linux/sched.h>	/* for idle_task_exit */
 #include <linux/cpu.h>
+#include <linux/of.h>
 #include <asm/prom.h>
 #include <asm/rtas.h>
 #include <asm/firmware.h>
 #include <asm/machdep.h>
 #include <asm/vdso_datapage.h>
-#include <asm/pSeries_reconfig.h>
 #include <asm/xics.h>
 #include "plpar_wrappers.h"
 #include "offline_states.h"
@@ -333,10 +333,10 @@ static int pseries_smp_notifier(struct notifier_block *nb,
 	int err = 0;
 
 	switch (action) {
-	case PSERIES_RECONFIG_ADD:
+	case OF_RECONFIG_ATTACH_NODE:
 		err = pseries_add_processor(node);
 		break;
-	case PSERIES_RECONFIG_REMOVE:
+	case OF_RECONFIG_DETACH_NODE:
 		pseries_remove_processor(node);
 		break;
 	}
@@ -399,7 +399,7 @@ static int __init pseries_cpu_hotplug_init(void)
 
 	/* Processors can be added/removed only on LPAR */
 	if (firmware_has_feature(FW_FEATURE_LPAR)) {
-		pSeries_reconfig_notifier_register(&pseries_smp_nb);
+		of_reconfig_notifier_register(&pseries_smp_nb);
 		cpu_maps_update_begin();
 		if (cede_offline_enabled && parse_cede_parameters() == 0) {
 			default_offline_state = CPU_STATE_INACTIVE;
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index ecdb0a6..2372c60 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -16,7 +16,6 @@
 
 #include <asm/firmware.h>
 #include <asm/machdep.h>
-#include <asm/pSeries_reconfig.h>
 #include <asm/sparsemem.h>
 
 static unsigned long get_memblock_size(void)
@@ -187,42 +186,69 @@ static int pseries_add_memory(struct device_node *np)
 	return (ret < 0) ? -EINVAL : 0;
 }
 
-static int pseries_drconf_memory(unsigned long *base, unsigned int action)
+static int pseries_update_drconf_memory(struct of_prop_reconfig *pr)
 {
+	struct of_drconf_cell *new_drmem, *old_drmem;
 	unsigned long memblock_size;
-	int rc;
+	u32 entries;
+	u32 *p;
+	int i, rc = -EINVAL;
 
 	memblock_size = get_memblock_size();
 	if (!memblock_size)
 		return -EINVAL;
 
-	if (action == PSERIES_DRCONF_MEM_ADD) {
-		rc = memblock_add(*base, memblock_size);
-		rc = (rc < 0) ? -EINVAL : 0;
-	} else if (action == PSERIES_DRCONF_MEM_REMOVE) {
-		rc = pseries_remove_memblock(*base, memblock_size);
-	} else {
-		rc = -EINVAL;
+	p = (u32 *)of_get_property(pr->dn, "ibm,dynamic-memory", NULL);
+	if (!p)
+		return -EINVAL;
+
+	/* The first int of the property is the number of lmb's described
+	 * by the property. This is followed by an array of of_drconf_cell
+	 * entries. Get the niumber of entries and skip to the array of
+	 * of_drconf_cell's.
+	 */
+	entries = *p++;
+	old_drmem = (struct of_drconf_cell *)p;
+
+	p = (u32 *)pr->prop->value;
+	p++;
+	new_drmem = (struct of_drconf_cell *)p;
+
+	for (i = 0; i < entries; i++) {
+		if ((old_drmem[i].flags & DRCONF_MEM_ASSIGNED) &&
+		    (!(new_drmem[i].flags & DRCONF_MEM_ASSIGNED))) {
+			rc = pseries_remove_memblock(old_drmem[i].base_addr,
+						     memblock_size);
+			break;
+		} else if ((!(old_drmem[i].flags & DRCONF_MEM_ASSIGNED)) &&
+			   (new_drmem[i].flags & DRCONF_MEM_ASSIGNED)) {
+			rc = memblock_add(old_drmem[i].base_addr,
+					  memblock_size);
+			rc = (rc < 0) ? -EINVAL : 0;
+			break;
+		}
 	}
 
 	return rc;
 }
 
 static int pseries_memory_notifier(struct notifier_block *nb,
-				unsigned long action, void *node)
+				   unsigned long action, void *node)
 {
+	struct of_prop_reconfig *pr;
 	int err = 0;
 
 	switch (action) {
-	case PSERIES_RECONFIG_ADD:
+	case OF_RECONFIG_ATTACH_NODE:
 		err = pseries_add_memory(node);
 		break;
-	case PSERIES_RECONFIG_REMOVE:
+	case OF_RECONFIG_DETACH_NODE:
 		err = pseries_remove_memory(node);
 		break;
-	case PSERIES_DRCONF_MEM_ADD:
-	case PSERIES_DRCONF_MEM_REMOVE:
-		err = pseries_drconf_memory(node, action);
+	case OF_RECONFIG_UPDATE_PROPERTY:
+		pr = (struct of_prop_reconfig *)node;
+		if (!strcmp(pr->prop->name, "ibm,dynamic-memory"))
+			err = pseries_update_drconf_memory(pr);
 		break;
 	}
 	return notifier_from_errno(err);
@@ -235,7 +261,7 @@ static struct notifier_block pseries_mem_nb = {
 static int __init pseries_memory_hotplug_init(void)
 {
 	if (firmware_has_feature(FW_FEATURE_LPAR))
-		pSeries_reconfig_notifier_register(&pseries_mem_nb);
+		of_reconfig_notifier_register(&pseries_mem_nb);
 
 	return 0;
 }
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 6153eea..e2685ba 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -36,13 +36,13 @@
 #include <linux/dma-mapping.h>
 #include <linux/crash_dump.h>
 #include <linux/memory.h>
+#include <linux/of.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/rtas.h>
 #include <asm/iommu.h>
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
-#include <asm/pSeries_reconfig.h>
 #include <asm/firmware.h>
 #include <asm/tce.h>
 #include <asm/ppc-pci.h>
@@ -760,7 +760,7 @@ static void remove_ddw(struct device_node *np)
 	__remove_ddw(np, ddw_avail, liobn);
 
 delprop:
-	ret = prom_remove_property(np, win64);
+	ret = of_remove_property(np, win64);
 	if (ret)
 		pr_warning("%s: failed to remove direct window property: %d\n",
 			np->full_name, ret);
@@ -1070,7 +1070,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
 		goto out_free_window;
 	}
 
-	ret = prom_add_property(pdn, win64);
+	ret = of_add_property(pdn, win64);
 	if (ret) {
 		dev_err(&dev->dev, "unable to add dma window property for %s: %d",
 			 pdn->full_name, ret);
@@ -1294,7 +1294,7 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti
 	struct direct_window *window;
 
 	switch (action) {
-	case PSERIES_RECONFIG_REMOVE:
+	case OF_RECONFIG_DETACH_NODE:
 		if (pci && pci->iommu_table)
 			iommu_free_table(pci->iommu_table, np->full_name);
 
@@ -1357,7 +1357,7 @@ void iommu_init_early_pSeries(void)
 	}
 
 
-	pSeries_reconfig_notifier_register(&iommu_reconfig_nb);
+	of_reconfig_notifier_register(&iommu_reconfig_nb);
 	register_memory_notifier(&iommu_mem_nb);
 
 	set_pci_dma_ops(&dma_iommu_ops);
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
index dd30b12..6573808 100644
--- a/arch/powerpc/platforms/pseries/mobility.c
+++ b/arch/powerpc/platforms/pseries/mobility.c
@@ -116,7 +116,7 @@ static int update_dt_property(struct device_node *dn, struct property **prop,
 	}
 
 	if (!more) {
-		prom_update_property(dn, new_prop);
+		of_update_property(dn, new_prop);
 		new_prop = NULL;
 	}
 
@@ -172,7 +172,7 @@ static int update_dt_node(u32 phandle)
 
 			case 0x80000000:
 				prop = of_find_property(dn, prop_name, NULL);
-				prom_remove_property(dn, prop);
+				of_remove_property(dn, prop);
 				prop = NULL;
 				break;
 
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index 13e8cc4..e6cc34a 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -273,4 +273,35 @@ static inline long plpar_put_term_char(unsigned long termno, unsigned long len,
 			lbuf[1]);
 }
 
+/* Set various resource mode parameters */
+static inline long plpar_set_mode(unsigned long mflags, unsigned long resource,
+		unsigned long value1, unsigned long value2)
+{
+	return plpar_hcall_norets(H_SET_MODE, mflags, resource, value1, value2);
+}
+
+/*
+ * Enable relocation on exceptions on this partition
+ *
+ * Note: this call has a partition wide scope and can take a while to complete.
+ * If it returns H_LONG_BUSY_* it should be retried periodically until it
+ * returns H_SUCCESS.
+ */
+static inline long enable_reloc_on_exceptions(void)
+{
+	/* mflags = 3: Exceptions at 0xC000000000004000 */
+	return plpar_set_mode(3, 3, 0, 0);
+}
+
+/*
+ * Disable relocation on exceptions on this partition
+ *
+ * Note: this call has a partition wide scope and can take a while to complete.
+ * If it returns H_LONG_BUSY_* it should be retried periodically until it
+ * returns H_SUCCESS.
+ */
+static inline long disable_reloc_on_exceptions(void) {
+	return plpar_set_mode(0, 3, 0, 0);
+}
+
 #endif /* _PSERIES_PLPAR_WRAPPERS_H */
diff --git a/arch/powerpc/platforms/pseries/processor_idle.c b/arch/powerpc/platforms/pseries/processor_idle.c
index 45d00e5..4d806b4 100644
--- a/arch/powerpc/platforms/pseries/processor_idle.c
+++ b/arch/powerpc/platforms/pseries/processor_idle.c
@@ -36,7 +36,7 @@ static struct cpuidle_state *cpuidle_state_table;
 static inline void idle_loop_prolog(unsigned long *in_purr, ktime_t *kt_before)
 {
 
-	*kt_before = ktime_get_real();
+	*kt_before = ktime_get();
 	*in_purr = mfspr(SPRN_PURR);
 	/*
 	 * Indicate to the HV that we are idle. Now would be
@@ -50,7 +50,7 @@ static inline  s64 idle_loop_epilog(unsigned long in_purr, ktime_t kt_before)
 	get_lppaca()->wait_state_cycles += mfspr(SPRN_PURR) - in_purr;
 	get_lppaca()->idle = 0;
 
-	return ktime_to_us(ktime_sub(ktime_get_real(), kt_before));
+	return ktime_to_us(ktime_sub(ktime_get(), kt_before));
 }
 
 static int snooze_loop(struct cpuidle_device *dev,
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 39f71fb..d6491bd 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -16,55 +16,13 @@
 #include <linux/notifier.h>
 #include <linux/proc_fs.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/uaccess.h>
-#include <asm/pSeries_reconfig.h>
 #include <asm/mmu.h>
 
-
-
-/*
- * Routines for "runtime" addition and removal of device tree nodes.
- */
-#ifdef CONFIG_PROC_DEVICETREE
-/*
- * Add a node to /proc/device-tree.
- */
-static void add_node_proc_entries(struct device_node *np)
-{
-	struct proc_dir_entry *ent;
-
-	ent = proc_mkdir(strrchr(np->full_name, '/') + 1, np->parent->pde);
-	if (ent)
-		proc_device_tree_add_node(np, ent);
-}
-
-static void remove_node_proc_entries(struct device_node *np)
-{
-	struct property *pp = np->properties;
-	struct device_node *parent = np->parent;
-
-	while (pp) {
-		remove_proc_entry(pp->name, np->pde);
-		pp = pp->next;
-	}
-	if (np->pde)
-		remove_proc_entry(np->pde->name, parent->pde);
-}
-#else /* !CONFIG_PROC_DEVICETREE */
-static void add_node_proc_entries(struct device_node *np)
-{
-	return;
-}
-
-static void remove_node_proc_entries(struct device_node *np)
-{
-	return;
-}
-#endif /* CONFIG_PROC_DEVICETREE */
-
 /**
  *	derive_parent - basically like dirname(1)
  *	@path:  the full_name of a node to be added to the tree
@@ -97,28 +55,6 @@ static struct device_node *derive_parent(const char *path)
 	return parent;
 }
 
-static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain);
-
-int pSeries_reconfig_notifier_register(struct notifier_block *nb)
-{
-	return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb);
-}
-EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_register);
-
-void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
-{
-	blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb);
-}
-EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_unregister);
-
-int pSeries_reconfig_notify(unsigned long action, void *p)
-{
-	int err = blocking_notifier_call_chain(&pSeries_reconfig_chain,
-						action, p);
-
-	return notifier_to_errno(err);
-}
-
 static int pSeries_reconfig_add_node(const char *path, struct property *proplist)
 {
 	struct device_node *np;
@@ -142,16 +78,12 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
 		goto out_err;
 	}
 
-	err = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, np);
+	err = of_attach_node(np);
 	if (err) {
 		printk(KERN_ERR "Failed to add device node %s\n", path);
 		goto out_err;
 	}
 
-	of_attach_node(np);
-
-	add_node_proc_entries(np);
-
 	of_node_put(np->parent);
 
 	return 0;
@@ -179,11 +111,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np)
 		return -EBUSY;
 	}
 
-	remove_node_proc_entries(np);
-
-	pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, np);
 	of_detach_node(np);
-
 	of_node_put(parent);
 	of_node_put(np); /* Must decrement the refcount */
 	return 0;
@@ -281,12 +209,11 @@ static struct property *new_property(const char *name, const int length,
 	if (!new)
 		return NULL;
 
-	if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL)))
+	if (!(new->name = kstrdup(name, GFP_KERNEL)))
 		goto cleanup;
 	if (!(new->value = kmalloc(length + 1, GFP_KERNEL)))
 		goto cleanup;
 
-	strcpy(new->name, name);
 	memcpy(new->value, value, length);
 	*(((char *)new->value) + length) = 0;
 	new->length = length;
@@ -398,7 +325,7 @@ static int do_add_property(char *buf, size_t bufsize)
 	if (!prop)
 		return -ENOMEM;
 
-	prom_add_property(np, prop);
+	of_add_property(np, prop);
 
 	return 0;
 }
@@ -422,16 +349,15 @@ static int do_remove_property(char *buf, size_t bufsize)
 
 	prop = of_find_property(np, buf, NULL);
 
-	return prom_remove_property(np, prop);
+	return of_remove_property(np, prop);
 }
 
 static int do_update_property(char *buf, size_t bufsize)
 {
 	struct device_node *np;
-	struct pSeries_reconfig_prop_update upd_value;
 	unsigned char *value;
 	char *name, *end, *next_prop;
-	int rc, length;
+	int length;
 	struct property *newprop;
 	buf = parse_node(buf, bufsize, &np);
 	end = buf + bufsize;
@@ -453,41 +379,7 @@ static int do_update_property(char *buf, size_t bufsize)
 	if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size"))
 		slb_set_size(*(int *)value);
 
-	upd_value.node = np;
-	upd_value.property = newprop;
-	pSeries_reconfig_notify(PSERIES_UPDATE_PROPERTY, &upd_value);
-
-	rc = prom_update_property(np, newprop);
-	if (rc)
-		return rc;
-
-	/* For memory under the ibm,dynamic-reconfiguration-memory node
-	 * of the device tree, adding and removing memory is just an update
-	 * to the ibm,dynamic-memory property instead of adding/removing a
-	 * memory node in the device tree.  For these cases we still need to
-	 * involve the notifier chain.
-	 */
-	if (!strcmp(name, "ibm,dynamic-memory")) {
-		int action;
-
-		next_prop = parse_next_property(next_prop, end, &name,
-						&length, &value);
-		if (!next_prop)
-			return -EINVAL;
-
-		if (!strcmp(name, "add"))
-			action = PSERIES_DRCONF_MEM_ADD;
-		else
-			action = PSERIES_DRCONF_MEM_REMOVE;
-
-		rc = pSeries_reconfig_notify(action, value);
-		if (rc) {
-			prom_update_property(np, newprop);
-			return rc;
-		}
-	}
-
-	return 0;
+	return of_update_property(np, newprop);
 }
 
 /**
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index e3cb7ae..ca55882 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -40,6 +40,8 @@
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/cpuidle.h>
+#include <linux/of.h>
+#include <linux/kexec.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>
@@ -63,7 +65,6 @@
 #include <asm/smp.h>
 #include <asm/firmware.h>
 #include <asm/eeh.h>
-#include <asm/pSeries_reconfig.h>
 
 #include "plpar_wrappers.h"
 #include "pseries.h"
@@ -258,7 +259,7 @@ static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long act
 	int err = NOTIFY_OK;
 
 	switch (action) {
-	case PSERIES_RECONFIG_ADD:
+	case OF_RECONFIG_ATTACH_NODE:
 		pci = np->parent->data;
 		if (pci) {
 			update_dn_pci_info(np, pci->phb);
@@ -367,6 +368,65 @@ static void pSeries_idle(void)
 	}
 }
 
+/*
+ * Enable relocation on during exceptions. This has partition wide scope and
+ * may take a while to complete, if it takes longer than one second we will
+ * just give up rather than wasting any more time on this - if that turns out
+ * to ever be a problem in practice we can move this into a kernel thread to
+ * finish off the process later in boot.
+ */
+static int __init pSeries_enable_reloc_on_exc(void)
+{
+	long rc;
+	unsigned int delay, total_delay = 0;
+
+	while (1) {
+		rc = enable_reloc_on_exceptions();
+		if (!H_IS_LONG_BUSY(rc))
+			return rc;
+
+		delay = get_longbusy_msecs(rc);
+		total_delay += delay;
+		if (total_delay > 1000) {
+			pr_warn("Warning: Giving up waiting to enable "
+				"relocation on exceptions (%u msec)!\n",
+				total_delay);
+			return rc;
+		}
+
+		mdelay(delay);
+	}
+}
+
+#ifdef CONFIG_KEXEC
+static long pSeries_disable_reloc_on_exc(void)
+{
+	long rc;
+
+	while (1) {
+		rc = disable_reloc_on_exceptions();
+		if (!H_IS_LONG_BUSY(rc))
+			return rc;
+		mdelay(get_longbusy_msecs(rc));
+	}
+}
+
+static void pSeries_machine_kexec(struct kimage *image)
+{
+	long rc;
+
+	if (firmware_has_feature(FW_FEATURE_SET_MODE) &&
+	    (image->type != KEXEC_TYPE_CRASH)) {
+		rc = pSeries_disable_reloc_on_exc();
+		if (rc != H_SUCCESS)
+			pr_warning("Warning: Failed to disable relocation on "
+				   "exceptions: %ld\n", rc);
+	}
+
+	default_machine_kexec(image);
+}
+#endif
+
 static void __init pSeries_setup_arch(void)
 {
 	panic_timeout = 10;
@@ -389,7 +449,7 @@ static void __init pSeries_setup_arch(void)
 	/* Find and initialize PCI host bridges */
 	init_pci_config_tokens();
 	find_and_init_phbs();
-	pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb);
+	of_reconfig_notifier_register(&pci_dn_reconfig_nb);
 
 	pSeries_nvram_init();
 
@@ -402,6 +462,14 @@ static void __init pSeries_setup_arch(void)
 		ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
 	else
 		ppc_md.enable_pmcs = power4_enable_pmcs;
+
+	if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
+		long rc;
+		if ((rc = pSeries_enable_reloc_on_exc()) != H_SUCCESS) {
+			pr_warn("Unable to enable relocation on exceptions: "
+				"%ld\n", rc);
+		}
+	}
 }
 
 static int __init pSeries_init_panel(void)
@@ -659,4 +727,7 @@ define_machine(pseries) {
 	.progress		= rtas_progress,
 	.system_reset_exception = pSeries_system_reset_exception,
 	.machine_check_exception = pSeries_machine_check_exception,
+#ifdef CONFIG_KEXEC
+	.machine_kexec          = pSeries_machine_kexec,
+#endif
 };
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 71706bc..9fc0a49 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -38,7 +38,6 @@
 #include <asm/cputable.h>
 #include <asm/firmware.h>
 #include <asm/rtas.h>
-#include <asm/pSeries_reconfig.h>
 #include <asm/mpic.h>
 #include <asm/vdso_datapage.h>
 #include <asm/cputhreads.h>
diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c
index 02cf1e7..0eb871c 100644
--- a/arch/powerpc/sysdev/fsl_gtm.c
+++ b/arch/powerpc/sysdev/fsl_gtm.c
@@ -1,7 +1,7 @@
 /*
  * Freescale General-purpose Timers Module
  *
- * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ * Copyright (c) Freescale Semiconductor, Inc. 2006.
  *               Shlomi Gridish <gridish@freescale.com>
  *               Jerry Huang <Chang-Ming.Huang@freescale.com>
  * Copyright (c) MontaVista Software, Inc. 2008.
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 51ffafa..63c5f04 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -236,7 +236,6 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
 	u32 intr_index;
 	u32 have_shift = 0;
 	struct fsl_msi_cascade_data *cascade_data;
-	unsigned int ret;
 
 	cascade_data = irq_get_handler_data(irq);
 	msi_data = cascade_data->msi_data;
@@ -268,7 +267,9 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
 	case FSL_PIC_IP_IPIC:
 		msir_value = fsl_msi_read(msi_data->msi_regs, msir_index * 0x4);
 		break;
-	case FSL_PIC_IP_VMPIC:
+#ifdef CONFIG_EPAPR_PARAVIRT
+	case FSL_PIC_IP_VMPIC: {
+		unsigned int ret;
 		ret = fh_vmpic_get_msir(virq_to_hw(irq), &msir_value);
 		if (ret) {
 			pr_err("fsl-msi: fh_vmpic_get_msir() failed for "
@@ -277,6 +278,8 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
 		}
 		break;
 	}
+#endif
+	}
 
 	while (msir_value) {
 		intr_index = ffs(msir_value) - 1;
@@ -508,10 +511,12 @@ static const struct of_device_id fsl_of_msi_ids[] = {
 		.compatible = "fsl,ipic-msi",
 		.data = &ipic_msi_feature,
 	},
+#ifdef CONFIG_EPAPR_PARAVIRT
 	{
 		.compatible = "fsl,vmpic-msi",
 		.data = &vmpic_msi_feature,
 	},
+#endif
 	{}
 };
 
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index ffb93ae..5ba325b 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -89,7 +89,7 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask)
 	return 0;
 }
 
-static int __init setup_one_atmu(struct ccsr_pci __iomem *pci,
+static int setup_one_atmu(struct ccsr_pci __iomem *pci,
 	unsigned int index, const struct resource *res,
 	resource_size_t offset)
 {
@@ -126,7 +126,7 @@ static int __init setup_one_atmu(struct ccsr_pci __iomem *pci,
 }
 
 /* atmu setup for fsl pci/pcie controller */
-static void __init setup_pci_atmu(struct pci_controller *hose,
+static void setup_pci_atmu(struct pci_controller *hose,
 				  struct resource *rsrc)
 {
 	struct ccsr_pci __iomem *pci;
@@ -136,7 +136,7 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
 	u32 pcicsrbar = 0, pcicsrbar_sz;
 	u32 piwar = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL |
 			PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;
-	char *name = hose->dn->full_name;
+	const char *name = hose->dn->full_name;
 	const u64 *reg;
 	int len;
 
@@ -902,9 +902,42 @@ static int __devinit fsl_pci_probe(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int fsl_pci_resume(struct device *dev)
+{
+	struct pci_controller *hose;
+	struct resource pci_rsrc;
+
+	hose = pci_find_hose_for_OF_device(dev->of_node);
+	if (!hose)
+		return -ENODEV;
+
+	if (of_address_to_resource(dev->of_node, 0, &pci_rsrc)) {
+		dev_err(dev, "Get pci register base failed.");
+		return -ENODEV;
+	}
+
+	setup_pci_atmu(hose, &pci_rsrc);
+
+	return 0;
+}
+
+static const struct dev_pm_ops pci_pm_ops = {
+	.resume = fsl_pci_resume,
+};
+
+#define PCI_PM_OPS (&pci_pm_ops)
+
+#else
+
+#define PCI_PM_OPS NULL
+
+#endif
+
 static struct platform_driver fsl_pci_driver = {
 	.driver = {
 		.name = "fsl-pci",
+		.pm = PCI_PM_OPS,
 		.of_match_table = pci_ids,
 	},
 	.probe = fsl_pci_probe,
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index c449dbd..97118dc 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -253,6 +253,7 @@ struct platform_diu_data_ops diu_ops;
 EXPORT_SYMBOL(diu_ops);
 #endif
 
+#ifdef CONFIG_EPAPR_PARAVIRT
 /*
  * Restart the current partition
  *
@@ -278,3 +279,4 @@ void fsl_hv_halt(void)
 	pr_info("hv exit\n");
 	fh_partition_stop(-1);
 }
+#endif
diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c
index 8f04654..5aaf86c 100644
--- a/arch/powerpc/sysdev/pmi.c
+++ b/arch/powerpc/sysdev/pmi.c
@@ -214,18 +214,7 @@ static struct platform_driver pmi_of_platform_driver = {
 		.of_match_table = pmi_match,
 	},
 };
-
-static int __init pmi_module_init(void)
-{
-	return platform_driver_register(&pmi_of_platform_driver);
-}
-module_init(pmi_module_init);
-
-static void __exit pmi_module_exit(void)
-{
-	platform_driver_unregister(&pmi_of_platform_driver);
-}
-module_exit(pmi_module_exit);
+module_platform_driver(pmi_of_platform_driver);
 
 int pmi_send_message(pmi_message_t msg)
 {
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index b043675..238a07b 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2010 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2006-2010 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index 2fba6ef..b2b87c3 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -1,7 +1,7 @@
 /*
  * arch/powerpc/sysdev/qe_lib/qe_ic.c
  *
- * Copyright (C) 2006 Freescale Semicondutor, Inc.  All rights reserved.
+ * Copyright (C) 2006 Freescale Semiconductor, Inc.  All rights reserved.
  *
  * Author: Li Yang <leoli@freescale.com>
  * Based on code from Shlomi Gridish <gridish@freescale.com>
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.h b/arch/powerpc/sysdev/qe_lib/qe_ic.h
index c327872..efef7ab 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.h
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.h
@@ -3,7 +3,7 @@
  *
  * QUICC ENGINE Interrupt Controller Header
  *
- * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Author: Li Yang <leoli@freescale.com>
  * Based on code from Shlomi Gridish <gridish@freescale.com>
diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c
index fd1a6c3..a88807b 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_io.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
@@ -3,7 +3,7 @@
  *
  * QE Parallel I/O ports configuration routines
  *
- * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ * Copyright 2006 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Author: Li Yang <LeoLi@freescale.com>
  * Based on code from Shlomi Gridish <gridish@freescale.com>
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c
index 0467750..134b07d 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc.c
@@ -3,7 +3,7 @@
  *
  * QE UCC API Set - UCC specific routines implementations.
  *
- * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
index fba0244..cceb2e3 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
index 524c0ea..1c062f4 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
diff --git a/arch/powerpc/sysdev/qe_lib/usb.c b/arch/powerpc/sysdev/qe_lib/usb.c
index 9162828..27f23bd 100644
--- a/arch/powerpc/sysdev/qe_lib/usb.c
+++ b/arch/powerpc/sysdev/qe_lib/usb.c
@@ -1,7 +1,7 @@
 /*
  * QE USB routines
  *
- * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ * Copyright 2006 Freescale Semiconductor, Inc.
  *               Shlomi Gridish <gridish@freescale.com>
  *               Jerry Huang <Chang-Ming.Huang@freescale.com>
  * Copyright (c) MontaVista Software, Inc. 2008.
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
index c168c54..b49fdbd 100644
--- a/arch/powerpc/xmon/Makefile
+++ b/arch/powerpc/xmon/Makefile
@@ -6,7 +6,7 @@ GCOV_PROFILE := n
 
 ccflags-$(CONFIG_PPC64) := -mno-minimal-toc
 
-obj-y			+= xmon.o start.o nonstdio.o
+obj-y			+= xmon.o nonstdio.o
 
 ifdef CONFIG_XMON_DISASSEMBLY
 obj-y			+= ppc-dis.o ppc-opc.o
diff --git a/arch/powerpc/xmon/nonstdio.c b/arch/powerpc/xmon/nonstdio.c
index bfac84f..bce3dcf 100644
--- a/arch/powerpc/xmon/nonstdio.c
+++ b/arch/powerpc/xmon/nonstdio.c
@@ -7,9 +7,23 @@
  *      2 of the License, or (at your option) any later version.
  */
 #include <linux/string.h>
+#include <asm/udbg.h>
 #include <asm/time.h>
 #include "nonstdio.h"
 
+
+static int xmon_write(const void *ptr, int nb)
+{
+	return udbg_write(ptr, nb);
+}
+
+static int xmon_readchar(void)
+{
+	if (udbg_getc)
+		return udbg_getc();
+	return -1;
+}
+
 int xmon_putchar(int c)
 {
 	char ch = c;
@@ -23,34 +37,7 @@ static char line[256];
 static char *lineptr;
 static int lineleft;
 
-int xmon_expect(const char *str, unsigned long timeout)
-{
-	int c;
-	unsigned long t0;
-
-	/* assume 25MHz default timebase if tb_ticks_per_sec not set yet */
-	timeout *= tb_ticks_per_sec? tb_ticks_per_sec: 25000000;
-	t0 = get_tbl();
-	do {
-		lineptr = line;
-		for (;;) {
-			c = xmon_read_poll();
-			if (c == -1) {
-				if (get_tbl() - t0 > timeout)
-					return 0;
-				continue;
-			}
-			if (c == '\n')
-				break;
-			if (c != '\r' && lineptr < &line[sizeof(line) - 1])
-				*lineptr++ = c;
-		}
-		*lineptr = 0;
-	} while (strstr(line, str) == NULL);
-	return 1;
-}
-
-int xmon_getchar(void)
+static int xmon_getchar(void)
 {
 	int c;
 
@@ -124,13 +111,19 @@ char *xmon_gets(char *str, int nb)
 void xmon_printf(const char *format, ...)
 {
 	va_list args;
-	int n;
 	static char xmon_outbuf[1024];
+	int rc, n;
 
 	va_start(args, format);
 	n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args);
 	va_end(args);
-	xmon_write(xmon_outbuf, n);
+
+	rc = xmon_write(xmon_outbuf, n);
+
+	if (n && rc == 0) {
+		/* No udbg hooks, fallback to printk() - dangerous */
+		printk(xmon_outbuf);
+	}
 }
 
 void xmon_puts(const char *str)
diff --git a/arch/powerpc/xmon/nonstdio.h b/arch/powerpc/xmon/nonstdio.h
index 23dd95f..18a51de 100644
--- a/arch/powerpc/xmon/nonstdio.h
+++ b/arch/powerpc/xmon/nonstdio.h
@@ -4,12 +4,6 @@
 #define putchar	xmon_putchar
 
 extern int xmon_putchar(int c);
-extern int xmon_getchar(void);
 extern void xmon_puts(const char *);
 extern char *xmon_gets(char *, int);
 extern void xmon_printf(const char *, ...);
-extern void xmon_map_scc(void);
-extern int xmon_expect(const char *str, unsigned long timeout);
-extern int xmon_write(const void *ptr, int nb);
-extern int xmon_readchar(void);
-extern int xmon_read_poll(void);
diff --git a/arch/powerpc/xmon/start.c b/arch/powerpc/xmon/start.c
deleted file mode 100644
index 8864de2..0000000
--- a/arch/powerpc/xmon/start.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 1996 Paul Mackerras.
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License
- *      as published by the Free Software Foundation; either version
- *      2 of the License, or (at your option) any later version.
- */
-#include <asm/machdep.h>
-#include <asm/udbg.h>
-#include "nonstdio.h"
-
-void xmon_map_scc(void)
-{
-}
-
-int xmon_write(const void *ptr, int nb)
-{
-	return udbg_write(ptr, nb);
-}
-
-int xmon_readchar(void)
-{
-	if (udbg_getc)
-		return udbg_getc();
-	return -1;
-}
-
-int xmon_read_poll(void)
-{
-	if (udbg_getc_poll)
-		return udbg_getc_poll();
-	return -1;
-}
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 3a56a63..1f8d2f1 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -52,9 +52,6 @@
 #include "nonstdio.h"
 #include "dis-asm.h"
 
-#define scanhex	xmon_scanhex
-#define skipbl	xmon_skipbl
-
 #ifdef CONFIG_SMP
 static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
 static unsigned long xmon_taken = 1;
@@ -169,12 +166,8 @@ extern void xmon_leave(void);
 
 #ifdef CONFIG_PPC64
 #define REG		"%.16lx"
-#define REGS_PER_LINE	4
-#define LAST_VOLATILE	13
 #else
 #define REG		"%.8lx"
-#define REGS_PER_LINE	8
-#define LAST_VOLATILE	12
 #endif
 
 #define GETWORD(v)	(((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
@@ -1288,27 +1281,19 @@ static void get_function_bounds(unsigned long pc, unsigned long *startp,
 	catch_memory_errors = 0;
 }
 
-static int xmon_depth_to_print = 64;
-
 #define LRSAVE_OFFSET		(STACK_FRAME_LR_SAVE * sizeof(unsigned long))
 #define MARKER_OFFSET		(STACK_FRAME_MARKER * sizeof(unsigned long))
 
-#ifdef __powerpc64__
-#define REGS_OFFSET		0x70
-#else
-#define REGS_OFFSET		16
-#endif
-
 static void xmon_show_stack(unsigned long sp, unsigned long lr,
 			    unsigned long pc)
 {
+	int max_to_print = 64;
 	unsigned long ip;
 	unsigned long newsp;
 	unsigned long marker;
-	int count = 0;
 	struct pt_regs regs;
 
-	do {
+	while (max_to_print--) {
 		if (sp < PAGE_OFFSET) {
 			if (sp != 0)
 				printf("SP (%lx) is in userspace\n", sp);
@@ -1362,10 +1347,10 @@ static void xmon_show_stack(unsigned long sp, unsigned long lr,
 		   an exception frame. */
 		if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
 		    && marker == STACK_FRAME_REGS_MARKER) {
-			if (mread(sp + REGS_OFFSET, &regs, sizeof(regs))
+			if (mread(sp + STACK_FRAME_OVERHEAD, &regs, sizeof(regs))
 			    != sizeof(regs)) {
 				printf("Couldn't read registers at %lx\n",
-				       sp + REGS_OFFSET);
+				       sp + STACK_FRAME_OVERHEAD);
 				break;
 			}
 			printf("--- Exception: %lx %s at ", regs.trap,
@@ -1379,7 +1364,7 @@ static void xmon_show_stack(unsigned long sp, unsigned long lr,
 			break;
 
 		sp = newsp;
-	} while (count++ < xmon_depth_to_print);
+	}
 }
 
 static void backtrace(struct pt_regs *excp)
@@ -2943,7 +2928,6 @@ static void xmon_init(int enable)
 		__debugger_dabr_match = NULL;
 		__debugger_fault_handler = NULL;
 	}
-	xmon_map_scc();
 }
 
 #ifdef CONFIG_MAGIC_SYSRQ
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index d385f39..881caea 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -138,8 +138,10 @@ config S390
 	select KTIME_SCALAR if 32BIT
 	select HAVE_ARCH_SECCOMP_FILTER
 	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
 	select HAVE_MOD_ARCH_SPECIFIC
 	select MODULES_USE_ELF_RELA
+	select CLONE_BACKWARDS2
 
 config SCHED_OMIT_FRAME_POINTER
 	def_bool y
@@ -169,6 +171,10 @@ config HAVE_MARCH_Z196_FEATURES
 	def_bool n
 	select HAVE_MARCH_Z10_FEATURES
 
+config HAVE_MARCH_ZEC12_FEATURES
+	def_bool n
+	select HAVE_MARCH_Z196_FEATURES
+
 choice
 	prompt "Processor type"
 	default MARCH_G5
@@ -220,6 +226,13 @@ config MARCH_Z196
 	  (2818 and 2817 series). The kernel will be slightly faster but will
 	  not work on older machines.
 
+config MARCH_ZEC12
+	bool "IBM zEC12"
+	select HAVE_MARCH_ZEC12_FEATURES if 64BIT
+	help
+	  Select this to enable optimizations for IBM zEC12 (2827 series). The
+	  kernel will be slightly faster but will not work on older machines.
+
 endchoice
 
 config 64BIT
@@ -660,8 +673,8 @@ source "arch/s390/kvm/Kconfig"
 
 config S390_GUEST
 	def_bool y
-	prompt "s390 support for virtio devices (EXPERIMENTAL)"
-	depends on 64BIT && EXPERIMENTAL
+	prompt "s390 support for virtio devices"
+	depends on 64BIT
 	select VIRTUALIZATION
 	select VIRTIO
 	select VIRTIO_CONSOLE
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 49e76e8..4b8e08b 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -41,6 +41,7 @@ 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)
 
 #KBUILD_IMAGE is necessary for make rpm
 KBUILD_IMAGE	:=arch/s390/boot/image
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index da3c1a7..b4dbade 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -325,7 +325,8 @@ static int ecb_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
 		u8 *in = walk->src.virt.addr;
 
 		ret = crypt_s390_km(func, param, out, in, n);
-		BUG_ON((ret < 0) || (ret != n));
+		if (ret < 0 || ret != n)
+			return -EIO;
 
 		nbytes &= AES_BLOCK_SIZE - 1;
 		ret = blkcipher_walk_done(desc, walk, nbytes);
@@ -457,7 +458,8 @@ static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
 		u8 *in = walk->src.virt.addr;
 
 		ret = crypt_s390_kmc(func, param, out, in, n);
-		BUG_ON((ret < 0) || (ret != n));
+		if (ret < 0 || ret != n)
+			return -EIO;
 
 		nbytes &= AES_BLOCK_SIZE - 1;
 		ret = blkcipher_walk_done(desc, walk, nbytes);
@@ -625,7 +627,8 @@ static int xts_aes_crypt(struct blkcipher_desc *desc, long func,
 	memcpy(xts_ctx->pcc.tweak, walk->iv, sizeof(xts_ctx->pcc.tweak));
 	param = xts_ctx->pcc.key + offset;
 	ret = crypt_s390_pcc(func, param);
-	BUG_ON(ret < 0);
+	if (ret < 0)
+		return -EIO;
 
 	memcpy(xts_ctx->xts_param, xts_ctx->pcc.xts, 16);
 	param = xts_ctx->key + offset;
@@ -636,7 +639,8 @@ static int xts_aes_crypt(struct blkcipher_desc *desc, long func,
 		in = walk->src.virt.addr;
 
 		ret = crypt_s390_km(func, param, out, in, n);
-		BUG_ON(ret < 0 || ret != n);
+		if (ret < 0 || ret != n)
+			return -EIO;
 
 		nbytes &= AES_BLOCK_SIZE - 1;
 		ret = blkcipher_walk_done(desc, walk, nbytes);
@@ -769,7 +773,8 @@ static int ctr_aes_crypt(struct blkcipher_desc *desc, long func,
 				crypto_inc(ctrblk + i, AES_BLOCK_SIZE);
 			}
 			ret = crypt_s390_kmctr(func, sctx->key, out, in, n, ctrblk);
-			BUG_ON(ret < 0 || ret != n);
+			if (ret < 0 || ret != n)
+				return -EIO;
 			if (n > AES_BLOCK_SIZE)
 				memcpy(ctrblk, ctrblk + n - AES_BLOCK_SIZE,
 				       AES_BLOCK_SIZE);
@@ -788,7 +793,8 @@ static int ctr_aes_crypt(struct blkcipher_desc *desc, long func,
 		in = walk->src.virt.addr;
 		ret = crypt_s390_kmctr(func, sctx->key, buf, in,
 				       AES_BLOCK_SIZE, ctrblk);
-		BUG_ON(ret < 0 || ret != AES_BLOCK_SIZE);
+		if (ret < 0 || ret != AES_BLOCK_SIZE)
+			return -EIO;
 		memcpy(out, buf, nbytes);
 		crypto_inc(ctrblk, AES_BLOCK_SIZE);
 		ret = blkcipher_walk_done(desc, walk, 0);
diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c
index b49fb96..bcca01c 100644
--- a/arch/s390/crypto/des_s390.c
+++ b/arch/s390/crypto/des_s390.c
@@ -94,7 +94,8 @@ static int ecb_desall_crypt(struct blkcipher_desc *desc, long func,
 		u8 *in = walk->src.virt.addr;
 
 		ret = crypt_s390_km(func, key, out, in, n);
-		BUG_ON((ret < 0) || (ret != n));
+		if (ret < 0 || ret != n)
+			return -EIO;
 
 		nbytes &= DES_BLOCK_SIZE - 1;
 		ret = blkcipher_walk_done(desc, walk, nbytes);
@@ -120,7 +121,8 @@ static int cbc_desall_crypt(struct blkcipher_desc *desc, long func,
 		u8 *in = walk->src.virt.addr;
 
 		ret = crypt_s390_kmc(func, iv, out, in, n);
-		BUG_ON((ret < 0) || (ret != n));
+		if (ret < 0 || ret != n)
+			return -EIO;
 
 		nbytes &= DES_BLOCK_SIZE - 1;
 		ret = blkcipher_walk_done(desc, walk, nbytes);
@@ -386,7 +388,8 @@ static int ctr_desall_crypt(struct blkcipher_desc *desc, long func,
 				crypto_inc(ctrblk + i, DES_BLOCK_SIZE);
 			}
 			ret = crypt_s390_kmctr(func, ctx->key, out, in, n, ctrblk);
-			BUG_ON((ret < 0) || (ret != n));
+			if (ret < 0 || ret != n)
+				return -EIO;
 			if (n > DES_BLOCK_SIZE)
 				memcpy(ctrblk, ctrblk + n - DES_BLOCK_SIZE,
 				       DES_BLOCK_SIZE);
@@ -404,7 +407,8 @@ static int ctr_desall_crypt(struct blkcipher_desc *desc, long func,
 		in = walk->src.virt.addr;
 		ret = crypt_s390_kmctr(func, ctx->key, buf, in,
 				       DES_BLOCK_SIZE, ctrblk);
-		BUG_ON(ret < 0 || ret != DES_BLOCK_SIZE);
+		if (ret < 0 || ret != DES_BLOCK_SIZE)
+			return -EIO;
 		memcpy(out, buf, nbytes);
 		crypto_inc(ctrblk, DES_BLOCK_SIZE);
 		ret = blkcipher_walk_done(desc, walk, 0);
diff --git a/arch/s390/crypto/ghash_s390.c b/arch/s390/crypto/ghash_s390.c
index 1ebd3a1..d43485d 100644
--- a/arch/s390/crypto/ghash_s390.c
+++ b/arch/s390/crypto/ghash_s390.c
@@ -72,14 +72,16 @@ static int ghash_update(struct shash_desc *desc,
 		if (!dctx->bytes) {
 			ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf,
 					      GHASH_BLOCK_SIZE);
-			BUG_ON(ret != GHASH_BLOCK_SIZE);
+			if (ret != GHASH_BLOCK_SIZE)
+				return -EIO;
 		}
 	}
 
 	n = srclen & ~(GHASH_BLOCK_SIZE - 1);
 	if (n) {
 		ret = crypt_s390_kimd(KIMD_GHASH, ctx, src, n);
-		BUG_ON(ret != n);
+		if (ret != n)
+			return -EIO;
 		src += n;
 		srclen -= n;
 	}
@@ -92,7 +94,7 @@ static int ghash_update(struct shash_desc *desc,
 	return 0;
 }
 
-static void ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx)
+static int ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx)
 {
 	u8 *buf = dctx->buffer;
 	int ret;
@@ -103,21 +105,24 @@ static void ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx)
 		memset(pos, 0, dctx->bytes);
 
 		ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, GHASH_BLOCK_SIZE);
-		BUG_ON(ret != GHASH_BLOCK_SIZE);
+		if (ret != GHASH_BLOCK_SIZE)
+			return -EIO;
 	}
 
 	dctx->bytes = 0;
+	return 0;
 }
 
 static int ghash_final(struct shash_desc *desc, u8 *dst)
 {
 	struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
 	struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
+	int ret;
 
-	ghash_flush(ctx, dctx);
-	memcpy(dst, ctx->icv, GHASH_BLOCK_SIZE);
-
-	return 0;
+	ret = ghash_flush(ctx, dctx);
+	if (!ret)
+		memcpy(dst, ctx->icv, GHASH_BLOCK_SIZE);
+	return ret;
 }
 
 static struct shash_alg ghash_alg = {
diff --git a/arch/s390/crypto/sha_common.c b/arch/s390/crypto/sha_common.c
index bd37d09..8620b0e 100644
--- a/arch/s390/crypto/sha_common.c
+++ b/arch/s390/crypto/sha_common.c
@@ -36,7 +36,8 @@ int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len)
 	if (index) {
 		memcpy(ctx->buf + index, data, bsize - index);
 		ret = crypt_s390_kimd(ctx->func, ctx->state, ctx->buf, bsize);
-		BUG_ON(ret != bsize);
+		if (ret != bsize)
+			return -EIO;
 		data += bsize - index;
 		len -= bsize - index;
 		index = 0;
@@ -46,7 +47,8 @@ int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len)
 	if (len >= bsize) {
 		ret = crypt_s390_kimd(ctx->func, ctx->state, data,
 				      len & ~(bsize - 1));
-		BUG_ON(ret != (len & ~(bsize - 1)));
+		if (ret != (len & ~(bsize - 1)))
+			return -EIO;
 		data += ret;
 		len -= ret;
 	}
@@ -88,7 +90,8 @@ int s390_sha_final(struct shash_desc *desc, u8 *out)
 	memcpy(ctx->buf + end - 8, &bits, sizeof(bits));
 
 	ret = crypt_s390_kimd(ctx->func, ctx->state, ctx->buf, end);
-	BUG_ON(ret != end);
+	if (ret != end)
+		return -EIO;
 
 	/* copy digest to out */
 	memcpy(out, ctx->state, crypto_shash_digestsize(desc->tfm));
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 0633dc6..f313f9c 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -1,3 +1,4 @@
 
 
 generic-y += clkdev.h
+generic-y += trace_clock.h
diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h
index 1cb4bb3..6d1f357 100644
--- a/arch/s390/include/asm/ccwdev.h
+++ b/arch/s390/include/asm/ccwdev.h
@@ -18,6 +18,9 @@ struct irb;
 struct ccw1;
 struct ccw_dev_id;
 
+/* from asm/schid.h */
+struct subchannel_id;
+
 /* simplified initializers for struct ccw_device:
  * CCW_DEVICE and CCW_DEVICE_DEVTYPE initialize one
  * entry in your MODULE_DEVICE_TABLE and set the match_flag correctly */
@@ -223,8 +226,7 @@ extern int ccw_device_force_console(void);
 
 int ccw_device_siosl(struct ccw_device *);
 
-// FIXME: these have to go
-extern int _ccw_device_get_subchannel_number(struct ccw_device *);
+extern void ccw_device_get_schid(struct ccw_device *, struct subchannel_id *);
 
 extern void *ccw_device_get_chp_desc(struct ccw_device *, int);
 #endif /* _S390_CCWDEV_H_ */
diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h
index 01a905e..23723ce 100644
--- a/arch/s390/include/asm/ccwgroup.h
+++ b/arch/s390/include/asm/ccwgroup.h
@@ -59,6 +59,9 @@ extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver);
 int ccwgroup_create_dev(struct device *root, struct ccwgroup_driver *gdrv,
 			int num_devices, const char *buf);
 
+extern int ccwgroup_set_online(struct ccwgroup_device *gdev);
+extern int ccwgroup_set_offline(struct ccwgroup_device *gdev);
+
 extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev);
 extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev);
 
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h
index 6d53670..a86ad40840 100644
--- a/arch/s390/include/asm/page.h
+++ b/arch/s390/include/asm/page.h
@@ -30,6 +30,8 @@
 #include <asm/setup.h>
 #ifndef __ASSEMBLY__
 
+void storage_key_init_range(unsigned long start, unsigned long end);
+
 static unsigned long pfmf(unsigned long function, unsigned long address)
 {
 	asm volatile(
@@ -158,6 +160,9 @@ static inline int page_reset_referenced(unsigned long addr)
  * race against modification of the referenced bit. This function
  * should therefore only be called if it is not mapped in any
  * address space.
+ *
+ * Note that the bit gets set whenever page content is changed. That means
+ * also when the page is modified by DMA or from inside the kernel.
  */
 #define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY
 static inline int page_test_and_clear_dirty(unsigned long pfn, int mapped)
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 2d3b7cb..23d9a8a 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -35,7 +35,6 @@
 extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
 extern void paging_init(void);
 extern void vmem_map_init(void);
-extern void fault_init(void);
 
 /*
  * The S390 doesn't have any external MMU info: the kernel page
@@ -345,6 +344,8 @@ extern unsigned long MODULES_END;
 #define _REGION3_ENTRY		(_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH)
 #define _REGION3_ENTRY_EMPTY	(_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INV)
 
+#define _REGION3_ENTRY_LARGE	0x400	/* RTTE-format control, large page  */
+
 /* Bits in the segment table entry */
 #define _SEGMENT_ENTRY_ORIGIN	~0x7ffUL/* segment table origin		    */
 #define _SEGMENT_ENTRY_RO	0x200	/* page protection bit		    */
@@ -444,6 +445,7 @@ static inline int pgd_bad(pgd_t pgd)     { return 0; }
 
 static inline int pud_present(pud_t pud) { return 1; }
 static inline int pud_none(pud_t pud)	 { return 0; }
+static inline int pud_large(pud_t pud)	 { return 0; }
 static inline int pud_bad(pud_t pud)	 { return 0; }
 
 #else /* CONFIG_64BIT */
@@ -489,6 +491,13 @@ static inline int pud_none(pud_t pud)
 	return (pud_val(pud) & _REGION_ENTRY_INV) != 0UL;
 }
 
+static inline int pud_large(pud_t pud)
+{
+	if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) != _REGION_ENTRY_TYPE_R3)
+		return 0;
+	return !!(pud_val(pud) & _REGION3_ENTRY_LARGE);
+}
+
 static inline int pud_bad(pud_t pud)
 {
 	/*
diff --git a/arch/s390/include/asm/signal.h b/arch/s390/include/asm/signal.h
index bffdbdd..db7ddfa 100644
--- a/arch/s390/include/asm/signal.h
+++ b/arch/s390/include/asm/signal.h
@@ -39,6 +39,4 @@ struct k_sigaction {
         struct sigaction sa;
 };
 
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
 #endif
diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h
index 9935cbd..05425b1 100644
--- a/arch/s390/include/asm/topology.h
+++ b/arch/s390/include/asm/topology.h
@@ -8,32 +8,34 @@ struct cpu;
 
 #ifdef CONFIG_SCHED_BOOK
 
-extern unsigned char cpu_socket_id[NR_CPUS];
-#define topology_physical_package_id(cpu) (cpu_socket_id[cpu])
+struct cpu_topology_s390 {
+	unsigned short core_id;
+	unsigned short socket_id;
+	unsigned short book_id;
+	cpumask_t core_mask;
+	cpumask_t book_mask;
+};
+
+extern struct cpu_topology_s390 cpu_topology[NR_CPUS];
+
+#define topology_physical_package_id(cpu)	(cpu_topology[cpu].socket_id)
+#define topology_core_id(cpu)			(cpu_topology[cpu].core_id)
+#define topology_core_cpumask(cpu)		(&cpu_topology[cpu].core_mask)
+#define topology_book_id(cpu)			(cpu_topology[cpu].book_id)
+#define topology_book_cpumask(cpu)		(&cpu_topology[cpu].book_mask)
 
-extern unsigned char cpu_core_id[NR_CPUS];
-extern cpumask_t cpu_core_map[NR_CPUS];
+#define mc_capable() 1
 
 static inline const struct cpumask *cpu_coregroup_mask(int cpu)
 {
-	return &cpu_core_map[cpu];
+	return &cpu_topology[cpu].core_mask;
 }
 
-#define topology_core_id(cpu)		(cpu_core_id[cpu])
-#define topology_core_cpumask(cpu)	(&cpu_core_map[cpu])
-#define mc_capable()			(1)
-
-extern unsigned char cpu_book_id[NR_CPUS];
-extern cpumask_t cpu_book_map[NR_CPUS];
-
 static inline const struct cpumask *cpu_book_mask(int cpu)
 {
-	return &cpu_book_map[cpu];
+	return &cpu_topology[cpu].book_mask;
 }
 
-#define topology_book_id(cpu)		(cpu_book_id[cpu])
-#define topology_book_cpumask(cpu)	(&cpu_book_map[cpu])
-
 int topology_cpu_init(struct cpu *);
 int topology_set_cpu_management(int fc);
 void topology_schedule_update(void);
diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h
index bbbae41..086bb8e 100644
--- a/arch/s390/include/asm/unistd.h
+++ b/arch/s390/include/asm/unistd.h
@@ -54,7 +54,9 @@
 #   define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 # endif
 #define __ARCH_WANT_SYS_EXECVE
-#define __ARCH_WANT_KERNEL_EXECVE
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_CLONE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h
index 69718cd..436d07c 100644
--- a/arch/s390/include/uapi/asm/socket.h
+++ b/arch/s390/include/uapi/asm/socket.h
@@ -46,6 +46,7 @@
 /* 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
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 4da52fe..2ac311e 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -23,7 +23,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 \
 	    processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \
 	    debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \
-	    sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o
+	    sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
 
 obj-y	+= $(if $(CONFIG_64BIT),entry64.o,entry.o)
 obj-y	+= $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index f00286b..afdb972 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -83,22 +83,29 @@ enum {
 	U4_12,	/* 4 bit unsigned value starting at 12 */
 	U4_16,	/* 4 bit unsigned value starting at 16 */
 	U4_20,	/* 4 bit unsigned value starting at 20 */
+	U4_24,	/* 4 bit unsigned value starting at 24 */
+	U4_28,	/* 4 bit unsigned value starting at 28 */
 	U4_32,	/* 4 bit unsigned value starting at 32 */
+	U4_36,	/* 4 bit unsigned value starting at 36 */
 	U8_8,	/* 8 bit unsigned value starting at 8 */
 	U8_16,	/* 8 bit unsigned value starting at 16 */
 	U8_24,	/* 8 bit unsigned value starting at 24 */
 	U8_32,	/* 8 bit unsigned value starting at 32 */
 	I8_8,	/* 8 bit signed value starting at 8 */
 	I8_32,	/* 8 bit signed value starting at 32 */
+	J12_12, /* PC relative offset at 12 */
 	I16_16,	/* 16 bit signed value starting at 16 */
 	I16_32,	/* 32 bit signed value starting at 16 */
 	U16_16,	/* 16 bit unsigned value starting at 16 */
 	U16_32,	/* 32 bit unsigned value starting at 16 */
 	J16_16,	/* PC relative jump offset at 16 */
+	J16_32, /* PC relative offset at 16 */
+	I24_24, /* 24 bit signed value starting at 24 */
 	J32_16,	/* PC relative long offset at 16 */
 	I32_16,	/* 32 bit signed value starting at 16 */
 	U32_16,	/* 32 bit unsigned value starting at 16 */
 	M_16,	/* 4 bit optional mask starting at 16 */
+	M_20,	/* 4 bit optional mask starting at 20 */
 	RO_28,	/* optional GPR starting at position 28 */
 };
 
@@ -109,6 +116,8 @@ enum {
 enum {
 	INSTR_INVALID,
 	INSTR_E,
+	INSTR_IE_UU,
+	INSTR_MII_UPI,
 	INSTR_RIE_R0IU, INSTR_RIE_R0UU, INSTR_RIE_RRP, INSTR_RIE_RRPU,
 	INSTR_RIE_RRUUU, INSTR_RIE_RUPI, INSTR_RIE_RUPU, INSTR_RIE_RRI0,
 	INSTR_RIL_RI, INSTR_RIL_RP, INSTR_RIL_RU, INSTR_RIL_UP,
@@ -118,13 +127,15 @@ enum {
 	INSTR_RRE_FF, INSTR_RRE_FR, INSTR_RRE_R0, INSTR_RRE_RA, INSTR_RRE_RF,
 	INSTR_RRE_RR, INSTR_RRE_RR_OPT,
 	INSTR_RRF_0UFF, INSTR_RRF_F0FF, INSTR_RRF_F0FF2, INSTR_RRF_F0FR,
-	INSTR_RRF_FFRU, INSTR_RRF_FUFF, INSTR_RRF_M0RR, INSTR_RRF_R0RR,
-	INSTR_RRF_R0RR2, INSTR_RRF_RURR, INSTR_RRF_U0FF, INSTR_RRF_U0RF,
-	INSTR_RRF_U0RR, INSTR_RRF_UUFF, INSTR_RRR_F0FF, INSTR_RRS_RRRDU,
+	INSTR_RRF_FFRU, INSTR_RRF_FUFF, INSTR_RRF_FUFF2, INSTR_RRF_M0RR,
+	INSTR_RRF_R0RR,	INSTR_RRF_R0RR2, INSTR_RRF_RMRR, INSTR_RRF_RURR,
+	INSTR_RRF_U0FF,	INSTR_RRF_U0RF, INSTR_RRF_U0RR, INSTR_RRF_UUFF,
+	INSTR_RRF_UUFR, INSTR_RRF_UURF,
+	INSTR_RRR_F0FF, INSTR_RRS_RRRDU,
 	INSTR_RR_FF, INSTR_RR_R0, INSTR_RR_RR, INSTR_RR_U0, INSTR_RR_UR,
 	INSTR_RSE_CCRD, INSTR_RSE_RRRD, INSTR_RSE_RURD,
 	INSTR_RSI_RRP,
-	INSTR_RSL_R0RD,
+	INSTR_RSL_LRDFU, INSTR_RSL_R0RD,
 	INSTR_RSY_AARD, INSTR_RSY_CCRD, INSTR_RSY_RRRD, INSTR_RSY_RURD,
 	INSTR_RSY_RDRM,
 	INSTR_RS_AARD, INSTR_RS_CCRD, INSTR_RS_R0RD, INSTR_RS_RRRD,
@@ -136,6 +147,7 @@ enum {
 	INSTR_SIL_RDI, INSTR_SIL_RDU,
 	INSTR_SIY_IRD, INSTR_SIY_URD,
 	INSTR_SI_URD,
+	INSTR_SMI_U0RDP,
 	INSTR_SSE_RDRD,
 	INSTR_SSF_RRDRD, INSTR_SSF_RRDRD2,
 	INSTR_SS_L0RDRD, INSTR_SS_LIRDRD, INSTR_SS_LLRDRD, INSTR_SS_RRRDRD,
@@ -191,31 +203,42 @@ static const struct operand operands[] =
 	[U4_12]  = {  4, 12, 0 },
 	[U4_16]  = {  4, 16, 0 },
 	[U4_20]  = {  4, 20, 0 },
+	[U4_24]  = {  4, 24, 0 },
+	[U4_28]  = {  4, 28, 0 },
 	[U4_32]  = {  4, 32, 0 },
+	[U4_36]  = {  4, 36, 0 },
 	[U8_8]	 = {  8,  8, 0 },
 	[U8_16]  = {  8, 16, 0 },
 	[U8_24]  = {  8, 24, 0 },
 	[U8_32]  = {  8, 32, 0 },
+	[J12_12] = { 12, 12, OPERAND_PCREL },
 	[I16_16] = { 16, 16, OPERAND_SIGNED },
 	[U16_16] = { 16, 16, 0 },
 	[U16_32] = { 16, 32, 0 },
 	[J16_16] = { 16, 16, OPERAND_PCREL },
+	[J16_32] = { 16, 32, OPERAND_PCREL },
 	[I16_32] = { 16, 32, OPERAND_SIGNED },
+	[I24_24] = { 24, 24, OPERAND_SIGNED },
 	[J32_16] = { 32, 16, OPERAND_PCREL },
 	[I32_16] = { 32, 16, OPERAND_SIGNED },
 	[U32_16] = { 32, 16, 0 },
 	[M_16]	 = {  4, 16, 0 },
+	[M_20]	 = {  4, 20, 0 },
 	[RO_28]  = {  4, 28, OPERAND_GPR }
 };
 
 static const unsigned char formats[][7] = {
 	[INSTR_E]	  = { 0xff, 0,0,0,0,0,0 },
+	[INSTR_IE_UU]	  = { 0xff, U4_24,U4_28,0,0,0,0 },
+	[INSTR_MII_UPI]	  = { 0xff, U4_8,J12_12,I24_24 },
+	[INSTR_RIE_R0IU]  = { 0xff, R_8,I16_16,U4_32,0,0,0 },
 	[INSTR_RIE_R0UU]  = { 0xff, R_8,U16_16,U4_32,0,0,0 },
+	[INSTR_RIE_RRI0]  = { 0xff, R_8,R_12,I16_16,0,0,0 },
 	[INSTR_RIE_RRPU]  = { 0xff, R_8,R_12,U4_32,J16_16,0,0 },
 	[INSTR_RIE_RRP]	  = { 0xff, R_8,R_12,J16_16,0,0,0 },
 	[INSTR_RIE_RRUUU] = { 0xff, R_8,R_12,U8_16,U8_24,U8_32,0 },
 	[INSTR_RIE_RUPI]  = { 0xff, R_8,I8_32,U4_12,J16_16,0,0 },
-	[INSTR_RIE_RRI0]  = { 0xff, R_8,R_12,I16_16,0,0,0 },
+	[INSTR_RIE_RUPU]  = { 0xff, R_8,U8_32,U4_12,J16_16,0,0 },
 	[INSTR_RIL_RI]	  = { 0x0f, R_8,I32_16,0,0,0,0 },
 	[INSTR_RIL_RP]	  = { 0x0f, R_8,J32_16,0,0,0,0 },
 	[INSTR_RIL_RU]	  = { 0x0f, R_8,U32_16,0,0,0,0 },
@@ -245,14 +268,18 @@ static const unsigned char formats[][7] = {
 	[INSTR_RRF_F0FR]  = { 0xff, F_24,F_16,R_28,0,0,0 },
 	[INSTR_RRF_FFRU]  = { 0xff, F_24,F_16,R_28,U4_20,0,0 },
 	[INSTR_RRF_FUFF]  = { 0xff, F_24,F_16,F_28,U4_20,0,0 },
+	[INSTR_RRF_FUFF2] = { 0xff, F_24,F_28,F_16,U4_20,0,0 },
 	[INSTR_RRF_M0RR]  = { 0xff, R_24,R_28,M_16,0,0,0 },
 	[INSTR_RRF_R0RR]  = { 0xff, R_24,R_16,R_28,0,0,0 },
 	[INSTR_RRF_R0RR2] = { 0xff, R_24,R_28,R_16,0,0,0 },
+	[INSTR_RRF_RMRR]  = { 0xff, R_24,R_16,R_28,M_20,0,0 },
 	[INSTR_RRF_RURR]  = { 0xff, R_24,R_28,R_16,U4_20,0,0 },
 	[INSTR_RRF_U0FF]  = { 0xff, F_24,U4_16,F_28,0,0,0 },
 	[INSTR_RRF_U0RF]  = { 0xff, R_24,U4_16,F_28,0,0,0 },
 	[INSTR_RRF_U0RR]  = { 0xff, R_24,R_28,U4_16,0,0,0 },
 	[INSTR_RRF_UUFF]  = { 0xff, F_24,U4_16,F_28,U4_20,0,0 },
+	[INSTR_RRF_UUFR]  = { 0xff, F_24,U4_16,R_28,U4_20,0,0 },
+	[INSTR_RRF_UURF]  = { 0xff, R_24,U4_16,F_28,U4_20,0,0 },
 	[INSTR_RRR_F0FF]  = { 0xff, F_24,F_28,F_16,0,0,0 },
 	[INSTR_RRS_RRRDU] = { 0xff, R_8,R_12,U4_32,D_20,B_16,0 },
 	[INSTR_RR_FF]	  = { 0xff, F_8,F_12,0,0,0,0 },
@@ -264,12 +291,13 @@ static const unsigned char formats[][7] = {
 	[INSTR_RSE_RRRD]  = { 0xff, R_8,R_12,D_20,B_16,0,0 },
 	[INSTR_RSE_RURD]  = { 0xff, R_8,U4_12,D_20,B_16,0,0 },
 	[INSTR_RSI_RRP]	  = { 0xff, R_8,R_12,J16_16,0,0,0 },
+	[INSTR_RSL_LRDFU] = { 0xff, F_32,D_20,L4_8,B_16,U4_36,0 },
 	[INSTR_RSL_R0RD]  = { 0xff, D_20,L4_8,B_16,0,0,0 },
 	[INSTR_RSY_AARD]  = { 0xff, A_8,A_12,D20_20,B_16,0,0 },
 	[INSTR_RSY_CCRD]  = { 0xff, C_8,C_12,D20_20,B_16,0,0 },
+	[INSTR_RSY_RDRM]  = { 0xff, R_8,D20_20,B_16,U4_12,0,0 },
 	[INSTR_RSY_RRRD]  = { 0xff, R_8,R_12,D20_20,B_16,0,0 },
 	[INSTR_RSY_RURD]  = { 0xff, R_8,U4_12,D20_20,B_16,0,0 },
-	[INSTR_RSY_RDRM]  = { 0xff, R_8,D20_20,B_16,U4_12,0,0 },
 	[INSTR_RS_AARD]	  = { 0xff, A_8,A_12,D_20,B_16,0,0 },
 	[INSTR_RS_CCRD]	  = { 0xff, C_8,C_12,D_20,B_16,0,0 },
 	[INSTR_RS_R0RD]	  = { 0xff, R_8,D_20,B_16,0,0,0 },
@@ -289,9 +317,10 @@ static const unsigned char formats[][7] = {
 	[INSTR_SIY_IRD]   = { 0xff, D20_20,B_16,I8_8,0,0,0 },
 	[INSTR_SIY_URD]	  = { 0xff, D20_20,B_16,U8_8,0,0,0 },
 	[INSTR_SI_URD]	  = { 0xff, D_20,B_16,U8_8,0,0,0 },
+	[INSTR_SMI_U0RDP] = { 0xff, U4_8,J16_32,D_20,B_16,0,0 },
 	[INSTR_SSE_RDRD]  = { 0xff, D_20,B_16,D_36,B_32,0,0 },
-	[INSTR_SSF_RRDRD] = { 0x00, D_20,B_16,D_36,B_32,R_8,0 },
-	[INSTR_SSF_RRDRD2]= { 0x00, R_8,D_20,B_16,D_36,B_32,0 },
+	[INSTR_SSF_RRDRD] = { 0x0f, D_20,B_16,D_36,B_32,R_8,0 },
+	[INSTR_SSF_RRDRD2]= { 0x0f, R_8,D_20,B_16,D_36,B_32,0 },
 	[INSTR_SS_L0RDRD] = { 0xff, D_20,L8_8,B_16,D_36,B_32,0 },
 	[INSTR_SS_LIRDRD] = { 0xff, D_20,L4_8,B_16,D_36,B_32,U4_12 },
 	[INSTR_SS_LLRDRD] = { 0xff, D_20,L4_8,B_16,D_36,L4_12,B_32 },
@@ -304,19 +333,69 @@ static const unsigned char formats[][7] = {
 
 enum {
 	LONG_INSN_ALGHSIK,
+	LONG_INSN_ALHHHR,
+	LONG_INSN_ALHHLR,
 	LONG_INSN_ALHSIK,
+	LONG_INSN_ALSIHN,
+	LONG_INSN_CDFBRA,
+	LONG_INSN_CDGBRA,
+	LONG_INSN_CDGTRA,
+	LONG_INSN_CDLFBR,
+	LONG_INSN_CDLFTR,
+	LONG_INSN_CDLGBR,
+	LONG_INSN_CDLGTR,
+	LONG_INSN_CEFBRA,
+	LONG_INSN_CEGBRA,
+	LONG_INSN_CELFBR,
+	LONG_INSN_CELGBR,
+	LONG_INSN_CFDBRA,
+	LONG_INSN_CFEBRA,
+	LONG_INSN_CFXBRA,
+	LONG_INSN_CGDBRA,
+	LONG_INSN_CGDTRA,
+	LONG_INSN_CGEBRA,
+	LONG_INSN_CGXBRA,
+	LONG_INSN_CGXTRA,
+	LONG_INSN_CLFDBR,
+	LONG_INSN_CLFDTR,
+	LONG_INSN_CLFEBR,
 	LONG_INSN_CLFHSI,
+	LONG_INSN_CLFXBR,
+	LONG_INSN_CLFXTR,
+	LONG_INSN_CLGDBR,
+	LONG_INSN_CLGDTR,
+	LONG_INSN_CLGEBR,
 	LONG_INSN_CLGFRL,
 	LONG_INSN_CLGHRL,
 	LONG_INSN_CLGHSI,
+	LONG_INSN_CLGXBR,
+	LONG_INSN_CLGXTR,
 	LONG_INSN_CLHHSI,
+	LONG_INSN_CXFBRA,
+	LONG_INSN_CXGBRA,
+	LONG_INSN_CXGTRA,
+	LONG_INSN_CXLFBR,
+	LONG_INSN_CXLFTR,
+	LONG_INSN_CXLGBR,
+	LONG_INSN_CXLGTR,
+	LONG_INSN_FIDBRA,
+	LONG_INSN_FIEBRA,
+	LONG_INSN_FIXBRA,
+	LONG_INSN_LDXBRA,
+	LONG_INSN_LEDBRA,
+	LONG_INSN_LEXBRA,
+	LONG_INSN_LLGFAT,
 	LONG_INSN_LLGFRL,
 	LONG_INSN_LLGHRL,
+	LONG_INSN_LLGTAT,
 	LONG_INSN_POPCNT,
+	LONG_INSN_RIEMIT,
+	LONG_INSN_RINEXT,
+	LONG_INSN_RISBGN,
 	LONG_INSN_RISBHG,
 	LONG_INSN_RISBLG,
-	LONG_INSN_RINEXT,
-	LONG_INSN_RIEMIT,
+	LONG_INSN_SLHHHR,
+	LONG_INSN_SLHHLR,
 	LONG_INSN_TABORT,
 	LONG_INSN_TBEGIN,
 	LONG_INSN_TBEGINC,
@@ -324,19 +403,69 @@ enum {
 
 static char *long_insn_name[] = {
 	[LONG_INSN_ALGHSIK] = "alghsik",
+	[LONG_INSN_ALHHHR] = "alhhhr",
+	[LONG_INSN_ALHHLR] = "alhhlr",
 	[LONG_INSN_ALHSIK] = "alhsik",
+	[LONG_INSN_ALSIHN] = "alsihn",
+	[LONG_INSN_CDFBRA] = "cdfbra",
+	[LONG_INSN_CDGBRA] = "cdgbra",
+	[LONG_INSN_CDGTRA] = "cdgtra",
+	[LONG_INSN_CDLFBR] = "cdlfbr",
+	[LONG_INSN_CDLFTR] = "cdlftr",
+	[LONG_INSN_CDLGBR] = "cdlgbr",
+	[LONG_INSN_CDLGTR] = "cdlgtr",
+	[LONG_INSN_CEFBRA] = "cefbra",
+	[LONG_INSN_CEGBRA] = "cegbra",
+	[LONG_INSN_CELFBR] = "celfbr",
+	[LONG_INSN_CELGBR] = "celgbr",
+	[LONG_INSN_CFDBRA] = "cfdbra",
+	[LONG_INSN_CFEBRA] = "cfebra",
+	[LONG_INSN_CFXBRA] = "cfxbra",
+	[LONG_INSN_CGDBRA] = "cgdbra",
+	[LONG_INSN_CGDTRA] = "cgdtra",
+	[LONG_INSN_CGEBRA] = "cgebra",
+	[LONG_INSN_CGXBRA] = "cgxbra",
+	[LONG_INSN_CGXTRA] = "cgxtra",
+	[LONG_INSN_CLFDBR] = "clfdbr",
+	[LONG_INSN_CLFDTR] = "clfdtr",
+	[LONG_INSN_CLFEBR] = "clfebr",
 	[LONG_INSN_CLFHSI] = "clfhsi",
+	[LONG_INSN_CLFXBR] = "clfxbr",
+	[LONG_INSN_CLFXTR] = "clfxtr",
+	[LONG_INSN_CLGDBR] = "clgdbr",
+	[LONG_INSN_CLGDTR] = "clgdtr",
+	[LONG_INSN_CLGEBR] = "clgebr",
 	[LONG_INSN_CLGFRL] = "clgfrl",
 	[LONG_INSN_CLGHRL] = "clghrl",
 	[LONG_INSN_CLGHSI] = "clghsi",
+	[LONG_INSN_CLGXBR] = "clgxbr",
+	[LONG_INSN_CLGXTR] = "clgxtr",
 	[LONG_INSN_CLHHSI] = "clhhsi",
+	[LONG_INSN_CXFBRA] = "cxfbra",
+	[LONG_INSN_CXGBRA] = "cxgbra",
+	[LONG_INSN_CXGTRA] = "cxgtra",
+	[LONG_INSN_CXLFBR] = "cxlfbr",
+	[LONG_INSN_CXLFTR] = "cxlftr",
+	[LONG_INSN_CXLGBR] = "cxlgbr",
+	[LONG_INSN_CXLGTR] = "cxlgtr",
+	[LONG_INSN_FIDBRA] = "fidbra",
+	[LONG_INSN_FIEBRA] = "fiebra",
+	[LONG_INSN_FIXBRA] = "fixbra",
+	[LONG_INSN_LDXBRA] = "ldxbra",
+	[LONG_INSN_LEDBRA] = "ledbra",
+	[LONG_INSN_LEXBRA] = "lexbra",
+	[LONG_INSN_LLGFAT] = "llgfat",
 	[LONG_INSN_LLGFRL] = "llgfrl",
 	[LONG_INSN_LLGHRL] = "llghrl",
+	[LONG_INSN_LLGTAT] = "llgtat",
 	[LONG_INSN_POPCNT] = "popcnt",
+	[LONG_INSN_RIEMIT] = "riemit",
+	[LONG_INSN_RINEXT] = "rinext",
+	[LONG_INSN_RISBGN] = "risbgn",
 	[LONG_INSN_RISBHG] = "risbhg",
 	[LONG_INSN_RISBLG] = "risblg",
-	[LONG_INSN_RINEXT] = "rinext",
-	[LONG_INSN_RIEMIT] = "riemit",
+	[LONG_INSN_SLHHHR] = "slhhhr",
+	[LONG_INSN_SLHHLR] = "slhhlr",
 	[LONG_INSN_TABORT] = "tabort",
 	[LONG_INSN_TBEGIN] = "tbegin",
 	[LONG_INSN_TBEGINC] = "tbeginc",
@@ -344,6 +473,9 @@ static char *long_insn_name[] = {
 
 static struct insn opcode[] = {
 #ifdef CONFIG_64BIT
+	{ "bprp", 0xc5, INSTR_MII_UPI },
+	{ "bpp", 0xc7, INSTR_SMI_U0RDP },
+	{ "trtr", 0xd0, INSTR_SS_L0RDRD },
 	{ "lmd", 0xef, INSTR_SS_RRRDRD3 },
 #endif
 	{ "spm", 0x04, INSTR_RR_R0 },
@@ -378,7 +510,6 @@ static struct insn opcode[] = {
 	{ "lcdr", 0x23, INSTR_RR_FF },
 	{ "hdr", 0x24, INSTR_RR_FF },
 	{ "ldxr", 0x25, INSTR_RR_FF },
-	{ "lrdr", 0x25, INSTR_RR_FF },
 	{ "mxr", 0x26, INSTR_RR_FF },
 	{ "mxdr", 0x27, INSTR_RR_FF },
 	{ "ldr", 0x28, INSTR_RR_FF },
@@ -395,7 +526,6 @@ static struct insn opcode[] = {
 	{ "lcer", 0x33, INSTR_RR_FF },
 	{ "her", 0x34, INSTR_RR_FF },
 	{ "ledr", 0x35, INSTR_RR_FF },
-	{ "lrer", 0x35, INSTR_RR_FF },
 	{ "axr", 0x36, INSTR_RR_FF },
 	{ "sxr", 0x37, INSTR_RR_FF },
 	{ "ler", 0x38, INSTR_RR_FF },
@@ -403,7 +533,6 @@ static struct insn opcode[] = {
 	{ "aer", 0x3a, INSTR_RR_FF },
 	{ "ser", 0x3b, INSTR_RR_FF },
 	{ "mder", 0x3c, INSTR_RR_FF },
-	{ "mer", 0x3c, INSTR_RR_FF },
 	{ "der", 0x3d, INSTR_RR_FF },
 	{ "aur", 0x3e, INSTR_RR_FF },
 	{ "sur", 0x3f, INSTR_RR_FF },
@@ -454,7 +583,6 @@ static struct insn opcode[] = {
 	{ "ae", 0x7a, INSTR_RX_FRRD },
 	{ "se", 0x7b, INSTR_RX_FRRD },
 	{ "mde", 0x7c, INSTR_RX_FRRD },
-	{ "me", 0x7c, INSTR_RX_FRRD },
 	{ "de", 0x7d, INSTR_RX_FRRD },
 	{ "au", 0x7e, INSTR_RX_FRRD },
 	{ "su", 0x7f, INSTR_RX_FRRD },
@@ -534,9 +662,9 @@ static struct insn opcode[] = {
 
 static struct insn opcode_01[] = {
 #ifdef CONFIG_64BIT
-	{ "sam64", 0x0e, INSTR_E },
-	{ "pfpo", 0x0a, INSTR_E },
 	{ "ptff", 0x04, INSTR_E },
+	{ "pfpo", 0x0a, INSTR_E },
+	{ "sam64", 0x0e, INSTR_E },
 #endif
 	{ "pr", 0x01, INSTR_E },
 	{ "upt", 0x02, INSTR_E },
@@ -605,19 +733,28 @@ static struct insn opcode_aa[] = {
 
 static struct insn opcode_b2[] = {
 #ifdef CONFIG_64BIT
-	{ "sske", 0x2b, INSTR_RRF_M0RR },
 	{ "stckf", 0x7c, INSTR_S_RD },
-	{ "cu21", 0xa6, INSTR_RRF_M0RR },
-	{ "cuutf", 0xa6, INSTR_RRF_M0RR },
-	{ "cu12", 0xa7, INSTR_RRF_M0RR },
-	{ "cutfu", 0xa7, INSTR_RRF_M0RR },
+	{ "lpp", 0x80, INSTR_S_RD },
+	{ "lcctl", 0x84, INSTR_S_RD },
+	{ "lpctl", 0x85, INSTR_S_RD },
+	{ "qsi", 0x86, INSTR_S_RD },
+	{ "lsctl", 0x87, INSTR_S_RD },
+	{ "qctri", 0x8e, INSTR_S_RD },
 	{ "stfle", 0xb0, INSTR_S_RD },
 	{ "lpswe", 0xb2, INSTR_S_RD },
+	{ "srnmb", 0xb8, INSTR_S_RD },
 	{ "srnmt", 0xb9, INSTR_S_RD },
 	{ "lfas", 0xbd, INSTR_S_RD },
-	{ "etndg", 0xec, INSTR_RRE_R0 },
+	{ "scctr", 0xe0, INSTR_RRE_RR },
+	{ "spctr", 0xe1, INSTR_RRE_RR },
+	{ "ecctr", 0xe4, INSTR_RRE_RR },
+	{ "epctr", 0xe5, INSTR_RRE_RR },
+	{ "ppa", 0xe8, INSTR_RRF_U0RR },
+	{ "etnd", 0xec, INSTR_RRE_R0 },
+	{ "ecpga", 0xed, INSTR_RRE_RR },
+	{ "tend", 0xf8, INSTR_S_00 },
+	{ "niai", 0xfa, INSTR_IE_UU },
 	{ { 0, LONG_INSN_TABORT }, 0xfc, INSTR_S_RD },
-	{ "tend", 0xf8, INSTR_S_RD },
 #endif
 	{ "stidp", 0x02, INSTR_S_RD },
 	{ "sck", 0x04, INSTR_S_RD },
@@ -635,8 +772,8 @@ static struct insn opcode_b2[] = {
 	{ "sie", 0x14, INSTR_S_RD },
 	{ "pc", 0x18, INSTR_S_RD },
 	{ "sac", 0x19, INSTR_S_RD },
-	{ "servc", 0x20, INSTR_RRE_RR },
 	{ "cfc", 0x1a, INSTR_S_RD },
+	{ "servc", 0x20, INSTR_RRE_RR },
 	{ "ipte", 0x21, INSTR_RRE_RR },
 	{ "ipm", 0x22, INSTR_RRE_R0 },
 	{ "ivsk", 0x23, INSTR_RRE_RR },
@@ -647,9 +784,9 @@ static struct insn opcode_b2[] = {
 	{ "pt", 0x28, INSTR_RRE_RR },
 	{ "iske", 0x29, INSTR_RRE_RR },
 	{ "rrbe", 0x2a, INSTR_RRE_RR },
-	{ "sske", 0x2b, INSTR_RRE_RR },
+	{ "sske", 0x2b, INSTR_RRF_M0RR },
 	{ "tb", 0x2c, INSTR_RRE_0R },
-	{ "dxr", 0x2d, INSTR_RRE_F0 },
+	{ "dxr", 0x2d, INSTR_RRE_FF },
 	{ "pgin", 0x2e, INSTR_RRE_RR },
 	{ "pgout", 0x2f, INSTR_RRE_RR },
 	{ "csch", 0x30, INSTR_S_00 },
@@ -667,8 +804,8 @@ static struct insn opcode_b2[] = {
 	{ "schm", 0x3c, INSTR_S_00 },
 	{ "bakr", 0x40, INSTR_RRE_RR },
 	{ "cksm", 0x41, INSTR_RRE_RR },
-	{ "sqdr", 0x44, INSTR_RRE_F0 },
-	{ "sqer", 0x45, INSTR_RRE_F0 },
+	{ "sqdr", 0x44, INSTR_RRE_FF },
+	{ "sqer", 0x45, INSTR_RRE_FF },
 	{ "stura", 0x46, INSTR_RRE_RR },
 	{ "msta", 0x47, INSTR_RRE_R0 },
 	{ "palb", 0x48, INSTR_RRE_00 },
@@ -694,14 +831,14 @@ static struct insn opcode_b2[] = {
 	{ "rp", 0x77, INSTR_S_RD },
 	{ "stcke", 0x78, INSTR_S_RD },
 	{ "sacf", 0x79, INSTR_S_RD },
-	{ "spp", 0x80, INSTR_S_RD },
 	{ "stsi", 0x7d, INSTR_S_RD },
+	{ "spp", 0x80, INSTR_S_RD },
 	{ "srnm", 0x99, INSTR_S_RD },
 	{ "stfpc", 0x9c, INSTR_S_RD },
 	{ "lfpc", 0x9d, INSTR_S_RD },
 	{ "tre", 0xa5, INSTR_RRE_RR },
-	{ "cuutf", 0xa6, INSTR_RRE_RR },
-	{ "cutfu", 0xa7, INSTR_RRE_RR },
+	{ "cuutf", 0xa6, INSTR_RRF_M0RR },
+	{ "cutfu", 0xa7, INSTR_RRF_M0RR },
 	{ "stfl", 0xb1, INSTR_S_RD },
 	{ "trap4", 0xff, INSTR_S_RD },
 	{ "", 0, INSTR_INVALID }
@@ -715,72 +852,87 @@ static struct insn opcode_b3[] = {
 	{ "myr", 0x3b, INSTR_RRF_F0FF },
 	{ "mayhr", 0x3c, INSTR_RRF_F0FF },
 	{ "myhr", 0x3d, INSTR_RRF_F0FF },
-	{ "cegbr", 0xa4, INSTR_RRE_RR },
-	{ "cdgbr", 0xa5, INSTR_RRE_RR },
-	{ "cxgbr", 0xa6, INSTR_RRE_RR },
-	{ "cgebr", 0xa8, INSTR_RRF_U0RF },
-	{ "cgdbr", 0xa9, INSTR_RRF_U0RF },
-	{ "cgxbr", 0xaa, INSTR_RRF_U0RF },
-	{ "cfer", 0xb8, INSTR_RRF_U0RF },
-	{ "cfdr", 0xb9, INSTR_RRF_U0RF },
-	{ "cfxr", 0xba, INSTR_RRF_U0RF },
-	{ "cegr", 0xc4, INSTR_RRE_RR },
-	{ "cdgr", 0xc5, INSTR_RRE_RR },
-	{ "cxgr", 0xc6, INSTR_RRE_RR },
-	{ "cger", 0xc8, INSTR_RRF_U0RF },
-	{ "cgdr", 0xc9, INSTR_RRF_U0RF },
-	{ "cgxr", 0xca, INSTR_RRF_U0RF },
 	{ "lpdfr", 0x70, INSTR_RRE_FF },
 	{ "lndfr", 0x71, INSTR_RRE_FF },
 	{ "cpsdr", 0x72, INSTR_RRF_F0FF2 },
 	{ "lcdfr", 0x73, INSTR_RRE_FF },
+	{ "sfasr", 0x85, INSTR_RRE_R0 },
+	{ { 0, LONG_INSN_CELFBR }, 0x90, INSTR_RRF_UUFR },
+	{ { 0, LONG_INSN_CDLFBR }, 0x91, INSTR_RRF_UUFR },
+	{ { 0, LONG_INSN_CXLFBR }, 0x92, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CEFBRA }, 0x94, INSTR_RRF_UUFR },
+	{ { 0, LONG_INSN_CDFBRA }, 0x95, INSTR_RRF_UUFR },
+	{ { 0, LONG_INSN_CXFBRA }, 0x96, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CFEBRA }, 0x98, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CFDBRA }, 0x99, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CFXBRA }, 0x9a, INSTR_RRF_UUFR },
+	{ { 0, LONG_INSN_CLFEBR }, 0x9c, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CLFDBR }, 0x9d, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CLFXBR }, 0x9e, INSTR_RRF_UUFR },
+	{ { 0, LONG_INSN_CELGBR }, 0xa0, INSTR_RRF_UUFR },
+	{ { 0, LONG_INSN_CDLGBR }, 0xa1, INSTR_RRF_UUFR },
+	{ { 0, LONG_INSN_CXLGBR }, 0xa2, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CEGBRA }, 0xa4, INSTR_RRF_UUFR },
+	{ { 0, LONG_INSN_CDGBRA }, 0xa5, INSTR_RRF_UUFR },
+	{ { 0, LONG_INSN_CXGBRA }, 0xa6, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CGEBRA }, 0xa8, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CGDBRA }, 0xa9, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CGXBRA }, 0xaa, INSTR_RRF_UUFR },
+	{ { 0, LONG_INSN_CLGEBR }, 0xac, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CLGDBR }, 0xad, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CLGXBR }, 0xae, INSTR_RRF_UUFR },
 	{ "ldgr", 0xc1, INSTR_RRE_FR },
+	{ "cegr", 0xc4, INSTR_RRE_FR },
+	{ "cdgr", 0xc5, INSTR_RRE_FR },
+	{ "cxgr", 0xc6, INSTR_RRE_FR },
+	{ "cger", 0xc8, INSTR_RRF_U0RF },
+	{ "cgdr", 0xc9, INSTR_RRF_U0RF },
+	{ "cgxr", 0xca, INSTR_RRF_U0RF },
 	{ "lgdr", 0xcd, INSTR_RRE_RF },
-	{ "adtr", 0xd2, INSTR_RRR_F0FF },
-	{ "axtr", 0xda, INSTR_RRR_F0FF },
-	{ "cdtr", 0xe4, INSTR_RRE_FF },
-	{ "cxtr", 0xec, INSTR_RRE_FF },
+	{ "mdtra", 0xd0, INSTR_RRF_FUFF2 },
+	{ "ddtra", 0xd1, INSTR_RRF_FUFF2 },
+	{ "adtra", 0xd2, INSTR_RRF_FUFF2 },
+	{ "sdtra", 0xd3, INSTR_RRF_FUFF2 },
+	{ "ldetr", 0xd4, INSTR_RRF_0UFF },
+	{ "ledtr", 0xd5, INSTR_RRF_UUFF },
+	{ "ltdtr", 0xd6, INSTR_RRE_FF },
+	{ "fidtr", 0xd7, INSTR_RRF_UUFF },
+	{ "mxtra", 0xd8, INSTR_RRF_FUFF2 },
+	{ "dxtra", 0xd9, INSTR_RRF_FUFF2 },
+	{ "axtra", 0xda, INSTR_RRF_FUFF2 },
+	{ "sxtra", 0xdb, INSTR_RRF_FUFF2 },
+	{ "lxdtr", 0xdc, INSTR_RRF_0UFF },
+	{ "ldxtr", 0xdd, INSTR_RRF_UUFF },
+	{ "ltxtr", 0xde, INSTR_RRE_FF },
+	{ "fixtr", 0xdf, INSTR_RRF_UUFF },
 	{ "kdtr", 0xe0, INSTR_RRE_FF },
-	{ "kxtr", 0xe8, INSTR_RRE_FF },
-	{ "cedtr", 0xf4, INSTR_RRE_FF },
-	{ "cextr", 0xfc, INSTR_RRE_FF },
-	{ "cdgtr", 0xf1, INSTR_RRE_FR },
-	{ "cxgtr", 0xf9, INSTR_RRE_FR },
-	{ "cdstr", 0xf3, INSTR_RRE_FR },
-	{ "cxstr", 0xfb, INSTR_RRE_FR },
-	{ "cdutr", 0xf2, INSTR_RRE_FR },
-	{ "cxutr", 0xfa, INSTR_RRE_FR },
-	{ "cgdtr", 0xe1, INSTR_RRF_U0RF },
-	{ "cgxtr", 0xe9, INSTR_RRF_U0RF },
-	{ "csdtr", 0xe3, INSTR_RRE_RF },
-	{ "csxtr", 0xeb, INSTR_RRE_RF },
+	{ { 0, LONG_INSN_CGDTRA }, 0xe1, INSTR_RRF_UURF },
 	{ "cudtr", 0xe2, INSTR_RRE_RF },
-	{ "cuxtr", 0xea, INSTR_RRE_RF },
-	{ "ddtr", 0xd1, INSTR_RRR_F0FF },
-	{ "dxtr", 0xd9, INSTR_RRR_F0FF },
+	{ "csdtr", 0xe3, INSTR_RRE_RF },
+	{ "cdtr", 0xe4, INSTR_RRE_FF },
 	{ "eedtr", 0xe5, INSTR_RRE_RF },
-	{ "eextr", 0xed, INSTR_RRE_RF },
 	{ "esdtr", 0xe7, INSTR_RRE_RF },
+	{ "kxtr", 0xe8, INSTR_RRE_FF },
+	{ { 0, LONG_INSN_CGXTRA }, 0xe9, INSTR_RRF_UUFR },
+	{ "cuxtr", 0xea, INSTR_RRE_RF },
+	{ "csxtr", 0xeb, INSTR_RRE_RF },
+	{ "cxtr", 0xec, INSTR_RRE_FF },
+	{ "eextr", 0xed, INSTR_RRE_RF },
 	{ "esxtr", 0xef, INSTR_RRE_RF },
-	{ "iedtr", 0xf6, INSTR_RRF_F0FR },
-	{ "iextr", 0xfe, INSTR_RRF_F0FR },
-	{ "ltdtr", 0xd6, INSTR_RRE_FF },
-	{ "ltxtr", 0xde, INSTR_RRE_FF },
-	{ "fidtr", 0xd7, INSTR_RRF_UUFF },
-	{ "fixtr", 0xdf, INSTR_RRF_UUFF },
-	{ "ldetr", 0xd4, INSTR_RRF_0UFF },
-	{ "lxdtr", 0xdc, INSTR_RRF_0UFF },
-	{ "ledtr", 0xd5, INSTR_RRF_UUFF },
-	{ "ldxtr", 0xdd, INSTR_RRF_UUFF },
-	{ "mdtr", 0xd0, INSTR_RRR_F0FF },
-	{ "mxtr", 0xd8, INSTR_RRR_F0FF },
+	{ { 0, LONG_INSN_CDGTRA }, 0xf1, INSTR_RRF_UUFR },
+	{ "cdutr", 0xf2, INSTR_RRE_FR },
+	{ "cdstr", 0xf3, INSTR_RRE_FR },
+	{ "cedtr", 0xf4, INSTR_RRE_FF },
 	{ "qadtr", 0xf5, INSTR_RRF_FUFF },
-	{ "qaxtr", 0xfd, INSTR_RRF_FUFF },
+	{ "iedtr", 0xf6, INSTR_RRF_F0FR },
 	{ "rrdtr", 0xf7, INSTR_RRF_FFRU },
+	{ { 0, LONG_INSN_CXGTRA }, 0xf9, INSTR_RRF_UURF },
+	{ "cxutr", 0xfa, INSTR_RRE_FR },
+	{ "cxstr", 0xfb, INSTR_RRE_FR },
+	{ "cextr", 0xfc, INSTR_RRE_FF },
+	{ "qaxtr", 0xfd, INSTR_RRF_FUFF },
+	{ "iextr", 0xfe, INSTR_RRF_F0FR },
 	{ "rrxtr", 0xff, INSTR_RRF_FFRU },
-	{ "sfasr", 0x85, INSTR_RRE_R0 },
-	{ "sdtr", 0xd3, INSTR_RRR_F0FF },
-	{ "sxtr", 0xdb, INSTR_RRR_F0FF },
 #endif
 	{ "lpebr", 0x00, INSTR_RRE_FF },
 	{ "lnebr", 0x01, INSTR_RRE_FF },
@@ -827,10 +979,10 @@ static struct insn opcode_b3[] = {
 	{ "lnxbr", 0x41, INSTR_RRE_FF },
 	{ "ltxbr", 0x42, INSTR_RRE_FF },
 	{ "lcxbr", 0x43, INSTR_RRE_FF },
-	{ "ledbr", 0x44, INSTR_RRE_FF },
-	{ "ldxbr", 0x45, INSTR_RRE_FF },
-	{ "lexbr", 0x46, INSTR_RRE_FF },
-	{ "fixbr", 0x47, INSTR_RRF_U0FF },
+	{ { 0, LONG_INSN_LEDBRA }, 0x44, INSTR_RRF_UUFF },
+	{ { 0, LONG_INSN_LDXBRA }, 0x45, INSTR_RRF_UUFF },
+	{ { 0, LONG_INSN_LEXBRA }, 0x46, INSTR_RRF_UUFF },
+	{ { 0, LONG_INSN_FIXBRA }, 0x47, INSTR_RRF_UUFF },
 	{ "kxbr", 0x48, INSTR_RRE_FF },
 	{ "cxbr", 0x49, INSTR_RRE_FF },
 	{ "axbr", 0x4a, INSTR_RRE_FF },
@@ -840,24 +992,24 @@ static struct insn opcode_b3[] = {
 	{ "tbedr", 0x50, INSTR_RRF_U0FF },
 	{ "tbdr", 0x51, INSTR_RRF_U0FF },
 	{ "diebr", 0x53, INSTR_RRF_FUFF },
-	{ "fiebr", 0x57, INSTR_RRF_U0FF },
-	{ "thder", 0x58, INSTR_RRE_RR },
-	{ "thdr", 0x59, INSTR_RRE_RR },
+	{ { 0, LONG_INSN_FIEBRA }, 0x57, INSTR_RRF_UUFF },
+	{ "thder", 0x58, INSTR_RRE_FF },
+	{ "thdr", 0x59, INSTR_RRE_FF },
 	{ "didbr", 0x5b, INSTR_RRF_FUFF },
-	{ "fidbr", 0x5f, INSTR_RRF_U0FF },
+	{ { 0, LONG_INSN_FIDBRA }, 0x5f, INSTR_RRF_UUFF },
 	{ "lpxr", 0x60, INSTR_RRE_FF },
 	{ "lnxr", 0x61, INSTR_RRE_FF },
 	{ "ltxr", 0x62, INSTR_RRE_FF },
 	{ "lcxr", 0x63, INSTR_RRE_FF },
-	{ "lxr", 0x65, INSTR_RRE_RR },
+	{ "lxr", 0x65, INSTR_RRE_FF },
 	{ "lexr", 0x66, INSTR_RRE_FF },
-	{ "fixr", 0x67, INSTR_RRF_U0FF },
+	{ "fixr", 0x67, INSTR_RRE_FF },
 	{ "cxr", 0x69, INSTR_RRE_FF },
-	{ "lzer", 0x74, INSTR_RRE_R0 },
-	{ "lzdr", 0x75, INSTR_RRE_R0 },
-	{ "lzxr", 0x76, INSTR_RRE_R0 },
-	{ "fier", 0x77, INSTR_RRF_U0FF },
-	{ "fidr", 0x7f, INSTR_RRF_U0FF },
+	{ "lzer", 0x74, INSTR_RRE_F0 },
+	{ "lzdr", 0x75, INSTR_RRE_F0 },
+	{ "lzxr", 0x76, INSTR_RRE_F0 },
+	{ "fier", 0x77, INSTR_RRE_FF },
+	{ "fidr", 0x7f, INSTR_RRE_FF },
 	{ "sfpc", 0x84, INSTR_RRE_RR_OPT },
 	{ "efpc", 0x8c, INSTR_RRE_RR_OPT },
 	{ "cefbr", 0x94, INSTR_RRE_RF },
@@ -866,9 +1018,12 @@ static struct insn opcode_b3[] = {
 	{ "cfebr", 0x98, INSTR_RRF_U0RF },
 	{ "cfdbr", 0x99, INSTR_RRF_U0RF },
 	{ "cfxbr", 0x9a, INSTR_RRF_U0RF },
-	{ "cefr", 0xb4, INSTR_RRE_RF },
-	{ "cdfr", 0xb5, INSTR_RRE_RF },
-	{ "cxfr", 0xb6, INSTR_RRE_RF },
+	{ "cefr", 0xb4, INSTR_RRE_FR },
+	{ "cdfr", 0xb5, INSTR_RRE_FR },
+	{ "cxfr", 0xb6, INSTR_RRE_FR },
+	{ "cfer", 0xb8, INSTR_RRF_U0RF },
+	{ "cfdr", 0xb9, INSTR_RRF_U0RF },
+	{ "cfxr", 0xba, INSTR_RRF_U0RF },
 	{ "", 0, INSTR_INVALID }
 };
 
@@ -910,7 +1065,23 @@ static struct insn opcode_b9[] = {
 	{ "lhr", 0x27, INSTR_RRE_RR },
 	{ "cgfr", 0x30, INSTR_RRE_RR },
 	{ "clgfr", 0x31, INSTR_RRE_RR },
+	{ "cfdtr", 0x41, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CLGDTR }, 0x42, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CLFDTR }, 0x43, INSTR_RRF_UURF },
 	{ "bctgr", 0x46, INSTR_RRE_RR },
+	{ "cfxtr", 0x49, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CLGXTR }, 0x4a, INSTR_RRF_UUFR },
+	{ { 0, LONG_INSN_CLFXTR }, 0x4b, INSTR_RRF_UUFR },
+	{ "cdftr", 0x51, INSTR_RRF_UUFR },
+	{ { 0, LONG_INSN_CDLGTR }, 0x52, INSTR_RRF_UUFR },
+	{ { 0, LONG_INSN_CDLFTR }, 0x53, INSTR_RRF_UUFR },
+	{ "cxftr", 0x59, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CXLGTR }, 0x5a, INSTR_RRF_UURF },
+	{ { 0, LONG_INSN_CXLFTR }, 0x5b, INSTR_RRF_UUFR },
+	{ "cgrt", 0x60, INSTR_RRF_U0RR },
+	{ "clgrt", 0x61, INSTR_RRF_U0RR },
+	{ "crt", 0x72, INSTR_RRF_U0RR },
+	{ "clrt", 0x73, INSTR_RRF_U0RR },
 	{ "ngr", 0x80, INSTR_RRE_RR },
 	{ "ogr", 0x81, INSTR_RRE_RR },
 	{ "xgr", 0x82, INSTR_RRE_RR },
@@ -923,32 +1094,31 @@ static struct insn opcode_b9[] = {
 	{ "slbgr", 0x89, INSTR_RRE_RR },
 	{ "cspg", 0x8a, INSTR_RRE_RR },
 	{ "idte", 0x8e, INSTR_RRF_R0RR },
+	{ "crdte", 0x8f, INSTR_RRF_RMRR },
 	{ "llcr", 0x94, INSTR_RRE_RR },
 	{ "llhr", 0x95, INSTR_RRE_RR },
 	{ "esea", 0x9d, INSTR_RRE_R0 },
+	{ "ptf", 0xa2, INSTR_RRE_R0 },
 	{ "lptea", 0xaa, INSTR_RRF_RURR },
+	{ "rrbm", 0xae, INSTR_RRE_RR },
+	{ "pfmf", 0xaf, INSTR_RRE_RR },
 	{ "cu14", 0xb0, INSTR_RRF_M0RR },
 	{ "cu24", 0xb1, INSTR_RRF_M0RR },
-	{ "cu41", 0xb2, INSTR_RRF_M0RR },
-	{ "cu42", 0xb3, INSTR_RRF_M0RR },
-	{ "crt", 0x72, INSTR_RRF_U0RR },
-	{ "cgrt", 0x60, INSTR_RRF_U0RR },
-	{ "clrt", 0x73, INSTR_RRF_U0RR },
-	{ "clgrt", 0x61, INSTR_RRF_U0RR },
-	{ "ptf", 0xa2, INSTR_RRE_R0 },
-	{ "pfmf", 0xaf, INSTR_RRE_RR },
-	{ "trte", 0xbf, INSTR_RRF_M0RR },
+	{ "cu41", 0xb2, INSTR_RRE_RR },
+	{ "cu42", 0xb3, INSTR_RRE_RR },
 	{ "trtre", 0xbd, INSTR_RRF_M0RR },
+	{ "srstu", 0xbe, INSTR_RRE_RR },
+	{ "trte", 0xbf, INSTR_RRF_M0RR },
 	{ "ahhhr", 0xc8, INSTR_RRF_R0RR2 },
 	{ "shhhr", 0xc9, INSTR_RRF_R0RR2 },
-	{ "alhhh", 0xca, INSTR_RRF_R0RR2 },
-	{ "alhhl", 0xca, INSTR_RRF_R0RR2 },
-	{ "slhhh", 0xcb, INSTR_RRF_R0RR2 },
-	{ "chhr ", 0xcd, INSTR_RRE_RR },
+	{ { 0, LONG_INSN_ALHHHR }, 0xca, INSTR_RRF_R0RR2 },
+	{ { 0, LONG_INSN_SLHHHR }, 0xcb, INSTR_RRF_R0RR2 },
+	{ "chhr", 0xcd, INSTR_RRE_RR },
 	{ "clhhr", 0xcf, INSTR_RRE_RR },
 	{ "ahhlr", 0xd8, INSTR_RRF_R0RR2 },
 	{ "shhlr", 0xd9, INSTR_RRF_R0RR2 },
-	{ "slhhl", 0xdb, INSTR_RRF_R0RR2 },
+	{ { 0, LONG_INSN_ALHHLR }, 0xda, INSTR_RRF_R0RR2 },
+	{ { 0, LONG_INSN_SLHHLR }, 0xdb, INSTR_RRF_R0RR2 },
 	{ "chlr", 0xdd, INSTR_RRE_RR },
 	{ "clhlr", 0xdf, INSTR_RRE_RR },
 	{ { 0, LONG_INSN_POPCNT }, 0xe1, INSTR_RRE_RR },
@@ -976,13 +1146,9 @@ static struct insn opcode_b9[] = {
 	{ "kimd", 0x3e, INSTR_RRE_RR },
 	{ "klmd", 0x3f, INSTR_RRE_RR },
 	{ "epsw", 0x8d, INSTR_RRE_RR },
-	{ "trtt", 0x90, INSTR_RRE_RR },
 	{ "trtt", 0x90, INSTR_RRF_M0RR },
-	{ "trto", 0x91, INSTR_RRE_RR },
 	{ "trto", 0x91, INSTR_RRF_M0RR },
-	{ "trot", 0x92, INSTR_RRE_RR },
 	{ "trot", 0x92, INSTR_RRF_M0RR },
-	{ "troo", 0x93, INSTR_RRE_RR },
 	{ "troo", 0x93, INSTR_RRF_M0RR },
 	{ "mlr", 0x96, INSTR_RRE_RR },
 	{ "dlr", 0x97, INSTR_RRE_RR },
@@ -1013,6 +1179,8 @@ static struct insn opcode_c0[] = {
 
 static struct insn opcode_c2[] = {
 #ifdef CONFIG_64BIT
+	{ "msgfi", 0x00, INSTR_RIL_RI },
+	{ "msfi", 0x01, INSTR_RIL_RI },
 	{ "slgfi", 0x04, INSTR_RIL_RU },
 	{ "slfi", 0x05, INSTR_RIL_RU },
 	{ "agfi", 0x08, INSTR_RIL_RI },
@@ -1023,43 +1191,41 @@ static struct insn opcode_c2[] = {
 	{ "cfi", 0x0d, INSTR_RIL_RI },
 	{ "clgfi", 0x0e, INSTR_RIL_RU },
 	{ "clfi", 0x0f, INSTR_RIL_RU },
-	{ "msfi", 0x01, INSTR_RIL_RI },
-	{ "msgfi", 0x00, INSTR_RIL_RI },
 #endif
 	{ "", 0, INSTR_INVALID }
 };
 
 static struct insn opcode_c4[] = {
 #ifdef CONFIG_64BIT
-	{ "lrl", 0x0d, INSTR_RIL_RP },
+	{ "llhrl", 0x02, INSTR_RIL_RP },
+	{ "lghrl", 0x04, INSTR_RIL_RP },
+	{ "lhrl", 0x05, INSTR_RIL_RP },
+	{ { 0, LONG_INSN_LLGHRL }, 0x06, INSTR_RIL_RP },
+	{ "sthrl", 0x07, INSTR_RIL_RP },
 	{ "lgrl", 0x08, INSTR_RIL_RP },
+	{ "stgrl", 0x0b, INSTR_RIL_RP },
 	{ "lgfrl", 0x0c, INSTR_RIL_RP },
-	{ "lhrl", 0x05, INSTR_RIL_RP },
-	{ "lghrl", 0x04, INSTR_RIL_RP },
+	{ "lrl", 0x0d, INSTR_RIL_RP },
 	{ { 0, LONG_INSN_LLGFRL }, 0x0e, INSTR_RIL_RP },
-	{ "llhrl", 0x02, INSTR_RIL_RP },
-	{ { 0, LONG_INSN_LLGHRL }, 0x06, INSTR_RIL_RP },
 	{ "strl", 0x0f, INSTR_RIL_RP },
-	{ "stgrl", 0x0b, INSTR_RIL_RP },
-	{ "sthrl", 0x07, INSTR_RIL_RP },
 #endif
 	{ "", 0, INSTR_INVALID }
 };
 
 static struct insn opcode_c6[] = {
 #ifdef CONFIG_64BIT
-	{ "crl", 0x0d, INSTR_RIL_RP },
-	{ "cgrl", 0x08, INSTR_RIL_RP },
-	{ "cgfrl", 0x0c, INSTR_RIL_RP },
-	{ "chrl", 0x05, INSTR_RIL_RP },
+	{ "exrl", 0x00, INSTR_RIL_RP },
+	{ "pfdrl", 0x02, INSTR_RIL_UP },
 	{ "cghrl", 0x04, INSTR_RIL_RP },
-	{ "clrl", 0x0f, INSTR_RIL_RP },
+	{ "chrl", 0x05, INSTR_RIL_RP },
+	{ { 0, LONG_INSN_CLGHRL }, 0x06, INSTR_RIL_RP },
+	{ "clhrl", 0x07, INSTR_RIL_RP },
+	{ "cgrl", 0x08, INSTR_RIL_RP },
 	{ "clgrl", 0x0a, INSTR_RIL_RP },
+	{ "cgfrl", 0x0c, INSTR_RIL_RP },
+	{ "crl", 0x0d, INSTR_RIL_RP },
 	{ { 0, LONG_INSN_CLGFRL }, 0x0e, INSTR_RIL_RP },
-	{ "clhrl", 0x07, INSTR_RIL_RP },
-	{ { 0, LONG_INSN_CLGHRL }, 0x06, INSTR_RIL_RP },
-	{ "pfdrl", 0x02, INSTR_RIL_UP },
-	{ "exrl", 0x00, INSTR_RIL_RP },
+	{ "clrl", 0x0f, INSTR_RIL_RP },
 #endif
 	{ "", 0, INSTR_INVALID }
 };
@@ -1070,7 +1236,7 @@ static struct insn opcode_c8[] = {
 	{ "ectg", 0x01, INSTR_SSF_RRDRD },
 	{ "csst", 0x02, INSTR_SSF_RRDRD },
 	{ "lpd", 0x04, INSTR_SSF_RRDRD2 },
-	{ "lpdg ", 0x05, INSTR_SSF_RRDRD2 },
+	{ "lpdg", 0x05, INSTR_SSF_RRDRD2 },
 #endif
 	{ "", 0, INSTR_INVALID }
 };
@@ -1080,9 +1246,9 @@ static struct insn opcode_cc[] = {
 	{ "brcth", 0x06, INSTR_RIL_RP },
 	{ "aih", 0x08, INSTR_RIL_RI },
 	{ "alsih", 0x0a, INSTR_RIL_RI },
-	{ "alsih", 0x0b, INSTR_RIL_RI },
+	{ { 0, LONG_INSN_ALSIHN }, 0x0b, INSTR_RIL_RI },
 	{ "cih", 0x0d, INSTR_RIL_RI },
-	{ "clih ", 0x0f, INSTR_RIL_RI },
+	{ "clih", 0x0f, INSTR_RIL_RI },
 #endif
 	{ "", 0, INSTR_INVALID }
 };
@@ -1116,11 +1282,15 @@ static struct insn opcode_e3[] = {
 	{ "cg", 0x20, INSTR_RXY_RRRD },
 	{ "clg", 0x21, INSTR_RXY_RRRD },
 	{ "stg", 0x24, INSTR_RXY_RRRD },
+	{ "ntstg", 0x25, INSTR_RXY_RRRD },
 	{ "cvdy", 0x26, INSTR_RXY_RRRD },
 	{ "cvdg", 0x2e, INSTR_RXY_RRRD },
 	{ "strvg", 0x2f, INSTR_RXY_RRRD },
 	{ "cgf", 0x30, INSTR_RXY_RRRD },
 	{ "clgf", 0x31, INSTR_RXY_RRRD },
+	{ "ltgf", 0x32, INSTR_RXY_RRRD },
+	{ "cgh", 0x34, INSTR_RXY_RRRD },
+	{ "pfd", 0x36, INSTR_RXY_URRD },
 	{ "strvh", 0x3f, INSTR_RXY_RRRD },
 	{ "bctg", 0x46, INSTR_RXY_RRRD },
 	{ "sty", 0x50, INSTR_RXY_RRRD },
@@ -1133,21 +1303,25 @@ static struct insn opcode_e3[] = {
 	{ "cy", 0x59, INSTR_RXY_RRRD },
 	{ "ay", 0x5a, INSTR_RXY_RRRD },
 	{ "sy", 0x5b, INSTR_RXY_RRRD },
+	{ "mfy", 0x5c, INSTR_RXY_RRRD },
 	{ "aly", 0x5e, INSTR_RXY_RRRD },
 	{ "sly", 0x5f, INSTR_RXY_RRRD },
 	{ "sthy", 0x70, INSTR_RXY_RRRD },
 	{ "lay", 0x71, INSTR_RXY_RRRD },
 	{ "stcy", 0x72, INSTR_RXY_RRRD },
 	{ "icy", 0x73, INSTR_RXY_RRRD },
+	{ "laey", 0x75, INSTR_RXY_RRRD },
 	{ "lb", 0x76, INSTR_RXY_RRRD },
 	{ "lgb", 0x77, INSTR_RXY_RRRD },
 	{ "lhy", 0x78, INSTR_RXY_RRRD },
 	{ "chy", 0x79, INSTR_RXY_RRRD },
 	{ "ahy", 0x7a, INSTR_RXY_RRRD },
 	{ "shy", 0x7b, INSTR_RXY_RRRD },
+	{ "mhy", 0x7c, INSTR_RXY_RRRD },
 	{ "ng", 0x80, INSTR_RXY_RRRD },
 	{ "og", 0x81, INSTR_RXY_RRRD },
 	{ "xg", 0x82, INSTR_RXY_RRRD },
+	{ "lgat", 0x85, INSTR_RXY_RRRD },
 	{ "mlg", 0x86, INSTR_RXY_RRRD },
 	{ "dlg", 0x87, INSTR_RXY_RRRD },
 	{ "alcg", 0x88, INSTR_RXY_RRRD },
@@ -1158,23 +1332,20 @@ static struct insn opcode_e3[] = {
 	{ "llgh", 0x91, INSTR_RXY_RRRD },
 	{ "llc", 0x94, INSTR_RXY_RRRD },
 	{ "llh", 0x95, INSTR_RXY_RRRD },
-	{ "cgh", 0x34, INSTR_RXY_RRRD },
-	{ "laey", 0x75, INSTR_RXY_RRRD },
-	{ "ltgf", 0x32, INSTR_RXY_RRRD },
-	{ "mfy", 0x5c, INSTR_RXY_RRRD },
-	{ "mhy", 0x7c, INSTR_RXY_RRRD },
-	{ "pfd", 0x36, INSTR_RXY_URRD },
+	{ { 0, LONG_INSN_LLGTAT }, 0x9c, INSTR_RXY_RRRD },
+	{ { 0, LONG_INSN_LLGFAT }, 0x9d, INSTR_RXY_RRRD },
+	{ "lat", 0x9f, INSTR_RXY_RRRD },
 	{ "lbh", 0xc0, INSTR_RXY_RRRD },
 	{ "llch", 0xc2, INSTR_RXY_RRRD },
 	{ "stch", 0xc3, INSTR_RXY_RRRD },
 	{ "lhh", 0xc4, INSTR_RXY_RRRD },
 	{ "llhh", 0xc6, INSTR_RXY_RRRD },
 	{ "sthh", 0xc7, INSTR_RXY_RRRD },
+	{ "lfhat", 0xc8, INSTR_RXY_RRRD },
 	{ "lfh", 0xca, INSTR_RXY_RRRD },
 	{ "stfh", 0xcb, INSTR_RXY_RRRD },
 	{ "chf", 0xcd, INSTR_RXY_RRRD },
 	{ "clhf", 0xcf, INSTR_RXY_RRRD },
-	{ "ntstg", 0x25, INSTR_RXY_RRRD },
 #endif
 	{ "lrv", 0x1e, INSTR_RXY_RRRD },
 	{ "lrvh", 0x1f, INSTR_RXY_RRRD },
@@ -1189,15 +1360,15 @@ static struct insn opcode_e3[] = {
 static struct insn opcode_e5[] = {
 #ifdef CONFIG_64BIT
 	{ "strag", 0x02, INSTR_SSE_RDRD },
+	{ "mvhhi", 0x44, INSTR_SIL_RDI },
+	{ "mvghi", 0x48, INSTR_SIL_RDI },
+	{ "mvhi", 0x4c, INSTR_SIL_RDI },
 	{ "chhsi", 0x54, INSTR_SIL_RDI },
-	{ "chsi", 0x5c, INSTR_SIL_RDI },
-	{ "cghsi", 0x58, INSTR_SIL_RDI },
 	{ { 0, LONG_INSN_CLHHSI }, 0x55, INSTR_SIL_RDU },
-	{ { 0, LONG_INSN_CLFHSI }, 0x5d, INSTR_SIL_RDU },
+	{ "cghsi", 0x58, INSTR_SIL_RDI },
 	{ { 0, LONG_INSN_CLGHSI }, 0x59, INSTR_SIL_RDU },
-	{ "mvhhi", 0x44, INSTR_SIL_RDI },
-	{ "mvhi", 0x4c, INSTR_SIL_RDI },
-	{ "mvghi", 0x48, INSTR_SIL_RDI },
+	{ "chsi", 0x5c, INSTR_SIL_RDI },
+	{ { 0, LONG_INSN_CLFHSI }, 0x5d, INSTR_SIL_RDU },
 	{ { 0, LONG_INSN_TBEGIN }, 0x60, INSTR_SIL_RDU },
 	{ { 0, LONG_INSN_TBEGINC }, 0x61, INSTR_SIL_RDU },
 #endif
@@ -1220,9 +1391,11 @@ static struct insn opcode_eb[] = {
 	{ "rllg", 0x1c, INSTR_RSY_RRRD },
 	{ "clmh", 0x20, INSTR_RSY_RURD },
 	{ "clmy", 0x21, INSTR_RSY_RURD },
+	{ "clt", 0x23, INSTR_RSY_RURD },
 	{ "stmg", 0x24, INSTR_RSY_RRRD },
 	{ "stctg", 0x25, INSTR_RSY_CCRD },
 	{ "stmh", 0x26, INSTR_RSY_RRRD },
+	{ "clgt", 0x2b, INSTR_RSY_RURD },
 	{ "stcmh", 0x2c, INSTR_RSY_RURD },
 	{ "stcmy", 0x2d, INSTR_RSY_RURD },
 	{ "lctlg", 0x2f, INSTR_RSY_CCRD },
@@ -1231,16 +1404,17 @@ static struct insn opcode_eb[] = {
 	{ "cdsg", 0x3e, INSTR_RSY_RRRD },
 	{ "bxhg", 0x44, INSTR_RSY_RRRD },
 	{ "bxleg", 0x45, INSTR_RSY_RRRD },
+	{ "ecag", 0x4c, INSTR_RSY_RRRD },
 	{ "tmy", 0x51, INSTR_SIY_URD },
 	{ "mviy", 0x52, INSTR_SIY_URD },
 	{ "niy", 0x54, INSTR_SIY_URD },
 	{ "cliy", 0x55, INSTR_SIY_URD },
 	{ "oiy", 0x56, INSTR_SIY_URD },
 	{ "xiy", 0x57, INSTR_SIY_URD },
-	{ "lric", 0x60, INSTR_RSY_RDRM },
-	{ "stric", 0x61, INSTR_RSY_RDRM },
-	{ "mric", 0x62, INSTR_RSY_RDRM },
-	{ "icmh", 0x80, INSTR_RSE_RURD },
+	{ "asi", 0x6a, INSTR_SIY_IRD },
+	{ "alsi", 0x6e, INSTR_SIY_IRD },
+	{ "agsi", 0x7a, INSTR_SIY_IRD },
+	{ "algsi", 0x7e, INSTR_SIY_IRD },
 	{ "icmh", 0x80, INSTR_RSY_RURD },
 	{ "icmy", 0x81, INSTR_RSY_RURD },
 	{ "clclu", 0x8f, INSTR_RSY_RRRD },
@@ -1249,11 +1423,6 @@ static struct insn opcode_eb[] = {
 	{ "lmy", 0x98, INSTR_RSY_RRRD },
 	{ "lamy", 0x9a, INSTR_RSY_AARD },
 	{ "stamy", 0x9b, INSTR_RSY_AARD },
-	{ "asi", 0x6a, INSTR_SIY_IRD },
-	{ "agsi", 0x7a, INSTR_SIY_IRD },
-	{ "alsi", 0x6e, INSTR_SIY_IRD },
-	{ "algsi", 0x7e, INSTR_SIY_IRD },
-	{ "ecag", 0x4c, INSTR_RSY_RRRD },
 	{ "srak", 0xdc, INSTR_RSY_RRRD },
 	{ "slak", 0xdd, INSTR_RSY_RRRD },
 	{ "srlk", 0xde, INSTR_RSY_RRRD },
@@ -1272,6 +1441,9 @@ static struct insn opcode_eb[] = {
 	{ "lax", 0xf7, INSTR_RSY_RRRD },
 	{ "laa", 0xf8, INSTR_RSY_RRRD },
 	{ "laal", 0xfa, INSTR_RSY_RRRD },
+	{ "lric", 0x60, INSTR_RSY_RDRM },
+	{ "stric", 0x61, INSTR_RSY_RDRM },
+	{ "mric", 0x62, INSTR_RSY_RDRM },
 #endif
 	{ "rll", 0x1d, INSTR_RSY_RRRD },
 	{ "mvclu", 0x8e, INSTR_RSY_RRRD },
@@ -1283,36 +1455,37 @@ static struct insn opcode_ec[] = {
 #ifdef CONFIG_64BIT
 	{ "brxhg", 0x44, INSTR_RIE_RRP },
 	{ "brxlg", 0x45, INSTR_RIE_RRP },
-	{ "crb", 0xf6, INSTR_RRS_RRRDU },
-	{ "cgrb", 0xe4, INSTR_RRS_RRRDU },
-	{ "crj", 0x76, INSTR_RIE_RRPU },
+	{ { 0, LONG_INSN_RISBLG }, 0x51, INSTR_RIE_RRUUU },
+	{ "rnsbg", 0x54, INSTR_RIE_RRUUU },
+	{ "risbg", 0x55, INSTR_RIE_RRUUU },
+	{ "rosbg", 0x56, INSTR_RIE_RRUUU },
+	{ "rxsbg", 0x57, INSTR_RIE_RRUUU },
+	{ { 0, LONG_INSN_RISBGN }, 0x59, INSTR_RIE_RRUUU },
+	{ { 0, LONG_INSN_RISBHG }, 0x5D, INSTR_RIE_RRUUU },
 	{ "cgrj", 0x64, INSTR_RIE_RRPU },
-	{ "cib", 0xfe, INSTR_RIS_RURDI },
-	{ "cgib", 0xfc, INSTR_RIS_RURDI },
-	{ "cij", 0x7e, INSTR_RIE_RUPI },
-	{ "cgij", 0x7c, INSTR_RIE_RUPI },
-	{ "cit", 0x72, INSTR_RIE_R0IU },
+	{ "clgrj", 0x65, INSTR_RIE_RRPU },
 	{ "cgit", 0x70, INSTR_RIE_R0IU },
-	{ "clrb", 0xf7, INSTR_RRS_RRRDU },
-	{ "clgrb", 0xe5, INSTR_RRS_RRRDU },
+	{ "clgit", 0x71, INSTR_RIE_R0UU },
+	{ "cit", 0x72, INSTR_RIE_R0IU },
+	{ "clfit", 0x73, INSTR_RIE_R0UU },
+	{ "crj", 0x76, INSTR_RIE_RRPU },
 	{ "clrj", 0x77, INSTR_RIE_RRPU },
-	{ "clgrj", 0x65, INSTR_RIE_RRPU },
-	{ "clib", 0xff, INSTR_RIS_RURDU },
-	{ "clgib", 0xfd, INSTR_RIS_RURDU },
-	{ "clij", 0x7f, INSTR_RIE_RUPU },
+	{ "cgij", 0x7c, INSTR_RIE_RUPI },
 	{ "clgij", 0x7d, INSTR_RIE_RUPU },
-	{ "clfit", 0x73, INSTR_RIE_R0UU },
-	{ "clgit", 0x71, INSTR_RIE_R0UU },
-	{ "rnsbg", 0x54, INSTR_RIE_RRUUU },
-	{ "rxsbg", 0x57, INSTR_RIE_RRUUU },
-	{ "rosbg", 0x56, INSTR_RIE_RRUUU },
-	{ "risbg", 0x55, INSTR_RIE_RRUUU },
-	{ { 0, LONG_INSN_RISBLG }, 0x51, INSTR_RIE_RRUUU },
-	{ { 0, LONG_INSN_RISBHG }, 0x5D, INSTR_RIE_RRUUU },
+	{ "cij", 0x7e, INSTR_RIE_RUPI },
+	{ "clij", 0x7f, INSTR_RIE_RUPU },
 	{ "ahik", 0xd8, INSTR_RIE_RRI0 },
 	{ "aghik", 0xd9, INSTR_RIE_RRI0 },
 	{ { 0, LONG_INSN_ALHSIK }, 0xda, INSTR_RIE_RRI0 },
 	{ { 0, LONG_INSN_ALGHSIK }, 0xdb, INSTR_RIE_RRI0 },
+	{ "cgrb", 0xe4, INSTR_RRS_RRRDU },
+	{ "clgrb", 0xe5, INSTR_RRS_RRRDU },
+	{ "crb", 0xf6, INSTR_RRS_RRRDU },
+	{ "clrb", 0xf7, INSTR_RRS_RRRDU },
+	{ "cgib", 0xfc, INSTR_RIS_RURDI },
+	{ "clgib", 0xfd, INSTR_RIS_RURDU },
+	{ "cib", 0xfe, INSTR_RIS_RURDI },
+	{ "clib", 0xff, INSTR_RIS_RURDU },
 #endif
 	{ "", 0, INSTR_INVALID }
 };
@@ -1325,20 +1498,24 @@ static struct insn opcode_ed[] = {
 	{ "my", 0x3b, INSTR_RXF_FRRDF },
 	{ "mayh", 0x3c, INSTR_RXF_FRRDF },
 	{ "myh", 0x3d, INSTR_RXF_FRRDF },
-	{ "ley", 0x64, INSTR_RXY_FRRD },
-	{ "ldy", 0x65, INSTR_RXY_FRRD },
-	{ "stey", 0x66, INSTR_RXY_FRRD },
-	{ "stdy", 0x67, INSTR_RXY_FRRD },
 	{ "sldt", 0x40, INSTR_RXF_FRRDF },
-	{ "slxt", 0x48, INSTR_RXF_FRRDF },
 	{ "srdt", 0x41, INSTR_RXF_FRRDF },
+	{ "slxt", 0x48, INSTR_RXF_FRRDF },
 	{ "srxt", 0x49, INSTR_RXF_FRRDF },
 	{ "tdcet", 0x50, INSTR_RXE_FRRD },
-	{ "tdcdt", 0x54, INSTR_RXE_FRRD },
-	{ "tdcxt", 0x58, INSTR_RXE_FRRD },
 	{ "tdget", 0x51, INSTR_RXE_FRRD },
+	{ "tdcdt", 0x54, INSTR_RXE_FRRD },
 	{ "tdgdt", 0x55, INSTR_RXE_FRRD },
+	{ "tdcxt", 0x58, INSTR_RXE_FRRD },
 	{ "tdgxt", 0x59, INSTR_RXE_FRRD },
+	{ "ley", 0x64, INSTR_RXY_FRRD },
+	{ "ldy", 0x65, INSTR_RXY_FRRD },
+	{ "stey", 0x66, INSTR_RXY_FRRD },
+	{ "stdy", 0x67, INSTR_RXY_FRRD },
+	{ "czdt", 0xa8, INSTR_RSL_LRDFU },
+	{ "czxt", 0xa9, INSTR_RSL_LRDFU },
+	{ "cdzt", 0xaa, INSTR_RSL_LRDFU },
+	{ "cxzt", 0xab, INSTR_RSL_LRDFU },
 #endif
 	{ "ldeb", 0x04, INSTR_RXE_FRRD },
 	{ "lxdb", 0x05, INSTR_RXE_FRRD },
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index ef46f66..5502285 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -231,12 +231,12 @@ sysc_work:
 	jo	sysc_mcck_pending
 	tm	__TI_flags+3(%r12),_TIF_NEED_RESCHED
 	jo	sysc_reschedule
+	tm	__TI_flags+3(%r12),_TIF_PER_TRAP
+	jo	sysc_singlestep
 	tm	__TI_flags+3(%r12),_TIF_SIGPENDING
 	jo	sysc_sigpending
 	tm	__TI_flags+3(%r12),_TIF_NOTIFY_RESUME
 	jo	sysc_notify_resume
-	tm	__TI_flags+3(%r12),_TIF_PER_TRAP
-	jo	sysc_singlestep
 	j	sysc_return		# beware of critical section cleanup
 
 #
@@ -259,7 +259,6 @@ sysc_mcck_pending:
 # _TIF_SIGPENDING is set, call do_signal
 #
 sysc_sigpending:
-	ni	__TI_flags+3(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
 	lr	%r2,%r11		# pass pointer to pt_regs
 	l	%r1,BASED(.Ldo_signal)
 	basr	%r14,%r1		# call do_signal
@@ -286,7 +285,7 @@ sysc_notify_resume:
 # _TIF_PER_TRAP is set, call do_per_trap
 #
 sysc_singlestep:
-	ni	__TI_flags+3(%r12),255-(_TIF_SYSCALL | _TIF_PER_TRAP)
+	ni	__TI_flags+3(%r12),255-_TIF_PER_TRAP
 	lr	%r2,%r11		# pass pointer to pt_regs
 	l	%r1,BASED(.Ldo_per_trap)
 	la	%r14,BASED(sysc_return)
@@ -330,40 +329,18 @@ ENTRY(ret_from_fork)
 	la	%r11,STACK_FRAME_OVERHEAD(%r15)
 	l	%r12,__LC_THREAD_INFO
 	l	%r13,__LC_SVC_NEW_PSW+4
-	tm	__PT_PSW+1(%r11),0x01	# forking a kernel thread ?
-	je	1f
-	l	%r1,BASED(.Lschedule_tail)
-	basr	%r14,%r1		# call schedule_tail
-	TRACE_IRQS_ON
-	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
-	j	sysc_tracenogo
-
-1:	# it's a kernel thread
-	st	%r15,__PT_R15(%r11)	# store stack pointer for new kthread
 	l	%r1,BASED(.Lschedule_tail)
 	basr	%r14,%r1		# call schedule_tail
 	TRACE_IRQS_ON
 	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
-	lm	%r9,%r11,__PT_R9(%r11)	# load gprs
+	tm	__PT_PSW+1(%r11),0x01	# forking a kernel thread ?
+	jne	sysc_tracenogo
+	# it's a kernel thread
+	lm	%r9,%r10,__PT_R9(%r11)	# load gprs
 ENTRY(kernel_thread_starter)
 	la	%r2,0(%r10)
 	basr	%r14,%r9
-	la	%r2,0
-	br	%r11			# do_exit
-
-#
-# kernel_execve function needs to deal with pt_regs that is not
-# at the usual place
-#
-ENTRY(ret_from_kernel_execve)
-	ssm	__LC_PGM_NEW_PSW	# disable I/O and ext. interrupts
-	lr	%r15,%r2
-	lr	%r11,%r2
-	ahi	%r15,-STACK_FRAME_OVERHEAD
-	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
-	l	%r12,__LC_THREAD_INFO
-	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
-	j	sysc_return
+	j	sysc_tracenogo
 
 /*
  * Program check handler routine
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index d0d3f69..80ebb98 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -6,7 +6,6 @@
 #include <asm/ptrace.h>
 #include <asm/cputime.h>
 
-extern void (*pgm_check_table[128])(struct pt_regs *);
 extern void *restart_stack;
 
 void system_call(void);
@@ -25,6 +24,26 @@ 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);
+void default_trap_handler(struct pt_regs *regs);
+void divide_exception(struct pt_regs *regs);
+void execute_exception(struct pt_regs *regs);
+void hfp_divide_exception(struct pt_regs *regs);
+void hfp_overflow_exception(struct pt_regs *regs);
+void hfp_significance_exception(struct pt_regs *regs);
+void hfp_sqrt_exception(struct pt_regs *regs);
+void hfp_underflow_exception(struct pt_regs *regs);
+void illegal_op(struct pt_regs *regs);
+void operand_exception(struct pt_regs *regs);
+void overflow_exception(struct pt_regs *regs);
+void privileged_op(struct pt_regs *regs);
+void space_switch_exception(struct pt_regs *regs);
+void special_op_exception(struct pt_regs *regs);
+void specification_exception(struct pt_regs *regs);
+void transaction_exception(struct pt_regs *regs);
+void translation_exception(struct pt_regs *regs);
+
 void do_per_trap(struct pt_regs *regs);
 void syscall_trace(struct pt_regs *regs, int entryexit);
 void kernel_stack_overflow(struct pt_regs * regs);
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 07d8de3..6d34e0c 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -80,14 +80,21 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
 #endif
 	.endm
 
-	.macro	HANDLE_SIE_INTERCEPT scratch
+	.macro	HANDLE_SIE_INTERCEPT scratch,pgmcheck
 #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
 	tmhh	%r8,0x0001		# interrupting from user ?
 	jnz	.+42
 	lgr	\scratch,%r9
 	slg	\scratch,BASED(.Lsie_loop)
 	clg	\scratch,BASED(.Lsie_length)
+	.if	\pgmcheck
+	# Some program interrupts are suppressing (e.g. protection).
+	# We must also check the instruction after SIE in that case.
+	# do_protection_exception will rewind to rewind_pad
+	jh	.+22
+	.else
 	jhe	.+22
+	.endif
 	lg	%r9,BASED(.Lsie_loop)
 	SPP	BASED(.Lhost_id)	# set host id
 #endif
@@ -262,12 +269,12 @@ sysc_work:
 	jo	sysc_mcck_pending
 	tm	__TI_flags+7(%r12),_TIF_NEED_RESCHED
 	jo	sysc_reschedule
+	tm	__TI_flags+7(%r12),_TIF_PER_TRAP
+	jo	sysc_singlestep
 	tm	__TI_flags+7(%r12),_TIF_SIGPENDING
 	jo	sysc_sigpending
 	tm	__TI_flags+7(%r12),_TIF_NOTIFY_RESUME
 	jo	sysc_notify_resume
-	tm	__TI_flags+7(%r12),_TIF_PER_TRAP
-	jo	sysc_singlestep
 	j	sysc_return		# beware of critical section cleanup
 
 #
@@ -288,7 +295,6 @@ sysc_mcck_pending:
 # _TIF_SIGPENDING is set, call do_signal
 #
 sysc_sigpending:
-	ni	__TI_flags+7(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
 	lgr	%r2,%r11		# pass pointer to pt_regs
 	brasl	%r14,do_signal
 	tm	__TI_flags+7(%r12),_TIF_SYSCALL
@@ -313,7 +319,7 @@ sysc_notify_resume:
 # _TIF_PER_TRAP is set, call do_per_trap
 #
 sysc_singlestep:
-	ni	__TI_flags+7(%r12),255-(_TIF_SYSCALL | _TIF_PER_TRAP)
+	ni	__TI_flags+7(%r12),255-_TIF_PER_TRAP
 	lgr	%r2,%r11		# pass pointer to pt_regs
 	larl	%r14,sysc_return
 	jg	do_per_trap
@@ -352,33 +358,17 @@ sysc_tracenogo:
 ENTRY(ret_from_fork)
 	la	%r11,STACK_FRAME_OVERHEAD(%r15)
 	lg	%r12,__LC_THREAD_INFO
-	tm	__PT_PSW+1(%r11),0x01	# forking a kernel thread ?
-	je	1f
-	brasl	%r14,schedule_tail
-	TRACE_IRQS_ON
-	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
-	j	sysc_tracenogo
-1:	# it's a kernel thread
-	stg	%r15,__PT_R15(%r11)	# store stack pointer for new kthread
 	brasl	%r14,schedule_tail
 	TRACE_IRQS_ON
 	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
-	lmg	%r9,%r11,__PT_R9(%r11)	# load gprs
+	tm	__PT_PSW+1(%r11),0x01	# forking a kernel thread ?
+	jne	sysc_tracenogo
+	# it's a kernel thread
+	lmg	%r9,%r10,__PT_R9(%r11)	# load gprs
 ENTRY(kernel_thread_starter)
 	la	%r2,0(%r10)
 	basr	%r14,%r9
-	la	%r2,0
-	br	%r11			# do_exit
-
-ENTRY(ret_from_kernel_execve)
-	ssm	__LC_PGM_NEW_PSW	# disable I/O and ext. interrupts
-	lgr	%r15,%r2
-	lgr	%r11,%r2
-	aghi	%r15,-STACK_FRAME_OVERHEAD
-	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
-	lg	%r12,__LC_THREAD_INFO
-	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
-	j	sysc_return
+	j	sysc_tracenogo
 
 /*
  * Program check handler routine
@@ -391,7 +381,7 @@ ENTRY(pgm_check_handler)
 	lg	%r12,__LC_THREAD_INFO
 	larl	%r13,system_call
 	lmg	%r8,%r9,__LC_PGM_OLD_PSW
-	HANDLE_SIE_INTERCEPT %r14
+	HANDLE_SIE_INTERCEPT %r14,1
 	tmhh	%r8,0x0001		# test problem state bit
 	jnz	1f			# -> fault in user space
 	tmhh	%r8,0x4000		# PER bit set in old PSW ?
@@ -429,9 +419,9 @@ ENTRY(pgm_check_handler)
 	larl	%r1,pgm_check_table
 	llgh	%r10,__PT_INT_CODE+2(%r11)
 	nill	%r10,0x007f
-	sll	%r10,3
+	sll	%r10,2
 	je	sysc_return
-	lg	%r1,0(%r10,%r1)		# load address of handler routine
+	lgf	%r1,0(%r10,%r1)		# load address of handler routine
 	lgr	%r2,%r11		# pass pointer to pt_regs
 	basr	%r14,%r1		# branch to interrupt-handler
 	j	sysc_return
@@ -467,7 +457,7 @@ ENTRY(io_int_handler)
 	lg	%r12,__LC_THREAD_INFO
 	larl	%r13,system_call
 	lmg	%r8,%r9,__LC_IO_OLD_PSW
-	HANDLE_SIE_INTERCEPT %r14
+	HANDLE_SIE_INTERCEPT %r14,0
 	SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT
 	tmhh	%r8,0x0001		# interrupting from user?
 	jz	io_skip
@@ -613,7 +603,7 @@ ENTRY(ext_int_handler)
 	lg	%r12,__LC_THREAD_INFO
 	larl	%r13,system_call
 	lmg	%r8,%r9,__LC_EXT_OLD_PSW
-	HANDLE_SIE_INTERCEPT %r14
+	HANDLE_SIE_INTERCEPT %r14,0
 	SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT
 	tmhh	%r8,0x0001		# interrupting from user ?
 	jz	ext_skip
@@ -661,7 +651,7 @@ ENTRY(mcck_int_handler)
 	lg	%r12,__LC_THREAD_INFO
 	larl	%r13,system_call
 	lmg	%r8,%r9,__LC_MCK_OLD_PSW
-	HANDLE_SIE_INTERCEPT %r14
+	HANDLE_SIE_INTERCEPT %r14,0
 	tm	__LC_MCCK_CODE,0x80	# system damage?
 	jo	mcck_panic		# yes -> rest of mcck code invalid
 	lghi	%r14,__LC_CPU_TIMER_SAVE_AREA
@@ -960,6 +950,13 @@ ENTRY(sie64a)
 	stg	%r3,__SF_EMPTY+8(%r15)		# save guest register save area
 	xc	__SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # host id == 0
 	lmg	%r0,%r13,0(%r3)			# load guest gprs 0-13
+# some program checks are suppressing. C code (e.g. do_protection_exception)
+# will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other
+# instructions in the sie_loop should not cause program interrupts. So
+# lets use a nop (47 00 00 00) as a landing pad.
+# See also HANDLE_SIE_INTERCEPT
+rewind_pad:
+	nop	0
 sie_loop:
 	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
 	tm	__TI_flags+7(%r14),_TIF_EXIT_SIE
@@ -999,6 +996,7 @@ sie_fault:
 .Lhost_id:
 	.quad	0
 
+	EX_TABLE(rewind_pad,sie_fault)
 	EX_TABLE(sie_loop,sie_fault)
 #endif
 
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index 984726c..fd8db63 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -393,30 +393,35 @@ ENTRY(startup_kdump)
 	xc	0x300(256),0x300
 	xc	0xe00(256),0xe00
 	stck	__LC_LAST_UPDATE_CLOCK
-	spt	5f-.LPG0(%r13)
-	mvc	__LC_LAST_UPDATE_TIMER(8),5f-.LPG0(%r13)
+	spt	6f-.LPG0(%r13)
+	mvc	__LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13)
 	xc	__LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST
 #ifndef CONFIG_MARCH_G5
 	# check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10}
 	.insn	s,0xb2b10000,__LC_STFL_FAC_LIST	# store facility list
 	tm	__LC_STFL_FAC_LIST,0x01	# stfle available ?
 	jz	0f
-	la	%r0,0
+	la	%r0,1
 	.insn	s,0xb2b00000,__LC_STFL_FAC_LIST	# store facility list extended
-0:	l	%r0,__LC_STFL_FAC_LIST
-	n	%r0,2f+8-.LPG0(%r13)
-	cl	%r0,2f+8-.LPG0(%r13)
-	jne	1f
-	l	%r0,__LC_STFL_FAC_LIST+4
-	n	%r0,2f+12-.LPG0(%r13)
-	cl	%r0,2f+12-.LPG0(%r13)
-	je	3f
-1:	l	%r15,.Lstack-.LPG0(%r13)
+	# verify if all required facilities are supported by the machine
+0:	la	%r1,__LC_STFL_FAC_LIST
+	la	%r2,3f+8-.LPG0(%r13)
+	l	%r3,0(%r2)
+1:	l	%r0,0(%r1)
+	n	%r0,4(%r2)
+	cl	%r0,4(%r2)
+	jne	2f
+	la	%r1,4(%r1)
+	la	%r2,4(%r2)
+	ahi	%r3,-1
+	jnz	1b
+	j	4f
+2:	l	%r15,.Lstack-.LPG0(%r13)
 	ahi	%r15,-96
 	la	%r2,.Lals_string-.LPG0(%r13)
 	l	%r3,.Lsclp_print-.LPG0(%r13)
 	basr	%r14,%r3
-	lpsw	2f-.LPG0(%r13)		# machine type not good enough, crash
+	lpsw	3f-.LPG0(%r13)		# machine type not good enough, crash
 .Lals_string:
 	.asciz	"The Linux kernel requires more recent processor hardware"
 .Lsclp_print:
@@ -424,33 +429,42 @@ ENTRY(startup_kdump)
 .Lstack:
 	.long	0x8000 + (1<<(PAGE_SHIFT+THREAD_ORDER))
 	.align 16
-2:	.long	0x000a0000,0x8badcccc
+3:	.long	0x000a0000,0x8badcccc
+
+# List of facilities that are required. If not all facilities are present
+# the kernel will crash. Format is number of facility words with bits set,
+# followed by the facility words.
+
 #if defined(CONFIG_64BIT)
-#if defined(CONFIG_MARCH_Z196)
-	.long 0xc100efe3, 0xf46c0000
+#if defined(CONFIG_MARCH_ZEC12)
+	.long 3, 0xc100efe3, 0xf46ce000, 0x00400000
+#elif defined(CONFIG_MARCH_Z196)
+	.long 2, 0xc100efe3, 0xf46c0000
 #elif defined(CONFIG_MARCH_Z10)
-	.long 0xc100efe3, 0xf0680000
+	.long 2, 0xc100efe3, 0xf0680000
 #elif defined(CONFIG_MARCH_Z9_109)
-	.long 0xc100efc3, 0x00000000
+	.long 1, 0xc100efc3
 #elif defined(CONFIG_MARCH_Z990)
-	.long 0xc0002000, 0x00000000
+	.long 1, 0xc0002000
 #elif defined(CONFIG_MARCH_Z900)
-	.long 0xc0000000, 0x00000000
+	.long 1, 0xc0000000
 #endif
 #else
-#if defined(CONFIG_MARCH_Z196)
-	.long 0x8100c880, 0x00000000
+#if defined(CONFIG_MARCH_ZEC12)
+	.long 1, 0x8100c880
+#elif defined(CONFIG_MARCH_Z196)
+	.long 1, 0x8100c880
 #elif defined(CONFIG_MARCH_Z10)
-	.long 0x8100c880, 0x00000000
+	.long 1, 0x8100c880
 #elif defined(CONFIG_MARCH_Z9_109)
-	.long 0x8100c880, 0x00000000
+	.long 1, 0x8100c880
 #elif defined(CONFIG_MARCH_Z990)
-	.long 0x80002000, 0x00000000
+	.long 1, 0x80002000
 #elif defined(CONFIG_MARCH_Z900)
-	.long 0x80000000, 0x00000000
+	.long 1, 0x80000000
 #endif
 #endif
-3:
+4:
 #endif
 
 #ifdef CONFIG_64BIT
@@ -459,14 +473,14 @@ ENTRY(startup_kdump)
 	jg	startup_continue
 #else
 	/* Continue with 31bit startup code in head31.S */
-	l	%r13,4f-.LPG0(%r13)
+	l	%r13,5f-.LPG0(%r13)
 	b	0(%r13)
 	.align	8
-4:	.long	startup_continue
+5:	.long	startup_continue
 #endif
 
 	.align	8
-5:	.long	0x7fffffff,0xffffffff
+6:	.long	0x7fffffff,0xffffffff
 
 #include "head_kdump.S"
 
diff --git a/arch/s390/kernel/pgm_check.S b/arch/s390/kernel/pgm_check.S
new file mode 100644
index 0000000..14bdecb
--- /dev/null
+++ b/arch/s390/kernel/pgm_check.S
@@ -0,0 +1,152 @@
+/*
+ *    Program check table.
+ *
+ *    Copyright IBM Corp. 2012
+ */
+
+#include <linux/linkage.h>
+
+#ifdef CONFIG_32BIT
+#define PGM_CHECK_64BIT(handler) .long default_trap_handler
+#else
+#define PGM_CHECK_64BIT(handler) .long handler
+#endif
+
+#define PGM_CHECK(handler)	.long handler
+#define PGM_CHECK_DEFAULT	PGM_CHECK(default_trap_handler)
+
+/*
+ * The program check table contains exactly 128 (0x00-0x7f) entries. Each
+ * line defines the 31 and/or 64 bit function to be called corresponding
+ * to the program check interruption code.
+ */
+.section .rodata, "a"
+ENTRY(pgm_check_table)
+PGM_CHECK_DEFAULT			/* 00 */
+PGM_CHECK(illegal_op)			/* 01 */
+PGM_CHECK(privileged_op)		/* 02 */
+PGM_CHECK(execute_exception)		/* 03 */
+PGM_CHECK(do_protection_exception)	/* 04 */
+PGM_CHECK(addressing_exception)		/* 05 */
+PGM_CHECK(specification_exception)	/* 06 */
+PGM_CHECK(data_exception)		/* 07 */
+PGM_CHECK(overflow_exception)		/* 08 */
+PGM_CHECK(divide_exception)		/* 09 */
+PGM_CHECK(overflow_exception)		/* 0a */
+PGM_CHECK(divide_exception)		/* 0b */
+PGM_CHECK(hfp_overflow_exception)	/* 0c */
+PGM_CHECK(hfp_underflow_exception)	/* 0d */
+PGM_CHECK(hfp_significance_exception)	/* 0e */
+PGM_CHECK(hfp_divide_exception)		/* 0f */
+PGM_CHECK(do_dat_exception)		/* 10 */
+PGM_CHECK(do_dat_exception)		/* 11 */
+PGM_CHECK(translation_exception)	/* 12 */
+PGM_CHECK(special_op_exception)		/* 13 */
+PGM_CHECK_DEFAULT			/* 14 */
+PGM_CHECK(operand_exception)		/* 15 */
+PGM_CHECK_DEFAULT			/* 16 */
+PGM_CHECK_DEFAULT			/* 17 */
+PGM_CHECK_64BIT(transaction_exception)	/* 18 */
+PGM_CHECK_DEFAULT			/* 19 */
+PGM_CHECK_DEFAULT			/* 1a */
+PGM_CHECK_DEFAULT			/* 1b */
+PGM_CHECK(space_switch_exception)	/* 1c */
+PGM_CHECK(hfp_sqrt_exception)		/* 1d */
+PGM_CHECK_DEFAULT			/* 1e */
+PGM_CHECK_DEFAULT			/* 1f */
+PGM_CHECK_DEFAULT			/* 20 */
+PGM_CHECK_DEFAULT			/* 21 */
+PGM_CHECK_DEFAULT			/* 22 */
+PGM_CHECK_DEFAULT			/* 23 */
+PGM_CHECK_DEFAULT			/* 24 */
+PGM_CHECK_DEFAULT			/* 25 */
+PGM_CHECK_DEFAULT			/* 26 */
+PGM_CHECK_DEFAULT			/* 27 */
+PGM_CHECK_DEFAULT			/* 28 */
+PGM_CHECK_DEFAULT			/* 29 */
+PGM_CHECK_DEFAULT			/* 2a */
+PGM_CHECK_DEFAULT			/* 2b */
+PGM_CHECK_DEFAULT			/* 2c */
+PGM_CHECK_DEFAULT			/* 2d */
+PGM_CHECK_DEFAULT			/* 2e */
+PGM_CHECK_DEFAULT			/* 2f */
+PGM_CHECK_DEFAULT			/* 30 */
+PGM_CHECK_DEFAULT			/* 31 */
+PGM_CHECK_DEFAULT			/* 32 */
+PGM_CHECK_DEFAULT			/* 33 */
+PGM_CHECK_DEFAULT			/* 34 */
+PGM_CHECK_DEFAULT			/* 35 */
+PGM_CHECK_DEFAULT			/* 36 */
+PGM_CHECK_DEFAULT			/* 37 */
+PGM_CHECK_64BIT(do_asce_exception)	/* 38 */
+PGM_CHECK_64BIT(do_dat_exception)	/* 39 */
+PGM_CHECK_64BIT(do_dat_exception)	/* 3a */
+PGM_CHECK_64BIT(do_dat_exception)	/* 3b */
+PGM_CHECK_DEFAULT			/* 3c */
+PGM_CHECK_DEFAULT			/* 3d */
+PGM_CHECK_DEFAULT			/* 3e */
+PGM_CHECK_DEFAULT			/* 3f */
+PGM_CHECK_DEFAULT			/* 40 */
+PGM_CHECK_DEFAULT			/* 41 */
+PGM_CHECK_DEFAULT			/* 42 */
+PGM_CHECK_DEFAULT			/* 43 */
+PGM_CHECK_DEFAULT			/* 44 */
+PGM_CHECK_DEFAULT			/* 45 */
+PGM_CHECK_DEFAULT			/* 46 */
+PGM_CHECK_DEFAULT			/* 47 */
+PGM_CHECK_DEFAULT			/* 48 */
+PGM_CHECK_DEFAULT			/* 49 */
+PGM_CHECK_DEFAULT			/* 4a */
+PGM_CHECK_DEFAULT			/* 4b */
+PGM_CHECK_DEFAULT			/* 4c */
+PGM_CHECK_DEFAULT			/* 4d */
+PGM_CHECK_DEFAULT			/* 4e */
+PGM_CHECK_DEFAULT			/* 4f */
+PGM_CHECK_DEFAULT			/* 50 */
+PGM_CHECK_DEFAULT			/* 51 */
+PGM_CHECK_DEFAULT			/* 52 */
+PGM_CHECK_DEFAULT			/* 53 */
+PGM_CHECK_DEFAULT			/* 54 */
+PGM_CHECK_DEFAULT			/* 55 */
+PGM_CHECK_DEFAULT			/* 56 */
+PGM_CHECK_DEFAULT			/* 57 */
+PGM_CHECK_DEFAULT			/* 58 */
+PGM_CHECK_DEFAULT			/* 59 */
+PGM_CHECK_DEFAULT			/* 5a */
+PGM_CHECK_DEFAULT			/* 5b */
+PGM_CHECK_DEFAULT			/* 5c */
+PGM_CHECK_DEFAULT			/* 5d */
+PGM_CHECK_DEFAULT			/* 5e */
+PGM_CHECK_DEFAULT			/* 5f */
+PGM_CHECK_DEFAULT			/* 60 */
+PGM_CHECK_DEFAULT			/* 61 */
+PGM_CHECK_DEFAULT			/* 62 */
+PGM_CHECK_DEFAULT			/* 63 */
+PGM_CHECK_DEFAULT			/* 64 */
+PGM_CHECK_DEFAULT			/* 65 */
+PGM_CHECK_DEFAULT			/* 66 */
+PGM_CHECK_DEFAULT			/* 67 */
+PGM_CHECK_DEFAULT			/* 68 */
+PGM_CHECK_DEFAULT			/* 69 */
+PGM_CHECK_DEFAULT			/* 6a */
+PGM_CHECK_DEFAULT			/* 6b */
+PGM_CHECK_DEFAULT			/* 6c */
+PGM_CHECK_DEFAULT			/* 6d */
+PGM_CHECK_DEFAULT			/* 6e */
+PGM_CHECK_DEFAULT			/* 6f */
+PGM_CHECK_DEFAULT			/* 70 */
+PGM_CHECK_DEFAULT			/* 71 */
+PGM_CHECK_DEFAULT			/* 72 */
+PGM_CHECK_DEFAULT			/* 73 */
+PGM_CHECK_DEFAULT			/* 74 */
+PGM_CHECK_DEFAULT			/* 75 */
+PGM_CHECK_DEFAULT			/* 76 */
+PGM_CHECK_DEFAULT			/* 77 */
+PGM_CHECK_DEFAULT			/* 78 */
+PGM_CHECK_DEFAULT			/* 79 */
+PGM_CHECK_DEFAULT			/* 7a */
+PGM_CHECK_DEFAULT			/* 7b */
+PGM_CHECK_DEFAULT			/* 7c */
+PGM_CHECK_DEFAULT			/* 7d */
+PGM_CHECK_DEFAULT			/* 7e */
+PGM_CHECK_DEFAULT			/* 7f */
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index cd31ad4..536d645 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -117,8 +117,7 @@ void release_thread(struct task_struct *dead_task)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
-		unsigned long arg,
-		struct task_struct *p, struct pt_regs *regs)
+		unsigned long arg, struct task_struct *p)
 {
 	struct thread_info *ti;
 	struct fake_frame
@@ -150,7 +149,7 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
 	frame->sf.gprs[9] = (unsigned long) frame;
 
 	/* Store access registers to kernel stack of new process. */
-	if (unlikely(!regs)) {
+	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 |
@@ -164,9 +163,10 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
 
 		return 0;
 	}
-	frame->childregs = *regs;
+	frame->childregs = *current_pt_regs();
 	frame->childregs.gprs[2] = 0;	/* child returns 0 on fork. */
-	frame->childregs.gprs[15] = new_stackp;
+	if (new_stackp)
+		frame->childregs.gprs[15] = new_stackp;
 
 	/* Don't copy runtime instrumentation info */
 	p->thread.ri_cb = NULL;
@@ -183,57 +183,24 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
 	       sizeof(s390_fp_regs));
 	/* Set a new TLS ?  */
 	if (clone_flags & CLONE_SETTLS)
-		p->thread.acrs[0] = regs->gprs[6];
+		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);
 	/* Set a new TLS ?  */
 	if (clone_flags & CLONE_SETTLS) {
+		unsigned long tls = frame->childregs.gprs[6];
 		if (is_compat_task()) {
-			p->thread.acrs[0] = (unsigned int) regs->gprs[6];
+			p->thread.acrs[0] = (unsigned int)tls;
 		} else {
-			p->thread.acrs[0] = (unsigned int)(regs->gprs[6] >> 32);
-			p->thread.acrs[1] = (unsigned int) regs->gprs[6];
+			p->thread.acrs[0] = (unsigned int)(tls >> 32);
+			p->thread.acrs[1] = (unsigned int)tls;
 		}
 	}
 #endif /* CONFIG_64BIT */
 	return 0;
 }
 
-SYSCALL_DEFINE0(fork)
-{
-	struct pt_regs *regs = task_pt_regs(current);
-	return do_fork(SIGCHLD, regs->gprs[15], regs, 0, NULL, NULL);
-}
-
-SYSCALL_DEFINE4(clone, unsigned long, newsp, unsigned long, clone_flags,
-		int __user *, parent_tidptr, int __user *, child_tidptr)
-{
-	struct pt_regs *regs = task_pt_regs(current);
-
-	if (!newsp)
-		newsp = regs->gprs[15];
-	return do_fork(clone_flags, newsp, regs, 0,
-		       parent_tidptr, child_tidptr);
-}
-
-/*
- * This is trivial, and on the face of it looks like it
- * could equally well be done in user mode.
- *
- * Not so, for quite unobvious reasons - register pressure.
- * In user mode vfork() cannot have a stack frame, and if
- * done by calling the "clone()" system call directly, you
- * do not have enough call-clobbered registers to hold all
- * the information you need.
- */
-SYSCALL_DEFINE0(vfork)
-{
-	struct pt_regs *regs = task_pt_regs(current);
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
-		       regs->gprs[15], regs, 0, NULL, NULL);
-}
-
 asmlinkage void execve_tail(void)
 {
 	current->thread.fp_regs.fpc = 0;
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index b1f2be9..2568590 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -777,40 +777,6 @@ static void __init reserve_crashkernel(void)
 #endif
 }
 
-static void __init init_storage_keys(unsigned long start, unsigned long end)
-{
-	unsigned long boundary, function, size;
-
-	while (start < end) {
-		if (MACHINE_HAS_EDAT2) {
-			/* set storage keys for a 2GB frame */
-			function = 0x22000 | PAGE_DEFAULT_KEY;
-			size = 1UL << 31;
-			boundary = (start + size) & ~(size - 1);
-			if (boundary <= end) {
-				do {
-					start = pfmf(function, start);
-				} while (start < boundary);
-				continue;
-			}
-		}
-		if (MACHINE_HAS_EDAT1) {
-			/* set storage keys for a 1MB frame */
-			function = 0x21000 | PAGE_DEFAULT_KEY;
-			size = 1UL << 20;
-			boundary = (start + size) & ~(size - 1);
-			if (boundary <= end) {
-				do {
-					start = pfmf(function, start);
-				} while (start < boundary);
-				continue;
-			}
-		}
-		page_set_storage_key(start, PAGE_DEFAULT_KEY, 0);
-		start += PAGE_SIZE;
-	}
-}
-
 static void __init setup_memory(void)
 {
         unsigned long bootmap_size;
@@ -889,7 +855,7 @@ static void __init setup_memory(void)
 		memblock_add_node(PFN_PHYS(start_chunk),
 				  PFN_PHYS(end_chunk - start_chunk), 0);
 		pfn = max(start_chunk, start_pfn);
-		init_storage_keys(PFN_PHYS(pfn), PFN_PHYS(end_chunk));
+		storage_key_init_range(PFN_PHYS(pfn), PFN_PHYS(end_chunk));
 	}
 
 	psw_set_key(PAGE_DEFAULT_KEY);
@@ -1040,6 +1006,9 @@ static void __init setup_hwcaps(void)
 	case 0x2818:
 		strcpy(elf_platform, "z196");
 		break;
+	case 0x2827:
+		strcpy(elf_platform, "zEC12");
+		break;
 	}
 }
 
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index d1259d8..c3ff70a 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -461,6 +461,8 @@ void do_signal(struct pt_regs *regs)
 			/* Restart system call with magic TIF bit. */
 			regs->gprs[2] = regs->orig_gpr2;
 			set_thread_flag(TIF_SYSCALL);
+			if (test_thread_flag(TIF_SINGLE_STEP))
+				set_thread_flag(TIF_PER_TRAP);
 			break;
 		}
 	}
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index dd55f7c..f1aba87 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -29,48 +29,38 @@ struct mask_info {
 	cpumask_t mask;
 };
 
-static int topology_enabled = 1;
+static void set_topology_timer(void);
 static void topology_work_fn(struct work_struct *work);
 static struct sysinfo_15_1_x *tl_info;
-static void set_topology_timer(void);
-static DECLARE_WORK(topology_work, topology_work_fn);
-/* topology_lock protects the core linked list */
-static DEFINE_SPINLOCK(topology_lock);
 
-static struct mask_info core_info;
-cpumask_t cpu_core_map[NR_CPUS];
-unsigned char cpu_core_id[NR_CPUS];
-unsigned char cpu_socket_id[NR_CPUS];
+static int topology_enabled = 1;
+static DECLARE_WORK(topology_work, topology_work_fn);
 
+/* topology_lock protects the socket and book linked lists */
+static DEFINE_SPINLOCK(topology_lock);
+static struct mask_info socket_info;
 static struct mask_info book_info;
-cpumask_t cpu_book_map[NR_CPUS];
-unsigned char cpu_book_id[NR_CPUS];
+
+struct cpu_topology_s390 cpu_topology[NR_CPUS];
 
 static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
 {
 	cpumask_t mask;
 
-	cpumask_clear(&mask);
-	if (!topology_enabled || !MACHINE_HAS_TOPOLOGY) {
-		cpumask_copy(&mask, cpumask_of(cpu));
+	cpumask_copy(&mask, cpumask_of(cpu));
+	if (!topology_enabled || !MACHINE_HAS_TOPOLOGY)
 		return mask;
+	for (; info; info = info->next) {
+		if (cpumask_test_cpu(cpu, &info->mask))
+			return info->mask;
 	}
-	while (info) {
-		if (cpumask_test_cpu(cpu, &info->mask)) {
-			mask = info->mask;
-			break;
-		}
-		info = info->next;
-	}
-	if (cpumask_empty(&mask))
-		cpumask_copy(&mask, cpumask_of(cpu));
 	return mask;
 }
 
 static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
 					  struct mask_info *book,
-					  struct mask_info *core,
-					  int one_core_per_cpu)
+					  struct mask_info *socket,
+					  int one_socket_per_cpu)
 {
 	unsigned int cpu;
 
@@ -80,28 +70,28 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
 
 		rcpu = TOPOLOGY_CPU_BITS - 1 - cpu + tl_cpu->origin;
 		lcpu = smp_find_processor_id(rcpu);
-		if (lcpu >= 0) {
-			cpumask_set_cpu(lcpu, &book->mask);
-			cpu_book_id[lcpu] = book->id;
-			cpumask_set_cpu(lcpu, &core->mask);
-			cpu_core_id[lcpu] = rcpu;
-			if (one_core_per_cpu) {
-				cpu_socket_id[lcpu] = rcpu;
-				core = core->next;
-			} else {
-				cpu_socket_id[lcpu] = core->id;
-			}
-			smp_cpu_set_polarization(lcpu, tl_cpu->pp);
+		if (lcpu < 0)
+			continue;
+		cpumask_set_cpu(lcpu, &book->mask);
+		cpu_topology[lcpu].book_id = book->id;
+		cpumask_set_cpu(lcpu, &socket->mask);
+		cpu_topology[lcpu].core_id = rcpu;
+		if (one_socket_per_cpu) {
+			cpu_topology[lcpu].socket_id = rcpu;
+			socket = socket->next;
+		} else {
+			cpu_topology[lcpu].socket_id = socket->id;
 		}
+		smp_cpu_set_polarization(lcpu, tl_cpu->pp);
 	}
-	return core;
+	return socket;
 }
 
 static void clear_masks(void)
 {
 	struct mask_info *info;
 
-	info = &core_info;
+	info = &socket_info;
 	while (info) {
 		cpumask_clear(&info->mask);
 		info = info->next;
@@ -120,9 +110,9 @@ static union topology_entry *next_tle(union topology_entry *tle)
 	return (union topology_entry *)((struct topology_container *)tle + 1);
 }
 
-static void __tl_to_cores_generic(struct sysinfo_15_1_x *info)
+static void __tl_to_masks_generic(struct sysinfo_15_1_x *info)
 {
-	struct mask_info *core = &core_info;
+	struct mask_info *socket = &socket_info;
 	struct mask_info *book = &book_info;
 	union topology_entry *tle, *end;
 
@@ -135,11 +125,11 @@ static void __tl_to_cores_generic(struct sysinfo_15_1_x *info)
 			book->id = tle->container.id;
 			break;
 		case 1:
-			core = core->next;
-			core->id = tle->container.id;
+			socket = socket->next;
+			socket->id = tle->container.id;
 			break;
 		case 0:
-			add_cpus_to_mask(&tle->cpu, book, core, 0);
+			add_cpus_to_mask(&tle->cpu, book, socket, 0);
 			break;
 		default:
 			clear_masks();
@@ -149,9 +139,9 @@ static void __tl_to_cores_generic(struct sysinfo_15_1_x *info)
 	}
 }
 
-static void __tl_to_cores_z10(struct sysinfo_15_1_x *info)
+static void __tl_to_masks_z10(struct sysinfo_15_1_x *info)
 {
-	struct mask_info *core = &core_info;
+	struct mask_info *socket = &socket_info;
 	struct mask_info *book = &book_info;
 	union topology_entry *tle, *end;
 
@@ -164,7 +154,7 @@ static void __tl_to_cores_z10(struct sysinfo_15_1_x *info)
 			book->id = tle->container.id;
 			break;
 		case 0:
-			core = add_cpus_to_mask(&tle->cpu, book, core, 1);
+			socket = add_cpus_to_mask(&tle->cpu, book, socket, 1);
 			break;
 		default:
 			clear_masks();
@@ -174,20 +164,20 @@ static void __tl_to_cores_z10(struct sysinfo_15_1_x *info)
 	}
 }
 
-static void tl_to_cores(struct sysinfo_15_1_x *info)
+static void tl_to_masks(struct sysinfo_15_1_x *info)
 {
 	struct cpuid cpu_id;
 
-	get_cpu_id(&cpu_id);
 	spin_lock_irq(&topology_lock);
+	get_cpu_id(&cpu_id);
 	clear_masks();
 	switch (cpu_id.machine) {
 	case 0x2097:
 	case 0x2098:
-		__tl_to_cores_z10(info);
+		__tl_to_masks_z10(info);
 		break;
 	default:
-		__tl_to_cores_generic(info);
+		__tl_to_masks_generic(info);
 	}
 	spin_unlock_irq(&topology_lock);
 }
@@ -232,15 +222,20 @@ int topology_set_cpu_management(int fc)
 	return rc;
 }
 
-static void update_cpu_core_map(void)
+static void update_cpu_masks(void)
 {
 	unsigned long flags;
 	int cpu;
 
 	spin_lock_irqsave(&topology_lock, flags);
 	for_each_possible_cpu(cpu) {
-		cpu_core_map[cpu] = cpu_group_map(&core_info, cpu);
-		cpu_book_map[cpu] = cpu_group_map(&book_info, cpu);
+		cpu_topology[cpu].core_mask = cpu_group_map(&socket_info, cpu);
+		cpu_topology[cpu].book_mask = cpu_group_map(&book_info, cpu);
+		if (!MACHINE_HAS_TOPOLOGY) {
+			cpu_topology[cpu].core_id = cpu;
+			cpu_topology[cpu].socket_id = cpu;
+			cpu_topology[cpu].book_id = cpu;
+		}
 	}
 	spin_unlock_irqrestore(&topology_lock, flags);
 }
@@ -260,13 +255,13 @@ int arch_update_cpu_topology(void)
 	int cpu;
 
 	if (!MACHINE_HAS_TOPOLOGY) {
-		update_cpu_core_map();
+		update_cpu_masks();
 		topology_update_polarization_simple();
 		return 0;
 	}
 	store_topology(info);
-	tl_to_cores(info);
-	update_cpu_core_map();
+	tl_to_masks(info);
+	update_cpu_masks();
 	for_each_online_cpu(cpu) {
 		dev = get_cpu_device(cpu);
 		kobject_uevent(&dev->kobj, KOBJ_CHANGE);
@@ -355,7 +350,7 @@ void __init s390_init_cpu_topology(void)
 	for (i = 0; i < TOPOLOGY_NR_MAG; i++)
 		printk(KERN_CONT " %d", info->mag[i]);
 	printk(KERN_CONT " / %d\n", info->mnest);
-	alloc_masks(info, &core_info, 1);
+	alloc_masks(info, &socket_info, 1);
 	alloc_masks(info, &book_info, 2);
 }
 
@@ -454,7 +449,7 @@ static int __init topology_init(void)
 	}
 	set_topology_timer();
 out:
-	update_cpu_core_map();
+	update_cpu_masks();
 	return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching);
 }
 device_initcall(topology_init);
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 3d2b0fa..70ecfc5 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -41,8 +41,6 @@
 #include <asm/ipl.h>
 #include "entry.h"
 
-void (*pgm_check_table[128])(struct pt_regs *regs);
-
 int show_unhandled_signals = 1;
 
 #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
@@ -350,7 +348,7 @@ void __kprobes do_per_trap(struct pt_regs *regs)
 	force_sig_info(SIGTRAP, &info, current);
 }
 
-static void default_trap_handler(struct pt_regs *regs)
+void default_trap_handler(struct pt_regs *regs)
 {
 	if (user_mode(regs)) {
 		report_user_fault(regs, SIGSEGV);
@@ -360,9 +358,9 @@ static void default_trap_handler(struct pt_regs *regs)
 }
 
 #define DO_ERROR_INFO(name, signr, sicode, str) \
-static void name(struct pt_regs *regs) \
-{ \
-	do_trap(regs, signr, sicode, str); \
+void name(struct pt_regs *regs)			\
+{						\
+	do_trap(regs, signr, sicode, str);	\
 }
 
 DO_ERROR_INFO(addressing_exception, SIGILL, ILL_ILLADR,
@@ -417,7 +415,7 @@ static inline void do_fp_trap(struct pt_regs *regs, int fpc)
 	do_trap(regs, SIGFPE, si_code, "floating point exception");
 }
 
-static void __kprobes illegal_op(struct pt_regs *regs)
+void __kprobes illegal_op(struct pt_regs *regs)
 {
 	siginfo_t info;
         __u8 opcode[6];
@@ -536,7 +534,7 @@ DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN,
 	      "specification exception");
 #endif
 
-static void data_exception(struct pt_regs *regs)
+void data_exception(struct pt_regs *regs)
 {
 	__u16 __user *location;
 	int signal = 0;
@@ -611,7 +609,7 @@ static void data_exception(struct pt_regs *regs)
 		do_trap(regs, signal, ILL_ILLOPN, "data exception");
 }
 
-static void space_switch_exception(struct pt_regs *regs)
+void space_switch_exception(struct pt_regs *regs)
 {
 	/* Set user psw back to home space mode. */
 	if (user_mode(regs))
@@ -629,43 +627,7 @@ void __kprobes kernel_stack_overflow(struct pt_regs * regs)
 	panic("Corrupt kernel stack, can't continue.");
 }
 
-/* init is done in lowcore.S and head.S */
-
 void __init trap_init(void)
 {
-        int i;
-
-        for (i = 0; i < 128; i++)
-          pgm_check_table[i] = &default_trap_handler;
-        pgm_check_table[1] = &illegal_op;
-        pgm_check_table[2] = &privileged_op;
-        pgm_check_table[3] = &execute_exception;
-        pgm_check_table[4] = &do_protection_exception;
-        pgm_check_table[5] = &addressing_exception;
-        pgm_check_table[6] = &specification_exception;
-        pgm_check_table[7] = &data_exception;
-        pgm_check_table[8] = &overflow_exception;
-        pgm_check_table[9] = &divide_exception;
-        pgm_check_table[0x0A] = &overflow_exception;
-        pgm_check_table[0x0B] = &divide_exception;
-        pgm_check_table[0x0C] = &hfp_overflow_exception;
-        pgm_check_table[0x0D] = &hfp_underflow_exception;
-        pgm_check_table[0x0E] = &hfp_significance_exception;
-        pgm_check_table[0x0F] = &hfp_divide_exception;
-        pgm_check_table[0x10] = &do_dat_exception;
-        pgm_check_table[0x11] = &do_dat_exception;
-        pgm_check_table[0x12] = &translation_exception;
-        pgm_check_table[0x13] = &special_op_exception;
-#ifdef CONFIG_64BIT
-	pgm_check_table[0x18] = &transaction_exception;
-	pgm_check_table[0x38] = &do_asce_exception;
-	pgm_check_table[0x39] = &do_dat_exception;
-	pgm_check_table[0x3A] = &do_dat_exception;
-        pgm_check_table[0x3B] = &do_dat_exception;
-#endif /* CONFIG_64BIT */
-        pgm_check_table[0x15] = &operand_exception;
-        pgm_check_table[0x1C] = &space_switch_exception;
-        pgm_check_table[0x1D] = &hfp_sqrt_exception;
-	/* Enable machine checks early. */
 	local_mcck_enable();
 }
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 7903344..783e988 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -140,6 +140,10 @@ void vtime_account(struct task_struct *tsk)
 }
 EXPORT_SYMBOL_GPL(vtime_account);
 
+void __vtime_account_system(struct task_struct *tsk)
+__attribute__((alias("vtime_account")));
+EXPORT_SYMBOL_GPL(__vtime_account_system);
+
 void __kprobes vtime_stop_cpu(void)
 {
 	struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
index b58dd86..60f9f8a 100644
--- a/arch/s390/kvm/Kconfig
+++ b/arch/s390/kvm/Kconfig
@@ -18,7 +18,7 @@ if VIRTUALIZATION
 config KVM
 	def_tristate y
 	prompt "Kernel-based Virtual Machine (KVM) support"
-	depends on HAVE_KVM && EXPERIMENTAL
+	depends on HAVE_KVM
 	select PREEMPT_NOTIFIERS
 	select ANON_INODES
 	select HAVE_KVM_CPU_RELAX_INTERCEPT
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index ff1e2f8..c30615e 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -629,10 +629,27 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
 		break;
 	case KVM_S390_SIGP_STOP:
 	case KVM_S390_RESTART:
+		VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
+		inti->type = s390int->type;
+		break;
 	case KVM_S390_INT_EXTERNAL_CALL:
+		if (s390int->parm & 0xffff0000) {
+			kfree(inti);
+			return -EINVAL;
+		}
+		VCPU_EVENT(vcpu, 3, "inject: external call source-cpu:%u",
+			   s390int->parm);
+		inti->type = s390int->type;
+		inti->extcall.code = s390int->parm;
+		break;
 	case KVM_S390_INT_EMERGENCY:
-		VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
+		if (s390int->parm & 0xffff0000) {
+			kfree(inti);
+			return -EINVAL;
+		}
+		VCPU_EVENT(vcpu, 3, "inject: emergency %u\n", s390int->parm);
 		inti->type = s390int->type;
+		inti->emerg.code = s390int->parm;
 		break;
 	case KVM_S390_INT_VIRTIO:
 	case KVM_S390_INT_SERVICE:
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index ecced9d..0c5e934 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -608,9 +608,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
 		kvm_s390_deliver_pending_interrupts(vcpu);
 
 	vcpu->arch.sie_block->icptcode = 0;
-	local_irq_disable();
 	kvm_guest_enter();
-	local_irq_enable();
 	VCPU_EVENT(vcpu, 6, "entering sie flags %x",
 		   atomic_read(&vcpu->arch.sie_block->cpuflags));
 	trace_kvm_s390_sie_enter(vcpu,
@@ -629,9 +627,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
 	VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
 		   vcpu->arch.sie_block->icptcode);
 	trace_kvm_s390_sie_exit(vcpu, vcpu->arch.sie_block->icptcode);
-	local_irq_disable();
 	kvm_guest_exit();
-	local_irq_enable();
 
 	memcpy(&vcpu->run->s.regs.gprs[14], &vcpu->arch.sie_block->gg14, 16);
 	return rc;
@@ -997,7 +993,7 @@ static int __init kvm_s390_init(void)
 	}
 	memcpy(facilities, S390_lowcore.stfle_fac_list, 16);
 	facilities[0] &= 0xff00fff3f47c0000ULL;
-	facilities[1] &= 0x201c000000000000ULL;
+	facilities[1] &= 0x001c000000000000ULL;
 	return 0;
 }
 
diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile
index 1bea6d1..640bea1 100644
--- a/arch/s390/mm/Makefile
+++ b/arch/s390/mm/Makefile
@@ -2,9 +2,9 @@
 # Makefile for the linux s390-specific parts of the memory manager.
 #
 
-obj-y	 := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o \
-	    page-states.o gup.o extable.o
-obj-$(CONFIG_CMM) += cmm.o
-obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
-obj-$(CONFIG_DEBUG_SET_MODULE_RONX) += pageattr.o
-obj-$(CONFIG_S390_PTDUMP) += dump_pagetables.o
+obj-y		:= init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o
+obj-y		+= page-states.o gup.o extable.o pageattr.o
+
+obj-$(CONFIG_CMM)		+= cmm.o
+obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
+obj-$(CONFIG_S390_PTDUMP)	+= dump_pagetables.o
diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c
index cbc6668..04e4892 100644
--- a/arch/s390/mm/dump_pagetables.c
+++ b/arch/s390/mm/dump_pagetables.c
@@ -150,6 +150,7 @@ static void walk_pmd_level(struct seq_file *m, struct pg_state *st,
 static void walk_pud_level(struct seq_file *m, struct pg_state *st,
 			   pgd_t *pgd, unsigned long addr)
 {
+	unsigned int prot;
 	pud_t *pud;
 	int i;
 
@@ -157,7 +158,11 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st,
 		st->current_address = addr;
 		pud = pud_offset(pgd, addr);
 		if (!pud_none(*pud))
-			walk_pmd_level(m, st, pud, addr);
+			if (pud_large(*pud)) {
+				prot = pud_val(*pud) & _PAGE_RO;
+				note_page(m, st, prot, 2);
+			} else
+				walk_pmd_level(m, st, pud, addr);
 		else
 			note_page(m, st, _PAGE_INVALID, 2);
 		addr += PUD_SIZE;
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 04ad400..42601d6 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -49,15 +49,19 @@
 #define VM_FAULT_BADCONTEXT	0x010000
 #define VM_FAULT_BADMAP		0x020000
 #define VM_FAULT_BADACCESS	0x040000
-#define VM_FAULT_SIGNAL	0x080000
+#define VM_FAULT_SIGNAL		0x080000
 
-static unsigned long store_indication;
+static unsigned long store_indication __read_mostly;
 
-void fault_init(void)
+#ifdef CONFIG_64BIT
+static int __init fault_init(void)
 {
-	if (test_facility(2) && test_facility(75))
+	if (test_facility(75))
 		store_indication = 0xc00;
+	return 0;
 }
+early_initcall(fault_init);
+#endif
 
 static inline int notify_page_fault(struct pt_regs *regs)
 {
@@ -273,10 +277,16 @@ static inline int do_exception(struct pt_regs *regs, int access)
 	unsigned int flags;
 	int fault;
 
+	tsk = current;
+	/*
+	 * The instruction that caused the program check has
+	 * been nullified. Don't signal single step via SIGTRAP.
+	 */
+	clear_tsk_thread_flag(tsk, TIF_PER_TRAP);
+
 	if (notify_page_fault(regs))
 		return 0;
 
-	tsk = current;
 	mm = tsk->mm;
 	trans_exc_code = regs->int_parm_long;
 
@@ -372,11 +382,6 @@ retry:
 			goto retry;
 		}
 	}
-	/*
-	 * The instruction that caused the program check will
-	 * be repeated. Don't signal single step via SIGTRAP.
-	 */
-	clear_tsk_thread_flag(tsk, TIF_PER_TRAP);
 	fault = 0;
 out_up:
 	up_read(&mm->mmap_sem);
@@ -423,6 +428,12 @@ void __kprobes do_asce_exception(struct pt_regs *regs)
 	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;
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 81e596c..ae672f4 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -125,7 +125,6 @@ void __init paging_init(void)
 	max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS);
 	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
 	free_area_init_nodes(max_zone_pfns);
-	fault_init();
 }
 
 void __init mem_init(void)
@@ -159,34 +158,6 @@ void __init mem_init(void)
 	       PFN_ALIGN((unsigned long)&_eshared) - 1);
 }
 
-#ifdef CONFIG_DEBUG_PAGEALLOC
-void kernel_map_pages(struct page *page, int numpages, int enable)
-{
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *pte;
-	unsigned long address;
-	int i;
-
-	for (i = 0; i < numpages; i++) {
-		address = page_to_phys(page + i);
-		pgd = pgd_offset_k(address);
-		pud = pud_offset(pgd, address);
-		pmd = pmd_offset(pud, address);
-		pte = pte_offset_kernel(pmd, address);
-		if (!enable) {
-			__ptep_ipte(address, pte);
-			pte_val(*pte) = _PAGE_TYPE_EMPTY;
-			continue;
-		}
-		*pte = mk_pte_phys(address, __pgprot(_PAGE_TYPE_RW));
-		/* Flush cpu write queue. */
-		mb();
-	}
-}
-#endif
-
 void free_init_pages(char *what, unsigned long begin, unsigned long end)
 {
 	unsigned long addr = begin;
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
index 00be01c..29ccee3 100644
--- a/arch/s390/mm/pageattr.c
+++ b/arch/s390/mm/pageattr.c
@@ -2,11 +2,46 @@
  * Copyright IBM Corp. 2011
  * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
  */
+#include <linux/hugetlb.h>
 #include <linux/module.h>
 #include <linux/mm.h>
-#include <linux/hugetlb.h>
 #include <asm/cacheflush.h>
 #include <asm/pgtable.h>
+#include <asm/page.h>
+
+void storage_key_init_range(unsigned long start, unsigned long end)
+{
+	unsigned long boundary, function, size;
+
+	while (start < end) {
+		if (MACHINE_HAS_EDAT2) {
+			/* set storage keys for a 2GB frame */
+			function = 0x22000 | PAGE_DEFAULT_KEY;
+			size = 1UL << 31;
+			boundary = (start + size) & ~(size - 1);
+			if (boundary <= end) {
+				do {
+					start = pfmf(function, start);
+				} while (start < boundary);
+				continue;
+			}
+		}
+		if (MACHINE_HAS_EDAT1) {
+			/* set storage keys for a 1MB frame */
+			function = 0x21000 | PAGE_DEFAULT_KEY;
+			size = 1UL << 20;
+			boundary = (start + size) & ~(size - 1);
+			if (boundary <= end) {
+				do {
+					start = pfmf(function, start);
+				} while (start < boundary);
+				continue;
+			}
+		}
+		page_set_storage_key(start, PAGE_DEFAULT_KEY, 0);
+		start += PAGE_SIZE;
+	}
+}
 
 static pte_t *walk_page_table(unsigned long addr)
 {
@@ -19,7 +54,7 @@ static pte_t *walk_page_table(unsigned long addr)
 	if (pgd_none(*pgdp))
 		return NULL;
 	pudp = pud_offset(pgdp, addr);
-	if (pud_none(*pudp))
+	if (pud_none(*pudp) || pud_large(*pudp))
 		return NULL;
 	pmdp = pmd_offset(pudp, addr);
 	if (pmd_none(*pmdp) || pmd_large(*pmdp))
@@ -70,3 +105,46 @@ int set_memory_x(unsigned long addr, int numpages)
 {
 	return 0;
 }
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+void kernel_map_pages(struct page *page, int numpages, int enable)
+{
+	unsigned long address;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+	int i;
+
+	for (i = 0; i < numpages; i++) {
+		address = page_to_phys(page + i);
+		pgd = pgd_offset_k(address);
+		pud = pud_offset(pgd, address);
+		pmd = pmd_offset(pud, address);
+		pte = pte_offset_kernel(pmd, address);
+		if (!enable) {
+			__ptep_ipte(address, pte);
+			pte_val(*pte) = _PAGE_TYPE_EMPTY;
+			continue;
+		}
+		*pte = mk_pte_phys(address, __pgprot(_PAGE_TYPE_RW));
+	}
+}
+
+#ifdef CONFIG_HIBERNATION
+bool kernel_page_present(struct page *page)
+{
+	unsigned long addr;
+	int cc;
+
+	addr = page_to_phys(page);
+	asm volatile(
+		"	lra	%1,0(%1)\n"
+		"	ipm	%0\n"
+		"	srl	%0,28"
+		: "=d" (cc), "+a" (addr) : : "cc");
+	return cc == 0;
+}
+#endif /* CONFIG_HIBERNATION */
+
+#endif /* CONFIG_DEBUG_PAGEALLOC */
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index c8188a1..ae44d2a 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -881,22 +881,6 @@ int s390_enable_sie(void)
 }
 EXPORT_SYMBOL_GPL(s390_enable_sie);
 
-#if defined(CONFIG_DEBUG_PAGEALLOC) && defined(CONFIG_HIBERNATION)
-bool kernel_page_present(struct page *page)
-{
-	unsigned long addr;
-	int cc;
-
-	addr = page_to_phys(page);
-	asm volatile(
-		"	lra	%1,0(%1)\n"
-		"	ipm	%0\n"
-		"	srl	%0,28"
-		: "=d" (cc), "+a" (addr) : : "cc");
-	return cc == 0;
-}
-#endif /* CONFIG_HIBERNATION && CONFIG_DEBUG_PAGEALLOC */
-
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 int pmdp_clear_flush_young(struct vm_area_struct *vma, unsigned long address,
 			   pmd_t *pmdp)
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 387c7c6..6ed1426 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -89,6 +89,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
 	int ret = -ENOMEM;
 
 	while (address < end) {
+		pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0));
 		pg_dir = pgd_offset_k(address);
 		if (pgd_none(*pg_dir)) {
 			pu_dir = vmem_pud_alloc();
@@ -96,18 +97,24 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
 				goto out;
 			pgd_populate(&init_mm, pg_dir, pu_dir);
 		}
-
 		pu_dir = pud_offset(pg_dir, address);
+#if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC)
+		if (MACHINE_HAS_EDAT2 && pud_none(*pu_dir) && address &&
+		    !(address & ~PUD_MASK) && (address + PUD_SIZE <= end)) {
+			pte_val(pte) |= _REGION3_ENTRY_LARGE;
+			pte_val(pte) |= _REGION_ENTRY_TYPE_R3;
+			pud_val(*pu_dir) = pte_val(pte);
+			address += PUD_SIZE;
+			continue;
+		}
+#endif
 		if (pud_none(*pu_dir)) {
 			pm_dir = vmem_pmd_alloc();
 			if (!pm_dir)
 				goto out;
 			pud_populate(&init_mm, pu_dir, pm_dir);
 		}
-
-		pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0));
 		pm_dir = pmd_offset(pu_dir, address);
-
 #if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC)
 		if (MACHINE_HAS_EDAT1 && pmd_none(*pm_dir) && address &&
 		    !(address & ~PMD_MASK) && (address + PMD_SIZE <= end)) {
@@ -160,6 +167,11 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
 			address += PUD_SIZE;
 			continue;
 		}
+		if (pud_large(*pu_dir)) {
+			pud_clear(pu_dir);
+			address += PUD_SIZE;
+			continue;
+		}
 		pm_dir = pmd_offset(pu_dir, address);
 		if (pmd_none(*pm_dir)) {
 			address += PMD_SIZE;
@@ -193,7 +205,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
 	start_addr = (unsigned long) start;
 	end_addr = (unsigned long) (start + nr);
 
-	for (address = start_addr; address < end_addr; address += PAGE_SIZE) {
+	for (address = start_addr; address < end_addr;) {
 		pg_dir = pgd_offset_k(address);
 		if (pgd_none(*pg_dir)) {
 			pu_dir = vmem_pud_alloc();
@@ -212,10 +224,33 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
 
 		pm_dir = pmd_offset(pu_dir, address);
 		if (pmd_none(*pm_dir)) {
+#ifdef CONFIG_64BIT
+			/* Use 1MB frames for vmemmap if available. We always
+			 * use large frames even if they are only partially
+			 * used.
+			 * Otherwise we would have also page tables since
+			 * vmemmap_populate gets called for each section
+			 * separately. */
+			if (MACHINE_HAS_EDAT1) {
+				void *new_page;
+
+				new_page = vmemmap_alloc_block(PMD_SIZE, node);
+				if (!new_page)
+					goto out;
+				pte = mk_pte_phys(__pa(new_page), PAGE_RW);
+				pte_val(pte) |= _SEGMENT_ENTRY_LARGE;
+				pmd_val(*pm_dir) = pte_val(pte);
+				address = (address + PMD_SIZE) & PMD_MASK;
+				continue;
+			}
+#endif
 			pt_dir = vmem_pte_alloc(address);
 			if (!pt_dir)
 				goto out;
 			pmd_populate(&init_mm, pm_dir, pt_dir);
+		} else if (pmd_large(*pm_dir)) {
+			address = (address + PMD_SIZE) & PMD_MASK;
+			continue;
 		}
 
 		pt_dir = pte_offset_kernel(pm_dir, address);
@@ -228,6 +263,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
 			pte = pfn_pte(new_page >> PAGE_SHIFT, PAGE_KERNEL);
 			*pt_dir = pte;
 		}
+		address += PAGE_SIZE;
 	}
 	memset(start, 0, nr * sizeof(struct page));
 	ret = 0;
diff --git a/arch/score/Kconfig b/arch/score/Kconfig
index 4f93a43..4589339 100644
--- a/arch/score/Kconfig
+++ b/arch/score/Kconfig
@@ -13,6 +13,9 @@ config SCORE
        select GENERIC_CLOCKEVENTS
        select HAVE_MOD_ARCH_SPECIFIC
 	select MODULES_USE_ELF_REL
+	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
+	select CLONE_BACKWARDS
 
 choice
 	prompt "System type"
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index ec697ae..16e41fe 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -3,3 +3,4 @@ include include/asm-generic/Kbuild.asm
 header-y +=
 
 generic-y += clkdev.h
+generic-y += trace_clock.h
diff --git a/arch/score/include/asm/processor.h b/arch/score/include/asm/processor.h
index ab3aceb..d9a922d 100644
--- a/arch/score/include/asm/processor.h
+++ b/arch/score/include/asm/processor.h
@@ -13,7 +13,6 @@ struct task_struct;
  */
 extern void (*cpu_wait)(void);
 
-extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
 extern unsigned long thread_saved_pc(struct task_struct *tsk);
 extern void start_thread(struct pt_regs *regs,
 			unsigned long pc, unsigned long sp);
diff --git a/arch/score/include/asm/syscalls.h b/arch/score/include/asm/syscalls.h
index 1dd5e0d..8d33253 100644
--- a/arch/score/include/asm/syscalls.h
+++ b/arch/score/include/asm/syscalls.h
@@ -2,7 +2,6 @@
 #define _ASM_SCORE_SYSCALLS_H
 
 asmlinkage long score_clone(struct pt_regs *regs);
-asmlinkage long score_execve(struct pt_regs *regs);
 asmlinkage long score_sigaltstack(struct pt_regs *regs);
 asmlinkage long score_rt_sigreturn(struct pt_regs *regs);
 
diff --git a/arch/score/include/asm/unistd.h b/arch/score/include/asm/unistd.h
index a862384..56001c9 100644
--- a/arch/score/include/asm/unistd.h
+++ b/arch/score/include/asm/unistd.h
@@ -4,5 +4,9 @@
 #define __ARCH_WANT_SYSCALL_NO_FLAGS
 #define __ARCH_WANT_SYSCALL_OFF_T
 #define __ARCH_WANT_SYSCALL_DEPRECATED
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_VFORK
 
 #include <asm-generic/unistd.h>
diff --git a/arch/score/kernel/entry.S b/arch/score/kernel/entry.S
index 83bb960..1557ca1 100644
--- a/arch/score/kernel/entry.S
+++ b/arch/score/kernel/entry.S
@@ -278,6 +278,13 @@ need_resched:
 	nop
 #endif
 
+ENTRY(ret_from_kernel_thread)
+	bl	schedule_tail			# r4=struct task_struct *prev
+	nop
+	mv	r4, r13
+	brl	r12
+	j	syscall_exit
+
 ENTRY(ret_from_fork)
 	bl	schedule_tail			# r4=struct task_struct *prev
 
@@ -480,16 +487,6 @@ illegal_syscall:
 	sw	r9, [r0, PT_R7]
 	j	syscall_return
 
-ENTRY(sys_execve)
-	mv	r4, r0
-	la	r8, score_execve
-	br	r8
-
-ENTRY(sys_clone)
-	mv	r4, r0
-	la	r8, score_clone
-	br	r8
-
 ENTRY(sys_rt_sigreturn)
 	mv	r4, r0
 	la	r8, score_rt_sigreturn
@@ -499,16 +496,3 @@ ENTRY(sys_sigaltstack)
 	mv	r4, r0
 	la	r8, score_sigaltstack
 	br	r8
-
-#ifdef __ARCH_WANT_SYSCALL_DEPRECATED
-ENTRY(sys_fork)
-	mv	r4, r0
-	la	r8, score_fork
-	br	r8
-
-ENTRY(sys_vfork)
-	mv	r4, r0
-	la	r8, score_vfork
-	br	r8
-#endif /* __ARCH_WANT_SYSCALL_DEPRECATED */
-
diff --git a/arch/score/kernel/process.c b/arch/score/kernel/process.c
index 637970c..7956846 100644
--- a/arch/score/kernel/process.c
+++ b/arch/score/kernel/process.c
@@ -60,6 +60,7 @@ void __noreturn cpu_idle(void)
 }
 
 void ret_from_fork(void);
+void ret_from_kernel_thread(void);
 
 void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
 {
@@ -86,29 +87,27 @@ void flush_thread(void) {}
  * set up the kernel stack and exception frames for a new process
  */
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-		unsigned long unused,
-		struct task_struct *p, struct pt_regs *regs)
+		unsigned long arg, struct task_struct *p)
 {
 	struct thread_info *ti = task_thread_info(p);
 	struct pt_regs *childregs = task_pt_regs(p);
+	struct pt_regs *regs = current_pt_regs();
 
-	p->set_child_tid = NULL;
-	p->clear_child_tid = NULL;
-
-	*childregs = *regs;
-	childregs->regs[7] = 0;		/* Clear error flag */
-	childregs->regs[4] = 0;		/* Child gets zero as return value */
-	regs->regs[4] = p->pid;
-
-	if (childregs->cp0_psr & 0x8) {	/* test kernel fork or user fork */
-		childregs->regs[0] = usp;		/* user fork */
+	p->thread.reg0 = (unsigned long) childregs;
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		memset(childregs, 0, sizeof(struct pt_regs));
+		p->thread->reg12 = usp;
+		p->thread->reg13 = arg;
+		p->thread.reg3 = (unsigned long) ret_from_kernel_thread;
 	} else {
-		childregs->regs[28] = (unsigned long) ti; /* kernel fork */
-		childregs->regs[0] = (unsigned long) childregs;
+		*childregs = *current_pt_regs();
+		childregs->regs[7] = 0;		/* Clear error flag */
+		childregs->regs[4] = 0;		/* Child gets zero as return value */
+		if (usp)
+			childregs->regs[0] = usp;	/* user fork */
+		p->thread.reg3 = (unsigned long) ret_from_fork;
 	}
 
-	p->thread.reg0 = (unsigned long) childregs;
-	p->thread.reg3 = (unsigned long) ret_from_fork;
 	p->thread.cp0_psr = 0;
 
 	return 0;
@@ -120,32 +119,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
 	return 1;
 }
 
-static void __noreturn
-kernel_thread_helper(void *unused0, int (*fn)(void *),
-		 void *arg, void *unused1)
-{
-	do_exit(fn(arg));
-}
-
-/*
- * Create a kernel thread.
- */
-long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-
-	regs.regs[6] = (unsigned long) arg;
-	regs.regs[5] = (unsigned long) fn;
-	regs.cp0_epc = (unsigned long) kernel_thread_helper;
-	regs.cp0_psr = (regs.cp0_psr & ~(0x1|0x4|0x8)) | \
-			((regs.cp0_psr & 0x3) << 2);
-
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, \
-			0, &regs, 0, NULL, NULL);
-}
-
 unsigned long thread_saved_pc(struct task_struct *tsk)
 {
 	return task_pt_regs(tsk)->cp0_epc;
diff --git a/arch/score/kernel/sys_score.c b/arch/score/kernel/sys_score.c
index d45cf00..47c20ba 100644
--- a/arch/score/kernel/sys_score.c
+++ b/arch/score/kernel/sys_score.c
@@ -48,92 +48,3 @@ sys_mmap(unsigned long addr, unsigned long len, unsigned long prot,
 		return -EINVAL;
 	return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
 }
-
-asmlinkage long
-score_fork(struct pt_regs *regs)
-{
-	return do_fork(SIGCHLD, regs->regs[0], regs, 0, NULL, NULL);
-}
-
-/*
- * Clone a task - this clones the calling program thread.
- * This is called indirectly via a small wrapper
- */
-asmlinkage long
-score_clone(struct pt_regs *regs)
-{
-	unsigned long clone_flags;
-	unsigned long newsp;
-	int __user *parent_tidptr, *child_tidptr;
-
-	clone_flags = regs->regs[4];
-	newsp = regs->regs[5];
-	if (!newsp)
-		newsp = regs->regs[0];
-	parent_tidptr = (int __user *)regs->regs[6];
-	child_tidptr = (int __user *)regs->regs[8];
-
-	return do_fork(clone_flags, newsp, regs, 0,
-			parent_tidptr, child_tidptr);
-}
-
-asmlinkage long
-score_vfork(struct pt_regs *regs)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
-			regs->regs[0], regs, 0, NULL, NULL);
-}
-
-/*
- * sys_execve() executes a new program.
- * This is called indirectly via a small wrapper
- */
-asmlinkage long
-score_execve(struct pt_regs *regs)
-{
-	int error;
-	struct filename *filename;
-
-	filename = getname((char __user*)regs->regs[4]);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		return error;
-
-	error = do_execve(filename->name,
-			  (const char __user *const __user *)regs->regs[5],
-			  (const char __user *const __user *)regs->regs[6],
-			  regs);
-
-	putname(filename);
-	return error;
-}
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-asmlinkage
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	register unsigned long __r4 asm("r4") = (unsigned long) filename;
-	register unsigned long __r5 asm("r5") = (unsigned long) argv;
-	register unsigned long __r6 asm("r6") = (unsigned long) envp;
-	register unsigned long __r7 asm("r7");
-
-	__asm__ __volatile__ ("	\n"
-		"ldi	r27, %5		\n"
-		"syscall		\n"
-		"mv	%0, r4		\n"
-		"mv	%1, r7		\n"
-		: "=&r" (__r4), "=r" (__r7)
-		: "r" (__r4), "r" (__r5), "r" (__r6), "i" (__NR_execve)
-		: "r8", "r9", "r10", "r11", "r22", "r23", "r24", "r25",
-		  "r26", "r27", "memory");
-
-	if (__r7 == 0)
-		return __r4;
-
-	return -__r4;
-}
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index babc2b8..89f574e 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -16,6 +16,7 @@ config SUPERH
 	select HAVE_DEBUG_BUGVERBOSE
 	select ARCH_HAVE_CUSTOM_GPIO_H
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG if (GUSA_RB || CPU_SH4A)
+	select ARCH_NO_VIRT_TO_BUS
 	select PERF_USE_VMALLOC
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_KERNEL_GZIP
@@ -40,6 +41,8 @@ config SUPERH
 	select GENERIC_STRNLEN_USER
 	select HAVE_MOD_ARCH_SPECIFIC if DWARF_UNWINDER
 	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
 	help
 	  The SuperH is a RISC processor targeted for use in embedded systems
 	  and consumer electronics; it was also used in the Sega Dreamcast
@@ -150,9 +153,6 @@ config ARCH_HAS_ILOG2_U32
 config ARCH_HAS_ILOG2_U64
 	def_bool n
 
-config ARCH_NO_VIRT_TO_BUS
-	def_bool y
-
 config ARCH_HAS_DEFAULT_IDLE
 	def_bool y
 
diff --git a/arch/sh/boards/board-espt.c b/arch/sh/boards/board-espt.c
index 6cba0a7..d71a0bc 100644
--- a/arch/sh/boards/board-espt.c
+++ b/arch/sh/boards/board-espt.c
@@ -1,5 +1,5 @@
 /*
- * Data Technology Inc. ESPT-GIGA board suport
+ * Data Technology Inc. ESPT-GIGA board support
  *
  * Copyright (C) 2008, 2009 Renesas Solutions Corp.
  * Copyright (C) 2008, 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
diff --git a/arch/sh/configs/ecovec24_defconfig b/arch/sh/configs/ecovec24_defconfig
index 911e30c9..c6c2bec 100644
--- a/arch/sh/configs/ecovec24_defconfig
+++ b/arch/sh/configs/ecovec24_defconfig
@@ -112,7 +112,7 @@ CONFIG_USB_MON=y
 CONFIG_USB_R8A66597_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_MMC=y
 CONFIG_MMC_SPI=y
 CONFIG_MMC_SDHI=y
diff --git a/arch/sh/configs/se7724_defconfig b/arch/sh/configs/se7724_defconfig
index ed35093..1faa788 100644
--- a/arch/sh/configs/se7724_defconfig
+++ b/arch/sh/configs/se7724_defconfig
@@ -109,7 +109,7 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 CONFIG_MMC_SPI=y
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index a7e078f..81e5daf 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -319,7 +319,5 @@ EXPORT_SYMBOL(pci_iounmap);
 
 #endif /* CONFIG_GENERIC_IOMAP */
 
-#ifdef CONFIG_HOTPLUG
 EXPORT_SYMBOL(PCIBIOS_MIN_IO);
 EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
-#endif
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 29f83be..280bea9 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -31,5 +31,6 @@ generic-y += socket.h
 generic-y += statfs.h
 generic-y += termbits.h
 generic-y += termios.h
+generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
diff --git a/arch/sh/include/asm/dma-mapping.h b/arch/sh/include/asm/dma-mapping.h
index 8bd965e..b437f2c 100644
--- a/arch/sh/include/asm/dma-mapping.h
+++ b/arch/sh/include/asm/dma-mapping.h
@@ -46,6 +46,7 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 
+	debug_dma_mapping_error(dev, dma_addr);
 	if (ops->mapping_error)
 		return ops->mapping_error(dev, dma_addr);
 
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 73a23f4..629db2a 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -382,7 +382,7 @@ static inline int iounmap_fixed(void __iomem *addr) { return -EINVAL; }
 #define xlate_dev_kmem_ptr(p)	p
 
 #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
-int valid_phys_addr_range(unsigned long addr, size_t size);
+int valid_phys_addr_range(phys_addr_t addr, size_t size);
 int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
 
 #endif /* __KERNEL__ */
diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h
index b6311fd..b1320d5 100644
--- a/arch/sh/include/asm/processor_32.h
+++ b/arch/sh/include/asm/processor_32.h
@@ -126,11 +126,6 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_pc, unsigned lo
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
-/*
- * create a kernel thread without removing it from tasklists
- */
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 /* Copy and release all segment info associated with a VM */
 #define copy_segments(p, mm)	do { } while(0)
 #define release_segments(mm)	do { } while(0)
diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h
index cd6029f..1ee8946 100644
--- a/arch/sh/include/asm/processor_64.h
+++ b/arch/sh/include/asm/processor_64.h
@@ -159,11 +159,6 @@ struct mm_struct;
 
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
-/*
- * create a kernel thread without removing it from tasklists
- */
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 
 /* Copy and release all segment info associated with a VM */
 #define copy_segments(p, mm)	do { } while (0)
diff --git a/arch/sh/include/asm/syscalls_32.h b/arch/sh/include/asm/syscalls_32.h
index 6c1fa55..cc25485 100644
--- a/arch/sh/include/asm/syscalls_32.h
+++ b/arch/sh/include/asm/syscalls_32.h
@@ -9,20 +9,6 @@
 
 struct pt_regs;
 
-asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
-			unsigned long r6, unsigned long r7,
-			struct pt_regs __regs);
-asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
-			 unsigned long parent_tidptr,
-			 unsigned long child_tidptr,
-			 struct pt_regs __regs);
-asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
-			 unsigned long r6, unsigned long r7,
-			 struct pt_regs __regs);
-asmlinkage int sys_execve(const char __user *ufilename,
-			  const char __user *const __user *uargv,
-			  const char __user *const __user *uenvp,
-			  unsigned long r7, struct pt_regs __regs);
 asmlinkage int sys_sigsuspend(old_sigset_t mask);
 asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act,
 			     struct old_sigaction __user *oact);
diff --git a/arch/sh/include/asm/syscalls_64.h b/arch/sh/include/asm/syscalls_64.h
index ee519f4..d62e8eb 100644
--- a/arch/sh/include/asm/syscalls_64.h
+++ b/arch/sh/include/asm/syscalls_64.h
@@ -9,23 +9,6 @@
 
 struct pt_regs;
 
-asmlinkage int sys_fork(unsigned long r2, unsigned long r3,
-			unsigned long r4, unsigned long r5,
-			unsigned long r6, unsigned long r7,
-			struct pt_regs *pregs);
-asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
-			 unsigned long r4, unsigned long r5,
-			 unsigned long r6, unsigned long r7,
-			 struct pt_regs *pregs);
-asmlinkage int sys_vfork(unsigned long r2, unsigned long r3,
-			 unsigned long r4, unsigned long r5,
-			 unsigned long r6, unsigned long r7,
-			 struct pt_regs *pregs);
-asmlinkage int sys_execve(const char *ufilename, char **uargv,
-			  char **uenvp, unsigned long r5,
-			  unsigned long r6, unsigned long r7,
-			  struct pt_regs *pregs);
-
 /* Misc syscall related bits */
 asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs);
 asmlinkage void do_syscall_trace_leave(struct pt_regs *regs);
diff --git a/arch/sh/include/asm/unistd.h b/arch/sh/include/asm/unistd.h
index 38956df..43d3f26b 100644
--- a/arch/sh/include/asm/unistd.h
+++ b/arch/sh/include/asm/unistd.h
@@ -28,6 +28,10 @@
 # define __ARCH_WANT_SYS_SIGPENDING
 # define __ARCH_WANT_SYS_SIGPROCMASK
 # define __ARCH_WANT_SYS_RT_SIGACTION
+# define __ARCH_WANT_SYS_EXECVE
+# define __ARCH_WANT_SYS_FORK
+# define __ARCH_WANT_SYS_VFORK
+# define __ARCH_WANT_SYS_CLONE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/sh/include/uapi/asm/ioctls.h b/arch/sh/include/uapi/asm/ioctls.h
index a6769f3..3422410 100644
--- a/arch/sh/include/uapi/asm/ioctls.h
+++ b/arch/sh/include/uapi/asm/ioctls.h
@@ -88,6 +88,9 @@
 #define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
 #define TIOCVHANGUP	_IO('T', 0x37)
+#define TIOCGPKT	_IOR('T', 0x38, int) /* Get packet mode state */
+#define TIOCGPTLCK	_IOR('T', 0x39, int) /* Get Pty lock state */
+#define TIOCGEXCL	_IOR('T', 0x40, int) /* Get exclusive mode state */
 
 #define TIOCSERCONFIG	_IO('T', 83) /* 0x5453 */
 #define TIOCSERGWILD	_IOR('T', 84,  int) /* 0x5454 */
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 88571ff..f259b37 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -16,7 +16,7 @@ obj-y	:= debugtraps.o dma-nommu.o dumpstack.o 		\
 	   machvec.o nmi_debug.o process.o				\
 	   process_$(BITS).o ptrace.o ptrace_$(BITS).o			\
 	   reboot.o return_address.o					\
-	   setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o		\
+	   setup.o signal_$(BITS).o sys_sh.o 				\
 	   syscalls_$(BITS).o time.o topology.o traps.o			\
 	   traps_$(BITS).o unwinder.o
 
@@ -25,6 +25,7 @@ obj-y				+= iomap.o
 obj-$(CONFIG_HAS_IOPORT)	+= ioport.o
 endif
 
+obj-$(CONFIG_SUPERH32)		+= sys_sh32.o
 obj-y				+= cpu/
 obj-$(CONFIG_VSYSCALL)		+= vsyscall/
 obj-$(CONFIG_SMP)		+= smp.o
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
index 0c2f1b2..42d991f 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7720.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
@@ -20,6 +20,7 @@
 #include <linux/serial_sci.h>
 #include <linux/sh_timer.h>
 #include <linux/sh_intc.h>
+#include <linux/usb/ohci_pdriver.h>
 #include <asm/rtc.h>
 #include <cpu/serial.h>
 
@@ -103,12 +104,15 @@ static struct resource usb_ohci_resources[] = {
 
 static u64 usb_ohci_dma_mask = 0xffffffffUL;
 
+static struct usb_ohci_pdata usb_ohci_pdata;
+
 static struct platform_device usb_ohci_device = {
-	.name		= "sh_ohci",
+	.name		= "ohci-platform",
 	.id		= -1,
 	.dev = {
 		.dma_mask		= &usb_ohci_dma_mask,
 		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &usb_ohci_pdata,
 	},
 	.num_resources	= ARRAY_SIZE(usb_ohci_resources),
 	.resource	= usb_ohci_resources,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
index 4a2f357..9079a0f 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
@@ -19,6 +19,7 @@
 #include <linux/sh_timer.h>
 #include <linux/sh_dma.h>
 #include <linux/sh_intc.h>
+#include <linux/usb/ohci_pdriver.h>
 #include <cpu/dma-register.h>
 #include <cpu/sh7757.h>
 
@@ -750,12 +751,15 @@ static struct resource usb_ohci_resources[] = {
 	},
 };
 
+static struct usb_ohci_pdata usb_ohci_pdata;
+
 static struct platform_device usb_ohci_device = {
-	.name		= "sh_ohci",
+	.name		= "ohci-platform",
 	.id		= -1,
 	.dev = {
 		.dma_mask = &usb_ohci_device.dev.coherent_dma_mask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data	= &usb_ohci_pdata,
 	},
 	.num_resources	= ARRAY_SIZE(usb_ohci_resources),
 	.resource	= usb_ohci_resources,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
index bd0a8fb..1686aca 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
@@ -16,6 +16,7 @@
 #include <linux/sh_intc.h>
 #include <linux/io.h>
 #include <linux/serial_sci.h>
+#include <linux/usb/ohci_pdriver.h>
 
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xffe00000,
@@ -106,12 +107,15 @@ static struct resource usb_ohci_resources[] = {
 
 static u64 usb_ohci_dma_mask = 0xffffffffUL;
 
+static struct usb_ohci_pdata usb_ohci_pdata;
+
 static struct platform_device usb_ohci_device = {
-	.name		= "sh_ohci",
+	.name		= "ohci-platform",
 	.id		= -1,
 	.dev = {
 		.dma_mask		= &usb_ohci_dma_mask,
 		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &usb_ohci_pdata,
 	},
 	.num_resources	= ARRAY_SIZE(usb_ohci_resources),
 	.resource	= usb_ohci_resources,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
index 2e6952f..ab52d4d 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
@@ -23,6 +23,7 @@
 #include <linux/sh_timer.h>
 #include <linux/sh_dma.h>
 #include <linux/sh_intc.h>
+#include <linux/usb/ohci_pdriver.h>
 #include <cpu/dma-register.h>
 #include <asm/mmzone.h>
 
@@ -583,12 +584,15 @@ static struct resource usb_ohci_resources[] = {
 	},
 };
 
+static struct usb_ohci_pdata usb_ohci_pdata;
+
 static struct platform_device usb_ohci_device = {
-	.name		= "sh_ohci",
+	.name		= "ohci-platform",
 	.id		= -1,
 	.dev = {
 		.dma_mask		= &usb_ohci_device.dev.coherent_dma_mask,
 		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &usb_ohci_pdata,
 	},
 	.num_resources	= ARRAY_SIZE(usb_ohci_resources),
 	.resource	= usb_ohci_resources,
diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S
index 7e605b9..0c8d037 100644
--- a/arch/sh/kernel/cpu/sh5/entry.S
+++ b/arch/sh/kernel/cpu/sh5/entry.S
@@ -1228,6 +1228,25 @@ ret_from_fork:
 	pta	ret_from_syscall, tr0
 	blink	tr0, ZERO
 
+.global	ret_from_kernel_thread
+ret_from_kernel_thread:
+
+	movi	schedule_tail,r5
+	ori	r5, 1, r5
+	ptabs	r5, tr0
+	blink	tr0, LINK
+
+	ld.q	SP, FRAME_R(2), r2
+	ld.q	SP, FRAME_R(3), r3
+	ptabs	r3, tr0
+	blink	tr0, LINK
+
+	ld.q	SP, FRAME_S(FSPC), r2
+	addi	r2, 4, r2		/* Move PC, being pre-execution event */
+	st.q	SP, FRAME_S(FSPC), r2
+	pta	ret_from_syscall, tr0
+	blink	tr0, ZERO
+
 syscall_allowed:
 	/* Use LINK to deflect the exit point, default is syscall_ret */
 	pta	syscall_ret, tr0
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
index b96489d..9b6e4be 100644
--- a/arch/sh/kernel/entry-common.S
+++ b/arch/sh/kernel/entry-common.S
@@ -297,6 +297,19 @@ ret_from_fork:
 	 mov	r0, r4
 	bra	syscall_exit
 	 nop
+
+	.align	2
+	.globl	ret_from_kernel_thread
+ret_from_kernel_thread:
+	mov.l	1f, r8
+	jsr	@r8
+	 mov	r0, r4
+	mov.l	@(OFF_R5,r15), r5   ! fn
+	jsr	@r5
+	 mov.l	@(OFF_R4,r15), r4   ! arg
+	bra	syscall_exit
+	 nop
+
 	.align	2
 1:	.long	schedule_tail
 
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index ba7345f..73eb66f 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -68,38 +68,6 @@ void show_regs(struct pt_regs * regs)
 	show_code(regs);
 }
 
-/*
- * Create a kernel thread
- */
-__noreturn void kernel_thread_helper(void *arg, int (*fn)(void *))
-{
-	do_exit(fn(arg));
-}
-
-/* Don't use this in BL=1(cli).  Or else, CPU resets! */
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	struct pt_regs regs;
-	int pid;
-
-	memset(&regs, 0, sizeof(regs));
-	regs.regs[4] = (unsigned long)arg;
-	regs.regs[5] = (unsigned long)fn;
-
-	regs.pc = (unsigned long)kernel_thread_helper;
-	regs.sr = SR_MD;
-#if defined(CONFIG_SH_FPU)
-	regs.sr |= SR_FD;
-#endif
-
-	/* Ok, create the new process.. */
-	pid = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
-		      &regs, 0, NULL, NULL);
-
-	return pid;
-}
-EXPORT_SYMBOL(kernel_thread);
-
 void start_thread(struct pt_regs *regs, unsigned long new_pc,
 		  unsigned long new_sp)
 {
@@ -157,10 +125,10 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 EXPORT_SYMBOL(dump_fpu);
 
 asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-		unsigned long unused,
-		struct task_struct *p, struct pt_regs *regs)
+		unsigned long arg, struct task_struct *p)
 {
 	struct thread_info *ti = task_thread_info(p);
 	struct pt_regs *childregs;
@@ -177,29 +145,35 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	}
 #endif
 
-	childregs = task_pt_regs(p);
-	*childregs = *regs;
+	memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
 
-	if (user_mode(regs)) {
-		childregs->regs[15] = usp;
-		ti->addr_limit = USER_DS;
-	} else {
-		childregs->regs[15] = (unsigned long)childregs;
+	childregs = task_pt_regs(p);
+	p->thread.sp = (unsigned long) childregs;
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		memset(childregs, 0, sizeof(struct pt_regs));
+		p->thread.pc = (unsigned long) ret_from_kernel_thread;
+		childregs->regs[4] = arg;
+		childregs->regs[5] = usp;
+		childregs->sr = SR_MD;
+#if defined(CONFIG_SH_FPU)
+		childregs->sr |= SR_FD;
+#endif
 		ti->addr_limit = KERNEL_DS;
 		ti->status &= ~TS_USEDFPU;
 		p->fpu_counter = 0;
+		return 0;
 	}
+	*childregs = *current_pt_regs();
+
+	if (usp)
+		childregs->regs[15] = usp;
+	ti->addr_limit = USER_DS;
 
 	if (clone_flags & CLONE_SETTLS)
 		childregs->gbr = childregs->regs[0];
 
 	childregs->regs[0] = 0; /* Set return value for child */
-
-	p->thread.sp = (unsigned long) childregs;
 	p->thread.pc = (unsigned long) ret_from_fork;
-
-	memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
-
 	return 0;
 }
 
@@ -243,74 +217,6 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
 	return prev;
 }
 
-asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
-			unsigned long r6, unsigned long r7,
-			struct pt_regs __regs)
-{
-#ifdef CONFIG_MMU
-	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
-	return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL);
-#else
-	/* fork almost works, enough to trick you into looking elsewhere :-( */
-	return -EINVAL;
-#endif
-}
-
-asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
-			 unsigned long parent_tidptr,
-			 unsigned long child_tidptr,
-			 struct pt_regs __regs)
-{
-	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
-	if (!newsp)
-		newsp = regs->regs[15];
-	return do_fork(clone_flags, newsp, regs, 0,
-			(int __user *)parent_tidptr,
-			(int __user *)child_tidptr);
-}
-
-/*
- * This is trivial, and on the face of it looks like it
- * could equally well be done in user mode.
- *
- * Not so, for quite unobvious reasons - register pressure.
- * In user mode vfork() cannot have a stack frame, and if
- * done by calling the "clone()" system call directly, you
- * do not have enough call-clobbered registers to hold all
- * the information you need.
- */
-asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
-			 unsigned long r6, unsigned long r7,
-			 struct pt_regs __regs)
-{
-	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs,
-		       0, NULL, NULL);
-}
-
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char __user *ufilename,
-			  const char __user *const __user *uargv,
-			  const char __user *const __user *uenvp,
-			  unsigned long r7, struct pt_regs __regs)
-{
-	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
-	int error;
-	struct filename *filename;
-
-	filename = getname(ufilename);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-
-	error = do_execve(filename->name, uargv, uenvp, regs);
-	putname(filename);
-out:
-	return error;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
 	unsigned long pc;
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c
index 98a709f..e611c85 100644
--- a/arch/sh/kernel/process_64.c
+++ b/arch/sh/kernel/process_64.c
@@ -285,39 +285,6 @@ void show_regs(struct pt_regs *regs)
 }
 
 /*
- * Create a kernel thread
- */
-__noreturn void kernel_thread_helper(void *arg, int (*fn)(void *))
-{
-	do_exit(fn(arg));
-}
-
-/*
- * This is the mechanism for creating a new kernel thread.
- *
- * NOTE! Only a kernel-only process(ie the swapper or direct descendants
- * who haven't done an "execve()") should use this: it will work within
- * a system call from a "real" process, but the process memory space will
- * not be freed until both the parent and the child have exited.
- */
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-	regs.regs[2] = (unsigned long)arg;
-	regs.regs[3] = (unsigned long)fn;
-
-	regs.pc = (unsigned long)kernel_thread_helper;
-	regs.sr = (1 << 30);
-
-	/* Ok, create the new process.. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
-		      &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
-/*
  * Free current thread data structures etc..
  */
 void exit_thread(void)
@@ -401,26 +368,37 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 EXPORT_SYMBOL(dump_fpu);
 
 asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-		unsigned long unused,
-		struct task_struct *p, struct pt_regs *regs)
+		unsigned long arg, struct task_struct *p)
 {
-	struct pt_regs *childregs;
+	struct pt_regs *childregs, *regs = current_pt_regs();
 
 #ifdef CONFIG_SH_FPU
-	if(last_task_used_math == current) {
+	/* can't happen for a kernel thread */
+	if (last_task_used_math == current) {
 		enable_fpu();
 		save_fpu(current);
 		disable_fpu();
 		last_task_used_math = NULL;
-		regs->sr |= SR_FD;
+		current_pt_regs()->sr |= SR_FD;
 	}
 #endif
 	/* Copy from sh version */
 	childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1;
+	p->thread.sp = (unsigned long) childregs;
 
-	*childregs = *regs;
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		memset(childregs, 0, sizeof(struct pt_regs));
+		childregs->regs[2] = (unsigned long)arg;
+		childregs->regs[3] = (unsigned long)fn;
+		childregs->sr = (1 << 30); /* not user_mode */
+		childregs->sr |= SR_FD; /* Invalidate FPU flag */
+		p->thread.pc = (unsigned long) ret_from_kernel_thread;
+		return 0;
+	}
+	*childregs = *current_pt_regs();
 
 	/*
 	 * Sign extend the edited stack.
@@ -428,85 +406,18 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	 * 32-bit wide and context switch must take care
 	 * of NEFF sign extension.
 	 */
-	if (user_mode(regs)) {
+	if (usp)
 		childregs->regs[15] = neff_sign_extend(usp);
-		p->thread.uregs = childregs;
-	} else {
-		childregs->regs[15] =
-			neff_sign_extend((unsigned long)task_stack_page(p) +
-					 THREAD_SIZE);
-	}
+	p->thread.uregs = childregs;
 
 	childregs->regs[9] = 0; /* Set return value for child */
 	childregs->sr |= SR_FD; /* Invalidate FPU flag */
 
-	p->thread.sp = (unsigned long) childregs;
 	p->thread.pc = (unsigned long) ret_from_fork;
 
 	return 0;
 }
 
-asmlinkage int sys_fork(unsigned long r2, unsigned long r3,
-			unsigned long r4, unsigned long r5,
-			unsigned long r6, unsigned long r7,
-			struct pt_regs *pregs)
-{
-	return do_fork(SIGCHLD, pregs->regs[15], pregs, 0, 0, 0);
-}
-
-asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
-			 unsigned long r4, unsigned long r5,
-			 unsigned long r6, unsigned long r7,
-			 struct pt_regs *pregs)
-{
-	if (!newsp)
-		newsp = pregs->regs[15];
-	return do_fork(clone_flags, newsp, pregs, 0, 0, 0);
-}
-
-/*
- * This is trivial, and on the face of it looks like it
- * could equally well be done in user mode.
- *
- * Not so, for quite unobvious reasons - register pressure.
- * In user mode vfork() cannot have a stack frame, and if
- * done by calling the "clone()" system call directly, you
- * do not have enough call-clobbered registers to hold all
- * the information you need.
- */
-asmlinkage int sys_vfork(unsigned long r2, unsigned long r3,
-			 unsigned long r4, unsigned long r5,
-			 unsigned long r6, unsigned long r7,
-			 struct pt_regs *pregs)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, pregs->regs[15], pregs, 0, 0, 0);
-}
-
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char *ufilename, char **uargv,
-			  char **uenvp, unsigned long r5,
-			  unsigned long r6, unsigned long r7,
-			  struct pt_regs *pregs)
-{
-	int error;
-	struct filename *filename;
-
-	filename = getname((char __user *)ufilename);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-
-	error = do_execve(filename->name,
-			  (const char __user *const __user *)uargv,
-			  (const char __user *const __user *)uenvp,
-			  pregs);
-	putname(filename);
-out:
-	return error;
-}
-
 #ifdef CONFIG_FRAME_POINTER
 static int in_sh64_switch_to(unsigned long pc)
 {
diff --git a/arch/sh/kernel/sys_sh32.c b/arch/sh/kernel/sys_sh32.c
index f56b6fe5..497bab3 100644
--- a/arch/sh/kernel/sys_sh32.c
+++ b/arch/sh/kernel/sys_sh32.c
@@ -60,27 +60,3 @@ asmlinkage int sys_fadvise64_64_wrapper(int fd, u32 offset0, u32 offset1,
 				(u64)len0 << 32 | len1,	advice);
 #endif
 }
-
-#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A)
-#define SYSCALL_ARG3	"trapa #0x23"
-#else
-#define SYSCALL_ARG3	"trapa #0x13"
-#endif
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	register long __sc0 __asm__ ("r3") = __NR_execve;
-	register long __sc4 __asm__ ("r4") = (long) filename;
-	register long __sc5 __asm__ ("r5") = (long) argv;
-	register long __sc6 __asm__ ("r6") = (long) envp;
-	__asm__ __volatile__ (SYSCALL_ARG3 : "=z" (__sc0)
-			: "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6)
-			: "memory");
-	return __sc0;
-}
diff --git a/arch/sh/kernel/sys_sh64.c b/arch/sh/kernel/sys_sh64.c
deleted file mode 100644
index c5a38c4..0000000
--- a/arch/sh/kernel/sys_sh64.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * arch/sh/kernel/sys_sh64.c
- *
- * Copyright (C) 2000, 2001  Paolo Alberelli
- *
- * This file contains various random system calls that
- * have a non-standard calling sequence on the Linux/SH5
- * platform.
- *
- * 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/errno.h>
-#include <linux/rwsem.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/smp.h>
-#include <linux/sem.h>
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <linux/stat.h>
-#include <linux/mman.h>
-#include <linux/file.h>
-#include <linux/syscalls.h>
-#include <linux/ipc.h>
-#include <asm/uaccess.h>
-#include <asm/ptrace.h>
-#include <asm/unistd.h>
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	register unsigned long __sc0 __asm__ ("r9") = ((0x13 << 16) | __NR_execve);
-	register unsigned long __sc2 __asm__ ("r2") = (unsigned long) filename;
-	register unsigned long __sc3 __asm__ ("r3") = (unsigned long) argv;
-	register unsigned long __sc4 __asm__ ("r4") = (unsigned long) envp;
-	__asm__ __volatile__ ("trapa	%1 !\t\t\t execve(%2,%3,%4)"
-	: "=r" (__sc0)
-	: "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) );
-	__asm__ __volatile__ ("!dummy	%0 %1 %2 %3"
-	: : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) : "memory");
-	return __sc0;
-}
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index cb8f992..5d2a4df 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -111,6 +111,7 @@ config VSYSCALL
 config NUMA
 	bool "Non Uniform Memory Access (NUMA) Support"
 	depends on MMU && SYS_SUPPORTS_NUMA && EXPERIMENTAL
+	select ARCH_WANTS_NUMA_VARIABLE_LOCALITY
 	default n
 	help
 	  Some SH systems have many various memories scattered around
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index cbbdcad..1f49c28 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -301,17 +301,6 @@ bad_area_access_error(struct pt_regs *regs, unsigned long error_code,
 	__bad_area(regs, error_code, address, SEGV_ACCERR);
 }
 
-static void out_of_memory(void)
-{
-	/*
-	 * We ran out of memory, call the OOM killer, and return the userspace
-	 * (which will retry the fault, or kill us if we got oom-killed):
-	 */
-	up_read(&current->mm->mmap_sem);
-
-	pagefault_out_of_memory();
-}
-
 static void
 do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address)
 {
@@ -353,8 +342,14 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
 			no_context(regs, error_code, address);
 			return 1;
 		}
+		up_read(&current->mm->mmap_sem);
 
-		out_of_memory();
+		/*
+		 * We ran out of memory, call the OOM killer, and return the
+		 * userspace (which will retry the fault, or kill us if we got
+		 * oom-killed):
+		 */
+		pagefault_out_of_memory();
 	} else {
 		if (fault & VM_FAULT_SIGBUS)
 			do_sigbus(regs, error_code, address);
diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c
index afeb710..6777177 100644
--- a/arch/sh/mm/mmap.c
+++ b/arch/sh/mm/mmap.c
@@ -30,25 +30,13 @@ static inline unsigned long COLOUR_ALIGN(unsigned long addr,
 	return base + off;
 }
 
-static inline unsigned long COLOUR_ALIGN_DOWN(unsigned long addr,
-					      unsigned long pgoff)
-{
-	unsigned long base = addr & ~shm_align_mask;
-	unsigned long off = (pgoff << PAGE_SHIFT) & shm_align_mask;
-
-	if (base + off <= addr)
-		return base + off;
-
-	return base - off;
-}
-
 unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	unsigned long len, unsigned long pgoff, unsigned long flags)
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
-	unsigned long start_addr;
 	int do_colour_align;
+	struct vm_unmapped_area_info info;
 
 	if (flags & MAP_FIXED) {
 		/* We do not accept a shared mapping if it would violate
@@ -79,47 +67,13 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
 			return addr;
 	}
 
-	if (len > mm->cached_hole_size) {
-		start_addr = addr = mm->free_area_cache;
-	} else {
-	        mm->cached_hole_size = 0;
-		start_addr = addr = TASK_UNMAPPED_BASE;
-	}
-
-full_search:
-	if (do_colour_align)
-		addr = COLOUR_ALIGN(addr, pgoff);
-	else
-		addr = PAGE_ALIGN(mm->free_area_cache);
-
-	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
-		/* At this point:  (!vma || addr < vma->vm_end). */
-		if (unlikely(TASK_SIZE - len < addr)) {
-			/*
-			 * Start a new search - just in case we missed
-			 * some holes.
-			 */
-			if (start_addr != TASK_UNMAPPED_BASE) {
-				start_addr = addr = TASK_UNMAPPED_BASE;
-				mm->cached_hole_size = 0;
-				goto full_search;
-			}
-			return -ENOMEM;
-		}
-		if (likely(!vma || addr + len <= vma->vm_start)) {
-			/*
-			 * Remember the place where we stopped the search:
-			 */
-			mm->free_area_cache = addr + len;
-			return addr;
-		}
-		if (addr + mm->cached_hole_size < vma->vm_start)
-		        mm->cached_hole_size = vma->vm_start - addr;
-
-		addr = vma->vm_end;
-		if (do_colour_align)
-			addr = COLOUR_ALIGN(addr, pgoff);
-	}
+	info.flags = 0;
+	info.length = len;
+	info.low_limit = TASK_UNMAPPED_BASE;
+	info.high_limit = TASK_SIZE;
+	info.align_mask = do_colour_align ? (PAGE_MASK & shm_align_mask) : 0;
+	info.align_offset = pgoff << PAGE_SHIFT;
+	return vm_unmapped_area(&info);
 }
 
 unsigned long
@@ -131,6 +85,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	struct mm_struct *mm = current->mm;
 	unsigned long addr = addr0;
 	int do_colour_align;
+	struct vm_unmapped_area_info info;
 
 	if (flags & MAP_FIXED) {
 		/* We do not accept a shared mapping if it would violate
@@ -162,73 +117,27 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 			return addr;
 	}
 
-	/* check if free_area_cache is useful for us */
-	if (len <= mm->cached_hole_size) {
-	        mm->cached_hole_size = 0;
-		mm->free_area_cache = mm->mmap_base;
-	}
-
-	/* either no address requested or can't fit in requested address hole */
-	addr = mm->free_area_cache;
-	if (do_colour_align) {
-		unsigned long base = COLOUR_ALIGN_DOWN(addr-len, pgoff);
+	info.flags = VM_UNMAPPED_AREA_TOPDOWN;
+	info.length = len;
+	info.low_limit = PAGE_SIZE;
+	info.high_limit = mm->mmap_base;
+	info.align_mask = do_colour_align ? (PAGE_MASK & shm_align_mask) : 0;
+	info.align_offset = pgoff << PAGE_SHIFT;
+	addr = vm_unmapped_area(&info);
 
-		addr = base + len;
-	}
-
-	/* make sure it can fit in the remaining address space */
-	if (likely(addr > len)) {
-		vma = find_vma(mm, addr-len);
-		if (!vma || addr <= vma->vm_start) {
-			/* remember the address as a hint for next time */
-			return (mm->free_area_cache = addr-len);
-		}
-	}
-
-	if (unlikely(mm->mmap_base < len))
-		goto bottomup;
-
-	addr = mm->mmap_base-len;
-	if (do_colour_align)
-		addr = COLOUR_ALIGN_DOWN(addr, pgoff);
-
-	do {
-		/*
-		 * Lookup failure means no vma is above this address,
-		 * else if new region fits below vma->vm_start,
-		 * return with success:
-		 */
-		vma = find_vma(mm, addr);
-		if (likely(!vma || addr+len <= vma->vm_start)) {
-			/* remember the address as a hint for next time */
-			return (mm->free_area_cache = addr);
-		}
-
-		/* remember the largest hole we saw so far */
-		if (addr + mm->cached_hole_size < vma->vm_start)
-		        mm->cached_hole_size = vma->vm_start - addr;
-
-		/* try just below the current vma->vm_start */
-		addr = vma->vm_start-len;
-		if (do_colour_align)
-			addr = COLOUR_ALIGN_DOWN(addr, pgoff);
-	} while (likely(len < vma->vm_start));
-
-bottomup:
 	/*
 	 * A failed mmap() very likely causes application failure,
 	 * so fall back to the bottom-up function here. This scenario
 	 * can happen with large stack limits and large mmap()
 	 * allocations.
 	 */
-	mm->cached_hole_size = ~0UL;
-	mm->free_area_cache = TASK_UNMAPPED_BASE;
-	addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
-	/*
-	 * Restore the topdown base:
-	 */
-	mm->free_area_cache = mm->mmap_base;
-	mm->cached_hole_size = ~0UL;
+	if (addr & ~PAGE_MASK) {
+		VM_BUG_ON(addr != -ENOMEM);
+		info.flags = 0;
+		info.low_limit = TASK_UNMAPPED_BASE;
+		info.high_limit = TASK_SIZE;
+		addr = vm_unmapped_area(&info);
+	}
 
 	return addr;
 }
@@ -238,7 +147,7 @@ bottomup:
  * You really shouldn't be using read() or write() on /dev/mem.  This
  * might go away in the future.
  */
-int valid_phys_addr_range(unsigned long addr, size_t count)
+int valid_phys_addr_range(phys_addr_t addr, size_t count)
 {
 	if (addr < __MEMORY_START)
 		return 0;
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 9f2edb5..ff44c7e 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -21,6 +21,7 @@ config SPARC
 	select SYSCTL_EXCEPTION_TRACE
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
+	select ARCH_NO_VIRT_TO_BUS
 	select RTC_CLASS
 	select RTC_DRV_M48T59
 	select HAVE_IRQ_WORK
@@ -41,6 +42,8 @@ config SPARC
 	select GENERIC_STRNCPY_FROM_USER
 	select GENERIC_STRNLEN_USER
 	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
 
 config SPARC32
 	def_bool !64BIT
@@ -143,9 +146,6 @@ config GENERIC_GPIO
 	help
 	  Generic GPIO API support
 
-config ARCH_NO_VIRT_TO_BUS
-	def_bool y
-
 config ARCH_SUPPORTS_DEBUG_PAGEALLOC
 	def_bool y if SPARC64
 
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 645a58d..e26d430 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -8,4 +8,5 @@ generic-y += local64.h
 generic-y += irq_regs.h
 generic-y += local.h
 generic-y += module.h
+generic-y += trace_clock.h
 generic-y += word-at-a-time.h
diff --git a/arch/sparc/include/asm/dma-mapping.h b/arch/sparc/include/asm/dma-mapping.h
index 8493fd3..05fe53f 100644
--- a/arch/sparc/include/asm/dma-mapping.h
+++ b/arch/sparc/include/asm/dma-mapping.h
@@ -59,6 +59,7 @@ static inline void dma_free_attrs(struct device *dev, size_t size,
 
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
+	debug_dma_mapping_error(dev, dma_addr);
 	return (dma_addr == DMA_ERROR_CODE);
 }
 
diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h
index f74ac9e..c1e0191 100644
--- a/arch/sparc/include/asm/processor_32.h
+++ b/arch/sparc/include/asm/processor_32.h
@@ -106,7 +106,6 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
 
 /* Free all resources held by a thread. */
 #define release_thread(tsk)		do { } while(0)
-extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 extern unsigned long get_wchan(struct task_struct *);
 
diff --git a/arch/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h
index 721e25f..cce72ce 100644
--- a/arch/sparc/include/asm/processor_64.h
+++ b/arch/sparc/include/asm/processor_64.h
@@ -94,6 +94,7 @@ struct thread_struct {
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
+#include <asm/fpumacro.h>
 
 /* Return saved PC of a blocked thread. */
 struct task_struct;
@@ -143,6 +144,10 @@ do { \
 	: \
 	: "r" (regs), "r" (sp - sizeof(struct reg_window) - STACK_BIAS), \
 	  "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
+	fprs_write(0);	\
+	current_thread_info()->xfsr[0] = 0;	\
+	current_thread_info()->fpsaved[0] = 0;	\
+	regs->tstate &= ~TSTATE_PEF;	\
 } while (0)
 
 #define start_thread32(regs, pc, sp) \
@@ -183,13 +188,15 @@ do { \
 	: \
 	: "r" (regs), "r" (sp - sizeof(struct reg_window32)), \
 	  "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
+	fprs_write(0);	\
+	current_thread_info()->xfsr[0] = 0;	\
+	current_thread_info()->fpsaved[0] = 0;	\
+	regs->tstate &= ~TSTATE_PEF;	\
 } while (0)
 
 /* Free all resources held by a thread. */
 #define release_thread(tsk)		do { } while (0)
 
-extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 extern unsigned long get_wchan(struct task_struct *task);
 
 #define task_pt_regs(tsk) (task_thread_info(tsk)->kregs)
diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h
index da43bdc..bdfafd7 100644
--- a/arch/sparc/include/asm/ptrace.h
+++ b/arch/sparc/include/asm/ptrace.h
@@ -32,6 +32,9 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
 #define arch_ptrace_stop(exit_code, info) \
 	synchronize_user_stack()
 
+#define current_pt_regs() \
+	((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
+
 struct global_reg_snapshot {
 	unsigned long		tstate;
 	unsigned long		tpc;
@@ -55,9 +58,7 @@ union global_cpu_snapshot {
 
 extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS];
 
-#define force_successful_syscall_return()	    \
-do {	current_thread_info()->syscall_noerror = 1; \
-} while (0)
+#define force_successful_syscall_return() set_thread_noerror(1)
 #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
 #define instruction_pointer(regs) ((regs)->tpc)
 #define instruction_pointer_set(regs, val) ((regs)->tpc = (val))
@@ -100,6 +101,9 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
 #define arch_ptrace_stop(exit_code, info) \
 	synchronize_user_stack()
 
+#define current_pt_regs() \
+	((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
+
 #define user_mode(regs) (!((regs)->psr & PSR_PS))
 #define instruction_pointer(regs) ((regs)->pc)
 #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
diff --git a/arch/sparc/include/asm/signal.h b/arch/sparc/include/asm/signal.h
index d243c2a..77b8585 100644
--- a/arch/sparc/include/asm/signal.h
+++ b/arch/sparc/include/asm/signal.h
@@ -26,7 +26,5 @@ struct k_sigaction {
 	void			__user *ka_restorer;
 };
 
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
 #endif /* !(__ASSEMBLY__) */
 #endif /* !(__SPARC_SIGNAL_H) */
diff --git a/arch/sparc/include/asm/switch_to_64.h b/arch/sparc/include/asm/switch_to_64.h
index 7923c4a..cad36f5 100644
--- a/arch/sparc/include/asm/switch_to_64.h
+++ b/arch/sparc/include/asm/switch_to_64.h
@@ -23,7 +23,7 @@ do {	flush_tlb_pending();						\
 	/* If you are tempted to conditionalize the following */	\
 	/* so that ASI is only written if it changes, think again. */	\
 	__asm__ __volatile__("wr %%g0, %0, %%asi"			\
-	: : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\
+	: : "r" (task_thread_info(next)->current_ds));\
 	trap_block[current_thread_info()->cpu].thread =			\
 		task_thread_info(next);					\
 	__asm__ __volatile__(						\
diff --git a/arch/sparc/include/asm/syscalls.h b/arch/sparc/include/asm/syscalls.h
index 45a43f6..bf8972a 100644
--- a/arch/sparc/include/asm/syscalls.h
+++ b/arch/sparc/include/asm/syscalls.h
@@ -8,6 +8,4 @@ extern asmlinkage long sparc_do_fork(unsigned long clone_flags,
 				     struct pt_regs *regs,
 				     unsigned long stack_size);
 
-extern asmlinkage int sparc_execve(struct pt_regs *regs);
-
 #endif /* _SPARC64_SYSCALLS_H */
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h
index a3fe4dc..269bd92 100644
--- a/arch/sparc/include/asm/thread_info_64.h
+++ b/arch/sparc/include/asm/thread_info_64.h
@@ -14,12 +14,12 @@
 #define TI_FLAG_FAULT_CODE_SHIFT	56
 #define TI_FLAG_BYTE_WSTATE		1
 #define TI_FLAG_WSTATE_SHIFT		48
-#define TI_FLAG_BYTE_CWP		2
-#define TI_FLAG_CWP_SHIFT		40
-#define TI_FLAG_BYTE_CURRENT_DS		3
-#define TI_FLAG_CURRENT_DS_SHIFT	32
-#define TI_FLAG_BYTE_FPDEPTH		4
-#define TI_FLAG_FPDEPTH_SHIFT		24
+#define TI_FLAG_BYTE_NOERROR		2
+#define TI_FLAG_BYTE_NOERROR_SHIFT	40
+#define TI_FLAG_BYTE_FPDEPTH		3
+#define TI_FLAG_FPDEPTH_SHIFT		32
+#define TI_FLAG_BYTE_CWP		4
+#define TI_FLAG_CWP_SHIFT		24
 #define TI_FLAG_BYTE_WSAVED		5
 #define TI_FLAG_WSAVED_SHIFT		16
 
@@ -47,7 +47,7 @@ struct thread_info {
 	struct exec_domain	*exec_domain;
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
 	__u8			new_child;
-	__u8			syscall_noerror;
+	__u8			current_ds;
 	__u16			cpu;
 
 	unsigned long		*utraps;
@@ -74,9 +74,9 @@ struct thread_info {
 #define TI_FAULT_CODE	(TI_FLAGS + TI_FLAG_BYTE_FAULT_CODE)
 #define TI_WSTATE	(TI_FLAGS + TI_FLAG_BYTE_WSTATE)
 #define TI_CWP		(TI_FLAGS + TI_FLAG_BYTE_CWP)
-#define TI_CURRENT_DS	(TI_FLAGS + TI_FLAG_BYTE_CURRENT_DS)
 #define TI_FPDEPTH	(TI_FLAGS + TI_FLAG_BYTE_FPDEPTH)
 #define TI_WSAVED	(TI_FLAGS + TI_FLAG_BYTE_WSAVED)
+#define TI_SYS_NOERROR	(TI_FLAGS + TI_FLAG_BYTE_NOERROR)
 #define TI_FPSAVED	0x00000010
 #define TI_KSP		0x00000018
 #define TI_FAULT_ADDR	0x00000020
@@ -84,7 +84,7 @@ struct thread_info {
 #define TI_EXEC_DOMAIN	0x00000030
 #define TI_PRE_COUNT	0x00000038
 #define TI_NEW_CHILD	0x0000003c
-#define TI_SYS_NOERROR	0x0000003d
+#define TI_CURRENT_DS	0x0000003d
 #define TI_CPU		0x0000003e
 #define TI_UTRAPS	0x00000040
 #define TI_REG_WINDOW	0x00000048
@@ -121,7 +121,7 @@ struct thread_info {
 #define INIT_THREAD_INFO(tsk)				\
 {							\
 	.task		=	&tsk,			\
-	.flags		= ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT,	\
+	.current_ds	=	ASI_P,			\
 	.exec_domain	=	&default_exec_domain,	\
 	.preempt_count	=	INIT_PREEMPT_COUNT,	\
 	.restart_block	= {				\
@@ -153,13 +153,12 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define set_thread_wstate(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE] = (val))
 #define get_thread_cwp()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP])
 #define set_thread_cwp(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP] = (val))
-#define get_thread_current_ds()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS])
-#define set_thread_current_ds(val)	(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS] = (val))
+#define get_thread_noerror()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_NOERROR])
+#define set_thread_noerror(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_NOERROR] = (val))
 #define get_thread_fpdepth()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH])
 #define set_thread_fpdepth(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH] = (val))
 #define get_thread_wsaved()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED])
 #define set_thread_wsaved(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED] = (val))
-
 #endif /* !(__ASSEMBLY__) */
 
 /*
diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h
index 73083e1..e562d3c 100644
--- a/arch/sparc/include/asm/uaccess_64.h
+++ b/arch/sparc/include/asm/uaccess_64.h
@@ -38,14 +38,14 @@
 #define VERIFY_READ	0
 #define VERIFY_WRITE	1
 
-#define get_fs() ((mm_segment_t) { get_thread_current_ds() })
+#define get_fs() ((mm_segment_t){(current_thread_info()->current_ds)})
 #define get_ds() (KERNEL_DS)
 
 #define segment_eq(a,b)  ((a).seg == (b).seg)
 
 #define set_fs(val)								\
 do {										\
-	set_thread_current_ds((val).seg);					\
+	current_thread_info()->current_ds =(val).seg;				\
 	__asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg));	\
 } while(0)
 
diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h
index 0ecea6e..497386a 100644
--- a/arch/sparc/include/asm/unistd.h
+++ b/arch/sparc/include/asm/unistd.h
@@ -45,7 +45,9 @@
 #define __ARCH_WANT_COMPAT_SYS_TIME
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_COMPAT_SYS_SENDFILE
+#define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL
 #endif
+#define __ARCH_WANT_SYS_EXECVE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/sparc/include/uapi/asm/ioctls.h b/arch/sparc/include/uapi/asm/ioctls.h
index 9155f70..897d172 100644
--- a/arch/sparc/include/uapi/asm/ioctls.h
+++ b/arch/sparc/include/uapi/asm/ioctls.h
@@ -21,6 +21,9 @@
 #define TCSETSF2	_IOW('T', 15, struct termios2)
 #define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCVHANGUP	_IO('T', 0x37)
+#define TIOCGPKT	_IOR('T', 0x38, int) /* Get packet mode state */
+#define TIOCGPTLCK	_IOR('T', 0x39, int) /* Get Pty lock state */
+#define TIOCGEXCL	_IOR('T', 0x40, int) /* Get exclusive mode state */
 
 /* Note that all the ioctls that are not available in Linux have a 
  * double underscore on the front to: a) avoid some programs to
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
index bea1568..c83a937 100644
--- a/arch/sparc/include/uapi/asm/socket.h
+++ b/arch/sparc/include/uapi/asm/socket.h
@@ -41,6 +41,7 @@
 
 #define SO_ATTACH_FILTER	0x001a
 #define SO_DETACH_FILTER        0x001b
+#define SO_GET_FILTER		SO_ATTACH_FILTER
 
 #define SO_PEERNAME		0x001c
 #define SO_TIMESTAMP		0x001d
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index dcaa1cf..21fd1a8 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -806,23 +806,10 @@ sys_nis_syscall:
 	call	c_sys_nis_syscall
 	 mov	%l5, %o7
 
-	.align	4
-	.globl	sys_execve
-sys_execve:
-	mov	%o7, %l5
-	add	%sp, STACKFRAME_SZ, %o0		! pt_regs *regs arg
-	call	sparc_execve
-	 mov	%l5, %o7
-
-	.globl	sunos_execv
 sunos_execv:
-	st	%g0, [%sp + STACKFRAME_SZ + PT_I2]
-
-	call	sparc_execve
-	 add	%sp, STACKFRAME_SZ, %o0
-
-	b	ret_sys_call
-	 ld	[%sp + STACKFRAME_SZ + PT_I0], %o0
+	.globl	sunos_execv
+	b	sys_execve
+	 clr	%i2
 
 	.align	4
 	.globl	sys_sparc_pipe
@@ -959,17 +946,9 @@ flush_patch_four:
         .align  4
 linux_sparc_ni_syscall:
 	sethi   %hi(sys_ni_syscall), %l7
-	b       syscall_is_too_hard
+	b       do_syscall
 	 or     %l7, %lo(sys_ni_syscall), %l7
 
-linux_fast_syscall:
-	andn	%l7, 3, %l7
-	mov	%i0, %o0
-	mov	%i1, %o1
-	mov 	%i2, %o2
-	jmpl	%l7 + %g0, %g0
-	 mov	%i3, %o3
-
 linux_syscall_trace:
 	add	%sp, STACKFRAME_SZ, %o0
 	call	syscall_trace
@@ -991,6 +970,23 @@ ret_from_fork:
 	b	ret_sys_call
 	 ld	[%sp + STACKFRAME_SZ + PT_I0], %o0
 
+	.globl	ret_from_kernel_thread
+ret_from_kernel_thread:
+	call	schedule_tail
+	 ld	[%g3 + TI_TASK], %o0
+	ld	[%sp + STACKFRAME_SZ + PT_G1], %l0
+	call	%l0
+	 ld	[%sp + STACKFRAME_SZ + PT_G2], %o0
+	rd	%psr, %l1
+	ld	[%sp + STACKFRAME_SZ + PT_PSR], %l0
+	andn	%l0, PSR_CWP, %l0
+	nop
+	and	%l1, PSR_CWP, %l1
+	or	%l0, %l1, %l0
+	st	%l0, [%sp + STACKFRAME_SZ + PT_PSR]
+	b	ret_sys_call
+	 mov	0, %o0
+
 	/* Linux native system calls enter here... */
 	.align	4
 	.globl	linux_sparc_syscall
@@ -1002,11 +998,8 @@ linux_sparc_syscall:
 	bgeu	linux_sparc_ni_syscall
 	 sll	%g1, 2, %l4
 	ld	[%l7 + %l4], %l7
-	andcc	%l7, 1, %g0
-	bne	linux_fast_syscall
-	 /* Just do first insn from SAVE_ALL in the delay slot */
 
-syscall_is_too_hard:
+do_syscall:
 	SAVE_ALL_HEAD
 	 rd	%wim, %l3
 
diff --git a/arch/sparc/kernel/etrap_64.S b/arch/sparc/kernel/etrap_64.S
index 786b185..1276ca2 100644
--- a/arch/sparc/kernel/etrap_64.S
+++ b/arch/sparc/kernel/etrap_64.S
@@ -92,8 +92,10 @@ etrap_save:	save	%g2, -STACK_BIAS, %sp
 		rdpr	%wstate, %g2
 		wrpr	%g0, 0, %canrestore
 		sll	%g2, 3, %g2
+
+		/* Set TI_SYS_FPDEPTH to 1 and clear TI_SYS_NOERROR.  */
 		mov	1, %l5
-		stb	%l5, [%l6 + TI_FPDEPTH]
+		sth	%l5, [%l6 + TI_SYS_NOERROR]
 
 		wrpr	%g3, 0, %otherwin
 		wrpr	%g2, 0, %wstate
@@ -152,7 +154,9 @@ etrap_save:	save	%g2, -STACK_BIAS, %sp
 		add	%l6, TI_FPSAVED + 1, %l4
 		srl	%l5, 1, %l3
 		add	%l5, 2, %l5
-		stb	%l5, [%l6 + TI_FPDEPTH]
+
+		/* Set TI_SYS_FPDEPTH to %l5 and clear TI_SYS_NOERROR.  */
+		sth	%l5, [%l6 + TI_SYS_NOERROR]
 		ba,pt	%xcc, 2b
 		 stb	%g0, [%l4 + %l3]
 		nop
diff --git a/arch/sparc/kernel/pci_impl.h b/arch/sparc/kernel/pci_impl.h
index 918a203..5f68853 100644
--- a/arch/sparc/kernel/pci_impl.h
+++ b/arch/sparc/kernel/pci_impl.h
@@ -88,7 +88,7 @@ struct pci_pbm_info {
 	int				chip_revision;
 
 	/* Name used for top-level resources. */
-	char				*name;
+	const char			*name;
 
 	/* OBP specific information. */
 	struct platform_device		*op;
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c
index 487bffb..be8e862 100644
--- a/arch/sparc/kernel/process_32.c
+++ b/arch/sparc/kernel/process_32.c
@@ -286,8 +286,7 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags,
 	parent_tid_ptr = regs->u_regs[UREG_I2];
 	child_tid_ptr = regs->u_regs[UREG_I4];
 
-	ret = do_fork(clone_flags, stack_start,
-		      regs, stack_size,
+	ret = do_fork(clone_flags, stack_start, stack_size,
 		      (int __user *) parent_tid_ptr,
 		      (int __user *) child_tid_ptr);
 
@@ -316,13 +315,13 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags,
  * XXX See comment above sys_vfork in sparc64. todo.
  */
 extern void ret_from_fork(void);
+extern void ret_from_kernel_thread(void);
 
 int copy_thread(unsigned long clone_flags, unsigned long sp,
-		unsigned long unused,
-		struct task_struct *p, struct pt_regs *regs)
+		unsigned long arg, struct task_struct *p)
 {
 	struct thread_info *ti = task_thread_info(p);
-	struct pt_regs *childregs;
+	struct pt_regs *childregs, *regs = current_pt_regs();
 	char *new_stack;
 
 #ifndef CONFIG_SMP
@@ -336,16 +335,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 	}
 
 	/*
-	 *  p->thread_info         new_stack   childregs
-	 *  !                      !           !             {if(PSR_PS) }
-	 *  V                      V (stk.fr.) V  (pt_regs)  { (stk.fr.) }
-	 *  +----- - - - - - ------+===========+============={+==========}+
+	 *  p->thread_info         new_stack   childregs stack bottom
+	 *  !                      !           !             !
+	 *  V                      V (stk.fr.) V  (pt_regs)  V
+	 *  +----- - - - - - ------+===========+=============+
 	 */
 	new_stack = task_stack_page(p) + THREAD_SIZE;
-	if (regs->psr & PSR_PS)
-		new_stack -= STACKFRAME_SZ;
 	new_stack -= STACKFRAME_SZ + TRACEREG_SZ;
-	memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ);
 	childregs = (struct pt_regs *) (new_stack + STACKFRAME_SZ);
 
 	/*
@@ -356,55 +352,58 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 	 * Thus, kpsr|=PSR_PIL.
 	 */
 	ti->ksp = (unsigned long) new_stack;
+	p->thread.kregs = childregs;
+
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		extern int nwindows;
+		unsigned long psr;
+		memset(new_stack, 0, STACKFRAME_SZ + TRACEREG_SZ);
+		p->thread.flags |= SPARC_FLAG_KTHREAD;
+		p->thread.current_ds = KERNEL_DS;
+		ti->kpc = (((unsigned long) ret_from_kernel_thread) - 0x8);
+		childregs->u_regs[UREG_G1] = sp; /* function */
+		childregs->u_regs[UREG_G2] = arg;
+		psr = childregs->psr = get_psr();
+		ti->kpsr = psr | PSR_PIL;
+		ti->kwim = 1 << (((psr & PSR_CWP) + 1) % nwindows);
+		return 0;
+	}
+	memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ);
+	childregs->u_regs[UREG_FP] = sp;
+	p->thread.flags &= ~SPARC_FLAG_KTHREAD;
+	p->thread.current_ds = USER_DS;
 	ti->kpc = (((unsigned long) ret_from_fork) - 0x8);
 	ti->kpsr = current->thread.fork_kpsr | PSR_PIL;
 	ti->kwim = current->thread.fork_kwim;
 
-	if(regs->psr & PSR_PS) {
-		extern struct pt_regs fake_swapper_regs;
+	if (sp != regs->u_regs[UREG_FP]) {
+		struct sparc_stackf __user *childstack;
+		struct sparc_stackf __user *parentstack;
 
-		p->thread.kregs = &fake_swapper_regs;
-		new_stack += STACKFRAME_SZ + TRACEREG_SZ;
-		childregs->u_regs[UREG_FP] = (unsigned long) new_stack;
-		p->thread.flags |= SPARC_FLAG_KTHREAD;
-		p->thread.current_ds = KERNEL_DS;
-		memcpy(new_stack, (void *)regs->u_regs[UREG_FP], STACKFRAME_SZ);
-		childregs->u_regs[UREG_G6] = (unsigned long) ti;
-	} else {
-		p->thread.kregs = childregs;
-		childregs->u_regs[UREG_FP] = sp;
-		p->thread.flags &= ~SPARC_FLAG_KTHREAD;
-		p->thread.current_ds = USER_DS;
-
-		if (sp != regs->u_regs[UREG_FP]) {
-			struct sparc_stackf __user *childstack;
-			struct sparc_stackf __user *parentstack;
-
-			/*
-			 * This is a clone() call with supplied user stack.
-			 * Set some valid stack frames to give to the child.
-			 */
-			childstack = (struct sparc_stackf __user *)
-				(sp & ~0xfUL);
-			parentstack = (struct sparc_stackf __user *)
-				regs->u_regs[UREG_FP];
+		/*
+		 * This is a clone() call with supplied user stack.
+		 * Set some valid stack frames to give to the child.
+		 */
+		childstack = (struct sparc_stackf __user *)
+			(sp & ~0xfUL);
+		parentstack = (struct sparc_stackf __user *)
+			regs->u_regs[UREG_FP];
 
 #if 0
-			printk("clone: parent stack:\n");
-			show_stackframe(parentstack);
+		printk("clone: parent stack:\n");
+		show_stackframe(parentstack);
 #endif
 
-			childstack = clone_stackframe(childstack, parentstack);
-			if (!childstack)
-				return -EFAULT;
+		childstack = clone_stackframe(childstack, parentstack);
+		if (!childstack)
+			return -EFAULT;
 
 #if 0
-			printk("clone: child stack:\n");
-			show_stackframe(childstack);
+		printk("clone: child stack:\n");
+		show_stackframe(childstack);
 #endif
 
-			childregs->u_regs[UREG_FP] = (unsigned long)childstack;
-		}
+		childregs->u_regs[UREG_FP] = (unsigned long)childstack;
 	}
 
 #ifdef CONFIG_SMP
@@ -475,69 +474,6 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
 	return 1;
 }
 
-/*
- * sparc_execve() executes a new program after the asm stub has set
- * things up for us.  This should basically do what I want it to.
- */
-asmlinkage int sparc_execve(struct pt_regs *regs)
-{
-	int error, base = 0;
-	struct filename *filename;
-
-	/* Check for indirect call. */
-	if(regs->u_regs[UREG_G1] == 0)
-		base = 1;
-
-	filename = getname((char __user *)regs->u_regs[base + UREG_I0]);
-	error = PTR_ERR(filename);
-	if(IS_ERR(filename))
-		goto out;
-	error = do_execve(filename->name,
-			  (const char __user *const  __user *)
-			  regs->u_regs[base + UREG_I1],
-			  (const char __user *const  __user *)
-			  regs->u_regs[base + UREG_I2],
-			  regs);
-	putname(filename);
-out:
-	return error;
-}
-
-/*
- * This is the mechanism for creating a new kernel thread.
- *
- * NOTE! Only a kernel-only process(ie the swapper or direct descendants
- * who haven't done an "execve()") should use this: it will work within
- * a system call from a "real" process, but the process memory space will
- * not be freed until both the parent and the child have exited.
- */
-pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	long retval;
-
-	__asm__ __volatile__("mov %4, %%g2\n\t"    /* Set aside fn ptr... */
-			     "mov %5, %%g3\n\t"    /* and arg. */
-			     "mov %1, %%g1\n\t"
-			     "mov %2, %%o0\n\t"    /* Clone flags. */
-			     "mov 0, %%o1\n\t"     /* usp arg == 0 */
-			     "t 0x10\n\t"          /* Linux/Sparc clone(). */
-			     "cmp %%o1, 0\n\t"
-			     "be 1f\n\t"           /* The parent, just return. */
-			     " nop\n\t"            /* Delay slot. */
-			     "jmpl %%g2, %%o7\n\t" /* Call the function. */
-			     " mov %%g3, %%o0\n\t" /* Get back the arg in delay. */
-			     "mov %3, %%g1\n\t"
-			     "t 0x10\n\t"          /* Linux/Sparc exit(). */
-			     /* Notreached by child. */
-			     "1: mov %%o0, %0\n\t" :
-			     "=r" (retval) :
-			     "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED),
-			     "i" (__NR_exit),  "r" (fn), "r" (arg) :
-			     "g1", "g2", "g3", "o0", "o1", "memory", "cc");
-	return retval;
-}
-EXPORT_SYMBOL(kernel_thread);
-
 unsigned long get_wchan(struct task_struct *task)
 {
 	unsigned long pc, fp, bias = 0;
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c
index c6e0c29..cdb80b2 100644
--- a/arch/sparc/kernel/process_64.c
+++ b/arch/sparc/kernel/process_64.c
@@ -601,8 +601,7 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags,
 		child_tid_ptr = (int __user *) regs->u_regs[UREG_I4];
 	}
 
-	ret = do_fork(clone_flags, stack_start,
-		      regs, stack_size,
+	ret = do_fork(clone_flags, stack_start, stack_size,
 		      parent_tid_ptr, child_tid_ptr);
 
 	/* If we get an error and potentially restart the system
@@ -622,64 +621,55 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags,
  * Child  -->  %o0 == parents pid, %o1 == 1
  */
 int copy_thread(unsigned long clone_flags, unsigned long sp,
-		unsigned long unused,
-		struct task_struct *p, struct pt_regs *regs)
+		unsigned long arg, struct task_struct *p)
 {
 	struct thread_info *t = task_thread_info(p);
+	struct pt_regs *regs = current_pt_regs();
 	struct sparc_stackf *parent_sf;
 	unsigned long child_stack_sz;
 	char *child_trap_frame;
-	int kernel_thread;
-
-	kernel_thread = (regs->tstate & TSTATE_PRIV) ? 1 : 0;
-	parent_sf = ((struct sparc_stackf *) regs) - 1;
 
 	/* Calculate offset to stack_frame & pt_regs */
-	child_stack_sz = ((STACKFRAME_SZ + TRACEREG_SZ) +
-			  (kernel_thread ? STACKFRAME_SZ : 0));
+	child_stack_sz = (STACKFRAME_SZ + TRACEREG_SZ);
 	child_trap_frame = (task_stack_page(p) +
 			    (THREAD_SIZE - child_stack_sz));
-	memcpy(child_trap_frame, parent_sf, child_stack_sz);
 
-	t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) |
-				 (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) |
-		(((regs->tstate + 1) & TSTATE_CWP) << TI_FLAG_CWP_SHIFT);
 	t->new_child = 1;
 	t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;
 	t->kregs = (struct pt_regs *) (child_trap_frame +
 				       sizeof(struct sparc_stackf));
 	t->fpsaved[0] = 0;
 
-	if (kernel_thread) {
-		struct sparc_stackf *child_sf = (struct sparc_stackf *)
-			(child_trap_frame + (STACKFRAME_SZ + TRACEREG_SZ));
-
-		/* Zero terminate the stack backtrace.  */
-		child_sf->fp = NULL;
-		t->kregs->u_regs[UREG_FP] =
-		  ((unsigned long) child_sf) - STACK_BIAS;
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		memset(child_trap_frame, 0, child_stack_sz);
+		__thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] = 
+			(current_pt_regs()->tstate + 1) & TSTATE_CWP;
+		t->current_ds = ASI_P;
+		t->kregs->u_regs[UREG_G1] = sp; /* function */
+		t->kregs->u_regs[UREG_G2] = arg;
+		return 0;
+	}
 
-		t->flags |= ((long)ASI_P << TI_FLAG_CURRENT_DS_SHIFT);
-		t->kregs->u_regs[UREG_G6] = (unsigned long) t;
-		t->kregs->u_regs[UREG_G4] = (unsigned long) t->task;
-	} else {
-		if (t->flags & _TIF_32BIT) {
-			sp &= 0x00000000ffffffffUL;
-			regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
-		}
-		t->kregs->u_regs[UREG_FP] = sp;
-		t->flags |= ((long)ASI_AIUS << TI_FLAG_CURRENT_DS_SHIFT);
-		if (sp != regs->u_regs[UREG_FP]) {
-			unsigned long csp;
-
-			csp = clone_stackframe(sp, regs->u_regs[UREG_FP]);
-			if (!csp)
-				return -EFAULT;
-			t->kregs->u_regs[UREG_FP] = csp;
-		}
-		if (t->utraps)
-			t->utraps[0]++;
+	parent_sf = ((struct sparc_stackf *) regs) - 1;
+	memcpy(child_trap_frame, parent_sf, child_stack_sz);
+	if (t->flags & _TIF_32BIT) {
+		sp &= 0x00000000ffffffffUL;
+		regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
 	}
+	t->kregs->u_regs[UREG_FP] = sp;
+	__thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] = 
+		(regs->tstate + 1) & TSTATE_CWP;
+	t->current_ds = ASI_AIUS;
+	if (sp != regs->u_regs[UREG_FP]) {
+		unsigned long csp;
+
+		csp = clone_stackframe(sp, regs->u_regs[UREG_FP]);
+		if (!csp)
+			return -EFAULT;
+		t->kregs->u_regs[UREG_FP] = csp;
+	}
+	if (t->utraps)
+		t->utraps[0]++;
 
 	/* Set the return value for the child. */
 	t->kregs->u_regs[UREG_I0] = current->pid;
@@ -694,45 +684,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 	return 0;
 }
 
-/*
- * This is the mechanism for creating a new kernel thread.
- *
- * NOTE! Only a kernel-only process(ie the swapper or direct descendants
- * who haven't done an "execve()") should use this: it will work within
- * a system call from a "real" process, but the process memory space will
- * not be freed until both the parent and the child have exited.
- */
-pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	long retval;
-
-	/* If the parent runs before fn(arg) is called by the child,
-	 * the input registers of this function can be clobbered.
-	 * So we stash 'fn' and 'arg' into global registers which
-	 * will not be modified by the parent.
-	 */
-	__asm__ __volatile__("mov %4, %%g2\n\t"	   /* Save FN into global */
-			     "mov %5, %%g3\n\t"	   /* Save ARG into global */
-			     "mov %1, %%g1\n\t"	   /* Clone syscall nr. */
-			     "mov %2, %%o0\n\t"	   /* Clone flags. */
-			     "mov 0, %%o1\n\t"	   /* usp arg == 0 */
-			     "t 0x6d\n\t"	   /* Linux/Sparc clone(). */
-			     "brz,a,pn %%o1, 1f\n\t" /* Parent, just return. */
-			     " mov %%o0, %0\n\t"
-			     "jmpl %%g2, %%o7\n\t"   /* Call the function. */
-			     " mov %%g3, %%o0\n\t"   /* Set arg in delay. */
-			     "mov %3, %%g1\n\t"
-			     "t 0x6d\n\t"	   /* Linux/Sparc exit(). */
-			     /* Notreached by child. */
-			     "1:" :
-			     "=r" (retval) :
-			     "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED),
-			     "i" (__NR_exit),  "r" (fn), "r" (arg) :
-			     "g1", "g2", "g3", "o0", "o1", "memory", "cc");
-	return retval;
-}
-EXPORT_SYMBOL(kernel_thread);
-
 typedef struct {
 	union {
 		unsigned int	pr_regs[32];
@@ -799,41 +750,6 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
 }
 EXPORT_SYMBOL(dump_fpu);
 
-/*
- * sparc_execve() executes a new program after the asm stub has set
- * things up for us.  This should basically do what I want it to.
- */
-asmlinkage int sparc_execve(struct pt_regs *regs)
-{
-	int error, base = 0;
-	struct filename *filename;
-
-	/* User register window flush is done by entry.S */
-
-	/* Check for indirect call. */
-	if (regs->u_regs[UREG_G1] == 0)
-		base = 1;
-
-	filename = getname((char __user *)regs->u_regs[base + UREG_I0]);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-	error = do_execve(filename->name,
-			  (const char __user *const __user *)
-			  regs->u_regs[base + UREG_I1],
-			  (const char __user *const __user *)
-			  regs->u_regs[base + UREG_I2], regs);
-	putname(filename);
-	if (!error) {
-		fprs_write(0);
-		current_thread_info()->xfsr[0] = 0;
-		current_thread_info()->fpsaved[0] = 0;
-		regs->tstate &= ~TSTATE_PEF;
-	}
-out:
-	return error;
-}
-
 unsigned long get_wchan(struct task_struct *task)
 {
 	unsigned long pc, fp, bias = 0;
diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c
index c323981..4a4cdc6 100644
--- a/arch/sparc/kernel/sys_sparc32.c
+++ b/arch/sparc/kernel/sys_sparc32.c
@@ -211,20 +211,6 @@ asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2)
 	return sys_sysfs(option, arg1, arg2);
 }
 
-asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval)
-{
-	struct timespec t;
-	int ret;
-	mm_segment_t old_fs = get_fs ();
-	
-	set_fs (KERNEL_DS);
-	ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t);
-	set_fs (old_fs);
-	if (put_compat_timespec(&t, interval))
-		return -EFAULT;
-	return ret;
-}
-
 asmlinkage long compat_sys_rt_sigprocmask(int how,
 					  compat_sigset_t __user *set,
 					  compat_sigset_t __user *oset,
@@ -396,42 +382,6 @@ asmlinkage long compat_sys_rt_sigaction(int sig,
         return ret;
 }
 
-/*
- * sparc32_execve() executes a new program after the asm stub has set
- * things up for us.  This should basically do what I want it to.
- */
-asmlinkage long sparc32_execve(struct pt_regs *regs)
-{
-	int error, base = 0;
-	struct filename *filename;
-
-	/* User register window flush is done by entry.S */
-
-	/* Check for indirect call. */
-	if ((u32)regs->u_regs[UREG_G1] == 0)
-		base = 1;
-
-	filename = getname(compat_ptr(regs->u_regs[base + UREG_I0]));
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-
-	error = compat_do_execve(filename->name,
-				 compat_ptr(regs->u_regs[base + UREG_I1]),
-				 compat_ptr(regs->u_regs[base + UREG_I2]), regs);
-
-	putname(filename);
-
-	if (!error) {
-		fprs_write(0);
-		current_thread_info()->xfsr[0] = 0;
-		current_thread_info()->fpsaved[0] = 0;
-		regs->tstate &= ~TSTATE_PEF;
-	}
-out:
-	return error;
-}
-
 #ifdef CONFIG_MODULES
 
 asmlinkage long sys32_init_module(void __user *umod, u32 len,
diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c
index 0c9b31b..2da0bdc 100644
--- a/arch/sparc/kernel/sys_sparc_32.c
+++ b/arch/sparc/kernel/sys_sparc_32.c
@@ -34,11 +34,9 @@ asmlinkage unsigned long sys_getpagesize(void)
 	return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */
 }
 
-#define COLOUR_ALIGN(addr)      (((addr)+SHMLBA-1)&~(SHMLBA-1))
-
 unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
 {
-	struct vm_area_struct * vmm;
+	struct vm_unmapped_area_info info;
 
 	if (flags & MAP_FIXED) {
 		/* We do not accept a shared mapping if it would violate
@@ -56,21 +54,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
 	if (!addr)
 		addr = TASK_UNMAPPED_BASE;
 
-	if (flags & MAP_SHARED)
-		addr = COLOUR_ALIGN(addr);
-	else
-		addr = PAGE_ALIGN(addr);
-
-	for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
-		/* At this point:  (!vmm || addr < vmm->vm_end). */
-		if (TASK_SIZE - PAGE_SIZE - len < addr)
-			return -ENOMEM;
-		if (!vmm || addr + len <= vmm->vm_start)
-			return addr;
-		addr = vmm->vm_end;
-		if (flags & MAP_SHARED)
-			addr = COLOUR_ALIGN(addr);
-	}
+	info.flags = 0;
+	info.length = len;
+	info.low_limit = addr;
+	info.high_limit = TASK_SIZE;
+	info.align_mask = (flags & MAP_SHARED) ?
+		(PAGE_MASK & (SHMLBA - 1)) : 0;
+	info.align_offset = pgoff << PAGE_SHIFT;
+	return vm_unmapped_area(&info);
 }
 
 /*
@@ -258,27 +249,3 @@ out:
 	up_read(&uts_sem);
 	return err;
 }
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	long __res;
-	register long __g1 __asm__ ("g1") = __NR_execve;
-	register long __o0 __asm__ ("o0") = (long)(filename);
-	register long __o1 __asm__ ("o1") = (long)(argv);
-	register long __o2 __asm__ ("o2") = (long)(envp);
-	asm volatile ("t 0x10\n\t"
-		      "bcc 1f\n\t"
-		      "mov %%o0, %0\n\t"
-		      "sub %%g0, %%o0, %0\n\t"
-		      "1:\n\t"
-		      : "=r" (__res), "=&r" (__o0)
-		      : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1)
-		      : "cc");
-	return __res;
-}
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index 878ef3d..708bc29 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -75,7 +75,7 @@ static inline int invalid_64bit_range(unsigned long addr, unsigned long len)
  *    the spitfire/niagara VA-hole.
  */
 
-static inline unsigned long COLOUR_ALIGN(unsigned long addr,
+static inline unsigned long COLOR_ALIGN(unsigned long addr,
 					 unsigned long pgoff)
 {
 	unsigned long base = (addr+SHMLBA-1)&~(SHMLBA-1);
@@ -84,24 +84,13 @@ static inline unsigned long COLOUR_ALIGN(unsigned long addr,
 	return base + off;
 }
 
-static inline unsigned long COLOUR_ALIGN_DOWN(unsigned long addr,
-					      unsigned long pgoff)
-{
-	unsigned long base = addr & ~(SHMLBA-1);
-	unsigned long off = (pgoff<<PAGE_SHIFT) & (SHMLBA-1);
-
-	if (base + off <= addr)
-		return base + off;
-	return base - off;
-}
-
 unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct * vma;
 	unsigned long task_size = TASK_SIZE;
-	unsigned long start_addr;
 	int do_color_align;
+	struct vm_unmapped_area_info info;
 
 	if (flags & MAP_FIXED) {
 		/* We do not accept a shared mapping if it would violate
@@ -124,7 +113,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
 
 	if (addr) {
 		if (do_color_align)
-			addr = COLOUR_ALIGN(addr, pgoff);
+			addr = COLOR_ALIGN(addr, pgoff);
 		else
 			addr = PAGE_ALIGN(addr);
 
@@ -134,50 +123,22 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
 			return addr;
 	}
 
-	if (len > mm->cached_hole_size) {
-	        start_addr = addr = mm->free_area_cache;
-	} else {
-	        start_addr = addr = TASK_UNMAPPED_BASE;
-	        mm->cached_hole_size = 0;
+	info.flags = 0;
+	info.length = len;
+	info.low_limit = TASK_UNMAPPED_BASE;
+	info.high_limit = min(task_size, VA_EXCLUDE_START);
+	info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
+	info.align_offset = pgoff << PAGE_SHIFT;
+	addr = vm_unmapped_area(&info);
+
+	if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) {
+		VM_BUG_ON(addr != -ENOMEM);
+		info.low_limit = VA_EXCLUDE_END;
+		info.high_limit = task_size;
+		addr = vm_unmapped_area(&info);
 	}
 
-	task_size -= len;
-
-full_search:
-	if (do_color_align)
-		addr = COLOUR_ALIGN(addr, pgoff);
-	else
-		addr = PAGE_ALIGN(addr);
-
-	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
-		/* At this point:  (!vma || addr < vma->vm_end). */
-		if (addr < VA_EXCLUDE_START &&
-		    (addr + len) >= VA_EXCLUDE_START) {
-			addr = VA_EXCLUDE_END;
-			vma = find_vma(mm, VA_EXCLUDE_END);
-		}
-		if (unlikely(task_size < addr)) {
-			if (start_addr != TASK_UNMAPPED_BASE) {
-				start_addr = addr = TASK_UNMAPPED_BASE;
-				mm->cached_hole_size = 0;
-				goto full_search;
-			}
-			return -ENOMEM;
-		}
-		if (likely(!vma || addr + len <= vma->vm_start)) {
-			/*
-			 * Remember the place where we stopped the search:
-			 */
-			mm->free_area_cache = addr + len;
-			return addr;
-		}
-		if (addr + mm->cached_hole_size < vma->vm_start)
-		        mm->cached_hole_size = vma->vm_start - addr;
-
-		addr = vma->vm_end;
-		if (do_color_align)
-			addr = COLOUR_ALIGN(addr, pgoff);
-	}
+	return addr;
 }
 
 unsigned long
@@ -190,6 +151,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	unsigned long task_size = STACK_TOP32;
 	unsigned long addr = addr0;
 	int do_color_align;
+	struct vm_unmapped_area_info info;
 
 	/* This should only ever run for 32-bit processes.  */
 	BUG_ON(!test_thread_flag(TIF_32BIT));
@@ -214,7 +176,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	/* requesting a specific address */
 	if (addr) {
 		if (do_color_align)
-			addr = COLOUR_ALIGN(addr, pgoff);
+			addr = COLOR_ALIGN(addr, pgoff);
 		else
 			addr = PAGE_ALIGN(addr);
 
@@ -224,73 +186,27 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 			return addr;
 	}
 
-	/* check if free_area_cache is useful for us */
-	if (len <= mm->cached_hole_size) {
- 	        mm->cached_hole_size = 0;
- 		mm->free_area_cache = mm->mmap_base;
- 	}
-
-	/* either no address requested or can't fit in requested address hole */
-	addr = mm->free_area_cache;
-	if (do_color_align) {
-		unsigned long base = COLOUR_ALIGN_DOWN(addr-len, pgoff);
-
-		addr = base + len;
-	}
-
-	/* make sure it can fit in the remaining address space */
-	if (likely(addr > len)) {
-		vma = find_vma(mm, addr-len);
-		if (!vma || addr <= vma->vm_start) {
-			/* remember the address as a hint for next time */
-			return (mm->free_area_cache = addr-len);
-		}
-	}
-
-	if (unlikely(mm->mmap_base < len))
-		goto bottomup;
-
-	addr = mm->mmap_base-len;
-	if (do_color_align)
-		addr = COLOUR_ALIGN_DOWN(addr, pgoff);
-
-	do {
-		/*
-		 * Lookup failure means no vma is above this address,
-		 * else if new region fits below vma->vm_start,
-		 * return with success:
-		 */
-		vma = find_vma(mm, addr);
-		if (likely(!vma || addr+len <= vma->vm_start)) {
-			/* remember the address as a hint for next time */
-			return (mm->free_area_cache = addr);
-		}
-
- 		/* remember the largest hole we saw so far */
- 		if (addr + mm->cached_hole_size < vma->vm_start)
- 		        mm->cached_hole_size = vma->vm_start - addr;
+	info.flags = VM_UNMAPPED_AREA_TOPDOWN;
+	info.length = len;
+	info.low_limit = PAGE_SIZE;
+	info.high_limit = mm->mmap_base;
+	info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
+	info.align_offset = pgoff << PAGE_SHIFT;
+	addr = vm_unmapped_area(&info);
 
-		/* try just below the current vma->vm_start */
-		addr = vma->vm_start-len;
-		if (do_color_align)
-			addr = COLOUR_ALIGN_DOWN(addr, pgoff);
-	} while (likely(len < vma->vm_start));
-
-bottomup:
 	/*
 	 * A failed mmap() very likely causes application failure,
 	 * so fall back to the bottom-up function here. This scenario
 	 * can happen with large stack limits and large mmap()
 	 * allocations.
 	 */
-	mm->cached_hole_size = ~0UL;
-  	mm->free_area_cache = TASK_UNMAPPED_BASE;
-	addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
-	/*
-	 * Restore the topdown base:
-	 */
-	mm->free_area_cache = mm->mmap_base;
-	mm->cached_hole_size = ~0UL;
+	if (addr & ~PAGE_MASK) {
+		VM_BUG_ON(addr != -ENOMEM);
+		info.flags = 0;
+		info.low_limit = TASK_UNMAPPED_BASE;
+		info.high_limit = STACK_TOP32;
+		addr = vm_unmapped_area(&info);
+	}
 
 	return addr;
 }
@@ -730,28 +646,6 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
 	return ret;
 }
 
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	long __res;
-	register long __g1 __asm__ ("g1") = __NR_execve;
-	register long __o0 __asm__ ("o0") = (long)(filename);
-	register long __o1 __asm__ ("o1") = (long)(argv);
-	register long __o2 __asm__ ("o2") = (long)(envp);
-	asm volatile ("t 0x6d\n\t"
-		      "sub %%g0, %%o0, %0\n\t"
-		      "movcc %%xcc, %%o0, %0\n\t"
-		      : "=r" (__res), "=&r" (__o0)
-		      : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1)
-		      : "cc");
-	return __res;
-}
-
 asmlinkage long sys_kern_features(void)
 {
 	return KERN_FEATURE_MIXED_MODE_STACK;
diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S
index 7f5f65d..2ef41e6 100644
--- a/arch/sparc/kernel/syscalls.S
+++ b/arch/sparc/kernel/syscalls.S
@@ -1,23 +1,19 @@
 	/* SunOS's execv() call only specifies the argv argument, the
 	 * environment settings are the same as the calling processes.
 	 */
-sys_execve:
-	sethi	%hi(sparc_execve), %g1
-	ba,pt	%xcc, execve_merge
-	 or	%g1, %lo(sparc_execve), %g1
+sys64_execve:
+	set	sys_execve, %g1
+	jmpl	%g1, %g0
+	 flushw
 
 #ifdef CONFIG_COMPAT
 sunos_execv:
-	stx	%g0, [%sp + PTREGS_OFF + PT_V9_I2]
+	mov	%g0, %o2
 sys32_execve:
-	sethi	%hi(sparc32_execve), %g1
-	or	%g1, %lo(sparc32_execve), %g1
-#endif
-
-execve_merge:
-	flushw
+	set	compat_sys_execve, %g1
 	jmpl	%g1, %g0
-	 add	%sp, PTREGS_OFF, %o0
+	 flushw
+#endif
 
 	.align	32
 sys_sparc_pipe:
@@ -112,11 +108,16 @@ sys_clone:
 ret_from_syscall:
 	/* Clear current_thread_info()->new_child. */
 	stb	%g0, [%g6 + TI_NEW_CHILD]
-	ldx	[%g6 + TI_FLAGS], %l0
 	call	schedule_tail
 	 mov	%g7, %o0
+	ldx	[%sp + PTREGS_OFF + PT_V9_I0], %o0
+	brnz,pt	%o0, ret_sys_call
+	 ldx	[%g6 + TI_FLAGS], %l0
+	ldx	[%sp + PTREGS_OFF + PT_V9_G1], %l1
+	call	%l1
+	 ldx	[%sp + PTREGS_OFF + PT_V9_G2], %o0
 	ba,pt	%xcc, ret_sys_call
-	 ldx	[%sp + PTREGS_OFF + PT_V9_I0], %o0
+	 mov	0, %o0
 
 	.globl	sparc_exit
 	.type	sparc_exit,#function
@@ -222,7 +223,6 @@ ret_sys_call:
 	ldx	[%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
 
 2:
-	stb	%g0, [%g6 + TI_SYS_NOERROR]
 	/* System call success, clear Carry condition code. */
 	andn	%g3, %g2, %g3
 3:
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index 1c9af9f..ebb7f5f 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -107,7 +107,7 @@ sys_call_table:
 /*40*/	.word sys_newlstat, sys_dup, sys_sparc_pipe, sys_times, sys_nis_syscall
 	.word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid
 /*50*/	.word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl
-	.word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve
+	.word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys64_execve
 /*60*/	.word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize
 	.word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall
 /*70*/	.word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_64_munmap, sys_mprotect
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c
index b66a779..e7ecf15 100644
--- a/arch/sparc/kernel/traps_64.c
+++ b/arch/sparc/kernel/traps_64.c
@@ -2688,8 +2688,8 @@ void __init trap_init(void)
 		     TI_PRE_COUNT != offsetof(struct thread_info,
 					      preempt_count) ||
 		     TI_NEW_CHILD != offsetof(struct thread_info, new_child) ||
-		     TI_SYS_NOERROR != offsetof(struct thread_info,
-						syscall_noerror) ||
+		     TI_CURRENT_DS != offsetof(struct thread_info,
+						current_ds) ||
 		     TI_RESTART_BLOCK != offsetof(struct thread_info,
 						  restart_block) ||
 		     TI_KUNA_REGS != offsetof(struct thread_info,
diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c
index f76f83d..d2b5944 100644
--- a/arch/sparc/mm/hugetlbpage.c
+++ b/arch/sparc/mm/hugetlbpage.c
@@ -30,55 +30,28 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *filp,
 							unsigned long pgoff,
 							unsigned long flags)
 {
-	struct mm_struct *mm = current->mm;
-	struct vm_area_struct * vma;
 	unsigned long task_size = TASK_SIZE;
-	unsigned long start_addr;
+	struct vm_unmapped_area_info info;
 
 	if (test_thread_flag(TIF_32BIT))
 		task_size = STACK_TOP32;
-	if (unlikely(len >= VA_EXCLUDE_START))
-		return -ENOMEM;
 
-	if (len > mm->cached_hole_size) {
-	        start_addr = addr = mm->free_area_cache;
-	} else {
-	        start_addr = addr = TASK_UNMAPPED_BASE;
-	        mm->cached_hole_size = 0;
+	info.flags = 0;
+	info.length = len;
+	info.low_limit = TASK_UNMAPPED_BASE;
+	info.high_limit = min(task_size, VA_EXCLUDE_START);
+	info.align_mask = PAGE_MASK & ~HPAGE_MASK;
+	info.align_offset = 0;
+	addr = vm_unmapped_area(&info);
+
+	if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) {
+		VM_BUG_ON(addr != -ENOMEM);
+		info.low_limit = VA_EXCLUDE_END;
+		info.high_limit = task_size;
+		addr = vm_unmapped_area(&info);
 	}
 
-	task_size -= len;
-
-full_search:
-	addr = ALIGN(addr, HPAGE_SIZE);
-
-	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
-		/* At this point:  (!vma || addr < vma->vm_end). */
-		if (addr < VA_EXCLUDE_START &&
-		    (addr + len) >= VA_EXCLUDE_START) {
-			addr = VA_EXCLUDE_END;
-			vma = find_vma(mm, VA_EXCLUDE_END);
-		}
-		if (unlikely(task_size < addr)) {
-			if (start_addr != TASK_UNMAPPED_BASE) {
-				start_addr = addr = TASK_UNMAPPED_BASE;
-				mm->cached_hole_size = 0;
-				goto full_search;
-			}
-			return -ENOMEM;
-		}
-		if (likely(!vma || addr + len <= vma->vm_start)) {
-			/*
-			 * Remember the place where we stopped the search:
-			 */
-			mm->free_area_cache = addr + len;
-			return addr;
-		}
-		if (addr + mm->cached_hole_size < vma->vm_start)
-		        mm->cached_hole_size = vma->vm_start - addr;
-
-		addr = ALIGN(vma->vm_end, HPAGE_SIZE);
-	}
+	return addr;
 }
 
 static unsigned long
@@ -87,71 +60,34 @@ hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 				  const unsigned long pgoff,
 				  const unsigned long flags)
 {
-	struct vm_area_struct *vma;
 	struct mm_struct *mm = current->mm;
 	unsigned long addr = addr0;
+	struct vm_unmapped_area_info info;
 
 	/* This should only ever run for 32-bit processes.  */
 	BUG_ON(!test_thread_flag(TIF_32BIT));
 
-	/* check if free_area_cache is useful for us */
-	if (len <= mm->cached_hole_size) {
- 	        mm->cached_hole_size = 0;
- 		mm->free_area_cache = mm->mmap_base;
- 	}
-
-	/* either no address requested or can't fit in requested address hole */
-	addr = mm->free_area_cache & HPAGE_MASK;
-
-	/* make sure it can fit in the remaining address space */
-	if (likely(addr > len)) {
-		vma = find_vma(mm, addr-len);
-		if (!vma || addr <= vma->vm_start) {
-			/* remember the address as a hint for next time */
-			return (mm->free_area_cache = addr-len);
-		}
-	}
-
-	if (unlikely(mm->mmap_base < len))
-		goto bottomup;
-
-	addr = (mm->mmap_base-len) & HPAGE_MASK;
-
-	do {
-		/*
-		 * Lookup failure means no vma is above this address,
-		 * else if new region fits below vma->vm_start,
-		 * return with success:
-		 */
-		vma = find_vma(mm, addr);
-		if (likely(!vma || addr+len <= vma->vm_start)) {
-			/* remember the address as a hint for next time */
-			return (mm->free_area_cache = addr);
-		}
-
- 		/* remember the largest hole we saw so far */
- 		if (addr + mm->cached_hole_size < vma->vm_start)
- 		        mm->cached_hole_size = vma->vm_start - addr;
-
-		/* try just below the current vma->vm_start */
-		addr = (vma->vm_start-len) & HPAGE_MASK;
-	} while (likely(len < vma->vm_start));
+	info.flags = VM_UNMAPPED_AREA_TOPDOWN;
+	info.length = len;
+	info.low_limit = PAGE_SIZE;
+	info.high_limit = mm->mmap_base;
+	info.align_mask = PAGE_MASK & ~HPAGE_MASK;
+	info.align_offset = 0;
+	addr = vm_unmapped_area(&info);
 
-bottomup:
 	/*
 	 * A failed mmap() very likely causes application failure,
 	 * so fall back to the bottom-up function here. This scenario
 	 * can happen with large stack limits and large mmap()
 	 * allocations.
 	 */
-	mm->cached_hole_size = ~0UL;
-  	mm->free_area_cache = TASK_UNMAPPED_BASE;
-	addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
-	/*
-	 * Restore the topdown base:
-	 */
-	mm->free_area_cache = mm->mmap_base;
-	mm->cached_hole_size = ~0UL;
+	if (addr & ~PAGE_MASK) {
+		VM_BUG_ON(addr != -ENOMEM);
+		info.flags = 0;
+		info.low_limit = TASK_UNMAPPED_BASE;
+		info.high_limit = STACK_TOP32;
+		addr = vm_unmapped_area(&info);
+	}
 
 	return addr;
 }
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 9e28a11..85be1ca 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -624,7 +624,7 @@ static void __init inherit_prom_mappings(void)
 void prom_world(int enter)
 {
 	if (!enter)
-		set_fs((mm_segment_t) { get_thread_current_ds() });
+		set_fs(get_fs());
 
 	__asm__ __volatile__("flushw");
 }
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index 2836870..3109ca6 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -3,6 +3,7 @@
 #include <linux/netdevice.h>
 #include <linux/filter.h>
 #include <linux/cache.h>
+#include <linux/if_vlan.h>
 
 #include <asm/cacheflush.h>
 #include <asm/ptrace.h>
@@ -312,6 +313,12 @@ do {	*prog++ = BR_OPC | WDISP22(OFF);		\
 #define emit_addi(R1, IMM, R3) \
 	*prog++ = (ADD | IMMED | RS1(R1) | S13(IMM) | RD(R3))
 
+#define emit_and(R1, R2, R3) \
+	*prog++ = (AND | RS1(R1) | RS2(R2) | RD(R3))
+
+#define emit_andi(R1, IMM, R3) \
+	*prog++ = (AND | IMMED | RS1(R1) | S13(IMM) | RD(R3))
+
 #define emit_alloc_stack(SZ) \
 	*prog++ = (SUB | IMMED | RS1(SP) | S13(SZ) | RD(SP))
 
@@ -415,6 +422,8 @@ void bpf_jit_compile(struct sk_filter *fp)
 		case BPF_S_ANC_IFINDEX:
 		case BPF_S_ANC_MARK:
 		case BPF_S_ANC_RXHASH:
+		case BPF_S_ANC_VLAN_TAG:
+		case BPF_S_ANC_VLAN_TAG_PRESENT:
 		case BPF_S_ANC_CPU:
 		case BPF_S_ANC_QUEUE:
 		case BPF_S_LD_W_ABS:
@@ -600,6 +609,16 @@ void bpf_jit_compile(struct sk_filter *fp)
 			case BPF_S_ANC_RXHASH:
 				emit_skb_load32(rxhash, r_A);
 				break;
+			case BPF_S_ANC_VLAN_TAG:
+			case BPF_S_ANC_VLAN_TAG_PRESENT:
+				emit_skb_load16(vlan_tci, r_A);
+				if (filter[i].code == BPF_S_ANC_VLAN_TAG) {
+					emit_andi(r_A, VLAN_VID_MASK, r_A);
+				} else {
+					emit_loadimm(VLAN_TAG_PRESENT, r_TMP);
+					emit_and(r_A, r_TMP, r_A);
+				}
+				break;
 
 			case BPF_S_LD_IMM:
 				emit_loadimm(K, r_A);
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 875d008..ea7f61e 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -21,6 +21,8 @@ config TILE
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
 	select GENERIC_CLOCKEVENTS
 	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
+	select GENERIC_KERNEL_EXECVE
 
 # FIXME: investigate whether we need/want these options.
 #	select HAVE_IOREMAP_PROT
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 6948015..b17b9b8 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -34,5 +34,6 @@ generic-y += sockios.h
 generic-y += statfs.h
 generic-y += termbits.h
 generic-y += termios.h
+generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h
index 3063e6f..88f3c22 100644
--- a/arch/tile/include/asm/compat.h
+++ b/arch/tile/include/asm/compat.h
@@ -275,18 +275,14 @@ extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka,
 struct compat_sigaction;
 struct compat_siginfo;
 struct compat_sigaltstack;
-long compat_sys_execve(const char __user *path,
-		       compat_uptr_t __user *argv,
-		       compat_uptr_t __user *envp, struct pt_regs *);
 long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act,
 			     struct compat_sigaction __user *oact,
 			     size_t sigsetsize);
 long compat_sys_rt_sigqueueinfo(int pid, int sig,
 				struct compat_siginfo __user *uinfo);
-long compat_sys_rt_sigreturn(struct pt_regs *);
+long compat_sys_rt_sigreturn(void);
 long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
-			    struct compat_sigaltstack __user *uoss_ptr,
-			    struct pt_regs *);
+			    struct compat_sigaltstack __user *uoss_ptr);
 long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high);
 long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high);
 long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count,
@@ -300,15 +296,8 @@ long compat_sys_sync_file_range2(int fd, unsigned int flags,
 long compat_sys_fallocate(int fd, int mode,
 			  u32 offset_lo, u32 offset_hi,
 			  u32 len_lo, u32 len_hi);
-long compat_sys_sched_rr_get_interval(compat_pid_t pid,
-				      struct compat_timespec __user *interval);
-
-/* These are the intvec_64.S trampolines. */
-long _compat_sys_execve(const char __user *path,
-			const compat_uptr_t __user *argv,
-			const compat_uptr_t __user *envp);
-long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
-			    struct compat_sigaltstack __user *uoss_ptr);
+
+/* Assembly trampoline to avoid clobbering r0. */
 long _compat_sys_rt_sigreturn(void);
 
 #endif /* _ASM_TILE_COMPAT_H */
diff --git a/arch/tile/include/asm/dma-mapping.h b/arch/tile/include/asm/dma-mapping.h
index 4b6247d..f2ff191 100644
--- a/arch/tile/include/asm/dma-mapping.h
+++ b/arch/tile/include/asm/dma-mapping.h
@@ -72,6 +72,7 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
 static inline int
 dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
+	debug_dma_mapping_error(dev, dma_addr);
 	return get_dma_ops(dev)->mapping_error(dev, dma_addr);
 }
 
diff --git a/arch/tile/include/asm/elf.h b/arch/tile/include/asm/elf.h
index f8ccf08..b73e103 100644
--- a/arch/tile/include/asm/elf.h
+++ b/arch/tile/include/asm/elf.h
@@ -148,6 +148,7 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
 #define compat_start_thread(regs, ip, usp) do { \
 		regs->pc = ptr_to_compat_reg((void *)(ip)); \
 		regs->sp = ptr_to_compat_reg((void *)(usp)); \
+		single_step_execve();	\
 	} while (0)
 
 /*
diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h
index 8c4dd9f..2b70dfb 100644
--- a/arch/tile/include/asm/processor.h
+++ b/arch/tile/include/asm/processor.h
@@ -211,6 +211,7 @@ static inline void start_thread(struct pt_regs *regs,
 {
 	regs->pc = pc;
 	regs->sp = usp;
+	single_step_execve();
 }
 
 /* Free all resources held by a thread. */
@@ -219,8 +220,6 @@ static inline void release_thread(struct task_struct *dead_task)
 	/* Nothing for now */
 }
 
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 extern int do_work_pending(struct pt_regs *regs, u32 flags);
 
 
@@ -239,6 +238,9 @@ unsigned long get_wchan(struct task_struct *p);
 #define KSTK_TOP(task)	(task_ksp0(task) - STACK_TOP_DELTA)
 #define task_pt_regs(task) \
   ((struct pt_regs *)(task_ksp0(task) - KSTK_PTREGS_GAP) - 1)
+#define current_pt_regs()                                   \
+  ((struct pt_regs *)((stack_pointer | (THREAD_SIZE - 1)) - \
+                      (KSTK_PTREGS_GAP - 1)) - 1)
 #define task_sp(task)	(task_pt_regs(task)->sp)
 #define task_pc(task)	(task_pt_regs(task)->pc)
 /* Aliases for pc and sp (used in fs/proc/array.c) */
diff --git a/arch/tile/include/asm/switch_to.h b/arch/tile/include/asm/switch_to.h
index 1d48c5f..b8f888c 100644
--- a/arch/tile/include/asm/switch_to.h
+++ b/arch/tile/include/asm/switch_to.h
@@ -68,7 +68,10 @@ extern unsigned long get_switch_to_pc(void);
 /* Support function for forking a new task. */
 void ret_from_fork(void);
 
-/* Called from ret_from_fork() when a new process starts up. */
+/* Support function for forking a new kernel thread. */
+void ret_from_kernel_thread(void *fn, void *arg);
+
+/* Called from ret_from_xxx() when a new process starts up. */
 struct task_struct *sim_notify_fork(struct task_struct *prev);
 
 #endif /* !__ASSEMBLY__ */
diff --git a/arch/tile/include/asm/syscalls.h b/arch/tile/include/asm/syscalls.h
index 06f0464..394c76f 100644
--- a/arch/tile/include/asm/syscalls.h
+++ b/arch/tile/include/asm/syscalls.h
@@ -51,8 +51,7 @@ long sys_cacheflush(unsigned long addr, unsigned long len,
 
 #ifndef __tilegx__
 /* mm/fault.c */
-long sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *);
-long _sys_cmpxchg_badaddr(unsigned long address);
+long sys_cmpxchg_badaddr(unsigned long address);
 #endif
 
 #ifdef CONFIG_COMPAT
@@ -63,14 +62,19 @@ long sys_truncate64(const char __user *path, loff_t length);
 long sys_ftruncate64(unsigned int fd, loff_t length);
 #endif
 
+/* Provide versions of standard syscalls that use current_pt_regs(). */
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+		void __user *parent_tid, void __user *child_tid);
+long sys_rt_sigreturn(void);
+long sys_sigaltstack(const stack_t __user *, stack_t __user *);
+#define sys_clone sys_clone
+#define sys_rt_sigreturn sys_rt_sigreturn
+#define sys_sigaltstack sys_sigaltstack
+
 /* These are the intvec*.S trampolines. */
-long _sys_sigaltstack(const stack_t __user *, stack_t __user *);
 long _sys_rt_sigreturn(void);
 long _sys_clone(unsigned long clone_flags, unsigned long newsp,
 		void __user *parent_tid, void __user *child_tid);
-long _sys_execve(const char __user *filename,
-		 const char __user *const __user *argv,
-		 const char __user *const __user *envp);
 
 #include <asm-generic/syscalls.h>
 
diff --git a/arch/tile/include/asm/unistd.h b/arch/tile/include/asm/unistd.h
index 6e032a0..fe841e7 100644
--- a/arch/tile/include/asm/unistd.h
+++ b/arch/tile/include/asm/unistd.h
@@ -14,6 +14,9 @@
 /* In compat mode, we use sys_llseek() for compat_sys_llseek(). */
 #ifdef CONFIG_COMPAT
 #define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL
 #endif
 #define __ARCH_WANT_SYS_NEWFSTATAT
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c
index d67459b..637fa3a 100644
--- a/arch/tile/kernel/compat.c
+++ b/arch/tile/kernel/compat.c
@@ -76,24 +76,6 @@ long compat_sys_fallocate(int fd, int mode,
 			     ((loff_t)len_hi << 32) | len_lo);
 }
 
-
-
-long compat_sys_sched_rr_get_interval(compat_pid_t pid,
-				      struct compat_timespec __user *interval)
-{
-	struct timespec t;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-
-	set_fs(KERNEL_DS);
-	ret = sys_sched_rr_get_interval(pid,
-					(struct timespec __force __user *)&t);
-	set_fs(old_fs);
-	if (put_compat_timespec(&t, interval))
-		return -EFAULT;
-	return ret;
-}
-
 /* Provide the compat syscall number to call mapping. */
 #undef __SYSCALL
 #define __SYSCALL(nr, call) [nr] = (call),
@@ -102,10 +84,9 @@ long compat_sys_sched_rr_get_interval(compat_pid_t pid,
 #define compat_sys_fadvise64_64 sys32_fadvise64_64
 #define compat_sys_readahead sys32_readahead
 
-/* Call the trampolines to manage pt_regs where necessary. */
-#define compat_sys_execve _compat_sys_execve
-#define compat_sys_sigaltstack _compat_sys_sigaltstack
+/* Call the assembly trampolines where necessary. */
 #define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn
+#undef sys_clone
 #define sys_clone _sys_clone
 
 /*
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c
index 08b4fe1..210a9bb 100644
--- a/arch/tile/kernel/compat_signal.c
+++ b/arch/tile/kernel/compat_signal.c
@@ -197,8 +197,7 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
 }
 
 long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
-			    struct compat_sigaltstack __user *uoss_ptr,
-			    struct pt_regs *regs)
+			    struct compat_sigaltstack __user *uoss_ptr)
 {
 	stack_t uss, uoss;
 	int ret;
@@ -219,7 +218,7 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
 	set_fs(KERNEL_DS);
 	ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL,
 			     (stack_t __user __force *)&uoss,
-			     (unsigned long)compat_ptr(regs->sp));
+			     (unsigned long)compat_ptr(current_pt_regs()->sp));
 	set_fs(seg);
 	if (ret >= 0 && uoss_ptr)  {
 		if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) ||
@@ -232,8 +231,9 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
 }
 
 /* The assembly shim for this function arranges to ignore the return value. */
-long compat_sys_rt_sigreturn(struct pt_regs *regs)
+long compat_sys_rt_sigreturn(void)
 {
+	struct pt_regs *regs = current_pt_regs();
 	struct compat_rt_sigframe __user *frame =
 		(struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
 	sigset_t set;
@@ -248,7 +248,7 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs)
 	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
 		goto badframe;
 
-	if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
+	if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL) != 0)
 		goto badframe;
 
 	return 0;
diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S
index c31637b..f116cb0 100644
--- a/arch/tile/kernel/entry.S
+++ b/arch/tile/kernel/entry.S
@@ -28,17 +28,6 @@ STD_ENTRY(current_text_addr)
 	STD_ENDPROC(current_text_addr)
 
 /*
- * Implement execve().  The i386 code has a note that forking from kernel
- * space results in no copy on write until the execve, so we should be
- * careful not to write to the stack here.
- */
-STD_ENTRY(kernel_execve)
-	moveli TREG_SYSCALL_NR_NAME, __NR_execve
-	swint1
-	jrp lr
-	STD_ENDPROC(kernel_execve)
-
-/*
  * We don't run this function directly, but instead copy it to a page
  * we map into every user process.  See vdso_setup().
  *
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S
index 6943515..f212bf7 100644
--- a/arch/tile/kernel/intvec_32.S
+++ b/arch/tile/kernel/intvec_32.S
@@ -1291,6 +1291,21 @@ STD_ENTRY(ret_from_fork)
 	}
 	STD_ENDPROC(ret_from_fork)
 
+STD_ENTRY(ret_from_kernel_thread)
+	jal     sim_notify_fork
+	jal     schedule_tail
+	FEEDBACK_REENTER(ret_from_fork)
+	{
+	 move   r0, r31
+	 jalr   r30
+	}
+	FEEDBACK_REENTER(ret_from_kernel_thread)
+	{
+	 movei  r30, 0               /* not an NMI */
+	 j      .Lresume_userspace   /* jump into middle of interrupt_return */
+	}
+	STD_ENDPROC(ret_from_kernel_thread)
+
 	/*
 	 * Code for ill interrupt.
 	 */
@@ -1437,15 +1452,6 @@ STD_ENTRY_LOCAL(bad_intr)
 	panic   "Unhandled interrupt %#x: PC %#lx"
 	STD_ENDPROC(bad_intr)
 
-/* Put address of pt_regs in reg and jump. */
-#define PTREGS_SYSCALL(x, reg)                          \
-	STD_ENTRY(_##x);                                \
-	{                                               \
-	 PTREGS_PTR(reg, PTREGS_OFFSET_BASE);           \
-	 j      x                                       \
-	};                                              \
-	STD_ENDPROC(_##x)
-
 /*
  * Special-case sigreturn to not write r0 to the stack on return.
  * This is technically more efficient, but it also avoids difficulties
@@ -1461,12 +1467,9 @@ STD_ENTRY_LOCAL(bad_intr)
 	};                                              \
 	STD_ENDPROC(_##x)
 
-PTREGS_SYSCALL(sys_execve, r3)
-PTREGS_SYSCALL(sys_sigaltstack, r2)
 PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)
-PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1)
 
-/* Save additional callee-saves to pt_regs, put address in r4 and jump. */
+/* Save additional callee-saves to pt_regs and jump to standard function. */
 STD_ENTRY(_sys_clone)
 	push_extra_callee_saves r4
 	j       sys_clone
diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S
index 7c06d59..54bc9a6 100644
--- a/arch/tile/kernel/intvec_64.S
+++ b/arch/tile/kernel/intvec_64.S
@@ -1150,6 +1150,21 @@ STD_ENTRY(ret_from_fork)
 	}
 	STD_ENDPROC(ret_from_fork)
 
+STD_ENTRY(ret_from_kernel_thread)
+	jal     sim_notify_fork
+	jal     schedule_tail
+	FEEDBACK_REENTER(ret_from_fork)
+	{
+	 move   r0, r31
+	 jalr   r30
+	}
+	FEEDBACK_REENTER(ret_from_kernel_thread)
+	{
+	 movei  r30, 0               /* not an NMI */
+	 j      .Lresume_userspace   /* jump into middle of interrupt_return */
+	}
+	STD_ENDPROC(ret_from_kernel_thread)
+
 /* Various stub interrupt handlers and syscall handlers */
 
 STD_ENTRY_LOCAL(_kernel_double_fault)
@@ -1166,15 +1181,6 @@ STD_ENTRY_LOCAL(bad_intr)
 	panic   "Unhandled interrupt %#x: PC %#lx"
 	STD_ENDPROC(bad_intr)
 
-/* Put address of pt_regs in reg and jump. */
-#define PTREGS_SYSCALL(x, reg)                          \
-	STD_ENTRY(_##x);                                \
-	{                                               \
-	 PTREGS_PTR(reg, PTREGS_OFFSET_BASE);           \
-	 j      x                                       \
-	};                                              \
-	STD_ENDPROC(_##x)
-
 /*
  * Special-case sigreturn to not write r0 to the stack on return.
  * This is technically more efficient, but it also avoids difficulties
@@ -1190,16 +1196,12 @@ STD_ENTRY_LOCAL(bad_intr)
 	};                                              \
 	STD_ENDPROC(_##x)
 
-PTREGS_SYSCALL(sys_execve, r3)
-PTREGS_SYSCALL(sys_sigaltstack, r2)
 PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)
 #ifdef CONFIG_COMPAT
-PTREGS_SYSCALL(compat_sys_execve, r3)
-PTREGS_SYSCALL(compat_sys_sigaltstack, r2)
 PTREGS_SYSCALL_SIGRETURN(compat_sys_rt_sigreturn, r0)
 #endif
 
-/* Save additional callee-saves to pt_regs, put address in r4 and jump. */
+/* Save additional callee-saves to pt_regs and jump to standard function. */
 STD_ENTRY(_sys_clone)
 	push_extra_callee_saves r4
 	j       sys_clone
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c
index 307d010..0e5661e 100644
--- a/arch/tile/kernel/process.c
+++ b/arch/tile/kernel/process.c
@@ -157,24 +157,43 @@ void arch_release_thread_info(struct thread_info *info)
 static void save_arch_state(struct thread_struct *t);
 
 int copy_thread(unsigned long clone_flags, unsigned long sp,
-		unsigned long stack_size,
-		struct task_struct *p, struct pt_regs *regs)
+		unsigned long arg, struct task_struct *p)
 {
-	struct pt_regs *childregs;
+	struct pt_regs *childregs = task_pt_regs(p), *regs = current_pt_regs();
 	unsigned long ksp;
+	unsigned long *callee_regs;
 
 	/*
-	 * When creating a new kernel thread we pass sp as zero.
-	 * Assign it to a reasonable value now that we have the stack.
+	 * Set up the stack and stack pointer appropriately for the
+	 * new child to find itself woken up in __switch_to().
+	 * The callee-saved registers must be on the stack to be read;
+	 * the new task will then jump to assembly support to handle
+	 * calling schedule_tail(), etc., and (for userspace tasks)
+	 * returning to the context set up in the pt_regs.
 	 */
-	if (sp == 0 && regs->ex1 == PL_ICS_EX1(KERNEL_PL, 0))
-		sp = KSTK_TOP(p);
+	ksp = (unsigned long) childregs;
+	ksp -= C_ABI_SAVE_AREA_SIZE;   /* interrupt-entry save area */
+	((long *)ksp)[0] = ((long *)ksp)[1] = 0;
+	ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long);
+	callee_regs = (unsigned long *)ksp;
+	ksp -= C_ABI_SAVE_AREA_SIZE;   /* __switch_to() save area */
+	((long *)ksp)[0] = ((long *)ksp)[1] = 0;
+	p->thread.ksp = ksp;
 
-	/*
-	 * Do not clone step state from the parent; each thread
-	 * must make its own lazily.
-	 */
-	task_thread_info(p)->step_state = NULL;
+	/* Record the pid of the task that created this one. */
+	p->thread.creator_pid = current->pid;
+
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		/* kernel thread */
+		memset(childregs, 0, sizeof(struct pt_regs));
+		memset(&callee_regs[2], 0,
+		       (CALLEE_SAVED_REGS_COUNT - 2) * sizeof(unsigned long));
+		callee_regs[0] = sp;   /* r30 = function */
+		callee_regs[1] = arg;  /* r31 = arg */
+		childregs->ex1 = PL_ICS_EX1(KERNEL_PL, 0);
+		p->thread.pc = (unsigned long) ret_from_kernel_thread;
+		return 0;
+	}
 
 	/*
 	 * Start new thread in ret_from_fork so it schedules properly
@@ -182,46 +201,33 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 	 */
 	p->thread.pc = (unsigned long) ret_from_fork;
 
-	/* Save user stack top pointer so we can ID the stack vm area later. */
-	p->thread.usp0 = sp;
-
-	/* Record the pid of the process that created this one. */
-	p->thread.creator_pid = current->pid;
+	/*
+	 * Do not clone step state from the parent; each thread
+	 * must make its own lazily.
+	 */
+	task_thread_info(p)->step_state = NULL;
 
 	/*
 	 * Copy the registers onto the kernel stack so the
 	 * return-from-interrupt code will reload it into registers.
 	 */
-	childregs = task_pt_regs(p);
-	*childregs = *regs;
+	*childregs = *current_pt_regs();
 	childregs->regs[0] = 0;         /* return value is zero */
-	childregs->sp = sp;  /* override with new user stack pointer */
+	if (sp)
+		childregs->sp = sp;  /* override with new user stack pointer */
+	memcpy(callee_regs, &childregs->regs[CALLEE_SAVED_FIRST_REG],
+	       CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long));
+
+	/* Save user stack top pointer so we can ID the stack vm area later. */
+	p->thread.usp0 = childregs->sp;
 
 	/*
 	 * If CLONE_SETTLS is set, set "tp" in the new task to "r4",
 	 * which is passed in as arg #5 to sys_clone().
 	 */
 	if (clone_flags & CLONE_SETTLS)
-		childregs->tp = regs->regs[4];
+		childregs->tp = childregs->regs[4];
 
-	/*
-	 * Copy the callee-saved registers from the passed pt_regs struct
-	 * into the context-switch callee-saved registers area.
-	 * This way when we start the interrupt-return sequence, the
-	 * callee-save registers will be correctly in registers, which
-	 * is how we assume the compiler leaves them as we start doing
-	 * the normal return-from-interrupt path after calling C code.
-	 * Zero out the C ABI save area to mark the top of the stack.
-	 */
-	ksp = (unsigned long) childregs;
-	ksp -= C_ABI_SAVE_AREA_SIZE;   /* interrupt-entry save area */
-	((long *)ksp)[0] = ((long *)ksp)[1] = 0;
-	ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long);
-	memcpy((void *)ksp, &regs->regs[CALLEE_SAVED_FIRST_REG],
-	       CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long));
-	ksp -= C_ABI_SAVE_AREA_SIZE;   /* __switch_to() save area */
-	((long *)ksp)[0] = ((long *)ksp)[1] = 0;
-	p->thread.ksp = ksp;
 
 #if CHIP_HAS_TILE_DMA()
 	/*
@@ -577,62 +583,6 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags)
 	panic("work_pending: bad flags %#x\n", thread_info_flags);
 }
 
-/* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */
-SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
-		void __user *, parent_tidptr, void __user *, child_tidptr,
-		struct pt_regs *, regs)
-{
-	if (!newsp)
-		newsp = regs->sp;
-	return do_fork(clone_flags, newsp, regs, 0,
-		       parent_tidptr, child_tidptr);
-}
-
-/*
- * sys_execve() executes a new program.
- */
-SYSCALL_DEFINE4(execve, const char __user *, path,
-		const char __user *const __user *, argv,
-		const char __user *const __user *, envp,
-		struct pt_regs *, regs)
-{
-	long error;
-	struct filename *filename;
-
-	filename = getname(path);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-	error = do_execve(filename->name, argv, envp, regs);
-	putname(filename);
-	if (error == 0)
-		single_step_execve();
-out:
-	return error;
-}
-
-#ifdef CONFIG_COMPAT
-long compat_sys_execve(const char __user *path,
-		       compat_uptr_t __user *argv,
-		       compat_uptr_t __user *envp,
-		       struct pt_regs *regs)
-{
-	long error;
-	struct filename *filename;
-
-	filename = getname(path);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-	error = compat_do_execve(filename->name, argv, envp, regs);
-	putname(filename);
-	if (error == 0)
-		single_step_execve();
-out:
-	return error;
-}
-#endif
-
 unsigned long get_wchan(struct task_struct *p)
 {
 	struct KBacktraceIterator kbt;
@@ -650,37 +600,6 @@ unsigned long get_wchan(struct task_struct *p)
 	return 0;
 }
 
-/*
- * We pass in lr as zero (cleared in kernel_thread) and the caller
- * part of the backtrace ABI on the stack also zeroed (in copy_thread)
- * so that backtraces will stop with this function.
- * Note that we don't use r0, since copy_thread() clears it.
- */
-static void start_kernel_thread(int dummy, int (*fn)(int), int arg)
-{
-	do_exit(fn(arg));
-}
-
-/*
- * Create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-	regs.ex1 = PL_ICS_EX1(KERNEL_PL, 0);  /* run at kernel PL, no ICS */
-	regs.pc = (long) start_kernel_thread;
-	regs.flags = PT_FLAGS_CALLER_SAVES;   /* need to restore r1 and r2 */
-	regs.regs[1] = (long) fn;             /* function pointer */
-	regs.regs[2] = (long) arg;            /* parameter register */
-
-	/* Ok, create the new process.. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs,
-		       0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 /* Flush thread state. */
 void flush_thread(void)
 {
diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c
index 67efb65..657a7ac 100644
--- a/arch/tile/kernel/signal.c
+++ b/arch/tile/kernel/signal.c
@@ -37,10 +37,10 @@
 
 #define DEBUG_SIG 0
 
-SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,
-		stack_t __user *, uoss, struct pt_regs *, regs)
+SYSCALL_DEFINE2(sigaltstack, const stack_t __user *, uss,
+		stack_t __user *, uoss)
 {
-	return do_sigaltstack(uss, uoss, regs->sp);
+	return do_sigaltstack(uss, uoss, current_pt_regs()->sp);
 }
 
 
@@ -83,8 +83,9 @@ void signal_fault(const char *type, struct pt_regs *regs,
 }
 
 /* The assembly shim for this function arranges to ignore the return value. */
-SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
+SYSCALL_DEFINE0(rt_sigreturn)
 {
+	struct pt_regs *regs = current_pt_regs();
 	struct rt_sigframe __user *frame =
 		(struct rt_sigframe __user *)(regs->sp);
 	sigset_t set;
diff --git a/arch/tile/kernel/sys.c b/arch/tile/kernel/sys.c
index b08095b..02ff5c0 100644
--- a/arch/tile/kernel/sys.c
+++ b/arch/tile/kernel/sys.c
@@ -106,14 +106,11 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
 #define sys_readahead sys32_readahead
 #endif
 
-/* Call the trampolines to manage pt_regs where necessary. */
-#define sys_execve _sys_execve
-#define sys_sigaltstack _sys_sigaltstack
+/* Call the assembly trampolines where necessary. */
+#undef sys_rt_sigreturn
 #define sys_rt_sigreturn _sys_rt_sigreturn
+#undef sys_clone
 #define sys_clone _sys_clone
-#ifndef __tilegx__
-#define sys_cmpxchg_badaddr _sys_cmpxchg_badaddr
-#endif
 
 /*
  * Note that we can't include <linux/unistd.h> here since the header
diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c
index fe811fa..3d2b81c 100644
--- a/arch/tile/mm/fault.c
+++ b/arch/tile/mm/fault.c
@@ -70,9 +70,10 @@ static noinline void force_sig_info_fault(const char *type, int si_signo,
  * Synthesize the fault a PL0 process would get by doing a word-load of
  * an unaligned address or a high kernel address.
  */
-SYSCALL_DEFINE2(cmpxchg_badaddr, unsigned long, address,
-		struct pt_regs *, regs)
+SYSCALL_DEFINE1(cmpxchg_badaddr, unsigned long, address)
 {
+	struct pt_regs *regs = current_pt_regs();
+
 	if (address >= PAGE_OFFSET)
 		force_sig_info_fault("atomic segfault", SIGSEGV, SEGV_MAPERR,
 				     address, INT_DTLB_MISS, current, regs);
diff --git a/arch/tile/mm/hugetlbpage.c b/arch/tile/mm/hugetlbpage.c
index 812e2d0..650ccff 100644
--- a/arch/tile/mm/hugetlbpage.c
+++ b/arch/tile/mm/hugetlbpage.c
@@ -231,42 +231,15 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
 		unsigned long pgoff, unsigned long flags)
 {
 	struct hstate *h = hstate_file(file);
-	struct mm_struct *mm = current->mm;
-	struct vm_area_struct *vma;
-	unsigned long start_addr;
-
-	if (len > mm->cached_hole_size) {
-		start_addr = mm->free_area_cache;
-	} else {
-		start_addr = TASK_UNMAPPED_BASE;
-		mm->cached_hole_size = 0;
-	}
-
-full_search:
-	addr = ALIGN(start_addr, huge_page_size(h));
-
-	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
-		/* At this point:  (!vma || addr < vma->vm_end). */
-		if (TASK_SIZE - len < addr) {
-			/*
-			 * Start a new search - just in case we missed
-			 * some holes.
-			 */
-			if (start_addr != TASK_UNMAPPED_BASE) {
-				start_addr = TASK_UNMAPPED_BASE;
-				mm->cached_hole_size = 0;
-				goto full_search;
-			}
-			return -ENOMEM;
-		}
-		if (!vma || addr + len <= vma->vm_start) {
-			mm->free_area_cache = addr + len;
-			return addr;
-		}
-		if (addr + mm->cached_hole_size < vma->vm_start)
-			mm->cached_hole_size = vma->vm_start - addr;
-		addr = ALIGN(vma->vm_end, huge_page_size(h));
-	}
+	struct vm_unmapped_area_info info;
+
+	info.flags = 0;
+	info.length = len;
+	info.low_limit = TASK_UNMAPPED_BASE;
+	info.high_limit = TASK_SIZE;
+	info.align_mask = PAGE_MASK & ~huge_page_mask(h);
+	info.align_offset = 0;
+	return vm_unmapped_area(&info);
 }
 
 static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
@@ -274,92 +247,30 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
 		unsigned long pgoff, unsigned long flags)
 {
 	struct hstate *h = hstate_file(file);
-	struct mm_struct *mm = current->mm;
-	struct vm_area_struct *vma, *prev_vma;
-	unsigned long base = mm->mmap_base, addr = addr0;
-	unsigned long largest_hole = mm->cached_hole_size;
-	int first_time = 1;
-
-	/* don't allow allocations above current base */
-	if (mm->free_area_cache > base)
-		mm->free_area_cache = base;
-
-	if (len <= largest_hole) {
-		largest_hole = 0;
-		mm->free_area_cache  = base;
-	}
-try_again:
-	/* make sure it can fit in the remaining address space */
-	if (mm->free_area_cache < len)
-		goto fail;
-
-	/* either no address requested or can't fit in requested address hole */
-	addr = (mm->free_area_cache - len) & huge_page_mask(h);
-	do {
-		/*
-		 * Lookup failure means no vma is above this address,
-		 * i.e. return with success:
-		 */
-		vma = find_vma_prev(mm, addr, &prev_vma);
-		if (!vma) {
-			return addr;
-			break;
-		}
-
-		/*
-		 * new region fits between prev_vma->vm_end and
-		 * vma->vm_start, use it:
-		 */
-		if (addr + len <= vma->vm_start &&
-			    (!prev_vma || (addr >= prev_vma->vm_end))) {
-			/* remember the address as a hint for next time */
-			mm->cached_hole_size = largest_hole;
-			mm->free_area_cache = addr;
-			return addr;
-		} else {
-			/* pull free_area_cache down to the first hole */
-			if (mm->free_area_cache == vma->vm_end) {
-				mm->free_area_cache = vma->vm_start;
-				mm->cached_hole_size = largest_hole;
-			}
-		}
+	struct vm_unmapped_area_info info;
+	unsigned long addr;
 
-		/* remember the largest hole we saw so far */
-		if (addr + largest_hole < vma->vm_start)
-			largest_hole = vma->vm_start - addr;
+	info.flags = VM_UNMAPPED_AREA_TOPDOWN;
+	info.length = len;
+	info.low_limit = PAGE_SIZE;
+	info.high_limit = current->mm->mmap_base;
+	info.align_mask = PAGE_MASK & ~huge_page_mask(h);
+	info.align_offset = 0;
+	addr = vm_unmapped_area(&info);
 
-		/* try just below the current vma->vm_start */
-		addr = (vma->vm_start - len) & huge_page_mask(h);
-
-	} while (len <= vma->vm_start);
-
-fail:
-	/*
-	 * if hint left us with no space for the requested
-	 * mapping then try again:
-	 */
-	if (first_time) {
-		mm->free_area_cache = base;
-		largest_hole = 0;
-		first_time = 0;
-		goto try_again;
-	}
 	/*
 	 * A failed mmap() very likely causes application failure,
 	 * so fall back to the bottom-up function here. This scenario
 	 * can happen with large stack limits and large mmap()
 	 * allocations.
 	 */
-	mm->free_area_cache = TASK_UNMAPPED_BASE;
-	mm->cached_hole_size = ~0UL;
-	addr = hugetlb_get_unmapped_area_bottomup(file, addr0,
-			len, pgoff, flags);
-
-	/*
-	 * Restore the topdown base:
-	 */
-	mm->free_area_cache = base;
-	mm->cached_hole_size = ~0UL;
+	if (addr & ~PAGE_MASK) {
+		VM_BUG_ON(addr != -ENOMEM);
+		info.flags = 0;
+		info.low_limit = TASK_UNMAPPED_BASE;
+		info.high_limit = TASK_SIZE;
+		addr = vm_unmapped_area(&info);
+	}
 
 	return addr;
 }
diff --git a/arch/um/Kconfig.net b/arch/um/Kconfig.net
index 3160b1a..820a56f 100644
--- a/arch/um/Kconfig.net
+++ b/arch/um/Kconfig.net
@@ -157,7 +157,7 @@ config UML_NET_MCAST
 
 config UML_NET_PCAP
 	bool "pcap transport"
-	depends on UML_NET && EXPERIMENTAL
+	depends on UML_NET
 	help
 	The pcap transport makes a pcap packet stream on the host look
 	like an ethernet device inside UML.  This is useful for making
diff --git a/arch/um/Kconfig.um b/arch/um/Kconfig.um
index bf87f25..a7520c9 100644
--- a/arch/um/Kconfig.um
+++ b/arch/um/Kconfig.um
@@ -45,8 +45,8 @@ config HOSTFS
           say Y or M here; otherwise say N.
 
 config HPPFS
-	tristate "HoneyPot ProcFS (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && PROC_FS
+	tristate "HoneyPot ProcFS"
+	depends on PROC_FS
 	help
 	  hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
 	  entries to be overridden, removed, or fabricated from the host.
@@ -96,7 +96,7 @@ config MAGIC_SYSRQ
 	  unless you really know what this hack does.
 
 config SMP
-	bool "Symmetric multi-processing support (EXPERIMENTAL)"
+	bool "Symmetric multi-processing support"
 	default n
 	depends on BROKEN
 	help
@@ -126,7 +126,7 @@ config NR_CPUS
 	default "32"
 
 config HIGHMEM
-	bool "Highmem support (EXPERIMENTAL)"
+	bool "Highmem support"
 	depends on !64BIT && BROKEN
 	default n
 	help
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index c3bba73..e9a0abc 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -83,21 +83,8 @@ static const struct chan_ops not_configged_ops = {
 
 static void tty_receive_char(struct tty_struct *tty, char ch)
 {
-	if (tty == NULL)
-		return;
-
-	if (I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) {
-		if (ch == STOP_CHAR(tty)) {
-			stop_tty(tty);
-			return;
-		}
-		else if (ch == START_CHAR(tty)) {
-			start_tty(tty);
-			return;
-		}
-	}
-
-	tty_insert_flip_char(tty, ch, TTY_NORMAL);
+	if (tty)
+		tty_insert_flip_char(tty, ch, TTY_NORMAL);
 }
 
 static int open_one_chan(struct chan *chan)
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index fd9a15b..9ffc28b 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -584,6 +584,8 @@ int register_lines(struct line_driver *line_driver,
 		printk(KERN_ERR "register_lines : can't register %s driver\n",
 		       line_driver->name);
 		put_tty_driver(driver);
+		for (i = 0; i < nlines; i++)
+			tty_port_destroy(&lines[i].port);
 		return err;
 	}
 
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 79ccfe6..4bd82ac 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -123,7 +123,7 @@ void mconsole_log(struct mc_request *req)
 
 void mconsole_proc(struct mc_request *req)
 {
-	struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt;
+	struct vfsmount *mnt = task_active_pid_ns(current)->proc_mnt;
 	char *buf;
 	int len;
 	struct file *file;
@@ -648,7 +648,7 @@ static void stack_proc(void *arg)
 	struct task_struct *from = current, *to = arg;
 
 	to->thread.saved_task = from;
-	rcu_switch(from, to);
+	rcu_user_hooks_switch(from, to);
 	switch_to(from, to, from);
 }
 
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 0f6e7b3..b30f34a 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -2,3 +2,4 @@ generic-y += bug.h cputime.h device.h emergency-restart.h futex.h hardirq.h
 generic-y += hw_irq.h irq_regs.h kdebug.h percpu.h sections.h topology.h xor.h
 generic-y += ftrace.h 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
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index b6d699c..b462b13 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -161,8 +161,7 @@ void fork_handler(void)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long sp,
-		unsigned long arg, struct task_struct * p,
-		struct pt_regs *regs)
+		unsigned long arg, struct task_struct * p)
 {
 	void (*handler)(void);
 	int kthread = current->flags & PF_KTHREAD;
@@ -171,7 +170,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 	p->thread = (struct thread_struct) INIT_THREAD;
 
 	if (!kthread) {
-	  	memcpy(&p->thread.regs.regs, &regs->regs,
+	  	memcpy(&p->thread.regs.regs, current_pt_regs(),
 		       sizeof(p->thread.regs.regs));
 		PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0);
 		if (sp != 0)
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index a81f370..c1d0ae0 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -14,29 +14,6 @@
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 
-long sys_fork(void)
-{
-	return do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
-		      &current->thread.regs, 0, NULL, NULL);
-}
-
-long sys_vfork(void)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
-		      UPT_SP(&current->thread.regs.regs),
-		      &current->thread.regs, 0, NULL, NULL);
-}
-
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
-	       void __user *parent_tid, void __user *child_tid)
-{
-	if (!newsp)
-		newsp = UPT_SP(&current->thread.regs.regs);
-
-	return do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
-		      child_tid);
-}
-
 long old_mmap(unsigned long addr, unsigned long len,
 	      unsigned long prot, unsigned long flags,
 	      unsigned long fd, unsigned long offset)
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 601e92f..89d8b6c 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -53,6 +53,7 @@ generic-y += syscalls.h
 generic-y += termbits.h
 generic-y += termios.h
 generic-y += topology.h
+generic-y += trace_clock.h
 generic-y += types.h
 generic-y += ucontext.h
 generic-y += unaligned.h
diff --git a/arch/unicore32/include/uapi/asm/unistd.h b/arch/unicore32/include/uapi/asm/unistd.h
index d18a3be8..00cf5e2 100644
--- a/arch/unicore32/include/uapi/asm/unistd.h
+++ b/arch/unicore32/include/uapi/asm/unistd.h
@@ -13,3 +13,4 @@
 /* Use the standard ABI for syscalls. */
 #include <asm-generic/unistd.h>
 #define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_CLONE
diff --git a/arch/unicore32/kernel/entry.S b/arch/unicore32/kernel/entry.S
index 7049350..581630d 100644
--- a/arch/unicore32/kernel/entry.S
+++ b/arch/unicore32/kernel/entry.S
@@ -668,12 +668,6 @@ __cr_alignment:
 #endif
 	.ltorg
 
-ENTRY(sys_clone)
-		add	ip, sp, #S_OFF
-		stw	ip, [sp+], #4
-		b	__sys_clone
-ENDPROC(sys_clone)
-
 ENTRY(sys_rt_sigreturn)
 		add	r0, sp, #S_OFF
 		mov	why, #0		@ prevent syscall restart handling
diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
index b0056f6..7c43592 100644
--- a/arch/unicore32/kernel/pci.c
+++ b/arch/unicore32/kernel/pci.c
@@ -250,9 +250,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 	printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
 		bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
 }
-#ifdef CONFIG_HOTPLUG
 EXPORT_SYMBOL(pcibios_fixup_bus);
-#endif
 
 static int __init pci_common_init(void)
 {
diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c
index a8fe265..62bad9f 100644
--- a/arch/unicore32/kernel/process.c
+++ b/arch/unicore32/kernel/process.c
@@ -262,26 +262,27 @@ asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
 
 int
 copy_thread(unsigned long clone_flags, unsigned long stack_start,
-	    unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs)
+	    unsigned long stk_sz, struct task_struct *p)
 {
 	struct thread_info *thread = task_thread_info(p);
 	struct pt_regs *childregs = task_pt_regs(p);
 
 	memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
 	thread->cpu_context.sp = (unsigned long)childregs;
-	if (unlikely(!regs)) {
+	if (unlikely(p->flags & PF_KTHREAD)) {
 		thread->cpu_context.pc = (unsigned long)ret_from_kernel_thread;
 		thread->cpu_context.r4 = stack_start;
 		thread->cpu_context.r5 = stk_sz;
 		memset(childregs, 0, sizeof(struct pt_regs));
 	} else {
 		thread->cpu_context.pc = (unsigned long)ret_from_fork;
-		*childregs = *regs;
+		*childregs = *current_pt_regs();
 		childregs->UCreg_00 = 0;
-		childregs->UCreg_sp = stack_start;
+		if (stack_start)
+			childregs->UCreg_sp = stack_start;
 
 		if (clone_flags & CLONE_SETTLS)
-			childregs->UCreg_16 = regs->UCreg_03;
+			childregs->UCreg_16 = childregs->UCreg_03;
 	}
 	return 0;
 }
diff --git a/arch/unicore32/kernel/sys.c b/arch/unicore32/kernel/sys.c
index 9680134..cfe79c9 100644
--- a/arch/unicore32/kernel/sys.c
+++ b/arch/unicore32/kernel/sys.c
@@ -28,20 +28,6 @@
 #include <asm/syscalls.h>
 #include <asm/cacheflush.h>
 
-/* Clone a task - this clones the calling program thread.
- * This is called indirectly via a small wrapper
- */
-asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp,
-			 void __user *parent_tid, void __user *child_tid,
-			 struct pt_regs *regs)
-{
-	if (!newsp)
-		newsp = regs->UCreg_sp;
-
-	return do_fork(clone_flags, newsp, regs, 0,
-			parent_tid, child_tid);
-}
-
 /* Note: used by the compat code even in 64-bit Linux. */
 SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
 		unsigned long, prot, unsigned long, flags,
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 46c3bff..cd98a44 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -22,6 +22,8 @@ config X86
 	def_bool y
 	select HAVE_AOUT if X86_32
 	select HAVE_UNSTABLE_SCHED_CLOCK
+	select ARCH_SUPPORTS_NUMA_BALANCING
+	select ARCH_WANTS_NUMA_GENERIC_PGPROT
 	select HAVE_IDE
 	select HAVE_OPROFILE
 	select HAVE_PCSPKR_PLATFORM
@@ -106,12 +108,13 @@ config X86
 	select KTIME_SCALAR if X86_32
 	select GENERIC_STRNCPY_FROM_USER
 	select GENERIC_STRNLEN_USER
-	select HAVE_RCU_USER_QS if X86_64
+	select HAVE_CONTEXT_TRACKING if X86_64
 	select HAVE_IRQ_TIME_ACCOUNTING
 	select GENERIC_KERNEL_THREAD
 	select GENERIC_KERNEL_EXECVE
 	select MODULES_USE_ELF_REL if X86_32
 	select MODULES_USE_ELF_RELA if X86_64
+	select CLONE_BACKWARDS if X86_32
 
 config INSTRUCTION_DECODER
 	def_bool y
@@ -225,7 +228,7 @@ config ARCH_SUPPORTS_DEBUG_PAGEALLOC
 
 config HAVE_INTEL_TXT
 	def_bool y
-	depends on EXPERIMENTAL && INTEL_IOMMU && ACPI
+	depends on INTEL_IOMMU && ACPI
 
 config X86_32_SMP
 	def_bool y
@@ -310,7 +313,7 @@ config X86_X2APIC
 	  If you don't know what to do here, say N.
 
 config X86_MPPARSE
-	bool "Enable MPS table" if ACPI
+	bool "Enable MPS table" if ACPI || SFI
 	default y
 	depends on X86_LOCAL_APIC
 	---help---
@@ -570,6 +573,37 @@ config SCHED_OMIT_FRAME_POINTER
 
 	  If in doubt, say "Y".
 
+config KVMTOOL_TEST_ENABLE
+	bool "Enable options to create a bootable tools/kvm/ kernel"
+	select NET
+	select NETDEVICES
+	select PCI
+	select BLOCK
+	select BLK_DEV
+	select NETWORK_FILESYSTEMS
+	select INET
+	select EXPERIMENTAL
+	select SERIAL_8250
+	select SERIAL_8250_CONSOLE
+	select IP_PNP
+	select IP_PNP_DHCP
+	select BINFMT_ELF
+	select PCI_MSI
+	select HAVE_ARCH_KGDB
+	select DEBUG_KERNEL
+	select KGDB
+	select KGDB_SERIAL_CONSOLE
+	select VIRTUALIZATION
+	select VIRTIO
+	select VIRTIO_RING
+	select VIRTIO_PCI
+	select VIRTIO_BLK
+	select VIRTIO_CONSOLE
+	select VIRTIO_NET
+	select 9P_FS
+	select NET_9P
+	select NET_9P_VIRTIO
+
 menuconfig PARAVIRT_GUEST
 	bool "Paravirtualized guest support"
 	---help---
@@ -619,7 +653,7 @@ config PARAVIRT
 
 config PARAVIRT_SPINLOCKS
 	bool "Paravirtualization layer for spinlocks"
-	depends on PARAVIRT && SMP && EXPERIMENTAL
+	depends on PARAVIRT && SMP
 	---help---
 	  Paravirtualized spinlocks allow a pvops backend to replace the
 	  spinlock implementation with something virtualization-friendly
@@ -731,7 +765,7 @@ config GART_IOMMU
 config CALGARY_IOMMU
 	bool "IBM Calgary IOMMU support"
 	select SWIOTLB
-	depends on X86_64 && PCI && EXPERIMENTAL
+	depends on X86_64 && PCI
 	---help---
 	  Support for hardware IOMMUs in IBM's xSeries x366 and x460
 	  systems. Needed to run systems with more than 3GB of memory
@@ -773,7 +807,7 @@ config IOMMU_HELPER
 
 config MAXSMP
 	bool "Enable Maximum number of SMP Processors and NUMA Nodes"
-	depends on X86_64 && SMP && DEBUG_KERNEL && EXPERIMENTAL
+	depends on X86_64 && SMP && DEBUG_KERNEL
 	select CPUMASK_OFFSTACK
 	---help---
 	  Enable maximum number of CPUS and NUMA Nodes for this architecture.
@@ -1109,7 +1143,6 @@ config HIGHMEM64G
 endchoice
 
 choice
-	depends on EXPERIMENTAL
 	prompt "Memory split" if EXPERT
 	default VMSPLIT_3G
 	depends on X86_32
@@ -1186,7 +1219,7 @@ config DIRECT_GBPAGES
 config NUMA
 	bool "Numa Memory Allocation and Scheduler Support"
 	depends on SMP
-	depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || X86_BIGSMP || X86_SUMMIT && ACPI) && EXPERIMENTAL)
+	depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || X86_BIGSMP || X86_SUMMIT && ACPI))
 	default y if (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP)
 	---help---
 	  Enable NUMA (Non Uniform Memory Access) support.
@@ -1281,7 +1314,7 @@ config ARCH_DISCONTIGMEM_DEFAULT
 
 config ARCH_SPARSEMEM_ENABLE
 	def_bool y
-	depends on X86_64 || NUMA || (EXPERIMENTAL && X86_32) || X86_32_NON_STANDARD
+	depends on X86_64 || NUMA || X86_32 || X86_32_NON_STANDARD
 	select SPARSEMEM_STATIC if X86_32
 	select SPARSEMEM_VMEMMAP_ENABLE if X86_64
 
@@ -1595,8 +1628,7 @@ config CRASH_DUMP
 	  For more details see Documentation/kdump/kdump.txt
 
 config KEXEC_JUMP
-	bool "kexec jump (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	bool "kexec jump"
 	depends on KEXEC && HIBERNATION
 	---help---
 	  Jump between original kernel and kexeced kernel and invoke
@@ -1995,7 +2027,7 @@ config PCI_MMCONFIG
 
 config PCI_CNB20LE_QUIRK
 	bool "Read CNB20LE Host Bridge Windows" if EXPERT
-	depends on PCI && EXPERIMENTAL
+	depends on PCI
 	help
 	  Read the PCI windows out of the CNB20LE host bridge. This allows
 	  PCI hotplug to work on systems with the CNB20LE chipset which do
@@ -2096,6 +2128,7 @@ config OLPC_XO1_RTC
 config OLPC_XO1_SCI
 	bool "OLPC XO-1 SCI extras"
 	depends on OLPC && OLPC_XO1_PM
+	depends on INPUT=y
 	select POWER_SUPPLY
 	select GPIO_CS5535
 	select MFD_CORE
@@ -2189,8 +2222,8 @@ config IA32_AOUT
 	  Support old a.out binaries in the 32bit emulation.
 
 config X86_X32
-	bool "x32 ABI for 64-bit mode (EXPERIMENTAL)"
-	depends on X86_64 && IA32_EMULATION && EXPERIMENTAL
+	bool "x32 ABI for 64-bit mode"
+	depends on X86_64 && IA32_EMULATION
 	---help---
 	  Include code to run binaries for the x32 native 32-bit ABI
 	  for 64-bit processors.  An x32 process gets access to the
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 05afcca..e71fc42 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -123,9 +123,10 @@ cfi-sections := $(call as-instr,.cfi_sections .debug_frame,-DCONFIG_AS_CFI_SECTI
 # does binutils support specific instructions?
 asinstr := $(call as-instr,fxsaveq (%rax),-DCONFIG_AS_FXSAVEQ=1)
 avx_instr := $(call as-instr,vxorps %ymm0$(comma)%ymm1$(comma)%ymm2,-DCONFIG_AS_AVX=1)
+avx2_instr :=$(call as-instr,vpbroadcastb %xmm0$(comma)%ymm1,-DCONFIG_AS_AVX2=1)
 
-KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr)
-KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr)
+KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr)
+KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr)
 
 LDFLAGS := -m elf_$(UTS_MACHINE)
 
diff --git a/arch/x86/boot/.gitignore b/arch/x86/boot/.gitignore
index 851fe93..e3cf9f6 100644
--- a/arch/x86/boot/.gitignore
+++ b/arch/x86/boot/.gitignore
@@ -2,7 +2,6 @@ bootsect
 bzImage
 cpustr.h
 mkcpustr
-offsets.h
 voffset.h
 zoffset.h
 setup
diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
index 5bacb4a..e0ca7c9 100644
--- a/arch/x86/crypto/Makefile
+++ b/arch/x86/crypto/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_CRYPTO_SERPENT_SSE2_586) += serpent-sse2-i586.o
 
 obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
 obj-$(CONFIG_CRYPTO_CAMELLIA_X86_64) += camellia-x86_64.o
+obj-$(CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64) += camellia-aesni-avx-x86_64.o
 obj-$(CONFIG_CRYPTO_CAST5_AVX_X86_64) += cast5-avx-x86_64.o
 obj-$(CONFIG_CRYPTO_CAST6_AVX_X86_64) += cast6-avx-x86_64.o
 obj-$(CONFIG_CRYPTO_BLOWFISH_X86_64) += blowfish-x86_64.o
@@ -34,6 +35,8 @@ serpent-sse2-i586-y := serpent-sse2-i586-asm_32.o serpent_sse2_glue.o
 
 aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
 camellia-x86_64-y := camellia-x86_64-asm_64.o camellia_glue.o
+camellia-aesni-avx-x86_64-y := camellia-aesni-avx-asm_64.o \
+			       camellia_aesni_avx_glue.o
 cast5-avx-x86_64-y := cast5-avx-x86_64-asm_64.o cast5_avx_glue.o
 cast6-avx-x86_64-y := cast6-avx-x86_64-asm_64.o cast6_avx_glue.o
 blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o
@@ -47,3 +50,5 @@ serpent-avx-x86_64-y := serpent-avx-x86_64-asm_64.o serpent_avx_glue.o
 aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o
 ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
 sha1-ssse3-y := sha1_ssse3_asm.o sha1_ssse3_glue.o
+crc32c-intel-y := crc32c-intel_glue.o
+crc32c-intel-$(CONFIG_CRYPTO_CRC32C_X86_64) += crc32c-pcl-intel-asm_64.o
diff --git a/arch/x86/crypto/camellia-aesni-avx-asm_64.S b/arch/x86/crypto/camellia-aesni-avx-asm_64.S
new file mode 100644
index 0000000..2306d2e
--- /dev/null
+++ b/arch/x86/crypto/camellia-aesni-avx-asm_64.S
@@ -0,0 +1,1102 @@
+/*
+ * x86_64/AVX/AES-NI assembler implementation of Camellia
+ *
+ * Copyright © 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+/*
+ * Version licensed under 2-clause BSD License is available at:
+ *	http://koti.mbnet.fi/axh/crypto/camellia-BSD-1.2.0-aesni1.tar.xz
+ */
+
+#define CAMELLIA_TABLE_BYTE_LEN 272
+
+/* struct camellia_ctx: */
+#define key_table 0
+#define key_length CAMELLIA_TABLE_BYTE_LEN
+
+/* register macros */
+#define CTX %rdi
+
+/**********************************************************************
+  16-way camellia
+ **********************************************************************/
+#define filter_8bit(x, lo_t, hi_t, mask4bit, tmp0) \
+	vpand x, mask4bit, tmp0; \
+	vpandn x, mask4bit, x; \
+	vpsrld $4, x, x; \
+	\
+	vpshufb tmp0, lo_t, tmp0; \
+	vpshufb x, hi_t, x; \
+	vpxor tmp0, x, x;
+
+/*
+ * IN:
+ *   x0..x7: byte-sliced AB state
+ *   mem_cd: register pointer storing CD state
+ *   key: index for key material
+ * OUT:
+ *   x0..x7: new byte-sliced CD state
+ */
+#define roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, t0, t1, t2, t3, t4, t5, t6, \
+		  t7, mem_cd, key) \
+	/* \
+	 * S-function with AES subbytes \
+	 */ \
+	vmovdqa .Linv_shift_row, t4; \
+	vbroadcastss .L0f0f0f0f, t7; \
+	vmovdqa .Lpre_tf_lo_s1, t0; \
+	vmovdqa .Lpre_tf_hi_s1, t1; \
+	\
+	/* AES inverse shift rows */ \
+	vpshufb t4, x0, x0; \
+	vpshufb t4, x7, x7; \
+	vpshufb t4, x1, x1; \
+	vpshufb t4, x4, x4; \
+	vpshufb t4, x2, x2; \
+	vpshufb t4, x5, x5; \
+	vpshufb t4, x3, x3; \
+	vpshufb t4, x6, x6; \
+	\
+	/* prefilter sboxes 1, 2 and 3 */ \
+	vmovdqa .Lpre_tf_lo_s4, t2; \
+	vmovdqa .Lpre_tf_hi_s4, t3; \
+	filter_8bit(x0, t0, t1, t7, t6); \
+	filter_8bit(x7, t0, t1, t7, t6); \
+	filter_8bit(x1, t0, t1, t7, t6); \
+	filter_8bit(x4, t0, t1, t7, t6); \
+	filter_8bit(x2, t0, t1, t7, t6); \
+	filter_8bit(x5, t0, t1, t7, t6); \
+	\
+	/* prefilter sbox 4 */ \
+	vpxor t4, t4, t4; \
+	filter_8bit(x3, t2, t3, t7, t6); \
+	filter_8bit(x6, t2, t3, t7, t6); \
+	\
+	/* AES subbytes + AES shift rows */ \
+	vmovdqa .Lpost_tf_lo_s1, t0; \
+	vmovdqa .Lpost_tf_hi_s1, t1; \
+	vaesenclast t4, x0, x0; \
+	vaesenclast t4, x7, x7; \
+	vaesenclast t4, x1, x1; \
+	vaesenclast t4, x4, x4; \
+	vaesenclast t4, x2, x2; \
+	vaesenclast t4, x5, x5; \
+	vaesenclast t4, x3, x3; \
+	vaesenclast t4, x6, x6; \
+	\
+	/* postfilter sboxes 1 and 4 */ \
+	vmovdqa .Lpost_tf_lo_s3, t2; \
+	vmovdqa .Lpost_tf_hi_s3, t3; \
+	filter_8bit(x0, t0, t1, t7, t6); \
+	filter_8bit(x7, t0, t1, t7, t6); \
+	filter_8bit(x3, t0, t1, t7, t6); \
+	filter_8bit(x6, t0, t1, t7, t6); \
+	\
+	/* postfilter sbox 3 */ \
+	vmovdqa .Lpost_tf_lo_s2, t4; \
+	vmovdqa .Lpost_tf_hi_s2, t5; \
+	filter_8bit(x2, t2, t3, t7, t6); \
+	filter_8bit(x5, t2, t3, t7, t6); \
+	\
+	vpxor t6, t6, t6; \
+	vmovq key, t0; \
+	\
+	/* postfilter sbox 2 */ \
+	filter_8bit(x1, t4, t5, t7, t2); \
+	filter_8bit(x4, t4, t5, t7, t2); \
+	\
+	vpsrldq $5, t0, t5; \
+	vpsrldq $1, t0, t1; \
+	vpsrldq $2, t0, t2; \
+	vpsrldq $3, t0, t3; \
+	vpsrldq $4, t0, t4; \
+	vpshufb t6, t0, t0; \
+	vpshufb t6, t1, t1; \
+	vpshufb t6, t2, t2; \
+	vpshufb t6, t3, t3; \
+	vpshufb t6, t4, t4; \
+	vpsrldq $2, t5, t7; \
+	vpshufb t6, t7, t7; \
+	\
+	/* \
+	 * P-function \
+	 */ \
+	vpxor x5, x0, x0; \
+	vpxor x6, x1, x1; \
+	vpxor x7, x2, x2; \
+	vpxor x4, x3, x3; \
+	\
+	vpxor x2, x4, x4; \
+	vpxor x3, x5, x5; \
+	vpxor x0, x6, x6; \
+	vpxor x1, x7, x7; \
+	\
+	vpxor x7, x0, x0; \
+	vpxor x4, x1, x1; \
+	vpxor x5, x2, x2; \
+	vpxor x6, x3, x3; \
+	\
+	vpxor x3, x4, x4; \
+	vpxor x0, x5, x5; \
+	vpxor x1, x6, x6; \
+	vpxor x2, x7, x7; /* note: high and low parts swapped */ \
+	\
+	/* \
+	 * Add key material and result to CD (x becomes new CD) \
+	 */ \
+	\
+	vpxor t3, x4, x4; \
+	vpxor 0 * 16(mem_cd), x4, x4; \
+	\
+	vpxor t2, x5, x5; \
+	vpxor 1 * 16(mem_cd), x5, x5; \
+	\
+	vpsrldq $1, t5, t3; \
+	vpshufb t6, t5, t5; \
+	vpshufb t6, t3, t6; \
+	\
+	vpxor t1, x6, x6; \
+	vpxor 2 * 16(mem_cd), x6, x6; \
+	\
+	vpxor t0, x7, x7; \
+	vpxor 3 * 16(mem_cd), x7, x7; \
+	\
+	vpxor t7, x0, x0; \
+	vpxor 4 * 16(mem_cd), x0, x0; \
+	\
+	vpxor t6, x1, x1; \
+	vpxor 5 * 16(mem_cd), x1, x1; \
+	\
+	vpxor t5, x2, x2; \
+	vpxor 6 * 16(mem_cd), x2, x2; \
+	\
+	vpxor t4, x3, x3; \
+	vpxor 7 * 16(mem_cd), x3, x3;
+
+/*
+ * Size optimization... with inlined roundsm16, binary would be over 5 times
+ * larger and would only be 0.5% faster (on sandy-bridge).
+ */
+.align 8
+roundsm16_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_cd:
+	roundsm16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+		  %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, %xmm15,
+		  %rcx, (%r9));
+	ret;
+
+.align 8
+roundsm16_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab:
+	roundsm16(%xmm4, %xmm5, %xmm6, %xmm7, %xmm0, %xmm1, %xmm2, %xmm3,
+		  %xmm12, %xmm13, %xmm14, %xmm15, %xmm8, %xmm9, %xmm10, %xmm11,
+		  %rax, (%r9));
+	ret;
+
+/*
+ * IN/OUT:
+ *  x0..x7: byte-sliced AB state preloaded
+ *  mem_ab: byte-sliced AB state in memory
+ *  mem_cb: byte-sliced CD state in memory
+ */
+#define two_roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+		      y6, y7, mem_ab, mem_cd, i, dir, store_ab) \
+	leaq (key_table + (i) * 8)(CTX), %r9; \
+	call roundsm16_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_cd; \
+	\
+	vmovdqu x4, 0 * 16(mem_cd); \
+	vmovdqu x5, 1 * 16(mem_cd); \
+	vmovdqu x6, 2 * 16(mem_cd); \
+	vmovdqu x7, 3 * 16(mem_cd); \
+	vmovdqu x0, 4 * 16(mem_cd); \
+	vmovdqu x1, 5 * 16(mem_cd); \
+	vmovdqu x2, 6 * 16(mem_cd); \
+	vmovdqu x3, 7 * 16(mem_cd); \
+	\
+	leaq (key_table + ((i) + (dir)) * 8)(CTX), %r9; \
+	call roundsm16_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab; \
+	\
+	store_ab(x0, x1, x2, x3, x4, x5, x6, x7, mem_ab);
+
+#define dummy_store(x0, x1, x2, x3, x4, x5, x6, x7, mem_ab) /* do nothing */
+
+#define store_ab_state(x0, x1, x2, x3, x4, x5, x6, x7, mem_ab) \
+	/* Store new AB state */ \
+	vmovdqu x0, 0 * 16(mem_ab); \
+	vmovdqu x1, 1 * 16(mem_ab); \
+	vmovdqu x2, 2 * 16(mem_ab); \
+	vmovdqu x3, 3 * 16(mem_ab); \
+	vmovdqu x4, 4 * 16(mem_ab); \
+	vmovdqu x5, 5 * 16(mem_ab); \
+	vmovdqu x6, 6 * 16(mem_ab); \
+	vmovdqu x7, 7 * 16(mem_ab);
+
+#define enc_rounds16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+		      y6, y7, mem_ab, mem_cd, i) \
+	two_roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+		      y6, y7, mem_ab, mem_cd, (i) + 2, 1, store_ab_state); \
+	two_roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+		      y6, y7, mem_ab, mem_cd, (i) + 4, 1, store_ab_state); \
+	two_roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+		      y6, y7, mem_ab, mem_cd, (i) + 6, 1, dummy_store);
+
+#define dec_rounds16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+		      y6, y7, mem_ab, mem_cd, i) \
+	two_roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+		      y6, y7, mem_ab, mem_cd, (i) + 7, -1, store_ab_state); \
+	two_roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+		      y6, y7, mem_ab, mem_cd, (i) + 5, -1, store_ab_state); \
+	two_roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+		      y6, y7, mem_ab, mem_cd, (i) + 3, -1, dummy_store);
+
+/*
+ * IN:
+ *  v0..3: byte-sliced 32-bit integers
+ * OUT:
+ *  v0..3: (IN <<< 1)
+ */
+#define rol32_1_16(v0, v1, v2, v3, t0, t1, t2, zero) \
+	vpcmpgtb v0, zero, t0; \
+	vpaddb v0, v0, v0; \
+	vpabsb t0, t0; \
+	\
+	vpcmpgtb v1, zero, t1; \
+	vpaddb v1, v1, v1; \
+	vpabsb t1, t1; \
+	\
+	vpcmpgtb v2, zero, t2; \
+	vpaddb v2, v2, v2; \
+	vpabsb t2, t2; \
+	\
+	vpor t0, v1, v1; \
+	\
+	vpcmpgtb v3, zero, t0; \
+	vpaddb v3, v3, v3; \
+	vpabsb t0, t0; \
+	\
+	vpor t1, v2, v2; \
+	vpor t2, v3, v3; \
+	vpor t0, v0, v0;
+
+/*
+ * IN:
+ *   r: byte-sliced AB state in memory
+ *   l: byte-sliced CD state in memory
+ * OUT:
+ *   x0..x7: new byte-sliced CD state
+ */
+#define fls16(l, l0, l1, l2, l3, l4, l5, l6, l7, r, t0, t1, t2, t3, tt0, \
+	      tt1, tt2, tt3, kll, klr, krl, krr) \
+	/* \
+	 * t0 = kll; \
+	 * t0 &= ll; \
+	 * lr ^= rol32(t0, 1); \
+	 */ \
+	vpxor tt0, tt0, tt0; \
+	vmovd kll, t0; \
+	vpshufb tt0, t0, t3; \
+	vpsrldq $1, t0, t0; \
+	vpshufb tt0, t0, t2; \
+	vpsrldq $1, t0, t0; \
+	vpshufb tt0, t0, t1; \
+	vpsrldq $1, t0, t0; \
+	vpshufb tt0, t0, t0; \
+	\
+	vpand l0, t0, t0; \
+	vpand l1, t1, t1; \
+	vpand l2, t2, t2; \
+	vpand l3, t3, t3; \
+	\
+	rol32_1_16(t3, t2, t1, t0, tt1, tt2, tt3, tt0); \
+	\
+	vpxor l4, t0, l4; \
+	vmovdqu l4, 4 * 16(l); \
+	vpxor l5, t1, l5; \
+	vmovdqu l5, 5 * 16(l); \
+	vpxor l6, t2, l6; \
+	vmovdqu l6, 6 * 16(l); \
+	vpxor l7, t3, l7; \
+	vmovdqu l7, 7 * 16(l); \
+	\
+	/* \
+	 * t2 = krr; \
+	 * t2 |= rr; \
+	 * rl ^= t2; \
+	 */ \
+	\
+	vmovd krr, t0; \
+	vpshufb tt0, t0, t3; \
+	vpsrldq $1, t0, t0; \
+	vpshufb tt0, t0, t2; \
+	vpsrldq $1, t0, t0; \
+	vpshufb tt0, t0, t1; \
+	vpsrldq $1, t0, t0; \
+	vpshufb tt0, t0, t0; \
+	\
+	vpor 4 * 16(r), t0, t0; \
+	vpor 5 * 16(r), t1, t1; \
+	vpor 6 * 16(r), t2, t2; \
+	vpor 7 * 16(r), t3, t3; \
+	\
+	vpxor 0 * 16(r), t0, t0; \
+	vpxor 1 * 16(r), t1, t1; \
+	vpxor 2 * 16(r), t2, t2; \
+	vpxor 3 * 16(r), t3, t3; \
+	vmovdqu t0, 0 * 16(r); \
+	vmovdqu t1, 1 * 16(r); \
+	vmovdqu t2, 2 * 16(r); \
+	vmovdqu t3, 3 * 16(r); \
+	\
+	/* \
+	 * t2 = krl; \
+	 * t2 &= rl; \
+	 * rr ^= rol32(t2, 1); \
+	 */ \
+	vmovd krl, t0; \
+	vpshufb tt0, t0, t3; \
+	vpsrldq $1, t0, t0; \
+	vpshufb tt0, t0, t2; \
+	vpsrldq $1, t0, t0; \
+	vpshufb tt0, t0, t1; \
+	vpsrldq $1, t0, t0; \
+	vpshufb tt0, t0, t0; \
+	\
+	vpand 0 * 16(r), t0, t0; \
+	vpand 1 * 16(r), t1, t1; \
+	vpand 2 * 16(r), t2, t2; \
+	vpand 3 * 16(r), t3, t3; \
+	\
+	rol32_1_16(t3, t2, t1, t0, tt1, tt2, tt3, tt0); \
+	\
+	vpxor 4 * 16(r), t0, t0; \
+	vpxor 5 * 16(r), t1, t1; \
+	vpxor 6 * 16(r), t2, t2; \
+	vpxor 7 * 16(r), t3, t3; \
+	vmovdqu t0, 4 * 16(r); \
+	vmovdqu t1, 5 * 16(r); \
+	vmovdqu t2, 6 * 16(r); \
+	vmovdqu t3, 7 * 16(r); \
+	\
+	/* \
+	 * t0 = klr; \
+	 * t0 |= lr; \
+	 * ll ^= t0; \
+	 */ \
+	\
+	vmovd klr, t0; \
+	vpshufb tt0, t0, t3; \
+	vpsrldq $1, t0, t0; \
+	vpshufb tt0, t0, t2; \
+	vpsrldq $1, t0, t0; \
+	vpshufb tt0, t0, t1; \
+	vpsrldq $1, t0, t0; \
+	vpshufb tt0, t0, t0; \
+	\
+	vpor l4, t0, t0; \
+	vpor l5, t1, t1; \
+	vpor l6, t2, t2; \
+	vpor l7, t3, t3; \
+	\
+	vpxor l0, t0, l0; \
+	vmovdqu l0, 0 * 16(l); \
+	vpxor l1, t1, l1; \
+	vmovdqu l1, 1 * 16(l); \
+	vpxor l2, t2, l2; \
+	vmovdqu l2, 2 * 16(l); \
+	vpxor l3, t3, l3; \
+	vmovdqu l3, 3 * 16(l);
+
+#define transpose_4x4(x0, x1, x2, x3, t1, t2) \
+	vpunpckhdq x1, x0, t2; \
+	vpunpckldq x1, x0, x0; \
+	\
+	vpunpckldq x3, x2, t1; \
+	vpunpckhdq x3, x2, x2; \
+	\
+	vpunpckhqdq t1, x0, x1; \
+	vpunpcklqdq t1, x0, x0; \
+	\
+	vpunpckhqdq x2, t2, x3; \
+	vpunpcklqdq x2, t2, x2;
+
+#define byteslice_16x16b(a0, b0, c0, d0, a1, b1, c1, d1, a2, b2, c2, d2, a3, \
+			 b3, c3, d3, st0, st1) \
+	vmovdqu d2, st0; \
+	vmovdqu d3, st1; \
+	transpose_4x4(a0, a1, a2, a3, d2, d3); \
+	transpose_4x4(b0, b1, b2, b3, d2, d3); \
+	vmovdqu st0, d2; \
+	vmovdqu st1, d3; \
+	\
+	vmovdqu a0, st0; \
+	vmovdqu a1, st1; \
+	transpose_4x4(c0, c1, c2, c3, a0, a1); \
+	transpose_4x4(d0, d1, d2, d3, a0, a1); \
+	\
+	vmovdqu .Lshufb_16x16b, a0; \
+	vmovdqu st1, a1; \
+	vpshufb a0, a2, a2; \
+	vpshufb a0, a3, a3; \
+	vpshufb a0, b0, b0; \
+	vpshufb a0, b1, b1; \
+	vpshufb a0, b2, b2; \
+	vpshufb a0, b3, b3; \
+	vpshufb a0, a1, a1; \
+	vpshufb a0, c0, c0; \
+	vpshufb a0, c1, c1; \
+	vpshufb a0, c2, c2; \
+	vpshufb a0, c3, c3; \
+	vpshufb a0, d0, d0; \
+	vpshufb a0, d1, d1; \
+	vpshufb a0, d2, d2; \
+	vpshufb a0, d3, d3; \
+	vmovdqu d3, st1; \
+	vmovdqu st0, d3; \
+	vpshufb a0, d3, a0; \
+	vmovdqu d2, st0; \
+	\
+	transpose_4x4(a0, b0, c0, d0, d2, d3); \
+	transpose_4x4(a1, b1, c1, d1, d2, d3); \
+	vmovdqu st0, d2; \
+	vmovdqu st1, d3; \
+	\
+	vmovdqu b0, st0; \
+	vmovdqu b1, st1; \
+	transpose_4x4(a2, b2, c2, d2, b0, b1); \
+	transpose_4x4(a3, b3, c3, d3, b0, b1); \
+	vmovdqu st0, b0; \
+	vmovdqu st1, b1; \
+	/* does not adjust output bytes inside vectors */
+
+/* load blocks to registers and apply pre-whitening */
+#define inpack16_pre(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+		     y6, y7, rio, key) \
+	vmovq key, x0; \
+	vpshufb .Lpack_bswap, x0, x0; \
+	\
+	vpxor 0 * 16(rio), x0, y7; \
+	vpxor 1 * 16(rio), x0, y6; \
+	vpxor 2 * 16(rio), x0, y5; \
+	vpxor 3 * 16(rio), x0, y4; \
+	vpxor 4 * 16(rio), x0, y3; \
+	vpxor 5 * 16(rio), x0, y2; \
+	vpxor 6 * 16(rio), x0, y1; \
+	vpxor 7 * 16(rio), x0, y0; \
+	vpxor 8 * 16(rio), x0, x7; \
+	vpxor 9 * 16(rio), x0, x6; \
+	vpxor 10 * 16(rio), x0, x5; \
+	vpxor 11 * 16(rio), x0, x4; \
+	vpxor 12 * 16(rio), x0, x3; \
+	vpxor 13 * 16(rio), x0, x2; \
+	vpxor 14 * 16(rio), x0, x1; \
+	vpxor 15 * 16(rio), x0, x0;
+
+/* byteslice pre-whitened blocks and store to temporary memory */
+#define inpack16_post(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+		      y6, y7, mem_ab, mem_cd) \
+	byteslice_16x16b(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, \
+			 y5, y6, y7, (mem_ab), (mem_cd)); \
+	\
+	vmovdqu x0, 0 * 16(mem_ab); \
+	vmovdqu x1, 1 * 16(mem_ab); \
+	vmovdqu x2, 2 * 16(mem_ab); \
+	vmovdqu x3, 3 * 16(mem_ab); \
+	vmovdqu x4, 4 * 16(mem_ab); \
+	vmovdqu x5, 5 * 16(mem_ab); \
+	vmovdqu x6, 6 * 16(mem_ab); \
+	vmovdqu x7, 7 * 16(mem_ab); \
+	vmovdqu y0, 0 * 16(mem_cd); \
+	vmovdqu y1, 1 * 16(mem_cd); \
+	vmovdqu y2, 2 * 16(mem_cd); \
+	vmovdqu y3, 3 * 16(mem_cd); \
+	vmovdqu y4, 4 * 16(mem_cd); \
+	vmovdqu y5, 5 * 16(mem_cd); \
+	vmovdqu y6, 6 * 16(mem_cd); \
+	vmovdqu y7, 7 * 16(mem_cd);
+
+/* de-byteslice, apply post-whitening and store blocks */
+#define outunpack16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, \
+		    y5, y6, y7, key, stack_tmp0, stack_tmp1) \
+	byteslice_16x16b(y0, y4, x0, x4, y1, y5, x1, x5, y2, y6, x2, x6, y3, \
+			 y7, x3, x7, stack_tmp0, stack_tmp1); \
+	\
+	vmovdqu x0, stack_tmp0; \
+	\
+	vmovq key, x0; \
+	vpshufb .Lpack_bswap, x0, x0; \
+	\
+	vpxor x0, y7, y7; \
+	vpxor x0, y6, y6; \
+	vpxor x0, y5, y5; \
+	vpxor x0, y4, y4; \
+	vpxor x0, y3, y3; \
+	vpxor x0, y2, y2; \
+	vpxor x0, y1, y1; \
+	vpxor x0, y0, y0; \
+	vpxor x0, x7, x7; \
+	vpxor x0, x6, x6; \
+	vpxor x0, x5, x5; \
+	vpxor x0, x4, x4; \
+	vpxor x0, x3, x3; \
+	vpxor x0, x2, x2; \
+	vpxor x0, x1, x1; \
+	vpxor stack_tmp0, x0, x0;
+
+#define write_output(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+		     y6, y7, rio) \
+	vmovdqu x0, 0 * 16(rio); \
+	vmovdqu x1, 1 * 16(rio); \
+	vmovdqu x2, 2 * 16(rio); \
+	vmovdqu x3, 3 * 16(rio); \
+	vmovdqu x4, 4 * 16(rio); \
+	vmovdqu x5, 5 * 16(rio); \
+	vmovdqu x6, 6 * 16(rio); \
+	vmovdqu x7, 7 * 16(rio); \
+	vmovdqu y0, 8 * 16(rio); \
+	vmovdqu y1, 9 * 16(rio); \
+	vmovdqu y2, 10 * 16(rio); \
+	vmovdqu y3, 11 * 16(rio); \
+	vmovdqu y4, 12 * 16(rio); \
+	vmovdqu y5, 13 * 16(rio); \
+	vmovdqu y6, 14 * 16(rio); \
+	vmovdqu y7, 15 * 16(rio);
+
+.data
+.align 16
+
+#define SHUFB_BYTES(idx) \
+	0 + (idx), 4 + (idx), 8 + (idx), 12 + (idx)
+
+.Lshufb_16x16b:
+	.byte SHUFB_BYTES(0), SHUFB_BYTES(1), SHUFB_BYTES(2), SHUFB_BYTES(3);
+
+.Lpack_bswap:
+	.long 0x00010203
+	.long 0x04050607
+	.long 0x80808080
+	.long 0x80808080
+
+/* For CTR-mode IV byteswap */
+.Lbswap128_mask:
+	.byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+
+/*
+ * pre-SubByte transform
+ *
+ * pre-lookup for sbox1, sbox2, sbox3:
+ *   swap_bitendianness(
+ *       isom_map_camellia_to_aes(
+ *           camellia_f(
+ *               swap_bitendianess(in)
+ *           )
+ *       )
+ *   )
+ *
+ * (note: '⊕ 0xc5' inside camellia_f())
+ */
+.Lpre_tf_lo_s1:
+	.byte 0x45, 0xe8, 0x40, 0xed, 0x2e, 0x83, 0x2b, 0x86
+	.byte 0x4b, 0xe6, 0x4e, 0xe3, 0x20, 0x8d, 0x25, 0x88
+.Lpre_tf_hi_s1:
+	.byte 0x00, 0x51, 0xf1, 0xa0, 0x8a, 0xdb, 0x7b, 0x2a
+	.byte 0x09, 0x58, 0xf8, 0xa9, 0x83, 0xd2, 0x72, 0x23
+
+/*
+ * pre-SubByte transform
+ *
+ * pre-lookup for sbox4:
+ *   swap_bitendianness(
+ *       isom_map_camellia_to_aes(
+ *           camellia_f(
+ *               swap_bitendianess(in <<< 1)
+ *           )
+ *       )
+ *   )
+ *
+ * (note: '⊕ 0xc5' inside camellia_f())
+ */
+.Lpre_tf_lo_s4:
+	.byte 0x45, 0x40, 0x2e, 0x2b, 0x4b, 0x4e, 0x20, 0x25
+	.byte 0x14, 0x11, 0x7f, 0x7a, 0x1a, 0x1f, 0x71, 0x74
+.Lpre_tf_hi_s4:
+	.byte 0x00, 0xf1, 0x8a, 0x7b, 0x09, 0xf8, 0x83, 0x72
+	.byte 0xad, 0x5c, 0x27, 0xd6, 0xa4, 0x55, 0x2e, 0xdf
+
+/*
+ * post-SubByte transform
+ *
+ * post-lookup for sbox1, sbox4:
+ *  swap_bitendianness(
+ *      camellia_h(
+ *          isom_map_aes_to_camellia(
+ *              swap_bitendianness(
+ *                  aes_inverse_affine_transform(in)
+ *              )
+ *          )
+ *      )
+ *  )
+ *
+ * (note: '⊕ 0x6e' inside camellia_h())
+ */
+.Lpost_tf_lo_s1:
+	.byte 0x3c, 0xcc, 0xcf, 0x3f, 0x32, 0xc2, 0xc1, 0x31
+	.byte 0xdc, 0x2c, 0x2f, 0xdf, 0xd2, 0x22, 0x21, 0xd1
+.Lpost_tf_hi_s1:
+	.byte 0x00, 0xf9, 0x86, 0x7f, 0xd7, 0x2e, 0x51, 0xa8
+	.byte 0xa4, 0x5d, 0x22, 0xdb, 0x73, 0x8a, 0xf5, 0x0c
+
+/*
+ * post-SubByte transform
+ *
+ * post-lookup for sbox2:
+ *  swap_bitendianness(
+ *      camellia_h(
+ *          isom_map_aes_to_camellia(
+ *              swap_bitendianness(
+ *                  aes_inverse_affine_transform(in)
+ *              )
+ *          )
+ *      )
+ *  ) <<< 1
+ *
+ * (note: '⊕ 0x6e' inside camellia_h())
+ */
+.Lpost_tf_lo_s2:
+	.byte 0x78, 0x99, 0x9f, 0x7e, 0x64, 0x85, 0x83, 0x62
+	.byte 0xb9, 0x58, 0x5e, 0xbf, 0xa5, 0x44, 0x42, 0xa3
+.Lpost_tf_hi_s2:
+	.byte 0x00, 0xf3, 0x0d, 0xfe, 0xaf, 0x5c, 0xa2, 0x51
+	.byte 0x49, 0xba, 0x44, 0xb7, 0xe6, 0x15, 0xeb, 0x18
+
+/*
+ * post-SubByte transform
+ *
+ * post-lookup for sbox3:
+ *  swap_bitendianness(
+ *      camellia_h(
+ *          isom_map_aes_to_camellia(
+ *              swap_bitendianness(
+ *                  aes_inverse_affine_transform(in)
+ *              )
+ *          )
+ *      )
+ *  ) >>> 1
+ *
+ * (note: '⊕ 0x6e' inside camellia_h())
+ */
+.Lpost_tf_lo_s3:
+	.byte 0x1e, 0x66, 0xe7, 0x9f, 0x19, 0x61, 0xe0, 0x98
+	.byte 0x6e, 0x16, 0x97, 0xef, 0x69, 0x11, 0x90, 0xe8
+.Lpost_tf_hi_s3:
+	.byte 0x00, 0xfc, 0x43, 0xbf, 0xeb, 0x17, 0xa8, 0x54
+	.byte 0x52, 0xae, 0x11, 0xed, 0xb9, 0x45, 0xfa, 0x06
+
+/* For isolating SubBytes from AESENCLAST, inverse shift row */
+.Linv_shift_row:
+	.byte 0x00, 0x0d, 0x0a, 0x07, 0x04, 0x01, 0x0e, 0x0b
+	.byte 0x08, 0x05, 0x02, 0x0f, 0x0c, 0x09, 0x06, 0x03
+
+/* 4-bit mask */
+.align 4
+.L0f0f0f0f:
+	.long 0x0f0f0f0f
+
+.text
+
+.align 8
+.type   __camellia_enc_blk16,@function;
+
+__camellia_enc_blk16:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rax: temporary storage, 256 bytes
+	 *	%xmm0..%xmm15: 16 plaintext blocks
+	 * output:
+	 *	%xmm0..%xmm15: 16 encrypted blocks, order swapped:
+	 *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
+	 */
+
+	leaq 8 * 16(%rax), %rcx;
+
+	inpack16_post(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+		      %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+		      %xmm15, %rax, %rcx);
+
+	enc_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+		     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+		     %xmm15, %rax, %rcx, 0);
+
+	fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+	      %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+	      %xmm15,
+	      ((key_table + (8) * 8) + 0)(CTX),
+	      ((key_table + (8) * 8) + 4)(CTX),
+	      ((key_table + (8) * 8) + 8)(CTX),
+	      ((key_table + (8) * 8) + 12)(CTX));
+
+	enc_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+		     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+		     %xmm15, %rax, %rcx, 8);
+
+	fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+	      %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+	      %xmm15,
+	      ((key_table + (16) * 8) + 0)(CTX),
+	      ((key_table + (16) * 8) + 4)(CTX),
+	      ((key_table + (16) * 8) + 8)(CTX),
+	      ((key_table + (16) * 8) + 12)(CTX));
+
+	enc_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+		     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+		     %xmm15, %rax, %rcx, 16);
+
+	movl $24, %r8d;
+	cmpl $16, key_length(CTX);
+	jne .Lenc_max32;
+
+.Lenc_done:
+	/* load CD for output */
+	vmovdqu 0 * 16(%rcx), %xmm8;
+	vmovdqu 1 * 16(%rcx), %xmm9;
+	vmovdqu 2 * 16(%rcx), %xmm10;
+	vmovdqu 3 * 16(%rcx), %xmm11;
+	vmovdqu 4 * 16(%rcx), %xmm12;
+	vmovdqu 5 * 16(%rcx), %xmm13;
+	vmovdqu 6 * 16(%rcx), %xmm14;
+	vmovdqu 7 * 16(%rcx), %xmm15;
+
+	outunpack16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+		    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+		    %xmm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 16(%rax));
+
+	ret;
+
+.align 8
+.Lenc_max32:
+	movl $32, %r8d;
+
+	fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+	      %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+	      %xmm15,
+	      ((key_table + (24) * 8) + 0)(CTX),
+	      ((key_table + (24) * 8) + 4)(CTX),
+	      ((key_table + (24) * 8) + 8)(CTX),
+	      ((key_table + (24) * 8) + 12)(CTX));
+
+	enc_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+		     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+		     %xmm15, %rax, %rcx, 24);
+
+	jmp .Lenc_done;
+
+.align 8
+.type   __camellia_dec_blk16,@function;
+
+__camellia_dec_blk16:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rax: temporary storage, 256 bytes
+	 *	%r8d: 24 for 16 byte key, 32 for larger
+	 *	%xmm0..%xmm15: 16 encrypted blocks
+	 * output:
+	 *	%xmm0..%xmm15: 16 plaintext blocks, order swapped:
+	 *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
+	 */
+
+	leaq 8 * 16(%rax), %rcx;
+
+	inpack16_post(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+		      %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+		      %xmm15, %rax, %rcx);
+
+	cmpl $32, %r8d;
+	je .Ldec_max32;
+
+.Ldec_max24:
+	dec_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+		     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+		     %xmm15, %rax, %rcx, 16);
+
+	fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+	      %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+	      %xmm15,
+	      ((key_table + (16) * 8) + 8)(CTX),
+	      ((key_table + (16) * 8) + 12)(CTX),
+	      ((key_table + (16) * 8) + 0)(CTX),
+	      ((key_table + (16) * 8) + 4)(CTX));
+
+	dec_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+		     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+		     %xmm15, %rax, %rcx, 8);
+
+	fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+	      %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+	      %xmm15,
+	      ((key_table + (8) * 8) + 8)(CTX),
+	      ((key_table + (8) * 8) + 12)(CTX),
+	      ((key_table + (8) * 8) + 0)(CTX),
+	      ((key_table + (8) * 8) + 4)(CTX));
+
+	dec_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+		     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+		     %xmm15, %rax, %rcx, 0);
+
+	/* load CD for output */
+	vmovdqu 0 * 16(%rcx), %xmm8;
+	vmovdqu 1 * 16(%rcx), %xmm9;
+	vmovdqu 2 * 16(%rcx), %xmm10;
+	vmovdqu 3 * 16(%rcx), %xmm11;
+	vmovdqu 4 * 16(%rcx), %xmm12;
+	vmovdqu 5 * 16(%rcx), %xmm13;
+	vmovdqu 6 * 16(%rcx), %xmm14;
+	vmovdqu 7 * 16(%rcx), %xmm15;
+
+	outunpack16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+		    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+		    %xmm15, (key_table)(CTX), (%rax), 1 * 16(%rax));
+
+	ret;
+
+.align 8
+.Ldec_max32:
+	dec_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+		     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+		     %xmm15, %rax, %rcx, 24);
+
+	fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+	      %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+	      %xmm15,
+	      ((key_table + (24) * 8) + 8)(CTX),
+	      ((key_table + (24) * 8) + 12)(CTX),
+	      ((key_table + (24) * 8) + 0)(CTX),
+	      ((key_table + (24) * 8) + 4)(CTX));
+
+	jmp .Ldec_max24;
+
+.align 8
+.global camellia_ecb_enc_16way
+.type   camellia_ecb_enc_16way,@function;
+
+camellia_ecb_enc_16way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst (16 blocks)
+	 *	%rdx: src (16 blocks)
+	 */
+
+	inpack16_pre(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+		     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+		     %xmm15, %rdx, (key_table)(CTX));
+
+	/* now dst can be used as temporary buffer (even in src == dst case) */
+	movq	%rsi, %rax;
+
+	call __camellia_enc_blk16;
+
+	write_output(%xmm7, %xmm6, %xmm5, %xmm4, %xmm3, %xmm2, %xmm1, %xmm0,
+		     %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
+		     %xmm8, %rsi);
+
+	ret;
+
+.align 8
+.global camellia_ecb_dec_16way
+.type   camellia_ecb_dec_16way,@function;
+
+camellia_ecb_dec_16way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst (16 blocks)
+	 *	%rdx: src (16 blocks)
+	 */
+
+	cmpl $16, key_length(CTX);
+	movl $32, %r8d;
+	movl $24, %eax;
+	cmovel %eax, %r8d; /* max */
+
+	inpack16_pre(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+		     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+		     %xmm15, %rdx, (key_table)(CTX, %r8, 8));
+
+	/* now dst can be used as temporary buffer (even in src == dst case) */
+	movq	%rsi, %rax;
+
+	call __camellia_dec_blk16;
+
+	write_output(%xmm7, %xmm6, %xmm5, %xmm4, %xmm3, %xmm2, %xmm1, %xmm0,
+		     %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
+		     %xmm8, %rsi);
+
+	ret;
+
+.align 8
+.global camellia_cbc_dec_16way
+.type   camellia_cbc_dec_16way,@function;
+
+camellia_cbc_dec_16way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst (16 blocks)
+	 *	%rdx: src (16 blocks)
+	 */
+
+	cmpl $16, key_length(CTX);
+	movl $32, %r8d;
+	movl $24, %eax;
+	cmovel %eax, %r8d; /* max */
+
+	inpack16_pre(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+		     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
+		     %xmm15, %rdx, (key_table)(CTX, %r8, 8));
+
+	/*
+	 * dst might still be in-use (in case dst == src), so use stack for
+	 * temporary storage.
+	 */
+	subq $(16 * 16), %rsp;
+	movq %rsp, %rax;
+
+	call __camellia_dec_blk16;
+
+	addq $(16 * 16), %rsp;
+
+	vpxor (0 * 16)(%rdx), %xmm6, %xmm6;
+	vpxor (1 * 16)(%rdx), %xmm5, %xmm5;
+	vpxor (2 * 16)(%rdx), %xmm4, %xmm4;
+	vpxor (3 * 16)(%rdx), %xmm3, %xmm3;
+	vpxor (4 * 16)(%rdx), %xmm2, %xmm2;
+	vpxor (5 * 16)(%rdx), %xmm1, %xmm1;
+	vpxor (6 * 16)(%rdx), %xmm0, %xmm0;
+	vpxor (7 * 16)(%rdx), %xmm15, %xmm15;
+	vpxor (8 * 16)(%rdx), %xmm14, %xmm14;
+	vpxor (9 * 16)(%rdx), %xmm13, %xmm13;
+	vpxor (10 * 16)(%rdx), %xmm12, %xmm12;
+	vpxor (11 * 16)(%rdx), %xmm11, %xmm11;
+	vpxor (12 * 16)(%rdx), %xmm10, %xmm10;
+	vpxor (13 * 16)(%rdx), %xmm9, %xmm9;
+	vpxor (14 * 16)(%rdx), %xmm8, %xmm8;
+	write_output(%xmm7, %xmm6, %xmm5, %xmm4, %xmm3, %xmm2, %xmm1, %xmm0,
+		     %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
+		     %xmm8, %rsi);
+
+	ret;
+
+#define inc_le128(x, minus_one, tmp) \
+	vpcmpeqq minus_one, x, tmp; \
+	vpsubq minus_one, x, x; \
+	vpslldq $8, tmp, tmp; \
+	vpsubq tmp, x, x;
+
+.align 8
+.global camellia_ctr_16way
+.type   camellia_ctr_16way,@function;
+
+camellia_ctr_16way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst (16 blocks)
+	 *	%rdx: src (16 blocks)
+	 *	%rcx: iv (little endian, 128bit)
+	 */
+
+	subq $(16 * 16), %rsp;
+	movq %rsp, %rax;
+
+	vmovdqa .Lbswap128_mask, %xmm14;
+
+	/* load IV and byteswap */
+	vmovdqu (%rcx), %xmm0;
+	vpshufb %xmm14, %xmm0, %xmm15;
+	vmovdqu %xmm15, 15 * 16(%rax);
+
+	vpcmpeqd %xmm15, %xmm15, %xmm15;
+	vpsrldq $8, %xmm15, %xmm15; /* low: -1, high: 0 */
+
+	/* construct IVs */
+	inc_le128(%xmm0, %xmm15, %xmm13);
+	vpshufb %xmm14, %xmm0, %xmm13;
+	vmovdqu %xmm13, 14 * 16(%rax);
+	inc_le128(%xmm0, %xmm15, %xmm13);
+	vpshufb %xmm14, %xmm0, %xmm13;
+	vmovdqu %xmm13, 13 * 16(%rax);
+	inc_le128(%xmm0, %xmm15, %xmm13);
+	vpshufb %xmm14, %xmm0, %xmm12;
+	inc_le128(%xmm0, %xmm15, %xmm13);
+	vpshufb %xmm14, %xmm0, %xmm11;
+	inc_le128(%xmm0, %xmm15, %xmm13);
+	vpshufb %xmm14, %xmm0, %xmm10;
+	inc_le128(%xmm0, %xmm15, %xmm13);
+	vpshufb %xmm14, %xmm0, %xmm9;
+	inc_le128(%xmm0, %xmm15, %xmm13);
+	vpshufb %xmm14, %xmm0, %xmm8;
+	inc_le128(%xmm0, %xmm15, %xmm13);
+	vpshufb %xmm14, %xmm0, %xmm7;
+	inc_le128(%xmm0, %xmm15, %xmm13);
+	vpshufb %xmm14, %xmm0, %xmm6;
+	inc_le128(%xmm0, %xmm15, %xmm13);
+	vpshufb %xmm14, %xmm0, %xmm5;
+	inc_le128(%xmm0, %xmm15, %xmm13);
+	vpshufb %xmm14, %xmm0, %xmm4;
+	inc_le128(%xmm0, %xmm15, %xmm13);
+	vpshufb %xmm14, %xmm0, %xmm3;
+	inc_le128(%xmm0, %xmm15, %xmm13);
+	vpshufb %xmm14, %xmm0, %xmm2;
+	inc_le128(%xmm0, %xmm15, %xmm13);
+	vpshufb %xmm14, %xmm0, %xmm1;
+	inc_le128(%xmm0, %xmm15, %xmm13);
+	vmovdqa %xmm0, %xmm13;
+	vpshufb %xmm14, %xmm0, %xmm0;
+	inc_le128(%xmm13, %xmm15, %xmm14);
+	vmovdqu %xmm13, (%rcx);
+
+	/* inpack16_pre: */
+	vmovq (key_table)(CTX), %xmm15;
+	vpshufb .Lpack_bswap, %xmm15, %xmm15;
+	vpxor %xmm0, %xmm15, %xmm0;
+	vpxor %xmm1, %xmm15, %xmm1;
+	vpxor %xmm2, %xmm15, %xmm2;
+	vpxor %xmm3, %xmm15, %xmm3;
+	vpxor %xmm4, %xmm15, %xmm4;
+	vpxor %xmm5, %xmm15, %xmm5;
+	vpxor %xmm6, %xmm15, %xmm6;
+	vpxor %xmm7, %xmm15, %xmm7;
+	vpxor %xmm8, %xmm15, %xmm8;
+	vpxor %xmm9, %xmm15, %xmm9;
+	vpxor %xmm10, %xmm15, %xmm10;
+	vpxor %xmm11, %xmm15, %xmm11;
+	vpxor %xmm12, %xmm15, %xmm12;
+	vpxor 13 * 16(%rax), %xmm15, %xmm13;
+	vpxor 14 * 16(%rax), %xmm15, %xmm14;
+	vpxor 15 * 16(%rax), %xmm15, %xmm15;
+
+	call __camellia_enc_blk16;
+
+	addq $(16 * 16), %rsp;
+
+	vpxor 0 * 16(%rdx), %xmm7, %xmm7;
+	vpxor 1 * 16(%rdx), %xmm6, %xmm6;
+	vpxor 2 * 16(%rdx), %xmm5, %xmm5;
+	vpxor 3 * 16(%rdx), %xmm4, %xmm4;
+	vpxor 4 * 16(%rdx), %xmm3, %xmm3;
+	vpxor 5 * 16(%rdx), %xmm2, %xmm2;
+	vpxor 6 * 16(%rdx), %xmm1, %xmm1;
+	vpxor 7 * 16(%rdx), %xmm0, %xmm0;
+	vpxor 8 * 16(%rdx), %xmm15, %xmm15;
+	vpxor 9 * 16(%rdx), %xmm14, %xmm14;
+	vpxor 10 * 16(%rdx), %xmm13, %xmm13;
+	vpxor 11 * 16(%rdx), %xmm12, %xmm12;
+	vpxor 12 * 16(%rdx), %xmm11, %xmm11;
+	vpxor 13 * 16(%rdx), %xmm10, %xmm10;
+	vpxor 14 * 16(%rdx), %xmm9, %xmm9;
+	vpxor 15 * 16(%rdx), %xmm8, %xmm8;
+	write_output(%xmm7, %xmm6, %xmm5, %xmm4, %xmm3, %xmm2, %xmm1, %xmm0,
+		     %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
+		     %xmm8, %rsi);
+
+	ret;
diff --git a/arch/x86/crypto/camellia_aesni_avx_glue.c b/arch/x86/crypto/camellia_aesni_avx_glue.c
new file mode 100644
index 0000000..96cbb60
--- /dev/null
+++ b/arch/x86/crypto/camellia_aesni_avx_glue.c
@@ -0,0 +1,558 @@
+/*
+ * Glue Code for x86_64/AVX/AES-NI assembler optimized version of Camellia
+ *
+ * Copyright © 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <crypto/algapi.h>
+#include <crypto/ctr.h>
+#include <crypto/lrw.h>
+#include <crypto/xts.h>
+#include <asm/xcr.h>
+#include <asm/xsave.h>
+#include <asm/crypto/camellia.h>
+#include <asm/crypto/ablk_helper.h>
+#include <asm/crypto/glue_helper.h>
+
+#define CAMELLIA_AESNI_PARALLEL_BLOCKS 16
+
+/* 16-way AES-NI parallel cipher functions */
+asmlinkage void camellia_ecb_enc_16way(struct camellia_ctx *ctx, u8 *dst,
+				       const u8 *src);
+asmlinkage void camellia_ecb_dec_16way(struct camellia_ctx *ctx, u8 *dst,
+				       const u8 *src);
+
+asmlinkage void camellia_cbc_dec_16way(struct camellia_ctx *ctx, u8 *dst,
+				       const u8 *src);
+asmlinkage void camellia_ctr_16way(struct camellia_ctx *ctx, u8 *dst,
+				   const u8 *src, le128 *iv);
+
+static const struct common_glue_ctx camellia_enc = {
+	.num_funcs = 3,
+	.fpu_blocks_limit = CAMELLIA_AESNI_PARALLEL_BLOCKS,
+
+	.funcs = { {
+		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
+		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_ecb_enc_16way) }
+	}, {
+		.num_blocks = 2,
+		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_enc_blk_2way) }
+	}, {
+		.num_blocks = 1,
+		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_enc_blk) }
+	} }
+};
+
+static const struct common_glue_ctx camellia_ctr = {
+	.num_funcs = 3,
+	.fpu_blocks_limit = CAMELLIA_AESNI_PARALLEL_BLOCKS,
+
+	.funcs = { {
+		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
+		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_ctr_16way) }
+	}, {
+		.num_blocks = 2,
+		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_crypt_ctr_2way) }
+	}, {
+		.num_blocks = 1,
+		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_crypt_ctr) }
+	} }
+};
+
+static const struct common_glue_ctx camellia_dec = {
+	.num_funcs = 3,
+	.fpu_blocks_limit = CAMELLIA_AESNI_PARALLEL_BLOCKS,
+
+	.funcs = { {
+		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
+		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_ecb_dec_16way) }
+	}, {
+		.num_blocks = 2,
+		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_dec_blk_2way) }
+	}, {
+		.num_blocks = 1,
+		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_dec_blk) }
+	} }
+};
+
+static const struct common_glue_ctx camellia_dec_cbc = {
+	.num_funcs = 3,
+	.fpu_blocks_limit = CAMELLIA_AESNI_PARALLEL_BLOCKS,
+
+	.funcs = { {
+		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
+		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_cbc_dec_16way) }
+	}, {
+		.num_blocks = 2,
+		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_decrypt_cbc_2way) }
+	}, {
+		.num_blocks = 1,
+		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_dec_blk) }
+	} }
+};
+
+static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	return glue_ecb_crypt_128bit(&camellia_enc, desc, dst, src, nbytes);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	return glue_ecb_crypt_128bit(&camellia_dec, desc, dst, src, nbytes);
+}
+
+static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	return glue_cbc_encrypt_128bit(GLUE_FUNC_CAST(camellia_enc_blk), desc,
+				       dst, src, nbytes);
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	return glue_cbc_decrypt_128bit(&camellia_dec_cbc, desc, dst, src,
+				       nbytes);
+}
+
+static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		     struct scatterlist *src, unsigned int nbytes)
+{
+	return glue_ctr_crypt_128bit(&camellia_ctr, desc, dst, src, nbytes);
+}
+
+static inline bool camellia_fpu_begin(bool fpu_enabled, unsigned int nbytes)
+{
+	return glue_fpu_begin(CAMELLIA_BLOCK_SIZE,
+			      CAMELLIA_AESNI_PARALLEL_BLOCKS, NULL, fpu_enabled,
+			      nbytes);
+}
+
+static inline void camellia_fpu_end(bool fpu_enabled)
+{
+	glue_fpu_end(fpu_enabled);
+}
+
+static int camellia_setkey(struct crypto_tfm *tfm, const u8 *in_key,
+			   unsigned int key_len)
+{
+	return __camellia_setkey(crypto_tfm_ctx(tfm), in_key, key_len,
+				 &tfm->crt_flags);
+}
+
+struct crypt_priv {
+	struct camellia_ctx *ctx;
+	bool fpu_enabled;
+};
+
+static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
+{
+	const unsigned int bsize = CAMELLIA_BLOCK_SIZE;
+	struct crypt_priv *ctx = priv;
+	int i;
+
+	ctx->fpu_enabled = camellia_fpu_begin(ctx->fpu_enabled, nbytes);
+
+	if (nbytes >= CAMELLIA_AESNI_PARALLEL_BLOCKS * bsize) {
+		camellia_ecb_enc_16way(ctx->ctx, srcdst, srcdst);
+		srcdst += bsize * CAMELLIA_AESNI_PARALLEL_BLOCKS;
+		nbytes -= bsize * CAMELLIA_AESNI_PARALLEL_BLOCKS;
+	}
+
+	while (nbytes >= CAMELLIA_PARALLEL_BLOCKS * bsize) {
+		camellia_enc_blk_2way(ctx->ctx, srcdst, srcdst);
+		srcdst += bsize * CAMELLIA_PARALLEL_BLOCKS;
+		nbytes -= bsize * CAMELLIA_PARALLEL_BLOCKS;
+	}
+
+	for (i = 0; i < nbytes / bsize; i++, srcdst += bsize)
+		camellia_enc_blk(ctx->ctx, srcdst, srcdst);
+}
+
+static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
+{
+	const unsigned int bsize = CAMELLIA_BLOCK_SIZE;
+	struct crypt_priv *ctx = priv;
+	int i;
+
+	ctx->fpu_enabled = camellia_fpu_begin(ctx->fpu_enabled, nbytes);
+
+	if (nbytes >= CAMELLIA_AESNI_PARALLEL_BLOCKS * bsize) {
+		camellia_ecb_dec_16way(ctx->ctx, srcdst, srcdst);
+		srcdst += bsize * CAMELLIA_AESNI_PARALLEL_BLOCKS;
+		nbytes -= bsize * CAMELLIA_AESNI_PARALLEL_BLOCKS;
+	}
+
+	while (nbytes >= CAMELLIA_PARALLEL_BLOCKS * bsize) {
+		camellia_dec_blk_2way(ctx->ctx, srcdst, srcdst);
+		srcdst += bsize * CAMELLIA_PARALLEL_BLOCKS;
+		nbytes -= bsize * CAMELLIA_PARALLEL_BLOCKS;
+	}
+
+	for (i = 0; i < nbytes / bsize; i++, srcdst += bsize)
+		camellia_dec_blk(ctx->ctx, srcdst, srcdst);
+}
+
+static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct camellia_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	be128 buf[CAMELLIA_AESNI_PARALLEL_BLOCKS];
+	struct crypt_priv crypt_ctx = {
+		.ctx = &ctx->camellia_ctx,
+		.fpu_enabled = false,
+	};
+	struct lrw_crypt_req req = {
+		.tbuf = buf,
+		.tbuflen = sizeof(buf),
+
+		.table_ctx = &ctx->lrw_table,
+		.crypt_ctx = &crypt_ctx,
+		.crypt_fn = encrypt_callback,
+	};
+	int ret;
+
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+	ret = lrw_crypt(desc, dst, src, nbytes, &req);
+	camellia_fpu_end(crypt_ctx.fpu_enabled);
+
+	return ret;
+}
+
+static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct camellia_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	be128 buf[CAMELLIA_AESNI_PARALLEL_BLOCKS];
+	struct crypt_priv crypt_ctx = {
+		.ctx = &ctx->camellia_ctx,
+		.fpu_enabled = false,
+	};
+	struct lrw_crypt_req req = {
+		.tbuf = buf,
+		.tbuflen = sizeof(buf),
+
+		.table_ctx = &ctx->lrw_table,
+		.crypt_ctx = &crypt_ctx,
+		.crypt_fn = decrypt_callback,
+	};
+	int ret;
+
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+	ret = lrw_crypt(desc, dst, src, nbytes, &req);
+	camellia_fpu_end(crypt_ctx.fpu_enabled);
+
+	return ret;
+}
+
+static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct camellia_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	be128 buf[CAMELLIA_AESNI_PARALLEL_BLOCKS];
+	struct crypt_priv crypt_ctx = {
+		.ctx = &ctx->crypt_ctx,
+		.fpu_enabled = false,
+	};
+	struct xts_crypt_req req = {
+		.tbuf = buf,
+		.tbuflen = sizeof(buf),
+
+		.tweak_ctx = &ctx->tweak_ctx,
+		.tweak_fn = XTS_TWEAK_CAST(camellia_enc_blk),
+		.crypt_ctx = &crypt_ctx,
+		.crypt_fn = encrypt_callback,
+	};
+	int ret;
+
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+	ret = xts_crypt(desc, dst, src, nbytes, &req);
+	camellia_fpu_end(crypt_ctx.fpu_enabled);
+
+	return ret;
+}
+
+static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct camellia_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	be128 buf[CAMELLIA_AESNI_PARALLEL_BLOCKS];
+	struct crypt_priv crypt_ctx = {
+		.ctx = &ctx->crypt_ctx,
+		.fpu_enabled = false,
+	};
+	struct xts_crypt_req req = {
+		.tbuf = buf,
+		.tbuflen = sizeof(buf),
+
+		.tweak_ctx = &ctx->tweak_ctx,
+		.tweak_fn = XTS_TWEAK_CAST(camellia_enc_blk),
+		.crypt_ctx = &crypt_ctx,
+		.crypt_fn = decrypt_callback,
+	};
+	int ret;
+
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+	ret = xts_crypt(desc, dst, src, nbytes, &req);
+	camellia_fpu_end(crypt_ctx.fpu_enabled);
+
+	return ret;
+}
+
+static struct crypto_alg cmll_algs[10] = { {
+	.cra_name		= "__ecb-camellia-aesni",
+	.cra_driver_name	= "__driver-ecb-camellia-aesni",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= CAMELLIA_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct camellia_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= CAMELLIA_MIN_KEY_SIZE,
+			.max_keysize	= CAMELLIA_MAX_KEY_SIZE,
+			.setkey		= camellia_setkey,
+			.encrypt	= ecb_encrypt,
+			.decrypt	= ecb_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "__cbc-camellia-aesni",
+	.cra_driver_name	= "__driver-cbc-camellia-aesni",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= CAMELLIA_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct camellia_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= CAMELLIA_MIN_KEY_SIZE,
+			.max_keysize	= CAMELLIA_MAX_KEY_SIZE,
+			.setkey		= camellia_setkey,
+			.encrypt	= cbc_encrypt,
+			.decrypt	= cbc_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "__ctr-camellia-aesni",
+	.cra_driver_name	= "__driver-ctr-camellia-aesni",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= 1,
+	.cra_ctxsize		= sizeof(struct camellia_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= CAMELLIA_MIN_KEY_SIZE,
+			.max_keysize	= CAMELLIA_MAX_KEY_SIZE,
+			.ivsize		= CAMELLIA_BLOCK_SIZE,
+			.setkey		= camellia_setkey,
+			.encrypt	= ctr_crypt,
+			.decrypt	= ctr_crypt,
+		},
+	},
+}, {
+	.cra_name		= "__lrw-camellia-aesni",
+	.cra_driver_name	= "__driver-lrw-camellia-aesni",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= CAMELLIA_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct camellia_lrw_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_exit		= lrw_camellia_exit_tfm,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= CAMELLIA_MIN_KEY_SIZE +
+					  CAMELLIA_BLOCK_SIZE,
+			.max_keysize	= CAMELLIA_MAX_KEY_SIZE +
+					  CAMELLIA_BLOCK_SIZE,
+			.ivsize		= CAMELLIA_BLOCK_SIZE,
+			.setkey		= lrw_camellia_setkey,
+			.encrypt	= lrw_encrypt,
+			.decrypt	= lrw_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "__xts-camellia-aesni",
+	.cra_driver_name	= "__driver-xts-camellia-aesni",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= CAMELLIA_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct camellia_xts_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= CAMELLIA_MIN_KEY_SIZE * 2,
+			.max_keysize	= CAMELLIA_MAX_KEY_SIZE * 2,
+			.ivsize		= CAMELLIA_BLOCK_SIZE,
+			.setkey		= xts_camellia_setkey,
+			.encrypt	= xts_encrypt,
+			.decrypt	= xts_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "ecb(camellia)",
+	.cra_driver_name	= "ecb-camellia-aesni",
+	.cra_priority		= 400,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= CAMELLIA_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct async_helper_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= ablk_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= CAMELLIA_MIN_KEY_SIZE,
+			.max_keysize	= CAMELLIA_MAX_KEY_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= ablk_encrypt,
+			.decrypt	= ablk_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "cbc(camellia)",
+	.cra_driver_name	= "cbc-camellia-aesni",
+	.cra_priority		= 400,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= CAMELLIA_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct async_helper_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= ablk_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= CAMELLIA_MIN_KEY_SIZE,
+			.max_keysize	= CAMELLIA_MAX_KEY_SIZE,
+			.ivsize		= CAMELLIA_BLOCK_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= __ablk_encrypt,
+			.decrypt	= ablk_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "ctr(camellia)",
+	.cra_driver_name	= "ctr-camellia-aesni",
+	.cra_priority		= 400,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= 1,
+	.cra_ctxsize		= sizeof(struct async_helper_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= ablk_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= CAMELLIA_MIN_KEY_SIZE,
+			.max_keysize	= CAMELLIA_MAX_KEY_SIZE,
+			.ivsize		= CAMELLIA_BLOCK_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= ablk_encrypt,
+			.decrypt	= ablk_encrypt,
+			.geniv		= "chainiv",
+		},
+	},
+}, {
+	.cra_name		= "lrw(camellia)",
+	.cra_driver_name	= "lrw-camellia-aesni",
+	.cra_priority		= 400,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= CAMELLIA_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct async_helper_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= ablk_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= CAMELLIA_MIN_KEY_SIZE +
+					  CAMELLIA_BLOCK_SIZE,
+			.max_keysize	= CAMELLIA_MAX_KEY_SIZE +
+					  CAMELLIA_BLOCK_SIZE,
+			.ivsize		= CAMELLIA_BLOCK_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= ablk_encrypt,
+			.decrypt	= ablk_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "xts(camellia)",
+	.cra_driver_name	= "xts-camellia-aesni",
+	.cra_priority		= 400,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= CAMELLIA_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct async_helper_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= ablk_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= CAMELLIA_MIN_KEY_SIZE * 2,
+			.max_keysize	= CAMELLIA_MAX_KEY_SIZE * 2,
+			.ivsize		= CAMELLIA_BLOCK_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= ablk_encrypt,
+			.decrypt	= ablk_decrypt,
+		},
+	},
+} };
+
+static int __init camellia_aesni_init(void)
+{
+	u64 xcr0;
+
+	if (!cpu_has_avx || !cpu_has_aes || !cpu_has_osxsave) {
+		pr_info("AVX or AES-NI instructions are not detected.\n");
+		return -ENODEV;
+	}
+
+	xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
+	if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) {
+		pr_info("AVX detected but unusable.\n");
+		return -ENODEV;
+	}
+
+	return crypto_register_algs(cmll_algs, ARRAY_SIZE(cmll_algs));
+}
+
+static void __exit camellia_aesni_fini(void)
+{
+	crypto_unregister_algs(cmll_algs, ARRAY_SIZE(cmll_algs));
+}
+
+module_init(camellia_aesni_init);
+module_exit(camellia_aesni_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Camellia Cipher Algorithm, AES-NI/AVX optimized");
+MODULE_ALIAS("camellia");
+MODULE_ALIAS("camellia-asm");
diff --git a/arch/x86/crypto/camellia_glue.c b/arch/x86/crypto/camellia_glue.c
index 42ffd2b..5cb86cc 100644
--- a/arch/x86/crypto/camellia_glue.c
+++ b/arch/x86/crypto/camellia_glue.c
@@ -32,53 +32,24 @@
 #include <crypto/algapi.h>
 #include <crypto/lrw.h>
 #include <crypto/xts.h>
+#include <asm/crypto/camellia.h>
 #include <asm/crypto/glue_helper.h>
 
-#define CAMELLIA_MIN_KEY_SIZE	16
-#define CAMELLIA_MAX_KEY_SIZE	32
-#define CAMELLIA_BLOCK_SIZE	16
-#define CAMELLIA_TABLE_BYTE_LEN	272
-
-struct camellia_ctx {
-	u64 key_table[CAMELLIA_TABLE_BYTE_LEN / sizeof(u64)];
-	u32 key_length;
-};
-
 /* regular block cipher functions */
 asmlinkage void __camellia_enc_blk(struct camellia_ctx *ctx, u8 *dst,
 				   const u8 *src, bool xor);
+EXPORT_SYMBOL_GPL(__camellia_enc_blk);
 asmlinkage void camellia_dec_blk(struct camellia_ctx *ctx, u8 *dst,
 				 const u8 *src);
+EXPORT_SYMBOL_GPL(camellia_dec_blk);
 
 /* 2-way parallel cipher functions */
 asmlinkage void __camellia_enc_blk_2way(struct camellia_ctx *ctx, u8 *dst,
 					const u8 *src, bool xor);
+EXPORT_SYMBOL_GPL(__camellia_enc_blk_2way);
 asmlinkage void camellia_dec_blk_2way(struct camellia_ctx *ctx, u8 *dst,
 				      const u8 *src);
-
-static inline void camellia_enc_blk(struct camellia_ctx *ctx, u8 *dst,
-				    const u8 *src)
-{
-	__camellia_enc_blk(ctx, dst, src, false);
-}
-
-static inline void camellia_enc_blk_xor(struct camellia_ctx *ctx, u8 *dst,
-					const u8 *src)
-{
-	__camellia_enc_blk(ctx, dst, src, true);
-}
-
-static inline void camellia_enc_blk_2way(struct camellia_ctx *ctx, u8 *dst,
-					 const u8 *src)
-{
-	__camellia_enc_blk_2way(ctx, dst, src, false);
-}
-
-static inline void camellia_enc_blk_xor_2way(struct camellia_ctx *ctx, u8 *dst,
-					     const u8 *src)
-{
-	__camellia_enc_blk_2way(ctx, dst, src, true);
-}
+EXPORT_SYMBOL_GPL(camellia_dec_blk_2way);
 
 static void camellia_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
@@ -1275,9 +1246,8 @@ static void camellia_setup192(const unsigned char *key, u64 *subkey)
 	camellia_setup256(kk, subkey);
 }
 
-static int __camellia_setkey(struct camellia_ctx *cctx,
-			     const unsigned char *key,
-			     unsigned int key_len, u32 *flags)
+int __camellia_setkey(struct camellia_ctx *cctx, const unsigned char *key,
+		      unsigned int key_len, u32 *flags)
 {
 	if (key_len != 16 && key_len != 24 && key_len != 32) {
 		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
@@ -1300,6 +1270,7 @@ static int __camellia_setkey(struct camellia_ctx *cctx,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(__camellia_setkey);
 
 static int camellia_setkey(struct crypto_tfm *tfm, const u8 *in_key,
 			   unsigned int key_len)
@@ -1308,7 +1279,7 @@ static int camellia_setkey(struct crypto_tfm *tfm, const u8 *in_key,
 				 &tfm->crt_flags);
 }
 
-static void camellia_decrypt_cbc_2way(void *ctx, u128 *dst, const u128 *src)
+void camellia_decrypt_cbc_2way(void *ctx, u128 *dst, const u128 *src)
 {
 	u128 iv = *src;
 
@@ -1316,22 +1287,23 @@ static void camellia_decrypt_cbc_2way(void *ctx, u128 *dst, const u128 *src)
 
 	u128_xor(&dst[1], &dst[1], &iv);
 }
+EXPORT_SYMBOL_GPL(camellia_decrypt_cbc_2way);
 
-static void camellia_crypt_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
+void camellia_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
 	be128 ctrblk;
 
 	if (dst != src)
 		*dst = *src;
 
-	u128_to_be128(&ctrblk, iv);
-	u128_inc(iv);
+	le128_to_be128(&ctrblk, iv);
+	le128_inc(iv);
 
 	camellia_enc_blk_xor(ctx, (u8 *)dst, (u8 *)&ctrblk);
 }
+EXPORT_SYMBOL_GPL(camellia_crypt_ctr);
 
-static void camellia_crypt_ctr_2way(void *ctx, u128 *dst, const u128 *src,
-				    u128 *iv)
+void camellia_crypt_ctr_2way(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
 	be128 ctrblks[2];
 
@@ -1340,13 +1312,14 @@ static void camellia_crypt_ctr_2way(void *ctx, u128 *dst, const u128 *src,
 		dst[1] = src[1];
 	}
 
-	u128_to_be128(&ctrblks[0], iv);
-	u128_inc(iv);
-	u128_to_be128(&ctrblks[1], iv);
-	u128_inc(iv);
+	le128_to_be128(&ctrblks[0], iv);
+	le128_inc(iv);
+	le128_to_be128(&ctrblks[1], iv);
+	le128_inc(iv);
 
 	camellia_enc_blk_xor_2way(ctx, (u8 *)dst, (u8 *)ctrblks);
 }
+EXPORT_SYMBOL_GPL(camellia_crypt_ctr_2way);
 
 static const struct common_glue_ctx camellia_enc = {
 	.num_funcs = 2,
@@ -1464,13 +1437,8 @@ static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
 		camellia_dec_blk(ctx, srcdst, srcdst);
 }
 
-struct camellia_lrw_ctx {
-	struct lrw_table_ctx lrw_table;
-	struct camellia_ctx camellia_ctx;
-};
-
-static int lrw_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
-			      unsigned int keylen)
+int lrw_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
+			unsigned int keylen)
 {
 	struct camellia_lrw_ctx *ctx = crypto_tfm_ctx(tfm);
 	int err;
@@ -1484,6 +1452,7 @@ static int lrw_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
 	return lrw_init_table(&ctx->lrw_table,
 			      key + keylen - CAMELLIA_BLOCK_SIZE);
 }
+EXPORT_SYMBOL_GPL(lrw_camellia_setkey);
 
 static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
 		       struct scatterlist *src, unsigned int nbytes)
@@ -1519,20 +1488,16 @@ static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
 	return lrw_crypt(desc, dst, src, nbytes, &req);
 }
 
-static void lrw_exit_tfm(struct crypto_tfm *tfm)
+void lrw_camellia_exit_tfm(struct crypto_tfm *tfm)
 {
 	struct camellia_lrw_ctx *ctx = crypto_tfm_ctx(tfm);
 
 	lrw_free_table(&ctx->lrw_table);
 }
+EXPORT_SYMBOL_GPL(lrw_camellia_exit_tfm);
 
-struct camellia_xts_ctx {
-	struct camellia_ctx tweak_ctx;
-	struct camellia_ctx crypt_ctx;
-};
-
-static int xts_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
-			      unsigned int keylen)
+int xts_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
+			unsigned int keylen)
 {
 	struct camellia_xts_ctx *ctx = crypto_tfm_ctx(tfm);
 	u32 *flags = &tfm->crt_flags;
@@ -1555,6 +1520,7 @@ static int xts_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
 	return __camellia_setkey(&ctx->tweak_ctx, key + keylen / 2, keylen / 2,
 				flags);
 }
+EXPORT_SYMBOL_GPL(xts_camellia_setkey);
 
 static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
 		       struct scatterlist *src, unsigned int nbytes)
@@ -1679,7 +1645,7 @@ static struct crypto_alg camellia_algs[6] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_exit		= lrw_exit_tfm,
+	.cra_exit		= lrw_camellia_exit_tfm,
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= CAMELLIA_MIN_KEY_SIZE +
diff --git a/arch/x86/crypto/cast5-avx-x86_64-asm_64.S b/arch/x86/crypto/cast5-avx-x86_64-asm_64.S
index a41a3aa..12478e4 100644
--- a/arch/x86/crypto/cast5-avx-x86_64-asm_64.S
+++ b/arch/x86/crypto/cast5-avx-x86_64-asm_64.S
@@ -180,31 +180,17 @@
 	vpunpcklqdq		t1, t0, x0; \
 	vpunpckhqdq		t1, t0, x1;
 
-#define inpack_blocks(in, x0, x1, t0, t1, rmask) \
-	vmovdqu (0*4*4)(in),	x0; \
-	vmovdqu (1*4*4)(in),	x1; \
+#define inpack_blocks(x0, x1, t0, t1, rmask) \
 	vpshufb rmask, 	x0,	x0; \
 	vpshufb rmask, 	x1,	x1; \
 	\
 	transpose_2x4(x0, x1, t0, t1)
 
-#define outunpack_blocks(out, x0, x1, t0, t1, rmask) \
+#define outunpack_blocks(x0, x1, t0, t1, rmask) \
 	transpose_2x4(x0, x1, t0, t1) \
 	\
 	vpshufb rmask,	x0, x0;           \
-	vpshufb rmask,	x1, x1;           \
-	vmovdqu 	x0, (0*4*4)(out); \
-	vmovdqu		x1, (1*4*4)(out);
-
-#define outunpack_xor_blocks(out, x0, x1, t0, t1, rmask) \
-	transpose_2x4(x0, x1, t0, t1) \
-	\
-	vpshufb rmask,	x0, x0;               \
-	vpshufb rmask,	x1, x1;               \
-	vpxor		(0*4*4)(out), x0, x0; \
-	vmovdqu 	x0, (0*4*4)(out);     \
-	vpxor		(1*4*4)(out), x1, x1; \
-	vmovdqu	        x1, (1*4*4)(out);
+	vpshufb rmask,	x1, x1;
 
 .data
 
@@ -213,6 +199,8 @@
 	.byte 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
 .Lbswap128_mask:
 	.byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+.Lbswap_iv_mask:
+	.byte 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0
 .L16_mask:
 	.byte 16, 16, 16, 16
 .L32_mask:
@@ -223,35 +211,42 @@
 .text
 
 .align 16
-.global __cast5_enc_blk_16way
-.type   __cast5_enc_blk_16way,@function;
+.type   __cast5_enc_blk16,@function;
 
-__cast5_enc_blk_16way:
+__cast5_enc_blk16:
 	/* input:
 	 *	%rdi: ctx, CTX
-	 *	%rsi: dst
-	 *	%rdx: src
-	 *	%rcx: bool, if true: xor output
+	 *	RL1: blocks 1 and 2
+	 *	RR1: blocks 3 and 4
+	 *	RL2: blocks 5 and 6
+	 *	RR2: blocks 7 and 8
+	 *	RL3: blocks 9 and 10
+	 *	RR3: blocks 11 and 12
+	 *	RL4: blocks 13 and 14
+	 *	RR4: blocks 15 and 16
+	 * output:
+	 *	RL1: encrypted blocks 1 and 2
+	 *	RR1: encrypted blocks 3 and 4
+	 *	RL2: encrypted blocks 5 and 6
+	 *	RR2: encrypted blocks 7 and 8
+	 *	RL3: encrypted blocks 9 and 10
+	 *	RR3: encrypted blocks 11 and 12
+	 *	RL4: encrypted blocks 13 and 14
+	 *	RR4: encrypted blocks 15 and 16
 	 */
 
 	pushq %rbp;
 	pushq %rbx;
-	pushq %rcx;
 
 	vmovdqa .Lbswap_mask, RKM;
 	vmovd .Lfirst_mask, R1ST;
 	vmovd .L32_mask, R32;
 	enc_preload_rkr();
 
-	leaq 1*(2*4*4)(%rdx), %rax;
-	inpack_blocks(%rdx, RL1, RR1, RTMP, RX, RKM);
-	inpack_blocks(%rax, RL2, RR2, RTMP, RX, RKM);
-	leaq 2*(2*4*4)(%rdx), %rax;
-	inpack_blocks(%rax, RL3, RR3, RTMP, RX, RKM);
-	leaq 3*(2*4*4)(%rdx), %rax;
-	inpack_blocks(%rax, RL4, RR4, RTMP, RX, RKM);
-
-	movq %rsi, %r11;
+	inpack_blocks(RL1, RR1, RTMP, RX, RKM);
+	inpack_blocks(RL2, RR2, RTMP, RX, RKM);
+	inpack_blocks(RL3, RR3, RTMP, RX, RKM);
+	inpack_blocks(RL4, RR4, RTMP, RX, RKM);
 
 	round(RL, RR, 0, 1);
 	round(RR, RL, 1, 2);
@@ -276,44 +271,41 @@ __cast5_enc_blk_16way:
 	round(RR, RL, 15, 1);
 
 __skip_enc:
-	popq %rcx;
 	popq %rbx;
 	popq %rbp;
 
 	vmovdqa .Lbswap_mask, RKM;
-	leaq 1*(2*4*4)(%r11), %rax;
 
-	testb %cl, %cl;
-	jnz __enc_xor16;
-
-	outunpack_blocks(%r11, RR1, RL1, RTMP, RX, RKM);
-	outunpack_blocks(%rax, RR2, RL2, RTMP, RX, RKM);
-	leaq 2*(2*4*4)(%r11), %rax;
-	outunpack_blocks(%rax, RR3, RL3, RTMP, RX, RKM);
-	leaq 3*(2*4*4)(%r11), %rax;
-	outunpack_blocks(%rax, RR4, RL4, RTMP, RX, RKM);
-
-	ret;
-
-__enc_xor16:
-	outunpack_xor_blocks(%r11, RR1, RL1, RTMP, RX, RKM);
-	outunpack_xor_blocks(%rax, RR2, RL2, RTMP, RX, RKM);
-	leaq 2*(2*4*4)(%r11), %rax;
-	outunpack_xor_blocks(%rax, RR3, RL3, RTMP, RX, RKM);
-	leaq 3*(2*4*4)(%r11), %rax;
-	outunpack_xor_blocks(%rax, RR4, RL4, RTMP, RX, RKM);
+	outunpack_blocks(RR1, RL1, RTMP, RX, RKM);
+	outunpack_blocks(RR2, RL2, RTMP, RX, RKM);
+	outunpack_blocks(RR3, RL3, RTMP, RX, RKM);
+	outunpack_blocks(RR4, RL4, RTMP, RX, RKM);
 
 	ret;
 
 .align 16
-.global cast5_dec_blk_16way
-.type   cast5_dec_blk_16way,@function;
+.type   __cast5_dec_blk16,@function;
 
-cast5_dec_blk_16way:
+__cast5_dec_blk16:
 	/* input:
 	 *	%rdi: ctx, CTX
-	 *	%rsi: dst
-	 *	%rdx: src
+	 *	RL1: encrypted blocks 1 and 2
+	 *	RR1: encrypted blocks 3 and 4
+	 *	RL2: encrypted blocks 5 and 6
+	 *	RR2: encrypted blocks 7 and 8
+	 *	RL3: encrypted blocks 9 and 10
+	 *	RR3: encrypted blocks 11 and 12
+	 *	RL4: encrypted blocks 13 and 14
+	 *	RR4: encrypted blocks 15 and 16
+	 * output:
+	 *	RL1: decrypted blocks 1 and 2
+	 *	RR1: decrypted blocks 3 and 4
+	 *	RL2: decrypted blocks 5 and 6
+	 *	RR2: decrypted blocks 7 and 8
+	 *	RL3: decrypted blocks 9 and 10
+	 *	RR3: decrypted blocks 11 and 12
+	 *	RL4: decrypted blocks 13 and 14
+	 *	RR4: decrypted blocks 15 and 16
 	 */
 
 	pushq %rbp;
@@ -324,15 +316,10 @@ cast5_dec_blk_16way:
 	vmovd .L32_mask, R32;
 	dec_preload_rkr();
 
-	leaq 1*(2*4*4)(%rdx), %rax;
-	inpack_blocks(%rdx, RL1, RR1, RTMP, RX, RKM);
-	inpack_blocks(%rax, RL2, RR2, RTMP, RX, RKM);
-	leaq 2*(2*4*4)(%rdx), %rax;
-	inpack_blocks(%rax, RL3, RR3, RTMP, RX, RKM);
-	leaq 3*(2*4*4)(%rdx), %rax;
-	inpack_blocks(%rax, RL4, RR4, RTMP, RX, RKM);
-
-	movq %rsi, %r11;
+	inpack_blocks(RL1, RR1, RTMP, RX, RKM);
+	inpack_blocks(RL2, RR2, RTMP, RX, RKM);
+	inpack_blocks(RL3, RR3, RTMP, RX, RKM);
+	inpack_blocks(RL4, RR4, RTMP, RX, RKM);
 
 	movzbl rr(CTX), %eax;
 	testl %eax, %eax;
@@ -361,16 +348,211 @@ __dec_tail:
 	popq %rbx;
 	popq %rbp;
 
-	leaq 1*(2*4*4)(%r11), %rax;
-	outunpack_blocks(%r11, RR1, RL1, RTMP, RX, RKM);
-	outunpack_blocks(%rax, RR2, RL2, RTMP, RX, RKM);
-	leaq 2*(2*4*4)(%r11), %rax;
-	outunpack_blocks(%rax, RR3, RL3, RTMP, RX, RKM);
-	leaq 3*(2*4*4)(%r11), %rax;
-	outunpack_blocks(%rax, RR4, RL4, RTMP, RX, RKM);
+	outunpack_blocks(RR1, RL1, RTMP, RX, RKM);
+	outunpack_blocks(RR2, RL2, RTMP, RX, RKM);
+	outunpack_blocks(RR3, RL3, RTMP, RX, RKM);
+	outunpack_blocks(RR4, RL4, RTMP, RX, RKM);
 
 	ret;
 
 __skip_dec:
 	vpsrldq $4, RKR, RKR;
 	jmp __dec_tail;
+
+.align 16
+.global cast5_ecb_enc_16way
+.type   cast5_ecb_enc_16way,@function;
+
+cast5_ecb_enc_16way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+
+	movq %rsi, %r11;
+
+	vmovdqu (0*4*4)(%rdx), RL1;
+	vmovdqu (1*4*4)(%rdx), RR1;
+	vmovdqu (2*4*4)(%rdx), RL2;
+	vmovdqu (3*4*4)(%rdx), RR2;
+	vmovdqu (4*4*4)(%rdx), RL3;
+	vmovdqu (5*4*4)(%rdx), RR3;
+	vmovdqu (6*4*4)(%rdx), RL4;
+	vmovdqu (7*4*4)(%rdx), RR4;
+
+	call __cast5_enc_blk16;
+
+	vmovdqu RR1, (0*4*4)(%r11);
+	vmovdqu RL1, (1*4*4)(%r11);
+	vmovdqu RR2, (2*4*4)(%r11);
+	vmovdqu RL2, (3*4*4)(%r11);
+	vmovdqu RR3, (4*4*4)(%r11);
+	vmovdqu RL3, (5*4*4)(%r11);
+	vmovdqu RR4, (6*4*4)(%r11);
+	vmovdqu RL4, (7*4*4)(%r11);
+
+	ret;
+
+.align 16
+.global cast5_ecb_dec_16way
+.type   cast5_ecb_dec_16way,@function;
+
+cast5_ecb_dec_16way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+
+	movq %rsi, %r11;
+
+	vmovdqu (0*4*4)(%rdx), RL1;
+	vmovdqu (1*4*4)(%rdx), RR1;
+	vmovdqu (2*4*4)(%rdx), RL2;
+	vmovdqu (3*4*4)(%rdx), RR2;
+	vmovdqu (4*4*4)(%rdx), RL3;
+	vmovdqu (5*4*4)(%rdx), RR3;
+	vmovdqu (6*4*4)(%rdx), RL4;
+	vmovdqu (7*4*4)(%rdx), RR4;
+
+	call __cast5_dec_blk16;
+
+	vmovdqu RR1, (0*4*4)(%r11);
+	vmovdqu RL1, (1*4*4)(%r11);
+	vmovdqu RR2, (2*4*4)(%r11);
+	vmovdqu RL2, (3*4*4)(%r11);
+	vmovdqu RR3, (4*4*4)(%r11);
+	vmovdqu RL3, (5*4*4)(%r11);
+	vmovdqu RR4, (6*4*4)(%r11);
+	vmovdqu RL4, (7*4*4)(%r11);
+
+	ret;
+
+.align 16
+.global cast5_cbc_dec_16way
+.type   cast5_cbc_dec_16way,@function;
+
+cast5_cbc_dec_16way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+
+	pushq %r12;
+
+	movq %rsi, %r11;
+	movq %rdx, %r12;
+
+	vmovdqu (0*16)(%rdx), RL1;
+	vmovdqu (1*16)(%rdx), RR1;
+	vmovdqu (2*16)(%rdx), RL2;
+	vmovdqu (3*16)(%rdx), RR2;
+	vmovdqu (4*16)(%rdx), RL3;
+	vmovdqu (5*16)(%rdx), RR3;
+	vmovdqu (6*16)(%rdx), RL4;
+	vmovdqu (7*16)(%rdx), RR4;
+
+	call __cast5_dec_blk16;
+
+	/* xor with src */
+	vmovq (%r12), RX;
+	vpshufd $0x4f, RX, RX;
+	vpxor RX, RR1, RR1;
+	vpxor 0*16+8(%r12), RL1, RL1;
+	vpxor 1*16+8(%r12), RR2, RR2;
+	vpxor 2*16+8(%r12), RL2, RL2;
+	vpxor 3*16+8(%r12), RR3, RR3;
+	vpxor 4*16+8(%r12), RL3, RL3;
+	vpxor 5*16+8(%r12), RR4, RR4;
+	vpxor 6*16+8(%r12), RL4, RL4;
+
+	vmovdqu RR1, (0*16)(%r11);
+	vmovdqu RL1, (1*16)(%r11);
+	vmovdqu RR2, (2*16)(%r11);
+	vmovdqu RL2, (3*16)(%r11);
+	vmovdqu RR3, (4*16)(%r11);
+	vmovdqu RL3, (5*16)(%r11);
+	vmovdqu RR4, (6*16)(%r11);
+	vmovdqu RL4, (7*16)(%r11);
+
+	popq %r12;
+
+	ret;
+
+.align 16
+.global cast5_ctr_16way
+.type   cast5_ctr_16way,@function;
+
+cast5_ctr_16way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 *	%rcx: iv (big endian, 64bit)
+	 */
+
+	pushq %r12;
+
+	movq %rsi, %r11;
+	movq %rdx, %r12;
+
+	vpcmpeqd RTMP, RTMP, RTMP;
+	vpsrldq $8, RTMP, RTMP; /* low: -1, high: 0 */
+
+	vpcmpeqd RKR, RKR, RKR;
+	vpaddq RKR, RKR, RKR; /* low: -2, high: -2 */
+	vmovdqa .Lbswap_iv_mask, R1ST;
+	vmovdqa .Lbswap128_mask, RKM;
+
+	/* load IV and byteswap */
+	vmovq (%rcx), RX;
+	vpshufb R1ST, RX, RX;
+
+	/* construct IVs */
+	vpsubq RTMP, RX, RX;  /* le: IV1, IV0 */
+	vpshufb RKM, RX, RL1; /* be: IV0, IV1 */
+	vpsubq RKR, RX, RX;
+	vpshufb RKM, RX, RR1; /* be: IV2, IV3 */
+	vpsubq RKR, RX, RX;
+	vpshufb RKM, RX, RL2; /* be: IV4, IV5 */
+	vpsubq RKR, RX, RX;
+	vpshufb RKM, RX, RR2; /* be: IV6, IV7 */
+	vpsubq RKR, RX, RX;
+	vpshufb RKM, RX, RL3; /* be: IV8, IV9 */
+	vpsubq RKR, RX, RX;
+	vpshufb RKM, RX, RR3; /* be: IV10, IV11 */
+	vpsubq RKR, RX, RX;
+	vpshufb RKM, RX, RL4; /* be: IV12, IV13 */
+	vpsubq RKR, RX, RX;
+	vpshufb RKM, RX, RR4; /* be: IV14, IV15 */
+
+	/* store last IV */
+	vpsubq RTMP, RX, RX; /* le: IV16, IV14 */
+	vpshufb R1ST, RX, RX; /* be: IV16, IV16 */
+	vmovq RX, (%rcx);
+
+	call __cast5_enc_blk16;
+
+	/* dst = src ^ iv */
+	vpxor (0*16)(%r12), RR1, RR1;
+	vpxor (1*16)(%r12), RL1, RL1;
+	vpxor (2*16)(%r12), RR2, RR2;
+	vpxor (3*16)(%r12), RL2, RL2;
+	vpxor (4*16)(%r12), RR3, RR3;
+	vpxor (5*16)(%r12), RL3, RL3;
+	vpxor (6*16)(%r12), RR4, RR4;
+	vpxor (7*16)(%r12), RL4, RL4;
+	vmovdqu RR1, (0*16)(%r11);
+	vmovdqu RL1, (1*16)(%r11);
+	vmovdqu RR2, (2*16)(%r11);
+	vmovdqu RL2, (3*16)(%r11);
+	vmovdqu RR3, (4*16)(%r11);
+	vmovdqu RL3, (5*16)(%r11);
+	vmovdqu RR4, (6*16)(%r11);
+	vmovdqu RL4, (7*16)(%r11);
+
+	popq %r12;
+
+	ret;
diff --git a/arch/x86/crypto/cast5_avx_glue.c b/arch/x86/crypto/cast5_avx_glue.c
index e0ea14f..c663181 100644
--- a/arch/x86/crypto/cast5_avx_glue.c
+++ b/arch/x86/crypto/cast5_avx_glue.c
@@ -37,29 +37,14 @@
 
 #define CAST5_PARALLEL_BLOCKS 16
 
-asmlinkage void __cast5_enc_blk_16way(struct cast5_ctx *ctx, u8 *dst,
-				      const u8 *src, bool xor);
-asmlinkage void cast5_dec_blk_16way(struct cast5_ctx *ctx, u8 *dst,
+asmlinkage void cast5_ecb_enc_16way(struct cast5_ctx *ctx, u8 *dst,
 				    const u8 *src);
-
-static inline void cast5_enc_blk_xway(struct cast5_ctx *ctx, u8 *dst,
-				      const u8 *src)
-{
-	__cast5_enc_blk_16way(ctx, dst, src, false);
-}
-
-static inline void cast5_enc_blk_xway_xor(struct cast5_ctx *ctx, u8 *dst,
-					  const u8 *src)
-{
-	__cast5_enc_blk_16way(ctx, dst, src, true);
-}
-
-static inline void cast5_dec_blk_xway(struct cast5_ctx *ctx, u8 *dst,
-				      const u8 *src)
-{
-	cast5_dec_blk_16way(ctx, dst, src);
-}
-
+asmlinkage void cast5_ecb_dec_16way(struct cast5_ctx *ctx, u8 *dst,
+				    const u8 *src);
+asmlinkage void cast5_cbc_dec_16way(struct cast5_ctx *ctx, u8 *dst,
+				    const u8 *src);
+asmlinkage void cast5_ctr_16way(struct cast5_ctx *ctx, u8 *dst, const u8 *src,
+				__be64 *iv);
 
 static inline bool cast5_fpu_begin(bool fpu_enabled, unsigned int nbytes)
 {
@@ -79,8 +64,11 @@ static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
 	struct cast5_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
 	const unsigned int bsize = CAST5_BLOCK_SIZE;
 	unsigned int nbytes;
+	void (*fn)(struct cast5_ctx *ctx, u8 *dst, const u8 *src);
 	int err;
 
+	fn = (enc) ? cast5_ecb_enc_16way : cast5_ecb_dec_16way;
+
 	err = blkcipher_walk_virt(desc, walk);
 	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
 
@@ -93,10 +81,7 @@ static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
 		/* Process multi-block batch */
 		if (nbytes >= bsize * CAST5_PARALLEL_BLOCKS) {
 			do {
-				if (enc)
-					cast5_enc_blk_xway(ctx, wdst, wsrc);
-				else
-					cast5_dec_blk_xway(ctx, wdst, wsrc);
+				fn(ctx, wdst, wsrc);
 
 				wsrc += bsize * CAST5_PARALLEL_BLOCKS;
 				wdst += bsize * CAST5_PARALLEL_BLOCKS;
@@ -107,12 +92,11 @@ static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
 				goto done;
 		}
 
+		fn = (enc) ? __cast5_encrypt : __cast5_decrypt;
+
 		/* Handle leftovers */
 		do {
-			if (enc)
-				__cast5_encrypt(ctx, wdst, wsrc);
-			else
-				__cast5_decrypt(ctx, wdst, wsrc);
+			fn(ctx, wdst, wsrc);
 
 			wsrc += bsize;
 			wdst += bsize;
@@ -194,9 +178,7 @@ static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
 	unsigned int nbytes = walk->nbytes;
 	u64 *src = (u64 *)walk->src.virt.addr;
 	u64 *dst = (u64 *)walk->dst.virt.addr;
-	u64 ivs[CAST5_PARALLEL_BLOCKS - 1];
 	u64 last_iv;
-	int i;
 
 	/* Start of the last block. */
 	src += nbytes / bsize - 1;
@@ -211,13 +193,7 @@ static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
 			src -= CAST5_PARALLEL_BLOCKS - 1;
 			dst -= CAST5_PARALLEL_BLOCKS - 1;
 
-			for (i = 0; i < CAST5_PARALLEL_BLOCKS - 1; i++)
-				ivs[i] = src[i];
-
-			cast5_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src);
-
-			for (i = 0; i < CAST5_PARALLEL_BLOCKS - 1; i++)
-				*(dst + (i + 1)) ^= *(ivs + i);
+			cast5_cbc_dec_16way(ctx, (u8 *)dst, (u8 *)src);
 
 			nbytes -= bsize;
 			if (nbytes < bsize)
@@ -298,23 +274,12 @@ static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
 	unsigned int nbytes = walk->nbytes;
 	u64 *src = (u64 *)walk->src.virt.addr;
 	u64 *dst = (u64 *)walk->dst.virt.addr;
-	u64 ctrblk = be64_to_cpu(*(__be64 *)walk->iv);
-	__be64 ctrblocks[CAST5_PARALLEL_BLOCKS];
-	int i;
 
 	/* Process multi-block batch */
 	if (nbytes >= bsize * CAST5_PARALLEL_BLOCKS) {
 		do {
-			/* create ctrblks for parallel encrypt */
-			for (i = 0; i < CAST5_PARALLEL_BLOCKS; i++) {
-				if (dst != src)
-					dst[i] = src[i];
-
-				ctrblocks[i] = cpu_to_be64(ctrblk++);
-			}
-
-			cast5_enc_blk_xway_xor(ctx, (u8 *)dst,
-					       (u8 *)ctrblocks);
+			cast5_ctr_16way(ctx, (u8 *)dst, (u8 *)src,
+					(__be64 *)walk->iv);
 
 			src += CAST5_PARALLEL_BLOCKS;
 			dst += CAST5_PARALLEL_BLOCKS;
@@ -327,13 +292,16 @@ static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
 
 	/* Handle leftovers */
 	do {
+		u64 ctrblk;
+
 		if (dst != src)
 			*dst = *src;
 
-		ctrblocks[0] = cpu_to_be64(ctrblk++);
+		ctrblk = *(u64 *)walk->iv;
+		be64_add_cpu((__be64 *)walk->iv, 1);
 
-		__cast5_encrypt(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks);
-		*dst ^= ctrblocks[0];
+		__cast5_encrypt(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
+		*dst ^= ctrblk;
 
 		src += 1;
 		dst += 1;
@@ -341,7 +309,6 @@ static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
 	} while (nbytes >= bsize);
 
 done:
-	*(__be64 *)walk->iv = cpu_to_be64(ctrblk);
 	return nbytes;
 }
 
diff --git a/arch/x86/crypto/cast6-avx-x86_64-asm_64.S b/arch/x86/crypto/cast6-avx-x86_64-asm_64.S
index 218d283..83a5381 100644
--- a/arch/x86/crypto/cast6-avx-x86_64-asm_64.S
+++ b/arch/x86/crypto/cast6-avx-x86_64-asm_64.S
@@ -23,6 +23,8 @@
  *
  */
 
+#include "glue_helper-asm-avx.S"
+
 .file "cast6-avx-x86_64-asm_64.S"
 
 .extern cast6_s1
@@ -205,11 +207,7 @@
 	vpunpcklqdq		x3, t2, x2; \
 	vpunpckhqdq		x3, t2, x3;
 
-#define inpack_blocks(in, x0, x1, x2, x3, t0, t1, t2, rmask) \
-	vmovdqu (0*4*4)(in),	x0; \
-	vmovdqu (1*4*4)(in),	x1; \
-	vmovdqu (2*4*4)(in),	x2; \
-	vmovdqu (3*4*4)(in),	x3; \
+#define inpack_blocks(x0, x1, x2, x3, t0, t1, t2, rmask) \
 	vpshufb rmask, x0,	x0; \
 	vpshufb rmask, x1,	x1; \
 	vpshufb rmask, x2,	x2; \
@@ -217,39 +215,21 @@
 	\
 	transpose_4x4(x0, x1, x2, x3, t0, t1, t2)
 
-#define outunpack_blocks(out, x0, x1, x2, x3, t0, t1, t2, rmask) \
+#define outunpack_blocks(x0, x1, x2, x3, t0, t1, t2, rmask) \
 	transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
 	\
 	vpshufb rmask,		x0, x0;       \
 	vpshufb rmask,		x1, x1;       \
 	vpshufb rmask,		x2, x2;       \
-	vpshufb rmask,		x3, x3;       \
-	vmovdqu x0,		(0*4*4)(out); \
-	vmovdqu	x1,		(1*4*4)(out); \
-	vmovdqu	x2,		(2*4*4)(out); \
-	vmovdqu	x3,		(3*4*4)(out);
-
-#define outunpack_xor_blocks(out, x0, x1, x2, x3, t0, t1, t2, rmask) \
-	transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
-	\
-	vpshufb rmask,		x0, x0;       \
-	vpshufb rmask,		x1, x1;       \
-	vpshufb rmask,		x2, x2;       \
-	vpshufb rmask,		x3, x3;       \
-	vpxor (0*4*4)(out),	x0, x0;       \
-	vmovdqu	x0,		(0*4*4)(out); \
-	vpxor (1*4*4)(out),	x1, x1;       \
-	vmovdqu	x1,		(1*4*4)(out); \
-	vpxor (2*4*4)(out),	x2, x2;       \
-	vmovdqu x2,		(2*4*4)(out); \
-	vpxor (3*4*4)(out),	x3, x3;       \
-	vmovdqu x3,		(3*4*4)(out);
+	vpshufb rmask,		x3, x3;
 
 .data
 
 .align 16
 .Lbswap_mask:
 	.byte 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
+.Lbswap128_mask:
+	.byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
 .Lrkr_enc_Q_Q_QBAR_QBAR:
 	.byte 0, 1, 2, 3, 4, 5, 6, 7, 11, 10, 9, 8, 15, 14, 13, 12
 .Lrkr_enc_QBAR_QBAR_QBAR_QBAR:
@@ -269,31 +249,26 @@
 
 .text
 
-.align 16
-.global __cast6_enc_blk_8way
-.type   __cast6_enc_blk_8way,@function;
+.align 8
+.type   __cast6_enc_blk8,@function;
 
-__cast6_enc_blk_8way:
+__cast6_enc_blk8:
 	/* input:
 	 *	%rdi: ctx, CTX
-	 *	%rsi: dst
-	 *	%rdx: src
-	 *	%rcx: bool, if true: xor output
+	 *	RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: blocks
+	 * output:
+	 *	RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: encrypted blocks
 	 */
 
 	pushq %rbp;
 	pushq %rbx;
-	pushq %rcx;
 
 	vmovdqa .Lbswap_mask, RKM;
 	vmovd .Lfirst_mask, R1ST;
 	vmovd .L32_mask, R32;
 
-	leaq (4*4*4)(%rdx), %rax;
-	inpack_blocks(%rdx, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
-	inpack_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
-
-	movq %rsi, %r11;
+	inpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+	inpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
 
 	preload_rkr(0, dummy, none);
 	Q(0);
@@ -311,36 +286,25 @@ __cast6_enc_blk_8way:
 	QBAR(10);
 	QBAR(11);
 
-	popq %rcx;
 	popq %rbx;
 	popq %rbp;
 
 	vmovdqa .Lbswap_mask, RKM;
-	leaq (4*4*4)(%r11), %rax;
-
-	testb %cl, %cl;
-	jnz __enc_xor8;
-
-	outunpack_blocks(%r11, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
-	outunpack_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
-
-	ret;
 
-__enc_xor8:
-	outunpack_xor_blocks(%r11, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
-	outunpack_xor_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
+	outunpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+	outunpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
 
 	ret;
 
-.align 16
-.global cast6_dec_blk_8way
-.type   cast6_dec_blk_8way,@function;
+.align 8
+.type   __cast6_dec_blk8,@function;
 
-cast6_dec_blk_8way:
+__cast6_dec_blk8:
 	/* input:
 	 *	%rdi: ctx, CTX
-	 *	%rsi: dst
-	 *	%rdx: src
+	 *	RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: encrypted blocks
+	 * output:
+	 *	RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: decrypted blocks
 	 */
 
 	pushq %rbp;
@@ -350,11 +314,8 @@ cast6_dec_blk_8way:
 	vmovd .Lfirst_mask, R1ST;
 	vmovd .L32_mask, R32;
 
-	leaq (4*4*4)(%rdx), %rax;
-	inpack_blocks(%rdx, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
-	inpack_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
-
-	movq %rsi, %r11;
+	inpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+	inpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
 
 	preload_rkr(2, shuffle, .Lrkr_dec_Q_Q_Q_Q);
 	Q(11);
@@ -376,8 +337,103 @@ cast6_dec_blk_8way:
 	popq %rbp;
 
 	vmovdqa .Lbswap_mask, RKM;
-	leaq (4*4*4)(%r11), %rax;
-	outunpack_blocks(%r11, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
-	outunpack_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
+	outunpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+	outunpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
+
+	ret;
+
+.align 8
+.global cast6_ecb_enc_8way
+.type   cast6_ecb_enc_8way,@function;
+
+cast6_ecb_enc_8way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+
+	movq %rsi, %r11;
+
+	load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+	call __cast6_enc_blk8;
+
+	store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+	ret;
+
+.align 8
+.global cast6_ecb_dec_8way
+.type   cast6_ecb_dec_8way,@function;
+
+cast6_ecb_dec_8way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+
+	movq %rsi, %r11;
+
+	load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+	call __cast6_dec_blk8;
+
+	store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+	ret;
+
+.align 8
+.global cast6_cbc_dec_8way
+.type   cast6_cbc_dec_8way,@function;
+
+cast6_cbc_dec_8way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+
+	pushq %r12;
+
+	movq %rsi, %r11;
+	movq %rdx, %r12;
+
+	load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+	call __cast6_dec_blk8;
+
+	store_cbc_8way(%r12, %r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+	popq %r12;
+
+	ret;
+
+.align 8
+.global cast6_ctr_8way
+.type   cast6_ctr_8way,@function;
+
+cast6_ctr_8way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 *	%rcx: iv (little endian, 128bit)
+	 */
+
+	pushq %r12;
+
+	movq %rsi, %r11;
+	movq %rdx, %r12;
+
+	load_ctr_8way(%rcx, .Lbswap128_mask, RA1, RB1, RC1, RD1, RA2, RB2, RC2,
+		      RD2, RX, RKR, RKM);
+
+	call __cast6_enc_blk8;
+
+	store_ctr_8way(%r12, %r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+	popq %r12;
 
 	ret;
diff --git a/arch/x86/crypto/cast6_avx_glue.c b/arch/x86/crypto/cast6_avx_glue.c
index 15e5f85..92f7ca2 100644
--- a/arch/x86/crypto/cast6_avx_glue.c
+++ b/arch/x86/crypto/cast6_avx_glue.c
@@ -40,79 +40,34 @@
 
 #define CAST6_PARALLEL_BLOCKS 8
 
-asmlinkage void __cast6_enc_blk_8way(struct cast6_ctx *ctx, u8 *dst,
-				     const u8 *src, bool xor);
-asmlinkage void cast6_dec_blk_8way(struct cast6_ctx *ctx, u8 *dst,
+asmlinkage void cast6_ecb_enc_8way(struct cast6_ctx *ctx, u8 *dst,
+				   const u8 *src);
+asmlinkage void cast6_ecb_dec_8way(struct cast6_ctx *ctx, u8 *dst,
 				   const u8 *src);
 
-static inline void cast6_enc_blk_xway(struct cast6_ctx *ctx, u8 *dst,
-				      const u8 *src)
-{
-	__cast6_enc_blk_8way(ctx, dst, src, false);
-}
-
-static inline void cast6_enc_blk_xway_xor(struct cast6_ctx *ctx, u8 *dst,
-					  const u8 *src)
-{
-	__cast6_enc_blk_8way(ctx, dst, src, true);
-}
-
-static inline void cast6_dec_blk_xway(struct cast6_ctx *ctx, u8 *dst,
-				      const u8 *src)
-{
-	cast6_dec_blk_8way(ctx, dst, src);
-}
-
-
-static void cast6_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src)
-{
-	u128 ivs[CAST6_PARALLEL_BLOCKS - 1];
-	unsigned int j;
-
-	for (j = 0; j < CAST6_PARALLEL_BLOCKS - 1; j++)
-		ivs[j] = src[j];
-
-	cast6_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src);
-
-	for (j = 0; j < CAST6_PARALLEL_BLOCKS - 1; j++)
-		u128_xor(dst + (j + 1), dst + (j + 1), ivs + j);
-}
+asmlinkage void cast6_cbc_dec_8way(struct cast6_ctx *ctx, u8 *dst,
+				   const u8 *src);
+asmlinkage void cast6_ctr_8way(struct cast6_ctx *ctx, u8 *dst, const u8 *src,
+			       le128 *iv);
 
-static void cast6_crypt_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
+static void cast6_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
 	be128 ctrblk;
 
-	u128_to_be128(&ctrblk, iv);
-	u128_inc(iv);
+	le128_to_be128(&ctrblk, iv);
+	le128_inc(iv);
 
 	__cast6_encrypt(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
 	u128_xor(dst, src, (u128 *)&ctrblk);
 }
 
-static void cast6_crypt_ctr_xway(void *ctx, u128 *dst, const u128 *src,
-				   u128 *iv)
-{
-	be128 ctrblks[CAST6_PARALLEL_BLOCKS];
-	unsigned int i;
-
-	for (i = 0; i < CAST6_PARALLEL_BLOCKS; i++) {
-		if (dst != src)
-			dst[i] = src[i];
-
-		u128_to_be128(&ctrblks[i], iv);
-		u128_inc(iv);
-	}
-
-	cast6_enc_blk_xway_xor(ctx, (u8 *)dst, (u8 *)ctrblks);
-}
-
 static const struct common_glue_ctx cast6_enc = {
 	.num_funcs = 2,
 	.fpu_blocks_limit = CAST6_PARALLEL_BLOCKS,
 
 	.funcs = { {
 		.num_blocks = CAST6_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(cast6_enc_blk_xway) }
+		.fn_u = { .ecb = GLUE_FUNC_CAST(cast6_ecb_enc_8way) }
 	}, {
 		.num_blocks = 1,
 		.fn_u = { .ecb = GLUE_FUNC_CAST(__cast6_encrypt) }
@@ -125,7 +80,7 @@ static const struct common_glue_ctx cast6_ctr = {
 
 	.funcs = { {
 		.num_blocks = CAST6_PARALLEL_BLOCKS,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(cast6_crypt_ctr_xway) }
+		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(cast6_ctr_8way) }
 	}, {
 		.num_blocks = 1,
 		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(cast6_crypt_ctr) }
@@ -138,7 +93,7 @@ static const struct common_glue_ctx cast6_dec = {
 
 	.funcs = { {
 		.num_blocks = CAST6_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(cast6_dec_blk_xway) }
+		.fn_u = { .ecb = GLUE_FUNC_CAST(cast6_ecb_dec_8way) }
 	}, {
 		.num_blocks = 1,
 		.fn_u = { .ecb = GLUE_FUNC_CAST(__cast6_decrypt) }
@@ -151,7 +106,7 @@ static const struct common_glue_ctx cast6_dec_cbc = {
 
 	.funcs = { {
 		.num_blocks = CAST6_PARALLEL_BLOCKS,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(cast6_decrypt_cbc_xway) }
+		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(cast6_cbc_dec_8way) }
 	}, {
 		.num_blocks = 1,
 		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(__cast6_decrypt) }
@@ -215,7 +170,7 @@ static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
 	ctx->fpu_enabled = cast6_fpu_begin(ctx->fpu_enabled, nbytes);
 
 	if (nbytes == bsize * CAST6_PARALLEL_BLOCKS) {
-		cast6_enc_blk_xway(ctx->ctx, srcdst, srcdst);
+		cast6_ecb_enc_8way(ctx->ctx, srcdst, srcdst);
 		return;
 	}
 
@@ -232,7 +187,7 @@ static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
 	ctx->fpu_enabled = cast6_fpu_begin(ctx->fpu_enabled, nbytes);
 
 	if (nbytes == bsize * CAST6_PARALLEL_BLOCKS) {
-		cast6_dec_blk_xway(ctx->ctx, srcdst, srcdst);
+		cast6_ecb_dec_8way(ctx->ctx, srcdst, srcdst);
 		return;
 	}
 
diff --git a/arch/x86/crypto/crc32c-intel.c b/arch/x86/crypto/crc32c-intel.c
deleted file mode 100644
index 493f959..0000000
--- a/arch/x86/crypto/crc32c-intel.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Using hardware provided CRC32 instruction to accelerate the CRC32 disposal.
- * CRC32C polynomial:0x1EDC6F41(BE)/0x82F63B78(LE)
- * CRC32 is a new instruction in Intel SSE4.2, the reference can be found at:
- * http://www.intel.com/products/processor/manuals/
- * Intel(R) 64 and IA-32 Architectures Software Developer's Manual
- * Volume 2A: Instruction Set Reference, A-M
- *
- * Copyright (C) 2008 Intel Corporation
- * Authors: Austin Zhang <austin_zhang@linux.intel.com>
- *          Kent Liu <kent.liu@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <crypto/internal/hash.h>
-
-#include <asm/cpufeature.h>
-#include <asm/cpu_device_id.h>
-
-#define CHKSUM_BLOCK_SIZE	1
-#define CHKSUM_DIGEST_SIZE	4
-
-#define SCALE_F	sizeof(unsigned long)
-
-#ifdef CONFIG_X86_64
-#define REX_PRE "0x48, "
-#else
-#define REX_PRE
-#endif
-
-static u32 crc32c_intel_le_hw_byte(u32 crc, unsigned char const *data, size_t length)
-{
-	while (length--) {
-		__asm__ __volatile__(
-			".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
-			:"=S"(crc)
-			:"0"(crc), "c"(*data)
-		);
-		data++;
-	}
-
-	return crc;
-}
-
-static u32 __pure crc32c_intel_le_hw(u32 crc, unsigned char const *p, size_t len)
-{
-	unsigned int iquotient = len / SCALE_F;
-	unsigned int iremainder = len % SCALE_F;
-	unsigned long *ptmp = (unsigned long *)p;
-
-	while (iquotient--) {
-		__asm__ __volatile__(
-			".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
-			:"=S"(crc)
-			:"0"(crc), "c"(*ptmp)
-		);
-		ptmp++;
-	}
-
-	if (iremainder)
-		crc = crc32c_intel_le_hw_byte(crc, (unsigned char *)ptmp,
-				 iremainder);
-
-	return crc;
-}
-
-/*
- * Setting the seed allows arbitrary accumulators and flexible XOR policy
- * If your algorithm starts with ~0, then XOR with ~0 before you set
- * the seed.
- */
-static int crc32c_intel_setkey(struct crypto_shash *hash, const u8 *key,
-			unsigned int keylen)
-{
-	u32 *mctx = crypto_shash_ctx(hash);
-
-	if (keylen != sizeof(u32)) {
-		crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
-		return -EINVAL;
-	}
-	*mctx = le32_to_cpup((__le32 *)key);
-	return 0;
-}
-
-static int crc32c_intel_init(struct shash_desc *desc)
-{
-	u32 *mctx = crypto_shash_ctx(desc->tfm);
-	u32 *crcp = shash_desc_ctx(desc);
-
-	*crcp = *mctx;
-
-	return 0;
-}
-
-static int crc32c_intel_update(struct shash_desc *desc, const u8 *data,
-			       unsigned int len)
-{
-	u32 *crcp = shash_desc_ctx(desc);
-
-	*crcp = crc32c_intel_le_hw(*crcp, data, len);
-	return 0;
-}
-
-static int __crc32c_intel_finup(u32 *crcp, const u8 *data, unsigned int len,
-				u8 *out)
-{
-	*(__le32 *)out = ~cpu_to_le32(crc32c_intel_le_hw(*crcp, data, len));
-	return 0;
-}
-
-static int crc32c_intel_finup(struct shash_desc *desc, const u8 *data,
-			      unsigned int len, u8 *out)
-{
-	return __crc32c_intel_finup(shash_desc_ctx(desc), data, len, out);
-}
-
-static int crc32c_intel_final(struct shash_desc *desc, u8 *out)
-{
-	u32 *crcp = shash_desc_ctx(desc);
-
-	*(__le32 *)out = ~cpu_to_le32p(crcp);
-	return 0;
-}
-
-static int crc32c_intel_digest(struct shash_desc *desc, const u8 *data,
-			       unsigned int len, u8 *out)
-{
-	return __crc32c_intel_finup(crypto_shash_ctx(desc->tfm), data, len,
-				    out);
-}
-
-static int crc32c_intel_cra_init(struct crypto_tfm *tfm)
-{
-	u32 *key = crypto_tfm_ctx(tfm);
-
-	*key = ~0;
-
-	return 0;
-}
-
-static struct shash_alg alg = {
-	.setkey			=	crc32c_intel_setkey,
-	.init			=	crc32c_intel_init,
-	.update			=	crc32c_intel_update,
-	.final			=	crc32c_intel_final,
-	.finup			=	crc32c_intel_finup,
-	.digest			=	crc32c_intel_digest,
-	.descsize		=	sizeof(u32),
-	.digestsize		=	CHKSUM_DIGEST_SIZE,
-	.base			=	{
-		.cra_name		=	"crc32c",
-		.cra_driver_name	=	"crc32c-intel",
-		.cra_priority		=	200,
-		.cra_blocksize		=	CHKSUM_BLOCK_SIZE,
-		.cra_ctxsize		=	sizeof(u32),
-		.cra_module		=	THIS_MODULE,
-		.cra_init		=	crc32c_intel_cra_init,
-	}
-};
-
-static const struct x86_cpu_id crc32c_cpu_id[] = {
-	X86_FEATURE_MATCH(X86_FEATURE_XMM4_2),
-	{}
-};
-MODULE_DEVICE_TABLE(x86cpu, crc32c_cpu_id);
-
-static int __init crc32c_intel_mod_init(void)
-{
-	if (!x86_match_cpu(crc32c_cpu_id))
-		return -ENODEV;
-	return crypto_register_shash(&alg);
-}
-
-static void __exit crc32c_intel_mod_fini(void)
-{
-	crypto_unregister_shash(&alg);
-}
-
-module_init(crc32c_intel_mod_init);
-module_exit(crc32c_intel_mod_fini);
-
-MODULE_AUTHOR("Austin Zhang <austin.zhang@intel.com>, Kent Liu <kent.liu@intel.com>");
-MODULE_DESCRIPTION("CRC32c (Castagnoli) optimization using Intel Hardware.");
-MODULE_LICENSE("GPL");
-
-MODULE_ALIAS("crc32c");
-MODULE_ALIAS("crc32c-intel");
diff --git a/arch/x86/crypto/crc32c-intel_glue.c b/arch/x86/crypto/crc32c-intel_glue.c
new file mode 100644
index 0000000..6812ad9
--- /dev/null
+++ b/arch/x86/crypto/crc32c-intel_glue.c
@@ -0,0 +1,284 @@
+/*
+ * Using hardware provided CRC32 instruction to accelerate the CRC32 disposal.
+ * CRC32C polynomial:0x1EDC6F41(BE)/0x82F63B78(LE)
+ * CRC32 is a new instruction in Intel SSE4.2, the reference can be found at:
+ * http://www.intel.com/products/processor/manuals/
+ * Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+ * Volume 2A: Instruction Set Reference, A-M
+ *
+ * Copyright (C) 2008 Intel Corporation
+ * Authors: Austin Zhang <austin_zhang@linux.intel.com>
+ *          Kent Liu <kent.liu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <crypto/internal/hash.h>
+
+#include <asm/cpufeature.h>
+#include <asm/cpu_device_id.h>
+#include <asm/i387.h>
+#include <asm/fpu-internal.h>
+
+#define CHKSUM_BLOCK_SIZE	1
+#define CHKSUM_DIGEST_SIZE	4
+
+#define SCALE_F	sizeof(unsigned long)
+
+#ifdef CONFIG_X86_64
+#define REX_PRE "0x48, "
+#else
+#define REX_PRE
+#endif
+
+#ifdef CONFIG_X86_64
+/*
+ * use carryless multiply version of crc32c when buffer
+ * size is >= 512 (when eager fpu is enabled) or
+ * >= 1024 (when eager fpu is disabled) to account
+ * for fpu state save/restore overhead.
+ */
+#define CRC32C_PCL_BREAKEVEN_EAGERFPU	512
+#define CRC32C_PCL_BREAKEVEN_NOEAGERFPU	1024
+
+asmlinkage unsigned int crc_pcl(const u8 *buffer, int len,
+				unsigned int crc_init);
+static int crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_EAGERFPU;
+#if defined(X86_FEATURE_EAGER_FPU)
+#define set_pcl_breakeven_point()					\
+do {									\
+	if (!use_eager_fpu())						\
+		crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_NOEAGERFPU;	\
+} while (0)
+#else
+#define set_pcl_breakeven_point()					\
+	(crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_NOEAGERFPU)
+#endif
+#endif /* CONFIG_X86_64 */
+
+static u32 crc32c_intel_le_hw_byte(u32 crc, unsigned char const *data, size_t length)
+{
+	while (length--) {
+		__asm__ __volatile__(
+			".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
+			:"=S"(crc)
+			:"0"(crc), "c"(*data)
+		);
+		data++;
+	}
+
+	return crc;
+}
+
+static u32 __pure crc32c_intel_le_hw(u32 crc, unsigned char const *p, size_t len)
+{
+	unsigned int iquotient = len / SCALE_F;
+	unsigned int iremainder = len % SCALE_F;
+	unsigned long *ptmp = (unsigned long *)p;
+
+	while (iquotient--) {
+		__asm__ __volatile__(
+			".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
+			:"=S"(crc)
+			:"0"(crc), "c"(*ptmp)
+		);
+		ptmp++;
+	}
+
+	if (iremainder)
+		crc = crc32c_intel_le_hw_byte(crc, (unsigned char *)ptmp,
+				 iremainder);
+
+	return crc;
+}
+
+/*
+ * Setting the seed allows arbitrary accumulators and flexible XOR policy
+ * If your algorithm starts with ~0, then XOR with ~0 before you set
+ * the seed.
+ */
+static int crc32c_intel_setkey(struct crypto_shash *hash, const u8 *key,
+			unsigned int keylen)
+{
+	u32 *mctx = crypto_shash_ctx(hash);
+
+	if (keylen != sizeof(u32)) {
+		crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+	*mctx = le32_to_cpup((__le32 *)key);
+	return 0;
+}
+
+static int crc32c_intel_init(struct shash_desc *desc)
+{
+	u32 *mctx = crypto_shash_ctx(desc->tfm);
+	u32 *crcp = shash_desc_ctx(desc);
+
+	*crcp = *mctx;
+
+	return 0;
+}
+
+static int crc32c_intel_update(struct shash_desc *desc, const u8 *data,
+			       unsigned int len)
+{
+	u32 *crcp = shash_desc_ctx(desc);
+
+	*crcp = crc32c_intel_le_hw(*crcp, data, len);
+	return 0;
+}
+
+static int __crc32c_intel_finup(u32 *crcp, const u8 *data, unsigned int len,
+				u8 *out)
+{
+	*(__le32 *)out = ~cpu_to_le32(crc32c_intel_le_hw(*crcp, data, len));
+	return 0;
+}
+
+static int crc32c_intel_finup(struct shash_desc *desc, const u8 *data,
+			      unsigned int len, u8 *out)
+{
+	return __crc32c_intel_finup(shash_desc_ctx(desc), data, len, out);
+}
+
+static int crc32c_intel_final(struct shash_desc *desc, u8 *out)
+{
+	u32 *crcp = shash_desc_ctx(desc);
+
+	*(__le32 *)out = ~cpu_to_le32p(crcp);
+	return 0;
+}
+
+static int crc32c_intel_digest(struct shash_desc *desc, const u8 *data,
+			       unsigned int len, u8 *out)
+{
+	return __crc32c_intel_finup(crypto_shash_ctx(desc->tfm), data, len,
+				    out);
+}
+
+static int crc32c_intel_cra_init(struct crypto_tfm *tfm)
+{
+	u32 *key = crypto_tfm_ctx(tfm);
+
+	*key = ~0;
+
+	return 0;
+}
+
+#ifdef CONFIG_X86_64
+static int crc32c_pcl_intel_update(struct shash_desc *desc, const u8 *data,
+			       unsigned int len)
+{
+	u32 *crcp = shash_desc_ctx(desc);
+
+	/*
+	 * use faster PCL version if datasize is large enough to
+	 * overcome kernel fpu state save/restore overhead
+	 */
+	if (len >= crc32c_pcl_breakeven && irq_fpu_usable()) {
+		kernel_fpu_begin();
+		*crcp = crc_pcl(data, len, *crcp);
+		kernel_fpu_end();
+	} else
+		*crcp = crc32c_intel_le_hw(*crcp, data, len);
+	return 0;
+}
+
+static int __crc32c_pcl_intel_finup(u32 *crcp, const u8 *data, unsigned int len,
+				u8 *out)
+{
+	if (len >= crc32c_pcl_breakeven && irq_fpu_usable()) {
+		kernel_fpu_begin();
+		*(__le32 *)out = ~cpu_to_le32(crc_pcl(data, len, *crcp));
+		kernel_fpu_end();
+	} else
+		*(__le32 *)out =
+			~cpu_to_le32(crc32c_intel_le_hw(*crcp, data, len));
+	return 0;
+}
+
+static int crc32c_pcl_intel_finup(struct shash_desc *desc, const u8 *data,
+			      unsigned int len, u8 *out)
+{
+	return __crc32c_pcl_intel_finup(shash_desc_ctx(desc), data, len, out);
+}
+
+static int crc32c_pcl_intel_digest(struct shash_desc *desc, const u8 *data,
+			       unsigned int len, u8 *out)
+{
+	return __crc32c_pcl_intel_finup(crypto_shash_ctx(desc->tfm), data, len,
+				    out);
+}
+#endif /* CONFIG_X86_64 */
+
+static struct shash_alg alg = {
+	.setkey			=	crc32c_intel_setkey,
+	.init			=	crc32c_intel_init,
+	.update			=	crc32c_intel_update,
+	.final			=	crc32c_intel_final,
+	.finup			=	crc32c_intel_finup,
+	.digest			=	crc32c_intel_digest,
+	.descsize		=	sizeof(u32),
+	.digestsize		=	CHKSUM_DIGEST_SIZE,
+	.base			=	{
+		.cra_name		=	"crc32c",
+		.cra_driver_name	=	"crc32c-intel",
+		.cra_priority		=	200,
+		.cra_blocksize		=	CHKSUM_BLOCK_SIZE,
+		.cra_ctxsize		=	sizeof(u32),
+		.cra_module		=	THIS_MODULE,
+		.cra_init		=	crc32c_intel_cra_init,
+	}
+};
+
+static const struct x86_cpu_id crc32c_cpu_id[] = {
+	X86_FEATURE_MATCH(X86_FEATURE_XMM4_2),
+	{}
+};
+MODULE_DEVICE_TABLE(x86cpu, crc32c_cpu_id);
+
+static int __init crc32c_intel_mod_init(void)
+{
+	if (!x86_match_cpu(crc32c_cpu_id))
+		return -ENODEV;
+#ifdef CONFIG_X86_64
+	if (cpu_has_pclmulqdq) {
+		alg.update = crc32c_pcl_intel_update;
+		alg.finup = crc32c_pcl_intel_finup;
+		alg.digest = crc32c_pcl_intel_digest;
+		set_pcl_breakeven_point();
+	}
+#endif
+	return crypto_register_shash(&alg);
+}
+
+static void __exit crc32c_intel_mod_fini(void)
+{
+	crypto_unregister_shash(&alg);
+}
+
+module_init(crc32c_intel_mod_init);
+module_exit(crc32c_intel_mod_fini);
+
+MODULE_AUTHOR("Austin Zhang <austin.zhang@intel.com>, Kent Liu <kent.liu@intel.com>");
+MODULE_DESCRIPTION("CRC32c (Castagnoli) optimization using Intel Hardware.");
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("crc32c");
+MODULE_ALIAS("crc32c-intel");
diff --git a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
new file mode 100644
index 0000000..93c6d39
--- /dev/null
+++ b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
@@ -0,0 +1,460 @@
+/*
+ * Implement fast CRC32C with PCLMULQDQ instructions. (x86_64)
+ *
+ * The white paper on CRC32C calculations with PCLMULQDQ instruction can be
+ * downloaded from:
+ * http://download.intel.com/design/intarch/papers/323405.pdf
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Authors:
+ *	Wajdi Feghali <wajdi.k.feghali@intel.com>
+ *	James Guilford <james.guilford@intel.com>
+ *	David Cote <david.m.cote@intel.com>
+ *	Tim Chen <tim.c.chen@linux.intel.com>
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+## ISCSI CRC 32 Implementation with crc32 and pclmulqdq Instruction
+
+.macro LABEL prefix n
+\prefix\n\():
+.endm
+
+.macro JMPTBL_ENTRY i
+.word crc_\i - crc_array
+.endm
+
+.macro JNC_LESS_THAN j
+	jnc less_than_\j
+.endm
+
+# Define threshold where buffers are considered "small" and routed to more
+# efficient "by-1" code. This "by-1" code only handles up to 255 bytes, so
+# SMALL_SIZE can be no larger than 255.
+
+#define SMALL_SIZE 200
+
+.if (SMALL_SIZE > 255)
+.error "SMALL_ SIZE must be < 256"
+.endif
+
+# unsigned int crc_pcl(u8 *buffer, int len, unsigned int crc_init);
+
+.global crc_pcl
+crc_pcl:
+#define    bufp		%rdi
+#define    bufp_dw	%edi
+#define    bufp_w	%di
+#define    bufp_b	%dil
+#define    bufptmp	%rcx
+#define    block_0	%rcx
+#define    block_1	%rdx
+#define    block_2	%r11
+#define    len		%rsi
+#define    len_dw	%esi
+#define    len_w	%si
+#define    len_b	%sil
+#define    crc_init_arg %rdx
+#define    tmp		%rbx
+#define    crc_init	%r8
+#define    crc_init_dw	%r8d
+#define    crc1		%r9
+#define    crc2		%r10
+
+	pushq   %rbx
+	pushq   %rdi
+	pushq   %rsi
+
+	## Move crc_init for Linux to a different
+	mov     crc_init_arg, crc_init
+
+	################################################################
+	## 1) ALIGN:
+	################################################################
+
+	mov     bufp, bufptmp		# rdi = *buf
+	neg     bufp
+	and     $7, bufp		# calculate the unalignment amount of
+					# the address
+	je      proc_block		# Skip if aligned
+
+	## If len is less than 8 and we're unaligned, we need to jump
+	## to special code to avoid reading beyond the end of the buffer
+	cmp     $8, len
+	jae     do_align
+	# less_than_8 expects length in upper 3 bits of len_dw
+	# less_than_8_post_shl1 expects length = carryflag * 8 + len_dw[31:30]
+	shl     $32-3+1, len_dw
+	jmp     less_than_8_post_shl1
+
+do_align:
+	#### Calculate CRC of unaligned bytes of the buffer (if any)
+	movq    (bufptmp), tmp		# load a quadward from the buffer
+	add     bufp, bufptmp		# align buffer pointer for quadword
+					# processing
+	sub     bufp, len		# update buffer length
+align_loop:
+	crc32b  %bl, crc_init_dw 	# compute crc32 of 1-byte
+	shr     $8, tmp			# get next byte
+	dec     bufp
+	jne     align_loop
+
+proc_block:
+
+	################################################################
+	## 2) PROCESS  BLOCKS:
+	################################################################
+
+	## compute num of bytes to be processed
+	movq    len, tmp		# save num bytes in tmp
+
+	cmpq    $128*24, len
+	jae     full_block
+
+continue_block:
+	cmpq    $SMALL_SIZE, len
+	jb      small
+
+	## len < 128*24
+	movq    $2731, %rax		# 2731 = ceil(2^16 / 24)
+	mul     len_dw
+	shrq    $16, %rax
+
+	## eax contains floor(bytes / 24) = num 24-byte chunks to do
+
+	## process rax 24-byte chunks (128 >= rax >= 0)
+
+	## compute end address of each block
+	## block 0 (base addr + RAX * 8)
+	## block 1 (base addr + RAX * 16)
+	## block 2 (base addr + RAX * 24)
+	lea     (bufptmp, %rax, 8), block_0
+	lea     (block_0, %rax, 8), block_1
+	lea     (block_1, %rax, 8), block_2
+
+	xor     crc1, crc1
+	xor     crc2, crc2
+
+	## branch into array
+	lea	jump_table(%rip), bufp
+	movzxw  (bufp, %rax, 2), len
+	offset=crc_array-jump_table
+	lea     offset(bufp, len, 1), bufp
+	jmp     *bufp
+
+	################################################################
+	## 2a) PROCESS FULL BLOCKS:
+	################################################################
+full_block:
+	movq    $128,%rax
+	lea     128*8*2(block_0), block_1
+	lea     128*8*3(block_0), block_2
+	add     $128*8*1, block_0
+
+	xor     crc1,crc1
+	xor     crc2,crc2
+
+	# Fall thruogh into top of crc array (crc_128)
+
+	################################################################
+	## 3) CRC Array:
+	################################################################
+
+crc_array:
+	i=128
+.rept 128-1
+.altmacro
+LABEL crc_ %i
+.noaltmacro
+	crc32q   -i*8(block_0), crc_init
+	crc32q   -i*8(block_1), crc1
+	crc32q   -i*8(block_2), crc2
+	i=(i-1)
+.endr
+
+.altmacro
+LABEL crc_ %i
+.noaltmacro
+	crc32q   -i*8(block_0), crc_init
+	crc32q   -i*8(block_1), crc1
+# SKIP  crc32  -i*8(block_2), crc2 ; Don't do this one yet
+
+	mov     block_2, block_0
+
+	################################################################
+	## 4) Combine three results:
+	################################################################
+
+	lea	(K_table-16)(%rip), bufp	# first entry is for idx 1
+	shlq    $3, %rax			# rax *= 8
+	subq    %rax, tmp			# tmp -= rax*8
+	shlq    $1, %rax
+	subq    %rax, tmp			# tmp -= rax*16
+						# (total tmp -= rax*24)
+	addq    %rax, bufp
+
+	movdqa  (bufp), %xmm0			# 2 consts: K1:K2
+
+	movq    crc_init, %xmm1			# CRC for block 1
+	pclmulqdq $0x00,%xmm0,%xmm1		# Multiply by K2
+
+	movq    crc1, %xmm2			# CRC for block 2
+	pclmulqdq $0x10, %xmm0, %xmm2		# Multiply by K1
+
+	pxor    %xmm2,%xmm1
+	movq    %xmm1, %rax
+	xor     -i*8(block_2), %rax
+	mov     crc2, crc_init
+	crc32   %rax, crc_init
+
+################################################################
+## 5) Check for end:
+################################################################
+
+LABEL crc_ 0
+	mov     tmp, len
+	cmp     $128*24, tmp
+	jae     full_block
+	cmp     $24, tmp
+	jae     continue_block
+
+less_than_24:
+	shl     $32-4, len_dw			# less_than_16 expects length
+						# in upper 4 bits of len_dw
+	jnc     less_than_16
+	crc32q  (bufptmp), crc_init
+	crc32q  8(bufptmp), crc_init
+	jz      do_return
+	add     $16, bufptmp
+	# len is less than 8 if we got here
+	# less_than_8 expects length in upper 3 bits of len_dw
+	# less_than_8_post_shl1 expects length = carryflag * 8 + len_dw[31:30]
+	shl     $2, len_dw
+	jmp     less_than_8_post_shl1
+
+	#######################################################################
+	## 6) LESS THAN 256-bytes REMAIN AT THIS POINT (8-bits of len are full)
+	#######################################################################
+small:
+	shl $32-8, len_dw		# Prepare len_dw for less_than_256
+	j=256
+.rept 5					# j = {256, 128, 64, 32, 16}
+.altmacro
+LABEL less_than_ %j			# less_than_j: Length should be in
+					# upper lg(j) bits of len_dw
+	j=(j/2)
+	shl     $1, len_dw		# Get next MSB
+	JNC_LESS_THAN %j
+.noaltmacro
+	i=0
+.rept (j/8)
+	crc32q  i(bufptmp), crc_init	# Compute crc32 of 8-byte data
+	i=i+8
+.endr
+	jz      do_return		# Return if remaining length is zero
+	add     $j, bufptmp		# Advance buf
+.endr
+
+less_than_8:				# Length should be stored in
+					# upper 3 bits of len_dw
+	shl     $1, len_dw
+less_than_8_post_shl1:
+	jnc     less_than_4
+	crc32l  (bufptmp), crc_init_dw	# CRC of 4 bytes
+	jz      do_return		# return if remaining data is zero
+	add     $4, bufptmp
+less_than_4:				# Length should be stored in
+					# upper 2 bits of len_dw
+	shl     $1, len_dw
+	jnc     less_than_2
+	crc32w  (bufptmp), crc_init_dw	# CRC of 2 bytes
+	jz      do_return		# return if remaining data is zero
+	add     $2, bufptmp
+less_than_2:				# Length should be stored in the MSB
+					# of len_dw
+	shl     $1, len_dw
+	jnc     less_than_1
+	crc32b  (bufptmp), crc_init_dw	# CRC of 1 byte
+less_than_1:				# Length should be zero
+do_return:
+	movq    crc_init, %rax
+	popq    %rsi
+	popq    %rdi
+	popq    %rbx
+        ret
+
+        ################################################################
+        ## jump table        Table is 129 entries x 2 bytes each
+        ################################################################
+.align 4
+jump_table:
+	i=0
+.rept 129
+.altmacro
+JMPTBL_ENTRY %i
+.noaltmacro
+	i=i+1
+.endr
+	################################################################
+	## PCLMULQDQ tables
+	## Table is 128 entries x 2 quad words each
+	################################################################
+.data
+.align 64
+K_table:
+        .quad 0x14cd00bd6,0x105ec76f0
+        .quad 0x0ba4fc28e,0x14cd00bd6
+        .quad 0x1d82c63da,0x0f20c0dfe
+        .quad 0x09e4addf8,0x0ba4fc28e
+        .quad 0x039d3b296,0x1384aa63a
+        .quad 0x102f9b8a2,0x1d82c63da
+        .quad 0x14237f5e6,0x01c291d04
+        .quad 0x00d3b6092,0x09e4addf8
+        .quad 0x0c96cfdc0,0x0740eef02
+        .quad 0x18266e456,0x039d3b296
+        .quad 0x0daece73e,0x0083a6eec
+        .quad 0x0ab7aff2a,0x102f9b8a2
+        .quad 0x1248ea574,0x1c1733996
+        .quad 0x083348832,0x14237f5e6
+        .quad 0x12c743124,0x02ad91c30
+        .quad 0x0b9e02b86,0x00d3b6092
+        .quad 0x018b33a4e,0x06992cea2
+        .quad 0x1b331e26a,0x0c96cfdc0
+        .quad 0x17d35ba46,0x07e908048
+        .quad 0x1bf2e8b8a,0x18266e456
+        .quad 0x1a3e0968a,0x11ed1f9d8
+        .quad 0x0ce7f39f4,0x0daece73e
+        .quad 0x061d82e56,0x0f1d0f55e
+        .quad 0x0d270f1a2,0x0ab7aff2a
+        .quad 0x1c3f5f66c,0x0a87ab8a8
+        .quad 0x12ed0daac,0x1248ea574
+        .quad 0x065863b64,0x08462d800
+        .quad 0x11eef4f8e,0x083348832
+        .quad 0x1ee54f54c,0x071d111a8
+        .quad 0x0b3e32c28,0x12c743124
+        .quad 0x0064f7f26,0x0ffd852c6
+        .quad 0x0dd7e3b0c,0x0b9e02b86
+        .quad 0x0f285651c,0x0dcb17aa4
+        .quad 0x010746f3c,0x018b33a4e
+        .quad 0x1c24afea4,0x0f37c5aee
+        .quad 0x0271d9844,0x1b331e26a
+        .quad 0x08e766a0c,0x06051d5a2
+        .quad 0x093a5f730,0x17d35ba46
+        .quad 0x06cb08e5c,0x11d5ca20e
+        .quad 0x06b749fb2,0x1bf2e8b8a
+        .quad 0x1167f94f2,0x021f3d99c
+        .quad 0x0cec3662e,0x1a3e0968a
+        .quad 0x19329634a,0x08f158014
+        .quad 0x0e6fc4e6a,0x0ce7f39f4
+        .quad 0x08227bb8a,0x1a5e82106
+        .quad 0x0b0cd4768,0x061d82e56
+        .quad 0x13c2b89c4,0x188815ab2
+        .quad 0x0d7a4825c,0x0d270f1a2
+        .quad 0x10f5ff2ba,0x105405f3e
+        .quad 0x00167d312,0x1c3f5f66c
+        .quad 0x0f6076544,0x0e9adf796
+        .quad 0x026f6a60a,0x12ed0daac
+        .quad 0x1a2adb74e,0x096638b34
+        .quad 0x19d34af3a,0x065863b64
+        .quad 0x049c3cc9c,0x1e50585a0
+        .quad 0x068bce87a,0x11eef4f8e
+        .quad 0x1524fa6c6,0x19f1c69dc
+        .quad 0x16cba8aca,0x1ee54f54c
+        .quad 0x042d98888,0x12913343e
+        .quad 0x1329d9f7e,0x0b3e32c28
+        .quad 0x1b1c69528,0x088f25a3a
+        .quad 0x02178513a,0x0064f7f26
+        .quad 0x0e0ac139e,0x04e36f0b0
+        .quad 0x0170076fa,0x0dd7e3b0c
+        .quad 0x141a1a2e2,0x0bd6f81f8
+        .quad 0x16ad828b4,0x0f285651c
+        .quad 0x041d17b64,0x19425cbba
+        .quad 0x1fae1cc66,0x010746f3c
+        .quad 0x1a75b4b00,0x18db37e8a
+        .quad 0x0f872e54c,0x1c24afea4
+        .quad 0x01e41e9fc,0x04c144932
+        .quad 0x086d8e4d2,0x0271d9844
+        .quad 0x160f7af7a,0x052148f02
+        .quad 0x05bb8f1bc,0x08e766a0c
+        .quad 0x0a90fd27a,0x0a3c6f37a
+        .quad 0x0b3af077a,0x093a5f730
+        .quad 0x04984d782,0x1d22c238e
+        .quad 0x0ca6ef3ac,0x06cb08e5c
+        .quad 0x0234e0b26,0x063ded06a
+        .quad 0x1d88abd4a,0x06b749fb2
+        .quad 0x04597456a,0x04d56973c
+        .quad 0x0e9e28eb4,0x1167f94f2
+        .quad 0x07b3ff57a,0x19385bf2e
+        .quad 0x0c9c8b782,0x0cec3662e
+        .quad 0x13a9cba9e,0x0e417f38a
+        .quad 0x093e106a4,0x19329634a
+        .quad 0x167001a9c,0x14e727980
+        .quad 0x1ddffc5d4,0x0e6fc4e6a
+        .quad 0x00df04680,0x0d104b8fc
+        .quad 0x02342001e,0x08227bb8a
+        .quad 0x00a2a8d7e,0x05b397730
+        .quad 0x168763fa6,0x0b0cd4768
+        .quad 0x1ed5a407a,0x0e78eb416
+        .quad 0x0d2c3ed1a,0x13c2b89c4
+        .quad 0x0995a5724,0x1641378f0
+        .quad 0x19b1afbc4,0x0d7a4825c
+        .quad 0x109ffedc0,0x08d96551c
+        .quad 0x0f2271e60,0x10f5ff2ba
+        .quad 0x00b0bf8ca,0x00bf80dd2
+        .quad 0x123888b7a,0x00167d312
+        .quad 0x1e888f7dc,0x18dcddd1c
+        .quad 0x002ee03b2,0x0f6076544
+        .quad 0x183e8d8fe,0x06a45d2b2
+        .quad 0x133d7a042,0x026f6a60a
+        .quad 0x116b0f50c,0x1dd3e10e8
+        .quad 0x05fabe670,0x1a2adb74e
+        .quad 0x130004488,0x0de87806c
+        .quad 0x000bcf5f6,0x19d34af3a
+        .quad 0x18f0c7078,0x014338754
+        .quad 0x017f27698,0x049c3cc9c
+        .quad 0x058ca5f00,0x15e3e77ee
+        .quad 0x1af900c24,0x068bce87a
+        .quad 0x0b5cfca28,0x0dd07448e
+        .quad 0x0ded288f8,0x1524fa6c6
+        .quad 0x059f229bc,0x1d8048348
+        .quad 0x06d390dec,0x16cba8aca
+        .quad 0x037170390,0x0a3e3e02c
+        .quad 0x06353c1cc,0x042d98888
+        .quad 0x0c4584f5c,0x0d73c7bea
+        .quad 0x1f16a3418,0x1329d9f7e
+        .quad 0x0531377e2,0x185137662
+        .quad 0x1d8d9ca7c,0x1b1c69528
+        .quad 0x0b25b29f2,0x18a08b5bc
+        .quad 0x19fb2a8b0,0x02178513a
+        .quad 0x1a08fe6ac,0x1da758ae0
+        .quad 0x045cddf4e,0x0e0ac139e
+        .quad 0x1a91647f2,0x169cf9eb0
+        .quad 0x1a0f717c4,0x0170076fa
diff --git a/arch/x86/crypto/glue_helper-asm-avx.S b/arch/x86/crypto/glue_helper-asm-avx.S
new file mode 100644
index 0000000..f7b6ea2
--- /dev/null
+++ b/arch/x86/crypto/glue_helper-asm-avx.S
@@ -0,0 +1,91 @@
+/*
+ * Shared glue code for 128bit block ciphers, AVX assembler macros
+ *
+ * Copyright (c) 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define load_8way(src, x0, x1, x2, x3, x4, x5, x6, x7) \
+	vmovdqu (0*16)(src), x0; \
+	vmovdqu (1*16)(src), x1; \
+	vmovdqu (2*16)(src), x2; \
+	vmovdqu (3*16)(src), x3; \
+	vmovdqu (4*16)(src), x4; \
+	vmovdqu (5*16)(src), x5; \
+	vmovdqu (6*16)(src), x6; \
+	vmovdqu (7*16)(src), x7;
+
+#define store_8way(dst, x0, x1, x2, x3, x4, x5, x6, x7) \
+	vmovdqu x0, (0*16)(dst); \
+	vmovdqu x1, (1*16)(dst); \
+	vmovdqu x2, (2*16)(dst); \
+	vmovdqu x3, (3*16)(dst); \
+	vmovdqu x4, (4*16)(dst); \
+	vmovdqu x5, (5*16)(dst); \
+	vmovdqu x6, (6*16)(dst); \
+	vmovdqu x7, (7*16)(dst);
+
+#define store_cbc_8way(src, dst, x0, x1, x2, x3, x4, x5, x6, x7) \
+	vpxor (0*16)(src), x1, x1; \
+	vpxor (1*16)(src), x2, x2; \
+	vpxor (2*16)(src), x3, x3; \
+	vpxor (3*16)(src), x4, x4; \
+	vpxor (4*16)(src), x5, x5; \
+	vpxor (5*16)(src), x6, x6; \
+	vpxor (6*16)(src), x7, x7; \
+	store_8way(dst, x0, x1, x2, x3, x4, x5, x6, x7);
+
+#define inc_le128(x, minus_one, tmp) \
+	vpcmpeqq minus_one, x, tmp; \
+	vpsubq minus_one, x, x; \
+	vpslldq $8, tmp, tmp; \
+	vpsubq tmp, x, x;
+
+#define load_ctr_8way(iv, bswap, x0, x1, x2, x3, x4, x5, x6, x7, t0, t1, t2) \
+	vpcmpeqd t0, t0, t0; \
+	vpsrldq $8, t0, t0; /* low: -1, high: 0 */ \
+	vmovdqa bswap, t1; \
+	\
+	/* load IV and byteswap */ \
+	vmovdqu (iv), x7; \
+	vpshufb t1, x7, x0; \
+	\
+	/* construct IVs */ \
+	inc_le128(x7, t0, t2); \
+	vpshufb t1, x7, x1; \
+	inc_le128(x7, t0, t2); \
+	vpshufb t1, x7, x2; \
+	inc_le128(x7, t0, t2); \
+	vpshufb t1, x7, x3; \
+	inc_le128(x7, t0, t2); \
+	vpshufb t1, x7, x4; \
+	inc_le128(x7, t0, t2); \
+	vpshufb t1, x7, x5; \
+	inc_le128(x7, t0, t2); \
+	vpshufb t1, x7, x6; \
+	inc_le128(x7, t0, t2); \
+	vmovdqa x7, t2; \
+	vpshufb t1, x7, x7; \
+	inc_le128(t2, t0, t1); \
+	vmovdqu t2, (iv);
+
+#define store_ctr_8way(src, dst, x0, x1, x2, x3, x4, x5, x6, x7) \
+	vpxor (0*16)(src), x0, x0; \
+	vpxor (1*16)(src), x1, x1; \
+	vpxor (2*16)(src), x2, x2; \
+	vpxor (3*16)(src), x3, x3; \
+	vpxor (4*16)(src), x4, x4; \
+	vpxor (5*16)(src), x5, x5; \
+	vpxor (6*16)(src), x6, x6; \
+	vpxor (7*16)(src), x7, x7; \
+	store_8way(dst, x0, x1, x2, x3, x4, x5, x6, x7);
diff --git a/arch/x86/crypto/glue_helper.c b/arch/x86/crypto/glue_helper.c
index 30b3927..22ce4f6 100644
--- a/arch/x86/crypto/glue_helper.c
+++ b/arch/x86/crypto/glue_helper.c
@@ -221,16 +221,16 @@ static void glue_ctr_crypt_final_128bit(const common_glue_ctr_func_t fn_ctr,
 	u8 *src = (u8 *)walk->src.virt.addr;
 	u8 *dst = (u8 *)walk->dst.virt.addr;
 	unsigned int nbytes = walk->nbytes;
-	u128 ctrblk;
+	le128 ctrblk;
 	u128 tmp;
 
-	be128_to_u128(&ctrblk, (be128 *)walk->iv);
+	be128_to_le128(&ctrblk, (be128 *)walk->iv);
 
 	memcpy(&tmp, src, nbytes);
 	fn_ctr(ctx, &tmp, &tmp, &ctrblk);
 	memcpy(dst, &tmp, nbytes);
 
-	u128_to_be128((be128 *)walk->iv, &ctrblk);
+	le128_to_be128((be128 *)walk->iv, &ctrblk);
 }
 EXPORT_SYMBOL_GPL(glue_ctr_crypt_final_128bit);
 
@@ -243,11 +243,11 @@ static unsigned int __glue_ctr_crypt_128bit(const struct common_glue_ctx *gctx,
 	unsigned int nbytes = walk->nbytes;
 	u128 *src = (u128 *)walk->src.virt.addr;
 	u128 *dst = (u128 *)walk->dst.virt.addr;
-	u128 ctrblk;
+	le128 ctrblk;
 	unsigned int num_blocks, func_bytes;
 	unsigned int i;
 
-	be128_to_u128(&ctrblk, (be128 *)walk->iv);
+	be128_to_le128(&ctrblk, (be128 *)walk->iv);
 
 	/* Process multi-block batch */
 	for (i = 0; i < gctx->num_funcs; i++) {
@@ -269,7 +269,7 @@ static unsigned int __glue_ctr_crypt_128bit(const struct common_glue_ctx *gctx,
 	}
 
 done:
-	u128_to_be128((be128 *)walk->iv, &ctrblk);
+	le128_to_be128((be128 *)walk->iv, &ctrblk);
 	return nbytes;
 }
 
diff --git a/arch/x86/crypto/serpent-avx-x86_64-asm_64.S b/arch/x86/crypto/serpent-avx-x86_64-asm_64.S
index 504106b..02b0e9f 100644
--- a/arch/x86/crypto/serpent-avx-x86_64-asm_64.S
+++ b/arch/x86/crypto/serpent-avx-x86_64-asm_64.S
@@ -24,7 +24,16 @@
  *
  */
 
+#include "glue_helper-asm-avx.S"
+
 .file "serpent-avx-x86_64-asm_64.S"
+
+.data
+.align 16
+
+.Lbswap128_mask:
+	.byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+
 .text
 
 #define CTX %rdi
@@ -550,51 +559,27 @@
 	vpunpcklqdq		x3, t2, x2; \
 	vpunpckhqdq		x3, t2, x3;
 
-#define read_blocks(in, x0, x1, x2, x3, t0, t1, t2) \
-	vmovdqu (0*4*4)(in),	x0; \
-	vmovdqu (1*4*4)(in),	x1; \
-	vmovdqu (2*4*4)(in),	x2; \
-	vmovdqu (3*4*4)(in),	x3; \
-	\
+#define read_blocks(x0, x1, x2, x3, t0, t1, t2) \
 	transpose_4x4(x0, x1, x2, x3, t0, t1, t2)
 
-#define write_blocks(out, x0, x1, x2, x3, t0, t1, t2) \
-	transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
-	\
-	vmovdqu x0,		(0*4*4)(out); \
-	vmovdqu x1,		(1*4*4)(out); \
-	vmovdqu x2,		(2*4*4)(out); \
-	vmovdqu x3,		(3*4*4)(out);
-
-#define xor_blocks(out, x0, x1, x2, x3, t0, t1, t2) \
-	transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
-	\
-	vpxor (0*4*4)(out),	x0, x0;       \
-	vmovdqu x0,		(0*4*4)(out); \
-	vpxor (1*4*4)(out),	x1, x1;       \
-	vmovdqu x1,		(1*4*4)(out); \
-	vpxor (2*4*4)(out),	x2, x2;       \
-	vmovdqu x2,		(2*4*4)(out); \
-	vpxor (3*4*4)(out),	x3, x3;       \
-	vmovdqu x3,		(3*4*4)(out);
+#define write_blocks(x0, x1, x2, x3, t0, t1, t2) \
+	transpose_4x4(x0, x1, x2, x3, t0, t1, t2)
 
 .align 8
-.global __serpent_enc_blk_8way_avx
-.type   __serpent_enc_blk_8way_avx,@function;
+.type   __serpent_enc_blk8_avx,@function;
 
-__serpent_enc_blk_8way_avx:
+__serpent_enc_blk8_avx:
 	/* input:
 	 *	%rdi: ctx, CTX
-	 *	%rsi: dst
-	 *	%rdx: src
-	 *	%rcx: bool, if true: xor output
+	 *	RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: blocks
+	 * output:
+	 *	RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: encrypted blocks
 	 */
 
 	vpcmpeqd RNOT, RNOT, RNOT;
 
-	leaq (4*4*4)(%rdx), %rax;
-	read_blocks(%rdx, RA1, RB1, RC1, RD1, RK0, RK1, RK2);
-	read_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2);
+	read_blocks(RA1, RB1, RC1, RD1, RK0, RK1, RK2);
+	read_blocks(RA2, RB2, RC2, RD2, RK0, RK1, RK2);
 
 						 K2(RA, RB, RC, RD, RE, 0);
 	S(S0, RA, RB, RC, RD, RE);		LK2(RC, RB, RD, RA, RE, 1);
@@ -630,38 +615,26 @@ __serpent_enc_blk_8way_avx:
 	S(S6, RA, RB, RD, RC, RE);		LK2(RD, RE, RB, RC, RA, 31);
 	S(S7, RD, RE, RB, RC, RA);		 K2(RA, RB, RC, RD, RE, 32);
 
-	leaq (4*4*4)(%rsi), %rax;
-
-	testb %cl, %cl;
-	jnz __enc_xor8;
-
-	write_blocks(%rsi, RA1, RB1, RC1, RD1, RK0, RK1, RK2);
-	write_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2);
-
-	ret;
-
-__enc_xor8:
-	xor_blocks(%rsi, RA1, RB1, RC1, RD1, RK0, RK1, RK2);
-	xor_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2);
+	write_blocks(RA1, RB1, RC1, RD1, RK0, RK1, RK2);
+	write_blocks(RA2, RB2, RC2, RD2, RK0, RK1, RK2);
 
 	ret;
 
 .align 8
-.global serpent_dec_blk_8way_avx
-.type   serpent_dec_blk_8way_avx,@function;
+.type   __serpent_dec_blk8_avx,@function;
 
-serpent_dec_blk_8way_avx:
+__serpent_dec_blk8_avx:
 	/* input:
 	 *	%rdi: ctx, CTX
-	 *	%rsi: dst
-	 *	%rdx: src
+	 *	RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: encrypted blocks
+	 * output:
+	 *	RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2: decrypted blocks
 	 */
 
 	vpcmpeqd RNOT, RNOT, RNOT;
 
-	leaq (4*4*4)(%rdx), %rax;
-	read_blocks(%rdx, RA1, RB1, RC1, RD1, RK0, RK1, RK2);
-	read_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2);
+	read_blocks(RA1, RB1, RC1, RD1, RK0, RK1, RK2);
+	read_blocks(RA2, RB2, RC2, RD2, RK0, RK1, RK2);
 
 						 K2(RA, RB, RC, RD, RE, 32);
 	SP(SI7, RA, RB, RC, RD, RE, 31);	KL2(RB, RD, RA, RE, RC, 31);
@@ -697,8 +670,85 @@ serpent_dec_blk_8way_avx:
 	SP(SI1, RD, RB, RC, RA, RE, 1);		KL2(RE, RB, RC, RA, RD, 1);
 	S(SI0, RE, RB, RC, RA, RD);		 K2(RC, RD, RB, RE, RA, 0);
 
-	leaq (4*4*4)(%rsi), %rax;
-	write_blocks(%rsi, RC1, RD1, RB1, RE1, RK0, RK1, RK2);
-	write_blocks(%rax, RC2, RD2, RB2, RE2, RK0, RK1, RK2);
+	write_blocks(RC1, RD1, RB1, RE1, RK0, RK1, RK2);
+	write_blocks(RC2, RD2, RB2, RE2, RK0, RK1, RK2);
+
+	ret;
+
+.align 8
+.global serpent_ecb_enc_8way_avx
+.type   serpent_ecb_enc_8way_avx,@function;
+
+serpent_ecb_enc_8way_avx:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+
+	load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+	call __serpent_enc_blk8_avx;
+
+	store_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+	ret;
+
+.align 8
+.global serpent_ecb_dec_8way_avx
+.type   serpent_ecb_dec_8way_avx,@function;
+
+serpent_ecb_dec_8way_avx:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+
+	load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+	call __serpent_dec_blk8_avx;
+
+	store_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
+
+	ret;
+
+.align 8
+.global serpent_cbc_dec_8way_avx
+.type   serpent_cbc_dec_8way_avx,@function;
+
+serpent_cbc_dec_8way_avx:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+
+	load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+	call __serpent_dec_blk8_avx;
+
+	store_cbc_8way(%rdx, %rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
+
+	ret;
+
+.align 8
+.global serpent_ctr_8way_avx
+.type   serpent_ctr_8way_avx,@function;
+
+serpent_ctr_8way_avx:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 *	%rcx: iv (little endian, 128bit)
+	 */
+
+	load_ctr_8way(%rcx, .Lbswap128_mask, RA1, RB1, RC1, RD1, RA2, RB2, RC2,
+		      RD2, RK0, RK1, RK2);
+
+	call __serpent_enc_blk8_avx;
+
+	store_ctr_8way(%rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
 	ret;
diff --git a/arch/x86/crypto/serpent_avx_glue.c b/arch/x86/crypto/serpent_avx_glue.c
index 3f543a0..52abaaf 100644
--- a/arch/x86/crypto/serpent_avx_glue.c
+++ b/arch/x86/crypto/serpent_avx_glue.c
@@ -42,55 +42,24 @@
 #include <asm/crypto/ablk_helper.h>
 #include <asm/crypto/glue_helper.h>
 
-static void serpent_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src)
-{
-	u128 ivs[SERPENT_PARALLEL_BLOCKS - 1];
-	unsigned int j;
-
-	for (j = 0; j < SERPENT_PARALLEL_BLOCKS - 1; j++)
-		ivs[j] = src[j];
-
-	serpent_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src);
-
-	for (j = 0; j < SERPENT_PARALLEL_BLOCKS - 1; j++)
-		u128_xor(dst + (j + 1), dst + (j + 1), ivs + j);
-}
-
-static void serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
+static void serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
 	be128 ctrblk;
 
-	u128_to_be128(&ctrblk, iv);
-	u128_inc(iv);
+	le128_to_be128(&ctrblk, iv);
+	le128_inc(iv);
 
 	__serpent_encrypt(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
 	u128_xor(dst, src, (u128 *)&ctrblk);
 }
 
-static void serpent_crypt_ctr_xway(void *ctx, u128 *dst, const u128 *src,
-				   u128 *iv)
-{
-	be128 ctrblks[SERPENT_PARALLEL_BLOCKS];
-	unsigned int i;
-
-	for (i = 0; i < SERPENT_PARALLEL_BLOCKS; i++) {
-		if (dst != src)
-			dst[i] = src[i];
-
-		u128_to_be128(&ctrblks[i], iv);
-		u128_inc(iv);
-	}
-
-	serpent_enc_blk_xway_xor(ctx, (u8 *)dst, (u8 *)ctrblks);
-}
-
 static const struct common_glue_ctx serpent_enc = {
 	.num_funcs = 2,
 	.fpu_blocks_limit = SERPENT_PARALLEL_BLOCKS,
 
 	.funcs = { {
 		.num_blocks = SERPENT_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(serpent_enc_blk_xway) }
+		.fn_u = { .ecb = GLUE_FUNC_CAST(serpent_ecb_enc_8way_avx) }
 	}, {
 		.num_blocks = 1,
 		.fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_encrypt) }
@@ -103,7 +72,7 @@ static const struct common_glue_ctx serpent_ctr = {
 
 	.funcs = { {
 		.num_blocks = SERPENT_PARALLEL_BLOCKS,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_crypt_ctr_xway) }
+		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_ctr_8way_avx) }
 	}, {
 		.num_blocks = 1,
 		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_crypt_ctr) }
@@ -116,7 +85,7 @@ static const struct common_glue_ctx serpent_dec = {
 
 	.funcs = { {
 		.num_blocks = SERPENT_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(serpent_dec_blk_xway) }
+		.fn_u = { .ecb = GLUE_FUNC_CAST(serpent_ecb_dec_8way_avx) }
 	}, {
 		.num_blocks = 1,
 		.fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_decrypt) }
@@ -129,7 +98,7 @@ static const struct common_glue_ctx serpent_dec_cbc = {
 
 	.funcs = { {
 		.num_blocks = SERPENT_PARALLEL_BLOCKS,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(serpent_decrypt_cbc_xway) }
+		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(serpent_cbc_dec_8way_avx) }
 	}, {
 		.num_blocks = 1,
 		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(__serpent_decrypt) }
@@ -193,7 +162,7 @@ static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
 	ctx->fpu_enabled = serpent_fpu_begin(ctx->fpu_enabled, nbytes);
 
 	if (nbytes == bsize * SERPENT_PARALLEL_BLOCKS) {
-		serpent_enc_blk_xway(ctx->ctx, srcdst, srcdst);
+		serpent_ecb_enc_8way_avx(ctx->ctx, srcdst, srcdst);
 		return;
 	}
 
@@ -210,7 +179,7 @@ static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
 	ctx->fpu_enabled = serpent_fpu_begin(ctx->fpu_enabled, nbytes);
 
 	if (nbytes == bsize * SERPENT_PARALLEL_BLOCKS) {
-		serpent_dec_blk_xway(ctx->ctx, srcdst, srcdst);
+		serpent_ecb_dec_8way_avx(ctx->ctx, srcdst, srcdst);
 		return;
 	}
 
diff --git a/arch/x86/crypto/serpent_sse2_glue.c b/arch/x86/crypto/serpent_sse2_glue.c
index 9107a99..97a356e 100644
--- a/arch/x86/crypto/serpent_sse2_glue.c
+++ b/arch/x86/crypto/serpent_sse2_glue.c
@@ -59,19 +59,19 @@ static void serpent_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src)
 		u128_xor(dst + (j + 1), dst + (j + 1), ivs + j);
 }
 
-static void serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
+static void serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
 	be128 ctrblk;
 
-	u128_to_be128(&ctrblk, iv);
-	u128_inc(iv);
+	le128_to_be128(&ctrblk, iv);
+	le128_inc(iv);
 
 	__serpent_encrypt(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
 	u128_xor(dst, src, (u128 *)&ctrblk);
 }
 
 static void serpent_crypt_ctr_xway(void *ctx, u128 *dst, const u128 *src,
-				   u128 *iv)
+				   le128 *iv)
 {
 	be128 ctrblks[SERPENT_PARALLEL_BLOCKS];
 	unsigned int i;
@@ -80,8 +80,8 @@ static void serpent_crypt_ctr_xway(void *ctx, u128 *dst, const u128 *src,
 		if (dst != src)
 			dst[i] = src[i];
 
-		u128_to_be128(&ctrblks[i], iv);
-		u128_inc(iv);
+		le128_to_be128(&ctrblks[i], iv);
+		le128_inc(iv);
 	}
 
 	serpent_enc_blk_xway_xor(ctx, (u8 *)dst, (u8 *)ctrblks);
diff --git a/arch/x86/crypto/twofish-avx-x86_64-asm_64.S b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S
index 1585abb..ebac16b 100644
--- a/arch/x86/crypto/twofish-avx-x86_64-asm_64.S
+++ b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S
@@ -23,7 +23,16 @@
  *
  */
 
+#include "glue_helper-asm-avx.S"
+
 .file "twofish-avx-x86_64-asm_64.S"
+
+.data
+.align 16
+
+.Lbswap128_mask:
+	.byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+
 .text
 
 /* structure of crypto context */
@@ -217,69 +226,45 @@
 	vpunpcklqdq		x3, t2, x2; \
 	vpunpckhqdq		x3, t2, x3;
 
-#define inpack_blocks(in, x0, x1, x2, x3, wkey, t0, t1, t2) \
-	vpxor (0*4*4)(in),	wkey, x0; \
-	vpxor (1*4*4)(in),	wkey, x1; \
-	vpxor (2*4*4)(in),	wkey, x2; \
-	vpxor (3*4*4)(in),	wkey, x3; \
+#define inpack_blocks(x0, x1, x2, x3, wkey, t0, t1, t2) \
+	vpxor		x0, wkey, x0; \
+	vpxor		x1, wkey, x1; \
+	vpxor		x2, wkey, x2; \
+	vpxor		x3, wkey, x3; \
 	\
 	transpose_4x4(x0, x1, x2, x3, t0, t1, t2)
 
-#define outunpack_blocks(out, x0, x1, x2, x3, wkey, t0, t1, t2) \
-	transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
-	\
-	vpxor		x0, wkey, x0;     \
-	vmovdqu 	x0, (0*4*4)(out); \
-	vpxor		x1, wkey, x1;     \
-	vmovdqu		x1, (1*4*4)(out); \
-	vpxor		x2, wkey, x2;     \
-	vmovdqu		x2, (2*4*4)(out); \
-	vpxor		x3, wkey, x3;     \
-	vmovdqu		x3, (3*4*4)(out);
-
-#define outunpack_xor_blocks(out, x0, x1, x2, x3, wkey, t0, t1, t2) \
+#define outunpack_blocks(x0, x1, x2, x3, wkey, t0, t1, t2) \
 	transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
 	\
-	vpxor		x0, wkey, x0;         \
-	vpxor		(0*4*4)(out), x0, x0; \
-	vmovdqu 	x0, (0*4*4)(out);     \
-	vpxor		x1, wkey, x1;         \
-	vpxor		(1*4*4)(out), x1, x1; \
-	vmovdqu	        x1, (1*4*4)(out);     \
-	vpxor		x2, wkey, x2;         \
-	vpxor           (2*4*4)(out), x2, x2; \
-	vmovdqu		x2, (2*4*4)(out);     \
-	vpxor		x3, wkey, x3;         \
-	vpxor           (3*4*4)(out), x3, x3; \
-	vmovdqu		x3, (3*4*4)(out);
+	vpxor		x0, wkey, x0; \
+	vpxor		x1, wkey, x1; \
+	vpxor		x2, wkey, x2; \
+	vpxor		x3, wkey, x3;
 
 .align 8
-.global __twofish_enc_blk_8way
-.type   __twofish_enc_blk_8way,@function;
+.type	__twofish_enc_blk8,@function;
 
-__twofish_enc_blk_8way:
+__twofish_enc_blk8:
 	/* input:
 	 *	%rdi: ctx, CTX
-	 *	%rsi: dst
-	 *	%rdx: src
-	 *	%rcx: bool, if true: xor output
+	 *	RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: blocks
+	 * output:
+	 *	RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2: encrypted blocks
 	 */
 
+	vmovdqu w(CTX), RK1;
+
 	pushq %rbp;
 	pushq %rbx;
 	pushq %rcx;
 
-	vmovdqu w(CTX), RK1;
-
-	leaq (4*4*4)(%rdx), %rax;
-	inpack_blocks(%rdx, RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2);
+	inpack_blocks(RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2);
 	preload_rgi(RA1);
 	rotate_1l(RD1);
-	inpack_blocks(%rax, RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2);
+	inpack_blocks(RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2);
 	rotate_1l(RD2);
 
-	movq %rsi, %r11;
-
 	encrypt_cycle(0);
 	encrypt_cycle(1);
 	encrypt_cycle(2);
@@ -295,47 +280,33 @@ __twofish_enc_blk_8way:
 	popq %rbx;
 	popq %rbp;
 
-	leaq (4*4*4)(%r11), %rax;
-
-	testb %cl, %cl;
-	jnz __enc_xor8;
-
-	outunpack_blocks(%r11, RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
-	outunpack_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
-
-	ret;
-
-__enc_xor8:
-	outunpack_xor_blocks(%r11, RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
-	outunpack_xor_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
+	outunpack_blocks(RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
+	outunpack_blocks(RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
 
 	ret;
 
 .align 8
-.global twofish_dec_blk_8way
-.type   twofish_dec_blk_8way,@function;
+.type	__twofish_dec_blk8,@function;
 
-twofish_dec_blk_8way:
+__twofish_dec_blk8:
 	/* input:
 	 *	%rdi: ctx, CTX
-	 *	%rsi: dst
-	 *	%rdx: src
+	 *	RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2: encrypted blocks
+	 * output:
+	 *	RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: decrypted blocks
 	 */
 
+	vmovdqu (w+4*4)(CTX), RK1;
+
 	pushq %rbp;
 	pushq %rbx;
 
-	vmovdqu (w+4*4)(CTX), RK1;
-
-	leaq (4*4*4)(%rdx), %rax;
-	inpack_blocks(%rdx, RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
+	inpack_blocks(RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
 	preload_rgi(RC1);
 	rotate_1l(RA1);
-	inpack_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
+	inpack_blocks(RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
 	rotate_1l(RA2);
 
-	movq %rsi, %r11;
-
 	decrypt_cycle(7);
 	decrypt_cycle(6);
 	decrypt_cycle(5);
@@ -350,8 +321,103 @@ twofish_dec_blk_8way:
 	popq %rbx;
 	popq %rbp;
 
-	leaq (4*4*4)(%r11), %rax;
-	outunpack_blocks(%r11, RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2);
-	outunpack_blocks(%rax, RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2);
+	outunpack_blocks(RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2);
+	outunpack_blocks(RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2);
+
+	ret;
+
+.align 8
+.global twofish_ecb_enc_8way
+.type   twofish_ecb_enc_8way,@function;
+
+twofish_ecb_enc_8way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+
+	movq %rsi, %r11;
+
+	load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+	call __twofish_enc_blk8;
+
+	store_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
+
+	ret;
+
+.align 8
+.global twofish_ecb_dec_8way
+.type   twofish_ecb_dec_8way,@function;
+
+twofish_ecb_dec_8way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+
+	movq %rsi, %r11;
+
+	load_8way(%rdx, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
+
+	call __twofish_dec_blk8;
+
+	store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+	ret;
+
+.align 8
+.global twofish_cbc_dec_8way
+.type   twofish_cbc_dec_8way,@function;
+
+twofish_cbc_dec_8way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+
+	pushq %r12;
+
+	movq %rsi, %r11;
+	movq %rdx, %r12;
+
+	load_8way(%rdx, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
+
+	call __twofish_dec_blk8;
+
+	store_cbc_8way(%r12, %r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
+
+	popq %r12;
+
+	ret;
+
+.align 8
+.global twofish_ctr_8way
+.type   twofish_ctr_8way,@function;
+
+twofish_ctr_8way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 *	%rcx: iv (little endian, 128bit)
+	 */
+
+	pushq %r12;
+
+	movq %rsi, %r11;
+	movq %rdx, %r12;
+
+	load_ctr_8way(%rcx, .Lbswap128_mask, RA1, RB1, RC1, RD1, RA2, RB2, RC2,
+		      RD2, RX0, RX1, RY0);
+
+	call __twofish_enc_blk8;
+
+	store_ctr_8way(%r12, %r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
+
+	popq %r12;
 
 	ret;
diff --git a/arch/x86/crypto/twofish_avx_glue.c b/arch/x86/crypto/twofish_avx_glue.c
index e7708b5..94ac91d 100644
--- a/arch/x86/crypto/twofish_avx_glue.c
+++ b/arch/x86/crypto/twofish_avx_glue.c
@@ -45,66 +45,23 @@
 
 #define TWOFISH_PARALLEL_BLOCKS 8
 
-static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
-					const u8 *src)
-{
-	__twofish_enc_blk_3way(ctx, dst, src, false);
-}
-
 /* 8-way parallel cipher functions */
-asmlinkage void __twofish_enc_blk_8way(struct twofish_ctx *ctx, u8 *dst,
-				       const u8 *src, bool xor);
-asmlinkage void twofish_dec_blk_8way(struct twofish_ctx *ctx, u8 *dst,
+asmlinkage void twofish_ecb_enc_8way(struct twofish_ctx *ctx, u8 *dst,
+				     const u8 *src);
+asmlinkage void twofish_ecb_dec_8way(struct twofish_ctx *ctx, u8 *dst,
 				     const u8 *src);
 
-static inline void twofish_enc_blk_xway(struct twofish_ctx *ctx, u8 *dst,
-					const u8 *src)
-{
-	__twofish_enc_blk_8way(ctx, dst, src, false);
-}
-
-static inline void twofish_enc_blk_xway_xor(struct twofish_ctx *ctx, u8 *dst,
-					    const u8 *src)
-{
-	__twofish_enc_blk_8way(ctx, dst, src, true);
-}
+asmlinkage void twofish_cbc_dec_8way(struct twofish_ctx *ctx, u8 *dst,
+				     const u8 *src);
+asmlinkage void twofish_ctr_8way(struct twofish_ctx *ctx, u8 *dst,
+				 const u8 *src, le128 *iv);
 
-static inline void twofish_dec_blk_xway(struct twofish_ctx *ctx, u8 *dst,
+static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
 					const u8 *src)
 {
-	twofish_dec_blk_8way(ctx, dst, src);
-}
-
-static void twofish_dec_blk_cbc_xway(void *ctx, u128 *dst, const u128 *src)
-{
-	u128 ivs[TWOFISH_PARALLEL_BLOCKS - 1];
-	unsigned int j;
-
-	for (j = 0; j < TWOFISH_PARALLEL_BLOCKS - 1; j++)
-		ivs[j] = src[j];
-
-	twofish_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src);
-
-	for (j = 0; j < TWOFISH_PARALLEL_BLOCKS - 1; j++)
-		u128_xor(dst + (j + 1), dst + (j + 1), ivs + j);
+	__twofish_enc_blk_3way(ctx, dst, src, false);
 }
 
-static void twofish_enc_blk_ctr_xway(void *ctx, u128 *dst, const u128 *src,
-				     u128 *iv)
-{
-	be128 ctrblks[TWOFISH_PARALLEL_BLOCKS];
-	unsigned int i;
-
-	for (i = 0; i < TWOFISH_PARALLEL_BLOCKS; i++) {
-		if (dst != src)
-			dst[i] = src[i];
-
-		u128_to_be128(&ctrblks[i], iv);
-		u128_inc(iv);
-	}
-
-	twofish_enc_blk_xway_xor(ctx, (u8 *)dst, (u8 *)ctrblks);
-}
 
 static const struct common_glue_ctx twofish_enc = {
 	.num_funcs = 3,
@@ -112,7 +69,7 @@ static const struct common_glue_ctx twofish_enc = {
 
 	.funcs = { {
 		.num_blocks = TWOFISH_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_xway) }
+		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_ecb_enc_8way) }
 	}, {
 		.num_blocks = 3,
 		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_3way) }
@@ -128,7 +85,7 @@ static const struct common_glue_ctx twofish_ctr = {
 
 	.funcs = { {
 		.num_blocks = TWOFISH_PARALLEL_BLOCKS,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_enc_blk_ctr_xway) }
+		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_ctr_8way) }
 	}, {
 		.num_blocks = 3,
 		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_enc_blk_ctr_3way) }
@@ -144,7 +101,7 @@ static const struct common_glue_ctx twofish_dec = {
 
 	.funcs = { {
 		.num_blocks = TWOFISH_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk_xway) }
+		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_ecb_dec_8way) }
 	}, {
 		.num_blocks = 3,
 		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk_3way) }
@@ -160,7 +117,7 @@ static const struct common_glue_ctx twofish_dec_cbc = {
 
 	.funcs = { {
 		.num_blocks = TWOFISH_PARALLEL_BLOCKS,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk_cbc_xway) }
+		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_cbc_dec_8way) }
 	}, {
 		.num_blocks = 3,
 		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk_cbc_3way) }
@@ -227,7 +184,7 @@ static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
 	ctx->fpu_enabled = twofish_fpu_begin(ctx->fpu_enabled, nbytes);
 
 	if (nbytes == bsize * TWOFISH_PARALLEL_BLOCKS) {
-		twofish_enc_blk_xway(ctx->ctx, srcdst, srcdst);
+		twofish_ecb_enc_8way(ctx->ctx, srcdst, srcdst);
 		return;
 	}
 
@@ -249,7 +206,7 @@ static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
 	ctx->fpu_enabled = twofish_fpu_begin(ctx->fpu_enabled, nbytes);
 
 	if (nbytes == bsize * TWOFISH_PARALLEL_BLOCKS) {
-		twofish_dec_blk_xway(ctx->ctx, srcdst, srcdst);
+		twofish_ecb_dec_8way(ctx->ctx, srcdst, srcdst);
 		return;
 	}
 
diff --git a/arch/x86/crypto/twofish_glue_3way.c b/arch/x86/crypto/twofish_glue_3way.c
index aa3eb35..13e63b3 100644
--- a/arch/x86/crypto/twofish_glue_3way.c
+++ b/arch/x86/crypto/twofish_glue_3way.c
@@ -62,15 +62,15 @@ void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src)
 }
 EXPORT_SYMBOL_GPL(twofish_dec_blk_cbc_3way);
 
-void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
+void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
 	be128 ctrblk;
 
 	if (dst != src)
 		*dst = *src;
 
-	u128_to_be128(&ctrblk, iv);
-	u128_inc(iv);
+	le128_to_be128(&ctrblk, iv);
+	le128_inc(iv);
 
 	twofish_enc_blk(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
 	u128_xor(dst, dst, (u128 *)&ctrblk);
@@ -78,7 +78,7 @@ void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
 EXPORT_SYMBOL_GPL(twofish_enc_blk_ctr);
 
 void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src,
-				     u128 *iv)
+			      le128 *iv)
 {
 	be128 ctrblks[3];
 
@@ -88,12 +88,12 @@ void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src,
 		dst[2] = src[2];
 	}
 
-	u128_to_be128(&ctrblks[0], iv);
-	u128_inc(iv);
-	u128_to_be128(&ctrblks[1], iv);
-	u128_inc(iv);
-	u128_to_be128(&ctrblks[2], iv);
-	u128_inc(iv);
+	le128_to_be128(&ctrblks[0], iv);
+	le128_inc(iv);
+	le128_to_be128(&ctrblks[1], iv);
+	le128_inc(iv);
+	le128_to_be128(&ctrblks[2], iv);
+	le128_inc(iv);
 
 	twofish_enc_blk_xor_3way(ctx, (u8 *)dst, (u8 *)ctrblks);
 }
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index 07b3a68..a703af1 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -35,7 +35,7 @@
 #undef WARN_OLD
 #undef CORE_DUMP /* definitely broken */
 
-static int load_aout_binary(struct linux_binprm *, struct pt_regs *regs);
+static int load_aout_binary(struct linux_binprm *);
 static int load_aout_library(struct file *);
 
 #ifdef CORE_DUMP
@@ -260,9 +260,10 @@ static u32 __user *create_aout_tables(char __user *p, struct linux_binprm *bprm)
  * These are the functions used to load a.out style executables and shared
  * libraries.  There is no binary dependent code anywhere else.
  */
-static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+static int load_aout_binary(struct linux_binprm *bprm)
 {
 	unsigned long error, fd_offset, rlim;
+	struct pt_regs *regs = current_pt_regs();
 	struct exec ex;
 	int retval;
 
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 076745f..32e6f05 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -467,11 +467,16 @@ GLOBAL(\label)
 	PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
 	PTREGSCALL stub32_execve, compat_sys_execve, %rcx
 	PTREGSCALL stub32_fork, sys_fork, %rdi
-	PTREGSCALL stub32_clone, sys32_clone, %rdx
 	PTREGSCALL stub32_vfork, sys_vfork, %rdi
 	PTREGSCALL stub32_iopl, sys_iopl, %rsi
 
 	ALIGN
+GLOBAL(stub32_clone)
+	leaq sys_clone(%rip),%rax
+	mov	%r8, %rcx
+	jmp  ia32_ptregs_common	
+
+	ALIGN
 ia32_ptregs_common:
 	popq %r11
 	CFI_ENDPROC
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
index 86d68d1..d0b689b 100644
--- a/arch/x86/ia32/sys_ia32.c
+++ b/arch/x86/ia32/sys_ia32.c
@@ -385,17 +385,6 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd,
 	return ret;
 }
 
-asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp,
-			    struct pt_regs *regs)
-{
-	void __user *parent_tid = (void __user *)regs->dx;
-	void __user *child_tid = (void __user *)regs->di;
-
-	if (!newsp)
-		newsp = regs->sp;
-	return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
-}
-
 /*
  * Some system calls that need sign extended arguments. This could be
  * done by a generic wrapper.
diff --git a/arch/x86/include/asm/context_tracking.h b/arch/x86/include/asm/context_tracking.h
new file mode 100644
index 0000000..1616562
--- /dev/null
+++ b/arch/x86/include/asm/context_tracking.h
@@ -0,0 +1,31 @@
+#ifndef _ASM_X86_CONTEXT_TRACKING_H
+#define _ASM_X86_CONTEXT_TRACKING_H
+
+#ifndef __ASSEMBLY__
+#include <linux/context_tracking.h>
+#include <asm/ptrace.h>
+
+static inline void exception_enter(struct pt_regs *regs)
+{
+	user_exit();
+}
+
+static inline void exception_exit(struct pt_regs *regs)
+{
+#ifdef CONFIG_CONTEXT_TRACKING
+	if (user_mode(regs))
+		user_enter();
+#endif
+}
+
+#else /* __ASSEMBLY__ */
+
+#ifdef CONFIG_CONTEXT_TRACKING
+# define SCHEDULE_USER call schedule_user
+#else
+# define SCHEDULE_USER call schedule
+#endif
+
+#endif /* !__ASSEMBLY__ */
+
+#endif
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 8c297aa..c22a492 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -311,6 +311,7 @@ extern const char * const x86_power_flags[32];
 #define cpu_has_cx8		boot_cpu_has(X86_FEATURE_CX8)
 #define cpu_has_cx16		boot_cpu_has(X86_FEATURE_CX16)
 #define cpu_has_eager_fpu	boot_cpu_has(X86_FEATURE_EAGER_FPU)
+#define cpu_has_topoext		boot_cpu_has(X86_FEATURE_TOPOEXT)
 
 #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64)
 # define cpu_has_invlpg		1
diff --git a/arch/x86/include/asm/crypto/camellia.h b/arch/x86/include/asm/crypto/camellia.h
new file mode 100644
index 0000000..98038ad
--- /dev/null
+++ b/arch/x86/include/asm/crypto/camellia.h
@@ -0,0 +1,82 @@
+#ifndef ASM_X86_CAMELLIA_H
+#define ASM_X86_CAMELLIA_H
+
+#include <linux/kernel.h>
+#include <linux/crypto.h>
+
+#define CAMELLIA_MIN_KEY_SIZE	16
+#define CAMELLIA_MAX_KEY_SIZE	32
+#define CAMELLIA_BLOCK_SIZE	16
+#define CAMELLIA_TABLE_BYTE_LEN	272
+#define CAMELLIA_PARALLEL_BLOCKS 2
+
+struct camellia_ctx {
+	u64 key_table[CAMELLIA_TABLE_BYTE_LEN / sizeof(u64)];
+	u32 key_length;
+};
+
+struct camellia_lrw_ctx {
+	struct lrw_table_ctx lrw_table;
+	struct camellia_ctx camellia_ctx;
+};
+
+struct camellia_xts_ctx {
+	struct camellia_ctx tweak_ctx;
+	struct camellia_ctx crypt_ctx;
+};
+
+extern int __camellia_setkey(struct camellia_ctx *cctx,
+			     const unsigned char *key,
+			     unsigned int key_len, u32 *flags);
+
+extern int lrw_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
+			       unsigned int keylen);
+extern void lrw_camellia_exit_tfm(struct crypto_tfm *tfm);
+
+extern int xts_camellia_setkey(struct crypto_tfm *tfm, const u8 *key,
+			       unsigned int keylen);
+
+/* regular block cipher functions */
+asmlinkage void __camellia_enc_blk(struct camellia_ctx *ctx, u8 *dst,
+				   const u8 *src, bool xor);
+asmlinkage void camellia_dec_blk(struct camellia_ctx *ctx, u8 *dst,
+				 const u8 *src);
+
+/* 2-way parallel cipher functions */
+asmlinkage void __camellia_enc_blk_2way(struct camellia_ctx *ctx, u8 *dst,
+					const u8 *src, bool xor);
+asmlinkage void camellia_dec_blk_2way(struct camellia_ctx *ctx, u8 *dst,
+				      const u8 *src);
+
+static inline void camellia_enc_blk(struct camellia_ctx *ctx, u8 *dst,
+				    const u8 *src)
+{
+	__camellia_enc_blk(ctx, dst, src, false);
+}
+
+static inline void camellia_enc_blk_xor(struct camellia_ctx *ctx, u8 *dst,
+					const u8 *src)
+{
+	__camellia_enc_blk(ctx, dst, src, true);
+}
+
+static inline void camellia_enc_blk_2way(struct camellia_ctx *ctx, u8 *dst,
+					 const u8 *src)
+{
+	__camellia_enc_blk_2way(ctx, dst, src, false);
+}
+
+static inline void camellia_enc_blk_xor_2way(struct camellia_ctx *ctx, u8 *dst,
+					     const u8 *src)
+{
+	__camellia_enc_blk_2way(ctx, dst, src, true);
+}
+
+/* glue helpers */
+extern void camellia_decrypt_cbc_2way(void *ctx, u128 *dst, const u128 *src);
+extern void camellia_crypt_ctr(void *ctx, u128 *dst, const u128 *src,
+			       le128 *iv);
+extern void camellia_crypt_ctr_2way(void *ctx, u128 *dst, const u128 *src,
+				    le128 *iv);
+
+#endif /* ASM_X86_CAMELLIA_H */
diff --git a/arch/x86/include/asm/crypto/glue_helper.h b/arch/x86/include/asm/crypto/glue_helper.h
index 3e408bd..e2d65b0 100644
--- a/arch/x86/include/asm/crypto/glue_helper.h
+++ b/arch/x86/include/asm/crypto/glue_helper.h
@@ -13,7 +13,7 @@
 typedef void (*common_glue_func_t)(void *ctx, u8 *dst, const u8 *src);
 typedef void (*common_glue_cbc_func_t)(void *ctx, u128 *dst, const u128 *src);
 typedef void (*common_glue_ctr_func_t)(void *ctx, u128 *dst, const u128 *src,
-				       u128 *iv);
+				       le128 *iv);
 
 #define GLUE_FUNC_CAST(fn) ((common_glue_func_t)(fn))
 #define GLUE_CBC_FUNC_CAST(fn) ((common_glue_cbc_func_t)(fn))
@@ -71,23 +71,29 @@ static inline void glue_fpu_end(bool fpu_enabled)
 		kernel_fpu_end();
 }
 
-static inline void u128_to_be128(be128 *dst, const u128 *src)
+static inline void le128_to_be128(be128 *dst, const le128 *src)
 {
-	dst->a = cpu_to_be64(src->a);
-	dst->b = cpu_to_be64(src->b);
+	dst->a = cpu_to_be64(le64_to_cpu(src->a));
+	dst->b = cpu_to_be64(le64_to_cpu(src->b));
 }
 
-static inline void be128_to_u128(u128 *dst, const be128 *src)
+static inline void be128_to_le128(le128 *dst, const be128 *src)
 {
-	dst->a = be64_to_cpu(src->a);
-	dst->b = be64_to_cpu(src->b);
+	dst->a = cpu_to_le64(be64_to_cpu(src->a));
+	dst->b = cpu_to_le64(be64_to_cpu(src->b));
 }
 
-static inline void u128_inc(u128 *i)
+static inline void le128_inc(le128 *i)
 {
-	i->b++;
-	if (!i->b)
-		i->a++;
+	u64 a = le64_to_cpu(i->a);
+	u64 b = le64_to_cpu(i->b);
+
+	b++;
+	if (!b)
+		a++;
+
+	i->a = cpu_to_le64(a);
+	i->b = cpu_to_le64(b);
 }
 
 extern int glue_ecb_crypt_128bit(const struct common_glue_ctx *gctx,
diff --git a/arch/x86/include/asm/crypto/serpent-avx.h b/arch/x86/include/asm/crypto/serpent-avx.h
index 432deed..0da1d3e 100644
--- a/arch/x86/include/asm/crypto/serpent-avx.h
+++ b/arch/x86/include/asm/crypto/serpent-avx.h
@@ -6,27 +6,14 @@
 
 #define SERPENT_PARALLEL_BLOCKS 8
 
-asmlinkage void __serpent_enc_blk_8way_avx(struct serpent_ctx *ctx, u8 *dst,
-					   const u8 *src, bool xor);
-asmlinkage void serpent_dec_blk_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void serpent_ecb_enc_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+					 const u8 *src);
+asmlinkage void serpent_ecb_dec_8way_avx(struct serpent_ctx *ctx, u8 *dst,
 					 const u8 *src);
 
-static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst,
-				   const u8 *src)
-{
-	__serpent_enc_blk_8way_avx(ctx, dst, src, false);
-}
-
-static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst,
-				       const u8 *src)
-{
-	__serpent_enc_blk_8way_avx(ctx, dst, src, true);
-}
-
-static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst,
-				   const u8 *src)
-{
-	serpent_dec_blk_8way_avx(ctx, dst, src);
-}
+asmlinkage void serpent_cbc_dec_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+					 const u8 *src);
+asmlinkage void serpent_ctr_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+				     const u8 *src, le128 *iv);
 
 #endif
diff --git a/arch/x86/include/asm/crypto/twofish.h b/arch/x86/include/asm/crypto/twofish.h
index 9d2c514..878c51c 100644
--- a/arch/x86/include/asm/crypto/twofish.h
+++ b/arch/x86/include/asm/crypto/twofish.h
@@ -31,9 +31,9 @@ asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst,
 /* helpers from twofish_x86_64-3way module */
 extern void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src);
 extern void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src,
-				u128 *iv);
+				le128 *iv);
 extern void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src,
-				     u128 *iv);
+				     le128 *iv);
 
 extern int lrw_twofish_setkey(struct crypto_tfm *tfm, const u8 *key,
 			      unsigned int keylen);
diff --git a/arch/x86/include/asm/device.h b/arch/x86/include/asm/device.h
index 93e1c55..03dd729 100644
--- a/arch/x86/include/asm/device.h
+++ b/arch/x86/include/asm/device.h
@@ -2,9 +2,6 @@
 #define _ASM_X86_DEVICE_H
 
 struct dev_archdata {
-#ifdef CONFIG_ACPI
-	void	*acpi_handle;
-#endif
 #ifdef CONFIG_X86_DEV_DMA_OPS
 	struct dma_map_ops *dma_ops;
 #endif
diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index f7b4c79..808dae6 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -47,6 +47,7 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
+	debug_dma_mapping_error(dev, dma_addr);
 	if (ops->mapping_error)
 		return ops->mapping_error(dev, dma_addr);
 
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index 3778256..c1f31ee 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -84,6 +84,8 @@ extern unsigned long pci_mem_start;
 extern int e820_any_mapped(u64 start, u64 end, unsigned type);
 extern int e820_all_mapped(u64 start, u64 end, unsigned type);
 extern void e820_add_region(u64 start, u64 size, int type);
+extern void e820_add_limit_region(u64 start, u64 size, int type);
+extern void e820_adjust_region(u64 *start, u64 *size);
 extern void e820_print_map(char *who);
 extern int
 sanitize_e820_map(struct e820entry *biosmap, int max_nr_map, u32 *pnr_map);
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index 5939f44..9c999c1 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -354,12 +354,10 @@ static inline int mmap_is_ia32(void)
 	return 0;
 }
 
-/* The first two values are special, do not change. See align_addr() */
+/* Do not change the values. See get_align_mask() */
 enum align_flags {
 	ALIGN_VA_32	= BIT(0),
 	ALIGN_VA_64	= BIT(1),
-	ALIGN_VDSO	= BIT(2),
-	ALIGN_TOPDOWN	= BIT(3),
 };
 
 struct va_alignment {
@@ -368,5 +366,5 @@ struct va_alignment {
 } ____cacheline_aligned;
 
 extern struct va_alignment va_align;
-extern unsigned long align_addr(unsigned long, struct file *, enum align_flags);
+extern unsigned long align_vdso_addr(unsigned long);
 #endif /* _ASM_X86_ELF_H */
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 54d73b1..d90c2fc 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -119,6 +119,23 @@ struct mce_log {
 #define K8_MCE_THRESHOLD_BASE      (MCE_EXTENDED_BANK + 1)
 
 #ifdef __KERNEL__
+
+struct mca_config {
+	bool dont_log_ce;
+	bool cmci_disabled;
+	bool ignore_ce;
+	bool disabled;
+	bool ser;
+	bool bios_cmci_threshold;
+	u8 banks;
+	s8 bootlog;
+	int tolerant;
+	int monarch_timeout;
+	int panic_timeout;
+	u32 rip_msr;
+};
+
+extern struct mca_config mca_cfg;
 extern void mce_register_decode_chain(struct notifier_block *nb);
 extern void mce_unregister_decode_chain(struct notifier_block *nb);
 
@@ -126,7 +143,6 @@ extern void mce_unregister_decode_chain(struct notifier_block *nb);
 #include <linux/init.h>
 #include <linux/atomic.h>
 
-extern int mce_disabled;
 extern int mce_p5_enabled;
 
 #ifdef CONFIG_X86_MCE
@@ -159,9 +175,6 @@ DECLARE_PER_CPU(struct device *, mce_device);
 #define MAX_NR_BANKS 32
 
 #ifdef CONFIG_X86_MCE_INTEL
-extern int mce_cmci_disabled;
-extern int mce_ignore_ce;
-extern int mce_bios_cmci_threshold;
 void mce_intel_feature_init(struct cpuinfo_x86 *c);
 void cmci_clear(void);
 void cmci_reenable(void);
diff --git a/arch/x86/include/asm/mman.h b/arch/x86/include/asm/mman.h
index 593e51d..513b05f 100644
--- a/arch/x86/include/asm/mman.h
+++ b/arch/x86/include/asm/mman.h
@@ -3,6 +3,9 @@
 
 #define MAP_32BIT	0x40		/* only give out 32bit addresses */
 
+#define MAP_HUGE_2MB    (21 << MAP_HUGE_SHIFT)
+#define MAP_HUGE_1GB    (30 << MAP_HUGE_SHIFT)
+
 #include <asm-generic/mman.h>
 
 #endif /* _ASM_X86_MMAN_H */
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 7f0edce..bcc3a35 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -35,11 +35,14 @@
 #define MSR_IA32_PERFCTR0		0x000000c1
 #define MSR_IA32_PERFCTR1		0x000000c2
 #define MSR_FSB_FREQ			0x000000cd
+#define MSR_NHM_PLATFORM_INFO		0x000000ce
 
 #define MSR_NHM_SNB_PKG_CST_CFG_CTL	0x000000e2
 #define NHM_C3_AUTO_DEMOTE		(1UL << 25)
 #define NHM_C1_AUTO_DEMOTE		(1UL << 26)
 #define ATM_LNC_C6_AUTO_DEMOTE		(1UL << 25)
+#define SNB_C1_AUTO_UNDEMOTE		(1UL << 27)
+#define SNB_C3_AUTO_UNDEMOTE		(1UL << 28)
 
 #define MSR_MTRRcap			0x000000fe
 #define MSR_IA32_BBL_CR_CTL		0x00000119
@@ -55,6 +58,8 @@
 
 #define MSR_OFFCORE_RSP_0		0x000001a6
 #define MSR_OFFCORE_RSP_1		0x000001a7
+#define MSR_NHM_TURBO_RATIO_LIMIT	0x000001ad
+#define MSR_IVT_TURBO_RATIO_LIMIT	0x000001ae
 
 #define MSR_LBR_SELECT			0x000001c8
 #define MSR_LBR_TOS			0x000001c9
@@ -103,6 +108,38 @@
 #define MSR_IA32_MC0_ADDR		0x00000402
 #define MSR_IA32_MC0_MISC		0x00000403
 
+/* C-state Residency Counters */
+#define MSR_PKG_C3_RESIDENCY		0x000003f8
+#define MSR_PKG_C6_RESIDENCY		0x000003f9
+#define MSR_PKG_C7_RESIDENCY		0x000003fa
+#define MSR_CORE_C3_RESIDENCY		0x000003fc
+#define MSR_CORE_C6_RESIDENCY		0x000003fd
+#define MSR_CORE_C7_RESIDENCY		0x000003fe
+#define MSR_PKG_C2_RESIDENCY		0x0000060d
+
+/* Run Time Average Power Limiting (RAPL) Interface */
+
+#define MSR_RAPL_POWER_UNIT		0x00000606
+
+#define MSR_PKG_POWER_LIMIT		0x00000610
+#define MSR_PKG_ENERGY_STATUS		0x00000611
+#define MSR_PKG_PERF_STATUS		0x00000613
+#define MSR_PKG_POWER_INFO		0x00000614
+
+#define MSR_DRAM_POWER_LIMIT		0x00000618
+#define MSR_DRAM_ENERGY_STATUS		0x00000619
+#define MSR_DRAM_PERF_STATUS		0x0000061b
+#define MSR_DRAM_POWER_INFO		0x0000061c
+
+#define MSR_PP0_POWER_LIMIT		0x00000638
+#define MSR_PP0_ENERGY_STATUS		0x00000639
+#define MSR_PP0_POLICY			0x0000063a
+#define MSR_PP0_PERF_STATUS		0x0000063b
+
+#define MSR_PP1_POWER_LIMIT		0x00000640
+#define MSR_PP1_ENERGY_STATUS		0x00000641
+#define MSR_PP1_POLICY			0x00000642
+
 #define MSR_AMD64_MC0_MASK		0xc0010044
 
 #define MSR_IA32_MCx_CTL(x)		(MSR_IA32_MC0_CTL + 4*(x))
@@ -337,6 +374,8 @@
 #define MSR_IA32_MISC_ENABLE_TURBO_DISABLE	(1ULL << 38)
 #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE	(1ULL << 39)
 
+#define MSR_IA32_TSC_DEADLINE		0x000006E0
+
 /* P4/Xeon+ specific */
 #define MSR_IA32_MCG_EAX		0x00000180
 #define MSR_IA32_MCG_EBX		0x00000181
diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
index 8ca8283..3698a6a 100644
--- a/arch/x86/include/asm/page.h
+++ b/arch/x86/include/asm/page.h
@@ -44,7 +44,8 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
  * case properly. Once all supported versions of gcc understand it, we can
  * remove this Voodoo magic stuff. (i.e. once gcc3.x is deprecated)
  */
-#define __pa_symbol(x)	__pa(__phys_reloc_hide((unsigned long)(x)))
+#define __pa_symbol(x) \
+	__phys_addr_symbol(__phys_reloc_hide((unsigned long)(x)))
 
 #define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
 
diff --git a/arch/x86/include/asm/page_32.h b/arch/x86/include/asm/page_32.h
index da4e762..4d550d0 100644
--- a/arch/x86/include/asm/page_32.h
+++ b/arch/x86/include/asm/page_32.h
@@ -15,6 +15,7 @@ extern unsigned long __phys_addr(unsigned long);
 #else
 #define __phys_addr(x)		__phys_addr_nodebug(x)
 #endif
+#define __phys_addr_symbol(x)	__phys_addr(x)
 #define __phys_reloc_hide(x)	RELOC_HIDE((x), 0)
 
 #ifdef CONFIG_FLATMEM
diff --git a/arch/x86/include/asm/page_64.h b/arch/x86/include/asm/page_64.h
index 072694e..0f1ddee 100644
--- a/arch/x86/include/asm/page_64.h
+++ b/arch/x86/include/asm/page_64.h
@@ -3,4 +3,40 @@
 
 #include <asm/page_64_types.h>
 
+#ifndef __ASSEMBLY__
+
+/* duplicated to the one in bootmem.h */
+extern unsigned long max_pfn;
+extern unsigned long phys_base;
+
+static inline unsigned long __phys_addr_nodebug(unsigned long x)
+{
+	unsigned long y = x - __START_KERNEL_map;
+
+	/* use the carry flag to determine if x was < __START_KERNEL_map */
+	x = y + ((x > y) ? phys_base : (__START_KERNEL_map - PAGE_OFFSET));
+
+	return x;
+}
+
+#ifdef CONFIG_DEBUG_VIRTUAL
+extern unsigned long __phys_addr(unsigned long);
+extern unsigned long __phys_addr_symbol(unsigned long);
+#else
+#define __phys_addr(x)		__phys_addr_nodebug(x)
+#define __phys_addr_symbol(x) \
+	((unsigned long)(x) - __START_KERNEL_map + phys_base)
+#endif
+
+#define __phys_reloc_hide(x)	(x)
+
+#ifdef CONFIG_FLATMEM
+#define pfn_valid(pfn)          ((pfn) < max_pfn)
+#endif
+
+void clear_page(void *page);
+void copy_page(void *to, void *from);
+
+#endif	/* !__ASSEMBLY__ */
+
 #endif /* _ASM_X86_PAGE_64_H */
diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h
index 320f7bb..8b491e6 100644
--- a/arch/x86/include/asm/page_64_types.h
+++ b/arch/x86/include/asm/page_64_types.h
@@ -50,26 +50,4 @@
 #define KERNEL_IMAGE_SIZE	(512 * 1024 * 1024)
 #define KERNEL_IMAGE_START	_AC(0xffffffff80000000, UL)
 
-#ifndef __ASSEMBLY__
-void clear_page(void *page);
-void copy_page(void *to, void *from);
-
-/* duplicated to the one in bootmem.h */
-extern unsigned long max_pfn;
-extern unsigned long phys_base;
-
-extern unsigned long __phys_addr(unsigned long);
-#define __phys_reloc_hide(x)	(x)
-
-#define vmemmap ((struct page *)VMEMMAP_START)
-
-extern void init_extra_mapping_uc(unsigned long phys, unsigned long size);
-extern void init_extra_mapping_wb(unsigned long phys, unsigned long size);
-
-#endif	/* !__ASSEMBLY__ */
-
-#ifdef CONFIG_FLATMEM
-#define pfn_valid(pfn)          ((pfn) < max_pfn)
-#endif
-
 #endif /* _ASM_X86_PAGE_64_DEFS_H */
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index a1f780d..d369359 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -407,6 +407,12 @@ static inline int pte_present(pte_t a)
 	return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE);
 }
 
+#define pte_accessible pte_accessible
+static inline int pte_accessible(pte_t a)
+{
+	return pte_flags(a) & _PAGE_PRESENT;
+}
+
 static inline int pte_hidden(pte_t pte)
 {
 	return pte_flags(pte) & _PAGE_HIDDEN;
@@ -768,6 +774,18 @@ static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
        memcpy(dst, src, count * sizeof(pgd_t));
 }
 
+/*
+ * The x86 doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
+ */
+static inline void update_mmu_cache(struct vm_area_struct *vma,
+		unsigned long addr, pte_t *ptep)
+{
+}
+static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
+		unsigned long addr, pmd_t *pmd)
+{
+}
 
 #include <asm-generic/pgtable.h>
 #endif	/* __ASSEMBLY__ */
diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h
index 8faa215..9ee3221 100644
--- a/arch/x86/include/asm/pgtable_32.h
+++ b/arch/x86/include/asm/pgtable_32.h
@@ -66,13 +66,6 @@ do {						\
 	__flush_tlb_one((vaddr));		\
 } while (0)
 
-/*
- * The i386 doesn't have any external MMU info: the kernel page
- * tables contain all the necessary information.
- */
-#define update_mmu_cache(vma, address, ptep) do { } while (0)
-#define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)
-
 #endif /* !__ASSEMBLY__ */
 
 /*
diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h
index 47356f9..e22c1db 100644
--- a/arch/x86/include/asm/pgtable_64.h
+++ b/arch/x86/include/asm/pgtable_64.h
@@ -142,9 +142,6 @@ static inline int pgd_large(pgd_t pgd) { return 0; }
 #define pte_offset_map(dir, address) pte_offset_kernel((dir), (address))
 #define pte_unmap(pte) ((void)(pte))/* NOP */
 
-#define update_mmu_cache(vma, address, ptep) do { } while (0)
-#define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)
-
 /* Encode and de-code a swap entry */
 #if _PAGE_BIT_FILE < _PAGE_BIT_PROTNONE
 #define SWP_TYPE_BITS (_PAGE_BIT_FILE - _PAGE_BIT_PRESENT - 1)
@@ -183,6 +180,11 @@ extern void cleanup_highmap(void);
 
 #define __HAVE_ARCH_PTE_SAME
 
+#define vmemmap ((struct page *)VMEMMAP_START)
+
+extern void init_extra_mapping_uc(unsigned long phys, unsigned long size);
+extern void init_extra_mapping_wb(unsigned long phys, unsigned long size);
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _ASM_X86_PGTABLE_64_H */
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index ad1fc85..51350f3 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -178,8 +178,6 @@ static inline int hlt_works(int cpu)
 
 extern void cpu_detect(struct cpuinfo_x86 *c);
 
-extern struct pt_regs *idle_regs(struct pt_regs *);
-
 extern void early_cpu_init(void);
 extern void identify_boot_cpu(void);
 extern void identify_secondary_cpu(struct cpuinfo_x86 *);
@@ -187,7 +185,7 @@ extern void print_cpu_info(struct cpuinfo_x86 *);
 void print_cpu_msr(struct cpuinfo_x86 *);
 extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
 extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
-extern unsigned short num_cache_leaves;
+extern void init_amd_cacheinfo(struct cpuinfo_x86 *c);
 
 extern void detect_extended_topology(struct cpuinfo_x86 *c);
 extern void detect_ht(struct cpuinfo_x86 *c);
diff --git a/arch/x86/include/asm/rcu.h b/arch/x86/include/asm/rcu.h
deleted file mode 100644
index d1ac07a..0000000
--- a/arch/x86/include/asm/rcu.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef _ASM_X86_RCU_H
-#define _ASM_X86_RCU_H
-
-#ifndef __ASSEMBLY__
-
-#include <linux/rcupdate.h>
-#include <asm/ptrace.h>
-
-static inline void exception_enter(struct pt_regs *regs)
-{
-	rcu_user_exit();
-}
-
-static inline void exception_exit(struct pt_regs *regs)
-{
-#ifdef CONFIG_RCU_USER_QS
-	if (user_mode(regs))
-		rcu_user_enter();
-#endif
-}
-
-#else /* __ASSEMBLY__ */
-
-#ifdef CONFIG_RCU_USER_QS
-# define SCHEDULE_USER call schedule_user
-#else
-# define SCHEDULE_USER call schedule
-#endif
-
-#endif /* !__ASSEMBLY__ */
-
-#endif
diff --git a/arch/x86/include/asm/signal.h b/arch/x86/include/asm/signal.h
index 323973f..0dba8b7 100644
--- a/arch/x86/include/asm/signal.h
+++ b/arch/x86/include/asm/signal.h
@@ -260,8 +260,6 @@ struct pt_regs;
 
 #endif /* !__i386__ */
 
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h
index a9a8cf3..c76fae4 100644
--- a/arch/x86/include/asm/sys_ia32.h
+++ b/arch/x86/include/asm/sys_ia32.h
@@ -54,8 +54,6 @@ asmlinkage long sys32_pwrite(unsigned int, const char __user *, u32, u32, u32);
 asmlinkage long sys32_personality(unsigned long);
 asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32);
 
-asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *);
-
 long sys32_lseek(unsigned int, int, unsigned int);
 long sys32_kill(int, int);
 long sys32_fadvise64_64(int, __u32, __u32, __u32, __u32, int);
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h
index 2be0b88..7fddd7a 100644
--- a/arch/x86/include/asm/syscalls.h
+++ b/arch/x86/include/asm/syscalls.h
@@ -21,13 +21,15 @@ asmlinkage long sys_ioperm(unsigned long, unsigned long, int);
 long sys_iopl(unsigned int, struct pt_regs *);
 
 /* kernel/process.c */
-int sys_fork(struct pt_regs *);
-int sys_vfork(struct pt_regs *);
-long sys_execve(const char __user *,
-		const char __user *const __user *,
-		const char __user *const __user *);
+int sys_fork(void);
+int sys_vfork(void);
+#ifdef CONFIG_CLONE_BACKWARDS
+long sys_clone(unsigned long, unsigned long, void __user *, int,
+	       void __user *);
+#else
 long sys_clone(unsigned long, unsigned long, void __user *,
-	       void __user *, struct pt_regs *);
+	       void __user *, int);
+#endif
 
 /* kernel/ldt.c */
 asmlinkage int sys_modify_ldt(int, void __user *, unsigned long);
diff --git a/arch/x86/include/asm/trace_clock.h b/arch/x86/include/asm/trace_clock.h
new file mode 100644
index 0000000..beab86c
--- /dev/null
+++ b/arch/x86/include/asm/trace_clock.h
@@ -0,0 +1,20 @@
+#ifndef _ASM_X86_TRACE_CLOCK_H
+#define _ASM_X86_TRACE_CLOCK_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#ifdef CONFIG_X86_TSC
+
+extern u64 notrace trace_clock_x86_tsc(void);
+
+# define ARCH_TRACE_CLOCKS \
+	{ trace_clock_x86_tsc,	"x86-tsc",	.in_ns = 0 },
+
+#else /* !CONFIG_X86_TSC */
+
+#define ARCH_TRACE_CLOCKS
+
+#endif
+
+#endif  /* _ASM_X86_TRACE_CLOCK_H */
diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h
index 16f3fc6..0e7dea7 100644
--- a/arch/x86/include/asm/unistd.h
+++ b/arch/x86/include/asm/unistd.h
@@ -51,6 +51,9 @@
 # define __ARCH_WANT_SYS_UTIME
 # define __ARCH_WANT_SYS_WAITPID
 # define __ARCH_WANT_SYS_EXECVE
+# define __ARCH_WANT_SYS_FORK
+# define __ARCH_WANT_SYS_VFORK
+# define __ARCH_WANT_SYS_CLONE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h
index b47c2a8..062921e 100644
--- a/arch/x86/include/asm/uv/uv.h
+++ b/arch/x86/include/asm/uv/uv.h
@@ -16,7 +16,7 @@ extern void uv_system_init(void);
 extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
 						 struct mm_struct *mm,
 						 unsigned long start,
-						 unsigned end,
+						 unsigned long end,
 						 unsigned int cpu);
 
 #else	/* X86_UV */
diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h
index 54d52ff..20e738a 100644
--- a/arch/x86/include/asm/xen/interface.h
+++ b/arch/x86/include/asm/xen/interface.h
@@ -63,6 +63,7 @@ DEFINE_GUEST_HANDLE(void);
 DEFINE_GUEST_HANDLE(uint64_t);
 DEFINE_GUEST_HANDLE(uint32_t);
 DEFINE_GUEST_HANDLE(xen_pfn_t);
+DEFINE_GUEST_HANDLE(xen_ulong_t);
 #endif
 
 #ifndef HYPERVISOR_VIRT_START
@@ -144,7 +145,16 @@ struct vcpu_guest_context {
     struct cpu_user_regs user_regs;         /* User-level CPU registers     */
     struct trap_info trap_ctxt[256];        /* Virtual IDT                  */
     unsigned long ldt_base, ldt_ents;       /* LDT (linear address, # ents) */
-    unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
+    union {
+	struct {
+		/* PV: GDT (machine frames, # ents).*/
+		unsigned long gdt_frames[16], gdt_ents;
+	} pv;
+	struct {
+		/* PVH: GDTR addr and size */
+		unsigned long gdtaddr, gdtsz;
+	} pvh;
+    } u;
     unsigned long kernel_ss, kernel_sp;     /* Virtual TSS (only SS1/SP1)   */
     /* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */
     unsigned long ctrlreg[8];               /* CR0-CR7 (control registers)  */
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h
index 472b9b7..6af440d 100644
--- a/arch/x86/include/asm/xen/page.h
+++ b/arch/x86/include/asm/xen/page.h
@@ -159,6 +159,9 @@ static inline xpaddr_t machine_to_phys(xmaddr_t machine)
 static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
 {
 	unsigned long pfn = mfn_to_pfn(mfn);
+
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return mfn;
 	if (get_phys_to_machine(pfn) != mfn)
 		return -1; /* force !pfn_valid() */
 	return pfn;
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 91ce48f..34e923a 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -9,7 +9,6 @@ CPPFLAGS_vmlinux.lds += -U$(UTS_MACHINE)
 ifdef CONFIG_FUNCTION_TRACER
 # Do not profile debug and lowlevel utilities
 CFLAGS_REMOVE_tsc.o = -pg
-CFLAGS_REMOVE_rtc.o = -pg
 CFLAGS_REMOVE_paravirt-spinlocks.o = -pg
 CFLAGS_REMOVE_pvclock.o = -pg
 CFLAGS_REMOVE_kvmclock.o = -pg
@@ -62,6 +61,7 @@ obj-$(CONFIG_X86_REBOOTFIXUPS)	+= reboot_fixups_32.o
 obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
 obj-$(CONFIG_FTRACE_SYSCALLS)	+= ftrace.o
+obj-$(CONFIG_X86_TSC)		+= trace_clock.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec_$(BITS).o
 obj-$(CONFIG_KEXEC)		+= relocate_kernel_$(BITS).o crash.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump_$(BITS).o
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index e651f7a..bacf4b0 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -574,6 +574,12 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
 
 	return irq;
 }
+EXPORT_SYMBOL_GPL(acpi_register_gsi);
+
+void acpi_unregister_gsi(u32 gsi)
+{
+}
+EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
 
 void __init acpi_set_irq_model_pic(void)
 {
@@ -1700,3 +1706,9 @@ int __acpi_release_global_lock(unsigned int *lock)
 	} while (unlikely (val != old));
 	return old & 0x1;
 }
+
+void __init arch_reserve_mem_area(acpi_physical_address addr, size_t size)
+{
+	e820_add_region(addr, size, E820_ACPI);
+	update_e820();
+}
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index 11676cf..0532f5d 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -69,7 +69,7 @@ int acpi_suspend_lowlevel(void)
 
 #ifndef CONFIG_64BIT
 	header->pmode_entry = (u32)&wakeup_pmode_return;
-	header->pmode_cr3 = (u32)__pa(&initial_page_table);
+	header->pmode_cr3 = (u32)__pa_symbol(initial_page_table);
 	saved_magic = 0x12345678;
 #else /* CONFIG_64BIT */
 #ifdef CONFIG_SMP
@@ -101,6 +101,8 @@ static int __init acpi_sleep_setup(char *str)
 #endif
 		if (strncmp(str, "nonvs", 5) == 0)
 			acpi_nvs_nosave();
+		if (strncmp(str, "nonvs_s3", 8) == 0)
+			acpi_nvs_nosave_s3();
 		if (strncmp(str, "old_ordering", 12) == 0)
 			acpi_old_suspend_ordering();
 		str = strchr(str, ',');
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index b17416e..b994cc8 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -90,21 +90,6 @@ EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
  */
 DEFINE_EARLY_PER_CPU_READ_MOSTLY(int, x86_cpu_to_logical_apicid, BAD_APICID);
 
-/*
- * Knob to control our willingness to enable the local APIC.
- *
- * +1=force-enable
- */
-static int force_enable_local_apic __initdata;
-/*
- * APIC command line parameters
- */
-static int __init parse_lapic(char *arg)
-{
-	force_enable_local_apic = 1;
-	return 0;
-}
-early_param("lapic", parse_lapic);
 /* Local APIC was disabled by the BIOS and enabled by the kernel */
 static int enabled_via_apicbase;
 
@@ -133,6 +118,25 @@ static inline void imcr_apic_to_pic(void)
 }
 #endif
 
+/*
+ * Knob to control our willingness to enable the local APIC.
+ *
+ * +1=force-enable
+ */
+static int force_enable_local_apic __initdata;
+/*
+ * APIC command line parameters
+ */
+static int __init parse_lapic(char *arg)
+{
+	if (config_enabled(CONFIG_X86_32) && !arg)
+		force_enable_local_apic = 1;
+	else if (!strncmp(arg, "notscdeadline", 13))
+		setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
+	return 0;
+}
+early_param("lapic", parse_lapic);
+
 #ifdef CONFIG_X86_64
 static int apic_calibrate_pmtmr __initdata;
 static __init int setup_apicpmtimer(char *s)
@@ -315,6 +319,7 @@ int lapic_get_maxlvt(void)
 
 /* Clock divisor */
 #define APIC_DIVISOR 16
+#define TSC_DIVISOR  32
 
 /*
  * This function sets up the local APIC timer, with a timeout of
@@ -333,6 +338,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
 	lvtt_value = LOCAL_TIMER_VECTOR;
 	if (!oneshot)
 		lvtt_value |= APIC_LVT_TIMER_PERIODIC;
+	else if (boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
+		lvtt_value |= APIC_LVT_TIMER_TSCDEADLINE;
+
 	if (!lapic_is_integrated())
 		lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
 
@@ -341,6 +349,11 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
 
 	apic_write(APIC_LVTT, lvtt_value);
 
+	if (lvtt_value & APIC_LVT_TIMER_TSCDEADLINE) {
+		printk_once(KERN_DEBUG "TSC deadline timer enabled\n");
+		return;
+	}
+
 	/*
 	 * Divide PICLK by 16
 	 */
@@ -453,6 +466,16 @@ static int lapic_next_event(unsigned long delta,
 	return 0;
 }
 
+static int lapic_next_deadline(unsigned long delta,
+			       struct clock_event_device *evt)
+{
+	u64 tsc;
+
+	rdtscll(tsc);
+	wrmsrl(MSR_IA32_TSC_DEADLINE, tsc + (((u64) delta) * TSC_DIVISOR));
+	return 0;
+}
+
 /*
  * Setup the lapic timer in periodic or oneshot mode
  */
@@ -533,7 +556,15 @@ static void __cpuinit setup_APIC_timer(void)
 	memcpy(levt, &lapic_clockevent, sizeof(*levt));
 	levt->cpumask = cpumask_of(smp_processor_id());
 
-	clockevents_register_device(levt);
+	if (this_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) {
+		levt->features &= ~(CLOCK_EVT_FEAT_PERIODIC |
+				    CLOCK_EVT_FEAT_DUMMY);
+		levt->set_next_event = lapic_next_deadline;
+		clockevents_config_and_register(levt,
+						(tsc_khz / TSC_DIVISOR) * 1000,
+						0xF, ~0UL);
+	} else
+		clockevents_register_device(levt);
 }
 
 /*
@@ -661,7 +692,9 @@ static int __init calibrate_APIC_clock(void)
 	 * in the clockevent structure and return.
 	 */
 
-	if (lapic_timer_frequency) {
+	if (boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) {
+		return 0;
+	} else if (lapic_timer_frequency) {
 		apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n",
 				lapic_timer_frequency);
 		lapic_clockevent.mult = div_sc(lapic_timer_frequency/APIC_DIVISOR,
@@ -674,6 +707,9 @@ static int __init calibrate_APIC_clock(void)
 		return 0;
 	}
 
+	apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
+		    "calibrating APIC timer ...\n");
+
 	local_irq_disable();
 
 	/* Replace the global interrupt handler */
@@ -811,9 +847,6 @@ void __init setup_boot_APIC_clock(void)
 		return;
 	}
 
-	apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
-		    "calibrating APIC timer ...\n");
-
 	if (calibrate_APIC_clock()) {
 		/* No broadcast on UP ! */
 		if (num_possible_cpus() > 1)
diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c
index a65829a..ae9196f 100644
--- a/arch/x86/kernel/apic/apic_numachip.c
+++ b/arch/x86/kernel/apic/apic_numachip.c
@@ -27,6 +27,7 @@
 #include <asm/apic.h>
 #include <asm/ipi.h>
 #include <asm/apic_flat_64.h>
+#include <asm/pgtable.h>
 
 static int numachip_system __read_mostly;
 
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 1817fa9..b134f0b 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3317,8 +3317,9 @@ int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
 	int ret;
 
 	if (irq_remapping_enabled) {
-		if (!setup_hpet_msi_remapped(irq, id))
-			return -1;
+		ret = setup_hpet_msi_remapped(irq, id);
+		if (ret)
+			return ret;
 	}
 
 	ret = msi_compose_msg(NULL, irq, &msg, id);
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 1b7d165..ce71a25 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -304,7 +304,7 @@ static void __cpuinit amd_get_topology(struct cpuinfo_x86 *c)
 	int cpu = smp_processor_id();
 
 	/* get information required for multi-node processors */
-	if (cpu_has(c, X86_FEATURE_TOPOEXT)) {
+	if (cpu_has_topoext) {
 		u32 eax, ebx, ecx, edx;
 
 		cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
@@ -657,12 +657,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
 	detect_ht(c);
 #endif
 
-	if (c->extended_cpuid_level >= 0x80000006) {
-		if (cpuid_edx(0x80000006) & 0xf000)
-			num_cache_leaves = 4;
-		else
-			num_cache_leaves = 3;
-	}
+	init_amd_cacheinfo(c);
 
 	if (c->x86 >= 0xf)
 		set_cpu_cap(c, X86_FEATURE_K8);
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 7505f7b..6a6432c 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1173,15 +1173,6 @@ DEFINE_PER_CPU(struct task_struct *, fpu_owner_task);
 DEFINE_PER_CPU_ALIGNED(struct stack_canary, stack_canary);
 #endif
 
-/* Make sure %fs and %gs are initialized properly in idle threads */
-struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
-{
-	memset(regs, 0, sizeof(struct pt_regs));
-	regs->fs = __KERNEL_PERCPU;
-	regs->gs = __KERNEL_STACK_CANARY;
-
-	return regs;
-}
 #endif	/* CONFIG_X86_64 */
 
 /*
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 198e019..2249e7e 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -168,7 +168,7 @@ int __cpuinit ppro_with_ram_bug(void)
 #ifdef CONFIG_X86_F00F_BUG
 static void __cpuinit trap_init_f00f_bug(void)
 {
-	__set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO);
+	__set_fixmap(FIX_F00F_IDT, __pa_symbol(idt_table), PAGE_KERNEL_RO);
 
 	/*
 	 * Update the IDT descriptor and reload the IDT so that
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index 93c5451..fe9edec 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -538,7 +538,11 @@ __cpuinit cpuid4_cache_lookup_regs(int index,
 	unsigned		edx;
 
 	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
-		amd_cpuid4(index, &eax, &ebx, &ecx);
+		if (cpu_has_topoext)
+			cpuid_count(0x8000001d, index, &eax.full,
+				    &ebx.full, &ecx.full, &edx);
+		else
+			amd_cpuid4(index, &eax, &ebx, &ecx);
 		amd_init_l3_cache(this_leaf, index);
 	} else {
 		cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
@@ -557,21 +561,39 @@ __cpuinit cpuid4_cache_lookup_regs(int index,
 	return 0;
 }
 
-static int __cpuinit find_num_cache_leaves(void)
+static int __cpuinit find_num_cache_leaves(struct cpuinfo_x86 *c)
 {
-	unsigned int		eax, ebx, ecx, edx;
+	unsigned int		eax, ebx, ecx, edx, op;
 	union _cpuid4_leaf_eax	cache_eax;
 	int 			i = -1;
 
+	if (c->x86_vendor == X86_VENDOR_AMD)
+		op = 0x8000001d;
+	else
+		op = 4;
+
 	do {
 		++i;
-		/* Do cpuid(4) loop to find out num_cache_leaves */
-		cpuid_count(4, i, &eax, &ebx, &ecx, &edx);
+		/* Do cpuid(op) loop to find out num_cache_leaves */
+		cpuid_count(op, i, &eax, &ebx, &ecx, &edx);
 		cache_eax.full = eax;
 	} while (cache_eax.split.type != CACHE_TYPE_NULL);
 	return i;
 }
 
+void __cpuinit init_amd_cacheinfo(struct cpuinfo_x86 *c)
+{
+
+	if (cpu_has_topoext) {
+		num_cache_leaves = find_num_cache_leaves(c);
+	} else if (c->extended_cpuid_level >= 0x80000006) {
+		if (cpuid_edx(0x80000006) & 0xf000)
+			num_cache_leaves = 4;
+		else
+			num_cache_leaves = 3;
+	}
+}
+
 unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
 {
 	/* Cache sizes */
@@ -588,7 +610,7 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
 
 		if (is_initialized == 0) {
 			/* Init num_cache_leaves from boot CPU */
-			num_cache_leaves = find_num_cache_leaves();
+			num_cache_leaves = find_num_cache_leaves(c);
 			is_initialized++;
 		}
 
@@ -728,37 +750,50 @@ static DEFINE_PER_CPU(struct _cpuid4_info *, ici_cpuid4_info);
 static int __cpuinit cache_shared_amd_cpu_map_setup(unsigned int cpu, int index)
 {
 	struct _cpuid4_info *this_leaf;
-	int ret, i, sibling;
-	struct cpuinfo_x86 *c = &cpu_data(cpu);
+	int i, sibling;
 
-	ret = 0;
-	if (index == 3) {
-		ret = 1;
-		for_each_cpu(i, cpu_llc_shared_mask(cpu)) {
+	if (cpu_has_topoext) {
+		unsigned int apicid, nshared, first, last;
+
+		if (!per_cpu(ici_cpuid4_info, cpu))
+			return 0;
+
+		this_leaf = CPUID4_INFO_IDX(cpu, index);
+		nshared = this_leaf->base.eax.split.num_threads_sharing + 1;
+		apicid = cpu_data(cpu).apicid;
+		first = apicid - (apicid % nshared);
+		last = first + nshared - 1;
+
+		for_each_online_cpu(i) {
+			apicid = cpu_data(i).apicid;
+			if ((apicid < first) || (apicid > last))
+				continue;
 			if (!per_cpu(ici_cpuid4_info, i))
 				continue;
 			this_leaf = CPUID4_INFO_IDX(i, index);
-			for_each_cpu(sibling, cpu_llc_shared_mask(cpu)) {
-				if (!cpu_online(sibling))
+
+			for_each_online_cpu(sibling) {
+				apicid = cpu_data(sibling).apicid;
+				if ((apicid < first) || (apicid > last))
 					continue;
 				set_bit(sibling, this_leaf->shared_cpu_map);
 			}
 		}
-	} else if ((c->x86 == 0x15) && ((index == 1) || (index == 2))) {
-		ret = 1;
-		for_each_cpu(i, cpu_sibling_mask(cpu)) {
+	} else if (index == 3) {
+		for_each_cpu(i, cpu_llc_shared_mask(cpu)) {
 			if (!per_cpu(ici_cpuid4_info, i))
 				continue;
 			this_leaf = CPUID4_INFO_IDX(i, index);
-			for_each_cpu(sibling, cpu_sibling_mask(cpu)) {
+			for_each_cpu(sibling, cpu_llc_shared_mask(cpu)) {
 				if (!cpu_online(sibling))
 					continue;
 				set_bit(sibling, this_leaf->shared_cpu_map);
 			}
 		}
-	}
+	} else
+		return 0;
 
-	return ret;
+	return 1;
 }
 
 static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
diff --git a/arch/x86/kernel/cpu/mcheck/mce-internal.h b/arch/x86/kernel/cpu/mcheck/mce-internal.h
index 6a05c1d..5b7d4fa 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-internal.h
+++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h
@@ -24,8 +24,6 @@ struct mce_bank {
 int mce_severity(struct mce *a, int tolerant, char **msg);
 struct dentry *mce_get_debugfs_dir(void);
 
-extern int mce_ser;
-
 extern struct mce_bank *mce_banks;
 
 #ifdef CONFIG_X86_MCE_INTEL
diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c
index 1301762..beb1f16 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c
@@ -193,9 +193,9 @@ int mce_severity(struct mce *m, int tolerant, char **msg)
 			continue;
 		if ((m->mcgstatus & s->mcgmask) != s->mcgres)
 			continue;
-		if (s->ser == SER_REQUIRED && !mce_ser)
+		if (s->ser == SER_REQUIRED && !mca_cfg.ser)
 			continue;
-		if (s->ser == NO_SER && mce_ser)
+		if (s->ser == NO_SER && mca_cfg.ser)
 			continue;
 		if (s->context && ctx != s->context)
 			continue;
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 46cbf86..80dbda8 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -58,34 +58,26 @@ static DEFINE_MUTEX(mce_chrdev_read_mutex);
 #define CREATE_TRACE_POINTS
 #include <trace/events/mce.h>
 
-int mce_disabled __read_mostly;
-
 #define SPINUNIT 100	/* 100ns */
 
 atomic_t mce_entry;
 
 DEFINE_PER_CPU(unsigned, mce_exception_count);
 
-/*
- * Tolerant levels:
- *   0: always panic on uncorrected errors, log corrected errors
- *   1: panic or SIGBUS on uncorrected errors, log corrected errors
- *   2: SIGBUS or log uncorrected errors (if possible), log corrected errors
- *   3: never panic or SIGBUS, log all errors (for testing only)
- */
-static int			tolerant		__read_mostly = 1;
-static int			banks			__read_mostly;
-static int			rip_msr			__read_mostly;
-static int			mce_bootlog		__read_mostly = -1;
-static int			monarch_timeout		__read_mostly = -1;
-static int			mce_panic_timeout	__read_mostly;
-static int			mce_dont_log_ce		__read_mostly;
-int				mce_cmci_disabled	__read_mostly;
-int				mce_ignore_ce		__read_mostly;
-int				mce_ser			__read_mostly;
-int				mce_bios_cmci_threshold	__read_mostly;
-
-struct mce_bank                *mce_banks		__read_mostly;
+struct mce_bank *mce_banks __read_mostly;
+
+struct mca_config mca_cfg __read_mostly = {
+	.bootlog  = -1,
+	/*
+	 * Tolerant levels:
+	 * 0: always panic on uncorrected errors, log corrected errors
+	 * 1: panic or SIGBUS on uncorrected errors, log corrected errors
+	 * 2: SIGBUS or log uncorrected errors (if possible), log corr. errors
+	 * 3: never panic or SIGBUS, log all errors (for testing only)
+	 */
+	.tolerant = 1,
+	.monarch_timeout = -1
+};
 
 /* User mode helper program triggered by machine check event */
 static unsigned long		mce_need_notify;
@@ -302,7 +294,7 @@ static void wait_for_panic(void)
 	while (timeout-- > 0)
 		udelay(1);
 	if (panic_timeout == 0)
-		panic_timeout = mce_panic_timeout;
+		panic_timeout = mca_cfg.panic_timeout;
 	panic("Panicing machine check CPU died");
 }
 
@@ -360,7 +352,7 @@ static void mce_panic(char *msg, struct mce *final, char *exp)
 		pr_emerg(HW_ERR "Machine check: %s\n", exp);
 	if (!fake_panic) {
 		if (panic_timeout == 0)
-			panic_timeout = mce_panic_timeout;
+			panic_timeout = mca_cfg.panic_timeout;
 		panic(msg);
 	} else
 		pr_emerg(HW_ERR "Fake kernel panic: %s\n", msg);
@@ -372,7 +364,7 @@ static int msr_to_offset(u32 msr)
 {
 	unsigned bank = __this_cpu_read(injectm.bank);
 
-	if (msr == rip_msr)
+	if (msr == mca_cfg.rip_msr)
 		return offsetof(struct mce, ip);
 	if (msr == MSR_IA32_MCx_STATUS(bank))
 		return offsetof(struct mce, status);
@@ -451,8 +443,8 @@ static inline void mce_gather_info(struct mce *m, struct pt_regs *regs)
 				m->cs |= 3;
 		}
 		/* Use accurate RIP reporting if available. */
-		if (rip_msr)
-			m->ip = mce_rdmsrl(rip_msr);
+		if (mca_cfg.rip_msr)
+			m->ip = mce_rdmsrl(mca_cfg.rip_msr);
 	}
 }
 
@@ -513,7 +505,7 @@ static int mce_ring_add(unsigned long pfn)
 
 int mce_available(struct cpuinfo_x86 *c)
 {
-	if (mce_disabled)
+	if (mca_cfg.disabled)
 		return 0;
 	return cpu_has(c, X86_FEATURE_MCE) && cpu_has(c, X86_FEATURE_MCA);
 }
@@ -565,7 +557,7 @@ static void mce_read_aux(struct mce *m, int i)
 		/*
 		 * Mask the reported address by the reported granularity.
 		 */
-		if (mce_ser && (m->status & MCI_STATUS_MISCV)) {
+		if (mca_cfg.ser && (m->status & MCI_STATUS_MISCV)) {
 			u8 shift = MCI_MISC_ADDR_LSB(m->misc);
 			m->addr >>= shift;
 			m->addr <<= shift;
@@ -599,7 +591,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
 
 	mce_gather_info(&m, NULL);
 
-	for (i = 0; i < banks; i++) {
+	for (i = 0; i < mca_cfg.banks; i++) {
 		if (!mce_banks[i].ctl || !test_bit(i, *b))
 			continue;
 
@@ -620,7 +612,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
 		 * TBD do the same check for MCI_STATUS_EN here?
 		 */
 		if (!(flags & MCP_UC) &&
-		    (m.status & (mce_ser ? MCI_STATUS_S : MCI_STATUS_UC)))
+		    (m.status & (mca_cfg.ser ? MCI_STATUS_S : MCI_STATUS_UC)))
 			continue;
 
 		mce_read_aux(&m, i);
@@ -631,7 +623,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
 		 * Don't get the IP here because it's unlikely to
 		 * have anything to do with the actual error location.
 		 */
-		if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce)
+		if (!(flags & MCP_DONTLOG) && !mca_cfg.dont_log_ce)
 			mce_log(&m);
 
 		/*
@@ -658,14 +650,14 @@ static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,
 {
 	int i, ret = 0;
 
-	for (i = 0; i < banks; i++) {
+	for (i = 0; i < mca_cfg.banks; i++) {
 		m->status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i));
 		if (m->status & MCI_STATUS_VAL) {
 			__set_bit(i, validp);
 			if (quirk_no_way_out)
 				quirk_no_way_out(i, m, regs);
 		}
-		if (mce_severity(m, tolerant, msg) >= MCE_PANIC_SEVERITY)
+		if (mce_severity(m, mca_cfg.tolerant, msg) >= MCE_PANIC_SEVERITY)
 			ret = 1;
 	}
 	return ret;
@@ -696,11 +688,11 @@ static int mce_timed_out(u64 *t)
 	rmb();
 	if (atomic_read(&mce_paniced))
 		wait_for_panic();
-	if (!monarch_timeout)
+	if (!mca_cfg.monarch_timeout)
 		goto out;
 	if ((s64)*t < SPINUNIT) {
 		/* CHECKME: Make panic default for 1 too? */
-		if (tolerant < 1)
+		if (mca_cfg.tolerant < 1)
 			mce_panic("Timeout synchronizing machine check over CPUs",
 				  NULL, NULL);
 		cpu_missing = 1;
@@ -750,7 +742,8 @@ static void mce_reign(void)
 	 * Grade the severity of the errors of all the CPUs.
 	 */
 	for_each_possible_cpu(cpu) {
-		int severity = mce_severity(&per_cpu(mces_seen, cpu), tolerant,
+		int severity = mce_severity(&per_cpu(mces_seen, cpu),
+					    mca_cfg.tolerant,
 					    &nmsg);
 		if (severity > global_worst) {
 			msg = nmsg;
@@ -764,7 +757,7 @@ static void mce_reign(void)
 	 * This dumps all the mces in the log buffer and stops the
 	 * other CPUs.
 	 */
-	if (m && global_worst >= MCE_PANIC_SEVERITY && tolerant < 3)
+	if (m && global_worst >= MCE_PANIC_SEVERITY && mca_cfg.tolerant < 3)
 		mce_panic("Fatal Machine check", m, msg);
 
 	/*
@@ -777,7 +770,7 @@ static void mce_reign(void)
 	 * No machine check event found. Must be some external
 	 * source or one CPU is hung. Panic.
 	 */
-	if (global_worst <= MCE_KEEP_SEVERITY && tolerant < 3)
+	if (global_worst <= MCE_KEEP_SEVERITY && mca_cfg.tolerant < 3)
 		mce_panic("Machine check from unknown source", NULL, NULL);
 
 	/*
@@ -801,7 +794,7 @@ static int mce_start(int *no_way_out)
 {
 	int order;
 	int cpus = num_online_cpus();
-	u64 timeout = (u64)monarch_timeout * NSEC_PER_USEC;
+	u64 timeout = (u64)mca_cfg.monarch_timeout * NSEC_PER_USEC;
 
 	if (!timeout)
 		return -1;
@@ -865,7 +858,7 @@ static int mce_start(int *no_way_out)
 static int mce_end(int order)
 {
 	int ret = -1;
-	u64 timeout = (u64)monarch_timeout * NSEC_PER_USEC;
+	u64 timeout = (u64)mca_cfg.monarch_timeout * NSEC_PER_USEC;
 
 	if (!timeout)
 		goto reset;
@@ -946,7 +939,7 @@ static void mce_clear_state(unsigned long *toclear)
 {
 	int i;
 
-	for (i = 0; i < banks; i++) {
+	for (i = 0; i < mca_cfg.banks; i++) {
 		if (test_bit(i, toclear))
 			mce_wrmsrl(MSR_IA32_MCx_STATUS(i), 0);
 	}
@@ -1011,6 +1004,7 @@ static void mce_clear_info(struct mce_info *mi)
  */
 void do_machine_check(struct pt_regs *regs, long error_code)
 {
+	struct mca_config *cfg = &mca_cfg;
 	struct mce m, *final;
 	int i;
 	int worst = 0;
@@ -1022,7 +1016,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
 	int order;
 	/*
 	 * If no_way_out gets set, there is no safe way to recover from this
-	 * MCE.  If tolerant is cranked up, we'll try anyway.
+	 * MCE.  If mca_cfg.tolerant is cranked up, we'll try anyway.
 	 */
 	int no_way_out = 0;
 	/*
@@ -1038,7 +1032,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
 
 	this_cpu_inc(mce_exception_count);
 
-	if (!banks)
+	if (!cfg->banks)
 		goto out;
 
 	mce_gather_info(&m, regs);
@@ -1065,7 +1059,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
 	 * because the first one to see it will clear it.
 	 */
 	order = mce_start(&no_way_out);
-	for (i = 0; i < banks; i++) {
+	for (i = 0; i < cfg->banks; i++) {
 		__clear_bit(i, toclear);
 		if (!test_bit(i, valid_banks))
 			continue;
@@ -1084,7 +1078,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
 		 * Non uncorrected or non signaled errors are handled by
 		 * machine_check_poll. Leave them alone, unless this panics.
 		 */
-		if (!(m.status & (mce_ser ? MCI_STATUS_S : MCI_STATUS_UC)) &&
+		if (!(m.status & (cfg->ser ? MCI_STATUS_S : MCI_STATUS_UC)) &&
 			!no_way_out)
 			continue;
 
@@ -1093,7 +1087,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
 		 */
 		add_taint(TAINT_MACHINE_CHECK);
 
-		severity = mce_severity(&m, tolerant, NULL);
+		severity = mce_severity(&m, cfg->tolerant, NULL);
 
 		/*
 		 * When machine check was for corrected handler don't touch,
@@ -1117,7 +1111,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
 		 * When the ring overflows we just ignore the AO error.
 		 * RED-PEN add some logging mechanism when
 		 * usable_address or mce_add_ring fails.
-		 * RED-PEN don't ignore overflow for tolerant == 0
+		 * RED-PEN don't ignore overflow for mca_cfg.tolerant == 0
 		 */
 		if (severity == MCE_AO_SEVERITY && mce_usable_address(&m))
 			mce_ring_add(m.addr >> PAGE_SHIFT);
@@ -1149,7 +1143,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
 	 * issues we try to recover, or limit damage to the current
 	 * process.
 	 */
-	if (tolerant < 3) {
+	if (cfg->tolerant < 3) {
 		if (no_way_out)
 			mce_panic("Fatal machine check on current CPU", &m, msg);
 		if (worst == MCE_AR_SEVERITY) {
@@ -1377,11 +1371,13 @@ EXPORT_SYMBOL_GPL(mce_notify_irq);
 static int __cpuinit __mcheck_cpu_mce_banks_init(void)
 {
 	int i;
+	u8 num_banks = mca_cfg.banks;
 
-	mce_banks = kzalloc(banks * sizeof(struct mce_bank), GFP_KERNEL);
+	mce_banks = kzalloc(num_banks * sizeof(struct mce_bank), GFP_KERNEL);
 	if (!mce_banks)
 		return -ENOMEM;
-	for (i = 0; i < banks; i++) {
+
+	for (i = 0; i < num_banks; i++) {
 		struct mce_bank *b = &mce_banks[i];
 
 		b->ctl = -1ULL;
@@ -1401,7 +1397,7 @@ static int __cpuinit __mcheck_cpu_cap_init(void)
 	rdmsrl(MSR_IA32_MCG_CAP, cap);
 
 	b = cap & MCG_BANKCNT_MASK;
-	if (!banks)
+	if (!mca_cfg.banks)
 		pr_info("CPU supports %d MCE banks\n", b);
 
 	if (b > MAX_NR_BANKS) {
@@ -1411,8 +1407,9 @@ static int __cpuinit __mcheck_cpu_cap_init(void)
 	}
 
 	/* Don't support asymmetric configurations today */
-	WARN_ON(banks != 0 && b != banks);
-	banks = b;
+	WARN_ON(mca_cfg.banks != 0 && b != mca_cfg.banks);
+	mca_cfg.banks = b;
+
 	if (!mce_banks) {
 		int err = __mcheck_cpu_mce_banks_init();
 
@@ -1422,25 +1419,29 @@ static int __cpuinit __mcheck_cpu_cap_init(void)
 
 	/* Use accurate RIP reporting if available. */
 	if ((cap & MCG_EXT_P) && MCG_EXT_CNT(cap) >= 9)
-		rip_msr = MSR_IA32_MCG_EIP;
+		mca_cfg.rip_msr = MSR_IA32_MCG_EIP;
 
 	if (cap & MCG_SER_P)
-		mce_ser = 1;
+		mca_cfg.ser = true;
 
 	return 0;
 }
 
 static void __mcheck_cpu_init_generic(void)
 {
+	enum mcp_flags m_fl = 0;
 	mce_banks_t all_banks;
 	u64 cap;
 	int i;
 
+	if (!mca_cfg.bootlog)
+		m_fl = MCP_DONTLOG;
+
 	/*
 	 * Log the machine checks left over from the previous reset.
 	 */
 	bitmap_fill(all_banks, MAX_NR_BANKS);
-	machine_check_poll(MCP_UC|(!mce_bootlog ? MCP_DONTLOG : 0), &all_banks);
+	machine_check_poll(MCP_UC | m_fl, &all_banks);
 
 	set_in_cr4(X86_CR4_MCE);
 
@@ -1448,7 +1449,7 @@ static void __mcheck_cpu_init_generic(void)
 	if (cap & MCG_CTL_P)
 		wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
 
-	for (i = 0; i < banks; i++) {
+	for (i = 0; i < mca_cfg.banks; i++) {
 		struct mce_bank *b = &mce_banks[i];
 
 		if (!b->init)
@@ -1489,6 +1490,8 @@ static void quirk_sandybridge_ifu(int bank, struct mce *m, struct pt_regs *regs)
 /* Add per CPU specific workarounds here */
 static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
 {
+	struct mca_config *cfg = &mca_cfg;
+
 	if (c->x86_vendor == X86_VENDOR_UNKNOWN) {
 		pr_info("unknown CPU type - not enabling MCE support\n");
 		return -EOPNOTSUPP;
@@ -1496,7 +1499,7 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
 
 	/* This should be disabled by the BIOS, but isn't always */
 	if (c->x86_vendor == X86_VENDOR_AMD) {
-		if (c->x86 == 15 && banks > 4) {
+		if (c->x86 == 15 && cfg->banks > 4) {
 			/*
 			 * disable GART TBL walk error reporting, which
 			 * trips off incorrectly with the IOMMU & 3ware
@@ -1504,18 +1507,18 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
 			 */
 			clear_bit(10, (unsigned long *)&mce_banks[4].ctl);
 		}
-		if (c->x86 <= 17 && mce_bootlog < 0) {
+		if (c->x86 <= 17 && cfg->bootlog < 0) {
 			/*
 			 * Lots of broken BIOS around that don't clear them
 			 * by default and leave crap in there. Don't log:
 			 */
-			mce_bootlog = 0;
+			cfg->bootlog = 0;
 		}
 		/*
 		 * Various K7s with broken bank 0 around. Always disable
 		 * by default.
 		 */
-		 if (c->x86 == 6 && banks > 0)
+		 if (c->x86 == 6 && cfg->banks > 0)
 			mce_banks[0].ctl = 0;
 
 		 /*
@@ -1566,7 +1569,7 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
 		 * valid event later, merely don't write CTL0.
 		 */
 
-		if (c->x86 == 6 && c->x86_model < 0x1A && banks > 0)
+		if (c->x86 == 6 && c->x86_model < 0x1A && cfg->banks > 0)
 			mce_banks[0].init = 0;
 
 		/*
@@ -1574,23 +1577,23 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
 		 * synchronization with a one second timeout.
 		 */
 		if ((c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xe)) &&
-			monarch_timeout < 0)
-			monarch_timeout = USEC_PER_SEC;
+			cfg->monarch_timeout < 0)
+			cfg->monarch_timeout = USEC_PER_SEC;
 
 		/*
 		 * There are also broken BIOSes on some Pentium M and
 		 * earlier systems:
 		 */
-		if (c->x86 == 6 && c->x86_model <= 13 && mce_bootlog < 0)
-			mce_bootlog = 0;
+		if (c->x86 == 6 && c->x86_model <= 13 && cfg->bootlog < 0)
+			cfg->bootlog = 0;
 
 		if (c->x86 == 6 && c->x86_model == 45)
 			quirk_no_way_out = quirk_sandybridge_ifu;
 	}
-	if (monarch_timeout < 0)
-		monarch_timeout = 0;
-	if (mce_bootlog != 0)
-		mce_panic_timeout = 30;
+	if (cfg->monarch_timeout < 0)
+		cfg->monarch_timeout = 0;
+	if (cfg->bootlog != 0)
+		cfg->panic_timeout = 30;
 
 	return 0;
 }
@@ -1635,7 +1638,7 @@ static void mce_start_timer(unsigned int cpu, struct timer_list *t)
 
 	__this_cpu_write(mce_next_interval, iv);
 
-	if (mce_ignore_ce || !iv)
+	if (mca_cfg.ignore_ce || !iv)
 		return;
 
 	t->expires = round_jiffies(jiffies + iv);
@@ -1668,7 +1671,7 @@ void (*machine_check_vector)(struct pt_regs *, long error_code) =
  */
 void __cpuinit mcheck_cpu_init(struct cpuinfo_x86 *c)
 {
-	if (mce_disabled)
+	if (mca_cfg.disabled)
 		return;
 
 	if (__mcheck_cpu_ancient_init(c))
@@ -1678,7 +1681,7 @@ void __cpuinit mcheck_cpu_init(struct cpuinfo_x86 *c)
 		return;
 
 	if (__mcheck_cpu_cap_init() < 0 || __mcheck_cpu_apply_quirks(c) < 0) {
-		mce_disabled = 1;
+		mca_cfg.disabled = true;
 		return;
 	}
 
@@ -1951,6 +1954,8 @@ static struct miscdevice mce_chrdev_device = {
  */
 static int __init mcheck_enable(char *str)
 {
+	struct mca_config *cfg = &mca_cfg;
+
 	if (*str == 0) {
 		enable_p5_mce();
 		return 1;
@@ -1958,22 +1963,22 @@ static int __init mcheck_enable(char *str)
 	if (*str == '=')
 		str++;
 	if (!strcmp(str, "off"))
-		mce_disabled = 1;
+		cfg->disabled = true;
 	else if (!strcmp(str, "no_cmci"))
-		mce_cmci_disabled = 1;
+		cfg->cmci_disabled = true;
 	else if (!strcmp(str, "dont_log_ce"))
-		mce_dont_log_ce = 1;
+		cfg->dont_log_ce = true;
 	else if (!strcmp(str, "ignore_ce"))
-		mce_ignore_ce = 1;
+		cfg->ignore_ce = true;
 	else if (!strcmp(str, "bootlog") || !strcmp(str, "nobootlog"))
-		mce_bootlog = (str[0] == 'b');
+		cfg->bootlog = (str[0] == 'b');
 	else if (!strcmp(str, "bios_cmci_threshold"))
-		mce_bios_cmci_threshold = 1;
+		cfg->bios_cmci_threshold = true;
 	else if (isdigit(str[0])) {
-		get_option(&str, &tolerant);
+		get_option(&str, &(cfg->tolerant));
 		if (*str == ',') {
 			++str;
-			get_option(&str, &monarch_timeout);
+			get_option(&str, &(cfg->monarch_timeout));
 		}
 	} else {
 		pr_info("mce argument %s ignored. Please use /sys\n", str);
@@ -2002,7 +2007,7 @@ static int mce_disable_error_reporting(void)
 {
 	int i;
 
-	for (i = 0; i < banks; i++) {
+	for (i = 0; i < mca_cfg.banks; i++) {
 		struct mce_bank *b = &mce_banks[i];
 
 		if (b->init)
@@ -2142,15 +2147,15 @@ static ssize_t set_ignore_ce(struct device *s,
 	if (strict_strtoull(buf, 0, &new) < 0)
 		return -EINVAL;
 
-	if (mce_ignore_ce ^ !!new) {
+	if (mca_cfg.ignore_ce ^ !!new) {
 		if (new) {
 			/* disable ce features */
 			mce_timer_delete_all();
 			on_each_cpu(mce_disable_cmci, NULL, 1);
-			mce_ignore_ce = 1;
+			mca_cfg.ignore_ce = true;
 		} else {
 			/* enable ce features */
-			mce_ignore_ce = 0;
+			mca_cfg.ignore_ce = false;
 			on_each_cpu(mce_enable_ce, (void *)1, 1);
 		}
 	}
@@ -2166,14 +2171,14 @@ static ssize_t set_cmci_disabled(struct device *s,
 	if (strict_strtoull(buf, 0, &new) < 0)
 		return -EINVAL;
 
-	if (mce_cmci_disabled ^ !!new) {
+	if (mca_cfg.cmci_disabled ^ !!new) {
 		if (new) {
 			/* disable cmci */
 			on_each_cpu(mce_disable_cmci, NULL, 1);
-			mce_cmci_disabled = 1;
+			mca_cfg.cmci_disabled = true;
 		} else {
 			/* enable cmci */
-			mce_cmci_disabled = 0;
+			mca_cfg.cmci_disabled = false;
 			on_each_cpu(mce_enable_ce, NULL, 1);
 		}
 	}
@@ -2190,9 +2195,9 @@ static ssize_t store_int_with_restart(struct device *s,
 }
 
 static DEVICE_ATTR(trigger, 0644, show_trigger, set_trigger);
-static DEVICE_INT_ATTR(tolerant, 0644, tolerant);
-static DEVICE_INT_ATTR(monarch_timeout, 0644, monarch_timeout);
-static DEVICE_INT_ATTR(dont_log_ce, 0644, mce_dont_log_ce);
+static DEVICE_INT_ATTR(tolerant, 0644, mca_cfg.tolerant);
+static DEVICE_INT_ATTR(monarch_timeout, 0644, mca_cfg.monarch_timeout);
+static DEVICE_BOOL_ATTR(dont_log_ce, 0644, mca_cfg.dont_log_ce);
 
 static struct dev_ext_attribute dev_attr_check_interval = {
 	__ATTR(check_interval, 0644, device_show_int, store_int_with_restart),
@@ -2200,13 +2205,13 @@ static struct dev_ext_attribute dev_attr_check_interval = {
 };
 
 static struct dev_ext_attribute dev_attr_ignore_ce = {
-	__ATTR(ignore_ce, 0644, device_show_int, set_ignore_ce),
-	&mce_ignore_ce
+	__ATTR(ignore_ce, 0644, device_show_bool, set_ignore_ce),
+	&mca_cfg.ignore_ce
 };
 
 static struct dev_ext_attribute dev_attr_cmci_disabled = {
-	__ATTR(cmci_disabled, 0644, device_show_int, set_cmci_disabled),
-	&mce_cmci_disabled
+	__ATTR(cmci_disabled, 0644, device_show_bool, set_cmci_disabled),
+	&mca_cfg.cmci_disabled
 };
 
 static struct device_attribute *mce_device_attrs[] = {
@@ -2253,7 +2258,7 @@ static __cpuinit int mce_device_create(unsigned int cpu)
 		if (err)
 			goto error;
 	}
-	for (j = 0; j < banks; j++) {
+	for (j = 0; j < mca_cfg.banks; j++) {
 		err = device_create_file(dev, &mce_banks[j].attr);
 		if (err)
 			goto error2;
@@ -2285,7 +2290,7 @@ static __cpuinit void mce_device_remove(unsigned int cpu)
 	for (i = 0; mce_device_attrs[i]; i++)
 		device_remove_file(dev, mce_device_attrs[i]);
 
-	for (i = 0; i < banks; i++)
+	for (i = 0; i < mca_cfg.banks; i++)
 		device_remove_file(dev, &mce_banks[i].attr);
 
 	device_unregister(dev);
@@ -2304,7 +2309,7 @@ static void __cpuinit mce_disable_cpu(void *h)
 
 	if (!(action & CPU_TASKS_FROZEN))
 		cmci_clear();
-	for (i = 0; i < banks; i++) {
+	for (i = 0; i < mca_cfg.banks; i++) {
 		struct mce_bank *b = &mce_banks[i];
 
 		if (b->init)
@@ -2322,7 +2327,7 @@ static void __cpuinit mce_reenable_cpu(void *h)
 
 	if (!(action & CPU_TASKS_FROZEN))
 		cmci_reenable();
-	for (i = 0; i < banks; i++) {
+	for (i = 0; i < mca_cfg.banks; i++) {
 		struct mce_bank *b = &mce_banks[i];
 
 		if (b->init)
@@ -2375,7 +2380,7 @@ static __init void mce_init_banks(void)
 {
 	int i;
 
-	for (i = 0; i < banks; i++) {
+	for (i = 0; i < mca_cfg.banks; i++) {
 		struct mce_bank *b = &mce_banks[i];
 		struct device_attribute *a = &b->attr;
 
@@ -2426,7 +2431,7 @@ device_initcall_sync(mcheck_init_device);
  */
 static int __init mcheck_disable(char *str)
 {
-	mce_disabled = 1;
+	mca_cfg.disabled = true;
 	return 1;
 }
 __setup("nomce", mcheck_disable);
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
index 4f9a3cb..402c454 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -53,7 +53,7 @@ static int cmci_supported(int *banks)
 {
 	u64 cap;
 
-	if (mce_cmci_disabled || mce_ignore_ce)
+	if (mca_cfg.cmci_disabled || mca_cfg.ignore_ce)
 		return 0;
 
 	/*
@@ -200,7 +200,7 @@ static void cmci_discover(int banks)
 			continue;
 		}
 
-		if (!mce_bios_cmci_threshold) {
+		if (!mca_cfg.bios_cmci_threshold) {
 			val &= ~MCI_CTL2_CMCI_THRESHOLD_MASK;
 			val |= CMCI_THRESHOLD;
 		} else if (!(val & MCI_CTL2_CMCI_THRESHOLD_MASK)) {
@@ -227,7 +227,7 @@ static void cmci_discover(int banks)
 			 * set the thresholds properly or does not work with
 			 * this boot option. Note down now and report later.
 			 */
-			if (mce_bios_cmci_threshold && bios_zero_thresh &&
+			if (mca_cfg.bios_cmci_threshold && bios_zero_thresh &&
 					(val & MCI_CTL2_CMCI_THRESHOLD_MASK))
 				bios_wrong_thresh = 1;
 		} else {
@@ -235,7 +235,7 @@ static void cmci_discover(int banks)
 		}
 	}
 	raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
-	if (mce_bios_cmci_threshold && bios_wrong_thresh) {
+	if (mca_cfg.bios_cmci_threshold && bios_wrong_thresh) {
 		pr_info_once(
 			"bios_cmci_threshold: Some banks do not have valid thresholds set\n");
 		pr_info_once(
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 4a3374e..4428fd1 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1316,6 +1316,121 @@ static struct attribute_group x86_pmu_format_group = {
 	.attrs = NULL,
 };
 
+struct perf_pmu_events_attr {
+	struct device_attribute attr;
+	u64 id;
+};
+
+/*
+ * Remove all undefined events (x86_pmu.event_map(id) == 0)
+ * out of events_attr attributes.
+ */
+static void __init filter_events(struct attribute **attrs)
+{
+	int i, j;
+
+	for (i = 0; attrs[i]; i++) {
+		if (x86_pmu.event_map(i))
+			continue;
+
+		for (j = i; attrs[j]; j++)
+			attrs[j] = attrs[j + 1];
+
+		/* Check the shifted attr. */
+		i--;
+	}
+}
+
+static ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr,
+			  char *page)
+{
+	struct perf_pmu_events_attr *pmu_attr = \
+		container_of(attr, struct perf_pmu_events_attr, attr);
+
+	u64 config = x86_pmu.event_map(pmu_attr->id);
+	return x86_pmu.events_sysfs_show(page, config);
+}
+
+#define EVENT_VAR(_id)  event_attr_##_id
+#define EVENT_PTR(_id) &event_attr_##_id.attr.attr
+
+#define EVENT_ATTR(_name, _id)					\
+static struct perf_pmu_events_attr EVENT_VAR(_id) = {		\
+	.attr = __ATTR(_name, 0444, events_sysfs_show, NULL),	\
+	.id   =  PERF_COUNT_HW_##_id,				\
+};
+
+EVENT_ATTR(cpu-cycles,			CPU_CYCLES		);
+EVENT_ATTR(instructions,		INSTRUCTIONS		);
+EVENT_ATTR(cache-references,		CACHE_REFERENCES	);
+EVENT_ATTR(cache-misses, 		CACHE_MISSES		);
+EVENT_ATTR(branch-instructions,		BRANCH_INSTRUCTIONS	);
+EVENT_ATTR(branch-misses,		BRANCH_MISSES		);
+EVENT_ATTR(bus-cycles,			BUS_CYCLES		);
+EVENT_ATTR(stalled-cycles-frontend,	STALLED_CYCLES_FRONTEND	);
+EVENT_ATTR(stalled-cycles-backend,	STALLED_CYCLES_BACKEND	);
+EVENT_ATTR(ref-cycles,			REF_CPU_CYCLES		);
+
+static struct attribute *empty_attrs;
+
+static struct attribute *events_attr[] = {
+	EVENT_PTR(CPU_CYCLES),
+	EVENT_PTR(INSTRUCTIONS),
+	EVENT_PTR(CACHE_REFERENCES),
+	EVENT_PTR(CACHE_MISSES),
+	EVENT_PTR(BRANCH_INSTRUCTIONS),
+	EVENT_PTR(BRANCH_MISSES),
+	EVENT_PTR(BUS_CYCLES),
+	EVENT_PTR(STALLED_CYCLES_FRONTEND),
+	EVENT_PTR(STALLED_CYCLES_BACKEND),
+	EVENT_PTR(REF_CPU_CYCLES),
+	NULL,
+};
+
+static struct attribute_group x86_pmu_events_group = {
+	.name = "events",
+	.attrs = events_attr,
+};
+
+ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event)
+{
+	u64 umask  = (config & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
+	u64 cmask  = (config & ARCH_PERFMON_EVENTSEL_CMASK) >> 24;
+	bool edge  = (config & ARCH_PERFMON_EVENTSEL_EDGE);
+	bool pc    = (config & ARCH_PERFMON_EVENTSEL_PIN_CONTROL);
+	bool any   = (config & ARCH_PERFMON_EVENTSEL_ANY);
+	bool inv   = (config & ARCH_PERFMON_EVENTSEL_INV);
+	ssize_t ret;
+
+	/*
+	* We have whole page size to spend and just little data
+	* to write, so we can safely use sprintf.
+	*/
+	ret = sprintf(page, "event=0x%02llx", event);
+
+	if (umask)
+		ret += sprintf(page + ret, ",umask=0x%02llx", umask);
+
+	if (edge)
+		ret += sprintf(page + ret, ",edge");
+
+	if (pc)
+		ret += sprintf(page + ret, ",pc");
+
+	if (any)
+		ret += sprintf(page + ret, ",any");
+
+	if (inv)
+		ret += sprintf(page + ret, ",inv");
+
+	if (cmask)
+		ret += sprintf(page + ret, ",cmask=0x%02llx", cmask);
+
+	ret += sprintf(page + ret, "\n");
+
+	return ret;
+}
+
 static int __init init_hw_perf_events(void)
 {
 	struct x86_pmu_quirk *quirk;
@@ -1362,6 +1477,11 @@ static int __init init_hw_perf_events(void)
 	x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
 	x86_pmu_format_group.attrs = x86_pmu.format_attrs;
 
+	if (!x86_pmu.events_sysfs_show)
+		x86_pmu_events_group.attrs = &empty_attrs;
+	else
+		filter_events(x86_pmu_events_group.attrs);
+
 	pr_info("... version:                %d\n",     x86_pmu.version);
 	pr_info("... bit width:              %d\n",     x86_pmu.cntval_bits);
 	pr_info("... generic registers:      %d\n",     x86_pmu.num_counters);
@@ -1651,6 +1771,7 @@ static struct attribute_group x86_pmu_attr_group = {
 static const struct attribute_group *x86_pmu_attr_groups[] = {
 	&x86_pmu_attr_group,
 	&x86_pmu_format_group,
+	&x86_pmu_events_group,
 	NULL,
 };
 
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 271d257..115c1ea 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -354,6 +354,8 @@ struct x86_pmu {
 	int		attr_rdpmc;
 	struct attribute **format_attrs;
 
+	ssize_t		(*events_sysfs_show)(char *page, u64 config);
+
 	/*
 	 * CPU Hotplug hooks
 	 */
@@ -536,6 +538,9 @@ static inline void set_linear_ip(struct pt_regs *regs, unsigned long ip)
 	regs->ip = ip;
 }
 
+ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event);
+ssize_t intel_event_sysfs_show(char *page, u64 config);
+
 #ifdef CONFIG_CPU_SUP_AMD
 
 int amd_pmu_init(void);
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
index 4528ae7..c93bc4e 100644
--- a/arch/x86/kernel/cpu/perf_event_amd.c
+++ b/arch/x86/kernel/cpu/perf_event_amd.c
@@ -568,6 +568,14 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *ev
 	}
 }
 
+static ssize_t amd_event_sysfs_show(char *page, u64 config)
+{
+	u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT) |
+		    (config & AMD64_EVENTSEL_EVENT) >> 24;
+
+	return x86_event_sysfs_show(page, config, event);
+}
+
 static __initconst const struct x86_pmu amd_pmu = {
 	.name			= "AMD",
 	.handle_irq		= x86_pmu_handle_irq,
@@ -591,6 +599,7 @@ static __initconst const struct x86_pmu amd_pmu = {
 	.put_event_constraints	= amd_put_event_constraints,
 
 	.format_attrs		= amd_format_attr,
+	.events_sysfs_show	= amd_event_sysfs_show,
 
 	.cpu_prepare		= amd_pmu_cpu_prepare,
 	.cpu_starting		= amd_pmu_cpu_starting,
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 324bb52..93b9e11 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -1603,6 +1603,13 @@ static struct attribute *intel_arch_formats_attr[] = {
 	NULL,
 };
 
+ssize_t intel_event_sysfs_show(char *page, u64 config)
+{
+	u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT);
+
+	return x86_event_sysfs_show(page, config, event);
+}
+
 static __initconst const struct x86_pmu core_pmu = {
 	.name			= "core",
 	.handle_irq		= x86_pmu_handle_irq,
@@ -1628,6 +1635,7 @@ static __initconst const struct x86_pmu core_pmu = {
 	.event_constraints	= intel_core_event_constraints,
 	.guest_get_msrs		= core_guest_get_msrs,
 	.format_attrs		= intel_arch_formats_attr,
+	.events_sysfs_show	= intel_event_sysfs_show,
 };
 
 struct intel_shared_regs *allocate_shared_regs(int cpu)
@@ -1766,6 +1774,7 @@ static __initconst const struct x86_pmu intel_pmu = {
 	.pebs_aliases		= intel_pebs_aliases_core2,
 
 	.format_attrs		= intel_arch3_formats_attr,
+	.events_sysfs_show	= intel_event_sysfs_show,
 
 	.cpu_prepare		= intel_pmu_cpu_prepare,
 	.cpu_starting		= intel_pmu_cpu_starting,
diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c
index 7d0270b..f2af39f 100644
--- a/arch/x86/kernel/cpu/perf_event_p6.c
+++ b/arch/x86/kernel/cpu/perf_event_p6.c
@@ -227,6 +227,8 @@ static __initconst const struct x86_pmu p6_pmu = {
 	.event_constraints	= p6_event_constraints,
 
 	.format_attrs		= intel_p6_formats_attr,
+	.events_sysfs_show	= intel_event_sysfs_show,
+
 };
 
 __init int p6_pmu_init(void)
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index df06ade..7578c01 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -47,6 +47,7 @@ unsigned long pci_mem_start = 0xaeedbabe;
 #ifdef CONFIG_PCI
 EXPORT_SYMBOL(pci_mem_start);
 #endif
+static u64 mem_limit = ~0ULL;
 
 /*
  * This function checks if any part of the range <start,end> is mapped
@@ -108,7 +109,7 @@ int __init e820_all_mapped(u64 start, u64 end, unsigned type)
  * Add a memory region to the kernel e820 map.
  */
 static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
-					 int type)
+					 int type, bool limited)
 {
 	int x = e820x->nr_map;
 
@@ -119,6 +120,22 @@ static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
 		return;
 	}
 
+	if (limited) {
+		if (start >= mem_limit) {
+			printk(KERN_ERR "e820: ignoring [mem %#010llx-%#010llx]\n",
+			       (unsigned long long)start,
+			       (unsigned long long)(start + size - 1));
+			return;
+		}
+
+		if (mem_limit - start < size) {
+			printk(KERN_ERR "e820: ignoring [mem %#010llx-%#010llx]\n",
+			       (unsigned long long)mem_limit,
+			       (unsigned long long)(start + size - 1));
+			size = mem_limit - start;
+		}
+	}
+
 	e820x->map[x].addr = start;
 	e820x->map[x].size = size;
 	e820x->map[x].type = type;
@@ -127,7 +144,37 @@ static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
 
 void __init e820_add_region(u64 start, u64 size, int type)
 {
-	__e820_add_region(&e820, start, size, type);
+	__e820_add_region(&e820, start, size, type, false);
+}
+
+/*
+ * do_add_efi_memmap() calls this function().
+ *
+ * Note: BOOT_SERVICES_{CODE,DATA} regions on some efi machines are marked
+ * as E820_RAM, and they are needed to be mapped. Please use e820_add_region()
+ * to add BOOT_SERVICES_{CODE,DATA} regions.
+ */
+void __init e820_add_limit_region(u64 start, u64 size, int type)
+{
+	/*
+	 * efi_init() is called after finish_e820_parsing(), so we should
+	 * check whether [start, start + size) contains address above
+	 * mem_limit if the type is E820_RAM.
+	 */
+	__e820_add_region(&e820, start, size, type, type == E820_RAM);
+}
+
+void __init e820_adjust_region(u64 *start, u64 *size)
+{
+	if (*start >= mem_limit) {
+		*size = 0;
+		return;
+	}
+
+	if (mem_limit - *start < *size)
+		*size = mem_limit - *start;
+
+	return;
 }
 
 static void __init e820_print_type(u32 type)
@@ -455,8 +502,9 @@ static u64 __init __e820_update_range(struct e820map *e820x, u64 start,
 
 		/* new range is totally covered? */
 		if (ei->addr < start && ei_end > end) {
-			__e820_add_region(e820x, start, size, new_type);
-			__e820_add_region(e820x, end, ei_end - end, ei->type);
+			__e820_add_region(e820x, start, size, new_type, false);
+			__e820_add_region(e820x, end, ei_end - end, ei->type,
+					  false);
 			ei->size = start - ei->addr;
 			real_updated_size += size;
 			continue;
@@ -469,7 +517,7 @@ static u64 __init __e820_update_range(struct e820map *e820x, u64 start,
 			continue;
 
 		__e820_add_region(e820x, final_start, final_end - final_start,
-				  new_type);
+				  new_type, false);
 
 		real_updated_size += final_end - final_start;
 
@@ -809,7 +857,7 @@ static int userdef __initdata;
 /* "mem=nopentium" disables the 4MB page tables. */
 static int __init parse_memopt(char *p)
 {
-	u64 mem_size;
+	char *oldp;
 
 	if (!p)
 		return -EINVAL;
@@ -825,11 +873,11 @@ static int __init parse_memopt(char *p)
 	}
 
 	userdef = 1;
-	mem_size = memparse(p, &p);
+	oldp = p;
+	mem_limit = memparse(p, &p);
 	/* don't remove all of memory when handling "mem={invalid}" param */
-	if (mem_size == 0)
+	if (mem_limit == 0 || p == oldp)
 		return -EINVAL;
-	e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
 
 	return 0;
 }
@@ -881,6 +929,12 @@ early_param("memmap", parse_memmap_opt);
 
 void __init finish_e820_parsing(void)
 {
+	if (mem_limit != ~0ULL) {
+		userdef = 1;
+		e820_remove_range(mem_limit, ULLONG_MAX - mem_limit,
+				  E820_RAM, 1);
+	}
+
 	if (userdef) {
 		u32 nr = e820.nr_map;
 
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 88b725a..c763116 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -739,30 +739,12 @@ ENTRY(ptregs_##name) ; \
 ENDPROC(ptregs_##name)
 
 PTREGSCALL1(iopl)
-PTREGSCALL0(fork)
-PTREGSCALL0(vfork)
 PTREGSCALL2(sigaltstack)
 PTREGSCALL0(sigreturn)
 PTREGSCALL0(rt_sigreturn)
 PTREGSCALL2(vm86)
 PTREGSCALL1(vm86old)
 
-/* Clone is an oddball.  The 4th arg is in %edi */
-ENTRY(ptregs_clone)
-	CFI_STARTPROC
-	leal 4(%esp),%eax
-	pushl_cfi %eax
-	pushl_cfi PT_EDI(%eax)
-	movl PT_EDX(%eax),%ecx
-	movl PT_ECX(%eax),%edx
-	movl PT_EBX(%eax),%eax
-	call sys_clone
-	addl $8,%esp
-	CFI_ADJUST_CFA_OFFSET -8
-	ret
-	CFI_ENDPROC
-ENDPROC(ptregs_clone)
-
 .macro FIXUP_ESPFIX_STACK
 /*
  * Switch back for ESPFIX stack to the normal zerobased stack
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 1328fe4..70641af 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -56,7 +56,7 @@
 #include <asm/ftrace.h>
 #include <asm/percpu.h>
 #include <asm/asm.h>
-#include <asm/rcu.h>
+#include <asm/context_tracking.h>
 #include <asm/smap.h>
 #include <linux/err.h>
 
@@ -845,9 +845,25 @@ ENTRY(\label)
 END(\label)
 	.endm
 
-	PTREGSCALL stub_clone, sys_clone, %r8
-	PTREGSCALL stub_fork, sys_fork, %rdi
-	PTREGSCALL stub_vfork, sys_vfork, %rdi
+	.macro FORK_LIKE func
+ENTRY(stub_\func)
+	CFI_STARTPROC
+	popq	%r11			/* save return address */
+	PARTIAL_FRAME 0
+	SAVE_REST
+	pushq	%r11			/* put it back on stack */
+	FIXUP_TOP_OF_STACK %r11, 8
+	DEFAULT_FRAME 0 8		/* offset 8: return address */
+	call sys_\func
+	RESTORE_TOP_OF_STACK %r11, 8
+	ret $REST_SKIP		/* pop extended registers */
+	CFI_ENDPROC
+END(stub_\func)
+	.endm
+
+	FORK_LIKE  clone
+	FORK_LIKE  fork
+	FORK_LIKE  vfork
 	PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
 	PTREGSCALL stub_iopl, sys_iopl, %rsi
 
@@ -1699,9 +1715,10 @@ nested_nmi:
 
 1:
 	/* Set up the interrupted NMIs stack to jump to repeat_nmi */
-	leaq -6*8(%rsp), %rdx
+	leaq -1*8(%rsp), %rdx
 	movq %rdx, %rsp
-	CFI_ADJUST_CFA_OFFSET 6*8
+	CFI_ADJUST_CFA_OFFSET 1*8
+	leaq -10*8(%rsp), %rdx
 	pushq_cfi $__KERNEL_DS
 	pushq_cfi %rdx
 	pushfq_cfi
@@ -1709,8 +1726,8 @@ nested_nmi:
 	pushq_cfi $repeat_nmi
 
 	/* Put stack back */
-	addq $(11*8), %rsp
-	CFI_ADJUST_CFA_OFFSET -11*8
+	addq $(6*8), %rsp
+	CFI_ADJUST_CFA_OFFSET -6*8
 
 nested_nmi_out:
 	popq_cfi %rdx
@@ -1736,18 +1753,18 @@ first_nmi:
 	 * +-------------------------+
 	 * | NMI executing variable  |
 	 * +-------------------------+
-	 * | Saved SS                |
-	 * | Saved Return RSP        |
-	 * | Saved RFLAGS            |
-	 * | Saved CS                |
-	 * | Saved RIP               |
-	 * +-------------------------+
 	 * | copied SS               |
 	 * | copied Return RSP       |
 	 * | copied RFLAGS           |
 	 * | copied CS               |
 	 * | copied RIP              |
 	 * +-------------------------+
+	 * | Saved SS                |
+	 * | Saved Return RSP        |
+	 * | Saved RFLAGS            |
+	 * | Saved CS                |
+	 * | Saved RIP               |
+	 * +-------------------------+
 	 * | pt_regs                 |
 	 * +-------------------------+
 	 *
@@ -1763,9 +1780,14 @@ first_nmi:
 	/* Set the NMI executing variable on the stack. */
 	pushq_cfi $1
 
+	/*
+	 * Leave room for the "copied" frame
+	 */
+	subq $(5*8), %rsp
+
 	/* Copy the stack frame to the Saved frame */
 	.rept 5
-	pushq_cfi 6*8(%rsp)
+	pushq_cfi 11*8(%rsp)
 	.endr
 	CFI_DEF_CFA_OFFSET SS+8-RIP
 
@@ -1786,12 +1808,15 @@ repeat_nmi:
 	 * is benign for the non-repeat case, where 1 was pushed just above
 	 * to this very stack slot).
 	 */
-	movq $1, 5*8(%rsp)
+	movq $1, 10*8(%rsp)
 
 	/* Make another copy, this one may be modified by nested NMIs */
+	addq $(10*8), %rsp
+	CFI_ADJUST_CFA_OFFSET -10*8
 	.rept 5
-	pushq_cfi 4*8(%rsp)
+	pushq_cfi -6*8(%rsp)
 	.endr
+	subq $(5*8), %rsp
 	CFI_DEF_CFA_OFFSET SS+8-RIP
 end_repeat_nmi:
 
@@ -1842,8 +1867,12 @@ nmi_swapgs:
 	SWAPGS_UNSAFE_STACK
 nmi_restore:
 	RESTORE_ALL 8
+
+	/* Pop the extra iret frame */
+	addq $(5*8), %rsp
+
 	/* Clear the NMI executing stack variable */
-	movq $0, 10*8(%rsp)
+	movq $0, 5*8(%rsp)
 	jmp irq_return
 	CFI_ENDPROC
 END(nmi)
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 1d41402..42a392a 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -89,7 +89,7 @@ do_ftrace_mod_code(unsigned long ip, const void *new_code)
 	 * kernel identity mapping to modify code.
 	 */
 	if (within(ip, (unsigned long)_text, (unsigned long)_etext))
-		ip = (unsigned long)__va(__pa(ip));
+		ip = (unsigned long)__va(__pa_symbol(ip));
 
 	return probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE);
 }
@@ -279,7 +279,7 @@ static int ftrace_write(unsigned long ip, const char *val, int size)
 	 * kernel identity mapping to modify code.
 	 */
 	if (within(ip, (unsigned long)_text, (unsigned long)_etext))
-		ip = (unsigned long)__va(__pa(ip));
+		ip = (unsigned long)__va(__pa_symbol(ip));
 
 	return probe_kernel_write((void *)ip, val, size);
 }
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index c18f59d..f15db0c 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -30,8 +30,8 @@ static void __init i386_default_early_setup(void)
 
 void __init i386_start_kernel(void)
 {
-	memblock_reserve(__pa_symbol(&_text),
-			 __pa_symbol(&__bss_stop) - __pa_symbol(&_text));
+	memblock_reserve(__pa_symbol(_text),
+			 (phys_addr_t)__bss_stop - (phys_addr_t)_text);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* Reserve INITRD */
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 037df57..42f5df1 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -97,8 +97,8 @@ void __init x86_64_start_reservations(char *real_mode_data)
 {
 	copy_bootdata(__va(real_mode_data));
 
-	memblock_reserve(__pa_symbol(&_text),
-			 __pa_symbol(&__bss_stop) - __pa_symbol(&_text));
+	memblock_reserve(__pa_symbol(_text),
+			 (phys_addr_t)__bss_stop - (phys_addr_t)_text);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* Reserve INITRD */
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 1460a5d..e28670f 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -434,7 +434,7 @@ void hpet_msi_unmask(struct irq_data *data)
 
 	/* unmask it */
 	cfg = hpet_readl(HPET_Tn_CFG(hdev->num));
-	cfg |= HPET_TN_FSB;
+	cfg |= HPET_TN_ENABLE | HPET_TN_FSB;
 	hpet_writel(cfg, HPET_Tn_CFG(hdev->num));
 }
 
@@ -445,7 +445,7 @@ void hpet_msi_mask(struct irq_data *data)
 
 	/* mask it */
 	cfg = hpet_readl(HPET_Tn_CFG(hdev->num));
-	cfg &= ~HPET_TN_FSB;
+	cfg &= ~(HPET_TN_ENABLE | HPET_TN_FSB);
 	hpet_writel(cfg, HPET_Tn_CFG(hdev->num));
 }
 
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index b644e1c..2ed787f 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -262,36 +262,6 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
 	propagate_user_return_notify(prev_p, next_p);
 }
 
-int sys_fork(struct pt_regs *regs)
-{
-	return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
-}
-
-/*
- * This is trivial, and on the face of it looks like it
- * could equally well be done in user mode.
- *
- * Not so, for quite unobvious reasons - register pressure.
- * In user mode vfork() cannot have a stack frame, and if
- * done by calling the "clone()" system call directly, you
- * do not have enough call-clobbered registers to hold all
- * the information you need.
- */
-int sys_vfork(struct pt_regs *regs)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0,
-		       NULL, NULL);
-}
-
-long
-sys_clone(unsigned long clone_flags, unsigned long newsp,
-	  void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
-{
-	if (!newsp)
-		newsp = regs->sp;
-	return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
-}
-
 /*
  * Idle related variables and functions
  */
@@ -306,11 +276,6 @@ void (*pm_idle)(void);
 EXPORT_SYMBOL(pm_idle);
 #endif
 
-static inline int hlt_use_halt(void)
-{
-	return 1;
-}
-
 #ifndef CONFIG_SMP
 static inline void play_dead(void)
 {
@@ -410,28 +375,22 @@ void cpu_idle(void)
  */
 void default_idle(void)
 {
-	if (hlt_use_halt()) {
-		trace_power_start_rcuidle(POWER_CSTATE, 1, smp_processor_id());
-		trace_cpu_idle_rcuidle(1, smp_processor_id());
-		current_thread_info()->status &= ~TS_POLLING;
-		/*
-		 * TS_POLLING-cleared state must be visible before we
-		 * test NEED_RESCHED:
-		 */
-		smp_mb();
+	trace_power_start_rcuidle(POWER_CSTATE, 1, smp_processor_id());
+	trace_cpu_idle_rcuidle(1, smp_processor_id());
+	current_thread_info()->status &= ~TS_POLLING;
+	/*
+	 * TS_POLLING-cleared state must be visible before we
+	 * test NEED_RESCHED:
+	 */
+	smp_mb();
 
-		if (!need_resched())
-			safe_halt();	/* enables interrupts racelessly */
-		else
-			local_irq_enable();
-		current_thread_info()->status |= TS_POLLING;
-		trace_power_end_rcuidle(smp_processor_id());
-		trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
-	} else {
+	if (!need_resched())
+		safe_halt();	/* enables interrupts racelessly */
+	else
 		local_irq_enable();
-		/* loop is done by the caller */
-		cpu_relax();
-	}
+	current_thread_info()->status |= TS_POLLING;
+	trace_power_end_rcuidle(smp_processor_id());
+	trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
 }
 #ifdef CONFIG_APM_MODULE
 EXPORT_SYMBOL(default_idle);
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 44e0bff..b5a8905 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -128,8 +128,7 @@ void release_thread(struct task_struct *dead_task)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long sp,
-	unsigned long arg,
-	struct task_struct *p, struct pt_regs *regs)
+	unsigned long arg, struct task_struct *p)
 {
 	struct pt_regs *childregs = task_pt_regs(p);
 	struct task_struct *tsk;
@@ -138,7 +137,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 	p->thread.sp = (unsigned long) childregs;
 	p->thread.sp0 = (unsigned long) (childregs+1);
 
-	if (unlikely(!regs)) {
+	if (unlikely(p->flags & PF_KTHREAD)) {
 		/* kernel thread */
 		memset(childregs, 0, sizeof(struct pt_regs));
 		p->thread.ip = (unsigned long) ret_from_kernel_thread;
@@ -156,12 +155,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 		memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
 		return 0;
 	}
-	*childregs = *regs;
+	*childregs = *current_pt_regs();
 	childregs->ax = 0;
-	childregs->sp = sp;
+	if (sp)
+		childregs->sp = sp;
 
 	p->thread.ip = (unsigned long) ret_from_fork;
-	task_user_gs(p) = get_user_gs(regs);
+	task_user_gs(p) = get_user_gs(current_pt_regs());
 
 	p->fpu_counter = 0;
 	p->thread.io_bitmap_ptr = NULL;
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 16c6365..6e68a61 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -146,8 +146,7 @@ static inline u32 read_32bit_tls(struct task_struct *t, int tls)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long sp,
-		unsigned long arg,
-	struct task_struct *p, struct pt_regs *regs)
+		unsigned long arg, struct task_struct *p)
 {
 	int err;
 	struct pt_regs *childregs;
@@ -169,7 +168,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 	savesegment(ds, p->thread.ds);
 	memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
 
-	if (unlikely(!regs)) {
+	if (unlikely(p->flags & PF_KTHREAD)) {
 		/* kernel thread */
 		memset(childregs, 0, sizeof(struct pt_regs));
 		childregs->sp = (unsigned long)childregs;
@@ -181,10 +180,11 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 		childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1;
 		return 0;
 	}
-	*childregs = *regs;
+	*childregs = *current_pt_regs();
 
 	childregs->ax = 0;
-	childregs->sp = sp;
+	if (sp)
+		childregs->sp = sp;
 
 	err = -ENOMEM;
 	memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 5e0596b..078c7ff 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -21,8 +21,8 @@
 #include <linux/signal.h>
 #include <linux/perf_event.h>
 #include <linux/hw_breakpoint.h>
-#include <linux/rcupdate.h>
 #include <linux/module.h>
+#include <linux/context_tracking.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -1491,7 +1491,7 @@ long syscall_trace_enter(struct pt_regs *regs)
 {
 	long ret = 0;
 
-	rcu_user_exit();
+	user_exit();
 
 	/*
 	 * If we stepped into a sysenter/syscall insn, it trapped in
@@ -1541,6 +1541,13 @@ void syscall_trace_leave(struct pt_regs *regs)
 {
 	bool step;
 
+	/*
+	 * We may come here right after calling schedule_user()
+	 * or do_notify_resume(), in which case we can be in RCU
+	 * user mode.
+	 */
+	user_exit();
+
 	audit_syscall_exit(regs);
 
 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
@@ -1557,5 +1564,5 @@ void syscall_trace_leave(struct pt_regs *regs)
 	if (step || test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall_exit(regs, step);
 
-	rcu_user_enter();
+	user_enter();
 }
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index 4929c1b..801602b 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -195,12 +195,6 @@ void read_persistent_clock(struct timespec *ts)
 	ts->tv_nsec = 0;
 }
 
-unsigned long long native_read_tsc(void)
-{
-	return __native_read_tsc();
-}
-EXPORT_SYMBOL(native_read_tsc);
-
 
 static struct resource rtc_resources[] = {
 	[0] = {
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index ca45696..4343570 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -300,8 +300,8 @@ static void __init cleanup_highmap(void)
 static void __init reserve_brk(void)
 {
 	if (_brk_end > _brk_start)
-		memblock_reserve(__pa(_brk_start),
-				 __pa(_brk_end) - __pa(_brk_start));
+		memblock_reserve(__pa_symbol(_brk_start),
+				 _brk_end - _brk_start);
 
 	/* Mark brk area as locked down and no longer taking any
 	   new allocations */
@@ -761,12 +761,12 @@ void __init setup_arch(char **cmdline_p)
 	init_mm.end_data = (unsigned long) _edata;
 	init_mm.brk = _brk_end;
 
-	code_resource.start = virt_to_phys(_text);
-	code_resource.end = virt_to_phys(_etext)-1;
-	data_resource.start = virt_to_phys(_etext);
-	data_resource.end = virt_to_phys(_edata)-1;
-	bss_resource.start = virt_to_phys(&__bss_start);
-	bss_resource.end = virt_to_phys(&__bss_stop)-1;
+	code_resource.start = __pa_symbol(_text);
+	code_resource.end = __pa_symbol(_etext)-1;
+	data_resource.start = __pa_symbol(_etext);
+	data_resource.end = __pa_symbol(_edata)-1;
+	bss_resource.start = __pa_symbol(__bss_start);
+	bss_resource.end = __pa_symbol(__bss_stop)-1;
 
 #ifdef CONFIG_CMDLINE_BOOL
 #ifdef CONFIG_CMDLINE_OVERRIDE
@@ -956,6 +956,10 @@ void __init setup_arch(char **cmdline_p)
 
 	reserve_initrd();
 
+#if defined(CONFIG_ACPI) && defined(CONFIG_BLK_DEV_INITRD)
+	acpi_initrd_override((void *)initrd_start, initrd_end - initrd_start);
+#endif
+
 	reserve_crashkernel();
 
 	vsmp_init();
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 70b27ee..fbbb604 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -22,6 +22,7 @@
 #include <linux/uaccess.h>
 #include <linux/user-return-notifier.h>
 #include <linux/uprobes.h>
+#include <linux/context_tracking.h>
 
 #include <asm/processor.h>
 #include <asm/ucontext.h>
@@ -816,7 +817,7 @@ static void do_signal(struct pt_regs *regs)
 void
 do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
 {
-	rcu_user_exit();
+	user_exit();
 
 #ifdef CONFIG_X86_MCE
 	/* notify userspace of pending MCEs */
@@ -838,7 +839,7 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
 	if (thread_info_flags & _TIF_USER_RETURN_NOTIFY)
 		fire_user_return_notifiers();
 
-	rcu_user_enter();
+	user_enter();
 }
 
 void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index c80a33b..732bf5c 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -313,7 +313,7 @@ do {									\
 
 static bool __cpuinit match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
 {
-	if (cpu_has(c, X86_FEATURE_TOPOEXT)) {
+	if (cpu_has_topoext) {
 		int cpu1 = c->cpu_index, cpu2 = o->cpu_index;
 
 		if (c->phys_proc_id == o->phys_proc_id &&
diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c
index b4d3c39..97ef74b 100644
--- a/arch/x86/kernel/sys_x86_64.c
+++ b/arch/x86/kernel/sys_x86_64.c
@@ -21,37 +21,23 @@
 
 /*
  * Align a virtual address to avoid aliasing in the I$ on AMD F15h.
- *
- * @flags denotes the allocation direction - bottomup or topdown -
- * or vDSO; see call sites below.
  */
-unsigned long align_addr(unsigned long addr, struct file *filp,
-			 enum align_flags flags)
+static unsigned long get_align_mask(void)
 {
-	unsigned long tmp_addr;
-
 	/* handle 32- and 64-bit case with a single conditional */
 	if (va_align.flags < 0 || !(va_align.flags & (2 - mmap_is_ia32())))
-		return addr;
+		return 0;
 
 	if (!(current->flags & PF_RANDOMIZE))
-		return addr;
-
-	if (!((flags & ALIGN_VDSO) || filp))
-		return addr;
-
-	tmp_addr = addr;
-
-	/*
-	 * We need an address which is <= than the original
-	 * one only when in topdown direction.
-	 */
-	if (!(flags & ALIGN_TOPDOWN))
-		tmp_addr += va_align.mask;
+		return 0;
 
-	tmp_addr &= ~va_align.mask;
+	return va_align.mask;
+}
 
-	return tmp_addr;
+unsigned long align_vdso_addr(unsigned long addr)
+{
+	unsigned long align_mask = get_align_mask();
+	return (addr + align_mask) & ~align_mask;
 }
 
 static int __init control_va_addr_alignment(char *str)
@@ -126,7 +112,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
-	unsigned long start_addr;
+	struct vm_unmapped_area_info info;
 	unsigned long begin, end;
 
 	if (flags & MAP_FIXED)
@@ -144,50 +130,16 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 		    (!vma || addr + len <= vma->vm_start))
 			return addr;
 	}
-	if (((flags & MAP_32BIT) || test_thread_flag(TIF_ADDR32))
-	    && len <= mm->cached_hole_size) {
-		mm->cached_hole_size = 0;
-		mm->free_area_cache = begin;
-	}
-	addr = mm->free_area_cache;
-	if (addr < begin)
-		addr = begin;
-	start_addr = addr;
-
-full_search:
-
-	addr = align_addr(addr, filp, 0);
-
-	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
-		/* At this point:  (!vma || addr < vma->vm_end). */
-		if (end - len < addr) {
-			/*
-			 * Start a new search - just in case we missed
-			 * some holes.
-			 */
-			if (start_addr != begin) {
-				start_addr = addr = begin;
-				mm->cached_hole_size = 0;
-				goto full_search;
-			}
-			return -ENOMEM;
-		}
-		if (!vma || addr + len <= vma->vm_start) {
-			/*
-			 * Remember the place where we stopped the search:
-			 */
-			mm->free_area_cache = addr + len;
-			return addr;
-		}
-		if (addr + mm->cached_hole_size < vma->vm_start)
-			mm->cached_hole_size = vma->vm_start - addr;
 
-		addr = vma->vm_end;
-		addr = align_addr(addr, filp, 0);
-	}
+	info.flags = 0;
+	info.length = len;
+	info.low_limit = begin;
+	info.high_limit = end;
+	info.align_mask = filp ? get_align_mask() : 0;
+	info.align_offset = pgoff << PAGE_SHIFT;
+	return vm_unmapped_area(&info);
 }
 
-
 unsigned long
 arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 			  const unsigned long len, const unsigned long pgoff,
@@ -195,7 +147,8 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 {
 	struct vm_area_struct *vma;
 	struct mm_struct *mm = current->mm;
-	unsigned long addr = addr0, start_addr;
+	unsigned long addr = addr0;
+	struct vm_unmapped_area_info info;
 
 	/* requested length too big for entire address space */
 	if (len > TASK_SIZE)
@@ -217,51 +170,16 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 			return addr;
 	}
 
-	/* check if free_area_cache is useful for us */
-	if (len <= mm->cached_hole_size) {
-		mm->cached_hole_size = 0;
-		mm->free_area_cache = mm->mmap_base;
-	}
-
-try_again:
-	/* either no address requested or can't fit in requested address hole */
-	start_addr = addr = mm->free_area_cache;
-
-	if (addr < len)
-		goto fail;
-
-	addr -= len;
-	do {
-		addr = align_addr(addr, filp, ALIGN_TOPDOWN);
-
-		/*
-		 * Lookup failure means no vma is above this address,
-		 * else if new region fits below vma->vm_start,
-		 * return with success:
-		 */
-		vma = find_vma(mm, addr);
-		if (!vma || addr+len <= vma->vm_start)
-			/* remember the address as a hint for next time */
-			return mm->free_area_cache = addr;
-
-		/* remember the largest hole we saw so far */
-		if (addr + mm->cached_hole_size < vma->vm_start)
-			mm->cached_hole_size = vma->vm_start - addr;
-
-		/* try just below the current vma->vm_start */
-		addr = vma->vm_start-len;
-	} while (len < vma->vm_start);
-
-fail:
-	/*
-	 * if hint left us with no space for the requested
-	 * mapping then try again:
-	 */
-	if (start_addr != mm->mmap_base) {
-		mm->free_area_cache = mm->mmap_base;
-		mm->cached_hole_size = 0;
-		goto try_again;
-	}
+	info.flags = VM_UNMAPPED_AREA_TOPDOWN;
+	info.length = len;
+	info.low_limit = PAGE_SIZE;
+	info.high_limit = mm->mmap_base;
+	info.align_mask = filp ? get_align_mask() : 0;
+	info.align_offset = pgoff << PAGE_SHIFT;
+	addr = vm_unmapped_area(&info);
+	if (!(addr & ~PAGE_MASK))
+		return addr;
+	VM_BUG_ON(addr != -ENOMEM);
 
 bottomup:
 	/*
@@ -270,14 +188,5 @@ bottomup:
 	 * can happen with large stack limits and large mmap()
 	 * allocations.
 	 */
-	mm->cached_hole_size = ~0UL;
-	mm->free_area_cache = TASK_UNMAPPED_BASE;
-	addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
-	/*
-	 * Restore the topdown base:
-	 */
-	mm->free_area_cache = mm->mmap_base;
-	mm->cached_hole_size = ~0UL;
-
-	return addr;
+	return arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
 }
diff --git a/arch/x86/kernel/trace_clock.c b/arch/x86/kernel/trace_clock.c
new file mode 100644
index 0000000..25b9937
--- /dev/null
+++ b/arch/x86/kernel/trace_clock.c
@@ -0,0 +1,21 @@
+/*
+ * X86 trace clocks
+ */
+#include <asm/trace_clock.h>
+#include <asm/barrier.h>
+#include <asm/msr.h>
+
+/*
+ * trace_clock_x86_tsc(): A clock that is just the cycle counter.
+ *
+ * Unlike the other clocks, this is not in nanoseconds.
+ */
+u64 notrace trace_clock_x86_tsc(void)
+{
+	u64 ret;
+
+	rdtsc_barrier();
+	rdtscll(ret);
+
+	return ret;
+}
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 8276dc6..eb85866 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -55,7 +55,7 @@
 #include <asm/i387.h>
 #include <asm/fpu-internal.h>
 #include <asm/mce.h>
-#include <asm/rcu.h>
+#include <asm/context_tracking.h>
 
 #include <asm/mach_traps.h>
 
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index cfa5d4f..06ccb50 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -77,6 +77,12 @@ unsigned long long
 sched_clock(void) __attribute__((alias("native_sched_clock")));
 #endif
 
+unsigned long long native_read_tsc(void)
+{
+	return __native_read_tsc();
+}
+EXPORT_SYMBOL(native_read_tsc);
+
 int check_tsc_unstable(void)
 {
 	return tsc_unstable;
diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c
index 5c9687b..1dfe69c 100644
--- a/arch/x86/kernel/vm86_32.c
+++ b/arch/x86/kernel/vm86_32.c
@@ -182,7 +182,7 @@ static void mark_screen_rdonly(struct mm_struct *mm)
 	if (pud_none_or_clear_bad(pud))
 		goto out;
 	pmd = pmd_offset(pud, 0xA0000);
-	split_huge_page_pmd(mm, pmd);
+	split_huge_page_pmd_mm(mm, 0xA0000, pmd);
 	if (pmd_none_or_clear_bad(pmd))
 		goto out;
 	pte = pte_offset_map_lock(mm, pmd, 0xA0000, &ptl);
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index 3a3e8c9..9a907a6 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -145,19 +145,6 @@ static int addr_to_vsyscall_nr(unsigned long addr)
 	return nr;
 }
 
-#ifdef CONFIG_SECCOMP
-static int vsyscall_seccomp(struct task_struct *tsk, int syscall_nr)
-{
-	if (!seccomp_mode(&tsk->seccomp))
-		return 0;
-	task_pt_regs(tsk)->orig_ax = syscall_nr;
-	task_pt_regs(tsk)->ax = syscall_nr;
-	return __secure_computing(syscall_nr);
-}
-#else
-#define vsyscall_seccomp(_tsk, _nr) 0
-#endif
-
 static bool write_ok_or_segv(unsigned long ptr, size_t size)
 {
 	/*
@@ -190,10 +177,9 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
 {
 	struct task_struct *tsk;
 	unsigned long caller;
-	int vsyscall_nr;
+	int vsyscall_nr, syscall_nr, tmp;
 	int prev_sig_on_uaccess_error;
 	long ret;
-	int skip;
 
 	/*
 	 * No point in checking CS -- the only way to get here is a user mode
@@ -225,56 +211,84 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
 	}
 
 	tsk = current;
-	/*
-	 * With a real vsyscall, page faults cause SIGSEGV.  We want to
-	 * preserve that behavior to make writing exploits harder.
-	 */
-	prev_sig_on_uaccess_error = current_thread_info()->sig_on_uaccess_error;
-	current_thread_info()->sig_on_uaccess_error = 1;
 
 	/*
+	 * Check for access_ok violations and find the syscall nr.
+	 *
 	 * NULL is a valid user pointer (in the access_ok sense) on 32-bit and
 	 * 64-bit, so we don't need to special-case it here.  For all the
 	 * vsyscalls, NULL means "don't write anything" not "write it at
 	 * address 0".
 	 */
-	ret = -EFAULT;
-	skip = 0;
 	switch (vsyscall_nr) {
 	case 0:
-		skip = vsyscall_seccomp(tsk, __NR_gettimeofday);
-		if (skip)
-			break;
-
 		if (!write_ok_or_segv(regs->di, sizeof(struct timeval)) ||
-		    !write_ok_or_segv(regs->si, sizeof(struct timezone)))
-			break;
+		    !write_ok_or_segv(regs->si, sizeof(struct timezone))) {
+			ret = -EFAULT;
+			goto check_fault;
+		}
+
+		syscall_nr = __NR_gettimeofday;
+		break;
+
+	case 1:
+		if (!write_ok_or_segv(regs->di, sizeof(time_t))) {
+			ret = -EFAULT;
+			goto check_fault;
+		}
+
+		syscall_nr = __NR_time;
+		break;
+
+	case 2:
+		if (!write_ok_or_segv(regs->di, sizeof(unsigned)) ||
+		    !write_ok_or_segv(regs->si, sizeof(unsigned))) {
+			ret = -EFAULT;
+			goto check_fault;
+		}
+
+		syscall_nr = __NR_getcpu;
+		break;
+	}
+
+	/*
+	 * Handle seccomp.  regs->ip must be the original value.
+	 * See seccomp_send_sigsys and Documentation/prctl/seccomp_filter.txt.
+	 *
+	 * We could optimize the seccomp disabled case, but performance
+	 * here doesn't matter.
+	 */
+	regs->orig_ax = syscall_nr;
+	regs->ax = -ENOSYS;
+	tmp = secure_computing(syscall_nr);
+	if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) {
+		warn_bad_vsyscall(KERN_DEBUG, regs,
+				  "seccomp tried to change syscall nr or ip");
+		do_exit(SIGSYS);
+	}
+	if (tmp)
+		goto do_ret;  /* skip requested */
 
+	/*
+	 * With a real vsyscall, page faults cause SIGSEGV.  We want to
+	 * preserve that behavior to make writing exploits harder.
+	 */
+	prev_sig_on_uaccess_error = current_thread_info()->sig_on_uaccess_error;
+	current_thread_info()->sig_on_uaccess_error = 1;
+
+	ret = -EFAULT;
+	switch (vsyscall_nr) {
+	case 0:
 		ret = sys_gettimeofday(
 			(struct timeval __user *)regs->di,
 			(struct timezone __user *)regs->si);
 		break;
 
 	case 1:
-		skip = vsyscall_seccomp(tsk, __NR_time);
-		if (skip)
-			break;
-
-		if (!write_ok_or_segv(regs->di, sizeof(time_t)))
-			break;
-
 		ret = sys_time((time_t __user *)regs->di);
 		break;
 
 	case 2:
-		skip = vsyscall_seccomp(tsk, __NR_getcpu);
-		if (skip)
-			break;
-
-		if (!write_ok_or_segv(regs->di, sizeof(unsigned)) ||
-		    !write_ok_or_segv(regs->si, sizeof(unsigned)))
-			break;
-
 		ret = sys_getcpu((unsigned __user *)regs->di,
 				 (unsigned __user *)regs->si,
 				 NULL);
@@ -283,12 +297,7 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
 
 	current_thread_info()->sig_on_uaccess_error = prev_sig_on_uaccess_error;
 
-	if (skip) {
-		if ((long)regs->ax <= 0L) /* seccomp errno emulation */
-			goto do_ret;
-		goto done; /* seccomp trace/trap */
-	}
-
+check_fault:
 	if (ret == -EFAULT) {
 		/* Bad news -- userspace fed a bad pointer to a vsyscall. */
 		warn_bad_vsyscall(KERN_INFO, regs,
@@ -311,7 +320,6 @@ do_ret:
 	/* Emulate a ret instruction. */
 	regs->ip = caller;
 	regs->sp += 8;
-done:
 	return true;
 
 sigsegv:
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index 1330dd1..b014d94 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -59,6 +59,9 @@ EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(__memcpy);
 EXPORT_SYMBOL(memmove);
 
+#ifndef CONFIG_DEBUG_VIRTUAL
+EXPORT_SYMBOL(phys_base);
+#endif
 EXPORT_SYMBOL(empty_zero_page);
 #ifndef CONFIG_PARAVIRT
 EXPORT_SYMBOL(native_load_gs_index);
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 6f85fe0..b875a9e 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2505,6 +2505,14 @@ static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
 	mmu_free_roots(vcpu);
 }
 
+static bool is_rsvd_bits_set(struct kvm_mmu *mmu, u64 gpte, int level)
+{
+	int bit7;
+
+	bit7 = (gpte >> 7) & 1;
+	return (gpte & mmu->rsvd_bits_mask[bit7][level-1]) != 0;
+}
+
 static pfn_t pte_prefetch_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn,
 				     bool no_dirty_log)
 {
@@ -2517,6 +2525,26 @@ static pfn_t pte_prefetch_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn,
 	return gfn_to_pfn_memslot_atomic(slot, gfn);
 }
 
+static bool prefetch_invalid_gpte(struct kvm_vcpu *vcpu,
+				  struct kvm_mmu_page *sp, u64 *spte,
+				  u64 gpte)
+{
+	if (is_rsvd_bits_set(&vcpu->arch.mmu, gpte, PT_PAGE_TABLE_LEVEL))
+		goto no_present;
+
+	if (!is_present_gpte(gpte))
+		goto no_present;
+
+	if (!(gpte & PT_ACCESSED_MASK))
+		goto no_present;
+
+	return false;
+
+no_present:
+	drop_spte(vcpu->kvm, spte);
+	return true;
+}
+
 static int direct_pte_prefetch_many(struct kvm_vcpu *vcpu,
 				    struct kvm_mmu_page *sp,
 				    u64 *start, u64 *end)
@@ -2671,7 +2699,7 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
 	 * PT_PAGE_TABLE_LEVEL and there would be no adjustment done
 	 * here.
 	 */
-	if (!is_error_pfn(pfn) && !kvm_is_mmio_pfn(pfn) &&
+	if (!is_error_noslot_pfn(pfn) && !kvm_is_mmio_pfn(pfn) &&
 	    level == PT_PAGE_TABLE_LEVEL &&
 	    PageTransCompound(pfn_to_page(pfn)) &&
 	    !has_wrprotected_page(vcpu->kvm, gfn, PT_DIRECTORY_LEVEL)) {
@@ -2699,18 +2727,13 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
 	}
 }
 
-static bool mmu_invalid_pfn(pfn_t pfn)
-{
-	return unlikely(is_invalid_pfn(pfn));
-}
-
 static bool handle_abnormal_pfn(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn,
 				pfn_t pfn, unsigned access, int *ret_val)
 {
 	bool ret = true;
 
 	/* The pfn is invalid, report the error! */
-	if (unlikely(is_invalid_pfn(pfn))) {
+	if (unlikely(is_error_pfn(pfn))) {
 		*ret_val = kvm_handle_bad_page(vcpu, gfn, pfn);
 		goto exit;
 	}
@@ -2862,7 +2885,7 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, u32 error_code,
 		return r;
 
 	spin_lock(&vcpu->kvm->mmu_lock);
-	if (mmu_notifier_retry(vcpu, mmu_seq))
+	if (mmu_notifier_retry(vcpu->kvm, mmu_seq))
 		goto out_unlock;
 	kvm_mmu_free_some_pages(vcpu);
 	if (likely(!force_pt_level))
@@ -3331,7 +3354,7 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
 		return r;
 
 	spin_lock(&vcpu->kvm->mmu_lock);
-	if (mmu_notifier_retry(vcpu, mmu_seq))
+	if (mmu_notifier_retry(vcpu->kvm, mmu_seq))
 		goto out_unlock;
 	kvm_mmu_free_some_pages(vcpu);
 	if (likely(!force_pt_level))
@@ -3399,14 +3422,6 @@ static void paging_free(struct kvm_vcpu *vcpu)
 	nonpaging_free(vcpu);
 }
 
-static bool is_rsvd_bits_set(struct kvm_mmu *mmu, u64 gpte, int level)
-{
-	int bit7;
-
-	bit7 = (gpte >> 7) & 1;
-	return (gpte & mmu->rsvd_bits_mask[bit7][level-1]) != 0;
-}
-
 static inline void protect_clean_gpte(unsigned *access, unsigned gpte)
 {
 	unsigned mask;
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 714e2c0..891eb6d 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -305,51 +305,43 @@ static int FNAME(walk_addr_nested)(struct guest_walker *walker,
 					addr, access);
 }
 
-static bool FNAME(prefetch_invalid_gpte)(struct kvm_vcpu *vcpu,
-				    struct kvm_mmu_page *sp, u64 *spte,
-				    pt_element_t gpte)
+static bool
+FNAME(prefetch_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
+		     u64 *spte, pt_element_t gpte, bool no_dirty_log)
 {
-	if (is_rsvd_bits_set(&vcpu->arch.mmu, gpte, PT_PAGE_TABLE_LEVEL))
-		goto no_present;
-
-	if (!is_present_gpte(gpte))
-		goto no_present;
-
-	if (!(gpte & PT_ACCESSED_MASK))
-		goto no_present;
-
-	return false;
-
-no_present:
-	drop_spte(vcpu->kvm, spte);
-	return true;
-}
-
-static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
-			      u64 *spte, const void *pte)
-{
-	pt_element_t gpte;
 	unsigned pte_access;
+	gfn_t gfn;
 	pfn_t pfn;
 
-	gpte = *(const pt_element_t *)pte;
-	if (FNAME(prefetch_invalid_gpte)(vcpu, sp, spte, gpte))
-		return;
+	if (prefetch_invalid_gpte(vcpu, sp, spte, gpte))
+		return false;
 
 	pgprintk("%s: gpte %llx spte %p\n", __func__, (u64)gpte, spte);
+
+	gfn = gpte_to_gfn(gpte);
 	pte_access = sp->role.access & gpte_access(vcpu, gpte);
 	protect_clean_gpte(&pte_access, gpte);
-	pfn = gfn_to_pfn_atomic(vcpu->kvm, gpte_to_gfn(gpte));
-	if (mmu_invalid_pfn(pfn))
-		return;
+	pfn = pte_prefetch_gfn_to_pfn(vcpu, gfn,
+			no_dirty_log && (pte_access & ACC_WRITE_MASK));
+	if (is_error_pfn(pfn))
+		return false;
 
 	/*
-	 * we call mmu_set_spte() with host_writable = true because that
-	 * vcpu->arch.update_pte.pfn was fetched from get_user_pages(write = 1).
+	 * we call mmu_set_spte() with host_writable = true because
+	 * pte_prefetch_gfn_to_pfn always gets a writable pfn.
 	 */
 	mmu_set_spte(vcpu, spte, sp->role.access, pte_access, 0, 0,
-		     NULL, PT_PAGE_TABLE_LEVEL,
-		     gpte_to_gfn(gpte), pfn, true, true);
+		     NULL, PT_PAGE_TABLE_LEVEL, gfn, pfn, true, true);
+
+	return true;
+}
+
+static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
+			      u64 *spte, const void *pte)
+{
+	pt_element_t gpte = *(const pt_element_t *)pte;
+
+	FNAME(prefetch_gpte)(vcpu, sp, spte, gpte, false);
 }
 
 static bool FNAME(gpte_changed)(struct kvm_vcpu *vcpu,
@@ -395,53 +387,34 @@ static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, struct guest_walker *gw,
 	spte = sp->spt + i;
 
 	for (i = 0; i < PTE_PREFETCH_NUM; i++, spte++) {
-		pt_element_t gpte;
-		unsigned pte_access;
-		gfn_t gfn;
-		pfn_t pfn;
-
 		if (spte == sptep)
 			continue;
 
 		if (is_shadow_present_pte(*spte))
 			continue;
 
-		gpte = gptep[i];
-
-		if (FNAME(prefetch_invalid_gpte)(vcpu, sp, spte, gpte))
-			continue;
-
-		pte_access = sp->role.access & gpte_access(vcpu, gpte);
-		protect_clean_gpte(&pte_access, gpte);
-		gfn = gpte_to_gfn(gpte);
-		pfn = pte_prefetch_gfn_to_pfn(vcpu, gfn,
-				      pte_access & ACC_WRITE_MASK);
-		if (mmu_invalid_pfn(pfn))
+		if (!FNAME(prefetch_gpte)(vcpu, sp, spte, gptep[i], true))
 			break;
-
-		mmu_set_spte(vcpu, spte, sp->role.access, pte_access, 0, 0,
-			     NULL, PT_PAGE_TABLE_LEVEL, gfn,
-			     pfn, true, true);
 	}
 }
 
 /*
  * Fetch a shadow pte for a specific level in the paging hierarchy.
+ * If the guest tries to write a write-protected page, we need to
+ * emulate this operation, return 1 to indicate this case.
  */
-static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
+static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
 			 struct guest_walker *gw,
 			 int user_fault, int write_fault, int hlevel,
-			 int *emulate, pfn_t pfn, bool map_writable,
-			 bool prefault)
+			 pfn_t pfn, bool map_writable, bool prefault)
 {
-	unsigned access = gw->pt_access;
 	struct kvm_mmu_page *sp = NULL;
-	int top_level;
-	unsigned direct_access;
 	struct kvm_shadow_walk_iterator it;
+	unsigned direct_access, access = gw->pt_access;
+	int top_level, emulate = 0;
 
 	if (!is_present_gpte(gw->ptes[gw->level - 1]))
-		return NULL;
+		return 0;
 
 	direct_access = gw->pte_access;
 
@@ -505,17 +478,17 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
 
 	clear_sp_write_flooding_count(it.sptep);
 	mmu_set_spte(vcpu, it.sptep, access, gw->pte_access,
-		     user_fault, write_fault, emulate, it.level,
+		     user_fault, write_fault, &emulate, it.level,
 		     gw->gfn, pfn, prefault, map_writable);
 	FNAME(pte_prefetch)(vcpu, gw, it.sptep);
 
-	return it.sptep;
+	return emulate;
 
 out_gpte_changed:
 	if (sp)
 		kvm_mmu_put_page(sp, it.sptep);
 	kvm_release_pfn_clean(pfn);
-	return NULL;
+	return 0;
 }
 
 /*
@@ -538,8 +511,6 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
 	int write_fault = error_code & PFERR_WRITE_MASK;
 	int user_fault = error_code & PFERR_USER_MASK;
 	struct guest_walker walker;
-	u64 *sptep;
-	int emulate = 0;
 	int r;
 	pfn_t pfn;
 	int level = PT_PAGE_TABLE_LEVEL;
@@ -594,24 +565,20 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
 		return r;
 
 	spin_lock(&vcpu->kvm->mmu_lock);
-	if (mmu_notifier_retry(vcpu, mmu_seq))
+	if (mmu_notifier_retry(vcpu->kvm, mmu_seq))
 		goto out_unlock;
 
 	kvm_mmu_audit(vcpu, AUDIT_PRE_PAGE_FAULT);
 	kvm_mmu_free_some_pages(vcpu);
 	if (!force_pt_level)
 		transparent_hugepage_adjust(vcpu, &walker.gfn, &pfn, &level);
-	sptep = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault,
-			     level, &emulate, pfn, map_writable, prefault);
-	(void)sptep;
-	pgprintk("%s: shadow pte %p %llx emulate %d\n", __func__,
-		 sptep, *sptep, emulate);
-
+	r = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault,
+			 level, pfn, map_writable, prefault);
 	++vcpu->stat.pf_fixed;
 	kvm_mmu_audit(vcpu, AUDIT_POST_PAGE_FAULT);
 	spin_unlock(&vcpu->kvm->mmu_lock);
 
-	return emulate;
+	return r;
 
 out_unlock:
 	spin_unlock(&vcpu->kvm->mmu_lock);
@@ -757,7 +724,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 					  sizeof(pt_element_t)))
 			return -EINVAL;
 
-		if (FNAME(prefetch_invalid_gpte)(vcpu, sp, &sp->spt[i], gpte)) {
+		if (prefetch_invalid_gpte(vcpu, sp, &sp->spt[i], gpte)) {
 			vcpu->kvm->tlbs_dirty++;
 			continue;
 		}
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index d017df3..e93908f 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -630,15 +630,12 @@ static int svm_hardware_enable(void *garbage)
 		return -EBUSY;
 
 	if (!has_svm()) {
-		printk(KERN_ERR "svm_hardware_enable: err EOPNOTSUPP on %d\n",
-		       me);
+		pr_err("%s: err EOPNOTSUPP on %d\n", __func__, me);
 		return -EINVAL;
 	}
 	sd = per_cpu(svm_data, me);
-
 	if (!sd) {
-		printk(KERN_ERR "svm_hardware_enable: svm_data is NULL on %d\n",
-		       me);
+		pr_err("%s: svm_data is NULL on %d\n", __func__, me);
 		return -EINVAL;
 	}
 
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index f858159..5b472f4 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4287,16 +4287,6 @@ static int handle_exception(struct kvm_vcpu *vcpu)
 	if (is_machine_check(intr_info))
 		return handle_machine_check(vcpu);
 
-	if ((vect_info & VECTORING_INFO_VALID_MASK) &&
-	    !is_page_fault(intr_info)) {
-		vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-		vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_SIMUL_EX;
-		vcpu->run->internal.ndata = 2;
-		vcpu->run->internal.data[0] = vect_info;
-		vcpu->run->internal.data[1] = intr_info;
-		return 0;
-	}
-
 	if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR)
 		return 1;  /* already handled by vmx_vcpu_run() */
 
@@ -4315,6 +4305,22 @@ static int handle_exception(struct kvm_vcpu *vcpu)
 	error_code = 0;
 	if (intr_info & INTR_INFO_DELIVER_CODE_MASK)
 		error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
+
+	/*
+	 * The #PF with PFEC.RSVD = 1 indicates the guest is accessing
+	 * MMIO, it is better to report an internal error.
+	 * See the comments in vmx_handle_exit.
+	 */
+	if ((vect_info & VECTORING_INFO_VALID_MASK) &&
+	    !(is_page_fault(intr_info) && !(error_code & PFERR_RSVD_MASK))) {
+		vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_SIMUL_EX;
+		vcpu->run->internal.ndata = 2;
+		vcpu->run->internal.data[0] = vect_info;
+		vcpu->run->internal.data[1] = intr_info;
+		return 0;
+	}
+
 	if (is_page_fault(intr_info)) {
 		/* EPT won't cause page fault directly */
 		BUG_ON(enable_ept);
@@ -5979,13 +5985,24 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu)
 		return 0;
 	}
 
+	/*
+	 * Note:
+	 * Do not try to fix EXIT_REASON_EPT_MISCONFIG if it caused by
+	 * delivery event since it indicates guest is accessing MMIO.
+	 * The vm-exit can be triggered again after return to guest that
+	 * will cause infinite loop.
+	 */
 	if ((vectoring_info & VECTORING_INFO_VALID_MASK) &&
 			(exit_reason != EXIT_REASON_EXCEPTION_NMI &&
 			exit_reason != EXIT_REASON_EPT_VIOLATION &&
-			exit_reason != EXIT_REASON_TASK_SWITCH))
-		printk(KERN_WARNING "%s: unexpected, valid vectoring info "
-		       "(0x%x) and exit reason is 0x%x\n",
-		       __func__, vectoring_info, exit_reason);
+			exit_reason != EXIT_REASON_TASK_SWITCH)) {
+		vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+		vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_DELIVERY_EV;
+		vcpu->run->internal.ndata = 2;
+		vcpu->run->internal.data[0] = vectoring_info;
+		vcpu->run->internal.data[1] = exit_reason;
+		return 0;
+	}
 
 	if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked &&
 	    !(is_guest_mode(vcpu) && nested_cpu_has_virtual_nmis(
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 4f76417..2e47f1c 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -158,7 +158,9 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 
 u64 __read_mostly host_xcr0;
 
-int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt);
+static int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt);
+
+static int kvm_vcpu_reset(struct kvm_vcpu *vcpu);
 
 static inline void kvm_async_pf_hash_reset(struct kvm_vcpu *vcpu)
 {
@@ -633,7 +635,7 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 	}
 
 	if (is_long_mode(vcpu)) {
-		if (kvm_read_cr4(vcpu) & X86_CR4_PCIDE) {
+		if (kvm_read_cr4_bits(vcpu, X86_CR4_PCIDE)) {
 			if (cr3 & CR3_PCID_ENABLED_RESERVED_BITS)
 				return 1;
 		} else
@@ -2687,19 +2689,13 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
 		break;
 	}
 	case KVM_SET_LAPIC: {
-		r = -EINVAL;
 		if (!vcpu->arch.apic)
 			goto out;
 		u.lapic = memdup_user(argp, sizeof(*u.lapic));
-		if (IS_ERR(u.lapic)) {
-			r = PTR_ERR(u.lapic);
-			goto out;
-		}
+		if (IS_ERR(u.lapic))
+			return PTR_ERR(u.lapic);
 
 		r = kvm_vcpu_ioctl_set_lapic(vcpu, u.lapic);
-		if (r)
-			goto out;
-		r = 0;
 		break;
 	}
 	case KVM_INTERRUPT: {
@@ -2709,16 +2705,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
 		if (copy_from_user(&irq, argp, sizeof irq))
 			goto out;
 		r = kvm_vcpu_ioctl_interrupt(vcpu, &irq);
-		if (r)
-			goto out;
-		r = 0;
 		break;
 	}
 	case KVM_NMI: {
 		r = kvm_vcpu_ioctl_nmi(vcpu);
-		if (r)
-			goto out;
-		r = 0;
 		break;
 	}
 	case KVM_SET_CPUID: {
@@ -2729,8 +2719,6 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
 		if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid))
 			goto out;
 		r = kvm_vcpu_ioctl_set_cpuid(vcpu, &cpuid, cpuid_arg->entries);
-		if (r)
-			goto out;
 		break;
 	}
 	case KVM_SET_CPUID2: {
@@ -2742,8 +2730,6 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
 			goto out;
 		r = kvm_vcpu_ioctl_set_cpuid2(vcpu, &cpuid,
 					      cpuid_arg->entries);
-		if (r)
-			goto out;
 		break;
 	}
 	case KVM_GET_CPUID2: {
@@ -2875,10 +2861,8 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
 	}
 	case KVM_SET_XSAVE: {
 		u.xsave = memdup_user(argp, sizeof(*u.xsave));
-		if (IS_ERR(u.xsave)) {
-			r = PTR_ERR(u.xsave);
-			goto out;
-		}
+		if (IS_ERR(u.xsave))
+			return PTR_ERR(u.xsave);
 
 		r = kvm_vcpu_ioctl_x86_set_xsave(vcpu, u.xsave);
 		break;
@@ -2900,10 +2884,8 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
 	}
 	case KVM_SET_XCRS: {
 		u.xcrs = memdup_user(argp, sizeof(*u.xcrs));
-		if (IS_ERR(u.xcrs)) {
-			r = PTR_ERR(u.xcrs);
-			goto out;
-		}
+		if (IS_ERR(u.xcrs))
+			return PTR_ERR(u.xcrs);
 
 		r = kvm_vcpu_ioctl_x86_set_xcrs(vcpu, u.xcrs);
 		break;
@@ -2951,7 +2933,7 @@ static int kvm_vm_ioctl_set_tss_addr(struct kvm *kvm, unsigned long addr)
 	int ret;
 
 	if (addr > (unsigned int)(-3 * PAGE_SIZE))
-		return -1;
+		return -EINVAL;
 	ret = kvm_x86_ops->set_tss_addr(kvm, addr);
 	return ret;
 }
@@ -3212,8 +3194,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
 	switch (ioctl) {
 	case KVM_SET_TSS_ADDR:
 		r = kvm_vm_ioctl_set_tss_addr(kvm, arg);
-		if (r < 0)
-			goto out;
 		break;
 	case KVM_SET_IDENTITY_MAP_ADDR: {
 		u64 ident_addr;
@@ -3222,14 +3202,10 @@ long kvm_arch_vm_ioctl(struct file *filp,
 		if (copy_from_user(&ident_addr, argp, sizeof ident_addr))
 			goto out;
 		r = kvm_vm_ioctl_set_identity_map_addr(kvm, ident_addr);
-		if (r < 0)
-			goto out;
 		break;
 	}
 	case KVM_SET_NR_MMU_PAGES:
 		r = kvm_vm_ioctl_set_nr_mmu_pages(kvm, arg);
-		if (r)
-			goto out;
 		break;
 	case KVM_GET_NR_MMU_PAGES:
 		r = kvm_vm_ioctl_get_nr_mmu_pages(kvm);
@@ -3320,8 +3296,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
 		r = 0;
 	get_irqchip_out:
 		kfree(chip);
-		if (r)
-			goto out;
 		break;
 	}
 	case KVM_SET_IRQCHIP: {
@@ -3343,8 +3317,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
 		r = 0;
 	set_irqchip_out:
 		kfree(chip);
-		if (r)
-			goto out;
 		break;
 	}
 	case KVM_GET_PIT: {
@@ -3371,9 +3343,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
 		if (!kvm->arch.vpit)
 			goto out;
 		r = kvm_vm_ioctl_set_pit(kvm, &u.ps);
-		if (r)
-			goto out;
-		r = 0;
 		break;
 	}
 	case KVM_GET_PIT2: {
@@ -3397,9 +3366,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
 		if (!kvm->arch.vpit)
 			goto out;
 		r = kvm_vm_ioctl_set_pit2(kvm, &u.ps2);
-		if (r)
-			goto out;
-		r = 0;
 		break;
 	}
 	case KVM_REINJECT_CONTROL: {
@@ -3408,9 +3374,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
 		if (copy_from_user(&control, argp, sizeof(control)))
 			goto out;
 		r = kvm_vm_ioctl_reinject(kvm, &control);
-		if (r)
-			goto out;
-		r = 0;
 		break;
 	}
 	case KVM_XEN_HVM_CONFIG: {
@@ -4495,7 +4458,7 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t gva)
 	 * instruction -> ...
 	 */
 	pfn = gfn_to_pfn(vcpu->kvm, gpa_to_gfn(gpa));
-	if (!is_error_pfn(pfn)) {
+	if (!is_error_noslot_pfn(pfn)) {
 		kvm_release_pfn_clean(pfn);
 		return true;
 	}
@@ -5059,7 +5022,7 @@ out:
 }
 EXPORT_SYMBOL_GPL(kvm_emulate_hypercall);
 
-int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt)
+static int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt)
 {
 	struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
 	char instruction[3];
@@ -5419,7 +5382,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
 		pr_debug("vcpu %d received sipi with vector # %x\n",
 			 vcpu->vcpu_id, vcpu->arch.sipi_vector);
 		kvm_lapic_reset(vcpu);
-		r = kvm_arch_vcpu_reset(vcpu);
+		r = kvm_vcpu_reset(vcpu);
 		if (r)
 			return r;
 		vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
@@ -6047,7 +6010,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 	r = vcpu_load(vcpu);
 	if (r)
 		return r;
-	r = kvm_arch_vcpu_reset(vcpu);
+	r = kvm_vcpu_reset(vcpu);
 	if (r == 0)
 		r = kvm_mmu_setup(vcpu);
 	vcpu_put(vcpu);
@@ -6069,7 +6032,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 	kvm_x86_ops->vcpu_free(vcpu);
 }
 
-int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu)
+static int kvm_vcpu_reset(struct kvm_vcpu *vcpu)
 {
 	atomic_set(&vcpu->arch.nmi_queued, 0);
 	vcpu->arch.nmi_pending = 0;
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 642d880..df4176c 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -1412,7 +1412,7 @@ __init void lguest_init(void)
 
 	/* We don't have features.  We have puppies!  Puppies! */
 #ifdef CONFIG_X86_MCE
-	mce_disabled = 1;
+	mca_cfg.disabled = true;
 #endif
 #ifdef CONFIG_ACPI
 	acpi_disabled = 1;
diff --git a/arch/x86/lib/copy_page_64.S b/arch/x86/lib/copy_page_64.S
index 6b34d04..176cca6 100644
--- a/arch/x86/lib/copy_page_64.S
+++ b/arch/x86/lib/copy_page_64.S
@@ -5,91 +5,89 @@
 #include <asm/alternative-asm.h>
 
 	ALIGN
-copy_page_c:
+copy_page_rep:
 	CFI_STARTPROC
-	movl $4096/8,%ecx
-	rep movsq
+	movl	$4096/8, %ecx
+	rep	movsq
 	ret
 	CFI_ENDPROC
-ENDPROC(copy_page_c)
+ENDPROC(copy_page_rep)
 
-/* Don't use streaming store because it's better when the target
-   ends up in cache. */
-	    
-/* Could vary the prefetch distance based on SMP/UP */
+/*
+ *  Don't use streaming copy unless the CPU indicates X86_FEATURE_REP_GOOD.
+ *  Could vary the prefetch distance based on SMP/UP.
+*/
 
 ENTRY(copy_page)
 	CFI_STARTPROC
-	subq	$2*8,%rsp
+	subq	$2*8,	%rsp
 	CFI_ADJUST_CFA_OFFSET 2*8
-	movq	%rbx,(%rsp)
+	movq	%rbx,	(%rsp)
 	CFI_REL_OFFSET rbx, 0
-	movq	%r12,1*8(%rsp)
+	movq	%r12,	1*8(%rsp)
 	CFI_REL_OFFSET r12, 1*8
 
-	movl	$(4096/64)-5,%ecx
+	movl	$(4096/64)-5,	%ecx
 	.p2align 4
 .Loop64:
-  	dec     %rcx
-
-	movq        (%rsi), %rax
-	movq      8 (%rsi), %rbx
-	movq     16 (%rsi), %rdx
-	movq     24 (%rsi), %r8
-	movq     32 (%rsi), %r9
-	movq     40 (%rsi), %r10
-	movq     48 (%rsi), %r11
-	movq     56 (%rsi), %r12
+	dec	%rcx
+	movq	0x8*0(%rsi), %rax
+	movq	0x8*1(%rsi), %rbx
+	movq	0x8*2(%rsi), %rdx
+	movq	0x8*3(%rsi), %r8
+	movq	0x8*4(%rsi), %r9
+	movq	0x8*5(%rsi), %r10
+	movq	0x8*6(%rsi), %r11
+	movq	0x8*7(%rsi), %r12
 
 	prefetcht0 5*64(%rsi)
 
-	movq     %rax,    (%rdi)
-	movq     %rbx,  8 (%rdi)
-	movq     %rdx, 16 (%rdi)
-	movq     %r8,  24 (%rdi)
-	movq     %r9,  32 (%rdi)
-	movq     %r10, 40 (%rdi)
-	movq     %r11, 48 (%rdi)
-	movq     %r12, 56 (%rdi)
+	movq	%rax, 0x8*0(%rdi)
+	movq	%rbx, 0x8*1(%rdi)
+	movq	%rdx, 0x8*2(%rdi)
+	movq	%r8,  0x8*3(%rdi)
+	movq	%r9,  0x8*4(%rdi)
+	movq	%r10, 0x8*5(%rdi)
+	movq	%r11, 0x8*6(%rdi)
+	movq	%r12, 0x8*7(%rdi)
 
-	leaq    64 (%rsi), %rsi
-	leaq    64 (%rdi), %rdi
+	leaq	64 (%rsi), %rsi
+	leaq	64 (%rdi), %rdi
 
-	jnz     .Loop64
+	jnz	.Loop64
 
-	movl	$5,%ecx
+	movl	$5, %ecx
 	.p2align 4
 .Loop2:
-	decl   %ecx
-
-	movq        (%rsi), %rax
-	movq      8 (%rsi), %rbx
-	movq     16 (%rsi), %rdx
-	movq     24 (%rsi), %r8
-	movq     32 (%rsi), %r9
-	movq     40 (%rsi), %r10
-	movq     48 (%rsi), %r11
-	movq     56 (%rsi), %r12
-
-	movq     %rax,    (%rdi)
-	movq     %rbx,  8 (%rdi)
-	movq     %rdx, 16 (%rdi)
-	movq     %r8,  24 (%rdi)
-	movq     %r9,  32 (%rdi)
-	movq     %r10, 40 (%rdi)
-	movq     %r11, 48 (%rdi)
-	movq     %r12, 56 (%rdi)
-
-	leaq	64(%rdi),%rdi
-	leaq	64(%rsi),%rsi
-
+	decl	%ecx
+
+	movq	0x8*0(%rsi), %rax
+	movq	0x8*1(%rsi), %rbx
+	movq	0x8*2(%rsi), %rdx
+	movq	0x8*3(%rsi), %r8
+	movq	0x8*4(%rsi), %r9
+	movq	0x8*5(%rsi), %r10
+	movq	0x8*6(%rsi), %r11
+	movq	0x8*7(%rsi), %r12
+
+	movq	%rax, 0x8*0(%rdi)
+	movq	%rbx, 0x8*1(%rdi)
+	movq	%rdx, 0x8*2(%rdi)
+	movq	%r8,  0x8*3(%rdi)
+	movq	%r9,  0x8*4(%rdi)
+	movq	%r10, 0x8*5(%rdi)
+	movq	%r11, 0x8*6(%rdi)
+	movq	%r12, 0x8*7(%rdi)
+
+	leaq	64(%rdi), %rdi
+	leaq	64(%rsi), %rsi
 	jnz	.Loop2
 
-	movq	(%rsp),%rbx
+	movq	(%rsp), %rbx
 	CFI_RESTORE rbx
-	movq	1*8(%rsp),%r12
+	movq	1*8(%rsp), %r12
 	CFI_RESTORE r12
-	addq	$2*8,%rsp
+	addq	$2*8, %rsp
 	CFI_ADJUST_CFA_OFFSET -2*8
 	ret
 .Lcopy_page_end:
@@ -103,7 +101,7 @@ ENDPROC(copy_page)
 
 	.section .altinstr_replacement,"ax"
 1:	.byte 0xeb					/* jmp <disp8> */
-	.byte (copy_page_c - copy_page) - (2f - 1b)	/* offset */
+	.byte (copy_page_rep - copy_page) - (2f - 1b)	/* offset */
 2:
 	.previous
 	.section .altinstructions,"a"
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 8e13ecb..513f924 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -18,7 +18,7 @@
 #include <asm/pgalloc.h>		/* pgd_*(), ...			*/
 #include <asm/kmemcheck.h>		/* kmemcheck_*(), ...		*/
 #include <asm/fixmap.h>			/* VSYSCALL_START		*/
-#include <asm/rcu.h>			/* exception_enter(), ...	*/
+#include <asm/context_tracking.h>		/* exception_enter(), ...	*/
 
 /*
  * Page fault error code bits:
@@ -803,20 +803,6 @@ bad_area_access_error(struct pt_regs *regs, unsigned long error_code,
 	__bad_area(regs, error_code, address, SEGV_ACCERR);
 }
 
-/* TODO: fixup for "mm-invoke-oom-killer-from-page-fault.patch" */
-static void
-out_of_memory(struct pt_regs *regs, unsigned long error_code,
-	      unsigned long address)
-{
-	/*
-	 * We ran out of memory, call the OOM killer, and return the userspace
-	 * (which will retry the fault, or kill us if we got oom-killed):
-	 */
-	up_read(&current->mm->mmap_sem);
-
-	pagefault_out_of_memory();
-}
-
 static void
 do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
 	  unsigned int fault)
@@ -879,7 +865,14 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
 			return 1;
 		}
 
-		out_of_memory(regs, error_code, address);
+		up_read(&current->mm->mmap_sem);
+
+		/*
+		 * We ran out of memory, call the OOM killer, and return the
+		 * userspace (which will retry the fault, or kill us if we got
+		 * oom-killed):
+		 */
+		pagefault_out_of_memory();
 	} else {
 		if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
 			     VM_FAULT_HWPOISON_LARGE))
diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c
index dd74e46..6dc9921 100644
--- a/arch/x86/mm/gup.c
+++ b/arch/x86/mm/gup.c
@@ -150,7 +150,13 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
 
 	pmdp = pmd_offset(&pud, addr);
 	do {
-		pmd_t pmd = *pmdp;
+		/*
+		 * With THP and hugetlbfs the pmd can change from
+		 * under us and it can be cleared as well by the TLB
+		 * shootdown, so read it with ACCESS_ONCE to do all
+		 * computations on the same sampling.
+		 */
+		pmd_t pmd = ACCESS_ONCE(*pmdp);
 
 		next = pmd_addr_end(addr, end);
 		/*
@@ -220,7 +226,13 @@ static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end,
 
 	pudp = pud_offset(&pgd, addr);
 	do {
-		pud_t pud = *pudp;
+		/*
+		 * With hugetlbfs giga pages the pud can change from
+		 * under us and it can be cleared as well by the TLB
+		 * shootdown, so read it with ACCESS_ONCE to do all
+		 * computations on the same sampling.
+		 */
+		pud_t pud = ACCESS_ONCE(*pudp);
 
 		next = pud_addr_end(addr, end);
 		if (pud_none(pud))
@@ -280,7 +292,12 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
 	local_irq_save(flags);
 	pgdp = pgd_offset(mm, addr);
 	do {
-		pgd_t pgd = *pgdp;
+		/*
+		 * The pgd could be cleared by the TLB shootdown from
+		 * under us so read it with ACCESS_ONCE to do all
+		 * computations on the same sampling.
+		 */
+		pgd_t pgd = ACCESS_ONCE(*pgdp);
 
 		next = pgd_addr_end(addr, end);
 		if (pgd_none(pgd))
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index 937bff5..ae1aa71 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -274,42 +274,15 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
 		unsigned long pgoff, unsigned long flags)
 {
 	struct hstate *h = hstate_file(file);
-	struct mm_struct *mm = current->mm;
-	struct vm_area_struct *vma;
-	unsigned long start_addr;
-
-	if (len > mm->cached_hole_size) {
-	        start_addr = mm->free_area_cache;
-	} else {
-	        start_addr = TASK_UNMAPPED_BASE;
-	        mm->cached_hole_size = 0;
-	}
-
-full_search:
-	addr = ALIGN(start_addr, huge_page_size(h));
-
-	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
-		/* At this point:  (!vma || addr < vma->vm_end). */
-		if (TASK_SIZE - len < addr) {
-			/*
-			 * Start a new search - just in case we missed
-			 * some holes.
-			 */
-			if (start_addr != TASK_UNMAPPED_BASE) {
-				start_addr = TASK_UNMAPPED_BASE;
-				mm->cached_hole_size = 0;
-				goto full_search;
-			}
-			return -ENOMEM;
-		}
-		if (!vma || addr + len <= vma->vm_start) {
-			mm->free_area_cache = addr + len;
-			return addr;
-		}
-		if (addr + mm->cached_hole_size < vma->vm_start)
-		        mm->cached_hole_size = vma->vm_start - addr;
-		addr = ALIGN(vma->vm_end, huge_page_size(h));
-	}
+	struct vm_unmapped_area_info info;
+
+	info.flags = 0;
+	info.length = len;
+	info.low_limit = TASK_UNMAPPED_BASE;
+	info.high_limit = TASK_SIZE;
+	info.align_mask = PAGE_MASK & ~huge_page_mask(h);
+	info.align_offset = 0;
+	return vm_unmapped_area(&info);
 }
 
 static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
@@ -317,83 +290,30 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
 		unsigned long pgoff, unsigned long flags)
 {
 	struct hstate *h = hstate_file(file);
-	struct mm_struct *mm = current->mm;
-	struct vm_area_struct *vma;
-	unsigned long base = mm->mmap_base;
-	unsigned long addr = addr0;
-	unsigned long largest_hole = mm->cached_hole_size;
-	unsigned long start_addr;
-
-	/* don't allow allocations above current base */
-	if (mm->free_area_cache > base)
-		mm->free_area_cache = base;
-
-	if (len <= largest_hole) {
-	        largest_hole = 0;
-		mm->free_area_cache  = base;
-	}
-try_again:
-	start_addr = mm->free_area_cache;
-
-	/* make sure it can fit in the remaining address space */
-	if (mm->free_area_cache < len)
-		goto fail;
-
-	/* either no address requested or can't fit in requested address hole */
-	addr = (mm->free_area_cache - len) & huge_page_mask(h);
-	do {
-		/*
-		 * Lookup failure means no vma is above this address,
-		 * i.e. return with success:
-		 */
-		vma = find_vma(mm, addr);
-		if (!vma)
-			return addr;
+	struct vm_unmapped_area_info info;
+	unsigned long addr;
 
-		if (addr + len <= vma->vm_start) {
-			/* remember the address as a hint for next time */
-		        mm->cached_hole_size = largest_hole;
-		        return (mm->free_area_cache = addr);
-		} else if (mm->free_area_cache == vma->vm_end) {
-			/* pull free_area_cache down to the first hole */
-			mm->free_area_cache = vma->vm_start;
-			mm->cached_hole_size = largest_hole;
-		}
+	info.flags = VM_UNMAPPED_AREA_TOPDOWN;
+	info.length = len;
+	info.low_limit = PAGE_SIZE;
+	info.high_limit = current->mm->mmap_base;
+	info.align_mask = PAGE_MASK & ~huge_page_mask(h);
+	info.align_offset = 0;
+	addr = vm_unmapped_area(&info);
 
-		/* remember the largest hole we saw so far */
-		if (addr + largest_hole < vma->vm_start)
-		        largest_hole = vma->vm_start - addr;
-
-		/* try just below the current vma->vm_start */
-		addr = (vma->vm_start - len) & huge_page_mask(h);
-	} while (len <= vma->vm_start);
-
-fail:
-	/*
-	 * if hint left us with no space for the requested
-	 * mapping then try again:
-	 */
-	if (start_addr != base) {
-		mm->free_area_cache = base;
-		largest_hole = 0;
-		goto try_again;
-	}
 	/*
 	 * A failed mmap() very likely causes application failure,
 	 * so fall back to the bottom-up function here. This scenario
 	 * can happen with large stack limits and large mmap()
 	 * allocations.
 	 */
-	mm->free_area_cache = TASK_UNMAPPED_BASE;
-	mm->cached_hole_size = ~0UL;
-	addr = hugetlb_get_unmapped_area_bottomup(file, addr0,
-			len, pgoff, flags);
-
-	/*
-	 * Restore the topdown base:
-	 */
-	mm->free_area_cache = base;
-	mm->cached_hole_size = ~0UL;
+	if (addr & ~PAGE_MASK) {
+		VM_BUG_ON(addr != -ENOMEM);
+		info.flags = 0;
+		info.low_limit = TASK_UNMAPPED_BASE;
+		info.high_limit = TASK_SIZE;
+		addr = vm_unmapped_area(&info);
+	}
 
 	return addr;
 }
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 3baff25..cd85e09 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -605,7 +605,7 @@ kernel_physical_mapping_init(unsigned long start,
 	}
 
 	if (pgd_changed)
-		sync_global_pgds(addr, end);
+		sync_global_pgds(addr, end - 1);
 
 	__flush_tlb_all();
 
@@ -630,7 +630,9 @@ void __init paging_init(void)
 	 *	 numa support is not compiled in, and later node_set_state
 	 *	 will not set it back.
 	 */
-	node_clear_state(0, N_NORMAL_MEMORY);
+	node_clear_state(0, N_MEMORY);
+	if (N_MEMORY != N_NORMAL_MEMORY)
+		node_clear_state(0, N_NORMAL_MEMORY);
 
 	zone_sizes_init();
 }
@@ -770,12 +772,10 @@ void set_kernel_text_ro(void)
 void mark_rodata_ro(void)
 {
 	unsigned long start = PFN_ALIGN(_text);
-	unsigned long rodata_start =
-		((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK;
+	unsigned long rodata_start = PFN_ALIGN(__start_rodata);
 	unsigned long end = (unsigned long) &__end_rodata_hpage_align;
-	unsigned long text_end = PAGE_ALIGN((unsigned long) &__stop___ex_table);
-	unsigned long rodata_end = PAGE_ALIGN((unsigned long) &__end_rodata);
-	unsigned long data_start = (unsigned long) &_sdata;
+	unsigned long text_end = PFN_ALIGN(&__stop___ex_table);
+	unsigned long rodata_end = PFN_ALIGN(&__end_rodata);
 
 	printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
 	       (end - start) >> 10);
@@ -800,12 +800,12 @@ void mark_rodata_ro(void)
 #endif
 
 	free_init_pages("unused kernel memory",
-			(unsigned long) page_address(virt_to_page(text_end)),
-			(unsigned long)
-				 page_address(virt_to_page(rodata_start)));
+			(unsigned long) __va(__pa_symbol(text_end)),
+			(unsigned long) __va(__pa_symbol(rodata_start)));
+
 	free_init_pages("unused kernel memory",
-			(unsigned long) page_address(virt_to_page(rodata_end)),
-			(unsigned long) page_address(virt_to_page(data_start)));
+			(unsigned long) __va(__pa_symbol(rodata_end)),
+			(unsigned long) __va(__pa_symbol(_sdata)));
 }
 
 #endif
@@ -979,7 +979,7 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node)
 		}
 
 	}
-	sync_global_pgds((unsigned long)start_page, end);
+	sync_global_pgds((unsigned long)start_page, end - 1);
 	return 0;
 }
 
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
index 2d125be..21d02f0 100644
--- a/arch/x86/mm/numa.c
+++ b/arch/x86/mm/numa.c
@@ -97,8 +97,7 @@ void __cpuinit numa_set_node(int cpu, int node)
 #endif
 	per_cpu(x86_cpu_to_node_map, cpu) = node;
 
-	if (node != NUMA_NO_NODE)
-		set_cpu_numa_node(cpu, node);
+	set_cpu_numa_node(cpu, node);
 }
 
 void __cpuinit numa_clear_node(int cpu)
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index a718e0d..40f92f3 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -94,12 +94,12 @@ static inline void split_page_count(int level) { }
 
 static inline unsigned long highmap_start_pfn(void)
 {
-	return __pa(_text) >> PAGE_SHIFT;
+	return __pa_symbol(_text) >> PAGE_SHIFT;
 }
 
 static inline unsigned long highmap_end_pfn(void)
 {
-	return __pa(roundup(_brk_end, PMD_SIZE)) >> PAGE_SHIFT;
+	return __pa_symbol(roundup(_brk_end, PMD_SIZE)) >> PAGE_SHIFT;
 }
 
 #endif
@@ -276,8 +276,8 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address,
 	 * The .rodata section needs to be read-only. Using the pfn
 	 * catches all aliases.
 	 */
-	if (within(pfn, __pa((unsigned long)__start_rodata) >> PAGE_SHIFT,
-		   __pa((unsigned long)__end_rodata) >> PAGE_SHIFT))
+	if (within(pfn, __pa_symbol(__start_rodata) >> PAGE_SHIFT,
+		   __pa_symbol(__end_rodata) >> PAGE_SHIFT))
 		pgprot_val(forbidden) |= _PAGE_RW;
 
 #if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA)
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index 8573b83..7353de3 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -301,6 +301,13 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 	free_page((unsigned long)pgd);
 }
 
+/*
+ * Used to set accessed or dirty bits in the page table entries
+ * on other architectures. On x86, the accessed and dirty bits
+ * are tracked by hardware. However, do_wp_page calls this function
+ * to also make the pte writeable at the same time the dirty bit is
+ * set. In that case we do actually need to write the PTE.
+ */
 int ptep_set_access_flags(struct vm_area_struct *vma,
 			  unsigned long address, pte_t *ptep,
 			  pte_t entry, int dirty)
@@ -310,7 +317,6 @@ int ptep_set_access_flags(struct vm_area_struct *vma,
 	if (changed && dirty) {
 		*ptep = entry;
 		pte_update_defer(vma->vm_mm, address, ptep);
-		flush_tlb_page(vma, address);
 	}
 
 	return changed;
diff --git a/arch/x86/mm/physaddr.c b/arch/x86/mm/physaddr.c
index d2e2735..c73fedd 100644
--- a/arch/x86/mm/physaddr.c
+++ b/arch/x86/mm/physaddr.c
@@ -8,33 +8,54 @@
 
 #ifdef CONFIG_X86_64
 
+#ifdef CONFIG_DEBUG_VIRTUAL
 unsigned long __phys_addr(unsigned long x)
 {
-	if (x >= __START_KERNEL_map) {
-		x -= __START_KERNEL_map;
-		VIRTUAL_BUG_ON(x >= KERNEL_IMAGE_SIZE);
-		x += phys_base;
+	unsigned long y = x - __START_KERNEL_map;
+
+	/* use the carry flag to determine if x was < __START_KERNEL_map */
+	if (unlikely(x > y)) {
+		x = y + phys_base;
+
+		VIRTUAL_BUG_ON(y >= KERNEL_IMAGE_SIZE);
 	} else {
-		VIRTUAL_BUG_ON(x < PAGE_OFFSET);
-		x -= PAGE_OFFSET;
-		VIRTUAL_BUG_ON(!phys_addr_valid(x));
+		x = y + (__START_KERNEL_map - PAGE_OFFSET);
+
+		/* carry flag will be set if starting x was >= PAGE_OFFSET */
+		VIRTUAL_BUG_ON((x > y) || !phys_addr_valid(x));
 	}
+
 	return x;
 }
 EXPORT_SYMBOL(__phys_addr);
 
+unsigned long __phys_addr_symbol(unsigned long x)
+{
+	unsigned long y = x - __START_KERNEL_map;
+
+	/* only check upper bounds since lower bounds will trigger carry */
+	VIRTUAL_BUG_ON(y >= KERNEL_IMAGE_SIZE);
+
+	return y + phys_base;
+}
+EXPORT_SYMBOL(__phys_addr_symbol);
+#endif
+
 bool __virt_addr_valid(unsigned long x)
 {
-	if (x >= __START_KERNEL_map) {
-		x -= __START_KERNEL_map;
-		if (x >= KERNEL_IMAGE_SIZE)
+	unsigned long y = x - __START_KERNEL_map;
+
+	/* use the carry flag to determine if x was < __START_KERNEL_map */
+	if (unlikely(x > y)) {
+		x = y + phys_base;
+
+		if (y >= KERNEL_IMAGE_SIZE)
 			return false;
-		x += phys_base;
 	} else {
-		if (x < PAGE_OFFSET)
-			return false;
-		x -= PAGE_OFFSET;
-		if (!phys_addr_valid(x))
+		x = y + (__START_KERNEL_map - PAGE_OFFSET);
+
+		/* carry flag will be set if starting x was >= PAGE_OFFSET */
+		if ((x > y) || !phys_addr_valid(x))
 			return false;
 	}
 
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 520d2bd..d11a470 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -11,6 +11,7 @@
 #include <asm/cacheflush.h>
 #include <linux/netdevice.h>
 #include <linux/filter.h>
+#include <linux/if_vlan.h>
 
 /*
  * Conventions :
@@ -212,6 +213,8 @@ void bpf_jit_compile(struct sk_filter *fp)
 		case BPF_S_ANC_MARK:
 		case BPF_S_ANC_RXHASH:
 		case BPF_S_ANC_CPU:
+		case BPF_S_ANC_VLAN_TAG:
+		case BPF_S_ANC_VLAN_TAG_PRESENT:
 		case BPF_S_ANC_QUEUE:
 		case BPF_S_LD_W_ABS:
 		case BPF_S_LD_H_ABS:
@@ -515,6 +518,24 @@ void bpf_jit_compile(struct sk_filter *fp)
 				CLEAR_A();
 #endif
 				break;
+			case BPF_S_ANC_VLAN_TAG:
+			case BPF_S_ANC_VLAN_TAG_PRESENT:
+				BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
+				if (is_imm8(offsetof(struct sk_buff, vlan_tci))) {
+					/* movzwl off8(%rdi),%eax */
+					EMIT4(0x0f, 0xb7, 0x47, offsetof(struct sk_buff, vlan_tci));
+				} else {
+					EMIT3(0x0f, 0xb7, 0x87); /* movzwl off32(%rdi),%eax */
+					EMIT(offsetof(struct sk_buff, vlan_tci), 4);
+				}
+				BUILD_BUG_ON(VLAN_TAG_PRESENT != 0x1000);
+				if (filter[i].code == BPF_S_ANC_VLAN_TAG) {
+					EMIT3(0x80, 0xe4, 0xef); /* and    $0xef,%ah */
+				} else {
+					EMIT3(0xc1, 0xe8, 0x0c); /* shr    $0xc,%eax */
+					EMIT3(0x83, 0xe0, 0x01); /* and    $0x1,%eax */
+				}
+				break;
 			case BPF_S_LD_W_ABS:
 				func = CHOOSE_LOAD_FUNC(K, sk_load_word);
 common_load:			seen |= SEEN_DATAREF;
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 192397c..0c01261 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -12,6 +12,7 @@ struct pci_root_info {
 	char name[16];
 	unsigned int res_num;
 	struct resource *res;
+	resource_size_t *res_offset;
 	struct pci_sysdata sd;
 #ifdef	CONFIG_PCI_MMCONFIG
 	bool mcfg_added;
@@ -22,6 +23,7 @@ struct pci_root_info {
 };
 
 static bool pci_use_crs = true;
+static bool pci_ignore_seg = false;
 
 static int __init set_use_crs(const struct dmi_system_id *id)
 {
@@ -35,7 +37,14 @@ static int __init set_nouse_crs(const struct dmi_system_id *id)
 	return 0;
 }
 
-static const struct dmi_system_id pci_use_crs_table[] __initconst = {
+static int __init set_ignore_seg(const struct dmi_system_id *id)
+{
+	printk(KERN_INFO "PCI: %s detected: ignoring ACPI _SEG\n", id->ident);
+	pci_ignore_seg = true;
+	return 0;
+}
+
+static const struct dmi_system_id pci_crs_quirks[] __initconst = {
 	/* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */
 	{
 		.callback = set_use_crs,
@@ -98,6 +107,16 @@ static const struct dmi_system_id pci_use_crs_table[] __initconst = {
 			DMI_MATCH(DMI_BIOS_VERSION, "6JET85WW (1.43 )"),
 		},
 	},
+
+	/* https://bugzilla.kernel.org/show_bug.cgi?id=15362 */
+	{
+		.callback = set_ignore_seg,
+		.ident = "HP xw9300",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP xw9300 Workstation"),
+		},
+	},
 	{}
 };
 
@@ -108,7 +127,7 @@ void __init pci_acpi_crs_quirks(void)
 	if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008)
 		pci_use_crs = false;
 
-	dmi_check_system(pci_use_crs_table);
+	dmi_check_system(pci_crs_quirks);
 
 	/*
 	 * If the user specifies "pci=use_crs" or "pci=nocrs" explicitly, that
@@ -305,6 +324,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
 	res->flags = flags;
 	res->start = start;
 	res->end = end;
+	info->res_offset[info->res_num] = addr.translation_offset;
 
 	if (!pci_use_crs) {
 		dev_printk(KERN_DEBUG, &info->bridge->dev,
@@ -374,7 +394,8 @@ static void add_resources(struct pci_root_info *info,
 				 "ignoring host bridge window %pR (conflicts with %s %pR)\n",
 				 res, conflict->name, conflict);
 		else
-			pci_add_resource(resources, res);
+			pci_add_resource_offset(resources, res,
+					info->res_offset[i]);
 	}
 }
 
@@ -382,6 +403,8 @@ static void free_pci_root_info_res(struct pci_root_info *info)
 {
 	kfree(info->res);
 	info->res = NULL;
+	kfree(info->res_offset);
+	info->res_offset = NULL;
 	info->res_num = 0;
 }
 
@@ -432,10 +455,20 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
 		return;
 
 	size = sizeof(*info->res) * info->res_num;
-	info->res_num = 0;
 	info->res = kzalloc(size, GFP_KERNEL);
-	if (!info->res)
+	if (!info->res) {
+		info->res_num = 0;
+		return;
+	}
+
+	size = sizeof(*info->res_offset) * info->res_num;
+	info->res_num = 0;
+	info->res_offset = kzalloc(size, GFP_KERNEL);
+	if (!info->res_offset) {
+		kfree(info->res);
+		info->res = NULL;
 		return;
+	}
 
 	acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
 				info);
@@ -455,6 +488,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
 	int pxm;
 #endif
 
+	if (pci_ignore_seg)
+		domain = 0;
+
 	if (domain && !pci_domains_supported) {
 		printk(KERN_WARNING "pci_bus %04x:%02x: "
 		       "ignored (multiple domains not supported)\n",
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 720e973f..52dbf1a 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -626,7 +626,7 @@ void pcibios_disable_device (struct pci_dev *dev)
 		pcibios_disable_irq(dev);
 }
 
-int pci_ext_cfg_avail(struct pci_dev *dev)
+int pci_ext_cfg_avail(void)
 {
 	if (raw_pci_ext_ops)
 		return 1;
diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c
index 92525cb..f8ab494 100644
--- a/arch/x86/platform/ce4100/ce4100.c
+++ b/arch/x86/platform/ce4100/ce4100.c
@@ -105,8 +105,11 @@ static void ce4100_serial_fixup(int port, struct uart_port *up,
 		up->membase =
 			(void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
 		up->membase += up->mapbase & ~PAGE_MASK;
+		up->mapbase += port * 0x100;
+		up->membase += port * 0x100;
 		up->iotype   = UPIO_MEM32;
 		up->regshift = 2;
+		up->irq = 4;
 	}
 #endif
 	up->iobase = 0;
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index ad44391..92e4bc3 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -314,10 +314,17 @@ static void __init do_add_efi_memmap(void)
 		int e820_type;
 
 		switch (md->type) {
-		case EFI_LOADER_CODE:
-		case EFI_LOADER_DATA:
 		case EFI_BOOT_SERVICES_CODE:
 		case EFI_BOOT_SERVICES_DATA:
+			/* EFI_BOOT_SERVICES_{CODE,DATA} needs to be mapped */
+			if (md->attribute & EFI_MEMORY_WB)
+				e820_type = E820_RAM;
+			else
+				e820_type = E820_RESERVED;
+			e820_add_region(start, size, e820_type);
+			continue;
+		case EFI_LOADER_CODE:
+		case EFI_LOADER_DATA:
 		case EFI_CONVENTIONAL_MEMORY:
 			if (md->attribute & EFI_MEMORY_WB)
 				e820_type = E820_RAM;
@@ -342,7 +349,7 @@ static void __init do_add_efi_memmap(void)
 			e820_type = E820_RESERVED;
 			break;
 		}
-		e820_add_region(start, size, e820_type);
+		e820_add_limit_region(start, size, e820_type);
 	}
 	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 }
@@ -410,8 +417,8 @@ void __init efi_reserve_boot_services(void)
 		 * - Not within any part of the kernel
 		 * - Not the bios reserved area
 		*/
-		if ((start+size >= virt_to_phys(_text)
-				&& start <= virt_to_phys(_end)) ||
+		if ((start+size >= __pa_symbol(_text)
+				&& start <= __pa_symbol(_end)) ||
 			!e820_all_mapped(start, start+size, E820_RAM) ||
 			memblock_is_region_reserved(start, size)) {
 			/* Could not reserve, skip it */
@@ -448,6 +455,8 @@ void __init efi_free_boot_services(void)
 		    md->type != EFI_BOOT_SERVICES_DATA)
 			continue;
 
+		e820_adjust_region(&start, &size);
+
 		/* Could not reserve boot area */
 		if (!size)
 			continue;
diff --git a/arch/x86/platform/iris/iris.c b/arch/x86/platform/iris/iris.c
index 5917eb5..e6cb80f 100644
--- a/arch/x86/platform/iris/iris.c
+++ b/arch/x86/platform/iris/iris.c
@@ -23,6 +23,7 @@
 
 #include <linux/moduleparam.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
@@ -62,29 +63,75 @@ static void iris_power_off(void)
  * by reading its input port and seeing whether the read value is
  * meaningful.
  */
-static int iris_init(void)
+static int iris_probe(struct platform_device *pdev)
 {
-	unsigned char status;
-	if (force != 1) {
-		printk(KERN_ERR "The force parameter has not been set to 1 so the Iris poweroff handler will not be installed.\n");
-		return -ENODEV;
-	}
-	status = inb(IRIS_GIO_INPUT);
+	unsigned char status = inb(IRIS_GIO_INPUT);
 	if (status == IRIS_GIO_NODEV) {
-		printk(KERN_ERR "This machine does not seem to be an Iris. Power_off handler not installed.\n");
+		printk(KERN_ERR "This machine does not seem to be an Iris. "
+			"Power off handler not installed.\n");
 		return -ENODEV;
 	}
 	old_pm_power_off = pm_power_off;
 	pm_power_off = &iris_power_off;
 	printk(KERN_INFO "Iris power_off handler installed.\n");
-
 	return 0;
 }
 
-static void iris_exit(void)
+static int iris_remove(struct platform_device *pdev)
 {
 	pm_power_off = old_pm_power_off;
 	printk(KERN_INFO "Iris power_off handler uninstalled.\n");
+	return 0;
+}
+
+static struct platform_driver iris_driver = {
+	.driver		= {
+		.name   = "iris",
+		.owner  = THIS_MODULE,
+	},
+	.probe          = iris_probe,
+	.remove         = iris_remove,
+};
+
+static struct resource iris_resources[] = {
+	{
+		.start  = IRIS_GIO_BASE,
+		.end    = IRIS_GIO_OUTPUT,
+		.flags  = IORESOURCE_IO,
+		.name   = "address"
+	}
+};
+
+static struct platform_device *iris_device;
+
+static int iris_init(void)
+{
+	int ret;
+	if (force != 1) {
+		printk(KERN_ERR "The force parameter has not been set to 1."
+			" The Iris poweroff handler will not be installed.\n");
+		return -ENODEV;
+	}
+	ret = platform_driver_register(&iris_driver);
+	if (ret < 0) {
+		printk(KERN_ERR "Failed to register iris platform driver: %d\n",
+			ret);
+		return ret;
+	}
+	iris_device = platform_device_register_simple("iris", (-1),
+				iris_resources, ARRAY_SIZE(iris_resources));
+	if (IS_ERR(iris_device)) {
+		printk(KERN_ERR "Failed to register iris platform device\n");
+		platform_driver_unregister(&iris_driver);
+		return PTR_ERR(iris_device);
+	}
+	return 0;
+}
+
+static void iris_exit(void)
+{
+	platform_device_unregister(iris_device);
+	platform_driver_unregister(&iris_driver);
 }
 
 module_init(iris_init);
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index b8b3a37..dbbdca5 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -1034,7 +1034,8 @@ static int set_distrib_bits(struct cpumask *flush_mask, struct bau_control *bcp,
  * globally purge translation cache of a virtual address or all TLB's
  * @cpumask: mask of all cpu's in which the address is to be removed
  * @mm: mm_struct containing virtual address range
- * @va: virtual address to be removed (or TLB_FLUSH_ALL for all TLB's on cpu)
+ * @start: start virtual address to be removed from TLB
+ * @end: end virtual address to be remove from TLB
  * @cpu: the current cpu
  *
  * This is the entry point for initiating any UV global TLB shootdown.
@@ -1056,7 +1057,7 @@ static int set_distrib_bits(struct cpumask *flush_mask, struct bau_control *bcp,
  */
 const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
 				struct mm_struct *mm, unsigned long start,
-				unsigned end, unsigned int cpu)
+				unsigned long end, unsigned int cpu)
 {
 	int locals = 0;
 	int remotes = 0;
@@ -1113,7 +1114,10 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
 
 	record_send_statistics(stat, locals, hubs, remotes, bau_desc);
 
-	bau_desc->payload.address = start;
+	if (!end || (end - start) <= PAGE_SIZE)
+		bau_desc->payload.address = start;
+	else
+		bau_desc->payload.address = TLB_FLUSH_ALL;
 	bau_desc->payload.sending_cpu = cpu;
 	/*
 	 * uv_flush_send_and_wait returns 0 if all cpu's were messaged,
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index cbca565..8045026 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -62,9 +62,9 @@ void __init setup_real_mode(void)
 		__va(real_mode_header->trampoline_header);
 
 #ifdef CONFIG_X86_32
-	trampoline_header->start = __pa(startup_32_smp);
+	trampoline_header->start = __pa_symbol(startup_32_smp);
 	trampoline_header->gdt_limit = __BOOT_DS + 7;
-	trampoline_header->gdt_base = __pa(boot_gdt);
+	trampoline_header->gdt_base = __pa_symbol(boot_gdt);
 #else
 	/*
 	 * Some AMD processors will #GP(0) if EFER.LMA is set in WRMSR
@@ -78,8 +78,8 @@ void __init setup_real_mode(void)
 	*trampoline_cr4_features = read_cr4();
 
 	trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
-	trampoline_pgd[0] = __pa(level3_ident_pgt) + _KERNPG_TABLE;
-	trampoline_pgd[511] = __pa(level3_kernel_pgt) + _KERNPG_TABLE;
+	trampoline_pgd[0] = __pa_symbol(level3_ident_pgt) + _KERNPG_TABLE;
+	trampoline_pgd[511] = __pa_symbol(level3_kernel_pgt) + _KERNPG_TABLE;
 #endif
 }
 
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
index a47103f..05f404f 100644
--- a/arch/x86/syscalls/syscall_32.tbl
+++ b/arch/x86/syscalls/syscall_32.tbl
@@ -8,7 +8,7 @@
 #
 0	i386	restart_syscall		sys_restart_syscall
 1	i386	exit			sys_exit
-2	i386	fork			ptregs_fork			stub32_fork
+2	i386	fork			sys_fork			stub32_fork
 3	i386	read			sys_read
 4	i386	write			sys_write
 5	i386	open			sys_open			compat_sys_open
@@ -126,7 +126,7 @@
 117	i386	ipc			sys_ipc				sys32_ipc
 118	i386	fsync			sys_fsync
 119	i386	sigreturn		ptregs_sigreturn		stub32_sigreturn
-120	i386	clone			ptregs_clone			stub32_clone
+120	i386	clone			sys_clone			stub32_clone
 121	i386	setdomainname		sys_setdomainname
 122	i386	uname			sys_newuname
 123	i386	modify_ldt		sys_modify_ldt
@@ -196,7 +196,7 @@
 187	i386	sendfile		sys_sendfile			sys32_sendfile
 188	i386	getpmsg
 189	i386	putpmsg
-190	i386	vfork			ptregs_vfork			stub32_vfork
+190	i386	vfork			sys_vfork			stub32_vfork
 191	i386	ugetrlimit		sys_getrlimit			compat_sys_getrlimit
 192	i386	mmap2			sys_mmap_pgoff
 193	i386	truncate64		sys_truncate64			sys32_truncate64
@@ -356,3 +356,4 @@
 347	i386	process_vm_readv	sys_process_vm_readv		compat_sys_process_vm_readv
 348	i386	process_vm_writev	sys_process_vm_writev		compat_sys_process_vm_writev
 349	i386	kcmp			sys_kcmp
+350	i386	finit_module		sys_finit_module
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl
index a582bfe..7c58c84 100644
--- a/arch/x86/syscalls/syscall_64.tbl
+++ b/arch/x86/syscalls/syscall_64.tbl
@@ -319,6 +319,7 @@
 310	64	process_vm_readv	sys_process_vm_readv
 311	64	process_vm_writev	sys_process_vm_writev
 312	common	kcmp			sys_kcmp
+313	common	finit_module		sys_finit_module
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/arch/x86/tools/insn_sanity.c b/arch/x86/tools/insn_sanity.c
index cc2f8c1..872eb60 100644
--- a/arch/x86/tools/insn_sanity.c
+++ b/arch/x86/tools/insn_sanity.c
@@ -55,7 +55,7 @@ static FILE		*input_file;	/* Input file name */
 static void usage(const char *err)
 {
 	if (err)
-		fprintf(stderr, "Error: %s\n\n", err);
+		fprintf(stderr, "%s: Error: %s\n\n", prog, err);
 	fprintf(stderr, "Usage: %s [-y|-n|-v] [-s seed[,no]] [-m max] [-i input]\n", prog);
 	fprintf(stderr, "\t-y	64bit mode\n");
 	fprintf(stderr, "\t-n	32bit mode\n");
@@ -269,7 +269,13 @@ int main(int argc, char **argv)
 		insns++;
 	}
 
-	fprintf(stdout, "%s: decoded and checked %d %s instructions with %d errors (seed:0x%x)\n", (errors) ? "Failure" : "Success", insns, (input_file) ? "given" : "random", errors, seed);
+	fprintf(stdout, "%s: %s: decoded and checked %d %s instructions with %d errors (seed:0x%x)\n",
+		prog,
+		(errors) ? "Failure" : "Success",
+		insns,
+		(input_file) ? "given" : "random",
+		errors,
+		seed);
 
 	return errors ? 1 : 0;
 }
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig
index 0761175..5fe0075 100644
--- a/arch/x86/um/Kconfig
+++ b/arch/x86/um/Kconfig
@@ -25,6 +25,7 @@ config X86_32
 	select HAVE_AOUT
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select MODULES_USE_ELF_REL
+	select CLONE_BACKWARDS
 
 config X86_64
 	def_bool 64BIT
@@ -37,9 +38,8 @@ config RWSEM_GENERIC_SPINLOCK
 	def_bool !RWSEM_XCHGADD_ALGORITHM
 
 config 3_LEVEL_PGTABLES
-	bool "Three-level pagetables (EXPERIMENTAL)" if !64BIT
+	bool "Three-level pagetables" if !64BIT
 	default 64BIT
-	depends on EXPERIMENTAL
 	help
 	Three-level pagetables will let UML have more than 4G of physical
 	memory.  All the memory that can't be mapped directly will be treated
diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c
index 232e605..812e98c 100644
--- a/arch/x86/um/sys_call_table_32.c
+++ b/arch/x86/um/sys_call_table_32.c
@@ -24,13 +24,10 @@
 
 #define old_mmap sys_old_mmap
 
-#define ptregs_fork sys_fork
 #define ptregs_iopl sys_iopl
 #define ptregs_vm86old sys_vm86old
-#define ptregs_clone i386_clone
 #define ptregs_vm86 sys_vm86
 #define ptregs_sigaltstack sys_sigaltstack
-#define ptregs_vfork sys_vfork
 
 #define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void sym(void) ;
 #include <asm/syscalls_32.h>
diff --git a/arch/x86/um/syscalls_32.c b/arch/x86/um/syscalls_32.c
index db444c7..e8bcea9 100644
--- a/arch/x86/um/syscalls_32.c
+++ b/arch/x86/um/syscalls_32.c
@@ -6,21 +6,6 @@
 #include <linux/syscalls.h>
 #include <sysdep/syscalls.h>
 
-/*
- * The prototype on i386 is:
- *
- *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls
- *
- * and the "newtls" arg. on i386 is read by copy_thread directly from the
- * register saved on the stack.
- */
-long i386_clone(unsigned long clone_flags, unsigned long newsp,
-		int __user *parent_tid, void *newtls, int __user *child_tid)
-{
-	return sys_clone(clone_flags, newsp, parent_tid, child_tid);
-}
-
-
 long sys_sigaction(int sig, const struct old_sigaction __user *act,
 			 struct old_sigaction __user *oact)
 {
diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c
index 00aaf04..431e875 100644
--- a/arch/x86/vdso/vma.c
+++ b/arch/x86/vdso/vma.c
@@ -141,7 +141,7 @@ static unsigned long vdso_addr(unsigned long start, unsigned len)
 	 * unaligned here as a result of stack start randomization.
 	 */
 	addr = PAGE_ALIGN(addr);
-	addr = align_addr(addr, NULL, ALIGN_VDSO);
+	addr = align_vdso_addr(addr);
 
 	return addr;
 }
diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
index fdce49c..7e938ba 100644
--- a/arch/x86/xen/Kconfig
+++ b/arch/x86/xen/Kconfig
@@ -6,6 +6,7 @@ config XEN
 	bool "Xen guest support"
 	select PARAVIRT
 	select PARAVIRT_CLOCK
+	select XEN_HAVE_PVMMU
 	depends on X86_64 || (X86_32 && X86_PAE && !X86_VISWS)
 	depends on X86_CMPXCHG && X86_TSC
 	help
@@ -50,3 +51,13 @@ config XEN_DEBUG_FS
 	  Enable statistics output and various tuning options in debugfs.
 	  Enabling this option may incur a significant performance overhead.
 
+config XEN_X86_PVH
+	bool "Support for running as a PVH guest (EXPERIMENTAL)"
+	depends on X86_64 && XEN && EXPERIMENTAL
+	default n
+	help
+	   This option enables support for running as a PVH guest (PV guest
+	   using hardware extensions) under a suitably capable hypervisor.
+	   This option is EXPERIMENTAL because the hypervisor interfaces
+	   which it uses is not yet considered stable therefore backwards and
+	   forwards compatibility is not yet guaranteed.  If unsure, say N.
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 586d838..8ddb5c1 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -105,6 +105,9 @@ RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
 __read_mostly int xen_have_vector_callback;
 EXPORT_SYMBOL_GPL(xen_have_vector_callback);
 
+#define xen_pvh_domain() (xen_pv_domain() && \
+			  xen_feature(XENFEAT_auto_translated_physmap) && \
+			  xen_have_vector_callback)
 /*
  * Point at some empty memory to start with. We map the real shared_info
  * page as soon as fixmap is up and running.
@@ -217,12 +220,28 @@ static void __init xen_banner(void)
 	struct xen_extraversion extra;
 	HYPERVISOR_xen_version(XENVER_extraversion, &extra);
 
-	printk(KERN_INFO "Booting paravirtualized kernel on %s\n",
-	       pv_info.name);
+	pr_info("Booting paravirtualized kernel %son %s\n",
+		xen_feature(XENFEAT_auto_translated_physmap) ?
+			"with PVH extensions " : "", pv_info.name);
 	printk(KERN_INFO "Xen version: %d.%d%s%s\n",
 	       version >> 16, version & 0xffff, extra.extraversion,
 	       xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
 }
+/* Check if running on Xen version (major, minor) or later */
+bool
+xen_running_on_version_or_later(unsigned int major, unsigned int minor)
+{
+	unsigned int version;
+
+	if (!xen_domain())
+		return false;
+
+	version = HYPERVISOR_xen_version(XENVER_version, NULL);
+	if ((((version >> 16) == major) && ((version & 0xffff) >= minor)) ||
+		((version >> 16) > major))
+		return true;
+	return false;
+}
 
 #define CPUID_THERM_POWER_LEAF 6
 #define APERFMPERF_PRESENT 0
@@ -271,12 +290,15 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
 		break;
 	}
 
-	asm(XEN_EMULATE_PREFIX "cpuid"
-		: "=a" (*ax),
-		  "=b" (*bx),
-		  "=c" (*cx),
-		  "=d" (*dx)
-		: "0" (*ax), "2" (*cx));
+	if (xen_pvh_domain())
+		native_cpuid(ax, bx, cx, dx);
+	else
+		asm(XEN_EMULATE_PREFIX "cpuid"
+			: "=a" (*ax),
+			"=b" (*bx),
+			"=c" (*cx),
+			"=d" (*dx)
+			: "0" (*ax), "2" (*cx));
 
 	*bx &= maskebx;
 	*cx &= maskecx;
@@ -287,8 +309,7 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
 
 static bool __init xen_check_mwait(void)
 {
-#if defined(CONFIG_ACPI) && !defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) && \
-	!defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
+#ifdef CONFIG_ACPI
 	struct xen_platform_op op = {
 		.cmd			= XENPF_set_processor_pminfo,
 		.u.set_pminfo.id	= -1,
@@ -309,6 +330,13 @@ static bool __init xen_check_mwait(void)
 	if (!xen_initial_domain())
 		return false;
 
+	/*
+	 * When running under platform earlier than Xen4.2, do not expose
+	 * mwait, to avoid the risk of loading native acpi pad driver
+	 */
+	if (!xen_running_on_version_or_later(4, 2))
+		return false;
+
 	ax = 1;
 	cx = 0;
 
@@ -1053,6 +1081,10 @@ void xen_setup_shared_info(void)
 		HYPERVISOR_shared_info =
 			(struct shared_info *)__va(xen_start_info->shared_info);
 
+	/* PVH TBD/FIXME: vcpu info placement in phase 2 */
+	if (xen_pvh_domain())
+		return;
+
 #ifndef CONFIG_SMP
 	/* In UP this is as good a place as any to set up shared info */
 	xen_setup_vcpu_info_placement();
@@ -1290,6 +1322,11 @@ static const struct machine_ops xen_machine_ops __initconst = {
  */
 static void __init xen_setup_stackprotector(void)
 {
+	/* PVH TBD/FIXME: investigate setup_stack_canary_segment */
+	if (xen_feature(XENFEAT_auto_translated_physmap)) {
+		switch_to_new_gdt(0);
+		return;
+	}
 	pv_cpu_ops.write_gdt_entry = xen_write_gdt_entry_boot;
 	pv_cpu_ops.load_gdt = xen_load_gdt_boot;
 
@@ -1300,6 +1337,19 @@ static void __init xen_setup_stackprotector(void)
 	pv_cpu_ops.load_gdt = xen_load_gdt;
 }
 
+static void __init xen_pvh_early_guest_init(void)
+{
+	if (xen_feature(XENFEAT_hvm_callback_vector))
+		xen_have_vector_callback = 1;
+
+#ifdef CONFIG_X86_32
+	if (xen_feature(XENFEAT_auto_translated_physmap)) {
+		xen_raw_printk("ERROR: 32bit PVH guests are not supported\n");
+		BUG();
+	}
+#endif
+}
+
 /* First C function to be called on Xen boot */
 asmlinkage void __init xen_start_kernel(void)
 {
@@ -1311,13 +1361,18 @@ asmlinkage void __init xen_start_kernel(void)
 
 	xen_domain_type = XEN_PV_DOMAIN;
 
+	xen_setup_features();
+	xen_pvh_early_guest_init();
 	xen_setup_machphys_mapping();
 
 	/* Install Xen paravirt ops */
 	pv_info = xen_info;
 	pv_init_ops = xen_init_ops;
-	pv_cpu_ops = xen_cpu_ops;
 	pv_apic_ops = xen_apic_ops;
+	if (xen_pvh_domain())
+		pv_cpu_ops.cpuid = xen_cpuid;
+	else
+		pv_cpu_ops = xen_cpu_ops;
 
 	x86_init.resources.memory_setup = xen_memory_setup;
 	x86_init.oem.arch_setup = xen_arch_setup;
@@ -1349,8 +1404,6 @@ asmlinkage void __init xen_start_kernel(void)
 	/* Work out if we support NX */
 	x86_configure_nx();
 
-	xen_setup_features();
-
 	/* Get mfn list */
 	if (!xen_feature(XENFEAT_auto_translated_physmap))
 		xen_build_dynamic_phys_to_machine();
@@ -1421,14 +1474,18 @@ asmlinkage void __init xen_start_kernel(void)
 	/* set the limit of our address space */
 	xen_reserve_top();
 
-	/* We used to do this in xen_arch_setup, but that is too late on AMD
-	 * were early_cpu_init (run before ->arch_setup()) calls early_amd_init
-	 * which pokes 0xcf8 port.
-	 */
-	set_iopl.iopl = 1;
-	rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl);
-	if (rc != 0)
-		xen_raw_printk("physdev_op failed %d\n", rc);
+	/* PVH: runs at default kernel iopl of 0 */
+	if (!xen_pvh_domain()) {
+		/*
+		 * We used to do this in xen_arch_setup, but that is too late
+		 * on AMD were early_cpu_init (run before ->arch_setup()) calls
+		 * early_amd_init which pokes 0xcf8 port.
+		 */
+		set_iopl.iopl = 1;
+		rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl);
+		if (rc != 0)
+			xen_raw_printk("physdev_op failed %d\n", rc);
+	}
 
 #ifdef CONFIG_X86_32
 	/* set up basic CPUID stuff */
@@ -1495,51 +1552,72 @@ asmlinkage void __init xen_start_kernel(void)
 #endif
 }
 
-void __ref xen_hvm_init_shared_info(void)
+#ifdef CONFIG_XEN_PVHVM
+#define HVM_SHARED_INFO_ADDR 0xFE700000UL
+static struct shared_info *xen_hvm_shared_info;
+static unsigned long xen_hvm_sip_phys;
+static int xen_major, xen_minor;
+
+static void xen_hvm_connect_shared_info(unsigned long pfn)
 {
-	int cpu;
 	struct xen_add_to_physmap xatp;
-	static struct shared_info *shared_info_page = 0;
 
-	if (!shared_info_page)
-		shared_info_page = (struct shared_info *)
-			extend_brk(PAGE_SIZE, PAGE_SIZE);
 	xatp.domid = DOMID_SELF;
 	xatp.idx = 0;
 	xatp.space = XENMAPSPACE_shared_info;
-	xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
+	xatp.gpfn = pfn;
 	if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
 		BUG();
 
-	HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
+}
+static void __init xen_hvm_set_shared_info(struct shared_info *sip)
+{
+	int cpu;
+
+	HYPERVISOR_shared_info = sip;
 
 	/* xen_vcpu is a pointer to the vcpu_info struct in the shared_info
 	 * page, we use it in the event channel upcall and in some pvclock
 	 * related functions. We don't need the vcpu_info placement
 	 * optimizations because we don't use any pv_mmu or pv_irq op on
-	 * HVM.
-	 * When xen_hvm_init_shared_info is run at boot time only vcpu 0 is
-	 * online but xen_hvm_init_shared_info is run at resume time too and
-	 * in that case multiple vcpus might be online. */
-	for_each_online_cpu(cpu) {
+	 * HVM. */
+	for_each_online_cpu(cpu)
 		per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
+}
+
+/* Reconnect the shared_info pfn to a (new) mfn */
+void xen_hvm_resume_shared_info(void)
+{
+	xen_hvm_connect_shared_info(xen_hvm_sip_phys >> PAGE_SHIFT);
+}
+
+/* Xen tools prior to Xen 4 do not provide a E820_Reserved area for guest usage.
+ * On these old tools the shared info page will be placed in E820_Ram.
+ * Xen 4 provides a E820_Reserved area at 0xFC000000, and this code expects
+ * that nothing is mapped up to HVM_SHARED_INFO_ADDR.
+ * Xen 4.3+ provides an explicit 1MB area at HVM_SHARED_INFO_ADDR which is used
+ * here for the shared info page. */
+static void __init xen_hvm_init_shared_info(void)
+{
+	if (xen_major < 4) {
+		xen_hvm_shared_info = extend_brk(PAGE_SIZE, PAGE_SIZE);
+		xen_hvm_sip_phys = __pa(xen_hvm_shared_info);
+	} else {
+		xen_hvm_sip_phys = HVM_SHARED_INFO_ADDR;
+		set_fixmap(FIX_PARAVIRT_BOOTMAP, xen_hvm_sip_phys);
+		xen_hvm_shared_info =
+		(struct shared_info *)fix_to_virt(FIX_PARAVIRT_BOOTMAP);
 	}
+	xen_hvm_connect_shared_info(xen_hvm_sip_phys >> PAGE_SHIFT);
+	xen_hvm_set_shared_info(xen_hvm_shared_info);
 }
 
-#ifdef CONFIG_XEN_PVHVM
 static void __init init_hvm_pv_info(void)
 {
-	int major, minor;
 	uint32_t eax, ebx, ecx, edx, pages, msr, base;
 	u64 pfn;
 
 	base = xen_cpuid_base();
-	cpuid(base + 1, &eax, &ebx, &ecx, &edx);
-
-	major = eax >> 16;
-	minor = eax & 0xffff;
-	printk(KERN_INFO "Xen version %d.%d.\n", major, minor);
-
 	cpuid(base + 2, &pages, &msr, &ecx, &edx);
 
 	pfn = __pa(hypercall_page);
@@ -1590,12 +1668,22 @@ static void __init xen_hvm_guest_init(void)
 
 static bool __init xen_hvm_platform(void)
 {
+	uint32_t eax, ebx, ecx, edx, base;
+
 	if (xen_pv_domain())
 		return false;
 
-	if (!xen_cpuid_base())
+	base = xen_cpuid_base();
+	if (!base)
 		return false;
 
+	cpuid(base + 1, &eax, &ebx, &ecx, &edx);
+
+	xen_major = eax >> 16;
+	xen_minor = eax & 0xffff;
+
+	printk(KERN_INFO "Xen version %d.%d.\n", xen_major, xen_minor);
+
 	return true;
 }
 
diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c
index 01a4dc0..fcbe56a 100644
--- a/arch/x86/xen/irq.c
+++ b/arch/x86/xen/irq.c
@@ -5,6 +5,7 @@
 #include <xen/interface/xen.h>
 #include <xen/interface/sched.h>
 #include <xen/interface/vcpu.h>
+#include <xen/features.h>
 #include <xen/events.h>
 
 #include <asm/xen/hypercall.h>
@@ -129,6 +130,8 @@ static const struct pv_irq_ops xen_irq_ops __initconst = {
 
 void __init xen_init_irq_ops(void)
 {
-	pv_irq_ops = xen_irq_ops;
+	/* For PVH we use default pv_irq_ops settings */
+	if (!xen_feature(XENFEAT_hvm_callback_vector))
+		pv_irq_ops = xen_irq_ops;
 	x86_init.irqs.intr_init = xen_init_IRQ;
 }
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index dcf5f2d..a63e5f9 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -74,6 +74,7 @@
 #include <xen/interface/version.h>
 #include <xen/interface/memory.h>
 #include <xen/hvc-console.h>
+#include <xen/balloon.h>
 
 #include "multicalls.h"
 #include "mmu.h"
@@ -332,6 +333,20 @@ static void xen_set_pte(pte_t *ptep, pte_t pteval)
 	__xen_set_pte(ptep, pteval);
 }
 
+void xen_set_clr_mmio_pvh_pte(unsigned long pfn, unsigned long mfn,
+			      int nr_mfns, int add_mapping)
+{
+	struct physdev_map_iomem iomem;
+
+	iomem.first_gfn = pfn;
+	iomem.first_mfn = mfn;
+	iomem.nr_mfns = nr_mfns;
+	iomem.add_mapping = add_mapping;
+
+	if (HYPERVISOR_physdev_op(PHYSDEVOP_map_iomem, &iomem))
+		BUG();
+}
+
 static void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
 		    pte_t *ptep, pte_t pteval)
 {
@@ -1221,6 +1236,8 @@ static void __init xen_pagetable_init(void)
 #endif
 	paging_init();
 	xen_setup_shared_info();
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return;
 #ifdef CONFIG_X86_64
 	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
 		unsigned long new_mfn_list;
@@ -1469,7 +1486,8 @@ static int xen_pgd_alloc(struct mm_struct *mm)
 
 		if (user_pgd != NULL) {
 			user_pgd[pgd_index(VSYSCALL_START)] =
-				__pgd(__pa(level3_user_vsyscall) | _PAGE_TABLE);
+				__pgd(__pa_symbol(level3_user_vsyscall) |
+				      _PAGE_TABLE);
 			ret = 0;
 		}
 
@@ -1547,6 +1565,10 @@ static void __init xen_set_pte_init(pte_t *ptep, pte_t pte)
 static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn)
 {
 	struct mmuext_op op;
+
+	if (xen_feature(XENFEAT_writable_page_tables))
+		return;
+
 	op.cmd = cmd;
 	op.arg1.mfn = pfn_to_mfn(pfn);
 	if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF))
@@ -1744,6 +1766,10 @@ static void set_page_prot(void *addr, pgprot_t prot)
 	unsigned long pfn = __pa(addr) >> PAGE_SHIFT;
 	pte_t pte = pfn_pte(pfn, prot);
 
+	/* recall for PVH, page tables are native. */
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return;
+
 	if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, 0))
 		BUG();
 }
@@ -1821,6 +1847,9 @@ static void convert_pfn_mfn(void *v)
 	pte_t *pte = v;
 	int i;
 
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return;
+
 	/* All levels are converted the same way, so just treat them
 	   as ptes. */
 	for (i = 0; i < PTRS_PER_PTE; i++)
@@ -1840,6 +1869,7 @@ static void __init check_pt_base(unsigned long *pt_base, unsigned long *pt_end,
 		(*pt_end)--;
 	}
 }
+
 /*
  * Set up the initial kernel pagetable.
  *
@@ -1850,6 +1880,7 @@ static void __init check_pt_base(unsigned long *pt_base, unsigned long *pt_end,
  * but that's enough to get __va working.  We need to fill in the rest
  * of the physical mapping once some sort of allocator has been set
  * up.
+ * NOTE: for PVH, the page tables are native.
  */
 void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
 {
@@ -1927,10 +1958,13 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
 	 * structure to attach it to, so make sure we just set kernel
 	 * pgd.
 	 */
-	xen_mc_batch();
-	__xen_write_cr3(true, __pa(init_level4_pgt));
-	xen_mc_issue(PARAVIRT_LAZY_CPU);
-
+	if (xen_feature(XENFEAT_writable_page_tables)) {
+		native_write_cr3(__pa_symbol(init_level4_pgt));
+	} else {
+		xen_mc_batch();
+		__xen_write_cr3(true, __pa_symbol(init_level4_pgt));
+		xen_mc_issue(PARAVIRT_LAZY_CPU);
+	}
 	/* We can't that easily rip out L3 and L2, as the Xen pagetables are
 	 * set out this way: [L4], [L1], [L2], [L3], [L1], [L1] ...  for
 	 * the initial domain. For guests using the toolstack, they are in:
@@ -1951,10 +1985,10 @@ static RESERVE_BRK_ARRAY(pmd_t, swapper_kernel_pmd, PTRS_PER_PMD);
 
 static void __init xen_write_cr3_init(unsigned long cr3)
 {
-	unsigned long pfn = PFN_DOWN(__pa(swapper_pg_dir));
+	unsigned long pfn = PFN_DOWN(__pa_symbol(swapper_pg_dir));
 
-	BUG_ON(read_cr3() != __pa(initial_page_table));
-	BUG_ON(cr3 != __pa(swapper_pg_dir));
+	BUG_ON(read_cr3() != __pa_symbol(initial_page_table));
+	BUG_ON(cr3 != __pa_symbol(swapper_pg_dir));
 
 	/*
 	 * We are switching to swapper_pg_dir for the first time (from
@@ -1978,7 +2012,7 @@ static void __init xen_write_cr3_init(unsigned long cr3)
 	pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, pfn);
 
 	pin_pagetable_pfn(MMUEXT_UNPIN_TABLE,
-			  PFN_DOWN(__pa(initial_page_table)));
+			  PFN_DOWN(__pa_symbol(initial_page_table)));
 	set_page_prot(initial_page_table, PAGE_KERNEL);
 	set_page_prot(initial_kernel_pmd, PAGE_KERNEL);
 
@@ -2003,7 +2037,7 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
 
 	copy_page(initial_page_table, pgd);
 	initial_page_table[KERNEL_PGD_BOUNDARY] =
-		__pgd(__pa(initial_kernel_pmd) | _PAGE_PRESENT);
+		__pgd(__pa_symbol(initial_kernel_pmd) | _PAGE_PRESENT);
 
 	set_page_prot(initial_kernel_pmd, PAGE_KERNEL_RO);
 	set_page_prot(initial_page_table, PAGE_KERNEL_RO);
@@ -2012,8 +2046,8 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
 	pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
 
 	pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE,
-			  PFN_DOWN(__pa(initial_page_table)));
-	xen_write_cr3(__pa(initial_page_table));
+			  PFN_DOWN(__pa_symbol(initial_page_table)));
+	xen_write_cr3(__pa_symbol(initial_page_table));
 
 	memblock_reserve(__pa(xen_start_info->pt_base),
 			 xen_start_info->nr_pt_frames * PAGE_SIZE);
@@ -2197,8 +2231,13 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = {
 
 void __init xen_init_mmu_ops(void)
 {
-	x86_init.mapping.pagetable_reserve = xen_mapping_pagetable_reserve;
 	x86_init.paging.pagetable_init = xen_pagetable_init;
+
+	if (xen_feature(XENFEAT_auto_translated_physmap)) {
+		pv_mmu_ops.flush_tlb_others = xen_flush_tlb_others;
+		return;
+	}
+	x86_init.mapping.pagetable_reserve = xen_mapping_pagetable_reserve;
 	pv_mmu_ops = xen_mmu_ops;
 
 	memset(dummy_mapping, 0xff, PAGE_SIZE);
@@ -2474,6 +2513,95 @@ void __init xen_hvm_init_mmu_ops(void)
 }
 #endif
 
+/* Map foreign gmfn, fgmfn, to local pfn, lpfn. This for the user space
+ * creating new guest on PVH dom0 and needs to map domU pages.
+ */
+static int pvh_add_to_xen_p2m(unsigned long lpfn, unsigned long fgmfn,
+			      unsigned int domid)
+{
+	int rc;
+	struct xen_add_to_physmap_range xatp = {
+		.domid = DOMID_SELF,
+		.foreign_domid = domid,
+		.size = 1,
+		.space = XENMAPSPACE_gmfn_foreign,
+	};
+	xen_ulong_t idx = fgmfn;
+	xen_pfn_t gpfn = lpfn;
+
+	set_xen_guest_handle(xatp.idxs, &idx);
+	set_xen_guest_handle(xatp.gpfns, &gpfn);
+
+	rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp);
+	if (rc)
+		pr_warn("d0: Failed to map pfn (0x%lx) to mfn (0x%lx) rc:%d\n",
+			lpfn, fgmfn, rc);
+	return rc;
+}
+
+static int pvh_rem_xen_p2m(unsigned long spfn, int count)
+{
+	struct xen_remove_from_physmap xrp;
+	int i, rc;
+
+	for (i = 0; i < count; i++) {
+		xrp.domid = DOMID_SELF;
+		xrp.gpfn = spfn+i;
+		rc = HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrp);
+		if (rc) {
+			pr_warn("Failed to unmap pfn:%lx rc:%d done:%d\n",
+				spfn+i, rc, i);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+struct pvh_remap_data {
+	unsigned long fgmfn;		/* foreign domain's gmfn */
+	pgprot_t prot;
+	domid_t  domid;
+	int	 index;
+	struct page **pages;
+};
+
+static int pvh_map_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr,
+			void *data)
+{
+	int rc;
+	struct pvh_remap_data *remap = data;
+	unsigned long pfn = page_to_pfn(remap->pages[remap->index++]);
+	pte_t pteval = pte_mkspecial(pfn_pte(pfn, remap->prot));
+
+	rc = pvh_add_to_xen_p2m(pfn, remap->fgmfn, remap->domid);
+	if (rc)
+		return rc;
+	native_set_pte(ptep, pteval);
+
+	return 0;
+}
+
+static int pvh_remap_gmfn_range(struct vm_area_struct *vma,
+				unsigned long addr, unsigned long mfn, int nr,
+				pgprot_t prot, unsigned domid,
+				struct page **pages)
+{
+	int err;
+	struct pvh_remap_data pvhdata;
+
+	BUG_ON(!pages);
+
+	pvhdata.fgmfn = mfn;
+	pvhdata.prot = prot;
+	pvhdata.domid = domid;
+	pvhdata.index = 0;
+	pvhdata.pages = pages;
+	err = apply_to_page_range(vma->vm_mm, addr, nr << PAGE_SHIFT,
+				  pvh_map_pte_fn, &pvhdata);
+	flush_tlb_all();
+	return err;
+}
+
 #define REMAP_BATCH_SIZE 16
 
 struct remap_data {
@@ -2497,8 +2625,10 @@ static int remap_area_mfn_pte_fn(pte_t *ptep, pgtable_t token,
 
 int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
 			       unsigned long addr,
-			       unsigned long mfn, int nr,
-			       pgprot_t prot, unsigned domid)
+			       xen_pfn_t mfn, int nr,
+			       pgprot_t prot, unsigned domid,
+			       struct page **pages)
+
 {
 	struct remap_data rmd;
 	struct mmu_update mmu_update[REMAP_BATCH_SIZE];
@@ -2513,6 +2643,10 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
 
 	BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO)));
 
+	if (xen_feature(XENFEAT_auto_translated_physmap)) {
+		/* We need to update the local page tables and the xen HAP */
+		return pvh_remap_gmfn_range(vma, addr, mfn, nr, prot, domid, pages);
+	}
 	rmd.mfn = mfn;
 	rmd.prot = prot;
 
@@ -2542,3 +2676,26 @@ out:
 	return err;
 }
 EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);
+
+/* Returns: 0 success */
+int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
+			       int numpgs, struct page **pages)
+{
+	if (!pages || !xen_feature(XENFEAT_auto_translated_physmap))
+		return 0;
+
+	while (numpgs--) {
+
+		/* the mmu has already cleaned up the process mmu resources at
+		 * this point (lookup_address will return NULL). */
+		unsigned long pfn = page_to_pfn(pages[numpgs]);
+
+		pvh_rem_xen_p2m(pfn, 1);
+	}
+	/* We don't need to flush tlbs because as part of pvh_rem_xen_p2m(),
+	 * the hypervisor will do tlb flushes after removing the p2m entries
+	 * from the EPT/NPT */
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range);
diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h
index 73809bb..6d0bb56 100644
--- a/arch/x86/xen/mmu.h
+++ b/arch/x86/xen/mmu.h
@@ -23,4 +23,6 @@ unsigned long xen_read_cr2_direct(void);
 
 extern void xen_init_mmu_ops(void);
 extern void xen_hvm_init_mmu_ops(void);
+extern void xen_set_clr_mmio_pvh_pte(unsigned long pfn, unsigned long mfn,
+				     int nr_mfns, int add_mapping);
 #endif	/* _XEN_MMU_H */
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index 95fb2aa..ea553c8 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -798,7 +798,7 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
 	unsigned topidx, mididx, idx;
 
-	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
+	if (xen_feature(XENFEAT_auto_translated_physmap)) {
 		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
 		return true;
 	}
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 8971a26..8cce47b 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -27,6 +27,7 @@
 #include <xen/interface/memory.h>
 #include <xen/interface/physdev.h>
 #include <xen/features.h>
+#include "mmu.h"
 #include "xen-ops.h"
 #include "vdso.h"
 
@@ -78,6 +79,9 @@ static void __init xen_add_extra_mem(u64 start, u64 size)
 
 	memblock_reserve(start, size);
 
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return;
+
 	xen_max_p2m_pfn = PFN_DOWN(start + size);
 	for (pfn = PFN_DOWN(start); pfn < xen_max_p2m_pfn; pfn++) {
 		unsigned long mfn = pfn_to_mfn(pfn);
@@ -100,6 +104,7 @@ static unsigned long __init xen_do_chunk(unsigned long start,
 		.domid        = DOMID_SELF
 	};
 	unsigned long len = 0;
+	int xlated_phys = xen_feature(XENFEAT_auto_translated_physmap);
 	unsigned long pfn;
 	int ret;
 
@@ -113,7 +118,7 @@ static unsigned long __init xen_do_chunk(unsigned long start,
 				continue;
 			frame = mfn;
 		} else {
-			if (mfn != INVALID_P2M_ENTRY)
+			if (!xlated_phys && mfn != INVALID_P2M_ENTRY)
 				continue;
 			frame = pfn;
 		}
@@ -230,6 +235,27 @@ static void __init xen_set_identity_and_release_chunk(
 	*identity += set_phys_range_identity(start_pfn, end_pfn);
 }
 
+/* For PVH, the pfns [0..MAX] are mapped to mfn's in the EPT/NPT. The mfns
+ * are released as part of this 1:1 mapping hypercall back to the dom heap.
+ * Also, we map the entire IO space, ie, beyond max_pfn_mapped.
+ */
+static void __init xen_pvh_identity_map_chunk(unsigned long start_pfn,
+		unsigned long end_pfn, unsigned long *released,
+		unsigned long *identity, unsigned long max_pfn)
+{
+	unsigned long pfn;
+	int numpfns = 1, add_mapping = 1;
+
+	for (pfn = start_pfn; pfn < end_pfn; pfn++)
+		xen_set_clr_mmio_pvh_pte(pfn, pfn, numpfns, add_mapping);
+
+	if (start_pfn <= max_pfn) {
+		unsigned long end = min(max_pfn_mapped, end_pfn);
+		*released += end - start_pfn;
+	}
+	*identity += end_pfn - start_pfn;
+}
+
 static unsigned long __init xen_set_identity_and_release(
 	const struct e820entry *list, size_t map_size, unsigned long nr_pages)
 {
@@ -238,6 +264,7 @@ static unsigned long __init xen_set_identity_and_release(
 	unsigned long identity = 0;
 	const struct e820entry *entry;
 	int i;
+	int xlated_phys = xen_feature(XENFEAT_auto_translated_physmap);
 
 	/*
 	 * Combine non-RAM regions and gaps until a RAM region (or the
@@ -259,11 +286,17 @@ static unsigned long __init xen_set_identity_and_release(
 			if (entry->type == E820_RAM)
 				end_pfn = PFN_UP(entry->addr);
 
-			if (start_pfn < end_pfn)
-				xen_set_identity_and_release_chunk(
-					start_pfn, end_pfn, nr_pages,
-					&released, &identity);
-
+			if (start_pfn < end_pfn) {
+				if (xlated_phys) {
+					xen_pvh_identity_map_chunk(start_pfn,
+						end_pfn, &released, &identity,
+						nr_pages);
+				} else {
+					xen_set_identity_and_release_chunk(
+						start_pfn, end_pfn, nr_pages,
+						&released, &identity);
+				}
+			}
 			start = end;
 		}
 	}
@@ -526,16 +559,14 @@ void __cpuinit xen_enable_syscall(void)
 #endif /* CONFIG_X86_64 */
 }
 
-void __init xen_arch_setup(void)
+/* Non auto translated PV domain, ie, it's not PVH. */
+static __init void xen_pvmmu_arch_setup(void)
 {
-	xen_panic_handler_init();
-
 	HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments);
 	HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables);
 
-	if (!xen_feature(XENFEAT_auto_translated_physmap))
-		HYPERVISOR_vm_assist(VMASST_CMD_enable,
-				     VMASST_TYPE_pae_extended_cr3);
+	HYPERVISOR_vm_assist(VMASST_CMD_enable,
+			     VMASST_TYPE_pae_extended_cr3);
 
 	if (register_callback(CALLBACKTYPE_event, xen_hypervisor_callback) ||
 	    register_callback(CALLBACKTYPE_failsafe, xen_failsafe_callback))
@@ -543,6 +574,15 @@ void __init xen_arch_setup(void)
 
 	xen_enable_sysenter();
 	xen_enable_syscall();
+}
+
+/* This function not called for HVM domain */
+void __init xen_arch_setup(void)
+{
+	xen_panic_handler_init();
+
+	if (!xen_feature(XENFEAT_auto_translated_physmap))
+		xen_pvmmu_arch_setup();
 
 #ifdef CONFIG_ACPI
 	if (!(xen_start_info->flags & SIF_INITDOMAIN)) {
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 353c50f..448f737 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -68,9 +68,11 @@ static void __cpuinit cpu_bringup(void)
 	touch_softlockup_watchdog();
 	preempt_disable();
 
-	xen_enable_sysenter();
-	xen_enable_syscall();
-
+	/* PVH runs in ring 0 and allows us to do native syscalls. Yay! */
+	if (!xen_feature(XENFEAT_supervisor_mode_kernel)) {
+		xen_enable_sysenter();
+		xen_enable_syscall();
+	}
 	cpu = smp_processor_id();
 	smp_store_cpu_info(cpu);
 	cpu_data(cpu).x86_max_cores = 1;
@@ -230,10 +232,11 @@ static void __init xen_smp_prepare_boot_cpu(void)
 	BUG_ON(smp_processor_id() != 0);
 	native_smp_prepare_boot_cpu();
 
-	/* We've switched to the "real" per-cpu gdt, so make sure the
-	   old memory can be recycled */
-	make_lowmem_page_readwrite(xen_initial_gdt);
-
+	if (!xen_feature(XENFEAT_writable_page_tables)) {
+		/* We've switched to the "real" per-cpu gdt, so make sure the
+		 * old memory can be recycled */
+		make_lowmem_page_readwrite(xen_initial_gdt);
+	}
 	xen_filter_cpu_maps();
 	xen_setup_vcpu_info_placement();
 }
@@ -300,8 +303,6 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
 	gdt = get_cpu_gdt_table(cpu);
 
 	ctxt->flags = VGCF_IN_KERNEL;
-	ctxt->user_regs.ds = __USER_DS;
-	ctxt->user_regs.es = __USER_DS;
 	ctxt->user_regs.ss = __KERNEL_DS;
 #ifdef CONFIG_X86_32
 	ctxt->user_regs.fs = __KERNEL_PERCPU;
@@ -310,35 +311,57 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
 	ctxt->gs_base_kernel = per_cpu_offset(cpu);
 #endif
 	ctxt->user_regs.eip = (unsigned long)cpu_bringup_and_idle;
-	ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */
 
 	memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
 
-	xen_copy_trap_info(ctxt->trap_ctxt);
+	if (xen_feature(XENFEAT_auto_translated_physmap) &&
+	    xen_feature(XENFEAT_supervisor_mode_kernel)) {
+		/* Note: PVH is not supported on x86_32. */
+#ifdef CONFIG_X86_64
+		ctxt->user_regs.ds = __KERNEL_DS;
+		ctxt->user_regs.es = 0;
+		ctxt->user_regs.gs = 0;
+
+		/* GUEST_GDTR_BASE and */
+		ctxt->u.pvh.gdtaddr = (unsigned long)gdt;
+		/* GUEST_GDTR_LIMIT in the VMCS. */
+		ctxt->u.pvh.gdtsz = (unsigned long)(GDT_SIZE - 1);
+
+		ctxt->gs_base_user = (unsigned long)
+					per_cpu(irq_stack_union.gs_base, cpu);
+#endif
+	} else {
+		ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */
+		ctxt->user_regs.ds = __USER_DS;
+		ctxt->user_regs.es = __USER_DS;
 
-	ctxt->ldt_ents = 0;
+		xen_copy_trap_info(ctxt->trap_ctxt);
 
-	BUG_ON((unsigned long)gdt & ~PAGE_MASK);
+		ctxt->ldt_ents = 0;
 
-	gdt_mfn = arbitrary_virt_to_mfn(gdt);
-	make_lowmem_page_readonly(gdt);
-	make_lowmem_page_readonly(mfn_to_virt(gdt_mfn));
+		BUG_ON((unsigned long)gdt & ~PAGE_MASK);
 
-	ctxt->gdt_frames[0] = gdt_mfn;
-	ctxt->gdt_ents      = GDT_ENTRIES;
+		gdt_mfn = arbitrary_virt_to_mfn(gdt);
+		make_lowmem_page_readonly(gdt);
+		make_lowmem_page_readonly(mfn_to_virt(gdt_mfn));
 
-	ctxt->user_regs.cs = __KERNEL_CS;
-	ctxt->user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs);
+		ctxt->u.pv.gdt_frames[0] = gdt_mfn;
+		ctxt->u.pv.gdt_ents      = GDT_ENTRIES;
 
-	ctxt->kernel_ss = __KERNEL_DS;
-	ctxt->kernel_sp = idle->thread.sp0;
+		ctxt->kernel_ss = __KERNEL_DS;
+		ctxt->kernel_sp = idle->thread.sp0;
 
 #ifdef CONFIG_X86_32
-	ctxt->event_callback_cs     = __KERNEL_CS;
-	ctxt->failsafe_callback_cs  = __KERNEL_CS;
+		ctxt->event_callback_cs     = __KERNEL_CS;
+		ctxt->failsafe_callback_cs  = __KERNEL_CS;
 #endif
-	ctxt->event_callback_eip    = (unsigned long)xen_hypervisor_callback;
-	ctxt->failsafe_callback_eip = (unsigned long)xen_failsafe_callback;
+		ctxt->event_callback_eip    =
+					(unsigned long)xen_hypervisor_callback;
+		ctxt->failsafe_callback_eip =
+					(unsigned long)xen_failsafe_callback;
+	}
+	ctxt->user_regs.cs = __KERNEL_CS;
+	ctxt->user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs);
 
 	per_cpu(xen_cr3, cpu) = __pa(swapper_pg_dir);
 	ctxt->ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir));
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
index 45329c8..ae8a00c 100644
--- a/arch/x86/xen/suspend.c
+++ b/arch/x86/xen/suspend.c
@@ -30,7 +30,7 @@ void xen_arch_hvm_post_suspend(int suspend_cancelled)
 {
 #ifdef CONFIG_XEN_PVHVM
 	int cpu;
-	xen_hvm_init_shared_info();
+	xen_hvm_resume_shared_info();
 	xen_callback_vector();
 	xen_unplug_emulated_devices();
 	if (xen_feature(XENFEAT_hvm_safe_pvclock)) {
diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S
index 7faed58..1a6bca1 100644
--- a/arch/x86/xen/xen-head.S
+++ b/arch/x86/xen/xen-head.S
@@ -13,6 +13,15 @@
 #include <xen/interface/elfnote.h>
 #include <asm/xen/interface.h>
 
+#ifdef CONFIG_XEN_X86_PVH
+#define FEATURES_PVH "|writable_descriptor_tables" \
+		     "|auto_translated_physmap" \
+		     "|supervisor_mode_kernel" \
+		     "|hvm_callback_vector"
+#else
+#define FEATURES_PVH /* Not supported */
+#endif
+
 	__INIT
 ENTRY(startup_xen)
 	cld
@@ -95,7 +104,7 @@ NEXT_HYPERCALL(arch_6)
 #endif
 	ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          _ASM_PTR startup_xen)
 	ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page)
-	ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,       .asciz "!writable_page_tables|pae_pgdir_above_4gb")
+	ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,       .asciz "!writable_page_tables|pae_pgdir_above_4gb"FEATURES_PVH)
 	ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz "yes")
 	ELFNOTE(Xen, XEN_ELFNOTE_LOADER,         .asciz "generic")
 	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index a95b417..d2e73d1 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -40,7 +40,7 @@ void xen_enable_syscall(void);
 void xen_vcpu_restore(void);
 
 void xen_callback_vector(void);
-void xen_hvm_init_shared_info(void);
+void xen_hvm_resume_shared_info(void);
 void xen_unplug_emulated_devices(void);
 
 void __init xen_build_dynamic_phys_to_machine(void);
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 0d1f36a..a47852d 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -16,6 +16,8 @@ config XTENSA
 	select GENERIC_KERNEL_THREAD
 	select GENERIC_KERNEL_EXECVE
 	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select IRQ_DOMAIN
+	select CLONE_BACKWARDS
 	help
 	  Xtensa processors are 32-bit RISC machines designed by Tensilica
 	  primarily for embedded systems.  These processors are both
@@ -149,6 +151,15 @@ config XTENSA_PLATFORM_S6105
 	select SERIAL_CONSOLE
 	select NO_IOPORT
 
+config XTENSA_PLATFORM_XTFPGA
+	bool "XTFPGA"
+	select SERIAL_CONSOLE
+	select ETHOC
+	select XTENSA_CALIBRATE_CCOUNT
+	help
+	  XTFPGA is the name of Tensilica board family (LX60, LX110, LX200, ML605).
+	  This hardware is capable of running a full Linux distribution.
+
 endchoice
 
 
@@ -176,6 +187,17 @@ config CMDLINE
 	  time by entering them here. As a minimum, you should specify the
 	  memory size and the root device (e.g., mem=64M root=/dev/nfs).
 
+config USE_OF
+	bool "Flattened Device Tree support"
+	select OF
+	select OF_EARLY_FLATTREE
+	help
+	  Include support for flattened device tree machine descriptions.
+
+config BUILTIN_DTB
+	string "DTB to build into the kernel image"
+	depends on OF
+
 source "mm/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
diff --git a/arch/xtensa/Kconfig.debug b/arch/xtensa/Kconfig.debug
index 11c5852..a34010e 100644
--- a/arch/xtensa/Kconfig.debug
+++ b/arch/xtensa/Kconfig.debug
@@ -2,6 +2,26 @@ menu "Kernel hacking"
 
 source "lib/Kconfig.debug"
 
-endmenu
+config LD_NO_RELAX
+	bool "Disable linker relaxation"
+	default n
+	help
+	  Enable this function to disable link-time optimizations.
+	  The default linker behavior is to combine identical literal
+	  values to reduce code size and remove unnecessary overhead from
+	  assembler-generated 'longcall' sequences.
+	  Enabling this option improves the link time but increases the
+	  code size, and possibly execution time.
+
+config S32C1I_SELFTEST
+	bool "Perform S32C1I instruction self-test at boot"
+	default y
+	help
+	  Enable this option to test S32C1I instruction behavior at boot.
+	  Correct operation of this instruction requires some cooperation from hardware
+	  external to the processor (such as bus bridge, bus fabric, or memory controller).
+	  It is easy to make wrong hardware configuration, this test should catch it early.
 
+	  Say 'N' on stable hardware.
 
+endmenu
diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile
index bb5ba61..7e0ae8f 100644
--- a/arch/xtensa/Makefile
+++ b/arch/xtensa/Makefile
@@ -38,6 +38,7 @@ endif
 platform-$(CONFIG_XTENSA_PLATFORM_XT2000)	:= xt2000
 platform-$(CONFIG_XTENSA_PLATFORM_ISS)		:= iss
 platform-$(CONFIG_XTENSA_PLATFORM_S6105)	:= s6105
+platform-$(CONFIG_XTENSA_PLATFORM_XTFPGA)	:= xtfpga
 
 PLATFORM = $(platform-y)
 export PLATFORM
@@ -49,6 +50,10 @@ KBUILD_CFLAGS += -pipe -mlongcalls
 
 KBUILD_CFLAGS += $(call cc-option,-mforce-no-pic,)
 
+ifneq ($(CONFIG_LD_NO_RELAX),)
+LDFLAGS := --no-relax
+endif
+
 vardirs := $(patsubst %,arch/xtensa/variants/%/,$(variant-y))
 plfdirs := $(patsubst %,arch/xtensa/platforms/%/,$(platform-y))
 
@@ -75,6 +80,10 @@ core-y		+= $(buildvar) $(buildplf)
 
 libs-y		+= arch/xtensa/lib/ $(LIBGCC)
 
+ifneq ($(CONFIG_BUILTIN_DTB),"")
+core-y += arch/xtensa/boot/
+endif
+
 boot		:= arch/xtensa/boot
 
 all: zImage
@@ -84,6 +93,9 @@ bzImage : zImage
 zImage: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $@
 
+%.dtb:
+	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
 define archhelp
   @echo '* zImage      - Compressed kernel image (arch/xtensa/boot/images/zImage.*)'
 endef
diff --git a/arch/xtensa/boot/Makefile b/arch/xtensa/boot/Makefile
index 4018f89..196bc3c 100644
--- a/arch/xtensa/boot/Makefile
+++ b/arch/xtensa/boot/Makefile
@@ -22,12 +22,35 @@ subdir-y	:= lib
 # Subdirs for the boot loader(s)
 
 bootdir-$(CONFIG_XTENSA_PLATFORM_ISS)	 += boot-elf
-bootdir-$(CONFIG_XTENSA_PLATFORM_XT2000) += boot-redboot boot-elf
+bootdir-$(CONFIG_XTENSA_PLATFORM_XT2000) += boot-redboot boot-elf boot-uboot
+bootdir-$(CONFIG_XTENSA_PLATFORM_XTFPGA) += boot-redboot boot-elf boot-uboot
 
 
+BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB)).dtb.o
+ifneq ($(CONFIG_BUILTIN_DTB),"")
+obj-y += $(BUILTIN_DTB)
+endif
+
+# Rule to build device tree blobs
+$(obj)/%.dtb: $(src)/dts/%.dts FORCE
+	$(call if_changed_dep,dtc)
+
+clean-files := *.dtb.S
+
 zImage Image: $(bootdir-y)
 
 $(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) \
 	      $(addprefix $(obj)/,$(host-progs))
 	$(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS)
 
+OBJCOPYFLAGS = --strip-all -R .comment -R .note.gnu.build-id -O binary
+
+vmlinux.bin: vmlinux FORCE
+	$(call if_changed,objcopy)
+
+vmlinux.bin.gz: vmlinux.bin FORCE
+	$(call if_changed,gzip)
+
+boot-elf: vmlinux.bin
+boot-redboot: vmlinux.bin.gz
+boot-uboot: vmlinux.bin.gz
diff --git a/arch/xtensa/boot/boot-elf/Makefile b/arch/xtensa/boot/boot-elf/Makefile
index f10992b..1fe01b7 100644
--- a/arch/xtensa/boot/boot-elf/Makefile
+++ b/arch/xtensa/boot/boot-elf/Makefile
@@ -4,9 +4,6 @@
 # for more details.
 #
 
-GZIP = gzip
-GZIP_FLAGS = -v9fc
-
 ifeq ($(BIG_ENDIAN),1)
 OBJCOPY_ARGS    := -O elf32-xtensa-be
 else
@@ -20,18 +17,17 @@ boot-y		:= bootstrap.o
 
 OBJS		:= $(addprefix $(obj)/,$(boot-y))
 
-vmlinux.tmp: vmlinux
-	$(OBJCOPY) --strip-all -R .comment -R .note.gnu.build-id -O binary \
-		$^ $@
-
-Image:	vmlinux.tmp $(OBJS) arch/$(ARCH)/boot/boot-elf/boot.lds
-	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
-		--add-section image=vmlinux.tmp \
+$(obj)/Image.o: vmlinux.bin $(OBJS)
+	$(Q)$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+		--add-section image=vmlinux.bin \
 		--set-section-flags image=contents,alloc,load,load,data \
-		$(OBJS) $@.tmp
-	$(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) \
-		-T arch/$(ARCH)/boot/boot-elf/boot.lds \
-		-o arch/$(ARCH)/boot/$@.elf $@.tmp
+		$(OBJS) $@
 
-zImage:	Image
+$(obj)/../Image.elf: $(obj)/Image.o $(obj)/boot.lds
+	$(Q)$(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) \
+		-T $(obj)/boot.lds \
+		--build-id=none \
+		-o $@ $(obj)/Image.o
+	$(Q)$(kecho) '  Kernel: $@ is ready'
 
+zImage:	$(obj)/../Image.elf
diff --git a/arch/xtensa/boot/boot-redboot/Makefile b/arch/xtensa/boot/boot-redboot/Makefile
index 25a78c6..8be8b94 100644
--- a/arch/xtensa/boot/boot-redboot/Makefile
+++ b/arch/xtensa/boot/boot-redboot/Makefile
@@ -4,8 +4,6 @@
 # for more details.
 #
 
-GZIP = gzip
-GZIP_FLAGS = -v9fc
 ifeq ($(BIG_ENDIAN),1)
 OBJCOPY_ARGS 	:= -O elf32-xtensa-be
 else
@@ -21,17 +19,17 @@ LIBS	:= arch/xtensa/boot/lib/lib.a arch/xtensa/lib/lib.a
 
 LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
 
-vmlinux.tmp: vmlinux
-	$(OBJCOPY) --strip-all -R .comment -R .note.gnu.build-id -O binary \
-		$^ $@
+$(obj)/zImage.o: vmlinux.bin.gz $(OBJS)
+	$(Q)$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+		--add-section image=vmlinux.bin.gz \
+		--set-section-flags image=contents,alloc,load,load,data \
+		$(OBJS) $@
 
-vmlinux.tmp.gz: vmlinux.tmp
-	$(GZIP) $(GZIP_FLAGS) $^ > $@
+$(obj)/zImage.elf: $(obj)/zImage.o $(LIBS)
+	$(Q)$(LD) $(LD_ARGS) -o $@ $^ -L/xtensa-elf/lib $(LIBGCC)
 
-zImage: vmlinux.tmp.gz $(OBJS) $(LIBS)
-	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
-		--add-section image=vmlinux.tmp.gz \
-		--set-section-flags image=contents,alloc,load,load,data \
-		$(OBJS) $@.tmp
-	$(LD) $(LD_ARGS) -o $@.elf $@.tmp $(LIBS) -L/xtensa-elf/lib $(LIBGCC)
-	$(OBJCOPY) -S -O binary $@.elf arch/$(ARCH)/boot/$@.redboot
+$(obj)/../zImage.redboot: $(obj)/zImage.elf
+	$(Q)$(OBJCOPY) -S -O binary $< $@
+	$(Q)$(kecho) '  Kernel: $@ is ready'
+
+zImage: $(obj)/../zImage.redboot
diff --git a/arch/xtensa/boot/boot-uboot/Makefile b/arch/xtensa/boot/boot-uboot/Makefile
new file mode 100644
index 0000000..bfbf8af
--- /dev/null
+++ b/arch/xtensa/boot/boot-uboot/Makefile
@@ -0,0 +1,14 @@
+#
+# 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.
+#
+
+UIMAGE_LOADADDR = 0xd0001000
+UIMAGE_COMPRESSION = gzip
+
+$(obj)/../uImage: vmlinux.bin.gz FORCE
+	$(call if_changed,uimage)
+	$(Q)$(kecho) '  Kernel: $@ is ready'
+
+zImage: $(obj)/../uImage
diff --git a/arch/xtensa/boot/dts/lx60.dts b/arch/xtensa/boot/dts/lx60.dts
new file mode 100644
index 0000000..2eab365
--- /dev/null
+++ b/arch/xtensa/boot/dts/lx60.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+/include/ "xtfpga.dtsi"
+/include/ "xtfpga-flash-4m.dtsi"
+
+/ {
+	compatible = "xtensa,lx60";
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x04000000>;
+	};
+};
diff --git a/arch/xtensa/boot/dts/ml605.dts b/arch/xtensa/boot/dts/ml605.dts
new file mode 100644
index 0000000..6ed51d6
--- /dev/null
+++ b/arch/xtensa/boot/dts/ml605.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+/include/ "xtfpga.dtsi"
+/include/ "xtfpga-flash-16m.dtsi"
+
+/ {
+	compatible = "xtensa,ml605";
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x08000000>;
+	};
+};
diff --git a/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi b/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
new file mode 100644
index 0000000..e5703c7
--- /dev/null
+++ b/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
@@ -0,0 +1,26 @@
+/ {
+	flash: flash@f8000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "cfi-flash";
+		reg = <0xf8000000 0x01000000>;
+		bank-width = <2>;
+		device-width = <2>;
+		partition@0x0 {
+			label = "boot loader area";
+			reg = <0x00000000 0x00400000>;
+		};
+		partition@0x400000 {
+			label = "kernel image";
+			reg = <0x00400000 0x00600000>;
+		};
+		partition@0xa00000 {
+			label = "data";
+			reg = <0x00a00000 0x005e0000>;
+		};
+		partition@0xfe0000 {
+			label = "boot environment";
+			reg = <0x00fe0000 0x00020000>;
+		};
+        };
+};
diff --git a/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi b/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
new file mode 100644
index 0000000..6f9c10d
--- /dev/null
+++ b/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
@@ -0,0 +1,18 @@
+/ {
+	flash: flash@f8000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "cfi-flash";
+		reg = <0xf8000000 0x00400000>;
+		bank-width = <2>;
+		device-width = <2>;
+		partition@0x0 {
+			label = "boot loader area";
+			reg = <0x00000000 0x003f0000>;
+		};
+		partition@0x3f0000 {
+			label = "boot environment";
+			reg = <0x003f0000 0x00010000>;
+		};
+        };
+};
diff --git a/arch/xtensa/boot/dts/xtfpga.dtsi b/arch/xtensa/boot/dts/xtfpga.dtsi
new file mode 100644
index 0000000..7eda6ec
--- /dev/null
+++ b/arch/xtensa/boot/dts/xtfpga.dtsi
@@ -0,0 +1,56 @@
+/ {
+	compatible = "xtensa,xtfpga";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&pic>;
+
+	chosen {
+		bootargs = "earlycon=uart8250,mmio32,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x06000000>;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu@0 {
+			compatible = "xtensa,cpu";
+			reg = <0>;
+			/* Filled in by platform_setup from FPGA register
+			 * clock-frequency = <100000000>;
+			 */
+		};
+	};
+
+	pic: pic {
+		compatible = "xtensa,pic";
+		/* one cell: internal irq number,
+		 * two cells: second cell == 0: internal irq number
+		 *            second cell == 1: external irq number
+		 */
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	serial0: serial@fd050020 {
+		device_type = "serial";
+		compatible = "ns16550a";
+		no-loopback-test;
+		reg = <0xfd050020 0x20>;
+		reg-shift = <2>;
+		interrupts = <0 1>; /* external irq 0 */
+		/* Filled in by platform_setup from FPGA register
+		 * clock-frequency = <100000000>;
+		 */
+	};
+
+	enet0: ethoc@fd030000 {
+		compatible = "opencores,ethoc";
+		reg = <0xfd030000 0x4000 0xfd800000 0x4000>;
+		interrupts = <1 1>; /* external irq 1 */
+		local-mac-address = [00 50 c2 13 6f 00];
+	};
+};
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 6d13027..095f0a2 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -25,4 +25,5 @@ generic-y += siginfo.h
 generic-y += statfs.h
 generic-y += termios.h
 generic-y += topology.h
+generic-y += trace_clock.h
 generic-y += xor.h
diff --git a/arch/xtensa/include/asm/atomic.h b/arch/xtensa/include/asm/atomic.h
index 24f50ca..c3f2891 100644
--- a/arch/xtensa/include/asm/atomic.h
+++ b/arch/xtensa/include/asm/atomic.h
@@ -66,19 +66,35 @@
  */
 static inline void atomic_add(int i, atomic_t * v)
 {
-    unsigned int vval;
-
-    __asm__ __volatile__(
-	"rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
-	"l32i    %0, %2, 0              \n\t"
-	"add     %0, %0, %1             \n\t"
-	"s32i    %0, %2, 0              \n\t"
-	"wsr     a15, ps                \n\t"
-	"rsync                          \n"
-	: "=&a" (vval)
-	: "a" (i), "a" (v)
-	: "a15", "memory"
-	);
+#if XCHAL_HAVE_S32C1I
+	unsigned long tmp;
+	int result;
+
+	__asm__ __volatile__(
+			"1:     l32i    %1, %3, 0\n"
+			"       wsr     %1, scompare1\n"
+			"       add     %0, %1, %2\n"
+			"       s32c1i  %0, %3, 0\n"
+			"       bne     %0, %1, 1b\n"
+			: "=&a" (result), "=&a" (tmp)
+			: "a" (i), "a" (v)
+			: "memory"
+			);
+#else
+	unsigned int vval;
+
+	__asm__ __volatile__(
+			"       rsil    a15, "__stringify(LOCKLEVEL)"\n"
+			"       l32i    %0, %2, 0\n"
+			"       add     %0, %0, %1\n"
+			"       s32i    %0, %2, 0\n"
+			"       wsr     a15, ps\n"
+			"       rsync\n"
+			: "=&a" (vval)
+			: "a" (i), "a" (v)
+			: "a15", "memory"
+			);
+#endif
 }
 
 /**
@@ -90,19 +106,35 @@ static inline void atomic_add(int i, atomic_t * v)
  */
 static inline void atomic_sub(int i, atomic_t *v)
 {
-    unsigned int vval;
-
-    __asm__ __volatile__(
-	"rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
-	"l32i    %0, %2, 0              \n\t"
-	"sub     %0, %0, %1             \n\t"
-	"s32i    %0, %2, 0              \n\t"
-	"wsr     a15, ps                \n\t"
-	"rsync                          \n"
-	: "=&a" (vval)
-	: "a" (i), "a" (v)
-	: "a15", "memory"
-	);
+#if XCHAL_HAVE_S32C1I
+	unsigned long tmp;
+	int result;
+
+	__asm__ __volatile__(
+			"1:     l32i    %1, %3, 0\n"
+			"       wsr     %1, scompare1\n"
+			"       sub     %0, %1, %2\n"
+			"       s32c1i  %0, %3, 0\n"
+			"       bne     %0, %1, 1b\n"
+			: "=&a" (result), "=&a" (tmp)
+			: "a" (i), "a" (v)
+			: "memory"
+			);
+#else
+	unsigned int vval;
+
+	__asm__ __volatile__(
+			"       rsil    a15, "__stringify(LOCKLEVEL)"\n"
+			"       l32i    %0, %2, 0\n"
+			"       sub     %0, %0, %1\n"
+			"       s32i    %0, %2, 0\n"
+			"       wsr     a15, ps\n"
+			"       rsync\n"
+			: "=&a" (vval)
+			: "a" (i), "a" (v)
+			: "a15", "memory"
+			);
+#endif
 }
 
 /*
@@ -111,40 +143,78 @@ static inline void atomic_sub(int i, atomic_t *v)
 
 static inline int atomic_add_return(int i, atomic_t * v)
 {
-     unsigned int vval;
-
-    __asm__ __volatile__(
-	"rsil    a15,"__stringify(LOCKLEVEL)"\n\t"
-	"l32i    %0, %2, 0             \n\t"
-	"add     %0, %0, %1            \n\t"
-	"s32i    %0, %2, 0             \n\t"
-	"wsr     a15, ps               \n\t"
-	"rsync                         \n"
-	: "=&a" (vval)
-	: "a" (i), "a" (v)
-	: "a15", "memory"
-	);
-
-    return vval;
+#if XCHAL_HAVE_S32C1I
+	unsigned long tmp;
+	int result;
+
+	__asm__ __volatile__(
+			"1:     l32i    %1, %3, 0\n"
+			"       wsr     %1, scompare1\n"
+			"       add     %0, %1, %2\n"
+			"       s32c1i  %0, %3, 0\n"
+			"       bne     %0, %1, 1b\n"
+			"       add     %0, %0, %2\n"
+			: "=&a" (result), "=&a" (tmp)
+			: "a" (i), "a" (v)
+			: "memory"
+			);
+
+	return result;
+#else
+	unsigned int vval;
+
+	__asm__ __volatile__(
+			"       rsil    a15,"__stringify(LOCKLEVEL)"\n"
+			"       l32i    %0, %2, 0\n"
+			"       add     %0, %0, %1\n"
+			"       s32i    %0, %2, 0\n"
+			"       wsr     a15, ps\n"
+			"       rsync\n"
+			: "=&a" (vval)
+			: "a" (i), "a" (v)
+			: "a15", "memory"
+			);
+
+	return vval;
+#endif
 }
 
 static inline int atomic_sub_return(int i, atomic_t * v)
 {
-    unsigned int vval;
-
-    __asm__ __volatile__(
-	"rsil    a15,"__stringify(LOCKLEVEL)"\n\t"
-	"l32i    %0, %2, 0             \n\t"
-	"sub     %0, %0, %1            \n\t"
-	"s32i    %0, %2, 0             \n\t"
-	"wsr     a15, ps               \n\t"
-	"rsync                         \n"
-	: "=&a" (vval)
-	: "a" (i), "a" (v)
-	: "a15", "memory"
-	);
-
-    return vval;
+#if XCHAL_HAVE_S32C1I
+	unsigned long tmp;
+	int result;
+
+	__asm__ __volatile__(
+			"1:     l32i    %1, %3, 0\n"
+			"       wsr     %1, scompare1\n"
+			"       sub     %0, %1, %2\n"
+			"       s32c1i  %0, %3, 0\n"
+			"       bne     %0, %1, 1b\n"
+			"       sub     %0, %0, %2\n"
+			: "=&a" (result), "=&a" (tmp)
+			: "a" (i), "a" (v)
+			: "memory"
+			);
+
+	return result;
+#else
+	unsigned int vval;
+
+	__asm__ __volatile__(
+			"       rsil    a15,"__stringify(LOCKLEVEL)"\n"
+			"       l32i    %0, %2, 0\n"
+			"       sub     %0, %0, %1\n"
+			"       s32i    %0, %2, 0\n"
+			"       wsr     a15, ps\n"
+			"       rsync\n"
+			: "=&a" (vval)
+			: "a" (i), "a" (v)
+			: "a15", "memory"
+			);
+
+	return vval;
+#endif
 }
 
 /**
@@ -251,38 +321,70 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 
 static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
 {
-    unsigned int all_f = -1;
-    unsigned int vval;
-
-    __asm__ __volatile__(
-	"rsil    a15,"__stringify(LOCKLEVEL)"\n\t"
-	"l32i    %0, %2, 0             \n\t"
-	"xor     %1, %4, %3            \n\t"
-	"and     %0, %0, %4            \n\t"
-	"s32i    %0, %2, 0             \n\t"
-	"wsr     a15, ps               \n\t"
-	"rsync                         \n"
-	: "=&a" (vval), "=a" (mask)
-	: "a" (v), "a" (all_f), "1" (mask)
-	: "a15", "memory"
-	);
+#if XCHAL_HAVE_S32C1I
+	unsigned long tmp;
+	int result;
+
+	__asm__ __volatile__(
+			"1:     l32i    %1, %3, 0\n"
+			"       wsr     %1, scompare1\n"
+			"       and     %0, %1, %2\n"
+			"       s32c1i  %0, %3, 0\n"
+			"       bne     %0, %1, 1b\n"
+			: "=&a" (result), "=&a" (tmp)
+			: "a" (~mask), "a" (v)
+			: "memory"
+			);
+#else
+	unsigned int all_f = -1;
+	unsigned int vval;
+
+	__asm__ __volatile__(
+			"       rsil    a15,"__stringify(LOCKLEVEL)"\n"
+			"       l32i    %0, %2, 0\n"
+			"       xor     %1, %4, %3\n"
+			"       and     %0, %0, %4\n"
+			"       s32i    %0, %2, 0\n"
+			"       wsr     a15, ps\n"
+			"       rsync\n"
+			: "=&a" (vval), "=a" (mask)
+			: "a" (v), "a" (all_f), "1" (mask)
+			: "a15", "memory"
+			);
+#endif
 }
 
 static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
 {
-    unsigned int vval;
-
-    __asm__ __volatile__(
-	"rsil    a15,"__stringify(LOCKLEVEL)"\n\t"
-	"l32i    %0, %2, 0             \n\t"
-	"or      %0, %0, %1            \n\t"
-	"s32i    %0, %2, 0             \n\t"
-	"wsr     a15, ps               \n\t"
-	"rsync                         \n"
-	: "=&a" (vval)
-	: "a" (mask), "a" (v)
-	: "a15", "memory"
-	);
+#if XCHAL_HAVE_S32C1I
+	unsigned long tmp;
+	int result;
+
+	__asm__ __volatile__(
+			"1:     l32i    %1, %3, 0\n"
+			"       wsr     %1, scompare1\n"
+			"       or      %0, %1, %2\n"
+			"       s32c1i  %0, %3, 0\n"
+			"       bne     %0, %1, 1b\n"
+			: "=&a" (result), "=&a" (tmp)
+			: "a" (mask), "a" (v)
+			: "memory"
+			);
+#else
+	unsigned int vval;
+
+	__asm__ __volatile__(
+			"       rsil    a15,"__stringify(LOCKLEVEL)"\n"
+			"       l32i    %0, %2, 0\n"
+			"       or      %0, %0, %1\n"
+			"       s32i    %0, %2, 0\n"
+			"       wsr     a15, ps\n"
+			"       rsync\n"
+			: "=&a" (vval)
+			: "a" (mask), "a" (v)
+			: "a15", "memory"
+			);
+#endif
 }
 
 /* Atomic operations are already serializing */
@@ -294,4 +396,3 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
 #endif /* __KERNEL__ */
 
 #endif /* _XTENSA_ATOMIC_H */
-
diff --git a/arch/xtensa/include/asm/barrier.h b/arch/xtensa/include/asm/barrier.h
index 55707a8..ef02167 100644
--- a/arch/xtensa/include/asm/barrier.h
+++ b/arch/xtensa/include/asm/barrier.h
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2001 - 2012 Tensilica Inc.
  */
 
 #ifndef _XTENSA_SYSTEM_H
@@ -12,8 +12,8 @@
 #define smp_read_barrier_depends() do { } while(0)
 #define read_barrier_depends() do { } while(0)
 
-#define mb()  barrier()
-#define rmb() mb()
+#define mb()  ({ __asm__ __volatile__("memw" : : : "memory"); })
+#define rmb() barrier()
 #define wmb() mb()
 
 #ifdef CONFIG_SMP
diff --git a/arch/xtensa/include/asm/bitops.h b/arch/xtensa/include/asm/bitops.h
index 5270197..84afe58 100644
--- a/arch/xtensa/include/asm/bitops.h
+++ b/arch/xtensa/include/asm/bitops.h
@@ -29,7 +29,6 @@
 #define smp_mb__before_clear_bit()	barrier()
 #define smp_mb__after_clear_bit()	barrier()
 
-#include <asm-generic/bitops/atomic.h>
 #include <asm-generic/bitops/non-atomic.h>
 
 #if XCHAL_HAVE_NSA
@@ -104,6 +103,132 @@ static inline unsigned long __fls(unsigned long word)
 #endif
 
 #include <asm-generic/bitops/fls64.h>
+
+#if XCHAL_HAVE_S32C1I
+
+static inline void set_bit(unsigned int bit, volatile unsigned long *p)
+{
+	unsigned long tmp, value;
+	unsigned long mask = 1UL << (bit & 31);
+
+	p += bit >> 5;
+
+	__asm__ __volatile__(
+			"1:     l32i    %1, %3, 0\n"
+			"       wsr     %1, scompare1\n"
+			"       or      %0, %1, %2\n"
+			"       s32c1i  %0, %3, 0\n"
+			"       bne     %0, %1, 1b\n"
+			: "=&a" (tmp), "=&a" (value)
+			: "a" (mask), "a" (p)
+			: "memory");
+}
+
+static inline void clear_bit(unsigned int bit, volatile unsigned long *p)
+{
+	unsigned long tmp, value;
+	unsigned long mask = 1UL << (bit & 31);
+
+	p += bit >> 5;
+
+	__asm__ __volatile__(
+			"1:     l32i    %1, %3, 0\n"
+			"       wsr     %1, scompare1\n"
+			"       and     %0, %1, %2\n"
+			"       s32c1i  %0, %3, 0\n"
+			"       bne     %0, %1, 1b\n"
+			: "=&a" (tmp), "=&a" (value)
+			: "a" (~mask), "a" (p)
+			: "memory");
+}
+
+static inline void change_bit(unsigned int bit, volatile unsigned long *p)
+{
+	unsigned long tmp, value;
+	unsigned long mask = 1UL << (bit & 31);
+
+	p += bit >> 5;
+
+	__asm__ __volatile__(
+			"1:     l32i    %1, %3, 0\n"
+			"       wsr     %1, scompare1\n"
+			"       xor     %0, %1, %2\n"
+			"       s32c1i  %0, %3, 0\n"
+			"       bne     %0, %1, 1b\n"
+			: "=&a" (tmp), "=&a" (value)
+			: "a" (mask), "a" (p)
+			: "memory");
+}
+
+static inline int
+test_and_set_bit(unsigned int bit, volatile unsigned long *p)
+{
+	unsigned long tmp, value;
+	unsigned long mask = 1UL << (bit & 31);
+
+	p += bit >> 5;
+
+	__asm__ __volatile__(
+			"1:     l32i    %1, %3, 0\n"
+			"       wsr     %1, scompare1\n"
+			"       or      %0, %1, %2\n"
+			"       s32c1i  %0, %3, 0\n"
+			"       bne     %0, %1, 1b\n"
+			: "=&a" (tmp), "=&a" (value)
+			: "a" (mask), "a" (p)
+			: "memory");
+
+	return tmp & mask;
+}
+
+static inline int
+test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
+{
+	unsigned long tmp, value;
+	unsigned long mask = 1UL << (bit & 31);
+
+	p += bit >> 5;
+
+	__asm__ __volatile__(
+			"1:     l32i    %1, %3, 0\n"
+			"       wsr     %1, scompare1\n"
+			"       and     %0, %1, %2\n"
+			"       s32c1i  %0, %3, 0\n"
+			"       bne     %0, %1, 1b\n"
+			: "=&a" (tmp), "=&a" (value)
+			: "a" (~mask), "a" (p)
+			: "memory");
+
+	return tmp & mask;
+}
+
+static inline int
+test_and_change_bit(unsigned int bit, volatile unsigned long *p)
+{
+	unsigned long tmp, value;
+	unsigned long mask = 1UL << (bit & 31);
+
+	p += bit >> 5;
+
+	__asm__ __volatile__(
+			"1:     l32i    %1, %3, 0\n"
+			"       wsr     %1, scompare1\n"
+			"       xor     %0, %1, %2\n"
+			"       s32c1i  %0, %3, 0\n"
+			"       bne     %0, %1, 1b\n"
+			: "=&a" (tmp), "=&a" (value)
+			: "a" (mask), "a" (p)
+			: "memory");
+
+	return tmp & mask;
+}
+
+#else
+
+#include <asm-generic/bitops/atomic.h>
+
+#endif /* XCHAL_HAVE_S32C1I */
+
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/le.h>
 
diff --git a/arch/xtensa/include/asm/bootparam.h b/arch/xtensa/include/asm/bootparam.h
index 9983f2c..057077e 100644
--- a/arch/xtensa/include/asm/bootparam.h
+++ b/arch/xtensa/include/asm/bootparam.h
@@ -22,6 +22,7 @@
 #define BP_TAG_MEMORY		0x1003	/* memory addr and size (bp_meminfo) */
 #define BP_TAG_SERIAL_BAUSRATE	0x1004	/* baud rate of current console. */
 #define BP_TAG_SERIAL_PORT	0x1005	/* serial device of current console */
+#define BP_TAG_FDT		0x1006	/* flat device tree addr */
 
 #define BP_TAG_FIRST		0x7B0B  /* first tag with a version number */
 #define BP_TAG_LAST 		0x7E0B	/* last tag */
diff --git a/arch/xtensa/include/asm/cmpxchg.h b/arch/xtensa/include/asm/cmpxchg.h
index 64dad04..25869a1 100644
--- a/arch/xtensa/include/asm/cmpxchg.h
+++ b/arch/xtensa/include/asm/cmpxchg.h
@@ -22,17 +22,30 @@
 static inline unsigned long
 __cmpxchg_u32(volatile int *p, int old, int new)
 {
-  __asm__ __volatile__("rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
-		       "l32i    %0, %1, 0              \n\t"
-		       "bne	%0, %2, 1f             \n\t"
-		       "s32i    %3, %1, 0              \n\t"
-		       "1:                             \n\t"
-		       "wsr     a15, ps                \n\t"
-		       "rsync                          \n\t"
-		       : "=&a" (old)
-		       : "a" (p), "a" (old), "r" (new)
-		       : "a15", "memory");
-  return old;
+#if XCHAL_HAVE_S32C1I
+	__asm__ __volatile__(
+			"       wsr     %2, scompare1\n"
+			"       s32c1i  %0, %1, 0\n"
+			: "+a" (new)
+			: "a" (p), "a" (old)
+			: "memory"
+			);
+
+	return new;
+#else
+	__asm__ __volatile__(
+			"       rsil    a15, "__stringify(LOCKLEVEL)"\n"
+			"       l32i    %0, %1, 0\n"
+			"       bne     %0, %2, 1f\n"
+			"       s32i    %3, %1, 0\n"
+			"1:\n"
+			"       wsr     a15, ps\n"
+			"       rsync\n"
+			: "=&a" (old)
+			: "a" (p), "a" (old), "r" (new)
+			: "a15", "memory");
+	return old;
+#endif
 }
 /* This function doesn't exist, so you'll get a linker error
  * if something tries to do an invalid cmpxchg(). */
@@ -93,16 +106,32 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
 
 static inline unsigned long xchg_u32(volatile int * m, unsigned long val)
 {
-  unsigned long tmp;
-  __asm__ __volatile__("rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
-		       "l32i    %0, %1, 0              \n\t"
-		       "s32i    %2, %1, 0              \n\t"
-		       "wsr     a15, ps                \n\t"
-		       "rsync                          \n\t"
-		       : "=&a" (tmp)
-		       : "a" (m), "a" (val)
-		       : "a15", "memory");
-  return tmp;
+#if XCHAL_HAVE_S32C1I
+	unsigned long tmp, result;
+	__asm__ __volatile__(
+			"1:     l32i    %1, %2, 0\n"
+			"       mov     %0, %3\n"
+			"       wsr     %1, scompare1\n"
+			"       s32c1i  %0, %2, 0\n"
+			"       bne     %0, %1, 1b\n"
+			: "=&a" (result), "=&a" (tmp)
+			: "a" (m), "a" (val)
+			: "memory"
+			);
+	return result;
+#else
+	unsigned long tmp;
+	__asm__ __volatile__(
+			"       rsil    a15, "__stringify(LOCKLEVEL)"\n"
+			"       l32i    %0, %1, 0\n"
+			"       s32i    %2, %1, 0\n"
+			"       wsr     a15, ps\n"
+			"       rsync\n"
+			: "=&a" (tmp)
+			: "a" (m), "a" (val)
+			: "a15", "memory");
+	return tmp;
+#endif
 }
 
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
diff --git a/arch/xtensa/include/asm/dma-mapping.h b/arch/xtensa/include/asm/dma-mapping.h
index 492c957..eb69743 100644
--- a/arch/xtensa/include/asm/dma-mapping.h
+++ b/arch/xtensa/include/asm/dma-mapping.h
@@ -16,6 +16,8 @@
 #include <linux/mm.h>
 #include <linux/scatterlist.h>
 
+#define DMA_ERROR_CODE		(~(dma_addr_t)0x0)
+
 /*
  * DMA-consistent mapping functions.
  */
diff --git a/arch/xtensa/include/asm/initialize_mmu.h b/arch/xtensa/include/asm/initialize_mmu.h
new file mode 100644
index 0000000..e1f8ba4
--- /dev/null
+++ b/arch/xtensa/include/asm/initialize_mmu.h
@@ -0,0 +1,55 @@
+/*
+ * arch/xtensa/include/asm/initialize_mmu.h
+ *
+ * Initializes MMU:
+ *
+ *      For the new V3 MMU we remap the TLB from virtual == physical
+ *      to the standard Linux mapping used in earlier MMU's.
+ *
+ *      The the MMU we also support a new configuration register that
+ *      specifies how the S32C1I instruction operates with the cache
+ *      controller.
+ *
+ * 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.
+ *
+ * Copyright (C) 2008 - 2012 Tensilica, Inc.
+ *
+ *   Marc Gauthier <marc@tensilica.com>
+ *   Pete Delaney <piet@tensilica.com>
+ */
+
+#ifndef _XTENSA_INITIALIZE_MMU_H
+#define _XTENSA_INITIALIZE_MMU_H
+
+#ifdef __ASSEMBLY__
+
+#define XTENSA_HWVERSION_RC_2009_0 230000
+
+	.macro	initialize_mmu
+
+#if XCHAL_HAVE_S32C1I && (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0)
+/*
+ * We Have Atomic Operation Control (ATOMCTL) Register; Initialize it.
+ * For details see Documentation/xtensa/atomctl.txt
+ */
+#if XCHAL_DCACHE_IS_COHERENT
+	movi	a3, 0x25	/* For SMP/MX -- internal for writeback,
+				 * RCW otherwise
+				 */
+#else
+	movi	a3, 0x29	/* non-MX -- Most cores use Std Memory
+				 * Controlers which usually can't use RCW
+				 */
+#endif
+	wsr	a3, atomctl
+#endif  /* XCHAL_HAVE_S32C1I &&
+	 * (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0)
+	 */
+
+	.endm
+
+#endif /*__ASSEMBLY__*/
+
+#endif /* _XTENSA_INITIALIZE_MMU_H */
diff --git a/arch/xtensa/include/asm/prom.h b/arch/xtensa/include/asm/prom.h
new file mode 100644
index 0000000..f3d7cd2
--- /dev/null
+++ b/arch/xtensa/include/asm/prom.h
@@ -0,0 +1,6 @@
+#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/include/asm/ptrace.h b/arch/xtensa/include/asm/ptrace.h
index da21c17..9fe249c 100644
--- a/arch/xtensa/include/asm/ptrace.h
+++ b/arch/xtensa/include/asm/ptrace.h
@@ -37,7 +37,7 @@ struct pt_regs {
 	unsigned long windowstart;	/*  52 */
 	unsigned long syscall;		/*  56 */
 	unsigned long icountlevel;	/*  60 */
-	int reserved[1];		/*  64 */
+	unsigned long scompare1;	/*  64 */
 
 	/* Additional configurable registers that are used by the compiler. */
 	xtregs_opt_t xtregs_opt;
diff --git a/arch/xtensa/include/asm/regs.h b/arch/xtensa/include/asm/regs.h
index 8a8aa61..6aaf6d6 100644
--- a/arch/xtensa/include/asm/regs.h
+++ b/arch/xtensa/include/asm/regs.h
@@ -52,6 +52,10 @@
 #define EXCCAUSE_SPECULATION			7
 #define EXCCAUSE_PRIVILEGED			8
 #define EXCCAUSE_UNALIGNED			9
+#define EXCCAUSE_INSTR_DATA_ERROR		12
+#define EXCCAUSE_LOAD_STORE_DATA_ERROR		13
+#define EXCCAUSE_INSTR_ADDR_ERROR		14
+#define EXCCAUSE_LOAD_STORE_ADDR_ERROR		15
 #define EXCCAUSE_ITLB_MISS			16
 #define EXCCAUSE_ITLB_MULTIHIT			17
 #define EXCCAUSE_ITLB_PRIVILEGE			18
diff --git a/arch/xtensa/include/asm/signal.h b/arch/xtensa/include/asm/signal.h
index 72fd44c..6f586bd 100644
--- a/arch/xtensa/include/asm/signal.h
+++ b/arch/xtensa/include/asm/signal.h
@@ -27,7 +27,6 @@ struct k_sigaction {
 };
 
 #include <asm/sigcontext.h>
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
 
 #endif	/* __ASSEMBLY__ */
 #endif	/* _XTENSA_SIGNAL_H */
diff --git a/arch/xtensa/include/asm/spinlock.h b/arch/xtensa/include/asm/spinlock.h
index 8ff2364..0397590 100644
--- a/arch/xtensa/include/asm/spinlock.h
+++ b/arch/xtensa/include/asm/spinlock.h
@@ -11,6 +11,192 @@
 #ifndef _XTENSA_SPINLOCK_H
 #define _XTENSA_SPINLOCK_H
 
-#include <linux/spinlock.h>
+/*
+ * spinlock
+ *
+ * There is at most one owner of a spinlock.  There are not different
+ * types of spinlock owners like there are for rwlocks (see below).
+ *
+ * When trying to obtain a spinlock, the function "spins" forever, or busy-
+ * waits, until the lock is obtained.  When spinning, presumably some other
+ * owner will soon give up the spinlock making it available to others.  Use
+ * the trylock functions to avoid spinning forever.
+ *
+ * possible values:
+ *
+ *    0         nobody owns the spinlock
+ *    1         somebody owns the spinlock
+ */
+
+#define __raw_spin_is_locked(x) ((x)->slock != 0)
+#define __raw_spin_unlock_wait(lock) \
+	do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
+
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__(
+			"       movi    %0, 0\n"
+			"       wsr     %0, scompare1\n"
+			"1:     movi    %0, 1\n"
+			"       s32c1i  %0, %1, 0\n"
+			"       bnez    %0, 1b\n"
+			: "=&a" (tmp)
+			: "a" (&lock->slock)
+			: "memory");
+}
+
+/* Returns 1 if the lock is obtained, 0 otherwise. */
+
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__(
+			"       movi    %0, 0\n"
+			"       wsr     %0, scompare1\n"
+			"       movi    %0, 1\n"
+			"       s32c1i  %0, %1, 0\n"
+			: "=&a" (tmp)
+			: "a" (&lock->slock)
+			: "memory");
+
+	return tmp == 0 ? 1 : 0;
+}
+
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__(
+			"       movi    %0, 0\n"
+			"       s32ri   %0, %1, 0\n"
+			: "=&a" (tmp)
+			: "a" (&lock->slock)
+			: "memory");
+}
+
+/*
+ * rwlock
+ *
+ * Read-write locks are really a more flexible spinlock.  They allow
+ * multiple readers but only one writer.  Write ownership is exclusive
+ * (i.e., all other readers and writers are blocked from ownership while
+ * there is a write owner).  These rwlocks are unfair to writers.  Writers
+ * can be starved for an indefinite time by readers.
+ *
+ * possible values:
+ *
+ *   0          nobody owns the rwlock
+ *  >0          one or more readers own the rwlock
+ *                (the positive value is the actual number of readers)
+ *  0x80000000  one writer owns the rwlock, no other writers, no readers
+ */
+
+#define __raw_write_can_lock(x)  ((x)->lock == 0)
+
+static inline void __raw_write_lock(raw_rwlock_t *rw)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__(
+			"       movi    %0, 0\n"
+			"       wsr     %0, scompare1\n"
+			"1:     movi    %0, 1\n"
+			"       slli    %0, %0, 31\n"
+			"       s32c1i  %0, %1, 0\n"
+			"       bnez    %0, 1b\n"
+			: "=&a" (tmp)
+			: "a" (&rw->lock)
+			: "memory");
+}
+
+/* Returns 1 if the lock is obtained, 0 otherwise. */
+
+static inline int __raw_write_trylock(raw_rwlock_t *rw)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__(
+			"       movi    %0, 0\n"
+			"       wsr     %0, scompare1\n"
+			"       movi    %0, 1\n"
+			"       slli    %0, %0, 31\n"
+			"       s32c1i  %0, %1, 0\n"
+			: "=&a" (tmp)
+			: "a" (&rw->lock)
+			: "memory");
+
+	return tmp == 0 ? 1 : 0;
+}
+
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__(
+			"       movi    %0, 0\n"
+			"       s32ri   %0, %1, 0\n"
+			: "=&a" (tmp)
+			: "a" (&rw->lock)
+			: "memory");
+}
+
+static inline void __raw_read_lock(raw_rwlock_t *rw)
+{
+	unsigned long tmp;
+	unsigned long result;
+
+	__asm__ __volatile__(
+			"1:     l32i    %1, %2, 0\n"
+			"       bltz    %1, 1b\n"
+			"       wsr     %1, scompare1\n"
+			"       addi    %0, %1, 1\n"
+			"       s32c1i  %0, %2, 0\n"
+			"       bne     %0, %1, 1b\n"
+			: "=&a" (result), "=&a" (tmp)
+			: "a" (&rw->lock)
+			: "memory");
+}
+
+/* Returns 1 if the lock is obtained, 0 otherwise. */
+
+static inline int __raw_read_trylock(raw_rwlock_t *rw)
+{
+	unsigned long result;
+	unsigned long tmp;
+
+	__asm__ __volatile__(
+			"       l32i    %1, %2, 0\n"
+			"       addi    %0, %1, 1\n"
+			"       bltz    %0, 1f\n"
+			"       wsr     %1, scompare1\n"
+			"       s32c1i  %0, %2, 0\n"
+			"       sub     %0, %0, %1\n"
+			"1:\n"
+			: "=&a" (result), "=&a" (tmp)
+			: "a" (&rw->lock)
+			: "memory");
+
+	return result == 0;
+}
+
+static inline void __raw_read_unlock(raw_rwlock_t *rw)
+{
+	unsigned long tmp1, tmp2;
+
+	__asm__ __volatile__(
+			"1:     l32i    %1, %2, 0\n"
+			"       addi    %0, %1, -1\n"
+			"       wsr     %1, scompare1\n"
+			"       s32c1i  %0, %2, 0\n"
+			"       bne     %0, %1, 1b\n"
+			: "=&a" (tmp1), "=&a" (tmp2)
+			: "a" (&rw->lock)
+			: "memory");
+}
 
 #endif	/* _XTENSA_SPINLOCK_H */
diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h
index 124aeee..b00c928 100644
--- a/arch/xtensa/include/asm/syscall.h
+++ b/arch/xtensa/include/asm/syscall.h
@@ -10,8 +10,6 @@
 
 struct pt_regs;
 struct sigaction;
-asmlinkage long sys_execve(char*, char**, char**, struct pt_regs*);
-asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
 asmlinkage long xtensa_ptrace(long, long, long, long);
 asmlinkage long xtensa_sigreturn(struct pt_regs*);
 asmlinkage long xtensa_rt_sigreturn(struct pt_regs*);
diff --git a/arch/xtensa/include/asm/traps.h b/arch/xtensa/include/asm/traps.h
new file mode 100644
index 0000000..54f7044
--- /dev/null
+++ b/arch/xtensa/include/asm/traps.h
@@ -0,0 +1,23 @@
+/*
+ * arch/xtensa/include/asm/traps.h
+ *
+ * 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.
+ *
+ * Copyright (C) 2012 Tensilica Inc.
+ */
+#ifndef _XTENSA_TRAPS_H
+#define _XTENSA_TRAPS_H
+
+#include <asm/ptrace.h>
+
+/*
+ * handler must be either of the following:
+ *  void (*)(struct pt_regs *regs);
+ *  void (*)(struct pt_regs *regs, unsigned long exccause);
+ */
+extern void * __init trap_set_handler(int cause, void *handler);
+extern void do_unhandled(struct pt_regs *regs, unsigned long exccause);
+
+#endif /* _XTENSA_TRAPS_H */
diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h
index f4e6eaa..e002dbc 100644
--- a/arch/xtensa/include/asm/unistd.h
+++ b/arch/xtensa/include/asm/unistd.h
@@ -2,6 +2,7 @@
 #define _XTENSA_UNISTD_H
 
 #define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
 
 /*
diff --git a/arch/xtensa/include/uapi/asm/ioctls.h b/arch/xtensa/include/uapi/asm/ioctls.h
index 2aa4cd9..b4cb110 100644
--- a/arch/xtensa/include/uapi/asm/ioctls.h
+++ b/arch/xtensa/include/uapi/asm/ioctls.h
@@ -101,6 +101,9 @@
 #define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
 #define TIOCVHANGUP	_IO('T', 0x37)
+#define TIOCGPKT	_IOR('T', 0x38, int) /* Get packet mode state */
+#define TIOCGPTLCK	_IOR('T', 0x39, int) /* Get Pty lock state */
+#define TIOCGEXCL	_IOR('T', 0x40, int) /* Get exclusive mode state */
 
 #define TIOCSERCONFIG	_IO('T', 83)
 #define TIOCSERGWILD	_IOR('T', 84,  int)
diff --git a/arch/xtensa/include/uapi/asm/mman.h b/arch/xtensa/include/uapi/asm/mman.h
index 25bc6c1..00eed67 100644
--- a/arch/xtensa/include/uapi/asm/mman.h
+++ b/arch/xtensa/include/uapi/asm/mman.h
@@ -93,4 +93,15 @@
 /* compatibility flags */
 #define MAP_FILE	0
 
+/*
+ * When MAP_HUGETLB is set bits [26:31] encode the log2 of the huge page size.
+ * This gives us 6 bits, which is enough until someone invents 128 bit address
+ * spaces.
+ *
+ * Assume these are all power of twos.
+ * When 0 use the default page size.
+ */
+#define MAP_HUGE_SHIFT	26
+#define MAP_HUGE_MASK	0x3f
+
 #endif /* _XTENSA_MMAN_H */
diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h
index e36c681..38079be 100644
--- a/arch/xtensa/include/uapi/asm/socket.h
+++ b/arch/xtensa/include/uapi/asm/socket.h
@@ -52,6 +52,7 @@
 
 #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
diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h
index 9f36d0e..5162418 100644
--- a/arch/xtensa/include/uapi/asm/unistd.h
+++ b/arch/xtensa/include/uapi/asm/unistd.h
@@ -260,7 +260,7 @@ __SYSCALL(115, sys_sendmmsg, 4)
 /* Process Operations */
 
 #define __NR_clone 				116
-__SYSCALL(116, xtensa_clone, 5)
+__SYSCALL(116, sys_clone, 5)
 #define __NR_execve 				117
 __SYSCALL(117, sys_execve, 3)
 #define __NR_exit 				118
diff --git a/arch/xtensa/kernel/align.S b/arch/xtensa/kernel/align.S
index 934ae58..39d2f59 100644
--- a/arch/xtensa/kernel/align.S
+++ b/arch/xtensa/kernel/align.S
@@ -450,6 +450,7 @@ ENTRY(fast_unaligned)
 1:	movi	a0, _user_exception
 	jx	a0
 
+ENDPROC(fast_unaligned)
 
 #endif /* XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION */
 
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c
index 7dc3f91..845475a 100644
--- a/arch/xtensa/kernel/asm-offsets.c
+++ b/arch/xtensa/kernel/asm-offsets.c
@@ -41,6 +41,7 @@ int main(void)
 	DEFINE(PT_SAR, offsetof (struct pt_regs, sar));
 	DEFINE(PT_ICOUNTLEVEL, offsetof (struct pt_regs, icountlevel));
 	DEFINE(PT_SYSCALL, offsetof (struct pt_regs, syscall));
+	DEFINE(PT_SCOMPARE1, offsetof(struct pt_regs, scompare1));
 	DEFINE(PT_AREG, offsetof (struct pt_regs, areg[0]));
 	DEFINE(PT_AREG0, offsetof (struct pt_regs, areg[0]));
 	DEFINE(PT_AREG1, offsetof (struct pt_regs, areg[1]));
diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S
index 54c3be3..60bb135 100644
--- a/arch/xtensa/kernel/coprocessor.S
+++ b/arch/xtensa/kernel/coprocessor.S
@@ -43,10 +43,13 @@
 /* IO protection is currently unsupported. */
 
 ENTRY(fast_io_protect)
+
 	wsr	a0, excsave1
 	movi	a0, unrecoverable_exception
 	callx0	a0
 
+ENDPROC(fast_io_protect)
+
 #if XTENSA_HAVE_COPROCESSORS
 
 /*
@@ -139,6 +142,7 @@ ENTRY(fast_io_protect)
  */
 
 ENTRY(coprocessor_save)
+
 	entry	a1, 32
 	s32i	a0, a1, 0
 	movi	a0, .Lsave_cp_regs_jump_table
@@ -150,7 +154,10 @@ ENTRY(coprocessor_save)
 1:	l32i	a0, a1, 0
 	retw
 
+ENDPROC(coprocessor_save)
+
 ENTRY(coprocessor_load)
+
 	entry	a1, 32
 	s32i	a0, a1, 0
 	movi	a0, .Lload_cp_regs_jump_table
@@ -162,6 +169,8 @@ ENTRY(coprocessor_load)
 1:	l32i	a0, a1, 0
 	retw
 
+ENDPROC(coprocessor_load)
+
 /*
  * coprocessor_flush(struct task_info*, index) 
  *                             a2        a3
@@ -178,6 +187,7 @@ ENTRY(coprocessor_load)
 
 
 ENTRY(coprocessor_flush)
+
 	entry	a1, 32
 	s32i	a0, a1, 0
 	movi	a0, .Lsave_cp_regs_jump_table
@@ -191,6 +201,8 @@ ENTRY(coprocessor_flush)
 1:	l32i	a0, a1, 0
 	retw
 
+ENDPROC(coprocessor_flush)
+
 ENTRY(coprocessor_restore)
 	entry	a1, 32
 	s32i	a0, a1, 0
@@ -205,6 +217,8 @@ ENTRY(coprocessor_restore)
 1:	l32i	a0, a1, 0
 	retw
 
+ENDPROC(coprocessor_restore)
+
 /*
  * Entry condition:
  *
@@ -220,10 +234,12 @@ ENTRY(coprocessor_restore)
  */
 
 ENTRY(fast_coprocessor_double)
+
 	wsr	a0, excsave1
 	movi	a0, unrecoverable_exception
 	callx0	a0
 
+ENDPROC(fast_coprocessor_double)
 
 ENTRY(fast_coprocessor)
 
@@ -327,9 +343,15 @@ ENTRY(fast_coprocessor)
 
 	rfe
 
+ENDPROC(fast_coprocessor)
+
 	.data
+
 ENTRY(coprocessor_owner)
+
 	.fill XCHAL_CP_MAX, 4, 0
 
+END(coprocessor_owner)
+
 #endif /* XTENSA_HAVE_COPROCESSORS */
 
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 90bfc1d..4c2f270 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -219,6 +219,7 @@ _user_exception:
 
 	j	common_exception
 
+ENDPROC(user_exception)
 
 /*
  * First-level exit handler for kernel exceptions
@@ -371,6 +372,13 @@ common_exception:
 	s32i	a2, a1, PT_LBEG
 	s32i	a3, a1, PT_LEND
 
+	/* Save SCOMPARE1 */
+
+#if XCHAL_HAVE_S32C1I
+	rsr     a2, scompare1
+	s32i    a2, a1, PT_SCOMPARE1
+#endif
+
 	/* Save optional registers. */
 
 	save_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT
@@ -432,6 +440,12 @@ common_exception_return:
 
 	load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT
 
+	/* Restore SCOMPARE1 */
+
+#if XCHAL_HAVE_S32C1I
+	l32i    a2, a1, PT_SCOMPARE1
+	wsr     a2, scompare1
+#endif
 	wsr	a3, ps		/* disable interrupts */
 
 	_bbci.l	a3, PS_UM_BIT, kernel_exception_exit
@@ -641,6 +655,8 @@ common_exception_exit:
 	l32i	a1, a1, PT_AREG1
 	rfde
 
+ENDPROC(kernel_exception)
+
 /*
  * Debug exception handler.
  *
@@ -701,6 +717,7 @@ ENTRY(debug_exception)
 	/* Debug exception while in exception mode. */
 1:	j	1b	// FIXME!!
 
+ENDPROC(debug_exception)
 
 /*
  * We get here in case of an unrecoverable exception.
@@ -751,6 +768,7 @@ ENTRY(unrecoverable_exception)
 
 1:	j	1b
 
+ENDPROC(unrecoverable_exception)
 
 /* -------------------------- FAST EXCEPTION HANDLERS ----------------------- */
 
@@ -929,6 +947,7 @@ ENTRY(fast_alloca)
 	l32i	a2, a2, PT_AREG2
 	rfe
 
+ENDPROC(fast_alloca)
 
 /*
  * fast system calls.
@@ -966,6 +985,8 @@ ENTRY(fast_syscall_kernel)
 
 	j	kernel_exception
 
+ENDPROC(fast_syscall_kernel)
+
 ENTRY(fast_syscall_user)
 
 	/* Skip syscall. */
@@ -983,6 +1004,8 @@ ENTRY(fast_syscall_user)
 
 	j	user_exception
 
+ENDPROC(fast_syscall_user)
+
 ENTRY(fast_syscall_unrecoverable)
 
         /* Restore all states. */
@@ -995,7 +1018,7 @@ ENTRY(fast_syscall_unrecoverable)
         movi    a0, unrecoverable_exception
         callx0  a0
 
-
+ENDPROC(fast_syscall_unrecoverable)
 
 /*
  * sysxtensa syscall handler
@@ -1101,7 +1124,7 @@ CATCH
 	movi	a2, -EINVAL
 	rfe
 
-
+ENDPROC(fast_syscall_xtensa)
 
 
 /* fast_syscall_spill_registers.
@@ -1160,6 +1183,8 @@ ENTRY(fast_syscall_spill_registers)
 	movi	a2, 0
 	rfe
 
+ENDPROC(fast_syscall_spill_registers)
+
 /* Fixup handler.
  *
  * We get here if the spill routine causes an exception, e.g. tlb miss.
@@ -1464,6 +1489,8 @@ ENTRY(_spill_registers)
 	callx0	a0		# should not return
 1:	j	1b
 
+ENDPROC(_spill_registers)
+
 #ifdef CONFIG_MMU
 /*
  * We should never get here. Bail out!
@@ -1475,6 +1502,8 @@ ENTRY(fast_second_level_miss_double_kernel)
 	callx0	a0		# should not return
 1:	j	1b
 
+ENDPROC(fast_second_level_miss_double_kernel)
+
 /* First-level entry handler for user, kernel, and double 2nd-level
  * TLB miss exceptions.  Note that for now, user and kernel miss
  * exceptions share the same entry point and are handled identically.
@@ -1682,6 +1711,7 @@ ENTRY(fast_second_level_miss)
 	j	_kernel_exception
 1:	j	_user_exception
 
+ENDPROC(fast_second_level_miss)
 
 /*
  * StoreProhibitedException
@@ -1777,6 +1807,9 @@ ENTRY(fast_store_prohibited)
 	bbsi.l	a2, PS_UM_BIT, 1f
 	j	_kernel_exception
 1:	j	_user_exception
+
+ENDPROC(fast_store_prohibited)
+
 #endif /* CONFIG_MMU */
 
 /*
@@ -1787,6 +1820,7 @@ ENTRY(fast_store_prohibited)
  */
 
 ENTRY(system_call)
+
 	entry	a1, 32
 
 	/* regs->syscall = regs->areg[2] */
@@ -1831,6 +1865,8 @@ ENTRY(system_call)
 	callx4	a4
 	retw
 
+ENDPROC(system_call)
+
 
 /*
  * Task switch.
@@ -1899,6 +1935,7 @@ ENTRY(_switch_to)
 
 	retw
 
+ENDPROC(_switch_to)
 
 ENTRY(ret_from_fork)
 
@@ -1914,6 +1951,8 @@ ENTRY(ret_from_fork)
 
 	j	common_exception_return
 
+ENDPROC(ret_from_fork)
+
 /*
  * Kernel thread creation helper
  * On entry, set up by copy_thread: a2 = thread_fn, a3 = thread_fn arg
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S
index bdc5078..9013ae0 100644
--- a/arch/xtensa/kernel/head.S
+++ b/arch/xtensa/kernel/head.S
@@ -18,6 +18,7 @@
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/cacheasm.h>
+#include <asm/initialize_mmu.h>
 
 #include <linux/init.h>
 #include <linux/linkage.h>
@@ -47,16 +48,19 @@
 	 */
 
 	__HEAD
-	.globl _start
-_start:	_j	2f
+ENTRY(_start)
+
+	_j	2f
 	.align	4
 1:	.word	_startup
 2:	l32r	a0, 1b
 	jx	a0
 
+ENDPROC(_start)
+
 	.section .init.text, "ax"
-	.align 4
-_startup:
+
+ENTRY(_startup)
 
 	/* Disable interrupts and exceptions. */
 
@@ -152,6 +156,8 @@ _startup:
 
 	isync
 
+	initialize_mmu
+
 	/* Unpack data sections
 	 *
 	 * The linker script used to build the Linux kernel image
@@ -230,6 +236,7 @@ _startup:
 should_never_return:
 	j	should_never_return
 
+ENDPROC(_startup)
 
 /*
  * BSS section
@@ -239,6 +246,8 @@ __PAGE_ALIGNED_BSS
 #ifdef CONFIG_MMU
 ENTRY(swapper_pg_dir)
 	.fill	PAGE_SIZE, 1, 0
+END(swapper_pg_dir)
 #endif
 ENTRY(empty_zero_page)
 	.fill	PAGE_SIZE, 1, 0
+END(empty_zero_page)
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c
index a6ce3e5..6f4f974 100644
--- a/arch/xtensa/kernel/irq.c
+++ b/arch/xtensa/kernel/irq.c
@@ -18,6 +18,8 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/kernel_stat.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
 
 #include <asm/uaccess.h>
 #include <asm/platform.h>
@@ -26,19 +28,22 @@ static unsigned int cached_irq_mask;
 
 atomic_t irq_err_count;
 
+static struct irq_domain *root_domain;
+
 /*
  * do_IRQ handles all normal device IRQ's (the special
  * SMP cross-CPU interrupts have their own specific
  * handlers).
  */
 
-asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
+asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
 {
 	struct pt_regs *old_regs = set_irq_regs(regs);
+	int irq = irq_find_mapping(root_domain, hwirq);
 
-	if (irq >= NR_IRQS) {
+	if (hwirq >= NR_IRQS) {
 		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
-				__func__, irq);
+				__func__, hwirq);
 	}
 
 	irq_enter();
@@ -71,40 +76,39 @@ int arch_show_interrupts(struct seq_file *p, int prec)
 
 static void xtensa_irq_mask(struct irq_data *d)
 {
-	cached_irq_mask &= ~(1 << d->irq);
+	cached_irq_mask &= ~(1 << d->hwirq);
 	set_sr (cached_irq_mask, intenable);
 }
 
 static void xtensa_irq_unmask(struct irq_data *d)
 {
-	cached_irq_mask |= 1 << d->irq;
+	cached_irq_mask |= 1 << d->hwirq;
 	set_sr (cached_irq_mask, intenable);
 }
 
 static void xtensa_irq_enable(struct irq_data *d)
 {
-	variant_irq_enable(d->irq);
+	variant_irq_enable(d->hwirq);
 	xtensa_irq_unmask(d);
 }
 
 static void xtensa_irq_disable(struct irq_data *d)
 {
 	xtensa_irq_mask(d);
-	variant_irq_disable(d->irq);
+	variant_irq_disable(d->hwirq);
 }
 
 static void xtensa_irq_ack(struct irq_data *d)
 {
-	set_sr(1 << d->irq, intclear);
+	set_sr(1 << d->hwirq, intclear);
 }
 
 static int xtensa_irq_retrigger(struct irq_data *d)
 {
-	set_sr (1 << d->irq, INTSET);
+	set_sr(1 << d->hwirq, intset);
 	return 1;
 }
 
-
 static struct irq_chip xtensa_irq_chip = {
 	.name		= "xtensa",
 	.irq_enable	= xtensa_irq_enable,
@@ -115,37 +119,99 @@ static struct irq_chip xtensa_irq_chip = {
 	.irq_retrigger	= xtensa_irq_retrigger,
 };
 
-void __init init_IRQ(void)
+static int xtensa_irq_map(struct irq_domain *d, unsigned int irq,
+		irq_hw_number_t hw)
 {
-	int index;
-
-	for (index = 0; index < XTENSA_NR_IRQS; index++) {
-		int mask = 1 << index;
-
-		if (mask & XCHAL_INTTYPE_MASK_SOFTWARE)
-			irq_set_chip_and_handler(index, &xtensa_irq_chip,
-						 handle_simple_irq);
+	u32 mask = 1 << hw;
+
+	if (mask & XCHAL_INTTYPE_MASK_SOFTWARE) {
+		irq_set_chip_and_handler_name(irq, &xtensa_irq_chip,
+				handle_simple_irq, "level");
+		irq_set_status_flags(irq, IRQ_LEVEL);
+	} else if (mask & XCHAL_INTTYPE_MASK_EXTERN_EDGE) {
+		irq_set_chip_and_handler_name(irq, &xtensa_irq_chip,
+				handle_edge_irq, "edge");
+		irq_clear_status_flags(irq, IRQ_LEVEL);
+	} else if (mask & XCHAL_INTTYPE_MASK_EXTERN_LEVEL) {
+		irq_set_chip_and_handler_name(irq, &xtensa_irq_chip,
+				handle_level_irq, "level");
+		irq_set_status_flags(irq, IRQ_LEVEL);
+	} else if (mask & XCHAL_INTTYPE_MASK_TIMER) {
+		irq_set_chip_and_handler_name(irq, &xtensa_irq_chip,
+				handle_edge_irq, "edge");
+		irq_clear_status_flags(irq, IRQ_LEVEL);
+	} else {/* XCHAL_INTTYPE_MASK_WRITE_ERROR */
+		/* XCHAL_INTTYPE_MASK_NMI */
+
+		irq_set_chip_and_handler_name(irq, &xtensa_irq_chip,
+				handle_level_irq, "level");
+		irq_set_status_flags(irq, IRQ_LEVEL);
+	}
+	return 0;
+}
 
-		else if (mask & XCHAL_INTTYPE_MASK_EXTERN_EDGE)
-			irq_set_chip_and_handler(index, &xtensa_irq_chip,
-						 handle_edge_irq);
+static unsigned map_ext_irq(unsigned ext_irq)
+{
+	unsigned mask = XCHAL_INTTYPE_MASK_EXTERN_EDGE |
+		XCHAL_INTTYPE_MASK_EXTERN_LEVEL;
+	unsigned i;
 
-		else if (mask & XCHAL_INTTYPE_MASK_EXTERN_LEVEL)
-			irq_set_chip_and_handler(index, &xtensa_irq_chip,
-						 handle_level_irq);
+	for (i = 0; mask; ++i, mask >>= 1) {
+		if ((mask & 1) && ext_irq-- == 0)
+			return i;
+	}
+	return XCHAL_NUM_INTERRUPTS;
+}
 
-		else if (mask & XCHAL_INTTYPE_MASK_TIMER)
-			irq_set_chip_and_handler(index, &xtensa_irq_chip,
-						 handle_edge_irq);
+/*
+ * Device Tree IRQ specifier translation function which works with one or
+ * two cell bindings. First cell value maps directly to the hwirq number.
+ * Second cell if present specifies whether hwirq number is external (1) or
+ * internal (0).
+ */
+int xtensa_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
+		const u32 *intspec, unsigned int intsize,
+		unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (WARN_ON(intsize < 1 || intsize > 2))
+		return -EINVAL;
+	if (intsize == 2 && intspec[1] == 1) {
+		unsigned int_irq = map_ext_irq(intspec[0]);
+		if (int_irq < XCHAL_NUM_INTERRUPTS)
+			*out_hwirq = int_irq;
+		else
+			return -EINVAL;
+	} else {
+		*out_hwirq = intspec[0];
+	}
+	*out_type = IRQ_TYPE_NONE;
+	return 0;
+}
 
-		else	/* XCHAL_INTTYPE_MASK_WRITE_ERROR */
-			/* XCHAL_INTTYPE_MASK_NMI */
+static const struct irq_domain_ops xtensa_irq_domain_ops = {
+	.xlate = xtensa_irq_domain_xlate,
+	.map = xtensa_irq_map,
+};
 
-			irq_set_chip_and_handler(index, &xtensa_irq_chip,
-						 handle_level_irq);
-	}
+void __init init_IRQ(void)
+{
+	struct device_node *intc = NULL;
 
 	cached_irq_mask = 0;
+	set_sr(~0, intclear);
+
+#ifdef CONFIG_OF
+	/* The interrupt controller device node is mandatory */
+	intc = of_find_compatible_node(NULL, NULL, "xtensa,pic");
+	BUG_ON(!intc);
+
+	root_domain = irq_domain_add_linear(intc, NR_IRQS,
+			&xtensa_irq_domain_ops, NULL);
+#else
+	root_domain = irq_domain_add_legacy(intc, NR_IRQS, 0, 0,
+			&xtensa_irq_domain_ops, NULL);
+#endif
+	irq_set_default_host(root_domain);
 
 	variant_init_irq();
 }
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index 09ae7bf..1accf28 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -199,8 +199,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
  */
 
 int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
-		unsigned long thread_fn_arg,
-		struct task_struct *p, struct pt_regs *unused)
+		unsigned long thread_fn_arg, struct task_struct *p)
 {
 	struct pt_regs *childregs = task_pt_regs(p);
 
@@ -364,12 +363,3 @@ int dump_fpu(void)
 {
 	return 0;
 }
-
-asmlinkage
-long xtensa_clone(unsigned long clone_flags, unsigned long newsp,
-                  void __user *parent_tid, void *child_tls,
-                  void __user *child_tid, long a5,
-                  struct pt_regs *regs)
-{
-        return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
-}
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index b237988..64d80e4 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -22,6 +22,11 @@
 #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>
 #endif
@@ -42,6 +47,7 @@
 #include <asm/page.h>
 #include <asm/setup.h>
 #include <asm/param.h>
+#include <asm/traps.h>
 
 #include <platform/hardware.h>
 
@@ -64,6 +70,11 @@ int initrd_is_mapped = 0;
 extern int initrd_below_start_ok;
 #endif
 
+#ifdef CONFIG_OF
+extern u32 __dtb_start[];
+void *dtb_start = __dtb_start;
+#endif
+
 unsigned char aux_device_present;
 extern unsigned long loops_per_jiffy;
 
@@ -83,6 +94,8 @@ extern void init_mmu(void);
 static inline void init_mmu(void) { }
 #endif
 
+extern int mem_reserve(unsigned long, unsigned long, int);
+extern void bootmem_init(void);
 extern void zones_init(void);
 
 /*
@@ -104,28 +117,33 @@ typedef struct tagtable {
 
 /* parse current tag */
 
-static int __init parse_tag_mem(const bp_tag_t *tag)
+static int __init add_sysmem_bank(unsigned long type, unsigned long start,
+		unsigned long end)
 {
-	meminfo_t *mi = (meminfo_t*)(tag->data);
-
-	if (mi->type != MEMORY_TYPE_CONVENTIONAL)
-		return -1;
-
 	if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) {
 		printk(KERN_WARNING
-		       "Ignoring memory bank 0x%08lx size %ldKB\n",
-		       (unsigned long)mi->start,
-		       (unsigned long)mi->end - (unsigned long)mi->start);
+				"Ignoring memory bank 0x%08lx size %ldKB\n",
+				start, end - start);
 		return -EINVAL;
 	}
-	sysmem.bank[sysmem.nr_banks].type  = mi->type;
-	sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(mi->start);
-	sysmem.bank[sysmem.nr_banks].end   = mi->end & PAGE_MASK;
+	sysmem.bank[sysmem.nr_banks].type  = type;
+	sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(start);
+	sysmem.bank[sysmem.nr_banks].end   = end & PAGE_MASK;
 	sysmem.nr_banks++;
 
 	return 0;
 }
 
+static int __init parse_tag_mem(const bp_tag_t *tag)
+{
+	meminfo_t *mi = (meminfo_t *)(tag->data);
+
+	if (mi->type != MEMORY_TYPE_CONVENTIONAL)
+		return -1;
+
+	return add_sysmem_bank(mi->type, mi->start, mi->end);
+}
+
 __tagtable(BP_TAG_MEMORY, parse_tag_mem);
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -142,12 +160,31 @@ static int __init parse_tag_initrd(const bp_tag_t* tag)
 
 __tagtable(BP_TAG_INITRD, parse_tag_initrd);
 
+#ifdef CONFIG_OF
+
+static int __init parse_tag_fdt(const bp_tag_t *tag)
+{
+	dtb_start = (void *)(tag->data[0]);
+	return 0;
+}
+
+__tagtable(BP_TAG_FDT, parse_tag_fdt);
+
+void __init early_init_dt_setup_initrd_arch(unsigned long start,
+		unsigned long end)
+{
+	initrd_start = (void *)__va(start);
+	initrd_end = (void *)__va(end);
+	initrd_below_start_ok = 1;
+}
+
+#endif /* CONFIG_OF */
+
 #endif /* CONFIG_BLK_DEV_INITRD */
 
 static int __init parse_tag_cmdline(const bp_tag_t* tag)
 {
-	strncpy(command_line, (char*)(tag->data), COMMAND_LINE_SIZE);
-	command_line[COMMAND_LINE_SIZE - 1] = '\0';
+	strlcpy(command_line, (char *)(tag->data), COMMAND_LINE_SIZE);
 	return 0;
 }
 
@@ -185,6 +222,58 @@ static int __init parse_bootparam(const bp_tag_t* tag)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+
+void __init early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+	size &= PAGE_MASK;
+	add_sysmem_bank(MEMORY_TYPE_CONVENTIONAL, base, base + size);
+}
+
+void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+{
+	return __alloc_bootmem(size, align, 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, 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);
+}
+
+static void __init copy_devtree(void)
+{
+	void *alloc = early_init_dt_alloc_memory_arch(
+			be32_to_cpu(initial_boot_params->totalsize), 0);
+	if (alloc) {
+		memcpy(alloc, initial_boot_params,
+				be32_to_cpu(initial_boot_params->totalsize));
+		initial_boot_params = alloc;
+	}
+}
+
+static int __init xtensa_device_probe(void)
+{
+	of_platform_populate(NULL, NULL, NULL, NULL);
+	return 0;
+}
+
+device_initcall(xtensa_device_probe);
+
+#endif /* CONFIG_OF */
+
 /*
  * Initialize architecture. (Early stage)
  */
@@ -193,14 +282,14 @@ void __init init_arch(bp_tag_t *bp_start)
 {
 	sysmem.nr_banks = 0;
 
-#ifdef CONFIG_CMDLINE_BOOL
-	strcpy(command_line, default_command_line);
-#endif
-
 	/* Parse boot parameters */
 
         if (bp_start)
-	  parse_bootparam(bp_start);
+		parse_bootparam(bp_start);
+
+#ifdef CONFIG_OF
+	early_init_devtree(dtb_start);
+#endif
 
 	if (sysmem.nr_banks == 0) {
 		sysmem.nr_banks = 1;
@@ -209,6 +298,11 @@ void __init init_arch(bp_tag_t *bp_start)
 				     + PLATFORM_DEFAULT_MEM_SIZE;
 	}
 
+#ifdef CONFIG_CMDLINE_BOOL
+	if (!command_line[0])
+		strlcpy(command_line, default_command_line, COMMAND_LINE_SIZE);
+#endif
+
 	/* Early hook for platforms */
 
 	platform_init(bp_start);
@@ -235,15 +329,130 @@ extern char _UserExceptionVector_text_end;
 extern char _DoubleExceptionVector_literal_start;
 extern char _DoubleExceptionVector_text_end;
 
-void __init setup_arch(char **cmdline_p)
+
+#ifdef CONFIG_S32C1I_SELFTEST
+#if XCHAL_HAVE_S32C1I
+
+static int __initdata rcw_word, rcw_probe_pc, rcw_exc;
+
+/*
+ * Basic atomic compare-and-swap, that records PC of S32C1I for probing.
+ *
+ * If *v == cmp, set *v = set.  Return previous *v.
+ */
+static inline int probed_compare_swap(int *v, int cmp, int set)
+{
+	int tmp;
+
+	__asm__ __volatile__(
+			"	movi	%1, 1f\n"
+			"	s32i	%1, %4, 0\n"
+			"	wsr	%2, scompare1\n"
+			"1:	s32c1i	%0, %3, 0\n"
+			: "=a" (set), "=&a" (tmp)
+			: "a" (cmp), "a" (v), "a" (&rcw_probe_pc), "0" (set)
+			: "memory"
+			);
+	return set;
+}
+
+/* Handle probed exception */
+
+void __init do_probed_exception(struct pt_regs *regs, unsigned long exccause)
 {
-	extern int mem_reserve(unsigned long, unsigned long, int);
-	extern void bootmem_init(void);
+	if (regs->pc == rcw_probe_pc) {	/* exception on s32c1i ? */
+		regs->pc += 3;		/* skip the s32c1i instruction */
+		rcw_exc = exccause;
+	} else {
+		do_unhandled(regs, exccause);
+	}
+}
+
+/* Simple test of S32C1I (soc bringup assist) */
+
+void __init check_s32c1i(void)
+{
+	int n, cause1, cause2;
+	void *handbus, *handdata, *handaddr; /* temporarily saved handlers */
+
+	rcw_probe_pc = 0;
+	handbus  = trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR,
+			do_probed_exception);
+	handdata = trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR,
+			do_probed_exception);
+	handaddr = trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR,
+			do_probed_exception);
+
+	/* First try an S32C1I that does not store: */
+	rcw_exc = 0;
+	rcw_word = 1;
+	n = probed_compare_swap(&rcw_word, 0, 2);
+	cause1 = rcw_exc;
+
+	/* took exception? */
+	if (cause1 != 0) {
+		/* unclean exception? */
+		if (n != 2 || rcw_word != 1)
+			panic("S32C1I exception error");
+	} else if (rcw_word != 1 || n != 1) {
+		panic("S32C1I compare error");
+	}
 
-	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
-	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	/* Then an S32C1I that stores: */
+	rcw_exc = 0;
+	rcw_word = 0x1234567;
+	n = probed_compare_swap(&rcw_word, 0x1234567, 0xabcde);
+	cause2 = rcw_exc;
+
+	if (cause2 != 0) {
+		/* unclean exception? */
+		if (n != 0xabcde || rcw_word != 0x1234567)
+			panic("S32C1I exception error (b)");
+	} else if (rcw_word != 0xabcde || n != 0x1234567) {
+		panic("S32C1I store error");
+	}
+
+	/* Verify consistency of exceptions: */
+	if (cause1 || cause2) {
+		pr_warn("S32C1I took exception %d, %d\n", cause1, cause2);
+		/* If emulation of S32C1I upon bus error gets implemented,
+		   we can get rid of this panic for single core (not SMP) */
+		panic("S32C1I exceptions not currently supported");
+	}
+	if (cause1 != cause2)
+		panic("inconsistent S32C1I exceptions");
+
+	trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, handbus);
+	trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, handdata);
+	trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, handaddr);
+}
+
+#else /* XCHAL_HAVE_S32C1I */
+
+/* This condition should not occur with a commercially deployed processor.
+   Display reminder for early engr test or demo chips / FPGA bitstreams */
+void __init check_s32c1i(void)
+{
+	pr_warn("Processor configuration lacks atomic compare-and-swap support!\n");
+}
+
+#endif /* XCHAL_HAVE_S32C1I */
+#else /* CONFIG_S32C1I_SELFTEST */
+
+void __init check_s32c1i(void)
+{
+}
+
+#endif /* CONFIG_S32C1I_SELFTEST */
+
+
+void __init setup_arch(char **cmdline_p)
+{
+	strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
 	*cmdline_p = command_line;
 
+	check_s32c1i();
+
 	/* Reserve some memory regions */
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -275,8 +484,12 @@ void __init setup_arch(char **cmdline_p)
 
 	bootmem_init();
 
-	platform_setup(cmdline_p);
+#ifdef CONFIG_OF
+	copy_devtree();
+	unflatten_device_tree();
+#endif
 
+	platform_setup(cmdline_p);
 
 	paging_init();
 	zones_init();
@@ -381,6 +594,9 @@ c_show(struct seq_file *f, void *slot)
 #if XCHAL_HAVE_FP
 		     "fpu "
 #endif
+#if XCHAL_HAVE_S32C1I
+		     "s32c1i "
+#endif
 		     "\n");
 
 	/* Registers. */
@@ -412,7 +628,7 @@ c_show(struct seq_file *f, void *slot)
 		     "icache size\t: %d\n"
 		     "icache flags\t: "
 #if XCHAL_ICACHE_LINE_LOCKABLE
-		     "lock"
+		     "lock "
 #endif
 		     "\n"
 		     "dcache line size: %d\n"
@@ -420,10 +636,10 @@ c_show(struct seq_file *f, void *slot)
 		     "dcache size\t: %d\n"
 		     "dcache flags\t: "
 #if XCHAL_DCACHE_IS_WRITEBACK
-		     "writeback"
+		     "writeback "
 #endif
 #if XCHAL_DCACHE_LINE_LOCKABLE
-		     "lock"
+		     "lock "
 #endif
 		     "\n",
 		     XCHAL_ICACHE_LINESIZE,
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index ac62f9c..ffb4741 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/profile.h>
 #include <linux/delay.h>
+#include <linux/irqdomain.h>
 
 #include <asm/timex.h>
 #include <asm/platform.h>
@@ -31,7 +32,7 @@ unsigned long ccount_per_jiffy;		/* per 1/HZ */
 unsigned long nsec_per_ccount;		/* nsec per ccount increment */
 #endif
 
-static cycle_t ccount_read(void)
+static cycle_t ccount_read(struct clocksource *cs)
 {
 	return (cycle_t)get_ccount();
 }
@@ -52,6 +53,7 @@ static struct irqaction timer_irqaction = {
 
 void __init time_init(void)
 {
+	unsigned int irq;
 #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
 	printk("Calibrating CPU frequency ");
 	platform_calibrate_ccount();
@@ -62,7 +64,8 @@ void __init time_init(void)
 
 	/* Initialize the linux timer interrupt. */
 
-	setup_irq(LINUX_TIMER_INT, &timer_irqaction);
+	irq = irq_create_mapping(NULL, LINUX_TIMER_INT);
+	setup_irq(irq, &timer_irqaction);
 	set_linux_timer(get_ccount() + CCOUNT_PER_JIFFY);
 }
 
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 5caf2b6..691a792 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -293,6 +293,17 @@ do_debug(struct pt_regs *regs)
 }
 
 
+/* Set exception C handler - for temporary use when probing exceptions */
+
+void * __init trap_set_handler(int cause, void *handler)
+{
+	unsigned long *entry = &exc_table[EXC_TABLE_DEFAULT / 4 + cause];
+	void *previous = (void *)*entry;
+	*entry = (unsigned long)handler;
+	return previous;
+}
+
+
 /*
  * Initialize dispatch tables.
  *
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S
index 4462c1e..9365ee5 100644
--- a/arch/xtensa/kernel/vectors.S
+++ b/arch/xtensa/kernel/vectors.S
@@ -79,6 +79,8 @@ ENTRY(_UserExceptionVector)
 	l32i	a0, a0, EXC_TABLE_FAST_USER	# load handler
 	jx	a0
 
+ENDPROC(_UserExceptionVector)
+
 /*
  * Kernel exception vector. (Exceptions with PS.UM == 0, PS.EXCM == 0)
  *
@@ -103,6 +105,7 @@ ENTRY(_KernelExceptionVector)
 	l32i	a0, a0, EXC_TABLE_FAST_KERNEL	# load handler address
 	jx	a0
 
+ENDPROC(_KernelExceptionVector)
 
 /*
  * Double exception vector (Exceptions with PS.EXCM == 1)
@@ -225,7 +228,13 @@ ENTRY(_DoubleExceptionVector)
 	/* Window overflow/underflow exception. Get stack pointer. */
 
 	mov	a3, a2
-	movi	a2, exc_table
+	/* This explicit literal and the following references to it are made
+	 * in order to fit DoubleExceptionVector.literals into the available
+	 * 16-byte gap before DoubleExceptionVector.text in the absence of
+	 * link time relaxation. See kernel/vmlinux.lds.S
+	 */
+	.literal .Lexc_table, exc_table
+	l32r	a2, .Lexc_table
 	l32i	a2, a2, EXC_TABLE_KSTK
 
 	/* Check for overflow/underflow exception, jump if overflow. */
@@ -255,7 +264,7 @@ ENTRY(_DoubleExceptionVector)
 	s32i	a0, a2, PT_AREG0
 
 	wsr	a3, excsave1		# save a3
-	movi	a3, exc_table
+	l32r	a3, .Lexc_table
 
 	rsr	a0, exccause
 	s32i	a0, a2, PT_DEPC		# mark it as a regular exception
@@ -267,7 +276,7 @@ ENTRY(_DoubleExceptionVector)
 
 	/* a0: depc, a1: a1, a2: a2, a3: trashed, depc: a0, excsave1: a3 */
 
-	movi	a3, exc_table
+	l32r	a3, .Lexc_table
 	s32i	a2, a3, EXC_TABLE_DOUBLE_SAVE	# temporary variable
 
 	/* Enter critical section. */
@@ -296,7 +305,7 @@ ENTRY(_DoubleExceptionVector)
 
 	/* a0: avail, a1: a1, a2: kstk, a3: avail, depc: a2, excsave: a3 */
 
-	movi	a3, exc_table
+	l32r	a3, .Lexc_table
 	rsr	a0, exccause
 	addx4	a0, a0, a3
 	l32i	a0, a0, EXC_TABLE_FAST_USER
@@ -338,6 +347,7 @@ ENTRY(_DoubleExceptionVector)
 
 	.end literal_prefix
 
+ENDPROC(_DoubleExceptionVector)
 
 /*
  * Debug interrupt vector
@@ -349,9 +359,11 @@ ENTRY(_DoubleExceptionVector)
 	.section .DebugInterruptVector.text, "ax"
 
 ENTRY(_DebugInterruptVector)
+
 	xsr	a0, SREG_EXCSAVE + XCHAL_DEBUGLEVEL
 	jx	a0
 
+ENDPROC(_DebugInterruptVector)
 
 
 /* Window overflow and underflow handlers.
@@ -363,38 +375,43 @@ ENTRY(_DebugInterruptVector)
  *	 we try to access any page that would cause a page fault early.
  */
 
+#define ENTRY_ALIGN64(name)	\
+	.globl name;		\
+	.align 64;		\
+	name:
+
 	.section		.WindowVectors.text, "ax"
 
 
 /* 4-Register Window Overflow Vector (Handler) */
 
-	.align 64
-.global _WindowOverflow4
-_WindowOverflow4:
+ENTRY_ALIGN64(_WindowOverflow4)
+
 	s32e	a0, a5, -16
 	s32e	a1, a5, -12
 	s32e	a2, a5,  -8
 	s32e	a3, a5,  -4
 	rfwo
 
+ENDPROC(_WindowOverflow4)
+
 
 /* 4-Register Window Underflow Vector (Handler) */
 
-	.align 64
-.global _WindowUnderflow4
-_WindowUnderflow4:
+ENTRY_ALIGN64(_WindowUnderflow4)
+
 	l32e	a0, a5, -16
 	l32e	a1, a5, -12
 	l32e	a2, a5,  -8
 	l32e	a3, a5,  -4
 	rfwu
 
+ENDPROC(_WindowUnderflow4)
 
 /* 8-Register Window Overflow Vector (Handler) */
 
-	.align 64
-.global _WindowOverflow8
-_WindowOverflow8:
+ENTRY_ALIGN64(_WindowOverflow8)
+
 	s32e	a0, a9, -16
 	l32e	a0, a1, -12
 	s32e	a2, a9,  -8
@@ -406,11 +423,12 @@ _WindowOverflow8:
 	s32e	a7, a0, -20
 	rfwo
 
+ENDPROC(_WindowOverflow8)
+
 /* 8-Register Window Underflow Vector (Handler) */
 
-	.align 64
-.global _WindowUnderflow8
-_WindowUnderflow8:
+ENTRY_ALIGN64(_WindowUnderflow8)
+
 	l32e	a1, a9, -12
 	l32e	a0, a9, -16
 	l32e	a7, a1, -12
@@ -422,12 +440,12 @@ _WindowUnderflow8:
 	l32e	a7, a7, -20
 	rfwu
 
+ENDPROC(_WindowUnderflow8)
 
 /* 12-Register Window Overflow Vector (Handler) */
 
-	.align 64
-.global _WindowOverflow12
-_WindowOverflow12:
+ENTRY_ALIGN64(_WindowOverflow12)
+
 	s32e	a0,  a13, -16
 	l32e	a0,  a1,  -12
 	s32e	a1,  a13, -12
@@ -443,11 +461,12 @@ _WindowOverflow12:
 	s32e	a11, a0,  -20
 	rfwo
 
+ENDPROC(_WindowOverflow12)
+
 /* 12-Register Window Underflow Vector (Handler) */
 
-	.align 64
-.global _WindowUnderflow12
-_WindowUnderflow12:
+ENTRY_ALIGN64(_WindowUnderflow12)
+
 	l32e	a1,  a13, -12
 	l32e	a0,  a13, -16
 	l32e	a11, a1,  -12
@@ -463,6 +482,8 @@ _WindowUnderflow12:
 	l32e	a11, a11, -20
 	rfwu
 
+ENDPROC(_WindowUnderflow12)
+
 	.text
 
 
diff --git a/arch/xtensa/lib/checksum.S b/arch/xtensa/lib/checksum.S
index df397f9..0470ca2 100644
--- a/arch/xtensa/lib/checksum.S
+++ b/arch/xtensa/lib/checksum.S
@@ -170,7 +170,7 @@ ENTRY(csum_partial)
 3:
 	j	5b		/* branch to handle the remaining byte */
 
-
+ENDPROC(csum_partial)
 
 /*
  * Copy from ds while checksumming, otherwise like csum_partial
@@ -211,6 +211,7 @@ unsigned int csum_partial_copy_generic (const char *src, char *dst, int len,
  */
 
 ENTRY(csum_partial_copy_generic)
+
 	entry	sp, 32
 	mov	a12, a3
 	mov	a11, a4
@@ -367,6 +368,8 @@ DST(	s8i	a8, a3, 1	)
 6:
 	j	4b		/* process the possible trailing odd byte */
 
+ENDPROC(csum_partial_copy_generic)
+
 
 # Exception handler:
 .section .fixup, "ax"
diff --git a/arch/xtensa/mm/misc.S b/arch/xtensa/mm/misc.S
index b048406..7f7078f 100644
--- a/arch/xtensa/mm/misc.S
+++ b/arch/xtensa/mm/misc.S
@@ -29,6 +29,7 @@
  */
 
 ENTRY(clear_page)
+
 	entry	a1, 16
 
 	movi	a3, 0
@@ -45,6 +46,8 @@ ENTRY(clear_page)
 
 	retw
 
+ENDPROC(clear_page)
+
 /*
  * copy_page and copy_user_page are the same for non-cache-aliased configs.
  *
@@ -53,6 +56,7 @@ ENTRY(clear_page)
  */
 
 ENTRY(copy_page)
+
 	entry	a1, 16
 
 	__loopi a2, a4, PAGE_SIZE, 32
@@ -84,6 +88,8 @@ ENTRY(copy_page)
 
 	retw
 
+ENDPROC(copy_page)
+
 #ifdef CONFIG_MMU
 /*
  * If we have to deal with cache aliasing, we use temporary memory mappings
@@ -109,6 +115,7 @@ ENTRY(__tlbtemp_mapping_start)
  */
 
 ENTRY(clear_user_page)
+
 	entry	a1, 32
 
 	/* Mark page dirty and determine alias. */
@@ -164,6 +171,8 @@ ENTRY(clear_user_page)
 
 	retw
 
+ENDPROC(clear_user_page)
+
 /*
  * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page)
  *                    a2          a3	        a4		    a5
@@ -262,6 +271,8 @@ ENTRY(copy_user_page)
 
 	retw
 
+ENDPROC(copy_user_page)
+
 #endif
 
 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
@@ -272,6 +283,7 @@ ENTRY(copy_user_page)
  */
 
 ENTRY(__flush_invalidate_dcache_page_alias)
+
 	entry	sp, 16
 
 	movi	a7, 0			# required for exception handler
@@ -287,6 +299,7 @@ ENTRY(__flush_invalidate_dcache_page_alias)
 
 	retw
 
+ENDPROC(__flush_invalidate_dcache_page_alias)
 #endif
 
 ENTRY(__tlbtemp_mapping_itlb)
@@ -294,6 +307,7 @@ ENTRY(__tlbtemp_mapping_itlb)
 #if (ICACHE_WAY_SIZE > PAGE_SIZE)
 	
 ENTRY(__invalidate_icache_page_alias)
+
 	entry	sp, 16
 
 	addi	a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE)
@@ -307,11 +321,14 @@ ENTRY(__invalidate_icache_page_alias)
 	isync
 	retw
 
+ENDPROC(__invalidate_icache_page_alias)
+
 #endif
 
 /* End of special treatment in tlb miss exception */
 
 ENTRY(__tlbtemp_mapping_end)
+
 #endif /* CONFIG_MMU
 
 /*
@@ -319,6 +336,7 @@ ENTRY(__tlbtemp_mapping_end)
  */
 
 ENTRY(__invalidate_icache_page)
+
 	entry	sp, 16
 
 	___invalidate_icache_page a2 a3
@@ -326,11 +344,14 @@ ENTRY(__invalidate_icache_page)
 
 	retw
 
+ENDPROC(__invalidate_icache_page)
+
 /*
  * void __invalidate_dcache_page(ulong start)
  */
 
 ENTRY(__invalidate_dcache_page)
+
 	entry	sp, 16
 
 	___invalidate_dcache_page a2 a3
@@ -338,11 +359,14 @@ ENTRY(__invalidate_dcache_page)
 
 	retw
 
+ENDPROC(__invalidate_dcache_page)
+
 /*
  * void __flush_invalidate_dcache_page(ulong start)
  */
 
 ENTRY(__flush_invalidate_dcache_page)
+
 	entry	sp, 16
 
 	___flush_invalidate_dcache_page a2 a3
@@ -350,11 +374,14 @@ ENTRY(__flush_invalidate_dcache_page)
 	dsync
 	retw
 
+ENDPROC(__flush_invalidate_dcache_page)
+
 /*
  * void __flush_dcache_page(ulong start)
  */
 
 ENTRY(__flush_dcache_page)
+
 	entry	sp, 16
 
 	___flush_dcache_page a2 a3
@@ -362,11 +389,14 @@ ENTRY(__flush_dcache_page)
 	dsync
 	retw
 
+ENDPROC(__flush_dcache_page)
+
 /*
  * void __invalidate_icache_range(ulong start, ulong size)
  */
 
 ENTRY(__invalidate_icache_range)
+
 	entry	sp, 16
 
 	___invalidate_icache_range a2 a3 a4
@@ -374,11 +404,14 @@ ENTRY(__invalidate_icache_range)
 
 	retw
 
+ENDPROC(__invalidate_icache_range)
+
 /*
  * void __flush_invalidate_dcache_range(ulong start, ulong size)
  */
 
 ENTRY(__flush_invalidate_dcache_range)
+
 	entry	sp, 16
 
 	___flush_invalidate_dcache_range a2 a3 a4
@@ -386,11 +419,14 @@ ENTRY(__flush_invalidate_dcache_range)
 
 	retw
 
+ENDPROC(__flush_invalidate_dcache_range)
+
 /*
  * void _flush_dcache_range(ulong start, ulong size)
  */
 
 ENTRY(__flush_dcache_range)
+
 	entry	sp, 16
 
 	___flush_dcache_range a2 a3 a4
@@ -398,22 +434,28 @@ ENTRY(__flush_dcache_range)
 
 	retw
 
+ENDPROC(__flush_dcache_range)
+
 /*
  * void _invalidate_dcache_range(ulong start, ulong size)
  */
 
 ENTRY(__invalidate_dcache_range)
+
 	entry	sp, 16
 
 	___invalidate_dcache_range a2 a3 a4
 
 	retw
 
+ENDPROC(__invalidate_dcache_range)
+
 /*
  * void _invalidate_icache_all(void)
  */
 
 ENTRY(__invalidate_icache_all)
+
 	entry	sp, 16
 
 	___invalidate_icache_all a2 a3
@@ -421,11 +463,14 @@ ENTRY(__invalidate_icache_all)
 
 	retw
 
+ENDPROC(__invalidate_icache_all)
+
 /*
  * void _flush_invalidate_dcache_all(void)
  */
 
 ENTRY(__flush_invalidate_dcache_all)
+
 	entry	sp, 16
 
 	___flush_invalidate_dcache_all a2 a3
@@ -433,11 +478,14 @@ ENTRY(__flush_invalidate_dcache_all)
 
 	retw
 
+ENDPROC(__flush_invalidate_dcache_all)
+
 /*
  * void _invalidate_dcache_all(void)
  */
 
 ENTRY(__invalidate_dcache_all)
+
 	entry	sp, 16
 
 	___invalidate_dcache_all a2 a3
@@ -445,3 +493,4 @@ ENTRY(__invalidate_dcache_all)
 
 	retw
 
+ENDPROC(__invalidate_dcache_all)
diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c
index e2700b2..070fb7a 100644
--- a/arch/xtensa/mm/tlb.c
+++ b/arch/xtensa/mm/tlb.c
@@ -63,7 +63,7 @@ void flush_tlb_all (void)
 void flush_tlb_mm(struct mm_struct *mm)
 {
 	if (mm == current->active_mm) {
-		int flags;
+		unsigned long flags;
 		local_save_flags(flags);
 		__get_new_mmu_context(mm);
 		__load_mmu_context(mm);
diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c
index 7e74895..8207a11 100644
--- a/arch/xtensa/platforms/iss/console.c
+++ b/arch/xtensa/platforms/iss/console.c
@@ -221,6 +221,7 @@ static __exit void rs_exit(void)
 		printk("ISS_SERIAL: failed to unregister serial driver (%d)\n",
 		       error);
 	put_tty_driver(serial_driver);
+	tty_port_destroy(&serial_port);
 }
 
 
diff --git a/arch/xtensa/platforms/iss/include/platform/serial.h b/arch/xtensa/platforms/iss/include/platform/serial.h
index e69de29..16aec54 100644
--- a/arch/xtensa/platforms/iss/include/platform/serial.h
+++ b/arch/xtensa/platforms/iss/include/platform/serial.h
@@ -0,0 +1,15 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2012 Tensilica Inc.
+ */
+
+#ifndef __ASM_XTENSA_ISS_SERIAL_H
+#define __ASM_XTENSA_ISS_SERIAL_H
+
+/* Have no meaning on ISS, but needed for 8250_early.c */
+#define BASE_BAUD 0
+
+#endif /* __ASM_XTENSA_ISS_SERIAL_H */
diff --git a/arch/xtensa/platforms/iss/include/platform/simcall.h b/arch/xtensa/platforms/iss/include/platform/simcall.h
index bd78192..b5a4edf 100644
--- a/arch/xtensa/platforms/iss/include/platform/simcall.h
+++ b/arch/xtensa/platforms/iss/include/platform/simcall.h
@@ -74,13 +74,12 @@ static inline int __simc(int a, int b, int c, int d, int e, int f)
 			"mov %1, a3\n"
 			: "=a" (ret), "=a" (errno), "+r"(a1), "+r"(b1)
 			: "r"(c1), "r"(d1), "r"(e1), "r"(f1)
-			: );
+			: "memory");
 	return ret;
 }
 
 static inline int simc_open(const char *file, int flags, int mode)
 {
-	wmb();
 	return __simc(SYS_open, (int) file, flags, mode, 0, 0);
 }
 
@@ -91,19 +90,16 @@ static inline int simc_close(int fd)
 
 static inline int simc_ioctl(int fd, int request, void *arg)
 {
-	wmb();
 	return __simc(SYS_ioctl, fd, request, (int) arg, 0, 0);
 }
 
 static inline int simc_read(int fd, void *buf, size_t count)
 {
-	rmb();
 	return __simc(SYS_read, fd, (int) buf, count, 0, 0);
 }
 
 static inline int simc_write(int fd, const void *buf, size_t count)
 {
-	wmb();
 	return __simc(SYS_write, fd, (int) buf, count, 0, 0);
 }
 
@@ -111,7 +107,6 @@ static inline int simc_poll(int fd)
 {
 	struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
 
-	wmb();
 	return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv,
 			0, 0);
 }
diff --git a/arch/xtensa/platforms/xtfpga/Makefile b/arch/xtensa/platforms/xtfpga/Makefile
new file mode 100644
index 0000000..b9ae206
--- /dev/null
+++ b/arch/xtensa/platforms/xtfpga/Makefile
@@ -0,0 +1,9 @@
+# Makefile for the Tensilica xtavnet Emulation Board
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are in the main makefile...
+
+obj-y			= setup.o lcd.o
diff --git a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h
new file mode 100644
index 0000000..4416773
--- /dev/null
+++ b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h
@@ -0,0 +1,69 @@
+/*
+ * arch/xtensa/platform/xtavnet/include/platform/hardware.h
+ *
+ * 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.
+ *
+ * Copyright (C) 2006 Tensilica Inc.
+ */
+
+/*
+ * This file contains the hardware configuration of the XTAVNET boards.
+ */
+
+#ifndef __XTENSA_XTAVNET_HARDWARE_H
+#define __XTENSA_XTAVNET_HARDWARE_H
+
+/* By default NO_IRQ is defined to 0 in Linux, but we use the
+   interrupt 0 for UART... */
+#define NO_IRQ                 -1
+
+/* Memory configuration. */
+
+#define PLATFORM_DEFAULT_MEM_START 0x00000000
+#define PLATFORM_DEFAULT_MEM_SIZE  0x04000000
+
+/* Interrupt configuration. */
+
+#define PLATFORM_NR_IRQS	10
+
+/* Default assignment of LX60 devices to external interrupts. */
+
+#ifdef CONFIG_ARCH_HAS_SMP
+#define DUART16552_INTNUM	XCHAL_EXTINT3_NUM
+#define OETH_IRQ		XCHAL_EXTINT4_NUM
+#else
+#define DUART16552_INTNUM	XCHAL_EXTINT0_NUM
+#define OETH_IRQ		XCHAL_EXTINT1_NUM
+#endif
+
+/*
+ *  Device addresses and parameters.
+ */
+
+/* UART */
+#define DUART16552_PADDR	(XCHAL_KIO_PADDR + 0x0D050020)
+/* LCD instruction and data addresses. */
+#define LCD_INSTR_ADDR		((char *)IOADDR(0x0D040000))
+#define LCD_DATA_ADDR		((char *)IOADDR(0x0D040004))
+
+/* Misc. */
+#define XTFPGA_FPGAREGS_VADDR	IOADDR(0x0D020000)
+/* Clock frequency in Hz (read-only):  */
+#define XTFPGA_CLKFRQ_VADDR	(XTFPGA_FPGAREGS_VADDR + 0x04)
+/* Setting of 8 DIP switches:  */
+#define DIP_SWITCHES_VADDR	(XTFPGA_FPGAREGS_VADDR + 0x0C)
+/* Software reset (write 0xdead):  */
+#define XTFPGA_SWRST_VADDR	(XTFPGA_FPGAREGS_VADDR + 0x10)
+
+/*  OpenCores Ethernet controller:  */
+				/* regs + RX/TX descriptors */
+#define OETH_REGS_PADDR		(XCHAL_KIO_PADDR + 0x0D030000)
+#define OETH_REGS_SIZE		0x1000
+#define OETH_SRAMBUFF_PADDR	(XCHAL_KIO_PADDR + 0x0D800000)
+
+				/* 5*rx buffs + 5*tx buffs */
+#define OETH_SRAMBUFF_SIZE	(5 * 0x600 + 5 * 0x600)
+
+#endif /* __XTENSA_XTAVNET_HARDWARE_H */
diff --git a/arch/xtensa/platforms/xtfpga/include/platform/lcd.h b/arch/xtensa/platforms/xtfpga/include/platform/lcd.h
new file mode 100644
index 0000000..0e43564
--- /dev/null
+++ b/arch/xtensa/platforms/xtfpga/include/platform/lcd.h
@@ -0,0 +1,20 @@
+/*
+ * arch/xtensa/platform/xtavnet/include/platform/lcd.h
+ *
+ * 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.
+ *
+ * Copyright (C) 2001, 2006 Tensilica Inc.
+ */
+
+#ifndef __XTENSA_XTAVNET_LCD_H
+#define __XTENSA_XTAVNET_LCD_H
+
+/* Display string STR at position POS on the LCD. */
+void lcd_disp_at_pos(char *str, unsigned char pos);
+
+/* Shift the contents of the LCD display left or right. */
+void lcd_shiftleft(void);
+void lcd_shiftright(void);
+#endif
diff --git a/arch/xtensa/platforms/xtfpga/include/platform/serial.h b/arch/xtensa/platforms/xtfpga/include/platform/serial.h
new file mode 100644
index 0000000..14d8f7b
--- /dev/null
+++ b/arch/xtensa/platforms/xtfpga/include/platform/serial.h
@@ -0,0 +1,18 @@
+/*
+ * arch/xtensa/platform/xtavnet/include/platform/serial.h
+ *
+ * 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.
+ *
+ * Copyright (C) 2001, 2006 Tensilica Inc.
+ */
+
+#ifndef __ASM_XTENSA_XTAVNET_SERIAL_H
+#define __ASM_XTENSA_XTAVNET_SERIAL_H
+
+#include <platform/hardware.h>
+
+#define BASE_BAUD (*(long *)XTFPGA_CLKFRQ_VADDR / 16)
+
+#endif /* __ASM_XTENSA_XTAVNET_SERIAL_H */
diff --git a/arch/xtensa/platforms/xtfpga/lcd.c b/arch/xtensa/platforms/xtfpga/lcd.c
new file mode 100644
index 0000000..2872301
--- /dev/null
+++ b/arch/xtensa/platforms/xtfpga/lcd.c
@@ -0,0 +1,76 @@
+/*
+ * Driver for the LCD display on the Tensilica LX60 Board.
+ *
+ * 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.
+ *
+ * Copyright (C) 2001, 2006 Tensilica Inc.
+ */
+
+/*
+ *
+ * FIXME: this code is from the examples from the LX60 user guide.
+ *
+ * The lcd_pause function does busy waiting, which is probably not
+ * great. Maybe the code could be changed to use kernel timers, or
+ * change the hardware to not need to wait.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <platform/hardware.h>
+#include <platform/lcd.h>
+#include <linux/delay.h>
+
+#define LCD_PAUSE_ITERATIONS	4000
+#define LCD_CLEAR		0x1
+#define LCD_DISPLAY_ON		0xc
+
+/* 8bit and 2 lines display */
+#define LCD_DISPLAY_MODE8BIT	0x38
+#define LCD_DISPLAY_POS		0x80
+#define LCD_SHIFT_LEFT		0x18
+#define LCD_SHIFT_RIGHT		0x1c
+
+static int __init lcd_init(void)
+{
+	*LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
+	mdelay(5);
+	*LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
+	udelay(200);
+	*LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
+	udelay(50);
+	*LCD_INSTR_ADDR = LCD_DISPLAY_ON;
+	udelay(50);
+	*LCD_INSTR_ADDR = LCD_CLEAR;
+	mdelay(10);
+	lcd_disp_at_pos("XTENSA LINUX", 0);
+	return 0;
+}
+
+void lcd_disp_at_pos(char *str, unsigned char pos)
+{
+	*LCD_INSTR_ADDR = LCD_DISPLAY_POS | pos;
+	udelay(100);
+	while (*str != 0) {
+		*LCD_DATA_ADDR = *str;
+		udelay(200);
+		str++;
+	}
+}
+
+void lcd_shiftleft(void)
+{
+	*LCD_INSTR_ADDR = LCD_SHIFT_LEFT;
+	udelay(50);
+}
+
+void lcd_shiftright(void)
+{
+	*LCD_INSTR_ADDR = LCD_SHIFT_RIGHT;
+	udelay(50);
+}
+
+arch_initcall(lcd_init);
diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c
new file mode 100644
index 0000000..71d61ca6
--- /dev/null
+++ b/arch/xtensa/platforms/xtfpga/setup.c
@@ -0,0 +1,269 @@
+/*
+ *
+ * arch/xtensa/platform/xtavnet/setup.c
+ *
+ * ...
+ *
+ * Authors:	Chris Zankel <chris@zankel.net>
+ *		Joe Taylor <joe@tensilica.com>
+ *
+ * Copyright 2001 - 2006 Tensilica 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+
+#include <asm/timex.h>
+#include <asm/processor.h>
+#include <asm/platform.h>
+#include <asm/bootparam.h>
+#include <platform/lcd.h>
+
+void platform_halt(void)
+{
+	lcd_disp_at_pos(" HALT ", 0);
+	local_irq_disable();
+	while (1)
+		cpu_relax();
+}
+
+void platform_power_off(void)
+{
+	lcd_disp_at_pos("POWEROFF", 0);
+	local_irq_disable();
+	while (1)
+		cpu_relax();
+}
+
+void platform_restart(void)
+{
+	/* Flush and reset the mmu, simulate a processor reset, and
+	 * jump to the reset vector. */
+
+
+	__asm__ __volatile__ ("movi	a2, 15\n\t"
+			      "wsr	a2, icountlevel\n\t"
+			      "movi	a2, 0\n\t"
+			      "wsr	a2, icount\n\t"
+			      "wsr	a2, ibreakenable\n\t"
+			      "wsr	a2, lcount\n\t"
+			      "movi	a2, 0x1f\n\t"
+			      "wsr	a2, ps\n\t"
+			      "isync\n\t"
+			      "jx	%0\n\t"
+			      :
+			      : "a" (XCHAL_RESET_VECTOR_VADDR)
+			      : "a2"
+			      );
+
+	/* control never gets here */
+}
+
+void __init platform_setup(char **cmdline)
+{
+}
+
+#ifdef CONFIG_OF
+
+static void __init update_clock_frequency(struct device_node *node)
+{
+	struct property *newfreq;
+	u32 freq;
+
+	if (!of_property_read_u32(node, "clock-frequency", &freq) &&
+			freq != 0)
+		return;
+
+	newfreq = kzalloc(sizeof(*newfreq) + sizeof(u32), GFP_KERNEL);
+	if (!newfreq)
+		return;
+	newfreq->value = newfreq + 1;
+	newfreq->length = sizeof(freq);
+	newfreq->name = kstrdup("clock-frequency", GFP_KERNEL);
+	if (!newfreq->name) {
+		kfree(newfreq);
+		return;
+	}
+
+	*(u32 *)newfreq->value = cpu_to_be32(*(u32 *)XTFPGA_CLKFRQ_VADDR);
+	prom_update_property(node, newfreq);
+}
+
+static int __init machine_setup(void)
+{
+	struct device_node *serial = NULL;
+
+	while ((serial = of_find_compatible_node(serial, NULL, "ns16550a")))
+		update_clock_frequency(serial);
+	return 0;
+}
+arch_initcall(machine_setup);
+
+#endif
+
+/* early initialization */
+
+void __init platform_init(bp_tag_t *first)
+{
+}
+
+/* Heartbeat. */
+
+void platform_heartbeat(void)
+{
+}
+
+#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
+
+void platform_calibrate_ccount(void)
+{
+	long clk_freq = 0;
+#ifdef CONFIG_OF
+	struct device_node *cpu =
+		of_find_compatible_node(NULL, NULL, "xtensa,cpu");
+	if (cpu) {
+		u32 freq;
+		update_clock_frequency(cpu);
+		if (!of_property_read_u32(cpu, "clock-frequency", &freq))
+			clk_freq = freq;
+	}
+#endif
+	if (!clk_freq)
+		clk_freq = *(long *)XTFPGA_CLKFRQ_VADDR;
+
+	ccount_per_jiffy = clk_freq / HZ;
+	nsec_per_ccount = 1000000000UL / clk_freq;
+}
+
+#endif
+
+#ifndef CONFIG_OF
+
+#include <linux/serial_8250.h>
+#include <linux/if.h>
+#include <net/ethoc.h>
+
+/*----------------------------------------------------------------------------
+ *  Ethernet -- OpenCores Ethernet MAC (ethoc driver)
+ */
+
+static struct resource ethoc_res[] __initdata = {
+	[0] = { /* register space */
+		.start = OETH_REGS_PADDR,
+		.end   = OETH_REGS_PADDR + OETH_REGS_SIZE - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = { /* buffer space */
+		.start = OETH_SRAMBUFF_PADDR,
+		.end   = OETH_SRAMBUFF_PADDR + OETH_SRAMBUFF_SIZE - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[2] = { /* IRQ number */
+		.start = OETH_IRQ,
+		.end   = OETH_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct ethoc_platform_data ethoc_pdata __initdata = {
+	/*
+	 * The MAC address for these boards is 00:50:c2:13:6f:xx.
+	 * The last byte (here as zero) is read from the DIP switches on the
+	 * board.
+	 */
+	.hwaddr = { 0x00, 0x50, 0xc2, 0x13, 0x6f, 0 },
+	.phy_id = -1,
+};
+
+static struct platform_device ethoc_device __initdata = {
+	.name = "ethoc",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(ethoc_res),
+	.resource = ethoc_res,
+	.dev = {
+		.platform_data = &ethoc_pdata,
+	},
+};
+
+/*----------------------------------------------------------------------------
+ *  UART
+ */
+
+static struct resource serial_resource __initdata = {
+	.start	= DUART16552_PADDR,
+	.end	= DUART16552_PADDR + 0x1f,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct plat_serial8250_port serial_platform_data[] __initdata = {
+	[0] = {
+		.mapbase	= DUART16552_PADDR,
+		.irq		= DUART16552_INTNUM,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+				  UPF_IOREMAP,
+		.iotype		= UPIO_MEM32,
+		.regshift	= 2,
+		.uartclk	= 0,    /* set in xtavnet_init() */
+	},
+	{ },
+};
+
+static struct platform_device xtavnet_uart __initdata = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.dev		= {
+		.platform_data	= serial_platform_data,
+	},
+	.num_resources	= 1,
+	.resource	= &serial_resource,
+};
+
+/* platform devices */
+static struct platform_device *platform_devices[] __initdata = {
+	&ethoc_device,
+	&xtavnet_uart,
+};
+
+
+static int __init xtavnet_init(void)
+{
+	/* Ethernet MAC address.  */
+	ethoc_pdata.hwaddr[5] = *(u32 *)DIP_SWITCHES_VADDR;
+
+	/* Clock rate varies among FPGA bitstreams; board specific FPGA register
+	 * reports the actual clock rate.
+	 */
+	serial_platform_data[0].uartclk = *(long *)XTFPGA_CLKFRQ_VADDR;
+
+
+	/* register platform devices */
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+	/* ETHOC driver is a bit quiet; at least display Ethernet MAC, so user
+	 * knows whether they set it correctly on the DIP switches.
+	 */
+	pr_info("XTFPGA: Ethernet MAC %pM\n", ethoc_pdata.hwaddr);
+
+	return 0;
+}
+
+/*
+ * Register to be done during do_initcalls().
+ */
+arch_initcall(xtavnet_init);
+
+#endif /* CONFIG_OF */
diff --git a/arch/xtensa/variants/s6000/gpio.c b/arch/xtensa/variants/s6000/gpio.c
index b89541b..da9e85c 100644
--- a/arch/xtensa/variants/s6000/gpio.c
+++ b/arch/xtensa/variants/s6000/gpio.c
@@ -164,7 +164,7 @@ static void demux_irqs(unsigned int irq, struct irq_desc *desc)
 	int cirq;
 
 	chip->irq_mask(&desc->irq_data);
-	chip->irq_ack(&desc->irq_data));
+	chip->irq_ack(&desc->irq_data);
 	pending = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_MIS) & *mask;
 	cirq = IRQ_BASE - 1;
 	while (pending) {
@@ -173,7 +173,7 @@ static void demux_irqs(unsigned int irq, struct irq_desc *desc)
 		pending >>= n;
 		generic_handle_irq(cirq);
 	}
-	chip->irq_unmask(&desc->irq_data));
+	chip->irq_unmask(&desc->irq_data);
 }
 
 extern const signed char *platform_irq_mappings[XTENSA_NR_IRQS];
diff --git a/block/Kconfig b/block/Kconfig
index a7e40a7..4a85ccf 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -4,6 +4,7 @@
 menuconfig BLOCK
        bool "Enable the block layer" if EXPERT
        default y
+       select PERCPU_RWSEM
        help
 	 Provide block layer support for the kernel.
 
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index d0b7703..3f6d39d 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -600,7 +600,7 @@ struct cftype blkcg_files[] = {
 };
 
 /**
- * blkcg_pre_destroy - cgroup pre_destroy callback
+ * blkcg_css_offline - cgroup css_offline callback
  * @cgroup: cgroup of interest
  *
  * This function is called when @cgroup is about to go away and responsible
@@ -610,7 +610,7 @@ struct cftype blkcg_files[] = {
  *
  * This is the blkcg counterpart of ioc_release_fn().
  */
-static int blkcg_pre_destroy(struct cgroup *cgroup)
+static void blkcg_css_offline(struct cgroup *cgroup)
 {
 	struct blkcg *blkcg = cgroup_to_blkcg(cgroup);
 
@@ -632,10 +632,9 @@ static int blkcg_pre_destroy(struct cgroup *cgroup)
 	}
 
 	spin_unlock_irq(&blkcg->lock);
-	return 0;
 }
 
-static void blkcg_destroy(struct cgroup *cgroup)
+static void blkcg_css_free(struct cgroup *cgroup)
 {
 	struct blkcg *blkcg = cgroup_to_blkcg(cgroup);
 
@@ -643,7 +642,7 @@ static void blkcg_destroy(struct cgroup *cgroup)
 		kfree(blkcg);
 }
 
-static struct cgroup_subsys_state *blkcg_create(struct cgroup *cgroup)
+static struct cgroup_subsys_state *blkcg_css_alloc(struct cgroup *cgroup)
 {
 	static atomic64_t id_seq = ATOMIC64_INIT(0);
 	struct blkcg *blkcg;
@@ -740,10 +739,10 @@ static int blkcg_can_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
 
 struct cgroup_subsys blkio_subsys = {
 	.name = "blkio",
-	.create = blkcg_create,
+	.css_alloc = blkcg_css_alloc,
+	.css_offline = blkcg_css_offline,
+	.css_free = blkcg_css_free,
 	.can_attach = blkcg_can_attach,
-	.pre_destroy = blkcg_pre_destroy,
-	.destroy = blkcg_destroy,
 	.subsys_id = blkio_subsys_id,
 	.base_cftypes = blkcg_files,
 	.module = THIS_MODULE,
diff --git a/block/blk-core.c b/block/blk-core.c
index 3c95c4d..a8b1527 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -40,6 +40,7 @@
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete);
+EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug);
 
 DEFINE_IDA(blk_queue_ida);
 
@@ -549,7 +550,7 @@ void blk_exit_rl(struct request_list *rl)
 
 struct request_queue *blk_alloc_queue(gfp_t gfp_mask)
 {
-	return blk_alloc_queue_node(gfp_mask, -1);
+	return blk_alloc_queue_node(gfp_mask, NUMA_NO_NODE);
 }
 EXPORT_SYMBOL(blk_alloc_queue);
 
@@ -660,7 +661,7 @@ EXPORT_SYMBOL(blk_alloc_queue_node);
 
 struct request_queue *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock)
 {
-	return blk_init_queue_node(rfn, lock, -1);
+	return blk_init_queue_node(rfn, lock, NUMA_NO_NODE);
 }
 EXPORT_SYMBOL(blk_init_queue);
 
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index fb52df9..e62e920 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1973,7 +1973,8 @@ cfq_merged_requests(struct request_queue *q, struct request *rq,
 	 * reposition in fifo if next is older than rq
 	 */
 	if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) &&
-	    time_before(rq_fifo_time(next), rq_fifo_time(rq))) {
+	    time_before(rq_fifo_time(next), rq_fifo_time(rq)) &&
+	    cfqq == RQ_CFQQ(next)) {
 		list_move(&rq->queuelist, &next->queuelist);
 		rq_set_fifo_time(rq, rq_fifo_time(next));
 	}
diff --git a/block/elevator.c b/block/elevator.c
index 9b1d42b..9edba1b 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -458,6 +458,7 @@ static bool elv_attempt_insert_merge(struct request_queue *q,
 				     struct request *rq)
 {
 	struct request *__rq;
+	bool ret;
 
 	if (blk_queue_nomerges(q))
 		return false;
@@ -471,14 +472,21 @@ static bool elv_attempt_insert_merge(struct request_queue *q,
 	if (blk_queue_noxmerges(q))
 		return false;
 
+	ret = false;
 	/*
 	 * See if our hash lookup can find a potential backmerge.
 	 */
-	__rq = elv_rqhash_find(q, blk_rq_pos(rq));
-	if (__rq && blk_attempt_req_merge(q, __rq, rq))
-		return true;
+	while (1) {
+		__rq = elv_rqhash_find(q, blk_rq_pos(rq));
+		if (!__rq || !blk_attempt_req_merge(q, __rq, rq))
+			break;
 
-	return false;
+		/* The merged request could be merged with others, try again */
+		ret = true;
+		rq = __rq;
+	}
+
+	return ret;
 }
 
 void elv_merged_request(struct request_queue *q, struct request *rq, int type)
diff --git a/block/genhd.c b/block/genhd.c
index 6cace66..9a289d7 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -743,7 +743,6 @@ void __init printk_all_partitions(void)
 		struct hd_struct *part;
 		char name_buf[BDEVNAME_SIZE];
 		char devt_buf[BDEVT_SIZE];
-		char uuid_buf[PARTITION_META_INFO_UUIDLTH * 2 + 5];
 
 		/*
 		 * Don't show empty devices or things that have been
@@ -762,16 +761,11 @@ void __init printk_all_partitions(void)
 		while ((part = disk_part_iter_next(&piter))) {
 			bool is_part0 = part == &disk->part0;
 
-			uuid_buf[0] = '\0';
-			if (part->info)
-				snprintf(uuid_buf, sizeof(uuid_buf), "%pU",
-					 part->info->uuid);
-
 			printk("%s%s %10llu %s %s", is_part0 ? "" : "  ",
 			       bdevt_str(part_devt(part), devt_buf),
 			       (unsigned long long)part_nr_sects_read(part) >> 1
 			       , disk_name(disk, part->partno, name_buf),
-			       uuid_buf);
+			       part->info ? part->info->uuid : "");
 			if (is_part0) {
 				if (disk->driverfs_dev != NULL &&
 				    disk->driverfs_dev->driver != NULL)
@@ -1245,7 +1239,7 @@ EXPORT_SYMBOL(blk_lookup_devt);
 
 struct gendisk *alloc_disk(int minors)
 {
-	return alloc_disk_node(minors, -1);
+	return alloc_disk_node(minors, NUMA_NO_NODE);
 }
 EXPORT_SYMBOL(alloc_disk);
 
diff --git a/block/partitions/efi.c b/block/partitions/efi.c
index 6296b40..b62fb88 100644
--- a/block/partitions/efi.c
+++ b/block/partitions/efi.c
@@ -620,7 +620,6 @@ int efi_partition(struct parsed_partitions *state)
 	gpt_entry *ptes = NULL;
 	u32 i;
 	unsigned ssz = bdev_logical_block_size(state->bdev) / 512;
-	u8 unparsed_guid[37];
 
 	if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) {
 		kfree(gpt);
@@ -649,11 +648,7 @@ int efi_partition(struct parsed_partitions *state)
 			state->parts[i + 1].flags = ADDPART_FLAG_RAID;
 
 		info = &state->parts[i + 1].info;
-		/* Instead of doing a manual swap to big endian, reuse the
-		 * common ASCII hex format as the interim.
-		 */
-		efi_guid_unparse(&ptes[i].unique_partition_guid, unparsed_guid);
-		part_pack_uuid(unparsed_guid, info->uuid);
+		efi_guid_unparse(&ptes[i].unique_partition_guid, info->uuid);
 
 		/* Naively convert UTF16-LE to 7 bits. */
 		label_max = min(sizeof(info->volname) - 1,
diff --git a/block/partitions/msdos.c b/block/partitions/msdos.c
index 5f79a66..8752a5d 100644
--- a/block/partitions/msdos.c
+++ b/block/partitions/msdos.c
@@ -94,6 +94,17 @@ static int aix_magic_present(struct parsed_partitions *state, unsigned char *p)
 	return ret;
 }
 
+static void set_info(struct parsed_partitions *state, int slot,
+		     u32 disksig)
+{
+	struct partition_meta_info *info = &state->parts[slot].info;
+
+	snprintf(info->uuid, sizeof(info->uuid), "%08x-%02x", disksig,
+		 slot);
+	info->volname[0] = 0;
+	state->parts[slot].has_info = true;
+}
+
 /*
  * Create devices for each logical partition in an extended partition.
  * The logical partitions form a linked list, with each entry being
@@ -106,7 +117,8 @@ static int aix_magic_present(struct parsed_partitions *state, unsigned char *p)
  */
 
 static void parse_extended(struct parsed_partitions *state,
-			   sector_t first_sector, sector_t first_size)
+			   sector_t first_sector, sector_t first_size,
+			   u32 disksig)
 {
 	struct partition *p;
 	Sector sect;
@@ -166,6 +178,7 @@ static void parse_extended(struct parsed_partitions *state,
 			}
 
 			put_partition(state, state->next, next, size);
+			set_info(state, state->next, disksig);
 			if (SYS_IND(p) == LINUX_RAID_PARTITION)
 				state->parts[state->next].flags = ADDPART_FLAG_RAID;
 			loopct = 0;
@@ -437,6 +450,7 @@ int msdos_partition(struct parsed_partitions *state)
 	struct partition *p;
 	struct fat_boot_sector *fb;
 	int slot;
+	u32 disksig;
 
 	data = read_part_sector(state, 0, &sect);
 	if (!data)
@@ -491,6 +505,8 @@ int msdos_partition(struct parsed_partitions *state)
 #endif
 	p = (struct partition *) (data + 0x1be);
 
+	disksig = le32_to_cpup((__le32 *)(data + 0x1b8));
+
 	/*
 	 * Look for partitions in two passes:
 	 * First find the primary and DOS-type extended partitions.
@@ -515,11 +531,12 @@ int msdos_partition(struct parsed_partitions *state)
 			put_partition(state, slot, start, n);
 
 			strlcat(state->pp_buf, " <", PAGE_SIZE);
-			parse_extended(state, start, size);
+			parse_extended(state, start, size, disksig);
 			strlcat(state->pp_buf, " >", PAGE_SIZE);
 			continue;
 		}
 		put_partition(state, slot, start, size);
+		set_info(state, slot, disksig);
 		if (SYS_IND(p) == LINUX_RAID_PARTITION)
 			state->parts[slot].flags = ADDPART_FLAG_RAID;
 		if (SYS_IND(p) == DM6_PARTITION)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 6563366..bc060d4 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -134,8 +134,8 @@ config CRYPTO_NULL
 	  These are 'Null' algorithms, used by IPsec, which do nothing.
 
 config CRYPTO_PCRYPT
-	tristate "Parallel crypto engine (EXPERIMENTAL)"
-	depends on SMP && EXPERIMENTAL
+	tristate "Parallel crypto engine"
+	depends on SMP
 	select PADATA
 	select CRYPTO_MANAGER
 	select CRYPTO_AEAD
@@ -292,7 +292,6 @@ config CRYPTO_HMAC
 
 config CRYPTO_XCBC
 	tristate "XCBC support"
-	depends on EXPERIMENTAL
 	select CRYPTO_HASH
 	select CRYPTO_MANAGER
 	help
@@ -303,7 +302,6 @@ config CRYPTO_XCBC
 
 config CRYPTO_VMAC
 	tristate "VMAC support"
-	depends on EXPERIMENTAL
 	select CRYPTO_HASH
 	select CRYPTO_MANAGER
 	help
@@ -324,9 +322,19 @@ config CRYPTO_CRC32C
 	  by iSCSI for header and data digests and by others.
 	  See Castagnoli93.  Module will be crc32c.
 
+config CRYPTO_CRC32C_X86_64
+	bool
+	depends on X86 && 64BIT
+	select CRYPTO_HASH
+	help
+	  In Intel processor with SSE4.2 supported, the processor will
+	  support CRC32C calculation using hardware accelerated CRC32
+	  instruction optimized with PCLMULQDQ instruction when available.
+
 config CRYPTO_CRC32C_INTEL
 	tristate "CRC32c INTEL hardware acceleration"
 	depends on X86
+	select CRYPTO_CRC32C_X86_64 if 64BIT
 	select CRYPTO_HASH
 	help
 	  In Intel processor with SSE4.2 supported, the processor will
@@ -793,6 +801,28 @@ config CRYPTO_CAMELLIA_X86_64
 	  See also:
 	  <https://info.isl.ntt.co.jp/crypt/eng/camellia/index_s.html>
 
+config CRYPTO_CAMELLIA_AESNI_AVX_X86_64
+	tristate "Camellia cipher algorithm (x86_64/AES-NI/AVX)"
+	depends on X86 && 64BIT
+	depends on CRYPTO
+	select CRYPTO_ALGAPI
+	select CRYPTO_CRYPTD
+	select CRYPTO_ABLK_HELPER_X86
+	select CRYPTO_GLUE_HELPER_X86
+	select CRYPTO_CAMELLIA_X86_64
+	select CRYPTO_LRW
+	select CRYPTO_XTS
+	help
+	  Camellia cipher algorithm module (x86_64/AES-NI/AVX).
+
+	  Camellia is a symmetric key block cipher developed jointly
+	  at NTT and Mitsubishi Electric Corporation.
+
+	  The Camellia specifies three key sizes: 128, 192 and 256 bits.
+
+	  See also:
+	  <https://info.isl.ntt.co.jp/crypt/eng/camellia/index_s.html>
+
 config CRYPTO_CAMELLIA_SPARC64
 	tristate "Camellia cipher algorithm (SPARC64)"
 	depends on SPARC64
@@ -890,8 +920,7 @@ config CRYPTO_KHAZAD
 	  <http://www.larc.usp.br/~pbarreto/KhazadPage.html>
 
 config CRYPTO_SALSA20
-	tristate "Salsa20 stream cipher algorithm (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	tristate "Salsa20 stream cipher algorithm"
 	select CRYPTO_BLKCIPHER
 	help
 	  Salsa20 stream cipher algorithm.
@@ -903,9 +932,8 @@ config CRYPTO_SALSA20
 	  Bernstein <djb@cr.yp.to>. See <http://cr.yp.to/snuffle.html>
 
 config CRYPTO_SALSA20_586
-	tristate "Salsa20 stream cipher algorithm (i586) (EXPERIMENTAL)"
+	tristate "Salsa20 stream cipher algorithm (i586)"
 	depends on (X86 || UML_X86) && !64BIT
-	depends on EXPERIMENTAL
 	select CRYPTO_BLKCIPHER
 	help
 	  Salsa20 stream cipher algorithm.
@@ -917,9 +945,8 @@ config CRYPTO_SALSA20_586
 	  Bernstein <djb@cr.yp.to>. See <http://cr.yp.to/snuffle.html>
 
 config CRYPTO_SALSA20_X86_64
-	tristate "Salsa20 stream cipher algorithm (x86_64) (EXPERIMENTAL)"
+	tristate "Salsa20 stream cipher algorithm (x86_64)"
 	depends on (X86 || UML_X86) && 64BIT
-	depends on EXPERIMENTAL
 	select CRYPTO_BLKCIPHER
 	help
 	  Salsa20 stream cipher algorithm.
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
index 154cc84..8ade0a0 100644
--- a/crypto/async_tx/async_xor.c
+++ b/crypto/async_tx/async_xor.c
@@ -230,9 +230,7 @@ EXPORT_SYMBOL_GPL(async_xor);
 
 static int page_is_zero(struct page *p, unsigned int offset, size_t len)
 {
-	char *a = page_address(p) + offset;
-	return ((*(u32 *) a) == 0 &&
-		memcmp(a, a + 4, len - 4) == 0);
+	return !memchr_inv(page_address(p) + offset, 0, len);
 }
 
 static inline struct dma_chan *
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index e87fa60..7ae2130 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -971,11 +971,13 @@ static int do_test(int m)
 	case 3:
 		ret += tcrypt_test("ecb(des)");
 		ret += tcrypt_test("cbc(des)");
+		ret += tcrypt_test("ctr(des)");
 		break;
 
 	case 4:
 		ret += tcrypt_test("ecb(des3_ede)");
 		ret += tcrypt_test("cbc(des3_ede)");
+		ret += tcrypt_test("ctr(des3_ede)");
 		break;
 
 	case 5:
@@ -1479,6 +1481,10 @@ static int do_test(int m)
 		test_hash_speed("ghash-generic", sec, hash_speed_template_16);
 		if (mode > 300 && mode < 400) break;
 
+	case 319:
+		test_hash_speed("crc32c", sec, generic_hash_speed_template);
+		if (mode > 300 && mode < 400) break;
+
 	case 399:
 		break;
 
@@ -1722,6 +1728,29 @@ static int do_test(int m)
 				   speed_template_32_64);
 		break;
 
+	case 508:
+		test_acipher_speed("ecb(camellia)", ENCRYPT, sec, NULL, 0,
+				   speed_template_16_32);
+		test_acipher_speed("ecb(camellia)", DECRYPT, sec, NULL, 0,
+				   speed_template_16_32);
+		test_acipher_speed("cbc(camellia)", ENCRYPT, sec, NULL, 0,
+				   speed_template_16_32);
+		test_acipher_speed("cbc(camellia)", DECRYPT, sec, NULL, 0,
+				   speed_template_16_32);
+		test_acipher_speed("ctr(camellia)", ENCRYPT, sec, NULL, 0,
+				   speed_template_16_32);
+		test_acipher_speed("ctr(camellia)", DECRYPT, sec, NULL, 0,
+				   speed_template_16_32);
+		test_acipher_speed("lrw(camellia)", ENCRYPT, sec, NULL, 0,
+				   speed_template_32_48);
+		test_acipher_speed("lrw(camellia)", DECRYPT, sec, NULL, 0,
+				   speed_template_32_48);
+		test_acipher_speed("xts(camellia)", ENCRYPT, sec, NULL, 0,
+				   speed_template_32_64);
+		test_acipher_speed("xts(camellia)", DECRYPT, sec, NULL, 0,
+				   speed_template_32_64);
+		break;
+
 	case 1000:
 		test_available();
 		break;
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 941d75c..3933241 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1727,6 +1727,21 @@ static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}, {
+		.alg = "__driver-cbc-camellia-aesni",
+		.test = alg_test_null,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = NULL,
+					.count = 0
+				},
+				.dec = {
+					.vecs = NULL,
+					.count = 0
+				}
+			}
+		}
+	}, {
 		.alg = "__driver-cbc-cast5-avx",
 		.test = alg_test_null,
 		.suite = {
@@ -1818,6 +1833,21 @@ static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}, {
+		.alg = "__driver-ecb-camellia-aesni",
+		.test = alg_test_null,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = NULL,
+					.count = 0
+				},
+				.dec = {
+					.vecs = NULL,
+					.count = 0
+				}
+			}
+		}
+	}, {
 		.alg = "__driver-ecb-cast5-avx",
 		.test = alg_test_null,
 		.suite = {
@@ -2143,6 +2173,22 @@ static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}, {
+		.alg = "cryptd(__driver-cbc-camellia-aesni)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = NULL,
+					.count = 0
+				},
+				.dec = {
+					.vecs = NULL,
+					.count = 0
+				}
+			}
+		}
+	}, {
 		.alg = "cryptd(__driver-ecb-aes-aesni)",
 		.test = alg_test_null,
 		.fips_allowed = 1,
@@ -2159,6 +2205,22 @@ static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}, {
+		.alg = "cryptd(__driver-ecb-camellia-aesni)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = NULL,
+					.count = 0
+				},
+				.dec = {
+					.vecs = NULL,
+					.count = 0
+				}
+			}
+		}
+	}, {
 		.alg = "cryptd(__driver-ecb-cast5-avx)",
 		.test = alg_test_null,
 		.suite = {
@@ -2336,6 +2398,36 @@ static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}, {
+		.alg = "ctr(des)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = des_ctr_enc_tv_template,
+					.count = DES_CTR_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = des_ctr_dec_tv_template,
+					.count = DES_CTR_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
+		.alg = "ctr(des3_ede)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = des3_ede_ctr_enc_tv_template,
+					.count = DES3_EDE_CTR_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = des3_ede_ctr_dec_tv_template,
+					.count = DES3_EDE_CTR_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
 		.alg = "ctr(serpent)",
 		.test = alg_test_skcipher,
 		.suite = {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 76d7f6c..76ef5cb 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -1707,7 +1707,7 @@ static struct hash_testvec aes_xcbc128_tv_template[] = {
 	}
 };
 
-#define VMAC_AES_TEST_VECTORS	8
+#define VMAC_AES_TEST_VECTORS	11
 static char vmac_string1[128] = {'\x01', '\x01', '\x01', '\x01',
 				'\x02', '\x03', '\x02', '\x02',
 				'\x02', '\x04', '\x01', '\x07',
@@ -1723,6 +1723,19 @@ static char vmac_string3[128] = {'a', 'b', 'c', 'a', 'b', 'c',
 				'a', 'b', 'c', 'a', 'b', 'c',
 				};
 
+static char vmac_string4[17] = {'b', 'c', 'e', 'f',
+				'i', 'j', 'l', 'm',
+				'o', 'p', 'r', 's',
+				't', 'u', 'w', 'x', 'z'};
+
+static char vmac_string5[127] = {'r', 'm', 'b', 't', 'c',
+				 'o', 'l', 'k', ']', '%',
+				 '9', '2', '7', '!', 'A'};
+
+static char vmac_string6[129] = {'p', 't', '*', '7', 'l',
+				 'i', '!', '#', 'w', '0',
+				 'z', '/', '4', 'A', 'n'};
+
 static struct hash_testvec aes_vmac128_tv_template[] = {
 	{
 		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
@@ -1776,6 +1789,24 @@ static struct hash_testvec aes_vmac128_tv_template[] = {
 		.digest = "\x8b\x32\x8f\xe1\xed\x8f\xfa\xd4",
 		.psize  = 128,
 		.ksize  = 16,
+	}, {
+		.key = "a09b5cd!f#07K\x00\x00\x00",
+		.plaintext = vmac_string4,
+		.digest = "\xab\xa5\x0f\xea\x42\x4e\xa1\x5f",
+		.psize = sizeof(vmac_string4),
+		.ksize = 16,
+	}, {
+		.key = "a09b5cd!f#07K\x00\x00\x00",
+		.plaintext = vmac_string5,
+		.digest = "\x25\x31\x98\xbc\x1d\xe8\x67\x60",
+		.psize = sizeof(vmac_string5),
+		.ksize = 16,
+	}, {
+		.key = "a09b5cd!f#07K\x00\x00\x00",
+		.plaintext = vmac_string6,
+		.digest = "\xc4\xae\x9b\x47\x95\x65\xeb\x41",
+		.psize = sizeof(vmac_string6),
+		.ksize = 16,
 	},
 };
 
@@ -1993,14 +2024,18 @@ static struct hash_testvec hmac_sha512_tv_template[] = {
 /*
  * DES test vectors.
  */
-#define DES_ENC_TEST_VECTORS		10
-#define DES_DEC_TEST_VECTORS		4
-#define DES_CBC_ENC_TEST_VECTORS	5
-#define DES_CBC_DEC_TEST_VECTORS	4
-#define DES3_EDE_ENC_TEST_VECTORS	3
-#define DES3_EDE_DEC_TEST_VECTORS	3
-#define DES3_EDE_CBC_ENC_TEST_VECTORS	1
-#define DES3_EDE_CBC_DEC_TEST_VECTORS	1
+#define DES_ENC_TEST_VECTORS		11
+#define DES_DEC_TEST_VECTORS		5
+#define DES_CBC_ENC_TEST_VECTORS	6
+#define DES_CBC_DEC_TEST_VECTORS	5
+#define DES_CTR_ENC_TEST_VECTORS	2
+#define DES_CTR_DEC_TEST_VECTORS	2
+#define DES3_EDE_ENC_TEST_VECTORS	4
+#define DES3_EDE_DEC_TEST_VECTORS	4
+#define DES3_EDE_CBC_ENC_TEST_VECTORS	2
+#define DES3_EDE_CBC_DEC_TEST_VECTORS	2
+#define DES3_EDE_CTR_ENC_TEST_VECTORS	2
+#define DES3_EDE_CTR_DEC_TEST_VECTORS	2
 
 static struct cipher_testvec des_enc_tv_template[] = {
 	{ /* From Applied Cryptography */
@@ -2103,6 +2138,76 @@ static struct cipher_testvec des_enc_tv_template[] = {
 		.rlen	= 8,
 		.np	= 8,
 		.tap	= { 1, 1, 1, 1, 1, 1, 1, 1 }
+	}, { /* Generated with Crypto++ */
+		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+		.klen	= 8,
+		.input	= "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+			  "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+			  "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+			  "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+			  "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+			  "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+			  "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+			  "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+			  "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+			  "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+			  "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+			  "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+			  "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+			  "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+			  "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+			  "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+			  "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+			  "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+			  "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+			  "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+			  "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+			  "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+			  "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+			  "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+			  "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+			  "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+			  "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+			  "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+			  "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+			  "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+		.ilen	= 248,
+		.result	= "\x88\xCB\x1F\xAB\x2F\x2A\x49\x57"
+			  "\x92\xB9\x77\xFF\x2F\x47\x58\xDD"
+			  "\xD7\x8A\x91\x95\x26\x33\x78\xB2"
+			  "\x33\xBA\xB2\x3E\x02\xF5\x1F\xEF"
+			  "\x98\xC5\xA6\xD2\x7D\x79\xEC\xB3"
+			  "\x45\xF3\x4C\x61\xAC\x6C\xC2\x55"
+			  "\xE5\xD3\x06\x58\x8A\x42\x3E\xDD"
+			  "\x3D\x20\x45\xE9\x6F\x0D\x25\xA8"
+			  "\xA5\xC7\x69\xCE\xD5\x3B\x7B\xC9"
+			  "\x9E\x65\xE7\xA3\xF2\xE4\x18\x94"
+			  "\xD2\x81\xE9\x33\x2B\x2D\x49\xC4"
+			  "\xFE\xDA\x7F\xE2\xF2\x8C\x9C\xDC"
+			  "\x73\x58\x11\x1F\x81\xD7\x21\x1A"
+			  "\x80\xD0\x0D\xE8\x45\xD6\xD8\xD5"
+			  "\x2E\x51\x16\xCA\x09\x89\x54\x62"
+			  "\xF7\x04\x3D\x75\xB9\xA3\x84\xF4"
+			  "\x62\xF0\x02\x58\x83\xAF\x30\x87"
+			  "\x85\x3F\x01\xCD\x8E\x58\x42\xC4"
+			  "\x41\x73\xE0\x15\x0A\xE6\x2E\x80"
+			  "\x94\xF8\x5B\x3A\x4E\xDF\x51\xB2"
+			  "\x9D\xE4\xC4\x9D\xF7\x3F\xF8\x8E"
+			  "\x37\x22\x4D\x00\x2A\xEF\xC1\x0F"
+			  "\x14\xA0\x66\xAB\x79\x39\xD0\x8E"
+			  "\xE9\x95\x61\x74\x12\xED\x07\xD7"
+			  "\xDD\x95\xDC\x7B\x57\x25\x27\x9C"
+			  "\x51\x96\x16\xF7\x94\x61\xB8\x87"
+			  "\xF0\x21\x1B\x32\xFB\x07\x0F\x29"
+			  "\x56\xBD\x9D\x22\xA2\x9F\xA2\xB9"
+			  "\x46\x31\x4C\x5E\x2E\x95\x61\xEF"
+			  "\xE1\x58\x39\x09\xB4\x8B\x40\xAC"
+			  "\x5F\x62\xC7\x72\xD9\xFC\xCB\x9A",
+		.rlen	= 248,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 248 - 8, 8 },
 	},
 };
 
@@ -2143,6 +2248,76 @@ static struct cipher_testvec des_dec_tv_template[] = {
 		.rlen	= 16,
 		.np	= 3,
 		.tap	= { 3, 12, 1 }
+	}, { /* Generated with Crypto++ */
+		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+		.klen	= 8,
+		.input	= "\x88\xCB\x1F\xAB\x2F\x2A\x49\x57"
+			  "\x92\xB9\x77\xFF\x2F\x47\x58\xDD"
+			  "\xD7\x8A\x91\x95\x26\x33\x78\xB2"
+			  "\x33\xBA\xB2\x3E\x02\xF5\x1F\xEF"
+			  "\x98\xC5\xA6\xD2\x7D\x79\xEC\xB3"
+			  "\x45\xF3\x4C\x61\xAC\x6C\xC2\x55"
+			  "\xE5\xD3\x06\x58\x8A\x42\x3E\xDD"
+			  "\x3D\x20\x45\xE9\x6F\x0D\x25\xA8"
+			  "\xA5\xC7\x69\xCE\xD5\x3B\x7B\xC9"
+			  "\x9E\x65\xE7\xA3\xF2\xE4\x18\x94"
+			  "\xD2\x81\xE9\x33\x2B\x2D\x49\xC4"
+			  "\xFE\xDA\x7F\xE2\xF2\x8C\x9C\xDC"
+			  "\x73\x58\x11\x1F\x81\xD7\x21\x1A"
+			  "\x80\xD0\x0D\xE8\x45\xD6\xD8\xD5"
+			  "\x2E\x51\x16\xCA\x09\x89\x54\x62"
+			  "\xF7\x04\x3D\x75\xB9\xA3\x84\xF4"
+			  "\x62\xF0\x02\x58\x83\xAF\x30\x87"
+			  "\x85\x3F\x01\xCD\x8E\x58\x42\xC4"
+			  "\x41\x73\xE0\x15\x0A\xE6\x2E\x80"
+			  "\x94\xF8\x5B\x3A\x4E\xDF\x51\xB2"
+			  "\x9D\xE4\xC4\x9D\xF7\x3F\xF8\x8E"
+			  "\x37\x22\x4D\x00\x2A\xEF\xC1\x0F"
+			  "\x14\xA0\x66\xAB\x79\x39\xD0\x8E"
+			  "\xE9\x95\x61\x74\x12\xED\x07\xD7"
+			  "\xDD\x95\xDC\x7B\x57\x25\x27\x9C"
+			  "\x51\x96\x16\xF7\x94\x61\xB8\x87"
+			  "\xF0\x21\x1B\x32\xFB\x07\x0F\x29"
+			  "\x56\xBD\x9D\x22\xA2\x9F\xA2\xB9"
+			  "\x46\x31\x4C\x5E\x2E\x95\x61\xEF"
+			  "\xE1\x58\x39\x09\xB4\x8B\x40\xAC"
+			  "\x5F\x62\xC7\x72\xD9\xFC\xCB\x9A",
+		.ilen	= 248,
+		.result	= "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+			  "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+			  "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+			  "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+			  "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+			  "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+			  "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+			  "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+			  "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+			  "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+			  "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+			  "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+			  "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+			  "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+			  "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+			  "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+			  "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+			  "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+			  "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+			  "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+			  "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+			  "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+			  "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+			  "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+			  "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+			  "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+			  "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+			  "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+			  "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+			  "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+		.rlen	= 248,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 248 - 8, 8 },
 	},
 };
 
@@ -2198,6 +2373,77 @@ static struct cipher_testvec des_cbc_enc_tv_template[] = {
 		.rlen	= 24,
 		.np	= 2,
 		.tap	= { 13, 11 }
+	}, { /* Generated with Crypto++ */
+		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+		.klen	= 8,
+		.iv	= "\xE7\x82\x1D\xB8\x53\x11\xAC\x47",
+		.input	= "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+			  "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+			  "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+			  "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+			  "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+			  "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+			  "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+			  "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+			  "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+			  "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+			  "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+			  "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+			  "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+			  "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+			  "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+			  "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+			  "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+			  "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+			  "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+			  "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+			  "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+			  "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+			  "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+			  "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+			  "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+			  "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+			  "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+			  "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+			  "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+			  "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+		.ilen	= 248,
+		.result	= "\x71\xCC\x56\x1C\x87\x2C\x43\x20"
+			  "\x1C\x20\x13\x09\xF9\x2B\x40\x47"
+			  "\x99\x10\xD1\x1B\x65\x33\x33\xBA"
+			  "\x88\x0D\xA2\xD1\x86\xFF\x4D\xF4"
+			  "\x5A\x0C\x12\x96\x32\x57\xAA\x26"
+			  "\xA7\xF4\x32\x8D\xBC\x10\x31\x9E"
+			  "\x81\x72\x74\xDE\x30\x19\x69\x49"
+			  "\x54\x9C\xC3\xEB\x0B\x97\xDD\xD1"
+			  "\xE8\x6D\x0D\x05\x83\xA5\x12\x08"
+			  "\x47\xF8\x88\x03\x86\x51\x3C\xEF"
+			  "\xE7\x11\x73\x4D\x44\x2B\xE2\x16"
+			  "\xE8\xA5\x06\x50\x66\x70\x0E\x14"
+			  "\xBA\x21\x3B\xD5\x23\x5B\xA7\x8F"
+			  "\x56\xB6\xA7\x44\xDB\x86\xAB\x69"
+			  "\x33\x3C\xBE\x64\xC4\x22\xD3\xFE"
+			  "\x49\x90\x88\x6A\x09\x8F\x76\x59"
+			  "\xCB\xB7\xA0\x2D\x79\x75\x92\x8A"
+			  "\x82\x1D\xC2\xFE\x09\x1F\x78\x6B"
+			  "\x2F\xD6\xA4\x87\x1E\xC4\x53\x63"
+			  "\x80\x02\x61\x2F\xE3\x46\xB6\xB5"
+			  "\xAA\x95\xF4\xEE\xA7\x64\x2B\x4F"
+			  "\x20\xCF\xD2\x47\x4E\x39\x65\xB3"
+			  "\x11\x87\xA2\x6C\x49\x7E\x36\xC7"
+			  "\x62\x8B\x48\x0D\x6A\x64\x00\xBD"
+			  "\x71\x91\x8C\xE9\x70\x19\x01\x4F"
+			  "\x4E\x68\x23\xBA\xDA\x24\x2E\x45"
+			  "\x02\x14\x33\x21\xAE\x58\x4B\xCF"
+			  "\x3B\x4B\xE8\xF8\xF6\x4F\x34\x93"
+			  "\xD7\x07\x8A\xD7\x18\x92\x36\x8C"
+			  "\x82\xA9\xBD\x6A\x31\x91\x39\x11"
+			  "\xC6\x4A\xF3\x55\xC7\x29\x2E\x63",
+		.rlen	= 248,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 248 - 8, 8 },
 	},
 };
 
@@ -2236,6 +2482,369 @@ static struct cipher_testvec des_cbc_dec_tv_template[] = {
 		.rlen	= 8,
 		.np	= 2,
 		.tap	= { 4, 4 }
+	}, { /* Generated with Crypto++ */
+		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+		.klen	= 8,
+		.iv	= "\xE7\x82\x1D\xB8\x53\x11\xAC\x47",
+		.input	= "\x71\xCC\x56\x1C\x87\x2C\x43\x20"
+			  "\x1C\x20\x13\x09\xF9\x2B\x40\x47"
+			  "\x99\x10\xD1\x1B\x65\x33\x33\xBA"
+			  "\x88\x0D\xA2\xD1\x86\xFF\x4D\xF4"
+			  "\x5A\x0C\x12\x96\x32\x57\xAA\x26"
+			  "\xA7\xF4\x32\x8D\xBC\x10\x31\x9E"
+			  "\x81\x72\x74\xDE\x30\x19\x69\x49"
+			  "\x54\x9C\xC3\xEB\x0B\x97\xDD\xD1"
+			  "\xE8\x6D\x0D\x05\x83\xA5\x12\x08"
+			  "\x47\xF8\x88\x03\x86\x51\x3C\xEF"
+			  "\xE7\x11\x73\x4D\x44\x2B\xE2\x16"
+			  "\xE8\xA5\x06\x50\x66\x70\x0E\x14"
+			  "\xBA\x21\x3B\xD5\x23\x5B\xA7\x8F"
+			  "\x56\xB6\xA7\x44\xDB\x86\xAB\x69"
+			  "\x33\x3C\xBE\x64\xC4\x22\xD3\xFE"
+			  "\x49\x90\x88\x6A\x09\x8F\x76\x59"
+			  "\xCB\xB7\xA0\x2D\x79\x75\x92\x8A"
+			  "\x82\x1D\xC2\xFE\x09\x1F\x78\x6B"
+			  "\x2F\xD6\xA4\x87\x1E\xC4\x53\x63"
+			  "\x80\x02\x61\x2F\xE3\x46\xB6\xB5"
+			  "\xAA\x95\xF4\xEE\xA7\x64\x2B\x4F"
+			  "\x20\xCF\xD2\x47\x4E\x39\x65\xB3"
+			  "\x11\x87\xA2\x6C\x49\x7E\x36\xC7"
+			  "\x62\x8B\x48\x0D\x6A\x64\x00\xBD"
+			  "\x71\x91\x8C\xE9\x70\x19\x01\x4F"
+			  "\x4E\x68\x23\xBA\xDA\x24\x2E\x45"
+			  "\x02\x14\x33\x21\xAE\x58\x4B\xCF"
+			  "\x3B\x4B\xE8\xF8\xF6\x4F\x34\x93"
+			  "\xD7\x07\x8A\xD7\x18\x92\x36\x8C"
+			  "\x82\xA9\xBD\x6A\x31\x91\x39\x11"
+			  "\xC6\x4A\xF3\x55\xC7\x29\x2E\x63",
+		.ilen	= 248,
+		.result	= "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+			  "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+			  "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+			  "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+			  "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+			  "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+			  "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+			  "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+			  "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+			  "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+			  "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+			  "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+			  "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+			  "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+			  "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+			  "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+			  "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+			  "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+			  "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+			  "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+			  "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+			  "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+			  "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+			  "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+			  "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+			  "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+			  "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+			  "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+			  "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+			  "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+		.rlen	= 248,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 248 - 8, 8 },
+	},
+};
+
+static struct cipher_testvec des_ctr_enc_tv_template[] = {
+	{ /* Generated with Crypto++ */
+		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+		.klen	= 8,
+		.iv	= "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+		.input	= "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+			  "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+			  "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+			  "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+			  "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+			  "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+			  "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+			  "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+			  "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+			  "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+			  "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+			  "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+			  "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+			  "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+			  "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+			  "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+			  "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+			  "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+			  "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+			  "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+			  "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+			  "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+			  "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+			  "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+			  "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+			  "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+			  "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+			  "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+			  "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+			  "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+		.ilen	= 248,
+		.result	= "\x2F\x96\x06\x0F\x50\xC9\x68\x03"
+			  "\x0F\x31\xD4\x64\xA5\x29\x77\x35"
+			  "\xBC\x7A\x9F\x19\xE7\x0D\x33\x3E"
+			  "\x12\x0B\x8C\xAE\x48\xAE\xD9\x02"
+			  "\x0A\xD4\xB0\xD6\x37\xB2\x65\x1C"
+			  "\x4B\x65\xEB\x24\xB5\x8E\xAD\x47"
+			  "\x0D\xDA\x79\x77\xA0\x29\xA0\x2B"
+			  "\xC8\x0F\x85\xDC\x03\x13\xA9\x04"
+			  "\x19\x40\xBE\xBE\x5C\x49\x4A\x69"
+			  "\xED\xE8\xE1\x9E\x14\x43\x74\xDE"
+			  "\xEC\x6E\x11\x3F\x36\xEF\x7B\xFB"
+			  "\xBE\x4C\x91\x43\x22\x65\x72\x48"
+			  "\xE2\x12\xED\x88\xAC\xA7\xC9\x91"
+			  "\x14\xA2\x36\x1C\x29\xFF\xC8\x4F"
+			  "\x72\x5C\x4B\xB0\x1E\x93\xC2\xFA"
+			  "\x9D\x53\x86\xA0\xAE\xC6\xB7\x3C"
+			  "\x59\x0C\xD0\x8F\xA6\xD8\xA4\x31"
+			  "\xB7\x30\x1C\x21\x38\xFB\x68\x8C"
+			  "\x2E\xF5\x6E\x73\xC3\x16\x5F\x12"
+			  "\x0C\x33\xB9\x1E\x7B\x70\xDE\x86"
+			  "\x32\xB3\xC1\x16\xAB\xD9\x49\x0B"
+			  "\x96\x28\x72\x6B\xF3\x30\xA9\xEB"
+			  "\x69\xE2\x1E\x58\x46\xA2\x8E\xC7"
+			  "\xC0\xEF\x07\xB7\x77\x2C\x00\x05"
+			  "\x46\xBD\xFE\x53\x81\x8B\xA4\x03"
+			  "\x20\x0F\xDB\x78\x0B\x1F\x53\x04"
+			  "\x4C\x60\x4C\xC3\x2A\x86\x86\x7E"
+			  "\x13\xD2\x26\xED\x5D\x3E\x9C\xF2"
+			  "\x5C\xC4\x15\xC9\x9A\x21\xC5\xCD"
+			  "\x19\x7F\x99\x19\x53\xCE\x1D\x14"
+			  "\x69\x74\xA1\x06\x46\x0F\x4E\x75",
+		.rlen	= 248,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 248 - 8, 8 },
+	}, { /* Generated with Crypto++ */
+		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+		.klen	= 8,
+		.iv	= "\xE7\x82\x1D\xB8\x53\x11\xAC\x47",
+		.input	= "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+			  "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+			  "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+			  "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+			  "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+			  "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+			  "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+			  "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+			  "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+			  "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+			  "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+			  "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+			  "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+			  "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+			  "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+			  "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+			  "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+			  "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+			  "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+			  "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+			  "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+			  "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+			  "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+			  "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+			  "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+			  "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+			  "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+			  "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+			  "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+			  "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+			  "\xC6\x2F\xBB\x24\x8D\x19\x82",
+		.ilen	= 247,
+		.result	= "\x62\xE5\xF4\xDC\x99\xE7\x89\xE3"
+			  "\xF4\x10\xCC\x21\x99\xEB\xDC\x15"
+			  "\x19\x13\x93\x27\x9D\xB6\x6F\x45"
+			  "\x17\x55\x61\x72\xC8\xD3\x7F\xA5"
+			  "\x32\xD0\xD3\x02\x15\xA4\x05\x23"
+			  "\x9C\x23\x61\x60\x77\x7B\x6C\x95"
+			  "\x26\x49\x42\x2E\xF3\xC1\x8C\x6D"
+			  "\xC8\x47\xD5\x94\xE7\x53\xC8\x23"
+			  "\x1B\xA5\x0B\xCB\x12\xD3\x7A\x12"
+			  "\xA4\x42\x15\x34\xF7\x5F\xDC\x58"
+			  "\x5B\x58\x4C\xAD\xD1\x33\x8E\xE6"
+			  "\xE5\xA0\xDA\x4D\x94\x3D\x63\xA8"
+			  "\x02\x82\xBB\x16\xB8\xDC\xB5\x58"
+			  "\xC3\x2D\x79\xE4\x25\x79\x43\xF9"
+			  "\x6D\xD3\xCA\xC0\xE8\x12\xD4\x7E"
+			  "\x04\x25\x79\xFD\x27\xFB\xC4\xEA"
+			  "\x32\x94\x48\x92\xF3\x68\x1A\x7F"
+			  "\x36\x33\x43\x79\xF7\xCA\xC2\x38"
+			  "\xC0\x68\xD4\x53\xA9\xCC\x43\x0C"
+			  "\x40\x57\x3E\xED\x00\x9F\x22\x6E"
+			  "\x80\x99\x0B\xCC\x40\x63\x46\x8A"
+			  "\xE8\xC4\x9B\x6D\x7A\x08\x6E\xA9"
+			  "\x6F\x84\xBC\xB3\xF4\x95\x0B\x2D"
+			  "\x6A\xBA\x37\x50\xC3\xCF\x9F\x7C"
+			  "\x59\x5E\xDE\x0B\x30\xFA\x34\x8A"
+			  "\xF8\xD1\xA2\xF8\x4E\xBD\x5D\x5E"
+			  "\x7D\x71\x99\xE0\xF6\xE5\x7C\xE0"
+			  "\x6D\xEE\x82\x89\x92\xD4\xF5\xD7"
+			  "\xDF\x85\x2D\xE1\xB2\xD6\xAB\x94"
+			  "\xA5\xA6\xE7\xB0\x51\x36\x52\x37"
+			  "\x91\x45\x05\x3E\x58\xBF\x32",
+		.rlen	= 247,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 247 - 8, 8 },
+	},
+};
+
+static struct cipher_testvec des_ctr_dec_tv_template[] = {
+	{ /* Generated with Crypto++ */
+		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+		.klen	= 8,
+		.iv	= "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+		.input	= "\x2F\x96\x06\x0F\x50\xC9\x68\x03"
+			  "\x0F\x31\xD4\x64\xA5\x29\x77\x35"
+			  "\xBC\x7A\x9F\x19\xE7\x0D\x33\x3E"
+			  "\x12\x0B\x8C\xAE\x48\xAE\xD9\x02"
+			  "\x0A\xD4\xB0\xD6\x37\xB2\x65\x1C"
+			  "\x4B\x65\xEB\x24\xB5\x8E\xAD\x47"
+			  "\x0D\xDA\x79\x77\xA0\x29\xA0\x2B"
+			  "\xC8\x0F\x85\xDC\x03\x13\xA9\x04"
+			  "\x19\x40\xBE\xBE\x5C\x49\x4A\x69"
+			  "\xED\xE8\xE1\x9E\x14\x43\x74\xDE"
+			  "\xEC\x6E\x11\x3F\x36\xEF\x7B\xFB"
+			  "\xBE\x4C\x91\x43\x22\x65\x72\x48"
+			  "\xE2\x12\xED\x88\xAC\xA7\xC9\x91"
+			  "\x14\xA2\x36\x1C\x29\xFF\xC8\x4F"
+			  "\x72\x5C\x4B\xB0\x1E\x93\xC2\xFA"
+			  "\x9D\x53\x86\xA0\xAE\xC6\xB7\x3C"
+			  "\x59\x0C\xD0\x8F\xA6\xD8\xA4\x31"
+			  "\xB7\x30\x1C\x21\x38\xFB\x68\x8C"
+			  "\x2E\xF5\x6E\x73\xC3\x16\x5F\x12"
+			  "\x0C\x33\xB9\x1E\x7B\x70\xDE\x86"
+			  "\x32\xB3\xC1\x16\xAB\xD9\x49\x0B"
+			  "\x96\x28\x72\x6B\xF3\x30\xA9\xEB"
+			  "\x69\xE2\x1E\x58\x46\xA2\x8E\xC7"
+			  "\xC0\xEF\x07\xB7\x77\x2C\x00\x05"
+			  "\x46\xBD\xFE\x53\x81\x8B\xA4\x03"
+			  "\x20\x0F\xDB\x78\x0B\x1F\x53\x04"
+			  "\x4C\x60\x4C\xC3\x2A\x86\x86\x7E"
+			  "\x13\xD2\x26\xED\x5D\x3E\x9C\xF2"
+			  "\x5C\xC4\x15\xC9\x9A\x21\xC5\xCD"
+			  "\x19\x7F\x99\x19\x53\xCE\x1D\x14"
+			  "\x69\x74\xA1\x06\x46\x0F\x4E\x75",
+		.ilen	= 248,
+		.result	= "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+			  "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+			  "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+			  "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+			  "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+			  "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+			  "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+			  "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+			  "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+			  "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+			  "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+			  "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+			  "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+			  "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+			  "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+			  "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+			  "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+			  "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+			  "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+			  "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+			  "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+			  "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+			  "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+			  "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+			  "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+			  "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+			  "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+			  "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+			  "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+			  "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
+		.rlen	= 248,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 248 - 8, 8 },
+	}, { /* Generated with Crypto++ */
+		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
+		.klen	= 8,
+		.iv	= "\xE7\x82\x1D\xB8\x53\x11\xAC\x47",
+		.input	= "\x62\xE5\xF4\xDC\x99\xE7\x89\xE3"
+			  "\xF4\x10\xCC\x21\x99\xEB\xDC\x15"
+			  "\x19\x13\x93\x27\x9D\xB6\x6F\x45"
+			  "\x17\x55\x61\x72\xC8\xD3\x7F\xA5"
+			  "\x32\xD0\xD3\x02\x15\xA4\x05\x23"
+			  "\x9C\x23\x61\x60\x77\x7B\x6C\x95"
+			  "\x26\x49\x42\x2E\xF3\xC1\x8C\x6D"
+			  "\xC8\x47\xD5\x94\xE7\x53\xC8\x23"
+			  "\x1B\xA5\x0B\xCB\x12\xD3\x7A\x12"
+			  "\xA4\x42\x15\x34\xF7\x5F\xDC\x58"
+			  "\x5B\x58\x4C\xAD\xD1\x33\x8E\xE6"
+			  "\xE5\xA0\xDA\x4D\x94\x3D\x63\xA8"
+			  "\x02\x82\xBB\x16\xB8\xDC\xB5\x58"
+			  "\xC3\x2D\x79\xE4\x25\x79\x43\xF9"
+			  "\x6D\xD3\xCA\xC0\xE8\x12\xD4\x7E"
+			  "\x04\x25\x79\xFD\x27\xFB\xC4\xEA"
+			  "\x32\x94\x48\x92\xF3\x68\x1A\x7F"
+			  "\x36\x33\x43\x79\xF7\xCA\xC2\x38"
+			  "\xC0\x68\xD4\x53\xA9\xCC\x43\x0C"
+			  "\x40\x57\x3E\xED\x00\x9F\x22\x6E"
+			  "\x80\x99\x0B\xCC\x40\x63\x46\x8A"
+			  "\xE8\xC4\x9B\x6D\x7A\x08\x6E\xA9"
+			  "\x6F\x84\xBC\xB3\xF4\x95\x0B\x2D"
+			  "\x6A\xBA\x37\x50\xC3\xCF\x9F\x7C"
+			  "\x59\x5E\xDE\x0B\x30\xFA\x34\x8A"
+			  "\xF8\xD1\xA2\xF8\x4E\xBD\x5D\x5E"
+			  "\x7D\x71\x99\xE0\xF6\xE5\x7C\xE0"
+			  "\x6D\xEE\x82\x89\x92\xD4\xF5\xD7"
+			  "\xDF\x85\x2D\xE1\xB2\xD6\xAB\x94"
+			  "\xA5\xA6\xE7\xB0\x51\x36\x52\x37"
+			  "\x91\x45\x05\x3E\x58\xBF\x32",
+		.ilen	= 247,
+		.result	= "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+			  "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+			  "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+			  "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+			  "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+			  "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+			  "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+			  "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+			  "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+			  "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+			  "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+			  "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+			  "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+			  "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+			  "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+			  "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+			  "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+			  "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+			  "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+			  "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+			  "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+			  "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+			  "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+			  "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+			  "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+			  "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+			  "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+			  "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+			  "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+			  "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+			  "\xC6\x2F\xBB\x24\x8D\x19\x82",
+		.rlen	= 247,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 247 - 8, 8 },
 	},
 };
 
@@ -2267,6 +2876,140 @@ static struct cipher_testvec des3_ede_enc_tv_template[] = {
 		.ilen	= 8,
 		.result	= "\xe1\xef\x62\xc3\x32\xfe\x82\x5b",
 		.rlen	= 8,
+	}, { /* Generated with Crypto++ */
+		.key	= "\xF3\x9C\xD6\xF3\x9C\xB9\x5A\x67"
+			  "\x00\x5A\x67\x00\x2D\xCE\xEB\x2D"
+			  "\xCE\xEB\xB4\x51\x72\xB4\x51\x72",
+		.klen	= 24,
+		.input	= "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+			  "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+			  "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+			  "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+			  "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+			  "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+			  "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+			  "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+			  "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+			  "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+			  "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+			  "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+			  "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+			  "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+			  "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+			  "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+			  "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+			  "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+			  "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+			  "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+			  "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+			  "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+			  "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+			  "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+			  "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+			  "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+			  "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+			  "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+			  "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+			  "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+			  "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+			  "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+			  "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+			  "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+			  "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+			  "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+			  "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+			  "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+			  "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+			  "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+			  "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+			  "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+			  "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+			  "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+			  "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+			  "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+			  "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+			  "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+			  "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+			  "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+			  "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+			  "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+			  "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+			  "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+			  "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+			  "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+			  "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+			  "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+			  "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+			  "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+			  "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+			  "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+		.ilen	= 496,
+		.result	= "\x4E\x9A\x40\x3D\x61\x7D\x17\xFA"
+			  "\x16\x86\x88\x0B\xD8\xAE\xF8\xE4"
+			  "\x81\x01\x04\x00\x76\xFA\xED\xD3"
+			  "\x44\x7E\x21\x9D\xF0\xFB\x2B\x64"
+			  "\xCA\x4E\x90\xE0\xC0\x63\x28\x92"
+			  "\xF3\x1F\xA4\x53\x2C\x77\xCC\x77"
+			  "\x69\x56\xD0\x19\xAD\x00\x2D\x97"
+			  "\xBC\xDE\x49\x6A\x82\xBC\x16\xE2"
+			  "\x2F\x3E\x72\xEE\xD1\xCE\xFC\x1B"
+			  "\xEA\x32\x56\xE4\x0B\xAF\x27\x36"
+			  "\xAF\x08\xB9\x61\xB7\x48\x23\x27"
+			  "\xEE\x4D\xC8\x79\x56\x06\xEB\xC7"
+			  "\x5B\xCA\x0A\xC6\x5E\x5C\xCB\xB6"
+			  "\x9D\xDA\x04\x59\xE2\x09\x48\x7E"
+			  "\x6B\x37\xC6\xFE\x92\xA9\x1E\x6E"
+			  "\x0D\x19\xFA\x33\x0F\xEE\x36\x68"
+			  "\x11\xBB\xF9\x5A\x73\xAB\x3A\xEA"
+			  "\xAC\x28\xD8\xD5\x27\xE8\x6B\x16"
+			  "\x45\x86\x50\x01\x70\x35\x99\x92"
+			  "\xDF\x0C\x07\x88\x8B\x7F\x9E\x4B"
+			  "\xD2\x04\x84\x90\xC4\x27\xDF\x0A"
+			  "\x49\xA8\xA7\x1A\x6D\x78\x16\xCA"
+			  "\xB3\x18\x5C\xC3\x93\x63\x5A\x68"
+			  "\x77\x02\xBA\xED\x62\x71\xB1\xD9"
+			  "\x5E\xE5\x6F\x1A\xCC\x1D\xBE\x2E"
+			  "\x11\xF3\xA6\x97\xCA\x8E\xBF\xB4"
+			  "\x56\xA1\x36\x6B\xB1\x0A\x3E\x70"
+			  "\xEA\xD7\xCD\x72\x7B\x79\xC8\xAD"
+			  "\x6B\xFE\xFB\xBA\x64\xAE\x19\xC1"
+			  "\x82\xCF\x8A\xA1\x50\x17\x7F\xB2"
+			  "\x6F\x7B\x0F\x52\xC5\x3E\x4A\x52"
+			  "\x3F\xD9\x3F\x01\xA6\x41\x1A\xB3"
+			  "\xB3\x7A\x0E\x8E\x75\xB2\xB1\x5F"
+			  "\xDB\xEA\x84\x13\x26\x6C\x85\x4E"
+			  "\xAE\x6B\xDC\xE7\xE7\xAD\xB0\x06"
+			  "\x5C\xBA\x92\xD0\x30\xBB\x8D\xD2"
+			  "\xAE\x4C\x70\x85\xA0\x07\xE3\x2C"
+			  "\xD1\x27\x9C\xCF\xDB\x13\xB7\xE5"
+			  "\xF9\x6A\x02\xD0\x39\x9D\xB6\xE7"
+			  "\xD1\x17\x25\x08\xF9\xA9\xA6\x67"
+			  "\x38\x80\xD1\x22\xAB\x1A\xD7\x26"
+			  "\xAD\xCA\x19\x1B\xFA\x18\xA7\x57"
+			  "\x31\xEC\xC9\xED\xDB\x79\xC0\x48"
+			  "\xAC\x31\x9F\x03\x8B\x62\x5B\x7E"
+			  "\x0E\xA6\xD0\x64\xEE\xEA\x00\xFC"
+			  "\x58\xC8\xDE\x51\x4E\x17\x15\x11"
+			  "\x66\x58\xB6\x90\xDC\xDF\xA1\x49"
+			  "\xCA\x79\xE9\x31\x31\x42\xDC\x56"
+			  "\x0B\xCD\xB6\x0D\xC7\x64\xF7\x19"
+			  "\xD9\x42\x05\x7F\xBC\x2F\xFC\x90"
+			  "\xAE\x29\x86\xAA\x43\x7A\x4F\x6B"
+			  "\xCE\xEA\xBC\x31\x8D\x65\x9D\x46"
+			  "\xEA\x77\xB4\xF9\x58\xEA\x5D\x84"
+			  "\xE4\xDC\x14\xBB\xBD\x15\x0E\xDA"
+			  "\xD8\xE4\xA4\x5D\x61\xF9\x58\x0F"
+			  "\xE4\x82\x77\xCE\x87\xC0\x09\xF0"
+			  "\xD6\x10\x9E\x34\xE1\x0C\x67\x55"
+			  "\x7B\x6D\xD5\x51\x4B\x00\xEE\xBA"
+			  "\xF2\x7B\xBE\x75\x07\x42\x9D\x99"
+			  "\x12\xE1\x71\x4A\xF9\x2A\xF5\xF6"
+			  "\x93\x03\xD7\x51\x09\xFA\xBE\x68"
+			  "\xD8\x45\xFF\x33\xBA\xBB\x2B\x63",
+		.rlen	= 496,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 496 - 16, 16 },
 	},
 };
 
@@ -2298,6 +3041,140 @@ static struct cipher_testvec des3_ede_dec_tv_template[] = {
 		.ilen	= 8,
 		.result	= "\x00\x00\x00\x00\x00\x00\x00\x00",
 		.rlen	= 8,
+	}, { /* Generated with Crypto++ */
+		.key	= "\xF3\x9C\xD6\xF3\x9C\xB9\x5A\x67"
+			  "\x00\x5A\x67\x00\x2D\xCE\xEB\x2D"
+			  "\xCE\xEB\xB4\x51\x72\xB4\x51\x72",
+		.klen	= 24,
+		.input	= "\x4E\x9A\x40\x3D\x61\x7D\x17\xFA"
+			  "\x16\x86\x88\x0B\xD8\xAE\xF8\xE4"
+			  "\x81\x01\x04\x00\x76\xFA\xED\xD3"
+			  "\x44\x7E\x21\x9D\xF0\xFB\x2B\x64"
+			  "\xCA\x4E\x90\xE0\xC0\x63\x28\x92"
+			  "\xF3\x1F\xA4\x53\x2C\x77\xCC\x77"
+			  "\x69\x56\xD0\x19\xAD\x00\x2D\x97"
+			  "\xBC\xDE\x49\x6A\x82\xBC\x16\xE2"
+			  "\x2F\x3E\x72\xEE\xD1\xCE\xFC\x1B"
+			  "\xEA\x32\x56\xE4\x0B\xAF\x27\x36"
+			  "\xAF\x08\xB9\x61\xB7\x48\x23\x27"
+			  "\xEE\x4D\xC8\x79\x56\x06\xEB\xC7"
+			  "\x5B\xCA\x0A\xC6\x5E\x5C\xCB\xB6"
+			  "\x9D\xDA\x04\x59\xE2\x09\x48\x7E"
+			  "\x6B\x37\xC6\xFE\x92\xA9\x1E\x6E"
+			  "\x0D\x19\xFA\x33\x0F\xEE\x36\x68"
+			  "\x11\xBB\xF9\x5A\x73\xAB\x3A\xEA"
+			  "\xAC\x28\xD8\xD5\x27\xE8\x6B\x16"
+			  "\x45\x86\x50\x01\x70\x35\x99\x92"
+			  "\xDF\x0C\x07\x88\x8B\x7F\x9E\x4B"
+			  "\xD2\x04\x84\x90\xC4\x27\xDF\x0A"
+			  "\x49\xA8\xA7\x1A\x6D\x78\x16\xCA"
+			  "\xB3\x18\x5C\xC3\x93\x63\x5A\x68"
+			  "\x77\x02\xBA\xED\x62\x71\xB1\xD9"
+			  "\x5E\xE5\x6F\x1A\xCC\x1D\xBE\x2E"
+			  "\x11\xF3\xA6\x97\xCA\x8E\xBF\xB4"
+			  "\x56\xA1\x36\x6B\xB1\x0A\x3E\x70"
+			  "\xEA\xD7\xCD\x72\x7B\x79\xC8\xAD"
+			  "\x6B\xFE\xFB\xBA\x64\xAE\x19\xC1"
+			  "\x82\xCF\x8A\xA1\x50\x17\x7F\xB2"
+			  "\x6F\x7B\x0F\x52\xC5\x3E\x4A\x52"
+			  "\x3F\xD9\x3F\x01\xA6\x41\x1A\xB3"
+			  "\xB3\x7A\x0E\x8E\x75\xB2\xB1\x5F"
+			  "\xDB\xEA\x84\x13\x26\x6C\x85\x4E"
+			  "\xAE\x6B\xDC\xE7\xE7\xAD\xB0\x06"
+			  "\x5C\xBA\x92\xD0\x30\xBB\x8D\xD2"
+			  "\xAE\x4C\x70\x85\xA0\x07\xE3\x2C"
+			  "\xD1\x27\x9C\xCF\xDB\x13\xB7\xE5"
+			  "\xF9\x6A\x02\xD0\x39\x9D\xB6\xE7"
+			  "\xD1\x17\x25\x08\xF9\xA9\xA6\x67"
+			  "\x38\x80\xD1\x22\xAB\x1A\xD7\x26"
+			  "\xAD\xCA\x19\x1B\xFA\x18\xA7\x57"
+			  "\x31\xEC\xC9\xED\xDB\x79\xC0\x48"
+			  "\xAC\x31\x9F\x03\x8B\x62\x5B\x7E"
+			  "\x0E\xA6\xD0\x64\xEE\xEA\x00\xFC"
+			  "\x58\xC8\xDE\x51\x4E\x17\x15\x11"
+			  "\x66\x58\xB6\x90\xDC\xDF\xA1\x49"
+			  "\xCA\x79\xE9\x31\x31\x42\xDC\x56"
+			  "\x0B\xCD\xB6\x0D\xC7\x64\xF7\x19"
+			  "\xD9\x42\x05\x7F\xBC\x2F\xFC\x90"
+			  "\xAE\x29\x86\xAA\x43\x7A\x4F\x6B"
+			  "\xCE\xEA\xBC\x31\x8D\x65\x9D\x46"
+			  "\xEA\x77\xB4\xF9\x58\xEA\x5D\x84"
+			  "\xE4\xDC\x14\xBB\xBD\x15\x0E\xDA"
+			  "\xD8\xE4\xA4\x5D\x61\xF9\x58\x0F"
+			  "\xE4\x82\x77\xCE\x87\xC0\x09\xF0"
+			  "\xD6\x10\x9E\x34\xE1\x0C\x67\x55"
+			  "\x7B\x6D\xD5\x51\x4B\x00\xEE\xBA"
+			  "\xF2\x7B\xBE\x75\x07\x42\x9D\x99"
+			  "\x12\xE1\x71\x4A\xF9\x2A\xF5\xF6"
+			  "\x93\x03\xD7\x51\x09\xFA\xBE\x68"
+			  "\xD8\x45\xFF\x33\xBA\xBB\x2B\x63",
+		.ilen	= 496,
+		.result	= "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+			  "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+			  "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+			  "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+			  "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+			  "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+			  "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+			  "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+			  "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+			  "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+			  "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+			  "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+			  "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+			  "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+			  "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+			  "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+			  "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+			  "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+			  "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+			  "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+			  "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+			  "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+			  "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+			  "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+			  "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+			  "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+			  "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+			  "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+			  "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+			  "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+			  "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+			  "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+			  "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+			  "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+			  "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+			  "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+			  "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+			  "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+			  "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+			  "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+			  "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+			  "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+			  "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+			  "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+			  "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+			  "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+			  "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+			  "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+			  "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+			  "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+			  "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+			  "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+			  "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+			  "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+			  "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+			  "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+			  "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+			  "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+			  "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+			  "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+			  "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+			  "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+		.rlen	= 496,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 496 - 16, 16 },
 	},
 };
 
@@ -2342,6 +3219,142 @@ static struct cipher_testvec des3_ede_cbc_enc_tv_template[] = {
 			  "\x9d\xde\xa5\x70\xe9\x42\x45\x8a"
 			  "\x6b\xfa\xb1\x91\x13\xb0\xd9\x19",
 		.rlen	= 128,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+			  "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+			  "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+		.klen	= 24,
+		.iv	= "\xB2\xD7\x48\xED\x06\x44\xF9\x12"
+			  "\xB7\x28\x4D\x83\x24\x59\xF2\x17",
+		.input	= "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+			  "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+			  "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+			  "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+			  "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+			  "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+			  "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+			  "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+			  "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+			  "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+			  "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+			  "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+			  "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+			  "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+			  "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+			  "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+			  "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+			  "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+			  "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+			  "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+			  "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+			  "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+			  "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+			  "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+			  "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+			  "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+			  "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+			  "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+			  "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+			  "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+			  "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+			  "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+			  "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+			  "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+			  "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+			  "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+			  "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+			  "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+			  "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+			  "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+			  "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+			  "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+			  "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+			  "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+			  "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+			  "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+			  "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+			  "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+			  "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+			  "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+			  "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+			  "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+			  "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+			  "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+			  "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+			  "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+			  "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+			  "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+			  "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+			  "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+			  "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+			  "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+		.ilen	= 496,
+		.result	= "\xF8\xF6\xB5\x60\x5C\x5A\x75\x84"
+			  "\x87\x81\x53\xBA\xC9\x6F\xEC\xD5"
+			  "\x1E\x68\x8E\x85\x12\x86\x1D\x38"
+			  "\x1C\x91\x40\xCC\x69\x6A\xD5\x35"
+			  "\x0D\x7C\xB5\x07\x7C\x7B\x2A\xAF"
+			  "\x32\xBC\xA1\xB3\x84\x31\x1B\x3C"
+			  "\x0A\x2B\xFA\xD3\x9F\xB0\x8C\x37"
+			  "\x8F\x9D\xA7\x6D\x6C\xFA\xD7\x90"
+			  "\xE3\x69\x54\xED\x3A\xC4\xF1\x6B"
+			  "\xB1\xCC\xFB\x7D\xD8\x8E\x17\x0B"
+			  "\x9C\xF6\x4C\xD6\xFF\x03\x4E\xD9"
+			  "\xE6\xA5\xAD\x25\xE6\x17\x69\x63"
+			  "\x11\x35\x61\x94\x88\x7B\x1C\x48"
+			  "\xF1\x24\x20\x29\x6B\x93\x1A\x8E"
+			  "\x43\x03\x89\xD8\xB1\xDA\x47\x7B"
+			  "\x79\x3A\x83\x76\xDA\xAE\xC6\xBB"
+			  "\x22\xF8\xE8\x3D\x9A\x65\x54\xD8"
+			  "\x4C\xE9\xE7\xE4\x63\x2F\x5C\x73"
+			  "\x5A\xC3\xAE\x46\xA8\xCD\x57\xE6"
+			  "\x67\x88\xA5\x20\x6F\x5F\x97\xC7"
+			  "\xCC\x15\xA2\x0A\x93\xEA\x33\xE7"
+			  "\x03\x5F\xEC\x64\x30\x6F\xEE\xD7"
+			  "\x7E\xDF\xD6\xE9\x6F\x3F\xD6\x1E"
+			  "\xBE\x67\x6C\x5B\x97\xA0\x09\xE6"
+			  "\xEE\xFE\x55\xA3\x29\x65\xE0\x12"
+			  "\xA1\x6A\x8A\x6F\xF2\xE6\xF1\x96"
+			  "\x87\xFB\x9C\x05\xDD\x80\xEC\xFF"
+			  "\xC5\xED\x50\xFE\xFC\x91\xCD\xCE"
+			  "\x25\x2C\x5F\xD9\xAD\x95\x7D\x99"
+			  "\xF0\x05\xC4\x71\x46\x5F\xF9\x0D"
+			  "\xD2\x63\xDF\x9B\x96\x2E\x2B\xA6"
+			  "\x2B\x1C\xD5\xFB\x96\x24\x60\x60"
+			  "\x54\x40\xB8\x62\xA4\xF8\x46\x95"
+			  "\x73\x28\xA3\xA6\x16\x2B\x17\xE7"
+			  "\x7A\xF8\x62\x54\x3B\x64\x69\xE1"
+			  "\x71\x34\x29\x5B\x4E\x05\x9B\xFA"
+			  "\x5E\xF1\x96\xB7\xCE\x16\x9B\x59"
+			  "\xF1\x1A\x4C\x51\x26\xFD\x79\xE2"
+			  "\x3B\x8E\x71\x69\x6A\x91\xB6\x65"
+			  "\x32\x09\xB8\xE4\x09\x1F\xEA\x39"
+			  "\xCE\x20\x65\x9F\xD6\xD1\xC7\xF0"
+			  "\x73\x50\x08\x56\x20\x9B\x94\x23"
+			  "\x14\x39\xB7\x2B\xB1\x2D\x6D\x6F"
+			  "\x41\x5B\xCC\xE2\x18\xAE\x62\x89"
+			  "\x78\x8E\x67\x23\xD0\xFB\x2B\xE5"
+			  "\x25\xC9\x48\x97\xB5\xD3\x17\xD5"
+			  "\x6A\x9F\xA7\x48\x0C\x2B\x73\x3B"
+			  "\x57\x08\xAE\x91\xF2\xB7\x57\x89"
+			  "\xF4\xD0\xB0\x07\xB0\x42\x6C\xAF"
+			  "\x98\x1A\xE7\xD1\xAC\x1E\xB5\x02"
+			  "\xD4\x56\x42\x79\x79\x7F\x2A\x77"
+			  "\x25\xE9\x7D\xC1\x88\x19\x2B\x49"
+			  "\x6F\x46\x59\xAB\x56\x1F\x61\xE0"
+			  "\x0C\x24\x9C\xC9\x5B\x63\xA9\x12"
+			  "\xCF\x88\x96\xB6\xA8\x24\xC6\xA8"
+			  "\x21\x85\x1A\x62\x7E\x34\xBB\xEB"
+			  "\xBD\x02\x2A\xC7\xD8\x89\x80\xC5"
+			  "\xB1\xBB\x60\xA5\x22\xFC\x6F\x38"
+			  "\x02\x80\xA3\x28\x22\x75\xE1\xE9"
+			  "\x90\xE9\xFA\x4B\x00\x10\xAC\x58"
+			  "\x83\x70\xFF\x86\xE6\xAA\x0F\x1F"
+			  "\x95\x63\x73\xA2\x44\xAC\xF8\xA5",
+		.rlen	= 496,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 496 - 16, 16 },
 	},
 };
 
@@ -2386,6 +3399,698 @@ static struct cipher_testvec des3_ede_cbc_dec_tv_template[] = {
 			  "\x63\x65\x65\x72\x73\x74\x54\x20"
 			  "\x6f\x6f\x4d\x20\x6e\x61\x0a\x79",
 		.rlen	= 128,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+			  "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+			  "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+		.klen	= 24,
+		.iv	= "\xB2\xD7\x48\xED\x06\x44\xF9\x12"
+			  "\xB7\x28\x4D\x83\x24\x59\xF2\x17",
+		.input	= "\xF8\xF6\xB5\x60\x5C\x5A\x75\x84"
+			  "\x87\x81\x53\xBA\xC9\x6F\xEC\xD5"
+			  "\x1E\x68\x8E\x85\x12\x86\x1D\x38"
+			  "\x1C\x91\x40\xCC\x69\x6A\xD5\x35"
+			  "\x0D\x7C\xB5\x07\x7C\x7B\x2A\xAF"
+			  "\x32\xBC\xA1\xB3\x84\x31\x1B\x3C"
+			  "\x0A\x2B\xFA\xD3\x9F\xB0\x8C\x37"
+			  "\x8F\x9D\xA7\x6D\x6C\xFA\xD7\x90"
+			  "\xE3\x69\x54\xED\x3A\xC4\xF1\x6B"
+			  "\xB1\xCC\xFB\x7D\xD8\x8E\x17\x0B"
+			  "\x9C\xF6\x4C\xD6\xFF\x03\x4E\xD9"
+			  "\xE6\xA5\xAD\x25\xE6\x17\x69\x63"
+			  "\x11\x35\x61\x94\x88\x7B\x1C\x48"
+			  "\xF1\x24\x20\x29\x6B\x93\x1A\x8E"
+			  "\x43\x03\x89\xD8\xB1\xDA\x47\x7B"
+			  "\x79\x3A\x83\x76\xDA\xAE\xC6\xBB"
+			  "\x22\xF8\xE8\x3D\x9A\x65\x54\xD8"
+			  "\x4C\xE9\xE7\xE4\x63\x2F\x5C\x73"
+			  "\x5A\xC3\xAE\x46\xA8\xCD\x57\xE6"
+			  "\x67\x88\xA5\x20\x6F\x5F\x97\xC7"
+			  "\xCC\x15\xA2\x0A\x93\xEA\x33\xE7"
+			  "\x03\x5F\xEC\x64\x30\x6F\xEE\xD7"
+			  "\x7E\xDF\xD6\xE9\x6F\x3F\xD6\x1E"
+			  "\xBE\x67\x6C\x5B\x97\xA0\x09\xE6"
+			  "\xEE\xFE\x55\xA3\x29\x65\xE0\x12"
+			  "\xA1\x6A\x8A\x6F\xF2\xE6\xF1\x96"
+			  "\x87\xFB\x9C\x05\xDD\x80\xEC\xFF"
+			  "\xC5\xED\x50\xFE\xFC\x91\xCD\xCE"
+			  "\x25\x2C\x5F\xD9\xAD\x95\x7D\x99"
+			  "\xF0\x05\xC4\x71\x46\x5F\xF9\x0D"
+			  "\xD2\x63\xDF\x9B\x96\x2E\x2B\xA6"
+			  "\x2B\x1C\xD5\xFB\x96\x24\x60\x60"
+			  "\x54\x40\xB8\x62\xA4\xF8\x46\x95"
+			  "\x73\x28\xA3\xA6\x16\x2B\x17\xE7"
+			  "\x7A\xF8\x62\x54\x3B\x64\x69\xE1"
+			  "\x71\x34\x29\x5B\x4E\x05\x9B\xFA"
+			  "\x5E\xF1\x96\xB7\xCE\x16\x9B\x59"
+			  "\xF1\x1A\x4C\x51\x26\xFD\x79\xE2"
+			  "\x3B\x8E\x71\x69\x6A\x91\xB6\x65"
+			  "\x32\x09\xB8\xE4\x09\x1F\xEA\x39"
+			  "\xCE\x20\x65\x9F\xD6\xD1\xC7\xF0"
+			  "\x73\x50\x08\x56\x20\x9B\x94\x23"
+			  "\x14\x39\xB7\x2B\xB1\x2D\x6D\x6F"
+			  "\x41\x5B\xCC\xE2\x18\xAE\x62\x89"
+			  "\x78\x8E\x67\x23\xD0\xFB\x2B\xE5"
+			  "\x25\xC9\x48\x97\xB5\xD3\x17\xD5"
+			  "\x6A\x9F\xA7\x48\x0C\x2B\x73\x3B"
+			  "\x57\x08\xAE\x91\xF2\xB7\x57\x89"
+			  "\xF4\xD0\xB0\x07\xB0\x42\x6C\xAF"
+			  "\x98\x1A\xE7\xD1\xAC\x1E\xB5\x02"
+			  "\xD4\x56\x42\x79\x79\x7F\x2A\x77"
+			  "\x25\xE9\x7D\xC1\x88\x19\x2B\x49"
+			  "\x6F\x46\x59\xAB\x56\x1F\x61\xE0"
+			  "\x0C\x24\x9C\xC9\x5B\x63\xA9\x12"
+			  "\xCF\x88\x96\xB6\xA8\x24\xC6\xA8"
+			  "\x21\x85\x1A\x62\x7E\x34\xBB\xEB"
+			  "\xBD\x02\x2A\xC7\xD8\x89\x80\xC5"
+			  "\xB1\xBB\x60\xA5\x22\xFC\x6F\x38"
+			  "\x02\x80\xA3\x28\x22\x75\xE1\xE9"
+			  "\x90\xE9\xFA\x4B\x00\x10\xAC\x58"
+			  "\x83\x70\xFF\x86\xE6\xAA\x0F\x1F"
+			  "\x95\x63\x73\xA2\x44\xAC\xF8\xA5",
+		.ilen	= 496,
+		.result	= "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+			  "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+			  "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+			  "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+			  "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+			  "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+			  "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+			  "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+			  "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+			  "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+			  "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+			  "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+			  "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+			  "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+			  "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+			  "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+			  "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+			  "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+			  "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+			  "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+			  "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+			  "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+			  "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+			  "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+			  "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+			  "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+			  "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+			  "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+			  "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+			  "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+			  "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+			  "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+			  "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+			  "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+			  "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+			  "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+			  "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+			  "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+			  "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+			  "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+			  "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+			  "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+			  "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+			  "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+			  "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+			  "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+			  "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+			  "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+			  "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+			  "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+			  "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+			  "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+			  "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+			  "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+			  "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+			  "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+			  "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+			  "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+			  "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+			  "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+			  "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+			  "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+		.rlen	= 496,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 496 - 16, 16 },
+	},
+};
+
+static struct cipher_testvec des3_ede_ctr_enc_tv_template[] = {
+	{ /* Generated with Crypto++ */
+		.key	= "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+			  "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+			  "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+		.klen	= 24,
+		.iv	= "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+			  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+		.input	= "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+			  "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+			  "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+			  "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+			  "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+			  "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+			  "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+			  "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+			  "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+			  "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+			  "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+			  "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+			  "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+			  "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+			  "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+			  "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+			  "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+			  "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+			  "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+			  "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+			  "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+			  "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+			  "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+			  "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+			  "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+			  "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+			  "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+			  "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+			  "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+			  "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+			  "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+			  "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+			  "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+			  "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+			  "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+			  "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+			  "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+			  "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+			  "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+			  "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+			  "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+			  "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+			  "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+			  "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+			  "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+			  "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+			  "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+			  "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+			  "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+			  "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+			  "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+			  "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+			  "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+			  "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+			  "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+			  "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+			  "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+			  "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+			  "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+			  "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+			  "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+			  "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+		.ilen	= 496,
+		.result	= "\x07\xC2\x08\x20\x72\x1F\x49\xEF"
+			  "\x19\xCD\x6F\x32\x53\x05\x22\x15"
+			  "\xA2\x85\x2B\xDB\x85\xD2\xD8\xB9"
+			  "\xDD\x0D\x1B\x45\xCB\x69\x11\xD4"
+			  "\xEA\xBE\xB2\x45\x5D\x0C\xAE\xBE"
+			  "\xA0\xC1\x27\xAC\x65\x9F\x53\x7E"
+			  "\xAF\xC2\x1B\xB5\xB8\x6D\x36\x0C"
+			  "\x25\xC0\xF8\x6D\x0B\x29\x01\xDA"
+			  "\x13\x78\xDC\x89\x12\x12\x43\xFA"
+			  "\xF6\x12\xEF\x8D\x87\x62\x78\x83"
+			  "\xE2\xBE\x41\x20\x4C\x6D\x35\x1B"
+			  "\xD1\x0C\x30\xCF\xE2\xDE\x2B\x03"
+			  "\xBF\x45\x73\xD4\xE5\x59\x95\xD1"
+			  "\xB3\x9B\x27\x62\x97\xBD\xDE\x7F"
+			  "\xA4\xD2\x39\x80\xAA\x50\x23\xF0"
+			  "\x74\x88\x3D\xA8\x6A\x18\x79\x3B"
+			  "\xC4\x96\x6C\x8D\x22\x40\x92\x6E"
+			  "\xD6\xAD\x2A\x1F\xDE\x63\xC0\xE7"
+			  "\x07\xF7\x2D\xF7\xB5\xF3\xF0\xCC"
+			  "\x01\x7C\x2A\x9B\xC2\x10\xCA\xAA"
+			  "\xFD\x2B\x3F\xC5\xF3\xF6\xFC\x9B"
+			  "\x45\xDB\x53\xE4\x5B\xF3\xC9\x7B"
+			  "\x8E\x52\xFF\xC8\x02\xB8\xAC\x9D"
+			  "\xA1\x00\x39\xDA\x3D\x2D\x0E\x01"
+			  "\x09\x7D\x8D\x5E\xBE\x53\xB9\xB0"
+			  "\x8E\xE7\xE2\x96\x6A\xB2\x78\xEA"
+			  "\xDE\x23\x8B\xA5\xFA\x5C\xE3\xDA"
+			  "\xBF\x8E\x31\x6A\x55\xD1\x6A\xB2"
+			  "\xB5\x46\x6F\xA5\xF0\xEE\xBA\x1F"
+			  "\x9F\x98\xB0\x66\x4F\xD0\x3F\xA9"
+			  "\xDF\x5F\x58\xC4\xF4\xFF\x75\x5C"
+			  "\x40\x3A\x09\x7E\x6E\x1C\x97\xD4"
+			  "\xCC\xE7\xE7\x71\xCF\x0B\x15\x08"
+			  "\x71\xFA\x07\x97\xCD\xE6\xCA\x1D"
+			  "\x14\x28\x0C\xCF\x99\x13\x7A\xF1"
+			  "\xEB\xFA\xFA\x92\x07\xDE\x1D\xA1"
+			  "\xD3\x36\x69\xFE\x51\x4D\x9F\x2E"
+			  "\x83\x37\x4F\x1F\x48\x30\xED\x04"
+			  "\x4D\xA4\xEF\x3A\xCA\x76\xF4\x1C"
+			  "\x41\x8F\x63\x37\x78\x2F\x86\xA6"
+			  "\xEF\x41\x7E\xD2\xAF\x88\xAB\x67"
+			  "\x52\x71\xC3\x8E\xF8\x26\x93\x72"
+			  "\xAA\xD6\x0E\xE7\x0B\x46\xB1\x3A"
+			  "\xB4\x08\xA9\xA8\xA0\xCF\x20\x0C"
+			  "\x52\xBC\x8B\x05\x56\xB2\xBC\x31"
+			  "\x9B\x74\xB9\x29\x29\x96\x9A\x50"
+			  "\xDC\x45\xDC\x1A\xEB\x0C\x64\xD4"
+			  "\xD3\x05\x7E\x59\x55\xC3\xF4\x90"
+			  "\xC2\xAB\xF8\x9B\x8A\xDA\xCE\xA1"
+			  "\xC3\xF4\xAD\x77\xDD\x44\xC8\xAC"
+			  "\xA3\xF1\xC9\xD2\x19\x5C\xB0\xCA"
+			  "\xA2\x34\xC1\xF7\x6C\xFD\xAC\x65"
+			  "\x32\xDC\x48\xC4\xF2\x00\x6B\x77"
+			  "\xF1\x7D\x76\xAC\xC0\x31\x63\x2A"
+			  "\xA5\x3A\x62\xC8\x91\xB1\x03\x65"
+			  "\xCB\x43\xD1\x06\xDF\xC3\x67\xBC"
+			  "\xDC\xE0\xCD\x35\xCE\x49\x65\xA0"
+			  "\x52\x7B\xA7\x0D\x07\xA9\x1B\xB0"
+			  "\x40\x77\x72\xC2\xEA\x0E\x3A\x78"
+			  "\x46\xB9\x91\xB6\xE7\x3D\x51\x42"
+			  "\xFD\x51\xB0\xC6\x2C\x63\x13\x78"
+			  "\x5C\xEE\xFC\xCF\xC4\x70\x00\x34",
+		.rlen	= 496,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 496 - 16, 16 },
+	}, { /* Generated with Crypto++ */
+		.key	= "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+			  "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+			  "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+		.klen	= 24,
+		.iv	= "\xB2\xD7\x48\xED\x06\x44\xF9\x12"
+			  "\xB7\x28\x4D\x83\x24\x59\xF2\x17",
+		.input	= "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+			  "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+			  "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+			  "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+			  "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+			  "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+			  "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+			  "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+			  "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+			  "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+			  "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+			  "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+			  "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+			  "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+			  "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+			  "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+			  "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+			  "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+			  "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+			  "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+			  "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+			  "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+			  "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+			  "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+			  "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+			  "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+			  "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+			  "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+			  "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+			  "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+			  "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+			  "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+			  "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+			  "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+			  "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+			  "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+			  "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+			  "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+			  "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+			  "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+			  "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+			  "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+			  "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+			  "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+			  "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+			  "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+			  "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+			  "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+			  "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+			  "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+			  "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+			  "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+			  "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+			  "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+			  "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+			  "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+			  "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+			  "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+			  "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+			  "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+			  "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+			  "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47"
+			  "\x2E\xB1\x18",
+		.ilen	= 499,
+		.result	= "\x23\xFF\x5C\x99\x75\xBB\x1F\xD4"
+			  "\xBC\x27\x9D\x36\x60\xA9\xC9\xF7"
+			  "\x94\x9D\x1B\xFF\x8E\x95\x57\x89"
+			  "\x8C\x2E\x33\x70\x43\x61\xE6\xD2"
+			  "\x82\x33\x63\xB6\xC4\x34\x5E\xF8"
+			  "\x96\x07\xA7\xD2\x3B\x8E\xC9\xAA"
+			  "\x7C\xA0\x55\x89\x2E\xE1\x85\x25"
+			  "\x14\x04\xDA\x6B\xE0\xEE\x56\xCF"
+			  "\x08\x2E\x69\xD4\x54\xDE\x22\x84"
+			  "\x69\xA6\xA7\xD3\x3A\x9A\xE8\x05"
+			  "\x63\xDB\xBF\x46\x3A\x26\x2E\x0F"
+			  "\x58\x5C\x46\xEA\x07\x40\xDA\xE1"
+			  "\x14\x1D\xCD\x4F\x06\xC0\xCA\x54"
+			  "\x1E\xC9\x45\x85\x67\x7C\xC2\xB5"
+			  "\x97\x5D\x61\x78\x2E\x46\xEC\x6A"
+			  "\x53\xF4\xD0\xAE\xFA\xB4\x86\x29"
+			  "\x9F\x17\x33\x24\xD8\xB9\xB2\x05"
+			  "\x93\x88\xEA\xF7\xA0\x70\x69\x49"
+			  "\x88\x6B\x73\x40\x41\x8D\xD9\xD9"
+			  "\x7E\x78\xE9\xBE\x6C\x14\x22\x7A"
+			  "\x66\xE1\xDA\xED\x10\xFF\x69\x1D"
+			  "\xB9\xAA\xF2\x56\x72\x1B\x23\xE2"
+			  "\x45\x54\x8B\xA3\x70\x23\xB4\x5E"
+			  "\x8E\x96\xC9\x05\x00\xB3\xB6\xC2"
+			  "\x2A\x02\x43\x7A\x62\xD5\xC8\xD2"
+			  "\xC2\xD0\xE4\x78\xA1\x7B\x3E\xE8"
+			  "\x9F\x7F\x7D\x40\x54\x30\x3B\xC0"
+			  "\xA5\x54\xFD\xCA\x25\xEC\x44\x3E"
+			  "\x1A\x54\x7F\x88\xD0\xE1\xFE\x71"
+			  "\xCE\x05\x49\x89\xBA\xD6\x72\xE7"
+			  "\xD6\x5D\x3F\xA2\xD9\xAB\xC5\x02"
+			  "\xD6\x43\x22\xAF\xA2\xE4\x80\x85"
+			  "\xD7\x87\xB9\xEA\x43\xDB\xC8\xEF"
+			  "\x5C\x82\x2E\x98\x0D\x30\x41\x6B"
+			  "\x08\x48\x8D\xF0\xF8\x60\xD7\x9D"
+			  "\xE9\xDE\x40\xAD\x0D\xAD\x0D\x58"
+			  "\x2A\x98\x35\xFE\xF7\xDD\x4B\x40"
+			  "\xDE\xB0\x05\xD9\x7B\x09\x4D\xBC"
+			  "\x42\xC0\xF1\x15\x0B\xFA\x26\x6B"
+			  "\xC6\x12\x13\x4F\xCB\x35\xBA\x35"
+			  "\xDD\x7A\x36\x9C\x12\x57\x55\x83"
+			  "\x78\x58\x09\xD0\xB0\xCF\x7C\x5C"
+			  "\x38\xCF\xBD\x79\x5B\x13\x4D\x97"
+			  "\xC1\x85\x6F\x97\xC9\xE8\xC2\xA4"
+			  "\x98\xE2\xBD\x77\x6B\x53\x39\x1A"
+			  "\x28\x10\xE7\xE0\xE7\xDE\x9D\x69"
+			  "\x78\x6F\x8E\xD2\xD9\x5D\xD2\x15"
+			  "\x9E\xB5\x4D\x8C\xC0\x78\x22\x2F"
+			  "\x17\x11\x2E\x99\xD7\xE3\xA4\x4F"
+			  "\x65\xA5\x6B\x03\x2C\x35\x6F\xDA"
+			  "\x8A\x19\x08\xE1\x08\x48\x59\x51"
+			  "\x53\x4B\xD1\xDF\xDA\x14\x50\x5F"
+			  "\xDF\xB5\x8C\xDF\xC6\xFD\x85\xFA"
+			  "\xD4\xF9\x64\x45\x65\x0D\x7D\xF4"
+			  "\xC8\xCD\x3F\x32\xAF\xDD\x30\xED"
+			  "\x7B\xAA\xAC\xF0\xDA\x7F\xDF\x75"
+			  "\x1C\xA4\xF1\xCB\x5E\x4F\x0B\xB4"
+			  "\x97\x73\x28\xDE\xCF\xAF\x82\xBD"
+			  "\xC4\xBA\xB4\x9C\x0D\x16\x77\x42"
+			  "\x42\x39\x7C\x53\xA4\xD4\xDD\x40"
+			  "\x5C\x60\x1F\x6E\xA7\xE2\xDC\xE7"
+			  "\x32\x0F\x05\x2F\xF2\x4C\x95\x3B"
+			  "\xF2\x79\xD9",
+		.rlen	= 499,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 499 - 16, 16 },
+	},
+};
+
+static struct cipher_testvec des3_ede_ctr_dec_tv_template[] = {
+	{ /* Generated with Crypto++ */
+		.key	= "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+			  "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+			  "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+		.klen	= 24,
+		.iv	= "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+			  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+		.input	= "\x07\xC2\x08\x20\x72\x1F\x49\xEF"
+			  "\x19\xCD\x6F\x32\x53\x05\x22\x15"
+			  "\xA2\x85\x2B\xDB\x85\xD2\xD8\xB9"
+			  "\xDD\x0D\x1B\x45\xCB\x69\x11\xD4"
+			  "\xEA\xBE\xB2\x45\x5D\x0C\xAE\xBE"
+			  "\xA0\xC1\x27\xAC\x65\x9F\x53\x7E"
+			  "\xAF\xC2\x1B\xB5\xB8\x6D\x36\x0C"
+			  "\x25\xC0\xF8\x6D\x0B\x29\x01\xDA"
+			  "\x13\x78\xDC\x89\x12\x12\x43\xFA"
+			  "\xF6\x12\xEF\x8D\x87\x62\x78\x83"
+			  "\xE2\xBE\x41\x20\x4C\x6D\x35\x1B"
+			  "\xD1\x0C\x30\xCF\xE2\xDE\x2B\x03"
+			  "\xBF\x45\x73\xD4\xE5\x59\x95\xD1"
+			  "\xB3\x9B\x27\x62\x97\xBD\xDE\x7F"
+			  "\xA4\xD2\x39\x80\xAA\x50\x23\xF0"
+			  "\x74\x88\x3D\xA8\x6A\x18\x79\x3B"
+			  "\xC4\x96\x6C\x8D\x22\x40\x92\x6E"
+			  "\xD6\xAD\x2A\x1F\xDE\x63\xC0\xE7"
+			  "\x07\xF7\x2D\xF7\xB5\xF3\xF0\xCC"
+			  "\x01\x7C\x2A\x9B\xC2\x10\xCA\xAA"
+			  "\xFD\x2B\x3F\xC5\xF3\xF6\xFC\x9B"
+			  "\x45\xDB\x53\xE4\x5B\xF3\xC9\x7B"
+			  "\x8E\x52\xFF\xC8\x02\xB8\xAC\x9D"
+			  "\xA1\x00\x39\xDA\x3D\x2D\x0E\x01"
+			  "\x09\x7D\x8D\x5E\xBE\x53\xB9\xB0"
+			  "\x8E\xE7\xE2\x96\x6A\xB2\x78\xEA"
+			  "\xDE\x23\x8B\xA5\xFA\x5C\xE3\xDA"
+			  "\xBF\x8E\x31\x6A\x55\xD1\x6A\xB2"
+			  "\xB5\x46\x6F\xA5\xF0\xEE\xBA\x1F"
+			  "\x9F\x98\xB0\x66\x4F\xD0\x3F\xA9"
+			  "\xDF\x5F\x58\xC4\xF4\xFF\x75\x5C"
+			  "\x40\x3A\x09\x7E\x6E\x1C\x97\xD4"
+			  "\xCC\xE7\xE7\x71\xCF\x0B\x15\x08"
+			  "\x71\xFA\x07\x97\xCD\xE6\xCA\x1D"
+			  "\x14\x28\x0C\xCF\x99\x13\x7A\xF1"
+			  "\xEB\xFA\xFA\x92\x07\xDE\x1D\xA1"
+			  "\xD3\x36\x69\xFE\x51\x4D\x9F\x2E"
+			  "\x83\x37\x4F\x1F\x48\x30\xED\x04"
+			  "\x4D\xA4\xEF\x3A\xCA\x76\xF4\x1C"
+			  "\x41\x8F\x63\x37\x78\x2F\x86\xA6"
+			  "\xEF\x41\x7E\xD2\xAF\x88\xAB\x67"
+			  "\x52\x71\xC3\x8E\xF8\x26\x93\x72"
+			  "\xAA\xD6\x0E\xE7\x0B\x46\xB1\x3A"
+			  "\xB4\x08\xA9\xA8\xA0\xCF\x20\x0C"
+			  "\x52\xBC\x8B\x05\x56\xB2\xBC\x31"
+			  "\x9B\x74\xB9\x29\x29\x96\x9A\x50"
+			  "\xDC\x45\xDC\x1A\xEB\x0C\x64\xD4"
+			  "\xD3\x05\x7E\x59\x55\xC3\xF4\x90"
+			  "\xC2\xAB\xF8\x9B\x8A\xDA\xCE\xA1"
+			  "\xC3\xF4\xAD\x77\xDD\x44\xC8\xAC"
+			  "\xA3\xF1\xC9\xD2\x19\x5C\xB0\xCA"
+			  "\xA2\x34\xC1\xF7\x6C\xFD\xAC\x65"
+			  "\x32\xDC\x48\xC4\xF2\x00\x6B\x77"
+			  "\xF1\x7D\x76\xAC\xC0\x31\x63\x2A"
+			  "\xA5\x3A\x62\xC8\x91\xB1\x03\x65"
+			  "\xCB\x43\xD1\x06\xDF\xC3\x67\xBC"
+			  "\xDC\xE0\xCD\x35\xCE\x49\x65\xA0"
+			  "\x52\x7B\xA7\x0D\x07\xA9\x1B\xB0"
+			  "\x40\x77\x72\xC2\xEA\x0E\x3A\x78"
+			  "\x46\xB9\x91\xB6\xE7\x3D\x51\x42"
+			  "\xFD\x51\xB0\xC6\x2C\x63\x13\x78"
+			  "\x5C\xEE\xFC\xCF\xC4\x70\x00\x34",
+		.ilen	= 496,
+		.result	= "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+			  "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+			  "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+			  "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+			  "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+			  "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+			  "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+			  "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+			  "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+			  "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+			  "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+			  "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+			  "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+			  "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+			  "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+			  "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+			  "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+			  "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+			  "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+			  "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+			  "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+			  "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+			  "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+			  "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+			  "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+			  "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+			  "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+			  "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+			  "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+			  "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+			  "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+			  "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+			  "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+			  "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+			  "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+			  "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+			  "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+			  "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+			  "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+			  "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+			  "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+			  "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+			  "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+			  "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+			  "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+			  "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+			  "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+			  "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+			  "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+			  "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+			  "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+			  "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+			  "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+			  "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+			  "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+			  "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+			  "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+			  "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+			  "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+			  "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+			  "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+			  "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
+		.rlen	= 496,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 496 - 16, 16 },
+	}, { /* Generated with Crypto++ */
+		.key	= "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
+			  "\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
+			  "\xEB\xB4\x51\x72\xB4\x51\x72\x1F",
+		.klen	= 24,
+		.iv	= "\xB2\xD7\x48\xED\x06\x44\xF9\x12"
+			  "\xB7\x28\x4D\x83\x24\x59\xF2\x17",
+		.input	= "\x23\xFF\x5C\x99\x75\xBB\x1F\xD4"
+			  "\xBC\x27\x9D\x36\x60\xA9\xC9\xF7"
+			  "\x94\x9D\x1B\xFF\x8E\x95\x57\x89"
+			  "\x8C\x2E\x33\x70\x43\x61\xE6\xD2"
+			  "\x82\x33\x63\xB6\xC4\x34\x5E\xF8"
+			  "\x96\x07\xA7\xD2\x3B\x8E\xC9\xAA"
+			  "\x7C\xA0\x55\x89\x2E\xE1\x85\x25"
+			  "\x14\x04\xDA\x6B\xE0\xEE\x56\xCF"
+			  "\x08\x2E\x69\xD4\x54\xDE\x22\x84"
+			  "\x69\xA6\xA7\xD3\x3A\x9A\xE8\x05"
+			  "\x63\xDB\xBF\x46\x3A\x26\x2E\x0F"
+			  "\x58\x5C\x46\xEA\x07\x40\xDA\xE1"
+			  "\x14\x1D\xCD\x4F\x06\xC0\xCA\x54"
+			  "\x1E\xC9\x45\x85\x67\x7C\xC2\xB5"
+			  "\x97\x5D\x61\x78\x2E\x46\xEC\x6A"
+			  "\x53\xF4\xD0\xAE\xFA\xB4\x86\x29"
+			  "\x9F\x17\x33\x24\xD8\xB9\xB2\x05"
+			  "\x93\x88\xEA\xF7\xA0\x70\x69\x49"
+			  "\x88\x6B\x73\x40\x41\x8D\xD9\xD9"
+			  "\x7E\x78\xE9\xBE\x6C\x14\x22\x7A"
+			  "\x66\xE1\xDA\xED\x10\xFF\x69\x1D"
+			  "\xB9\xAA\xF2\x56\x72\x1B\x23\xE2"
+			  "\x45\x54\x8B\xA3\x70\x23\xB4\x5E"
+			  "\x8E\x96\xC9\x05\x00\xB3\xB6\xC2"
+			  "\x2A\x02\x43\x7A\x62\xD5\xC8\xD2"
+			  "\xC2\xD0\xE4\x78\xA1\x7B\x3E\xE8"
+			  "\x9F\x7F\x7D\x40\x54\x30\x3B\xC0"
+			  "\xA5\x54\xFD\xCA\x25\xEC\x44\x3E"
+			  "\x1A\x54\x7F\x88\xD0\xE1\xFE\x71"
+			  "\xCE\x05\x49\x89\xBA\xD6\x72\xE7"
+			  "\xD6\x5D\x3F\xA2\xD9\xAB\xC5\x02"
+			  "\xD6\x43\x22\xAF\xA2\xE4\x80\x85"
+			  "\xD7\x87\xB9\xEA\x43\xDB\xC8\xEF"
+			  "\x5C\x82\x2E\x98\x0D\x30\x41\x6B"
+			  "\x08\x48\x8D\xF0\xF8\x60\xD7\x9D"
+			  "\xE9\xDE\x40\xAD\x0D\xAD\x0D\x58"
+			  "\x2A\x98\x35\xFE\xF7\xDD\x4B\x40"
+			  "\xDE\xB0\x05\xD9\x7B\x09\x4D\xBC"
+			  "\x42\xC0\xF1\x15\x0B\xFA\x26\x6B"
+			  "\xC6\x12\x13\x4F\xCB\x35\xBA\x35"
+			  "\xDD\x7A\x36\x9C\x12\x57\x55\x83"
+			  "\x78\x58\x09\xD0\xB0\xCF\x7C\x5C"
+			  "\x38\xCF\xBD\x79\x5B\x13\x4D\x97"
+			  "\xC1\x85\x6F\x97\xC9\xE8\xC2\xA4"
+			  "\x98\xE2\xBD\x77\x6B\x53\x39\x1A"
+			  "\x28\x10\xE7\xE0\xE7\xDE\x9D\x69"
+			  "\x78\x6F\x8E\xD2\xD9\x5D\xD2\x15"
+			  "\x9E\xB5\x4D\x8C\xC0\x78\x22\x2F"
+			  "\x17\x11\x2E\x99\xD7\xE3\xA4\x4F"
+			  "\x65\xA5\x6B\x03\x2C\x35\x6F\xDA"
+			  "\x8A\x19\x08\xE1\x08\x48\x59\x51"
+			  "\x53\x4B\xD1\xDF\xDA\x14\x50\x5F"
+			  "\xDF\xB5\x8C\xDF\xC6\xFD\x85\xFA"
+			  "\xD4\xF9\x64\x45\x65\x0D\x7D\xF4"
+			  "\xC8\xCD\x3F\x32\xAF\xDD\x30\xED"
+			  "\x7B\xAA\xAC\xF0\xDA\x7F\xDF\x75"
+			  "\x1C\xA4\xF1\xCB\x5E\x4F\x0B\xB4"
+			  "\x97\x73\x28\xDE\xCF\xAF\x82\xBD"
+			  "\xC4\xBA\xB4\x9C\x0D\x16\x77\x42"
+			  "\x42\x39\x7C\x53\xA4\xD4\xDD\x40"
+			  "\x5C\x60\x1F\x6E\xA7\xE2\xDC\xE7"
+			  "\x32\x0F\x05\x2F\xF2\x4C\x95\x3B"
+			  "\xF2\x79\xD9",
+		.ilen	= 499,
+		.result	= "\x05\xEC\x77\xFB\x42\xD5\x59\x20"
+			  "\x8B\x12\x86\x69\xF0\x5B\xCF\x56"
+			  "\x39\xAD\x34\x9F\x66\xEA\x7D\xC4"
+			  "\x48\xD3\xBA\x0D\xB1\x18\xE3\x4A"
+			  "\xFE\x41\x28\x5C\x27\x8E\x11\x85"
+			  "\x6C\xF7\x5E\xC2\x55\x3C\xA0\x0B"
+			  "\x92\x65\xE9\x70\xDB\x4F\xD6\xB9"
+			  "\x00\xB4\x1F\xE6\x49\xFD\x44\x2F"
+			  "\x53\x3A\x8D\x14\x98\x63\xCA\x5D"
+			  "\xC1\xA8\x33\xA7\x0E\x91\x78\xEC"
+			  "\x77\xDE\x42\xD5\xBC\x07\x8B\x12"
+			  "\xE5\x4C\xF0\x5B\x22\x56\x39\x80"
+			  "\x6B\x9F\x66\xC9\x50\xC4\xAF\x36"
+			  "\xBA\x0D\x94\x7F\xE3\x4A\xDD\x41"
+			  "\x28\xB3\x1A\x8E\x11\xF8\x43\xF7"
+			  "\x5E\x21\x55\x3C\x87\x6E\x92\x65"
+			  "\xCC\x57\xDB\xA2\x35\xB9\x00\xEB"
+			  "\x72\xE6\x49\xD0\x44\x2F\xB6\x19"
+			  "\x8D\x14\xFF\x46\xCA\x5D\x24\xA8"
+			  "\x33\x9A\x6D\x91\x78\xC3\x77\xDE"
+			  "\xA1\x08\xBC\x07\xEE\x71\xE5\x4C"
+			  "\xD7\x5B\x22\xB5\x1C\x80\x6B\xF2"
+			  "\x45\xC9\x50\x3B\xAF\x36\x99\x60"
+			  "\x94\x7F\xC6\x4A\xDD\xA4\x0F\xB3"
+			  "\x1A\xED\x74\xF8\x43\x2A\x5E\x21"
+			  "\x88\x13\x87\x6E\xF1\x58\xCC\x57"
+			  "\x3E\xA2\x35\x9C\x67\xEB\x72\xC5"
+			  "\x49\xD0\xBB\x02\xB6\x19\xE0\x4B"
+			  "\xFF\x46\x29\x5D\x24\x8F\x16\x9A"
+			  "\x6D\xF4\x5F\xC3\xAA\x3D\xA1\x08"
+			  "\x93\x7A\xEE\x71\xD8\x4C\xD7\xBE"
+			  "\x01\xB5\x1C\xE7\x4E\xF2\x45\x2C"
+			  "\x50\x3B\x82\x15\x99\x60\xCB\x52"
+			  "\xC6\xA9\x30\xA4\x0F\x96\x79\xED"
+			  "\x74\xDF\x43\x2A\xBD\x04\x88\x13"
+			  "\xFA\x4D\xF1\x58\x23\x57\x3E\x81"
+			  "\x68\x9C\x67\xCE\x51\xC5\xAC\x37"
+			  "\xBB\x02\x95\x7C\xE0\x4B\xD2\x46"
+			  "\x29\xB0\x1B\x8F\x16\xF9\x40\xF4"
+			  "\x5F\x26\xAA\x3D\x84\x6F\x93\x7A"
+			  "\xCD\x54\xD8\xA3\x0A\xBE\x01\xE8"
+			  "\x73\xE7\x4E\xD1\x45\x2C\xB7\x1E"
+			  "\x82\x15\xFC\x47\xCB\x52\x25\xA9"
+			  "\x30\x9B\x62\x96\x79\xC0\x74\xDF"
+			  "\xA6\x09\xBD\x04\xEF\x76\xFA\x4D"
+			  "\xD4\x58\x23\x8A\x1D\x81\x68\xF3"
+			  "\x5A\xCE\x51\x38\xAC\x37\x9E\x61"
+			  "\x95\x7C\xC7\x4B\xD2\xA5\x0C\xB0"
+			  "\x1B\xE2\x75\xF9\x40\x2B\x5F\x26"
+			  "\x89\x10\x84\x6F\xF6\x59\xCD\x54"
+			  "\x3F\xA3\x0A\x9D\x64\xE8\x73\xDA"
+			  "\x4E\xD1\xB8\x03\xB7\x1E\xE1\x48"
+			  "\xFC\x47\x2E\x52\x25\x8C\x17\x9B"
+			  "\x62\xF5\x5C\xC0\xAB\x32\xA6\x09"
+			  "\x90\x7B\xEF\x76\xD9\x4D\xD4\xBF"
+			  "\x06\x8A\x1D\xE4\x4F\xF3\x5A\x2D"
+			  "\x51\x38\x83\x6A\x9E\x61\xC8\x53"
+			  "\xC7\xAE\x31\xA5\x0C\x97\x7E\xE2"
+			  "\x75\xDC\x40\x2B\xB2\x05\x89\x10"
+			  "\xFB\x42\xF6\x59\x20\x54\x3F\x86"
+			  "\x69\x9D\x64\xCF\x56\xDA\xAD\x34"
+			  "\xB8\x03\xEA\x7D\xE1\x48\xD3\x47"
+			  "\x2E\xB1\x18",
+		.rlen	= 499,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 499 - 16, 16 },
 	},
 };
 
@@ -2461,17 +4166,133 @@ static struct cipher_testvec bf_enc_tv_template[] = {
 			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
 			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-		.ilen	= 40,
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+			  "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+		.ilen	= 504,
 		.result	= "\x96\x87\x3D\x0C\x7B\xFB\xBD\x1F"
 			  "\xE3\xC1\x99\x6D\x39\xD4\xC2\x7D"
 			  "\xD7\x87\xA1\xF2\xDF\x51\x71\x26"
 			  "\xC2\xF4\x6D\xFF\xF6\xCD\x6B\x40"
-			  "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B",
-		.rlen	= 40,
+			  "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B"
+			  "\xD3\xB2\xD4\x61\xC7\x9F\x06\xE9"
+			  "\xCD\xF3\x88\x39\x39\x7A\xDF\x19"
+			  "\xE8\x03\x2A\x0B\x9E\xA0\x2B\x86"
+			  "\x31\xF8\x9D\xB1\xEE\x78\x9D\xB5"
+			  "\xCD\x8B\x7C\x2E\xF5\xA2\x2D\x5D"
+			  "\x6E\x66\xAF\x38\x6C\xD3\x13\xED"
+			  "\x14\xEA\x5D\xD0\x17\x77\x0F\x4A"
+			  "\x50\xF2\xD0\x0F\xC8\xF7\x1E\x7B"
+			  "\x9D\x5B\x54\x65\x4F\x16\x8A\x97"
+			  "\xF3\xF6\xD4\xAA\x87\x36\x77\x72"
+			  "\x99\x4A\xB5\x5E\x88\xC3\xCD\x7D"
+			  "\x1D\x97\xF9\x11\xBD\xE0\x1F\x1F"
+			  "\x96\x3E\x4B\x22\xF4\xC0\xE6\xB8"
+			  "\x47\x82\x98\x23\x33\x36\xBC\x1B"
+			  "\x36\xE7\xF6\xCF\x97\x37\x16\xC0"
+			  "\x87\x31\x8B\xB0\xDB\x19\x42\xA5"
+			  "\x1F\x90\x7E\x66\x34\xDD\x5E\xE9"
+			  "\x4F\xB2\x2B\x9A\xDE\xB3\x5D\x71"
+			  "\x4D\x68\xF0\xDC\xA6\xEA\xE3\x9B"
+			  "\x60\x00\x55\x57\x06\x8B\xD5\xB3"
+			  "\x86\x30\x78\xDA\x33\x9A\x9D\xCC"
+			  "\xBA\x0B\x81\x06\x77\x43\xC7\xC9"
+			  "\xDB\x37\x60\x11\x45\x59\x6D\x2D"
+			  "\x90\x3D\x65\x3E\xD0\x13\xC6\x3C"
+			  "\x0E\x78\x7D\x9A\x00\xD6\x2F\x0B"
+			  "\x3B\x53\x19\x1E\xA8\x9B\x11\xD9"
+			  "\x98\xE4\x7F\xC3\x6E\x51\x24\x70"
+			  "\x9F\x04\x9C\xC2\x9E\x44\x84\xE3"
+			  "\xE0\x8A\x44\xA2\x5C\x94\x74\x34"
+			  "\x37\x52\x7C\x03\xE8\x8E\x97\xE1"
+			  "\x5B\x5C\x0E\xB0\x70\xFE\x54\x3F"
+			  "\xD8\x65\xA9\xC5\xCD\xEC\xF4\x45"
+			  "\x55\xC5\xA7\xA3\x19\x80\x28\x51"
+			  "\xBE\x64\x4A\xC1\xD4\xE1\xBE\xEB"
+			  "\x73\x4C\xB6\xF9\x5F\x6D\x82\xBC"
+			  "\x3E\x42\x14\x49\x88\x51\xBF\x68"
+			  "\x45\x75\x27\x1B\x0A\x72\xED\xAF"
+			  "\xDA\xC4\x4D\x67\x0D\xEE\x75\xE3"
+			  "\x34\xDD\x91\x19\x42\x3A\xCB\xDA"
+			  "\x38\xFA\x3C\x93\x62\xF2\xE3\x81"
+			  "\xB3\xE4\xBB\xF6\x0D\x0B\x1D\x09"
+			  "\x9C\x52\x0D\x50\x63\xA4\xB2\xD2"
+			  "\x82\xA0\x23\x3F\x1F\xB6\xED\x6E"
+			  "\xC2\x9C\x1C\xD0\x9A\x40\xB6\xFC"
+			  "\x36\x56\x6E\x85\x73\xD7\x52\xBA"
+			  "\x35\x5E\x32\x89\x5D\x42\xF5\x36"
+			  "\x52\x8D\x46\x7D\xC8\x71\xAD\x33"
+			  "\xE1\xAF\x6A\xA8\xEC\xBA\x1C\xDC"
+			  "\xFE\x88\xE6\x16\xE4\xC8\x13\x00"
+			  "\x3C\xDA\x59\x32\x38\x19\xD5\xEB"
+			  "\xB6\x7F\x78\x45\x1B\x8E\x07\x8C"
+			  "\x66\x52\x75\xFF\xAF\xCE\x2D\x2B"
+			  "\x22\x29\xCA\xB3\x5F\x7F\xE3\x29"
+			  "\xB2\xB8\x9D\xEB\x16\xC8\xC5\x1D"
+			  "\xC9\x0D\x59\x82\x27\x57\x9D\x42"
+			  "\x54\x59\x09\xA5\x3D\xC5\x84\x68"
+			  "\x56\xEB\x36\x77\x3D\xAA\xB8\xF5"
+			  "\xC9\x1A\xFB\x5D\xDE\xBB\x43\xF4",
+		.rlen	= 504,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 40 - 8, 8 },
+		.tap	= { 504 - 8, 8 },
 	},
 };
 
@@ -2537,17 +4358,133 @@ static struct cipher_testvec bf_dec_tv_template[] = {
 			  "\xE3\xC1\x99\x6D\x39\xD4\xC2\x7D"
 			  "\xD7\x87\xA1\xF2\xDF\x51\x71\x26"
 			  "\xC2\xF4\x6D\xFF\xF6\xCD\x6B\x40"
-			  "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B",
-		.ilen	= 40,
+			  "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B"
+			  "\xD3\xB2\xD4\x61\xC7\x9F\x06\xE9"
+			  "\xCD\xF3\x88\x39\x39\x7A\xDF\x19"
+			  "\xE8\x03\x2A\x0B\x9E\xA0\x2B\x86"
+			  "\x31\xF8\x9D\xB1\xEE\x78\x9D\xB5"
+			  "\xCD\x8B\x7C\x2E\xF5\xA2\x2D\x5D"
+			  "\x6E\x66\xAF\x38\x6C\xD3\x13\xED"
+			  "\x14\xEA\x5D\xD0\x17\x77\x0F\x4A"
+			  "\x50\xF2\xD0\x0F\xC8\xF7\x1E\x7B"
+			  "\x9D\x5B\x54\x65\x4F\x16\x8A\x97"
+			  "\xF3\xF6\xD4\xAA\x87\x36\x77\x72"
+			  "\x99\x4A\xB5\x5E\x88\xC3\xCD\x7D"
+			  "\x1D\x97\xF9\x11\xBD\xE0\x1F\x1F"
+			  "\x96\x3E\x4B\x22\xF4\xC0\xE6\xB8"
+			  "\x47\x82\x98\x23\x33\x36\xBC\x1B"
+			  "\x36\xE7\xF6\xCF\x97\x37\x16\xC0"
+			  "\x87\x31\x8B\xB0\xDB\x19\x42\xA5"
+			  "\x1F\x90\x7E\x66\x34\xDD\x5E\xE9"
+			  "\x4F\xB2\x2B\x9A\xDE\xB3\x5D\x71"
+			  "\x4D\x68\xF0\xDC\xA6\xEA\xE3\x9B"
+			  "\x60\x00\x55\x57\x06\x8B\xD5\xB3"
+			  "\x86\x30\x78\xDA\x33\x9A\x9D\xCC"
+			  "\xBA\x0B\x81\x06\x77\x43\xC7\xC9"
+			  "\xDB\x37\x60\x11\x45\x59\x6D\x2D"
+			  "\x90\x3D\x65\x3E\xD0\x13\xC6\x3C"
+			  "\x0E\x78\x7D\x9A\x00\xD6\x2F\x0B"
+			  "\x3B\x53\x19\x1E\xA8\x9B\x11\xD9"
+			  "\x98\xE4\x7F\xC3\x6E\x51\x24\x70"
+			  "\x9F\x04\x9C\xC2\x9E\x44\x84\xE3"
+			  "\xE0\x8A\x44\xA2\x5C\x94\x74\x34"
+			  "\x37\x52\x7C\x03\xE8\x8E\x97\xE1"
+			  "\x5B\x5C\x0E\xB0\x70\xFE\x54\x3F"
+			  "\xD8\x65\xA9\xC5\xCD\xEC\xF4\x45"
+			  "\x55\xC5\xA7\xA3\x19\x80\x28\x51"
+			  "\xBE\x64\x4A\xC1\xD4\xE1\xBE\xEB"
+			  "\x73\x4C\xB6\xF9\x5F\x6D\x82\xBC"
+			  "\x3E\x42\x14\x49\x88\x51\xBF\x68"
+			  "\x45\x75\x27\x1B\x0A\x72\xED\xAF"
+			  "\xDA\xC4\x4D\x67\x0D\xEE\x75\xE3"
+			  "\x34\xDD\x91\x19\x42\x3A\xCB\xDA"
+			  "\x38\xFA\x3C\x93\x62\xF2\xE3\x81"
+			  "\xB3\xE4\xBB\xF6\x0D\x0B\x1D\x09"
+			  "\x9C\x52\x0D\x50\x63\xA4\xB2\xD2"
+			  "\x82\xA0\x23\x3F\x1F\xB6\xED\x6E"
+			  "\xC2\x9C\x1C\xD0\x9A\x40\xB6\xFC"
+			  "\x36\x56\x6E\x85\x73\xD7\x52\xBA"
+			  "\x35\x5E\x32\x89\x5D\x42\xF5\x36"
+			  "\x52\x8D\x46\x7D\xC8\x71\xAD\x33"
+			  "\xE1\xAF\x6A\xA8\xEC\xBA\x1C\xDC"
+			  "\xFE\x88\xE6\x16\xE4\xC8\x13\x00"
+			  "\x3C\xDA\x59\x32\x38\x19\xD5\xEB"
+			  "\xB6\x7F\x78\x45\x1B\x8E\x07\x8C"
+			  "\x66\x52\x75\xFF\xAF\xCE\x2D\x2B"
+			  "\x22\x29\xCA\xB3\x5F\x7F\xE3\x29"
+			  "\xB2\xB8\x9D\xEB\x16\xC8\xC5\x1D"
+			  "\xC9\x0D\x59\x82\x27\x57\x9D\x42"
+			  "\x54\x59\x09\xA5\x3D\xC5\x84\x68"
+			  "\x56\xEB\x36\x77\x3D\xAA\xB8\xF5"
+			  "\xC9\x1A\xFB\x5D\xDE\xBB\x43\xF4",
+		.ilen	= 504,
 		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
 			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
 			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-		.rlen	= 40,
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+			  "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+		.rlen	= 504,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 40 - 8, 8 },
+		.tap	= { 504 - 8, 8 },
 	},
 };
 
@@ -2578,29 +4515,145 @@ static struct cipher_testvec bf_cbc_enc_tv_template[] = {
 			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
 			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-		.ilen	= 40,
-		.result	= "\xB4\xFE\xA5\xBB\x3D\x2C\x27\x06"
-			  "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
-			  "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
-			  "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
-			  "\x01\x9C\x93\x63\x51\x60\x82\xD2",
-		.rlen	= 40,
-		.also_non_np = 1,
-		.np	= 2,
-		.tap	= { 40 - 8, 8 },
-	},
-};
-
-static struct cipher_testvec bf_cbc_dec_tv_template[] = {
-	{ /* From OpenSSL */
-		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
-			  "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
-		.klen	= 16,
-		.iv	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
-		.input	= "\x6b\x77\xb4\xd6\x30\x06\xde\xe6"
-			  "\x05\xb1\x56\xe2\x74\x03\x97\x93"
-			  "\x58\xde\xb9\xe7\x15\x46\x16\xd9"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+			  "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+		.ilen	= 504,
+		.result	= "\xB4\xFE\xA5\xBB\x3D\x2C\x27\x06"
+			  "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
+			  "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
+			  "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
+			  "\x01\x9C\x93\x63\x51\x60\x82\xD2"
+			  "\x4D\xE5\xC2\xB7\xAE\x60\xD8\xAD"
+			  "\x9F\xAB\x6C\xFA\x20\x05\xDA\x6F"
+			  "\x1F\xD1\xD8\x36\x0F\xB5\x16\x69"
+			  "\x3C\xAF\xB3\x30\x18\x33\xE6\xB5"
+			  "\x43\x29\x9D\x94\xF4\x2F\x0A\x65"
+			  "\x40\xB2\xB2\xB2\x42\x89\xEE\x8A"
+			  "\x60\xD3\x52\xA8\xED\x91\xDF\xE1"
+			  "\x91\x73\x7C\x28\xA1\x14\xC3\x4C"
+			  "\x82\x72\x4B\x7D\x7D\x32\xD5\x19"
+			  "\xE8\xB8\x6B\x30\x21\x09\x0E\x27"
+			  "\x10\x9D\x2D\x3A\x6A\x4B\x7B\xE6"
+			  "\x8D\x4E\x02\x32\xFF\x7F\x8E\x13"
+			  "\xB0\x96\xF4\xC2\xA1\x60\x8A\x69"
+			  "\xEF\x0F\x86\xD0\x25\x13\x1A\x7C"
+			  "\x6E\xF0\x41\xA3\xFB\xB3\xAB\x40"
+			  "\x7D\x19\xA0\x11\x4F\x3E\x1D\x43"
+			  "\x65\xFE\x15\x40\xD0\x62\x41\x02"
+			  "\xEA\x0C\x7A\xC3\x84\xEE\xB0\xBE"
+			  "\xBE\xC8\x57\x51\xCD\x4F\xAD\x5C"
+			  "\xCC\x79\xBA\x0D\x85\x3A\xED\x6B"
+			  "\xAC\x6B\xA3\x4D\xBC\xE8\x02\x6A"
+			  "\xC2\x6D\xBD\x5E\x89\x95\x86\x43"
+			  "\x2C\x17\x4B\xC6\x40\xA2\xBD\x24"
+			  "\x04\xF0\x86\x08\x78\x18\x42\xE0"
+			  "\x39\x1B\x22\x9E\x89\x4C\x04\x6B"
+			  "\x65\xC5\xB6\x0E\xF6\x63\xFC\xD7"
+			  "\xAE\x9E\x87\x13\xCC\xD3\x1A\xEC"
+			  "\xF0\x51\xCC\x93\x68\xFC\xE9\x19"
+			  "\x7C\x4E\x9B\xCC\x17\xAD\xD2\xFC"
+			  "\x97\x18\x92\xFF\x15\x11\xCE\xED"
+			  "\x04\x41\x05\xA3\x92\xFF\x3B\xE6"
+			  "\xB6\x8C\x90\xC6\xCD\x15\xA0\x04"
+			  "\x25\x8B\x5D\x5B\x5F\xDB\xAE\x68"
+			  "\xEF\xB3\x61\x18\xDB\x83\x9B\x39"
+			  "\xCA\x82\xD1\x88\xF0\xA2\x5C\x02"
+			  "\x87\xBD\x8D\x8F\xBB\x62\xF0\x35"
+			  "\x75\x6F\x06\x81\x0A\x97\x4D\xF0"
+			  "\x43\x12\x73\x77\xDB\x91\x83\x5B"
+			  "\xE7\x3A\xA6\x07\x7B\xBF\x2C\x50"
+			  "\x94\xDE\x7B\x65\xDA\x1C\xF1\x9F"
+			  "\x7E\x12\x40\xB2\x3E\x19\x23\xF1"
+			  "\x7C\x1B\x5F\xA8\xF3\xAC\x63\x87"
+			  "\xEB\x3E\x0C\xBE\xA3\x63\x97\x88"
+			  "\x8D\x27\xC6\x2A\xF8\xF2\x67\x9A"
+			  "\x0D\x14\x16\x2B\x6F\xCB\xD4\x76"
+			  "\x14\x48\x2E\xDE\x2A\x44\x5E\x45"
+			  "\xF1\x97\x82\xEF\xB7\xAE\xED\x3A"
+			  "\xED\x73\xD3\x79\xF7\x38\x1D\xD0"
+			  "\xC5\xF8\x69\x83\x28\x84\x87\x56"
+			  "\x3F\xAE\x81\x04\x79\x1F\xD1\x09"
+			  "\xC5\xE5\x05\x0D\x64\x16\xCE\x42"
+			  "\xC5\xF8\xDB\x57\x89\x33\x22\xFC"
+			  "\xB4\xD7\x94\xB9\xF3\xCC\x02\x90"
+			  "\x02\xBA\x55\x1E\x24\x3E\x02\x1D"
+			  "\xC6\xCD\x8F\xD9\xBD\xED\xB0\x51"
+			  "\xCD\xE9\xD5\x0C\xFE\x12\x39\xA9"
+			  "\x93\x9B\xEE\xB5\x97\x41\xD2\xA0"
+			  "\xB4\x98\xD8\x6B\x74\xE7\x65\xF4",
+		.rlen	= 504,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 504 - 8, 8 },
+	},
+};
+
+static struct cipher_testvec bf_cbc_dec_tv_template[] = {
+	{ /* From OpenSSL */
+		.key	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
+			  "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+		.klen	= 16,
+		.iv	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+		.input	= "\x6b\x77\xb4\xd6\x30\x06\xde\xe6"
+			  "\x05\xb1\x56\xe2\x74\x03\x97\x93"
+			  "\x58\xde\xb9\xe7\x15\x46\x16\xd9"
 			  "\x59\xf1\x65\x2b\xd5\xff\x92\xcc",
 		.ilen	= 32,
 		.result	= "\x37\x36\x35\x34\x33\x32\x31\x20"
@@ -2619,17 +4672,133 @@ static struct cipher_testvec bf_cbc_dec_tv_template[] = {
 			  "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
 			  "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
 			  "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
-			  "\x01\x9C\x93\x63\x51\x60\x82\xD2",
-		.ilen	= 40,
+			  "\x01\x9C\x93\x63\x51\x60\x82\xD2"
+			  "\x4D\xE5\xC2\xB7\xAE\x60\xD8\xAD"
+			  "\x9F\xAB\x6C\xFA\x20\x05\xDA\x6F"
+			  "\x1F\xD1\xD8\x36\x0F\xB5\x16\x69"
+			  "\x3C\xAF\xB3\x30\x18\x33\xE6\xB5"
+			  "\x43\x29\x9D\x94\xF4\x2F\x0A\x65"
+			  "\x40\xB2\xB2\xB2\x42\x89\xEE\x8A"
+			  "\x60\xD3\x52\xA8\xED\x91\xDF\xE1"
+			  "\x91\x73\x7C\x28\xA1\x14\xC3\x4C"
+			  "\x82\x72\x4B\x7D\x7D\x32\xD5\x19"
+			  "\xE8\xB8\x6B\x30\x21\x09\x0E\x27"
+			  "\x10\x9D\x2D\x3A\x6A\x4B\x7B\xE6"
+			  "\x8D\x4E\x02\x32\xFF\x7F\x8E\x13"
+			  "\xB0\x96\xF4\xC2\xA1\x60\x8A\x69"
+			  "\xEF\x0F\x86\xD0\x25\x13\x1A\x7C"
+			  "\x6E\xF0\x41\xA3\xFB\xB3\xAB\x40"
+			  "\x7D\x19\xA0\x11\x4F\x3E\x1D\x43"
+			  "\x65\xFE\x15\x40\xD0\x62\x41\x02"
+			  "\xEA\x0C\x7A\xC3\x84\xEE\xB0\xBE"
+			  "\xBE\xC8\x57\x51\xCD\x4F\xAD\x5C"
+			  "\xCC\x79\xBA\x0D\x85\x3A\xED\x6B"
+			  "\xAC\x6B\xA3\x4D\xBC\xE8\x02\x6A"
+			  "\xC2\x6D\xBD\x5E\x89\x95\x86\x43"
+			  "\x2C\x17\x4B\xC6\x40\xA2\xBD\x24"
+			  "\x04\xF0\x86\x08\x78\x18\x42\xE0"
+			  "\x39\x1B\x22\x9E\x89\x4C\x04\x6B"
+			  "\x65\xC5\xB6\x0E\xF6\x63\xFC\xD7"
+			  "\xAE\x9E\x87\x13\xCC\xD3\x1A\xEC"
+			  "\xF0\x51\xCC\x93\x68\xFC\xE9\x19"
+			  "\x7C\x4E\x9B\xCC\x17\xAD\xD2\xFC"
+			  "\x97\x18\x92\xFF\x15\x11\xCE\xED"
+			  "\x04\x41\x05\xA3\x92\xFF\x3B\xE6"
+			  "\xB6\x8C\x90\xC6\xCD\x15\xA0\x04"
+			  "\x25\x8B\x5D\x5B\x5F\xDB\xAE\x68"
+			  "\xEF\xB3\x61\x18\xDB\x83\x9B\x39"
+			  "\xCA\x82\xD1\x88\xF0\xA2\x5C\x02"
+			  "\x87\xBD\x8D\x8F\xBB\x62\xF0\x35"
+			  "\x75\x6F\x06\x81\x0A\x97\x4D\xF0"
+			  "\x43\x12\x73\x77\xDB\x91\x83\x5B"
+			  "\xE7\x3A\xA6\x07\x7B\xBF\x2C\x50"
+			  "\x94\xDE\x7B\x65\xDA\x1C\xF1\x9F"
+			  "\x7E\x12\x40\xB2\x3E\x19\x23\xF1"
+			  "\x7C\x1B\x5F\xA8\xF3\xAC\x63\x87"
+			  "\xEB\x3E\x0C\xBE\xA3\x63\x97\x88"
+			  "\x8D\x27\xC6\x2A\xF8\xF2\x67\x9A"
+			  "\x0D\x14\x16\x2B\x6F\xCB\xD4\x76"
+			  "\x14\x48\x2E\xDE\x2A\x44\x5E\x45"
+			  "\xF1\x97\x82\xEF\xB7\xAE\xED\x3A"
+			  "\xED\x73\xD3\x79\xF7\x38\x1D\xD0"
+			  "\xC5\xF8\x69\x83\x28\x84\x87\x56"
+			  "\x3F\xAE\x81\x04\x79\x1F\xD1\x09"
+			  "\xC5\xE5\x05\x0D\x64\x16\xCE\x42"
+			  "\xC5\xF8\xDB\x57\x89\x33\x22\xFC"
+			  "\xB4\xD7\x94\xB9\xF3\xCC\x02\x90"
+			  "\x02\xBA\x55\x1E\x24\x3E\x02\x1D"
+			  "\xC6\xCD\x8F\xD9\xBD\xED\xB0\x51"
+			  "\xCD\xE9\xD5\x0C\xFE\x12\x39\xA9"
+			  "\x93\x9B\xEE\xB5\x97\x41\xD2\xA0"
+			  "\xB4\x98\xD8\x6B\x74\xE7\x65\xF4",
+		.ilen	= 504,
 		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
 			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
 			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-		.rlen	= 40,
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+			  "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+		.rlen	= 504,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 40 - 8, 8 },
+		.tap	= { 504 - 8, 8 },
 	},
 };
 
@@ -2645,14 +4814,130 @@ static struct cipher_testvec bf_ctr_enc_tv_template[] = {
 			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
 			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-		.ilen	= 40,
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+			  "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+		.ilen	= 504,
 		.result	= "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
 			  "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
 			  "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
 			  "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
-			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC",
-		.rlen	= 40,
+			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
+			  "\x3D\xA7\xE9\x0A\x5C\x70\x4D\xDE"
+			  "\x99\x38\x07\xCA\x1D\x21\xC1\x11"
+			  "\x97\xEB\x98\x75\xC4\x73\x45\x83"
+			  "\x46\x1C\x9C\x91\x87\xC1\xA0\x56"
+			  "\x98\xA1\x8B\xDB\x22\x76\xBD\x62"
+			  "\xA4\xBC\xE8\x86\xDA\xD2\x51\x13"
+			  "\x13\xD2\x96\x68\x69\x10\x67\x0C"
+			  "\xD0\x17\x25\x7C\xB2\xAE\x4F\x93"
+			  "\xA6\x82\x20\xCF\x0F\xA6\x47\x79"
+			  "\x88\x09\x40\x59\xBD\x12\x64\xB5"
+			  "\x19\x38\x0D\xFF\x86\xD9\x42\x20"
+			  "\x81\x0D\x96\x99\xAF\x22\x1F\x94"
+			  "\x5C\x6E\xEC\xEA\xA3\x39\xCB\x09"
+			  "\x43\x19\x7F\xD0\xBB\x10\xC2\x49"
+			  "\xF7\xE9\xF2\xEE\xBF\xF7\xF8\xB3"
+			  "\x0E\x1A\xF1\x8D\x70\x82\x0C\x04"
+			  "\xFD\x29\x1A\xAC\xC0\x92\x48\x34"
+			  "\x6A\xE3\x1D\x4F\xFC\x1C\x72\x6A"
+			  "\x57\xCB\xAD\xD0\x98\xAB\xB1\x01"
+			  "\x03\x6A\x45\xDD\x07\x71\x5F\x5B"
+			  "\xB5\x4A\xE4\xE5\xB9\xB9\xBC\xAC"
+			  "\x44\xF7\x41\xA4\x5F\x2E\xE9\x28"
+			  "\xE3\x05\xD2\x94\x78\x4C\x33\x1B"
+			  "\xBD\xC1\x6E\x51\xD9\xAD\xD9\x86"
+			  "\x15\x4A\x78\xAE\x7B\xAD\x3B\xBC"
+			  "\x2F\xE0\x0E\xC5\x7B\x54\x97\x5F"
+			  "\x60\x51\x14\x65\xF9\x91\xE9\xDA"
+			  "\x9A\xBC\xFC\x19\x29\x67\xAA\x63"
+			  "\x5E\xF2\x48\x88\xEB\x79\xE1\xE4"
+			  "\xF7\xF6\x4C\xA9\xE2\x8C\x3B\xE0"
+			  "\xED\x52\xAE\x90\x8F\x5B\x98\x34"
+			  "\x29\x94\x34\x7F\xF9\x6C\x1E\xB6"
+			  "\xA4\xE7\x2D\x06\x54\x9D\xC3\x02"
+			  "\xC1\x90\xA4\x72\x31\x6B\x24\x51"
+			  "\x0B\xB3\x7C\x63\x15\xBA\xAF\x5D"
+			  "\x41\xE0\x37\x6D\xBE\x41\x58\xDE"
+			  "\xF2\x07\x62\x99\xBE\xC1\x8C\x0F"
+			  "\x0F\x28\xFB\x8F\x0E\x1D\x91\xE2"
+			  "\xDA\x99\x5C\x49\xBA\x9C\xA8\x86"
+			  "\x82\x63\x11\xB3\x54\x49\x00\x08"
+			  "\x07\xF2\xE8\x1F\x34\x49\x61\xF4"
+			  "\x81\xE9\xF6\xA9\x5A\x28\x60\x1F"
+			  "\x66\x99\x08\x06\xF2\xE8\x2D\xD1"
+			  "\xD0\x67\xBA\x32\x1F\x02\x86\x7B"
+			  "\xFB\x79\x3D\xC5\xB1\x7F\x15\xAF"
+			  "\xD7\xBF\x31\x46\x22\x7F\xAE\x5B"
+			  "\x8B\x95\x47\xC2\xB1\x62\xA1\xCE"
+			  "\x52\xAC\x9C\x8B\xC2\x49\x7F\xBC"
+			  "\x9C\x89\xB8\xB6\xCA\xE3\x8F\xEA"
+			  "\xAC\xB4\x5D\xE4\x50\xDC\x3A\xB5"
+			  "\x91\x04\x94\x99\x03\x3B\x42\x6D"
+			  "\x9C\x4A\x02\xF5\xB5\x38\x98\xA8"
+			  "\x5C\x97\x2E\x4D\x79\x67\x71\xAF"
+			  "\xF0\x70\x77\xFF\x2D\xDA\xA0\x9E"
+			  "\x23\x8D\xD6\xA6\x68\x10\x78\x9A"
+			  "\x64\xBB\x15\xB8\x56\xCF\xEE\xE5"
+			  "\x32\x44\x96\x1C\xD8\xEB\x95\xD2"
+			  "\xF3\x71\xEF\xEB\x4E\xBB\x4D\x29",
+		.rlen	= 504,
 	}, { /* Generated with Crypto++ */
 		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
 			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -2665,18 +4950,132 @@ static struct cipher_testvec bf_ctr_enc_tv_template[] = {
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
 			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
 			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-			  "\x6D\x04\x9B",
-		.ilen	= 43,
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+			  "\x2B\xC2\x59\xF0\x64\xFB\x92",
+		.ilen	= 503,
 		.result	= "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
 			  "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
 			  "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
 			  "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
 			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
-			  "\x3D\xA7\xE9",
-		.rlen	= 43,
+			  "\x3D\xA7\xE9\x0A\x5C\x70\x4D\xDE"
+			  "\x99\x38\x07\xCA\x1D\x21\xC1\x11"
+			  "\x97\xEB\x98\x75\xC4\x73\x45\x83"
+			  "\x46\x1C\x9C\x91\x87\xC1\xA0\x56"
+			  "\x98\xA1\x8B\xDB\x22\x76\xBD\x62"
+			  "\xA4\xBC\xE8\x86\xDA\xD2\x51\x13"
+			  "\x13\xD2\x96\x68\x69\x10\x67\x0C"
+			  "\xD0\x17\x25\x7C\xB2\xAE\x4F\x93"
+			  "\xA6\x82\x20\xCF\x0F\xA6\x47\x79"
+			  "\x88\x09\x40\x59\xBD\x12\x64\xB5"
+			  "\x19\x38\x0D\xFF\x86\xD9\x42\x20"
+			  "\x81\x0D\x96\x99\xAF\x22\x1F\x94"
+			  "\x5C\x6E\xEC\xEA\xA3\x39\xCB\x09"
+			  "\x43\x19\x7F\xD0\xBB\x10\xC2\x49"
+			  "\xF7\xE9\xF2\xEE\xBF\xF7\xF8\xB3"
+			  "\x0E\x1A\xF1\x8D\x70\x82\x0C\x04"
+			  "\xFD\x29\x1A\xAC\xC0\x92\x48\x34"
+			  "\x6A\xE3\x1D\x4F\xFC\x1C\x72\x6A"
+			  "\x57\xCB\xAD\xD0\x98\xAB\xB1\x01"
+			  "\x03\x6A\x45\xDD\x07\x71\x5F\x5B"
+			  "\xB5\x4A\xE4\xE5\xB9\xB9\xBC\xAC"
+			  "\x44\xF7\x41\xA4\x5F\x2E\xE9\x28"
+			  "\xE3\x05\xD2\x94\x78\x4C\x33\x1B"
+			  "\xBD\xC1\x6E\x51\xD9\xAD\xD9\x86"
+			  "\x15\x4A\x78\xAE\x7B\xAD\x3B\xBC"
+			  "\x2F\xE0\x0E\xC5\x7B\x54\x97\x5F"
+			  "\x60\x51\x14\x65\xF9\x91\xE9\xDA"
+			  "\x9A\xBC\xFC\x19\x29\x67\xAA\x63"
+			  "\x5E\xF2\x48\x88\xEB\x79\xE1\xE4"
+			  "\xF7\xF6\x4C\xA9\xE2\x8C\x3B\xE0"
+			  "\xED\x52\xAE\x90\x8F\x5B\x98\x34"
+			  "\x29\x94\x34\x7F\xF9\x6C\x1E\xB6"
+			  "\xA4\xE7\x2D\x06\x54\x9D\xC3\x02"
+			  "\xC1\x90\xA4\x72\x31\x6B\x24\x51"
+			  "\x0B\xB3\x7C\x63\x15\xBA\xAF\x5D"
+			  "\x41\xE0\x37\x6D\xBE\x41\x58\xDE"
+			  "\xF2\x07\x62\x99\xBE\xC1\x8C\x0F"
+			  "\x0F\x28\xFB\x8F\x0E\x1D\x91\xE2"
+			  "\xDA\x99\x5C\x49\xBA\x9C\xA8\x86"
+			  "\x82\x63\x11\xB3\x54\x49\x00\x08"
+			  "\x07\xF2\xE8\x1F\x34\x49\x61\xF4"
+			  "\x81\xE9\xF6\xA9\x5A\x28\x60\x1F"
+			  "\x66\x99\x08\x06\xF2\xE8\x2D\xD1"
+			  "\xD0\x67\xBA\x32\x1F\x02\x86\x7B"
+			  "\xFB\x79\x3D\xC5\xB1\x7F\x15\xAF"
+			  "\xD7\xBF\x31\x46\x22\x7F\xAE\x5B"
+			  "\x8B\x95\x47\xC2\xB1\x62\xA1\xCE"
+			  "\x52\xAC\x9C\x8B\xC2\x49\x7F\xBC"
+			  "\x9C\x89\xB8\xB6\xCA\xE3\x8F\xEA"
+			  "\xAC\xB4\x5D\xE4\x50\xDC\x3A\xB5"
+			  "\x91\x04\x94\x99\x03\x3B\x42\x6D"
+			  "\x9C\x4A\x02\xF5\xB5\x38\x98\xA8"
+			  "\x5C\x97\x2E\x4D\x79\x67\x71\xAF"
+			  "\xF0\x70\x77\xFF\x2D\xDA\xA0\x9E"
+			  "\x23\x8D\xD6\xA6\x68\x10\x78\x9A"
+			  "\x64\xBB\x15\xB8\x56\xCF\xEE\xE5"
+			  "\x32\x44\x96\x1C\xD8\xEB\x95\xD2"
+			  "\xF3\x71\xEF\xEB\x4E\xBB\x4D",
+		.rlen	= 503,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 43 - 8, 8 },
+		.tap	= { 503 - 8, 8 },
 	}, { /* Generated with Crypto++ */
 		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
 			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -2827,14 +5226,130 @@ static struct cipher_testvec bf_ctr_dec_tv_template[] = {
 			  "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
 			  "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
 			  "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
-			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC",
-		.ilen	= 40,
+			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
+			  "\x3D\xA7\xE9\x0A\x5C\x70\x4D\xDE"
+			  "\x99\x38\x07\xCA\x1D\x21\xC1\x11"
+			  "\x97\xEB\x98\x75\xC4\x73\x45\x83"
+			  "\x46\x1C\x9C\x91\x87\xC1\xA0\x56"
+			  "\x98\xA1\x8B\xDB\x22\x76\xBD\x62"
+			  "\xA4\xBC\xE8\x86\xDA\xD2\x51\x13"
+			  "\x13\xD2\x96\x68\x69\x10\x67\x0C"
+			  "\xD0\x17\x25\x7C\xB2\xAE\x4F\x93"
+			  "\xA6\x82\x20\xCF\x0F\xA6\x47\x79"
+			  "\x88\x09\x40\x59\xBD\x12\x64\xB5"
+			  "\x19\x38\x0D\xFF\x86\xD9\x42\x20"
+			  "\x81\x0D\x96\x99\xAF\x22\x1F\x94"
+			  "\x5C\x6E\xEC\xEA\xA3\x39\xCB\x09"
+			  "\x43\x19\x7F\xD0\xBB\x10\xC2\x49"
+			  "\xF7\xE9\xF2\xEE\xBF\xF7\xF8\xB3"
+			  "\x0E\x1A\xF1\x8D\x70\x82\x0C\x04"
+			  "\xFD\x29\x1A\xAC\xC0\x92\x48\x34"
+			  "\x6A\xE3\x1D\x4F\xFC\x1C\x72\x6A"
+			  "\x57\xCB\xAD\xD0\x98\xAB\xB1\x01"
+			  "\x03\x6A\x45\xDD\x07\x71\x5F\x5B"
+			  "\xB5\x4A\xE4\xE5\xB9\xB9\xBC\xAC"
+			  "\x44\xF7\x41\xA4\x5F\x2E\xE9\x28"
+			  "\xE3\x05\xD2\x94\x78\x4C\x33\x1B"
+			  "\xBD\xC1\x6E\x51\xD9\xAD\xD9\x86"
+			  "\x15\x4A\x78\xAE\x7B\xAD\x3B\xBC"
+			  "\x2F\xE0\x0E\xC5\x7B\x54\x97\x5F"
+			  "\x60\x51\x14\x65\xF9\x91\xE9\xDA"
+			  "\x9A\xBC\xFC\x19\x29\x67\xAA\x63"
+			  "\x5E\xF2\x48\x88\xEB\x79\xE1\xE4"
+			  "\xF7\xF6\x4C\xA9\xE2\x8C\x3B\xE0"
+			  "\xED\x52\xAE\x90\x8F\x5B\x98\x34"
+			  "\x29\x94\x34\x7F\xF9\x6C\x1E\xB6"
+			  "\xA4\xE7\x2D\x06\x54\x9D\xC3\x02"
+			  "\xC1\x90\xA4\x72\x31\x6B\x24\x51"
+			  "\x0B\xB3\x7C\x63\x15\xBA\xAF\x5D"
+			  "\x41\xE0\x37\x6D\xBE\x41\x58\xDE"
+			  "\xF2\x07\x62\x99\xBE\xC1\x8C\x0F"
+			  "\x0F\x28\xFB\x8F\x0E\x1D\x91\xE2"
+			  "\xDA\x99\x5C\x49\xBA\x9C\xA8\x86"
+			  "\x82\x63\x11\xB3\x54\x49\x00\x08"
+			  "\x07\xF2\xE8\x1F\x34\x49\x61\xF4"
+			  "\x81\xE9\xF6\xA9\x5A\x28\x60\x1F"
+			  "\x66\x99\x08\x06\xF2\xE8\x2D\xD1"
+			  "\xD0\x67\xBA\x32\x1F\x02\x86\x7B"
+			  "\xFB\x79\x3D\xC5\xB1\x7F\x15\xAF"
+			  "\xD7\xBF\x31\x46\x22\x7F\xAE\x5B"
+			  "\x8B\x95\x47\xC2\xB1\x62\xA1\xCE"
+			  "\x52\xAC\x9C\x8B\xC2\x49\x7F\xBC"
+			  "\x9C\x89\xB8\xB6\xCA\xE3\x8F\xEA"
+			  "\xAC\xB4\x5D\xE4\x50\xDC\x3A\xB5"
+			  "\x91\x04\x94\x99\x03\x3B\x42\x6D"
+			  "\x9C\x4A\x02\xF5\xB5\x38\x98\xA8"
+			  "\x5C\x97\x2E\x4D\x79\x67\x71\xAF"
+			  "\xF0\x70\x77\xFF\x2D\xDA\xA0\x9E"
+			  "\x23\x8D\xD6\xA6\x68\x10\x78\x9A"
+			  "\x64\xBB\x15\xB8\x56\xCF\xEE\xE5"
+			  "\x32\x44\x96\x1C\xD8\xEB\x95\xD2"
+			  "\xF3\x71\xEF\xEB\x4E\xBB\x4D\x29",
+		.ilen	= 504,
 		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
 			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
 			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
-			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
-		.rlen	= 40,
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+			  "\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
+		.rlen	= 504,
 	}, { /* Generated with Crypto++ */
 		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
 			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -2847,18 +5362,132 @@ static struct cipher_testvec bf_ctr_dec_tv_template[] = {
 			  "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
 			  "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
 			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
-			  "\x3D\xA7\xE9",
-		.ilen	= 43,
+			  "\x3D\xA7\xE9\x0A\x5C\x70\x4D\xDE"
+			  "\x99\x38\x07\xCA\x1D\x21\xC1\x11"
+			  "\x97\xEB\x98\x75\xC4\x73\x45\x83"
+			  "\x46\x1C\x9C\x91\x87\xC1\xA0\x56"
+			  "\x98\xA1\x8B\xDB\x22\x76\xBD\x62"
+			  "\xA4\xBC\xE8\x86\xDA\xD2\x51\x13"
+			  "\x13\xD2\x96\x68\x69\x10\x67\x0C"
+			  "\xD0\x17\x25\x7C\xB2\xAE\x4F\x93"
+			  "\xA6\x82\x20\xCF\x0F\xA6\x47\x79"
+			  "\x88\x09\x40\x59\xBD\x12\x64\xB5"
+			  "\x19\x38\x0D\xFF\x86\xD9\x42\x20"
+			  "\x81\x0D\x96\x99\xAF\x22\x1F\x94"
+			  "\x5C\x6E\xEC\xEA\xA3\x39\xCB\x09"
+			  "\x43\x19\x7F\xD0\xBB\x10\xC2\x49"
+			  "\xF7\xE9\xF2\xEE\xBF\xF7\xF8\xB3"
+			  "\x0E\x1A\xF1\x8D\x70\x82\x0C\x04"
+			  "\xFD\x29\x1A\xAC\xC0\x92\x48\x34"
+			  "\x6A\xE3\x1D\x4F\xFC\x1C\x72\x6A"
+			  "\x57\xCB\xAD\xD0\x98\xAB\xB1\x01"
+			  "\x03\x6A\x45\xDD\x07\x71\x5F\x5B"
+			  "\xB5\x4A\xE4\xE5\xB9\xB9\xBC\xAC"
+			  "\x44\xF7\x41\xA4\x5F\x2E\xE9\x28"
+			  "\xE3\x05\xD2\x94\x78\x4C\x33\x1B"
+			  "\xBD\xC1\x6E\x51\xD9\xAD\xD9\x86"
+			  "\x15\x4A\x78\xAE\x7B\xAD\x3B\xBC"
+			  "\x2F\xE0\x0E\xC5\x7B\x54\x97\x5F"
+			  "\x60\x51\x14\x65\xF9\x91\xE9\xDA"
+			  "\x9A\xBC\xFC\x19\x29\x67\xAA\x63"
+			  "\x5E\xF2\x48\x88\xEB\x79\xE1\xE4"
+			  "\xF7\xF6\x4C\xA9\xE2\x8C\x3B\xE0"
+			  "\xED\x52\xAE\x90\x8F\x5B\x98\x34"
+			  "\x29\x94\x34\x7F\xF9\x6C\x1E\xB6"
+			  "\xA4\xE7\x2D\x06\x54\x9D\xC3\x02"
+			  "\xC1\x90\xA4\x72\x31\x6B\x24\x51"
+			  "\x0B\xB3\x7C\x63\x15\xBA\xAF\x5D"
+			  "\x41\xE0\x37\x6D\xBE\x41\x58\xDE"
+			  "\xF2\x07\x62\x99\xBE\xC1\x8C\x0F"
+			  "\x0F\x28\xFB\x8F\x0E\x1D\x91\xE2"
+			  "\xDA\x99\x5C\x49\xBA\x9C\xA8\x86"
+			  "\x82\x63\x11\xB3\x54\x49\x00\x08"
+			  "\x07\xF2\xE8\x1F\x34\x49\x61\xF4"
+			  "\x81\xE9\xF6\xA9\x5A\x28\x60\x1F"
+			  "\x66\x99\x08\x06\xF2\xE8\x2D\xD1"
+			  "\xD0\x67\xBA\x32\x1F\x02\x86\x7B"
+			  "\xFB\x79\x3D\xC5\xB1\x7F\x15\xAF"
+			  "\xD7\xBF\x31\x46\x22\x7F\xAE\x5B"
+			  "\x8B\x95\x47\xC2\xB1\x62\xA1\xCE"
+			  "\x52\xAC\x9C\x8B\xC2\x49\x7F\xBC"
+			  "\x9C\x89\xB8\xB6\xCA\xE3\x8F\xEA"
+			  "\xAC\xB4\x5D\xE4\x50\xDC\x3A\xB5"
+			  "\x91\x04\x94\x99\x03\x3B\x42\x6D"
+			  "\x9C\x4A\x02\xF5\xB5\x38\x98\xA8"
+			  "\x5C\x97\x2E\x4D\x79\x67\x71\xAF"
+			  "\xF0\x70\x77\xFF\x2D\xDA\xA0\x9E"
+			  "\x23\x8D\xD6\xA6\x68\x10\x78\x9A"
+			  "\x64\xBB\x15\xB8\x56\xCF\xEE\xE5"
+			  "\x32\x44\x96\x1C\xD8\xEB\x95\xD2"
+			  "\xF3\x71\xEF\xEB\x4E\xBB\x4D",
+		.ilen	= 503,
 		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
 			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
 			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
 			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-			  "\x6D\x04\x9B",
-		.rlen	= 43,
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+			  "\x2B\xC2\x59\xF0\x64\xFB\x92",
+		.rlen	= 503,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 43 - 8, 8 },
+		.tap	= { 503 - 8, 8 },
 	}, { /* Generated with Crypto++ */
 		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
 			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -5808,8 +8437,52 @@ static struct cipher_testvec serpent_enc_tv_template[] = {
 			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
 			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
 			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-		.ilen	= 144,
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.ilen	= 496,
 		.result	= "\xFB\xB0\x5D\xDE\xC0\xFE\xFC\xEB"
 			  "\xB1\x80\x10\x43\xDE\x62\x70\xBD"
 			  "\xFA\x8A\x93\xEA\x6B\xF7\xC5\xD7"
@@ -5827,11 +8500,55 @@ static struct cipher_testvec serpent_enc_tv_template[] = {
 			  "\x9D\x74\x2B\x77\x53\x2D\xE5\xBD"
 			  "\x69\xDA\x7A\x01\xF5\x6A\x70\x39"
 			  "\x30\xD4\x2C\xF2\x8E\x06\x4B\x39"
-			  "\xB3\x12\x1D\xB3\x17\x46\xE6\xD6",
-		.rlen	= 144,
+			  "\xB3\x12\x1D\xB3\x17\x46\xE6\xD6"
+			  "\xB6\x31\x36\x34\x38\x3C\x1D\x69"
+			  "\x9F\x47\x28\x9A\x1D\x96\x70\x54"
+			  "\x8E\x88\xCB\xE0\xF5\x6A\xAE\x0A"
+			  "\x3C\xD5\x93\x1C\x21\xC9\x14\x3A"
+			  "\x23\x9C\x9B\x79\xC7\x75\xC8\x39"
+			  "\xA6\xAC\x65\x9A\x99\x37\xAF\x6D"
+			  "\xBD\xB5\x32\xFD\xD8\x9C\x95\x7B"
+			  "\xC6\x6A\x80\x64\xEA\xEF\x6D\x3F"
+			  "\xA9\xFE\x5B\x16\xA3\xCF\x32\xC8"
+			  "\xEF\x50\x22\x20\x93\x30\xBE\xE2"
+			  "\x38\x05\x65\xAF\xBA\xB6\xE4\x72"
+			  "\xA9\xEE\x05\x42\x88\xBD\x9D\x49"
+			  "\xAD\x93\xCA\x4D\x45\x11\x43\x4D"
+			  "\xB8\xF5\x74\x2B\x48\xE7\x21\xE4"
+			  "\x4E\x3A\x4C\xDE\x65\x7A\x5A\xAD"
+			  "\x86\xE6\x23\xEC\x6B\xA7\x17\xE6"
+			  "\xF6\xA1\xAC\x29\xAE\xF9\x9B\x69"
+			  "\x73\x65\x65\x51\xD6\x0B\x4E\x8C"
+			  "\x17\x15\x9D\xB0\xCF\xB2\x42\x2B"
+			  "\x51\xC3\x03\xE8\xB7\x7D\x2D\x39"
+			  "\xE8\x10\x93\x16\xC8\x68\x4C\x60"
+			  "\x87\x70\x14\xD0\x01\x57\xCB\x42"
+			  "\x13\x59\xB1\x7F\x12\x4F\xBB\xC7"
+			  "\xBD\x2B\xD4\xA9\x12\x26\x4F\xDE"
+			  "\xFD\x72\xEC\xD7\x6F\x97\x14\x90"
+			  "\x0E\x37\x13\xE6\x67\x1D\xE5\xFE"
+			  "\x9E\x18\x3C\x8F\x3A\x3F\x59\x9B"
+			  "\x71\x80\x05\x35\x3F\x40\x0B\x21"
+			  "\x76\xE5\xEF\x42\x6C\xDB\x31\x05"
+			  "\x5F\x05\xCF\x14\xE3\xF0\x61\xA2"
+			  "\x49\x03\x5E\x77\x2E\x20\xBA\xA1"
+			  "\xAF\x46\x51\xC0\x2B\xC4\x64\x1E"
+			  "\x65\xCC\x51\x58\x0A\xDF\xF0\x5F"
+			  "\x75\x9F\x48\xCD\x81\xEC\xC3\xF6"
+			  "\xED\xC9\x4B\x7B\x4E\x26\x23\xE1"
+			  "\xBB\xE9\x83\x0B\xCF\xE4\xDE\x00"
+			  "\x48\xFF\xBF\x6C\xB4\x72\x16\xEF"
+			  "\xC7\x46\xEE\x48\x8C\xB8\xAF\x45"
+			  "\x91\x76\xE7\x6E\x65\x3D\x15\x86"
+			  "\x10\xF8\xDB\x66\x97\x7C\x43\x4D"
+			  "\x79\x12\x4E\xCE\x06\xD1\xD1\x6A"
+			  "\x34\xC1\xC9\xF2\x28\x4A\xCD\x02"
+			  "\x75\x55\x9B\xFF\x36\x73\xAB\x7C"
+			  "\xF4\x46\x2E\xEB\xAC\xF3\xD2\xB7",
+		.rlen	= 496,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 144 - 16, 16 },
+		.tap	= { 496 - 16, 16 },
 	},
 };
 
@@ -5946,8 +8663,52 @@ static struct cipher_testvec serpent_dec_tv_template[] = {
 			  "\x9D\x74\x2B\x77\x53\x2D\xE5\xBD"
 			  "\x69\xDA\x7A\x01\xF5\x6A\x70\x39"
 			  "\x30\xD4\x2C\xF2\x8E\x06\x4B\x39"
-			  "\xB3\x12\x1D\xB3\x17\x46\xE6\xD6",
-		.ilen	= 144,
+			  "\xB3\x12\x1D\xB3\x17\x46\xE6\xD6"
+			  "\xB6\x31\x36\x34\x38\x3C\x1D\x69"
+			  "\x9F\x47\x28\x9A\x1D\x96\x70\x54"
+			  "\x8E\x88\xCB\xE0\xF5\x6A\xAE\x0A"
+			  "\x3C\xD5\x93\x1C\x21\xC9\x14\x3A"
+			  "\x23\x9C\x9B\x79\xC7\x75\xC8\x39"
+			  "\xA6\xAC\x65\x9A\x99\x37\xAF\x6D"
+			  "\xBD\xB5\x32\xFD\xD8\x9C\x95\x7B"
+			  "\xC6\x6A\x80\x64\xEA\xEF\x6D\x3F"
+			  "\xA9\xFE\x5B\x16\xA3\xCF\x32\xC8"
+			  "\xEF\x50\x22\x20\x93\x30\xBE\xE2"
+			  "\x38\x05\x65\xAF\xBA\xB6\xE4\x72"
+			  "\xA9\xEE\x05\x42\x88\xBD\x9D\x49"
+			  "\xAD\x93\xCA\x4D\x45\x11\x43\x4D"
+			  "\xB8\xF5\x74\x2B\x48\xE7\x21\xE4"
+			  "\x4E\x3A\x4C\xDE\x65\x7A\x5A\xAD"
+			  "\x86\xE6\x23\xEC\x6B\xA7\x17\xE6"
+			  "\xF6\xA1\xAC\x29\xAE\xF9\x9B\x69"
+			  "\x73\x65\x65\x51\xD6\x0B\x4E\x8C"
+			  "\x17\x15\x9D\xB0\xCF\xB2\x42\x2B"
+			  "\x51\xC3\x03\xE8\xB7\x7D\x2D\x39"
+			  "\xE8\x10\x93\x16\xC8\x68\x4C\x60"
+			  "\x87\x70\x14\xD0\x01\x57\xCB\x42"
+			  "\x13\x59\xB1\x7F\x12\x4F\xBB\xC7"
+			  "\xBD\x2B\xD4\xA9\x12\x26\x4F\xDE"
+			  "\xFD\x72\xEC\xD7\x6F\x97\x14\x90"
+			  "\x0E\x37\x13\xE6\x67\x1D\xE5\xFE"
+			  "\x9E\x18\x3C\x8F\x3A\x3F\x59\x9B"
+			  "\x71\x80\x05\x35\x3F\x40\x0B\x21"
+			  "\x76\xE5\xEF\x42\x6C\xDB\x31\x05"
+			  "\x5F\x05\xCF\x14\xE3\xF0\x61\xA2"
+			  "\x49\x03\x5E\x77\x2E\x20\xBA\xA1"
+			  "\xAF\x46\x51\xC0\x2B\xC4\x64\x1E"
+			  "\x65\xCC\x51\x58\x0A\xDF\xF0\x5F"
+			  "\x75\x9F\x48\xCD\x81\xEC\xC3\xF6"
+			  "\xED\xC9\x4B\x7B\x4E\x26\x23\xE1"
+			  "\xBB\xE9\x83\x0B\xCF\xE4\xDE\x00"
+			  "\x48\xFF\xBF\x6C\xB4\x72\x16\xEF"
+			  "\xC7\x46\xEE\x48\x8C\xB8\xAF\x45"
+			  "\x91\x76\xE7\x6E\x65\x3D\x15\x86"
+			  "\x10\xF8\xDB\x66\x97\x7C\x43\x4D"
+			  "\x79\x12\x4E\xCE\x06\xD1\xD1\x6A"
+			  "\x34\xC1\xC9\xF2\x28\x4A\xCD\x02"
+			  "\x75\x55\x9B\xFF\x36\x73\xAB\x7C"
+			  "\xF4\x46\x2E\xEB\xAC\xF3\xD2\xB7",
+		.ilen	= 496,
 		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
 			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
@@ -5965,11 +8726,55 @@ static struct cipher_testvec serpent_dec_tv_template[] = {
 			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
 			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
 			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-		.rlen	= 144,
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.rlen	= 496,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 144 - 16, 16 },
+		.tap	= { 496 - 16, 16 },
 	},
 };
 
@@ -6040,8 +8845,52 @@ static struct cipher_testvec serpent_cbc_enc_tv_template[] = {
 			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
 			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
 			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-		.ilen	= 144,
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.ilen	= 496,
 		.result	= "\x80\xCF\x11\x41\x1A\xB9\x4B\x9C"
 			  "\xFF\xB7\x6C\xEA\xF0\xAF\x77\x6E"
 			  "\x71\x75\x95\x9D\x4E\x1C\xCF\xAD"
@@ -6059,11 +8908,55 @@ static struct cipher_testvec serpent_cbc_enc_tv_template[] = {
 			  "\x15\x26\xE1\xDB\xA4\x3D\x74\xD2"
 			  "\x41\x1E\x3F\xA9\xC6\x7D\x2A\xAB"
 			  "\x27\xDF\x89\x1D\x86\x3E\xF7\x5A"
-			  "\xF6\xE3\x0F\xC7\x6B\x4C\x96\x7C",
-		.rlen	= 144,
+			  "\xF6\xE3\x0F\xC7\x6B\x4C\x96\x7C"
+			  "\x2D\x12\xA5\x05\x92\xCB\xD7\x4A"
+			  "\x4D\x1E\x88\x21\xE1\x63\xB4\xFC"
+			  "\x4A\xF2\xCD\x35\xB9\xD7\x70\x97"
+			  "\x5A\x5E\x7E\x96\x52\x20\xDC\x25"
+			  "\xE9\x6B\x36\xB4\xE0\x98\x85\x2C"
+			  "\x3C\xD2\xF7\x78\x8A\x73\x26\x9B"
+			  "\xAF\x0B\x11\xE8\x4D\x67\x23\xE9"
+			  "\x77\xDF\x58\xF6\x6F\x9E\xA4\xC5"
+			  "\x10\xA1\x82\x0E\x80\xA0\x8F\x4B"
+			  "\xA1\xC0\x12\x54\x4E\xC9\x20\x92"
+			  "\x11\x00\x10\x4E\xB3\x7C\xCA\x63"
+			  "\xE5\x3F\xD3\x41\x37\xCD\x74\xB7"
+			  "\xA5\x7C\x61\xB8\x0B\x7A\x7F\x4D"
+			  "\xFE\x96\x7D\x1B\xBE\x60\x37\xB7"
+			  "\x81\x92\x66\x67\x15\x1E\x39\x98"
+			  "\x52\xC0\xF4\x69\xC0\x99\x4F\x5A"
+			  "\x2E\x32\xAD\x7C\x8B\xE9\xAD\x05"
+			  "\x55\xF9\x0A\x1F\x97\x5C\xFA\x2B"
+			  "\xF4\x99\x76\x3A\x6E\x4D\xE1\x4C"
+			  "\x14\x4E\x6F\x87\xEE\x1A\x85\xA3"
+			  "\x96\xC6\x66\x49\xDA\x0D\x71\xAC"
+			  "\x04\x05\x46\xD3\x90\x0F\x64\x64"
+			  "\x01\x66\x2C\x62\x5D\x34\xD1\xCB"
+			  "\x3A\x24\xCE\x95\xEF\xAE\x2C\x97"
+			  "\x0E\x0C\x1D\x36\x49\xEB\xE9\x3D"
+			  "\x62\xA6\x19\x28\x9E\x26\xB4\x3F"
+			  "\xD7\x55\x42\x3C\xCD\x72\x0A\xF0"
+			  "\x7D\xE9\x95\x45\x86\xED\xB1\xE0"
+			  "\x8D\xE9\xC5\x86\x13\x24\x28\x7D"
+			  "\x74\xEF\xCA\x50\x12\x7E\x64\x8F"
+			  "\x1B\xF5\x5B\xFE\xE2\xAC\xFA\xE7"
+			  "\xBD\x38\x8C\x11\x20\xEF\xB1\xAA"
+			  "\x7B\xE5\xE5\x78\xAD\x9D\x2D\xA2"
+			  "\x8E\xDD\x48\xB3\xEF\x18\x92\x7E"
+			  "\xE6\x75\x0D\x54\x64\x11\xA3\x3A"
+			  "\xDB\x97\x0F\xD3\xDF\x07\xD3\x7E"
+			  "\x1E\xD1\x87\xE4\x74\xBB\x46\xF4"
+			  "\xBA\x23\x2D\x8D\x29\x07\x12\xCF"
+			  "\x34\xCD\x72\x7F\x01\x30\xE7\xA0"
+			  "\xF8\xDD\xA8\x08\xF0\xBC\xB1\xA2"
+			  "\xCC\xE1\x6B\x5F\xBE\xEA\xF1\xE4"
+			  "\x02\xC4\xAF\xFA\xAD\x31\xF4\xBF"
+			  "\xFC\x66\xAA\x37\xF2\x37\x39\x6B"
+			  "\xBC\x08\x3A\xA2\x29\xB3\xDF\xD1",
+		.rlen	= 496,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 144 - 16, 16 },
+		.tap	= { 496 - 16, 16 },
 	},
 };
 
@@ -6093,8 +8986,52 @@ static struct cipher_testvec serpent_cbc_dec_tv_template[] = {
 			  "\x15\x26\xE1\xDB\xA4\x3D\x74\xD2"
 			  "\x41\x1E\x3F\xA9\xC6\x7D\x2A\xAB"
 			  "\x27\xDF\x89\x1D\x86\x3E\xF7\x5A"
-			  "\xF6\xE3\x0F\xC7\x6B\x4C\x96\x7C",
-		.ilen	= 144,
+			  "\xF6\xE3\x0F\xC7\x6B\x4C\x96\x7C"
+			  "\x2D\x12\xA5\x05\x92\xCB\xD7\x4A"
+			  "\x4D\x1E\x88\x21\xE1\x63\xB4\xFC"
+			  "\x4A\xF2\xCD\x35\xB9\xD7\x70\x97"
+			  "\x5A\x5E\x7E\x96\x52\x20\xDC\x25"
+			  "\xE9\x6B\x36\xB4\xE0\x98\x85\x2C"
+			  "\x3C\xD2\xF7\x78\x8A\x73\x26\x9B"
+			  "\xAF\x0B\x11\xE8\x4D\x67\x23\xE9"
+			  "\x77\xDF\x58\xF6\x6F\x9E\xA4\xC5"
+			  "\x10\xA1\x82\x0E\x80\xA0\x8F\x4B"
+			  "\xA1\xC0\x12\x54\x4E\xC9\x20\x92"
+			  "\x11\x00\x10\x4E\xB3\x7C\xCA\x63"
+			  "\xE5\x3F\xD3\x41\x37\xCD\x74\xB7"
+			  "\xA5\x7C\x61\xB8\x0B\x7A\x7F\x4D"
+			  "\xFE\x96\x7D\x1B\xBE\x60\x37\xB7"
+			  "\x81\x92\x66\x67\x15\x1E\x39\x98"
+			  "\x52\xC0\xF4\x69\xC0\x99\x4F\x5A"
+			  "\x2E\x32\xAD\x7C\x8B\xE9\xAD\x05"
+			  "\x55\xF9\x0A\x1F\x97\x5C\xFA\x2B"
+			  "\xF4\x99\x76\x3A\x6E\x4D\xE1\x4C"
+			  "\x14\x4E\x6F\x87\xEE\x1A\x85\xA3"
+			  "\x96\xC6\x66\x49\xDA\x0D\x71\xAC"
+			  "\x04\x05\x46\xD3\x90\x0F\x64\x64"
+			  "\x01\x66\x2C\x62\x5D\x34\xD1\xCB"
+			  "\x3A\x24\xCE\x95\xEF\xAE\x2C\x97"
+			  "\x0E\x0C\x1D\x36\x49\xEB\xE9\x3D"
+			  "\x62\xA6\x19\x28\x9E\x26\xB4\x3F"
+			  "\xD7\x55\x42\x3C\xCD\x72\x0A\xF0"
+			  "\x7D\xE9\x95\x45\x86\xED\xB1\xE0"
+			  "\x8D\xE9\xC5\x86\x13\x24\x28\x7D"
+			  "\x74\xEF\xCA\x50\x12\x7E\x64\x8F"
+			  "\x1B\xF5\x5B\xFE\xE2\xAC\xFA\xE7"
+			  "\xBD\x38\x8C\x11\x20\xEF\xB1\xAA"
+			  "\x7B\xE5\xE5\x78\xAD\x9D\x2D\xA2"
+			  "\x8E\xDD\x48\xB3\xEF\x18\x92\x7E"
+			  "\xE6\x75\x0D\x54\x64\x11\xA3\x3A"
+			  "\xDB\x97\x0F\xD3\xDF\x07\xD3\x7E"
+			  "\x1E\xD1\x87\xE4\x74\xBB\x46\xF4"
+			  "\xBA\x23\x2D\x8D\x29\x07\x12\xCF"
+			  "\x34\xCD\x72\x7F\x01\x30\xE7\xA0"
+			  "\xF8\xDD\xA8\x08\xF0\xBC\xB1\xA2"
+			  "\xCC\xE1\x6B\x5F\xBE\xEA\xF1\xE4"
+			  "\x02\xC4\xAF\xFA\xAD\x31\xF4\xBF"
+			  "\xFC\x66\xAA\x37\xF2\x37\x39\x6B"
+			  "\xBC\x08\x3A\xA2\x29\xB3\xDF\xD1",
+		.ilen	= 496,
 		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
 			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
@@ -6112,11 +9049,55 @@ static struct cipher_testvec serpent_cbc_dec_tv_template[] = {
 			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
 			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
 			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-		.rlen	= 144,
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.rlen	= 496,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 144 - 16, 16 },
+		.tap	= { 496 - 16, 16 },
 	},
 };
 
@@ -6146,8 +9127,52 @@ static struct cipher_testvec serpent_ctr_enc_tv_template[] = {
 			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
 			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
 			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-		.ilen	= 144,
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.ilen	= 496,
 		.result	= "\x84\x68\xEC\xF2\x1C\x88\x20\xCA"
 			  "\x37\x69\xE3\x3A\x22\x85\x48\x46"
 			  "\x70\xAA\x25\xB4\xCD\x8B\x04\x4E"
@@ -6165,8 +9190,52 @@ static struct cipher_testvec serpent_ctr_enc_tv_template[] = {
 			  "\xBA\x58\x2A\x1C\xDF\xC2\x3A\xA5"
 			  "\x7C\xB5\x12\x89\xED\xBF\xB6\x09"
 			  "\x13\x4F\x7D\x61\x3C\x5C\x27\xFC"
-			  "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9",
-		.rlen	= 144,
+			  "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9"
+			  "\xE6\xD0\x97\x81\xDE\xD1\xFB\x8A"
+			  "\x30\xDB\xA3\x5D\xEC\x25\x0B\x86"
+			  "\x71\xC8\xA7\x67\xE8\xBC\x7D\x4C"
+			  "\xAE\x82\xD3\x73\x31\x09\xCB\xB3"
+			  "\x4D\xD4\xC0\x8A\x2B\xFA\xA6\x55"
+			  "\x39\x0A\xBC\x6E\x75\xAB\xC2\xE2"
+			  "\x8A\xF2\x26\xCD\x63\x38\x35\xF7"
+			  "\xAE\x12\x83\xCD\x8A\x9E\x7E\x4C"
+			  "\xFE\x4D\xD7\xCE\x5C\x6E\x4C\xAF"
+			  "\xE3\xCD\x76\xA7\x87\xA1\x54\x7C"
+			  "\xEC\x32\xC7\x83\x2A\xFF\xF8\xEA"
+			  "\x87\xB2\x47\xA3\x9D\xC2\x9C\xA2"
+			  "\xB7\x2C\x7C\x1A\x24\xCB\x88\x61"
+			  "\xFF\xA7\x1A\x16\x01\xDD\x4B\xFC"
+			  "\x2E\xE0\x48\x67\x09\x42\xCC\x91"
+			  "\xBE\x20\x38\xC0\x5E\x3B\x95\x00"
+			  "\xA1\x96\x66\x0B\x8A\xE9\x9E\xF7"
+			  "\x6B\x34\x0A\x51\xC0\x3B\xEB\x71"
+			  "\x07\x97\x38\x4B\x5C\x56\x98\x67"
+			  "\x78\x9C\xD0\x0E\x2B\xB5\x67\x90"
+			  "\x75\xF8\xFE\x6D\x4E\x85\xCC\x0D"
+			  "\x18\x06\x15\x9D\x5A\x10\x13\x37"
+			  "\xA3\xD6\x68\xA2\xDF\x7E\xC7\x12"
+			  "\xC9\x0D\x4D\x91\xB0\x2A\x55\xFF"
+			  "\x6F\x73\x13\xDF\x28\xB5\x2A\x2C"
+			  "\xE4\xFC\x20\xD9\xF1\x7A\x82\xB1"
+			  "\xCB\x57\xB6\x3D\x8C\xF4\x8E\x27"
+			  "\x37\xDC\x35\xF3\x79\x01\x53\xA4"
+			  "\x7B\x37\xDE\x7C\x04\xAE\x50\xDB"
+			  "\x9B\x1E\x8C\x07\xA7\x52\x49\x50"
+			  "\x34\x25\x65\xDD\xA9\x8F\x7E\xBD"
+			  "\x7A\xC9\x36\xAE\xDE\x21\x48\x64"
+			  "\xC2\x02\xBA\xBE\x11\x1E\x3D\x9C"
+			  "\x98\x52\xCC\x04\xBD\x5E\x61\x26"
+			  "\x10\xD3\x21\xD9\x6E\x25\x98\x77"
+			  "\x8E\x98\x63\xF6\xF6\x52\xFB\x13"
+			  "\xAA\x30\xF2\xB9\xA4\x43\x53\x39"
+			  "\x1C\x97\x07\x7E\x6B\xFF\x3D\x43"
+			  "\xA6\x71\x6B\x66\x8F\x58\x3F\x71"
+			  "\x90\x47\x40\x92\xE6\x69\xD1\x96"
+			  "\x34\xB3\x3B\xE5\x43\xE4\xD5\x56"
+			  "\xB2\xE6\x7E\x86\x7A\x12\x17\x5B"
+			  "\x30\xF3\x9B\x0D\xFA\x57\xE4\x50"
+			  "\x40\x53\x77\x8C\x15\xF8\x8D\x13",
+		.rlen	= 496,
 	}, { /* Generated with Crypto++ */
 		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
 			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -6193,8 +9262,52 @@ static struct cipher_testvec serpent_ctr_enc_tv_template[] = {
 			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
 			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
 			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
-			  "\xF1\x65\xFC",
-		.ilen	= 147,
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+			  "\x2B\xC2\x59",
+		.ilen	= 499,
 		.result	= "\x84\x68\xEC\xF2\x1C\x88\x20\xCA"
 			  "\x37\x69\xE3\x3A\x22\x85\x48\x46"
 			  "\x70\xAA\x25\xB4\xCD\x8B\x04\x4E"
@@ -6213,11 +9326,55 @@ static struct cipher_testvec serpent_ctr_enc_tv_template[] = {
 			  "\x7C\xB5\x12\x89\xED\xBF\xB6\x09"
 			  "\x13\x4F\x7D\x61\x3C\x5C\x27\xFC"
 			  "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9"
-			  "\xE6\xD0\x97",
-		.rlen	= 147,
+			  "\xE6\xD0\x97\x81\xDE\xD1\xFB\x8A"
+			  "\x30\xDB\xA3\x5D\xEC\x25\x0B\x86"
+			  "\x71\xC8\xA7\x67\xE8\xBC\x7D\x4C"
+			  "\xAE\x82\xD3\x73\x31\x09\xCB\xB3"
+			  "\x4D\xD4\xC0\x8A\x2B\xFA\xA6\x55"
+			  "\x39\x0A\xBC\x6E\x75\xAB\xC2\xE2"
+			  "\x8A\xF2\x26\xCD\x63\x38\x35\xF7"
+			  "\xAE\x12\x83\xCD\x8A\x9E\x7E\x4C"
+			  "\xFE\x4D\xD7\xCE\x5C\x6E\x4C\xAF"
+			  "\xE3\xCD\x76\xA7\x87\xA1\x54\x7C"
+			  "\xEC\x32\xC7\x83\x2A\xFF\xF8\xEA"
+			  "\x87\xB2\x47\xA3\x9D\xC2\x9C\xA2"
+			  "\xB7\x2C\x7C\x1A\x24\xCB\x88\x61"
+			  "\xFF\xA7\x1A\x16\x01\xDD\x4B\xFC"
+			  "\x2E\xE0\x48\x67\x09\x42\xCC\x91"
+			  "\xBE\x20\x38\xC0\x5E\x3B\x95\x00"
+			  "\xA1\x96\x66\x0B\x8A\xE9\x9E\xF7"
+			  "\x6B\x34\x0A\x51\xC0\x3B\xEB\x71"
+			  "\x07\x97\x38\x4B\x5C\x56\x98\x67"
+			  "\x78\x9C\xD0\x0E\x2B\xB5\x67\x90"
+			  "\x75\xF8\xFE\x6D\x4E\x85\xCC\x0D"
+			  "\x18\x06\x15\x9D\x5A\x10\x13\x37"
+			  "\xA3\xD6\x68\xA2\xDF\x7E\xC7\x12"
+			  "\xC9\x0D\x4D\x91\xB0\x2A\x55\xFF"
+			  "\x6F\x73\x13\xDF\x28\xB5\x2A\x2C"
+			  "\xE4\xFC\x20\xD9\xF1\x7A\x82\xB1"
+			  "\xCB\x57\xB6\x3D\x8C\xF4\x8E\x27"
+			  "\x37\xDC\x35\xF3\x79\x01\x53\xA4"
+			  "\x7B\x37\xDE\x7C\x04\xAE\x50\xDB"
+			  "\x9B\x1E\x8C\x07\xA7\x52\x49\x50"
+			  "\x34\x25\x65\xDD\xA9\x8F\x7E\xBD"
+			  "\x7A\xC9\x36\xAE\xDE\x21\x48\x64"
+			  "\xC2\x02\xBA\xBE\x11\x1E\x3D\x9C"
+			  "\x98\x52\xCC\x04\xBD\x5E\x61\x26"
+			  "\x10\xD3\x21\xD9\x6E\x25\x98\x77"
+			  "\x8E\x98\x63\xF6\xF6\x52\xFB\x13"
+			  "\xAA\x30\xF2\xB9\xA4\x43\x53\x39"
+			  "\x1C\x97\x07\x7E\x6B\xFF\x3D\x43"
+			  "\xA6\x71\x6B\x66\x8F\x58\x3F\x71"
+			  "\x90\x47\x40\x92\xE6\x69\xD1\x96"
+			  "\x34\xB3\x3B\xE5\x43\xE4\xD5\x56"
+			  "\xB2\xE6\x7E\x86\x7A\x12\x17\x5B"
+			  "\x30\xF3\x9B\x0D\xFA\x57\xE4\x50"
+			  "\x40\x53\x77\x8C\x15\xF8\x8D\x13"
+			  "\x38\xE2\xE5",
+		.rlen	= 499,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 147 - 16, 16 },
+		.tap	= { 499 - 16, 16 },
 	}, { /* Generated with Crypto++ */
 		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
 			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -6381,8 +9538,52 @@ static struct cipher_testvec serpent_ctr_dec_tv_template[] = {
 			  "\xBA\x58\x2A\x1C\xDF\xC2\x3A\xA5"
 			  "\x7C\xB5\x12\x89\xED\xBF\xB6\x09"
 			  "\x13\x4F\x7D\x61\x3C\x5C\x27\xFC"
-			  "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9",
-		.ilen	= 144,
+			  "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9"
+			  "\xE6\xD0\x97\x81\xDE\xD1\xFB\x8A"
+			  "\x30\xDB\xA3\x5D\xEC\x25\x0B\x86"
+			  "\x71\xC8\xA7\x67\xE8\xBC\x7D\x4C"
+			  "\xAE\x82\xD3\x73\x31\x09\xCB\xB3"
+			  "\x4D\xD4\xC0\x8A\x2B\xFA\xA6\x55"
+			  "\x39\x0A\xBC\x6E\x75\xAB\xC2\xE2"
+			  "\x8A\xF2\x26\xCD\x63\x38\x35\xF7"
+			  "\xAE\x12\x83\xCD\x8A\x9E\x7E\x4C"
+			  "\xFE\x4D\xD7\xCE\x5C\x6E\x4C\xAF"
+			  "\xE3\xCD\x76\xA7\x87\xA1\x54\x7C"
+			  "\xEC\x32\xC7\x83\x2A\xFF\xF8\xEA"
+			  "\x87\xB2\x47\xA3\x9D\xC2\x9C\xA2"
+			  "\xB7\x2C\x7C\x1A\x24\xCB\x88\x61"
+			  "\xFF\xA7\x1A\x16\x01\xDD\x4B\xFC"
+			  "\x2E\xE0\x48\x67\x09\x42\xCC\x91"
+			  "\xBE\x20\x38\xC0\x5E\x3B\x95\x00"
+			  "\xA1\x96\x66\x0B\x8A\xE9\x9E\xF7"
+			  "\x6B\x34\x0A\x51\xC0\x3B\xEB\x71"
+			  "\x07\x97\x38\x4B\x5C\x56\x98\x67"
+			  "\x78\x9C\xD0\x0E\x2B\xB5\x67\x90"
+			  "\x75\xF8\xFE\x6D\x4E\x85\xCC\x0D"
+			  "\x18\x06\x15\x9D\x5A\x10\x13\x37"
+			  "\xA3\xD6\x68\xA2\xDF\x7E\xC7\x12"
+			  "\xC9\x0D\x4D\x91\xB0\x2A\x55\xFF"
+			  "\x6F\x73\x13\xDF\x28\xB5\x2A\x2C"
+			  "\xE4\xFC\x20\xD9\xF1\x7A\x82\xB1"
+			  "\xCB\x57\xB6\x3D\x8C\xF4\x8E\x27"
+			  "\x37\xDC\x35\xF3\x79\x01\x53\xA4"
+			  "\x7B\x37\xDE\x7C\x04\xAE\x50\xDB"
+			  "\x9B\x1E\x8C\x07\xA7\x52\x49\x50"
+			  "\x34\x25\x65\xDD\xA9\x8F\x7E\xBD"
+			  "\x7A\xC9\x36\xAE\xDE\x21\x48\x64"
+			  "\xC2\x02\xBA\xBE\x11\x1E\x3D\x9C"
+			  "\x98\x52\xCC\x04\xBD\x5E\x61\x26"
+			  "\x10\xD3\x21\xD9\x6E\x25\x98\x77"
+			  "\x8E\x98\x63\xF6\xF6\x52\xFB\x13"
+			  "\xAA\x30\xF2\xB9\xA4\x43\x53\x39"
+			  "\x1C\x97\x07\x7E\x6B\xFF\x3D\x43"
+			  "\xA6\x71\x6B\x66\x8F\x58\x3F\x71"
+			  "\x90\x47\x40\x92\xE6\x69\xD1\x96"
+			  "\x34\xB3\x3B\xE5\x43\xE4\xD5\x56"
+			  "\xB2\xE6\x7E\x86\x7A\x12\x17\x5B"
+			  "\x30\xF3\x9B\x0D\xFA\x57\xE4\x50"
+			  "\x40\x53\x77\x8C\x15\xF8\x8D\x13",
+		.ilen	= 496,
 		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
 			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
@@ -6400,8 +9601,52 @@ static struct cipher_testvec serpent_ctr_dec_tv_template[] = {
 			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
 			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
 			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
-			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A",
-		.rlen	= 144,
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.rlen	= 496,
 	}, { /* Generated with Crypto++ */
 		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
 			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -6428,8 +9673,52 @@ static struct cipher_testvec serpent_ctr_dec_tv_template[] = {
 			  "\x7C\xB5\x12\x89\xED\xBF\xB6\x09"
 			  "\x13\x4F\x7D\x61\x3C\x5C\x27\xFC"
 			  "\x5D\xE1\x4F\xA1\xEA\xB3\xCA\xB9"
-			  "\xE6\xD0\x97",
-		.ilen	= 147,
+			  "\xE6\xD0\x97\x81\xDE\xD1\xFB\x8A"
+			  "\x30\xDB\xA3\x5D\xEC\x25\x0B\x86"
+			  "\x71\xC8\xA7\x67\xE8\xBC\x7D\x4C"
+			  "\xAE\x82\xD3\x73\x31\x09\xCB\xB3"
+			  "\x4D\xD4\xC0\x8A\x2B\xFA\xA6\x55"
+			  "\x39\x0A\xBC\x6E\x75\xAB\xC2\xE2"
+			  "\x8A\xF2\x26\xCD\x63\x38\x35\xF7"
+			  "\xAE\x12\x83\xCD\x8A\x9E\x7E\x4C"
+			  "\xFE\x4D\xD7\xCE\x5C\x6E\x4C\xAF"
+			  "\xE3\xCD\x76\xA7\x87\xA1\x54\x7C"
+			  "\xEC\x32\xC7\x83\x2A\xFF\xF8\xEA"
+			  "\x87\xB2\x47\xA3\x9D\xC2\x9C\xA2"
+			  "\xB7\x2C\x7C\x1A\x24\xCB\x88\x61"
+			  "\xFF\xA7\x1A\x16\x01\xDD\x4B\xFC"
+			  "\x2E\xE0\x48\x67\x09\x42\xCC\x91"
+			  "\xBE\x20\x38\xC0\x5E\x3B\x95\x00"
+			  "\xA1\x96\x66\x0B\x8A\xE9\x9E\xF7"
+			  "\x6B\x34\x0A\x51\xC0\x3B\xEB\x71"
+			  "\x07\x97\x38\x4B\x5C\x56\x98\x67"
+			  "\x78\x9C\xD0\x0E\x2B\xB5\x67\x90"
+			  "\x75\xF8\xFE\x6D\x4E\x85\xCC\x0D"
+			  "\x18\x06\x15\x9D\x5A\x10\x13\x37"
+			  "\xA3\xD6\x68\xA2\xDF\x7E\xC7\x12"
+			  "\xC9\x0D\x4D\x91\xB0\x2A\x55\xFF"
+			  "\x6F\x73\x13\xDF\x28\xB5\x2A\x2C"
+			  "\xE4\xFC\x20\xD9\xF1\x7A\x82\xB1"
+			  "\xCB\x57\xB6\x3D\x8C\xF4\x8E\x27"
+			  "\x37\xDC\x35\xF3\x79\x01\x53\xA4"
+			  "\x7B\x37\xDE\x7C\x04\xAE\x50\xDB"
+			  "\x9B\x1E\x8C\x07\xA7\x52\x49\x50"
+			  "\x34\x25\x65\xDD\xA9\x8F\x7E\xBD"
+			  "\x7A\xC9\x36\xAE\xDE\x21\x48\x64"
+			  "\xC2\x02\xBA\xBE\x11\x1E\x3D\x9C"
+			  "\x98\x52\xCC\x04\xBD\x5E\x61\x26"
+			  "\x10\xD3\x21\xD9\x6E\x25\x98\x77"
+			  "\x8E\x98\x63\xF6\xF6\x52\xFB\x13"
+			  "\xAA\x30\xF2\xB9\xA4\x43\x53\x39"
+			  "\x1C\x97\x07\x7E\x6B\xFF\x3D\x43"
+			  "\xA6\x71\x6B\x66\x8F\x58\x3F\x71"
+			  "\x90\x47\x40\x92\xE6\x69\xD1\x96"
+			  "\x34\xB3\x3B\xE5\x43\xE4\xD5\x56"
+			  "\xB2\xE6\x7E\x86\x7A\x12\x17\x5B"
+			  "\x30\xF3\x9B\x0D\xFA\x57\xE4\x50"
+			  "\x40\x53\x77\x8C\x15\xF8\x8D\x13"
+			  "\x38\xE2\xE5",
+		.ilen	= 499,
 		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
 			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
@@ -6448,11 +9737,55 @@ static struct cipher_testvec serpent_ctr_dec_tv_template[] = {
 			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
 			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
 			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
-			  "\xF1\x65\xFC",
-		.rlen	= 147,
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+			  "\x2B\xC2\x59",
+		.rlen	= 499,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 147 - 16, 16 },
+		.tap	= { 499 - 16, 16 },
 	}, { /* Generated with Crypto++ */
 		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
 			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -9326,10 +12659,10 @@ static struct cipher_testvec cast6_xts_dec_tv_template[] = {
 /*
  * AES test vectors.
  */
-#define AES_ENC_TEST_VECTORS 3
-#define AES_DEC_TEST_VECTORS 3
-#define AES_CBC_ENC_TEST_VECTORS 4
-#define AES_CBC_DEC_TEST_VECTORS 4
+#define AES_ENC_TEST_VECTORS 4
+#define AES_DEC_TEST_VECTORS 4
+#define AES_CBC_ENC_TEST_VECTORS 5
+#define AES_CBC_DEC_TEST_VECTORS 5
 #define HMAC_SHA1_AES_CBC_ENC_TEST_VECTORS 7
 #define HMAC_SHA256_AES_CBC_ENC_TEST_VECTORS 7
 #define HMAC_SHA512_AES_CBC_ENC_TEST_VECTORS 7
@@ -9337,8 +12670,8 @@ static struct cipher_testvec cast6_xts_dec_tv_template[] = {
 #define AES_LRW_DEC_TEST_VECTORS 8
 #define AES_XTS_ENC_TEST_VECTORS 5
 #define AES_XTS_DEC_TEST_VECTORS 5
-#define AES_CTR_ENC_TEST_VECTORS 3
-#define AES_CTR_DEC_TEST_VECTORS 3
+#define AES_CTR_ENC_TEST_VECTORS 5
+#define AES_CTR_DEC_TEST_VECTORS 5
 #define AES_OFB_ENC_TEST_VECTORS 1
 #define AES_OFB_DEC_TEST_VECTORS 1
 #define AES_CTR_3686_ENC_TEST_VECTORS 7
@@ -9386,6 +12719,141 @@ static struct cipher_testvec aes_enc_tv_template[] = {
 		.result	= "\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
 			  "\xea\xfc\x49\x90\x4b\x49\x60\x89",
 		.rlen	= 16,
+	}, { /* Generated with Crypto++ */
+		.key	= "\xA6\xC9\x83\xA6\xC9\xEC\x0F\x32"
+			  "\x55\x0F\x32\x55\x78\x9B\xBE\x78"
+			  "\x9B\xBE\xE1\x04\x27\xE1\x04\x27"
+			  "\x4A\x6D\x90\x4A\x6D\x90\xB3\xD6",
+		.klen	= 32,
+		.input	= "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+			  "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+			  "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+			  "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+			  "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+			  "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+			  "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+			  "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+			  "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+			  "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+			  "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+			  "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+			  "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+			  "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+			  "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+			  "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+			  "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+			  "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+			  "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+			  "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+			  "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+			  "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+			  "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+			  "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+			  "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+			  "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+			  "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+			  "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+			  "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+			  "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+			  "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+			  "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+			  "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+			  "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+			  "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+			  "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+			  "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+			  "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+			  "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+			  "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+			  "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+			  "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+			  "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+			  "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+			  "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+			  "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+			  "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+			  "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+			  "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+			  "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+			  "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+			  "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+			  "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+			  "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+			  "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+			  "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+			  "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+			  "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+			  "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+			  "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+			  "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+		.ilen	= 496,
+		.result	= "\x71\x73\xF7\xDB\x24\x93\x21\x6D"
+			  "\x61\x1E\xBB\x63\x42\x79\xDB\x64"
+			  "\x6F\x82\xC0\xCA\xA3\x9B\xFA\x0B"
+			  "\xD9\x08\xC7\x4A\x90\xAE\x8F\x5F"
+			  "\x5E\x06\xF0\x5F\x31\x51\x18\x37"
+			  "\x45\xD7\xCA\x3A\xFD\x6C\x3F\xE1"
+			  "\xDD\x8D\x22\x65\x2B\x00\x50\xCE"
+			  "\xBA\x28\x67\xD7\xCE\x0E\x0D\xEA"
+			  "\x78\x69\x7F\xAE\x8F\x8B\x69\x37"
+			  "\x75\xE0\xDC\x96\xE0\xB7\xF4\x09"
+			  "\xCB\x6D\xA2\xFB\xDA\xAF\x09\xF8"
+			  "\x81\x82\x27\xFA\x45\x9C\x29\xA4"
+			  "\x22\x8B\x78\x69\x5B\x46\xF9\x39"
+			  "\x1B\xCC\xF9\x1D\x09\xEB\xBC\x5C"
+			  "\x41\x72\x51\x97\x1D\x07\x49\xA0"
+			  "\x1B\x8E\x65\x4B\xB2\x6A\x12\x03"
+			  "\x6A\x60\x95\xAC\xBD\xAC\x1A\x64"
+			  "\xDE\x5A\xA5\xF0\x83\x2F\xCB\xCA"
+			  "\x22\x74\xA6\x6C\x9B\x73\xCE\x3F"
+			  "\xE1\x8B\x22\x17\x59\x0C\x47\x89"
+			  "\x33\xA1\xD6\x47\x03\x19\x4F\xA8"
+			  "\x67\x69\xF0\x5B\xF0\x20\xAD\x06"
+			  "\x27\x81\x92\xD8\xC5\xBA\x98\x12"
+			  "\xBE\x24\xB5\x2F\x75\x02\xC2\xAD"
+			  "\x12\x2F\x07\x32\xEE\x39\xAF\x64"
+			  "\x05\x8F\xB3\xD4\xEB\x1B\x46\x6E"
+			  "\xD9\x21\xF9\xC4\xB7\xC9\x45\x68"
+			  "\xB4\xA1\x74\x9F\x82\x47\xEB\xCC"
+			  "\xBD\x0A\x14\x95\x0F\x8B\xA8\x2F"
+			  "\x4B\x1B\xA7\xBF\x82\xA6\x43\x0C"
+			  "\xB9\x39\x4A\xA8\x10\x6F\x50\x7B"
+			  "\x25\xFB\x26\x81\xE0\x2F\xF0\x96"
+			  "\x8D\x8B\xAC\x92\x0F\xF6\xED\x64"
+			  "\x63\x29\x4C\x8E\x18\x13\xC5\xBF"
+			  "\xFC\xA0\xD9\xBF\x7C\x3A\x0E\x29"
+			  "\x6F\xD1\x6C\x6F\xA5\xDA\xBF\xB1"
+			  "\x30\xEA\x44\x2D\xC3\x8F\x16\xE1"
+			  "\x66\xFA\xA3\x21\x3E\xFC\x13\xCA"
+			  "\xF0\xF6\xF0\x59\xBD\x8F\x38\x50"
+			  "\x31\xCB\x69\x3F\x96\x15\xD6\xF5"
+			  "\xAE\xFF\xF6\xAA\x41\x85\x4C\x10"
+			  "\x58\xE3\xF9\x44\xE6\x28\xDA\x9A"
+			  "\xDC\x6A\x80\x34\x73\x97\x1B\xC5"
+			  "\xCA\x26\x16\x77\x0E\x60\xAB\x89"
+			  "\x0F\x04\x27\xBD\xCE\x3E\x71\xB4"
+			  "\xA0\xD7\x22\x7E\xDB\xEB\x24\x70"
+			  "\x42\x71\x51\x78\x70\xB3\xE0\x3D"
+			  "\x84\x8E\x8D\x7B\xD0\x6D\xEA\x92"
+			  "\x11\x08\x42\x4F\xE5\xAD\x26\x92"
+			  "\xD2\x00\xAE\xA8\xE3\x4B\x37\x47"
+			  "\x22\xC1\x95\xC1\x63\x7F\xCB\x03"
+			  "\xF3\xE3\xD7\x9D\x60\xC7\xBC\xEA"
+			  "\x35\xA2\xFD\x45\x52\x39\x13\x6F"
+			  "\xC1\x53\xF3\x53\xDF\x33\x84\xD7"
+			  "\xD2\xC8\x37\xB0\x75\xE3\x41\x46"
+			  "\xB3\xC7\x83\x2E\x8A\xBB\xA4\xE5"
+			  "\x7F\x3C\xFD\x8B\xEB\xEA\x63\xBD"
+			  "\xB7\x46\xE7\xBF\x09\x9C\x0D\x0F"
+			  "\x40\x86\x7F\x51\xE1\x11\x9C\xCB"
+			  "\x88\xE6\x68\x47\xE3\x2B\xC5\xFF"
+			  "\x09\x79\xA0\x43\x5C\x0D\x08\x58"
+			  "\x17\xBB\xC0\x6B\x62\x3F\x56\xE9",
+		.rlen	= 496,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 496 - 16, 16 },
 	},
 };
 
@@ -9423,6 +12891,141 @@ static struct cipher_testvec aes_dec_tv_template[] = {
 		.result	= "\x00\x11\x22\x33\x44\x55\x66\x77"
 			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
 		.rlen	= 16,
+	}, { /* Generated with Crypto++ */
+		.key	= "\xA6\xC9\x83\xA6\xC9\xEC\x0F\x32"
+			  "\x55\x0F\x32\x55\x78\x9B\xBE\x78"
+			  "\x9B\xBE\xE1\x04\x27\xE1\x04\x27"
+			  "\x4A\x6D\x90\x4A\x6D\x90\xB3\xD6",
+		.klen	= 32,
+		.input	= "\x71\x73\xF7\xDB\x24\x93\x21\x6D"
+			  "\x61\x1E\xBB\x63\x42\x79\xDB\x64"
+			  "\x6F\x82\xC0\xCA\xA3\x9B\xFA\x0B"
+			  "\xD9\x08\xC7\x4A\x90\xAE\x8F\x5F"
+			  "\x5E\x06\xF0\x5F\x31\x51\x18\x37"
+			  "\x45\xD7\xCA\x3A\xFD\x6C\x3F\xE1"
+			  "\xDD\x8D\x22\x65\x2B\x00\x50\xCE"
+			  "\xBA\x28\x67\xD7\xCE\x0E\x0D\xEA"
+			  "\x78\x69\x7F\xAE\x8F\x8B\x69\x37"
+			  "\x75\xE0\xDC\x96\xE0\xB7\xF4\x09"
+			  "\xCB\x6D\xA2\xFB\xDA\xAF\x09\xF8"
+			  "\x81\x82\x27\xFA\x45\x9C\x29\xA4"
+			  "\x22\x8B\x78\x69\x5B\x46\xF9\x39"
+			  "\x1B\xCC\xF9\x1D\x09\xEB\xBC\x5C"
+			  "\x41\x72\x51\x97\x1D\x07\x49\xA0"
+			  "\x1B\x8E\x65\x4B\xB2\x6A\x12\x03"
+			  "\x6A\x60\x95\xAC\xBD\xAC\x1A\x64"
+			  "\xDE\x5A\xA5\xF0\x83\x2F\xCB\xCA"
+			  "\x22\x74\xA6\x6C\x9B\x73\xCE\x3F"
+			  "\xE1\x8B\x22\x17\x59\x0C\x47\x89"
+			  "\x33\xA1\xD6\x47\x03\x19\x4F\xA8"
+			  "\x67\x69\xF0\x5B\xF0\x20\xAD\x06"
+			  "\x27\x81\x92\xD8\xC5\xBA\x98\x12"
+			  "\xBE\x24\xB5\x2F\x75\x02\xC2\xAD"
+			  "\x12\x2F\x07\x32\xEE\x39\xAF\x64"
+			  "\x05\x8F\xB3\xD4\xEB\x1B\x46\x6E"
+			  "\xD9\x21\xF9\xC4\xB7\xC9\x45\x68"
+			  "\xB4\xA1\x74\x9F\x82\x47\xEB\xCC"
+			  "\xBD\x0A\x14\x95\x0F\x8B\xA8\x2F"
+			  "\x4B\x1B\xA7\xBF\x82\xA6\x43\x0C"
+			  "\xB9\x39\x4A\xA8\x10\x6F\x50\x7B"
+			  "\x25\xFB\x26\x81\xE0\x2F\xF0\x96"
+			  "\x8D\x8B\xAC\x92\x0F\xF6\xED\x64"
+			  "\x63\x29\x4C\x8E\x18\x13\xC5\xBF"
+			  "\xFC\xA0\xD9\xBF\x7C\x3A\x0E\x29"
+			  "\x6F\xD1\x6C\x6F\xA5\xDA\xBF\xB1"
+			  "\x30\xEA\x44\x2D\xC3\x8F\x16\xE1"
+			  "\x66\xFA\xA3\x21\x3E\xFC\x13\xCA"
+			  "\xF0\xF6\xF0\x59\xBD\x8F\x38\x50"
+			  "\x31\xCB\x69\x3F\x96\x15\xD6\xF5"
+			  "\xAE\xFF\xF6\xAA\x41\x85\x4C\x10"
+			  "\x58\xE3\xF9\x44\xE6\x28\xDA\x9A"
+			  "\xDC\x6A\x80\x34\x73\x97\x1B\xC5"
+			  "\xCA\x26\x16\x77\x0E\x60\xAB\x89"
+			  "\x0F\x04\x27\xBD\xCE\x3E\x71\xB4"
+			  "\xA0\xD7\x22\x7E\xDB\xEB\x24\x70"
+			  "\x42\x71\x51\x78\x70\xB3\xE0\x3D"
+			  "\x84\x8E\x8D\x7B\xD0\x6D\xEA\x92"
+			  "\x11\x08\x42\x4F\xE5\xAD\x26\x92"
+			  "\xD2\x00\xAE\xA8\xE3\x4B\x37\x47"
+			  "\x22\xC1\x95\xC1\x63\x7F\xCB\x03"
+			  "\xF3\xE3\xD7\x9D\x60\xC7\xBC\xEA"
+			  "\x35\xA2\xFD\x45\x52\x39\x13\x6F"
+			  "\xC1\x53\xF3\x53\xDF\x33\x84\xD7"
+			  "\xD2\xC8\x37\xB0\x75\xE3\x41\x46"
+			  "\xB3\xC7\x83\x2E\x8A\xBB\xA4\xE5"
+			  "\x7F\x3C\xFD\x8B\xEB\xEA\x63\xBD"
+			  "\xB7\x46\xE7\xBF\x09\x9C\x0D\x0F"
+			  "\x40\x86\x7F\x51\xE1\x11\x9C\xCB"
+			  "\x88\xE6\x68\x47\xE3\x2B\xC5\xFF"
+			  "\x09\x79\xA0\x43\x5C\x0D\x08\x58"
+			  "\x17\xBB\xC0\x6B\x62\x3F\x56\xE9",
+		.ilen	= 496,
+		.result	= "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+			  "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+			  "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+			  "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+			  "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+			  "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+			  "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+			  "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+			  "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+			  "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+			  "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+			  "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+			  "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+			  "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+			  "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+			  "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+			  "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+			  "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+			  "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+			  "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+			  "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+			  "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+			  "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+			  "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+			  "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+			  "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+			  "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+			  "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+			  "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+			  "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+			  "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+			  "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+			  "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+			  "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+			  "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+			  "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+			  "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+			  "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+			  "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+			  "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+			  "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+			  "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+			  "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+			  "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+			  "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+			  "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+			  "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+			  "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+			  "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+			  "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+			  "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+			  "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+			  "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+			  "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+			  "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+			  "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+			  "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+			  "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+			  "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+			  "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+			  "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+		.rlen	= 496,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 496 - 16, 16 },
 	},
 };
 
@@ -9505,6 +13108,143 @@ static struct cipher_testvec aes_cbc_enc_tv_template[] = {
 			  "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc"
 			  "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b",
 		.rlen	= 64,
+	}, { /* Generated with Crypto++ */
+		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+			  "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+			  "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+			  "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+		.klen	= 32,
+		.iv	= "\xE7\x82\x1D\xB8\x53\x11\xAC\x47"
+			  "\xE2\x7D\x18\xD6\x71\x0C\xA7\x42",
+		.input	= "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+			  "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+			  "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+			  "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+			  "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+			  "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+			  "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+			  "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+			  "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+			  "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+			  "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+			  "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+			  "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+			  "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+			  "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+			  "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+			  "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+			  "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+			  "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+			  "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+			  "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+			  "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+			  "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+			  "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+			  "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+			  "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+			  "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+			  "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+			  "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+			  "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+			  "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+			  "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+			  "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+			  "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+			  "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+			  "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+			  "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+			  "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+			  "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+			  "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+			  "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+			  "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+			  "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+			  "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+			  "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+			  "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+			  "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+			  "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+			  "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+			  "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+			  "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+			  "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+			  "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+			  "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+			  "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+			  "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+			  "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+			  "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+			  "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+			  "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+			  "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+		.ilen	= 496,
+		.result	= "\xEA\x65\x8A\x19\xB0\x66\xC1\x3F"
+			  "\xCE\xF1\x97\x75\xC1\xFD\xB5\xAF"
+			  "\x52\x65\xF7\xFF\xBC\xD8\x2D\x9F"
+			  "\x2F\xB9\x26\x9B\x6F\x10\xB7\xB8"
+			  "\x26\xA1\x02\x46\xA2\xAD\xC6\xC0"
+			  "\x11\x15\xFF\x6D\x1E\x82\x04\xA6"
+			  "\xB1\x74\xD1\x08\x13\xFD\x90\x7C"
+			  "\xF5\xED\xD3\xDB\x5A\x0A\x0C\x2F"
+			  "\x0A\x70\xF1\x88\x07\xCF\x21\x26"
+			  "\x40\x40\x8A\xF5\x53\xF7\x24\x4F"
+			  "\x83\x38\x43\x5F\x08\x99\xEB\xE3"
+			  "\xDC\x02\x64\x67\x50\x6E\x15\xC3"
+			  "\x01\x1A\xA0\x81\x13\x65\xA6\x73"
+			  "\x71\xA6\x3B\x91\x83\x77\xBE\xFA"
+			  "\xDB\x71\x73\xA6\xC1\xAE\x43\xC3"
+			  "\x36\xCE\xD6\xEB\xF9\x30\x1C\x4F"
+			  "\x80\x38\x5E\x9C\x6E\xAB\x98\x2F"
+			  "\x53\xAF\xCF\xC8\x9A\xB8\x86\x43"
+			  "\x3E\x86\xE7\xA1\xF4\x2F\x30\x40"
+			  "\x03\xA8\x6C\x50\x42\x9F\x77\x59"
+			  "\x89\xA0\xC5\xEC\x9A\xB8\xDD\x99"
+			  "\x16\x24\x02\x07\x48\xAE\xF2\x31"
+			  "\x34\x0E\xC3\x85\xFE\x1C\x95\x99"
+			  "\x87\x58\x98\x8B\xE7\xC6\xC5\x70"
+			  "\x73\x81\x07\x7C\x56\x2F\xD8\x1B"
+			  "\xB7\xB9\x2B\xAB\xE3\x01\x87\x0F"
+			  "\xD8\xBB\xC0\x0D\xAC\x2C\x2F\x98"
+			  "\x3C\x0B\xA2\x99\x4A\x8C\xF7\x04"
+			  "\xE0\xE0\xCF\xD1\x81\x5B\xFE\xF5"
+			  "\x24\x04\xFD\xB8\xDF\x13\xD8\xCD"
+			  "\xF1\xE3\x3D\x98\x50\x02\x77\x9E"
+			  "\xBC\x22\xAB\xFA\xC2\x43\x1F\x66"
+			  "\x20\x02\x23\xDA\xDF\xA0\x89\xF6"
+			  "\xD8\xF3\x45\x24\x53\x6F\x16\x77"
+			  "\x02\x3E\x7B\x36\x5F\xA0\x3B\x78"
+			  "\x63\xA2\xBD\xB5\xA4\xCA\x1E\xD3"
+			  "\x57\xBC\x0B\x9F\x43\x51\x28\x4F"
+			  "\x07\x50\x6C\x68\x12\x07\xCF\xFA"
+			  "\x6B\x72\x0B\xEB\xF8\x88\x90\x2C"
+			  "\x7E\xF5\x91\xD1\x03\xD8\xD5\xBD"
+			  "\x22\x39\x7B\x16\x03\x01\x69\xAF"
+			  "\x3D\x38\x66\x28\x0C\xBE\x5B\xC5"
+			  "\x03\xB4\x2F\x51\x8A\x56\x17\x2B"
+			  "\x88\x42\x6D\x40\x68\x8F\xD0\x11"
+			  "\x19\xF9\x1F\x43\x79\x95\x31\xFA"
+			  "\x28\x7A\x3D\xF7\x66\xEB\xEF\xAC"
+			  "\x06\xB2\x01\xAD\xDB\x68\xDB\xEC"
+			  "\x8D\x53\x6E\x72\x68\xA3\xC7\x63"
+			  "\x43\x2B\x78\xE0\x04\x29\x8F\x72"
+			  "\xB2\x2C\xE6\x84\x03\x30\x6D\xCD"
+			  "\x26\x92\x37\xE1\x2F\xBB\x8B\x9D"
+			  "\xE4\x4C\xF6\x93\xBC\xD9\xAD\x44"
+			  "\x52\x65\xC7\xB0\x0E\x3F\x0E\x61"
+			  "\x56\x5D\x1C\x6D\xA7\x05\x2E\xBC"
+			  "\x58\x08\x15\xAB\x12\xAB\x17\x4A"
+			  "\x5E\x1C\xF2\xCD\xB8\xA2\xAE\xFB"
+			  "\x9B\x2E\x0E\x85\x34\x80\x0E\x3F"
+			  "\x4C\xB8\xDB\xCE\x1C\x90\xA1\x61"
+			  "\x6C\x69\x09\x35\x9E\xD4\xF4\xAD"
+			  "\xBC\x06\x41\xE3\x01\xB4\x4E\x0A"
+			  "\xE0\x1F\x91\xF8\x82\x96\x2D\x65"
+			  "\xA3\xAA\x13\xCC\x50\xFF\x7B\x02",
+		.rlen	= 496,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 496 - 16, 16 },
 	},
 };
 
@@ -9587,6 +13327,143 @@ static struct cipher_testvec aes_cbc_dec_tv_template[] = {
 			  "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
 			  "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
 		.rlen	= 64,
+	}, { /* Generated with Crypto++ */
+		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+			  "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+			  "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+			  "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+		.klen	= 32,
+		.iv	= "\xE7\x82\x1D\xB8\x53\x11\xAC\x47"
+			  "\xE2\x7D\x18\xD6\x71\x0C\xA7\x42",
+		.input	= "\xEA\x65\x8A\x19\xB0\x66\xC1\x3F"
+			  "\xCE\xF1\x97\x75\xC1\xFD\xB5\xAF"
+			  "\x52\x65\xF7\xFF\xBC\xD8\x2D\x9F"
+			  "\x2F\xB9\x26\x9B\x6F\x10\xB7\xB8"
+			  "\x26\xA1\x02\x46\xA2\xAD\xC6\xC0"
+			  "\x11\x15\xFF\x6D\x1E\x82\x04\xA6"
+			  "\xB1\x74\xD1\x08\x13\xFD\x90\x7C"
+			  "\xF5\xED\xD3\xDB\x5A\x0A\x0C\x2F"
+			  "\x0A\x70\xF1\x88\x07\xCF\x21\x26"
+			  "\x40\x40\x8A\xF5\x53\xF7\x24\x4F"
+			  "\x83\x38\x43\x5F\x08\x99\xEB\xE3"
+			  "\xDC\x02\x64\x67\x50\x6E\x15\xC3"
+			  "\x01\x1A\xA0\x81\x13\x65\xA6\x73"
+			  "\x71\xA6\x3B\x91\x83\x77\xBE\xFA"
+			  "\xDB\x71\x73\xA6\xC1\xAE\x43\xC3"
+			  "\x36\xCE\xD6\xEB\xF9\x30\x1C\x4F"
+			  "\x80\x38\x5E\x9C\x6E\xAB\x98\x2F"
+			  "\x53\xAF\xCF\xC8\x9A\xB8\x86\x43"
+			  "\x3E\x86\xE7\xA1\xF4\x2F\x30\x40"
+			  "\x03\xA8\x6C\x50\x42\x9F\x77\x59"
+			  "\x89\xA0\xC5\xEC\x9A\xB8\xDD\x99"
+			  "\x16\x24\x02\x07\x48\xAE\xF2\x31"
+			  "\x34\x0E\xC3\x85\xFE\x1C\x95\x99"
+			  "\x87\x58\x98\x8B\xE7\xC6\xC5\x70"
+			  "\x73\x81\x07\x7C\x56\x2F\xD8\x1B"
+			  "\xB7\xB9\x2B\xAB\xE3\x01\x87\x0F"
+			  "\xD8\xBB\xC0\x0D\xAC\x2C\x2F\x98"
+			  "\x3C\x0B\xA2\x99\x4A\x8C\xF7\x04"
+			  "\xE0\xE0\xCF\xD1\x81\x5B\xFE\xF5"
+			  "\x24\x04\xFD\xB8\xDF\x13\xD8\xCD"
+			  "\xF1\xE3\x3D\x98\x50\x02\x77\x9E"
+			  "\xBC\x22\xAB\xFA\xC2\x43\x1F\x66"
+			  "\x20\x02\x23\xDA\xDF\xA0\x89\xF6"
+			  "\xD8\xF3\x45\x24\x53\x6F\x16\x77"
+			  "\x02\x3E\x7B\x36\x5F\xA0\x3B\x78"
+			  "\x63\xA2\xBD\xB5\xA4\xCA\x1E\xD3"
+			  "\x57\xBC\x0B\x9F\x43\x51\x28\x4F"
+			  "\x07\x50\x6C\x68\x12\x07\xCF\xFA"
+			  "\x6B\x72\x0B\xEB\xF8\x88\x90\x2C"
+			  "\x7E\xF5\x91\xD1\x03\xD8\xD5\xBD"
+			  "\x22\x39\x7B\x16\x03\x01\x69\xAF"
+			  "\x3D\x38\x66\x28\x0C\xBE\x5B\xC5"
+			  "\x03\xB4\x2F\x51\x8A\x56\x17\x2B"
+			  "\x88\x42\x6D\x40\x68\x8F\xD0\x11"
+			  "\x19\xF9\x1F\x43\x79\x95\x31\xFA"
+			  "\x28\x7A\x3D\xF7\x66\xEB\xEF\xAC"
+			  "\x06\xB2\x01\xAD\xDB\x68\xDB\xEC"
+			  "\x8D\x53\x6E\x72\x68\xA3\xC7\x63"
+			  "\x43\x2B\x78\xE0\x04\x29\x8F\x72"
+			  "\xB2\x2C\xE6\x84\x03\x30\x6D\xCD"
+			  "\x26\x92\x37\xE1\x2F\xBB\x8B\x9D"
+			  "\xE4\x4C\xF6\x93\xBC\xD9\xAD\x44"
+			  "\x52\x65\xC7\xB0\x0E\x3F\x0E\x61"
+			  "\x56\x5D\x1C\x6D\xA7\x05\x2E\xBC"
+			  "\x58\x08\x15\xAB\x12\xAB\x17\x4A"
+			  "\x5E\x1C\xF2\xCD\xB8\xA2\xAE\xFB"
+			  "\x9B\x2E\x0E\x85\x34\x80\x0E\x3F"
+			  "\x4C\xB8\xDB\xCE\x1C\x90\xA1\x61"
+			  "\x6C\x69\x09\x35\x9E\xD4\xF4\xAD"
+			  "\xBC\x06\x41\xE3\x01\xB4\x4E\x0A"
+			  "\xE0\x1F\x91\xF8\x82\x96\x2D\x65"
+			  "\xA3\xAA\x13\xCC\x50\xFF\x7B\x02",
+		.ilen	= 496,
+		.result	= "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+			  "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+			  "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+			  "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+			  "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+			  "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+			  "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+			  "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+			  "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+			  "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+			  "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+			  "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+			  "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+			  "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+			  "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+			  "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+			  "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+			  "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+			  "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+			  "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+			  "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+			  "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+			  "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+			  "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+			  "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+			  "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+			  "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+			  "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+			  "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+			  "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+			  "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+			  "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+			  "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+			  "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+			  "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+			  "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+			  "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+			  "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+			  "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+			  "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+			  "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+			  "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+			  "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+			  "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+			  "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+			  "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+			  "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+			  "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+			  "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+			  "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+			  "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+			  "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+			  "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+			  "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+			  "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+			  "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+			  "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+			  "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+			  "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+			  "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+			  "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+		.rlen	= 496,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 496 - 16, 16 },
 	},
 };
 
@@ -11693,7 +15570,283 @@ static struct cipher_testvec aes_ctr_enc_tv_template[] = {
 			  "\xdf\xc9\xc5\x8d\xb6\x7a\xad\xa6"
 			  "\x13\xc2\xdd\x08\x45\x79\x41\xa6",
 		.rlen	= 64,
-	}
+	}, { /* Generated with Crypto++ */
+		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+			  "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+			  "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+			  "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+		.klen	= 32,
+		.iv	= "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+			  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+		.input	= "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+			  "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+			  "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+			  "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+			  "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+			  "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+			  "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+			  "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+			  "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+			  "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+			  "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+			  "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+			  "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+			  "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+			  "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+			  "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+			  "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+			  "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+			  "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+			  "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+			  "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+			  "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+			  "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+			  "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+			  "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+			  "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+			  "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+			  "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+			  "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+			  "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+			  "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+			  "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+			  "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+			  "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+			  "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+			  "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+			  "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+			  "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+			  "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+			  "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+			  "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+			  "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+			  "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+			  "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+			  "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+			  "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+			  "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+			  "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+			  "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+			  "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+			  "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+			  "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+			  "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+			  "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+			  "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+			  "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+			  "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+			  "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+			  "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+			  "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+			  "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+		.ilen	= 496,
+		.result	= "\x04\xF3\xD3\x88\x17\xEF\xDC\xEF"
+			  "\x8B\x04\xF8\x3A\x66\x8D\x1A\x53"
+			  "\x57\x1F\x4B\x23\xE4\xA0\xAF\xF9"
+			  "\x69\x95\x35\x98\x8D\x4D\x8C\xC1"
+			  "\xF0\xB2\x7F\x80\xBB\x54\x28\xA2"
+			  "\x7A\x1B\x9F\x77\xEC\x0E\x6E\xDE"
+			  "\xF0\xEC\xB8\xE4\x20\x62\xEE\xDB"
+			  "\x5D\xF5\xDD\xE3\x54\xFC\xDD\xEB"
+			  "\x6A\xEE\x65\xA1\x21\xD6\xD7\x81"
+			  "\x47\x61\x12\x4D\xC2\x8C\xFA\x78"
+			  "\x1F\x28\x02\x01\xC3\xFC\x1F\xEC"
+			  "\x0F\x10\x4F\xB3\x12\x45\xC6\x3B"
+			  "\x7E\x08\xF9\x5A\xD0\x5D\x73\x2D"
+			  "\x58\xA4\xE5\xCB\x1C\xB4\xCE\x74"
+			  "\x32\x41\x1F\x31\x9C\x08\xA2\x5D"
+			  "\x67\xEB\x72\x1D\xF8\xE7\x70\x54"
+			  "\x34\x4B\x31\x69\x84\x66\x96\x44"
+			  "\x56\xCC\x1E\xD9\xE6\x13\x6A\xB9"
+			  "\x2D\x0A\x05\x45\x2D\x90\xCC\xDF"
+			  "\x16\x5C\x5F\x79\x34\x52\x54\xFE"
+			  "\xFE\xCD\xAD\x04\x2E\xAD\x86\x06"
+			  "\x1F\x37\xE8\x28\xBC\xD3\x8F\x5B"
+			  "\x92\x66\x87\x3B\x8A\x0A\x1A\xCC"
+			  "\x6E\xAB\x9F\x0B\xFA\x5C\xE6\xFD"
+			  "\x3C\x98\x08\x12\xEC\xAA\x9E\x11"
+			  "\xCA\xB2\x1F\xCE\x5E\x5B\xB2\x72"
+			  "\x9C\xCC\x5D\xC5\xE0\x32\xC0\x56"
+			  "\xD5\x45\x16\xD2\xAF\x13\x66\xF7"
+			  "\x8C\x67\xAC\x79\xB2\xAF\x56\x27"
+			  "\x3F\xCC\xFE\xCB\x1E\xC0\x75\xF1"
+			  "\xA7\xC9\xC3\x1D\x8E\xDD\xF9\xD4"
+			  "\x42\xC8\x21\x08\x16\xF7\x01\xD7"
+			  "\xAC\x8E\x3F\x1D\x56\xC1\x06\xE4"
+			  "\x9C\x62\xD6\xA5\x6A\x50\x44\xB3"
+			  "\x35\x1C\x82\xB9\x10\xF9\x42\xA1"
+			  "\xFC\x74\x9B\x44\x4F\x25\x02\xE3"
+			  "\x08\xF5\xD4\x32\x39\x08\x11\xE8"
+			  "\xD2\x6B\x50\x53\xD4\x08\xD1\x6B"
+			  "\x3A\x4A\x68\x7B\x7C\xCD\x46\x5E"
+			  "\x0D\x07\x19\xDB\x67\xD7\x98\x91"
+			  "\xD7\x17\x10\x9B\x7B\x8A\x9B\x33"
+			  "\xAE\xF3\x00\xA6\xD4\x15\xD9\xEA"
+			  "\x85\x99\x22\xE8\x91\x38\x70\x83"
+			  "\x93\x01\x24\x6C\xFA\x9A\xB9\x07"
+			  "\xEA\x8D\x3B\xD9\x2A\x43\x59\x16"
+			  "\x2F\x69\xEE\x84\x36\x44\x76\x98"
+			  "\xF3\x04\x2A\x7C\x74\x3D\x29\x2B"
+			  "\x0D\xAD\x8F\x44\x82\x9E\x57\x8D"
+			  "\xAC\xED\x18\x1F\x50\xA4\xF5\x98"
+			  "\x1F\xBD\x92\x91\x1B\x2D\xA6\xD6"
+			  "\xD2\xE3\x02\xAA\x92\x3B\xC6\xB3"
+			  "\x1B\x39\x72\xD5\x26\xCA\x04\xE0"
+			  "\xFC\x58\x78\xBB\xB1\x3F\xA1\x9C"
+			  "\x42\x24\x3E\x2E\x22\xBB\x4B\xBA"
+			  "\xF4\x52\x0A\xE6\xAE\x47\xB4\x7D"
+			  "\x1D\xA8\xBE\x81\x1A\x75\xDA\xAC"
+			  "\xA6\x25\x1E\xEF\x3A\xC0\x6C\x63"
+			  "\xEF\xDC\xC9\x79\x10\x26\xE8\x61"
+			  "\x29\xFC\xA4\x05\xDF\x7D\x5C\x63"
+			  "\x10\x09\x9B\x46\x9B\xF2\x2C\x2B"
+			  "\xFA\x3A\x05\x4C\xFA\xD1\xFF\xFE"
+			  "\xF1\x4C\xE5\xB2\x91\x64\x0C\x51",
+		.rlen	= 496,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 496 - 16, 16 },
+	}, { /* Generated with Crypto++ */
+		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+			  "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+			  "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+			  "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+		.klen	= 32,
+		.iv	= "\xE7\x82\x1D\xB8\x53\x11\xAC\x47"
+			  "\xE2\x7D\x18\xD6\x71\x0C\xA7\x42",
+		.input	= "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+			  "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+			  "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+			  "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+			  "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+			  "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+			  "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+			  "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+			  "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+			  "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+			  "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+			  "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+			  "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+			  "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+			  "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+			  "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+			  "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+			  "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+			  "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+			  "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+			  "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+			  "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+			  "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+			  "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+			  "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+			  "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+			  "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+			  "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+			  "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+			  "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+			  "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+			  "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+			  "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+			  "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+			  "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+			  "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+			  "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+			  "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+			  "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+			  "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+			  "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+			  "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+			  "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+			  "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+			  "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+			  "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+			  "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+			  "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+			  "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+			  "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+			  "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+			  "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+			  "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+			  "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+			  "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+			  "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+			  "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+			  "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+			  "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+			  "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+			  "\xED\x56\xBF\x28\xB4\x1D\x86\x12"
+			  "\x7B\xE4\x4D",
+		.ilen	= 499,
+		.result	= "\xDA\x4E\x3F\xBC\xE8\xB6\x3A\xA2"
+			  "\xD5\x4D\x84\x4A\xA9\x0C\xE1\xA5"
+			  "\xB8\x73\xBC\xF9\xBB\x59\x2F\x44"
+			  "\x8B\xAB\x82\x6C\xB4\x32\x9A\xDE"
+			  "\x5A\x0B\xDB\x7A\x6B\xF2\x38\x9F"
+			  "\x06\xF7\xF7\xFF\xFF\xC0\x8A\x2E"
+			  "\x76\xEA\x06\x32\x23\xF3\x59\x2E"
+			  "\x75\xDE\x71\x86\x3C\x98\x23\x44"
+			  "\x5B\xF2\xFA\x6A\x00\xBB\xC1\xAD"
+			  "\x58\xBD\x3E\x6F\x2E\xB4\x19\x04"
+			  "\x70\x8B\x92\x55\x23\xE9\x6A\x3A"
+			  "\x78\x7A\x1B\x10\x85\x52\x9C\x12"
+			  "\xE4\x55\x81\x21\xCE\x53\xD0\x3B"
+			  "\x63\x77\x2C\x74\xD1\xF5\x60\xF3"
+			  "\xA1\xDE\x44\x3C\x8F\x4D\x2F\xDD"
+			  "\x8A\xFE\x3C\x42\x8E\xD3\xF2\x8E"
+			  "\xA8\x28\x69\x65\x31\xE1\x45\x83"
+			  "\xE4\x49\xC4\x9C\xA7\x28\xAA\x21"
+			  "\xCD\x5D\x0F\x15\xB7\x93\x07\x26"
+			  "\xB0\x65\x6D\x91\x90\x23\x7A\xC6"
+			  "\xDB\x68\xB0\xA1\x8E\xA4\x76\x4E"
+			  "\xC6\x91\x83\x20\x92\x4D\x63\x7A"
+			  "\x45\x18\x18\x74\x19\xAD\x71\x01"
+			  "\x6B\x23\xAD\x9D\x4E\xE4\x6E\x46"
+			  "\xC9\x73\x7A\xF9\x02\x95\xF4\x07"
+			  "\x0E\x7A\xA6\xC5\xAE\xFA\x15\x2C"
+			  "\x51\x71\xF1\xDC\x22\xB6\xAC\xD8"
+			  "\x19\x24\x44\xBC\x0C\xFB\x3C\x2D"
+			  "\xB1\x50\x47\x15\x0E\xDB\xB6\xD7"
+			  "\xE8\x61\xE5\x95\x52\x1E\x3E\x49"
+			  "\x70\xE9\x66\x04\x4C\xE1\xAF\xBD"
+			  "\xDD\x15\x3B\x20\x59\x24\xFF\xB0"
+			  "\x39\xAA\xE7\xBF\x23\xA3\x6E\xD5"
+			  "\x15\xF0\x61\x4F\xAE\x89\x10\x58"
+			  "\x5A\x33\x95\x52\x2A\xB5\x77\x9C"
+			  "\xA5\x43\x80\x40\x27\x2D\xAE\xD9"
+			  "\x3F\xE0\x80\x94\x78\x79\xCB\x7E"
+			  "\xAD\x12\x44\x4C\xEC\x27\xB0\xEE"
+			  "\x0B\x05\x2A\x82\x99\x58\xBB\x7A"
+			  "\x8D\x6D\x9D\x8E\xE2\x8E\xE7\x93"
+			  "\x2F\xB3\x09\x8D\x06\xD5\xEE\x70"
+			  "\x16\xAE\x35\xC5\x52\x0F\x46\x1F"
+			  "\x71\xF9\x5E\xF2\x67\xDC\x98\x2F"
+			  "\xA3\x23\xAA\xD5\xD0\x49\xF4\xA6"
+			  "\xF6\xB8\x32\xCD\xD6\x85\x73\x60"
+			  "\x59\x20\xE7\x55\x0E\x91\xE2\x0C"
+			  "\x3F\x1C\xEB\x3D\xDF\x52\x64\xF2"
+			  "\x7D\x8B\x5D\x63\x16\xB9\xB2\x5D"
+			  "\x5E\xAB\xB2\x97\xAB\x78\x44\xE7"
+			  "\xC6\x72\x20\xC5\x90\x9B\xDC\x5D"
+			  "\xB0\xEF\x44\xEF\x87\x31\x8D\xF4"
+			  "\xFB\x81\x5D\xF7\x96\x96\xD4\x50"
+			  "\x89\xA7\xF6\xB9\x67\x76\x40\x9E"
+			  "\x9D\x40\xD5\x2C\x30\xB8\x01\x8F"
+			  "\xE4\x7B\x71\x48\xA9\xA0\xA0\x1D"
+			  "\x87\x52\xA4\x91\xA9\xD7\xA9\x51"
+			  "\xD9\x59\xF7\xCC\x63\x22\xC1\x8D"
+			  "\x84\x7B\xD8\x22\x32\x5C\x6F\x1D"
+			  "\x6E\x9F\xFA\xDD\x49\x40\xDC\x37"
+			  "\x14\x8C\xE1\x80\x1B\xDD\x36\x2A"
+			  "\xD0\xE9\x54\x99\x5D\xBA\x3B\x11"
+			  "\xD8\xFE\xC9\x5B\x5C\x25\xE5\x76"
+			  "\xFB\xF2\x3F",
+		.rlen	= 499,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 499 - 16, 16 },
+	},
 };
 
 static struct cipher_testvec aes_ctr_dec_tv_template[] = {
@@ -11772,7 +15925,283 @@ static struct cipher_testvec aes_ctr_dec_tv_template[] = {
 			  "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
 			  "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
 		.rlen	= 64,
-	}
+	}, { /* Generated with Crypto++ */
+		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+			  "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+			  "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+			  "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+		.klen	= 32,
+		.iv	= "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+			  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD",
+		.input	= "\x04\xF3\xD3\x88\x17\xEF\xDC\xEF"
+			  "\x8B\x04\xF8\x3A\x66\x8D\x1A\x53"
+			  "\x57\x1F\x4B\x23\xE4\xA0\xAF\xF9"
+			  "\x69\x95\x35\x98\x8D\x4D\x8C\xC1"
+			  "\xF0\xB2\x7F\x80\xBB\x54\x28\xA2"
+			  "\x7A\x1B\x9F\x77\xEC\x0E\x6E\xDE"
+			  "\xF0\xEC\xB8\xE4\x20\x62\xEE\xDB"
+			  "\x5D\xF5\xDD\xE3\x54\xFC\xDD\xEB"
+			  "\x6A\xEE\x65\xA1\x21\xD6\xD7\x81"
+			  "\x47\x61\x12\x4D\xC2\x8C\xFA\x78"
+			  "\x1F\x28\x02\x01\xC3\xFC\x1F\xEC"
+			  "\x0F\x10\x4F\xB3\x12\x45\xC6\x3B"
+			  "\x7E\x08\xF9\x5A\xD0\x5D\x73\x2D"
+			  "\x58\xA4\xE5\xCB\x1C\xB4\xCE\x74"
+			  "\x32\x41\x1F\x31\x9C\x08\xA2\x5D"
+			  "\x67\xEB\x72\x1D\xF8\xE7\x70\x54"
+			  "\x34\x4B\x31\x69\x84\x66\x96\x44"
+			  "\x56\xCC\x1E\xD9\xE6\x13\x6A\xB9"
+			  "\x2D\x0A\x05\x45\x2D\x90\xCC\xDF"
+			  "\x16\x5C\x5F\x79\x34\x52\x54\xFE"
+			  "\xFE\xCD\xAD\x04\x2E\xAD\x86\x06"
+			  "\x1F\x37\xE8\x28\xBC\xD3\x8F\x5B"
+			  "\x92\x66\x87\x3B\x8A\x0A\x1A\xCC"
+			  "\x6E\xAB\x9F\x0B\xFA\x5C\xE6\xFD"
+			  "\x3C\x98\x08\x12\xEC\xAA\x9E\x11"
+			  "\xCA\xB2\x1F\xCE\x5E\x5B\xB2\x72"
+			  "\x9C\xCC\x5D\xC5\xE0\x32\xC0\x56"
+			  "\xD5\x45\x16\xD2\xAF\x13\x66\xF7"
+			  "\x8C\x67\xAC\x79\xB2\xAF\x56\x27"
+			  "\x3F\xCC\xFE\xCB\x1E\xC0\x75\xF1"
+			  "\xA7\xC9\xC3\x1D\x8E\xDD\xF9\xD4"
+			  "\x42\xC8\x21\x08\x16\xF7\x01\xD7"
+			  "\xAC\x8E\x3F\x1D\x56\xC1\x06\xE4"
+			  "\x9C\x62\xD6\xA5\x6A\x50\x44\xB3"
+			  "\x35\x1C\x82\xB9\x10\xF9\x42\xA1"
+			  "\xFC\x74\x9B\x44\x4F\x25\x02\xE3"
+			  "\x08\xF5\xD4\x32\x39\x08\x11\xE8"
+			  "\xD2\x6B\x50\x53\xD4\x08\xD1\x6B"
+			  "\x3A\x4A\x68\x7B\x7C\xCD\x46\x5E"
+			  "\x0D\x07\x19\xDB\x67\xD7\x98\x91"
+			  "\xD7\x17\x10\x9B\x7B\x8A\x9B\x33"
+			  "\xAE\xF3\x00\xA6\xD4\x15\xD9\xEA"
+			  "\x85\x99\x22\xE8\x91\x38\x70\x83"
+			  "\x93\x01\x24\x6C\xFA\x9A\xB9\x07"
+			  "\xEA\x8D\x3B\xD9\x2A\x43\x59\x16"
+			  "\x2F\x69\xEE\x84\x36\x44\x76\x98"
+			  "\xF3\x04\x2A\x7C\x74\x3D\x29\x2B"
+			  "\x0D\xAD\x8F\x44\x82\x9E\x57\x8D"
+			  "\xAC\xED\x18\x1F\x50\xA4\xF5\x98"
+			  "\x1F\xBD\x92\x91\x1B\x2D\xA6\xD6"
+			  "\xD2\xE3\x02\xAA\x92\x3B\xC6\xB3"
+			  "\x1B\x39\x72\xD5\x26\xCA\x04\xE0"
+			  "\xFC\x58\x78\xBB\xB1\x3F\xA1\x9C"
+			  "\x42\x24\x3E\x2E\x22\xBB\x4B\xBA"
+			  "\xF4\x52\x0A\xE6\xAE\x47\xB4\x7D"
+			  "\x1D\xA8\xBE\x81\x1A\x75\xDA\xAC"
+			  "\xA6\x25\x1E\xEF\x3A\xC0\x6C\x63"
+			  "\xEF\xDC\xC9\x79\x10\x26\xE8\x61"
+			  "\x29\xFC\xA4\x05\xDF\x7D\x5C\x63"
+			  "\x10\x09\x9B\x46\x9B\xF2\x2C\x2B"
+			  "\xFA\x3A\x05\x4C\xFA\xD1\xFF\xFE"
+			  "\xF1\x4C\xE5\xB2\x91\x64\x0C\x51",
+		.ilen	= 496,
+		.result	= "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+			  "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+			  "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+			  "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+			  "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+			  "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+			  "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+			  "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+			  "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+			  "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+			  "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+			  "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+			  "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+			  "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+			  "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+			  "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+			  "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+			  "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+			  "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+			  "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+			  "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+			  "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+			  "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+			  "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+			  "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+			  "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+			  "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+			  "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+			  "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+			  "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+			  "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+			  "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+			  "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+			  "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+			  "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+			  "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+			  "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+			  "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+			  "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+			  "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+			  "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+			  "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+			  "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+			  "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+			  "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+			  "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+			  "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+			  "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+			  "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+			  "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+			  "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+			  "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+			  "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+			  "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+			  "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+			  "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+			  "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+			  "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+			  "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+			  "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+			  "\xED\x56\xBF\x28\xB4\x1D\x86\x12",
+		.rlen	= 496,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 496 - 16, 16 },
+	}, { /* Generated with Crypto++ */
+		.key	= "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
+			  "\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
+			  "\xBE\xE1\x04\x27\xE1\x04\x27\x4A"
+			  "\x6D\x90\x4A\x6D\x90\xB3\xD6\xF9",
+		.klen	= 32,
+		.iv	= "\xE7\x82\x1D\xB8\x53\x11\xAC\x47"
+			  "\xE2\x7D\x18\xD6\x71\x0C\xA7\x42",
+		.input	= "\xDA\x4E\x3F\xBC\xE8\xB6\x3A\xA2"
+			  "\xD5\x4D\x84\x4A\xA9\x0C\xE1\xA5"
+			  "\xB8\x73\xBC\xF9\xBB\x59\x2F\x44"
+			  "\x8B\xAB\x82\x6C\xB4\x32\x9A\xDE"
+			  "\x5A\x0B\xDB\x7A\x6B\xF2\x38\x9F"
+			  "\x06\xF7\xF7\xFF\xFF\xC0\x8A\x2E"
+			  "\x76\xEA\x06\x32\x23\xF3\x59\x2E"
+			  "\x75\xDE\x71\x86\x3C\x98\x23\x44"
+			  "\x5B\xF2\xFA\x6A\x00\xBB\xC1\xAD"
+			  "\x58\xBD\x3E\x6F\x2E\xB4\x19\x04"
+			  "\x70\x8B\x92\x55\x23\xE9\x6A\x3A"
+			  "\x78\x7A\x1B\x10\x85\x52\x9C\x12"
+			  "\xE4\x55\x81\x21\xCE\x53\xD0\x3B"
+			  "\x63\x77\x2C\x74\xD1\xF5\x60\xF3"
+			  "\xA1\xDE\x44\x3C\x8F\x4D\x2F\xDD"
+			  "\x8A\xFE\x3C\x42\x8E\xD3\xF2\x8E"
+			  "\xA8\x28\x69\x65\x31\xE1\x45\x83"
+			  "\xE4\x49\xC4\x9C\xA7\x28\xAA\x21"
+			  "\xCD\x5D\x0F\x15\xB7\x93\x07\x26"
+			  "\xB0\x65\x6D\x91\x90\x23\x7A\xC6"
+			  "\xDB\x68\xB0\xA1\x8E\xA4\x76\x4E"
+			  "\xC6\x91\x83\x20\x92\x4D\x63\x7A"
+			  "\x45\x18\x18\x74\x19\xAD\x71\x01"
+			  "\x6B\x23\xAD\x9D\x4E\xE4\x6E\x46"
+			  "\xC9\x73\x7A\xF9\x02\x95\xF4\x07"
+			  "\x0E\x7A\xA6\xC5\xAE\xFA\x15\x2C"
+			  "\x51\x71\xF1\xDC\x22\xB6\xAC\xD8"
+			  "\x19\x24\x44\xBC\x0C\xFB\x3C\x2D"
+			  "\xB1\x50\x47\x15\x0E\xDB\xB6\xD7"
+			  "\xE8\x61\xE5\x95\x52\x1E\x3E\x49"
+			  "\x70\xE9\x66\x04\x4C\xE1\xAF\xBD"
+			  "\xDD\x15\x3B\x20\x59\x24\xFF\xB0"
+			  "\x39\xAA\xE7\xBF\x23\xA3\x6E\xD5"
+			  "\x15\xF0\x61\x4F\xAE\x89\x10\x58"
+			  "\x5A\x33\x95\x52\x2A\xB5\x77\x9C"
+			  "\xA5\x43\x80\x40\x27\x2D\xAE\xD9"
+			  "\x3F\xE0\x80\x94\x78\x79\xCB\x7E"
+			  "\xAD\x12\x44\x4C\xEC\x27\xB0\xEE"
+			  "\x0B\x05\x2A\x82\x99\x58\xBB\x7A"
+			  "\x8D\x6D\x9D\x8E\xE2\x8E\xE7\x93"
+			  "\x2F\xB3\x09\x8D\x06\xD5\xEE\x70"
+			  "\x16\xAE\x35\xC5\x52\x0F\x46\x1F"
+			  "\x71\xF9\x5E\xF2\x67\xDC\x98\x2F"
+			  "\xA3\x23\xAA\xD5\xD0\x49\xF4\xA6"
+			  "\xF6\xB8\x32\xCD\xD6\x85\x73\x60"
+			  "\x59\x20\xE7\x55\x0E\x91\xE2\x0C"
+			  "\x3F\x1C\xEB\x3D\xDF\x52\x64\xF2"
+			  "\x7D\x8B\x5D\x63\x16\xB9\xB2\x5D"
+			  "\x5E\xAB\xB2\x97\xAB\x78\x44\xE7"
+			  "\xC6\x72\x20\xC5\x90\x9B\xDC\x5D"
+			  "\xB0\xEF\x44\xEF\x87\x31\x8D\xF4"
+			  "\xFB\x81\x5D\xF7\x96\x96\xD4\x50"
+			  "\x89\xA7\xF6\xB9\x67\x76\x40\x9E"
+			  "\x9D\x40\xD5\x2C\x30\xB8\x01\x8F"
+			  "\xE4\x7B\x71\x48\xA9\xA0\xA0\x1D"
+			  "\x87\x52\xA4\x91\xA9\xD7\xA9\x51"
+			  "\xD9\x59\xF7\xCC\x63\x22\xC1\x8D"
+			  "\x84\x7B\xD8\x22\x32\x5C\x6F\x1D"
+			  "\x6E\x9F\xFA\xDD\x49\x40\xDC\x37"
+			  "\x14\x8C\xE1\x80\x1B\xDD\x36\x2A"
+			  "\xD0\xE9\x54\x99\x5D\xBA\x3B\x11"
+			  "\xD8\xFE\xC9\x5B\x5C\x25\xE5\x76"
+			  "\xFB\xF2\x3F",
+		.ilen	= 499,
+		.result	= "\x50\xB9\x22\xAE\x17\x80\x0C\x75"
+			  "\xDE\x47\xD3\x3C\xA5\x0E\x9A\x03"
+			  "\x6C\xF8\x61\xCA\x33\xBF\x28\x91"
+			  "\x1D\x86\xEF\x58\xE4\x4D\xB6\x1F"
+			  "\xAB\x14\x7D\x09\x72\xDB\x44\xD0"
+			  "\x39\xA2\x0B\x97\x00\x69\xF5\x5E"
+			  "\xC7\x30\xBC\x25\x8E\x1A\x83\xEC"
+			  "\x55\xE1\x4A\xB3\x1C\xA8\x11\x7A"
+			  "\x06\x6F\xD8\x41\xCD\x36\x9F\x08"
+			  "\x94\xFD\x66\xF2\x5B\xC4\x2D\xB9"
+			  "\x22\x8B\x17\x80\xE9\x52\xDE\x47"
+			  "\xB0\x19\xA5\x0E\x77\x03\x6C\xD5"
+			  "\x3E\xCA\x33\x9C\x05\x91\xFA\x63"
+			  "\xEF\x58\xC1\x2A\xB6\x1F\x88\x14"
+			  "\x7D\xE6\x4F\xDB\x44\xAD\x16\xA2"
+			  "\x0B\x74\x00\x69\xD2\x3B\xC7\x30"
+			  "\x99\x02\x8E\xF7\x60\xEC\x55\xBE"
+			  "\x27\xB3\x1C\x85\x11\x7A\xE3\x4C"
+			  "\xD8\x41\xAA\x13\x9F\x08\x71\xFD"
+			  "\x66\xCF\x38\xC4\x2D\x96\x22\x8B"
+			  "\xF4\x5D\xE9\x52\xBB\x24\xB0\x19"
+			  "\x82\x0E\x77\xE0\x49\xD5\x3E\xA7"
+			  "\x10\x9C\x05\x6E\xFA\x63\xCC\x35"
+			  "\xC1\x2A\x93\x1F\x88\xF1\x5A\xE6"
+			  "\x4F\xB8\x21\xAD\x16\x7F\x0B\x74"
+			  "\xDD\x46\xD2\x3B\xA4\x0D\x99\x02"
+			  "\x6B\xF7\x60\xC9\x32\xBE\x27\x90"
+			  "\x1C\x85\xEE\x57\xE3\x4C\xB5\x1E"
+			  "\xAA\x13\x7C\x08\x71\xDA\x43\xCF"
+			  "\x38\xA1\x0A\x96\xFF\x68\xF4\x5D"
+			  "\xC6\x2F\xBB\x24\x8D\x19\x82\xEB"
+			  "\x54\xE0\x49\xB2\x1B\xA7\x10\x79"
+			  "\x05\x6E\xD7\x40\xCC\x35\x9E\x07"
+			  "\x93\xFC\x65\xF1\x5A\xC3\x2C\xB8"
+			  "\x21\x8A\x16\x7F\xE8\x51\xDD\x46"
+			  "\xAF\x18\xA4\x0D\x76\x02\x6B\xD4"
+			  "\x3D\xC9\x32\x9B\x04\x90\xF9\x62"
+			  "\xEE\x57\xC0\x29\xB5\x1E\x87\x13"
+			  "\x7C\xE5\x4E\xDA\x43\xAC\x15\xA1"
+			  "\x0A\x73\xFF\x68\xD1\x3A\xC6\x2F"
+			  "\x98\x01\x8D\xF6\x5F\xEB\x54\xBD"
+			  "\x26\xB2\x1B\x84\x10\x79\xE2\x4B"
+			  "\xD7\x40\xA9\x12\x9E\x07\x70\xFC"
+			  "\x65\xCE\x37\xC3\x2C\x95\x21\x8A"
+			  "\xF3\x5C\xE8\x51\xBA\x23\xAF\x18"
+			  "\x81\x0D\x76\xDF\x48\xD4\x3D\xA6"
+			  "\x0F\x9B\x04\x6D\xF9\x62\xCB\x34"
+			  "\xC0\x29\x92\x1E\x87\xF0\x59\xE5"
+			  "\x4E\xB7\x20\xAC\x15\x7E\x0A\x73"
+			  "\xDC\x45\xD1\x3A\xA3\x0C\x98\x01"
+			  "\x6A\xF6\x5F\xC8\x31\xBD\x26\x8F"
+			  "\x1B\x84\xED\x56\xE2\x4B\xB4\x1D"
+			  "\xA9\x12\x7B\x07\x70\xD9\x42\xCE"
+			  "\x37\xA0\x09\x95\xFE\x67\xF3\x5C"
+			  "\xC5\x2E\xBA\x23\x8C\x18\x81\xEA"
+			  "\x53\xDF\x48\xB1\x1A\xA6\x0F\x78"
+			  "\x04\x6D\xD6\x3F\xCB\x34\x9D\x06"
+			  "\x92\xFB\x64\xF0\x59\xC2\x2B\xB7"
+			  "\x20\x89\x15\x7E\xE7\x50\xDC\x45"
+			  "\xAE\x17\xA3\x0C\x75\x01\x6A\xD3"
+			  "\x3C\xC8\x31\x9A\x03\x8F\xF8\x61"
+			  "\xED\x56\xBF\x28\xB4\x1D\x86\x12"
+			  "\x7B\xE4\x4D",
+		.rlen	= 499,
+		.also_non_np = 1,
+		.np	= 2,
+		.tap	= { 499 - 16, 16 },
+	},
 };
 
 static struct cipher_testvec aes_ctr_rfc3686_enc_tv_template[] = {
@@ -16291,8 +20720,7 @@ static struct cipher_testvec camellia_enc_tv_template[] = {
 		.result	= "\x9a\xcc\x23\x7d\xff\x16\xd7\x6c"
 			  "\x20\xef\x7c\x91\x9e\x3a\x75\x09",
 		.rlen	= 16,
-	},
-	{ /* Generated with Crypto++ */
+	}, { /* Generated with Crypto++ */
 		.key	= "\x3F\x85\x62\x3F\x1C\xF9\xD6\x1C"
 			  "\xF9\xD6\xB3\x90\x6D\x4A\x90\x6D"
 			  "\x4A\x27\x04\xE1\x27\x04\xE1\xBE"
@@ -16303,18 +20731,130 @@ static struct cipher_testvec camellia_enc_tv_template[] = {
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
 			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
 			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-		.ilen	= 48,
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.ilen	= 496,
 		.result	= "\xED\xCD\xDB\xB8\x68\xCE\xBD\xEA"
 			  "\x9D\x9D\xCD\x9F\x4F\xFC\x4D\xB7"
 			  "\xA5\xFF\x6F\x43\x0F\xBA\x32\x04"
 			  "\xB3\xC2\xB9\x03\xAA\x91\x56\x29"
 			  "\x0D\xD0\xFD\xC4\x65\xA5\x69\xB9"
-			  "\xF1\xF6\xB1\xA5\xB2\x75\x4F\x8A",
-		.rlen	= 48,
+			  "\xF1\xF6\xB1\xA5\xB2\x75\x4F\x8A"
+			  "\x8D\x7D\x1B\x9B\xC7\x68\x72\xF8"
+			  "\x01\x9B\x17\x0A\x29\xE7\x61\x28"
+			  "\x7F\xA7\x50\xCA\x20\x2C\x96\x3B"
+			  "\x6E\x5C\x5D\x3F\xB5\x7F\xF3\x2B"
+			  "\x04\xEF\x9D\xD4\xCE\x41\x28\x8E"
+			  "\x83\x54\xAE\x7C\x82\x46\x10\xC9"
+			  "\xC4\x8A\x1E\x1F\x4C\xA9\xFC\xEC"
+			  "\x3C\x8C\x30\xFC\x59\xD2\x54\xC4"
+			  "\x6F\x50\xC6\xCA\x8C\x14\x5B\x9C"
+			  "\x18\x56\x5B\xF8\x33\x0E\x4A\xDB"
+			  "\xEC\xB5\x6E\x5B\x31\xC4\x0E\x98"
+			  "\x9F\x32\xBA\xA2\x18\xCF\x55\x43"
+			  "\xFE\x80\x8F\x60\xCF\x05\x30\x9B"
+			  "\x70\x50\x1E\x9C\x08\x87\xE6\x20"
+			  "\xD2\xF3\x27\xF8\x2A\x8D\x12\xB2"
+			  "\xBC\x5F\xFE\x52\x52\xF6\x7F\xB6"
+			  "\xB8\x30\x86\x3B\x0F\x94\x1E\x79"
+			  "\x13\x94\x35\xA2\xB1\x35\x5B\x05"
+			  "\x2A\x98\x6B\x96\x4C\xB1\x20\xBE"
+			  "\xB6\x14\xC2\x06\xBF\xFD\x5F\x2A"
+			  "\xF5\x33\xC8\x19\x45\x14\x44\x5D"
+			  "\xFE\x94\x7B\xBB\x63\x13\x57\xC3"
+			  "\x2A\x8F\x6C\x11\x2A\x07\xA7\x6A"
+			  "\xBF\x20\xD3\x99\xC6\x00\x0B\xBF"
+			  "\x83\x46\x25\x3A\xB0\xF6\xC5\xC8"
+			  "\x00\xCA\xE5\x28\x4A\x7C\x95\x9C"
+			  "\x7B\x43\xAB\xF9\xE4\xF8\x74\xAB"
+			  "\xA7\xB8\x9C\x0F\x53\x7B\xB6\x74"
+			  "\x60\x64\x0D\x1C\x80\xD1\x20\x9E"
+			  "\xDC\x14\x27\x9B\xFC\xBD\x5C\x96"
+			  "\xD2\x51\xDC\x96\xEE\xE5\xEA\x2B"
+			  "\x02\x7C\xAA\x3C\xDC\x9D\x7B\x01"
+			  "\x20\xC3\xE1\x0B\xDD\xAB\xF3\x1E"
+			  "\x19\xA8\x84\x29\x5F\xCC\xC3\x5B"
+			  "\xE4\x33\x59\xDC\x12\xEB\x2B\x4D"
+			  "\x5B\x55\x23\xB7\x40\x31\xDE\xEE"
+			  "\x18\xC9\x3C\x4D\xBC\xED\xE0\x42"
+			  "\xAD\xDE\xA0\xA3\xC3\xFE\x44\xD3"
+			  "\xE1\x9A\xDA\xAB\x32\xFC\x1A\xBF"
+			  "\x63\xA9\xF0\x6A\x08\x46\xBD\x48"
+			  "\x83\x06\xAB\x82\x99\x01\x16\x1A"
+			  "\x03\x36\xC5\x59\x6B\xB8\x8C\x9F"
+			  "\xC6\x51\x3D\xE5\x7F\xBF\xAB\xBC"
+			  "\xC9\xA1\x88\x34\x5F\xA9\x7C\x3B"
+			  "\x9F\x1B\x98\x2B\x4F\xFB\x9B\xF0"
+			  "\xCD\xB6\x45\xB2\x29\x2E\x34\x23"
+			  "\xA9\x97\xC0\x22\x8C\x42\x9B\x5F"
+			  "\x40\xC8\xD7\x3D\x82\x9A\x6F\xAA"
+			  "\x74\x83\x29\x05\xE8\xC4\x4D\x01"
+			  "\xB5\xE5\x84\x3F\x7F\xD3\xE0\x99"
+			  "\xDA\xE7\x6F\x30\xFD\xAA\x92\x30"
+			  "\xA5\x46\x8B\xA2\xE6\x58\x62\x7C"
+			  "\x2C\x35\x1B\x38\x85\x7D\xE8\xF3"
+			  "\x87\x4F\xDA\xD8\x5F\xFC\xB6\x44"
+			  "\xD0\xE3\x9B\x8B\xBF\xD6\xB8\xC4"
+			  "\x73\xAE\x1D\x8B\x5B\x74\x8B\xCB",
+		.rlen	= 496,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 48 - 16, 16 },
+		.tap	= { 496 - 16, 16 },
 	},
 };
 
@@ -16352,8 +20892,7 @@ static struct cipher_testvec camellia_dec_tv_template[] = {
 		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xef"
 			  "\xfe\xdc\xba\x98\x76\x54\x32\x10",
 		.rlen	= 16,
-	},
-	{ /* Generated with Crypto++ */
+	}, { /* Generated with Crypto++ */
 		.key	= "\x3F\x85\x62\x3F\x1C\xF9\xD6\x1C"
 			  "\xF9\xD6\xB3\x90\x6D\x4A\x90\x6D"
 			  "\x4A\x27\x04\xE1\x27\x04\xE1\xBE"
@@ -16364,18 +20903,130 @@ static struct cipher_testvec camellia_dec_tv_template[] = {
 			  "\xA5\xFF\x6F\x43\x0F\xBA\x32\x04"
 			  "\xB3\xC2\xB9\x03\xAA\x91\x56\x29"
 			  "\x0D\xD0\xFD\xC4\x65\xA5\x69\xB9"
-			  "\xF1\xF6\xB1\xA5\xB2\x75\x4F\x8A",
-		.ilen	= 48,
+			  "\xF1\xF6\xB1\xA5\xB2\x75\x4F\x8A"
+			  "\x8D\x7D\x1B\x9B\xC7\x68\x72\xF8"
+			  "\x01\x9B\x17\x0A\x29\xE7\x61\x28"
+			  "\x7F\xA7\x50\xCA\x20\x2C\x96\x3B"
+			  "\x6E\x5C\x5D\x3F\xB5\x7F\xF3\x2B"
+			  "\x04\xEF\x9D\xD4\xCE\x41\x28\x8E"
+			  "\x83\x54\xAE\x7C\x82\x46\x10\xC9"
+			  "\xC4\x8A\x1E\x1F\x4C\xA9\xFC\xEC"
+			  "\x3C\x8C\x30\xFC\x59\xD2\x54\xC4"
+			  "\x6F\x50\xC6\xCA\x8C\x14\x5B\x9C"
+			  "\x18\x56\x5B\xF8\x33\x0E\x4A\xDB"
+			  "\xEC\xB5\x6E\x5B\x31\xC4\x0E\x98"
+			  "\x9F\x32\xBA\xA2\x18\xCF\x55\x43"
+			  "\xFE\x80\x8F\x60\xCF\x05\x30\x9B"
+			  "\x70\x50\x1E\x9C\x08\x87\xE6\x20"
+			  "\xD2\xF3\x27\xF8\x2A\x8D\x12\xB2"
+			  "\xBC\x5F\xFE\x52\x52\xF6\x7F\xB6"
+			  "\xB8\x30\x86\x3B\x0F\x94\x1E\x79"
+			  "\x13\x94\x35\xA2\xB1\x35\x5B\x05"
+			  "\x2A\x98\x6B\x96\x4C\xB1\x20\xBE"
+			  "\xB6\x14\xC2\x06\xBF\xFD\x5F\x2A"
+			  "\xF5\x33\xC8\x19\x45\x14\x44\x5D"
+			  "\xFE\x94\x7B\xBB\x63\x13\x57\xC3"
+			  "\x2A\x8F\x6C\x11\x2A\x07\xA7\x6A"
+			  "\xBF\x20\xD3\x99\xC6\x00\x0B\xBF"
+			  "\x83\x46\x25\x3A\xB0\xF6\xC5\xC8"
+			  "\x00\xCA\xE5\x28\x4A\x7C\x95\x9C"
+			  "\x7B\x43\xAB\xF9\xE4\xF8\x74\xAB"
+			  "\xA7\xB8\x9C\x0F\x53\x7B\xB6\x74"
+			  "\x60\x64\x0D\x1C\x80\xD1\x20\x9E"
+			  "\xDC\x14\x27\x9B\xFC\xBD\x5C\x96"
+			  "\xD2\x51\xDC\x96\xEE\xE5\xEA\x2B"
+			  "\x02\x7C\xAA\x3C\xDC\x9D\x7B\x01"
+			  "\x20\xC3\xE1\x0B\xDD\xAB\xF3\x1E"
+			  "\x19\xA8\x84\x29\x5F\xCC\xC3\x5B"
+			  "\xE4\x33\x59\xDC\x12\xEB\x2B\x4D"
+			  "\x5B\x55\x23\xB7\x40\x31\xDE\xEE"
+			  "\x18\xC9\x3C\x4D\xBC\xED\xE0\x42"
+			  "\xAD\xDE\xA0\xA3\xC3\xFE\x44\xD3"
+			  "\xE1\x9A\xDA\xAB\x32\xFC\x1A\xBF"
+			  "\x63\xA9\xF0\x6A\x08\x46\xBD\x48"
+			  "\x83\x06\xAB\x82\x99\x01\x16\x1A"
+			  "\x03\x36\xC5\x59\x6B\xB8\x8C\x9F"
+			  "\xC6\x51\x3D\xE5\x7F\xBF\xAB\xBC"
+			  "\xC9\xA1\x88\x34\x5F\xA9\x7C\x3B"
+			  "\x9F\x1B\x98\x2B\x4F\xFB\x9B\xF0"
+			  "\xCD\xB6\x45\xB2\x29\x2E\x34\x23"
+			  "\xA9\x97\xC0\x22\x8C\x42\x9B\x5F"
+			  "\x40\xC8\xD7\x3D\x82\x9A\x6F\xAA"
+			  "\x74\x83\x29\x05\xE8\xC4\x4D\x01"
+			  "\xB5\xE5\x84\x3F\x7F\xD3\xE0\x99"
+			  "\xDA\xE7\x6F\x30\xFD\xAA\x92\x30"
+			  "\xA5\x46\x8B\xA2\xE6\x58\x62\x7C"
+			  "\x2C\x35\x1B\x38\x85\x7D\xE8\xF3"
+			  "\x87\x4F\xDA\xD8\x5F\xFC\xB6\x44"
+			  "\xD0\xE3\x9B\x8B\xBF\xD6\xB8\xC4"
+			  "\x73\xAE\x1D\x8B\x5B\x74\x8B\xCB",
+		.ilen	= 496,
 		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
 			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
 			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
 			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-		.rlen	= 48,
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.rlen	= 496,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 48 - 16, 16 },
+		.tap	= { 496 - 16, 16 },
 	},
 };
 
@@ -16407,8 +21058,7 @@ static struct cipher_testvec camellia_cbc_enc_tv_template[] = {
 			  "\x19\xb4\x3e\x57\x1c\x02\x5e\xa0"
 			  "\x15\x78\xe0\x5e\xf2\xcb\x87\x16",
 		.rlen   = 32,
-	},
-	{ /* Generated with Crypto++ */
+	}, { /* Generated with Crypto++ */
 		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
 			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
 			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
@@ -16421,18 +21071,130 @@ static struct cipher_testvec camellia_cbc_enc_tv_template[] = {
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
 			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
 			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-		.ilen	= 48,
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.ilen	= 496,
 		.result	= "\xCD\x3E\x2A\x3B\x3E\x94\xC5\x77"
 			  "\xBA\xBB\x5B\xB1\xDE\x7B\xA4\x40"
 			  "\x88\x39\xE3\xFD\x94\x4B\x25\x58"
 			  "\xE1\x4B\xC4\x18\x7A\xFD\x17\x2B"
 			  "\xB9\xF9\xC2\x27\x6A\xB6\x31\x27"
-			  "\xA6\xAD\xEF\xE5\x5D\xE4\x02\x01",
-		.rlen	= 48,
+			  "\xA6\xAD\xEF\xE5\x5D\xE4\x02\x01"
+			  "\x56\x2E\x10\xC2\x2C\xFF\xC6\x83"
+			  "\xB5\xDC\x4F\x63\xAD\x0E\x63\x5E"
+			  "\x56\xC8\x18\x3D\x79\x86\x97\xEF"
+			  "\x57\x0E\x63\xA1\xC1\x41\x48\xB8"
+			  "\x98\xB7\x51\x6D\x18\xF6\x19\x82"
+			  "\x37\x49\x88\xA4\xEF\x91\x21\x47"
+			  "\x03\x28\xEA\x42\xF4\xFB\x7A\x58"
+			  "\x28\x90\x77\x46\xD8\xD2\x35\x16"
+			  "\x44\xA9\x9E\x49\x52\x2A\xE4\x16"
+			  "\x5D\xF7\x65\xEB\x0F\xC9\x29\xE6"
+			  "\xCF\x76\x91\x89\x8A\x94\x39\xFA"
+			  "\x6B\x5F\x63\x53\x74\x43\x91\xF5"
+			  "\x3F\xBC\x88\x53\xB2\x1A\x02\x3F"
+			  "\x9D\x32\x84\xEB\x56\x28\xD6\x06"
+			  "\xD5\xB2\x20\xA9\xFC\xC3\x76\x62"
+			  "\x32\xCC\x86\xC8\x36\x67\x5E\x7E"
+			  "\xA4\xAA\x15\x63\x6B\xA9\x86\xAF"
+			  "\x1A\x52\x82\x36\x5F\xF4\x3F\x7A"
+			  "\x9B\x78\x62\x3B\x02\x28\x60\xB3"
+			  "\xBA\x82\xB1\xDD\xC9\x60\x8F\x47"
+			  "\xF1\x6B\xFE\xE5\x39\x34\xA0\x28"
+			  "\xA4\xB3\xC9\x7E\xED\x28\x8D\x70"
+			  "\xB2\x1D\xFD\xC6\x00\xCF\x1A\x94"
+			  "\x28\xF8\xC1\x34\xB7\x58\xA5\x6C"
+			  "\x1A\x9D\xE4\xE4\xF6\xB9\xB4\xB0"
+			  "\x5D\x51\x54\x9A\x53\xA0\xF9\x32"
+			  "\xBD\x31\x54\x14\x7B\x33\xEE\x17"
+			  "\xD3\xC7\x1F\x48\xBF\x0B\x22\xA2"
+			  "\x7D\x0C\xDF\xD0\x2E\x98\xFA\xD2"
+			  "\xFA\xCF\x24\x1D\x99\x9B\xD0\x7E"
+			  "\xF4\x4F\x88\xFF\x45\x99\x4A\xF4"
+			  "\xF2\x0A\x5B\x3B\x21\xAB\x92\xAE"
+			  "\x40\x78\x91\x95\xC4\x2F\xA3\xE8"
+			  "\x18\xC7\x07\xA6\xC8\xC0\x66\x33"
+			  "\x35\xC0\xB4\xA0\xF8\xEE\x1E\xF3"
+			  "\x40\xF5\x40\x54\xF1\x84\x8C\xEA"
+			  "\x27\x38\x1F\xF8\x77\xC7\xDF\xD8"
+			  "\x1D\xE2\xD9\x59\x40\x4F\x59\xD4"
+			  "\xF8\x17\x99\x8D\x58\x2D\x72\x44"
+			  "\x9D\x1D\x91\x64\xD6\x3F\x0A\x82"
+			  "\xC7\x57\x3D\xEF\xD3\x41\xFA\xA7"
+			  "\x68\xA3\xB8\xA5\x93\x74\x2E\x85"
+			  "\x4C\x9D\x69\x59\xCE\x15\xAE\xBF"
+			  "\x9C\x8F\x14\x64\x5D\x7F\xCF\x0B"
+			  "\xCE\x43\x5D\x28\xC0\x2F\xFB\x18"
+			  "\x79\x9A\xFC\x43\x16\x7C\x6B\x7B"
+			  "\x38\xB8\x48\x36\x66\x4E\x20\x43"
+			  "\xBA\x76\x13\x9A\xC3\xF2\xEB\x52"
+			  "\xD7\xDC\xB2\x67\x63\x14\x25\xCD"
+			  "\xB1\x13\x4B\xDE\x8C\x59\x21\x84"
+			  "\x81\x8D\x97\x23\x45\x33\x7C\xF3"
+			  "\xC5\xBC\x79\x95\xAA\x84\x68\x31"
+			  "\x2D\x1A\x68\xFE\xEC\x92\x94\xDA"
+			  "\x94\x2A\x6F\xD6\xFE\xE5\x76\x97"
+			  "\xF4\x6E\xEE\xCB\x2B\x95\x4E\x36"
+			  "\x5F\x74\x8C\x86\x5B\x71\xD0\x20",
+		.rlen	= 496,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 48 - 16, 16 },
+		.tap	= { 496 - 16, 16 },
 	},
 };
 
@@ -16464,8 +21226,7 @@ static struct cipher_testvec camellia_cbc_dec_tv_template[] = {
 			  "\x10\x11\x12\x13\x14\x15\x16\x17"
 			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
 		.rlen   = 32,
-	},
-	{ /* Generated with Crypto++ */
+	}, { /* Generated with Crypto++ */
 		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
 			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
 			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
@@ -16478,18 +21239,130 @@ static struct cipher_testvec camellia_cbc_dec_tv_template[] = {
 			  "\x88\x39\xE3\xFD\x94\x4B\x25\x58"
 			  "\xE1\x4B\xC4\x18\x7A\xFD\x17\x2B"
 			  "\xB9\xF9\xC2\x27\x6A\xB6\x31\x27"
-			  "\xA6\xAD\xEF\xE5\x5D\xE4\x02\x01",
-		.ilen	= 48,
+			  "\xA6\xAD\xEF\xE5\x5D\xE4\x02\x01"
+			  "\x56\x2E\x10\xC2\x2C\xFF\xC6\x83"
+			  "\xB5\xDC\x4F\x63\xAD\x0E\x63\x5E"
+			  "\x56\xC8\x18\x3D\x79\x86\x97\xEF"
+			  "\x57\x0E\x63\xA1\xC1\x41\x48\xB8"
+			  "\x98\xB7\x51\x6D\x18\xF6\x19\x82"
+			  "\x37\x49\x88\xA4\xEF\x91\x21\x47"
+			  "\x03\x28\xEA\x42\xF4\xFB\x7A\x58"
+			  "\x28\x90\x77\x46\xD8\xD2\x35\x16"
+			  "\x44\xA9\x9E\x49\x52\x2A\xE4\x16"
+			  "\x5D\xF7\x65\xEB\x0F\xC9\x29\xE6"
+			  "\xCF\x76\x91\x89\x8A\x94\x39\xFA"
+			  "\x6B\x5F\x63\x53\x74\x43\x91\xF5"
+			  "\x3F\xBC\x88\x53\xB2\x1A\x02\x3F"
+			  "\x9D\x32\x84\xEB\x56\x28\xD6\x06"
+			  "\xD5\xB2\x20\xA9\xFC\xC3\x76\x62"
+			  "\x32\xCC\x86\xC8\x36\x67\x5E\x7E"
+			  "\xA4\xAA\x15\x63\x6B\xA9\x86\xAF"
+			  "\x1A\x52\x82\x36\x5F\xF4\x3F\x7A"
+			  "\x9B\x78\x62\x3B\x02\x28\x60\xB3"
+			  "\xBA\x82\xB1\xDD\xC9\x60\x8F\x47"
+			  "\xF1\x6B\xFE\xE5\x39\x34\xA0\x28"
+			  "\xA4\xB3\xC9\x7E\xED\x28\x8D\x70"
+			  "\xB2\x1D\xFD\xC6\x00\xCF\x1A\x94"
+			  "\x28\xF8\xC1\x34\xB7\x58\xA5\x6C"
+			  "\x1A\x9D\xE4\xE4\xF6\xB9\xB4\xB0"
+			  "\x5D\x51\x54\x9A\x53\xA0\xF9\x32"
+			  "\xBD\x31\x54\x14\x7B\x33\xEE\x17"
+			  "\xD3\xC7\x1F\x48\xBF\x0B\x22\xA2"
+			  "\x7D\x0C\xDF\xD0\x2E\x98\xFA\xD2"
+			  "\xFA\xCF\x24\x1D\x99\x9B\xD0\x7E"
+			  "\xF4\x4F\x88\xFF\x45\x99\x4A\xF4"
+			  "\xF2\x0A\x5B\x3B\x21\xAB\x92\xAE"
+			  "\x40\x78\x91\x95\xC4\x2F\xA3\xE8"
+			  "\x18\xC7\x07\xA6\xC8\xC0\x66\x33"
+			  "\x35\xC0\xB4\xA0\xF8\xEE\x1E\xF3"
+			  "\x40\xF5\x40\x54\xF1\x84\x8C\xEA"
+			  "\x27\x38\x1F\xF8\x77\xC7\xDF\xD8"
+			  "\x1D\xE2\xD9\x59\x40\x4F\x59\xD4"
+			  "\xF8\x17\x99\x8D\x58\x2D\x72\x44"
+			  "\x9D\x1D\x91\x64\xD6\x3F\x0A\x82"
+			  "\xC7\x57\x3D\xEF\xD3\x41\xFA\xA7"
+			  "\x68\xA3\xB8\xA5\x93\x74\x2E\x85"
+			  "\x4C\x9D\x69\x59\xCE\x15\xAE\xBF"
+			  "\x9C\x8F\x14\x64\x5D\x7F\xCF\x0B"
+			  "\xCE\x43\x5D\x28\xC0\x2F\xFB\x18"
+			  "\x79\x9A\xFC\x43\x16\x7C\x6B\x7B"
+			  "\x38\xB8\x48\x36\x66\x4E\x20\x43"
+			  "\xBA\x76\x13\x9A\xC3\xF2\xEB\x52"
+			  "\xD7\xDC\xB2\x67\x63\x14\x25\xCD"
+			  "\xB1\x13\x4B\xDE\x8C\x59\x21\x84"
+			  "\x81\x8D\x97\x23\x45\x33\x7C\xF3"
+			  "\xC5\xBC\x79\x95\xAA\x84\x68\x31"
+			  "\x2D\x1A\x68\xFE\xEC\x92\x94\xDA"
+			  "\x94\x2A\x6F\xD6\xFE\xE5\x76\x97"
+			  "\xF4\x6E\xEE\xCB\x2B\x95\x4E\x36"
+			  "\x5F\x74\x8C\x86\x5B\x71\xD0\x20",
+		.ilen	= 496,
 		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
 			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
 			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
 			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-		.rlen	= 48,
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.rlen	= 496,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 48 - 16, 16 },
+		.tap	= { 496 - 16, 16 },
 	},
 };
 
@@ -16507,17 +21380,128 @@ static struct cipher_testvec camellia_ctr_enc_tv_template[] = {
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
 			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
 			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-		.ilen	= 48,
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.ilen	= 496,
 		.result	= "\xF3\x06\x3A\x84\xCD\xBA\x8E\x11"
 			  "\xB7\x74\x6F\x5C\x97\xFB\x36\xFE"
 			  "\xDE\x71\x58\xD4\x15\xD1\xC1\xA4"
 			  "\xC9\x28\x74\xA6\x6B\xC7\x95\xA6"
 			  "\x6C\x77\xF7\x2F\xDF\xC7\xBB\x85"
-			  "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C",
-		.rlen	= 48,
-	},
-	{ /* Generated with Crypto++ */
+			  "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C"
+			  "\x1E\x43\xEF\x6C\xE9\x98\xC5\xA0"
+			  "\x7B\x13\xE5\x7F\xF8\x49\x9A\x8C"
+			  "\xE6\x7B\x08\xC3\x32\x66\x55\x4E"
+			  "\xA5\x44\x1D\x2C\x18\xC7\x29\x1F"
+			  "\x61\x28\x4A\xE3\xCD\xE5\x47\xB2"
+			  "\x82\x2F\x66\x83\x91\x51\xAE\xD7"
+			  "\x1C\x91\x3C\x57\xE3\x1D\x5A\xC9"
+			  "\xFD\xC5\x58\x58\xEF\xCC\x33\xC9"
+			  "\x0F\xEA\x26\x32\xD1\x15\x19\x2D"
+			  "\x25\xB4\x7F\xB0\xDF\xFB\x88\x60"
+			  "\x4E\x4D\x06\x7D\xCC\x1F\xED\x3B"
+			  "\x68\x84\xD5\xB3\x1B\xE7\xB9\xA1"
+			  "\x68\x8B\x2C\x1A\x44\xDA\x63\xD3"
+			  "\x29\xE9\x59\x32\x1F\x30\x1C\x43"
+			  "\xEA\x3A\xA3\x6B\x54\x3C\xAA\x11"
+			  "\xAD\x38\x20\xC9\xB9\x8A\x64\x66"
+			  "\x5A\x07\x49\xDF\xA1\x9C\xF9\x76"
+			  "\x36\x65\xB6\x81\x8F\x76\x09\xE5"
+			  "\xEB\xD1\x29\xA4\xE4\xF4\x4C\xCD"
+			  "\xAF\xFC\xB9\x16\xD9\xC3\x73\x6A"
+			  "\x33\x12\xF8\x7E\xBC\xCC\x7D\x80"
+			  "\xBF\x3C\x25\x06\x13\x84\xFA\x35"
+			  "\xF7\x40\xFA\xA1\x44\x13\x70\xD8"
+			  "\x01\xF9\x85\x15\x63\xEC\x7D\xB9"
+			  "\x02\xD8\xBA\x41\x6C\x92\x68\x66"
+			  "\x95\xDD\xD6\x42\xE7\xBB\xE1\xFD"
+			  "\x28\x3E\x94\xB6\xBD\xA7\xBF\x47"
+			  "\x58\x8D\xFF\x19\x30\x75\x0D\x48"
+			  "\x94\xE9\xA6\xCD\xB3\x8E\x1E\xCD"
+			  "\x59\xBC\x1A\xAC\x3C\x4F\xA9\xEB"
+			  "\xF4\xA7\xE4\x75\x4A\x18\x40\xC9"
+			  "\x1E\xEC\x06\x9C\x28\x4B\xF7\x2B"
+			  "\xE2\xEF\xD6\x42\x2E\xBB\xFC\x0A"
+			  "\x79\xA2\x99\x28\x93\x1B\x00\x57"
+			  "\x35\x1E\x1A\x93\x90\xA4\x68\x95"
+			  "\x5E\x57\x40\xD5\xA9\xAA\x19\x48"
+			  "\xEC\xFF\x76\x77\xDC\x78\x89\x76"
+			  "\xE5\x3B\x00\xEC\x58\x4D\xD1\xE3"
+			  "\xC8\x6C\x2C\x45\x5E\x5F\xD9\x4E"
+			  "\x71\xA5\x36\x6D\x03\xF1\xC7\xD5"
+			  "\xF3\x63\xC0\xD8\xCB\x2B\xF1\xA8"
+			  "\xB9\x2B\xE6\x0B\xB9\x65\x78\xA0"
+			  "\xC4\x46\xE6\x9B\x8B\x43\x2D\xAB"
+			  "\x70\xA6\xE0\x59\x1E\xAC\x9D\xE0"
+			  "\x76\x44\x45\xF3\x24\x11\x57\x98"
+			  "\x9A\x86\xB4\x12\x80\x28\x86\x20"
+			  "\x23\x9D\x2D\xE9\x38\x32\xB1\xE1"
+			  "\xCF\x0A\x23\x73\x7D\xC5\x80\x3D"
+			  "\x9F\x6D\xA0\xD0\xEE\x93\x8A\x79"
+			  "\x3A\xDD\x1D\xBB\x9E\x26\x5D\x01"
+			  "\x44\xD0\xD4\x4E\xC3\xF1\xE4\x38"
+			  "\x09\x62\x0A\x1A\x4E\xD2\x63\x0F"
+			  "\x6E\x3E\xD2\xA4\x3A\xF4\xF3\xFF"
+			  "\x7E\x42\xEC\xB6\x6F\x4D\x6B\x48"
+			  "\xE6\xA6\x50\x80\x78\x9E\xF1\xB0"
+			  "\x4D\xB2\x0D\x3D\xFC\x40\x25\x4D",
+		.rlen	= 496,
+	}, { /* Generated with Crypto++ */
 		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
 			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
 			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
@@ -16531,19 +21515,131 @@ static struct cipher_testvec camellia_ctr_enc_tv_template[] = {
 			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
 			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
 			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
-			  "\xDF\x76\x0D",
-		.ilen	= 51,
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+			  "\x2B\xC2\x59",
+		.ilen	= 499,
 		.result	= "\xF3\x06\x3A\x84\xCD\xBA\x8E\x11"
 			  "\xB7\x74\x6F\x5C\x97\xFB\x36\xFE"
 			  "\xDE\x71\x58\xD4\x15\xD1\xC1\xA4"
 			  "\xC9\x28\x74\xA6\x6B\xC7\x95\xA6"
 			  "\x6C\x77\xF7\x2F\xDF\xC7\xBB\x85"
 			  "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C"
-			  "\x1E\x43\xEF",
-		.rlen	= 51,
+			  "\x1E\x43\xEF\x6C\xE9\x98\xC5\xA0"
+			  "\x7B\x13\xE5\x7F\xF8\x49\x9A\x8C"
+			  "\xE6\x7B\x08\xC3\x32\x66\x55\x4E"
+			  "\xA5\x44\x1D\x2C\x18\xC7\x29\x1F"
+			  "\x61\x28\x4A\xE3\xCD\xE5\x47\xB2"
+			  "\x82\x2F\x66\x83\x91\x51\xAE\xD7"
+			  "\x1C\x91\x3C\x57\xE3\x1D\x5A\xC9"
+			  "\xFD\xC5\x58\x58\xEF\xCC\x33\xC9"
+			  "\x0F\xEA\x26\x32\xD1\x15\x19\x2D"
+			  "\x25\xB4\x7F\xB0\xDF\xFB\x88\x60"
+			  "\x4E\x4D\x06\x7D\xCC\x1F\xED\x3B"
+			  "\x68\x84\xD5\xB3\x1B\xE7\xB9\xA1"
+			  "\x68\x8B\x2C\x1A\x44\xDA\x63\xD3"
+			  "\x29\xE9\x59\x32\x1F\x30\x1C\x43"
+			  "\xEA\x3A\xA3\x6B\x54\x3C\xAA\x11"
+			  "\xAD\x38\x20\xC9\xB9\x8A\x64\x66"
+			  "\x5A\x07\x49\xDF\xA1\x9C\xF9\x76"
+			  "\x36\x65\xB6\x81\x8F\x76\x09\xE5"
+			  "\xEB\xD1\x29\xA4\xE4\xF4\x4C\xCD"
+			  "\xAF\xFC\xB9\x16\xD9\xC3\x73\x6A"
+			  "\x33\x12\xF8\x7E\xBC\xCC\x7D\x80"
+			  "\xBF\x3C\x25\x06\x13\x84\xFA\x35"
+			  "\xF7\x40\xFA\xA1\x44\x13\x70\xD8"
+			  "\x01\xF9\x85\x15\x63\xEC\x7D\xB9"
+			  "\x02\xD8\xBA\x41\x6C\x92\x68\x66"
+			  "\x95\xDD\xD6\x42\xE7\xBB\xE1\xFD"
+			  "\x28\x3E\x94\xB6\xBD\xA7\xBF\x47"
+			  "\x58\x8D\xFF\x19\x30\x75\x0D\x48"
+			  "\x94\xE9\xA6\xCD\xB3\x8E\x1E\xCD"
+			  "\x59\xBC\x1A\xAC\x3C\x4F\xA9\xEB"
+			  "\xF4\xA7\xE4\x75\x4A\x18\x40\xC9"
+			  "\x1E\xEC\x06\x9C\x28\x4B\xF7\x2B"
+			  "\xE2\xEF\xD6\x42\x2E\xBB\xFC\x0A"
+			  "\x79\xA2\x99\x28\x93\x1B\x00\x57"
+			  "\x35\x1E\x1A\x93\x90\xA4\x68\x95"
+			  "\x5E\x57\x40\xD5\xA9\xAA\x19\x48"
+			  "\xEC\xFF\x76\x77\xDC\x78\x89\x76"
+			  "\xE5\x3B\x00\xEC\x58\x4D\xD1\xE3"
+			  "\xC8\x6C\x2C\x45\x5E\x5F\xD9\x4E"
+			  "\x71\xA5\x36\x6D\x03\xF1\xC7\xD5"
+			  "\xF3\x63\xC0\xD8\xCB\x2B\xF1\xA8"
+			  "\xB9\x2B\xE6\x0B\xB9\x65\x78\xA0"
+			  "\xC4\x46\xE6\x9B\x8B\x43\x2D\xAB"
+			  "\x70\xA6\xE0\x59\x1E\xAC\x9D\xE0"
+			  "\x76\x44\x45\xF3\x24\x11\x57\x98"
+			  "\x9A\x86\xB4\x12\x80\x28\x86\x20"
+			  "\x23\x9D\x2D\xE9\x38\x32\xB1\xE1"
+			  "\xCF\x0A\x23\x73\x7D\xC5\x80\x3D"
+			  "\x9F\x6D\xA0\xD0\xEE\x93\x8A\x79"
+			  "\x3A\xDD\x1D\xBB\x9E\x26\x5D\x01"
+			  "\x44\xD0\xD4\x4E\xC3\xF1\xE4\x38"
+			  "\x09\x62\x0A\x1A\x4E\xD2\x63\x0F"
+			  "\x6E\x3E\xD2\xA4\x3A\xF4\xF3\xFF"
+			  "\x7E\x42\xEC\xB6\x6F\x4D\x6B\x48"
+			  "\xE6\xA6\x50\x80\x78\x9E\xF1\xB0"
+			  "\x4D\xB2\x0D\x3D\xFC\x40\x25\x4D"
+			  "\x93\x11\x1C",
+		.rlen	= 499,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 51 - 16, 16 },
+		.tap	= { 499 - 16, 16 },
 	}, { /* Generated with Crypto++ */
 		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
 			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -16695,17 +21791,128 @@ static struct cipher_testvec camellia_ctr_dec_tv_template[] = {
 			  "\xDE\x71\x58\xD4\x15\xD1\xC1\xA4"
 			  "\xC9\x28\x74\xA6\x6B\xC7\x95\xA6"
 			  "\x6C\x77\xF7\x2F\xDF\xC7\xBB\x85"
-			  "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C",
-		.ilen	= 48,
+			  "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C"
+			  "\x1E\x43\xEF\x6C\xE9\x98\xC5\xA0"
+			  "\x7B\x13\xE5\x7F\xF8\x49\x9A\x8C"
+			  "\xE6\x7B\x08\xC3\x32\x66\x55\x4E"
+			  "\xA5\x44\x1D\x2C\x18\xC7\x29\x1F"
+			  "\x61\x28\x4A\xE3\xCD\xE5\x47\xB2"
+			  "\x82\x2F\x66\x83\x91\x51\xAE\xD7"
+			  "\x1C\x91\x3C\x57\xE3\x1D\x5A\xC9"
+			  "\xFD\xC5\x58\x58\xEF\xCC\x33\xC9"
+			  "\x0F\xEA\x26\x32\xD1\x15\x19\x2D"
+			  "\x25\xB4\x7F\xB0\xDF\xFB\x88\x60"
+			  "\x4E\x4D\x06\x7D\xCC\x1F\xED\x3B"
+			  "\x68\x84\xD5\xB3\x1B\xE7\xB9\xA1"
+			  "\x68\x8B\x2C\x1A\x44\xDA\x63\xD3"
+			  "\x29\xE9\x59\x32\x1F\x30\x1C\x43"
+			  "\xEA\x3A\xA3\x6B\x54\x3C\xAA\x11"
+			  "\xAD\x38\x20\xC9\xB9\x8A\x64\x66"
+			  "\x5A\x07\x49\xDF\xA1\x9C\xF9\x76"
+			  "\x36\x65\xB6\x81\x8F\x76\x09\xE5"
+			  "\xEB\xD1\x29\xA4\xE4\xF4\x4C\xCD"
+			  "\xAF\xFC\xB9\x16\xD9\xC3\x73\x6A"
+			  "\x33\x12\xF8\x7E\xBC\xCC\x7D\x80"
+			  "\xBF\x3C\x25\x06\x13\x84\xFA\x35"
+			  "\xF7\x40\xFA\xA1\x44\x13\x70\xD8"
+			  "\x01\xF9\x85\x15\x63\xEC\x7D\xB9"
+			  "\x02\xD8\xBA\x41\x6C\x92\x68\x66"
+			  "\x95\xDD\xD6\x42\xE7\xBB\xE1\xFD"
+			  "\x28\x3E\x94\xB6\xBD\xA7\xBF\x47"
+			  "\x58\x8D\xFF\x19\x30\x75\x0D\x48"
+			  "\x94\xE9\xA6\xCD\xB3\x8E\x1E\xCD"
+			  "\x59\xBC\x1A\xAC\x3C\x4F\xA9\xEB"
+			  "\xF4\xA7\xE4\x75\x4A\x18\x40\xC9"
+			  "\x1E\xEC\x06\x9C\x28\x4B\xF7\x2B"
+			  "\xE2\xEF\xD6\x42\x2E\xBB\xFC\x0A"
+			  "\x79\xA2\x99\x28\x93\x1B\x00\x57"
+			  "\x35\x1E\x1A\x93\x90\xA4\x68\x95"
+			  "\x5E\x57\x40\xD5\xA9\xAA\x19\x48"
+			  "\xEC\xFF\x76\x77\xDC\x78\x89\x76"
+			  "\xE5\x3B\x00\xEC\x58\x4D\xD1\xE3"
+			  "\xC8\x6C\x2C\x45\x5E\x5F\xD9\x4E"
+			  "\x71\xA5\x36\x6D\x03\xF1\xC7\xD5"
+			  "\xF3\x63\xC0\xD8\xCB\x2B\xF1\xA8"
+			  "\xB9\x2B\xE6\x0B\xB9\x65\x78\xA0"
+			  "\xC4\x46\xE6\x9B\x8B\x43\x2D\xAB"
+			  "\x70\xA6\xE0\x59\x1E\xAC\x9D\xE0"
+			  "\x76\x44\x45\xF3\x24\x11\x57\x98"
+			  "\x9A\x86\xB4\x12\x80\x28\x86\x20"
+			  "\x23\x9D\x2D\xE9\x38\x32\xB1\xE1"
+			  "\xCF\x0A\x23\x73\x7D\xC5\x80\x3D"
+			  "\x9F\x6D\xA0\xD0\xEE\x93\x8A\x79"
+			  "\x3A\xDD\x1D\xBB\x9E\x26\x5D\x01"
+			  "\x44\xD0\xD4\x4E\xC3\xF1\xE4\x38"
+			  "\x09\x62\x0A\x1A\x4E\xD2\x63\x0F"
+			  "\x6E\x3E\xD2\xA4\x3A\xF4\xF3\xFF"
+			  "\x7E\x42\xEC\xB6\x6F\x4D\x6B\x48"
+			  "\xE6\xA6\x50\x80\x78\x9E\xF1\xB0"
+			  "\x4D\xB2\x0D\x3D\xFC\x40\x25\x4D",
+		.ilen	= 496,
 		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
 			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
 			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
 			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
-			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48",
-		.rlen	= 48,
-	},
-	{ /* Generated with Crypto++ */
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.rlen	= 496,
+	}, { /* Generated with Crypto++ */
 		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
 			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
 			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
@@ -16719,19 +21926,131 @@ static struct cipher_testvec camellia_ctr_dec_tv_template[] = {
 			  "\xC9\x28\x74\xA6\x6B\xC7\x95\xA6"
 			  "\x6C\x77\xF7\x2F\xDF\xC7\xBB\x85"
 			  "\x60\xFC\xE8\x94\xE8\xB5\x09\x2C"
-			  "\x1E\x43\xEF",
-		.ilen	= 51,
+			  "\x1E\x43\xEF\x6C\xE9\x98\xC5\xA0"
+			  "\x7B\x13\xE5\x7F\xF8\x49\x9A\x8C"
+			  "\xE6\x7B\x08\xC3\x32\x66\x55\x4E"
+			  "\xA5\x44\x1D\x2C\x18\xC7\x29\x1F"
+			  "\x61\x28\x4A\xE3\xCD\xE5\x47\xB2"
+			  "\x82\x2F\x66\x83\x91\x51\xAE\xD7"
+			  "\x1C\x91\x3C\x57\xE3\x1D\x5A\xC9"
+			  "\xFD\xC5\x58\x58\xEF\xCC\x33\xC9"
+			  "\x0F\xEA\x26\x32\xD1\x15\x19\x2D"
+			  "\x25\xB4\x7F\xB0\xDF\xFB\x88\x60"
+			  "\x4E\x4D\x06\x7D\xCC\x1F\xED\x3B"
+			  "\x68\x84\xD5\xB3\x1B\xE7\xB9\xA1"
+			  "\x68\x8B\x2C\x1A\x44\xDA\x63\xD3"
+			  "\x29\xE9\x59\x32\x1F\x30\x1C\x43"
+			  "\xEA\x3A\xA3\x6B\x54\x3C\xAA\x11"
+			  "\xAD\x38\x20\xC9\xB9\x8A\x64\x66"
+			  "\x5A\x07\x49\xDF\xA1\x9C\xF9\x76"
+			  "\x36\x65\xB6\x81\x8F\x76\x09\xE5"
+			  "\xEB\xD1\x29\xA4\xE4\xF4\x4C\xCD"
+			  "\xAF\xFC\xB9\x16\xD9\xC3\x73\x6A"
+			  "\x33\x12\xF8\x7E\xBC\xCC\x7D\x80"
+			  "\xBF\x3C\x25\x06\x13\x84\xFA\x35"
+			  "\xF7\x40\xFA\xA1\x44\x13\x70\xD8"
+			  "\x01\xF9\x85\x15\x63\xEC\x7D\xB9"
+			  "\x02\xD8\xBA\x41\x6C\x92\x68\x66"
+			  "\x95\xDD\xD6\x42\xE7\xBB\xE1\xFD"
+			  "\x28\x3E\x94\xB6\xBD\xA7\xBF\x47"
+			  "\x58\x8D\xFF\x19\x30\x75\x0D\x48"
+			  "\x94\xE9\xA6\xCD\xB3\x8E\x1E\xCD"
+			  "\x59\xBC\x1A\xAC\x3C\x4F\xA9\xEB"
+			  "\xF4\xA7\xE4\x75\x4A\x18\x40\xC9"
+			  "\x1E\xEC\x06\x9C\x28\x4B\xF7\x2B"
+			  "\xE2\xEF\xD6\x42\x2E\xBB\xFC\x0A"
+			  "\x79\xA2\x99\x28\x93\x1B\x00\x57"
+			  "\x35\x1E\x1A\x93\x90\xA4\x68\x95"
+			  "\x5E\x57\x40\xD5\xA9\xAA\x19\x48"
+			  "\xEC\xFF\x76\x77\xDC\x78\x89\x76"
+			  "\xE5\x3B\x00\xEC\x58\x4D\xD1\xE3"
+			  "\xC8\x6C\x2C\x45\x5E\x5F\xD9\x4E"
+			  "\x71\xA5\x36\x6D\x03\xF1\xC7\xD5"
+			  "\xF3\x63\xC0\xD8\xCB\x2B\xF1\xA8"
+			  "\xB9\x2B\xE6\x0B\xB9\x65\x78\xA0"
+			  "\xC4\x46\xE6\x9B\x8B\x43\x2D\xAB"
+			  "\x70\xA6\xE0\x59\x1E\xAC\x9D\xE0"
+			  "\x76\x44\x45\xF3\x24\x11\x57\x98"
+			  "\x9A\x86\xB4\x12\x80\x28\x86\x20"
+			  "\x23\x9D\x2D\xE9\x38\x32\xB1\xE1"
+			  "\xCF\x0A\x23\x73\x7D\xC5\x80\x3D"
+			  "\x9F\x6D\xA0\xD0\xEE\x93\x8A\x79"
+			  "\x3A\xDD\x1D\xBB\x9E\x26\x5D\x01"
+			  "\x44\xD0\xD4\x4E\xC3\xF1\xE4\x38"
+			  "\x09\x62\x0A\x1A\x4E\xD2\x63\x0F"
+			  "\x6E\x3E\xD2\xA4\x3A\xF4\xF3\xFF"
+			  "\x7E\x42\xEC\xB6\x6F\x4D\x6B\x48"
+			  "\xE6\xA6\x50\x80\x78\x9E\xF1\xB0"
+			  "\x4D\xB2\x0D\x3D\xFC\x40\x25\x4D"
+			  "\x93\x11\x1C",
+		.ilen	= 499,
 		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
 			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
 			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
 			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
 			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
 			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
-			  "\xDF\x76\x0D",
-		.rlen	= 51,
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7"
+			  "\x2B\xC2\x59",
+		.rlen	= 499,
 		.also_non_np = 1,
 		.np	= 2,
-		.tap	= { 51 - 16, 16 },
+		.tap	= { 499 - 16, 16 },
 	}, { /* Generated with Crypto++ */
 		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
 			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
@@ -19769,38 +25088,40 @@ static struct pcomp_testvec zlib_decomp_tv_template[] = {
 static struct comp_testvec lzo_comp_tv_template[] = {
 	{
 		.inlen	= 70,
-		.outlen	= 46,
+		.outlen	= 57,
 		.input	= "Join us now and share the software "
 			"Join us now and share the software ",
 		.output	= "\x00\x0d\x4a\x6f\x69\x6e\x20\x75"
-			"\x73\x20\x6e\x6f\x77\x20\x61\x6e"
-			"\x64\x20\x73\x68\x61\x72\x65\x20"
-			"\x74\x68\x65\x20\x73\x6f\x66\x74"
-			"\x77\x70\x01\x01\x4a\x6f\x69\x6e"
-			"\x3d\x88\x00\x11\x00\x00",
+			  "\x73\x20\x6e\x6f\x77\x20\x61\x6e"
+			  "\x64\x20\x73\x68\x61\x72\x65\x20"
+			  "\x74\x68\x65\x20\x73\x6f\x66\x74"
+			  "\x77\x70\x01\x32\x88\x00\x0c\x65"
+			  "\x20\x74\x68\x65\x20\x73\x6f\x66"
+			  "\x74\x77\x61\x72\x65\x20\x11\x00"
+			  "\x00",
 	}, {
 		.inlen	= 159,
-		.outlen	= 133,
+		.outlen	= 131,
 		.input	= "This document describes a compression method based on the LZO "
 			"compression algorithm.  This document defines the application of "
 			"the LZO algorithm used in UBIFS.",
-		.output	= "\x00\x2b\x54\x68\x69\x73\x20\x64"
+		.output	= "\x00\x2c\x54\x68\x69\x73\x20\x64"
 			  "\x6f\x63\x75\x6d\x65\x6e\x74\x20"
 			  "\x64\x65\x73\x63\x72\x69\x62\x65"
 			  "\x73\x20\x61\x20\x63\x6f\x6d\x70"
 			  "\x72\x65\x73\x73\x69\x6f\x6e\x20"
 			  "\x6d\x65\x74\x68\x6f\x64\x20\x62"
 			  "\x61\x73\x65\x64\x20\x6f\x6e\x20"
-			  "\x74\x68\x65\x20\x4c\x5a\x4f\x2b"
-			  "\x8c\x00\x0d\x61\x6c\x67\x6f\x72"
-			  "\x69\x74\x68\x6d\x2e\x20\x20\x54"
-			  "\x68\x69\x73\x2a\x54\x01\x02\x66"
-			  "\x69\x6e\x65\x73\x94\x06\x05\x61"
-			  "\x70\x70\x6c\x69\x63\x61\x74\x76"
-			  "\x0a\x6f\x66\x88\x02\x60\x09\x27"
-			  "\xf0\x00\x0c\x20\x75\x73\x65\x64"
-			  "\x20\x69\x6e\x20\x55\x42\x49\x46"
-			  "\x53\x2e\x11\x00\x00",
+			  "\x74\x68\x65\x20\x4c\x5a\x4f\x20"
+			  "\x2a\x8c\x00\x09\x61\x6c\x67\x6f"
+			  "\x72\x69\x74\x68\x6d\x2e\x20\x20"
+			  "\x2e\x54\x01\x03\x66\x69\x6e\x65"
+			  "\x73\x20\x74\x06\x05\x61\x70\x70"
+			  "\x6c\x69\x63\x61\x74\x76\x0a\x6f"
+			  "\x66\x88\x02\x60\x09\x27\xf0\x00"
+			  "\x0c\x20\x75\x73\x65\x64\x20\x69"
+			  "\x6e\x20\x55\x42\x49\x46\x53\x2e"
+			  "\x11\x00\x00",
 	},
 };
 
diff --git a/crypto/vmac.c b/crypto/vmac.c
index f2338ca..2eb11a3 100644
--- a/crypto/vmac.c
+++ b/crypto/vmac.c
@@ -375,6 +375,11 @@ static void vhash_update(const unsigned char *m,
 	u64 pkh = ctx->polykey[0];
 	u64 pkl = ctx->polykey[1];
 
+	if (!mbytes)
+		return;
+
+	BUG_ON(mbytes % VMAC_NHBYTES);
+
 	mptr = (u64 *)m;
 	i = mbytes / VMAC_NHBYTES;  /* Must be non-zero */
 
@@ -454,7 +459,7 @@ do_l3:
 }
 
 static u64 vmac(unsigned char m[], unsigned int mbytes,
-			unsigned char n[16], u64 *tagl,
+			const unsigned char n[16], u64 *tagl,
 			struct vmac_ctx_t *ctx)
 {
 	u64 *in_n, *out_p;
@@ -559,8 +564,33 @@ static int vmac_update(struct shash_desc *pdesc, const u8 *p,
 {
 	struct crypto_shash *parent = pdesc->tfm;
 	struct vmac_ctx_t *ctx = crypto_shash_ctx(parent);
+	int expand;
+	int min;
+
+	expand = VMAC_NHBYTES - ctx->partial_size > 0 ?
+			VMAC_NHBYTES - ctx->partial_size : 0;
+
+	min = len < expand ? len : expand;
+
+	memcpy(ctx->partial + ctx->partial_size, p, min);
+	ctx->partial_size += min;
+
+	if (len < expand)
+		return 0;
 
-	vhash_update(p, len, &ctx->__vmac_ctx);
+	vhash_update(ctx->partial, VMAC_NHBYTES, &ctx->__vmac_ctx);
+	ctx->partial_size = 0;
+
+	len -= expand;
+	p += expand;
+
+	if (len % VMAC_NHBYTES) {
+		memcpy(ctx->partial, p + len - (len % VMAC_NHBYTES),
+			len % VMAC_NHBYTES);
+		ctx->partial_size = len % VMAC_NHBYTES;
+	}
+
+	vhash_update(p, len - len % VMAC_NHBYTES, &ctx->__vmac_ctx);
 
 	return 0;
 }
@@ -572,10 +602,20 @@ static int vmac_final(struct shash_desc *pdesc, u8 *out)
 	vmac_t mac;
 	u8 nonce[16] = {};
 
-	mac = vmac(NULL, 0, nonce, NULL, ctx);
+	/* vmac() ends up accessing outside the array bounds that
+	 * we specify.  In appears to access up to the next 2-word
+	 * boundary.  We'll just be uber cautious and zero the
+	 * unwritten bytes in the buffer.
+	 */
+	if (ctx->partial_size) {
+		memset(ctx->partial + ctx->partial_size, 0,
+			VMAC_NHBYTES - ctx->partial_size);
+	}
+	mac = vmac(ctx->partial, ctx->partial_size, nonce, NULL, ctx);
 	memcpy(out, &mac, sizeof(vmac_t));
 	memset(&mac, 0, sizeof(vmac_t));
 	memset(&ctx->__vmac_ctx, 0, sizeof(struct vmac_ctx));
+	ctx->partial_size = 0;
 	return 0;
 }
 
@@ -673,4 +713,3 @@ module_exit(vmac_module_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("VMAC hash algorithm");
-
diff --git a/drivers/Kconfig b/drivers/Kconfig
index dbdefa3..f5fb072 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -156,4 +156,6 @@ source "drivers/pwm/Kconfig"
 
 source "drivers/irqchip/Kconfig"
 
+source "drivers/ipack/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index a16a8d0..7863b9f 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -145,3 +145,4 @@ obj-$(CONFIG_EXTCON)		+= extcon/
 obj-$(CONFIG_MEMORY)		+= memory/
 obj-$(CONFIG_IIO)		+= iio/
 obj-$(CONFIG_VME_BUS)		+= vme/
+obj-$(CONFIG_IPACK_BUS)		+= ipack/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 119d58d..38c5078 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -181,6 +181,12 @@ config ACPI_DOCK
 	  This driver supports ACPI-controlled docking stations and removable
 	  drive bays such as the IBM Ultrabay and the Dell Module Bay.
 
+config ACPI_I2C
+	def_tristate I2C
+	depends on I2C
+	help
+	  ACPI I2C enumeration support.
+
 config ACPI_PROCESSOR
 	tristate "Processor"
 	select THERMAL
@@ -261,6 +267,15 @@ config ACPI_CUSTOM_DSDT
 	bool
 	default ACPI_CUSTOM_DSDT_FILE != ""
 
+config ACPI_INITRD_TABLE_OVERRIDE
+	bool "ACPI tables can be passed via uncompressed cpio in initrd"
+	default n
+	help
+	  This option provides functionality to override arbitrary ACPI tables
+	  via initrd. No functional change if no ACPI tables are passed via
+	  initrd, therefore it's safe to say Y.
+	  See Documentation/acpi/initrd_table_override.txt for details
+
 config ACPI_BLACKLIST_YEAR
 	int "Disable ACPI for systems before Jan 1st this year" if X86_32
 	default 0
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 82422fe..2a4502b 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -21,9 +21,10 @@ obj-y				+= acpi.o \
 acpi-y				+= osl.o utils.o reboot.o
 acpi-y				+= nvs.o
 
-# sleep related files
+# Power management related files
 acpi-y				+= wakeup.o
 acpi-y				+= sleep.o
+acpi-$(CONFIG_PM)		+= device_pm.o
 acpi-$(CONFIG_ACPI_SLEEP)	+= proc.o
 
 
@@ -32,10 +33,12 @@ acpi-$(CONFIG_ACPI_SLEEP)	+= proc.o
 #
 acpi-y				+= bus.o glue.o
 acpi-y				+= scan.o
+acpi-y				+= resource.o
 acpi-y				+= processor_core.o
 acpi-y				+= ec.o
 acpi-$(CONFIG_ACPI_DOCK)	+= dock.o
 acpi-y				+= pci_root.o pci_link.o pci_irq.o pci_bind.o
+acpi-y				+= acpi_platform.o
 acpi-y				+= power.o
 acpi-y				+= event.o
 acpi-y				+= sysfs.o
@@ -67,6 +70,7 @@ obj-$(CONFIG_ACPI_HED)		+= hed.o
 obj-$(CONFIG_ACPI_EC_DEBUGFS)	+= ec_sys.o
 obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
 obj-$(CONFIG_ACPI_BGRT)		+= bgrt.o
+obj-$(CONFIG_ACPI_I2C)		+= acpi_i2c.o
 
 # processor has its own "processor." module_param namespace
 processor-y			:= processor_driver.o processor_throttling.o
diff --git a/drivers/acpi/acpi_i2c.c b/drivers/acpi/acpi_i2c.c
new file mode 100644
index 0000000..82045e3
--- /dev/null
+++ b/drivers/acpi/acpi_i2c.c
@@ -0,0 +1,103 @@
+/*
+ * ACPI I2C enumeration support
+ *
+ * Copyright (C) 2012, Intel Corporation
+ * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/i2c.h>
+#include <linux/ioport.h>
+
+ACPI_MODULE_NAME("i2c");
+
+static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
+{
+	struct i2c_board_info *info = data;
+
+	if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+		struct acpi_resource_i2c_serialbus *sb;
+
+		sb = &ares->data.i2c_serial_bus;
+		if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
+			info->addr = sb->slave_address;
+			if (sb->access_mode == ACPI_I2C_10BIT_MODE)
+				info->flags |= I2C_CLIENT_TEN;
+		}
+	} else if (info->irq < 0) {
+		struct resource r;
+
+		if (acpi_dev_resource_interrupt(ares, 0, &r))
+			info->irq = r.start;
+	}
+
+	/* Tell the ACPI core to skip this resource */
+	return 1;
+}
+
+static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
+				       void *data, void **return_value)
+{
+	struct i2c_adapter *adapter = data;
+	struct list_head resource_list;
+	struct i2c_board_info info;
+	struct acpi_device *adev;
+	int ret;
+
+	if (acpi_bus_get_device(handle, &adev))
+		return AE_OK;
+	if (acpi_bus_get_status(adev) || !adev->status.present)
+		return AE_OK;
+
+	memset(&info, 0, sizeof(info));
+	info.acpi_node.handle = handle;
+	info.irq = -1;
+
+	INIT_LIST_HEAD(&resource_list);
+	ret = acpi_dev_get_resources(adev, &resource_list,
+				     acpi_i2c_add_resource, &info);
+	acpi_dev_free_resource_list(&resource_list);
+
+	if (ret < 0 || !info.addr)
+		return AE_OK;
+
+	strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
+	if (!i2c_new_device(adapter, &info)) {
+		dev_err(&adapter->dev,
+			"failed to add I2C device %s from ACPI\n",
+			dev_name(&adev->dev));
+	}
+
+	return AE_OK;
+}
+
+/**
+ * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
+ * @adapter: pointer to adapter
+ *
+ * Enumerate all I2C slave devices behind this adapter by walking the ACPI
+ * namespace. When a device is found it will be added to the Linux device
+ * model and bound to the corresponding ACPI handle.
+ */
+void acpi_i2c_register_devices(struct i2c_adapter *adapter)
+{
+	acpi_handle handle;
+	acpi_status status;
+
+	handle = ACPI_HANDLE(&adapter->dev);
+	if (!handle)
+		return;
+
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+				     acpi_i2c_add_device, NULL,
+				     adapter, NULL);
+	if (ACPI_FAILURE(status))
+		dev_warn(&adapter->dev, "failed to enumerate I2C slaves\n");
+}
+EXPORT_SYMBOL_GPL(acpi_i2c_register_devices);
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 24c807f..eb30e5a 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -31,6 +31,7 @@
 #include <linux/types.h>
 #include <linux/memory_hotplug.h>
 #include <linux/slab.h>
+#include <linux/acpi.h>
 #include <acpi/acpi_drivers.h>
 
 #define ACPI_MEMORY_DEVICE_CLASS		"memory"
@@ -78,6 +79,7 @@ struct acpi_memory_info {
 	unsigned short caching;	/* memory cache attribute */
 	unsigned short write_protect;	/* memory read/write attribute */
 	unsigned int enabled:1;
+	unsigned int failed:1;
 };
 
 struct acpi_memory_device {
@@ -86,8 +88,6 @@ struct acpi_memory_device {
 	struct list_head res_list;
 };
 
-static int acpi_hotmem_initialized;
-
 static acpi_status
 acpi_memory_get_resource(struct acpi_resource *resource, void *context)
 {
@@ -125,12 +125,20 @@ acpi_memory_get_resource(struct acpi_resource *resource, void *context)
 	return AE_OK;
 }
 
+static void
+acpi_memory_free_device_resources(struct acpi_memory_device *mem_device)
+{
+	struct acpi_memory_info *info, *n;
+
+	list_for_each_entry_safe(info, n, &mem_device->res_list, list)
+		kfree(info);
+	INIT_LIST_HEAD(&mem_device->res_list);
+}
+
 static int
 acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
 {
 	acpi_status status;
-	struct acpi_memory_info *info, *n;
-
 
 	if (!list_empty(&mem_device->res_list))
 		return 0;
@@ -138,9 +146,7 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
 	status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS,
 				     acpi_memory_get_resource, mem_device);
 	if (ACPI_FAILURE(status)) {
-		list_for_each_entry_safe(info, n, &mem_device->res_list, list)
-			kfree(info);
-		INIT_LIST_HEAD(&mem_device->res_list);
+		acpi_memory_free_device_resources(mem_device);
 		return -EINVAL;
 	}
 
@@ -170,7 +176,7 @@ acpi_memory_get_device(acpi_handle handle,
 	/* Get the parent device */
 	result = acpi_bus_get_device(phandle, &pdevice);
 	if (result) {
-		printk(KERN_WARNING PREFIX "Cannot get acpi bus device");
+		acpi_handle_warn(phandle, "Cannot get acpi bus device\n");
 		return -EINVAL;
 	}
 
@@ -180,14 +186,14 @@ acpi_memory_get_device(acpi_handle handle,
 	 */
 	result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE);
 	if (result) {
-		printk(KERN_WARNING PREFIX "Cannot add acpi bus");
+		acpi_handle_warn(handle, "Cannot add acpi bus\n");
 		return -EINVAL;
 	}
 
       end:
 	*mem_device = acpi_driver_data(device);
 	if (!(*mem_device)) {
-		printk(KERN_ERR "\n driver data not found");
+		dev_err(&device->dev, "driver data not found\n");
 		return -ENODEV;
 	}
 
@@ -224,7 +230,8 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
 	/* Get the range from the _CRS */
 	result = acpi_memory_get_device_resources(mem_device);
 	if (result) {
-		printk(KERN_ERR PREFIX "get_device_resources failed\n");
+		dev_err(&mem_device->device->dev,
+			"get_device_resources failed\n");
 		mem_device->state = MEMORY_INVALID_STATE;
 		return result;
 	}
@@ -251,13 +258,27 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
 			node = memory_add_physaddr_to_nid(info->start_addr);
 
 		result = add_memory(node, info->start_addr, info->length);
-		if (result)
+
+		/*
+		 * If the memory block has been used by the kernel, add_memory()
+		 * returns -EEXIST. If add_memory() returns the other error, it
+		 * means that this memory block is not used by the kernel.
+		 */
+		if (result && result != -EEXIST) {
+			info->failed = 1;
 			continue;
-		info->enabled = 1;
+		}
+
+		if (!result)
+			info->enabled = 1;
+		/*
+		 * Add num_enable even if add_memory() returns -EEXIST, so the
+		 * device is bound to this driver.
+		 */
 		num_enabled++;
 	}
 	if (!num_enabled) {
-		printk(KERN_ERR PREFIX "add_memory failed\n");
+		dev_err(&mem_device->device->dev, "add_memory failed\n");
 		mem_device->state = MEMORY_INVALID_STATE;
 		return -EINVAL;
 	}
@@ -272,68 +293,31 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
 	return 0;
 }
 
-static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
+static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
 {
-	acpi_status status;
-	struct acpi_object_list arg_list;
-	union acpi_object arg;
-	unsigned long long current_status;
-
-
-	/* Issue the _EJ0 command */
-	arg_list.count = 1;
-	arg_list.pointer = &arg;
-	arg.type = ACPI_TYPE_INTEGER;
-	arg.integer.value = 1;
-	status = acpi_evaluate_object(mem_device->device->handle,
-				      "_EJ0", &arg_list, NULL);
-	/* Return on _EJ0 failure */
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "_EJ0 failed"));
-		return -ENODEV;
-	}
-
-	/* Evalute _STA to check if the device is disabled */
-	status = acpi_evaluate_integer(mem_device->device->handle, "_STA",
-				       NULL, &current_status);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
-
-	/* Check for device status.  Device should be disabled */
-	if (current_status & ACPI_STA_DEVICE_ENABLED)
-		return -EINVAL;
+	int result = 0;
+	struct acpi_memory_info *info, *n;
 
-	return 0;
-}
+	list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
+		if (info->failed)
+			/* The kernel does not use this memory block */
+			continue;
 
-static int acpi_memory_disable_device(struct acpi_memory_device *mem_device)
-{
-	int result;
-	struct acpi_memory_info *info, *n;
+		if (!info->enabled)
+			/*
+			 * The kernel uses this memory block, but it may be not
+			 * managed by us.
+			 */
+			return -EBUSY;
 
+		result = remove_memory(info->start_addr, info->length);
+		if (result)
+			return result;
 
-	/*
-	 * Ask the VM to offline this memory range.
-	 * Note: Assume that this function returns zero on success
-	 */
-	list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
-		if (info->enabled) {
-			result = remove_memory(info->start_addr, info->length);
-			if (result)
-				return result;
-		}
+		list_del(&info->list);
 		kfree(info);
 	}
 
-	/* Power-off and eject the device */
-	result = acpi_memory_powerdown_device(mem_device);
-	if (result) {
-		/* Set the status of the device to invalid */
-		mem_device->state = MEMORY_INVALID_STATE;
-		return result;
-	}
-
-	mem_device->state = MEMORY_POWER_OFF_STATE;
 	return result;
 }
 
@@ -341,6 +325,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
 {
 	struct acpi_memory_device *mem_device;
 	struct acpi_device *device;
+	struct acpi_eject_event *ej_event = NULL;
 	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
 
 	switch (event) {
@@ -353,7 +338,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
 			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 					  "\nReceived DEVICE CHECK notification for device\n"));
 		if (acpi_memory_get_device(handle, &mem_device)) {
-			printk(KERN_ERR PREFIX "Cannot find driver data\n");
+			acpi_handle_err(handle, "Cannot find driver data\n");
 			break;
 		}
 
@@ -361,7 +346,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
 			break;
 
 		if (acpi_memory_enable_device(mem_device)) {
-			printk(KERN_ERR PREFIX "Cannot enable memory device\n");
+			acpi_handle_err(handle,"Cannot enable memory device\n");
 			break;
 		}
 
@@ -373,40 +358,28 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
 				  "\nReceived EJECT REQUEST notification for device\n"));
 
 		if (acpi_bus_get_device(handle, &device)) {
-			printk(KERN_ERR PREFIX "Device doesn't exist\n");
+			acpi_handle_err(handle, "Device doesn't exist\n");
 			break;
 		}
 		mem_device = acpi_driver_data(device);
 		if (!mem_device) {
-			printk(KERN_ERR PREFIX "Driver Data is NULL\n");
+			acpi_handle_err(handle, "Driver Data is NULL\n");
 			break;
 		}
 
-		/*
-		 * Currently disabling memory device from kernel mode
-		 * TBD: Can also be disabled from user mode scripts
-		 * TBD: Can also be disabled by Callback registration
-		 *      with generic sysfs driver
-		 */
-		if (acpi_memory_disable_device(mem_device)) {
-			printk(KERN_ERR PREFIX "Disable memory device\n");
-			/*
-			 * If _EJ0 was called but failed, _OST is not
-			 * necessary.
-			 */
-			if (mem_device->state == MEMORY_INVALID_STATE)
-				return;
-
+		ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
+		if (!ej_event) {
+			pr_err(PREFIX "No memory, dropping EJECT\n");
 			break;
 		}
 
-		/*
-		 * TBD: Invoke acpi_bus_remove to cleanup data structures
-		 */
+		ej_event->handle = handle;
+		ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
+		acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
+					(void *)ej_event);
 
-		/* _EJ0 succeeded; _OST is not necessary */
+		/* eject is performed asynchronously */
 		return;
-
 	default:
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 				  "Unsupported event [0x%x]\n", event));
@@ -420,6 +393,15 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
 	return;
 }
 
+static void acpi_memory_device_free(struct acpi_memory_device *mem_device)
+{
+	if (!mem_device)
+		return;
+
+	acpi_memory_free_device_resources(mem_device);
+	kfree(mem_device);
+}
+
 static int acpi_memory_device_add(struct acpi_device *device)
 {
 	int result;
@@ -449,23 +431,16 @@ static int acpi_memory_device_add(struct acpi_device *device)
 	/* Set the device state */
 	mem_device->state = MEMORY_POWER_ON_STATE;
 
-	printk(KERN_DEBUG "%s \n", acpi_device_name(device));
-
-	/*
-	 * Early boot code has recognized memory area by EFI/E820.
-	 * If DSDT shows these memory devices on boot, hotplug is not necessary
-	 * for them. So, it just returns until completion of this driver's
-	 * start up.
-	 */
-	if (!acpi_hotmem_initialized)
-		return 0;
+	pr_debug("%s\n", acpi_device_name(device));
 
 	if (!acpi_memory_check_device(mem_device)) {
 		/* call add_memory func */
 		result = acpi_memory_enable_device(mem_device);
-		if (result)
-			printk(KERN_ERR PREFIX
+		if (result) {
+			dev_err(&device->dev,
 				"Error in acpi_memory_enable_device\n");
+			acpi_memory_device_free(mem_device);
+		}
 	}
 	return result;
 }
@@ -473,13 +448,18 @@ static int acpi_memory_device_add(struct acpi_device *device)
 static int acpi_memory_device_remove(struct acpi_device *device, int type)
 {
 	struct acpi_memory_device *mem_device = NULL;
-
+	int result;
 
 	if (!device || !acpi_driver_data(device))
 		return -EINVAL;
 
 	mem_device = acpi_driver_data(device);
-	kfree(mem_device);
+
+	result = acpi_memory_remove_memory(mem_device);
+	if (result)
+		return result;
+
+	acpi_memory_device_free(mem_device);
 
 	return 0;
 }
@@ -568,7 +548,6 @@ static int __init acpi_memory_device_init(void)
 		return -ENODEV;
 	}
 
-	acpi_hotmem_initialized = 1;
 	return 0;
 }
 
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index af4aad6..16fa979 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -286,7 +286,7 @@ static ssize_t acpi_pad_rrtime_store(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
 	unsigned long num;
-	if (strict_strtoul(buf, 0, &num))
+	if (kstrtoul(buf, 0, &num))
 		return -EINVAL;
 	if (num < 1 || num >= 100)
 		return -EINVAL;
@@ -309,7 +309,7 @@ static ssize_t acpi_pad_idlepct_store(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
 	unsigned long num;
-	if (strict_strtoul(buf, 0, &num))
+	if (kstrtoul(buf, 0, &num))
 		return -EINVAL;
 	if (num < 1 || num >= 100)
 		return -EINVAL;
@@ -332,7 +332,7 @@ static ssize_t acpi_pad_idlecpus_store(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
 	unsigned long num;
-	if (strict_strtoul(buf, 0, &num))
+	if (kstrtoul(buf, 0, &num))
 		return -EINVAL;
 	mutex_lock(&isolated_cpus_lock);
 	acpi_pad_idle_cpus(num);
@@ -457,7 +457,7 @@ static void acpi_pad_notify(acpi_handle handle, u32 event,
 			dev_name(&device->dev), event, 0);
 		break;
 	default:
-		printk(KERN_WARNING "Unsupported event [0x%x]\n", event);
+		pr_warn("Unsupported event [0x%x]\n", event);
 		break;
 	}
 }
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
new file mode 100644
index 0000000..db129b9
--- /dev/null
+++ b/drivers/acpi/acpi_platform.c
@@ -0,0 +1,104 @@
+/*
+ * ACPI support for platform bus type.
+ *
+ * Copyright (C) 2012, Intel Corporation
+ * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
+ *          Mathias Nyman <mathias.nyman@linux.intel.com>
+ *          Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "internal.h"
+
+ACPI_MODULE_NAME("platform");
+
+/**
+ * acpi_create_platform_device - Create platform device for ACPI device node
+ * @adev: ACPI device node to create a platform device for.
+ *
+ * Check if the given @adev can be represented as a platform device and, if
+ * that's the case, create and register a platform device, populate its common
+ * resources and returns a pointer to it.  Otherwise, return %NULL.
+ *
+ * The platform device's name will be taken from the @adev's _HID and _UID.
+ */
+struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
+{
+	struct platform_device *pdev = NULL;
+	struct acpi_device *acpi_parent;
+	struct platform_device_info pdevinfo;
+	struct resource_list_entry *rentry;
+	struct list_head resource_list;
+	struct resource *resources;
+	int count;
+
+	/* If the ACPI node already has a physical device attached, skip it. */
+	if (adev->physical_node_count)
+		return NULL;
+
+	INIT_LIST_HEAD(&resource_list);
+	count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
+	if (count <= 0)
+		return NULL;
+
+	resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
+	if (!resources) {
+		dev_err(&adev->dev, "No memory for resources\n");
+		acpi_dev_free_resource_list(&resource_list);
+		return NULL;
+	}
+	count = 0;
+	list_for_each_entry(rentry, &resource_list, node)
+		resources[count++] = rentry->res;
+
+	acpi_dev_free_resource_list(&resource_list);
+
+	memset(&pdevinfo, 0, sizeof(pdevinfo));
+	/*
+	 * If the ACPI node has a parent and that parent has a physical device
+	 * attached to it, that physical device should be the parent of the
+	 * platform device we are about to create.
+	 */
+	pdevinfo.parent = NULL;
+	acpi_parent = adev->parent;
+	if (acpi_parent) {
+		struct acpi_device_physical_node *entry;
+		struct list_head *list;
+
+		mutex_lock(&acpi_parent->physical_node_lock);
+		list = &acpi_parent->physical_node_list;
+		if (!list_empty(list)) {
+			entry = list_first_entry(list,
+					struct acpi_device_physical_node,
+					node);
+			pdevinfo.parent = entry->dev;
+		}
+		mutex_unlock(&acpi_parent->physical_node_lock);
+	}
+	pdevinfo.name = dev_name(&adev->dev);
+	pdevinfo.id = -1;
+	pdevinfo.res = resources;
+	pdevinfo.num_res = count;
+	pdevinfo.acpi_node.handle = adev->handle;
+	pdev = platform_device_register_full(&pdevinfo);
+	if (IS_ERR(pdev)) {
+		dev_err(&adev->dev, "platform device creation failed: %ld\n",
+			PTR_ERR(pdev));
+		pdev = NULL;
+	} else {
+		dev_dbg(&adev->dev, "created platform device %s\n",
+			dev_name(&pdev->dev));
+	}
+
+	kfree(resources);
+	return pdev;
+}
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index 7f1d407..c8bc24b 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -161,3 +161,6 @@ acpi-y +=		\
 	utxfinit.o	\
 	utxferror.o	\
 	utxfmutex.o
+
+acpi-$(ACPI_FUTURE_USAGE) += uttrack.o utcache.o utclib.o
+
diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h
index 5e8abb0..432a318 100644
--- a/drivers/acpi/acpica/acdebug.h
+++ b/drivers/acpi/acpica/acdebug.h
@@ -44,17 +44,28 @@
 #ifndef __ACDEBUG_H__
 #define __ACDEBUG_H__
 
-#define ACPI_DEBUG_BUFFER_SIZE  4196
+#define ACPI_DEBUG_BUFFER_SIZE  0x4000	/* 16K buffer for return objects */
 
-struct command_info {
+struct acpi_db_command_info {
 	char *name;		/* Command Name */
 	u8 min_args;		/* Minimum arguments required */
 };
 
-struct argument_info {
+struct acpi_db_command_help {
+	u8 line_count;		/* Number of help lines */
+	char *invocation;	/* Command Invocation */
+	char *description;	/* Command Description */
+};
+
+struct acpi_db_argument_info {
 	char *name;		/* Argument Name */
 };
 
+struct acpi_db_execute_walk {
+	u32 count;
+	u32 max_count;
+};
+
 #define PARAM_LIST(pl)                  pl
 #define DBTEST_OUTPUT_LEVEL(lvl)        if (acpi_gbl_db_opt_verbose)
 #define VERBOSE_PRINT(fp)               DBTEST_OUTPUT_LEVEL(lvl) {\
@@ -77,59 +88,71 @@ acpi_db_single_step(struct acpi_walk_state *walk_state,
 /*
  * dbcmds - debug commands and output routines
  */
-acpi_status acpi_db_disassemble_method(char *name);
+struct acpi_namespace_node *acpi_db_convert_to_node(char *in_string);
 
 void acpi_db_display_table_info(char *table_arg);
 
-void acpi_db_unload_acpi_table(char *table_arg, char *instance_arg);
+void acpi_db_display_template(char *buffer_arg);
 
-void
-acpi_db_set_method_breakpoint(char *location,
-			      struct acpi_walk_state *walk_state,
-			      union acpi_parse_object *op);
+void acpi_db_unload_acpi_table(char *name);
 
-void acpi_db_set_method_call_breakpoint(union acpi_parse_object *op);
+void acpi_db_send_notify(char *name, u32 value);
 
-void acpi_db_get_bus_info(void);
+void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg);
 
-void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op);
+acpi_status acpi_db_sleep(char *object_arg);
 
-void acpi_db_dump_namespace(char *start_arg, char *depth_arg);
+void acpi_db_display_locks(void);
 
-void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg);
+void acpi_db_display_resources(char *object_arg);
 
-void acpi_db_send_notify(char *name, u32 value);
+ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_display_gpes(void))
+
+void acpi_db_display_handlers(void);
+
+ACPI_HW_DEPENDENT_RETURN_VOID(void
+			      acpi_db_generate_gpe(char *gpe_arg,
+						   char *block_arg))
+
+/*
+ * dbmethod - control method commands
+ */
+void
+acpi_db_set_method_breakpoint(char *location,
+			      struct acpi_walk_state *walk_state,
+			      union acpi_parse_object *op);
+
+void acpi_db_set_method_call_breakpoint(union acpi_parse_object *op);
 
 void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg);
 
-acpi_status
-acpi_db_display_objects(char *obj_type_arg, char *display_count_arg);
+acpi_status acpi_db_disassemble_method(char *name);
 
-void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg);
+void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op);
 
-acpi_status acpi_db_find_name_in_namespace(char *name_arg);
+void acpi_db_batch_execute(char *count_arg);
 
+/*
+ * dbnames - namespace commands
+ */
 void acpi_db_set_scope(char *name);
 
-ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_db_sleep(char *object_arg))
+void acpi_db_dump_namespace(char *start_arg, char *depth_arg);
 
-void acpi_db_find_references(char *object_arg);
+void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg);
 
-void acpi_db_display_locks(void);
+acpi_status acpi_db_find_name_in_namespace(char *name_arg);
 
-void acpi_db_display_resources(char *object_arg);
+void acpi_db_check_predefined_names(void);
 
-ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_display_gpes(void))
+acpi_status
+acpi_db_display_objects(char *obj_type_arg, char *display_count_arg);
 
 void acpi_db_check_integrity(void);
 
-ACPI_HW_DEPENDENT_RETURN_VOID(void
-			      acpi_db_generate_gpe(char *gpe_arg,
-						   char *block_arg))
-
-void acpi_db_check_predefined_names(void);
+void acpi_db_find_references(char *object_arg);
 
-void acpi_db_batch_execute(void);
+void acpi_db_get_bus_info(void);
 
 /*
  * dbdisply - debug display commands
@@ -161,7 +184,8 @@ acpi_db_display_argument_object(union acpi_operand_object *obj_desc,
 /*
  * dbexec - debugger control method execution
  */
-void acpi_db_execute(char *name, char **args, u32 flags);
+void
+acpi_db_execute(char *name, char **args, acpi_object_type * types, u32 flags);
 
 void
 acpi_db_create_execution_threads(char *num_threads_arg,
@@ -175,7 +199,8 @@ u32 acpi_db_get_cache_info(struct acpi_memory_list *cache);
  * dbfileio - Debugger file I/O commands
  */
 acpi_object_type
-acpi_db_match_argument(char *user_argument, struct argument_info *arguments);
+acpi_db_match_argument(char *user_argument,
+		       struct acpi_db_argument_info *arguments);
 
 void acpi_db_close_debug_file(void);
 
@@ -208,6 +233,11 @@ acpi_db_command_dispatch(char *input_buffer,
 
 void ACPI_SYSTEM_XFACE acpi_db_execute_thread(void *context);
 
+acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op);
+
+char *acpi_db_get_next_token(char *string,
+			     char **next, acpi_object_type * return_type);
+
 /*
  * dbstats - Generation and display of ACPI table statistics
  */
diff --git a/drivers/acpi/acpica/acdispat.h b/drivers/acpi/acpica/acdispat.h
index 5935ba6..ed33ebc 100644
--- a/drivers/acpi/acpica/acdispat.h
+++ b/drivers/acpi/acpica/acdispat.h
@@ -309,10 +309,13 @@ acpi_ds_obj_stack_push(void *object, struct acpi_walk_state *walk_state);
 acpi_status
 acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state *walk_state);
 
-struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object
-						  *origin, union acpi_operand_object
-						  *mth_desc, struct acpi_thread_state
-						  *thread);
+struct acpi_walk_state * acpi_ds_create_walk_state(acpi_owner_id owner_id,
+						   union acpi_parse_object
+						   *origin,
+						   union acpi_operand_object
+						   *mth_desc,
+						   struct acpi_thread_state
+						   *thread);
 
 acpi_status
 acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index c0a43b3..e975c67 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -84,9 +84,11 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info);
 
 acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info);
 
-acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
+acpi_status
+acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
 
-acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
+acpi_status
+acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
 
 struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
 						       u32 gpe_number);
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index ce79100..64472e4 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -70,7 +70,7 @@
 
 /*
  * Enable "slack" in the AML interpreter?  Default is FALSE, and the
- * interpreter strictly follows the ACPI specification.  Setting to TRUE
+ * interpreter strictly follows the ACPI specification. Setting to TRUE
  * allows the interpreter to ignore certain errors and/or bad AML constructs.
  *
  * Currently, these features are enabled by this flag:
@@ -155,26 +155,6 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_no_resource_disassembly, FALSE);
 
 /*****************************************************************************
  *
- * Debug support
- *
- ****************************************************************************/
-
-/* Procedure nesting level for debug output */
-
-extern u32 acpi_gbl_nesting_level;
-
-ACPI_EXTERN u32 acpi_gpe_count;
-ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS];
-
-/* Support for dynamic control method tracing mechanism */
-
-ACPI_EXTERN u32 acpi_gbl_original_dbg_level;
-ACPI_EXTERN u32 acpi_gbl_original_dbg_layer;
-ACPI_EXTERN u32 acpi_gbl_trace_dbg_level;
-ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer;
-
-/*****************************************************************************
- *
  * ACPI Table globals
  *
  ****************************************************************************/
@@ -259,15 +239,6 @@ ACPI_EXTERN acpi_spinlock acpi_gbl_hardware_lock;	/* For ACPI H/W except GPE reg
  *
  ****************************************************************************/
 
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
-
-/* Lists for tracking memory allocations */
-
-ACPI_EXTERN struct acpi_memory_list *acpi_gbl_global_list;
-ACPI_EXTERN struct acpi_memory_list *acpi_gbl_ns_node_list;
-ACPI_EXTERN u8 acpi_gbl_display_final_mem_stats;
-#endif
-
 /* Object caches */
 
 ACPI_EXTERN acpi_cache_t *acpi_gbl_namespace_cache;
@@ -326,6 +297,15 @@ extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS];
 
 #endif
 
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+
+/* Lists for tracking memory allocations */
+
+ACPI_EXTERN struct acpi_memory_list *acpi_gbl_global_list;
+ACPI_EXTERN struct acpi_memory_list *acpi_gbl_ns_node_list;
+ACPI_EXTERN u8 acpi_gbl_display_final_mem_stats;
+#endif
+
 /*****************************************************************************
  *
  * Namespace globals
@@ -396,13 +376,35 @@ ACPI_EXTERN struct acpi_gpe_block_info
 #if (!ACPI_REDUCED_HARDWARE)
 
 ACPI_EXTERN u8 acpi_gbl_all_gpes_initialized;
-ACPI_EXTERN ACPI_GBL_EVENT_HANDLER acpi_gbl_global_event_handler;
+ACPI_EXTERN acpi_gbl_event_handler acpi_gbl_global_event_handler;
 ACPI_EXTERN void *acpi_gbl_global_event_handler_context;
 
 #endif				/* !ACPI_REDUCED_HARDWARE */
 
 /*****************************************************************************
  *
+ * Debug support
+ *
+ ****************************************************************************/
+
+/* Procedure nesting level for debug output */
+
+extern u32 acpi_gbl_nesting_level;
+
+/* Event counters */
+
+ACPI_EXTERN u32 acpi_gpe_count;
+ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS];
+
+/* Support for dynamic control method tracing mechanism */
+
+ACPI_EXTERN u32 acpi_gbl_original_dbg_level;
+ACPI_EXTERN u32 acpi_gbl_original_dbg_layer;
+ACPI_EXTERN u32 acpi_gbl_trace_dbg_level;
+ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer;
+
+/*****************************************************************************
+ *
  * Debugger globals
  *
  ****************************************************************************/
@@ -426,10 +428,11 @@ ACPI_EXTERN u8 acpi_gbl_db_opt_stats;
 ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods;
 
 ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS];
-ACPI_EXTERN char acpi_gbl_db_line_buf[80];
-ACPI_EXTERN char acpi_gbl_db_parsed_buf[80];
-ACPI_EXTERN char acpi_gbl_db_scope_buf[40];
-ACPI_EXTERN char acpi_gbl_db_debug_filename[40];
+ACPI_EXTERN acpi_object_type acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS];
+ACPI_EXTERN char acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char acpi_gbl_db_scope_buf[80];
+ACPI_EXTERN char acpi_gbl_db_debug_filename[80];
 ACPI_EXTERN u8 acpi_gbl_db_output_to_file;
 ACPI_EXTERN char *acpi_gbl_db_buffer;
 ACPI_EXTERN char *acpi_gbl_db_filename;
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index c816ee6..ff8bd00 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -262,10 +262,10 @@ struct acpi_create_field_info {
 };
 
 typedef
-acpi_status(*ACPI_INTERNAL_METHOD) (struct acpi_walk_state * walk_state);
+acpi_status(*acpi_internal_method) (struct acpi_walk_state * walk_state);
 
 /*
- * Bitmapped ACPI types.  Used internally only
+ * Bitmapped ACPI types. Used internally only
  */
 #define ACPI_BTYPE_ANY                  0x00000000
 #define ACPI_BTYPE_INTEGER              0x00000001
@@ -486,8 +486,10 @@ struct acpi_gpe_device_info {
 	struct acpi_namespace_node *gpe_device;
 };
 
-typedef acpi_status(*acpi_gpe_callback) (struct acpi_gpe_xrupt_info *gpe_xrupt_info,
-		struct acpi_gpe_block_info *gpe_block, void *context);
+typedef acpi_status(*acpi_gpe_callback) (struct acpi_gpe_xrupt_info *
+					 gpe_xrupt_info,
+					 struct acpi_gpe_block_info *gpe_block,
+					 void *context);
 
 /* Information about each particular fixed event */
 
@@ -582,7 +584,7 @@ struct acpi_pscope_state {
 };
 
 /*
- * Thread state - one per thread across multiple walk states.  Multiple walk
+ * Thread state - one per thread across multiple walk states. Multiple walk
  * states are created when there are nested control methods executing.
  */
 struct acpi_thread_state {
@@ -645,7 +647,7 @@ union acpi_generic_state {
  *
  ****************************************************************************/
 
-typedef acpi_status(*ACPI_EXECUTE_OP) (struct acpi_walk_state * walk_state);
+typedef acpi_status(*acpi_execute_op) (struct acpi_walk_state * walk_state);
 
 /* Address Range info block */
 
@@ -1031,6 +1033,7 @@ struct acpi_db_method_info {
 	acpi_handle method;
 	acpi_handle main_thread_gate;
 	acpi_handle thread_complete_gate;
+	acpi_handle info_gate;
 	acpi_thread_id *threads;
 	u32 num_threads;
 	u32 num_created;
@@ -1041,6 +1044,7 @@ struct acpi_db_method_info {
 	u32 num_loops;
 	char pathname[128];
 	char **args;
+	acpi_object_type *types;
 
 	/*
 	 * Arguments to be passed to method for the command
diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h
index a7f68c4..5efad99 100644
--- a/drivers/acpi/acpica/acmacros.h
+++ b/drivers/acpi/acpica/acmacros.h
@@ -84,29 +84,29 @@
 
 /* These macros reverse the bytes during the move, converting little-endian to big endian */
 
-			  /* Big Endian      <==        Little Endian */
-			  /*  Hi...Lo                     Lo...Hi     */
+	 /* Big Endian      <==        Little Endian */
+	 /*  Hi...Lo                     Lo...Hi     */
 /* 16-bit source, 16/32/64 destination */
 
 #define ACPI_MOVE_16_TO_16(d, s)        {((  u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[1];\
-					   ((  u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];}
+			  ((  u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];}
 
 #define ACPI_MOVE_16_TO_32(d, s)        {(*(u32 *)(void *)(d))=0;\
-							   ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
-							   ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
+					  ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
+					  ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
 
 #define ACPI_MOVE_16_TO_64(d, s)        {(*(u64 *)(void *)(d))=0;\
-									 ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\
-									 ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];}
+							   ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\
+							   ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];}
 
 /* 32-bit source, 16/32/64 destination */
 
 #define ACPI_MOVE_32_TO_16(d, s)        ACPI_MOVE_16_TO_16(d, s)	/* Truncate to 16 */
 
 #define ACPI_MOVE_32_TO_32(d, s)        {((  u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[3];\
-										 ((  u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\
-										 ((  u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
-										 ((  u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
+									  ((  u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\
+									  ((  u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
+									  ((  u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
 
 #define ACPI_MOVE_32_TO_64(d, s)        {(*(u64 *)(void *)(d))=0;\
 										   ((u8 *)(void *)(d))[4] = ((u8 *)(void *)(s))[3];\
@@ -196,24 +196,12 @@
 #endif
 #endif
 
-/* Macros based on machine integer width */
-
-#if ACPI_MACHINE_WIDTH == 32
-#define ACPI_MOVE_SIZE_TO_16(d, s)       ACPI_MOVE_32_TO_16(d, s)
-
-#elif ACPI_MACHINE_WIDTH == 64
-#define ACPI_MOVE_SIZE_TO_16(d, s)       ACPI_MOVE_64_TO_16(d, s)
-
-#else
-#error unknown ACPI_MACHINE_WIDTH
-#endif
-
 /*
  * Fast power-of-two math macros for non-optimized compilers
  */
-#define _ACPI_DIV(value, power_of2)      ((u32) ((value) >> (power_of2)))
-#define _ACPI_MUL(value, power_of2)      ((u32) ((value) << (power_of2)))
-#define _ACPI_MOD(value, divisor)        ((u32) ((value) & ((divisor) -1)))
+#define _ACPI_DIV(value, power_of2)     ((u32) ((value) >> (power_of2)))
+#define _ACPI_MUL(value, power_of2)     ((u32) ((value) << (power_of2)))
+#define _ACPI_MOD(value, divisor)       ((u32) ((value) & ((divisor) -1)))
 
 #define ACPI_DIV_2(a)                   _ACPI_DIV(a, 1)
 #define ACPI_MUL_2(a)                   _ACPI_MUL(a, 1)
@@ -238,12 +226,12 @@
 /*
  * Rounding macros (Power of two boundaries only)
  */
-#define ACPI_ROUND_DOWN(value, boundary)     (((acpi_size)(value)) & \
-						(~(((acpi_size) boundary)-1)))
+#define ACPI_ROUND_DOWN(value, boundary)    (((acpi_size)(value)) & \
+												(~(((acpi_size) boundary)-1)))
 
-#define ACPI_ROUND_UP(value, boundary)	     ((((acpi_size)(value)) + \
-						(((acpi_size) boundary)-1)) & \
-						(~(((acpi_size) boundary)-1)))
+#define ACPI_ROUND_UP(value, boundary)      ((((acpi_size)(value)) + \
+												(((acpi_size) boundary)-1)) & \
+												(~(((acpi_size) boundary)-1)))
 
 /* Note: sizeof(acpi_size) evaluates to either 4 or 8 (32- vs 64-bit mode) */
 
@@ -264,7 +252,7 @@
 
 #define ACPI_ROUND_UP_TO(value, boundary)   (((value) + ((boundary)-1)) / (boundary))
 
-#define ACPI_IS_MISALIGNED(value)	    (((acpi_size) value) & (sizeof(acpi_size)-1))
+#define ACPI_IS_MISALIGNED(value)           (((acpi_size) value) & (sizeof(acpi_size)-1))
 
 /*
  * Bitmask creation
@@ -355,7 +343,6 @@
  * Ascii error messages can be configured out
  */
 #ifndef ACPI_NO_ERROR_MESSAGES
-
 /*
  * Error reporting. Callers module and line number are inserted by AE_INFO,
  * the plist contains a set of parens to allow variable-length lists.
@@ -375,18 +362,15 @@
 #define ACPI_WARN_PREDEFINED(plist)
 #define ACPI_INFO_PREDEFINED(plist)
 
-#endif		/* ACPI_NO_ERROR_MESSAGES */
+#endif				/* ACPI_NO_ERROR_MESSAGES */
 
 /*
  * Debug macros that are conditionally compiled
  */
 #ifdef ACPI_DEBUG_OUTPUT
-
 /*
  * Function entry tracing
  */
-#ifdef CONFIG_ACPI_DEBUG_FUNC_TRACE
-
 #define ACPI_FUNCTION_TRACE(a)          ACPI_FUNCTION_NAME(a) \
 			  acpi_ut_trace(ACPI_DEBUG_PARAMETERS)
 #define ACPI_FUNCTION_TRACE_PTR(a, b)   ACPI_FUNCTION_NAME(a) \
@@ -464,45 +448,19 @@
 
 #endif				/* ACPI_SIMPLE_RETURN_MACROS */
 
-#else /* !CONFIG_ACPI_DEBUG_FUNC_TRACE */
-
-#define ACPI_FUNCTION_TRACE(a)
-#define ACPI_FUNCTION_TRACE_PTR(a,b)
-#define ACPI_FUNCTION_TRACE_U32(a,b)
-#define ACPI_FUNCTION_TRACE_STR(a,b)
-#define ACPI_FUNCTION_EXIT
-#define ACPI_FUNCTION_STATUS_EXIT(s)
-#define ACPI_FUNCTION_VALUE_EXIT(s)
-#define ACPI_FUNCTION_TRACE(a)
-#define ACPI_FUNCTION_ENTRY()
-
-#define return_VOID                     return
-#define return_ACPI_STATUS(s)           return(s)
-#define return_VALUE(s)                 return(s)
-#define return_UINT8(s)                 return(s)
-#define return_UINT32(s)                return(s)
-#define return_PTR(s)                   return(s)
-
-#endif /* CONFIG_ACPI_DEBUG_FUNC_TRACE */
-
 /* Conditional execution */
 
 #define ACPI_DEBUG_EXEC(a)              a
-#define ACPI_NORMAL_EXEC(a)
-
-#define ACPI_DEBUG_DEFINE(a)            a;
 #define ACPI_DEBUG_ONLY_MEMBERS(a)      a;
 #define _VERBOSE_STRUCTURES
 
-/* Stack and buffer dumping */
+/* Various object display routines for debug */
 
 #define ACPI_DUMP_STACK_ENTRY(a)        acpi_ex_dump_operand((a), 0)
-#define ACPI_DUMP_OPERANDS(a, b, c)	acpi_ex_dump_operands(a, b, c)
-
+#define ACPI_DUMP_OPERANDS(a, b ,c)     acpi_ex_dump_operands(a, b, c)
 #define ACPI_DUMP_ENTRY(a, b)           acpi_ns_dump_entry (a, b)
 #define ACPI_DUMP_PATHNAME(a, b, c, d)  acpi_ns_dump_pathname(a, b, c, d)
-#define ACPI_DUMP_RESOURCE_LIST(a)      acpi_rs_dump_resource_list(a)
-#define ACPI_DUMP_BUFFER(a, b)          acpi_ut_dump_buffer((u8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT)
+#define ACPI_DUMP_BUFFER(a, b)          acpi_ut_debug_dump_buffer((u8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT)
 
 #else
 /*
@@ -510,25 +468,23 @@
  * leaving no executable debug code!
  */
 #define ACPI_DEBUG_EXEC(a)
-#define ACPI_NORMAL_EXEC(a)             a;
-
-#define ACPI_DEBUG_DEFINE(a)		do { } while(0)
-#define ACPI_DEBUG_ONLY_MEMBERS(a)	do { } while(0)
-#define ACPI_FUNCTION_TRACE(a)		do { } while(0)
-#define ACPI_FUNCTION_TRACE_PTR(a, b)	do { } while(0)
-#define ACPI_FUNCTION_TRACE_U32(a, b)	do { } while(0)
-#define ACPI_FUNCTION_TRACE_STR(a, b)	do { } while(0)
-#define ACPI_FUNCTION_EXIT		do { } while(0)
-#define ACPI_FUNCTION_STATUS_EXIT(s)	do { } while(0)
-#define ACPI_FUNCTION_VALUE_EXIT(s)	do { } while(0)
-#define ACPI_FUNCTION_ENTRY()		do { } while(0)
-#define ACPI_DUMP_STACK_ENTRY(a)	do { } while(0)
-#define ACPI_DUMP_OPERANDS(a, b, c)     do { } while(0)
-#define ACPI_DUMP_ENTRY(a, b)		do { } while(0)
-#define ACPI_DUMP_TABLES(a, b)		do { } while(0)
-#define ACPI_DUMP_PATHNAME(a, b, c, d)	do { } while(0)
-#define ACPI_DUMP_RESOURCE_LIST(a)	do { } while(0)
-#define ACPI_DUMP_BUFFER(a, b)		do { } while(0)
+#define ACPI_DEBUG_ONLY_MEMBERS(a)
+#define ACPI_FUNCTION_TRACE(a)
+#define ACPI_FUNCTION_TRACE_PTR(a, b)
+#define ACPI_FUNCTION_TRACE_U32(a, b)
+#define ACPI_FUNCTION_TRACE_STR(a, b)
+#define ACPI_FUNCTION_EXIT
+#define ACPI_FUNCTION_STATUS_EXIT(s)
+#define ACPI_FUNCTION_VALUE_EXIT(s)
+#define ACPI_FUNCTION_ENTRY()
+#define ACPI_DUMP_STACK_ENTRY(a)
+#define ACPI_DUMP_OPERANDS(a, b, c)
+#define ACPI_DUMP_ENTRY(a, b)
+#define ACPI_DUMP_TABLES(a, b)
+#define ACPI_DUMP_PATHNAME(a, b, c, d)
+#define ACPI_DUMP_BUFFER(a, b)
+#define ACPI_DEBUG_PRINT(pl)
+#define ACPI_DEBUG_PRINT_RAW(pl)
 
 #define return_VOID                     return
 #define return_ACPI_STATUS(s)           return(s)
@@ -556,18 +512,6 @@
 #define ACPI_DEBUGGER_EXEC(a)
 #endif
 
-#ifdef ACPI_DEBUG_OUTPUT
-/*
- * 1) Set name to blanks
- * 2) Copy the object name
- */
-#define ACPI_ADD_OBJECT_NAME(a,b)       ACPI_MEMSET (a->common.name, ' ', sizeof (a->common.name));\
-										ACPI_STRNCPY (a->common.name, acpi_gbl_ns_type_names[b], sizeof (a->common.name))
-#else
-
-#define ACPI_ADD_OBJECT_NAME(a,b)
-#endif
-
 /*
  * Memory allocation tracking (DEBUG ONLY)
  */
@@ -578,13 +522,13 @@
 /* Memory allocation */
 
 #ifndef ACPI_ALLOCATE
-#define ACPI_ALLOCATE(a)            acpi_ut_allocate((acpi_size)(a), ACPI_MEM_PARAMETERS)
+#define ACPI_ALLOCATE(a)            acpi_ut_allocate((acpi_size) (a), ACPI_MEM_PARAMETERS)
 #endif
 #ifndef ACPI_ALLOCATE_ZEROED
-#define ACPI_ALLOCATE_ZEROED(a)     acpi_ut_allocate_zeroed((acpi_size)(a), ACPI_MEM_PARAMETERS)
+#define ACPI_ALLOCATE_ZEROED(a)     acpi_ut_allocate_zeroed((acpi_size) (a), ACPI_MEM_PARAMETERS)
 #endif
 #ifndef ACPI_FREE
-#define ACPI_FREE(a)                acpio_os_free(a)
+#define ACPI_FREE(a)                acpi_os_free(a)
 #endif
 #define ACPI_MEM_TRACKING(a)
 
@@ -592,16 +536,25 @@
 
 /* Memory allocation */
 
-#define ACPI_ALLOCATE(a)            acpi_ut_allocate_and_track((acpi_size)(a), ACPI_MEM_PARAMETERS)
-#define ACPI_ALLOCATE_ZEROED(a)     acpi_ut_allocate_zeroed_and_track((acpi_size)(a), ACPI_MEM_PARAMETERS)
+#define ACPI_ALLOCATE(a)            acpi_ut_allocate_and_track((acpi_size) (a), ACPI_MEM_PARAMETERS)
+#define ACPI_ALLOCATE_ZEROED(a)     acpi_ut_allocate_zeroed_and_track((acpi_size) (a), ACPI_MEM_PARAMETERS)
 #define ACPI_FREE(a)                acpi_ut_free_and_track(a, ACPI_MEM_PARAMETERS)
 #define ACPI_MEM_TRACKING(a)        a
 
 #endif				/* ACPI_DBG_TRACK_ALLOCATIONS */
 
-/* Preemption point */
-#ifndef ACPI_PREEMPTION_POINT
-#define ACPI_PREEMPTION_POINT() /* no preemption */
-#endif
+/*
+ * Macros used for ACPICA utilities only
+ */
+
+/* Generate a UUID */
+
+#define ACPI_INIT_UUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
+	(a) & 0xFF, ((a) >> 8) & 0xFF, ((a) >> 16) & 0xFF, ((a) >> 24) & 0xFF, \
+	(b) & 0xFF, ((b) >> 8) & 0xFF, \
+	(c) & 0xFF, ((c) >> 8) & 0xFF, \
+	(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)
+
+#define ACPI_IS_OCTAL_DIGIT(d)              (((char)(d) >= '0') && ((char)(d) <= '7'))
 
 #endif				/* ACMACROS_H */
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h
index 364a130..24eb9ea 100644
--- a/drivers/acpi/acpica/acobject.h
+++ b/drivers/acpi/acpica/acobject.h
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Name: acobject.h - Definition of union acpi_operand_object  (Internal object only)
@@ -179,7 +178,7 @@ struct acpi_object_method {
 	union acpi_operand_object *mutex;
 	u8 *aml_start;
 	union {
-		ACPI_INTERNAL_METHOD implementation;
+		acpi_internal_method implementation;
 		union acpi_operand_object *handler;
 	} dispatch;
 
@@ -198,7 +197,7 @@ struct acpi_object_method {
 
 /******************************************************************************
  *
- * Objects that can be notified.  All share a common notify_info area.
+ * Objects that can be notified. All share a common notify_info area.
  *
  *****************************************************************************/
 
@@ -235,7 +234,7 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
 
 /******************************************************************************
  *
- * Fields.  All share a common header/info field.
+ * Fields. All share a common header/info field.
  *
  *****************************************************************************/
 
diff --git a/drivers/acpi/acpica/acopcode.h b/drivers/acpi/acpica/acopcode.h
index 9440d05..d786a51 100644
--- a/drivers/acpi/acpica/acopcode.h
+++ b/drivers/acpi/acpica/acopcode.h
@@ -54,7 +54,7 @@
 #define _UNK                        0x6B
 
 /*
- * Reserved ASCII characters.  Do not use any of these for
+ * Reserved ASCII characters. Do not use any of these for
  * internal opcodes, since they are used to differentiate
  * name strings from AML opcodes
  */
@@ -63,7 +63,7 @@
 #define _PFX                        0x6D
 
 /*
- * All AML opcodes and the parse-time arguments for each.  Used by the AML
+ * All AML opcodes and the parse-time arguments for each. Used by the AML
  * parser  Each list is compressed into a 32-bit number and stored in the
  * master opcode table (in psopcode.c).
  */
@@ -193,7 +193,7 @@
 #define ARGP_ZERO_OP                    ARG_NONE
 
 /*
- * All AML opcodes and the runtime arguments for each.  Used by the AML
+ * All AML opcodes and the runtime arguments for each. Used by the AML
  * interpreter  Each list is compressed into a 32-bit number and stored
  * in the master opcode table (in psopcode.c).
  *
diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h
index b725d78..eefcf47 100644
--- a/drivers/acpi/acpica/acparser.h
+++ b/drivers/acpi/acpica/acparser.h
@@ -150,8 +150,7 @@ u8 acpi_ps_has_completed_scope(struct acpi_parse_state *parser_state);
 
 void
 acpi_ps_pop_scope(struct acpi_parse_state *parser_state,
-		  union acpi_parse_object **op,
-		  u32 * arg_list, u32 * arg_count);
+		  union acpi_parse_object **op, u32 *arg_list, u32 *arg_count);
 
 acpi_status
 acpi_ps_push_scope(struct acpi_parse_state *parser_state,
diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h
index 3080c01..9dfa1c8 100644
--- a/drivers/acpi/acpica/acpredef.h
+++ b/drivers/acpi/acpica/acpredef.h
@@ -150,8 +150,7 @@ enum acpi_return_package_types {
  * is saved here (rather than in a separate table) in order to minimize the
  * overall size of the stored data.
  */
-static const union acpi_predefined_info predefined_names[] =
-{
+static const union acpi_predefined_info predefined_names[] = {
 	{{"_AC0", 0, ACPI_RTYPE_INTEGER}},
 	{{"_AC1", 0, ACPI_RTYPE_INTEGER}},
 	{{"_AC2", 0, ACPI_RTYPE_INTEGER}},
@@ -538,7 +537,8 @@ static const union acpi_predefined_info predefined_names[] =
 
 	/* Acpi 1.0 defined _WAK with no return value. Later, it was changed to return a package */
 
-	{{"_WAK", 1, ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}},
+	{{"_WAK", 1,
+          ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}},
 			  {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2,0}, 0,0}}, /* Fixed-length (2 Int), but is optional */
 
 	/* _WDG/_WED are MS extensions defined by "Windows Instrumentation" */
@@ -551,11 +551,12 @@ static const union acpi_predefined_info predefined_names[] =
 };
 
 #if 0
+
 	/* This is an internally implemented control method, no need to check */
-	{{"_OSI", 1, ACPI_RTYPE_INTEGER}},
+{ {
+"_OSI", 1, ACPI_RTYPE_INTEGER}},
 
 	/* TBD: */
-
 	_PRT - currently ignore reversed entries. attempt to fix here?
 	think about possibly fixing package elements like _BIF, etc.
 #endif
diff --git a/drivers/acpi/acpica/acstruct.h b/drivers/acpi/acpica/acstruct.h
index f196e2c..937e66c 100644
--- a/drivers/acpi/acpica/acstruct.h
+++ b/drivers/acpi/acpica/acstruct.h
@@ -53,7 +53,7 @@
  ****************************************************************************/
 
 /*
- * Walk state - current state of a parse tree walk.  Used for both a leisurely
+ * Walk state - current state of a parse tree walk. Used for both a leisurely
  * stroll through the tree (for whatever reason), and for control method
  * execution.
  */
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index 5035327..b0f5f92 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -69,6 +69,22 @@ extern const char *acpi_gbl_siz_decode[];
 extern const char *acpi_gbl_trs_decode[];
 extern const char *acpi_gbl_ttp_decode[];
 extern const char *acpi_gbl_typ_decode[];
+extern const char *acpi_gbl_ppc_decode[];
+extern const char *acpi_gbl_ior_decode[];
+extern const char *acpi_gbl_dts_decode[];
+extern const char *acpi_gbl_ct_decode[];
+extern const char *acpi_gbl_sbt_decode[];
+extern const char *acpi_gbl_am_decode[];
+extern const char *acpi_gbl_sm_decode[];
+extern const char *acpi_gbl_wm_decode[];
+extern const char *acpi_gbl_cph_decode[];
+extern const char *acpi_gbl_cpo_decode[];
+extern const char *acpi_gbl_dp_decode[];
+extern const char *acpi_gbl_ed_decode[];
+extern const char *acpi_gbl_bpb_decode[];
+extern const char *acpi_gbl_sb_decode[];
+extern const char *acpi_gbl_fc_decode[];
+extern const char *acpi_gbl_pt_decode[];
 #endif
 
 /* Types for Resource descriptor entries */
@@ -79,14 +95,14 @@ extern const char *acpi_gbl_typ_decode[];
 #define ACPI_SMALL_VARIABLE_LENGTH      3
 
 typedef
-acpi_status(*acpi_walk_aml_callback) (u8 * aml,
+acpi_status(*acpi_walk_aml_callback) (u8 *aml,
 				      u32 length,
 				      u32 offset,
 				      u8 resource_index, void **context);
 
 typedef
 acpi_status(*acpi_pkg_callback) (u8 object_type,
-				 union acpi_operand_object * source_object,
+				 union acpi_operand_object *source_object,
 				 union acpi_generic_state * state,
 				 void *context);
 
@@ -202,7 +218,9 @@ extern const u8 _acpi_ctype[];
 #define ACPI_IS_PRINT(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_SP | _ACPI_PU))
 #define ACPI_IS_ALPHA(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP))
 
-#endif				/* ACPI_USE_SYSTEM_CLIBRARY */
+#endif				/* !ACPI_USE_SYSTEM_CLIBRARY */
+
+#define ACPI_IS_ASCII(c)  ((c) < 0x80)
 
 /*
  * utcopy - Object construction and conversion interfaces
@@ -210,11 +228,11 @@ extern const u8 _acpi_ctype[];
 acpi_status
 acpi_ut_build_simple_object(union acpi_operand_object *obj,
 			    union acpi_object *user_obj,
-			    u8 * data_space, u32 * buffer_space_used);
+			    u8 *data_space, u32 *buffer_space_used);
 
 acpi_status
 acpi_ut_build_package_object(union acpi_operand_object *obj,
-			     u8 * buffer, u32 * space_used);
+			     u8 *buffer, u32 *space_used);
 
 acpi_status
 acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *obj,
@@ -287,9 +305,10 @@ acpi_ut_ptr_exit(u32 line_number,
 		 const char *function_name,
 		 const char *module_name, u32 component_id, u8 *ptr);
 
-void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id);
+void
+acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id);
 
-void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display);
+void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 offset);
 
 void acpi_ut_report_error(char *module_name, u32 line_number);
 
@@ -337,15 +356,19 @@ acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node,
  */
 acpi_status
 acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
-		    struct acpica_device_id **return_id);
+		    struct acpi_pnp_device_id ** return_id);
 
 acpi_status
 acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
-		    struct acpica_device_id **return_id);
+		    struct acpi_pnp_device_id ** return_id);
+
+acpi_status
+acpi_ut_execute_SUB(struct acpi_namespace_node *device_node,
+		    struct acpi_pnp_device_id **return_id);
 
 acpi_status
 acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
-		    struct acpica_device_id_list **return_cid_list);
+		    struct acpi_pnp_device_id_list ** return_cid_list);
 
 /*
  * utlock - reader/writer locks
@@ -479,15 +502,19 @@ acpi_ut_walk_package_tree(union acpi_operand_object *source_object,
 
 void acpi_ut_strupr(char *src_string);
 
+void acpi_ut_strlwr(char *src_string);
+
+int acpi_ut_stricmp(char *string1, char *string2);
+
 void acpi_ut_print_string(char *string, u8 max_length);
 
 u8 acpi_ut_valid_acpi_name(u32 name);
 
-acpi_name acpi_ut_repair_name(char *name);
+void acpi_ut_repair_name(char *name);
 
 u8 acpi_ut_valid_acpi_char(char character, u32 position);
 
-acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer);
+acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer);
 
 /* Values for Base above (16=Hex, 10=Decimal) */
 
@@ -508,12 +535,12 @@ acpi_ut_display_init_pathname(u8 type,
  * utresrc
  */
 acpi_status
-acpi_ut_walk_aml_resources(u8 * aml,
+acpi_ut_walk_aml_resources(u8 *aml,
 			   acpi_size aml_length,
 			   acpi_walk_aml_callback user_function,
 			   void **context);
 
-acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index);
+acpi_status acpi_ut_validate_resource(void *aml, u8 *return_index);
 
 u32 acpi_ut_get_descriptor_length(void *aml);
 
@@ -524,8 +551,7 @@ u8 acpi_ut_get_resource_header_length(void *aml);
 u8 acpi_ut_get_resource_type(void *aml);
 
 acpi_status
-acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc,
-			     u8 ** end_tag);
+acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag);
 
 /*
  * utmutex - mutex support
diff --git a/drivers/acpi/acpica/amlresrc.h b/drivers/acpi/acpica/amlresrc.h
index af49479..9684496 100644
--- a/drivers/acpi/acpica/amlresrc.h
+++ b/drivers/acpi/acpica/amlresrc.h
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: amlresrc.h - AML resource descriptors
diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c
index 465f021..57895db 100644
--- a/drivers/acpi/acpica/dscontrol.c
+++ b/drivers/acpi/acpica/dscontrol.c
@@ -280,7 +280,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
 
 			/*
 			 * Get the return value and save as the last result
-			 * value.  This is the only place where walk_state->return_desc
+			 * value. This is the only place where walk_state->return_desc
 			 * is set to anything other than zero!
 			 */
 			walk_state->return_desc = walk_state->operands[0];
diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c
index 3da6fd8..b5b904e 100644
--- a/drivers/acpi/acpica/dsfield.c
+++ b/drivers/acpi/acpica/dsfield.c
@@ -277,7 +277,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Process all named fields in a field declaration.  Names are
+ * DESCRIPTION: Process all named fields in a field declaration. Names are
  *              entered into the namespace.
  *
  ******************************************************************************/
diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c
index aa9a5d4..52eb4e0 100644
--- a/drivers/acpi/acpica/dsmethod.c
+++ b/drivers/acpi/acpica/dsmethod.c
@@ -170,7 +170,7 @@ acpi_ds_create_method_mutex(union acpi_operand_object *method_desc)
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Prepare a method for execution.  Parses the method if necessary,
+ * DESCRIPTION: Prepare a method for execution. Parses the method if necessary,
  *              increments the thread count, and waits at the method semaphore
  *              for clearance to execute.
  *
@@ -444,7 +444,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
  * RETURN:      Status
  *
  * DESCRIPTION: Restart a method that was preempted by another (nested) method
- *              invocation.  Handle the return value (if any) from the callee.
+ *              invocation. Handle the return value (if any) from the callee.
  *
  ******************************************************************************/
 
@@ -530,7 +530,7 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
  *
  * RETURN:      None
  *
- * DESCRIPTION: Terminate a control method.  Delete everything that the method
+ * DESCRIPTION: Terminate a control method. Delete everything that the method
  *              created, delete all locals and arguments, and delete the parse
  *              tree if requested.
  *
diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c
index 8d55ceb..9a83b7e 100644
--- a/drivers/acpi/acpica/dsmthdat.c
+++ b/drivers/acpi/acpica/dsmthdat.c
@@ -76,7 +76,7 @@ acpi_ds_method_data_get_type(u16 opcode,
  * RETURN:      Status
  *
  * DESCRIPTION: Initialize the data structures that hold the method's arguments
- *              and locals.  The data struct is an array of namespace nodes for
+ *              and locals. The data struct is an array of namespace nodes for
  *              each - this allows ref_of and de_ref_of to work properly for these
  *              special data types.
  *
@@ -129,7 +129,7 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state)
  *
  * RETURN:      None
  *
- * DESCRIPTION: Delete method locals and arguments.  Arguments are only
+ * DESCRIPTION: Delete method locals and arguments. Arguments are only
  *              deleted if this method was called from another method.
  *
  ******************************************************************************/
@@ -183,7 +183,7 @@ void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state)
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Initialize arguments for a method.  The parameter list is a list
+ * DESCRIPTION: Initialize arguments for a method. The parameter list is a list
  *              of ACPI operand objects, either null terminated or whose length
  *              is defined by max_param_count.
  *
@@ -401,7 +401,7 @@ acpi_ds_method_data_get_value(u8 type,
 		 * This means that either 1) The expected argument was
 		 * not passed to the method, or 2) A local variable
 		 * was referenced by the method (via the ASL)
-		 * before it was initialized.  Either case is an error.
+		 * before it was initialized. Either case is an error.
 		 */
 
 		/* If slack enabled, init the local_x/arg_x to an Integer of value zero */
@@ -465,7 +465,7 @@ acpi_ds_method_data_get_value(u8 type,
  *
  * RETURN:      None
  *
- * DESCRIPTION: Delete the entry at Opcode:Index.  Inserts
+ * DESCRIPTION: Delete the entry at Opcode:Index. Inserts
  *              a null into the stack slot after the object is deleted.
  *
  ******************************************************************************/
@@ -523,7 +523,7 @@ acpi_ds_method_data_delete_value(u8 type,
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Store a value in an Arg or Local.  The obj_desc is installed
+ * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed
  *              as the new value for the Arg or Local and the reference count
  *              for obj_desc is incremented.
  *
@@ -566,7 +566,7 @@ acpi_ds_store_object_to_local(u8 type,
 
 	/*
 	 * If the reference count on the object is more than one, we must
-	 * take a copy of the object before we store.  A reference count
+	 * take a copy of the object before we store. A reference count
 	 * of exactly 1 means that the object was just created during the
 	 * evaluation of an expression, and we can safely use it since it
 	 * is not used anywhere else.
diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c
index 68592dd..c9f15d3 100644
--- a/drivers/acpi/acpica/dsobject.c
+++ b/drivers/acpi/acpica/dsobject.c
@@ -293,7 +293,7 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
 
 	/*
 	 * Second arg is the buffer data (optional) byte_list can be either
-	 * individual bytes or a string initializer.  In either case, a
+	 * individual bytes or a string initializer. In either case, a
 	 * byte_list appears in the AML.
 	 */
 	arg = op->common.value.arg;	/* skip first arg */
@@ -568,7 +568,7 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state,
 
 	/*
 	 * Because of the execution pass through the non-control-method
-	 * parts of the table, we can arrive here twice.  Only init
+	 * parts of the table, we can arrive here twice. Only init
 	 * the named object node the first time through
 	 */
 	if (acpi_ns_get_attached_object(node)) {
@@ -618,7 +618,7 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state,
  * RETURN:      Status
  *
  * DESCRIPTION: Initialize a namespace object from a parser Op and its
- *              associated arguments.  The namespace object is a more compact
+ *              associated arguments. The namespace object is a more compact
  *              representation of the Op and its arguments.
  *
  ******************************************************************************/
diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c
index aa34d89..d09c6b4 100644
--- a/drivers/acpi/acpica/dsopcode.c
+++ b/drivers/acpi/acpica/dsopcode.c
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Module Name: dsopcode - Dispatcher suport for regions and fields
+ * Module Name: dsopcode - Dispatcher support for regions and fields
  *
  *****************************************************************************/
 
@@ -649,7 +649,8 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
 		    ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
 		     (op->common.parent->common.aml_opcode !=
 		      AML_VAR_PACKAGE_OP)
-		     && (op->common.parent->common.aml_opcode != AML_NAME_OP))) {
+		     && (op->common.parent->common.aml_opcode !=
+			 AML_NAME_OP))) {
 			walk_state->result_obj = obj_desc;
 		}
 	}
diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c
index 73a5447..afeb99f 100644
--- a/drivers/acpi/acpica/dsutils.c
+++ b/drivers/acpi/acpica/dsutils.c
@@ -61,7 +61,7 @@ ACPI_MODULE_NAME("dsutils")
  *
  * RETURN:      None.
  *
- * DESCRIPTION: Clear and remove a reference on an implicit return value.  Used
+ * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
  *              to delete "stale" return values (if enabled, the return value
  *              from every operator is saved at least momentarily, in case the
  *              parent method exits.)
@@ -107,7 +107,7 @@ void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state)
  *
  * DESCRIPTION: Implements the optional "implicit return".  We save the result
  *              of every ASL operator and control method invocation in case the
- *              parent method exit.  Before storing a new return value, we
+ *              parent method exit. Before storing a new return value, we
  *              delete the previous return value.
  *
  ******************************************************************************/
@@ -198,7 +198,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
 	 *
 	 * If there is no parent, or the parent is a scope_op, we are executing
 	 * at the method level. An executing method typically has no parent,
-	 * since each method is parsed separately.  A method invoked externally
+	 * since each method is parsed separately. A method invoked externally
 	 * via execute_control_method has a scope_op as the parent.
 	 */
 	if ((!op->common.parent) ||
@@ -223,7 +223,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
 	}
 
 	/*
-	 * Decide what to do with the result based on the parent.  If
+	 * Decide what to do with the result based on the parent. If
 	 * the parent opcode will not use the result, delete the object.
 	 * Otherwise leave it as is, it will be deleted when it is used
 	 * as an operand later.
@@ -266,7 +266,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
 
 		/*
 		 * These opcodes allow term_arg(s) as operands and therefore
-		 * the operands can be method calls.  The result is used.
+		 * the operands can be method calls. The result is used.
 		 */
 		goto result_used;
 
@@ -284,7 +284,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
 			AML_BANK_FIELD_OP)) {
 			/*
 			 * These opcodes allow term_arg(s) as operands and therefore
-			 * the operands can be method calls.  The result is used.
+			 * the operands can be method calls. The result is used.
 			 */
 			goto result_used;
 		}
@@ -329,9 +329,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Used after interpretation of an opcode.  If there is an internal
+ * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
  *              result descriptor, check if the parent opcode will actually use
- *              this result.  If not, delete the result now so that it will
+ *              this result. If not, delete the result now so that it will
  *              not become orphaned.
  *
  ******************************************************************************/
@@ -376,7 +376,7 @@ acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Resolve all operands to their values.  Used to prepare
+ * DESCRIPTION: Resolve all operands to their values. Used to prepare
  *              arguments to a control method invocation (a call from one
  *              method to another.)
  *
@@ -391,7 +391,7 @@ acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state)
 
 	/*
 	 * Attempt to resolve each of the valid operands
-	 * Method arguments are passed by reference, not by value.  This means
+	 * Method arguments are passed by reference, not by value. This means
 	 * that the actual objects are passed, not copies of the objects.
 	 */
 	for (i = 0; i < walk_state->num_operands; i++) {
@@ -451,7 +451,7 @@ void acpi_ds_clear_operands(struct acpi_walk_state *walk_state)
  * RETURN:      Status
  *
  * DESCRIPTION: Translate a parse tree object that is an argument to an AML
- *              opcode to the equivalent interpreter object.  This may include
+ *              opcode to the equivalent interpreter object. This may include
  *              looking up a name or entering a new name into the internal
  *              namespace.
  *
@@ -496,9 +496,9 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
 		/*
 		 * Special handling for buffer_field declarations. This is a deferred
 		 * opcode that unfortunately defines the field name as the last
-		 * parameter instead of the first.  We get here when we are performing
+		 * parameter instead of the first. We get here when we are performing
 		 * the deferred execution, so the actual name of the field is already
-		 * in the namespace.  We don't want to attempt to look it up again
+		 * in the namespace. We don't want to attempt to look it up again
 		 * because we may be executing in a different scope than where the
 		 * actual opcode exists.
 		 */
@@ -560,7 +560,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
 					 * indicate this to the interpreter, set the
 					 * object to the root
 					 */
-					obj_desc = ACPI_CAST_PTR(union
+					obj_desc =
+					    ACPI_CAST_PTR(union
 								 acpi_operand_object,
 								 acpi_gbl_root_node);
 					status = AE_OK;
@@ -604,8 +605,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
 			/*
 			 * If the name is null, this means that this is an
 			 * optional result parameter that was not specified
-			 * in the original ASL.  Create a Zero Constant for a
-			 * placeholder.  (Store to a constant is a Noop.)
+			 * in the original ASL. Create a Zero Constant for a
+			 * placeholder. (Store to a constant is a Noop.)
 			 */
 			opcode = AML_ZERO_OP;	/* Has no arguments! */
 
diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c
index 642f3c0..5859393 100644
--- a/drivers/acpi/acpica/dswexec.c
+++ b/drivers/acpi/acpica/dswexec.c
@@ -57,7 +57,7 @@ ACPI_MODULE_NAME("dswexec")
 /*
  * Dispatch table for opcode classes
  */
-static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch[] = {
+static acpi_execute_op acpi_gbl_op_type_dispatch[] = {
 	acpi_ex_opcode_0A_0T_1R,
 	acpi_ex_opcode_1A_0T_0R,
 	acpi_ex_opcode_1A_0T_1R,
@@ -204,7 +204,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
  * RETURN:      Status
  *
  * DESCRIPTION: Descending callback used during the execution of control
- *              methods.  This is where most operators and operands are
+ *              methods. This is where most operators and operands are
  *              dispatched to the interpreter.
  *
  ****************************************************************************/
@@ -297,7 +297,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
 		if (walk_state->walk_type & ACPI_WALK_METHOD) {
 			/*
 			 * Found a named object declaration during method execution;
-			 * we must enter this object into the namespace.  The created
+			 * we must enter this object into the namespace. The created
 			 * object is temporary and will be deleted upon completion of
 			 * the execution of this method.
 			 *
@@ -348,7 +348,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
  * RETURN:      Status
  *
  * DESCRIPTION: Ascending callback used during the execution of control
- *              methods.  The only thing we really need to do here is to
+ *              methods. The only thing we really need to do here is to
  *              notice the beginning of IF, ELSE, and WHILE blocks.
  *
  ****************************************************************************/
@@ -432,7 +432,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
 		if (ACPI_SUCCESS(status)) {
 			/*
 			 * Dispatch the request to the appropriate interpreter handler
-			 * routine.  There is one routine per opcode "type" based upon the
+			 * routine. There is one routine per opcode "type" based upon the
 			 * number of opcode arguments and return type.
 			 */
 			status =
diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c
index 89c0114..3798357 100644
--- a/drivers/acpi/acpica/dswload2.c
+++ b/drivers/acpi/acpica/dswload2.c
@@ -254,7 +254,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
 				    acpi_ut_get_type_name(node->type),
 				    acpi_ut_get_node_name(node)));
 
-			return (AE_AML_OPERAND_TYPE);
+			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 		}
 		break;
 
@@ -602,7 +602,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
 							  region_space,
 							  walk_state);
 				if (ACPI_FAILURE(status)) {
-					return (status);
+					return_ACPI_STATUS(status);
 				}
 
 				acpi_ex_exit_interpreter();
diff --git a/drivers/acpi/acpica/dswstate.c b/drivers/acpi/acpica/dswstate.c
index d0e6555..3e65a15 100644
--- a/drivers/acpi/acpica/dswstate.c
+++ b/drivers/acpi/acpica/dswstate.c
@@ -51,8 +51,9 @@
 ACPI_MODULE_NAME("dswstate")
 
   /* Local prototypes */
-static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *ws);
-static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *ws);
+static acpi_status
+acpi_ds_result_stack_push(struct acpi_walk_state *walk_state);
+static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state);
 
 /*******************************************************************************
  *
@@ -347,7 +348,7 @@ acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state)
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Pop this walk's object stack.  Objects on the stack are NOT
+ * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
  *              deleted by this routine.
  *
  ******************************************************************************/
@@ -491,7 +492,7 @@ acpi_ds_push_walk_state(struct acpi_walk_state *walk_state,
  * RETURN:      A walk_state object popped from the thread's stack
  *
  * DESCRIPTION: Remove and return the walkstate object that is at the head of
- *              the walk stack for the given walk list.  NULL indicates that
+ *              the walk stack for the given walk list. NULL indicates that
  *              the list is empty.
  *
  ******************************************************************************/
@@ -531,14 +532,17 @@ struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread)
  *
  * RETURN:      Pointer to the new walk state.
  *
- * DESCRIPTION: Allocate and initialize a new walk state.  The current walk
+ * DESCRIPTION: Allocate and initialize a new walk state. The current walk
  *              state is set to this new state.
  *
  ******************************************************************************/
 
-struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object
-						  *origin, union acpi_operand_object
-						  *method_desc, struct acpi_thread_state
+struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id,
+						  union acpi_parse_object
+						  *origin,
+						  union acpi_operand_object
+						  *method_desc,
+						  struct acpi_thread_state
 						  *thread)
 {
 	struct acpi_walk_state *walk_state;
@@ -653,7 +657,7 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
 		/*
 		 * Setup the current scope.
 		 * Find a Named Op that has a namespace node associated with it.
-		 * search upwards from this Op.  Current scope is the first
+		 * search upwards from this Op. Current scope is the first
 		 * Op with a namespace node.
 		 */
 		extra_op = parser_state->start_op;
@@ -704,13 +708,13 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state)
 	ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state);
 
 	if (!walk_state) {
-		return;
+		return_VOID;
 	}
 
 	if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) {
 		ACPI_ERROR((AE_INFO, "%p is not a valid walk state",
 			    walk_state));
-		return;
+		return_VOID;
 	}
 
 	/* There should not be any open scopes */
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index ef0193d..36d1205 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -89,7 +89,8 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)
 	/* Set the mask bit only if there are references to this GPE */
 
 	if (gpe_event_info->runtime_count) {
-		ACPI_SET_BIT(gpe_register_info->enable_for_run, (u8)register_bit);
+		ACPI_SET_BIT(gpe_register_info->enable_for_run,
+			     (u8)register_bit);
 	}
 
 	return_ACPI_STATUS(AE_OK);
@@ -106,8 +107,7 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)
  * DESCRIPTION: Clear a GPE of stale events and enable it.
  *
  ******************************************************************************/
-acpi_status
-acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
+acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
 {
 	acpi_status status;
 
@@ -131,8 +131,8 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
 	}
 
 	/* Enable the requested GPE */
-	status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
 
+	status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
 	return_ACPI_STATUS(status);
 }
 
@@ -150,7 +150,8 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
  *
  ******************************************************************************/
 
-acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
+acpi_status
+acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
 {
 	acpi_status status = AE_OK;
 
@@ -191,7 +192,8 @@ acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info
  *
  ******************************************************************************/
 
-acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
+acpi_status
+acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
 {
 	acpi_status status = AE_OK;
 
@@ -208,7 +210,8 @@ acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_i
 
 		status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
 		if (ACPI_SUCCESS(status)) {
-			status = acpi_hw_low_set_gpe(gpe_event_info,
+			status =
+			    acpi_hw_low_set_gpe(gpe_event_info,
 						     ACPI_GPE_DISABLE);
 		}
 
@@ -306,7 +309,8 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
 
 	/* A Non-NULL gpe_device means this is a GPE Block Device */
 
-	obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *)
+	obj_desc =
+	    acpi_ns_get_attached_object((struct acpi_namespace_node *)
 					       gpe_device);
 	if (!obj_desc || !obj_desc->device.gpe_block) {
 		return (NULL);
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c
index 8cf4c10..1571a61 100644
--- a/drivers/acpi/acpica/evgpeblk.c
+++ b/drivers/acpi/acpica/evgpeblk.c
@@ -486,7 +486,8 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 			if (ACPI_FAILURE(status)) {
 				ACPI_EXCEPTION((AE_INFO, status,
 					"Could not enable GPE 0x%02X",
-					gpe_index + gpe_block->block_base_number));
+					gpe_index +
+					gpe_block->block_base_number));
 				continue;
 			}
 
diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c
index cb50dd9..228a0c3 100644
--- a/drivers/acpi/acpica/evgpeutil.c
+++ b/drivers/acpi/acpica/evgpeutil.c
@@ -374,7 +374,8 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 				gpe_event_info->dispatch.handler = NULL;
 				gpe_event_info->flags &=
 				    ~ACPI_GPE_DISPATCH_MASK;
-			} else if ((gpe_event_info->
+			} else
+			    if ((gpe_event_info->
 				 flags & ACPI_GPE_DISPATCH_MASK) ==
 				ACPI_GPE_DISPATCH_NOTIFY) {
 
diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c
index 4c1c826..1474241 100644
--- a/drivers/acpi/acpica/evrgnini.c
+++ b/drivers/acpi/acpica/evrgnini.c
@@ -227,8 +227,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
 
 				/* Install a handler for this PCI root bridge */
 
-				status =
-				    acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
+				status = acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
 				if (ACPI_FAILURE(status)) {
 					if (status == AE_SAME_HANDLER) {
 						/*
@@ -350,8 +349,8 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
 static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
 {
 	acpi_status status;
-	struct acpica_device_id *hid;
-	struct acpica_device_id_list *cid;
+	struct acpi_pnp_device_id *hid;
+	struct acpi_pnp_device_id_list *cid;
 	u32 i;
 	u8 match;
 
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index 7587eb6..ae668f3 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -398,7 +398,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
  *
  ******************************************************************************/
 acpi_status
-acpi_install_global_event_handler(ACPI_GBL_EVENT_HANDLER handler, void *context)
+acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context)
 {
 	acpi_status status;
 
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c
index 87c5f23..3f30e75 100644
--- a/drivers/acpi/acpica/evxfgpe.c
+++ b/drivers/acpi/acpica/evxfgpe.c
@@ -221,7 +221,8 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device,
 	if (wake_device == ACPI_ROOT_OBJECT) {
 		device_node = acpi_gbl_root_node;
 	} else {
-		device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
+		device_node =
+		    ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
 	}
 
 	/* Validate WakeDevice is of type Device */
@@ -324,7 +325,8 @@ ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)
  *
  ******************************************************************************/
 
-acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
+acpi_status
+acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
 {
 	acpi_status status = AE_OK;
 	struct acpi_gpe_event_info *gpe_event_info;
@@ -567,7 +569,7 @@ acpi_install_gpe_block(acpi_handle gpe_device,
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE(status)) {
-		return (status);
+		return_ACPI_STATUS(status);
 	}
 
 	node = acpi_ns_validate_handle(gpe_device);
@@ -650,7 +652,7 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE(status)) {
-		return (status);
+		return_ACPI_STATUS(status);
 	}
 
 	node = acpi_ns_validate_handle(gpe_device);
@@ -694,8 +696,7 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
  *
  ******************************************************************************/
-acpi_status
-acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
+acpi_status acpi_get_gpe_device(u32 index, acpi_handle * gpe_device)
 {
 	struct acpi_gpe_device_info info;
 	acpi_status status;
diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c
index bfb062e..4492a4e 100644
--- a/drivers/acpi/acpica/exconvrt.c
+++ b/drivers/acpi/acpica/exconvrt.c
@@ -516,8 +516,8 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
 			string_length--;
 		}
 
-		return_desc = acpi_ut_create_string_object((acpi_size)
-							   string_length);
+		return_desc =
+		    acpi_ut_create_string_object((acpi_size) string_length);
 		if (!return_desc) {
 			return_ACPI_STATUS(AE_NO_MEMORY);
 		}
diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c
index 691d476..66554bc 100644
--- a/drivers/acpi/acpica/excreate.c
+++ b/drivers/acpi/acpica/excreate.c
@@ -78,7 +78,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
 	    (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
 		/*
 		 * Dereference an existing alias so that we don't create a chain
-		 * of aliases.  With this code, we guarantee that an alias is
+		 * of aliases. With this code, we guarantee that an alias is
 		 * always exactly one level of indirection away from the
 		 * actual aliased name.
 		 */
@@ -90,7 +90,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
 	/*
 	 * For objects that can never change (i.e., the NS node will
 	 * permanently point to the same object), we can simply attach
-	 * the object to the new NS node.  For other objects (such as
+	 * the object to the new NS node. For other objects (such as
 	 * Integers, buffers, etc.), we have to point the Alias node
 	 * to the original Node.
 	 */
@@ -139,7 +139,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
 
 		/*
 		 * The new alias assumes the type of the target, and it points
-		 * to the same object.  The reference count of the object has an
+		 * to the same object. The reference count of the object has an
 		 * additional reference to prevent deletion out from under either the
 		 * target node or the alias Node
 		 */
@@ -243,8 +243,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
 
 	/* Init object and attach to NS node */
 
-	obj_desc->mutex.sync_level =
-	    (u8) walk_state->operands[1]->integer.value;
+	obj_desc->mutex.sync_level = (u8)walk_state->operands[1]->integer.value;
 	obj_desc->mutex.node =
 	    (struct acpi_namespace_node *)walk_state->operands[0];
 
diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c
index bc5b9a6..d7c9f51 100644
--- a/drivers/acpi/acpica/exdebug.c
+++ b/drivers/acpi/acpica/exdebug.c
@@ -145,10 +145,10 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
 	case ACPI_TYPE_BUFFER:
 
 		acpi_os_printf("[0x%.2X]\n", (u32)source_desc->buffer.length);
-		acpi_ut_dump_buffer2(source_desc->buffer.pointer,
-				     (source_desc->buffer.length < 256) ?
-				     source_desc->buffer.length : 256,
-				     DB_BYTE_DISPLAY);
+		acpi_ut_dump_buffer(source_desc->buffer.pointer,
+				    (source_desc->buffer.length < 256) ?
+				    source_desc->buffer.length : 256,
+				    DB_BYTE_DISPLAY, 0);
 		break;
 
 	case ACPI_TYPE_STRING:
@@ -190,7 +190,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
 
 			acpi_os_printf("Table Index 0x%X\n",
 				       source_desc->reference.value);
-			return;
+			return_VOID;
 
 		default:
 			break;
diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c
index 213c081..858b43a 100644
--- a/drivers/acpi/acpica/exdump.c
+++ b/drivers/acpi/acpica/exdump.c
@@ -464,7 +464,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
 
 	ACPI_FUNCTION_NAME(ex_dump_operand)
 
-	    if (!((ACPI_LV_EXEC & acpi_dbg_level)
+	    if (!
+		((ACPI_LV_EXEC & acpi_dbg_level)
 		  && (_COMPONENT & acpi_dbg_layer))) {
 		return;
 	}
@@ -777,7 +778,7 @@ acpi_ex_dump_operands(union acpi_operand_object **operands,
  * PARAMETERS:  title               - Descriptive text
  *              value               - Value to be displayed
  *
- * DESCRIPTION: Object dump output formatting functions.  These functions
+ * DESCRIPTION: Object dump output formatting functions. These functions
  *              reduce the number of format strings required and keeps them
  *              all in one place for easy modification.
  *
@@ -810,7 +811,8 @@ void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags)
 	ACPI_FUNCTION_ENTRY();
 
 	if (!flags) {
-		if (!((ACPI_LV_OBJECTS & acpi_dbg_level)
+		if (!
+		    ((ACPI_LV_OBJECTS & acpi_dbg_level)
 		      && (_COMPONENT & acpi_dbg_layer))) {
 			return;
 		}
@@ -940,10 +942,11 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc,
 		acpi_os_printf("[Buffer] Length %.2X = ",
 			       obj_desc->buffer.length);
 		if (obj_desc->buffer.length) {
-			acpi_ut_dump_buffer(ACPI_CAST_PTR
-					    (u8, obj_desc->buffer.pointer),
-					    obj_desc->buffer.length,
-					    DB_DWORD_DISPLAY, _COMPONENT);
+			acpi_ut_debug_dump_buffer(ACPI_CAST_PTR
+						  (u8,
+						   obj_desc->buffer.pointer),
+						  obj_desc->buffer.length,
+						  DB_DWORD_DISPLAY, _COMPONENT);
 		} else {
 			acpi_os_printf("\n");
 		}
@@ -996,7 +999,8 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags)
 	}
 
 	if (!flags) {
-		if (!((ACPI_LV_OBJECTS & acpi_dbg_level)
+		if (!
+		    ((ACPI_LV_OBJECTS & acpi_dbg_level)
 		      && (_COMPONENT & acpi_dbg_layer))) {
 			return_VOID;
 		}
diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c
index dc092f5..ebc55fb 100644
--- a/drivers/acpi/acpica/exfield.c
+++ b/drivers/acpi/acpica/exfield.c
@@ -59,7 +59,7 @@ ACPI_MODULE_NAME("exfield")
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Read from a named field.  Returns either an Integer or a
+ * DESCRIPTION: Read from a named field. Returns either an Integer or a
  *              Buffer, depending on the size of the field.
  *
  ******************************************************************************/
@@ -149,7 +149,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
 	 * Allocate a buffer for the contents of the field.
 	 *
 	 * If the field is larger than the current integer width, create
-	 * a BUFFER to hold it.  Otherwise, use an INTEGER.  This allows
+	 * a BUFFER to hold it. Otherwise, use an INTEGER. This allows
 	 * the use of arithmetic operators on the returned value if the
 	 * field size is equal or smaller than an Integer.
 	 *
diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c
index a778415..aa2ccfb 100644
--- a/drivers/acpi/acpica/exfldio.c
+++ b/drivers/acpi/acpica/exfldio.c
@@ -54,8 +54,7 @@ ACPI_MODULE_NAME("exfldio")
 /* Local prototypes */
 static acpi_status
 acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
-		       u32 field_datum_byte_offset,
-		       u64 *value, u32 read_write);
+		       u32 field_datum_byte_offset, u64 *value, u32 read_write);
 
 static u8
 acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value);
@@ -155,7 +154,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
 #endif
 
 	/*
-	 * Validate the request.  The entire request from the byte offset for a
+	 * Validate the request. The entire request from the byte offset for a
 	 * length of one field datum (access width) must fit within the region.
 	 * (Region length is specified in bytes)
 	 */
@@ -183,7 +182,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
 		    obj_desc->common_field.access_byte_width) {
 			/*
 			 * This is the case where the access_type (acc_word, etc.) is wider
-			 * than the region itself.  For example, a region of length one
+			 * than the region itself. For example, a region of length one
 			 * byte, and a field with Dword access specified.
 			 */
 			ACPI_ERROR((AE_INFO,
@@ -321,7 +320,7 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
  *
  * DESCRIPTION: Check if a value is out of range of the field being written.
  *              Used to check if the values written to Index and Bank registers
- *              are out of range.  Normally, the value is simply truncated
+ *              are out of range. Normally, the value is simply truncated
  *              to fit the field, but this case is most likely a serious
  *              coding error in the ASL.
  *
@@ -370,7 +369,7 @@ acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value)
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Read or Write a single datum of a field.  The field_type is
+ * DESCRIPTION: Read or Write a single datum of a field. The field_type is
  *              demultiplexed here to handle the different types of fields
  *              (buffer_field, region_field, index_field, bank_field)
  *
@@ -860,7 +859,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
 	    ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
 	/*
 	 * We must have a buffer that is at least as long as the field
-	 * we are writing to.  This is because individual fields are
+	 * we are writing to. This is because individual fields are
 	 * indivisible and partial writes are not supported -- as per
 	 * the ACPI specification.
 	 */
@@ -875,7 +874,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
 
 		/*
 		 * Copy the original data to the new buffer, starting
-		 * at Byte zero.  All unused (upper) bytes of the
+		 * at Byte zero. All unused (upper) bytes of the
 		 * buffer will be 0.
 		 */
 		ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length);
diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c
index 271c0c5..8405870 100644
--- a/drivers/acpi/acpica/exmisc.c
+++ b/drivers/acpi/acpica/exmisc.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
@@ -254,7 +253,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
 	ACPI_FUNCTION_TRACE(ex_do_concatenate);
 
 	/*
-	 * Convert the second operand if necessary.  The first operand
+	 * Convert the second operand if necessary. The first operand
 	 * determines the type of the second operand, (See the Data Types
 	 * section of the ACPI specification.)  Both object types are
 	 * guaranteed to be either Integer/String/Buffer by the operand
@@ -573,7 +572,7 @@ acpi_ex_do_logical_op(u16 opcode,
 	ACPI_FUNCTION_TRACE(ex_do_logical_op);
 
 	/*
-	 * Convert the second operand if necessary.  The first operand
+	 * Convert the second operand if necessary. The first operand
 	 * determines the type of the second operand, (See the Data Types
 	 * section of the ACPI 3.0+ specification.)  Both object types are
 	 * guaranteed to be either Integer/String/Buffer by the operand
diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c
index bcceda5..d1f449d 100644
--- a/drivers/acpi/acpica/exmutex.c
+++ b/drivers/acpi/acpica/exmutex.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exmutex - ASL Mutex Acquire/Release functions
@@ -305,7 +304,7 @@ acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc)
 	ACPI_FUNCTION_TRACE(ex_release_mutex_object);
 
 	if (obj_desc->mutex.acquisition_depth == 0) {
-		return (AE_NOT_ACQUIRED);
+		return_ACPI_STATUS(AE_NOT_ACQUIRED);
 	}
 
 	/* Match multiple Acquires with multiple Releases */
@@ -462,7 +461,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
 	union acpi_operand_object *next = thread->acquired_mutex_list;
 	union acpi_operand_object *obj_desc;
 
-	ACPI_FUNCTION_ENTRY();
+	ACPI_FUNCTION_NAME(ex_release_all_mutexes);
 
 	/* Traverse the list of owned mutexes, releasing each one */
 
@@ -474,6 +473,10 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
 		obj_desc->mutex.next = NULL;
 		obj_desc->mutex.acquisition_depth = 0;
 
+		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+				  "Force-releasing held mutex: %p\n",
+				  obj_desc));
+
 		/* Release the mutex, special case for Global Lock */
 
 		if (obj_desc == acpi_gbl_global_lock_mutex) {
diff --git a/drivers/acpi/acpica/exnames.c b/drivers/acpi/acpica/exnames.c
index fcc75fa..2ff578a 100644
--- a/drivers/acpi/acpica/exnames.c
+++ b/drivers/acpi/acpica/exnames.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exnames - interpreter/scanner name load/execute
@@ -53,8 +52,7 @@ ACPI_MODULE_NAME("exnames")
 /* Local prototypes */
 static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs);
 
-static acpi_status
-acpi_ex_name_segment(u8 ** in_aml_address, char *name_string);
+static acpi_status acpi_ex_name_segment(u8 **in_aml_address, char *name_string);
 
 /*******************************************************************************
  *
@@ -64,7 +62,7 @@ acpi_ex_name_segment(u8 ** in_aml_address, char *name_string);
  *                                    (-1)==root,  0==none
  *              num_name_segs       - count of 4-character name segments
  *
- * RETURN:      A pointer to the allocated string segment.  This segment must
+ * RETURN:      A pointer to the allocated string segment. This segment must
  *              be deleted by the caller.
  *
  * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
@@ -178,7 +176,8 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
 
 	ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Bytes from stream:\n"));
 
-	for (index = 0; (index < ACPI_NAME_SIZE)
+	for (index = 0;
+	     (index < ACPI_NAME_SIZE)
 	     && (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) {
 		char_buf[index] = *aml_address++;
 		ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index]));
diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c
index 9ba8c73..bbf01e9 100644
--- a/drivers/acpi/acpica/exoparg1.c
+++ b/drivers/acpi/acpica/exoparg1.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exoparg1 - AML execution - opcodes with 1 argument
@@ -606,7 +605,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
 		}
 
 		/*
-		 * Set result to ONES (TRUE) if Value == 0.  Note:
+		 * Set result to ONES (TRUE) if Value == 0. Note:
 		 * return_desc->Integer.Value is initially == 0 (FALSE) from above.
 		 */
 		if (!operand[0]->integer.value) {
@@ -618,7 +617,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
 	case AML_INCREMENT_OP:	/* Increment (Operand)  */
 
 		/*
-		 * Create a new integer.  Can't just get the base integer and
+		 * Create a new integer. Can't just get the base integer and
 		 * increment it because it may be an Arg or Field.
 		 */
 		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
@@ -686,7 +685,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
 
 		/*
 		 * Note: The operand is not resolved at this point because we want to
-		 * get the associated object, not its value.  For example, we don't
+		 * get the associated object, not its value. For example, we don't
 		 * want to resolve a field_unit to its value, we want the actual
 		 * field_unit object.
 		 */
@@ -727,7 +726,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
 
 		/*
 		 * The type of the base object must be integer, buffer, string, or
-		 * package.  All others are not supported.
+		 * package. All others are not supported.
 		 *
 		 * NOTE: Integer is not specifically supported by the ACPI spec,
 		 * but is supported implicitly via implicit operand conversion.
@@ -965,7 +964,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
 				case ACPI_TYPE_PACKAGE:
 
 					/*
-					 * Return the referenced element of the package.  We must
+					 * Return the referenced element of the package. We must
 					 * add another reference to the referenced object, however.
 					 */
 					return_desc =
diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c
index 879e8a2..ee5634a 100644
--- a/drivers/acpi/acpica/exoparg2.c
+++ b/drivers/acpi/acpica/exoparg2.c
@@ -123,7 +123,7 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
 		/*
 		 * Dispatch the notify to the appropriate handler
 		 * NOTE: the request is queued for execution after this method
-		 * completes.  The notify handlers are NOT invoked synchronously
+		 * completes. The notify handlers are NOT invoked synchronously
 		 * from this thread -- because handlers may in turn run other
 		 * control methods.
 		 */
diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c
index 71fcc65..2c89b46 100644
--- a/drivers/acpi/acpica/exoparg3.c
+++ b/drivers/acpi/acpica/exoparg3.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exoparg3 - AML execution - opcodes with 3 arguments
@@ -158,7 +157,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
 	case AML_MID_OP:	/* Mid (Source[0], Index[1], Length[2], Result[3]) */
 
 		/*
-		 * Create the return object.  The Source operand is guaranteed to be
+		 * Create the return object. The Source operand is guaranteed to be
 		 * either a String or a Buffer, so just use its type.
 		 */
 		return_desc = acpi_ut_create_internal_object((operand[0])->
diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c
index 0786b86..3e08695 100644
--- a/drivers/acpi/acpica/exoparg6.c
+++ b/drivers/acpi/acpica/exoparg6.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exoparg6 - AML execution - opcodes with 6 arguments
@@ -198,7 +197,7 @@ acpi_ex_do_match(u32 match_op,
 		return (FALSE);
 	}
 
-	return logical_result;
+	return (logical_result);
 }
 
 /*******************************************************************************
@@ -269,7 +268,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
 		 * and the next should be examined.
 		 *
 		 * Upon finding a match, the loop will terminate via "break" at
-		 * the bottom.  If it terminates "normally", match_value will be
+		 * the bottom. If it terminates "normally", match_value will be
 		 * ACPI_UINT64_MAX (Ones) (its initial value) indicating that no
 		 * match was found.
 		 */
diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c
index 81eca60..ba9db4d 100644
--- a/drivers/acpi/acpica/exprep.c
+++ b/drivers/acpi/acpica/exprep.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities
@@ -78,8 +77,8 @@ acpi_ex_generate_access(u32 field_bit_offset,
  *              any_acc keyword.
  *
  * NOTE: Need to have the region_length in order to check for boundary
- *       conditions (end-of-region).  However, the region_length is a deferred
- *       operation.  Therefore, to complete this implementation, the generation
+ *       conditions (end-of-region). However, the region_length is a deferred
+ *       operation. Therefore, to complete this implementation, the generation
  *       of this access width must be deferred until the region length has
  *       been evaluated.
  *
@@ -308,7 +307,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
  * RETURN:      Status
  *
  * DESCRIPTION: Initialize the areas of the field object that are common
- *              to the various types of fields.  Note: This is very "sensitive"
+ *              to the various types of fields. Note: This is very "sensitive"
  *              code because we are solving the general case for field
  *              alignment.
  *
@@ -336,13 +335,13 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
 	obj_desc->common_field.bit_length = field_bit_length;
 
 	/*
-	 * Decode the access type so we can compute offsets.  The access type gives
+	 * Decode the access type so we can compute offsets. The access type gives
 	 * two pieces of information - the width of each field access and the
 	 * necessary byte_alignment (address granularity) of the access.
 	 *
 	 * For any_acc, the access_bit_width is the largest width that is both
 	 * necessary and possible in an attempt to access the whole field in one
-	 * I/O operation.  However, for any_acc, the byte_alignment is always one
+	 * I/O operation. However, for any_acc, the byte_alignment is always one
 	 * byte.
 	 *
 	 * For all Buffer Fields, the byte_alignment is always one byte.
@@ -363,7 +362,7 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
 
 	/*
 	 * base_byte_offset is the address of the start of the field within the
-	 * region.  It is the byte address of the first *datum* (field-width data
+	 * region. It is the byte address of the first *datum* (field-width data
 	 * unit) of the field. (i.e., the first datum that contains at least the
 	 * first *bit* of the field.)
 	 *
diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c
index 1f1ce0c..1db2c0b 100644
--- a/drivers/acpi/acpica/exregion.c
+++ b/drivers/acpi/acpica/exregion.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exregion - ACPI default op_region (address space) handlers
@@ -202,7 +201,7 @@ acpi_ex_system_memory_space_handler(u32 function,
 	 * Perform the memory read or write
 	 *
 	 * Note: For machines that do not support non-aligned transfers, the target
-	 * address was checked for alignment above.  We do not attempt to break the
+	 * address was checked for alignment above. We do not attempt to break the
 	 * transfer up into smaller (byte-size) chunks because the AML specifically
 	 * asked for a transfer width that the hardware may require.
 	 */
diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c
index fa50e77..6239956 100644
--- a/drivers/acpi/acpica/exresnte.c
+++ b/drivers/acpi/acpica/exresnte.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exresnte - AML Interpreter object resolution
@@ -58,8 +57,8 @@ ACPI_MODULE_NAME("exresnte")
  * PARAMETERS:  object_ptr      - Pointer to a location that contains
  *                                a pointer to a NS node, and will receive a
  *                                pointer to the resolved object.
- *              walk_state      - Current state.  Valid only if executing AML
- *                                code.  NULL if simply resolving an object
+ *              walk_state      - Current state. Valid only if executing AML
+ *                                code. NULL if simply resolving an object
  *
  * RETURN:      Status
  *
@@ -67,7 +66,7 @@ ACPI_MODULE_NAME("exresnte")
  *
  * Note: for some of the data types, the pointer attached to the Node
  * can be either a pointer to an actual internal object or a pointer into the
- * AML stream itself.  These types are currently:
+ * AML stream itself. These types are currently:
  *
  *      ACPI_TYPE_INTEGER
  *      ACPI_TYPE_STRING
@@ -89,7 +88,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
 	ACPI_FUNCTION_TRACE(ex_resolve_node_to_value);
 
 	/*
-	 * The stack pointer points to a struct acpi_namespace_node (Node).  Get the
+	 * The stack pointer points to a struct acpi_namespace_node (Node). Get the
 	 * object that is attached to the Node.
 	 */
 	node = *object_ptr;
diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c
index bbf40ac..cc176b2 100644
--- a/drivers/acpi/acpica/exresolv.c
+++ b/drivers/acpi/acpica/exresolv.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exresolv - AML Interpreter object resolution
@@ -327,7 +326,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Return the base object and type.  Traverse a reference list if
+ * DESCRIPTION: Return the base object and type. Traverse a reference list if
  *              necessary to get to the base object.
  *
  ******************************************************************************/
diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c
index f232fba..b9ebff2 100644
--- a/drivers/acpi/acpica/exresop.c
+++ b/drivers/acpi/acpica/exresop.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exresop - AML Interpreter operand/object resolution
@@ -87,7 +86,7 @@ acpi_ex_check_object_type(acpi_object_type type_needed,
 	if (type_needed == ACPI_TYPE_LOCAL_REFERENCE) {
 		/*
 		 * Allow the AML "Constant" opcodes (Zero, One, etc.) to be reference
-		 * objects and thus allow them to be targets.  (As per the ACPI
+		 * objects and thus allow them to be targets. (As per the ACPI
 		 * specification, a store to a constant is a noop.)
 		 */
 		if ((this_type == ACPI_TYPE_INTEGER) &&
@@ -337,7 +336,8 @@ acpi_ex_resolve_operands(u16 opcode,
 			if ((opcode == AML_STORE_OP) &&
 			    ((*stack_ptr)->common.type ==
 			     ACPI_TYPE_LOCAL_REFERENCE)
-			    && ((*stack_ptr)->reference.class == ACPI_REFCLASS_INDEX)) {
+			    && ((*stack_ptr)->reference.class ==
+				ACPI_REFCLASS_INDEX)) {
 				goto next_operand;
 			}
 			break;
@@ -638,7 +638,7 @@ acpi_ex_resolve_operands(u16 opcode,
 				if (acpi_gbl_enable_interpreter_slack) {
 					/*
 					 * Enable original behavior of Store(), allowing any and all
-					 * objects as the source operand.  The ACPI spec does not
+					 * objects as the source operand. The ACPI spec does not
 					 * allow this, however.
 					 */
 					break;
diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c
index 5fffe7a..90431f1 100644
--- a/drivers/acpi/acpica/exstore.c
+++ b/drivers/acpi/acpica/exstore.c
@@ -374,7 +374,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
  *              with the input value.
  *
  *              When storing into an object the data is converted to the
- *              target object type then stored in the object.  This means
+ *              target object type then stored in the object. This means
  *              that the target object type (for an initialized target) will
  *              not be changed by a store operation.
  *
@@ -491,7 +491,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
 				  acpi_ut_get_object_type_name(source_desc),
 				  source_desc, node));
 
-		/* No conversions for all other types.  Just attach the source object */
+		/* No conversions for all other types. Just attach the source object */
 
 		status = acpi_ns_attach_object(node, source_desc,
 					       source_desc->common.type);
diff --git a/drivers/acpi/acpica/exstoren.c b/drivers/acpi/acpica/exstoren.c
index b35bed5..87153bb 100644
--- a/drivers/acpi/acpica/exstoren.c
+++ b/drivers/acpi/acpica/exstoren.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exstoren - AML Interpreter object store support,
@@ -61,7 +60,7 @@ ACPI_MODULE_NAME("exstoren")
  *
  * RETURN:      Status, resolved object in source_desc_ptr.
  *
- * DESCRIPTION: Resolve an object.  If the object is a reference, dereference
+ * DESCRIPTION: Resolve an object. If the object is a reference, dereference
  *              it and return the actual object in the source_desc_ptr.
  *
  ******************************************************************************/
@@ -93,7 +92,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
 
 		/*
 		 * Stores into a Field/Region or into a Integer/Buffer/String
-		 * are all essentially the same.  This case handles the
+		 * are all essentially the same. This case handles the
 		 * "interchangeable" types Integer, String, and Buffer.
 		 */
 		if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
@@ -167,7 +166,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
  *
  * RETURN:      Status
  *
- * DESCRIPTION: "Store" an object to another object.  This may include
+ * DESCRIPTION: "Store" an object to another object. This may include
  *              converting the source type to the target type (implicit
  *              conversion), and a copy of the value of the source to
  *              the target.
@@ -178,14 +177,14 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
  *              with the input value.
  *
  *              When storing into an object the data is converted to the
- *              target object type then stored in the object.  This means
+ *              target object type then stored in the object. This means
  *              that the target object type (for an initialized target) will
  *              not be changed by a store operation.
  *
  *              This module allows destination types of Number, String,
  *              Buffer, and Package.
  *
- *              Assumes parameters are already validated.  NOTE: source_desc
+ *              Assumes parameters are already validated. NOTE: source_desc
  *              resolution (from a reference object) must be performed by
  *              the caller if necessary.
  *
diff --git a/drivers/acpi/acpica/exstorob.c b/drivers/acpi/acpica/exstorob.c
index 53c2484..b5f339c 100644
--- a/drivers/acpi/acpica/exstorob.c
+++ b/drivers/acpi/acpica/exstorob.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exstorob - AML Interpreter object store support, store to object
@@ -108,7 +107,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
 #ifdef ACPI_OBSOLETE_BEHAVIOR
 		/*
 		 * NOTE: ACPI versions up to 3.0 specified that the buffer must be
-		 * truncated if the string is smaller than the buffer.  However, "other"
+		 * truncated if the string is smaller than the buffer. However, "other"
 		 * implementations of ACPI never did this and thus became the defacto
 		 * standard. ACPI 3.0A changes this behavior such that the buffer
 		 * is no longer truncated.
@@ -117,7 +116,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
 		/*
 		 * OBSOLETE BEHAVIOR:
 		 * If the original source was a string, we must truncate the buffer,
-		 * according to the ACPI spec.  Integer-to-Buffer and Buffer-to-Buffer
+		 * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer
 		 * copy must not truncate the original buffer.
 		 */
 		if (original_src_type == ACPI_TYPE_STRING) {
diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c
index b760641..c8a0ad5 100644
--- a/drivers/acpi/acpica/exsystem.c
+++ b/drivers/acpi/acpica/exsystem.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exsystem - Interface to OS services
@@ -59,7 +58,7 @@ ACPI_MODULE_NAME("exsystem")
  * RETURN:      Status
  *
  * DESCRIPTION: Implements a semaphore wait with a check to see if the
- *              semaphore is available immediately.  If it is not, the
+ *              semaphore is available immediately. If it is not, the
  *              interpreter is released before waiting.
  *
  ******************************************************************************/
@@ -104,7 +103,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
  * RETURN:      Status
  *
  * DESCRIPTION: Implements a mutex wait with a check to see if the
- *              mutex is available immediately.  If it is not, the
+ *              mutex is available immediately. If it is not, the
  *              interpreter is released before waiting.
  *
  ******************************************************************************/
@@ -152,7 +151,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout)
  * DESCRIPTION: Suspend running thread for specified amount of time.
  *              Note: ACPI specification requires that Stall() does not
  *              relinquish the processor, and delays longer than 100 usec
- *              should use Sleep() instead.  We allow stalls up to 255 usec
+ *              should use Sleep() instead. We allow stalls up to 255 usec
  *              for compatibility with other interpreters and existing BIOSs.
  *
  ******************************************************************************/
@@ -254,7 +253,7 @@ acpi_status acpi_ex_system_signal_event(union acpi_operand_object * obj_desc)
  * RETURN:      Status
  *
  * DESCRIPTION: Provides an access point to perform synchronization operations
- *              within the AML.  This operation is a request to wait for an
+ *              within the AML. This operation is a request to wait for an
  *              event.
  *
  ******************************************************************************/
diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c
index d1ab791..264d22d 100644
--- a/drivers/acpi/acpica/exutils.c
+++ b/drivers/acpi/acpica/exutils.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exutils - interpreter/scanner utilities
@@ -45,12 +44,12 @@
 /*
  * DEFINE_AML_GLOBALS is tested in amlcode.h
  * to determine whether certain global names should be "defined" or only
- * "declared" in the current compilation.  This enhances maintainability
+ * "declared" in the current compilation. This enhances maintainability
  * by enabling a single header file to embody all knowledge of the names
  * in question.
  *
  * Exactly one module of any executable should #define DEFINE_GLOBALS
- * before #including the header files which use this convention.  The
+ * before #including the header files which use this convention. The
  * names in question will be defined and initialized in that module,
  * and declared as extern in all other modules which #include those
  * header files.
diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c
index a1e71d0..90a9aea 100644
--- a/drivers/acpi/acpica/hwacpi.c
+++ b/drivers/acpi/acpica/hwacpi.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
@@ -136,7 +135,7 @@ acpi_status acpi_hw_set_mode(u32 mode)
  *
  * RETURN:      SYS_MODE_ACPI or SYS_MODE_LEGACY
  *
- * DESCRIPTION: Return current operating state of system.  Determined by
+ * DESCRIPTION: Return current operating state of system. Determined by
  *              querying the SCI_EN bit.
  *
  ******************************************************************************/
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c
index db40765..6456004 100644
--- a/drivers/acpi/acpica/hwgpe.c
+++ b/drivers/acpi/acpica/hwgpe.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: hwgpe - Low level GPE enable/disable/clear functions
@@ -339,7 +338,8 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 
 acpi_status
 acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
-				 struct acpi_gpe_block_info *gpe_block, void *context)
+				 struct acpi_gpe_block_info * gpe_block,
+				 void *context)
 {
 	u32 i;
 	acpi_status status;
diff --git a/drivers/acpi/acpica/hwpci.c b/drivers/acpi/acpica/hwpci.c
index 1455ddc..65bc345 100644
--- a/drivers/acpi/acpica/hwpci.c
+++ b/drivers/acpi/acpica/hwpci.c
@@ -259,7 +259,7 @@ acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
 		status = acpi_hw_get_pci_device_info(pci_id, info->device,
 						     &bus_number, &is_bridge);
 		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
+			return (status);
 		}
 
 		info = info->next;
@@ -271,7 +271,7 @@ acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
 			  pci_id->segment, pci_id->bus, pci_id->device,
 			  pci_id->function, status, bus_number, is_bridge));
 
-	return_ACPI_STATUS(AE_OK);
+	return (AE_OK);
 }
 
 /*******************************************************************************
diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c
index 4af6d20..f4e5750 100644
--- a/drivers/acpi/acpica/hwregs.c
+++ b/drivers/acpi/acpica/hwregs.c
@@ -1,4 +1,3 @@
-
 /*******************************************************************************
  *
  * Module Name: hwregs - Read/write access functions for the various ACPI
diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c
index b6411f1..bfdce22 100644
--- a/drivers/acpi/acpica/hwtimer.c
+++ b/drivers/acpi/acpica/hwtimer.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Name: hwtimer.c - ACPI Power Management Timer Interface
@@ -101,8 +100,7 @@ acpi_status acpi_get_timer(u32 * ticks)
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
-	status =
-	    acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block);
+	status = acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block);
 
 	return_ACPI_STATUS(status);
 }
@@ -129,7 +127,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_timer)
  *              a versatile and accurate timer.
  *
  *              Note that this function accommodates only a single timer
- *              rollover.  Thus for 24-bit timers, this function should only
+ *              rollover. Thus for 24-bit timers, this function should only
  *              be used for calculating durations less than ~4.6 seconds
  *              (~20 minutes for 32-bit timers) -- calculations below:
  *
diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c
index c99d546..b6aae58 100644
--- a/drivers/acpi/acpica/hwvalid.c
+++ b/drivers/acpi/acpica/hwvalid.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: hwvalid - I/O request validation
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c
index 7bfd649..05a154c 100644
--- a/drivers/acpi/acpica/hwxface.c
+++ b/drivers/acpi/acpica/hwxface.c
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: hwxface - Public ACPICA hardware interfaces
diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c
index 0ff1ece..ae443fe2 100644
--- a/drivers/acpi/acpica/hwxfsleep.c
+++ b/drivers/acpi/acpica/hwxfsleep.c
@@ -49,8 +49,7 @@
 ACPI_MODULE_NAME("hwxfsleep")
 
 /* Local prototypes */
-static acpi_status
-acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id);
+static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id);
 
 /*
  * Dispatch table used to efficiently branch to the various sleep
@@ -234,8 +233,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
  *              function.
  *
  ******************************************************************************/
-static acpi_status
-acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id)
+static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id)
 {
 	acpi_status status;
 	struct acpi_sleep_functions *sleep_functions =
@@ -369,8 +367,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
 		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
 	}
 
-	status =
-	    acpi_hw_sleep_dispatch(sleep_state, ACPI_SLEEP_FUNCTION_ID);
+	status = acpi_hw_sleep_dispatch(sleep_state, ACPI_SLEEP_FUNCTION_ID);
 	return_ACPI_STATUS(status);
 }
 
@@ -396,8 +393,7 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
 	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);
 
 	status =
-	    acpi_hw_sleep_dispatch(sleep_state,
-				   ACPI_WAKE_PREP_FUNCTION_ID);
+	    acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_PREP_FUNCTION_ID);
 	return_ACPI_STATUS(status);
 }
 
diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c
index 23db53c..d70eaf3 100644
--- a/drivers/acpi/acpica/nsaccess.c
+++ b/drivers/acpi/acpica/nsaccess.c
@@ -110,11 +110,11 @@ acpi_status acpi_ns_root_initialize(void)
 		status = acpi_ns_lookup(NULL, init_val->name, init_val->type,
 					ACPI_IMODE_LOAD_PASS2,
 					ACPI_NS_NO_UPSEARCH, NULL, &new_node);
-
-		if (ACPI_FAILURE(status) || (!new_node)) {	/* Must be on same line for code converter */
+		if (ACPI_FAILURE(status)) {
 			ACPI_EXCEPTION((AE_INFO, status,
 					"Could not create predefined name %s",
 					init_val->name));
+			continue;
 		}
 
 		/*
@@ -179,8 +179,7 @@ acpi_status acpi_ns_root_initialize(void)
 
 				/* Build an object around the static string */
 
-				obj_desc->string.length =
-				    (u32) ACPI_STRLEN(val);
+				obj_desc->string.length = (u32)ACPI_STRLEN(val);
 				obj_desc->string.pointer = val;
 				obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
 				break;
diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c
index ac389e5..15143c4 100644
--- a/drivers/acpi/acpica/nsalloc.c
+++ b/drivers/acpi/acpica/nsalloc.c
@@ -332,7 +332,7 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node)
  *
  * RETURN:      None.
  *
- * DESCRIPTION: Delete a subtree of the namespace.  This includes all objects
+ * DESCRIPTION: Delete a subtree of the namespace. This includes all objects
  *              stored within the subtree.
  *
  ******************************************************************************/
@@ -418,7 +418,7 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node)
  * RETURN:      Status
  *
  * DESCRIPTION: Delete entries within the namespace that are owned by a
- *              specific ID.  Used to delete entire ACPI tables.  All
+ *              specific ID. Used to delete entire ACPI tables. All
  *              reference counts are updated.
  *
  * MUTEX:       Locks namespace during deletion walk.
diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c
index 2526aaf..924b3c7 100644
--- a/drivers/acpi/acpica/nsdump.c
+++ b/drivers/acpi/acpica/nsdump.c
@@ -209,14 +209,6 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
 				      "Invalid ACPI Object Type 0x%08X", type));
 		}
 
-		if (!acpi_ut_valid_acpi_name(this_node->name.integer)) {
-			this_node->name.integer =
-			    acpi_ut_repair_name(this_node->name.ascii);
-
-			ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X",
-				      this_node->name.integer));
-		}
-
 		acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node));
 	}
 
@@ -700,7 +692,7 @@ void acpi_ns_dump_entry(acpi_handle handle, u32 debug_level)
  *
  * PARAMETERS:  search_base         - Root of subtree to be dumped, or
  *                                    NS_ALL to dump the entire namespace
- *              max_depth           - Maximum depth of dump.  Use INT_MAX
+ *              max_depth           - Maximum depth of dump. Use INT_MAX
  *                                    for an effectively unlimited depth.
  *
  * RETURN:      None
diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c
index 95ffe8d..4328e2a 100644
--- a/drivers/acpi/acpica/nsinit.c
+++ b/drivers/acpi/acpica/nsinit.c
@@ -96,8 +96,8 @@ acpi_status acpi_ns_initialize_objects(void)
 	/* Walk entire namespace from the supplied root */
 
 	status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
-				     ACPI_UINT32_MAX, acpi_ns_init_one_object, NULL,
-				     &info, NULL);
+				     ACPI_UINT32_MAX, acpi_ns_init_one_object,
+				     NULL, &info, NULL);
 	if (ACPI_FAILURE(status)) {
 		ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
 	}
diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c
index 76935ff..911f991 100644
--- a/drivers/acpi/acpica/nsload.c
+++ b/drivers/acpi/acpica/nsload.c
@@ -80,8 +80,8 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
 
 	/*
 	 * Parse the table and load the namespace with all named
-	 * objects found within.  Control methods are NOT parsed
-	 * at this time.  In fact, the control methods cannot be
+	 * objects found within. Control methods are NOT parsed
+	 * at this time. In fact, the control methods cannot be
 	 * parsed until the entire namespace is loaded, because
 	 * if a control method makes a forward reference (call)
 	 * to another control method, we can't continue parsing
@@ -122,7 +122,7 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
 	}
 
 	/*
-	 * Now we can parse the control methods.  We always parse
+	 * Now we can parse the control methods. We always parse
 	 * them here for a sanity check, and if configured for
 	 * just-in-time parsing, we delete the control method
 	 * parse trees.
@@ -166,7 +166,7 @@ acpi_status acpi_ns_load_namespace(void)
 	}
 
 	/*
-	 * Load the namespace.  The DSDT is required,
+	 * Load the namespace. The DSDT is required,
 	 * but the SSDT and PSDT tables are optional.
 	 */
 	status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT);
@@ -283,7 +283,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle)
  *  RETURN:         Status
  *
  *  DESCRIPTION:    Shrinks the namespace, typically in response to an undocking
- *                  event.  Deletes an entire subtree starting from (and
+ *                  event. Deletes an entire subtree starting from (and
  *                  including) the given handle.
  *
  ******************************************************************************/
diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c
index 96e0eb6..55a175e 100644
--- a/drivers/acpi/acpica/nsnames.c
+++ b/drivers/acpi/acpica/nsnames.c
@@ -195,7 +195,7 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
 			ACPI_ERROR((AE_INFO,
 				    "Invalid Namespace Node (%p) while traversing namespace",
 				    next_node));
-			return 0;
+			return (0);
 		}
 		size += ACPI_PATH_SEGMENT_LENGTH;
 		next_node = next_node->parent;
diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c
index d6c9a3c..e69f7fa 100644
--- a/drivers/acpi/acpica/nsobject.c
+++ b/drivers/acpi/acpica/nsobject.c
@@ -61,7 +61,7 @@ ACPI_MODULE_NAME("nsobject")
  * RETURN:      Status
  *
  * DESCRIPTION: Record the given object as the value associated with the
- *              name whose acpi_handle is passed.  If Object is NULL
+ *              name whose acpi_handle is passed. If Object is NULL
  *              and Type is ACPI_TYPE_ANY, set the name as having no value.
  *              Note: Future may require that the Node->Flags field be passed
  *              as a parameter.
@@ -133,7 +133,7 @@ acpi_ns_attach_object(struct acpi_namespace_node *node,
 		 ((struct acpi_namespace_node *)object)->object) {
 		/*
 		 * Value passed is a name handle and that name has a
-		 * non-null value.  Use that name's value and type.
+		 * non-null value. Use that name's value and type.
 		 */
 		obj_desc = ((struct acpi_namespace_node *)object)->object;
 		object_type = ((struct acpi_namespace_node *)object)->type;
@@ -321,7 +321,7 @@ union acpi_operand_object *acpi_ns_get_secondary_object(union
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Low-level attach data.  Create and attach a Data object.
+ * DESCRIPTION: Low-level attach data. Create and attach a Data object.
  *
  ******************************************************************************/
 
@@ -377,7 +377,7 @@ acpi_ns_attach_data(struct acpi_namespace_node *node,
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Low-level detach data.  Delete the data node, but the caller
+ * DESCRIPTION: Low-level detach data. Delete the data node, but the caller
  *              is responsible for the actual data.
  *
  ******************************************************************************/
diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c
index ec7ba2d..233f756 100644
--- a/drivers/acpi/acpica/nsparse.c
+++ b/drivers/acpi/acpica/nsparse.c
@@ -168,11 +168,11 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
 	/*
 	 * AML Parse, pass 1
 	 *
-	 * In this pass, we load most of the namespace.  Control methods
-	 * are not parsed until later.  A parse tree is not created.  Instead,
-	 * each Parser Op subtree is deleted when it is finished.  This saves
+	 * In this pass, we load most of the namespace. Control methods
+	 * are not parsed until later. A parse tree is not created. Instead,
+	 * each Parser Op subtree is deleted when it is finished. This saves
 	 * a great deal of memory, and allows a small cache of parse objects
-	 * to service the entire parse.  The second pass of the parse then
+	 * to service the entire parse. The second pass of the parse then
 	 * performs another complete parse of the AML.
 	 */
 	ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n"));
diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c
index 456cc85..1d2d8ff 100644
--- a/drivers/acpi/acpica/nssearch.c
+++ b/drivers/acpi/acpica/nssearch.c
@@ -314,22 +314,7 @@ acpi_ns_search_and_enter(u32 target_name,
 	 * this problem, and we want to be able to enable ACPI support for them,
 	 * even though there are a few bad names.
 	 */
-	if (!acpi_ut_valid_acpi_name(target_name)) {
-		target_name =
-		    acpi_ut_repair_name(ACPI_CAST_PTR(char, &target_name));
-
-		/* Report warning only if in strict mode or debug mode */
-
-		if (!acpi_gbl_enable_interpreter_slack) {
-			ACPI_WARNING((AE_INFO,
-				      "Found bad character(s) in name, repaired: [%4.4s]\n",
-				      ACPI_CAST_PTR(char, &target_name)));
-		} else {
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-					  "Found bad character(s) in name, repaired: [%4.4s]\n",
-					  ACPI_CAST_PTR(char, &target_name)));
-		}
-	}
+	acpi_ut_repair_name(ACPI_CAST_PTR(char, &target_name));
 
 	/* Try to find the name in the namespace level specified by the caller */
 
diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c
index ef753a4..b5b4cb7 100644
--- a/drivers/acpi/acpica/nsutils.c
+++ b/drivers/acpi/acpica/nsutils.c
@@ -530,7 +530,7 @@ acpi_ns_externalize_name(u32 internal_name_length,
 	    ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
 
 	/*
-	 * Check to see if we're still in bounds.  If not, there's a problem
+	 * Check to see if we're still in bounds. If not, there's a problem
 	 * with internal_name (invalid format).
 	 */
 	if (required_length > internal_name_length) {
@@ -557,10 +557,14 @@ acpi_ns_externalize_name(u32 internal_name_length,
 				(*converted_name)[j++] = '.';
 			}
 
-			(*converted_name)[j++] = internal_name[names_index++];
-			(*converted_name)[j++] = internal_name[names_index++];
-			(*converted_name)[j++] = internal_name[names_index++];
-			(*converted_name)[j++] = internal_name[names_index++];
+			/* Copy and validate the 4-char name segment */
+
+			ACPI_MOVE_NAME(&(*converted_name)[j],
+				       &internal_name[names_index]);
+			acpi_ut_repair_name(&(*converted_name)[j]);
+
+			j += ACPI_NAME_SIZE;
+			names_index += ACPI_NAME_SIZE;
 		}
 	}
 
@@ -681,7 +685,7 @@ u32 acpi_ns_opens_scope(acpi_object_type type)
  *                            \ (backslash) and ^ (carat) prefixes, and the
  *                            . (period) to separate segments are supported.
  *              prefix_node  - Root of subtree to be searched, or NS_ALL for the
- *                            root of the name space.  If Name is fully
+ *                            root of the name space. If Name is fully
  *                            qualified (first s8 is '\'), the passed value
  *                            of Scope will not be accessed.
  *              flags       - Used to indicate whether to perform upsearch or
@@ -689,7 +693,7 @@ u32 acpi_ns_opens_scope(acpi_object_type type)
  *              return_node - Where the Node is returned
  *
  * DESCRIPTION: Look up a name relative to a given scope and return the
- *              corresponding Node.  NOTE: Scope can be null.
+ *              corresponding Node. NOTE: Scope can be null.
  *
  * MUTEX:       Locks namespace
  *
diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c
index 730bccc..0483877 100644
--- a/drivers/acpi/acpica/nswalk.c
+++ b/drivers/acpi/acpica/nswalk.c
@@ -60,8 +60,8 @@ ACPI_MODULE_NAME("nswalk")
  * RETURN:      struct acpi_namespace_node - Pointer to the NEXT child or NULL if
  *                                    none is found.
  *
- * DESCRIPTION: Return the next peer node within the namespace.  If Handle
- *              is valid, Scope is ignored.  Otherwise, the first node
+ * DESCRIPTION: Return the next peer node within the namespace. If Handle
+ *              is valid, Scope is ignored. Otherwise, the first node
  *              within Scope is returned.
  *
  ******************************************************************************/
@@ -97,8 +97,8 @@ struct acpi_namespace_node *acpi_ns_get_next_node(struct acpi_namespace_node
  * RETURN:      struct acpi_namespace_node - Pointer to the NEXT child or NULL if
  *                                    none is found.
  *
- * DESCRIPTION: Return the next peer node within the namespace.  If Handle
- *              is valid, Scope is ignored.  Otherwise, the first node
+ * DESCRIPTION: Return the next peer node within the namespace. If Handle
+ *              is valid, Scope is ignored. Otherwise, the first node
  *              within Scope is returned.
  *
  ******************************************************************************/
@@ -305,7 +305,7 @@ acpi_ns_walk_namespace(acpi_object_type type,
 
 		/*
 		 * Depth first search: Attempt to go down another level in the
-		 * namespace if we are allowed to.  Don't go any further if we have
+		 * namespace if we are allowed to. Don't go any further if we have
 		 * reached the caller specified maximum depth or if the user
 		 * function has specified that the maximum depth has been reached.
 		 */
diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c
index 9692e67..d6a9f77 100644
--- a/drivers/acpi/acpica/nsxfeval.c
+++ b/drivers/acpi/acpica/nsxfeval.c
@@ -61,16 +61,16 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info);
  * PARAMETERS:  handle              - Object handle (optional)
  *              pathname            - Object pathname (optional)
  *              external_params     - List of parameters to pass to method,
- *                                    terminated by NULL.  May be NULL
+ *                                    terminated by NULL. May be NULL
  *                                    if no parameters are being passed.
  *              return_buffer       - Where to put method's return value (if
- *                                    any).  If NULL, no value is returned.
+ *                                    any). If NULL, no value is returned.
  *              return_type         - Expected type of return object
  *
  * RETURN:      Status
  *
  * DESCRIPTION: Find and evaluate the given object, passing the given
- *              parameters if necessary.  One of "Handle" or "Pathname" must
+ *              parameters if necessary. One of "Handle" or "Pathname" must
  *              be valid (non-null)
  *
  ******************************************************************************/
@@ -155,15 +155,15 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed)
  * PARAMETERS:  handle              - Object handle (optional)
  *              pathname            - Object pathname (optional)
  *              external_params     - List of parameters to pass to method,
- *                                    terminated by NULL.  May be NULL
+ *                                    terminated by NULL. May be NULL
  *                                    if no parameters are being passed.
  *              return_buffer       - Where to put method's return value (if
- *                                    any).  If NULL, no value is returned.
+ *                                    any). If NULL, no value is returned.
  *
  * RETURN:      Status
  *
  * DESCRIPTION: Find and evaluate the given object, passing the given
- *              parameters if necessary.  One of "Handle" or "Pathname" must
+ *              parameters if necessary. One of "Handle" or "Pathname" must
  *              be valid (non-null)
  *
  ******************************************************************************/
@@ -542,15 +542,15 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
 	acpi_status status;
 	struct acpi_namespace_node *node;
 	u32 flags;
-	struct acpica_device_id *hid;
-	struct acpica_device_id_list *cid;
+	struct acpi_pnp_device_id *hid;
+	struct acpi_pnp_device_id_list *cid;
 	u32 i;
 	u8 found;
 	int no_match;
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE(status)) {
-		return (status);
+		return_ACPI_STATUS(status);
 	}
 
 	node = acpi_ns_validate_handle(obj_handle);
@@ -656,7 +656,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
  *              starting (and ending) at the object specified by start_handle.
  *              The user_function is called whenever an object of type
- *              Device is found.  If the user function returns
+ *              Device is found. If the user function returns
  *              a non-zero value, the search is terminated immediately and this
  *              value is returned to the caller.
  *
diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c
index 08e9610..811c6f1 100644
--- a/drivers/acpi/acpica/nsxfname.c
+++ b/drivers/acpi/acpica/nsxfname.c
@@ -53,8 +53,8 @@
 ACPI_MODULE_NAME("nsxfname")
 
 /* Local prototypes */
-static char *acpi_ns_copy_device_id(struct acpica_device_id *dest,
-				    struct acpica_device_id *source,
+static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
+				    struct acpi_pnp_device_id *source,
 				    char *string_area);
 
 /******************************************************************************
@@ -69,8 +69,8 @@ static char *acpi_ns_copy_device_id(struct acpica_device_id *dest,
  * RETURN:      Status
  *
  * DESCRIPTION: This routine will search for a caller specified name in the
- *              name space.  The caller can restrict the search region by
- *              specifying a non NULL parent.  The parent value is itself a
+ *              name space. The caller can restrict the search region by
+ *              specifying a non NULL parent. The parent value is itself a
  *              namespace handle.
  *
  ******************************************************************************/
@@ -149,7 +149,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_handle)
  * RETURN:      Pointer to a string containing the fully qualified Name.
  *
  * DESCRIPTION: This routine returns the fully qualified name associated with
- *              the Handle parameter.  This and the acpi_pathname_to_handle are
+ *              the Handle parameter. This and the acpi_pathname_to_handle are
  *              complementary functions.
  *
  ******************************************************************************/
@@ -202,8 +202,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
 
 	/* Just copy the ACPI name from the Node and zero terminate it */
 
-	ACPI_STRNCPY(buffer->pointer, acpi_ut_get_node_name(node),
-		     ACPI_NAME_SIZE);
+	ACPI_MOVE_NAME(buffer->pointer, acpi_ut_get_node_name(node));
 	((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0;
 	status = AE_OK;
 
@@ -219,20 +218,21 @@ ACPI_EXPORT_SYMBOL(acpi_get_name)
  *
  * FUNCTION:    acpi_ns_copy_device_id
  *
- * PARAMETERS:  dest                - Pointer to the destination DEVICE_ID
- *              source              - Pointer to the source DEVICE_ID
+ * PARAMETERS:  dest                - Pointer to the destination PNP_DEVICE_ID
+ *              source              - Pointer to the source PNP_DEVICE_ID
  *              string_area         - Pointer to where to copy the dest string
  *
  * RETURN:      Pointer to the next string area
  *
- * DESCRIPTION: Copy a single DEVICE_ID, including the string data.
+ * DESCRIPTION: Copy a single PNP_DEVICE_ID, including the string data.
  *
  ******************************************************************************/
-static char *acpi_ns_copy_device_id(struct acpica_device_id *dest,
-				    struct acpica_device_id *source,
+static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
+				    struct acpi_pnp_device_id *source,
 				    char *string_area)
 {
-	/* Create the destination DEVICE_ID */
+
+	/* Create the destination PNP_DEVICE_ID */
 
 	dest->string = string_area;
 	dest->length = source->length;
@@ -256,8 +256,8 @@ static char *acpi_ns_copy_device_id(struct acpica_device_id *dest,
  *              namespace node and possibly by running several standard
  *              control methods (Such as in the case of a device.)
  *
- * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA,
- * _ADR, _sx_w, and _sx_d methods.
+ * For Device and Processor objects, run the Device _HID, _UID, _CID, _SUB,
+ * _STA, _ADR, _sx_w, and _sx_d methods.
  *
  * Note: Allocates the return buffer, must be freed by the caller.
  *
@@ -269,9 +269,10 @@ acpi_get_object_info(acpi_handle handle,
 {
 	struct acpi_namespace_node *node;
 	struct acpi_device_info *info;
-	struct acpica_device_id_list *cid_list = NULL;
-	struct acpica_device_id *hid = NULL;
-	struct acpica_device_id *uid = NULL;
+	struct acpi_pnp_device_id_list *cid_list = NULL;
+	struct acpi_pnp_device_id *hid = NULL;
+	struct acpi_pnp_device_id *uid = NULL;
+	struct acpi_pnp_device_id *sub = NULL;
 	char *next_id_string;
 	acpi_object_type type;
 	acpi_name name;
@@ -316,7 +317,7 @@ acpi_get_object_info(acpi_handle handle,
 	if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
 		/*
 		 * Get extra info for ACPI Device/Processor objects only:
-		 * Run the Device _HID, _UID, and _CID methods.
+		 * Run the Device _HID, _UID, _SUB, and _CID methods.
 		 *
 		 * Note: none of these methods are required, so they may or may
 		 * not be present for this device. The Info->Valid bitfield is used
@@ -339,6 +340,14 @@ acpi_get_object_info(acpi_handle handle,
 			valid |= ACPI_VALID_UID;
 		}
 
+		/* Execute the Device._SUB method */
+
+		status = acpi_ut_execute_SUB(node, &sub);
+		if (ACPI_SUCCESS(status)) {
+			info_size += sub->length;
+			valid |= ACPI_VALID_SUB;
+		}
+
 		/* Execute the Device._CID method */
 
 		status = acpi_ut_execute_CID(node, &cid_list);
@@ -348,7 +357,7 @@ acpi_get_object_info(acpi_handle handle,
 
 			info_size +=
 			    (cid_list->list_size -
-			     sizeof(struct acpica_device_id_list));
+			     sizeof(struct acpi_pnp_device_id_list));
 			valid |= ACPI_VALID_CID;
 		}
 	}
@@ -418,16 +427,17 @@ acpi_get_object_info(acpi_handle handle,
 	next_id_string = ACPI_CAST_PTR(char, info->compatible_id_list.ids);
 	if (cid_list) {
 
-		/* Point past the CID DEVICE_ID array */
+		/* Point past the CID PNP_DEVICE_ID array */
 
 		next_id_string +=
 		    ((acpi_size) cid_list->count *
-		     sizeof(struct acpica_device_id));
+		     sizeof(struct acpi_pnp_device_id));
 	}
 
 	/*
-	 * Copy the HID, UID, and CIDs to the return buffer. The variable-length
-	 * strings are copied to the reserved area at the end of the buffer.
+	 * Copy the HID, UID, SUB, and CIDs to the return buffer.
+	 * The variable-length strings are copied to the reserved area
+	 * at the end of the buffer.
 	 *
 	 * For HID and CID, check if the ID is a PCI Root Bridge.
 	 */
@@ -445,6 +455,11 @@ acpi_get_object_info(acpi_handle handle,
 							uid, next_id_string);
 	}
 
+	if (sub) {
+		next_id_string = acpi_ns_copy_device_id(&info->subsystem_id,
+							sub, next_id_string);
+	}
+
 	if (cid_list) {
 		info->compatible_id_list.count = cid_list->count;
 		info->compatible_id_list.list_size = cid_list->list_size;
@@ -481,6 +496,9 @@ acpi_get_object_info(acpi_handle handle,
 	if (uid) {
 		ACPI_FREE(uid);
 	}
+	if (sub) {
+		ACPI_FREE(sub);
+	}
 	if (cid_list) {
 		ACPI_FREE(cid_list);
 	}
diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c
index 6766fc4..9d029da 100644
--- a/drivers/acpi/acpica/nsxfobj.c
+++ b/drivers/acpi/acpica/nsxfobj.c
@@ -220,8 +220,8 @@ ACPI_EXPORT_SYMBOL(acpi_get_parent)
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Return the next peer object within the namespace.  If Handle is
- *              valid, Scope is ignored.  Otherwise, the first object within
+ * DESCRIPTION: Return the next peer object within the namespace. If Handle is
+ *              valid, Scope is ignored. Otherwise, the first object within
  *              Scope is returned.
  *
  ******************************************************************************/
diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c
index 844464c..cb79e2d 100644
--- a/drivers/acpi/acpica/psargs.c
+++ b/drivers/acpi/acpica/psargs.c
@@ -120,7 +120,7 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
  * RETURN:      Pointer to end-of-package +1
  *
  * DESCRIPTION: Get next package length and return a pointer past the end of
- *              the package.  Consumes the package length field
+ *              the package. Consumes the package length field
  *
  ******************************************************************************/
 
@@ -147,8 +147,8 @@ u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state)
  * RETURN:      Pointer to the start of the name string (pointer points into
  *              the AML.
  *
- * DESCRIPTION: Get next raw namestring within the AML stream.  Handles all name
- *              prefix characters.  Set parser state to point past the string.
+ * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name
+ *              prefix characters. Set parser state to point past the string.
  *              (Name is consumed from the AML.)
  *
  ******************************************************************************/
@@ -220,7 +220,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state)
  *
  * DESCRIPTION: Get next name (if method call, return # of required args).
  *              Names are looked up in the internal namespace to determine
- *              if the name represents a control method.  If a method
+ *              if the name represents a control method. If a method
  *              is found, the number of arguments to the method is returned.
  *              This information is critical for parsing to continue correctly.
  *
diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c
index 799162c..5607805 100644
--- a/drivers/acpi/acpica/psloop.c
+++ b/drivers/acpi/acpica/psloop.c
@@ -133,18 +133,46 @@ static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state)
 
 	case AML_CLASS_UNKNOWN:
 
-		/* The opcode is unrecognized. Just skip unknown opcodes */
+		/* The opcode is unrecognized. Complain and skip unknown opcodes */
 
-		ACPI_ERROR((AE_INFO,
-			    "Found unknown opcode 0x%X at AML address %p offset 0x%X, ignoring",
-			    walk_state->opcode, walk_state->parser_state.aml,
-			    walk_state->aml_offset));
+		if (walk_state->pass_number == 2) {
+			ACPI_ERROR((AE_INFO,
+				    "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring",
+				    walk_state->opcode,
+				    (u32)(walk_state->aml_offset +
+					  sizeof(struct acpi_table_header))));
 
-		ACPI_DUMP_BUFFER(walk_state->parser_state.aml, 128);
+			ACPI_DUMP_BUFFER(walk_state->parser_state.aml - 16, 48);
 
-		/* Assume one-byte bad opcode */
+#ifdef ACPI_ASL_COMPILER
+			/*
+			 * This is executed for the disassembler only. Output goes
+			 * to the disassembled ASL output file.
+			 */
+			acpi_os_printf
+			    ("/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n",
+			     walk_state->opcode,
+			     (u32)(walk_state->aml_offset +
+				   sizeof(struct acpi_table_header)));
+
+			/* Dump the context surrounding the invalid opcode */
+
+			acpi_ut_dump_buffer(((u8 *)walk_state->parser_state.
+					     aml - 16), 48, DB_BYTE_DISPLAY,
+					    walk_state->aml_offset +
+					    sizeof(struct acpi_table_header) -
+					    16);
+			acpi_os_printf(" */\n");
+#endif
+		}
+
+		/* Increment past one-byte or two-byte opcode */
 
 		walk_state->parser_state.aml++;
+		if (walk_state->opcode > 0xFF) {	/* Can only happen if first byte is 0x5B */
+			walk_state->parser_state.aml++;
+		}
+
 		return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE);
 
 	default:
@@ -519,11 +547,18 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
 					if ((op_info->class ==
 					     AML_CLASS_EXECUTE) && (!arg)) {
 						ACPI_WARNING((AE_INFO,
-							      "Detected an unsupported executable opcode "
-							      "at module-level: [0x%.4X] at table offset 0x%.4X",
-							      op->common.aml_opcode,
-							      (u32)((aml_op_start - walk_state->parser_state.aml_start)
-								+ sizeof(struct acpi_table_header))));
+							      "Unsupported module-level executable opcode "
+							      "0x%.2X at table offset 0x%.4X",
+							      op->common.
+							      aml_opcode,
+							      (u32)
+							      (ACPI_PTR_DIFF
+							       (aml_op_start,
+								walk_state->
+								parser_state.
+								aml_start) +
+							       sizeof(struct
+								      acpi_table_header))));
 					}
 				}
 				break;
@@ -843,8 +878,6 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state,
 		*op = NULL;
 	}
 
-	ACPI_PREEMPTION_POINT();
-
 	return_ACPI_STATUS(AE_OK);
 }
 
diff --git a/drivers/acpi/acpica/psopcode.c b/drivers/acpi/acpica/psopcode.c
index ed1d457..1793d93 100644
--- a/drivers/acpi/acpica/psopcode.c
+++ b/drivers/acpi/acpica/psopcode.c
@@ -59,7 +59,7 @@ static const u8 acpi_gbl_argument_count[] =
  *
  * DESCRIPTION: Opcode table. Each entry contains <opcode, type, name, operands>
  *              The name is a simple ascii string, the operand specifier is an
- *              ascii string with one letter per operand.  The letter specifies
+ *              ascii string with one letter per operand. The letter specifies
  *              the operand type.
  *
  ******************************************************************************/
@@ -183,7 +183,7 @@ static const u8 acpi_gbl_argument_count[] =
  ******************************************************************************/
 
 /*
- * Master Opcode information table.  A summary of everything we know about each
+ * Master Opcode information table. A summary of everything we know about each
  * opcode, all in one place.
  */
 const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
@@ -392,10 +392,12 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
 		 AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
 /* 38 */ ACPI_OP("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY,
 		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
-		 AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
+			 AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
+			 AML_CONSTANT),
 /* 39 */ ACPI_OP("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY,
 		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
-		 AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
+		 	 AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
+			 AML_CONSTANT),
 /* 3A */ ACPI_OP("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY,
 		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
 		 AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
@@ -495,7 +497,8 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
 		 AML_NSNODE | AML_NAMED | AML_DEFER),
 /* 59 */ ACPI_OP("Field", ARGP_FIELD_OP, ARGI_FIELD_OP, ACPI_TYPE_ANY,
 		 AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD,
-		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
+			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+			 AML_FIELD),
 /* 5A */ ACPI_OP("Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP,
 		 ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT,
 		 AML_TYPE_NAMED_NO_OBJ,
@@ -519,12 +522,13 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
 /* 5E */ ACPI_OP("IndexField", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP,
 		 ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
 		 AML_TYPE_NAMED_FIELD,
-		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
+		 	 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+			 AML_FIELD),
 /* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP,
-		 ACPI_TYPE_LOCAL_BANK_FIELD, AML_CLASS_NAMED_OBJECT,
-		 AML_TYPE_NAMED_FIELD,
-		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD |
-		 AML_DEFER),
+		 	 ACPI_TYPE_LOCAL_BANK_FIELD,
+			 AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD,
+		 	 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+			 AML_FIELD | AML_DEFER),
 
 /* Internal opcodes that map to invalid AML opcodes */
 
@@ -632,7 +636,8 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
 /* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP,
 		 ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
 		 AML_TYPE_NAMED_NO_OBJ,
-		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE),
+		 	 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+			 AML_NSNODE),
 
 /* ACPI 3.0 opcodes */
 
@@ -695,7 +700,7 @@ static const u8 acpi_gbl_short_op_index[256] = {
 
 /*
  * This table is indexed by the second opcode of the extended opcode
- * pair.  It returns an index into the opcode table (acpi_gbl_aml_op_info)
+ * pair. It returns an index into the opcode table (acpi_gbl_aml_op_info)
  */
 static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = {
 /*              0     1     2     3     4     5     6     7  */
diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c
index 0198570..2494caf 100644
--- a/drivers/acpi/acpica/psparse.c
+++ b/drivers/acpi/acpica/psparse.c
@@ -43,9 +43,9 @@
 
 /*
  * Parse the AML and build an operation tree as most interpreters,
- * like Perl, do.  Parsing is done by hand rather than with a YACC
+ * like Perl, do. Parsing is done by hand rather than with a YACC
  * generated parser to tightly constrain stack and dynamic memory
- * usage.  At the same time, parsing is kept flexible and the code
+ * usage. At the same time, parsing is kept flexible and the code
  * fairly compact by parsing based on a list of AML opcode
  * templates in aml_op_info[]
  */
@@ -379,7 +379,7 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
 	case AE_CTRL_FALSE:
 		/*
 		 * Either an IF/WHILE Predicate was false or we encountered a BREAK
-		 * opcode.  In both cases, we do not execute the rest of the
+		 * opcode. In both cases, we do not execute the rest of the
 		 * package;  We simply close out the parent (finishing the walk of
 		 * this branch of the tree) and continue execution at the parent
 		 * level.
@@ -459,8 +459,9 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
 
 			/* Executing a control method - additional cleanup */
 
-			acpi_ds_terminate_control_method(
-				walk_state->method_desc, walk_state);
+			acpi_ds_terminate_control_method(walk_state->
+							 method_desc,
+							 walk_state);
 		}
 
 		acpi_ds_delete_walk_state(walk_state);
@@ -487,7 +488,7 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
 	acpi_gbl_current_walk_list = thread;
 
 	/*
-	 * Execute the walk loop as long as there is a valid Walk State.  This
+	 * Execute the walk loop as long as there is a valid Walk State. This
 	 * handles nested control method invocations without recursion.
 	 */
 	ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "State=%p\n", walk_state));
diff --git a/drivers/acpi/acpica/psutils.c b/drivers/acpi/acpica/psutils.c
index 8736ad5..4137dcb 100644
--- a/drivers/acpi/acpica/psutils.c
+++ b/drivers/acpi/acpica/psutils.c
@@ -108,7 +108,7 @@ void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode)
  * RETURN:      Pointer to the new Op, null on failure
  *
  * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on
- *              opcode.  A cache of opcodes is available for the pure
+ *              opcode. A cache of opcodes is available for the pure
  *              GENERIC_OP, since this is by far the most commonly used.
  *
  ******************************************************************************/
@@ -164,7 +164,7 @@ union acpi_parse_object *acpi_ps_alloc_op(u16 opcode)
  *
  * RETURN:      None.
  *
- * DESCRIPTION: Free an Op object.  Either put it on the GENERIC_OP cache list
+ * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list
  *              or actually free it.
  *
  ******************************************************************************/
diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c
index de12469..147feb6 100644
--- a/drivers/acpi/acpica/rscalc.c
+++ b/drivers/acpi/acpica/rscalc.c
@@ -457,6 +457,15 @@ acpi_rs_get_list_length(u8 * aml_buffer,
 			 * Get the number of vendor data bytes
 			 */
 			extra_struct_bytes = resource_length;
+
+			/*
+			 * There is already one byte included in the minimum
+			 * descriptor size. If there are extra struct bytes,
+			 * subtract one from the count.
+			 */
+			if (extra_struct_bytes) {
+				extra_struct_bytes--;
+			}
 			break;
 
 		case ACPI_RESOURCE_NAME_END_TAG:
@@ -601,7 +610,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
 	/*
 	 * Calculate the size of the return buffer.
 	 * The base size is the number of elements * the sizes of the
-	 * structures.  Additional space for the strings is added below.
+	 * structures. Additional space for the strings is added below.
 	 * The minus one is to subtract the size of the u8 Source[1]
 	 * member because it is added below.
 	 *
@@ -664,8 +673,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
 						     (*sub_object_list)->string.
 						     length + 1);
 			} else {
-				temp_size_needed +=
-				    acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
+				temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
 			}
 		} else {
 			/*
diff --git a/drivers/acpi/acpica/rslist.c b/drivers/acpi/acpica/rslist.c
index 46b5324..8b64db9 100644
--- a/drivers/acpi/acpica/rslist.c
+++ b/drivers/acpi/acpica/rslist.c
@@ -109,7 +109,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml,
 		ACPI_ERROR((AE_INFO,
 			    "Invalid/unsupported resource descriptor: Type 0x%2.2X",
 			    resource_index));
-		return (AE_AML_INVALID_RESOURCE_TYPE);
+		return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
 	}
 
 	/* Convert the AML byte stream resource to a local resource struct */
@@ -200,7 +200,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
 			ACPI_ERROR((AE_INFO,
 				    "Invalid/unsupported resource descriptor: Type 0x%2.2X",
 				    resource->type));
-			return (AE_AML_INVALID_RESOURCE_TYPE);
+			return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
 		}
 
 		status = acpi_rs_convert_resource_to_aml(resource,
diff --git a/drivers/acpi/acpica/tbfind.c b/drivers/acpi/acpica/tbfind.c
index 57deae1..77d1db2 100644
--- a/drivers/acpi/acpica/tbfind.c
+++ b/drivers/acpi/acpica/tbfind.c
@@ -77,7 +77,7 @@ acpi_tb_find_table(char *signature,
 	/* Normalize the input strings */
 
 	ACPI_MEMSET(&header, 0, sizeof(struct acpi_table_header));
-	ACPI_STRNCPY(header.signature, signature, ACPI_NAME_SIZE);
+	ACPI_MOVE_NAME(header.signature, signature);
 	ACPI_STRNCPY(header.oem_id, oem_id, ACPI_OEM_ID_SIZE);
 	ACPI_STRNCPY(header.oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE);
 
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c
index 70f9d78..f540ae4 100644
--- a/drivers/acpi/acpica/tbinstal.c
+++ b/drivers/acpi/acpica/tbinstal.c
@@ -526,6 +526,8 @@ void acpi_tb_terminate(void)
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+
+	return_VOID;
 }
 
 /*******************************************************************************
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
index b6cea30..285e24b 100644
--- a/drivers/acpi/acpica/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -354,7 +354,7 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length)
 		sum = (u8) (sum + *(buffer++));
 	}
 
-	return sum;
+	return (sum);
 }
 
 /*******************************************************************************
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c
index 2110126..f563278 100644
--- a/drivers/acpi/acpica/tbxface.c
+++ b/drivers/acpi/acpica/tbxface.c
@@ -236,7 +236,7 @@ acpi_get_table_header(char *signature,
 						       sizeof(struct
 							      acpi_table_header));
 				if (!header) {
-					return AE_NO_MEMORY;
+					return (AE_NO_MEMORY);
 				}
 				ACPI_MEMCPY(out_table_header, header,
 					    sizeof(struct acpi_table_header));
@@ -244,7 +244,7 @@ acpi_get_table_header(char *signature,
 						     sizeof(struct
 							    acpi_table_header));
 			} else {
-				return AE_NOT_FOUND;
+				return (AE_NOT_FOUND);
 			}
 		} else {
 			ACPI_MEMCPY(out_table_header,
diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c
index f87cc63..a5e1e4e 100644
--- a/drivers/acpi/acpica/tbxfload.c
+++ b/drivers/acpi/acpica/tbxfload.c
@@ -211,7 +211,7 @@ static acpi_status acpi_tb_load_namespace(void)
  * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must
  *              be a valid ACPI table with a valid ACPI table header.
  *              Note1: Mainly intended to support hotplug addition of SSDTs.
- *              Note2: Does not copy the incoming table. User is reponsible
+ *              Note2: Does not copy the incoming table. User is responsible
  *              to ensure that the table is not deleted or unmapped.
  *
  ******************************************************************************/
diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c
index 74e7208..28f3302 100644
--- a/drivers/acpi/acpica/tbxfroot.c
+++ b/drivers/acpi/acpica/tbxfroot.c
@@ -67,7 +67,6 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp);
 
 static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
 {
-	ACPI_FUNCTION_ENTRY();
 
 	/*
 	 * The signature and checksum must both be correct
@@ -108,7 +107,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
  * RETURN:      Status, RSDP physical address
  *
  * DESCRIPTION: Search lower 1Mbyte of memory for the root system descriptor
- *              pointer structure.  If it is found, set *RSDP to point to it.
+ *              pointer structure. If it is found, set *RSDP to point to it.
  *
  * NOTE1:       The RSDP must be either in the first 1K of the Extended
  *              BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
diff --git a/drivers/acpi/acpica/utcache.c b/drivers/acpi/acpica/utcache.c
new file mode 100644
index 0000000..e1d40ed
--- /dev/null
+++ b/drivers/acpi/acpica/utcache.c
@@ -0,0 +1,323 @@
+/******************************************************************************
+ *
+ * Module Name: utcache - local cache allocation routines
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+#define _COMPONENT          ACPI_UTILITIES
+ACPI_MODULE_NAME("utcache")
+
+#ifdef ACPI_USE_LOCAL_CACHE
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_os_create_cache
+ *
+ * PARAMETERS:  cache_name      - Ascii name for the cache
+ *              object_size     - Size of each cached object
+ *              max_depth       - Maximum depth of the cache (in objects)
+ *              return_cache    - Where the new cache object is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Create a cache object
+ *
+ ******************************************************************************/
+acpi_status
+acpi_os_create_cache(char *cache_name,
+		     u16 object_size,
+		     u16 max_depth, struct acpi_memory_list ** return_cache)
+{
+	struct acpi_memory_list *cache;
+
+	ACPI_FUNCTION_ENTRY();
+
+	if (!cache_name || !return_cache || (object_size < 16)) {
+		return (AE_BAD_PARAMETER);
+	}
+
+	/* Create the cache object */
+
+	cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
+	if (!cache) {
+		return (AE_NO_MEMORY);
+	}
+
+	/* Populate the cache object and return it */
+
+	ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list));
+	cache->link_offset = 8;
+	cache->list_name = cache_name;
+	cache->object_size = object_size;
+	cache->max_depth = max_depth;
+
+	*return_cache = cache;
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_os_purge_cache
+ *
+ * PARAMETERS:  cache           - Handle to cache object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Free all objects within the requested cache.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache)
+{
+	char *next;
+	acpi_status status;
+
+	ACPI_FUNCTION_ENTRY();
+
+	if (!cache) {
+		return (AE_BAD_PARAMETER);
+	}
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	/* Walk the list of objects in this cache */
+
+	while (cache->list_head) {
+
+		/* Delete and unlink one cached state object */
+
+		next = *(ACPI_CAST_INDIRECT_PTR(char,
+						&(((char *)cache->
+						   list_head)[cache->
+							      link_offset])));
+		ACPI_FREE(cache->list_head);
+
+		cache->list_head = next;
+		cache->current_depth--;
+	}
+
+	(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_os_delete_cache
+ *
+ * PARAMETERS:  cache           - Handle to cache object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Free all objects within the requested cache and delete the
+ *              cache object.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_delete_cache(struct acpi_memory_list * cache)
+{
+	acpi_status status;
+
+	ACPI_FUNCTION_ENTRY();
+
+	/* Purge all objects in the cache */
+
+	status = acpi_os_purge_cache(cache);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	/* Now we can delete the cache object */
+
+	acpi_os_free(cache);
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_os_release_object
+ *
+ * PARAMETERS:  cache       - Handle to cache object
+ *              object      - The object to be released
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Release an object to the specified cache. If cache is full,
+ *              the object is deleted.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_os_release_object(struct acpi_memory_list * cache, void *object)
+{
+	acpi_status status;
+
+	ACPI_FUNCTION_ENTRY();
+
+	if (!cache || !object) {
+		return (AE_BAD_PARAMETER);
+	}
+
+	/* If cache is full, just free this object */
+
+	if (cache->current_depth >= cache->max_depth) {
+		ACPI_FREE(object);
+		ACPI_MEM_TRACKING(cache->total_freed++);
+	}
+
+	/* Otherwise put this object back into the cache */
+
+	else {
+		status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+		if (ACPI_FAILURE(status)) {
+			return (status);
+		}
+
+		/* Mark the object as cached */
+
+		ACPI_MEMSET(object, 0xCA, cache->object_size);
+		ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_CACHED);
+
+		/* Put the object at the head of the cache list */
+
+		*(ACPI_CAST_INDIRECT_PTR(char,
+					 &(((char *)object)[cache->
+							    link_offset]))) =
+		    cache->list_head;
+		cache->list_head = object;
+		cache->current_depth++;
+
+		(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
+	}
+
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_os_acquire_object
+ *
+ * PARAMETERS:  cache           - Handle to cache object
+ *
+ * RETURN:      the acquired object. NULL on error
+ *
+ * DESCRIPTION: Get an object from the specified cache. If cache is empty,
+ *              the object is allocated.
+ *
+ ******************************************************************************/
+
+void *acpi_os_acquire_object(struct acpi_memory_list *cache)
+{
+	acpi_status status;
+	void *object;
+
+	ACPI_FUNCTION_NAME(os_acquire_object);
+
+	if (!cache) {
+		return (NULL);
+	}
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+	if (ACPI_FAILURE(status)) {
+		return (NULL);
+	}
+
+	ACPI_MEM_TRACKING(cache->requests++);
+
+	/* Check the cache first */
+
+	if (cache->list_head) {
+
+		/* There is an object available, use it */
+
+		object = cache->list_head;
+		cache->list_head = *(ACPI_CAST_INDIRECT_PTR(char,
+							    &(((char *)
+							       object)[cache->
+								       link_offset])));
+
+		cache->current_depth--;
+
+		ACPI_MEM_TRACKING(cache->hits++);
+		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+				  "Object %p from %s cache\n", object,
+				  cache->list_name));
+
+		status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
+		if (ACPI_FAILURE(status)) {
+			return (NULL);
+		}
+
+		/* Clear (zero) the previously used Object */
+
+		ACPI_MEMSET(object, 0, cache->object_size);
+	} else {
+		/* The cache is empty, create a new object */
+
+		ACPI_MEM_TRACKING(cache->total_allocated++);
+
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+		if ((cache->total_allocated - cache->total_freed) >
+		    cache->max_occupied) {
+			cache->max_occupied =
+			    cache->total_allocated - cache->total_freed;
+		}
+#endif
+
+		/* Avoid deadlock with ACPI_ALLOCATE_ZEROED */
+
+		status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
+		if (ACPI_FAILURE(status)) {
+			return (NULL);
+		}
+
+		object = ACPI_ALLOCATE_ZEROED(cache->object_size);
+		if (!object) {
+			return (NULL);
+		}
+	}
+
+	return (object);
+}
+#endif				/* ACPI_USE_LOCAL_CACHE */
diff --git a/drivers/acpi/acpica/utclib.c b/drivers/acpi/acpica/utclib.c
new file mode 100644
index 0000000..19ea4755
--- /dev/null
+++ b/drivers/acpi/acpica/utclib.c
@@ -0,0 +1,749 @@
+/******************************************************************************
+ *
+ * Module Name: cmclib - Local implementation of C library functions
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+/*
+ * These implementations of standard C Library routines can optionally be
+ * used if a C library is not available. In general, they are less efficient
+ * than an inline or assembly implementation
+ */
+
+#define _COMPONENT          ACPI_UTILITIES
+ACPI_MODULE_NAME("cmclib")
+
+#ifndef ACPI_USE_SYSTEM_CLIBRARY
+#define NEGATIVE    1
+#define POSITIVE    0
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_memcmp (memcmp)
+ *
+ * PARAMETERS:  buffer1         - First Buffer
+ *              buffer2         - Second Buffer
+ *              count           - Maximum # of bytes to compare
+ *
+ * RETURN:      Index where Buffers mismatched, or 0 if Buffers matched
+ *
+ * DESCRIPTION: Compare two Buffers, with a maximum length
+ *
+ ******************************************************************************/
+int acpi_ut_memcmp(const char *buffer1, const char *buffer2, acpi_size count)
+{
+
+	return ((count == ACPI_SIZE_MAX) ? 0 : ((unsigned char)*buffer1 -
+						(unsigned char)*buffer2));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_memcpy (memcpy)
+ *
+ * PARAMETERS:  dest        - Target of the copy
+ *              src         - Source buffer to copy
+ *              count       - Number of bytes to copy
+ *
+ * RETURN:      Dest
+ *
+ * DESCRIPTION: Copy arbitrary bytes of memory
+ *
+ ******************************************************************************/
+
+void *acpi_ut_memcpy(void *dest, const void *src, acpi_size count)
+{
+	char *new = (char *)dest;
+	char *old = (char *)src;
+
+	while (count) {
+		*new = *old;
+		new++;
+		old++;
+		count--;
+	}
+
+	return (dest);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_memset (memset)
+ *
+ * PARAMETERS:  dest        - Buffer to set
+ *              value       - Value to set each byte of memory
+ *              count       - Number of bytes to set
+ *
+ * RETURN:      Dest
+ *
+ * DESCRIPTION: Initialize a buffer to a known value.
+ *
+ ******************************************************************************/
+
+void *acpi_ut_memset(void *dest, u8 value, acpi_size count)
+{
+	char *new = (char *)dest;
+
+	while (count) {
+		*new = (char)value;
+		new++;
+		count--;
+	}
+
+	return (dest);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strlen (strlen)
+ *
+ * PARAMETERS:  string              - Null terminated string
+ *
+ * RETURN:      Length
+ *
+ * DESCRIPTION: Returns the length of the input string
+ *
+ ******************************************************************************/
+
+acpi_size acpi_ut_strlen(const char *string)
+{
+	u32 length = 0;
+
+	/* Count the string until a null is encountered */
+
+	while (*string) {
+		length++;
+		string++;
+	}
+
+	return (length);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strcpy (strcpy)
+ *
+ * PARAMETERS:  dst_string      - Target of the copy
+ *              src_string      - The source string to copy
+ *
+ * RETURN:      dst_string
+ *
+ * DESCRIPTION: Copy a null terminated string
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strcpy(char *dst_string, const char *src_string)
+{
+	char *string = dst_string;
+
+	/* Move bytes brute force */
+
+	while (*src_string) {
+		*string = *src_string;
+
+		string++;
+		src_string++;
+	}
+
+	/* Null terminate */
+
+	*string = 0;
+	return (dst_string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strncpy (strncpy)
+ *
+ * PARAMETERS:  dst_string      - Target of the copy
+ *              src_string      - The source string to copy
+ *              count           - Maximum # of bytes to copy
+ *
+ * RETURN:      dst_string
+ *
+ * DESCRIPTION: Copy a null terminated string, with a maximum length
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strncpy(char *dst_string, const char *src_string, acpi_size count)
+{
+	char *string = dst_string;
+
+	/* Copy the string */
+
+	for (string = dst_string;
+	     count && (count--, (*string++ = *src_string++));) {;
+	}
+
+	/* Pad with nulls if necessary */
+
+	while (count--) {
+		*string = 0;
+		string++;
+	}
+
+	/* Return original pointer */
+
+	return (dst_string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strcmp (strcmp)
+ *
+ * PARAMETERS:  string1         - First string
+ *              string2         - Second string
+ *
+ * RETURN:      Index where strings mismatched, or 0 if strings matched
+ *
+ * DESCRIPTION: Compare two null terminated strings
+ *
+ ******************************************************************************/
+
+int acpi_ut_strcmp(const char *string1, const char *string2)
+{
+
+	for (; (*string1 == *string2); string2++) {
+		if (!*string1++) {
+			return (0);
+		}
+	}
+
+	return ((unsigned char)*string1 - (unsigned char)*string2);
+}
+
+#ifdef ACPI_FUTURE_IMPLEMENTATION
+/* Not used at this time */
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strchr (strchr)
+ *
+ * PARAMETERS:  string          - Search string
+ *              ch              - character to search for
+ *
+ * RETURN:      Ptr to char or NULL if not found
+ *
+ * DESCRIPTION: Search a string for a character
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strchr(const char *string, int ch)
+{
+
+	for (; (*string); string++) {
+		if ((*string) == (char)ch) {
+			return ((char *)string);
+		}
+	}
+
+	return (NULL);
+}
+#endif
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strncmp (strncmp)
+ *
+ * PARAMETERS:  string1         - First string
+ *              string2         - Second string
+ *              count           - Maximum # of bytes to compare
+ *
+ * RETURN:      Index where strings mismatched, or 0 if strings matched
+ *
+ * DESCRIPTION: Compare two null terminated strings, with a maximum length
+ *
+ ******************************************************************************/
+
+int acpi_ut_strncmp(const char *string1, const char *string2, acpi_size count)
+{
+
+	for (; count-- && (*string1 == *string2); string2++) {
+		if (!*string1++) {
+			return (0);
+		}
+	}
+
+	return ((count == ACPI_SIZE_MAX) ? 0 : ((unsigned char)*string1 -
+						(unsigned char)*string2));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strcat (Strcat)
+ *
+ * PARAMETERS:  dst_string      - Target of the copy
+ *              src_string      - The source string to copy
+ *
+ * RETURN:      dst_string
+ *
+ * DESCRIPTION: Append a null terminated string to a null terminated string
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strcat(char *dst_string, const char *src_string)
+{
+	char *string;
+
+	/* Find end of the destination string */
+
+	for (string = dst_string; *string++;) {;
+	}
+
+	/* Concatenate the string */
+
+	for (--string; (*string++ = *src_string++);) {;
+	}
+
+	return (dst_string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strncat (strncat)
+ *
+ * PARAMETERS:  dst_string      - Target of the copy
+ *              src_string      - The source string to copy
+ *              count           - Maximum # of bytes to copy
+ *
+ * RETURN:      dst_string
+ *
+ * DESCRIPTION: Append a null terminated string to a null terminated string,
+ *              with a maximum count.
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strncat(char *dst_string, const char *src_string, acpi_size count)
+{
+	char *string;
+
+	if (count) {
+
+		/* Find end of the destination string */
+
+		for (string = dst_string; *string++;) {;
+		}
+
+		/* Concatenate the string */
+
+		for (--string; (*string++ = *src_string++) && --count;) {;
+		}
+
+		/* Null terminate if necessary */
+
+		if (!count) {
+			*string = 0;
+		}
+	}
+
+	return (dst_string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strstr (strstr)
+ *
+ * PARAMETERS:  string1         - Target string
+ *              string2         - Substring to search for
+ *
+ * RETURN:      Where substring match starts, Null if no match found
+ *
+ * DESCRIPTION: Checks if String2 occurs in String1. This is not really a
+ *              full implementation of strstr, only sufficient for command
+ *              matching
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strstr(char *string1, char *string2)
+{
+	char *string;
+
+	if (acpi_ut_strlen(string2) > acpi_ut_strlen(string1)) {
+		return (NULL);
+	}
+
+	/* Walk entire string, comparing the letters */
+
+	for (string = string1; *string2;) {
+		if (*string2 != *string) {
+			return (NULL);
+		}
+
+		string2++;
+		string++;
+	}
+
+	return (string1);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strtoul (strtoul)
+ *
+ * PARAMETERS:  string          - Null terminated string
+ *              terminater      - Where a pointer to the terminating byte is
+ *                                returned
+ *              base            - Radix of the string
+ *
+ * RETURN:      Converted value
+ *
+ * DESCRIPTION: Convert a string into a 32-bit unsigned value.
+ *              Note: use acpi_ut_strtoul64 for 64-bit integers.
+ *
+ ******************************************************************************/
+
+u32 acpi_ut_strtoul(const char *string, char **terminator, u32 base)
+{
+	u32 converted = 0;
+	u32 index;
+	u32 sign;
+	const char *string_start;
+	u32 return_value = 0;
+	acpi_status status = AE_OK;
+
+	/*
+	 * Save the value of the pointer to the buffer's first
+	 * character, save the current errno value, and then
+	 * skip over any white space in the buffer:
+	 */
+	string_start = string;
+	while (ACPI_IS_SPACE(*string) || *string == '\t') {
+		++string;
+	}
+
+	/*
+	 * The buffer may contain an optional plus or minus sign.
+	 * If it does, then skip over it but remember what is was:
+	 */
+	if (*string == '-') {
+		sign = NEGATIVE;
+		++string;
+	} else if (*string == '+') {
+		++string;
+		sign = POSITIVE;
+	} else {
+		sign = POSITIVE;
+	}
+
+	/*
+	 * If the input parameter Base is zero, then we need to
+	 * determine if it is octal, decimal, or hexadecimal:
+	 */
+	if (base == 0) {
+		if (*string == '0') {
+			if (acpi_ut_to_lower(*(++string)) == 'x') {
+				base = 16;
+				++string;
+			} else {
+				base = 8;
+			}
+		} else {
+			base = 10;
+		}
+	} else if (base < 2 || base > 36) {
+		/*
+		 * The specified Base parameter is not in the domain of
+		 * this function:
+		 */
+		goto done;
+	}
+
+	/*
+	 * For octal and hexadecimal bases, skip over the leading
+	 * 0 or 0x, if they are present.
+	 */
+	if (base == 8 && *string == '0') {
+		string++;
+	}
+
+	if (base == 16 &&
+	    *string == '0' && acpi_ut_to_lower(*(++string)) == 'x') {
+		string++;
+	}
+
+	/*
+	 * Main loop: convert the string to an unsigned long:
+	 */
+	while (*string) {
+		if (ACPI_IS_DIGIT(*string)) {
+			index = (u32)((u8)*string - '0');
+		} else {
+			index = (u32)acpi_ut_to_upper(*string);
+			if (ACPI_IS_UPPER(index)) {
+				index = index - 'A' + 10;
+			} else {
+				goto done;
+			}
+		}
+
+		if (index >= base) {
+			goto done;
+		}
+
+		/*
+		 * Check to see if value is out of range:
+		 */
+
+		if (return_value > ((ACPI_UINT32_MAX - (u32)index) / (u32)base)) {
+			status = AE_ERROR;
+			return_value = 0;	/* reset */
+		} else {
+			return_value *= base;
+			return_value += index;
+			converted = 1;
+		}
+
+		++string;
+	}
+
+      done:
+	/*
+	 * If appropriate, update the caller's pointer to the next
+	 * unconverted character in the buffer.
+	 */
+	if (terminator) {
+		if (converted == 0 && return_value == 0 && string != NULL) {
+			*terminator = (char *)string_start;
+		} else {
+			*terminator = (char *)string;
+		}
+	}
+
+	if (status == AE_ERROR) {
+		return_value = ACPI_UINT32_MAX;
+	}
+
+	/*
+	 * If a minus sign was present, then "the conversion is negated":
+	 */
+	if (sign == NEGATIVE) {
+		return_value = (ACPI_UINT32_MAX - return_value) + 1;
+	}
+
+	return (return_value);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_to_upper (TOUPPER)
+ *
+ * PARAMETERS:  c           - Character to convert
+ *
+ * RETURN:      Converted character as an int
+ *
+ * DESCRIPTION: Convert character to uppercase
+ *
+ ******************************************************************************/
+
+int acpi_ut_to_upper(int c)
+{
+
+	return (ACPI_IS_LOWER(c) ? ((c) - 0x20) : (c));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_to_lower (TOLOWER)
+ *
+ * PARAMETERS:  c           - Character to convert
+ *
+ * RETURN:      Converted character as an int
+ *
+ * DESCRIPTION: Convert character to lowercase
+ *
+ ******************************************************************************/
+
+int acpi_ut_to_lower(int c)
+{
+
+	return (ACPI_IS_UPPER(c) ? ((c) + 0x20) : (c));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    is* functions
+ *
+ * DESCRIPTION: is* functions use the ctype table below
+ *
+ ******************************************************************************/
+
+const u8 _acpi_ctype[257] = {
+	_ACPI_CN,		/* 0x00     0 NUL */
+	_ACPI_CN,		/* 0x01     1 SOH */
+	_ACPI_CN,		/* 0x02     2 STX */
+	_ACPI_CN,		/* 0x03     3 ETX */
+	_ACPI_CN,		/* 0x04     4 EOT */
+	_ACPI_CN,		/* 0x05     5 ENQ */
+	_ACPI_CN,		/* 0x06     6 ACK */
+	_ACPI_CN,		/* 0x07     7 BEL */
+	_ACPI_CN,		/* 0x08     8 BS  */
+	_ACPI_CN | _ACPI_SP,	/* 0x09     9 TAB */
+	_ACPI_CN | _ACPI_SP,	/* 0x0A    10 LF  */
+	_ACPI_CN | _ACPI_SP,	/* 0x0B    11 VT  */
+	_ACPI_CN | _ACPI_SP,	/* 0x0C    12 FF  */
+	_ACPI_CN | _ACPI_SP,	/* 0x0D    13 CR  */
+	_ACPI_CN,		/* 0x0E    14 SO  */
+	_ACPI_CN,		/* 0x0F    15 SI  */
+	_ACPI_CN,		/* 0x10    16 DLE */
+	_ACPI_CN,		/* 0x11    17 DC1 */
+	_ACPI_CN,		/* 0x12    18 DC2 */
+	_ACPI_CN,		/* 0x13    19 DC3 */
+	_ACPI_CN,		/* 0x14    20 DC4 */
+	_ACPI_CN,		/* 0x15    21 NAK */
+	_ACPI_CN,		/* 0x16    22 SYN */
+	_ACPI_CN,		/* 0x17    23 ETB */
+	_ACPI_CN,		/* 0x18    24 CAN */
+	_ACPI_CN,		/* 0x19    25 EM  */
+	_ACPI_CN,		/* 0x1A    26 SUB */
+	_ACPI_CN,		/* 0x1B    27 ESC */
+	_ACPI_CN,		/* 0x1C    28 FS  */
+	_ACPI_CN,		/* 0x1D    29 GS  */
+	_ACPI_CN,		/* 0x1E    30 RS  */
+	_ACPI_CN,		/* 0x1F    31 US  */
+	_ACPI_XS | _ACPI_SP,	/* 0x20    32 ' ' */
+	_ACPI_PU,		/* 0x21    33 '!' */
+	_ACPI_PU,		/* 0x22    34 '"' */
+	_ACPI_PU,		/* 0x23    35 '#' */
+	_ACPI_PU,		/* 0x24    36 '$' */
+	_ACPI_PU,		/* 0x25    37 '%' */
+	_ACPI_PU,		/* 0x26    38 '&' */
+	_ACPI_PU,		/* 0x27    39 ''' */
+	_ACPI_PU,		/* 0x28    40 '(' */
+	_ACPI_PU,		/* 0x29    41 ')' */
+	_ACPI_PU,		/* 0x2A    42 '*' */
+	_ACPI_PU,		/* 0x2B    43 '+' */
+	_ACPI_PU,		/* 0x2C    44 ',' */
+	_ACPI_PU,		/* 0x2D    45 '-' */
+	_ACPI_PU,		/* 0x2E    46 '.' */
+	_ACPI_PU,		/* 0x2F    47 '/' */
+	_ACPI_XD | _ACPI_DI,	/* 0x30    48 '0' */
+	_ACPI_XD | _ACPI_DI,	/* 0x31    49 '1' */
+	_ACPI_XD | _ACPI_DI,	/* 0x32    50 '2' */
+	_ACPI_XD | _ACPI_DI,	/* 0x33    51 '3' */
+	_ACPI_XD | _ACPI_DI,	/* 0x34    52 '4' */
+	_ACPI_XD | _ACPI_DI,	/* 0x35    53 '5' */
+	_ACPI_XD | _ACPI_DI,	/* 0x36    54 '6' */
+	_ACPI_XD | _ACPI_DI,	/* 0x37    55 '7' */
+	_ACPI_XD | _ACPI_DI,	/* 0x38    56 '8' */
+	_ACPI_XD | _ACPI_DI,	/* 0x39    57 '9' */
+	_ACPI_PU,		/* 0x3A    58 ':' */
+	_ACPI_PU,		/* 0x3B    59 ';' */
+	_ACPI_PU,		/* 0x3C    60 '<' */
+	_ACPI_PU,		/* 0x3D    61 '=' */
+	_ACPI_PU,		/* 0x3E    62 '>' */
+	_ACPI_PU,		/* 0x3F    63 '?' */
+	_ACPI_PU,		/* 0x40    64 '@' */
+	_ACPI_XD | _ACPI_UP,	/* 0x41    65 'A' */
+	_ACPI_XD | _ACPI_UP,	/* 0x42    66 'B' */
+	_ACPI_XD | _ACPI_UP,	/* 0x43    67 'C' */
+	_ACPI_XD | _ACPI_UP,	/* 0x44    68 'D' */
+	_ACPI_XD | _ACPI_UP,	/* 0x45    69 'E' */
+	_ACPI_XD | _ACPI_UP,	/* 0x46    70 'F' */
+	_ACPI_UP,		/* 0x47    71 'G' */
+	_ACPI_UP,		/* 0x48    72 'H' */
+	_ACPI_UP,		/* 0x49    73 'I' */
+	_ACPI_UP,		/* 0x4A    74 'J' */
+	_ACPI_UP,		/* 0x4B    75 'K' */
+	_ACPI_UP,		/* 0x4C    76 'L' */
+	_ACPI_UP,		/* 0x4D    77 'M' */
+	_ACPI_UP,		/* 0x4E    78 'N' */
+	_ACPI_UP,		/* 0x4F    79 'O' */
+	_ACPI_UP,		/* 0x50    80 'P' */
+	_ACPI_UP,		/* 0x51    81 'Q' */
+	_ACPI_UP,		/* 0x52    82 'R' */
+	_ACPI_UP,		/* 0x53    83 'S' */
+	_ACPI_UP,		/* 0x54    84 'T' */
+	_ACPI_UP,		/* 0x55    85 'U' */
+	_ACPI_UP,		/* 0x56    86 'V' */
+	_ACPI_UP,		/* 0x57    87 'W' */
+	_ACPI_UP,		/* 0x58    88 'X' */
+	_ACPI_UP,		/* 0x59    89 'Y' */
+	_ACPI_UP,		/* 0x5A    90 'Z' */
+	_ACPI_PU,		/* 0x5B    91 '[' */
+	_ACPI_PU,		/* 0x5C    92 '\' */
+	_ACPI_PU,		/* 0x5D    93 ']' */
+	_ACPI_PU,		/* 0x5E    94 '^' */
+	_ACPI_PU,		/* 0x5F    95 '_' */
+	_ACPI_PU,		/* 0x60    96 '`' */
+	_ACPI_XD | _ACPI_LO,	/* 0x61    97 'a' */
+	_ACPI_XD | _ACPI_LO,	/* 0x62    98 'b' */
+	_ACPI_XD | _ACPI_LO,	/* 0x63    99 'c' */
+	_ACPI_XD | _ACPI_LO,	/* 0x64   100 'd' */
+	_ACPI_XD | _ACPI_LO,	/* 0x65   101 'e' */
+	_ACPI_XD | _ACPI_LO,	/* 0x66   102 'f' */
+	_ACPI_LO,		/* 0x67   103 'g' */
+	_ACPI_LO,		/* 0x68   104 'h' */
+	_ACPI_LO,		/* 0x69   105 'i' */
+	_ACPI_LO,		/* 0x6A   106 'j' */
+	_ACPI_LO,		/* 0x6B   107 'k' */
+	_ACPI_LO,		/* 0x6C   108 'l' */
+	_ACPI_LO,		/* 0x6D   109 'm' */
+	_ACPI_LO,		/* 0x6E   110 'n' */
+	_ACPI_LO,		/* 0x6F   111 'o' */
+	_ACPI_LO,		/* 0x70   112 'p' */
+	_ACPI_LO,		/* 0x71   113 'q' */
+	_ACPI_LO,		/* 0x72   114 'r' */
+	_ACPI_LO,		/* 0x73   115 's' */
+	_ACPI_LO,		/* 0x74   116 't' */
+	_ACPI_LO,		/* 0x75   117 'u' */
+	_ACPI_LO,		/* 0x76   118 'v' */
+	_ACPI_LO,		/* 0x77   119 'w' */
+	_ACPI_LO,		/* 0x78   120 'x' */
+	_ACPI_LO,		/* 0x79   121 'y' */
+	_ACPI_LO,		/* 0x7A   122 'z' */
+	_ACPI_PU,		/* 0x7B   123 '{' */
+	_ACPI_PU,		/* 0x7C   124 '|' */
+	_ACPI_PU,		/* 0x7D   125 '}' */
+	_ACPI_PU,		/* 0x7E   126 '~' */
+	_ACPI_CN,		/* 0x7F   127 DEL */
+
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0x80 to 0x8F    */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0x90 to 0x9F    */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0xA0 to 0xAF    */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0xB0 to 0xBF    */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0xC0 to 0xCF    */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0xD0 to 0xDF    */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0xE0 to 0xEF    */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0xF0 to 0xFF    */
+	0			/* 0x100 */
+};
+
+#endif				/* ACPI_USE_SYSTEM_CLIBRARY */
diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c
index e810894..5d95166 100644
--- a/drivers/acpi/acpica/utdebug.c
+++ b/drivers/acpi/acpica/utdebug.c
@@ -47,8 +47,9 @@
 
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utdebug")
+
 #ifdef ACPI_DEBUG_OUTPUT
-static acpi_thread_id acpi_gbl_prev_thread_id;
+static acpi_thread_id acpi_gbl_prev_thread_id = (acpi_thread_id) 0xFFFFFFFF;
 static char *acpi_gbl_fn_entry_str = "----Entry";
 static char *acpi_gbl_fn_exit_str = "----Exit-";
 
@@ -109,7 +110,7 @@ void acpi_ut_track_stack_ptr(void)
  * RETURN:      Updated pointer to the function name
  *
  * DESCRIPTION: Remove the "Acpi" prefix from the function name, if present.
- *              This allows compiler macros such as __func__ to be used
+ *              This allows compiler macros such as __FUNCTION__ to be used
  *              with no change to the debug output.
  *
  ******************************************************************************/
@@ -222,7 +223,7 @@ ACPI_EXPORT_SYMBOL(acpi_debug_print)
  *
  * RETURN:      None
  *
- * DESCRIPTION: Print message with no headers.  Has same interface as
+ * DESCRIPTION: Print message with no headers. Has same interface as
  *              debug_print so that the same macros can be used.
  *
  ******************************************************************************/
@@ -258,7 +259,7 @@ ACPI_EXPORT_SYMBOL(acpi_debug_print_raw)
  *
  * RETURN:      None
  *
- * DESCRIPTION: Function entry trace.  Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
  *              set in debug_level
  *
  ******************************************************************************/
@@ -290,7 +291,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_trace)
  *
  * RETURN:      None
  *
- * DESCRIPTION: Function entry trace.  Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
  *              set in debug_level
  *
  ******************************************************************************/
@@ -299,6 +300,7 @@ acpi_ut_trace_ptr(u32 line_number,
 		  const char *function_name,
 		  const char *module_name, u32 component_id, void *pointer)
 {
+
 	acpi_gbl_nesting_level++;
 	acpi_ut_track_stack_ptr();
 
@@ -319,7 +321,7 @@ acpi_ut_trace_ptr(u32 line_number,
  *
  * RETURN:      None
  *
- * DESCRIPTION: Function entry trace.  Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
  *              set in debug_level
  *
  ******************************************************************************/
@@ -350,7 +352,7 @@ acpi_ut_trace_str(u32 line_number,
  *
  * RETURN:      None
  *
- * DESCRIPTION: Function entry trace.  Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
  *              set in debug_level
  *
  ******************************************************************************/
@@ -380,7 +382,7 @@ acpi_ut_trace_u32(u32 line_number,
  *
  * RETURN:      None
  *
- * DESCRIPTION: Function exit trace.  Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
  *              set in debug_level
  *
  ******************************************************************************/
@@ -412,7 +414,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_exit)
  *
  * RETURN:      None
  *
- * DESCRIPTION: Function exit trace.  Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
  *              set in debug_level. Prints exit status also.
  *
  ******************************************************************************/
@@ -453,7 +455,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_status_exit)
  *
  * RETURN:      None
  *
- * DESCRIPTION: Function exit trace.  Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
  *              set in debug_level. Prints exit value also.
  *
  ******************************************************************************/
@@ -485,7 +487,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_value_exit)
  *
  * RETURN:      None
  *
- * DESCRIPTION: Function exit trace.  Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
  *              set in debug_level. Prints exit value also.
  *
  ******************************************************************************/
@@ -511,7 +513,7 @@ acpi_ut_ptr_exit(u32 line_number,
  * PARAMETERS:  buffer              - Buffer to dump
  *              count               - Amount to dump, in bytes
  *              display             - BYTE, WORD, DWORD, or QWORD display
- *              component_ID        - Caller's component ID
+ *              offset              - Beginning buffer offset (display only)
  *
  * RETURN:      None
  *
@@ -519,7 +521,7 @@ acpi_ut_ptr_exit(u32 line_number,
  *
  ******************************************************************************/
 
-void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
+void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 base_offset)
 {
 	u32 i = 0;
 	u32 j;
@@ -541,7 +543,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
 
 		/* Print current offset */
 
-		acpi_os_printf("%6.4X: ", i);
+		acpi_os_printf("%6.4X: ", (base_offset + i));
 
 		/* Print 16 hex chars */
 
@@ -623,7 +625,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ut_dump_buffer
+ * FUNCTION:    acpi_ut_debug_dump_buffer
  *
  * PARAMETERS:  buffer              - Buffer to dump
  *              count               - Amount to dump, in bytes
@@ -636,7 +638,8 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
  *
  ******************************************************************************/
 
-void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id)
+void
+acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id)
 {
 
 	/* Only dump the buffer if tracing is enabled */
@@ -646,5 +649,5 @@ void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id)
 		return;
 	}
 
-	acpi_ut_dump_buffer2(buffer, count, display);
+	acpi_ut_dump_buffer(buffer, count, display, 0);
 }
diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c
index 5d84e19..774c3ae 100644
--- a/drivers/acpi/acpica/utids.c
+++ b/drivers/acpi/acpica/utids.c
@@ -67,10 +67,10 @@ ACPI_MODULE_NAME("utids")
  ******************************************************************************/
 acpi_status
 acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
-		    struct acpica_device_id **return_id)
+		    struct acpi_pnp_device_id **return_id)
 {
 	union acpi_operand_object *obj_desc;
-	struct acpica_device_id *hid;
+	struct acpi_pnp_device_id *hid;
 	u32 length;
 	acpi_status status;
 
@@ -94,16 +94,17 @@ acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
 	/* Allocate a buffer for the HID */
 
 	hid =
-	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) +
+	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
 				 (acpi_size) length);
 	if (!hid) {
 		status = AE_NO_MEMORY;
 		goto cleanup;
 	}
 
-	/* Area for the string starts after DEVICE_ID struct */
+	/* Area for the string starts after PNP_DEVICE_ID struct */
 
-	hid->string = ACPI_ADD_PTR(char, hid, sizeof(struct acpica_device_id));
+	hid->string =
+	    ACPI_ADD_PTR(char, hid, sizeof(struct acpi_pnp_device_id));
 
 	/* Convert EISAID to a string or simply copy existing string */
 
@@ -126,6 +127,73 @@ cleanup:
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ut_execute_SUB
+ *
+ * PARAMETERS:  device_node         - Node for the device
+ *              return_id           - Where the _SUB is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Executes the _SUB control method that returns the subsystem
+ *              ID of the device. The _SUB value is always a string containing
+ *              either a valid PNP or ACPI ID.
+ *
+ *              NOTE: Internal function, no parameter validation
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_execute_SUB(struct acpi_namespace_node *device_node,
+		    struct acpi_pnp_device_id **return_id)
+{
+	union acpi_operand_object *obj_desc;
+	struct acpi_pnp_device_id *sub;
+	u32 length;
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE(ut_execute_SUB);
+
+	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__SUB,
+					 ACPI_BTYPE_STRING, &obj_desc);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	/* Get the size of the String to be returned, includes null terminator */
+
+	length = obj_desc->string.length + 1;
+
+	/* Allocate a buffer for the SUB */
+
+	sub =
+	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
+				 (acpi_size) length);
+	if (!sub) {
+		status = AE_NO_MEMORY;
+		goto cleanup;
+	}
+
+	/* Area for the string starts after PNP_DEVICE_ID struct */
+
+	sub->string =
+	    ACPI_ADD_PTR(char, sub, sizeof(struct acpi_pnp_device_id));
+
+	/* Simply copy existing string */
+
+	ACPI_STRCPY(sub->string, obj_desc->string.pointer);
+	sub->length = length;
+	*return_id = sub;
+
+      cleanup:
+
+	/* On exit, we must delete the return object */
+
+	acpi_ut_remove_reference(obj_desc);
+	return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ut_execute_UID
  *
  * PARAMETERS:  device_node         - Node for the device
@@ -144,10 +212,10 @@ cleanup:
 
 acpi_status
 acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
-		    struct acpica_device_id **return_id)
+		    struct acpi_pnp_device_id **return_id)
 {
 	union acpi_operand_object *obj_desc;
-	struct acpica_device_id *uid;
+	struct acpi_pnp_device_id *uid;
 	u32 length;
 	acpi_status status;
 
@@ -171,16 +239,17 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
 	/* Allocate a buffer for the UID */
 
 	uid =
-	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) +
+	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
 				 (acpi_size) length);
 	if (!uid) {
 		status = AE_NO_MEMORY;
 		goto cleanup;
 	}
 
-	/* Area for the string starts after DEVICE_ID struct */
+	/* Area for the string starts after PNP_DEVICE_ID struct */
 
-	uid->string = ACPI_ADD_PTR(char, uid, sizeof(struct acpica_device_id));
+	uid->string =
+	    ACPI_ADD_PTR(char, uid, sizeof(struct acpi_pnp_device_id));
 
 	/* Convert an Integer to string, or just copy an existing string */
 
@@ -226,11 +295,11 @@ cleanup:
 
 acpi_status
 acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
-		    struct acpica_device_id_list **return_cid_list)
+		    struct acpi_pnp_device_id_list **return_cid_list)
 {
 	union acpi_operand_object **cid_objects;
 	union acpi_operand_object *obj_desc;
-	struct acpica_device_id_list *cid_list;
+	struct acpi_pnp_device_id_list *cid_list;
 	char *next_id_string;
 	u32 string_area_size;
 	u32 length;
@@ -288,11 +357,12 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
 	/*
 	 * Now that we know the length of the CIDs, allocate return buffer:
 	 * 1) Size of the base structure +
-	 * 2) Size of the CID DEVICE_ID array +
+	 * 2) Size of the CID PNP_DEVICE_ID array +
 	 * 3) Size of the actual CID strings
 	 */
-	cid_list_size = sizeof(struct acpica_device_id_list) +
-	    ((count - 1) * sizeof(struct acpica_device_id)) + string_area_size;
+	cid_list_size = sizeof(struct acpi_pnp_device_id_list) +
+	    ((count - 1) * sizeof(struct acpi_pnp_device_id)) +
+	    string_area_size;
 
 	cid_list = ACPI_ALLOCATE_ZEROED(cid_list_size);
 	if (!cid_list) {
@@ -300,10 +370,10 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
 		goto cleanup;
 	}
 
-	/* Area for CID strings starts after the CID DEVICE_ID array */
+	/* Area for CID strings starts after the CID PNP_DEVICE_ID array */
 
 	next_id_string = ACPI_CAST_PTR(char, cid_list->ids) +
-	    ((acpi_size) count * sizeof(struct acpica_device_id));
+	    ((acpi_size) count * sizeof(struct acpi_pnp_device_id));
 
 	/* Copy/convert the CIDs to the return buffer */
 
diff --git a/drivers/acpi/acpica/utmath.c b/drivers/acpi/acpica/utmath.c
index d88a8aa..4956367 100644
--- a/drivers/acpi/acpica/utmath.c
+++ b/drivers/acpi/acpica/utmath.c
@@ -81,7 +81,7 @@ typedef union uint64_overlay {
  * RETURN:      Status (Checks for divide-by-zero)
  *
  * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits)
- *              divide and modulo.  The result is a 64-bit quotient and a
+ *              divide and modulo. The result is a 64-bit quotient and a
  *              32-bit remainder.
  *
  ******************************************************************************/
diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c
index 33c6cf7..9286a69 100644
--- a/drivers/acpi/acpica/utmisc.c
+++ b/drivers/acpi/acpica/utmisc.c
@@ -41,8 +41,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
-
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
@@ -201,8 +199,8 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
 				 */
 				acpi_gbl_owner_id_mask[j] |= (1 << k);
 
-				acpi_gbl_last_owner_id_index = (u8) j;
-				acpi_gbl_next_owner_id_offset = (u8) (k + 1);
+				acpi_gbl_last_owner_id_index = (u8)j;
+				acpi_gbl_next_owner_id_offset = (u8)(k + 1);
 
 				/*
 				 * Construct encoded ID from the index and bit position
@@ -252,7 +250,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
  *              control method or unloading a table. Either way, we would
  *              ignore any error anyway.
  *
- * DESCRIPTION: Release a table or method owner ID.  Valid IDs are 1 - 255
+ * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255
  *
  ******************************************************************************/
 
@@ -339,6 +337,73 @@ void acpi_ut_strupr(char *src_string)
 	return;
 }
 
+#ifdef ACPI_ASL_COMPILER
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strlwr (strlwr)
+ *
+ * PARAMETERS:  src_string      - The source string to convert
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Convert string to lowercase
+ *
+ * NOTE: This is not a POSIX function, so it appears here, not in utclib.c
+ *
+ ******************************************************************************/
+
+void acpi_ut_strlwr(char *src_string)
+{
+	char *string;
+
+	ACPI_FUNCTION_ENTRY();
+
+	if (!src_string) {
+		return;
+	}
+
+	/* Walk entire string, lowercasing the letters */
+
+	for (string = src_string; *string; string++) {
+		*string = (char)ACPI_TOLOWER(*string);
+	}
+
+	return;
+}
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_stricmp
+ *
+ * PARAMETERS:  string1             - first string to compare
+ *              string2             - second string to compare
+ *
+ * RETURN:      int that signifies string relationship. Zero means strings
+ *              are equal.
+ *
+ * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare
+ *              strings with no case sensitivity)
+ *
+ ******************************************************************************/
+
+int acpi_ut_stricmp(char *string1, char *string2)
+{
+	int c1;
+	int c2;
+
+	do {
+		c1 = tolower((int)*string1);
+		c2 = tolower((int)*string2);
+
+		string1++;
+		string2++;
+	}
+	while ((c1 == c2) && (c1));
+
+	return (c1 - c2);
+}
+#endif
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_print_string
@@ -469,8 +534,8 @@ u32 acpi_ut_dword_byte_swap(u32 value)
  * RETURN:      None
  *
  * DESCRIPTION: Set the global integer bit width based upon the revision
- *              of the DSDT.  For Revision 1 and 0, Integers are 32 bits.
- *              For Revision 2 and above, Integers are 64 bits.  Yes, this
+ *              of the DSDT. For Revision 1 and 0, Integers are 32 bits.
+ *              For Revision 2 and above, Integers are 64 bits. Yes, this
  *              makes a difference.
  *
  ******************************************************************************/
@@ -606,7 +671,7 @@ u8 acpi_ut_valid_acpi_char(char character, u32 position)
  *
  * RETURN:      TRUE if the name is valid, FALSE otherwise
  *
- * DESCRIPTION: Check for a valid ACPI name.  Each character must be one of:
+ * DESCRIPTION: Check for a valid ACPI name. Each character must be one of:
  *              1) Upper case alpha
  *              2) numeric
  *              3) underscore
@@ -638,29 +703,59 @@ u8 acpi_ut_valid_acpi_name(u32 name)
  * RETURN:      Repaired version of the name
  *
  * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and
- *              return the new name.
+ *              return the new name. NOTE: the Name parameter must reside in
+ *              read/write memory, cannot be a const.
+ *
+ * An ACPI Name must consist of valid ACPI characters. We will repair the name
+ * if necessary because we don't want to abort because of this, but we want
+ * all namespace names to be printable. A warning message is appropriate.
+ *
+ * This issue came up because there are in fact machines that exhibit
+ * this problem, and we want to be able to enable ACPI support for them,
+ * even though there are a few bad names.
  *
  ******************************************************************************/
 
-acpi_name acpi_ut_repair_name(char *name)
+void acpi_ut_repair_name(char *name)
 {
-       u32 i;
-	char new_name[ACPI_NAME_SIZE];
+	u32 i;
+	u8 found_bad_char = FALSE;
+	u32 original_name;
+
+	ACPI_FUNCTION_NAME(ut_repair_name);
+
+	ACPI_MOVE_NAME(&original_name, name);
+
+	/* Check each character in the name */
 
 	for (i = 0; i < ACPI_NAME_SIZE; i++) {
-		new_name[i] = name[i];
+		if (acpi_ut_valid_acpi_char(name[i], i)) {
+			continue;
+		}
 
 		/*
 		 * Replace a bad character with something printable, yet technically
 		 * still invalid. This prevents any collisions with existing "good"
 		 * names in the namespace.
 		 */
-		if (!acpi_ut_valid_acpi_char(name[i], i)) {
-			new_name[i] = '*';
-		}
+		name[i] = '*';
+		found_bad_char = TRUE;
 	}
 
-	return (*(u32 *) new_name);
+	if (found_bad_char) {
+
+		/* Report warning only if in strict mode or debug mode */
+
+		if (!acpi_gbl_enable_interpreter_slack) {
+			ACPI_WARNING((AE_INFO,
+				      "Found bad character(s) in name, repaired: [%4.4s]\n",
+				      name));
+		} else {
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+					  "Found bad character(s) in name, repaired: [%4.4s]\n",
+					  name));
+		}
+	}
 }
 
 /*******************************************************************************
@@ -681,7 +776,7 @@ acpi_name acpi_ut_repair_name(char *name)
  *
  ******************************************************************************/
 
-acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer)
+acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
 {
 	u32 this_digit = 0;
 	u64 return_value = 0;
@@ -754,14 +849,14 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer)
 
 			/* Convert ASCII 0-9 to Decimal value */
 
-			this_digit = ((u8) * string) - '0';
+			this_digit = ((u8)*string) - '0';
 		} else if (base == 10) {
 
 			/* Digit is out of range; possible in to_integer case only */
 
 			term = 1;
 		} else {
-			this_digit = (u8) ACPI_TOUPPER(*string);
+			this_digit = (u8)ACPI_TOUPPER(*string);
 			if (ACPI_IS_XDIGIT((char)this_digit)) {
 
 				/* Convert ASCII Hex char to value */
@@ -788,8 +883,9 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer)
 
 		valid_digits++;
 
-		if (sign_of0x && ((valid_digits > 16)
-				  || ((valid_digits > 8) && mode32))) {
+		if (sign_of0x
+		    && ((valid_digits > 16)
+			|| ((valid_digits > 8) && mode32))) {
 			/*
 			 * This is to_integer operation case.
 			 * No any restrictions for string-to-integer conversion,
@@ -800,7 +896,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer)
 
 		/* Divide the digit into the correct position */
 
-		(void)acpi_ut_short_divide((dividend - (u64) this_digit),
+		(void)acpi_ut_short_divide((dividend - (u64)this_digit),
 					   base, &quotient, NULL);
 
 		if (return_value > quotient) {
@@ -890,7 +986,7 @@ acpi_ut_create_update_state_and_push(union acpi_operand_object *object,
  ******************************************************************************/
 
 acpi_status
-acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
+acpi_ut_walk_package_tree(union acpi_operand_object *source_object,
 			  void *target_object,
 			  acpi_pkg_callback walk_callback, void *context)
 {
@@ -917,10 +1013,10 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
 
 		/*
 		 * Check for:
-		 * 1) An uninitialized package element.  It is completely
+		 * 1) An uninitialized package element. It is completely
 		 *    legal to declare a package and leave it uninitialized
 		 * 2) Not an internal object - can be a namespace node instead
-		 * 3) Any type other than a package.  Packages are handled in else
+		 * 3) Any type other than a package. Packages are handled in else
 		 *    case below.
 		 */
 		if ((!this_source_obj) ||
@@ -939,7 +1035,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
 			       state->pkg.source_object->package.count) {
 				/*
 				 * We've handled all of the objects at this level,  This means
-				 * that we have just completed a package.  That package may
+				 * that we have just completed a package. That package may
 				 * have contained one or more packages itself.
 				 *
 				 * Delete this state and pop the previous state (package).
diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c
index 296baa6..5ccf57c 100644
--- a/drivers/acpi/acpica/utmutex.c
+++ b/drivers/acpi/acpica/utmutex.c
@@ -193,6 +193,8 @@ static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id)
 
 	acpi_gbl_mutex_info[mutex_id].mutex = NULL;
 	acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
+
+	return_VOID;
 }
 
 /*******************************************************************************
@@ -226,9 +228,9 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
 		/*
 		 * Mutex debug code, for internal debugging only.
 		 *
-		 * Deadlock prevention.  Check if this thread owns any mutexes of value
-		 * greater than or equal to this one.  If so, the thread has violated
-		 * the mutex ordering rule.  This indicates a coding error somewhere in
+		 * Deadlock prevention. Check if this thread owns any mutexes of value
+		 * greater than or equal to this one. If so, the thread has violated
+		 * the mutex ordering rule. This indicates a coding error somewhere in
 		 * the ACPI subsystem code.
 		 */
 		for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
@@ -319,9 +321,9 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
 		/*
 		 * Mutex debug code, for internal debugging only.
 		 *
-		 * Deadlock prevention.  Check if this thread owns any mutexes of value
-		 * greater than this one.  If so, the thread has violated the mutex
-		 * ordering rule.  This indicates a coding error somewhere in
+		 * Deadlock prevention. Check if this thread owns any mutexes of value
+		 * greater than this one. If so, the thread has violated the mutex
+		 * ordering rule. This indicates a coding error somewhere in
 		 * the ACPI subsystem code.
 		 */
 		for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c
index 655f079..5c52ca7 100644
--- a/drivers/acpi/acpica/utobject.c
+++ b/drivers/acpi/acpica/utobject.c
@@ -77,7 +77,7 @@ acpi_ut_get_element_length(u8 object_type,
  *
  * NOTE:        We always allocate the worst-case object descriptor because
  *              these objects are cached, and we want them to be
- *              one-size-satisifies-any-request.  This in itself may not be
+ *              one-size-satisifies-any-request. This in itself may not be
  *              the most memory efficient, but the efficiency of the object
  *              cache should more than make up for this!
  *
@@ -370,9 +370,9 @@ u8 acpi_ut_valid_internal_object(void *object)
  *              line_number         - Caller's line number (for error output)
  *              component_id        - Caller's component ID (for error output)
  *
- * RETURN:      Pointer to newly allocated object descriptor.  Null on error
+ * RETURN:      Pointer to newly allocated object descriptor. Null on error
  *
- * DESCRIPTION: Allocate a new object descriptor.  Gracefully handle
+ * DESCRIPTION: Allocate a new object descriptor. Gracefully handle
  *              error conditions.
  *
  ******************************************************************************/
@@ -554,7 +554,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
 
 	/*
 	 * Account for the space required by the object rounded up to the next
-	 * multiple of the machine word size.  This keeps each object aligned
+	 * multiple of the machine word size. This keeps each object aligned
 	 * on a machine word boundary. (preventing alignment faults on some
 	 * machines.)
 	 */
diff --git a/drivers/acpi/acpica/utstate.c b/drivers/acpi/acpica/utstate.c
index a1c9882..cee0473 100644
--- a/drivers/acpi/acpica/utstate.c
+++ b/drivers/acpi/acpica/utstate.c
@@ -147,7 +147,7 @@ union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state
  *
  * RETURN:      The new state object. NULL on failure.
  *
- * DESCRIPTION: Create a generic state object.  Attempt to obtain one from
+ * DESCRIPTION: Create a generic state object. Attempt to obtain one from
  *              the global state cache;  If none available, create a new one.
  *
  ******************************************************************************/
diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c
new file mode 100644
index 0000000..a424a9e
--- /dev/null
+++ b/drivers/acpi/acpica/uttrack.c
@@ -0,0 +1,692 @@
+/******************************************************************************
+ *
+ * Module Name: uttrack - Memory allocation tracking routines (debug only)
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/*
+ * These procedures are used for tracking memory leaks in the subsystem, and
+ * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
+ *
+ * Each memory allocation is tracked via a doubly linked list. Each
+ * element contains the caller's component, module name, function name, and
+ * line number. acpi_ut_allocate and acpi_ut_allocate_zeroed call
+ * acpi_ut_track_allocation to add an element to the list; deletion
+ * occurs in the body of acpi_ut_free.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+
+#define _COMPONENT          ACPI_UTILITIES
+ACPI_MODULE_NAME("uttrack")
+
+/* Local prototypes */
+static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
+							    acpi_debug_mem_block
+							    *allocation);
+
+static acpi_status
+acpi_ut_track_allocation(struct acpi_debug_mem_block *address,
+			 acpi_size size,
+			 u8 alloc_type,
+			 u32 component, const char *module, u32 line);
+
+static acpi_status
+acpi_ut_remove_allocation(struct acpi_debug_mem_block *address,
+			  u32 component, const char *module, u32 line);
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_create_list
+ *
+ * PARAMETERS:  cache_name      - Ascii name for the cache
+ *              object_size     - Size of each cached object
+ *              return_cache    - Where the new cache object is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Create a local memory list for tracking purposed
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_create_list(char *list_name,
+		    u16 object_size, struct acpi_memory_list **return_cache)
+{
+	struct acpi_memory_list *cache;
+
+	cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
+	if (!cache) {
+		return (AE_NO_MEMORY);
+	}
+
+	ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list));
+
+	cache->list_name = list_name;
+	cache->object_size = object_size;
+
+	*return_cache = cache;
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_allocate_and_track
+ *
+ * PARAMETERS:  size                - Size of the allocation
+ *              component           - Component type of caller
+ *              module              - Source file name of caller
+ *              line                - Line number of caller
+ *
+ * RETURN:      Address of the allocated memory on success, NULL on failure.
+ *
+ * DESCRIPTION: The subsystem's equivalent of malloc.
+ *
+ ******************************************************************************/
+
+void *acpi_ut_allocate_and_track(acpi_size size,
+				 u32 component, const char *module, u32 line)
+{
+	struct acpi_debug_mem_block *allocation;
+	acpi_status status;
+
+	allocation =
+	    acpi_ut_allocate(size + sizeof(struct acpi_debug_mem_header),
+			     component, module, line);
+	if (!allocation) {
+		return (NULL);
+	}
+
+	status = acpi_ut_track_allocation(allocation, size,
+					  ACPI_MEM_MALLOC, component, module,
+					  line);
+	if (ACPI_FAILURE(status)) {
+		acpi_os_free(allocation);
+		return (NULL);
+	}
+
+	acpi_gbl_global_list->total_allocated++;
+	acpi_gbl_global_list->total_size += (u32)size;
+	acpi_gbl_global_list->current_total_size += (u32)size;
+	if (acpi_gbl_global_list->current_total_size >
+	    acpi_gbl_global_list->max_occupied) {
+		acpi_gbl_global_list->max_occupied =
+		    acpi_gbl_global_list->current_total_size;
+	}
+
+	return ((void *)&allocation->user_space);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_allocate_zeroed_and_track
+ *
+ * PARAMETERS:  size                - Size of the allocation
+ *              component           - Component type of caller
+ *              module              - Source file name of caller
+ *              line                - Line number of caller
+ *
+ * RETURN:      Address of the allocated memory on success, NULL on failure.
+ *
+ * DESCRIPTION: Subsystem equivalent of calloc.
+ *
+ ******************************************************************************/
+
+void *acpi_ut_allocate_zeroed_and_track(acpi_size size,
+					u32 component,
+					const char *module, u32 line)
+{
+	struct acpi_debug_mem_block *allocation;
+	acpi_status status;
+
+	allocation =
+	    acpi_ut_allocate_zeroed(size + sizeof(struct acpi_debug_mem_header),
+				    component, module, line);
+	if (!allocation) {
+
+		/* Report allocation error */
+
+		ACPI_ERROR((module, line,
+			    "Could not allocate size %u", (u32)size));
+		return (NULL);
+	}
+
+	status = acpi_ut_track_allocation(allocation, size,
+					  ACPI_MEM_CALLOC, component, module,
+					  line);
+	if (ACPI_FAILURE(status)) {
+		acpi_os_free(allocation);
+		return (NULL);
+	}
+
+	acpi_gbl_global_list->total_allocated++;
+	acpi_gbl_global_list->total_size += (u32)size;
+	acpi_gbl_global_list->current_total_size += (u32)size;
+	if (acpi_gbl_global_list->current_total_size >
+	    acpi_gbl_global_list->max_occupied) {
+		acpi_gbl_global_list->max_occupied =
+		    acpi_gbl_global_list->current_total_size;
+	}
+
+	return ((void *)&allocation->user_space);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_free_and_track
+ *
+ * PARAMETERS:  allocation          - Address of the memory to deallocate
+ *              component           - Component type of caller
+ *              module              - Source file name of caller
+ *              line                - Line number of caller
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Frees the memory at Allocation
+ *
+ ******************************************************************************/
+
+void
+acpi_ut_free_and_track(void *allocation,
+		       u32 component, const char *module, u32 line)
+{
+	struct acpi_debug_mem_block *debug_block;
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE_PTR(ut_free, allocation);
+
+	if (NULL == allocation) {
+		ACPI_ERROR((module, line, "Attempt to delete a NULL address"));
+
+		return_VOID;
+	}
+
+	debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block,
+				    (((char *)allocation) -
+				     sizeof(struct acpi_debug_mem_header)));
+
+	acpi_gbl_global_list->total_freed++;
+	acpi_gbl_global_list->current_total_size -= debug_block->size;
+
+	status = acpi_ut_remove_allocation(debug_block,
+					   component, module, line);
+	if (ACPI_FAILURE(status)) {
+		ACPI_EXCEPTION((AE_INFO, status, "Could not free memory"));
+	}
+
+	acpi_os_free(debug_block);
+	ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation));
+	return_VOID;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_find_allocation
+ *
+ * PARAMETERS:  allocation              - Address of allocated memory
+ *
+ * RETURN:      Three cases:
+ *              1) List is empty, NULL is returned.
+ *              2) Element was found. Returns Allocation parameter.
+ *              3) Element was not found. Returns position where it should be
+ *                  inserted into the list.
+ *
+ * DESCRIPTION: Searches for an element in the global allocation tracking list.
+ *              If the element is not found, returns the location within the
+ *              list where the element should be inserted.
+ *
+ *              Note: The list is ordered by larger-to-smaller addresses.
+ *
+ *              This global list is used to detect memory leaks in ACPICA as
+ *              well as other issues such as an attempt to release the same
+ *              internal object more than once. Although expensive as far
+ *              as cpu time, this list is much more helpful for finding these
+ *              types of issues than using memory leak detectors outside of
+ *              the ACPICA code.
+ *
+ ******************************************************************************/
+
+static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
+							    acpi_debug_mem_block
+							    *allocation)
+{
+	struct acpi_debug_mem_block *element;
+
+	element = acpi_gbl_global_list->list_head;
+	if (!element) {
+		return (NULL);
+	}
+
+	/*
+	 * Search for the address.
+	 *
+	 * Note: List is ordered by larger-to-smaller addresses, on the
+	 * assumption that a new allocation usually has a larger address
+	 * than previous allocations.
+	 */
+	while (element > allocation) {
+
+		/* Check for end-of-list */
+
+		if (!element->next) {
+			return (element);
+		}
+
+		element = element->next;
+	}
+
+	if (element == allocation) {
+		return (element);
+	}
+
+	return (element->previous);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_track_allocation
+ *
+ * PARAMETERS:  allocation          - Address of allocated memory
+ *              size                - Size of the allocation
+ *              alloc_type          - MEM_MALLOC or MEM_CALLOC
+ *              component           - Component type of caller
+ *              module              - Source file name of caller
+ *              line                - Line number of caller
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Inserts an element into the global allocation tracking list.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
+			 acpi_size size,
+			 u8 alloc_type,
+			 u32 component, const char *module, u32 line)
+{
+	struct acpi_memory_list *mem_list;
+	struct acpi_debug_mem_block *element;
+	acpi_status status = AE_OK;
+
+	ACPI_FUNCTION_TRACE_PTR(ut_track_allocation, allocation);
+
+	if (acpi_gbl_disable_mem_tracking) {
+		return_ACPI_STATUS(AE_OK);
+	}
+
+	mem_list = acpi_gbl_global_list;
+	status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	/*
+	 * Search the global list for this address to make sure it is not
+	 * already present. This will catch several kinds of problems.
+	 */
+	element = acpi_ut_find_allocation(allocation);
+	if (element == allocation) {
+		ACPI_ERROR((AE_INFO,
+			    "UtTrackAllocation: Allocation (%p) already present in global list!",
+			    allocation));
+		goto unlock_and_exit;
+	}
+
+	/* Fill in the instance data */
+
+	allocation->size = (u32)size;
+	allocation->alloc_type = alloc_type;
+	allocation->component = component;
+	allocation->line = line;
+
+	ACPI_STRNCPY(allocation->module, module, ACPI_MAX_MODULE_NAME);
+	allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0;
+
+	if (!element) {
+
+		/* Insert at list head */
+
+		if (mem_list->list_head) {
+			((struct acpi_debug_mem_block *)(mem_list->list_head))->
+			    previous = allocation;
+		}
+
+		allocation->next = mem_list->list_head;
+		allocation->previous = NULL;
+
+		mem_list->list_head = allocation;
+	} else {
+		/* Insert after element */
+
+		allocation->next = element->next;
+		allocation->previous = element;
+
+		if (element->next) {
+			(element->next)->previous = allocation;
+		}
+
+		element->next = allocation;
+	}
+
+      unlock_and_exit:
+	status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
+	return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_remove_allocation
+ *
+ * PARAMETERS:  allocation          - Address of allocated memory
+ *              component           - Component type of caller
+ *              module              - Source file name of caller
+ *              line                - Line number of caller
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Deletes an element from the global allocation tracking list.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation,
+			  u32 component, const char *module, u32 line)
+{
+	struct acpi_memory_list *mem_list;
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE(ut_remove_allocation);
+
+	if (acpi_gbl_disable_mem_tracking) {
+		return_ACPI_STATUS(AE_OK);
+	}
+
+	mem_list = acpi_gbl_global_list;
+	if (NULL == mem_list->list_head) {
+
+		/* No allocations! */
+
+		ACPI_ERROR((module, line,
+			    "Empty allocation list, nothing to free!"));
+
+		return_ACPI_STATUS(AE_OK);
+	}
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	/* Unlink */
+
+	if (allocation->previous) {
+		(allocation->previous)->next = allocation->next;
+	} else {
+		mem_list->list_head = allocation->next;
+	}
+
+	if (allocation->next) {
+		(allocation->next)->previous = allocation->previous;
+	}
+
+	/* Mark the segment as deleted */
+
+	ACPI_MEMSET(&allocation->user_space, 0xEA, allocation->size);
+
+	ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n",
+			  allocation->size));
+
+	status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
+	return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_dump_allocation_info
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print some info about the outstanding allocations.
+ *
+ ******************************************************************************/
+
+void acpi_ut_dump_allocation_info(void)
+{
+/*
+	struct acpi_memory_list         *mem_list;
+*/
+
+	ACPI_FUNCTION_TRACE(ut_dump_allocation_info);
+
+/*
+	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+			  ("%30s: %4d (%3d Kb)\n", "Current allocations",
+			  mem_list->current_count,
+			  ROUND_UP_TO_1K (mem_list->current_size)));
+
+	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+			  ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
+			  mem_list->max_concurrent_count,
+			  ROUND_UP_TO_1K (mem_list->max_concurrent_size)));
+
+	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+			  ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
+			  running_object_count,
+			  ROUND_UP_TO_1K (running_object_size)));
+
+	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+			  ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
+			  running_alloc_count,
+			  ROUND_UP_TO_1K (running_alloc_size)));
+
+	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+			  ("%30s: %4d (%3d Kb)\n", "Current Nodes",
+			  acpi_gbl_current_node_count,
+			  ROUND_UP_TO_1K (acpi_gbl_current_node_size)));
+
+	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+			  ("%30s: %4d (%3d Kb)\n", "Max Nodes",
+			  acpi_gbl_max_concurrent_node_count,
+			  ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count *
+					 sizeof (struct acpi_namespace_node)))));
+*/
+	return_VOID;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_dump_allocations
+ *
+ * PARAMETERS:  component           - Component(s) to dump info for.
+ *              module              - Module to dump info for. NULL means all.
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print a list of all outstanding allocations.
+ *
+ ******************************************************************************/
+
+void acpi_ut_dump_allocations(u32 component, const char *module)
+{
+	struct acpi_debug_mem_block *element;
+	union acpi_descriptor *descriptor;
+	u32 num_outstanding = 0;
+	u8 descriptor_type;
+
+	ACPI_FUNCTION_TRACE(ut_dump_allocations);
+
+	if (acpi_gbl_disable_mem_tracking) {
+		return_VOID;
+	}
+
+	/*
+	 * Walk the allocation list.
+	 */
+	if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) {
+		return_VOID;
+	}
+
+	element = acpi_gbl_global_list->list_head;
+	while (element) {
+		if ((element->component & component) &&
+		    ((module == NULL)
+		     || (0 == ACPI_STRCMP(module, element->module)))) {
+			descriptor =
+			    ACPI_CAST_PTR(union acpi_descriptor,
+					  &element->user_space);
+
+			if (element->size <
+			    sizeof(struct acpi_common_descriptor)) {
+				acpi_os_printf("%p Length 0x%04X %9.9s-%u "
+					       "[Not a Descriptor - too small]\n",
+					       descriptor, element->size,
+					       element->module, element->line);
+			} else {
+				/* Ignore allocated objects that are in a cache */
+
+				if (ACPI_GET_DESCRIPTOR_TYPE(descriptor) !=
+				    ACPI_DESC_TYPE_CACHED) {
+					acpi_os_printf
+					    ("%p Length 0x%04X %9.9s-%u [%s] ",
+					     descriptor, element->size,
+					     element->module, element->line,
+					     acpi_ut_get_descriptor_name
+					     (descriptor));
+
+					/* Validate the descriptor type using Type field and length */
+
+					descriptor_type = 0;	/* Not a valid descriptor type */
+
+					switch (ACPI_GET_DESCRIPTOR_TYPE
+						(descriptor)) {
+					case ACPI_DESC_TYPE_OPERAND:
+						if (element->size ==
+						    sizeof(union
+							   acpi_operand_object))
+						{
+							descriptor_type =
+							    ACPI_DESC_TYPE_OPERAND;
+						}
+						break;
+
+					case ACPI_DESC_TYPE_PARSER:
+						if (element->size ==
+						    sizeof(union
+							   acpi_parse_object)) {
+							descriptor_type =
+							    ACPI_DESC_TYPE_PARSER;
+						}
+						break;
+
+					case ACPI_DESC_TYPE_NAMED:
+						if (element->size ==
+						    sizeof(struct
+							   acpi_namespace_node))
+						{
+							descriptor_type =
+							    ACPI_DESC_TYPE_NAMED;
+						}
+						break;
+
+					default:
+						break;
+					}
+
+					/* Display additional info for the major descriptor types */
+
+					switch (descriptor_type) {
+					case ACPI_DESC_TYPE_OPERAND:
+						acpi_os_printf
+						    ("%12.12s RefCount 0x%04X\n",
+						     acpi_ut_get_type_name
+						     (descriptor->object.common.
+						      type),
+						     descriptor->object.common.
+						     reference_count);
+						break;
+
+					case ACPI_DESC_TYPE_PARSER:
+						acpi_os_printf
+						    ("AmlOpcode 0x%04hX\n",
+						     descriptor->op.asl.
+						     aml_opcode);
+						break;
+
+					case ACPI_DESC_TYPE_NAMED:
+						acpi_os_printf("%4.4s\n",
+							       acpi_ut_get_node_name
+							       (&descriptor->
+								node));
+						break;
+
+					default:
+						acpi_os_printf("\n");
+						break;
+					}
+				}
+			}
+
+			num_outstanding++;
+		}
+
+		element = element->next;
+	}
+
+	(void)acpi_ut_release_mutex(ACPI_MTX_MEMORY);
+
+	/* Print summary */
+
+	if (!num_outstanding) {
+		ACPI_INFO((AE_INFO, "No outstanding allocations"));
+	} else {
+		ACPI_ERROR((AE_INFO, "%u(0x%X) Outstanding allocations",
+			    num_outstanding, num_outstanding));
+	}
+
+	return_VOID;
+}
+
+#endif				/* ACPI_DBG_TRACK_ALLOCATIONS */
diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c
index b09632b..390db0c 100644
--- a/drivers/acpi/acpica/utxface.c
+++ b/drivers/acpi/acpica/utxface.c
@@ -147,7 +147,7 @@ ACPI_EXPORT_SYMBOL(acpi_subsystem_status)
  * RETURN:      status          - the status of the call
  *
  * DESCRIPTION: This function is called to get information about the current
- *              state of the ACPI subsystem.  It will return system information
+ *              state of the ACPI subsystem. It will return system information
  *              in the out_buffer.
  *
  *              If the function fails an appropriate status will be returned
@@ -238,7 +238,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function)
 	}
 
 	acpi_gbl_init_handler = handler;
-	return AE_OK;
+	return (AE_OK);
 }
 
 ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler)
@@ -263,6 +263,7 @@ acpi_status acpi_purge_cached_objects(void)
 	(void)acpi_os_purge_cache(acpi_gbl_operand_cache);
 	(void)acpi_os_purge_cache(acpi_gbl_ps_node_cache);
 	(void)acpi_os_purge_cache(acpi_gbl_ps_node_ext_cache);
+
 	return_ACPI_STATUS(AE_OK);
 }
 
diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c
index 6d63cc3..d4d3826 100644
--- a/drivers/acpi/acpica/utxferror.c
+++ b/drivers/acpi/acpica/utxferror.c
@@ -408,7 +408,7 @@ acpi_ut_namespace_error(const char *module_name,
 
 		ACPI_MOVE_32_TO_32(&bad_name,
 				   ACPI_CAST_PTR(u32, internal_name));
-		acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name);
+		acpi_os_printf("[0x%.8X] (NON-ASCII)", bad_name);
 	} else {
 		/* Convert path to external format */
 
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index e4d9d24..6d894bf 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -931,14 +931,14 @@ static int erst_check_table(struct acpi_table_erst *erst_tab)
 
 static int erst_open_pstore(struct pstore_info *psi);
 static int erst_close_pstore(struct pstore_info *psi);
-static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
+static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count,
 			   struct timespec *time, char **buf,
 			   struct pstore_info *psi);
 static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason,
-		       u64 *id, unsigned int part,
+		       u64 *id, unsigned int part, int count,
 		       size_t size, struct pstore_info *psi);
-static int erst_clearer(enum pstore_type_id type, u64 id,
-			struct pstore_info *psi);
+static int erst_clearer(enum pstore_type_id type, u64 id, int count,
+			struct timespec time, struct pstore_info *psi);
 
 static struct pstore_info erst_info = {
 	.owner		= THIS_MODULE,
@@ -987,7 +987,7 @@ static int erst_close_pstore(struct pstore_info *psi)
 	return 0;
 }
 
-static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
+static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count,
 			   struct timespec *time, char **buf,
 			   struct pstore_info *psi)
 {
@@ -1055,7 +1055,7 @@ out:
 }
 
 static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason,
-		       u64 *id, unsigned int part,
+		       u64 *id, unsigned int part, int count,
 		       size_t size, struct pstore_info *psi)
 {
 	struct cper_pstore_record *rcd = (struct cper_pstore_record *)
@@ -1101,8 +1101,8 @@ static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason,
 	return ret;
 }
 
-static int erst_clearer(enum pstore_type_id type, u64 id,
-			struct pstore_info *psi)
+static int erst_clearer(enum pstore_type_id type, u64 id, int count,
+			struct timespec time, struct pstore_info *psi)
 {
 	return erst_clear(id);
 }
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 1599566..7ae2750 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -901,7 +901,7 @@ static unsigned long ghes_esource_prealloc_size(
 	return prealloc_size;
 }
 
-static int __devinit ghes_probe(struct platform_device *ghes_dev)
+static int ghes_probe(struct platform_device *ghes_dev)
 {
 	struct acpi_hest_generic *generic;
 	struct ghes *ghes = NULL;
@@ -994,7 +994,7 @@ err:
 	return rc;
 }
 
-static int __devexit ghes_remove(struct platform_device *ghes_dev)
+static int ghes_remove(struct platform_device *ghes_dev)
 {
 	struct ghes *ghes;
 	struct acpi_hest_generic *generic;
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 45e3e17..7efaeaa 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -34,6 +34,7 @@
 #include <linux/dmi.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
+#include <asm/unaligned.h>
 
 #ifdef CONFIG_ACPI_PROCFS_POWER
 #include <linux/proc_fs.h>
@@ -95,6 +96,18 @@ enum {
 	ACPI_BATTERY_ALARM_PRESENT,
 	ACPI_BATTERY_XINFO_PRESENT,
 	ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
+	/* On Lenovo Thinkpad models from 2010 and 2011, the power unit
+	   switches between mWh and mAh depending on whether the system
+	   is running on battery or not.  When mAh is the unit, most
+	   reported values are incorrect and need to be adjusted by
+	   10000/design_voltage.  Verified on x201, t410, t410s, and x220.
+	   Pre-2010 and 2012 models appear to always report in mWh and
+	   are thus unaffected (tested with t42, t61, t500, x200, x300,
+	   and x230).  Also, in mid-2012 Lenovo issued a BIOS update for
+	   the 2011 models that fixes the issue (tested on x220 with a
+	   post-1.29 BIOS), but as of Nov. 2012, no such update is
+	   available for the 2010 models.  */
+	ACPI_BATTERY_QUIRK_THINKPAD_MAH,
 };
 
 struct acpi_battery {
@@ -438,6 +451,21 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
 	kfree(buffer.pointer);
 	if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
 		battery->full_charge_capacity = battery->design_capacity;
+	if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
+	    battery->power_unit && battery->design_voltage) {
+		battery->design_capacity = battery->design_capacity *
+		    10000 / battery->design_voltage;
+		battery->full_charge_capacity = battery->full_charge_capacity *
+		    10000 / battery->design_voltage;
+		battery->design_capacity_warning =
+		    battery->design_capacity_warning *
+		    10000 / battery->design_voltage;
+		/* Curiously, design_capacity_low, unlike the rest of them,
+		   is correct.  */
+		/* capacity_granularity_* equal 1 on the systems tested, so
+		   it's impossible to tell if they would need an adjustment
+		   or not if their values were higher.  */
+	}
 	return result;
 }
 
@@ -486,6 +514,11 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
 	    && battery->capacity_now >= 0 && battery->capacity_now <= 100)
 		battery->capacity_now = (battery->capacity_now *
 				battery->full_charge_capacity) / 100;
+	if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
+	    battery->power_unit && battery->design_voltage) {
+		battery->capacity_now = battery->capacity_now *
+		    10000 / battery->design_voltage;
+	}
 	return result;
 }
 
@@ -595,6 +628,24 @@ static void sysfs_remove_battery(struct acpi_battery *battery)
 	mutex_unlock(&battery->sysfs_lock);
 }
 
+static void find_battery(const struct dmi_header *dm, void *private)
+{
+	struct acpi_battery *battery = (struct acpi_battery *)private;
+	/* Note: the hardcoded offsets below have been extracted from
+	   the source code of dmidecode.  */
+	if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) {
+		const u8 *dmi_data = (const u8 *)(dm + 1);
+		int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6));
+		if (dm->length >= 18)
+			dmi_capacity *= dmi_data[17];
+		if (battery->design_capacity * battery->design_voltage / 1000
+		    != dmi_capacity &&
+		    battery->design_capacity * 10 == dmi_capacity)
+			set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
+				&battery->flags);
+	}
+}
+
 /*
  * According to the ACPI spec, some kinds of primary batteries can
  * report percentage battery remaining capacity directly to OS.
@@ -620,6 +671,32 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
 		battery->capacity_now = (battery->capacity_now *
 				battery->full_charge_capacity) / 100;
 	}
+
+	if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags))
+		return ;
+
+	if (battery->power_unit && dmi_name_in_vendors("LENOVO")) {
+		const char *s;
+		s = dmi_get_system_info(DMI_PRODUCT_VERSION);
+		if (s && !strnicmp(s, "ThinkPad", 8)) {
+			dmi_walk(find_battery, battery);
+			if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
+				     &battery->flags) &&
+			    battery->design_voltage) {
+				battery->design_capacity =
+				    battery->design_capacity *
+				    10000 / battery->design_voltage;
+				battery->full_charge_capacity =
+				    battery->full_charge_capacity *
+				    10000 / battery->design_voltage;
+				battery->design_capacity_warning =
+				    battery->design_capacity_warning *
+				    10000 / battery->design_voltage;
+				battery->capacity_now = battery->capacity_now *
+				    10000 / battery->design_voltage;
+			}
+		}
+	}
 }
 
 static int acpi_battery_update(struct acpi_battery *battery)
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index d59175e..1f0d457 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -257,7 +257,15 @@ static int __acpi_bus_get_power(struct acpi_device *device, int *state)
 }
 
 
-static int __acpi_bus_set_power(struct acpi_device *device, int state)
+/**
+ * acpi_device_set_power - Set power state of an ACPI device.
+ * @device: Device to set the power state of.
+ * @state: New power state to set.
+ *
+ * Callers must ensure that the device is power manageable before using this
+ * function.
+ */
+int acpi_device_set_power(struct acpi_device *device, int state)
 {
 	int result = 0;
 	acpi_status status = AE_OK;
@@ -298,6 +306,12 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state)
 	 * a lower-powered state.
 	 */
 	if (state < device->power.state) {
+		if (device->power.state >= ACPI_STATE_D3_HOT &&
+		    state != ACPI_STATE_D0) {
+			printk(KERN_WARNING PREFIX
+			      "Cannot transition to non-D0 state from D3\n");
+			return -ENODEV;
+		}
 		if (device->power.flags.power_resources) {
 			result = acpi_power_transition(device, state);
 			if (result)
@@ -341,6 +355,7 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state)
 
 	return result;
 }
+EXPORT_SYMBOL(acpi_device_set_power);
 
 
 int acpi_bus_set_power(acpi_handle handle, int state)
@@ -359,7 +374,7 @@ int acpi_bus_set_power(acpi_handle handle, int state)
 		return -ENODEV;
 	}
 
-	return __acpi_bus_set_power(device, state);
+	return acpi_device_set_power(device, state);
 }
 EXPORT_SYMBOL(acpi_bus_set_power);
 
@@ -402,7 +417,7 @@ int acpi_bus_update_power(acpi_handle handle, int *state_p)
 	if (result)
 		return result;
 
-	result = __acpi_bus_set_power(device, state);
+	result = acpi_device_set_power(device, state);
 	if (!result && state_p)
 		*state_p = state;
 
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 1f9f7d7..811910b 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -92,17 +92,24 @@ static int is_device_present(acpi_handle handle)
 	return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
 }
 
+static bool is_container_device(const char *hid)
+{
+	const struct acpi_device_id *container_id;
+
+	for (container_id = container_device_ids;
+	     container_id->id[0]; container_id++) {
+		if (!strcmp((char *)container_id->id, hid))
+			return true;
+	}
+
+	return false;
+}
+
 /*******************************************************************/
 static int acpi_container_add(struct acpi_device *device)
 {
 	struct acpi_container *container;
 
-
-	if (!device) {
-		printk(KERN_ERR PREFIX "device is NULL\n");
-		return -EINVAL;
-	}
-
 	container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
 	if (!container)
 		return -ENOMEM;
@@ -164,7 +171,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
 	case ACPI_NOTIFY_BUS_CHECK:
 		/* Fall through */
 	case ACPI_NOTIFY_DEVICE_CHECK:
-		printk(KERN_WARNING "Container driver received %s event\n",
+		pr_debug("Container driver received %s event\n",
 		       (type == ACPI_NOTIFY_BUS_CHECK) ?
 		       "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
 
@@ -185,7 +192,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
 
 		result = container_device_add(&device, handle);
 		if (result) {
-			printk(KERN_WARNING "Failed to add container\n");
+			acpi_handle_warn(handle, "Failed to add container\n");
 			break;
 		}
 
@@ -232,10 +239,8 @@ container_walk_namespace_cb(acpi_handle handle,
 		goto end;
 	}
 
-	if (strcmp(hid, "ACPI0004") && strcmp(hid, "PNP0A05") &&
-	    strcmp(hid, "PNP0A06")) {
+	if (!is_container_device(hid))
 		goto end;
-	}
 
 	switch (*action) {
 	case INSTALL_NOTIFY_HANDLER:
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
new file mode 100644
index 0000000..f09dc98
--- /dev/null
+++ b/drivers/acpi/device_pm.c
@@ -0,0 +1,668 @@
+/*
+ * drivers/acpi/device_pm.c - ACPI device power management routines.
+ *
+ * Copyright (C) 2012, Intel Corp.
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/mutex.h>
+#include <linux/pm_qos.h>
+#include <linux/pm_runtime.h>
+
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+
+static DEFINE_MUTEX(acpi_pm_notifier_lock);
+
+/**
+ * acpi_add_pm_notifier - Register PM notifier for given ACPI device.
+ * @adev: ACPI device to add the notifier for.
+ * @context: Context information to pass to the notifier routine.
+ *
+ * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
+ * PM wakeup events.  For example, wakeup events may be generated for bridges
+ * if one of the devices below the bridge is signaling wakeup, even if the
+ * bridge itself doesn't have a wakeup GPE associated with it.
+ */
+acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
+				 acpi_notify_handler handler, void *context)
+{
+	acpi_status status = AE_ALREADY_EXISTS;
+
+	mutex_lock(&acpi_pm_notifier_lock);
+
+	if (adev->wakeup.flags.notifier_present)
+		goto out;
+
+	status = acpi_install_notify_handler(adev->handle,
+					     ACPI_SYSTEM_NOTIFY,
+					     handler, context);
+	if (ACPI_FAILURE(status))
+		goto out;
+
+	adev->wakeup.flags.notifier_present = true;
+
+ out:
+	mutex_unlock(&acpi_pm_notifier_lock);
+	return status;
+}
+
+/**
+ * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device.
+ * @adev: ACPI device to remove the notifier from.
+ */
+acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
+				    acpi_notify_handler handler)
+{
+	acpi_status status = AE_BAD_PARAMETER;
+
+	mutex_lock(&acpi_pm_notifier_lock);
+
+	if (!adev->wakeup.flags.notifier_present)
+		goto out;
+
+	status = acpi_remove_notify_handler(adev->handle,
+					    ACPI_SYSTEM_NOTIFY,
+					    handler);
+	if (ACPI_FAILURE(status))
+		goto out;
+
+	adev->wakeup.flags.notifier_present = false;
+
+ out:
+	mutex_unlock(&acpi_pm_notifier_lock);
+	return status;
+}
+
+/**
+ * acpi_device_power_state - Get preferred power state of ACPI device.
+ * @dev: Device whose preferred target power state to return.
+ * @adev: ACPI device node corresponding to @dev.
+ * @target_state: System state to match the resultant device state.
+ * @d_max_in: Deepest low-power state to take into consideration.
+ * @d_min_p: Location to store the upper limit of the allowed states range.
+ * Return value: Preferred power state of the device on success, -ENODEV
+ * (if there's no 'struct acpi_device' for @dev) or -EINVAL on failure
+ *
+ * Find the lowest power (highest number) ACPI device power state that the
+ * device can be in while the system is in the state represented by
+ * @target_state.  If @d_min_p is set, the highest power (lowest number) device
+ * power state that @dev can be in for the given system sleep state is stored
+ * at the location pointed to by it.
+ *
+ * Callers must ensure that @dev and @adev are valid pointers and that @adev
+ * actually corresponds to @dev before using this function.
+ */
+int acpi_device_power_state(struct device *dev, struct acpi_device *adev,
+			    u32 target_state, int d_max_in, int *d_min_p)
+{
+	char acpi_method[] = "_SxD";
+	unsigned long long d_min, d_max;
+	bool wakeup = false;
+
+	if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3)
+		return -EINVAL;
+
+	if (d_max_in > ACPI_STATE_D3_HOT) {
+		enum pm_qos_flags_status stat;
+
+		stat = dev_pm_qos_flags(dev, PM_QOS_FLAG_NO_POWER_OFF);
+		if (stat == PM_QOS_FLAGS_ALL)
+			d_max_in = ACPI_STATE_D3_HOT;
+	}
+
+	acpi_method[2] = '0' + target_state;
+	/*
+	 * If the sleep state is S0, the lowest limit from ACPI is D3,
+	 * but if the device has _S0W, we will use the value from _S0W
+	 * as the lowest limit from ACPI.  Finally, we will constrain
+	 * the lowest limit with the specified one.
+	 */
+	d_min = ACPI_STATE_D0;
+	d_max = ACPI_STATE_D3;
+
+	/*
+	 * If present, _SxD methods return the minimum D-state (highest power
+	 * state) we can use for the corresponding S-states.  Otherwise, the
+	 * minimum D-state is D0 (ACPI 3.x).
+	 *
+	 * NOTE: We rely on acpi_evaluate_integer() not clobbering the integer
+	 * provided -- that's our fault recovery, we ignore retval.
+	 */
+	if (target_state > ACPI_STATE_S0) {
+		acpi_evaluate_integer(adev->handle, acpi_method, NULL, &d_min);
+		wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid
+			&& adev->wakeup.sleep_state >= target_state;
+	} else if (dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) !=
+			PM_QOS_FLAGS_NONE) {
+		wakeup = adev->wakeup.flags.valid;
+	}
+
+	/*
+	 * If _PRW says we can wake up the system from the target sleep state,
+	 * the D-state returned by _SxD is sufficient for that (we assume a
+	 * wakeup-aware driver if wake is set).  Still, if _SxW exists
+	 * (ACPI 3.x), it should return the maximum (lowest power) D-state that
+	 * can wake the system.  _S0W may be valid, too.
+	 */
+	if (wakeup) {
+		acpi_status status;
+
+		acpi_method[3] = 'W';
+		status = acpi_evaluate_integer(adev->handle, acpi_method, NULL,
+						&d_max);
+		if (ACPI_FAILURE(status)) {
+			if (target_state != ACPI_STATE_S0 ||
+			    status != AE_NOT_FOUND)
+				d_max = d_min;
+		} else if (d_max < d_min) {
+			/* Warn the user of the broken DSDT */
+			printk(KERN_WARNING "ACPI: Wrong value from %s\n",
+				acpi_method);
+			/* Sanitize it */
+			d_min = d_max;
+		}
+	}
+
+	if (d_max_in < d_min)
+		return -EINVAL;
+	if (d_min_p)
+		*d_min_p = d_min;
+	/* constrain d_max with specified lowest limit (max number) */
+	if (d_max > d_max_in) {
+		for (d_max = d_max_in; d_max > d_min; d_max--) {
+			if (adev->power.states[d_max].flags.valid)
+				break;
+		}
+	}
+	return d_max;
+}
+EXPORT_SYMBOL_GPL(acpi_device_power_state);
+
+/**
+ * acpi_pm_device_sleep_state - Get preferred power state of ACPI device.
+ * @dev: Device whose preferred target power state to return.
+ * @d_min_p: Location to store the upper limit of the allowed states range.
+ * @d_max_in: Deepest low-power state to take into consideration.
+ * Return value: Preferred power state of the device on success, -ENODEV
+ * (if there's no 'struct acpi_device' for @dev) or -EINVAL on failure
+ *
+ * The caller must ensure that @dev is valid before using this function.
+ */
+int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
+{
+	acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
+	struct acpi_device *adev;
+
+	if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
+		dev_dbg(dev, "ACPI handle without context in %s!\n", __func__);
+		return -ENODEV;
+	}
+
+	return acpi_device_power_state(dev, adev, acpi_target_system_state(),
+				       d_max_in, d_min_p);
+}
+EXPORT_SYMBOL(acpi_pm_device_sleep_state);
+
+#ifdef CONFIG_PM_RUNTIME
+/**
+ * acpi_wakeup_device - Wakeup notification handler for ACPI devices.
+ * @handle: ACPI handle of the device the notification is for.
+ * @event: Type of the signaled event.
+ * @context: Device corresponding to @handle.
+ */
+static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context)
+{
+	struct device *dev = context;
+
+	if (event == ACPI_NOTIFY_DEVICE_WAKE && dev) {
+		pm_wakeup_event(dev, 0);
+		pm_runtime_resume(dev);
+	}
+}
+
+/**
+ * __acpi_device_run_wake - Enable/disable runtime remote wakeup for device.
+ * @adev: ACPI device to enable/disable the remote wakeup for.
+ * @enable: Whether to enable or disable the wakeup functionality.
+ *
+ * Enable/disable the GPE associated with @adev so that it can generate
+ * wakeup signals for the device in response to external (remote) events and
+ * enable/disable device wakeup power.
+ *
+ * Callers must ensure that @adev is a valid ACPI device node before executing
+ * this function.
+ */
+int __acpi_device_run_wake(struct acpi_device *adev, bool enable)
+{
+	struct acpi_device_wakeup *wakeup = &adev->wakeup;
+
+	if (enable) {
+		acpi_status res;
+		int error;
+
+		error = acpi_enable_wakeup_device_power(adev, ACPI_STATE_S0);
+		if (error)
+			return error;
+
+		res = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number);
+		if (ACPI_FAILURE(res)) {
+			acpi_disable_wakeup_device_power(adev);
+			return -EIO;
+		}
+	} else {
+		acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number);
+		acpi_disable_wakeup_device_power(adev);
+	}
+	return 0;
+}
+
+/**
+ * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device.
+ * @dev: Device to enable/disable the platform to wake up.
+ * @enable: Whether to enable or disable the wakeup functionality.
+ */
+int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
+{
+	struct acpi_device *adev;
+	acpi_handle handle;
+
+	if (!device_run_wake(phys_dev))
+		return -EINVAL;
+
+	handle = DEVICE_ACPI_HANDLE(phys_dev);
+	if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
+		dev_dbg(phys_dev, "ACPI handle without context in %s!\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	return __acpi_device_run_wake(adev, enable);
+}
+EXPORT_SYMBOL(acpi_pm_device_run_wake);
+#else
+static inline void acpi_wakeup_device(acpi_handle handle, u32 event,
+				      void *context) {}
+#endif /* CONFIG_PM_RUNTIME */
+
+ #ifdef CONFIG_PM_SLEEP
+/**
+ * __acpi_device_sleep_wake - Enable or disable device to wake up the system.
+ * @dev: Device to enable/desible to wake up the system.
+ * @target_state: System state the device is supposed to wake up from.
+ * @enable: Whether to enable or disable @dev to wake up the system.
+ */
+int __acpi_device_sleep_wake(struct acpi_device *adev, u32 target_state,
+			     bool enable)
+{
+	return enable ?
+		acpi_enable_wakeup_device_power(adev, target_state) :
+		acpi_disable_wakeup_device_power(adev);
+}
+
+/**
+ * acpi_pm_device_sleep_wake - Enable or disable device to wake up the system.
+ * @dev: Device to enable/desible to wake up the system from sleep states.
+ * @enable: Whether to enable or disable @dev to wake up the system.
+ */
+int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
+{
+	acpi_handle handle;
+	struct acpi_device *adev;
+	int error;
+
+	if (!device_can_wakeup(dev))
+		return -EINVAL;
+
+	handle = DEVICE_ACPI_HANDLE(dev);
+	if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
+		dev_dbg(dev, "ACPI handle without context in %s!\n", __func__);
+		return -ENODEV;
+	}
+
+	error = __acpi_device_sleep_wake(adev, acpi_target_system_state(),
+					 enable);
+	if (!error)
+		dev_info(dev, "System wakeup %s by ACPI\n",
+				enable ? "enabled" : "disabled");
+
+	return error;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+/**
+ * acpi_dev_pm_get_node - Get ACPI device node for the given physical device.
+ * @dev: Device to get the ACPI node for.
+ */
+static struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
+{
+	acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
+	struct acpi_device *adev;
+
+	return handle && ACPI_SUCCESS(acpi_bus_get_device(handle, &adev)) ?
+		adev : NULL;
+}
+
+/**
+ * acpi_dev_pm_low_power - Put ACPI device into a low-power state.
+ * @dev: Device to put into a low-power state.
+ * @adev: ACPI device node corresponding to @dev.
+ * @system_state: System state to choose the device state for.
+ */
+static int acpi_dev_pm_low_power(struct device *dev, struct acpi_device *adev,
+				 u32 system_state)
+{
+	int power_state;
+
+	if (!acpi_device_power_manageable(adev))
+		return 0;
+
+	power_state = acpi_device_power_state(dev, adev, system_state,
+					      ACPI_STATE_D3, NULL);
+	if (power_state < ACPI_STATE_D0 || power_state > ACPI_STATE_D3)
+		return -EIO;
+
+	return acpi_device_set_power(adev, power_state);
+}
+
+/**
+ * acpi_dev_pm_full_power - Put ACPI device into the full-power state.
+ * @adev: ACPI device node to put into the full-power state.
+ */
+static int acpi_dev_pm_full_power(struct acpi_device *adev)
+{
+	return acpi_device_power_manageable(adev) ?
+		acpi_device_set_power(adev, ACPI_STATE_D0) : 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+/**
+ * acpi_dev_runtime_suspend - Put device into a low-power state using ACPI.
+ * @dev: Device to put into a low-power state.
+ *
+ * Put the given device into a runtime low-power state using the standard ACPI
+ * mechanism.  Set up remote wakeup if desired, choose the state to put the
+ * device into (this checks if remote wakeup is expected to work too), and set
+ * the power state of the device.
+ */
+int acpi_dev_runtime_suspend(struct device *dev)
+{
+	struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+	bool remote_wakeup;
+	int error;
+
+	if (!adev)
+		return 0;
+
+	remote_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) >
+				PM_QOS_FLAGS_NONE;
+	error = __acpi_device_run_wake(adev, remote_wakeup);
+	if (remote_wakeup && error)
+		return -EAGAIN;
+
+	error = acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
+	if (error)
+		__acpi_device_run_wake(adev, false);
+
+	return error;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_runtime_suspend);
+
+/**
+ * acpi_dev_runtime_resume - Put device into the full-power state using ACPI.
+ * @dev: Device to put into the full-power state.
+ *
+ * Put the given device into the full-power state using the standard ACPI
+ * mechanism at run time.  Set the power state of the device to ACPI D0 and
+ * disable remote wakeup.
+ */
+int acpi_dev_runtime_resume(struct device *dev)
+{
+	struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+	int error;
+
+	if (!adev)
+		return 0;
+
+	error = acpi_dev_pm_full_power(adev);
+	__acpi_device_run_wake(adev, false);
+	return error;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_runtime_resume);
+
+/**
+ * acpi_subsys_runtime_suspend - Suspend device using ACPI.
+ * @dev: Device to suspend.
+ *
+ * Carry out the generic runtime suspend procedure for @dev and use ACPI to put
+ * it into a runtime low-power state.
+ */
+int acpi_subsys_runtime_suspend(struct device *dev)
+{
+	int ret = pm_generic_runtime_suspend(dev);
+	return ret ? ret : acpi_dev_runtime_suspend(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_subsys_runtime_suspend);
+
+/**
+ * acpi_subsys_runtime_resume - Resume device using ACPI.
+ * @dev: Device to Resume.
+ *
+ * Use ACPI to put the given device into the full-power state and carry out the
+ * generic runtime resume procedure for it.
+ */
+int acpi_subsys_runtime_resume(struct device *dev)
+{
+	int ret = acpi_dev_runtime_resume(dev);
+	return ret ? ret : pm_generic_runtime_resume(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_subsys_runtime_resume);
+#endif /* CONFIG_PM_RUNTIME */
+
+#ifdef CONFIG_PM_SLEEP
+/**
+ * acpi_dev_suspend_late - Put device into a low-power state using ACPI.
+ * @dev: Device to put into a low-power state.
+ *
+ * Put the given device into a low-power state during system transition to a
+ * sleep state using the standard ACPI mechanism.  Set up system wakeup if
+ * desired, choose the state to put the device into (this checks if system
+ * wakeup is expected to work too), and set the power state of the device.
+ */
+int acpi_dev_suspend_late(struct device *dev)
+{
+	struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+	u32 target_state;
+	bool wakeup;
+	int error;
+
+	if (!adev)
+		return 0;
+
+	target_state = acpi_target_system_state();
+	wakeup = device_may_wakeup(dev);
+	error = __acpi_device_sleep_wake(adev, target_state, wakeup);
+	if (wakeup && error)
+		return error;
+
+	error = acpi_dev_pm_low_power(dev, adev, target_state);
+	if (error)
+		__acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false);
+
+	return error;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_suspend_late);
+
+/**
+ * acpi_dev_resume_early - Put device into the full-power state using ACPI.
+ * @dev: Device to put into the full-power state.
+ *
+ * Put the given device into the full-power state using the standard ACPI
+ * mechanism during system transition to the working state.  Set the power
+ * state of the device to ACPI D0 and disable remote wakeup.
+ */
+int acpi_dev_resume_early(struct device *dev)
+{
+	struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+	int error;
+
+	if (!adev)
+		return 0;
+
+	error = acpi_dev_pm_full_power(adev);
+	__acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false);
+	return error;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resume_early);
+
+/**
+ * acpi_subsys_prepare - Prepare device for system transition to a sleep state.
+ * @dev: Device to prepare.
+ */
+int acpi_subsys_prepare(struct device *dev)
+{
+	/*
+	 * Follow PCI and resume devices suspended at run time before running
+	 * their system suspend callbacks.
+	 */
+	pm_runtime_resume(dev);
+	return pm_generic_prepare(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_subsys_prepare);
+
+/**
+ * acpi_subsys_suspend_late - Suspend device using ACPI.
+ * @dev: Device to suspend.
+ *
+ * Carry out the generic late suspend procedure for @dev and use ACPI to put
+ * it into a low-power state during system transition into a sleep state.
+ */
+int acpi_subsys_suspend_late(struct device *dev)
+{
+	int ret = pm_generic_suspend_late(dev);
+	return ret ? ret : acpi_dev_suspend_late(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_subsys_suspend_late);
+
+/**
+ * acpi_subsys_resume_early - Resume device using ACPI.
+ * @dev: Device to Resume.
+ *
+ * Use ACPI to put the given device into the full-power state and carry out the
+ * generic early resume procedure for it during system transition into the
+ * working state.
+ */
+int acpi_subsys_resume_early(struct device *dev)
+{
+	int ret = acpi_dev_resume_early(dev);
+	return ret ? ret : pm_generic_resume_early(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_subsys_resume_early);
+#endif /* CONFIG_PM_SLEEP */
+
+static struct dev_pm_domain acpi_general_pm_domain = {
+	.ops = {
+#ifdef CONFIG_PM_RUNTIME
+		.runtime_suspend = acpi_subsys_runtime_suspend,
+		.runtime_resume = acpi_subsys_runtime_resume,
+		.runtime_idle = pm_generic_runtime_idle,
+#endif
+#ifdef CONFIG_PM_SLEEP
+		.prepare = acpi_subsys_prepare,
+		.suspend_late = acpi_subsys_suspend_late,
+		.resume_early = acpi_subsys_resume_early,
+		.poweroff_late = acpi_subsys_suspend_late,
+		.restore_early = acpi_subsys_resume_early,
+#endif
+	},
+};
+
+/**
+ * acpi_dev_pm_attach - Prepare device for ACPI power management.
+ * @dev: Device to prepare.
+ * @power_on: Whether or not to power on the device.
+ *
+ * If @dev has a valid ACPI handle that has a valid struct acpi_device object
+ * attached to it, install a wakeup notification handler for the device and
+ * add it to the general ACPI PM domain.  If @power_on is set, the device will
+ * be put into the ACPI D0 state before the function returns.
+ *
+ * This assumes that the @dev's bus type uses generic power management callbacks
+ * (or doesn't use any power management callbacks at all).
+ *
+ * Callers must ensure proper synchronization of this function with power
+ * management callbacks.
+ */
+int acpi_dev_pm_attach(struct device *dev, bool power_on)
+{
+	struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+
+	if (!adev)
+		return -ENODEV;
+
+	if (dev->pm_domain)
+		return -EEXIST;
+
+	acpi_add_pm_notifier(adev, acpi_wakeup_device, dev);
+	dev->pm_domain = &acpi_general_pm_domain;
+	if (power_on) {
+		acpi_dev_pm_full_power(adev);
+		__acpi_device_run_wake(adev, false);
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_pm_attach);
+
+/**
+ * acpi_dev_pm_detach - Remove ACPI power management from the device.
+ * @dev: Device to take care of.
+ * @power_off: Whether or not to try to remove power from the device.
+ *
+ * Remove the device from the general ACPI PM domain and remove its wakeup
+ * notifier.  If @power_off is set, additionally remove power from the device if
+ * possible.
+ *
+ * Callers must ensure proper synchronization of this function with power
+ * management callbacks.
+ */
+void acpi_dev_pm_detach(struct device *dev, bool power_off)
+{
+	struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+
+	if (adev && dev->pm_domain == &acpi_general_pm_domain) {
+		dev->pm_domain = NULL;
+		acpi_remove_pm_notifier(adev, acpi_wakeup_device);
+		if (power_off) {
+			/*
+			 * If the device's PM QoS resume latency limit or flags
+			 * have been exposed to user space, they have to be
+			 * hidden at this point, so that they don't affect the
+			 * choice of the low-power state to put the device into.
+			 */
+			dev_pm_qos_hide_latency_limit(dev);
+			dev_pm_qos_hide_flags(dev);
+			__acpi_device_run_wake(adev, false);
+			acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(acpi_dev_pm_detach);
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 88eb143..f32bd47 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -31,6 +31,7 @@
 #include <linux/platform_device.h>
 #include <linux/jiffies.h>
 #include <linux/stddef.h>
+#include <linux/acpi.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -460,12 +461,8 @@ static void handle_dock(struct dock_station *ds, int dock)
 	struct acpi_object_list arg_list;
 	union acpi_object arg;
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-	struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 
-	acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer);
-
-	printk(KERN_INFO PREFIX "%s - %s\n",
-		(char *)name_buffer.pointer, dock ? "docking" : "undocking");
+	acpi_handle_info(ds->handle, "%s\n", dock ? "docking" : "undocking");
 
 	/* _DCK method has one argument */
 	arg_list.count = 1;
@@ -474,11 +471,10 @@ static void handle_dock(struct dock_station *ds, int dock)
 	arg.integer.value = dock;
 	status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer);
 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
-		ACPI_EXCEPTION((AE_INFO, status, "%s - failed to execute"
-			" _DCK\n", (char *)name_buffer.pointer));
+		acpi_handle_err(ds->handle, "Failed to execute _DCK (0x%x)\n",
+				status);
 
 	kfree(buffer.pointer);
-	kfree(name_buffer.pointer);
 }
 
 static inline void dock(struct dock_station *ds)
@@ -525,9 +521,11 @@ static void dock_lock(struct dock_station *ds, int lock)
 	status = acpi_evaluate_object(ds->handle, "_LCK", &arg_list, NULL);
 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
 		if (lock)
-			printk(KERN_WARNING PREFIX "Locking device failed\n");
+			acpi_handle_warn(ds->handle,
+				"Locking device failed (0x%x)\n", status);
 		else
-			printk(KERN_WARNING PREFIX "Unlocking device failed\n");
+			acpi_handle_warn(ds->handle,
+				"Unlocking device failed (0x%x)\n", status);
 	}
 }
 
@@ -667,7 +665,7 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
 	dock_lock(ds, 0);
 	eject_dock(ds);
 	if (dock_present(ds)) {
-		printk(KERN_ERR PREFIX "Unable to undock!\n");
+		acpi_handle_err(ds->handle, "Unable to undock!\n");
 		return -EBUSY;
 	}
 	complete_undock(ds);
@@ -715,7 +713,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
 			begin_dock(ds);
 			dock(ds);
 			if (!dock_present(ds)) {
-				printk(KERN_ERR PREFIX "Unable to dock!\n");
+				acpi_handle_err(handle, "Unable to dock!\n");
 				complete_dock(ds);
 				break;
 			}
@@ -743,7 +741,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
 			dock_event(ds, event, UNDOCK_EVENT);
 		break;
 	default:
-		printk(KERN_ERR PREFIX "Unknown dock event %d\n", event);
+		acpi_handle_err(handle, "Unknown dock event %d\n", event);
 	}
 }
 
@@ -987,7 +985,7 @@ err_rmgroup:
 	sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group);
 err_unregister:
 	platform_device_unregister(dd);
-	printk(KERN_ERR "%s encountered error %d\n", __func__, ret);
+	acpi_handle_err(handle, "%s encountered error %d\n", __func__, ret);
 	return ret;
 }
 
@@ -1016,51 +1014,39 @@ static int dock_remove(struct dock_station *ds)
 }
 
 /**
- * find_dock - look for a dock station
+ * find_dock_and_bay - look for dock stations and bays
  * @handle: acpi handle of a device
  * @lvl: unused
- * @context: counter of dock stations found
+ * @context: unused
  * @rv: unused
  *
- * This is called by acpi_walk_namespace to look for dock stations.
+ * This is called by acpi_walk_namespace to look for dock stations and bays.
  */
 static __init acpi_status
-find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
+find_dock_and_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
-	if (is_dock(handle))
+	if (is_dock(handle) || is_ejectable_bay(handle))
 		dock_add(handle);
 
 	return AE_OK;
 }
 
-static __init acpi_status
-find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-	/* If bay is a dock, it's already handled */
-	if (is_ejectable_bay(handle) && !is_dock(handle))
-		dock_add(handle);
-	return AE_OK;
-}
-
 static int __init dock_init(void)
 {
 	if (acpi_disabled)
 		return 0;
 
-	/* look for a dock station */
+	/* look for dock stations and bays */
 	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-			    ACPI_UINT32_MAX, find_dock, NULL, NULL, NULL);
+		ACPI_UINT32_MAX, find_dock_and_bay, NULL, NULL, NULL);
 
-	/* look for bay */
-	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-			ACPI_UINT32_MAX, find_bay, NULL, NULL, NULL);
 	if (!dock_station_count) {
-		printk(KERN_INFO PREFIX "No dock devices found.\n");
+		pr_info(PREFIX "No dock devices found.\n");
 		return 0;
 	}
 
 	register_acpi_bus_notifier(&dock_acpi_notifier);
-	printk(KERN_INFO PREFIX "%s: %d docks/bays found\n",
+	pr_info(PREFIX "%s: %d docks/bays found\n",
 		ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
 	return 0;
 }
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index a51df96..354007d 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -158,10 +158,10 @@ static int ec_transaction_done(struct acpi_ec *ec)
 {
 	unsigned long flags;
 	int ret = 0;
-	spin_lock_irqsave(&ec->curr_lock, flags);
+	spin_lock_irqsave(&ec->lock, flags);
 	if (!ec->curr || ec->curr->done)
 		ret = 1;
-	spin_unlock_irqrestore(&ec->curr_lock, flags);
+	spin_unlock_irqrestore(&ec->lock, flags);
 	return ret;
 }
 
@@ -175,32 +175,38 @@ static void start_transaction(struct acpi_ec *ec)
 static void advance_transaction(struct acpi_ec *ec, u8 status)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&ec->curr_lock, flags);
-	if (!ec->curr)
+	struct transaction *t = ec->curr;
+
+	spin_lock_irqsave(&ec->lock, flags);
+	if (!t)
 		goto unlock;
-	if (ec->curr->wlen > ec->curr->wi) {
+	if (t->wlen > t->wi) {
 		if ((status & ACPI_EC_FLAG_IBF) == 0)
 			acpi_ec_write_data(ec,
-				ec->curr->wdata[ec->curr->wi++]);
+				t->wdata[t->wi++]);
 		else
 			goto err;
-	} else if (ec->curr->rlen > ec->curr->ri) {
+	} else if (t->rlen > t->ri) {
 		if ((status & ACPI_EC_FLAG_OBF) == 1) {
-			ec->curr->rdata[ec->curr->ri++] = acpi_ec_read_data(ec);
-			if (ec->curr->rlen == ec->curr->ri)
-				ec->curr->done = true;
+			t->rdata[t->ri++] = acpi_ec_read_data(ec);
+			if (t->rlen == t->ri)
+				t->done = true;
 		} else
 			goto err;
-	} else if (ec->curr->wlen == ec->curr->wi &&
+	} else if (t->wlen == t->wi &&
 		   (status & ACPI_EC_FLAG_IBF) == 0)
-		ec->curr->done = true;
+		t->done = true;
 	goto unlock;
 err:
-	/* false interrupt, state didn't change */
-	if (in_interrupt())
-		++ec->curr->irq_count;
+	/*
+	 * If SCI bit is set, then don't think it's a false IRQ
+	 * otherwise will take a not handled IRQ as a false one.
+	 */
+	if (in_interrupt() && !(status & ACPI_EC_FLAG_SCI))
+		++t->irq_count;
+
 unlock:
-	spin_unlock_irqrestore(&ec->curr_lock, flags);
+	spin_unlock_irqrestore(&ec->lock, flags);
 }
 
 static int acpi_ec_sync_query(struct acpi_ec *ec);
@@ -238,9 +244,9 @@ static int ec_poll(struct acpi_ec *ec)
 		if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)
 			break;
 		pr_debug(PREFIX "controller reset, restart transaction\n");
-		spin_lock_irqsave(&ec->curr_lock, flags);
+		spin_lock_irqsave(&ec->lock, flags);
 		start_transaction(ec);
-		spin_unlock_irqrestore(&ec->curr_lock, flags);
+		spin_unlock_irqrestore(&ec->lock, flags);
 	}
 	return -ETIME;
 }
@@ -253,17 +259,17 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
 	if (EC_FLAGS_MSI)
 		udelay(ACPI_EC_MSI_UDELAY);
 	/* start transaction */
-	spin_lock_irqsave(&ec->curr_lock, tmp);
+	spin_lock_irqsave(&ec->lock, tmp);
 	/* following two actions should be kept atomic */
 	ec->curr = t;
 	start_transaction(ec);
 	if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
 		clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
-	spin_unlock_irqrestore(&ec->curr_lock, tmp);
+	spin_unlock_irqrestore(&ec->lock, tmp);
 	ret = ec_poll(ec);
-	spin_lock_irqsave(&ec->curr_lock, tmp);
+	spin_lock_irqsave(&ec->lock, tmp);
 	ec->curr = NULL;
-	spin_unlock_irqrestore(&ec->curr_lock, tmp);
+	spin_unlock_irqrestore(&ec->lock, tmp);
 	return ret;
 }
 
@@ -292,7 +298,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
 		return -EINVAL;
 	if (t->rdata)
 		memset(t->rdata, 0, t->rlen);
-	mutex_lock(&ec->lock);
+	mutex_lock(&ec->mutex);
 	if (test_bit(EC_FLAGS_BLOCKED, &ec->flags)) {
 		status = -EINVAL;
 		goto unlock;
@@ -310,7 +316,8 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
 		status = -ETIME;
 		goto end;
 	}
-	pr_debug(PREFIX "transaction start\n");
+	pr_debug(PREFIX "transaction start (cmd=0x%02x, addr=0x%02x)\n",
+			t->command, t->wdata ? t->wdata[0] : 0);
 	/* disable GPE during transaction if storm is detected */
 	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
 		/* It has to be disabled, so that it doesn't trigger. */
@@ -326,8 +333,9 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
 		/* It is safe to enable the GPE outside of the transaction. */
 		acpi_enable_gpe(NULL, ec->gpe);
 	} else if (t->irq_count > ec_storm_threshold) {
-		pr_info(PREFIX "GPE storm detected, "
-			"transactions will use polling mode\n");
+		pr_info(PREFIX "GPE storm detected(%d GPEs), "
+			"transactions will use polling mode\n",
+			t->irq_count);
 		set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
 	}
 	pr_debug(PREFIX "transaction end\n");
@@ -335,7 +343,7 @@ end:
 	if (ec->global_lock)
 		acpi_release_global_lock(glk);
 unlock:
-	mutex_unlock(&ec->lock);
+	mutex_unlock(&ec->mutex);
 	return status;
 }
 
@@ -403,7 +411,7 @@ int ec_burst_disable(void)
 
 EXPORT_SYMBOL(ec_burst_disable);
 
-int ec_read(u8 addr, u8 * val)
+int ec_read(u8 addr, u8 *val)
 {
 	int err;
 	u8 temp_data;
@@ -468,10 +476,10 @@ void acpi_ec_block_transactions(void)
 	if (!ec)
 		return;
 
-	mutex_lock(&ec->lock);
+	mutex_lock(&ec->mutex);
 	/* Prevent transactions from being carried out */
 	set_bit(EC_FLAGS_BLOCKED, &ec->flags);
-	mutex_unlock(&ec->lock);
+	mutex_unlock(&ec->mutex);
 }
 
 void acpi_ec_unblock_transactions(void)
@@ -481,10 +489,10 @@ void acpi_ec_unblock_transactions(void)
 	if (!ec)
 		return;
 
-	mutex_lock(&ec->lock);
+	mutex_lock(&ec->mutex);
 	/* Allow transactions to be carried out again */
 	clear_bit(EC_FLAGS_BLOCKED, &ec->flags);
-	mutex_unlock(&ec->lock);
+	mutex_unlock(&ec->mutex);
 }
 
 void acpi_ec_unblock_transactions_early(void)
@@ -536,9 +544,9 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
 	handler->handle = handle;
 	handler->func = func;
 	handler->data = data;
-	mutex_lock(&ec->lock);
+	mutex_lock(&ec->mutex);
 	list_add(&handler->node, &ec->list);
-	mutex_unlock(&ec->lock);
+	mutex_unlock(&ec->mutex);
 	return 0;
 }
 
@@ -547,14 +555,14 @@ EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
 void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
 {
 	struct acpi_ec_query_handler *handler, *tmp;
-	mutex_lock(&ec->lock);
+	mutex_lock(&ec->mutex);
 	list_for_each_entry_safe(handler, tmp, &ec->list, node) {
 		if (query_bit == handler->query_bit) {
 			list_del(&handler->node);
 			kfree(handler);
 		}
 	}
-	mutex_unlock(&ec->lock);
+	mutex_unlock(&ec->mutex);
 }
 
 EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
@@ -601,9 +609,9 @@ static void acpi_ec_gpe_query(void *ec_cxt)
 	struct acpi_ec *ec = ec_cxt;
 	if (!ec)
 		return;
-	mutex_lock(&ec->lock);
+	mutex_lock(&ec->mutex);
 	acpi_ec_sync_query(ec);
-	mutex_unlock(&ec->lock);
+	mutex_unlock(&ec->mutex);
 }
 
 static int ec_check_sci(struct acpi_ec *ec, u8 state)
@@ -622,10 +630,11 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
 	u32 gpe_number, void *data)
 {
 	struct acpi_ec *ec = data;
+	u8 status = acpi_ec_read_status(ec);
 
-	pr_debug(PREFIX "~~~> interrupt\n");
+	pr_debug(PREFIX "~~~> interrupt, status:0x%02x\n", status);
 
-	advance_transaction(ec, acpi_ec_read_status(ec));
+	advance_transaction(ec, status);
 	if (ec_transaction_done(ec) &&
 	    (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) {
 		wake_up(&ec->wait);
@@ -691,10 +700,10 @@ static struct acpi_ec *make_acpi_ec(void)
 	if (!ec)
 		return NULL;
 	ec->flags = 1 << EC_FLAGS_QUERY_PENDING;
-	mutex_init(&ec->lock);
+	mutex_init(&ec->mutex);
 	init_waitqueue_head(&ec->wait);
 	INIT_LIST_HEAD(&ec->list);
-	spin_lock_init(&ec->curr_lock);
+	spin_lock_init(&ec->lock);
 	return ec;
 }
 
@@ -853,12 +862,12 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
 
 	ec = acpi_driver_data(device);
 	ec_remove_handlers(ec);
-	mutex_lock(&ec->lock);
+	mutex_lock(&ec->mutex);
 	list_for_each_entry_safe(handler, tmp, &ec->list, node) {
 		list_del(&handler->node);
 		kfree(handler);
 	}
-	mutex_unlock(&ec->lock);
+	mutex_unlock(&ec->mutex);
 	release_region(ec->data_addr, 1);
 	release_region(ec->command_addr, 1);
 	device->driver_data = NULL;
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 0837308..0155184 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -130,46 +130,59 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
 {
 	struct acpi_device *acpi_dev;
 	acpi_status status;
-	struct acpi_device_physical_node *physical_node;
+	struct acpi_device_physical_node *physical_node, *pn;
 	char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];
 	int retval = -EINVAL;
 
-	if (dev->archdata.acpi_handle) {
-		dev_warn(dev, "Drivers changed 'acpi_handle'\n");
-		return -EINVAL;
+	if (ACPI_HANDLE(dev)) {
+		if (handle) {
+			dev_warn(dev, "ACPI handle is already set\n");
+			return -EINVAL;
+		} else {
+			handle = ACPI_HANDLE(dev);
+		}
 	}
+	if (!handle)
+		return -EINVAL;
 
 	get_device(dev);
 	status = acpi_bus_get_device(handle, &acpi_dev);
 	if (ACPI_FAILURE(status))
 		goto err;
 
-	physical_node = kzalloc(sizeof(struct acpi_device_physical_node),
-		GFP_KERNEL);
+	physical_node = kzalloc(sizeof(*physical_node), GFP_KERNEL);
 	if (!physical_node) {
 		retval = -ENOMEM;
 		goto err;
 	}
 
 	mutex_lock(&acpi_dev->physical_node_lock);
+
+	/* Sanity check. */
+	list_for_each_entry(pn, &acpi_dev->physical_node_list, node)
+		if (pn->dev == dev) {
+			dev_warn(dev, "Already associated with ACPI node\n");
+			goto err_free;
+		}
+
 	/* allocate physical node id according to physical_node_id_bitmap */
 	physical_node->node_id =
 		find_first_zero_bit(acpi_dev->physical_node_id_bitmap,
 		ACPI_MAX_PHYSICAL_NODE);
 	if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) {
 		retval = -ENOSPC;
-		mutex_unlock(&acpi_dev->physical_node_lock);
-		kfree(physical_node);
-		goto err;
+		goto err_free;
 	}
 
 	set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap);
 	physical_node->dev = dev;
 	list_add_tail(&physical_node->node, &acpi_dev->physical_node_list);
 	acpi_dev->physical_node_count++;
+
 	mutex_unlock(&acpi_dev->physical_node_lock);
 
-	dev->archdata.acpi_handle = handle;
+	if (!ACPI_HANDLE(dev))
+		ACPI_HANDLE_SET(dev, acpi_dev->handle);
 
 	if (!physical_node->node_id)
 		strcpy(physical_node_name, PHYSICAL_NODE_STRING);
@@ -187,8 +200,14 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
 	return 0;
 
  err:
+	ACPI_HANDLE_SET(dev, NULL);
 	put_device(dev);
 	return retval;
+
+ err_free:
+	mutex_unlock(&acpi_dev->physical_node_lock);
+	kfree(physical_node);
+	goto err;
 }
 
 static int acpi_unbind_one(struct device *dev)
@@ -198,11 +217,10 @@ static int acpi_unbind_one(struct device *dev)
 	acpi_status status;
 	struct list_head *node, *next;
 
-	if (!dev->archdata.acpi_handle)
+	if (!ACPI_HANDLE(dev))
 		return 0;
 
-	status = acpi_bus_get_device(dev->archdata.acpi_handle,
-		&acpi_dev);
+	status = acpi_bus_get_device(ACPI_HANDLE(dev), &acpi_dev);
 	if (ACPI_FAILURE(status))
 		goto err;
 
@@ -228,7 +246,7 @@ static int acpi_unbind_one(struct device *dev)
 
 		sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name);
 		sysfs_remove_link(&dev->kobj, "firmware_node");
-		dev->archdata.acpi_handle = NULL;
+		ACPI_HANDLE_SET(dev, NULL);
 		/* acpi_bind_one increase refcnt by one */
 		put_device(dev);
 		kfree(entry);
@@ -248,6 +266,10 @@ static int acpi_platform_notify(struct device *dev)
 	acpi_handle handle;
 	int ret = -EINVAL;
 
+	ret = acpi_bind_one(dev, NULL);
+	if (!ret)
+		goto out;
+
 	if (!dev->bus || !dev->parent) {
 		/* bridge devices genernally haven't bus or parent */
 		ret = acpi_find_bridge_device(dev, &handle);
@@ -261,16 +283,16 @@ static int acpi_platform_notify(struct device *dev)
 	}
 	if ((ret = type->find_device(dev, &handle)) != 0)
 		DBG("Can't get handler for %s\n", dev_name(dev));
-      end:
+ end:
 	if (!ret)
 		acpi_bind_one(dev, handle);
 
+ out:
 #if ACPI_GLUE_DEBUG
 	if (!ret) {
 		struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 
-		acpi_get_name(dev->archdata.acpi_handle,
-			      ACPI_FULL_PATHNAME, &buffer);
+		acpi_get_name(dev->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
 		DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer);
 		kfree(buffer.pointer);
 	} else
diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c
index 20a0f2c..a0cc796 100644
--- a/drivers/acpi/hed.c
+++ b/drivers/acpi/hed.c
@@ -61,7 +61,7 @@ static void acpi_hed_notify(struct acpi_device *device, u32 event)
 	blocking_notifier_call_chain(&acpi_hed_notify_list, 0, NULL);
 }
 
-static int __devinit acpi_hed_add(struct acpi_device *device)
+static int acpi_hed_add(struct acpi_device *device)
 {
 	/* Only one hardware error device */
 	if (hed_handle)
@@ -70,7 +70,7 @@ static int __devinit acpi_hed_add(struct acpi_device *device)
 	return 0;
 }
 
-static int __devexit acpi_hed_remove(struct acpi_device *device, int type)
+static int acpi_hed_remove(struct acpi_device *device, int type)
 {
 	hed_handle = NULL;
 	return 0;
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index ca75b9c..3c407cd 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -58,11 +58,11 @@ struct acpi_ec {
 	unsigned long data_addr;
 	unsigned long global_lock;
 	unsigned long flags;
-	struct mutex lock;
+	struct mutex mutex;
 	wait_queue_head_t wait;
 	struct list_head list;
 	struct transaction *curr;
-	spinlock_t curr_lock;
+	spinlock_t lock;
 };
 
 extern struct acpi_ec *first_ec;
@@ -93,4 +93,11 @@ static inline int suspend_nvs_save(void) { return 0; }
 static inline void suspend_nvs_restore(void) {}
 #endif
 
+/*--------------------------------------------------------------------------
+				Platform bus support
+  -------------------------------------------------------------------------- */
+struct platform_device;
+
+struct platform_device *acpi_create_platform_device(struct acpi_device *adev);
+
 #endif /* _ACPI_INTERNAL_H_ */
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 9eaf708..3ff2678 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -534,6 +534,137 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
 	return AE_OK;
 }
 
+#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+#include <linux/earlycpio.h>
+#include <linux/memblock.h>
+
+static u64 acpi_tables_addr;
+static int all_tables_size;
+
+/* Copied from acpica/tbutils.c:acpi_tb_checksum() */
+u8 __init acpi_table_checksum(u8 *buffer, u32 length)
+{
+	u8 sum = 0;
+	u8 *end = buffer + length;
+
+	while (buffer < end)
+		sum = (u8) (sum + *(buffer++));
+	return sum;
+}
+
+/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */
+static const char * const table_sigs[] = {
+	ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ,
+	ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT,
+	ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF,
+	ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET,
+	ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI,
+	ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA,
+	ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT,
+	ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
+	ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };
+
+/* Non-fatal errors: Affected tables/files are ignored */
+#define INVALID_TABLE(x, path, name)					\
+	{ pr_err("ACPI OVERRIDE: " x " [%s%s]\n", path, name); continue; }
+
+#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
+
+/* Must not increase 10 or needs code modification below */
+#define ACPI_OVERRIDE_TABLES 10
+
+void __init acpi_initrd_override(void *data, size_t size)
+{
+	int sig, no, table_nr = 0, total_offset = 0;
+	long offset = 0;
+	struct acpi_table_header *table;
+	char cpio_path[32] = "kernel/firmware/acpi/";
+	struct cpio_data file;
+	struct cpio_data early_initrd_files[ACPI_OVERRIDE_TABLES];
+	char *p;
+
+	if (data == NULL || size == 0)
+		return;
+
+	for (no = 0; no < ACPI_OVERRIDE_TABLES; no++) {
+		file = find_cpio_data(cpio_path, data, size, &offset);
+		if (!file.data)
+			break;
+
+		data += offset;
+		size -= offset;
+
+		if (file.size < sizeof(struct acpi_table_header))
+			INVALID_TABLE("Table smaller than ACPI header",
+				      cpio_path, file.name);
+
+		table = file.data;
+
+		for (sig = 0; table_sigs[sig]; sig++)
+			if (!memcmp(table->signature, table_sigs[sig], 4))
+				break;
+
+		if (!table_sigs[sig])
+			INVALID_TABLE("Unknown signature",
+				      cpio_path, file.name);
+		if (file.size != table->length)
+			INVALID_TABLE("File length does not match table length",
+				      cpio_path, file.name);
+		if (acpi_table_checksum(file.data, table->length))
+			INVALID_TABLE("Bad table checksum",
+				      cpio_path, file.name);
+
+		pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n",
+			table->signature, cpio_path, file.name, table->length);
+
+		all_tables_size += table->length;
+		early_initrd_files[table_nr].data = file.data;
+		early_initrd_files[table_nr].size = file.size;
+		table_nr++;
+	}
+	if (table_nr == 0)
+		return;
+
+	acpi_tables_addr =
+		memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
+				       all_tables_size, PAGE_SIZE);
+	if (!acpi_tables_addr) {
+		WARN_ON(1);
+		return;
+	}
+	/*
+	 * Only calling e820_add_reserve does not work and the
+	 * tables are invalid (memory got used) later.
+	 * memblock_reserve works as expected and the tables won't get modified.
+	 * But it's not enough on X86 because ioremap will
+	 * complain later (used by acpi_os_map_memory) that the pages
+	 * that should get mapped are not marked "reserved".
+	 * Both memblock_reserve and e820_add_region (via arch_reserve_mem_area)
+	 * works fine.
+	 */
+	memblock_reserve(acpi_tables_addr, acpi_tables_addr + all_tables_size);
+	arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
+
+	p = early_ioremap(acpi_tables_addr, all_tables_size);
+
+	for (no = 0; no < table_nr; no++) {
+		memcpy(p + total_offset, early_initrd_files[no].data,
+		       early_initrd_files[no].size);
+		total_offset += early_initrd_files[no].size;
+	}
+	early_iounmap(p, all_tables_size);
+}
+#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */
+
+static void acpi_table_taint(struct acpi_table_header *table)
+{
+	pr_warn(PREFIX
+		"Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n",
+		table->signature, table->oem_table_id);
+	add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
+}
+
+
 acpi_status
 acpi_os_table_override(struct acpi_table_header * existing_table,
 		       struct acpi_table_header ** new_table)
@@ -547,24 +678,73 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
 	if (strncmp(existing_table->signature, "DSDT", 4) == 0)
 		*new_table = (struct acpi_table_header *)AmlCode;
 #endif
-	if (*new_table != NULL) {
-		printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], "
-			   "this is unsafe: tainting kernel\n",
-		       existing_table->signature,
-		       existing_table->oem_table_id);
-		add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
-	}
+	if (*new_table != NULL)
+		acpi_table_taint(existing_table);
 	return AE_OK;
 }
 
 acpi_status
 acpi_os_physical_table_override(struct acpi_table_header *existing_table,
-				acpi_physical_address * new_address,
-				u32 *new_table_length)
+				acpi_physical_address *address,
+				u32 *table_length)
 {
-	return AE_SUPPORT;
-}
+#ifndef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+	*table_length = 0;
+	*address = 0;
+	return AE_OK;
+#else
+	int table_offset = 0;
+	struct acpi_table_header *table;
+
+	*table_length = 0;
+	*address = 0;
+
+	if (!acpi_tables_addr)
+		return AE_OK;
+
+	do {
+		if (table_offset + ACPI_HEADER_SIZE > all_tables_size) {
+			WARN_ON(1);
+			return AE_OK;
+		}
+
+		table = acpi_os_map_memory(acpi_tables_addr + table_offset,
+					   ACPI_HEADER_SIZE);
+
+		if (table_offset + table->length > all_tables_size) {
+			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+			WARN_ON(1);
+			return AE_OK;
+		}
 
+		table_offset += table->length;
+
+		if (memcmp(existing_table->signature, table->signature, 4)) {
+			acpi_os_unmap_memory(table,
+				     ACPI_HEADER_SIZE);
+			continue;
+		}
+
+		/* Only override tables with matching oem id */
+		if (memcmp(table->oem_table_id, existing_table->oem_table_id,
+			   ACPI_OEM_TABLE_ID_SIZE)) {
+			acpi_os_unmap_memory(table,
+				     ACPI_HEADER_SIZE);
+			continue;
+		}
+
+		table_offset -= table->length;
+		*table_length = table->length;
+		acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+		*address = acpi_tables_addr + table_offset;
+		break;
+	} while (table_offset + ACPI_HEADER_SIZE < all_tables_size);
+
+	if (*address != 0)
+		acpi_table_taint(existing_table);
+	return AE_OK;
+#endif
+}
 
 static irqreturn_t acpi_irq(int irq, void *dev_id)
 {
@@ -932,7 +1112,7 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
 	 * having a static work_struct.
 	 */
 
-	dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC);
+	dpc = kzalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC);
 	if (!dpc)
 		return AE_NO_MEMORY;
 
@@ -944,17 +1124,22 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
 	 * because the hotplug code may call driver .remove() functions,
 	 * which invoke flush_scheduled_work/acpi_os_wait_events_complete
 	 * to flush these workqueues.
+	 *
+	 * To prevent lockdep from complaining unnecessarily, make sure that
+	 * there is a different static lockdep key for each workqueue by using
+	 * INIT_WORK() for each of them separately.
 	 */
-	queue = hp ? kacpi_hotplug_wq :
-		(type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq);
-	dpc->wait = hp ? 1 : 0;
-
-	if (queue == kacpi_hotplug_wq)
+	if (hp) {
+		queue = kacpi_hotplug_wq;
+		dpc->wait = 1;
 		INIT_WORK(&dpc->work, acpi_os_execute_deferred);
-	else if (queue == kacpi_notify_wq)
+	} else if (type == OSL_NOTIFY_HANDLER) {
+		queue = kacpi_notify_wq;
 		INIT_WORK(&dpc->work, acpi_os_execute_deferred);
-	else
+	} else {
+		queue = kacpid_wq;
 		INIT_WORK(&dpc->work, acpi_os_execute_deferred);
+	}
 
 	/*
 	 * On some machines, a software-initiated SMI causes corruption unless
@@ -986,6 +1171,7 @@ acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function,
 {
 	return __acpi_os_execute(0, function, context, 1);
 }
+EXPORT_SYMBOL(acpi_os_hotplug_execute);
 
 void acpi_os_wait_events_complete(void)
 {
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
index 2ef0409..a1dee29 100644
--- a/drivers/acpi/pci_bind.c
+++ b/drivers/acpi/pci_bind.c
@@ -45,11 +45,12 @@ static int acpi_pci_unbind(struct acpi_device *device)
 
 	device_set_run_wake(&dev->dev, false);
 	pci_acpi_remove_pm_notifier(device);
+	acpi_power_resource_unregister_device(&dev->dev, device->handle);
 
 	if (!dev->subordinate)
 		goto out;
 
-	acpi_pci_irq_del_prt(dev->subordinate);
+	acpi_pci_irq_del_prt(pci_domain_nr(dev->bus), dev->subordinate->number);
 
 	device->ops.bind = NULL;
 	device->ops.unbind = NULL;
@@ -63,7 +64,7 @@ static int acpi_pci_bind(struct acpi_device *device)
 {
 	acpi_status status;
 	acpi_handle handle;
-	struct pci_bus *bus;
+	unsigned char bus;
 	struct pci_dev *dev;
 
 	dev = acpi_get_pci_dev(device->handle);
@@ -71,6 +72,7 @@ static int acpi_pci_bind(struct acpi_device *device)
 		return 0;
 
 	pci_acpi_add_pm_notifier(device, dev);
+	acpi_power_resource_register_device(&dev->dev, device->handle);
 	if (device->wakeup.flags.run_wake)
 		device_set_run_wake(&dev->dev, true);
 
@@ -100,11 +102,11 @@ static int acpi_pci_bind(struct acpi_device *device)
 		goto out;
 
 	if (dev->subordinate)
-		bus = dev->subordinate;
+		bus = dev->subordinate->number;
 	else
-		bus = dev->bus;
+		bus = dev->bus->number;
 
-	acpi_pci_irq_add_prt(device->handle, bus);
+	acpi_pci_irq_add_prt(device->handle, pci_domain_nr(dev->bus), bus);
 
 out:
 	pci_dev_put(dev);
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 0eefa12..68a921d 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -184,7 +184,7 @@ static void do_prt_fixups(struct acpi_prt_entry *entry,
 	}
 }
 
-static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
+static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
 				  struct acpi_pci_routing_table *prt)
 {
 	struct acpi_prt_entry *entry;
@@ -198,8 +198,8 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
 	 * 1=INTA, 2=INTB.  We use the PCI encoding throughout, so convert
 	 * it here.
 	 */
-	entry->id.segment = pci_domain_nr(bus);
-	entry->id.bus = bus->number;
+	entry->id.segment = segment;
+	entry->id.bus = bus;
 	entry->id.device = (prt->address >> 16) & 0xFFFF;
 	entry->pin = prt->pin + 1;
 
@@ -244,7 +244,7 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
 	return 0;
 }
 
-int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
+int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
 {
 	acpi_status status;
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -273,7 +273,7 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
 
 	entry = buffer.pointer;
 	while (entry && (entry->length > 0)) {
-		acpi_pci_irq_add_entry(handle, bus, entry);
+		acpi_pci_irq_add_entry(handle, segment, bus, entry);
 		entry = (struct acpi_pci_routing_table *)
 		    ((unsigned long)entry + entry->length);
 	}
@@ -282,17 +282,16 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
 	return 0;
 }
 
-void acpi_pci_irq_del_prt(struct pci_bus *bus)
+void acpi_pci_irq_del_prt(int segment, int bus)
 {
 	struct acpi_prt_entry *entry, *tmp;
 
 	printk(KERN_DEBUG
 	       "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
-	       pci_domain_nr(bus), bus->number);
+	       segment, bus);
 	spin_lock(&acpi_prt_lock);
 	list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
-		if (pci_domain_nr(bus) == entry->id.segment
-			&& bus->number == entry->id.bus) {
+		if (segment == entry->id.segment && bus == entry->id.bus) {
 			list_del(&entry->list);
 			kfree(entry);
 		}
@@ -459,19 +458,19 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 	 */
 	if (gsi < 0) {
 		u32 dev_gsi;
-		dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin));
 		/* Interrupt Line values above 0xF are forbidden */
 		if (dev->irq > 0 && (dev->irq <= 0xF) &&
 		    (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) {
-			printk(" - using ISA IRQ %d\n", dev->irq);
+			dev_warn(&dev->dev, "PCI INT %c: no GSI - using ISA IRQ %d\n",
+				 pin_name(pin), dev->irq);
 			acpi_register_gsi(&dev->dev, dev_gsi,
 					  ACPI_LEVEL_SENSITIVE,
 					  ACPI_ACTIVE_LOW);
-			return 0;
 		} else {
-			printk("\n");
-			return 0;
+			dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
+				 pin_name(pin));
 		}
+		return 0;
 	}
 
 	rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
@@ -495,11 +494,6 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 	return 0;
 }
 
-/* FIXME: implement x86/x86_64 version */
-void __attribute__ ((weak)) acpi_unregister_gsi(u32 i)
-{
-}
-
 void acpi_pci_irq_disable(struct pci_dev *dev)
 {
 	struct acpi_prt_entry *entry;
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index bce469c..7928d4d 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -445,7 +445,7 @@ out:
 }
 EXPORT_SYMBOL(acpi_pci_osc_control_set);
 
-static int __devinit acpi_pci_root_add(struct acpi_device *device)
+static int acpi_pci_root_add(struct acpi_device *device)
 {
 	unsigned long long segment, bus;
 	acpi_status status;
@@ -454,6 +454,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
 	acpi_handle handle;
 	struct acpi_device *child;
 	u32 flags, base_flags;
+	bool is_osc_granted = false;
 
 	root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
 	if (!root)
@@ -501,85 +502,47 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
 	strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
 	device->driver_data = root;
 
-	root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
-
-	/*
-	 * All supported architectures that use ACPI have support for
-	 * PCI domains, so we indicate this in _OSC support capabilities.
-	 */
-	flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
-	acpi_pci_osc_support(root, flags);
-
-	/*
-	 * TBD: Need PCI interface for enumeration/configuration of roots.
-	 */
-
-	mutex_lock(&acpi_pci_root_lock);
-	list_add_tail(&root->node, &acpi_pci_roots);
-	mutex_unlock(&acpi_pci_root_lock);
-
 	printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
 	       acpi_device_name(device), acpi_device_bid(device),
 	       root->segment, &root->secondary);
 
 	/*
-	 * Scan the Root Bridge
-	 * --------------------
-	 * Must do this prior to any attempt to bind the root device, as the
-	 * PCI namespace does not get created until this call is made (and 
-	 * thus the root bridge's pci_dev does not exist).
-	 */
-	root->bus = pci_acpi_scan_root(root);
-	if (!root->bus) {
-		printk(KERN_ERR PREFIX
-			    "Bus %04x:%02x not present in PCI namespace\n",
-			    root->segment, (unsigned int)root->secondary.start);
-		result = -ENODEV;
-		goto out_del_root;
-	}
-
-	/*
-	 * Attach ACPI-PCI Context
-	 * -----------------------
-	 * Thus binding the ACPI and PCI devices.
-	 */
-	result = acpi_pci_bind_root(device);
-	if (result)
-		goto out_del_root;
-
-	/*
 	 * PCI Routing Table
 	 * -----------------
 	 * Evaluate and parse _PRT, if exists.
 	 */
 	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
 	if (ACPI_SUCCESS(status))
-		result = acpi_pci_irq_add_prt(device->handle, root->bus);
+		result = acpi_pci_irq_add_prt(device->handle, root->segment,
+					      root->secondary.start);
+
+	root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
 
 	/*
-	 * Scan and bind all _ADR-Based Devices
+	 * All supported architectures that use ACPI have support for
+	 * PCI domains, so we indicate this in _OSC support capabilities.
 	 */
-	list_for_each_entry(child, &device->children, node)
-		acpi_pci_bridge_scan(child);
+	flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
+	acpi_pci_osc_support(root, flags);
 
 	/* Indicate support for various _OSC capabilities. */
-	if (pci_ext_cfg_avail(root->bus->self))
+	if (pci_ext_cfg_avail())
 		flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
-	if (pcie_aspm_support_enabled())
+	if (pcie_aspm_support_enabled()) {
 		flags |= OSC_ACTIVE_STATE_PWR_SUPPORT |
-			OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
+		OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
+	}
 	if (pci_msi_enabled())
 		flags |= OSC_MSI_SUPPORT;
 	if (flags != base_flags) {
 		status = acpi_pci_osc_support(root, flags);
 		if (ACPI_FAILURE(status)) {
-			dev_info(root->bus->bridge, "ACPI _OSC support "
+			dev_info(&device->dev, "ACPI _OSC support "
 				"notification failed, disabling PCIe ASPM\n");
 			pcie_no_aspm();
 			flags = base_flags;
 		}
 	}
-
 	if (!pcie_ports_disabled
 	    && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) {
 		flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL
@@ -588,40 +551,81 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
 
 		if (pci_aer_available()) {
 			if (aer_acpi_firmware_first())
-				dev_dbg(root->bus->bridge,
+				dev_dbg(&device->dev,
 					"PCIe errors handled by BIOS.\n");
 			else
 				flags |= OSC_PCI_EXPRESS_AER_CONTROL;
 		}
 
-		dev_info(root->bus->bridge,
+		dev_info(&device->dev,
 			"Requesting ACPI _OSC control (0x%02x)\n", flags);
 
 		status = acpi_pci_osc_control_set(device->handle, &flags,
-					OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
+				       OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
 		if (ACPI_SUCCESS(status)) {
-			dev_info(root->bus->bridge,
+			is_osc_granted = true;
+			dev_info(&device->dev,
 				"ACPI _OSC control (0x%02x) granted\n", flags);
-			if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
-				/*
-				 * We have ASPM control, but the FADT indicates
-				 * that it's unsupported. Clear it.
-				 */
-				pcie_clear_aspm(root->bus);
-			}
 		} else {
-			dev_info(root->bus->bridge,
+			is_osc_granted = false;
+			dev_info(&device->dev,
 				"ACPI _OSC request failed (%s), "
 				"returned control mask: 0x%02x\n",
 				acpi_format_exception(status), flags);
-			pr_info("ACPI _OSC control for PCIe not granted, "
-				"disabling ASPM\n");
-			pcie_no_aspm();
 		}
 	} else {
-		dev_info(root->bus->bridge,
-			 "Unable to request _OSC control "
-			 "(_OSC support mask: 0x%02x)\n", flags);
+		dev_info(&device->dev,
+			"Unable to request _OSC control "
+			"(_OSC support mask: 0x%02x)\n", flags);
+	}
+
+	/*
+	 * TBD: Need PCI interface for enumeration/configuration of roots.
+	 */
+
+	mutex_lock(&acpi_pci_root_lock);
+	list_add_tail(&root->node, &acpi_pci_roots);
+	mutex_unlock(&acpi_pci_root_lock);
+
+	/*
+	 * Scan the Root Bridge
+	 * --------------------
+	 * Must do this prior to any attempt to bind the root device, as the
+	 * PCI namespace does not get created until this call is made (and 
+	 * thus the root bridge's pci_dev does not exist).
+	 */
+	root->bus = pci_acpi_scan_root(root);
+	if (!root->bus) {
+		printk(KERN_ERR PREFIX
+			    "Bus %04x:%02x not present in PCI namespace\n",
+			    root->segment, (unsigned int)root->secondary.start);
+		result = -ENODEV;
+		goto out_del_root;
+	}
+
+	/*
+	 * Attach ACPI-PCI Context
+	 * -----------------------
+	 * Thus binding the ACPI and PCI devices.
+	 */
+	result = acpi_pci_bind_root(device);
+	if (result)
+		goto out_del_root;
+
+	/*
+	 * Scan and bind all _ADR-Based Devices
+	 */
+	list_for_each_entry(child, &device->children, node)
+		acpi_pci_bridge_scan(child);
+
+	/* ASPM setting */
+	if (is_osc_granted) {
+		if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM)
+			pcie_clear_aspm(root->bus);
+	} else {
+		pr_info("ACPI _OSC control for PCIe not granted, "
+			"disabling ASPM\n");
+		pcie_no_aspm();
 	}
 
 	pci_acpi_add_bus_pm_notifier(device, root->bus);
@@ -634,6 +638,8 @@ out_del_root:
 	mutex_lock(&acpi_pci_root_lock);
 	list_del(&root->node);
 	mutex_unlock(&acpi_pci_root_lock);
+
+	acpi_pci_irq_del_prt(root->segment, root->secondary.start);
 end:
 	kfree(root);
 	return result;
@@ -644,12 +650,19 @@ static int acpi_pci_root_start(struct acpi_device *device)
 	struct acpi_pci_root *root = acpi_driver_data(device);
 	struct acpi_pci_driver *driver;
 
+	if (system_state != SYSTEM_BOOTING)
+		pci_assign_unassigned_bus_resources(root->bus);
+
 	mutex_lock(&acpi_pci_root_lock);
 	list_for_each_entry(driver, &acpi_pci_drivers, node)
 		if (driver->add)
 			driver->add(root);
 	mutex_unlock(&acpi_pci_root_lock);
 
+	/* need to after hot-added ioapic is registered */
+	if (system_state != SYSTEM_BOOTING)
+		pci_enable_bridges(root->bus);
+
 	pci_bus_add_devices(root->bus);
 
 	return 0;
@@ -657,17 +670,29 @@ static int acpi_pci_root_start(struct acpi_device *device)
 
 static int acpi_pci_root_remove(struct acpi_device *device, int type)
 {
+	acpi_status status;
+	acpi_handle handle;
 	struct acpi_pci_root *root = acpi_driver_data(device);
 	struct acpi_pci_driver *driver;
 
+	pci_stop_root_bus(root->bus);
+
 	mutex_lock(&acpi_pci_root_lock);
-	list_for_each_entry(driver, &acpi_pci_drivers, node)
+	list_for_each_entry_reverse(driver, &acpi_pci_drivers, node)
 		if (driver->remove)
 			driver->remove(root);
+	mutex_unlock(&acpi_pci_root_lock);
 
 	device_set_run_wake(root->bus->bridge, false);
 	pci_acpi_remove_bus_pm_notifier(device);
 
+	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
+	if (ACPI_SUCCESS(status))
+		acpi_pci_irq_del_prt(root->segment, root->secondary.start);
+
+	pci_remove_root_bus(root->bus);
+
+	mutex_lock(&acpi_pci_root_lock);
 	list_del(&root->node);
 	mutex_unlock(&acpi_pci_root_lock);
 	kfree(root);
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 40e38a0..7db61b8 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -473,7 +473,7 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle)
 	return ret;
 
 no_power_resource:
-	printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!");
+	printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!\n");
 	return -ENODEV;
 }
 EXPORT_SYMBOL_GPL(acpi_power_resource_register_device);
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c
index 27adb09..ef98796 100644
--- a/drivers/acpi/proc.c
+++ b/drivers/acpi/proc.c
@@ -362,16 +362,13 @@ acpi_system_write_wakeup_device(struct file *file,
 	struct list_head *node, *next;
 	char strbuf[5];
 	char str[5] = "";
-	unsigned int len = count;
 
-	if (len > 4)
-		len = 4;
-	if (len < 0)
-		return -EFAULT;
+	if (count > 4)
+		count = 4;
 
-	if (copy_from_user(strbuf, buffer, len))
+	if (copy_from_user(strbuf, buffer, count))
 		return -EFAULT;
-	strbuf[len] = '\0';
+	strbuf[count] = '\0';
 	sscanf(strbuf, "%s", str);
 
 	mutex_lock(&acpi_device_lock);
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index bd4e5dc..e83311b 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -44,6 +44,7 @@
 #include <linux/moduleparam.h>
 #include <linux/cpuidle.h>
 #include <linux/slab.h>
+#include <linux/acpi.h>
 
 #include <asm/io.h>
 #include <asm/cpu.h>
@@ -282,7 +283,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
 		/* Declared with "Processor" statement; match ProcessorID */
 		status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
 		if (ACPI_FAILURE(status)) {
-			printk(KERN_ERR PREFIX "Evaluating processor object\n");
+			dev_err(&device->dev,
+				"Failed to evaluate processor object (0x%x)\n",
+				status);
 			return -ENODEV;
 		}
 
@@ -301,8 +304,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
 		status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
 						NULL, &value);
 		if (ACPI_FAILURE(status)) {
-			printk(KERN_ERR PREFIX
-			    "Evaluating processor _UID [%#x]\n", status);
+			dev_err(&device->dev,
+				"Failed to evaluate processor _UID (0x%x)\n",
+				status);
 			return -ENODEV;
 		}
 		device_declaration = 1;
@@ -345,7 +349,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
 	if (!object.processor.pblk_address)
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
 	else if (object.processor.pblk_length != 6)
-		printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n",
+		dev_err(&device->dev, "Invalid PBLK length [%d]\n",
 			    object.processor.pblk_length);
 	else {
 		pr->throttling.address = object.processor.pblk_address;
@@ -430,8 +434,8 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
 		 * Initialize missing things
 		 */
 		if (pr->flags.need_hotplug_init) {
-			printk(KERN_INFO "Will online and init hotplugged "
-			       "CPU: %d\n", pr->id);
+			pr_info("Will online and init hotplugged CPU: %d\n",
+				pr->id);
 			WARN(acpi_processor_start(pr), "Failed to start CPU:"
 				" %d\n", pr->id);
 			pr->flags.need_hotplug_init = 0;
@@ -492,14 +496,16 @@ static __ref int acpi_processor_start(struct acpi_processor *pr)
 				   &pr->cdev->device.kobj,
 				   "thermal_cooling");
 	if (result) {
-		printk(KERN_ERR PREFIX "Create sysfs link\n");
+		dev_err(&device->dev,
+			"Failed to create sysfs link 'thermal_cooling'\n");
 		goto err_thermal_unregister;
 	}
 	result = sysfs_create_link(&pr->cdev->device.kobj,
 				   &device->dev.kobj,
 				   "device");
 	if (result) {
-		printk(KERN_ERR PREFIX "Create sysfs link\n");
+		dev_err(&pr->cdev->device,
+			"Failed to create sysfs link 'device'\n");
 		goto err_remove_sysfs_thermal;
 	}
 
@@ -561,8 +567,9 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
 	 */
 	if (per_cpu(processor_device_array, pr->id) != NULL &&
 	    per_cpu(processor_device_array, pr->id) != device) {
-		printk(KERN_WARNING "BIOS reported wrong ACPI id "
-			"for the processor\n");
+		dev_warn(&device->dev,
+			"BIOS reported wrong ACPI id %d for the processor\n",
+			pr->id);
 		result = -ENODEV;
 		goto err_free_cpumask;
 	}
@@ -695,8 +702,8 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
 static void acpi_processor_hotplug_notify(acpi_handle handle,
 					  u32 event, void *data)
 {
-	struct acpi_processor *pr;
 	struct acpi_device *device = NULL;
+	struct acpi_eject_event *ej_event = NULL;
 	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
 	int result;
 
@@ -716,7 +723,7 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
 
 		result = acpi_processor_device_add(handle, &device);
 		if (result) {
-			printk(KERN_ERR PREFIX "Unable to add the device\n");
+			acpi_handle_err(handle, "Unable to add the device\n");
 			break;
 		}
 
@@ -728,20 +735,29 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
 				  "received ACPI_NOTIFY_EJECT_REQUEST\n"));
 
 		if (acpi_bus_get_device(handle, &device)) {
-			printk(KERN_ERR PREFIX
-				    "Device don't exist, dropping EJECT\n");
+			acpi_handle_err(handle,
+				"Device don't exist, dropping EJECT\n");
 			break;
 		}
-		pr = acpi_driver_data(device);
-		if (!pr) {
-			printk(KERN_ERR PREFIX
-				    "Driver data is NULL, dropping EJECT\n");
+		if (!acpi_driver_data(device)) {
+			acpi_handle_err(handle,
+				"Driver data is NULL, dropping EJECT\n");
 			break;
 		}
 
-		/* REVISIT: update when eject is supported */
-		ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-		break;
+		ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
+		if (!ej_event) {
+			acpi_handle_err(handle, "No memory, dropping EJECT\n");
+			break;
+		}
+
+		ej_event->handle = handle;
+		ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
+		acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
+					(void *)ej_event);
+
+		/* eject is performed asynchronously */
+		return;
 
 	default:
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -841,7 +857,7 @@ static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr)
 	 * and do it when the CPU gets online the first time
 	 * TBD: Cleanup above functions and try to do this more elegant.
 	 */
-	printk(KERN_INFO "CPU %d got hotplugged\n", pr->id);
+	pr_info("CPU %d got hotplugged\n", pr->id);
 	pr->flags.need_hotplug_init = 1;
 
 	return AE_OK;
@@ -852,8 +868,22 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr)
 	if (cpu_online(pr->id))
 		cpu_down(pr->id);
 
+	get_online_cpus();
+	/*
+	 * The cpu might become online again at this point. So we check whether
+	 * the cpu has been onlined or not. If the cpu became online, it means
+	 * that someone wants to use the cpu. So acpi_processor_handle_eject()
+	 * returns -EAGAIN.
+	 */
+	if (unlikely(cpu_online(pr->id))) {
+		put_online_cpus();
+		pr_warn("Failed to remove CPU %d, because other task "
+			"brought the CPU back online\n", pr->id);
+		return -EAGAIN;
+	}
 	arch_unregister_cpu(pr->id);
 	acpi_unmap_lsapic(pr->id);
+	put_online_cpus();
 	return (0);
 }
 #else
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index e8086c7..f1a5da4 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -735,31 +735,18 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
 static int acpi_idle_enter_c1(struct cpuidle_device *dev,
 		struct cpuidle_driver *drv, int index)
 {
-	ktime_t  kt1, kt2;
-	s64 idle_time;
 	struct acpi_processor *pr;
 	struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
 	struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
 
 	pr = __this_cpu_read(processors);
-	dev->last_residency = 0;
 
 	if (unlikely(!pr))
 		return -EINVAL;
 
-	local_irq_disable();
-
-
 	lapic_timer_state_broadcast(pr, cx, 1);
-	kt1 = ktime_get_real();
 	acpi_idle_do_entry(cx);
-	kt2 = ktime_get_real();
-	idle_time =  ktime_to_us(ktime_sub(kt2, kt1));
-
-	/* Update device last_residency*/
-	dev->last_residency = (int)idle_time;
 
-	local_irq_enable();
 	lapic_timer_state_broadcast(pr, cx, 0);
 
 	return index;
@@ -806,19 +793,12 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
 	struct acpi_processor *pr;
 	struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
 	struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
-	ktime_t  kt1, kt2;
-	s64 idle_time_ns;
-	s64 idle_time;
 
 	pr = __this_cpu_read(processors);
-	dev->last_residency = 0;
 
 	if (unlikely(!pr))
 		return -EINVAL;
 
-	local_irq_disable();
-
-
 	if (cx->entry_method != ACPI_CSTATE_FFH) {
 		current_thread_info()->status &= ~TS_POLLING;
 		/*
@@ -829,7 +809,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
 
 		if (unlikely(need_resched())) {
 			current_thread_info()->status |= TS_POLLING;
-			local_irq_enable();
 			return -EINVAL;
 		}
 	}
@@ -843,22 +822,12 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
 	if (cx->type == ACPI_STATE_C3)
 		ACPI_FLUSH_CPU_CACHE();
 
-	kt1 = ktime_get_real();
 	/* Tell the scheduler that we are going deep-idle: */
 	sched_clock_idle_sleep_event();
 	acpi_idle_do_entry(cx);
-	kt2 = ktime_get_real();
-	idle_time_ns = ktime_to_ns(ktime_sub(kt2, kt1));
-	idle_time = idle_time_ns;
-	do_div(idle_time, NSEC_PER_USEC);
 
-	/* Update device last_residency*/
-	dev->last_residency = (int)idle_time;
+	sched_clock_idle_wakeup_event(0);
 
-	/* Tell the scheduler how much we idled: */
-	sched_clock_idle_wakeup_event(idle_time_ns);
-
-	local_irq_enable();
 	if (cx->entry_method != ACPI_CSTATE_FFH)
 		current_thread_info()->status |= TS_POLLING;
 
@@ -883,13 +852,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
 	struct acpi_processor *pr;
 	struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
 	struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
-	ktime_t  kt1, kt2;
-	s64 idle_time_ns;
-	s64 idle_time;
-
 
 	pr = __this_cpu_read(processors);
-	dev->last_residency = 0;
 
 	if (unlikely(!pr))
 		return -EINVAL;
@@ -899,16 +863,11 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
 			return drv->states[drv->safe_state_index].enter(dev,
 						drv, drv->safe_state_index);
 		} else {
-			local_irq_disable();
 			acpi_safe_halt();
-			local_irq_enable();
 			return -EBUSY;
 		}
 	}
 
-	local_irq_disable();
-
-
 	if (cx->entry_method != ACPI_CSTATE_FFH) {
 		current_thread_info()->status &= ~TS_POLLING;
 		/*
@@ -919,7 +878,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
 
 		if (unlikely(need_resched())) {
 			current_thread_info()->status |= TS_POLLING;
-			local_irq_enable();
 			return -EINVAL;
 		}
 	}
@@ -934,7 +892,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
 	 */
 	lapic_timer_state_broadcast(pr, cx, 1);
 
-	kt1 = ktime_get_real();
 	/*
 	 * disable bus master
 	 * bm_check implies we need ARB_DIS
@@ -965,18 +922,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
 		c3_cpu_count--;
 		raw_spin_unlock(&c3_lock);
 	}
-	kt2 = ktime_get_real();
-	idle_time_ns = ktime_to_ns(ktime_sub(kt2, kt1));
-	idle_time = idle_time_ns;
-	do_div(idle_time, NSEC_PER_USEC);
-
-	/* Update device last_residency*/
-	dev->last_residency = (int)idle_time;
 
-	/* Tell the scheduler how much we idled: */
-	sched_clock_idle_wakeup_event(idle_time_ns);
+	sched_clock_idle_wakeup_event(0);
 
-	local_irq_enable();
 	if (cx->entry_method != ACPI_CSTATE_FFH)
 		current_thread_info()->status |= TS_POLLING;
 
@@ -987,6 +935,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
 struct cpuidle_driver acpi_idle_driver = {
 	.name =		"acpi_idle",
 	.owner =	THIS_MODULE,
+	.en_core_tk_irqen = 1,
 };
 
 /**
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
new file mode 100644
index 0000000..a3868f6
--- /dev/null
+++ b/drivers/acpi/resource.c
@@ -0,0 +1,526 @@
+/*
+ * drivers/acpi/resource.c - ACPI device resources interpretation.
+ *
+ * Copyright (C) 2012, Intel Corp.
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_X86
+#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
+#else
+#define valid_IRQ(i) (true)
+#endif
+
+static unsigned long acpi_dev_memresource_flags(u64 len, u8 write_protect,
+						bool window)
+{
+	unsigned long flags = IORESOURCE_MEM;
+
+	if (len == 0)
+		flags |= IORESOURCE_DISABLED;
+
+	if (write_protect == ACPI_READ_WRITE_MEMORY)
+		flags |= IORESOURCE_MEM_WRITEABLE;
+
+	if (window)
+		flags |= IORESOURCE_WINDOW;
+
+	return flags;
+}
+
+static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
+				     u8 write_protect)
+{
+	res->start = start;
+	res->end = start + len - 1;
+	res->flags = acpi_dev_memresource_flags(len, write_protect, false);
+}
+
+/**
+ * acpi_dev_resource_memory - Extract ACPI memory resource information.
+ * @ares: Input ACPI resource object.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents a memory resource and
+ * if that's the case, use the information in it to populate the generic
+ * resource object pointed to by @res.
+ */
+bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
+{
+	struct acpi_resource_memory24 *memory24;
+	struct acpi_resource_memory32 *memory32;
+	struct acpi_resource_fixed_memory32 *fixed_memory32;
+
+	switch (ares->type) {
+	case ACPI_RESOURCE_TYPE_MEMORY24:
+		memory24 = &ares->data.memory24;
+		acpi_dev_get_memresource(res, memory24->minimum,
+					 memory24->address_length,
+					 memory24->write_protect);
+		break;
+	case ACPI_RESOURCE_TYPE_MEMORY32:
+		memory32 = &ares->data.memory32;
+		acpi_dev_get_memresource(res, memory32->minimum,
+					 memory32->address_length,
+					 memory32->write_protect);
+		break;
+	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+		fixed_memory32 = &ares->data.fixed_memory32;
+		acpi_dev_get_memresource(res, fixed_memory32->address,
+					 fixed_memory32->address_length,
+					 fixed_memory32->write_protect);
+		break;
+	default:
+		return false;
+	}
+	return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);
+
+static unsigned int acpi_dev_ioresource_flags(u64 start, u64 end, u8 io_decode,
+					      bool window)
+{
+	int flags = IORESOURCE_IO;
+
+	if (io_decode == ACPI_DECODE_16)
+		flags |= IORESOURCE_IO_16BIT_ADDR;
+
+	if (start > end || end >= 0x10003)
+		flags |= IORESOURCE_DISABLED;
+
+	if (window)
+		flags |= IORESOURCE_WINDOW;
+
+	return flags;
+}
+
+static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
+				    u8 io_decode)
+{
+	u64 end = start + len - 1;
+
+	res->start = start;
+	res->end = end;
+	res->flags = acpi_dev_ioresource_flags(start, end, io_decode, false);
+}
+
+/**
+ * acpi_dev_resource_io - Extract ACPI I/O resource information.
+ * @ares: Input ACPI resource object.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents an I/O resource and
+ * if that's the case, use the information in it to populate the generic
+ * resource object pointed to by @res.
+ */
+bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
+{
+	struct acpi_resource_io *io;
+	struct acpi_resource_fixed_io *fixed_io;
+
+	switch (ares->type) {
+	case ACPI_RESOURCE_TYPE_IO:
+		io = &ares->data.io;
+		acpi_dev_get_ioresource(res, io->minimum,
+					io->address_length,
+					io->io_decode);
+		break;
+	case ACPI_RESOURCE_TYPE_FIXED_IO:
+		fixed_io = &ares->data.fixed_io;
+		acpi_dev_get_ioresource(res, fixed_io->address,
+					fixed_io->address_length,
+					ACPI_DECODE_10);
+		break;
+	default:
+		return false;
+	}
+	return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_io);
+
+/**
+ * acpi_dev_resource_address_space - Extract ACPI address space information.
+ * @ares: Input ACPI resource object.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents an address space resource
+ * and if that's the case, use the information in it to populate the generic
+ * resource object pointed to by @res.
+ */
+bool acpi_dev_resource_address_space(struct acpi_resource *ares,
+				     struct resource *res)
+{
+	acpi_status status;
+	struct acpi_resource_address64 addr;
+	bool window;
+	u64 len;
+	u8 io_decode;
+
+	switch (ares->type) {
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+		break;
+	default:
+		return false;
+	}
+
+	status = acpi_resource_to_address64(ares, &addr);
+	if (ACPI_FAILURE(status))
+		return true;
+
+	res->start = addr.minimum;
+	res->end = addr.maximum;
+	window = addr.producer_consumer == ACPI_PRODUCER;
+
+	switch(addr.resource_type) {
+	case ACPI_MEMORY_RANGE:
+		len = addr.maximum - addr.minimum + 1;
+		res->flags = acpi_dev_memresource_flags(len,
+						addr.info.mem.write_protect,
+						window);
+		break;
+	case ACPI_IO_RANGE:
+		io_decode = addr.granularity == 0xfff ?
+				ACPI_DECODE_10 : ACPI_DECODE_16;
+		res->flags = acpi_dev_ioresource_flags(addr.minimum,
+						       addr.maximum,
+						       io_decode, window);
+		break;
+	case ACPI_BUS_NUMBER_RANGE:
+		res->flags = IORESOURCE_BUS;
+		break;
+	default:
+		res->flags = 0;
+	}
+
+	return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space);
+
+/**
+ * acpi_dev_resource_ext_address_space - Extract ACPI address space information.
+ * @ares: Input ACPI resource object.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents an extended address space
+ * resource and if that's the case, use the information in it to populate the
+ * generic resource object pointed to by @res.
+ */
+bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
+					 struct resource *res)
+{
+	struct acpi_resource_extended_address64 *ext_addr;
+	bool window;
+	u64 len;
+	u8 io_decode;
+
+	if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64)
+		return false;
+
+	ext_addr = &ares->data.ext_address64;
+
+	res->start = ext_addr->minimum;
+	res->end = ext_addr->maximum;
+	window = ext_addr->producer_consumer == ACPI_PRODUCER;
+
+	switch(ext_addr->resource_type) {
+	case ACPI_MEMORY_RANGE:
+		len = ext_addr->maximum - ext_addr->minimum + 1;
+		res->flags = acpi_dev_memresource_flags(len,
+					ext_addr->info.mem.write_protect,
+					window);
+		break;
+	case ACPI_IO_RANGE:
+		io_decode = ext_addr->granularity == 0xfff ?
+				ACPI_DECODE_10 : ACPI_DECODE_16;
+		res->flags = acpi_dev_ioresource_flags(ext_addr->minimum,
+						       ext_addr->maximum,
+						       io_decode, window);
+		break;
+	case ACPI_BUS_NUMBER_RANGE:
+		res->flags = IORESOURCE_BUS;
+		break;
+	default:
+		res->flags = 0;
+	}
+
+	return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space);
+
+/**
+ * acpi_dev_irq_flags - Determine IRQ resource flags.
+ * @triggering: Triggering type as provided by ACPI.
+ * @polarity: Interrupt polarity as provided by ACPI.
+ * @shareable: Whether or not the interrupt is shareable.
+ */
+unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable)
+{
+	unsigned long flags;
+
+	if (triggering == ACPI_LEVEL_SENSITIVE)
+		flags = polarity == ACPI_ACTIVE_LOW ?
+			IORESOURCE_IRQ_LOWLEVEL : IORESOURCE_IRQ_HIGHLEVEL;
+	else
+		flags = polarity == ACPI_ACTIVE_LOW ?
+			IORESOURCE_IRQ_LOWEDGE : IORESOURCE_IRQ_HIGHEDGE;
+
+	if (shareable == ACPI_SHARED)
+		flags |= IORESOURCE_IRQ_SHAREABLE;
+
+	return flags | IORESOURCE_IRQ;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_irq_flags);
+
+static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi)
+{
+	res->start = gsi;
+	res->end = gsi;
+	res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED;
+}
+
+static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
+				     u8 triggering, u8 polarity, u8 shareable)
+{
+	int irq, p, t;
+
+	if (!valid_IRQ(gsi)) {
+		acpi_dev_irqresource_disabled(res, gsi);
+		return;
+	}
+
+	/*
+	 * In IO-APIC mode, use overrided attribute. Two reasons:
+	 * 1. BIOS bug in DSDT
+	 * 2. BIOS uses IO-APIC mode Interrupt Source Override
+	 */
+	if (!acpi_get_override_irq(gsi, &t, &p)) {
+		u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
+		u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
+
+		if (triggering != trig || polarity != pol) {
+			pr_warning("ACPI: IRQ %d override to %s, %s\n", gsi,
+				   t ? "edge" : "level", p ? "low" : "high");
+			triggering = trig;
+			polarity = pol;
+		}
+	}
+
+	res->flags = acpi_dev_irq_flags(triggering, polarity, shareable);
+	irq = acpi_register_gsi(NULL, gsi, triggering, polarity);
+	if (irq >= 0) {
+		res->start = irq;
+		res->end = irq;
+	} else {
+		acpi_dev_irqresource_disabled(res, gsi);
+	}
+}
+
+/**
+ * acpi_dev_resource_interrupt - Extract ACPI interrupt resource information.
+ * @ares: Input ACPI resource object.
+ * @index: Index into the array of GSIs represented by the resource.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents an interrupt resource
+ * and @index does not exceed the resource's interrupt count (true is returned
+ * in that case regardless of the results of the other checks)).  If that's the
+ * case, register the GSI corresponding to @index from the array of interrupts
+ * represented by the resource and populate the generic resource object pointed
+ * to by @res accordingly.  If the registration of the GSI is not successful,
+ * IORESOURCE_DISABLED will be set it that object's flags.
+ */
+bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
+				 struct resource *res)
+{
+	struct acpi_resource_irq *irq;
+	struct acpi_resource_extended_irq *ext_irq;
+
+	switch (ares->type) {
+	case ACPI_RESOURCE_TYPE_IRQ:
+		/*
+		 * Per spec, only one interrupt per descriptor is allowed in
+		 * _CRS, but some firmware violates this, so parse them all.
+		 */
+		irq = &ares->data.irq;
+		if (index >= irq->interrupt_count) {
+			acpi_dev_irqresource_disabled(res, 0);
+			return false;
+		}
+		acpi_dev_get_irqresource(res, irq->interrupts[index],
+					 irq->triggering, irq->polarity,
+					 irq->sharable);
+		break;
+	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+		ext_irq = &ares->data.extended_irq;
+		if (index >= ext_irq->interrupt_count) {
+			acpi_dev_irqresource_disabled(res, 0);
+			return false;
+		}
+		acpi_dev_get_irqresource(res, ext_irq->interrupts[index],
+					 ext_irq->triggering, ext_irq->polarity,
+					 ext_irq->sharable);
+		break;
+	default:
+		return false;
+	}
+
+	return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt);
+
+/**
+ * acpi_dev_free_resource_list - Free resource from %acpi_dev_get_resources().
+ * @list: The head of the resource list to free.
+ */
+void acpi_dev_free_resource_list(struct list_head *list)
+{
+	struct resource_list_entry *rentry, *re;
+
+	list_for_each_entry_safe(rentry, re, list, node) {
+		list_del(&rentry->node);
+		kfree(rentry);
+	}
+}
+EXPORT_SYMBOL_GPL(acpi_dev_free_resource_list);
+
+struct res_proc_context {
+	struct list_head *list;
+	int (*preproc)(struct acpi_resource *, void *);
+	void *preproc_data;
+	int count;
+	int error;
+};
+
+static acpi_status acpi_dev_new_resource_entry(struct resource *r,
+					       struct res_proc_context *c)
+{
+	struct resource_list_entry *rentry;
+
+	rentry = kmalloc(sizeof(*rentry), GFP_KERNEL);
+	if (!rentry) {
+		c->error = -ENOMEM;
+		return AE_NO_MEMORY;
+	}
+	rentry->res = *r;
+	list_add_tail(&rentry->node, c->list);
+	c->count++;
+	return AE_OK;
+}
+
+static acpi_status acpi_dev_process_resource(struct acpi_resource *ares,
+					     void *context)
+{
+	struct res_proc_context *c = context;
+	struct resource r;
+	int i;
+
+	if (c->preproc) {
+		int ret;
+
+		ret = c->preproc(ares, c->preproc_data);
+		if (ret < 0) {
+			c->error = ret;
+			return AE_CTRL_TERMINATE;
+		} else if (ret > 0) {
+			return AE_OK;
+		}
+	}
+
+	memset(&r, 0, sizeof(r));
+
+	if (acpi_dev_resource_memory(ares, &r)
+	    || acpi_dev_resource_io(ares, &r)
+	    || acpi_dev_resource_address_space(ares, &r)
+	    || acpi_dev_resource_ext_address_space(ares, &r))
+		return acpi_dev_new_resource_entry(&r, c);
+
+	for (i = 0; acpi_dev_resource_interrupt(ares, i, &r); i++) {
+		acpi_status status;
+
+		status = acpi_dev_new_resource_entry(&r, c);
+		if (ACPI_FAILURE(status))
+			return status;
+	}
+
+	return AE_OK;
+}
+
+/**
+ * acpi_dev_get_resources - Get current resources of a device.
+ * @adev: ACPI device node to get the resources for.
+ * @list: Head of the resultant list of resources (must be empty).
+ * @preproc: The caller's preprocessing routine.
+ * @preproc_data: Pointer passed to the caller's preprocessing routine.
+ *
+ * Evaluate the _CRS method for the given device node and process its output by
+ * (1) executing the @preproc() rountine provided by the caller, passing the
+ * resource pointer and @preproc_data to it as arguments, for each ACPI resource
+ * returned and (2) converting all of the returned ACPI resources into struct
+ * resource objects if possible.  If the return value of @preproc() in step (1)
+ * is different from 0, step (2) is not applied to the given ACPI resource and
+ * if that value is negative, the whole processing is aborted and that value is
+ * returned as the final error code.
+ *
+ * The resultant struct resource objects are put on the list pointed to by
+ * @list, that must be empty initially, as members of struct resource_list_entry
+ * objects.  Callers of this routine should use %acpi_dev_free_resource_list() to
+ * free that list.
+ *
+ * The number of resources in the output list is returned on success, an error
+ * code reflecting the error condition is returned otherwise.
+ */
+int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
+			   int (*preproc)(struct acpi_resource *, void *),
+			   void *preproc_data)
+{
+	struct res_proc_context c;
+	acpi_handle not_used;
+	acpi_status status;
+
+	if (!adev || !adev->handle || !list_empty(list))
+		return -EINVAL;
+
+	status = acpi_get_handle(adev->handle, METHOD_NAME__CRS, &not_used);
+	if (ACPI_FAILURE(status))
+		return 0;
+
+	c.list = list;
+	c.preproc = preproc;
+	c.preproc_data = preproc_data;
+	c.count = 0;
+	c.error = 0;
+	status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS,
+				     acpi_dev_process_resource, &c);
+	if (ACPI_FAILURE(status)) {
+		acpi_dev_free_resource_list(list);
+		return c.error ? c.error : -EIO;
+	}
+
+	return c.count;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_get_resources);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 1fcb867..67a7fa6 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -29,6 +29,17 @@ extern struct acpi_device *acpi_root;
 
 static const char *dummy_hid = "device";
 
+/*
+ * The following ACPI IDs are known to be suitable for representing as
+ * platform devices.
+ */
+static const struct acpi_device_id acpi_platform_device_ids[] = {
+
+	{ "PNP0D40" },
+
+	{ }
+};
+
 static LIST_HEAD(acpi_device_list);
 static LIST_HEAD(acpi_bus_id_list);
 DEFINE_MUTEX(acpi_device_lock);
@@ -97,6 +108,7 @@ void acpi_bus_hot_remove_device(void *context)
 	struct acpi_eject_event *ej_event = (struct acpi_eject_event *) context;
 	struct acpi_device *device;
 	acpi_handle handle = ej_event->handle;
+	acpi_handle temp;
 	struct acpi_object_list arg_list;
 	union acpi_object arg;
 	acpi_status status = AE_OK;
@@ -117,13 +129,16 @@ void acpi_bus_hot_remove_device(void *context)
 		goto err_out;
 	}
 
+	/* device has been freed */
+	device = NULL;
+
 	/* power off device */
 	status = acpi_evaluate_object(handle, "_PS3", NULL, NULL);
 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
 		printk(KERN_WARNING PREFIX
 				"Power-off device failed\n");
 
-	if (device->flags.lockable) {
+	if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) {
 		arg_list.count = 1;
 		arg_list.pointer = &arg;
 		arg.type = ACPI_TYPE_INTEGER;
@@ -157,6 +172,7 @@ err_out:
 	kfree(context);
 	return;
 }
+EXPORT_SYMBOL(acpi_bus_hot_remove_device);
 
 static ssize_t
 acpi_eject_store(struct device *d, struct device_attribute *attr,
@@ -216,6 +232,25 @@ acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *bu
 }
 static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
 
+static ssize_t acpi_device_uid_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+	return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
+}
+static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL);
+
+static ssize_t acpi_device_adr_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+	return sprintf(buf, "0x%08x\n",
+		       (unsigned int)(acpi_dev->pnp.bus_address));
+}
+static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL);
+
 static ssize_t
 acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) {
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
@@ -259,11 +294,21 @@ static ssize_t description_show(struct device *dev,
 }
 static DEVICE_ATTR(description, 0444, description_show, NULL);
 
+static ssize_t
+acpi_device_sun_show(struct device *dev, struct device_attribute *attr,
+		     char *buf) {
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+	return sprintf(buf, "%lu\n", acpi_dev->pnp.sun);
+}
+static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);
+
 static int acpi_device_setup_files(struct acpi_device *dev)
 {
 	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
 	acpi_status status;
 	acpi_handle temp;
+	unsigned long long sun;
 	int result = 0;
 
 	/*
@@ -300,6 +345,21 @@ static int acpi_device_setup_files(struct acpi_device *dev)
 			goto end;
 	}
 
+	if (dev->flags.bus_address)
+		result = device_create_file(&dev->dev, &dev_attr_adr);
+	if (dev->pnp.unique_id)
+		result = device_create_file(&dev->dev, &dev_attr_uid);
+
+	status = acpi_evaluate_integer(dev->handle, "_SUN", NULL, &sun);
+	if (ACPI_SUCCESS(status)) {
+		dev->pnp.sun = (unsigned long)sun;
+		result = device_create_file(&dev->dev, &dev_attr_sun);
+		if (result)
+			goto end;
+	} else {
+		dev->pnp.sun = (unsigned long)-1;
+	}
+
         /*
          * If device has _EJ0, 'eject' file is created that is used to trigger
          * hot-removal function from userland.
@@ -331,6 +391,14 @@ static void acpi_device_remove_files(struct acpi_device *dev)
 	if (ACPI_SUCCESS(status))
 		device_remove_file(&dev->dev, &dev_attr_eject);
 
+	status = acpi_get_handle(dev->handle, "_SUN", &temp);
+	if (ACPI_SUCCESS(status))
+		device_remove_file(&dev->dev, &dev_attr_sun);
+
+	if (dev->pnp.unique_id)
+		device_remove_file(&dev->dev, &dev_attr_uid);
+	if (dev->flags.bus_address)
+		device_remove_file(&dev->dev, &dev_attr_adr);
 	device_remove_file(&dev->dev, &dev_attr_modalias);
 	device_remove_file(&dev->dev, &dev_attr_hid);
 	if (dev->handle)
@@ -340,8 +408,8 @@ static void acpi_device_remove_files(struct acpi_device *dev)
 			ACPI Bus operations
    -------------------------------------------------------------------------- */
 
-int acpi_match_device_ids(struct acpi_device *device,
-			  const struct acpi_device_id *ids)
+static const struct acpi_device_id *__acpi_match_device(
+	struct acpi_device *device, const struct acpi_device_id *ids)
 {
 	const struct acpi_device_id *id;
 	struct acpi_hardware_id *hwid;
@@ -351,14 +419,44 @@ int acpi_match_device_ids(struct acpi_device *device,
 	 * driver for it.
 	 */
 	if (!device->status.present)
-		return -ENODEV;
+		return NULL;
 
 	for (id = ids; id->id[0]; id++)
 		list_for_each_entry(hwid, &device->pnp.ids, list)
 			if (!strcmp((char *) id->id, hwid->id))
-				return 0;
+				return id;
 
-	return -ENOENT;
+	return NULL;
+}
+
+/**
+ * acpi_match_device - Match a struct device against a given list of ACPI IDs
+ * @ids: Array of struct acpi_device_id object to match against.
+ * @dev: The device structure to match.
+ *
+ * Check if @dev has a valid ACPI handle and if there is a struct acpi_device
+ * object for that handle and use that object to match against a given list of
+ * device IDs.
+ *
+ * Return a pointer to the first matching ID on success or %NULL on failure.
+ */
+const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
+					       const struct device *dev)
+{
+	struct acpi_device *adev;
+
+	if (!ids || !ACPI_HANDLE(dev)
+	    || ACPI_FAILURE(acpi_bus_get_device(ACPI_HANDLE(dev), &adev)))
+		return NULL;
+
+	return __acpi_match_device(adev, ids);
+}
+EXPORT_SYMBOL_GPL(acpi_match_device);
+
+int acpi_match_device_ids(struct acpi_device *device,
+			  const struct acpi_device_id *ids)
+{
+	return __acpi_match_device(device, ids) ? 0 : -ENOENT;
 }
 EXPORT_SYMBOL(acpi_match_device_ids);
 
@@ -377,6 +475,7 @@ static void acpi_device_release(struct device *dev)
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 
 	acpi_free_ids(acpi_dev);
+	kfree(acpi_dev->pnp.unique_id);
 	kfree(acpi_dev);
 }
 
@@ -965,8 +1064,10 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
 		 * D3hot is only valid if _PR3 present.
 		 */
 		if (ps->resources.count ||
-		    (ps->flags.explicit_set && i < ACPI_STATE_D3_HOT))
+		    (ps->flags.explicit_set && i < ACPI_STATE_D3_HOT)) {
 			ps->flags.valid = 1;
+			ps->flags.os_accessible = 1;
+		}
 
 		ps->power = -1;	/* Unknown - driver assigned */
 		ps->latency = -1;	/* Unknown - driver assigned */
@@ -982,6 +1083,11 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
 	if (device->power.states[ACPI_STATE_D3_HOT].flags.explicit_set)
 		device->power.states[ACPI_STATE_D3_COLD].flags.explicit_set = 1;
 
+	/* Presence of _PS3 or _PRx means we can put the device into D3 cold */
+	if (device->power.states[ACPI_STATE_D3_HOT].flags.explicit_set ||
+			device->power.flags.power_resources)
+		device->power.states[ACPI_STATE_D3_COLD].flags.os_accessible = 1;
+
 	acpi_bus_init_power(device);
 
 	return 0;
@@ -1013,11 +1119,6 @@ static int acpi_bus_get_flags(struct acpi_device *device)
 			device->flags.ejectable = 1;
 	}
 
-	/* Presence of _LCK indicates 'lockable' */
-	status = acpi_get_handle(device->handle, "_LCK", &temp);
-	if (ACPI_SUCCESS(status))
-		device->flags.lockable = 1;
-
 	/* Power resources cannot be power manageable. */
 	if (device->device_type == ACPI_BUS_TYPE_POWER)
 		return 0;
@@ -1185,7 +1286,7 @@ static void acpi_device_set_id(struct acpi_device *device)
 {
 	acpi_status status;
 	struct acpi_device_info *info;
-	struct acpica_device_id_list *cid_list;
+	struct acpi_pnp_device_id_list *cid_list;
 	int i;
 
 	switch (device->device_type) {
@@ -1212,6 +1313,9 @@ static void acpi_device_set_id(struct acpi_device *device)
 			device->pnp.bus_address = info->address;
 			device->flags.bus_address = 1;
 		}
+		if (info->valid & ACPI_VALID_UID)
+			device->pnp.unique_id = kstrdup(info->unique_id.string,
+							GFP_KERNEL);
 
 		kfree(info);
 
@@ -1483,8 +1587,13 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
 	 */
 	device = NULL;
 	acpi_bus_get_device(handle, &device);
-	if (ops->acpi_op_add && !device)
+	if (ops->acpi_op_add && !device) {
 		acpi_add_single_object(&device, handle, type, sta, ops);
+		/* Is the device a known good platform device? */
+		if (device
+		    && !acpi_match_device_ids(device, acpi_platform_device_ids))
+			acpi_create_platform_device(device);
+	}
 
 	if (!device)
 		return AE_CTRL_DEPTH;
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index fdcdbb6..1e25319 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -18,7 +18,6 @@
 #include <linux/reboot.h>
 #include <linux/acpi.h>
 #include <linux/module.h>
-#include <linux/pm_runtime.h>
 
 #include <asm/io.h>
 
@@ -81,6 +80,12 @@ static int acpi_sleep_prepare(u32 acpi_state)
 
 #ifdef CONFIG_ACPI_SLEEP
 static u32 acpi_target_sleep_state = ACPI_STATE_S0;
+
+u32 acpi_target_system_state(void)
+{
+	return acpi_target_sleep_state;
+}
+
 static bool pwr_btn_event_pending;
 
 /*
@@ -98,6 +103,21 @@ void __init acpi_nvs_nosave(void)
 }
 
 /*
+ * The ACPI specification wants us to save NVS memory regions during hibernation
+ * but says nothing about saving NVS during S3.  Not all versions of Windows
+ * save NVS on S3 suspend either, and it is clear that not all systems need
+ * NVS to be saved at S3 time.  To improve suspend/resume time, allow the
+ * user to disable saving NVS on S3 if their system does not require it, but
+ * continue to save/restore NVS for S4 as specified.
+ */
+static bool nvs_nosave_s3;
+
+void __init acpi_nvs_nosave_s3(void)
+{
+	nvs_nosave_s3 = true;
+}
+
+/*
  * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the
  * user to request that behavior by using the 'acpi_old_suspend_ordering'
  * kernel command line option that causes the following variable to be set.
@@ -243,7 +263,7 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
 	u32 acpi_state = acpi_suspend_states[pm_state];
 	int error = 0;
 
-	error = nvs_nosave ? 0 : suspend_nvs_alloc();
+	error = (nvs_nosave || nvs_nosave_s3) ? 0 : suspend_nvs_alloc();
 	if (error)
 		return error;
 
@@ -519,6 +539,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
 	},
 	{
 	.callback = init_nvs_nosave,
+	.ident = "Sony Vaio VPCEB1S1E",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1S1E"),
+		},
+	},
+	{
+	.callback = init_nvs_nosave,
 	.ident = "Sony Vaio VGN-FW520F",
 	.matches = {
 		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
@@ -681,177 +709,6 @@ int acpi_suspend(u32 acpi_state)
 	return -EINVAL;
 }
 
-#ifdef CONFIG_PM
-/**
- *	acpi_pm_device_sleep_state - return preferred power state of ACPI device
- *		in the system sleep state given by %acpi_target_sleep_state
- *	@dev: device to examine; its driver model wakeup flags control
- *		whether it should be able to wake up the system
- *	@d_min_p: used to store the upper limit of allowed states range
- *	@d_max_in: specify the lowest allowed states
- *	Return value: preferred power state of the device on success, -ENODEV
- *	(ie. if there's no 'struct acpi_device' for @dev) or -EINVAL on failure
- *
- *	Find the lowest power (highest number) ACPI device power state that
- *	device @dev can be in while the system is in the sleep state represented
- *	by %acpi_target_sleep_state.  If @wake is nonzero, the device should be
- *	able to wake up the system from this sleep state.  If @d_min_p is set,
- *	the highest power (lowest number) device power state of @dev allowed
- *	in this system sleep state is stored at the location pointed to by it.
- *
- *	The caller must ensure that @dev is valid before using this function.
- *	The caller is also responsible for figuring out if the device is
- *	supposed to be able to wake up the system and passing this information
- *	via @wake.
- */
-
-int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
-{
-	acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
-	struct acpi_device *adev;
-	char acpi_method[] = "_SxD";
-	unsigned long long d_min, d_max;
-
-	if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3)
-		return -EINVAL;
-	if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
-		printk(KERN_DEBUG "ACPI handle has no context!\n");
-		return -ENODEV;
-	}
-
-	acpi_method[2] = '0' + acpi_target_sleep_state;
-	/*
-	 * If the sleep state is S0, the lowest limit from ACPI is D3,
-	 * but if the device has _S0W, we will use the value from _S0W
-	 * as the lowest limit from ACPI.  Finally, we will constrain
-	 * the lowest limit with the specified one.
-	 */
-	d_min = ACPI_STATE_D0;
-	d_max = ACPI_STATE_D3;
-
-	/*
-	 * If present, _SxD methods return the minimum D-state (highest power
-	 * state) we can use for the corresponding S-states.  Otherwise, the
-	 * minimum D-state is D0 (ACPI 3.x).
-	 *
-	 * NOTE: We rely on acpi_evaluate_integer() not clobbering the integer
-	 * provided -- that's our fault recovery, we ignore retval.
-	 */
-	if (acpi_target_sleep_state > ACPI_STATE_S0)
-		acpi_evaluate_integer(handle, acpi_method, NULL, &d_min);
-
-	/*
-	 * If _PRW says we can wake up the system from the target sleep state,
-	 * the D-state returned by _SxD is sufficient for that (we assume a
-	 * wakeup-aware driver if wake is set).  Still, if _SxW exists
-	 * (ACPI 3.x), it should return the maximum (lowest power) D-state that
-	 * can wake the system.  _S0W may be valid, too.
-	 */
-	if (acpi_target_sleep_state == ACPI_STATE_S0 ||
-	    (device_may_wakeup(dev) && adev->wakeup.flags.valid &&
-	     adev->wakeup.sleep_state >= acpi_target_sleep_state)) {
-		acpi_status status;
-
-		acpi_method[3] = 'W';
-		status = acpi_evaluate_integer(handle, acpi_method, NULL,
-						&d_max);
-		if (ACPI_FAILURE(status)) {
-			if (acpi_target_sleep_state != ACPI_STATE_S0 ||
-			    status != AE_NOT_FOUND)
-				d_max = d_min;
-		} else if (d_max < d_min) {
-			/* Warn the user of the broken DSDT */
-			printk(KERN_WARNING "ACPI: Wrong value from %s\n",
-				acpi_method);
-			/* Sanitize it */
-			d_min = d_max;
-		}
-	}
-
-	if (d_max_in < d_min)
-		return -EINVAL;
-	if (d_min_p)
-		*d_min_p = d_min;
-	/* constrain d_max with specified lowest limit (max number) */
-	if (d_max > d_max_in) {
-		for (d_max = d_max_in; d_max > d_min; d_max--) {
-			if (adev->power.states[d_max].flags.valid)
-				break;
-		}
-	}
-	return d_max;
-}
-EXPORT_SYMBOL(acpi_pm_device_sleep_state);
-#endif /* CONFIG_PM */
-
-#ifdef CONFIG_PM_SLEEP
-/**
- * acpi_pm_device_run_wake - Enable/disable wake-up for given device.
- * @phys_dev: Device to enable/disable the platform to wake-up the system for.
- * @enable: Whether enable or disable the wake-up functionality.
- *
- * Find the ACPI device object corresponding to @pci_dev and try to
- * enable/disable the GPE associated with it.
- */
-int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
-{
-	struct acpi_device *dev;
-	acpi_handle handle;
-
-	if (!device_run_wake(phys_dev))
-		return -EINVAL;
-
-	handle = DEVICE_ACPI_HANDLE(phys_dev);
-	if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &dev))) {
-		dev_dbg(phys_dev, "ACPI handle has no context in %s!\n",
-			__func__);
-		return -ENODEV;
-	}
-
-	if (enable) {
-		acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0);
-		acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number);
-	} else {
-		acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number);
-		acpi_disable_wakeup_device_power(dev);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(acpi_pm_device_run_wake);
-
-/**
- *	acpi_pm_device_sleep_wake - enable or disable the system wake-up
- *                                  capability of given device
- *	@dev: device to handle
- *	@enable: 'true' - enable, 'false' - disable the wake-up capability
- */
-int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
-{
-	acpi_handle handle;
-	struct acpi_device *adev;
-	int error;
-
-	if (!device_can_wakeup(dev))
-		return -EINVAL;
-
-	handle = DEVICE_ACPI_HANDLE(dev);
-	if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
-		dev_dbg(dev, "ACPI handle has no context in %s!\n", __func__);
-		return -ENODEV;
-	}
-
-	error = enable ?
-		acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) :
-		acpi_disable_wakeup_device_power(adev);
-	if (!error)
-		dev_info(dev, "wake-up capability %s by ACPI\n",
-				enable ? "enabled" : "disabled");
-
-	return error;
-}
-#endif  /* CONFIG_PM_SLEEP */
-
 static void acpi_power_off_prepare(void)
 {
 	/* Prepare to power off the system */
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 7c3f98b..ea61ca9 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -476,7 +476,7 @@ static void fixed_event_count(u32 event_number)
 	return;
 }
 
-static void acpi_gbl_event_handler(u32 event_type, acpi_handle device,
+static void acpi_global_event_handler(u32 event_type, acpi_handle device,
 	u32 event_number, void *context)
 {
 	if (event_type == ACPI_EVENT_TYPE_GPE)
@@ -638,7 +638,7 @@ void acpi_irq_stats_init(void)
 	if (all_counters == NULL)
 		goto fail;
 
-	status = acpi_install_global_event_handler(acpi_gbl_event_handler, NULL);
+	status = acpi_install_global_event_handler(acpi_global_event_handler, NULL);
 	if (ACPI_FAILURE(status))
 		goto fail;
 
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 804204d..506fbd4 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -900,14 +900,14 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
 	if (tz->trips.passive.flags.valid)
 		tz->thermal_zone =
 			thermal_zone_device_register("acpitz", trips, 0, tz,
-						     &acpi_thermal_zone_ops,
+						&acpi_thermal_zone_ops, NULL,
 						     tz->trips.passive.tsp*100,
 						     tz->polling_frequency*100);
 	else
 		tz->thermal_zone =
 			thermal_zone_device_register("acpitz", trips, 0, tz,
-						     &acpi_thermal_zone_ops, 0,
-						     tz->polling_frequency*100);
+						&acpi_thermal_zone_ops, NULL,
+						0, tz->polling_frequency*100);
 	if (IS_ERR(tz->thermal_zone))
 		return -ENODEV;
 
@@ -984,6 +984,38 @@ static void acpi_thermal_notify(struct acpi_device *device, u32 event)
 	}
 }
 
+/*
+ * On some platforms, the AML code has dependency about
+ * the evaluating order of _TMP and _CRT/_HOT/_PSV/_ACx.
+ * 1. On HP Pavilion G4-1016tx, _TMP must be invoked after
+ *    /_CRT/_HOT/_PSV/_ACx, or else system will be power off.
+ * 2. On HP Compaq 6715b/6715s, the return value of _PSV is 0
+ *    if _TMP has never been evaluated.
+ *
+ * As this dependency is totally transparent to OS, evaluate
+ * all of them once, in the order of _CRT/_HOT/_PSV/_ACx,
+ * _TMP, before they are actually used.
+ */
+static void acpi_thermal_aml_dependency_fix(struct acpi_thermal *tz)
+{
+	acpi_handle handle = tz->device->handle;
+	unsigned long long value;
+	int i;
+
+	acpi_evaluate_integer(handle, "_CRT", NULL, &value);
+	acpi_evaluate_integer(handle, "_HOT", NULL, &value);
+	acpi_evaluate_integer(handle, "_PSV", NULL, &value);
+	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+		char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
+		acpi_status status;
+
+		status = acpi_evaluate_integer(handle, name, NULL, &value);
+		if (status == AE_NOT_FOUND)
+			break;
+	}
+	acpi_evaluate_integer(handle, "_TMP", NULL, &value);
+}
+
 static int acpi_thermal_get_info(struct acpi_thermal *tz)
 {
 	int result = 0;
@@ -992,6 +1024,8 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz)
 	if (!tz)
 		return -EINVAL;
 
+	acpi_thermal_aml_dependency_fix(tz);
+
 	/* Get trip points [_CRT, _PSV, etc.] (required) */
 	result = acpi_thermal_get_trip_points(tz);
 	if (result)
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 462f7e3..74437130 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -28,6 +28,8 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/types.h>
+#include <linux/hardirq.h>
+#include <linux/acpi.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -457,3 +459,39 @@ acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event,
 #endif
 }
 EXPORT_SYMBOL(acpi_evaluate_hotplug_ost);
+
+/**
+ * acpi_handle_printk: Print message with ACPI prefix and object path
+ *
+ * This function is called through acpi_handle_<level> macros and prints
+ * a message with ACPI prefix and object path.  This function acquires
+ * the global namespace mutex to obtain an object path.  In interrupt
+ * context, it shows the object path as <n/a>.
+ */
+void
+acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+	struct acpi_buffer buffer = {
+		.length = ACPI_ALLOCATE_BUFFER,
+		.pointer = NULL
+	};
+	const char *path;
+
+	va_start(args, fmt);
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	if (in_interrupt() ||
+	    acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer) != AE_OK)
+		path = "<n/a>";
+	else
+		path = buffer.pointer;
+
+	printk("%sACPI: %s: %pV", level, path, &vaf);
+
+	va_end(args);
+	kfree(buffer.pointer);
+}
+EXPORT_SYMBOL(acpi_handle_printk);
diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c
index 0b6f0b2..0576a7d 100644
--- a/drivers/amba/tegra-ahb.c
+++ b/drivers/amba/tegra-ahb.c
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/tegra-ahb.h>
 
 #define DRV_NAME "tegra-ahb"
 
@@ -156,6 +157,7 @@ int tegra_ahb_enable_smmu(struct device_node *dn)
 EXPORT_SYMBOL(tegra_ahb_enable_smmu);
 #endif
 
+#ifdef CONFIG_PM_SLEEP
 static int tegra_ahb_suspend(struct device *dev)
 {
 	int i;
@@ -175,6 +177,7 @@ static int tegra_ahb_resume(struct device *dev)
 		gizmo_writel(ahb, ahb->ctx[i], tegra_ahb_gizmo[i]);
 	return 0;
 }
+#endif
 
 static UNIVERSAL_DEV_PM_OPS(tegra_ahb_pm,
 			    tegra_ahb_suspend,
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index ef773e1..bec35f4 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -1585,12 +1585,31 @@ static void piix_ignore_devices_quirk(struct ata_host *host)
 		},
 		{ }	/* terminate list */
 	};
-	const struct dmi_system_id *dmi = dmi_first_match(ignore_hyperv);
+	static const struct dmi_system_id allow_virtual_pc[] = {
+		{
+			/* In MS Virtual PC guests the DMI ident is nearly
+			 * identical to a Hyper-V guest. One difference is the
+			 * product version which is used here to identify
+			 * a Virtual PC guest. This entry allows ata_piix to
+			 * drive the emulated hardware.
+			 */
+			.ident = "MS Virtual PC 2007",
+			.matches = {
+				DMI_MATCH(DMI_SYS_VENDOR,
+						"Microsoft Corporation"),
+				DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+				DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"),
+			},
+		},
+		{ }	/* terminate list */
+	};
+	const struct dmi_system_id *ignore = dmi_first_match(ignore_hyperv);
+	const struct dmi_system_id *allow = dmi_first_match(allow_virtual_pc);
 
-	if (dmi && prefer_ms_hyperv) {
+	if (ignore && !allow && prefer_ms_hyperv) {
 		host->flags |= ATA_HOST_IGNORE_ATA;
 		dev_info(host->dev, "%s detected, ATA device ignore set\n",
-			dmi->ident);
+			ignore->ident);
 	}
 #endif
 }
diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c
index 371fd2c..9764e80 100644
--- a/drivers/ata/pata_arasan_cf.c
+++ b/drivers/ata/pata_arasan_cf.c
@@ -674,13 +674,16 @@ void arasan_cf_error_handler(struct ata_port *ap)
 
 static void arasan_cf_dma_start(struct arasan_cf_dev *acdev)
 {
+	struct ata_queued_cmd *qc = acdev->qc;
+	struct ata_port *ap = qc->ap;
+	struct ata_taskfile *tf = &qc->tf;
 	u32 xfer_ctr = readl(acdev->vbase + XFER_CTR) & ~XFER_DIR_MASK;
-	u32 write = acdev->qc->tf.flags & ATA_TFLAG_WRITE;
+	u32 write = tf->flags & ATA_TFLAG_WRITE;
 
 	xfer_ctr |= write ? XFER_WRITE : XFER_READ;
 	writel(xfer_ctr, acdev->vbase + XFER_CTR);
 
-	acdev->qc->ap->ops->sff_exec_command(acdev->qc->ap, &acdev->qc->tf);
+	ap->ops->sff_exec_command(ap, tf);
 	ata_sff_queue_work(&acdev->work);
 }
 
diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c
index 53d3770..2a96bb2 100644
--- a/drivers/ata/pata_at91.c
+++ b/drivers/ata/pata_at91.c
@@ -27,9 +27,9 @@
 #include <linux/libata.h>
 #include <linux/platform_device.h>
 #include <linux/ata_platform.h>
+#include <linux/platform_data/atmel.h>
 
 #include <mach/at91sam9_smc.h>
-#include <mach/board.h>
 #include <asm/gpio.h>
 
 #define DRV_NAME		"pata_at91"
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 7ba0141..2949cfc 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -474,14 +474,14 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	/* check for enabled ports */
 	pci_read_config_byte(pdev, CNTRL, &reg);
 	if (!port_ok)
-		dev_printk(KERN_NOTICE, &pdev->dev, "Mobility Bridge detected, ignoring CNTRL port enable/disable\n");
+		dev_notice(&pdev->dev, "Mobility Bridge detected, ignoring CNTRL port enable/disable\n");
 	if (port_ok && cntrl_ch0_ok && !(reg & CNTRL_CH0)) {
-		dev_printk(KERN_NOTICE, &pdev->dev, "Primary port is disabled\n");
+		dev_notice(&pdev->dev, "Primary port is disabled\n");
 		ppi[0] = &ata_dummy_port_info;
 
 	}
 	if (port_ok && !(reg & CNTRL_CH1)) {
-		dev_printk(KERN_NOTICE, &pdev->dev, "Secondary port is disabled\n");
+		dev_notice(&pdev->dev, "Secondary port is disabled\n");
 		ppi[1] = &ata_dummy_port_info;
 	}
 
diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c
index dec1b6c..0448860 100644
--- a/drivers/ata/pata_cs5536.c
+++ b/drivers/ata/pata_cs5536.c
@@ -38,6 +38,7 @@
 #include <linux/delay.h>
 #include <linux/libata.h>
 #include <scsi/scsi_host.h>
+#include <linux/dmi.h>
 
 #ifdef CONFIG_X86_32
 #include <asm/msr.h>
@@ -80,6 +81,21 @@ enum {
 	IDE_ETC_UDMA_MASK	= 0xc0,
 };
 
+/* Some Bachmann OT200 devices have a non working UDMA support due a
+ * missing resistor.
+ */
+static const struct dmi_system_id udma_quirk_dmi_table[] = {
+	{
+		.ident = "Bachmann electronic OT200",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Bachmann electronic"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OT200"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "1")
+		},
+	},
+	{ }
+};
+
 static int cs5536_read(struct pci_dev *pdev, int reg, u32 *val)
 {
 	if (unlikely(use_msr)) {
@@ -242,9 +258,23 @@ static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 		.port_ops = &cs5536_port_ops,
 	};
 
-	const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
+	static const struct ata_port_info no_udma_info = {
+		.flags = ATA_FLAG_SLAVE_POSS,
+		.pio_mask = ATA_PIO4,
+		.port_ops = &cs5536_port_ops,
+	};
+
+
+	const struct ata_port_info *ppi[2];
 	u32 cfg;
 
+	if (dmi_check_system(udma_quirk_dmi_table))
+		ppi[0] = &no_udma_info;
+	else
+		ppi[0] = &info;
+
+	ppi[1] = &ata_dummy_port_info;
+
 	if (use_msr)
 		printk(KERN_ERR DRV_NAME ": Using MSR regs instead of PCI\n");
 
diff --git a/drivers/ata/pata_rdc.c b/drivers/ata/pata_rdc.c
index 32a3499..e71f998 100644
--- a/drivers/ata/pata_rdc.c
+++ b/drivers/ata/pata_rdc.c
@@ -327,7 +327,6 @@ static int __devinit rdc_init_one(struct pci_dev *pdev,
 	struct device *dev = &pdev->dev;
 	struct ata_port_info port_info[2];
 	const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
-	unsigned long port_flags;
 	struct ata_host *host;
 	struct rdc_host_priv *hpriv;
 	int rc;
@@ -337,8 +336,6 @@ static int __devinit rdc_init_one(struct pci_dev *pdev,
 	port_info[0] = rdc_port_info;
 	port_info[1] = rdc_port_info;
 
-	port_flags = port_info[0].flags;
-
 	/* enable device and prepare host */
 	rc = pcim_enable_device(pdev);
 	if (rc)
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index 400bf1c..75c0f3c 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -213,7 +213,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
 
 	/* clear D2H reception area to properly wait for D2H FIS */
 	ata_tf_init(link->device, &tf);
-	tf.command = 0x80;
+	tf.command = ATA_BUSY;
 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
 
 	do {
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index dc35f4d..1e6827c 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -273,12 +273,10 @@ static void inic_reset_port(void __iomem *port_base)
 static int inic_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val)
 {
 	void __iomem *scr_addr = inic_port_base(link->ap) + PORT_SCR;
-	void __iomem *addr;
 
 	if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
 		return -EINVAL;
 
-	addr = scr_addr + scr_map[sc_reg] * 4;
 	*val = readl(scr_addr + scr_map[sc_reg] * 4);
 
 	/* this controller has stuck DIAG.N, ignore it */
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 489c817..fb0dd87 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -147,6 +147,10 @@ struct pdc_port_priv {
 	dma_addr_t		pkt_dma;
 };
 
+struct pdc_host_priv {
+	spinlock_t hard_reset_lock;
+};
+
 static int pdc_sata_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
 static int pdc_sata_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
 static int pdc_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
@@ -801,9 +805,10 @@ static void pdc_hard_reset_port(struct ata_port *ap)
 	void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR];
 	void __iomem *pcictl_b1_mmio = host_mmio + PDC_PCI_CTL + 1;
 	unsigned int ata_no = pdc_ata_port_to_ata_no(ap);
+	struct pdc_host_priv *hpriv = ap->host->private_data;
 	u8 tmp;
 
-	spin_lock(&ap->host->lock);
+	spin_lock(&hpriv->hard_reset_lock);
 
 	tmp = readb(pcictl_b1_mmio);
 	tmp &= ~(0x10 << ata_no);
@@ -814,7 +819,7 @@ static void pdc_hard_reset_port(struct ata_port *ap)
 	writeb(tmp, pcictl_b1_mmio);
 	readb(pcictl_b1_mmio); /* flush */
 
-	spin_unlock(&ap->host->lock);
+	spin_unlock(&hpriv->hard_reset_lock);
 }
 
 static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class,
@@ -1182,6 +1187,7 @@ static int pdc_ata_init_one(struct pci_dev *pdev,
 	const struct ata_port_info *pi = &pdc_port_info[ent->driver_data];
 	const struct ata_port_info *ppi[PDC_MAX_PORTS];
 	struct ata_host *host;
+	struct pdc_host_priv *hpriv;
 	void __iomem *host_mmio;
 	int n_ports, i, rc;
 	int is_sataii_tx4;
@@ -1218,6 +1224,11 @@ static int pdc_ata_init_one(struct pci_dev *pdev,
 		dev_err(&pdev->dev, "failed to allocate host\n");
 		return -ENOMEM;
 	}
+	hpriv = devm_kzalloc(&pdev->dev, sizeof *hpriv, GFP_KERNEL);
+	if (!hpriv)
+		return -ENOMEM;
+	spin_lock_init(&hpriv->hard_reset_lock);
+	host->private_data = hpriv;
 	host->iomap = pcim_iomap_table(pdev);
 
 	is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags);
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index a5f2a56..59f0d63 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -506,8 +506,6 @@ static int sil24_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val)
 	void __iomem *scr_addr = sil24_port_base(link->ap) + PORT_SCONTROL;
 
 	if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
-		void __iomem *addr;
-		addr = scr_addr + sil24_scr_map[sc_reg] * 4;
 		*val = readl(scr_addr + sil24_scr_map[sc_reg] * 4);
 		return 0;
 	}
@@ -519,8 +517,6 @@ static int sil24_scr_write(struct ata_link *link, unsigned sc_reg, u32 val)
 	void __iomem *scr_addr = sil24_port_base(link->ap) + PORT_SCONTROL;
 
 	if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
-		void __iomem *addr;
-		addr = scr_addr + sil24_scr_map[sc_reg] * 4;
 		writel(val, scr_addr + sil24_scr_map[sc_reg] * 4);
 		return 0;
 	}
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index 1226055..7b7127a 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -315,9 +315,8 @@ static int pdc_port_start(struct ata_port *ap)
 	return 0;
 }
 
-static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,
-				   unsigned int portno,
-					   unsigned int total_len)
+static inline void pdc20621_ata_sg(u8 *buf, unsigned int portno,
+				   unsigned int total_len)
 {
 	u32 addr;
 	unsigned int dw = PDC_DIMM_APKT_PRD >> 2;
@@ -337,9 +336,8 @@ static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,
 		buf32[dw], buf32[dw + 1]);
 }
 
-static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf,
-				    unsigned int portno,
-					    unsigned int total_len)
+static inline void pdc20621_host_sg(u8 *buf, unsigned int portno,
+				    unsigned int total_len)
 {
 	u32 addr;
 	unsigned int dw = PDC_DIMM_HPKT_PRD >> 2;
@@ -486,10 +484,10 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
 	/*
 	 * Build ATA, host DMA packets
 	 */
-	pdc20621_host_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len);
+	pdc20621_host_sg(&pp->dimm_buf[0], portno, total_len);
 	pdc20621_host_pkt(&qc->tf, &pp->dimm_buf[0], portno);
 
-	pdc20621_ata_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len);
+	pdc20621_ata_sg(&pp->dimm_buf[0], portno, total_len);
 	i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno);
 
 	if (qc->tf.flags & ATA_TFLAG_LBA48)
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index 89b30f3..ff7bb8a 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -1961,6 +1961,7 @@ static int __devinit ucode_init (loader_block * lb, amb_dev * dev) {
     res = loader_verify(lb, dev, rec);
     if (res)
       break;
+    rec = ihex_next_binrec(rec);
   }
   release_firmware(fw);
   if (!res)
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index b34b5cd..c8b4539 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -57,7 +57,7 @@ config DEVTMPFS_MOUNT
 	  on the rootfs is completely empty.
 
 config STANDALONE
-	bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL
+	bool "Select only drivers that don't need compile-time external firmware"
 	default y
 	help
 	  Select this option if you don't have magic firmware for drivers that
@@ -185,7 +185,6 @@ config DMA_SHARED_BUFFER
 	bool
 	default n
 	select ANON_INODES
-	depends on EXPERIMENTAL
 	help
 	  This option enables the framework for buffer-sharing between
 	  multiple drivers. A buffer is associated with a file using driver
@@ -193,8 +192,8 @@ config DMA_SHARED_BUFFER
 	  driver.
 
 config CMA
-	bool "Contiguous Memory Allocator (EXPERIMENTAL)"
-	depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK && EXPERIMENTAL
+	bool "Contiguous Memory Allocator"
+	depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK
 	select MIGRATION
 	select MEMORY_ISOLATION
 	help
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index 8fc200b..d78b204 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -158,7 +158,7 @@ attribute_container_add_device(struct device *dev,
 
 		ic = kzalloc(sizeof(*ic), GFP_KERNEL);
 		if (!ic) {
-			dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
+			dev_err(dev, "failed to allocate class container\n");
 			continue;
 		}
 
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 181ed26..24eb078 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -164,8 +164,6 @@ static const struct kset_uevent_ops bus_uevent_ops = {
 
 static struct kset *bus_kset;
 
-
-#ifdef CONFIG_HOTPLUG
 /* Manually detach a device from its associated driver. */
 static ssize_t driver_unbind(struct device_driver *drv,
 			     const char *buf, size_t count)
@@ -252,7 +250,6 @@ static ssize_t store_drivers_probe(struct bus_type *bus,
 		return -EINVAL;
 	return count;
 }
-#endif
 
 static struct device *next_device(struct klist_iter *i)
 {
@@ -618,11 +615,6 @@ static void driver_remove_attrs(struct bus_type *bus,
 	}
 }
 
-#ifdef CONFIG_HOTPLUG
-/*
- * Thanks to drivers making their tables __devinit, we can't allow manual
- * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled.
- */
 static int __must_check add_bind_files(struct device_driver *drv)
 {
 	int ret;
@@ -666,12 +658,6 @@ static void remove_probe_files(struct bus_type *bus)
 	bus_remove_file(bus, &bus_attr_drivers_autoprobe);
 	bus_remove_file(bus, &bus_attr_drivers_probe);
 }
-#else
-static inline int add_bind_files(struct device_driver *drv) { return 0; }
-static inline void remove_bind_files(struct device_driver *drv) {}
-static inline int add_probe_files(struct bus_type *bus) { return 0; }
-static inline void remove_probe_files(struct bus_type *bus) {}
-#endif
 
 static ssize_t driver_uevent_store(struct device_driver *drv,
 				   const char *buf, size_t count)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index abea76c..a235085 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -171,6 +171,27 @@ ssize_t device_show_int(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(device_show_int);
 
+ssize_t device_store_bool(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t size)
+{
+	struct dev_ext_attribute *ea = to_ext_attr(attr);
+
+	if (strtobool(buf, ea->var) < 0)
+		return -EINVAL;
+
+	return size;
+}
+EXPORT_SYMBOL_GPL(device_store_bool);
+
+ssize_t device_show_bool(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct dev_ext_attribute *ea = to_ext_attr(attr);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", *(bool *)(ea->var));
+}
+EXPORT_SYMBOL_GPL(device_show_bool);
+
 /**
  *	device_release - free device structure.
  *	@kobj:	device's kobject.
@@ -1180,7 +1201,6 @@ void device_del(struct device *dev)
 	if (dev->bus)
 		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 					     BUS_NOTIFY_DEL_DEVICE, dev);
-	device_pm_remove(dev);
 	dpm_sysfs_remove(dev);
 	if (parent)
 		klist_del(&dev->p->knode_parent);
@@ -1205,6 +1225,7 @@ void device_del(struct device *dev)
 	device_remove_file(dev, &uevent_attr);
 	device_remove_attrs(dev);
 	bus_remove_device(dev);
+	device_pm_remove(dev);
 	driver_deferred_probe_del(dev);
 
 	/* Notify the platform of the removal, in case they
@@ -1399,7 +1420,7 @@ struct root_device {
 	struct module *owner;
 };
 
-inline struct root_device *to_root_device(struct device *d)
+static inline struct root_device *to_root_device(struct device *d)
 {
 	return container_of(d, struct root_device, dev);
 }
@@ -1840,10 +1861,12 @@ void device_shutdown(void)
 		pm_runtime_barrier(dev);
 
 		if (dev->bus && dev->bus->shutdown) {
-			dev_dbg(dev, "shutdown\n");
+			if (initcall_debug)
+				dev_info(dev, "shutdown\n");
 			dev->bus->shutdown(dev);
 		} else if (dev->driver && dev->driver->shutdown) {
-			dev_dbg(dev, "shutdown\n");
+			if (initcall_debug)
+				dev_info(dev, "shutdown\n");
 			dev->driver->shutdown(dev);
 		}
 
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index 8731979..6683906 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -50,8 +50,8 @@ static void devres_log(struct device *dev, struct devres_node *node,
 		       const char *op)
 {
 	if (unlikely(log_devres))
-		dev_printk(KERN_ERR, dev, "DEVRES %3s %p %s (%lu bytes)\n",
-			   op, node, node->name, (unsigned long)node->size);
+		dev_err(dev, "DEVRES %3s %p %s (%lu bytes)\n",
+			op, node, node->name, (unsigned long)node->size);
 }
 #else /* CONFIG_DEBUG_DEVRES */
 #define set_node_dbginfo(node, n, s)	do {} while (0)
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
index 460e22d..a3f79c4 100644
--- a/drivers/base/dma-buf.c
+++ b/drivers/base/dma-buf.c
@@ -298,6 +298,8 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
 				struct sg_table *sg_table,
 				enum dma_data_direction direction)
 {
+	might_sleep();
+
 	if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
 		return;
 
diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index 3fbedc7..0ce39a3 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -218,6 +218,8 @@ void dmam_release_declared_memory(struct device *dev)
 }
 EXPORT_SYMBOL(dmam_release_declared_memory);
 
+#endif
+
 /*
  * Create scatter-list for the already allocated DMA buffer.
  */
@@ -236,8 +238,6 @@ int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
 }
 EXPORT_SYMBOL(dma_common_get_sgtable);
 
-#endif
-
 /*
  * Create userspace mapping for the DMA-coherent memory.
  */
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 8945f4e..d814603 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -143,7 +143,7 @@ struct fw_cache_entry {
 };
 
 struct firmware_priv {
-	struct timer_list timeout;
+	struct delayed_work timeout_work;
 	bool nowait;
 	struct device dev;
 	struct firmware_buf *buf;
@@ -246,7 +246,6 @@ static void __fw_free_buf(struct kref *ref)
 		 __func__, buf->fw_id, buf, buf->data,
 		 (unsigned int)buf->size);
 
-	spin_lock(&fwc->lock);
 	list_del(&buf->list);
 	spin_unlock(&fwc->lock);
 
@@ -263,19 +262,32 @@ static void __fw_free_buf(struct kref *ref)
 
 static void fw_free_buf(struct firmware_buf *buf)
 {
-	kref_put(&buf->ref, __fw_free_buf);
+	struct firmware_cache *fwc = buf->fwc;
+	spin_lock(&fwc->lock);
+	if (!kref_put(&buf->ref, __fw_free_buf))
+		spin_unlock(&fwc->lock);
 }
 
 /* direct firmware loading support */
-static const char *fw_path[] = {
+static char fw_path_para[256];
+static const char * const fw_path[] = {
+	fw_path_para,
 	"/lib/firmware/updates/" UTS_RELEASE,
 	"/lib/firmware/updates",
 	"/lib/firmware/" UTS_RELEASE,
 	"/lib/firmware"
 };
 
+/*
+ * Typical usage is that passing 'firmware_class.path=$CUSTOMIZED_PATH'
+ * from kernel command line because firmware_class is generally built in
+ * kernel instead of module.
+ */
+module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644);
+MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path");
+
 /* Don't inline this: 'struct kstat' is biggish */
-static noinline long fw_file_size(struct file *file)
+static noinline_for_stack long fw_file_size(struct file *file)
 {
 	struct kstat st;
 	if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st))
@@ -315,6 +327,11 @@ static bool fw_get_filesystem_firmware(struct firmware_buf *buf)
 
 	for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
 		struct file *file;
+
+		/* skip the unset customized path */
+		if (!fw_path[i][0])
+			continue;
+
 		snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id);
 
 		file = filp_open(path, O_RDONLY, 0);
@@ -667,11 +684,18 @@ static struct bin_attribute firmware_attr_data = {
 	.write = firmware_data_write,
 };
 
-static void firmware_class_timeout(u_long data)
+static void firmware_class_timeout_work(struct work_struct *work)
 {
-	struct firmware_priv *fw_priv = (struct firmware_priv *) data;
+	struct firmware_priv *fw_priv = container_of(work,
+			struct firmware_priv, timeout_work.work);
 
+	mutex_lock(&fw_lock);
+	if (test_bit(FW_STATUS_DONE, &(fw_priv->buf->status))) {
+		mutex_unlock(&fw_lock);
+		return;
+	}
 	fw_load_abort(fw_priv);
+	mutex_unlock(&fw_lock);
 }
 
 static struct firmware_priv *
@@ -690,8 +714,8 @@ fw_create_instance(struct firmware *firmware, const char *fw_name,
 
 	fw_priv->nowait = nowait;
 	fw_priv->fw = firmware;
-	setup_timer(&fw_priv->timeout,
-		    firmware_class_timeout, (u_long) fw_priv);
+	INIT_DELAYED_WORK(&fw_priv->timeout_work,
+		firmware_class_timeout_work);
 
 	f_dev = &fw_priv->dev;
 
@@ -858,7 +882,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
 		dev_dbg(f_dev->parent, "firmware: direct-loading"
 			" firmware %s\n", buf->fw_id);
 
+		mutex_lock(&fw_lock);
 		set_bit(FW_STATUS_DONE, &buf->status);
+		mutex_unlock(&fw_lock);
 		complete_all(&buf->completion);
 		direct_load = 1;
 		goto handle_fw;
@@ -894,15 +920,14 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
 		dev_set_uevent_suppress(f_dev, false);
 		dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id);
 		if (timeout != MAX_SCHEDULE_TIMEOUT)
-			mod_timer(&fw_priv->timeout,
-				  round_jiffies_up(jiffies + timeout));
+			schedule_delayed_work(&fw_priv->timeout_work, timeout);
 
 		kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
 	}
 
 	wait_for_completion(&buf->completion);
 
-	del_timer_sync(&fw_priv->timeout);
+	cancel_delayed_work_sync(&fw_priv->timeout_work);
 
 handle_fw:
 	mutex_lock(&fw_lock);
@@ -963,6 +988,9 @@ err_put_dev:
  *      firmware image for this or any other device.
  *
  *	Caller must hold the reference count of @device.
+ *
+ *	The function can be called safely inside device's suspend and
+ *	resume callback.
  **/
 int
 request_firmware(const struct firmware **firmware_p, const char *name,
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 86c8821..987604d 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -70,6 +70,13 @@ void unregister_memory_isolate_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(unregister_memory_isolate_notifier);
 
+static void memory_block_release(struct device *dev)
+{
+	struct memory_block *mem = container_of(dev, struct memory_block, dev);
+
+	kfree(mem);
+}
+
 /*
  * register_memory - Setup a sysfs device for a memory block
  */
@@ -80,6 +87,7 @@ int register_memory(struct memory_block *memory)
 
 	memory->dev.bus = &memory_subsys;
 	memory->dev.id = memory->start_section_nr / sections_per_block;
+	memory->dev.release = memory_block_release;
 
 	error = device_register(&memory->dev);
 	return error;
@@ -246,7 +254,7 @@ static bool pages_correctly_reserved(unsigned long start_pfn,
  * OK to have direct references to sparsemem variables in here.
  */
 static int
-memory_block_action(unsigned long phys_index, unsigned long action)
+memory_block_action(unsigned long phys_index, unsigned long action, int online_type)
 {
 	unsigned long start_pfn;
 	unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
@@ -261,7 +269,7 @@ memory_block_action(unsigned long phys_index, unsigned long action)
 			if (!pages_correctly_reserved(start_pfn, nr_pages))
 				return -EBUSY;
 
-			ret = online_pages(start_pfn, nr_pages);
+			ret = online_pages(start_pfn, nr_pages, online_type);
 			break;
 		case MEM_OFFLINE:
 			ret = offline_pages(start_pfn, nr_pages);
@@ -276,7 +284,8 @@ memory_block_action(unsigned long phys_index, unsigned long action)
 }
 
 static int __memory_block_change_state(struct memory_block *mem,
-		unsigned long to_state, unsigned long from_state_req)
+		unsigned long to_state, unsigned long from_state_req,
+		int online_type)
 {
 	int ret = 0;
 
@@ -288,7 +297,7 @@ static int __memory_block_change_state(struct memory_block *mem,
 	if (to_state == MEM_OFFLINE)
 		mem->state = MEM_GOING_OFFLINE;
 
-	ret = memory_block_action(mem->start_section_nr, to_state);
+	ret = memory_block_action(mem->start_section_nr, to_state, online_type);
 
 	if (ret) {
 		mem->state = from_state_req;
@@ -311,12 +320,14 @@ out:
 }
 
 static int memory_block_change_state(struct memory_block *mem,
-		unsigned long to_state, unsigned long from_state_req)
+		unsigned long to_state, unsigned long from_state_req,
+		int online_type)
 {
 	int ret;
 
 	mutex_lock(&mem->state_mutex);
-	ret = __memory_block_change_state(mem, to_state, from_state_req);
+	ret = __memory_block_change_state(mem, to_state, from_state_req,
+					  online_type);
 	mutex_unlock(&mem->state_mutex);
 
 	return ret;
@@ -330,10 +341,18 @@ store_mem_state(struct device *dev,
 
 	mem = container_of(dev, struct memory_block, dev);
 
-	if (!strncmp(buf, "online", min((int)count, 6)))
-		ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
-	else if(!strncmp(buf, "offline", min((int)count, 7)))
-		ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
+	if (!strncmp(buf, "online_kernel", min_t(int, count, 13)))
+		ret = memory_block_change_state(mem, MEM_ONLINE,
+						MEM_OFFLINE, ONLINE_KERNEL);
+	else if (!strncmp(buf, "online_movable", min_t(int, count, 14)))
+		ret = memory_block_change_state(mem, MEM_ONLINE,
+						MEM_OFFLINE, ONLINE_MOVABLE);
+	else if (!strncmp(buf, "online", min_t(int, count, 6)))
+		ret = memory_block_change_state(mem, MEM_ONLINE,
+						MEM_OFFLINE, ONLINE_KEEP);
+	else if(!strncmp(buf, "offline", min_t(int, count, 7)))
+		ret = memory_block_change_state(mem, MEM_OFFLINE,
+						MEM_ONLINE, -1);
 
 	if (ret)
 		return ret;
@@ -635,7 +654,6 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
 		mem_remove_simple_file(mem, phys_device);
 		mem_remove_simple_file(mem, removable);
 		unregister_memory(mem);
-		kfree(mem);
 	} else
 		kobject_put(&mem->dev.kobj);
 
@@ -669,7 +687,7 @@ int offline_memory_block(struct memory_block *mem)
 
 	mutex_lock(&mem->state_mutex);
 	if (mem->state != MEM_OFFLINE)
-		ret = __memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
+		ret = __memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE, -1);
 	mutex_unlock(&mem->state_mutex);
 
 	return ret;
diff --git a/drivers/base/node.c b/drivers/base/node.c
index af1a177..fac124a 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -227,7 +227,7 @@ static node_registration_func_t __hugetlb_unregister_node;
 static inline bool hugetlb_register_node(struct node *node)
 {
 	if (__hugetlb_register_node &&
-			node_state(node->dev.id, N_HIGH_MEMORY)) {
+			node_state(node->dev.id, N_MEMORY)) {
 		__hugetlb_register_node(node);
 		return true;
 	}
@@ -252,6 +252,24 @@ static inline void hugetlb_register_node(struct node *node) {}
 static inline void hugetlb_unregister_node(struct node *node) {}
 #endif
 
+static void node_device_release(struct device *dev)
+{
+	struct node *node = to_node(dev);
+
+#if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) && defined(CONFIG_HUGETLBFS)
+	/*
+	 * We schedule the work only when a memory section is
+	 * onlined/offlined on this node. When we come here,
+	 * all the memory on this node has been offlined,
+	 * so we won't enqueue new work to this work.
+	 *
+	 * The work is using node->node_work, so we should
+	 * flush work before freeing the memory.
+	 */
+	flush_work(&node->node_work);
+#endif
+	kfree(node);
+}
 
 /*
  * register_node - Setup a sysfs device for a node.
@@ -259,12 +277,13 @@ static inline void hugetlb_unregister_node(struct node *node) {}
  *
  * Initialize and register the node device.
  */
-int register_node(struct node *node, int num, struct node *parent)
+static int register_node(struct node *node, int num, struct node *parent)
 {
 	int error;
 
 	node->dev.id = num;
 	node->dev.bus = &node_subsys;
+	node->dev.release = node_device_release;
 	error = device_register(&node->dev);
 
 	if (!error){
@@ -306,7 +325,7 @@ void unregister_node(struct node *node)
 	device_unregister(&node->dev);
 }
 
-struct node node_devices[MAX_NUMNODES];
+struct node *node_devices[MAX_NUMNODES];
 
 /*
  * register cpu under node
@@ -323,15 +342,15 @@ int register_cpu_under_node(unsigned int cpu, unsigned int nid)
 	if (!obj)
 		return 0;
 
-	ret = sysfs_create_link(&node_devices[nid].dev.kobj,
+	ret = sysfs_create_link(&node_devices[nid]->dev.kobj,
 				&obj->kobj,
 				kobject_name(&obj->kobj));
 	if (ret)
 		return ret;
 
 	return sysfs_create_link(&obj->kobj,
-				 &node_devices[nid].dev.kobj,
-				 kobject_name(&node_devices[nid].dev.kobj));
+				 &node_devices[nid]->dev.kobj,
+				 kobject_name(&node_devices[nid]->dev.kobj));
 }
 
 int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
@@ -345,10 +364,10 @@ int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
 	if (!obj)
 		return 0;
 
-	sysfs_remove_link(&node_devices[nid].dev.kobj,
+	sysfs_remove_link(&node_devices[nid]->dev.kobj,
 			  kobject_name(&obj->kobj));
 	sysfs_remove_link(&obj->kobj,
-			  kobject_name(&node_devices[nid].dev.kobj));
+			  kobject_name(&node_devices[nid]->dev.kobj));
 
 	return 0;
 }
@@ -390,15 +409,15 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid)
 			continue;
 		if (page_nid != nid)
 			continue;
-		ret = sysfs_create_link_nowarn(&node_devices[nid].dev.kobj,
+		ret = sysfs_create_link_nowarn(&node_devices[nid]->dev.kobj,
 					&mem_blk->dev.kobj,
 					kobject_name(&mem_blk->dev.kobj));
 		if (ret)
 			return ret;
 
 		return sysfs_create_link_nowarn(&mem_blk->dev.kobj,
-				&node_devices[nid].dev.kobj,
-				kobject_name(&node_devices[nid].dev.kobj));
+				&node_devices[nid]->dev.kobj,
+				kobject_name(&node_devices[nid]->dev.kobj));
 	}
 	/* mem section does not span the specified node */
 	return 0;
@@ -431,10 +450,10 @@ int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
 			continue;
 		if (node_test_and_set(nid, *unlinked_nodes))
 			continue;
-		sysfs_remove_link(&node_devices[nid].dev.kobj,
+		sysfs_remove_link(&node_devices[nid]->dev.kobj,
 			 kobject_name(&mem_blk->dev.kobj));
 		sysfs_remove_link(&mem_blk->dev.kobj,
-			 kobject_name(&node_devices[nid].dev.kobj));
+			 kobject_name(&node_devices[nid]->dev.kobj));
 	}
 	NODEMASK_FREE(unlinked_nodes);
 	return 0;
@@ -500,7 +519,7 @@ static void node_hugetlb_work(struct work_struct *work)
 
 static void init_node_hugetlb_work(int nid)
 {
-	INIT_WORK(&node_devices[nid].node_work, node_hugetlb_work);
+	INIT_WORK(&node_devices[nid]->node_work, node_hugetlb_work);
 }
 
 static int node_memory_callback(struct notifier_block *self,
@@ -517,7 +536,7 @@ static int node_memory_callback(struct notifier_block *self,
 		 * when transitioning to/from memoryless state.
 		 */
 		if (nid != NUMA_NO_NODE)
-			schedule_work(&node_devices[nid].node_work);
+			schedule_work(&node_devices[nid]->node_work);
 		break;
 
 	case MEM_GOING_ONLINE:
@@ -558,9 +577,13 @@ int register_one_node(int nid)
 		struct node *parent = NULL;
 
 		if (p_node != nid)
-			parent = &node_devices[p_node];
+			parent = node_devices[p_node];
+
+		node_devices[nid] = kzalloc(sizeof(struct node), GFP_KERNEL);
+		if (!node_devices[nid])
+			return -ENOMEM;
 
-		error = register_node(&node_devices[nid], nid, parent);
+		error = register_node(node_devices[nid], nid, parent);
 
 		/* link cpu under this node */
 		for_each_present_cpu(cpu) {
@@ -581,7 +604,8 @@ int register_one_node(int nid)
 
 void unregister_one_node(int nid)
 {
-	unregister_node(&node_devices[nid]);
+	unregister_node(node_devices[nid]);
+	node_devices[nid] = NULL;
 }
 
 /*
@@ -614,23 +638,29 @@ static ssize_t show_node_state(struct device *dev,
 	{ __ATTR(name, 0444, show_node_state, NULL), state }
 
 static struct node_attr node_state_attr[] = {
-	_NODE_ATTR(possible, N_POSSIBLE),
-	_NODE_ATTR(online, N_ONLINE),
-	_NODE_ATTR(has_normal_memory, N_NORMAL_MEMORY),
-	_NODE_ATTR(has_cpu, N_CPU),
+	[N_POSSIBLE] = _NODE_ATTR(possible, N_POSSIBLE),
+	[N_ONLINE] = _NODE_ATTR(online, N_ONLINE),
+	[N_NORMAL_MEMORY] = _NODE_ATTR(has_normal_memory, N_NORMAL_MEMORY),
 #ifdef CONFIG_HIGHMEM
-	_NODE_ATTR(has_high_memory, N_HIGH_MEMORY),
+	[N_HIGH_MEMORY] = _NODE_ATTR(has_high_memory, N_HIGH_MEMORY),
 #endif
+#ifdef CONFIG_MOVABLE_NODE
+	[N_MEMORY] = _NODE_ATTR(has_memory, N_MEMORY),
+#endif
+	[N_CPU] = _NODE_ATTR(has_cpu, N_CPU),
 };
 
 static struct attribute *node_state_attrs[] = {
-	&node_state_attr[0].attr.attr,
-	&node_state_attr[1].attr.attr,
-	&node_state_attr[2].attr.attr,
-	&node_state_attr[3].attr.attr,
+	&node_state_attr[N_POSSIBLE].attr.attr,
+	&node_state_attr[N_ONLINE].attr.attr,
+	&node_state_attr[N_NORMAL_MEMORY].attr.attr,
 #ifdef CONFIG_HIGHMEM
-	&node_state_attr[4].attr.attr,
+	&node_state_attr[N_HIGH_MEMORY].attr.attr,
+#endif
+#ifdef CONFIG_MOVABLE_NODE
+	&node_state_attr[N_MEMORY].attr.attr,
 #endif
+	&node_state_attr[N_CPU].attr.attr,
 	NULL
 };
 
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 72c776f..c0b8df3 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <linux/idr.h>
+#include <linux/acpi.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -44,7 +45,7 @@ EXPORT_SYMBOL_GPL(platform_bus);
  * be setup before the platform_notifier is called.  So if a user needs to
  * manipulate any relevant information in the pdev_archdata they can do:
  *
- * 	platform_devic_alloc()
+ *	platform_device_alloc()
  * 	... manipulate ...
  * 	platform_device_add()
  *
@@ -122,7 +123,7 @@ struct resource *platform_get_resource_byname(struct platform_device *dev,
 EXPORT_SYMBOL_GPL(platform_get_resource_byname);
 
 /**
- * platform_get_irq - get an IRQ for a device
+ * platform_get_irq_byname - get an IRQ for a device by name
  * @dev: platform device
  * @name: IRQ name
  */
@@ -436,6 +437,7 @@ struct platform_device *platform_device_register_full(
 		goto err_alloc;
 
 	pdev->dev.parent = pdevinfo->parent;
+	ACPI_HANDLE_SET(&pdev->dev, pdevinfo->acpi_node.handle);
 
 	if (pdevinfo->dma_mask) {
 		/*
@@ -466,6 +468,7 @@ struct platform_device *platform_device_register_full(
 	ret = platform_device_add(pdev);
 	if (ret) {
 err:
+		ACPI_HANDLE_SET(&pdev->dev, NULL);
 		kfree(pdev->dev.dma_mask);
 
 err_alloc:
@@ -481,8 +484,16 @@ static int platform_drv_probe(struct device *_dev)
 {
 	struct platform_driver *drv = to_platform_driver(_dev->driver);
 	struct platform_device *dev = to_platform_device(_dev);
+	int ret;
+
+	if (ACPI_HANDLE(_dev))
+		acpi_dev_pm_attach(_dev, true);
 
-	return drv->probe(dev);
+	ret = drv->probe(dev);
+	if (ret && ACPI_HANDLE(_dev))
+		acpi_dev_pm_detach(_dev, true);
+
+	return ret;
 }
 
 static int platform_drv_probe_fail(struct device *_dev)
@@ -494,8 +505,13 @@ static int platform_drv_remove(struct device *_dev)
 {
 	struct platform_driver *drv = to_platform_driver(_dev->driver);
 	struct platform_device *dev = to_platform_device(_dev);
+	int ret;
 
-	return drv->remove(dev);
+	ret = drv->remove(dev);
+	if (ACPI_HANDLE(_dev))
+		acpi_dev_pm_detach(_dev, true);
+
+	return ret;
 }
 
 static void platform_drv_shutdown(struct device *_dev)
@@ -504,6 +520,8 @@ static void platform_drv_shutdown(struct device *_dev)
 	struct platform_device *dev = to_platform_device(_dev);
 
 	drv->shutdown(dev);
+	if (ACPI_HANDLE(_dev))
+		acpi_dev_pm_detach(_dev, true);
 }
 
 /**
@@ -709,6 +727,10 @@ static int platform_match(struct device *dev, struct device_driver *drv)
 	if (of_driver_match_device(dev, drv))
 		return 1;
 
+	/* Then try ACPI style match */
+	if (acpi_driver_match_device(dev, drv))
+		return 1;
+
 	/* Then try to match against the id table */
 	if (pdrv->id_table)
 		return platform_match_id(pdrv->id_table, pdev) != NULL;
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index eb78e96..9d8fde7 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -99,7 +99,7 @@ static void __pm_clk_remove(struct pm_clock_entry *ce)
 
 	if (ce->status < PCE_STATUS_ERROR) {
 		if (ce->status == PCE_STATUS_ENABLED)
-			clk_disable(ce->clk);
+			clk_disable_unprepare(ce->clk);
 
 		if (ce->status >= PCE_STATUS_ACQUIRED)
 			clk_put(ce->clk);
@@ -396,7 +396,7 @@ static void enable_clock(struct device *dev, const char *con_id)
 
 	clk = clk_get(dev, con_id);
 	if (!IS_ERR(clk)) {
-		clk_enable(clk);
+		clk_prepare_enable(clk);
 		clk_put(clk);
 		dev_info(dev, "Runtime PM disabled, clock forced on.\n");
 	}
@@ -413,7 +413,7 @@ static void disable_clock(struct device *dev, const char *con_id)
 
 	clk = clk_get(dev, con_id);
 	if (!IS_ERR(clk)) {
-		clk_disable(clk);
+		clk_disable_unprepare(clk);
 		clk_put(clk);
 		dev_info(dev, "Runtime PM disabled, clock forced off.\n");
 	}
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 96b71b6..acc3a8d 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -470,10 +470,19 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
 		return -EBUSY;
 
 	not_suspended = 0;
-	list_for_each_entry(pdd, &genpd->dev_list, list_node)
+	list_for_each_entry(pdd, &genpd->dev_list, list_node) {
+		enum pm_qos_flags_status stat;
+
+		stat = dev_pm_qos_flags(pdd->dev,
+					PM_QOS_FLAG_NO_POWER_OFF
+						| PM_QOS_FLAG_REMOTE_WAKEUP);
+		if (stat > PM_QOS_FLAGS_NONE)
+			return -EBUSY;
+
 		if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev)
 		    || pdd->dev->power.irq_safe))
 			not_suspended++;
+	}
 
 	if (not_suspended > genpd->in_progress)
 		return -EBUSY;
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index d946864..50b2831 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -23,6 +23,7 @@
 #include <linux/rcupdate.h>
 #include <linux/opp.h>
 #include <linux/of.h>
+#include <linux/export.h>
 
 /*
  * Internal data structure organization with the OPP layer library is as
@@ -65,6 +66,7 @@ struct opp {
 	unsigned long u_volt;
 
 	struct device_opp *dev_opp;
+	struct rcu_head head;
 };
 
 /**
@@ -160,6 +162,7 @@ unsigned long opp_get_voltage(struct opp *opp)
 
 	return v;
 }
+EXPORT_SYMBOL(opp_get_voltage);
 
 /**
  * opp_get_freq() - Gets the frequency corresponding to an available opp
@@ -189,6 +192,7 @@ unsigned long opp_get_freq(struct opp *opp)
 
 	return f;
 }
+EXPORT_SYMBOL(opp_get_freq);
 
 /**
  * opp_get_opp_count() - Get number of opps available in the opp list
@@ -221,6 +225,7 @@ int opp_get_opp_count(struct device *dev)
 
 	return count;
 }
+EXPORT_SYMBOL(opp_get_opp_count);
 
 /**
  * opp_find_freq_exact() - search for an exact frequency
@@ -230,7 +235,10 @@ int opp_get_opp_count(struct device *dev)
  *
  * Searches for exact match in the opp list and returns pointer to the matching
  * opp if found, else returns ERR_PTR in case of error and should be handled
- * using IS_ERR.
+ * using IS_ERR. Error return values can be:
+ * EINVAL:	for bad pointer
+ * ERANGE:	no match found for search
+ * ENODEV:	if device not found in list of registered devices
  *
  * Note: available is a modifier for the search. if available=true, then the
  * match is for exact matching frequency and is available in the stored OPP
@@ -249,7 +257,7 @@ struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
 				bool available)
 {
 	struct device_opp *dev_opp;
-	struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+	struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
 	dev_opp = find_device_opp(dev);
 	if (IS_ERR(dev_opp)) {
@@ -268,6 +276,7 @@ struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
 
 	return opp;
 }
+EXPORT_SYMBOL(opp_find_freq_exact);
 
 /**
  * opp_find_freq_ceil() - Search for an rounded ceil freq
@@ -278,7 +287,11 @@ struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
  * for a device.
  *
  * Returns matching *opp and refreshes *freq accordingly, else returns
- * ERR_PTR in case of error and should be handled using IS_ERR.
+ * ERR_PTR in case of error and should be handled using IS_ERR. Error return
+ * values can be:
+ * EINVAL:	for bad pointer
+ * ERANGE:	no match found for search
+ * ENODEV:	if device not found in list of registered devices
  *
  * Locking: This function must be called under rcu_read_lock(). opp is a rcu
  * protected pointer. The reason for the same is that the opp pointer which is
@@ -289,7 +302,7 @@ struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
 struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
 {
 	struct device_opp *dev_opp;
-	struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+	struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
 	if (!dev || !freq) {
 		dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
@@ -298,7 +311,7 @@ struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
 
 	dev_opp = find_device_opp(dev);
 	if (IS_ERR(dev_opp))
-		return opp;
+		return ERR_CAST(dev_opp);
 
 	list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
 		if (temp_opp->available && temp_opp->rate >= *freq) {
@@ -310,6 +323,7 @@ struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
 
 	return opp;
 }
+EXPORT_SYMBOL(opp_find_freq_ceil);
 
 /**
  * opp_find_freq_floor() - Search for a rounded floor freq
@@ -320,7 +334,11 @@ struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
  * for a device.
  *
  * Returns matching *opp and refreshes *freq accordingly, else returns
- * ERR_PTR in case of error and should be handled using IS_ERR.
+ * ERR_PTR in case of error and should be handled using IS_ERR. Error return
+ * values can be:
+ * EINVAL:	for bad pointer
+ * ERANGE:	no match found for search
+ * ENODEV:	if device not found in list of registered devices
  *
  * Locking: This function must be called under rcu_read_lock(). opp is a rcu
  * protected pointer. The reason for the same is that the opp pointer which is
@@ -331,7 +349,7 @@ struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
 struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
 {
 	struct device_opp *dev_opp;
-	struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+	struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
 	if (!dev || !freq) {
 		dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
@@ -340,7 +358,7 @@ struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
 
 	dev_opp = find_device_opp(dev);
 	if (IS_ERR(dev_opp))
-		return opp;
+		return ERR_CAST(dev_opp);
 
 	list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
 		if (temp_opp->available) {
@@ -356,6 +374,7 @@ struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
 
 	return opp;
 }
+EXPORT_SYMBOL(opp_find_freq_floor);
 
 /**
  * opp_add()  - Add an OPP table from a table definitions
@@ -512,7 +531,7 @@ static int opp_set_availability(struct device *dev, unsigned long freq,
 
 	list_replace_rcu(&opp->node, &new_opp->node);
 	mutex_unlock(&dev_opp_list_lock);
-	synchronize_rcu();
+	kfree_rcu(opp, head);
 
 	/* Notify the change of the OPP availability */
 	if (availability_req)
@@ -522,13 +541,10 @@ static int opp_set_availability(struct device *dev, unsigned long freq,
 		srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_DISABLE,
 					 new_opp);
 
-	/* clean up old opp */
-	new_opp = opp;
-	goto out;
+	return 0;
 
 unlock:
 	mutex_unlock(&dev_opp_list_lock);
-out:
 	kfree(new_opp);
 	return r;
 }
@@ -552,6 +568,7 @@ int opp_enable(struct device *dev, unsigned long freq)
 {
 	return opp_set_availability(dev, freq, true);
 }
+EXPORT_SYMBOL(opp_enable);
 
 /**
  * opp_disable() - Disable a specific OPP
@@ -573,6 +590,7 @@ int opp_disable(struct device *dev, unsigned long freq)
 {
 	return opp_set_availability(dev, freq, false);
 }
+EXPORT_SYMBOL(opp_disable);
 
 #ifdef CONFIG_CPU_FREQ
 /**
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 0dbfdf4..b16686a 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -93,8 +93,10 @@ extern void dpm_sysfs_remove(struct device *dev);
 extern void rpm_sysfs_remove(struct device *dev);
 extern int wakeup_sysfs_add(struct device *dev);
 extern void wakeup_sysfs_remove(struct device *dev);
-extern int pm_qos_sysfs_add(struct device *dev);
-extern void pm_qos_sysfs_remove(struct device *dev);
+extern int pm_qos_sysfs_add_latency(struct device *dev);
+extern void pm_qos_sysfs_remove_latency(struct device *dev);
+extern int pm_qos_sysfs_add_flags(struct device *dev);
+extern void pm_qos_sysfs_remove_flags(struct device *dev);
 
 #else /* CONFIG_PM */
 
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c
index fbbd4ed..ff46387 100644
--- a/drivers/base/power/qos.c
+++ b/drivers/base/power/qos.c
@@ -40,6 +40,7 @@
 #include <linux/device.h>
 #include <linux/mutex.h>
 #include <linux/export.h>
+#include <linux/pm_runtime.h>
 
 #include "power.h"
 
@@ -48,6 +49,50 @@ static DEFINE_MUTEX(dev_pm_qos_mtx);
 static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
 
 /**
+ * __dev_pm_qos_flags - Check PM QoS flags for a given device.
+ * @dev: Device to check the PM QoS flags for.
+ * @mask: Flags to check against.
+ *
+ * This routine must be called with dev->power.lock held.
+ */
+enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask)
+{
+	struct dev_pm_qos *qos = dev->power.qos;
+	struct pm_qos_flags *pqf;
+	s32 val;
+
+	if (!qos)
+		return PM_QOS_FLAGS_UNDEFINED;
+
+	pqf = &qos->flags;
+	if (list_empty(&pqf->list))
+		return PM_QOS_FLAGS_UNDEFINED;
+
+	val = pqf->effective_flags & mask;
+	if (val)
+		return (val == mask) ? PM_QOS_FLAGS_ALL : PM_QOS_FLAGS_SOME;
+
+	return PM_QOS_FLAGS_NONE;
+}
+
+/**
+ * dev_pm_qos_flags - Check PM QoS flags for a given device (locked).
+ * @dev: Device to check the PM QoS flags for.
+ * @mask: Flags to check against.
+ */
+enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask)
+{
+	unsigned long irqflags;
+	enum pm_qos_flags_status ret;
+
+	spin_lock_irqsave(&dev->power.lock, irqflags);
+	ret = __dev_pm_qos_flags(dev, mask);
+	spin_unlock_irqrestore(&dev->power.lock, irqflags);
+
+	return ret;
+}
+
+/**
  * __dev_pm_qos_read_value - Get PM QoS constraint for a given device.
  * @dev: Device to get the PM QoS constraint value for.
  *
@@ -55,9 +100,7 @@ static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
  */
 s32 __dev_pm_qos_read_value(struct device *dev)
 {
-	struct pm_qos_constraints *c = dev->power.constraints;
-
-	return c ? pm_qos_read_value(c) : 0;
+	return dev->power.qos ? pm_qos_read_value(&dev->power.qos->latency) : 0;
 }
 
 /**
@@ -76,30 +119,39 @@ s32 dev_pm_qos_read_value(struct device *dev)
 	return ret;
 }
 
-/*
- * apply_constraint
- * @req: constraint request to apply
- * @action: action to perform add/update/remove, of type enum pm_qos_req_action
- * @value: defines the qos request
+/**
+ * apply_constraint - Add/modify/remove device PM QoS request.
+ * @req: Constraint request to apply
+ * @action: Action to perform (add/update/remove).
+ * @value: Value to assign to the QoS request.
  *
  * Internal function to update the constraints list using the PM QoS core
  * code and if needed call the per-device and the global notification
  * callbacks
  */
 static int apply_constraint(struct dev_pm_qos_request *req,
-			    enum pm_qos_req_action action, int value)
+			    enum pm_qos_req_action action, s32 value)
 {
-	int ret, curr_value;
-
-	ret = pm_qos_update_target(req->dev->power.constraints,
-				   &req->node, action, value);
+	struct dev_pm_qos *qos = req->dev->power.qos;
+	int ret;
 
-	if (ret) {
-		/* Call the global callbacks if needed */
-		curr_value = pm_qos_read_value(req->dev->power.constraints);
-		blocking_notifier_call_chain(&dev_pm_notifiers,
-					     (unsigned long)curr_value,
-					     req);
+	switch(req->type) {
+	case DEV_PM_QOS_LATENCY:
+		ret = pm_qos_update_target(&qos->latency, &req->data.pnode,
+					   action, value);
+		if (ret) {
+			value = pm_qos_read_value(&qos->latency);
+			blocking_notifier_call_chain(&dev_pm_notifiers,
+						     (unsigned long)value,
+						     req);
+		}
+		break;
+	case DEV_PM_QOS_FLAGS:
+		ret = pm_qos_update_flags(&qos->flags, &req->data.flr,
+					  action, value);
+		break;
+	default:
+		ret = -EINVAL;
 	}
 
 	return ret;
@@ -114,28 +166,32 @@ static int apply_constraint(struct dev_pm_qos_request *req,
  */
 static int dev_pm_qos_constraints_allocate(struct device *dev)
 {
+	struct dev_pm_qos *qos;
 	struct pm_qos_constraints *c;
 	struct blocking_notifier_head *n;
 
-	c = kzalloc(sizeof(*c), GFP_KERNEL);
-	if (!c)
+	qos = kzalloc(sizeof(*qos), GFP_KERNEL);
+	if (!qos)
 		return -ENOMEM;
 
 	n = kzalloc(sizeof(*n), GFP_KERNEL);
 	if (!n) {
-		kfree(c);
+		kfree(qos);
 		return -ENOMEM;
 	}
 	BLOCKING_INIT_NOTIFIER_HEAD(n);
 
+	c = &qos->latency;
 	plist_head_init(&c->list);
 	c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
 	c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
 	c->type = PM_QOS_MIN;
 	c->notifiers = n;
 
+	INIT_LIST_HEAD(&qos->flags.list);
+
 	spin_lock_irq(&dev->power.lock);
-	dev->power.constraints = c;
+	dev->power.qos = qos;
 	spin_unlock_irq(&dev->power.lock);
 
 	return 0;
@@ -151,7 +207,7 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
 void dev_pm_qos_constraints_init(struct device *dev)
 {
 	mutex_lock(&dev_pm_qos_mtx);
-	dev->power.constraints = NULL;
+	dev->power.qos = NULL;
 	dev->power.power_state = PMSG_ON;
 	mutex_unlock(&dev_pm_qos_mtx);
 }
@@ -164,24 +220,28 @@ void dev_pm_qos_constraints_init(struct device *dev)
  */
 void dev_pm_qos_constraints_destroy(struct device *dev)
 {
+	struct dev_pm_qos *qos;
 	struct dev_pm_qos_request *req, *tmp;
 	struct pm_qos_constraints *c;
+	struct pm_qos_flags *f;
 
 	/*
-	 * If the device's PM QoS resume latency limit has been exposed to user
-	 * space, it has to be hidden at this point.
+	 * If the device's PM QoS resume latency limit or PM QoS flags have been
+	 * exposed to user space, they have to be hidden at this point.
 	 */
 	dev_pm_qos_hide_latency_limit(dev);
+	dev_pm_qos_hide_flags(dev);
 
 	mutex_lock(&dev_pm_qos_mtx);
 
 	dev->power.power_state = PMSG_INVALID;
-	c = dev->power.constraints;
-	if (!c)
+	qos = dev->power.qos;
+	if (!qos)
 		goto out;
 
-	/* Flush the constraints list for the device */
-	plist_for_each_entry_safe(req, tmp, &c->list, node) {
+	/* Flush the constraints lists for the device. */
+	c = &qos->latency;
+	plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
 		/*
 		 * Update constraints list and call the notification
 		 * callbacks if needed
@@ -189,13 +249,18 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
 		apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
 		memset(req, 0, sizeof(*req));
 	}
+	f = &qos->flags;
+	list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) {
+		apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
+		memset(req, 0, sizeof(*req));
+	}
 
 	spin_lock_irq(&dev->power.lock);
-	dev->power.constraints = NULL;
+	dev->power.qos = NULL;
 	spin_unlock_irq(&dev->power.lock);
 
 	kfree(c->notifiers);
-	kfree(c);
+	kfree(qos);
 
  out:
 	mutex_unlock(&dev_pm_qos_mtx);
@@ -205,6 +270,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
  * dev_pm_qos_add_request - inserts new qos request into the list
  * @dev: target device for the constraint
  * @req: pointer to a preallocated handle
+ * @type: type of the request
  * @value: defines the qos request
  *
  * This function inserts a new entry in the device constraints list of
@@ -218,9 +284,12 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
  * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory
  * to allocate for data structures, -ENODEV if the device has just been removed
  * from the system.
+ *
+ * Callers should ensure that the target device is not RPM_SUSPENDED before
+ * using this function for requests of type DEV_PM_QOS_FLAGS.
  */
 int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
-			   s32 value)
+			   enum dev_pm_qos_req_type type, s32 value)
 {
 	int ret = 0;
 
@@ -235,7 +304,7 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
 
 	mutex_lock(&dev_pm_qos_mtx);
 
-	if (!dev->power.constraints) {
+	if (!dev->power.qos) {
 		if (dev->power.power_state.event == PM_EVENT_INVALID) {
 			/* The device has been removed from the system. */
 			req->dev = NULL;
@@ -251,8 +320,10 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
 		}
 	}
 
-	if (!ret)
+	if (!ret) {
+		req->type = type;
 		ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
+	}
 
  out:
 	mutex_unlock(&dev_pm_qos_mtx);
@@ -262,6 +333,37 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
 EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
 
 /**
+ * __dev_pm_qos_update_request - Modify an existing device PM QoS request.
+ * @req : PM QoS request to modify.
+ * @new_value: New value to request.
+ */
+static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req,
+				       s32 new_value)
+{
+	s32 curr_value;
+	int ret = 0;
+
+	if (!req->dev->power.qos)
+		return -ENODEV;
+
+	switch(req->type) {
+	case DEV_PM_QOS_LATENCY:
+		curr_value = req->data.pnode.prio;
+		break;
+	case DEV_PM_QOS_FLAGS:
+		curr_value = req->data.flr.flags;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (curr_value != new_value)
+		ret = apply_constraint(req, PM_QOS_UPDATE_REQ, new_value);
+
+	return ret;
+}
+
+/**
  * dev_pm_qos_update_request - modifies an existing qos request
  * @req : handle to list element holding a dev_pm_qos request to use
  * @new_value: defines the qos request
@@ -275,11 +377,13 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
  * 0 if the aggregated constraint value has not changed,
  * -EINVAL in case of wrong parameters, -ENODEV if the device has been
  * removed from the system
+ *
+ * Callers should ensure that the target device is not RPM_SUSPENDED before
+ * using this function for requests of type DEV_PM_QOS_FLAGS.
  */
-int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
-			      s32 new_value)
+int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value)
 {
-	int ret = 0;
+	int ret;
 
 	if (!req) /*guard against callers passing in null */
 		return -EINVAL;
@@ -289,17 +393,9 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
 		return -EINVAL;
 
 	mutex_lock(&dev_pm_qos_mtx);
-
-	if (req->dev->power.constraints) {
-		if (new_value != req->node.prio)
-			ret = apply_constraint(req, PM_QOS_UPDATE_REQ,
-					       new_value);
-	} else {
-		/* Return if the device has been removed */
-		ret = -ENODEV;
-	}
-
+	ret = __dev_pm_qos_update_request(req, new_value);
 	mutex_unlock(&dev_pm_qos_mtx);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
@@ -315,6 +411,9 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
  * 0 if the aggregated constraint value has not changed,
  * -EINVAL in case of wrong parameters, -ENODEV if the device has been
  * removed from the system
+ *
+ * Callers should ensure that the target device is not RPM_SUSPENDED before
+ * using this function for requests of type DEV_PM_QOS_FLAGS.
  */
 int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
 {
@@ -329,7 +428,7 @@ int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
 
 	mutex_lock(&dev_pm_qos_mtx);
 
-	if (req->dev->power.constraints) {
+	if (req->dev->power.qos) {
 		ret = apply_constraint(req, PM_QOS_REMOVE_REQ,
 				       PM_QOS_DEFAULT_VALUE);
 		memset(req, 0, sizeof(*req));
@@ -362,13 +461,13 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
 
 	mutex_lock(&dev_pm_qos_mtx);
 
-	if (!dev->power.constraints)
+	if (!dev->power.qos)
 		ret = dev->power.power_state.event != PM_EVENT_INVALID ?
 			dev_pm_qos_constraints_allocate(dev) : -ENODEV;
 
 	if (!ret)
 		ret = blocking_notifier_chain_register(
-				dev->power.constraints->notifiers, notifier);
+				dev->power.qos->latency.notifiers, notifier);
 
 	mutex_unlock(&dev_pm_qos_mtx);
 	return ret;
@@ -393,9 +492,9 @@ int dev_pm_qos_remove_notifier(struct device *dev,
 	mutex_lock(&dev_pm_qos_mtx);
 
 	/* Silently return if the constraints object is not present. */
-	if (dev->power.constraints)
+	if (dev->power.qos)
 		retval = blocking_notifier_chain_unregister(
-				dev->power.constraints->notifiers,
+				dev->power.qos->latency.notifiers,
 				notifier);
 
 	mutex_unlock(&dev_pm_qos_mtx);
@@ -449,7 +548,8 @@ int dev_pm_qos_add_ancestor_request(struct device *dev,
 		ancestor = ancestor->parent;
 
 	if (ancestor)
-		error = dev_pm_qos_add_request(ancestor, req, value);
+		error = dev_pm_qos_add_request(ancestor, req,
+					       DEV_PM_QOS_LATENCY, value);
 
 	if (error < 0)
 		req->dev = NULL;
@@ -459,10 +559,19 @@ int dev_pm_qos_add_ancestor_request(struct device *dev,
 EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request);
 
 #ifdef CONFIG_PM_RUNTIME
-static void __dev_pm_qos_drop_user_request(struct device *dev)
+static void __dev_pm_qos_drop_user_request(struct device *dev,
+					   enum dev_pm_qos_req_type type)
 {
-	dev_pm_qos_remove_request(dev->power.pq_req);
-	dev->power.pq_req = NULL;
+	switch(type) {
+	case DEV_PM_QOS_LATENCY:
+		dev_pm_qos_remove_request(dev->power.qos->latency_req);
+		dev->power.qos->latency_req = NULL;
+		break;
+	case DEV_PM_QOS_FLAGS:
+		dev_pm_qos_remove_request(dev->power.qos->flags_req);
+		dev->power.qos->flags_req = NULL;
+		break;
+	}
 }
 
 /**
@@ -478,21 +587,21 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
 	if (!device_is_registered(dev) || value < 0)
 		return -EINVAL;
 
-	if (dev->power.pq_req)
+	if (dev->power.qos && dev->power.qos->latency_req)
 		return -EEXIST;
 
 	req = kzalloc(sizeof(*req), GFP_KERNEL);
 	if (!req)
 		return -ENOMEM;
 
-	ret = dev_pm_qos_add_request(dev, req, value);
+	ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY, value);
 	if (ret < 0)
 		return ret;
 
-	dev->power.pq_req = req;
-	ret = pm_qos_sysfs_add(dev);
+	dev->power.qos->latency_req = req;
+	ret = pm_qos_sysfs_add_latency(dev);
 	if (ret)
-		__dev_pm_qos_drop_user_request(dev);
+		__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
 
 	return ret;
 }
@@ -504,10 +613,92 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit);
  */
 void dev_pm_qos_hide_latency_limit(struct device *dev)
 {
-	if (dev->power.pq_req) {
-		pm_qos_sysfs_remove(dev);
-		__dev_pm_qos_drop_user_request(dev);
+	if (dev->power.qos && dev->power.qos->latency_req) {
+		pm_qos_sysfs_remove_latency(dev);
+		__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
 	}
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit);
+
+/**
+ * dev_pm_qos_expose_flags - Expose PM QoS flags of a device to user space.
+ * @dev: Device whose PM QoS flags are to be exposed to user space.
+ * @val: Initial values of the flags.
+ */
+int dev_pm_qos_expose_flags(struct device *dev, s32 val)
+{
+	struct dev_pm_qos_request *req;
+	int ret;
+
+	if (!device_is_registered(dev))
+		return -EINVAL;
+
+	if (dev->power.qos && dev->power.qos->flags_req)
+		return -EEXIST;
+
+	req = kzalloc(sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	pm_runtime_get_sync(dev);
+	ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_FLAGS, val);
+	if (ret < 0)
+		goto fail;
+
+	dev->power.qos->flags_req = req;
+	ret = pm_qos_sysfs_add_flags(dev);
+	if (ret)
+		__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
+
+fail:
+	pm_runtime_put(dev);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags);
+
+/**
+ * dev_pm_qos_hide_flags - Hide PM QoS flags of a device from user space.
+ * @dev: Device whose PM QoS flags are to be hidden from user space.
+ */
+void dev_pm_qos_hide_flags(struct device *dev)
+{
+	if (dev->power.qos && dev->power.qos->flags_req) {
+		pm_qos_sysfs_remove_flags(dev);
+		pm_runtime_get_sync(dev);
+		__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
+		pm_runtime_put(dev);
+	}
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags);
+
+/**
+ * dev_pm_qos_update_flags - Update PM QoS flags request owned by user space.
+ * @dev: Device to update the PM QoS flags request for.
+ * @mask: Flags to set/clear.
+ * @set: Whether to set or clear the flags (true means set).
+ */
+int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set)
+{
+	s32 value;
+	int ret;
+
+	if (!dev->power.qos || !dev->power.qos->flags_req)
+		return -EINVAL;
+
+	pm_runtime_get_sync(dev);
+	mutex_lock(&dev_pm_qos_mtx);
+
+	value = dev_pm_qos_requested_flags(dev);
+	if (set)
+		value |= mask;
+	else
+		value &= ~mask;
+
+	ret = __dev_pm_qos_update_request(dev->power.qos->flags_req, value);
+
+	mutex_unlock(&dev_pm_qos_mtx);
+	pm_runtime_put(dev);
+
+	return ret;
+}
 #endif /* CONFIG_PM_RUNTIME */
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index b91dc6f..50d16e3 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -221,7 +221,7 @@ static DEVICE_ATTR(autosuspend_delay_ms, 0644, autosuspend_delay_ms_show,
 static ssize_t pm_qos_latency_show(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%d\n", dev->power.pq_req->node.prio);
+	return sprintf(buf, "%d\n", dev_pm_qos_requested_latency(dev));
 }
 
 static ssize_t pm_qos_latency_store(struct device *dev,
@@ -237,12 +237,66 @@ static ssize_t pm_qos_latency_store(struct device *dev,
 	if (value < 0)
 		return -EINVAL;
 
-	ret = dev_pm_qos_update_request(dev->power.pq_req, value);
+	ret = dev_pm_qos_update_request(dev->power.qos->latency_req, value);
 	return ret < 0 ? ret : n;
 }
 
 static DEVICE_ATTR(pm_qos_resume_latency_us, 0644,
 		   pm_qos_latency_show, pm_qos_latency_store);
+
+static ssize_t pm_qos_no_power_off_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	return sprintf(buf, "%d\n", !!(dev_pm_qos_requested_flags(dev)
+					& PM_QOS_FLAG_NO_POWER_OFF));
+}
+
+static ssize_t pm_qos_no_power_off_store(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t n)
+{
+	int ret;
+
+	if (kstrtoint(buf, 0, &ret))
+		return -EINVAL;
+
+	if (ret != 0 && ret != 1)
+		return -EINVAL;
+
+	ret = dev_pm_qos_update_flags(dev, PM_QOS_FLAG_NO_POWER_OFF, ret);
+	return ret < 0 ? ret : n;
+}
+
+static DEVICE_ATTR(pm_qos_no_power_off, 0644,
+		   pm_qos_no_power_off_show, pm_qos_no_power_off_store);
+
+static ssize_t pm_qos_remote_wakeup_show(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	return sprintf(buf, "%d\n", !!(dev_pm_qos_requested_flags(dev)
+					& PM_QOS_FLAG_REMOTE_WAKEUP));
+}
+
+static ssize_t pm_qos_remote_wakeup_store(struct device *dev,
+					  struct device_attribute *attr,
+					  const char *buf, size_t n)
+{
+	int ret;
+
+	if (kstrtoint(buf, 0, &ret))
+		return -EINVAL;
+
+	if (ret != 0 && ret != 1)
+		return -EINVAL;
+
+	ret = dev_pm_qos_update_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP, ret);
+	return ret < 0 ? ret : n;
+}
+
+static DEVICE_ATTR(pm_qos_remote_wakeup, 0644,
+		   pm_qos_remote_wakeup_show, pm_qos_remote_wakeup_store);
 #endif /* CONFIG_PM_RUNTIME */
 
 #ifdef CONFIG_PM_SLEEP
@@ -564,15 +618,27 @@ static struct attribute_group pm_runtime_attr_group = {
 	.attrs	= runtime_attrs,
 };
 
-static struct attribute *pm_qos_attrs[] = {
+static struct attribute *pm_qos_latency_attrs[] = {
 #ifdef CONFIG_PM_RUNTIME
 	&dev_attr_pm_qos_resume_latency_us.attr,
 #endif /* CONFIG_PM_RUNTIME */
 	NULL,
 };
-static struct attribute_group pm_qos_attr_group = {
+static struct attribute_group pm_qos_latency_attr_group = {
 	.name	= power_group_name,
-	.attrs	= pm_qos_attrs,
+	.attrs	= pm_qos_latency_attrs,
+};
+
+static struct attribute *pm_qos_flags_attrs[] = {
+#ifdef CONFIG_PM_RUNTIME
+	&dev_attr_pm_qos_no_power_off.attr,
+	&dev_attr_pm_qos_remote_wakeup.attr,
+#endif /* CONFIG_PM_RUNTIME */
+	NULL,
+};
+static struct attribute_group pm_qos_flags_attr_group = {
+	.name	= power_group_name,
+	.attrs	= pm_qos_flags_attrs,
 };
 
 int dpm_sysfs_add(struct device *dev)
@@ -615,14 +681,24 @@ void wakeup_sysfs_remove(struct device *dev)
 	sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
 }
 
-int pm_qos_sysfs_add(struct device *dev)
+int pm_qos_sysfs_add_latency(struct device *dev)
+{
+	return sysfs_merge_group(&dev->kobj, &pm_qos_latency_attr_group);
+}
+
+void pm_qos_sysfs_remove_latency(struct device *dev)
+{
+	sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_attr_group);
+}
+
+int pm_qos_sysfs_add_flags(struct device *dev)
 {
-	return sysfs_merge_group(&dev->kobj, &pm_qos_attr_group);
+	return sysfs_merge_group(&dev->kobj, &pm_qos_flags_attr_group);
 }
 
-void pm_qos_sysfs_remove(struct device *dev)
+void pm_qos_sysfs_remove_flags(struct device *dev)
 {
-	sysfs_unmerge_group(&dev->kobj, &pm_qos_attr_group);
+	sysfs_unmerge_group(&dev->kobj, &pm_qos_flags_attr_group);
 }
 
 void rpm_sysfs_remove(struct device *dev)
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 80f9ab9..288e135 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -31,14 +31,12 @@ struct regmap_format {
 	unsigned int (*parse_val)(void *buf);
 };
 
-typedef void (*regmap_lock)(struct regmap *map);
-typedef void (*regmap_unlock)(struct regmap *map);
-
 struct regmap {
 	struct mutex mutex;
 	spinlock_t spinlock;
 	regmap_lock lock;
 	regmap_unlock unlock;
+	void *lock_arg; /* This is passed to lock/unlock functions */
 
 	struct device *dev; /* Device we do I/O on */
 	void *work_buf;     /* Scratch buffer used to format I/O */
@@ -57,6 +55,10 @@ struct regmap {
 	bool (*readable_reg)(struct device *dev, unsigned int reg);
 	bool (*volatile_reg)(struct device *dev, unsigned int reg);
 	bool (*precious_reg)(struct device *dev, unsigned int reg);
+	const struct regmap_access_table *wr_table;
+	const struct regmap_access_table *rd_table;
+	const struct regmap_access_table *volatile_table;
+	const struct regmap_access_table *precious_table;
 
 	u8 read_flag_mask;
 	u8 write_flag_mask;
@@ -120,6 +122,8 @@ int _regmap_write(struct regmap *map, unsigned int reg,
 
 struct regmap_range_node {
 	struct rb_node node;
+	const char *name;
+	struct regmap *map;
 
 	unsigned int range_min;
 	unsigned int range_max;
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index bb1ff17..f4b9dd0 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -56,15 +56,15 @@ static const struct file_operations regmap_name_fops = {
 	.llseek = default_llseek,
 };
 
-static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
-				    size_t count, loff_t *ppos)
+static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from,
+				   unsigned int to, char __user *user_buf,
+				   size_t count, loff_t *ppos)
 {
 	int reg_len, val_len, tot_len;
 	size_t buf_pos = 0;
 	loff_t p = 0;
 	ssize_t ret;
 	int i;
-	struct regmap *map = file->private_data;
 	char *buf;
 	unsigned int val;
 
@@ -80,7 +80,7 @@ static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
 	val_len = 2 * map->format.val_bytes;
 	tot_len = reg_len + val_len + 3;      /* : \n */
 
-	for (i = 0; i <= map->max_register; i += map->reg_stride) {
+	for (i = from; i <= to; i += map->reg_stride) {
 		if (!regmap_readable(map, i))
 			continue;
 
@@ -95,7 +95,7 @@ static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
 
 			/* Format the register */
 			snprintf(buf + buf_pos, count - buf_pos, "%.*x: ",
-				 reg_len, i);
+				 reg_len, i - from);
 			buf_pos += reg_len + 2;
 
 			/* Format the value, write all X if we can't read */
@@ -126,6 +126,15 @@ out:
 	return ret;
 }
 
+static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	struct regmap *map = file->private_data;
+
+	return regmap_read_debugfs(map, 0, map->max_register, user_buf,
+				   count, ppos);
+}
+
 #undef REGMAP_ALLOW_WRITE_DEBUGFS
 #ifdef REGMAP_ALLOW_WRITE_DEBUGFS
 /*
@@ -174,6 +183,22 @@ static const struct file_operations regmap_map_fops = {
 	.llseek = default_llseek,
 };
 
+static ssize_t regmap_range_read_file(struct file *file, char __user *user_buf,
+				      size_t count, loff_t *ppos)
+{
+	struct regmap_range_node *range = file->private_data;
+	struct regmap *map = range->map;
+
+	return regmap_read_debugfs(map, range->range_min, range->range_max,
+				   user_buf, count, ppos);
+}
+
+static const struct file_operations regmap_range_fops = {
+	.open = simple_open,
+	.read = regmap_range_read_file,
+	.llseek = default_llseek,
+};
+
 static ssize_t regmap_access_read_file(struct file *file,
 				       char __user *user_buf, size_t count,
 				       loff_t *ppos)
@@ -244,6 +269,9 @@ static const struct file_operations regmap_access_fops = {
 
 void regmap_debugfs_init(struct regmap *map, const char *name)
 {
+	struct rb_node *next;
+	struct regmap_range_node *range_node;
+
 	if (name) {
 		map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s",
 					      dev_name(map->dev), name);
@@ -276,6 +304,18 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
 		debugfs_create_bool("cache_bypass", 0400, map->debugfs,
 				    &map->cache_bypass);
 	}
+
+	next = rb_first(&map->range_tree);
+	while (next) {
+		range_node = rb_entry(next, struct regmap_range_node, node);
+
+		if (range_node->name)
+			debugfs_create_file(range_node->name, 0400,
+					    map->debugfs, range_node,
+					    &regmap_range_fops);
+
+		next = rb_next(&range_node->node);
+	}
 }
 
 void regmap_debugfs_exit(struct regmap *map)
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 5b6b1d8..5972ad9 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -458,3 +458,22 @@ int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq)
 	return irq_create_mapping(data->domain, irq);
 }
 EXPORT_SYMBOL_GPL(regmap_irq_get_virq);
+
+/**
+ * regmap_irq_get_domain(): Retrieve the irq_domain for the chip
+ *
+ * Useful for drivers to request their own IRQs and for integration
+ * with subsystems.  For ease of integration NULL is accepted as a
+ * domain, allowing devices to just call this even if no domain is
+ * allocated.
+ *
+ * @data: regmap_irq controller to operate on.
+ */
+struct irq_domain *regmap_irq_get_domain(struct regmap_irq_chip_data *data)
+{
+	if (data)
+		return data->domain;
+	else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(regmap_irq_get_domain);
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 52069d2..42d5cb0 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -34,6 +34,36 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
 			       unsigned int mask, unsigned int val,
 			       bool *change);
 
+bool regmap_reg_in_ranges(unsigned int reg,
+			  const struct regmap_range *ranges,
+			  unsigned int nranges)
+{
+	const struct regmap_range *r;
+	int i;
+
+	for (i = 0, r = ranges; i < nranges; i++, r++)
+		if (regmap_reg_in_range(reg, r))
+			return true;
+	return false;
+}
+EXPORT_SYMBOL_GPL(regmap_reg_in_ranges);
+
+static bool _regmap_check_range_table(struct regmap *map,
+				      unsigned int reg,
+				      const struct regmap_access_table *table)
+{
+	/* Check "no ranges" first */
+	if (regmap_reg_in_ranges(reg, table->no_ranges, table->n_no_ranges))
+		return false;
+
+	/* In case zero "yes ranges" are supplied, any reg is OK */
+	if (!table->n_yes_ranges)
+		return true;
+
+	return regmap_reg_in_ranges(reg, table->yes_ranges,
+				    table->n_yes_ranges);
+}
+
 bool regmap_writeable(struct regmap *map, unsigned int reg)
 {
 	if (map->max_register && reg > map->max_register)
@@ -42,6 +72,9 @@ bool regmap_writeable(struct regmap *map, unsigned int reg)
 	if (map->writeable_reg)
 		return map->writeable_reg(map->dev, reg);
 
+	if (map->wr_table)
+		return _regmap_check_range_table(map, reg, map->wr_table);
+
 	return true;
 }
 
@@ -56,6 +89,9 @@ bool regmap_readable(struct regmap *map, unsigned int reg)
 	if (map->readable_reg)
 		return map->readable_reg(map->dev, reg);
 
+	if (map->rd_table)
+		return _regmap_check_range_table(map, reg, map->rd_table);
+
 	return true;
 }
 
@@ -67,6 +103,9 @@ bool regmap_volatile(struct regmap *map, unsigned int reg)
 	if (map->volatile_reg)
 		return map->volatile_reg(map->dev, reg);
 
+	if (map->volatile_table)
+		return _regmap_check_range_table(map, reg, map->volatile_table);
+
 	return true;
 }
 
@@ -78,11 +117,14 @@ bool regmap_precious(struct regmap *map, unsigned int reg)
 	if (map->precious_reg)
 		return map->precious_reg(map->dev, reg);
 
+	if (map->precious_table)
+		return _regmap_check_range_table(map, reg, map->precious_table);
+
 	return false;
 }
 
 static bool regmap_volatile_range(struct regmap *map, unsigned int reg,
-	unsigned int num)
+	size_t num)
 {
 	unsigned int i;
 
@@ -214,23 +256,27 @@ static unsigned int regmap_parse_32_native(void *buf)
 	return *(u32 *)buf;
 }
 
-static void regmap_lock_mutex(struct regmap *map)
+static void regmap_lock_mutex(void *__map)
 {
+	struct regmap *map = __map;
 	mutex_lock(&map->mutex);
 }
 
-static void regmap_unlock_mutex(struct regmap *map)
+static void regmap_unlock_mutex(void *__map)
 {
+	struct regmap *map = __map;
 	mutex_unlock(&map->mutex);
 }
 
-static void regmap_lock_spinlock(struct regmap *map)
+static void regmap_lock_spinlock(void *__map)
 {
+	struct regmap *map = __map;
 	spin_lock(&map->spinlock);
 }
 
-static void regmap_unlock_spinlock(struct regmap *map)
+static void regmap_unlock_spinlock(void *__map)
 {
+	struct regmap *map = __map;
 	spin_unlock(&map->spinlock);
 }
 
@@ -335,14 +381,21 @@ struct regmap *regmap_init(struct device *dev,
 		goto err;
 	}
 
-	if (bus->fast_io) {
-		spin_lock_init(&map->spinlock);
-		map->lock = regmap_lock_spinlock;
-		map->unlock = regmap_unlock_spinlock;
+	if (config->lock && config->unlock) {
+		map->lock = config->lock;
+		map->unlock = config->unlock;
+		map->lock_arg = config->lock_arg;
 	} else {
-		mutex_init(&map->mutex);
-		map->lock = regmap_lock_mutex;
-		map->unlock = regmap_unlock_mutex;
+		if (bus->fast_io) {
+			spin_lock_init(&map->spinlock);
+			map->lock = regmap_lock_spinlock;
+			map->unlock = regmap_unlock_spinlock;
+		} else {
+			mutex_init(&map->mutex);
+			map->lock = regmap_lock_mutex;
+			map->unlock = regmap_unlock_mutex;
+		}
+		map->lock_arg = map;
 	}
 	map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8);
 	map->format.pad_bytes = config->pad_bits / 8;
@@ -359,6 +412,10 @@ struct regmap *regmap_init(struct device *dev,
 	map->bus = bus;
 	map->bus_context = bus_context;
 	map->max_register = config->max_register;
+	map->wr_table = config->wr_table;
+	map->rd_table = config->rd_table;
+	map->volatile_table = config->volatile_table;
+	map->precious_table = config->precious_table;
 	map->writeable_reg = config->writeable_reg;
 	map->readable_reg = config->readable_reg;
 	map->volatile_reg = config->volatile_reg;
@@ -519,20 +576,38 @@ struct regmap *regmap_init(struct device *dev,
 	}
 
 	map->range_tree = RB_ROOT;
-	for (i = 0; i < config->n_ranges; i++) {
+	for (i = 0; i < config->num_ranges; i++) {
 		const struct regmap_range_cfg *range_cfg = &config->ranges[i];
 		struct regmap_range_node *new;
 
 		/* Sanity check */
-		if (range_cfg->range_max < range_cfg->range_min ||
-		    range_cfg->range_max > map->max_register ||
-		    range_cfg->selector_reg > map->max_register ||
-		    range_cfg->window_len == 0)
+		if (range_cfg->range_max < range_cfg->range_min) {
+			dev_err(map->dev, "Invalid range %d: %d < %d\n", i,
+				range_cfg->range_max, range_cfg->range_min);
+			goto err_range;
+		}
+
+		if (range_cfg->range_max > map->max_register) {
+			dev_err(map->dev, "Invalid range %d: %d > %d\n", i,
+				range_cfg->range_max, map->max_register);
+			goto err_range;
+		}
+
+		if (range_cfg->selector_reg > map->max_register) {
+			dev_err(map->dev,
+				"Invalid range %d: selector out of map\n", i);
+			goto err_range;
+		}
+
+		if (range_cfg->window_len == 0) {
+			dev_err(map->dev, "Invalid range %d: window_len 0\n",
+				i);
 			goto err_range;
+		}
 
 		/* Make sure, that this register range has no selector
 		   or data window within its boundary */
-		for (j = 0; j < config->n_ranges; j++) {
+		for (j = 0; j < config->num_ranges; j++) {
 			unsigned sel_reg = config->ranges[j].selector_reg;
 			unsigned win_min = config->ranges[j].window_start;
 			unsigned win_max = win_min +
@@ -540,11 +615,17 @@ struct regmap *regmap_init(struct device *dev,
 
 			if (range_cfg->range_min <= sel_reg &&
 			    sel_reg <= range_cfg->range_max) {
+				dev_err(map->dev,
+					"Range %d: selector for %d in window\n",
+					i, j);
 				goto err_range;
 			}
 
 			if (!(win_max < range_cfg->range_min ||
 			      win_min > range_cfg->range_max)) {
+				dev_err(map->dev,
+					"Range %d: window for %d in window\n",
+					i, j);
 				goto err_range;
 			}
 		}
@@ -555,6 +636,8 @@ struct regmap *regmap_init(struct device *dev,
 			goto err_range;
 		}
 
+		new->map = map;
+		new->name = range_cfg->name;
 		new->range_min = range_cfg->range_min;
 		new->range_max = range_cfg->range_max;
 		new->selector_reg = range_cfg->selector_reg;
@@ -564,6 +647,7 @@ struct regmap *regmap_init(struct device *dev,
 		new->window_len = range_cfg->window_len;
 
 		if (_regmap_range_add(map, new) == false) {
+			dev_err(map->dev, "Failed to add range %d\n", i);
 			kfree(new);
 			goto err_range;
 		}
@@ -579,7 +663,7 @@ struct regmap *regmap_init(struct device *dev,
 	}
 
 	ret = regcache_init(map, config);
-	if (ret < 0)
+	if (ret != 0)
 		goto err_range;
 
 	regmap_debugfs_init(map, config->name);
@@ -738,59 +822,57 @@ struct regmap *dev_get_regmap(struct device *dev, const char *name)
 EXPORT_SYMBOL_GPL(dev_get_regmap);
 
 static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+			       struct regmap_range_node *range,
 			       unsigned int val_num)
 {
-	struct regmap_range_node *range;
 	void *orig_work_buf;
 	unsigned int win_offset;
 	unsigned int win_page;
 	bool page_chg;
 	int ret;
 
-	range = _regmap_range_lookup(map, *reg);
-	if (range) {
-		win_offset = (*reg - range->range_min) % range->window_len;
-		win_page = (*reg - range->range_min) / range->window_len;
-
-		if (val_num > 1) {
-			/* Bulk write shouldn't cross range boundary */
-			if (*reg + val_num - 1 > range->range_max)
-				return -EINVAL;
+	win_offset = (*reg - range->range_min) % range->window_len;
+	win_page = (*reg - range->range_min) / range->window_len;
 
-			/* ... or single page boundary */
-			if (val_num > range->window_len - win_offset)
-				return -EINVAL;
-		}
+	if (val_num > 1) {
+		/* Bulk write shouldn't cross range boundary */
+		if (*reg + val_num - 1 > range->range_max)
+			return -EINVAL;
 
-		/* It is possible to have selector register inside data window.
-		   In that case, selector register is located on every page and
-		   it needs no page switching, when accessed alone. */
-		if (val_num > 1 ||
-		    range->window_start + win_offset != range->selector_reg) {
-			/* Use separate work_buf during page switching */
-			orig_work_buf = map->work_buf;
-			map->work_buf = map->selector_work_buf;
+		/* ... or single page boundary */
+		if (val_num > range->window_len - win_offset)
+			return -EINVAL;
+	}
 
-			ret = _regmap_update_bits(map, range->selector_reg,
-					range->selector_mask,
-					win_page << range->selector_shift,
-					&page_chg);
+	/* It is possible to have selector register inside data window.
+	   In that case, selector register is located on every page and
+	   it needs no page switching, when accessed alone. */
+	if (val_num > 1 ||
+	    range->window_start + win_offset != range->selector_reg) {
+		/* Use separate work_buf during page switching */
+		orig_work_buf = map->work_buf;
+		map->work_buf = map->selector_work_buf;
 
-			map->work_buf = orig_work_buf;
+		ret = _regmap_update_bits(map, range->selector_reg,
+					  range->selector_mask,
+					  win_page << range->selector_shift,
+					  &page_chg);
 
-			if (ret < 0)
-				return ret;
-		}
+		map->work_buf = orig_work_buf;
 
-		*reg = range->window_start + win_offset;
+		if (ret != 0)
+			return ret;
 	}
 
+	*reg = range->window_start + win_offset;
+
 	return 0;
 }
 
 static int _regmap_raw_write(struct regmap *map, unsigned int reg,
 			     const void *val, size_t val_len)
 {
+	struct regmap_range_node *range;
 	u8 *u8 = map->work_buf;
 	void *buf;
 	int ret = -ENOTSUPP;
@@ -814,7 +896,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
 					     ival);
 			if (ret) {
 				dev_err(map->dev,
-				   "Error in caching of register: %u ret: %d\n",
+					"Error in caching of register: %x ret: %d\n",
 					reg + i, ret);
 				return ret;
 			}
@@ -825,9 +907,35 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
 		}
 	}
 
-	ret = _regmap_select_page(map, &reg, val_len / map->format.val_bytes);
-	if (ret < 0)
-		return ret;
+	range = _regmap_range_lookup(map, reg);
+	if (range) {
+		int val_num = val_len / map->format.val_bytes;
+		int win_offset = (reg - range->range_min) % range->window_len;
+		int win_residue = range->window_len - win_offset;
+
+		/* If the write goes beyond the end of the window split it */
+		while (val_num > win_residue) {
+			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);
+			if (ret != 0)
+				return ret;
+
+			reg += win_residue;
+			val_num -= win_residue;
+			val += win_residue * map->format.val_bytes;
+			val_len -= win_residue * map->format.val_bytes;
+
+			win_offset = (reg - range->range_min) %
+				range->window_len;
+			win_residue = range->window_len - win_offset;
+		}
+
+		ret = _regmap_select_page(map, &reg, range, val_num);
+		if (ret != 0)
+			return ret;
+	}
 
 	map->format.format_reg(map->work_buf, reg, map->reg_shift);
 
@@ -876,6 +984,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
 int _regmap_write(struct regmap *map, unsigned int reg,
 		  unsigned int val)
 {
+	struct regmap_range_node *range;
 	int ret;
 	BUG_ON(!map->format.format_write && !map->format.format_val);
 
@@ -897,9 +1006,12 @@ int _regmap_write(struct regmap *map, unsigned int reg,
 	trace_regmap_reg_write(map->dev, reg, val);
 
 	if (map->format.format_write) {
-		ret = _regmap_select_page(map, &reg, 1);
-		if (ret < 0)
-			return ret;
+		range = _regmap_range_lookup(map, reg);
+		if (range) {
+			ret = _regmap_select_page(map, &reg, range, 1);
+			if (ret != 0)
+				return ret;
+		}
 
 		map->format.format_write(map, reg, val);
 
@@ -939,11 +1051,11 @@ int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)
 	if (reg % map->reg_stride)
 		return -EINVAL;
 
-	map->lock(map);
+	map->lock(map->lock_arg);
 
 	ret = _regmap_write(map, reg, val);
 
-	map->unlock(map);
+	map->unlock(map->lock_arg);
 
 	return ret;
 }
@@ -975,11 +1087,11 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
 	if (reg % map->reg_stride)
 		return -EINVAL;
 
-	map->lock(map);
+	map->lock(map->lock_arg);
 
 	ret = _regmap_raw_write(map, reg, val, val_len);
 
-	map->unlock(map);
+	map->unlock(map->lock_arg);
 
 	return ret;
 }
@@ -1011,7 +1123,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
 	if (reg % map->reg_stride)
 		return -EINVAL;
 
-	map->lock(map);
+	map->lock(map->lock_arg);
 
 	/* No formatting is require if val_byte is 1 */
 	if (val_bytes == 1) {
@@ -1047,7 +1159,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
 		kfree(wval);
 
 out:
-	map->unlock(map);
+	map->unlock(map->lock_arg);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(regmap_bulk_write);
@@ -1055,12 +1167,17 @@ EXPORT_SYMBOL_GPL(regmap_bulk_write);
 static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
 			    unsigned int val_len)
 {
+	struct regmap_range_node *range;
 	u8 *u8 = map->work_buf;
 	int ret;
 
-	ret = _regmap_select_page(map, &reg, val_len / map->format.val_bytes);
-	if (ret < 0)
-		return ret;
+	range = _regmap_range_lookup(map, reg);
+	if (range) {
+		ret = _regmap_select_page(map, &reg, range,
+					  val_len / map->format.val_bytes);
+		if (ret != 0)
+			return ret;
+	}
 
 	map->format.format_reg(map->work_buf, reg, map->reg_shift);
 
@@ -1137,11 +1254,11 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
 	if (reg % map->reg_stride)
 		return -EINVAL;
 
-	map->lock(map);
+	map->lock(map->lock_arg);
 
 	ret = _regmap_read(map, reg, val);
 
-	map->unlock(map);
+	map->unlock(map->lock_arg);
 
 	return ret;
 }
@@ -1171,7 +1288,7 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
 	if (reg % map->reg_stride)
 		return -EINVAL;
 
-	map->lock(map);
+	map->lock(map->lock_arg);
 
 	if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass ||
 	    map->cache_type == REGCACHE_NONE) {
@@ -1193,7 +1310,7 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
 	}
 
  out:
-	map->unlock(map);
+	map->unlock(map->lock_arg);
 
 	return ret;
 }
@@ -1300,9 +1417,9 @@ int regmap_update_bits(struct regmap *map, unsigned int reg,
 	bool change;
 	int ret;
 
-	map->lock(map);
+	map->lock(map->lock_arg);
 	ret = _regmap_update_bits(map, reg, mask, val, &change);
-	map->unlock(map);
+	map->unlock(map->lock_arg);
 
 	return ret;
 }
@@ -1326,9 +1443,9 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
 {
 	int ret;
 
-	map->lock(map);
+	map->lock(map->lock_arg);
 	ret = _regmap_update_bits(map, reg, mask, val, change);
-	map->unlock(map);
+	map->unlock(map->lock_arg);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(regmap_update_bits_check);
@@ -1357,7 +1474,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
 	if (map->patch)
 		return -EBUSY;
 
-	map->lock(map);
+	map->lock(map->lock_arg);
 
 	bypass = map->cache_bypass;
 
@@ -1385,7 +1502,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
 out:
 	map->cache_bypass = bypass;
 
-	map->unlock(map);
+	map->unlock(map->lock_arg);
 
 	return ret;
 }
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index a533af2..d7b56a8 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -65,6 +65,15 @@ config BCMA_DRIVER_GMAC_CMN
 
 	  If unsure, say N
 
+config BCMA_DRIVER_GPIO
+	bool "BCMA GPIO driver"
+	depends on BCMA
+	select GPIOLIB
+	help
+	  Driver to provide access to the GPIO pins of the bcma bus.
+
+	  If unsure, say N
+
 config BCMA_DEBUG
 	bool "BCMA debugging"
 	depends on BCMA
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile
index 8ad42d4..734b32f 100644
--- a/drivers/bcma/Makefile
+++ b/drivers/bcma/Makefile
@@ -6,6 +6,7 @@ bcma-y					+= driver_pci.o
 bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE)	+= driver_pci_host.o
 bcma-$(CONFIG_BCMA_DRIVER_MIPS)		+= driver_mips.o
 bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN)	+= driver_gmac_cmn.o
+bcma-$(CONFIG_BCMA_DRIVER_GPIO)		+= driver_gpio.o
 bcma-$(CONFIG_BCMA_HOST_PCI)		+= host_pci.o
 bcma-$(CONFIG_BCMA_HOST_SOC)		+= host_soc.o
 obj-$(CONFIG_BCMA)			+= bcma.o
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index 169fc58..8cd80bf 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -89,4 +89,14 @@ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc);
 void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
 #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
 
+#ifdef CONFIG_BCMA_DRIVER_GPIO
+/* driver_gpio.c */
+int bcma_gpio_init(struct bcma_drv_cc *cc);
+#else
+static inline int bcma_gpio_init(struct bcma_drv_cc *cc)
+{
+	return -ENOTSUPP;
+}
+#endif /* CONFIG_BCMA_DRIVER_GPIO */
+
 #endif
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index a4c3ebc..51e22b4 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -22,20 +22,35 @@ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
 	return value;
 }
 
-void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
+void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
 {
-	u32 leddc_on = 10;
-	u32 leddc_off = 90;
-
-	if (cc->setup_done)
+	if (cc->early_setup_done)
 		return;
 
+	spin_lock_init(&cc->gpio_lock);
+
 	if (cc->core->id.rev >= 11)
 		cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
 	cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
 	if (cc->core->id.rev >= 35)
 		cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT);
 
+	if (cc->capabilities & BCMA_CC_CAP_PMU)
+		bcma_pmu_early_init(cc);
+
+	cc->early_setup_done = true;
+}
+
+void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
+{
+	u32 leddc_on = 10;
+	u32 leddc_off = 90;
+
+	if (cc->setup_done)
+		return;
+
+	bcma_core_chipcommon_early_init(cc);
+
 	if (cc->core->id.rev >= 20) {
 		bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0);
 		bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0);
@@ -84,28 +99,97 @@ u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask)
 
 u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value)
 {
-	return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
+	unsigned long flags;
+	u32 res;
+
+	spin_lock_irqsave(&cc->gpio_lock, flags);
+	res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
+	spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+	return res;
 }
 
 u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
 {
-	return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
+	unsigned long flags;
+	u32 res;
+
+	spin_lock_irqsave(&cc->gpio_lock, flags);
+	res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
+	spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+	return res;
 }
 
+/*
+ * If the bit is set to 0, chipcommon controlls this GPIO,
+ * if the bit is set to 1, it is used by some part of the chip and not our code.
+ */
 u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value)
 {
-	return bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
+	unsigned long flags;
+	u32 res;
+
+	spin_lock_irqsave(&cc->gpio_lock, flags);
+	res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
+	spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+	return res;
 }
 EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control);
 
 u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value)
 {
-	return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
+	unsigned long flags;
+	u32 res;
+
+	spin_lock_irqsave(&cc->gpio_lock, flags);
+	res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
+	spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+	return res;
 }
 
 u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
 {
-	return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
+	unsigned long flags;
+	u32 res;
+
+	spin_lock_irqsave(&cc->gpio_lock, flags);
+	res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
+	spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+	return res;
+}
+
+u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value)
+{
+	unsigned long flags;
+	u32 res;
+
+	if (cc->core->id.rev < 20)
+		return 0;
+
+	spin_lock_irqsave(&cc->gpio_lock, flags);
+	res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLUP, mask, value);
+	spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+	return res;
+}
+
+u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value)
+{
+	unsigned long flags;
+	u32 res;
+
+	if (cc->core->id.rev < 20)
+		return 0;
+
+	spin_lock_irqsave(&cc->gpio_lock, flags);
+	res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLDOWN, mask, value);
+	spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+	return res;
 }
 
 #ifdef CONFIG_BCMA_DRIVER_MIPS
diff --git a/drivers/bcma/driver_chipcommon_nflash.c b/drivers/bcma/driver_chipcommon_nflash.c
index 9042781..dbda91e 100644
--- a/drivers/bcma/driver_chipcommon_nflash.c
+++ b/drivers/bcma/driver_chipcommon_nflash.c
@@ -32,6 +32,9 @@ int bcma_nflash_init(struct bcma_drv_cc *cc)
 	}
 
 	cc->nflash.present = true;
+	if (cc->core->id.rev == 38 &&
+	    (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT))
+		cc->nflash.boot = true;
 
 	/* Prepare platform device, but don't register it yet. It's too early,
 	 * malloc (required by device_private_init) is not available yet. */
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index 201faf1..e0abb38 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -13,12 +13,13 @@
 #include <linux/export.h>
 #include <linux/bcma/bcma.h>
 
-static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
+u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
 {
 	bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
 	bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
 	return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
 }
+EXPORT_SYMBOL_GPL(bcma_chipco_pll_read);
 
 void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value)
 {
@@ -144,7 +145,7 @@ static void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
 	}
 }
 
-void bcma_pmu_init(struct bcma_drv_cc *cc)
+void bcma_pmu_early_init(struct bcma_drv_cc *cc)
 {
 	u32 pmucap;
 
@@ -153,7 +154,10 @@ void bcma_pmu_init(struct bcma_drv_cc *cc)
 
 	bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n",
 		   cc->pmu.rev, pmucap);
+}
 
+void bcma_pmu_init(struct bcma_drv_cc *cc)
+{
 	if (cc->pmu.rev == 1)
 		bcma_cc_mask32(cc, BCMA_CC_PMU_CTL,
 			      ~BCMA_CC_PMU_CTL_NOILPONW);
diff --git a/drivers/bcma/driver_chipcommon_sflash.c b/drivers/bcma/driver_chipcommon_sflash.c
index 2c4eec2..63e6883 100644
--- a/drivers/bcma/driver_chipcommon_sflash.c
+++ b/drivers/bcma/driver_chipcommon_sflash.c
@@ -12,7 +12,7 @@
 
 static struct resource bcma_sflash_resource = {
 	.name	= "bcma_sflash",
-	.start	= BCMA_SFLASH,
+	.start	= BCMA_SOC_FLASH2,
 	.end	= 0,
 	.flags  = IORESOURCE_MEM | IORESOURCE_READONLY,
 };
@@ -31,15 +31,42 @@ struct bcma_sflash_tbl_e {
 };
 
 static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = {
-	{ "", 0x14, 0x10000, 32, },
+	{ "M25P20", 0x11, 0x10000, 4, },
+	{ "M25P40", 0x12, 0x10000, 8, },
+
+	{ "M25P16", 0x14, 0x10000, 32, },
+	{ "M25P32", 0x14, 0x10000, 64, },
+	{ "M25P64", 0x16, 0x10000, 128, },
+	{ "M25FL128", 0x17, 0x10000, 256, },
 	{ 0 },
 };
 
 static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
+	{ "SST25WF512", 1, 0x1000, 16, },
+	{ "SST25VF512", 0x48, 0x1000, 16, },
+	{ "SST25WF010", 2, 0x1000, 32, },
+	{ "SST25VF010", 0x49, 0x1000, 32, },
+	{ "SST25WF020", 3, 0x1000, 64, },
+	{ "SST25VF020", 0x43, 0x1000, 64, },
+	{ "SST25WF040", 4, 0x1000, 128, },
+	{ "SST25VF040", 0x44, 0x1000, 128, },
+	{ "SST25VF040B", 0x8d, 0x1000, 128, },
+	{ "SST25WF080", 5, 0x1000, 256, },
+	{ "SST25VF080B", 0x8e, 0x1000, 256, },
+	{ "SST25VF016", 0x41, 0x1000, 512, },
+	{ "SST25VF032", 0x4a, 0x1000, 1024, },
+	{ "SST25VF064", 0x4b, 0x1000, 2048, },
 	{ 0 },
 };
 
 static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
+	{ "AT45DB011", 0xc, 256, 512, },
+	{ "AT45DB021", 0x14, 256, 1024, },
+	{ "AT45DB041", 0x1c, 256, 2048, },
+	{ "AT45DB081", 0x24, 256, 4096, },
+	{ "AT45DB161", 0x2c, 512, 4096, },
+	{ "AT45DB321", 0x34, 512, 8192, },
+	{ "AT45DB642", 0x3c, 1024, 8192, },
 	{ 0 },
 };
 
@@ -84,6 +111,8 @@ int bcma_sflash_init(struct bcma_drv_cc *cc)
 					break;
 			}
 			break;
+		case 0x13:
+			return -ENOTSUPP;
 		default:
 			for (e = bcma_sflash_st_tbl; e->name; e++) {
 				if (e->id == id)
@@ -116,7 +145,7 @@ int bcma_sflash_init(struct bcma_drv_cc *cc)
 		return -ENOTSUPP;
 	}
 
-	sflash->window = BCMA_SFLASH;
+	sflash->window = BCMA_SOC_FLASH2;
 	sflash->blocksize = e->blocksize;
 	sflash->numblocks = e->numblocks;
 	sflash->size = sflash->blocksize * sflash->numblocks;
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c
new file mode 100644
index 0000000..9a6f585
--- /dev/null
+++ b/drivers/bcma/driver_gpio.c
@@ -0,0 +1,98 @@
+/*
+ * Broadcom specific AMBA
+ * GPIO driver
+ *
+ * Copyright 2011, Broadcom Corporation
+ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/gpio.h>
+#include <linux/export.h>
+#include <linux/bcma/bcma.h>
+
+#include "bcma_private.h"
+
+static inline struct bcma_drv_cc *bcma_gpio_get_cc(struct gpio_chip *chip)
+{
+	return container_of(chip, struct bcma_drv_cc, gpio);
+}
+
+static int bcma_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+	struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
+
+	return !!bcma_chipco_gpio_in(cc, 1 << gpio);
+}
+
+static void bcma_gpio_set_value(struct gpio_chip *chip, unsigned gpio,
+				int value)
+{
+	struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
+
+	bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0);
+}
+
+static int bcma_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+	struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
+
+	bcma_chipco_gpio_outen(cc, 1 << gpio, 0);
+	return 0;
+}
+
+static int bcma_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
+				      int value)
+{
+	struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
+
+	bcma_chipco_gpio_outen(cc, 1 << gpio, 1 << gpio);
+	bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0);
+	return 0;
+}
+
+static int bcma_gpio_request(struct gpio_chip *chip, unsigned gpio)
+{
+	struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
+
+	bcma_chipco_gpio_control(cc, 1 << gpio, 0);
+	/* clear pulldown */
+	bcma_chipco_gpio_pulldown(cc, 1 << gpio, 0);
+	/* Set pullup */
+	bcma_chipco_gpio_pullup(cc, 1 << gpio, 1 << gpio);
+
+	return 0;
+}
+
+static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio)
+{
+	struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
+
+	/* clear pullup */
+	bcma_chipco_gpio_pullup(cc, 1 << gpio, 0);
+}
+
+int bcma_gpio_init(struct bcma_drv_cc *cc)
+{
+	struct gpio_chip *chip = &cc->gpio;
+
+	chip->label		= "bcma_gpio";
+	chip->owner		= THIS_MODULE;
+	chip->request		= bcma_gpio_request;
+	chip->free		= bcma_gpio_free;
+	chip->get		= bcma_gpio_get_value;
+	chip->set		= bcma_gpio_set_value;
+	chip->direction_input	= bcma_gpio_direction_input;
+	chip->direction_output	= bcma_gpio_direction_output;
+	chip->ngpio		= 16;
+	/* There is just one SoC in one device and its GPIO addresses should be
+	 * deterministic to address them more easily. The other buses could get
+	 * a random base number. */
+	if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
+		chip->base		= 0;
+	else
+		chip->base		= -1;
+
+	return gpiochip_add(chip);
+}
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c
index cc65b45..170822e 100644
--- a/drivers/bcma/driver_mips.c
+++ b/drivers/bcma/driver_mips.c
@@ -181,47 +181,66 @@ EXPORT_SYMBOL(bcma_cpu_clock);
 static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
 {
 	struct bcma_bus *bus = mcore->core->bus;
+	struct bcma_drv_cc *cc = &bus->drv_cc;
 
-	switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
+	switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
 	case BCMA_CC_FLASHT_STSER:
 	case BCMA_CC_FLASHT_ATSER:
 		bcma_debug(bus, "Found serial flash\n");
-		bcma_sflash_init(&bus->drv_cc);
+		bcma_sflash_init(cc);
 		break;
 	case BCMA_CC_FLASHT_PARA:
 		bcma_debug(bus, "Found parallel flash\n");
-		bus->drv_cc.pflash.window = 0x1c000000;
-		bus->drv_cc.pflash.window_size = 0x02000000;
+		cc->pflash.present = true;
+		cc->pflash.window = BCMA_SOC_FLASH2;
+		cc->pflash.window_size = BCMA_SOC_FLASH2_SZ;
 
-		if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) &
+		if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) &
 		     BCMA_CC_FLASH_CFG_DS) == 0)
-			bus->drv_cc.pflash.buswidth = 1;
+			cc->pflash.buswidth = 1;
 		else
-			bus->drv_cc.pflash.buswidth = 2;
+			cc->pflash.buswidth = 2;
 		break;
 	default:
 		bcma_err(bus, "Flash type not supported\n");
 	}
 
-	if (bus->drv_cc.core->id.rev == 38 ||
+	if (cc->core->id.rev == 38 ||
 	    bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
-		if (bus->drv_cc.capabilities & BCMA_CC_CAP_NFLASH) {
+		if (cc->capabilities & BCMA_CC_CAP_NFLASH) {
 			bcma_debug(bus, "Found NAND flash\n");
-			bcma_nflash_init(&bus->drv_cc);
+			bcma_nflash_init(cc);
 		}
 	}
 }
 
+void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
+{
+	struct bcma_bus *bus = mcore->core->bus;
+
+	if (mcore->early_setup_done)
+		return;
+
+	bcma_chipco_serial_init(&bus->drv_cc);
+	bcma_core_mips_flash_detect(mcore);
+
+	mcore->early_setup_done = true;
+}
+
 void bcma_core_mips_init(struct bcma_drv_mips *mcore)
 {
 	struct bcma_bus *bus;
 	struct bcma_device *core;
 	bus = mcore->core->bus;
 
+	if (mcore->setup_done)
+		return;
+
 	bcma_info(bus, "Initializing MIPS core...\n");
 
-	if (!mcore->setup_done)
-		mcore->assigned_irqs = 1;
+	bcma_core_mips_early_init(mcore);
+
+	mcore->assigned_irqs = 1;
 
 	/* Assign IRQs to all cores on the bus */
 	list_for_each_entry(core, &bus->cores, list) {
@@ -256,10 +275,5 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
 	bcma_info(bus, "IRQ reconfiguration done\n");
 	bcma_core_mips_dump_irq(bus);
 
-	if (mcore->setup_done)
-		return;
-
-	bcma_chipco_serial_init(&bus->drv_cc);
-	bcma_core_mips_flash_detect(mcore);
 	mcore->setup_done = true;
 }
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c
index 9baf886..e564495 100644
--- a/drivers/bcma/driver_pci_host.c
+++ b/drivers/bcma/driver_pci_host.c
@@ -35,11 +35,6 @@ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
 	    chipid_top != 0x5300)
 		return false;
 
-	if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
-		bcma_info(bus, "This PCI core is disabled and not working\n");
-		return false;
-	}
-
 	bcma_core_enable(pc->core, 0);
 
 	return !mips_busprobe32(tmp, pc->core->io_addr);
@@ -396,6 +391,11 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
 
 	bcma_info(bus, "PCIEcore in host mode found\n");
 
+	if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
+		bcma_info(bus, "This PCIE core is disabled and not working\n");
+		return;
+	}
+
 	pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL);
 	if (!pc_host)  {
 		bcma_err(bus, "can not allocate memory");
@@ -452,6 +452,8 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
 			pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
 			pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
 						    BCMA_SOC_PCI_MEM_SZ - 1;
+			pc_host->io_resource.start = 0x100;
+			pc_host->io_resource.end = 0x47F;
 			pci_membase_1G = BCMA_SOC_PCIE_DMA_H32;
 			pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
 					tmp | BCMA_SOC_PCI_MEM);
@@ -459,6 +461,8 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
 			pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM;
 			pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM +
 						    BCMA_SOC_PCI_MEM_SZ - 1;
+			pc_host->io_resource.start = 0x480;
+			pc_host->io_resource.end = 0x7FF;
 			pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32;
 			pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG;
 			pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index b6b4b5e..98fdc3e 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -238,7 +238,7 @@ static void __devexit bcma_host_pci_remove(struct pci_dev *dev)
 	pci_set_drvdata(dev, NULL);
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int bcma_host_pci_suspend(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
@@ -261,11 +261,11 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
 			 bcma_host_pci_resume);
 #define BCMA_PM_OPS	(&bcma_pm_ops)
 
-#else /* CONFIG_PM */
+#else /* CONFIG_PM_SLEEP */
 
 #define BCMA_PM_OPS     NULL
 
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 
 static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index d865470..2a81a8b 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -81,6 +81,18 @@ struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
 }
 EXPORT_SYMBOL_GPL(bcma_find_core);
 
+static struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
+					       u8 unit)
+{
+	struct bcma_device *core;
+
+	list_for_each_entry(core, &bus->cores, list) {
+		if (core->id.id == coreid && core->core_unit == unit)
+			return core;
+	}
+	return NULL;
+}
+
 static void bcma_release_core_dev(struct device *dev)
 {
 	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
@@ -152,6 +164,11 @@ static int bcma_register_cores(struct bcma_bus *bus)
 			bcma_err(bus, "Error registering NAND flash\n");
 	}
 #endif
+	err = bcma_gpio_init(&bus->drv_cc);
+	if (err == -ENOTSUPP)
+		bcma_debug(bus, "GPIO driver not activated\n");
+	else if (err)
+		bcma_err(bus, "Error registering GPIO driver: %i\n", err);
 
 	return 0;
 }
@@ -183,6 +200,20 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
 		return -1;
 	}
 
+	/* Early init CC core */
+	core = bcma_find_core(bus, bcma_cc_core_id(bus));
+	if (core) {
+		bus->drv_cc.core = core;
+		bcma_core_chipcommon_early_init(&bus->drv_cc);
+	}
+
+	/* Try to get SPROM */
+	err = bcma_sprom_get(bus);
+	if (err == -ENOENT) {
+		bcma_err(bus, "No SPROM available\n");
+	} else if (err)
+		bcma_err(bus, "Failed to get SPROM: %d\n", err);
+
 	/* Init CC core */
 	core = bcma_find_core(bus, bcma_cc_core_id(bus));
 	if (core) {
@@ -198,10 +229,17 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
 	}
 
 	/* Init PCIE core */
-	core = bcma_find_core(bus, BCMA_CORE_PCIE);
+	core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 0);
 	if (core) {
-		bus->drv_pci.core = core;
-		bcma_core_pci_init(&bus->drv_pci);
+		bus->drv_pci[0].core = core;
+		bcma_core_pci_init(&bus->drv_pci[0]);
+	}
+
+	/* Init PCIE core */
+	core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 1);
+	if (core) {
+		bus->drv_pci[1].core = core;
+		bcma_core_pci_init(&bus->drv_pci[1]);
 	}
 
 	/* Init GBIT MAC COMMON core */
@@ -211,13 +249,6 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
 		bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn);
 	}
 
-	/* Try to get SPROM */
-	err = bcma_sprom_get(bus);
-	if (err == -ENOENT) {
-		bcma_err(bus, "No SPROM available\n");
-	} else if (err)
-		bcma_err(bus, "Failed to get SPROM: %d\n", err);
-
 	/* Register found cores */
 	bcma_register_cores(bus);
 
@@ -275,18 +306,18 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
 		return -1;
 	}
 
-	/* Init CC core */
+	/* Early init CC core */
 	core = bcma_find_core(bus, bcma_cc_core_id(bus));
 	if (core) {
 		bus->drv_cc.core = core;
-		bcma_core_chipcommon_init(&bus->drv_cc);
+		bcma_core_chipcommon_early_init(&bus->drv_cc);
 	}
 
-	/* Init MIPS core */
+	/* Early init MIPS core */
 	core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
 	if (core) {
 		bus->drv_mips.core = core;
-		bcma_core_mips_init(&bus->drv_mips);
+		bcma_core_mips_early_init(&bus->drv_mips);
 	}
 
 	bcma_info(bus, "Early bus registered\n");
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index 0d546b6..4adf9ef9 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -595,8 +595,11 @@ int bcma_sprom_get(struct bcma_bus *bus)
 		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
 
 	err = bcma_sprom_valid(sprom);
-	if (err)
+	if (err) {
+		bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n");
+		err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
 		goto out;
+	}
 
 	bcma_sprom_extract_r8(bus, sprom);
 
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index d2ed7f1..bfd765c 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -1,5 +1,6 @@
+
 /* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
-#define VERSION "50"
+#define VERSION "64+"
 #define AOE_MAJOR 152
 #define DEVICE_NAME "aoe"
 
@@ -86,8 +87,10 @@ enum {
 	NFACTIVE = 61,
 
 	TIMERTICK = HZ / 10,
-	MINTIMER = HZ >> 2,
-	MAXTIMER = HZ << 1,
+	RTTSCALE = 8,
+	RTTDSCALE = 3,
+	RTTAVG_INIT = USEC_PER_SEC / 4 << RTTSCALE,
+	RTTDEV_INIT = RTTAVG_INIT / 4,
 };
 
 struct buf {
@@ -103,7 +106,10 @@ struct buf {
 struct frame {
 	struct list_head head;
 	u32 tag;
+	struct timeval sent;	/* high-res time packet was sent */
+	u32 sent_jiffs;		/* low-res jiffies-based sent time */
 	ulong waited;
+	ulong waited_total;
 	struct aoetgt *t;		/* parent target I belong to */
 	sector_t lba;
 	struct sk_buff *skb;		/* command skb freed on module exit */
@@ -122,15 +128,16 @@ struct aoeif {
 
 struct aoetgt {
 	unsigned char addr[6];
-	ushort nframes;
+	ushort nframes;		/* cap on frames to use */
 	struct aoedev *d;			/* parent device I belong to */
 	struct list_head ffree;			/* list of free frames */
 	struct aoeif ifs[NAOEIFS];
 	struct aoeif *ifp;	/* current aoeif in use */
-	ushort nout;
-	ushort maxout;
-	ulong falloc;
-	ulong lastwadj;		/* last window adjustment */
+	ushort nout;		/* number of AoE commands outstanding */
+	ushort maxout;		/* current value for max outstanding */
+	ushort next_cwnd;	/* incr maxout after decrementing to zero */
+	ushort ssthresh;	/* slow start threshold */
+	ulong falloc;		/* number of allocated frames */
 	int minbcnt;
 	int wpkts, rpkts;
 };
@@ -139,11 +146,11 @@ struct aoedev {
 	struct aoedev *next;
 	ulong sysminor;
 	ulong aoemajor;
+	u32 rttavg;		/* scaled AoE round trip time average */
+	u32 rttdev;		/* scaled round trip time mean deviation */
 	u16 aoeminor;
 	u16 flags;
 	u16 nopen;		/* (bd_openers isn't available without sleeping) */
-	u16 rttavg;		/* round trip average of requests/responses */
-	u16 mintimer;
 	u16 fw_ver;		/* version of blade's firmware */
 	u16 lasttag;		/* last tag sent */
 	u16 useme;
@@ -151,7 +158,7 @@ struct aoedev {
 	struct work_struct work;/* disk create work struct */
 	struct gendisk *gd;
 	struct request_queue *blkq;
-	struct hd_geometry geo; 
+	struct hd_geometry geo;
 	sector_t ssize;
 	struct timer_list timer;
 	spinlock_t lock;
@@ -164,11 +171,13 @@ struct aoedev {
 	} ip;
 	ulong maxbcnt;
 	struct list_head factive[NFACTIVE];	/* hash of active frames */
+	struct list_head rexmitq; /* deferred retransmissions */
 	struct aoetgt *targets[NTARGETS];
 	struct aoetgt **tgt;	/* target in use when working */
 	struct aoetgt *htgt;	/* target needing rexmit assistance */
 	ulong ntargets;
 	ulong kicked;
+	char ident[512];
 };
 
 /* kthread tracking */
@@ -195,6 +204,7 @@ void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor);
 struct sk_buff *aoecmd_ata_rsp(struct sk_buff *);
 void aoecmd_cfg_rsp(struct sk_buff *);
 void aoecmd_sleepwork(struct work_struct *);
+void aoecmd_wreset(struct aoetgt *t);
 void aoecmd_cleanslate(struct aoedev *);
 void aoecmd_exit(void);
 int aoecmd_init(void);
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index 00dfc50..57ac72c 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -16,11 +16,19 @@
 #include <linux/netdevice.h>
 #include <linux/mutex.h>
 #include <linux/export.h>
+#include <linux/moduleparam.h>
+#include <scsi/sg.h>
 #include "aoe.h"
 
 static DEFINE_MUTEX(aoeblk_mutex);
 static struct kmem_cache *buf_pool_cache;
 
+/* GPFS needs a larger value than the default. */
+static int aoe_maxsectors;
+module_param(aoe_maxsectors, int, 0644);
+MODULE_PARM_DESC(aoe_maxsectors,
+	"When nonzero, set the maximum number of sectors per I/O request");
+
 static ssize_t aoedisk_show_state(struct device *dev,
 				  struct device_attribute *attr, char *page)
 {
@@ -91,6 +99,14 @@ static ssize_t aoedisk_show_fwver(struct device *dev,
 
 	return snprintf(page, PAGE_SIZE, "0x%04x\n", (unsigned int) d->fw_ver);
 }
+static ssize_t aoedisk_show_payload(struct device *dev,
+				    struct device_attribute *attr, char *page)
+{
+	struct gendisk *disk = dev_to_disk(dev);
+	struct aoedev *d = disk->private_data;
+
+	return snprintf(page, PAGE_SIZE, "%lu\n", d->maxbcnt);
+}
 
 static DEVICE_ATTR(state, S_IRUGO, aoedisk_show_state, NULL);
 static DEVICE_ATTR(mac, S_IRUGO, aoedisk_show_mac, NULL);
@@ -99,12 +115,14 @@ static struct device_attribute dev_attr_firmware_version = {
 	.attr = { .name = "firmware-version", .mode = S_IRUGO },
 	.show = aoedisk_show_fwver,
 };
+static DEVICE_ATTR(payload, S_IRUGO, aoedisk_show_payload, NULL);
 
 static struct attribute *aoe_attrs[] = {
 	&dev_attr_state.attr,
 	&dev_attr_mac.attr,
 	&dev_attr_netif.attr,
 	&dev_attr_firmware_version.attr,
+	&dev_attr_payload.attr,
 	NULL,
 };
 
@@ -195,9 +213,38 @@ aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 	return 0;
 }
 
+static int
+aoeblk_ioctl(struct block_device *bdev, fmode_t mode, uint cmd, ulong arg)
+{
+	struct aoedev *d;
+
+	if (!arg)
+		return -EINVAL;
+
+	d = bdev->bd_disk->private_data;
+	if ((d->flags & DEVFL_UP) == 0) {
+		pr_err("aoe: disk not up\n");
+		return -ENODEV;
+	}
+
+	if (cmd == HDIO_GET_IDENTITY) {
+		if (!copy_to_user((void __user *) arg, &d->ident,
+			sizeof(d->ident)))
+			return 0;
+		return -EFAULT;
+	}
+
+	/* udev calls scsi_id, which uses SG_IO, resulting in noise */
+	if (cmd != SG_IO)
+		pr_info("aoe: unknown ioctl 0x%x\n", cmd);
+
+	return -ENOTTY;
+}
+
 static const struct block_device_operations aoe_bdops = {
 	.open = aoeblk_open,
 	.release = aoeblk_release,
+	.ioctl = aoeblk_ioctl,
 	.getgeo = aoeblk_getgeo,
 	.owner = THIS_MODULE,
 };
@@ -231,23 +278,19 @@ aoeblk_gdalloc(void *vp)
 	if (q == NULL) {
 		pr_err("aoe: cannot allocate block queue for %ld.%d\n",
 			d->aoemajor, d->aoeminor);
-		mempool_destroy(mp);
-		goto err_disk;
+		goto err_mempool;
 	}
 
-	d->blkq = blk_alloc_queue(GFP_KERNEL);
-	if (!d->blkq)
-		goto err_mempool;
-	d->blkq->backing_dev_info.name = "aoe";
-	if (bdi_init(&d->blkq->backing_dev_info))
-		goto err_blkq;
 	spin_lock_irqsave(&d->lock, flags);
-	blk_queue_max_hw_sectors(d->blkq, BLK_DEF_MAX_SECTORS);
+	blk_queue_max_hw_sectors(q, BLK_DEF_MAX_SECTORS);
+	q->backing_dev_info.name = "aoe";
 	q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE;
 	d->bufpool = mp;
 	d->blkq = gd->queue = q;
 	q->queuedata = d;
 	d->gd = gd;
+	if (aoe_maxsectors)
+		blk_queue_max_hw_sectors(q, aoe_maxsectors);
 	gd->major = AOE_MAJOR;
 	gd->first_minor = d->sysminor;
 	gd->fops = &aoe_bdops;
@@ -265,11 +308,8 @@ aoeblk_gdalloc(void *vp)
 	aoedisk_add_sysfs(d);
 	return;
 
-err_blkq:
-	blk_cleanup_queue(d->blkq);
-	d->blkq = NULL;
 err_mempool:
-	mempool_destroy(d->bufpool);
+	mempool_destroy(mp);
 err_disk:
 	put_disk(gd);
 err:
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index ed57a89..42e67ad 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -39,6 +39,11 @@ struct ErrMsg {
 };
 
 static DEFINE_MUTEX(aoechr_mutex);
+
+/* A ring buffer of error messages, to be read through
+ * "/dev/etherd/err".  When no messages are present,
+ * readers will block waiting for messages to appear.
+ */
 static struct ErrMsg emsgs[NMSG];
 static int emsgs_head_idx, emsgs_tail_idx;
 static struct completion emsgs_comp;
@@ -282,7 +287,7 @@ aoechr_init(void)
 	int n, i;
 
 	n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops);
-	if (n < 0) { 
+	if (n < 0) {
 		printk(KERN_ERR "aoe: can't register char device\n");
 		return n;
 	}
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 9fe4f18..391dd8e 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -29,7 +29,7 @@ static int aoe_deadsecs = 60 * 3;
 module_param(aoe_deadsecs, int, 0644);
 MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev.");
 
-static int aoe_maxout = 16;
+static int aoe_maxout = 64;
 module_param(aoe_maxout, int, 0644);
 MODULE_PARM_DESC(aoe_maxout,
 	"Only aoe_maxout outstanding packets for every MAC on eX.Y.");
@@ -59,6 +59,23 @@ new_skb(ulong len)
 }
 
 static struct frame *
+getframe_deferred(struct aoedev *d, u32 tag)
+{
+	struct list_head *head, *pos, *nx;
+	struct frame *f;
+
+	head = &d->rexmitq;
+	list_for_each_safe(pos, nx, head) {
+		f = list_entry(pos, struct frame, head);
+		if (f->tag == tag) {
+			list_del(pos);
+			return f;
+		}
+	}
+	return NULL;
+}
+
+static struct frame *
 getframe(struct aoedev *d, u32 tag)
 {
 	struct frame *f;
@@ -335,6 +352,7 @@ aoecmd_ata_rw(struct aoedev *d)
 	fhash(f);
 	t->nout++;
 	f->waited = 0;
+	f->waited_total = 0;
 	f->buf = buf;
 	f->bcnt = bcnt;
 	f->lba = buf->sector;
@@ -370,6 +388,8 @@ aoecmd_ata_rw(struct aoedev *d)
 	skb->dev = t->ifp->nd;
 	skb = skb_clone(skb, GFP_ATOMIC);
 	if (skb) {
+		do_gettimeofday(&f->sent);
+		f->sent_jiffs = (u32) jiffies;
 		__skb_queue_head_init(&queue);
 		__skb_queue_tail(&queue, skb);
 		aoenet_xmit(&queue);
@@ -458,12 +478,46 @@ resend(struct aoedev *d, struct frame *f)
 	skb = skb_clone(skb, GFP_ATOMIC);
 	if (skb == NULL)
 		return;
+	do_gettimeofday(&f->sent);
+	f->sent_jiffs = (u32) jiffies;
 	__skb_queue_head_init(&queue);
 	__skb_queue_tail(&queue, skb);
 	aoenet_xmit(&queue);
 }
 
 static int
+tsince_hr(struct frame *f)
+{
+	struct timeval now;
+	int n;
+
+	do_gettimeofday(&now);
+	n = now.tv_usec - f->sent.tv_usec;
+	n += (now.tv_sec - f->sent.tv_sec) * USEC_PER_SEC;
+
+	if (n < 0)
+		n = -n;
+
+	/* For relatively long periods, use jiffies to avoid
+	 * discrepancies caused by updates to the system time.
+	 *
+	 * On system with HZ of 1000, 32-bits is over 49 days
+	 * worth of jiffies, or over 71 minutes worth of usecs.
+	 *
+	 * Jiffies overflow is handled by subtraction of unsigned ints:
+	 * (gdb) print (unsigned) 2 - (unsigned) 0xfffffffe
+	 * $3 = 4
+	 * (gdb)
+	 */
+	if (n > USEC_PER_SEC / 4) {
+		n = ((u32) jiffies) - f->sent_jiffs;
+		n *= USEC_PER_SEC / HZ;
+	}
+
+	return n;
+}
+
+static int
 tsince(u32 tag)
 {
 	int n;
@@ -472,7 +526,7 @@ tsince(u32 tag)
 	n -= tag & 0xffff;
 	if (n < 0)
 		n += 1<<16;
-	return n;
+	return jiffies_to_usecs(n + 1);
 }
 
 static struct aoeif *
@@ -503,45 +557,70 @@ ejectif(struct aoetgt *t, struct aoeif *ifp)
 	dev_put(nd);
 }
 
+static struct frame *
+reassign_frame(struct list_head *pos)
+{
+	struct frame *f;
+	struct frame *nf;
+	struct sk_buff *skb;
+
+	f = list_entry(pos, struct frame, head);
+	nf = newframe(f->t->d);
+	if (!nf)
+		return NULL;
+
+	list_del(pos);
+
+	skb = nf->skb;
+	nf->skb = f->skb;
+	nf->buf = f->buf;
+	nf->bcnt = f->bcnt;
+	nf->lba = f->lba;
+	nf->bv = f->bv;
+	nf->bv_off = f->bv_off;
+	nf->waited = 0;
+	nf->waited_total = f->waited_total;
+	nf->sent = f->sent;
+	nf->sent_jiffs = f->sent_jiffs;
+	f->skb = skb;
+	aoe_freetframe(f);
+	f->t->nout--;
+	nf->t->nout++;
+
+	return nf;
+}
+
 static int
 sthtith(struct aoedev *d)
 {
 	struct frame *f, *nf;
 	struct list_head *nx, *pos, *head;
-	struct sk_buff *skb;
 	struct aoetgt *ht = d->htgt;
 	int i;
 
+	/* look through the active and pending retransmit frames */
 	for (i = 0; i < NFACTIVE; i++) {
 		head = &d->factive[i];
 		list_for_each_safe(pos, nx, head) {
 			f = list_entry(pos, struct frame, head);
 			if (f->t != ht)
 				continue;
-
-			nf = newframe(d);
+			nf = reassign_frame(pos);
 			if (!nf)
 				return 0;
-
-			/* remove frame from active list */
-			list_del(pos);
-
-			/* reassign all pertinent bits to new outbound frame */
-			skb = nf->skb;
-			nf->skb = f->skb;
-			nf->buf = f->buf;
-			nf->bcnt = f->bcnt;
-			nf->lba = f->lba;
-			nf->bv = f->bv;
-			nf->bv_off = f->bv_off;
-			nf->waited = 0;
-			f->skb = skb;
-			aoe_freetframe(f);
-			ht->nout--;
-			nf->t->nout++;
 			resend(d, nf);
 		}
 	}
+	head = &d->rexmitq;
+	list_for_each_safe(pos, nx, head) {
+		f = list_entry(pos, struct frame, head);
+		if (f->t != ht)
+			continue;
+		nf = reassign_frame(pos);
+		if (!nf)
+			return 0;
+		resend(d, nf);
+	}
 	/* We've cleaned up the outstanding so take away his
 	 * interfaces so he won't be used.  We should remove him from
 	 * the target array here, but cleaning up a target is
@@ -552,21 +631,34 @@ sthtith(struct aoedev *d)
 	return 1;
 }
 
-static inline unsigned char
-ata_scnt(unsigned char *packet) {
-	struct aoe_hdr *h;
-	struct aoe_atahdr *ah;
+static void
+rexmit_deferred(struct aoedev *d)
+{
+	struct aoetgt *t;
+	struct frame *f;
+	struct list_head *pos, *nx, *head;
+	int since;
 
-	h = (struct aoe_hdr *) packet;
-	ah = (struct aoe_atahdr *) (h+1);
-	return ah->scnt;
+	head = &d->rexmitq;
+	list_for_each_safe(pos, nx, head) {
+		f = list_entry(pos, struct frame, head);
+		t = f->t;
+		if (t->nout >= t->maxout)
+			continue;
+		list_del(pos);
+		t->nout++;
+		since = tsince_hr(f);
+		f->waited += since;
+		f->waited_total += since;
+		resend(d, f);
+	}
 }
 
 static void
 rexmit_timer(ulong vp)
 {
 	struct aoedev *d;
-	struct aoetgt *t, **tt, **te;
+	struct aoetgt *t;
 	struct aoeif *ifp;
 	struct frame *f;
 	struct list_head *head, *pos, *nx;
@@ -574,15 +666,18 @@ rexmit_timer(ulong vp)
 	register long timeout;
 	ulong flags, n;
 	int i;
+	int since;
 
 	d = (struct aoedev *) vp;
 
-	/* timeout is always ~150% of the moving average */
-	timeout = d->rttavg;
-	timeout += timeout >> 1;
-
 	spin_lock_irqsave(&d->lock, flags);
 
+	/* timeout based on observed timings and variations */
+	timeout = 2 * d->rttavg >> RTTSCALE;
+	timeout += 8 * d->rttdev >> RTTDSCALE;
+	if (timeout == 0)
+		timeout = 1;
+
 	if (d->flags & DEVFL_TKILL) {
 		spin_unlock_irqrestore(&d->lock, flags);
 		return;
@@ -593,36 +688,20 @@ rexmit_timer(ulong vp)
 		head = &d->factive[i];
 		list_for_each_safe(pos, nx, head) {
 			f = list_entry(pos, struct frame, head);
-			if (tsince(f->tag) < timeout)
+			if (tsince_hr(f) < timeout)
 				break;	/* end of expired frames */
 			/* move to flist for later processing */
 			list_move_tail(pos, &flist);
 		}
 	}
-	/* window check */
-	tt = d->targets;
-	te = tt + d->ntargets;
-	for (; tt < te && (t = *tt); tt++) {
-		if (t->nout == t->maxout
-		&& t->maxout < t->nframes
-		&& (jiffies - t->lastwadj)/HZ > 10) {
-			t->maxout++;
-			t->lastwadj = jiffies;
-		}
-	}
-
-	if (!list_empty(&flist)) {	/* retransmissions necessary */
-		n = d->rttavg <<= 1;
-		if (n > MAXTIMER)
-			d->rttavg = MAXTIMER;
-	}
 
 	/* process expired frames */
 	while (!list_empty(&flist)) {
 		pos = flist.next;
 		f = list_entry(pos, struct frame, head);
-		n = f->waited += timeout;
-		n /= HZ;
+		since = tsince_hr(f);
+		n = f->waited_total + since;
+		n /= USEC_PER_SEC;
 		if (n > aoe_deadsecs) {
 			/* Waited too long.  Device failure.
 			 * Hang all frames on first hash bucket for downdev
@@ -630,18 +709,16 @@ rexmit_timer(ulong vp)
 			 */
 			list_splice(&flist, &d->factive[0]);
 			aoedev_downdev(d);
-			break;
+			goto out;
 		}
-		list_del(pos);
 
 		t = f->t;
 		if (n > aoe_deadsecs/2)
 			d->htgt = t; /* see if another target can help */
 
-		if (t->nout == t->maxout) {
-			if (t->maxout > 1)
-				t->maxout--;
-			t->lastwadj = jiffies;
+		if (t->maxout != 1) {
+			t->ssthresh = t->maxout / 2;
+			t->maxout = 1;
 		}
 
 		ifp = getif(t, f->skb->dev);
@@ -650,9 +727,12 @@ rexmit_timer(ulong vp)
 			ejectif(t, ifp);
 			ifp = NULL;
 		}
-		resend(d, f);
+		list_move_tail(pos, &d->rexmitq);
+		t->nout--;
 	}
+	rexmit_deferred(d);
 
+out:
 	if ((d->flags & DEVFL_KICKME || d->htgt) && d->blkq) {
 		d->flags &= ~DEVFL_KICKME;
 		d->blkq->request_fn(d->blkq);
@@ -776,6 +856,7 @@ aoecmd_work(struct aoedev *d)
 {
 	if (d->htgt && !sthtith(d))
 		return;
+	rexmit_deferred(d);
 	while (aoecmd_ata_rw(d))
 		;
 }
@@ -809,6 +890,17 @@ aoecmd_sleepwork(struct work_struct *work)
 }
 
 static void
+ata_ident_fixstring(u16 *id, int ns)
+{
+	u16 s;
+
+	while (ns-- > 0) {
+		s = *id;
+		*id++ = s >> 8 | s << 8;
+	}
+}
+
+static void
 ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id)
 {
 	u64 ssize;
@@ -843,6 +935,11 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id)
 		d->geo.sectors = get_unaligned_le16(&id[56 << 1]);
 	}
 
+	ata_ident_fixstring((u16 *) &id[10<<1], 10);	/* serial */
+	ata_ident_fixstring((u16 *) &id[23<<1], 4);	/* firmware */
+	ata_ident_fixstring((u16 *) &id[27<<1], 20);	/* model */
+	memcpy(d->ident, id, sizeof(d->ident));
+
 	if (d->ssize != ssize)
 		printk(KERN_INFO
 			"aoe: %pm e%ld.%d v%04x has %llu sectors\n",
@@ -862,26 +959,28 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id)
 }
 
 static void
-calc_rttavg(struct aoedev *d, int rtt)
+calc_rttavg(struct aoedev *d, struct aoetgt *t, int rtt)
 {
 	register long n;
 
 	n = rtt;
-	if (n < 0) {
-		n = -rtt;
-		if (n < MINTIMER)
-			n = MINTIMER;
-		else if (n > MAXTIMER)
-			n = MAXTIMER;
-		d->mintimer += (n - d->mintimer) >> 1;
-	} else if (n < d->mintimer)
-		n = d->mintimer;
-	else if (n > MAXTIMER)
-		n = MAXTIMER;
-
-	/* g == .25; cf. Congestion Avoidance and Control, Jacobson & Karels; 1988 */
-	n -= d->rttavg;
-	d->rttavg += n >> 2;
+
+	/* cf. Congestion Avoidance and Control, Jacobson & Karels, 1988 */
+	n -= d->rttavg >> RTTSCALE;
+	d->rttavg += n;
+	if (n < 0)
+		n = -n;
+	n -= d->rttdev >> RTTDSCALE;
+	d->rttdev += n;
+
+	if (!t || t->maxout >= t->nframes)
+		return;
+	if (t->maxout < t->ssthresh)
+		t->maxout += 1;
+	else if (t->nout == t->maxout && t->next_cwnd-- == 0) {
+		t->maxout += 1;
+		t->next_cwnd = t->maxout;
+	}
 }
 
 static struct aoetgt *
@@ -988,7 +1087,7 @@ ktiocomplete(struct frame *f)
 		pr_err("aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%d\n",
 			ahout->cmdstat, ahin->cmdstat,
 			d->aoemajor, d->aoeminor);
-noskb:	if (buf)
+noskb:		if (buf)
 			clear_bit(BIO_UPTODATE, &buf->bio->bi_flags);
 		goto badrsp;
 	}
@@ -1040,8 +1139,6 @@ badrsp:
 	if (buf && --buf->nframesout == 0 && buf->resid == 0)
 		aoe_end_buf(d, buf);
 
-	aoecmd_work(d);
-
 	spin_unlock_irq(&d->lock);
 	aoedev_put(d);
 	dev_kfree_skb(skb);
@@ -1141,7 +1238,6 @@ aoecmd_ata_rsp(struct sk_buff *skb)
 	struct aoedev *d;
 	struct aoe_hdr *h;
 	struct frame *f;
-	struct aoetgt *t;
 	u32 n;
 	ulong flags;
 	char ebuf[128];
@@ -1162,23 +1258,30 @@ aoecmd_ata_rsp(struct sk_buff *skb)
 
 	n = be32_to_cpu(get_unaligned(&h->tag));
 	f = getframe(d, n);
-	if (f == NULL) {
-		calc_rttavg(d, -tsince(n));
-		spin_unlock_irqrestore(&d->lock, flags);
-		aoedev_put(d);
-		snprintf(ebuf, sizeof ebuf,
-			"%15s e%d.%d    tag=%08x@%08lx\n",
-			"unexpected rsp",
-			get_unaligned_be16(&h->major),
-			h->minor,
-			get_unaligned_be32(&h->tag),
-			jiffies);
-		aoechr_error(ebuf);
-		return skb;
+	if (f) {
+		calc_rttavg(d, f->t, tsince_hr(f));
+		f->t->nout--;
+	} else {
+		f = getframe_deferred(d, n);
+		if (f) {
+			calc_rttavg(d, NULL, tsince_hr(f));
+		} else {
+			calc_rttavg(d, NULL, tsince(n));
+			spin_unlock_irqrestore(&d->lock, flags);
+			aoedev_put(d);
+			snprintf(ebuf, sizeof(ebuf),
+				 "%15s e%d.%d    tag=%08x@%08lx s=%pm d=%pm\n",
+				 "unexpected rsp",
+				 get_unaligned_be16(&h->major),
+				 h->minor,
+				 get_unaligned_be32(&h->tag),
+				 jiffies,
+				 h->src,
+				 h->dst);
+			aoechr_error(ebuf);
+			return skb;
+		}
 	}
-	t = f->t;
-	calc_rttavg(d, tsince(f->tag));
-	t->nout--;
 	aoecmd_work(d);
 
 	spin_unlock_irqrestore(&d->lock, flags);
@@ -1201,7 +1304,7 @@ aoecmd_cfg(ushort aoemajor, unsigned char aoeminor)
 	aoecmd_cfg_pkts(aoemajor, aoeminor, &queue);
 	aoenet_xmit(&queue);
 }
- 
+
 struct sk_buff *
 aoecmd_ata_id(struct aoedev *d)
 {
@@ -1227,6 +1330,7 @@ aoecmd_ata_id(struct aoedev *d)
 	fhash(f);
 	t->nout++;
 	f->waited = 0;
+	f->waited_total = 0;
 
 	/* set up ata header */
 	ah->scnt = 1;
@@ -1235,12 +1339,19 @@ aoecmd_ata_id(struct aoedev *d)
 
 	skb->dev = t->ifp->nd;
 
-	d->rttavg = MAXTIMER;
+	d->rttavg = RTTAVG_INIT;
+	d->rttdev = RTTDEV_INIT;
 	d->timer.function = rexmit_timer;
 
-	return skb_clone(skb, GFP_ATOMIC);
+	skb = skb_clone(skb, GFP_ATOMIC);
+	if (skb) {
+		do_gettimeofday(&f->sent);
+		f->sent_jiffs = (u32) jiffies;
+	}
+
+	return skb;
 }
- 
+
 static struct aoetgt *
 addtgt(struct aoedev *d, char *addr, ulong nframes)
 {
@@ -1267,7 +1378,7 @@ addtgt(struct aoedev *d, char *addr, ulong nframes)
 	t->d = d;
 	memcpy(t->addr, addr, sizeof t->addr);
 	t->ifp = t->ifs;
-	t->maxout = t->nframes;
+	aoecmd_wreset(t);
 	INIT_LIST_HEAD(&t->ffree);
 	return *tt = t;
 }
@@ -1373,7 +1484,11 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
 	spin_lock_irqsave(&d->lock, flags);
 
 	t = gettgt(d, h->src);
-	if (!t) {
+	if (t) {
+		t->nframes = n;
+		if (n < t->maxout)
+			aoecmd_wreset(t);
+	} else {
 		t = addtgt(d, h->src, n);
 		if (!t)
 			goto bail;
@@ -1402,17 +1517,26 @@ bail:
 }
 
 void
+aoecmd_wreset(struct aoetgt *t)
+{
+	t->maxout = 1;
+	t->ssthresh = t->nframes / 2;
+	t->next_cwnd = t->nframes;
+}
+
+void
 aoecmd_cleanslate(struct aoedev *d)
 {
 	struct aoetgt **t, **te;
 
-	d->mintimer = MINTIMER;
+	d->rttavg = RTTAVG_INIT;
+	d->rttdev = RTTDEV_INIT;
 	d->maxbcnt = 0;
 
 	t = d->targets;
 	te = t + NTARGETS;
 	for (; t < te && *t; t++)
-		(*t)->maxout = (*t)->nframes;
+		aoecmd_wreset(*t);
 }
 
 void
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index 90e5b53..aaaea66 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -69,25 +69,34 @@ minor_get_static(ulong *sysminor, ulong aoemaj, int aoemin)
 		NPERSHELF = 16,
 	};
 
+	if (aoemin >= NPERSHELF) {
+		pr_err("aoe: %s %d slots per shelf\n",
+			"static minor device numbers support only",
+			NPERSHELF);
+		error = -1;
+		goto out;
+	}
+
 	n = aoemaj * NPERSHELF + aoemin;
-	if (aoemin >= NPERSHELF || n >= N_DEVS) {
+	if (n >= N_DEVS) {
 		pr_err("aoe: %s with e%ld.%d\n",
 			"cannot use static minor device numbers",
 			aoemaj, aoemin);
 		error = -1;
-	} else {
-		spin_lock_irqsave(&used_minors_lock, flags);
-		if (test_bit(n, used_minors)) {
-			pr_err("aoe: %s %lu\n",
-				"existing device already has static minor number",
-				n);
-			error = -1;
-		} else
-			set_bit(n, used_minors);
-		spin_unlock_irqrestore(&used_minors_lock, flags);
+		goto out;
 	}
 
-	*sysminor = n;
+	spin_lock_irqsave(&used_minors_lock, flags);
+	if (test_bit(n, used_minors)) {
+		pr_err("aoe: %s %lu\n",
+			"existing device already has static minor number",
+			n);
+		error = -1;
+	} else
+		set_bit(n, used_minors);
+	spin_unlock_irqrestore(&used_minors_lock, flags);
+	*sysminor = n * AOE_PARTITIONS;
+out:
 	return error;
 }
 
@@ -170,35 +179,45 @@ aoe_failip(struct aoedev *d)
 		aoe_end_request(d, rq, 0);
 }
 
+static void
+downdev_frame(struct list_head *pos)
+{
+	struct frame *f;
+
+	f = list_entry(pos, struct frame, head);
+	list_del(pos);
+	if (f->buf) {
+		f->buf->nframesout--;
+		aoe_failbuf(f->t->d, f->buf);
+	}
+	aoe_freetframe(f);
+}
+
 void
 aoedev_downdev(struct aoedev *d)
 {
 	struct aoetgt *t, **tt, **te;
-	struct frame *f;
 	struct list_head *head, *pos, *nx;
 	struct request *rq;
 	int i;
 
 	d->flags &= ~DEVFL_UP;
 
-	/* clean out active buffers */
+	/* clean out active and to-be-retransmitted buffers */
 	for (i = 0; i < NFACTIVE; i++) {
 		head = &d->factive[i];
-		list_for_each_safe(pos, nx, head) {
-			f = list_entry(pos, struct frame, head);
-			list_del(pos);
-			if (f->buf) {
-				f->buf->nframesout--;
-				aoe_failbuf(d, f->buf);
-			}
-			aoe_freetframe(f);
-		}
+		list_for_each_safe(pos, nx, head)
+			downdev_frame(pos);
 	}
+	head = &d->rexmitq;
+	list_for_each_safe(pos, nx, head)
+		downdev_frame(pos);
+
 	/* reset window dressings */
 	tt = d->targets;
 	te = tt + NTARGETS;
 	for (; tt < te && (t = *tt); tt++) {
-		t->maxout = t->nframes;
+		aoecmd_wreset(t);
 		t->nout = 0;
 	}
 
@@ -241,6 +260,30 @@ aoedev_freedev(struct aoedev *d)
 	kfree(d);
 }
 
+/* return whether the user asked for this particular
+ * device to be flushed
+ */
+static int
+user_req(char *s, size_t slen, struct aoedev *d)
+{
+	char *p;
+	size_t lim;
+
+	if (!d->gd)
+		return 0;
+	p = strrchr(d->gd->disk_name, '/');
+	if (!p)
+		p = d->gd->disk_name;
+	else
+		p += 1;
+	lim = sizeof(d->gd->disk_name);
+	lim -= p - d->gd->disk_name;
+	if (slen < lim)
+		lim = slen;
+
+	return !strncmp(s, p, lim);
+}
+
 int
 aoedev_flush(const char __user *str, size_t cnt)
 {
@@ -249,6 +292,7 @@ aoedev_flush(const char __user *str, size_t cnt)
 	struct aoedev *rmd = NULL;
 	char buf[16];
 	int all = 0;
+	int specified = 0;	/* flush a specific device */
 
 	if (cnt >= 3) {
 		if (cnt > sizeof buf)
@@ -256,26 +300,33 @@ aoedev_flush(const char __user *str, size_t cnt)
 		if (copy_from_user(buf, str, cnt))
 			return -EFAULT;
 		all = !strncmp(buf, "all", 3);
+		if (!all)
+			specified = 1;
 	}
 
 	spin_lock_irqsave(&devlist_lock, flags);
 	dd = &devlist;
 	while ((d = *dd)) {
 		spin_lock(&d->lock);
-		if ((!all && (d->flags & DEVFL_UP))
+		if (specified) {
+			if (!user_req(buf, cnt, d))
+				goto skip;
+		} else if ((!all && (d->flags & DEVFL_UP))
 		|| (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE))
 		|| d->nopen
-		|| d->ref) {
-			spin_unlock(&d->lock);
-			dd = &d->next;
-			continue;
-		}
+		|| d->ref)
+			goto skip;
+
 		*dd = d->next;
 		aoedev_downdev(d);
 		d->flags |= DEVFL_TKILL;
 		spin_unlock(&d->lock);
 		d->next = rmd;
 		rmd = d;
+		continue;
+skip:
+		spin_unlock(&d->lock);
+		dd = &d->next;
 	}
 	spin_unlock_irqrestore(&devlist_lock, flags);
 	while ((d = rmd)) {
@@ -332,7 +383,7 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc)
 	struct aoedev *d;
 	int i;
 	ulong flags;
-	ulong sysminor;
+	ulong sysminor = 0;
 
 	spin_lock_irqsave(&devlist_lock, flags);
 
@@ -359,10 +410,12 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc)
 	d->ref = 1;
 	for (i = 0; i < NFACTIVE; i++)
 		INIT_LIST_HEAD(&d->factive[i]);
+	INIT_LIST_HEAD(&d->rexmitq);
 	d->sysminor = sysminor;
 	d->aoemajor = maj;
 	d->aoeminor = min;
-	d->mintimer = MINTIMER;
+	d->rttavg = RTTAVG_INIT;
+	d->rttdev = RTTDEV_INIT;
 	d->next = devlist;
 	devlist = d;
  out:
diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c
index 04793c2..4b987c2 100644
--- a/drivers/block/aoe/aoemain.c
+++ b/drivers/block/aoe/aoemain.c
@@ -105,7 +105,7 @@ aoe_init(void)
 	aoechr_exit();
  chr_fail:
 	aoedev_exit();
-	
+
 	printk(KERN_INFO "aoe: initialisation failure.\n");
 	return ret;
 }
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
index 162c647..2e47404 100644
--- a/drivers/block/aoe/aoenet.c
+++ b/drivers/block/aoe/aoenet.c
@@ -52,13 +52,18 @@ static struct sk_buff_head skbtxq;
 
 /* enters with txlock held */
 static int
-tx(void)
+tx(void) __must_hold(&txlock)
 {
 	struct sk_buff *skb;
+	struct net_device *ifp;
 
 	while ((skb = skb_dequeue(&skbtxq))) {
 		spin_unlock_irq(&txlock);
-		dev_queue_xmit(skb);
+		ifp = skb->dev;
+		if (dev_queue_xmit(skb) == NET_XMIT_DROP && net_ratelimit())
+			pr_warn("aoe: packet could not be sent on %s.  %s\n",
+				ifp ? ifp->name : "netif",
+				"consider increasing tx_queue_len");
 		spin_lock_irq(&txlock);
 	}
 	return 0;
@@ -119,8 +124,8 @@ aoenet_xmit(struct sk_buff_head *queue)
 	}
 }
 
-/* 
- * (1) len doesn't include the header by default.  I want this. 
+/*
+ * (1) len doesn't include the header by default.  I want this.
  */
 static int
 aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev)
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index ca83f96..6526157 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -41,8 +41,9 @@
 #include <linux/spinlock.h>
 #include <linux/compat.h>
 #include <linux/mutex.h>
+#include <linux/bitmap.h>
+#include <linux/io.h>
 #include <asm/uaccess.h>
-#include <asm/io.h>
 
 #include <linux/dma-mapping.h>
 #include <linux/blkdev.h>
@@ -978,8 +979,7 @@ static CommandList_struct *cmd_alloc(ctlr_info_t *h)
 		i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds);
 		if (i == h->nr_cmds)
 			return NULL;
-	} while (test_and_set_bit(i & (BITS_PER_LONG - 1),
-		  h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0);
+	} while (test_and_set_bit(i, h->cmd_pool_bits) != 0);
 	c = h->cmd_pool + i;
 	memset(c, 0, sizeof(CommandList_struct));
 	cmd_dma_handle = h->cmd_pool_dhandle + i * sizeof(CommandList_struct);
@@ -1046,8 +1046,7 @@ static void cmd_free(ctlr_info_t *h, CommandList_struct *c)
 	int i;
 
 	i = c - h->cmd_pool;
-	clear_bit(i & (BITS_PER_LONG - 1),
-		  h->cmd_pool_bits + (i / BITS_PER_LONG));
+	clear_bit(i, h->cmd_pool_bits);
 	h->nr_frees++;
 }
 
@@ -4268,10 +4267,7 @@ static void __devinit cciss_find_board_params(ctlr_info_t *h)
 
 static inline bool CISS_signature_present(ctlr_info_t *h)
 {
-	if ((readb(&h->cfgtable->Signature[0]) != 'C') ||
-	    (readb(&h->cfgtable->Signature[1]) != 'I') ||
-	    (readb(&h->cfgtable->Signature[2]) != 'S') ||
-	    (readb(&h->cfgtable->Signature[3]) != 'S')) {
+	if (!check_signature(h->cfgtable->Signature, "CISS", 4)) {
 		dev_warn(&h->pdev->dev, "not a valid CISS config table\n");
 		return false;
 	}
@@ -4812,8 +4808,7 @@ static __devinit int cciss_init_reset_devices(struct pci_dev *pdev)
 
 static __devinit int cciss_allocate_cmd_pool(ctlr_info_t *h)
 {
-	h->cmd_pool_bits = kmalloc(
-		DIV_ROUND_UP(h->nr_cmds, BITS_PER_LONG) *
+	h->cmd_pool_bits = kmalloc(BITS_TO_LONGS(h->nr_cmds) *
 		sizeof(unsigned long), GFP_KERNEL);
 	h->cmd_pool = pci_alloc_consistent(h->pdev,
 		h->nr_cmds * sizeof(CommandList_struct),
@@ -5068,9 +5063,7 @@ reinit_after_soft_reset:
 	pci_set_drvdata(pdev, h);
 	/* command and error info recs zeroed out before
 	   they are used */
-	memset(h->cmd_pool_bits, 0,
-	       DIV_ROUND_UP(h->nr_cmds, BITS_PER_LONG)
-			* sizeof(unsigned long));
+	bitmap_zero(h->cmd_pool_bits, h->nr_cmds);
 
 	h->num_luns = 0;
 	h->highest_lun = -1;
diff --git a/drivers/block/drbd/Makefile b/drivers/block/drbd/Makefile
index 0d3f337..8b45033 100644
--- a/drivers/block/drbd/Makefile
+++ b/drivers/block/drbd/Makefile
@@ -1,5 +1,7 @@
 drbd-y := drbd_bitmap.o drbd_proc.o
 drbd-y += drbd_worker.o drbd_receiver.o drbd_req.o drbd_actlog.o
 drbd-y += drbd_main.o drbd_strings.o drbd_nl.o
+drbd-y += drbd_interval.o drbd_state.o
+drbd-y += drbd_nla.o
 
 obj-$(CONFIG_BLK_DEV_DRBD)     += drbd.o
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index 3fbef01..92510f8 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -24,21 +24,73 @@
  */
 
 #include <linux/slab.h>
+#include <linux/crc32c.h>
 #include <linux/drbd.h>
+#include <linux/drbd_limits.h>
+#include <linux/dynamic_debug.h>
 #include "drbd_int.h"
 #include "drbd_wrappers.h"
 
-/* We maintain a trivial checksum in our on disk activity log.
- * With that we can ensure correct operation even when the storage
- * device might do a partial (last) sector write while losing power.
- */
-struct __packed al_transaction {
-	u32       magic;
-	u32       tr_number;
-	struct __packed {
-		u32 pos;
-		u32 extent; } updates[1 + AL_EXTENTS_PT];
-	u32       xor_sum;
+
+enum al_transaction_types {
+	AL_TR_UPDATE = 0,
+	AL_TR_INITIALIZED = 0xffff
+};
+/* all fields on disc in big endian */
+struct __packed al_transaction_on_disk {
+	/* don't we all like magic */
+	__be32	magic;
+
+	/* to identify the most recent transaction block
+	 * in the on disk ring buffer */
+	__be32	tr_number;
+
+	/* checksum on the full 4k block, with this field set to 0. */
+	__be32	crc32c;
+
+	/* type of transaction, special transaction types like:
+	 * purge-all, set-all-idle, set-all-active, ... to-be-defined
+	 * see also enum al_transaction_types */
+	__be16	transaction_type;
+
+	/* we currently allow only a few thousand extents,
+	 * so 16bit will be enough for the slot number. */
+
+	/* how many updates in this transaction */
+	__be16	n_updates;
+
+	/* maximum slot number, "al-extents" in drbd.conf speak.
+	 * Having this in each transaction should make reconfiguration
+	 * of that parameter easier. */
+	__be16	context_size;
+
+	/* slot number the context starts with */
+	__be16	context_start_slot_nr;
+
+	/* Some reserved bytes.  Expected usage is a 64bit counter of
+	 * sectors-written since device creation, and other data generation tag
+	 * supporting usage */
+	__be32	__reserved[4];
+
+	/* --- 36 byte used --- */
+
+	/* Reserve space for up to AL_UPDATES_PER_TRANSACTION changes
+	 * in one transaction, then use the remaining byte in the 4k block for
+	 * context information.  "Flexible" number of updates per transaction
+	 * does not help, as we have to account for the case when all update
+	 * slots are used anyways, so it would only complicate code without
+	 * additional benefit.
+	 */
+	__be16	update_slot_nr[AL_UPDATES_PER_TRANSACTION];
+
+	/* but the extent number is 32bit, which at an extent size of 4 MiB
+	 * allows to cover device sizes of up to 2**54 Byte (16 PiB) */
+	__be32	update_extent_nr[AL_UPDATES_PER_TRANSACTION];
+
+	/* --- 420 bytes used (36 + 64*6) --- */
+
+	/* 4096 - 420 = 3676 = 919 * 4 */
+	__be32	context[AL_CONTEXT_PER_TRANSACTION];
 };
 
 struct update_odbm_work {
@@ -48,22 +100,11 @@ struct update_odbm_work {
 
 struct update_al_work {
 	struct drbd_work w;
-	struct lc_element *al_ext;
 	struct completion event;
-	unsigned int enr;
-	/* if old_enr != LC_FREE, write corresponding bitmap sector, too */
-	unsigned int old_enr;
-};
-
-struct drbd_atodb_wait {
-	atomic_t           count;
-	struct completion  io_done;
-	struct drbd_conf   *mdev;
-	int                error;
+	int err;
 };
 
-
-int w_al_write_transaction(struct drbd_conf *, struct drbd_work *, int);
+static int al_write_transaction(struct drbd_conf *mdev);
 
 void *drbd_md_get_buffer(struct drbd_conf *mdev)
 {
@@ -82,22 +123,24 @@ void drbd_md_put_buffer(struct drbd_conf *mdev)
 		wake_up(&mdev->misc_wait);
 }
 
-static bool md_io_allowed(struct drbd_conf *mdev)
-{
-	enum drbd_disk_state ds = mdev->state.disk;
-	return ds >= D_NEGOTIATING || ds == D_ATTACHING;
-}
-
-void wait_until_done_or_disk_failure(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
+void wait_until_done_or_force_detached(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
 				     unsigned int *done)
 {
-	long dt = bdev->dc.disk_timeout * HZ / 10;
+	long dt;
+
+	rcu_read_lock();
+	dt = rcu_dereference(bdev->disk_conf)->disk_timeout;
+	rcu_read_unlock();
+	dt = dt * HZ / 10;
 	if (dt == 0)
 		dt = MAX_SCHEDULE_TIMEOUT;
 
-	dt = wait_event_timeout(mdev->misc_wait, *done || !md_io_allowed(mdev), dt);
-	if (dt == 0)
+	dt = wait_event_timeout(mdev->misc_wait,
+			*done || test_bit(FORCE_DETACH, &mdev->flags), dt);
+	if (dt == 0) {
 		dev_err(DEV, "meta-data IO operation timed out\n");
+		drbd_chk_io_error(mdev, 1, DRBD_FORCE_DETACH);
+	}
 }
 
 static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
@@ -106,7 +149,7 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
 				 int rw, int size)
 {
 	struct bio *bio;
-	int ok;
+	int err;
 
 	mdev->md_io.done = 0;
 	mdev->md_io.error = -ENODEV;
@@ -118,8 +161,8 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
 	bio = bio_alloc_drbd(GFP_NOIO);
 	bio->bi_bdev = bdev->md_bdev;
 	bio->bi_sector = sector;
-	ok = (bio_add_page(bio, page, size, 0) == size);
-	if (!ok)
+	err = -EIO;
+	if (bio_add_page(bio, page, size, 0) != size)
 		goto out;
 	bio->bi_private = &mdev->md_io;
 	bio->bi_end_io = drbd_md_io_complete;
@@ -127,7 +170,7 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
 
 	if (!get_ldev_if_state(mdev, D_ATTACHING)) {  /* Corresponding put_ldev in drbd_md_io_complete() */
 		dev_err(DEV, "ASSERT FAILED: get_ldev_if_state() == 1 in _drbd_md_sync_page_io()\n");
-		ok = 0;
+		err = -ENODEV;
 		goto out;
 	}
 
@@ -137,86 +180,47 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
 		bio_endio(bio, -EIO);
 	else
 		submit_bio(rw, bio);
-	wait_until_done_or_disk_failure(mdev, bdev, &mdev->md_io.done);
-	ok = bio_flagged(bio, BIO_UPTODATE) && mdev->md_io.error == 0;
+	wait_until_done_or_force_detached(mdev, bdev, &mdev->md_io.done);
+	if (bio_flagged(bio, BIO_UPTODATE))
+		err = mdev->md_io.error;
 
  out:
 	bio_put(bio);
-	return ok;
+	return err;
 }
 
 int drbd_md_sync_page_io(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
 			 sector_t sector, int rw)
 {
-	int logical_block_size, mask, ok;
-	int offset = 0;
+	int err;
 	struct page *iop = mdev->md_io_page;
 
 	D_ASSERT(atomic_read(&mdev->md_io_in_use) == 1);
 
 	BUG_ON(!bdev->md_bdev);
 
-	logical_block_size = bdev_logical_block_size(bdev->md_bdev);
-	if (logical_block_size == 0)
-		logical_block_size = MD_SECTOR_SIZE;
-
-	/* in case logical_block_size != 512 [ s390 only? ] */
-	if (logical_block_size != MD_SECTOR_SIZE) {
-		mask = (logical_block_size / MD_SECTOR_SIZE) - 1;
-		D_ASSERT(mask == 1 || mask == 3 || mask == 7);
-		D_ASSERT(logical_block_size == (mask+1) * MD_SECTOR_SIZE);
-		offset = sector & mask;
-		sector = sector & ~mask;
-		iop = mdev->md_io_tmpp;
-
-		if (rw & WRITE) {
-			/* these are GFP_KERNEL pages, pre-allocated
-			 * on device initialization */
-			void *p = page_address(mdev->md_io_page);
-			void *hp = page_address(mdev->md_io_tmpp);
-
-			ok = _drbd_md_sync_page_io(mdev, bdev, iop, sector,
-					READ, logical_block_size);
-
-			if (unlikely(!ok)) {
-				dev_err(DEV, "drbd_md_sync_page_io(,%llus,"
-				    "READ [logical_block_size!=512]) failed!\n",
-				    (unsigned long long)sector);
-				return 0;
-			}
-
-			memcpy(hp + offset*MD_SECTOR_SIZE, p, MD_SECTOR_SIZE);
-		}
-	}
+	dev_dbg(DEV, "meta_data io: %s [%d]:%s(,%llus,%s)\n",
+	     current->comm, current->pid, __func__,
+	     (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ");
 
 	if (sector < drbd_md_first_sector(bdev) ||
-	    sector > drbd_md_last_sector(bdev))
+	    sector + 7 > drbd_md_last_sector(bdev))
 		dev_alert(DEV, "%s [%d]:%s(,%llus,%s) out of range md access!\n",
 		     current->comm, current->pid, __func__,
 		     (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ");
 
-	ok = _drbd_md_sync_page_io(mdev, bdev, iop, sector, rw, logical_block_size);
-	if (unlikely(!ok)) {
-		dev_err(DEV, "drbd_md_sync_page_io(,%llus,%s) failed!\n",
-		    (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ");
-		return 0;
-	}
-
-	if (logical_block_size != MD_SECTOR_SIZE && !(rw & WRITE)) {
-		void *p = page_address(mdev->md_io_page);
-		void *hp = page_address(mdev->md_io_tmpp);
-
-		memcpy(p, hp + offset*MD_SECTOR_SIZE, MD_SECTOR_SIZE);
+	err = _drbd_md_sync_page_io(mdev, bdev, iop, sector, rw, MD_BLOCK_SIZE);
+	if (err) {
+		dev_err(DEV, "drbd_md_sync_page_io(,%llus,%s) failed with error %d\n",
+		    (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ", err);
 	}
-
-	return ok;
+	return err;
 }
 
 static struct lc_element *_al_get(struct drbd_conf *mdev, unsigned int enr)
 {
 	struct lc_element *al_ext;
 	struct lc_element *tmp;
-	unsigned long     al_flags = 0;
 	int wake;
 
 	spin_lock_irq(&mdev->al_lock);
@@ -231,76 +235,92 @@ static struct lc_element *_al_get(struct drbd_conf *mdev, unsigned int enr)
 			return NULL;
 		}
 	}
-	al_ext   = lc_get(mdev->act_log, enr);
-	al_flags = mdev->act_log->flags;
+	al_ext = lc_get(mdev->act_log, enr);
 	spin_unlock_irq(&mdev->al_lock);
-
-	/*
-	if (!al_ext) {
-		if (al_flags & LC_STARVING)
-			dev_warn(DEV, "Have to wait for LRU element (AL too small?)\n");
-		if (al_flags & LC_DIRTY)
-			dev_warn(DEV, "Ongoing AL update (AL device too slow?)\n");
-	}
-	*/
-
 	return al_ext;
 }
 
-void drbd_al_begin_io(struct drbd_conf *mdev, sector_t sector)
+void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i)
 {
-	unsigned int enr = (sector >> (AL_EXTENT_SHIFT-9));
-	struct lc_element *al_ext;
-	struct update_al_work al_work;
+	/* for bios crossing activity log extent boundaries,
+	 * we may need to activate two extents in one go */
+	unsigned first = i->sector >> (AL_EXTENT_SHIFT-9);
+	unsigned last = i->size == 0 ? first : (i->sector + (i->size >> 9) - 1) >> (AL_EXTENT_SHIFT-9);
+	unsigned enr;
+	bool locked = false;
 
+
+	D_ASSERT(first <= last);
 	D_ASSERT(atomic_read(&mdev->local_cnt) > 0);
 
-	wait_event(mdev->al_wait, (al_ext = _al_get(mdev, enr)));
+	for (enr = first; enr <= last; enr++)
+		wait_event(mdev->al_wait, _al_get(mdev, enr) != NULL);
+
+	/* Serialize multiple transactions.
+	 * This uses test_and_set_bit, memory barrier is implicit.
+	 */
+	wait_event(mdev->al_wait,
+			mdev->act_log->pending_changes == 0 ||
+			(locked = lc_try_lock_for_transaction(mdev->act_log)));
 
-	if (al_ext->lc_number != enr) {
+	if (locked) {
 		/* drbd_al_write_transaction(mdev,al_ext,enr);
 		 * recurses into generic_make_request(), which
 		 * disallows recursion, bios being serialized on the
 		 * current->bio_tail list now.
 		 * we have to delegate updates to the activity log
 		 * to the worker thread. */
-		init_completion(&al_work.event);
-		al_work.al_ext = al_ext;
-		al_work.enr = enr;
-		al_work.old_enr = al_ext->lc_number;
-		al_work.w.cb = w_al_write_transaction;
-		drbd_queue_work_front(&mdev->data.work, &al_work.w);
-		wait_for_completion(&al_work.event);
-
-		mdev->al_writ_cnt++;
-
-		spin_lock_irq(&mdev->al_lock);
-		lc_changed(mdev->act_log, al_ext);
-		spin_unlock_irq(&mdev->al_lock);
+
+		/* Double check: it may have been committed by someone else,
+		 * while we have been waiting for the lock. */
+		if (mdev->act_log->pending_changes) {
+			bool write_al_updates;
+
+			rcu_read_lock();
+			write_al_updates = rcu_dereference(mdev->ldev->disk_conf)->al_updates;
+			rcu_read_unlock();
+
+			if (write_al_updates) {
+				al_write_transaction(mdev);
+				mdev->al_writ_cnt++;
+			}
+
+			spin_lock_irq(&mdev->al_lock);
+			/* FIXME
+			if (err)
+				we need an "lc_cancel" here;
+			*/
+			lc_committed(mdev->act_log);
+			spin_unlock_irq(&mdev->al_lock);
+		}
+		lc_unlock(mdev->act_log);
 		wake_up(&mdev->al_wait);
 	}
 }
 
-void drbd_al_complete_io(struct drbd_conf *mdev, sector_t sector)
+void drbd_al_complete_io(struct drbd_conf *mdev, struct drbd_interval *i)
 {
-	unsigned int enr = (sector >> (AL_EXTENT_SHIFT-9));
+	/* for bios crossing activity log extent boundaries,
+	 * we may need to activate two extents in one go */
+	unsigned first = i->sector >> (AL_EXTENT_SHIFT-9);
+	unsigned last = i->size == 0 ? first : (i->sector + (i->size >> 9) - 1) >> (AL_EXTENT_SHIFT-9);
+	unsigned enr;
 	struct lc_element *extent;
 	unsigned long flags;
 
+	D_ASSERT(first <= last);
 	spin_lock_irqsave(&mdev->al_lock, flags);
 
-	extent = lc_find(mdev->act_log, enr);
-
-	if (!extent) {
-		spin_unlock_irqrestore(&mdev->al_lock, flags);
-		dev_err(DEV, "al_complete_io() called on inactive extent %u\n", enr);
-		return;
+	for (enr = first; enr <= last; enr++) {
+		extent = lc_find(mdev->act_log, enr);
+		if (!extent) {
+			dev_err(DEV, "al_complete_io() called on inactive extent %u\n", enr);
+			continue;
+		}
+		lc_put(mdev->act_log, extent);
 	}
-
-	if (lc_put(mdev->act_log, extent) == 0)
-		wake_up(&mdev->al_wait);
-
 	spin_unlock_irqrestore(&mdev->al_lock, flags);
+	wake_up(&mdev->al_wait);
 }
 
 #if (PAGE_SHIFT + 3) < (AL_EXTENT_SHIFT - BM_BLOCK_SHIFT)
@@ -326,296 +346,148 @@ static unsigned int rs_extent_to_bm_page(unsigned int rs_enr)
 	return rs_enr >>
 		/* bit to page */
 		((PAGE_SHIFT + 3) -
-		/* al extent number to bit */
+		/* resync extent number to bit */
 		 (BM_EXT_SHIFT - BM_BLOCK_SHIFT));
 }
 
-int
-w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused)
+static int
+_al_write_transaction(struct drbd_conf *mdev)
 {
-	struct update_al_work *aw = container_of(w, struct update_al_work, w);
-	struct lc_element *updated = aw->al_ext;
-	const unsigned int new_enr = aw->enr;
-	const unsigned int evicted = aw->old_enr;
-	struct al_transaction *buffer;
+	struct al_transaction_on_disk *buffer;
+	struct lc_element *e;
 	sector_t sector;
-	int i, n, mx;
-	unsigned int extent_nr;
-	u32 xor_sum = 0;
+	int i, mx;
+	unsigned extent_nr;
+	unsigned crc = 0;
+	int err = 0;
 
 	if (!get_ldev(mdev)) {
-		dev_err(DEV,
-			"disk is %s, cannot start al transaction (-%d +%d)\n",
-			drbd_disk_str(mdev->state.disk), evicted, new_enr);
-		complete(&((struct update_al_work *)w)->event);
-		return 1;
+		dev_err(DEV, "disk is %s, cannot start al transaction\n",
+			drbd_disk_str(mdev->state.disk));
+		return -EIO;
 	}
-	/* do we have to do a bitmap write, first?
-	 * TODO reduce maximum latency:
-	 * submit both bios, then wait for both,
-	 * instead of doing two synchronous sector writes.
-	 * For now, we must not write the transaction,
-	 * if we cannot write out the bitmap of the evicted extent. */
-	if (mdev->state.conn < C_CONNECTED && evicted != LC_FREE)
-		drbd_bm_write_page(mdev, al_extent_to_bm_page(evicted));
 
 	/* The bitmap write may have failed, causing a state change. */
 	if (mdev->state.disk < D_INCONSISTENT) {
 		dev_err(DEV,
-			"disk is %s, cannot write al transaction (-%d +%d)\n",
-			drbd_disk_str(mdev->state.disk), evicted, new_enr);
-		complete(&((struct update_al_work *)w)->event);
+			"disk is %s, cannot write al transaction\n",
+			drbd_disk_str(mdev->state.disk));
 		put_ldev(mdev);
-		return 1;
+		return -EIO;
 	}
 
 	buffer = drbd_md_get_buffer(mdev); /* protects md_io_buffer, al_tr_cycle, ... */
 	if (!buffer) {
 		dev_err(DEV, "disk failed while waiting for md_io buffer\n");
-		complete(&((struct update_al_work *)w)->event);
 		put_ldev(mdev);
-		return 1;
+		return -ENODEV;
 	}
 
-	buffer->magic = __constant_cpu_to_be32(DRBD_MAGIC);
+	memset(buffer, 0, sizeof(*buffer));
+	buffer->magic = cpu_to_be32(DRBD_AL_MAGIC);
 	buffer->tr_number = cpu_to_be32(mdev->al_tr_number);
 
-	n = lc_index_of(mdev->act_log, updated);
+	i = 0;
+
+	/* Even though no one can start to change this list
+	 * once we set the LC_LOCKED -- from drbd_al_begin_io(),
+	 * lc_try_lock_for_transaction() --, someone may still
+	 * be in the process of changing it. */
+	spin_lock_irq(&mdev->al_lock);
+	list_for_each_entry(e, &mdev->act_log->to_be_changed, list) {
+		if (i == AL_UPDATES_PER_TRANSACTION) {
+			i++;
+			break;
+		}
+		buffer->update_slot_nr[i] = cpu_to_be16(e->lc_index);
+		buffer->update_extent_nr[i] = cpu_to_be32(e->lc_new_number);
+		if (e->lc_number != LC_FREE)
+			drbd_bm_mark_for_writeout(mdev,
+					al_extent_to_bm_page(e->lc_number));
+		i++;
+	}
+	spin_unlock_irq(&mdev->al_lock);
+	BUG_ON(i > AL_UPDATES_PER_TRANSACTION);
 
-	buffer->updates[0].pos = cpu_to_be32(n);
-	buffer->updates[0].extent = cpu_to_be32(new_enr);
+	buffer->n_updates = cpu_to_be16(i);
+	for ( ; i < AL_UPDATES_PER_TRANSACTION; i++) {
+		buffer->update_slot_nr[i] = cpu_to_be16(-1);
+		buffer->update_extent_nr[i] = cpu_to_be32(LC_FREE);
+	}
 
-	xor_sum ^= new_enr;
+	buffer->context_size = cpu_to_be16(mdev->act_log->nr_elements);
+	buffer->context_start_slot_nr = cpu_to_be16(mdev->al_tr_cycle);
 
-	mx = min_t(int, AL_EXTENTS_PT,
+	mx = min_t(int, AL_CONTEXT_PER_TRANSACTION,
 		   mdev->act_log->nr_elements - mdev->al_tr_cycle);
 	for (i = 0; i < mx; i++) {
 		unsigned idx = mdev->al_tr_cycle + i;
 		extent_nr = lc_element_by_index(mdev->act_log, idx)->lc_number;
-		buffer->updates[i+1].pos = cpu_to_be32(idx);
-		buffer->updates[i+1].extent = cpu_to_be32(extent_nr);
-		xor_sum ^= extent_nr;
-	}
-	for (; i < AL_EXTENTS_PT; i++) {
-		buffer->updates[i+1].pos = __constant_cpu_to_be32(-1);
-		buffer->updates[i+1].extent = __constant_cpu_to_be32(LC_FREE);
-		xor_sum ^= LC_FREE;
+		buffer->context[i] = cpu_to_be32(extent_nr);
 	}
-	mdev->al_tr_cycle += AL_EXTENTS_PT;
+	for (; i < AL_CONTEXT_PER_TRANSACTION; i++)
+		buffer->context[i] = cpu_to_be32(LC_FREE);
+
+	mdev->al_tr_cycle += AL_CONTEXT_PER_TRANSACTION;
 	if (mdev->al_tr_cycle >= mdev->act_log->nr_elements)
 		mdev->al_tr_cycle = 0;
 
-	buffer->xor_sum = cpu_to_be32(xor_sum);
-
 	sector =  mdev->ldev->md.md_offset
-		+ mdev->ldev->md.al_offset + mdev->al_tr_pos;
-
-	if (!drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE))
-		drbd_chk_io_error(mdev, 1, DRBD_META_IO_ERROR);
+		+ mdev->ldev->md.al_offset
+		+ mdev->al_tr_pos * (MD_BLOCK_SIZE>>9);
 
-	if (++mdev->al_tr_pos >
-	    div_ceil(mdev->act_log->nr_elements, AL_EXTENTS_PT))
-		mdev->al_tr_pos = 0;
+	crc = crc32c(0, buffer, 4096);
+	buffer->crc32c = cpu_to_be32(crc);
 
-	D_ASSERT(mdev->al_tr_pos < MD_AL_MAX_SIZE);
-	mdev->al_tr_number++;
+	if (drbd_bm_write_hinted(mdev))
+		err = -EIO;
+		/* drbd_chk_io_error done already */
+	else if (drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
+		err = -EIO;
+		drbd_chk_io_error(mdev, 1, DRBD_META_IO_ERROR);
+	} else {
+		/* advance ringbuffer position and transaction counter */
+		mdev->al_tr_pos = (mdev->al_tr_pos + 1) % (MD_AL_SECTORS*512/MD_BLOCK_SIZE);
+		mdev->al_tr_number++;
+	}
 
 	drbd_md_put_buffer(mdev);
-
-	complete(&((struct update_al_work *)w)->event);
 	put_ldev(mdev);
 
-	return 1;
+	return err;
 }
 
-/**
- * drbd_al_read_tr() - Read a single transaction from the on disk activity log
- * @mdev:	DRBD device.
- * @bdev:	Block device to read form.
- * @b:		pointer to an al_transaction.
- * @index:	On disk slot of the transaction to read.
- *
- * Returns -1 on IO error, 0 on checksum error and 1 upon success.
- */
-static int drbd_al_read_tr(struct drbd_conf *mdev,
-			   struct drbd_backing_dev *bdev,
-			   struct al_transaction *b,
-			   int index)
-{
-	sector_t sector;
-	int rv, i;
-	u32 xor_sum = 0;
-
-	sector = bdev->md.md_offset + bdev->md.al_offset + index;
-
-	/* Dont process error normally,
-	 * as this is done before disk is attached! */
-	if (!drbd_md_sync_page_io(mdev, bdev, sector, READ))
-		return -1;
-
-	rv = (be32_to_cpu(b->magic) == DRBD_MAGIC);
-
-	for (i = 0; i < AL_EXTENTS_PT + 1; i++)
-		xor_sum ^= be32_to_cpu(b->updates[i].extent);
-	rv &= (xor_sum == be32_to_cpu(b->xor_sum));
 
-	return rv;
-}
-
-/**
- * drbd_al_read_log() - Restores the activity log from its on disk representation.
- * @mdev:	DRBD device.
- * @bdev:	Block device to read form.
- *
- * Returns 1 on success, returns 0 when reading the log failed due to IO errors.
- */
-int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
+static int w_al_write_transaction(struct drbd_work *w, int unused)
 {
-	struct al_transaction *buffer;
-	int i;
-	int rv;
-	int mx;
-	int active_extents = 0;
-	int transactions = 0;
-	int found_valid = 0;
-	int from = 0;
-	int to = 0;
-	u32 from_tnr = 0;
-	u32 to_tnr = 0;
-	u32 cnr;
-
-	mx = div_ceil(mdev->act_log->nr_elements, AL_EXTENTS_PT);
-
-	/* lock out all other meta data io for now,
-	 * and make sure the page is mapped.
-	 */
-	buffer = drbd_md_get_buffer(mdev);
-	if (!buffer)
-		return 0;
-
-	/* Find the valid transaction in the log */
-	for (i = 0; i <= mx; i++) {
-		rv = drbd_al_read_tr(mdev, bdev, buffer, i);
-		if (rv == 0)
-			continue;
-		if (rv == -1) {
-			drbd_md_put_buffer(mdev);
-			return 0;
-		}
-		cnr = be32_to_cpu(buffer->tr_number);
-
-		if (++found_valid == 1) {
-			from = i;
-			to = i;
-			from_tnr = cnr;
-			to_tnr = cnr;
-			continue;
-		}
-		if ((int)cnr - (int)from_tnr < 0) {
-			D_ASSERT(from_tnr - cnr + i - from == mx+1);
-			from = i;
-			from_tnr = cnr;
-		}
-		if ((int)cnr - (int)to_tnr > 0) {
-			D_ASSERT(cnr - to_tnr == i - to);
-			to = i;
-			to_tnr = cnr;
-		}
-	}
-
-	if (!found_valid) {
-		dev_warn(DEV, "No usable activity log found.\n");
-		drbd_md_put_buffer(mdev);
-		return 1;
-	}
-
-	/* Read the valid transactions.
-	 * dev_info(DEV, "Reading from %d to %d.\n",from,to); */
-	i = from;
-	while (1) {
-		int j, pos;
-		unsigned int extent_nr;
-		unsigned int trn;
-
-		rv = drbd_al_read_tr(mdev, bdev, buffer, i);
-		ERR_IF(rv == 0) goto cancel;
-		if (rv == -1) {
-			drbd_md_put_buffer(mdev);
-			return 0;
-		}
-
-		trn = be32_to_cpu(buffer->tr_number);
-
-		spin_lock_irq(&mdev->al_lock);
-
-		/* This loop runs backwards because in the cyclic
-		   elements there might be an old version of the
-		   updated element (in slot 0). So the element in slot 0
-		   can overwrite old versions. */
-		for (j = AL_EXTENTS_PT; j >= 0; j--) {
-			pos = be32_to_cpu(buffer->updates[j].pos);
-			extent_nr = be32_to_cpu(buffer->updates[j].extent);
-
-			if (extent_nr == LC_FREE)
-				continue;
-
-			lc_set(mdev->act_log, extent_nr, pos);
-			active_extents++;
-		}
-		spin_unlock_irq(&mdev->al_lock);
-
-		transactions++;
-
-cancel:
-		if (i == to)
-			break;
-		i++;
-		if (i > mx)
-			i = 0;
-	}
-
-	mdev->al_tr_number = to_tnr+1;
-	mdev->al_tr_pos = to;
-	if (++mdev->al_tr_pos >
-	    div_ceil(mdev->act_log->nr_elements, AL_EXTENTS_PT))
-		mdev->al_tr_pos = 0;
-
-	/* ok, we are done with it */
-	drbd_md_put_buffer(mdev);
+	struct update_al_work *aw = container_of(w, struct update_al_work, w);
+	struct drbd_conf *mdev = w->mdev;
+	int err;
 
-	dev_info(DEV, "Found %d transactions (%d active extents) in activity log.\n",
-	     transactions, active_extents);
+	err = _al_write_transaction(mdev);
+	aw->err = err;
+	complete(&aw->event);
 
-	return 1;
+	return err != -EIO ? err : 0;
 }
 
-/**
- * drbd_al_apply_to_bm() - Sets the bitmap to diry(1) where covered ba active AL extents
- * @mdev:	DRBD device.
- */
-void drbd_al_apply_to_bm(struct drbd_conf *mdev)
+/* Calls from worker context (see w_restart_disk_io()) need to write the
+   transaction directly. Others came through generic_make_request(),
+   those need to delegate it to the worker. */
+static int al_write_transaction(struct drbd_conf *mdev)
 {
-	unsigned int enr;
-	unsigned long add = 0;
-	char ppb[10];
-	int i, tmp;
-
-	wait_event(mdev->al_wait, lc_try_lock(mdev->act_log));
+	struct update_al_work al_work;
 
-	for (i = 0; i < mdev->act_log->nr_elements; i++) {
-		enr = lc_element_by_index(mdev->act_log, i)->lc_number;
-		if (enr == LC_FREE)
-			continue;
-		tmp = drbd_bm_ALe_set_all(mdev, enr);
-		dynamic_dev_dbg(DEV, "AL: set %d bits in extent %u\n", tmp, enr);
-		add += tmp;
-	}
+	if (current == mdev->tconn->worker.task)
+		return _al_write_transaction(mdev);
 
-	lc_unlock(mdev->act_log);
-	wake_up(&mdev->al_wait);
+	init_completion(&al_work.event);
+	al_work.w.cb = w_al_write_transaction;
+	al_work.w.mdev = mdev;
+	drbd_queue_work_front(&mdev->tconn->sender_work, &al_work.w);
+	wait_for_completion(&al_work.event);
 
-	dev_info(DEV, "Marked additional %s as out-of-sync based on AL.\n",
-	     ppsize(ppb, Bit2KB(add)));
+	return al_work.err;
 }
 
 static int _try_lc_del(struct drbd_conf *mdev, struct lc_element *al_ext)
@@ -645,7 +517,7 @@ void drbd_al_shrink(struct drbd_conf *mdev)
 	struct lc_element *al_ext;
 	int i;
 
-	D_ASSERT(test_bit(__LC_DIRTY, &mdev->act_log->flags));
+	D_ASSERT(test_bit(__LC_LOCKED, &mdev->act_log->flags));
 
 	for (i = 0; i < mdev->act_log->nr_elements; i++) {
 		al_ext = lc_element_by_index(mdev->act_log, i);
@@ -657,15 +529,17 @@ void drbd_al_shrink(struct drbd_conf *mdev)
 	wake_up(&mdev->al_wait);
 }
 
-static int w_update_odbm(struct drbd_conf *mdev, struct drbd_work *w, int unused)
+static int w_update_odbm(struct drbd_work *w, int unused)
 {
 	struct update_odbm_work *udw = container_of(w, struct update_odbm_work, w);
+	struct drbd_conf *mdev = w->mdev;
+	struct sib_info sib = { .sib_reason = SIB_SYNC_PROGRESS, };
 
 	if (!get_ldev(mdev)) {
 		if (__ratelimit(&drbd_ratelimit_state))
 			dev_warn(DEV, "Can not update on disk bitmap, local IO disabled.\n");
 		kfree(udw);
-		return 1;
+		return 0;
 	}
 
 	drbd_bm_write_page(mdev, rs_extent_to_bm_page(udw->enr));
@@ -683,9 +557,9 @@ static int w_update_odbm(struct drbd_conf *mdev, struct drbd_work *w, int unused
 			break;
 		}
 	}
-	drbd_bcast_sync_progress(mdev);
+	drbd_bcast_event(mdev, &sib);
 
-	return 1;
+	return 0;
 }
 
 
@@ -755,7 +629,9 @@ static void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector,
 			}
 			ext->rs_left = rs_left;
 			ext->rs_failed = success ? 0 : count;
-			lc_changed(mdev->resync, &ext->lce);
+			/* we don't keep a persistent log of the resync lru,
+			 * we can commit any change right away. */
+			lc_committed(mdev->resync);
 		}
 		lc_put(mdev->resync, &ext->lce);
 		/* no race, we are within the al_lock! */
@@ -767,7 +643,8 @@ static void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector,
 			if (udw) {
 				udw->enr = ext->lce.lc_number;
 				udw->w.cb = w_update_odbm;
-				drbd_queue_work_front(&mdev->data.work, &udw->w);
+				udw->w.mdev = mdev;
+				drbd_queue_work_front(&mdev->tconn->sender_work, &udw->w);
 			} else {
 				dev_warn(DEV, "Could not kmalloc an udw\n");
 			}
@@ -813,16 +690,22 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size,
 	int wake_up = 0;
 	unsigned long flags;
 
-	if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
+	if (size <= 0 || !IS_ALIGNED(size, 512) || size > DRBD_MAX_BIO_SIZE) {
 		dev_err(DEV, "drbd_set_in_sync: sector=%llus size=%d nonsense!\n",
 				(unsigned long long)sector, size);
 		return;
 	}
+
+	if (!get_ldev(mdev))
+		return; /* no disk, no metadata, no bitmap to clear bits in */
+
 	nr_sectors = drbd_get_capacity(mdev->this_bdev);
 	esector = sector + (size >> 9) - 1;
 
-	ERR_IF(sector >= nr_sectors) return;
-	ERR_IF(esector >= nr_sectors) esector = (nr_sectors-1);
+	if (!expect(sector < nr_sectors))
+		goto out;
+	if (!expect(esector < nr_sectors))
+		esector = nr_sectors - 1;
 
 	lbnr = BM_SECT_TO_BIT(nr_sectors-1);
 
@@ -830,7 +713,7 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size,
 	 * round up start sector, round down end sector.  we make sure we only
 	 * clear full, aligned, BM_BLOCK_SIZE (4K) blocks */
 	if (unlikely(esector < BM_SECT_PER_BIT-1))
-		return;
+		goto out;
 	if (unlikely(esector == (nr_sectors-1)))
 		ebnr = lbnr;
 	else
@@ -838,14 +721,14 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size,
 	sbnr = BM_SECT_TO_BIT(sector + BM_SECT_PER_BIT-1);
 
 	if (sbnr > ebnr)
-		return;
+		goto out;
 
 	/*
 	 * ok, (capacity & 7) != 0 sometimes, but who cares...
 	 * we count rs_{total,left} in bits, not sectors.
 	 */
 	count = drbd_bm_clear_bits(mdev, sbnr, ebnr);
-	if (count && get_ldev(mdev)) {
+	if (count) {
 		drbd_advance_rs_marks(mdev, drbd_bm_total_weight(mdev));
 		spin_lock_irqsave(&mdev->al_lock, flags);
 		drbd_try_clear_on_disk_bm(mdev, sector, count, true);
@@ -854,8 +737,9 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size,
 		/* just wake_up unconditional now, various lc_chaged(),
 		 * lc_put() in drbd_try_clear_on_disk_bm(). */
 		wake_up = 1;
-		put_ldev(mdev);
 	}
+out:
+	put_ldev(mdev);
 	if (wake_up)
 		wake_up(&mdev->al_wait);
 }
@@ -871,7 +755,7 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size,
 int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size,
 			    const char *file, const unsigned int line)
 {
-	unsigned long sbnr, ebnr, lbnr, flags;
+	unsigned long sbnr, ebnr, flags;
 	sector_t esector, nr_sectors;
 	unsigned int enr, count = 0;
 	struct lc_element *e;
@@ -880,7 +764,7 @@ int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size,
 	if (size == 0)
 		return 0;
 
-	if (size < 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
+	if (size < 0 || !IS_ALIGNED(size, 512) || size > DRBD_MAX_BIO_SIZE) {
 		dev_err(DEV, "sector: %llus, size: %d\n",
 			(unsigned long long)sector, size);
 		return 0;
@@ -892,12 +776,10 @@ int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size,
 	nr_sectors = drbd_get_capacity(mdev->this_bdev);
 	esector = sector + (size >> 9) - 1;
 
-	ERR_IF(sector >= nr_sectors)
+	if (!expect(sector < nr_sectors))
 		goto out;
-	ERR_IF(esector >= nr_sectors)
-		esector = (nr_sectors-1);
-
-	lbnr = BM_SECT_TO_BIT(nr_sectors-1);
+	if (!expect(esector < nr_sectors))
+		esector = nr_sectors - 1;
 
 	/* we set it out of sync,
 	 * we do not need to round anything here */
@@ -940,7 +822,7 @@ struct bm_extent *_bme_get(struct drbd_conf *mdev, unsigned int enr)
 		if (bm_ext->lce.lc_number != enr) {
 			bm_ext->rs_left = drbd_bm_e_weight(mdev, enr);
 			bm_ext->rs_failed = 0;
-			lc_changed(mdev->resync, &bm_ext->lce);
+			lc_committed(mdev->resync);
 			wakeup = 1;
 		}
 		if (bm_ext->lce.refcnt == 1)
@@ -956,7 +838,7 @@ struct bm_extent *_bme_get(struct drbd_conf *mdev, unsigned int enr)
 		if (rs_flags & LC_STARVING)
 			dev_warn(DEV, "Have to wait for element"
 			     " (resync LRU too small?)\n");
-		BUG_ON(rs_flags & LC_DIRTY);
+		BUG_ON(rs_flags & LC_LOCKED);
 	}
 
 	return bm_ext;
@@ -964,26 +846,12 @@ struct bm_extent *_bme_get(struct drbd_conf *mdev, unsigned int enr)
 
 static int _is_in_al(struct drbd_conf *mdev, unsigned int enr)
 {
-	struct lc_element *al_ext;
-	int rv = 0;
+	int rv;
 
 	spin_lock_irq(&mdev->al_lock);
-	if (unlikely(enr == mdev->act_log->new_number))
-		rv = 1;
-	else {
-		al_ext = lc_find(mdev->act_log, enr);
-		if (al_ext) {
-			if (al_ext->refcnt)
-				rv = 1;
-		}
-	}
+	rv = lc_is_used(mdev->act_log, enr);
 	spin_unlock_irq(&mdev->al_lock);
 
-	/*
-	if (unlikely(rv)) {
-		dev_info(DEV, "Delaying sync read until app's write is done\n");
-	}
-	*/
 	return rv;
 }
 
@@ -1113,13 +981,13 @@ int drbd_try_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
 			if (rs_flags & LC_STARVING)
 				dev_warn(DEV, "Have to wait for element"
 				     " (resync LRU too small?)\n");
-			BUG_ON(rs_flags & LC_DIRTY);
+			BUG_ON(rs_flags & LC_LOCKED);
 			goto try_again;
 		}
 		if (bm_ext->lce.lc_number != enr) {
 			bm_ext->rs_left = drbd_bm_e_weight(mdev, enr);
 			bm_ext->rs_failed = 0;
-			lc_changed(mdev->resync, &bm_ext->lce);
+			lc_committed(mdev->resync);
 			wake_up(&mdev->al_wait);
 			D_ASSERT(test_bit(BME_LOCKED, &bm_ext->flags) == 0);
 		}
@@ -1130,8 +998,6 @@ int drbd_try_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
 	}
 check_al:
 	for (i = 0; i < AL_EXT_PER_BM_SECT; i++) {
-		if (unlikely(al_enr+i == mdev->act_log->new_number))
-			goto try_again;
 		if (lc_is_used(mdev->act_log, al_enr+i))
 			goto try_again;
 	}
@@ -1266,7 +1132,7 @@ void drbd_rs_failed_io(struct drbd_conf *mdev, sector_t sector, int size)
 	sector_t esector, nr_sectors;
 	int wake_up = 0;
 
-	if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
+	if (size <= 0 || !IS_ALIGNED(size, 512) || size > DRBD_MAX_BIO_SIZE) {
 		dev_err(DEV, "drbd_rs_failed_io: sector=%llus size=%d nonsense!\n",
 				(unsigned long long)sector, size);
 		return;
@@ -1274,8 +1140,10 @@ void drbd_rs_failed_io(struct drbd_conf *mdev, sector_t sector, int size)
 	nr_sectors = drbd_get_capacity(mdev->this_bdev);
 	esector = sector + (size >> 9) - 1;
 
-	ERR_IF(sector >= nr_sectors) return;
-	ERR_IF(esector >= nr_sectors) esector = (nr_sectors-1);
+	if (!expect(sector < nr_sectors))
+		return;
+	if (!expect(esector < nr_sectors))
+		esector = nr_sectors - 1;
 
 	lbnr = BM_SECT_TO_BIT(nr_sectors-1);
 
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index d845664..8dc2950 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -119,13 +119,9 @@ static void __bm_print_lock_info(struct drbd_conf *mdev, const char *func)
 	if (!__ratelimit(&drbd_ratelimit_state))
 		return;
 	dev_err(DEV, "FIXME %s in %s, bitmap locked for '%s' by %s\n",
-	    current == mdev->receiver.task ? "receiver" :
-	    current == mdev->asender.task  ? "asender"  :
-	    current == mdev->worker.task   ? "worker"   : current->comm,
-	    func, b->bm_why ?: "?",
-	    b->bm_task == mdev->receiver.task ? "receiver" :
-	    b->bm_task == mdev->asender.task  ? "asender"  :
-	    b->bm_task == mdev->worker.task   ? "worker"   : "?");
+		drbd_task_to_thread_name(mdev->tconn, current),
+		func, b->bm_why ?: "?",
+		drbd_task_to_thread_name(mdev->tconn, b->bm_task));
 }
 
 void drbd_bm_lock(struct drbd_conf *mdev, char *why, enum bm_flag flags)
@@ -142,13 +138,9 @@ void drbd_bm_lock(struct drbd_conf *mdev, char *why, enum bm_flag flags)
 
 	if (trylock_failed) {
 		dev_warn(DEV, "%s going to '%s' but bitmap already locked for '%s' by %s\n",
-		    current == mdev->receiver.task ? "receiver" :
-		    current == mdev->asender.task  ? "asender"  :
-		    current == mdev->worker.task   ? "worker"   : current->comm,
-		    why, b->bm_why ?: "?",
-		    b->bm_task == mdev->receiver.task ? "receiver" :
-		    b->bm_task == mdev->asender.task  ? "asender"  :
-		    b->bm_task == mdev->worker.task   ? "worker"   : "?");
+			 drbd_task_to_thread_name(mdev->tconn, current),
+			 why, b->bm_why ?: "?",
+			 drbd_task_to_thread_name(mdev->tconn, b->bm_task));
 		mutex_lock(&b->bm_change);
 	}
 	if (BM_LOCKED_MASK & b->bm_flags)
@@ -196,6 +188,9 @@ void drbd_bm_unlock(struct drbd_conf *mdev)
 /* to mark for lazy writeout once syncer cleared all clearable bits,
  * we if bits have been cleared since last IO. */
 #define BM_PAGE_LAZY_WRITEOUT	28
+/* pages marked with this "HINT" will be considered for writeout
+ * on activity log transactions */
+#define BM_PAGE_HINT_WRITEOUT	27
 
 /* store_page_idx uses non-atomic assignment. It is only used directly after
  * allocating the page.  All other bm_set_page_* and bm_clear_page_* need to
@@ -227,8 +222,7 @@ static void bm_page_unlock_io(struct drbd_conf *mdev, int page_nr)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
 	void *addr = &page_private(b->bm_pages[page_nr]);
-	clear_bit(BM_PAGE_IO_LOCK, addr);
-	smp_mb__after_clear_bit();
+	clear_bit_unlock(BM_PAGE_IO_LOCK, addr);
 	wake_up(&mdev->bitmap->bm_io_wait);
 }
 
@@ -246,6 +240,27 @@ static void bm_set_page_need_writeout(struct page *page)
 	set_bit(BM_PAGE_NEED_WRITEOUT, &page_private(page));
 }
 
+/**
+ * drbd_bm_mark_for_writeout() - mark a page with a "hint" to be considered for writeout
+ * @mdev:	DRBD device.
+ * @page_nr:	the bitmap page to mark with the "hint" flag
+ *
+ * From within an activity log transaction, we mark a few pages with these
+ * hints, then call drbd_bm_write_hinted(), which will only write out changed
+ * pages which are flagged with this mark.
+ */
+void drbd_bm_mark_for_writeout(struct drbd_conf *mdev, int page_nr)
+{
+	struct page *page;
+	if (page_nr >= mdev->bitmap->bm_number_of_pages) {
+		dev_warn(DEV, "BAD: page_nr: %u, number_of_pages: %u\n",
+			 page_nr, (int)mdev->bitmap->bm_number_of_pages);
+		return;
+	}
+	page = mdev->bitmap->bm_pages[page_nr];
+	set_bit(BM_PAGE_HINT_WRITEOUT, &page_private(page));
+}
+
 static int bm_test_page_unchanged(struct page *page)
 {
 	volatile const unsigned long *addr = &page_private(page);
@@ -373,14 +388,16 @@ static struct page **bm_realloc_pages(struct drbd_bitmap *b, unsigned long want)
 		return old_pages;
 
 	/* Trying kmalloc first, falling back to vmalloc.
-	 * GFP_KERNEL is ok, as this is done when a lower level disk is
-	 * "attached" to the drbd.  Context is receiver thread or cqueue
-	 * thread.  As we have no disk yet, we are not in the IO path,
-	 * not even the IO path of the peer. */
+	 * GFP_NOIO, as this is called while drbd IO is "suspended",
+	 * and during resize or attach on diskless Primary,
+	 * we must not block on IO to ourselves.
+	 * Context is receiver thread or dmsetup. */
 	bytes = sizeof(struct page *)*want;
-	new_pages = kzalloc(bytes, GFP_KERNEL);
+	new_pages = kzalloc(bytes, GFP_NOIO);
 	if (!new_pages) {
-		new_pages = vzalloc(bytes);
+		new_pages = __vmalloc(bytes,
+				GFP_NOIO | __GFP_HIGHMEM | __GFP_ZERO,
+				PAGE_KERNEL);
 		if (!new_pages)
 			return NULL;
 		vmalloced = 1;
@@ -390,7 +407,7 @@ static struct page **bm_realloc_pages(struct drbd_bitmap *b, unsigned long want)
 		for (i = 0; i < have; i++)
 			new_pages[i] = old_pages[i];
 		for (; i < want; i++) {
-			page = alloc_page(GFP_HIGHUSER);
+			page = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
 			if (!page) {
 				bm_free_pages(new_pages + have, i - have);
 				bm_vk_free(new_pages, vmalloced);
@@ -439,7 +456,8 @@ int drbd_bm_init(struct drbd_conf *mdev)
 
 sector_t drbd_bm_capacity(struct drbd_conf *mdev)
 {
-	ERR_IF(!mdev->bitmap) return 0;
+	if (!expect(mdev->bitmap))
+		return 0;
 	return mdev->bitmap->bm_dev_capacity;
 }
 
@@ -447,7 +465,8 @@ sector_t drbd_bm_capacity(struct drbd_conf *mdev)
  */
 void drbd_bm_cleanup(struct drbd_conf *mdev)
 {
-	ERR_IF (!mdev->bitmap) return;
+	if (!expect(mdev->bitmap))
+		return;
 	bm_free_pages(mdev->bitmap->bm_pages, mdev->bitmap->bm_number_of_pages);
 	bm_vk_free(mdev->bitmap->bm_pages, (BM_P_VMALLOCED & mdev->bitmap->bm_flags));
 	kfree(mdev->bitmap);
@@ -610,7 +629,8 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits)
 	int err = 0, growing;
 	int opages_vmalloced;
 
-	ERR_IF(!b) return -ENOMEM;
+	if (!expect(b))
+		return -ENOMEM;
 
 	drbd_bm_lock(mdev, "resize", BM_LOCKED_MASK);
 
@@ -732,8 +752,10 @@ unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev)
 	unsigned long s;
 	unsigned long flags;
 
-	ERR_IF(!b) return 0;
-	ERR_IF(!b->bm_pages) return 0;
+	if (!expect(b))
+		return 0;
+	if (!expect(b->bm_pages))
+		return 0;
 
 	spin_lock_irqsave(&b->bm_lock, flags);
 	s = b->bm_set;
@@ -756,8 +778,10 @@ unsigned long drbd_bm_total_weight(struct drbd_conf *mdev)
 size_t drbd_bm_words(struct drbd_conf *mdev)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
-	ERR_IF(!b) return 0;
-	ERR_IF(!b->bm_pages) return 0;
+	if (!expect(b))
+		return 0;
+	if (!expect(b->bm_pages))
+		return 0;
 
 	return b->bm_words;
 }
@@ -765,7 +789,8 @@ size_t drbd_bm_words(struct drbd_conf *mdev)
 unsigned long drbd_bm_bits(struct drbd_conf *mdev)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
-	ERR_IF(!b) return 0;
+	if (!expect(b))
+		return 0;
 
 	return b->bm_bits;
 }
@@ -786,8 +811,10 @@ void drbd_bm_merge_lel(struct drbd_conf *mdev, size_t offset, size_t number,
 
 	end = offset + number;
 
-	ERR_IF(!b) return;
-	ERR_IF(!b->bm_pages) return;
+	if (!expect(b))
+		return;
+	if (!expect(b->bm_pages))
+		return;
 	if (number == 0)
 		return;
 	WARN_ON(offset >= b->bm_words);
@@ -831,8 +858,10 @@ void drbd_bm_get_lel(struct drbd_conf *mdev, size_t offset, size_t number,
 
 	end = offset + number;
 
-	ERR_IF(!b) return;
-	ERR_IF(!b->bm_pages) return;
+	if (!expect(b))
+		return;
+	if (!expect(b->bm_pages))
+		return;
 
 	spin_lock_irq(&b->bm_lock);
 	if ((offset >= b->bm_words) ||
@@ -860,8 +889,10 @@ void drbd_bm_get_lel(struct drbd_conf *mdev, size_t offset, size_t number,
 void drbd_bm_set_all(struct drbd_conf *mdev)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
-	ERR_IF(!b) return;
-	ERR_IF(!b->bm_pages) return;
+	if (!expect(b))
+		return;
+	if (!expect(b->bm_pages))
+		return;
 
 	spin_lock_irq(&b->bm_lock);
 	bm_memset(b, 0, 0xff, b->bm_words);
@@ -874,8 +905,10 @@ void drbd_bm_set_all(struct drbd_conf *mdev)
 void drbd_bm_clear_all(struct drbd_conf *mdev)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
-	ERR_IF(!b) return;
-	ERR_IF(!b->bm_pages) return;
+	if (!expect(b))
+		return;
+	if (!expect(b->bm_pages))
+		return;
 
 	spin_lock_irq(&b->bm_lock);
 	bm_memset(b, 0, 0, b->bm_words);
@@ -889,7 +922,8 @@ struct bm_aio_ctx {
 	unsigned int done;
 	unsigned flags;
 #define BM_AIO_COPY_PAGES	1
-#define BM_WRITE_ALL_PAGES	2
+#define BM_AIO_WRITE_HINTED	2
+#define BM_WRITE_ALL_PAGES	4
 	int error;
 	struct kref kref;
 };
@@ -977,17 +1011,11 @@ static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must
 	bm_set_page_unchanged(b->bm_pages[page_nr]);
 
 	if (ctx->flags & BM_AIO_COPY_PAGES) {
-		void *src, *dest;
 		page = mempool_alloc(drbd_md_io_page_pool, __GFP_HIGHMEM|__GFP_WAIT);
-		dest = kmap_atomic(page);
-		src = kmap_atomic(b->bm_pages[page_nr]);
-		memcpy(dest, src, PAGE_SIZE);
-		kunmap_atomic(src);
-		kunmap_atomic(dest);
+		copy_highpage(page, b->bm_pages[page_nr]);
 		bm_store_page_idx(page, page_nr);
 	} else
 		page = b->bm_pages[page_nr];
-
 	bio->bi_bdev = mdev->ldev->md_bdev;
 	bio->bi_sector = on_disk_sector;
 	/* bio_add_page of a single page to an empty bio will always succeed,
@@ -1060,6 +1088,11 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w
 		if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx)
 			break;
 		if (rw & WRITE) {
+			if ((flags & BM_AIO_WRITE_HINTED) &&
+			    !test_and_clear_bit(BM_PAGE_HINT_WRITEOUT,
+				    &page_private(b->bm_pages[i])))
+				continue;
+
 			if (!(flags & BM_WRITE_ALL_PAGES) &&
 			    bm_test_page_unchanged(b->bm_pages[i])) {
 				dynamic_dev_dbg(DEV, "skipped bm write for idx %u\n", i);
@@ -1088,13 +1121,15 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w
 	 * "in_flight reached zero, all done" event.
 	 */
 	if (!atomic_dec_and_test(&ctx->in_flight))
-		wait_until_done_or_disk_failure(mdev, mdev->ldev, &ctx->done);
+		wait_until_done_or_force_detached(mdev, mdev->ldev, &ctx->done);
 	else
 		kref_put(&ctx->kref, &bm_aio_ctx_destroy);
 
-	dev_info(DEV, "bitmap %s of %u pages took %lu jiffies\n",
-			rw == WRITE ? "WRITE" : "READ",
-			count, jiffies - now);
+	/* summary for global bitmap IO */
+	if (flags == 0)
+		dev_info(DEV, "bitmap %s of %u pages took %lu jiffies\n",
+			 rw == WRITE ? "WRITE" : "READ",
+			 count, jiffies - now);
 
 	if (ctx->error) {
 		dev_alert(DEV, "we had at least one MD IO ERROR during bitmap IO\n");
@@ -1103,7 +1138,7 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w
 	}
 
 	if (atomic_read(&ctx->in_flight))
-		err = -EIO; /* Disk failed during IO... */
+		err = -EIO; /* Disk timeout/force-detach during IO... */
 
 	now = jiffies;
 	if (rw == WRITE) {
@@ -1115,8 +1150,9 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w
 	}
 	now = b->bm_set;
 
-	dev_info(DEV, "%s (%lu bits) marked out-of-sync by on disk bit-map.\n",
-	     ppsize(ppb, now << (BM_BLOCK_SHIFT-10)), now);
+	if (flags == 0)
+		dev_info(DEV, "%s (%lu bits) marked out-of-sync by on disk bit-map.\n",
+		     ppsize(ppb, now << (BM_BLOCK_SHIFT-10)), now);
 
 	kref_put(&ctx->kref, &bm_aio_ctx_destroy);
 	return err;
@@ -1179,9 +1215,17 @@ int drbd_bm_write_copy_pages(struct drbd_conf *mdev) __must_hold(local)
 	return bm_rw(mdev, WRITE, BM_AIO_COPY_PAGES, 0);
 }
 
+/**
+ * drbd_bm_write_hinted() - Write bitmap pages with "hint" marks, if they have changed.
+ * @mdev:	DRBD device.
+ */
+int drbd_bm_write_hinted(struct drbd_conf *mdev) __must_hold(local)
+{
+	return bm_rw(mdev, WRITE, BM_AIO_WRITE_HINTED | BM_AIO_COPY_PAGES, 0);
+}
 
 /**
- * drbd_bm_write_page: Writes a PAGE_SIZE aligned piece of bitmap
+ * drbd_bm_write_page() - Writes a PAGE_SIZE aligned piece of bitmap
  * @mdev:	DRBD device.
  * @idx:	bitmap page index
  *
@@ -1222,11 +1266,11 @@ int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(loc
 	}
 
 	bm_page_io_async(ctx, idx, WRITE_SYNC);
-	wait_until_done_or_disk_failure(mdev, mdev->ldev, &ctx->done);
+	wait_until_done_or_force_detached(mdev, mdev->ldev, &ctx->done);
 
 	if (ctx->error)
 		drbd_chk_io_error(mdev, 1, DRBD_META_IO_ERROR);
-		/* that should force detach, so the in memory bitmap will be
+		/* that causes us to detach, so the in memory bitmap will be
 		 * gone in a moment as well. */
 
 	mdev->bm_writ_cnt++;
@@ -1289,8 +1333,10 @@ static unsigned long bm_find_next(struct drbd_conf *mdev,
 	struct drbd_bitmap *b = mdev->bitmap;
 	unsigned long i = DRBD_END_OF_BITMAP;
 
-	ERR_IF(!b) return i;
-	ERR_IF(!b->bm_pages) return i;
+	if (!expect(b))
+		return i;
+	if (!expect(b->bm_pages))
+		return i;
 
 	spin_lock_irq(&b->bm_lock);
 	if (BM_DONT_TEST & b->bm_flags)
@@ -1391,8 +1437,10 @@ static int bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s,
 	struct drbd_bitmap *b = mdev->bitmap;
 	int c = 0;
 
-	ERR_IF(!b) return 1;
-	ERR_IF(!b->bm_pages) return 0;
+	if (!expect(b))
+		return 1;
+	if (!expect(b->bm_pages))
+		return 0;
 
 	spin_lock_irqsave(&b->bm_lock, flags);
 	if ((val ? BM_DONT_SET : BM_DONT_CLEAR) & b->bm_flags)
@@ -1423,13 +1471,21 @@ static inline void bm_set_full_words_within_one_page(struct drbd_bitmap *b,
 {
 	int i;
 	int bits;
+	int changed = 0;
 	unsigned long *paddr = kmap_atomic(b->bm_pages[page_nr]);
 	for (i = first_word; i < last_word; i++) {
 		bits = hweight_long(paddr[i]);
 		paddr[i] = ~0UL;
-		b->bm_set += BITS_PER_LONG - bits;
+		changed += BITS_PER_LONG - bits;
 	}
 	kunmap_atomic(paddr);
+	if (changed) {
+		/* We only need lazy writeout, the information is still in the
+		 * remote bitmap as well, and is reconstructed during the next
+		 * bitmap exchange, if lost locally due to a crash. */
+		bm_set_page_lazy_writeout(b->bm_pages[page_nr]);
+		b->bm_set += changed;
+	}
 }
 
 /* Same thing as drbd_bm_set_bits,
@@ -1524,8 +1580,10 @@ int drbd_bm_test_bit(struct drbd_conf *mdev, const unsigned long bitnr)
 	unsigned long *p_addr;
 	int i;
 
-	ERR_IF(!b) return 0;
-	ERR_IF(!b->bm_pages) return 0;
+	if (!expect(b))
+		return 0;
+	if (!expect(b->bm_pages))
+		return 0;
 
 	spin_lock_irqsave(&b->bm_lock, flags);
 	if (BM_DONT_TEST & b->bm_flags)
@@ -1559,8 +1617,10 @@ int drbd_bm_count_bits(struct drbd_conf *mdev, const unsigned long s, const unsi
 	 * robust in case we screwed up elsewhere, in that case pretend there
 	 * was one dirty bit in the requested area, so we won't try to do a
 	 * local read there (no bitmap probably implies no disk) */
-	ERR_IF(!b) return 1;
-	ERR_IF(!b->bm_pages) return 1;
+	if (!expect(b))
+		return 1;
+	if (!expect(b->bm_pages))
+		return 1;
 
 	spin_lock_irqsave(&b->bm_lock, flags);
 	if (BM_DONT_TEST & b->bm_flags)
@@ -1573,11 +1633,10 @@ int drbd_bm_count_bits(struct drbd_conf *mdev, const unsigned long s, const unsi
 				bm_unmap(p_addr);
 			p_addr = bm_map_pidx(b, idx);
 		}
-		ERR_IF (bitnr >= b->bm_bits) {
-			dev_err(DEV, "bitnr=%lu bm_bits=%lu\n", bitnr, b->bm_bits);
-		} else {
+		if (expect(bitnr < b->bm_bits))
 			c += (0 != test_bit_le(bitnr - (page_nr << (PAGE_SHIFT+3)), p_addr));
-		}
+		else
+			dev_err(DEV, "bitnr=%lu bm_bits=%lu\n", bitnr, b->bm_bits);
 	}
 	if (p_addr)
 		bm_unmap(p_addr);
@@ -1607,8 +1666,10 @@ int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr)
 	unsigned long flags;
 	unsigned long *p_addr, *bm;
 
-	ERR_IF(!b) return 0;
-	ERR_IF(!b->bm_pages) return 0;
+	if (!expect(b))
+		return 0;
+	if (!expect(b->bm_pages))
+		return 0;
 
 	spin_lock_irqsave(&b->bm_lock, flags);
 	if (BM_DONT_TEST & b->bm_flags)
@@ -1630,47 +1691,3 @@ int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr)
 	spin_unlock_irqrestore(&b->bm_lock, flags);
 	return count;
 }
-
-/* Set all bits covered by the AL-extent al_enr.
- * Returns number of bits changed. */
-unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, unsigned long al_enr)
-{
-	struct drbd_bitmap *b = mdev->bitmap;
-	unsigned long *p_addr, *bm;
-	unsigned long weight;
-	unsigned long s, e;
-	int count, i, do_now;
-	ERR_IF(!b) return 0;
-	ERR_IF(!b->bm_pages) return 0;
-
-	spin_lock_irq(&b->bm_lock);
-	if (BM_DONT_SET & b->bm_flags)
-		bm_print_lock_info(mdev);
-	weight = b->bm_set;
-
-	s = al_enr * BM_WORDS_PER_AL_EXT;
-	e = min_t(size_t, s + BM_WORDS_PER_AL_EXT, b->bm_words);
-	/* assert that s and e are on the same page */
-	D_ASSERT((e-1) >> (PAGE_SHIFT - LN2_BPL + 3)
-	      ==  s    >> (PAGE_SHIFT - LN2_BPL + 3));
-	count = 0;
-	if (s < b->bm_words) {
-		i = do_now = e-s;
-		p_addr = bm_map_pidx(b, bm_word_to_page_idx(b, s));
-		bm = p_addr + MLPP(s);
-		while (i--) {
-			count += hweight_long(*bm);
-			*bm = -1UL;
-			bm++;
-		}
-		bm_unmap(p_addr);
-		b->bm_set += do_now*BITS_PER_LONG - count;
-		if (e == b->bm_words)
-			b->bm_set -= bm_clear_surplus(b);
-	} else {
-		dev_err(DEV, "start offset (%lu) too large in drbd_bm_ALe_set_all\n", s);
-	}
-	weight = b->bm_set - weight;
-	spin_unlock_irq(&b->bm_lock);
-	return weight;
-}
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index b953cc7..ef72a72 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -39,9 +39,13 @@
 #include <linux/major.h>
 #include <linux/blkdev.h>
 #include <linux/genhd.h>
+#include <linux/idr.h>
 #include <net/tcp.h>
 #include <linux/lru_cache.h>
 #include <linux/prefetch.h>
+#include <linux/drbd_genl_api.h>
+#include <linux/drbd.h>
+#include "drbd_state.h"
 
 #ifdef __CHECKER__
 # define __protected_by(x)       __attribute__((require_context(x,1,999,"rdwr")))
@@ -61,7 +65,6 @@
 extern unsigned int minor_count;
 extern bool disable_sendpage;
 extern bool allow_oos;
-extern unsigned int cn_idx;
 
 #ifdef CONFIG_DRBD_FAULT_INJECTION
 extern int enable_faults;
@@ -86,34 +89,44 @@ extern char usermode_helper[];
  */
 #define DRBD_SIGKILL SIGHUP
 
-/* All EEs on the free list should have ID_VACANT (== 0)
- * freshly allocated EEs get !ID_VACANT (== 1)
- * so if it says "cannot dereference null pointer at address 0x00000001",
- * it is most likely one of these :( */
-
 #define ID_IN_SYNC      (4711ULL)
 #define ID_OUT_OF_SYNC  (4712ULL)
-
 #define ID_SYNCER (-1ULL)
-#define ID_VACANT 0
-#define is_syncer_block_id(id) ((id) == ID_SYNCER)
+
 #define UUID_NEW_BM_OFFSET ((u64)0x0001000000000000ULL)
 
 struct drbd_conf;
+struct drbd_tconn;
 
 
 /* to shorten dev_warn(DEV, "msg"); and relatives statements */
 #define DEV (disk_to_dev(mdev->vdisk))
 
+#define conn_printk(LEVEL, TCONN, FMT, ARGS...) \
+	printk(LEVEL "d-con %s: " FMT, TCONN->name , ## ARGS)
+#define conn_alert(TCONN, FMT, ARGS...)  conn_printk(KERN_ALERT, TCONN, FMT, ## ARGS)
+#define conn_crit(TCONN, FMT, ARGS...)   conn_printk(KERN_CRIT, TCONN, FMT, ## ARGS)
+#define conn_err(TCONN, FMT, ARGS...)    conn_printk(KERN_ERR, TCONN, FMT, ## ARGS)
+#define conn_warn(TCONN, FMT, ARGS...)   conn_printk(KERN_WARNING, TCONN, FMT, ## ARGS)
+#define conn_notice(TCONN, FMT, ARGS...) conn_printk(KERN_NOTICE, TCONN, FMT, ## ARGS)
+#define conn_info(TCONN, FMT, ARGS...)   conn_printk(KERN_INFO, TCONN, FMT, ## ARGS)
+#define conn_dbg(TCONN, FMT, ARGS...)    conn_printk(KERN_DEBUG, TCONN, FMT, ## ARGS)
+
 #define D_ASSERT(exp)	if (!(exp)) \
 	 dev_err(DEV, "ASSERT( " #exp " ) in %s:%d\n", __FILE__, __LINE__)
 
-#define ERR_IF(exp) if (({						\
-	int _b = (exp) != 0;						\
-	if (_b) dev_err(DEV, "ASSERT FAILED: %s: (%s) in %s:%d\n",	\
-			__func__, #exp, __FILE__, __LINE__);		\
-	_b;								\
-	}))
+/**
+ * expect  -  Make an assertion
+ *
+ * Unlike the assert macro, this macro returns a boolean result.
+ */
+#define expect(exp) ({								\
+		bool _bool = (exp);						\
+		if (!_bool)							\
+			dev_err(DEV, "ASSERTION %s FAILED in %s\n",		\
+			        #exp, __func__);				\
+		_bool;								\
+		})
 
 /* Defines to control fault insertion */
 enum {
@@ -150,15 +163,12 @@ drbd_insert_fault(struct drbd_conf *mdev, unsigned int type) {
 /* usual integer division */
 #define div_floor(A, B) ((A)/(B))
 
-/* drbd_meta-data.c (still in drbd_main.c) */
-/* 4th incarnation of the disk layout. */
-#define DRBD_MD_MAGIC (DRBD_MAGIC+4)
-
-extern struct drbd_conf **minor_table;
 extern struct ratelimit_state drbd_ratelimit_state;
+extern struct idr minors; /* RCU, updates: genl_lock() */
+extern struct list_head drbd_tconns; /* RCU, updates: genl_lock() */
 
 /* on the wire */
-enum drbd_packets {
+enum drbd_packet {
 	/* receiver (data socket) */
 	P_DATA		      = 0x00,
 	P_DATA_REPLY	      = 0x01, /* Response to P_DATA_REQUEST */
@@ -186,7 +196,7 @@ enum drbd_packets {
 	P_RECV_ACK	      = 0x15, /* Used in protocol B */
 	P_WRITE_ACK	      = 0x16, /* Used in protocol C */
 	P_RS_WRITE_ACK	      = 0x17, /* Is a P_WRITE_ACK, additionally call set_in_sync(). */
-	P_DISCARD_ACK	      = 0x18, /* Used in proto C, two-primaries conflict detection */
+	P_SUPERSEDED	      = 0x18, /* Used in proto C, two-primaries conflict detection */
 	P_NEG_ACK	      = 0x19, /* Sent if local disk is unusable */
 	P_NEG_DREPLY	      = 0x1a, /* Local disk is broken... */
 	P_NEG_RS_DREPLY	      = 0x1b, /* Local disk is broken... */
@@ -207,77 +217,23 @@ enum drbd_packets {
 	P_DELAY_PROBE         = 0x27, /* is used on BOTH sockets */
 	P_OUT_OF_SYNC         = 0x28, /* Mark as out of sync (Outrunning), data socket */
 	P_RS_CANCEL           = 0x29, /* meta: Used to cancel RS_DATA_REQUEST packet by SyncSource */
+	P_CONN_ST_CHG_REQ     = 0x2a, /* data sock: Connection wide state request */
+	P_CONN_ST_CHG_REPLY   = 0x2b, /* meta sock: Connection side state req reply */
+	P_RETRY_WRITE	      = 0x2c, /* Protocol C: retry conflicting write request */
+	P_PROTOCOL_UPDATE     = 0x2d, /* data sock: is used in established connections */
 
-	P_MAX_CMD	      = 0x2A,
 	P_MAY_IGNORE	      = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */
 	P_MAX_OPT_CMD	      = 0x101,
 
 	/* special command ids for handshake */
 
-	P_HAND_SHAKE_M	      = 0xfff1, /* First Packet on the MetaSock */
-	P_HAND_SHAKE_S	      = 0xfff2, /* First Packet on the Socket */
+	P_INITIAL_META	      = 0xfff1, /* First Packet on the MetaSock */
+	P_INITIAL_DATA	      = 0xfff2, /* First Packet on the Socket */
 
-	P_HAND_SHAKE	      = 0xfffe	/* FIXED for the next century! */
+	P_CONNECTION_FEATURES = 0xfffe	/* FIXED for the next century! */
 };
 
-static inline const char *cmdname(enum drbd_packets cmd)
-{
-	/* THINK may need to become several global tables
-	 * when we want to support more than
-	 * one PRO_VERSION */
-	static const char *cmdnames[] = {
-		[P_DATA]	        = "Data",
-		[P_DATA_REPLY]	        = "DataReply",
-		[P_RS_DATA_REPLY]	= "RSDataReply",
-		[P_BARRIER]	        = "Barrier",
-		[P_BITMAP]	        = "ReportBitMap",
-		[P_BECOME_SYNC_TARGET]  = "BecomeSyncTarget",
-		[P_BECOME_SYNC_SOURCE]  = "BecomeSyncSource",
-		[P_UNPLUG_REMOTE]	= "UnplugRemote",
-		[P_DATA_REQUEST]	= "DataRequest",
-		[P_RS_DATA_REQUEST]     = "RSDataRequest",
-		[P_SYNC_PARAM]	        = "SyncParam",
-		[P_SYNC_PARAM89]	= "SyncParam89",
-		[P_PROTOCOL]            = "ReportProtocol",
-		[P_UUIDS]	        = "ReportUUIDs",
-		[P_SIZES]	        = "ReportSizes",
-		[P_STATE]	        = "ReportState",
-		[P_SYNC_UUID]           = "ReportSyncUUID",
-		[P_AUTH_CHALLENGE]      = "AuthChallenge",
-		[P_AUTH_RESPONSE]	= "AuthResponse",
-		[P_PING]		= "Ping",
-		[P_PING_ACK]	        = "PingAck",
-		[P_RECV_ACK]	        = "RecvAck",
-		[P_WRITE_ACK]	        = "WriteAck",
-		[P_RS_WRITE_ACK]	= "RSWriteAck",
-		[P_DISCARD_ACK]	        = "DiscardAck",
-		[P_NEG_ACK]	        = "NegAck",
-		[P_NEG_DREPLY]	        = "NegDReply",
-		[P_NEG_RS_DREPLY]	= "NegRSDReply",
-		[P_BARRIER_ACK]	        = "BarrierAck",
-		[P_STATE_CHG_REQ]       = "StateChgRequest",
-		[P_STATE_CHG_REPLY]     = "StateChgReply",
-		[P_OV_REQUEST]          = "OVRequest",
-		[P_OV_REPLY]            = "OVReply",
-		[P_OV_RESULT]           = "OVResult",
-		[P_CSUM_RS_REQUEST]     = "CsumRSRequest",
-		[P_RS_IS_IN_SYNC]	= "CsumRSIsInSync",
-		[P_COMPRESSED_BITMAP]   = "CBitmap",
-		[P_DELAY_PROBE]         = "DelayProbe",
-		[P_OUT_OF_SYNC]		= "OutOfSync",
-		[P_MAX_CMD]	        = NULL,
-	};
-
-	if (cmd == P_HAND_SHAKE_M)
-		return "HandShakeM";
-	if (cmd == P_HAND_SHAKE_S)
-		return "HandShakeS";
-	if (cmd == P_HAND_SHAKE)
-		return "HandShake";
-	if (cmd >= P_MAX_CMD)
-		return "Unknown";
-	return cmdnames[cmd];
-}
+extern const char *cmdname(enum drbd_packet cmd);
 
 /* for sending/receiving the bitmap,
  * possibly in some encoding scheme */
@@ -337,37 +293,24 @@ struct p_header80 {
 	u32	  magic;
 	u16	  command;
 	u16	  length;	/* bytes of data after this header */
-	u8	  payload[0];
 } __packed;
 
 /* Header for big packets, Used for data packets exceeding 64kB */
 struct p_header95 {
 	u16	  magic;	/* use DRBD_MAGIC_BIG here */
 	u16	  command;
-	u32	  length;	/* Use only 24 bits of that. Ignore the highest 8 bit. */
-	u8	  payload[0];
+	u32	  length;
 } __packed;
 
-union p_header {
-	struct p_header80 h80;
-	struct p_header95 h95;
-};
-
-/*
- * short commands, packets without payload, plain p_header:
- *   P_PING
- *   P_PING_ACK
- *   P_BECOME_SYNC_TARGET
- *   P_BECOME_SYNC_SOURCE
- *   P_UNPLUG_REMOTE
- */
+struct p_header100 {
+	u32	  magic;
+	u16	  volume;
+	u16	  command;
+	u32	  length;
+	u32	  pad;
+} __packed;
 
-/*
- * commands with out-of-struct payload:
- *   P_BITMAP    (no additional fields)
- *   P_DATA, P_DATA_REPLY (see p_data)
- *   P_COMPRESSED_BITMAP (see receive_compressed_bitmap)
- */
+extern unsigned int drbd_header_size(struct drbd_tconn *tconn);
 
 /* these defines must not be changed without changing the protocol version */
 #define DP_HARDBARRIER	      1 /* depricated */
@@ -377,9 +320,10 @@ union p_header {
 #define DP_FUA               16 /* equals REQ_FUA     */
 #define DP_FLUSH             32 /* equals REQ_FLUSH   */
 #define DP_DISCARD           64 /* equals REQ_DISCARD */
+#define DP_SEND_RECEIVE_ACK 128 /* This is a proto B write request */
+#define DP_SEND_WRITE_ACK   256 /* This is a proto C write request */
 
 struct p_data {
-	union p_header head;
 	u64	    sector;    /* 64 bits sector number */
 	u64	    block_id;  /* to identify the request in protocol B&C */
 	u32	    seq_num;
@@ -390,21 +334,18 @@ struct p_data {
  * commands which share a struct:
  *  p_block_ack:
  *   P_RECV_ACK (proto B), P_WRITE_ACK (proto C),
- *   P_DISCARD_ACK (proto C, two-primaries conflict detection)
+ *   P_SUPERSEDED (proto C, two-primaries conflict detection)
  *  p_block_req:
  *   P_DATA_REQUEST, P_RS_DATA_REQUEST
  */
 struct p_block_ack {
-	struct p_header80 head;
 	u64	    sector;
 	u64	    block_id;
 	u32	    blksize;
 	u32	    seq_num;
 } __packed;
 
-
 struct p_block_req {
-	struct p_header80 head;
 	u64 sector;
 	u64 block_id;
 	u32 blksize;
@@ -413,59 +354,52 @@ struct p_block_req {
 
 /*
  * commands with their own struct for additional fields:
- *   P_HAND_SHAKE
+ *   P_CONNECTION_FEATURES
  *   P_BARRIER
  *   P_BARRIER_ACK
  *   P_SYNC_PARAM
  *   ReportParams
  */
 
-struct p_handshake {
-	struct p_header80 head;	/* 8 bytes */
+struct p_connection_features {
 	u32 protocol_min;
 	u32 feature_flags;
 	u32 protocol_max;
 
 	/* should be more than enough for future enhancements
-	 * for now, feature_flags and the reserverd array shall be zero.
+	 * for now, feature_flags and the reserved array shall be zero.
 	 */
 
 	u32 _pad;
-	u64 reserverd[7];
+	u64 reserved[7];
 } __packed;
-/* 80 bytes, FIXED for the next century */
 
 struct p_barrier {
-	struct p_header80 head;
 	u32 barrier;	/* barrier number _handle_ only */
 	u32 pad;	/* to multiple of 8 Byte */
 } __packed;
 
 struct p_barrier_ack {
-	struct p_header80 head;
 	u32 barrier;
 	u32 set_size;
 } __packed;
 
 struct p_rs_param {
-	struct p_header80 head;
-	u32 rate;
+	u32 resync_rate;
 
 	      /* Since protocol version 88 and higher. */
 	char verify_alg[0];
 } __packed;
 
 struct p_rs_param_89 {
-	struct p_header80 head;
-	u32 rate;
+	u32 resync_rate;
         /* protocol version 89: */
 	char verify_alg[SHARED_SECRET_MAX];
 	char csums_alg[SHARED_SECRET_MAX];
 } __packed;
 
 struct p_rs_param_95 {
-	struct p_header80 head;
-	u32 rate;
+	u32 resync_rate;
 	char verify_alg[SHARED_SECRET_MAX];
 	char csums_alg[SHARED_SECRET_MAX];
 	u32 c_plan_ahead;
@@ -475,12 +409,11 @@ struct p_rs_param_95 {
 } __packed;
 
 enum drbd_conn_flags {
-	CF_WANT_LOSE = 1,
+	CF_DISCARD_MY_DATA = 1,
 	CF_DRY_RUN = 2,
 };
 
 struct p_protocol {
-	struct p_header80 head;
 	u32 protocol;
 	u32 after_sb_0p;
 	u32 after_sb_1p;
@@ -494,17 +427,14 @@ struct p_protocol {
 } __packed;
 
 struct p_uuids {
-	struct p_header80 head;
 	u64 uuid[UI_EXTENDED_SIZE];
 } __packed;
 
 struct p_rs_uuid {
-	struct p_header80 head;
 	u64	    uuid;
 } __packed;
 
 struct p_sizes {
-	struct p_header80 head;
 	u64	    d_size;  /* size of disk */
 	u64	    u_size;  /* user requested size */
 	u64	    c_size;  /* current exported size */
@@ -514,18 +444,15 @@ struct p_sizes {
 } __packed;
 
 struct p_state {
-	struct p_header80 head;
 	u32	    state;
 } __packed;
 
 struct p_req_state {
-	struct p_header80 head;
 	u32	    mask;
 	u32	    val;
 } __packed;
 
 struct p_req_state_reply {
-	struct p_header80 head;
 	u32	    retcode;
 } __packed;
 
@@ -539,15 +466,7 @@ struct p_drbd06_param {
 	u32	  bit_map_gen[5];
 } __packed;
 
-struct p_discard {
-	struct p_header80 head;
-	u64	    block_id;
-	u32	    seq_num;
-	u32	    pad;
-} __packed;
-
 struct p_block_desc {
-	struct p_header80 head;
 	u64 sector;
 	u32 blksize;
 	u32 pad;	/* to multiple of 8 Byte */
@@ -563,7 +482,6 @@ enum drbd_bitmap_code {
 };
 
 struct p_compressed_bm {
-	struct p_header80 head;
 	/* (encoding & 0x0f): actual encoding, see enum drbd_bitmap_code
 	 * (encoding & 0x80): polarity (set/unset) of first runlength
 	 * ((encoding >> 4) & 0x07): pad_bits, number of trailing zero bits
@@ -575,90 +493,22 @@ struct p_compressed_bm {
 } __packed;
 
 struct p_delay_probe93 {
-	struct p_header80 head;
 	u32     seq_num; /* sequence number to match the two probe packets */
 	u32     offset;  /* usecs the probe got sent after the reference time point */
 } __packed;
 
-/* DCBP: Drbd Compressed Bitmap Packet ... */
-static inline enum drbd_bitmap_code
-DCBP_get_code(struct p_compressed_bm *p)
-{
-	return (enum drbd_bitmap_code)(p->encoding & 0x0f);
-}
-
-static inline void
-DCBP_set_code(struct p_compressed_bm *p, enum drbd_bitmap_code code)
-{
-	BUG_ON(code & ~0xf);
-	p->encoding = (p->encoding & ~0xf) | code;
-}
-
-static inline int
-DCBP_get_start(struct p_compressed_bm *p)
-{
-	return (p->encoding & 0x80) != 0;
-}
-
-static inline void
-DCBP_set_start(struct p_compressed_bm *p, int set)
-{
-	p->encoding = (p->encoding & ~0x80) | (set ? 0x80 : 0);
-}
-
-static inline int
-DCBP_get_pad_bits(struct p_compressed_bm *p)
-{
-	return (p->encoding >> 4) & 0x7;
-}
-
-static inline void
-DCBP_set_pad_bits(struct p_compressed_bm *p, int n)
-{
-	BUG_ON(n & ~0x7);
-	p->encoding = (p->encoding & (~0x7 << 4)) | (n << 4);
-}
-
-/* one bitmap packet, including the p_header,
- * should fit within one _architecture independend_ page.
- * so we need to use the fixed size 4KiB page size
- * most architectures have used for a long time.
+/*
+ * Bitmap packets need to fit within a single page on the sender and receiver,
+ * so we are limited to 4 KiB (and not to PAGE_SIZE, which can be bigger).
  */
-#define BM_PACKET_PAYLOAD_BYTES (4096 - sizeof(struct p_header80))
-#define BM_PACKET_WORDS (BM_PACKET_PAYLOAD_BYTES/sizeof(long))
-#define BM_PACKET_VLI_BYTES_MAX (4096 - sizeof(struct p_compressed_bm))
-#if (PAGE_SIZE < 4096)
-/* drbd_send_bitmap / receive_bitmap would break horribly */
-#error "PAGE_SIZE too small"
-#endif
-
-union p_polymorph {
-        union p_header           header;
-        struct p_handshake       handshake;
-        struct p_data            data;
-        struct p_block_ack       block_ack;
-        struct p_barrier         barrier;
-        struct p_barrier_ack     barrier_ack;
-        struct p_rs_param_89     rs_param_89;
-        struct p_rs_param_95     rs_param_95;
-        struct p_protocol        protocol;
-        struct p_sizes           sizes;
-        struct p_uuids           uuids;
-        struct p_state           state;
-        struct p_req_state       req_state;
-        struct p_req_state_reply req_state_reply;
-        struct p_block_req       block_req;
-	struct p_delay_probe93   delay_probe93;
-	struct p_rs_uuid         rs_uuid;
-	struct p_block_desc      block_desc;
-} __packed;
+#define DRBD_SOCKET_BUFFER_SIZE 4096
 
 /**********************************************************************/
 enum drbd_thread_state {
-	None,
-	Running,
-	Exiting,
-	Restarting
+	NONE,
+	RUNNING,
+	EXITING,
+	RESTARTING
 };
 
 struct drbd_thread {
@@ -667,8 +517,9 @@ struct drbd_thread {
 	struct completion stop;
 	enum drbd_thread_state t_state;
 	int (*function) (struct drbd_thread *);
-	struct drbd_conf *mdev;
+	struct drbd_tconn *tconn;
 	int reset_cpu_mask;
+	char name[9];
 };
 
 static inline enum drbd_thread_state get_t_state(struct drbd_thread *thi)
@@ -681,58 +532,54 @@ static inline enum drbd_thread_state get_t_state(struct drbd_thread *thi)
 	return thi->t_state;
 }
 
-struct drbd_work;
-typedef int (*drbd_work_cb)(struct drbd_conf *, struct drbd_work *, int cancel);
 struct drbd_work {
 	struct list_head list;
-	drbd_work_cb cb;
+	int (*cb)(struct drbd_work *, int cancel);
+	union {
+		struct drbd_conf *mdev;
+		struct drbd_tconn *tconn;
+	};
 };
 
-struct drbd_tl_epoch;
+#include "drbd_interval.h"
+
+extern int drbd_wait_misc(struct drbd_conf *, struct drbd_interval *);
+
 struct drbd_request {
 	struct drbd_work w;
-	struct drbd_conf *mdev;
 
 	/* if local IO is not allowed, will be NULL.
 	 * if local IO _is_ allowed, holds the locally submitted bio clone,
 	 * or, after local IO completion, the ERR_PTR(error).
-	 * see drbd_endio_pri(). */
+	 * see drbd_request_endio(). */
 	struct bio *private_bio;
 
-	struct hlist_node collision;
-	sector_t sector;
-	unsigned int size;
-	unsigned int epoch; /* barrier_nr */
+	struct drbd_interval i;
 
-	/* barrier_nr: used to check on "completion" whether this req was in
+	/* epoch: used to check on "completion" whether this req was in
 	 * the current epoch, and we therefore have to close it,
-	 * starting a new epoch...
+	 * causing a p_barrier packet to be send, starting a new epoch.
+	 *
+	 * This corresponds to "barrier" in struct p_barrier[_ack],
+	 * and to "barrier_nr" in struct drbd_epoch (and various
+	 * comments/function parameters/local variable names).
 	 */
+	unsigned int epoch;
 
 	struct list_head tl_requests; /* ring list in the transfer log */
 	struct bio *master_bio;       /* master bio pointer */
-	unsigned long rq_state; /* see comments above _req_mod() */
 	unsigned long start_time;
-};
-
-struct drbd_tl_epoch {
-	struct drbd_work w;
-	struct list_head requests; /* requests before */
-	struct drbd_tl_epoch *next; /* pointer to the next barrier */
-	unsigned int br_number;  /* the barriers identifier. */
-	int n_writes;	/* number of requests attached before this barrier */
-};
 
-struct drbd_request;
+	/* once it hits 0, we may complete the master_bio */
+	atomic_t completion_ref;
+	/* once it hits 0, we may destroy this drbd_request object */
+	struct kref kref;
 
-/* These Tl_epoch_entries may be in one of 6 lists:
-   active_ee .. data packet being written
-   sync_ee   .. syncer block being written
-   done_ee   .. block written, need to send P_WRITE_ACK
-   read_ee   .. [RS]P_DATA_REQUEST being read
-*/
+	unsigned rq_state; /* see comments above _req_mod() */
+};
 
 struct drbd_epoch {
+	struct drbd_tconn *tconn;
 	struct list_head list;
 	unsigned int barrier_nr;
 	atomic_t epoch_size; /* increased on every request added. */
@@ -762,17 +609,14 @@ struct digest_info {
 	void *digest;
 };
 
-struct drbd_epoch_entry {
+struct drbd_peer_request {
 	struct drbd_work w;
-	struct hlist_node collision;
 	struct drbd_epoch *epoch; /* for writes */
-	struct drbd_conf *mdev;
 	struct page *pages;
 	atomic_t pending_bios;
-	unsigned int size;
+	struct drbd_interval i;
 	/* see comments on ee flag bits below */
 	unsigned long flags;
-	sector_t sector;
 	union {
 		u64 block_id;
 		struct digest_info *digest;
@@ -793,31 +637,37 @@ enum {
 	 * we need to resubmit without the barrier flag. */
 	__EE_RESUBMITTED,
 
-	/* we may have several bios per epoch entry.
+	/* we may have several bios per peer request.
 	 * if any of those fail, we set this flag atomically
 	 * from the endio callback */
 	__EE_WAS_ERROR,
 
 	/* This ee has a pointer to a digest instead of a block id */
 	__EE_HAS_DIGEST,
+
+	/* Conflicting local requests need to be restarted after this request */
+	__EE_RESTART_REQUESTS,
+
+	/* The peer wants a write ACK for this (wire proto C) */
+	__EE_SEND_WRITE_ACK,
+
+	/* Is set when net_conf had two_primaries set while creating this peer_req */
+	__EE_IN_INTERVAL_TREE,
 };
 #define EE_CALL_AL_COMPLETE_IO (1<<__EE_CALL_AL_COMPLETE_IO)
 #define EE_MAY_SET_IN_SYNC     (1<<__EE_MAY_SET_IN_SYNC)
 #define	EE_RESUBMITTED         (1<<__EE_RESUBMITTED)
 #define EE_WAS_ERROR           (1<<__EE_WAS_ERROR)
 #define EE_HAS_DIGEST          (1<<__EE_HAS_DIGEST)
+#define EE_RESTART_REQUESTS	(1<<__EE_RESTART_REQUESTS)
+#define EE_SEND_WRITE_ACK	(1<<__EE_SEND_WRITE_ACK)
+#define EE_IN_INTERVAL_TREE	(1<<__EE_IN_INTERVAL_TREE)
 
-/* global flag bits */
+/* flag bits per mdev */
 enum {
-	CREATE_BARRIER,		/* next P_DATA is preceded by a P_BARRIER */
-	SIGNAL_ASENDER,		/* whether asender wants to be interrupted */
-	SEND_PING,		/* whether asender should send a ping asap */
-
 	UNPLUG_REMOTE,		/* sending a "UnplugRemote" could help */
 	MD_DIRTY,		/* current uuids and flags not yet on disk */
-	DISCARD_CONCURRENT,	/* Set on one node, cleared on the peer! */
 	USE_DEGR_WFC_T,		/* degr-wfc-timeout instead of wfc-timeout. */
-	CLUSTER_ST_CHANGE,	/* Cluster wide state change going on... */
 	CL_ST_CHG_SUCCESS,
 	CL_ST_CHG_FAIL,
 	CRASHED_PRIMARY,	/* This node was a crashed primary.
@@ -831,32 +681,18 @@ enum {
 				   once no more io in flight, start bitmap io */
 	BITMAP_IO_QUEUED,       /* Started bitmap IO */
 	GO_DISKLESS,		/* Disk is being detached, on io-error or admin request. */
-	WAS_IO_ERROR,		/* Local disk failed returned IO error */
+	WAS_IO_ERROR,		/* Local disk failed, returned IO error */
+	WAS_READ_ERROR,		/* Local disk READ failed (set additionally to the above) */
 	FORCE_DETACH,		/* Force-detach from local disk, aborting any pending local IO */
 	RESYNC_AFTER_NEG,       /* Resync after online grow after the attach&negotiate finished. */
-	NET_CONGESTED,		/* The data socket is congested */
-
-	CONFIG_PENDING,		/* serialization of (re)configuration requests.
-				 * if set, also prevents the device from dying */
-	DEVICE_DYING,		/* device became unconfigured,
-				 * but worker thread is still handling the cleanup.
-				 * reconfiguring (nl_disk_conf, nl_net_conf) is dissalowed,
-				 * while this is set. */
 	RESIZE_PENDING,		/* Size change detected locally, waiting for the response from
 				 * the peer, if it changed there as well. */
-	CONN_DRY_RUN,		/* Expect disconnect after resync handshake. */
-	GOT_PING_ACK,		/* set when we receive a ping_ack packet, misc wait gets woken */
 	NEW_CUR_UUID,		/* Create new current UUID when thawing IO */
 	AL_SUSPENDED,		/* Activity logging is currently suspended. */
 	AHEAD_TO_SYNC_SOURCE,   /* Ahead -> SyncSource queued */
-	STATE_SENT,		/* Do not change state/UUIDs while this is set */
-
-	CALLBACK_PENDING,	/* Whether we have a call_usermodehelper(, UMH_WAIT_PROC)
-				 * pending, from drbd worker context.
-				 * If set, bdi_write_congested() returns true,
-				 * so shrink_page_list() would not recurse into,
-				 * and potentially deadlock on, this drbd worker.
-				 */
+	B_RS_H_DONE,		/* Before resync handler done (already executed) */
+	DISCARD_MY_DATA,	/* discard_my_data flag per volume */
+	READ_BALANCE_RR,
 };
 
 struct drbd_bitmap; /* opaque for drbd_conf */
@@ -894,24 +730,24 @@ enum bm_flag {
 
 struct drbd_work_queue {
 	struct list_head q;
-	struct semaphore s; /* producers up it, worker down()s it */
 	spinlock_t q_lock;  /* to protect the list. */
+	wait_queue_head_t q_wait;
 };
 
 struct drbd_socket {
-	struct drbd_work_queue work;
 	struct mutex mutex;
 	struct socket    *socket;
 	/* this way we get our
 	 * send/receive buffers off the stack */
-	union p_polymorph sbuf;
-	union p_polymorph rbuf;
+	void *sbuf;
+	void *rbuf;
 };
 
 struct drbd_md {
 	u64 md_offset;		/* sector offset to 'super' block */
 
 	u64 la_size_sect;	/* last agreed size, unit sectors */
+	spinlock_t uuid_lock;
 	u64 uuid[UI_SIZE];
 	u64 device_uuid;
 	u32 flags;
@@ -921,24 +757,16 @@ struct drbd_md {
 	s32 bm_offset;	/* signed relative sector offset to bitmap */
 
 	/* u32 al_nr_extents;	   important for restoring the AL
-	 * is stored into  sync_conf.al_extents, which in turn
+	 * is stored into  ldev->dc.al_extents, which in turn
 	 * gets applied to act_log->nr_elements
 	 */
 };
 
-/* for sync_conf and other types... */
-#define NL_PACKET(name, number, fields) struct name { fields };
-#define NL_INTEGER(pn,pr,member) int member;
-#define NL_INT64(pn,pr,member) __u64 member;
-#define NL_BIT(pn,pr,member)   unsigned member:1;
-#define NL_STRING(pn,pr,member,len) unsigned char member[len]; int member ## _len;
-#include <linux/drbd_nl.h>
-
 struct drbd_backing_dev {
 	struct block_device *backing_bdev;
 	struct block_device *md_bdev;
 	struct drbd_md md;
-	struct disk_conf dc; /* The user provided config... */
+	struct disk_conf *disk_conf; /* RCU, for updates: mdev->tconn->conf_update */
 	sector_t known_size; /* last known size of that backing device */
 };
 
@@ -962,18 +790,116 @@ enum write_ordering_e {
 };
 
 struct fifo_buffer {
-	int *values;
 	unsigned int head_index;
 	unsigned int size;
+	int total; /* sum of all values */
+	int values[0];
+};
+extern struct fifo_buffer *fifo_alloc(int fifo_size);
+
+/* flag bits per tconn */
+enum {
+	NET_CONGESTED,		/* The data socket is congested */
+	RESOLVE_CONFLICTS,	/* Set on one node, cleared on the peer! */
+	SEND_PING,		/* whether asender should send a ping asap */
+	SIGNAL_ASENDER,		/* whether asender wants to be interrupted */
+	GOT_PING_ACK,		/* set when we receive a ping_ack packet, ping_wait gets woken */
+	CONN_WD_ST_CHG_REQ,	/* A cluster wide state change on the connection is active */
+	CONN_WD_ST_CHG_OKAY,
+	CONN_WD_ST_CHG_FAIL,
+	CONN_DRY_RUN,		/* Expect disconnect after resync handshake. */
+	CREATE_BARRIER,		/* next P_DATA is preceded by a P_BARRIER */
+	STATE_SENT,		/* Do not change state/UUIDs while this is set */
+	CALLBACK_PENDING,	/* Whether we have a call_usermodehelper(, UMH_WAIT_PROC)
+				 * pending, from drbd worker context.
+				 * If set, bdi_write_congested() returns true,
+				 * so shrink_page_list() would not recurse into,
+				 * and potentially deadlock on, this drbd worker.
+				 */
+	DISCONNECT_SENT,
+};
+
+struct drbd_tconn {			/* is a resource from the config file */
+	char *name;			/* Resource name */
+	struct list_head all_tconn;	/* linked on global drbd_tconns */
+	struct kref kref;
+	struct idr volumes;		/* <tconn, vnr> to mdev mapping */
+	enum drbd_conns cstate;		/* Only C_STANDALONE to C_WF_REPORT_PARAMS */
+	unsigned susp:1;		/* IO suspended by user */
+	unsigned susp_nod:1;		/* IO suspended because no data */
+	unsigned susp_fen:1;		/* IO suspended because fence peer handler runs */
+	struct mutex cstate_mutex;	/* Protects graceful disconnects */
+
+	unsigned long flags;
+	struct net_conf *net_conf;	/* content protected by rcu */
+	struct mutex conf_update;	/* mutex for ready-copy-update of net_conf and disk_conf */
+	wait_queue_head_t ping_wait;	/* Woken upon reception of a ping, and a state change */
+	struct res_opts res_opts;
+
+	struct sockaddr_storage my_addr;
+	int my_addr_len;
+	struct sockaddr_storage peer_addr;
+	int peer_addr_len;
+
+	struct drbd_socket data;	/* data/barrier/cstate/parameter packets */
+	struct drbd_socket meta;	/* ping/ack (metadata) packets */
+	int agreed_pro_version;		/* actually used protocol version */
+	unsigned long last_received;	/* in jiffies, either socket */
+	unsigned int ko_count;
+
+	spinlock_t req_lock;
+
+	struct list_head transfer_log;	/* all requests not yet fully processed */
+
+	struct crypto_hash *cram_hmac_tfm;
+	struct crypto_hash *integrity_tfm;  /* checksums we compute, updates protected by tconn->data->mutex */
+	struct crypto_hash *peer_integrity_tfm;  /* checksums we verify, only accessed from receiver thread  */
+	struct crypto_hash *csums_tfm;
+	struct crypto_hash *verify_tfm;
+	void *int_dig_in;
+	void *int_dig_vv;
+
+	/* receiver side */
+	struct drbd_epoch *current_epoch;
+	spinlock_t epoch_lock;
+	unsigned int epochs;
+	enum write_ordering_e write_ordering;
+	atomic_t current_tle_nr;	/* transfer log epoch number */
+	unsigned current_tle_writes;	/* writes seen within this tl epoch */
+
+	unsigned long last_reconnect_jif;
+	struct drbd_thread receiver;
+	struct drbd_thread worker;
+	struct drbd_thread asender;
+	cpumask_var_t cpu_mask;
+
+	/* sender side */
+	struct drbd_work_queue sender_work;
+
+	struct {
+		/* whether this sender thread
+		 * has processed a single write yet. */
+		bool seen_any_write_yet;
+
+		/* Which barrier number to send with the next P_BARRIER */
+		int current_epoch_nr;
+
+		/* how many write requests have been sent
+		 * with req->epoch == current_epoch_nr.
+		 * If none, no P_BARRIER will be sent. */
+		unsigned current_epoch_writes;
+	} send;
 };
 
 struct drbd_conf {
+	struct drbd_tconn *tconn;
+	int vnr;			/* volume number within the connection */
+	struct kref kref;
+
 	/* things that are stored as / read from meta data on disk */
 	unsigned long flags;
 
 	/* configured by drbdsetup */
-	struct net_conf *net_conf; /* protected by get_net_conf() and put_net_conf() */
-	struct syncer_conf sync_conf;
 	struct drbd_backing_dev *ldev __protected_by(local);
 
 	sector_t p_size;     /* partner's disk size */
@@ -981,11 +907,7 @@ struct drbd_conf {
 	struct block_device *this_bdev;
 	struct gendisk	    *vdisk;
 
-	struct drbd_socket data; /* data/barrier/cstate/parameter packets */
-	struct drbd_socket meta; /* ping/ack (metadata) packets */
-	int agreed_pro_version;  /* actually used protocol version */
-	unsigned long last_received; /* in jiffies, either socket */
-	unsigned int ko_count;
+	unsigned long last_reattach_jif;
 	struct drbd_work  resync_work,
 			  unplug_work,
 			  go_diskless,
@@ -1005,10 +927,9 @@ struct drbd_conf {
 	/* Used after attach while negotiating new disk state. */
 	union drbd_state new_state_tmp;
 
-	union drbd_state state;
+	union drbd_dev_state state;
 	wait_queue_head_t misc_wait;
 	wait_queue_head_t state_wait;  /* upon each state change. */
-	wait_queue_head_t net_cnt_wait;
 	unsigned int send_cnt;
 	unsigned int recv_cnt;
 	unsigned int read_cnt;
@@ -1018,17 +939,12 @@ struct drbd_conf {
 	atomic_t ap_bio_cnt;	 /* Requests we need to complete */
 	atomic_t ap_pending_cnt; /* AP data packets on the wire, ack expected */
 	atomic_t rs_pending_cnt; /* RS request/data packets on the wire */
-	atomic_t unacked_cnt;	 /* Need to send replys for */
+	atomic_t unacked_cnt;	 /* Need to send replies for */
 	atomic_t local_cnt;	 /* Waiting for local completion */
-	atomic_t net_cnt;	 /* Users of net_conf */
-	spinlock_t req_lock;
-	struct drbd_tl_epoch *unused_spare_tle; /* for pre-allocation */
-	struct drbd_tl_epoch *newest_tle;
-	struct drbd_tl_epoch *oldest_tle;
-	struct list_head out_of_sequence_requests;
-	struct list_head barrier_acked_requests;
-	struct hlist_head *tl_hash;
-	unsigned int tl_hash_s;
+
+	/* Interval tree of pending local requests */
+	struct rb_root read_requests;
+	struct rb_root write_requests;
 
 	/* blocks to resync in this run [unit BM_BLOCK_SIZE] */
 	unsigned long rs_total;
@@ -1048,9 +964,11 @@ struct drbd_conf {
 	unsigned long rs_mark_time[DRBD_SYNC_MARKS];
 	/* current index into rs_mark_{left,time} */
 	int rs_last_mark;
+	unsigned long rs_last_bcast; /* [unit jiffies] */
 
 	/* where does the admin want us to start? (sector) */
 	sector_t ov_start_sector;
+	sector_t ov_stop_sector;
 	/* where are we now? (sector) */
 	sector_t ov_position;
 	/* Start sector of out of sync range (to merge printk reporting). */
@@ -1058,14 +976,7 @@ struct drbd_conf {
 	/* size of out-of-sync range in sectors. */
 	sector_t ov_last_oos_size;
 	unsigned long ov_left; /* in bits */
-	struct crypto_hash *csums_tfm;
-	struct crypto_hash *verify_tfm;
 
-	unsigned long last_reattach_jif;
-	unsigned long last_reconnect_jif;
-	struct drbd_thread receiver;
-	struct drbd_thread worker;
-	struct drbd_thread asender;
 	struct drbd_bitmap *bitmap;
 	unsigned long bm_resync_fo; /* bit offset for drbd_bm_find_next */
 
@@ -1078,29 +989,19 @@ struct drbd_conf {
 
 	int open_cnt;
 	u64 *p_uuid;
-	struct drbd_epoch *current_epoch;
-	spinlock_t epoch_lock;
-	unsigned int epochs;
-	enum write_ordering_e write_ordering;
+
 	struct list_head active_ee; /* IO in progress (P_DATA gets written to disk) */
 	struct list_head sync_ee;   /* IO in progress (P_RS_DATA_REPLY gets written to disk) */
-	struct list_head done_ee;   /* send ack */
-	struct list_head read_ee;   /* IO in progress (any read) */
+	struct list_head done_ee;   /* need to send P_WRITE_ACK */
+	struct list_head read_ee;   /* [RS]P_DATA_REQUEST being read */
 	struct list_head net_ee;    /* zero-copy network send in progress */
-	struct hlist_head *ee_hash; /* is proteced by req_lock! */
-	unsigned int ee_hash_s;
-
-	/* this one is protected by ee_lock, single thread */
-	struct drbd_epoch_entry *last_write_w_barrier;
 
 	int next_barrier_nr;
-	struct hlist_head *app_reads_hash; /* is proteced by req_lock */
 	struct list_head resync_reads;
 	atomic_t pp_in_use;		/* allocated from page pool */
 	atomic_t pp_in_use_by_net;	/* sendpage()d, still referenced by tcp */
 	wait_queue_head_t ee_wait;
 	struct page *md_io_page;	/* one page buffer for md_io */
-	struct page *md_io_tmpp;	/* for logical_block_size != 512 */
 	struct drbd_md_io md_io;
 	atomic_t md_io_in_use;		/* protects the md_io, md_io_page and md_io_tmpp */
 	spinlock_t al_lock;
@@ -1109,22 +1010,16 @@ struct drbd_conf {
 	unsigned int al_tr_number;
 	int al_tr_cycle;
 	int al_tr_pos;   /* position of the next transaction in the journal */
-	struct crypto_hash *cram_hmac_tfm;
-	struct crypto_hash *integrity_w_tfm; /* to be used by the worker thread */
-	struct crypto_hash *integrity_r_tfm; /* to be used by the receiver thread */
-	void *int_dig_out;
-	void *int_dig_in;
-	void *int_dig_vv;
 	wait_queue_head_t seq_wait;
 	atomic_t packet_seq;
 	unsigned int peer_seq;
 	spinlock_t peer_seq_lock;
 	unsigned int minor;
 	unsigned long comm_bm_set; /* communicated number of set bits. */
-	cpumask_var_t cpu_mask;
 	struct bm_io_work bm_io_work;
 	u64 ed_uuid; /* UUID of the exposed data */
-	struct mutex state_mutex;
+	struct mutex own_state_mutex;
+	struct mutex *state_mutex; /* either own_state_mutex or mdev->tconn->cstate_mutex */
 	char congestion_reason;  /* Why we where congested... */
 	atomic_t rs_sect_in; /* for incoming resync data rate, SyncTarget */
 	atomic_t rs_sect_ev; /* for submitted resync data rate, both */
@@ -1132,9 +1027,8 @@ struct drbd_conf {
 	int rs_last_events;  /* counter of read or write "events" (unit sectors)
 			      * on the lower level device when we last looked. */
 	int c_sync_rate; /* current resync rate after syncer throttle magic */
-	struct fifo_buffer rs_plan_s; /* correction values of resync planer */
+	struct fifo_buffer *rs_plan_s; /* correction values of resync planer (RCU, tconn->conn_update) */
 	int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and from proxy) */
-	int rs_planed;    /* resync sectors already planned */
 	atomic_t ap_in_flight; /* App sectors in flight (waiting for ack) */
 	unsigned int peer_max_bio_size;
 	unsigned int local_max_bio_size;
@@ -1142,11 +1036,7 @@ struct drbd_conf {
 
 static inline struct drbd_conf *minor_to_mdev(unsigned int minor)
 {
-	struct drbd_conf *mdev;
-
-	mdev = minor < minor_count ? minor_table[minor] : NULL;
-
-	return mdev;
+	return (struct drbd_conf *)idr_find(&minors, minor);
 }
 
 static inline unsigned int mdev_to_minor(struct drbd_conf *mdev)
@@ -1154,29 +1044,9 @@ static inline unsigned int mdev_to_minor(struct drbd_conf *mdev)
 	return mdev->minor;
 }
 
-/* returns 1 if it was successful,
- * returns 0 if there was no data socket.
- * so wherever you are going to use the data.socket, e.g. do
- * if (!drbd_get_data_sock(mdev))
- *	return 0;
- *	CODE();
- * drbd_put_data_sock(mdev);
- */
-static inline int drbd_get_data_sock(struct drbd_conf *mdev)
-{
-	mutex_lock(&mdev->data.mutex);
-	/* drbd_disconnect() could have called drbd_free_sock()
-	 * while we were waiting in down()... */
-	if (unlikely(mdev->data.socket == NULL)) {
-		mutex_unlock(&mdev->data.mutex);
-		return 0;
-	}
-	return 1;
-}
-
-static inline void drbd_put_data_sock(struct drbd_conf *mdev)
+static inline struct drbd_conf *vnr_to_mdev(struct drbd_tconn *tconn, int vnr)
 {
-	mutex_unlock(&mdev->data.mutex);
+	return (struct drbd_conf *)idr_find(&tconn->volumes, vnr);
 }
 
 /*
@@ -1185,106 +1055,77 @@ static inline void drbd_put_data_sock(struct drbd_conf *mdev)
 
 /* drbd_main.c */
 
-enum chg_state_flags {
-	CS_HARD	= 1,
-	CS_VERBOSE = 2,
-	CS_WAIT_COMPLETE = 4,
-	CS_SERIALIZE    = 8,
-	CS_ORDERED      = CS_WAIT_COMPLETE + CS_SERIALIZE,
-};
-
 enum dds_flags {
 	DDSF_FORCED    = 1,
 	DDSF_NO_RESYNC = 2, /* Do not run a resync for the new space */
 };
 
 extern void drbd_init_set_defaults(struct drbd_conf *mdev);
-extern enum drbd_state_rv drbd_change_state(struct drbd_conf *mdev,
-					    enum chg_state_flags f,
-					    union drbd_state mask,
-					    union drbd_state val);
-extern void drbd_force_state(struct drbd_conf *, union drbd_state,
-			union drbd_state);
-extern enum drbd_state_rv _drbd_request_state(struct drbd_conf *,
-					      union drbd_state,
-					      union drbd_state,
-					      enum chg_state_flags);
-extern enum drbd_state_rv __drbd_set_state(struct drbd_conf *, union drbd_state,
-					   enum chg_state_flags,
-					   struct completion *done);
-extern void print_st_err(struct drbd_conf *, union drbd_state,
-			union drbd_state, int);
 extern int  drbd_thread_start(struct drbd_thread *thi);
 extern void _drbd_thread_stop(struct drbd_thread *thi, int restart, int wait);
+extern char *drbd_task_to_thread_name(struct drbd_tconn *tconn, struct task_struct *task);
 #ifdef CONFIG_SMP
-extern void drbd_thread_current_set_cpu(struct drbd_conf *mdev);
-extern void drbd_calc_cpu_mask(struct drbd_conf *mdev);
+extern void drbd_thread_current_set_cpu(struct drbd_thread *thi);
+extern void drbd_calc_cpu_mask(struct drbd_tconn *tconn);
 #else
 #define drbd_thread_current_set_cpu(A) ({})
 #define drbd_calc_cpu_mask(A) ({})
 #endif
-extern void drbd_free_resources(struct drbd_conf *mdev);
-extern void tl_release(struct drbd_conf *mdev, unsigned int barrier_nr,
+extern void tl_release(struct drbd_tconn *, unsigned int barrier_nr,
 		       unsigned int set_size);
-extern void tl_clear(struct drbd_conf *mdev);
-extern void _tl_add_barrier(struct drbd_conf *, struct drbd_tl_epoch *);
-extern void drbd_free_sock(struct drbd_conf *mdev);
-extern int drbd_send(struct drbd_conf *mdev, struct socket *sock,
-			void *buf, size_t size, unsigned msg_flags);
-extern int drbd_send_protocol(struct drbd_conf *mdev);
+extern void tl_clear(struct drbd_tconn *);
+extern void drbd_free_sock(struct drbd_tconn *tconn);
+extern int drbd_send(struct drbd_tconn *tconn, struct socket *sock,
+		     void *buf, size_t size, unsigned msg_flags);
+extern int drbd_send_all(struct drbd_tconn *, struct socket *, void *, size_t,
+			 unsigned);
+
+extern int __drbd_send_protocol(struct drbd_tconn *tconn, enum drbd_packet cmd);
+extern int drbd_send_protocol(struct drbd_tconn *tconn);
 extern int drbd_send_uuids(struct drbd_conf *mdev);
 extern int drbd_send_uuids_skip_initial_sync(struct drbd_conf *mdev);
-extern int drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev);
+extern void drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev);
 extern int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags flags);
 extern int drbd_send_state(struct drbd_conf *mdev, union drbd_state s);
 extern int drbd_send_current_state(struct drbd_conf *mdev);
-extern int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock,
-			enum drbd_packets cmd, struct p_header80 *h,
-			size_t size, unsigned msg_flags);
-#define USE_DATA_SOCKET 1
-#define USE_META_SOCKET 0
-extern int drbd_send_cmd(struct drbd_conf *mdev, int use_data_socket,
-			enum drbd_packets cmd, struct p_header80 *h,
-			size_t size);
-extern int drbd_send_cmd2(struct drbd_conf *mdev, enum drbd_packets cmd,
-			char *data, size_t size);
-extern int drbd_send_sync_param(struct drbd_conf *mdev, struct syncer_conf *sc);
-extern int drbd_send_b_ack(struct drbd_conf *mdev, u32 barrier_nr,
-			u32 set_size);
-extern int drbd_send_ack(struct drbd_conf *mdev, enum drbd_packets cmd,
-			struct drbd_epoch_entry *e);
-extern int drbd_send_ack_rp(struct drbd_conf *mdev, enum drbd_packets cmd,
-			struct p_block_req *rp);
-extern int drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packets cmd,
-			struct p_data *dp, int data_size);
-extern int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packets cmd,
+extern int drbd_send_sync_param(struct drbd_conf *mdev);
+extern void drbd_send_b_ack(struct drbd_tconn *tconn, u32 barrier_nr,
+			    u32 set_size);
+extern int drbd_send_ack(struct drbd_conf *, enum drbd_packet,
+			 struct drbd_peer_request *);
+extern void drbd_send_ack_rp(struct drbd_conf *mdev, enum drbd_packet cmd,
+			     struct p_block_req *rp);
+extern void drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packet cmd,
+			     struct p_data *dp, int data_size);
+extern int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packet cmd,
 			    sector_t sector, int blksize, u64 block_id);
-extern int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req);
-extern int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd,
-			   struct drbd_epoch_entry *e);
+extern int drbd_send_out_of_sync(struct drbd_conf *, struct drbd_request *);
+extern int drbd_send_block(struct drbd_conf *, enum drbd_packet,
+			   struct drbd_peer_request *);
 extern int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req);
 extern int drbd_send_drequest(struct drbd_conf *mdev, int cmd,
 			      sector_t sector, int size, u64 block_id);
-extern int drbd_send_drequest_csum(struct drbd_conf *mdev,
-				   sector_t sector,int size,
-				   void *digest, int digest_size,
-				   enum drbd_packets cmd);
+extern int drbd_send_drequest_csum(struct drbd_conf *mdev, sector_t sector,
+				   int size, void *digest, int digest_size,
+				   enum drbd_packet cmd);
 extern int drbd_send_ov_request(struct drbd_conf *mdev,sector_t sector,int size);
 
 extern int drbd_send_bitmap(struct drbd_conf *mdev);
-extern int _drbd_send_bitmap(struct drbd_conf *mdev);
-extern int drbd_send_sr_reply(struct drbd_conf *mdev, enum drbd_state_rv retcode);
+extern void drbd_send_sr_reply(struct drbd_conf *mdev, enum drbd_state_rv retcode);
+extern void conn_send_sr_reply(struct drbd_tconn *tconn, enum drbd_state_rv retcode);
 extern void drbd_free_bc(struct drbd_backing_dev *ldev);
 extern void drbd_mdev_cleanup(struct drbd_conf *mdev);
 void drbd_print_uuids(struct drbd_conf *mdev, const char *text);
 
+extern void conn_md_sync(struct drbd_tconn *tconn);
 extern void drbd_md_sync(struct drbd_conf *mdev);
 extern int  drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev);
 extern void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local);
 extern void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local);
 extern void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local);
-extern void _drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local);
 extern void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local);
+extern void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local);
+extern void __drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local);
 extern void drbd_md_set_flag(struct drbd_conf *mdev, int flags) __must_hold(local);
 extern void drbd_md_clear_flag(struct drbd_conf *mdev, int flags)__must_hold(local);
 extern int drbd_md_test_flag(struct drbd_backing_dev *, int);
@@ -1302,33 +1143,52 @@ extern void drbd_queue_bitmap_io(struct drbd_conf *mdev,
 extern int drbd_bitmap_io(struct drbd_conf *mdev,
 		int (*io_fn)(struct drbd_conf *),
 		char *why, enum bm_flag flags);
+extern int drbd_bitmap_io_from_worker(struct drbd_conf *mdev,
+		int (*io_fn)(struct drbd_conf *),
+		char *why, enum bm_flag flags);
 extern int drbd_bmio_set_n_write(struct drbd_conf *mdev);
 extern int drbd_bmio_clear_n_write(struct drbd_conf *mdev);
 extern void drbd_go_diskless(struct drbd_conf *mdev);
 extern void drbd_ldev_destroy(struct drbd_conf *mdev);
 
-
 /* Meta data layout
    We reserve a 128MB Block (4k aligned)
    * either at the end of the backing device
    * or on a separate meta data device. */
 
-#define MD_RESERVED_SECT (128LU << 11)  /* 128 MB, unit sectors */
 /* The following numbers are sectors */
-#define MD_AL_OFFSET 8	    /* 8 Sectors after start of meta area */
-#define MD_AL_MAX_SIZE 64   /* = 32 kb LOG  ~ 3776 extents ~ 14 GB Storage */
-/* Allows up to about 3.8TB */
-#define MD_BM_OFFSET (MD_AL_OFFSET + MD_AL_MAX_SIZE)
-
-/* Since the smalles IO unit is usually 512 byte */
-#define MD_SECTOR_SHIFT	 9
-#define MD_SECTOR_SIZE	 (1<<MD_SECTOR_SHIFT)
-
-/* activity log */
-#define AL_EXTENTS_PT ((MD_SECTOR_SIZE-12)/8-1) /* 61 ; Extents per 512B sector */
-#define AL_EXTENT_SHIFT 22		 /* One extent represents 4M Storage */
+/* Allows up to about 3.8TB, so if you want more,
+ * you need to use the "flexible" meta data format. */
+#define MD_RESERVED_SECT (128LU << 11)  /* 128 MB, unit sectors */
+#define MD_AL_OFFSET	8    /* 8 Sectors after start of meta area */
+#define MD_AL_SECTORS	64   /* = 32 kB on disk activity log ring buffer */
+#define MD_BM_OFFSET (MD_AL_OFFSET + MD_AL_SECTORS)
+
+/* we do all meta data IO in 4k blocks */
+#define MD_BLOCK_SHIFT	12
+#define MD_BLOCK_SIZE	(1<<MD_BLOCK_SHIFT)
+
+/* One activity log extent represents 4M of storage */
+#define AL_EXTENT_SHIFT 22
 #define AL_EXTENT_SIZE (1<<AL_EXTENT_SHIFT)
 
+/* We could make these currently hardcoded constants configurable
+ * variables at create-md time (or even re-configurable at runtime?).
+ * Which will require some more changes to the DRBD "super block"
+ * and attach code.
+ *
+ * updates per transaction:
+ *   This many changes to the active set can be logged with one transaction.
+ *   This number is arbitrary.
+ * context per transaction:
+ *   This many context extent numbers are logged with each transaction.
+ *   This number is resulting from the transaction block size (4k), the layout
+ *   of the transaction header, and the number of updates per transaction.
+ *   See drbd_actlog.c:struct al_transaction_on_disk
+ * */
+#define AL_UPDATES_PER_TRANSACTION	 64	// arbitrary
+#define AL_CONTEXT_PER_TRANSACTION	919	// (4096 - 36 - 6*64)/4
+
 #if BITS_PER_LONG == 32
 #define LN2_BPL 5
 #define cpu_to_lel(A) cpu_to_le32(A)
@@ -1364,11 +1224,14 @@ struct bm_extent {
 
 #define SLEEP_TIME (HZ/10)
 
-#define BM_BLOCK_SHIFT  12			 /* 4k per bit */
+/* We do bitmap IO in units of 4k blocks.
+ * We also still have a hardcoded 4k per bit relation. */
+#define BM_BLOCK_SHIFT	12			 /* 4k per bit */
 #define BM_BLOCK_SIZE	 (1<<BM_BLOCK_SHIFT)
-/* (9+3) : 512 bytes @ 8 bits; representing 16M storage
- * per sector of on disk bitmap */
-#define BM_EXT_SHIFT	 (BM_BLOCK_SHIFT + MD_SECTOR_SHIFT + 3)  /* = 24 */
+/* mostly arbitrarily set the represented size of one bitmap extent,
+ * aka resync extent, to 16 MiB (which is also 512 Byte worth of bitmap
+ * at 4k per bit resolution) */
+#define BM_EXT_SHIFT	 24	/* 16 MiB per resync extent */
 #define BM_EXT_SIZE	 (1<<BM_EXT_SHIFT)
 
 #if (BM_EXT_SHIFT != 24) || (BM_BLOCK_SHIFT != 12)
@@ -1436,17 +1299,20 @@ struct bm_extent {
 #endif
 #endif
 
-/* Sector shift value for the "hash" functions of tl_hash and ee_hash tables.
- * With a value of 8 all IO in one 128K block make it to the same slot of the
- * hash table. */
-#define HT_SHIFT 8
-#define DRBD_MAX_BIO_SIZE (1U<<(9+HT_SHIFT))
+/* BIO_MAX_SIZE is 256 * PAGE_CACHE_SIZE,
+ * so for typical PAGE_CACHE_SIZE of 4k, that is (1<<20) Byte.
+ * Since we may live in a mixed-platform cluster,
+ * we limit us to a platform agnostic constant here for now.
+ * A followup commit may allow even bigger BIO sizes,
+ * once we thought that through. */
+#define DRBD_MAX_BIO_SIZE (1U << 20)
+#if DRBD_MAX_BIO_SIZE > BIO_MAX_SIZE
+#error Architecture not supported: DRBD_MAX_BIO_SIZE > BIO_MAX_SIZE
+#endif
 #define DRBD_MAX_BIO_SIZE_SAFE (1U << 12)       /* Works always = 4k */
 
-#define DRBD_MAX_SIZE_H80_PACKET (1U << 15) /* The old header only allows packets up to 32Kib data */
-
-/* Number of elements in the app_reads_hash */
-#define APP_R_HSIZE 15
+#define DRBD_MAX_SIZE_H80_PACKET (1U << 15) /* Header 80 only allows packets up to 32KiB data */
+#define DRBD_MAX_BIO_SIZE_P95    (1U << 17) /* Protocol 95 to 99 allows bios up to 128KiB */
 
 extern int  drbd_bm_init(struct drbd_conf *mdev);
 extern int  drbd_bm_resize(struct drbd_conf *mdev, sector_t sectors, int set_new_bits);
@@ -1468,11 +1334,11 @@ extern int  drbd_bm_test_bit(struct drbd_conf *mdev, unsigned long bitnr);
 extern int  drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr);
 extern int  drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local);
 extern int  drbd_bm_read(struct drbd_conf *mdev) __must_hold(local);
+extern void drbd_bm_mark_for_writeout(struct drbd_conf *mdev, int page_nr);
 extern int  drbd_bm_write(struct drbd_conf *mdev) __must_hold(local);
+extern int  drbd_bm_write_hinted(struct drbd_conf *mdev) __must_hold(local);
 extern int drbd_bm_write_all(struct drbd_conf *mdev) __must_hold(local);
 extern int  drbd_bm_write_copy_pages(struct drbd_conf *mdev) __must_hold(local);
-extern unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev,
-		unsigned long al_enr);
 extern size_t	     drbd_bm_words(struct drbd_conf *mdev);
 extern unsigned long drbd_bm_bits(struct drbd_conf *mdev);
 extern sector_t      drbd_bm_capacity(struct drbd_conf *mdev);
@@ -1497,7 +1363,7 @@ extern void drbd_bm_unlock(struct drbd_conf *mdev);
 /* drbd_main.c */
 
 extern struct kmem_cache *drbd_request_cache;
-extern struct kmem_cache *drbd_ee_cache;	/* epoch entries */
+extern struct kmem_cache *drbd_ee_cache;	/* peer requests */
 extern struct kmem_cache *drbd_bm_ext_cache;	/* bitmap extents */
 extern struct kmem_cache *drbd_al_ext_cache;	/* activity log extents */
 extern mempool_t *drbd_request_mempool;
@@ -1537,12 +1403,22 @@ extern struct bio *bio_alloc_drbd(gfp_t gfp_mask);
 
 extern rwlock_t global_state_lock;
 
-extern struct drbd_conf *drbd_new_device(unsigned int minor);
-extern void drbd_free_mdev(struct drbd_conf *mdev);
+extern int conn_lowest_minor(struct drbd_tconn *tconn);
+enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor, int vnr);
+extern void drbd_minor_destroy(struct kref *kref);
+
+extern int set_resource_options(struct drbd_tconn *tconn, struct res_opts *res_opts);
+extern struct drbd_tconn *conn_create(const char *name, struct res_opts *res_opts);
+extern void conn_destroy(struct kref *kref);
+struct drbd_tconn *conn_get_by_name(const char *name);
+extern struct drbd_tconn *conn_get_by_addrs(void *my_addr, int my_addr_len,
+					    void *peer_addr, int peer_addr_len);
+extern void conn_free_crypto(struct drbd_tconn *tconn);
 
 extern int proc_details;
 
 /* drbd_req */
+extern void __drbd_make_request(struct drbd_conf *, struct bio *, unsigned long);
 extern void drbd_make_request(struct request_queue *q, struct bio *bio);
 extern int drbd_read_remote(struct drbd_conf *mdev, struct drbd_request *req);
 extern int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec);
@@ -1550,10 +1426,11 @@ extern int is_valid_ar_handle(struct drbd_request *, sector_t);
 
 
 /* drbd_nl.c */
+extern int drbd_msg_put_info(const char *info);
 extern void drbd_suspend_io(struct drbd_conf *mdev);
 extern void drbd_resume_io(struct drbd_conf *mdev);
 extern char *ppsize(char *buf, unsigned long long size);
-extern sector_t drbd_new_dev_size(struct drbd_conf *, struct drbd_backing_dev *, int);
+extern sector_t drbd_new_dev_size(struct drbd_conf *, struct drbd_backing_dev *, sector_t, int);
 enum determine_dev_size { dev_size_error = -1, unchanged = 0, shrunk = 1, grew = 2 };
 extern enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *, enum dds_flags) __must_hold(local);
 extern void resync_after_online_grow(struct drbd_conf *);
@@ -1561,13 +1438,14 @@ extern void drbd_reconsider_max_bio_size(struct drbd_conf *mdev);
 extern enum drbd_state_rv drbd_set_role(struct drbd_conf *mdev,
 					enum drbd_role new_role,
 					int force);
-extern enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev);
-extern void drbd_try_outdate_peer_async(struct drbd_conf *mdev);
+extern bool conn_try_outdate_peer(struct drbd_tconn *tconn);
+extern void conn_try_outdate_peer_async(struct drbd_tconn *tconn);
 extern int drbd_khelper(struct drbd_conf *mdev, char *cmd);
 
 /* drbd_worker.c */
 extern int drbd_worker(struct drbd_thread *thi);
-extern int drbd_alter_sa(struct drbd_conf *mdev, int na);
+enum drbd_ret_code drbd_resync_after_valid(struct drbd_conf *mdev, int o_minor);
+void drbd_resync_after_changed(struct drbd_conf *mdev);
 extern void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side);
 extern void resume_next_sg(struct drbd_conf *mdev);
 extern void suspend_other_sg(struct drbd_conf *mdev);
@@ -1576,13 +1454,13 @@ extern int drbd_resync_finished(struct drbd_conf *mdev);
 extern void *drbd_md_get_buffer(struct drbd_conf *mdev);
 extern void drbd_md_put_buffer(struct drbd_conf *mdev);
 extern int drbd_md_sync_page_io(struct drbd_conf *mdev,
-				struct drbd_backing_dev *bdev, sector_t sector, int rw);
-extern void wait_until_done_or_disk_failure(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
-					    unsigned int *done);
-extern void drbd_ov_oos_found(struct drbd_conf*, sector_t, int);
+		struct drbd_backing_dev *bdev, sector_t sector, int rw);
+extern void drbd_ov_out_of_sync_found(struct drbd_conf *, sector_t, int);
+extern void wait_until_done_or_force_detached(struct drbd_conf *mdev,
+		struct drbd_backing_dev *bdev, unsigned int *done);
 extern void drbd_rs_controller_reset(struct drbd_conf *mdev);
 
-static inline void ov_oos_print(struct drbd_conf *mdev)
+static inline void ov_out_of_sync_print(struct drbd_conf *mdev)
 {
 	if (mdev->ov_last_oos_size) {
 		dev_err(DEV, "Out of sync: start=%llu, size=%lu (sectors)\n",
@@ -1594,97 +1472,102 @@ static inline void ov_oos_print(struct drbd_conf *mdev)
 
 
 extern void drbd_csum_bio(struct drbd_conf *, struct crypto_hash *, struct bio *, void *);
-extern void drbd_csum_ee(struct drbd_conf *, struct crypto_hash *, struct drbd_epoch_entry *, void *);
+extern void drbd_csum_ee(struct drbd_conf *, struct crypto_hash *,
+			 struct drbd_peer_request *, void *);
 /* worker callbacks */
-extern int w_req_cancel_conflict(struct drbd_conf *, struct drbd_work *, int);
-extern int w_read_retry_remote(struct drbd_conf *, struct drbd_work *, int);
-extern int w_e_end_data_req(struct drbd_conf *, struct drbd_work *, int);
-extern int w_e_end_rsdata_req(struct drbd_conf *, struct drbd_work *, int);
-extern int w_e_end_csum_rs_req(struct drbd_conf *, struct drbd_work *, int);
-extern int w_e_end_ov_reply(struct drbd_conf *, struct drbd_work *, int);
-extern int w_e_end_ov_req(struct drbd_conf *, struct drbd_work *, int);
-extern int w_ov_finished(struct drbd_conf *, struct drbd_work *, int);
-extern int w_resync_timer(struct drbd_conf *, struct drbd_work *, int);
-extern int w_resume_next_sg(struct drbd_conf *, struct drbd_work *, int);
-extern int w_send_write_hint(struct drbd_conf *, struct drbd_work *, int);
-extern int w_send_dblock(struct drbd_conf *, struct drbd_work *, int);
-extern int w_send_barrier(struct drbd_conf *, struct drbd_work *, int);
-extern int w_send_read_req(struct drbd_conf *, struct drbd_work *, int);
-extern int w_prev_work_done(struct drbd_conf *, struct drbd_work *, int);
-extern int w_e_reissue(struct drbd_conf *, struct drbd_work *, int);
-extern int w_restart_disk_io(struct drbd_conf *, struct drbd_work *, int);
-extern int w_send_oos(struct drbd_conf *, struct drbd_work *, int);
-extern int w_start_resync(struct drbd_conf *, struct drbd_work *, int);
+extern int w_e_end_data_req(struct drbd_work *, int);
+extern int w_e_end_rsdata_req(struct drbd_work *, int);
+extern int w_e_end_csum_rs_req(struct drbd_work *, int);
+extern int w_e_end_ov_reply(struct drbd_work *, int);
+extern int w_e_end_ov_req(struct drbd_work *, int);
+extern int w_ov_finished(struct drbd_work *, int);
+extern int w_resync_timer(struct drbd_work *, int);
+extern int w_send_write_hint(struct drbd_work *, int);
+extern int w_make_resync_request(struct drbd_work *, int);
+extern int w_send_dblock(struct drbd_work *, int);
+extern int w_send_read_req(struct drbd_work *, int);
+extern int w_prev_work_done(struct drbd_work *, int);
+extern int w_e_reissue(struct drbd_work *, int);
+extern int w_restart_disk_io(struct drbd_work *, int);
+extern int w_send_out_of_sync(struct drbd_work *, int);
+extern int w_start_resync(struct drbd_work *, int);
 
 extern void resync_timer_fn(unsigned long data);
 extern void start_resync_timer_fn(unsigned long data);
 
 /* drbd_receiver.c */
 extern int drbd_rs_should_slow_down(struct drbd_conf *mdev, sector_t sector);
-extern int drbd_submit_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
-		const unsigned rw, const int fault_type);
-extern int drbd_release_ee(struct drbd_conf *mdev, struct list_head *list);
-extern struct drbd_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev,
-					    u64 id,
-					    sector_t sector,
-					    unsigned int data_size,
-					    gfp_t gfp_mask) __must_hold(local);
-extern void drbd_free_some_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
-		int is_net);
-#define drbd_free_ee(m,e)	drbd_free_some_ee(m, e, 0)
-#define drbd_free_net_ee(m,e)	drbd_free_some_ee(m, e, 1)
-extern void drbd_wait_ee_list_empty(struct drbd_conf *mdev,
-		struct list_head *head);
-extern void _drbd_wait_ee_list_empty(struct drbd_conf *mdev,
-		struct list_head *head);
+extern int drbd_submit_peer_request(struct drbd_conf *,
+				    struct drbd_peer_request *, const unsigned,
+				    const int);
+extern int drbd_free_peer_reqs(struct drbd_conf *, struct list_head *);
+extern struct drbd_peer_request *drbd_alloc_peer_req(struct drbd_conf *, u64,
+						     sector_t, unsigned int,
+						     gfp_t) __must_hold(local);
+extern void __drbd_free_peer_req(struct drbd_conf *, struct drbd_peer_request *,
+				 int);
+#define drbd_free_peer_req(m,e) __drbd_free_peer_req(m, e, 0)
+#define drbd_free_net_peer_req(m,e) __drbd_free_peer_req(m, e, 1)
+extern struct page *drbd_alloc_pages(struct drbd_conf *, unsigned int, bool);
 extern void drbd_set_recv_tcq(struct drbd_conf *mdev, int tcq_enabled);
 extern void _drbd_clear_done_ee(struct drbd_conf *mdev, struct list_head *to_be_freed);
-extern void drbd_flush_workqueue(struct drbd_conf *mdev);
-extern void drbd_free_tl_hash(struct drbd_conf *mdev);
+extern void conn_flush_workqueue(struct drbd_tconn *tconn);
+extern int drbd_connected(struct drbd_conf *mdev);
+static inline void drbd_flush_workqueue(struct drbd_conf *mdev)
+{
+	conn_flush_workqueue(mdev->tconn);
+}
 
-/* yes, there is kernel_setsockopt, but only since 2.6.18. we don't need to
- * mess with get_fs/set_fs, we know we are KERNEL_DS always. */
+/* Yes, there is kernel_setsockopt, but only since 2.6.18.
+ * So we have our own copy of it here. */
 static inline int drbd_setsockopt(struct socket *sock, int level, int optname,
-			char __user *optval, int optlen)
+				  char *optval, int optlen)
 {
+	mm_segment_t oldfs = get_fs();
+	char __user *uoptval;
 	int err;
+
+	uoptval = (char __user __force *)optval;
+
+	set_fs(KERNEL_DS);
 	if (level == SOL_SOCKET)
-		err = sock_setsockopt(sock, level, optname, optval, optlen);
+		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
 	else
-		err = sock->ops->setsockopt(sock, level, optname, optval,
+		err = sock->ops->setsockopt(sock, level, optname, uoptval,
 					    optlen);
+	set_fs(oldfs);
 	return err;
 }
 
 static inline void drbd_tcp_cork(struct socket *sock)
 {
-	int __user val = 1;
+	int val = 1;
 	(void) drbd_setsockopt(sock, SOL_TCP, TCP_CORK,
-			(char __user *)&val, sizeof(val));
+			(char*)&val, sizeof(val));
 }
 
 static inline void drbd_tcp_uncork(struct socket *sock)
 {
-	int __user val = 0;
+	int val = 0;
 	(void) drbd_setsockopt(sock, SOL_TCP, TCP_CORK,
-			(char __user *)&val, sizeof(val));
+			(char*)&val, sizeof(val));
 }
 
 static inline void drbd_tcp_nodelay(struct socket *sock)
 {
-	int __user val = 1;
+	int val = 1;
 	(void) drbd_setsockopt(sock, SOL_TCP, TCP_NODELAY,
-			(char __user *)&val, sizeof(val));
+			(char*)&val, sizeof(val));
 }
 
 static inline void drbd_tcp_quickack(struct socket *sock)
 {
-	int __user val = 2;
+	int val = 2;
 	(void) drbd_setsockopt(sock, SOL_TCP, TCP_QUICKACK,
-			(char __user *)&val, sizeof(val));
+			(char*)&val, sizeof(val));
 }
 
-void drbd_bump_write_ordering(struct drbd_conf *mdev, enum write_ordering_e wo);
+void drbd_bump_write_ordering(struct drbd_tconn *tconn, enum write_ordering_e wo);
 
 /* drbd_proc.c */
 extern struct proc_dir_entry *drbd_proc;
@@ -1693,8 +1576,8 @@ extern const char *drbd_conn_str(enum drbd_conns s);
 extern const char *drbd_role_str(enum drbd_role s);
 
 /* drbd_actlog.c */
-extern void drbd_al_begin_io(struct drbd_conf *mdev, sector_t sector);
-extern void drbd_al_complete_io(struct drbd_conf *mdev, sector_t sector);
+extern void drbd_al_begin_io(struct drbd_conf *mdev, struct drbd_interval *i);
+extern void drbd_al_complete_io(struct drbd_conf *mdev, struct drbd_interval *i);
 extern void drbd_rs_complete_io(struct drbd_conf *mdev, sector_t sector);
 extern int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector);
 extern int drbd_try_rs_begin_io(struct drbd_conf *mdev, sector_t sector);
@@ -1702,7 +1585,6 @@ extern void drbd_rs_cancel_all(struct drbd_conf *mdev);
 extern int drbd_rs_del_all(struct drbd_conf *mdev);
 extern void drbd_rs_failed_io(struct drbd_conf *mdev,
 		sector_t sector, int size);
-extern int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *);
 extern void drbd_advance_rs_marks(struct drbd_conf *mdev, unsigned long still_to_go);
 extern void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector,
 		int size, const char *file, const unsigned int line);
@@ -1712,73 +1594,24 @@ extern int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector,
 		int size, const char *file, const unsigned int line);
 #define drbd_set_out_of_sync(mdev, sector, size) \
 	__drbd_set_out_of_sync(mdev, sector, size, __FILE__, __LINE__)
-extern void drbd_al_apply_to_bm(struct drbd_conf *mdev);
 extern void drbd_al_shrink(struct drbd_conf *mdev);
 
-
 /* drbd_nl.c */
-
-void drbd_nl_cleanup(void);
-int __init drbd_nl_init(void);
-void drbd_bcast_state(struct drbd_conf *mdev, union drbd_state);
-void drbd_bcast_sync_progress(struct drbd_conf *mdev);
-void drbd_bcast_ee(struct drbd_conf *mdev,
-		const char *reason, const int dgs,
-		const char* seen_hash, const char* calc_hash,
-		const struct drbd_epoch_entry* e);
-
-
-/**
- * DOC: DRBD State macros
- *
- * These macros are used to express state changes in easily readable form.
- *
- * The NS macros expand to a mask and a value, that can be bit ored onto the
- * current state as soon as the spinlock (req_lock) was taken.
- *
- * The _NS macros are used for state functions that get called with the
- * spinlock. These macros expand directly to the new state value.
- *
- * Besides the basic forms NS() and _NS() additional _?NS[23] are defined
- * to express state changes that affect more than one aspect of the state.
- *
- * E.g. NS2(conn, C_CONNECTED, peer, R_SECONDARY)
- * Means that the network connection was established and that the peer
- * is in secondary role.
- */
-#define role_MASK R_MASK
-#define peer_MASK R_MASK
-#define disk_MASK D_MASK
-#define pdsk_MASK D_MASK
-#define conn_MASK C_MASK
-#define susp_MASK 1
-#define user_isp_MASK 1
-#define aftr_isp_MASK 1
-#define susp_nod_MASK 1
-#define susp_fen_MASK 1
-
-#define NS(T, S) \
-	({ union drbd_state mask; mask.i = 0; mask.T = T##_MASK; mask; }), \
-	({ union drbd_state val; val.i = 0; val.T = (S); val; })
-#define NS2(T1, S1, T2, S2) \
-	({ union drbd_state mask; mask.i = 0; mask.T1 = T1##_MASK; \
-	  mask.T2 = T2##_MASK; mask; }), \
-	({ union drbd_state val; val.i = 0; val.T1 = (S1); \
-	  val.T2 = (S2); val; })
-#define NS3(T1, S1, T2, S2, T3, S3) \
-	({ union drbd_state mask; mask.i = 0; mask.T1 = T1##_MASK; \
-	  mask.T2 = T2##_MASK; mask.T3 = T3##_MASK; mask; }), \
-	({ union drbd_state val;  val.i = 0; val.T1 = (S1); \
-	  val.T2 = (S2); val.T3 = (S3); val; })
-
-#define _NS(D, T, S) \
-	D, ({ union drbd_state __ns; __ns.i = D->state.i; __ns.T = (S); __ns; })
-#define _NS2(D, T1, S1, T2, S2) \
-	D, ({ union drbd_state __ns; __ns.i = D->state.i; __ns.T1 = (S1); \
-	__ns.T2 = (S2); __ns; })
-#define _NS3(D, T1, S1, T2, S2, T3, S3) \
-	D, ({ union drbd_state __ns; __ns.i = D->state.i; __ns.T1 = (S1); \
-	__ns.T2 = (S2); __ns.T3 = (S3); __ns; })
+/* state info broadcast */
+struct sib_info {
+	enum drbd_state_info_bcast_reason sib_reason;
+	union {
+		struct {
+			char *helper_name;
+			unsigned helper_exit_code;
+		};
+		struct {
+			union drbd_state os;
+			union drbd_state ns;
+		};
+	};
+};
+void drbd_bcast_event(struct drbd_conf *mdev, const struct sib_info *sib);
 
 /*
  * inline helper functions
@@ -1795,9 +1628,10 @@ static inline struct page *page_chain_next(struct page *page)
 #define page_chain_for_each_safe(page, n) \
 	for (; page && ({ n = page_chain_next(page); 1; }); page = n)
 
-static inline int drbd_ee_has_active_page(struct drbd_epoch_entry *e)
+
+static inline int drbd_peer_req_has_active_page(struct drbd_peer_request *peer_req)
 {
-	struct page *page = e->pages;
+	struct page *page = peer_req->pages;
 	page_chain_for_each(page) {
 		if (page_count(page) > 1)
 			return 1;
@@ -1805,18 +1639,6 @@ static inline int drbd_ee_has_active_page(struct drbd_epoch_entry *e)
 	return 0;
 }
 
-static inline void drbd_state_lock(struct drbd_conf *mdev)
-{
-	wait_event(mdev->misc_wait,
-		   !test_and_set_bit(CLUSTER_ST_CHANGE, &mdev->flags));
-}
-
-static inline void drbd_state_unlock(struct drbd_conf *mdev)
-{
-	clear_bit(CLUSTER_ST_CHANGE, &mdev->flags);
-	wake_up(&mdev->misc_wait);
-}
-
 static inline enum drbd_state_rv
 _drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
 		enum chg_state_flags flags, struct completion *done)
@@ -1830,48 +1652,71 @@ _drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
 	return rv;
 }
 
-/**
- * drbd_request_state() - Reqest a state change
- * @mdev:	DRBD device.
- * @mask:	mask of state bits to change.
- * @val:	value of new state bits.
- *
- * This is the most graceful way of requesting a state change. It is verbose
- * quite verbose in case the state change is not possible, and all those
- * state changes are globally serialized.
- */
-static inline int drbd_request_state(struct drbd_conf *mdev,
-				     union drbd_state mask,
-				     union drbd_state val)
+static inline union drbd_state drbd_read_state(struct drbd_conf *mdev)
 {
-	return _drbd_request_state(mdev, mask, val, CS_VERBOSE + CS_ORDERED);
+	union drbd_state rv;
+
+	rv.i = mdev->state.i;
+	rv.susp = mdev->tconn->susp;
+	rv.susp_nod = mdev->tconn->susp_nod;
+	rv.susp_fen = mdev->tconn->susp_fen;
+
+	return rv;
 }
 
 enum drbd_force_detach_flags {
-	DRBD_IO_ERROR,
+	DRBD_READ_ERROR,
+	DRBD_WRITE_ERROR,
 	DRBD_META_IO_ERROR,
 	DRBD_FORCE_DETACH,
 };
 
 #define __drbd_chk_io_error(m,f) __drbd_chk_io_error_(m,f, __func__)
 static inline void __drbd_chk_io_error_(struct drbd_conf *mdev,
-		enum drbd_force_detach_flags forcedetach,
+		enum drbd_force_detach_flags df,
 		const char *where)
 {
-	switch (mdev->ldev->dc.on_io_error) {
-	case EP_PASS_ON:
-		if (forcedetach == DRBD_IO_ERROR) {
+	enum drbd_io_error_p ep;
+
+	rcu_read_lock();
+	ep = rcu_dereference(mdev->ldev->disk_conf)->on_io_error;
+	rcu_read_unlock();
+	switch (ep) {
+	case EP_PASS_ON: /* FIXME would this be better named "Ignore"? */
+		if (df == DRBD_READ_ERROR || df == DRBD_WRITE_ERROR) {
 			if (__ratelimit(&drbd_ratelimit_state))
 				dev_err(DEV, "Local IO failed in %s.\n", where);
 			if (mdev->state.disk > D_INCONSISTENT)
 				_drbd_set_state(_NS(mdev, disk, D_INCONSISTENT), CS_HARD, NULL);
 			break;
 		}
-		/* NOTE fall through to detach case if forcedetach set */
+		/* NOTE fall through for DRBD_META_IO_ERROR or DRBD_FORCE_DETACH */
 	case EP_DETACH:
 	case EP_CALL_HELPER:
+		/* Remember whether we saw a READ or WRITE error.
+		 *
+		 * Recovery of the affected area for WRITE failure is covered
+		 * by the activity log.
+		 * READ errors may fall outside that area though. Certain READ
+		 * errors can be "healed" by writing good data to the affected
+		 * blocks, which triggers block re-allocation in lower layers.
+		 *
+		 * If we can not write the bitmap after a READ error,
+		 * we may need to trigger a full sync (see w_go_diskless()).
+		 *
+		 * Force-detach is not really an IO error, but rather a
+		 * desperate measure to try to deal with a completely
+		 * unresponsive lower level IO stack.
+		 * Still it should be treated as a WRITE error.
+		 *
+		 * Meta IO error is always WRITE error:
+		 * we read meta data only once during attach,
+		 * which will fail in case of errors.
+		 */
 		set_bit(WAS_IO_ERROR, &mdev->flags);
-		if (forcedetach == DRBD_FORCE_DETACH)
+		if (df == DRBD_READ_ERROR)
+			set_bit(WAS_READ_ERROR, &mdev->flags);
+		if (df == DRBD_FORCE_DETACH)
 			set_bit(FORCE_DETACH, &mdev->flags);
 		if (mdev->state.disk > D_FAILED) {
 			_drbd_set_state(_NS(mdev, disk, D_FAILED), CS_HARD, NULL);
@@ -1896,9 +1741,9 @@ static inline void drbd_chk_io_error_(struct drbd_conf *mdev,
 {
 	if (error) {
 		unsigned long flags;
-		spin_lock_irqsave(&mdev->req_lock, flags);
+		spin_lock_irqsave(&mdev->tconn->req_lock, flags);
 		__drbd_chk_io_error_(mdev, forcedetach, where);
-		spin_unlock_irqrestore(&mdev->req_lock, flags);
+		spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
 	}
 }
 
@@ -1910,9 +1755,9 @@ static inline void drbd_chk_io_error_(struct drbd_conf *mdev,
  * BTW, for internal meta data, this happens to be the maximum capacity
  * we could agree upon with our peer node.
  */
-static inline sector_t drbd_md_first_sector(struct drbd_backing_dev *bdev)
+static inline sector_t _drbd_md_first_sector(int meta_dev_idx, struct drbd_backing_dev *bdev)
 {
-	switch (bdev->dc.meta_dev_idx) {
+	switch (meta_dev_idx) {
 	case DRBD_MD_INDEX_INTERNAL:
 	case DRBD_MD_INDEX_FLEX_INT:
 		return bdev->md.md_offset + bdev->md.bm_offset;
@@ -1922,13 +1767,30 @@ static inline sector_t drbd_md_first_sector(struct drbd_backing_dev *bdev)
 	}
 }
 
+static inline sector_t drbd_md_first_sector(struct drbd_backing_dev *bdev)
+{
+	int meta_dev_idx;
+
+	rcu_read_lock();
+	meta_dev_idx = rcu_dereference(bdev->disk_conf)->meta_dev_idx;
+	rcu_read_unlock();
+
+	return _drbd_md_first_sector(meta_dev_idx, bdev);
+}
+
 /**
  * drbd_md_last_sector() - Return the last sector number of the meta data area
  * @bdev:	Meta data block device.
  */
 static inline sector_t drbd_md_last_sector(struct drbd_backing_dev *bdev)
 {
-	switch (bdev->dc.meta_dev_idx) {
+	int meta_dev_idx;
+
+	rcu_read_lock();
+	meta_dev_idx = rcu_dereference(bdev->disk_conf)->meta_dev_idx;
+	rcu_read_unlock();
+
+	switch (meta_dev_idx) {
 	case DRBD_MD_INDEX_INTERNAL:
 	case DRBD_MD_INDEX_FLEX_INT:
 		return bdev->md.md_offset + MD_AL_OFFSET - 1;
@@ -1956,12 +1818,18 @@ static inline sector_t drbd_get_capacity(struct block_device *bdev)
 static inline sector_t drbd_get_max_capacity(struct drbd_backing_dev *bdev)
 {
 	sector_t s;
-	switch (bdev->dc.meta_dev_idx) {
+	int meta_dev_idx;
+
+	rcu_read_lock();
+	meta_dev_idx = rcu_dereference(bdev->disk_conf)->meta_dev_idx;
+	rcu_read_unlock();
+
+	switch (meta_dev_idx) {
 	case DRBD_MD_INDEX_INTERNAL:
 	case DRBD_MD_INDEX_FLEX_INT:
 		s = drbd_get_capacity(bdev->backing_bdev)
 			? min_t(sector_t, DRBD_MAX_SECTORS_FLEX,
-					drbd_md_first_sector(bdev))
+				_drbd_md_first_sector(meta_dev_idx, bdev))
 			: 0;
 		break;
 	case DRBD_MD_INDEX_FLEX_EXT:
@@ -1987,9 +1855,15 @@ static inline sector_t drbd_get_max_capacity(struct drbd_backing_dev *bdev)
 static inline sector_t drbd_md_ss__(struct drbd_conf *mdev,
 				    struct drbd_backing_dev *bdev)
 {
-	switch (bdev->dc.meta_dev_idx) {
+	int meta_dev_idx;
+
+	rcu_read_lock();
+	meta_dev_idx = rcu_dereference(bdev->disk_conf)->meta_dev_idx;
+	rcu_read_unlock();
+
+	switch (meta_dev_idx) {
 	default: /* external, some index */
-		return MD_RESERVED_SECT * bdev->dc.meta_dev_idx;
+		return MD_RESERVED_SECT * meta_dev_idx;
 	case DRBD_MD_INDEX_INTERNAL:
 		/* with drbd08, internal meta data is always "flexible" */
 	case DRBD_MD_INDEX_FLEX_INT:
@@ -2015,9 +1889,8 @@ drbd_queue_work_front(struct drbd_work_queue *q, struct drbd_work *w)
 	unsigned long flags;
 	spin_lock_irqsave(&q->q_lock, flags);
 	list_add(&w->list, &q->q);
-	up(&q->s); /* within the spinlock,
-		      see comment near end of drbd_worker() */
 	spin_unlock_irqrestore(&q->q_lock, flags);
+	wake_up(&q->q_wait);
 }
 
 static inline void
@@ -2026,41 +1899,35 @@ drbd_queue_work(struct drbd_work_queue *q, struct drbd_work *w)
 	unsigned long flags;
 	spin_lock_irqsave(&q->q_lock, flags);
 	list_add_tail(&w->list, &q->q);
-	up(&q->s); /* within the spinlock,
-		      see comment near end of drbd_worker() */
 	spin_unlock_irqrestore(&q->q_lock, flags);
+	wake_up(&q->q_wait);
 }
 
-static inline void wake_asender(struct drbd_conf *mdev)
+static inline void wake_asender(struct drbd_tconn *tconn)
 {
-	if (test_bit(SIGNAL_ASENDER, &mdev->flags))
-		force_sig(DRBD_SIG, mdev->asender.task);
+	if (test_bit(SIGNAL_ASENDER, &tconn->flags))
+		force_sig(DRBD_SIG, tconn->asender.task);
 }
 
-static inline void request_ping(struct drbd_conf *mdev)
+static inline void request_ping(struct drbd_tconn *tconn)
 {
-	set_bit(SEND_PING, &mdev->flags);
-	wake_asender(mdev);
+	set_bit(SEND_PING, &tconn->flags);
+	wake_asender(tconn);
 }
 
-static inline int drbd_send_short_cmd(struct drbd_conf *mdev,
-	enum drbd_packets cmd)
-{
-	struct p_header80 h;
-	return drbd_send_cmd(mdev, USE_DATA_SOCKET, cmd, &h, sizeof(h));
-}
-
-static inline int drbd_send_ping(struct drbd_conf *mdev)
-{
-	struct p_header80 h;
-	return drbd_send_cmd(mdev, USE_META_SOCKET, P_PING, &h, sizeof(h));
-}
+extern void *conn_prepare_command(struct drbd_tconn *, struct drbd_socket *);
+extern void *drbd_prepare_command(struct drbd_conf *, struct drbd_socket *);
+extern int conn_send_command(struct drbd_tconn *, struct drbd_socket *,
+			     enum drbd_packet, unsigned int, void *,
+			     unsigned int);
+extern int drbd_send_command(struct drbd_conf *, struct drbd_socket *,
+			     enum drbd_packet, unsigned int, void *,
+			     unsigned int);
 
-static inline int drbd_send_ping_ack(struct drbd_conf *mdev)
-{
-	struct p_header80 h;
-	return drbd_send_cmd(mdev, USE_META_SOCKET, P_PING_ACK, &h, sizeof(h));
-}
+extern int drbd_send_ping(struct drbd_tconn *tconn);
+extern int drbd_send_ping_ack(struct drbd_tconn *tconn);
+extern int drbd_send_state_req(struct drbd_conf *, union drbd_state, union drbd_state);
+extern int conn_send_state_req(struct drbd_tconn *, union drbd_state, union drbd_state);
 
 static inline void drbd_thread_stop(struct drbd_thread *thi)
 {
@@ -2082,21 +1949,21 @@ static inline void drbd_thread_restart_nowait(struct drbd_thread *thi)
  * or implicit barrier packets as necessary.
  * increased:
  *  w_send_barrier
- *  _req_mod(req, queue_for_net_write or queue_for_net_read);
+ *  _req_mod(req, QUEUE_FOR_NET_WRITE or QUEUE_FOR_NET_READ);
  *    it is much easier and equally valid to count what we queue for the
  *    worker, even before it actually was queued or send.
  *    (drbd_make_request_common; recovery path on read io-error)
  * decreased:
  *  got_BarrierAck (respective tl_clear, tl_clear_barrier)
- *  _req_mod(req, data_received)
+ *  _req_mod(req, DATA_RECEIVED)
  *     [from receive_DataReply]
- *  _req_mod(req, write_acked_by_peer or recv_acked_by_peer or neg_acked)
+ *  _req_mod(req, WRITE_ACKED_BY_PEER or RECV_ACKED_BY_PEER or NEG_ACKED)
  *     [from got_BlockAck (P_WRITE_ACK, P_RECV_ACK)]
  *     for some reason it is NOT decreased in got_NegAck,
  *     but in the resulting cleanup code from report_params.
  *     we should try to remember the reason for that...
- *  _req_mod(req, send_failed or send_canceled)
- *  _req_mod(req, connection_lost_while_pending)
+ *  _req_mod(req, SEND_FAILED or SEND_CANCELED)
+ *  _req_mod(req, CONNECTION_LOST_WHILE_PENDING)
  *     [from tl_clear_barrier]
  */
 static inline void inc_ap_pending(struct drbd_conf *mdev)
@@ -2104,17 +1971,19 @@ static inline void inc_ap_pending(struct drbd_conf *mdev)
 	atomic_inc(&mdev->ap_pending_cnt);
 }
 
-#define ERR_IF_CNT_IS_NEGATIVE(which)				\
-	if (atomic_read(&mdev->which) < 0)			\
+#define ERR_IF_CNT_IS_NEGATIVE(which, func, line)			\
+	if (atomic_read(&mdev->which) < 0)				\
 		dev_err(DEV, "in %s:%d: " #which " = %d < 0 !\n",	\
-		    __func__ , __LINE__ ,			\
-		    atomic_read(&mdev->which))
+			func, line,					\
+			atomic_read(&mdev->which))
 
-#define dec_ap_pending(mdev)	do {				\
-	typecheck(struct drbd_conf *, mdev);			\
-	if (atomic_dec_and_test(&mdev->ap_pending_cnt))		\
-		wake_up(&mdev->misc_wait);			\
-	ERR_IF_CNT_IS_NEGATIVE(ap_pending_cnt); } while (0)
+#define dec_ap_pending(mdev) _dec_ap_pending(mdev, __FUNCTION__, __LINE__)
+static inline void _dec_ap_pending(struct drbd_conf *mdev, const char *func, int line)
+{
+	if (atomic_dec_and_test(&mdev->ap_pending_cnt))
+		wake_up(&mdev->misc_wait);
+	ERR_IF_CNT_IS_NEGATIVE(ap_pending_cnt, func, line);
+}
 
 /* counts how many resync-related answers we still expect from the peer
  *		     increase			decrease
@@ -2127,10 +1996,12 @@ static inline void inc_rs_pending(struct drbd_conf *mdev)
 	atomic_inc(&mdev->rs_pending_cnt);
 }
 
-#define dec_rs_pending(mdev)	do {				\
-	typecheck(struct drbd_conf *, mdev);			\
-	atomic_dec(&mdev->rs_pending_cnt);			\
-	ERR_IF_CNT_IS_NEGATIVE(rs_pending_cnt); } while (0)
+#define dec_rs_pending(mdev) _dec_rs_pending(mdev, __FUNCTION__, __LINE__)
+static inline void _dec_rs_pending(struct drbd_conf *mdev, const char *func, int line)
+{
+	atomic_dec(&mdev->rs_pending_cnt);
+	ERR_IF_CNT_IS_NEGATIVE(rs_pending_cnt, func, line);
+}
 
 /* counts how many answers we still need to send to the peer.
  * increased on
@@ -2146,38 +2017,18 @@ static inline void inc_unacked(struct drbd_conf *mdev)
 	atomic_inc(&mdev->unacked_cnt);
 }
 
-#define dec_unacked(mdev)	do {				\
-	typecheck(struct drbd_conf *, mdev);			\
-	atomic_dec(&mdev->unacked_cnt);				\
-	ERR_IF_CNT_IS_NEGATIVE(unacked_cnt); } while (0)
-
-#define sub_unacked(mdev, n)	do {				\
-	typecheck(struct drbd_conf *, mdev);			\
-	atomic_sub(n, &mdev->unacked_cnt);			\
-	ERR_IF_CNT_IS_NEGATIVE(unacked_cnt); } while (0)
-
-
-static inline void put_net_conf(struct drbd_conf *mdev)
+#define dec_unacked(mdev) _dec_unacked(mdev, __FUNCTION__, __LINE__)
+static inline void _dec_unacked(struct drbd_conf *mdev, const char *func, int line)
 {
-	if (atomic_dec_and_test(&mdev->net_cnt))
-		wake_up(&mdev->net_cnt_wait);
+	atomic_dec(&mdev->unacked_cnt);
+	ERR_IF_CNT_IS_NEGATIVE(unacked_cnt, func, line);
 }
 
-/**
- * get_net_conf() - Increase ref count on mdev->net_conf; Returns 0 if nothing there
- * @mdev:	DRBD device.
- *
- * You have to call put_net_conf() when finished working with mdev->net_conf.
- */
-static inline int get_net_conf(struct drbd_conf *mdev)
+#define sub_unacked(mdev, n) _sub_unacked(mdev, n, __FUNCTION__, __LINE__)
+static inline void _sub_unacked(struct drbd_conf *mdev, int n, const char *func, int line)
 {
-	int have_net_conf;
-
-	atomic_inc(&mdev->net_cnt);
-	have_net_conf = mdev->state.conn >= C_UNCONNECTED;
-	if (!have_net_conf)
-		put_net_conf(mdev);
-	return have_net_conf;
+	atomic_sub(n, &mdev->unacked_cnt);
+	ERR_IF_CNT_IS_NEGATIVE(unacked_cnt, func, line);
 }
 
 /**
@@ -2281,17 +2132,20 @@ static inline void drbd_get_syncer_progress(struct drbd_conf *mdev,
  * maybe re-implement using semaphores? */
 static inline int drbd_get_max_buffers(struct drbd_conf *mdev)
 {
-	int mxb = 1000000; /* arbitrary limit on open requests */
-	if (get_net_conf(mdev)) {
-		mxb = mdev->net_conf->max_buffers;
-		put_net_conf(mdev);
-	}
+	struct net_conf *nc;
+	int mxb;
+
+	rcu_read_lock();
+	nc = rcu_dereference(mdev->tconn->net_conf);
+	mxb = nc ? nc->max_buffers : 1000000;  /* arbitrary limit on open requests */
+	rcu_read_unlock();
+
 	return mxb;
 }
 
 static inline int drbd_state_is_stable(struct drbd_conf *mdev)
 {
-	union drbd_state s = mdev->state;
+	union drbd_dev_state s = mdev->state;
 
 	/* DO NOT add a default clause, we want the compiler to warn us
 	 * for any newly introduced state we may have forgotten to add here */
@@ -2325,7 +2179,7 @@ static inline int drbd_state_is_stable(struct drbd_conf *mdev)
 
 		/* Allow IO in BM exchange states with new protocols */
 	case C_WF_BITMAP_S:
-		if (mdev->agreed_pro_version < 96)
+		if (mdev->tconn->agreed_pro_version < 96)
 			return 0;
 		break;
 
@@ -2347,7 +2201,7 @@ static inline int drbd_state_is_stable(struct drbd_conf *mdev)
 		/* disk state is stable as well. */
 		break;
 
-	/* no new io accepted during tansitional states */
+	/* no new io accepted during transitional states */
 	case D_ATTACHING:
 	case D_NEGOTIATING:
 	case D_UNKNOWN:
@@ -2359,16 +2213,18 @@ static inline int drbd_state_is_stable(struct drbd_conf *mdev)
 	return 1;
 }
 
-static inline int is_susp(union drbd_state s)
+static inline int drbd_suspended(struct drbd_conf *mdev)
 {
-	return s.susp || s.susp_nod || s.susp_fen;
+	struct drbd_tconn *tconn = mdev->tconn;
+
+	return tconn->susp || tconn->susp_fen || tconn->susp_nod;
 }
 
 static inline bool may_inc_ap_bio(struct drbd_conf *mdev)
 {
 	int mxb = drbd_get_max_buffers(mdev);
 
-	if (is_susp(mdev->state))
+	if (drbd_suspended(mdev))
 		return false;
 	if (test_bit(SUSPEND_IO, &mdev->flags))
 		return false;
@@ -2390,30 +2246,30 @@ static inline bool may_inc_ap_bio(struct drbd_conf *mdev)
 	return true;
 }
 
-static inline bool inc_ap_bio_cond(struct drbd_conf *mdev, int count)
+static inline bool inc_ap_bio_cond(struct drbd_conf *mdev)
 {
 	bool rv = false;
 
-	spin_lock_irq(&mdev->req_lock);
+	spin_lock_irq(&mdev->tconn->req_lock);
 	rv = may_inc_ap_bio(mdev);
 	if (rv)
-		atomic_add(count, &mdev->ap_bio_cnt);
-	spin_unlock_irq(&mdev->req_lock);
+		atomic_inc(&mdev->ap_bio_cnt);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
 	return rv;
 }
 
-static inline void inc_ap_bio(struct drbd_conf *mdev, int count)
+static inline void inc_ap_bio(struct drbd_conf *mdev)
 {
 	/* we wait here
 	 *    as long as the device is suspended
 	 *    until the bitmap is no longer on the fly during connection
-	 *    handshake as long as we would exeed the max_buffer limit.
+	 *    handshake as long as we would exceed the max_buffer limit.
 	 *
 	 * to avoid races with the reconnect code,
 	 * we need to atomic_inc within the spinlock. */
 
-	wait_event(mdev->misc_wait, inc_ap_bio_cond(mdev, count));
+	wait_event(mdev->misc_wait, inc_ap_bio_cond(mdev));
 }
 
 static inline void dec_ap_bio(struct drbd_conf *mdev)
@@ -2425,7 +2281,7 @@ static inline void dec_ap_bio(struct drbd_conf *mdev)
 
 	if (ap_bio == 0 && test_bit(BITMAP_IO, &mdev->flags)) {
 		if (!test_and_set_bit(BITMAP_IO_QUEUED, &mdev->flags))
-			drbd_queue_work(&mdev->data.work, &mdev->bm_io_work.w);
+			drbd_queue_work(&mdev->tconn->sender_work, &mdev->bm_io_work.w);
 	}
 
 	/* this currently does wake_up for every dec_ap_bio!
@@ -2435,6 +2291,12 @@ static inline void dec_ap_bio(struct drbd_conf *mdev)
 		wake_up(&mdev->misc_wait);
 }
 
+static inline bool verify_can_do_stop_sector(struct drbd_conf *mdev)
+{
+	return mdev->tconn->agreed_pro_version >= 97 &&
+		mdev->tconn->agreed_pro_version != 100;
+}
+
 static inline int drbd_set_ed_uuid(struct drbd_conf *mdev, u64 val)
 {
 	int changed = mdev->ed_uuid != val;
@@ -2442,40 +2304,6 @@ static inline int drbd_set_ed_uuid(struct drbd_conf *mdev, u64 val)
 	return changed;
 }
 
-static inline int seq_cmp(u32 a, u32 b)
-{
-	/* we assume wrap around at 32bit.
-	 * for wrap around at 24bit (old atomic_t),
-	 * we'd have to
-	 *  a <<= 8; b <<= 8;
-	 */
-	return (s32)(a) - (s32)(b);
-}
-#define seq_lt(a, b) (seq_cmp((a), (b)) < 0)
-#define seq_gt(a, b) (seq_cmp((a), (b)) > 0)
-#define seq_ge(a, b) (seq_cmp((a), (b)) >= 0)
-#define seq_le(a, b) (seq_cmp((a), (b)) <= 0)
-/* CAUTION: please no side effects in arguments! */
-#define seq_max(a, b) ((u32)(seq_gt((a), (b)) ? (a) : (b)))
-
-static inline void update_peer_seq(struct drbd_conf *mdev, unsigned int new_seq)
-{
-	unsigned int m;
-	spin_lock(&mdev->peer_seq_lock);
-	m = seq_max(mdev->peer_seq, new_seq);
-	mdev->peer_seq = m;
-	spin_unlock(&mdev->peer_seq_lock);
-	if (m == new_seq)
-		wake_up(&mdev->seq_wait);
-}
-
-static inline void drbd_update_congested(struct drbd_conf *mdev)
-{
-	struct sock *sk = mdev->data.socket->sk;
-	if (sk->sk_wmem_queued > sk->sk_sndbuf * 4 / 5)
-		set_bit(NET_CONGESTED, &mdev->flags);
-}
-
 static inline int drbd_queue_order_type(struct drbd_conf *mdev)
 {
 	/* sorry, we currently have no working implementation
@@ -2490,10 +2318,15 @@ static inline void drbd_md_flush(struct drbd_conf *mdev)
 {
 	int r;
 
+	if (mdev->ldev == NULL) {
+		dev_warn(DEV, "mdev->ldev == NULL in drbd_md_flush\n");
+		return;
+	}
+
 	if (test_bit(MD_NO_FUA, &mdev->flags))
 		return;
 
-	r = blkdev_issue_flush(mdev->ldev->md_bdev, GFP_KERNEL, NULL);
+	r = blkdev_issue_flush(mdev->ldev->md_bdev, GFP_NOIO, NULL);
 	if (r) {
 		set_bit(MD_NO_FUA, &mdev->flags);
 		dev_err(DEV, "meta data flush failed with status %d, disabling md-flushes\n", r);
@@ -2501,3 +2334,30 @@ static inline void drbd_md_flush(struct drbd_conf *mdev)
 }
 
 #endif
+
+/* This is defined in drivers/md/md.h as well. Should go into wait.h */
+#define __wait_event_lock_irq(wq, condition, lock, cmd) 		\
+do {									\
+	wait_queue_t __wait;						\
+	init_waitqueue_entry(&__wait, current);				\
+									\
+	add_wait_queue(&wq, &__wait);					\
+	for (;;) {							\
+		set_current_state(TASK_UNINTERRUPTIBLE);		\
+		if (condition)						\
+			break;						\
+		spin_unlock_irq(&lock);					\
+		cmd;							\
+		schedule();						\
+		spin_lock_irq(&lock);					\
+	}								\
+	current->state = TASK_RUNNING;					\
+	remove_wait_queue(&wq, &__wait);				\
+} while (0)
+
+#define wait_event_lock_irq(wq, condition, lock, cmd) 			\
+do {									\
+	if (condition)	 						\
+		break;							\
+	__wait_event_lock_irq(wq, condition, lock, cmd);		\
+} while (0)
diff --git a/drivers/block/drbd/drbd_interval.c b/drivers/block/drbd/drbd_interval.c
new file mode 100644
index 0000000..89c497c
--- /dev/null
+++ b/drivers/block/drbd/drbd_interval.c
@@ -0,0 +1,207 @@
+#include <asm/bug.h>
+#include <linux/rbtree_augmented.h>
+#include "drbd_interval.h"
+
+/**
+ * interval_end  -  return end of @node
+ */
+static inline
+sector_t interval_end(struct rb_node *node)
+{
+	struct drbd_interval *this = rb_entry(node, struct drbd_interval, rb);
+	return this->end;
+}
+
+/**
+ * compute_subtree_last  -  compute end of @node
+ *
+ * The end of an interval is the highest (start + (size >> 9)) value of this
+ * node and of its children.  Called for @node and its parents whenever the end
+ * may have changed.
+ */
+static inline sector_t
+compute_subtree_last(struct drbd_interval *node)
+{
+	sector_t max = node->sector + (node->size >> 9);
+
+	if (node->rb.rb_left) {
+		sector_t left = interval_end(node->rb.rb_left);
+		if (left > max)
+			max = left;
+	}
+	if (node->rb.rb_right) {
+		sector_t right = interval_end(node->rb.rb_right);
+		if (right > max)
+			max = right;
+	}
+	return max;
+}
+
+static void augment_propagate(struct rb_node *rb, struct rb_node *stop)
+{
+	while (rb != stop) {
+		struct drbd_interval *node = rb_entry(rb, struct drbd_interval, rb);
+		sector_t subtree_last = compute_subtree_last(node);
+		if (node->end == subtree_last)
+			break;
+		node->end = subtree_last;
+		rb = rb_parent(&node->rb);
+	}
+}
+
+static void augment_copy(struct rb_node *rb_old, struct rb_node *rb_new)
+{
+	struct drbd_interval *old = rb_entry(rb_old, struct drbd_interval, rb);
+	struct drbd_interval *new = rb_entry(rb_new, struct drbd_interval, rb);
+
+	new->end = old->end;
+}
+
+static void augment_rotate(struct rb_node *rb_old, struct rb_node *rb_new)
+{
+	struct drbd_interval *old = rb_entry(rb_old, struct drbd_interval, rb);
+	struct drbd_interval *new = rb_entry(rb_new, struct drbd_interval, rb);
+
+	new->end = old->end;
+	old->end = compute_subtree_last(old);
+}
+
+static const struct rb_augment_callbacks augment_callbacks = {
+	augment_propagate,
+	augment_copy,
+	augment_rotate,
+};
+
+/**
+ * drbd_insert_interval  -  insert a new interval into a tree
+ */
+bool
+drbd_insert_interval(struct rb_root *root, struct drbd_interval *this)
+{
+	struct rb_node **new = &root->rb_node, *parent = NULL;
+
+	BUG_ON(!IS_ALIGNED(this->size, 512));
+
+	while (*new) {
+		struct drbd_interval *here =
+			rb_entry(*new, struct drbd_interval, rb);
+
+		parent = *new;
+		if (this->sector < here->sector)
+			new = &(*new)->rb_left;
+		else if (this->sector > here->sector)
+			new = &(*new)->rb_right;
+		else if (this < here)
+			new = &(*new)->rb_left;
+		else if (this > here)
+			new = &(*new)->rb_right;
+		else
+			return false;
+	}
+
+	rb_link_node(&this->rb, parent, new);
+	rb_insert_augmented(&this->rb, root, &augment_callbacks);
+	return true;
+}
+
+/**
+ * drbd_contains_interval  -  check if a tree contains a given interval
+ * @sector:	start sector of @interval
+ * @interval:	may not be a valid pointer
+ *
+ * Returns if the tree contains the node @interval with start sector @start.
+ * Does not dereference @interval until @interval is known to be a valid object
+ * in @tree.  Returns %false if @interval is in the tree but with a different
+ * sector number.
+ */
+bool
+drbd_contains_interval(struct rb_root *root, sector_t sector,
+		       struct drbd_interval *interval)
+{
+	struct rb_node *node = root->rb_node;
+
+	while (node) {
+		struct drbd_interval *here =
+			rb_entry(node, struct drbd_interval, rb);
+
+		if (sector < here->sector)
+			node = node->rb_left;
+		else if (sector > here->sector)
+			node = node->rb_right;
+		else if (interval < here)
+			node = node->rb_left;
+		else if (interval > here)
+			node = node->rb_right;
+		else
+			return true;
+	}
+	return false;
+}
+
+/**
+ * drbd_remove_interval  -  remove an interval from a tree
+ */
+void
+drbd_remove_interval(struct rb_root *root, struct drbd_interval *this)
+{
+	rb_erase_augmented(&this->rb, root, &augment_callbacks);
+}
+
+/**
+ * drbd_find_overlap  - search for an interval overlapping with [sector, sector + size)
+ * @sector:	start sector
+ * @size:	size, aligned to 512 bytes
+ *
+ * Returns an interval overlapping with [sector, sector + size), or NULL if
+ * there is none.  When there is more than one overlapping interval in the
+ * tree, the interval with the lowest start sector is returned, and all other
+ * overlapping intervals will be on the right side of the tree, reachable with
+ * rb_next().
+ */
+struct drbd_interval *
+drbd_find_overlap(struct rb_root *root, sector_t sector, unsigned int size)
+{
+	struct rb_node *node = root->rb_node;
+	struct drbd_interval *overlap = NULL;
+	sector_t end = sector + (size >> 9);
+
+	BUG_ON(!IS_ALIGNED(size, 512));
+
+	while (node) {
+		struct drbd_interval *here =
+			rb_entry(node, struct drbd_interval, rb);
+
+		if (node->rb_left &&
+		    sector < interval_end(node->rb_left)) {
+			/* Overlap if any must be on left side */
+			node = node->rb_left;
+		} else if (here->sector < end &&
+			   sector < here->sector + (here->size >> 9)) {
+			overlap = here;
+			break;
+		} else if (sector >= here->sector) {
+			/* Overlap if any must be on right side */
+			node = node->rb_right;
+		} else
+			break;
+	}
+	return overlap;
+}
+
+struct drbd_interval *
+drbd_next_overlap(struct drbd_interval *i, sector_t sector, unsigned int size)
+{
+	sector_t end = sector + (size >> 9);
+	struct rb_node *node;
+
+	for (;;) {
+		node = rb_next(&i->rb);
+		if (!node)
+			return NULL;
+		i = rb_entry(node, struct drbd_interval, rb);
+		if (i->sector >= end)
+			return NULL;
+		if (sector < i->sector + (i->size >> 9))
+			return i;
+	}
+}
diff --git a/drivers/block/drbd/drbd_interval.h b/drivers/block/drbd/drbd_interval.h
new file mode 100644
index 0000000..f38fcb0
--- /dev/null
+++ b/drivers/block/drbd/drbd_interval.h
@@ -0,0 +1,40 @@
+#ifndef __DRBD_INTERVAL_H
+#define __DRBD_INTERVAL_H
+
+#include <linux/types.h>
+#include <linux/rbtree.h>
+
+struct drbd_interval {
+	struct rb_node rb;
+	sector_t sector;	/* start sector of the interval */
+	unsigned int size;	/* size in bytes */
+	sector_t end;		/* highest interval end in subtree */
+	int local:1		/* local or remote request? */;
+	int waiting:1;
+};
+
+static inline void drbd_clear_interval(struct drbd_interval *i)
+{
+	RB_CLEAR_NODE(&i->rb);
+}
+
+static inline bool drbd_interval_empty(struct drbd_interval *i)
+{
+	return RB_EMPTY_NODE(&i->rb);
+}
+
+extern bool drbd_insert_interval(struct rb_root *, struct drbd_interval *);
+extern bool drbd_contains_interval(struct rb_root *, sector_t,
+				   struct drbd_interval *);
+extern void drbd_remove_interval(struct rb_root *, struct drbd_interval *);
+extern struct drbd_interval *drbd_find_overlap(struct rb_root *, sector_t,
+					unsigned int);
+extern struct drbd_interval *drbd_next_overlap(struct drbd_interval *, sector_t,
+					unsigned int);
+
+#define drbd_for_each_overlap(i, root, sector, size)		\
+	for (i = drbd_find_overlap(root, sector, size);		\
+	     i;							\
+	     i = drbd_next_overlap(i, sector, size))
+
+#endif  /* __DRBD_INTERVAL_H */
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index f55683a..52de26d 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -56,14 +56,6 @@
 
 #include "drbd_vli.h"
 
-struct after_state_chg_work {
-	struct drbd_work w;
-	union drbd_state os;
-	union drbd_state ns;
-	enum chg_state_flags flags;
-	struct completion *done;
-};
-
 static DEFINE_MUTEX(drbd_main_mutex);
 int drbdd_init(struct drbd_thread *);
 int drbd_worker(struct drbd_thread *);
@@ -72,21 +64,17 @@ int drbd_asender(struct drbd_thread *);
 int drbd_init(void);
 static int drbd_open(struct block_device *bdev, fmode_t mode);
 static int drbd_release(struct gendisk *gd, fmode_t mode);
-static int w_after_state_ch(struct drbd_conf *mdev, struct drbd_work *w, int unused);
-static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
-			   union drbd_state ns, enum chg_state_flags flags);
-static int w_md_sync(struct drbd_conf *mdev, struct drbd_work *w, int unused);
+static int w_md_sync(struct drbd_work *w, int unused);
 static void md_sync_timer_fn(unsigned long data);
-static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused);
-static int w_go_diskless(struct drbd_conf *mdev, struct drbd_work *w, int unused);
-static void _tl_clear(struct drbd_conf *mdev);
+static int w_bitmap_io(struct drbd_work *w, int unused);
+static int w_go_diskless(struct drbd_work *w, int unused);
 
 MODULE_AUTHOR("Philipp Reisner <phil@linbit.com>, "
 	      "Lars Ellenberg <lars@linbit.com>");
 MODULE_DESCRIPTION("drbd - Distributed Replicated Block Device v" REL_VERSION);
 MODULE_VERSION(REL_VERSION);
 MODULE_LICENSE("GPL");
-MODULE_PARM_DESC(minor_count, "Maximum number of drbd devices ("
+MODULE_PARM_DESC(minor_count, "Approximate number of drbd devices ("
 		 __stringify(DRBD_MINOR_COUNT_MIN) "-" __stringify(DRBD_MINOR_COUNT_MAX) ")");
 MODULE_ALIAS_BLOCKDEV_MAJOR(DRBD_MAJOR);
 
@@ -98,7 +86,6 @@ MODULE_PARM_DESC(allow_oos, "DONT USE!");
 module_param(minor_count, uint, 0444);
 module_param(disable_sendpage, bool, 0644);
 module_param(allow_oos, bool, 0);
-module_param(cn_idx, uint, 0444);
 module_param(proc_details, int, 0644);
 
 #ifdef CONFIG_DRBD_FAULT_INJECTION
@@ -120,7 +107,6 @@ module_param(fault_devs, int, 0644);
 unsigned int minor_count = DRBD_MINOR_COUNT_DEF;
 bool disable_sendpage;
 bool allow_oos;
-unsigned int cn_idx = CN_IDX_DRBD;
 int proc_details;       /* Detail level in proc drbd*/
 
 /* Module parameter for setting the user mode helper program
@@ -132,10 +118,11 @@ module_param_string(usermode_helper, usermode_helper, sizeof(usermode_helper), 0
 /* in 2.6.x, our device mapping and config info contains our virtual gendisks
  * as member "struct gendisk *vdisk;"
  */
-struct drbd_conf **minor_table;
+struct idr minors;
+struct list_head drbd_tconns;  /* list of struct drbd_tconn */
 
 struct kmem_cache *drbd_request_cache;
-struct kmem_cache *drbd_ee_cache;	/* epoch entries */
+struct kmem_cache *drbd_ee_cache;	/* peer requests */
 struct kmem_cache *drbd_bm_ext_cache;	/* bitmap extents */
 struct kmem_cache *drbd_al_ext_cache;	/* activity log extents */
 mempool_t *drbd_request_mempool;
@@ -164,10 +151,15 @@ static const struct block_device_operations drbd_ops = {
 
 struct bio *bio_alloc_drbd(gfp_t gfp_mask)
 {
+	struct bio *bio;
+
 	if (!drbd_md_io_bio_set)
 		return bio_alloc(gfp_mask, 1);
 
-	return bio_alloc_bioset(gfp_mask, 1, drbd_md_io_bio_set);
+	bio = bio_alloc_bioset(gfp_mask, 1, drbd_md_io_bio_set);
+	if (!bio)
+		return NULL;
+	return bio;
 }
 
 #ifdef __CHECKER__
@@ -184,1676 +176,264 @@ int _get_ldev_if_state(struct drbd_conf *mdev, enum drbd_disk_state mins)
 		if (atomic_dec_and_test(&mdev->local_cnt))
 			wake_up(&mdev->misc_wait);
 	}
-	return io_allowed;
-}
-
-#endif
-
-/**
- * DOC: The transfer log
- *
- * The transfer log is a single linked list of &struct drbd_tl_epoch objects.
- * mdev->newest_tle points to the head, mdev->oldest_tle points to the tail
- * of the list. There is always at least one &struct drbd_tl_epoch object.
- *
- * Each &struct drbd_tl_epoch has a circular double linked list of requests
- * attached.
- */
-static int tl_init(struct drbd_conf *mdev)
-{
-	struct drbd_tl_epoch *b;
-
-	/* during device minor initialization, we may well use GFP_KERNEL */
-	b = kmalloc(sizeof(struct drbd_tl_epoch), GFP_KERNEL);
-	if (!b)
-		return 0;
-	INIT_LIST_HEAD(&b->requests);
-	INIT_LIST_HEAD(&b->w.list);
-	b->next = NULL;
-	b->br_number = 4711;
-	b->n_writes = 0;
-	b->w.cb = NULL; /* if this is != NULL, we need to dec_ap_pending in tl_clear */
-
-	mdev->oldest_tle = b;
-	mdev->newest_tle = b;
-	INIT_LIST_HEAD(&mdev->out_of_sequence_requests);
-	INIT_LIST_HEAD(&mdev->barrier_acked_requests);
-
-	mdev->tl_hash = NULL;
-	mdev->tl_hash_s = 0;
-
-	return 1;
-}
-
-static void tl_cleanup(struct drbd_conf *mdev)
-{
-	D_ASSERT(mdev->oldest_tle == mdev->newest_tle);
-	D_ASSERT(list_empty(&mdev->out_of_sequence_requests));
-	kfree(mdev->oldest_tle);
-	mdev->oldest_tle = NULL;
-	kfree(mdev->unused_spare_tle);
-	mdev->unused_spare_tle = NULL;
-	kfree(mdev->tl_hash);
-	mdev->tl_hash = NULL;
-	mdev->tl_hash_s = 0;
-}
-
-/**
- * _tl_add_barrier() - Adds a barrier to the transfer log
- * @mdev:	DRBD device.
- * @new:	Barrier to be added before the current head of the TL.
- *
- * The caller must hold the req_lock.
- */
-void _tl_add_barrier(struct drbd_conf *mdev, struct drbd_tl_epoch *new)
-{
-	struct drbd_tl_epoch *newest_before;
-
-	INIT_LIST_HEAD(&new->requests);
-	INIT_LIST_HEAD(&new->w.list);
-	new->w.cb = NULL; /* if this is != NULL, we need to dec_ap_pending in tl_clear */
-	new->next = NULL;
-	new->n_writes = 0;
-
-	newest_before = mdev->newest_tle;
-	new->br_number = newest_before->br_number+1;
-	if (mdev->newest_tle != new) {
-		mdev->newest_tle->next = new;
-		mdev->newest_tle = new;
-	}
-}
-
-/**
- * tl_release() - Free or recycle the oldest &struct drbd_tl_epoch object of the TL
- * @mdev:	DRBD device.
- * @barrier_nr:	Expected identifier of the DRBD write barrier packet.
- * @set_size:	Expected number of requests before that barrier.
- *
- * In case the passed barrier_nr or set_size does not match the oldest
- * &struct drbd_tl_epoch objects this function will cause a termination
- * of the connection.
- */
-void tl_release(struct drbd_conf *mdev, unsigned int barrier_nr,
-		       unsigned int set_size)
-{
-	struct drbd_tl_epoch *b, *nob; /* next old barrier */
-	struct list_head *le, *tle;
-	struct drbd_request *r;
-
-	spin_lock_irq(&mdev->req_lock);
-
-	b = mdev->oldest_tle;
-
-	/* first some paranoia code */
-	if (b == NULL) {
-		dev_err(DEV, "BAD! BarrierAck #%u received, but no epoch in tl!?\n",
-			barrier_nr);
-		goto bail;
-	}
-	if (b->br_number != barrier_nr) {
-		dev_err(DEV, "BAD! BarrierAck #%u received, expected #%u!\n",
-			barrier_nr, b->br_number);
-		goto bail;
-	}
-	if (b->n_writes != set_size) {
-		dev_err(DEV, "BAD! BarrierAck #%u received with n_writes=%u, expected n_writes=%u!\n",
-			barrier_nr, set_size, b->n_writes);
-		goto bail;
-	}
-
-	/* Clean up list of requests processed during current epoch */
-	list_for_each_safe(le, tle, &b->requests) {
-		r = list_entry(le, struct drbd_request, tl_requests);
-		_req_mod(r, barrier_acked);
-	}
-	/* There could be requests on the list waiting for completion
-	   of the write to the local disk. To avoid corruptions of
-	   slab's data structures we have to remove the lists head.
-
-	   Also there could have been a barrier ack out of sequence, overtaking
-	   the write acks - which would be a bug and violating write ordering.
-	   To not deadlock in case we lose connection while such requests are
-	   still pending, we need some way to find them for the
-	   _req_mode(connection_lost_while_pending).
-
-	   These have been list_move'd to the out_of_sequence_requests list in
-	   _req_mod(, barrier_acked) above.
-	   */
-	list_splice_init(&b->requests, &mdev->barrier_acked_requests);
-
-	nob = b->next;
-	if (test_and_clear_bit(CREATE_BARRIER, &mdev->flags)) {
-		_tl_add_barrier(mdev, b);
-		if (nob)
-			mdev->oldest_tle = nob;
-		/* if nob == NULL b was the only barrier, and becomes the new
-		   barrier. Therefore mdev->oldest_tle points already to b */
-	} else {
-		D_ASSERT(nob != NULL);
-		mdev->oldest_tle = nob;
-		kfree(b);
-	}
-
-	spin_unlock_irq(&mdev->req_lock);
-	dec_ap_pending(mdev);
-
-	return;
-
-bail:
-	spin_unlock_irq(&mdev->req_lock);
-	drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
-}
-
-
-/**
- * _tl_restart() - Walks the transfer log, and applies an action to all requests
- * @mdev:	DRBD device.
- * @what:       The action/event to perform with all request objects
- *
- * @what might be one of connection_lost_while_pending, resend, fail_frozen_disk_io,
- * restart_frozen_disk_io.
- */
-static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what)
-{
-	struct drbd_tl_epoch *b, *tmp, **pn;
-	struct list_head *le, *tle, carry_reads;
-	struct drbd_request *req;
-	int rv, n_writes, n_reads;
-
-	b = mdev->oldest_tle;
-	pn = &mdev->oldest_tle;
-	while (b) {
-		n_writes = 0;
-		n_reads = 0;
-		INIT_LIST_HEAD(&carry_reads);
-		list_for_each_safe(le, tle, &b->requests) {
-			req = list_entry(le, struct drbd_request, tl_requests);
-			rv = _req_mod(req, what);
-
-			n_writes += (rv & MR_WRITE) >> MR_WRITE_SHIFT;
-			n_reads  += (rv & MR_READ) >> MR_READ_SHIFT;
-		}
-		tmp = b->next;
-
-		if (n_writes) {
-			if (what == resend) {
-				b->n_writes = n_writes;
-				if (b->w.cb == NULL) {
-					b->w.cb = w_send_barrier;
-					inc_ap_pending(mdev);
-					set_bit(CREATE_BARRIER, &mdev->flags);
-				}
-
-				drbd_queue_work(&mdev->data.work, &b->w);
-			}
-			pn = &b->next;
-		} else {
-			if (n_reads)
-				list_add(&carry_reads, &b->requests);
-			/* there could still be requests on that ring list,
-			 * in case local io is still pending */
-			list_del(&b->requests);
-
-			/* dec_ap_pending corresponding to queue_barrier.
-			 * the newest barrier may not have been queued yet,
-			 * in which case w.cb is still NULL. */
-			if (b->w.cb != NULL)
-				dec_ap_pending(mdev);
-
-			if (b == mdev->newest_tle) {
-				/* recycle, but reinit! */
-				D_ASSERT(tmp == NULL);
-				INIT_LIST_HEAD(&b->requests);
-				list_splice(&carry_reads, &b->requests);
-				INIT_LIST_HEAD(&b->w.list);
-				b->w.cb = NULL;
-				b->br_number = net_random();
-				b->n_writes = 0;
-
-				*pn = b;
-				break;
-			}
-			*pn = tmp;
-			kfree(b);
-		}
-		b = tmp;
-		list_splice(&carry_reads, &b->requests);
-	}
-
-	/* Actions operating on the disk state, also want to work on
-	   requests that got barrier acked. */
-
-	list_for_each_safe(le, tle, &mdev->barrier_acked_requests) {
-		req = list_entry(le, struct drbd_request, tl_requests);
-		_req_mod(req, what);
-	}
-}
-
-
-/**
- * tl_clear() - Clears all requests and &struct drbd_tl_epoch objects out of the TL
- * @mdev:	DRBD device.
- *
- * This is called after the connection to the peer was lost. The storage covered
- * by the requests on the transfer gets marked as our of sync. Called from the
- * receiver thread and the worker thread.
- */
-void tl_clear(struct drbd_conf *mdev)
-{
-	spin_lock_irq(&mdev->req_lock);
-	_tl_clear(mdev);
-	spin_unlock_irq(&mdev->req_lock);
-}
-
-static void _tl_clear(struct drbd_conf *mdev)
-{
-	struct list_head *le, *tle;
-	struct drbd_request *r;
-
-	_tl_restart(mdev, connection_lost_while_pending);
-
-	/* we expect this list to be empty. */
-	D_ASSERT(list_empty(&mdev->out_of_sequence_requests));
-
-	/* but just in case, clean it up anyways! */
-	list_for_each_safe(le, tle, &mdev->out_of_sequence_requests) {
-		r = list_entry(le, struct drbd_request, tl_requests);
-		/* It would be nice to complete outside of spinlock.
-		 * But this is easier for now. */
-		_req_mod(r, connection_lost_while_pending);
-	}
-
-	/* ensure bit indicating barrier is required is clear */
-	clear_bit(CREATE_BARRIER, &mdev->flags);
-
-	memset(mdev->app_reads_hash, 0, APP_R_HSIZE*sizeof(void *));
-
-}
-
-void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what)
-{
-	spin_lock_irq(&mdev->req_lock);
-	_tl_restart(mdev, what);
-	spin_unlock_irq(&mdev->req_lock);
-}
-
-/**
- * tl_abort_disk_io() - Abort disk I/O for all requests for a certain mdev in the TL
- * @mdev:	DRBD device.
- */
-void tl_abort_disk_io(struct drbd_conf *mdev)
-{
-	struct drbd_tl_epoch *b;
-	struct list_head *le, *tle;
-	struct drbd_request *req;
-
-	spin_lock_irq(&mdev->req_lock);
-	b = mdev->oldest_tle;
-	while (b) {
-		list_for_each_safe(le, tle, &b->requests) {
-			req = list_entry(le, struct drbd_request, tl_requests);
-			if (!(req->rq_state & RQ_LOCAL_PENDING))
-				continue;
-			_req_mod(req, abort_disk_io);
-		}
-		b = b->next;
-	}
-
-	list_for_each_safe(le, tle, &mdev->barrier_acked_requests) {
-		req = list_entry(le, struct drbd_request, tl_requests);
-		if (!(req->rq_state & RQ_LOCAL_PENDING))
-			continue;
-		_req_mod(req, abort_disk_io);
-	}
-
-	spin_unlock_irq(&mdev->req_lock);
-}
-
-/**
- * cl_wide_st_chg() - true if the state change is a cluster wide one
- * @mdev:	DRBD device.
- * @os:		old (current) state.
- * @ns:		new (wanted) state.
- */
-static int cl_wide_st_chg(struct drbd_conf *mdev,
-			  union drbd_state os, union drbd_state ns)
-{
-	return (os.conn >= C_CONNECTED && ns.conn >= C_CONNECTED &&
-		 ((os.role != R_PRIMARY && ns.role == R_PRIMARY) ||
-		  (os.conn != C_STARTING_SYNC_T && ns.conn == C_STARTING_SYNC_T) ||
-		  (os.conn != C_STARTING_SYNC_S && ns.conn == C_STARTING_SYNC_S) ||
-		  (os.disk != D_FAILED && ns.disk == D_FAILED))) ||
-		(os.conn >= C_CONNECTED && ns.conn == C_DISCONNECTING) ||
-		(os.conn == C_CONNECTED && ns.conn == C_VERIFY_S);
-}
-
-enum drbd_state_rv
-drbd_change_state(struct drbd_conf *mdev, enum chg_state_flags f,
-		  union drbd_state mask, union drbd_state val)
-{
-	unsigned long flags;
-	union drbd_state os, ns;
-	enum drbd_state_rv rv;
-
-	spin_lock_irqsave(&mdev->req_lock, flags);
-	os = mdev->state;
-	ns.i = (os.i & ~mask.i) | val.i;
-	rv = _drbd_set_state(mdev, ns, f, NULL);
-	ns = mdev->state;
-	spin_unlock_irqrestore(&mdev->req_lock, flags);
-
-	return rv;
-}
-
-/**
- * drbd_force_state() - Impose a change which happens outside our control on our state
- * @mdev:	DRBD device.
- * @mask:	mask of state bits to change.
- * @val:	value of new state bits.
- */
-void drbd_force_state(struct drbd_conf *mdev,
-	union drbd_state mask, union drbd_state val)
-{
-	drbd_change_state(mdev, CS_HARD, mask, val);
-}
-
-static enum drbd_state_rv is_valid_state(struct drbd_conf *, union drbd_state);
-static enum drbd_state_rv is_valid_state_transition(struct drbd_conf *,
-						    union drbd_state,
-						    union drbd_state);
-enum sanitize_state_warnings {
-	NO_WARNING,
-	ABORTED_ONLINE_VERIFY,
-	ABORTED_RESYNC,
-	CONNECTION_LOST_NEGOTIATING,
-	IMPLICITLY_UPGRADED_DISK,
-	IMPLICITLY_UPGRADED_PDSK,
-};
-static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state os,
-				       union drbd_state ns, enum sanitize_state_warnings *warn);
-int drbd_send_state_req(struct drbd_conf *,
-			union drbd_state, union drbd_state);
-
-static enum drbd_state_rv
-_req_st_cond(struct drbd_conf *mdev, union drbd_state mask,
-	     union drbd_state val)
-{
-	union drbd_state os, ns;
-	unsigned long flags;
-	enum drbd_state_rv rv;
-
-	if (test_and_clear_bit(CL_ST_CHG_SUCCESS, &mdev->flags))
-		return SS_CW_SUCCESS;
-
-	if (test_and_clear_bit(CL_ST_CHG_FAIL, &mdev->flags))
-		return SS_CW_FAILED_BY_PEER;
-
-	rv = 0;
-	spin_lock_irqsave(&mdev->req_lock, flags);
-	os = mdev->state;
-	ns.i = (os.i & ~mask.i) | val.i;
-	ns = sanitize_state(mdev, os, ns, NULL);
-
-	if (!cl_wide_st_chg(mdev, os, ns))
-		rv = SS_CW_NO_NEED;
-	if (!rv) {
-		rv = is_valid_state(mdev, ns);
-		if (rv == SS_SUCCESS) {
-			rv = is_valid_state_transition(mdev, ns, os);
-			if (rv == SS_SUCCESS)
-				rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */
-		}
-	}
-	spin_unlock_irqrestore(&mdev->req_lock, flags);
-
-	return rv;
-}
-
-/**
- * drbd_req_state() - Perform an eventually cluster wide state change
- * @mdev:	DRBD device.
- * @mask:	mask of state bits to change.
- * @val:	value of new state bits.
- * @f:		flags
- *
- * Should not be called directly, use drbd_request_state() or
- * _drbd_request_state().
- */
-static enum drbd_state_rv
-drbd_req_state(struct drbd_conf *mdev, union drbd_state mask,
-	       union drbd_state val, enum chg_state_flags f)
-{
-	struct completion done;
-	unsigned long flags;
-	union drbd_state os, ns;
-	enum drbd_state_rv rv;
-
-	init_completion(&done);
-
-	if (f & CS_SERIALIZE)
-		mutex_lock(&mdev->state_mutex);
-
-	spin_lock_irqsave(&mdev->req_lock, flags);
-	os = mdev->state;
-	ns.i = (os.i & ~mask.i) | val.i;
-	ns = sanitize_state(mdev, os, ns, NULL);
-
-	if (cl_wide_st_chg(mdev, os, ns)) {
-		rv = is_valid_state(mdev, ns);
-		if (rv == SS_SUCCESS)
-			rv = is_valid_state_transition(mdev, ns, os);
-		spin_unlock_irqrestore(&mdev->req_lock, flags);
-
-		if (rv < SS_SUCCESS) {
-			if (f & CS_VERBOSE)
-				print_st_err(mdev, os, ns, rv);
-			goto abort;
-		}
-
-		drbd_state_lock(mdev);
-		if (!drbd_send_state_req(mdev, mask, val)) {
-			drbd_state_unlock(mdev);
-			rv = SS_CW_FAILED_BY_PEER;
-			if (f & CS_VERBOSE)
-				print_st_err(mdev, os, ns, rv);
-			goto abort;
-		}
-
-		wait_event(mdev->state_wait,
-			(rv = _req_st_cond(mdev, mask, val)));
-
-		if (rv < SS_SUCCESS) {
-			drbd_state_unlock(mdev);
-			if (f & CS_VERBOSE)
-				print_st_err(mdev, os, ns, rv);
-			goto abort;
-		}
-		spin_lock_irqsave(&mdev->req_lock, flags);
-		os = mdev->state;
-		ns.i = (os.i & ~mask.i) | val.i;
-		rv = _drbd_set_state(mdev, ns, f, &done);
-		drbd_state_unlock(mdev);
-	} else {
-		rv = _drbd_set_state(mdev, ns, f, &done);
-	}
-
-	spin_unlock_irqrestore(&mdev->req_lock, flags);
-
-	if (f & CS_WAIT_COMPLETE && rv == SS_SUCCESS) {
-		D_ASSERT(current != mdev->worker.task);
-		wait_for_completion(&done);
-	}
-
-abort:
-	if (f & CS_SERIALIZE)
-		mutex_unlock(&mdev->state_mutex);
-
-	return rv;
-}
-
-/**
- * _drbd_request_state() - Request a state change (with flags)
- * @mdev:	DRBD device.
- * @mask:	mask of state bits to change.
- * @val:	value of new state bits.
- * @f:		flags
- *
- * Cousin of drbd_request_state(), useful with the CS_WAIT_COMPLETE
- * flag, or when logging of failed state change requests is not desired.
- */
-enum drbd_state_rv
-_drbd_request_state(struct drbd_conf *mdev, union drbd_state mask,
-		    union drbd_state val, enum chg_state_flags f)
-{
-	enum drbd_state_rv rv;
-
-	wait_event(mdev->state_wait,
-		   (rv = drbd_req_state(mdev, mask, val, f)) != SS_IN_TRANSIENT_STATE);
-
-	return rv;
-}
-
-static void print_st(struct drbd_conf *mdev, char *name, union drbd_state ns)
-{
-	dev_err(DEV, " %s = { cs:%s ro:%s/%s ds:%s/%s %c%c%c%c }\n",
-	    name,
-	    drbd_conn_str(ns.conn),
-	    drbd_role_str(ns.role),
-	    drbd_role_str(ns.peer),
-	    drbd_disk_str(ns.disk),
-	    drbd_disk_str(ns.pdsk),
-	    is_susp(ns) ? 's' : 'r',
-	    ns.aftr_isp ? 'a' : '-',
-	    ns.peer_isp ? 'p' : '-',
-	    ns.user_isp ? 'u' : '-'
-	    );
-}
-
-void print_st_err(struct drbd_conf *mdev, union drbd_state os,
-	          union drbd_state ns, enum drbd_state_rv err)
-{
-	if (err == SS_IN_TRANSIENT_STATE)
-		return;
-	dev_err(DEV, "State change failed: %s\n", drbd_set_st_err_str(err));
-	print_st(mdev, " state", os);
-	print_st(mdev, "wanted", ns);
-}
-
-
-/**
- * is_valid_state() - Returns an SS_ error code if ns is not valid
- * @mdev:	DRBD device.
- * @ns:		State to consider.
- */
-static enum drbd_state_rv
-is_valid_state(struct drbd_conf *mdev, union drbd_state ns)
-{
-	/* See drbd_state_sw_errors in drbd_strings.c */
-
-	enum drbd_fencing_p fp;
-	enum drbd_state_rv rv = SS_SUCCESS;
-
-	fp = FP_DONT_CARE;
-	if (get_ldev(mdev)) {
-		fp = mdev->ldev->dc.fencing;
-		put_ldev(mdev);
-	}
-
-	if (get_net_conf(mdev)) {
-		if (!mdev->net_conf->two_primaries &&
-		    ns.role == R_PRIMARY && ns.peer == R_PRIMARY)
-			rv = SS_TWO_PRIMARIES;
-		put_net_conf(mdev);
-	}
-
-	if (rv <= 0)
-		/* already found a reason to abort */;
-	else if (ns.role == R_SECONDARY && mdev->open_cnt)
-		rv = SS_DEVICE_IN_USE;
-
-	else if (ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.disk < D_UP_TO_DATE)
-		rv = SS_NO_UP_TO_DATE_DISK;
-
-	else if (fp >= FP_RESOURCE &&
-		 ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.pdsk >= D_UNKNOWN)
-		rv = SS_PRIMARY_NOP;
-
-	else if (ns.role == R_PRIMARY && ns.disk <= D_INCONSISTENT && ns.pdsk <= D_INCONSISTENT)
-		rv = SS_NO_UP_TO_DATE_DISK;
-
-	else if (ns.conn > C_CONNECTED && ns.disk < D_INCONSISTENT)
-		rv = SS_NO_LOCAL_DISK;
-
-	else if (ns.conn > C_CONNECTED && ns.pdsk < D_INCONSISTENT)
-		rv = SS_NO_REMOTE_DISK;
-
-	else if (ns.conn > C_CONNECTED && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE)
-		rv = SS_NO_UP_TO_DATE_DISK;
-
-	else if ((ns.conn == C_CONNECTED ||
-		  ns.conn == C_WF_BITMAP_S ||
-		  ns.conn == C_SYNC_SOURCE ||
-		  ns.conn == C_PAUSED_SYNC_S) &&
-		  ns.disk == D_OUTDATED)
-		rv = SS_CONNECTED_OUTDATES;
-
-	else if ((ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) &&
-		 (mdev->sync_conf.verify_alg[0] == 0))
-		rv = SS_NO_VERIFY_ALG;
-
-	else if ((ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) &&
-		  mdev->agreed_pro_version < 88)
-		rv = SS_NOT_SUPPORTED;
-
-	else if (ns.conn >= C_CONNECTED && ns.pdsk == D_UNKNOWN)
-		rv = SS_CONNECTED_OUTDATES;
-
-	return rv;
-}
-
-/**
- * is_valid_state_transition() - Returns an SS_ error code if the state transition is not possible
- * @mdev:	DRBD device.
- * @ns:		new state.
- * @os:		old state.
- */
-static enum drbd_state_rv
-is_valid_state_transition(struct drbd_conf *mdev, union drbd_state ns,
-			  union drbd_state os)
-{
-	enum drbd_state_rv rv = SS_SUCCESS;
-
-	if ((ns.conn == C_STARTING_SYNC_T || ns.conn == C_STARTING_SYNC_S) &&
-	    os.conn > C_CONNECTED)
-		rv = SS_RESYNC_RUNNING;
-
-	if (ns.conn == C_DISCONNECTING && os.conn == C_STANDALONE)
-		rv = SS_ALREADY_STANDALONE;
-
-	if (ns.disk > D_ATTACHING && os.disk == D_DISKLESS)
-		rv = SS_IS_DISKLESS;
-
-	if (ns.conn == C_WF_CONNECTION && os.conn < C_UNCONNECTED)
-		rv = SS_NO_NET_CONFIG;
-
-	if (ns.disk == D_OUTDATED && os.disk < D_OUTDATED && os.disk != D_ATTACHING)
-		rv = SS_LOWER_THAN_OUTDATED;
-
-	if (ns.conn == C_DISCONNECTING && os.conn == C_UNCONNECTED)
-		rv = SS_IN_TRANSIENT_STATE;
-
-	if (ns.conn == os.conn && ns.conn == C_WF_REPORT_PARAMS)
-		rv = SS_IN_TRANSIENT_STATE;
-
-	/* While establishing a connection only allow cstate to change.
-	   Delay/refuse role changes, detach attach etc... */
-	if (test_bit(STATE_SENT, &mdev->flags) &&
-	    !(os.conn == C_WF_REPORT_PARAMS ||
-	      (ns.conn == C_WF_REPORT_PARAMS && os.conn == C_WF_CONNECTION)))
-		rv = SS_IN_TRANSIENT_STATE;
-
-	if ((ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) && os.conn < C_CONNECTED)
-		rv = SS_NEED_CONNECTION;
-
-	if ((ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) &&
-	    ns.conn != os.conn && os.conn > C_CONNECTED)
-		rv = SS_RESYNC_RUNNING;
-
-	if ((ns.conn == C_STARTING_SYNC_S || ns.conn == C_STARTING_SYNC_T) &&
-	    os.conn < C_CONNECTED)
-		rv = SS_NEED_CONNECTION;
-
-	if ((ns.conn == C_SYNC_TARGET || ns.conn == C_SYNC_SOURCE)
-	    && os.conn < C_WF_REPORT_PARAMS)
-		rv = SS_NEED_CONNECTION; /* No NetworkFailure -> SyncTarget etc... */
-
-	return rv;
-}
-
-static void print_sanitize_warnings(struct drbd_conf *mdev, enum sanitize_state_warnings warn)
-{
-	static const char *msg_table[] = {
-		[NO_WARNING] = "",
-		[ABORTED_ONLINE_VERIFY] = "Online-verify aborted.",
-		[ABORTED_RESYNC] = "Resync aborted.",
-		[CONNECTION_LOST_NEGOTIATING] = "Connection lost while negotiating, no data!",
-		[IMPLICITLY_UPGRADED_DISK] = "Implicitly upgraded disk",
-		[IMPLICITLY_UPGRADED_PDSK] = "Implicitly upgraded pdsk",
-	};
-
-	if (warn != NO_WARNING)
-		dev_warn(DEV, "%s\n", msg_table[warn]);
-}
-
-/**
- * sanitize_state() - Resolves implicitly necessary additional changes to a state transition
- * @mdev:	DRBD device.
- * @os:		old state.
- * @ns:		new state.
- * @warn_sync_abort:
- *
- * When we loose connection, we have to set the state of the peers disk (pdsk)
- * to D_UNKNOWN. This rule and many more along those lines are in this function.
- */
-static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state os,
-				       union drbd_state ns, enum sanitize_state_warnings *warn)
-{
-	enum drbd_fencing_p fp;
-	enum drbd_disk_state disk_min, disk_max, pdsk_min, pdsk_max;
-
-	if (warn)
-		*warn = NO_WARNING;
-
-	fp = FP_DONT_CARE;
-	if (get_ldev(mdev)) {
-		fp = mdev->ldev->dc.fencing;
-		put_ldev(mdev);
-	}
-
-	/* Disallow Network errors to configure a device's network part */
-	if ((ns.conn >= C_TIMEOUT && ns.conn <= C_TEAR_DOWN) &&
-	    os.conn <= C_DISCONNECTING)
-		ns.conn = os.conn;
-
-	/* After a network error (+C_TEAR_DOWN) only C_UNCONNECTED or C_DISCONNECTING can follow.
-	 * If you try to go into some Sync* state, that shall fail (elsewhere). */
-	if (os.conn >= C_TIMEOUT && os.conn <= C_TEAR_DOWN &&
-	    ns.conn != C_UNCONNECTED && ns.conn != C_DISCONNECTING && ns.conn <= C_CONNECTED)
-		ns.conn = os.conn;
-
-	/* we cannot fail (again) if we already detached */
-	if (ns.disk == D_FAILED && os.disk == D_DISKLESS)
-		ns.disk = D_DISKLESS;
-
-	/* After C_DISCONNECTING only C_STANDALONE may follow */
-	if (os.conn == C_DISCONNECTING && ns.conn != C_STANDALONE)
-		ns.conn = os.conn;
-
-	if (ns.conn < C_CONNECTED) {
-		ns.peer_isp = 0;
-		ns.peer = R_UNKNOWN;
-		if (ns.pdsk > D_UNKNOWN || ns.pdsk < D_INCONSISTENT)
-			ns.pdsk = D_UNKNOWN;
-	}
-
-	/* Clear the aftr_isp when becoming unconfigured */
-	if (ns.conn == C_STANDALONE && ns.disk == D_DISKLESS && ns.role == R_SECONDARY)
-		ns.aftr_isp = 0;
-
-	/* Abort resync if a disk fails/detaches */
-	if (os.conn > C_CONNECTED && ns.conn > C_CONNECTED &&
-	    (ns.disk <= D_FAILED || ns.pdsk <= D_FAILED)) {
-		if (warn)
-			*warn =	os.conn == C_VERIFY_S || os.conn == C_VERIFY_T ?
-				ABORTED_ONLINE_VERIFY : ABORTED_RESYNC;
-		ns.conn = C_CONNECTED;
-	}
-
-	/* Connection breaks down before we finished "Negotiating" */
-	if (ns.conn < C_CONNECTED && ns.disk == D_NEGOTIATING &&
-	    get_ldev_if_state(mdev, D_NEGOTIATING)) {
-		if (mdev->ed_uuid == mdev->ldev->md.uuid[UI_CURRENT]) {
-			ns.disk = mdev->new_state_tmp.disk;
-			ns.pdsk = mdev->new_state_tmp.pdsk;
-		} else {
-			if (warn)
-				*warn = CONNECTION_LOST_NEGOTIATING;
-			ns.disk = D_DISKLESS;
-			ns.pdsk = D_UNKNOWN;
-		}
-		put_ldev(mdev);
-	}
-
-	/* D_CONSISTENT and D_OUTDATED vanish when we get connected */
-	if (ns.conn >= C_CONNECTED && ns.conn < C_AHEAD) {
-		if (ns.disk == D_CONSISTENT || ns.disk == D_OUTDATED)
-			ns.disk = D_UP_TO_DATE;
-		if (ns.pdsk == D_CONSISTENT || ns.pdsk == D_OUTDATED)
-			ns.pdsk = D_UP_TO_DATE;
-	}
-
-	/* Implications of the connection stat on the disk states */
-	disk_min = D_DISKLESS;
-	disk_max = D_UP_TO_DATE;
-	pdsk_min = D_INCONSISTENT;
-	pdsk_max = D_UNKNOWN;
-	switch ((enum drbd_conns)ns.conn) {
-	case C_WF_BITMAP_T:
-	case C_PAUSED_SYNC_T:
-	case C_STARTING_SYNC_T:
-	case C_WF_SYNC_UUID:
-	case C_BEHIND:
-		disk_min = D_INCONSISTENT;
-		disk_max = D_OUTDATED;
-		pdsk_min = D_UP_TO_DATE;
-		pdsk_max = D_UP_TO_DATE;
-		break;
-	case C_VERIFY_S:
-	case C_VERIFY_T:
-		disk_min = D_UP_TO_DATE;
-		disk_max = D_UP_TO_DATE;
-		pdsk_min = D_UP_TO_DATE;
-		pdsk_max = D_UP_TO_DATE;
-		break;
-	case C_CONNECTED:
-		disk_min = D_DISKLESS;
-		disk_max = D_UP_TO_DATE;
-		pdsk_min = D_DISKLESS;
-		pdsk_max = D_UP_TO_DATE;
-		break;
-	case C_WF_BITMAP_S:
-	case C_PAUSED_SYNC_S:
-	case C_STARTING_SYNC_S:
-	case C_AHEAD:
-		disk_min = D_UP_TO_DATE;
-		disk_max = D_UP_TO_DATE;
-		pdsk_min = D_INCONSISTENT;
-		pdsk_max = D_CONSISTENT; /* D_OUTDATED would be nice. But explicit outdate necessary*/
-		break;
-	case C_SYNC_TARGET:
-		disk_min = D_INCONSISTENT;
-		disk_max = D_INCONSISTENT;
-		pdsk_min = D_UP_TO_DATE;
-		pdsk_max = D_UP_TO_DATE;
-		break;
-	case C_SYNC_SOURCE:
-		disk_min = D_UP_TO_DATE;
-		disk_max = D_UP_TO_DATE;
-		pdsk_min = D_INCONSISTENT;
-		pdsk_max = D_INCONSISTENT;
-		break;
-	case C_STANDALONE:
-	case C_DISCONNECTING:
-	case C_UNCONNECTED:
-	case C_TIMEOUT:
-	case C_BROKEN_PIPE:
-	case C_NETWORK_FAILURE:
-	case C_PROTOCOL_ERROR:
-	case C_TEAR_DOWN:
-	case C_WF_CONNECTION:
-	case C_WF_REPORT_PARAMS:
-	case C_MASK:
-		break;
-	}
-	if (ns.disk > disk_max)
-		ns.disk = disk_max;
-
-	if (ns.disk < disk_min) {
-		if (warn)
-			*warn = IMPLICITLY_UPGRADED_DISK;
-		ns.disk = disk_min;
-	}
-	if (ns.pdsk > pdsk_max)
-		ns.pdsk = pdsk_max;
-
-	if (ns.pdsk < pdsk_min) {
-		if (warn)
-			*warn = IMPLICITLY_UPGRADED_PDSK;
-		ns.pdsk = pdsk_min;
-	}
-
-	if (fp == FP_STONITH &&
-	    (ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.pdsk > D_OUTDATED) &&
-	    !(os.role == R_PRIMARY && os.conn < C_CONNECTED && os.pdsk > D_OUTDATED))
-		ns.susp_fen = 1; /* Suspend IO while fence-peer handler runs (peer lost) */
-
-	if (mdev->sync_conf.on_no_data == OND_SUSPEND_IO &&
-	    (ns.role == R_PRIMARY && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE) &&
-	    !(os.role == R_PRIMARY && os.disk < D_UP_TO_DATE && os.pdsk < D_UP_TO_DATE))
-		ns.susp_nod = 1; /* Suspend IO while no data available (no accessible data available) */
-
-	if (ns.aftr_isp || ns.peer_isp || ns.user_isp) {
-		if (ns.conn == C_SYNC_SOURCE)
-			ns.conn = C_PAUSED_SYNC_S;
-		if (ns.conn == C_SYNC_TARGET)
-			ns.conn = C_PAUSED_SYNC_T;
-	} else {
-		if (ns.conn == C_PAUSED_SYNC_S)
-			ns.conn = C_SYNC_SOURCE;
-		if (ns.conn == C_PAUSED_SYNC_T)
-			ns.conn = C_SYNC_TARGET;
-	}
-
-	return ns;
-}
-
-/* helper for __drbd_set_state */
-static void set_ov_position(struct drbd_conf *mdev, enum drbd_conns cs)
-{
-	if (mdev->agreed_pro_version < 90)
-		mdev->ov_start_sector = 0;
-	mdev->rs_total = drbd_bm_bits(mdev);
-	mdev->ov_position = 0;
-	if (cs == C_VERIFY_T) {
-		/* starting online verify from an arbitrary position
-		 * does not fit well into the existing protocol.
-		 * on C_VERIFY_T, we initialize ov_left and friends
-		 * implicitly in receive_DataRequest once the
-		 * first P_OV_REQUEST is received */
-		mdev->ov_start_sector = ~(sector_t)0;
-	} else {
-		unsigned long bit = BM_SECT_TO_BIT(mdev->ov_start_sector);
-		if (bit >= mdev->rs_total) {
-			mdev->ov_start_sector =
-				BM_BIT_TO_SECT(mdev->rs_total - 1);
-			mdev->rs_total = 1;
-		} else
-			mdev->rs_total -= bit;
-		mdev->ov_position = mdev->ov_start_sector;
-	}
-	mdev->ov_left = mdev->rs_total;
-}
-
-static void drbd_resume_al(struct drbd_conf *mdev)
-{
-	if (test_and_clear_bit(AL_SUSPENDED, &mdev->flags))
-		dev_info(DEV, "Resumed AL updates\n");
-}
-
-/**
- * __drbd_set_state() - Set a new DRBD state
- * @mdev:	DRBD device.
- * @ns:		new state.
- * @flags:	Flags
- * @done:	Optional completion, that will get completed after the after_state_ch() finished
- *
- * Caller needs to hold req_lock, and global_state_lock. Do not call directly.
- */
-enum drbd_state_rv
-__drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
-	         enum chg_state_flags flags, struct completion *done)
-{
-	union drbd_state os;
-	enum drbd_state_rv rv = SS_SUCCESS;
-	enum sanitize_state_warnings ssw;
-	struct after_state_chg_work *ascw;
-
-	os = mdev->state;
-
-	ns = sanitize_state(mdev, os, ns, &ssw);
-
-	if (ns.i == os.i)
-		return SS_NOTHING_TO_DO;
-
-	if (!(flags & CS_HARD)) {
-		/*  pre-state-change checks ; only look at ns  */
-		/* See drbd_state_sw_errors in drbd_strings.c */
-
-		rv = is_valid_state(mdev, ns);
-		if (rv < SS_SUCCESS) {
-			/* If the old state was illegal as well, then let
-			   this happen...*/
-
-			if (is_valid_state(mdev, os) == rv)
-				rv = is_valid_state_transition(mdev, ns, os);
-		} else
-			rv = is_valid_state_transition(mdev, ns, os);
-	}
-
-	if (rv < SS_SUCCESS) {
-		if (flags & CS_VERBOSE)
-			print_st_err(mdev, os, ns, rv);
-		return rv;
-	}
-
-	print_sanitize_warnings(mdev, ssw);
-
-	{
-	char *pbp, pb[300];
-	pbp = pb;
-	*pbp = 0;
-	if (ns.role != os.role)
-		pbp += sprintf(pbp, "role( %s -> %s ) ",
-			       drbd_role_str(os.role),
-			       drbd_role_str(ns.role));
-	if (ns.peer != os.peer)
-		pbp += sprintf(pbp, "peer( %s -> %s ) ",
-			       drbd_role_str(os.peer),
-			       drbd_role_str(ns.peer));
-	if (ns.conn != os.conn)
-		pbp += sprintf(pbp, "conn( %s -> %s ) ",
-			       drbd_conn_str(os.conn),
-			       drbd_conn_str(ns.conn));
-	if (ns.disk != os.disk)
-		pbp += sprintf(pbp, "disk( %s -> %s ) ",
-			       drbd_disk_str(os.disk),
-			       drbd_disk_str(ns.disk));
-	if (ns.pdsk != os.pdsk)
-		pbp += sprintf(pbp, "pdsk( %s -> %s ) ",
-			       drbd_disk_str(os.pdsk),
-			       drbd_disk_str(ns.pdsk));
-	if (is_susp(ns) != is_susp(os))
-		pbp += sprintf(pbp, "susp( %d -> %d ) ",
-			       is_susp(os),
-			       is_susp(ns));
-	if (ns.aftr_isp != os.aftr_isp)
-		pbp += sprintf(pbp, "aftr_isp( %d -> %d ) ",
-			       os.aftr_isp,
-			       ns.aftr_isp);
-	if (ns.peer_isp != os.peer_isp)
-		pbp += sprintf(pbp, "peer_isp( %d -> %d ) ",
-			       os.peer_isp,
-			       ns.peer_isp);
-	if (ns.user_isp != os.user_isp)
-		pbp += sprintf(pbp, "user_isp( %d -> %d ) ",
-			       os.user_isp,
-			       ns.user_isp);
-	dev_info(DEV, "%s\n", pb);
-	}
-
-	/* solve the race between becoming unconfigured,
-	 * worker doing the cleanup, and
-	 * admin reconfiguring us:
-	 * on (re)configure, first set CONFIG_PENDING,
-	 * then wait for a potentially exiting worker,
-	 * start the worker, and schedule one no_op.
-	 * then proceed with configuration.
-	 */
-	if (ns.disk == D_DISKLESS &&
-	    ns.conn == C_STANDALONE &&
-	    ns.role == R_SECONDARY &&
-	    !test_and_set_bit(CONFIG_PENDING, &mdev->flags))
-		set_bit(DEVICE_DYING, &mdev->flags);
-
-	/* if we are going -> D_FAILED or D_DISKLESS, grab one extra reference
-	 * on the ldev here, to be sure the transition -> D_DISKLESS resp.
-	 * drbd_ldev_destroy() won't happen before our corresponding
-	 * after_state_ch works run, where we put_ldev again. */
-	if ((os.disk != D_FAILED && ns.disk == D_FAILED) ||
-	    (os.disk != D_DISKLESS && ns.disk == D_DISKLESS))
-		atomic_inc(&mdev->local_cnt);
-
-	mdev->state = ns;
-
-	if (os.disk == D_ATTACHING && ns.disk >= D_NEGOTIATING)
-		drbd_print_uuids(mdev, "attached to UUIDs");
-
-	wake_up(&mdev->misc_wait);
-	wake_up(&mdev->state_wait);
-
-	/* aborted verify run. log the last position */
-	if ((os.conn == C_VERIFY_S || os.conn == C_VERIFY_T) &&
-	    ns.conn < C_CONNECTED) {
-		mdev->ov_start_sector =
-			BM_BIT_TO_SECT(drbd_bm_bits(mdev) - mdev->ov_left);
-		dev_info(DEV, "Online Verify reached sector %llu\n",
-			(unsigned long long)mdev->ov_start_sector);
-	}
-
-	if ((os.conn == C_PAUSED_SYNC_T || os.conn == C_PAUSED_SYNC_S) &&
-	    (ns.conn == C_SYNC_TARGET  || ns.conn == C_SYNC_SOURCE)) {
-		dev_info(DEV, "Syncer continues.\n");
-		mdev->rs_paused += (long)jiffies
-				  -(long)mdev->rs_mark_time[mdev->rs_last_mark];
-		if (ns.conn == C_SYNC_TARGET)
-			mod_timer(&mdev->resync_timer, jiffies);
-	}
-
-	if ((os.conn == C_SYNC_TARGET  || os.conn == C_SYNC_SOURCE) &&
-	    (ns.conn == C_PAUSED_SYNC_T || ns.conn == C_PAUSED_SYNC_S)) {
-		dev_info(DEV, "Resync suspended\n");
-		mdev->rs_mark_time[mdev->rs_last_mark] = jiffies;
-	}
-
-	if (os.conn == C_CONNECTED &&
-	    (ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T)) {
-		unsigned long now = jiffies;
-		int i;
-
-		set_ov_position(mdev, ns.conn);
-		mdev->rs_start = now;
-		mdev->rs_last_events = 0;
-		mdev->rs_last_sect_ev = 0;
-		mdev->ov_last_oos_size = 0;
-		mdev->ov_last_oos_start = 0;
-
-		for (i = 0; i < DRBD_SYNC_MARKS; i++) {
-			mdev->rs_mark_left[i] = mdev->ov_left;
-			mdev->rs_mark_time[i] = now;
-		}
-
-		drbd_rs_controller_reset(mdev);
-
-		if (ns.conn == C_VERIFY_S) {
-			dev_info(DEV, "Starting Online Verify from sector %llu\n",
-					(unsigned long long)mdev->ov_position);
-			mod_timer(&mdev->resync_timer, jiffies);
-		}
-	}
-
-	if (get_ldev(mdev)) {
-		u32 mdf = mdev->ldev->md.flags & ~(MDF_CONSISTENT|MDF_PRIMARY_IND|
-						 MDF_CONNECTED_IND|MDF_WAS_UP_TO_DATE|
-						 MDF_PEER_OUT_DATED|MDF_CRASHED_PRIMARY);
-
-		if (test_bit(CRASHED_PRIMARY, &mdev->flags))
-			mdf |= MDF_CRASHED_PRIMARY;
-		if (mdev->state.role == R_PRIMARY ||
-		    (mdev->state.pdsk < D_INCONSISTENT && mdev->state.peer == R_PRIMARY))
-			mdf |= MDF_PRIMARY_IND;
-		if (mdev->state.conn > C_WF_REPORT_PARAMS)
-			mdf |= MDF_CONNECTED_IND;
-		if (mdev->state.disk > D_INCONSISTENT)
-			mdf |= MDF_CONSISTENT;
-		if (mdev->state.disk > D_OUTDATED)
-			mdf |= MDF_WAS_UP_TO_DATE;
-		if (mdev->state.pdsk <= D_OUTDATED && mdev->state.pdsk >= D_INCONSISTENT)
-			mdf |= MDF_PEER_OUT_DATED;
-		if (mdf != mdev->ldev->md.flags) {
-			mdev->ldev->md.flags = mdf;
-			drbd_md_mark_dirty(mdev);
-		}
-		if (os.disk < D_CONSISTENT && ns.disk >= D_CONSISTENT)
-			drbd_set_ed_uuid(mdev, mdev->ldev->md.uuid[UI_CURRENT]);
-		put_ldev(mdev);
-	}
-
-	/* Peer was forced D_UP_TO_DATE & R_PRIMARY, consider to resync */
-	if (os.disk == D_INCONSISTENT && os.pdsk == D_INCONSISTENT &&
-	    os.peer == R_SECONDARY && ns.peer == R_PRIMARY)
-		set_bit(CONSIDER_RESYNC, &mdev->flags);
-
-	/* Receiver should clean up itself */
-	if (os.conn != C_DISCONNECTING && ns.conn == C_DISCONNECTING)
-		drbd_thread_stop_nowait(&mdev->receiver);
-
-	/* Now the receiver finished cleaning up itself, it should die */
-	if (os.conn != C_STANDALONE && ns.conn == C_STANDALONE)
-		drbd_thread_stop_nowait(&mdev->receiver);
-
-	/* Upon network failure, we need to restart the receiver. */
-	if (os.conn > C_WF_CONNECTION &&
-	    ns.conn <= C_TEAR_DOWN && ns.conn >= C_TIMEOUT)
-		drbd_thread_restart_nowait(&mdev->receiver);
-
-	/* Resume AL writing if we get a connection */
-	if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED)
-		drbd_resume_al(mdev);
-
-	/* remember last connect and attach times so request_timer_fn() won't
-	 * kill newly established sessions while we are still trying to thaw
-	 * previously frozen IO */
-	if (os.conn != C_WF_REPORT_PARAMS && ns.conn == C_WF_REPORT_PARAMS)
-		mdev->last_reconnect_jif = jiffies;
-	if ((os.disk == D_ATTACHING || os.disk == D_NEGOTIATING) &&
-	    ns.disk > D_NEGOTIATING)
-		mdev->last_reattach_jif = jiffies;
-
-	ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC);
-	if (ascw) {
-		ascw->os = os;
-		ascw->ns = ns;
-		ascw->flags = flags;
-		ascw->w.cb = w_after_state_ch;
-		ascw->done = done;
-		drbd_queue_work(&mdev->data.work, &ascw->w);
-	} else {
-		dev_warn(DEV, "Could not kmalloc an ascw\n");
-	}
-
-	return rv;
-}
-
-static int w_after_state_ch(struct drbd_conf *mdev, struct drbd_work *w, int unused)
-{
-	struct after_state_chg_work *ascw =
-		container_of(w, struct after_state_chg_work, w);
-	after_state_ch(mdev, ascw->os, ascw->ns, ascw->flags);
-	if (ascw->flags & CS_WAIT_COMPLETE) {
-		D_ASSERT(ascw->done != NULL);
-		complete(ascw->done);
-	}
-	kfree(ascw);
-
-	return 1;
-}
-
-static void abw_start_sync(struct drbd_conf *mdev, int rv)
-{
-	if (rv) {
-		dev_err(DEV, "Writing the bitmap failed not starting resync.\n");
-		_drbd_request_state(mdev, NS(conn, C_CONNECTED), CS_VERBOSE);
-		return;
-	}
-
-	switch (mdev->state.conn) {
-	case C_STARTING_SYNC_T:
-		_drbd_request_state(mdev, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE);
-		break;
-	case C_STARTING_SYNC_S:
-		drbd_start_resync(mdev, C_SYNC_SOURCE);
-		break;
-	}
-}
-
-int drbd_bitmap_io_from_worker(struct drbd_conf *mdev,
-		int (*io_fn)(struct drbd_conf *),
-		char *why, enum bm_flag flags)
-{
-	int rv;
-
-	D_ASSERT(current == mdev->worker.task);
-
-	/* open coded non-blocking drbd_suspend_io(mdev); */
-	set_bit(SUSPEND_IO, &mdev->flags);
-
-	drbd_bm_lock(mdev, why, flags);
-	rv = io_fn(mdev);
-	drbd_bm_unlock(mdev);
-
-	drbd_resume_io(mdev);
-
-	return rv;
+	return io_allowed;
 }
 
+#endif
+
 /**
- * after_state_ch() - Perform after state change actions that may sleep
- * @mdev:	DRBD device.
- * @os:		old state.
- * @ns:		new state.
- * @flags:	Flags
+ * tl_release() - mark as BARRIER_ACKED all requests in the corresponding transfer log epoch
+ * @tconn:	DRBD connection.
+ * @barrier_nr:	Expected identifier of the DRBD write barrier packet.
+ * @set_size:	Expected number of requests before that barrier.
+ *
+ * In case the passed barrier_nr or set_size does not match the oldest
+ * epoch of not yet barrier-acked requests, this function will cause a
+ * termination of the connection.
  */
-static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
-			   union drbd_state ns, enum chg_state_flags flags)
+void tl_release(struct drbd_tconn *tconn, unsigned int barrier_nr,
+		unsigned int set_size)
 {
-	enum drbd_fencing_p fp;
-	enum drbd_req_event what = nothing;
-	union drbd_state nsm = (union drbd_state){ .i = -1 };
-
-	if (os.conn != C_CONNECTED && ns.conn == C_CONNECTED) {
-		clear_bit(CRASHED_PRIMARY, &mdev->flags);
-		if (mdev->p_uuid)
-			mdev->p_uuid[UI_FLAGS] &= ~((u64)2);
-	}
-
-	fp = FP_DONT_CARE;
-	if (get_ldev(mdev)) {
-		fp = mdev->ldev->dc.fencing;
-		put_ldev(mdev);
-	}
-
-	/* Inform userspace about the change... */
-	drbd_bcast_state(mdev, ns);
-
-	if (!(os.role == R_PRIMARY && os.disk < D_UP_TO_DATE && os.pdsk < D_UP_TO_DATE) &&
-	    (ns.role == R_PRIMARY && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE))
-		drbd_khelper(mdev, "pri-on-incon-degr");
-
-	/* Here we have the actions that are performed after a
-	   state change. This function might sleep */
-
-	if (os.disk <= D_NEGOTIATING && ns.disk > D_NEGOTIATING)
-		mod_timer(&mdev->request_timer, jiffies + HZ);
-
-	nsm.i = -1;
-	if (ns.susp_nod) {
-		if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED)
-			what = resend;
-
-		if ((os.disk == D_ATTACHING || os.disk == D_NEGOTIATING) &&
-		    ns.disk > D_NEGOTIATING)
-			what = restart_frozen_disk_io;
-
-		if (what != nothing)
-			nsm.susp_nod = 0;
-	}
-
-	if (ns.susp_fen) {
-		/* case1: The outdate peer handler is successful: */
-		if (os.pdsk > D_OUTDATED  && ns.pdsk <= D_OUTDATED) {
-			if (test_bit(NEW_CUR_UUID, &mdev->flags)) {
-				drbd_uuid_new_current(mdev);
-				clear_bit(NEW_CUR_UUID, &mdev->flags);
-			}
-			spin_lock_irq(&mdev->req_lock);
-			_tl_clear(mdev);
-			_drbd_set_state(_NS(mdev, susp_fen, 0), CS_VERBOSE, NULL);
-			spin_unlock_irq(&mdev->req_lock);
-		}
-		/* case2: The connection was established again: */
-		if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) {
-			clear_bit(NEW_CUR_UUID, &mdev->flags);
-			what = resend;
-			nsm.susp_fen = 0;
+	struct drbd_request *r;
+	struct drbd_request *req = NULL;
+	int expect_epoch = 0;
+	int expect_size = 0;
+
+	spin_lock_irq(&tconn->req_lock);
+
+	/* find oldest not yet barrier-acked write request,
+	 * count writes in its epoch. */
+	list_for_each_entry(r, &tconn->transfer_log, tl_requests) {
+		const unsigned s = r->rq_state;
+		if (!req) {
+			if (!(s & RQ_WRITE))
+				continue;
+			if (!(s & RQ_NET_MASK))
+				continue;
+			if (s & RQ_NET_DONE)
+				continue;
+			req = r;
+			expect_epoch = req->epoch;
+			expect_size ++;
+		} else {
+			if (r->epoch != expect_epoch)
+				break;
+			if (!(s & RQ_WRITE))
+				continue;
+			/* if (s & RQ_DONE): not expected */
+			/* if (!(s & RQ_NET_MASK)): not expected */
+			expect_size++;
 		}
 	}
 
-	if (what != nothing) {
-		spin_lock_irq(&mdev->req_lock);
-		_tl_restart(mdev, what);
-		nsm.i &= mdev->state.i;
-		_drbd_set_state(mdev, nsm, CS_VERBOSE, NULL);
-		spin_unlock_irq(&mdev->req_lock);
+	/* first some paranoia code */
+	if (req == NULL) {
+		conn_err(tconn, "BAD! BarrierAck #%u received, but no epoch in tl!?\n",
+			 barrier_nr);
+		goto bail;
 	}
-
-	/* Became sync source.  With protocol >= 96, we still need to send out
-	 * the sync uuid now. Need to do that before any drbd_send_state, or
-	 * the other side may go "paused sync" before receiving the sync uuids,
-	 * which is unexpected. */
-	if ((os.conn != C_SYNC_SOURCE && os.conn != C_PAUSED_SYNC_S) &&
-	    (ns.conn == C_SYNC_SOURCE || ns.conn == C_PAUSED_SYNC_S) &&
-	    mdev->agreed_pro_version >= 96 && get_ldev(mdev)) {
-		drbd_gen_and_send_sync_uuid(mdev);
-		put_ldev(mdev);
+	if (expect_epoch != barrier_nr) {
+		conn_err(tconn, "BAD! BarrierAck #%u received, expected #%u!\n",
+			 barrier_nr, expect_epoch);
+		goto bail;
 	}
 
-	/* Do not change the order of the if above and the two below... */
-	if (os.pdsk == D_DISKLESS && ns.pdsk > D_DISKLESS) {      /* attach on the peer */
-		/* we probably will start a resync soon.
-		 * make sure those things are properly reset. */
-		mdev->rs_total = 0;
-		mdev->rs_failed = 0;
-		atomic_set(&mdev->rs_pending_cnt, 0);
-		drbd_rs_cancel_all(mdev);
-
-		drbd_send_uuids(mdev);
-		drbd_send_state(mdev, ns);
-	}
-	/* No point in queuing send_bitmap if we don't have a connection
-	 * anymore, so check also the _current_ state, not only the new state
-	 * at the time this work was queued. */
-	if (os.conn != C_WF_BITMAP_S && ns.conn == C_WF_BITMAP_S &&
-	    mdev->state.conn == C_WF_BITMAP_S)
-		drbd_queue_bitmap_io(mdev, &drbd_send_bitmap, NULL,
-				"send_bitmap (WFBitMapS)",
-				BM_LOCKED_TEST_ALLOWED);
-
-	/* Lost contact to peer's copy of the data */
-	if ((os.pdsk >= D_INCONSISTENT &&
-	     os.pdsk != D_UNKNOWN &&
-	     os.pdsk != D_OUTDATED)
-	&&  (ns.pdsk < D_INCONSISTENT ||
-	     ns.pdsk == D_UNKNOWN ||
-	     ns.pdsk == D_OUTDATED)) {
-		if (get_ldev(mdev)) {
-			if ((ns.role == R_PRIMARY || ns.peer == R_PRIMARY) &&
-			    mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
-				if (is_susp(mdev->state)) {
-					set_bit(NEW_CUR_UUID, &mdev->flags);
-				} else {
-					drbd_uuid_new_current(mdev);
-					drbd_send_uuids(mdev);
-				}
-			}
-			put_ldev(mdev);
-		}
+	if (expect_size != set_size) {
+		conn_err(tconn, "BAD! BarrierAck #%u received with n_writes=%u, expected n_writes=%u!\n",
+			 barrier_nr, set_size, expect_size);
+		goto bail;
 	}
 
-	if (ns.pdsk < D_INCONSISTENT && get_ldev(mdev)) {
-		if (os.peer == R_SECONDARY && ns.peer == R_PRIMARY &&
-		    mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
-			drbd_uuid_new_current(mdev);
-			drbd_send_uuids(mdev);
-		}
-		/* D_DISKLESS Peer becomes secondary */
-		if (os.peer == R_PRIMARY && ns.peer == R_SECONDARY)
-			/* We may still be Primary ourselves.
-			 * No harm done if the bitmap still changes,
-			 * redirtied pages will follow later. */
-			drbd_bitmap_io_from_worker(mdev, &drbd_bm_write,
-				"demote diskless peer", BM_LOCKED_SET_ALLOWED);
-		put_ldev(mdev);
+	/* Clean up list of requests processed during current epoch. */
+	/* this extra list walk restart is paranoia,
+	 * to catch requests being barrier-acked "unexpectedly".
+	 * It usually should find the same req again, or some READ preceding it. */
+	list_for_each_entry(req, &tconn->transfer_log, tl_requests)
+		if (req->epoch == expect_epoch)
+			break;
+	list_for_each_entry_safe_from(req, r, &tconn->transfer_log, tl_requests) {
+		if (req->epoch != expect_epoch)
+			break;
+		_req_mod(req, BARRIER_ACKED);
 	}
+	spin_unlock_irq(&tconn->req_lock);
 
-	/* Write out all changed bits on demote.
-	 * Though, no need to da that just yet
-	 * if there is a resync going on still */
-	if (os.role == R_PRIMARY && ns.role == R_SECONDARY &&
-		mdev->state.conn <= C_CONNECTED && get_ldev(mdev)) {
-		/* No changes to the bitmap expected this time, so assert that,
-		 * even though no harm was done if it did change. */
-		drbd_bitmap_io_from_worker(mdev, &drbd_bm_write,
-				"demote", BM_LOCKED_TEST_ALLOWED);
-		put_ldev(mdev);
-	}
+	return;
 
-	/* Last part of the attaching process ... */
-	if (ns.conn >= C_CONNECTED &&
-	    os.disk == D_ATTACHING && ns.disk == D_NEGOTIATING) {
-		drbd_send_sizes(mdev, 0, 0);  /* to start sync... */
-		drbd_send_uuids(mdev);
-		drbd_send_state(mdev, ns);
-	}
+bail:
+	spin_unlock_irq(&tconn->req_lock);
+	conn_request_state(tconn, NS(conn, C_PROTOCOL_ERROR), CS_HARD);
+}
 
-	/* We want to pause/continue resync, tell peer. */
-	if (ns.conn >= C_CONNECTED &&
-	     ((os.aftr_isp != ns.aftr_isp) ||
-	      (os.user_isp != ns.user_isp)))
-		drbd_send_state(mdev, ns);
-
-	/* In case one of the isp bits got set, suspend other devices. */
-	if ((!os.aftr_isp && !os.peer_isp && !os.user_isp) &&
-	    (ns.aftr_isp || ns.peer_isp || ns.user_isp))
-		suspend_other_sg(mdev);
-
-	/* Make sure the peer gets informed about eventual state
-	   changes (ISP bits) while we were in WFReportParams. */
-	if (os.conn == C_WF_REPORT_PARAMS && ns.conn >= C_CONNECTED)
-		drbd_send_state(mdev, ns);
-
-	if (os.conn != C_AHEAD && ns.conn == C_AHEAD)
-		drbd_send_state(mdev, ns);
-
-	/* We are in the progress to start a full sync... */
-	if ((os.conn != C_STARTING_SYNC_T && ns.conn == C_STARTING_SYNC_T) ||
-	    (os.conn != C_STARTING_SYNC_S && ns.conn == C_STARTING_SYNC_S))
-		/* no other bitmap changes expected during this phase */
-		drbd_queue_bitmap_io(mdev,
-			&drbd_bmio_set_n_write, &abw_start_sync,
-			"set_n_write from StartingSync", BM_LOCKED_TEST_ALLOWED);
-
-	/* We are invalidating our self... */
-	if (os.conn < C_CONNECTED && ns.conn < C_CONNECTED &&
-	    os.disk > D_INCONSISTENT && ns.disk == D_INCONSISTENT)
-		/* other bitmap operation expected during this phase */
-		drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, NULL,
-			"set_n_write from invalidate", BM_LOCKED_MASK);
-
-	/* first half of local IO error, failure to attach,
-	 * or administrative detach */
-	if (os.disk != D_FAILED && ns.disk == D_FAILED) {
-		enum drbd_io_error_p eh = EP_PASS_ON;
-		int was_io_error = 0;
-		/* corresponding get_ldev was in __drbd_set_state, to serialize
-		 * our cleanup here with the transition to D_DISKLESS.
-		 * But is is still not save to dreference ldev here, since
-		 * we might come from an failed Attach before ldev was set. */
-		if (mdev->ldev) {
-			eh = mdev->ldev->dc.on_io_error;
-			was_io_error = test_and_clear_bit(WAS_IO_ERROR, &mdev->flags);
-
-			if (was_io_error && eh == EP_CALL_HELPER)
-				drbd_khelper(mdev, "local-io-error");
-
-			/* Immediately allow completion of all application IO,
-			 * that waits for completion from the local disk,
-			 * if this was a force-detach due to disk_timeout
-			 * or administrator request (drbdsetup detach --force).
-			 * Do NOT abort otherwise.
-			 * Aborting local requests may cause serious problems,
-			 * if requests are completed to upper layers already,
-			 * and then later the already submitted local bio completes.
-			 * This can cause DMA into former bio pages that meanwhile
-			 * have been re-used for other things.
-			 * So aborting local requests may cause crashes,
-			 * or even worse, silent data corruption.
-			 */
-			if (test_and_clear_bit(FORCE_DETACH, &mdev->flags))
-				tl_abort_disk_io(mdev);
-
-			/* current state still has to be D_FAILED,
-			 * there is only one way out: to D_DISKLESS,
-			 * and that may only happen after our put_ldev below. */
-			if (mdev->state.disk != D_FAILED)
-				dev_err(DEV,
-					"ASSERT FAILED: disk is %s during detach\n",
-					drbd_disk_str(mdev->state.disk));
-
-			if (ns.conn >= C_CONNECTED)
-				drbd_send_state(mdev, ns);
-
-			drbd_rs_cancel_all(mdev);
-
-			/* In case we want to get something to stable storage still,
-			 * this may be the last chance.
-			 * Following put_ldev may transition to D_DISKLESS. */
-			drbd_md_sync(mdev);
-		}
-		put_ldev(mdev);
-	}
 
-        /* second half of local IO error, failure to attach,
-         * or administrative detach,
-         * after local_cnt references have reached zero again */
-        if (os.disk != D_DISKLESS && ns.disk == D_DISKLESS) {
-                /* We must still be diskless,
-                 * re-attach has to be serialized with this! */
-                if (mdev->state.disk != D_DISKLESS)
-                        dev_err(DEV,
-                                "ASSERT FAILED: disk is %s while going diskless\n",
-                                drbd_disk_str(mdev->state.disk));
-
-		if (ns.conn >= C_CONNECTED)
-			drbd_send_state(mdev, ns);
-
-		/* corresponding get_ldev in __drbd_set_state
-		 * this may finally trigger drbd_ldev_destroy. */
-		put_ldev(mdev);
-	}
+/**
+ * _tl_restart() - Walks the transfer log, and applies an action to all requests
+ * @mdev:	DRBD device.
+ * @what:       The action/event to perform with all request objects
+ *
+ * @what might be one of CONNECTION_LOST_WHILE_PENDING, RESEND, FAIL_FROZEN_DISK_IO,
+ * RESTART_FROZEN_DISK_IO.
+ */
+/* must hold resource->req_lock */
+void _tl_restart(struct drbd_tconn *tconn, enum drbd_req_event what)
+{
+	struct drbd_request *req, *r;
 
-	/* Notify peer that I had a local IO error, and did not detached.. */
-	if (os.disk == D_UP_TO_DATE && ns.disk == D_INCONSISTENT && ns.conn >= C_CONNECTED)
-		drbd_send_state(mdev, ns);
+	list_for_each_entry_safe(req, r, &tconn->transfer_log, tl_requests)
+		_req_mod(req, what);
+}
 
-	/* Disks got bigger while they were detached */
-	if (ns.disk > D_NEGOTIATING && ns.pdsk > D_NEGOTIATING &&
-	    test_and_clear_bit(RESYNC_AFTER_NEG, &mdev->flags)) {
-		if (ns.conn == C_CONNECTED)
-			resync_after_online_grow(mdev);
-	}
+void tl_restart(struct drbd_tconn *tconn, enum drbd_req_event what)
+{
+	spin_lock_irq(&tconn->req_lock);
+	_tl_restart(tconn, what);
+	spin_unlock_irq(&tconn->req_lock);
+}
 
-	/* A resync finished or aborted, wake paused devices... */
-	if ((os.conn > C_CONNECTED && ns.conn <= C_CONNECTED) ||
-	    (os.peer_isp && !ns.peer_isp) ||
-	    (os.user_isp && !ns.user_isp))
-		resume_next_sg(mdev);
-
-	/* sync target done with resync.  Explicitly notify peer, even though
-	 * it should (at least for non-empty resyncs) already know itself. */
-	if (os.disk < D_UP_TO_DATE && os.conn >= C_SYNC_SOURCE && ns.conn == C_CONNECTED)
-		drbd_send_state(mdev, ns);
-
-	/* Wake up role changes, that were delayed because of connection establishing */
-	if (os.conn == C_WF_REPORT_PARAMS && ns.conn != C_WF_REPORT_PARAMS) {
-		clear_bit(STATE_SENT, &mdev->flags);
-		wake_up(&mdev->state_wait);
-	}
+/**
+ * tl_clear() - Clears all requests and &struct drbd_tl_epoch objects out of the TL
+ * @mdev:	DRBD device.
+ *
+ * This is called after the connection to the peer was lost. The storage covered
+ * by the requests on the transfer gets marked as our of sync. Called from the
+ * receiver thread and the worker thread.
+ */
+void tl_clear(struct drbd_tconn *tconn)
+{
+	tl_restart(tconn, CONNECTION_LOST_WHILE_PENDING);
+}
 
-	/* This triggers bitmap writeout of potentially still unwritten pages
-	 * if the resync finished cleanly, or aborted because of peer disk
-	 * failure, or because of connection loss.
-	 * For resync aborted because of local disk failure, we cannot do
-	 * any bitmap writeout anymore.
-	 * No harm done if some bits change during this phase.
-	 */
-	if (os.conn > C_CONNECTED && ns.conn <= C_CONNECTED && get_ldev(mdev)) {
-		drbd_queue_bitmap_io(mdev, &drbd_bm_write_copy_pages, NULL,
-			"write from resync_finished", BM_LOCKED_CHANGE_ALLOWED);
-		put_ldev(mdev);
-	}
+/**
+ * tl_abort_disk_io() - Abort disk I/O for all requests for a certain mdev in the TL
+ * @mdev:	DRBD device.
+ */
+void tl_abort_disk_io(struct drbd_conf *mdev)
+{
+	struct drbd_tconn *tconn = mdev->tconn;
+	struct drbd_request *req, *r;
 
-	/* free tl_hash if we Got thawed and are C_STANDALONE */
-	if (ns.conn == C_STANDALONE && !is_susp(ns) && mdev->tl_hash)
-		drbd_free_tl_hash(mdev);
-
-	/* Upon network connection, we need to start the receiver */
-	if (os.conn == C_STANDALONE && ns.conn == C_UNCONNECTED)
-		drbd_thread_start(&mdev->receiver);
-
-	/* Terminate worker thread if we are unconfigured - it will be
-	   restarted as needed... */
-	if (ns.disk == D_DISKLESS &&
-	    ns.conn == C_STANDALONE &&
-	    ns.role == R_SECONDARY) {
-		if (os.aftr_isp != ns.aftr_isp)
-			resume_next_sg(mdev);
-		/* set in __drbd_set_state, unless CONFIG_PENDING was set */
-		if (test_bit(DEVICE_DYING, &mdev->flags))
-			drbd_thread_stop_nowait(&mdev->worker);
+	spin_lock_irq(&tconn->req_lock);
+	list_for_each_entry_safe(req, r, &tconn->transfer_log, tl_requests) {
+		if (!(req->rq_state & RQ_LOCAL_PENDING))
+			continue;
+		if (req->w.mdev != mdev)
+			continue;
+		_req_mod(req, ABORT_DISK_IO);
 	}
-
-	drbd_md_sync(mdev);
+	spin_unlock_irq(&tconn->req_lock);
 }
 
-
 static int drbd_thread_setup(void *arg)
 {
 	struct drbd_thread *thi = (struct drbd_thread *) arg;
-	struct drbd_conf *mdev = thi->mdev;
+	struct drbd_tconn *tconn = thi->tconn;
 	unsigned long flags;
 	int retval;
 
+	snprintf(current->comm, sizeof(current->comm), "drbd_%c_%s",
+		 thi->name[0], thi->tconn->name);
+
 restart:
 	retval = thi->function(thi);
 
 	spin_lock_irqsave(&thi->t_lock, flags);
 
-	/* if the receiver has been "Exiting", the last thing it did
+	/* if the receiver has been "EXITING", the last thing it did
 	 * was set the conn state to "StandAlone",
 	 * if now a re-connect request comes in, conn state goes C_UNCONNECTED,
 	 * and receiver thread will be "started".
-	 * drbd_thread_start needs to set "Restarting" in that case.
+	 * drbd_thread_start needs to set "RESTARTING" in that case.
 	 * t_state check and assignment needs to be within the same spinlock,
-	 * so either thread_start sees Exiting, and can remap to Restarting,
-	 * or thread_start see None, and can proceed as normal.
+	 * so either thread_start sees EXITING, and can remap to RESTARTING,
+	 * or thread_start see NONE, and can proceed as normal.
 	 */
 
-	if (thi->t_state == Restarting) {
-		dev_info(DEV, "Restarting %s\n", current->comm);
-		thi->t_state = Running;
+	if (thi->t_state == RESTARTING) {
+		conn_info(tconn, "Restarting %s thread\n", thi->name);
+		thi->t_state = RUNNING;
 		spin_unlock_irqrestore(&thi->t_lock, flags);
 		goto restart;
 	}
 
 	thi->task = NULL;
-	thi->t_state = None;
+	thi->t_state = NONE;
 	smp_mb();
-	complete(&thi->stop);
+	complete_all(&thi->stop);
 	spin_unlock_irqrestore(&thi->t_lock, flags);
 
-	dev_info(DEV, "Terminating %s\n", current->comm);
+	conn_info(tconn, "Terminating %s\n", current->comm);
 
 	/* Release mod reference taken when thread was started */
+
+	kref_put(&tconn->kref, &conn_destroy);
 	module_put(THIS_MODULE);
 	return retval;
 }
 
-static void drbd_thread_init(struct drbd_conf *mdev, struct drbd_thread *thi,
-		      int (*func) (struct drbd_thread *))
+static void drbd_thread_init(struct drbd_tconn *tconn, struct drbd_thread *thi,
+			     int (*func) (struct drbd_thread *), char *name)
 {
 	spin_lock_init(&thi->t_lock);
 	thi->task    = NULL;
-	thi->t_state = None;
+	thi->t_state = NONE;
 	thi->function = func;
-	thi->mdev = mdev;
+	thi->tconn = tconn;
+	strncpy(thi->name, name, ARRAY_SIZE(thi->name));
 }
 
 int drbd_thread_start(struct drbd_thread *thi)
 {
-	struct drbd_conf *mdev = thi->mdev;
+	struct drbd_tconn *tconn = thi->tconn;
 	struct task_struct *nt;
 	unsigned long flags;
 
-	const char *me =
-		thi == &mdev->receiver ? "receiver" :
-		thi == &mdev->asender  ? "asender"  :
-		thi == &mdev->worker   ? "worker"   : "NONSENSE";
-
 	/* is used from state engine doing drbd_thread_stop_nowait,
 	 * while holding the req lock irqsave */
 	spin_lock_irqsave(&thi->t_lock, flags);
 
 	switch (thi->t_state) {
-	case None:
-		dev_info(DEV, "Starting %s thread (from %s [%d])\n",
-				me, current->comm, current->pid);
+	case NONE:
+		conn_info(tconn, "Starting %s thread (from %s [%d])\n",
+			 thi->name, current->comm, current->pid);
 
 		/* Get ref on module for thread - this is released when thread exits */
 		if (!try_module_get(THIS_MODULE)) {
-			dev_err(DEV, "Failed to get module reference in drbd_thread_start\n");
+			conn_err(tconn, "Failed to get module reference in drbd_thread_start\n");
 			spin_unlock_irqrestore(&thi->t_lock, flags);
 			return false;
 		}
 
+		kref_get(&thi->tconn->kref);
+
 		init_completion(&thi->stop);
-		D_ASSERT(thi->task == NULL);
 		thi->reset_cpu_mask = 1;
-		thi->t_state = Running;
+		thi->t_state = RUNNING;
 		spin_unlock_irqrestore(&thi->t_lock, flags);
 		flush_signals(current); /* otherw. may get -ERESTARTNOINTR */
 
 		nt = kthread_create(drbd_thread_setup, (void *) thi,
-				    "drbd%d_%s", mdev_to_minor(mdev), me);
+				    "drbd_%c_%s", thi->name[0], thi->tconn->name);
 
 		if (IS_ERR(nt)) {
-			dev_err(DEV, "Couldn't start thread\n");
+			conn_err(tconn, "Couldn't start thread\n");
 
+			kref_put(&tconn->kref, &conn_destroy);
 			module_put(THIS_MODULE);
 			return false;
 		}
 		spin_lock_irqsave(&thi->t_lock, flags);
 		thi->task = nt;
-		thi->t_state = Running;
+		thi->t_state = RUNNING;
 		spin_unlock_irqrestore(&thi->t_lock, flags);
 		wake_up_process(nt);
 		break;
-	case Exiting:
-		thi->t_state = Restarting;
-		dev_info(DEV, "Restarting %s thread (from %s [%d])\n",
-				me, current->comm, current->pid);
+	case EXITING:
+		thi->t_state = RESTARTING;
+		conn_info(tconn, "Restarting %s thread (from %s [%d])\n",
+				thi->name, current->comm, current->pid);
 		/* fall through */
-	case Running:
-	case Restarting:
+	case RUNNING:
+	case RESTARTING:
 	default:
 		spin_unlock_irqrestore(&thi->t_lock, flags);
 		break;
@@ -1867,12 +447,12 @@ void _drbd_thread_stop(struct drbd_thread *thi, int restart, int wait)
 {
 	unsigned long flags;
 
-	enum drbd_thread_state ns = restart ? Restarting : Exiting;
+	enum drbd_thread_state ns = restart ? RESTARTING : EXITING;
 
 	/* may be called from state engine, holding the req lock irqsave */
 	spin_lock_irqsave(&thi->t_lock, flags);
 
-	if (thi->t_state == None) {
+	if (thi->t_state == NONE) {
 		spin_unlock_irqrestore(&thi->t_lock, flags);
 		if (restart)
 			drbd_thread_start(thi);
@@ -1890,7 +470,6 @@ void _drbd_thread_stop(struct drbd_thread *thi, int restart, int wait)
 		init_completion(&thi->stop);
 		if (thi->task != current)
 			force_sig(DRBD_SIGKILL, thi->task);
-
 	}
 
 	spin_unlock_irqrestore(&thi->t_lock, flags);
@@ -1899,6 +478,35 @@ void _drbd_thread_stop(struct drbd_thread *thi, int restart, int wait)
 		wait_for_completion(&thi->stop);
 }
 
+static struct drbd_thread *drbd_task_to_thread(struct drbd_tconn *tconn, struct task_struct *task)
+{
+	struct drbd_thread *thi =
+		task == tconn->receiver.task ? &tconn->receiver :
+		task == tconn->asender.task  ? &tconn->asender :
+		task == tconn->worker.task   ? &tconn->worker : NULL;
+
+	return thi;
+}
+
+char *drbd_task_to_thread_name(struct drbd_tconn *tconn, struct task_struct *task)
+{
+	struct drbd_thread *thi = drbd_task_to_thread(tconn, task);
+	return thi ? thi->name : task->comm;
+}
+
+int conn_lowest_minor(struct drbd_tconn *tconn)
+{
+	struct drbd_conf *mdev;
+	int vnr = 0, m;
+
+	rcu_read_lock();
+	mdev = idr_get_next(&tconn->volumes, &vnr);
+	m = mdev ? mdev_to_minor(mdev) : -1;
+	rcu_read_unlock();
+
+	return m;
+}
+
 #ifdef CONFIG_SMP
 /**
  * drbd_calc_cpu_mask() - Generate CPU masks, spread over all CPUs
@@ -1907,238 +515,345 @@ void _drbd_thread_stop(struct drbd_thread *thi, int restart, int wait)
  * Forces all threads of a device onto the same CPU. This is beneficial for
  * DRBD's performance. May be overwritten by user's configuration.
  */
-void drbd_calc_cpu_mask(struct drbd_conf *mdev)
+void drbd_calc_cpu_mask(struct drbd_tconn *tconn)
 {
 	int ord, cpu;
 
 	/* user override. */
-	if (cpumask_weight(mdev->cpu_mask))
+	if (cpumask_weight(tconn->cpu_mask))
 		return;
 
-	ord = mdev_to_minor(mdev) % cpumask_weight(cpu_online_mask);
+	ord = conn_lowest_minor(tconn) % cpumask_weight(cpu_online_mask);
 	for_each_online_cpu(cpu) {
 		if (ord-- == 0) {
-			cpumask_set_cpu(cpu, mdev->cpu_mask);
+			cpumask_set_cpu(cpu, tconn->cpu_mask);
 			return;
 		}
 	}
 	/* should not be reached */
-	cpumask_setall(mdev->cpu_mask);
+	cpumask_setall(tconn->cpu_mask);
 }
 
 /**
  * drbd_thread_current_set_cpu() - modifies the cpu mask of the _current_ thread
  * @mdev:	DRBD device.
+ * @thi:	drbd_thread object
  *
  * call in the "main loop" of _all_ threads, no need for any mutex, current won't die
  * prematurely.
  */
-void drbd_thread_current_set_cpu(struct drbd_conf *mdev)
+void drbd_thread_current_set_cpu(struct drbd_thread *thi)
 {
 	struct task_struct *p = current;
-	struct drbd_thread *thi =
-		p == mdev->asender.task  ? &mdev->asender  :
-		p == mdev->receiver.task ? &mdev->receiver :
-		p == mdev->worker.task   ? &mdev->worker   :
-		NULL;
-	ERR_IF(thi == NULL)
-		return;
+
 	if (!thi->reset_cpu_mask)
 		return;
 	thi->reset_cpu_mask = 0;
-	set_cpus_allowed_ptr(p, mdev->cpu_mask);
+	set_cpus_allowed_ptr(p, thi->tconn->cpu_mask);
 }
 #endif
 
-/* the appropriate socket mutex must be held already */
-int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock,
-			  enum drbd_packets cmd, struct p_header80 *h,
-			  size_t size, unsigned msg_flags)
+/**
+ * drbd_header_size  -  size of a packet header
+ *
+ * The header size is a multiple of 8, so any payload following the header is
+ * word aligned on 64-bit architectures.  (The bitmap send and receive code
+ * relies on this.)
+ */
+unsigned int drbd_header_size(struct drbd_tconn *tconn)
+{
+	if (tconn->agreed_pro_version >= 100) {
+		BUILD_BUG_ON(!IS_ALIGNED(sizeof(struct p_header100), 8));
+		return sizeof(struct p_header100);
+	} else {
+		BUILD_BUG_ON(sizeof(struct p_header80) !=
+			     sizeof(struct p_header95));
+		BUILD_BUG_ON(!IS_ALIGNED(sizeof(struct p_header80), 8));
+		return sizeof(struct p_header80);
+	}
+}
+
+static unsigned int prepare_header80(struct p_header80 *h, enum drbd_packet cmd, int size)
 {
-	int sent, ok;
+	h->magic   = cpu_to_be32(DRBD_MAGIC);
+	h->command = cpu_to_be16(cmd);
+	h->length  = cpu_to_be16(size);
+	return sizeof(struct p_header80);
+}
 
-	ERR_IF(!h) return false;
-	ERR_IF(!size) return false;
+static unsigned int prepare_header95(struct p_header95 *h, enum drbd_packet cmd, int size)
+{
+	h->magic   = cpu_to_be16(DRBD_MAGIC_BIG);
+	h->command = cpu_to_be16(cmd);
+	h->length = cpu_to_be32(size);
+	return sizeof(struct p_header95);
+}
 
-	h->magic   = BE_DRBD_MAGIC;
+static unsigned int prepare_header100(struct p_header100 *h, enum drbd_packet cmd,
+				      int size, int vnr)
+{
+	h->magic = cpu_to_be32(DRBD_MAGIC_100);
+	h->volume = cpu_to_be16(vnr);
 	h->command = cpu_to_be16(cmd);
-	h->length  = cpu_to_be16(size-sizeof(struct p_header80));
+	h->length = cpu_to_be32(size);
+	h->pad = 0;
+	return sizeof(struct p_header100);
+}
 
-	sent = drbd_send(mdev, sock, h, size, msg_flags);
+static unsigned int prepare_header(struct drbd_tconn *tconn, int vnr,
+				   void *buffer, enum drbd_packet cmd, int size)
+{
+	if (tconn->agreed_pro_version >= 100)
+		return prepare_header100(buffer, cmd, size, vnr);
+	else if (tconn->agreed_pro_version >= 95 &&
+		 size > DRBD_MAX_SIZE_H80_PACKET)
+		return prepare_header95(buffer, cmd, size);
+	else
+		return prepare_header80(buffer, cmd, size);
+}
 
-	ok = (sent == size);
-	if (!ok && !signal_pending(current))
-		dev_warn(DEV, "short sent %s size=%d sent=%d\n",
-		    cmdname(cmd), (int)size, sent);
-	return ok;
+static void *__conn_prepare_command(struct drbd_tconn *tconn,
+				    struct drbd_socket *sock)
+{
+	if (!sock->socket)
+		return NULL;
+	return sock->sbuf + drbd_header_size(tconn);
 }
 
-/* don't pass the socket. we may only look at it
- * when we hold the appropriate socket mutex.
- */
-int drbd_send_cmd(struct drbd_conf *mdev, int use_data_socket,
-		  enum drbd_packets cmd, struct p_header80 *h, size_t size)
+void *conn_prepare_command(struct drbd_tconn *tconn, struct drbd_socket *sock)
 {
-	int ok = 0;
-	struct socket *sock;
+	void *p;
 
-	if (use_data_socket) {
-		mutex_lock(&mdev->data.mutex);
-		sock = mdev->data.socket;
-	} else {
-		mutex_lock(&mdev->meta.mutex);
-		sock = mdev->meta.socket;
-	}
+	mutex_lock(&sock->mutex);
+	p = __conn_prepare_command(tconn, sock);
+	if (!p)
+		mutex_unlock(&sock->mutex);
 
-	/* drbd_disconnect() could have called drbd_free_sock()
-	 * while we were waiting in down()... */
-	if (likely(sock != NULL))
-		ok = _drbd_send_cmd(mdev, sock, cmd, h, size, 0);
+	return p;
+}
 
-	if (use_data_socket)
-		mutex_unlock(&mdev->data.mutex);
-	else
-		mutex_unlock(&mdev->meta.mutex);
-	return ok;
+void *drbd_prepare_command(struct drbd_conf *mdev, struct drbd_socket *sock)
+{
+	return conn_prepare_command(mdev->tconn, sock);
 }
 
-int drbd_send_cmd2(struct drbd_conf *mdev, enum drbd_packets cmd, char *data,
-		   size_t size)
+static int __send_command(struct drbd_tconn *tconn, int vnr,
+			  struct drbd_socket *sock, enum drbd_packet cmd,
+			  unsigned int header_size, void *data,
+			  unsigned int size)
 {
-	struct p_header80 h;
-	int ok;
+	int msg_flags;
+	int err;
 
-	h.magic   = BE_DRBD_MAGIC;
-	h.command = cpu_to_be16(cmd);
-	h.length  = cpu_to_be16(size);
+	/*
+	 * Called with @data == NULL and the size of the data blocks in @size
+	 * for commands that send data blocks.  For those commands, omit the
+	 * MSG_MORE flag: this will increase the likelihood that data blocks
+	 * which are page aligned on the sender will end up page aligned on the
+	 * receiver.
+	 */
+	msg_flags = data ? MSG_MORE : 0;
+
+	header_size += prepare_header(tconn, vnr, sock->sbuf, cmd,
+				      header_size + size);
+	err = drbd_send_all(tconn, sock->socket, sock->sbuf, header_size,
+			    msg_flags);
+	if (data && !err)
+		err = drbd_send_all(tconn, sock->socket, data, size, 0);
+	return err;
+}
 
-	if (!drbd_get_data_sock(mdev))
-		return 0;
+static int __conn_send_command(struct drbd_tconn *tconn, struct drbd_socket *sock,
+			       enum drbd_packet cmd, unsigned int header_size,
+			       void *data, unsigned int size)
+{
+	return __send_command(tconn, 0, sock, cmd, header_size, data, size);
+}
+
+int conn_send_command(struct drbd_tconn *tconn, struct drbd_socket *sock,
+		      enum drbd_packet cmd, unsigned int header_size,
+		      void *data, unsigned int size)
+{
+	int err;
+
+	err = __conn_send_command(tconn, sock, cmd, header_size, data, size);
+	mutex_unlock(&sock->mutex);
+	return err;
+}
+
+int drbd_send_command(struct drbd_conf *mdev, struct drbd_socket *sock,
+		      enum drbd_packet cmd, unsigned int header_size,
+		      void *data, unsigned int size)
+{
+	int err;
+
+	err = __send_command(mdev->tconn, mdev->vnr, sock, cmd, header_size,
+			     data, size);
+	mutex_unlock(&sock->mutex);
+	return err;
+}
 
-	ok = (sizeof(h) ==
-		drbd_send(mdev, mdev->data.socket, &h, sizeof(h), 0));
-	ok = ok && (size ==
-		drbd_send(mdev, mdev->data.socket, data, size, 0));
+int drbd_send_ping(struct drbd_tconn *tconn)
+{
+	struct drbd_socket *sock;
+
+	sock = &tconn->meta;
+	if (!conn_prepare_command(tconn, sock))
+		return -EIO;
+	return conn_send_command(tconn, sock, P_PING, 0, NULL, 0);
+}
 
-	drbd_put_data_sock(mdev);
+int drbd_send_ping_ack(struct drbd_tconn *tconn)
+{
+	struct drbd_socket *sock;
 
-	return ok;
+	sock = &tconn->meta;
+	if (!conn_prepare_command(tconn, sock))
+		return -EIO;
+	return conn_send_command(tconn, sock, P_PING_ACK, 0, NULL, 0);
 }
 
-int drbd_send_sync_param(struct drbd_conf *mdev, struct syncer_conf *sc)
+int drbd_send_sync_param(struct drbd_conf *mdev)
 {
+	struct drbd_socket *sock;
 	struct p_rs_param_95 *p;
-	struct socket *sock;
-	int size, rv;
-	const int apv = mdev->agreed_pro_version;
+	int size;
+	const int apv = mdev->tconn->agreed_pro_version;
+	enum drbd_packet cmd;
+	struct net_conf *nc;
+	struct disk_conf *dc;
+
+	sock = &mdev->tconn->data;
+	p = drbd_prepare_command(mdev, sock);
+	if (!p)
+		return -EIO;
+
+	rcu_read_lock();
+	nc = rcu_dereference(mdev->tconn->net_conf);
 
 	size = apv <= 87 ? sizeof(struct p_rs_param)
 		: apv == 88 ? sizeof(struct p_rs_param)
-			+ strlen(mdev->sync_conf.verify_alg) + 1
+			+ strlen(nc->verify_alg) + 1
 		: apv <= 94 ? sizeof(struct p_rs_param_89)
 		: /* apv >= 95 */ sizeof(struct p_rs_param_95);
 
-	/* used from admin command context and receiver/worker context.
-	 * to avoid kmalloc, grab the socket right here,
-	 * then use the pre-allocated sbuf there */
-	mutex_lock(&mdev->data.mutex);
-	sock = mdev->data.socket;
-
-	if (likely(sock != NULL)) {
-		enum drbd_packets cmd = apv >= 89 ? P_SYNC_PARAM89 : P_SYNC_PARAM;
-
-		p = &mdev->data.sbuf.rs_param_95;
-
-		/* initialize verify_alg and csums_alg */
-		memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX);
-
-		p->rate = cpu_to_be32(sc->rate);
-		p->c_plan_ahead = cpu_to_be32(sc->c_plan_ahead);
-		p->c_delay_target = cpu_to_be32(sc->c_delay_target);
-		p->c_fill_target = cpu_to_be32(sc->c_fill_target);
-		p->c_max_rate = cpu_to_be32(sc->c_max_rate);
+	cmd = apv >= 89 ? P_SYNC_PARAM89 : P_SYNC_PARAM;
 
-		if (apv >= 88)
-			strcpy(p->verify_alg, mdev->sync_conf.verify_alg);
-		if (apv >= 89)
-			strcpy(p->csums_alg, mdev->sync_conf.csums_alg);
+	/* initialize verify_alg and csums_alg */
+	memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX);
 
-		rv = _drbd_send_cmd(mdev, sock, cmd, &p->head, size, 0);
-	} else
-		rv = 0; /* not ok */
+	if (get_ldev(mdev)) {
+		dc = rcu_dereference(mdev->ldev->disk_conf);
+		p->resync_rate = cpu_to_be32(dc->resync_rate);
+		p->c_plan_ahead = cpu_to_be32(dc->c_plan_ahead);
+		p->c_delay_target = cpu_to_be32(dc->c_delay_target);
+		p->c_fill_target = cpu_to_be32(dc->c_fill_target);
+		p->c_max_rate = cpu_to_be32(dc->c_max_rate);
+		put_ldev(mdev);
+	} else {
+		p->resync_rate = cpu_to_be32(DRBD_RESYNC_RATE_DEF);
+		p->c_plan_ahead = cpu_to_be32(DRBD_C_PLAN_AHEAD_DEF);
+		p->c_delay_target = cpu_to_be32(DRBD_C_DELAY_TARGET_DEF);
+		p->c_fill_target = cpu_to_be32(DRBD_C_FILL_TARGET_DEF);
+		p->c_max_rate = cpu_to_be32(DRBD_C_MAX_RATE_DEF);
+	}
 
-	mutex_unlock(&mdev->data.mutex);
+	if (apv >= 88)
+		strcpy(p->verify_alg, nc->verify_alg);
+	if (apv >= 89)
+		strcpy(p->csums_alg, nc->csums_alg);
+	rcu_read_unlock();
 
-	return rv;
+	return drbd_send_command(mdev, sock, cmd, size, NULL, 0);
 }
 
-int drbd_send_protocol(struct drbd_conf *mdev)
+int __drbd_send_protocol(struct drbd_tconn *tconn, enum drbd_packet cmd)
 {
+	struct drbd_socket *sock;
 	struct p_protocol *p;
-	int size, cf, rv;
+	struct net_conf *nc;
+	int size, cf;
 
-	size = sizeof(struct p_protocol);
+	sock = &tconn->data;
+	p = __conn_prepare_command(tconn, sock);
+	if (!p)
+		return -EIO;
 
-	if (mdev->agreed_pro_version >= 87)
-		size += strlen(mdev->net_conf->integrity_alg) + 1;
+	rcu_read_lock();
+	nc = rcu_dereference(tconn->net_conf);
 
-	/* we must not recurse into our own queue,
-	 * as that is blocked during handshake */
-	p = kmalloc(size, GFP_NOIO);
-	if (p == NULL)
-		return 0;
+	if (nc->tentative && tconn->agreed_pro_version < 92) {
+		rcu_read_unlock();
+		mutex_unlock(&sock->mutex);
+		conn_err(tconn, "--dry-run is not supported by peer");
+		return -EOPNOTSUPP;
+	}
 
-	p->protocol      = cpu_to_be32(mdev->net_conf->wire_protocol);
-	p->after_sb_0p   = cpu_to_be32(mdev->net_conf->after_sb_0p);
-	p->after_sb_1p   = cpu_to_be32(mdev->net_conf->after_sb_1p);
-	p->after_sb_2p   = cpu_to_be32(mdev->net_conf->after_sb_2p);
-	p->two_primaries = cpu_to_be32(mdev->net_conf->two_primaries);
+	size = sizeof(*p);
+	if (tconn->agreed_pro_version >= 87)
+		size += strlen(nc->integrity_alg) + 1;
 
+	p->protocol      = cpu_to_be32(nc->wire_protocol);
+	p->after_sb_0p   = cpu_to_be32(nc->after_sb_0p);
+	p->after_sb_1p   = cpu_to_be32(nc->after_sb_1p);
+	p->after_sb_2p   = cpu_to_be32(nc->after_sb_2p);
+	p->two_primaries = cpu_to_be32(nc->two_primaries);
 	cf = 0;
-	if (mdev->net_conf->want_lose)
-		cf |= CF_WANT_LOSE;
-	if (mdev->net_conf->dry_run) {
-		if (mdev->agreed_pro_version >= 92)
-			cf |= CF_DRY_RUN;
-		else {
-			dev_err(DEV, "--dry-run is not supported by peer");
-			kfree(p);
-			return -1;
-		}
-	}
+	if (nc->discard_my_data)
+		cf |= CF_DISCARD_MY_DATA;
+	if (nc->tentative)
+		cf |= CF_DRY_RUN;
 	p->conn_flags    = cpu_to_be32(cf);
 
-	if (mdev->agreed_pro_version >= 87)
-		strcpy(p->integrity_alg, mdev->net_conf->integrity_alg);
+	if (tconn->agreed_pro_version >= 87)
+		strcpy(p->integrity_alg, nc->integrity_alg);
+	rcu_read_unlock();
 
-	rv = drbd_send_cmd(mdev, USE_DATA_SOCKET, P_PROTOCOL,
-			   (struct p_header80 *)p, size);
-	kfree(p);
-	return rv;
+	return __conn_send_command(tconn, sock, cmd, size, NULL, 0);
+}
+
+int drbd_send_protocol(struct drbd_tconn *tconn)
+{
+	int err;
+
+	mutex_lock(&tconn->data.mutex);
+	err = __drbd_send_protocol(tconn, P_PROTOCOL);
+	mutex_unlock(&tconn->data.mutex);
+
+	return err;
 }
 
 int _drbd_send_uuids(struct drbd_conf *mdev, u64 uuid_flags)
 {
-	struct p_uuids p;
+	struct drbd_socket *sock;
+	struct p_uuids *p;
 	int i;
 
 	if (!get_ldev_if_state(mdev, D_NEGOTIATING))
-		return 1;
+		return 0;
 
+	sock = &mdev->tconn->data;
+	p = drbd_prepare_command(mdev, sock);
+	if (!p) {
+		put_ldev(mdev);
+		return -EIO;
+	}
+	spin_lock_irq(&mdev->ldev->md.uuid_lock);
 	for (i = UI_CURRENT; i < UI_SIZE; i++)
-		p.uuid[i] = mdev->ldev ? cpu_to_be64(mdev->ldev->md.uuid[i]) : 0;
+		p->uuid[i] = mdev->ldev ? cpu_to_be64(mdev->ldev->md.uuid[i]) : 0;
+	spin_unlock_irq(&mdev->ldev->md.uuid_lock);
 
 	mdev->comm_bm_set = drbd_bm_total_weight(mdev);
-	p.uuid[UI_SIZE] = cpu_to_be64(mdev->comm_bm_set);
-	uuid_flags |= mdev->net_conf->want_lose ? 1 : 0;
+	p->uuid[UI_SIZE] = cpu_to_be64(mdev->comm_bm_set);
+	rcu_read_lock();
+	uuid_flags |= rcu_dereference(mdev->tconn->net_conf)->discard_my_data ? 1 : 0;
+	rcu_read_unlock();
 	uuid_flags |= test_bit(CRASHED_PRIMARY, &mdev->flags) ? 2 : 0;
 	uuid_flags |= mdev->new_state_tmp.disk == D_INCONSISTENT ? 4 : 0;
-	p.uuid[UI_FLAGS] = cpu_to_be64(uuid_flags);
+	p->uuid[UI_FLAGS] = cpu_to_be64(uuid_flags);
 
 	put_ldev(mdev);
-
-	return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_UUIDS,
-			     (struct p_header80 *)&p, sizeof(p));
+	return drbd_send_command(mdev, sock, P_UUIDS, sizeof(*p), NULL, 0);
 }
 
 int drbd_send_uuids(struct drbd_conf *mdev)
@@ -2169,9 +884,10 @@ void drbd_print_uuids(struct drbd_conf *mdev, const char *text)
 	}
 }
 
-int drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev)
+void drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev)
 {
-	struct p_rs_uuid p;
+	struct drbd_socket *sock;
+	struct p_rs_uuid *p;
 	u64 uuid;
 
 	D_ASSERT(mdev->state.disk == D_UP_TO_DATE);
@@ -2184,24 +900,29 @@ int drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev)
 	drbd_uuid_set(mdev, UI_BITMAP, uuid);
 	drbd_print_uuids(mdev, "updated sync UUID");
 	drbd_md_sync(mdev);
-	p.uuid = cpu_to_be64(uuid);
 
-	return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_SYNC_UUID,
-			     (struct p_header80 *)&p, sizeof(p));
+	sock = &mdev->tconn->data;
+	p = drbd_prepare_command(mdev, sock);
+	if (p) {
+		p->uuid = cpu_to_be64(uuid);
+		drbd_send_command(mdev, sock, P_SYNC_UUID, sizeof(*p), NULL, 0);
+	}
 }
 
 int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags flags)
 {
-	struct p_sizes p;
+	struct drbd_socket *sock;
+	struct p_sizes *p;
 	sector_t d_size, u_size;
 	int q_order_type;
 	unsigned int max_bio_size;
-	int ok;
 
 	if (get_ldev_if_state(mdev, D_NEGOTIATING)) {
 		D_ASSERT(mdev->ldev->backing_bdev);
 		d_size = drbd_get_max_capacity(mdev->ldev);
-		u_size = mdev->ldev->dc.disk_size;
+		rcu_read_lock();
+		u_size = rcu_dereference(mdev->ldev->disk_conf)->disk_size;
+		rcu_read_unlock();
 		q_order_type = drbd_queue_order_type(mdev);
 		max_bio_size = queue_max_hw_sectors(mdev->ldev->backing_bdev->bd_disk->queue) << 9;
 		max_bio_size = min(max_bio_size, DRBD_MAX_BIO_SIZE);
@@ -2213,20 +934,23 @@ int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags fl
 		max_bio_size = DRBD_MAX_BIO_SIZE; /* ... multiple BIOs per peer_request */
 	}
 
-	/* Never allow old drbd (up to 8.3.7) to see more than 32KiB */
-	if (mdev->agreed_pro_version <= 94)
-		max_bio_size = min(max_bio_size, DRBD_MAX_SIZE_H80_PACKET);
+	sock = &mdev->tconn->data;
+	p = drbd_prepare_command(mdev, sock);
+	if (!p)
+		return -EIO;
 
-	p.d_size = cpu_to_be64(d_size);
-	p.u_size = cpu_to_be64(u_size);
-	p.c_size = cpu_to_be64(trigger_reply ? 0 : drbd_get_capacity(mdev->this_bdev));
-	p.max_bio_size = cpu_to_be32(max_bio_size);
-	p.queue_order_type = cpu_to_be16(q_order_type);
-	p.dds_flags = cpu_to_be16(flags);
+	if (mdev->tconn->agreed_pro_version <= 94)
+		max_bio_size = min(max_bio_size, DRBD_MAX_SIZE_H80_PACKET);
+	else if (mdev->tconn->agreed_pro_version < 100)
+		max_bio_size = min(max_bio_size, DRBD_MAX_BIO_SIZE_P95);
 
-	ok = drbd_send_cmd(mdev, USE_DATA_SOCKET, P_SIZES,
-			   (struct p_header80 *)&p, sizeof(p));
-	return ok;
+	p->d_size = cpu_to_be64(d_size);
+	p->u_size = cpu_to_be64(u_size);
+	p->c_size = cpu_to_be64(trigger_reply ? 0 : drbd_get_capacity(mdev->this_bdev));
+	p->max_bio_size = cpu_to_be32(max_bio_size);
+	p->queue_order_type = cpu_to_be16(q_order_type);
+	p->dds_flags = cpu_to_be16(flags);
+	return drbd_send_command(mdev, sock, P_SIZES, sizeof(*p), NULL, 0);
 }
 
 /**
@@ -2235,34 +959,21 @@ int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags fl
  */
 int drbd_send_current_state(struct drbd_conf *mdev)
 {
-	struct socket *sock;
-	struct p_state p;
-	int ok = 0;
-
-	/* Grab state lock so we wont send state if we're in the middle
-	 * of a cluster wide state change on another thread */
-	drbd_state_lock(mdev);
-
-	mutex_lock(&mdev->data.mutex);
-
-	p.state = cpu_to_be32(mdev->state.i); /* Within the send mutex */
-	sock = mdev->data.socket;
+	struct drbd_socket *sock;
+	struct p_state *p;
 
-	if (likely(sock != NULL)) {
-		ok = _drbd_send_cmd(mdev, sock, P_STATE,
-				    (struct p_header80 *)&p, sizeof(p), 0);
-	}
-
-	mutex_unlock(&mdev->data.mutex);
-
-	drbd_state_unlock(mdev);
-	return ok;
+	sock = &mdev->tconn->data;
+	p = drbd_prepare_command(mdev, sock);
+	if (!p)
+		return -EIO;
+	p->state = cpu_to_be32(mdev->state.i); /* Within the send mutex */
+	return drbd_send_command(mdev, sock, P_STATE, sizeof(*p), NULL, 0);
 }
 
 /**
  * drbd_send_state() - After a state change, sends the new state to the peer
- * @mdev:	DRBD device.
- * @state:	the state to send, not necessarily the current state.
+ * @mdev:      DRBD device.
+ * @state:     the state to send, not necessarily the current state.
  *
  * Each state change queues an "after_state_ch" work, which will eventually
  * send the resulting new state to the peer. If more state changes happen
@@ -2271,50 +982,95 @@ int drbd_send_current_state(struct drbd_conf *mdev)
  */
 int drbd_send_state(struct drbd_conf *mdev, union drbd_state state)
 {
-	struct socket *sock;
-	struct p_state p;
-	int ok = 0;
+	struct drbd_socket *sock;
+	struct p_state *p;
 
-	mutex_lock(&mdev->data.mutex);
+	sock = &mdev->tconn->data;
+	p = drbd_prepare_command(mdev, sock);
+	if (!p)
+		return -EIO;
+	p->state = cpu_to_be32(state.i); /* Within the send mutex */
+	return drbd_send_command(mdev, sock, P_STATE, sizeof(*p), NULL, 0);
+}
 
-	p.state = cpu_to_be32(state.i);
-	sock = mdev->data.socket;
+int drbd_send_state_req(struct drbd_conf *mdev, union drbd_state mask, union drbd_state val)
+{
+	struct drbd_socket *sock;
+	struct p_req_state *p;
 
-	if (likely(sock != NULL)) {
-		ok = _drbd_send_cmd(mdev, sock, P_STATE,
-				    (struct p_header80 *)&p, sizeof(p), 0);
-	}
+	sock = &mdev->tconn->data;
+	p = drbd_prepare_command(mdev, sock);
+	if (!p)
+		return -EIO;
+	p->mask = cpu_to_be32(mask.i);
+	p->val = cpu_to_be32(val.i);
+	return drbd_send_command(mdev, sock, P_STATE_CHG_REQ, sizeof(*p), NULL, 0);
+}
 
-	mutex_unlock(&mdev->data.mutex);
+int conn_send_state_req(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val)
+{
+	enum drbd_packet cmd;
+	struct drbd_socket *sock;
+	struct p_req_state *p;
 
-	return ok;
+	cmd = tconn->agreed_pro_version < 100 ? P_STATE_CHG_REQ : P_CONN_ST_CHG_REQ;
+	sock = &tconn->data;
+	p = conn_prepare_command(tconn, sock);
+	if (!p)
+		return -EIO;
+	p->mask = cpu_to_be32(mask.i);
+	p->val = cpu_to_be32(val.i);
+	return conn_send_command(tconn, sock, cmd, sizeof(*p), NULL, 0);
 }
 
-int drbd_send_state_req(struct drbd_conf *mdev,
-	union drbd_state mask, union drbd_state val)
+void drbd_send_sr_reply(struct drbd_conf *mdev, enum drbd_state_rv retcode)
 {
-	struct p_req_state p;
+	struct drbd_socket *sock;
+	struct p_req_state_reply *p;
+
+	sock = &mdev->tconn->meta;
+	p = drbd_prepare_command(mdev, sock);
+	if (p) {
+		p->retcode = cpu_to_be32(retcode);
+		drbd_send_command(mdev, sock, P_STATE_CHG_REPLY, sizeof(*p), NULL, 0);
+	}
+}
 
-	p.mask    = cpu_to_be32(mask.i);
-	p.val     = cpu_to_be32(val.i);
+void conn_send_sr_reply(struct drbd_tconn *tconn, enum drbd_state_rv retcode)
+{
+	struct drbd_socket *sock;
+	struct p_req_state_reply *p;
+	enum drbd_packet cmd = tconn->agreed_pro_version < 100 ? P_STATE_CHG_REPLY : P_CONN_ST_CHG_REPLY;
 
-	return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_STATE_CHG_REQ,
-			     (struct p_header80 *)&p, sizeof(p));
+	sock = &tconn->meta;
+	p = conn_prepare_command(tconn, sock);
+	if (p) {
+		p->retcode = cpu_to_be32(retcode);
+		conn_send_command(tconn, sock, cmd, sizeof(*p), NULL, 0);
+	}
 }
 
-int drbd_send_sr_reply(struct drbd_conf *mdev, enum drbd_state_rv retcode)
+static void dcbp_set_code(struct p_compressed_bm *p, enum drbd_bitmap_code code)
 {
-	struct p_req_state_reply p;
+	BUG_ON(code & ~0xf);
+	p->encoding = (p->encoding & ~0xf) | code;
+}
 
-	p.retcode    = cpu_to_be32(retcode);
+static void dcbp_set_start(struct p_compressed_bm *p, int set)
+{
+	p->encoding = (p->encoding & ~0x80) | (set ? 0x80 : 0);
+}
 
-	return drbd_send_cmd(mdev, USE_META_SOCKET, P_STATE_CHG_REPLY,
-			     (struct p_header80 *)&p, sizeof(p));
+static void dcbp_set_pad_bits(struct p_compressed_bm *p, int n)
+{
+	BUG_ON(n & ~0x7);
+	p->encoding = (p->encoding & (~0x7 << 4)) | (n << 4);
 }
 
 int fill_bitmap_rle_bits(struct drbd_conf *mdev,
-	struct p_compressed_bm *p,
-	struct bm_xfer_ctx *c)
+			 struct p_compressed_bm *p,
+			 unsigned int size,
+			 struct bm_xfer_ctx *c)
 {
 	struct bitstream bs;
 	unsigned long plain_bits;
@@ -2322,19 +1078,21 @@ int fill_bitmap_rle_bits(struct drbd_conf *mdev,
 	unsigned long rl;
 	unsigned len;
 	unsigned toggle;
-	int bits;
+	int bits, use_rle;
 
 	/* may we use this feature? */
-	if ((mdev->sync_conf.use_rle == 0) ||
-		(mdev->agreed_pro_version < 90))
-			return 0;
+	rcu_read_lock();
+	use_rle = rcu_dereference(mdev->tconn->net_conf)->use_rle;
+	rcu_read_unlock();
+	if (!use_rle || mdev->tconn->agreed_pro_version < 90)
+		return 0;
 
 	if (c->bit_offset >= c->bm_bits)
 		return 0; /* nothing to do. */
 
 	/* use at most thus many bytes */
-	bitstream_init(&bs, p->code, BM_PACKET_VLI_BYTES_MAX, 0);
-	memset(p->code, 0, BM_PACKET_VLI_BYTES_MAX);
+	bitstream_init(&bs, p->code, size, 0);
+	memset(p->code, 0, size);
 	/* plain bits covered in this code string */
 	plain_bits = 0;
 
@@ -2356,12 +1114,12 @@ int fill_bitmap_rle_bits(struct drbd_conf *mdev,
 			if (rl == 0) {
 				/* the first checked bit was set,
 				 * store start value, */
-				DCBP_set_start(p, 1);
+				dcbp_set_start(p, 1);
 				/* but skip encoding of zero run length */
 				toggle = !toggle;
 				continue;
 			}
-			DCBP_set_start(p, 0);
+			dcbp_set_start(p, 0);
 		}
 
 		/* paranoia: catch zero runlength.
@@ -2401,7 +1159,7 @@ int fill_bitmap_rle_bits(struct drbd_conf *mdev,
 	bm_xfer_ctx_bit_to_word_offset(c);
 
 	/* store pad_bits */
-	DCBP_set_pad_bits(p, (8 - bs.cur.bit) & 0x7);
+	dcbp_set_pad_bits(p, (8 - bs.cur.bit) & 0x7);
 
 	return len;
 }
@@ -2413,48 +1171,52 @@ int fill_bitmap_rle_bits(struct drbd_conf *mdev,
  * code upon failure.
  */
 static int
-send_bitmap_rle_or_plain(struct drbd_conf *mdev,
-			 struct p_header80 *h, struct bm_xfer_ctx *c)
+send_bitmap_rle_or_plain(struct drbd_conf *mdev, struct bm_xfer_ctx *c)
 {
-	struct p_compressed_bm *p = (void*)h;
-	unsigned long num_words;
-	int len;
-	int ok;
-
-	len = fill_bitmap_rle_bits(mdev, p, c);
+	struct drbd_socket *sock = &mdev->tconn->data;
+	unsigned int header_size = drbd_header_size(mdev->tconn);
+	struct p_compressed_bm *p = sock->sbuf + header_size;
+	int len, err;
 
+	len = fill_bitmap_rle_bits(mdev, p,
+			DRBD_SOCKET_BUFFER_SIZE - header_size - sizeof(*p), c);
 	if (len < 0)
 		return -EIO;
 
 	if (len) {
-		DCBP_set_code(p, RLE_VLI_Bits);
-		ok = _drbd_send_cmd(mdev, mdev->data.socket, P_COMPRESSED_BITMAP, h,
-			sizeof(*p) + len, 0);
-
+		dcbp_set_code(p, RLE_VLI_Bits);
+		err = __send_command(mdev->tconn, mdev->vnr, sock,
+				     P_COMPRESSED_BITMAP, sizeof(*p) + len,
+				     NULL, 0);
 		c->packets[0]++;
-		c->bytes[0] += sizeof(*p) + len;
+		c->bytes[0] += header_size + sizeof(*p) + len;
 
 		if (c->bit_offset >= c->bm_bits)
 			len = 0; /* DONE */
 	} else {
 		/* was not compressible.
 		 * send a buffer full of plain text bits instead. */
-		num_words = min_t(size_t, BM_PACKET_WORDS, c->bm_words - c->word_offset);
-		len = num_words * sizeof(long);
+		unsigned int data_size;
+		unsigned long num_words;
+		unsigned long *p = sock->sbuf + header_size;
+
+		data_size = DRBD_SOCKET_BUFFER_SIZE - header_size;
+		num_words = min_t(size_t, data_size / sizeof(*p),
+				  c->bm_words - c->word_offset);
+		len = num_words * sizeof(*p);
 		if (len)
-			drbd_bm_get_lel(mdev, c->word_offset, num_words, (unsigned long*)h->payload);
-		ok = _drbd_send_cmd(mdev, mdev->data.socket, P_BITMAP,
-				   h, sizeof(struct p_header80) + len, 0);
+			drbd_bm_get_lel(mdev, c->word_offset, num_words, p);
+		err = __send_command(mdev->tconn, mdev->vnr, sock, P_BITMAP, len, NULL, 0);
 		c->word_offset += num_words;
 		c->bit_offset = c->word_offset * BITS_PER_LONG;
 
 		c->packets[1]++;
-		c->bytes[1] += sizeof(struct p_header80) + len;
+		c->bytes[1] += header_size + len;
 
 		if (c->bit_offset > c->bm_bits)
 			c->bit_offset = c->bm_bits;
 	}
-	if (ok) {
+	if (!err) {
 		if (len == 0) {
 			INFO_bm_xfer_stats(mdev, "send", c);
 			return 0;
@@ -2465,21 +1227,13 @@ send_bitmap_rle_or_plain(struct drbd_conf *mdev,
 }
 
 /* See the comment at receive_bitmap() */
-int _drbd_send_bitmap(struct drbd_conf *mdev)
+static int _drbd_send_bitmap(struct drbd_conf *mdev)
 {
 	struct bm_xfer_ctx c;
-	struct p_header80 *p;
 	int err;
 
-	ERR_IF(!mdev->bitmap) return false;
-
-	/* maybe we should use some per thread scratch page,
-	 * and allocate that during initial device creation? */
-	p = (struct p_header80 *) __get_free_page(GFP_NOIO);
-	if (!p) {
-		dev_err(DEV, "failed to allocate one page buffer in %s\n", __func__);
+	if (!expect(mdev->bitmap))
 		return false;
-	}
 
 	if (get_ldev(mdev)) {
 		if (drbd_md_test_flag(mdev->ldev, MDF_FULL_SYNC)) {
@@ -2504,37 +1258,39 @@ int _drbd_send_bitmap(struct drbd_conf *mdev)
 	};
 
 	do {
-		err = send_bitmap_rle_or_plain(mdev, p, &c);
+		err = send_bitmap_rle_or_plain(mdev, &c);
 	} while (err > 0);
 
-	free_page((unsigned long) p);
 	return err == 0;
 }
 
 int drbd_send_bitmap(struct drbd_conf *mdev)
 {
-	int err;
+	struct drbd_socket *sock = &mdev->tconn->data;
+	int err = -1;
 
-	if (!drbd_get_data_sock(mdev))
-		return -1;
-	err = !_drbd_send_bitmap(mdev);
-	drbd_put_data_sock(mdev);
+	mutex_lock(&sock->mutex);
+	if (sock->socket)
+		err = !_drbd_send_bitmap(mdev);
+	mutex_unlock(&sock->mutex);
 	return err;
 }
 
-int drbd_send_b_ack(struct drbd_conf *mdev, u32 barrier_nr, u32 set_size)
+void drbd_send_b_ack(struct drbd_tconn *tconn, u32 barrier_nr, u32 set_size)
 {
-	int ok;
-	struct p_barrier_ack p;
+	struct drbd_socket *sock;
+	struct p_barrier_ack *p;
 
-	p.barrier  = barrier_nr;
-	p.set_size = cpu_to_be32(set_size);
+	if (tconn->cstate < C_WF_REPORT_PARAMS)
+		return;
 
-	if (mdev->state.conn < C_CONNECTED)
-		return false;
-	ok = drbd_send_cmd(mdev, USE_META_SOCKET, P_BARRIER_ACK,
-			(struct p_header80 *)&p, sizeof(p));
-	return ok;
+	sock = &tconn->meta;
+	p = conn_prepare_command(tconn, sock);
+	if (!p)
+		return;
+	p->barrier = barrier_nr;
+	p->set_size = cpu_to_be32(set_size);
+	conn_send_command(tconn, sock, P_BARRIER_ACK, sizeof(*p), NULL, 0);
 }
 
 /**
@@ -2545,62 +1301,62 @@ int drbd_send_b_ack(struct drbd_conf *mdev, u32 barrier_nr, u32 set_size)
  * @blksize:	size in byte, needs to be in big endian byte order
  * @block_id:	Id, big endian byte order
  */
-static int _drbd_send_ack(struct drbd_conf *mdev, enum drbd_packets cmd,
-			  u64 sector,
-			  u32 blksize,
-			  u64 block_id)
+static int _drbd_send_ack(struct drbd_conf *mdev, enum drbd_packet cmd,
+			  u64 sector, u32 blksize, u64 block_id)
 {
-	int ok;
-	struct p_block_ack p;
+	struct drbd_socket *sock;
+	struct p_block_ack *p;
 
-	p.sector   = sector;
-	p.block_id = block_id;
-	p.blksize  = blksize;
-	p.seq_num  = cpu_to_be32(atomic_add_return(1, &mdev->packet_seq));
+	if (mdev->state.conn < C_CONNECTED)
+		return -EIO;
 
-	if (!mdev->meta.socket || mdev->state.conn < C_CONNECTED)
-		return false;
-	ok = drbd_send_cmd(mdev, USE_META_SOCKET, cmd,
-				(struct p_header80 *)&p, sizeof(p));
-	return ok;
+	sock = &mdev->tconn->meta;
+	p = drbd_prepare_command(mdev, sock);
+	if (!p)
+		return -EIO;
+	p->sector = sector;
+	p->block_id = block_id;
+	p->blksize = blksize;
+	p->seq_num = cpu_to_be32(atomic_inc_return(&mdev->packet_seq));
+	return drbd_send_command(mdev, sock, cmd, sizeof(*p), NULL, 0);
 }
 
 /* dp->sector and dp->block_id already/still in network byte order,
  * data_size is payload size according to dp->head,
  * and may need to be corrected for digest size. */
-int drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packets cmd,
-		     struct p_data *dp, int data_size)
+void drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packet cmd,
+		      struct p_data *dp, int data_size)
 {
-	data_size -= (mdev->agreed_pro_version >= 87 && mdev->integrity_r_tfm) ?
-		crypto_hash_digestsize(mdev->integrity_r_tfm) : 0;
-	return _drbd_send_ack(mdev, cmd, dp->sector, cpu_to_be32(data_size),
-			      dp->block_id);
+	if (mdev->tconn->peer_integrity_tfm)
+		data_size -= crypto_hash_digestsize(mdev->tconn->peer_integrity_tfm);
+	_drbd_send_ack(mdev, cmd, dp->sector, cpu_to_be32(data_size),
+		       dp->block_id);
 }
 
-int drbd_send_ack_rp(struct drbd_conf *mdev, enum drbd_packets cmd,
-		     struct p_block_req *rp)
+void drbd_send_ack_rp(struct drbd_conf *mdev, enum drbd_packet cmd,
+		      struct p_block_req *rp)
 {
-	return _drbd_send_ack(mdev, cmd, rp->sector, rp->blksize, rp->block_id);
+	_drbd_send_ack(mdev, cmd, rp->sector, rp->blksize, rp->block_id);
 }
 
 /**
  * drbd_send_ack() - Sends an ack packet
- * @mdev:	DRBD device.
- * @cmd:	Packet command code.
- * @e:		Epoch entry.
+ * @mdev:	DRBD device
+ * @cmd:	packet command code
+ * @peer_req:	peer request
  */
-int drbd_send_ack(struct drbd_conf *mdev,
-	enum drbd_packets cmd, struct drbd_epoch_entry *e)
+int drbd_send_ack(struct drbd_conf *mdev, enum drbd_packet cmd,
+		  struct drbd_peer_request *peer_req)
 {
 	return _drbd_send_ack(mdev, cmd,
-			      cpu_to_be64(e->sector),
-			      cpu_to_be32(e->size),
-			      e->block_id);
+			      cpu_to_be64(peer_req->i.sector),
+			      cpu_to_be32(peer_req->i.size),
+			      peer_req->block_id);
 }
 
 /* This function misuses the block_id field to signal if the blocks
  * are is sync or not. */
-int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packets cmd,
+int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packet cmd,
 		     sector_t sector, int blksize, u64 block_id)
 {
 	return _drbd_send_ack(mdev, cmd,
@@ -2612,85 +1368,87 @@ int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packets cmd,
 int drbd_send_drequest(struct drbd_conf *mdev, int cmd,
 		       sector_t sector, int size, u64 block_id)
 {
-	int ok;
-	struct p_block_req p;
+	struct drbd_socket *sock;
+	struct p_block_req *p;
 
-	p.sector   = cpu_to_be64(sector);
-	p.block_id = block_id;
-	p.blksize  = cpu_to_be32(size);
-
-	ok = drbd_send_cmd(mdev, USE_DATA_SOCKET, cmd,
-				(struct p_header80 *)&p, sizeof(p));
-	return ok;
-}
-
-int drbd_send_drequest_csum(struct drbd_conf *mdev,
-			    sector_t sector, int size,
-			    void *digest, int digest_size,
-			    enum drbd_packets cmd)
-{
-	int ok;
-	struct p_block_req p;
-
-	p.sector   = cpu_to_be64(sector);
-	p.block_id = BE_DRBD_MAGIC + 0xbeef;
-	p.blksize  = cpu_to_be32(size);
-
-	p.head.magic   = BE_DRBD_MAGIC;
-	p.head.command = cpu_to_be16(cmd);
-	p.head.length  = cpu_to_be16(sizeof(p) - sizeof(struct p_header80) + digest_size);
-
-	mutex_lock(&mdev->data.mutex);
+	sock = &mdev->tconn->data;
+	p = drbd_prepare_command(mdev, sock);
+	if (!p)
+		return -EIO;
+	p->sector = cpu_to_be64(sector);
+	p->block_id = block_id;
+	p->blksize = cpu_to_be32(size);
+	return drbd_send_command(mdev, sock, cmd, sizeof(*p), NULL, 0);
+}
 
-	ok = (sizeof(p) == drbd_send(mdev, mdev->data.socket, &p, sizeof(p), 0));
-	ok = ok && (digest_size == drbd_send(mdev, mdev->data.socket, digest, digest_size, 0));
+int drbd_send_drequest_csum(struct drbd_conf *mdev, sector_t sector, int size,
+			    void *digest, int digest_size, enum drbd_packet cmd)
+{
+	struct drbd_socket *sock;
+	struct p_block_req *p;
 
-	mutex_unlock(&mdev->data.mutex);
+	/* FIXME: Put the digest into the preallocated socket buffer.  */
 
-	return ok;
+	sock = &mdev->tconn->data;
+	p = drbd_prepare_command(mdev, sock);
+	if (!p)
+		return -EIO;
+	p->sector = cpu_to_be64(sector);
+	p->block_id = ID_SYNCER /* unused */;
+	p->blksize = cpu_to_be32(size);
+	return drbd_send_command(mdev, sock, cmd, sizeof(*p),
+				 digest, digest_size);
 }
 
 int drbd_send_ov_request(struct drbd_conf *mdev, sector_t sector, int size)
 {
-	int ok;
-	struct p_block_req p;
-
-	p.sector   = cpu_to_be64(sector);
-	p.block_id = BE_DRBD_MAGIC + 0xbabe;
-	p.blksize  = cpu_to_be32(size);
+	struct drbd_socket *sock;
+	struct p_block_req *p;
 
-	ok = drbd_send_cmd(mdev, USE_DATA_SOCKET, P_OV_REQUEST,
-			   (struct p_header80 *)&p, sizeof(p));
-	return ok;
+	sock = &mdev->tconn->data;
+	p = drbd_prepare_command(mdev, sock);
+	if (!p)
+		return -EIO;
+	p->sector = cpu_to_be64(sector);
+	p->block_id = ID_SYNCER /* unused */;
+	p->blksize = cpu_to_be32(size);
+	return drbd_send_command(mdev, sock, P_OV_REQUEST, sizeof(*p), NULL, 0);
 }
 
 /* called on sndtimeo
  * returns false if we should retry,
  * true if we think connection is dead
  */
-static int we_should_drop_the_connection(struct drbd_conf *mdev, struct socket *sock)
+static int we_should_drop_the_connection(struct drbd_tconn *tconn, struct socket *sock)
 {
 	int drop_it;
 	/* long elapsed = (long)(jiffies - mdev->last_received); */
 
-	drop_it =   mdev->meta.socket == sock
-		|| !mdev->asender.task
-		|| get_t_state(&mdev->asender) != Running
-		|| mdev->state.conn < C_CONNECTED;
+	drop_it =   tconn->meta.socket == sock
+		|| !tconn->asender.task
+		|| get_t_state(&tconn->asender) != RUNNING
+		|| tconn->cstate < C_WF_REPORT_PARAMS;
 
 	if (drop_it)
 		return true;
 
-	drop_it = !--mdev->ko_count;
+	drop_it = !--tconn->ko_count;
 	if (!drop_it) {
-		dev_err(DEV, "[%s/%d] sock_sendmsg time expired, ko = %u\n",
-		       current->comm, current->pid, mdev->ko_count);
-		request_ping(mdev);
+		conn_err(tconn, "[%s/%d] sock_sendmsg time expired, ko = %u\n",
+			 current->comm, current->pid, tconn->ko_count);
+		request_ping(tconn);
 	}
 
 	return drop_it; /* && (mdev->state == R_PRIMARY) */;
 }
 
+static void drbd_update_congested(struct drbd_tconn *tconn)
+{
+	struct sock *sk = tconn->data.socket->sk;
+	if (sk->sk_wmem_queued > sk->sk_sndbuf * 4 / 5)
+		set_bit(NET_CONGESTED, &tconn->flags);
+}
+
 /* The idea of sendpage seems to be to put some kind of reference
  * to the page into the skb, and to hand it over to the NIC. In
  * this process get_page() gets called.
@@ -2713,21 +1471,28 @@ static int we_should_drop_the_connection(struct drbd_conf *mdev, struct socket *
  * with page_count == 0 or PageSlab.
  */
 static int _drbd_no_send_page(struct drbd_conf *mdev, struct page *page,
-		   int offset, size_t size, unsigned msg_flags)
+			      int offset, size_t size, unsigned msg_flags)
 {
-	int sent = drbd_send(mdev, mdev->data.socket, kmap(page) + offset, size, msg_flags);
+	struct socket *socket;
+	void *addr;
+	int err;
+
+	socket = mdev->tconn->data.socket;
+	addr = kmap(page) + offset;
+	err = drbd_send_all(mdev->tconn, socket, addr, size, msg_flags);
 	kunmap(page);
-	if (sent == size)
-		mdev->send_cnt += size>>9;
-	return sent == size;
+	if (!err)
+		mdev->send_cnt += size >> 9;
+	return err;
 }
 
 static int _drbd_send_page(struct drbd_conf *mdev, struct page *page,
 		    int offset, size_t size, unsigned msg_flags)
 {
+	struct socket *socket = mdev->tconn->data.socket;
 	mm_segment_t oldfs = get_fs();
-	int sent, ok;
 	int len = size;
+	int err = -EIO;
 
 	/* e.g. XFS meta- & log-data is in slab pages, which have a
 	 * page_count of 0 and/or have PageSlab() set.
@@ -2739,34 +1504,35 @@ static int _drbd_send_page(struct drbd_conf *mdev, struct page *page,
 		return _drbd_no_send_page(mdev, page, offset, size, msg_flags);
 
 	msg_flags |= MSG_NOSIGNAL;
-	drbd_update_congested(mdev);
+	drbd_update_congested(mdev->tconn);
 	set_fs(KERNEL_DS);
 	do {
-		sent = mdev->data.socket->ops->sendpage(mdev->data.socket, page,
-							offset, len,
-							msg_flags);
-		if (sent == -EAGAIN) {
-			if (we_should_drop_the_connection(mdev,
-							  mdev->data.socket))
-				break;
-			else
-				continue;
-		}
+		int sent;
+
+		sent = socket->ops->sendpage(socket, page, offset, len, msg_flags);
 		if (sent <= 0) {
+			if (sent == -EAGAIN) {
+				if (we_should_drop_the_connection(mdev->tconn, socket))
+					break;
+				continue;
+			}
 			dev_warn(DEV, "%s: size=%d len=%d sent=%d\n",
 			     __func__, (int)size, len, sent);
+			if (sent < 0)
+				err = sent;
 			break;
 		}
 		len    -= sent;
 		offset += sent;
 	} while (len > 0 /* THINK && mdev->cstate >= C_CONNECTED*/);
 	set_fs(oldfs);
-	clear_bit(NET_CONGESTED, &mdev->flags);
+	clear_bit(NET_CONGESTED, &mdev->tconn->flags);
 
-	ok = (len == 0);
-	if (likely(ok))
-		mdev->send_cnt += size>>9;
-	return ok;
+	if (len == 0) {
+		err = 0;
+		mdev->send_cnt += size >> 9;
+	}
+	return err;
 }
 
 static int _drbd_send_bio(struct drbd_conf *mdev, struct bio *bio)
@@ -2775,12 +1541,15 @@ static int _drbd_send_bio(struct drbd_conf *mdev, struct bio *bio)
 	int i;
 	/* hint all but last page with MSG_MORE */
 	bio_for_each_segment(bvec, bio, i) {
-		if (!_drbd_no_send_page(mdev, bvec->bv_page,
-				     bvec->bv_offset, bvec->bv_len,
-				     i == bio->bi_vcnt -1 ? 0 : MSG_MORE))
-			return 0;
+		int err;
+
+		err = _drbd_no_send_page(mdev, bvec->bv_page,
+					 bvec->bv_offset, bvec->bv_len,
+					 i == bio->bi_vcnt - 1 ? 0 : MSG_MORE);
+		if (err)
+			return err;
 	}
-	return 1;
+	return 0;
 }
 
 static int _drbd_send_zc_bio(struct drbd_conf *mdev, struct bio *bio)
@@ -2789,32 +1558,40 @@ static int _drbd_send_zc_bio(struct drbd_conf *mdev, struct bio *bio)
 	int i;
 	/* hint all but last page with MSG_MORE */
 	bio_for_each_segment(bvec, bio, i) {
-		if (!_drbd_send_page(mdev, bvec->bv_page,
-				     bvec->bv_offset, bvec->bv_len,
-				     i == bio->bi_vcnt -1 ? 0 : MSG_MORE))
-			return 0;
+		int err;
+
+		err = _drbd_send_page(mdev, bvec->bv_page,
+				      bvec->bv_offset, bvec->bv_len,
+				      i == bio->bi_vcnt - 1 ? 0 : MSG_MORE);
+		if (err)
+			return err;
 	}
-	return 1;
+	return 0;
 }
 
-static int _drbd_send_zc_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e)
+static int _drbd_send_zc_ee(struct drbd_conf *mdev,
+			    struct drbd_peer_request *peer_req)
 {
-	struct page *page = e->pages;
-	unsigned len = e->size;
+	struct page *page = peer_req->pages;
+	unsigned len = peer_req->i.size;
+	int err;
+
 	/* hint all but last page with MSG_MORE */
 	page_chain_for_each(page) {
 		unsigned l = min_t(unsigned, len, PAGE_SIZE);
-		if (!_drbd_send_page(mdev, page, 0, l,
-				page_chain_next(page) ? MSG_MORE : 0))
-			return 0;
+
+		err = _drbd_send_page(mdev, page, 0, l,
+				      page_chain_next(page) ? MSG_MORE : 0);
+		if (err)
+			return err;
 		len -= l;
 	}
-	return 1;
+	return 0;
 }
 
 static u32 bio_flags_to_wire(struct drbd_conf *mdev, unsigned long bi_rw)
 {
-	if (mdev->agreed_pro_version >= 95)
+	if (mdev->tconn->agreed_pro_version >= 95)
 		return  (bi_rw & REQ_SYNC ? DP_RW_SYNC : 0) |
 			(bi_rw & REQ_FUA ? DP_FUA : 0) |
 			(bi_rw & REQ_FLUSH ? DP_FLUSH : 0) |
@@ -2828,50 +1605,36 @@ static u32 bio_flags_to_wire(struct drbd_conf *mdev, unsigned long bi_rw)
  */
 int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req)
 {
-	int ok = 1;
-	struct p_data p;
+	struct drbd_socket *sock;
+	struct p_data *p;
 	unsigned int dp_flags = 0;
-	void *dgb;
 	int dgs;
+	int err;
 
-	if (!drbd_get_data_sock(mdev))
-		return 0;
-
-	dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_w_tfm) ?
-		crypto_hash_digestsize(mdev->integrity_w_tfm) : 0;
-
-	if (req->size <= DRBD_MAX_SIZE_H80_PACKET) {
-		p.head.h80.magic   = BE_DRBD_MAGIC;
-		p.head.h80.command = cpu_to_be16(P_DATA);
-		p.head.h80.length  =
-			cpu_to_be16(sizeof(p) - sizeof(union p_header) + dgs + req->size);
-	} else {
-		p.head.h95.magic   = BE_DRBD_MAGIC_BIG;
-		p.head.h95.command = cpu_to_be16(P_DATA);
-		p.head.h95.length  =
-			cpu_to_be32(sizeof(p) - sizeof(union p_header) + dgs + req->size);
-	}
-
-	p.sector   = cpu_to_be64(req->sector);
-	p.block_id = (unsigned long)req;
-	p.seq_num  = cpu_to_be32(atomic_add_return(1, &mdev->packet_seq));
+	sock = &mdev->tconn->data;
+	p = drbd_prepare_command(mdev, sock);
+	dgs = mdev->tconn->integrity_tfm ? crypto_hash_digestsize(mdev->tconn->integrity_tfm) : 0;
 
+	if (!p)
+		return -EIO;
+	p->sector = cpu_to_be64(req->i.sector);
+	p->block_id = (unsigned long)req;
+	p->seq_num = cpu_to_be32(atomic_inc_return(&mdev->packet_seq));
 	dp_flags = bio_flags_to_wire(mdev, req->master_bio->bi_rw);
-
 	if (mdev->state.conn >= C_SYNC_SOURCE &&
 	    mdev->state.conn <= C_PAUSED_SYNC_T)
 		dp_flags |= DP_MAY_SET_IN_SYNC;
-
-	p.dp_flags = cpu_to_be32(dp_flags);
-	set_bit(UNPLUG_REMOTE, &mdev->flags);
-	ok = (sizeof(p) ==
-		drbd_send(mdev, mdev->data.socket, &p, sizeof(p), dgs ? MSG_MORE : 0));
-	if (ok && dgs) {
-		dgb = mdev->int_dig_out;
-		drbd_csum_bio(mdev, mdev->integrity_w_tfm, req->master_bio, dgb);
-		ok = dgs == drbd_send(mdev, mdev->data.socket, dgb, dgs, 0);
-	}
-	if (ok) {
+	if (mdev->tconn->agreed_pro_version >= 100) {
+		if (req->rq_state & RQ_EXP_RECEIVE_ACK)
+			dp_flags |= DP_SEND_RECEIVE_ACK;
+		if (req->rq_state & RQ_EXP_WRITE_ACK)
+			dp_flags |= DP_SEND_WRITE_ACK;
+	}
+	p->dp_flags = cpu_to_be32(dp_flags);
+	if (dgs)
+		drbd_csum_bio(mdev, mdev->tconn->integrity_tfm, req->master_bio, p + 1);
+	err = __send_command(mdev->tconn, mdev->vnr, sock, P_DATA, sizeof(*p) + dgs, NULL, req->i.size);
+	if (!err) {
 		/* For protocol A, we have to memcpy the payload into
 		 * socket buffers, as we may complete right away
 		 * as soon as we handed it over to tcp, at which point the data
@@ -2883,92 +1646,76 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req)
 		 * out ok after sending on this side, but does not fit on the
 		 * receiving side, we sure have detected corruption elsewhere.
 		 */
-		if (mdev->net_conf->wire_protocol == DRBD_PROT_A || dgs)
-			ok = _drbd_send_bio(mdev, req->master_bio);
+		if (!(req->rq_state & (RQ_EXP_RECEIVE_ACK | RQ_EXP_WRITE_ACK)) || dgs)
+			err = _drbd_send_bio(mdev, req->master_bio);
 		else
-			ok = _drbd_send_zc_bio(mdev, req->master_bio);
+			err = _drbd_send_zc_bio(mdev, req->master_bio);
 
 		/* double check digest, sometimes buffers have been modified in flight. */
 		if (dgs > 0 && dgs <= 64) {
 			/* 64 byte, 512 bit, is the largest digest size
 			 * currently supported in kernel crypto. */
 			unsigned char digest[64];
-			drbd_csum_bio(mdev, mdev->integrity_w_tfm, req->master_bio, digest);
-			if (memcmp(mdev->int_dig_out, digest, dgs)) {
+			drbd_csum_bio(mdev, mdev->tconn->integrity_tfm, req->master_bio, digest);
+			if (memcmp(p + 1, digest, dgs)) {
 				dev_warn(DEV,
 					"Digest mismatch, buffer modified by upper layers during write: %llus +%u\n",
-					(unsigned long long)req->sector, req->size);
+					(unsigned long long)req->i.sector, req->i.size);
 			}
 		} /* else if (dgs > 64) {
 		     ... Be noisy about digest too large ...
 		} */
 	}
+	mutex_unlock(&sock->mutex);  /* locked by drbd_prepare_command() */
 
-	drbd_put_data_sock(mdev);
-
-	return ok;
+	return err;
 }
 
 /* answer packet, used to send data back for read requests:
  *  Peer       -> (diskless) R_PRIMARY   (P_DATA_REPLY)
  *  C_SYNC_SOURCE -> C_SYNC_TARGET         (P_RS_DATA_REPLY)
  */
-int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd,
-		    struct drbd_epoch_entry *e)
+int drbd_send_block(struct drbd_conf *mdev, enum drbd_packet cmd,
+		    struct drbd_peer_request *peer_req)
 {
-	int ok;
-	struct p_data p;
-	void *dgb;
+	struct drbd_socket *sock;
+	struct p_data *p;
+	int err;
 	int dgs;
 
-	dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_w_tfm) ?
-		crypto_hash_digestsize(mdev->integrity_w_tfm) : 0;
-
-	if (e->size <= DRBD_MAX_SIZE_H80_PACKET) {
-		p.head.h80.magic   = BE_DRBD_MAGIC;
-		p.head.h80.command = cpu_to_be16(cmd);
-		p.head.h80.length  =
-			cpu_to_be16(sizeof(p) - sizeof(struct p_header80) + dgs + e->size);
-	} else {
-		p.head.h95.magic   = BE_DRBD_MAGIC_BIG;
-		p.head.h95.command = cpu_to_be16(cmd);
-		p.head.h95.length  =
-			cpu_to_be32(sizeof(p) - sizeof(struct p_header80) + dgs + e->size);
-	}
-
-	p.sector   = cpu_to_be64(e->sector);
-	p.block_id = e->block_id;
-	/* p.seq_num  = 0;    No sequence numbers here.. */
-
-	/* Only called by our kernel thread.
-	 * This one may be interrupted by DRBD_SIG and/or DRBD_SIGKILL
-	 * in response to admin command or module unload.
-	 */
-	if (!drbd_get_data_sock(mdev))
-		return 0;
+	sock = &mdev->tconn->data;
+	p = drbd_prepare_command(mdev, sock);
 
-	ok = sizeof(p) == drbd_send(mdev, mdev->data.socket, &p, sizeof(p), dgs ? MSG_MORE : 0);
-	if (ok && dgs) {
-		dgb = mdev->int_dig_out;
-		drbd_csum_ee(mdev, mdev->integrity_w_tfm, e, dgb);
-		ok = dgs == drbd_send(mdev, mdev->data.socket, dgb, dgs, 0);
-	}
-	if (ok)
-		ok = _drbd_send_zc_ee(mdev, e);
+	dgs = mdev->tconn->integrity_tfm ? crypto_hash_digestsize(mdev->tconn->integrity_tfm) : 0;
 
-	drbd_put_data_sock(mdev);
+	if (!p)
+		return -EIO;
+	p->sector = cpu_to_be64(peer_req->i.sector);
+	p->block_id = peer_req->block_id;
+	p->seq_num = 0;  /* unused */
+	p->dp_flags = 0;
+	if (dgs)
+		drbd_csum_ee(mdev, mdev->tconn->integrity_tfm, peer_req, p + 1);
+	err = __send_command(mdev->tconn, mdev->vnr, sock, cmd, sizeof(*p) + dgs, NULL, peer_req->i.size);
+	if (!err)
+		err = _drbd_send_zc_ee(mdev, peer_req);
+	mutex_unlock(&sock->mutex);  /* locked by drbd_prepare_command() */
 
-	return ok;
+	return err;
 }
 
-int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req)
+int drbd_send_out_of_sync(struct drbd_conf *mdev, struct drbd_request *req)
 {
-	struct p_block_desc p;
-
-	p.sector  = cpu_to_be64(req->sector);
-	p.blksize = cpu_to_be32(req->size);
+	struct drbd_socket *sock;
+	struct p_block_desc *p;
 
-	return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_OUT_OF_SYNC, &p.head, sizeof(p));
+	sock = &mdev->tconn->data;
+	p = drbd_prepare_command(mdev, sock);
+	if (!p)
+		return -EIO;
+	p->sector = cpu_to_be64(req->i.sector);
+	p->blksize = cpu_to_be32(req->i.size);
+	return drbd_send_command(mdev, sock, P_OUT_OF_SYNC, sizeof(*p), NULL, 0);
 }
 
 /*
@@ -2987,7 +1734,7 @@ int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req)
 /*
  * you must have down()ed the appropriate [m]sock_mutex elsewhere!
  */
-int drbd_send(struct drbd_conf *mdev, struct socket *sock,
+int drbd_send(struct drbd_tconn *tconn, struct socket *sock,
 	      void *buf, size_t size, unsigned msg_flags)
 {
 	struct kvec iov;
@@ -2995,7 +1742,7 @@ int drbd_send(struct drbd_conf *mdev, struct socket *sock,
 	int rv, sent = 0;
 
 	if (!sock)
-		return -1000;
+		return -EBADR;
 
 	/* THINK  if (signal_pending) return ... ? */
 
@@ -3008,9 +1755,11 @@ int drbd_send(struct drbd_conf *mdev, struct socket *sock,
 	msg.msg_controllen = 0;
 	msg.msg_flags      = msg_flags | MSG_NOSIGNAL;
 
-	if (sock == mdev->data.socket) {
-		mdev->ko_count = mdev->net_conf->ko_count;
-		drbd_update_congested(mdev);
+	if (sock == tconn->data.socket) {
+		rcu_read_lock();
+		tconn->ko_count = rcu_dereference(tconn->net_conf)->ko_count;
+		rcu_read_unlock();
+		drbd_update_congested(tconn);
 	}
 	do {
 		/* STRANGE
@@ -3024,12 +1773,11 @@ int drbd_send(struct drbd_conf *mdev, struct socket *sock,
  */
 		rv = kernel_sendmsg(sock, &msg, &iov, 1, size);
 		if (rv == -EAGAIN) {
-			if (we_should_drop_the_connection(mdev, sock))
+			if (we_should_drop_the_connection(tconn, sock))
 				break;
 			else
 				continue;
 		}
-		D_ASSERT(rv != 0);
 		if (rv == -EINTR) {
 			flush_signals(current);
 			rv = 0;
@@ -3041,22 +1789,40 @@ int drbd_send(struct drbd_conf *mdev, struct socket *sock,
 		iov.iov_len  -= rv;
 	} while (sent < size);
 
-	if (sock == mdev->data.socket)
-		clear_bit(NET_CONGESTED, &mdev->flags);
+	if (sock == tconn->data.socket)
+		clear_bit(NET_CONGESTED, &tconn->flags);
 
 	if (rv <= 0) {
 		if (rv != -EAGAIN) {
-			dev_err(DEV, "%s_sendmsg returned %d\n",
-			    sock == mdev->meta.socket ? "msock" : "sock",
-			    rv);
-			drbd_force_state(mdev, NS(conn, C_BROKEN_PIPE));
+			conn_err(tconn, "%s_sendmsg returned %d\n",
+				 sock == tconn->meta.socket ? "msock" : "sock",
+				 rv);
+			conn_request_state(tconn, NS(conn, C_BROKEN_PIPE), CS_HARD);
 		} else
-			drbd_force_state(mdev, NS(conn, C_TIMEOUT));
+			conn_request_state(tconn, NS(conn, C_TIMEOUT), CS_HARD);
 	}
 
 	return sent;
 }
 
+/**
+ * drbd_send_all  -  Send an entire buffer
+ *
+ * Returns 0 upon success and a negative error value otherwise.
+ */
+int drbd_send_all(struct drbd_tconn *tconn, struct socket *sock, void *buffer,
+		  size_t size, unsigned msg_flags)
+{
+	int err;
+
+	err = drbd_send(tconn, sock, buffer, size, msg_flags);
+	if (err < 0)
+		return err;
+	if (err != size)
+		return -EIO;
+	return 0;
+}
+
 static int drbd_open(struct block_device *bdev, fmode_t mode)
 {
 	struct drbd_conf *mdev = bdev->bd_disk->private_data;
@@ -3064,7 +1830,7 @@ static int drbd_open(struct block_device *bdev, fmode_t mode)
 	int rv = 0;
 
 	mutex_lock(&drbd_main_mutex);
-	spin_lock_irqsave(&mdev->req_lock, flags);
+	spin_lock_irqsave(&mdev->tconn->req_lock, flags);
 	/* to have a stable mdev->state.role
 	 * and no race with updating open_cnt */
 
@@ -3077,7 +1843,7 @@ static int drbd_open(struct block_device *bdev, fmode_t mode)
 
 	if (!rv)
 		mdev->open_cnt++;
-	spin_unlock_irqrestore(&mdev->req_lock, flags);
+	spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
 	mutex_unlock(&drbd_main_mutex);
 
 	return rv;
@@ -3094,35 +1860,14 @@ static int drbd_release(struct gendisk *gd, fmode_t mode)
 
 static void drbd_set_defaults(struct drbd_conf *mdev)
 {
-	/* This way we get a compile error when sync_conf grows,
-	   and we forgot to initialize it here */
-	mdev->sync_conf = (struct syncer_conf) {
-		/* .rate = */		DRBD_RATE_DEF,
-		/* .after = */		DRBD_AFTER_DEF,
-		/* .al_extents = */	DRBD_AL_EXTENTS_DEF,
-		/* .verify_alg = */	{}, 0,
-		/* .cpu_mask = */	{}, 0,
-		/* .csums_alg = */	{}, 0,
-		/* .use_rle = */	0,
-		/* .on_no_data = */	DRBD_ON_NO_DATA_DEF,
-		/* .c_plan_ahead = */	DRBD_C_PLAN_AHEAD_DEF,
-		/* .c_delay_target = */	DRBD_C_DELAY_TARGET_DEF,
-		/* .c_fill_target = */	DRBD_C_FILL_TARGET_DEF,
-		/* .c_max_rate = */	DRBD_C_MAX_RATE_DEF,
-		/* .c_min_rate = */	DRBD_C_MIN_RATE_DEF
-	};
-
-	/* Have to use that way, because the layout differs between
-	   big endian and little endian */
-	mdev->state = (union drbd_state) {
+	/* Beware! The actual layout differs
+	 * between big endian and little endian */
+	mdev->state = (union drbd_dev_state) {
 		{ .role = R_SECONDARY,
 		  .peer = R_UNKNOWN,
 		  .conn = C_STANDALONE,
 		  .disk = D_DISKLESS,
 		  .pdsk = D_UNKNOWN,
-		  .susp = 0,
-		  .susp_nod = 0,
-		  .susp_fen = 0
 		} };
 }
 
@@ -3138,28 +1883,17 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
 	atomic_set(&mdev->rs_pending_cnt, 0);
 	atomic_set(&mdev->unacked_cnt, 0);
 	atomic_set(&mdev->local_cnt, 0);
-	atomic_set(&mdev->net_cnt, 0);
-	atomic_set(&mdev->packet_seq, 0);
-	atomic_set(&mdev->pp_in_use, 0);
 	atomic_set(&mdev->pp_in_use_by_net, 0);
 	atomic_set(&mdev->rs_sect_in, 0);
 	atomic_set(&mdev->rs_sect_ev, 0);
 	atomic_set(&mdev->ap_in_flight, 0);
 	atomic_set(&mdev->md_io_in_use, 0);
 
-	mutex_init(&mdev->data.mutex);
-	mutex_init(&mdev->meta.mutex);
-	sema_init(&mdev->data.work.s, 0);
-	sema_init(&mdev->meta.work.s, 0);
-	mutex_init(&mdev->state_mutex);
-
-	spin_lock_init(&mdev->data.work.q_lock);
-	spin_lock_init(&mdev->meta.work.q_lock);
+	mutex_init(&mdev->own_state_mutex);
+	mdev->state_mutex = &mdev->own_state_mutex;
 
 	spin_lock_init(&mdev->al_lock);
-	spin_lock_init(&mdev->req_lock);
 	spin_lock_init(&mdev->peer_seq_lock);
-	spin_lock_init(&mdev->epoch_lock);
 
 	INIT_LIST_HEAD(&mdev->active_ee);
 	INIT_LIST_HEAD(&mdev->sync_ee);
@@ -3167,8 +1901,6 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
 	INIT_LIST_HEAD(&mdev->read_ee);
 	INIT_LIST_HEAD(&mdev->net_ee);
 	INIT_LIST_HEAD(&mdev->resync_reads);
-	INIT_LIST_HEAD(&mdev->data.work.q);
-	INIT_LIST_HEAD(&mdev->meta.work.q);
 	INIT_LIST_HEAD(&mdev->resync_work.list);
 	INIT_LIST_HEAD(&mdev->unplug_work.list);
 	INIT_LIST_HEAD(&mdev->go_diskless.list);
@@ -3182,6 +1914,14 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
 	mdev->md_sync_work.cb = w_md_sync;
 	mdev->bm_io_work.w.cb = w_bitmap_io;
 	mdev->start_resync_work.cb = w_start_resync;
+
+	mdev->resync_work.mdev  = mdev;
+	mdev->unplug_work.mdev  = mdev;
+	mdev->go_diskless.mdev  = mdev;
+	mdev->md_sync_work.mdev = mdev;
+	mdev->bm_io_work.w.mdev = mdev;
+	mdev->start_resync_work.mdev = mdev;
+
 	init_timer(&mdev->resync_timer);
 	init_timer(&mdev->md_sync_timer);
 	init_timer(&mdev->start_resync_timer);
@@ -3197,17 +1937,10 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
 
 	init_waitqueue_head(&mdev->misc_wait);
 	init_waitqueue_head(&mdev->state_wait);
-	init_waitqueue_head(&mdev->net_cnt_wait);
 	init_waitqueue_head(&mdev->ee_wait);
 	init_waitqueue_head(&mdev->al_wait);
 	init_waitqueue_head(&mdev->seq_wait);
 
-	drbd_thread_init(mdev, &mdev->receiver, drbdd_init);
-	drbd_thread_init(mdev, &mdev->worker, drbd_worker);
-	drbd_thread_init(mdev, &mdev->asender, drbd_asender);
-
-	mdev->agreed_pro_version = PRO_VERSION_MAX;
-	mdev->write_ordering = WO_bdev_flush;
 	mdev->resync_wenr = LC_FREE;
 	mdev->peer_max_bio_size = DRBD_MAX_BIO_SIZE_SAFE;
 	mdev->local_max_bio_size = DRBD_MAX_BIO_SIZE_SAFE;
@@ -3216,13 +1949,10 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
 void drbd_mdev_cleanup(struct drbd_conf *mdev)
 {
 	int i;
-	if (mdev->receiver.t_state != None)
+	if (mdev->tconn->receiver.t_state != NONE)
 		dev_err(DEV, "ASSERT FAILED: receiver t_state == %d expected 0.\n",
-				mdev->receiver.t_state);
+				mdev->tconn->receiver.t_state);
 
-	/* no need to lock it, I'm the only thread alive */
-	if (atomic_read(&mdev->current_epoch->epoch_size) !=  0)
-		dev_err(DEV, "epoch_size:%d\n", atomic_read(&mdev->current_epoch->epoch_size));
 	mdev->al_writ_cnt  =
 	mdev->bm_writ_cnt  =
 	mdev->read_cnt     =
@@ -3239,7 +1969,7 @@ void drbd_mdev_cleanup(struct drbd_conf *mdev)
 		mdev->rs_mark_left[i] = 0;
 		mdev->rs_mark_time[i] = 0;
 	}
-	D_ASSERT(mdev->net_conf == NULL);
+	D_ASSERT(mdev->tconn->net_conf == NULL);
 
 	drbd_set_my_capacity(mdev, 0);
 	if (mdev->bitmap) {
@@ -3248,21 +1978,18 @@ void drbd_mdev_cleanup(struct drbd_conf *mdev)
 		drbd_bm_cleanup(mdev);
 	}
 
-	drbd_free_resources(mdev);
+	drbd_free_bc(mdev->ldev);
+	mdev->ldev = NULL;
+
 	clear_bit(AL_SUSPENDED, &mdev->flags);
 
-	/*
-	 * currently we drbd_init_ee only on module load, so
-	 * we may do drbd_release_ee only on module unload!
-	 */
 	D_ASSERT(list_empty(&mdev->active_ee));
 	D_ASSERT(list_empty(&mdev->sync_ee));
 	D_ASSERT(list_empty(&mdev->done_ee));
 	D_ASSERT(list_empty(&mdev->read_ee));
 	D_ASSERT(list_empty(&mdev->net_ee));
 	D_ASSERT(list_empty(&mdev->resync_reads));
-	D_ASSERT(list_empty(&mdev->data.work.q));
-	D_ASSERT(list_empty(&mdev->meta.work.q));
+	D_ASSERT(list_empty(&mdev->tconn->sender_work.q));
 	D_ASSERT(list_empty(&mdev->resync_work.list));
 	D_ASSERT(list_empty(&mdev->unplug_work.list));
 	D_ASSERT(list_empty(&mdev->go_diskless.list));
@@ -3336,7 +2063,7 @@ static int drbd_create_mempools(void)
 		goto Enomem;
 
 	drbd_ee_cache = kmem_cache_create(
-		"drbd_ee", sizeof(struct drbd_epoch_entry), 0, 0, NULL);
+		"drbd_ee", sizeof(struct drbd_peer_request), 0, 0, NULL);
 	if (drbd_ee_cache == NULL)
 		goto Enomem;
 
@@ -3351,11 +2078,9 @@ static int drbd_create_mempools(void)
 		goto Enomem;
 
 	/* mempools */
-#ifdef COMPAT_HAVE_BIOSET_CREATE
 	drbd_md_io_bio_set = bioset_create(DRBD_MIN_POOL_PAGES, 0);
 	if (drbd_md_io_bio_set == NULL)
 		goto Enomem;
-#endif
 
 	drbd_md_io_page_pool = mempool_create_page_pool(DRBD_MIN_POOL_PAGES, 0);
 	if (drbd_md_io_page_pool == NULL)
@@ -3404,73 +2129,53 @@ static struct notifier_block drbd_notifier = {
 	.notifier_call = drbd_notify_sys,
 };
 
-static void drbd_release_ee_lists(struct drbd_conf *mdev)
+static void drbd_release_all_peer_reqs(struct drbd_conf *mdev)
 {
 	int rr;
 
-	rr = drbd_release_ee(mdev, &mdev->active_ee);
+	rr = drbd_free_peer_reqs(mdev, &mdev->active_ee);
 	if (rr)
 		dev_err(DEV, "%d EEs in active list found!\n", rr);
 
-	rr = drbd_release_ee(mdev, &mdev->sync_ee);
+	rr = drbd_free_peer_reqs(mdev, &mdev->sync_ee);
 	if (rr)
 		dev_err(DEV, "%d EEs in sync list found!\n", rr);
 
-	rr = drbd_release_ee(mdev, &mdev->read_ee);
+	rr = drbd_free_peer_reqs(mdev, &mdev->read_ee);
 	if (rr)
 		dev_err(DEV, "%d EEs in read list found!\n", rr);
 
-	rr = drbd_release_ee(mdev, &mdev->done_ee);
+	rr = drbd_free_peer_reqs(mdev, &mdev->done_ee);
 	if (rr)
 		dev_err(DEV, "%d EEs in done list found!\n", rr);
 
-	rr = drbd_release_ee(mdev, &mdev->net_ee);
+	rr = drbd_free_peer_reqs(mdev, &mdev->net_ee);
 	if (rr)
 		dev_err(DEV, "%d EEs in net list found!\n", rr);
 }
 
-/* caution. no locking.
- * currently only used from module cleanup code. */
-static void drbd_delete_device(unsigned int minor)
+/* caution. no locking. */
+void drbd_minor_destroy(struct kref *kref)
 {
-	struct drbd_conf *mdev = minor_to_mdev(minor);
-
-	if (!mdev)
-		return;
+	struct drbd_conf *mdev = container_of(kref, struct drbd_conf, kref);
+	struct drbd_tconn *tconn = mdev->tconn;
 
 	del_timer_sync(&mdev->request_timer);
 
 	/* paranoia asserts */
-	if (mdev->open_cnt != 0)
-		dev_err(DEV, "open_cnt = %d in %s:%u", mdev->open_cnt,
-				__FILE__ , __LINE__);
-
-	ERR_IF (!list_empty(&mdev->data.work.q)) {
-		struct list_head *lp;
-		list_for_each(lp, &mdev->data.work.q) {
-			dev_err(DEV, "lp = %p\n", lp);
-		}
-	};
+	D_ASSERT(mdev->open_cnt == 0);
 	/* end paranoia asserts */
 
-	del_gendisk(mdev->vdisk);
-
 	/* cleanup stuff that may have been allocated during
 	 * device (re-)configuration or state changes */
 
 	if (mdev->this_bdev)
 		bdput(mdev->this_bdev);
 
-	drbd_free_resources(mdev);
+	drbd_free_bc(mdev->ldev);
+	mdev->ldev = NULL;
 
-	drbd_release_ee_lists(mdev);
-
-	/* should be freed on disconnect? */
-	kfree(mdev->ee_hash);
-	/*
-	mdev->ee_hash_s = 0;
-	mdev->ee_hash = NULL;
-	*/
+	drbd_release_all_peer_reqs(mdev);
 
 	lc_destroy(mdev->act_log);
 	lc_destroy(mdev->resync);
@@ -3478,19 +2183,101 @@ static void drbd_delete_device(unsigned int minor)
 	kfree(mdev->p_uuid);
 	/* mdev->p_uuid = NULL; */
 
-	kfree(mdev->int_dig_out);
-	kfree(mdev->int_dig_in);
-	kfree(mdev->int_dig_vv);
+	if (mdev->bitmap) /* should no longer be there. */
+		drbd_bm_cleanup(mdev);
+	__free_page(mdev->md_io_page);
+	put_disk(mdev->vdisk);
+	blk_cleanup_queue(mdev->rq_queue);
+	kfree(mdev->rs_plan_s);
+	kfree(mdev);
+
+	kref_put(&tconn->kref, &conn_destroy);
+}
+
+/* One global retry thread, if we need to push back some bio and have it
+ * reinserted through our make request function.
+ */
+static struct retry_worker {
+	struct workqueue_struct *wq;
+	struct work_struct worker;
+
+	spinlock_t lock;
+	struct list_head writes;
+} retry;
+
+static void do_retry(struct work_struct *ws)
+{
+	struct retry_worker *retry = container_of(ws, struct retry_worker, worker);
+	LIST_HEAD(writes);
+	struct drbd_request *req, *tmp;
+
+	spin_lock_irq(&retry->lock);
+	list_splice_init(&retry->writes, &writes);
+	spin_unlock_irq(&retry->lock);
+
+	list_for_each_entry_safe(req, tmp, &writes, tl_requests) {
+		struct drbd_conf *mdev = req->w.mdev;
+		struct bio *bio = req->master_bio;
+		unsigned long start_time = req->start_time;
+		bool expected;
+
+		expected = 
+			expect(atomic_read(&req->completion_ref) == 0) &&
+			expect(req->rq_state & RQ_POSTPONED) &&
+			expect((req->rq_state & RQ_LOCAL_PENDING) == 0 ||
+				(req->rq_state & RQ_LOCAL_ABORTED) != 0);
+
+		if (!expected)
+			dev_err(DEV, "req=%p completion_ref=%d rq_state=%x\n",
+				req, atomic_read(&req->completion_ref),
+				req->rq_state);
+
+		/* We still need to put one kref associated with the
+		 * "completion_ref" going zero in the code path that queued it
+		 * here.  The request object may still be referenced by a
+		 * frozen local req->private_bio, in case we force-detached.
+		 */
+		kref_put(&req->kref, drbd_req_destroy);
+
+		/* A single suspended or otherwise blocking device may stall
+		 * all others as well.  Fortunately, this code path is to
+		 * recover from a situation that "should not happen":
+		 * concurrent writes in multi-primary setup.
+		 * In a "normal" lifecycle, this workqueue is supposed to be
+		 * destroyed without ever doing anything.
+		 * If it turns out to be an issue anyways, we can do per
+		 * resource (replication group) or per device (minor) retry
+		 * workqueues instead.
+		 */
+
+		/* We are not just doing generic_make_request(),
+		 * as we want to keep the start_time information. */
+		inc_ap_bio(mdev);
+		__drbd_make_request(mdev, bio, start_time);
+	}
+}
+
+void drbd_restart_request(struct drbd_request *req)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&retry.lock, flags);
+	list_move_tail(&req->tl_requests, &retry.writes);
+	spin_unlock_irqrestore(&retry.lock, flags);
+
+	/* Drop the extra reference that would otherwise
+	 * have been dropped by complete_master_bio.
+	 * do_retry() needs to grab a new one. */
+	dec_ap_bio(req->w.mdev);
 
-	/* cleanup the rest that has been
-	 * allocated from drbd_new_device
-	 * and actually free the mdev itself */
-	drbd_free_mdev(mdev);
+	queue_work(retry.wq, &retry.worker);
 }
 
+
 static void drbd_cleanup(void)
 {
 	unsigned int i;
+	struct drbd_conf *mdev;
+	struct drbd_tconn *tconn, *tmp;
 
 	unregister_reboot_notifier(&drbd_notifier);
 
@@ -3505,19 +2292,31 @@ static void drbd_cleanup(void)
 	if (drbd_proc)
 		remove_proc_entry("drbd", NULL);
 
-	drbd_nl_cleanup();
+	if (retry.wq)
+		destroy_workqueue(retry.wq);
+
+	drbd_genl_unregister();
 
-	if (minor_table) {
-		i = minor_count;
-		while (i--)
-			drbd_delete_device(i);
-		drbd_destroy_mempools();
+	idr_for_each_entry(&minors, mdev, i) {
+		idr_remove(&minors, mdev_to_minor(mdev));
+		idr_remove(&mdev->tconn->volumes, mdev->vnr);
+		del_gendisk(mdev->vdisk);
+		/* synchronize_rcu(); No other threads running at this point */
+		kref_put(&mdev->kref, &drbd_minor_destroy);
 	}
 
-	kfree(minor_table);
+	/* not _rcu since, no other updater anymore. Genl already unregistered */
+	list_for_each_entry_safe(tconn, tmp, &drbd_tconns, all_tconn) {
+		list_del(&tconn->all_tconn); /* not _rcu no proc, not other threads */
+		/* synchronize_rcu(); */
+		kref_put(&tconn->kref, &conn_destroy);
+	}
 
+	drbd_destroy_mempools();
 	unregister_blkdev(DRBD_MAJOR, "drbd");
 
+	idr_destroy(&minors);
+
 	printk(KERN_INFO "drbd: module cleanup done.\n");
 }
 
@@ -3542,7 +2341,7 @@ static int drbd_congested(void *congested_data, int bdi_bits)
 		goto out;
 	}
 
-	if (test_bit(CALLBACK_PENDING, &mdev->flags)) {
+	if (test_bit(CALLBACK_PENDING, &mdev->tconn->flags)) {
 		r |= (1 << BDI_async_congested);
 		/* Without good local data, we would need to read from remote,
 		 * and that would need the worker thread as well, which is
@@ -3566,7 +2365,7 @@ static int drbd_congested(void *congested_data, int bdi_bits)
 			reason = 'b';
 	}
 
-	if (bdi_bits & (1 << BDI_async_congested) && test_bit(NET_CONGESTED, &mdev->flags)) {
+	if (bdi_bits & (1 << BDI_async_congested) && test_bit(NET_CONGESTED, &mdev->tconn->flags)) {
 		r |= (1 << BDI_async_congested);
 		reason = reason == 'b' ? 'a' : 'n';
 	}
@@ -3576,20 +2375,243 @@ out:
 	return r;
 }
 
-struct drbd_conf *drbd_new_device(unsigned int minor)
+static void drbd_init_workqueue(struct drbd_work_queue* wq)
+{
+	spin_lock_init(&wq->q_lock);
+	INIT_LIST_HEAD(&wq->q);
+	init_waitqueue_head(&wq->q_wait);
+}
+
+struct drbd_tconn *conn_get_by_name(const char *name)
+{
+	struct drbd_tconn *tconn;
+
+	if (!name || !name[0])
+		return NULL;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(tconn, &drbd_tconns, all_tconn) {
+		if (!strcmp(tconn->name, name)) {
+			kref_get(&tconn->kref);
+			goto found;
+		}
+	}
+	tconn = NULL;
+found:
+	rcu_read_unlock();
+	return tconn;
+}
+
+struct drbd_tconn *conn_get_by_addrs(void *my_addr, int my_addr_len,
+				     void *peer_addr, int peer_addr_len)
+{
+	struct drbd_tconn *tconn;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(tconn, &drbd_tconns, all_tconn) {
+		if (tconn->my_addr_len == my_addr_len &&
+		    tconn->peer_addr_len == peer_addr_len &&
+		    !memcmp(&tconn->my_addr, my_addr, my_addr_len) &&
+		    !memcmp(&tconn->peer_addr, peer_addr, peer_addr_len)) {
+			kref_get(&tconn->kref);
+			goto found;
+		}
+	}
+	tconn = NULL;
+found:
+	rcu_read_unlock();
+	return tconn;
+}
+
+static int drbd_alloc_socket(struct drbd_socket *socket)
+{
+	socket->rbuf = (void *) __get_free_page(GFP_KERNEL);
+	if (!socket->rbuf)
+		return -ENOMEM;
+	socket->sbuf = (void *) __get_free_page(GFP_KERNEL);
+	if (!socket->sbuf)
+		return -ENOMEM;
+	return 0;
+}
+
+static void drbd_free_socket(struct drbd_socket *socket)
+{
+	free_page((unsigned long) socket->sbuf);
+	free_page((unsigned long) socket->rbuf);
+}
+
+void conn_free_crypto(struct drbd_tconn *tconn)
+{
+	drbd_free_sock(tconn);
+
+	crypto_free_hash(tconn->csums_tfm);
+	crypto_free_hash(tconn->verify_tfm);
+	crypto_free_hash(tconn->cram_hmac_tfm);
+	crypto_free_hash(tconn->integrity_tfm);
+	crypto_free_hash(tconn->peer_integrity_tfm);
+	kfree(tconn->int_dig_in);
+	kfree(tconn->int_dig_vv);
+
+	tconn->csums_tfm = NULL;
+	tconn->verify_tfm = NULL;
+	tconn->cram_hmac_tfm = NULL;
+	tconn->integrity_tfm = NULL;
+	tconn->peer_integrity_tfm = NULL;
+	tconn->int_dig_in = NULL;
+	tconn->int_dig_vv = NULL;
+}
+
+int set_resource_options(struct drbd_tconn *tconn, struct res_opts *res_opts)
+{
+	cpumask_var_t new_cpu_mask;
+	int err;
+
+	if (!zalloc_cpumask_var(&new_cpu_mask, GFP_KERNEL))
+		return -ENOMEM;
+		/*
+		retcode = ERR_NOMEM;
+		drbd_msg_put_info("unable to allocate cpumask");
+		*/
+
+	/* silently ignore cpu mask on UP kernel */
+	if (nr_cpu_ids > 1 && res_opts->cpu_mask[0] != 0) {
+		/* FIXME: Get rid of constant 32 here */
+		err = bitmap_parse(res_opts->cpu_mask, 32,
+				   cpumask_bits(new_cpu_mask), nr_cpu_ids);
+		if (err) {
+			conn_warn(tconn, "bitmap_parse() failed with %d\n", err);
+			/* retcode = ERR_CPU_MASK_PARSE; */
+			goto fail;
+		}
+	}
+	tconn->res_opts = *res_opts;
+	if (!cpumask_equal(tconn->cpu_mask, new_cpu_mask)) {
+		cpumask_copy(tconn->cpu_mask, new_cpu_mask);
+		drbd_calc_cpu_mask(tconn);
+		tconn->receiver.reset_cpu_mask = 1;
+		tconn->asender.reset_cpu_mask = 1;
+		tconn->worker.reset_cpu_mask = 1;
+	}
+	err = 0;
+
+fail:
+	free_cpumask_var(new_cpu_mask);
+	return err;
+
+}
+
+/* caller must be under genl_lock() */
+struct drbd_tconn *conn_create(const char *name, struct res_opts *res_opts)
+{
+	struct drbd_tconn *tconn;
+
+	tconn = kzalloc(sizeof(struct drbd_tconn), GFP_KERNEL);
+	if (!tconn)
+		return NULL;
+
+	tconn->name = kstrdup(name, GFP_KERNEL);
+	if (!tconn->name)
+		goto fail;
+
+	if (drbd_alloc_socket(&tconn->data))
+		goto fail;
+	if (drbd_alloc_socket(&tconn->meta))
+		goto fail;
+
+	if (!zalloc_cpumask_var(&tconn->cpu_mask, GFP_KERNEL))
+		goto fail;
+
+	if (set_resource_options(tconn, res_opts))
+		goto fail;
+
+	tconn->current_epoch = kzalloc(sizeof(struct drbd_epoch), GFP_KERNEL);
+	if (!tconn->current_epoch)
+		goto fail;
+
+	INIT_LIST_HEAD(&tconn->transfer_log);
+
+	INIT_LIST_HEAD(&tconn->current_epoch->list);
+	tconn->epochs = 1;
+	spin_lock_init(&tconn->epoch_lock);
+	tconn->write_ordering = WO_bdev_flush;
+
+	tconn->send.seen_any_write_yet = false;
+	tconn->send.current_epoch_nr = 0;
+	tconn->send.current_epoch_writes = 0;
+
+	tconn->cstate = C_STANDALONE;
+	mutex_init(&tconn->cstate_mutex);
+	spin_lock_init(&tconn->req_lock);
+	mutex_init(&tconn->conf_update);
+	init_waitqueue_head(&tconn->ping_wait);
+	idr_init(&tconn->volumes);
+
+	drbd_init_workqueue(&tconn->sender_work);
+	mutex_init(&tconn->data.mutex);
+	mutex_init(&tconn->meta.mutex);
+
+	drbd_thread_init(tconn, &tconn->receiver, drbdd_init, "receiver");
+	drbd_thread_init(tconn, &tconn->worker, drbd_worker, "worker");
+	drbd_thread_init(tconn, &tconn->asender, drbd_asender, "asender");
+
+	kref_init(&tconn->kref);
+	list_add_tail_rcu(&tconn->all_tconn, &drbd_tconns);
+
+	return tconn;
+
+fail:
+	kfree(tconn->current_epoch);
+	free_cpumask_var(tconn->cpu_mask);
+	drbd_free_socket(&tconn->meta);
+	drbd_free_socket(&tconn->data);
+	kfree(tconn->name);
+	kfree(tconn);
+
+	return NULL;
+}
+
+void conn_destroy(struct kref *kref)
+{
+	struct drbd_tconn *tconn = container_of(kref, struct drbd_tconn, kref);
+
+	if (atomic_read(&tconn->current_epoch->epoch_size) !=  0)
+		conn_err(tconn, "epoch_size:%d\n", atomic_read(&tconn->current_epoch->epoch_size));
+	kfree(tconn->current_epoch);
+
+	idr_destroy(&tconn->volumes);
+
+	free_cpumask_var(tconn->cpu_mask);
+	drbd_free_socket(&tconn->meta);
+	drbd_free_socket(&tconn->data);
+	kfree(tconn->name);
+	kfree(tconn->int_dig_in);
+	kfree(tconn->int_dig_vv);
+	kfree(tconn);
+}
+
+enum drbd_ret_code conn_new_minor(struct drbd_tconn *tconn, unsigned int minor, int vnr)
 {
 	struct drbd_conf *mdev;
 	struct gendisk *disk;
 	struct request_queue *q;
+	int vnr_got = vnr;
+	int minor_got = minor;
+	enum drbd_ret_code err = ERR_NOMEM;
+
+	mdev = minor_to_mdev(minor);
+	if (mdev)
+		return ERR_MINOR_EXISTS;
 
 	/* GFP_KERNEL, we are outside of all write-out paths */
 	mdev = kzalloc(sizeof(struct drbd_conf), GFP_KERNEL);
 	if (!mdev)
-		return NULL;
-	if (!zalloc_cpumask_var(&mdev->cpu_mask, GFP_KERNEL))
-		goto out_no_cpumask;
+		return ERR_NOMEM;
+
+	kref_get(&tconn->kref);
+	mdev->tconn = tconn;
 
 	mdev->minor = minor;
+	mdev->vnr = vnr;
 
 	drbd_init_set_defaults(mdev);
 
@@ -3627,7 +2649,7 @@ struct drbd_conf *drbd_new_device(unsigned int minor)
 	blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE_SAFE >> 8);
 	blk_queue_bounce_limit(q, BLK_BOUNCE_ANY);
 	blk_queue_merge_bvec(q, drbd_merge_bvec);
-	q->queue_lock = &mdev->req_lock;
+	q->queue_lock = &mdev->tconn->req_lock; /* needed since we use */
 
 	mdev->md_io_page = alloc_page(GFP_KERNEL);
 	if (!mdev->md_io_page)
@@ -3635,30 +2657,44 @@ struct drbd_conf *drbd_new_device(unsigned int minor)
 
 	if (drbd_bm_init(mdev))
 		goto out_no_bitmap;
-	/* no need to lock access, we are still initializing this minor device. */
-	if (!tl_init(mdev))
-		goto out_no_tl;
-
-	mdev->app_reads_hash = kzalloc(APP_R_HSIZE*sizeof(void *), GFP_KERNEL);
-	if (!mdev->app_reads_hash)
-		goto out_no_app_reads;
-
-	mdev->current_epoch = kzalloc(sizeof(struct drbd_epoch), GFP_KERNEL);
-	if (!mdev->current_epoch)
-		goto out_no_epoch;
-
-	INIT_LIST_HEAD(&mdev->current_epoch->list);
-	mdev->epochs = 1;
-
-	return mdev;
-
-/* out_whatever_else:
-	kfree(mdev->current_epoch); */
-out_no_epoch:
-	kfree(mdev->app_reads_hash);
-out_no_app_reads:
-	tl_cleanup(mdev);
-out_no_tl:
+	mdev->read_requests = RB_ROOT;
+	mdev->write_requests = RB_ROOT;
+
+	if (!idr_pre_get(&minors, GFP_KERNEL))
+		goto out_no_minor_idr;
+	if (idr_get_new_above(&minors, mdev, minor, &minor_got))
+		goto out_no_minor_idr;
+	if (minor_got != minor) {
+		err = ERR_MINOR_EXISTS;
+		drbd_msg_put_info("requested minor exists already");
+		goto out_idr_remove_minor;
+	}
+
+	if (!idr_pre_get(&tconn->volumes, GFP_KERNEL))
+		goto out_idr_remove_minor;
+	if (idr_get_new_above(&tconn->volumes, mdev, vnr, &vnr_got))
+		goto out_idr_remove_minor;
+	if (vnr_got != vnr) {
+		err = ERR_INVALID_REQUEST;
+		drbd_msg_put_info("requested volume exists already");
+		goto out_idr_remove_vol;
+	}
+	add_disk(disk);
+	kref_init(&mdev->kref); /* one ref for both idrs and the the add_disk */
+
+	/* inherit the connection state */
+	mdev->state.conn = tconn->cstate;
+	if (mdev->state.conn == C_WF_REPORT_PARAMS)
+		drbd_connected(mdev);
+
+	return NO_ERROR;
+
+out_idr_remove_vol:
+	idr_remove(&tconn->volumes, vnr_got);
+out_idr_remove_minor:
+	idr_remove(&minors, minor_got);
+	synchronize_rcu();
+out_no_minor_idr:
 	drbd_bm_cleanup(mdev);
 out_no_bitmap:
 	__free_page(mdev->md_io_page);
@@ -3667,55 +2703,25 @@ out_no_io_page:
 out_no_disk:
 	blk_cleanup_queue(q);
 out_no_q:
-	free_cpumask_var(mdev->cpu_mask);
-out_no_cpumask:
-	kfree(mdev);
-	return NULL;
-}
-
-/* counterpart of drbd_new_device.
- * last part of drbd_delete_device. */
-void drbd_free_mdev(struct drbd_conf *mdev)
-{
-	kfree(mdev->current_epoch);
-	kfree(mdev->app_reads_hash);
-	tl_cleanup(mdev);
-	if (mdev->bitmap) /* should no longer be there. */
-		drbd_bm_cleanup(mdev);
-	__free_page(mdev->md_io_page);
-	put_disk(mdev->vdisk);
-	blk_cleanup_queue(mdev->rq_queue);
-	free_cpumask_var(mdev->cpu_mask);
-	drbd_free_tl_hash(mdev);
 	kfree(mdev);
+	kref_put(&tconn->kref, &conn_destroy);
+	return err;
 }
 
-
 int __init drbd_init(void)
 {
 	int err;
 
-	if (sizeof(struct p_handshake) != 80) {
-		printk(KERN_ERR
-		       "drbd: never change the size or layout "
-		       "of the HandShake packet.\n");
-		return -EINVAL;
-	}
-
 	if (minor_count < DRBD_MINOR_COUNT_MIN || minor_count > DRBD_MINOR_COUNT_MAX) {
 		printk(KERN_ERR
-			"drbd: invalid minor_count (%d)\n", minor_count);
+		       "drbd: invalid minor_count (%d)\n", minor_count);
 #ifdef MODULE
 		return -EINVAL;
 #else
-		minor_count = 8;
+		minor_count = DRBD_MINOR_COUNT_DEF;
 #endif
 	}
 
-	err = drbd_nl_init();
-	if (err)
-		return err;
-
 	err = register_blkdev(DRBD_MAJOR, "drbd");
 	if (err) {
 		printk(KERN_ERR
@@ -3724,6 +2730,13 @@ int __init drbd_init(void)
 		return err;
 	}
 
+	err = drbd_genl_register();
+	if (err) {
+		printk(KERN_ERR "drbd: unable to register generic netlink family\n");
+		goto fail;
+	}
+
+
 	register_reboot_notifier(&drbd_notifier);
 
 	/*
@@ -3734,22 +2747,29 @@ int __init drbd_init(void)
 	init_waitqueue_head(&drbd_pp_wait);
 
 	drbd_proc = NULL; /* play safe for drbd_cleanup */
-	minor_table = kzalloc(sizeof(struct drbd_conf *)*minor_count,
-				GFP_KERNEL);
-	if (!minor_table)
-		goto Enomem;
+	idr_init(&minors);
 
 	err = drbd_create_mempools();
 	if (err)
-		goto Enomem;
+		goto fail;
 
 	drbd_proc = proc_create_data("drbd", S_IFREG | S_IRUGO , NULL, &drbd_proc_fops, NULL);
 	if (!drbd_proc)	{
 		printk(KERN_ERR "drbd: unable to register proc file\n");
-		goto Enomem;
+		goto fail;
 	}
 
 	rwlock_init(&global_state_lock);
+	INIT_LIST_HEAD(&drbd_tconns);
+
+	retry.wq = create_singlethread_workqueue("drbd-reissue");
+	if (!retry.wq) {
+		printk(KERN_ERR "drbd: unable to create retry workqueue\n");
+		goto fail;
+	}
+	INIT_WORK(&retry.worker, do_retry);
+	spin_lock_init(&retry.lock);
+	INIT_LIST_HEAD(&retry.writes);
 
 	printk(KERN_INFO "drbd: initialized. "
 	       "Version: " REL_VERSION " (api:%d/proto:%d-%d)\n",
@@ -3757,11 +2777,10 @@ int __init drbd_init(void)
 	printk(KERN_INFO "drbd: %s\n", drbd_buildtag());
 	printk(KERN_INFO "drbd: registered as block device major %d\n",
 		DRBD_MAJOR);
-	printk(KERN_INFO "drbd: minor_table @ 0x%p\n", minor_table);
 
 	return 0; /* Success! */
 
-Enomem:
+fail:
 	drbd_cleanup();
 	if (err == -ENOMEM)
 		/* currently always the case */
@@ -3782,47 +2801,42 @@ void drbd_free_bc(struct drbd_backing_dev *ldev)
 	kfree(ldev);
 }
 
-void drbd_free_sock(struct drbd_conf *mdev)
+void drbd_free_sock(struct drbd_tconn *tconn)
 {
-	if (mdev->data.socket) {
-		mutex_lock(&mdev->data.mutex);
-		kernel_sock_shutdown(mdev->data.socket, SHUT_RDWR);
-		sock_release(mdev->data.socket);
-		mdev->data.socket = NULL;
-		mutex_unlock(&mdev->data.mutex);
+	if (tconn->data.socket) {
+		mutex_lock(&tconn->data.mutex);
+		kernel_sock_shutdown(tconn->data.socket, SHUT_RDWR);
+		sock_release(tconn->data.socket);
+		tconn->data.socket = NULL;
+		mutex_unlock(&tconn->data.mutex);
 	}
-	if (mdev->meta.socket) {
-		mutex_lock(&mdev->meta.mutex);
-		kernel_sock_shutdown(mdev->meta.socket, SHUT_RDWR);
-		sock_release(mdev->meta.socket);
-		mdev->meta.socket = NULL;
-		mutex_unlock(&mdev->meta.mutex);
+	if (tconn->meta.socket) {
+		mutex_lock(&tconn->meta.mutex);
+		kernel_sock_shutdown(tconn->meta.socket, SHUT_RDWR);
+		sock_release(tconn->meta.socket);
+		tconn->meta.socket = NULL;
+		mutex_unlock(&tconn->meta.mutex);
 	}
 }
 
+/* meta data management */
 
-void drbd_free_resources(struct drbd_conf *mdev)
+void conn_md_sync(struct drbd_tconn *tconn)
 {
-	crypto_free_hash(mdev->csums_tfm);
-	mdev->csums_tfm = NULL;
-	crypto_free_hash(mdev->verify_tfm);
-	mdev->verify_tfm = NULL;
-	crypto_free_hash(mdev->cram_hmac_tfm);
-	mdev->cram_hmac_tfm = NULL;
-	crypto_free_hash(mdev->integrity_w_tfm);
-	mdev->integrity_w_tfm = NULL;
-	crypto_free_hash(mdev->integrity_r_tfm);
-	mdev->integrity_r_tfm = NULL;
-
-	drbd_free_sock(mdev);
+	struct drbd_conf *mdev;
+	int vnr;
 
-	__no_warn(local,
-		  drbd_free_bc(mdev->ldev);
-		  mdev->ldev = NULL;);
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+		kref_get(&mdev->kref);
+		rcu_read_unlock();
+		drbd_md_sync(mdev);
+		kref_put(&mdev->kref, &drbd_minor_destroy);
+		rcu_read_lock();
+	}
+	rcu_read_unlock();
 }
 
-/* meta data management */
-
 struct meta_data_on_disk {
 	u64 la_size;           /* last agreed size. */
 	u64 uuid[UI_SIZE];   /* UUIDs. */
@@ -3833,7 +2847,7 @@ struct meta_data_on_disk {
 	u32 md_size_sect;
 	u32 al_offset;         /* offset to this block */
 	u32 al_nr_extents;     /* important for restoring the AL */
-	      /* `-- act_log->nr_elements <-- sync_conf.al_extents */
+	      /* `-- act_log->nr_elements <-- ldev->dc.al_extents */
 	u32 bm_offset;         /* offset to the bitmap, from here */
 	u32 bm_bytes_per_bit;  /* BM_BLOCK_SIZE */
 	u32 la_peer_max_bio_size;   /* last peer max_bio_size */
@@ -3871,7 +2885,7 @@ void drbd_md_sync(struct drbd_conf *mdev)
 	for (i = UI_CURRENT; i < UI_SIZE; i++)
 		buffer->uuid[i] = cpu_to_be64(mdev->ldev->md.uuid[i]);
 	buffer->flags = cpu_to_be32(mdev->ldev->md.flags);
-	buffer->magic = cpu_to_be32(DRBD_MD_MAGIC);
+	buffer->magic = cpu_to_be32(DRBD_MD_MAGIC_84_UNCLEAN);
 
 	buffer->md_size_sect  = cpu_to_be32(mdev->ldev->md.md_size_sect);
 	buffer->al_offset     = cpu_to_be32(mdev->ldev->md.al_offset);
@@ -3885,7 +2899,7 @@ void drbd_md_sync(struct drbd_conf *mdev)
 	D_ASSERT(drbd_md_ss__(mdev, mdev->ldev) == mdev->ldev->md.md_offset);
 	sector = mdev->ldev->md.md_offset;
 
-	if (!drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
+	if (drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
 		/* this was a try anyways ... */
 		dev_err(DEV, "meta data update failed!\n");
 		drbd_chk_io_error(mdev, 1, DRBD_META_IO_ERROR);
@@ -3906,11 +2920,12 @@ out:
  * @bdev:	Device from which the meta data should be read in.
  *
  * Return 0 (NO_ERROR) on success, and an enum drbd_ret_code in case
- * something goes wrong.  Currently only: ERR_IO_MD_DISK, ERR_MD_INVALID.
+ * something goes wrong.
  */
 int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
 {
 	struct meta_data_on_disk *buffer;
+	u32 magic, flags;
 	int i, rv = NO_ERROR;
 
 	if (!get_ldev_if_state(mdev, D_ATTACHING))
@@ -3920,7 +2935,7 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
 	if (!buffer)
 		goto out;
 
-	if (!drbd_md_sync_page_io(mdev, bdev, bdev->md.md_offset, READ)) {
+	if (drbd_md_sync_page_io(mdev, bdev, bdev->md.md_offset, READ)) {
 		/* NOTE: can't do normal error processing here as this is
 		   called BEFORE disk is attached */
 		dev_err(DEV, "Error while reading metadata.\n");
@@ -3928,8 +2943,20 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
 		goto err;
 	}
 
-	if (be32_to_cpu(buffer->magic) != DRBD_MD_MAGIC) {
-		dev_err(DEV, "Error while reading metadata, magic not found.\n");
+	magic = be32_to_cpu(buffer->magic);
+	flags = be32_to_cpu(buffer->flags);
+	if (magic == DRBD_MD_MAGIC_84_UNCLEAN ||
+	    (magic == DRBD_MD_MAGIC_08 && !(flags & MDF_AL_CLEAN))) {
+			/* btw: that's Activity Log clean, not "all" clean. */
+		dev_err(DEV, "Found unclean meta data. Did you \"drbdadm apply-al\"?\n");
+		rv = ERR_MD_UNCLEAN;
+		goto err;
+	}
+	if (magic != DRBD_MD_MAGIC_08) {
+		if (magic == DRBD_MD_MAGIC_07)
+			dev_err(DEV, "Found old (0.7) meta data magic. Did you \"drbdadm create-md\"?\n");
+		else
+			dev_err(DEV, "Meta data magic not found. Did you \"drbdadm create-md\"?\n");
 		rv = ERR_MD_INVALID;
 		goto err;
 	}
@@ -3963,20 +2990,16 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
 	for (i = UI_CURRENT; i < UI_SIZE; i++)
 		bdev->md.uuid[i] = be64_to_cpu(buffer->uuid[i]);
 	bdev->md.flags = be32_to_cpu(buffer->flags);
-	mdev->sync_conf.al_extents = be32_to_cpu(buffer->al_nr_extents);
 	bdev->md.device_uuid = be64_to_cpu(buffer->device_uuid);
 
-	spin_lock_irq(&mdev->req_lock);
+	spin_lock_irq(&mdev->tconn->req_lock);
 	if (mdev->state.conn < C_CONNECTED) {
 		unsigned int peer;
 		peer = be32_to_cpu(buffer->la_peer_max_bio_size);
 		peer = max(peer, DRBD_MAX_BIO_SIZE_SAFE);
 		mdev->peer_max_bio_size = peer;
 	}
-	spin_unlock_irq(&mdev->req_lock);
-
-	if (mdev->sync_conf.al_extents < 7)
-		mdev->sync_conf.al_extents = 127;
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
  err:
 	drbd_md_put_buffer(mdev);
@@ -4011,7 +3034,7 @@ void drbd_md_mark_dirty(struct drbd_conf *mdev)
 }
 #endif
 
-static void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local)
+void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local)
 {
 	int i;
 
@@ -4019,7 +3042,7 @@ static void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local)
 		mdev->ldev->md.uuid[i+1] = mdev->ldev->md.uuid[i];
 }
 
-void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
+void __drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
 {
 	if (idx == UI_CURRENT) {
 		if (mdev->state.role == R_PRIMARY)
@@ -4034,14 +3057,24 @@ void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
 	drbd_md_mark_dirty(mdev);
 }
 
+void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&mdev->ldev->md.uuid_lock, flags);
+	__drbd_uuid_set(mdev, idx, val);
+	spin_unlock_irqrestore(&mdev->ldev->md.uuid_lock, flags);
+}
 
 void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&mdev->ldev->md.uuid_lock, flags);
 	if (mdev->ldev->md.uuid[idx]) {
 		drbd_uuid_move_history(mdev);
 		mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[idx];
 	}
-	_drbd_uuid_set(mdev, idx, val);
+	__drbd_uuid_set(mdev, idx, val);
+	spin_unlock_irqrestore(&mdev->ldev->md.uuid_lock, flags);
 }
 
 /**
@@ -4054,15 +3087,20 @@ void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
 void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local)
 {
 	u64 val;
-	unsigned long long bm_uuid = mdev->ldev->md.uuid[UI_BITMAP];
+	unsigned long long bm_uuid;
+
+	get_random_bytes(&val, sizeof(u64));
+
+	spin_lock_irq(&mdev->ldev->md.uuid_lock);
+	bm_uuid = mdev->ldev->md.uuid[UI_BITMAP];
 
 	if (bm_uuid)
 		dev_warn(DEV, "bm UUID was already set: %llX\n", bm_uuid);
 
 	mdev->ldev->md.uuid[UI_BITMAP] = mdev->ldev->md.uuid[UI_CURRENT];
+	__drbd_uuid_set(mdev, UI_CURRENT, val);
+	spin_unlock_irq(&mdev->ldev->md.uuid_lock);
 
-	get_random_bytes(&val, sizeof(u64));
-	_drbd_uuid_set(mdev, UI_CURRENT, val);
 	drbd_print_uuids(mdev, "new current UUID");
 	/* get it to stable storage _now_ */
 	drbd_md_sync(mdev);
@@ -4070,9 +3108,11 @@ void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local)
 
 void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local)
 {
+	unsigned long flags;
 	if (mdev->ldev->md.uuid[UI_BITMAP] == 0 && val == 0)
 		return;
 
+	spin_lock_irqsave(&mdev->ldev->md.uuid_lock, flags);
 	if (val == 0) {
 		drbd_uuid_move_history(mdev);
 		mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[UI_BITMAP];
@@ -4084,6 +3124,8 @@ void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local)
 
 		mdev->ldev->md.uuid[UI_BITMAP] = val & ~((u64)1);
 	}
+	spin_unlock_irqrestore(&mdev->ldev->md.uuid_lock, flags);
+
 	drbd_md_mark_dirty(mdev);
 }
 
@@ -4135,9 +3177,10 @@ int drbd_bmio_clear_n_write(struct drbd_conf *mdev)
 	return rv;
 }
 
-static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused)
+static int w_bitmap_io(struct drbd_work *w, int unused)
 {
 	struct bm_io_work *work = container_of(w, struct bm_io_work, w);
+	struct drbd_conf *mdev = w->mdev;
 	int rv = -EIO;
 
 	D_ASSERT(atomic_read(&mdev->ap_bio_cnt) == 0);
@@ -4149,8 +3192,7 @@ static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused)
 		put_ldev(mdev);
 	}
 
-	clear_bit(BITMAP_IO, &mdev->flags);
-	smp_mb__after_clear_bit();
+	clear_bit_unlock(BITMAP_IO, &mdev->flags);
 	wake_up(&mdev->misc_wait);
 
 	if (work->done)
@@ -4160,7 +3202,7 @@ static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused)
 	work->why = NULL;
 	work->flags = 0;
 
-	return 1;
+	return 0;
 }
 
 void drbd_ldev_destroy(struct drbd_conf *mdev)
@@ -4173,29 +3215,51 @@ void drbd_ldev_destroy(struct drbd_conf *mdev)
 		drbd_free_bc(mdev->ldev);
 		mdev->ldev = NULL;);
 
-	if (mdev->md_io_tmpp) {
-		__free_page(mdev->md_io_tmpp);
-		mdev->md_io_tmpp = NULL;
-	}
 	clear_bit(GO_DISKLESS, &mdev->flags);
 }
 
-static int w_go_diskless(struct drbd_conf *mdev, struct drbd_work *w, int unused)
+static int w_go_diskless(struct drbd_work *w, int unused)
 {
+	struct drbd_conf *mdev = w->mdev;
+
 	D_ASSERT(mdev->state.disk == D_FAILED);
 	/* we cannot assert local_cnt == 0 here, as get_ldev_if_state will
 	 * inc/dec it frequently. Once we are D_DISKLESS, no one will touch
 	 * the protected members anymore, though, so once put_ldev reaches zero
 	 * again, it will be safe to free them. */
+
+	/* Try to write changed bitmap pages, read errors may have just
+	 * set some bits outside the area covered by the activity log.
+	 *
+	 * If we have an IO error during the bitmap writeout,
+	 * we will want a full sync next time, just in case.
+	 * (Do we want a specific meta data flag for this?)
+	 *
+	 * If that does not make it to stable storage either,
+	 * we cannot do anything about that anymore.
+	 *
+	 * We still need to check if both bitmap and ldev are present, we may
+	 * end up here after a failed attach, before ldev was even assigned.
+	 */
+	if (mdev->bitmap && mdev->ldev) {
+		if (drbd_bitmap_io_from_worker(mdev, drbd_bm_write,
+					"detach", BM_LOCKED_MASK)) {
+			if (test_bit(WAS_READ_ERROR, &mdev->flags)) {
+				drbd_md_set_flag(mdev, MDF_FULL_SYNC);
+				drbd_md_sync(mdev);
+			}
+		}
+	}
+
 	drbd_force_state(mdev, NS(disk, D_DISKLESS));
-	return 1;
+	return 0;
 }
 
 void drbd_go_diskless(struct drbd_conf *mdev)
 {
 	D_ASSERT(mdev->state.disk == D_FAILED);
 	if (!test_and_set_bit(GO_DISKLESS, &mdev->flags))
-		drbd_queue_work(&mdev->data.work, &mdev->go_diskless);
+		drbd_queue_work(&mdev->tconn->sender_work, &mdev->go_diskless);
 }
 
 /**
@@ -4215,7 +3279,7 @@ void drbd_queue_bitmap_io(struct drbd_conf *mdev,
 			  void (*done)(struct drbd_conf *, int),
 			  char *why, enum bm_flag flags)
 {
-	D_ASSERT(current == mdev->worker.task);
+	D_ASSERT(current == mdev->tconn->worker.task);
 
 	D_ASSERT(!test_bit(BITMAP_IO_QUEUED, &mdev->flags));
 	D_ASSERT(!test_bit(BITMAP_IO, &mdev->flags));
@@ -4229,13 +3293,13 @@ void drbd_queue_bitmap_io(struct drbd_conf *mdev,
 	mdev->bm_io_work.why = why;
 	mdev->bm_io_work.flags = flags;
 
-	spin_lock_irq(&mdev->req_lock);
+	spin_lock_irq(&mdev->tconn->req_lock);
 	set_bit(BITMAP_IO, &mdev->flags);
 	if (atomic_read(&mdev->ap_bio_cnt) == 0) {
 		if (!test_and_set_bit(BITMAP_IO_QUEUED, &mdev->flags))
-			drbd_queue_work(&mdev->data.work, &mdev->bm_io_work.w);
+			drbd_queue_work(&mdev->tconn->sender_work, &mdev->bm_io_work.w);
 	}
-	spin_unlock_irq(&mdev->req_lock);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 }
 
 /**
@@ -4252,7 +3316,7 @@ int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *),
 {
 	int rv;
 
-	D_ASSERT(current != mdev->worker.task);
+	D_ASSERT(current != mdev->tconn->worker.task);
 
 	if ((flags & BM_LOCKED_SET_ALLOWED) == 0)
 		drbd_suspend_io(mdev);
@@ -4291,18 +3355,127 @@ static void md_sync_timer_fn(unsigned long data)
 {
 	struct drbd_conf *mdev = (struct drbd_conf *) data;
 
-	drbd_queue_work_front(&mdev->data.work, &mdev->md_sync_work);
+	/* must not double-queue! */
+	if (list_empty(&mdev->md_sync_work.list))
+		drbd_queue_work_front(&mdev->tconn->sender_work, &mdev->md_sync_work);
 }
 
-static int w_md_sync(struct drbd_conf *mdev, struct drbd_work *w, int unused)
+static int w_md_sync(struct drbd_work *w, int unused)
 {
+	struct drbd_conf *mdev = w->mdev;
+
 	dev_warn(DEV, "md_sync_timer expired! Worker calls drbd_md_sync().\n");
 #ifdef DEBUG
 	dev_warn(DEV, "last md_mark_dirty: %s:%u\n",
 		mdev->last_md_mark_dirty.func, mdev->last_md_mark_dirty.line);
 #endif
 	drbd_md_sync(mdev);
-	return 1;
+	return 0;
+}
+
+const char *cmdname(enum drbd_packet cmd)
+{
+	/* THINK may need to become several global tables
+	 * when we want to support more than
+	 * one PRO_VERSION */
+	static const char *cmdnames[] = {
+		[P_DATA]	        = "Data",
+		[P_DATA_REPLY]	        = "DataReply",
+		[P_RS_DATA_REPLY]	= "RSDataReply",
+		[P_BARRIER]	        = "Barrier",
+		[P_BITMAP]	        = "ReportBitMap",
+		[P_BECOME_SYNC_TARGET]  = "BecomeSyncTarget",
+		[P_BECOME_SYNC_SOURCE]  = "BecomeSyncSource",
+		[P_UNPLUG_REMOTE]	= "UnplugRemote",
+		[P_DATA_REQUEST]	= "DataRequest",
+		[P_RS_DATA_REQUEST]     = "RSDataRequest",
+		[P_SYNC_PARAM]	        = "SyncParam",
+		[P_SYNC_PARAM89]	= "SyncParam89",
+		[P_PROTOCOL]            = "ReportProtocol",
+		[P_UUIDS]	        = "ReportUUIDs",
+		[P_SIZES]	        = "ReportSizes",
+		[P_STATE]	        = "ReportState",
+		[P_SYNC_UUID]           = "ReportSyncUUID",
+		[P_AUTH_CHALLENGE]      = "AuthChallenge",
+		[P_AUTH_RESPONSE]	= "AuthResponse",
+		[P_PING]		= "Ping",
+		[P_PING_ACK]	        = "PingAck",
+		[P_RECV_ACK]	        = "RecvAck",
+		[P_WRITE_ACK]	        = "WriteAck",
+		[P_RS_WRITE_ACK]	= "RSWriteAck",
+		[P_SUPERSEDED]          = "Superseded",
+		[P_NEG_ACK]	        = "NegAck",
+		[P_NEG_DREPLY]	        = "NegDReply",
+		[P_NEG_RS_DREPLY]	= "NegRSDReply",
+		[P_BARRIER_ACK]	        = "BarrierAck",
+		[P_STATE_CHG_REQ]       = "StateChgRequest",
+		[P_STATE_CHG_REPLY]     = "StateChgReply",
+		[P_OV_REQUEST]          = "OVRequest",
+		[P_OV_REPLY]            = "OVReply",
+		[P_OV_RESULT]           = "OVResult",
+		[P_CSUM_RS_REQUEST]     = "CsumRSRequest",
+		[P_RS_IS_IN_SYNC]	= "CsumRSIsInSync",
+		[P_COMPRESSED_BITMAP]   = "CBitmap",
+		[P_DELAY_PROBE]         = "DelayProbe",
+		[P_OUT_OF_SYNC]		= "OutOfSync",
+		[P_RETRY_WRITE]		= "RetryWrite",
+		[P_RS_CANCEL]		= "RSCancel",
+		[P_CONN_ST_CHG_REQ]	= "conn_st_chg_req",
+		[P_CONN_ST_CHG_REPLY]	= "conn_st_chg_reply",
+		[P_RETRY_WRITE]		= "retry_write",
+		[P_PROTOCOL_UPDATE]	= "protocol_update",
+
+		/* enum drbd_packet, but not commands - obsoleted flags:
+		 *	P_MAY_IGNORE
+		 *	P_MAX_OPT_CMD
+		 */
+	};
+
+	/* too big for the array: 0xfffX */
+	if (cmd == P_INITIAL_META)
+		return "InitialMeta";
+	if (cmd == P_INITIAL_DATA)
+		return "InitialData";
+	if (cmd == P_CONNECTION_FEATURES)
+		return "ConnectionFeatures";
+	if (cmd >= ARRAY_SIZE(cmdnames))
+		return "Unknown";
+	return cmdnames[cmd];
+}
+
+/**
+ * drbd_wait_misc  -  wait for a request to make progress
+ * @mdev:	device associated with the request
+ * @i:		the struct drbd_interval embedded in struct drbd_request or
+ *		struct drbd_peer_request
+ */
+int drbd_wait_misc(struct drbd_conf *mdev, struct drbd_interval *i)
+{
+	struct net_conf *nc;
+	DEFINE_WAIT(wait);
+	long timeout;
+
+	rcu_read_lock();
+	nc = rcu_dereference(mdev->tconn->net_conf);
+	if (!nc) {
+		rcu_read_unlock();
+		return -ETIMEDOUT;
+	}
+	timeout = nc->ko_count ? nc->timeout * HZ / 10 * nc->ko_count : MAX_SCHEDULE_TIMEOUT;
+	rcu_read_unlock();
+
+	/* Indicate to wake up mdev->misc_wait on progress.  */
+	i->waiting = true;
+	prepare_to_wait(&mdev->misc_wait, &wait, TASK_INTERRUPTIBLE);
+	spin_unlock_irq(&mdev->tconn->req_lock);
+	timeout = schedule_timeout(timeout);
+	finish_wait(&mdev->misc_wait, &wait);
+	spin_lock_irq(&mdev->tconn->req_lock);
+	if (!timeout || mdev->state.conn < C_CONNECTED)
+		return -ETIMEDOUT;
+	if (signal_pending(current))
+		return -ERESTARTSYS;
+	return 0;
 }
 
 #ifdef CONFIG_DRBD_FAULT_INJECTION
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index edb490a..76bb3a6 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -29,159 +29,317 @@
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/slab.h>
-#include <linux/connector.h>
 #include <linux/blkpg.h>
 #include <linux/cpumask.h>
 #include "drbd_int.h"
 #include "drbd_req.h"
 #include "drbd_wrappers.h"
 #include <asm/unaligned.h>
-#include <linux/drbd_tag_magic.h>
 #include <linux/drbd_limits.h>
-#include <linux/compiler.h>
 #include <linux/kthread.h>
 
-static unsigned short *tl_add_blob(unsigned short *, enum drbd_tags, const void *, int);
-static unsigned short *tl_add_str(unsigned short *, enum drbd_tags, const char *);
-static unsigned short *tl_add_int(unsigned short *, enum drbd_tags, const void *);
-
-/* see get_sb_bdev and bd_claim */
+#include <net/genetlink.h>
+
+/* .doit */
+// int drbd_adm_create_resource(struct sk_buff *skb, struct genl_info *info);
+// int drbd_adm_delete_resource(struct sk_buff *skb, struct genl_info *info);
+
+int drbd_adm_add_minor(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_delete_minor(struct sk_buff *skb, struct genl_info *info);
+
+int drbd_adm_new_resource(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_del_resource(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_down(struct sk_buff *skb, struct genl_info *info);
+
+int drbd_adm_set_role(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_detach(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_start_ov(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_new_c_uuid(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_disconnect(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_invalidate(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_invalidate_peer(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_pause_sync(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_resume_sync(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_suspend_io(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_resume_io(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_outdate(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_resource_opts(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_get_status(struct sk_buff *skb, struct genl_info *info);
+int drbd_adm_get_timeout_type(struct sk_buff *skb, struct genl_info *info);
+/* .dumpit */
+int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb);
+
+#include <linux/drbd_genl_api.h>
+#include "drbd_nla.h"
+#include <linux/genl_magic_func.h>
+
+/* used blkdev_get_by_path, to claim our meta data device(s) */
 static char *drbd_m_holder = "Hands off! this is DRBD's meta data device.";
 
-/* Generate the tag_list to struct functions */
-#define NL_PACKET(name, number, fields) \
-static int name ## _from_tags(struct drbd_conf *mdev, \
-	unsigned short *tags, struct name *arg) __attribute__ ((unused)); \
-static int name ## _from_tags(struct drbd_conf *mdev, \
-	unsigned short *tags, struct name *arg) \
-{ \
-	int tag; \
-	int dlen; \
-	\
-	while ((tag = get_unaligned(tags++)) != TT_END) {	\
-		dlen = get_unaligned(tags++);			\
-		switch (tag_number(tag)) { \
-		fields \
-		default: \
-			if (tag & T_MANDATORY) { \
-				dev_err(DEV, "Unknown tag: %d\n", tag_number(tag)); \
-				return 0; \
-			} \
-		} \
-		tags = (unsigned short *)((char *)tags + dlen); \
-	} \
-	return 1; \
-}
-#define NL_INTEGER(pn, pr, member) \
-	case pn: /* D_ASSERT( tag_type(tag) == TT_INTEGER ); */ \
-		arg->member = get_unaligned((int *)(tags));	\
-		break;
-#define NL_INT64(pn, pr, member) \
-	case pn: /* D_ASSERT( tag_type(tag) == TT_INT64 ); */ \
-		arg->member = get_unaligned((u64 *)(tags));	\
+/* Configuration is strictly serialized, because generic netlink message
+ * processing is strictly serialized by the genl_lock().
+ * Which means we can use one static global drbd_config_context struct.
+ */
+static struct drbd_config_context {
+	/* assigned from drbd_genlmsghdr */
+	unsigned int minor;
+	/* assigned from request attributes, if present */
+	unsigned int volume;
+#define VOLUME_UNSPECIFIED		(-1U)
+	/* pointer into the request skb,
+	 * limited lifetime! */
+	char *resource_name;
+	struct nlattr *my_addr;
+	struct nlattr *peer_addr;
+
+	/* reply buffer */
+	struct sk_buff *reply_skb;
+	/* pointer into reply buffer */
+	struct drbd_genlmsghdr *reply_dh;
+	/* resolved from attributes, if possible */
+	struct drbd_conf *mdev;
+	struct drbd_tconn *tconn;
+} adm_ctx;
+
+static void drbd_adm_send_reply(struct sk_buff *skb, struct genl_info *info)
+{
+	genlmsg_end(skb, genlmsg_data(nlmsg_data(nlmsg_hdr(skb))));
+	if (genlmsg_reply(skb, info))
+		printk(KERN_ERR "drbd: error sending genl reply\n");
+}
+
+/* Used on a fresh "drbd_adm_prepare"d reply_skb, this cannot fail: The only
+ * reason it could fail was no space in skb, and there are 4k available. */
+int drbd_msg_put_info(const char *info)
+{
+	struct sk_buff *skb = adm_ctx.reply_skb;
+	struct nlattr *nla;
+	int err = -EMSGSIZE;
+
+	if (!info || !info[0])
+		return 0;
+
+	nla = nla_nest_start(skb, DRBD_NLA_CFG_REPLY);
+	if (!nla)
+		return err;
+
+	err = nla_put_string(skb, T_info_text, info);
+	if (err) {
+		nla_nest_cancel(skb, nla);
+		return err;
+	} else
+		nla_nest_end(skb, nla);
+	return 0;
+}
+
+/* This would be a good candidate for a "pre_doit" hook,
+ * and per-family private info->pointers.
+ * But we need to stay compatible with older kernels.
+ * If it returns successfully, adm_ctx members are valid.
+ */
+#define DRBD_ADM_NEED_MINOR	1
+#define DRBD_ADM_NEED_RESOURCE	2
+#define DRBD_ADM_NEED_CONNECTION 4
+static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info,
+		unsigned flags)
+{
+	struct drbd_genlmsghdr *d_in = info->userhdr;
+	const u8 cmd = info->genlhdr->cmd;
+	int err;
+
+	memset(&adm_ctx, 0, sizeof(adm_ctx));
+
+	/* genl_rcv_msg only checks for CAP_NET_ADMIN on "GENL_ADMIN_PERM" :( */
+	if (cmd != DRBD_ADM_GET_STATUS && !capable(CAP_NET_ADMIN))
+	       return -EPERM;
+
+	adm_ctx.reply_skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!adm_ctx.reply_skb) {
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	adm_ctx.reply_dh = genlmsg_put_reply(adm_ctx.reply_skb,
+					info, &drbd_genl_family, 0, cmd);
+	/* put of a few bytes into a fresh skb of >= 4k will always succeed.
+	 * but anyways */
+	if (!adm_ctx.reply_dh) {
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	adm_ctx.reply_dh->minor = d_in->minor;
+	adm_ctx.reply_dh->ret_code = NO_ERROR;
+
+	adm_ctx.volume = VOLUME_UNSPECIFIED;
+	if (info->attrs[DRBD_NLA_CFG_CONTEXT]) {
+		struct nlattr *nla;
+		/* parse and validate only */
+		err = drbd_cfg_context_from_attrs(NULL, info);
+		if (err)
+			goto fail;
+
+		/* It was present, and valid,
+		 * copy it over to the reply skb. */
+		err = nla_put_nohdr(adm_ctx.reply_skb,
+				info->attrs[DRBD_NLA_CFG_CONTEXT]->nla_len,
+				info->attrs[DRBD_NLA_CFG_CONTEXT]);
+		if (err)
+			goto fail;
+
+		/* and assign stuff to the global adm_ctx */
+		nla = nested_attr_tb[__nla_type(T_ctx_volume)];
+		if (nla)
+			adm_ctx.volume = nla_get_u32(nla);
+		nla = nested_attr_tb[__nla_type(T_ctx_resource_name)];
+		if (nla)
+			adm_ctx.resource_name = nla_data(nla);
+		adm_ctx.my_addr = nested_attr_tb[__nla_type(T_ctx_my_addr)];
+		adm_ctx.peer_addr = nested_attr_tb[__nla_type(T_ctx_peer_addr)];
+		if ((adm_ctx.my_addr &&
+		     nla_len(adm_ctx.my_addr) > sizeof(adm_ctx.tconn->my_addr)) ||
+		    (adm_ctx.peer_addr &&
+		     nla_len(adm_ctx.peer_addr) > sizeof(adm_ctx.tconn->peer_addr))) {
+			err = -EINVAL;
+			goto fail;
+		}
+	}
+
+	adm_ctx.minor = d_in->minor;
+	adm_ctx.mdev = minor_to_mdev(d_in->minor);
+	adm_ctx.tconn = conn_get_by_name(adm_ctx.resource_name);
+
+	if (!adm_ctx.mdev && (flags & DRBD_ADM_NEED_MINOR)) {
+		drbd_msg_put_info("unknown minor");
+		return ERR_MINOR_INVALID;
+	}
+	if (!adm_ctx.tconn && (flags & DRBD_ADM_NEED_RESOURCE)) {
+		drbd_msg_put_info("unknown resource");
+		return ERR_INVALID_REQUEST;
+	}
+
+	if (flags & DRBD_ADM_NEED_CONNECTION) {
+		if (adm_ctx.tconn && !(flags & DRBD_ADM_NEED_RESOURCE)) {
+			drbd_msg_put_info("no resource name expected");
+			return ERR_INVALID_REQUEST;
+		}
+		if (adm_ctx.mdev) {
+			drbd_msg_put_info("no minor number expected");
+			return ERR_INVALID_REQUEST;
+		}
+		if (adm_ctx.my_addr && adm_ctx.peer_addr)
+			adm_ctx.tconn = conn_get_by_addrs(nla_data(adm_ctx.my_addr),
+							  nla_len(adm_ctx.my_addr),
+							  nla_data(adm_ctx.peer_addr),
+							  nla_len(adm_ctx.peer_addr));
+		if (!adm_ctx.tconn) {
+			drbd_msg_put_info("unknown connection");
+			return ERR_INVALID_REQUEST;
+		}
+	}
+
+	/* some more paranoia, if the request was over-determined */
+	if (adm_ctx.mdev && adm_ctx.tconn &&
+	    adm_ctx.mdev->tconn != adm_ctx.tconn) {
+		pr_warning("request: minor=%u, resource=%s; but that minor belongs to connection %s\n",
+				adm_ctx.minor, adm_ctx.resource_name,
+				adm_ctx.mdev->tconn->name);
+		drbd_msg_put_info("minor exists in different resource");
+		return ERR_INVALID_REQUEST;
+	}
+	if (adm_ctx.mdev &&
+	    adm_ctx.volume != VOLUME_UNSPECIFIED &&
+	    adm_ctx.volume != adm_ctx.mdev->vnr) {
+		pr_warning("request: minor=%u, volume=%u; but that minor is volume %u in %s\n",
+				adm_ctx.minor, adm_ctx.volume,
+				adm_ctx.mdev->vnr, adm_ctx.mdev->tconn->name);
+		drbd_msg_put_info("minor exists as different volume");
+		return ERR_INVALID_REQUEST;
+	}
+
+	return NO_ERROR;
+
+fail:
+	nlmsg_free(adm_ctx.reply_skb);
+	adm_ctx.reply_skb = NULL;
+	return err;
+}
+
+static int drbd_adm_finish(struct genl_info *info, int retcode)
+{
+	if (adm_ctx.tconn) {
+		kref_put(&adm_ctx.tconn->kref, &conn_destroy);
+		adm_ctx.tconn = NULL;
+	}
+
+	if (!adm_ctx.reply_skb)
+		return -ENOMEM;
+
+	adm_ctx.reply_dh->ret_code = retcode;
+	drbd_adm_send_reply(adm_ctx.reply_skb, info);
+	return 0;
+}
+
+static void setup_khelper_env(struct drbd_tconn *tconn, char **envp)
+{
+	char *afs;
+
+	/* FIXME: A future version will not allow this case. */
+	if (tconn->my_addr_len == 0 || tconn->peer_addr_len == 0)
+		return;
+
+	switch (((struct sockaddr *)&tconn->peer_addr)->sa_family) {
+	case AF_INET6:
+		afs = "ipv6";
+		snprintf(envp[4], 60, "DRBD_PEER_ADDRESS=%pI6",
+			 &((struct sockaddr_in6 *)&tconn->peer_addr)->sin6_addr);
 		break;
-#define NL_BIT(pn, pr, member) \
-	case pn: /* D_ASSERT( tag_type(tag) == TT_BIT ); */ \
-		arg->member = *(char *)(tags) ? 1 : 0; \
+	case AF_INET:
+		afs = "ipv4";
+		snprintf(envp[4], 60, "DRBD_PEER_ADDRESS=%pI4",
+			 &((struct sockaddr_in *)&tconn->peer_addr)->sin_addr);
 		break;
-#define NL_STRING(pn, pr, member, len) \
-	case pn: /* D_ASSERT( tag_type(tag) == TT_STRING ); */ \
-		if (dlen > len) { \
-			dev_err(DEV, "arg too long: %s (%u wanted, max len: %u bytes)\n", \
-				#member, dlen, (unsigned int)len); \
-			return 0; \
-		} \
-		 arg->member ## _len = dlen; \
-		 memcpy(arg->member, tags, min_t(size_t, dlen, len)); \
-		 break;
-#include <linux/drbd_nl.h>
-
-/* Generate the struct to tag_list functions */
-#define NL_PACKET(name, number, fields) \
-static unsigned short* \
-name ## _to_tags(struct drbd_conf *mdev, \
-	struct name *arg, unsigned short *tags) __attribute__ ((unused)); \
-static unsigned short* \
-name ## _to_tags(struct drbd_conf *mdev, \
-	struct name *arg, unsigned short *tags) \
-{ \
-	fields \
-	return tags; \
-}
-
-#define NL_INTEGER(pn, pr, member) \
-	put_unaligned(pn | pr | TT_INTEGER, tags++);	\
-	put_unaligned(sizeof(int), tags++);		\
-	put_unaligned(arg->member, (int *)tags);	\
-	tags = (unsigned short *)((char *)tags+sizeof(int));
-#define NL_INT64(pn, pr, member) \
-	put_unaligned(pn | pr | TT_INT64, tags++);	\
-	put_unaligned(sizeof(u64), tags++);		\
-	put_unaligned(arg->member, (u64 *)tags);	\
-	tags = (unsigned short *)((char *)tags+sizeof(u64));
-#define NL_BIT(pn, pr, member) \
-	put_unaligned(pn | pr | TT_BIT, tags++);	\
-	put_unaligned(sizeof(char), tags++);		\
-	*(char *)tags = arg->member; \
-	tags = (unsigned short *)((char *)tags+sizeof(char));
-#define NL_STRING(pn, pr, member, len) \
-	put_unaligned(pn | pr | TT_STRING, tags++);	\
-	put_unaligned(arg->member ## _len, tags++);	\
-	memcpy(tags, arg->member, arg->member ## _len); \
-	tags = (unsigned short *)((char *)tags + arg->member ## _len);
-#include <linux/drbd_nl.h>
-
-void drbd_bcast_ev_helper(struct drbd_conf *mdev, char *helper_name);
-void drbd_nl_send_reply(struct cn_msg *, int);
+	default:
+		afs = "ssocks";
+		snprintf(envp[4], 60, "DRBD_PEER_ADDRESS=%pI4",
+			 &((struct sockaddr_in *)&tconn->peer_addr)->sin_addr);
+	}
+	snprintf(envp[3], 20, "DRBD_PEER_AF=%s", afs);
+}
 
 int drbd_khelper(struct drbd_conf *mdev, char *cmd)
 {
 	char *envp[] = { "HOME=/",
 			"TERM=linux",
 			"PATH=/sbin:/usr/sbin:/bin:/usr/bin",
-			NULL, /* Will be set to address family */
-			NULL, /* Will be set to address */
+			 (char[20]) { }, /* address family */
+			 (char[60]) { }, /* address */
 			NULL };
-
-	char mb[12], af[20], ad[60], *afs;
+	char mb[12];
 	char *argv[] = {usermode_helper, cmd, mb, NULL };
+	struct drbd_tconn *tconn = mdev->tconn;
+	struct sib_info sib;
 	int ret;
 
-	if (current == mdev->worker.task)
-		set_bit(CALLBACK_PENDING, &mdev->flags);
+	if (current == tconn->worker.task)
+		set_bit(CALLBACK_PENDING, &tconn->flags);
 
 	snprintf(mb, 12, "minor-%d", mdev_to_minor(mdev));
-
-	if (get_net_conf(mdev)) {
-		switch (((struct sockaddr *)mdev->net_conf->peer_addr)->sa_family) {
-		case AF_INET6:
-			afs = "ipv6";
-			snprintf(ad, 60, "DRBD_PEER_ADDRESS=%pI6",
-				 &((struct sockaddr_in6 *)mdev->net_conf->peer_addr)->sin6_addr);
-			break;
-		case AF_INET:
-			afs = "ipv4";
-			snprintf(ad, 60, "DRBD_PEER_ADDRESS=%pI4",
-				 &((struct sockaddr_in *)mdev->net_conf->peer_addr)->sin_addr);
-			break;
-		default:
-			afs = "ssocks";
-			snprintf(ad, 60, "DRBD_PEER_ADDRESS=%pI4",
-				 &((struct sockaddr_in *)mdev->net_conf->peer_addr)->sin_addr);
-		}
-		snprintf(af, 20, "DRBD_PEER_AF=%s", afs);
-		envp[3]=af;
-		envp[4]=ad;
-		put_net_conf(mdev);
-	}
+	setup_khelper_env(tconn, envp);
 
 	/* The helper may take some time.
 	 * write out any unsynced meta data changes now */
 	drbd_md_sync(mdev);
 
 	dev_info(DEV, "helper command: %s %s %s\n", usermode_helper, cmd, mb);
-
-	drbd_bcast_ev_helper(mdev, cmd);
+	sib.sib_reason = SIB_HELPER_PRE;
+	sib.helper_name = cmd;
+	drbd_bcast_event(mdev, &sib);
 	ret = call_usermodehelper(usermode_helper, argv, envp, UMH_WAIT_PROC);
 	if (ret)
 		dev_warn(DEV, "helper command: %s %s %s exit code %u (0x%x)\n",
@@ -191,9 +349,46 @@ int drbd_khelper(struct drbd_conf *mdev, char *cmd)
 		dev_info(DEV, "helper command: %s %s %s exit code %u (0x%x)\n",
 				usermode_helper, cmd, mb,
 				(ret >> 8) & 0xff, ret);
+	sib.sib_reason = SIB_HELPER_POST;
+	sib.helper_exit_code = ret;
+	drbd_bcast_event(mdev, &sib);
+
+	if (current == tconn->worker.task)
+		clear_bit(CALLBACK_PENDING, &tconn->flags);
 
-	if (current == mdev->worker.task)
-		clear_bit(CALLBACK_PENDING, &mdev->flags);
+	if (ret < 0) /* Ignore any ERRNOs we got. */
+		ret = 0;
+
+	return ret;
+}
+
+int conn_khelper(struct drbd_tconn *tconn, char *cmd)
+{
+	char *envp[] = { "HOME=/",
+			"TERM=linux",
+			"PATH=/sbin:/usr/sbin:/bin:/usr/bin",
+			 (char[20]) { }, /* address family */
+			 (char[60]) { }, /* address */
+			NULL };
+	char *argv[] = {usermode_helper, cmd, tconn->name, NULL };
+	int ret;
+
+	setup_khelper_env(tconn, envp);
+	conn_md_sync(tconn);
+
+	conn_info(tconn, "helper command: %s %s %s\n", usermode_helper, cmd, tconn->name);
+	/* TODO: conn_bcast_event() ?? */
+
+	ret = call_usermodehelper(usermode_helper, argv, envp, UMH_WAIT_PROC);
+	if (ret)
+		conn_warn(tconn, "helper command: %s %s %s exit code %u (0x%x)\n",
+			  usermode_helper, cmd, tconn->name,
+			  (ret >> 8) & 0xff, ret);
+	else
+		conn_info(tconn, "helper command: %s %s %s exit code %u (0x%x)\n",
+			  usermode_helper, cmd, tconn->name,
+			  (ret >> 8) & 0xff, ret);
+	/* TODO: conn_bcast_event() ?? */
 
 	if (ret < 0) /* Ignore any ERRNOs we got. */
 		ret = 0;
@@ -201,116 +396,129 @@ int drbd_khelper(struct drbd_conf *mdev, char *cmd)
 	return ret;
 }
 
-enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev)
+static enum drbd_fencing_p highest_fencing_policy(struct drbd_tconn *tconn)
+{
+	enum drbd_fencing_p fp = FP_NOT_AVAIL;
+	struct drbd_conf *mdev;
+	int vnr;
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+		if (get_ldev_if_state(mdev, D_CONSISTENT)) {
+			fp = max_t(enum drbd_fencing_p, fp,
+				   rcu_dereference(mdev->ldev->disk_conf)->fencing);
+			put_ldev(mdev);
+		}
+	}
+	rcu_read_unlock();
+
+	return fp;
+}
+
+bool conn_try_outdate_peer(struct drbd_tconn *tconn)
 {
+	union drbd_state mask = { };
+	union drbd_state val = { };
+	enum drbd_fencing_p fp;
 	char *ex_to_string;
 	int r;
-	enum drbd_disk_state nps;
-	enum drbd_fencing_p fp;
 
-	D_ASSERT(mdev->state.pdsk == D_UNKNOWN);
+	if (tconn->cstate >= C_WF_REPORT_PARAMS) {
+		conn_err(tconn, "Expected cstate < C_WF_REPORT_PARAMS\n");
+		return false;
+	}
 
-	if (get_ldev_if_state(mdev, D_CONSISTENT)) {
-		fp = mdev->ldev->dc.fencing;
-		put_ldev(mdev);
-	} else {
-		dev_warn(DEV, "Not fencing peer, I'm not even Consistent myself.\n");
-		nps = mdev->state.pdsk;
+	fp = highest_fencing_policy(tconn);
+	switch (fp) {
+	case FP_NOT_AVAIL:
+		conn_warn(tconn, "Not fencing peer, I'm not even Consistent myself.\n");
 		goto out;
+	case FP_DONT_CARE:
+		return true;
+	default: ;
 	}
 
-	r = drbd_khelper(mdev, "fence-peer");
+	r = conn_khelper(tconn, "fence-peer");
 
 	switch ((r>>8) & 0xff) {
 	case 3: /* peer is inconsistent */
 		ex_to_string = "peer is inconsistent or worse";
-		nps = D_INCONSISTENT;
+		mask.pdsk = D_MASK;
+		val.pdsk = D_INCONSISTENT;
 		break;
 	case 4: /* peer got outdated, or was already outdated */
 		ex_to_string = "peer was fenced";
-		nps = D_OUTDATED;
+		mask.pdsk = D_MASK;
+		val.pdsk = D_OUTDATED;
 		break;
 	case 5: /* peer was down */
-		if (mdev->state.disk == D_UP_TO_DATE) {
+		if (conn_highest_disk(tconn) == D_UP_TO_DATE) {
 			/* we will(have) create(d) a new UUID anyways... */
 			ex_to_string = "peer is unreachable, assumed to be dead";
-			nps = D_OUTDATED;
+			mask.pdsk = D_MASK;
+			val.pdsk = D_OUTDATED;
 		} else {
 			ex_to_string = "peer unreachable, doing nothing since disk != UpToDate";
-			nps = mdev->state.pdsk;
 		}
 		break;
 	case 6: /* Peer is primary, voluntarily outdate myself.
 		 * This is useful when an unconnected R_SECONDARY is asked to
 		 * become R_PRIMARY, but finds the other peer being active. */
 		ex_to_string = "peer is active";
-		dev_warn(DEV, "Peer is primary, outdating myself.\n");
-		nps = D_UNKNOWN;
-		_drbd_request_state(mdev, NS(disk, D_OUTDATED), CS_WAIT_COMPLETE);
+		conn_warn(tconn, "Peer is primary, outdating myself.\n");
+		mask.disk = D_MASK;
+		val.disk = D_OUTDATED;
 		break;
 	case 7:
 		if (fp != FP_STONITH)
-			dev_err(DEV, "fence-peer() = 7 && fencing != Stonith !!!\n");
+			conn_err(tconn, "fence-peer() = 7 && fencing != Stonith !!!\n");
 		ex_to_string = "peer was stonithed";
-		nps = D_OUTDATED;
+		mask.pdsk = D_MASK;
+		val.pdsk = D_OUTDATED;
 		break;
 	default:
 		/* The script is broken ... */
-		nps = D_UNKNOWN;
-		dev_err(DEV, "fence-peer helper broken, returned %d\n", (r>>8)&0xff);
-		return nps;
+		conn_err(tconn, "fence-peer helper broken, returned %d\n", (r>>8)&0xff);
+		return false; /* Eventually leave IO frozen */
 	}
 
-	dev_info(DEV, "fence-peer helper returned %d (%s)\n",
-			(r>>8) & 0xff, ex_to_string);
+	conn_info(tconn, "fence-peer helper returned %d (%s)\n",
+		  (r>>8) & 0xff, ex_to_string);
 
-out:
-	if (mdev->state.susp_fen && nps >= D_UNKNOWN) {
-		/* The handler was not successful... unfreeze here, the
-		   state engine can not unfreeze... */
-		_drbd_request_state(mdev, NS(susp_fen, 0), CS_VERBOSE);
-	}
+ out:
 
-	return nps;
+	/* Not using
+	   conn_request_state(tconn, mask, val, CS_VERBOSE);
+	   here, because we might were able to re-establish the connection in the
+	   meantime. */
+	spin_lock_irq(&tconn->req_lock);
+	if (tconn->cstate < C_WF_REPORT_PARAMS && !test_bit(STATE_SENT, &tconn->flags))
+		_conn_request_state(tconn, mask, val, CS_VERBOSE);
+	spin_unlock_irq(&tconn->req_lock);
+
+	return conn_highest_pdsk(tconn) <= D_OUTDATED;
 }
 
 static int _try_outdate_peer_async(void *data)
 {
-	struct drbd_conf *mdev = (struct drbd_conf *)data;
-	enum drbd_disk_state nps;
-	union drbd_state ns;
+	struct drbd_tconn *tconn = (struct drbd_tconn *)data;
 
-	nps = drbd_try_outdate_peer(mdev);
-
-	/* Not using
-	   drbd_request_state(mdev, NS(pdsk, nps));
-	   here, because we might were able to re-establish the connection
-	   in the meantime. This can only partially be solved in the state's
-	   engine is_valid_state() and is_valid_state_transition()
-	   functions.
-
-	   nps can be D_INCONSISTENT, D_OUTDATED or D_UNKNOWN.
-	   pdsk == D_INCONSISTENT while conn >= C_CONNECTED is valid,
-	   therefore we have to have the pre state change check here.
-	*/
-	spin_lock_irq(&mdev->req_lock);
-	ns = mdev->state;
-	if (ns.conn < C_WF_REPORT_PARAMS && !test_bit(STATE_SENT, &mdev->flags)) {
-		ns.pdsk = nps;
-		_drbd_set_state(mdev, ns, CS_VERBOSE, NULL);
-	}
-	spin_unlock_irq(&mdev->req_lock);
+	conn_try_outdate_peer(tconn);
 
+	kref_put(&tconn->kref, &conn_destroy);
 	return 0;
 }
 
-void drbd_try_outdate_peer_async(struct drbd_conf *mdev)
+void conn_try_outdate_peer_async(struct drbd_tconn *tconn)
 {
 	struct task_struct *opa;
 
-	opa = kthread_run(_try_outdate_peer_async, mdev, "drbd%d_a_helper", mdev_to_minor(mdev));
-	if (IS_ERR(opa))
-		dev_err(DEV, "out of mem, failed to invoke fence-peer helper\n");
+	kref_get(&tconn->kref);
+	opa = kthread_run(_try_outdate_peer_async, tconn, "drbd_async_h");
+	if (IS_ERR(opa)) {
+		conn_err(tconn, "out of mem, failed to invoke fence-peer helper\n");
+		kref_put(&tconn->kref, &conn_destroy);
+	}
 }
 
 enum drbd_state_rv
@@ -318,15 +526,15 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 {
 	const int max_tries = 4;
 	enum drbd_state_rv rv = SS_UNKNOWN_ERROR;
+	struct net_conf *nc;
 	int try = 0;
 	int forced = 0;
 	union drbd_state mask, val;
-	enum drbd_disk_state nps;
 
 	if (new_role == R_PRIMARY)
-		request_ping(mdev); /* Detect a dead peer ASAP */
+		request_ping(mdev->tconn); /* Detect a dead peer ASAP */
 
-	mutex_lock(&mdev->state_mutex);
+	mutex_lock(mdev->state_mutex);
 
 	mask.i = 0; mask.role = R_MASK;
 	val.i  = 0; val.role  = new_role;
@@ -354,38 +562,34 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 		if (rv == SS_NO_UP_TO_DATE_DISK &&
 		    mdev->state.disk == D_CONSISTENT && mask.pdsk == 0) {
 			D_ASSERT(mdev->state.pdsk == D_UNKNOWN);
-			nps = drbd_try_outdate_peer(mdev);
 
-			if (nps == D_OUTDATED || nps == D_INCONSISTENT) {
+			if (conn_try_outdate_peer(mdev->tconn)) {
 				val.disk = D_UP_TO_DATE;
 				mask.disk = D_MASK;
 			}
-
-			val.pdsk = nps;
-			mask.pdsk = D_MASK;
-
 			continue;
 		}
 
 		if (rv == SS_NOTHING_TO_DO)
-			goto fail;
+			goto out;
 		if (rv == SS_PRIMARY_NOP && mask.pdsk == 0) {
-			nps = drbd_try_outdate_peer(mdev);
-
-			if (force && nps > D_OUTDATED) {
+			if (!conn_try_outdate_peer(mdev->tconn) && force) {
 				dev_warn(DEV, "Forced into split brain situation!\n");
-				nps = D_OUTDATED;
-			}
-
-			mask.pdsk = D_MASK;
-			val.pdsk  = nps;
+				mask.pdsk = D_MASK;
+				val.pdsk  = D_OUTDATED;
 
+			}
 			continue;
 		}
 		if (rv == SS_TWO_PRIMARIES) {
 			/* Maybe the peer is detected as dead very soon...
 			   retry at most once more in this case. */
-			schedule_timeout_interruptible((mdev->net_conf->ping_timeo+1)*HZ/10);
+			int timeo;
+			rcu_read_lock();
+			nc = rcu_dereference(mdev->tconn->net_conf);
+			timeo = nc ? (nc->ping_timeo + 1) * HZ / 10 : 1;
+			rcu_read_unlock();
+			schedule_timeout_interruptible(timeo);
 			if (try < max_tries)
 				try = max_tries - 1;
 			continue;
@@ -394,13 +598,13 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 			rv = _drbd_request_state(mdev, mask, val,
 						CS_VERBOSE + CS_WAIT_COMPLETE);
 			if (rv < SS_SUCCESS)
-				goto fail;
+				goto out;
 		}
 		break;
 	}
 
 	if (rv < SS_SUCCESS)
-		goto fail;
+		goto out;
 
 	if (forced)
 		dev_warn(DEV, "Forced to consider local data as UpToDate!\n");
@@ -408,6 +612,8 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 	/* Wait until nothing is on the fly :) */
 	wait_event(mdev->misc_wait, atomic_read(&mdev->ap_pending_cnt) == 0);
 
+	/* FIXME also wait for all pending P_BARRIER_ACK? */
+
 	if (new_role == R_SECONDARY) {
 		set_disk_ro(mdev->vdisk, true);
 		if (get_ldev(mdev)) {
@@ -415,10 +621,12 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 			put_ldev(mdev);
 		}
 	} else {
-		if (get_net_conf(mdev)) {
-			mdev->net_conf->want_lose = 0;
-			put_net_conf(mdev);
-		}
+		mutex_lock(&mdev->tconn->conf_update);
+		nc = mdev->tconn->net_conf;
+		if (nc)
+			nc->discard_my_data = 0; /* without copy; single bit op is atomic */
+		mutex_unlock(&mdev->tconn->conf_update);
+
 		set_disk_ro(mdev->vdisk, false);
 		if (get_ldev(mdev)) {
 			if (((mdev->state.conn < C_CONNECTED ||
@@ -444,67 +652,47 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 	drbd_md_sync(mdev);
 
 	kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE);
- fail:
-	mutex_unlock(&mdev->state_mutex);
+out:
+	mutex_unlock(mdev->state_mutex);
 	return rv;
 }
 
-static struct drbd_conf *ensure_mdev(int minor, int create)
+static const char *from_attrs_err_to_txt(int err)
 {
-	struct drbd_conf *mdev;
-
-	if (minor >= minor_count)
-		return NULL;
-
-	mdev = minor_to_mdev(minor);
-
-	if (!mdev && create) {
-		struct gendisk *disk = NULL;
-		mdev = drbd_new_device(minor);
-
-		spin_lock_irq(&drbd_pp_lock);
-		if (minor_table[minor] == NULL) {
-			minor_table[minor] = mdev;
-			disk = mdev->vdisk;
-			mdev = NULL;
-		} /* else: we lost the race */
-		spin_unlock_irq(&drbd_pp_lock);
-
-		if (disk) /* we won the race above */
-			/* in case we ever add a drbd_delete_device(),
-			 * don't forget the del_gendisk! */
-			add_disk(disk);
-		else /* we lost the race above */
-			drbd_free_mdev(mdev);
-
-		mdev = minor_to_mdev(minor);
-	}
-
-	return mdev;
+	return	err == -ENOMSG ? "required attribute missing" :
+		err == -EOPNOTSUPP ? "unknown mandatory attribute" :
+		err == -EEXIST ? "can not change invariant setting" :
+		"invalid attribute value";
 }
 
-static int drbd_nl_primary(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			   struct drbd_nl_cfg_reply *reply)
+int drbd_adm_set_role(struct sk_buff *skb, struct genl_info *info)
 {
-	struct primary primary_args;
-
-	memset(&primary_args, 0, sizeof(struct primary));
-	if (!primary_from_tags(mdev, nlp->tag_list, &primary_args)) {
-		reply->ret_code = ERR_MANDATORY_TAG;
-		return 0;
-	}
-
-	reply->ret_code =
-		drbd_set_role(mdev, R_PRIMARY, primary_args.primary_force);
+	struct set_role_parms parms;
+	int err;
+	enum drbd_ret_code retcode;
 
-	return 0;
-}
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
 
-static int drbd_nl_secondary(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			     struct drbd_nl_cfg_reply *reply)
-{
-	reply->ret_code = drbd_set_role(mdev, R_SECONDARY, 0);
+	memset(&parms, 0, sizeof(parms));
+	if (info->attrs[DRBD_NLA_SET_ROLE_PARMS]) {
+		err = set_role_parms_from_attrs(&parms, info);
+		if (err) {
+			retcode = ERR_MANDATORY_TAG;
+			drbd_msg_put_info(from_attrs_err_to_txt(err));
+			goto out;
+		}
+	}
 
+	if (info->genlhdr->cmd == DRBD_ADM_PRIMARY)
+		retcode = drbd_set_role(adm_ctx.mdev, R_PRIMARY, parms.assume_uptodate);
+	else
+		retcode = drbd_set_role(adm_ctx.mdev, R_SECONDARY, 0);
+out:
+	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
@@ -514,7 +702,12 @@ static void drbd_md_set_sector_offsets(struct drbd_conf *mdev,
 				       struct drbd_backing_dev *bdev)
 {
 	sector_t md_size_sect = 0;
-	switch (bdev->dc.meta_dev_idx) {
+	int meta_dev_idx;
+
+	rcu_read_lock();
+	meta_dev_idx = rcu_dereference(bdev->disk_conf)->meta_dev_idx;
+
+	switch (meta_dev_idx) {
 	default:
 		/* v07 style fixed size indexed meta data */
 		bdev->md.md_size_sect = MD_RESERVED_SECT;
@@ -533,7 +726,7 @@ static void drbd_md_set_sector_offsets(struct drbd_conf *mdev,
 	case DRBD_MD_INDEX_FLEX_INT:
 		bdev->md.md_offset = drbd_md_ss__(mdev, bdev);
 		/* al size is still fixed */
-		bdev->md.al_offset = -MD_AL_MAX_SIZE;
+		bdev->md.al_offset = -MD_AL_SECTORS;
 		/* we need (slightly less than) ~ this much bitmap sectors: */
 		md_size_sect = drbd_get_capacity(bdev->backing_bdev);
 		md_size_sect = ALIGN(md_size_sect, BM_SECT_PER_EXT);
@@ -549,6 +742,7 @@ static void drbd_md_set_sector_offsets(struct drbd_conf *mdev,
 		bdev->md.bm_offset   = -md_size_sect + MD_AL_OFFSET;
 		break;
 	}
+	rcu_read_unlock();
 }
 
 /* input size is expected to be in KB */
@@ -581,10 +775,16 @@ char *ppsize(char *buf, unsigned long long size)
  *  R_PRIMARY D_INCONSISTENT, and C_SYNC_TARGET:
  *  peer may not initiate a resize.
  */
+/* Note these are not to be confused with
+ * drbd_adm_suspend_io/drbd_adm_resume_io,
+ * which are (sub) state changes triggered by admin (drbdsetup),
+ * and can be long lived.
+ * This changes an mdev->flag, is triggered by drbd internals,
+ * and should be short-lived. */
 void drbd_suspend_io(struct drbd_conf *mdev)
 {
 	set_bit(SUSPEND_IO, &mdev->flags);
-	if (is_susp(mdev->state))
+	if (drbd_suspended(mdev))
 		return;
 	wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
 }
@@ -605,7 +805,7 @@ void drbd_resume_io(struct drbd_conf *mdev)
 enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *mdev, enum dds_flags flags) __must_hold(local)
 {
 	sector_t prev_first_sect, prev_size; /* previous meta location */
-	sector_t la_size;
+	sector_t la_size, u_size;
 	sector_t size;
 	char ppb[10];
 
@@ -633,7 +833,10 @@ enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *mdev, enum dds
 	/* TODO: should only be some assert here, not (re)init... */
 	drbd_md_set_sector_offsets(mdev, mdev->ldev);
 
-	size = drbd_new_dev_size(mdev, mdev->ldev, flags & DDSF_FORCED);
+	rcu_read_lock();
+	u_size = rcu_dereference(mdev->ldev->disk_conf)->disk_size;
+	rcu_read_unlock();
+	size = drbd_new_dev_size(mdev, mdev->ldev, u_size, flags & DDSF_FORCED);
 
 	if (drbd_get_capacity(mdev->this_bdev) != size ||
 	    drbd_bm_capacity(mdev) != size) {
@@ -696,12 +899,12 @@ out:
 }
 
 sector_t
-drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev, int assume_peer_has_space)
+drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
+		  sector_t u_size, int assume_peer_has_space)
 {
 	sector_t p_size = mdev->p_size;   /* partner's disk size. */
 	sector_t la_size = bdev->md.la_size_sect; /* last agreed size. */
 	sector_t m_size; /* my size */
-	sector_t u_size = bdev->dc.disk_size; /* size requested by user. */
 	sector_t size = 0;
 
 	m_size = drbd_get_max_capacity(bdev);
@@ -750,24 +953,21 @@ drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev, int ass
  * failed, and 0 on success. You should call drbd_md_sync() after you called
  * this function.
  */
-static int drbd_check_al_size(struct drbd_conf *mdev)
+static int drbd_check_al_size(struct drbd_conf *mdev, struct disk_conf *dc)
 {
 	struct lru_cache *n, *t;
 	struct lc_element *e;
 	unsigned int in_use;
 	int i;
 
-	ERR_IF(mdev->sync_conf.al_extents < 7)
-		mdev->sync_conf.al_extents = 127;
-
 	if (mdev->act_log &&
-	    mdev->act_log->nr_elements == mdev->sync_conf.al_extents)
+	    mdev->act_log->nr_elements == dc->al_extents)
 		return 0;
 
 	in_use = 0;
 	t = mdev->act_log;
-	n = lc_create("act_log", drbd_al_ext_cache,
-		mdev->sync_conf.al_extents, sizeof(struct lc_element), 0);
+	n = lc_create("act_log", drbd_al_ext_cache, AL_UPDATES_PER_TRANSACTION,
+		dc->al_extents, sizeof(struct lc_element), 0);
 
 	if (n == NULL) {
 		dev_err(DEV, "Cannot allocate act_log lru!\n");
@@ -808,7 +1008,9 @@ static void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_bio_
 		struct request_queue * const b = mdev->ldev->backing_bdev->bd_disk->queue;
 
 		max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9);
-		max_segments = mdev->ldev->dc.max_bio_bvecs;
+		rcu_read_lock();
+		max_segments = rcu_dereference(mdev->ldev->disk_conf)->max_bio_bvecs;
+		rcu_read_unlock();
 		put_ldev(mdev);
 	}
 
@@ -852,12 +1054,14 @@ void drbd_reconsider_max_bio_size(struct drbd_conf *mdev)
 	   Because new from 8.3.8 onwards the peer can use multiple
 	   BIOs for a single peer_request */
 	if (mdev->state.conn >= C_CONNECTED) {
-		if (mdev->agreed_pro_version < 94) {
-			peer = min(mdev->peer_max_bio_size, DRBD_MAX_SIZE_H80_PACKET);
+		if (mdev->tconn->agreed_pro_version < 94)
+			peer = min( mdev->peer_max_bio_size, DRBD_MAX_SIZE_H80_PACKET);
 			/* Correct old drbd (up to 8.3.7) if it believes it can do more than 32KiB */
-		} else if (mdev->agreed_pro_version == 94)
+		else if (mdev->tconn->agreed_pro_version == 94)
 			peer = DRBD_MAX_SIZE_H80_PACKET;
-		else /* drbd 8.3.8 onwards */
+		else if (mdev->tconn->agreed_pro_version < 100)
+			peer = DRBD_MAX_BIO_SIZE_P95;  /* drbd 8.3.8 onwards, before 8.4.0 */
+		else
 			peer = DRBD_MAX_BIO_SIZE;
 	}
 
@@ -872,36 +1076,27 @@ void drbd_reconsider_max_bio_size(struct drbd_conf *mdev)
 	drbd_setup_queue_param(mdev, new);
 }
 
-/* serialize deconfig (worker exiting, doing cleanup)
- * and reconfig (drbdsetup disk, drbdsetup net)
- *
- * Wait for a potentially exiting worker, then restart it,
- * or start a new one.  Flush any pending work, there may still be an
- * after_state_change queued.
- */
-static void drbd_reconfig_start(struct drbd_conf *mdev)
+/* Starts the worker thread */
+static void conn_reconfig_start(struct drbd_tconn *tconn)
 {
-	wait_event(mdev->state_wait, !test_and_set_bit(CONFIG_PENDING, &mdev->flags));
-	wait_event(mdev->state_wait, !test_bit(DEVICE_DYING, &mdev->flags));
-	drbd_thread_start(&mdev->worker);
-	drbd_flush_workqueue(mdev);
+	drbd_thread_start(&tconn->worker);
+	conn_flush_workqueue(tconn);
 }
 
-/* if still unconfigured, stops worker again.
- * if configured now, clears CONFIG_PENDING.
- * wakes potential waiters */
-static void drbd_reconfig_done(struct drbd_conf *mdev)
+/* if still unconfigured, stops worker again. */
+static void conn_reconfig_done(struct drbd_tconn *tconn)
 {
-	spin_lock_irq(&mdev->req_lock);
-	if (mdev->state.disk == D_DISKLESS &&
-	    mdev->state.conn == C_STANDALONE &&
-	    mdev->state.role == R_SECONDARY) {
-		set_bit(DEVICE_DYING, &mdev->flags);
-		drbd_thread_stop_nowait(&mdev->worker);
-	} else
-		clear_bit(CONFIG_PENDING, &mdev->flags);
-	spin_unlock_irq(&mdev->req_lock);
-	wake_up(&mdev->state_wait);
+	bool stop_threads;
+	spin_lock_irq(&tconn->req_lock);
+	stop_threads = conn_all_vols_unconf(tconn) &&
+		tconn->cstate == C_STANDALONE;
+	spin_unlock_irq(&tconn->req_lock);
+	if (stop_threads) {
+		/* asender is implicitly stopped by receiver
+		 * in conn_disconnect() */
+		drbd_thread_stop(&tconn->receiver);
+		drbd_thread_stop(&tconn->worker);
+	}
 }
 
 /* Make sure IO is suspended before calling this function(). */
@@ -909,42 +1104,182 @@ static void drbd_suspend_al(struct drbd_conf *mdev)
 {
 	int s = 0;
 
-	if (lc_try_lock(mdev->act_log)) {
-		drbd_al_shrink(mdev);
-		lc_unlock(mdev->act_log);
-	} else {
+	if (!lc_try_lock(mdev->act_log)) {
 		dev_warn(DEV, "Failed to lock al in drbd_suspend_al()\n");
 		return;
 	}
 
-	spin_lock_irq(&mdev->req_lock);
+	drbd_al_shrink(mdev);
+	spin_lock_irq(&mdev->tconn->req_lock);
 	if (mdev->state.conn < C_CONNECTED)
 		s = !test_and_set_bit(AL_SUSPENDED, &mdev->flags);
-
-	spin_unlock_irq(&mdev->req_lock);
+	spin_unlock_irq(&mdev->tconn->req_lock);
+	lc_unlock(mdev->act_log);
 
 	if (s)
 		dev_info(DEV, "Suspended AL updates\n");
 }
 
-/* does always return 0;
- * interesting return code is in reply->ret_code */
-static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			     struct drbd_nl_cfg_reply *reply)
+
+static bool should_set_defaults(struct genl_info *info)
+{
+	unsigned flags = ((struct drbd_genlmsghdr*)info->userhdr)->flags;
+	return 0 != (flags & DRBD_GENL_F_SET_DEFAULTS);
+}
+
+static void enforce_disk_conf_limits(struct disk_conf *dc)
+{
+	if (dc->al_extents < DRBD_AL_EXTENTS_MIN)
+		dc->al_extents = DRBD_AL_EXTENTS_MIN;
+	if (dc->al_extents > DRBD_AL_EXTENTS_MAX)
+		dc->al_extents = DRBD_AL_EXTENTS_MAX;
+
+	if (dc->c_plan_ahead > DRBD_C_PLAN_AHEAD_MAX)
+		dc->c_plan_ahead = DRBD_C_PLAN_AHEAD_MAX;
+}
+
+int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
+{
+	enum drbd_ret_code retcode;
+	struct drbd_conf *mdev;
+	struct disk_conf *new_disk_conf, *old_disk_conf;
+	struct fifo_buffer *old_plan = NULL, *new_plan = NULL;
+	int err, fifo_size;
+
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
+
+	mdev = adm_ctx.mdev;
+
+	/* we also need a disk
+	 * to change the options on */
+	if (!get_ldev(mdev)) {
+		retcode = ERR_NO_DISK;
+		goto out;
+	}
+
+	new_disk_conf = kmalloc(sizeof(struct disk_conf), GFP_KERNEL);
+	if (!new_disk_conf) {
+		retcode = ERR_NOMEM;
+		goto fail;
+	}
+
+	mutex_lock(&mdev->tconn->conf_update);
+	old_disk_conf = mdev->ldev->disk_conf;
+	*new_disk_conf = *old_disk_conf;
+	if (should_set_defaults(info))
+		set_disk_conf_defaults(new_disk_conf);
+
+	err = disk_conf_from_attrs_for_change(new_disk_conf, info);
+	if (err && err != -ENOMSG) {
+		retcode = ERR_MANDATORY_TAG;
+		drbd_msg_put_info(from_attrs_err_to_txt(err));
+	}
+
+	if (!expect(new_disk_conf->resync_rate >= 1))
+		new_disk_conf->resync_rate = 1;
+
+	enforce_disk_conf_limits(new_disk_conf);
+
+	fifo_size = (new_disk_conf->c_plan_ahead * 10 * SLEEP_TIME) / HZ;
+	if (fifo_size != mdev->rs_plan_s->size) {
+		new_plan = fifo_alloc(fifo_size);
+		if (!new_plan) {
+			dev_err(DEV, "kmalloc of fifo_buffer failed");
+			retcode = ERR_NOMEM;
+			goto fail_unlock;
+		}
+	}
+
+	drbd_suspend_io(mdev);
+	wait_event(mdev->al_wait, lc_try_lock(mdev->act_log));
+	drbd_al_shrink(mdev);
+	err = drbd_check_al_size(mdev, new_disk_conf);
+	lc_unlock(mdev->act_log);
+	wake_up(&mdev->al_wait);
+	drbd_resume_io(mdev);
+
+	if (err) {
+		retcode = ERR_NOMEM;
+		goto fail_unlock;
+	}
+
+	write_lock_irq(&global_state_lock);
+	retcode = drbd_resync_after_valid(mdev, new_disk_conf->resync_after);
+	if (retcode == NO_ERROR) {
+		rcu_assign_pointer(mdev->ldev->disk_conf, new_disk_conf);
+		drbd_resync_after_changed(mdev);
+	}
+	write_unlock_irq(&global_state_lock);
+
+	if (retcode != NO_ERROR)
+		goto fail_unlock;
+
+	if (new_plan) {
+		old_plan = mdev->rs_plan_s;
+		rcu_assign_pointer(mdev->rs_plan_s, new_plan);
+	}
+
+	mutex_unlock(&mdev->tconn->conf_update);
+
+	if (new_disk_conf->al_updates)
+		mdev->ldev->md.flags &= ~MDF_AL_DISABLED;
+	else
+		mdev->ldev->md.flags |= MDF_AL_DISABLED;
+
+	drbd_bump_write_ordering(mdev->tconn, WO_bdev_flush);
+
+	drbd_md_sync(mdev);
+
+	if (mdev->state.conn >= C_CONNECTED)
+		drbd_send_sync_param(mdev);
+
+	synchronize_rcu();
+	kfree(old_disk_conf);
+	kfree(old_plan);
+	mod_timer(&mdev->request_timer, jiffies + HZ);
+	goto success;
+
+fail_unlock:
+	mutex_unlock(&mdev->tconn->conf_update);
+ fail:
+	kfree(new_disk_conf);
+	kfree(new_plan);
+success:
+	put_ldev(mdev);
+ out:
+	drbd_adm_finish(info, retcode);
+	return 0;
+}
+
+int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
 {
+	struct drbd_conf *mdev;
+	int err;
 	enum drbd_ret_code retcode;
 	enum determine_dev_size dd;
 	sector_t max_possible_sectors;
 	sector_t min_md_device_sectors;
 	struct drbd_backing_dev *nbc = NULL; /* new_backing_conf */
+	struct disk_conf *new_disk_conf = NULL;
 	struct block_device *bdev;
 	struct lru_cache *resync_lru = NULL;
+	struct fifo_buffer *new_plan = NULL;
 	union drbd_state ns, os;
 	enum drbd_state_rv rv;
-	int cp_discovered = 0;
-	int logical_block_size;
+	struct net_conf *nc;
+
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto finish;
 
-	drbd_reconfig_start(mdev);
+	mdev = adm_ctx.mdev;
+	conn_reconfig_start(mdev->tconn);
 
 	/* if you want to reconfigure, please tear down first */
 	if (mdev->state.disk > D_DISKLESS) {
@@ -959,47 +1294,65 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 
 	/* make sure there is no leftover from previous force-detach attempts */
 	clear_bit(FORCE_DETACH, &mdev->flags);
+	clear_bit(WAS_IO_ERROR, &mdev->flags);
+	clear_bit(WAS_READ_ERROR, &mdev->flags);
 
 	/* and no leftover from previously aborted resync or verify, either */
 	mdev->rs_total = 0;
 	mdev->rs_failed = 0;
 	atomic_set(&mdev->rs_pending_cnt, 0);
 
-	/* allocation not in the IO path, cqueue thread context */
+	/* allocation not in the IO path, drbdsetup context */
 	nbc = kzalloc(sizeof(struct drbd_backing_dev), GFP_KERNEL);
 	if (!nbc) {
 		retcode = ERR_NOMEM;
 		goto fail;
 	}
+	spin_lock_init(&nbc->md.uuid_lock);
 
-	nbc->dc.disk_size     = DRBD_DISK_SIZE_SECT_DEF;
-	nbc->dc.on_io_error   = DRBD_ON_IO_ERROR_DEF;
-	nbc->dc.fencing       = DRBD_FENCING_DEF;
-	nbc->dc.max_bio_bvecs = DRBD_MAX_BIO_BVECS_DEF;
+	new_disk_conf = kzalloc(sizeof(struct disk_conf), GFP_KERNEL);
+	if (!new_disk_conf) {
+		retcode = ERR_NOMEM;
+		goto fail;
+	}
+	nbc->disk_conf = new_disk_conf;
 
-	if (!disk_conf_from_tags(mdev, nlp->tag_list, &nbc->dc)) {
+	set_disk_conf_defaults(new_disk_conf);
+	err = disk_conf_from_attrs(new_disk_conf, info);
+	if (err) {
 		retcode = ERR_MANDATORY_TAG;
+		drbd_msg_put_info(from_attrs_err_to_txt(err));
 		goto fail;
 	}
 
-	if (nbc->dc.meta_dev_idx < DRBD_MD_INDEX_FLEX_INT) {
-		retcode = ERR_MD_IDX_INVALID;
+	enforce_disk_conf_limits(new_disk_conf);
+
+	new_plan = fifo_alloc((new_disk_conf->c_plan_ahead * 10 * SLEEP_TIME) / HZ);
+	if (!new_plan) {
+		retcode = ERR_NOMEM;
 		goto fail;
 	}
 
-	if (get_net_conf(mdev)) {
-		int prot = mdev->net_conf->wire_protocol;
-		put_net_conf(mdev);
-		if (nbc->dc.fencing == FP_STONITH && prot == DRBD_PROT_A) {
-			retcode = ERR_STONITH_AND_PROT_A;
+	if (new_disk_conf->meta_dev_idx < DRBD_MD_INDEX_FLEX_INT) {
+		retcode = ERR_MD_IDX_INVALID;
+		goto fail;
+	}
+
+	rcu_read_lock();
+	nc = rcu_dereference(mdev->tconn->net_conf);
+	if (nc) {
+		if (new_disk_conf->fencing == FP_STONITH && nc->wire_protocol == DRBD_PROT_A) {
+			rcu_read_unlock();
+			retcode = ERR_STONITH_AND_PROT_A;
 			goto fail;
 		}
 	}
+	rcu_read_unlock();
 
-	bdev = blkdev_get_by_path(nbc->dc.backing_dev,
+	bdev = blkdev_get_by_path(new_disk_conf->backing_dev,
 				  FMODE_READ | FMODE_WRITE | FMODE_EXCL, mdev);
 	if (IS_ERR(bdev)) {
-		dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.backing_dev,
+		dev_err(DEV, "open(\"%s\") failed with %ld\n", new_disk_conf->backing_dev,
 			PTR_ERR(bdev));
 		retcode = ERR_OPEN_DISK;
 		goto fail;
@@ -1014,12 +1367,12 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 	 * should check it for you already; but if you don't, or
 	 * someone fooled it, we need to double check here)
 	 */
-	bdev = blkdev_get_by_path(nbc->dc.meta_dev,
+	bdev = blkdev_get_by_path(new_disk_conf->meta_dev,
 				  FMODE_READ | FMODE_WRITE | FMODE_EXCL,
-				  (nbc->dc.meta_dev_idx < 0) ?
+				  (new_disk_conf->meta_dev_idx < 0) ?
 				  (void *)mdev : (void *)drbd_m_holder);
 	if (IS_ERR(bdev)) {
-		dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.meta_dev,
+		dev_err(DEV, "open(\"%s\") failed with %ld\n", new_disk_conf->meta_dev,
 			PTR_ERR(bdev));
 		retcode = ERR_OPEN_MD_DISK;
 		goto fail;
@@ -1027,14 +1380,14 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 	nbc->md_bdev = bdev;
 
 	if ((nbc->backing_bdev == nbc->md_bdev) !=
-	    (nbc->dc.meta_dev_idx == DRBD_MD_INDEX_INTERNAL ||
-	     nbc->dc.meta_dev_idx == DRBD_MD_INDEX_FLEX_INT)) {
+	    (new_disk_conf->meta_dev_idx == DRBD_MD_INDEX_INTERNAL ||
+	     new_disk_conf->meta_dev_idx == DRBD_MD_INDEX_FLEX_INT)) {
 		retcode = ERR_MD_IDX_INVALID;
 		goto fail;
 	}
 
 	resync_lru = lc_create("resync", drbd_bm_ext_cache,
-			61, sizeof(struct bm_extent),
+			1, 61, sizeof(struct bm_extent),
 			offsetof(struct bm_extent, lce));
 	if (!resync_lru) {
 		retcode = ERR_NOMEM;
@@ -1044,21 +1397,21 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 	/* RT - for drbd_get_max_capacity() DRBD_MD_INDEX_FLEX_INT */
 	drbd_md_set_sector_offsets(mdev, nbc);
 
-	if (drbd_get_max_capacity(nbc) < nbc->dc.disk_size) {
+	if (drbd_get_max_capacity(nbc) < new_disk_conf->disk_size) {
 		dev_err(DEV, "max capacity %llu smaller than disk size %llu\n",
 			(unsigned long long) drbd_get_max_capacity(nbc),
-			(unsigned long long) nbc->dc.disk_size);
+			(unsigned long long) new_disk_conf->disk_size);
 		retcode = ERR_DISK_TOO_SMALL;
 		goto fail;
 	}
 
-	if (nbc->dc.meta_dev_idx < 0) {
+	if (new_disk_conf->meta_dev_idx < 0) {
 		max_possible_sectors = DRBD_MAX_SECTORS_FLEX;
 		/* at least one MB, otherwise it does not make sense */
 		min_md_device_sectors = (2<<10);
 	} else {
 		max_possible_sectors = DRBD_MAX_SECTORS;
-		min_md_device_sectors = MD_RESERVED_SECT * (nbc->dc.meta_dev_idx + 1);
+		min_md_device_sectors = MD_RESERVED_SECT * (new_disk_conf->meta_dev_idx + 1);
 	}
 
 	if (drbd_get_capacity(nbc->md_bdev) < min_md_device_sectors) {
@@ -1083,14 +1436,20 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 		dev_warn(DEV, "==> truncating very big lower level device "
 			"to currently maximum possible %llu sectors <==\n",
 			(unsigned long long) max_possible_sectors);
-		if (nbc->dc.meta_dev_idx >= 0)
+		if (new_disk_conf->meta_dev_idx >= 0)
 			dev_warn(DEV, "==>> using internal or flexible "
 				      "meta data may help <<==\n");
 	}
 
 	drbd_suspend_io(mdev);
 	/* also wait for the last barrier ack. */
-	wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_pending_cnt) || is_susp(mdev->state));
+	/* FIXME see also https://daiquiri.linbit/cgi-bin/bugzilla/show_bug.cgi?id=171
+	 * We need a way to either ignore barrier acks for barriers sent before a device
+	 * was attached, or a way to wait for all pending barrier acks to come in.
+	 * As barriers are counted per resource,
+	 * we'd need to suspend io on all devices of a resource.
+	 */
+	wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_pending_cnt) || drbd_suspended(mdev));
 	/* and for any other previously queued work */
 	drbd_flush_workqueue(mdev);
 
@@ -1105,25 +1464,6 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 
 	drbd_md_set_sector_offsets(mdev, nbc);
 
-	/* allocate a second IO page if logical_block_size != 512 */
-	logical_block_size = bdev_logical_block_size(nbc->md_bdev);
-	if (logical_block_size == 0)
-		logical_block_size = MD_SECTOR_SIZE;
-
-	if (logical_block_size != MD_SECTOR_SIZE) {
-		if (!mdev->md_io_tmpp) {
-			struct page *page = alloc_page(GFP_NOIO);
-			if (!page)
-				goto force_diskless_dec;
-
-			dev_warn(DEV, "Meta data's bdev logical_block_size = %d != %d\n",
-			     logical_block_size, MD_SECTOR_SIZE);
-			dev_warn(DEV, "Workaround engaged (has performance impact).\n");
-
-			mdev->md_io_tmpp = page;
-		}
-	}
-
 	if (!mdev->bitmap) {
 		if (drbd_bm_init(mdev)) {
 			retcode = ERR_NOMEM;
@@ -1145,30 +1485,25 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 	}
 
 	/* Since we are diskless, fix the activity log first... */
-	if (drbd_check_al_size(mdev)) {
+	if (drbd_check_al_size(mdev, new_disk_conf)) {
 		retcode = ERR_NOMEM;
 		goto force_diskless_dec;
 	}
 
 	/* Prevent shrinking of consistent devices ! */
 	if (drbd_md_test_flag(nbc, MDF_CONSISTENT) &&
-	    drbd_new_dev_size(mdev, nbc, 0) < nbc->md.la_size_sect) {
+	    drbd_new_dev_size(mdev, nbc, nbc->disk_conf->disk_size, 0) < nbc->md.la_size_sect) {
 		dev_warn(DEV, "refusing to truncate a consistent device\n");
 		retcode = ERR_DISK_TOO_SMALL;
 		goto force_diskless_dec;
 	}
 
-	if (!drbd_al_read_log(mdev, nbc)) {
-		retcode = ERR_IO_MD_DISK;
-		goto force_diskless_dec;
-	}
-
 	/* Reset the "barriers don't work" bits here, then force meta data to
 	 * be written, to ensure we determine if barriers are supported. */
-	if (nbc->dc.no_md_flush)
-		set_bit(MD_NO_FUA, &mdev->flags);
-	else
+	if (new_disk_conf->md_flushes)
 		clear_bit(MD_NO_FUA, &mdev->flags);
+	else
+		set_bit(MD_NO_FUA, &mdev->flags);
 
 	/* Point of no return reached.
 	 * Devices and memory are no longer released by error cleanup below.
@@ -1177,11 +1512,13 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 	D_ASSERT(mdev->ldev == NULL);
 	mdev->ldev = nbc;
 	mdev->resync = resync_lru;
+	mdev->rs_plan_s = new_plan;
 	nbc = NULL;
 	resync_lru = NULL;
+	new_disk_conf = NULL;
+	new_plan = NULL;
 
-	mdev->write_ordering = WO_bdev_flush;
-	drbd_bump_write_ordering(mdev, WO_bdev_flush);
+	drbd_bump_write_ordering(mdev->tconn, WO_bdev_flush);
 
 	if (drbd_md_test_flag(mdev->ldev, MDF_CRASHED_PRIMARY))
 		set_bit(CRASHED_PRIMARY, &mdev->flags);
@@ -1189,10 +1526,8 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 		clear_bit(CRASHED_PRIMARY, &mdev->flags);
 
 	if (drbd_md_test_flag(mdev->ldev, MDF_PRIMARY_IND) &&
-	    !(mdev->state.role == R_PRIMARY && mdev->state.susp_nod)) {
+	    !(mdev->state.role == R_PRIMARY && mdev->tconn->susp_nod))
 		set_bit(CRASHED_PRIMARY, &mdev->flags);
-		cp_discovered = 1;
-	}
 
 	mdev->send_cnt = 0;
 	mdev->recv_cnt = 0;
@@ -1228,7 +1563,9 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 	} else if (dd == grew)
 		set_bit(RESYNC_AFTER_NEG, &mdev->flags);
 
-	if (drbd_md_test_flag(mdev->ldev, MDF_FULL_SYNC)) {
+	if (drbd_md_test_flag(mdev->ldev, MDF_FULL_SYNC) ||
+	    (test_bit(CRASHED_PRIMARY, &mdev->flags) &&
+	     drbd_md_test_flag(mdev->ldev, MDF_AL_DISABLED))) {
 		dev_info(DEV, "Assuming that all blocks are out of sync "
 		     "(aka FullSync)\n");
 		if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write,
@@ -1238,16 +1575,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 		}
 	} else {
 		if (drbd_bitmap_io(mdev, &drbd_bm_read,
-			"read from attaching", BM_LOCKED_MASK) < 0) {
-			retcode = ERR_IO_MD_DISK;
-			goto force_diskless_dec;
-		}
-	}
-
-	if (cp_discovered) {
-		drbd_al_apply_to_bm(mdev);
-		if (drbd_bitmap_io(mdev, &drbd_bm_write,
-			"crashed primary apply AL", BM_LOCKED_MASK)) {
+			"read from attaching", BM_LOCKED_MASK)) {
 			retcode = ERR_IO_MD_DISK;
 			goto force_diskless_dec;
 		}
@@ -1256,9 +1584,9 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 	if (_drbd_bm_total_weight(mdev) == drbd_bm_bits(mdev))
 		drbd_suspend_al(mdev); /* IO is still suspended here... */
 
-	spin_lock_irq(&mdev->req_lock);
-	os = mdev->state;
-	ns.i = os.i;
+	spin_lock_irq(&mdev->tconn->req_lock);
+	os = drbd_read_state(mdev);
+	ns = os;
 	/* If MDF_CONSISTENT is not set go into inconsistent state,
 	   otherwise investigate MDF_WasUpToDate...
 	   If MDF_WAS_UP_TO_DATE is not set go into D_OUTDATED disk state,
@@ -1276,8 +1604,9 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 	if (drbd_md_test_flag(mdev->ldev, MDF_PEER_OUT_DATED))
 		ns.pdsk = D_OUTDATED;
 
-	if ( ns.disk == D_CONSISTENT &&
-	    (ns.pdsk == D_OUTDATED || mdev->ldev->dc.fencing == FP_DONT_CARE))
+	rcu_read_lock();
+	if (ns.disk == D_CONSISTENT &&
+	    (ns.pdsk == D_OUTDATED || rcu_dereference(mdev->ldev->disk_conf)->fencing == FP_DONT_CARE))
 		ns.disk = D_UP_TO_DATE;
 
 	/* All tests on MDF_PRIMARY_IND, MDF_CONNECTED_IND,
@@ -1285,6 +1614,13 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 	   this point, because drbd_request_state() modifies these
 	   flags. */
 
+	if (rcu_dereference(mdev->ldev->disk_conf)->al_updates)
+		mdev->ldev->md.flags &= ~MDF_AL_DISABLED;
+	else
+		mdev->ldev->md.flags |= MDF_AL_DISABLED;
+
+	rcu_read_unlock();
+
 	/* In case we are C_CONNECTED postpone any decision on the new disk
 	   state after the negotiation phase. */
 	if (mdev->state.conn == C_CONNECTED) {
@@ -1300,12 +1636,13 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 	}
 
 	rv = _drbd_set_state(mdev, ns, CS_VERBOSE, NULL);
-	ns = mdev->state;
-	spin_unlock_irq(&mdev->req_lock);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
 	if (rv < SS_SUCCESS)
 		goto force_diskless_dec;
 
+	mod_timer(&mdev->request_timer, jiffies + HZ);
+
 	if (mdev->state.role == R_PRIMARY)
 		mdev->ldev->md.uuid[UI_CURRENT] |=  (u64)1;
 	else
@@ -1316,16 +1653,17 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 
 	kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE);
 	put_ldev(mdev);
-	reply->ret_code = retcode;
-	drbd_reconfig_done(mdev);
+	conn_reconfig_done(mdev->tconn);
+	drbd_adm_finish(info, retcode);
 	return 0;
 
  force_diskless_dec:
 	put_ldev(mdev);
  force_diskless:
-	drbd_force_state(mdev, NS(disk, D_FAILED));
+	drbd_force_state(mdev, NS(disk, D_DISKLESS));
 	drbd_md_sync(mdev);
  fail:
+	conn_reconfig_done(mdev->tconn);
 	if (nbc) {
 		if (nbc->backing_bdev)
 			blkdev_put(nbc->backing_bdev,
@@ -1335,34 +1673,24 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 				   FMODE_READ | FMODE_WRITE | FMODE_EXCL);
 		kfree(nbc);
 	}
+	kfree(new_disk_conf);
 	lc_destroy(resync_lru);
+	kfree(new_plan);
 
-	reply->ret_code = retcode;
-	drbd_reconfig_done(mdev);
+ finish:
+	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
-/* Detaching the disk is a process in multiple stages.  First we need to lock
- * out application IO, in-flight IO, IO stuck in drbd_al_begin_io.
- * Then we transition to D_DISKLESS, and wait for put_ldev() to return all
- * internal references as well.
- * Only then we have finally detached. */
-static int drbd_nl_detach(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			  struct drbd_nl_cfg_reply *reply)
+static int adm_detach(struct drbd_conf *mdev, int force)
 {
-	enum drbd_ret_code retcode;
+	enum drbd_state_rv retcode;
 	int ret;
-	struct detach dt = {};
-
-	if (!detach_from_tags(mdev, nlp->tag_list, &dt)) {
-		reply->ret_code = ERR_MANDATORY_TAG;
-		goto out;
-	}
 
-	if (dt.detach_force) {
+	if (force) {
 		set_bit(FORCE_DETACH, &mdev->flags);
 		drbd_force_state(mdev, NS(disk, D_FAILED));
-		reply->ret_code = SS_SUCCESS;
+		retcode = SS_SUCCESS;
 		goto out;
 	}
 
@@ -1374,608 +1702,697 @@ static int drbd_nl_detach(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
 	ret = wait_event_interruptible(mdev->misc_wait,
 			mdev->state.disk != D_FAILED);
 	drbd_resume_io(mdev);
-
 	if ((int)retcode == (int)SS_IS_DISKLESS)
 		retcode = SS_NOTHING_TO_DO;
 	if (ret)
 		retcode = ERR_INTR;
-	reply->ret_code = retcode;
 out:
-	return 0;
+	return retcode;
 }
 
-static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			    struct drbd_nl_cfg_reply *reply)
+/* Detaching the disk is a process in multiple stages.  First we need to lock
+ * out application IO, in-flight IO, IO stuck in drbd_al_begin_io.
+ * Then we transition to D_DISKLESS, and wait for put_ldev() to return all
+ * internal references as well.
+ * Only then we have finally detached. */
+int drbd_adm_detach(struct sk_buff *skb, struct genl_info *info)
 {
-	int i, ns;
 	enum drbd_ret_code retcode;
-	struct net_conf *new_conf = NULL;
-	struct crypto_hash *tfm = NULL;
-	struct crypto_hash *integrity_w_tfm = NULL;
-	struct crypto_hash *integrity_r_tfm = NULL;
-	struct hlist_head *new_tl_hash = NULL;
-	struct hlist_head *new_ee_hash = NULL;
-	struct drbd_conf *odev;
-	char hmac_name[CRYPTO_MAX_ALG_NAME];
-	void *int_dig_out = NULL;
-	void *int_dig_in = NULL;
-	void *int_dig_vv = NULL;
-	struct sockaddr *new_my_addr, *new_peer_addr, *taken_addr;
+	struct detach_parms parms = { };
+	int err;
 
-	drbd_reconfig_start(mdev);
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
 
-	if (mdev->state.conn > C_STANDALONE) {
-		retcode = ERR_NET_CONFIGURED;
-		goto fail;
+	if (info->attrs[DRBD_NLA_DETACH_PARMS]) {
+		err = detach_parms_from_attrs(&parms, info);
+		if (err) {
+			retcode = ERR_MANDATORY_TAG;
+			drbd_msg_put_info(from_attrs_err_to_txt(err));
+			goto out;
+		}
 	}
 
-	/* allocation not in the IO path, cqueue thread context */
-	new_conf = kzalloc(sizeof(struct net_conf), GFP_KERNEL);
-	if (!new_conf) {
-		retcode = ERR_NOMEM;
-		goto fail;
-	}
+	retcode = adm_detach(adm_ctx.mdev, parms.force_detach);
+out:
+	drbd_adm_finish(info, retcode);
+	return 0;
+}
 
-	new_conf->timeout	   = DRBD_TIMEOUT_DEF;
-	new_conf->try_connect_int  = DRBD_CONNECT_INT_DEF;
-	new_conf->ping_int	   = DRBD_PING_INT_DEF;
-	new_conf->max_epoch_size   = DRBD_MAX_EPOCH_SIZE_DEF;
-	new_conf->max_buffers	   = DRBD_MAX_BUFFERS_DEF;
-	new_conf->unplug_watermark = DRBD_UNPLUG_WATERMARK_DEF;
-	new_conf->sndbuf_size	   = DRBD_SNDBUF_SIZE_DEF;
-	new_conf->rcvbuf_size	   = DRBD_RCVBUF_SIZE_DEF;
-	new_conf->ko_count	   = DRBD_KO_COUNT_DEF;
-	new_conf->after_sb_0p	   = DRBD_AFTER_SB_0P_DEF;
-	new_conf->after_sb_1p	   = DRBD_AFTER_SB_1P_DEF;
-	new_conf->after_sb_2p	   = DRBD_AFTER_SB_2P_DEF;
-	new_conf->want_lose	   = 0;
-	new_conf->two_primaries    = 0;
-	new_conf->wire_protocol    = DRBD_PROT_C;
-	new_conf->ping_timeo	   = DRBD_PING_TIMEO_DEF;
-	new_conf->rr_conflict	   = DRBD_RR_CONFLICT_DEF;
-	new_conf->on_congestion    = DRBD_ON_CONGESTION_DEF;
-	new_conf->cong_extents     = DRBD_CONG_EXTENTS_DEF;
-
-	if (!net_conf_from_tags(mdev, nlp->tag_list, new_conf)) {
-		retcode = ERR_MANDATORY_TAG;
-		goto fail;
+static bool conn_resync_running(struct drbd_tconn *tconn)
+{
+	struct drbd_conf *mdev;
+	bool rv = false;
+	int vnr;
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+		if (mdev->state.conn == C_SYNC_SOURCE ||
+		    mdev->state.conn == C_SYNC_TARGET ||
+		    mdev->state.conn == C_PAUSED_SYNC_S ||
+		    mdev->state.conn == C_PAUSED_SYNC_T) {
+			rv = true;
+			break;
+		}
 	}
+	rcu_read_unlock();
 
-	if (new_conf->two_primaries
-	    && (new_conf->wire_protocol != DRBD_PROT_C)) {
-		retcode = ERR_NOT_PROTO_C;
-		goto fail;
-	}
+	return rv;
+}
 
-	if (get_ldev(mdev)) {
-		enum drbd_fencing_p fp = mdev->ldev->dc.fencing;
-		put_ldev(mdev);
-		if (new_conf->wire_protocol == DRBD_PROT_A && fp == FP_STONITH) {
-			retcode = ERR_STONITH_AND_PROT_A;
-			goto fail;
+static bool conn_ov_running(struct drbd_tconn *tconn)
+{
+	struct drbd_conf *mdev;
+	bool rv = false;
+	int vnr;
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+		if (mdev->state.conn == C_VERIFY_S ||
+		    mdev->state.conn == C_VERIFY_T) {
+			rv = true;
+			break;
 		}
 	}
+	rcu_read_unlock();
 
-	if (new_conf->on_congestion != OC_BLOCK && new_conf->wire_protocol != DRBD_PROT_A) {
-		retcode = ERR_CONG_NOT_PROTO_A;
-		goto fail;
-	}
+	return rv;
+}
 
-	if (mdev->state.role == R_PRIMARY && new_conf->want_lose) {
-		retcode = ERR_DISCARD;
-		goto fail;
-	}
+static enum drbd_ret_code
+_check_net_options(struct drbd_tconn *tconn, struct net_conf *old_conf, struct net_conf *new_conf)
+{
+	struct drbd_conf *mdev;
+	int i;
 
-	retcode = NO_ERROR;
+	if (old_conf && tconn->cstate == C_WF_REPORT_PARAMS && tconn->agreed_pro_version < 100) {
+		if (new_conf->wire_protocol != old_conf->wire_protocol)
+			return ERR_NEED_APV_100;
 
-	new_my_addr = (struct sockaddr *)&new_conf->my_addr;
-	new_peer_addr = (struct sockaddr *)&new_conf->peer_addr;
-	for (i = 0; i < minor_count; i++) {
-		odev = minor_to_mdev(i);
-		if (!odev || odev == mdev)
-			continue;
-		if (get_net_conf(odev)) {
-			taken_addr = (struct sockaddr *)&odev->net_conf->my_addr;
-			if (new_conf->my_addr_len == odev->net_conf->my_addr_len &&
-			    !memcmp(new_my_addr, taken_addr, new_conf->my_addr_len))
-				retcode = ERR_LOCAL_ADDR;
-
-			taken_addr = (struct sockaddr *)&odev->net_conf->peer_addr;
-			if (new_conf->peer_addr_len == odev->net_conf->peer_addr_len &&
-			    !memcmp(new_peer_addr, taken_addr, new_conf->peer_addr_len))
-				retcode = ERR_PEER_ADDR;
-
-			put_net_conf(odev);
-			if (retcode != NO_ERROR)
-				goto fail;
-		}
+		if (new_conf->two_primaries != old_conf->two_primaries)
+			return ERR_NEED_APV_100;
+
+		if (strcmp(new_conf->integrity_alg, old_conf->integrity_alg))
+			return ERR_NEED_APV_100;
 	}
 
-	if (new_conf->cram_hmac_alg[0] != 0) {
-		snprintf(hmac_name, CRYPTO_MAX_ALG_NAME, "hmac(%s)",
-			new_conf->cram_hmac_alg);
-		tfm = crypto_alloc_hash(hmac_name, 0, CRYPTO_ALG_ASYNC);
-		if (IS_ERR(tfm)) {
-			tfm = NULL;
-			retcode = ERR_AUTH_ALG;
-			goto fail;
-		}
+	if (!new_conf->two_primaries &&
+	    conn_highest_role(tconn) == R_PRIMARY &&
+	    conn_highest_peer(tconn) == R_PRIMARY)
+		return ERR_NEED_ALLOW_TWO_PRI;
 
-		if (!drbd_crypto_is_hash(crypto_hash_tfm(tfm))) {
-			retcode = ERR_AUTH_ALG_ND;
-			goto fail;
+	if (new_conf->two_primaries &&
+	    (new_conf->wire_protocol != DRBD_PROT_C))
+		return ERR_NOT_PROTO_C;
+
+	idr_for_each_entry(&tconn->volumes, mdev, i) {
+		if (get_ldev(mdev)) {
+			enum drbd_fencing_p fp = rcu_dereference(mdev->ldev->disk_conf)->fencing;
+			put_ldev(mdev);
+			if (new_conf->wire_protocol == DRBD_PROT_A && fp == FP_STONITH)
+				return ERR_STONITH_AND_PROT_A;
 		}
+		if (mdev->state.role == R_PRIMARY && new_conf->discard_my_data)
+			return ERR_DISCARD_IMPOSSIBLE;
 	}
 
-	if (new_conf->integrity_alg[0]) {
-		integrity_w_tfm = crypto_alloc_hash(new_conf->integrity_alg, 0, CRYPTO_ALG_ASYNC);
-		if (IS_ERR(integrity_w_tfm)) {
-			integrity_w_tfm = NULL;
-			retcode=ERR_INTEGRITY_ALG;
-			goto fail;
-		}
+	if (new_conf->on_congestion != OC_BLOCK && new_conf->wire_protocol != DRBD_PROT_A)
+		return ERR_CONG_NOT_PROTO_A;
 
-		if (!drbd_crypto_is_hash(crypto_hash_tfm(integrity_w_tfm))) {
-			retcode=ERR_INTEGRITY_ALG_ND;
-			goto fail;
-		}
+	return NO_ERROR;
+}
 
-		integrity_r_tfm = crypto_alloc_hash(new_conf->integrity_alg, 0, CRYPTO_ALG_ASYNC);
-		if (IS_ERR(integrity_r_tfm)) {
-			integrity_r_tfm = NULL;
-			retcode=ERR_INTEGRITY_ALG;
-			goto fail;
-		}
-	}
+static enum drbd_ret_code
+check_net_options(struct drbd_tconn *tconn, struct net_conf *new_conf)
+{
+	static enum drbd_ret_code rv;
+	struct drbd_conf *mdev;
+	int i;
 
-	ns = new_conf->max_epoch_size/8;
-	if (mdev->tl_hash_s != ns) {
-		new_tl_hash = kzalloc(ns*sizeof(void *), GFP_KERNEL);
-		if (!new_tl_hash) {
-			retcode = ERR_NOMEM;
-			goto fail;
-		}
-	}
+	rcu_read_lock();
+	rv = _check_net_options(tconn, rcu_dereference(tconn->net_conf), new_conf);
+	rcu_read_unlock();
 
-	ns = new_conf->max_buffers/8;
-	if (new_conf->two_primaries && (mdev->ee_hash_s != ns)) {
-		new_ee_hash = kzalloc(ns*sizeof(void *), GFP_KERNEL);
-		if (!new_ee_hash) {
-			retcode = ERR_NOMEM;
-			goto fail;
+	/* tconn->volumes protected by genl_lock() here */
+	idr_for_each_entry(&tconn->volumes, mdev, i) {
+		if (!mdev->bitmap) {
+			if(drbd_bm_init(mdev))
+				return ERR_NOMEM;
 		}
 	}
 
-	((char *)new_conf->shared_secret)[SHARED_SECRET_MAX-1] = 0;
+	return rv;
+}
 
-	if (integrity_w_tfm) {
-		i = crypto_hash_digestsize(integrity_w_tfm);
-		int_dig_out = kmalloc(i, GFP_KERNEL);
-		if (!int_dig_out) {
-			retcode = ERR_NOMEM;
-			goto fail;
-		}
-		int_dig_in = kmalloc(i, GFP_KERNEL);
-		if (!int_dig_in) {
-			retcode = ERR_NOMEM;
-			goto fail;
-		}
-		int_dig_vv = kmalloc(i, GFP_KERNEL);
-		if (!int_dig_vv) {
-			retcode = ERR_NOMEM;
-			goto fail;
-		}
-	}
+struct crypto {
+	struct crypto_hash *verify_tfm;
+	struct crypto_hash *csums_tfm;
+	struct crypto_hash *cram_hmac_tfm;
+	struct crypto_hash *integrity_tfm;
+};
 
-	if (!mdev->bitmap) {
-		if(drbd_bm_init(mdev)) {
-			retcode = ERR_NOMEM;
-			goto fail;
-		}
-	}
+static int
+alloc_hash(struct crypto_hash **tfm, char *tfm_name, int err_alg)
+{
+	if (!tfm_name[0])
+		return NO_ERROR;
 
-	drbd_flush_workqueue(mdev);
-	spin_lock_irq(&mdev->req_lock);
-	if (mdev->net_conf != NULL) {
-		retcode = ERR_NET_CONFIGURED;
-		spin_unlock_irq(&mdev->req_lock);
-		goto fail;
+	*tfm = crypto_alloc_hash(tfm_name, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(*tfm)) {
+		*tfm = NULL;
+		return err_alg;
 	}
-	mdev->net_conf = new_conf;
 
-	mdev->send_cnt = 0;
-	mdev->recv_cnt = 0;
+	return NO_ERROR;
+}
 
-	if (new_tl_hash) {
-		kfree(mdev->tl_hash);
-		mdev->tl_hash_s = mdev->net_conf->max_epoch_size/8;
-		mdev->tl_hash = new_tl_hash;
-	}
+static enum drbd_ret_code
+alloc_crypto(struct crypto *crypto, struct net_conf *new_conf)
+{
+	char hmac_name[CRYPTO_MAX_ALG_NAME];
+	enum drbd_ret_code rv;
+
+	rv = alloc_hash(&crypto->csums_tfm, new_conf->csums_alg,
+		       ERR_CSUMS_ALG);
+	if (rv != NO_ERROR)
+		return rv;
+	rv = alloc_hash(&crypto->verify_tfm, new_conf->verify_alg,
+		       ERR_VERIFY_ALG);
+	if (rv != NO_ERROR)
+		return rv;
+	rv = alloc_hash(&crypto->integrity_tfm, new_conf->integrity_alg,
+		       ERR_INTEGRITY_ALG);
+	if (rv != NO_ERROR)
+		return rv;
+	if (new_conf->cram_hmac_alg[0] != 0) {
+		snprintf(hmac_name, CRYPTO_MAX_ALG_NAME, "hmac(%s)",
+			 new_conf->cram_hmac_alg);
 
-	if (new_ee_hash) {
-		kfree(mdev->ee_hash);
-		mdev->ee_hash_s = mdev->net_conf->max_buffers/8;
-		mdev->ee_hash = new_ee_hash;
+		rv = alloc_hash(&crypto->cram_hmac_tfm, hmac_name,
+			       ERR_AUTH_ALG);
 	}
 
-	crypto_free_hash(mdev->cram_hmac_tfm);
-	mdev->cram_hmac_tfm = tfm;
+	return rv;
+}
 
-	crypto_free_hash(mdev->integrity_w_tfm);
-	mdev->integrity_w_tfm = integrity_w_tfm;
+static void free_crypto(struct crypto *crypto)
+{
+	crypto_free_hash(crypto->cram_hmac_tfm);
+	crypto_free_hash(crypto->integrity_tfm);
+	crypto_free_hash(crypto->csums_tfm);
+	crypto_free_hash(crypto->verify_tfm);
+}
 
-	crypto_free_hash(mdev->integrity_r_tfm);
-	mdev->integrity_r_tfm = integrity_r_tfm;
+int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info)
+{
+	enum drbd_ret_code retcode;
+	struct drbd_tconn *tconn;
+	struct net_conf *old_conf, *new_conf = NULL;
+	int err;
+	int ovr; /* online verify running */
+	int rsr; /* re-sync running */
+	struct crypto crypto = { };
 
-	kfree(mdev->int_dig_out);
-	kfree(mdev->int_dig_in);
-	kfree(mdev->int_dig_vv);
-	mdev->int_dig_out=int_dig_out;
-	mdev->int_dig_in=int_dig_in;
-	mdev->int_dig_vv=int_dig_vv;
-	retcode = _drbd_set_state(_NS(mdev, conn, C_UNCONNECTED), CS_VERBOSE, NULL);
-	spin_unlock_irq(&mdev->req_lock);
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_CONNECTION);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
 
-	kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE);
-	reply->ret_code = retcode;
-	drbd_reconfig_done(mdev);
-	return 0;
+	tconn = adm_ctx.tconn;
 
-fail:
-	kfree(int_dig_out);
-	kfree(int_dig_in);
-	kfree(int_dig_vv);
-	crypto_free_hash(tfm);
-	crypto_free_hash(integrity_w_tfm);
-	crypto_free_hash(integrity_r_tfm);
-	kfree(new_tl_hash);
-	kfree(new_ee_hash);
-	kfree(new_conf);
+	new_conf = kzalloc(sizeof(struct net_conf), GFP_KERNEL);
+	if (!new_conf) {
+		retcode = ERR_NOMEM;
+		goto out;
+	}
 
-	reply->ret_code = retcode;
-	drbd_reconfig_done(mdev);
-	return 0;
-}
+	conn_reconfig_start(tconn);
 
-static int drbd_nl_disconnect(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			      struct drbd_nl_cfg_reply *reply)
-{
-	int retcode;
-	struct disconnect dc;
+	mutex_lock(&tconn->data.mutex);
+	mutex_lock(&tconn->conf_update);
+	old_conf = tconn->net_conf;
 
-	memset(&dc, 0, sizeof(struct disconnect));
-	if (!disconnect_from_tags(mdev, nlp->tag_list, &dc)) {
-		retcode = ERR_MANDATORY_TAG;
+	if (!old_conf) {
+		drbd_msg_put_info("net conf missing, try connect");
+		retcode = ERR_INVALID_REQUEST;
 		goto fail;
 	}
 
-	if (dc.force) {
-		spin_lock_irq(&mdev->req_lock);
-		if (mdev->state.conn >= C_WF_CONNECTION)
-			_drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), CS_HARD, NULL);
-		spin_unlock_irq(&mdev->req_lock);
-		goto done;
+	*new_conf = *old_conf;
+	if (should_set_defaults(info))
+		set_net_conf_defaults(new_conf);
+
+	err = net_conf_from_attrs_for_change(new_conf, info);
+	if (err && err != -ENOMSG) {
+		retcode = ERR_MANDATORY_TAG;
+		drbd_msg_put_info(from_attrs_err_to_txt(err));
+		goto fail;
 	}
 
-	retcode = _drbd_request_state(mdev, NS(conn, C_DISCONNECTING), CS_ORDERED);
+	retcode = check_net_options(tconn, new_conf);
+	if (retcode != NO_ERROR)
+		goto fail;
 
-	if (retcode == SS_NOTHING_TO_DO)
-		goto done;
-	else if (retcode == SS_ALREADY_STANDALONE)
-		goto done;
-	else if (retcode == SS_PRIMARY_NOP) {
-		/* Our statche checking code wants to see the peer outdated. */
-		retcode = drbd_request_state(mdev, NS2(conn, C_DISCONNECTING,
-						      pdsk, D_OUTDATED));
-	} else if (retcode == SS_CW_FAILED_BY_PEER) {
-		/* The peer probably wants to see us outdated. */
-		retcode = _drbd_request_state(mdev, NS2(conn, C_DISCONNECTING,
-							disk, D_OUTDATED),
-					      CS_ORDERED);
-		if (retcode == SS_IS_DISKLESS || retcode == SS_LOWER_THAN_OUTDATED) {
-			drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-			retcode = SS_SUCCESS;
-		}
+	/* re-sync running */
+	rsr = conn_resync_running(tconn);
+	if (rsr && strcmp(new_conf->csums_alg, old_conf->csums_alg)) {
+		retcode = ERR_CSUMS_RESYNC_RUNNING;
+		goto fail;
 	}
 
-	if (retcode < SS_SUCCESS)
+	/* online verify running */
+	ovr = conn_ov_running(tconn);
+	if (ovr && strcmp(new_conf->verify_alg, old_conf->verify_alg)) {
+		retcode = ERR_VERIFY_RUNNING;
 		goto fail;
+	}
 
-	if (wait_event_interruptible(mdev->state_wait,
-				     mdev->state.conn != C_DISCONNECTING)) {
-		/* Do not test for mdev->state.conn == C_STANDALONE, since
-		   someone else might connect us in the mean time! */
-		retcode = ERR_INTR;
+	retcode = alloc_crypto(&crypto, new_conf);
+	if (retcode != NO_ERROR)
 		goto fail;
+
+	rcu_assign_pointer(tconn->net_conf, new_conf);
+
+	if (!rsr) {
+		crypto_free_hash(tconn->csums_tfm);
+		tconn->csums_tfm = crypto.csums_tfm;
+		crypto.csums_tfm = NULL;
+	}
+	if (!ovr) {
+		crypto_free_hash(tconn->verify_tfm);
+		tconn->verify_tfm = crypto.verify_tfm;
+		crypto.verify_tfm = NULL;
 	}
 
- done:
-	retcode = NO_ERROR;
+	crypto_free_hash(tconn->integrity_tfm);
+	tconn->integrity_tfm = crypto.integrity_tfm;
+	if (tconn->cstate >= C_WF_REPORT_PARAMS && tconn->agreed_pro_version >= 100)
+		/* Do this without trying to take tconn->data.mutex again.  */
+		__drbd_send_protocol(tconn, P_PROTOCOL_UPDATE);
+
+	crypto_free_hash(tconn->cram_hmac_tfm);
+	tconn->cram_hmac_tfm = crypto.cram_hmac_tfm;
+
+	mutex_unlock(&tconn->conf_update);
+	mutex_unlock(&tconn->data.mutex);
+	synchronize_rcu();
+	kfree(old_conf);
+
+	if (tconn->cstate >= C_WF_REPORT_PARAMS)
+		drbd_send_sync_param(minor_to_mdev(conn_lowest_minor(tconn)));
+
+	goto done;
+
  fail:
-	drbd_md_sync(mdev);
-	reply->ret_code = retcode;
+	mutex_unlock(&tconn->conf_update);
+	mutex_unlock(&tconn->data.mutex);
+	free_crypto(&crypto);
+	kfree(new_conf);
+ done:
+	conn_reconfig_done(tconn);
+ out:
+	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
-void resync_after_online_grow(struct drbd_conf *mdev)
+int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info)
 {
-	int iass; /* I am sync source */
+	struct drbd_conf *mdev;
+	struct net_conf *old_conf, *new_conf = NULL;
+	struct crypto crypto = { };
+	struct drbd_tconn *tconn;
+	enum drbd_ret_code retcode;
+	int i;
+	int err;
 
-	dev_info(DEV, "Resync of new storage after online grow\n");
-	if (mdev->state.role != mdev->state.peer)
-		iass = (mdev->state.role == R_PRIMARY);
-	else
-		iass = test_bit(DISCARD_CONCURRENT, &mdev->flags);
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_RESOURCE);
 
-	if (iass)
-		drbd_start_resync(mdev, C_SYNC_SOURCE);
-	else
-		_drbd_request_state(mdev, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE + CS_SERIALIZE);
-}
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
+	if (!(adm_ctx.my_addr && adm_ctx.peer_addr)) {
+		drbd_msg_put_info("connection endpoint(s) missing");
+		retcode = ERR_INVALID_REQUEST;
+		goto out;
+	}
 
-static int drbd_nl_resize(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			  struct drbd_nl_cfg_reply *reply)
-{
-	struct resize rs;
-	int retcode = NO_ERROR;
-	enum determine_dev_size dd;
-	enum dds_flags ddsf;
+	/* No need for _rcu here. All reconfiguration is
+	 * strictly serialized on genl_lock(). We are protected against
+	 * concurrent reconfiguration/addition/deletion */
+	list_for_each_entry(tconn, &drbd_tconns, all_tconn) {
+		if (nla_len(adm_ctx.my_addr) == tconn->my_addr_len &&
+		    !memcmp(nla_data(adm_ctx.my_addr), &tconn->my_addr, tconn->my_addr_len)) {
+			retcode = ERR_LOCAL_ADDR;
+			goto out;
+		}
 
-	memset(&rs, 0, sizeof(struct resize));
-	if (!resize_from_tags(mdev, nlp->tag_list, &rs)) {
-		retcode = ERR_MANDATORY_TAG;
-		goto fail;
+		if (nla_len(adm_ctx.peer_addr) == tconn->peer_addr_len &&
+		    !memcmp(nla_data(adm_ctx.peer_addr), &tconn->peer_addr, tconn->peer_addr_len)) {
+			retcode = ERR_PEER_ADDR;
+			goto out;
+		}
 	}
 
-	if (mdev->state.conn > C_CONNECTED) {
-		retcode = ERR_RESIZE_RESYNC;
-		goto fail;
-	}
+	tconn = adm_ctx.tconn;
+	conn_reconfig_start(tconn);
 
-	if (mdev->state.role == R_SECONDARY &&
-	    mdev->state.peer == R_SECONDARY) {
-		retcode = ERR_NO_PRIMARY;
+	if (tconn->cstate > C_STANDALONE) {
+		retcode = ERR_NET_CONFIGURED;
 		goto fail;
 	}
 
-	if (!get_ldev(mdev)) {
-		retcode = ERR_NO_DISK;
+	/* allocation not in the IO path, drbdsetup / netlink process context */
+	new_conf = kzalloc(sizeof(*new_conf), GFP_KERNEL);
+	if (!new_conf) {
+		retcode = ERR_NOMEM;
 		goto fail;
 	}
 
-	if (rs.no_resync && mdev->agreed_pro_version < 93) {
-		retcode = ERR_NEED_APV_93;
-		goto fail_ldev;
-	}
-
-	if (mdev->ldev->known_size != drbd_get_capacity(mdev->ldev->backing_bdev))
-		mdev->ldev->known_size = drbd_get_capacity(mdev->ldev->backing_bdev);
+	set_net_conf_defaults(new_conf);
 
-	mdev->ldev->dc.disk_size = (sector_t)rs.resize_size;
-	ddsf = (rs.resize_force ? DDSF_FORCED : 0) | (rs.no_resync ? DDSF_NO_RESYNC : 0);
-	dd = drbd_determine_dev_size(mdev, ddsf);
-	drbd_md_sync(mdev);
-	put_ldev(mdev);
-	if (dd == dev_size_error) {
-		retcode = ERR_NOMEM_BITMAP;
+	err = net_conf_from_attrs(new_conf, info);
+	if (err && err != -ENOMSG) {
+		retcode = ERR_MANDATORY_TAG;
+		drbd_msg_put_info(from_attrs_err_to_txt(err));
 		goto fail;
 	}
 
-	if (mdev->state.conn == C_CONNECTED) {
-		if (dd == grew)
-			set_bit(RESIZE_PENDING, &mdev->flags);
+	retcode = check_net_options(tconn, new_conf);
+	if (retcode != NO_ERROR)
+		goto fail;
 
-		drbd_send_uuids(mdev);
-		drbd_send_sizes(mdev, 1, ddsf);
-	}
+	retcode = alloc_crypto(&crypto, new_conf);
+	if (retcode != NO_ERROR)
+		goto fail;
 
- fail:
-	reply->ret_code = retcode;
-	return 0;
+	((char *)new_conf->shared_secret)[SHARED_SECRET_MAX-1] = 0;
 
- fail_ldev:
-	put_ldev(mdev);
-	goto fail;
-}
+	conn_flush_workqueue(tconn);
 
-static int drbd_nl_syncer_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			       struct drbd_nl_cfg_reply *reply)
-{
-	int retcode = NO_ERROR;
-	int err;
-	int ovr; /* online verify running */
-	int rsr; /* re-sync running */
-	struct crypto_hash *verify_tfm = NULL;
-	struct crypto_hash *csums_tfm = NULL;
-	struct syncer_conf sc;
-	cpumask_var_t new_cpu_mask;
-	int *rs_plan_s = NULL;
-	int fifo_size;
-
-	if (!zalloc_cpumask_var(&new_cpu_mask, GFP_KERNEL)) {
-		retcode = ERR_NOMEM;
+	mutex_lock(&tconn->conf_update);
+	old_conf = tconn->net_conf;
+	if (old_conf) {
+		retcode = ERR_NET_CONFIGURED;
+		mutex_unlock(&tconn->conf_update);
 		goto fail;
 	}
+	rcu_assign_pointer(tconn->net_conf, new_conf);
 
-	if (nlp->flags & DRBD_NL_SET_DEFAULTS) {
-		memset(&sc, 0, sizeof(struct syncer_conf));
-		sc.rate       = DRBD_RATE_DEF;
-		sc.after      = DRBD_AFTER_DEF;
-		sc.al_extents = DRBD_AL_EXTENTS_DEF;
-		sc.on_no_data  = DRBD_ON_NO_DATA_DEF;
-		sc.c_plan_ahead = DRBD_C_PLAN_AHEAD_DEF;
-		sc.c_delay_target = DRBD_C_DELAY_TARGET_DEF;
-		sc.c_fill_target = DRBD_C_FILL_TARGET_DEF;
-		sc.c_max_rate = DRBD_C_MAX_RATE_DEF;
-		sc.c_min_rate = DRBD_C_MIN_RATE_DEF;
-	} else
-		memcpy(&sc, &mdev->sync_conf, sizeof(struct syncer_conf));
+	conn_free_crypto(tconn);
+	tconn->cram_hmac_tfm = crypto.cram_hmac_tfm;
+	tconn->integrity_tfm = crypto.integrity_tfm;
+	tconn->csums_tfm = crypto.csums_tfm;
+	tconn->verify_tfm = crypto.verify_tfm;
 
-	if (!syncer_conf_from_tags(mdev, nlp->tag_list, &sc)) {
-		retcode = ERR_MANDATORY_TAG;
-		goto fail;
-	}
+	tconn->my_addr_len = nla_len(adm_ctx.my_addr);
+	memcpy(&tconn->my_addr, nla_data(adm_ctx.my_addr), tconn->my_addr_len);
+	tconn->peer_addr_len = nla_len(adm_ctx.peer_addr);
+	memcpy(&tconn->peer_addr, nla_data(adm_ctx.peer_addr), tconn->peer_addr_len);
 
-	/* re-sync running */
-	rsr = (	mdev->state.conn == C_SYNC_SOURCE ||
-		mdev->state.conn == C_SYNC_TARGET ||
-		mdev->state.conn == C_PAUSED_SYNC_S ||
-		mdev->state.conn == C_PAUSED_SYNC_T );
+	mutex_unlock(&tconn->conf_update);
 
-	if (rsr && strcmp(sc.csums_alg, mdev->sync_conf.csums_alg)) {
-		retcode = ERR_CSUMS_RESYNC_RUNNING;
-		goto fail;
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, i) {
+		mdev->send_cnt = 0;
+		mdev->recv_cnt = 0;
 	}
+	rcu_read_unlock();
 
-	if (!rsr && sc.csums_alg[0]) {
-		csums_tfm = crypto_alloc_hash(sc.csums_alg, 0, CRYPTO_ALG_ASYNC);
-		if (IS_ERR(csums_tfm)) {
-			csums_tfm = NULL;
-			retcode = ERR_CSUMS_ALG;
-			goto fail;
-		}
+	retcode = conn_request_state(tconn, NS(conn, C_UNCONNECTED), CS_VERBOSE);
 
-		if (!drbd_crypto_is_hash(crypto_hash_tfm(csums_tfm))) {
-			retcode = ERR_CSUMS_ALG_ND;
-			goto fail;
-		}
-	}
+	conn_reconfig_done(tconn);
+	drbd_adm_finish(info, retcode);
+	return 0;
 
-	/* online verify running */
-	ovr = (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T);
+fail:
+	free_crypto(&crypto);
+	kfree(new_conf);
 
-	if (ovr) {
-		if (strcmp(sc.verify_alg, mdev->sync_conf.verify_alg)) {
-			retcode = ERR_VERIFY_RUNNING;
-			goto fail;
+	conn_reconfig_done(tconn);
+out:
+	drbd_adm_finish(info, retcode);
+	return 0;
+}
+
+static enum drbd_state_rv conn_try_disconnect(struct drbd_tconn *tconn, bool force)
+{
+	enum drbd_state_rv rv;
+
+	rv = conn_request_state(tconn, NS(conn, C_DISCONNECTING),
+			force ? CS_HARD : 0);
+
+	switch (rv) {
+	case SS_NOTHING_TO_DO:
+		break;
+	case SS_ALREADY_STANDALONE:
+		return SS_SUCCESS;
+	case SS_PRIMARY_NOP:
+		/* Our state checking code wants to see the peer outdated. */
+		rv = conn_request_state(tconn, NS2(conn, C_DISCONNECTING,
+						pdsk, D_OUTDATED), CS_VERBOSE);
+		break;
+	case SS_CW_FAILED_BY_PEER:
+		/* The peer probably wants to see us outdated. */
+		rv = conn_request_state(tconn, NS2(conn, C_DISCONNECTING,
+							disk, D_OUTDATED), 0);
+		if (rv == SS_IS_DISKLESS || rv == SS_LOWER_THAN_OUTDATED) {
+			rv = conn_request_state(tconn, NS(conn, C_DISCONNECTING),
+					CS_HARD);
 		}
+		break;
+	default:;
+		/* no special handling necessary */
+	}
+
+	if (rv >= SS_SUCCESS) {
+		enum drbd_state_rv rv2;
+		/* No one else can reconfigure the network while I am here.
+		 * The state handling only uses drbd_thread_stop_nowait(),
+		 * we want to really wait here until the receiver is no more.
+		 */
+		drbd_thread_stop(&adm_ctx.tconn->receiver);
+
+		/* Race breaker.  This additional state change request may be
+		 * necessary, if this was a forced disconnect during a receiver
+		 * restart.  We may have "killed" the receiver thread just
+		 * after drbdd_init() returned.  Typically, we should be
+		 * C_STANDALONE already, now, and this becomes a no-op.
+		 */
+		rv2 = conn_request_state(tconn, NS(conn, C_STANDALONE),
+				CS_VERBOSE | CS_HARD);
+		if (rv2 < SS_SUCCESS)
+			conn_err(tconn,
+				"unexpected rv2=%d in conn_try_disconnect()\n",
+				rv2);
 	}
+	return rv;
+}
 
-	if (!ovr && sc.verify_alg[0]) {
-		verify_tfm = crypto_alloc_hash(sc.verify_alg, 0, CRYPTO_ALG_ASYNC);
-		if (IS_ERR(verify_tfm)) {
-			verify_tfm = NULL;
-			retcode = ERR_VERIFY_ALG;
-			goto fail;
-		}
+int drbd_adm_disconnect(struct sk_buff *skb, struct genl_info *info)
+{
+	struct disconnect_parms parms;
+	struct drbd_tconn *tconn;
+	enum drbd_state_rv rv;
+	enum drbd_ret_code retcode;
+	int err;
+
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_CONNECTION);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto fail;
 
-		if (!drbd_crypto_is_hash(crypto_hash_tfm(verify_tfm))) {
-			retcode = ERR_VERIFY_ALG_ND;
+	tconn = adm_ctx.tconn;
+	memset(&parms, 0, sizeof(parms));
+	if (info->attrs[DRBD_NLA_DISCONNECT_PARMS]) {
+		err = disconnect_parms_from_attrs(&parms, info);
+		if (err) {
+			retcode = ERR_MANDATORY_TAG;
+			drbd_msg_put_info(from_attrs_err_to_txt(err));
 			goto fail;
 		}
 	}
 
-	/* silently ignore cpu mask on UP kernel */
-	if (nr_cpu_ids > 1 && sc.cpu_mask[0] != 0) {
-		err = bitmap_parse(sc.cpu_mask, 32,
-				cpumask_bits(new_cpu_mask), nr_cpu_ids);
+	rv = conn_try_disconnect(tconn, parms.force_disconnect);
+	if (rv < SS_SUCCESS)
+		retcode = rv;  /* FIXME: Type mismatch. */
+	else
+		retcode = NO_ERROR;
+ fail:
+	drbd_adm_finish(info, retcode);
+	return 0;
+}
+
+void resync_after_online_grow(struct drbd_conf *mdev)
+{
+	int iass; /* I am sync source */
+
+	dev_info(DEV, "Resync of new storage after online grow\n");
+	if (mdev->state.role != mdev->state.peer)
+		iass = (mdev->state.role == R_PRIMARY);
+	else
+		iass = test_bit(RESOLVE_CONFLICTS, &mdev->tconn->flags);
+
+	if (iass)
+		drbd_start_resync(mdev, C_SYNC_SOURCE);
+	else
+		_drbd_request_state(mdev, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE + CS_SERIALIZE);
+}
+
+int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info)
+{
+	struct disk_conf *old_disk_conf, *new_disk_conf = NULL;
+	struct resize_parms rs;
+	struct drbd_conf *mdev;
+	enum drbd_ret_code retcode;
+	enum determine_dev_size dd;
+	enum dds_flags ddsf;
+	sector_t u_size;
+	int err;
+
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto fail;
+
+	memset(&rs, 0, sizeof(struct resize_parms));
+	if (info->attrs[DRBD_NLA_RESIZE_PARMS]) {
+		err = resize_parms_from_attrs(&rs, info);
 		if (err) {
-			dev_warn(DEV, "bitmap_parse() failed with %d\n", err);
-			retcode = ERR_CPU_MASK_PARSE;
+			retcode = ERR_MANDATORY_TAG;
+			drbd_msg_put_info(from_attrs_err_to_txt(err));
 			goto fail;
 		}
 	}
 
-	ERR_IF (sc.rate < 1) sc.rate = 1;
-	ERR_IF (sc.al_extents < 7) sc.al_extents = 127; /* arbitrary minimum */
-#define AL_MAX ((MD_AL_MAX_SIZE-1) * AL_EXTENTS_PT)
-	if (sc.al_extents > AL_MAX) {
-		dev_err(DEV, "sc.al_extents > %d\n", AL_MAX);
-		sc.al_extents = AL_MAX;
+	mdev = adm_ctx.mdev;
+	if (mdev->state.conn > C_CONNECTED) {
+		retcode = ERR_RESIZE_RESYNC;
+		goto fail;
 	}
-#undef AL_MAX
 
-	/* to avoid spurious errors when configuring minors before configuring
-	 * the minors they depend on: if necessary, first create the minor we
-	 * depend on */
-	if (sc.after >= 0)
-		ensure_mdev(sc.after, 1);
+	if (mdev->state.role == R_SECONDARY &&
+	    mdev->state.peer == R_SECONDARY) {
+		retcode = ERR_NO_PRIMARY;
+		goto fail;
+	}
 
-	/* most sanity checks done, try to assign the new sync-after
-	 * dependency.  need to hold the global lock in there,
-	 * to avoid a race in the dependency loop check. */
-	retcode = drbd_alter_sa(mdev, sc.after);
-	if (retcode != NO_ERROR)
+	if (!get_ldev(mdev)) {
+		retcode = ERR_NO_DISK;
 		goto fail;
+	}
 
-	fifo_size = (sc.c_plan_ahead * 10 * SLEEP_TIME) / HZ;
-	if (fifo_size != mdev->rs_plan_s.size && fifo_size > 0) {
-		rs_plan_s   = kzalloc(sizeof(int) * fifo_size, GFP_KERNEL);
-		if (!rs_plan_s) {
-			dev_err(DEV, "kmalloc of fifo_buffer failed");
+	if (rs.no_resync && mdev->tconn->agreed_pro_version < 93) {
+		retcode = ERR_NEED_APV_93;
+		goto fail_ldev;
+	}
+
+	rcu_read_lock();
+	u_size = rcu_dereference(mdev->ldev->disk_conf)->disk_size;
+	rcu_read_unlock();
+	if (u_size != (sector_t)rs.resize_size) {
+		new_disk_conf = kmalloc(sizeof(struct disk_conf), GFP_KERNEL);
+		if (!new_disk_conf) {
 			retcode = ERR_NOMEM;
-			goto fail;
+			goto fail_ldev;
 		}
 	}
 
-	/* ok, assign the rest of it as well.
-	 * lock against receive_SyncParam() */
-	spin_lock(&mdev->peer_seq_lock);
-	mdev->sync_conf = sc;
+	if (mdev->ldev->known_size != drbd_get_capacity(mdev->ldev->backing_bdev))
+		mdev->ldev->known_size = drbd_get_capacity(mdev->ldev->backing_bdev);
 
-	if (!rsr) {
-		crypto_free_hash(mdev->csums_tfm);
-		mdev->csums_tfm = csums_tfm;
-		csums_tfm = NULL;
+	if (new_disk_conf) {
+		mutex_lock(&mdev->tconn->conf_update);
+		old_disk_conf = mdev->ldev->disk_conf;
+		*new_disk_conf = *old_disk_conf;
+		new_disk_conf->disk_size = (sector_t)rs.resize_size;
+		rcu_assign_pointer(mdev->ldev->disk_conf, new_disk_conf);
+		mutex_unlock(&mdev->tconn->conf_update);
+		synchronize_rcu();
+		kfree(old_disk_conf);
 	}
 
-	if (!ovr) {
-		crypto_free_hash(mdev->verify_tfm);
-		mdev->verify_tfm = verify_tfm;
-		verify_tfm = NULL;
+	ddsf = (rs.resize_force ? DDSF_FORCED : 0) | (rs.no_resync ? DDSF_NO_RESYNC : 0);
+	dd = drbd_determine_dev_size(mdev, ddsf);
+	drbd_md_sync(mdev);
+	put_ldev(mdev);
+	if (dd == dev_size_error) {
+		retcode = ERR_NOMEM_BITMAP;
+		goto fail;
 	}
 
-	if (fifo_size != mdev->rs_plan_s.size) {
-		kfree(mdev->rs_plan_s.values);
-		mdev->rs_plan_s.values = rs_plan_s;
-		mdev->rs_plan_s.size   = fifo_size;
-		mdev->rs_planed = 0;
-		rs_plan_s = NULL;
+	if (mdev->state.conn == C_CONNECTED) {
+		if (dd == grew)
+			set_bit(RESIZE_PENDING, &mdev->flags);
+
+		drbd_send_uuids(mdev);
+		drbd_send_sizes(mdev, 1, ddsf);
 	}
 
-	spin_unlock(&mdev->peer_seq_lock);
+ fail:
+	drbd_adm_finish(info, retcode);
+	return 0;
 
-	if (get_ldev(mdev)) {
-		wait_event(mdev->al_wait, lc_try_lock(mdev->act_log));
-		drbd_al_shrink(mdev);
-		err = drbd_check_al_size(mdev);
-		lc_unlock(mdev->act_log);
-		wake_up(&mdev->al_wait);
+ fail_ldev:
+	put_ldev(mdev);
+	goto fail;
+}
 
-		put_ldev(mdev);
-		drbd_md_sync(mdev);
+int drbd_adm_resource_opts(struct sk_buff *skb, struct genl_info *info)
+{
+	enum drbd_ret_code retcode;
+	struct drbd_tconn *tconn;
+	struct res_opts res_opts;
+	int err;
 
-		if (err) {
-			retcode = ERR_NOMEM;
-			goto fail;
-		}
-	}
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_RESOURCE);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto fail;
+	tconn = adm_ctx.tconn;
 
-	if (mdev->state.conn >= C_CONNECTED)
-		drbd_send_sync_param(mdev, &sc);
+	res_opts = tconn->res_opts;
+	if (should_set_defaults(info))
+		set_res_opts_defaults(&res_opts);
 
-	if (!cpumask_equal(mdev->cpu_mask, new_cpu_mask)) {
-		cpumask_copy(mdev->cpu_mask, new_cpu_mask);
-		drbd_calc_cpu_mask(mdev);
-		mdev->receiver.reset_cpu_mask = 1;
-		mdev->asender.reset_cpu_mask = 1;
-		mdev->worker.reset_cpu_mask = 1;
+	err = res_opts_from_attrs(&res_opts, info);
+	if (err && err != -ENOMSG) {
+		retcode = ERR_MANDATORY_TAG;
+		drbd_msg_put_info(from_attrs_err_to_txt(err));
+		goto fail;
+	}
+
+	err = set_resource_options(tconn, &res_opts);
+	if (err) {
+		retcode = ERR_INVALID_REQUEST;
+		if (err == -ENOMEM)
+			retcode = ERR_NOMEM;
 	}
 
-	kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE);
 fail:
-	kfree(rs_plan_s);
-	free_cpumask_var(new_cpu_mask);
-	crypto_free_hash(csums_tfm);
-	crypto_free_hash(verify_tfm);
-	reply->ret_code = retcode;
+	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
-static int drbd_nl_invalidate(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			      struct drbd_nl_cfg_reply *reply)
+int drbd_adm_invalidate(struct sk_buff *skb, struct genl_info *info)
 {
-	int retcode;
+	struct drbd_conf *mdev;
+	int retcode; /* enum drbd_ret_code rsp. enum drbd_state_rv */
+
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
+
+	mdev = adm_ctx.mdev;
 
 	/* If there is still bitmap IO pending, probably because of a previous
 	 * resync just being finished, wait for it before requesting a new resync.
@@ -1990,10 +2407,10 @@ static int drbd_nl_invalidate(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl
 		retcode = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_T));
 
 	while (retcode == SS_NEED_CONNECTION) {
-		spin_lock_irq(&mdev->req_lock);
+		spin_lock_irq(&mdev->tconn->req_lock);
 		if (mdev->state.conn < C_CONNECTED)
 			retcode = _drbd_set_state(_NS(mdev, disk, D_INCONSISTENT), CS_VERBOSE, NULL);
-		spin_unlock_irq(&mdev->req_lock);
+		spin_unlock_irq(&mdev->tconn->req_lock);
 
 		if (retcode != SS_NEED_CONNECTION)
 			break;
@@ -2002,7 +2419,25 @@ static int drbd_nl_invalidate(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl
 	}
 	drbd_resume_io(mdev);
 
-	reply->ret_code = retcode;
+out:
+	drbd_adm_finish(info, retcode);
+	return 0;
+}
+
+static int drbd_adm_simple_request_state(struct sk_buff *skb, struct genl_info *info,
+		union drbd_state mask, union drbd_state val)
+{
+	enum drbd_ret_code retcode;
+
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
+
+	retcode = drbd_request_state(adm_ctx.mdev, mask, val);
+out:
+	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
@@ -2015,10 +2450,18 @@ static int drbd_bmio_set_susp_al(struct drbd_conf *mdev)
 	return rv;
 }
 
-static int drbd_nl_invalidate_peer(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-				   struct drbd_nl_cfg_reply *reply)
+int drbd_adm_invalidate_peer(struct sk_buff *skb, struct genl_info *info)
 {
-	int retcode;
+	int retcode; /* drbd_ret_code, drbd_state_rv */
+	struct drbd_conf *mdev;
+
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
+
+	mdev = adm_ctx.mdev;
 
 	/* If there is still bitmap IO pending, probably because of a previous
 	 * resync just being finished, wait for it before requesting a new resync.
@@ -2028,16 +2471,15 @@ static int drbd_nl_invalidate_peer(struct drbd_conf *mdev, struct drbd_nl_cfg_re
 	drbd_flush_workqueue(mdev);
 
 	retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S), CS_ORDERED);
-
 	if (retcode < SS_SUCCESS) {
 		if (retcode == SS_NEED_CONNECTION && mdev->state.role == R_PRIMARY) {
-			/* The peer will get a resync upon connect anyways. Just make that
-			   into a full resync. */
+			/* The peer will get a resync upon connect anyways.
+			 * Just make that into a full resync. */
 			retcode = drbd_request_state(mdev, NS(pdsk, D_INCONSISTENT));
 			if (retcode >= SS_SUCCESS) {
 				if (drbd_bitmap_io(mdev, &drbd_bmio_set_susp_al,
-					"set_n_write from invalidate_peer",
-					BM_LOCKED_SET_ALLOWED))
+						   "set_n_write from invalidate_peer",
+						   BM_LOCKED_SET_ALLOWED))
 					retcode = ERR_IO_MD_DISK;
 			}
 		} else
@@ -2045,30 +2487,41 @@ static int drbd_nl_invalidate_peer(struct drbd_conf *mdev, struct drbd_nl_cfg_re
 	}
 	drbd_resume_io(mdev);
 
-	reply->ret_code = retcode;
+out:
+	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
-static int drbd_nl_pause_sync(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			      struct drbd_nl_cfg_reply *reply)
+int drbd_adm_pause_sync(struct sk_buff *skb, struct genl_info *info)
 {
-	int retcode = NO_ERROR;
+	enum drbd_ret_code retcode;
 
-	if (drbd_request_state(mdev, NS(user_isp, 1)) == SS_NOTHING_TO_DO)
-		retcode = ERR_PAUSE_IS_SET;
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
 
-	reply->ret_code = retcode;
+	if (drbd_request_state(adm_ctx.mdev, NS(user_isp, 1)) == SS_NOTHING_TO_DO)
+		retcode = ERR_PAUSE_IS_SET;
+out:
+	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
-static int drbd_nl_resume_sync(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			       struct drbd_nl_cfg_reply *reply)
+int drbd_adm_resume_sync(struct sk_buff *skb, struct genl_info *info)
 {
-	int retcode = NO_ERROR;
-	union drbd_state s;
+	union drbd_dev_state s;
+	enum drbd_ret_code retcode;
+
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
 
-	if (drbd_request_state(mdev, NS(user_isp, 0)) == SS_NOTHING_TO_DO) {
-		s = mdev->state;
+	if (drbd_request_state(adm_ctx.mdev, NS(user_isp, 0)) == SS_NOTHING_TO_DO) {
+		s = adm_ctx.mdev->state;
 		if (s.conn == C_PAUSED_SYNC_S || s.conn == C_PAUSED_SYNC_T) {
 			retcode = s.aftr_isp ? ERR_PIC_AFTER_DEP :
 				  s.peer_isp ? ERR_PIC_PEER_DEP : ERR_PAUSE_IS_CLEAR;
@@ -2077,172 +2530,482 @@ static int drbd_nl_resume_sync(struct drbd_conf *mdev, struct drbd_nl_cfg_req *n
 		}
 	}
 
-	reply->ret_code = retcode;
+out:
+	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
-static int drbd_nl_suspend_io(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			      struct drbd_nl_cfg_reply *reply)
+int drbd_adm_suspend_io(struct sk_buff *skb, struct genl_info *info)
 {
-	reply->ret_code = drbd_request_state(mdev, NS(susp, 1));
-
-	return 0;
+	return drbd_adm_simple_request_state(skb, info, NS(susp, 1));
 }
 
-static int drbd_nl_resume_io(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			     struct drbd_nl_cfg_reply *reply)
+int drbd_adm_resume_io(struct sk_buff *skb, struct genl_info *info)
 {
+	struct drbd_conf *mdev;
+	int retcode; /* enum drbd_ret_code rsp. enum drbd_state_rv */
+
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
+
+	mdev = adm_ctx.mdev;
 	if (test_bit(NEW_CUR_UUID, &mdev->flags)) {
 		drbd_uuid_new_current(mdev);
 		clear_bit(NEW_CUR_UUID, &mdev->flags);
 	}
 	drbd_suspend_io(mdev);
-	reply->ret_code = drbd_request_state(mdev, NS3(susp, 0, susp_nod, 0, susp_fen, 0));
-	if (reply->ret_code == SS_SUCCESS) {
+	retcode = drbd_request_state(mdev, NS3(susp, 0, susp_nod, 0, susp_fen, 0));
+	if (retcode == SS_SUCCESS) {
 		if (mdev->state.conn < C_CONNECTED)
-			tl_clear(mdev);
+			tl_clear(mdev->tconn);
 		if (mdev->state.disk == D_DISKLESS || mdev->state.disk == D_FAILED)
-			tl_restart(mdev, fail_frozen_disk_io);
+			tl_restart(mdev->tconn, FAIL_FROZEN_DISK_IO);
 	}
 	drbd_resume_io(mdev);
 
+out:
+	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
-static int drbd_nl_outdate(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			   struct drbd_nl_cfg_reply *reply)
+int drbd_adm_outdate(struct sk_buff *skb, struct genl_info *info)
 {
-	reply->ret_code = drbd_request_state(mdev, NS(disk, D_OUTDATED));
-	return 0;
+	return drbd_adm_simple_request_state(skb, info, NS(disk, D_OUTDATED));
 }
 
-static int drbd_nl_get_config(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			   struct drbd_nl_cfg_reply *reply)
+int nla_put_drbd_cfg_context(struct sk_buff *skb, struct drbd_tconn *tconn, unsigned vnr)
 {
-	unsigned short *tl;
+	struct nlattr *nla;
+	nla = nla_nest_start(skb, DRBD_NLA_CFG_CONTEXT);
+	if (!nla)
+		goto nla_put_failure;
+	if (vnr != VOLUME_UNSPECIFIED &&
+	    nla_put_u32(skb, T_ctx_volume, vnr))
+		goto nla_put_failure;
+	if (nla_put_string(skb, T_ctx_resource_name, tconn->name))
+		goto nla_put_failure;
+	if (tconn->my_addr_len &&
+	    nla_put(skb, T_ctx_my_addr, tconn->my_addr_len, &tconn->my_addr))
+		goto nla_put_failure;
+	if (tconn->peer_addr_len &&
+	    nla_put(skb, T_ctx_peer_addr, tconn->peer_addr_len, &tconn->peer_addr))
+		goto nla_put_failure;
+	nla_nest_end(skb, nla);
+	return 0;
 
-	tl = reply->tag_list;
+nla_put_failure:
+	if (nla)
+		nla_nest_cancel(skb, nla);
+	return -EMSGSIZE;
+}
 
-	if (get_ldev(mdev)) {
-		tl = disk_conf_to_tags(mdev, &mdev->ldev->dc, tl);
-		put_ldev(mdev);
-	}
+int nla_put_status_info(struct sk_buff *skb, struct drbd_conf *mdev,
+		const struct sib_info *sib)
+{
+	struct state_info *si = NULL; /* for sizeof(si->member); */
+	struct net_conf *nc;
+	struct nlattr *nla;
+	int got_ldev;
+	int err = 0;
+	int exclude_sensitive;
+
+	/* If sib != NULL, this is drbd_bcast_event, which anyone can listen
+	 * to.  So we better exclude_sensitive information.
+	 *
+	 * If sib == NULL, this is drbd_adm_get_status, executed synchronously
+	 * in the context of the requesting user process. Exclude sensitive
+	 * information, unless current has superuser.
+	 *
+	 * NOTE: for drbd_adm_get_status_all(), this is a netlink dump, and
+	 * relies on the current implementation of netlink_dump(), which
+	 * executes the dump callback successively from netlink_recvmsg(),
+	 * always in the context of the receiving process */
+	exclude_sensitive = sib || !capable(CAP_SYS_ADMIN);
+
+	got_ldev = get_ldev(mdev);
+
+	/* We need to add connection name and volume number information still.
+	 * Minor number is in drbd_genlmsghdr. */
+	if (nla_put_drbd_cfg_context(skb, mdev->tconn, mdev->vnr))
+		goto nla_put_failure;
+
+	if (res_opts_to_skb(skb, &mdev->tconn->res_opts, exclude_sensitive))
+		goto nla_put_failure;
+
+	rcu_read_lock();
+	if (got_ldev)
+		if (disk_conf_to_skb(skb, rcu_dereference(mdev->ldev->disk_conf), exclude_sensitive))
+			goto nla_put_failure;
+
+	nc = rcu_dereference(mdev->tconn->net_conf);
+	if (nc)
+		err = net_conf_to_skb(skb, nc, exclude_sensitive);
+	rcu_read_unlock();
+	if (err)
+		goto nla_put_failure;
+
+	nla = nla_nest_start(skb, DRBD_NLA_STATE_INFO);
+	if (!nla)
+		goto nla_put_failure;
+	if (nla_put_u32(skb, T_sib_reason, sib ? sib->sib_reason : SIB_GET_STATUS_REPLY) ||
+	    nla_put_u32(skb, T_current_state, mdev->state.i) ||
+	    nla_put_u64(skb, T_ed_uuid, mdev->ed_uuid) ||
+	    nla_put_u64(skb, T_capacity, drbd_get_capacity(mdev->this_bdev)) ||
+	    nla_put_u64(skb, T_send_cnt, mdev->send_cnt) ||
+	    nla_put_u64(skb, T_recv_cnt, mdev->recv_cnt) ||
+	    nla_put_u64(skb, T_read_cnt, mdev->read_cnt) ||
+	    nla_put_u64(skb, T_writ_cnt, mdev->writ_cnt) ||
+	    nla_put_u64(skb, T_al_writ_cnt, mdev->al_writ_cnt) ||
+	    nla_put_u64(skb, T_bm_writ_cnt, mdev->bm_writ_cnt) ||
+	    nla_put_u32(skb, T_ap_bio_cnt, atomic_read(&mdev->ap_bio_cnt)) ||
+	    nla_put_u32(skb, T_ap_pending_cnt, atomic_read(&mdev->ap_pending_cnt)) ||
+	    nla_put_u32(skb, T_rs_pending_cnt, atomic_read(&mdev->rs_pending_cnt)))
+		goto nla_put_failure;
+
+	if (got_ldev) {
+		int err;
 
-	if (get_net_conf(mdev)) {
-		tl = net_conf_to_tags(mdev, mdev->net_conf, tl);
-		put_net_conf(mdev);
+		spin_lock_irq(&mdev->ldev->md.uuid_lock);
+		err = nla_put(skb, T_uuids, sizeof(si->uuids), mdev->ldev->md.uuid);
+		spin_unlock_irq(&mdev->ldev->md.uuid_lock);
+
+		if (err)
+			goto nla_put_failure;
+
+		if (nla_put_u32(skb, T_disk_flags, mdev->ldev->md.flags) ||
+		    nla_put_u64(skb, T_bits_total, drbd_bm_bits(mdev)) ||
+		    nla_put_u64(skb, T_bits_oos, drbd_bm_total_weight(mdev)))
+			goto nla_put_failure;
+		if (C_SYNC_SOURCE <= mdev->state.conn &&
+		    C_PAUSED_SYNC_T >= mdev->state.conn) {
+			if (nla_put_u64(skb, T_bits_rs_total, mdev->rs_total) ||
+			    nla_put_u64(skb, T_bits_rs_failed, mdev->rs_failed))
+				goto nla_put_failure;
+		}
 	}
-	tl = syncer_conf_to_tags(mdev, &mdev->sync_conf, tl);
 
-	put_unaligned(TT_END, tl++); /* Close the tag list */
+	if (sib) {
+		switch(sib->sib_reason) {
+		case SIB_SYNC_PROGRESS:
+		case SIB_GET_STATUS_REPLY:
+			break;
+		case SIB_STATE_CHANGE:
+			if (nla_put_u32(skb, T_prev_state, sib->os.i) ||
+			    nla_put_u32(skb, T_new_state, sib->ns.i))
+				goto nla_put_failure;
+			break;
+		case SIB_HELPER_POST:
+			if (nla_put_u32(skb, T_helper_exit_code,
+					sib->helper_exit_code))
+				goto nla_put_failure;
+			/* fall through */
+		case SIB_HELPER_PRE:
+			if (nla_put_string(skb, T_helper, sib->helper_name))
+				goto nla_put_failure;
+			break;
+		}
+	}
+	nla_nest_end(skb, nla);
 
-	return (int)((char *)tl - (char *)reply->tag_list);
+	if (0)
+nla_put_failure:
+		err = -EMSGSIZE;
+	if (got_ldev)
+		put_ldev(mdev);
+	return err;
 }
 
-static int drbd_nl_get_state(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			     struct drbd_nl_cfg_reply *reply)
+int drbd_adm_get_status(struct sk_buff *skb, struct genl_info *info)
 {
-	unsigned short *tl = reply->tag_list;
-	union drbd_state s = mdev->state;
-	unsigned long rs_left;
-	unsigned int res;
+	enum drbd_ret_code retcode;
+	int err;
 
-	tl = get_state_to_tags(mdev, (struct get_state *)&s, tl);
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
 
-	/* no local ref, no bitmap, no syncer progress. */
-	if (s.conn >= C_SYNC_SOURCE && s.conn <= C_PAUSED_SYNC_T) {
-		if (get_ldev(mdev)) {
-			drbd_get_syncer_progress(mdev, &rs_left, &res);
-			tl = tl_add_int(tl, T_sync_progress, &res);
-			put_ldev(mdev);
-		}
+	err = nla_put_status_info(adm_ctx.reply_skb, adm_ctx.mdev, NULL);
+	if (err) {
+		nlmsg_free(adm_ctx.reply_skb);
+		return err;
 	}
-	put_unaligned(TT_END, tl++); /* Close the tag list */
-
-	return (int)((char *)tl - (char *)reply->tag_list);
+out:
+	drbd_adm_finish(info, retcode);
+	return 0;
 }
 
-static int drbd_nl_get_uuids(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			     struct drbd_nl_cfg_reply *reply)
+int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	unsigned short *tl;
-
-	tl = reply->tag_list;
+	struct drbd_conf *mdev;
+	struct drbd_genlmsghdr *dh;
+	struct drbd_tconn *pos = (struct drbd_tconn*)cb->args[0];
+	struct drbd_tconn *tconn = NULL;
+	struct drbd_tconn *tmp;
+	unsigned volume = cb->args[1];
+
+	/* Open coded, deferred, iteration:
+	 * list_for_each_entry_safe(tconn, tmp, &drbd_tconns, all_tconn) {
+	 *	idr_for_each_entry(&tconn->volumes, mdev, i) {
+	 *	  ...
+	 *	}
+	 * }
+	 * where tconn is cb->args[0];
+	 * and i is cb->args[1];
+	 *
+	 * cb->args[2] indicates if we shall loop over all resources,
+	 * or just dump all volumes of a single resource.
+	 *
+	 * This may miss entries inserted after this dump started,
+	 * or entries deleted before they are reached.
+	 *
+	 * We need to make sure the mdev won't disappear while
+	 * we are looking at it, and revalidate our iterators
+	 * on each iteration.
+	 */
 
-	if (get_ldev(mdev)) {
-		tl = tl_add_blob(tl, T_uuids, mdev->ldev->md.uuid, UI_SIZE*sizeof(u64));
-		tl = tl_add_int(tl, T_uuids_flags, &mdev->ldev->md.flags);
-		put_ldev(mdev);
+	/* synchronize with conn_create()/conn_destroy() */
+	rcu_read_lock();
+	/* revalidate iterator position */
+	list_for_each_entry_rcu(tmp, &drbd_tconns, all_tconn) {
+		if (pos == NULL) {
+			/* first iteration */
+			pos = tmp;
+			tconn = pos;
+			break;
+		}
+		if (tmp == pos) {
+			tconn = pos;
+			break;
+		}
 	}
-	put_unaligned(TT_END, tl++); /* Close the tag list */
+	if (tconn) {
+next_tconn:
+		mdev = idr_get_next(&tconn->volumes, &volume);
+		if (!mdev) {
+			/* No more volumes to dump on this tconn.
+			 * Advance tconn iterator. */
+			pos = list_entry_rcu(tconn->all_tconn.next,
+					     struct drbd_tconn, all_tconn);
+			/* Did we dump any volume on this tconn yet? */
+			if (volume != 0) {
+				/* If we reached the end of the list,
+				 * or only a single resource dump was requested,
+				 * we are done. */
+				if (&pos->all_tconn == &drbd_tconns || cb->args[2])
+					goto out;
+				volume = 0;
+				tconn = pos;
+				goto next_tconn;
+			}
+		}
+
+		dh = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
+				cb->nlh->nlmsg_seq, &drbd_genl_family,
+				NLM_F_MULTI, DRBD_ADM_GET_STATUS);
+		if (!dh)
+			goto out;
+
+		if (!mdev) {
+			/* This is a tconn without a single volume.
+			 * Suprisingly enough, it may have a network
+			 * configuration. */
+			struct net_conf *nc;
+			dh->minor = -1U;
+			dh->ret_code = NO_ERROR;
+			if (nla_put_drbd_cfg_context(skb, tconn, VOLUME_UNSPECIFIED))
+				goto cancel;
+			nc = rcu_dereference(tconn->net_conf);
+			if (nc && net_conf_to_skb(skb, nc, 1) != 0)
+				goto cancel;
+			goto done;
+		}
 
-	return (int)((char *)tl - (char *)reply->tag_list);
+		D_ASSERT(mdev->vnr == volume);
+		D_ASSERT(mdev->tconn == tconn);
+
+		dh->minor = mdev_to_minor(mdev);
+		dh->ret_code = NO_ERROR;
+
+		if (nla_put_status_info(skb, mdev, NULL)) {
+cancel:
+			genlmsg_cancel(skb, dh);
+			goto out;
+		}
+done:
+		genlmsg_end(skb, dh);
+        }
+
+out:
+	rcu_read_unlock();
+	/* where to start the next iteration */
+        cb->args[0] = (long)pos;
+        cb->args[1] = (pos == tconn) ? volume + 1 : 0;
+
+	/* No more tconns/volumes/minors found results in an empty skb.
+	 * Which will terminate the dump. */
+        return skb->len;
 }
 
-/**
- * drbd_nl_get_timeout_flag() - Used by drbdsetup to find out which timeout value to use
- * @mdev:	DRBD device.
- * @nlp:	Netlink/connector packet from drbdsetup
- * @reply:	Reply packet for drbdsetup
+/*
+ * Request status of all resources, or of all volumes within a single resource.
+ *
+ * This is a dump, as the answer may not fit in a single reply skb otherwise.
+ * Which means we cannot use the family->attrbuf or other such members, because
+ * dump is NOT protected by the genl_lock().  During dump, we only have access
+ * to the incoming skb, and need to opencode "parsing" of the nlattr payload.
+ *
+ * Once things are setup properly, we call into get_one_status().
  */
-static int drbd_nl_get_timeout_flag(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-				    struct drbd_nl_cfg_reply *reply)
+int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	unsigned short *tl;
-	char rv;
+	const unsigned hdrlen = GENL_HDRLEN + GENL_MAGIC_FAMILY_HDRSZ;
+	struct nlattr *nla;
+	const char *resource_name;
+	struct drbd_tconn *tconn;
+	int maxtype;
+
+	/* Is this a followup call? */
+	if (cb->args[0]) {
+		/* ... of a single resource dump,
+		 * and the resource iterator has been advanced already? */
+		if (cb->args[2] && cb->args[2] != cb->args[0])
+			return 0; /* DONE. */
+		goto dump;
+	}
+
+	/* First call (from netlink_dump_start).  We need to figure out
+	 * which resource(s) the user wants us to dump. */
+	nla = nla_find(nlmsg_attrdata(cb->nlh, hdrlen),
+			nlmsg_attrlen(cb->nlh, hdrlen),
+			DRBD_NLA_CFG_CONTEXT);
+
+	/* No explicit context given.  Dump all. */
+	if (!nla)
+		goto dump;
+	maxtype = ARRAY_SIZE(drbd_cfg_context_nl_policy) - 1;
+	nla = drbd_nla_find_nested(maxtype, nla, __nla_type(T_ctx_resource_name));
+	if (IS_ERR(nla))
+		return PTR_ERR(nla);
+	/* context given, but no name present? */
+	if (!nla)
+		return -EINVAL;
+	resource_name = nla_data(nla);
+	tconn = conn_get_by_name(resource_name);
+
+	if (!tconn)
+		return -ENODEV;
+
+	kref_put(&tconn->kref, &conn_destroy); /* get_one_status() (re)validates tconn by itself */
+
+	/* prime iterators, and set "filter" mode mark:
+	 * only dump this tconn. */
+	cb->args[0] = (long)tconn;
+	/* cb->args[1] = 0; passed in this way. */
+	cb->args[2] = (long)tconn;
+
+dump:
+	return get_one_status(skb, cb);
+}
 
-	tl = reply->tag_list;
+int drbd_adm_get_timeout_type(struct sk_buff *skb, struct genl_info *info)
+{
+	enum drbd_ret_code retcode;
+	struct timeout_parms tp;
+	int err;
 
-	rv = mdev->state.pdsk == D_OUTDATED        ? UT_PEER_OUTDATED :
-	  test_bit(USE_DEGR_WFC_T, &mdev->flags) ? UT_DEGRADED : UT_DEFAULT;
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
 
-	tl = tl_add_blob(tl, T_use_degraded, &rv, sizeof(rv));
-	put_unaligned(TT_END, tl++); /* Close the tag list */
+	tp.timeout_type =
+		adm_ctx.mdev->state.pdsk == D_OUTDATED ? UT_PEER_OUTDATED :
+		test_bit(USE_DEGR_WFC_T, &adm_ctx.mdev->flags) ? UT_DEGRADED :
+		UT_DEFAULT;
 
-	return (int)((char *)tl - (char *)reply->tag_list);
+	err = timeout_parms_to_priv_skb(adm_ctx.reply_skb, &tp);
+	if (err) {
+		nlmsg_free(adm_ctx.reply_skb);
+		return err;
+	}
+out:
+	drbd_adm_finish(info, retcode);
+	return 0;
 }
 
-static int drbd_nl_start_ov(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-				    struct drbd_nl_cfg_reply *reply)
+int drbd_adm_start_ov(struct sk_buff *skb, struct genl_info *info)
 {
-	/* default to resume from last known position, if possible */
-	struct start_ov args =
-		{ .start_sector = mdev->ov_start_sector };
+	struct drbd_conf *mdev;
+	enum drbd_ret_code retcode;
+	struct start_ov_parms parms;
 
-	if (!start_ov_from_tags(mdev, nlp->tag_list, &args)) {
-		reply->ret_code = ERR_MANDATORY_TAG;
-		return 0;
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
+
+	mdev = adm_ctx.mdev;
+
+	/* resume from last known position, if possible */
+	parms.ov_start_sector = mdev->ov_start_sector;
+	parms.ov_stop_sector = ULLONG_MAX;
+	if (info->attrs[DRBD_NLA_START_OV_PARMS]) {
+		int err = start_ov_parms_from_attrs(&parms, info);
+		if (err) {
+			retcode = ERR_MANDATORY_TAG;
+			drbd_msg_put_info(from_attrs_err_to_txt(err));
+			goto out;
+		}
 	}
+	/* w_make_ov_request expects position to be aligned */
+	mdev->ov_start_sector = parms.ov_start_sector & ~(BM_SECT_PER_BIT-1);
+	mdev->ov_stop_sector = parms.ov_stop_sector;
 
 	/* If there is still bitmap IO pending, e.g. previous resync or verify
 	 * just being finished, wait for it before requesting a new resync. */
 	drbd_suspend_io(mdev);
 	wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags));
-
-	/* w_make_ov_request expects position to be aligned */
-	mdev->ov_start_sector = args.start_sector & ~BM_SECT_PER_BIT;
-	reply->ret_code = drbd_request_state(mdev,NS(conn,C_VERIFY_S));
+	retcode = drbd_request_state(mdev,NS(conn,C_VERIFY_S));
 	drbd_resume_io(mdev);
+out:
+	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
 
-static int drbd_nl_new_c_uuid(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
-			      struct drbd_nl_cfg_reply *reply)
+int drbd_adm_new_c_uuid(struct sk_buff *skb, struct genl_info *info)
 {
-	int retcode = NO_ERROR;
+	struct drbd_conf *mdev;
+	enum drbd_ret_code retcode;
 	int skip_initial_sync = 0;
 	int err;
+	struct new_c_uuid_parms args;
 
-	struct new_c_uuid args;
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out_nolock;
 
-	memset(&args, 0, sizeof(struct new_c_uuid));
-	if (!new_c_uuid_from_tags(mdev, nlp->tag_list, &args)) {
-		reply->ret_code = ERR_MANDATORY_TAG;
-		return 0;
+	mdev = adm_ctx.mdev;
+	memset(&args, 0, sizeof(args));
+	if (info->attrs[DRBD_NLA_NEW_C_UUID_PARMS]) {
+		err = new_c_uuid_parms_from_attrs(&args, info);
+		if (err) {
+			retcode = ERR_MANDATORY_TAG;
+			drbd_msg_put_info(from_attrs_err_to_txt(err));
+			goto out_nolock;
+		}
 	}
 
-	mutex_lock(&mdev->state_mutex); /* Protects us against serialized state changes. */
+	mutex_lock(mdev->state_mutex); /* Protects us against serialized state changes. */
 
 	if (!get_ldev(mdev)) {
 		retcode = ERR_NO_DISK;
@@ -2250,7 +3013,7 @@ static int drbd_nl_new_c_uuid(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl
 	}
 
 	/* this is "skip initial sync", assume to be clean */
-	if (mdev->state.conn == C_CONNECTED && mdev->agreed_pro_version >= 90 &&
+	if (mdev->state.conn == C_CONNECTED && mdev->tconn->agreed_pro_version >= 90 &&
 	    mdev->ldev->md.uuid[UI_CURRENT] == UUID_JUST_CREATED && args.clear_bm) {
 		dev_info(DEV, "Preparing to skip initial sync\n");
 		skip_initial_sync = 1;
@@ -2273,10 +3036,10 @@ static int drbd_nl_new_c_uuid(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl
 			drbd_send_uuids_skip_initial_sync(mdev);
 			_drbd_uuid_set(mdev, UI_BITMAP, 0);
 			drbd_print_uuids(mdev, "cleared bitmap UUID");
-			spin_lock_irq(&mdev->req_lock);
+			spin_lock_irq(&mdev->tconn->req_lock);
 			_drbd_set_state(_NS2(mdev, disk, D_UP_TO_DATE, pdsk, D_UP_TO_DATE),
 					CS_VERBOSE, NULL);
-			spin_unlock_irq(&mdev->req_lock);
+			spin_unlock_irq(&mdev->tconn->req_lock);
 		}
 	}
 
@@ -2284,416 +3047,283 @@ static int drbd_nl_new_c_uuid(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl
 out_dec:
 	put_ldev(mdev);
 out:
-	mutex_unlock(&mdev->state_mutex);
-
-	reply->ret_code = retcode;
+	mutex_unlock(mdev->state_mutex);
+out_nolock:
+	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
-struct cn_handler_struct {
-	int (*function)(struct drbd_conf *,
-			 struct drbd_nl_cfg_req *,
-			 struct drbd_nl_cfg_reply *);
-	int reply_body_size;
-};
-
-static struct cn_handler_struct cnd_table[] = {
-	[ P_primary ]		= { &drbd_nl_primary,		0 },
-	[ P_secondary ]		= { &drbd_nl_secondary,		0 },
-	[ P_disk_conf ]		= { &drbd_nl_disk_conf,		0 },
-	[ P_detach ]		= { &drbd_nl_detach,		0 },
-	[ P_net_conf ]		= { &drbd_nl_net_conf,		0 },
-	[ P_disconnect ]	= { &drbd_nl_disconnect,	0 },
-	[ P_resize ]		= { &drbd_nl_resize,		0 },
-	[ P_syncer_conf ]	= { &drbd_nl_syncer_conf,	0 },
-	[ P_invalidate ]	= { &drbd_nl_invalidate,	0 },
-	[ P_invalidate_peer ]	= { &drbd_nl_invalidate_peer,	0 },
-	[ P_pause_sync ]	= { &drbd_nl_pause_sync,	0 },
-	[ P_resume_sync ]	= { &drbd_nl_resume_sync,	0 },
-	[ P_suspend_io ]	= { &drbd_nl_suspend_io,	0 },
-	[ P_resume_io ]		= { &drbd_nl_resume_io,		0 },
-	[ P_outdate ]		= { &drbd_nl_outdate,		0 },
-	[ P_get_config ]	= { &drbd_nl_get_config,
-				    sizeof(struct syncer_conf_tag_len_struct) +
-				    sizeof(struct disk_conf_tag_len_struct) +
-				    sizeof(struct net_conf_tag_len_struct) },
-	[ P_get_state ]		= { &drbd_nl_get_state,
-				    sizeof(struct get_state_tag_len_struct) +
-				    sizeof(struct sync_progress_tag_len_struct)	},
-	[ P_get_uuids ]		= { &drbd_nl_get_uuids,
-				    sizeof(struct get_uuids_tag_len_struct) },
-	[ P_get_timeout_flag ]	= { &drbd_nl_get_timeout_flag,
-				    sizeof(struct get_timeout_flag_tag_len_struct)},
-	[ P_start_ov ]		= { &drbd_nl_start_ov,		0 },
-	[ P_new_c_uuid ]	= { &drbd_nl_new_c_uuid,	0 },
-};
-
-static void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms *nsp)
+static enum drbd_ret_code
+drbd_check_resource_name(const char *name)
 {
-	struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req *)req->data;
-	struct cn_handler_struct *cm;
-	struct cn_msg *cn_reply;
-	struct drbd_nl_cfg_reply *reply;
-	struct drbd_conf *mdev;
-	int retcode, rr;
-	int reply_size = sizeof(struct cn_msg)
-		+ sizeof(struct drbd_nl_cfg_reply)
-		+ sizeof(short int);
-
-	if (!try_module_get(THIS_MODULE)) {
-		printk(KERN_ERR "drbd: try_module_get() failed!\n");
-		return;
+	if (!name || !name[0]) {
+		drbd_msg_put_info("resource name missing");
+		return ERR_MANDATORY_TAG;
 	}
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		retcode = ERR_PERM;
-		goto fail;
-	}
-
-	mdev = ensure_mdev(nlp->drbd_minor,
-			(nlp->flags & DRBD_NL_CREATE_DEVICE));
-	if (!mdev) {
-		retcode = ERR_MINOR_INVALID;
-		goto fail;
+	/* if we want to use these in sysfs/configfs/debugfs some day,
+	 * we must not allow slashes */
+	if (strchr(name, '/')) {
+		drbd_msg_put_info("invalid resource name");
+		return ERR_INVALID_REQUEST;
 	}
+	return NO_ERROR;
+}
 
-	if (nlp->packet_type >= P_nl_after_last_packet ||
-	    nlp->packet_type == P_return_code_only) {
-		retcode = ERR_PACKET_NR;
-		goto fail;
-	}
+int drbd_adm_new_resource(struct sk_buff *skb, struct genl_info *info)
+{
+	enum drbd_ret_code retcode;
+	struct res_opts res_opts;
+	int err;
 
-	cm = cnd_table + nlp->packet_type;
+	retcode = drbd_adm_prepare(skb, info, 0);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
 
-	/* This may happen if packet number is 0: */
-	if (cm->function == NULL) {
-		retcode = ERR_PACKET_NR;
-		goto fail;
+	set_res_opts_defaults(&res_opts);
+	err = res_opts_from_attrs(&res_opts, info);
+	if (err && err != -ENOMSG) {
+		retcode = ERR_MANDATORY_TAG;
+		drbd_msg_put_info(from_attrs_err_to_txt(err));
+		goto out;
 	}
 
-	reply_size += cm->reply_body_size;
+	retcode = drbd_check_resource_name(adm_ctx.resource_name);
+	if (retcode != NO_ERROR)
+		goto out;
 
-	/* allocation not in the IO path, cqueue thread context */
-	cn_reply = kzalloc(reply_size, GFP_KERNEL);
-	if (!cn_reply) {
-		retcode = ERR_NOMEM;
-		goto fail;
+	if (adm_ctx.tconn) {
+		if (info->nlhdr->nlmsg_flags & NLM_F_EXCL) {
+			retcode = ERR_INVALID_REQUEST;
+			drbd_msg_put_info("resource exists");
+		}
+		/* else: still NO_ERROR */
+		goto out;
 	}
-	reply = (struct drbd_nl_cfg_reply *) cn_reply->data;
-
-	reply->packet_type =
-		cm->reply_body_size ? nlp->packet_type : P_return_code_only;
-	reply->minor = nlp->drbd_minor;
-	reply->ret_code = NO_ERROR; /* Might by modified by cm->function. */
-	/* reply->tag_list; might be modified by cm->function. */
-
-	rr = cm->function(mdev, nlp, reply);
-
-	cn_reply->id = req->id;
-	cn_reply->seq = req->seq;
-	cn_reply->ack = req->ack  + 1;
-	cn_reply->len = sizeof(struct drbd_nl_cfg_reply) + rr;
-	cn_reply->flags = 0;
-
-	rr = cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_KERNEL);
-	if (rr && rr != -ESRCH)
-		printk(KERN_INFO "drbd: cn_netlink_send()=%d\n", rr);
 
-	kfree(cn_reply);
-	module_put(THIS_MODULE);
-	return;
- fail:
-	drbd_nl_send_reply(req, retcode);
-	module_put(THIS_MODULE);
+	if (!conn_create(adm_ctx.resource_name, &res_opts))
+		retcode = ERR_NOMEM;
+out:
+	drbd_adm_finish(info, retcode);
+	return 0;
 }
 
-static atomic_t drbd_nl_seq = ATOMIC_INIT(2); /* two. */
-
-static unsigned short *
-__tl_add_blob(unsigned short *tl, enum drbd_tags tag, const void *data,
-	unsigned short len, int nul_terminated)
+int drbd_adm_add_minor(struct sk_buff *skb, struct genl_info *info)
 {
-	unsigned short l = tag_descriptions[tag_number(tag)].max_len;
-	len = (len < l) ? len :  l;
-	put_unaligned(tag, tl++);
-	put_unaligned(len, tl++);
-	memcpy(tl, data, len);
-	tl = (unsigned short*)((char*)tl + len);
-	if (nul_terminated)
-		*((char*)tl - 1) = 0;
-	return tl;
-}
+	struct drbd_genlmsghdr *dh = info->userhdr;
+	enum drbd_ret_code retcode;
 
-static unsigned short *
-tl_add_blob(unsigned short *tl, enum drbd_tags tag, const void *data, int len)
-{
-	return __tl_add_blob(tl, tag, data, len, 0);
-}
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_RESOURCE);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
 
-static unsigned short *
-tl_add_str(unsigned short *tl, enum drbd_tags tag, const char *str)
-{
-	return __tl_add_blob(tl, tag, str, strlen(str)+1, 0);
-}
+	if (dh->minor > MINORMASK) {
+		drbd_msg_put_info("requested minor out of range");
+		retcode = ERR_INVALID_REQUEST;
+		goto out;
+	}
+	if (adm_ctx.volume > DRBD_VOLUME_MAX) {
+		drbd_msg_put_info("requested volume id out of range");
+		retcode = ERR_INVALID_REQUEST;
+		goto out;
+	}
 
-static unsigned short *
-tl_add_int(unsigned short *tl, enum drbd_tags tag, const void *val)
-{
-	put_unaligned(tag, tl++);
-	switch(tag_type(tag)) {
-	case TT_INTEGER:
-		put_unaligned(sizeof(int), tl++);
-		put_unaligned(*(int *)val, (int *)tl);
-		tl = (unsigned short*)((char*)tl+sizeof(int));
-		break;
-	case TT_INT64:
-		put_unaligned(sizeof(u64), tl++);
-		put_unaligned(*(u64 *)val, (u64 *)tl);
-		tl = (unsigned short*)((char*)tl+sizeof(u64));
-		break;
-	default:
-		/* someone did something stupid. */
-		;
+	/* drbd_adm_prepare made sure already
+	 * that mdev->tconn and mdev->vnr match the request. */
+	if (adm_ctx.mdev) {
+		if (info->nlhdr->nlmsg_flags & NLM_F_EXCL)
+			retcode = ERR_MINOR_EXISTS;
+		/* else: still NO_ERROR */
+		goto out;
 	}
-	return tl;
+
+	retcode = conn_new_minor(adm_ctx.tconn, dh->minor, adm_ctx.volume);
+out:
+	drbd_adm_finish(info, retcode);
+	return 0;
 }
 
-void drbd_bcast_state(struct drbd_conf *mdev, union drbd_state state)
+static enum drbd_ret_code adm_delete_minor(struct drbd_conf *mdev)
 {
-	char buffer[sizeof(struct cn_msg)+
-		    sizeof(struct drbd_nl_cfg_reply)+
-		    sizeof(struct get_state_tag_len_struct)+
-		    sizeof(short int)];
-	struct cn_msg *cn_reply = (struct cn_msg *) buffer;
-	struct drbd_nl_cfg_reply *reply =
-		(struct drbd_nl_cfg_reply *)cn_reply->data;
-	unsigned short *tl = reply->tag_list;
-
-	/* dev_warn(DEV, "drbd_bcast_state() got called\n"); */
-
-	tl = get_state_to_tags(mdev, (struct get_state *)&state, tl);
-
-	put_unaligned(TT_END, tl++); /* Close the tag list */
-
-	cn_reply->id.idx = CN_IDX_DRBD;
-	cn_reply->id.val = CN_VAL_DRBD;
-
-	cn_reply->seq = atomic_add_return(1, &drbd_nl_seq);
-	cn_reply->ack = 0; /* not used here. */
-	cn_reply->len = sizeof(struct drbd_nl_cfg_reply) +
-		(int)((char *)tl - (char *)reply->tag_list);
-	cn_reply->flags = 0;
-
-	reply->packet_type = P_get_state;
-	reply->minor = mdev_to_minor(mdev);
-	reply->ret_code = NO_ERROR;
-
-	cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_NOIO);
+	if (mdev->state.disk == D_DISKLESS &&
+	    /* no need to be mdev->state.conn == C_STANDALONE &&
+	     * we may want to delete a minor from a live replication group.
+	     */
+	    mdev->state.role == R_SECONDARY) {
+		_drbd_request_state(mdev, NS(conn, C_WF_REPORT_PARAMS),
+				    CS_VERBOSE + CS_WAIT_COMPLETE);
+		idr_remove(&mdev->tconn->volumes, mdev->vnr);
+		idr_remove(&minors, mdev_to_minor(mdev));
+		del_gendisk(mdev->vdisk);
+		synchronize_rcu();
+		kref_put(&mdev->kref, &drbd_minor_destroy);
+		return NO_ERROR;
+	} else
+		return ERR_MINOR_CONFIGURED;
 }
 
-void drbd_bcast_ev_helper(struct drbd_conf *mdev, char *helper_name)
+int drbd_adm_delete_minor(struct sk_buff *skb, struct genl_info *info)
 {
-	char buffer[sizeof(struct cn_msg)+
-		    sizeof(struct drbd_nl_cfg_reply)+
-		    sizeof(struct call_helper_tag_len_struct)+
-		    sizeof(short int)];
-	struct cn_msg *cn_reply = (struct cn_msg *) buffer;
-	struct drbd_nl_cfg_reply *reply =
-		(struct drbd_nl_cfg_reply *)cn_reply->data;
-	unsigned short *tl = reply->tag_list;
-
-	/* dev_warn(DEV, "drbd_bcast_state() got called\n"); */
-
-	tl = tl_add_str(tl, T_helper, helper_name);
-	put_unaligned(TT_END, tl++); /* Close the tag list */
-
-	cn_reply->id.idx = CN_IDX_DRBD;
-	cn_reply->id.val = CN_VAL_DRBD;
-
-	cn_reply->seq = atomic_add_return(1, &drbd_nl_seq);
-	cn_reply->ack = 0; /* not used here. */
-	cn_reply->len = sizeof(struct drbd_nl_cfg_reply) +
-		(int)((char *)tl - (char *)reply->tag_list);
-	cn_reply->flags = 0;
+	enum drbd_ret_code retcode;
 
-	reply->packet_type = P_call_helper;
-	reply->minor = mdev_to_minor(mdev);
-	reply->ret_code = NO_ERROR;
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
 
-	cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_NOIO);
+	retcode = adm_delete_minor(adm_ctx.mdev);
+out:
+	drbd_adm_finish(info, retcode);
+	return 0;
 }
 
-void drbd_bcast_ee(struct drbd_conf *mdev,
-		const char *reason, const int dgs,
-		const char* seen_hash, const char* calc_hash,
-		const struct drbd_epoch_entry* e)
+int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
 {
-	struct cn_msg *cn_reply;
-	struct drbd_nl_cfg_reply *reply;
-	unsigned short *tl;
-	struct page *page;
-	unsigned len;
+	int retcode; /* enum drbd_ret_code rsp. enum drbd_state_rv */
+	struct drbd_conf *mdev;
+	unsigned i;
 
-	if (!e)
-		return;
-	if (!reason || !reason[0])
-		return;
+	retcode = drbd_adm_prepare(skb, info, 0);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
 
-	/* apparently we have to memcpy twice, first to prepare the data for the
-	 * struct cn_msg, then within cn_netlink_send from the cn_msg to the
-	 * netlink skb. */
-	/* receiver thread context, which is not in the writeout path (of this node),
-	 * but may be in the writeout path of the _other_ node.
-	 * GFP_NOIO to avoid potential "distributed deadlock". */
-	cn_reply = kzalloc(
-		sizeof(struct cn_msg)+
-		sizeof(struct drbd_nl_cfg_reply)+
-		sizeof(struct dump_ee_tag_len_struct)+
-		sizeof(short int),
-		GFP_NOIO);
-
-	if (!cn_reply) {
-		dev_err(DEV, "could not kmalloc buffer for drbd_bcast_ee, sector %llu, size %u\n",
-				(unsigned long long)e->sector, e->size);
-		return;
+	if (!adm_ctx.tconn) {
+		retcode = ERR_RES_NOT_KNOWN;
+		goto out;
 	}
 
-	reply = (struct drbd_nl_cfg_reply*)cn_reply->data;
-	tl = reply->tag_list;
-
-	tl = tl_add_str(tl, T_dump_ee_reason, reason);
-	tl = tl_add_blob(tl, T_seen_digest, seen_hash, dgs);
-	tl = tl_add_blob(tl, T_calc_digest, calc_hash, dgs);
-	tl = tl_add_int(tl, T_ee_sector, &e->sector);
-	tl = tl_add_int(tl, T_ee_block_id, &e->block_id);
-
-	/* dump the first 32k */
-	len = min_t(unsigned, e->size, 32 << 10);
-	put_unaligned(T_ee_data, tl++);
-	put_unaligned(len, tl++);
-
-	page = e->pages;
-	page_chain_for_each(page) {
-		void *d = kmap_atomic(page);
-		unsigned l = min_t(unsigned, len, PAGE_SIZE);
-		memcpy(tl, d, l);
-		kunmap_atomic(d);
-		tl = (unsigned short*)((char*)tl + l);
-		len -= l;
-		if (len == 0)
-			break;
+	/* demote */
+	idr_for_each_entry(&adm_ctx.tconn->volumes, mdev, i) {
+		retcode = drbd_set_role(mdev, R_SECONDARY, 0);
+		if (retcode < SS_SUCCESS) {
+			drbd_msg_put_info("failed to demote");
+			goto out;
+		}
 	}
-	put_unaligned(TT_END, tl++); /* Close the tag list */
-
-	cn_reply->id.idx = CN_IDX_DRBD;
-	cn_reply->id.val = CN_VAL_DRBD;
-
-	cn_reply->seq = atomic_add_return(1,&drbd_nl_seq);
-	cn_reply->ack = 0; // not used here.
-	cn_reply->len = sizeof(struct drbd_nl_cfg_reply) +
-		(int)((char*)tl - (char*)reply->tag_list);
-	cn_reply->flags = 0;
 
-	reply->packet_type = P_dump_ee;
-	reply->minor = mdev_to_minor(mdev);
-	reply->ret_code = NO_ERROR;
-
-	cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_NOIO);
-	kfree(cn_reply);
-}
-
-void drbd_bcast_sync_progress(struct drbd_conf *mdev)
-{
-	char buffer[sizeof(struct cn_msg)+
-		    sizeof(struct drbd_nl_cfg_reply)+
-		    sizeof(struct sync_progress_tag_len_struct)+
-		    sizeof(short int)];
-	struct cn_msg *cn_reply = (struct cn_msg *) buffer;
-	struct drbd_nl_cfg_reply *reply =
-		(struct drbd_nl_cfg_reply *)cn_reply->data;
-	unsigned short *tl = reply->tag_list;
-	unsigned long rs_left;
-	unsigned int res;
+	retcode = conn_try_disconnect(adm_ctx.tconn, 0);
+	if (retcode < SS_SUCCESS) {
+		drbd_msg_put_info("failed to disconnect");
+		goto out;
+	}
 
-	/* no local ref, no bitmap, no syncer progress, no broadcast. */
-	if (!get_ldev(mdev))
-		return;
-	drbd_get_syncer_progress(mdev, &rs_left, &res);
-	put_ldev(mdev);
+	/* detach */
+	idr_for_each_entry(&adm_ctx.tconn->volumes, mdev, i) {
+		retcode = adm_detach(mdev, 0);
+		if (retcode < SS_SUCCESS || retcode > NO_ERROR) {
+			drbd_msg_put_info("failed to detach");
+			goto out;
+		}
+	}
 
-	tl = tl_add_int(tl, T_sync_progress, &res);
-	put_unaligned(TT_END, tl++); /* Close the tag list */
+	/* If we reach this, all volumes (of this tconn) are Secondary,
+	 * Disconnected, Diskless, aka Unconfigured. Make sure all threads have
+	 * actually stopped, state handling only does drbd_thread_stop_nowait(). */
+	drbd_thread_stop(&adm_ctx.tconn->worker);
 
-	cn_reply->id.idx = CN_IDX_DRBD;
-	cn_reply->id.val = CN_VAL_DRBD;
+	/* Now, nothing can fail anymore */
 
-	cn_reply->seq = atomic_add_return(1, &drbd_nl_seq);
-	cn_reply->ack = 0; /* not used here. */
-	cn_reply->len = sizeof(struct drbd_nl_cfg_reply) +
-		(int)((char *)tl - (char *)reply->tag_list);
-	cn_reply->flags = 0;
+	/* delete volumes */
+	idr_for_each_entry(&adm_ctx.tconn->volumes, mdev, i) {
+		retcode = adm_delete_minor(mdev);
+		if (retcode != NO_ERROR) {
+			/* "can not happen" */
+			drbd_msg_put_info("failed to delete volume");
+			goto out;
+		}
+	}
 
-	reply->packet_type = P_sync_progress;
-	reply->minor = mdev_to_minor(mdev);
-	reply->ret_code = NO_ERROR;
+	/* delete connection */
+	if (conn_lowest_minor(adm_ctx.tconn) < 0) {
+		list_del_rcu(&adm_ctx.tconn->all_tconn);
+		synchronize_rcu();
+		kref_put(&adm_ctx.tconn->kref, &conn_destroy);
 
-	cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_NOIO);
+		retcode = NO_ERROR;
+	} else {
+		/* "can not happen" */
+		retcode = ERR_RES_IN_USE;
+		drbd_msg_put_info("failed to delete connection");
+	}
+	goto out;
+out:
+	drbd_adm_finish(info, retcode);
+	return 0;
 }
 
-int __init drbd_nl_init(void)
+int drbd_adm_del_resource(struct sk_buff *skb, struct genl_info *info)
 {
-	static struct cb_id cn_id_drbd;
-	int err, try=10;
+	enum drbd_ret_code retcode;
 
-	cn_id_drbd.val = CN_VAL_DRBD;
-	do {
-		cn_id_drbd.idx = cn_idx;
-		err = cn_add_callback(&cn_id_drbd, "cn_drbd", &drbd_connector_callback);
-		if (!err)
-			break;
-		cn_idx = (cn_idx + CN_IDX_STEP);
-	} while (try--);
+	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_RESOURCE);
+	if (!adm_ctx.reply_skb)
+		return retcode;
+	if (retcode != NO_ERROR)
+		goto out;
 
-	if (err) {
-		printk(KERN_ERR "drbd: cn_drbd failed to register\n");
-		return err;
+	if (conn_lowest_minor(adm_ctx.tconn) < 0) {
+		list_del_rcu(&adm_ctx.tconn->all_tconn);
+		synchronize_rcu();
+		kref_put(&adm_ctx.tconn->kref, &conn_destroy);
+
+		retcode = NO_ERROR;
+	} else {
+		retcode = ERR_RES_IN_USE;
 	}
 
+	if (retcode == NO_ERROR)
+		drbd_thread_stop(&adm_ctx.tconn->worker);
+out:
+	drbd_adm_finish(info, retcode);
 	return 0;
 }
 
-void drbd_nl_cleanup(void)
-{
-	static struct cb_id cn_id_drbd;
-
-	cn_id_drbd.idx = cn_idx;
-	cn_id_drbd.val = CN_VAL_DRBD;
-
-	cn_del_callback(&cn_id_drbd);
-}
-
-void drbd_nl_send_reply(struct cn_msg *req, int ret_code)
+void drbd_bcast_event(struct drbd_conf *mdev, const struct sib_info *sib)
 {
-	char buffer[sizeof(struct cn_msg)+sizeof(struct drbd_nl_cfg_reply)];
-	struct cn_msg *cn_reply = (struct cn_msg *) buffer;
-	struct drbd_nl_cfg_reply *reply =
-		(struct drbd_nl_cfg_reply *)cn_reply->data;
-	int rr;
-
-	memset(buffer, 0, sizeof(buffer));
-	cn_reply->id = req->id;
+	static atomic_t drbd_genl_seq = ATOMIC_INIT(2); /* two. */
+	struct sk_buff *msg;
+	struct drbd_genlmsghdr *d_out;
+	unsigned seq;
+	int err = -ENOMEM;
+
+	if (sib->sib_reason == SIB_SYNC_PROGRESS &&
+	    time_after(jiffies, mdev->rs_last_bcast + HZ))
+		mdev->rs_last_bcast = jiffies;
+	else
+		return;
 
-	cn_reply->seq = req->seq;
-	cn_reply->ack = req->ack  + 1;
-	cn_reply->len = sizeof(struct drbd_nl_cfg_reply);
-	cn_reply->flags = 0;
+	seq = atomic_inc_return(&drbd_genl_seq);
+	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_NOIO);
+	if (!msg)
+		goto failed;
+
+	err = -EMSGSIZE;
+	d_out = genlmsg_put(msg, 0, seq, &drbd_genl_family, 0, DRBD_EVENT);
+	if (!d_out) /* cannot happen, but anyways. */
+		goto nla_put_failure;
+	d_out->minor = mdev_to_minor(mdev);
+	d_out->ret_code = NO_ERROR;
+
+	if (nla_put_status_info(msg, mdev, sib))
+		goto nla_put_failure;
+	genlmsg_end(msg, d_out);
+	err = drbd_genl_multicast_events(msg, 0);
+	/* msg has been consumed or freed in netlink_broadcast() */
+	if (err && err != -ESRCH)
+		goto failed;
 
-	reply->packet_type = P_return_code_only;
-	reply->minor = ((struct drbd_nl_cfg_req *)req->data)->drbd_minor;
-	reply->ret_code = ret_code;
+	return;
 
-	rr = cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_NOIO);
-	if (rr && rr != -ESRCH)
-		printk(KERN_INFO "drbd: cn_netlink_send()=%d\n", rr);
+nla_put_failure:
+	nlmsg_free(msg);
+failed:
+	dev_err(DEV, "Error %d while broadcasting event. "
+			"Event seq:%u sib_reason:%u\n",
+			err, seq, sib->sib_reason);
 }
-
diff --git a/drivers/block/drbd/drbd_nla.c b/drivers/block/drbd/drbd_nla.c
new file mode 100644
index 0000000..fa672b6
--- /dev/null
+++ b/drivers/block/drbd/drbd_nla.c
@@ -0,0 +1,55 @@
+#include "drbd_wrappers.h"
+#include <linux/kernel.h>
+#include <net/netlink.h>
+#include <linux/drbd_genl_api.h>
+#include "drbd_nla.h"
+
+static int drbd_nla_check_mandatory(int maxtype, struct nlattr *nla)
+{
+	struct nlattr *head = nla_data(nla);
+	int len = nla_len(nla);
+	int rem;
+
+	/*
+	 * validate_nla (called from nla_parse_nested) ignores attributes
+	 * beyond maxtype, and does not understand the DRBD_GENLA_F_MANDATORY flag.
+	 * In order to have it validate attributes with the DRBD_GENLA_F_MANDATORY
+	 * flag set also, check and remove that flag before calling
+	 * nla_parse_nested.
+	 */
+
+	nla_for_each_attr(nla, head, len, rem) {
+		if (nla->nla_type & DRBD_GENLA_F_MANDATORY) {
+			nla->nla_type &= ~DRBD_GENLA_F_MANDATORY;
+			if (nla_type(nla) > maxtype)
+				return -EOPNOTSUPP;
+		}
+	}
+	return 0;
+}
+
+int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
+			  const struct nla_policy *policy)
+{
+	int err;
+
+	err = drbd_nla_check_mandatory(maxtype, nla);
+	if (!err)
+		err = nla_parse_nested(tb, maxtype, nla, policy);
+
+	return err;
+}
+
+struct nlattr *drbd_nla_find_nested(int maxtype, struct nlattr *nla, int attrtype)
+{
+	int err;
+	/*
+	 * If any nested attribute has the DRBD_GENLA_F_MANDATORY flag set and
+	 * we don't know about that attribute, reject all the nested
+	 * attributes.
+	 */
+	err = drbd_nla_check_mandatory(maxtype, nla);
+	if (err)
+		return ERR_PTR(err);
+	return nla_find_nested(nla, attrtype);
+}
diff --git a/drivers/block/drbd/drbd_nla.h b/drivers/block/drbd/drbd_nla.h
new file mode 100644
index 0000000..679c2d5
--- /dev/null
+++ b/drivers/block/drbd/drbd_nla.h
@@ -0,0 +1,8 @@
+#ifndef __DRBD_NLA_H
+#define __DRBD_NLA_H
+
+extern int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
+				 const struct nla_policy *policy);
+extern struct nlattr *drbd_nla_find_nested(int maxtype, struct nlattr *nla, int attrtype);
+
+#endif  /* __DRBD_NLA_H */
diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c
index 5496104..56672a6 100644
--- a/drivers/block/drbd/drbd_proc.c
+++ b/drivers/block/drbd/drbd_proc.c
@@ -167,18 +167,24 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
 		 * we convert to sectors in the display below. */
 		unsigned long bm_bits = drbd_bm_bits(mdev);
 		unsigned long bit_pos;
+		unsigned long long stop_sector = 0;
 		if (mdev->state.conn == C_VERIFY_S ||
-		    mdev->state.conn == C_VERIFY_T)
+		    mdev->state.conn == C_VERIFY_T) {
 			bit_pos = bm_bits - mdev->ov_left;
-		else
+			if (verify_can_do_stop_sector(mdev))
+				stop_sector = mdev->ov_stop_sector;
+		} else
 			bit_pos = mdev->bm_resync_fo;
 		/* Total sectors may be slightly off for oddly
 		 * sized devices. So what. */
 		seq_printf(seq,
-			"\t%3d%% sector pos: %llu/%llu\n",
+			"\t%3d%% sector pos: %llu/%llu",
 			(int)(bit_pos / (bm_bits/100+1)),
 			(unsigned long long)bit_pos * BM_SECT_PER_BIT,
 			(unsigned long long)bm_bits * BM_SECT_PER_BIT);
+		if (stop_sector != 0 && stop_sector != ULLONG_MAX)
+			seq_printf(seq, " stop sector: %llu", stop_sector);
+		seq_printf(seq, "\n");
 	}
 }
 
@@ -194,9 +200,11 @@ static void resync_dump_detail(struct seq_file *seq, struct lc_element *e)
 
 static int drbd_seq_show(struct seq_file *seq, void *v)
 {
-	int i, hole = 0;
+	int i, prev_i = -1;
 	const char *sn;
 	struct drbd_conf *mdev;
+	struct net_conf *nc;
+	char wp;
 
 	static char write_ordering_chars[] = {
 		[WO_none] = 'n',
@@ -227,16 +235,11 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
 	 oos .. known out-of-sync kB
 	*/
 
-	for (i = 0; i < minor_count; i++) {
-		mdev = minor_to_mdev(i);
-		if (!mdev) {
-			hole = 1;
-			continue;
-		}
-		if (hole) {
-			hole = 0;
+	rcu_read_lock();
+	idr_for_each_entry(&minors, mdev, i) {
+		if (prev_i != i - 1)
 			seq_printf(seq, "\n");
-		}
+		prev_i = i;
 
 		sn = drbd_conn_str(mdev->state.conn);
 
@@ -248,6 +251,8 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
 			/* reset mdev->congestion_reason */
 			bdi_rw_congested(&mdev->rq_queue->backing_dev_info);
 
+			nc = rcu_dereference(mdev->tconn->net_conf);
+			wp = nc ? nc->wire_protocol - DRBD_PROT_A + 'A' : ' ';
 			seq_printf(seq,
 			   "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
 			   "    ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
@@ -257,9 +262,8 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
 			   drbd_role_str(mdev->state.peer),
 			   drbd_disk_str(mdev->state.disk),
 			   drbd_disk_str(mdev->state.pdsk),
-			   (mdev->net_conf == NULL ? ' ' :
-			    (mdev->net_conf->wire_protocol - DRBD_PROT_A+'A')),
-			   is_susp(mdev->state) ? 's' : 'r',
+			   wp,
+			   drbd_suspended(mdev) ? 's' : 'r',
 			   mdev->state.aftr_isp ? 'a' : '-',
 			   mdev->state.peer_isp ? 'p' : '-',
 			   mdev->state.user_isp ? 'u' : '-',
@@ -276,8 +280,8 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
 			   atomic_read(&mdev->rs_pending_cnt),
 			   atomic_read(&mdev->unacked_cnt),
 			   atomic_read(&mdev->ap_bio_cnt),
-			   mdev->epochs,
-			   write_ordering_chars[mdev->write_ordering]
+			   mdev->tconn->epochs,
+			   write_ordering_chars[mdev->tconn->write_ordering]
 			);
 			seq_printf(seq, " oos:%llu\n",
 				   Bit2KB((unsigned long long)
@@ -302,6 +306,7 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
 			}
 		}
 	}
+	rcu_read_unlock();
 
 	return 0;
 }
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index c74ca2d..1599a1a 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -48,17 +48,25 @@
 
 #include "drbd_vli.h"
 
+struct packet_info {
+	enum drbd_packet cmd;
+	unsigned int size;
+	unsigned int vnr;
+	void *data;
+};
+
 enum finish_epoch {
 	FE_STILL_LIVE,
 	FE_DESTROYED,
 	FE_RECYCLED,
 };
 
-static int drbd_do_handshake(struct drbd_conf *mdev);
-static int drbd_do_auth(struct drbd_conf *mdev);
+static int drbd_do_features(struct drbd_tconn *tconn);
+static int drbd_do_auth(struct drbd_tconn *tconn);
+static int drbd_disconnected(struct drbd_conf *mdev);
 
-static enum finish_epoch drbd_may_finish_epoch(struct drbd_conf *, struct drbd_epoch *, enum epoch_event);
-static int e_end_block(struct drbd_conf *, struct drbd_work *, int);
+static enum finish_epoch drbd_may_finish_epoch(struct drbd_tconn *, struct drbd_epoch *, enum epoch_event);
+static int e_end_block(struct drbd_work *, int);
 
 
 #define GFP_TRY	(__GFP_HIGHMEM | __GFP_NOWARN)
@@ -142,11 +150,12 @@ static void page_chain_add(struct page **head,
 	*head = chain_first;
 }
 
-static struct page *drbd_pp_first_pages_or_try_alloc(struct drbd_conf *mdev, int number)
+static struct page *__drbd_alloc_pages(struct drbd_conf *mdev,
+				       unsigned int number)
 {
 	struct page *page = NULL;
 	struct page *tmp = NULL;
-	int i = 0;
+	unsigned int i = 0;
 
 	/* Yes, testing drbd_pp_vacant outside the lock is racy.
 	 * So what. It saves a spin_lock. */
@@ -175,7 +184,7 @@ static struct page *drbd_pp_first_pages_or_try_alloc(struct drbd_conf *mdev, int
 		return page;
 
 	/* Not enough pages immediately available this time.
-	 * No need to jump around here, drbd_pp_alloc will retry this
+	 * No need to jump around here, drbd_alloc_pages will retry this
 	 * function "soon". */
 	if (page) {
 		tmp = page_chain_tail(page, NULL);
@@ -187,9 +196,10 @@ static struct page *drbd_pp_first_pages_or_try_alloc(struct drbd_conf *mdev, int
 	return NULL;
 }
 
-static void reclaim_net_ee(struct drbd_conf *mdev, struct list_head *to_be_freed)
+static void reclaim_finished_net_peer_reqs(struct drbd_conf *mdev,
+					   struct list_head *to_be_freed)
 {
-	struct drbd_epoch_entry *e;
+	struct drbd_peer_request *peer_req;
 	struct list_head *le, *tle;
 
 	/* The EEs are always appended to the end of the list. Since
@@ -198,8 +208,8 @@ static void reclaim_net_ee(struct drbd_conf *mdev, struct list_head *to_be_freed
 	   stop to examine the list... */
 
 	list_for_each_safe(le, tle, &mdev->net_ee) {
-		e = list_entry(le, struct drbd_epoch_entry, w.list);
-		if (drbd_ee_has_active_page(e))
+		peer_req = list_entry(le, struct drbd_peer_request, w.list);
+		if (drbd_peer_req_has_active_page(peer_req))
 			break;
 		list_move(le, to_be_freed);
 	}
@@ -208,18 +218,18 @@ static void reclaim_net_ee(struct drbd_conf *mdev, struct list_head *to_be_freed
 static void drbd_kick_lo_and_reclaim_net(struct drbd_conf *mdev)
 {
 	LIST_HEAD(reclaimed);
-	struct drbd_epoch_entry *e, *t;
+	struct drbd_peer_request *peer_req, *t;
 
-	spin_lock_irq(&mdev->req_lock);
-	reclaim_net_ee(mdev, &reclaimed);
-	spin_unlock_irq(&mdev->req_lock);
+	spin_lock_irq(&mdev->tconn->req_lock);
+	reclaim_finished_net_peer_reqs(mdev, &reclaimed);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
-	list_for_each_entry_safe(e, t, &reclaimed, w.list)
-		drbd_free_net_ee(mdev, e);
+	list_for_each_entry_safe(peer_req, t, &reclaimed, w.list)
+		drbd_free_net_peer_req(mdev, peer_req);
 }
 
 /**
- * drbd_pp_alloc() - Returns @number pages, retries forever (or until signalled)
+ * drbd_alloc_pages() - Returns @number pages, retries forever (or until signalled)
  * @mdev:	DRBD device.
  * @number:	number of pages requested
  * @retry:	whether to retry, if not enough pages are available right now
@@ -230,23 +240,31 @@ static void drbd_kick_lo_and_reclaim_net(struct drbd_conf *mdev)
  *
  * Returns a page chain linked via page->private.
  */
-static struct page *drbd_pp_alloc(struct drbd_conf *mdev, unsigned number, bool retry)
+struct page *drbd_alloc_pages(struct drbd_conf *mdev, unsigned int number,
+			      bool retry)
 {
 	struct page *page = NULL;
+	struct net_conf *nc;
 	DEFINE_WAIT(wait);
+	int mxb;
 
 	/* Yes, we may run up to @number over max_buffers. If we
 	 * follow it strictly, the admin will get it wrong anyways. */
-	if (atomic_read(&mdev->pp_in_use) < mdev->net_conf->max_buffers)
-		page = drbd_pp_first_pages_or_try_alloc(mdev, number);
+	rcu_read_lock();
+	nc = rcu_dereference(mdev->tconn->net_conf);
+	mxb = nc ? nc->max_buffers : 1000000;
+	rcu_read_unlock();
+
+	if (atomic_read(&mdev->pp_in_use) < mxb)
+		page = __drbd_alloc_pages(mdev, number);
 
 	while (page == NULL) {
 		prepare_to_wait(&drbd_pp_wait, &wait, TASK_INTERRUPTIBLE);
 
 		drbd_kick_lo_and_reclaim_net(mdev);
 
-		if (atomic_read(&mdev->pp_in_use) < mdev->net_conf->max_buffers) {
-			page = drbd_pp_first_pages_or_try_alloc(mdev, number);
+		if (atomic_read(&mdev->pp_in_use) < mxb) {
+			page = __drbd_alloc_pages(mdev, number);
 			if (page)
 				break;
 		}
@@ -255,7 +273,7 @@ static struct page *drbd_pp_alloc(struct drbd_conf *mdev, unsigned number, bool
 			break;
 
 		if (signal_pending(current)) {
-			dev_warn(DEV, "drbd_pp_alloc interrupted!\n");
+			dev_warn(DEV, "drbd_alloc_pages interrupted!\n");
 			break;
 		}
 
@@ -268,11 +286,11 @@ static struct page *drbd_pp_alloc(struct drbd_conf *mdev, unsigned number, bool
 	return page;
 }
 
-/* Must not be used from irq, as that may deadlock: see drbd_pp_alloc.
- * Is also used from inside an other spin_lock_irq(&mdev->req_lock);
+/* Must not be used from irq, as that may deadlock: see drbd_alloc_pages.
+ * Is also used from inside an other spin_lock_irq(&mdev->tconn->req_lock);
  * Either links the page chain back to the global pool,
  * or returns all pages to the system. */
-static void drbd_pp_free(struct drbd_conf *mdev, struct page *page, int is_net)
+static void drbd_free_pages(struct drbd_conf *mdev, struct page *page, int is_net)
 {
 	atomic_t *a = is_net ? &mdev->pp_in_use_by_net : &mdev->pp_in_use;
 	int i;
@@ -280,7 +298,7 @@ static void drbd_pp_free(struct drbd_conf *mdev, struct page *page, int is_net)
 	if (page == NULL)
 		return;
 
-	if (drbd_pp_vacant > (DRBD_MAX_BIO_SIZE/PAGE_SIZE)*minor_count)
+	if (drbd_pp_vacant > (DRBD_MAX_BIO_SIZE/PAGE_SIZE) * minor_count)
 		i = page_chain_free(page);
 	else {
 		struct page *tmp;
@@ -302,127 +320,130 @@ You need to hold the req_lock:
  _drbd_wait_ee_list_empty()
 
 You must not have the req_lock:
- drbd_free_ee()
- drbd_alloc_ee()
- drbd_init_ee()
- drbd_release_ee()
+ drbd_free_peer_req()
+ drbd_alloc_peer_req()
+ drbd_free_peer_reqs()
  drbd_ee_fix_bhs()
- drbd_process_done_ee()
+ drbd_finish_peer_reqs()
  drbd_clear_done_ee()
  drbd_wait_ee_list_empty()
 */
 
-struct drbd_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev,
-				     u64 id,
-				     sector_t sector,
-				     unsigned int data_size,
-				     gfp_t gfp_mask) __must_hold(local)
+struct drbd_peer_request *
+drbd_alloc_peer_req(struct drbd_conf *mdev, u64 id, sector_t sector,
+		    unsigned int data_size, gfp_t gfp_mask) __must_hold(local)
 {
-	struct drbd_epoch_entry *e;
+	struct drbd_peer_request *peer_req;
 	struct page *page = NULL;
 	unsigned nr_pages = (data_size + PAGE_SIZE -1) >> PAGE_SHIFT;
 
 	if (drbd_insert_fault(mdev, DRBD_FAULT_AL_EE))
 		return NULL;
 
-	e = mempool_alloc(drbd_ee_mempool, gfp_mask & ~__GFP_HIGHMEM);
-	if (!e) {
+	peer_req = mempool_alloc(drbd_ee_mempool, gfp_mask & ~__GFP_HIGHMEM);
+	if (!peer_req) {
 		if (!(gfp_mask & __GFP_NOWARN))
-			dev_err(DEV, "alloc_ee: Allocation of an EE failed\n");
+			dev_err(DEV, "%s: allocation failed\n", __func__);
 		return NULL;
 	}
 
 	if (data_size) {
-		page = drbd_pp_alloc(mdev, nr_pages, (gfp_mask & __GFP_WAIT));
+		page = drbd_alloc_pages(mdev, nr_pages, (gfp_mask & __GFP_WAIT));
 		if (!page)
 			goto fail;
 	}
 
-	INIT_HLIST_NODE(&e->collision);
-	e->epoch = NULL;
-	e->mdev = mdev;
-	e->pages = page;
-	atomic_set(&e->pending_bios, 0);
-	e->size = data_size;
-	e->flags = 0;
-	e->sector = sector;
-	e->block_id = id;
+	drbd_clear_interval(&peer_req->i);
+	peer_req->i.size = data_size;
+	peer_req->i.sector = sector;
+	peer_req->i.local = false;
+	peer_req->i.waiting = false;
+
+	peer_req->epoch = NULL;
+	peer_req->w.mdev = mdev;
+	peer_req->pages = page;
+	atomic_set(&peer_req->pending_bios, 0);
+	peer_req->flags = 0;
+	/*
+	 * The block_id is opaque to the receiver.  It is not endianness
+	 * converted, and sent back to the sender unchanged.
+	 */
+	peer_req->block_id = id;
 
-	return e;
+	return peer_req;
 
  fail:
-	mempool_free(e, drbd_ee_mempool);
+	mempool_free(peer_req, drbd_ee_mempool);
 	return NULL;
 }
 
-void drbd_free_some_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e, int is_net)
+void __drbd_free_peer_req(struct drbd_conf *mdev, struct drbd_peer_request *peer_req,
+		       int is_net)
 {
-	if (e->flags & EE_HAS_DIGEST)
-		kfree(e->digest);
-	drbd_pp_free(mdev, e->pages, is_net);
-	D_ASSERT(atomic_read(&e->pending_bios) == 0);
-	D_ASSERT(hlist_unhashed(&e->collision));
-	mempool_free(e, drbd_ee_mempool);
+	if (peer_req->flags & EE_HAS_DIGEST)
+		kfree(peer_req->digest);
+	drbd_free_pages(mdev, peer_req->pages, is_net);
+	D_ASSERT(atomic_read(&peer_req->pending_bios) == 0);
+	D_ASSERT(drbd_interval_empty(&peer_req->i));
+	mempool_free(peer_req, drbd_ee_mempool);
 }
 
-int drbd_release_ee(struct drbd_conf *mdev, struct list_head *list)
+int drbd_free_peer_reqs(struct drbd_conf *mdev, struct list_head *list)
 {
 	LIST_HEAD(work_list);
-	struct drbd_epoch_entry *e, *t;
+	struct drbd_peer_request *peer_req, *t;
 	int count = 0;
 	int is_net = list == &mdev->net_ee;
 
-	spin_lock_irq(&mdev->req_lock);
+	spin_lock_irq(&mdev->tconn->req_lock);
 	list_splice_init(list, &work_list);
-	spin_unlock_irq(&mdev->req_lock);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
-	list_for_each_entry_safe(e, t, &work_list, w.list) {
-		drbd_free_some_ee(mdev, e, is_net);
+	list_for_each_entry_safe(peer_req, t, &work_list, w.list) {
+		__drbd_free_peer_req(mdev, peer_req, is_net);
 		count++;
 	}
 	return count;
 }
 
-
 /*
- * This function is called from _asender only_
- * but see also comments in _req_mod(,barrier_acked)
- * and receive_Barrier.
- *
- * Move entries from net_ee to done_ee, if ready.
- * Grab done_ee, call all callbacks, free the entries.
- * The callbacks typically send out ACKs.
+ * See also comments in _req_mod(,BARRIER_ACKED) and receive_Barrier.
  */
-static int drbd_process_done_ee(struct drbd_conf *mdev)
+static int drbd_finish_peer_reqs(struct drbd_conf *mdev)
 {
 	LIST_HEAD(work_list);
 	LIST_HEAD(reclaimed);
-	struct drbd_epoch_entry *e, *t;
-	int ok = (mdev->state.conn >= C_WF_REPORT_PARAMS);
+	struct drbd_peer_request *peer_req, *t;
+	int err = 0;
 
-	spin_lock_irq(&mdev->req_lock);
-	reclaim_net_ee(mdev, &reclaimed);
+	spin_lock_irq(&mdev->tconn->req_lock);
+	reclaim_finished_net_peer_reqs(mdev, &reclaimed);
 	list_splice_init(&mdev->done_ee, &work_list);
-	spin_unlock_irq(&mdev->req_lock);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
-	list_for_each_entry_safe(e, t, &reclaimed, w.list)
-		drbd_free_net_ee(mdev, e);
+	list_for_each_entry_safe(peer_req, t, &reclaimed, w.list)
+		drbd_free_net_peer_req(mdev, peer_req);
 
 	/* possible callbacks here:
-	 * e_end_block, and e_end_resync_block, e_send_discard_ack.
+	 * e_end_block, and e_end_resync_block, e_send_superseded.
 	 * all ignore the last argument.
 	 */
-	list_for_each_entry_safe(e, t, &work_list, w.list) {
+	list_for_each_entry_safe(peer_req, t, &work_list, w.list) {
+		int err2;
+
 		/* list_del not necessary, next/prev members not touched */
-		ok = e->w.cb(mdev, &e->w, !ok) && ok;
-		drbd_free_ee(mdev, e);
+		err2 = peer_req->w.cb(&peer_req->w, !!err);
+		if (!err)
+			err = err2;
+		drbd_free_peer_req(mdev, peer_req);
 	}
 	wake_up(&mdev->ee_wait);
 
-	return ok;
+	return err;
 }
 
-void _drbd_wait_ee_list_empty(struct drbd_conf *mdev, struct list_head *head)
+static void _drbd_wait_ee_list_empty(struct drbd_conf *mdev,
+				     struct list_head *head)
 {
 	DEFINE_WAIT(wait);
 
@@ -430,55 +451,22 @@ void _drbd_wait_ee_list_empty(struct drbd_conf *mdev, struct list_head *head)
 	 * and calling prepare_to_wait in the fast path */
 	while (!list_empty(head)) {
 		prepare_to_wait(&mdev->ee_wait, &wait, TASK_UNINTERRUPTIBLE);
-		spin_unlock_irq(&mdev->req_lock);
+		spin_unlock_irq(&mdev->tconn->req_lock);
 		io_schedule();
 		finish_wait(&mdev->ee_wait, &wait);
-		spin_lock_irq(&mdev->req_lock);
+		spin_lock_irq(&mdev->tconn->req_lock);
 	}
 }
 
-void drbd_wait_ee_list_empty(struct drbd_conf *mdev, struct list_head *head)
+static void drbd_wait_ee_list_empty(struct drbd_conf *mdev,
+				    struct list_head *head)
 {
-	spin_lock_irq(&mdev->req_lock);
+	spin_lock_irq(&mdev->tconn->req_lock);
 	_drbd_wait_ee_list_empty(mdev, head);
-	spin_unlock_irq(&mdev->req_lock);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 }
 
-/* see also kernel_accept; which is only present since 2.6.18.
- * also we want to log which part of it failed, exactly */
-static int drbd_accept(struct drbd_conf *mdev, const char **what,
-		struct socket *sock, struct socket **newsock)
-{
-	struct sock *sk = sock->sk;
-	int err = 0;
-
-	*what = "listen";
-	err = sock->ops->listen(sock, 5);
-	if (err < 0)
-		goto out;
-
-	*what = "sock_create_lite";
-	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
-			       newsock);
-	if (err < 0)
-		goto out;
-
-	*what = "accept";
-	err = sock->ops->accept(sock, *newsock, 0);
-	if (err < 0) {
-		sock_release(*newsock);
-		*newsock = NULL;
-		goto out;
-	}
-	(*newsock)->ops  = sock->ops;
-	__module_get((*newsock)->ops->owner);
-
-out:
-	return err;
-}
-
-static int drbd_recv_short(struct drbd_conf *mdev, struct socket *sock,
-		    void *buf, size_t size, int flags)
+static int drbd_recv_short(struct socket *sock, void *buf, size_t size, int flags)
 {
 	mm_segment_t oldfs;
 	struct kvec iov = {
@@ -500,59 +488,62 @@ static int drbd_recv_short(struct drbd_conf *mdev, struct socket *sock,
 	return rv;
 }
 
-static int drbd_recv(struct drbd_conf *mdev, void *buf, size_t size)
+static int drbd_recv(struct drbd_tconn *tconn, void *buf, size_t size)
 {
-	mm_segment_t oldfs;
-	struct kvec iov = {
-		.iov_base = buf,
-		.iov_len = size,
-	};
-	struct msghdr msg = {
-		.msg_iovlen = 1,
-		.msg_iov = (struct iovec *)&iov,
-		.msg_flags = MSG_WAITALL | MSG_NOSIGNAL
-	};
 	int rv;
 
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
+	rv = drbd_recv_short(tconn->data.socket, buf, size, 0);
 
-	for (;;) {
-		rv = sock_recvmsg(mdev->data.socket, &msg, size, msg.msg_flags);
-		if (rv == size)
-			break;
+	if (rv < 0) {
+		if (rv == -ECONNRESET)
+			conn_info(tconn, "sock was reset by peer\n");
+		else if (rv != -ERESTARTSYS)
+			conn_err(tconn, "sock_recvmsg returned %d\n", rv);
+	} else if (rv == 0) {
+		if (test_bit(DISCONNECT_SENT, &tconn->flags)) {
+			long t;
+			rcu_read_lock();
+			t = rcu_dereference(tconn->net_conf)->ping_timeo * HZ/10;
+			rcu_read_unlock();
 
-		/* Note:
-		 * ECONNRESET	other side closed the connection
-		 * ERESTARTSYS	(on  sock) we got a signal
-		 */
+			t = wait_event_timeout(tconn->ping_wait, tconn->cstate < C_WF_REPORT_PARAMS, t);
 
-		if (rv < 0) {
-			if (rv == -ECONNRESET)
-				dev_info(DEV, "sock was reset by peer\n");
-			else if (rv != -ERESTARTSYS)
-				dev_err(DEV, "sock_recvmsg returned %d\n", rv);
-			break;
-		} else if (rv == 0) {
-			dev_info(DEV, "sock was shut down by peer\n");
-			break;
-		} else	{
-			/* signal came in, or peer/link went down,
-			 * after we read a partial message
-			 */
-			/* D_ASSERT(signal_pending(current)); */
-			break;
+			if (t)
+				goto out;
 		}
-	};
-
-	set_fs(oldfs);
+		conn_info(tconn, "sock was shut down by peer\n");
+	}
 
 	if (rv != size)
-		drbd_force_state(mdev, NS(conn, C_BROKEN_PIPE));
+		conn_request_state(tconn, NS(conn, C_BROKEN_PIPE), CS_HARD);
 
+out:
 	return rv;
 }
 
+static int drbd_recv_all(struct drbd_tconn *tconn, void *buf, size_t size)
+{
+	int err;
+
+	err = drbd_recv(tconn, buf, size);
+	if (err != size) {
+		if (err >= 0)
+			err = -EIO;
+	} else
+		err = 0;
+	return err;
+}
+
+static int drbd_recv_all_warn(struct drbd_tconn *tconn, void *buf, size_t size)
+{
+	int err;
+
+	err = drbd_recv_all(tconn, buf, size);
+	if (err && !signal_pending(current))
+		conn_warn(tconn, "short read (expected size %d)\n", (int)size);
+	return err;
+}
+
 /* quoting tcp(7):
  *   On individual connections, the socket buffer size must be set prior to the
  *   listen(2) or connect(2) calls in order to have it take effect.
@@ -572,29 +563,50 @@ static void drbd_setbufsize(struct socket *sock, unsigned int snd,
 	}
 }
 
-static struct socket *drbd_try_connect(struct drbd_conf *mdev)
+static struct socket *drbd_try_connect(struct drbd_tconn *tconn)
 {
 	const char *what;
 	struct socket *sock;
 	struct sockaddr_in6 src_in6;
-	int err;
+	struct sockaddr_in6 peer_in6;
+	struct net_conf *nc;
+	int err, peer_addr_len, my_addr_len;
+	int sndbuf_size, rcvbuf_size, connect_int;
 	int disconnect_on_error = 1;
 
-	if (!get_net_conf(mdev))
+	rcu_read_lock();
+	nc = rcu_dereference(tconn->net_conf);
+	if (!nc) {
+		rcu_read_unlock();
 		return NULL;
+	}
+	sndbuf_size = nc->sndbuf_size;
+	rcvbuf_size = nc->rcvbuf_size;
+	connect_int = nc->connect_int;
+	rcu_read_unlock();
+
+	my_addr_len = min_t(int, tconn->my_addr_len, sizeof(src_in6));
+	memcpy(&src_in6, &tconn->my_addr, my_addr_len);
+
+	if (((struct sockaddr *)&tconn->my_addr)->sa_family == AF_INET6)
+		src_in6.sin6_port = 0;
+	else
+		((struct sockaddr_in *)&src_in6)->sin_port = 0; /* AF_INET & AF_SCI */
+
+	peer_addr_len = min_t(int, tconn->peer_addr_len, sizeof(src_in6));
+	memcpy(&peer_in6, &tconn->peer_addr, peer_addr_len);
 
 	what = "sock_create_kern";
-	err = sock_create_kern(((struct sockaddr *)mdev->net_conf->my_addr)->sa_family,
-		SOCK_STREAM, IPPROTO_TCP, &sock);
+	err = sock_create_kern(((struct sockaddr *)&src_in6)->sa_family,
+			       SOCK_STREAM, IPPROTO_TCP, &sock);
 	if (err < 0) {
 		sock = NULL;
 		goto out;
 	}
 
 	sock->sk->sk_rcvtimeo =
-	sock->sk->sk_sndtimeo =  mdev->net_conf->try_connect_int*HZ;
-	drbd_setbufsize(sock, mdev->net_conf->sndbuf_size,
-			mdev->net_conf->rcvbuf_size);
+	sock->sk->sk_sndtimeo = connect_int * HZ;
+	drbd_setbufsize(sock, sndbuf_size, rcvbuf_size);
 
        /* explicitly bind to the configured IP as source IP
 	*  for the outgoing connections.
@@ -603,17 +615,8 @@ static struct socket *drbd_try_connect(struct drbd_conf *mdev)
 	* Make sure to use 0 as port number, so linux selects
 	*  a free one dynamically.
 	*/
-	memcpy(&src_in6, mdev->net_conf->my_addr,
-	       min_t(int, mdev->net_conf->my_addr_len, sizeof(src_in6)));
-	if (((struct sockaddr *)mdev->net_conf->my_addr)->sa_family == AF_INET6)
-		src_in6.sin6_port = 0;
-	else
-		((struct sockaddr_in *)&src_in6)->sin_port = 0; /* AF_INET & AF_SCI */
-
 	what = "bind before connect";
-	err = sock->ops->bind(sock,
-			      (struct sockaddr *) &src_in6,
-			      mdev->net_conf->my_addr_len);
+	err = sock->ops->bind(sock, (struct sockaddr *) &src_in6, my_addr_len);
 	if (err < 0)
 		goto out;
 
@@ -621,9 +624,7 @@ static struct socket *drbd_try_connect(struct drbd_conf *mdev)
 	 * stay C_WF_CONNECTION, don't go Disconnecting! */
 	disconnect_on_error = 0;
 	what = "connect";
-	err = sock->ops->connect(sock,
-				 (struct sockaddr *)mdev->net_conf->peer_addr,
-				 mdev->net_conf->peer_addr_len, 0);
+	err = sock->ops->connect(sock, (struct sockaddr *) &peer_in6, peer_addr_len, 0);
 
 out:
 	if (err < 0) {
@@ -641,91 +642,174 @@ out:
 			disconnect_on_error = 0;
 			break;
 		default:
-			dev_err(DEV, "%s failed, err = %d\n", what, err);
+			conn_err(tconn, "%s failed, err = %d\n", what, err);
 		}
 		if (disconnect_on_error)
-			drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
+			conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_HARD);
 	}
-	put_net_conf(mdev);
+
 	return sock;
 }
 
-static struct socket *drbd_wait_for_connect(struct drbd_conf *mdev)
+struct accept_wait_data {
+	struct drbd_tconn *tconn;
+	struct socket *s_listen;
+	struct completion door_bell;
+	void (*original_sk_state_change)(struct sock *sk);
+
+};
+
+static void drbd_incoming_connection(struct sock *sk)
+{
+	struct accept_wait_data *ad = sk->sk_user_data;
+	void (*state_change)(struct sock *sk);
+
+	state_change = ad->original_sk_state_change;
+	if (sk->sk_state == TCP_ESTABLISHED)
+		complete(&ad->door_bell);
+	state_change(sk);
+}
+
+static int prepare_listen_socket(struct drbd_tconn *tconn, struct accept_wait_data *ad)
 {
-	int timeo, err;
-	struct socket *s_estab = NULL, *s_listen;
+	int err, sndbuf_size, rcvbuf_size, my_addr_len;
+	struct sockaddr_in6 my_addr;
+	struct socket *s_listen;
+	struct net_conf *nc;
 	const char *what;
 
-	if (!get_net_conf(mdev))
-		return NULL;
+	rcu_read_lock();
+	nc = rcu_dereference(tconn->net_conf);
+	if (!nc) {
+		rcu_read_unlock();
+		return -EIO;
+	}
+	sndbuf_size = nc->sndbuf_size;
+	rcvbuf_size = nc->rcvbuf_size;
+	rcu_read_unlock();
+
+	my_addr_len = min_t(int, tconn->my_addr_len, sizeof(struct sockaddr_in6));
+	memcpy(&my_addr, &tconn->my_addr, my_addr_len);
 
 	what = "sock_create_kern";
-	err = sock_create_kern(((struct sockaddr *)mdev->net_conf->my_addr)->sa_family,
-		SOCK_STREAM, IPPROTO_TCP, &s_listen);
+	err = sock_create_kern(((struct sockaddr *)&my_addr)->sa_family,
+			       SOCK_STREAM, IPPROTO_TCP, &s_listen);
 	if (err) {
 		s_listen = NULL;
 		goto out;
 	}
 
-	timeo = mdev->net_conf->try_connect_int * HZ;
-	timeo += (random32() & 1) ? timeo / 7 : -timeo / 7; /* 28.5% random jitter */
-
-	s_listen->sk->sk_reuse    = SK_CAN_REUSE; /* SO_REUSEADDR */
-	s_listen->sk->sk_rcvtimeo = timeo;
-	s_listen->sk->sk_sndtimeo = timeo;
-	drbd_setbufsize(s_listen, mdev->net_conf->sndbuf_size,
-			mdev->net_conf->rcvbuf_size);
+	s_listen->sk->sk_reuse = SK_CAN_REUSE; /* SO_REUSEADDR */
+	drbd_setbufsize(s_listen, sndbuf_size, rcvbuf_size);
 
 	what = "bind before listen";
-	err = s_listen->ops->bind(s_listen,
-			      (struct sockaddr *) mdev->net_conf->my_addr,
-			      mdev->net_conf->my_addr_len);
+	err = s_listen->ops->bind(s_listen, (struct sockaddr *)&my_addr, my_addr_len);
 	if (err < 0)
 		goto out;
 
-	err = drbd_accept(mdev, &what, s_listen, &s_estab);
+	ad->s_listen = s_listen;
+	write_lock_bh(&s_listen->sk->sk_callback_lock);
+	ad->original_sk_state_change = s_listen->sk->sk_state_change;
+	s_listen->sk->sk_state_change = drbd_incoming_connection;
+	s_listen->sk->sk_user_data = ad;
+	write_unlock_bh(&s_listen->sk->sk_callback_lock);
+
+	what = "listen";
+	err = s_listen->ops->listen(s_listen, 5);
+	if (err < 0)
+		goto out;
 
+	return 0;
 out:
 	if (s_listen)
 		sock_release(s_listen);
 	if (err < 0) {
 		if (err != -EAGAIN && err != -EINTR && err != -ERESTARTSYS) {
-			dev_err(DEV, "%s failed, err = %d\n", what, err);
-			drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
+			conn_err(tconn, "%s failed, err = %d\n", what, err);
+			conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_HARD);
 		}
 	}
-	put_net_conf(mdev);
 
-	return s_estab;
+	return -EIO;
 }
 
-static int drbd_send_fp(struct drbd_conf *mdev,
-	struct socket *sock, enum drbd_packets cmd)
+static void unregister_state_change(struct sock *sk, struct accept_wait_data *ad)
 {
-	struct p_header80 *h = &mdev->data.sbuf.header.h80;
-
-	return _drbd_send_cmd(mdev, sock, cmd, h, sizeof(*h), 0);
+	write_lock_bh(&sk->sk_callback_lock);
+	sk->sk_state_change = ad->original_sk_state_change;
+	sk->sk_user_data = NULL;
+	write_unlock_bh(&sk->sk_callback_lock);
 }
 
-static enum drbd_packets drbd_recv_fp(struct drbd_conf *mdev, struct socket *sock)
+static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn, struct accept_wait_data *ad)
 {
-	struct p_header80 *h = &mdev->data.rbuf.header.h80;
-	int rr;
+	int timeo, connect_int, err = 0;
+	struct socket *s_estab = NULL;
+	struct net_conf *nc;
+
+	rcu_read_lock();
+	nc = rcu_dereference(tconn->net_conf);
+	if (!nc) {
+		rcu_read_unlock();
+		return NULL;
+	}
+	connect_int = nc->connect_int;
+	rcu_read_unlock();
+
+	timeo = connect_int * HZ;
+	timeo += (random32() & 1) ? timeo / 7 : -timeo / 7; /* 28.5% random jitter */
+
+	err = wait_for_completion_interruptible_timeout(&ad->door_bell, timeo);
+	if (err <= 0)
+		return NULL;
+
+	err = kernel_accept(ad->s_listen, &s_estab, 0);
+	if (err < 0) {
+		if (err != -EAGAIN && err != -EINTR && err != -ERESTARTSYS) {
+			conn_err(tconn, "accept failed, err = %d\n", err);
+			conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+		}
+	}
+
+	if (s_estab)
+		unregister_state_change(s_estab->sk, ad);
+
+	return s_estab;
+}
+
+static int decode_header(struct drbd_tconn *, void *, struct packet_info *);
 
-	rr = drbd_recv_short(mdev, sock, h, sizeof(*h), 0);
+static int send_first_packet(struct drbd_tconn *tconn, struct drbd_socket *sock,
+			     enum drbd_packet cmd)
+{
+	if (!conn_prepare_command(tconn, sock))
+		return -EIO;
+	return conn_send_command(tconn, sock, cmd, 0, NULL, 0);
+}
 
-	if (rr == sizeof(*h) && h->magic == BE_DRBD_MAGIC)
-		return be16_to_cpu(h->command);
+static int receive_first_packet(struct drbd_tconn *tconn, struct socket *sock)
+{
+	unsigned int header_size = drbd_header_size(tconn);
+	struct packet_info pi;
+	int err;
 
-	return 0xffff;
+	err = drbd_recv_short(sock, tconn->data.rbuf, header_size, 0);
+	if (err != header_size) {
+		if (err >= 0)
+			err = -EIO;
+		return err;
+	}
+	err = decode_header(tconn, tconn->data.rbuf, &pi);
+	if (err)
+		return err;
+	return pi.cmd;
 }
 
 /**
  * drbd_socket_okay() - Free the socket if its connection is not okay
- * @mdev:	DRBD device.
  * @sock:	pointer to the pointer to the socket.
  */
-static int drbd_socket_okay(struct drbd_conf *mdev, struct socket **sock)
+static int drbd_socket_okay(struct socket **sock)
 {
 	int rr;
 	char tb[4];
@@ -733,7 +817,7 @@ static int drbd_socket_okay(struct drbd_conf *mdev, struct socket **sock)
 	if (!*sock)
 		return false;
 
-	rr = drbd_recv_short(mdev, *sock, tb, 4, MSG_DONTWAIT | MSG_PEEK);
+	rr = drbd_recv_short(*sock, tb, 4, MSG_DONTWAIT | MSG_PEEK);
 
 	if (rr > 0 || rr == -EAGAIN) {
 		return true;
@@ -743,6 +827,31 @@ static int drbd_socket_okay(struct drbd_conf *mdev, struct socket **sock)
 		return false;
 	}
 }
+/* Gets called if a connection is established, or if a new minor gets created
+   in a connection */
+int drbd_connected(struct drbd_conf *mdev)
+{
+	int err;
+
+	atomic_set(&mdev->packet_seq, 0);
+	mdev->peer_seq = 0;
+
+	mdev->state_mutex = mdev->tconn->agreed_pro_version < 100 ?
+		&mdev->tconn->cstate_mutex :
+		&mdev->own_state_mutex;
+
+	err = drbd_send_sync_param(mdev);
+	if (!err)
+		err = drbd_send_sizes(mdev, 0, 0);
+	if (!err)
+		err = drbd_send_uuids(mdev);
+	if (!err)
+		err = drbd_send_current_state(mdev);
+	clear_bit(USE_DEGR_WFC_T, &mdev->flags);
+	clear_bit(RESIZE_PENDING, &mdev->flags);
+	mod_timer(&mdev->request_timer, jiffies + HZ); /* just start it here. */
+	return err;
+}
 
 /*
  * return values:
@@ -752,232 +861,305 @@ static int drbd_socket_okay(struct drbd_conf *mdev, struct socket **sock)
  *     no point in trying again, please go standalone.
  *  -2 We do not have a network config...
  */
-static int drbd_connect(struct drbd_conf *mdev)
+static int conn_connect(struct drbd_tconn *tconn)
 {
-	struct socket *s, *sock, *msock;
-	int try, h, ok;
+	struct drbd_socket sock, msock;
+	struct drbd_conf *mdev;
+	struct net_conf *nc;
+	int vnr, timeout, h, ok;
+	bool discard_my_data;
 	enum drbd_state_rv rv;
+	struct accept_wait_data ad = {
+		.tconn = tconn,
+		.door_bell = COMPLETION_INITIALIZER_ONSTACK(ad.door_bell),
+	};
 
-	D_ASSERT(!mdev->data.socket);
-
-	if (drbd_request_state(mdev, NS(conn, C_WF_CONNECTION)) < SS_SUCCESS)
+	clear_bit(DISCONNECT_SENT, &tconn->flags);
+	if (conn_request_state(tconn, NS(conn, C_WF_CONNECTION), CS_VERBOSE) < SS_SUCCESS)
 		return -2;
 
-	clear_bit(DISCARD_CONCURRENT, &mdev->flags);
+	mutex_init(&sock.mutex);
+	sock.sbuf = tconn->data.sbuf;
+	sock.rbuf = tconn->data.rbuf;
+	sock.socket = NULL;
+	mutex_init(&msock.mutex);
+	msock.sbuf = tconn->meta.sbuf;
+	msock.rbuf = tconn->meta.rbuf;
+	msock.socket = NULL;
+
+	/* Assume that the peer only understands protocol 80 until we know better.  */
+	tconn->agreed_pro_version = 80;
 
-	sock  = NULL;
-	msock = NULL;
+	if (prepare_listen_socket(tconn, &ad))
+		return 0;
 
 	do {
-		for (try = 0;;) {
-			/* 3 tries, this should take less than a second! */
-			s = drbd_try_connect(mdev);
-			if (s || ++try >= 3)
-				break;
-			/* give the other side time to call bind() & listen() */
-			schedule_timeout_interruptible(HZ / 10);
-		}
+		struct socket *s;
 
+		s = drbd_try_connect(tconn);
 		if (s) {
-			if (!sock) {
-				drbd_send_fp(mdev, s, P_HAND_SHAKE_S);
-				sock = s;
-				s = NULL;
-			} else if (!msock) {
-				drbd_send_fp(mdev, s, P_HAND_SHAKE_M);
-				msock = s;
-				s = NULL;
+			if (!sock.socket) {
+				sock.socket = s;
+				send_first_packet(tconn, &sock, P_INITIAL_DATA);
+			} else if (!msock.socket) {
+				clear_bit(RESOLVE_CONFLICTS, &tconn->flags);
+				msock.socket = s;
+				send_first_packet(tconn, &msock, P_INITIAL_META);
 			} else {
-				dev_err(DEV, "Logic error in drbd_connect()\n");
+				conn_err(tconn, "Logic error in conn_connect()\n");
 				goto out_release_sockets;
 			}
 		}
 
-		if (sock && msock) {
-			schedule_timeout_interruptible(mdev->net_conf->ping_timeo*HZ/10);
-			ok = drbd_socket_okay(mdev, &sock);
-			ok = drbd_socket_okay(mdev, &msock) && ok;
+		if (sock.socket && msock.socket) {
+			rcu_read_lock();
+			nc = rcu_dereference(tconn->net_conf);
+			timeout = nc->ping_timeo * HZ / 10;
+			rcu_read_unlock();
+			schedule_timeout_interruptible(timeout);
+			ok = drbd_socket_okay(&sock.socket);
+			ok = drbd_socket_okay(&msock.socket) && ok;
 			if (ok)
 				break;
 		}
 
 retry:
-		s = drbd_wait_for_connect(mdev);
+		s = drbd_wait_for_connect(tconn, &ad);
 		if (s) {
-			try = drbd_recv_fp(mdev, s);
-			drbd_socket_okay(mdev, &sock);
-			drbd_socket_okay(mdev, &msock);
-			switch (try) {
-			case P_HAND_SHAKE_S:
-				if (sock) {
-					dev_warn(DEV, "initial packet S crossed\n");
-					sock_release(sock);
+			int fp = receive_first_packet(tconn, s);
+			drbd_socket_okay(&sock.socket);
+			drbd_socket_okay(&msock.socket);
+			switch (fp) {
+			case P_INITIAL_DATA:
+				if (sock.socket) {
+					conn_warn(tconn, "initial packet S crossed\n");
+					sock_release(sock.socket);
+					sock.socket = s;
+					goto randomize;
 				}
-				sock = s;
+				sock.socket = s;
 				break;
-			case P_HAND_SHAKE_M:
-				if (msock) {
-					dev_warn(DEV, "initial packet M crossed\n");
-					sock_release(msock);
+			case P_INITIAL_META:
+				set_bit(RESOLVE_CONFLICTS, &tconn->flags);
+				if (msock.socket) {
+					conn_warn(tconn, "initial packet M crossed\n");
+					sock_release(msock.socket);
+					msock.socket = s;
+					goto randomize;
 				}
-				msock = s;
-				set_bit(DISCARD_CONCURRENT, &mdev->flags);
+				msock.socket = s;
 				break;
 			default:
-				dev_warn(DEV, "Error receiving initial packet\n");
+				conn_warn(tconn, "Error receiving initial packet\n");
 				sock_release(s);
+randomize:
 				if (random32() & 1)
 					goto retry;
 			}
 		}
 
-		if (mdev->state.conn <= C_DISCONNECTING)
+		if (tconn->cstate <= C_DISCONNECTING)
 			goto out_release_sockets;
 		if (signal_pending(current)) {
 			flush_signals(current);
 			smp_rmb();
-			if (get_t_state(&mdev->receiver) == Exiting)
+			if (get_t_state(&tconn->receiver) == EXITING)
 				goto out_release_sockets;
 		}
 
-		if (sock && msock) {
-			ok = drbd_socket_okay(mdev, &sock);
-			ok = drbd_socket_okay(mdev, &msock) && ok;
-			if (ok)
-				break;
-		}
-	} while (1);
+		ok = drbd_socket_okay(&sock.socket);
+		ok = drbd_socket_okay(&msock.socket) && ok;
+	} while (!ok);
+
+	if (ad.s_listen)
+		sock_release(ad.s_listen);
 
-	msock->sk->sk_reuse = SK_CAN_REUSE; /* SO_REUSEADDR */
-	sock->sk->sk_reuse = SK_CAN_REUSE; /* SO_REUSEADDR */
+	sock.socket->sk->sk_reuse = SK_CAN_REUSE; /* SO_REUSEADDR */
+	msock.socket->sk->sk_reuse = SK_CAN_REUSE; /* SO_REUSEADDR */
 
-	sock->sk->sk_allocation = GFP_NOIO;
-	msock->sk->sk_allocation = GFP_NOIO;
+	sock.socket->sk->sk_allocation = GFP_NOIO;
+	msock.socket->sk->sk_allocation = GFP_NOIO;
 
-	sock->sk->sk_priority = TC_PRIO_INTERACTIVE_BULK;
-	msock->sk->sk_priority = TC_PRIO_INTERACTIVE;
+	sock.socket->sk->sk_priority = TC_PRIO_INTERACTIVE_BULK;
+	msock.socket->sk->sk_priority = TC_PRIO_INTERACTIVE;
 
 	/* NOT YET ...
-	 * sock->sk->sk_sndtimeo = mdev->net_conf->timeout*HZ/10;
-	 * sock->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
-	 * first set it to the P_HAND_SHAKE timeout,
+	 * sock.socket->sk->sk_sndtimeo = tconn->net_conf->timeout*HZ/10;
+	 * sock.socket->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
+	 * first set it to the P_CONNECTION_FEATURES timeout,
 	 * which we set to 4x the configured ping_timeout. */
-	sock->sk->sk_sndtimeo =
-	sock->sk->sk_rcvtimeo = mdev->net_conf->ping_timeo*4*HZ/10;
+	rcu_read_lock();
+	nc = rcu_dereference(tconn->net_conf);
 
-	msock->sk->sk_sndtimeo = mdev->net_conf->timeout*HZ/10;
-	msock->sk->sk_rcvtimeo = mdev->net_conf->ping_int*HZ;
+	sock.socket->sk->sk_sndtimeo =
+	sock.socket->sk->sk_rcvtimeo = nc->ping_timeo*4*HZ/10;
+
+	msock.socket->sk->sk_rcvtimeo = nc->ping_int*HZ;
+	timeout = nc->timeout * HZ / 10;
+	discard_my_data = nc->discard_my_data;
+	rcu_read_unlock();
+
+	msock.socket->sk->sk_sndtimeo = timeout;
 
 	/* we don't want delays.
 	 * we use TCP_CORK where appropriate, though */
-	drbd_tcp_nodelay(sock);
-	drbd_tcp_nodelay(msock);
+	drbd_tcp_nodelay(sock.socket);
+	drbd_tcp_nodelay(msock.socket);
 
-	mdev->data.socket = sock;
-	mdev->meta.socket = msock;
-	mdev->last_received = jiffies;
+	tconn->data.socket = sock.socket;
+	tconn->meta.socket = msock.socket;
+	tconn->last_received = jiffies;
 
-	D_ASSERT(mdev->asender.task == NULL);
-
-	h = drbd_do_handshake(mdev);
+	h = drbd_do_features(tconn);
 	if (h <= 0)
 		return h;
 
-	if (mdev->cram_hmac_tfm) {
+	if (tconn->cram_hmac_tfm) {
 		/* drbd_request_state(mdev, NS(conn, WFAuth)); */
-		switch (drbd_do_auth(mdev)) {
+		switch (drbd_do_auth(tconn)) {
 		case -1:
-			dev_err(DEV, "Authentication of peer failed\n");
+			conn_err(tconn, "Authentication of peer failed\n");
 			return -1;
 		case 0:
-			dev_err(DEV, "Authentication of peer failed, trying again.\n");
+			conn_err(tconn, "Authentication of peer failed, trying again.\n");
 			return 0;
 		}
 	}
 
-	sock->sk->sk_sndtimeo = mdev->net_conf->timeout*HZ/10;
-	sock->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
+	tconn->data.socket->sk->sk_sndtimeo = timeout;
+	tconn->data.socket->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
 
-	atomic_set(&mdev->packet_seq, 0);
-	mdev->peer_seq = 0;
-
-	if (drbd_send_protocol(mdev) == -1)
+	if (drbd_send_protocol(tconn) == -EOPNOTSUPP)
 		return -1;
-	set_bit(STATE_SENT, &mdev->flags);
-	drbd_send_sync_param(mdev, &mdev->sync_conf);
-	drbd_send_sizes(mdev, 0, 0);
-	drbd_send_uuids(mdev);
-	drbd_send_current_state(mdev);
-	clear_bit(USE_DEGR_WFC_T, &mdev->flags);
-	clear_bit(RESIZE_PENDING, &mdev->flags);
 
-	spin_lock_irq(&mdev->req_lock);
-	rv = _drbd_set_state(_NS(mdev, conn, C_WF_REPORT_PARAMS), CS_VERBOSE, NULL);
-	if (mdev->state.conn != C_WF_REPORT_PARAMS)
-		clear_bit(STATE_SENT, &mdev->flags);
-	spin_unlock_irq(&mdev->req_lock);
+	set_bit(STATE_SENT, &tconn->flags);
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+		kref_get(&mdev->kref);
+		rcu_read_unlock();
 
-	if (rv < SS_SUCCESS)
+		if (discard_my_data)
+			set_bit(DISCARD_MY_DATA, &mdev->flags);
+		else
+			clear_bit(DISCARD_MY_DATA, &mdev->flags);
+
+		drbd_connected(mdev);
+		kref_put(&mdev->kref, &drbd_minor_destroy);
+		rcu_read_lock();
+	}
+	rcu_read_unlock();
+
+	rv = conn_request_state(tconn, NS(conn, C_WF_REPORT_PARAMS), CS_VERBOSE);
+	if (rv < SS_SUCCESS || tconn->cstate != C_WF_REPORT_PARAMS) {
+		clear_bit(STATE_SENT, &tconn->flags);
 		return 0;
+	}
 
-	drbd_thread_start(&mdev->asender);
-	mod_timer(&mdev->request_timer, jiffies + HZ); /* just start it here. */
+	drbd_thread_start(&tconn->asender);
 
-	return 1;
+	mutex_lock(&tconn->conf_update);
+	/* The discard_my_data flag is a single-shot modifier to the next
+	 * connection attempt, the handshake of which is now well underway.
+	 * No need for rcu style copying of the whole struct
+	 * just to clear a single value. */
+	tconn->net_conf->discard_my_data = 0;
+	mutex_unlock(&tconn->conf_update);
+
+	return h;
 
 out_release_sockets:
-	if (sock)
-		sock_release(sock);
-	if (msock)
-		sock_release(msock);
+	if (ad.s_listen)
+		sock_release(ad.s_listen);
+	if (sock.socket)
+		sock_release(sock.socket);
+	if (msock.socket)
+		sock_release(msock.socket);
 	return -1;
 }
 
-static int drbd_recv_header(struct drbd_conf *mdev, enum drbd_packets *cmd, unsigned int *packet_size)
+static int decode_header(struct drbd_tconn *tconn, void *header, struct packet_info *pi)
 {
-	union p_header *h = &mdev->data.rbuf.header;
-	int r;
-
-	r = drbd_recv(mdev, h, sizeof(*h));
-	if (unlikely(r != sizeof(*h))) {
-		if (!signal_pending(current))
-			dev_warn(DEV, "short read expecting header on sock: r=%d\n", r);
-		return false;
-	}
-
-	if (likely(h->h80.magic == BE_DRBD_MAGIC)) {
-		*cmd = be16_to_cpu(h->h80.command);
-		*packet_size = be16_to_cpu(h->h80.length);
-	} else if (h->h95.magic == BE_DRBD_MAGIC_BIG) {
-		*cmd = be16_to_cpu(h->h95.command);
-		*packet_size = be32_to_cpu(h->h95.length);
+	unsigned int header_size = drbd_header_size(tconn);
+
+	if (header_size == sizeof(struct p_header100) &&
+	    *(__be32 *)header == cpu_to_be32(DRBD_MAGIC_100)) {
+		struct p_header100 *h = header;
+		if (h->pad != 0) {
+			conn_err(tconn, "Header padding is not zero\n");
+			return -EINVAL;
+		}
+		pi->vnr = be16_to_cpu(h->volume);
+		pi->cmd = be16_to_cpu(h->command);
+		pi->size = be32_to_cpu(h->length);
+	} else if (header_size == sizeof(struct p_header95) &&
+		   *(__be16 *)header == cpu_to_be16(DRBD_MAGIC_BIG)) {
+		struct p_header95 *h = header;
+		pi->cmd = be16_to_cpu(h->command);
+		pi->size = be32_to_cpu(h->length);
+		pi->vnr = 0;
+	} else if (header_size == sizeof(struct p_header80) &&
+		   *(__be32 *)header == cpu_to_be32(DRBD_MAGIC)) {
+		struct p_header80 *h = header;
+		pi->cmd = be16_to_cpu(h->command);
+		pi->size = be16_to_cpu(h->length);
+		pi->vnr = 0;
 	} else {
-		dev_err(DEV, "magic?? on data m: 0x%08x c: %d l: %d\n",
-		    be32_to_cpu(h->h80.magic),
-		    be16_to_cpu(h->h80.command),
-		    be16_to_cpu(h->h80.length));
-		return false;
+		conn_err(tconn, "Wrong magic value 0x%08x in protocol version %d\n",
+			 be32_to_cpu(*(__be32 *)header),
+			 tconn->agreed_pro_version);
+		return -EINVAL;
 	}
-	mdev->last_received = jiffies;
+	pi->data = header + header_size;
+	return 0;
+}
+
+static int drbd_recv_header(struct drbd_tconn *tconn, struct packet_info *pi)
+{
+	void *buffer = tconn->data.rbuf;
+	int err;
+
+	err = drbd_recv_all_warn(tconn, buffer, drbd_header_size(tconn));
+	if (err)
+		return err;
+
+	err = decode_header(tconn, buffer, pi);
+	tconn->last_received = jiffies;
 
-	return true;
+	return err;
 }
 
-static void drbd_flush(struct drbd_conf *mdev)
+static void drbd_flush(struct drbd_tconn *tconn)
 {
 	int rv;
+	struct drbd_conf *mdev;
+	int vnr;
 
-	if (mdev->write_ordering >= WO_bdev_flush && get_ldev(mdev)) {
-		rv = blkdev_issue_flush(mdev->ldev->backing_bdev, GFP_KERNEL,
-					NULL);
-		if (rv) {
-			dev_info(DEV, "local disk flush failed with status %d\n", rv);
-			/* would rather check on EOPNOTSUPP, but that is not reliable.
-			 * don't try again for ANY return value != 0
-			 * if (rv == -EOPNOTSUPP) */
-			drbd_bump_write_ordering(mdev, WO_drain_io);
+	if (tconn->write_ordering >= WO_bdev_flush) {
+		rcu_read_lock();
+		idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+			if (!get_ldev(mdev))
+				continue;
+			kref_get(&mdev->kref);
+			rcu_read_unlock();
+
+			rv = blkdev_issue_flush(mdev->ldev->backing_bdev,
+					GFP_NOIO, NULL);
+			if (rv) {
+				dev_info(DEV, "local disk flush failed with status %d\n", rv);
+				/* would rather check on EOPNOTSUPP, but that is not reliable.
+				 * don't try again for ANY return value != 0
+				 * if (rv == -EOPNOTSUPP) */
+				drbd_bump_write_ordering(tconn, WO_drain_io);
+			}
+			put_ldev(mdev);
+			kref_put(&mdev->kref, &drbd_minor_destroy);
+
+			rcu_read_lock();
+			if (rv)
+				break;
 		}
-		put_ldev(mdev);
+		rcu_read_unlock();
 	}
 }
 
@@ -987,7 +1169,7 @@ static void drbd_flush(struct drbd_conf *mdev)
  * @epoch:	Epoch object.
  * @ev:		Epoch event.
  */
-static enum finish_epoch drbd_may_finish_epoch(struct drbd_conf *mdev,
+static enum finish_epoch drbd_may_finish_epoch(struct drbd_tconn *tconn,
 					       struct drbd_epoch *epoch,
 					       enum epoch_event ev)
 {
@@ -995,7 +1177,7 @@ static enum finish_epoch drbd_may_finish_epoch(struct drbd_conf *mdev,
 	struct drbd_epoch *next_epoch;
 	enum finish_epoch rv = FE_STILL_LIVE;
 
-	spin_lock(&mdev->epoch_lock);
+	spin_lock(&tconn->epoch_lock);
 	do {
 		next_epoch = NULL;
 
@@ -1017,18 +1199,22 @@ static enum finish_epoch drbd_may_finish_epoch(struct drbd_conf *mdev,
 		    atomic_read(&epoch->active) == 0 &&
 		    (test_bit(DE_HAVE_BARRIER_NUMBER, &epoch->flags) || ev & EV_CLEANUP)) {
 			if (!(ev & EV_CLEANUP)) {
-				spin_unlock(&mdev->epoch_lock);
-				drbd_send_b_ack(mdev, epoch->barrier_nr, epoch_size);
-				spin_lock(&mdev->epoch_lock);
+				spin_unlock(&tconn->epoch_lock);
+				drbd_send_b_ack(epoch->tconn, epoch->barrier_nr, epoch_size);
+				spin_lock(&tconn->epoch_lock);
 			}
+#if 0
+			/* FIXME: dec unacked on connection, once we have
+			 * something to count pending connection packets in. */
 			if (test_bit(DE_HAVE_BARRIER_NUMBER, &epoch->flags))
-				dec_unacked(mdev);
+				dec_unacked(epoch->tconn);
+#endif
 
-			if (mdev->current_epoch != epoch) {
+			if (tconn->current_epoch != epoch) {
 				next_epoch = list_entry(epoch->list.next, struct drbd_epoch, list);
 				list_del(&epoch->list);
 				ev = EV_BECAME_LAST | (ev & EV_CLEANUP);
-				mdev->epochs--;
+				tconn->epochs--;
 				kfree(epoch);
 
 				if (rv == FE_STILL_LIVE)
@@ -1039,7 +1225,6 @@ static enum finish_epoch drbd_may_finish_epoch(struct drbd_conf *mdev,
 				/* atomic_set(&epoch->active, 0); is already zero */
 				if (rv == FE_STILL_LIVE)
 					rv = FE_RECYCLED;
-				wake_up(&mdev->ee_wait);
 			}
 		}
 
@@ -1049,40 +1234,52 @@ static enum finish_epoch drbd_may_finish_epoch(struct drbd_conf *mdev,
 		epoch = next_epoch;
 	} while (1);
 
-	spin_unlock(&mdev->epoch_lock);
+	spin_unlock(&tconn->epoch_lock);
 
 	return rv;
 }
 
 /**
  * drbd_bump_write_ordering() - Fall back to an other write ordering method
- * @mdev:	DRBD device.
+ * @tconn:	DRBD connection.
  * @wo:		Write ordering method to try.
  */
-void drbd_bump_write_ordering(struct drbd_conf *mdev, enum write_ordering_e wo) __must_hold(local)
+void drbd_bump_write_ordering(struct drbd_tconn *tconn, enum write_ordering_e wo)
 {
+	struct disk_conf *dc;
+	struct drbd_conf *mdev;
 	enum write_ordering_e pwo;
+	int vnr;
 	static char *write_ordering_str[] = {
 		[WO_none] = "none",
 		[WO_drain_io] = "drain",
 		[WO_bdev_flush] = "flush",
 	};
 
-	pwo = mdev->write_ordering;
+	pwo = tconn->write_ordering;
 	wo = min(pwo, wo);
-	if (wo == WO_bdev_flush && mdev->ldev->dc.no_disk_flush)
-		wo = WO_drain_io;
-	if (wo == WO_drain_io && mdev->ldev->dc.no_disk_drain)
-		wo = WO_none;
-	mdev->write_ordering = wo;
-	if (pwo != mdev->write_ordering || wo == WO_bdev_flush)
-		dev_info(DEV, "Method to ensure write ordering: %s\n", write_ordering_str[mdev->write_ordering]);
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+		if (!get_ldev_if_state(mdev, D_ATTACHING))
+			continue;
+		dc = rcu_dereference(mdev->ldev->disk_conf);
+
+		if (wo == WO_bdev_flush && !dc->disk_flushes)
+			wo = WO_drain_io;
+		if (wo == WO_drain_io && !dc->disk_drain)
+			wo = WO_none;
+		put_ldev(mdev);
+	}
+	rcu_read_unlock();
+	tconn->write_ordering = wo;
+	if (pwo != tconn->write_ordering || wo == WO_bdev_flush)
+		conn_info(tconn, "Method to ensure write ordering: %s\n", write_ordering_str[tconn->write_ordering]);
 }
 
 /**
- * drbd_submit_ee()
+ * drbd_submit_peer_request()
  * @mdev:	DRBD device.
- * @e:		epoch entry
+ * @peer_req:	peer request
  * @rw:		flag field, see bio->bi_rw
  *
  * May spread the pages to multiple bios,
@@ -1096,14 +1293,15 @@ void drbd_bump_write_ordering(struct drbd_conf *mdev, enum write_ordering_e wo)
  *  on certain Xen deployments.
  */
 /* TODO allocate from our own bio_set. */
-int drbd_submit_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
-		const unsigned rw, const int fault_type)
+int drbd_submit_peer_request(struct drbd_conf *mdev,
+			     struct drbd_peer_request *peer_req,
+			     const unsigned rw, const int fault_type)
 {
 	struct bio *bios = NULL;
 	struct bio *bio;
-	struct page *page = e->pages;
-	sector_t sector = e->sector;
-	unsigned ds = e->size;
+	struct page *page = peer_req->pages;
+	sector_t sector = peer_req->i.sector;
+	unsigned ds = peer_req->i.size;
 	unsigned n_bios = 0;
 	unsigned nr_pages = (ds + PAGE_SIZE -1) >> PAGE_SHIFT;
 	int err = -ENOMEM;
@@ -1122,12 +1320,12 @@ next_bio:
 		dev_err(DEV, "submit_ee: Allocation of a bio failed\n");
 		goto fail;
 	}
-	/* > e->sector, unless this is the first bio */
+	/* > peer_req->i.sector, unless this is the first bio */
 	bio->bi_sector = sector;
 	bio->bi_bdev = mdev->ldev->backing_bdev;
 	bio->bi_rw = rw;
-	bio->bi_private = e;
-	bio->bi_end_io = drbd_endio_sec;
+	bio->bi_private = peer_req;
+	bio->bi_end_io = drbd_peer_request_endio;
 
 	bio->bi_next = bios;
 	bios = bio;
@@ -1156,7 +1354,7 @@ next_bio:
 	D_ASSERT(page == NULL);
 	D_ASSERT(ds == 0);
 
-	atomic_set(&e->pending_bios, n_bios);
+	atomic_set(&peer_req->pending_bios, n_bios);
 	do {
 		bio = bios;
 		bios = bios->bi_next;
@@ -1175,26 +1373,57 @@ fail:
 	return err;
 }
 
-static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
+static void drbd_remove_epoch_entry_interval(struct drbd_conf *mdev,
+					     struct drbd_peer_request *peer_req)
+{
+	struct drbd_interval *i = &peer_req->i;
+
+	drbd_remove_interval(&mdev->write_requests, i);
+	drbd_clear_interval(i);
+
+	/* Wake up any processes waiting for this peer request to complete.  */
+	if (i->waiting)
+		wake_up(&mdev->misc_wait);
+}
+
+void conn_wait_active_ee_empty(struct drbd_tconn *tconn)
+{
+	struct drbd_conf *mdev;
+	int vnr;
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+		kref_get(&mdev->kref);
+		rcu_read_unlock();
+		drbd_wait_ee_list_empty(mdev, &mdev->active_ee);
+		kref_put(&mdev->kref, &drbd_minor_destroy);
+		rcu_read_lock();
+	}
+	rcu_read_unlock();
+}
+
+static int receive_Barrier(struct drbd_tconn *tconn, struct packet_info *pi)
 {
 	int rv;
-	struct p_barrier *p = &mdev->data.rbuf.barrier;
+	struct p_barrier *p = pi->data;
 	struct drbd_epoch *epoch;
 
-	inc_unacked(mdev);
-
-	mdev->current_epoch->barrier_nr = p->barrier;
-	rv = drbd_may_finish_epoch(mdev, mdev->current_epoch, EV_GOT_BARRIER_NR);
+	/* FIXME these are unacked on connection,
+	 * not a specific (peer)device.
+	 */
+	tconn->current_epoch->barrier_nr = p->barrier;
+	tconn->current_epoch->tconn = tconn;
+	rv = drbd_may_finish_epoch(tconn, tconn->current_epoch, EV_GOT_BARRIER_NR);
 
 	/* P_BARRIER_ACK may imply that the corresponding extent is dropped from
 	 * the activity log, which means it would not be resynced in case the
 	 * R_PRIMARY crashes now.
 	 * Therefore we must send the barrier_ack after the barrier request was
 	 * completed. */
-	switch (mdev->write_ordering) {
+	switch (tconn->write_ordering) {
 	case WO_none:
 		if (rv == FE_RECYCLED)
-			return true;
+			return 0;
 
 		/* receiver context, in the writeout path of the other node.
 		 * avoid potential distributed deadlock */
@@ -1202,81 +1431,75 @@ static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packets cmd, unsign
 		if (epoch)
 			break;
 		else
-			dev_warn(DEV, "Allocation of an epoch failed, slowing down\n");
+			conn_warn(tconn, "Allocation of an epoch failed, slowing down\n");
 			/* Fall through */
 
 	case WO_bdev_flush:
 	case WO_drain_io:
-		drbd_wait_ee_list_empty(mdev, &mdev->active_ee);
-		drbd_flush(mdev);
+		conn_wait_active_ee_empty(tconn);
+		drbd_flush(tconn);
 
-		if (atomic_read(&mdev->current_epoch->epoch_size)) {
+		if (atomic_read(&tconn->current_epoch->epoch_size)) {
 			epoch = kmalloc(sizeof(struct drbd_epoch), GFP_NOIO);
 			if (epoch)
 				break;
 		}
 
-		epoch = mdev->current_epoch;
-		wait_event(mdev->ee_wait, atomic_read(&epoch->epoch_size) == 0);
-
-		D_ASSERT(atomic_read(&epoch->active) == 0);
-		D_ASSERT(epoch->flags == 0);
-
-		return true;
+		return 0;
 	default:
-		dev_err(DEV, "Strangeness in mdev->write_ordering %d\n", mdev->write_ordering);
-		return false;
+		conn_err(tconn, "Strangeness in tconn->write_ordering %d\n", tconn->write_ordering);
+		return -EIO;
 	}
 
 	epoch->flags = 0;
 	atomic_set(&epoch->epoch_size, 0);
 	atomic_set(&epoch->active, 0);
 
-	spin_lock(&mdev->epoch_lock);
-	if (atomic_read(&mdev->current_epoch->epoch_size)) {
-		list_add(&epoch->list, &mdev->current_epoch->list);
-		mdev->current_epoch = epoch;
-		mdev->epochs++;
+	spin_lock(&tconn->epoch_lock);
+	if (atomic_read(&tconn->current_epoch->epoch_size)) {
+		list_add(&epoch->list, &tconn->current_epoch->list);
+		tconn->current_epoch = epoch;
+		tconn->epochs++;
 	} else {
 		/* The current_epoch got recycled while we allocated this one... */
 		kfree(epoch);
 	}
-	spin_unlock(&mdev->epoch_lock);
+	spin_unlock(&tconn->epoch_lock);
 
-	return true;
+	return 0;
 }
 
 /* used from receive_RSDataReply (recv_resync_read)
  * and from receive_Data */
-static struct drbd_epoch_entry *
-read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __must_hold(local)
+static struct drbd_peer_request *
+read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector,
+	      int data_size) __must_hold(local)
 {
 	const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
-	struct drbd_epoch_entry *e;
+	struct drbd_peer_request *peer_req;
 	struct page *page;
-	int dgs, ds, rr;
-	void *dig_in = mdev->int_dig_in;
-	void *dig_vv = mdev->int_dig_vv;
+	int dgs, ds, err;
+	void *dig_in = mdev->tconn->int_dig_in;
+	void *dig_vv = mdev->tconn->int_dig_vv;
 	unsigned long *data;
 
-	dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_r_tfm) ?
-		crypto_hash_digestsize(mdev->integrity_r_tfm) : 0;
-
-	if (dgs) {
-		rr = drbd_recv(mdev, dig_in, dgs);
-		if (rr != dgs) {
-			if (!signal_pending(current))
-				dev_warn(DEV,
-					"short read receiving data digest: read %d expected %d\n",
-					rr, dgs);
+	dgs = 0;
+	if (mdev->tconn->peer_integrity_tfm) {
+		dgs = crypto_hash_digestsize(mdev->tconn->peer_integrity_tfm);
+		/*
+		 * FIXME: Receive the incoming digest into the receive buffer
+		 *	  here, together with its struct p_data?
+		 */
+		err = drbd_recv_all_warn(mdev->tconn, dig_in, dgs);
+		if (err)
 			return NULL;
-		}
+		data_size -= dgs;
 	}
 
-	data_size -= dgs;
-
-	ERR_IF(data_size &  0x1ff) return NULL;
-	ERR_IF(data_size >  DRBD_MAX_BIO_SIZE) return NULL;
+	if (!expect(IS_ALIGNED(data_size, 512)))
+		return NULL;
+	if (!expect(data_size <= DRBD_MAX_BIO_SIZE))
+		return NULL;
 
 	/* even though we trust out peer,
 	 * we sometimes have to double check. */
@@ -1291,47 +1514,42 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __
 	/* GFP_NOIO, because we must not cause arbitrary write-out: in a DRBD
 	 * "criss-cross" setup, that might cause write-out on some other DRBD,
 	 * which in turn might block on the other node at this very place.  */
-	e = drbd_alloc_ee(mdev, id, sector, data_size, GFP_NOIO);
-	if (!e)
+	peer_req = drbd_alloc_peer_req(mdev, id, sector, data_size, GFP_NOIO);
+	if (!peer_req)
 		return NULL;
 
 	if (!data_size)
-		return e;
+		return peer_req;
 
 	ds = data_size;
-	page = e->pages;
+	page = peer_req->pages;
 	page_chain_for_each(page) {
 		unsigned len = min_t(int, ds, PAGE_SIZE);
 		data = kmap(page);
-		rr = drbd_recv(mdev, data, len);
+		err = drbd_recv_all_warn(mdev->tconn, data, len);
 		if (drbd_insert_fault(mdev, DRBD_FAULT_RECEIVE)) {
 			dev_err(DEV, "Fault injection: Corrupting data on receive\n");
 			data[0] = data[0] ^ (unsigned long)-1;
 		}
 		kunmap(page);
-		if (rr != len) {
-			drbd_free_ee(mdev, e);
-			if (!signal_pending(current))
-				dev_warn(DEV, "short read receiving data: read %d expected %d\n",
-				rr, len);
+		if (err) {
+			drbd_free_peer_req(mdev, peer_req);
 			return NULL;
 		}
-		ds -= rr;
+		ds -= len;
 	}
 
 	if (dgs) {
-		drbd_csum_ee(mdev, mdev->integrity_r_tfm, e, dig_vv);
+		drbd_csum_ee(mdev, mdev->tconn->peer_integrity_tfm, peer_req, dig_vv);
 		if (memcmp(dig_in, dig_vv, dgs)) {
 			dev_err(DEV, "Digest integrity check FAILED: %llus +%u\n",
 				(unsigned long long)sector, data_size);
-			drbd_bcast_ee(mdev, "digest failed",
-					dgs, dig_in, dig_vv, e);
-			drbd_free_ee(mdev, e);
+			drbd_free_peer_req(mdev, peer_req);
 			return NULL;
 		}
 	}
 	mdev->recv_cnt += data_size>>9;
-	return e;
+	return peer_req;
 }
 
 /* drbd_drain_block() just takes a data block
@@ -1340,30 +1558,26 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __
 static int drbd_drain_block(struct drbd_conf *mdev, int data_size)
 {
 	struct page *page;
-	int rr, rv = 1;
+	int err = 0;
 	void *data;
 
 	if (!data_size)
-		return true;
+		return 0;
 
-	page = drbd_pp_alloc(mdev, 1, 1);
+	page = drbd_alloc_pages(mdev, 1, 1);
 
 	data = kmap(page);
 	while (data_size) {
-		rr = drbd_recv(mdev, data, min_t(int, data_size, PAGE_SIZE));
-		if (rr != min_t(int, data_size, PAGE_SIZE)) {
-			rv = 0;
-			if (!signal_pending(current))
-				dev_warn(DEV,
-					"short read receiving data: read %d expected %d\n",
-					rr, min_t(int, data_size, PAGE_SIZE));
+		unsigned int len = min_t(int, data_size, PAGE_SIZE);
+
+		err = drbd_recv_all_warn(mdev->tconn, data, len);
+		if (err)
 			break;
-		}
-		data_size -= rr;
+		data_size -= len;
 	}
 	kunmap(page);
-	drbd_pp_free(mdev, page, 0);
-	return rv;
+	drbd_free_pages(mdev, page, 0);
+	return err;
 }
 
 static int recv_dless_read(struct drbd_conf *mdev, struct drbd_request *req,
@@ -1371,26 +1585,19 @@ static int recv_dless_read(struct drbd_conf *mdev, struct drbd_request *req,
 {
 	struct bio_vec *bvec;
 	struct bio *bio;
-	int dgs, rr, i, expect;
-	void *dig_in = mdev->int_dig_in;
-	void *dig_vv = mdev->int_dig_vv;
-
-	dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_r_tfm) ?
-		crypto_hash_digestsize(mdev->integrity_r_tfm) : 0;
+	int dgs, err, i, expect;
+	void *dig_in = mdev->tconn->int_dig_in;
+	void *dig_vv = mdev->tconn->int_dig_vv;
 
-	if (dgs) {
-		rr = drbd_recv(mdev, dig_in, dgs);
-		if (rr != dgs) {
-			if (!signal_pending(current))
-				dev_warn(DEV,
-					"short read receiving data reply digest: read %d expected %d\n",
-					rr, dgs);
-			return 0;
-		}
+	dgs = 0;
+	if (mdev->tconn->peer_integrity_tfm) {
+		dgs = crypto_hash_digestsize(mdev->tconn->peer_integrity_tfm);
+		err = drbd_recv_all_warn(mdev->tconn, dig_in, dgs);
+		if (err)
+			return err;
+		data_size -= dgs;
 	}
 
-	data_size -= dgs;
-
 	/* optimistically update recv_cnt.  if receiving fails below,
 	 * we disconnect anyways, and counters will be reset. */
 	mdev->recv_cnt += data_size>>9;
@@ -1399,63 +1606,61 @@ static int recv_dless_read(struct drbd_conf *mdev, struct drbd_request *req,
 	D_ASSERT(sector == bio->bi_sector);
 
 	bio_for_each_segment(bvec, bio, i) {
+		void *mapped = kmap(bvec->bv_page) + bvec->bv_offset;
 		expect = min_t(int, data_size, bvec->bv_len);
-		rr = drbd_recv(mdev,
-			     kmap(bvec->bv_page)+bvec->bv_offset,
-			     expect);
+		err = drbd_recv_all_warn(mdev->tconn, mapped, expect);
 		kunmap(bvec->bv_page);
-		if (rr != expect) {
-			if (!signal_pending(current))
-				dev_warn(DEV, "short read receiving data reply: "
-					"read %d expected %d\n",
-					rr, expect);
-			return 0;
-		}
-		data_size -= rr;
+		if (err)
+			return err;
+		data_size -= expect;
 	}
 
 	if (dgs) {
-		drbd_csum_bio(mdev, mdev->integrity_r_tfm, bio, dig_vv);
+		drbd_csum_bio(mdev, mdev->tconn->peer_integrity_tfm, bio, dig_vv);
 		if (memcmp(dig_in, dig_vv, dgs)) {
 			dev_err(DEV, "Digest integrity check FAILED. Broken NICs?\n");
-			return 0;
+			return -EINVAL;
 		}
 	}
 
 	D_ASSERT(data_size == 0);
-	return 1;
+	return 0;
 }
 
-/* e_end_resync_block() is called via
- * drbd_process_done_ee() by asender only */
-static int e_end_resync_block(struct drbd_conf *mdev, struct drbd_work *w, int unused)
+/*
+ * e_end_resync_block() is called in asender context via
+ * drbd_finish_peer_reqs().
+ */
+static int e_end_resync_block(struct drbd_work *w, int unused)
 {
-	struct drbd_epoch_entry *e = (struct drbd_epoch_entry *)w;
-	sector_t sector = e->sector;
-	int ok;
+	struct drbd_peer_request *peer_req =
+		container_of(w, struct drbd_peer_request, w);
+	struct drbd_conf *mdev = w->mdev;
+	sector_t sector = peer_req->i.sector;
+	int err;
 
-	D_ASSERT(hlist_unhashed(&e->collision));
+	D_ASSERT(drbd_interval_empty(&peer_req->i));
 
-	if (likely((e->flags & EE_WAS_ERROR) == 0)) {
-		drbd_set_in_sync(mdev, sector, e->size);
-		ok = drbd_send_ack(mdev, P_RS_WRITE_ACK, e);
+	if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
+		drbd_set_in_sync(mdev, sector, peer_req->i.size);
+		err = drbd_send_ack(mdev, P_RS_WRITE_ACK, peer_req);
 	} else {
 		/* Record failure to sync */
-		drbd_rs_failed_io(mdev, sector, e->size);
+		drbd_rs_failed_io(mdev, sector, peer_req->i.size);
 
-		ok  = drbd_send_ack(mdev, P_NEG_ACK, e);
+		err  = drbd_send_ack(mdev, P_NEG_ACK, peer_req);
 	}
 	dec_unacked(mdev);
 
-	return ok;
+	return err;
 }
 
 static int recv_resync_read(struct drbd_conf *mdev, sector_t sector, int data_size) __releases(local)
 {
-	struct drbd_epoch_entry *e;
+	struct drbd_peer_request *peer_req;
 
-	e = read_in_block(mdev, ID_SYNCER, sector, data_size);
-	if (!e)
+	peer_req = read_in_block(mdev, ID_SYNCER, sector, data_size);
+	if (!peer_req)
 		goto fail;
 
 	dec_rs_pending(mdev);
@@ -1464,64 +1669,88 @@ static int recv_resync_read(struct drbd_conf *mdev, sector_t sector, int data_si
 	/* corresponding dec_unacked() in e_end_resync_block()
 	 * respective _drbd_clear_done_ee */
 
-	e->w.cb = e_end_resync_block;
+	peer_req->w.cb = e_end_resync_block;
 
-	spin_lock_irq(&mdev->req_lock);
-	list_add(&e->w.list, &mdev->sync_ee);
-	spin_unlock_irq(&mdev->req_lock);
+	spin_lock_irq(&mdev->tconn->req_lock);
+	list_add(&peer_req->w.list, &mdev->sync_ee);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
 	atomic_add(data_size >> 9, &mdev->rs_sect_ev);
-	if (drbd_submit_ee(mdev, e, WRITE, DRBD_FAULT_RS_WR) == 0)
-		return true;
+	if (drbd_submit_peer_request(mdev, peer_req, WRITE, DRBD_FAULT_RS_WR) == 0)
+		return 0;
 
 	/* don't care for the reason here */
 	dev_err(DEV, "submit failed, triggering re-connect\n");
-	spin_lock_irq(&mdev->req_lock);
-	list_del(&e->w.list);
-	spin_unlock_irq(&mdev->req_lock);
+	spin_lock_irq(&mdev->tconn->req_lock);
+	list_del(&peer_req->w.list);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
-	drbd_free_ee(mdev, e);
+	drbd_free_peer_req(mdev, peer_req);
 fail:
 	put_ldev(mdev);
-	return false;
+	return -EIO;
 }
 
-static int receive_DataReply(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
+static struct drbd_request *
+find_request(struct drbd_conf *mdev, struct rb_root *root, u64 id,
+	     sector_t sector, bool missing_ok, const char *func)
 {
 	struct drbd_request *req;
+
+	/* Request object according to our peer */
+	req = (struct drbd_request *)(unsigned long)id;
+	if (drbd_contains_interval(root, sector, &req->i) && req->i.local)
+		return req;
+	if (!missing_ok) {
+		dev_err(DEV, "%s: failed to find request 0x%lx, sector %llus\n", func,
+			(unsigned long)id, (unsigned long long)sector);
+	}
+	return NULL;
+}
+
+static int receive_DataReply(struct drbd_tconn *tconn, struct packet_info *pi)
+{
+	struct drbd_conf *mdev;
+	struct drbd_request *req;
 	sector_t sector;
-	int ok;
-	struct p_data *p = &mdev->data.rbuf.data;
+	int err;
+	struct p_data *p = pi->data;
+
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return -EIO;
 
 	sector = be64_to_cpu(p->sector);
 
-	spin_lock_irq(&mdev->req_lock);
-	req = _ar_id_to_req(mdev, p->block_id, sector);
-	spin_unlock_irq(&mdev->req_lock);
-	if (unlikely(!req)) {
-		dev_err(DEV, "Got a corrupt block_id/sector pair(1).\n");
-		return false;
-	}
+	spin_lock_irq(&mdev->tconn->req_lock);
+	req = find_request(mdev, &mdev->read_requests, p->block_id, sector, false, __func__);
+	spin_unlock_irq(&mdev->tconn->req_lock);
+	if (unlikely(!req))
+		return -EIO;
 
 	/* hlist_del(&req->collision) is done in _req_may_be_done, to avoid
 	 * special casing it there for the various failure cases.
 	 * still no race with drbd_fail_pending_reads */
-	ok = recv_dless_read(mdev, req, sector, data_size);
-
-	if (ok)
-		req_mod(req, data_received);
+	err = recv_dless_read(mdev, req, sector, pi->size);
+	if (!err)
+		req_mod(req, DATA_RECEIVED);
 	/* else: nothing. handled from drbd_disconnect...
 	 * I don't think we may complete this just yet
 	 * in case we are "on-disconnect: freeze" */
 
-	return ok;
+	return err;
 }
 
-static int receive_RSDataReply(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
+static int receive_RSDataReply(struct drbd_tconn *tconn, struct packet_info *pi)
 {
+	struct drbd_conf *mdev;
 	sector_t sector;
-	int ok;
-	struct p_data *p = &mdev->data.rbuf.data;
+	int err;
+	struct p_data *p = pi->data;
+
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return -EIO;
 
 	sector = be64_to_cpu(p->sector);
 	D_ASSERT(p->block_id == ID_SYNCER);
@@ -1529,42 +1758,63 @@ static int receive_RSDataReply(struct drbd_conf *mdev, enum drbd_packets cmd, un
 	if (get_ldev(mdev)) {
 		/* data is submitted to disk within recv_resync_read.
 		 * corresponding put_ldev done below on error,
-		 * or in drbd_endio_write_sec. */
-		ok = recv_resync_read(mdev, sector, data_size);
+		 * or in drbd_peer_request_endio. */
+		err = recv_resync_read(mdev, sector, pi->size);
 	} else {
 		if (__ratelimit(&drbd_ratelimit_state))
 			dev_err(DEV, "Can not write resync data to local disk.\n");
 
-		ok = drbd_drain_block(mdev, data_size);
+		err = drbd_drain_block(mdev, pi->size);
 
-		drbd_send_ack_dp(mdev, P_NEG_ACK, p, data_size);
+		drbd_send_ack_dp(mdev, P_NEG_ACK, p, pi->size);
 	}
 
-	atomic_add(data_size >> 9, &mdev->rs_sect_in);
+	atomic_add(pi->size >> 9, &mdev->rs_sect_in);
 
-	return ok;
+	return err;
 }
 
-/* e_end_block() is called via drbd_process_done_ee().
- * this means this function only runs in the asender thread
- */
-static int e_end_block(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+static void restart_conflicting_writes(struct drbd_conf *mdev,
+				       sector_t sector, int size)
 {
-	struct drbd_epoch_entry *e = (struct drbd_epoch_entry *)w;
-	sector_t sector = e->sector;
-	int ok = 1, pcmd;
+	struct drbd_interval *i;
+	struct drbd_request *req;
+
+	drbd_for_each_overlap(i, &mdev->write_requests, sector, size) {
+		if (!i->local)
+			continue;
+		req = container_of(i, struct drbd_request, i);
+		if (req->rq_state & RQ_LOCAL_PENDING ||
+		    !(req->rq_state & RQ_POSTPONED))
+			continue;
+		/* as it is RQ_POSTPONED, this will cause it to
+		 * be queued on the retry workqueue. */
+		__req_mod(req, CONFLICT_RESOLVED, NULL);
+	}
+}
 
-	if (mdev->net_conf->wire_protocol == DRBD_PROT_C) {
-		if (likely((e->flags & EE_WAS_ERROR) == 0)) {
+/*
+ * e_end_block() is called in asender context via drbd_finish_peer_reqs().
+ */
+static int e_end_block(struct drbd_work *w, int cancel)
+{
+	struct drbd_peer_request *peer_req =
+		container_of(w, struct drbd_peer_request, w);
+	struct drbd_conf *mdev = w->mdev;
+	sector_t sector = peer_req->i.sector;
+	int err = 0, pcmd;
+
+	if (peer_req->flags & EE_SEND_WRITE_ACK) {
+		if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
 			pcmd = (mdev->state.conn >= C_SYNC_SOURCE &&
 				mdev->state.conn <= C_PAUSED_SYNC_T &&
-				e->flags & EE_MAY_SET_IN_SYNC) ?
+				peer_req->flags & EE_MAY_SET_IN_SYNC) ?
 				P_RS_WRITE_ACK : P_WRITE_ACK;
-			ok &= drbd_send_ack(mdev, pcmd, e);
+			err = drbd_send_ack(mdev, pcmd, peer_req);
 			if (pcmd == P_RS_WRITE_ACK)
-				drbd_set_in_sync(mdev, sector, e->size);
+				drbd_set_in_sync(mdev, sector, peer_req->i.size);
 		} else {
-			ok  = drbd_send_ack(mdev, P_NEG_ACK, e);
+			err = drbd_send_ack(mdev, P_NEG_ACK, peer_req);
 			/* we expect it to be marked out of sync anyways...
 			 * maybe assert this?  */
 		}
@@ -1572,52 +1822,115 @@ static int e_end_block(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
 	}
 	/* we delete from the conflict detection hash _after_ we sent out the
 	 * P_WRITE_ACK / P_NEG_ACK, to get the sequence number right.  */
-	if (mdev->net_conf->two_primaries) {
-		spin_lock_irq(&mdev->req_lock);
-		D_ASSERT(!hlist_unhashed(&e->collision));
-		hlist_del_init(&e->collision);
-		spin_unlock_irq(&mdev->req_lock);
-	} else {
-		D_ASSERT(hlist_unhashed(&e->collision));
-	}
+	if (peer_req->flags & EE_IN_INTERVAL_TREE) {
+		spin_lock_irq(&mdev->tconn->req_lock);
+		D_ASSERT(!drbd_interval_empty(&peer_req->i));
+		drbd_remove_epoch_entry_interval(mdev, peer_req);
+		if (peer_req->flags & EE_RESTART_REQUESTS)
+			restart_conflicting_writes(mdev, sector, peer_req->i.size);
+		spin_unlock_irq(&mdev->tconn->req_lock);
+	} else
+		D_ASSERT(drbd_interval_empty(&peer_req->i));
+
+	drbd_may_finish_epoch(mdev->tconn, peer_req->epoch, EV_PUT + (cancel ? EV_CLEANUP : 0));
+
+	return err;
+}
+
+static int e_send_ack(struct drbd_work *w, enum drbd_packet ack)
+{
+	struct drbd_conf *mdev = w->mdev;
+	struct drbd_peer_request *peer_req =
+		container_of(w, struct drbd_peer_request, w);
+	int err;
 
-	drbd_may_finish_epoch(mdev, e->epoch, EV_PUT + (cancel ? EV_CLEANUP : 0));
+	err = drbd_send_ack(mdev, ack, peer_req);
+	dec_unacked(mdev);
 
-	return ok;
+	return err;
+}
+
+static int e_send_superseded(struct drbd_work *w, int unused)
+{
+	return e_send_ack(w, P_SUPERSEDED);
 }
 
-static int e_send_discard_ack(struct drbd_conf *mdev, struct drbd_work *w, int unused)
+static int e_send_retry_write(struct drbd_work *w, int unused)
 {
-	struct drbd_epoch_entry *e = (struct drbd_epoch_entry *)w;
-	int ok = 1;
+	struct drbd_tconn *tconn = w->mdev->tconn;
 
-	D_ASSERT(mdev->net_conf->wire_protocol == DRBD_PROT_C);
-	ok = drbd_send_ack(mdev, P_DISCARD_ACK, e);
+	return e_send_ack(w, tconn->agreed_pro_version >= 100 ?
+			     P_RETRY_WRITE : P_SUPERSEDED);
+}
+
+static bool seq_greater(u32 a, u32 b)
+{
+	/*
+	 * We assume 32-bit wrap-around here.
+	 * For 24-bit wrap-around, we would have to shift:
+	 *  a <<= 8; b <<= 8;
+	 */
+	return (s32)a - (s32)b > 0;
+}
 
-	spin_lock_irq(&mdev->req_lock);
-	D_ASSERT(!hlist_unhashed(&e->collision));
-	hlist_del_init(&e->collision);
-	spin_unlock_irq(&mdev->req_lock);
+static u32 seq_max(u32 a, u32 b)
+{
+	return seq_greater(a, b) ? a : b;
+}
+
+static bool need_peer_seq(struct drbd_conf *mdev)
+{
+	struct drbd_tconn *tconn = mdev->tconn;
+	int tp;
+
+	/*
+	 * We only need to keep track of the last packet_seq number of our peer
+	 * if we are in dual-primary mode and we have the resolve-conflicts flag set; see
+	 * handle_write_conflicts().
+	 */
+
+	rcu_read_lock();
+	tp = rcu_dereference(mdev->tconn->net_conf)->two_primaries;
+	rcu_read_unlock();
+
+	return tp && test_bit(RESOLVE_CONFLICTS, &tconn->flags);
+}
 
-	dec_unacked(mdev);
+static void update_peer_seq(struct drbd_conf *mdev, unsigned int peer_seq)
+{
+	unsigned int newest_peer_seq;
 
-	return ok;
+	if (need_peer_seq(mdev)) {
+		spin_lock(&mdev->peer_seq_lock);
+		newest_peer_seq = seq_max(mdev->peer_seq, peer_seq);
+		mdev->peer_seq = newest_peer_seq;
+		spin_unlock(&mdev->peer_seq_lock);
+		/* wake up only if we actually changed mdev->peer_seq */
+		if (peer_seq == newest_peer_seq)
+			wake_up(&mdev->seq_wait);
+	}
 }
 
-static bool overlapping_resync_write(struct drbd_conf *mdev, struct drbd_epoch_entry *data_e)
+static inline int overlaps(sector_t s1, int l1, sector_t s2, int l2)
 {
+	return !((s1 + (l1>>9) <= s2) || (s1 >= s2 + (l2>>9)));
+}
 
-	struct drbd_epoch_entry *rs_e;
+/* maybe change sync_ee into interval trees as well? */
+static bool overlapping_resync_write(struct drbd_conf *mdev, struct drbd_peer_request *peer_req)
+{
+	struct drbd_peer_request *rs_req;
 	bool rv = 0;
 
-	spin_lock_irq(&mdev->req_lock);
-	list_for_each_entry(rs_e, &mdev->sync_ee, w.list) {
-		if (overlaps(data_e->sector, data_e->size, rs_e->sector, rs_e->size)) {
+	spin_lock_irq(&mdev->tconn->req_lock);
+	list_for_each_entry(rs_req, &mdev->sync_ee, w.list) {
+		if (overlaps(peer_req->i.sector, peer_req->i.size,
+			     rs_req->i.sector, rs_req->i.size)) {
 			rv = 1;
 			break;
 		}
 	}
-	spin_unlock_irq(&mdev->req_lock);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
 	return rv;
 }
@@ -1643,35 +1956,41 @@ static bool overlapping_resync_write(struct drbd_conf *mdev, struct drbd_epoch_e
  *
  * returns 0 if we may process the packet,
  * -ERESTARTSYS if we were interrupted (by disconnect signal). */
-static int drbd_wait_peer_seq(struct drbd_conf *mdev, const u32 packet_seq)
+static int wait_for_and_update_peer_seq(struct drbd_conf *mdev, const u32 peer_seq)
 {
 	DEFINE_WAIT(wait);
-	unsigned int p_seq;
 	long timeout;
-	int ret = 0;
+	int ret;
+
+	if (!need_peer_seq(mdev))
+		return 0;
+
 	spin_lock(&mdev->peer_seq_lock);
 	for (;;) {
-		prepare_to_wait(&mdev->seq_wait, &wait, TASK_INTERRUPTIBLE);
-		if (seq_le(packet_seq, mdev->peer_seq+1))
+		if (!seq_greater(peer_seq - 1, mdev->peer_seq)) {
+			mdev->peer_seq = seq_max(mdev->peer_seq, peer_seq);
+			ret = 0;
 			break;
+		}
 		if (signal_pending(current)) {
 			ret = -ERESTARTSYS;
 			break;
 		}
-		p_seq = mdev->peer_seq;
+		prepare_to_wait(&mdev->seq_wait, &wait, TASK_INTERRUPTIBLE);
 		spin_unlock(&mdev->peer_seq_lock);
-		timeout = schedule_timeout(30*HZ);
+		rcu_read_lock();
+		timeout = rcu_dereference(mdev->tconn->net_conf)->ping_timeo*HZ/10;
+		rcu_read_unlock();
+		timeout = schedule_timeout(timeout);
 		spin_lock(&mdev->peer_seq_lock);
-		if (timeout == 0 && p_seq == mdev->peer_seq) {
+		if (!timeout) {
 			ret = -ETIMEDOUT;
-			dev_err(DEV, "ASSERT FAILED waited 30 seconds for sequence update, forcing reconnect\n");
+			dev_err(DEV, "Timed out waiting for missing ack packets; disconnecting\n");
 			break;
 		}
 	}
-	finish_wait(&mdev->seq_wait, &wait);
-	if (mdev->peer_seq+1 == packet_seq)
-		mdev->peer_seq++;
 	spin_unlock(&mdev->peer_seq_lock);
+	finish_wait(&mdev->seq_wait, &wait);
 	return ret;
 }
 
@@ -1686,233 +2005,277 @@ static unsigned long wire_flags_to_bio(struct drbd_conf *mdev, u32 dpf)
 		(dpf & DP_DISCARD ? REQ_DISCARD : 0);
 }
 
+static void fail_postponed_requests(struct drbd_conf *mdev, sector_t sector,
+				    unsigned int size)
+{
+	struct drbd_interval *i;
+
+    repeat:
+	drbd_for_each_overlap(i, &mdev->write_requests, sector, size) {
+		struct drbd_request *req;
+		struct bio_and_error m;
+
+		if (!i->local)
+			continue;
+		req = container_of(i, struct drbd_request, i);
+		if (!(req->rq_state & RQ_POSTPONED))
+			continue;
+		req->rq_state &= ~RQ_POSTPONED;
+		__req_mod(req, NEG_ACKED, &m);
+		spin_unlock_irq(&mdev->tconn->req_lock);
+		if (m.bio)
+			complete_master_bio(mdev, &m);
+		spin_lock_irq(&mdev->tconn->req_lock);
+		goto repeat;
+	}
+}
+
+static int handle_write_conflicts(struct drbd_conf *mdev,
+				  struct drbd_peer_request *peer_req)
+{
+	struct drbd_tconn *tconn = mdev->tconn;
+	bool resolve_conflicts = test_bit(RESOLVE_CONFLICTS, &tconn->flags);
+	sector_t sector = peer_req->i.sector;
+	const unsigned int size = peer_req->i.size;
+	struct drbd_interval *i;
+	bool equal;
+	int err;
+
+	/*
+	 * Inserting the peer request into the write_requests tree will prevent
+	 * new conflicting local requests from being added.
+	 */
+	drbd_insert_interval(&mdev->write_requests, &peer_req->i);
+
+    repeat:
+	drbd_for_each_overlap(i, &mdev->write_requests, sector, size) {
+		if (i == &peer_req->i)
+			continue;
+
+		if (!i->local) {
+			/*
+			 * Our peer has sent a conflicting remote request; this
+			 * should not happen in a two-node setup.  Wait for the
+			 * earlier peer request to complete.
+			 */
+			err = drbd_wait_misc(mdev, i);
+			if (err)
+				goto out;
+			goto repeat;
+		}
+
+		equal = i->sector == sector && i->size == size;
+		if (resolve_conflicts) {
+			/*
+			 * If the peer request is fully contained within the
+			 * overlapping request, it can be considered overwritten
+			 * and thus superseded; otherwise, it will be retried
+			 * once all overlapping requests have completed.
+			 */
+			bool superseded = i->sector <= sector && i->sector +
+				       (i->size >> 9) >= sector + (size >> 9);
+
+			if (!equal)
+				dev_alert(DEV, "Concurrent writes detected: "
+					       "local=%llus +%u, remote=%llus +%u, "
+					       "assuming %s came first\n",
+					  (unsigned long long)i->sector, i->size,
+					  (unsigned long long)sector, size,
+					  superseded ? "local" : "remote");
+
+			inc_unacked(mdev);
+			peer_req->w.cb = superseded ? e_send_superseded :
+						   e_send_retry_write;
+			list_add_tail(&peer_req->w.list, &mdev->done_ee);
+			wake_asender(mdev->tconn);
+
+			err = -ENOENT;
+			goto out;
+		} else {
+			struct drbd_request *req =
+				container_of(i, struct drbd_request, i);
+
+			if (!equal)
+				dev_alert(DEV, "Concurrent writes detected: "
+					       "local=%llus +%u, remote=%llus +%u\n",
+					  (unsigned long long)i->sector, i->size,
+					  (unsigned long long)sector, size);
+
+			if (req->rq_state & RQ_LOCAL_PENDING ||
+			    !(req->rq_state & RQ_POSTPONED)) {
+				/*
+				 * Wait for the node with the discard flag to
+				 * decide if this request has been superseded
+				 * or needs to be retried.
+				 * Requests that have been superseded will
+				 * disappear from the write_requests tree.
+				 *
+				 * In addition, wait for the conflicting
+				 * request to finish locally before submitting
+				 * the conflicting peer request.
+				 */
+				err = drbd_wait_misc(mdev, &req->i);
+				if (err) {
+					_conn_request_state(mdev->tconn,
+							    NS(conn, C_TIMEOUT),
+							    CS_HARD);
+					fail_postponed_requests(mdev, sector, size);
+					goto out;
+				}
+				goto repeat;
+			}
+			/*
+			 * Remember to restart the conflicting requests after
+			 * the new peer request has completed.
+			 */
+			peer_req->flags |= EE_RESTART_REQUESTS;
+		}
+	}
+	err = 0;
+
+    out:
+	if (err)
+		drbd_remove_epoch_entry_interval(mdev, peer_req);
+	return err;
+}
+
 /* mirrored write */
-static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
+static int receive_Data(struct drbd_tconn *tconn, struct packet_info *pi)
 {
+	struct drbd_conf *mdev;
 	sector_t sector;
-	struct drbd_epoch_entry *e;
-	struct p_data *p = &mdev->data.rbuf.data;
+	struct drbd_peer_request *peer_req;
+	struct p_data *p = pi->data;
+	u32 peer_seq = be32_to_cpu(p->seq_num);
 	int rw = WRITE;
 	u32 dp_flags;
+	int err, tp;
 
-	if (!get_ldev(mdev)) {
-		spin_lock(&mdev->peer_seq_lock);
-		if (mdev->peer_seq+1 == be32_to_cpu(p->seq_num))
-			mdev->peer_seq++;
-		spin_unlock(&mdev->peer_seq_lock);
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return -EIO;
 
-		drbd_send_ack_dp(mdev, P_NEG_ACK, p, data_size);
-		atomic_inc(&mdev->current_epoch->epoch_size);
-		return drbd_drain_block(mdev, data_size);
+	if (!get_ldev(mdev)) {
+		int err2;
+
+		err = wait_for_and_update_peer_seq(mdev, peer_seq);
+		drbd_send_ack_dp(mdev, P_NEG_ACK, p, pi->size);
+		atomic_inc(&tconn->current_epoch->epoch_size);
+		err2 = drbd_drain_block(mdev, pi->size);
+		if (!err)
+			err = err2;
+		return err;
 	}
 
-	/* get_ldev(mdev) successful.
-	 * Corresponding put_ldev done either below (on various errors),
-	 * or in drbd_endio_write_sec, if we successfully submit the data at
-	 * the end of this function. */
+	/*
+	 * Corresponding put_ldev done either below (on various errors), or in
+	 * drbd_peer_request_endio, if we successfully submit the data at the
+	 * end of this function.
+	 */
 
 	sector = be64_to_cpu(p->sector);
-	e = read_in_block(mdev, p->block_id, sector, data_size);
-	if (!e) {
+	peer_req = read_in_block(mdev, p->block_id, sector, pi->size);
+	if (!peer_req) {
 		put_ldev(mdev);
-		return false;
+		return -EIO;
 	}
 
-	e->w.cb = e_end_block;
+	peer_req->w.cb = e_end_block;
 
 	dp_flags = be32_to_cpu(p->dp_flags);
 	rw |= wire_flags_to_bio(mdev, dp_flags);
-	if (e->pages == NULL) {
-		D_ASSERT(e->size == 0);
+	if (peer_req->pages == NULL) {
+		D_ASSERT(peer_req->i.size == 0);
 		D_ASSERT(dp_flags & DP_FLUSH);
 	}
 
 	if (dp_flags & DP_MAY_SET_IN_SYNC)
-		e->flags |= EE_MAY_SET_IN_SYNC;
-
-	spin_lock(&mdev->epoch_lock);
-	e->epoch = mdev->current_epoch;
-	atomic_inc(&e->epoch->epoch_size);
-	atomic_inc(&e->epoch->active);
-	spin_unlock(&mdev->epoch_lock);
-
-	/* I'm the receiver, I do hold a net_cnt reference. */
-	if (!mdev->net_conf->two_primaries) {
-		spin_lock_irq(&mdev->req_lock);
-	} else {
-		/* don't get the req_lock yet,
-		 * we may sleep in drbd_wait_peer_seq */
-		const int size = e->size;
-		const int discard = test_bit(DISCARD_CONCURRENT, &mdev->flags);
-		DEFINE_WAIT(wait);
-		struct drbd_request *i;
-		struct hlist_node *n;
-		struct hlist_head *slot;
-		int first;
-
-		D_ASSERT(mdev->net_conf->wire_protocol == DRBD_PROT_C);
-		BUG_ON(mdev->ee_hash == NULL);
-		BUG_ON(mdev->tl_hash == NULL);
-
-		/* conflict detection and handling:
-		 * 1. wait on the sequence number,
-		 *    in case this data packet overtook ACK packets.
-		 * 2. check our hash tables for conflicting requests.
-		 *    we only need to walk the tl_hash, since an ee can not
-		 *    have a conflict with an other ee: on the submitting
-		 *    node, the corresponding req had already been conflicting,
-		 *    and a conflicting req is never sent.
-		 *
-		 * Note: for two_primaries, we are protocol C,
-		 * so there cannot be any request that is DONE
-		 * but still on the transfer log.
-		 *
-		 * unconditionally add to the ee_hash.
-		 *
-		 * if no conflicting request is found:
-		 *    submit.
-		 *
-		 * if any conflicting request is found
-		 * that has not yet been acked,
-		 * AND I have the "discard concurrent writes" flag:
-		 *	 queue (via done_ee) the P_DISCARD_ACK; OUT.
-		 *
-		 * if any conflicting request is found:
-		 *	 block the receiver, waiting on misc_wait
-		 *	 until no more conflicting requests are there,
-		 *	 or we get interrupted (disconnect).
-		 *
-		 *	 we do not just write after local io completion of those
-		 *	 requests, but only after req is done completely, i.e.
-		 *	 we wait for the P_DISCARD_ACK to arrive!
-		 *
-		 *	 then proceed normally, i.e. submit.
-		 */
-		if (drbd_wait_peer_seq(mdev, be32_to_cpu(p->seq_num)))
+		peer_req->flags |= EE_MAY_SET_IN_SYNC;
+
+	spin_lock(&tconn->epoch_lock);
+	peer_req->epoch = tconn->current_epoch;
+	atomic_inc(&peer_req->epoch->epoch_size);
+	atomic_inc(&peer_req->epoch->active);
+	spin_unlock(&tconn->epoch_lock);
+
+	rcu_read_lock();
+	tp = rcu_dereference(mdev->tconn->net_conf)->two_primaries;
+	rcu_read_unlock();
+	if (tp) {
+		peer_req->flags |= EE_IN_INTERVAL_TREE;
+		err = wait_for_and_update_peer_seq(mdev, peer_seq);
+		if (err)
 			goto out_interrupted;
-
-		spin_lock_irq(&mdev->req_lock);
-
-		hlist_add_head(&e->collision, ee_hash_slot(mdev, sector));
-
-#define OVERLAPS overlaps(i->sector, i->size, sector, size)
-		slot = tl_hash_slot(mdev, sector);
-		first = 1;
-		for (;;) {
-			int have_unacked = 0;
-			int have_conflict = 0;
-			prepare_to_wait(&mdev->misc_wait, &wait,
-				TASK_INTERRUPTIBLE);
-			hlist_for_each_entry(i, n, slot, collision) {
-				if (OVERLAPS) {
-					/* only ALERT on first iteration,
-					 * we may be woken up early... */
-					if (first)
-						dev_alert(DEV, "%s[%u] Concurrent local write detected!"
-						      "	new: %llus +%u; pending: %llus +%u\n",
-						      current->comm, current->pid,
-						      (unsigned long long)sector, size,
-						      (unsigned long long)i->sector, i->size);
-					if (i->rq_state & RQ_NET_PENDING)
-						++have_unacked;
-					++have_conflict;
-				}
-			}
-#undef OVERLAPS
-			if (!have_conflict)
-				break;
-
-			/* Discard Ack only for the _first_ iteration */
-			if (first && discard && have_unacked) {
-				dev_alert(DEV, "Concurrent write! [DISCARD BY FLAG] sec=%llus\n",
-				     (unsigned long long)sector);
-				inc_unacked(mdev);
-				e->w.cb = e_send_discard_ack;
-				list_add_tail(&e->w.list, &mdev->done_ee);
-
-				spin_unlock_irq(&mdev->req_lock);
-
-				/* we could probably send that P_DISCARD_ACK ourselves,
-				 * but I don't like the receiver using the msock */
-
+		spin_lock_irq(&mdev->tconn->req_lock);
+		err = handle_write_conflicts(mdev, peer_req);
+		if (err) {
+			spin_unlock_irq(&mdev->tconn->req_lock);
+			if (err == -ENOENT) {
 				put_ldev(mdev);
-				wake_asender(mdev);
-				finish_wait(&mdev->misc_wait, &wait);
-				return true;
+				return 0;
 			}
+			goto out_interrupted;
+		}
+	} else
+		spin_lock_irq(&mdev->tconn->req_lock);
+	list_add(&peer_req->w.list, &mdev->active_ee);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
-			if (signal_pending(current)) {
-				hlist_del_init(&e->collision);
-
-				spin_unlock_irq(&mdev->req_lock);
-
-				finish_wait(&mdev->misc_wait, &wait);
-				goto out_interrupted;
-			}
+	if (mdev->state.conn == C_SYNC_TARGET)
+		wait_event(mdev->ee_wait, !overlapping_resync_write(mdev, peer_req));
 
-			spin_unlock_irq(&mdev->req_lock);
-			if (first) {
-				first = 0;
-				dev_alert(DEV, "Concurrent write! [W AFTERWARDS] "
-				     "sec=%llus\n", (unsigned long long)sector);
-			} else if (discard) {
-				/* we had none on the first iteration.
-				 * there must be none now. */
-				D_ASSERT(have_unacked == 0);
-			}
-			schedule();
-			spin_lock_irq(&mdev->req_lock);
+	if (mdev->tconn->agreed_pro_version < 100) {
+		rcu_read_lock();
+		switch (rcu_dereference(mdev->tconn->net_conf)->wire_protocol) {
+		case DRBD_PROT_C:
+			dp_flags |= DP_SEND_WRITE_ACK;
+			break;
+		case DRBD_PROT_B:
+			dp_flags |= DP_SEND_RECEIVE_ACK;
+			break;
 		}
-		finish_wait(&mdev->misc_wait, &wait);
+		rcu_read_unlock();
 	}
 
-	list_add(&e->w.list, &mdev->active_ee);
-	spin_unlock_irq(&mdev->req_lock);
-
-	if (mdev->state.conn == C_SYNC_TARGET)
-		wait_event(mdev->ee_wait, !overlapping_resync_write(mdev, e));
-
-	switch (mdev->net_conf->wire_protocol) {
-	case DRBD_PROT_C:
+	if (dp_flags & DP_SEND_WRITE_ACK) {
+		peer_req->flags |= EE_SEND_WRITE_ACK;
 		inc_unacked(mdev);
 		/* corresponding dec_unacked() in e_end_block()
 		 * respective _drbd_clear_done_ee */
-		break;
-	case DRBD_PROT_B:
+	}
+
+	if (dp_flags & DP_SEND_RECEIVE_ACK) {
 		/* I really don't like it that the receiver thread
 		 * sends on the msock, but anyways */
-		drbd_send_ack(mdev, P_RECV_ACK, e);
-		break;
-	case DRBD_PROT_A:
-		/* nothing to do */
-		break;
+		drbd_send_ack(mdev, P_RECV_ACK, peer_req);
 	}
 
 	if (mdev->state.pdsk < D_INCONSISTENT) {
 		/* In case we have the only disk of the cluster, */
-		drbd_set_out_of_sync(mdev, e->sector, e->size);
-		e->flags |= EE_CALL_AL_COMPLETE_IO;
-		e->flags &= ~EE_MAY_SET_IN_SYNC;
-		drbd_al_begin_io(mdev, e->sector);
+		drbd_set_out_of_sync(mdev, peer_req->i.sector, peer_req->i.size);
+		peer_req->flags |= EE_CALL_AL_COMPLETE_IO;
+		peer_req->flags &= ~EE_MAY_SET_IN_SYNC;
+		drbd_al_begin_io(mdev, &peer_req->i);
 	}
 
-	if (drbd_submit_ee(mdev, e, rw, DRBD_FAULT_DT_WR) == 0)
-		return true;
+	err = drbd_submit_peer_request(mdev, peer_req, rw, DRBD_FAULT_DT_WR);
+	if (!err)
+		return 0;
 
 	/* don't care for the reason here */
 	dev_err(DEV, "submit failed, triggering re-connect\n");
-	spin_lock_irq(&mdev->req_lock);
-	list_del(&e->w.list);
-	hlist_del_init(&e->collision);
-	spin_unlock_irq(&mdev->req_lock);
-	if (e->flags & EE_CALL_AL_COMPLETE_IO)
-		drbd_al_complete_io(mdev, e->sector);
+	spin_lock_irq(&mdev->tconn->req_lock);
+	list_del(&peer_req->w.list);
+	drbd_remove_epoch_entry_interval(mdev, peer_req);
+	spin_unlock_irq(&mdev->tconn->req_lock);
+	if (peer_req->flags & EE_CALL_AL_COMPLETE_IO)
+		drbd_al_complete_io(mdev, &peer_req->i);
 
 out_interrupted:
-	drbd_may_finish_epoch(mdev, e->epoch, EV_PUT + EV_CLEANUP);
+	drbd_may_finish_epoch(tconn, peer_req->epoch, EV_PUT + EV_CLEANUP);
 	put_ldev(mdev);
-	drbd_free_ee(mdev, e);
-	return false;
+	drbd_free_peer_req(mdev, peer_req);
+	return err;
 }
 
 /* We may throttle resync, if the lower device seems to be busy,
@@ -1933,9 +2296,14 @@ int drbd_rs_should_slow_down(struct drbd_conf *mdev, sector_t sector)
 	struct lc_element *tmp;
 	int curr_events;
 	int throttle = 0;
+	unsigned int c_min_rate;
+
+	rcu_read_lock();
+	c_min_rate = rcu_dereference(mdev->ldev->disk_conf)->c_min_rate;
+	rcu_read_unlock();
 
 	/* feature disabled? */
-	if (mdev->sync_conf.c_min_rate == 0)
+	if (c_min_rate == 0)
 		return 0;
 
 	spin_lock_irq(&mdev->al_lock);
@@ -1975,40 +2343,46 @@ int drbd_rs_should_slow_down(struct drbd_conf *mdev, sector_t sector)
 		db = mdev->rs_mark_left[i] - rs_left;
 		dbdt = Bit2KB(db/dt);
 
-		if (dbdt > mdev->sync_conf.c_min_rate)
+		if (dbdt > c_min_rate)
 			throttle = 1;
 	}
 	return throttle;
 }
 
 
-static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int digest_size)
+static int receive_DataRequest(struct drbd_tconn *tconn, struct packet_info *pi)
 {
+	struct drbd_conf *mdev;
 	sector_t sector;
-	const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
-	struct drbd_epoch_entry *e;
+	sector_t capacity;
+	struct drbd_peer_request *peer_req;
 	struct digest_info *di = NULL;
 	int size, verb;
 	unsigned int fault_type;
-	struct p_block_req *p =	&mdev->data.rbuf.block_req;
+	struct p_block_req *p =	pi->data;
+
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return -EIO;
+	capacity = drbd_get_capacity(mdev->this_bdev);
 
 	sector = be64_to_cpu(p->sector);
 	size   = be32_to_cpu(p->blksize);
 
-	if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
+	if (size <= 0 || !IS_ALIGNED(size, 512) || size > DRBD_MAX_BIO_SIZE) {
 		dev_err(DEV, "%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__,
 				(unsigned long long)sector, size);
-		return false;
+		return -EINVAL;
 	}
 	if (sector + (size>>9) > capacity) {
 		dev_err(DEV, "%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__,
 				(unsigned long long)sector, size);
-		return false;
+		return -EINVAL;
 	}
 
 	if (!get_ldev_if_state(mdev, D_UP_TO_DATE)) {
 		verb = 1;
-		switch (cmd) {
+		switch (pi->cmd) {
 		case P_DATA_REQUEST:
 			drbd_send_ack_rp(mdev, P_NEG_DREPLY, p);
 			break;
@@ -2023,35 +2397,34 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un
 			drbd_send_ack_ex(mdev, P_OV_RESULT, sector, size, ID_IN_SYNC);
 			break;
 		default:
-			dev_err(DEV, "unexpected command (%s) in receive_DataRequest\n",
-				cmdname(cmd));
+			BUG();
 		}
 		if (verb && __ratelimit(&drbd_ratelimit_state))
 			dev_err(DEV, "Can not satisfy peer's read request, "
 			    "no local data.\n");
 
 		/* drain possibly payload */
-		return drbd_drain_block(mdev, digest_size);
+		return drbd_drain_block(mdev, pi->size);
 	}
 
 	/* GFP_NOIO, because we must not cause arbitrary write-out: in a DRBD
 	 * "criss-cross" setup, that might cause write-out on some other DRBD,
 	 * which in turn might block on the other node at this very place.  */
-	e = drbd_alloc_ee(mdev, p->block_id, sector, size, GFP_NOIO);
-	if (!e) {
+	peer_req = drbd_alloc_peer_req(mdev, p->block_id, sector, size, GFP_NOIO);
+	if (!peer_req) {
 		put_ldev(mdev);
-		return false;
+		return -ENOMEM;
 	}
 
-	switch (cmd) {
+	switch (pi->cmd) {
 	case P_DATA_REQUEST:
-		e->w.cb = w_e_end_data_req;
+		peer_req->w.cb = w_e_end_data_req;
 		fault_type = DRBD_FAULT_DT_RD;
 		/* application IO, don't drbd_rs_begin_io */
 		goto submit;
 
 	case P_RS_DATA_REQUEST:
-		e->w.cb = w_e_end_rsdata_req;
+		peer_req->w.cb = w_e_end_rsdata_req;
 		fault_type = DRBD_FAULT_RS_RD;
 		/* used in the sector offset progress display */
 		mdev->bm_resync_fo = BM_SECT_TO_BIT(sector);
@@ -2060,28 +2433,28 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un
 	case P_OV_REPLY:
 	case P_CSUM_RS_REQUEST:
 		fault_type = DRBD_FAULT_RS_RD;
-		di = kmalloc(sizeof(*di) + digest_size, GFP_NOIO);
+		di = kmalloc(sizeof(*di) + pi->size, GFP_NOIO);
 		if (!di)
 			goto out_free_e;
 
-		di->digest_size = digest_size;
+		di->digest_size = pi->size;
 		di->digest = (((char *)di)+sizeof(struct digest_info));
 
-		e->digest = di;
-		e->flags |= EE_HAS_DIGEST;
+		peer_req->digest = di;
+		peer_req->flags |= EE_HAS_DIGEST;
 
-		if (drbd_recv(mdev, di->digest, digest_size) != digest_size)
+		if (drbd_recv_all(mdev->tconn, di->digest, pi->size))
 			goto out_free_e;
 
-		if (cmd == P_CSUM_RS_REQUEST) {
-			D_ASSERT(mdev->agreed_pro_version >= 89);
-			e->w.cb = w_e_end_csum_rs_req;
+		if (pi->cmd == P_CSUM_RS_REQUEST) {
+			D_ASSERT(mdev->tconn->agreed_pro_version >= 89);
+			peer_req->w.cb = w_e_end_csum_rs_req;
 			/* used in the sector offset progress display */
 			mdev->bm_resync_fo = BM_SECT_TO_BIT(sector);
-		} else if (cmd == P_OV_REPLY) {
+		} else if (pi->cmd == P_OV_REPLY) {
 			/* track progress, we may need to throttle */
 			atomic_add(size >> 9, &mdev->rs_sect_in);
-			e->w.cb = w_e_end_ov_reply;
+			peer_req->w.cb = w_e_end_ov_reply;
 			dec_rs_pending(mdev);
 			/* drbd_rs_begin_io done when we sent this request,
 			 * but accounting still needs to be done. */
@@ -2091,7 +2464,7 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un
 
 	case P_OV_REQUEST:
 		if (mdev->ov_start_sector == ~(sector_t)0 &&
-		    mdev->agreed_pro_version >= 90) {
+		    mdev->tconn->agreed_pro_version >= 90) {
 			unsigned long now = jiffies;
 			int i;
 			mdev->ov_start_sector = sector;
@@ -2105,15 +2478,12 @@ static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, un
 			dev_info(DEV, "Online Verify start sector: %llu\n",
 					(unsigned long long)sector);
 		}
-		e->w.cb = w_e_end_ov_req;
+		peer_req->w.cb = w_e_end_ov_req;
 		fault_type = DRBD_FAULT_RS_RD;
 		break;
 
 	default:
-		dev_err(DEV, "unexpected command (%s) in receive_DataRequest\n",
-		    cmdname(cmd));
-		fault_type = DRBD_FAULT_MAX;
-		goto out_free_e;
+		BUG();
 	}
 
 	/* Throttle, drbd_rs_begin_io and submit should become asynchronous
@@ -2148,30 +2518,31 @@ submit_for_resync:
 
 submit:
 	inc_unacked(mdev);
-	spin_lock_irq(&mdev->req_lock);
-	list_add_tail(&e->w.list, &mdev->read_ee);
-	spin_unlock_irq(&mdev->req_lock);
+	spin_lock_irq(&mdev->tconn->req_lock);
+	list_add_tail(&peer_req->w.list, &mdev->read_ee);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
-	if (drbd_submit_ee(mdev, e, READ, fault_type) == 0)
-		return true;
+	if (drbd_submit_peer_request(mdev, peer_req, READ, fault_type) == 0)
+		return 0;
 
 	/* don't care for the reason here */
 	dev_err(DEV, "submit failed, triggering re-connect\n");
-	spin_lock_irq(&mdev->req_lock);
-	list_del(&e->w.list);
-	spin_unlock_irq(&mdev->req_lock);
+	spin_lock_irq(&mdev->tconn->req_lock);
+	list_del(&peer_req->w.list);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 	/* no drbd_rs_complete_io(), we are dropping the connection anyways */
 
 out_free_e:
 	put_ldev(mdev);
-	drbd_free_ee(mdev, e);
-	return false;
+	drbd_free_peer_req(mdev, peer_req);
+	return -EIO;
 }
 
 static int drbd_asb_recover_0p(struct drbd_conf *mdev) __must_hold(local)
 {
 	int self, peer, rv = -100;
 	unsigned long ch_self, ch_peer;
+	enum drbd_after_sb_p after_sb_0p;
 
 	self = mdev->ldev->md.uuid[UI_BITMAP] & 1;
 	peer = mdev->p_uuid[UI_BITMAP] & 1;
@@ -2179,10 +2550,14 @@ static int drbd_asb_recover_0p(struct drbd_conf *mdev) __must_hold(local)
 	ch_peer = mdev->p_uuid[UI_SIZE];
 	ch_self = mdev->comm_bm_set;
 
-	switch (mdev->net_conf->after_sb_0p) {
+	rcu_read_lock();
+	after_sb_0p = rcu_dereference(mdev->tconn->net_conf)->after_sb_0p;
+	rcu_read_unlock();
+	switch (after_sb_0p) {
 	case ASB_CONSENSUS:
 	case ASB_DISCARD_SECONDARY:
 	case ASB_CALL_HELPER:
+	case ASB_VIOLENTLY:
 		dev_err(DEV, "Configuration error.\n");
 		break;
 	case ASB_DISCONNECT:
@@ -2211,14 +2586,14 @@ static int drbd_asb_recover_0p(struct drbd_conf *mdev) __must_hold(local)
 		     "Using discard-least-changes instead\n");
 	case ASB_DISCARD_ZERO_CHG:
 		if (ch_peer == 0 && ch_self == 0) {
-			rv = test_bit(DISCARD_CONCURRENT, &mdev->flags)
+			rv = test_bit(RESOLVE_CONFLICTS, &mdev->tconn->flags)
 				? -1 : 1;
 			break;
 		} else {
 			if (ch_peer == 0) { rv =  1; break; }
 			if (ch_self == 0) { rv = -1; break; }
 		}
-		if (mdev->net_conf->after_sb_0p == ASB_DISCARD_ZERO_CHG)
+		if (after_sb_0p == ASB_DISCARD_ZERO_CHG)
 			break;
 	case ASB_DISCARD_LEAST_CHG:
 		if	(ch_self < ch_peer)
@@ -2227,7 +2602,7 @@ static int drbd_asb_recover_0p(struct drbd_conf *mdev) __must_hold(local)
 			rv =  1;
 		else /* ( ch_self == ch_peer ) */
 		     /* Well, then use something else. */
-			rv = test_bit(DISCARD_CONCURRENT, &mdev->flags)
+			rv = test_bit(RESOLVE_CONFLICTS, &mdev->tconn->flags)
 				? -1 : 1;
 		break;
 	case ASB_DISCARD_LOCAL:
@@ -2243,13 +2618,18 @@ static int drbd_asb_recover_0p(struct drbd_conf *mdev) __must_hold(local)
 static int drbd_asb_recover_1p(struct drbd_conf *mdev) __must_hold(local)
 {
 	int hg, rv = -100;
+	enum drbd_after_sb_p after_sb_1p;
 
-	switch (mdev->net_conf->after_sb_1p) {
+	rcu_read_lock();
+	after_sb_1p = rcu_dereference(mdev->tconn->net_conf)->after_sb_1p;
+	rcu_read_unlock();
+	switch (after_sb_1p) {
 	case ASB_DISCARD_YOUNGER_PRI:
 	case ASB_DISCARD_OLDER_PRI:
 	case ASB_DISCARD_LEAST_CHG:
 	case ASB_DISCARD_LOCAL:
 	case ASB_DISCARD_REMOTE:
+	case ASB_DISCARD_ZERO_CHG:
 		dev_err(DEV, "Configuration error.\n");
 		break;
 	case ASB_DISCONNECT:
@@ -2292,8 +2672,12 @@ static int drbd_asb_recover_1p(struct drbd_conf *mdev) __must_hold(local)
 static int drbd_asb_recover_2p(struct drbd_conf *mdev) __must_hold(local)
 {
 	int hg, rv = -100;
+	enum drbd_after_sb_p after_sb_2p;
 
-	switch (mdev->net_conf->after_sb_2p) {
+	rcu_read_lock();
+	after_sb_2p = rcu_dereference(mdev->tconn->net_conf)->after_sb_2p;
+	rcu_read_unlock();
+	switch (after_sb_2p) {
 	case ASB_DISCARD_YOUNGER_PRI:
 	case ASB_DISCARD_OLDER_PRI:
 	case ASB_DISCARD_LEAST_CHG:
@@ -2301,6 +2685,7 @@ static int drbd_asb_recover_2p(struct drbd_conf *mdev) __must_hold(local)
 	case ASB_DISCARD_REMOTE:
 	case ASB_CONSENSUS:
 	case ASB_DISCARD_SECONDARY:
+	case ASB_DISCARD_ZERO_CHG:
 		dev_err(DEV, "Configuration error.\n");
 		break;
 	case ASB_VIOLENTLY:
@@ -2386,13 +2771,15 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
 
 		if (mdev->p_uuid[UI_BITMAP] == (u64)0 && mdev->ldev->md.uuid[UI_BITMAP] != (u64)0) {
 
-			if (mdev->agreed_pro_version < 91)
+			if (mdev->tconn->agreed_pro_version < 91)
 				return -1091;
 
 			if ((mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1)) &&
 			    (mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1))) {
 				dev_info(DEV, "was SyncSource, missed the resync finished event, corrected myself:\n");
-				drbd_uuid_set_bm(mdev, 0UL);
+				drbd_uuid_move_history(mdev);
+				mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[UI_BITMAP];
+				mdev->ldev->md.uuid[UI_BITMAP] = 0;
 
 				drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid,
 					       mdev->state.disk >= D_NEGOTIATING ? drbd_bm_total_weight(mdev) : 0, 0);
@@ -2407,7 +2794,7 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
 
 		if (mdev->ldev->md.uuid[UI_BITMAP] == (u64)0 && mdev->p_uuid[UI_BITMAP] != (u64)0) {
 
-			if (mdev->agreed_pro_version < 91)
+			if (mdev->tconn->agreed_pro_version < 91)
 				return -1091;
 
 			if ((mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (mdev->p_uuid[UI_BITMAP] & ~((u64)1)) &&
@@ -2440,7 +2827,7 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
 		case 1: /*  self_pri && !peer_pri */ return 1;
 		case 2: /* !self_pri &&  peer_pri */ return -1;
 		case 3: /*  self_pri &&  peer_pri */
-			dc = test_bit(DISCARD_CONCURRENT, &mdev->flags);
+			dc = test_bit(RESOLVE_CONFLICTS, &mdev->tconn->flags);
 			return dc ? -1 : 1;
 		}
 	}
@@ -2453,14 +2840,14 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
 	*rule_nr = 51;
 	peer = mdev->p_uuid[UI_HISTORY_START] & ~((u64)1);
 	if (self == peer) {
-		if (mdev->agreed_pro_version < 96 ?
+		if (mdev->tconn->agreed_pro_version < 96 ?
 		    (mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) ==
 		    (mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1)) :
 		    peer + UUID_NEW_BM_OFFSET == (mdev->p_uuid[UI_BITMAP] & ~((u64)1))) {
 			/* The last P_SYNC_UUID did not get though. Undo the last start of
 			   resync as sync source modifications of the peer's UUIDs. */
 
-			if (mdev->agreed_pro_version < 91)
+			if (mdev->tconn->agreed_pro_version < 91)
 				return -1091;
 
 			mdev->p_uuid[UI_BITMAP] = mdev->p_uuid[UI_HISTORY_START];
@@ -2490,18 +2877,18 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
 	*rule_nr = 71;
 	self = mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1);
 	if (self == peer) {
-		if (mdev->agreed_pro_version < 96 ?
+		if (mdev->tconn->agreed_pro_version < 96 ?
 		    (mdev->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1)) ==
 		    (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1)) :
 		    self + UUID_NEW_BM_OFFSET == (mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1))) {
 			/* The last P_SYNC_UUID did not get though. Undo the last start of
 			   resync as sync source modifications of our UUIDs. */
 
-			if (mdev->agreed_pro_version < 91)
+			if (mdev->tconn->agreed_pro_version < 91)
 				return -1091;
 
-			_drbd_uuid_set(mdev, UI_BITMAP, mdev->ldev->md.uuid[UI_HISTORY_START]);
-			_drbd_uuid_set(mdev, UI_HISTORY_START, mdev->ldev->md.uuid[UI_HISTORY_START + 1]);
+			__drbd_uuid_set(mdev, UI_BITMAP, mdev->ldev->md.uuid[UI_HISTORY_START]);
+			__drbd_uuid_set(mdev, UI_HISTORY_START, mdev->ldev->md.uuid[UI_HISTORY_START + 1]);
 
 			dev_info(DEV, "Last syncUUID did not get through, corrected:\n");
 			drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid,
@@ -2545,20 +2932,24 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
 static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_role peer_role,
 					   enum drbd_disk_state peer_disk) __must_hold(local)
 {
-	int hg, rule_nr;
 	enum drbd_conns rv = C_MASK;
 	enum drbd_disk_state mydisk;
+	struct net_conf *nc;
+	int hg, rule_nr, rr_conflict, tentative;
 
 	mydisk = mdev->state.disk;
 	if (mydisk == D_NEGOTIATING)
 		mydisk = mdev->new_state_tmp.disk;
 
 	dev_info(DEV, "drbd_sync_handshake:\n");
+
+	spin_lock_irq(&mdev->ldev->md.uuid_lock);
 	drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid, mdev->comm_bm_set, 0);
 	drbd_uuid_dump(mdev, "peer", mdev->p_uuid,
 		       mdev->p_uuid[UI_SIZE], mdev->p_uuid[UI_FLAGS]);
 
 	hg = drbd_uuid_compare(mdev, &rule_nr);
+	spin_unlock_irq(&mdev->ldev->md.uuid_lock);
 
 	dev_info(DEV, "uuid_compare()=%d by rule %d\n", hg, rule_nr);
 
@@ -2584,7 +2975,10 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol
 	if (abs(hg) == 100)
 		drbd_khelper(mdev, "initial-split-brain");
 
-	if (hg == 100 || (hg == -100 && mdev->net_conf->always_asbp)) {
+	rcu_read_lock();
+	nc = rcu_dereference(mdev->tconn->net_conf);
+
+	if (hg == 100 || (hg == -100 && nc->always_asbp)) {
 		int pcount = (mdev->state.role == R_PRIMARY)
 			   + (peer_role == R_PRIMARY);
 		int forced = (hg == -100);
@@ -2613,9 +3007,9 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol
 	}
 
 	if (hg == -100) {
-		if (mdev->net_conf->want_lose && !(mdev->p_uuid[UI_FLAGS]&1))
+		if (test_bit(DISCARD_MY_DATA, &mdev->flags) && !(mdev->p_uuid[UI_FLAGS]&1))
 			hg = -1;
-		if (!mdev->net_conf->want_lose && (mdev->p_uuid[UI_FLAGS]&1))
+		if (!test_bit(DISCARD_MY_DATA, &mdev->flags) && (mdev->p_uuid[UI_FLAGS]&1))
 			hg = 1;
 
 		if (abs(hg) < 100)
@@ -2623,6 +3017,9 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol
 			     "Sync from %s node\n",
 			     (hg < 0) ? "peer" : "this");
 	}
+	rr_conflict = nc->rr_conflict;
+	tentative = nc->tentative;
+	rcu_read_unlock();
 
 	if (hg == -100) {
 		/* FIXME this log message is not correct if we end up here
@@ -2641,7 +3038,7 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol
 
 	if (hg < 0 && /* by intention we do not use mydisk here. */
 	    mdev->state.role == R_PRIMARY && mdev->state.disk >= D_CONSISTENT) {
-		switch (mdev->net_conf->rr_conflict) {
+		switch (rr_conflict) {
 		case ASB_CALL_HELPER:
 			drbd_khelper(mdev, "pri-lost");
 			/* fall through */
@@ -2654,7 +3051,7 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol
 		}
 	}
 
-	if (mdev->net_conf->dry_run || test_bit(CONN_DRY_RUN, &mdev->flags)) {
+	if (tentative || test_bit(CONN_DRY_RUN, &mdev->tconn->flags)) {
 		if (hg == 0)
 			dev_info(DEV, "dry-run connect: No resync, would become Connected immediately.\n");
 		else
@@ -2686,33 +3083,29 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol
 	return rv;
 }
 
-/* returns 1 if invalid */
-static int cmp_after_sb(enum drbd_after_sb_p peer, enum drbd_after_sb_p self)
+static enum drbd_after_sb_p convert_after_sb(enum drbd_after_sb_p peer)
 {
 	/* ASB_DISCARD_REMOTE - ASB_DISCARD_LOCAL is valid */
-	if ((peer == ASB_DISCARD_REMOTE && self == ASB_DISCARD_LOCAL) ||
-	    (self == ASB_DISCARD_REMOTE && peer == ASB_DISCARD_LOCAL))
-		return 0;
+	if (peer == ASB_DISCARD_REMOTE)
+		return ASB_DISCARD_LOCAL;
 
 	/* any other things with ASB_DISCARD_REMOTE or ASB_DISCARD_LOCAL are invalid */
-	if (peer == ASB_DISCARD_REMOTE || peer == ASB_DISCARD_LOCAL ||
-	    self == ASB_DISCARD_REMOTE || self == ASB_DISCARD_LOCAL)
-		return 1;
+	if (peer == ASB_DISCARD_LOCAL)
+		return ASB_DISCARD_REMOTE;
 
 	/* everything else is valid if they are equal on both sides. */
-	if (peer == self)
-		return 0;
-
-	/* everything es is invalid. */
-	return 1;
+	return peer;
 }
 
-static int receive_protocol(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
+static int receive_protocol(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	struct p_protocol *p = &mdev->data.rbuf.protocol;
-	int p_proto, p_after_sb_0p, p_after_sb_1p, p_after_sb_2p;
-	int p_want_lose, p_two_primaries, cf;
-	char p_integrity_alg[SHARED_SECRET_MAX] = "";
+	struct p_protocol *p = pi->data;
+	enum drbd_after_sb_p p_after_sb_0p, p_after_sb_1p, p_after_sb_2p;
+	int p_proto, p_discard_my_data, p_two_primaries, cf;
+	struct net_conf *nc, *old_net_conf, *new_net_conf = NULL;
+	char integrity_alg[SHARED_SECRET_MAX] = "";
+	struct crypto_hash *peer_integrity_tfm = NULL;
+	void *int_dig_in = NULL, *int_dig_vv = NULL;
 
 	p_proto		= be32_to_cpu(p->protocol);
 	p_after_sb_0p	= be32_to_cpu(p->after_sb_0p);
@@ -2720,63 +3113,138 @@ static int receive_protocol(struct drbd_conf *mdev, enum drbd_packets cmd, unsig
 	p_after_sb_2p	= be32_to_cpu(p->after_sb_2p);
 	p_two_primaries = be32_to_cpu(p->two_primaries);
 	cf		= be32_to_cpu(p->conn_flags);
-	p_want_lose = cf & CF_WANT_LOSE;
+	p_discard_my_data = cf & CF_DISCARD_MY_DATA;
 
-	clear_bit(CONN_DRY_RUN, &mdev->flags);
+	if (tconn->agreed_pro_version >= 87) {
+		int err;
 
-	if (cf & CF_DRY_RUN)
-		set_bit(CONN_DRY_RUN, &mdev->flags);
-
-	if (p_proto != mdev->net_conf->wire_protocol) {
-		dev_err(DEV, "incompatible communication protocols\n");
-		goto disconnect;
+		if (pi->size > sizeof(integrity_alg))
+			return -EIO;
+		err = drbd_recv_all(tconn, integrity_alg, pi->size);
+		if (err)
+			return err;
+		integrity_alg[SHARED_SECRET_MAX - 1] = 0;
 	}
 
-	if (cmp_after_sb(p_after_sb_0p, mdev->net_conf->after_sb_0p)) {
-		dev_err(DEV, "incompatible after-sb-0pri settings\n");
-		goto disconnect;
-	}
+	if (pi->cmd != P_PROTOCOL_UPDATE) {
+		clear_bit(CONN_DRY_RUN, &tconn->flags);
 
-	if (cmp_after_sb(p_after_sb_1p, mdev->net_conf->after_sb_1p)) {
-		dev_err(DEV, "incompatible after-sb-1pri settings\n");
-		goto disconnect;
-	}
+		if (cf & CF_DRY_RUN)
+			set_bit(CONN_DRY_RUN, &tconn->flags);
 
-	if (cmp_after_sb(p_after_sb_2p, mdev->net_conf->after_sb_2p)) {
-		dev_err(DEV, "incompatible after-sb-2pri settings\n");
-		goto disconnect;
-	}
+		rcu_read_lock();
+		nc = rcu_dereference(tconn->net_conf);
 
-	if (p_want_lose && mdev->net_conf->want_lose) {
-		dev_err(DEV, "both sides have the 'want_lose' flag set\n");
-		goto disconnect;
-	}
+		if (p_proto != nc->wire_protocol) {
+			conn_err(tconn, "incompatible %s settings\n", "protocol");
+			goto disconnect_rcu_unlock;
+		}
 
-	if (p_two_primaries != mdev->net_conf->two_primaries) {
-		dev_err(DEV, "incompatible setting of the two-primaries options\n");
-		goto disconnect;
+		if (convert_after_sb(p_after_sb_0p) != nc->after_sb_0p) {
+			conn_err(tconn, "incompatible %s settings\n", "after-sb-0pri");
+			goto disconnect_rcu_unlock;
+		}
+
+		if (convert_after_sb(p_after_sb_1p) != nc->after_sb_1p) {
+			conn_err(tconn, "incompatible %s settings\n", "after-sb-1pri");
+			goto disconnect_rcu_unlock;
+		}
+
+		if (convert_after_sb(p_after_sb_2p) != nc->after_sb_2p) {
+			conn_err(tconn, "incompatible %s settings\n", "after-sb-2pri");
+			goto disconnect_rcu_unlock;
+		}
+
+		if (p_discard_my_data && nc->discard_my_data) {
+			conn_err(tconn, "incompatible %s settings\n", "discard-my-data");
+			goto disconnect_rcu_unlock;
+		}
+
+		if (p_two_primaries != nc->two_primaries) {
+			conn_err(tconn, "incompatible %s settings\n", "allow-two-primaries");
+			goto disconnect_rcu_unlock;
+		}
+
+		if (strcmp(integrity_alg, nc->integrity_alg)) {
+			conn_err(tconn, "incompatible %s settings\n", "data-integrity-alg");
+			goto disconnect_rcu_unlock;
+		}
+
+		rcu_read_unlock();
 	}
 
-	if (mdev->agreed_pro_version >= 87) {
-		unsigned char *my_alg = mdev->net_conf->integrity_alg;
+	if (integrity_alg[0]) {
+		int hash_size;
+
+		/*
+		 * We can only change the peer data integrity algorithm
+		 * here.  Changing our own data integrity algorithm
+		 * requires that we send a P_PROTOCOL_UPDATE packet at
+		 * the same time; otherwise, the peer has no way to
+		 * tell between which packets the algorithm should
+		 * change.
+		 */
 
-		if (drbd_recv(mdev, p_integrity_alg, data_size) != data_size)
-			return false;
+		peer_integrity_tfm = crypto_alloc_hash(integrity_alg, 0, CRYPTO_ALG_ASYNC);
+		if (!peer_integrity_tfm) {
+			conn_err(tconn, "peer data-integrity-alg %s not supported\n",
+				 integrity_alg);
+			goto disconnect;
+		}
 
-		p_integrity_alg[SHARED_SECRET_MAX-1] = 0;
-		if (strcmp(p_integrity_alg, my_alg)) {
-			dev_err(DEV, "incompatible setting of the data-integrity-alg\n");
+		hash_size = crypto_hash_digestsize(peer_integrity_tfm);
+		int_dig_in = kmalloc(hash_size, GFP_KERNEL);
+		int_dig_vv = kmalloc(hash_size, GFP_KERNEL);
+		if (!(int_dig_in && int_dig_vv)) {
+			conn_err(tconn, "Allocation of buffers for data integrity checking failed\n");
 			goto disconnect;
 		}
-		dev_info(DEV, "data-integrity-alg: %s\n",
-		     my_alg[0] ? my_alg : (unsigned char *)"<not-used>");
 	}
 
-	return true;
+	new_net_conf = kmalloc(sizeof(struct net_conf), GFP_KERNEL);
+	if (!new_net_conf) {
+		conn_err(tconn, "Allocation of new net_conf failed\n");
+		goto disconnect;
+	}
+
+	mutex_lock(&tconn->data.mutex);
+	mutex_lock(&tconn->conf_update);
+	old_net_conf = tconn->net_conf;
+	*new_net_conf = *old_net_conf;
+
+	new_net_conf->wire_protocol = p_proto;
+	new_net_conf->after_sb_0p = convert_after_sb(p_after_sb_0p);
+	new_net_conf->after_sb_1p = convert_after_sb(p_after_sb_1p);
+	new_net_conf->after_sb_2p = convert_after_sb(p_after_sb_2p);
+	new_net_conf->two_primaries = p_two_primaries;
+
+	rcu_assign_pointer(tconn->net_conf, new_net_conf);
+	mutex_unlock(&tconn->conf_update);
+	mutex_unlock(&tconn->data.mutex);
 
+	crypto_free_hash(tconn->peer_integrity_tfm);
+	kfree(tconn->int_dig_in);
+	kfree(tconn->int_dig_vv);
+	tconn->peer_integrity_tfm = peer_integrity_tfm;
+	tconn->int_dig_in = int_dig_in;
+	tconn->int_dig_vv = int_dig_vv;
+
+	if (strcmp(old_net_conf->integrity_alg, integrity_alg))
+		conn_info(tconn, "peer data-integrity-alg: %s\n",
+			  integrity_alg[0] ? integrity_alg : "(none)");
+
+	synchronize_rcu();
+	kfree(old_net_conf);
+	return 0;
+
+disconnect_rcu_unlock:
+	rcu_read_unlock();
 disconnect:
-	drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-	return false;
+	crypto_free_hash(peer_integrity_tfm);
+	kfree(int_dig_in);
+	kfree(int_dig_vv);
+	conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+	return -EIO;
 }
 
 /* helper function
@@ -2798,24 +3266,64 @@ struct crypto_hash *drbd_crypto_alloc_digest_safe(const struct drbd_conf *mdev,
 			alg, name, PTR_ERR(tfm));
 		return tfm;
 	}
-	if (!drbd_crypto_is_hash(crypto_hash_tfm(tfm))) {
-		crypto_free_hash(tfm);
-		dev_err(DEV, "\"%s\" is not a digest (%s)\n", alg, name);
-		return ERR_PTR(-EINVAL);
-	}
 	return tfm;
 }
 
-static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int packet_size)
+static int ignore_remaining_packet(struct drbd_tconn *tconn, struct packet_info *pi)
+{
+	void *buffer = tconn->data.rbuf;
+	int size = pi->size;
+
+	while (size) {
+		int s = min_t(int, size, DRBD_SOCKET_BUFFER_SIZE);
+		s = drbd_recv(tconn, buffer, s);
+		if (s <= 0) {
+			if (s < 0)
+				return s;
+			break;
+		}
+		size -= s;
+	}
+	if (size)
+		return -EIO;
+	return 0;
+}
+
+/*
+ * config_unknown_volume  -  device configuration command for unknown volume
+ *
+ * When a device is added to an existing connection, the node on which the
+ * device is added first will send configuration commands to its peer but the
+ * peer will not know about the device yet.  It will warn and ignore these
+ * commands.  Once the device is added on the second node, the second node will
+ * send the same device configuration commands, but in the other direction.
+ *
+ * (We can also end up here if drbd is misconfigured.)
+ */
+static int config_unknown_volume(struct drbd_tconn *tconn, struct packet_info *pi)
+{
+	conn_warn(tconn, "%s packet received for volume %u, which is not configured locally\n",
+		  cmdname(pi->cmd), pi->vnr);
+	return ignore_remaining_packet(tconn, pi);
+}
+
+static int receive_SyncParam(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	int ok = true;
-	struct p_rs_param_95 *p = &mdev->data.rbuf.rs_param_95;
+	struct drbd_conf *mdev;
+	struct p_rs_param_95 *p;
 	unsigned int header_size, data_size, exp_max_sz;
 	struct crypto_hash *verify_tfm = NULL;
 	struct crypto_hash *csums_tfm = NULL;
-	const int apv = mdev->agreed_pro_version;
-	int *rs_plan_s = NULL;
+	struct net_conf *old_net_conf, *new_net_conf = NULL;
+	struct disk_conf *old_disk_conf = NULL, *new_disk_conf = NULL;
+	const int apv = tconn->agreed_pro_version;
+	struct fifo_buffer *old_plan = NULL, *new_plan = NULL;
 	int fifo_size = 0;
+	int err;
+
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return config_unknown_volume(tconn, pi);
 
 	exp_max_sz  = apv <= 87 ? sizeof(struct p_rs_param)
 		    : apv == 88 ? sizeof(struct p_rs_param)
@@ -2823,32 +3331,49 @@ static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsi
 		    : apv <= 94 ? sizeof(struct p_rs_param_89)
 		    : /* apv >= 95 */ sizeof(struct p_rs_param_95);
 
-	if (packet_size > exp_max_sz) {
+	if (pi->size > exp_max_sz) {
 		dev_err(DEV, "SyncParam packet too long: received %u, expected <= %u bytes\n",
-		    packet_size, exp_max_sz);
-		return false;
+		    pi->size, exp_max_sz);
+		return -EIO;
 	}
 
 	if (apv <= 88) {
-		header_size = sizeof(struct p_rs_param) - sizeof(struct p_header80);
-		data_size   = packet_size  - header_size;
+		header_size = sizeof(struct p_rs_param);
+		data_size = pi->size - header_size;
 	} else if (apv <= 94) {
-		header_size = sizeof(struct p_rs_param_89) - sizeof(struct p_header80);
-		data_size   = packet_size  - header_size;
+		header_size = sizeof(struct p_rs_param_89);
+		data_size = pi->size - header_size;
 		D_ASSERT(data_size == 0);
 	} else {
-		header_size = sizeof(struct p_rs_param_95) - sizeof(struct p_header80);
-		data_size   = packet_size  - header_size;
+		header_size = sizeof(struct p_rs_param_95);
+		data_size = pi->size - header_size;
 		D_ASSERT(data_size == 0);
 	}
 
 	/* initialize verify_alg and csums_alg */
+	p = pi->data;
 	memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX);
 
-	if (drbd_recv(mdev, &p->head.payload, header_size) != header_size)
-		return false;
+	err = drbd_recv_all(mdev->tconn, p, header_size);
+	if (err)
+		return err;
+
+	mutex_lock(&mdev->tconn->conf_update);
+	old_net_conf = mdev->tconn->net_conf;
+	if (get_ldev(mdev)) {
+		new_disk_conf = kzalloc(sizeof(struct disk_conf), GFP_KERNEL);
+		if (!new_disk_conf) {
+			put_ldev(mdev);
+			mutex_unlock(&mdev->tconn->conf_update);
+			dev_err(DEV, "Allocation of new disk_conf failed\n");
+			return -ENOMEM;
+		}
+
+		old_disk_conf = mdev->ldev->disk_conf;
+		*new_disk_conf = *old_disk_conf;
 
-	mdev->sync_conf.rate	  = be32_to_cpu(p->rate);
+		new_disk_conf->resync_rate = be32_to_cpu(p->resync_rate);
+	}
 
 	if (apv >= 88) {
 		if (apv == 88) {
@@ -2856,12 +3381,13 @@ static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsi
 				dev_err(DEV, "verify-alg of wrong size, "
 					"peer wants %u, accepting only up to %u byte\n",
 					data_size, SHARED_SECRET_MAX);
-				return false;
+				err = -EIO;
+				goto reconnect;
 			}
 
-			if (drbd_recv(mdev, p->verify_alg, data_size) != data_size)
-				return false;
-
+			err = drbd_recv_all(mdev->tconn, p->verify_alg, data_size);
+			if (err)
+				goto reconnect;
 			/* we expect NUL terminated string */
 			/* but just in case someone tries to be evil */
 			D_ASSERT(p->verify_alg[data_size-1] == 0);
@@ -2876,10 +3402,10 @@ static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsi
 			p->csums_alg[SHARED_SECRET_MAX-1] = 0;
 		}
 
-		if (strcmp(mdev->sync_conf.verify_alg, p->verify_alg)) {
+		if (strcmp(old_net_conf->verify_alg, p->verify_alg)) {
 			if (mdev->state.conn == C_WF_REPORT_PARAMS) {
 				dev_err(DEV, "Different verify-alg settings. me=\"%s\" peer=\"%s\"\n",
-				    mdev->sync_conf.verify_alg, p->verify_alg);
+				    old_net_conf->verify_alg, p->verify_alg);
 				goto disconnect;
 			}
 			verify_tfm = drbd_crypto_alloc_digest_safe(mdev,
@@ -2890,10 +3416,10 @@ static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsi
 			}
 		}
 
-		if (apv >= 89 && strcmp(mdev->sync_conf.csums_alg, p->csums_alg)) {
+		if (apv >= 89 && strcmp(old_net_conf->csums_alg, p->csums_alg)) {
 			if (mdev->state.conn == C_WF_REPORT_PARAMS) {
 				dev_err(DEV, "Different csums-alg settings. me=\"%s\" peer=\"%s\"\n",
-				    mdev->sync_conf.csums_alg, p->csums_alg);
+				    old_net_conf->csums_alg, p->csums_alg);
 				goto disconnect;
 			}
 			csums_tfm = drbd_crypto_alloc_digest_safe(mdev,
@@ -2904,57 +3430,91 @@ static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsi
 			}
 		}
 
-		if (apv > 94) {
-			mdev->sync_conf.rate	  = be32_to_cpu(p->rate);
-			mdev->sync_conf.c_plan_ahead = be32_to_cpu(p->c_plan_ahead);
-			mdev->sync_conf.c_delay_target = be32_to_cpu(p->c_delay_target);
-			mdev->sync_conf.c_fill_target = be32_to_cpu(p->c_fill_target);
-			mdev->sync_conf.c_max_rate = be32_to_cpu(p->c_max_rate);
-
-			fifo_size = (mdev->sync_conf.c_plan_ahead * 10 * SLEEP_TIME) / HZ;
-			if (fifo_size != mdev->rs_plan_s.size && fifo_size > 0) {
-				rs_plan_s   = kzalloc(sizeof(int) * fifo_size, GFP_KERNEL);
-				if (!rs_plan_s) {
+		if (apv > 94 && new_disk_conf) {
+			new_disk_conf->c_plan_ahead = be32_to_cpu(p->c_plan_ahead);
+			new_disk_conf->c_delay_target = be32_to_cpu(p->c_delay_target);
+			new_disk_conf->c_fill_target = be32_to_cpu(p->c_fill_target);
+			new_disk_conf->c_max_rate = be32_to_cpu(p->c_max_rate);
+
+			fifo_size = (new_disk_conf->c_plan_ahead * 10 * SLEEP_TIME) / HZ;
+			if (fifo_size != mdev->rs_plan_s->size) {
+				new_plan = fifo_alloc(fifo_size);
+				if (!new_plan) {
 					dev_err(DEV, "kmalloc of fifo_buffer failed");
+					put_ldev(mdev);
 					goto disconnect;
 				}
 			}
 		}
 
-		spin_lock(&mdev->peer_seq_lock);
-		/* lock against drbd_nl_syncer_conf() */
-		if (verify_tfm) {
-			strcpy(mdev->sync_conf.verify_alg, p->verify_alg);
-			mdev->sync_conf.verify_alg_len = strlen(p->verify_alg) + 1;
-			crypto_free_hash(mdev->verify_tfm);
-			mdev->verify_tfm = verify_tfm;
-			dev_info(DEV, "using verify-alg: \"%s\"\n", p->verify_alg);
-		}
-		if (csums_tfm) {
-			strcpy(mdev->sync_conf.csums_alg, p->csums_alg);
-			mdev->sync_conf.csums_alg_len = strlen(p->csums_alg) + 1;
-			crypto_free_hash(mdev->csums_tfm);
-			mdev->csums_tfm = csums_tfm;
-			dev_info(DEV, "using csums-alg: \"%s\"\n", p->csums_alg);
-		}
-		if (fifo_size != mdev->rs_plan_s.size) {
-			kfree(mdev->rs_plan_s.values);
-			mdev->rs_plan_s.values = rs_plan_s;
-			mdev->rs_plan_s.size   = fifo_size;
-			mdev->rs_planed = 0;
+		if (verify_tfm || csums_tfm) {
+			new_net_conf = kzalloc(sizeof(struct net_conf), GFP_KERNEL);
+			if (!new_net_conf) {
+				dev_err(DEV, "Allocation of new net_conf failed\n");
+				goto disconnect;
+			}
+
+			*new_net_conf = *old_net_conf;
+
+			if (verify_tfm) {
+				strcpy(new_net_conf->verify_alg, p->verify_alg);
+				new_net_conf->verify_alg_len = strlen(p->verify_alg) + 1;
+				crypto_free_hash(mdev->tconn->verify_tfm);
+				mdev->tconn->verify_tfm = verify_tfm;
+				dev_info(DEV, "using verify-alg: \"%s\"\n", p->verify_alg);
+			}
+			if (csums_tfm) {
+				strcpy(new_net_conf->csums_alg, p->csums_alg);
+				new_net_conf->csums_alg_len = strlen(p->csums_alg) + 1;
+				crypto_free_hash(mdev->tconn->csums_tfm);
+				mdev->tconn->csums_tfm = csums_tfm;
+				dev_info(DEV, "using csums-alg: \"%s\"\n", p->csums_alg);
+			}
+			rcu_assign_pointer(tconn->net_conf, new_net_conf);
 		}
-		spin_unlock(&mdev->peer_seq_lock);
 	}
 
-	return ok;
+	if (new_disk_conf) {
+		rcu_assign_pointer(mdev->ldev->disk_conf, new_disk_conf);
+		put_ldev(mdev);
+	}
+
+	if (new_plan) {
+		old_plan = mdev->rs_plan_s;
+		rcu_assign_pointer(mdev->rs_plan_s, new_plan);
+	}
+
+	mutex_unlock(&mdev->tconn->conf_update);
+	synchronize_rcu();
+	if (new_net_conf)
+		kfree(old_net_conf);
+	kfree(old_disk_conf);
+	kfree(old_plan);
+
+	return 0;
+
+reconnect:
+	if (new_disk_conf) {
+		put_ldev(mdev);
+		kfree(new_disk_conf);
+	}
+	mutex_unlock(&mdev->tconn->conf_update);
+	return -EIO;
+
 disconnect:
+	kfree(new_plan);
+	if (new_disk_conf) {
+		put_ldev(mdev);
+		kfree(new_disk_conf);
+	}
+	mutex_unlock(&mdev->tconn->conf_update);
 	/* just for completeness: actually not needed,
 	 * as this is not reached if csums_tfm was ok. */
 	crypto_free_hash(csums_tfm);
 	/* but free the verify_tfm again, if csums_tfm did not work out */
 	crypto_free_hash(verify_tfm);
-	drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-	return false;
+	conn_request_state(mdev->tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+	return -EIO;
 }
 
 /* warn if the arguments differ by more than 12.5% */
@@ -2970,59 +3530,77 @@ static void warn_if_differ_considerably(struct drbd_conf *mdev,
 		     (unsigned long long)a, (unsigned long long)b);
 }
 
-static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
+static int receive_sizes(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	struct p_sizes *p = &mdev->data.rbuf.sizes;
+	struct drbd_conf *mdev;
+	struct p_sizes *p = pi->data;
 	enum determine_dev_size dd = unchanged;
 	sector_t p_size, p_usize, my_usize;
 	int ldsc = 0; /* local disk size changed */
 	enum dds_flags ddsf;
 
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return config_unknown_volume(tconn, pi);
+
 	p_size = be64_to_cpu(p->d_size);
 	p_usize = be64_to_cpu(p->u_size);
 
-	if (p_size == 0 && mdev->state.disk == D_DISKLESS) {
-		dev_err(DEV, "some backing storage is needed\n");
-		drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-		return false;
-	}
-
 	/* just store the peer's disk size for now.
 	 * we still need to figure out whether we accept that. */
 	mdev->p_size = p_size;
 
 	if (get_ldev(mdev)) {
+		rcu_read_lock();
+		my_usize = rcu_dereference(mdev->ldev->disk_conf)->disk_size;
+		rcu_read_unlock();
+
 		warn_if_differ_considerably(mdev, "lower level device sizes",
 			   p_size, drbd_get_max_capacity(mdev->ldev));
 		warn_if_differ_considerably(mdev, "user requested size",
-					    p_usize, mdev->ldev->dc.disk_size);
+					    p_usize, my_usize);
 
 		/* if this is the first connect, or an otherwise expected
 		 * param exchange, choose the minimum */
 		if (mdev->state.conn == C_WF_REPORT_PARAMS)
-			p_usize = min_not_zero((sector_t)mdev->ldev->dc.disk_size,
-					     p_usize);
-
-		my_usize = mdev->ldev->dc.disk_size;
-
-		if (mdev->ldev->dc.disk_size != p_usize) {
-			mdev->ldev->dc.disk_size = p_usize;
-			dev_info(DEV, "Peer sets u_size to %lu sectors\n",
-			     (unsigned long)mdev->ldev->dc.disk_size);
-		}
+			p_usize = min_not_zero(my_usize, p_usize);
 
 		/* Never shrink a device with usable data during connect.
 		   But allow online shrinking if we are connected. */
-		if (drbd_new_dev_size(mdev, mdev->ldev, 0) <
-		   drbd_get_capacity(mdev->this_bdev) &&
-		   mdev->state.disk >= D_OUTDATED &&
-		   mdev->state.conn < C_CONNECTED) {
+		if (drbd_new_dev_size(mdev, mdev->ldev, p_usize, 0) <
+		    drbd_get_capacity(mdev->this_bdev) &&
+		    mdev->state.disk >= D_OUTDATED &&
+		    mdev->state.conn < C_CONNECTED) {
 			dev_err(DEV, "The peer's disk size is too small!\n");
-			drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-			mdev->ldev->dc.disk_size = my_usize;
+			conn_request_state(mdev->tconn, NS(conn, C_DISCONNECTING), CS_HARD);
 			put_ldev(mdev);
-			return false;
+			return -EIO;
+		}
+
+		if (my_usize != p_usize) {
+			struct disk_conf *old_disk_conf, *new_disk_conf = NULL;
+
+			new_disk_conf = kzalloc(sizeof(struct disk_conf), GFP_KERNEL);
+			if (!new_disk_conf) {
+				dev_err(DEV, "Allocation of new disk_conf failed\n");
+				put_ldev(mdev);
+				return -ENOMEM;
+			}
+
+			mutex_lock(&mdev->tconn->conf_update);
+			old_disk_conf = mdev->ldev->disk_conf;
+			*new_disk_conf = *old_disk_conf;
+			new_disk_conf->disk_size = p_usize;
+
+			rcu_assign_pointer(mdev->ldev->disk_conf, new_disk_conf);
+			mutex_unlock(&mdev->tconn->conf_update);
+			synchronize_rcu();
+			kfree(old_disk_conf);
+
+			dev_info(DEV, "Peer sets u_size to %lu sectors\n",
+				 (unsigned long)my_usize);
 		}
+
 		put_ldev(mdev);
 	}
 
@@ -3031,7 +3609,7 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
 		dd = drbd_determine_dev_size(mdev, ddsf);
 		put_ldev(mdev);
 		if (dd == dev_size_error)
-			return false;
+			return -EIO;
 		drbd_md_sync(mdev);
 	} else {
 		/* I am diskless, need to accept the peer's size. */
@@ -3070,16 +3648,25 @@ static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
 		}
 	}
 
-	return true;
+	return 0;
 }
 
-static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
+static int receive_uuids(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	struct p_uuids *p = &mdev->data.rbuf.uuids;
+	struct drbd_conf *mdev;
+	struct p_uuids *p = pi->data;
 	u64 *p_uuid;
 	int i, updated_uuids = 0;
 
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return config_unknown_volume(tconn, pi);
+
 	p_uuid = kmalloc(sizeof(u64)*UI_EXTENDED_SIZE, GFP_NOIO);
+	if (!p_uuid) {
+		dev_err(DEV, "kmalloc of p_uuid failed\n");
+		return false;
+	}
 
 	for (i = UI_CURRENT; i < UI_EXTENDED_SIZE; i++)
 		p_uuid[i] = be64_to_cpu(p->uuid[i]);
@@ -3093,14 +3680,14 @@ static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
 	    (mdev->ed_uuid & ~((u64)1)) != (p_uuid[UI_CURRENT] & ~((u64)1))) {
 		dev_err(DEV, "Can only connect to data with current UUID=%016llX\n",
 		    (unsigned long long)mdev->ed_uuid);
-		drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-		return false;
+		conn_request_state(mdev->tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+		return -EIO;
 	}
 
 	if (get_ldev(mdev)) {
 		int skip_initial_sync =
 			mdev->state.conn == C_CONNECTED &&
-			mdev->agreed_pro_version >= 90 &&
+			mdev->tconn->agreed_pro_version >= 90 &&
 			mdev->ldev->md.uuid[UI_CURRENT] == UUID_JUST_CREATED &&
 			(p_uuid[UI_FLAGS] & 8);
 		if (skip_initial_sync) {
@@ -3127,14 +3714,15 @@ static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
 	   ongoing cluster wide state change is finished. That is important if
 	   we are primary and are detaching from our disk. We need to see the
 	   new disk state... */
-	wait_event(mdev->misc_wait, !test_bit(CLUSTER_ST_CHANGE, &mdev->flags));
+	mutex_lock(mdev->state_mutex);
+	mutex_unlock(mdev->state_mutex);
 	if (mdev->state.conn >= C_CONNECTED && mdev->state.disk < D_INCONSISTENT)
 		updated_uuids |= drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]);
 
 	if (updated_uuids)
 		drbd_print_uuids(mdev, "receiver updated UUIDs to");
 
-	return true;
+	return 0;
 }
 
 /**
@@ -3146,6 +3734,7 @@ static union drbd_state convert_state(union drbd_state ps)
 	union drbd_state ms;
 
 	static enum drbd_conns c_tab[] = {
+		[C_WF_REPORT_PARAMS] = C_WF_REPORT_PARAMS,
 		[C_CONNECTED] = C_CONNECTED,
 
 		[C_STARTING_SYNC_S] = C_STARTING_SYNC_T,
@@ -3164,43 +3753,77 @@ static union drbd_state convert_state(union drbd_state ps)
 	ms.disk = ps.pdsk;
 	ms.peer_isp = (ps.aftr_isp | ps.user_isp);
 
-	return ms;
+	return ms;
+}
+
+static int receive_req_state(struct drbd_tconn *tconn, struct packet_info *pi)
+{
+	struct drbd_conf *mdev;
+	struct p_req_state *p = pi->data;
+	union drbd_state mask, val;
+	enum drbd_state_rv rv;
+
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return -EIO;
+
+	mask.i = be32_to_cpu(p->mask);
+	val.i = be32_to_cpu(p->val);
+
+	if (test_bit(RESOLVE_CONFLICTS, &mdev->tconn->flags) &&
+	    mutex_is_locked(mdev->state_mutex)) {
+		drbd_send_sr_reply(mdev, SS_CONCURRENT_ST_CHG);
+		return 0;
+	}
+
+	mask = convert_state(mask);
+	val = convert_state(val);
+
+	rv = drbd_change_state(mdev, CS_VERBOSE, mask, val);
+	drbd_send_sr_reply(mdev, rv);
+
+	drbd_md_sync(mdev);
+
+	return 0;
 }
 
-static int receive_req_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
+static int receive_req_conn_state(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	struct p_req_state *p = &mdev->data.rbuf.req_state;
+	struct p_req_state *p = pi->data;
 	union drbd_state mask, val;
 	enum drbd_state_rv rv;
 
 	mask.i = be32_to_cpu(p->mask);
 	val.i = be32_to_cpu(p->val);
 
-	if (test_bit(DISCARD_CONCURRENT, &mdev->flags) &&
-	    test_bit(CLUSTER_ST_CHANGE, &mdev->flags)) {
-		drbd_send_sr_reply(mdev, SS_CONCURRENT_ST_CHG);
-		return true;
+	if (test_bit(RESOLVE_CONFLICTS, &tconn->flags) &&
+	    mutex_is_locked(&tconn->cstate_mutex)) {
+		conn_send_sr_reply(tconn, SS_CONCURRENT_ST_CHG);
+		return 0;
 	}
 
 	mask = convert_state(mask);
 	val = convert_state(val);
 
-	rv = drbd_change_state(mdev, CS_VERBOSE, mask, val);
-
-	drbd_send_sr_reply(mdev, rv);
-	drbd_md_sync(mdev);
+	rv = conn_request_state(tconn, mask, val, CS_VERBOSE | CS_LOCAL_ONLY | CS_IGN_OUTD_FAIL);
+	conn_send_sr_reply(tconn, rv);
 
-	return true;
+	return 0;
 }
 
-static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
+static int receive_state(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	struct p_state *p = &mdev->data.rbuf.state;
+	struct drbd_conf *mdev;
+	struct p_state *p = pi->data;
 	union drbd_state os, ns, peer_state;
 	enum drbd_disk_state real_peer_disk;
 	enum chg_state_flags cs_flags;
 	int rv;
 
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return config_unknown_volume(tconn, pi);
+
 	peer_state.i = be32_to_cpu(p->state);
 
 	real_peer_disk = peer_state.disk;
@@ -3209,16 +3832,16 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
 		dev_info(DEV, "real peer disk state = %s\n", drbd_disk_str(real_peer_disk));
 	}
 
-	spin_lock_irq(&mdev->req_lock);
+	spin_lock_irq(&mdev->tconn->req_lock);
  retry:
-	os = ns = mdev->state;
-	spin_unlock_irq(&mdev->req_lock);
+	os = ns = drbd_read_state(mdev);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
 	/* If some other part of the code (asender thread, timeout)
 	 * already decided to close the connection again,
 	 * we must not "re-establish" it here. */
 	if (os.conn <= C_TEAR_DOWN)
-		return false;
+		return -ECONNRESET;
 
 	/* If this is the "end of sync" confirmation, usually the peer disk
 	 * transitions from D_INCONSISTENT to D_UP_TO_DATE. For empty (0 bits
@@ -3246,10 +3869,18 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
 			 peer_state.conn == C_CONNECTED) {
 			if (drbd_bm_total_weight(mdev) <= mdev->rs_failed)
 				drbd_resync_finished(mdev);
-			return true;
+			return 0;
 		}
 	}
 
+	/* explicit verify finished notification, stop sector reached. */
+	if (os.conn == C_VERIFY_T && os.disk == D_UP_TO_DATE &&
+	    peer_state.conn == C_CONNECTED && real_peer_disk == D_UP_TO_DATE) {
+		ov_out_of_sync_print(mdev);
+		drbd_resync_finished(mdev);
+		return 0;
+	}
+
 	/* peer says his disk is inconsistent, while we think it is uptodate,
 	 * and this happens while the peer still thinks we have a sync going on,
 	 * but we think we are already done with the sync.
@@ -3298,17 +3929,17 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
 				peer_state.disk = D_DISKLESS;
 				real_peer_disk = D_DISKLESS;
 			} else {
-				if (test_and_clear_bit(CONN_DRY_RUN, &mdev->flags))
-					return false;
+				if (test_and_clear_bit(CONN_DRY_RUN, &mdev->tconn->flags))
+					return -EIO;
 				D_ASSERT(os.conn == C_WF_REPORT_PARAMS);
-				drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-				return false;
+				conn_request_state(mdev->tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+				return -EIO;
 			}
 		}
 	}
 
-	spin_lock_irq(&mdev->req_lock);
-	if (mdev->state.i != os.i)
+	spin_lock_irq(&mdev->tconn->req_lock);
+	if (os.i != drbd_read_state(mdev).i)
 		goto retry;
 	clear_bit(CONSIDER_RESYNC, &mdev->flags);
 	ns.peer = peer_state.role;
@@ -3317,25 +3948,25 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
 	if ((ns.conn == C_CONNECTED || ns.conn == C_WF_BITMAP_S) && ns.disk == D_NEGOTIATING)
 		ns.disk = mdev->new_state_tmp.disk;
 	cs_flags = CS_VERBOSE + (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED ? 0 : CS_HARD);
-	if (ns.pdsk == D_CONSISTENT && is_susp(ns) && ns.conn == C_CONNECTED && os.conn < C_CONNECTED &&
+	if (ns.pdsk == D_CONSISTENT && drbd_suspended(mdev) && ns.conn == C_CONNECTED && os.conn < C_CONNECTED &&
 	    test_bit(NEW_CUR_UUID, &mdev->flags)) {
-		/* Do not allow tl_restart(resend) for a rebooted peer. We can only allow this
+		/* Do not allow tl_restart(RESEND) for a rebooted peer. We can only allow this
 		   for temporal network outages! */
-		spin_unlock_irq(&mdev->req_lock);
+		spin_unlock_irq(&mdev->tconn->req_lock);
 		dev_err(DEV, "Aborting Connect, can not thaw IO with an only Consistent peer\n");
-		tl_clear(mdev);
+		tl_clear(mdev->tconn);
 		drbd_uuid_new_current(mdev);
 		clear_bit(NEW_CUR_UUID, &mdev->flags);
-		drbd_force_state(mdev, NS2(conn, C_PROTOCOL_ERROR, susp, 0));
-		return false;
+		conn_request_state(mdev->tconn, NS2(conn, C_PROTOCOL_ERROR, susp, 0), CS_HARD);
+		return -EIO;
 	}
 	rv = _drbd_set_state(mdev, ns, cs_flags, NULL);
-	ns = mdev->state;
-	spin_unlock_irq(&mdev->req_lock);
+	ns = drbd_read_state(mdev);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
 	if (rv < SS_SUCCESS) {
-		drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-		return false;
+		conn_request_state(mdev->tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+		return -EIO;
 	}
 
 	if (os.conn > C_WF_REPORT_PARAMS) {
@@ -3349,16 +3980,21 @@ static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
 		}
 	}
 
-	mdev->net_conf->want_lose = 0;
+	clear_bit(DISCARD_MY_DATA, &mdev->flags);
 
 	drbd_md_sync(mdev); /* update connected indicator, la_size, ... */
 
-	return true;
+	return 0;
 }
 
-static int receive_sync_uuid(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
+static int receive_sync_uuid(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	struct p_rs_uuid *p = &mdev->data.rbuf.rs_uuid;
+	struct drbd_conf *mdev;
+	struct p_rs_uuid *p = pi->data;
+
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return -EIO;
 
 	wait_event(mdev->misc_wait,
 		   mdev->state.conn == C_WF_SYNC_UUID ||
@@ -3381,7 +4017,7 @@ static int receive_sync_uuid(struct drbd_conf *mdev, enum drbd_packets cmd, unsi
 	} else
 		dev_err(DEV, "Ignoring SyncUUID packet!\n");
 
-	return true;
+	return 0;
 }
 
 /**
@@ -3391,27 +4027,27 @@ static int receive_sync_uuid(struct drbd_conf *mdev, enum drbd_packets cmd, unsi
  * code upon failure.
  */
 static int
-receive_bitmap_plain(struct drbd_conf *mdev, unsigned int data_size,
-		     unsigned long *buffer, struct bm_xfer_ctx *c)
+receive_bitmap_plain(struct drbd_conf *mdev, unsigned int size,
+		     unsigned long *p, struct bm_xfer_ctx *c)
 {
-	unsigned num_words = min_t(size_t, BM_PACKET_WORDS, c->bm_words - c->word_offset);
-	unsigned want = num_words * sizeof(long);
+	unsigned int data_size = DRBD_SOCKET_BUFFER_SIZE -
+				 drbd_header_size(mdev->tconn);
+	unsigned int num_words = min_t(size_t, data_size / sizeof(*p),
+				       c->bm_words - c->word_offset);
+	unsigned int want = num_words * sizeof(*p);
 	int err;
 
-	if (want != data_size) {
-		dev_err(DEV, "%s:want (%u) != data_size (%u)\n", __func__, want, data_size);
+	if (want != size) {
+		dev_err(DEV, "%s:want (%u) != size (%u)\n", __func__, want, size);
 		return -EIO;
 	}
 	if (want == 0)
 		return 0;
-	err = drbd_recv(mdev, buffer, want);
-	if (err != want) {
-		if (err >= 0)
-			err = -EIO;
+	err = drbd_recv_all(mdev->tconn, p, want);
+	if (err)
 		return err;
-	}
 
-	drbd_bm_merge_lel(mdev, c->word_offset, num_words, buffer);
+	drbd_bm_merge_lel(mdev, c->word_offset, num_words, p);
 
 	c->word_offset += num_words;
 	c->bit_offset = c->word_offset * BITS_PER_LONG;
@@ -3421,6 +4057,21 @@ receive_bitmap_plain(struct drbd_conf *mdev, unsigned int data_size,
 	return 1;
 }
 
+static enum drbd_bitmap_code dcbp_get_code(struct p_compressed_bm *p)
+{
+	return (enum drbd_bitmap_code)(p->encoding & 0x0f);
+}
+
+static int dcbp_get_start(struct p_compressed_bm *p)
+{
+	return (p->encoding & 0x80) != 0;
+}
+
+static int dcbp_get_pad_bits(struct p_compressed_bm *p)
+{
+	return (p->encoding >> 4) & 0x7;
+}
+
 /**
  * recv_bm_rle_bits
  *
@@ -3430,7 +4081,8 @@ receive_bitmap_plain(struct drbd_conf *mdev, unsigned int data_size,
 static int
 recv_bm_rle_bits(struct drbd_conf *mdev,
 		struct p_compressed_bm *p,
-		struct bm_xfer_ctx *c)
+		 struct bm_xfer_ctx *c,
+		 unsigned int len)
 {
 	struct bitstream bs;
 	u64 look_ahead;
@@ -3438,12 +4090,11 @@ recv_bm_rle_bits(struct drbd_conf *mdev,
 	u64 tmp;
 	unsigned long s = c->bit_offset;
 	unsigned long e;
-	int len = be16_to_cpu(p->head.length) - (sizeof(*p) - sizeof(p->head));
-	int toggle = DCBP_get_start(p);
+	int toggle = dcbp_get_start(p);
 	int have;
 	int bits;
 
-	bitstream_init(&bs, p->code, len, DCBP_get_pad_bits(p));
+	bitstream_init(&bs, p->code, len, dcbp_get_pad_bits(p));
 
 	bits = bitstream_get_bits(&bs, &look_ahead, 64);
 	if (bits < 0)
@@ -3495,17 +4146,18 @@ recv_bm_rle_bits(struct drbd_conf *mdev,
 static int
 decode_bitmap_c(struct drbd_conf *mdev,
 		struct p_compressed_bm *p,
-		struct bm_xfer_ctx *c)
+		struct bm_xfer_ctx *c,
+		unsigned int len)
 {
-	if (DCBP_get_code(p) == RLE_VLI_Bits)
-		return recv_bm_rle_bits(mdev, p, c);
+	if (dcbp_get_code(p) == RLE_VLI_Bits)
+		return recv_bm_rle_bits(mdev, p, c, len - sizeof(*p));
 
 	/* other variants had been implemented for evaluation,
 	 * but have been dropped as this one turned out to be "best"
 	 * during all our tests. */
 
 	dev_err(DEV, "receive_bitmap_c: unknown encoding %u\n", p->encoding);
-	drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
+	conn_request_state(mdev->tconn, NS(conn, C_PROTOCOL_ERROR), CS_HARD);
 	return -EIO;
 }
 
@@ -3513,11 +4165,13 @@ void INFO_bm_xfer_stats(struct drbd_conf *mdev,
 		const char *direction, struct bm_xfer_ctx *c)
 {
 	/* what would it take to transfer it "plaintext" */
-	unsigned plain = sizeof(struct p_header80) *
-		((c->bm_words+BM_PACKET_WORDS-1)/BM_PACKET_WORDS+1)
-		+ c->bm_words * sizeof(long);
-	unsigned total = c->bytes[0] + c->bytes[1];
-	unsigned r;
+	unsigned int header_size = drbd_header_size(mdev->tconn);
+	unsigned int data_size = DRBD_SOCKET_BUFFER_SIZE - header_size;
+	unsigned int plain =
+		header_size * (DIV_ROUND_UP(c->bm_words, data_size) + 1) +
+		c->bm_words * sizeof(unsigned long);
+	unsigned int total = c->bytes[0] + c->bytes[1];
+	unsigned int r;
 
 	/* total can not be zero. but just in case: */
 	if (total == 0)
@@ -3551,67 +4205,63 @@ void INFO_bm_xfer_stats(struct drbd_conf *mdev,
    in order to be agnostic to the 32 vs 64 bits issue.
 
    returns 0 on failure, 1 if we successfully received it. */
-static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
+static int receive_bitmap(struct drbd_tconn *tconn, struct packet_info *pi)
 {
+	struct drbd_conf *mdev;
 	struct bm_xfer_ctx c;
-	void *buffer;
 	int err;
-	int ok = false;
-	struct p_header80 *h = &mdev->data.rbuf.header.h80;
+
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return -EIO;
 
 	drbd_bm_lock(mdev, "receive bitmap", BM_LOCKED_SET_ALLOWED);
 	/* you are supposed to send additional out-of-sync information
 	 * if you actually set bits during this phase */
 
-	/* maybe we should use some per thread scratch page,
-	 * and allocate that during initial device creation? */
-	buffer	 = (unsigned long *) __get_free_page(GFP_NOIO);
-	if (!buffer) {
-		dev_err(DEV, "failed to allocate one page buffer in %s\n", __func__);
-		goto out;
-	}
-
 	c = (struct bm_xfer_ctx) {
 		.bm_bits = drbd_bm_bits(mdev),
 		.bm_words = drbd_bm_words(mdev),
 	};
 
 	for(;;) {
-		if (cmd == P_BITMAP) {
-			err = receive_bitmap_plain(mdev, data_size, buffer, &c);
-		} else if (cmd == P_COMPRESSED_BITMAP) {
+		if (pi->cmd == P_BITMAP)
+			err = receive_bitmap_plain(mdev, pi->size, pi->data, &c);
+		else if (pi->cmd == P_COMPRESSED_BITMAP) {
 			/* MAYBE: sanity check that we speak proto >= 90,
 			 * and the feature is enabled! */
-			struct p_compressed_bm *p;
+			struct p_compressed_bm *p = pi->data;
 
-			if (data_size > BM_PACKET_PAYLOAD_BYTES) {
+			if (pi->size > DRBD_SOCKET_BUFFER_SIZE - drbd_header_size(tconn)) {
 				dev_err(DEV, "ReportCBitmap packet too large\n");
+				err = -EIO;
 				goto out;
 			}
-			/* use the page buff */
-			p = buffer;
-			memcpy(p, h, sizeof(*h));
-			if (drbd_recv(mdev, p->head.payload, data_size) != data_size)
-				goto out;
-			if (data_size <= (sizeof(*p) - sizeof(p->head))) {
-				dev_err(DEV, "ReportCBitmap packet too small (l:%u)\n", data_size);
+			if (pi->size <= sizeof(*p)) {
+				dev_err(DEV, "ReportCBitmap packet too small (l:%u)\n", pi->size);
+				err = -EIO;
 				goto out;
 			}
-			err = decode_bitmap_c(mdev, p, &c);
+			err = drbd_recv_all(mdev->tconn, p, pi->size);
+			if (err)
+			       goto out;
+			err = decode_bitmap_c(mdev, p, &c, pi->size);
 		} else {
-			dev_warn(DEV, "receive_bitmap: cmd neither ReportBitMap nor ReportCBitMap (is 0x%x)", cmd);
+			dev_warn(DEV, "receive_bitmap: cmd neither ReportBitMap nor ReportCBitMap (is 0x%x)", pi->cmd);
+			err = -EIO;
 			goto out;
 		}
 
-		c.packets[cmd == P_BITMAP]++;
-		c.bytes[cmd == P_BITMAP] += sizeof(struct p_header80) + data_size;
+		c.packets[pi->cmd == P_BITMAP]++;
+		c.bytes[pi->cmd == P_BITMAP] += drbd_header_size(tconn) + pi->size;
 
 		if (err <= 0) {
 			if (err < 0)
 				goto out;
 			break;
 		}
-		if (!drbd_recv_header(mdev, &cmd, &data_size))
+		err = drbd_recv_header(mdev->tconn, pi);
+		if (err)
 			goto out;
 	}
 
@@ -3620,8 +4270,8 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne
 	if (mdev->state.conn == C_WF_BITMAP_T) {
 		enum drbd_state_rv rv;
 
-		ok = !drbd_send_bitmap(mdev);
-		if (!ok)
+		err = drbd_send_bitmap(mdev);
+		if (err)
 			goto out;
 		/* Omit CS_ORDERED with this state transition to avoid deadlocks. */
 		rv = _drbd_request_state(mdev, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE);
@@ -3632,47 +4282,40 @@ static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigne
 		dev_info(DEV, "unexpected cstate (%s) in receive_bitmap\n",
 		    drbd_conn_str(mdev->state.conn));
 	}
+	err = 0;
 
-	ok = true;
  out:
 	drbd_bm_unlock(mdev);
-	if (ok && mdev->state.conn == C_WF_BITMAP_S)
+	if (!err && mdev->state.conn == C_WF_BITMAP_S)
 		drbd_start_resync(mdev, C_SYNC_SOURCE);
-	free_page((unsigned long) buffer);
-	return ok;
+	return err;
 }
 
-static int receive_skip(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
+static int receive_skip(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	/* TODO zero copy sink :) */
-	static char sink[128];
-	int size, want, r;
+	conn_warn(tconn, "skipping unknown optional packet type %d, l: %d!\n",
+		 pi->cmd, pi->size);
 
-	dev_warn(DEV, "skipping unknown optional packet type %d, l: %d!\n",
-		 cmd, data_size);
-
-	size = data_size;
-	while (size > 0) {
-		want = min_t(int, size, sizeof(sink));
-		r = drbd_recv(mdev, sink, want);
-		ERR_IF(r <= 0) break;
-		size -= r;
-	}
-	return size == 0;
+	return ignore_remaining_packet(tconn, pi);
 }
 
-static int receive_UnplugRemote(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
+static int receive_UnplugRemote(struct drbd_tconn *tconn, struct packet_info *pi)
 {
 	/* Make sure we've acked all the TCP data associated
 	 * with the data requests being unplugged */
-	drbd_tcp_quickack(mdev->data.socket);
+	drbd_tcp_quickack(tconn->data.socket);
 
-	return true;
+	return 0;
 }
 
-static int receive_out_of_sync(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
+static int receive_out_of_sync(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	struct p_block_desc *p = &mdev->data.rbuf.block_desc;
+	struct drbd_conf *mdev;
+	struct p_block_desc *p = pi->data;
+
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return -EIO;
 
 	switch (mdev->state.conn) {
 	case C_WF_SYNC_UUID:
@@ -3686,15 +4329,13 @@ static int receive_out_of_sync(struct drbd_conf *mdev, enum drbd_packets cmd, un
 
 	drbd_set_out_of_sync(mdev, be64_to_cpu(p->sector), be32_to_cpu(p->blksize));
 
-	return true;
+	return 0;
 }
 
-typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, enum drbd_packets cmd, unsigned int to_receive);
-
 struct data_cmd {
 	int expect_payload;
 	size_t pkt_size;
-	drbd_cmd_handler_f function;
+	int (*fn)(struct drbd_tconn *, struct packet_info *);
 };
 
 static struct data_cmd drbd_cmd_handler[] = {
@@ -3702,13 +4343,13 @@ static struct data_cmd drbd_cmd_handler[] = {
 	[P_DATA_REPLY]	    = { 1, sizeof(struct p_data), receive_DataReply },
 	[P_RS_DATA_REPLY]   = { 1, sizeof(struct p_data), receive_RSDataReply } ,
 	[P_BARRIER]	    = { 0, sizeof(struct p_barrier), receive_Barrier } ,
-	[P_BITMAP]	    = { 1, sizeof(struct p_header80), receive_bitmap } ,
-	[P_COMPRESSED_BITMAP] = { 1, sizeof(struct p_header80), receive_bitmap } ,
-	[P_UNPLUG_REMOTE]   = { 0, sizeof(struct p_header80), receive_UnplugRemote },
+	[P_BITMAP]	    = { 1, 0, receive_bitmap } ,
+	[P_COMPRESSED_BITMAP] = { 1, 0, receive_bitmap } ,
+	[P_UNPLUG_REMOTE]   = { 0, 0, receive_UnplugRemote },
 	[P_DATA_REQUEST]    = { 0, sizeof(struct p_block_req), receive_DataRequest },
 	[P_RS_DATA_REQUEST] = { 0, sizeof(struct p_block_req), receive_DataRequest },
-	[P_SYNC_PARAM]	    = { 1, sizeof(struct p_header80), receive_SyncParam },
-	[P_SYNC_PARAM89]    = { 1, sizeof(struct p_header80), receive_SyncParam },
+	[P_SYNC_PARAM]	    = { 1, 0, receive_SyncParam },
+	[P_SYNC_PARAM89]    = { 1, 0, receive_SyncParam },
 	[P_PROTOCOL]        = { 1, sizeof(struct p_protocol), receive_protocol },
 	[P_UUIDS]	    = { 0, sizeof(struct p_uuids), receive_uuids },
 	[P_SIZES]	    = { 0, sizeof(struct p_sizes), receive_sizes },
@@ -3720,124 +4361,75 @@ static struct data_cmd drbd_cmd_handler[] = {
 	[P_CSUM_RS_REQUEST] = { 1, sizeof(struct p_block_req), receive_DataRequest },
 	[P_DELAY_PROBE]     = { 0, sizeof(struct p_delay_probe93), receive_skip },
 	[P_OUT_OF_SYNC]     = { 0, sizeof(struct p_block_desc), receive_out_of_sync },
-	/* anything missing from this table is in
-	 * the asender_tbl, see get_asender_cmd */
-	[P_MAX_CMD]	    = { 0, 0, NULL },
+	[P_CONN_ST_CHG_REQ] = { 0, sizeof(struct p_req_state), receive_req_conn_state },
+	[P_PROTOCOL_UPDATE] = { 1, sizeof(struct p_protocol), receive_protocol },
 };
 
-/* All handler functions that expect a sub-header get that sub-heder in
-   mdev->data.rbuf.header.head.payload.
-
-   Usually in mdev->data.rbuf.header.head the callback can find the usual
-   p_header, but they may not rely on that. Since there is also p_header95 !
- */
-
-static void drbdd(struct drbd_conf *mdev)
+static void drbdd(struct drbd_tconn *tconn)
 {
-	union p_header *header = &mdev->data.rbuf.header;
-	unsigned int packet_size;
-	enum drbd_packets cmd;
+	struct packet_info pi;
 	size_t shs; /* sub header size */
-	int rv;
+	int err;
 
-	while (get_t_state(&mdev->receiver) == Running) {
-		drbd_thread_current_set_cpu(mdev);
-		if (!drbd_recv_header(mdev, &cmd, &packet_size))
+	while (get_t_state(&tconn->receiver) == RUNNING) {
+		struct data_cmd *cmd;
+
+		drbd_thread_current_set_cpu(&tconn->receiver);
+		if (drbd_recv_header(tconn, &pi))
 			goto err_out;
 
-		if (unlikely(cmd >= P_MAX_CMD || !drbd_cmd_handler[cmd].function)) {
-			dev_err(DEV, "unknown packet type %d, l: %d!\n", cmd, packet_size);
+		cmd = &drbd_cmd_handler[pi.cmd];
+		if (unlikely(pi.cmd >= ARRAY_SIZE(drbd_cmd_handler) || !cmd->fn)) {
+			conn_err(tconn, "Unexpected data packet %s (0x%04x)",
+				 cmdname(pi.cmd), pi.cmd);
 			goto err_out;
 		}
 
-		shs = drbd_cmd_handler[cmd].pkt_size - sizeof(union p_header);
-		if (packet_size - shs > 0 && !drbd_cmd_handler[cmd].expect_payload) {
-			dev_err(DEV, "No payload expected %s l:%d\n", cmdname(cmd), packet_size);
+		shs = cmd->pkt_size;
+		if (pi.size > shs && !cmd->expect_payload) {
+			conn_err(tconn, "No payload expected %s l:%d\n",
+				 cmdname(pi.cmd), pi.size);
 			goto err_out;
 		}
 
 		if (shs) {
-			rv = drbd_recv(mdev, &header->h80.payload, shs);
-			if (unlikely(rv != shs)) {
-				if (!signal_pending(current))
-					dev_warn(DEV, "short read while reading sub header: rv=%d\n", rv);
+			err = drbd_recv_all_warn(tconn, pi.data, shs);
+			if (err)
 				goto err_out;
-			}
+			pi.size -= shs;
 		}
 
-		rv = drbd_cmd_handler[cmd].function(mdev, cmd, packet_size - shs);
-
-		if (unlikely(!rv)) {
-			dev_err(DEV, "error receiving %s, l: %d!\n",
-			    cmdname(cmd), packet_size);
+		err = cmd->fn(tconn, &pi);
+		if (err) {
+			conn_err(tconn, "error receiving %s, e: %d l: %d!\n",
+				 cmdname(pi.cmd), err, pi.size);
 			goto err_out;
 		}
 	}
+	return;
 
-	if (0) {
-	err_out:
-		drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
-	}
-	/* If we leave here, we probably want to update at least the
-	 * "Connected" indicator on stable storage. Do so explicitly here. */
-	drbd_md_sync(mdev);
+    err_out:
+	conn_request_state(tconn, NS(conn, C_PROTOCOL_ERROR), CS_HARD);
 }
 
-void drbd_flush_workqueue(struct drbd_conf *mdev)
+void conn_flush_workqueue(struct drbd_tconn *tconn)
 {
 	struct drbd_wq_barrier barr;
 
 	barr.w.cb = w_prev_work_done;
+	barr.w.tconn = tconn;
 	init_completion(&barr.done);
-	drbd_queue_work(&mdev->data.work, &barr.w);
+	drbd_queue_work(&tconn->sender_work, &barr.w);
 	wait_for_completion(&barr.done);
 }
 
-void drbd_free_tl_hash(struct drbd_conf *mdev)
-{
-	struct hlist_head *h;
-
-	spin_lock_irq(&mdev->req_lock);
-
-	if (!mdev->tl_hash || mdev->state.conn != C_STANDALONE) {
-		spin_unlock_irq(&mdev->req_lock);
-		return;
-	}
-	/* paranoia code */
-	for (h = mdev->ee_hash; h < mdev->ee_hash + mdev->ee_hash_s; h++)
-		if (h->first)
-			dev_err(DEV, "ASSERT FAILED ee_hash[%u].first == %p, expected NULL\n",
-				(int)(h - mdev->ee_hash), h->first);
-	kfree(mdev->ee_hash);
-	mdev->ee_hash = NULL;
-	mdev->ee_hash_s = 0;
-
-	/* We may not have had the chance to wait for all locally pending
-	 * application requests. The hlist_add_fake() prevents access after
-	 * free on master bio completion. */
-	for (h = mdev->tl_hash; h < mdev->tl_hash + mdev->tl_hash_s; h++) {
-		struct drbd_request *req;
-		struct hlist_node *pos, *n;
-		hlist_for_each_entry_safe(req, pos, n, h, collision) {
-			hlist_del_init(&req->collision);
-			hlist_add_fake(&req->collision);
-		}
-	}
-
-	kfree(mdev->tl_hash);
-	mdev->tl_hash = NULL;
-	mdev->tl_hash_s = 0;
-	spin_unlock_irq(&mdev->req_lock);
-}
-
-static void drbd_disconnect(struct drbd_conf *mdev)
+static void conn_disconnect(struct drbd_tconn *tconn)
 {
-	enum drbd_fencing_p fp;
-	union drbd_state os, ns;
-	int rv = SS_UNKNOWN_ERROR;
-	unsigned int i;
+	struct drbd_conf *mdev;
+	enum drbd_conns oc;
+	int vnr;
 
-	if (mdev->state.conn == C_STANDALONE)
+	if (tconn->cstate == C_STANDALONE)
 		return;
 
 	/* We are about to start the cleanup after connection loss.
@@ -3845,18 +4437,54 @@ static void drbd_disconnect(struct drbd_conf *mdev)
 	 * Usually we should be in some network failure state already,
 	 * but just in case we are not, we fix it up here.
 	 */
-	drbd_force_state(mdev, NS(conn, C_NETWORK_FAILURE));
+	conn_request_state(tconn, NS(conn, C_NETWORK_FAILURE), CS_HARD);
 
 	/* asender does not clean up anything. it must not interfere, either */
-	drbd_thread_stop(&mdev->asender);
-	drbd_free_sock(mdev);
+	drbd_thread_stop(&tconn->asender);
+	drbd_free_sock(tconn);
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+		kref_get(&mdev->kref);
+		rcu_read_unlock();
+		drbd_disconnected(mdev);
+		kref_put(&mdev->kref, &drbd_minor_destroy);
+		rcu_read_lock();
+	}
+	rcu_read_unlock();
+
+	if (!list_empty(&tconn->current_epoch->list))
+		conn_err(tconn, "ASSERTION FAILED: tconn->current_epoch->list not empty\n");
+	/* ok, no more ee's on the fly, it is safe to reset the epoch_size */
+	atomic_set(&tconn->current_epoch->epoch_size, 0);
+	tconn->send.seen_any_write_yet = false;
+
+	conn_info(tconn, "Connection closed\n");
+
+	if (conn_highest_role(tconn) == R_PRIMARY && conn_highest_pdsk(tconn) >= D_UNKNOWN)
+		conn_try_outdate_peer_async(tconn);
+
+	spin_lock_irq(&tconn->req_lock);
+	oc = tconn->cstate;
+	if (oc >= C_UNCONNECTED)
+		_conn_request_state(tconn, NS(conn, C_UNCONNECTED), CS_VERBOSE);
+
+	spin_unlock_irq(&tconn->req_lock);
+
+	if (oc == C_DISCONNECTING)
+		conn_request_state(tconn, NS(conn, C_STANDALONE), CS_VERBOSE | CS_HARD);
+}
+
+static int drbd_disconnected(struct drbd_conf *mdev)
+{
+	unsigned int i;
 
 	/* wait for current activity to cease. */
-	spin_lock_irq(&mdev->req_lock);
+	spin_lock_irq(&mdev->tconn->req_lock);
 	_drbd_wait_ee_list_empty(mdev, &mdev->active_ee);
 	_drbd_wait_ee_list_empty(mdev, &mdev->sync_ee);
 	_drbd_wait_ee_list_empty(mdev, &mdev->read_ee);
-	spin_unlock_irq(&mdev->req_lock);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
 	/* We do not have data structures that would allow us to
 	 * get the rs_pending_cnt down to 0 again.
@@ -3874,7 +4502,6 @@ static void drbd_disconnect(struct drbd_conf *mdev)
 	atomic_set(&mdev->rs_pending_cnt, 0);
 	wake_up(&mdev->misc_wait);
 
-	/* make sure syncer is stopped and w_resume_next_sg queued */
 	del_timer_sync(&mdev->resync_timer);
 	resync_timer_fn((unsigned long)mdev);
 
@@ -3883,50 +4510,25 @@ static void drbd_disconnect(struct drbd_conf *mdev)
 	 * to be "canceled" */
 	drbd_flush_workqueue(mdev);
 
-	/* This also does reclaim_net_ee().  If we do this too early, we might
-	 * miss some resync ee and pages.*/
-	drbd_process_done_ee(mdev);
+	drbd_finish_peer_reqs(mdev);
+
+	/* This second workqueue flush is necessary, since drbd_finish_peer_reqs()
+	   might have issued a work again. The one before drbd_finish_peer_reqs() is
+	   necessary to reclain net_ee in drbd_finish_peer_reqs(). */
+	drbd_flush_workqueue(mdev);
+
+	/* need to do it again, drbd_finish_peer_reqs() may have populated it
+	 * again via drbd_try_clear_on_disk_bm(). */
+	drbd_rs_cancel_all(mdev);
 
 	kfree(mdev->p_uuid);
 	mdev->p_uuid = NULL;
 
-	if (!is_susp(mdev->state))
-		tl_clear(mdev);
-
-	dev_info(DEV, "Connection closed\n");
+	if (!drbd_suspended(mdev))
+		tl_clear(mdev->tconn);
 
 	drbd_md_sync(mdev);
 
-	fp = FP_DONT_CARE;
-	if (get_ldev(mdev)) {
-		fp = mdev->ldev->dc.fencing;
-		put_ldev(mdev);
-	}
-
-	if (mdev->state.role == R_PRIMARY && fp >= FP_RESOURCE && mdev->state.pdsk >= D_UNKNOWN)
-		drbd_try_outdate_peer_async(mdev);
-
-	spin_lock_irq(&mdev->req_lock);
-	os = mdev->state;
-	if (os.conn >= C_UNCONNECTED) {
-		/* Do not restart in case we are C_DISCONNECTING */
-		ns = os;
-		ns.conn = C_UNCONNECTED;
-		rv = _drbd_set_state(mdev, ns, CS_VERBOSE, NULL);
-	}
-	spin_unlock_irq(&mdev->req_lock);
-
-	if (os.conn == C_DISCONNECTING) {
-		wait_event(mdev->net_cnt_wait, atomic_read(&mdev->net_cnt) == 0);
-
-		crypto_free_hash(mdev->cram_hmac_tfm);
-		mdev->cram_hmac_tfm = NULL;
-
-		kfree(mdev->net_conf);
-		mdev->net_conf = NULL;
-		drbd_request_state(mdev, NS(conn, C_STANDALONE));
-	}
-
 	/* serialize with bitmap writeout triggered by the state change,
 	 * if any. */
 	wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags));
@@ -3938,7 +4540,7 @@ static void drbd_disconnect(struct drbd_conf *mdev)
 	 * Actually we don't care for exactly when the network stack does its
 	 * put_page(), but release our reference on these pages right here.
 	 */
-	i = drbd_release_ee(mdev, &mdev->net_ee);
+	i = drbd_free_peer_reqs(mdev, &mdev->net_ee);
 	if (i)
 		dev_info(DEV, "net_ee not empty, killed %u entries\n", i);
 	i = atomic_read(&mdev->pp_in_use_by_net);
@@ -3953,9 +4555,7 @@ static void drbd_disconnect(struct drbd_conf *mdev)
 	D_ASSERT(list_empty(&mdev->sync_ee));
 	D_ASSERT(list_empty(&mdev->done_ee));
 
-	/* ok, no more ee's on the fly, it is safe to reset the epoch_size */
-	atomic_set(&mdev->current_epoch->epoch_size, 0);
-	D_ASSERT(list_empty(&mdev->current_epoch->list));
+	return 0;
 }
 
 /*
@@ -3967,29 +4567,19 @@ static void drbd_disconnect(struct drbd_conf *mdev)
  *
  * for now, they are expected to be zero, but ignored.
  */
-static int drbd_send_handshake(struct drbd_conf *mdev)
+static int drbd_send_features(struct drbd_tconn *tconn)
 {
-	/* ASSERT current == mdev->receiver ... */
-	struct p_handshake *p = &mdev->data.sbuf.handshake;
-	int ok;
-
-	if (mutex_lock_interruptible(&mdev->data.mutex)) {
-		dev_err(DEV, "interrupted during initial handshake\n");
-		return 0; /* interrupted. not ok. */
-	}
-
-	if (mdev->data.socket == NULL) {
-		mutex_unlock(&mdev->data.mutex);
-		return 0;
-	}
+	struct drbd_socket *sock;
+	struct p_connection_features *p;
 
+	sock = &tconn->data;
+	p = conn_prepare_command(tconn, sock);
+	if (!p)
+		return -EIO;
 	memset(p, 0, sizeof(*p));
 	p->protocol_min = cpu_to_be32(PRO_VERSION_MIN);
 	p->protocol_max = cpu_to_be32(PRO_VERSION_MAX);
-	ok = _drbd_send_cmd( mdev, mdev->data.socket, P_HAND_SHAKE,
-			     (struct p_header80 *)p, sizeof(*p), 0 );
-	mutex_unlock(&mdev->data.mutex);
-	return ok;
+	return conn_send_command(tconn, sock, P_CONNECTION_FEATURES, sizeof(*p), NULL, 0);
 }
 
 /*
@@ -3999,42 +4589,38 @@ static int drbd_send_handshake(struct drbd_conf *mdev)
  *  -1 peer talks different language,
  *     no point in trying again, please go standalone.
  */
-static int drbd_do_handshake(struct drbd_conf *mdev)
+static int drbd_do_features(struct drbd_tconn *tconn)
 {
-	/* ASSERT current == mdev->receiver ... */
-	struct p_handshake *p = &mdev->data.rbuf.handshake;
-	const int expect = sizeof(struct p_handshake) - sizeof(struct p_header80);
-	unsigned int length;
-	enum drbd_packets cmd;
-	int rv;
+	/* ASSERT current == tconn->receiver ... */
+	struct p_connection_features *p;
+	const int expect = sizeof(struct p_connection_features);
+	struct packet_info pi;
+	int err;
 
-	rv = drbd_send_handshake(mdev);
-	if (!rv)
+	err = drbd_send_features(tconn);
+	if (err)
 		return 0;
 
-	rv = drbd_recv_header(mdev, &cmd, &length);
-	if (!rv)
+	err = drbd_recv_header(tconn, &pi);
+	if (err)
 		return 0;
 
-	if (cmd != P_HAND_SHAKE) {
-		dev_err(DEV, "expected HandShake packet, received: %s (0x%04x)\n",
-		     cmdname(cmd), cmd);
+	if (pi.cmd != P_CONNECTION_FEATURES) {
+		conn_err(tconn, "expected ConnectionFeatures packet, received: %s (0x%04x)\n",
+			 cmdname(pi.cmd), pi.cmd);
 		return -1;
 	}
 
-	if (length != expect) {
-		dev_err(DEV, "expected HandShake length: %u, received: %u\n",
-		     expect, length);
+	if (pi.size != expect) {
+		conn_err(tconn, "expected ConnectionFeatures length: %u, received: %u\n",
+		     expect, pi.size);
 		return -1;
 	}
 
-	rv = drbd_recv(mdev, &p->head.payload, expect);
-
-	if (rv != expect) {
-		if (!signal_pending(current))
-			dev_warn(DEV, "short read receiving handshake packet: l=%u\n", rv);
+	p = pi.data;
+	err = drbd_recv_all_warn(tconn, p, expect);
+	if (err)
 		return 0;
-	}
 
 	p->protocol_min = be32_to_cpu(p->protocol_min);
 	p->protocol_max = be32_to_cpu(p->protocol_max);
@@ -4045,15 +4631,15 @@ static int drbd_do_handshake(struct drbd_conf *mdev)
 	    PRO_VERSION_MIN > p->protocol_max)
 		goto incompat;
 
-	mdev->agreed_pro_version = min_t(int, PRO_VERSION_MAX, p->protocol_max);
+	tconn->agreed_pro_version = min_t(int, PRO_VERSION_MAX, p->protocol_max);
 
-	dev_info(DEV, "Handshake successful: "
-	     "Agreed network protocol version %d\n", mdev->agreed_pro_version);
+	conn_info(tconn, "Handshake successful: "
+	     "Agreed network protocol version %d\n", tconn->agreed_pro_version);
 
 	return 1;
 
  incompat:
-	dev_err(DEV, "incompatible DRBD dialects: "
+	conn_err(tconn, "incompatible DRBD dialects: "
 	    "I support %d-%d, peer supports %d-%d\n",
 	    PRO_VERSION_MIN, PRO_VERSION_MAX,
 	    p->protocol_min, p->protocol_max);
@@ -4061,7 +4647,7 @@ static int drbd_do_handshake(struct drbd_conf *mdev)
 }
 
 #if !defined(CONFIG_CRYPTO_HMAC) && !defined(CONFIG_CRYPTO_HMAC_MODULE)
-static int drbd_do_auth(struct drbd_conf *mdev)
+static int drbd_do_auth(struct drbd_tconn *tconn)
 {
 	dev_err(DEV, "This kernel was build without CONFIG_CRYPTO_HMAC.\n");
 	dev_err(DEV, "You need to disable 'cram-hmac-alg' in drbd.conf.\n");
@@ -4076,121 +4662,139 @@ static int drbd_do_auth(struct drbd_conf *mdev)
 	-1 - auth failed, don't try again.
 */
 
-static int drbd_do_auth(struct drbd_conf *mdev)
+static int drbd_do_auth(struct drbd_tconn *tconn)
 {
+	struct drbd_socket *sock;
 	char my_challenge[CHALLENGE_LEN];  /* 64 Bytes... */
 	struct scatterlist sg;
 	char *response = NULL;
 	char *right_response = NULL;
 	char *peers_ch = NULL;
-	unsigned int key_len = strlen(mdev->net_conf->shared_secret);
+	unsigned int key_len;
+	char secret[SHARED_SECRET_MAX]; /* 64 byte */
 	unsigned int resp_size;
 	struct hash_desc desc;
-	enum drbd_packets cmd;
-	unsigned int length;
-	int rv;
+	struct packet_info pi;
+	struct net_conf *nc;
+	int err, rv;
+
+	/* FIXME: Put the challenge/response into the preallocated socket buffer.  */
+
+	rcu_read_lock();
+	nc = rcu_dereference(tconn->net_conf);
+	key_len = strlen(nc->shared_secret);
+	memcpy(secret, nc->shared_secret, key_len);
+	rcu_read_unlock();
 
-	desc.tfm = mdev->cram_hmac_tfm;
+	desc.tfm = tconn->cram_hmac_tfm;
 	desc.flags = 0;
 
-	rv = crypto_hash_setkey(mdev->cram_hmac_tfm,
-				(u8 *)mdev->net_conf->shared_secret, key_len);
+	rv = crypto_hash_setkey(tconn->cram_hmac_tfm, (u8 *)secret, key_len);
 	if (rv) {
-		dev_err(DEV, "crypto_hash_setkey() failed with %d\n", rv);
+		conn_err(tconn, "crypto_hash_setkey() failed with %d\n", rv);
 		rv = -1;
 		goto fail;
 	}
 
 	get_random_bytes(my_challenge, CHALLENGE_LEN);
 
-	rv = drbd_send_cmd2(mdev, P_AUTH_CHALLENGE, my_challenge, CHALLENGE_LEN);
+	sock = &tconn->data;
+	if (!conn_prepare_command(tconn, sock)) {
+		rv = 0;
+		goto fail;
+	}
+	rv = !conn_send_command(tconn, sock, P_AUTH_CHALLENGE, 0,
+				my_challenge, CHALLENGE_LEN);
 	if (!rv)
 		goto fail;
 
-	rv = drbd_recv_header(mdev, &cmd, &length);
-	if (!rv)
+	err = drbd_recv_header(tconn, &pi);
+	if (err) {
+		rv = 0;
 		goto fail;
+	}
 
-	if (cmd != P_AUTH_CHALLENGE) {
-		dev_err(DEV, "expected AuthChallenge packet, received: %s (0x%04x)\n",
-		    cmdname(cmd), cmd);
+	if (pi.cmd != P_AUTH_CHALLENGE) {
+		conn_err(tconn, "expected AuthChallenge packet, received: %s (0x%04x)\n",
+			 cmdname(pi.cmd), pi.cmd);
 		rv = 0;
 		goto fail;
 	}
 
-	if (length > CHALLENGE_LEN * 2) {
-		dev_err(DEV, "expected AuthChallenge payload too big.\n");
+	if (pi.size > CHALLENGE_LEN * 2) {
+		conn_err(tconn, "expected AuthChallenge payload too big.\n");
 		rv = -1;
 		goto fail;
 	}
 
-	peers_ch = kmalloc(length, GFP_NOIO);
+	peers_ch = kmalloc(pi.size, GFP_NOIO);
 	if (peers_ch == NULL) {
-		dev_err(DEV, "kmalloc of peers_ch failed\n");
+		conn_err(tconn, "kmalloc of peers_ch failed\n");
 		rv = -1;
 		goto fail;
 	}
 
-	rv = drbd_recv(mdev, peers_ch, length);
-
-	if (rv != length) {
-		if (!signal_pending(current))
-			dev_warn(DEV, "short read AuthChallenge: l=%u\n", rv);
+	err = drbd_recv_all_warn(tconn, peers_ch, pi.size);
+	if (err) {
 		rv = 0;
 		goto fail;
 	}
 
-	resp_size = crypto_hash_digestsize(mdev->cram_hmac_tfm);
+	resp_size = crypto_hash_digestsize(tconn->cram_hmac_tfm);
 	response = kmalloc(resp_size, GFP_NOIO);
 	if (response == NULL) {
-		dev_err(DEV, "kmalloc of response failed\n");
+		conn_err(tconn, "kmalloc of response failed\n");
 		rv = -1;
 		goto fail;
 	}
 
 	sg_init_table(&sg, 1);
-	sg_set_buf(&sg, peers_ch, length);
+	sg_set_buf(&sg, peers_ch, pi.size);
 
 	rv = crypto_hash_digest(&desc, &sg, sg.length, response);
 	if (rv) {
-		dev_err(DEV, "crypto_hash_digest() failed with %d\n", rv);
+		conn_err(tconn, "crypto_hash_digest() failed with %d\n", rv);
 		rv = -1;
 		goto fail;
 	}
 
-	rv = drbd_send_cmd2(mdev, P_AUTH_RESPONSE, response, resp_size);
-	if (!rv)
+	if (!conn_prepare_command(tconn, sock)) {
+		rv = 0;
 		goto fail;
-
-	rv = drbd_recv_header(mdev, &cmd, &length);
+	}
+	rv = !conn_send_command(tconn, sock, P_AUTH_RESPONSE, 0,
+				response, resp_size);
 	if (!rv)
 		goto fail;
 
-	if (cmd != P_AUTH_RESPONSE) {
-		dev_err(DEV, "expected AuthResponse packet, received: %s (0x%04x)\n",
-			cmdname(cmd), cmd);
+	err = drbd_recv_header(tconn, &pi);
+	if (err) {
 		rv = 0;
 		goto fail;
 	}
 
-	if (length != resp_size) {
-		dev_err(DEV, "expected AuthResponse payload of wrong size\n");
+	if (pi.cmd != P_AUTH_RESPONSE) {
+		conn_err(tconn, "expected AuthResponse packet, received: %s (0x%04x)\n",
+			 cmdname(pi.cmd), pi.cmd);
 		rv = 0;
 		goto fail;
 	}
 
-	rv = drbd_recv(mdev, response , resp_size);
+	if (pi.size != resp_size) {
+		conn_err(tconn, "expected AuthResponse payload of wrong size\n");
+		rv = 0;
+		goto fail;
+	}
 
-	if (rv != resp_size) {
-		if (!signal_pending(current))
-			dev_warn(DEV, "short read receiving AuthResponse: l=%u\n", rv);
+	err = drbd_recv_all_warn(tconn, response , resp_size);
+	if (err) {
 		rv = 0;
 		goto fail;
 	}
 
 	right_response = kmalloc(resp_size, GFP_NOIO);
 	if (right_response == NULL) {
-		dev_err(DEV, "kmalloc of right_response failed\n");
+		conn_err(tconn, "kmalloc of right_response failed\n");
 		rv = -1;
 		goto fail;
 	}
@@ -4199,7 +4803,7 @@ static int drbd_do_auth(struct drbd_conf *mdev)
 
 	rv = crypto_hash_digest(&desc, &sg, sg.length, right_response);
 	if (rv) {
-		dev_err(DEV, "crypto_hash_digest() failed with %d\n", rv);
+		conn_err(tconn, "crypto_hash_digest() failed with %d\n", rv);
 		rv = -1;
 		goto fail;
 	}
@@ -4207,8 +4811,8 @@ static int drbd_do_auth(struct drbd_conf *mdev)
 	rv = !memcmp(response, right_response, resp_size);
 
 	if (rv)
-		dev_info(DEV, "Peer authenticated using %d bytes of '%s' HMAC\n",
-		     resp_size, mdev->net_conf->cram_hmac_alg);
+		conn_info(tconn, "Peer authenticated using %d bytes HMAC\n",
+		     resp_size);
 	else
 		rv = -1;
 
@@ -4223,82 +4827,106 @@ static int drbd_do_auth(struct drbd_conf *mdev)
 
 int drbdd_init(struct drbd_thread *thi)
 {
-	struct drbd_conf *mdev = thi->mdev;
-	unsigned int minor = mdev_to_minor(mdev);
+	struct drbd_tconn *tconn = thi->tconn;
 	int h;
 
-	sprintf(current->comm, "drbd%d_receiver", minor);
-
-	dev_info(DEV, "receiver (re)started\n");
+	conn_info(tconn, "receiver (re)started\n");
 
 	do {
-		h = drbd_connect(mdev);
+		h = conn_connect(tconn);
 		if (h == 0) {
-			drbd_disconnect(mdev);
+			conn_disconnect(tconn);
 			schedule_timeout_interruptible(HZ);
 		}
 		if (h == -1) {
-			dev_warn(DEV, "Discarding network configuration.\n");
-			drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
+			conn_warn(tconn, "Discarding network configuration.\n");
+			conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_HARD);
 		}
 	} while (h == 0);
 
-	if (h > 0) {
-		if (get_net_conf(mdev)) {
-			drbdd(mdev);
-			put_net_conf(mdev);
-		}
-	}
+	if (h > 0)
+		drbdd(tconn);
 
-	drbd_disconnect(mdev);
+	conn_disconnect(tconn);
 
-	dev_info(DEV, "receiver terminated\n");
+	conn_info(tconn, "receiver terminated\n");
 	return 0;
 }
 
 /* ********* acknowledge sender ******** */
 
-static int got_RqSReply(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_conn_RqSReply(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	struct p_req_state_reply *p = (struct p_req_state_reply *)h;
+	struct p_req_state_reply *p = pi->data;
+	int retcode = be32_to_cpu(p->retcode);
+
+	if (retcode >= SS_SUCCESS) {
+		set_bit(CONN_WD_ST_CHG_OKAY, &tconn->flags);
+	} else {
+		set_bit(CONN_WD_ST_CHG_FAIL, &tconn->flags);
+		conn_err(tconn, "Requested state change failed by peer: %s (%d)\n",
+			 drbd_set_st_err_str(retcode), retcode);
+	}
+	wake_up(&tconn->ping_wait);
+
+	return 0;
+}
 
+static int got_RqSReply(struct drbd_tconn *tconn, struct packet_info *pi)
+{
+	struct drbd_conf *mdev;
+	struct p_req_state_reply *p = pi->data;
 	int retcode = be32_to_cpu(p->retcode);
 
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return -EIO;
+
+	if (test_bit(CONN_WD_ST_CHG_REQ, &tconn->flags)) {
+		D_ASSERT(tconn->agreed_pro_version < 100);
+		return got_conn_RqSReply(tconn, pi);
+	}
+
 	if (retcode >= SS_SUCCESS) {
 		set_bit(CL_ST_CHG_SUCCESS, &mdev->flags);
 	} else {
 		set_bit(CL_ST_CHG_FAIL, &mdev->flags);
 		dev_err(DEV, "Requested state change failed by peer: %s (%d)\n",
-		    drbd_set_st_err_str(retcode), retcode);
+			drbd_set_st_err_str(retcode), retcode);
 	}
 	wake_up(&mdev->state_wait);
 
-	return true;
+	return 0;
 }
 
-static int got_Ping(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_Ping(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	return drbd_send_ping_ack(mdev);
+	return drbd_send_ping_ack(tconn);
 
 }
 
-static int got_PingAck(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_PingAck(struct drbd_tconn *tconn, struct packet_info *pi)
 {
 	/* restore idle timeout */
-	mdev->meta.socket->sk->sk_rcvtimeo = mdev->net_conf->ping_int*HZ;
-	if (!test_and_set_bit(GOT_PING_ACK, &mdev->flags))
-		wake_up(&mdev->misc_wait);
+	tconn->meta.socket->sk->sk_rcvtimeo = tconn->net_conf->ping_int*HZ;
+	if (!test_and_set_bit(GOT_PING_ACK, &tconn->flags))
+		wake_up(&tconn->ping_wait);
 
-	return true;
+	return 0;
 }
 
-static int got_IsInSync(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_IsInSync(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	struct p_block_ack *p = (struct p_block_ack *)h;
+	struct drbd_conf *mdev;
+	struct p_block_ack *p = pi->data;
 	sector_t sector = be64_to_cpu(p->sector);
 	int blksize = be32_to_cpu(p->blksize);
 
-	D_ASSERT(mdev->agreed_pro_version >= 89);
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return -EIO;
+
+	D_ASSERT(mdev->tconn->agreed_pro_version >= 89);
 
 	update_peer_seq(mdev, be32_to_cpu(p->seq_num));
 
@@ -4312,162 +4940,139 @@ static int got_IsInSync(struct drbd_conf *mdev, struct p_header80 *h)
 	dec_rs_pending(mdev);
 	atomic_add(blksize >> 9, &mdev->rs_sect_in);
 
-	return true;
-}
-
-/* when we receive the ACK for a write request,
- * verify that we actually know about it */
-static struct drbd_request *_ack_id_to_req(struct drbd_conf *mdev,
-	u64 id, sector_t sector)
-{
-	struct hlist_head *slot = tl_hash_slot(mdev, sector);
-	struct hlist_node *n;
-	struct drbd_request *req;
-
-	hlist_for_each_entry(req, n, slot, collision) {
-		if ((unsigned long)req == (unsigned long)id) {
-			if (req->sector != sector) {
-				dev_err(DEV, "_ack_id_to_req: found req %p but it has "
-				    "wrong sector (%llus versus %llus)\n", req,
-				    (unsigned long long)req->sector,
-				    (unsigned long long)sector);
-				break;
-			}
-			return req;
-		}
-	}
-	return NULL;
+	return 0;
 }
 
-typedef struct drbd_request *(req_validator_fn)
-	(struct drbd_conf *mdev, u64 id, sector_t sector);
-
-static int validate_req_change_req_state(struct drbd_conf *mdev,
-	u64 id, sector_t sector, req_validator_fn validator,
-	const char *func, enum drbd_req_event what)
+static int
+validate_req_change_req_state(struct drbd_conf *mdev, u64 id, sector_t sector,
+			      struct rb_root *root, const char *func,
+			      enum drbd_req_event what, bool missing_ok)
 {
 	struct drbd_request *req;
 	struct bio_and_error m;
 
-	spin_lock_irq(&mdev->req_lock);
-	req = validator(mdev, id, sector);
+	spin_lock_irq(&mdev->tconn->req_lock);
+	req = find_request(mdev, root, id, sector, missing_ok, func);
 	if (unlikely(!req)) {
-		spin_unlock_irq(&mdev->req_lock);
-
-		dev_err(DEV, "%s: failed to find req %p, sector %llus\n", func,
-			(void *)(unsigned long)id, (unsigned long long)sector);
-		return false;
+		spin_unlock_irq(&mdev->tconn->req_lock);
+		return -EIO;
 	}
 	__req_mod(req, what, &m);
-	spin_unlock_irq(&mdev->req_lock);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
 	if (m.bio)
 		complete_master_bio(mdev, &m);
-	return true;
+	return 0;
 }
 
-static int got_BlockAck(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_BlockAck(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	struct p_block_ack *p = (struct p_block_ack *)h;
+	struct drbd_conf *mdev;
+	struct p_block_ack *p = pi->data;
 	sector_t sector = be64_to_cpu(p->sector);
 	int blksize = be32_to_cpu(p->blksize);
 	enum drbd_req_event what;
 
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return -EIO;
+
 	update_peer_seq(mdev, be32_to_cpu(p->seq_num));
 
-	if (is_syncer_block_id(p->block_id)) {
+	if (p->block_id == ID_SYNCER) {
 		drbd_set_in_sync(mdev, sector, blksize);
 		dec_rs_pending(mdev);
-		return true;
+		return 0;
 	}
-	switch (be16_to_cpu(h->command)) {
+	switch (pi->cmd) {
 	case P_RS_WRITE_ACK:
-		D_ASSERT(mdev->net_conf->wire_protocol == DRBD_PROT_C);
-		what = write_acked_by_peer_and_sis;
+		what = WRITE_ACKED_BY_PEER_AND_SIS;
 		break;
 	case P_WRITE_ACK:
-		D_ASSERT(mdev->net_conf->wire_protocol == DRBD_PROT_C);
-		what = write_acked_by_peer;
+		what = WRITE_ACKED_BY_PEER;
 		break;
 	case P_RECV_ACK:
-		D_ASSERT(mdev->net_conf->wire_protocol == DRBD_PROT_B);
-		what = recv_acked_by_peer;
+		what = RECV_ACKED_BY_PEER;
 		break;
-	case P_DISCARD_ACK:
-		D_ASSERT(mdev->net_conf->wire_protocol == DRBD_PROT_C);
-		what = conflict_discarded_by_peer;
+	case P_SUPERSEDED:
+		what = CONFLICT_RESOLVED;
+		break;
+	case P_RETRY_WRITE:
+		what = POSTPONE_WRITE;
 		break;
 	default:
-		D_ASSERT(0);
-		return false;
+		BUG();
 	}
 
 	return validate_req_change_req_state(mdev, p->block_id, sector,
-		_ack_id_to_req, __func__ , what);
+					     &mdev->write_requests, __func__,
+					     what, false);
 }
 
-static int got_NegAck(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_NegAck(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	struct p_block_ack *p = (struct p_block_ack *)h;
+	struct drbd_conf *mdev;
+	struct p_block_ack *p = pi->data;
 	sector_t sector = be64_to_cpu(p->sector);
 	int size = be32_to_cpu(p->blksize);
-	struct drbd_request *req;
-	struct bio_and_error m;
+	int err;
+
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return -EIO;
 
 	update_peer_seq(mdev, be32_to_cpu(p->seq_num));
 
-	if (is_syncer_block_id(p->block_id)) {
+	if (p->block_id == ID_SYNCER) {
 		dec_rs_pending(mdev);
 		drbd_rs_failed_io(mdev, sector, size);
-		return true;
+		return 0;
 	}
 
-	spin_lock_irq(&mdev->req_lock);
-	req = _ack_id_to_req(mdev, p->block_id, sector);
-	if (!req) {
-		spin_unlock_irq(&mdev->req_lock);
-		if (mdev->net_conf->wire_protocol == DRBD_PROT_A ||
-		    mdev->net_conf->wire_protocol == DRBD_PROT_B) {
-			/* Protocol A has no P_WRITE_ACKs, but has P_NEG_ACKs.
-			   The master bio might already be completed, therefore the
-			   request is no longer in the collision hash.
-			   => Do not try to validate block_id as request. */
-			/* In Protocol B we might already have got a P_RECV_ACK
-			   but then get a P_NEG_ACK after wards. */
-			drbd_set_out_of_sync(mdev, sector, size);
-			return true;
-		} else {
-			dev_err(DEV, "%s: failed to find req %p, sector %llus\n", __func__,
-				(void *)(unsigned long)p->block_id, (unsigned long long)sector);
-			return false;
-		}
+	err = validate_req_change_req_state(mdev, p->block_id, sector,
+					    &mdev->write_requests, __func__,
+					    NEG_ACKED, true);
+	if (err) {
+		/* Protocol A has no P_WRITE_ACKs, but has P_NEG_ACKs.
+		   The master bio might already be completed, therefore the
+		   request is no longer in the collision hash. */
+		/* In Protocol B we might already have got a P_RECV_ACK
+		   but then get a P_NEG_ACK afterwards. */
+		drbd_set_out_of_sync(mdev, sector, size);
 	}
-	__req_mod(req, neg_acked, &m);
-	spin_unlock_irq(&mdev->req_lock);
-
-	if (m.bio)
-		complete_master_bio(mdev, &m);
-	return true;
+	return 0;
 }
 
-static int got_NegDReply(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_NegDReply(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	struct p_block_ack *p = (struct p_block_ack *)h;
+	struct drbd_conf *mdev;
+	struct p_block_ack *p = pi->data;
 	sector_t sector = be64_to_cpu(p->sector);
 
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return -EIO;
+
 	update_peer_seq(mdev, be32_to_cpu(p->seq_num));
-	dev_err(DEV, "Got NegDReply; Sector %llus, len %u; Fail original request.\n",
+
+	dev_err(DEV, "Got NegDReply; Sector %llus, len %u.\n",
 	    (unsigned long long)sector, be32_to_cpu(p->blksize));
 
 	return validate_req_change_req_state(mdev, p->block_id, sector,
-		_ar_id_to_req, __func__ , neg_acked);
+					     &mdev->read_requests, __func__,
+					     NEG_ACKED, false);
 }
 
-static int got_NegRSDReply(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_NegRSDReply(struct drbd_tconn *tconn, struct packet_info *pi)
 {
+	struct drbd_conf *mdev;
 	sector_t sector;
 	int size;
-	struct p_block_ack *p = (struct p_block_ack *)h;
+	struct p_block_ack *p = pi->data;
+
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return -EIO;
 
 	sector = be64_to_cpu(p->sector);
 	size = be32_to_cpu(p->blksize);
@@ -4478,57 +5083,66 @@ static int got_NegRSDReply(struct drbd_conf *mdev, struct p_header80 *h)
 
 	if (get_ldev_if_state(mdev, D_FAILED)) {
 		drbd_rs_complete_io(mdev, sector);
-		switch (be16_to_cpu(h->command)) {
+		switch (pi->cmd) {
 		case P_NEG_RS_DREPLY:
 			drbd_rs_failed_io(mdev, sector, size);
 		case P_RS_CANCEL:
 			break;
 		default:
-			D_ASSERT(0);
-			put_ldev(mdev);
-			return false;
+			BUG();
 		}
 		put_ldev(mdev);
 	}
 
-	return true;
+	return 0;
 }
 
-static int got_BarrierAck(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_BarrierAck(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	struct p_barrier_ack *p = (struct p_barrier_ack *)h;
-
-	tl_release(mdev, p->barrier, be32_to_cpu(p->set_size));
-
-	if (mdev->state.conn == C_AHEAD &&
-	    atomic_read(&mdev->ap_in_flight) == 0 &&
-	    !test_and_set_bit(AHEAD_TO_SYNC_SOURCE, &mdev->flags)) {
-		mdev->start_resync_timer.expires = jiffies + HZ;
-		add_timer(&mdev->start_resync_timer);
+	struct p_barrier_ack *p = pi->data;
+	struct drbd_conf *mdev;
+	int vnr;
+
+	tl_release(tconn, p->barrier, be32_to_cpu(p->set_size));
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+		if (mdev->state.conn == C_AHEAD &&
+		    atomic_read(&mdev->ap_in_flight) == 0 &&
+		    !test_and_set_bit(AHEAD_TO_SYNC_SOURCE, &mdev->flags)) {
+			mdev->start_resync_timer.expires = jiffies + HZ;
+			add_timer(&mdev->start_resync_timer);
+		}
 	}
+	rcu_read_unlock();
 
-	return true;
+	return 0;
 }
 
-static int got_OVResult(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_OVResult(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	struct p_block_ack *p = (struct p_block_ack *)h;
+	struct drbd_conf *mdev;
+	struct p_block_ack *p = pi->data;
 	struct drbd_work *w;
 	sector_t sector;
 	int size;
 
+	mdev = vnr_to_mdev(tconn, pi->vnr);
+	if (!mdev)
+		return -EIO;
+
 	sector = be64_to_cpu(p->sector);
 	size = be32_to_cpu(p->blksize);
 
 	update_peer_seq(mdev, be32_to_cpu(p->seq_num));
 
 	if (be64_to_cpu(p->block_id) == ID_OUT_OF_SYNC)
-		drbd_ov_oos_found(mdev, sector, size);
+		drbd_ov_out_of_sync_found(mdev, sector, size);
 	else
-		ov_oos_print(mdev);
+		ov_out_of_sync_print(mdev);
 
 	if (!get_ldev(mdev))
-		return true;
+		return 0;
 
 	drbd_rs_complete_io(mdev, sector);
 	dec_rs_pending(mdev);
@@ -4543,114 +5157,137 @@ static int got_OVResult(struct drbd_conf *mdev, struct p_header80 *h)
 		w = kmalloc(sizeof(*w), GFP_NOIO);
 		if (w) {
 			w->cb = w_ov_finished;
-			drbd_queue_work_front(&mdev->data.work, w);
+			w->mdev = mdev;
+			drbd_queue_work(&mdev->tconn->sender_work, w);
 		} else {
 			dev_err(DEV, "kmalloc(w) failed.");
-			ov_oos_print(mdev);
+			ov_out_of_sync_print(mdev);
 			drbd_resync_finished(mdev);
 		}
 	}
 	put_ldev(mdev);
-	return true;
+	return 0;
 }
 
-static int got_skip(struct drbd_conf *mdev, struct p_header80 *h)
+static int got_skip(struct drbd_tconn *tconn, struct packet_info *pi)
 {
-	return true;
+	return 0;
+}
+
+static int tconn_finish_peer_reqs(struct drbd_tconn *tconn)
+{
+	struct drbd_conf *mdev;
+	int vnr, not_empty = 0;
+
+	do {
+		clear_bit(SIGNAL_ASENDER, &tconn->flags);
+		flush_signals(current);
+
+		rcu_read_lock();
+		idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+			kref_get(&mdev->kref);
+			rcu_read_unlock();
+			if (drbd_finish_peer_reqs(mdev)) {
+				kref_put(&mdev->kref, &drbd_minor_destroy);
+				return 1;
+			}
+			kref_put(&mdev->kref, &drbd_minor_destroy);
+			rcu_read_lock();
+		}
+		set_bit(SIGNAL_ASENDER, &tconn->flags);
+
+		spin_lock_irq(&tconn->req_lock);
+		idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+			not_empty = !list_empty(&mdev->done_ee);
+			if (not_empty)
+				break;
+		}
+		spin_unlock_irq(&tconn->req_lock);
+		rcu_read_unlock();
+	} while (not_empty);
+
+	return 0;
 }
 
 struct asender_cmd {
 	size_t pkt_size;
-	int (*process)(struct drbd_conf *mdev, struct p_header80 *h);
+	int (*fn)(struct drbd_tconn *tconn, struct packet_info *);
 };
 
-static struct asender_cmd *get_asender_cmd(int cmd)
-{
-	static struct asender_cmd asender_tbl[] = {
-		/* anything missing from this table is in
-		 * the drbd_cmd_handler (drbd_default_handler) table,
-		 * see the beginning of drbdd() */
-	[P_PING]	    = { sizeof(struct p_header80), got_Ping },
-	[P_PING_ACK]	    = { sizeof(struct p_header80), got_PingAck },
+static struct asender_cmd asender_tbl[] = {
+	[P_PING]	    = { 0, got_Ping },
+	[P_PING_ACK]	    = { 0, got_PingAck },
 	[P_RECV_ACK]	    = { sizeof(struct p_block_ack), got_BlockAck },
 	[P_WRITE_ACK]	    = { sizeof(struct p_block_ack), got_BlockAck },
 	[P_RS_WRITE_ACK]    = { sizeof(struct p_block_ack), got_BlockAck },
-	[P_DISCARD_ACK]	    = { sizeof(struct p_block_ack), got_BlockAck },
+	[P_SUPERSEDED]   = { sizeof(struct p_block_ack), got_BlockAck },
 	[P_NEG_ACK]	    = { sizeof(struct p_block_ack), got_NegAck },
 	[P_NEG_DREPLY]	    = { sizeof(struct p_block_ack), got_NegDReply },
-	[P_NEG_RS_DREPLY]   = { sizeof(struct p_block_ack), got_NegRSDReply},
+	[P_NEG_RS_DREPLY]   = { sizeof(struct p_block_ack), got_NegRSDReply },
 	[P_OV_RESULT]	    = { sizeof(struct p_block_ack), got_OVResult },
 	[P_BARRIER_ACK]	    = { sizeof(struct p_barrier_ack), got_BarrierAck },
 	[P_STATE_CHG_REPLY] = { sizeof(struct p_req_state_reply), got_RqSReply },
 	[P_RS_IS_IN_SYNC]   = { sizeof(struct p_block_ack), got_IsInSync },
 	[P_DELAY_PROBE]     = { sizeof(struct p_delay_probe93), got_skip },
-	[P_RS_CANCEL]       = { sizeof(struct p_block_ack), got_NegRSDReply},
-	[P_MAX_CMD]	    = { 0, NULL },
-	};
-	if (cmd > P_MAX_CMD || asender_tbl[cmd].process == NULL)
-		return NULL;
-	return &asender_tbl[cmd];
-}
+	[P_RS_CANCEL]       = { sizeof(struct p_block_ack), got_NegRSDReply },
+	[P_CONN_ST_CHG_REPLY]={ sizeof(struct p_req_state_reply), got_conn_RqSReply },
+	[P_RETRY_WRITE]	    = { sizeof(struct p_block_ack), got_BlockAck },
+};
 
 int drbd_asender(struct drbd_thread *thi)
 {
-	struct drbd_conf *mdev = thi->mdev;
-	struct p_header80 *h = &mdev->meta.rbuf.header.h80;
+	struct drbd_tconn *tconn = thi->tconn;
 	struct asender_cmd *cmd = NULL;
-
-	int rv, len;
-	void *buf    = h;
+	struct packet_info pi;
+	int rv;
+	void *buf    = tconn->meta.rbuf;
 	int received = 0;
-	int expect   = sizeof(struct p_header80);
-	int empty;
-	int ping_timeout_active = 0;
-
-	sprintf(current->comm, "drbd%d_asender", mdev_to_minor(mdev));
+	unsigned int header_size = drbd_header_size(tconn);
+	int expect   = header_size;
+	bool ping_timeout_active = false;
+	struct net_conf *nc;
+	int ping_timeo, tcp_cork, ping_int;
 
 	current->policy = SCHED_RR;  /* Make this a realtime task! */
 	current->rt_priority = 2;    /* more important than all other tasks */
 
-	while (get_t_state(thi) == Running) {
-		drbd_thread_current_set_cpu(mdev);
-		if (test_and_clear_bit(SEND_PING, &mdev->flags)) {
-			ERR_IF(!drbd_send_ping(mdev)) goto reconnect;
-			mdev->meta.socket->sk->sk_rcvtimeo =
-				mdev->net_conf->ping_timeo*HZ/10;
-			ping_timeout_active = 1;
-		}
+	while (get_t_state(thi) == RUNNING) {
+		drbd_thread_current_set_cpu(thi);
 
-		/* conditionally cork;
-		 * it may hurt latency if we cork without much to send */
-		if (!mdev->net_conf->no_cork &&
-			3 < atomic_read(&mdev->unacked_cnt))
-			drbd_tcp_cork(mdev->meta.socket);
-		while (1) {
-			clear_bit(SIGNAL_ASENDER, &mdev->flags);
-			flush_signals(current);
-			if (!drbd_process_done_ee(mdev))
+		rcu_read_lock();
+		nc = rcu_dereference(tconn->net_conf);
+		ping_timeo = nc->ping_timeo;
+		tcp_cork = nc->tcp_cork;
+		ping_int = nc->ping_int;
+		rcu_read_unlock();
+
+		if (test_and_clear_bit(SEND_PING, &tconn->flags)) {
+			if (drbd_send_ping(tconn)) {
+				conn_err(tconn, "drbd_send_ping has failed\n");
 				goto reconnect;
-			/* to avoid race with newly queued ACKs */
-			set_bit(SIGNAL_ASENDER, &mdev->flags);
-			spin_lock_irq(&mdev->req_lock);
-			empty = list_empty(&mdev->done_ee);
-			spin_unlock_irq(&mdev->req_lock);
-			/* new ack may have been queued right here,
-			 * but then there is also a signal pending,
-			 * and we start over... */
-			if (empty)
-				break;
+			}
+			tconn->meta.socket->sk->sk_rcvtimeo = ping_timeo * HZ / 10;
+			ping_timeout_active = true;
+		}
+
+		/* TODO: conditionally cork; it may hurt latency if we cork without
+		   much to send */
+		if (tcp_cork)
+			drbd_tcp_cork(tconn->meta.socket);
+		if (tconn_finish_peer_reqs(tconn)) {
+			conn_err(tconn, "tconn_finish_peer_reqs() failed\n");
+			goto reconnect;
 		}
 		/* but unconditionally uncork unless disabled */
-		if (!mdev->net_conf->no_cork)
-			drbd_tcp_uncork(mdev->meta.socket);
+		if (tcp_cork)
+			drbd_tcp_uncork(tconn->meta.socket);
 
 		/* short circuit, recv_msg would return EINTR anyways. */
 		if (signal_pending(current))
 			continue;
 
-		rv = drbd_recv_short(mdev, mdev->meta.socket,
-				     buf, expect-received, 0);
-		clear_bit(SIGNAL_ASENDER, &mdev->flags);
+		rv = drbd_recv_short(tconn->meta.socket, buf, expect-received, 0);
+		clear_bit(SIGNAL_ASENDER, &tconn->flags);
 
 		flush_signals(current);
 
@@ -4668,80 +5305,91 @@ int drbd_asender(struct drbd_thread *thi)
 			received += rv;
 			buf	 += rv;
 		} else if (rv == 0) {
-			dev_err(DEV, "meta connection shut down by peer.\n");
+			if (test_bit(DISCONNECT_SENT, &tconn->flags)) {
+				long t;
+				rcu_read_lock();
+				t = rcu_dereference(tconn->net_conf)->ping_timeo * HZ/10;
+				rcu_read_unlock();
+
+				t = wait_event_timeout(tconn->ping_wait,
+						       tconn->cstate < C_WF_REPORT_PARAMS,
+						       t);
+				if (t)
+					break;
+			}
+			conn_err(tconn, "meta connection shut down by peer.\n");
 			goto reconnect;
 		} else if (rv == -EAGAIN) {
 			/* If the data socket received something meanwhile,
 			 * that is good enough: peer is still alive. */
-			if (time_after(mdev->last_received,
-				jiffies - mdev->meta.socket->sk->sk_rcvtimeo))
+			if (time_after(tconn->last_received,
+				jiffies - tconn->meta.socket->sk->sk_rcvtimeo))
 				continue;
 			if (ping_timeout_active) {
-				dev_err(DEV, "PingAck did not arrive in time.\n");
+				conn_err(tconn, "PingAck did not arrive in time.\n");
 				goto reconnect;
 			}
-			set_bit(SEND_PING, &mdev->flags);
+			set_bit(SEND_PING, &tconn->flags);
 			continue;
 		} else if (rv == -EINTR) {
 			continue;
 		} else {
-			dev_err(DEV, "sock_recvmsg returned %d\n", rv);
+			conn_err(tconn, "sock_recvmsg returned %d\n", rv);
 			goto reconnect;
 		}
 
 		if (received == expect && cmd == NULL) {
-			if (unlikely(h->magic != BE_DRBD_MAGIC)) {
-				dev_err(DEV, "magic?? on meta m: 0x%08x c: %d l: %d\n",
-				    be32_to_cpu(h->magic),
-				    be16_to_cpu(h->command),
-				    be16_to_cpu(h->length));
+			if (decode_header(tconn, tconn->meta.rbuf, &pi))
 				goto reconnect;
-			}
-			cmd = get_asender_cmd(be16_to_cpu(h->command));
-			len = be16_to_cpu(h->length);
-			if (unlikely(cmd == NULL)) {
-				dev_err(DEV, "unknown command?? on meta m: 0x%08x c: %d l: %d\n",
-				    be32_to_cpu(h->magic),
-				    be16_to_cpu(h->command),
-				    be16_to_cpu(h->length));
+			cmd = &asender_tbl[pi.cmd];
+			if (pi.cmd >= ARRAY_SIZE(asender_tbl) || !cmd->fn) {
+				conn_err(tconn, "Unexpected meta packet %s (0x%04x)\n",
+					 cmdname(pi.cmd), pi.cmd);
 				goto disconnect;
 			}
-			expect = cmd->pkt_size;
-			ERR_IF(len != expect-sizeof(struct p_header80))
+			expect = header_size + cmd->pkt_size;
+			if (pi.size != expect - header_size) {
+				conn_err(tconn, "Wrong packet size on meta (c: %d, l: %d)\n",
+					pi.cmd, pi.size);
 				goto reconnect;
+			}
 		}
 		if (received == expect) {
-			mdev->last_received = jiffies;
-			D_ASSERT(cmd != NULL);
-			if (!cmd->process(mdev, h))
+			bool err;
+
+			err = cmd->fn(tconn, &pi);
+			if (err) {
+				conn_err(tconn, "%pf failed\n", cmd->fn);
 				goto reconnect;
+			}
 
-			/* the idle_timeout (ping-int)
-			 * has been restored in got_PingAck() */
-			if (cmd == get_asender_cmd(P_PING_ACK))
-				ping_timeout_active = 0;
+			tconn->last_received = jiffies;
 
-			buf	 = h;
+			if (cmd == &asender_tbl[P_PING_ACK]) {
+				/* restore idle timeout */
+				tconn->meta.socket->sk->sk_rcvtimeo = ping_int * HZ;
+				ping_timeout_active = false;
+			}
+
+			buf	 = tconn->meta.rbuf;
 			received = 0;
-			expect	 = sizeof(struct p_header80);
+			expect	 = header_size;
 			cmd	 = NULL;
 		}
 	}
 
 	if (0) {
 reconnect:
-		drbd_force_state(mdev, NS(conn, C_NETWORK_FAILURE));
-		drbd_md_sync(mdev);
+		conn_request_state(tconn, NS(conn, C_NETWORK_FAILURE), CS_HARD);
+		conn_md_sync(tconn);
 	}
 	if (0) {
 disconnect:
-		drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-		drbd_md_sync(mdev);
+		conn_request_state(tconn, NS(conn, C_DISCONNECTING), CS_HARD);
 	}
-	clear_bit(SIGNAL_ASENDER, &mdev->flags);
+	clear_bit(SIGNAL_ASENDER, &tconn->flags);
 
-	D_ASSERT(mdev->state.conn < C_CONNECTED);
-	dev_info(DEV, "asender terminated\n");
+	conn_info(tconn, "asender terminated\n");
 
 	return 0;
 }
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 01b2ac6..f58a4a4 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -31,6 +31,8 @@
 #include "drbd_req.h"
 
 
+static bool drbd_may_do_local_read(struct drbd_conf *mdev, sector_t sector, int size);
+
 /* Update disk stats at start of I/O request */
 static void _drbd_start_io_acct(struct drbd_conf *mdev, struct drbd_request *req, struct bio *bio)
 {
@@ -40,6 +42,8 @@ static void _drbd_start_io_acct(struct drbd_conf *mdev, struct drbd_request *req
 	part_round_stats(cpu, &mdev->vdisk->part0);
 	part_stat_inc(cpu, &mdev->vdisk->part0, ios[rw]);
 	part_stat_add(cpu, &mdev->vdisk->part0, sectors[rw], bio_sectors(bio));
+	(void) cpu; /* The macro invocations above want the cpu argument, I do not like
+		       the compiler warning about cpu only assigned but never used... */
 	part_inc_in_flight(&mdev->vdisk->part0, rw);
 	part_stat_unlock();
 }
@@ -57,9 +61,51 @@ static void _drbd_end_io_acct(struct drbd_conf *mdev, struct drbd_request *req)
 	part_stat_unlock();
 }
 
-static void _req_is_done(struct drbd_conf *mdev, struct drbd_request *req, const int rw)
+static struct drbd_request *drbd_req_new(struct drbd_conf *mdev,
+					       struct bio *bio_src)
+{
+	struct drbd_request *req;
+
+	req = mempool_alloc(drbd_request_mempool, GFP_NOIO);
+	if (!req)
+		return NULL;
+
+	drbd_req_make_private_bio(req, bio_src);
+	req->rq_state    = bio_data_dir(bio_src) == WRITE ? RQ_WRITE : 0;
+	req->w.mdev      = mdev;
+	req->master_bio  = bio_src;
+	req->epoch       = 0;
+
+	drbd_clear_interval(&req->i);
+	req->i.sector     = bio_src->bi_sector;
+	req->i.size      = bio_src->bi_size;
+	req->i.local = true;
+	req->i.waiting = false;
+
+	INIT_LIST_HEAD(&req->tl_requests);
+	INIT_LIST_HEAD(&req->w.list);
+
+	/* one reference to be put by __drbd_make_request */
+	atomic_set(&req->completion_ref, 1);
+	/* one kref as long as completion_ref > 0 */
+	kref_init(&req->kref);
+	return req;
+}
+
+void drbd_req_destroy(struct kref *kref)
 {
-	const unsigned long s = req->rq_state;
+	struct drbd_request *req = container_of(kref, struct drbd_request, kref);
+	struct drbd_conf *mdev = req->w.mdev;
+	const unsigned s = req->rq_state;
+
+	if ((req->master_bio && !(s & RQ_POSTPONED)) ||
+		atomic_read(&req->completion_ref) ||
+		(s & RQ_LOCAL_PENDING) ||
+		((s & RQ_NET_MASK) && !(s & RQ_NET_DONE))) {
+		dev_err(DEV, "drbd_req_destroy: Logic BUG rq_state = 0x%x, completion_ref = %d\n",
+				s, atomic_read(&req->completion_ref));
+		return;
+	}
 
 	/* remove it from the transfer log.
 	 * well, only if it had been there in the first
@@ -67,24 +113,33 @@ static void _req_is_done(struct drbd_conf *mdev, struct drbd_request *req, const
 	 * and never sent), it should still be "empty" as
 	 * initialized in drbd_req_new(), so we can list_del() it
 	 * here unconditionally */
-	list_del(&req->tl_requests);
+	list_del_init(&req->tl_requests);
 
 	/* if it was a write, we may have to set the corresponding
 	 * bit(s) out-of-sync first. If it had a local part, we need to
 	 * release the reference to the activity log. */
-	if (rw == WRITE) {
+	if (s & RQ_WRITE) {
 		/* Set out-of-sync unless both OK flags are set
 		 * (local only or remote failed).
 		 * Other places where we set out-of-sync:
 		 * READ with local io-error */
-		if (!(s & RQ_NET_OK) || !(s & RQ_LOCAL_OK))
-			drbd_set_out_of_sync(mdev, req->sector, req->size);
 
-		if ((s & RQ_NET_OK) && (s & RQ_LOCAL_OK) && (s & RQ_NET_SIS))
-			drbd_set_in_sync(mdev, req->sector, req->size);
+		/* There is a special case:
+		 * we may notice late that IO was suspended,
+		 * and postpone, or schedule for retry, a write,
+		 * before it even was submitted or sent.
+		 * In that case we do not want to touch the bitmap at all.
+		 */
+		if ((s & (RQ_POSTPONED|RQ_LOCAL_MASK|RQ_NET_MASK)) != RQ_POSTPONED) {
+			if (!(s & RQ_NET_OK) || !(s & RQ_LOCAL_OK))
+				drbd_set_out_of_sync(mdev, req->i.sector, req->i.size);
+
+			if ((s & RQ_NET_OK) && (s & RQ_LOCAL_OK) && (s & RQ_NET_SIS))
+				drbd_set_in_sync(mdev, req->i.sector, req->i.size);
+		}
 
 		/* one might be tempted to move the drbd_al_complete_io
-		 * to the local io completion callback drbd_endio_pri.
+		 * to the local io completion callback drbd_request_endio.
 		 * but, if this was a mirror write, we may only
 		 * drbd_al_complete_io after this is RQ_NET_DONE,
 		 * otherwise the extent could be dropped from the al
@@ -93,109 +148,35 @@ static void _req_is_done(struct drbd_conf *mdev, struct drbd_request *req, const
 		 * but after the extent has been dropped from the al,
 		 * we would forget to resync the corresponding extent.
 		 */
-		if (s & RQ_LOCAL_MASK) {
+		if (s & RQ_IN_ACT_LOG) {
 			if (get_ldev_if_state(mdev, D_FAILED)) {
-				if (s & RQ_IN_ACT_LOG)
-					drbd_al_complete_io(mdev, req->sector);
+				drbd_al_complete_io(mdev, &req->i);
 				put_ldev(mdev);
 			} else if (__ratelimit(&drbd_ratelimit_state)) {
-				dev_warn(DEV, "Should have called drbd_al_complete_io(, %llu), "
-				     "but my Disk seems to have failed :(\n",
-				     (unsigned long long) req->sector);
+				dev_warn(DEV, "Should have called drbd_al_complete_io(, %llu, %u), "
+					 "but my Disk seems to have failed :(\n",
+					 (unsigned long long) req->i.sector, req->i.size);
 			}
 		}
 	}
 
-	drbd_req_free(req);
+	mempool_free(req, drbd_request_mempool);
 }
 
-static void queue_barrier(struct drbd_conf *mdev)
-{
-	struct drbd_tl_epoch *b;
-
-	/* We are within the req_lock. Once we queued the barrier for sending,
-	 * we set the CREATE_BARRIER bit. It is cleared as soon as a new
-	 * barrier/epoch object is added. This is the only place this bit is
-	 * set. It indicates that the barrier for this epoch is already queued,
-	 * and no new epoch has been created yet. */
-	if (test_bit(CREATE_BARRIER, &mdev->flags))
-		return;
-
-	b = mdev->newest_tle;
-	b->w.cb = w_send_barrier;
-	/* inc_ap_pending done here, so we won't
-	 * get imbalanced on connection loss.
-	 * dec_ap_pending will be done in got_BarrierAck
-	 * or (on connection loss) in tl_clear.  */
-	inc_ap_pending(mdev);
-	drbd_queue_work(&mdev->data.work, &b->w);
-	set_bit(CREATE_BARRIER, &mdev->flags);
+static void wake_all_senders(struct drbd_tconn *tconn) {
+	wake_up(&tconn->sender_work.q_wait);
 }
 
-static void _about_to_complete_local_write(struct drbd_conf *mdev,
-	struct drbd_request *req)
+/* must hold resource->req_lock */
+static void start_new_tl_epoch(struct drbd_tconn *tconn)
 {
-	const unsigned long s = req->rq_state;
-	struct drbd_request *i;
-	struct drbd_epoch_entry *e;
-	struct hlist_node *n;
-	struct hlist_head *slot;
-
-	/* Before we can signal completion to the upper layers,
-	 * we may need to close the current epoch.
-	 * We can skip this, if this request has not even been sent, because we
-	 * did not have a fully established connection yet/anymore, during
-	 * bitmap exchange, or while we are C_AHEAD due to congestion policy.
-	 */
-	if (mdev->state.conn >= C_CONNECTED &&
-	    (s & RQ_NET_SENT) != 0 &&
-	    req->epoch == mdev->newest_tle->br_number)
-		queue_barrier(mdev);
-
-	/* we need to do the conflict detection stuff,
-	 * if we have the ee_hash (two_primaries) and
-	 * this has been on the network */
-	if ((s & RQ_NET_DONE) && mdev->ee_hash != NULL) {
-		const sector_t sector = req->sector;
-		const int size = req->size;
-
-		/* ASSERT:
-		 * there must be no conflicting requests, since
-		 * they must have been failed on the spot */
-#define OVERLAPS overlaps(sector, size, i->sector, i->size)
-		slot = tl_hash_slot(mdev, sector);
-		hlist_for_each_entry(i, n, slot, collision) {
-			if (OVERLAPS) {
-				dev_alert(DEV, "LOGIC BUG: completed: %p %llus +%u; "
-				      "other: %p %llus +%u\n",
-				      req, (unsigned long long)sector, size,
-				      i, (unsigned long long)i->sector, i->size);
-			}
-		}
+	/* no point closing an epoch, if it is empty, anyways. */
+	if (tconn->current_tle_writes == 0)
+		return;
 
-		/* maybe "wake" those conflicting epoch entries
-		 * that wait for this request to finish.
-		 *
-		 * currently, there can be only _one_ such ee
-		 * (well, or some more, which would be pending
-		 * P_DISCARD_ACK not yet sent by the asender...),
-		 * since we block the receiver thread upon the
-		 * first conflict detection, which will wait on
-		 * misc_wait.  maybe we want to assert that?
-		 *
-		 * anyways, if we found one,
-		 * we just have to do a wake_up.  */
-#undef OVERLAPS
-#define OVERLAPS overlaps(sector, size, e->sector, e->size)
-		slot = ee_hash_slot(mdev, req->sector);
-		hlist_for_each_entry(e, n, slot, collision) {
-			if (OVERLAPS) {
-				wake_up(&mdev->misc_wait);
-				break;
-			}
-		}
-	}
-#undef OVERLAPS
+	tconn->current_tle_writes = 0;
+	atomic_inc(&tconn->current_tle_nr);
+	wake_all_senders(tconn);
 }
 
 void complete_master_bio(struct drbd_conf *mdev,
@@ -205,17 +186,33 @@ void complete_master_bio(struct drbd_conf *mdev,
 	dec_ap_bio(mdev);
 }
 
+
+static void drbd_remove_request_interval(struct rb_root *root,
+					 struct drbd_request *req)
+{
+	struct drbd_conf *mdev = req->w.mdev;
+	struct drbd_interval *i = &req->i;
+
+	drbd_remove_interval(root, i);
+
+	/* Wake up any processes waiting for this request to complete.  */
+	if (i->waiting)
+		wake_up(&mdev->misc_wait);
+}
+
 /* Helper for __req_mod().
  * Set m->bio to the master bio, if it is fit to be completed,
  * or leave it alone (it is initialized to NULL in __req_mod),
  * if it has already been completed, or cannot be completed yet.
  * If m->bio is set, the error status to be returned is placed in m->error.
  */
-void _req_may_be_done(struct drbd_request *req, struct bio_and_error *m)
+static
+void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m)
 {
-	const unsigned long s = req->rq_state;
-	struct drbd_conf *mdev = req->mdev;
-	int rw = req->rq_state & RQ_WRITE ? WRITE : READ;
+	const unsigned s = req->rq_state;
+	struct drbd_conf *mdev = req->w.mdev;
+	int rw;
+	int error, ok;
 
 	/* we must not complete the master bio, while it is
 	 *	still being processed by _drbd_send_zc_bio (drbd_send_dblock)
@@ -226,165 +223,220 @@ void _req_may_be_done(struct drbd_request *req, struct bio_and_error *m)
 	 *	the receiver,
 	 *	the bio_endio completion callbacks.
 	 */
-	if (s & RQ_NET_QUEUED)
-		return;
-	if (s & RQ_NET_PENDING)
+	if ((s & RQ_LOCAL_PENDING && !(s & RQ_LOCAL_ABORTED)) ||
+	    (s & RQ_NET_QUEUED) || (s & RQ_NET_PENDING) ||
+	    (s & RQ_COMPLETION_SUSP)) {
+		dev_err(DEV, "drbd_req_complete: Logic BUG rq_state = 0x%x\n", s);
 		return;
-	if (s & RQ_LOCAL_PENDING && !(s & RQ_LOCAL_ABORTED))
+	}
+
+	if (!req->master_bio) {
+		dev_err(DEV, "drbd_req_complete: Logic BUG, master_bio == NULL!\n");
 		return;
+	}
 
-	if (req->master_bio) {
-		/* this is data_received (remote read)
-		 * or protocol C P_WRITE_ACK
-		 * or protocol B P_RECV_ACK
-		 * or protocol A "handed_over_to_network" (SendAck)
-		 * or canceled or failed,
-		 * or killed from the transfer log due to connection loss.
-		 */
+	rw = bio_rw(req->master_bio);
 
-		/*
-		 * figure out whether to report success or failure.
-		 *
-		 * report success when at least one of the operations succeeded.
-		 * or, to put the other way,
-		 * only report failure, when both operations failed.
-		 *
-		 * what to do about the failures is handled elsewhere.
-		 * what we need to do here is just: complete the master_bio.
-		 *
-		 * local completion error, if any, has been stored as ERR_PTR
-		 * in private_bio within drbd_endio_pri.
-		 */
-		int ok = (s & RQ_LOCAL_OK) || (s & RQ_NET_OK);
-		int error = PTR_ERR(req->private_bio);
+	/*
+	 * figure out whether to report success or failure.
+	 *
+	 * report success when at least one of the operations succeeded.
+	 * or, to put the other way,
+	 * only report failure, when both operations failed.
+	 *
+	 * what to do about the failures is handled elsewhere.
+	 * what we need to do here is just: complete the master_bio.
+	 *
+	 * local completion error, if any, has been stored as ERR_PTR
+	 * in private_bio within drbd_request_endio.
+	 */
+	ok = (s & RQ_LOCAL_OK) || (s & RQ_NET_OK);
+	error = PTR_ERR(req->private_bio);
 
-		/* remove the request from the conflict detection
-		 * respective block_id verification hash */
-		if (!hlist_unhashed(&req->collision))
-			hlist_del(&req->collision);
-		else
-			D_ASSERT((s & (RQ_NET_MASK & ~RQ_NET_DONE)) == 0);
+	/* remove the request from the conflict detection
+	 * respective block_id verification hash */
+	if (!drbd_interval_empty(&req->i)) {
+		struct rb_root *root;
 
-		/* for writes we need to do some extra housekeeping */
 		if (rw == WRITE)
-			_about_to_complete_local_write(mdev, req);
+			root = &mdev->write_requests;
+		else
+			root = &mdev->read_requests;
+		drbd_remove_request_interval(root, req);
+	} else if (!(s & RQ_POSTPONED))
+		D_ASSERT((s & (RQ_NET_MASK & ~RQ_NET_DONE)) == 0);
 
-		/* Update disk stats */
-		_drbd_end_io_acct(mdev, req);
+	/* Before we can signal completion to the upper layers,
+	 * we may need to close the current transfer log epoch.
+	 * We are within the request lock, so we can simply compare
+	 * the request epoch number with the current transfer log
+	 * epoch number.  If they match, increase the current_tle_nr,
+	 * and reset the transfer log epoch write_cnt.
+	 */
+	if (rw == WRITE &&
+	    req->epoch == atomic_read(&mdev->tconn->current_tle_nr))
+		start_new_tl_epoch(mdev->tconn);
+
+	/* Update disk stats */
+	_drbd_end_io_acct(mdev, req);
+
+	/* If READ failed,
+	 * have it be pushed back to the retry work queue,
+	 * so it will re-enter __drbd_make_request(),
+	 * and be re-assigned to a suitable local or remote path,
+	 * or failed if we do not have access to good data anymore.
+	 *
+	 * Unless it was failed early by __drbd_make_request(),
+	 * because no path was available, in which case
+	 * it was not even added to the transfer_log.
+	 *
+	 * READA may fail, and will not be retried.
+	 *
+	 * WRITE should have used all available paths already.
+	 */
+	if (!ok && rw == READ && !list_empty(&req->tl_requests))
+		req->rq_state |= RQ_POSTPONED;
 
+	if (!(req->rq_state & RQ_POSTPONED)) {
 		m->error = ok ? 0 : (error ?: -EIO);
 		m->bio = req->master_bio;
 		req->master_bio = NULL;
 	}
+}
 
-	if (s & RQ_LOCAL_PENDING)
-		return;
+static int drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_error *m, int put)
+{
+	struct drbd_conf *mdev = req->w.mdev;
+	D_ASSERT(m || (req->rq_state & RQ_POSTPONED));
+
+	if (!atomic_sub_and_test(put, &req->completion_ref))
+		return 0;
 
-	if ((s & RQ_NET_MASK) == 0 || (s & RQ_NET_DONE)) {
-		/* this is disconnected (local only) operation,
-		 * or protocol C P_WRITE_ACK,
-		 * or protocol A or B P_BARRIER_ACK,
-		 * or killed from the transfer log due to connection loss. */
-		_req_is_done(mdev, req, rw);
+	drbd_req_complete(req, m);
+
+	if (req->rq_state & RQ_POSTPONED) {
+		/* don't destroy the req object just yet,
+		 * but queue it for retry */
+		drbd_restart_request(req);
+		return 0;
 	}
-	/* else: network part and not DONE yet. that is
-	 * protocol A or B, barrier ack still pending... */
+
+	return 1;
 }
 
-static void _req_may_be_done_not_susp(struct drbd_request *req, struct bio_and_error *m)
+/* I'd like this to be the only place that manipulates
+ * req->completion_ref and req->kref. */
+static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
+		int clear, int set)
 {
-	struct drbd_conf *mdev = req->mdev;
+	struct drbd_conf *mdev = req->w.mdev;
+	unsigned s = req->rq_state;
+	int c_put = 0;
+	int k_put = 0;
 
-	if (!is_susp(mdev->state))
-		_req_may_be_done(req, m);
-}
+	if (drbd_suspended(mdev) && !((s | clear) & RQ_COMPLETION_SUSP))
+		set |= RQ_COMPLETION_SUSP;
 
-/*
- * checks whether there was an overlapping request
- * or ee already registered.
- *
- * if so, return 1, in which case this request is completed on the spot,
- * without ever being submitted or send.
- *
- * return 0 if it is ok to submit this request.
- *
- * NOTE:
- * paranoia: assume something above us is broken, and issues different write
- * requests for the same block simultaneously...
- *
- * To ensure these won't be reordered differently on both nodes, resulting in
- * diverging data sets, we discard the later one(s). Not that this is supposed
- * to happen, but this is the rationale why we also have to check for
- * conflicting requests with local origin, and why we have to do so regardless
- * of whether we allowed multiple primaries.
- *
- * BTW, in case we only have one primary, the ee_hash is empty anyways, and the
- * second hlist_for_each_entry becomes a noop. This is even simpler than to
- * grab a reference on the net_conf, and check for the two_primaries flag...
- */
-static int _req_conflicts(struct drbd_request *req)
-{
-	struct drbd_conf *mdev = req->mdev;
-	const sector_t sector = req->sector;
-	const int size = req->size;
-	struct drbd_request *i;
-	struct drbd_epoch_entry *e;
-	struct hlist_node *n;
-	struct hlist_head *slot;
+	/* apply */
 
-	D_ASSERT(hlist_unhashed(&req->collision));
+	req->rq_state &= ~clear;
+	req->rq_state |= set;
 
-	if (!get_net_conf(mdev))
-		return 0;
+	/* no change? */
+	if (req->rq_state == s)
+		return;
 
-	/* BUG_ON */
-	ERR_IF (mdev->tl_hash_s == 0)
-		goto out_no_conflict;
-	BUG_ON(mdev->tl_hash == NULL);
-
-#define OVERLAPS overlaps(i->sector, i->size, sector, size)
-	slot = tl_hash_slot(mdev, sector);
-	hlist_for_each_entry(i, n, slot, collision) {
-		if (OVERLAPS) {
-			dev_alert(DEV, "%s[%u] Concurrent local write detected! "
-			      "[DISCARD L] new: %llus +%u; "
-			      "pending: %llus +%u\n",
-			      current->comm, current->pid,
-			      (unsigned long long)sector, size,
-			      (unsigned long long)i->sector, i->size);
-			goto out_conflict;
-		}
+	/* intent: get references */
+
+	if (!(s & RQ_LOCAL_PENDING) && (set & RQ_LOCAL_PENDING))
+		atomic_inc(&req->completion_ref);
+
+	if (!(s & RQ_NET_PENDING) && (set & RQ_NET_PENDING)) {
+		inc_ap_pending(mdev);
+		atomic_inc(&req->completion_ref);
 	}
 
-	if (mdev->ee_hash_s) {
-		/* now, check for overlapping requests with remote origin */
-		BUG_ON(mdev->ee_hash == NULL);
-#undef OVERLAPS
-#define OVERLAPS overlaps(e->sector, e->size, sector, size)
-		slot = ee_hash_slot(mdev, sector);
-		hlist_for_each_entry(e, n, slot, collision) {
-			if (OVERLAPS) {
-				dev_alert(DEV, "%s[%u] Concurrent remote write detected!"
-				      " [DISCARD L] new: %llus +%u; "
-				      "pending: %llus +%u\n",
-				      current->comm, current->pid,
-				      (unsigned long long)sector, size,
-				      (unsigned long long)e->sector, e->size);
-				goto out_conflict;
-			}
-		}
+	if (!(s & RQ_NET_QUEUED) && (set & RQ_NET_QUEUED))
+		atomic_inc(&req->completion_ref);
+
+	if (!(s & RQ_EXP_BARR_ACK) && (set & RQ_EXP_BARR_ACK))
+		kref_get(&req->kref); /* wait for the DONE */
+
+	if (!(s & RQ_NET_SENT) && (set & RQ_NET_SENT))
+		atomic_add(req->i.size >> 9, &mdev->ap_in_flight);
+
+	if (!(s & RQ_COMPLETION_SUSP) && (set & RQ_COMPLETION_SUSP))
+		atomic_inc(&req->completion_ref);
+
+	/* progress: put references */
+
+	if ((s & RQ_COMPLETION_SUSP) && (clear & RQ_COMPLETION_SUSP))
+		++c_put;
+
+	if (!(s & RQ_LOCAL_ABORTED) && (set & RQ_LOCAL_ABORTED)) {
+		D_ASSERT(req->rq_state & RQ_LOCAL_PENDING);
+		/* local completion may still come in later,
+		 * we need to keep the req object around. */
+		kref_get(&req->kref);
+		++c_put;
+	}
+
+	if ((s & RQ_LOCAL_PENDING) && (clear & RQ_LOCAL_PENDING)) {
+		if (req->rq_state & RQ_LOCAL_ABORTED)
+			++k_put;
+		else
+			++c_put;
 	}
-#undef OVERLAPS
 
-out_no_conflict:
-	/* this is like it should be, and what we expected.
-	 * our users do behave after all... */
-	put_net_conf(mdev);
-	return 0;
+	if ((s & RQ_NET_PENDING) && (clear & RQ_NET_PENDING)) {
+		dec_ap_pending(mdev);
+		++c_put;
+	}
 
-out_conflict:
-	put_net_conf(mdev);
-	return 1;
+	if ((s & RQ_NET_QUEUED) && (clear & RQ_NET_QUEUED))
+		++c_put;
+
+	if ((s & RQ_EXP_BARR_ACK) && !(s & RQ_NET_DONE) && (set & RQ_NET_DONE)) {
+		if (req->rq_state & RQ_NET_SENT)
+			atomic_sub(req->i.size >> 9, &mdev->ap_in_flight);
+		++k_put;
+	}
+
+	/* potentially complete and destroy */
+
+	if (k_put || c_put) {
+		/* Completion does it's own kref_put.  If we are going to
+		 * kref_sub below, we need req to be still around then. */
+		int at_least = k_put + !!c_put;
+		int refcount = atomic_read(&req->kref.refcount);
+		if (refcount < at_least)
+			dev_err(DEV,
+				"mod_rq_state: Logic BUG: %x -> %x: refcount = %d, should be >= %d\n",
+				s, req->rq_state, refcount, at_least);
+	}
+
+	/* If we made progress, retry conflicting peer requests, if any. */
+	if (req->i.waiting)
+		wake_up(&mdev->misc_wait);
+
+	if (c_put)
+		k_put += drbd_req_put_completion_ref(req, m, c_put);
+	if (k_put)
+		kref_sub(&req->kref, k_put, drbd_req_destroy);
+}
+
+static void drbd_report_io_error(struct drbd_conf *mdev, struct drbd_request *req)
+{
+        char b[BDEVNAME_SIZE];
+
+	if (!__ratelimit(&drbd_ratelimit_state))
+		return;
+
+	dev_warn(DEV, "local %s IO error sector %llu+%u on %s\n",
+			(req->rq_state & RQ_WRITE) ? "WRITE" : "READ",
+			(unsigned long long)req->i.sector,
+			req->i.size >> 9,
+			bdevname(mdev->ldev->backing_bdev, b));
 }
 
 /* obviously this could be coded as many single functions
@@ -402,9 +454,12 @@ out_conflict:
 int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		struct bio_and_error *m)
 {
-	struct drbd_conf *mdev = req->mdev;
-	int rv = 0;
-	m->bio = NULL;
+	struct drbd_conf *mdev = req->w.mdev;
+	struct net_conf *nc;
+	int p, rv = 0;
+
+	if (m)
+		m->bio = NULL;
 
 	switch (what) {
 	default:
@@ -413,116 +468,91 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 
 	/* does not happen...
 	 * initialization done in drbd_req_new
-	case created:
+	case CREATED:
 		break;
 		*/
 
-	case to_be_send: /* via network */
-		/* reached via drbd_make_request_common
+	case TO_BE_SENT: /* via network */
+		/* reached via __drbd_make_request
 		 * and from w_read_retry_remote */
 		D_ASSERT(!(req->rq_state & RQ_NET_MASK));
-		req->rq_state |= RQ_NET_PENDING;
-		inc_ap_pending(mdev);
+		rcu_read_lock();
+		nc = rcu_dereference(mdev->tconn->net_conf);
+		p = nc->wire_protocol;
+		rcu_read_unlock();
+		req->rq_state |=
+			p == DRBD_PROT_C ? RQ_EXP_WRITE_ACK :
+			p == DRBD_PROT_B ? RQ_EXP_RECEIVE_ACK : 0;
+		mod_rq_state(req, m, 0, RQ_NET_PENDING);
 		break;
 
-	case to_be_submitted: /* locally */
-		/* reached via drbd_make_request_common */
+	case TO_BE_SUBMITTED: /* locally */
+		/* reached via __drbd_make_request */
 		D_ASSERT(!(req->rq_state & RQ_LOCAL_MASK));
-		req->rq_state |= RQ_LOCAL_PENDING;
+		mod_rq_state(req, m, 0, RQ_LOCAL_PENDING);
 		break;
 
-	case completed_ok:
+	case COMPLETED_OK:
 		if (req->rq_state & RQ_WRITE)
-			mdev->writ_cnt += req->size>>9;
+			mdev->writ_cnt += req->i.size >> 9;
 		else
-			mdev->read_cnt += req->size>>9;
+			mdev->read_cnt += req->i.size >> 9;
 
-		req->rq_state |= (RQ_LOCAL_COMPLETED|RQ_LOCAL_OK);
-		req->rq_state &= ~RQ_LOCAL_PENDING;
-
-		_req_may_be_done_not_susp(req, m);
+		mod_rq_state(req, m, RQ_LOCAL_PENDING,
+				RQ_LOCAL_COMPLETED|RQ_LOCAL_OK);
 		break;
 
-	case abort_disk_io:
-		req->rq_state |= RQ_LOCAL_ABORTED;
-		if (req->rq_state & RQ_WRITE)
-			_req_may_be_done_not_susp(req, m);
-		else
-			goto goto_queue_for_net_read;
+	case ABORT_DISK_IO:
+		mod_rq_state(req, m, 0, RQ_LOCAL_ABORTED);
 		break;
 
-	case write_completed_with_error:
-		req->rq_state |= RQ_LOCAL_COMPLETED;
-		req->rq_state &= ~RQ_LOCAL_PENDING;
-
-		__drbd_chk_io_error(mdev, DRBD_IO_ERROR);
-		_req_may_be_done_not_susp(req, m);
+	case WRITE_COMPLETED_WITH_ERROR:
+		drbd_report_io_error(mdev, req);
+		__drbd_chk_io_error(mdev, DRBD_WRITE_ERROR);
+		mod_rq_state(req, m, RQ_LOCAL_PENDING, RQ_LOCAL_COMPLETED);
 		break;
 
-	case read_ahead_completed_with_error:
-		/* it is legal to fail READA */
-		req->rq_state |= RQ_LOCAL_COMPLETED;
-		req->rq_state &= ~RQ_LOCAL_PENDING;
-		_req_may_be_done_not_susp(req, m);
+	case READ_COMPLETED_WITH_ERROR:
+		drbd_set_out_of_sync(mdev, req->i.sector, req->i.size);
+		drbd_report_io_error(mdev, req);
+		__drbd_chk_io_error(mdev, DRBD_READ_ERROR);
+		/* fall through. */
+	case READ_AHEAD_COMPLETED_WITH_ERROR:
+		/* it is legal to fail READA, no __drbd_chk_io_error in that case. */
+		mod_rq_state(req, m, RQ_LOCAL_PENDING, RQ_LOCAL_COMPLETED);
 		break;
 
-	case read_completed_with_error:
-		drbd_set_out_of_sync(mdev, req->sector, req->size);
-
-		req->rq_state |= RQ_LOCAL_COMPLETED;
-		req->rq_state &= ~RQ_LOCAL_PENDING;
-
-		if (req->rq_state & RQ_LOCAL_ABORTED) {
-			_req_may_be_done(req, m);
-			break;
-		}
-
-		__drbd_chk_io_error(mdev, DRBD_IO_ERROR);
-
-	goto_queue_for_net_read:
-
-		D_ASSERT(!(req->rq_state & RQ_NET_MASK));
-
-		/* no point in retrying if there is no good remote data,
-		 * or we have no connection. */
-		if (mdev->state.pdsk != D_UP_TO_DATE) {
-			_req_may_be_done_not_susp(req, m);
-			break;
-		}
-
-		/* _req_mod(req,to_be_send); oops, recursion... */
-		req->rq_state |= RQ_NET_PENDING;
-		inc_ap_pending(mdev);
-		/* fall through: _req_mod(req,queue_for_net_read); */
-
-	case queue_for_net_read:
+	case QUEUE_FOR_NET_READ:
 		/* READ or READA, and
 		 * no local disk,
 		 * or target area marked as invalid,
 		 * or just got an io-error. */
-		/* from drbd_make_request_common
+		/* from __drbd_make_request
 		 * or from bio_endio during read io-error recovery */
 
-		/* so we can verify the handle in the answer packet
-		 * corresponding hlist_del is in _req_may_be_done() */
-		hlist_add_head(&req->collision, ar_hash_slot(mdev, req->sector));
+		/* So we can verify the handle in the answer packet.
+		 * Corresponding drbd_remove_request_interval is in
+		 * drbd_req_complete() */
+		D_ASSERT(drbd_interval_empty(&req->i));
+		drbd_insert_interval(&mdev->read_requests, &req->i);
 
 		set_bit(UNPLUG_REMOTE, &mdev->flags);
 
 		D_ASSERT(req->rq_state & RQ_NET_PENDING);
-		req->rq_state |= RQ_NET_QUEUED;
-		req->w.cb = (req->rq_state & RQ_LOCAL_MASK)
-			? w_read_retry_remote
-			: w_send_read_req;
-		drbd_queue_work(&mdev->data.work, &req->w);
+		D_ASSERT((req->rq_state & RQ_LOCAL_MASK) == 0);
+		mod_rq_state(req, m, 0, RQ_NET_QUEUED);
+		req->w.cb = w_send_read_req;
+		drbd_queue_work(&mdev->tconn->sender_work, &req->w);
 		break;
 
-	case queue_for_net_write:
+	case QUEUE_FOR_NET_WRITE:
 		/* assert something? */
-		/* from drbd_make_request_common only */
+		/* from __drbd_make_request only */
 
-		hlist_add_head(&req->collision, tl_hash_slot(mdev, req->sector));
-		/* corresponding hlist_del is in _req_may_be_done() */
+		/* Corresponding drbd_remove_request_interval is in
+		 * drbd_req_complete() */
+		D_ASSERT(drbd_interval_empty(&req->i));
+		drbd_insert_interval(&mdev->write_requests, &req->i);
 
 		/* NOTE
 		 * In case the req ended up on the transfer log before being
@@ -533,7 +563,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		 *
 		 * _req_add_to_epoch(req); this has to be after the
 		 * _maybe_start_new_epoch(req); which happened in
-		 * drbd_make_request_common, because we now may set the bit
+		 * __drbd_make_request, because we now may set the bit
 		 * again ourselves to close the current epoch.
 		 *
 		 * Add req to the (now) current epoch (barrier). */
@@ -543,202 +573,187 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		 * hurting performance. */
 		set_bit(UNPLUG_REMOTE, &mdev->flags);
 
-		/* see drbd_make_request_common,
-		 * just after it grabs the req_lock */
-		D_ASSERT(test_bit(CREATE_BARRIER, &mdev->flags) == 0);
-
-		req->epoch = mdev->newest_tle->br_number;
-
-		/* increment size of current epoch */
-		mdev->newest_tle->n_writes++;
-
 		/* queue work item to send data */
 		D_ASSERT(req->rq_state & RQ_NET_PENDING);
-		req->rq_state |= RQ_NET_QUEUED;
+		mod_rq_state(req, m, 0, RQ_NET_QUEUED|RQ_EXP_BARR_ACK);
 		req->w.cb =  w_send_dblock;
-		drbd_queue_work(&mdev->data.work, &req->w);
+		drbd_queue_work(&mdev->tconn->sender_work, &req->w);
 
 		/* close the epoch, in case it outgrew the limit */
-		if (mdev->newest_tle->n_writes >= mdev->net_conf->max_epoch_size)
-			queue_barrier(mdev);
+		rcu_read_lock();
+		nc = rcu_dereference(mdev->tconn->net_conf);
+		p = nc->max_epoch_size;
+		rcu_read_unlock();
+		if (mdev->tconn->current_tle_writes >= p)
+			start_new_tl_epoch(mdev->tconn);
 
 		break;
 
-	case queue_for_send_oos:
-		req->rq_state |= RQ_NET_QUEUED;
-		req->w.cb =  w_send_oos;
-		drbd_queue_work(&mdev->data.work, &req->w);
+	case QUEUE_FOR_SEND_OOS:
+		mod_rq_state(req, m, 0, RQ_NET_QUEUED);
+		req->w.cb =  w_send_out_of_sync;
+		drbd_queue_work(&mdev->tconn->sender_work, &req->w);
 		break;
 
-	case read_retry_remote_canceled:
-	case send_canceled:
-	case send_failed:
+	case READ_RETRY_REMOTE_CANCELED:
+	case SEND_CANCELED:
+	case SEND_FAILED:
 		/* real cleanup will be done from tl_clear.  just update flags
 		 * so it is no longer marked as on the worker queue */
-		req->rq_state &= ~RQ_NET_QUEUED;
-		/* if we did it right, tl_clear should be scheduled only after
-		 * this, so this should not be necessary! */
-		_req_may_be_done_not_susp(req, m);
+		mod_rq_state(req, m, RQ_NET_QUEUED, 0);
 		break;
 
-	case handed_over_to_network:
+	case HANDED_OVER_TO_NETWORK:
 		/* assert something? */
-		if (bio_data_dir(req->master_bio) == WRITE)
-			atomic_add(req->size>>9, &mdev->ap_in_flight);
-
 		if (bio_data_dir(req->master_bio) == WRITE &&
-		    mdev->net_conf->wire_protocol == DRBD_PROT_A) {
+		    !(req->rq_state & (RQ_EXP_RECEIVE_ACK | RQ_EXP_WRITE_ACK))) {
 			/* this is what is dangerous about protocol A:
 			 * pretend it was successfully written on the peer. */
-			if (req->rq_state & RQ_NET_PENDING) {
-				dec_ap_pending(mdev);
-				req->rq_state &= ~RQ_NET_PENDING;
-				req->rq_state |= RQ_NET_OK;
-			} /* else: neg-ack was faster... */
+			if (req->rq_state & RQ_NET_PENDING)
+				mod_rq_state(req, m, RQ_NET_PENDING, RQ_NET_OK);
+			/* else: neg-ack was faster... */
 			/* it is still not yet RQ_NET_DONE until the
 			 * corresponding epoch barrier got acked as well,
 			 * so we know what to dirty on connection loss */
 		}
-		req->rq_state &= ~RQ_NET_QUEUED;
-		req->rq_state |= RQ_NET_SENT;
-		_req_may_be_done_not_susp(req, m);
+		mod_rq_state(req, m, RQ_NET_QUEUED, RQ_NET_SENT);
 		break;
 
-	case oos_handed_to_network:
+	case OOS_HANDED_TO_NETWORK:
 		/* Was not set PENDING, no longer QUEUED, so is now DONE
 		 * as far as this connection is concerned. */
-		req->rq_state &= ~RQ_NET_QUEUED;
-		req->rq_state |= RQ_NET_DONE;
-		_req_may_be_done_not_susp(req, m);
+		mod_rq_state(req, m, RQ_NET_QUEUED, RQ_NET_DONE);
 		break;
 
-	case connection_lost_while_pending:
+	case CONNECTION_LOST_WHILE_PENDING:
 		/* transfer log cleanup after connection loss */
-		/* assert something? */
-		if (req->rq_state & RQ_NET_PENDING)
-			dec_ap_pending(mdev);
-		req->rq_state &= ~(RQ_NET_OK|RQ_NET_PENDING);
-		req->rq_state |= RQ_NET_DONE;
-		if (req->rq_state & RQ_NET_SENT && req->rq_state & RQ_WRITE)
-			atomic_sub(req->size>>9, &mdev->ap_in_flight);
-
-		/* if it is still queued, we may not complete it here.
-		 * it will be canceled soon. */
-		if (!(req->rq_state & RQ_NET_QUEUED))
-			_req_may_be_done(req, m); /* Allowed while state.susp */
+		mod_rq_state(req, m,
+				RQ_NET_OK|RQ_NET_PENDING|RQ_COMPLETION_SUSP,
+				RQ_NET_DONE);
 		break;
 
-	case conflict_discarded_by_peer:
-		/* for discarded conflicting writes of multiple primaries,
+	case CONFLICT_RESOLVED:
+		/* for superseded conflicting writes of multiple primaries,
 		 * there is no need to keep anything in the tl, potential
-		 * node crashes are covered by the activity log. */
-		if (what == conflict_discarded_by_peer)
-			dev_alert(DEV, "Got DiscardAck packet %llus +%u!"
-			      " DRBD is not a random data generator!\n",
-			      (unsigned long long)req->sector, req->size);
-		req->rq_state |= RQ_NET_DONE;
-		/* fall through */
-	case write_acked_by_peer_and_sis:
-	case write_acked_by_peer:
-		if (what == write_acked_by_peer_and_sis)
-			req->rq_state |= RQ_NET_SIS;
+		 * node crashes are covered by the activity log.
+		 *
+		 * If this request had been marked as RQ_POSTPONED before,
+		 * it will actually not be completed, but "restarted",
+		 * resubmitted from the retry worker context. */
+		D_ASSERT(req->rq_state & RQ_NET_PENDING);
+		D_ASSERT(req->rq_state & RQ_EXP_WRITE_ACK);
+		mod_rq_state(req, m, RQ_NET_PENDING, RQ_NET_DONE|RQ_NET_OK);
+		break;
+
+	case WRITE_ACKED_BY_PEER_AND_SIS:
+		req->rq_state |= RQ_NET_SIS;
+	case WRITE_ACKED_BY_PEER:
+		D_ASSERT(req->rq_state & RQ_EXP_WRITE_ACK);
 		/* protocol C; successfully written on peer.
 		 * Nothing more to do here.
 		 * We want to keep the tl in place for all protocols, to cater
 		 * for volatile write-back caches on lower level devices. */
 
-	case recv_acked_by_peer:
+		goto ack_common;
+	case RECV_ACKED_BY_PEER:
+		D_ASSERT(req->rq_state & RQ_EXP_RECEIVE_ACK);
 		/* protocol B; pretends to be successfully written on peer.
-		 * see also notes above in handed_over_to_network about
+		 * see also notes above in HANDED_OVER_TO_NETWORK about
 		 * protocol != C */
-		req->rq_state |= RQ_NET_OK;
+	ack_common:
 		D_ASSERT(req->rq_state & RQ_NET_PENDING);
-		dec_ap_pending(mdev);
-		atomic_sub(req->size>>9, &mdev->ap_in_flight);
-		req->rq_state &= ~RQ_NET_PENDING;
-		_req_may_be_done_not_susp(req, m);
+		mod_rq_state(req, m, RQ_NET_PENDING, RQ_NET_OK);
 		break;
 
-	case neg_acked:
-		/* assert something? */
-		if (req->rq_state & RQ_NET_PENDING) {
-			dec_ap_pending(mdev);
-			atomic_sub(req->size>>9, &mdev->ap_in_flight);
-		}
-		req->rq_state &= ~(RQ_NET_OK|RQ_NET_PENDING);
+	case POSTPONE_WRITE:
+		D_ASSERT(req->rq_state & RQ_EXP_WRITE_ACK);
+		/* If this node has already detected the write conflict, the
+		 * worker will be waiting on misc_wait.  Wake it up once this
+		 * request has completed locally.
+		 */
+		D_ASSERT(req->rq_state & RQ_NET_PENDING);
+		req->rq_state |= RQ_POSTPONED;
+		if (req->i.waiting)
+			wake_up(&mdev->misc_wait);
+		/* Do not clear RQ_NET_PENDING. This request will make further
+		 * progress via restart_conflicting_writes() or
+		 * fail_postponed_requests(). Hopefully. */
+		break;
 
-		req->rq_state |= RQ_NET_DONE;
-		_req_may_be_done_not_susp(req, m);
-		/* else: done by handed_over_to_network */
+	case NEG_ACKED:
+		mod_rq_state(req, m, RQ_NET_OK|RQ_NET_PENDING, 0);
 		break;
 
-	case fail_frozen_disk_io:
+	case FAIL_FROZEN_DISK_IO:
 		if (!(req->rq_state & RQ_LOCAL_COMPLETED))
 			break;
-
-		_req_may_be_done(req, m); /* Allowed while state.susp */
+		mod_rq_state(req, m, RQ_COMPLETION_SUSP, 0);
 		break;
 
-	case restart_frozen_disk_io:
+	case RESTART_FROZEN_DISK_IO:
 		if (!(req->rq_state & RQ_LOCAL_COMPLETED))
 			break;
 
-		req->rq_state &= ~RQ_LOCAL_COMPLETED;
+		mod_rq_state(req, m,
+				RQ_COMPLETION_SUSP|RQ_LOCAL_COMPLETED,
+				RQ_LOCAL_PENDING);
 
 		rv = MR_READ;
 		if (bio_data_dir(req->master_bio) == WRITE)
 			rv = MR_WRITE;
 
-		get_ldev(mdev);
+		get_ldev(mdev); /* always succeeds in this call path */
 		req->w.cb = w_restart_disk_io;
-		drbd_queue_work(&mdev->data.work, &req->w);
+		drbd_queue_work(&mdev->tconn->sender_work, &req->w);
 		break;
 
-	case resend:
+	case RESEND:
 		/* Simply complete (local only) READs. */
 		if (!(req->rq_state & RQ_WRITE) && !req->w.cb) {
-			_req_may_be_done(req, m);
+			mod_rq_state(req, m, RQ_COMPLETION_SUSP, 0);
 			break;
 		}
 
 		/* If RQ_NET_OK is already set, we got a P_WRITE_ACK or P_RECV_ACK
-		   before the connection loss (B&C only); only P_BARRIER_ACK was missing.
-		   Trowing them out of the TL here by pretending we got a BARRIER_ACK
-		   We ensure that the peer was not rebooted */
+		   before the connection loss (B&C only); only P_BARRIER_ACK
+		   (or the local completion?) was missing when we suspended.
+		   Throwing them out of the TL here by pretending we got a BARRIER_ACK.
+		   During connection handshake, we ensure that the peer was not rebooted. */
 		if (!(req->rq_state & RQ_NET_OK)) {
+			/* FIXME could this possibly be a req->w.cb == w_send_out_of_sync?
+			 * in that case we must not set RQ_NET_PENDING. */
+
+			mod_rq_state(req, m, RQ_COMPLETION_SUSP, RQ_NET_QUEUED|RQ_NET_PENDING);
 			if (req->w.cb) {
-				drbd_queue_work(&mdev->data.work, &req->w);
+				drbd_queue_work(&mdev->tconn->sender_work, &req->w);
 				rv = req->rq_state & RQ_WRITE ? MR_WRITE : MR_READ;
-			}
+			} /* else: FIXME can this happen? */
 			break;
 		}
-		/* else, fall through to barrier_acked */
+		/* else, fall through to BARRIER_ACKED */
 
-	case barrier_acked:
+	case BARRIER_ACKED:
+		/* barrier ack for READ requests does not make sense */
 		if (!(req->rq_state & RQ_WRITE))
 			break;
 
 		if (req->rq_state & RQ_NET_PENDING) {
-			/* barrier came in before all requests have been acked.
+			/* barrier came in before all requests were acked.
 			 * this is bad, because if the connection is lost now,
 			 * we won't be able to clean them up... */
-			dev_err(DEV, "FIXME (barrier_acked but pending)\n");
-			list_move(&req->tl_requests, &mdev->out_of_sequence_requests);
+			dev_err(DEV, "FIXME (BARRIER_ACKED but pending)\n");
 		}
-		if ((req->rq_state & RQ_NET_MASK) != 0) {
-			req->rq_state |= RQ_NET_DONE;
-			if (mdev->net_conf->wire_protocol == DRBD_PROT_A)
-				atomic_sub(req->size>>9, &mdev->ap_in_flight);
-		}
-		_req_may_be_done(req, m); /* Allowed while state.susp */
+		/* Allowed to complete requests, even while suspended.
+		 * As this is called for all requests within a matching epoch,
+		 * we need to filter, and only set RQ_NET_DONE for those that
+		 * have actually been on the wire. */
+		mod_rq_state(req, m, RQ_COMPLETION_SUSP,
+				(req->rq_state & RQ_NET_MASK) ? RQ_NET_DONE : 0);
 		break;
 
-	case data_received:
+	case DATA_RECEIVED:
 		D_ASSERT(req->rq_state & RQ_NET_PENDING);
-		dec_ap_pending(mdev);
-		req->rq_state &= ~RQ_NET_PENDING;
-		req->rq_state |= (RQ_NET_OK|RQ_NET_DONE);
-		_req_may_be_done_not_susp(req, m);
+		mod_rq_state(req, m, RQ_NET_PENDING, RQ_NET_OK|RQ_NET_DONE);
 		break;
 	};
 
@@ -752,75 +767,265 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
  *   since size may be bigger than BM_BLOCK_SIZE,
  *   we may need to check several bits.
  */
-static int drbd_may_do_local_read(struct drbd_conf *mdev, sector_t sector, int size)
+static bool drbd_may_do_local_read(struct drbd_conf *mdev, sector_t sector, int size)
 {
 	unsigned long sbnr, ebnr;
 	sector_t esector, nr_sectors;
 
 	if (mdev->state.disk == D_UP_TO_DATE)
-		return 1;
-	if (mdev->state.disk >= D_OUTDATED)
-		return 0;
-	if (mdev->state.disk <  D_INCONSISTENT)
-		return 0;
-	/* state.disk == D_INCONSISTENT   We will have a look at the BitMap */
-	nr_sectors = drbd_get_capacity(mdev->this_bdev);
+		return true;
+	if (mdev->state.disk != D_INCONSISTENT)
+		return false;
 	esector = sector + (size >> 9) - 1;
-
+	nr_sectors = drbd_get_capacity(mdev->this_bdev);
 	D_ASSERT(sector  < nr_sectors);
 	D_ASSERT(esector < nr_sectors);
 
 	sbnr = BM_SECT_TO_BIT(sector);
 	ebnr = BM_SECT_TO_BIT(esector);
 
-	return 0 == drbd_bm_count_bits(mdev, sbnr, ebnr);
+	return drbd_bm_count_bits(mdev, sbnr, ebnr) == 0;
+}
+
+static bool remote_due_to_read_balancing(struct drbd_conf *mdev, sector_t sector,
+		enum drbd_read_balancing rbm)
+{
+	struct backing_dev_info *bdi;
+	int stripe_shift;
+
+	switch (rbm) {
+	case RB_CONGESTED_REMOTE:
+		bdi = &mdev->ldev->backing_bdev->bd_disk->queue->backing_dev_info;
+		return bdi_read_congested(bdi);
+	case RB_LEAST_PENDING:
+		return atomic_read(&mdev->local_cnt) >
+			atomic_read(&mdev->ap_pending_cnt) + atomic_read(&mdev->rs_pending_cnt);
+	case RB_32K_STRIPING:  /* stripe_shift = 15 */
+	case RB_64K_STRIPING:
+	case RB_128K_STRIPING:
+	case RB_256K_STRIPING:
+	case RB_512K_STRIPING:
+	case RB_1M_STRIPING:   /* stripe_shift = 20 */
+		stripe_shift = (rbm - RB_32K_STRIPING + 15);
+		return (sector >> (stripe_shift - 9)) & 1;
+	case RB_ROUND_ROBIN:
+		return test_and_change_bit(READ_BALANCE_RR, &mdev->flags);
+	case RB_PREFER_REMOTE:
+		return true;
+	case RB_PREFER_LOCAL:
+	default:
+		return false;
+	}
+}
+
+/*
+ * complete_conflicting_writes  -  wait for any conflicting write requests
+ *
+ * The write_requests tree contains all active write requests which we
+ * currently know about.  Wait for any requests to complete which conflict with
+ * the new one.
+ *
+ * Only way out: remove the conflicting intervals from the tree.
+ */
+static void complete_conflicting_writes(struct drbd_request *req)
+{
+	DEFINE_WAIT(wait);
+	struct drbd_conf *mdev = req->w.mdev;
+	struct drbd_interval *i;
+	sector_t sector = req->i.sector;
+	int size = req->i.size;
+
+	i = drbd_find_overlap(&mdev->write_requests, sector, size);
+	if (!i)
+		return;
+
+	for (;;) {
+		prepare_to_wait(&mdev->misc_wait, &wait, TASK_UNINTERRUPTIBLE);
+		i = drbd_find_overlap(&mdev->write_requests, sector, size);
+		if (!i)
+			break;
+		/* Indicate to wake up device->misc_wait on progress.  */
+		i->waiting = true;
+		spin_unlock_irq(&mdev->tconn->req_lock);
+		schedule();
+		spin_lock_irq(&mdev->tconn->req_lock);
+	}
+	finish_wait(&mdev->misc_wait, &wait);
 }
 
+/* called within req_lock and rcu_read_lock() */
 static void maybe_pull_ahead(struct drbd_conf *mdev)
 {
-	int congested = 0;
+	struct drbd_tconn *tconn = mdev->tconn;
+	struct net_conf *nc;
+	bool congested = false;
+	enum drbd_on_congestion on_congestion;
+
+	nc = rcu_dereference(tconn->net_conf);
+	on_congestion = nc ? nc->on_congestion : OC_BLOCK;
+	if (on_congestion == OC_BLOCK ||
+	    tconn->agreed_pro_version < 96)
+		return;
 
 	/* If I don't even have good local storage, we can not reasonably try
 	 * to pull ahead of the peer. We also need the local reference to make
 	 * sure mdev->act_log is there.
-	 * Note: caller has to make sure that net_conf is there.
 	 */
 	if (!get_ldev_if_state(mdev, D_UP_TO_DATE))
 		return;
 
-	if (mdev->net_conf->cong_fill &&
-	    atomic_read(&mdev->ap_in_flight) >= mdev->net_conf->cong_fill) {
+	if (nc->cong_fill &&
+	    atomic_read(&mdev->ap_in_flight) >= nc->cong_fill) {
 		dev_info(DEV, "Congestion-fill threshold reached\n");
-		congested = 1;
+		congested = true;
 	}
 
-	if (mdev->act_log->used >= mdev->net_conf->cong_extents) {
+	if (mdev->act_log->used >= nc->cong_extents) {
 		dev_info(DEV, "Congestion-extents threshold reached\n");
-		congested = 1;
+		congested = true;
 	}
 
 	if (congested) {
-		queue_barrier(mdev); /* last barrier, after mirrored writes */
+		/* start a new epoch for non-mirrored writes */
+		start_new_tl_epoch(mdev->tconn);
 
-		if (mdev->net_conf->on_congestion == OC_PULL_AHEAD)
+		if (on_congestion == OC_PULL_AHEAD)
 			_drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL);
-		else  /*mdev->net_conf->on_congestion == OC_DISCONNECT */
+		else  /*nc->on_congestion == OC_DISCONNECT */
 			_drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), 0, NULL);
 	}
 	put_ldev(mdev);
 }
 
-static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time)
+/* If this returns false, and req->private_bio is still set,
+ * this should be submitted locally.
+ *
+ * If it returns false, but req->private_bio is not set,
+ * we do not have access to good data :(
+ *
+ * Otherwise, this destroys req->private_bio, if any,
+ * and returns true.
+ */
+static bool do_remote_read(struct drbd_request *req)
+{
+	struct drbd_conf *mdev = req->w.mdev;
+	enum drbd_read_balancing rbm;
+
+	if (req->private_bio) {
+		if (!drbd_may_do_local_read(mdev,
+					req->i.sector, req->i.size)) {
+			bio_put(req->private_bio);
+			req->private_bio = NULL;
+			put_ldev(mdev);
+		}
+	}
+
+	if (mdev->state.pdsk != D_UP_TO_DATE)
+		return false;
+
+	if (req->private_bio == NULL)
+		return true;
+
+	/* TODO: improve read balancing decisions, take into account drbd
+	 * protocol, pending requests etc. */
+
+	rcu_read_lock();
+	rbm = rcu_dereference(mdev->ldev->disk_conf)->read_balancing;
+	rcu_read_unlock();
+
+	if (rbm == RB_PREFER_LOCAL && req->private_bio)
+		return false; /* submit locally */
+
+	if (remote_due_to_read_balancing(mdev, req->i.sector, rbm)) {
+		if (req->private_bio) {
+			bio_put(req->private_bio);
+			req->private_bio = NULL;
+			put_ldev(mdev);
+		}
+		return true;
+	}
+
+	return false;
+}
+
+/* returns number of connections (== 1, for drbd 8.4)
+ * expected to actually write this data,
+ * which does NOT include those that we are L_AHEAD for. */
+static int drbd_process_write_request(struct drbd_request *req)
+{
+	struct drbd_conf *mdev = req->w.mdev;
+	int remote, send_oos;
+
+	rcu_read_lock();
+	remote = drbd_should_do_remote(mdev->state);
+	if (remote) {
+		maybe_pull_ahead(mdev);
+		remote = drbd_should_do_remote(mdev->state);
+	}
+	send_oos = drbd_should_send_out_of_sync(mdev->state);
+	rcu_read_unlock();
+
+	/* Need to replicate writes.  Unless it is an empty flush,
+	 * which is better mapped to a DRBD P_BARRIER packet,
+	 * also for drbd wire protocol compatibility reasons.
+	 * If this was a flush, just start a new epoch.
+	 * Unless the current epoch was empty anyways, or we are not currently
+	 * replicating, in which case there is no point. */
+	if (unlikely(req->i.size == 0)) {
+		/* The only size==0 bios we expect are empty flushes. */
+		D_ASSERT(req->master_bio->bi_rw & REQ_FLUSH);
+		if (remote)
+			start_new_tl_epoch(mdev->tconn);
+		return 0;
+	}
+
+	if (!remote && !send_oos)
+		return 0;
+
+	D_ASSERT(!(remote && send_oos));
+
+	if (remote) {
+		_req_mod(req, TO_BE_SENT);
+		_req_mod(req, QUEUE_FOR_NET_WRITE);
+	} else if (drbd_set_out_of_sync(mdev, req->i.sector, req->i.size))
+		_req_mod(req, QUEUE_FOR_SEND_OOS);
+
+	return remote;
+}
+
+static void
+drbd_submit_req_private_bio(struct drbd_request *req)
+{
+	struct drbd_conf *mdev = req->w.mdev;
+	struct bio *bio = req->private_bio;
+	const int rw = bio_rw(bio);
+
+	bio->bi_bdev = mdev->ldev->backing_bdev;
+
+	/* State may have changed since we grabbed our reference on the
+	 * ->ldev member. Double check, and short-circuit to endio.
+	 * In case the last activity log transaction failed to get on
+	 * stable storage, and this is a WRITE, we may not even submit
+	 * this bio. */
+	if (get_ldev(mdev)) {
+		if (drbd_insert_fault(mdev,
+				      rw == WRITE ? DRBD_FAULT_DT_WR
+				    : rw == READ  ? DRBD_FAULT_DT_RD
+				    :               DRBD_FAULT_DT_RA))
+			bio_endio(bio, -EIO);
+		else
+			generic_make_request(bio);
+		put_ldev(mdev);
+	} else
+		bio_endio(bio, -EIO);
+}
+
+void __drbd_make_request(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time)
 {
 	const int rw = bio_rw(bio);
-	const int size = bio->bi_size;
-	const sector_t sector = bio->bi_sector;
-	struct drbd_tl_epoch *b = NULL;
+	struct bio_and_error m = { NULL, };
 	struct drbd_request *req;
-	int local, remote, send_oos = 0;
-	int err = -EIO;
-	int ret = 0;
-	union drbd_state s;
+	bool no_remote = false;
 
 	/* allocate outside of all locks; */
 	req = drbd_req_new(mdev, bio);
@@ -830,55 +1035,14 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, uns
 		 * if user cannot handle io errors, that's not our business. */
 		dev_err(DEV, "could not kmalloc() req\n");
 		bio_endio(bio, -ENOMEM);
-		return 0;
+		return;
 	}
 	req->start_time = start_time;
 
-	local = get_ldev(mdev);
-	if (!local) {
-		bio_put(req->private_bio); /* or we get a bio leak */
+	if (!get_ldev(mdev)) {
+		bio_put(req->private_bio);
 		req->private_bio = NULL;
 	}
-	if (rw == WRITE) {
-		/* Need to replicate writes.  Unless it is an empty flush,
-		 * which is better mapped to a DRBD P_BARRIER packet,
-		 * also for drbd wire protocol compatibility reasons. */
-		if (unlikely(size == 0)) {
-			/* The only size==0 bios we expect are empty flushes. */
-			D_ASSERT(bio->bi_rw & REQ_FLUSH);
-			remote = 0;
-		} else
-			remote = 1;
-	} else {
-		/* READ || READA */
-		if (local) {
-			if (!drbd_may_do_local_read(mdev, sector, size)) {
-				/* we could kick the syncer to
-				 * sync this extent asap, wait for
-				 * it, then continue locally.
-				 * Or just issue the request remotely.
-				 */
-				local = 0;
-				bio_put(req->private_bio);
-				req->private_bio = NULL;
-				put_ldev(mdev);
-			}
-		}
-		remote = !local && mdev->state.pdsk >= D_UP_TO_DATE;
-	}
-
-	/* If we have a disk, but a READA request is mapped to remote,
-	 * we are R_PRIMARY, D_INCONSISTENT, SyncTarget.
-	 * Just fail that READA request right here.
-	 *
-	 * THINK: maybe fail all READA when not local?
-	 *        or make this configurable...
-	 *        if network is slow, READA won't do any good.
-	 */
-	if (rw == READA && mdev->state.disk >= D_INCONSISTENT && !local) {
-		err = -EWOULDBLOCK;
-		goto fail_and_free_req;
-	}
 
 	/* For WRITES going to the local disk, grab a reference on the target
 	 * extent.  This waits for any resync activity in the corresponding
@@ -887,348 +1051,131 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, uns
 	 * of transactional on-disk meta data updates.
 	 * Empty flushes don't need to go into the activity log, they can only
 	 * flush data for pending writes which are already in there. */
-	if (rw == WRITE && local && size
+	if (rw == WRITE && req->private_bio && req->i.size
 	&& !test_bit(AL_SUSPENDED, &mdev->flags)) {
 		req->rq_state |= RQ_IN_ACT_LOG;
-		drbd_al_begin_io(mdev, sector);
-	}
-
-	s = mdev->state;
-	remote = remote && drbd_should_do_remote(s);
-	send_oos = rw == WRITE && drbd_should_send_oos(s);
-	D_ASSERT(!(remote && send_oos));
-
-	if (!(local || remote) && !is_susp(mdev->state)) {
-		if (__ratelimit(&drbd_ratelimit_state))
-			dev_err(DEV, "IO ERROR: neither local nor remote disk\n");
-		goto fail_free_complete;
+		drbd_al_begin_io(mdev, &req->i);
 	}
 
-	/* For WRITE request, we have to make sure that we have an
-	 * unused_spare_tle, in case we need to start a new epoch.
-	 * I try to be smart and avoid to pre-allocate always "just in case",
-	 * but there is a race between testing the bit and pointer outside the
-	 * spinlock, and grabbing the spinlock.
-	 * if we lost that race, we retry.  */
-	if (rw == WRITE && (remote || send_oos) &&
-	    mdev->unused_spare_tle == NULL &&
-	    test_bit(CREATE_BARRIER, &mdev->flags)) {
-allocate_barrier:
-		b = kmalloc(sizeof(struct drbd_tl_epoch), GFP_NOIO);
-		if (!b) {
-			dev_err(DEV, "Failed to alloc barrier.\n");
-			err = -ENOMEM;
-			goto fail_free_complete;
-		}
+	spin_lock_irq(&mdev->tconn->req_lock);
+	if (rw == WRITE) {
+		/* This may temporarily give up the req_lock,
+		 * but will re-aquire it before it returns here.
+		 * Needs to be before the check on drbd_suspended() */
+		complete_conflicting_writes(req);
 	}
 
-	/* GOOD, everything prepared, grab the spin_lock */
-	spin_lock_irq(&mdev->req_lock);
-
-	if (is_susp(mdev->state)) {
-		/* If we got suspended, use the retry mechanism of
-		   drbd_make_request() to restart processing of this
-		   bio. In the next call to drbd_make_request
-		   we sleep in inc_ap_bio() */
-		ret = 1;
-		spin_unlock_irq(&mdev->req_lock);
-		goto fail_free_complete;
-	}
+	/* no more giving up req_lock from now on! */
 
-	if (remote || send_oos) {
-		remote = drbd_should_do_remote(mdev->state);
-		send_oos = rw == WRITE && drbd_should_send_oos(mdev->state);
-		D_ASSERT(!(remote && send_oos));
-
-		if (!(remote || send_oos))
-			dev_warn(DEV, "lost connection while grabbing the req_lock!\n");
-		if (!(local || remote)) {
-			dev_err(DEV, "IO ERROR: neither local nor remote disk\n");
-			spin_unlock_irq(&mdev->req_lock);
-			goto fail_free_complete;
+	if (drbd_suspended(mdev)) {
+		/* push back and retry: */
+		req->rq_state |= RQ_POSTPONED;
+		if (req->private_bio) {
+			bio_put(req->private_bio);
+			req->private_bio = NULL;
+			put_ldev(mdev);
 		}
+		goto out;
 	}
 
-	if (b && mdev->unused_spare_tle == NULL) {
-		mdev->unused_spare_tle = b;
-		b = NULL;
-	}
-	if (rw == WRITE && (remote || send_oos) &&
-	    mdev->unused_spare_tle == NULL &&
-	    test_bit(CREATE_BARRIER, &mdev->flags)) {
-		/* someone closed the current epoch
-		 * while we were grabbing the spinlock */
-		spin_unlock_irq(&mdev->req_lock);
-		goto allocate_barrier;
-	}
-
-
 	/* Update disk stats */
 	_drbd_start_io_acct(mdev, req, bio);
 
-	/* _maybe_start_new_epoch(mdev);
-	 * If we need to generate a write barrier packet, we have to add the
-	 * new epoch (barrier) object, and queue the barrier packet for sending,
-	 * and queue the req's data after it _within the same lock_, otherwise
-	 * we have race conditions were the reorder domains could be mixed up.
-	 *
-	 * Even read requests may start a new epoch and queue the corresponding
-	 * barrier packet.  To get the write ordering right, we only have to
-	 * make sure that, if this is a write request and it triggered a
-	 * barrier packet, this request is queued within the same spinlock. */
-	if ((remote || send_oos) && mdev->unused_spare_tle &&
-	    test_and_clear_bit(CREATE_BARRIER, &mdev->flags)) {
-		_tl_add_barrier(mdev, mdev->unused_spare_tle);
-		mdev->unused_spare_tle = NULL;
-	} else {
-		D_ASSERT(!(remote && rw == WRITE &&
-			   test_bit(CREATE_BARRIER, &mdev->flags)));
+	/* We fail READ/READA early, if we can not serve it.
+	 * We must do this before req is registered on any lists.
+	 * Otherwise, drbd_req_complete() will queue failed READ for retry. */
+	if (rw != WRITE) {
+		if (!do_remote_read(req) && !req->private_bio)
+			goto nodata;
 	}
 
-	/* NOTE
-	 * Actually, 'local' may be wrong here already, since we may have failed
-	 * to write to the meta data, and may become wrong anytime because of
-	 * local io-error for some other request, which would lead to us
-	 * "detaching" the local disk.
-	 *
-	 * 'remote' may become wrong any time because the network could fail.
-	 *
-	 * This is a harmless race condition, though, since it is handled
-	 * correctly at the appropriate places; so it just defers the failure
-	 * of the respective operation.
-	 */
-
-	/* mark them early for readability.
-	 * this just sets some state flags. */
-	if (remote)
-		_req_mod(req, to_be_send);
-	if (local)
-		_req_mod(req, to_be_submitted);
-
-	/* check this request on the collision detection hash tables.
-	 * if we have a conflict, just complete it here.
-	 * THINK do we want to check reads, too? (I don't think so...) */
-	if (rw == WRITE && _req_conflicts(req))
-		goto fail_conflicting;
+	/* which transfer log epoch does this belong to? */
+	req->epoch = atomic_read(&mdev->tconn->current_tle_nr);
 
 	/* no point in adding empty flushes to the transfer log,
 	 * they are mapped to drbd barriers already. */
-	if (likely(size!=0))
-		list_add_tail(&req->tl_requests, &mdev->newest_tle->requests);
+	if (likely(req->i.size!=0)) {
+		if (rw == WRITE)
+			mdev->tconn->current_tle_writes++;
 
-	/* NOTE remote first: to get the concurrent write detection right,
-	 * we must register the request before start of local IO.  */
-	if (remote) {
-		/* either WRITE and C_CONNECTED,
-		 * or READ, and no local disk,
-		 * or READ, but not in sync.
-		 */
-		_req_mod(req, (rw == WRITE)
-				? queue_for_net_write
-				: queue_for_net_read);
+		list_add_tail(&req->tl_requests, &mdev->tconn->transfer_log);
 	}
-	if (send_oos && drbd_set_out_of_sync(mdev, sector, size))
-		_req_mod(req, queue_for_send_oos);
 
-	if (remote &&
-	    mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96)
-		maybe_pull_ahead(mdev);
-
-	/* If this was a flush, queue a drbd barrier/start a new epoch.
-	 * Unless the current epoch was empty anyways, or we are not currently
-	 * replicating, in which case there is no point. */
-	if (unlikely(bio->bi_rw & REQ_FLUSH)
-		&& mdev->newest_tle->n_writes
-		&& drbd_should_do_remote(mdev->state))
-		queue_barrier(mdev);
-
-	spin_unlock_irq(&mdev->req_lock);
-	kfree(b); /* if someone else has beaten us to it... */
-
-	if (local) {
-		req->private_bio->bi_bdev = mdev->ldev->backing_bdev;
-
-		/* State may have changed since we grabbed our reference on the
-		 * mdev->ldev member. Double check, and short-circuit to endio.
-		 * In case the last activity log transaction failed to get on
-		 * stable storage, and this is a WRITE, we may not even submit
-		 * this bio. */
-		if (get_ldev(mdev)) {
-			if (drbd_insert_fault(mdev,   rw == WRITE ? DRBD_FAULT_DT_WR
-						    : rw == READ  ? DRBD_FAULT_DT_RD
-						    :               DRBD_FAULT_DT_RA))
-				bio_endio(req->private_bio, -EIO);
-			else
-				generic_make_request(req->private_bio);
-			put_ldev(mdev);
+	if (rw == WRITE) {
+		if (!drbd_process_write_request(req))
+			no_remote = true;
+	} else {
+		/* We either have a private_bio, or we can read from remote.
+		 * Otherwise we had done the goto nodata above. */
+		if (req->private_bio == NULL) {
+			_req_mod(req, TO_BE_SENT);
+			_req_mod(req, QUEUE_FOR_NET_READ);
 		} else
-			bio_endio(req->private_bio, -EIO);
+			no_remote = true;
 	}
 
-	return 0;
-
-fail_conflicting:
-	/* this is a conflicting request.
-	 * even though it may have been only _partially_
-	 * overlapping with one of the currently pending requests,
-	 * without even submitting or sending it, we will
-	 * pretend that it was successfully served right now.
-	 */
-	_drbd_end_io_acct(mdev, req);
-	spin_unlock_irq(&mdev->req_lock);
-	if (remote)
-		dec_ap_pending(mdev);
-	/* THINK: do we want to fail it (-EIO), or pretend success?
-	 * this pretends success. */
-	err = 0;
-
-fail_free_complete:
-	if (req->rq_state & RQ_IN_ACT_LOG)
-		drbd_al_complete_io(mdev, sector);
-fail_and_free_req:
-	if (local) {
-		bio_put(req->private_bio);
-		req->private_bio = NULL;
-		put_ldev(mdev);
+	if (req->private_bio) {
+		/* needs to be marked within the same spinlock */
+		_req_mod(req, TO_BE_SUBMITTED);
+		/* but we need to give up the spinlock to submit */
+		spin_unlock_irq(&mdev->tconn->req_lock);
+		drbd_submit_req_private_bio(req);
+		spin_lock_irq(&mdev->tconn->req_lock);
+	} else if (no_remote) {
+nodata:
+		if (__ratelimit(&drbd_ratelimit_state))
+			dev_err(DEV, "IO ERROR: neither local nor remote data, sector %llu+%u\n",
+					(unsigned long long)req->i.sector, req->i.size >> 9);
+		/* A write may have been queued for send_oos, however.
+		 * So we can not simply free it, we must go through drbd_req_put_completion_ref() */
 	}
-	if (!ret)
-		bio_endio(bio, err);
-
-	drbd_req_free(req);
-	dec_ap_bio(mdev);
-	kfree(b);
-
-	return ret;
-}
 
-/* helper function for drbd_make_request
- * if we can determine just by the mdev (state) that this request will fail,
- * return 1
- * otherwise return 0
- */
-static int drbd_fail_request_early(struct drbd_conf *mdev, int is_write)
-{
-	if (mdev->state.role != R_PRIMARY &&
-		(!allow_oos || is_write)) {
-		if (__ratelimit(&drbd_ratelimit_state)) {
-			dev_err(DEV, "Process %s[%u] tried to %s; "
-			    "since we are not in Primary state, "
-			    "we cannot allow this\n",
-			    current->comm, current->pid,
-			    is_write ? "WRITE" : "READ");
-		}
-		return 1;
-	}
+out:
+	if (drbd_req_put_completion_ref(req, &m, 1))
+		kref_put(&req->kref, drbd_req_destroy);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
-	return 0;
+	if (m.bio)
+		complete_master_bio(mdev, &m);
+	return;
 }
 
 void drbd_make_request(struct request_queue *q, struct bio *bio)
 {
-	unsigned int s_enr, e_enr;
 	struct drbd_conf *mdev = (struct drbd_conf *) q->queuedata;
 	unsigned long start_time;
 
-	if (drbd_fail_request_early(mdev, bio_data_dir(bio) & WRITE)) {
-		bio_endio(bio, -EPERM);
-		return;
-	}
-
 	start_time = jiffies;
 
 	/*
 	 * what we "blindly" assume:
 	 */
-	D_ASSERT((bio->bi_size & 0x1ff) == 0);
-
-	/* to make some things easier, force alignment of requests within the
-	 * granularity of our hash tables */
-	s_enr = bio->bi_sector >> HT_SHIFT;
-	e_enr = bio->bi_size ? (bio->bi_sector+(bio->bi_size>>9)-1) >> HT_SHIFT : s_enr;
-
-	if (likely(s_enr == e_enr)) {
-		do {
-			inc_ap_bio(mdev, 1);
-		} while (drbd_make_request_common(mdev, bio, start_time));
-		return;
-	}
-
-	/* can this bio be split generically?
-	 * Maybe add our own split-arbitrary-bios function. */
-	if (bio->bi_vcnt != 1 || bio->bi_idx != 0 || bio->bi_size > DRBD_MAX_BIO_SIZE) {
-		/* rather error out here than BUG in bio_split */
-		dev_err(DEV, "bio would need to, but cannot, be split: "
-		    "(vcnt=%u,idx=%u,size=%u,sector=%llu)\n",
-		    bio->bi_vcnt, bio->bi_idx, bio->bi_size,
-		    (unsigned long long)bio->bi_sector);
-		bio_endio(bio, -EINVAL);
-	} else {
-		/* This bio crosses some boundary, so we have to split it. */
-		struct bio_pair *bp;
-		/* works for the "do not cross hash slot boundaries" case
-		 * e.g. sector 262269, size 4096
-		 * s_enr = 262269 >> 6 = 4097
-		 * e_enr = (262269+8-1) >> 6 = 4098
-		 * HT_SHIFT = 6
-		 * sps = 64, mask = 63
-		 * first_sectors = 64 - (262269 & 63) = 3
-		 */
-		const sector_t sect = bio->bi_sector;
-		const int sps = 1 << HT_SHIFT; /* sectors per slot */
-		const int mask = sps - 1;
-		const sector_t first_sectors = sps - (sect & mask);
-		bp = bio_split(bio, first_sectors);
+	D_ASSERT(IS_ALIGNED(bio->bi_size, 512));
 
-		/* we need to get a "reference count" (ap_bio_cnt)
-		 * to avoid races with the disconnect/reconnect/suspend code.
-		 * In case we need to split the bio here, we need to get three references
-		 * atomically, otherwise we might deadlock when trying to submit the
-		 * second one! */
-		inc_ap_bio(mdev, 3);
-
-		D_ASSERT(e_enr == s_enr + 1);
-
-		while (drbd_make_request_common(mdev, &bp->bio1, start_time))
-			inc_ap_bio(mdev, 1);
-
-		while (drbd_make_request_common(mdev, &bp->bio2, start_time))
-			inc_ap_bio(mdev, 1);
-
-		dec_ap_bio(mdev);
-
-		bio_pair_release(bp);
-	}
+	inc_ap_bio(mdev);
+	__drbd_make_request(mdev, bio, start_time);
 }
 
-/* This is called by bio_add_page().  With this function we reduce
- * the number of BIOs that span over multiple DRBD_MAX_BIO_SIZEs
- * units (was AL_EXTENTs).
+/* This is called by bio_add_page().
+ *
+ * q->max_hw_sectors and other global limits are already enforced there.
  *
- * we do the calculation within the lower 32bit of the byte offsets,
- * since we don't care for actual offset, but only check whether it
- * would cross "activity log extent" boundaries.
+ * We need to call down to our lower level device,
+ * in case it has special restrictions.
+ *
+ * We also may need to enforce configured max-bio-bvecs limits.
  *
  * As long as the BIO is empty we have to allow at least one bvec,
- * regardless of size and offset.  so the resulting bio may still
- * cross extent boundaries.  those are dealt with (bio_split) in
- * drbd_make_request.
+ * regardless of size and offset, so no need to ask lower levels.
  */
 int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec)
 {
 	struct drbd_conf *mdev = (struct drbd_conf *) q->queuedata;
-	unsigned int bio_offset =
-		(unsigned int)bvm->bi_sector << 9; /* 32 bit */
 	unsigned int bio_size = bvm->bi_size;
-	int limit, backing_limit;
-
-	limit = DRBD_MAX_BIO_SIZE
-	      - ((bio_offset & (DRBD_MAX_BIO_SIZE-1)) + bio_size);
-	if (limit < 0)
-		limit = 0;
-	if (bio_size == 0) {
-		if (limit <= bvec->bv_len)
-			limit = bvec->bv_len;
-	} else if (limit && get_ldev(mdev)) {
+	int limit = DRBD_MAX_BIO_SIZE;
+	int backing_limit;
+
+	if (bio_size && get_ldev(mdev)) {
 		struct request_queue * const b =
 			mdev->ldev->backing_bdev->bd_disk->queue;
 		if (b->merge_bvec_fn) {
@@ -1240,24 +1187,38 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct
 	return limit;
 }
 
+struct drbd_request *find_oldest_request(struct drbd_tconn *tconn)
+{
+	/* Walk the transfer log,
+	 * and find the oldest not yet completed request */
+	struct drbd_request *r;
+	list_for_each_entry(r, &tconn->transfer_log, tl_requests) {
+		if (atomic_read(&r->completion_ref))
+			return r;
+	}
+	return NULL;
+}
+
 void request_timer_fn(unsigned long data)
 {
 	struct drbd_conf *mdev = (struct drbd_conf *) data;
+	struct drbd_tconn *tconn = mdev->tconn;
 	struct drbd_request *req; /* oldest request */
-	struct list_head *le;
+	struct net_conf *nc;
 	unsigned long ent = 0, dt = 0, et, nt; /* effective timeout = ko_count * timeout */
 	unsigned long now;
 
-	if (get_net_conf(mdev)) {
-		if (mdev->state.conn >= C_WF_REPORT_PARAMS)
-			ent = mdev->net_conf->timeout*HZ/10
-				* mdev->net_conf->ko_count;
-		put_net_conf(mdev);
-	}
+	rcu_read_lock();
+	nc = rcu_dereference(tconn->net_conf);
+	if (nc && mdev->state.conn >= C_WF_REPORT_PARAMS)
+		ent = nc->timeout * HZ/10 * nc->ko_count;
+
 	if (get_ldev(mdev)) { /* implicit state.disk >= D_INCONSISTENT */
-		dt = mdev->ldev->dc.disk_timeout * HZ / 10;
+		dt = rcu_dereference(mdev->ldev->disk_conf)->disk_timeout * HZ / 10;
 		put_ldev(mdev);
 	}
+	rcu_read_unlock();
+
 	et = min_not_zero(dt, ent);
 
 	if (!et)
@@ -1265,17 +1226,14 @@ void request_timer_fn(unsigned long data)
 
 	now = jiffies;
 
-	spin_lock_irq(&mdev->req_lock);
-	le = &mdev->oldest_tle->requests;
-	if (list_empty(le)) {
-		spin_unlock_irq(&mdev->req_lock);
+	spin_lock_irq(&tconn->req_lock);
+	req = find_oldest_request(tconn);
+	if (!req) {
+		spin_unlock_irq(&tconn->req_lock);
 		mod_timer(&mdev->request_timer, now + et);
 		return;
 	}
 
-	le = le->prev;
-	req = list_entry(le, struct drbd_request, tl_requests);
-
 	/* The request is considered timed out, if
 	 * - we have some effective timeout from the configuration,
 	 *   with above state restrictions applied,
@@ -1294,17 +1252,17 @@ void request_timer_fn(unsigned long data)
 	 */
 	if (ent && req->rq_state & RQ_NET_PENDING &&
 		 time_after(now, req->start_time + ent) &&
-		!time_in_range(now, mdev->last_reconnect_jif, mdev->last_reconnect_jif + ent)) {
+		!time_in_range(now, tconn->last_reconnect_jif, tconn->last_reconnect_jif + ent)) {
 		dev_warn(DEV, "Remote failed to finish a request within ko-count * timeout\n");
 		_drbd_set_state(_NS(mdev, conn, C_TIMEOUT), CS_VERBOSE | CS_HARD, NULL);
 	}
-	if (dt && req->rq_state & RQ_LOCAL_PENDING &&
+	if (dt && req->rq_state & RQ_LOCAL_PENDING && req->w.mdev == mdev &&
 		 time_after(now, req->start_time + dt) &&
 		!time_in_range(now, mdev->last_reattach_jif, mdev->last_reattach_jif + dt)) {
 		dev_warn(DEV, "Local backing device failed to meet the disk-timeout\n");
 		__drbd_chk_io_error(mdev, DRBD_FORCE_DETACH);
 	}
 	nt = (time_after(now, req->start_time + et) ? now : req->start_time) + et;
-	spin_unlock_irq(&mdev->req_lock);
+	spin_unlock_irq(&tconn->req_lock);
 	mod_timer(&mdev->request_timer, nt);
 }
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index 3d21119..016de6b 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -77,40 +77,41 @@
  */
 
 enum drbd_req_event {
-	created,
-	to_be_send,
-	to_be_submitted,
+	CREATED,
+	TO_BE_SENT,
+	TO_BE_SUBMITTED,
 
 	/* XXX yes, now I am inconsistent...
 	 * these are not "events" but "actions"
 	 * oh, well... */
-	queue_for_net_write,
-	queue_for_net_read,
-	queue_for_send_oos,
-
-	send_canceled,
-	send_failed,
-	handed_over_to_network,
-	oos_handed_to_network,
-	connection_lost_while_pending,
-	read_retry_remote_canceled,
-	recv_acked_by_peer,
-	write_acked_by_peer,
-	write_acked_by_peer_and_sis, /* and set_in_sync */
-	conflict_discarded_by_peer,
-	neg_acked,
-	barrier_acked, /* in protocol A and B */
-	data_received, /* (remote read) */
-
-	read_completed_with_error,
-	read_ahead_completed_with_error,
-	write_completed_with_error,
-	abort_disk_io,
-	completed_ok,
-	resend,
-	fail_frozen_disk_io,
-	restart_frozen_disk_io,
-	nothing, /* for tracing only */
+	QUEUE_FOR_NET_WRITE,
+	QUEUE_FOR_NET_READ,
+	QUEUE_FOR_SEND_OOS,
+
+	SEND_CANCELED,
+	SEND_FAILED,
+	HANDED_OVER_TO_NETWORK,
+	OOS_HANDED_TO_NETWORK,
+	CONNECTION_LOST_WHILE_PENDING,
+	READ_RETRY_REMOTE_CANCELED,
+	RECV_ACKED_BY_PEER,
+	WRITE_ACKED_BY_PEER,
+	WRITE_ACKED_BY_PEER_AND_SIS, /* and set_in_sync */
+	CONFLICT_RESOLVED,
+	POSTPONE_WRITE,
+	NEG_ACKED,
+	BARRIER_ACKED, /* in protocol A and B */
+	DATA_RECEIVED, /* (remote read) */
+
+	READ_COMPLETED_WITH_ERROR,
+	READ_AHEAD_COMPLETED_WITH_ERROR,
+	WRITE_COMPLETED_WITH_ERROR,
+	ABORT_DISK_IO,
+	COMPLETED_OK,
+	RESEND,
+	FAIL_FROZEN_DISK_IO,
+	RESTART_FROZEN_DISK_IO,
+	NOTHING,
 };
 
 /* encoding of request states for now.  we don't actually need that many bits.
@@ -142,8 +143,8 @@ enum drbd_req_state_bits {
 	 *        recv_ack (B) or implicit "ack" (A),
 	 *        still waiting for the barrier ack.
 	 *        master_bio may already be completed and invalidated.
-	 * 11100: write_acked (C),
-	 *        data_received (for remote read, any protocol)
+	 * 11100: write acked (C),
+	 *        data received (for remote read, any protocol)
 	 *        or finally the barrier ack has arrived (B,A)...
 	 *        request can be freed
 	 * 01100: neg-acked (write, protocol C)
@@ -198,6 +199,22 @@ enum drbd_req_state_bits {
 
 	/* Should call drbd_al_complete_io() for this request... */
 	__RQ_IN_ACT_LOG,
+
+	/* The peer has sent a retry ACK */
+	__RQ_POSTPONED,
+
+	/* would have been completed,
+	 * but was not, because of drbd_suspended() */
+	__RQ_COMPLETION_SUSP,
+
+	/* We expect a receive ACK (wire proto B) */
+	__RQ_EXP_RECEIVE_ACK,
+
+	/* We expect a write ACK (wite proto C) */
+	__RQ_EXP_WRITE_ACK,
+
+	/* waiting for a barrier ack, did an extra kref_get */
+	__RQ_EXP_BARR_ACK,
 };
 
 #define RQ_LOCAL_PENDING   (1UL << __RQ_LOCAL_PENDING)
@@ -219,56 +236,16 @@ enum drbd_req_state_bits {
 
 #define RQ_WRITE           (1UL << __RQ_WRITE)
 #define RQ_IN_ACT_LOG      (1UL << __RQ_IN_ACT_LOG)
+#define RQ_POSTPONED	   (1UL << __RQ_POSTPONED)
+#define RQ_COMPLETION_SUSP (1UL << __RQ_COMPLETION_SUSP)
+#define RQ_EXP_RECEIVE_ACK (1UL << __RQ_EXP_RECEIVE_ACK)
+#define RQ_EXP_WRITE_ACK   (1UL << __RQ_EXP_WRITE_ACK)
+#define RQ_EXP_BARR_ACK    (1UL << __RQ_EXP_BARR_ACK)
 
 /* For waking up the frozen transfer log mod_req() has to return if the request
    should be counted in the epoch object*/
-#define MR_WRITE_SHIFT 0
-#define MR_WRITE       (1 << MR_WRITE_SHIFT)
-#define MR_READ_SHIFT  1
-#define MR_READ        (1 << MR_READ_SHIFT)
-
-/* epoch entries */
-static inline
-struct hlist_head *ee_hash_slot(struct drbd_conf *mdev, sector_t sector)
-{
-	BUG_ON(mdev->ee_hash_s == 0);
-	return mdev->ee_hash +
-		((unsigned int)(sector>>HT_SHIFT) % mdev->ee_hash_s);
-}
-
-/* transfer log (drbd_request objects) */
-static inline
-struct hlist_head *tl_hash_slot(struct drbd_conf *mdev, sector_t sector)
-{
-	BUG_ON(mdev->tl_hash_s == 0);
-	return mdev->tl_hash +
-		((unsigned int)(sector>>HT_SHIFT) % mdev->tl_hash_s);
-}
-
-/* application reads (drbd_request objects) */
-static struct hlist_head *ar_hash_slot(struct drbd_conf *mdev, sector_t sector)
-{
-	return mdev->app_reads_hash
-		+ ((unsigned int)(sector) % APP_R_HSIZE);
-}
-
-/* when we receive the answer for a read request,
- * verify that we actually know about it */
-static inline struct drbd_request *_ar_id_to_req(struct drbd_conf *mdev,
-	u64 id, sector_t sector)
-{
-	struct hlist_head *slot = ar_hash_slot(mdev, sector);
-	struct hlist_node *n;
-	struct drbd_request *req;
-
-	hlist_for_each_entry(req, n, slot, collision) {
-		if ((unsigned long)req == (unsigned long)id) {
-			D_ASSERT(req->sector == sector);
-			return req;
-		}
-	}
-	return NULL;
-}
+#define MR_WRITE       1
+#define MR_READ        2
 
 static inline void drbd_req_make_private_bio(struct drbd_request *req, struct bio *bio_src)
 {
@@ -278,41 +255,10 @@ static inline void drbd_req_make_private_bio(struct drbd_request *req, struct bi
 	req->private_bio = bio;
 
 	bio->bi_private  = req;
-	bio->bi_end_io   = drbd_endio_pri;
+	bio->bi_end_io   = drbd_request_endio;
 	bio->bi_next     = NULL;
 }
 
-static inline struct drbd_request *drbd_req_new(struct drbd_conf *mdev,
-	struct bio *bio_src)
-{
-	struct drbd_request *req =
-		mempool_alloc(drbd_request_mempool, GFP_NOIO);
-	if (likely(req)) {
-		drbd_req_make_private_bio(req, bio_src);
-
-		req->rq_state    = bio_data_dir(bio_src) == WRITE ? RQ_WRITE : 0;
-		req->mdev        = mdev;
-		req->master_bio  = bio_src;
-		req->epoch       = 0;
-		req->sector      = bio_src->bi_sector;
-		req->size        = bio_src->bi_size;
-		INIT_HLIST_NODE(&req->collision);
-		INIT_LIST_HEAD(&req->tl_requests);
-		INIT_LIST_HEAD(&req->w.list);
-	}
-	return req;
-}
-
-static inline void drbd_req_free(struct drbd_request *req)
-{
-	mempool_free(req, drbd_request_mempool);
-}
-
-static inline int overlaps(sector_t s1, int l1, sector_t s2, int l2)
-{
-	return !((s1 + (l1>>9) <= s2) || (s1 >= s2 + (l2>>9)));
-}
-
 /* Short lived temporary struct on the stack.
  * We could squirrel the error to be returned into
  * bio->bi_size, or similar. But that would be too ugly. */
@@ -321,6 +267,7 @@ struct bio_and_error {
 	int error;
 };
 
+extern void drbd_req_destroy(struct kref *kref);
 extern void _req_may_be_done(struct drbd_request *req,
 		struct bio_and_error *m);
 extern int __req_mod(struct drbd_request *req, enum drbd_req_event what,
@@ -328,13 +275,17 @@ extern int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 extern void complete_master_bio(struct drbd_conf *mdev,
 		struct bio_and_error *m);
 extern void request_timer_fn(unsigned long data);
-extern void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what);
+extern void tl_restart(struct drbd_tconn *tconn, enum drbd_req_event what);
+extern void _tl_restart(struct drbd_tconn *tconn, enum drbd_req_event what);
+
+/* this is in drbd_main.c */
+extern void drbd_restart_request(struct drbd_request *req);
 
 /* use this if you don't want to deal with calling complete_master_bio()
  * outside the spinlock, e.g. when walking some list on cleanup. */
 static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what)
 {
-	struct drbd_conf *mdev = req->mdev;
+	struct drbd_conf *mdev = req->w.mdev;
 	struct bio_and_error m;
 	int rv;
 
@@ -354,13 +305,13 @@ static inline int req_mod(struct drbd_request *req,
 		enum drbd_req_event what)
 {
 	unsigned long flags;
-	struct drbd_conf *mdev = req->mdev;
+	struct drbd_conf *mdev = req->w.mdev;
 	struct bio_and_error m;
 	int rv;
 
-	spin_lock_irqsave(&mdev->req_lock, flags);
+	spin_lock_irqsave(&mdev->tconn->req_lock, flags);
 	rv = __req_mod(req, what, &m);
-	spin_unlock_irqrestore(&mdev->req_lock, flags);
+	spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
 
 	if (m.bio)
 		complete_master_bio(mdev, &m);
@@ -368,7 +319,7 @@ static inline int req_mod(struct drbd_request *req,
 	return rv;
 }
 
-static inline bool drbd_should_do_remote(union drbd_state s)
+static inline bool drbd_should_do_remote(union drbd_dev_state s)
 {
 	return s.pdsk == D_UP_TO_DATE ||
 		(s.pdsk >= D_INCONSISTENT &&
@@ -378,7 +329,7 @@ static inline bool drbd_should_do_remote(union drbd_state s)
 	   That is equivalent since before 96 IO was frozen in the C_WF_BITMAP*
 	   states. */
 }
-static inline bool drbd_should_send_oos(union drbd_state s)
+static inline bool drbd_should_send_out_of_sync(union drbd_dev_state s)
 {
 	return s.conn == C_AHEAD || s.conn == C_WF_BITMAP_S;
 	/* pdsk = D_INCONSISTENT as a consequence. Protocol 96 check not necessary
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c
new file mode 100644
index 0000000..69ef352
--- /dev/null
+++ b/drivers/block/drbd/drbd_state.c
@@ -0,0 +1,1857 @@
+/*
+   drbd_state.c
+
+   This file is part of DRBD by Philipp Reisner and Lars Ellenberg.
+
+   Copyright (C) 2001-2008, LINBIT Information Technologies GmbH.
+   Copyright (C) 1999-2008, Philipp Reisner <philipp.reisner@linbit.com>.
+   Copyright (C) 2002-2008, Lars Ellenberg <lars.ellenberg@linbit.com>.
+
+   Thanks to Carter Burden, Bart Grantham and Gennadiy Nerubayev
+   from Logicworks, Inc. for making SDP replication support possible.
+
+   drbd is free software; you can redistribute 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.
+
+   drbd is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with drbd; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/drbd_limits.h>
+#include "drbd_int.h"
+#include "drbd_req.h"
+
+/* in drbd_main.c */
+extern void tl_abort_disk_io(struct drbd_conf *mdev);
+
+struct after_state_chg_work {
+	struct drbd_work w;
+	union drbd_state os;
+	union drbd_state ns;
+	enum chg_state_flags flags;
+	struct completion *done;
+};
+
+enum sanitize_state_warnings {
+	NO_WARNING,
+	ABORTED_ONLINE_VERIFY,
+	ABORTED_RESYNC,
+	CONNECTION_LOST_NEGOTIATING,
+	IMPLICITLY_UPGRADED_DISK,
+	IMPLICITLY_UPGRADED_PDSK,
+};
+
+static int w_after_state_ch(struct drbd_work *w, int unused);
+static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
+			   union drbd_state ns, enum chg_state_flags flags);
+static enum drbd_state_rv is_valid_state(struct drbd_conf *, union drbd_state);
+static enum drbd_state_rv is_valid_soft_transition(union drbd_state, union drbd_state, struct drbd_tconn *);
+static enum drbd_state_rv is_valid_transition(union drbd_state os, union drbd_state ns);
+static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state ns,
+				       enum sanitize_state_warnings *warn);
+
+static inline bool is_susp(union drbd_state s)
+{
+        return s.susp || s.susp_nod || s.susp_fen;
+}
+
+bool conn_all_vols_unconf(struct drbd_tconn *tconn)
+{
+	struct drbd_conf *mdev;
+	bool rv = true;
+	int vnr;
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+		if (mdev->state.disk != D_DISKLESS ||
+		    mdev->state.conn != C_STANDALONE ||
+		    mdev->state.role != R_SECONDARY) {
+			rv = false;
+			break;
+		}
+	}
+	rcu_read_unlock();
+
+	return rv;
+}
+
+/* Unfortunately the states where not correctly ordered, when
+   they where defined. therefore can not use max_t() here. */
+static enum drbd_role max_role(enum drbd_role role1, enum drbd_role role2)
+{
+	if (role1 == R_PRIMARY || role2 == R_PRIMARY)
+		return R_PRIMARY;
+	if (role1 == R_SECONDARY || role2 == R_SECONDARY)
+		return R_SECONDARY;
+	return R_UNKNOWN;
+}
+static enum drbd_role min_role(enum drbd_role role1, enum drbd_role role2)
+{
+	if (role1 == R_UNKNOWN || role2 == R_UNKNOWN)
+		return R_UNKNOWN;
+	if (role1 == R_SECONDARY || role2 == R_SECONDARY)
+		return R_SECONDARY;
+	return R_PRIMARY;
+}
+
+enum drbd_role conn_highest_role(struct drbd_tconn *tconn)
+{
+	enum drbd_role role = R_UNKNOWN;
+	struct drbd_conf *mdev;
+	int vnr;
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr)
+		role = max_role(role, mdev->state.role);
+	rcu_read_unlock();
+
+	return role;
+}
+
+enum drbd_role conn_highest_peer(struct drbd_tconn *tconn)
+{
+	enum drbd_role peer = R_UNKNOWN;
+	struct drbd_conf *mdev;
+	int vnr;
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr)
+		peer = max_role(peer, mdev->state.peer);
+	rcu_read_unlock();
+
+	return peer;
+}
+
+enum drbd_disk_state conn_highest_disk(struct drbd_tconn *tconn)
+{
+	enum drbd_disk_state ds = D_DISKLESS;
+	struct drbd_conf *mdev;
+	int vnr;
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr)
+		ds = max_t(enum drbd_disk_state, ds, mdev->state.disk);
+	rcu_read_unlock();
+
+	return ds;
+}
+
+enum drbd_disk_state conn_lowest_disk(struct drbd_tconn *tconn)
+{
+	enum drbd_disk_state ds = D_MASK;
+	struct drbd_conf *mdev;
+	int vnr;
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr)
+		ds = min_t(enum drbd_disk_state, ds, mdev->state.disk);
+	rcu_read_unlock();
+
+	return ds;
+}
+
+enum drbd_disk_state conn_highest_pdsk(struct drbd_tconn *tconn)
+{
+	enum drbd_disk_state ds = D_DISKLESS;
+	struct drbd_conf *mdev;
+	int vnr;
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr)
+		ds = max_t(enum drbd_disk_state, ds, mdev->state.pdsk);
+	rcu_read_unlock();
+
+	return ds;
+}
+
+enum drbd_conns conn_lowest_conn(struct drbd_tconn *tconn)
+{
+	enum drbd_conns conn = C_MASK;
+	struct drbd_conf *mdev;
+	int vnr;
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr)
+		conn = min_t(enum drbd_conns, conn, mdev->state.conn);
+	rcu_read_unlock();
+
+	return conn;
+}
+
+static bool no_peer_wf_report_params(struct drbd_tconn *tconn)
+{
+	struct drbd_conf *mdev;
+	int vnr;
+	bool rv = true;
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr)
+		if (mdev->state.conn == C_WF_REPORT_PARAMS) {
+			rv = false;
+			break;
+		}
+	rcu_read_unlock();
+
+	return rv;
+}
+
+
+/**
+ * cl_wide_st_chg() - true if the state change is a cluster wide one
+ * @mdev:	DRBD device.
+ * @os:		old (current) state.
+ * @ns:		new (wanted) state.
+ */
+static int cl_wide_st_chg(struct drbd_conf *mdev,
+			  union drbd_state os, union drbd_state ns)
+{
+	return (os.conn >= C_CONNECTED && ns.conn >= C_CONNECTED &&
+		 ((os.role != R_PRIMARY && ns.role == R_PRIMARY) ||
+		  (os.conn != C_STARTING_SYNC_T && ns.conn == C_STARTING_SYNC_T) ||
+		  (os.conn != C_STARTING_SYNC_S && ns.conn == C_STARTING_SYNC_S) ||
+		  (os.disk != D_FAILED && ns.disk == D_FAILED))) ||
+		(os.conn >= C_CONNECTED && ns.conn == C_DISCONNECTING) ||
+		(os.conn == C_CONNECTED && ns.conn == C_VERIFY_S) ||
+		(os.conn == C_CONNECTED && ns.conn == C_WF_REPORT_PARAMS);
+}
+
+static union drbd_state
+apply_mask_val(union drbd_state os, union drbd_state mask, union drbd_state val)
+{
+	union drbd_state ns;
+	ns.i = (os.i & ~mask.i) | val.i;
+	return ns;
+}
+
+enum drbd_state_rv
+drbd_change_state(struct drbd_conf *mdev, enum chg_state_flags f,
+		  union drbd_state mask, union drbd_state val)
+{
+	unsigned long flags;
+	union drbd_state ns;
+	enum drbd_state_rv rv;
+
+	spin_lock_irqsave(&mdev->tconn->req_lock, flags);
+	ns = apply_mask_val(drbd_read_state(mdev), mask, val);
+	rv = _drbd_set_state(mdev, ns, f, NULL);
+	spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
+
+	return rv;
+}
+
+/**
+ * drbd_force_state() - Impose a change which happens outside our control on our state
+ * @mdev:	DRBD device.
+ * @mask:	mask of state bits to change.
+ * @val:	value of new state bits.
+ */
+void drbd_force_state(struct drbd_conf *mdev,
+	union drbd_state mask, union drbd_state val)
+{
+	drbd_change_state(mdev, CS_HARD, mask, val);
+}
+
+static enum drbd_state_rv
+_req_st_cond(struct drbd_conf *mdev, union drbd_state mask,
+	     union drbd_state val)
+{
+	union drbd_state os, ns;
+	unsigned long flags;
+	enum drbd_state_rv rv;
+
+	if (test_and_clear_bit(CL_ST_CHG_SUCCESS, &mdev->flags))
+		return SS_CW_SUCCESS;
+
+	if (test_and_clear_bit(CL_ST_CHG_FAIL, &mdev->flags))
+		return SS_CW_FAILED_BY_PEER;
+
+	spin_lock_irqsave(&mdev->tconn->req_lock, flags);
+	os = drbd_read_state(mdev);
+	ns = sanitize_state(mdev, apply_mask_val(os, mask, val), NULL);
+	rv = is_valid_transition(os, ns);
+	if (rv >= SS_SUCCESS)
+		rv = SS_UNKNOWN_ERROR;  /* cont waiting, otherwise fail. */
+
+	if (!cl_wide_st_chg(mdev, os, ns))
+		rv = SS_CW_NO_NEED;
+	if (rv == SS_UNKNOWN_ERROR) {
+		rv = is_valid_state(mdev, ns);
+		if (rv >= SS_SUCCESS) {
+			rv = is_valid_soft_transition(os, ns, mdev->tconn);
+			if (rv >= SS_SUCCESS)
+				rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */
+		}
+	}
+	spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
+
+	return rv;
+}
+
+/**
+ * drbd_req_state() - Perform an eventually cluster wide state change
+ * @mdev:	DRBD device.
+ * @mask:	mask of state bits to change.
+ * @val:	value of new state bits.
+ * @f:		flags
+ *
+ * Should not be called directly, use drbd_request_state() or
+ * _drbd_request_state().
+ */
+static enum drbd_state_rv
+drbd_req_state(struct drbd_conf *mdev, union drbd_state mask,
+	       union drbd_state val, enum chg_state_flags f)
+{
+	struct completion done;
+	unsigned long flags;
+	union drbd_state os, ns;
+	enum drbd_state_rv rv;
+
+	init_completion(&done);
+
+	if (f & CS_SERIALIZE)
+		mutex_lock(mdev->state_mutex);
+
+	spin_lock_irqsave(&mdev->tconn->req_lock, flags);
+	os = drbd_read_state(mdev);
+	ns = sanitize_state(mdev, apply_mask_val(os, mask, val), NULL);
+	rv = is_valid_transition(os, ns);
+	if (rv < SS_SUCCESS) {
+		spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
+		goto abort;
+	}
+
+	if (cl_wide_st_chg(mdev, os, ns)) {
+		rv = is_valid_state(mdev, ns);
+		if (rv == SS_SUCCESS)
+			rv = is_valid_soft_transition(os, ns, mdev->tconn);
+		spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
+
+		if (rv < SS_SUCCESS) {
+			if (f & CS_VERBOSE)
+				print_st_err(mdev, os, ns, rv);
+			goto abort;
+		}
+
+		if (drbd_send_state_req(mdev, mask, val)) {
+			rv = SS_CW_FAILED_BY_PEER;
+			if (f & CS_VERBOSE)
+				print_st_err(mdev, os, ns, rv);
+			goto abort;
+		}
+
+		wait_event(mdev->state_wait,
+			(rv = _req_st_cond(mdev, mask, val)));
+
+		if (rv < SS_SUCCESS) {
+			if (f & CS_VERBOSE)
+				print_st_err(mdev, os, ns, rv);
+			goto abort;
+		}
+		spin_lock_irqsave(&mdev->tconn->req_lock, flags);
+		ns = apply_mask_val(drbd_read_state(mdev), mask, val);
+		rv = _drbd_set_state(mdev, ns, f, &done);
+	} else {
+		rv = _drbd_set_state(mdev, ns, f, &done);
+	}
+
+	spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
+
+	if (f & CS_WAIT_COMPLETE && rv == SS_SUCCESS) {
+		D_ASSERT(current != mdev->tconn->worker.task);
+		wait_for_completion(&done);
+	}
+
+abort:
+	if (f & CS_SERIALIZE)
+		mutex_unlock(mdev->state_mutex);
+
+	return rv;
+}
+
+/**
+ * _drbd_request_state() - Request a state change (with flags)
+ * @mdev:	DRBD device.
+ * @mask:	mask of state bits to change.
+ * @val:	value of new state bits.
+ * @f:		flags
+ *
+ * Cousin of drbd_request_state(), useful with the CS_WAIT_COMPLETE
+ * flag, or when logging of failed state change requests is not desired.
+ */
+enum drbd_state_rv
+_drbd_request_state(struct drbd_conf *mdev, union drbd_state mask,
+		    union drbd_state val, enum chg_state_flags f)
+{
+	enum drbd_state_rv rv;
+
+	wait_event(mdev->state_wait,
+		   (rv = drbd_req_state(mdev, mask, val, f)) != SS_IN_TRANSIENT_STATE);
+
+	return rv;
+}
+
+static void print_st(struct drbd_conf *mdev, char *name, union drbd_state ns)
+{
+	dev_err(DEV, " %s = { cs:%s ro:%s/%s ds:%s/%s %c%c%c%c%c%c }\n",
+	    name,
+	    drbd_conn_str(ns.conn),
+	    drbd_role_str(ns.role),
+	    drbd_role_str(ns.peer),
+	    drbd_disk_str(ns.disk),
+	    drbd_disk_str(ns.pdsk),
+	    is_susp(ns) ? 's' : 'r',
+	    ns.aftr_isp ? 'a' : '-',
+	    ns.peer_isp ? 'p' : '-',
+	    ns.user_isp ? 'u' : '-',
+	    ns.susp_fen ? 'F' : '-',
+	    ns.susp_nod ? 'N' : '-'
+	    );
+}
+
+void print_st_err(struct drbd_conf *mdev, union drbd_state os,
+	          union drbd_state ns, enum drbd_state_rv err)
+{
+	if (err == SS_IN_TRANSIENT_STATE)
+		return;
+	dev_err(DEV, "State change failed: %s\n", drbd_set_st_err_str(err));
+	print_st(mdev, " state", os);
+	print_st(mdev, "wanted", ns);
+}
+
+static long print_state_change(char *pb, union drbd_state os, union drbd_state ns,
+			       enum chg_state_flags flags)
+{
+	char *pbp;
+	pbp = pb;
+	*pbp = 0;
+
+	if (ns.role != os.role && flags & CS_DC_ROLE)
+		pbp += sprintf(pbp, "role( %s -> %s ) ",
+			       drbd_role_str(os.role),
+			       drbd_role_str(ns.role));
+	if (ns.peer != os.peer && flags & CS_DC_PEER)
+		pbp += sprintf(pbp, "peer( %s -> %s ) ",
+			       drbd_role_str(os.peer),
+			       drbd_role_str(ns.peer));
+	if (ns.conn != os.conn && flags & CS_DC_CONN)
+		pbp += sprintf(pbp, "conn( %s -> %s ) ",
+			       drbd_conn_str(os.conn),
+			       drbd_conn_str(ns.conn));
+	if (ns.disk != os.disk && flags & CS_DC_DISK)
+		pbp += sprintf(pbp, "disk( %s -> %s ) ",
+			       drbd_disk_str(os.disk),
+			       drbd_disk_str(ns.disk));
+	if (ns.pdsk != os.pdsk && flags & CS_DC_PDSK)
+		pbp += sprintf(pbp, "pdsk( %s -> %s ) ",
+			       drbd_disk_str(os.pdsk),
+			       drbd_disk_str(ns.pdsk));
+
+	return pbp - pb;
+}
+
+static void drbd_pr_state_change(struct drbd_conf *mdev, union drbd_state os, union drbd_state ns,
+				 enum chg_state_flags flags)
+{
+	char pb[300];
+	char *pbp = pb;
+
+	pbp += print_state_change(pbp, os, ns, flags ^ CS_DC_MASK);
+
+	if (ns.aftr_isp != os.aftr_isp)
+		pbp += sprintf(pbp, "aftr_isp( %d -> %d ) ",
+			       os.aftr_isp,
+			       ns.aftr_isp);
+	if (ns.peer_isp != os.peer_isp)
+		pbp += sprintf(pbp, "peer_isp( %d -> %d ) ",
+			       os.peer_isp,
+			       ns.peer_isp);
+	if (ns.user_isp != os.user_isp)
+		pbp += sprintf(pbp, "user_isp( %d -> %d ) ",
+			       os.user_isp,
+			       ns.user_isp);
+
+	if (pbp != pb)
+		dev_info(DEV, "%s\n", pb);
+}
+
+static void conn_pr_state_change(struct drbd_tconn *tconn, union drbd_state os, union drbd_state ns,
+				 enum chg_state_flags flags)
+{
+	char pb[300];
+	char *pbp = pb;
+
+	pbp += print_state_change(pbp, os, ns, flags);
+
+	if (is_susp(ns) != is_susp(os) && flags & CS_DC_SUSP)
+		pbp += sprintf(pbp, "susp( %d -> %d ) ",
+			       is_susp(os),
+			       is_susp(ns));
+
+	if (pbp != pb)
+		conn_info(tconn, "%s\n", pb);
+}
+
+
+/**
+ * is_valid_state() - Returns an SS_ error code if ns is not valid
+ * @mdev:	DRBD device.
+ * @ns:		State to consider.
+ */
+static enum drbd_state_rv
+is_valid_state(struct drbd_conf *mdev, union drbd_state ns)
+{
+	/* See drbd_state_sw_errors in drbd_strings.c */
+
+	enum drbd_fencing_p fp;
+	enum drbd_state_rv rv = SS_SUCCESS;
+	struct net_conf *nc;
+
+	rcu_read_lock();
+	fp = FP_DONT_CARE;
+	if (get_ldev(mdev)) {
+		fp = rcu_dereference(mdev->ldev->disk_conf)->fencing;
+		put_ldev(mdev);
+	}
+
+	nc = rcu_dereference(mdev->tconn->net_conf);
+	if (nc) {
+		if (!nc->two_primaries && ns.role == R_PRIMARY) {
+			if (ns.peer == R_PRIMARY)
+				rv = SS_TWO_PRIMARIES;
+			else if (conn_highest_peer(mdev->tconn) == R_PRIMARY)
+				rv = SS_O_VOL_PEER_PRI;
+		}
+	}
+
+	if (rv <= 0)
+		/* already found a reason to abort */;
+	else if (ns.role == R_SECONDARY && mdev->open_cnt)
+		rv = SS_DEVICE_IN_USE;
+
+	else if (ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.disk < D_UP_TO_DATE)
+		rv = SS_NO_UP_TO_DATE_DISK;
+
+	else if (fp >= FP_RESOURCE &&
+		 ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.pdsk >= D_UNKNOWN)
+		rv = SS_PRIMARY_NOP;
+
+	else if (ns.role == R_PRIMARY && ns.disk <= D_INCONSISTENT && ns.pdsk <= D_INCONSISTENT)
+		rv = SS_NO_UP_TO_DATE_DISK;
+
+	else if (ns.conn > C_CONNECTED && ns.disk < D_INCONSISTENT)
+		rv = SS_NO_LOCAL_DISK;
+
+	else if (ns.conn > C_CONNECTED && ns.pdsk < D_INCONSISTENT)
+		rv = SS_NO_REMOTE_DISK;
+
+	else if (ns.conn > C_CONNECTED && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE)
+		rv = SS_NO_UP_TO_DATE_DISK;
+
+	else if ((ns.conn == C_CONNECTED ||
+		  ns.conn == C_WF_BITMAP_S ||
+		  ns.conn == C_SYNC_SOURCE ||
+		  ns.conn == C_PAUSED_SYNC_S) &&
+		  ns.disk == D_OUTDATED)
+		rv = SS_CONNECTED_OUTDATES;
+
+	else if ((ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) &&
+		 (nc->verify_alg[0] == 0))
+		rv = SS_NO_VERIFY_ALG;
+
+	else if ((ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) &&
+		  mdev->tconn->agreed_pro_version < 88)
+		rv = SS_NOT_SUPPORTED;
+
+	else if (ns.conn >= C_CONNECTED && ns.pdsk == D_UNKNOWN)
+		rv = SS_CONNECTED_OUTDATES;
+
+	rcu_read_unlock();
+
+	return rv;
+}
+
+/**
+ * is_valid_soft_transition() - Returns an SS_ error code if the state transition is not possible
+ * This function limits state transitions that may be declined by DRBD. I.e.
+ * user requests (aka soft transitions).
+ * @mdev:	DRBD device.
+ * @ns:		new state.
+ * @os:		old state.
+ */
+static enum drbd_state_rv
+is_valid_soft_transition(union drbd_state os, union drbd_state ns, struct drbd_tconn *tconn)
+{
+	enum drbd_state_rv rv = SS_SUCCESS;
+
+	if ((ns.conn == C_STARTING_SYNC_T || ns.conn == C_STARTING_SYNC_S) &&
+	    os.conn > C_CONNECTED)
+		rv = SS_RESYNC_RUNNING;
+
+	if (ns.conn == C_DISCONNECTING && os.conn == C_STANDALONE)
+		rv = SS_ALREADY_STANDALONE;
+
+	if (ns.disk > D_ATTACHING && os.disk == D_DISKLESS)
+		rv = SS_IS_DISKLESS;
+
+	if (ns.conn == C_WF_CONNECTION && os.conn < C_UNCONNECTED)
+		rv = SS_NO_NET_CONFIG;
+
+	if (ns.disk == D_OUTDATED && os.disk < D_OUTDATED && os.disk != D_ATTACHING)
+		rv = SS_LOWER_THAN_OUTDATED;
+
+	if (ns.conn == C_DISCONNECTING && os.conn == C_UNCONNECTED)
+		rv = SS_IN_TRANSIENT_STATE;
+
+	/* if (ns.conn == os.conn && ns.conn == C_WF_REPORT_PARAMS)
+	   rv = SS_IN_TRANSIENT_STATE; */
+
+	/* While establishing a connection only allow cstate to change.
+	   Delay/refuse role changes, detach attach etc... */
+	if (test_bit(STATE_SENT, &tconn->flags) &&
+	    !(os.conn == C_WF_REPORT_PARAMS ||
+	      (ns.conn == C_WF_REPORT_PARAMS && os.conn == C_WF_CONNECTION)))
+		rv = SS_IN_TRANSIENT_STATE;
+
+	if ((ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) && os.conn < C_CONNECTED)
+		rv = SS_NEED_CONNECTION;
+
+	if ((ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) &&
+	    ns.conn != os.conn && os.conn > C_CONNECTED)
+		rv = SS_RESYNC_RUNNING;
+
+	if ((ns.conn == C_STARTING_SYNC_S || ns.conn == C_STARTING_SYNC_T) &&
+	    os.conn < C_CONNECTED)
+		rv = SS_NEED_CONNECTION;
+
+	if ((ns.conn == C_SYNC_TARGET || ns.conn == C_SYNC_SOURCE)
+	    && os.conn < C_WF_REPORT_PARAMS)
+		rv = SS_NEED_CONNECTION; /* No NetworkFailure -> SyncTarget etc... */
+
+	return rv;
+}
+
+static enum drbd_state_rv
+is_valid_conn_transition(enum drbd_conns oc, enum drbd_conns nc)
+{
+	/* no change -> nothing to do, at least for the connection part */
+	if (oc == nc)
+		return SS_NOTHING_TO_DO;
+
+	/* disconnect of an unconfigured connection does not make sense */
+	if (oc == C_STANDALONE && nc == C_DISCONNECTING)
+		return SS_ALREADY_STANDALONE;
+
+	/* from C_STANDALONE, we start with C_UNCONNECTED */
+	if (oc == C_STANDALONE && nc != C_UNCONNECTED)
+		return SS_NEED_CONNECTION;
+
+	/* When establishing a connection we need to go through WF_REPORT_PARAMS!
+	   Necessary to do the right thing upon invalidate-remote on a disconnected resource */
+	if (oc < C_WF_REPORT_PARAMS && nc >= C_CONNECTED)
+		return SS_NEED_CONNECTION;
+
+	/* After a network error only C_UNCONNECTED or C_DISCONNECTING may follow. */
+	if (oc >= C_TIMEOUT && oc <= C_TEAR_DOWN && nc != C_UNCONNECTED && nc != C_DISCONNECTING)
+		return SS_IN_TRANSIENT_STATE;
+
+	/* After C_DISCONNECTING only C_STANDALONE may follow */
+	if (oc == C_DISCONNECTING && nc != C_STANDALONE)
+		return SS_IN_TRANSIENT_STATE;
+
+	return SS_SUCCESS;
+}
+
+
+/**
+ * is_valid_transition() - Returns an SS_ error code if the state transition is not possible
+ * This limits hard state transitions. Hard state transitions are facts there are
+ * imposed on DRBD by the environment. E.g. disk broke or network broke down.
+ * But those hard state transitions are still not allowed to do everything.
+ * @ns:		new state.
+ * @os:		old state.
+ */
+static enum drbd_state_rv
+is_valid_transition(union drbd_state os, union drbd_state ns)
+{
+	enum drbd_state_rv rv;
+
+	rv = is_valid_conn_transition(os.conn, ns.conn);
+
+	/* we cannot fail (again) if we already detached */
+	if (ns.disk == D_FAILED && os.disk == D_DISKLESS)
+		rv = SS_IS_DISKLESS;
+
+	return rv;
+}
+
+static void print_sanitize_warnings(struct drbd_conf *mdev, enum sanitize_state_warnings warn)
+{
+	static const char *msg_table[] = {
+		[NO_WARNING] = "",
+		[ABORTED_ONLINE_VERIFY] = "Online-verify aborted.",
+		[ABORTED_RESYNC] = "Resync aborted.",
+		[CONNECTION_LOST_NEGOTIATING] = "Connection lost while negotiating, no data!",
+		[IMPLICITLY_UPGRADED_DISK] = "Implicitly upgraded disk",
+		[IMPLICITLY_UPGRADED_PDSK] = "Implicitly upgraded pdsk",
+	};
+
+	if (warn != NO_WARNING)
+		dev_warn(DEV, "%s\n", msg_table[warn]);
+}
+
+/**
+ * sanitize_state() - Resolves implicitly necessary additional changes to a state transition
+ * @mdev:	DRBD device.
+ * @os:		old state.
+ * @ns:		new state.
+ * @warn_sync_abort:
+ *
+ * When we loose connection, we have to set the state of the peers disk (pdsk)
+ * to D_UNKNOWN. This rule and many more along those lines are in this function.
+ */
+static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state ns,
+				       enum sanitize_state_warnings *warn)
+{
+	enum drbd_fencing_p fp;
+	enum drbd_disk_state disk_min, disk_max, pdsk_min, pdsk_max;
+
+	if (warn)
+		*warn = NO_WARNING;
+
+	fp = FP_DONT_CARE;
+	if (get_ldev(mdev)) {
+		rcu_read_lock();
+		fp = rcu_dereference(mdev->ldev->disk_conf)->fencing;
+		rcu_read_unlock();
+		put_ldev(mdev);
+	}
+
+	/* Implications from connection to peer and peer_isp */
+	if (ns.conn < C_CONNECTED) {
+		ns.peer_isp = 0;
+		ns.peer = R_UNKNOWN;
+		if (ns.pdsk > D_UNKNOWN || ns.pdsk < D_INCONSISTENT)
+			ns.pdsk = D_UNKNOWN;
+	}
+
+	/* Clear the aftr_isp when becoming unconfigured */
+	if (ns.conn == C_STANDALONE && ns.disk == D_DISKLESS && ns.role == R_SECONDARY)
+		ns.aftr_isp = 0;
+
+	/* An implication of the disk states onto the connection state */
+	/* Abort resync if a disk fails/detaches */
+	if (ns.conn > C_CONNECTED && (ns.disk <= D_FAILED || ns.pdsk <= D_FAILED)) {
+		if (warn)
+			*warn = ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T ?
+				ABORTED_ONLINE_VERIFY : ABORTED_RESYNC;
+		ns.conn = C_CONNECTED;
+	}
+
+	/* Connection breaks down before we finished "Negotiating" */
+	if (ns.conn < C_CONNECTED && ns.disk == D_NEGOTIATING &&
+	    get_ldev_if_state(mdev, D_NEGOTIATING)) {
+		if (mdev->ed_uuid == mdev->ldev->md.uuid[UI_CURRENT]) {
+			ns.disk = mdev->new_state_tmp.disk;
+			ns.pdsk = mdev->new_state_tmp.pdsk;
+		} else {
+			if (warn)
+				*warn = CONNECTION_LOST_NEGOTIATING;
+			ns.disk = D_DISKLESS;
+			ns.pdsk = D_UNKNOWN;
+		}
+		put_ldev(mdev);
+	}
+
+	/* D_CONSISTENT and D_OUTDATED vanish when we get connected */
+	if (ns.conn >= C_CONNECTED && ns.conn < C_AHEAD) {
+		if (ns.disk == D_CONSISTENT || ns.disk == D_OUTDATED)
+			ns.disk = D_UP_TO_DATE;
+		if (ns.pdsk == D_CONSISTENT || ns.pdsk == D_OUTDATED)
+			ns.pdsk = D_UP_TO_DATE;
+	}
+
+	/* Implications of the connection stat on the disk states */
+	disk_min = D_DISKLESS;
+	disk_max = D_UP_TO_DATE;
+	pdsk_min = D_INCONSISTENT;
+	pdsk_max = D_UNKNOWN;
+	switch ((enum drbd_conns)ns.conn) {
+	case C_WF_BITMAP_T:
+	case C_PAUSED_SYNC_T:
+	case C_STARTING_SYNC_T:
+	case C_WF_SYNC_UUID:
+	case C_BEHIND:
+		disk_min = D_INCONSISTENT;
+		disk_max = D_OUTDATED;
+		pdsk_min = D_UP_TO_DATE;
+		pdsk_max = D_UP_TO_DATE;
+		break;
+	case C_VERIFY_S:
+	case C_VERIFY_T:
+		disk_min = D_UP_TO_DATE;
+		disk_max = D_UP_TO_DATE;
+		pdsk_min = D_UP_TO_DATE;
+		pdsk_max = D_UP_TO_DATE;
+		break;
+	case C_CONNECTED:
+		disk_min = D_DISKLESS;
+		disk_max = D_UP_TO_DATE;
+		pdsk_min = D_DISKLESS;
+		pdsk_max = D_UP_TO_DATE;
+		break;
+	case C_WF_BITMAP_S:
+	case C_PAUSED_SYNC_S:
+	case C_STARTING_SYNC_S:
+	case C_AHEAD:
+		disk_min = D_UP_TO_DATE;
+		disk_max = D_UP_TO_DATE;
+		pdsk_min = D_INCONSISTENT;
+		pdsk_max = D_CONSISTENT; /* D_OUTDATED would be nice. But explicit outdate necessary*/
+		break;
+	case C_SYNC_TARGET:
+		disk_min = D_INCONSISTENT;
+		disk_max = D_INCONSISTENT;
+		pdsk_min = D_UP_TO_DATE;
+		pdsk_max = D_UP_TO_DATE;
+		break;
+	case C_SYNC_SOURCE:
+		disk_min = D_UP_TO_DATE;
+		disk_max = D_UP_TO_DATE;
+		pdsk_min = D_INCONSISTENT;
+		pdsk_max = D_INCONSISTENT;
+		break;
+	case C_STANDALONE:
+	case C_DISCONNECTING:
+	case C_UNCONNECTED:
+	case C_TIMEOUT:
+	case C_BROKEN_PIPE:
+	case C_NETWORK_FAILURE:
+	case C_PROTOCOL_ERROR:
+	case C_TEAR_DOWN:
+	case C_WF_CONNECTION:
+	case C_WF_REPORT_PARAMS:
+	case C_MASK:
+		break;
+	}
+	if (ns.disk > disk_max)
+		ns.disk = disk_max;
+
+	if (ns.disk < disk_min) {
+		if (warn)
+			*warn = IMPLICITLY_UPGRADED_DISK;
+		ns.disk = disk_min;
+	}
+	if (ns.pdsk > pdsk_max)
+		ns.pdsk = pdsk_max;
+
+	if (ns.pdsk < pdsk_min) {
+		if (warn)
+			*warn = IMPLICITLY_UPGRADED_PDSK;
+		ns.pdsk = pdsk_min;
+	}
+
+	if (fp == FP_STONITH &&
+	    (ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.pdsk > D_OUTDATED))
+		ns.susp_fen = 1; /* Suspend IO while fence-peer handler runs (peer lost) */
+
+	if (mdev->tconn->res_opts.on_no_data == OND_SUSPEND_IO &&
+	    (ns.role == R_PRIMARY && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE))
+		ns.susp_nod = 1; /* Suspend IO while no data available (no accessible data available) */
+
+	if (ns.aftr_isp || ns.peer_isp || ns.user_isp) {
+		if (ns.conn == C_SYNC_SOURCE)
+			ns.conn = C_PAUSED_SYNC_S;
+		if (ns.conn == C_SYNC_TARGET)
+			ns.conn = C_PAUSED_SYNC_T;
+	} else {
+		if (ns.conn == C_PAUSED_SYNC_S)
+			ns.conn = C_SYNC_SOURCE;
+		if (ns.conn == C_PAUSED_SYNC_T)
+			ns.conn = C_SYNC_TARGET;
+	}
+
+	return ns;
+}
+
+void drbd_resume_al(struct drbd_conf *mdev)
+{
+	if (test_and_clear_bit(AL_SUSPENDED, &mdev->flags))
+		dev_info(DEV, "Resumed AL updates\n");
+}
+
+/* helper for __drbd_set_state */
+static void set_ov_position(struct drbd_conf *mdev, enum drbd_conns cs)
+{
+	if (mdev->tconn->agreed_pro_version < 90)
+		mdev->ov_start_sector = 0;
+	mdev->rs_total = drbd_bm_bits(mdev);
+	mdev->ov_position = 0;
+	if (cs == C_VERIFY_T) {
+		/* starting online verify from an arbitrary position
+		 * does not fit well into the existing protocol.
+		 * on C_VERIFY_T, we initialize ov_left and friends
+		 * implicitly in receive_DataRequest once the
+		 * first P_OV_REQUEST is received */
+		mdev->ov_start_sector = ~(sector_t)0;
+	} else {
+		unsigned long bit = BM_SECT_TO_BIT(mdev->ov_start_sector);
+		if (bit >= mdev->rs_total) {
+			mdev->ov_start_sector =
+				BM_BIT_TO_SECT(mdev->rs_total - 1);
+			mdev->rs_total = 1;
+		} else
+			mdev->rs_total -= bit;
+		mdev->ov_position = mdev->ov_start_sector;
+	}
+	mdev->ov_left = mdev->rs_total;
+}
+
+/**
+ * __drbd_set_state() - Set a new DRBD state
+ * @mdev:	DRBD device.
+ * @ns:		new state.
+ * @flags:	Flags
+ * @done:	Optional completion, that will get completed after the after_state_ch() finished
+ *
+ * Caller needs to hold req_lock, and global_state_lock. Do not call directly.
+ */
+enum drbd_state_rv
+__drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
+	         enum chg_state_flags flags, struct completion *done)
+{
+	union drbd_state os;
+	enum drbd_state_rv rv = SS_SUCCESS;
+	enum sanitize_state_warnings ssw;
+	struct after_state_chg_work *ascw;
+
+	os = drbd_read_state(mdev);
+
+	ns = sanitize_state(mdev, ns, &ssw);
+	if (ns.i == os.i)
+		return SS_NOTHING_TO_DO;
+
+	rv = is_valid_transition(os, ns);
+	if (rv < SS_SUCCESS)
+		return rv;
+
+	if (!(flags & CS_HARD)) {
+		/*  pre-state-change checks ; only look at ns  */
+		/* See drbd_state_sw_errors in drbd_strings.c */
+
+		rv = is_valid_state(mdev, ns);
+		if (rv < SS_SUCCESS) {
+			/* If the old state was illegal as well, then let
+			   this happen...*/
+
+			if (is_valid_state(mdev, os) == rv)
+				rv = is_valid_soft_transition(os, ns, mdev->tconn);
+		} else
+			rv = is_valid_soft_transition(os, ns, mdev->tconn);
+	}
+
+	if (rv < SS_SUCCESS) {
+		if (flags & CS_VERBOSE)
+			print_st_err(mdev, os, ns, rv);
+		return rv;
+	}
+
+	print_sanitize_warnings(mdev, ssw);
+
+	drbd_pr_state_change(mdev, os, ns, flags);
+
+	/* Display changes to the susp* flags that where caused by the call to
+	   sanitize_state(). Only display it here if we where not called from
+	   _conn_request_state() */
+	if (!(flags & CS_DC_SUSP))
+		conn_pr_state_change(mdev->tconn, os, ns, (flags & ~CS_DC_MASK) | CS_DC_SUSP);
+
+	/* if we are going -> D_FAILED or D_DISKLESS, grab one extra reference
+	 * on the ldev here, to be sure the transition -> D_DISKLESS resp.
+	 * drbd_ldev_destroy() won't happen before our corresponding
+	 * after_state_ch works run, where we put_ldev again. */
+	if ((os.disk != D_FAILED && ns.disk == D_FAILED) ||
+	    (os.disk != D_DISKLESS && ns.disk == D_DISKLESS))
+		atomic_inc(&mdev->local_cnt);
+
+	mdev->state.i = ns.i;
+	mdev->tconn->susp = ns.susp;
+	mdev->tconn->susp_nod = ns.susp_nod;
+	mdev->tconn->susp_fen = ns.susp_fen;
+
+	if (os.disk == D_ATTACHING && ns.disk >= D_NEGOTIATING)
+		drbd_print_uuids(mdev, "attached to UUIDs");
+
+	/* Wake up role changes, that were delayed because of connection establishing */
+	if (os.conn == C_WF_REPORT_PARAMS && ns.conn != C_WF_REPORT_PARAMS &&
+	    no_peer_wf_report_params(mdev->tconn))
+		clear_bit(STATE_SENT, &mdev->tconn->flags);
+
+	wake_up(&mdev->misc_wait);
+	wake_up(&mdev->state_wait);
+	wake_up(&mdev->tconn->ping_wait);
+
+	/* Aborted verify run, or we reached the stop sector.
+	 * Log the last position, unless end-of-device. */
+	if ((os.conn == C_VERIFY_S || os.conn == C_VERIFY_T) &&
+	    ns.conn <= C_CONNECTED) {
+		mdev->ov_start_sector =
+			BM_BIT_TO_SECT(drbd_bm_bits(mdev) - mdev->ov_left);
+		if (mdev->ov_left)
+			dev_info(DEV, "Online Verify reached sector %llu\n",
+				(unsigned long long)mdev->ov_start_sector);
+	}
+
+	if ((os.conn == C_PAUSED_SYNC_T || os.conn == C_PAUSED_SYNC_S) &&
+	    (ns.conn == C_SYNC_TARGET  || ns.conn == C_SYNC_SOURCE)) {
+		dev_info(DEV, "Syncer continues.\n");
+		mdev->rs_paused += (long)jiffies
+				  -(long)mdev->rs_mark_time[mdev->rs_last_mark];
+		if (ns.conn == C_SYNC_TARGET)
+			mod_timer(&mdev->resync_timer, jiffies);
+	}
+
+	if ((os.conn == C_SYNC_TARGET  || os.conn == C_SYNC_SOURCE) &&
+	    (ns.conn == C_PAUSED_SYNC_T || ns.conn == C_PAUSED_SYNC_S)) {
+		dev_info(DEV, "Resync suspended\n");
+		mdev->rs_mark_time[mdev->rs_last_mark] = jiffies;
+	}
+
+	if (os.conn == C_CONNECTED &&
+	    (ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T)) {
+		unsigned long now = jiffies;
+		int i;
+
+		set_ov_position(mdev, ns.conn);
+		mdev->rs_start = now;
+		mdev->rs_last_events = 0;
+		mdev->rs_last_sect_ev = 0;
+		mdev->ov_last_oos_size = 0;
+		mdev->ov_last_oos_start = 0;
+
+		for (i = 0; i < DRBD_SYNC_MARKS; i++) {
+			mdev->rs_mark_left[i] = mdev->ov_left;
+			mdev->rs_mark_time[i] = now;
+		}
+
+		drbd_rs_controller_reset(mdev);
+
+		if (ns.conn == C_VERIFY_S) {
+			dev_info(DEV, "Starting Online Verify from sector %llu\n",
+					(unsigned long long)mdev->ov_position);
+			mod_timer(&mdev->resync_timer, jiffies);
+		}
+	}
+
+	if (get_ldev(mdev)) {
+		u32 mdf = mdev->ldev->md.flags & ~(MDF_CONSISTENT|MDF_PRIMARY_IND|
+						 MDF_CONNECTED_IND|MDF_WAS_UP_TO_DATE|
+						 MDF_PEER_OUT_DATED|MDF_CRASHED_PRIMARY);
+
+		mdf &= ~MDF_AL_CLEAN;
+		if (test_bit(CRASHED_PRIMARY, &mdev->flags))
+			mdf |= MDF_CRASHED_PRIMARY;
+		if (mdev->state.role == R_PRIMARY ||
+		    (mdev->state.pdsk < D_INCONSISTENT && mdev->state.peer == R_PRIMARY))
+			mdf |= MDF_PRIMARY_IND;
+		if (mdev->state.conn > C_WF_REPORT_PARAMS)
+			mdf |= MDF_CONNECTED_IND;
+		if (mdev->state.disk > D_INCONSISTENT)
+			mdf |= MDF_CONSISTENT;
+		if (mdev->state.disk > D_OUTDATED)
+			mdf |= MDF_WAS_UP_TO_DATE;
+		if (mdev->state.pdsk <= D_OUTDATED && mdev->state.pdsk >= D_INCONSISTENT)
+			mdf |= MDF_PEER_OUT_DATED;
+		if (mdf != mdev->ldev->md.flags) {
+			mdev->ldev->md.flags = mdf;
+			drbd_md_mark_dirty(mdev);
+		}
+		if (os.disk < D_CONSISTENT && ns.disk >= D_CONSISTENT)
+			drbd_set_ed_uuid(mdev, mdev->ldev->md.uuid[UI_CURRENT]);
+		put_ldev(mdev);
+	}
+
+	/* Peer was forced D_UP_TO_DATE & R_PRIMARY, consider to resync */
+	if (os.disk == D_INCONSISTENT && os.pdsk == D_INCONSISTENT &&
+	    os.peer == R_SECONDARY && ns.peer == R_PRIMARY)
+		set_bit(CONSIDER_RESYNC, &mdev->flags);
+
+	/* Receiver should clean up itself */
+	if (os.conn != C_DISCONNECTING && ns.conn == C_DISCONNECTING)
+		drbd_thread_stop_nowait(&mdev->tconn->receiver);
+
+	/* Now the receiver finished cleaning up itself, it should die */
+	if (os.conn != C_STANDALONE && ns.conn == C_STANDALONE)
+		drbd_thread_stop_nowait(&mdev->tconn->receiver);
+
+	/* Upon network failure, we need to restart the receiver. */
+	if (os.conn > C_WF_CONNECTION &&
+	    ns.conn <= C_TEAR_DOWN && ns.conn >= C_TIMEOUT)
+		drbd_thread_restart_nowait(&mdev->tconn->receiver);
+
+	/* Resume AL writing if we get a connection */
+	if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED)
+		drbd_resume_al(mdev);
+
+	/* remember last attach time so request_timer_fn() won't
+	 * kill newly established sessions while we are still trying to thaw
+	 * previously frozen IO */
+	if ((os.disk == D_ATTACHING || os.disk == D_NEGOTIATING) &&
+	    ns.disk > D_NEGOTIATING)
+		mdev->last_reattach_jif = jiffies;
+
+	ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC);
+	if (ascw) {
+		ascw->os = os;
+		ascw->ns = ns;
+		ascw->flags = flags;
+		ascw->w.cb = w_after_state_ch;
+		ascw->w.mdev = mdev;
+		ascw->done = done;
+		drbd_queue_work(&mdev->tconn->sender_work, &ascw->w);
+	} else {
+		dev_err(DEV, "Could not kmalloc an ascw\n");
+	}
+
+	return rv;
+}
+
+static int w_after_state_ch(struct drbd_work *w, int unused)
+{
+	struct after_state_chg_work *ascw =
+		container_of(w, struct after_state_chg_work, w);
+	struct drbd_conf *mdev = w->mdev;
+
+	after_state_ch(mdev, ascw->os, ascw->ns, ascw->flags);
+	if (ascw->flags & CS_WAIT_COMPLETE) {
+		D_ASSERT(ascw->done != NULL);
+		complete(ascw->done);
+	}
+	kfree(ascw);
+
+	return 0;
+}
+
+static void abw_start_sync(struct drbd_conf *mdev, int rv)
+{
+	if (rv) {
+		dev_err(DEV, "Writing the bitmap failed not starting resync.\n");
+		_drbd_request_state(mdev, NS(conn, C_CONNECTED), CS_VERBOSE);
+		return;
+	}
+
+	switch (mdev->state.conn) {
+	case C_STARTING_SYNC_T:
+		_drbd_request_state(mdev, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE);
+		break;
+	case C_STARTING_SYNC_S:
+		drbd_start_resync(mdev, C_SYNC_SOURCE);
+		break;
+	}
+}
+
+int drbd_bitmap_io_from_worker(struct drbd_conf *mdev,
+		int (*io_fn)(struct drbd_conf *),
+		char *why, enum bm_flag flags)
+{
+	int rv;
+
+	D_ASSERT(current == mdev->tconn->worker.task);
+
+	/* open coded non-blocking drbd_suspend_io(mdev); */
+	set_bit(SUSPEND_IO, &mdev->flags);
+
+	drbd_bm_lock(mdev, why, flags);
+	rv = io_fn(mdev);
+	drbd_bm_unlock(mdev);
+
+	drbd_resume_io(mdev);
+
+	return rv;
+}
+
+/**
+ * after_state_ch() - Perform after state change actions that may sleep
+ * @mdev:	DRBD device.
+ * @os:		old state.
+ * @ns:		new state.
+ * @flags:	Flags
+ */
+static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
+			   union drbd_state ns, enum chg_state_flags flags)
+{
+	struct sib_info sib;
+
+	sib.sib_reason = SIB_STATE_CHANGE;
+	sib.os = os;
+	sib.ns = ns;
+
+	if (os.conn != C_CONNECTED && ns.conn == C_CONNECTED) {
+		clear_bit(CRASHED_PRIMARY, &mdev->flags);
+		if (mdev->p_uuid)
+			mdev->p_uuid[UI_FLAGS] &= ~((u64)2);
+	}
+
+	/* Inform userspace about the change... */
+	drbd_bcast_event(mdev, &sib);
+
+	if (!(os.role == R_PRIMARY && os.disk < D_UP_TO_DATE && os.pdsk < D_UP_TO_DATE) &&
+	    (ns.role == R_PRIMARY && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE))
+		drbd_khelper(mdev, "pri-on-incon-degr");
+
+	/* Here we have the actions that are performed after a
+	   state change. This function might sleep */
+
+	if (ns.susp_nod) {
+		struct drbd_tconn *tconn = mdev->tconn;
+		enum drbd_req_event what = NOTHING;
+
+		spin_lock_irq(&tconn->req_lock);
+		if (os.conn < C_CONNECTED && conn_lowest_conn(tconn) >= C_CONNECTED)
+			what = RESEND;
+
+		if ((os.disk == D_ATTACHING || os.disk == D_NEGOTIATING) &&
+		    conn_lowest_disk(tconn) > D_NEGOTIATING)
+			what = RESTART_FROZEN_DISK_IO;
+
+		if (tconn->susp_nod && what != NOTHING) {
+			_tl_restart(tconn, what);
+			_conn_request_state(tconn,
+					    (union drbd_state) { { .susp_nod = 1 } },
+					    (union drbd_state) { { .susp_nod = 0 } },
+					    CS_VERBOSE);
+		}
+		spin_unlock_irq(&tconn->req_lock);
+	}
+
+	if (ns.susp_fen) {
+		struct drbd_tconn *tconn = mdev->tconn;
+
+		spin_lock_irq(&tconn->req_lock);
+		if (tconn->susp_fen && conn_lowest_conn(tconn) >= C_CONNECTED) {
+			/* case2: The connection was established again: */
+			struct drbd_conf *odev;
+			int vnr;
+
+			rcu_read_lock();
+			idr_for_each_entry(&tconn->volumes, odev, vnr)
+				clear_bit(NEW_CUR_UUID, &odev->flags);
+			rcu_read_unlock();
+			_tl_restart(tconn, RESEND);
+			_conn_request_state(tconn,
+					    (union drbd_state) { { .susp_fen = 1 } },
+					    (union drbd_state) { { .susp_fen = 0 } },
+					    CS_VERBOSE);
+		}
+		spin_unlock_irq(&tconn->req_lock);
+	}
+
+	/* Became sync source.  With protocol >= 96, we still need to send out
+	 * the sync uuid now. Need to do that before any drbd_send_state, or
+	 * the other side may go "paused sync" before receiving the sync uuids,
+	 * which is unexpected. */
+	if ((os.conn != C_SYNC_SOURCE && os.conn != C_PAUSED_SYNC_S) &&
+	    (ns.conn == C_SYNC_SOURCE || ns.conn == C_PAUSED_SYNC_S) &&
+	    mdev->tconn->agreed_pro_version >= 96 && get_ldev(mdev)) {
+		drbd_gen_and_send_sync_uuid(mdev);
+		put_ldev(mdev);
+	}
+
+	/* Do not change the order of the if above and the two below... */
+	if (os.pdsk == D_DISKLESS &&
+	    ns.pdsk > D_DISKLESS && ns.pdsk != D_UNKNOWN) {      /* attach on the peer */
+		/* we probably will start a resync soon.
+		 * make sure those things are properly reset. */
+		mdev->rs_total = 0;
+		mdev->rs_failed = 0;
+		atomic_set(&mdev->rs_pending_cnt, 0);
+		drbd_rs_cancel_all(mdev);
+
+		drbd_send_uuids(mdev);
+		drbd_send_state(mdev, ns);
+	}
+	/* No point in queuing send_bitmap if we don't have a connection
+	 * anymore, so check also the _current_ state, not only the new state
+	 * at the time this work was queued. */
+	if (os.conn != C_WF_BITMAP_S && ns.conn == C_WF_BITMAP_S &&
+	    mdev->state.conn == C_WF_BITMAP_S)
+		drbd_queue_bitmap_io(mdev, &drbd_send_bitmap, NULL,
+				"send_bitmap (WFBitMapS)",
+				BM_LOCKED_TEST_ALLOWED);
+
+	/* Lost contact to peer's copy of the data */
+	if ((os.pdsk >= D_INCONSISTENT &&
+	     os.pdsk != D_UNKNOWN &&
+	     os.pdsk != D_OUTDATED)
+	&&  (ns.pdsk < D_INCONSISTENT ||
+	     ns.pdsk == D_UNKNOWN ||
+	     ns.pdsk == D_OUTDATED)) {
+		if (get_ldev(mdev)) {
+			if ((ns.role == R_PRIMARY || ns.peer == R_PRIMARY) &&
+			    mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
+				if (drbd_suspended(mdev)) {
+					set_bit(NEW_CUR_UUID, &mdev->flags);
+				} else {
+					drbd_uuid_new_current(mdev);
+					drbd_send_uuids(mdev);
+				}
+			}
+			put_ldev(mdev);
+		}
+	}
+
+	if (ns.pdsk < D_INCONSISTENT && get_ldev(mdev)) {
+		if (os.peer == R_SECONDARY && ns.peer == R_PRIMARY &&
+		    mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
+			drbd_uuid_new_current(mdev);
+			drbd_send_uuids(mdev);
+		}
+		/* D_DISKLESS Peer becomes secondary */
+		if (os.peer == R_PRIMARY && ns.peer == R_SECONDARY)
+			/* We may still be Primary ourselves.
+			 * No harm done if the bitmap still changes,
+			 * redirtied pages will follow later. */
+			drbd_bitmap_io_from_worker(mdev, &drbd_bm_write,
+				"demote diskless peer", BM_LOCKED_SET_ALLOWED);
+		put_ldev(mdev);
+	}
+
+	/* Write out all changed bits on demote.
+	 * Though, no need to da that just yet
+	 * if there is a resync going on still */
+	if (os.role == R_PRIMARY && ns.role == R_SECONDARY &&
+		mdev->state.conn <= C_CONNECTED && get_ldev(mdev)) {
+		/* No changes to the bitmap expected this time, so assert that,
+		 * even though no harm was done if it did change. */
+		drbd_bitmap_io_from_worker(mdev, &drbd_bm_write,
+				"demote", BM_LOCKED_TEST_ALLOWED);
+		put_ldev(mdev);
+	}
+
+	/* Last part of the attaching process ... */
+	if (ns.conn >= C_CONNECTED &&
+	    os.disk == D_ATTACHING && ns.disk == D_NEGOTIATING) {
+		drbd_send_sizes(mdev, 0, 0);  /* to start sync... */
+		drbd_send_uuids(mdev);
+		drbd_send_state(mdev, ns);
+	}
+
+	/* We want to pause/continue resync, tell peer. */
+	if (ns.conn >= C_CONNECTED &&
+	     ((os.aftr_isp != ns.aftr_isp) ||
+	      (os.user_isp != ns.user_isp)))
+		drbd_send_state(mdev, ns);
+
+	/* In case one of the isp bits got set, suspend other devices. */
+	if ((!os.aftr_isp && !os.peer_isp && !os.user_isp) &&
+	    (ns.aftr_isp || ns.peer_isp || ns.user_isp))
+		suspend_other_sg(mdev);
+
+	/* Make sure the peer gets informed about eventual state
+	   changes (ISP bits) while we were in WFReportParams. */
+	if (os.conn == C_WF_REPORT_PARAMS && ns.conn >= C_CONNECTED)
+		drbd_send_state(mdev, ns);
+
+	if (os.conn != C_AHEAD && ns.conn == C_AHEAD)
+		drbd_send_state(mdev, ns);
+
+	/* We are in the progress to start a full sync... */
+	if ((os.conn != C_STARTING_SYNC_T && ns.conn == C_STARTING_SYNC_T) ||
+	    (os.conn != C_STARTING_SYNC_S && ns.conn == C_STARTING_SYNC_S))
+		/* no other bitmap changes expected during this phase */
+		drbd_queue_bitmap_io(mdev,
+			&drbd_bmio_set_n_write, &abw_start_sync,
+			"set_n_write from StartingSync", BM_LOCKED_TEST_ALLOWED);
+
+	/* We are invalidating our self... */
+	if (os.conn < C_CONNECTED && ns.conn < C_CONNECTED &&
+	    os.disk > D_INCONSISTENT && ns.disk == D_INCONSISTENT)
+		/* other bitmap operation expected during this phase */
+		drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, NULL,
+			"set_n_write from invalidate", BM_LOCKED_MASK);
+
+	/* first half of local IO error, failure to attach,
+	 * or administrative detach */
+	if (os.disk != D_FAILED && ns.disk == D_FAILED) {
+		enum drbd_io_error_p eh = EP_PASS_ON;
+		int was_io_error = 0;
+		/* corresponding get_ldev was in __drbd_set_state, to serialize
+		 * our cleanup here with the transition to D_DISKLESS.
+		 * But is is still not save to dreference ldev here, since
+		 * we might come from an failed Attach before ldev was set. */
+		if (mdev->ldev) {
+			rcu_read_lock();
+			eh = rcu_dereference(mdev->ldev->disk_conf)->on_io_error;
+			rcu_read_unlock();
+
+			was_io_error = test_and_clear_bit(WAS_IO_ERROR, &mdev->flags);
+
+			if (was_io_error && eh == EP_CALL_HELPER)
+				drbd_khelper(mdev, "local-io-error");
+
+			/* Immediately allow completion of all application IO,
+			 * that waits for completion from the local disk,
+			 * if this was a force-detach due to disk_timeout
+			 * or administrator request (drbdsetup detach --force).
+			 * Do NOT abort otherwise.
+			 * Aborting local requests may cause serious problems,
+			 * if requests are completed to upper layers already,
+			 * and then later the already submitted local bio completes.
+			 * This can cause DMA into former bio pages that meanwhile
+			 * have been re-used for other things.
+			 * So aborting local requests may cause crashes,
+			 * or even worse, silent data corruption.
+			 */
+			if (test_and_clear_bit(FORCE_DETACH, &mdev->flags))
+				tl_abort_disk_io(mdev);
+
+			/* current state still has to be D_FAILED,
+			 * there is only one way out: to D_DISKLESS,
+			 * and that may only happen after our put_ldev below. */
+			if (mdev->state.disk != D_FAILED)
+				dev_err(DEV,
+					"ASSERT FAILED: disk is %s during detach\n",
+					drbd_disk_str(mdev->state.disk));
+
+			if (ns.conn >= C_CONNECTED)
+				drbd_send_state(mdev, ns);
+
+			drbd_rs_cancel_all(mdev);
+
+			/* In case we want to get something to stable storage still,
+			 * this may be the last chance.
+			 * Following put_ldev may transition to D_DISKLESS. */
+			drbd_md_sync(mdev);
+		}
+		put_ldev(mdev);
+	}
+
+        /* second half of local IO error, failure to attach,
+         * or administrative detach,
+         * after local_cnt references have reached zero again */
+        if (os.disk != D_DISKLESS && ns.disk == D_DISKLESS) {
+                /* We must still be diskless,
+                 * re-attach has to be serialized with this! */
+                if (mdev->state.disk != D_DISKLESS)
+                        dev_err(DEV,
+                                "ASSERT FAILED: disk is %s while going diskless\n",
+                                drbd_disk_str(mdev->state.disk));
+
+		if (ns.conn >= C_CONNECTED)
+			drbd_send_state(mdev, ns);
+		/* corresponding get_ldev in __drbd_set_state
+		 * this may finally trigger drbd_ldev_destroy. */
+		put_ldev(mdev);
+	}
+
+	/* Notify peer that I had a local IO error, and did not detached.. */
+	if (os.disk == D_UP_TO_DATE && ns.disk == D_INCONSISTENT && ns.conn >= C_CONNECTED)
+		drbd_send_state(mdev, ns);
+
+	/* Disks got bigger while they were detached */
+	if (ns.disk > D_NEGOTIATING && ns.pdsk > D_NEGOTIATING &&
+	    test_and_clear_bit(RESYNC_AFTER_NEG, &mdev->flags)) {
+		if (ns.conn == C_CONNECTED)
+			resync_after_online_grow(mdev);
+	}
+
+	/* A resync finished or aborted, wake paused devices... */
+	if ((os.conn > C_CONNECTED && ns.conn <= C_CONNECTED) ||
+	    (os.peer_isp && !ns.peer_isp) ||
+	    (os.user_isp && !ns.user_isp))
+		resume_next_sg(mdev);
+
+	/* sync target done with resync.  Explicitly notify peer, even though
+	 * it should (at least for non-empty resyncs) already know itself. */
+	if (os.disk < D_UP_TO_DATE && os.conn >= C_SYNC_SOURCE && ns.conn == C_CONNECTED)
+		drbd_send_state(mdev, ns);
+
+	/* Verify finished, or reached stop sector.  Peer did not know about
+	 * the stop sector, and we may even have changed the stop sector during
+	 * verify to interrupt/stop early.  Send the new state. */
+	if (os.conn == C_VERIFY_S && ns.conn == C_CONNECTED
+	&& verify_can_do_stop_sector(mdev))
+		drbd_send_state(mdev, ns);
+
+	/* This triggers bitmap writeout of potentially still unwritten pages
+	 * if the resync finished cleanly, or aborted because of peer disk
+	 * failure, or because of connection loss.
+	 * For resync aborted because of local disk failure, we cannot do
+	 * any bitmap writeout anymore.
+	 * No harm done if some bits change during this phase.
+	 */
+	if (os.conn > C_CONNECTED && ns.conn <= C_CONNECTED && get_ldev(mdev)) {
+		drbd_queue_bitmap_io(mdev, &drbd_bm_write_copy_pages, NULL,
+			"write from resync_finished", BM_LOCKED_CHANGE_ALLOWED);
+		put_ldev(mdev);
+	}
+
+	if (ns.disk == D_DISKLESS &&
+	    ns.conn == C_STANDALONE &&
+	    ns.role == R_SECONDARY) {
+		if (os.aftr_isp != ns.aftr_isp)
+			resume_next_sg(mdev);
+	}
+
+	drbd_md_sync(mdev);
+}
+
+struct after_conn_state_chg_work {
+	struct drbd_work w;
+	enum drbd_conns oc;
+	union drbd_state ns_min;
+	union drbd_state ns_max; /* new, max state, over all mdevs */
+	enum chg_state_flags flags;
+};
+
+static int w_after_conn_state_ch(struct drbd_work *w, int unused)
+{
+	struct after_conn_state_chg_work *acscw =
+		container_of(w, struct after_conn_state_chg_work, w);
+	struct drbd_tconn *tconn = w->tconn;
+	enum drbd_conns oc = acscw->oc;
+	union drbd_state ns_max = acscw->ns_max;
+	struct drbd_conf *mdev;
+	int vnr;
+
+	kfree(acscw);
+
+	/* Upon network configuration, we need to start the receiver */
+	if (oc == C_STANDALONE && ns_max.conn == C_UNCONNECTED)
+		drbd_thread_start(&tconn->receiver);
+
+	if (oc == C_DISCONNECTING && ns_max.conn == C_STANDALONE) {
+		struct net_conf *old_conf;
+
+		mutex_lock(&tconn->conf_update);
+		old_conf = tconn->net_conf;
+		tconn->my_addr_len = 0;
+		tconn->peer_addr_len = 0;
+		rcu_assign_pointer(tconn->net_conf, NULL);
+		conn_free_crypto(tconn);
+		mutex_unlock(&tconn->conf_update);
+
+		synchronize_rcu();
+		kfree(old_conf);
+	}
+
+	if (ns_max.susp_fen) {
+		/* case1: The outdate peer handler is successful: */
+		if (ns_max.pdsk <= D_OUTDATED) {
+			rcu_read_lock();
+			idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+				if (test_bit(NEW_CUR_UUID, &mdev->flags)) {
+					drbd_uuid_new_current(mdev);
+					clear_bit(NEW_CUR_UUID, &mdev->flags);
+				}
+			}
+			rcu_read_unlock();
+			spin_lock_irq(&tconn->req_lock);
+			_tl_restart(tconn, CONNECTION_LOST_WHILE_PENDING);
+			_conn_request_state(tconn,
+					    (union drbd_state) { { .susp_fen = 1 } },
+					    (union drbd_state) { { .susp_fen = 0 } },
+					    CS_VERBOSE);
+			spin_unlock_irq(&tconn->req_lock);
+		}
+	}
+	kref_put(&tconn->kref, &conn_destroy);
+
+	conn_md_sync(tconn);
+
+	return 0;
+}
+
+void conn_old_common_state(struct drbd_tconn *tconn, union drbd_state *pcs, enum chg_state_flags *pf)
+{
+	enum chg_state_flags flags = ~0;
+	struct drbd_conf *mdev;
+	int vnr, first_vol = 1;
+	union drbd_dev_state os, cs = {
+		{ .role = R_SECONDARY,
+		  .peer = R_UNKNOWN,
+		  .conn = tconn->cstate,
+		  .disk = D_DISKLESS,
+		  .pdsk = D_UNKNOWN,
+		} };
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+		os = mdev->state;
+
+		if (first_vol) {
+			cs = os;
+			first_vol = 0;
+			continue;
+		}
+
+		if (cs.role != os.role)
+			flags &= ~CS_DC_ROLE;
+
+		if (cs.peer != os.peer)
+			flags &= ~CS_DC_PEER;
+
+		if (cs.conn != os.conn)
+			flags &= ~CS_DC_CONN;
+
+		if (cs.disk != os.disk)
+			flags &= ~CS_DC_DISK;
+
+		if (cs.pdsk != os.pdsk)
+			flags &= ~CS_DC_PDSK;
+	}
+	rcu_read_unlock();
+
+	*pf |= CS_DC_MASK;
+	*pf &= flags;
+	(*pcs).i = cs.i;
+}
+
+static enum drbd_state_rv
+conn_is_valid_transition(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
+			 enum chg_state_flags flags)
+{
+	enum drbd_state_rv rv = SS_SUCCESS;
+	union drbd_state ns, os;
+	struct drbd_conf *mdev;
+	int vnr;
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+		os = drbd_read_state(mdev);
+		ns = sanitize_state(mdev, apply_mask_val(os, mask, val), NULL);
+
+		if (flags & CS_IGN_OUTD_FAIL && ns.disk == D_OUTDATED && os.disk < D_OUTDATED)
+			ns.disk = os.disk;
+
+		if (ns.i == os.i)
+			continue;
+
+		rv = is_valid_transition(os, ns);
+		if (rv < SS_SUCCESS)
+			break;
+
+		if (!(flags & CS_HARD)) {
+			rv = is_valid_state(mdev, ns);
+			if (rv < SS_SUCCESS) {
+				if (is_valid_state(mdev, os) == rv)
+					rv = is_valid_soft_transition(os, ns, tconn);
+			} else
+				rv = is_valid_soft_transition(os, ns, tconn);
+		}
+		if (rv < SS_SUCCESS)
+			break;
+	}
+	rcu_read_unlock();
+
+	if (rv < SS_SUCCESS && flags & CS_VERBOSE)
+		print_st_err(mdev, os, ns, rv);
+
+	return rv;
+}
+
+void
+conn_set_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
+	       union drbd_state *pns_min, union drbd_state *pns_max, enum chg_state_flags flags)
+{
+	union drbd_state ns, os, ns_max = { };
+	union drbd_state ns_min = {
+		{ .role = R_MASK,
+		  .peer = R_MASK,
+		  .conn = val.conn,
+		  .disk = D_MASK,
+		  .pdsk = D_MASK
+		} };
+	struct drbd_conf *mdev;
+	enum drbd_state_rv rv;
+	int vnr, number_of_volumes = 0;
+
+	if (mask.conn == C_MASK) {
+		/* remember last connect time so request_timer_fn() won't
+		 * kill newly established sessions while we are still trying to thaw
+		 * previously frozen IO */
+		if (tconn->cstate != C_WF_REPORT_PARAMS && val.conn == C_WF_REPORT_PARAMS)
+			tconn->last_reconnect_jif = jiffies;
+
+		tconn->cstate = val.conn;
+	}
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+		number_of_volumes++;
+		os = drbd_read_state(mdev);
+		ns = apply_mask_val(os, mask, val);
+		ns = sanitize_state(mdev, ns, NULL);
+
+		if (flags & CS_IGN_OUTD_FAIL && ns.disk == D_OUTDATED && os.disk < D_OUTDATED)
+			ns.disk = os.disk;
+
+		rv = __drbd_set_state(mdev, ns, flags, NULL);
+		if (rv < SS_SUCCESS)
+			BUG();
+
+		ns.i = mdev->state.i;
+		ns_max.role = max_role(ns.role, ns_max.role);
+		ns_max.peer = max_role(ns.peer, ns_max.peer);
+		ns_max.conn = max_t(enum drbd_conns, ns.conn, ns_max.conn);
+		ns_max.disk = max_t(enum drbd_disk_state, ns.disk, ns_max.disk);
+		ns_max.pdsk = max_t(enum drbd_disk_state, ns.pdsk, ns_max.pdsk);
+
+		ns_min.role = min_role(ns.role, ns_min.role);
+		ns_min.peer = min_role(ns.peer, ns_min.peer);
+		ns_min.conn = min_t(enum drbd_conns, ns.conn, ns_min.conn);
+		ns_min.disk = min_t(enum drbd_disk_state, ns.disk, ns_min.disk);
+		ns_min.pdsk = min_t(enum drbd_disk_state, ns.pdsk, ns_min.pdsk);
+	}
+	rcu_read_unlock();
+
+	if (number_of_volumes == 0) {
+		ns_min = ns_max = (union drbd_state) { {
+				.role = R_SECONDARY,
+				.peer = R_UNKNOWN,
+				.conn = val.conn,
+				.disk = D_DISKLESS,
+				.pdsk = D_UNKNOWN
+			} };
+	}
+
+	ns_min.susp = ns_max.susp = tconn->susp;
+	ns_min.susp_nod = ns_max.susp_nod = tconn->susp_nod;
+	ns_min.susp_fen = ns_max.susp_fen = tconn->susp_fen;
+
+	*pns_min = ns_min;
+	*pns_max = ns_max;
+}
+
+static enum drbd_state_rv
+_conn_rq_cond(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val)
+{
+	enum drbd_state_rv rv;
+
+	if (test_and_clear_bit(CONN_WD_ST_CHG_OKAY, &tconn->flags))
+		return SS_CW_SUCCESS;
+
+	if (test_and_clear_bit(CONN_WD_ST_CHG_FAIL, &tconn->flags))
+		return SS_CW_FAILED_BY_PEER;
+
+	rv = tconn->cstate != C_WF_REPORT_PARAMS ? SS_CW_NO_NEED : SS_UNKNOWN_ERROR;
+
+	if (rv == SS_UNKNOWN_ERROR)
+		rv = conn_is_valid_transition(tconn, mask, val, 0);
+
+	if (rv == SS_SUCCESS)
+		rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */
+
+	return rv;
+}
+
+enum drbd_state_rv
+_conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
+		    enum chg_state_flags flags)
+{
+	enum drbd_state_rv rv = SS_SUCCESS;
+	struct after_conn_state_chg_work *acscw;
+	enum drbd_conns oc = tconn->cstate;
+	union drbd_state ns_max, ns_min, os;
+	bool have_mutex = false;
+
+	if (mask.conn) {
+		rv = is_valid_conn_transition(oc, val.conn);
+		if (rv < SS_SUCCESS)
+			goto abort;
+	}
+
+	rv = conn_is_valid_transition(tconn, mask, val, flags);
+	if (rv < SS_SUCCESS)
+		goto abort;
+
+	if (oc == C_WF_REPORT_PARAMS && val.conn == C_DISCONNECTING &&
+	    !(flags & (CS_LOCAL_ONLY | CS_HARD))) {
+
+		/* This will be a cluster-wide state change.
+		 * Need to give up the spinlock, grab the mutex,
+		 * then send the state change request, ... */
+		spin_unlock_irq(&tconn->req_lock);
+		mutex_lock(&tconn->cstate_mutex);
+		have_mutex = true;
+
+		set_bit(CONN_WD_ST_CHG_REQ, &tconn->flags);
+		if (conn_send_state_req(tconn, mask, val)) {
+			/* sending failed. */
+			clear_bit(CONN_WD_ST_CHG_REQ, &tconn->flags);
+			rv = SS_CW_FAILED_BY_PEER;
+			/* need to re-aquire the spin lock, though */
+			goto abort_unlocked;
+		}
+
+		if (val.conn == C_DISCONNECTING)
+			set_bit(DISCONNECT_SENT, &tconn->flags);
+
+		/* ... and re-aquire the spinlock.
+		 * If _conn_rq_cond() returned >= SS_SUCCESS, we must call
+		 * conn_set_state() within the same spinlock. */
+		spin_lock_irq(&tconn->req_lock);
+		wait_event_lock_irq(tconn->ping_wait,
+				(rv = _conn_rq_cond(tconn, mask, val)),
+				tconn->req_lock,
+				);
+		clear_bit(CONN_WD_ST_CHG_REQ, &tconn->flags);
+		if (rv < SS_SUCCESS)
+			goto abort;
+	}
+
+	conn_old_common_state(tconn, &os, &flags);
+	flags |= CS_DC_SUSP;
+	conn_set_state(tconn, mask, val, &ns_min, &ns_max, flags);
+	conn_pr_state_change(tconn, os, ns_max, flags);
+
+	acscw = kmalloc(sizeof(*acscw), GFP_ATOMIC);
+	if (acscw) {
+		acscw->oc = os.conn;
+		acscw->ns_min = ns_min;
+		acscw->ns_max = ns_max;
+		acscw->flags = flags;
+		acscw->w.cb = w_after_conn_state_ch;
+		kref_get(&tconn->kref);
+		acscw->w.tconn = tconn;
+		drbd_queue_work(&tconn->sender_work, &acscw->w);
+	} else {
+		conn_err(tconn, "Could not kmalloc an acscw\n");
+	}
+
+ abort:
+	if (have_mutex) {
+		/* mutex_unlock() "... must not be used in interrupt context.",
+		 * so give up the spinlock, then re-aquire it */
+		spin_unlock_irq(&tconn->req_lock);
+ abort_unlocked:
+		mutex_unlock(&tconn->cstate_mutex);
+		spin_lock_irq(&tconn->req_lock);
+	}
+	if (rv < SS_SUCCESS && flags & CS_VERBOSE) {
+		conn_err(tconn, "State change failed: %s\n", drbd_set_st_err_str(rv));
+		conn_err(tconn, " mask = 0x%x val = 0x%x\n", mask.i, val.i);
+		conn_err(tconn, " old_conn:%s wanted_conn:%s\n", drbd_conn_str(oc), drbd_conn_str(val.conn));
+	}
+	return rv;
+}
+
+enum drbd_state_rv
+conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
+		   enum chg_state_flags flags)
+{
+	enum drbd_state_rv rv;
+
+	spin_lock_irq(&tconn->req_lock);
+	rv = _conn_request_state(tconn, mask, val, flags);
+	spin_unlock_irq(&tconn->req_lock);
+
+	return rv;
+}
diff --git a/drivers/block/drbd/drbd_state.h b/drivers/block/drbd/drbd_state.h
new file mode 100644
index 0000000..a3c361b
--- /dev/null
+++ b/drivers/block/drbd/drbd_state.h
@@ -0,0 +1,161 @@
+#ifndef DRBD_STATE_H
+#define DRBD_STATE_H
+
+struct drbd_conf;
+struct drbd_tconn;
+
+/**
+ * DOC: DRBD State macros
+ *
+ * These macros are used to express state changes in easily readable form.
+ *
+ * The NS macros expand to a mask and a value, that can be bit ored onto the
+ * current state as soon as the spinlock (req_lock) was taken.
+ *
+ * The _NS macros are used for state functions that get called with the
+ * spinlock. These macros expand directly to the new state value.
+ *
+ * Besides the basic forms NS() and _NS() additional _?NS[23] are defined
+ * to express state changes that affect more than one aspect of the state.
+ *
+ * E.g. NS2(conn, C_CONNECTED, peer, R_SECONDARY)
+ * Means that the network connection was established and that the peer
+ * is in secondary role.
+ */
+#define role_MASK R_MASK
+#define peer_MASK R_MASK
+#define disk_MASK D_MASK
+#define pdsk_MASK D_MASK
+#define conn_MASK C_MASK
+#define susp_MASK 1
+#define user_isp_MASK 1
+#define aftr_isp_MASK 1
+#define susp_nod_MASK 1
+#define susp_fen_MASK 1
+
+#define NS(T, S) \
+	({ union drbd_state mask; mask.i = 0; mask.T = T##_MASK; mask; }), \
+	({ union drbd_state val; val.i = 0; val.T = (S); val; })
+#define NS2(T1, S1, T2, S2) \
+	({ union drbd_state mask; mask.i = 0; mask.T1 = T1##_MASK; \
+	  mask.T2 = T2##_MASK; mask; }), \
+	({ union drbd_state val; val.i = 0; val.T1 = (S1); \
+	  val.T2 = (S2); val; })
+#define NS3(T1, S1, T2, S2, T3, S3) \
+	({ union drbd_state mask; mask.i = 0; mask.T1 = T1##_MASK; \
+	  mask.T2 = T2##_MASK; mask.T3 = T3##_MASK; mask; }), \
+	({ union drbd_state val;  val.i = 0; val.T1 = (S1); \
+	  val.T2 = (S2); val.T3 = (S3); val; })
+
+#define _NS(D, T, S) \
+	D, ({ union drbd_state __ns; __ns = drbd_read_state(D); __ns.T = (S); __ns; })
+#define _NS2(D, T1, S1, T2, S2) \
+	D, ({ union drbd_state __ns; __ns = drbd_read_state(D); __ns.T1 = (S1); \
+	__ns.T2 = (S2); __ns; })
+#define _NS3(D, T1, S1, T2, S2, T3, S3) \
+	D, ({ union drbd_state __ns; __ns = drbd_read_state(D); __ns.T1 = (S1); \
+	__ns.T2 = (S2); __ns.T3 = (S3); __ns; })
+
+enum chg_state_flags {
+	CS_HARD	         = 1 << 0,
+	CS_VERBOSE       = 1 << 1,
+	CS_WAIT_COMPLETE = 1 << 2,
+	CS_SERIALIZE     = 1 << 3,
+	CS_ORDERED       = CS_WAIT_COMPLETE + CS_SERIALIZE,
+	CS_LOCAL_ONLY    = 1 << 4, /* Do not consider a device pair wide state change */
+	CS_DC_ROLE       = 1 << 5, /* DC = display as connection state change */
+	CS_DC_PEER       = 1 << 6,
+	CS_DC_CONN       = 1 << 7,
+	CS_DC_DISK       = 1 << 8,
+	CS_DC_PDSK       = 1 << 9,
+	CS_DC_SUSP       = 1 << 10,
+	CS_DC_MASK       = CS_DC_ROLE + CS_DC_PEER + CS_DC_CONN + CS_DC_DISK + CS_DC_PDSK,
+	CS_IGN_OUTD_FAIL = 1 << 11,
+};
+
+/* drbd_dev_state and drbd_state are different types. This is to stress the
+   small difference. There is no suspended flag (.susp), and no suspended
+   while fence handler runs flas (susp_fen). */
+union drbd_dev_state {
+	struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+		unsigned role:2 ;   /* 3/4	 primary/secondary/unknown */
+		unsigned peer:2 ;   /* 3/4	 primary/secondary/unknown */
+		unsigned conn:5 ;   /* 17/32	 cstates */
+		unsigned disk:4 ;   /* 8/16	 from D_DISKLESS to D_UP_TO_DATE */
+		unsigned pdsk:4 ;   /* 8/16	 from D_DISKLESS to D_UP_TO_DATE */
+		unsigned _unused:1 ;
+		unsigned aftr_isp:1 ; /* isp .. imposed sync pause */
+		unsigned peer_isp:1 ;
+		unsigned user_isp:1 ;
+		unsigned _pad:11;   /* 0	 unused */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+		unsigned _pad:11;
+		unsigned user_isp:1 ;
+		unsigned peer_isp:1 ;
+		unsigned aftr_isp:1 ; /* isp .. imposed sync pause */
+		unsigned _unused:1 ;
+		unsigned pdsk:4 ;   /* 8/16	 from D_DISKLESS to D_UP_TO_DATE */
+		unsigned disk:4 ;   /* 8/16	 from D_DISKLESS to D_UP_TO_DATE */
+		unsigned conn:5 ;   /* 17/32	 cstates */
+		unsigned peer:2 ;   /* 3/4	 primary/secondary/unknown */
+		unsigned role:2 ;   /* 3/4	 primary/secondary/unknown */
+#else
+# error "this endianess is not supported"
+#endif
+	};
+	unsigned int i;
+};
+
+extern enum drbd_state_rv drbd_change_state(struct drbd_conf *mdev,
+					    enum chg_state_flags f,
+					    union drbd_state mask,
+					    union drbd_state val);
+extern void drbd_force_state(struct drbd_conf *, union drbd_state,
+			union drbd_state);
+extern enum drbd_state_rv _drbd_request_state(struct drbd_conf *,
+					      union drbd_state,
+					      union drbd_state,
+					      enum chg_state_flags);
+extern enum drbd_state_rv __drbd_set_state(struct drbd_conf *, union drbd_state,
+					   enum chg_state_flags,
+					   struct completion *done);
+extern void print_st_err(struct drbd_conf *, union drbd_state,
+			union drbd_state, int);
+
+enum drbd_state_rv
+_conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
+		    enum chg_state_flags flags);
+
+enum drbd_state_rv
+conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val,
+		   enum chg_state_flags flags);
+
+extern void drbd_resume_al(struct drbd_conf *mdev);
+extern bool conn_all_vols_unconf(struct drbd_tconn *tconn);
+
+/**
+ * drbd_request_state() - Reqest a state change
+ * @mdev:	DRBD device.
+ * @mask:	mask of state bits to change.
+ * @val:	value of new state bits.
+ *
+ * This is the most graceful way of requesting a state change. It is verbose
+ * quite verbose in case the state change is not possible, and all those
+ * state changes are globally serialized.
+ */
+static inline int drbd_request_state(struct drbd_conf *mdev,
+				     union drbd_state mask,
+				     union drbd_state val)
+{
+	return _drbd_request_state(mdev, mask, val, CS_VERBOSE + CS_ORDERED);
+}
+
+enum drbd_role conn_highest_role(struct drbd_tconn *tconn);
+enum drbd_role conn_highest_peer(struct drbd_tconn *tconn);
+enum drbd_disk_state conn_highest_disk(struct drbd_tconn *tconn);
+enum drbd_disk_state conn_lowest_disk(struct drbd_tconn *tconn);
+enum drbd_disk_state conn_highest_pdsk(struct drbd_tconn *tconn);
+enum drbd_conns conn_lowest_conn(struct drbd_tconn *tconn);
+
+#endif
diff --git a/drivers/block/drbd/drbd_strings.c b/drivers/block/drbd/drbd_strings.c
index c44a2a6..9a664bd 100644
--- a/drivers/block/drbd/drbd_strings.c
+++ b/drivers/block/drbd/drbd_strings.c
@@ -89,6 +89,7 @@ static const char *drbd_state_sw_errors[] = {
 	[-SS_LOWER_THAN_OUTDATED] = "Disk state is lower than outdated",
 	[-SS_IN_TRANSIENT_STATE] = "In transient state, retry after next state change",
 	[-SS_CONCURRENT_ST_CHG] = "Concurrent state changes detected and aborted",
+	[-SS_O_VOL_PEER_PRI] = "Other vol primary on peer not allowed by config",
 };
 
 const char *drbd_conn_str(enum drbd_conns s)
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 6bce2cc..424dc7b 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -38,16 +38,13 @@
 #include "drbd_int.h"
 #include "drbd_req.h"
 
-static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int cancel);
-static int w_make_resync_request(struct drbd_conf *mdev,
-				 struct drbd_work *w, int cancel);
-
+static int w_make_ov_request(struct drbd_work *w, int cancel);
 
 
 /* endio handlers:
  *   drbd_md_io_complete (defined here)
- *   drbd_endio_pri (defined here)
- *   drbd_endio_sec (defined here)
+ *   drbd_request_endio (defined here)
+ *   drbd_peer_request_endio (defined here)
  *   bm_async_io_complete (defined in drbd_bitmap.c)
  *
  * For all these callbacks, note the following:
@@ -60,7 +57,7 @@ static int w_make_resync_request(struct drbd_conf *mdev,
 
 /* About the global_state_lock
    Each state transition on an device holds a read lock. In case we have
-   to evaluate the sync after dependencies, we grab a write lock, because
+   to evaluate the resync after dependencies, we grab a write lock, because
    we need stable states on all devices for that.  */
 rwlock_t global_state_lock;
 
@@ -98,97 +95,93 @@ void drbd_md_io_complete(struct bio *bio, int error)
 /* reads on behalf of the partner,
  * "submitted" by the receiver
  */
-void drbd_endio_read_sec_final(struct drbd_epoch_entry *e) __releases(local)
+void drbd_endio_read_sec_final(struct drbd_peer_request *peer_req) __releases(local)
 {
 	unsigned long flags = 0;
-	struct drbd_conf *mdev = e->mdev;
-
-	D_ASSERT(e->block_id != ID_VACANT);
+	struct drbd_conf *mdev = peer_req->w.mdev;
 
-	spin_lock_irqsave(&mdev->req_lock, flags);
-	mdev->read_cnt += e->size >> 9;
-	list_del(&e->w.list);
+	spin_lock_irqsave(&mdev->tconn->req_lock, flags);
+	mdev->read_cnt += peer_req->i.size >> 9;
+	list_del(&peer_req->w.list);
 	if (list_empty(&mdev->read_ee))
 		wake_up(&mdev->ee_wait);
-	if (test_bit(__EE_WAS_ERROR, &e->flags))
-		__drbd_chk_io_error(mdev, DRBD_IO_ERROR);
-	spin_unlock_irqrestore(&mdev->req_lock, flags);
+	if (test_bit(__EE_WAS_ERROR, &peer_req->flags))
+		__drbd_chk_io_error(mdev, DRBD_READ_ERROR);
+	spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
 
-	drbd_queue_work(&mdev->data.work, &e->w);
+	drbd_queue_work(&mdev->tconn->sender_work, &peer_req->w);
 	put_ldev(mdev);
 }
 
 /* writes on behalf of the partner, or resync writes,
  * "submitted" by the receiver, final stage.  */
-static void drbd_endio_write_sec_final(struct drbd_epoch_entry *e) __releases(local)
+static void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req) __releases(local)
 {
 	unsigned long flags = 0;
-	struct drbd_conf *mdev = e->mdev;
-	sector_t e_sector;
+	struct drbd_conf *mdev = peer_req->w.mdev;
+	struct drbd_interval i;
 	int do_wake;
-	int is_syncer_req;
+	u64 block_id;
 	int do_al_complete_io;
 
-	D_ASSERT(e->block_id != ID_VACANT);
-
-	/* after we moved e to done_ee,
+	/* after we moved peer_req to done_ee,
 	 * we may no longer access it,
 	 * it may be freed/reused already!
 	 * (as soon as we release the req_lock) */
-	e_sector = e->sector;
-	do_al_complete_io = e->flags & EE_CALL_AL_COMPLETE_IO;
-	is_syncer_req = is_syncer_block_id(e->block_id);
+	i = peer_req->i;
+	do_al_complete_io = peer_req->flags & EE_CALL_AL_COMPLETE_IO;
+	block_id = peer_req->block_id;
 
-	spin_lock_irqsave(&mdev->req_lock, flags);
-	mdev->writ_cnt += e->size >> 9;
-	list_del(&e->w.list); /* has been on active_ee or sync_ee */
-	list_add_tail(&e->w.list, &mdev->done_ee);
+	spin_lock_irqsave(&mdev->tconn->req_lock, flags);
+	mdev->writ_cnt += peer_req->i.size >> 9;
+	list_move_tail(&peer_req->w.list, &mdev->done_ee);
 
-	/* No hlist_del_init(&e->collision) here, we did not send the Ack yet,
-	 * neither did we wake possibly waiting conflicting requests.
-	 * done from "drbd_process_done_ee" within the appropriate w.cb
-	 * (e_end_block/e_end_resync_block) or from _drbd_clear_done_ee */
+	/*
+	 * Do not remove from the write_requests tree here: we did not send the
+	 * Ack yet and did not wake possibly waiting conflicting requests.
+	 * Removed from the tree from "drbd_process_done_ee" within the
+	 * appropriate w.cb (e_end_block/e_end_resync_block) or from
+	 * _drbd_clear_done_ee.
+	 */
 
-	do_wake = is_syncer_req
-		? list_empty(&mdev->sync_ee)
-		: list_empty(&mdev->active_ee);
+	do_wake = list_empty(block_id == ID_SYNCER ? &mdev->sync_ee : &mdev->active_ee);
 
-	if (test_bit(__EE_WAS_ERROR, &e->flags))
-		__drbd_chk_io_error(mdev, DRBD_IO_ERROR);
-	spin_unlock_irqrestore(&mdev->req_lock, flags);
+	if (test_bit(__EE_WAS_ERROR, &peer_req->flags))
+		__drbd_chk_io_error(mdev, DRBD_WRITE_ERROR);
+	spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
 
-	if (is_syncer_req)
-		drbd_rs_complete_io(mdev, e_sector);
+	if (block_id == ID_SYNCER)
+		drbd_rs_complete_io(mdev, i.sector);
 
 	if (do_wake)
 		wake_up(&mdev->ee_wait);
 
 	if (do_al_complete_io)
-		drbd_al_complete_io(mdev, e_sector);
+		drbd_al_complete_io(mdev, &i);
 
-	wake_asender(mdev);
+	wake_asender(mdev->tconn);
 	put_ldev(mdev);
 }
 
 /* writes on behalf of the partner, or resync writes,
  * "submitted" by the receiver.
  */
-void drbd_endio_sec(struct bio *bio, int error)
+void drbd_peer_request_endio(struct bio *bio, int error)
 {
-	struct drbd_epoch_entry *e = bio->bi_private;
-	struct drbd_conf *mdev = e->mdev;
+	struct drbd_peer_request *peer_req = bio->bi_private;
+	struct drbd_conf *mdev = peer_req->w.mdev;
 	int uptodate = bio_flagged(bio, BIO_UPTODATE);
 	int is_write = bio_data_dir(bio) == WRITE;
 
 	if (error && __ratelimit(&drbd_ratelimit_state))
 		dev_warn(DEV, "%s: error=%d s=%llus\n",
 				is_write ? "write" : "read", error,
-				(unsigned long long)e->sector);
+				(unsigned long long)peer_req->i.sector);
 	if (!error && !uptodate) {
 		if (__ratelimit(&drbd_ratelimit_state))
 			dev_warn(DEV, "%s: setting error to -EIO s=%llus\n",
 					is_write ? "write" : "read",
-					(unsigned long long)e->sector);
+					(unsigned long long)peer_req->i.sector);
 		/* strange behavior of some lower level drivers...
 		 * fail the request by clearing the uptodate flag,
 		 * but do not return any error?! */
@@ -196,24 +189,24 @@ void drbd_endio_sec(struct bio *bio, int error)
 	}
 
 	if (error)
-		set_bit(__EE_WAS_ERROR, &e->flags);
+		set_bit(__EE_WAS_ERROR, &peer_req->flags);
 
 	bio_put(bio); /* no need for the bio anymore */
-	if (atomic_dec_and_test(&e->pending_bios)) {
+	if (atomic_dec_and_test(&peer_req->pending_bios)) {
 		if (is_write)
-			drbd_endio_write_sec_final(e);
+			drbd_endio_write_sec_final(peer_req);
 		else
-			drbd_endio_read_sec_final(e);
+			drbd_endio_read_sec_final(peer_req);
 	}
 }
 
 /* read, readA or write requests on R_PRIMARY coming from drbd_make_request
  */
-void drbd_endio_pri(struct bio *bio, int error)
+void drbd_request_endio(struct bio *bio, int error)
 {
 	unsigned long flags;
 	struct drbd_request *req = bio->bi_private;
-	struct drbd_conf *mdev = req->mdev;
+	struct drbd_conf *mdev = req->w.mdev;
 	struct bio_and_error m;
 	enum drbd_req_event what;
 	int uptodate = bio_flagged(bio, BIO_UPTODATE);
@@ -227,53 +220,72 @@ void drbd_endio_pri(struct bio *bio, int error)
 		error = -EIO;
 	}
 
+
+	/* If this request was aborted locally before,
+	 * but now was completed "successfully",
+	 * chances are that this caused arbitrary data corruption.
+	 *
+	 * "aborting" requests, or force-detaching the disk, is intended for
+	 * completely blocked/hung local backing devices which do no longer
+	 * complete requests at all, not even do error completions.  In this
+	 * situation, usually a hard-reset and failover is the only way out.
+	 *
+	 * By "aborting", basically faking a local error-completion,
+	 * we allow for a more graceful swichover by cleanly migrating services.
+	 * Still the affected node has to be rebooted "soon".
+	 *
+	 * By completing these requests, we allow the upper layers to re-use
+	 * the associated data pages.
+	 *
+	 * If later the local backing device "recovers", and now DMAs some data
+	 * from disk into the original request pages, in the best case it will
+	 * just put random data into unused pages; but typically it will corrupt
+	 * meanwhile completely unrelated data, causing all sorts of damage.
+	 *
+	 * Which means delayed successful completion,
+	 * especially for READ requests,
+	 * is a reason to panic().
+	 *
+	 * We assume that a delayed *error* completion is OK,
+	 * though we still will complain noisily about it.
+	 */
+	if (unlikely(req->rq_state & RQ_LOCAL_ABORTED)) {
+		if (__ratelimit(&drbd_ratelimit_state))
+			dev_emerg(DEV, "delayed completion of aborted local request; disk-timeout may be too aggressive\n");
+
+		if (!error)
+			panic("possible random memory corruption caused by delayed completion of aborted local request\n");
+	}
+
 	/* to avoid recursion in __req_mod */
 	if (unlikely(error)) {
 		what = (bio_data_dir(bio) == WRITE)
-			? write_completed_with_error
+			? WRITE_COMPLETED_WITH_ERROR
 			: (bio_rw(bio) == READ)
-			  ? read_completed_with_error
-			  : read_ahead_completed_with_error;
+			  ? READ_COMPLETED_WITH_ERROR
+			  : READ_AHEAD_COMPLETED_WITH_ERROR;
 	} else
-		what = completed_ok;
+		what = COMPLETED_OK;
 
 	bio_put(req->private_bio);
 	req->private_bio = ERR_PTR(error);
 
 	/* not req_mod(), we need irqsave here! */
-	spin_lock_irqsave(&mdev->req_lock, flags);
+	spin_lock_irqsave(&mdev->tconn->req_lock, flags);
 	__req_mod(req, what, &m);
-	spin_unlock_irqrestore(&mdev->req_lock, flags);
+	spin_unlock_irqrestore(&mdev->tconn->req_lock, flags);
 	put_ldev(mdev);
 
 	if (m.bio)
 		complete_master_bio(mdev, &m);
 }
 
-int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
-{
-	struct drbd_request *req = container_of(w, struct drbd_request, w);
-
-	/* We should not detach for read io-error,
-	 * but try to WRITE the P_DATA_REPLY to the failed location,
-	 * to give the disk the chance to relocate that block */
-
-	spin_lock_irq(&mdev->req_lock);
-	if (cancel || mdev->state.pdsk != D_UP_TO_DATE) {
-		_req_mod(req, read_retry_remote_canceled);
-		spin_unlock_irq(&mdev->req_lock);
-		return 1;
-	}
-	spin_unlock_irq(&mdev->req_lock);
-
-	return w_send_read_req(mdev, w, 0);
-}
-
-void drbd_csum_ee(struct drbd_conf *mdev, struct crypto_hash *tfm, struct drbd_epoch_entry *e, void *digest)
+void drbd_csum_ee(struct drbd_conf *mdev, struct crypto_hash *tfm,
+		  struct drbd_peer_request *peer_req, void *digest)
 {
 	struct hash_desc desc;
 	struct scatterlist sg;
-	struct page *page = e->pages;
+	struct page *page = peer_req->pages;
 	struct page *tmp;
 	unsigned len;
 
@@ -290,7 +302,7 @@ void drbd_csum_ee(struct drbd_conf *mdev, struct crypto_hash *tfm, struct drbd_e
 		page = tmp;
 	}
 	/* and now the last, possibly only partially used page */
-	len = e->size & (PAGE_SIZE - 1);
+	len = peer_req->i.size & (PAGE_SIZE - 1);
 	sg_set_page(&sg, page, len ?: PAGE_SIZE, 0);
 	crypto_hash_update(&desc, &sg, sg.length);
 	crypto_hash_final(&desc, digest);
@@ -316,59 +328,58 @@ void drbd_csum_bio(struct drbd_conf *mdev, struct crypto_hash *tfm, struct bio *
 	crypto_hash_final(&desc, digest);
 }
 
-/* TODO merge common code with w_e_end_ov_req */
-int w_e_send_csum(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+/* MAYBE merge common code with w_e_end_ov_req */
+static int w_e_send_csum(struct drbd_work *w, int cancel)
 {
-	struct drbd_epoch_entry *e = container_of(w, struct drbd_epoch_entry, w);
+	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
+	struct drbd_conf *mdev = w->mdev;
 	int digest_size;
 	void *digest;
-	int ok = 1;
-
-	D_ASSERT(e->block_id == DRBD_MAGIC + 0xbeef);
+	int err = 0;
 
 	if (unlikely(cancel))
 		goto out;
 
-	if (likely((e->flags & EE_WAS_ERROR) != 0))
+	if (unlikely((peer_req->flags & EE_WAS_ERROR) != 0))
 		goto out;
 
-	digest_size = crypto_hash_digestsize(mdev->csums_tfm);
+	digest_size = crypto_hash_digestsize(mdev->tconn->csums_tfm);
 	digest = kmalloc(digest_size, GFP_NOIO);
 	if (digest) {
-		sector_t sector = e->sector;
-		unsigned int size = e->size;
-		drbd_csum_ee(mdev, mdev->csums_tfm, e, digest);
-		/* Free e and pages before send.
+		sector_t sector = peer_req->i.sector;
+		unsigned int size = peer_req->i.size;
+		drbd_csum_ee(mdev, mdev->tconn->csums_tfm, peer_req, digest);
+		/* Free peer_req and pages before send.
 		 * In case we block on congestion, we could otherwise run into
 		 * some distributed deadlock, if the other side blocks on
 		 * congestion as well, because our receiver blocks in
-		 * drbd_pp_alloc due to pp_in_use > max_buffers. */
-		drbd_free_ee(mdev, e);
-		e = NULL;
+		 * drbd_alloc_pages due to pp_in_use > max_buffers. */
+		drbd_free_peer_req(mdev, peer_req);
+		peer_req = NULL;
 		inc_rs_pending(mdev);
-		ok = drbd_send_drequest_csum(mdev, sector, size,
-					     digest, digest_size,
-					     P_CSUM_RS_REQUEST);
+		err = drbd_send_drequest_csum(mdev, sector, size,
+					      digest, digest_size,
+					      P_CSUM_RS_REQUEST);
 		kfree(digest);
 	} else {
 		dev_err(DEV, "kmalloc() of digest failed.\n");
-		ok = 0;
+		err = -ENOMEM;
 	}
 
 out:
-	if (e)
-		drbd_free_ee(mdev, e);
+	if (peer_req)
+		drbd_free_peer_req(mdev, peer_req);
 
-	if (unlikely(!ok))
+	if (unlikely(err))
 		dev_err(DEV, "drbd_send_drequest(..., csum) failed\n");
-	return ok;
+	return err;
 }
 
 #define GFP_TRY	(__GFP_HIGHMEM | __GFP_NOWARN)
 
 static int read_for_csum(struct drbd_conf *mdev, sector_t sector, int size)
 {
-	struct drbd_epoch_entry *e;
+	struct drbd_peer_request *peer_req;
 
 	if (!get_ldev(mdev))
 		return -EIO;
@@ -378,45 +389,47 @@ static int read_for_csum(struct drbd_conf *mdev, sector_t sector, int size)
 
 	/* GFP_TRY, because if there is no memory available right now, this may
 	 * be rescheduled for later. It is "only" background resync, after all. */
-	e = drbd_alloc_ee(mdev, DRBD_MAGIC+0xbeef, sector, size, GFP_TRY);
-	if (!e)
+	peer_req = drbd_alloc_peer_req(mdev, ID_SYNCER /* unused */, sector,
+				       size, GFP_TRY);
+	if (!peer_req)
 		goto defer;
 
-	e->w.cb = w_e_send_csum;
-	spin_lock_irq(&mdev->req_lock);
-	list_add(&e->w.list, &mdev->read_ee);
-	spin_unlock_irq(&mdev->req_lock);
+	peer_req->w.cb = w_e_send_csum;
+	spin_lock_irq(&mdev->tconn->req_lock);
+	list_add(&peer_req->w.list, &mdev->read_ee);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
 	atomic_add(size >> 9, &mdev->rs_sect_ev);
-	if (drbd_submit_ee(mdev, e, READ, DRBD_FAULT_RS_RD) == 0)
+	if (drbd_submit_peer_request(mdev, peer_req, READ, DRBD_FAULT_RS_RD) == 0)
 		return 0;
 
 	/* If it failed because of ENOMEM, retry should help.  If it failed
 	 * because bio_add_page failed (probably broken lower level driver),
 	 * retry may or may not help.
 	 * If it does not, you may need to force disconnect. */
-	spin_lock_irq(&mdev->req_lock);
-	list_del(&e->w.list);
-	spin_unlock_irq(&mdev->req_lock);
+	spin_lock_irq(&mdev->tconn->req_lock);
+	list_del(&peer_req->w.list);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 
-	drbd_free_ee(mdev, e);
+	drbd_free_peer_req(mdev, peer_req);
 defer:
 	put_ldev(mdev);
 	return -EAGAIN;
 }
 
-int w_resync_timer(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+int w_resync_timer(struct drbd_work *w, int cancel)
 {
+	struct drbd_conf *mdev = w->mdev;
 	switch (mdev->state.conn) {
 	case C_VERIFY_S:
-		w_make_ov_request(mdev, w, cancel);
+		w_make_ov_request(w, cancel);
 		break;
 	case C_SYNC_TARGET:
-		w_make_resync_request(mdev, w, cancel);
+		w_make_resync_request(w, cancel);
 		break;
 	}
 
-	return 1;
+	return 0;
 }
 
 void resync_timer_fn(unsigned long data)
@@ -424,7 +437,7 @@ void resync_timer_fn(unsigned long data)
 	struct drbd_conf *mdev = (struct drbd_conf *) data;
 
 	if (list_empty(&mdev->resync_work.list))
-		drbd_queue_work(&mdev->data.work, &mdev->resync_work);
+		drbd_queue_work(&mdev->tconn->sender_work, &mdev->resync_work);
 }
 
 static void fifo_set(struct fifo_buffer *fb, int value)
@@ -456,8 +469,24 @@ static void fifo_add_val(struct fifo_buffer *fb, int value)
 		fb->values[i] += value;
 }
 
+struct fifo_buffer *fifo_alloc(int fifo_size)
+{
+	struct fifo_buffer *fb;
+
+	fb = kzalloc(sizeof(struct fifo_buffer) + sizeof(int) * fifo_size, GFP_NOIO);
+	if (!fb)
+		return NULL;
+
+	fb->head_index = 0;
+	fb->size = fifo_size;
+	fb->total = 0;
+
+	return fb;
+}
+
 static int drbd_rs_controller(struct drbd_conf *mdev)
 {
+	struct disk_conf *dc;
 	unsigned int sect_in;  /* Number of sectors that came in since the last turn */
 	unsigned int want;     /* The number of sectors we want in the proxy */
 	int req_sect; /* Number of sectors to request in this turn */
@@ -466,38 +495,39 @@ static int drbd_rs_controller(struct drbd_conf *mdev)
 	int steps; /* Number of time steps to plan ahead */
 	int curr_corr;
 	int max_sect;
+	struct fifo_buffer *plan;
 
 	sect_in = atomic_xchg(&mdev->rs_sect_in, 0); /* Number of sectors that came in */
 	mdev->rs_in_flight -= sect_in;
 
-	spin_lock(&mdev->peer_seq_lock); /* get an atomic view on mdev->rs_plan_s */
+	dc = rcu_dereference(mdev->ldev->disk_conf);
+	plan = rcu_dereference(mdev->rs_plan_s);
 
-	steps = mdev->rs_plan_s.size; /* (mdev->sync_conf.c_plan_ahead * 10 * SLEEP_TIME) / HZ; */
+	steps = plan->size; /* (dc->c_plan_ahead * 10 * SLEEP_TIME) / HZ; */
 
 	if (mdev->rs_in_flight + sect_in == 0) { /* At start of resync */
-		want = ((mdev->sync_conf.rate * 2 * SLEEP_TIME) / HZ) * steps;
+		want = ((dc->resync_rate * 2 * SLEEP_TIME) / HZ) * steps;
 	} else { /* normal path */
-		want = mdev->sync_conf.c_fill_target ? mdev->sync_conf.c_fill_target :
-			sect_in * mdev->sync_conf.c_delay_target * HZ / (SLEEP_TIME * 10);
+		want = dc->c_fill_target ? dc->c_fill_target :
+			sect_in * dc->c_delay_target * HZ / (SLEEP_TIME * 10);
 	}
 
-	correction = want - mdev->rs_in_flight - mdev->rs_planed;
+	correction = want - mdev->rs_in_flight - plan->total;
 
 	/* Plan ahead */
 	cps = correction / steps;
-	fifo_add_val(&mdev->rs_plan_s, cps);
-	mdev->rs_planed += cps * steps;
+	fifo_add_val(plan, cps);
+	plan->total += cps * steps;
 
 	/* What we do in this step */
-	curr_corr = fifo_push(&mdev->rs_plan_s, 0);
-	spin_unlock(&mdev->peer_seq_lock);
-	mdev->rs_planed -= curr_corr;
+	curr_corr = fifo_push(plan, 0);
+	plan->total -= curr_corr;
 
 	req_sect = sect_in + curr_corr;
 	if (req_sect < 0)
 		req_sect = 0;
 
-	max_sect = (mdev->sync_conf.c_max_rate * 2 * SLEEP_TIME) / HZ;
+	max_sect = (dc->c_max_rate * 2 * SLEEP_TIME) / HZ;
 	if (req_sect > max_sect)
 		req_sect = max_sect;
 
@@ -513,22 +543,25 @@ static int drbd_rs_controller(struct drbd_conf *mdev)
 static int drbd_rs_number_requests(struct drbd_conf *mdev)
 {
 	int number;
-	if (mdev->rs_plan_s.size) { /* mdev->sync_conf.c_plan_ahead */
+
+	rcu_read_lock();
+	if (rcu_dereference(mdev->rs_plan_s)->size) {
 		number = drbd_rs_controller(mdev) >> (BM_BLOCK_SHIFT - 9);
 		mdev->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / SLEEP_TIME;
 	} else {
-		mdev->c_sync_rate = mdev->sync_conf.rate;
+		mdev->c_sync_rate = rcu_dereference(mdev->ldev->disk_conf)->resync_rate;
 		number = SLEEP_TIME * mdev->c_sync_rate  / ((BM_BLOCK_SIZE / 1024) * HZ);
 	}
+	rcu_read_unlock();
 
 	/* ignore the amount of pending requests, the resync controller should
 	 * throttle down to incoming reply rate soon enough anyways. */
 	return number;
 }
 
-static int w_make_resync_request(struct drbd_conf *mdev,
-				 struct drbd_work *w, int cancel)
+int w_make_resync_request(struct drbd_work *w, int cancel)
 {
+	struct drbd_conf *mdev = w->mdev;
 	unsigned long bit;
 	sector_t sector;
 	const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
@@ -538,12 +571,12 @@ static int w_make_resync_request(struct drbd_conf *mdev,
 	int i = 0;
 
 	if (unlikely(cancel))
-		return 1;
+		return 0;
 
 	if (mdev->rs_total == 0) {
 		/* empty resync? */
 		drbd_resync_finished(mdev);
-		return 1;
+		return 0;
 	}
 
 	if (!get_ldev(mdev)) {
@@ -552,7 +585,7 @@ static int w_make_resync_request(struct drbd_conf *mdev,
 		   to continue resync with a broken disk makes no sense at
 		   all */
 		dev_err(DEV, "Disk broke down during resync!\n");
-		return 1;
+		return 0;
 	}
 
 	max_bio_size = queue_max_hw_sectors(mdev->rq_queue) << 9;
@@ -562,15 +595,15 @@ static int w_make_resync_request(struct drbd_conf *mdev,
 
 	for (i = 0; i < number; i++) {
 		/* Stop generating RS requests, when half of the send buffer is filled */
-		mutex_lock(&mdev->data.mutex);
-		if (mdev->data.socket) {
-			queued = mdev->data.socket->sk->sk_wmem_queued;
-			sndbuf = mdev->data.socket->sk->sk_sndbuf;
+		mutex_lock(&mdev->tconn->data.mutex);
+		if (mdev->tconn->data.socket) {
+			queued = mdev->tconn->data.socket->sk->sk_wmem_queued;
+			sndbuf = mdev->tconn->data.socket->sk->sk_sndbuf;
 		} else {
 			queued = 1;
 			sndbuf = 0;
 		}
-		mutex_unlock(&mdev->data.mutex);
+		mutex_unlock(&mdev->tconn->data.mutex);
 		if (queued > sndbuf / 2)
 			goto requeue;
 
@@ -581,7 +614,7 @@ next_sector:
 		if (bit == DRBD_END_OF_BITMAP) {
 			mdev->bm_resync_fo = drbd_bm_bits(mdev);
 			put_ldev(mdev);
-			return 1;
+			return 0;
 		}
 
 		sector = BM_BIT_TO_SECT(bit);
@@ -640,11 +673,11 @@ next_sector:
 		/* adjust very last sectors, in case we are oddly sized */
 		if (sector + (size>>9) > capacity)
 			size = (capacity-sector)<<9;
-		if (mdev->agreed_pro_version >= 89 && mdev->csums_tfm) {
+		if (mdev->tconn->agreed_pro_version >= 89 && mdev->tconn->csums_tfm) {
 			switch (read_for_csum(mdev, sector, size)) {
 			case -EIO: /* Disk failure */
 				put_ldev(mdev);
-				return 0;
+				return -EIO;
 			case -EAGAIN: /* allocation failed, or ldev busy */
 				drbd_rs_complete_io(mdev, sector);
 				mdev->bm_resync_fo = BM_SECT_TO_BIT(sector);
@@ -657,13 +690,16 @@ next_sector:
 				BUG();
 			}
 		} else {
+			int err;
+
 			inc_rs_pending(mdev);
-			if (!drbd_send_drequest(mdev, P_RS_DATA_REQUEST,
-					       sector, size, ID_SYNCER)) {
+			err = drbd_send_drequest(mdev, P_RS_DATA_REQUEST,
+						 sector, size, ID_SYNCER);
+			if (err) {
 				dev_err(DEV, "drbd_send_drequest() failed, aborting...\n");
 				dec_rs_pending(mdev);
 				put_ldev(mdev);
-				return 0;
+				return err;
 			}
 		}
 	}
@@ -676,21 +712,23 @@ next_sector:
 		 * until then resync "work" is "inactive" ...
 		 */
 		put_ldev(mdev);
-		return 1;
+		return 0;
 	}
 
  requeue:
 	mdev->rs_in_flight += (i << (BM_BLOCK_SHIFT - 9));
 	mod_timer(&mdev->resync_timer, jiffies + SLEEP_TIME);
 	put_ldev(mdev);
-	return 1;
+	return 0;
 }
 
-static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+static int w_make_ov_request(struct drbd_work *w, int cancel)
 {
+	struct drbd_conf *mdev = w->mdev;
 	int number, i, size;
 	sector_t sector;
 	const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
+	bool stop_sector_reached = false;
 
 	if (unlikely(cancel))
 		return 1;
@@ -699,9 +737,17 @@ static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int ca
 
 	sector = mdev->ov_position;
 	for (i = 0; i < number; i++) {
-		if (sector >= capacity) {
+		if (sector >= capacity)
 			return 1;
-		}
+
+		/* We check for "finished" only in the reply path:
+		 * w_e_end_ov_reply().
+		 * We need to send at least one request out. */
+		stop_sector_reached = i > 0
+			&& verify_can_do_stop_sector(mdev)
+			&& sector >= mdev->ov_stop_sector;
+		if (stop_sector_reached)
+			break;
 
 		size = BM_BLOCK_SIZE;
 
@@ -715,7 +761,7 @@ static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int ca
 			size = (capacity-sector)<<9;
 
 		inc_rs_pending(mdev);
-		if (!drbd_send_ov_request(mdev, sector, size)) {
+		if (drbd_send_ov_request(mdev, sector, size)) {
 			dec_rs_pending(mdev);
 			return 0;
 		}
@@ -725,56 +771,39 @@ static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int ca
 
  requeue:
 	mdev->rs_in_flight += (i << (BM_BLOCK_SHIFT - 9));
-	mod_timer(&mdev->resync_timer, jiffies + SLEEP_TIME);
-	return 1;
-}
-
-
-void start_resync_timer_fn(unsigned long data)
-{
-	struct drbd_conf *mdev = (struct drbd_conf *) data;
-
-	drbd_queue_work(&mdev->data.work, &mdev->start_resync_work);
-}
-
-int w_start_resync(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
-{
-	if (atomic_read(&mdev->unacked_cnt) || atomic_read(&mdev->rs_pending_cnt)) {
-		dev_warn(DEV, "w_start_resync later...\n");
-		mdev->start_resync_timer.expires = jiffies + HZ/10;
-		add_timer(&mdev->start_resync_timer);
-		return 1;
-	}
-
-	drbd_start_resync(mdev, C_SYNC_SOURCE);
-	clear_bit(AHEAD_TO_SYNC_SOURCE, &mdev->flags);
+	if (i == 0 || !stop_sector_reached)
+		mod_timer(&mdev->resync_timer, jiffies + SLEEP_TIME);
 	return 1;
 }
 
-int w_ov_finished(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+int w_ov_finished(struct drbd_work *w, int cancel)
 {
+	struct drbd_conf *mdev = w->mdev;
 	kfree(w);
-	ov_oos_print(mdev);
+	ov_out_of_sync_print(mdev);
 	drbd_resync_finished(mdev);
 
-	return 1;
+	return 0;
 }
 
-static int w_resync_finished(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+static int w_resync_finished(struct drbd_work *w, int cancel)
 {
+	struct drbd_conf *mdev = w->mdev;
 	kfree(w);
 
 	drbd_resync_finished(mdev);
 
-	return 1;
+	return 0;
 }
 
 static void ping_peer(struct drbd_conf *mdev)
 {
-	clear_bit(GOT_PING_ACK, &mdev->flags);
-	request_ping(mdev);
-	wait_event(mdev->misc_wait,
-		   test_bit(GOT_PING_ACK, &mdev->flags) || mdev->state.conn < C_CONNECTED);
+	struct drbd_tconn *tconn = mdev->tconn;
+
+	clear_bit(GOT_PING_ACK, &tconn->flags);
+	request_ping(tconn);
+	wait_event(tconn->ping_wait,
+		   test_bit(GOT_PING_ACK, &tconn->flags) || mdev->state.conn < C_CONNECTED);
 }
 
 int drbd_resync_finished(struct drbd_conf *mdev)
@@ -799,7 +828,8 @@ int drbd_resync_finished(struct drbd_conf *mdev)
 		w = kmalloc(sizeof(struct drbd_work), GFP_ATOMIC);
 		if (w) {
 			w->cb = w_resync_finished;
-			drbd_queue_work(&mdev->data.work, w);
+			w->mdev = mdev;
+			drbd_queue_work(&mdev->tconn->sender_work, w);
 			return 1;
 		}
 		dev_err(DEV, "Warn failed to drbd_rs_del_all() and to kmalloc(w).\n");
@@ -808,7 +838,12 @@ int drbd_resync_finished(struct drbd_conf *mdev)
 	dt = (jiffies - mdev->rs_start - mdev->rs_paused) / HZ;
 	if (dt <= 0)
 		dt = 1;
+	
 	db = mdev->rs_total;
+	/* adjust for verify start and stop sectors, respective reached position */
+	if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T)
+		db -= mdev->ov_left;
+
 	dbdt = Bit2KB(db/dt);
 	mdev->rs_paused /= HZ;
 
@@ -817,8 +852,8 @@ int drbd_resync_finished(struct drbd_conf *mdev)
 
 	ping_peer(mdev);
 
-	spin_lock_irq(&mdev->req_lock);
-	os = mdev->state;
+	spin_lock_irq(&mdev->tconn->req_lock);
+	os = drbd_read_state(mdev);
 
 	verify_done = (os.conn == C_VERIFY_S || os.conn == C_VERIFY_T);
 
@@ -831,7 +866,7 @@ int drbd_resync_finished(struct drbd_conf *mdev)
 	ns.conn = C_CONNECTED;
 
 	dev_info(DEV, "%s done (total %lu sec; paused %lu sec; %lu K/sec)\n",
-	     verify_done ? "Online verify " : "Resync",
+	     verify_done ? "Online verify" : "Resync",
 	     dt + mdev->rs_paused, mdev->rs_paused, dbdt);
 
 	n_oos = drbd_bm_total_weight(mdev);
@@ -848,7 +883,7 @@ int drbd_resync_finished(struct drbd_conf *mdev)
 		if (os.conn == C_SYNC_TARGET || os.conn == C_PAUSED_SYNC_T)
 			khelper_cmd = "after-resync-target";
 
-		if (mdev->csums_tfm && mdev->rs_total) {
+		if (mdev->tconn->csums_tfm && mdev->rs_total) {
 			const unsigned long s = mdev->rs_same_csum;
 			const unsigned long t = mdev->rs_total;
 			const int ratio =
@@ -906,13 +941,15 @@ int drbd_resync_finished(struct drbd_conf *mdev)
 
 	_drbd_set_state(mdev, ns, CS_VERBOSE, NULL);
 out_unlock:
-	spin_unlock_irq(&mdev->req_lock);
+	spin_unlock_irq(&mdev->tconn->req_lock);
 	put_ldev(mdev);
 out:
 	mdev->rs_total  = 0;
 	mdev->rs_failed = 0;
 	mdev->rs_paused = 0;
-	if (verify_done)
+
+	/* reset start sector, if we reached end of device */
+	if (verify_done && mdev->ov_left == 0)
 		mdev->ov_start_sector = 0;
 
 	drbd_md_sync(mdev);
@@ -924,19 +961,19 @@ out:
 }
 
 /* helper */
-static void move_to_net_ee_or_free(struct drbd_conf *mdev, struct drbd_epoch_entry *e)
+static void move_to_net_ee_or_free(struct drbd_conf *mdev, struct drbd_peer_request *peer_req)
 {
-	if (drbd_ee_has_active_page(e)) {
+	if (drbd_peer_req_has_active_page(peer_req)) {
 		/* This might happen if sendpage() has not finished */
-		int i = (e->size + PAGE_SIZE -1) >> PAGE_SHIFT;
+		int i = (peer_req->i.size + PAGE_SIZE -1) >> PAGE_SHIFT;
 		atomic_add(i, &mdev->pp_in_use_by_net);
 		atomic_sub(i, &mdev->pp_in_use);
-		spin_lock_irq(&mdev->req_lock);
-		list_add_tail(&e->w.list, &mdev->net_ee);
-		spin_unlock_irq(&mdev->req_lock);
+		spin_lock_irq(&mdev->tconn->req_lock);
+		list_add_tail(&peer_req->w.list, &mdev->net_ee);
+		spin_unlock_irq(&mdev->tconn->req_lock);
 		wake_up(&drbd_pp_wait);
 	} else
-		drbd_free_ee(mdev, e);
+		drbd_free_peer_req(mdev, peer_req);
 }
 
 /**
@@ -945,174 +982,177 @@ static void move_to_net_ee_or_free(struct drbd_conf *mdev, struct drbd_epoch_ent
  * @w:		work object.
  * @cancel:	The connection will be closed anyways
  */
-int w_e_end_data_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+int w_e_end_data_req(struct drbd_work *w, int cancel)
 {
-	struct drbd_epoch_entry *e = container_of(w, struct drbd_epoch_entry, w);
-	int ok;
+	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
+	struct drbd_conf *mdev = w->mdev;
+	int err;
 
 	if (unlikely(cancel)) {
-		drbd_free_ee(mdev, e);
+		drbd_free_peer_req(mdev, peer_req);
 		dec_unacked(mdev);
-		return 1;
+		return 0;
 	}
 
-	if (likely((e->flags & EE_WAS_ERROR) == 0)) {
-		ok = drbd_send_block(mdev, P_DATA_REPLY, e);
+	if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
+		err = drbd_send_block(mdev, P_DATA_REPLY, peer_req);
 	} else {
 		if (__ratelimit(&drbd_ratelimit_state))
 			dev_err(DEV, "Sending NegDReply. sector=%llus.\n",
-			    (unsigned long long)e->sector);
+			    (unsigned long long)peer_req->i.sector);
 
-		ok = drbd_send_ack(mdev, P_NEG_DREPLY, e);
+		err = drbd_send_ack(mdev, P_NEG_DREPLY, peer_req);
 	}
 
 	dec_unacked(mdev);
 
-	move_to_net_ee_or_free(mdev, e);
+	move_to_net_ee_or_free(mdev, peer_req);
 
-	if (unlikely(!ok))
+	if (unlikely(err))
 		dev_err(DEV, "drbd_send_block() failed\n");
-	return ok;
+	return err;
 }
 
 /**
- * w_e_end_rsdata_req() - Worker callback to send a P_RS_DATA_REPLY packet in response to a P_RS_DATA_REQUESTRS
+ * w_e_end_rsdata_req() - Worker callback to send a P_RS_DATA_REPLY packet in response to a P_RS_DATA_REQUEST
  * @mdev:	DRBD device.
  * @w:		work object.
  * @cancel:	The connection will be closed anyways
  */
-int w_e_end_rsdata_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+int w_e_end_rsdata_req(struct drbd_work *w, int cancel)
 {
-	struct drbd_epoch_entry *e = container_of(w, struct drbd_epoch_entry, w);
-	int ok;
+	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
+	struct drbd_conf *mdev = w->mdev;
+	int err;
 
 	if (unlikely(cancel)) {
-		drbd_free_ee(mdev, e);
+		drbd_free_peer_req(mdev, peer_req);
 		dec_unacked(mdev);
-		return 1;
+		return 0;
 	}
 
 	if (get_ldev_if_state(mdev, D_FAILED)) {
-		drbd_rs_complete_io(mdev, e->sector);
+		drbd_rs_complete_io(mdev, peer_req->i.sector);
 		put_ldev(mdev);
 	}
 
 	if (mdev->state.conn == C_AHEAD) {
-		ok = drbd_send_ack(mdev, P_RS_CANCEL, e);
-	} else if (likely((e->flags & EE_WAS_ERROR) == 0)) {
+		err = drbd_send_ack(mdev, P_RS_CANCEL, peer_req);
+	} else if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
 		if (likely(mdev->state.pdsk >= D_INCONSISTENT)) {
 			inc_rs_pending(mdev);
-			ok = drbd_send_block(mdev, P_RS_DATA_REPLY, e);
+			err = drbd_send_block(mdev, P_RS_DATA_REPLY, peer_req);
 		} else {
 			if (__ratelimit(&drbd_ratelimit_state))
 				dev_err(DEV, "Not sending RSDataReply, "
 				    "partner DISKLESS!\n");
-			ok = 1;
+			err = 0;
 		}
 	} else {
 		if (__ratelimit(&drbd_ratelimit_state))
 			dev_err(DEV, "Sending NegRSDReply. sector %llus.\n",
-			    (unsigned long long)e->sector);
+			    (unsigned long long)peer_req->i.sector);
 
-		ok = drbd_send_ack(mdev, P_NEG_RS_DREPLY, e);
+		err = drbd_send_ack(mdev, P_NEG_RS_DREPLY, peer_req);
 
 		/* update resync data with failure */
-		drbd_rs_failed_io(mdev, e->sector, e->size);
+		drbd_rs_failed_io(mdev, peer_req->i.sector, peer_req->i.size);
 	}
 
 	dec_unacked(mdev);
 
-	move_to_net_ee_or_free(mdev, e);
+	move_to_net_ee_or_free(mdev, peer_req);
 
-	if (unlikely(!ok))
+	if (unlikely(err))
 		dev_err(DEV, "drbd_send_block() failed\n");
-	return ok;
+	return err;
 }
 
-int w_e_end_csum_rs_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+int w_e_end_csum_rs_req(struct drbd_work *w, int cancel)
 {
-	struct drbd_epoch_entry *e = container_of(w, struct drbd_epoch_entry, w);
+	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
+	struct drbd_conf *mdev = w->mdev;
 	struct digest_info *di;
 	int digest_size;
 	void *digest = NULL;
-	int ok, eq = 0;
+	int err, eq = 0;
 
 	if (unlikely(cancel)) {
-		drbd_free_ee(mdev, e);
+		drbd_free_peer_req(mdev, peer_req);
 		dec_unacked(mdev);
-		return 1;
+		return 0;
 	}
 
 	if (get_ldev(mdev)) {
-		drbd_rs_complete_io(mdev, e->sector);
+		drbd_rs_complete_io(mdev, peer_req->i.sector);
 		put_ldev(mdev);
 	}
 
-	di = e->digest;
+	di = peer_req->digest;
 
-	if (likely((e->flags & EE_WAS_ERROR) == 0)) {
+	if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
 		/* quick hack to try to avoid a race against reconfiguration.
 		 * a real fix would be much more involved,
 		 * introducing more locking mechanisms */
-		if (mdev->csums_tfm) {
-			digest_size = crypto_hash_digestsize(mdev->csums_tfm);
+		if (mdev->tconn->csums_tfm) {
+			digest_size = crypto_hash_digestsize(mdev->tconn->csums_tfm);
 			D_ASSERT(digest_size == di->digest_size);
 			digest = kmalloc(digest_size, GFP_NOIO);
 		}
 		if (digest) {
-			drbd_csum_ee(mdev, mdev->csums_tfm, e, digest);
+			drbd_csum_ee(mdev, mdev->tconn->csums_tfm, peer_req, digest);
 			eq = !memcmp(digest, di->digest, digest_size);
 			kfree(digest);
 		}
 
 		if (eq) {
-			drbd_set_in_sync(mdev, e->sector, e->size);
+			drbd_set_in_sync(mdev, peer_req->i.sector, peer_req->i.size);
 			/* rs_same_csums unit is BM_BLOCK_SIZE */
-			mdev->rs_same_csum += e->size >> BM_BLOCK_SHIFT;
-			ok = drbd_send_ack(mdev, P_RS_IS_IN_SYNC, e);
+			mdev->rs_same_csum += peer_req->i.size >> BM_BLOCK_SHIFT;
+			err = drbd_send_ack(mdev, P_RS_IS_IN_SYNC, peer_req);
 		} else {
 			inc_rs_pending(mdev);
-			e->block_id = ID_SYNCER; /* By setting block_id, digest pointer becomes invalid! */
-			e->flags &= ~EE_HAS_DIGEST; /* This e no longer has a digest pointer */
+			peer_req->block_id = ID_SYNCER; /* By setting block_id, digest pointer becomes invalid! */
+			peer_req->flags &= ~EE_HAS_DIGEST; /* This peer request no longer has a digest pointer */
 			kfree(di);
-			ok = drbd_send_block(mdev, P_RS_DATA_REPLY, e);
+			err = drbd_send_block(mdev, P_RS_DATA_REPLY, peer_req);
 		}
 	} else {
-		ok = drbd_send_ack(mdev, P_NEG_RS_DREPLY, e);
+		err = drbd_send_ack(mdev, P_NEG_RS_DREPLY, peer_req);
 		if (__ratelimit(&drbd_ratelimit_state))
 			dev_err(DEV, "Sending NegDReply. I guess it gets messy.\n");
 	}
 
 	dec_unacked(mdev);
-	move_to_net_ee_or_free(mdev, e);
+	move_to_net_ee_or_free(mdev, peer_req);
 
-	if (unlikely(!ok))
+	if (unlikely(err))
 		dev_err(DEV, "drbd_send_block/ack() failed\n");
-	return ok;
+	return err;
 }
 
-/* TODO merge common code with w_e_send_csum */
-int w_e_end_ov_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+int w_e_end_ov_req(struct drbd_work *w, int cancel)
 {
-	struct drbd_epoch_entry *e = container_of(w, struct drbd_epoch_entry, w);
-	sector_t sector = e->sector;
-	unsigned int size = e->size;
+	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
+	struct drbd_conf *mdev = w->mdev;
+	sector_t sector = peer_req->i.sector;
+	unsigned int size = peer_req->i.size;
 	int digest_size;
 	void *digest;
-	int ok = 1;
+	int err = 0;
 
 	if (unlikely(cancel))
 		goto out;
 
-	digest_size = crypto_hash_digestsize(mdev->verify_tfm);
+	digest_size = crypto_hash_digestsize(mdev->tconn->verify_tfm);
 	digest = kmalloc(digest_size, GFP_NOIO);
 	if (!digest) {
-		ok = 0;	/* terminate the connection in case the allocation failed */
+		err = 1;	/* terminate the connection in case the allocation failed */
 		goto out;
 	}
 
-	if (likely(!(e->flags & EE_WAS_ERROR)))
-		drbd_csum_ee(mdev, mdev->verify_tfm, e, digest);
+	if (likely(!(peer_req->flags & EE_WAS_ERROR)))
+		drbd_csum_ee(mdev, mdev->tconn->verify_tfm, peer_req, digest);
 	else
 		memset(digest, 0, digest_size);
 
@@ -1120,25 +1160,23 @@ int w_e_end_ov_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
 	 * In case we block on congestion, we could otherwise run into
 	 * some distributed deadlock, if the other side blocks on
 	 * congestion as well, because our receiver blocks in
-	 * drbd_pp_alloc due to pp_in_use > max_buffers. */
-	drbd_free_ee(mdev, e);
-	e = NULL;
+	 * drbd_alloc_pages due to pp_in_use > max_buffers. */
+	drbd_free_peer_req(mdev, peer_req);
+	peer_req = NULL;
 	inc_rs_pending(mdev);
-	ok = drbd_send_drequest_csum(mdev, sector, size,
-				     digest, digest_size,
-				     P_OV_REPLY);
-	if (!ok)
+	err = drbd_send_drequest_csum(mdev, sector, size, digest, digest_size, P_OV_REPLY);
+	if (err)
 		dec_rs_pending(mdev);
 	kfree(digest);
 
 out:
-	if (e)
-		drbd_free_ee(mdev, e);
+	if (peer_req)
+		drbd_free_peer_req(mdev, peer_req);
 	dec_unacked(mdev);
-	return ok;
+	return err;
 }
 
-void drbd_ov_oos_found(struct drbd_conf *mdev, sector_t sector, int size)
+void drbd_ov_out_of_sync_found(struct drbd_conf *mdev, sector_t sector, int size)
 {
 	if (mdev->ov_last_oos_start + mdev->ov_last_oos_size == sector) {
 		mdev->ov_last_oos_size += size>>9;
@@ -1149,36 +1187,38 @@ void drbd_ov_oos_found(struct drbd_conf *mdev, sector_t sector, int size)
 	drbd_set_out_of_sync(mdev, sector, size);
 }
 
-int w_e_end_ov_reply(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+int w_e_end_ov_reply(struct drbd_work *w, int cancel)
 {
-	struct drbd_epoch_entry *e = container_of(w, struct drbd_epoch_entry, w);
+	struct drbd_peer_request *peer_req = container_of(w, struct drbd_peer_request, w);
+	struct drbd_conf *mdev = w->mdev;
 	struct digest_info *di;
 	void *digest;
-	sector_t sector = e->sector;
-	unsigned int size = e->size;
+	sector_t sector = peer_req->i.sector;
+	unsigned int size = peer_req->i.size;
 	int digest_size;
-	int ok, eq = 0;
+	int err, eq = 0;
+	bool stop_sector_reached = false;
 
 	if (unlikely(cancel)) {
-		drbd_free_ee(mdev, e);
+		drbd_free_peer_req(mdev, peer_req);
 		dec_unacked(mdev);
-		return 1;
+		return 0;
 	}
 
 	/* after "cancel", because after drbd_disconnect/drbd_rs_cancel_all
 	 * the resync lru has been cleaned up already */
 	if (get_ldev(mdev)) {
-		drbd_rs_complete_io(mdev, e->sector);
+		drbd_rs_complete_io(mdev, peer_req->i.sector);
 		put_ldev(mdev);
 	}
 
-	di = e->digest;
+	di = peer_req->digest;
 
-	if (likely((e->flags & EE_WAS_ERROR) == 0)) {
-		digest_size = crypto_hash_digestsize(mdev->verify_tfm);
+	if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
+		digest_size = crypto_hash_digestsize(mdev->tconn->verify_tfm);
 		digest = kmalloc(digest_size, GFP_NOIO);
 		if (digest) {
-			drbd_csum_ee(mdev, mdev->verify_tfm, e, digest);
+			drbd_csum_ee(mdev, mdev->tconn->verify_tfm, peer_req, digest);
 
 			D_ASSERT(digest_size == di->digest_size);
 			eq = !memcmp(digest, di->digest, digest_size);
@@ -1186,19 +1226,19 @@ int w_e_end_ov_reply(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
 		}
 	}
 
-		/* Free e and pages before send.
-		 * In case we block on congestion, we could otherwise run into
-		 * some distributed deadlock, if the other side blocks on
-		 * congestion as well, because our receiver blocks in
-		 * drbd_pp_alloc due to pp_in_use > max_buffers. */
-	drbd_free_ee(mdev, e);
+	/* Free peer_req and pages before send.
+	 * In case we block on congestion, we could otherwise run into
+	 * some distributed deadlock, if the other side blocks on
+	 * congestion as well, because our receiver blocks in
+	 * drbd_alloc_pages due to pp_in_use > max_buffers. */
+	drbd_free_peer_req(mdev, peer_req);
 	if (!eq)
-		drbd_ov_oos_found(mdev, sector, size);
+		drbd_ov_out_of_sync_found(mdev, sector, size);
 	else
-		ov_oos_print(mdev);
+		ov_out_of_sync_print(mdev);
 
-	ok = drbd_send_ack_ex(mdev, P_OV_RESULT, sector, size,
-			      eq ? ID_IN_SYNC : ID_OUT_OF_SYNC);
+	err = drbd_send_ack_ex(mdev, P_OV_RESULT, sector, size,
+			       eq ? ID_IN_SYNC : ID_OUT_OF_SYNC);
 
 	dec_unacked(mdev);
 
@@ -1208,73 +1248,102 @@ int w_e_end_ov_reply(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
 	if ((mdev->ov_left & 0x200) == 0x200)
 		drbd_advance_rs_marks(mdev, mdev->ov_left);
 
-	if (mdev->ov_left == 0) {
-		ov_oos_print(mdev);
+	stop_sector_reached = verify_can_do_stop_sector(mdev) &&
+		(sector + (size>>9)) >= mdev->ov_stop_sector;
+
+	if (mdev->ov_left == 0 || stop_sector_reached) {
+		ov_out_of_sync_print(mdev);
 		drbd_resync_finished(mdev);
 	}
 
-	return ok;
+	return err;
 }
 
-int w_prev_work_done(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+int w_prev_work_done(struct drbd_work *w, int cancel)
 {
 	struct drbd_wq_barrier *b = container_of(w, struct drbd_wq_barrier, w);
+
 	complete(&b->done);
-	return 1;
+	return 0;
 }
 
-int w_send_barrier(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+/* FIXME
+ * We need to track the number of pending barrier acks,
+ * and to be able to wait for them.
+ * See also comment in drbd_adm_attach before drbd_suspend_io.
+ */
+int drbd_send_barrier(struct drbd_tconn *tconn)
 {
-	struct drbd_tl_epoch *b = container_of(w, struct drbd_tl_epoch, w);
-	struct p_barrier *p = &mdev->data.sbuf.barrier;
-	int ok = 1;
-
-	/* really avoid racing with tl_clear.  w.cb may have been referenced
-	 * just before it was reassigned and re-queued, so double check that.
-	 * actually, this race was harmless, since we only try to send the
-	 * barrier packet here, and otherwise do nothing with the object.
-	 * but compare with the head of w_clear_epoch */
-	spin_lock_irq(&mdev->req_lock);
-	if (w->cb != w_send_barrier || mdev->state.conn < C_CONNECTED)
-		cancel = 1;
-	spin_unlock_irq(&mdev->req_lock);
-	if (cancel)
-		return 1;
+	struct p_barrier *p;
+	struct drbd_socket *sock;
 
-	if (!drbd_get_data_sock(mdev))
-		return 0;
-	p->barrier = b->br_number;
-	/* inc_ap_pending was done where this was queued.
-	 * dec_ap_pending will be done in got_BarrierAck
-	 * or (on connection loss) in w_clear_epoch.  */
-	ok = _drbd_send_cmd(mdev, mdev->data.socket, P_BARRIER,
-				(struct p_header80 *)p, sizeof(*p), 0);
-	drbd_put_data_sock(mdev);
-
-	return ok;
+	sock = &tconn->data;
+	p = conn_prepare_command(tconn, sock);
+	if (!p)
+		return -EIO;
+	p->barrier = tconn->send.current_epoch_nr;
+	p->pad = 0;
+	tconn->send.current_epoch_writes = 0;
+
+	return conn_send_command(tconn, sock, P_BARRIER, sizeof(*p), NULL, 0);
 }
 
-int w_send_write_hint(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+int w_send_write_hint(struct drbd_work *w, int cancel)
 {
+	struct drbd_conf *mdev = w->mdev;
+	struct drbd_socket *sock;
+
 	if (cancel)
-		return 1;
-	return drbd_send_short_cmd(mdev, P_UNPLUG_REMOTE);
+		return 0;
+	sock = &mdev->tconn->data;
+	if (!drbd_prepare_command(mdev, sock))
+		return -EIO;
+	return drbd_send_command(mdev, sock, P_UNPLUG_REMOTE, 0, NULL, 0);
 }
 
-int w_send_oos(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+static void re_init_if_first_write(struct drbd_tconn *tconn, unsigned int epoch)
+{
+	if (!tconn->send.seen_any_write_yet) {
+		tconn->send.seen_any_write_yet = true;
+		tconn->send.current_epoch_nr = epoch;
+		tconn->send.current_epoch_writes = 0;
+	}
+}
+
+static void maybe_send_barrier(struct drbd_tconn *tconn, unsigned int epoch)
+{
+	/* re-init if first write on this connection */
+	if (!tconn->send.seen_any_write_yet)
+		return;
+	if (tconn->send.current_epoch_nr != epoch) {
+		if (tconn->send.current_epoch_writes)
+			drbd_send_barrier(tconn);
+		tconn->send.current_epoch_nr = epoch;
+	}
+}
+
+int w_send_out_of_sync(struct drbd_work *w, int cancel)
 {
 	struct drbd_request *req = container_of(w, struct drbd_request, w);
-	int ok;
+	struct drbd_conf *mdev = w->mdev;
+	struct drbd_tconn *tconn = mdev->tconn;
+	int err;
 
 	if (unlikely(cancel)) {
-		req_mod(req, send_canceled);
-		return 1;
+		req_mod(req, SEND_CANCELED);
+		return 0;
 	}
 
-	ok = drbd_send_oos(mdev, req);
-	req_mod(req, oos_handed_to_network);
+	/* this time, no tconn->send.current_epoch_writes++;
+	 * If it was sent, it was the closing barrier for the last
+	 * replicated epoch, before we went into AHEAD mode.
+	 * No more barriers will be sent, until we leave AHEAD mode again. */
+	maybe_send_barrier(tconn, req->epoch);
+
+	err = drbd_send_out_of_sync(mdev, req);
+	req_mod(req, OOS_HANDED_TO_NETWORK);
 
-	return ok;
+	return err;
 }
 
 /**
@@ -1283,20 +1352,26 @@ int w_send_oos(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
  * @w:		work object.
  * @cancel:	The connection will be closed anyways
  */
-int w_send_dblock(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+int w_send_dblock(struct drbd_work *w, int cancel)
 {
 	struct drbd_request *req = container_of(w, struct drbd_request, w);
-	int ok;
+	struct drbd_conf *mdev = w->mdev;
+	struct drbd_tconn *tconn = mdev->tconn;
+	int err;
 
 	if (unlikely(cancel)) {
-		req_mod(req, send_canceled);
-		return 1;
+		req_mod(req, SEND_CANCELED);
+		return 0;
 	}
 
-	ok = drbd_send_dblock(mdev, req);
-	req_mod(req, ok ? handed_over_to_network : send_failed);
+	re_init_if_first_write(tconn, req->epoch);
+	maybe_send_barrier(tconn, req->epoch);
+	tconn->send.current_epoch_writes++;
+
+	err = drbd_send_dblock(mdev, req);
+	req_mod(req, err ? SEND_FAILED : HANDED_OVER_TO_NETWORK);
 
-	return ok;
+	return err;
 }
 
 /**
@@ -1305,57 +1380,61 @@ int w_send_dblock(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
  * @w:		work object.
  * @cancel:	The connection will be closed anyways
  */
-int w_send_read_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+int w_send_read_req(struct drbd_work *w, int cancel)
 {
 	struct drbd_request *req = container_of(w, struct drbd_request, w);
-	int ok;
+	struct drbd_conf *mdev = w->mdev;
+	struct drbd_tconn *tconn = mdev->tconn;
+	int err;
 
 	if (unlikely(cancel)) {
-		req_mod(req, send_canceled);
-		return 1;
+		req_mod(req, SEND_CANCELED);
+		return 0;
 	}
 
-	ok = drbd_send_drequest(mdev, P_DATA_REQUEST, req->sector, req->size,
-				(unsigned long)req);
+	/* Even read requests may close a write epoch,
+	 * if there was any yet. */
+	maybe_send_barrier(tconn, req->epoch);
 
-	if (!ok) {
-		/* ?? we set C_TIMEOUT or C_BROKEN_PIPE in drbd_send();
-		 * so this is probably redundant */
-		if (mdev->state.conn >= C_CONNECTED)
-			drbd_force_state(mdev, NS(conn, C_NETWORK_FAILURE));
-	}
-	req_mod(req, ok ? handed_over_to_network : send_failed);
+	err = drbd_send_drequest(mdev, P_DATA_REQUEST, req->i.sector, req->i.size,
+				 (unsigned long)req);
+
+	req_mod(req, err ? SEND_FAILED : HANDED_OVER_TO_NETWORK);
 
-	return ok;
+	return err;
 }
 
-int w_restart_disk_io(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+int w_restart_disk_io(struct drbd_work *w, int cancel)
 {
 	struct drbd_request *req = container_of(w, struct drbd_request, w);
+	struct drbd_conf *mdev = w->mdev;
 
 	if (bio_data_dir(req->master_bio) == WRITE && req->rq_state & RQ_IN_ACT_LOG)
-		drbd_al_begin_io(mdev, req->sector);
-	/* Calling drbd_al_begin_io() out of the worker might deadlocks
-	   theoretically. Practically it can not deadlock, since this is
-	   only used when unfreezing IOs. All the extents of the requests
-	   that made it into the TL are already active */
+		drbd_al_begin_io(mdev, &req->i);
 
 	drbd_req_make_private_bio(req, req->master_bio);
 	req->private_bio->bi_bdev = mdev->ldev->backing_bdev;
 	generic_make_request(req->private_bio);
 
-	return 1;
+	return 0;
 }
 
 static int _drbd_may_sync_now(struct drbd_conf *mdev)
 {
 	struct drbd_conf *odev = mdev;
+	int resync_after;
 
 	while (1) {
-		if (odev->sync_conf.after == -1)
+		if (!odev->ldev)
+			return 1;
+		rcu_read_lock();
+		resync_after = rcu_dereference(odev->ldev->disk_conf)->resync_after;
+		rcu_read_unlock();
+		if (resync_after == -1)
+			return 1;
+		odev = minor_to_mdev(resync_after);
+		if (!expect(odev))
 			return 1;
-		odev = minor_to_mdev(odev->sync_conf.after);
-		ERR_IF(!odev) return 1;
 		if ((odev->state.conn >= C_SYNC_SOURCE &&
 		     odev->state.conn <= C_PAUSED_SYNC_T) ||
 		    odev->state.aftr_isp || odev->state.peer_isp ||
@@ -1375,16 +1454,15 @@ static int _drbd_pause_after(struct drbd_conf *mdev)
 	struct drbd_conf *odev;
 	int i, rv = 0;
 
-	for (i = 0; i < minor_count; i++) {
-		odev = minor_to_mdev(i);
-		if (!odev)
-			continue;
+	rcu_read_lock();
+	idr_for_each_entry(&minors, odev, i) {
 		if (odev->state.conn == C_STANDALONE && odev->state.disk == D_DISKLESS)
 			continue;
 		if (!_drbd_may_sync_now(odev))
 			rv |= (__drbd_set_state(_NS(odev, aftr_isp, 1), CS_HARD, NULL)
 			       != SS_NOTHING_TO_DO);
 	}
+	rcu_read_unlock();
 
 	return rv;
 }
@@ -1400,10 +1478,8 @@ static int _drbd_resume_next(struct drbd_conf *mdev)
 	struct drbd_conf *odev;
 	int i, rv = 0;
 
-	for (i = 0; i < minor_count; i++) {
-		odev = minor_to_mdev(i);
-		if (!odev)
-			continue;
+	rcu_read_lock();
+	idr_for_each_entry(&minors, odev, i) {
 		if (odev->state.conn == C_STANDALONE && odev->state.disk == D_DISKLESS)
 			continue;
 		if (odev->state.aftr_isp) {
@@ -1413,6 +1489,7 @@ static int _drbd_resume_next(struct drbd_conf *mdev)
 				       != SS_NOTHING_TO_DO) ;
 		}
 	}
+	rcu_read_unlock();
 	return rv;
 }
 
@@ -1430,57 +1507,86 @@ void suspend_other_sg(struct drbd_conf *mdev)
 	write_unlock_irq(&global_state_lock);
 }
 
-static int sync_after_error(struct drbd_conf *mdev, int o_minor)
+/* caller must hold global_state_lock */
+enum drbd_ret_code drbd_resync_after_valid(struct drbd_conf *mdev, int o_minor)
 {
 	struct drbd_conf *odev;
+	int resync_after;
 
 	if (o_minor == -1)
 		return NO_ERROR;
 	if (o_minor < -1 || minor_to_mdev(o_minor) == NULL)
-		return ERR_SYNC_AFTER;
+		return ERR_RESYNC_AFTER;
 
 	/* check for loops */
 	odev = minor_to_mdev(o_minor);
 	while (1) {
 		if (odev == mdev)
-			return ERR_SYNC_AFTER_CYCLE;
+			return ERR_RESYNC_AFTER_CYCLE;
 
+		rcu_read_lock();
+		resync_after = rcu_dereference(odev->ldev->disk_conf)->resync_after;
+		rcu_read_unlock();
 		/* dependency chain ends here, no cycles. */
-		if (odev->sync_conf.after == -1)
+		if (resync_after == -1)
 			return NO_ERROR;
 
 		/* follow the dependency chain */
-		odev = minor_to_mdev(odev->sync_conf.after);
+		odev = minor_to_mdev(resync_after);
 	}
 }
 
-int drbd_alter_sa(struct drbd_conf *mdev, int na)
+/* caller must hold global_state_lock */
+void drbd_resync_after_changed(struct drbd_conf *mdev)
 {
 	int changes;
-	int retcode;
 
-	write_lock_irq(&global_state_lock);
-	retcode = sync_after_error(mdev, na);
-	if (retcode == NO_ERROR) {
-		mdev->sync_conf.after = na;
-		do {
-			changes  = _drbd_pause_after(mdev);
-			changes |= _drbd_resume_next(mdev);
-		} while (changes);
-	}
-	write_unlock_irq(&global_state_lock);
-	return retcode;
+	do {
+		changes  = _drbd_pause_after(mdev);
+		changes |= _drbd_resume_next(mdev);
+	} while (changes);
 }
 
 void drbd_rs_controller_reset(struct drbd_conf *mdev)
 {
+	struct fifo_buffer *plan;
+
 	atomic_set(&mdev->rs_sect_in, 0);
 	atomic_set(&mdev->rs_sect_ev, 0);
 	mdev->rs_in_flight = 0;
-	mdev->rs_planed = 0;
-	spin_lock(&mdev->peer_seq_lock);
-	fifo_set(&mdev->rs_plan_s, 0);
-	spin_unlock(&mdev->peer_seq_lock);
+
+	/* Updating the RCU protected object in place is necessary since
+	   this function gets called from atomic context.
+	   It is valid since all other updates also lead to an completely
+	   empty fifo */
+	rcu_read_lock();
+	plan = rcu_dereference(mdev->rs_plan_s);
+	plan->total = 0;
+	fifo_set(plan, 0);
+	rcu_read_unlock();
+}
+
+void start_resync_timer_fn(unsigned long data)
+{
+	struct drbd_conf *mdev = (struct drbd_conf *) data;
+
+	drbd_queue_work(&mdev->tconn->sender_work, &mdev->start_resync_work);
+}
+
+int w_start_resync(struct drbd_work *w, int cancel)
+{
+	struct drbd_conf *mdev = w->mdev;
+
+	if (atomic_read(&mdev->unacked_cnt) || atomic_read(&mdev->rs_pending_cnt)) {
+		dev_warn(DEV, "w_start_resync later...\n");
+		mdev->start_resync_timer.expires = jiffies + HZ/10;
+		add_timer(&mdev->start_resync_timer);
+		return 0;
+	}
+
+	drbd_start_resync(mdev, C_SYNC_SOURCE);
+	clear_bit(AHEAD_TO_SYNC_SOURCE, &mdev->flags);
+	return 0;
 }
 
 /**
@@ -1501,43 +1607,58 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
 		return;
 	}
 
-	if (side == C_SYNC_TARGET) {
-		/* Since application IO was locked out during C_WF_BITMAP_T and
-		   C_WF_SYNC_UUID we are still unmodified. Before going to C_SYNC_TARGET
-		   we check that we might make the data inconsistent. */
-		r = drbd_khelper(mdev, "before-resync-target");
-		r = (r >> 8) & 0xff;
-		if (r > 0) {
-			dev_info(DEV, "before-resync-target handler returned %d, "
-			     "dropping connection.\n", r);
-			drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-			return;
-		}
-	} else /* C_SYNC_SOURCE */ {
-		r = drbd_khelper(mdev, "before-resync-source");
-		r = (r >> 8) & 0xff;
-		if (r > 0) {
-			if (r == 3) {
-				dev_info(DEV, "before-resync-source handler returned %d, "
-					 "ignoring. Old userland tools?", r);
-			} else {
-				dev_info(DEV, "before-resync-source handler returned %d, "
+	if (!test_bit(B_RS_H_DONE, &mdev->flags)) {
+		if (side == C_SYNC_TARGET) {
+			/* Since application IO was locked out during C_WF_BITMAP_T and
+			   C_WF_SYNC_UUID we are still unmodified. Before going to C_SYNC_TARGET
+			   we check that we might make the data inconsistent. */
+			r = drbd_khelper(mdev, "before-resync-target");
+			r = (r >> 8) & 0xff;
+			if (r > 0) {
+				dev_info(DEV, "before-resync-target handler returned %d, "
 					 "dropping connection.\n", r);
-				drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
+				conn_request_state(mdev->tconn, NS(conn, C_DISCONNECTING), CS_HARD);
 				return;
 			}
+		} else /* C_SYNC_SOURCE */ {
+			r = drbd_khelper(mdev, "before-resync-source");
+			r = (r >> 8) & 0xff;
+			if (r > 0) {
+				if (r == 3) {
+					dev_info(DEV, "before-resync-source handler returned %d, "
+						 "ignoring. Old userland tools?", r);
+				} else {
+					dev_info(DEV, "before-resync-source handler returned %d, "
+						 "dropping connection.\n", r);
+					conn_request_state(mdev->tconn, NS(conn, C_DISCONNECTING), CS_HARD);
+					return;
+				}
+			}
 		}
 	}
 
-	drbd_state_lock(mdev);
+	if (current == mdev->tconn->worker.task) {
+		/* The worker should not sleep waiting for state_mutex,
+		   that can take long */
+		if (!mutex_trylock(mdev->state_mutex)) {
+			set_bit(B_RS_H_DONE, &mdev->flags);
+			mdev->start_resync_timer.expires = jiffies + HZ/5;
+			add_timer(&mdev->start_resync_timer);
+			return;
+		}
+	} else {
+		mutex_lock(mdev->state_mutex);
+	}
+	clear_bit(B_RS_H_DONE, &mdev->flags);
+
 	write_lock_irq(&global_state_lock);
 	if (!get_ldev_if_state(mdev, D_NEGOTIATING)) {
 		write_unlock_irq(&global_state_lock);
-		drbd_state_unlock(mdev);
+		mutex_unlock(mdev->state_mutex);
 		return;
 	}
 
-	ns.i = mdev->state.i;
+	ns = drbd_read_state(mdev);
 
 	ns.aftr_isp = !_drbd_may_sync_now(mdev);
 
@@ -1549,7 +1670,7 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
 		ns.pdsk = D_INCONSISTENT;
 
 	r = __drbd_set_state(mdev, ns, CS_VERBOSE, NULL);
-	ns = mdev->state;
+	ns = drbd_read_state(mdev);
 
 	if (ns.conn < C_CONNECTED)
 		r = SS_UNKNOWN_ERROR;
@@ -1575,6 +1696,10 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
 	write_unlock_irq(&global_state_lock);
 
 	if (r == SS_SUCCESS) {
+		/* reset rs_last_bcast when a resync or verify is started,
+		 * to deal with potential jiffies wrap. */
+		mdev->rs_last_bcast = jiffies - HZ;
+
 		dev_info(DEV, "Began resync as %s (will sync %lu KB [%lu bits set]).\n",
 		     drbd_conn_str(ns.conn),
 		     (unsigned long) mdev->rs_total << (BM_BLOCK_SHIFT-10),
@@ -1589,10 +1714,10 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
 		 * drbd_resync_finished from here in that case.
 		 * We drbd_gen_and_send_sync_uuid here for protocol < 96,
 		 * and from after_state_ch otherwise. */
-		if (side == C_SYNC_SOURCE && mdev->agreed_pro_version < 96)
+		if (side == C_SYNC_SOURCE && mdev->tconn->agreed_pro_version < 96)
 			drbd_gen_and_send_sync_uuid(mdev);
 
-		if (mdev->agreed_pro_version < 95 && mdev->rs_total == 0) {
+		if (mdev->tconn->agreed_pro_version < 95 && mdev->rs_total == 0) {
 			/* This still has a race (about when exactly the peers
 			 * detect connection loss) that can lead to a full sync
 			 * on next handshake. In 8.3.9 we fixed this with explicit
@@ -1603,10 +1728,16 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
 			 * detect connection loss, then waiting for a ping
 			 * response (implicit in drbd_resync_finished) reduces
 			 * the race considerably, but does not solve it. */
-			if (side == C_SYNC_SOURCE)
-				schedule_timeout_interruptible(
-					mdev->net_conf->ping_int * HZ +
-					mdev->net_conf->ping_timeo*HZ/9);
+			if (side == C_SYNC_SOURCE) {
+				struct net_conf *nc;
+				int timeo;
+
+				rcu_read_lock();
+				nc = rcu_dereference(mdev->tconn->net_conf);
+				timeo = nc->ping_int * HZ + nc->ping_timeo * HZ / 9;
+				rcu_read_unlock();
+				schedule_timeout_interruptible(timeo);
+			}
 			drbd_resync_finished(mdev);
 		}
 
@@ -1621,114 +1752,180 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
 		drbd_md_sync(mdev);
 	}
 	put_ldev(mdev);
-	drbd_state_unlock(mdev);
+	mutex_unlock(mdev->state_mutex);
 }
 
-int drbd_worker(struct drbd_thread *thi)
+/* If the resource already closed the current epoch, but we did not
+ * (because we have not yet seen new requests), we should send the
+ * corresponding barrier now.  Must be checked within the same spinlock
+ * that is used to check for new requests. */
+bool need_to_send_barrier(struct drbd_tconn *connection)
 {
-	struct drbd_conf *mdev = thi->mdev;
-	struct drbd_work *w = NULL;
-	LIST_HEAD(work_list);
-	int intr = 0, i;
+	if (!connection->send.seen_any_write_yet)
+		return false;
+
+	/* Skip barriers that do not contain any writes.
+	 * This may happen during AHEAD mode. */
+	if (!connection->send.current_epoch_writes)
+		return false;
+
+	/* ->req_lock is held when requests are queued on
+	 * connection->sender_work, and put into ->transfer_log.
+	 * It is also held when ->current_tle_nr is increased.
+	 * So either there are already new requests queued,
+	 * and corresponding barriers will be send there.
+	 * Or nothing new is queued yet, so the difference will be 1.
+	 */
+	if (atomic_read(&connection->current_tle_nr) !=
+	    connection->send.current_epoch_nr + 1)
+		return false;
+
+	return true;
+}
+
+bool dequeue_work_batch(struct drbd_work_queue *queue, struct list_head *work_list)
+{
+	spin_lock_irq(&queue->q_lock);
+	list_splice_init(&queue->q, work_list);
+	spin_unlock_irq(&queue->q_lock);
+	return !list_empty(work_list);
+}
 
-	sprintf(current->comm, "drbd%d_worker", mdev_to_minor(mdev));
+bool dequeue_work_item(struct drbd_work_queue *queue, struct list_head *work_list)
+{
+	spin_lock_irq(&queue->q_lock);
+	if (!list_empty(&queue->q))
+		list_move(queue->q.next, work_list);
+	spin_unlock_irq(&queue->q_lock);
+	return !list_empty(work_list);
+}
 
-	while (get_t_state(thi) == Running) {
-		drbd_thread_current_set_cpu(mdev);
+void wait_for_work(struct drbd_tconn *connection, struct list_head *work_list)
+{
+	DEFINE_WAIT(wait);
+	struct net_conf *nc;
+	int uncork, cork;
 
-		if (down_trylock(&mdev->data.work.s)) {
-			mutex_lock(&mdev->data.mutex);
-			if (mdev->data.socket && !mdev->net_conf->no_cork)
-				drbd_tcp_uncork(mdev->data.socket);
-			mutex_unlock(&mdev->data.mutex);
+	dequeue_work_item(&connection->sender_work, work_list);
+	if (!list_empty(work_list))
+		return;
 
-			intr = down_interruptible(&mdev->data.work.s);
+	/* Still nothing to do?
+	 * Maybe we still need to close the current epoch,
+	 * even if no new requests are queued yet.
+	 *
+	 * Also, poke TCP, just in case.
+	 * Then wait for new work (or signal). */
+	rcu_read_lock();
+	nc = rcu_dereference(connection->net_conf);
+	uncork = nc ? nc->tcp_cork : 0;
+	rcu_read_unlock();
+	if (uncork) {
+		mutex_lock(&connection->data.mutex);
+		if (connection->data.socket)
+			drbd_tcp_uncork(connection->data.socket);
+		mutex_unlock(&connection->data.mutex);
+	}
 
-			mutex_lock(&mdev->data.mutex);
-			if (mdev->data.socket  && !mdev->net_conf->no_cork)
-				drbd_tcp_cork(mdev->data.socket);
-			mutex_unlock(&mdev->data.mutex);
+	for (;;) {
+		int send_barrier;
+		prepare_to_wait(&connection->sender_work.q_wait, &wait, TASK_INTERRUPTIBLE);
+		spin_lock_irq(&connection->req_lock);
+		spin_lock(&connection->sender_work.q_lock);	/* FIXME get rid of this one? */
+		/* dequeue single item only,
+		 * we still use drbd_queue_work_front() in some places */
+		if (!list_empty(&connection->sender_work.q))
+			list_move(connection->sender_work.q.next, work_list);
+		spin_unlock(&connection->sender_work.q_lock);	/* FIXME get rid of this one? */
+		if (!list_empty(work_list) || signal_pending(current)) {
+			spin_unlock_irq(&connection->req_lock);
+			break;
 		}
+		send_barrier = need_to_send_barrier(connection);
+		spin_unlock_irq(&connection->req_lock);
+		if (send_barrier) {
+			drbd_send_barrier(connection);
+			connection->send.current_epoch_nr++;
+		}
+		schedule();
+		/* may be woken up for other things but new work, too,
+		 * e.g. if the current epoch got closed.
+		 * In which case we send the barrier above. */
+	}
+	finish_wait(&connection->sender_work.q_wait, &wait);
+
+	/* someone may have changed the config while we have been waiting above. */
+	rcu_read_lock();
+	nc = rcu_dereference(connection->net_conf);
+	cork = nc ? nc->tcp_cork : 0;
+	rcu_read_unlock();
+	mutex_lock(&connection->data.mutex);
+	if (connection->data.socket) {
+		if (cork)
+			drbd_tcp_cork(connection->data.socket);
+		else if (!uncork)
+			drbd_tcp_uncork(connection->data.socket);
+	}
+	mutex_unlock(&connection->data.mutex);
+}
 
-		if (intr) {
-			D_ASSERT(intr == -EINTR);
+int drbd_worker(struct drbd_thread *thi)
+{
+	struct drbd_tconn *tconn = thi->tconn;
+	struct drbd_work *w = NULL;
+	struct drbd_conf *mdev;
+	LIST_HEAD(work_list);
+	int vnr;
+
+	while (get_t_state(thi) == RUNNING) {
+		drbd_thread_current_set_cpu(thi);
+
+		/* as long as we use drbd_queue_work_front(),
+		 * we may only dequeue single work items here, not batches. */
+		if (list_empty(&work_list))
+			wait_for_work(tconn, &work_list);
+
+		if (signal_pending(current)) {
 			flush_signals(current);
-			ERR_IF (get_t_state(thi) == Running)
+			if (get_t_state(thi) == RUNNING) {
+				conn_warn(tconn, "Worker got an unexpected signal\n");
 				continue;
+			}
 			break;
 		}
 
-		if (get_t_state(thi) != Running)
+		if (get_t_state(thi) != RUNNING)
 			break;
-		/* With this break, we have done a down() but not consumed
-		   the entry from the list. The cleanup code takes care of
-		   this...   */
-
-		w = NULL;
-		spin_lock_irq(&mdev->data.work.q_lock);
-		ERR_IF(list_empty(&mdev->data.work.q)) {
-			/* something terribly wrong in our logic.
-			 * we were able to down() the semaphore,
-			 * but the list is empty... doh.
-			 *
-			 * what is the best thing to do now?
-			 * try again from scratch, restarting the receiver,
-			 * asender, whatnot? could break even more ugly,
-			 * e.g. when we are primary, but no good local data.
-			 *
-			 * I'll try to get away just starting over this loop.
-			 */
-			spin_unlock_irq(&mdev->data.work.q_lock);
-			continue;
-		}
-		w = list_entry(mdev->data.work.q.next, struct drbd_work, list);
-		list_del_init(&w->list);
-		spin_unlock_irq(&mdev->data.work.q_lock);
-
-		if (!w->cb(mdev, w, mdev->state.conn < C_CONNECTED)) {
-			/* dev_warn(DEV, "worker: a callback failed! \n"); */
-			if (mdev->state.conn >= C_CONNECTED)
-				drbd_force_state(mdev,
-						NS(conn, C_NETWORK_FAILURE));
+
+		while (!list_empty(&work_list)) {
+			w = list_first_entry(&work_list, struct drbd_work, list);
+			list_del_init(&w->list);
+			if (w->cb(w, tconn->cstate < C_WF_REPORT_PARAMS) == 0)
+				continue;
+			if (tconn->cstate >= C_WF_REPORT_PARAMS)
+				conn_request_state(tconn, NS(conn, C_NETWORK_FAILURE), CS_HARD);
 		}
 	}
-	D_ASSERT(test_bit(DEVICE_DYING, &mdev->flags));
-	D_ASSERT(test_bit(CONFIG_PENDING, &mdev->flags));
-
-	spin_lock_irq(&mdev->data.work.q_lock);
-	i = 0;
-	while (!list_empty(&mdev->data.work.q)) {
-		list_splice_init(&mdev->data.work.q, &work_list);
-		spin_unlock_irq(&mdev->data.work.q_lock);
 
+	do {
 		while (!list_empty(&work_list)) {
-			w = list_entry(work_list.next, struct drbd_work, list);
+			w = list_first_entry(&work_list, struct drbd_work, list);
 			list_del_init(&w->list);
-			w->cb(mdev, w, 1);
-			i++; /* dead debugging code */
+			w->cb(w, 1);
 		}
-
-		spin_lock_irq(&mdev->data.work.q_lock);
+		dequeue_work_batch(&tconn->sender_work, &work_list);
+	} while (!list_empty(&work_list));
+
+	rcu_read_lock();
+	idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+		D_ASSERT(mdev->state.disk == D_DISKLESS && mdev->state.conn == C_STANDALONE);
+		kref_get(&mdev->kref);
+		rcu_read_unlock();
+		drbd_mdev_cleanup(mdev);
+		kref_put(&mdev->kref, &drbd_minor_destroy);
+		rcu_read_lock();
 	}
-	sema_init(&mdev->data.work.s, 0);
-	/* DANGEROUS race: if someone did queue his work within the spinlock,
-	 * but up() ed outside the spinlock, we could get an up() on the
-	 * semaphore without corresponding list entry.
-	 * So don't do that.
-	 */
-	spin_unlock_irq(&mdev->data.work.q_lock);
-
-	D_ASSERT(mdev->state.disk == D_DISKLESS && mdev->state.conn == C_STANDALONE);
-	/* _drbd_set_state only uses stop_nowait.
-	 * wait here for the Exiting receiver. */
-	drbd_thread_stop(&mdev->receiver);
-	drbd_mdev_cleanup(mdev);
-
-	dev_info(DEV, "worker terminated\n");
-
-	clear_bit(DEVICE_DYING, &mdev->flags);
-	clear_bit(CONFIG_PENDING, &mdev->flags);
-	wake_up(&mdev->state_wait);
+	rcu_read_unlock();
 
 	return 0;
 }
diff --git a/drivers/block/drbd/drbd_wrappers.h b/drivers/block/drbd/drbd_wrappers.h
index 151f1a3..328f18e 100644
--- a/drivers/block/drbd/drbd_wrappers.h
+++ b/drivers/block/drbd/drbd_wrappers.h
@@ -3,6 +3,7 @@
 
 #include <linux/ctype.h>
 #include <linux/mm.h>
+#include "drbd_int.h"
 
 /* see get_sb_bdev and bd_claim */
 extern char *drbd_sec_holder;
@@ -20,8 +21,8 @@ static inline void drbd_set_my_capacity(struct drbd_conf *mdev,
 
 /* bi_end_io handlers */
 extern void drbd_md_io_complete(struct bio *bio, int error);
-extern void drbd_endio_sec(struct bio *bio, int error);
-extern void drbd_endio_pri(struct bio *bio, int error);
+extern void drbd_peer_request_endio(struct bio *bio, int error);
+extern void drbd_request_endio(struct bio *bio, int error);
 
 /*
  * used to submit our private bio
@@ -45,12 +46,6 @@ static inline void drbd_generic_make_request(struct drbd_conf *mdev,
 		generic_make_request(bio);
 }
 
-static inline int drbd_crypto_is_hash(struct crypto_tfm *tfm)
-{
-        return (crypto_tfm_alg_type(tfm) & CRYPTO_ALG_TYPE_HASH_MASK)
-                == CRYPTO_ALG_TYPE_HASH;
-}
-
 #ifndef __CHECKER__
 # undef __cond_lock
 # define __cond_lock(x,c) (c)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 54046e5..ae12512 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -463,6 +463,7 @@ out:
  */
 static void loop_add_bio(struct loop_device *lo, struct bio *bio)
 {
+	lo->lo_bio_count++;
 	bio_list_add(&lo->lo_bio_list, bio);
 }
 
@@ -471,6 +472,7 @@ static void loop_add_bio(struct loop_device *lo, struct bio *bio)
  */
 static struct bio *loop_get_bio(struct loop_device *lo)
 {
+	lo->lo_bio_count--;
 	return bio_list_pop(&lo->lo_bio_list);
 }
 
@@ -489,6 +491,10 @@ static void loop_make_request(struct request_queue *q, struct bio *old_bio)
 		goto out;
 	if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY)))
 		goto out;
+	if (lo->lo_bio_count >= q->nr_congestion_on)
+		wait_event_lock_irq(lo->lo_req_wait,
+				    lo->lo_bio_count < q->nr_congestion_off,
+				    lo->lo_lock);
 	loop_add_bio(lo, old_bio);
 	wake_up(&lo->lo_event);
 	spin_unlock_irq(&lo->lo_lock);
@@ -546,6 +552,8 @@ static int loop_thread(void *data)
 			continue;
 		spin_lock_irq(&lo->lo_lock);
 		bio = loop_get_bio(lo);
+		if (lo->lo_bio_count < lo->lo_queue->nr_congestion_off)
+			wake_up(&lo->lo_req_wait);
 		spin_unlock_irq(&lo->lo_lock);
 
 		BUG_ON(!bio);
@@ -873,6 +881,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 	lo->transfer = transfer_none;
 	lo->ioctl = NULL;
 	lo->lo_sizelimit = 0;
+	lo->lo_bio_count = 0;
 	lo->old_gfp_mask = mapping_gfp_mask(mapping);
 	mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
 
@@ -1673,6 +1682,7 @@ static int loop_add(struct loop_device **l, int i)
 	lo->lo_number		= i;
 	lo->lo_thread		= NULL;
 	init_waitqueue_head(&lo->lo_event);
+	init_waitqueue_head(&lo->lo_req_wait);
 	spin_lock_init(&lo->lo_lock);
 	disk->major		= LOOP_MAJOR;
 	disk->first_minor	= i << part_shift;
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index bb3d9be..8f56d37 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -70,6 +70,14 @@
 #define RBD_IMAGE_ID_LEN_MAX	64
 #define RBD_OBJ_PREFIX_LEN_MAX	64
 
+/* Feature bits */
+
+#define RBD_FEATURE_LAYERING      1
+
+/* Features supported by this (client software) implementation. */
+
+#define RBD_FEATURES_ALL          (0)
+
 /*
  * An RBD device name will be "rbd#", where the "rbd" comes from
  * RBD_DRV_NAME above, and # is a unique integer identifier.
@@ -268,7 +276,8 @@ static void rbd_put_dev(struct rbd_device *rbd_dev)
 	put_device(&rbd_dev->dev);
 }
 
-static int rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver);
+static int rbd_dev_refresh(struct rbd_device *rbd_dev, u64 *hver);
+static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev, u64 *hver);
 
 static int rbd_open(struct block_device *bdev, fmode_t mode)
 {
@@ -1304,7 +1313,7 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data)
 	dout("rbd_watch_cb %s notify_id=%llu opcode=%u\n",
 		rbd_dev->header_name, (unsigned long long) notify_id,
 		(unsigned int) opcode);
-	rc = rbd_refresh_header(rbd_dev, &hver);
+	rc = rbd_dev_refresh(rbd_dev, &hver);
 	if (rc)
 		pr_warning(RBD_DRV_NAME "%d got notification but failed to "
 			   " update snaps: %d\n", rbd_dev->major, rc);
@@ -1716,10 +1725,23 @@ static void __rbd_remove_all_snaps(struct rbd_device *rbd_dev)
 		__rbd_remove_snap_dev(snap);
 }
 
+static void rbd_update_mapping_size(struct rbd_device *rbd_dev)
+{
+	sector_t size;
+
+	if (rbd_dev->mapping.snap_id != CEPH_NOSNAP)
+		return;
+
+	size = (sector_t) rbd_dev->header.image_size / SECTOR_SIZE;
+	dout("setting size to %llu sectors", (unsigned long long) size);
+	rbd_dev->mapping.size = (u64) size;
+	set_capacity(rbd_dev->disk, size);
+}
+
 /*
  * only read the first part of the ondisk header, without the snaps info
  */
-static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver)
+static int rbd_dev_v1_refresh(struct rbd_device *rbd_dev, u64 *hver)
 {
 	int ret;
 	struct rbd_image_header h;
@@ -1730,17 +1752,9 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver)
 
 	down_write(&rbd_dev->header_rwsem);
 
-	/* resized? */
-	if (rbd_dev->mapping.snap_id == CEPH_NOSNAP) {
-		sector_t size = (sector_t) h.image_size / SECTOR_SIZE;
-
-		if (size != (sector_t) rbd_dev->mapping.size) {
-			dout("setting size to %llu sectors",
-				(unsigned long long) size);
-			rbd_dev->mapping.size = (u64) size;
-			set_capacity(rbd_dev->disk, size);
-		}
-	}
+	/* Update image size, and check for resize of mapped image */
+	rbd_dev->header.image_size = h.image_size;
+	rbd_update_mapping_size(rbd_dev);
 
 	/* rbd_dev->header.object_prefix shouldn't change */
 	kfree(rbd_dev->header.snap_sizes);
@@ -1768,12 +1782,16 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver)
 	return ret;
 }
 
-static int rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver)
+static int rbd_dev_refresh(struct rbd_device *rbd_dev, u64 *hver)
 {
 	int ret;
 
+	rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
 	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
-	ret = __rbd_refresh_header(rbd_dev, hver);
+	if (rbd_dev->image_format == 1)
+		ret = rbd_dev_v1_refresh(rbd_dev, hver);
+	else
+		ret = rbd_dev_v2_refresh(rbd_dev, hver);
 	mutex_unlock(&ctl_mutex);
 
 	return ret;
@@ -1933,7 +1951,7 @@ static ssize_t rbd_image_refresh(struct device *dev,
 	struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
 	int ret;
 
-	ret = rbd_refresh_header(rbd_dev, NULL);
+	ret = rbd_dev_refresh(rbd_dev, NULL);
 
 	return ret < 0 ? ret : size;
 }
@@ -2216,6 +2234,7 @@ static int _rbd_dev_v2_snap_features(struct rbd_device *rbd_dev, u64 snap_id,
 		__le64 features;
 		__le64 incompat;
 	} features_buf = { 0 };
+	u64 incompat;
 	int ret;
 
 	ret = rbd_req_sync_exec(rbd_dev, rbd_dev->header_name,
@@ -2226,6 +2245,11 @@ static int _rbd_dev_v2_snap_features(struct rbd_device *rbd_dev, u64 snap_id,
 	dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret);
 	if (ret < 0)
 		return ret;
+
+	incompat = le64_to_cpu(features_buf.incompat);
+	if (incompat & ~RBD_FEATURES_ALL)
+		return -ENOTSUPP;
+
 	*snap_features = le64_to_cpu(features_buf.features);
 
 	dout("  snap_id 0x%016llx features = 0x%016llx incompat = 0x%016llx\n",
@@ -2397,6 +2421,41 @@ static char *rbd_dev_snap_info(struct rbd_device *rbd_dev, u32 which,
 	return ERR_PTR(-EINVAL);
 }
 
+static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev, u64 *hver)
+{
+	int ret;
+	__u8 obj_order;
+
+	down_write(&rbd_dev->header_rwsem);
+
+	/* Grab old order first, to see if it changes */
+
+	obj_order = rbd_dev->header.obj_order,
+	ret = rbd_dev_v2_image_size(rbd_dev);
+	if (ret)
+		goto out;
+	if (rbd_dev->header.obj_order != obj_order) {
+		ret = -EIO;
+		goto out;
+	}
+	rbd_update_mapping_size(rbd_dev);
+
+	ret = rbd_dev_v2_snap_context(rbd_dev, hver);
+	dout("rbd_dev_v2_snap_context returned %d\n", ret);
+	if (ret)
+		goto out;
+	ret = rbd_dev_snaps_update(rbd_dev);
+	dout("rbd_dev_snaps_update returned %d\n", ret);
+	if (ret)
+		goto out;
+	ret = rbd_dev_snaps_register(rbd_dev);
+	dout("rbd_dev_snaps_register returned %d\n", ret);
+out:
+	up_write(&rbd_dev->header_rwsem);
+
+	return ret;
+}
+
 /*
  * Scan the rbd device's current snapshot list and compare it to the
  * newly-received snapshot context.  Remove any existing snapshots
@@ -2559,7 +2618,7 @@ static int rbd_init_watch_dev(struct rbd_device *rbd_dev)
 	do {
 		ret = rbd_req_sync_watch(rbd_dev);
 		if (ret == -ERANGE) {
-			rc = rbd_refresh_header(rbd_dev, NULL);
+			rc = rbd_dev_refresh(rbd_dev, NULL);
 			if (rc < 0)
 				return rc;
 		}
@@ -2932,7 +2991,7 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
 	if (ret < 0)
 		goto out_err;
 
-	/* Get the features for the image */
+	/* Get the and check features for the image */
 
 	ret = rbd_dev_v2_features(rbd_dev);
 	if (ret < 0)
@@ -2955,7 +3014,7 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
 	dout("discovered version 2 image, header name is %s\n",
 		rbd_dev->header_name);
 
-	return -ENOTSUPP;
+	return 0;
 out_err:
 	kfree(rbd_dev->header_name);
 	rbd_dev->header_name = NULL;
@@ -3040,7 +3099,6 @@ static ssize_t rbd_add(struct bus_type *bus,
 	rc = rbd_dev_probe(rbd_dev);
 	if (rc < 0)
 		goto err_out_client;
-	rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
 
 	/* no need to lock here, as rbd_dev is not registered yet */
 	rc = rbd_dev_snaps_update(rbd_dev);
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 3f4bfc8..9959d4c 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -492,7 +492,7 @@ done:
 static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
 {
 	u16 buf_len = 0;
-	int ret, buf_block_len, blksz;
+	int ret, num_blocks, blksz;
 	struct sk_buff *skb = NULL;
 	u32 type;
 	u8 *payload = NULL;
@@ -514,18 +514,17 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
 	}
 
 	blksz = SDIO_BLOCK_SIZE;
-	buf_block_len = (buf_len + blksz - 1) / blksz;
+	num_blocks = DIV_ROUND_UP(buf_len, blksz);
 
 	if (buf_len <= SDIO_HEADER_LEN
-			|| (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
+	    || (num_blocks * blksz) > ALLOC_BUF_SIZE) {
 		BT_ERR("invalid packet length: %d", buf_len);
 		ret = -EINVAL;
 		goto exit;
 	}
 
 	/* Allocate buffer */
-	skb = bt_skb_alloc(buf_block_len * blksz + BTSDIO_DMA_ALIGN,
-								GFP_ATOMIC);
+	skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC);
 	if (skb == NULL) {
 		BT_ERR("No free skb");
 		goto exit;
@@ -541,7 +540,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
 	payload = skb->data;
 
 	ret = sdio_readsb(card->func, payload, card->ioport,
-			  buf_block_len * blksz);
+			  num_blocks * blksz);
 	if (ret < 0) {
 		BT_ERR("readsb failed: %d", ret);
 		ret = -EIO;
@@ -553,7 +552,16 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
 	 */
 
 	buf_len = payload[0];
-	buf_len |= (u16) payload[1] << 8;
+	buf_len |= payload[1] << 8;
+	buf_len |= payload[2] << 16;
+
+	if (buf_len > blksz * num_blocks) {
+		BT_ERR("Skip incorrect packet: hdrlen %d buffer %d",
+		       buf_len, blksz * num_blocks);
+		ret = -EIO;
+		goto exit;
+	}
+
 	type = payload[3];
 
 	switch (type) {
@@ -589,8 +597,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
 
 	default:
 		BT_ERR("Unknown packet type:%d", type);
-		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload,
-						blksz * buf_block_len);
+		BT_ERR("hex: %*ph", blksz * num_blocks, payload);
 
 		kfree_skb(skb);
 		skb = NULL;
@@ -849,8 +856,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
 		if (ret < 0) {
 			i++;
 			BT_ERR("i=%d writesb failed: %d", i, ret);
-			print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
-						payload, nb);
+			BT_ERR("hex: %*ph", nb, payload);
 			ret = -EIO;
 			if (i > MAX_WRITE_IOMEM_RETRY)
 				goto exit;
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index ee82f2f..a1d4ede 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -96,6 +96,7 @@ static struct usb_device_id btusb_table[] = {
 	{ USB_DEVICE(0x0c10, 0x0000) },
 
 	/* Broadcom BCM20702A0 */
+	{ USB_DEVICE(0x0b05, 0x17b5) },
 	{ USB_DEVICE(0x04ca, 0x2003) },
 	{ USB_DEVICE(0x0489, 0xe042) },
 	{ USB_DEVICE(0x413c, 0x8197) },
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index c8abce3..ed0fade 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -270,15 +270,10 @@ static int hci_uart_send_frame(struct sk_buff *skb)
  */
 static int hci_uart_tty_open(struct tty_struct *tty)
 {
-	struct hci_uart *hu = (void *) tty->disc_data;
+	struct hci_uart *hu;
 
 	BT_DBG("tty %p", tty);
 
-	/* FIXME: This btw is bogus, nothing requires the old ldisc to clear
-	   the pointer */
-	if (hu)
-		return -EEXIST;
-
 	/* Error if the tty has no write op instead of leaving an exploitable
 	   hole */
 	if (tty->ops->write == NULL)
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index fd79351..4784935 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -249,7 +249,7 @@ static const struct agp_bridge_driver ali_m1541_bridge = {
 };
 
 
-static struct agp_device_ids ali_agp_device_ids[] __devinitdata =
+static struct agp_device_ids ali_agp_device_ids[] =
 {
 	{
 		.device_id	= PCI_DEVICE_ID_AL_M1541,
@@ -374,7 +374,7 @@ found:
 	return agp_add_bridge(bridge);
 }
 
-static void __devexit agp_ali_remove(struct pci_dev *pdev)
+static void agp_ali_remove(struct pci_dev *pdev)
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index f7e8878..1b21011 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -388,7 +388,7 @@ static const struct agp_bridge_driver amd_irongate_driver = {
 	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_device_ids amd_agp_device_ids[] __devinitdata =
+static struct agp_device_ids amd_agp_device_ids[] =
 {
 	{
 		.device_id	= PCI_DEVICE_ID_AMD_FE_GATE_7006,
@@ -480,7 +480,7 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
 	return agp_add_bridge(bridge);
 }
 
-static void __devexit agp_amdk7_remove(struct pci_dev *pdev)
+static void agp_amdk7_remove(struct pci_dev *pdev)
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 444f8b6..061d462 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -579,7 +579,7 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev,
 	return 0;
 }
 
-static void __devexit agp_amd64_remove(struct pci_dev *pdev)
+static void agp_amd64_remove(struct pci_dev *pdev)
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index dc30e22..ed04335 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -445,7 +445,7 @@ static const struct agp_bridge_driver ati_generic_bridge = {
 };
 
 
-static struct agp_device_ids ati_agp_device_ids[] __devinitdata =
+static struct agp_device_ids ati_agp_device_ids[] =
 {
 	{
 		.device_id	= PCI_DEVICE_ID_ATI_RS100,
@@ -533,7 +533,7 @@ found:
 	return agp_add_bridge(bridge);
 }
 
-static void __devexit agp_ati_remove(struct pci_dev *pdev)
+static void agp_ati_remove(struct pci_dev *pdev)
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index d607f53..55f3e33 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -407,7 +407,7 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
 	return agp_add_bridge(bridge);
 }
 
-static void __devexit agp_efficeon_remove(struct pci_dev *pdev)
+static void agp_efficeon_remove(struct pci_dev *pdev)
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index 75b763c..d328b66 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -611,7 +611,7 @@ static int __devinit agp_intel_i460_probe(struct pci_dev *pdev,
 	return agp_add_bridge(bridge);
 }
 
-static void __devexit agp_intel_i460_remove(struct pci_dev *pdev)
+static void agp_intel_i460_remove(struct pci_dev *pdev)
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index b130df0..f3a8f52 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -819,7 +819,7 @@ found_gmch:
 	return err;
 }
 
-static void __devexit agp_intel_remove(struct pci_dev *pdev)
+static void agp_intel_remove(struct pci_dev *pdev)
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h
index 6ec0fff..1042c1b 100644
--- a/drivers/char/agp/intel-agp.h
+++ b/drivers/char/agp/intel-agp.h
@@ -62,12 +62,6 @@
 #define I810_PTE_LOCAL		0x00000002
 #define I810_PTE_VALID		0x00000001
 #define I830_PTE_SYSTEM_CACHED  0x00000006
-/* GT PTE cache control fields */
-#define GEN6_PTE_UNCACHED	0x00000002
-#define HSW_PTE_UNCACHED	0x00000000
-#define GEN6_PTE_LLC		0x00000004
-#define GEN6_PTE_LLC_MLC	0x00000006
-#define GEN6_PTE_GFDT		0x00000008
 
 #define I810_SMRAM_MISCC	0x70
 #define I810_GFX_MEM_WIN_SIZE	0x00010000
@@ -97,7 +91,6 @@
 #define G4x_GMCH_SIZE_VT_2M	(G4x_GMCH_SIZE_2M | G4x_GMCH_SIZE_VT_EN)
 
 #define GFX_FLSH_CNTL		0x2170 /* 915+ */
-#define GFX_FLSH_CNTL_VLV	0x101008
 
 #define I810_DRAM_CTL		0x3000
 #define I810_DRAM_ROW_0		0x00000001
@@ -148,29 +141,6 @@
 #define INTEL_I7505_AGPCTRL	0x70
 #define INTEL_I7505_MCHCFG	0x50
 
-#define SNB_GMCH_CTRL	0x50
-#define SNB_GMCH_GMS_STOLEN_MASK	0xF8
-#define SNB_GMCH_GMS_STOLEN_32M		(1 << 3)
-#define SNB_GMCH_GMS_STOLEN_64M		(2 << 3)
-#define SNB_GMCH_GMS_STOLEN_96M		(3 << 3)
-#define SNB_GMCH_GMS_STOLEN_128M	(4 << 3)
-#define SNB_GMCH_GMS_STOLEN_160M	(5 << 3)
-#define SNB_GMCH_GMS_STOLEN_192M	(6 << 3)
-#define SNB_GMCH_GMS_STOLEN_224M	(7 << 3)
-#define SNB_GMCH_GMS_STOLEN_256M	(8 << 3)
-#define SNB_GMCH_GMS_STOLEN_288M	(9 << 3)
-#define SNB_GMCH_GMS_STOLEN_320M	(0xa << 3)
-#define SNB_GMCH_GMS_STOLEN_352M	(0xb << 3)
-#define SNB_GMCH_GMS_STOLEN_384M	(0xc << 3)
-#define SNB_GMCH_GMS_STOLEN_416M	(0xd << 3)
-#define SNB_GMCH_GMS_STOLEN_448M	(0xe << 3)
-#define SNB_GMCH_GMS_STOLEN_480M	(0xf << 3)
-#define SNB_GMCH_GMS_STOLEN_512M	(0x10 << 3)
-#define SNB_GTT_SIZE_0M			(0 << 8)
-#define SNB_GTT_SIZE_1M			(1 << 8)
-#define SNB_GTT_SIZE_2M			(2 << 8)
-#define SNB_GTT_SIZE_MASK		(3 << 8)
-
 /* pci devices ids */
 #define PCI_DEVICE_ID_INTEL_E7221_HB	0x2588
 #define PCI_DEVICE_ID_INTEL_E7221_IG	0x258a
@@ -219,66 +189,5 @@
 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB	    0x0062
 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB    0x006a
 #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG	    0x0046
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB		0x0100  /* Desktop */
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG		0x0102
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG		0x0112
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG	0x0122
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB		0x0104  /* Mobile */
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG	0x0106
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG	0x0116
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG	0x0126
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB		0x0108  /* Server */
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG		0x010A
-#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_HB		0x0150  /* Desktop */
-#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT1_IG		0x0152
-#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT2_IG		0x0162
-#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_HB		0x0154  /* Mobile */
-#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT1_IG		0x0156
-#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT2_IG		0x0166
-#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB		0x0158  /* Server */
-#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG		0x015A
-#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG		0x016A
-#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_HB		0x0F00 /* VLV1 */
-#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG		0x0F30
-#define PCI_DEVICE_ID_INTEL_HASWELL_HB			0x0400 /* Desktop */
-#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG		0x0402
-#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG		0x0412
-#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_PLUS_IG	0x0422
-#define PCI_DEVICE_ID_INTEL_HASWELL_M_HB		0x0404 /* Mobile */
-#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG		0x0406
-#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG		0x0416
-#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_PLUS_IG	0x0426
-#define PCI_DEVICE_ID_INTEL_HASWELL_S_HB		0x0408 /* Server */
-#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG		0x040a
-#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG		0x041a
-#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_PLUS_IG	0x042a
-#define PCI_DEVICE_ID_INTEL_HASWELL_E_HB		0x0c04
-#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT1_IG	0x0C02
-#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_IG	0x0C12
-#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_PLUS_IG	0x0C22
-#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT1_IG	0x0C06
-#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_IG	0x0C16
-#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_PLUS_IG	0x0C26
-#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT1_IG	0x0C0A
-#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_IG	0x0C1A
-#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_PLUS_IG	0x0C2A
-#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT1_IG	0x0A02
-#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_IG	0x0A12
-#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_PLUS_IG	0x0A22
-#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT1_IG	0x0A06
-#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_IG	0x0A16
-#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_PLUS_IG	0x0A26
-#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT1_IG	0x0A0A
-#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_IG	0x0A1A
-#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_PLUS_IG	0x0A2A
-#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT1_IG	0x0D12
-#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_IG	0x0D22
-#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_PLUS_IG	0x0D32
-#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT1_IG	0x0D16
-#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_IG	0x0D26
-#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_PLUS_IG	0x0D36
-#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT1_IG	0x0D1A
-#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_IG	0x0D2A
-#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_PLUS_IG	0x0D3A
 
 #endif
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index 38390f7..dbd901e 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -367,62 +367,6 @@ static unsigned int intel_gtt_stolen_size(void)
 			stolen_size = 0;
 			break;
 		}
-	} else if (INTEL_GTT_GEN == 6) {
-		/*
-		 * SandyBridge has new memory control reg at 0x50.w
-		 */
-		u16 snb_gmch_ctl;
-		pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
-		switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) {
-		case SNB_GMCH_GMS_STOLEN_32M:
-			stolen_size = MB(32);
-			break;
-		case SNB_GMCH_GMS_STOLEN_64M:
-			stolen_size = MB(64);
-			break;
-		case SNB_GMCH_GMS_STOLEN_96M:
-			stolen_size = MB(96);
-			break;
-		case SNB_GMCH_GMS_STOLEN_128M:
-			stolen_size = MB(128);
-			break;
-		case SNB_GMCH_GMS_STOLEN_160M:
-			stolen_size = MB(160);
-			break;
-		case SNB_GMCH_GMS_STOLEN_192M:
-			stolen_size = MB(192);
-			break;
-		case SNB_GMCH_GMS_STOLEN_224M:
-			stolen_size = MB(224);
-			break;
-		case SNB_GMCH_GMS_STOLEN_256M:
-			stolen_size = MB(256);
-			break;
-		case SNB_GMCH_GMS_STOLEN_288M:
-			stolen_size = MB(288);
-			break;
-		case SNB_GMCH_GMS_STOLEN_320M:
-			stolen_size = MB(320);
-			break;
-		case SNB_GMCH_GMS_STOLEN_352M:
-			stolen_size = MB(352);
-			break;
-		case SNB_GMCH_GMS_STOLEN_384M:
-			stolen_size = MB(384);
-			break;
-		case SNB_GMCH_GMS_STOLEN_416M:
-			stolen_size = MB(416);
-			break;
-		case SNB_GMCH_GMS_STOLEN_448M:
-			stolen_size = MB(448);
-			break;
-		case SNB_GMCH_GMS_STOLEN_480M:
-			stolen_size = MB(480);
-			break;
-		case SNB_GMCH_GMS_STOLEN_512M:
-			stolen_size = MB(512);
-			break;
-		}
 	} else {
 		switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
 		case I855_GMCH_GMS_STOLEN_1M:
@@ -556,29 +500,9 @@ static unsigned int i965_gtt_total_entries(void)
 
 static unsigned int intel_gtt_total_entries(void)
 {
-	int size;
-
 	if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5)
 		return i965_gtt_total_entries();
-	else if (INTEL_GTT_GEN == 6) {
-		u16 snb_gmch_ctl;
-
-		pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
-		switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) {
-		default:
-		case SNB_GTT_SIZE_0M:
-			printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl);
-			size = MB(0);
-			break;
-		case SNB_GTT_SIZE_1M:
-			size = MB(1);
-			break;
-		case SNB_GTT_SIZE_2M:
-			size = MB(2);
-			break;
-		}
-		return size/4;
-	} else {
+	else {
 		/* On previous hardware, the GTT size was just what was
 		 * required to map the aperture.
 		 */
@@ -778,9 +702,6 @@ bool intel_enable_gtt(void)
 {
 	u8 __iomem *reg;
 
-	if (INTEL_GTT_GEN >= 6)
-	    return true;
-
 	if (INTEL_GTT_GEN == 2) {
 		u16 gmch_ctrl;
 
@@ -1149,85 +1070,6 @@ static void i965_write_entry(dma_addr_t addr,
 	writel(addr | pte_flags, intel_private.gtt + entry);
 }
 
-static bool gen6_check_flags(unsigned int flags)
-{
-	return true;
-}
-
-static void haswell_write_entry(dma_addr_t addr, unsigned int entry,
-				unsigned int flags)
-{
-	unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT;
-	unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT;
-	u32 pte_flags;
-
-	if (type_mask == AGP_USER_MEMORY)
-		pte_flags = HSW_PTE_UNCACHED | I810_PTE_VALID;
-	else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) {
-		pte_flags = GEN6_PTE_LLC_MLC | I810_PTE_VALID;
-		if (gfdt)
-			pte_flags |= GEN6_PTE_GFDT;
-	} else { /* set 'normal'/'cached' to LLC by default */
-		pte_flags = GEN6_PTE_LLC | I810_PTE_VALID;
-		if (gfdt)
-			pte_flags |= GEN6_PTE_GFDT;
-	}
-
-	/* gen6 has bit11-4 for physical addr bit39-32 */
-	addr |= (addr >> 28) & 0xff0;
-	writel(addr | pte_flags, intel_private.gtt + entry);
-}
-
-static void gen6_write_entry(dma_addr_t addr, unsigned int entry,
-			     unsigned int flags)
-{
-	unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT;
-	unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT;
-	u32 pte_flags;
-
-	if (type_mask == AGP_USER_MEMORY)
-		pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID;
-	else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) {
-		pte_flags = GEN6_PTE_LLC_MLC | I810_PTE_VALID;
-		if (gfdt)
-			pte_flags |= GEN6_PTE_GFDT;
-	} else { /* set 'normal'/'cached' to LLC by default */
-		pte_flags = GEN6_PTE_LLC | I810_PTE_VALID;
-		if (gfdt)
-			pte_flags |= GEN6_PTE_GFDT;
-	}
-
-	/* gen6 has bit11-4 for physical addr bit39-32 */
-	addr |= (addr >> 28) & 0xff0;
-	writel(addr | pte_flags, intel_private.gtt + entry);
-}
-
-static void valleyview_write_entry(dma_addr_t addr, unsigned int entry,
-				   unsigned int flags)
-{
-	unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT;
-	unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT;
-	u32 pte_flags;
-
-	if (type_mask == AGP_USER_MEMORY)
-		pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID;
-	else {
-		pte_flags = GEN6_PTE_LLC | I810_PTE_VALID;
-		if (gfdt)
-			pte_flags |= GEN6_PTE_GFDT;
-	}
-
-	/* gen6 has bit11-4 for physical addr bit39-32 */
-	addr |= (addr >> 28) & 0xff0;
-	writel(addr | pte_flags, intel_private.gtt + entry);
-
-	writel(1, intel_private.registers + GFX_FLSH_CNTL_VLV);
-}
-
-static void gen6_cleanup(void)
-{
-}
-
 /* Certain Gen5 chipsets require require idling the GPU before
  * unmapping anything from the GTT when VT-d is enabled.
  */
@@ -1249,41 +1091,29 @@ static inline int needs_idle_maps(void)
 
 static int i9xx_setup(void)
 {
-	u32 reg_addr;
+	u32 reg_addr, gtt_addr;
 	int size = KB(512);
 
 	pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &reg_addr);
 
 	reg_addr &= 0xfff80000;
 
-	if (INTEL_GTT_GEN >= 7)
-		size = MB(2);
-
 	intel_private.registers = ioremap(reg_addr, size);
 	if (!intel_private.registers)
 		return -ENOMEM;
 
-	if (INTEL_GTT_GEN == 3) {
-		u32 gtt_addr;
-
+	switch (INTEL_GTT_GEN) {
+	case 3:
 		pci_read_config_dword(intel_private.pcidev,
 				      I915_PTEADDR, &gtt_addr);
 		intel_private.gtt_bus_addr = gtt_addr;
-	} else {
-		u32 gtt_offset;
-
-		switch (INTEL_GTT_GEN) {
-		case 5:
-		case 6:
-		case 7:
-			gtt_offset = MB(2);
-			break;
-		case 4:
-		default:
-			gtt_offset =  KB(512);
-			break;
-		}
-		intel_private.gtt_bus_addr = reg_addr + gtt_offset;
+		break;
+	case 5:
+		intel_private.gtt_bus_addr = reg_addr + MB(2);
+		break;
+	default:
+		intel_private.gtt_bus_addr = reg_addr + KB(512);
+		break;
 	}
 
 	if (needs_idle_maps())
@@ -1395,32 +1225,6 @@ static const struct intel_gtt_driver ironlake_gtt_driver = {
 	.check_flags = i830_check_flags,
 	.chipset_flush = i9xx_chipset_flush,
 };
-static const struct intel_gtt_driver sandybridge_gtt_driver = {
-	.gen = 6,
-	.setup = i9xx_setup,
-	.cleanup = gen6_cleanup,
-	.write_entry = gen6_write_entry,
-	.dma_mask_size = 40,
-	.check_flags = gen6_check_flags,
-	.chipset_flush = i9xx_chipset_flush,
-};
-static const struct intel_gtt_driver haswell_gtt_driver = {
-	.gen = 6,
-	.setup = i9xx_setup,
-	.cleanup = gen6_cleanup,
-	.write_entry = haswell_write_entry,
-	.dma_mask_size = 40,
-	.check_flags = gen6_check_flags,
-	.chipset_flush = i9xx_chipset_flush,
-};
-static const struct intel_gtt_driver valleyview_gtt_driver = {
-	.gen = 7,
-	.setup = i9xx_setup,
-	.cleanup = gen6_cleanup,
-	.write_entry = valleyview_write_entry,
-	.dma_mask_size = 40,
-	.check_flags = gen6_check_flags,
-};
 
 /* Table to describe Intel GMCH and AGP/PCIE GART drivers.  At least one of
  * driver and gmch_driver must be non-null, and find_gmch will determine
@@ -1501,106 +1305,6 @@ static const struct intel_gtt_driver_description {
 	    "HD Graphics", &ironlake_gtt_driver },
 	{ PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
 	    "HD Graphics", &ironlake_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG,
-	    "Sandybridge", &sandybridge_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG,
-	    "Sandybridge", &sandybridge_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG,
-	    "Sandybridge", &sandybridge_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG,
-	    "Sandybridge", &sandybridge_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG,
-	    "Sandybridge", &sandybridge_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG,
-	    "Sandybridge", &sandybridge_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG,
-	    "Sandybridge", &sandybridge_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT1_IG,
-	    "Ivybridge", &sandybridge_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT2_IG,
-	    "Ivybridge", &sandybridge_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT1_IG,
-	    "Ivybridge", &sandybridge_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT2_IG,
-	    "Ivybridge", &sandybridge_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG,
-	    "Ivybridge", &sandybridge_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG,
-	    "Ivybridge", &sandybridge_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG,
-	    "ValleyView", &valleyview_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_PLUS_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_PLUS_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_PLUS_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT1_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_PLUS_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT1_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_PLUS_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT1_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_PLUS_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT1_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_PLUS_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT1_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_PLUS_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT1_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_PLUS_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT1_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_PLUS_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT1_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_PLUS_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT1_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_IG,
-	    "Haswell", &haswell_gtt_driver },
-	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_PLUS_IG,
-	    "Haswell", &haswell_gtt_driver },
 	{ 0, NULL, NULL }
 };
 
@@ -1686,7 +1390,7 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
 }
 EXPORT_SYMBOL(intel_gmch_probe);
 
-const struct intel_gtt *intel_gtt_get(void)
+struct intel_gtt *intel_gtt_get(void)
 {
 	return &intel_private.base;
 }
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index b9734a9..66e0868 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -388,7 +388,7 @@ static int __devinit agp_nvidia_probe(struct pci_dev *pdev,
 	return agp_add_bridge(bridge);
 }
 
-static void __devexit agp_nvidia_remove(struct pci_dev *pdev)
+static void agp_nvidia_remove(struct pci_dev *pdev)
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index 3a5af2f..a18791d 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -327,7 +327,7 @@ static int __devinit agp_sgi_init(void)
 	return 0;
 }
 
-static void __devexit agp_sgi_cleanup(void)
+static void agp_sgi_cleanup(void)
 {
 	kfree(sgi_tioca_agp_bridges);
 	sgi_tioca_agp_bridges = NULL;
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
index 08704ae..93d1d31 100644
--- a/drivers/char/agp/sis-agp.c
+++ b/drivers/char/agp/sis-agp.c
@@ -17,8 +17,8 @@
 #define PCI_DEVICE_ID_SI_662	0x0662
 #define PCI_DEVICE_ID_SI_671	0x0671
 
-static bool __devinitdata agp_sis_force_delay = 0;
-static int __devinitdata agp_sis_agp_spec = -1;
+static bool agp_sis_force_delay = 0;
+static int agp_sis_agp_spec = -1;
 
 static int sis_fetch_size(void)
 {
@@ -148,7 +148,7 @@ static struct agp_bridge_driver sis_driver = {
 };
 
 // chipsets that require the 'delay hack'
-static int sis_broken_chipsets[] __devinitdata = {
+static int sis_broken_chipsets[] = {
 	PCI_DEVICE_ID_SI_648,
 	PCI_DEVICE_ID_SI_746,
 	0 // terminator
@@ -211,7 +211,7 @@ static int __devinit agp_sis_probe(struct pci_dev *pdev,
 	return agp_add_bridge(bridge);
 }
 
-static void __devexit agp_sis_remove(struct pci_dev *pdev)
+static void agp_sis_remove(struct pci_dev *pdev)
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index f02f9b0..26020fb 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -518,7 +518,7 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
 	return agp_add_bridge(bridge);
 }
 
-static void __devexit agp_serverworks_remove(struct pci_dev *pdev)
+static void agp_serverworks_remove(struct pci_dev *pdev)
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index a32c492..011967a 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -557,7 +557,7 @@ const struct agp_bridge_driver u3_agp_driver = {
 	.needs_scratch_page	= true,
 };
 
-static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = {
+static struct agp_device_ids uninorth_agp_device_ids[] = {
 	{
 		.device_id	= PCI_DEVICE_ID_APPLE_UNI_N_AGP,
 		.chipset_name	= "UniNorth",
@@ -663,7 +663,7 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
 	return agp_add_bridge(bridge);
 }
 
-static void __devexit agp_uninorth_remove(struct pci_dev *pdev)
+static void agp_uninorth_remove(struct pci_dev *pdev)
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index 8bc3849..6818595 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -224,7 +224,7 @@ static const struct agp_bridge_driver via_driver = {
 	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_device_ids via_agp_device_ids[] __devinitdata =
+static struct agp_device_ids via_agp_device_ids[] =
 {
 	{
 		.device_id	= PCI_DEVICE_ID_VIA_82C597_0,
@@ -485,7 +485,7 @@ static int __devinit agp_via_probe(struct pci_dev *pdev,
 	return agp_add_bridge(bridge);
 }
 
-static void __devexit agp_via_remove(struct pci_dev *pdev)
+static void agp_via_remove(struct pci_dev *pdev)
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index dfd7876..fe6d4be 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -816,7 +816,7 @@ static unsigned long __hpet_calibrate(struct hpets *hpetp)
 
 static unsigned long hpet_calibrate(struct hpets *hpetp)
 {
-	unsigned long ret = -1;
+	unsigned long ret = ~0UL;
 	unsigned long tmp;
 
 	/*
@@ -1001,6 +1001,9 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
 		irqp = &res->data.extended_irq;
 
 		for (i = 0; i < irqp->interrupt_count; i++) {
+			if (hdp->hd_nirqs >= HPET_MAX_TIMERS)
+				break;
+
 			irq = acpi_register_gsi(NULL, irqp->interrupts[i],
 				      irqp->triggering, irqp->polarity);
 			if (irq < 0)
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index fbd9b2b..c5a0262 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -127,12 +127,12 @@ config HW_RANDOM_VIA
 	  If unsure, say Y.
 
 config HW_RANDOM_IXP4XX
-	tristate "Intel IXP4xx NPU HW Random Number Generator support"
+	tristate "Intel IXP4xx NPU HW Pseudo-Random Number Generator support"
 	depends on HW_RANDOM && ARCH_IXP4XX
 	default HW_RANDOM
 	---help---
-	  This driver provides kernel-side support for the Random
-	  Number Generator hardware found on the Intel IXP4xx NPU.
+	  This driver provides kernel-side support for the Pseudo-Random
+	  Number Generator hardware found on the Intel IXP45x/46x NPU.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called ixp4xx-rng.
@@ -216,7 +216,7 @@ config HW_RANDOM_MXC_RNGA
 
 config HW_RANDOM_NOMADIK
 	tristate "ST-Ericsson Nomadik Random Number Generator support"
-	depends on HW_RANDOM && PLAT_NOMADIK
+	depends on HW_RANDOM && ARCH_NOMADIK
 	---help---
 	  This driver provides kernel-side support for the Random Number
 	  Generator hardware found on ST-Ericsson SoCs (8815 and 8500).
diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c
index 731c904..5a4a6e7 100644
--- a/drivers/char/hw_random/atmel-rng.c
+++ b/drivers/char/hw_random/atmel-rng.c
@@ -98,7 +98,7 @@ err_enable:
 	return ret;
 }
 
-static int __devexit atmel_trng_remove(struct platform_device *pdev)
+static int atmel_trng_remove(struct platform_device *pdev)
 {
 	struct atmel_trng *trng = platform_get_drvdata(pdev);
 
diff --git a/drivers/char/hw_random/bcm63xx-rng.c b/drivers/char/hw_random/bcm63xx-rng.c
index aec6a42..ae95bcb 100644
--- a/drivers/char/hw_random/bcm63xx-rng.c
+++ b/drivers/char/hw_random/bcm63xx-rng.c
@@ -145,7 +145,7 @@ out:
 	return ret;
 }
 
-static int __devexit bcm63xx_rng_remove(struct platform_device *pdev)
+static int bcm63xx_rng_remove(struct platform_device *pdev)
 {
 	struct hwrng *rng = platform_get_drvdata(pdev);
 	struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c
index 232ba9c..bdc852e 100644
--- a/drivers/char/hw_random/exynos-rng.c
+++ b/drivers/char/hw_random/exynos-rng.c
@@ -134,7 +134,7 @@ static int __devinit exynos_rng_probe(struct platform_device *pdev)
 	return hwrng_register(&exynos_rng->rng);
 }
 
-static int __devexit exynos_rng_remove(struct platform_device *pdev)
+static int exynos_rng_remove(struct platform_device *pdev)
 {
 	struct exynos_rng *exynos_rng = platform_get_drvdata(pdev);
 
diff --git a/drivers/char/hw_random/ixp4xx-rng.c b/drivers/char/hw_random/ixp4xx-rng.c
index 263567f..beec162 100644
--- a/drivers/char/hw_random/ixp4xx-rng.c
+++ b/drivers/char/hw_random/ixp4xx-rng.c
@@ -45,6 +45,9 @@ static int __init ixp4xx_rng_init(void)
 	void __iomem * rng_base;
 	int err;
 
+	if (!cpu_is_ixp46x()) /* includes IXP455 */
+		return -ENOSYS;
+
 	rng_base = ioremap(0x70002100, 4);
 	if (!rng_base)
 		return -ENOMEM;
@@ -68,5 +71,5 @@ module_init(ixp4xx_rng_init);
 module_exit(ixp4xx_rng_exit);
 
 MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
-MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for IXP4xx");
+MODULE_DESCRIPTION("H/W Pseudo-Random Number Generator (RNG) driver for IXP45x/46x");
 MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
index ebd48f0..d68a72a 100644
--- a/drivers/char/hw_random/n2-drv.c
+++ b/drivers/char/hw_random/n2-drv.c
@@ -25,7 +25,7 @@
 #define DRV_MODULE_VERSION	"0.2"
 #define DRV_MODULE_RELDATE	"July 27, 2011"
 
-static char version[] __devinitdata =
+static char version[] =
 	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
@@ -719,7 +719,7 @@ out:
 	return err;
 }
 
-static int __devexit n2rng_remove(struct platform_device *op)
+static int n2rng_remove(struct platform_device *op)
 {
 	struct n2rng *np = dev_get_drvdata(&op->dev);
 
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index a5effd8..45e467d 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -27,8 +27,6 @@
 
 #include <asm/io.h>
 
-#include <plat/cpu.h>
-
 #define RNG_OUT_REG		0x00		/* Output register */
 #define RNG_STAT_REG		0x04		/* Status register
 							[0] = STAT_BUSY */
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c
index 3a63267..a1f7040 100644
--- a/drivers/char/hw_random/pasemi-rng.c
+++ b/drivers/char/hw_random/pasemi-rng.c
@@ -122,7 +122,7 @@ static int __devinit rng_probe(struct platform_device *ofdev)
 	return err;
 }
 
-static int __devexit rng_remove(struct platform_device *dev)
+static int rng_remove(struct platform_device *dev)
 {
 	void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv;
 
diff --git a/drivers/char/hw_random/picoxcell-rng.c b/drivers/char/hw_random/picoxcell-rng.c
index 97bd891..d4b24c1 100644
--- a/drivers/char/hw_random/picoxcell-rng.c
+++ b/drivers/char/hw_random/picoxcell-rng.c
@@ -151,7 +151,7 @@ err_enable:
 	return ret;
 }
 
-static int __devexit picoxcell_trng_remove(struct platform_device *pdev)
+static int picoxcell_trng_remove(struct platform_device *pdev)
 {
 	hwrng_unregister(&picoxcell_trng);
 	clk_disable(rng_clk);
diff --git a/drivers/char/hw_random/ppc4xx-rng.c b/drivers/char/hw_random/ppc4xx-rng.c
index c51762c..af6506a 100644
--- a/drivers/char/hw_random/ppc4xx-rng.c
+++ b/drivers/char/hw_random/ppc4xx-rng.c
@@ -111,7 +111,7 @@ static int __devinit ppc4xx_rng_probe(struct platform_device *dev)
 	return err;
 }
 
-static int __devexit ppc4xx_rng_remove(struct platform_device *dev)
+static int ppc4xx_rng_remove(struct platform_device *dev)
 {
 	void __iomem *rng_regs = (void __iomem *) ppc4xx_rng.priv;
 
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c
index f1a1618..3a1abc9 100644
--- a/drivers/char/hw_random/timeriomem-rng.c
+++ b/drivers/char/hw_random/timeriomem-rng.c
@@ -130,7 +130,7 @@ failed:
 	return ret;
 }
 
-static int __devexit timeriomem_rng_remove(struct platform_device *pdev)
+static int timeriomem_rng_remove(struct platform_device *pdev)
 {
 	del_timer_sync(&timeriomem_rng_timer);
 	hwrng_unregister(&timeriomem_rng_ops);
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index 5708299..621f595 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -119,7 +119,7 @@ static int virtrng_probe(struct virtio_device *vdev)
 	return probe_common(vdev);
 }
 
-static void __devexit virtrng_remove(struct virtio_device *vdev)
+static void virtrng_remove(struct virtio_device *vdev)
 {
 	remove_common(vdev);
 }
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index a0c84bb..053201b 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -3789,7 +3789,7 @@ static int handle_one_recv_msg(ipmi_smi_t          intf,
 
 	} else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2))
 		   && (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD)) {
-		/* It's an asyncronous event. */
+		/* It's an asynchronous event. */
 		requeue = handle_read_event_rsp(intf, msg);
 	} else {
 		/* It's a response from the local BMC. */
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 32a6c7e..cfdfecd 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -155,7 +155,7 @@ enum si_stat_indexes {
 	/* Number of watchdog pretimeouts. */
 	SI_STAT_watchdog_pretimeouts,
 
-	/* Number of asyncronous messages received. */
+	/* Number of asynchronous messages received. */
 	SI_STAT_incoming_messages,
 
 
@@ -1836,7 +1836,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
 	return rv;
 }
 
-static int __devinit hardcode_find_bmc(void)
+static int hardcode_find_bmc(void)
 {
 	int ret = -ENODEV;
 	int             i;
@@ -2023,7 +2023,7 @@ struct SPMITable {
 	s8      spmi_id[1]; /* A '\0' terminated array starts here. */
 };
 
-static int __devinit try_init_spmi(struct SPMITable *spmi)
+static int try_init_spmi(struct SPMITable *spmi)
 {
 	struct smi_info  *info;
 
@@ -2106,7 +2106,7 @@ static int __devinit try_init_spmi(struct SPMITable *spmi)
 	return 0;
 }
 
-static void __devinit spmi_find_bmc(void)
+static void spmi_find_bmc(void)
 {
 	acpi_status      status;
 	struct SPMITable *spmi;
@@ -2128,7 +2128,7 @@ static void __devinit spmi_find_bmc(void)
 	}
 }
 
-static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
+static int ipmi_pnp_probe(struct pnp_dev *dev,
 				    const struct pnp_device_id *dev_id)
 {
 	struct acpi_device *acpi_dev;
@@ -2228,7 +2228,7 @@ err_free:
 	return -EINVAL;
 }
 
-static void __devexit ipmi_pnp_remove(struct pnp_dev *dev)
+static void ipmi_pnp_remove(struct pnp_dev *dev)
 {
 	struct smi_info *info = pnp_get_drvdata(dev);
 
@@ -2258,7 +2258,7 @@ struct dmi_ipmi_data {
 	u8              slave_addr;
 };
 
-static int __devinit decode_dmi(const struct dmi_header *dm,
+static int decode_dmi(const struct dmi_header *dm,
 				struct dmi_ipmi_data *dmi)
 {
 	const u8	*data = (const u8 *)dm;
@@ -2320,7 +2320,7 @@ static int __devinit decode_dmi(const struct dmi_header *dm,
 	return 0;
 }
 
-static void __devinit try_init_dmi(struct dmi_ipmi_data *ipmi_data)
+static void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
 {
 	struct smi_info *info;
 
@@ -2388,7 +2388,7 @@ static void __devinit try_init_dmi(struct dmi_ipmi_data *ipmi_data)
 		kfree(info);
 }
 
-static void __devinit dmi_find_bmc(void)
+static void dmi_find_bmc(void)
 {
 	const struct dmi_device *dev = NULL;
 	struct dmi_ipmi_data data;
@@ -2424,7 +2424,7 @@ static void ipmi_pci_cleanup(struct smi_info *info)
 	pci_disable_device(pdev);
 }
 
-static int __devinit ipmi_pci_probe_regspacing(struct smi_info *info)
+static int ipmi_pci_probe_regspacing(struct smi_info *info)
 {
 	if (info->si_type == SI_KCS) {
 		unsigned char	status;
@@ -2456,7 +2456,7 @@ static int __devinit ipmi_pci_probe_regspacing(struct smi_info *info)
 	return DEFAULT_REGSPACING;
 }
 
-static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
+static int ipmi_pci_probe(struct pci_dev *pdev,
 				    const struct pci_device_id *ent)
 {
 	int rv;
@@ -2529,7 +2529,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
 	return 0;
 }
 
-static void __devexit ipmi_pci_remove(struct pci_dev *pdev)
+static void ipmi_pci_remove(struct pci_dev *pdev)
 {
 	struct smi_info *info = pci_get_drvdata(pdev);
 	cleanup_one_si(info);
@@ -2551,7 +2551,7 @@ static struct pci_driver ipmi_pci_driver = {
 #endif /* CONFIG_PCI */
 
 static struct of_device_id ipmi_match[];
-static int __devinit ipmi_probe(struct platform_device *dev)
+static int ipmi_probe(struct platform_device *dev)
 {
 #ifdef CONFIG_OF
 	const struct of_device_id *match;
@@ -2635,7 +2635,7 @@ static int __devinit ipmi_probe(struct platform_device *dev)
 	return 0;
 }
 
-static int __devexit ipmi_remove(struct platform_device *dev)
+static int ipmi_remove(struct platform_device *dev)
 {
 #ifdef CONFIG_OF
 	cleanup_one_si(dev_get_drvdata(&dev->dev));
@@ -3047,7 +3047,7 @@ static inline void wait_for_timer_and_thread(struct smi_info *smi_info)
 	}
 }
 
-static __devinitdata struct ipmi_default_vals
+static struct ipmi_default_vals
 {
 	int type;
 	int port;
@@ -3059,7 +3059,7 @@ static __devinitdata struct ipmi_default_vals
 	{ .port = 0 }
 };
 
-static void __devinit default_find_bmc(void)
+static void default_find_bmc(void)
 {
 	struct smi_info *info;
 	int             i;
@@ -3359,7 +3359,7 @@ static int try_smi_init(struct smi_info *new_smi)
 	return rv;
 }
 
-static int __devinit init_ipmi_si(void)
+static int init_ipmi_si(void)
 {
 	int  i;
 	char *str;
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index f74e892..e5d3e3f 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -799,7 +799,7 @@ static int mbcs_remove(struct cx_dev *dev)
 	return 0;
 }
 
-static const struct cx_device_id __devinitconst mbcs_id_table[] = {
+static const struct cx_device_id mbcs_id_table[] = {
 	{
 	 .part_num = MBCS_PART_NUM,
 	 .mfg_num = MBCS_MFG_NUM,
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 0537903..c6fa3bc 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -48,7 +48,7 @@ static inline unsigned long size_inside_page(unsigned long start,
 }
 
 #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE
-static inline int valid_phys_addr_range(unsigned long addr, size_t count)
+static inline int valid_phys_addr_range(phys_addr_t addr, size_t count)
 {
 	return addr + count <= __pa(high_memory);
 }
@@ -96,7 +96,7 @@ void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr)
 static ssize_t read_mem(struct file *file, char __user *buf,
 			size_t count, loff_t *ppos)
 {
-	unsigned long p = *ppos;
+	phys_addr_t p = *ppos;
 	ssize_t read, sz;
 	char *ptr;
 
@@ -153,7 +153,7 @@ static ssize_t read_mem(struct file *file, char __user *buf,
 static ssize_t write_mem(struct file *file, const char __user *buf,
 			 size_t count, loff_t *ppos)
 {
-	unsigned long p = *ppos;
+	phys_addr_t p = *ppos;
 	ssize_t written, sz;
 	unsigned long copied;
 	void *ptr;
@@ -226,7 +226,7 @@ int __weak phys_mem_access_prot_allowed(struct file *file,
  *
  */
 #ifdef pgprot_noncached
-static int uncached_access(struct file *file, unsigned long addr)
+static int uncached_access(struct file *file, phys_addr_t addr)
 {
 #if defined(CONFIG_IA64)
 	/*
@@ -258,7 +258,7 @@ static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 				     unsigned long size, pgprot_t vma_prot)
 {
 #ifdef pgprot_noncached
-	unsigned long offset = pfn << PAGE_SHIFT;
+	phys_addr_t offset = pfn << PAGE_SHIFT;
 
 	if (uncached_access(file, offset))
 		return pgprot_noncached(vma_prot);
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c
index b304ec0..3f79a9f 100644
--- a/drivers/char/pc8736x_gpio.c
+++ b/drivers/char/pc8736x_gpio.c
@@ -345,8 +345,7 @@ static void __exit pc8736x_gpio_cleanup(void)
 	unregister_chrdev_region(MKDEV(major,0), PC8736X_GPIO_CT);
 	release_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE);
 
-	platform_device_del(pdev);
-	platform_device_put(pdev);
+	platform_device_unregister(pdev);
 }
 
 module_init(pc8736x_gpio_init);
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 21721d2..b66eaa0 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -549,8 +549,10 @@ static int mgslpc_probe(struct pcmcia_device *link)
     /* Initialize the struct pcmcia_device structure */
 
     ret = mgslpc_config(link);
-    if (ret)
+    if (ret) {
+	    tty_port_destroy(&info->port);
 	    return ret;
+    }
 
     mgslpc_add_device(info);
 
@@ -2757,6 +2759,7 @@ static void mgslpc_remove_device(MGSLPC_INFO *remove_info)
 			hdlcdev_exit(info);
 #endif
 			release_resources(info);
+			tty_port_destroy(&info->port);
 			kfree(info);
 			mgslpc_device_count--;
 			return;
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index d0d824e..1cd4924 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -251,12 +251,8 @@ static ssize_t pp_write (struct file * file, const char __user * buf,
 			break;
 		}
 
-		if (signal_pending (current)) {
-			if (!bytes_written) {
-				bytes_written = -EINTR;
-			}
+		if (signal_pending (current))
 			break;
-		}
 
 		cond_resched();
 	}
diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c
index 6abdde4..588063ac 100644
--- a/drivers/char/ps3flash.c
+++ b/drivers/char/ps3flash.c
@@ -363,7 +363,7 @@ static struct miscdevice ps3flash_misc = {
 	.fops	= &ps3flash_fops,
 };
 
-static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev)
+static int ps3flash_probe(struct ps3_system_bus_device *_dev)
 {
 	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
 	struct ps3flash_private *priv;
diff --git a/drivers/char/random.c b/drivers/char/random.c
index b86eae9..85e81ec 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -399,7 +399,6 @@ static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
 static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
 static struct fasync_struct *fasync;
 
-#if 0
 static bool debug;
 module_param(debug, bool, 0644);
 #define DEBUG_ENT(fmt, arg...) do { \
@@ -410,9 +409,6 @@ module_param(debug, bool, 0644);
 		blocking_pool.entropy_count,\
 		nonblocking_pool.entropy_count,\
 		## arg); } while (0)
-#else
-#define DEBUG_ENT(fmt, arg...) do {} while (0)
-#endif
 
 /**********************************************************************
  *
@@ -437,6 +433,7 @@ struct entropy_store {
 	int entropy_count;
 	int entropy_total;
 	unsigned int initialized:1;
+	bool last_data_init;
 	__u8 last_data[EXTRACT_SIZE];
 };
 
@@ -829,7 +826,7 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
 		bytes = min_t(int, bytes, sizeof(tmp));
 
 		DEBUG_ENT("going to reseed %s with %d bits "
-			  "(%d of %d requested)\n",
+			  "(%zu of %d requested)\n",
 			  r->name, bytes * 8, nbytes * 8, r->entropy_count);
 
 		bytes = extract_entropy(r->pull, tmp, bytes,
@@ -860,7 +857,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
 	spin_lock_irqsave(&r->lock, flags);
 
 	BUG_ON(r->entropy_count > r->poolinfo->POOLBITS);
-	DEBUG_ENT("trying to extract %d bits from %s\n",
+	DEBUG_ENT("trying to extract %zu bits from %s\n",
 		  nbytes * 8, r->name);
 
 	/* Can we pull enough? */
@@ -882,7 +879,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
 		}
 	}
 
-	DEBUG_ENT("debiting %d entropy credits from %s%s\n",
+	DEBUG_ENT("debiting %zu entropy credits from %s%s\n",
 		  nbytes * 8, r->name, r->limit ? "" : " (unlimited)");
 
 	spin_unlock_irqrestore(&r->lock, flags);
@@ -957,6 +954,10 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
 	ssize_t ret = 0, i;
 	__u8 tmp[EXTRACT_SIZE];
 
+	/* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */
+	if (fips_enabled && !r->last_data_init)
+		nbytes += EXTRACT_SIZE;
+
 	trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_);
 	xfer_secondary_pool(r, nbytes);
 	nbytes = account(r, nbytes, min, reserved);
@@ -967,6 +968,17 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
 		if (fips_enabled) {
 			unsigned long flags;
 
+
+			/* prime last_data value if need be, per fips 140-2 */
+			if (!r->last_data_init) {
+				spin_lock_irqsave(&r->lock, flags);
+				memcpy(r->last_data, tmp, EXTRACT_SIZE);
+				r->last_data_init = true;
+				nbytes -= EXTRACT_SIZE;
+				spin_unlock_irqrestore(&r->lock, flags);
+				extract_buf(r, tmp);
+			}
+
 			spin_lock_irqsave(&r->lock, flags);
 			if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
 				panic("Hardware RNG duplicated output!\n");
@@ -1086,6 +1098,7 @@ static void init_std_data(struct entropy_store *r)
 
 	r->entropy_count = 0;
 	r->entropy_total = 0;
+	r->last_data_init = false;
 	mix_pool_bytes(r, &now, sizeof(now), NULL);
 	for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) {
 		if (!arch_get_random_long(&rv))
@@ -1142,11 +1155,16 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 		if (n > SEC_XFER_SIZE)
 			n = SEC_XFER_SIZE;
 
-		DEBUG_ENT("reading %d bits\n", n*8);
+		DEBUG_ENT("reading %zu bits\n", n*8);
 
 		n = extract_entropy_user(&blocking_pool, buf, n);
 
-		DEBUG_ENT("read got %d bits (%d still needed)\n",
+		if (n < 0) {
+			retval = n;
+			break;
+		}
+
+		DEBUG_ENT("read got %zd bits (%zd still needed)\n",
 			  n*8, (nbytes-n)*8);
 
 		if (n == 0) {
@@ -1171,10 +1189,6 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 			continue;
 		}
 
-		if (n < 0) {
-			retval = n;
-			break;
-		}
 		count += n;
 		buf += n;
 		nbytes -= n;
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 9b4f011..d780295 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1164,7 +1164,7 @@ static struct acpi_driver sonypi_acpi_driver = {
 };
 #endif
 
-static int __devinit sonypi_create_input_devices(struct platform_device *pdev)
+static int sonypi_create_input_devices(struct platform_device *pdev)
 {
 	struct input_dev *jog_dev;
 	struct input_dev *key_dev;
@@ -1225,7 +1225,7 @@ static int __devinit sonypi_create_input_devices(struct platform_device *pdev)
 	return error;
 }
 
-static int __devinit sonypi_setup_ioports(struct sonypi_device *dev,
+static int sonypi_setup_ioports(struct sonypi_device *dev,
 				const struct sonypi_ioport_list *ioport_list)
 {
 	/* try to detect if sony-laptop is being used and thus
@@ -1265,7 +1265,7 @@ static int __devinit sonypi_setup_ioports(struct sonypi_device *dev,
 	return -EBUSY;
 }
 
-static int __devinit sonypi_setup_irq(struct sonypi_device *dev,
+static int sonypi_setup_irq(struct sonypi_device *dev,
 				      const struct sonypi_irq_list *irq_list)
 {
 	while (irq_list->irq) {
@@ -1282,7 +1282,7 @@ static int __devinit sonypi_setup_irq(struct sonypi_device *dev,
 	return -EBUSY;
 }
 
-static void __devinit sonypi_display_info(void)
+static void sonypi_display_info(void)
 {
 	printk(KERN_INFO "sonypi: detected type%d model, "
 	       "verbose = %d, fnkeyinit = %s, camera = %s, "
@@ -1304,7 +1304,7 @@ static void __devinit sonypi_display_info(void)
 		       sonypi_misc_device.minor);
 }
 
-static int __devinit sonypi_probe(struct platform_device *dev)
+static int sonypi_probe(struct platform_device *dev)
 {
 	const struct sonypi_ioport_list *ioport_list;
 	const struct sonypi_irq_list *irq_list;
@@ -1428,7 +1428,7 @@ static int __devinit sonypi_probe(struct platform_device *dev)
 	return error;
 }
 
-static int __devexit sonypi_remove(struct platform_device *dev)
+static int sonypi_remove(struct platform_device *dev)
 {
 	sonypi_disable();
 
@@ -1491,7 +1491,7 @@ static struct platform_driver sonypi_driver = {
 		.pm	= SONYPI_PM,
 	},
 	.probe		= sonypi_probe,
-	.remove		= __devexit_p(sonypi_remove),
+	.remove		= sonypi_remove,
 	.shutdown	= sonypi_shutdown,
 };
 
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
index ad26418..34c63f8 100644
--- a/drivers/char/tb0219.c
+++ b/drivers/char/tb0219.c
@@ -284,7 +284,7 @@ static void tb0219_pci_irq_init(void)
 	vr41xx_set_irq_level(TB0219_PCI_SLOT3_PIN, IRQ_LEVEL_LOW);
 }
 
-static int __devinit tb0219_probe(struct platform_device *dev)
+static int tb0219_probe(struct platform_device *dev)
 {
 	int retval;
 
@@ -318,7 +318,7 @@ static int __devinit tb0219_probe(struct platform_device *dev)
 	return 0;
 }
 
-static int __devexit tb0219_remove(struct platform_device *dev)
+static int tb0219_remove(struct platform_device *dev)
 {
 	_machine_restart = old_machine_restart;
 
@@ -334,7 +334,7 @@ static struct platform_device *tb0219_platform_device;
 
 static struct platform_driver tb0219_device_driver = {
 	.probe		= tb0219_probe,
-	.remove		= __devexit_p(tb0219_remove),
+	.remove		= tb0219_remove,
 	.driver		= {
 		.name	= "TB0219",
 		.owner	= THIS_MODULE,
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
index 5a831ae..fb447bd 100644
--- a/drivers/char/tpm/tpm_i2c_infineon.c
+++ b/drivers/char/tpm/tpm_i2c_infineon.c
@@ -555,7 +555,7 @@ static struct tpm_vendor_specific tpm_tis_i2c = {
 	.miscdev.fops = &tis_ops,
 };
 
-static int __devinit tpm_tis_i2c_init(struct device *dev)
+static int tpm_tis_i2c_init(struct device *dev)
 {
 	u32 vendor;
 	int rc = 0;
@@ -632,7 +632,7 @@ static const struct i2c_device_id tpm_tis_i2c_table[] = {
 MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table);
 static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume);
 
-static int __devinit tpm_tis_i2c_probe(struct i2c_client *client,
+static int tpm_tis_i2c_probe(struct i2c_client *client,
 			     const struct i2c_device_id *id)
 {
 	int rc;
@@ -656,7 +656,7 @@ static int __devinit tpm_tis_i2c_probe(struct i2c_client *client,
 	return rc;
 }
 
-static int __devexit tpm_tis_i2c_remove(struct i2c_client *client)
+static int tpm_tis_i2c_remove(struct i2c_client *client)
 {
 	struct tpm_chip *chip = tpm_dev.chip;
 	release_locality(chip, chip->vendor.locality, 1);
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
index efc4ab3..9978609 100644
--- a/drivers/char/tpm/tpm_ibmvtpm.c
+++ b/drivers/char/tpm/tpm_ibmvtpm.c
@@ -32,14 +32,12 @@
 
 static const char tpm_ibmvtpm_driver_name[] = "tpm_ibmvtpm";
 
-static struct vio_device_id tpm_ibmvtpm_device_table[] __devinitdata = {
+static struct vio_device_id tpm_ibmvtpm_device_table[] = {
 	{ "IBM,vtpm", "IBM,vtpm"},
 	{ "", "" }
 };
 MODULE_DEVICE_TABLE(vio, tpm_ibmvtpm_device_table);
 
-DECLARE_WAIT_QUEUE_HEAD(wq);
-
 /**
  * ibmvtpm_send_crq - Send a CRQ request
  * @vdev:	vio device struct
@@ -83,6 +81,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 {
 	struct ibmvtpm_dev *ibmvtpm;
 	u16 len;
+	int sig;
 
 	ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data;
 
@@ -91,22 +90,23 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 		return 0;
 	}
 
-	wait_event_interruptible(wq, ibmvtpm->crq_res.len != 0);
+	sig = wait_event_interruptible(ibmvtpm->wq, ibmvtpm->res_len != 0);
+	if (sig)
+		return -EINTR;
+
+	len = ibmvtpm->res_len;
 
-	if (count < ibmvtpm->crq_res.len) {
+	if (count < len) {
 		dev_err(ibmvtpm->dev,
 			"Invalid size in recv: count=%ld, crq_size=%d\n",
-			count, ibmvtpm->crq_res.len);
+			count, len);
 		return -EIO;
 	}
 
 	spin_lock(&ibmvtpm->rtce_lock);
-	memcpy((void *)buf, (void *)ibmvtpm->rtce_buf, ibmvtpm->crq_res.len);
-	memset(ibmvtpm->rtce_buf, 0, ibmvtpm->crq_res.len);
-	ibmvtpm->crq_res.valid = 0;
-	ibmvtpm->crq_res.msg = 0;
-	len = ibmvtpm->crq_res.len;
-	ibmvtpm->crq_res.len = 0;
+	memcpy((void *)buf, (void *)ibmvtpm->rtce_buf, len);
+	memset(ibmvtpm->rtce_buf, 0, len);
+	ibmvtpm->res_len = 0;
 	spin_unlock(&ibmvtpm->rtce_lock);
 	return len;
 }
@@ -267,13 +267,12 @@ static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
  * Return value:
  *	0
  */
-static int __devexit tpm_ibmvtpm_remove(struct vio_dev *vdev)
+static int tpm_ibmvtpm_remove(struct vio_dev *vdev)
 {
 	struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
 	int rc = 0;
 
 	free_irq(vdev->irq, ibmvtpm);
-	tasklet_kill(&ibmvtpm->tasklet);
 
 	do {
 		if (rc)
@@ -372,7 +371,6 @@ static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm)
 static int tpm_ibmvtpm_resume(struct device *dev)
 {
 	struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev);
-	unsigned long flags;
 	int rc = 0;
 
 	do {
@@ -387,10 +385,11 @@ static int tpm_ibmvtpm_resume(struct device *dev)
 		return rc;
 	}
 
-	spin_lock_irqsave(&ibmvtpm->lock, flags);
-	vio_disable_interrupts(ibmvtpm->vdev);
-	tasklet_schedule(&ibmvtpm->tasklet);
-	spin_unlock_irqrestore(&ibmvtpm->lock, flags);
+	rc = vio_enable_interrupts(ibmvtpm->vdev);
+	if (rc) {
+		dev_err(dev, "Error vio_enable_interrupts rc=%d\n", rc);
+		return rc;
+	}
 
 	rc = ibmvtpm_crq_send_init(ibmvtpm);
 	if (rc)
@@ -467,7 +466,7 @@ static struct ibmvtpm_crq *ibmvtpm_crq_get_next(struct ibmvtpm_dev *ibmvtpm)
 	if (crq->valid & VTPM_MSG_RES) {
 		if (++crq_q->index == crq_q->num_entry)
 			crq_q->index = 0;
-		rmb();
+		smp_rmb();
 	} else
 		crq = NULL;
 	return crq;
@@ -535,11 +534,9 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
 			ibmvtpm->vtpm_version = crq->data;
 			return;
 		case VTPM_TPM_COMMAND_RES:
-			ibmvtpm->crq_res.valid = crq->valid;
-			ibmvtpm->crq_res.msg = crq->msg;
-			ibmvtpm->crq_res.len = crq->len;
-			ibmvtpm->crq_res.data = crq->data;
-			wake_up_interruptible(&wq);
+			/* len of the data in rtce buffer */
+			ibmvtpm->res_len = crq->len;
+			wake_up_interruptible(&ibmvtpm->wq);
 			return;
 		default:
 			return;
@@ -559,38 +556,19 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
 static irqreturn_t ibmvtpm_interrupt(int irq, void *vtpm_instance)
 {
 	struct ibmvtpm_dev *ibmvtpm = (struct ibmvtpm_dev *) vtpm_instance;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ibmvtpm->lock, flags);
-	vio_disable_interrupts(ibmvtpm->vdev);
-	tasklet_schedule(&ibmvtpm->tasklet);
-	spin_unlock_irqrestore(&ibmvtpm->lock, flags);
-
-	return IRQ_HANDLED;
-}
-
-/**
- * ibmvtpm_tasklet - Interrupt handler tasklet
- * @data:	ibm vtpm device struct
- *
- * Returns:
- *	Nothing
- **/
-static void ibmvtpm_tasklet(void *data)
-{
-	struct ibmvtpm_dev *ibmvtpm = data;
 	struct ibmvtpm_crq *crq;
-	unsigned long flags;
 
-	spin_lock_irqsave(&ibmvtpm->lock, flags);
+	/* while loop is needed for initial setup (get version and
+	 * get rtce_size). There should be only one tpm request at any
+	 * given time.
+	 */
 	while ((crq = ibmvtpm_crq_get_next(ibmvtpm)) != NULL) {
 		ibmvtpm_crq_process(crq, ibmvtpm);
 		crq->valid = 0;
-		wmb();
+		smp_wmb();
 	}
 
-	vio_enable_interrupts(ibmvtpm->vdev);
-	spin_unlock_irqrestore(&ibmvtpm->lock, flags);
+	return IRQ_HANDLED;
 }
 
 /**
@@ -602,7 +580,7 @@ static void ibmvtpm_tasklet(void *data)
  *	0 - Success
  *	Non-zero - Failure
  */
-static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
+static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
 				   const struct vio_device_id *id)
 {
 	struct ibmvtpm_dev *ibmvtpm;
@@ -650,9 +628,6 @@ static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
 		goto reg_crq_cleanup;
 	}
 
-	tasklet_init(&ibmvtpm->tasklet, (void *)ibmvtpm_tasklet,
-		     (unsigned long)ibmvtpm);
-
 	rc = request_irq(vio_dev->irq, ibmvtpm_interrupt, 0,
 			 tpm_ibmvtpm_driver_name, ibmvtpm);
 	if (rc) {
@@ -666,13 +641,14 @@ static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
 		goto init_irq_cleanup;
 	}
 
+	init_waitqueue_head(&ibmvtpm->wq);
+
 	crq_q->index = 0;
 
 	ibmvtpm->dev = dev;
 	ibmvtpm->vdev = vio_dev;
 	chip->vendor.data = (void *)ibmvtpm;
 
-	spin_lock_init(&ibmvtpm->lock);
 	spin_lock_init(&ibmvtpm->rtce_lock);
 
 	rc = ibmvtpm_crq_send_init(ibmvtpm);
@@ -689,7 +665,6 @@ static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
 
 	return rc;
 init_irq_cleanup:
-	tasklet_kill(&ibmvtpm->tasklet);
 	do {
 		rc1 = plpar_hcall_norets(H_FREE_CRQ, vio_dev->unit_address);
 	} while (rc1 == H_BUSY || H_IS_LONG_BUSY(rc1));
diff --git a/drivers/char/tpm/tpm_ibmvtpm.h b/drivers/char/tpm/tpm_ibmvtpm.h
index 4296eb4..bd82a79 100644
--- a/drivers/char/tpm/tpm_ibmvtpm.h
+++ b/drivers/char/tpm/tpm_ibmvtpm.h
@@ -38,13 +38,12 @@ struct ibmvtpm_dev {
 	struct vio_dev *vdev;
 	struct ibmvtpm_crq_queue crq_queue;
 	dma_addr_t crq_dma_handle;
-	spinlock_t lock;
-	struct tasklet_struct tasklet;
 	u32 rtce_size;
 	void __iomem *rtce_buf;
 	dma_addr_t rtce_dma_handle;
 	spinlock_t rtce_lock;
-	struct ibmvtpm_crq crq_res;
+	wait_queue_head_t wq;
+	u16 res_len;
 	u32 vtpm_version;
 };
 
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index 3251a44..2b480c2 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -415,7 +415,7 @@ static const struct pnp_device_id tpm_inf_pnp_tbl[] = {
 
 MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl);
 
-static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
+static int tpm_inf_pnp_probe(struct pnp_dev *dev,
 				       const struct pnp_device_id *dev_id)
 {
 	int rc = 0;
@@ -594,7 +594,7 @@ err_last:
 	return rc;
 }
 
-static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev)
+static void tpm_inf_pnp_remove(struct pnp_dev *dev)
 {
 	struct tpm_chip *chip = pnp_get_drvdata(dev);
 
@@ -655,7 +655,7 @@ static struct pnp_driver tpm_inf_pnp_driver = {
 	.probe = tpm_inf_pnp_probe,
 	.suspend = tpm_inf_pnp_suspend,
 	.resume = tpm_inf_pnp_resume,
-	.remove = __devexit_p(tpm_inf_pnp_remove)
+	.remove = tpm_inf_pnp_remove
 };
 
 static int __init init_inf(void)
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 6bdf267..ea31daf 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -729,7 +729,7 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
 #endif
 
 #ifdef CONFIG_PNP
-static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
+static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
 				      const struct pnp_device_id *pnp_id)
 {
 	resource_size_t start, len;
@@ -769,7 +769,7 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev)
 	return ret;
 }
 
-static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
+static struct pnp_device_id tpm_pnp_tbl[] = {
 	{"PNP0C31", 0},		/* TPM */
 	{"ATM1200", 0},		/* Atmel */
 	{"IFX0102", 0},		/* Infineon */
@@ -783,7 +783,7 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
 };
 MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
 
-static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev)
+static void tpm_tis_pnp_remove(struct pnp_dev *dev)
 {
 	struct tpm_chip *chip = pnp_get_drvdata(dev);
 
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
index af98f6d..4945bd3 100644
--- a/drivers/char/ttyprintk.c
+++ b/drivers/char/ttyprintk.c
@@ -179,7 +179,6 @@ static int __init ttyprintk_init(void)
 {
 	int ret = -ENOMEM;
 
-	tty_port_init(&tpk_port.port);
 	tpk_port.port.ops = &null_ops;
 	mutex_init(&tpk_port.port_write_mutex);
 
@@ -190,6 +189,8 @@ static int __init ttyprintk_init(void)
 	if (IS_ERR(ttyprintk_driver))
 		return PTR_ERR(ttyprintk_driver);
 
+	tty_port_init(&tpk_port.port);
+
 	ttyprintk_driver->driver_name = "ttyprintk";
 	ttyprintk_driver->name = "ttyprintk";
 	ttyprintk_driver->major = TTYAUX_MAJOR;
@@ -211,6 +212,7 @@ static int __init ttyprintk_init(void)
 error:
 	tty_unregister_driver(ttyprintk_driver);
 	put_tty_driver(ttyprintk_driver);
+	tty_port_destroy(&tpk_port.port);
 	ttyprintk_driver = NULL;
 	return ret;
 }
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 8ab9c3d..469a9df 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -349,7 +349,7 @@ static struct port_buffer *alloc_buf(size_t buf_size)
 	buf = kmalloc(sizeof(*buf), GFP_KERNEL);
 	if (!buf)
 		goto fail;
-	buf->buf = kzalloc(buf_size, GFP_KERNEL);
+	buf->buf = kmalloc(buf_size, GFP_KERNEL);
 	if (!buf->buf)
 		goto free_buf;
 	buf->len = 0;
@@ -459,7 +459,7 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id,
 	vq = portdev->c_ovq;
 
 	sg_init_one(sg, &cpkt, sizeof(cpkt));
-	if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) >= 0) {
+	if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) == 0) {
 		virtqueue_kick(vq);
 		while (!virtqueue_get_buf(vq, &len))
 			cpu_relax();
@@ -524,7 +524,7 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,
 			      struct buffer_token *tok, bool nonblock)
 {
 	struct virtqueue *out_vq;
-	ssize_t ret;
+	int err;
 	unsigned long flags;
 	unsigned int len;
 
@@ -534,17 +534,17 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,
 
 	reclaim_consumed_buffers(port);
 
-	ret = virtqueue_add_buf(out_vq, sg, nents, 0, tok, GFP_ATOMIC);
+	err = virtqueue_add_buf(out_vq, sg, nents, 0, tok, GFP_ATOMIC);
 
 	/* Tell Host to go! */
 	virtqueue_kick(out_vq);
 
-	if (ret < 0) {
+	if (err) {
 		in_count = 0;
 		goto done;
 	}
 
-	if (ret == 0)
+	if (out_vq->num_free == 0)
 		port->outvq_full = true;
 
 	if (nonblock)
@@ -879,6 +879,8 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe,
 	if (likely(ret > 0))
 		ret = send_pages(port, sgl.sg, sgl.n, sgl.len, true);
 
+	if (unlikely(ret <= 0))
+		kfree(sgl.sg);
 	return ret;
 }
 
@@ -1435,6 +1437,10 @@ static void remove_port_data(struct port *port)
 	/* Remove buffers we queued up for the Host to send us data in. */
 	while ((buf = virtqueue_detach_unused_buf(port->in_vq)))
 		free_buf(buf);
+
+	/* Free pending buffers from the out-queue. */
+	while ((buf = virtqueue_detach_unused_buf(port->out_vq)))
+		free_buf(buf);
 }
 
 /*
@@ -1846,7 +1852,7 @@ static void remove_controlq_data(struct ports_device *portdev)
  * config space to see how many ports the host has spawned.  We
  * initialize each port found.
  */
-static int __devinit virtcons_probe(struct virtio_device *vdev)
+static int virtcons_probe(struct virtio_device *vdev)
 {
 	struct ports_device *portdev;
 	int err;
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 2c5d15b..5224da5 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -595,7 +595,7 @@ static const struct file_operations hwicap_fops = {
 	.llseek = noop_llseek,
 };
 
-static int __devinit hwicap_setup(struct device *dev, int id,
+static int hwicap_setup(struct device *dev, int id,
 		const struct resource *regs_res,
 		const struct hwicap_driver_config *config,
 		const struct config_registers *config_regs)
@@ -717,7 +717,7 @@ static struct hwicap_driver_config fifo_icap_config = {
 	.reset = fifo_icap_reset,
 };
 
-static int __devexit hwicap_remove(struct device *dev)
+static int hwicap_remove(struct device *dev)
 {
 	struct hwicap_drvdata *drvdata;
 
@@ -740,7 +740,7 @@ static int __devexit hwicap_remove(struct device *dev)
 }
 
 #ifdef CONFIG_OF
-static int __devinit hwicap_of_probe(struct platform_device *op,
+static int hwicap_of_probe(struct platform_device *op,
 				     const struct hwicap_driver_config *config)
 {
 	struct resource res;
@@ -785,8 +785,8 @@ static inline int hwicap_of_probe(struct platform_device *op,
 }
 #endif /* CONFIG_OF */
 
-static const struct of_device_id __devinitconst hwicap_of_match[];
-static int __devinit hwicap_drv_probe(struct platform_device *pdev)
+static const struct of_device_id hwicap_of_match[];
+static int hwicap_drv_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *match;
 	struct resource *res;
@@ -822,14 +822,14 @@ static int __devinit hwicap_drv_probe(struct platform_device *pdev)
 			&buffer_icap_config, regs);
 }
 
-static int __devexit hwicap_drv_remove(struct platform_device *pdev)
+static int hwicap_drv_remove(struct platform_device *pdev)
 {
 	return hwicap_remove(&pdev->dev);
 }
 
 #ifdef CONFIG_OF
 /* Match table for device tree binding */
-static const struct of_device_id __devinitconst hwicap_of_match[] = {
+static const struct of_device_id hwicap_of_match[] = {
 	{ .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},
 	{ .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config},
 	{},
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index bace9e9..823f62d 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -42,10 +42,12 @@ config COMMON_CLK_WM831X
 
 config COMMON_CLK_VERSATILE
 	bool "Clock driver for ARM Reference designs"
-	depends on ARCH_INTEGRATOR || ARCH_REALVIEW
+	depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS
 	---help---
-          Supports clocking on ARM Reference designs Integrator/AP,
-	  Integrator/CP, RealView PB1176, EB, PB11MP and PBX.
+          Supports clocking on ARM Reference designs:
+	  - Integrator/AP and Integrator/CP
+	  - RealView PB1176, EB, PB11MP and PBX
+	  - Versatile Express
 
 config COMMON_CLK_MAX77686
 	tristate "Clock driver for Maxim 77686 MFD"
@@ -53,4 +55,12 @@ config COMMON_CLK_MAX77686
 	---help---
 	  This driver supports Maxim 77686 crystal oscillator clock. 
 
+config CLK_TWL6040
+	tristate "External McPDM functional clock from twl6040"
+	depends on TWL6040_CORE
+	---help---
+	  Enable the external functional clock support on OMAP4+ platforms for
+	  McPDM. McPDM module is using the external bit clock on the McPDM bus
+	  as functional clock.
+
 endmenu
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 71a25b9..4e1ccb1 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -19,7 +19,10 @@ endif
 obj-$(CONFIG_MACH_LOONGSON1)	+= clk-ls1x.o
 obj-$(CONFIG_ARCH_U8500)	+= ux500/
 obj-$(CONFIG_ARCH_VT8500)	+= clk-vt8500.o
+obj-$(CONFIG_ARCH_SUNXI)	+= clk-sunxi.o
+obj-$(CONFIG_ARCH_ZYNQ)		+= clk-zynq.o
 
 # Chip specific
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
+obj-$(CONFIG_CLK_TWL6040)	+= clk-twl6040.o
diff --git a/drivers/clk/clk-bcm2835.c b/drivers/clk/clk-bcm2835.c
index 67ad16b..e69991a 100644
--- a/drivers/clk/clk-bcm2835.c
+++ b/drivers/clk/clk-bcm2835.c
@@ -33,17 +33,17 @@ void __init bcm2835_init_clocks(void)
 
 	clk = clk_register_fixed_rate(NULL, "sys_pclk", NULL, CLK_IS_ROOT,
 					250000000);
-	if (!clk)
+	if (IS_ERR(clk))
 		pr_err("sys_pclk not registered\n");
 
 	clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT,
 					126000000);
-	if (!clk)
+	if (IS_ERR(clk))
 		pr_err("apb_pclk not registered\n");
 
 	clk = clk_register_fixed_rate(NULL, "uart0_pclk", NULL, CLK_IS_ROOT,
 					3000000);
-	if (!clk)
+	if (IS_ERR(clk))
 		pr_err("uart0_pclk not registered\n");
 	ret = clk_register_clkdev(clk, NULL, "20201000.uart");
 	if (ret)
@@ -51,9 +51,9 @@ void __init bcm2835_init_clocks(void)
 
 	clk = clk_register_fixed_rate(NULL, "uart1_pclk", NULL, CLK_IS_ROOT,
 					125000000);
-	if (!clk)
+	if (IS_ERR(clk))
 		pr_err("uart1_pclk not registered\n");
 	ret = clk_register_clkdev(clk, NULL, "20215000.uart");
 	if (ret)
-		pr_err("uart0_pclk alias not registered\n");
+		pr_err("uart1_pclk alias not registered\n");
 }
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c
index f5ec0ee..af78ed6 100644
--- a/drivers/clk/clk-fixed-rate.c
+++ b/drivers/clk/clk-fixed-rate.c
@@ -97,7 +97,7 @@ void __init of_fixed_clk_setup(struct device_node *node)
 	of_property_read_string(node, "clock-output-names", &clk_name);
 
 	clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate);
-	if (clk)
+	if (!IS_ERR(clk))
 		of_clk_add_provider(node, of_clk_src_simple_get, clk);
 }
 EXPORT_SYMBOL_GPL(of_fixed_clk_setup);
diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c
index ac5f543..d098f72 100644
--- a/drivers/clk/clk-max77686.c
+++ b/drivers/clk/clk-max77686.c
@@ -143,7 +143,7 @@ static int max77686_clk_register(struct device *dev,
 	return 0;
 }
 
-static __devinit int max77686_clk_probe(struct platform_device *pdev)
+static int max77686_clk_probe(struct platform_device *pdev)
 {
 	struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 	struct max77686_clk **max77686_clks;
@@ -199,7 +199,7 @@ out:
 	return ret;
 }
 
-static int __devexit max77686_clk_remove(struct platform_device *pdev)
+static int max77686_clk_remove(struct platform_device *pdev)
 {
 	struct max77686_clk **max77686_clks = platform_get_drvdata(pdev);
 	int i;
@@ -223,7 +223,7 @@ static struct platform_driver max77686_clk_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = max77686_clk_probe,
-	.remove = __devexit_p(max77686_clk_remove),
+	.remove = max77686_clk_remove,
 	.id_table = max77686_clk_id,
 };
 
diff --git a/drivers/clk/clk-nomadik.c b/drivers/clk/clk-nomadik.c
index 517a8ff..6b4c70f7 100644
--- a/drivers/clk/clk-nomadik.c
+++ b/drivers/clk/clk-nomadik.c
@@ -20,6 +20,7 @@ void __init nomadik_clk_init(void)
 	clk_register_clkdev(clk, NULL, "gpio.2");
 	clk_register_clkdev(clk, NULL, "gpio.3");
 	clk_register_clkdev(clk, NULL, "rng");
+	clk_register_clkdev(clk, NULL, "fsmc-nand");
 
 	/*
 	 * The 2.4 MHz TIMCLK reference clock is active at boot time, this is
diff --git a/drivers/clk/clk-prima2.c b/drivers/clk/clk-prima2.c
index 517874f..a203ecc 100644
--- a/drivers/clk/clk-prima2.c
+++ b/drivers/clk/clk-prima2.c
@@ -1054,118 +1054,118 @@ void __init sirfsoc_of_clk_init(void)
 	/* These are always available (RTC and 26MHz OSC)*/
 	clk = clk_register_fixed_rate(NULL, "rtc", NULL,
 		CLK_IS_ROOT, 32768);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk = clk_register_fixed_rate(NULL, "osc", NULL,
 		CLK_IS_ROOT, 26000000);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 
 	clk = clk_register(NULL, &clk_pll1.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk = clk_register(NULL, &clk_pll2.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk = clk_register(NULL, &clk_pll3.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk = clk_register(NULL, &clk_mem.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk = clk_register(NULL, &clk_sys.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk = clk_register(NULL, &clk_security.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b8030000.security");
 	clk = clk_register(NULL, &clk_dsp.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk = clk_register(NULL, &clk_gps.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "a8010000.gps");
 	clk = clk_register(NULL, &clk_mf.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk = clk_register(NULL, &clk_io.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "io");
 	clk = clk_register(NULL, &clk_cpu.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "cpu");
 	clk = clk_register(NULL, &clk_uart0.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b0050000.uart");
 	clk = clk_register(NULL, &clk_uart1.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b0060000.uart");
 	clk = clk_register(NULL, &clk_uart2.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b0070000.uart");
 	clk = clk_register(NULL, &clk_tsc.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b0110000.tsc");
 	clk = clk_register(NULL, &clk_i2c0.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b00e0000.i2c");
 	clk = clk_register(NULL, &clk_i2c1.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b00f0000.i2c");
 	clk = clk_register(NULL, &clk_spi0.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b00d0000.spi");
 	clk = clk_register(NULL, &clk_spi1.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b0170000.spi");
 	clk = clk_register(NULL, &clk_pwmc.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b0130000.pwm");
 	clk = clk_register(NULL, &clk_efuse.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b0140000.efusesys");
 	clk = clk_register(NULL, &clk_pulse.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b0150000.pulsec");
 	clk = clk_register(NULL, &clk_dmac0.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b00b0000.dma-controller");
 	clk = clk_register(NULL, &clk_dmac1.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b0160000.dma-controller");
 	clk = clk_register(NULL, &clk_nand.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b0030000.nand");
 	clk = clk_register(NULL, &clk_audio.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b0040000.audio");
 	clk = clk_register(NULL, &clk_usp0.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b0080000.usp");
 	clk = clk_register(NULL, &clk_usp1.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b0090000.usp");
 	clk = clk_register(NULL, &clk_usp2.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b00a0000.usp");
 	clk = clk_register(NULL, &clk_vip.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b00c0000.vip");
 	clk = clk_register(NULL, &clk_gfx.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "98000000.graphics");
 	clk = clk_register(NULL, &clk_mm.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "a0000000.multimedia");
 	clk = clk_register(NULL, &clk_lcd.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "90010000.display");
 	clk = clk_register(NULL, &clk_vpp.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "90020000.vpp");
 	clk = clk_register(NULL, &clk_mmc01.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk = clk_register(NULL, &clk_mmc23.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk = clk_register(NULL, &clk_mmc45.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk = clk_register(NULL, &usb_pll_clk_hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk = clk_register(NULL, &clk_usb0.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b00e0000.usb");
 	clk = clk_register(NULL, &clk_usb1.hw);
-	BUG_ON(!clk);
+	BUG_ON(IS_ERR(clk));
 	clk_register_clkdev(clk, NULL, "b00f0000.usb");
 }
diff --git a/drivers/clk/clk-sunxi.c b/drivers/clk/clk-sunxi.c
new file mode 100644
index 0000000..0e831b5
--- /dev/null
+++ b/drivers/clk/clk-sunxi.c
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/sunxi.h>
+#include <linux/of.h>
+
+static const __initconst struct of_device_id clk_match[] = {
+	{ .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
+	{}
+};
+
+void __init sunxi_init_clocks(void)
+{
+	of_clk_init(clk_match);
+}
diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c
new file mode 100644
index 0000000..bc1e713
--- /dev/null
+++ b/drivers/clk/clk-twl6040.c
@@ -0,0 +1,126 @@
+/*
+* TWL6040 clock module driver for OMAP4 McPDM functional clock
+*
+* Copyright (C) 2012 Texas Instruments Inc.
+* Peter Ujfalusi <peter.ujfalusi@ti.com>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*
+*/
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/twl6040.h>
+#include <linux/clk-provider.h>
+
+struct twl6040_clk {
+	struct twl6040 *twl6040;
+	struct device *dev;
+	struct clk_hw mcpdm_fclk;
+	struct clk *clk;
+	int enabled;
+};
+
+static int twl6040_bitclk_is_enabled(struct clk_hw *hw)
+{
+	struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
+						       mcpdm_fclk);
+	return twl6040_clk->enabled;
+}
+
+static int twl6040_bitclk_prepare(struct clk_hw *hw)
+{
+	struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
+						       mcpdm_fclk);
+	int ret;
+
+	ret = twl6040_power(twl6040_clk->twl6040, 1);
+	if (!ret)
+		twl6040_clk->enabled = 1;
+
+	return ret;
+}
+
+static void twl6040_bitclk_unprepare(struct clk_hw *hw)
+{
+	struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
+						       mcpdm_fclk);
+	int ret;
+
+	ret = twl6040_power(twl6040_clk->twl6040, 0);
+	if (!ret)
+		twl6040_clk->enabled = 0;
+}
+
+static const struct clk_ops twl6040_mcpdm_ops = {
+	.is_enabled = twl6040_bitclk_is_enabled,
+	.prepare = twl6040_bitclk_prepare,
+	.unprepare = twl6040_bitclk_unprepare,
+};
+
+static struct clk_init_data wm831x_clkout_init = {
+	.name = "mcpdm_fclk",
+	.ops = &twl6040_mcpdm_ops,
+	.flags = CLK_IS_ROOT,
+};
+
+static int __devinit twl6040_clk_probe(struct platform_device *pdev)
+{
+	struct twl6040 *twl6040 = dev_get_drvdata(pdev->dev.parent);
+	struct twl6040_clk *clkdata;
+
+	clkdata = devm_kzalloc(&pdev->dev, sizeof(*clkdata), GFP_KERNEL);
+	if (!clkdata)
+		return -ENOMEM;
+
+	clkdata->dev = &pdev->dev;
+	clkdata->twl6040 = twl6040;
+
+	clkdata->mcpdm_fclk.init = &wm831x_clkout_init;
+	clkdata->clk = clk_register(&pdev->dev, &clkdata->mcpdm_fclk);
+	if (IS_ERR(clkdata->clk))
+		return PTR_ERR(clkdata->clk);
+
+	dev_set_drvdata(&pdev->dev, clkdata);
+
+	return 0;
+}
+
+static int __devexit twl6040_clk_remove(struct platform_device *pdev)
+{
+	struct twl6040_clk *clkdata = dev_get_drvdata(&pdev->dev);
+
+	clk_unregister(clkdata->clk);
+
+	return 0;
+}
+
+static struct platform_driver twl6040_clk_driver = {
+	.driver = {
+		.name = "twl6040-clk",
+		.owner = THIS_MODULE,
+	},
+	.probe = twl6040_clk_probe,
+	.remove = __devexit_p(twl6040_clk_remove),
+};
+
+module_platform_driver(twl6040_clk_driver);
+
+MODULE_DESCRIPTION("TWL6040 clock driver for McPDM functional clock");
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_ALIAS("platform:twl6040-clk");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c
index a885600..fe25570 100644
--- a/drivers/clk/clk-vt8500.c
+++ b/drivers/clk/clk-vt8500.c
@@ -120,8 +120,17 @@ static unsigned long vt8500_dclk_recalc_rate(struct clk_hw *hw,
 static long vt8500_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
 				unsigned long *prate)
 {
+	struct clk_device *cdev = to_clk_device(hw);
 	u32 divisor = *prate / rate;
 
+	/*
+	 * If this is a request for SDMMC we have to adjust the divisor
+	 * when >31 to use the fixed predivisor
+	 */
+	if ((cdev->div_mask == 0x3F) && (divisor > 31)) {
+		divisor = 64 * ((divisor / 64) + 1);
+	}
+
 	return *prate / divisor;
 }
 
@@ -135,6 +144,15 @@ static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
 	if (divisor == cdev->div_mask + 1)
 		divisor = 0;
 
+	/* SDMMC mask may need to be corrected before testing if its valid */
+	if ((cdev->div_mask == 0x3F) && (divisor > 31)) {
+		/*
+		 * Bit 5 is a fixed /64 predivisor. If the requested divisor
+		 * is >31 then correct for the fixed divisor being required.
+		 */
+		divisor = 0x20 + (divisor / 64);
+	}
+
 	if (divisor > cdev->div_mask) {
 		pr_err("%s: invalid divisor for clock\n", __func__);
 		return -EINVAL;
diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c
index e7b7765..16ed068 100644
--- a/drivers/clk/clk-wm831x.c
+++ b/drivers/clk/clk-wm831x.c
@@ -350,7 +350,7 @@ static struct clk_init_data wm831x_clkout_init = {
 	.flags = CLK_SET_RATE_PARENT,
 };
 
-static __devinit int wm831x_clk_probe(struct platform_device *pdev)
+static int wm831x_clk_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 	struct wm831x_clk *clkdata;
@@ -370,49 +370,33 @@ static __devinit int wm831x_clk_probe(struct platform_device *pdev)
 	clkdata->xtal_ena = ret & WM831X_XTAL_ENA;
 
 	clkdata->xtal_hw.init = &wm831x_xtal_init;
-	clkdata->xtal = clk_register(&pdev->dev, &clkdata->xtal_hw);
-	if (!clkdata->xtal)
-		return -EINVAL;
+	clkdata->xtal = devm_clk_register(&pdev->dev, &clkdata->xtal_hw);
+	if (IS_ERR(clkdata->xtal))
+		return PTR_ERR(clkdata->xtal);
 
 	clkdata->fll_hw.init = &wm831x_fll_init;
-	clkdata->fll = clk_register(&pdev->dev, &clkdata->fll_hw);
-	if (!clkdata->fll) {
-		ret = -EINVAL;
-		goto err_xtal;
-	}
+	clkdata->fll = devm_clk_register(&pdev->dev, &clkdata->fll_hw);
+	if (IS_ERR(clkdata->fll))
+		return PTR_ERR(clkdata->fll);
 
 	clkdata->clkout_hw.init = &wm831x_clkout_init;
-	clkdata->clkout = clk_register(&pdev->dev, &clkdata->clkout_hw);
-	if (!clkdata->clkout) {
-		ret = -EINVAL;
-		goto err_fll;
-	}
+	clkdata->clkout = devm_clk_register(&pdev->dev, &clkdata->clkout_hw);
+	if (IS_ERR(clkdata->clkout))
+		return PTR_ERR(clkdata->clkout);
 
 	dev_set_drvdata(&pdev->dev, clkdata);
 
 	return 0;
-
-err_fll:
-	clk_unregister(clkdata->fll);
-err_xtal:
-	clk_unregister(clkdata->xtal);
-	return ret;
 }
 
-static int __devexit wm831x_clk_remove(struct platform_device *pdev)
+static int wm831x_clk_remove(struct platform_device *pdev)
 {
-	struct wm831x_clk *clkdata = dev_get_drvdata(&pdev->dev);
-
-	clk_unregister(clkdata->clkout);
-	clk_unregister(clkdata->fll);
-	clk_unregister(clkdata->xtal);
-
 	return 0;
 }
 
 static struct platform_driver wm831x_clk_driver = {
 	.probe = wm831x_clk_probe,
-	.remove = __devexit_p(wm831x_clk_remove),
+	.remove = wm831x_clk_remove,
 	.driver		= {
 		.name	= "wm831x-clk",
 		.owner	= THIS_MODULE,
diff --git a/drivers/clk/clk-zynq.c b/drivers/clk/clk-zynq.c
new file mode 100644
index 0000000..37a3051
--- /dev/null
+++ b/drivers/clk/clk-zynq.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2012 National Instruments
+ *
+ * Josh Cartwright <josh.cartwright@ni.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/>.
+ */
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+
+static void __iomem *slcr_base;
+
+struct zynq_pll_clk {
+	struct clk_hw	hw;
+	void __iomem	*pll_ctrl;
+	void __iomem	*pll_cfg;
+};
+
+#define to_zynq_pll_clk(hw)	container_of(hw, struct zynq_pll_clk, hw)
+
+#define CTRL_PLL_FDIV(x)	((x) >> 12)
+
+static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
+					  unsigned long parent_rate)
+{
+	struct zynq_pll_clk *pll = to_zynq_pll_clk(hw);
+	return parent_rate * CTRL_PLL_FDIV(ioread32(pll->pll_ctrl));
+}
+
+static const struct clk_ops zynq_pll_clk_ops = {
+	.recalc_rate	= zynq_pll_recalc_rate,
+};
+
+static void __init zynq_pll_clk_setup(struct device_node *np)
+{
+	struct clk_init_data init;
+	struct zynq_pll_clk *pll;
+	const char *parent_name;
+	struct clk *clk;
+	u32 regs[2];
+	int ret;
+
+	ret = of_property_read_u32_array(np, "reg", regs, ARRAY_SIZE(regs));
+	if (WARN_ON(ret))
+		return;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (WARN_ON(!pll))
+		return;
+
+	pll->pll_ctrl = slcr_base + regs[0];
+	pll->pll_cfg  = slcr_base + regs[1];
+
+	of_property_read_string(np, "clock-output-names", &init.name);
+
+	init.ops = &zynq_pll_clk_ops;
+	parent_name = of_clk_get_parent_name(np, 0);
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	pll->hw.init = &init;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (WARN_ON(IS_ERR(clk)))
+		return;
+
+	ret = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	if (WARN_ON(ret))
+		return;
+}
+
+struct zynq_periph_clk {
+	struct clk_hw		hw;
+	struct clk_onecell_data	onecell_data;
+	struct clk		*gates[2];
+	void __iomem		*clk_ctrl;
+	spinlock_t		clkact_lock;
+};
+
+#define to_zynq_periph_clk(hw)	container_of(hw, struct zynq_periph_clk, hw)
+
+static const u8 periph_clk_parent_map[] = {
+	0, 0, 1, 2
+};
+#define PERIPH_CLK_CTRL_SRC(x)	(periph_clk_parent_map[((x) & 0x30) >> 4])
+#define PERIPH_CLK_CTRL_DIV(x)	(((x) & 0x3F00) >> 8)
+
+static unsigned long zynq_periph_recalc_rate(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	struct zynq_periph_clk *periph = to_zynq_periph_clk(hw);
+	return parent_rate / PERIPH_CLK_CTRL_DIV(ioread32(periph->clk_ctrl));
+}
+
+static u8 zynq_periph_get_parent(struct clk_hw *hw)
+{
+	struct zynq_periph_clk *periph = to_zynq_periph_clk(hw);
+	return PERIPH_CLK_CTRL_SRC(ioread32(periph->clk_ctrl));
+}
+
+static const struct clk_ops zynq_periph_clk_ops = {
+	.recalc_rate	= zynq_periph_recalc_rate,
+	.get_parent	= zynq_periph_get_parent,
+};
+
+static void __init zynq_periph_clk_setup(struct device_node *np)
+{
+	struct zynq_periph_clk *periph;
+	const char *parent_names[3];
+	struct clk_init_data init;
+	int clk_num = 0, err;
+	const char *name;
+	struct clk *clk;
+	u32 reg;
+	int i;
+
+	err = of_property_read_u32(np, "reg", &reg);
+	if (WARN_ON(err))
+		return;
+
+	periph = kzalloc(sizeof(*periph), GFP_KERNEL);
+	if (WARN_ON(!periph))
+		return;
+
+	periph->clk_ctrl = slcr_base + reg;
+	spin_lock_init(&periph->clkact_lock);
+
+	init.name = np->name;
+	init.ops = &zynq_periph_clk_ops;
+	for (i = 0; i < ARRAY_SIZE(parent_names); i++)
+		parent_names[i] = of_clk_get_parent_name(np, i);
+	init.parent_names = parent_names;
+	init.num_parents = ARRAY_SIZE(parent_names);
+
+	periph->hw.init = &init;
+
+	clk = clk_register(NULL, &periph->hw);
+	if (WARN_ON(IS_ERR(clk)))
+		return;
+
+	err = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	if (WARN_ON(err))
+		return;
+
+	err = of_property_read_string_index(np, "clock-output-names", 0,
+					    &name);
+	if (WARN_ON(err))
+		return;
+
+	periph->gates[0] = clk_register_gate(NULL, name, np->name, 0,
+					     periph->clk_ctrl, 0, 0,
+					     &periph->clkact_lock);
+	if (WARN_ON(IS_ERR(periph->gates[0])))
+		return;
+	clk_num++;
+
+	/* some periph clks have 2 downstream gates */
+	err = of_property_read_string_index(np, "clock-output-names", 1,
+					    &name);
+	if (err != -ENODATA) {
+		periph->gates[1] = clk_register_gate(NULL, name, np->name, 0,
+						     periph->clk_ctrl, 1, 0,
+						     &periph->clkact_lock);
+		if (WARN_ON(IS_ERR(periph->gates[1])))
+			return;
+		clk_num++;
+	}
+
+	periph->onecell_data.clks = periph->gates;
+	periph->onecell_data.clk_num = clk_num;
+
+	err = of_clk_add_provider(np, of_clk_src_onecell_get,
+				  &periph->onecell_data);
+	if (WARN_ON(err))
+		return;
+}
+
+/* CPU Clock domain is modelled as a mux with 4 children subclks, whose
+ * derivative rates depend on CLK_621_TRUE
+ */
+
+struct zynq_cpu_clk {
+	struct clk_hw		hw;
+	struct clk_onecell_data	onecell_data;
+	struct clk		*subclks[4];
+	void __iomem		*clk_ctrl;
+	spinlock_t		clkact_lock;
+};
+
+#define to_zynq_cpu_clk(hw)	container_of(hw, struct zynq_cpu_clk, hw)
+
+static const u8 zynq_cpu_clk_parent_map[] = {
+	1, 1, 2, 0
+};
+#define CPU_CLK_SRCSEL(x)	(zynq_cpu_clk_parent_map[(((x) & 0x30) >> 4)])
+#define CPU_CLK_CTRL_DIV(x)	(((x) & 0x3F00) >> 8)
+
+static u8 zynq_cpu_clk_get_parent(struct clk_hw *hw)
+{
+	struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(hw);
+	return CPU_CLK_SRCSEL(ioread32(cpuclk->clk_ctrl));
+}
+
+static unsigned long zynq_cpu_clk_recalc_rate(struct clk_hw *hw,
+					      unsigned long parent_rate)
+{
+	struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(hw);
+	return parent_rate / CPU_CLK_CTRL_DIV(ioread32(cpuclk->clk_ctrl));
+}
+
+static const struct clk_ops zynq_cpu_clk_ops = {
+	.get_parent	= zynq_cpu_clk_get_parent,
+	.recalc_rate	= zynq_cpu_clk_recalc_rate,
+};
+
+struct zynq_cpu_subclk {
+	struct clk_hw	hw;
+	void __iomem	*clk_621;
+	enum {
+		CPU_SUBCLK_6X4X,
+		CPU_SUBCLK_3X2X,
+		CPU_SUBCLK_2X,
+		CPU_SUBCLK_1X,
+	} which;
+};
+
+#define CLK_621_TRUE(x)	((x) & 1)
+
+#define to_zynq_cpu_subclk(hw)	container_of(hw, struct zynq_cpu_subclk, hw);
+
+static unsigned long zynq_cpu_subclk_recalc_rate(struct clk_hw *hw,
+						 unsigned long parent_rate)
+{
+	unsigned long uninitialized_var(rate);
+	struct zynq_cpu_subclk *subclk;
+	bool is_621;
+
+	subclk = to_zynq_cpu_subclk(hw)
+	is_621 = CLK_621_TRUE(ioread32(subclk->clk_621));
+
+	switch (subclk->which) {
+	case CPU_SUBCLK_6X4X:
+		rate = parent_rate;
+		break;
+	case CPU_SUBCLK_3X2X:
+		rate = parent_rate / 2;
+		break;
+	case CPU_SUBCLK_2X:
+		rate = parent_rate / (is_621 ? 3 : 2);
+		break;
+	case CPU_SUBCLK_1X:
+		rate = parent_rate / (is_621 ? 6 : 4);
+		break;
+	};
+
+	return rate;
+}
+
+static const struct clk_ops zynq_cpu_subclk_ops = {
+	.recalc_rate	= zynq_cpu_subclk_recalc_rate,
+};
+
+static struct clk *zynq_cpu_subclk_setup(struct device_node *np, u8 which,
+					 void __iomem *clk_621)
+{
+	struct zynq_cpu_subclk *subclk;
+	struct clk_init_data init;
+	struct clk *clk;
+	int err;
+
+	err = of_property_read_string_index(np, "clock-output-names",
+					    which, &init.name);
+	if (WARN_ON(err))
+		goto err_read_output_name;
+
+	subclk = kzalloc(sizeof(*subclk), GFP_KERNEL);
+	if (!subclk)
+		goto err_subclk_alloc;
+
+	subclk->clk_621 = clk_621;
+	subclk->which = which;
+
+	init.ops = &zynq_cpu_subclk_ops;
+	init.parent_names = &np->name;
+	init.num_parents = 1;
+
+	subclk->hw.init = &init;
+
+	clk = clk_register(NULL, &subclk->hw);
+	if (WARN_ON(IS_ERR(clk)))
+		goto err_clk_register;
+
+	return clk;
+
+err_clk_register:
+	kfree(subclk);
+err_subclk_alloc:
+err_read_output_name:
+	return ERR_PTR(-EINVAL);
+}
+
+static void __init zynq_cpu_clk_setup(struct device_node *np)
+{
+	struct zynq_cpu_clk *cpuclk;
+	const char *parent_names[3];
+	struct clk_init_data init;
+	void __iomem *clk_621;
+	struct clk *clk;
+	u32 reg[2];
+	int err;
+	int i;
+
+	err = of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg));
+	if (WARN_ON(err))
+		return;
+
+	cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
+	if (WARN_ON(!cpuclk))
+		return;
+
+	cpuclk->clk_ctrl = slcr_base + reg[0];
+	clk_621 = slcr_base + reg[1];
+	spin_lock_init(&cpuclk->clkact_lock);
+
+	init.name = np->name;
+	init.ops = &zynq_cpu_clk_ops;
+	for (i = 0; i < ARRAY_SIZE(parent_names); i++)
+		parent_names[i] = of_clk_get_parent_name(np, i);
+	init.parent_names = parent_names;
+	init.num_parents = ARRAY_SIZE(parent_names);
+
+	cpuclk->hw.init = &init;
+
+	clk = clk_register(NULL, &cpuclk->hw);
+	if (WARN_ON(IS_ERR(clk)))
+		return;
+
+	err = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	if (WARN_ON(err))
+		return;
+
+	for (i = 0; i < 4; i++) {
+		cpuclk->subclks[i] = zynq_cpu_subclk_setup(np, i, clk_621);
+		if (WARN_ON(IS_ERR(cpuclk->subclks[i])))
+			return;
+	}
+
+	cpuclk->onecell_data.clks = cpuclk->subclks;
+	cpuclk->onecell_data.clk_num = i;
+
+	err = of_clk_add_provider(np, of_clk_src_onecell_get,
+				  &cpuclk->onecell_data);
+	if (WARN_ON(err))
+		return;
+}
+
+static const __initconst struct of_device_id zynq_clk_match[] = {
+	{ .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
+	{ .compatible = "xlnx,zynq-pll", .data = zynq_pll_clk_setup, },
+	{ .compatible = "xlnx,zynq-periph-clock",
+		.data = zynq_periph_clk_setup, },
+	{ .compatible = "xlnx,zynq-cpu-clock", .data = zynq_cpu_clk_setup, },
+	{}
+};
+
+void __init xilinx_zynq_clocks_init(void __iomem *slcr)
+{
+	slcr_base = slcr;
+	of_clk_init(zynq_clk_match);
+}
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 56e4495e..9955ad7 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -17,6 +17,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/device.h>
 
 static DEFINE_SPINLOCK(enable_lock);
 static DEFINE_MUTEX(prepare_lock);
@@ -261,7 +262,7 @@ inline struct clk_hw *__clk_get_hw(struct clk *clk)
 
 inline u8 __clk_get_num_parents(struct clk *clk)
 {
-	return !clk ? -EINVAL : clk->num_parents;
+	return !clk ? 0 : clk->num_parents;
 }
 
 inline struct clk *__clk_get_parent(struct clk *clk)
@@ -269,14 +270,14 @@ inline struct clk *__clk_get_parent(struct clk *clk)
 	return !clk ? NULL : clk->parent;
 }
 
-inline int __clk_get_enable_count(struct clk *clk)
+inline unsigned int __clk_get_enable_count(struct clk *clk)
 {
-	return !clk ? -EINVAL : clk->enable_count;
+	return !clk ? 0 : clk->enable_count;
 }
 
-inline int __clk_get_prepare_count(struct clk *clk)
+inline unsigned int __clk_get_prepare_count(struct clk *clk)
 {
-	return !clk ? -EINVAL : clk->prepare_count;
+	return !clk ? 0 : clk->prepare_count;
 }
 
 unsigned long __clk_get_rate(struct clk *clk)
@@ -302,15 +303,15 @@ out:
 
 inline unsigned long __clk_get_flags(struct clk *clk)
 {
-	return !clk ? -EINVAL : clk->flags;
+	return !clk ? 0 : clk->flags;
 }
 
-int __clk_is_enabled(struct clk *clk)
+bool __clk_is_enabled(struct clk *clk)
 {
 	int ret;
 
 	if (!clk)
-		return -EINVAL;
+		return false;
 
 	/*
 	 * .is_enabled is only mandatory for clocks that gate
@@ -323,7 +324,7 @@ int __clk_is_enabled(struct clk *clk)
 
 	ret = clk->ops->is_enabled(clk->hw);
 out:
-	return ret;
+	return !!ret;
 }
 
 static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
@@ -568,7 +569,7 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
 	unsigned long parent_rate = 0;
 
 	if (!clk)
-		return -EINVAL;
+		return 0;
 
 	if (!clk->ops->round_rate) {
 		if (clk->flags & CLK_SET_RATE_PARENT)
@@ -1297,12 +1298,20 @@ int __clk_init(struct device *dev, struct clk *clk)
 	 * walk the list of orphan clocks and reparent any that are children of
 	 * this clock
 	 */
-	hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list, child_node)
+	hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list, child_node) {
+		if (orphan->ops->get_parent) {
+			i = orphan->ops->get_parent(orphan->hw);
+			if (!strcmp(clk->name, orphan->parent_names[i]))
+				__clk_reparent(orphan, clk);
+			continue;
+		}
+
 		for (i = 0; i < orphan->num_parents; i++)
 			if (!strcmp(clk->name, orphan->parent_names[i])) {
 				__clk_reparent(orphan, clk);
 				break;
 			}
+	 }
 
 	/*
 	 * optional platform-specific magic
@@ -1361,28 +1370,9 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
 }
 EXPORT_SYMBOL_GPL(__clk_register);
 
-/**
- * clk_register - allocate a new clock, register it and return an opaque cookie
- * @dev: device that is registering this clock
- * @hw: link to hardware-specific clock data
- *
- * clk_register is the primary interface for populating the clock tree with new
- * clock nodes.  It returns a pointer to the newly allocated struct clk which
- * cannot be dereferenced by driver code but may be used in conjuction with the
- * rest of the clock API.  In the event of an error clk_register will return an
- * error code; drivers must test for an error code after calling clk_register.
- */
-struct clk *clk_register(struct device *dev, struct clk_hw *hw)
+static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
 {
 	int i, ret;
-	struct clk *clk;
-
-	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
-	if (!clk) {
-		pr_err("%s: could not allocate clk\n", __func__);
-		ret = -ENOMEM;
-		goto fail_out;
-	}
 
 	clk->name = kstrdup(hw->init->name, GFP_KERNEL);
 	if (!clk->name) {
@@ -1420,7 +1410,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 
 	ret = __clk_init(dev, clk);
 	if (!ret)
-		return clk;
+		return 0;
 
 fail_parent_names_copy:
 	while (--i >= 0)
@@ -1429,6 +1419,36 @@ fail_parent_names_copy:
 fail_parent_names:
 	kfree(clk->name);
 fail_name:
+	return ret;
+}
+
+/**
+ * clk_register - allocate a new clock, register it and return an opaque cookie
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * clk_register is the primary interface for populating the clock tree with new
+ * clock nodes.  It returns a pointer to the newly allocated struct clk which
+ * cannot be dereferenced by driver code but may be used in conjuction with the
+ * rest of the clock API.  In the event of an error clk_register will return an
+ * error code; drivers must test for an error code after calling clk_register.
+ */
+struct clk *clk_register(struct device *dev, struct clk_hw *hw)
+{
+	int ret;
+	struct clk *clk;
+
+	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+	if (!clk) {
+		pr_err("%s: could not allocate clk\n", __func__);
+		ret = -ENOMEM;
+		goto fail_out;
+	}
+
+	ret = _clk_register(dev, hw, clk);
+	if (!ret)
+		return clk;
+
 	kfree(clk);
 fail_out:
 	return ERR_PTR(ret);
@@ -1444,6 +1464,63 @@ EXPORT_SYMBOL_GPL(clk_register);
 void clk_unregister(struct clk *clk) {}
 EXPORT_SYMBOL_GPL(clk_unregister);
 
+static void devm_clk_release(struct device *dev, void *res)
+{
+	clk_unregister(res);
+}
+
+/**
+ * devm_clk_register - resource managed clk_register()
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * Managed clk_register(). Clocks returned from this function are
+ * automatically clk_unregister()ed on driver detach. See clk_register() for
+ * more information.
+ */
+struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)
+{
+	struct clk *clk;
+	int ret;
+
+	clk = devres_alloc(devm_clk_release, sizeof(*clk), GFP_KERNEL);
+	if (!clk)
+		return ERR_PTR(-ENOMEM);
+
+	ret = _clk_register(dev, hw, clk);
+	if (!ret) {
+		devres_add(dev, clk);
+	} else {
+		devres_free(clk);
+		clk = ERR_PTR(ret);
+	}
+
+	return clk;
+}
+EXPORT_SYMBOL_GPL(devm_clk_register);
+
+static int devm_clk_match(struct device *dev, void *res, void *data)
+{
+	struct clk *c = res;
+	if (WARN_ON(!c))
+		return 0;
+	return c == data;
+}
+
+/**
+ * devm_clk_unregister - resource managed clk_unregister()
+ * @clk: clock to unregister
+ *
+ * Deallocate a clock allocated with devm_clk_register(). Normally
+ * this function will not need to be called and the resource management
+ * code will ensure that the resource is freed.
+ */
+void devm_clk_unregister(struct device *dev, struct clk *clk)
+{
+	WARN_ON(devres_release(dev, devm_clk_release, devm_clk_match, clk));
+}
+EXPORT_SYMBOL_GPL(devm_clk_unregister);
+
 /***        clk rate change notifiers        ***/
 
 /**
diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c
index f00dffb..8dd476e 100644
--- a/drivers/clk/mxs/clk-imx23.c
+++ b/drivers/clk/mxs/clk-imx23.c
@@ -85,7 +85,7 @@ enum imx23_clk {
 	cpu_xtal, hbus, xbus, lcdif_div, ssp_div, gpmi_div, emi_pll,
 	emi_xtal, etm_div, saif_div, clk32k_div, rtc, adc, spdif_div,
 	clk32k, dri, pwm, filt, uart, ssp, gpmi, spdif, emi, saif,
-	lcdif, etm, usb, usb_pwr,
+	lcdif, etm, usb, usb_phy,
 	clk_max
 };
 
@@ -143,8 +143,8 @@ int __init mx23_clocks_init(void)
 	clks[saif] = mxs_clk_gate("saif", "saif_div", SAIF, 31);
 	clks[lcdif] = mxs_clk_gate("lcdif", "lcdif_div", PIX, 31);
 	clks[etm] = mxs_clk_gate("etm", "etm_div", ETM, 31);
-	clks[usb] = mxs_clk_gate("usb", "usb_pwr", DIGCTRL, 2);
-	clks[usb_pwr] = clk_register_gate(NULL, "usb_pwr", "pll", 0, PLLCTRL0, 18, 0, &mxs_lock);
+	clks[usb] = mxs_clk_gate("usb", "usb_phy", DIGCTRL, 2);
+	clks[usb_phy] = clk_register_gate(NULL, "usb_phy", "pll", 0, PLLCTRL0, 18, 0, &mxs_lock);
 
 	for (i = 0; i < ARRAY_SIZE(clks); i++)
 		if (IS_ERR(clks[i])) {
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index 42978f1b..db3af08 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -140,7 +140,7 @@ enum imx28_clk {
 	emi_xtal, lcdif_div, etm_div, ptp, saif0_div, saif1_div,
 	clk32k_div, rtc, lradc, spdif_div, clk32k, pwm, uart, ssp0,
 	ssp1, ssp2, ssp3, gpmi, spdif, emi, saif0, saif1, lcdif, etm,
-	fec, can0, can1, usb0, usb1, usb0_pwr, usb1_pwr, enet_out,
+	fec, can0, can1, usb0, usb1, usb0_phy, usb1_phy, enet_out,
 	clk_max
 };
 
@@ -218,10 +218,10 @@ int __init mx28_clocks_init(void)
 	clks[fec] = mxs_clk_gate("fec", "hbus", ENET, 30);
 	clks[can0] = mxs_clk_gate("can0", "ref_xtal", FLEXCAN, 30);
 	clks[can1] = mxs_clk_gate("can1", "ref_xtal", FLEXCAN, 28);
-	clks[usb0] = mxs_clk_gate("usb0", "usb0_pwr", DIGCTRL, 2);
-	clks[usb1] = mxs_clk_gate("usb1", "usb1_pwr", DIGCTRL, 16);
-	clks[usb0_pwr] = clk_register_gate(NULL, "usb0_pwr", "pll0", 0, PLL0CTRL0, 18, 0, &mxs_lock);
-	clks[usb1_pwr] = clk_register_gate(NULL, "usb1_pwr", "pll1", 0, PLL1CTRL0, 18, 0, &mxs_lock);
+	clks[usb0] = mxs_clk_gate("usb0", "usb0_phy", DIGCTRL, 2);
+	clks[usb1] = mxs_clk_gate("usb1", "usb1_phy", DIGCTRL, 16);
+	clks[usb0_phy] = clk_register_gate(NULL, "usb0_phy", "pll0", 0, PLL0CTRL0, 18, 0, &mxs_lock);
+	clks[usb1_phy] = clk_register_gate(NULL, "usb1_phy", "pll1", 0, PLL1CTRL0, 18, 0, &mxs_lock);
 	clks[enet_out] = clk_register_gate(NULL, "enet_out", "pll2", 0, ENET, 18, 0, &mxs_lock);
 
 	for (i = 0; i < ARRAY_SIZE(clks); i++)
diff --git a/drivers/clk/spear/clk-aux-synth.c b/drivers/clk/spear/clk-aux-synth.c
index 6756e7c..bdfb442 100644
--- a/drivers/clk/spear/clk-aux-synth.c
+++ b/drivers/clk/spear/clk-aux-synth.c
@@ -179,7 +179,8 @@ struct clk *clk_register_aux(const char *aux_name, const char *gate_name,
 	if (gate_name) {
 		struct clk *tgate_clk;
 
-		tgate_clk = clk_register_gate(NULL, gate_name, aux_name, 0, reg,
+		tgate_clk = clk_register_gate(NULL, gate_name, aux_name,
+				CLK_SET_RATE_PARENT, reg,
 				aux->masks->enable_bit, 0, lock);
 		if (IS_ERR_OR_NULL(tgate_clk))
 			goto free_aux;
diff --git a/drivers/clk/spear/clk-vco-pll.c b/drivers/clk/spear/clk-vco-pll.c
index 5f1b6ba..1b9b65b 100644
--- a/drivers/clk/spear/clk-vco-pll.c
+++ b/drivers/clk/spear/clk-vco-pll.c
@@ -147,7 +147,7 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long drate,
 	struct clk_pll *pll = to_clk_pll(hw);
 	struct pll_rate_tbl *rtbl = pll->vco->rtbl;
 	unsigned long flags = 0, val;
-	int i;
+	int uninitialized_var(i);
 
 	clk_pll_round_rate_index(hw, drate, NULL, &i);
 
diff --git a/drivers/clk/spear/clk.c b/drivers/clk/spear/clk.c
index 7cd6378..628b6d5 100644
--- a/drivers/clk/spear/clk.c
+++ b/drivers/clk/spear/clk.c
@@ -32,5 +32,8 @@ long clk_round_rate_index(struct clk_hw *hw, unsigned long drate,
 		}
 	}
 
+	if ((*index) == rtbl_cnt)
+		(*index)--;
+
 	return rate;
 }
diff --git a/drivers/clk/spear/spear1310_clock.c b/drivers/clk/spear/spear1310_clock.c
index 0fcec2a..ed9af42 100644
--- a/drivers/clk/spear/spear1310_clock.c
+++ b/drivers/clk/spear/spear1310_clock.c
@@ -20,6 +20,7 @@
 #include <mach/spear.h>
 #include "clk.h"
 
+#define VA_SPEAR1310_RAS_BASE			IOMEM(UL(0xFA400000))
 /* PLL related registers and bit values */
 #define SPEAR1310_PLL_CFG			(VA_MISC_BASE + 0x210)
 	/* PLL_CFG bit values */
@@ -313,6 +314,20 @@ static struct aux_clk_masks i2s_sclk_masks = {
 /* i2s prs1 aux rate configuration table, in ascending order of rates */
 static struct aux_rate_tbl i2s_prs1_rtbl[] = {
 	/* For parent clk = 49.152 MHz */
+	{.xscale = 1, .yscale = 12, .eq = 0}, /* 2.048 MHz, smp freq = 8Khz */
+	{.xscale = 11, .yscale = 96, .eq = 0}, /* 2.816 MHz, smp freq = 11Khz */
+	{.xscale = 1, .yscale = 6, .eq = 0}, /* 4.096 MHz, smp freq = 16Khz */
+	{.xscale = 11, .yscale = 48, .eq = 0}, /* 5.632 MHz, smp freq = 22Khz */
+
+	/*
+	 * with parent clk = 49.152, freq gen is 8.192 MHz, smp freq = 32Khz
+	 * with parent clk = 12.288, freq gen is 2.048 MHz, smp freq = 8Khz
+	 */
+	{.xscale = 1, .yscale = 3, .eq = 0},
+
+	/* For parent clk = 49.152 MHz */
+	{.xscale = 17, .yscale = 37, .eq = 0}, /* 11.289 MHz, smp freq = 44Khz*/
+
 	{.xscale = 1, .yscale = 2, .eq = 0}, /* 12.288 MHz */
 };
 
@@ -374,9 +389,6 @@ void __init spear1310_clk_init(void)
 {
 	struct clk *clk, *clk1;
 
-	clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
-	clk_register_clkdev(clk, "apb_pclk", NULL);
-
 	clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, CLK_IS_ROOT,
 			32000);
 	clk_register_clkdev(clk, "osc_32k_clk", NULL);
@@ -401,7 +413,7 @@ void __init spear1310_clk_init(void)
 	clk = clk_register_gate(NULL, "rtc-spear", "osc_32k_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_RTC_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, NULL, "fc900000.rtc");
+	clk_register_clkdev(clk, NULL, "e0580000.rtc");
 
 	/* clock derived from 24 or 25 MHz osc clk */
 	/* vco-pll */
@@ -483,13 +495,18 @@ void __init spear1310_clk_init(void)
 	clk_register_clkdev(clk, "ddr_clk", NULL);
 
 	/* clock derived from pll1 clk */
-	clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk", 0, 1, 2);
+	clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk",
+			CLK_SET_RATE_PARENT, 1, 2);
 	clk_register_clkdev(clk, "cpu_clk", NULL);
 
 	clk = clk_register_fixed_factor(NULL, "wdt_clk", "cpu_clk", 0, 1,
 			2);
 	clk_register_clkdev(clk, NULL, "ec800620.wdt");
 
+	clk = clk_register_fixed_factor(NULL, "smp_twd_clk", "cpu_clk", 0, 1,
+			2);
+	clk_register_clkdev(clk, NULL, "smp_twd");
+
 	clk = clk_register_fixed_factor(NULL, "ahb_clk", "pll1_clk", 0, 1,
 			6);
 	clk_register_clkdev(clk, "ahb_clk", NULL);
@@ -547,14 +564,14 @@ void __init spear1310_clk_init(void)
 	clk_register_clkdev(clk1, "uart_syn_gclk", NULL);
 
 	clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
-			ARRAY_SIZE(uart0_parents), 0, SPEAR1310_PERIP_CLK_CFG,
-			SPEAR1310_UART_CLK_SHIFT, SPEAR1310_UART_CLK_MASK, 0,
-			&_lock);
+			ARRAY_SIZE(uart0_parents), CLK_SET_RATE_PARENT,
+			SPEAR1310_PERIP_CLK_CFG, SPEAR1310_UART_CLK_SHIFT,
+			SPEAR1310_UART_CLK_MASK, 0, &_lock);
 	clk_register_clkdev(clk, "uart0_mclk", NULL);
 
-	clk = clk_register_gate(NULL, "uart0_clk", "uart0_mclk", 0,
-			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_UART_CLK_ENB, 0,
-			&_lock);
+	clk = clk_register_gate(NULL, "uart0_clk", "uart0_mclk",
+			CLK_SET_RATE_PARENT, SPEAR1310_PERIP1_CLK_ENB,
+			SPEAR1310_UART_CLK_ENB, 0, &_lock);
 	clk_register_clkdev(clk, NULL, "e0000000.serial");
 
 	clk = clk_register_aux("sdhci_syn_clk", "sdhci_syn_gclk",
@@ -563,9 +580,9 @@ void __init spear1310_clk_init(void)
 	clk_register_clkdev(clk, "sdhci_syn_clk", NULL);
 	clk_register_clkdev(clk1, "sdhci_syn_gclk", NULL);
 
-	clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_syn_gclk", 0,
-			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_SDHCI_CLK_ENB, 0,
-			&_lock);
+	clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_syn_gclk",
+			CLK_SET_RATE_PARENT, SPEAR1310_PERIP1_CLK_ENB,
+			SPEAR1310_SDHCI_CLK_ENB, 0, &_lock);
 	clk_register_clkdev(clk, NULL, "b3000000.sdhci");
 
 	clk = clk_register_aux("cfxd_syn_clk", "cfxd_syn_gclk", "vco1div2_clk",
@@ -574,9 +591,9 @@ void __init spear1310_clk_init(void)
 	clk_register_clkdev(clk, "cfxd_syn_clk", NULL);
 	clk_register_clkdev(clk1, "cfxd_syn_gclk", NULL);
 
-	clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_syn_gclk", 0,
-			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_CFXD_CLK_ENB, 0,
-			&_lock);
+	clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_syn_gclk",
+			CLK_SET_RATE_PARENT, SPEAR1310_PERIP1_CLK_ENB,
+			SPEAR1310_CFXD_CLK_ENB, 0, &_lock);
 	clk_register_clkdev(clk, NULL, "b2800000.cf");
 	clk_register_clkdev(clk, NULL, "arasan_xd");
 
@@ -587,9 +604,9 @@ void __init spear1310_clk_init(void)
 	clk_register_clkdev(clk1, "c3_syn_gclk", NULL);
 
 	clk = clk_register_mux(NULL, "c3_mclk", c3_parents,
-			ARRAY_SIZE(c3_parents), 0, SPEAR1310_PERIP_CLK_CFG,
-			SPEAR1310_C3_CLK_SHIFT, SPEAR1310_C3_CLK_MASK, 0,
-			&_lock);
+			ARRAY_SIZE(c3_parents), CLK_SET_RATE_PARENT,
+			SPEAR1310_PERIP_CLK_CFG, SPEAR1310_C3_CLK_SHIFT,
+			SPEAR1310_C3_CLK_MASK, 0, &_lock);
 	clk_register_clkdev(clk, "c3_mclk", NULL);
 
 	clk = clk_register_gate(NULL, "c3_clk", "c3_mclk", 0,
@@ -615,7 +632,7 @@ void __init spear1310_clk_init(void)
 			ARRAY_SIZE(gmac_phy_parents), 0,
 			SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GMAC_PHY_CLK_SHIFT,
 			SPEAR1310_GMAC_PHY_CLK_MASK, 0, &_lock);
-	clk_register_clkdev(clk, NULL, "stmmacphy.0");
+	clk_register_clkdev(clk, "stmmacphy.0", NULL);
 
 	/* clcd */
 	clk = clk_register_mux(NULL, "clcd_syn_mclk", clcd_synth_parents,
@@ -630,22 +647,22 @@ void __init spear1310_clk_init(void)
 	clk_register_clkdev(clk, "clcd_syn_clk", NULL);
 
 	clk = clk_register_mux(NULL, "clcd_pixel_mclk", clcd_pixel_parents,
-			ARRAY_SIZE(clcd_pixel_parents), 0,
+			ARRAY_SIZE(clcd_pixel_parents), CLK_SET_RATE_PARENT,
 			SPEAR1310_PERIP_CLK_CFG, SPEAR1310_CLCD_CLK_SHIFT,
 			SPEAR1310_CLCD_CLK_MASK, 0, &_lock);
-	clk_register_clkdev(clk, "clcd_pixel_clk", NULL);
+	clk_register_clkdev(clk, "clcd_pixel_mclk", NULL);
 
 	clk = clk_register_gate(NULL, "clcd_clk", "clcd_pixel_mclk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_CLCD_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, "clcd_clk", NULL);
+	clk_register_clkdev(clk, NULL, "e1000000.clcd");
 
 	/* i2s */
 	clk = clk_register_mux(NULL, "i2s_src_mclk", i2s_src_parents,
 			ARRAY_SIZE(i2s_src_parents), 0, SPEAR1310_I2S_CLK_CFG,
 			SPEAR1310_I2S_SRC_CLK_SHIFT, SPEAR1310_I2S_SRC_CLK_MASK,
 			0, &_lock);
-	clk_register_clkdev(clk, "i2s_src_clk", NULL);
+	clk_register_clkdev(clk, "i2s_src_mclk", NULL);
 
 	clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk", 0,
 			SPEAR1310_I2S_CLK_CFG, &i2s_prs1_masks, i2s_prs1_rtbl,
@@ -653,10 +670,10 @@ void __init spear1310_clk_init(void)
 	clk_register_clkdev(clk, "i2s_prs1_clk", NULL);
 
 	clk = clk_register_mux(NULL, "i2s_ref_mclk", i2s_ref_parents,
-			ARRAY_SIZE(i2s_ref_parents), 0, SPEAR1310_I2S_CLK_CFG,
-			SPEAR1310_I2S_REF_SHIFT, SPEAR1310_I2S_REF_SEL_MASK, 0,
-			&_lock);
-	clk_register_clkdev(clk, "i2s_ref_clk", NULL);
+			ARRAY_SIZE(i2s_ref_parents), CLK_SET_RATE_PARENT,
+			SPEAR1310_I2S_CLK_CFG, SPEAR1310_I2S_REF_SHIFT,
+			SPEAR1310_I2S_REF_SEL_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "i2s_ref_mclk", NULL);
 
 	clk = clk_register_gate(NULL, "i2s_ref_pad_clk", "i2s_ref_mclk", 0,
 			SPEAR1310_PERIP2_CLK_ENB, SPEAR1310_I2S_REF_PAD_CLK_ENB,
@@ -664,7 +681,7 @@ void __init spear1310_clk_init(void)
 	clk_register_clkdev(clk, "i2s_ref_pad_clk", NULL);
 
 	clk = clk_register_aux("i2s_sclk_clk", "i2s_sclk_gclk",
-			"i2s_ref_pad_clk", 0, SPEAR1310_I2S_CLK_CFG,
+			"i2s_ref_mclk", 0, SPEAR1310_I2S_CLK_CFG,
 			&i2s_sclk_masks, i2s_sclk_rtbl,
 			ARRAY_SIZE(i2s_sclk_rtbl), &_lock, &clk1);
 	clk_register_clkdev(clk, "i2s_sclk_clk", NULL);
@@ -705,35 +722,37 @@ void __init spear1310_clk_init(void)
 	clk = clk_register_gate(NULL, "usbh0_clk", "ahb_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_UHC0_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, "usbh.0_clk", NULL);
+	clk_register_clkdev(clk, NULL, "e4000000.ohci");
+	clk_register_clkdev(clk, NULL, "e4800000.ehci");
 
 	clk = clk_register_gate(NULL, "usbh1_clk", "ahb_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_UHC1_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, "usbh.1_clk", NULL);
+	clk_register_clkdev(clk, NULL, "e5000000.ohci");
+	clk_register_clkdev(clk, NULL, "e5800000.ehci");
 
 	clk = clk_register_gate(NULL, "uoc_clk", "ahb_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_UOC_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, NULL, "uoc");
+	clk_register_clkdev(clk, NULL, "e3800000.otg");
 
 	clk = clk_register_gate(NULL, "pcie_sata_0_clk", "ahb_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_0_CLK_ENB,
 			0, &_lock);
 	clk_register_clkdev(clk, NULL, "dw_pcie.0");
-	clk_register_clkdev(clk, NULL, "ahci.0");
+	clk_register_clkdev(clk, NULL, "b1000000.ahci");
 
 	clk = clk_register_gate(NULL, "pcie_sata_1_clk", "ahb_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_1_CLK_ENB,
 			0, &_lock);
 	clk_register_clkdev(clk, NULL, "dw_pcie.1");
-	clk_register_clkdev(clk, NULL, "ahci.1");
+	clk_register_clkdev(clk, NULL, "b1800000.ahci");
 
 	clk = clk_register_gate(NULL, "pcie_sata_2_clk", "ahb_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_2_CLK_ENB,
 			0, &_lock);
 	clk_register_clkdev(clk, NULL, "dw_pcie.2");
-	clk_register_clkdev(clk, NULL, "ahci.2");
+	clk_register_clkdev(clk, NULL, "b4000000.ahci");
 
 	clk = clk_register_gate(NULL, "sysram0_clk", "ahb_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_SYSRAM0_CLK_ENB, 0,
@@ -751,10 +770,10 @@ void __init spear1310_clk_init(void)
 	clk_register_clkdev(clk, "adc_syn_clk", NULL);
 	clk_register_clkdev(clk1, "adc_syn_gclk", NULL);
 
-	clk = clk_register_gate(NULL, "adc_clk", "adc_syn_gclk", 0,
-			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_ADC_CLK_ENB, 0,
-			&_lock);
-	clk_register_clkdev(clk, NULL, "adc_clk");
+	clk = clk_register_gate(NULL, "adc_clk", "adc_syn_gclk",
+			CLK_SET_RATE_PARENT, SPEAR1310_PERIP1_CLK_ENB,
+			SPEAR1310_ADC_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "e0080000.adc");
 
 	/* clock derived from apb clk */
 	clk = clk_register_gate(NULL, "ssp0_clk", "apb_clk", 0,
@@ -916,15 +935,15 @@ void __init spear1310_clk_init(void)
 			SPEAR1310_RAS_CTRL_REG1,
 			SPEAR1310_SMII_RGMII_PHY_CLK_SHIFT,
 			SPEAR1310_PHY_CLK_MASK, 0, &_lock);
-	clk_register_clkdev(clk, NULL, "stmmacphy.1");
-	clk_register_clkdev(clk, NULL, "stmmacphy.2");
-	clk_register_clkdev(clk, NULL, "stmmacphy.4");
+	clk_register_clkdev(clk, "stmmacphy.1", NULL);
+	clk_register_clkdev(clk, "stmmacphy.2", NULL);
+	clk_register_clkdev(clk, "stmmacphy.4", NULL);
 
 	clk = clk_register_mux(NULL, "rmii_phy_mclk", rmii_phy_parents,
 			ARRAY_SIZE(rmii_phy_parents), 0,
 			SPEAR1310_RAS_CTRL_REG1, SPEAR1310_RMII_PHY_CLK_SHIFT,
 			SPEAR1310_PHY_CLK_MASK, 0, &_lock);
-	clk_register_clkdev(clk, NULL, "stmmacphy.3");
+	clk_register_clkdev(clk, "stmmacphy.3", NULL);
 
 	clk = clk_register_mux(NULL, "uart1_mclk", uart_parents,
 			ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0,
diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c
index 2352cee..82abea3 100644
--- a/drivers/clk/spear/spear1340_clock.c
+++ b/drivers/clk/spear/spear1340_clock.c
@@ -190,6 +190,7 @@ static struct pll_rate_tbl pll4_rtbl[] = {
  * different values of vco1div2
  */
 static struct frac_rate_tbl amba_synth_rtbl[] = {
+	{.div = 0x073A8}, /* for vco1div2 = 600 MHz */
 	{.div = 0x06062}, /* for vco1div2 = 500 MHz */
 	{.div = 0x04D1B}, /* for vco1div2 = 400 MHz */
 	{.div = 0x04000}, /* for vco1div2 = 332 MHz */
@@ -220,6 +221,12 @@ static struct frac_rate_tbl amba_synth_rtbl[] = {
  * 500			400		200			0x02800
  * 500			500		250			0x02000
  * --------------------------------------------------------------------
+ * 600			200		100			0x06000
+ * 600			250		125			0x04CCE
+ * 600			332		166			0x039D5
+ * 600			400		200			0x03000
+ * 600			500		250			0x02666
+ * --------------------------------------------------------------------
  * 664			200		100			0x06a38
  * 664			250		125			0x054FD
  * 664			332		166			0x04000
@@ -238,28 +245,50 @@ static struct frac_rate_tbl sys_synth_rtbl[] = {
 	{.div = 0x08000},
 	{.div = 0x06a38},
 	{.div = 0x06666},
+	{.div = 0x06000},
 	{.div = 0x054FD},
 	{.div = 0x05000},
 	{.div = 0x04D18},
+	{.div = 0x04CCE},
 	{.div = 0x04000},
+	{.div = 0x039D5},
 	{.div = 0x0351E},
 	{.div = 0x03333},
 	{.div = 0x03031},
+	{.div = 0x03000},
 	{.div = 0x02A7E},
 	{.div = 0x02800},
 	{.div = 0x0268D},
+	{.div = 0x02666},
 	{.div = 0x02000},
 };
 
 /* aux rate configuration table, in ascending order of rates */
 static struct aux_rate_tbl aux_rtbl[] = {
-	/* For VCO1div2 = 500 MHz */
-	{.xscale = 10, .yscale = 204, .eq = 0}, /* 12.29 MHz */
-	{.xscale = 4, .yscale = 21, .eq = 0}, /* 48 MHz */
-	{.xscale = 2, .yscale = 6, .eq = 0}, /* 83 MHz */
-	{.xscale = 2, .yscale = 4, .eq = 0}, /* 125 MHz */
-	{.xscale = 1, .yscale = 3, .eq = 1}, /* 166 MHz */
-	{.xscale = 1, .yscale = 2, .eq = 1}, /* 250 MHz */
+	/* 12.29MHz for vic1div2=600MHz and 10.24MHz for VCO1div2=500MHz */
+	{.xscale = 5, .yscale = 122, .eq = 0},
+	/* 14.70MHz for vic1div2=600MHz and 12.29MHz for VCO1div2=500MHz */
+	{.xscale = 10, .yscale = 204, .eq = 0},
+	/* 48MHz for vic1div2=600MHz and 40 MHz for VCO1div2=500MHz */
+	{.xscale = 4, .yscale = 25, .eq = 0},
+	/* 57.14MHz for vic1div2=600MHz and 48 MHz for VCO1div2=500MHz */
+	{.xscale = 4, .yscale = 21, .eq = 0},
+	/* 83.33MHz for vic1div2=600MHz and 69.44MHz for VCO1div2=500MHz */
+	{.xscale = 5, .yscale = 18, .eq = 0},
+	/* 100MHz for vic1div2=600MHz and 83.33 MHz for VCO1div2=500MHz */
+	{.xscale = 2, .yscale = 6, .eq = 0},
+	/* 125MHz for vic1div2=600MHz and 104.1MHz for VCO1div2=500MHz */
+	{.xscale = 5, .yscale = 12, .eq = 0},
+	/* 150MHz for vic1div2=600MHz and 125MHz for VCO1div2=500MHz */
+	{.xscale = 2, .yscale = 4, .eq = 0},
+	/* 166MHz for vic1div2=600MHz and 138.88MHz for VCO1div2=500MHz */
+	{.xscale = 5, .yscale = 18, .eq = 1},
+	/* 200MHz for vic1div2=600MHz and 166MHz for VCO1div2=500MHz */
+	{.xscale = 1, .yscale = 3, .eq = 1},
+	/* 250MHz for vic1div2=600MHz and 208.33MHz for VCO1div2=500MHz */
+	{.xscale = 5, .yscale = 12, .eq = 1},
+	/* 300MHz for vic1div2=600MHz and 250MHz for VCO1div2=500MHz */
+	{.xscale = 1, .yscale = 2, .eq = 1},
 };
 
 /* gmac rate configuration table, in ascending order of rates */
@@ -273,16 +302,23 @@ static struct aux_rate_tbl gmac_rtbl[] = {
 
 /* clcd rate configuration table, in ascending order of rates */
 static struct frac_rate_tbl clcd_rtbl[] = {
+	{.div = 0x18000}, /* 25 Mhz , for vc01div4 = 300 MHz*/
+	{.div = 0x1638E}, /* 27 Mhz , for vc01div4 = 300 MHz*/
 	{.div = 0x14000}, /* 25 Mhz , for vc01div4 = 250 MHz*/
 	{.div = 0x1284B}, /* 27 Mhz , for vc01div4 = 250 MHz*/
 	{.div = 0x0D8D3}, /* 58 Mhz , for vco1div4 = 393 MHz */
 	{.div = 0x0B72C}, /* 58 Mhz , for vco1div4 = 332 MHz */
+	{.div = 0x0A584}, /* 58 Mhz , for vco1div4 = 300 MHz */
+	{.div = 0x093B1}, /* 65 Mhz , for vc01div4 = 300 MHz*/
 	{.div = 0x089EE}, /* 58 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x081BA}, /* 74 Mhz , for vc01div4 = 300 MHz*/
 	{.div = 0x07BA0}, /* 65 Mhz , for vc01div4 = 250 MHz*/
 	{.div = 0x06f1C}, /* 72 Mhz , for vc01div4 = 250 MHz*/
 	{.div = 0x06E58}, /* 58 Mhz , for vco1div4 = 200 MHz */
 	{.div = 0x06c1B}, /* 74 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x058E3}, /* 108 Mhz , for vc01div4 = 300 MHz*/
 	{.div = 0x04A12}, /* 108 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x040A5}, /* 148.5 Mhz , for vc01div4 = 300 MHz*/
 	{.div = 0x0378E}, /* 144 Mhz , for vc01div4 = 250 MHz*/
 	{.div = 0x0360D}, /* 148 Mhz , for vc01div4 = 250 MHz*/
 	{.div = 0x035E0}, /* 148.5 MHz, for vc01div4 = 250 MHz*/
@@ -351,26 +387,37 @@ static struct aux_rate_tbl adc_rtbl[] = {
 
 /* General synth rate configuration table, in ascending order of rates */
 static struct frac_rate_tbl gen_rtbl[] = {
-	/* For vco1div4 = 250 MHz */
-	{.div = 0x1624E}, /* 22.5792 MHz */
-	{.div = 0x14585}, /* 24.576 MHz */
-	{.div = 0x14000}, /* 25 MHz */
-	{.div = 0x0B127}, /* 45.1584 MHz */
-	{.div = 0x0A000}, /* 50 MHz */
-	{.div = 0x061A8}, /* 81.92 MHz */
-	{.div = 0x05000}, /* 100 MHz */
-	{.div = 0x02800}, /* 200 MHz */
-	{.div = 0x02620}, /* 210 MHz */
-	{.div = 0x02460}, /* 220 MHz */
-	{.div = 0x022C0}, /* 230 MHz */
-	{.div = 0x02160}, /* 240 MHz */
-	{.div = 0x02000}, /* 250 MHz */
+	{.div = 0x1A92B}, /* 22.5792 MHz for vco1div4=300 MHz*/
+	{.div = 0x186A0}, /* 24.576 MHz for vco1div4=300 MHz*/
+	{.div = 0x18000}, /* 25 MHz for vco1div4=300 MHz*/
+	{.div = 0x1624E}, /* 22.5792 MHz for vco1div4=250 MHz*/
+	{.div = 0x14585}, /* 24.576 MHz for vco1div4=250 MHz*/
+	{.div = 0x14000}, /* 25 MHz for vco1div4=250 MHz*/
+	{.div = 0x0D495}, /* 45.1584 MHz for vco1div4=300 MHz*/
+	{.div = 0x0C000}, /* 50 MHz for vco1div4=300 MHz*/
+	{.div = 0x0B127}, /* 45.1584 MHz for vco1div4=250 MHz*/
+	{.div = 0x0A000}, /* 50 MHz for vco1div4=250 MHz*/
+	{.div = 0x07530}, /* 81.92 MHz for vco1div4=300 MHz*/
+	{.div = 0x061A8}, /* 81.92 MHz for vco1div4=250 MHz*/
+	{.div = 0x06000}, /* 100 MHz for vco1div4=300 MHz*/
+	{.div = 0x05000}, /* 100 MHz for vco1div4=250 MHz*/
+	{.div = 0x03000}, /* 200 MHz for vco1div4=300 MHz*/
+	{.div = 0x02DB6}, /* 210 MHz for vco1div4=300 MHz*/
+	{.div = 0x02BA2}, /* 220 MHz for vco1div4=300 MHz*/
+	{.div = 0x029BD}, /* 230 MHz for vco1div4=300 MHz*/
+	{.div = 0x02800}, /* 200 MHz for vco1div4=250 MHz*/
+	{.div = 0x02666}, /* 250 MHz for vco1div4=300 MHz*/
+	{.div = 0x02620}, /* 210 MHz for vco1div4=250 MHz*/
+	{.div = 0x02460}, /* 220 MHz for vco1div4=250 MHz*/
+	{.div = 0x022C0}, /* 230 MHz for vco1div4=250 MHz*/
+	{.div = 0x02160}, /* 240 MHz for vco1div4=250 MHz*/
+	{.div = 0x02000}, /* 250 MHz for vco1div4=250 MHz*/
 };
 
 /* clock parents */
 static const char *vco_parents[] = { "osc_24m_clk", "osc_25m_clk", };
 static const char *sys_parents[] = { "pll1_clk", "pll1_clk", "pll1_clk",
-	"pll1_clk", "sys_synth_clk", "sys_synth_clk", "pll2_clk", "pll3_clk", };
+	"pll1_clk", "sys_syn_clk", "sys_syn_clk", "pll2_clk", "pll3_clk", };
 static const char *ahb_parents[] = { "cpu_div3_clk", "amba_syn_clk", };
 static const char *gpt_parents[] = { "osc_24m_clk", "apb_clk", };
 static const char *uart0_parents[] = { "pll5_clk", "osc_24m_clk",
@@ -391,16 +438,13 @@ static const char *spdif_in_parents[] = { "pll2_clk", "gen_syn3_clk", };
 
 static const char *gen_synth0_1_parents[] = { "vco1div4_clk", "vco3div2_clk",
 	"pll3_clk", };
-static const char *gen_synth2_3_parents[] = { "vco1div4_clk", "vco3div2_clk",
+static const char *gen_synth2_3_parents[] = { "vco1div4_clk", "vco2div2_clk",
 	"pll2_clk", };
 
 void __init spear1340_clk_init(void)
 {
 	struct clk *clk, *clk1;
 
-	clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
-	clk_register_clkdev(clk, "apb_pclk", NULL);
-
 	clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, CLK_IS_ROOT,
 			32000);
 	clk_register_clkdev(clk, "osc_32k_clk", NULL);
@@ -425,7 +469,7 @@ void __init spear1340_clk_init(void)
 	clk = clk_register_gate(NULL, "rtc-spear", "osc_32k_clk", 0,
 			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_RTC_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, NULL, "fc900000.rtc");
+	clk_register_clkdev(clk, NULL, "e0580000.rtc");
 
 	/* clock derived from 24 or 25 MHz osc clk */
 	/* vco-pll */
@@ -499,7 +543,7 @@ void __init spear1340_clk_init(void)
 	clk = clk_register_gate(NULL, "thermal_gclk", "thermal_clk", 0,
 			SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_THSENS_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, NULL, "spear_thermal");
+	clk_register_clkdev(clk, NULL, "e07008c4.thermal");
 
 	/* clock derived from pll4 clk */
 	clk = clk_register_fixed_factor(NULL, "ddr_clk", "pll4_clk", 0, 1,
@@ -521,7 +565,7 @@ void __init spear1340_clk_init(void)
 			ARRAY_SIZE(sys_parents), 0, SPEAR1340_SYS_CLK_CTRL,
 			SPEAR1340_SCLK_SRC_SEL_SHIFT,
 			SPEAR1340_SCLK_SRC_SEL_MASK, 0, &_lock);
-	clk_register_clkdev(clk, "sys_clk", NULL);
+	clk_register_clkdev(clk, "sys_mclk", NULL);
 
 	clk = clk_register_fixed_factor(NULL, "cpu_clk", "sys_mclk", 0, 1,
 			2);
@@ -535,6 +579,10 @@ void __init spear1340_clk_init(void)
 			2);
 	clk_register_clkdev(clk, NULL, "ec800620.wdt");
 
+	clk = clk_register_fixed_factor(NULL, "smp_twd_clk", "cpu_clk", 0, 1,
+			2);
+	clk_register_clkdev(clk, NULL, "smp_twd");
+
 	clk = clk_register_mux(NULL, "ahb_clk", ahb_parents,
 			ARRAY_SIZE(ahb_parents), 0, SPEAR1340_SYS_CLK_CTRL,
 			SPEAR1340_HCLK_SRC_SEL_SHIFT,
@@ -594,14 +642,14 @@ void __init spear1340_clk_init(void)
 	clk_register_clkdev(clk1, "uart0_syn_gclk", NULL);
 
 	clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
-			ARRAY_SIZE(uart0_parents), 0, SPEAR1340_PERIP_CLK_CFG,
-			SPEAR1340_UART0_CLK_SHIFT, SPEAR1340_UART_CLK_MASK, 0,
-			&_lock);
+			ARRAY_SIZE(uart0_parents), CLK_SET_RATE_PARENT,
+			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_UART0_CLK_SHIFT,
+			SPEAR1340_UART_CLK_MASK, 0, &_lock);
 	clk_register_clkdev(clk, "uart0_mclk", NULL);
 
-	clk = clk_register_gate(NULL, "uart0_clk", "uart0_mclk", 0,
-			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UART0_CLK_ENB, 0,
-			&_lock);
+	clk = clk_register_gate(NULL, "uart0_clk", "uart0_mclk",
+			CLK_SET_RATE_PARENT, SPEAR1340_PERIP1_CLK_ENB,
+			SPEAR1340_UART0_CLK_ENB, 0, &_lock);
 	clk_register_clkdev(clk, NULL, "e0000000.serial");
 
 	clk = clk_register_aux("uart1_syn_clk", "uart1_syn_gclk",
@@ -627,9 +675,9 @@ void __init spear1340_clk_init(void)
 	clk_register_clkdev(clk, "sdhci_syn_clk", NULL);
 	clk_register_clkdev(clk1, "sdhci_syn_gclk", NULL);
 
-	clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_syn_gclk", 0,
-			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_SDHCI_CLK_ENB, 0,
-			&_lock);
+	clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_syn_gclk",
+			CLK_SET_RATE_PARENT, SPEAR1340_PERIP1_CLK_ENB,
+			SPEAR1340_SDHCI_CLK_ENB, 0, &_lock);
 	clk_register_clkdev(clk, NULL, "b3000000.sdhci");
 
 	clk = clk_register_aux("cfxd_syn_clk", "cfxd_syn_gclk", "vco1div2_clk",
@@ -638,9 +686,9 @@ void __init spear1340_clk_init(void)
 	clk_register_clkdev(clk, "cfxd_syn_clk", NULL);
 	clk_register_clkdev(clk1, "cfxd_syn_gclk", NULL);
 
-	clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_syn_gclk", 0,
-			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_CFXD_CLK_ENB, 0,
-			&_lock);
+	clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_syn_gclk",
+			CLK_SET_RATE_PARENT, SPEAR1340_PERIP1_CLK_ENB,
+			SPEAR1340_CFXD_CLK_ENB, 0, &_lock);
 	clk_register_clkdev(clk, NULL, "b2800000.cf");
 	clk_register_clkdev(clk, NULL, "arasan_xd");
 
@@ -651,15 +699,15 @@ void __init spear1340_clk_init(void)
 	clk_register_clkdev(clk1, "c3_syn_gclk", NULL);
 
 	clk = clk_register_mux(NULL, "c3_mclk", c3_parents,
-			ARRAY_SIZE(c3_parents), 0, SPEAR1340_PERIP_CLK_CFG,
-			SPEAR1340_C3_CLK_SHIFT, SPEAR1340_C3_CLK_MASK, 0,
-			&_lock);
+			ARRAY_SIZE(c3_parents), CLK_SET_RATE_PARENT,
+			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_C3_CLK_SHIFT,
+			SPEAR1340_C3_CLK_MASK, 0, &_lock);
 	clk_register_clkdev(clk, "c3_mclk", NULL);
 
-	clk = clk_register_gate(NULL, "c3_clk", "c3_mclk", 0,
+	clk = clk_register_gate(NULL, "c3_clk", "c3_mclk", CLK_SET_RATE_PARENT,
 			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_C3_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, NULL, "c3");
+	clk_register_clkdev(clk, NULL, "e1800000.c3");
 
 	/* gmac */
 	clk = clk_register_mux(NULL, "phy_input_mclk", gmac_phy_input_parents,
@@ -679,7 +727,7 @@ void __init spear1340_clk_init(void)
 			ARRAY_SIZE(gmac_phy_parents), 0,
 			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GMAC_PHY_CLK_SHIFT,
 			SPEAR1340_GMAC_PHY_CLK_MASK, 0, &_lock);
-	clk_register_clkdev(clk, NULL, "stmmacphy.0");
+	clk_register_clkdev(clk, "stmmacphy.0", NULL);
 
 	/* clcd */
 	clk = clk_register_mux(NULL, "clcd_syn_mclk", clcd_synth_parents,
@@ -694,33 +742,34 @@ void __init spear1340_clk_init(void)
 	clk_register_clkdev(clk, "clcd_syn_clk", NULL);
 
 	clk = clk_register_mux(NULL, "clcd_pixel_mclk", clcd_pixel_parents,
-			ARRAY_SIZE(clcd_pixel_parents), 0,
+			ARRAY_SIZE(clcd_pixel_parents), CLK_SET_RATE_PARENT,
 			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_CLCD_CLK_SHIFT,
 			SPEAR1340_CLCD_CLK_MASK, 0, &_lock);
-	clk_register_clkdev(clk, "clcd_pixel_clk", NULL);
+	clk_register_clkdev(clk, "clcd_pixel_mclk", NULL);
 
 	clk = clk_register_gate(NULL, "clcd_clk", "clcd_pixel_mclk", 0,
 			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_CLCD_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, "clcd_clk", NULL);
+	clk_register_clkdev(clk, NULL, "e1000000.clcd");
 
 	/* i2s */
 	clk = clk_register_mux(NULL, "i2s_src_mclk", i2s_src_parents,
 			ARRAY_SIZE(i2s_src_parents), 0, SPEAR1340_I2S_CLK_CFG,
 			SPEAR1340_I2S_SRC_CLK_SHIFT, SPEAR1340_I2S_SRC_CLK_MASK,
 			0, &_lock);
-	clk_register_clkdev(clk, "i2s_src_clk", NULL);
+	clk_register_clkdev(clk, "i2s_src_mclk", NULL);
 
-	clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk", 0,
-			SPEAR1340_I2S_CLK_CFG, &i2s_prs1_masks, i2s_prs1_rtbl,
+	clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk",
+			CLK_SET_RATE_PARENT, SPEAR1340_I2S_CLK_CFG,
+			&i2s_prs1_masks, i2s_prs1_rtbl,
 			ARRAY_SIZE(i2s_prs1_rtbl), &_lock, NULL);
 	clk_register_clkdev(clk, "i2s_prs1_clk", NULL);
 
 	clk = clk_register_mux(NULL, "i2s_ref_mclk", i2s_ref_parents,
-			ARRAY_SIZE(i2s_ref_parents), 0, SPEAR1340_I2S_CLK_CFG,
-			SPEAR1340_I2S_REF_SHIFT, SPEAR1340_I2S_REF_SEL_MASK, 0,
-			&_lock);
-	clk_register_clkdev(clk, "i2s_ref_clk", NULL);
+			ARRAY_SIZE(i2s_ref_parents), CLK_SET_RATE_PARENT,
+			SPEAR1340_I2S_CLK_CFG, SPEAR1340_I2S_REF_SHIFT,
+			SPEAR1340_I2S_REF_SEL_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "i2s_ref_mclk", NULL);
 
 	clk = clk_register_gate(NULL, "i2s_ref_pad_clk", "i2s_ref_mclk", 0,
 			SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_I2S_REF_PAD_CLK_ENB,
@@ -769,23 +818,25 @@ void __init spear1340_clk_init(void)
 	clk = clk_register_gate(NULL, "usbh0_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UHC0_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, "usbh.0_clk", NULL);
+	clk_register_clkdev(clk, NULL, "e4000000.ohci");
+	clk_register_clkdev(clk, NULL, "e4800000.ehci");
 
 	clk = clk_register_gate(NULL, "usbh1_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UHC1_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, "usbh.1_clk", NULL);
+	clk_register_clkdev(clk, NULL, "e5000000.ohci");
+	clk_register_clkdev(clk, NULL, "e5800000.ehci");
 
 	clk = clk_register_gate(NULL, "uoc_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UOC_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, NULL, "uoc");
+	clk_register_clkdev(clk, NULL, "e3800000.otg");
 
 	clk = clk_register_gate(NULL, "pcie_sata_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_PCIE_SATA_CLK_ENB,
 			0, &_lock);
 	clk_register_clkdev(clk, NULL, "dw_pcie");
-	clk_register_clkdev(clk, NULL, "ahci");
+	clk_register_clkdev(clk, NULL, "b1000000.ahci");
 
 	clk = clk_register_gate(NULL, "sysram0_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_SYSRAM0_CLK_ENB, 0,
@@ -803,10 +854,10 @@ void __init spear1340_clk_init(void)
 	clk_register_clkdev(clk, "adc_syn_clk", NULL);
 	clk_register_clkdev(clk1, "adc_syn_gclk", NULL);
 
-	clk = clk_register_gate(NULL, "adc_clk", "adc_syn_gclk", 0,
-			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_ADC_CLK_ENB, 0,
-			&_lock);
-	clk_register_clkdev(clk, NULL, "adc_clk");
+	clk = clk_register_gate(NULL, "adc_clk", "adc_syn_gclk",
+			CLK_SET_RATE_PARENT, SPEAR1340_PERIP1_CLK_ENB,
+			SPEAR1340_ADC_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "e0080000.adc");
 
 	/* clock derived from apb clk */
 	clk = clk_register_gate(NULL, "ssp_clk", "apb_clk", 0,
@@ -827,12 +878,12 @@ void __init spear1340_clk_init(void)
 	clk = clk_register_gate(NULL, "i2s_play_clk", "apb_clk", 0,
 			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_I2S_PLAY_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, NULL, "b2400000.i2s");
+	clk_register_clkdev(clk, NULL, "b2400000.i2s-play");
 
 	clk = clk_register_gate(NULL, "i2s_rec_clk", "apb_clk", 0,
 			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_I2S_REC_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, NULL, "b2000000.i2s");
+	clk_register_clkdev(clk, NULL, "b2000000.i2s-rec");
 
 	clk = clk_register_gate(NULL, "kbd_clk", "apb_clk", 0,
 			SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_KBD_CLK_ENB, 0,
@@ -844,37 +895,37 @@ void __init spear1340_clk_init(void)
 			ARRAY_SIZE(gen_synth0_1_parents), 0, SPEAR1340_PLL_CFG,
 			SPEAR1340_GEN_SYNT0_1_CLK_SHIFT,
 			SPEAR1340_GEN_SYNT_CLK_MASK, 0, &_lock);
-	clk_register_clkdev(clk, "gen_syn0_1_clk", NULL);
+	clk_register_clkdev(clk, "gen_syn0_1_mclk", NULL);
 
 	clk = clk_register_mux(NULL, "gen_syn2_3_mclk", gen_synth2_3_parents,
 			ARRAY_SIZE(gen_synth2_3_parents), 0, SPEAR1340_PLL_CFG,
 			SPEAR1340_GEN_SYNT2_3_CLK_SHIFT,
 			SPEAR1340_GEN_SYNT_CLK_MASK, 0, &_lock);
-	clk_register_clkdev(clk, "gen_syn2_3_clk", NULL);
+	clk_register_clkdev(clk, "gen_syn2_3_mclk", NULL);
 
-	clk = clk_register_frac("gen_syn0_clk", "gen_syn0_1_clk", 0,
+	clk = clk_register_frac("gen_syn0_clk", "gen_syn0_1_mclk", 0,
 			SPEAR1340_GEN_CLK_SYNT0, gen_rtbl, ARRAY_SIZE(gen_rtbl),
 			&_lock);
 	clk_register_clkdev(clk, "gen_syn0_clk", NULL);
 
-	clk = clk_register_frac("gen_syn1_clk", "gen_syn0_1_clk", 0,
+	clk = clk_register_frac("gen_syn1_clk", "gen_syn0_1_mclk", 0,
 			SPEAR1340_GEN_CLK_SYNT1, gen_rtbl, ARRAY_SIZE(gen_rtbl),
 			&_lock);
 	clk_register_clkdev(clk, "gen_syn1_clk", NULL);
 
-	clk = clk_register_frac("gen_syn2_clk", "gen_syn2_3_clk", 0,
+	clk = clk_register_frac("gen_syn2_clk", "gen_syn2_3_mclk", 0,
 			SPEAR1340_GEN_CLK_SYNT2, gen_rtbl, ARRAY_SIZE(gen_rtbl),
 			&_lock);
 	clk_register_clkdev(clk, "gen_syn2_clk", NULL);
 
-	clk = clk_register_frac("gen_syn3_clk", "gen_syn2_3_clk", 0,
+	clk = clk_register_frac("gen_syn3_clk", "gen_syn2_3_mclk", 0,
 			SPEAR1340_GEN_CLK_SYNT3, gen_rtbl, ARRAY_SIZE(gen_rtbl),
 			&_lock);
 	clk_register_clkdev(clk, "gen_syn3_clk", NULL);
 
-	clk = clk_register_gate(NULL, "mali_clk", "gen_syn3_clk", 0,
-			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_MALI_CLK_ENB, 0,
-			&_lock);
+	clk = clk_register_gate(NULL, "mali_clk", "gen_syn3_clk",
+			CLK_SET_RATE_PARENT, SPEAR1340_PERIP3_CLK_ENB,
+			SPEAR1340_MALI_CLK_ENB, 0, &_lock);
 	clk_register_clkdev(clk, NULL, "mali");
 
 	clk = clk_register_gate(NULL, "cec0_clk", "ahb_clk", 0,
@@ -888,26 +939,26 @@ void __init spear1340_clk_init(void)
 	clk_register_clkdev(clk, NULL, "spear_cec.1");
 
 	clk = clk_register_mux(NULL, "spdif_out_mclk", spdif_out_parents,
-			ARRAY_SIZE(spdif_out_parents), 0,
+			ARRAY_SIZE(spdif_out_parents), CLK_SET_RATE_PARENT,
 			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_SPDIF_OUT_CLK_SHIFT,
 			SPEAR1340_SPDIF_CLK_MASK, 0, &_lock);
 	clk_register_clkdev(clk, "spdif_out_mclk", NULL);
 
-	clk = clk_register_gate(NULL, "spdif_out_clk", "spdif_out_mclk", 0,
-			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_SPDIF_OUT_CLK_ENB,
-			0, &_lock);
-	clk_register_clkdev(clk, NULL, "spdif-out");
+	clk = clk_register_gate(NULL, "spdif_out_clk", "spdif_out_mclk",
+			CLK_SET_RATE_PARENT, SPEAR1340_PERIP3_CLK_ENB,
+			SPEAR1340_SPDIF_OUT_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "d0000000.spdif-out");
 
 	clk = clk_register_mux(NULL, "spdif_in_mclk", spdif_in_parents,
-			ARRAY_SIZE(spdif_in_parents), 0,
+			ARRAY_SIZE(spdif_in_parents), CLK_SET_RATE_PARENT,
 			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_SPDIF_IN_CLK_SHIFT,
 			SPEAR1340_SPDIF_CLK_MASK, 0, &_lock);
 	clk_register_clkdev(clk, "spdif_in_mclk", NULL);
 
-	clk = clk_register_gate(NULL, "spdif_in_clk", "spdif_in_mclk", 0,
-			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_SPDIF_IN_CLK_ENB, 0,
-			&_lock);
-	clk_register_clkdev(clk, NULL, "spdif-in");
+	clk = clk_register_gate(NULL, "spdif_in_clk", "spdif_in_mclk",
+			CLK_SET_RATE_PARENT, SPEAR1340_PERIP3_CLK_ENB,
+			SPEAR1340_SPDIF_IN_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "d0100000.spdif-in");
 
 	clk = clk_register_gate(NULL, "acp_clk", "acp_mclk", 0,
 			SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_ACP_CLK_ENB, 0,
@@ -917,7 +968,7 @@ void __init spear1340_clk_init(void)
 	clk = clk_register_gate(NULL, "plgpio_clk", "plgpio_mclk", 0,
 			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PLGPIO_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, NULL, "plgpio");
+	clk_register_clkdev(clk, NULL, "e2800000.gpio");
 
 	clk = clk_register_gate(NULL, "video_dec_clk", "video_dec_mclk", 0,
 			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_DEC_CLK_ENB,
@@ -937,25 +988,25 @@ void __init spear1340_clk_init(void)
 	clk = clk_register_gate(NULL, "cam0_clk", "cam0_mclk", 0,
 			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM0_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, NULL, "spear_camif.0");
+	clk_register_clkdev(clk, NULL, "d0200000.cam0");
 
 	clk = clk_register_gate(NULL, "cam1_clk", "cam1_mclk", 0,
 			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM1_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, NULL, "spear_camif.1");
+	clk_register_clkdev(clk, NULL, "d0300000.cam1");
 
 	clk = clk_register_gate(NULL, "cam2_clk", "cam2_mclk", 0,
 			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM2_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, NULL, "spear_camif.2");
+	clk_register_clkdev(clk, NULL, "d0400000.cam2");
 
 	clk = clk_register_gate(NULL, "cam3_clk", "cam3_mclk", 0,
 			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM3_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, NULL, "spear_camif.3");
+	clk_register_clkdev(clk, NULL, "d0500000.cam3");
 
-	clk = clk_register_gate(NULL, "pwm_clk", "pwm_mclk", 0,
+	clk = clk_register_gate(NULL, "pwm_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PWM_CLK_ENB, 0,
 			&_lock);
-	clk_register_clkdev(clk, NULL, "pwm");
+	clk_register_clkdev(clk, NULL, "e0180000.pwm");
 }
diff --git a/drivers/clk/spear/spear3xx_clock.c b/drivers/clk/spear/spear3xx_clock.c
index c315745..33d3ac5 100644
--- a/drivers/clk/spear/spear3xx_clock.c
+++ b/drivers/clk/spear/spear3xx_clock.c
@@ -107,6 +107,12 @@ static struct pll_rate_tbl pll_rtbl[] = {
 /* aux rate configuration table, in ascending order of rates */
 static struct aux_rate_tbl aux_rtbl[] = {
 	/* For PLL1 = 332 MHz */
+	{.xscale = 1, .yscale = 81, .eq = 0}, /* 2.049 MHz */
+	{.xscale = 1, .yscale = 59, .eq = 0}, /* 2.822 MHz */
+	{.xscale = 2, .yscale = 81, .eq = 0}, /* 4.098 MHz */
+	{.xscale = 3, .yscale = 89, .eq = 0}, /* 5.644 MHz */
+	{.xscale = 4, .yscale = 81, .eq = 0}, /* 8.197 MHz */
+	{.xscale = 4, .yscale = 59, .eq = 0}, /* 11.254 MHz */
 	{.xscale = 2, .yscale = 27, .eq = 0}, /* 12.296 MHz */
 	{.xscale = 2, .yscale = 8, .eq = 0}, /* 41.5 MHz */
 	{.xscale = 2, .yscale = 4, .eq = 0}, /* 83 MHz */
@@ -157,6 +163,8 @@ static void __init spear300_clk_init(void)
 			1);
 	clk_register_clkdev(clk, NULL, "a0000000.kbd");
 }
+#else
+static inline void spear300_clk_init(void) { }
 #endif
 
 /* array of all spear 310 clock lookups */
@@ -197,6 +205,8 @@ static void __init spear310_clk_init(void)
 			1);
 	clk_register_clkdev(clk, NULL, "b2200000.serial");
 }
+#else
+static inline void spear310_clk_init(void) { }
 #endif
 
 /* array of all spear 320 clock lookups */
@@ -251,7 +261,7 @@ static void __init spear320_clk_init(void)
 
 	clk = clk_register_fixed_factor(NULL, "pwm_clk", "ras_ahb_clk", 0, 1,
 			1);
-	clk_register_clkdev(clk, "pwm", NULL);
+	clk_register_clkdev(clk, NULL, "a8000000.pwm");
 
 	clk = clk_register_fixed_factor(NULL, "ssp1_clk", "ras_ahb_clk", 0, 1,
 			1);
@@ -271,26 +281,37 @@ static void __init spear320_clk_init(void)
 
 	clk = clk_register_fixed_factor(NULL, "i2s_clk", "ras_apb_clk", 0, 1,
 			1);
-	clk_register_clkdev(clk, NULL, "i2s");
+	clk_register_clkdev(clk, NULL, "a9400000.i2s");
 
 	clk = clk_register_mux(NULL, "i2s_ref_clk", i2s_ref_parents,
-			ARRAY_SIZE(i2s_ref_parents), 0, SPEAR320_CONTROL_REG,
-			I2S_REF_PCLK_SHIFT, I2S_REF_PCLK_MASK, 0, &_lock);
+			ARRAY_SIZE(i2s_ref_parents), CLK_SET_RATE_PARENT,
+			SPEAR320_CONTROL_REG, I2S_REF_PCLK_SHIFT,
+			I2S_REF_PCLK_MASK, 0, &_lock);
 	clk_register_clkdev(clk, "i2s_ref_clk", NULL);
 
-	clk = clk_register_fixed_factor(NULL, "i2s_sclk", "i2s_ref_clk", 0, 1,
+	clk = clk_register_fixed_factor(NULL, "i2s_sclk", "i2s_ref_clk",
+			CLK_SET_RATE_PARENT, 1,
 			4);
 	clk_register_clkdev(clk, "i2s_sclk", NULL);
 
+	clk = clk_register_fixed_factor(NULL, "macb1_clk", "ras_apb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, "hclk", "aa000000.eth");
+
+	clk = clk_register_fixed_factor(NULL, "macb2_clk", "ras_apb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, "hclk", "ab000000.eth");
+
 	clk = clk_register_mux(NULL, "rs485_clk", uartx_parents,
-			ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
-			SPEAR320_RS485_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
-			&_lock);
+			ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+			SPEAR320_EXT_CTRL_REG, SPEAR320_RS485_PCLK_SHIFT,
+			SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
 	clk_register_clkdev(clk, NULL, "a9300000.serial");
 
 	clk = clk_register_mux(NULL, "sdhci_clk", sdhci_parents,
-			ARRAY_SIZE(sdhci_parents), 0, SPEAR320_CONTROL_REG,
-			SDHCI_PCLK_SHIFT, SDHCI_PCLK_MASK, 0, &_lock);
+			ARRAY_SIZE(sdhci_parents), CLK_SET_RATE_PARENT,
+			SPEAR320_CONTROL_REG, SDHCI_PCLK_SHIFT, SDHCI_PCLK_MASK,
+			0, &_lock);
 	clk_register_clkdev(clk, NULL, "70000000.sdhci");
 
 	clk = clk_register_mux(NULL, "smii_pclk", smii0_parents,
@@ -302,49 +323,49 @@ static void __init spear320_clk_init(void)
 	clk_register_clkdev(clk, NULL, "smii");
 
 	clk = clk_register_mux(NULL, "uart1_clk", uartx_parents,
-			ARRAY_SIZE(uartx_parents), 0, SPEAR320_CONTROL_REG,
-			UART1_PCLK_SHIFT, UART1_PCLK_MASK, 0, &_lock);
+			ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+			SPEAR320_CONTROL_REG, UART1_PCLK_SHIFT, UART1_PCLK_MASK,
+			0, &_lock);
 	clk_register_clkdev(clk, NULL, "a3000000.serial");
 
 	clk = clk_register_mux(NULL, "uart2_clk", uartx_parents,
-			ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
-			SPEAR320_UART2_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
-			&_lock);
+			ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+			SPEAR320_EXT_CTRL_REG, SPEAR320_UART2_PCLK_SHIFT,
+			SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
 	clk_register_clkdev(clk, NULL, "a4000000.serial");
 
 	clk = clk_register_mux(NULL, "uart3_clk", uartx_parents,
-			ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
-			SPEAR320_UART3_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
-			&_lock);
+			ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+			SPEAR320_EXT_CTRL_REG, SPEAR320_UART3_PCLK_SHIFT,
+			SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
 	clk_register_clkdev(clk, NULL, "a9100000.serial");
 
 	clk = clk_register_mux(NULL, "uart4_clk", uartx_parents,
-			ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
-			SPEAR320_UART4_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
-			&_lock);
+			ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+			SPEAR320_EXT_CTRL_REG, SPEAR320_UART4_PCLK_SHIFT,
+			SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
 	clk_register_clkdev(clk, NULL, "a9200000.serial");
 
 	clk = clk_register_mux(NULL, "uart5_clk", uartx_parents,
-			ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
-			SPEAR320_UART5_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
-			&_lock);
+			ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+			SPEAR320_EXT_CTRL_REG, SPEAR320_UART5_PCLK_SHIFT,
+			SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
 	clk_register_clkdev(clk, NULL, "60000000.serial");
 
 	clk = clk_register_mux(NULL, "uart6_clk", uartx_parents,
-			ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
-			SPEAR320_UART6_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
-			&_lock);
+			ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+			SPEAR320_EXT_CTRL_REG, SPEAR320_UART6_PCLK_SHIFT,
+			SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
 	clk_register_clkdev(clk, NULL, "60100000.serial");
 }
+#else
+static inline void spear320_clk_init(void) { }
 #endif
 
 void __init spear3xx_clk_init(void)
 {
 	struct clk *clk, *clk1;
 
-	clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
-	clk_register_clkdev(clk, "apb_pclk", NULL);
-
 	clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, CLK_IS_ROOT,
 			32000);
 	clk_register_clkdev(clk, "osc_32k_clk", NULL);
@@ -380,7 +401,8 @@ void __init spear3xx_clk_init(void)
 	clk_register_clkdev(clk1, "pll2_clk", NULL);
 
 	/* clock derived from pll1 clk */
-	clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk", 0, 1, 1);
+	clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk",
+			CLK_SET_RATE_PARENT, 1, 1);
 	clk_register_clkdev(clk, "cpu_clk", NULL);
 
 	clk = clk_register_divider(NULL, "ahb_clk", "pll1_clk",
@@ -395,12 +417,14 @@ void __init spear3xx_clk_init(void)
 	clk_register_clkdev(clk1, "uart_syn_gclk", NULL);
 
 	clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
-			ARRAY_SIZE(uart0_parents), 0, PERIP_CLK_CFG,
-			UART_CLK_SHIFT, UART_CLK_MASK, 0, &_lock);
+			ARRAY_SIZE(uart0_parents), CLK_SET_RATE_PARENT,
+			PERIP_CLK_CFG, UART_CLK_SHIFT, UART_CLK_MASK, 0,
+			&_lock);
 	clk_register_clkdev(clk, "uart0_mclk", NULL);
 
-	clk = clk_register_gate(NULL, "uart0", "uart0_mclk", 0, PERIP1_CLK_ENB,
-			UART_CLK_ENB, 0, &_lock);
+	clk = clk_register_gate(NULL, "uart0", "uart0_mclk",
+			CLK_SET_RATE_PARENT, PERIP1_CLK_ENB, UART_CLK_ENB, 0,
+			&_lock);
 	clk_register_clkdev(clk, NULL, "d0000000.serial");
 
 	clk = clk_register_aux("firda_syn_clk", "firda_syn_gclk", "pll1_clk", 0,
@@ -410,40 +434,44 @@ void __init spear3xx_clk_init(void)
 	clk_register_clkdev(clk1, "firda_syn_gclk", NULL);
 
 	clk = clk_register_mux(NULL, "firda_mclk", firda_parents,
-			ARRAY_SIZE(firda_parents), 0, PERIP_CLK_CFG,
-			FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0, &_lock);
+			ARRAY_SIZE(firda_parents), CLK_SET_RATE_PARENT,
+			PERIP_CLK_CFG, FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0,
+			&_lock);
 	clk_register_clkdev(clk, "firda_mclk", NULL);
 
-	clk = clk_register_gate(NULL, "firda_clk", "firda_mclk", 0,
-			PERIP1_CLK_ENB, FIRDA_CLK_ENB, 0, &_lock);
+	clk = clk_register_gate(NULL, "firda_clk", "firda_mclk",
+			CLK_SET_RATE_PARENT, PERIP1_CLK_ENB, FIRDA_CLK_ENB, 0,
+			&_lock);
 	clk_register_clkdev(clk, NULL, "firda");
 
 	/* gpt clocks */
 	clk_register_gpt("gpt0_syn_clk", "pll1_clk", 0, PRSC0_CLK_CFG, gpt_rtbl,
 			ARRAY_SIZE(gpt_rtbl), &_lock);
 	clk = clk_register_mux(NULL, "gpt0_clk", gpt0_parents,
-			ARRAY_SIZE(gpt0_parents), 0, PERIP_CLK_CFG,
-			GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
+			ARRAY_SIZE(gpt0_parents), CLK_SET_RATE_PARENT,
+			PERIP_CLK_CFG, GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
 	clk_register_clkdev(clk, NULL, "gpt0");
 
 	clk_register_gpt("gpt1_syn_clk", "pll1_clk", 0, PRSC1_CLK_CFG, gpt_rtbl,
 			ARRAY_SIZE(gpt_rtbl), &_lock);
 	clk = clk_register_mux(NULL, "gpt1_mclk", gpt1_parents,
-			ARRAY_SIZE(gpt1_parents), 0, PERIP_CLK_CFG,
-			GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
+			ARRAY_SIZE(gpt1_parents), CLK_SET_RATE_PARENT,
+			PERIP_CLK_CFG, GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
 	clk_register_clkdev(clk, "gpt1_mclk", NULL);
-	clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", 0,
-			PERIP1_CLK_ENB, GPT1_CLK_ENB, 0, &_lock);
+	clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk",
+			CLK_SET_RATE_PARENT, PERIP1_CLK_ENB, GPT1_CLK_ENB, 0,
+			&_lock);
 	clk_register_clkdev(clk, NULL, "gpt1");
 
 	clk_register_gpt("gpt2_syn_clk", "pll1_clk", 0, PRSC2_CLK_CFG, gpt_rtbl,
 			ARRAY_SIZE(gpt_rtbl), &_lock);
 	clk = clk_register_mux(NULL, "gpt2_mclk", gpt2_parents,
-			ARRAY_SIZE(gpt2_parents), 0, PERIP_CLK_CFG,
-			GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
+			ARRAY_SIZE(gpt2_parents), CLK_SET_RATE_PARENT,
+			PERIP_CLK_CFG, GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
 	clk_register_clkdev(clk, "gpt2_mclk", NULL);
-	clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", 0,
-			PERIP1_CLK_ENB, GPT2_CLK_ENB, 0, &_lock);
+	clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk",
+			CLK_SET_RATE_PARENT, PERIP1_CLK_ENB, GPT2_CLK_ENB, 0,
+			&_lock);
 	clk_register_clkdev(clk, NULL, "gpt2");
 
 	/* general synths clocks */
@@ -480,7 +508,9 @@ void __init spear3xx_clk_init(void)
 	/* clock derived from pll3 clk */
 	clk = clk_register_gate(NULL, "usbh_clk", "pll3_clk", 0, PERIP1_CLK_ENB,
 			USBH_CLK_ENB, 0, &_lock);
-	clk_register_clkdev(clk, "usbh_clk", NULL);
+	clk_register_clkdev(clk, NULL, "e1800000.ehci");
+	clk_register_clkdev(clk, NULL, "e1900000.ohci");
+	clk_register_clkdev(clk, NULL, "e2100000.ohci");
 
 	clk = clk_register_fixed_factor(NULL, "usbh.0_clk", "usbh_clk", 0, 1,
 			1);
@@ -492,7 +522,7 @@ void __init spear3xx_clk_init(void)
 
 	clk = clk_register_gate(NULL, "usbd_clk", "pll3_clk", 0, PERIP1_CLK_ENB,
 			USBD_CLK_ENB, 0, &_lock);
-	clk_register_clkdev(clk, NULL, "designware_udc");
+	clk_register_clkdev(clk, NULL, "e1100000.usbd");
 
 	/* clock derived from ahb clk */
 	clk = clk_register_fixed_factor(NULL, "ahbmult2_clk", "ahb_clk", 0, 2,
@@ -540,7 +570,7 @@ void __init spear3xx_clk_init(void)
 	/* clock derived from apb clk */
 	clk = clk_register_gate(NULL, "adc_clk", "apb_clk", 0, PERIP1_CLK_ENB,
 			ADC_CLK_ENB, 0, &_lock);
-	clk_register_clkdev(clk, NULL, "adc");
+	clk_register_clkdev(clk, NULL, "d0080000.adc");
 
 	clk = clk_register_gate(NULL, "gpio0_clk", "apb_clk", 0, PERIP1_CLK_ENB,
 			GPIO_CLK_ENB, 0, &_lock);
@@ -579,20 +609,24 @@ void __init spear3xx_clk_init(void)
 			RAS_CLK_ENB, RAS_48M_CLK_ENB, 0, &_lock);
 	clk_register_clkdev(clk, "ras_pll3_clk", NULL);
 
-	clk = clk_register_gate(NULL, "ras_syn0_gclk", "gen0_syn_gclk", 0,
-			RAS_CLK_ENB, RAS_SYNT0_CLK_ENB, 0, &_lock);
+	clk = clk_register_gate(NULL, "ras_syn0_gclk", "gen0_syn_gclk",
+			CLK_SET_RATE_PARENT, RAS_CLK_ENB, RAS_SYNT0_CLK_ENB, 0,
+			&_lock);
 	clk_register_clkdev(clk, "ras_syn0_gclk", NULL);
 
-	clk = clk_register_gate(NULL, "ras_syn1_gclk", "gen1_syn_gclk", 0,
-			RAS_CLK_ENB, RAS_SYNT1_CLK_ENB, 0, &_lock);
+	clk = clk_register_gate(NULL, "ras_syn1_gclk", "gen1_syn_gclk",
+			CLK_SET_RATE_PARENT, RAS_CLK_ENB, RAS_SYNT1_CLK_ENB, 0,
+			&_lock);
 	clk_register_clkdev(clk, "ras_syn1_gclk", NULL);
 
-	clk = clk_register_gate(NULL, "ras_syn2_gclk", "gen2_syn_gclk", 0,
-			RAS_CLK_ENB, RAS_SYNT2_CLK_ENB, 0, &_lock);
+	clk = clk_register_gate(NULL, "ras_syn2_gclk", "gen2_syn_gclk",
+			CLK_SET_RATE_PARENT, RAS_CLK_ENB, RAS_SYNT2_CLK_ENB, 0,
+			&_lock);
 	clk_register_clkdev(clk, "ras_syn2_gclk", NULL);
 
-	clk = clk_register_gate(NULL, "ras_syn3_gclk", "gen3_syn_gclk", 0,
-			RAS_CLK_ENB, RAS_SYNT3_CLK_ENB, 0, &_lock);
+	clk = clk_register_gate(NULL, "ras_syn3_gclk", "gen3_syn_gclk",
+			CLK_SET_RATE_PARENT, RAS_CLK_ENB, RAS_SYNT3_CLK_ENB, 0,
+			&_lock);
 	clk_register_clkdev(clk, "ras_syn3_gclk", NULL);
 
 	if (of_machine_is_compatible("st,spear300"))
diff --git a/drivers/clk/spear/spear6xx_clock.c b/drivers/clk/spear/spear6xx_clock.c
index a98d086..e862a33 100644
--- a/drivers/clk/spear/spear6xx_clock.c
+++ b/drivers/clk/spear/spear6xx_clock.c
@@ -92,6 +92,7 @@ static struct pll_rate_tbl pll_rtbl[] = {
 /* aux rate configuration table, in ascending order of rates */
 static struct aux_rate_tbl aux_rtbl[] = {
 	/* For PLL1 = 332 MHz */
+	{.xscale = 2, .yscale = 27, .eq = 0}, /* 12.296 MHz */
 	{.xscale = 2, .yscale = 8, .eq = 0}, /* 41.5 MHz */
 	{.xscale = 2, .yscale = 4, .eq = 0}, /* 83 MHz */
 	{.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
@@ -118,9 +119,6 @@ void __init spear6xx_clk_init(void)
 {
 	struct clk *clk, *clk1;
 
-	clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
-	clk_register_clkdev(clk, "apb_pclk", NULL);
-
 	clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, CLK_IS_ROOT,
 			32000);
 	clk_register_clkdev(clk, "osc_32k_clk", NULL);
@@ -156,7 +154,8 @@ void __init spear6xx_clk_init(void)
 	clk_register_clkdev(clk, NULL, "wdt");
 
 	/* clock derived from pll1 clk */
-	clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk", 0, 1, 1);
+	clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk",
+			CLK_SET_RATE_PARENT, 1, 1);
 	clk_register_clkdev(clk, "cpu_clk", NULL);
 
 	clk = clk_register_divider(NULL, "ahb_clk", "pll1_clk",
@@ -261,11 +260,13 @@ void __init spear6xx_clk_init(void)
 	/* clock derived from pll3 clk */
 	clk = clk_register_gate(NULL, "usbh0_clk", "pll3_clk", 0,
 			PERIP1_CLK_ENB, USBH0_CLK_ENB, 0, &_lock);
-	clk_register_clkdev(clk, NULL, "usbh.0_clk");
+	clk_register_clkdev(clk, NULL, "e1800000.ehci");
+	clk_register_clkdev(clk, NULL, "e1900000.ohci");
 
 	clk = clk_register_gate(NULL, "usbh1_clk", "pll3_clk", 0,
 			PERIP1_CLK_ENB, USBH1_CLK_ENB, 0, &_lock);
-	clk_register_clkdev(clk, NULL, "usbh.1_clk");
+	clk_register_clkdev(clk, NULL, "e2000000.ehci");
+	clk_register_clkdev(clk, NULL, "e2100000.ohci");
 
 	clk = clk_register_gate(NULL, "usbd_clk", "pll3_clk", 0, PERIP1_CLK_ENB,
 			USBD_CLK_ENB, 0, &_lock);
diff --git a/drivers/clk/ux500/Makefile b/drivers/clk/ux500/Makefile
index 858fbfe..bcc0c11 100644
--- a/drivers/clk/ux500/Makefile
+++ b/drivers/clk/ux500/Makefile
@@ -10,3 +10,6 @@ obj-y += clk-prcmu.o
 obj-y += u8500_clk.o
 obj-y += u9540_clk.o
 obj-y += u8540_clk.o
+
+# ABX500 clock driver
+obj-y += abx500-clk.o
diff --git a/drivers/clk/ux500/abx500-clk.c b/drivers/clk/ux500/abx500-clk.c
new file mode 100644
index 0000000..e27c523
--- /dev/null
+++ b/drivers/clk/ux500/abx500-clk.c
@@ -0,0 +1,73 @@
+/*
+ * abx500 clock implementation for ux500 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/err.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/abx500/ab8500.h>
+
+/* TODO: Add clock implementations here */
+
+
+/* Clock definitions for ab8500 */
+static int ab8500_reg_clks(struct device *dev)
+{
+	return 0;
+}
+
+/* Clock definitions for ab8540 */
+static int ab8540_reg_clks(struct device *dev)
+{
+	return 0;
+}
+
+/* Clock definitions for ab9540 */
+static int ab9540_reg_clks(struct device *dev)
+{
+	return 0;
+}
+
+static int __devinit abx500_clk_probe(struct platform_device *pdev)
+{
+	struct ab8500 *parent = dev_get_drvdata(pdev->dev.parent);
+	int ret;
+
+	if (is_ab8500(parent) || is_ab8505(parent)) {
+		ret = ab8500_reg_clks(&pdev->dev);
+	} else if (is_ab8540(parent)) {
+		ret = ab8540_reg_clks(&pdev->dev);
+	} else if (is_ab9540(parent)) {
+		ret = ab9540_reg_clks(&pdev->dev);
+	} else {
+		dev_err(&pdev->dev, "non supported plf id\n");
+		return -ENODEV;
+	}
+
+	return ret;
+}
+
+static struct platform_driver abx500_clk_driver = {
+	.driver = {
+		.name = "abx500-clk",
+		.owner = THIS_MODULE,
+	},
+	.probe	= abx500_clk_probe,
+};
+
+static int __init abx500_clk_init(void)
+{
+	return platform_driver_register(&abx500_clk_driver);
+}
+
+arch_initcall(abx500_clk_init);
+
+MODULE_AUTHOR("Ulf Hansson <ulf.hansson@linaro.org");
+MODULE_DESCRIPTION("ABX500 clk driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c
index 930cdfe..74faa7e 100644
--- a/drivers/clk/ux500/clk-prcmu.c
+++ b/drivers/clk/ux500/clk-prcmu.c
@@ -133,6 +133,40 @@ out_error:
 		hw->init->name);
 }
 
+static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
+{
+	int err;
+	struct clk_prcmu *clk = to_clk_prcmu(hw);
+
+	err = prcmu_request_ape_opp_100_voltage(true);
+	if (err) {
+		pr_err("clk_prcmu: %s failed to request APE OPP VOLT for %s.\n",
+			__func__, hw->init->name);
+		return err;
+	}
+
+	err = prcmu_request_clock(clk->cg_sel, true);
+	if (err)
+		prcmu_request_ape_opp_100_voltage(false);
+
+	return err;
+}
+
+static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw)
+{
+	struct clk_prcmu *clk = to_clk_prcmu(hw);
+
+	if (prcmu_request_clock(clk->cg_sel, false))
+		goto out_error;
+	if (prcmu_request_ape_opp_100_voltage(false))
+		goto out_error;
+	return;
+
+out_error:
+	pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
+		hw->init->name);
+}
+
 static struct clk_ops clk_prcmu_scalable_ops = {
 	.prepare = clk_prcmu_prepare,
 	.unprepare = clk_prcmu_unprepare,
@@ -153,6 +187,13 @@ static struct clk_ops clk_prcmu_gate_ops = {
 	.recalc_rate = clk_prcmu_recalc_rate,
 };
 
+static struct clk_ops clk_prcmu_scalable_rate_ops = {
+	.is_enabled = clk_prcmu_is_enabled,
+	.recalc_rate = clk_prcmu_recalc_rate,
+	.round_rate = clk_prcmu_round_rate,
+	.set_rate = clk_prcmu_set_rate,
+};
+
 static struct clk_ops clk_prcmu_rate_ops = {
 	.is_enabled = clk_prcmu_is_enabled,
 	.recalc_rate = clk_prcmu_recalc_rate,
@@ -167,6 +208,17 @@ static struct clk_ops clk_prcmu_opp_gate_ops = {
 	.recalc_rate = clk_prcmu_recalc_rate,
 };
 
+static struct clk_ops clk_prcmu_opp_volt_scalable_ops = {
+	.prepare = clk_prcmu_opp_volt_prepare,
+	.unprepare = clk_prcmu_opp_volt_unprepare,
+	.enable = clk_prcmu_enable,
+	.disable = clk_prcmu_disable,
+	.is_enabled = clk_prcmu_is_enabled,
+	.recalc_rate = clk_prcmu_recalc_rate,
+	.round_rate = clk_prcmu_round_rate,
+	.set_rate = clk_prcmu_set_rate,
+};
+
 static struct clk *clk_reg_prcmu(const char *name,
 				 const char *parent_name,
 				 u8 cg_sel,
@@ -233,6 +285,16 @@ struct clk *clk_reg_prcmu_gate(const char *name,
 			&clk_prcmu_gate_ops);
 }
 
+struct clk *clk_reg_prcmu_scalable_rate(const char *name,
+					const char *parent_name,
+					u8 cg_sel,
+					unsigned long rate,
+					unsigned long flags)
+{
+	return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
+			&clk_prcmu_scalable_rate_ops);
+}
+
 struct clk *clk_reg_prcmu_rate(const char *name,
 			       const char *parent_name,
 			       u8 cg_sel,
@@ -250,3 +312,13 @@ struct clk *clk_reg_prcmu_opp_gate(const char *name,
 	return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
 			&clk_prcmu_opp_gate_ops);
 }
+
+struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name,
+					    const char *parent_name,
+					    u8 cg_sel,
+					    unsigned long rate,
+					    unsigned long flags)
+{
+	return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
+			&clk_prcmu_opp_volt_scalable_ops);
+}
diff --git a/drivers/clk/ux500/clk.h b/drivers/clk/ux500/clk.h
index 836d7d1..c3e4491 100644
--- a/drivers/clk/ux500/clk.h
+++ b/drivers/clk/ux500/clk.h
@@ -35,6 +35,12 @@ struct clk *clk_reg_prcmu_gate(const char *name,
 			       u8 cg_sel,
 			       unsigned long flags);
 
+struct clk *clk_reg_prcmu_scalable_rate(const char *name,
+					const char *parent_name,
+					u8 cg_sel,
+					unsigned long rate,
+					unsigned long flags);
+
 struct clk *clk_reg_prcmu_rate(const char *name,
 			       const char *parent_name,
 			       u8 cg_sel,
@@ -45,4 +51,10 @@ struct clk *clk_reg_prcmu_opp_gate(const char *name,
 				   u8 cg_sel,
 				   unsigned long flags);
 
+struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name,
+					    const char *parent_name,
+					    u8 cg_sel,
+					    unsigned long rate,
+					    unsigned long flags);
+
 #endif /* __UX500_CLK_H */
diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c
index e2c17d1..4ab2131 100644
--- a/drivers/clk/ux500/u8500_clk.c
+++ b/drivers/clk/ux500/u8500_clk.c
@@ -12,7 +12,7 @@
 #include <linux/clk-provider.h>
 #include <linux/mfd/dbx500-prcmu.h>
 #include <linux/platform_data/clk-ux500.h>
-
+#include <mach/db8500-regs.h>
 #include "clk.h"
 
 void u8500_clk_init(void)
@@ -160,20 +160,15 @@ void u8500_clk_init(void)
 	clk = clk_reg_prcmu_gate("uiccclk", NULL, PRCMU_UICCCLK, CLK_IS_ROOT);
 	clk_register_clkdev(clk, NULL, "uicc");
 
-	/*
-	 * FIXME: The MTU clocks might need some kind of "parent muxed join"
-	 * and these have no K-clocks. For now, we ignore the missing
-	 * connection to the corresponding P-clocks, p6_mtu0_clk and
-	 * p6_mtu1_clk. Instead timclk is used which is the valid parent.
-	 */
 	clk = clk_reg_prcmu_gate("timclk", NULL, PRCMU_TIMCLK, CLK_IS_ROOT);
 	clk_register_clkdev(clk, NULL, "mtu0");
 	clk_register_clkdev(clk, NULL, "mtu1");
 
-	clk = clk_reg_prcmu_gate("sdmmcclk", NULL, PRCMU_SDMMCCLK, CLK_IS_ROOT);
+	clk = clk_reg_prcmu_opp_volt_scalable("sdmmcclk", NULL, PRCMU_SDMMCCLK,
+					100000000,
+					CLK_IS_ROOT|CLK_SET_RATE_GATE);
 	clk_register_clkdev(clk, NULL, "sdmmc");
 
-
 	clk = clk_reg_prcmu_scalable("dsi_pll", "hdmiclk",
 				PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE);
 	clk_register_clkdev(clk, "dsihs2", "mcde");
@@ -205,16 +200,18 @@ void u8500_clk_init(void)
 	clk_register_clkdev(clk, "dsilp2", "dsilink.2");
 	clk_register_clkdev(clk, "dsilp2", "mcde");
 
-	clk = clk_reg_prcmu_rate("smp_twd", NULL, PRCMU_ARMSS,
-				CLK_IS_ROOT|CLK_GET_RATE_NOCACHE|
-				CLK_IGNORE_UNUSED);
+	clk = clk_reg_prcmu_scalable_rate("armss", NULL,
+				PRCMU_ARMSS, 0, CLK_IS_ROOT|CLK_IGNORE_UNUSED);
+	clk_register_clkdev(clk, "armss", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "smp_twd", "armss",
+				CLK_IGNORE_UNUSED, 1, 2);
 	clk_register_clkdev(clk, NULL, "smp_twd");
 
 	/*
 	 * FIXME: Add special handled PRCMU clocks here:
-	 * 1. clk_arm, use PRCMU_ARMCLK.
-	 * 2. clkout0yuv, use PRCMU as parent + need regulator + pinctrl.
-	 * 3. ab9540_clkout1yuv, see clkout0yuv
+	 * 1. clkout0yuv, use PRCMU as parent + need regulator + pinctrl.
+	 * 2. ab9540_clkout1yuv, see clkout0yuv
 	 */
 
 	/* PRCC P-clocks */
@@ -347,6 +344,8 @@ void u8500_clk_init(void)
 
 	clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", U8500_CLKRST3_BASE,
 				BIT(5), 0);
+	clk_register_clkdev(clk, "apb_pclk", "ske");
+	clk_register_clkdev(clk, "apb_pclk", "nmk-ske-keypad");
 
 	clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", U8500_CLKRST3_BASE,
 				BIT(6), 0);
@@ -375,6 +374,7 @@ void u8500_clk_init(void)
 
 	clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", U8500_CLKRST6_BASE,
 				BIT(0), 0);
+	clk_register_clkdev(clk, "apb_pclk", "rng");
 
 	clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", U8500_CLKRST6_BASE,
 				BIT(1), 0);
@@ -399,8 +399,11 @@ void u8500_clk_init(void)
 
 	clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", U8500_CLKRST6_BASE,
 				BIT(6), 0);
+	clk_register_clkdev(clk, "apb_pclk", "mtu0");
+
 	clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", U8500_CLKRST6_BASE,
 				BIT(7), 0);
+	clk_register_clkdev(clk, "apb_pclk", "mtu1");
 
 	/* PRCC K-clocks
 	 *
@@ -503,6 +506,8 @@ void u8500_clk_init(void)
 
 	clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k",
 			U8500_CLKRST3_BASE, BIT(5), CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, NULL, "ske");
+	clk_register_clkdev(clk, NULL, "nmk-ske-keypad");
 
 	clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk",
 			U8500_CLKRST3_BASE, BIT(6), CLK_SET_RATE_GATE);
@@ -515,5 +520,5 @@ void u8500_clk_init(void)
 	/* Periph6 */
 	clk = clk_reg_prcc_kclk("p3_rng_kclk", "rngclk",
 			U8500_CLKRST6_BASE, BIT(0), CLK_SET_RATE_GATE);
-
+	clk_register_clkdev(clk, NULL, "rng");
 }
diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile
index c0a0f64..ec3b88f 100644
--- a/drivers/clk/versatile/Makefile
+++ b/drivers/clk/versatile/Makefile
@@ -1,4 +1,7 @@
 # Makefile for Versatile-specific clocks
 obj-$(CONFIG_ICST)		+= clk-icst.o
 obj-$(CONFIG_ARCH_INTEGRATOR)	+= clk-integrator.o
+obj-$(CONFIG_INTEGRATOR_IMPD1)	+= clk-impd1.o
 obj-$(CONFIG_ARCH_REALVIEW)	+= clk-realview.o
+obj-$(CONFIG_ARCH_VEXPRESS)	+= clk-vexpress.o
+obj-$(CONFIG_VEXPRESS_CONFIG)	+= clk-vexpress-osc.o
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c
index f555b50..67ccf4a 100644
--- a/drivers/clk/versatile/clk-icst.c
+++ b/drivers/clk/versatile/clk-icst.c
@@ -3,6 +3,12 @@
  * We wrap the custom interface from <asm/hardware/icst.h> into the generic
  * clock framework.
  *
+ * Copyright (C) 2012 Linus Walleij
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
  * TODO: when all ARM reference designs are migrated to generic clocks, the
  * ICST clock code from the ARM tree should probably be merged into this
  * file.
@@ -11,33 +17,74 @@
 #include <linux/clkdev.h>
 #include <linux/err.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 
 #include "clk-icst.h"
 
 /**
  * struct clk_icst - ICST VCO clock wrapper
  * @hw: corresponding clock hardware entry
+ * @vcoreg: VCO register address
+ * @lockreg: VCO lock register address
  * @params: parameters for this ICST instance
  * @rate: current rate
- * @setvco: function to commit ICST settings to hardware
  */
 struct clk_icst {
 	struct clk_hw hw;
+	void __iomem *vcoreg;
+	void __iomem *lockreg;
 	const struct icst_params *params;
 	unsigned long rate;
-	struct icst_vco (*getvco)(void);
-	void (*setvco)(struct icst_vco);
 };
 
 #define to_icst(_hw) container_of(_hw, struct clk_icst, hw)
 
+/**
+ * vco_get() - get ICST VCO settings from a certain register
+ * @vcoreg: register containing the VCO settings
+ */
+static struct icst_vco vco_get(void __iomem *vcoreg)
+{
+	u32 val;
+	struct icst_vco vco;
+
+	val = readl(vcoreg);
+	vco.v = val & 0x1ff;
+	vco.r = (val >> 9) & 0x7f;
+	vco.s = (val >> 16) & 03;
+	return vco;
+}
+
+/**
+ * vco_set() - commit changes to an ICST VCO
+ * @locreg: register to poke to unlock the VCO for writing
+ * @vcoreg: register containing the VCO settings
+ * @vco: ICST VCO parameters to commit
+ */
+static void vco_set(void __iomem *lockreg,
+			void __iomem *vcoreg,
+			struct icst_vco vco)
+{
+	u32 val;
+
+	val = readl(vcoreg) & ~0x7ffff;
+	val |= vco.v | (vco.r << 9) | (vco.s << 16);
+
+	/* This magic unlocks the VCO so it can be controlled */
+	writel(0xa05f, lockreg);
+	writel(val, vcoreg);
+	/* This locks the VCO again */
+	writel(0, lockreg);
+}
+
+
 static unsigned long icst_recalc_rate(struct clk_hw *hw,
 				      unsigned long parent_rate)
 {
 	struct clk_icst *icst = to_icst(hw);
 	struct icst_vco vco;
 
-	vco = icst->getvco();
+	vco = vco_get(icst->vcoreg);
 	icst->rate = icst_hz(icst->params, vco);
 	return icst->rate;
 }
@@ -60,7 +107,7 @@ static int icst_set_rate(struct clk_hw *hw, unsigned long rate,
 
 	vco = icst_hz_to_vco(icst->params, rate);
 	icst->rate = icst_hz(icst->params, vco);
-	icst->setvco(vco);
+	vco_set(icst->vcoreg, icst->lockreg, vco);
 	return 0;
 }
 
@@ -70,8 +117,9 @@ static const struct clk_ops icst_ops = {
 	.set_rate = icst_set_rate,
 };
 
-struct clk * __init icst_clk_register(struct device *dev,
-				      const struct clk_icst_desc *desc)
+struct clk *icst_clk_register(struct device *dev,
+			const struct clk_icst_desc *desc,
+			void __iomem *base)
 {
 	struct clk *clk;
 	struct clk_icst *icst;
@@ -89,8 +137,8 @@ struct clk * __init icst_clk_register(struct device *dev,
 	init.num_parents = 0;
 	icst->hw.init = &init;
 	icst->params = desc->params;
-	icst->getvco = desc->getvco;
-	icst->setvco = desc->setvco;
+	icst->vcoreg = base + desc->vco_offset;
+	icst->lockreg = base + desc->lock_offset;
 
 	clk = clk_register(dev, &icst->hw);
 	if (IS_ERR(clk))
diff --git a/drivers/clk/versatile/clk-icst.h b/drivers/clk/versatile/clk-icst.h
index 71b4c56..dad51b6 100644
--- a/drivers/clk/versatile/clk-icst.h
+++ b/drivers/clk/versatile/clk-icst.h
@@ -1,10 +1,18 @@
 #include <asm/hardware/icst.h>
 
+/**
+ * struct clk_icst_desc - descriptor for the ICST VCO
+ * @params: ICST parameters
+ * @vco_offset: offset to the ICST VCO from the provided memory base
+ * @lock_offset: offset to the ICST VCO locking register from the provided
+ *	memory base
+ */
 struct clk_icst_desc {
 	const struct icst_params *params;
-	struct icst_vco (*getvco)(void);
-	void (*setvco)(struct icst_vco);
+	u32 vco_offset;
+	u32 lock_offset;
 };
 
 struct clk *icst_clk_register(struct device *dev,
-			      const struct clk_icst_desc *desc);
+			      const struct clk_icst_desc *desc,
+			      void __iomem *base);
diff --git a/drivers/clk/versatile/clk-impd1.c b/drivers/clk/versatile/clk-impd1.c
new file mode 100644
index 0000000..369139a
--- /dev/null
+++ b/drivers/clk/versatile/clk-impd1.c
@@ -0,0 +1,97 @@
+/*
+ * Clock driver for the ARM Integrator/IM-PD1 board
+ * Copyright (C) 2012 Linus Walleij
+ *
+ * This program is free software; you can redistribute 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/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_data/clk-integrator.h>
+
+#include <mach/impd1.h>
+
+#include "clk-icst.h"
+
+struct impd1_clk {
+	struct clk *vcoclk;
+	struct clk *uartclk;
+	struct clk_lookup *clks[3];
+};
+
+static struct impd1_clk impd1_clks[4];
+
+/*
+ * There are two VCO's on the IM-PD1 but only one is used by the
+ * kernel, that is why we are only implementing the control of
+ * IMPD1_OSC1 here.
+ */
+
+static const struct icst_params impd1_vco_params = {
+	.ref		= 24000000,	/* 24 MHz */
+	.vco_max	= ICST525_VCO_MAX_3V,
+	.vco_min	= ICST525_VCO_MIN,
+	.vd_min		= 12,
+	.vd_max		= 519,
+	.rd_min		= 3,
+	.rd_max		= 120,
+	.s2div		= icst525_s2div,
+	.idx2s		= icst525_idx2s,
+};
+
+static const struct clk_icst_desc impd1_icst1_desc = {
+	.params = &impd1_vco_params,
+	.vco_offset = IMPD1_OSC1,
+	.lock_offset = IMPD1_LOCK,
+};
+
+/**
+ * integrator_impd1_clk_init() - set up the integrator clock tree
+ * @base: base address of the logic module (LM)
+ * @id: the ID of this LM
+ */
+void integrator_impd1_clk_init(void __iomem *base, unsigned int id)
+{
+	struct impd1_clk *imc;
+	struct clk *clk;
+	int i;
+
+	if (id > 3) {
+		pr_crit("no more than 4 LMs can be attached\n");
+		return;
+	}
+	imc = &impd1_clks[id];
+
+	clk = icst_clk_register(NULL, &impd1_icst1_desc, base);
+	imc->vcoclk = clk;
+	imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id);
+
+	/* UART reference clock */
+	clk = clk_register_fixed_rate(NULL, "uartclk", NULL, CLK_IS_ROOT,
+				14745600);
+	imc->uartclk = clk;
+	imc->clks[1] = clkdev_alloc(clk, NULL, "lm%x:00100", id);
+	imc->clks[2] = clkdev_alloc(clk, NULL, "lm%x:00200", id);
+
+	for (i = 0; i < ARRAY_SIZE(imc->clks); i++)
+		clkdev_add(imc->clks[i]);
+}
+
+void integrator_impd1_clk_exit(unsigned int id)
+{
+	int i;
+	struct impd1_clk *imc;
+
+	if (id > 3)
+		return;
+	imc = &impd1_clks[id];
+
+	for (i = 0; i < ARRAY_SIZE(imc->clks); i++)
+		clkdev_drop(imc->clks[i]);
+	clk_unregister(imc->uartclk);
+	clk_unregister(imc->vcoclk);
+}
diff --git a/drivers/clk/versatile/clk-integrator.c b/drivers/clk/versatile/clk-integrator.c
index a505392..08593b4 100644
--- a/drivers/clk/versatile/clk-integrator.c
+++ b/drivers/clk/versatile/clk-integrator.c
@@ -1,8 +1,16 @@
+/*
+ * Clock driver for the ARM Integrator/AP and Integrator/CP boards
+ * Copyright (C) 2012 Linus Walleij
+ *
+ * This program is free software; you can redistribute 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/clk.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
-#include <linux/io.h>
-#include <linux/clk-provider.h>
+#include <linux/platform_data/clk-integrator.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
@@ -14,42 +22,6 @@
  * Inspired by portions of:
  * plat-versatile/clock.c and plat-versatile/include/plat/clock.h
  */
-#define CM_LOCK		(__io_address(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)
-#define CM_AUXOSC	(__io_address(INTEGRATOR_HDR_BASE)+0x1c)
-
-/**
- * cp_auxvco_get() - get ICST VCO settings for the Integrator/CP
- * @vco: ICST VCO parameters to update with hardware status
- */
-static struct icst_vco cp_auxvco_get(void)
-{
-	u32 val;
-	struct icst_vco vco;
-
-	val = readl(CM_AUXOSC);
-	vco.v = val & 0x1ff;
-	vco.r = (val >> 9) & 0x7f;
-	vco.s = (val >> 16) & 03;
-	return vco;
-}
-
-/**
- * cp_auxvco_set() - commit changes to Integrator/CP ICST VCO
- * @vco: ICST VCO parameters to commit
- */
-static void cp_auxvco_set(struct icst_vco vco)
-{
-	u32 val;
-
-	val = readl(CM_AUXOSC) & ~0x7ffff;
-	val |= vco.v | (vco.r << 9) | (vco.s << 16);
-
-	/* This magic unlocks the CM VCO so it can be controlled */
-	writel(0xa05f, CM_LOCK);
-	writel(val, CM_AUXOSC);
-	/* This locks the CM again */
-	writel(0, CM_LOCK);
-}
 
 static const struct icst_params cp_auxvco_params = {
 	.ref		= 24000000,
@@ -65,8 +37,8 @@ static const struct icst_params cp_auxvco_params = {
 
 static const struct clk_icst_desc __initdata cp_icst_desc = {
 	.params = &cp_auxvco_params,
-	.getvco = cp_auxvco_get,
-	.setvco = cp_auxvco_set,
+	.vco_offset = 0x1c,
+	.lock_offset = INTEGRATOR_HDR_LOCK_OFFSET,
 };
 
 /*
@@ -106,6 +78,7 @@ void __init integrator_clk_init(bool is_cp)
 	clk_register_clkdev(clk, NULL, "sp804");
 
 	/* ICST VCO clock used on the Integrator/CP CLCD */
-	clk = icst_clk_register(NULL, &cp_icst_desc);
+	clk = icst_clk_register(NULL, &cp_icst_desc,
+				__io_address(INTEGRATOR_HDR_BASE));
 	clk_register_clkdev(clk, NULL, "clcd");
 }
diff --git a/drivers/clk/versatile/clk-realview.c b/drivers/clk/versatile/clk-realview.c
index e21a99c..cda07e7 100644
--- a/drivers/clk/versatile/clk-realview.c
+++ b/drivers/clk/versatile/clk-realview.c
@@ -1,3 +1,11 @@
+/*
+ * Clock driver for the ARM RealView boards
+ * Copyright (C) 2012 Linus Walleij
+ *
+ * This program is free software; you can redistribute 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/clkdev.h>
 #include <linux/err.h>
@@ -13,38 +21,6 @@
  * Implementation of the ARM RealView clock trees.
  */
 
-static void __iomem *sys_lock;
-static void __iomem *sys_vcoreg;
-
-/**
- * realview_oscvco_get() - get ICST OSC settings for the RealView
- */
-static struct icst_vco realview_oscvco_get(void)
-{
-	u32 val;
-	struct icst_vco vco;
-
-	val = readl(sys_vcoreg);
-	vco.v = val & 0x1ff;
-	vco.r = (val >> 9) & 0x7f;
-	vco.s = (val >> 16) & 03;
-	return vco;
-}
-
-static void realview_oscvco_set(struct icst_vco vco)
-{
-	u32 val;
-
-	val = readl(sys_vcoreg) & ~0x7ffff;
-	val |= vco.v | (vco.r << 9) | (vco.s << 16);
-
-	/* This magic unlocks the CM VCO so it can be controlled */
-	writel(0xa05f, sys_lock);
-	writel(val, sys_vcoreg);
-	/* This locks the CM again */
-	writel(0, sys_lock);
-}
-
 static const struct icst_params realview_oscvco_params = {
 	.ref		= 24000000,
 	.vco_max	= ICST307_VCO_MAX,
@@ -57,10 +33,16 @@ static const struct icst_params realview_oscvco_params = {
 	.idx2s		= icst307_idx2s,
 };
 
-static const struct clk_icst_desc __initdata realview_icst_desc = {
+static const struct clk_icst_desc __initdata realview_osc0_desc = {
+	.params = &realview_oscvco_params,
+	.vco_offset = REALVIEW_SYS_OSC0_OFFSET,
+	.lock_offset = REALVIEW_SYS_LOCK_OFFSET,
+};
+
+static const struct clk_icst_desc __initdata realview_osc4_desc = {
 	.params = &realview_oscvco_params,
-	.getvco = realview_oscvco_get,
-	.setvco = realview_oscvco_set,
+	.vco_offset = REALVIEW_SYS_OSC4_OFFSET,
+	.lock_offset = REALVIEW_SYS_LOCK_OFFSET,
 };
 
 /*
@@ -70,13 +52,6 @@ void __init realview_clk_init(void __iomem *sysbase, bool is_pb1176)
 {
 	struct clk *clk;
 
-	sys_lock = sysbase + REALVIEW_SYS_LOCK_OFFSET;
-	if (is_pb1176)
-		sys_vcoreg = sysbase + REALVIEW_SYS_OSC0_OFFSET;
-	else
-		sys_vcoreg = sysbase + REALVIEW_SYS_OSC4_OFFSET;
-
-
 	/* APB clock dummy */
 	clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
 	clk_register_clkdev(clk, "apb_pclk", NULL);
@@ -108,7 +83,11 @@ void __init realview_clk_init(void __iomem *sysbase, bool is_pb1176)
 	clk_register_clkdev(clk, NULL, "sp804");
 
 	/* ICST VCO clock */
-	clk = icst_clk_register(NULL, &realview_icst_desc);
+	if (is_pb1176)
+		clk = icst_clk_register(NULL, &realview_osc0_desc, sysbase);
+	else
+		clk = icst_clk_register(NULL, &realview_osc4_desc, sysbase);
+
 	clk_register_clkdev(clk, NULL, "dev:clcd");
 	clk_register_clkdev(clk, NULL, "issp:clcd");
 }
diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c
new file mode 100644
index 0000000..dcb6ae0
--- /dev/null
+++ b/drivers/clk/versatile/clk-vexpress-osc.c
@@ -0,0 +1,146 @@
+/*
+ * This program is free software; you can 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#define pr_fmt(fmt) "vexpress-osc: " fmt
+
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/vexpress.h>
+
+struct vexpress_osc {
+	struct vexpress_config_func *func;
+	struct clk_hw hw;
+	unsigned long rate_min;
+	unsigned long rate_max;
+};
+
+#define to_vexpress_osc(osc) container_of(osc, struct vexpress_osc, hw)
+
+static unsigned long vexpress_osc_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct vexpress_osc *osc = to_vexpress_osc(hw);
+	u32 rate;
+
+	vexpress_config_read(osc->func, 0, &rate);
+
+	return rate;
+}
+
+static long vexpress_osc_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *parent_rate)
+{
+	struct vexpress_osc *osc = to_vexpress_osc(hw);
+
+	if (WARN_ON(osc->rate_min && rate < osc->rate_min))
+		rate = osc->rate_min;
+
+	if (WARN_ON(osc->rate_max && rate > osc->rate_max))
+		rate = osc->rate_max;
+
+	return rate;
+}
+
+static int vexpress_osc_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct vexpress_osc *osc = to_vexpress_osc(hw);
+
+	return vexpress_config_write(osc->func, 0, rate);
+}
+
+static struct clk_ops vexpress_osc_ops = {
+	.recalc_rate = vexpress_osc_recalc_rate,
+	.round_rate = vexpress_osc_round_rate,
+	.set_rate = vexpress_osc_set_rate,
+};
+
+
+struct clk * __init vexpress_osc_setup(struct device *dev)
+{
+	struct clk_init_data init;
+	struct vexpress_osc *osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+
+	if (!osc)
+		return NULL;
+
+	osc->func = vexpress_config_func_get_by_dev(dev);
+	if (!osc->func) {
+		kfree(osc);
+		return NULL;
+	}
+
+	init.name = dev_name(dev);
+	init.ops = &vexpress_osc_ops;
+	init.flags = CLK_IS_ROOT;
+	init.num_parents = 0;
+	osc->hw.init = &init;
+
+	return clk_register(NULL, &osc->hw);
+}
+
+void __init vexpress_osc_of_setup(struct device_node *node)
+{
+	struct clk_init_data init;
+	struct vexpress_osc *osc;
+	struct clk *clk;
+	u32 range[2];
+
+	osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+	if (!osc)
+		goto error;
+
+	osc->func = vexpress_config_func_get_by_node(node);
+	if (!osc->func) {
+		pr_err("Failed to obtain config func for node '%s'!\n",
+				node->name);
+		goto error;
+	}
+
+	if (of_property_read_u32_array(node, "freq-range", range,
+			ARRAY_SIZE(range)) == 0) {
+		osc->rate_min = range[0];
+		osc->rate_max = range[1];
+	}
+
+	of_property_read_string(node, "clock-output-names", &init.name);
+	if (!init.name)
+		init.name = node->name;
+
+	init.ops = &vexpress_osc_ops;
+	init.flags = CLK_IS_ROOT;
+	init.num_parents = 0;
+
+	osc->hw.init = &init;
+
+	clk = clk_register(NULL, &osc->hw);
+	if (IS_ERR(clk)) {
+		pr_err("Failed to register clock '%s'!\n", init.name);
+		goto error;
+	}
+
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+	pr_debug("Registered clock '%s'\n", init.name);
+
+	return;
+
+error:
+	if (osc->func)
+		vexpress_config_func_put(osc->func);
+	kfree(osc);
+}
diff --git a/drivers/clk/versatile/clk-vexpress.c b/drivers/clk/versatile/clk-vexpress.c
new file mode 100644
index 0000000..c742ac7
--- /dev/null
+++ b/drivers/clk/versatile/clk-vexpress.c
@@ -0,0 +1,142 @@
+/*
+ * This program is free software; you can 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/vexpress.h>
+
+#include <asm/hardware/sp810.h>
+
+static struct clk *vexpress_sp810_timerclken[4];
+static DEFINE_SPINLOCK(vexpress_sp810_lock);
+
+static void __init vexpress_sp810_init(void __iomem *base)
+{
+	int i;
+
+	if (WARN_ON(!base))
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++) {
+		char name[12];
+		const char *parents[] = {
+			"v2m:refclk32khz", /* REFCLK */
+			"v2m:refclk1mhz" /* TIMCLK */
+		};
+
+		snprintf(name, ARRAY_SIZE(name), "timerclken%d", i);
+
+		vexpress_sp810_timerclken[i] = clk_register_mux(NULL, name,
+				parents, 2, 0, base + SCCTRL,
+				SCCTRL_TIMERENnSEL_SHIFT(i), 1,
+				0, &vexpress_sp810_lock);
+
+		if (WARN_ON(IS_ERR(vexpress_sp810_timerclken[i])))
+			break;
+	}
+}
+
+
+static const char * const vexpress_clk_24mhz_periphs[] __initconst = {
+	"mb:uart0", "mb:uart1", "mb:uart2", "mb:uart3",
+	"mb:mmci", "mb:kmi0", "mb:kmi1"
+};
+
+void __init vexpress_clk_init(void __iomem *sp810_base)
+{
+	struct clk *clk;
+	int i;
+
+	clk = clk_register_fixed_rate(NULL, "dummy_apb_pclk", NULL,
+			CLK_IS_ROOT, 0);
+	WARN_ON(clk_register_clkdev(clk, "apb_pclk", NULL));
+
+	clk = clk_register_fixed_rate(NULL, "v2m:clk_24mhz", NULL,
+			CLK_IS_ROOT, 24000000);
+	for (i = 0; i < ARRAY_SIZE(vexpress_clk_24mhz_periphs); i++)
+		WARN_ON(clk_register_clkdev(clk, NULL,
+				vexpress_clk_24mhz_periphs[i]));
+
+	clk = clk_register_fixed_rate(NULL, "v2m:refclk32khz", NULL,
+			CLK_IS_ROOT, 32768);
+	WARN_ON(clk_register_clkdev(clk, NULL, "v2m:wdt"));
+
+	clk = clk_register_fixed_rate(NULL, "v2m:refclk1mhz", NULL,
+			CLK_IS_ROOT, 1000000);
+
+	vexpress_sp810_init(sp810_base);
+
+	for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++)
+		WARN_ON(clk_set_parent(vexpress_sp810_timerclken[i], clk));
+
+	WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[0],
+				"v2m-timer0", "sp804"));
+	WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1],
+				"v2m-timer1", "sp804"));
+}
+
+#if defined(CONFIG_OF)
+
+struct clk *vexpress_sp810_of_get(struct of_phandle_args *clkspec, void *data)
+{
+	if (WARN_ON(clkspec->args_count != 1 || clkspec->args[0] >
+			ARRAY_SIZE(vexpress_sp810_timerclken)))
+		return NULL;
+
+	return vexpress_sp810_timerclken[clkspec->args[0]];
+}
+
+static const __initconst struct of_device_id vexpress_fixed_clk_match[] = {
+	{ .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
+	{ .compatible = "arm,vexpress-osc", .data = vexpress_osc_of_setup, },
+	{}
+};
+
+void __init vexpress_clk_of_init(void)
+{
+	struct device_node *node;
+	struct clk *clk;
+	struct clk *refclk, *timclk;
+
+	of_clk_init(vexpress_fixed_clk_match);
+
+	node = of_find_compatible_node(NULL, NULL, "arm,sp810");
+	vexpress_sp810_init(of_iomap(node, 0));
+	of_clk_add_provider(node, vexpress_sp810_of_get, NULL);
+
+	/* Select "better" (faster) parent for SP804 timers */
+	refclk = of_clk_get_by_name(node, "refclk");
+	timclk = of_clk_get_by_name(node, "timclk");
+	if (!WARN_ON(IS_ERR(refclk) || IS_ERR(timclk))) {
+		int i = 0;
+
+		if (clk_get_rate(refclk) > clk_get_rate(timclk))
+			clk = refclk;
+		else
+			clk = timclk;
+
+		for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++)
+			WARN_ON(clk_set_parent(vexpress_sp810_timerclken[i],
+					clk));
+	}
+
+	WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[0],
+				"v2m-timer0", "sp804"));
+	WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1],
+				"v2m-timer1", "sp804"));
+}
+
+#endif
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 6a78073..3938543 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -22,6 +22,24 @@ config DW_APB_TIMER_OF
 config ARMADA_370_XP_TIMER
 	bool
 
+config CLKSRC_NOMADIK_MTU
+	bool
+	depends on (ARCH_NOMADIK || ARCH_U8500)
+	select CLKSRC_MMIO
+	help
+	  Support for Multi Timer Unit. MTU provides access
+	  to multiple interrupt generating programmable
+	  32-bit free running decrementing counters.
+
+config CLKSRC_NOMADIK_MTU_SCHED_CLOCK
+	bool
+	depends on CLKSRC_NOMADIK_MTU
+	help
+	  Use the Multi Timer Unit as the sched_clock.
+
+config SUNXI_TIMER
+	bool
+
 config CLKSRC_DBX500_PRCMU
 	bool "Clocksource PRCMU Timer"
 	depends on UX500_SOC_DB8500
@@ -31,7 +49,7 @@ config CLKSRC_DBX500_PRCMU
 
 config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
 	bool "Clocksource PRCMU Timer sched_clock"
-	depends on (CLKSRC_DBX500_PRCMU && !NOMADIK_MTU_SCHED_CLOCK)
+	depends on (CLKSRC_DBX500_PRCMU && !CLKSRC_NOMADIK_MTU_SCHED_CLOCK)
 	default y
 	help
 	  Use the always on PRCMU Timer as sched_clock
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 603be36..f93453d 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -11,8 +11,10 @@ obj-$(CONFIG_CLKBLD_I8253)	+= i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)	+= mmio.o
 obj-$(CONFIG_DW_APB_TIMER)	+= dw_apb_timer.o
 obj-$(CONFIG_DW_APB_TIMER_OF)	+= dw_apb_timer_of.o
+obj-$(CONFIG_CLKSRC_NOMADIK_MTU)	+= nomadik-mtu.o
 obj-$(CONFIG_CLKSRC_DBX500_PRCMU)	+= clksrc-dbx500-prcmu.o
 obj-$(CONFIG_ARMADA_370_XP_TIMER)	+= time-armada-370-xp.o
 obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835_timer.o
+obj-$(CONFIG_SUNXI_TIMER)	+= sunxi_timer.o
 
 obj-$(CONFIG_CLKSRC_ARM_GENERIC)	+= arm_generic.o
diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c
new file mode 100644
index 0000000..8914c3c
--- /dev/null
+++ b/drivers/clocksource/nomadik-mtu.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2008 STMicroelectronics
+ * Copyright (C) 2010 Alessandro Rubini
+ * Copyright (C) 2010 Linus Walleij for ST-Ericsson
+ *
+ * This program is free software; you can redistribute 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/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/clk.h>
+#include <linux/jiffies.h>
+#include <linux/err.h>
+#include <linux/platform_data/clocksource-nomadik-mtu.h>
+#include <asm/mach/time.h>
+#include <asm/sched_clock.h>
+
+/*
+ * The MTU device hosts four different counters, with 4 set of
+ * registers. These are register names.
+ */
+
+#define MTU_IMSC	0x00	/* Interrupt mask set/clear */
+#define MTU_RIS		0x04	/* Raw interrupt status */
+#define MTU_MIS		0x08	/* Masked interrupt status */
+#define MTU_ICR		0x0C	/* Interrupt clear register */
+
+/* per-timer registers take 0..3 as argument */
+#define MTU_LR(x)	(0x10 + 0x10 * (x) + 0x00)	/* Load value */
+#define MTU_VAL(x)	(0x10 + 0x10 * (x) + 0x04)	/* Current value */
+#define MTU_CR(x)	(0x10 + 0x10 * (x) + 0x08)	/* Control reg */
+#define MTU_BGLR(x)	(0x10 + 0x10 * (x) + 0x0c)	/* At next overflow */
+
+/* bits for the control register */
+#define MTU_CRn_ENA		0x80
+#define MTU_CRn_PERIODIC	0x40	/* if 0 = free-running */
+#define MTU_CRn_PRESCALE_MASK	0x0c
+#define MTU_CRn_PRESCALE_1		0x00
+#define MTU_CRn_PRESCALE_16		0x04
+#define MTU_CRn_PRESCALE_256		0x08
+#define MTU_CRn_32BITS		0x02
+#define MTU_CRn_ONESHOT		0x01	/* if 0 = wraps reloading from BGLR*/
+
+/* Other registers are usual amba/primecell registers, currently not used */
+#define MTU_ITCR	0xff0
+#define MTU_ITOP	0xff4
+
+#define MTU_PERIPH_ID0	0xfe0
+#define MTU_PERIPH_ID1	0xfe4
+#define MTU_PERIPH_ID2	0xfe8
+#define MTU_PERIPH_ID3	0xfeC
+
+#define MTU_PCELL0	0xff0
+#define MTU_PCELL1	0xff4
+#define MTU_PCELL2	0xff8
+#define MTU_PCELL3	0xffC
+
+static void __iomem *mtu_base;
+static bool clkevt_periodic;
+static u32 clk_prescale;
+static u32 nmdk_cycle;		/* write-once */
+
+#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
+/*
+ * Override the global weak sched_clock symbol with this
+ * local implementation which uses the clocksource to get some
+ * better resolution when scheduling the kernel.
+ */
+static u32 notrace nomadik_read_sched_clock(void)
+{
+	if (unlikely(!mtu_base))
+		return 0;
+
+	return -readl(mtu_base + MTU_VAL(0));
+}
+#endif
+
+/* Clockevent device: use one-shot mode */
+static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev)
+{
+	writel(1 << 1, mtu_base + MTU_IMSC);
+	writel(evt, mtu_base + MTU_LR(1));
+	/* Load highest value, enable device, enable interrupts */
+	writel(MTU_CRn_ONESHOT | clk_prescale |
+	       MTU_CRn_32BITS | MTU_CRn_ENA,
+	       mtu_base + MTU_CR(1));
+
+	return 0;
+}
+
+void nmdk_clkevt_reset(void)
+{
+	if (clkevt_periodic) {
+		/* Timer: configure load and background-load, and fire it up */
+		writel(nmdk_cycle, mtu_base + MTU_LR(1));
+		writel(nmdk_cycle, mtu_base + MTU_BGLR(1));
+
+		writel(MTU_CRn_PERIODIC | clk_prescale |
+		       MTU_CRn_32BITS | MTU_CRn_ENA,
+		       mtu_base + MTU_CR(1));
+		writel(1 << 1, mtu_base + MTU_IMSC);
+	} else {
+		/* Generate an interrupt to start the clockevent again */
+		(void) nmdk_clkevt_next(nmdk_cycle, NULL);
+	}
+}
+
+static void nmdk_clkevt_mode(enum clock_event_mode mode,
+			     struct clock_event_device *dev)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		clkevt_periodic = true;
+		nmdk_clkevt_reset();
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		clkevt_periodic = false;
+		break;
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+		writel(0, mtu_base + MTU_IMSC);
+		/* disable timer */
+		writel(0, mtu_base + MTU_CR(1));
+		/* load some high default value */
+		writel(0xffffffff, mtu_base + MTU_LR(1));
+		break;
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static struct clock_event_device nmdk_clkevt = {
+	.name		= "mtu_1",
+	.features	= CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
+	.rating		= 200,
+	.set_mode	= nmdk_clkevt_mode,
+	.set_next_event	= nmdk_clkevt_next,
+};
+
+/*
+ * IRQ Handler for timer 1 of the MTU block.
+ */
+static irqreturn_t nmdk_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evdev = dev_id;
+
+	writel(1 << 1, mtu_base + MTU_ICR); /* Interrupt clear reg */
+	evdev->event_handler(evdev);
+	return IRQ_HANDLED;
+}
+
+static struct irqaction nmdk_timer_irq = {
+	.name		= "Nomadik Timer Tick",
+	.flags		= IRQF_DISABLED | IRQF_TIMER,
+	.handler	= nmdk_timer_interrupt,
+	.dev_id		= &nmdk_clkevt,
+};
+
+void nmdk_clksrc_reset(void)
+{
+	/* Disable */
+	writel(0, mtu_base + MTU_CR(0));
+
+	/* ClockSource: configure load and background-load, and fire it up */
+	writel(nmdk_cycle, mtu_base + MTU_LR(0));
+	writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
+
+	writel(clk_prescale | MTU_CRn_32BITS | MTU_CRn_ENA,
+	       mtu_base + MTU_CR(0));
+}
+
+void __init nmdk_timer_init(void __iomem *base, int irq)
+{
+	unsigned long rate;
+	struct clk *clk0, *pclk0;
+
+	mtu_base = base;
+
+	pclk0 = clk_get_sys("mtu0", "apb_pclk");
+	BUG_ON(IS_ERR(pclk0));
+	BUG_ON(clk_prepare(pclk0) < 0);
+	BUG_ON(clk_enable(pclk0) < 0);
+
+	clk0 = clk_get_sys("mtu0", NULL);
+	BUG_ON(IS_ERR(clk0));
+	BUG_ON(clk_prepare(clk0) < 0);
+	BUG_ON(clk_enable(clk0) < 0);
+
+	/*
+	 * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz
+	 * for ux500.
+	 * Use a divide-by-16 counter if the tick rate is more than 32MHz.
+	 * At 32 MHz, the timer (with 32 bit counter) can be programmed
+	 * to wake-up at a max 127s a head in time. Dividing a 2.4 MHz timer
+	 * with 16 gives too low timer resolution.
+	 */
+	rate = clk_get_rate(clk0);
+	if (rate > 32000000) {
+		rate /= 16;
+		clk_prescale = MTU_CRn_PRESCALE_16;
+	} else {
+		clk_prescale = MTU_CRn_PRESCALE_1;
+	}
+
+	/* Cycles for periodic mode */
+	nmdk_cycle = DIV_ROUND_CLOSEST(rate, HZ);
+
+
+	/* Timer 0 is the free running clocksource */
+	nmdk_clksrc_reset();
+
+	if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0",
+			rate, 200, 32, clocksource_mmio_readl_down))
+		pr_err("timer: failed to initialize clock source %s\n",
+		       "mtu_0");
+
+#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
+	setup_sched_clock(nomadik_read_sched_clock, 32, rate);
+#endif
+
+	/* Timer 1 is used for events, register irq and clockevents */
+	setup_irq(irq, &nmdk_timer_irq);
+	nmdk_clkevt.cpumask = cpumask_of(0);
+	clockevents_config_and_register(&nmdk_clkevt, rate, 2, 0xffffffffU);
+}
diff --git a/drivers/clocksource/sunxi_timer.c b/drivers/clocksource/sunxi_timer.c
new file mode 100644
index 0000000..3c46434
--- /dev/null
+++ b/drivers/clocksource/sunxi_timer.c
@@ -0,0 +1,170 @@
+/*
+ * Allwinner A1X SoCs timer handling.
+ *
+ * Copyright (C) 2012 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * Based on code from
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Benn Huang <benn@allwinnertech.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqreturn.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sunxi_timer.h>
+#include <linux/clk/sunxi.h>
+
+#define TIMER_CTL_REG		0x00
+#define TIMER_CTL_ENABLE		(1 << 0)
+#define TIMER_IRQ_ST_REG	0x04
+#define TIMER0_CTL_REG		0x10
+#define TIMER0_CTL_ENABLE		(1 << 0)
+#define TIMER0_CTL_AUTORELOAD		(1 << 1)
+#define TIMER0_CTL_ONESHOT		(1 << 7)
+#define TIMER0_INTVAL_REG	0x14
+#define TIMER0_CNTVAL_REG	0x18
+
+#define TIMER_SCAL		16
+
+static void __iomem *timer_base;
+
+static void sunxi_clkevt_mode(enum clock_event_mode mode,
+			      struct clock_event_device *clk)
+{
+	u32 u = readl(timer_base + TIMER0_CTL_REG);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		u &= ~(TIMER0_CTL_ONESHOT);
+		writel(u | TIMER0_CTL_ENABLE, timer_base + TIMER0_CTL_REG);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+		writel(u | TIMER0_CTL_ONESHOT, timer_base + TIMER0_CTL_REG);
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	default:
+		writel(u & ~(TIMER0_CTL_ENABLE), timer_base + TIMER0_CTL_REG);
+		break;
+	}
+}
+
+static int sunxi_clkevt_next_event(unsigned long evt,
+				   struct clock_event_device *unused)
+{
+	u32 u = readl(timer_base + TIMER0_CTL_REG);
+	writel(evt, timer_base + TIMER0_CNTVAL_REG);
+	writel(u | TIMER0_CTL_ENABLE | TIMER0_CTL_AUTORELOAD,
+	       timer_base + TIMER0_CTL_REG);
+
+	return 0;
+}
+
+static struct clock_event_device sunxi_clockevent = {
+	.name = "sunxi_tick",
+	.shift = 32,
+	.rating = 300,
+	.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_mode = sunxi_clkevt_mode,
+	.set_next_event = sunxi_clkevt_next_event,
+};
+
+
+static irqreturn_t sunxi_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = (struct clock_event_device *)dev_id;
+
+	writel(0x1, timer_base + TIMER_IRQ_ST_REG);
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction sunxi_timer_irq = {
+	.name = "sunxi_timer0",
+	.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler = sunxi_timer_interrupt,
+	.dev_id = &sunxi_clockevent,
+};
+
+static struct of_device_id sunxi_timer_dt_ids[] = {
+	{ .compatible = "allwinner,sunxi-timer" },
+};
+
+static void __init sunxi_timer_init(void)
+{
+	struct device_node *node;
+	unsigned long rate = 0;
+	struct clk *clk;
+	int ret, irq;
+	u32 val;
+
+	node = of_find_matching_node(NULL, sunxi_timer_dt_ids);
+	if (!node)
+		panic("No sunxi timer node");
+
+	timer_base = of_iomap(node, 0);
+	if (!timer_base)
+		panic("Can't map registers");
+
+	irq = irq_of_parse_and_map(node, 0);
+	if (irq <= 0)
+		panic("Can't parse IRQ");
+
+	sunxi_init_clocks();
+
+	clk = of_clk_get(node, 0);
+	if (IS_ERR(clk))
+		panic("Can't get timer clock");
+
+	rate = clk_get_rate(clk);
+
+	writel(rate / (TIMER_SCAL * HZ),
+	       timer_base + TIMER0_INTVAL_REG);
+
+	/* set clock source to HOSC, 16 pre-division */
+	val = readl(timer_base + TIMER0_CTL_REG);
+	val &= ~(0x07 << 4);
+	val &= ~(0x03 << 2);
+	val |= (4 << 4) | (1 << 2);
+	writel(val, timer_base + TIMER0_CTL_REG);
+
+	/* set mode to auto reload */
+	val = readl(timer_base + TIMER0_CTL_REG);
+	writel(val | TIMER0_CTL_AUTORELOAD, timer_base + TIMER0_CTL_REG);
+
+	ret = setup_irq(irq, &sunxi_timer_irq);
+	if (ret)
+		pr_warn("failed to setup irq %d\n", irq);
+
+	/* Enable timer0 interrupt */
+	val = readl(timer_base + TIMER_CTL_REG);
+	writel(val | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG);
+
+	sunxi_clockevent.mult = div_sc(rate / TIMER_SCAL,
+				NSEC_PER_SEC,
+				sunxi_clockevent.shift);
+	sunxi_clockevent.max_delta_ns = clockevent_delta2ns(0xff,
+							    &sunxi_clockevent);
+	sunxi_clockevent.min_delta_ns = clockevent_delta2ns(0x1,
+							    &sunxi_clockevent);
+	sunxi_clockevent.cpumask = cpumask_of(0);
+
+	clockevents_register_device(&sunxi_clockevent);
+}
+
+struct sys_timer sunxi_timer = {
+	.init = sunxi_timer_init,
+};
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 5961e64..ee0ef07 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -21,8 +21,8 @@ config ARM_S3C2416_CPUFREQ
 	  If in doubt, say N.
 
 config ARM_S3C2416_CPUFREQ_VCORESCALE
-	bool "Allow voltage scaling for S3C2416 arm core (EXPERIMENTAL)"
-	depends on ARM_S3C2416_CPUFREQ && REGULATOR && EXPERIMENTAL
+	bool "Allow voltage scaling for S3C2416 arm core"
+	depends on ARM_S3C2416_CPUFREQ && REGULATOR
 	help
 	  Enable CPU voltage scaling when entering the dvs mode.
 	  It uses information gathered through existing hardware and
@@ -76,3 +76,10 @@ config ARM_EXYNOS5250_CPUFREQ
 	help
 	  This adds the CPUFreq driver for Samsung EXYNOS5250
 	  SoC.
+
+config ARM_SPEAR_CPUFREQ
+	bool "SPEAr CPUFreq support"
+	depends on PLAT_SPEAR
+	default y
+	help
+	  This adds the CPUFreq driver support for SPEAr SOCs.
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
index 934854a..0715d8e 100644
--- a/drivers/cpufreq/Kconfig.x86
+++ b/drivers/cpufreq/Kconfig.x86
@@ -174,7 +174,7 @@ config X86_SPEEDSTEP_ICH
 config X86_SPEEDSTEP_SMI
 	tristate "Intel SpeedStep on 440BX/ZX/MX chipsets (SMI interface)"
 	select CPU_FREQ_TABLE
-	depends on X86_32 && EXPERIMENTAL
+	depends on X86_32
 	help
 	  This adds the CPUFreq driver for certain mobile Intel Pentium III
 	  (Coppermine), all mobile Intel Pentium III-M (Tualatin)
@@ -206,7 +206,7 @@ config X86_P4_CLOCKMOD
 
 config X86_CPUFREQ_NFORCE2
 	tristate "nVidia nForce2 FSB changing"
-	depends on X86_32 && EXPERIMENTAL
+	depends on X86_32
 	help
 	  This adds the CPUFreq driver for FSB changing on nVidia nForce2
 	  platforms.
@@ -242,7 +242,7 @@ config X86_LONGHAUL
 config X86_E_POWERSAVER
 	tristate "VIA C7 Enhanced PowerSaver (DANGEROUS)"
 	select CPU_FREQ_TABLE
-	depends on X86_32 && EXPERIMENTAL
+	depends on X86_32
 	help
 	  This adds the CPUFreq driver for VIA C7 processors.  However, this driver
 	  does not have any safeguards to prevent operating the CPU out of spec
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 1bc90e1..1f254ec0 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -7,8 +7,8 @@ obj-$(CONFIG_CPU_FREQ_STAT)             += cpufreq_stats.o
 obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE)	+= cpufreq_performance.o
 obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE)	+= cpufreq_powersave.o
 obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE)	+= cpufreq_userspace.o
-obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND)	+= cpufreq_ondemand.o
-obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)	+= cpufreq_conservative.o
+obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND)	+= cpufreq_ondemand.o cpufreq_governor.o
+obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)	+= cpufreq_conservative.o cpufreq_governor.o
 
 # CPUfreq cross-arch helpers
 obj-$(CONFIG_CPU_FREQ_TABLE)		+= freq_table.o
@@ -50,6 +50,7 @@ obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ)	+= exynos4210-cpufreq.o
 obj-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ)	+= exynos4x12-cpufreq.o
 obj-$(CONFIG_ARM_EXYNOS5250_CPUFREQ)	+= exynos5250-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)     += omap-cpufreq.o
+obj-$(CONFIG_ARM_SPEAR_CPUFREQ)		+= spear-cpufreq.o
 
 ##################################################################################
 # PowerPC platform drivers
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index e915827..52bf36d 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -174,7 +174,7 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
 	.attr = cpu0_cpufreq_attr,
 };
 
-static int __devinit cpu0_cpufreq_driver_init(void)
+static int cpu0_cpufreq_driver_init(void)
 {
 	struct device_node *np;
 	int ret;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index fb8a527..1f93dbd 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -15,6 +15,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -127,7 +129,7 @@ static int __init init_cpufreq_transition_notifier_list(void)
 pure_initcall(init_cpufreq_transition_notifier_list);
 
 static int off __read_mostly;
-int cpufreq_disabled(void)
+static int cpufreq_disabled(void)
 {
 	return off;
 }
@@ -402,7 +404,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
 static ssize_t store_##file_name					\
 (struct cpufreq_policy *policy, const char *buf, size_t count)		\
 {									\
-	unsigned int ret = -EINVAL;					\
+	unsigned int ret;						\
 	struct cpufreq_policy new_policy;				\
 									\
 	ret = cpufreq_get_policy(&new_policy, policy->cpu);		\
@@ -445,7 +447,7 @@ static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
 	else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
 		return sprintf(buf, "performance\n");
 	else if (policy->governor)
-		return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n",
+		return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n",
 				policy->governor->name);
 	return -EINVAL;
 }
@@ -457,7 +459,7 @@ static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
 static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
 					const char *buf, size_t count)
 {
-	unsigned int ret = -EINVAL;
+	unsigned int ret;
 	char	str_governor[16];
 	struct cpufreq_policy new_policy;
 
@@ -491,7 +493,7 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
  */
 static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf)
 {
-	return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name);
+	return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", cpufreq_driver->name);
 }
 
 /**
@@ -512,7 +514,7 @@ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy,
 		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char))
 		    - (CPUFREQ_NAME_LEN + 2)))
 			goto out;
-		i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name);
+		i += scnprintf(&buf[i], CPUFREQ_NAME_PLEN, "%s ", t->name);
 	}
 out:
 	i += sprintf(&buf[i], "\n");
@@ -581,7 +583,7 @@ static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf)
 }
 
 /**
- * show_scaling_driver - show the current cpufreq HW/BIOS limitation
+ * show_bios_limit - show the current cpufreq HW/BIOS limitation
  */
 static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf)
 {
@@ -1468,12 +1470,23 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
 			    unsigned int relation)
 {
 	int retval = -EINVAL;
+	unsigned int old_target_freq = target_freq;
 
 	if (cpufreq_disabled())
 		return -ENODEV;
 
-	pr_debug("target for CPU %u: %u kHz, relation %u\n", policy->cpu,
-		target_freq, relation);
+	/* Make sure that target_freq is within supported range */
+	if (target_freq > policy->max)
+		target_freq = policy->max;
+	if (target_freq < policy->min)
+		target_freq = policy->min;
+
+	pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
+			policy->cpu, target_freq, relation, old_target_freq);
+
+	if (target_freq == policy->cur)
+		return 0;
+
 	if (cpu_online(policy->cpu) && cpufreq_driver->target)
 		retval = cpufreq_driver->target(policy, target_freq, relation);
 
@@ -1509,12 +1522,14 @@ int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu)
 {
 	int ret = 0;
 
+	if (!(cpu_online(cpu) && cpufreq_driver->getavg))
+		return 0;
+
 	policy = cpufreq_cpu_get(policy->cpu);
 	if (!policy)
 		return -EINVAL;
 
-	if (cpu_online(cpu) && cpufreq_driver->getavg)
-		ret = cpufreq_driver->getavg(policy, cpu);
+	ret = cpufreq_driver->getavg(policy, cpu);
 
 	cpufreq_cpu_put(policy);
 	return ret;
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index a152af7..64ef737 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -11,83 +11,30 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
 #include <linux/cpufreq.h>
-#include <linux/cpu.h>
-#include <linux/jiffies.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/kernel_stat.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
-#include <linux/hrtimer.h>
-#include <linux/tick.h>
-#include <linux/ktime.h>
-#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/percpu-defs.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
 
-/*
- * dbs is used in this file as a shortform for demandbased switching
- * It helps to keep variable names smaller, simpler
- */
+#include "cpufreq_governor.h"
 
+/* Conservative governor macors */
 #define DEF_FREQUENCY_UP_THRESHOLD		(80)
 #define DEF_FREQUENCY_DOWN_THRESHOLD		(20)
-
-/*
- * The polling frequency of this governor depends on the capability of
- * the processor. Default polling frequency is 1000 times the transition
- * latency of the processor. The governor will work on any processor with
- * transition latency <= 10mS, using appropriate sampling
- * rate.
- * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
- * this governor will not work.
- * All times here are in uS.
- */
-#define MIN_SAMPLING_RATE_RATIO			(2)
-
-static unsigned int min_sampling_rate;
-
-#define LATENCY_MULTIPLIER			(1000)
-#define MIN_LATENCY_MULTIPLIER			(100)
 #define DEF_SAMPLING_DOWN_FACTOR		(1)
 #define MAX_SAMPLING_DOWN_FACTOR		(10)
-#define TRANSITION_LATENCY_LIMIT		(10 * 1000 * 1000)
-
-static void do_dbs_timer(struct work_struct *work);
-
-struct cpu_dbs_info_s {
-	cputime64_t prev_cpu_idle;
-	cputime64_t prev_cpu_wall;
-	cputime64_t prev_cpu_nice;
-	struct cpufreq_policy *cur_policy;
-	struct delayed_work work;
-	unsigned int down_skip;
-	unsigned int requested_freq;
-	int cpu;
-	unsigned int enable:1;
-	/*
-	 * percpu mutex that serializes governor limit change with
-	 * do_dbs_timer invocation. We do not want do_dbs_timer to run
-	 * when user is changing the governor or limits.
-	 */
-	struct mutex timer_mutex;
-};
-static DEFINE_PER_CPU(struct cpu_dbs_info_s, cs_cpu_dbs_info);
 
-static unsigned int dbs_enable;	/* number of CPUs using this policy */
+static struct dbs_data cs_dbs_data;
+static DEFINE_PER_CPU(struct cs_cpu_dbs_info_s, cs_cpu_dbs_info);
 
-/*
- * dbs_mutex protects dbs_enable in governor start/stop.
- */
-static DEFINE_MUTEX(dbs_mutex);
-
-static struct dbs_tuners {
-	unsigned int sampling_rate;
-	unsigned int sampling_down_factor;
-	unsigned int up_threshold;
-	unsigned int down_threshold;
-	unsigned int ignore_nice;
-	unsigned int freq_step;
-} dbs_tuners_ins = {
+static struct cs_dbs_tuners cs_tuners = {
 	.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
 	.down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD,
 	.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
@@ -95,95 +42,121 @@ static struct dbs_tuners {
 	.freq_step = 5,
 };
 
-static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
+/*
+ * Every sampling_rate, we check, if current idle time is less than 20%
+ * (default), then we try to increase frequency Every sampling_rate *
+ * sampling_down_factor, we check, if current idle time is more than 80%, then
+ * we try to decrease frequency
+ *
+ * Any frequency increase takes it to the maximum frequency. Frequency reduction
+ * happens at minimum steps of 5% (default) of maximum frequency
+ */
+static void cs_check_cpu(int cpu, unsigned int load)
 {
-	u64 idle_time;
-	u64 cur_wall_time;
-	u64 busy_time;
+	struct cs_cpu_dbs_info_s *dbs_info = &per_cpu(cs_cpu_dbs_info, cpu);
+	struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
+	unsigned int freq_target;
+
+	/*
+	 * break out if we 'cannot' reduce the speed as the user might
+	 * want freq_step to be zero
+	 */
+	if (cs_tuners.freq_step == 0)
+		return;
 
-	cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
+	/* Check for frequency increase */
+	if (load > cs_tuners.up_threshold) {
+		dbs_info->down_skip = 0;
 
-	busy_time  = kcpustat_cpu(cpu).cpustat[CPUTIME_USER];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE];
+		/* if we are already at full speed then break out early */
+		if (dbs_info->requested_freq == policy->max)
+			return;
 
-	idle_time = cur_wall_time - busy_time;
-	if (wall)
-		*wall = jiffies_to_usecs(cur_wall_time);
+		freq_target = (cs_tuners.freq_step * policy->max) / 100;
 
-	return jiffies_to_usecs(idle_time);
+		/* max freq cannot be less than 100. But who knows.... */
+		if (unlikely(freq_target == 0))
+			freq_target = 5;
+
+		dbs_info->requested_freq += freq_target;
+		if (dbs_info->requested_freq > policy->max)
+			dbs_info->requested_freq = policy->max;
+
+		__cpufreq_driver_target(policy, dbs_info->requested_freq,
+			CPUFREQ_RELATION_H);
+		return;
+	}
+
+	/*
+	 * The optimal frequency is the frequency that is the lowest that can
+	 * support the current CPU usage without triggering the up policy. To be
+	 * safe, we focus 10 points under the threshold.
+	 */
+	if (load < (cs_tuners.down_threshold - 10)) {
+		freq_target = (cs_tuners.freq_step * policy->max) / 100;
+
+		dbs_info->requested_freq -= freq_target;
+		if (dbs_info->requested_freq < policy->min)
+			dbs_info->requested_freq = policy->min;
+
+		/*
+		 * if we cannot reduce the frequency anymore, break out early
+		 */
+		if (policy->cur == policy->min)
+			return;
+
+		__cpufreq_driver_target(policy, dbs_info->requested_freq,
+				CPUFREQ_RELATION_H);
+		return;
+	}
 }
 
-static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
+static void cs_dbs_timer(struct work_struct *work)
 {
-	u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
+	struct cs_cpu_dbs_info_s *dbs_info = container_of(work,
+			struct cs_cpu_dbs_info_s, cdbs.work.work);
+	unsigned int cpu = dbs_info->cdbs.cpu;
+	int delay = delay_for_sampling_rate(cs_tuners.sampling_rate);
 
-	if (idle_time == -1ULL)
-		return get_cpu_idle_time_jiffy(cpu, wall);
-	else
-		idle_time += get_cpu_iowait_time_us(cpu, wall);
+	mutex_lock(&dbs_info->cdbs.timer_mutex);
 
-	return idle_time;
+	dbs_check_cpu(&cs_dbs_data, cpu);
+
+	schedule_delayed_work_on(cpu, &dbs_info->cdbs.work, delay);
+	mutex_unlock(&dbs_info->cdbs.timer_mutex);
 }
 
-/* keep track of frequency transitions */
-static int
-dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
-		     void *data)
+static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
+		void *data)
 {
 	struct cpufreq_freqs *freq = data;
-	struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cs_cpu_dbs_info,
-							freq->cpu);
-
+	struct cs_cpu_dbs_info_s *dbs_info =
+					&per_cpu(cs_cpu_dbs_info, freq->cpu);
 	struct cpufreq_policy *policy;
 
-	if (!this_dbs_info->enable)
+	if (!dbs_info->enable)
 		return 0;
 
-	policy = this_dbs_info->cur_policy;
+	policy = dbs_info->cdbs.cur_policy;
 
 	/*
-	 * we only care if our internally tracked freq moves outside
-	 * the 'valid' ranges of freqency available to us otherwise
-	 * we do not change it
+	 * we only care if our internally tracked freq moves outside the 'valid'
+	 * ranges of freqency available to us otherwise we do not change it
 	*/
-	if (this_dbs_info->requested_freq > policy->max
-			|| this_dbs_info->requested_freq < policy->min)
-		this_dbs_info->requested_freq = freq->new;
+	if (dbs_info->requested_freq > policy->max
+			|| dbs_info->requested_freq < policy->min)
+		dbs_info->requested_freq = freq->new;
 
 	return 0;
 }
 
-static struct notifier_block dbs_cpufreq_notifier_block = {
-	.notifier_call = dbs_cpufreq_notifier
-};
-
 /************************** sysfs interface ************************/
 static ssize_t show_sampling_rate_min(struct kobject *kobj,
 				      struct attribute *attr, char *buf)
 {
-	return sprintf(buf, "%u\n", min_sampling_rate);
+	return sprintf(buf, "%u\n", cs_dbs_data.min_sampling_rate);
 }
 
-define_one_global_ro(sampling_rate_min);
-
-/* cpufreq_conservative Governor Tunables */
-#define show_one(file_name, object)					\
-static ssize_t show_##file_name						\
-(struct kobject *kobj, struct attribute *attr, char *buf)		\
-{									\
-	return sprintf(buf, "%u\n", dbs_tuners_ins.object);		\
-}
-show_one(sampling_rate, sampling_rate);
-show_one(sampling_down_factor, sampling_down_factor);
-show_one(up_threshold, up_threshold);
-show_one(down_threshold, down_threshold);
-show_one(ignore_nice_load, ignore_nice);
-show_one(freq_step, freq_step);
-
 static ssize_t store_sampling_down_factor(struct kobject *a,
 					  struct attribute *b,
 					  const char *buf, size_t count)
@@ -195,7 +168,7 @@ static ssize_t store_sampling_down_factor(struct kobject *a,
 	if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
 		return -EINVAL;
 
-	dbs_tuners_ins.sampling_down_factor = input;
+	cs_tuners.sampling_down_factor = input;
 	return count;
 }
 
@@ -209,7 +182,7 @@ static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
 	if (ret != 1)
 		return -EINVAL;
 
-	dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate);
+	cs_tuners.sampling_rate = max(input, cs_dbs_data.min_sampling_rate);
 	return count;
 }
 
@@ -220,11 +193,10 @@ static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
 	int ret;
 	ret = sscanf(buf, "%u", &input);
 
-	if (ret != 1 || input > 100 ||
-			input <= dbs_tuners_ins.down_threshold)
+	if (ret != 1 || input > 100 || input <= cs_tuners.down_threshold)
 		return -EINVAL;
 
-	dbs_tuners_ins.up_threshold = input;
+	cs_tuners.up_threshold = input;
 	return count;
 }
 
@@ -237,21 +209,19 @@ static ssize_t store_down_threshold(struct kobject *a, struct attribute *b,
 
 	/* cannot be lower than 11 otherwise freq will not fall */
 	if (ret != 1 || input < 11 || input > 100 ||
-			input >= dbs_tuners_ins.up_threshold)
+			input >= cs_tuners.up_threshold)
 		return -EINVAL;
 
-	dbs_tuners_ins.down_threshold = input;
+	cs_tuners.down_threshold = input;
 	return count;
 }
 
 static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
 				      const char *buf, size_t count)
 {
-	unsigned int input;
+	unsigned int input, j;
 	int ret;
 
-	unsigned int j;
-
 	ret = sscanf(buf, "%u", &input);
 	if (ret != 1)
 		return -EINVAL;
@@ -259,19 +229,20 @@ static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
 	if (input > 1)
 		input = 1;
 
-	if (input == dbs_tuners_ins.ignore_nice) /* nothing to do */
+	if (input == cs_tuners.ignore_nice) /* nothing to do */
 		return count;
 
-	dbs_tuners_ins.ignore_nice = input;
+	cs_tuners.ignore_nice = input;
 
 	/* we need to re-evaluate prev_cpu_idle */
 	for_each_online_cpu(j) {
-		struct cpu_dbs_info_s *dbs_info;
+		struct cs_cpu_dbs_info_s *dbs_info;
 		dbs_info = &per_cpu(cs_cpu_dbs_info, j);
-		dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
-						&dbs_info->prev_cpu_wall);
-		if (dbs_tuners_ins.ignore_nice)
-			dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+		dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
+						&dbs_info->cdbs.prev_cpu_wall);
+		if (cs_tuners.ignore_nice)
+			dbs_info->cdbs.prev_cpu_nice =
+				kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 	}
 	return count;
 }
@@ -289,18 +260,28 @@ static ssize_t store_freq_step(struct kobject *a, struct attribute *b,
 	if (input > 100)
 		input = 100;
 
-	/* no need to test here if freq_step is zero as the user might actually
-	 * want this, they would be crazy though :) */
-	dbs_tuners_ins.freq_step = input;
+	/*
+	 * no need to test here if freq_step is zero as the user might actually
+	 * want this, they would be crazy though :)
+	 */
+	cs_tuners.freq_step = input;
 	return count;
 }
 
+show_one(cs, sampling_rate, sampling_rate);
+show_one(cs, sampling_down_factor, sampling_down_factor);
+show_one(cs, up_threshold, up_threshold);
+show_one(cs, down_threshold, down_threshold);
+show_one(cs, ignore_nice_load, ignore_nice);
+show_one(cs, freq_step, freq_step);
+
 define_one_global_rw(sampling_rate);
 define_one_global_rw(sampling_down_factor);
 define_one_global_rw(up_threshold);
 define_one_global_rw(down_threshold);
 define_one_global_rw(ignore_nice_load);
 define_one_global_rw(freq_step);
+define_one_global_ro(sampling_rate_min);
 
 static struct attribute *dbs_attributes[] = {
 	&sampling_rate_min.attr,
@@ -313,283 +294,38 @@ static struct attribute *dbs_attributes[] = {
 	NULL
 };
 
-static struct attribute_group dbs_attr_group = {
+static struct attribute_group cs_attr_group = {
 	.attrs = dbs_attributes,
 	.name = "conservative",
 };
 
 /************************** sysfs end ************************/
 
-static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
-{
-	unsigned int load = 0;
-	unsigned int max_load = 0;
-	unsigned int freq_target;
-
-	struct cpufreq_policy *policy;
-	unsigned int j;
-
-	policy = this_dbs_info->cur_policy;
-
-	/*
-	 * Every sampling_rate, we check, if current idle time is less
-	 * than 20% (default), then we try to increase frequency
-	 * Every sampling_rate*sampling_down_factor, we check, if current
-	 * idle time is more than 80%, then we try to decrease frequency
-	 *
-	 * Any frequency increase takes it to the maximum frequency.
-	 * Frequency reduction happens at minimum steps of
-	 * 5% (default) of maximum frequency
-	 */
-
-	/* Get Absolute Load */
-	for_each_cpu(j, policy->cpus) {
-		struct cpu_dbs_info_s *j_dbs_info;
-		cputime64_t cur_wall_time, cur_idle_time;
-		unsigned int idle_time, wall_time;
-
-		j_dbs_info = &per_cpu(cs_cpu_dbs_info, j);
-
-		cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
-
-		wall_time = (unsigned int)
-			(cur_wall_time - j_dbs_info->prev_cpu_wall);
-		j_dbs_info->prev_cpu_wall = cur_wall_time;
-
-		idle_time = (unsigned int)
-			(cur_idle_time - j_dbs_info->prev_cpu_idle);
-		j_dbs_info->prev_cpu_idle = cur_idle_time;
-
-		if (dbs_tuners_ins.ignore_nice) {
-			u64 cur_nice;
-			unsigned long cur_nice_jiffies;
-
-			cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] -
-					 j_dbs_info->prev_cpu_nice;
-			/*
-			 * Assumption: nice time between sampling periods will
-			 * be less than 2^32 jiffies for 32 bit sys
-			 */
-			cur_nice_jiffies = (unsigned long)
-					cputime64_to_jiffies64(cur_nice);
-
-			j_dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
-			idle_time += jiffies_to_usecs(cur_nice_jiffies);
-		}
+define_get_cpu_dbs_routines(cs_cpu_dbs_info);
 
-		if (unlikely(!wall_time || wall_time < idle_time))
-			continue;
-
-		load = 100 * (wall_time - idle_time) / wall_time;
-
-		if (load > max_load)
-			max_load = load;
-	}
-
-	/*
-	 * break out if we 'cannot' reduce the speed as the user might
-	 * want freq_step to be zero
-	 */
-	if (dbs_tuners_ins.freq_step == 0)
-		return;
-
-	/* Check for frequency increase */
-	if (max_load > dbs_tuners_ins.up_threshold) {
-		this_dbs_info->down_skip = 0;
-
-		/* if we are already at full speed then break out early */
-		if (this_dbs_info->requested_freq == policy->max)
-			return;
-
-		freq_target = (dbs_tuners_ins.freq_step * policy->max) / 100;
-
-		/* max freq cannot be less than 100. But who knows.... */
-		if (unlikely(freq_target == 0))
-			freq_target = 5;
-
-		this_dbs_info->requested_freq += freq_target;
-		if (this_dbs_info->requested_freq > policy->max)
-			this_dbs_info->requested_freq = policy->max;
-
-		__cpufreq_driver_target(policy, this_dbs_info->requested_freq,
-			CPUFREQ_RELATION_H);
-		return;
-	}
-
-	/*
-	 * The optimal frequency is the frequency that is the lowest that
-	 * can support the current CPU usage without triggering the up
-	 * policy. To be safe, we focus 10 points under the threshold.
-	 */
-	if (max_load < (dbs_tuners_ins.down_threshold - 10)) {
-		freq_target = (dbs_tuners_ins.freq_step * policy->max) / 100;
-
-		this_dbs_info->requested_freq -= freq_target;
-		if (this_dbs_info->requested_freq < policy->min)
-			this_dbs_info->requested_freq = policy->min;
-
-		/*
-		 * if we cannot reduce the frequency anymore, break out early
-		 */
-		if (policy->cur == policy->min)
-			return;
-
-		__cpufreq_driver_target(policy, this_dbs_info->requested_freq,
-				CPUFREQ_RELATION_H);
-		return;
-	}
-}
-
-static void do_dbs_timer(struct work_struct *work)
-{
-	struct cpu_dbs_info_s *dbs_info =
-		container_of(work, struct cpu_dbs_info_s, work.work);
-	unsigned int cpu = dbs_info->cpu;
-
-	/* We want all CPUs to do sampling nearly on same jiffy */
-	int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
-
-	delay -= jiffies % delay;
-
-	mutex_lock(&dbs_info->timer_mutex);
-
-	dbs_check_cpu(dbs_info);
-
-	schedule_delayed_work_on(cpu, &dbs_info->work, delay);
-	mutex_unlock(&dbs_info->timer_mutex);
-}
-
-static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
-{
-	/* We want all CPUs to do sampling nearly on same jiffy */
-	int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
-	delay -= jiffies % delay;
+static struct notifier_block cs_cpufreq_notifier_block = {
+	.notifier_call = dbs_cpufreq_notifier,
+};
 
-	dbs_info->enable = 1;
-	INIT_DEFERRABLE_WORK(&dbs_info->work, do_dbs_timer);
-	schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay);
-}
+static struct cs_ops cs_ops = {
+	.notifier_block = &cs_cpufreq_notifier_block,
+};
 
-static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
-{
-	dbs_info->enable = 0;
-	cancel_delayed_work_sync(&dbs_info->work);
-}
+static struct dbs_data cs_dbs_data = {
+	.governor = GOV_CONSERVATIVE,
+	.attr_group = &cs_attr_group,
+	.tuners = &cs_tuners,
+	.get_cpu_cdbs = get_cpu_cdbs,
+	.get_cpu_dbs_info_s = get_cpu_dbs_info_s,
+	.gov_dbs_timer = cs_dbs_timer,
+	.gov_check_cpu = cs_check_cpu,
+	.gov_ops = &cs_ops,
+};
 
-static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
+static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy,
 				   unsigned int event)
 {
-	unsigned int cpu = policy->cpu;
-	struct cpu_dbs_info_s *this_dbs_info;
-	unsigned int j;
-	int rc;
-
-	this_dbs_info = &per_cpu(cs_cpu_dbs_info, cpu);
-
-	switch (event) {
-	case CPUFREQ_GOV_START:
-		if ((!cpu_online(cpu)) || (!policy->cur))
-			return -EINVAL;
-
-		mutex_lock(&dbs_mutex);
-
-		for_each_cpu(j, policy->cpus) {
-			struct cpu_dbs_info_s *j_dbs_info;
-			j_dbs_info = &per_cpu(cs_cpu_dbs_info, j);
-			j_dbs_info->cur_policy = policy;
-
-			j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
-						&j_dbs_info->prev_cpu_wall);
-			if (dbs_tuners_ins.ignore_nice)
-				j_dbs_info->prev_cpu_nice =
-						kcpustat_cpu(j).cpustat[CPUTIME_NICE];
-		}
-		this_dbs_info->cpu = cpu;
-		this_dbs_info->down_skip = 0;
-		this_dbs_info->requested_freq = policy->cur;
-
-		mutex_init(&this_dbs_info->timer_mutex);
-		dbs_enable++;
-		/*
-		 * Start the timerschedule work, when this governor
-		 * is used for first time
-		 */
-		if (dbs_enable == 1) {
-			unsigned int latency;
-			/* policy latency is in nS. Convert it to uS first */
-			latency = policy->cpuinfo.transition_latency / 1000;
-			if (latency == 0)
-				latency = 1;
-
-			rc = sysfs_create_group(cpufreq_global_kobject,
-						&dbs_attr_group);
-			if (rc) {
-				mutex_unlock(&dbs_mutex);
-				return rc;
-			}
-
-			/*
-			 * conservative does not implement micro like ondemand
-			 * governor, thus we are bound to jiffes/HZ
-			 */
-			min_sampling_rate =
-				MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10);
-			/* Bring kernel and HW constraints together */
-			min_sampling_rate = max(min_sampling_rate,
-					MIN_LATENCY_MULTIPLIER * latency);
-			dbs_tuners_ins.sampling_rate =
-				max(min_sampling_rate,
-				    latency * LATENCY_MULTIPLIER);
-
-			cpufreq_register_notifier(
-					&dbs_cpufreq_notifier_block,
-					CPUFREQ_TRANSITION_NOTIFIER);
-		}
-		mutex_unlock(&dbs_mutex);
-
-		dbs_timer_init(this_dbs_info);
-
-		break;
-
-	case CPUFREQ_GOV_STOP:
-		dbs_timer_exit(this_dbs_info);
-
-		mutex_lock(&dbs_mutex);
-		dbs_enable--;
-		mutex_destroy(&this_dbs_info->timer_mutex);
-
-		/*
-		 * Stop the timerschedule work, when this governor
-		 * is used for first time
-		 */
-		if (dbs_enable == 0)
-			cpufreq_unregister_notifier(
-					&dbs_cpufreq_notifier_block,
-					CPUFREQ_TRANSITION_NOTIFIER);
-
-		mutex_unlock(&dbs_mutex);
-		if (!dbs_enable)
-			sysfs_remove_group(cpufreq_global_kobject,
-					   &dbs_attr_group);
-
-		break;
-
-	case CPUFREQ_GOV_LIMITS:
-		mutex_lock(&this_dbs_info->timer_mutex);
-		if (policy->max < this_dbs_info->cur_policy->cur)
-			__cpufreq_driver_target(
-					this_dbs_info->cur_policy,
-					policy->max, CPUFREQ_RELATION_H);
-		else if (policy->min > this_dbs_info->cur_policy->cur)
-			__cpufreq_driver_target(
-					this_dbs_info->cur_policy,
-					policy->min, CPUFREQ_RELATION_L);
-		dbs_check_cpu(this_dbs_info);
-		mutex_unlock(&this_dbs_info->timer_mutex);
-
-		break;
-	}
-	return 0;
+	return cpufreq_governor_dbs(&cs_dbs_data, policy, event);
 }
 
 #ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
@@ -597,13 +333,14 @@ static
 #endif
 struct cpufreq_governor cpufreq_gov_conservative = {
 	.name			= "conservative",
-	.governor		= cpufreq_governor_dbs,
+	.governor		= cs_cpufreq_governor_dbs,
 	.max_transition_latency	= TRANSITION_LATENCY_LIMIT,
 	.owner			= THIS_MODULE,
 };
 
 static int __init cpufreq_gov_dbs_init(void)
 {
+	mutex_init(&cs_dbs_data.mutex);
 	return cpufreq_register_governor(&cpufreq_gov_conservative);
 }
 
@@ -612,7 +349,6 @@ static void __exit cpufreq_gov_dbs_exit(void)
 	cpufreq_unregister_governor(&cpufreq_gov_conservative);
 }
 
-
 MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>");
 MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for "
 		"Low Latency Frequency Transition capable processors "
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
new file mode 100644
index 0000000..6c5f1d3
--- /dev/null
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -0,0 +1,318 @@
+/*
+ * drivers/cpufreq/cpufreq_governor.c
+ *
+ * CPUFREQ governors common code
+ *
+ * Copyright	(C) 2001 Russell King
+ *		(C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
+ *		(C) 2003 Jun Nakajima <jun.nakajima@intel.com>
+ *		(C) 2009 Alexander Clouter <alex@digriz.org.uk>
+ *		(c) 2012 Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <asm/cputime.h>
+#include <linux/cpufreq.h>
+#include <linux/cpumask.h>
+#include <linux/export.h>
+#include <linux/kernel_stat.h>
+#include <linux/mutex.h>
+#include <linux/tick.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#include "cpufreq_governor.h"
+
+static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
+{
+	u64 idle_time;
+	u64 cur_wall_time;
+	u64 busy_time;
+
+	cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
+
+	busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER];
+	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM];
+	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ];
+	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ];
+	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL];
+	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE];
+
+	idle_time = cur_wall_time - busy_time;
+	if (wall)
+		*wall = cputime_to_usecs(cur_wall_time);
+
+	return cputime_to_usecs(idle_time);
+}
+
+u64 get_cpu_idle_time(unsigned int cpu, u64 *wall)
+{
+	u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
+
+	if (idle_time == -1ULL)
+		return get_cpu_idle_time_jiffy(cpu, wall);
+	else
+		idle_time += get_cpu_iowait_time_us(cpu, wall);
+
+	return idle_time;
+}
+EXPORT_SYMBOL_GPL(get_cpu_idle_time);
+
+void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
+{
+	struct cpu_dbs_common_info *cdbs = dbs_data->get_cpu_cdbs(cpu);
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
+	struct cpufreq_policy *policy;
+	unsigned int max_load = 0;
+	unsigned int ignore_nice;
+	unsigned int j;
+
+	if (dbs_data->governor == GOV_ONDEMAND)
+		ignore_nice = od_tuners->ignore_nice;
+	else
+		ignore_nice = cs_tuners->ignore_nice;
+
+	policy = cdbs->cur_policy;
+
+	/* Get Absolute Load (in terms of freq for ondemand gov) */
+	for_each_cpu(j, policy->cpus) {
+		struct cpu_dbs_common_info *j_cdbs;
+		u64 cur_wall_time, cur_idle_time, cur_iowait_time;
+		unsigned int idle_time, wall_time, iowait_time;
+		unsigned int load;
+
+		j_cdbs = dbs_data->get_cpu_cdbs(j);
+
+		cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
+
+		wall_time = (unsigned int)
+			(cur_wall_time - j_cdbs->prev_cpu_wall);
+		j_cdbs->prev_cpu_wall = cur_wall_time;
+
+		idle_time = (unsigned int)
+			(cur_idle_time - j_cdbs->prev_cpu_idle);
+		j_cdbs->prev_cpu_idle = cur_idle_time;
+
+		if (ignore_nice) {
+			u64 cur_nice;
+			unsigned long cur_nice_jiffies;
+
+			cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] -
+					 cdbs->prev_cpu_nice;
+			/*
+			 * Assumption: nice time between sampling periods will
+			 * be less than 2^32 jiffies for 32 bit sys
+			 */
+			cur_nice_jiffies = (unsigned long)
+					cputime64_to_jiffies64(cur_nice);
+
+			cdbs->prev_cpu_nice =
+				kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+			idle_time += jiffies_to_usecs(cur_nice_jiffies);
+		}
+
+		if (dbs_data->governor == GOV_ONDEMAND) {
+			struct od_cpu_dbs_info_s *od_j_dbs_info =
+				dbs_data->get_cpu_dbs_info_s(cpu);
+
+			cur_iowait_time = get_cpu_iowait_time_us(j,
+					&cur_wall_time);
+			if (cur_iowait_time == -1ULL)
+				cur_iowait_time = 0;
+
+			iowait_time = (unsigned int) (cur_iowait_time -
+					od_j_dbs_info->prev_cpu_iowait);
+			od_j_dbs_info->prev_cpu_iowait = cur_iowait_time;
+
+			/*
+			 * For the purpose of ondemand, waiting for disk IO is
+			 * an indication that you're performance critical, and
+			 * not that the system is actually idle. So subtract the
+			 * iowait time from the cpu idle time.
+			 */
+			if (od_tuners->io_is_busy && idle_time >= iowait_time)
+				idle_time -= iowait_time;
+		}
+
+		if (unlikely(!wall_time || wall_time < idle_time))
+			continue;
+
+		load = 100 * (wall_time - idle_time) / wall_time;
+
+		if (dbs_data->governor == GOV_ONDEMAND) {
+			int freq_avg = __cpufreq_driver_getavg(policy, j);
+			if (freq_avg <= 0)
+				freq_avg = policy->cur;
+
+			load *= freq_avg;
+		}
+
+		if (load > max_load)
+			max_load = load;
+	}
+
+	dbs_data->gov_check_cpu(cpu, max_load);
+}
+EXPORT_SYMBOL_GPL(dbs_check_cpu);
+
+static inline void dbs_timer_init(struct dbs_data *dbs_data,
+		struct cpu_dbs_common_info *cdbs, unsigned int sampling_rate)
+{
+	int delay = delay_for_sampling_rate(sampling_rate);
+
+	INIT_DEFERRABLE_WORK(&cdbs->work, dbs_data->gov_dbs_timer);
+	schedule_delayed_work_on(cdbs->cpu, &cdbs->work, delay);
+}
+
+static inline void dbs_timer_exit(struct cpu_dbs_common_info *cdbs)
+{
+	cancel_delayed_work_sync(&cdbs->work);
+}
+
+int cpufreq_governor_dbs(struct dbs_data *dbs_data,
+		struct cpufreq_policy *policy, unsigned int event)
+{
+	struct od_cpu_dbs_info_s *od_dbs_info = NULL;
+	struct cs_cpu_dbs_info_s *cs_dbs_info = NULL;
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
+	struct cpu_dbs_common_info *cpu_cdbs;
+	unsigned int *sampling_rate, latency, ignore_nice, j, cpu = policy->cpu;
+	int rc;
+
+	cpu_cdbs = dbs_data->get_cpu_cdbs(cpu);
+
+	if (dbs_data->governor == GOV_CONSERVATIVE) {
+		cs_dbs_info = dbs_data->get_cpu_dbs_info_s(cpu);
+		sampling_rate = &cs_tuners->sampling_rate;
+		ignore_nice = cs_tuners->ignore_nice;
+	} else {
+		od_dbs_info = dbs_data->get_cpu_dbs_info_s(cpu);
+		sampling_rate = &od_tuners->sampling_rate;
+		ignore_nice = od_tuners->ignore_nice;
+	}
+
+	switch (event) {
+	case CPUFREQ_GOV_START:
+		if ((!cpu_online(cpu)) || (!policy->cur))
+			return -EINVAL;
+
+		mutex_lock(&dbs_data->mutex);
+
+		dbs_data->enable++;
+		cpu_cdbs->cpu = cpu;
+		for_each_cpu(j, policy->cpus) {
+			struct cpu_dbs_common_info *j_cdbs;
+			j_cdbs = dbs_data->get_cpu_cdbs(j);
+
+			j_cdbs->cur_policy = policy;
+			j_cdbs->prev_cpu_idle = get_cpu_idle_time(j,
+					&j_cdbs->prev_cpu_wall);
+			if (ignore_nice)
+				j_cdbs->prev_cpu_nice =
+					kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+		}
+
+		/*
+		 * Start the timerschedule work, when this governor is used for
+		 * first time
+		 */
+		if (dbs_data->enable != 1)
+			goto second_time;
+
+		rc = sysfs_create_group(cpufreq_global_kobject,
+				dbs_data->attr_group);
+		if (rc) {
+			mutex_unlock(&dbs_data->mutex);
+			return rc;
+		}
+
+		/* policy latency is in nS. Convert it to uS first */
+		latency = policy->cpuinfo.transition_latency / 1000;
+		if (latency == 0)
+			latency = 1;
+
+		/*
+		 * conservative does not implement micro like ondemand
+		 * governor, thus we are bound to jiffes/HZ
+		 */
+		if (dbs_data->governor == GOV_CONSERVATIVE) {
+			struct cs_ops *ops = dbs_data->gov_ops;
+
+			cpufreq_register_notifier(ops->notifier_block,
+					CPUFREQ_TRANSITION_NOTIFIER);
+
+			dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
+				jiffies_to_usecs(10);
+		} else {
+			struct od_ops *ops = dbs_data->gov_ops;
+
+			od_tuners->io_is_busy = ops->io_busy();
+		}
+
+		/* Bring kernel and HW constraints together */
+		dbs_data->min_sampling_rate = max(dbs_data->min_sampling_rate,
+				MIN_LATENCY_MULTIPLIER * latency);
+		*sampling_rate = max(dbs_data->min_sampling_rate, latency *
+				LATENCY_MULTIPLIER);
+
+second_time:
+		if (dbs_data->governor == GOV_CONSERVATIVE) {
+			cs_dbs_info->down_skip = 0;
+			cs_dbs_info->enable = 1;
+			cs_dbs_info->requested_freq = policy->cur;
+		} else {
+			struct od_ops *ops = dbs_data->gov_ops;
+			od_dbs_info->rate_mult = 1;
+			od_dbs_info->sample_type = OD_NORMAL_SAMPLE;
+			ops->powersave_bias_init_cpu(cpu);
+		}
+		mutex_unlock(&dbs_data->mutex);
+
+		mutex_init(&cpu_cdbs->timer_mutex);
+		dbs_timer_init(dbs_data, cpu_cdbs, *sampling_rate);
+		break;
+
+	case CPUFREQ_GOV_STOP:
+		if (dbs_data->governor == GOV_CONSERVATIVE)
+			cs_dbs_info->enable = 0;
+
+		dbs_timer_exit(cpu_cdbs);
+
+		mutex_lock(&dbs_data->mutex);
+		mutex_destroy(&cpu_cdbs->timer_mutex);
+		dbs_data->enable--;
+		if (!dbs_data->enable) {
+			struct cs_ops *ops = dbs_data->gov_ops;
+
+			sysfs_remove_group(cpufreq_global_kobject,
+					dbs_data->attr_group);
+			if (dbs_data->governor == GOV_CONSERVATIVE)
+				cpufreq_unregister_notifier(ops->notifier_block,
+						CPUFREQ_TRANSITION_NOTIFIER);
+		}
+		mutex_unlock(&dbs_data->mutex);
+
+		break;
+
+	case CPUFREQ_GOV_LIMITS:
+		mutex_lock(&cpu_cdbs->timer_mutex);
+		if (policy->max < cpu_cdbs->cur_policy->cur)
+			__cpufreq_driver_target(cpu_cdbs->cur_policy,
+					policy->max, CPUFREQ_RELATION_H);
+		else if (policy->min > cpu_cdbs->cur_policy->cur)
+			__cpufreq_driver_target(cpu_cdbs->cur_policy,
+					policy->min, CPUFREQ_RELATION_L);
+		dbs_check_cpu(dbs_data, cpu);
+		mutex_unlock(&cpu_cdbs->timer_mutex);
+		break;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_governor_dbs);
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
new file mode 100644
index 0000000..f661654
--- /dev/null
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -0,0 +1,176 @@
+/*
+ * drivers/cpufreq/cpufreq_governor.h
+ *
+ * Header file for CPUFreq governors common code
+ *
+ * Copyright	(C) 2001 Russell King
+ *		(C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
+ *		(C) 2003 Jun Nakajima <jun.nakajima@intel.com>
+ *		(C) 2009 Alexander Clouter <alex@digriz.org.uk>
+ *		(c) 2012 Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _CPUFREQ_GOVERNER_H
+#define _CPUFREQ_GOVERNER_H
+
+#include <linux/cpufreq.h>
+#include <linux/kobject.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/sysfs.h>
+
+/*
+ * The polling frequency depends on the capability of the processor. Default
+ * polling frequency is 1000 times the transition latency of the processor. The
+ * governor will work on any processor with transition latency <= 10mS, using
+ * appropriate sampling rate.
+ *
+ * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
+ * this governor will not work. All times here are in uS.
+ */
+#define MIN_SAMPLING_RATE_RATIO			(2)
+#define LATENCY_MULTIPLIER			(1000)
+#define MIN_LATENCY_MULTIPLIER			(100)
+#define TRANSITION_LATENCY_LIMIT		(10 * 1000 * 1000)
+
+/* Ondemand Sampling types */
+enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE};
+
+/* Macro creating sysfs show routines */
+#define show_one(_gov, file_name, object)				\
+static ssize_t show_##file_name						\
+(struct kobject *kobj, struct attribute *attr, char *buf)		\
+{									\
+	return sprintf(buf, "%u\n", _gov##_tuners.object);		\
+}
+
+#define define_get_cpu_dbs_routines(_dbs_info)				\
+static struct cpu_dbs_common_info *get_cpu_cdbs(int cpu)		\
+{									\
+	return &per_cpu(_dbs_info, cpu).cdbs;				\
+}									\
+									\
+static void *get_cpu_dbs_info_s(int cpu)				\
+{									\
+	return &per_cpu(_dbs_info, cpu);				\
+}
+
+/*
+ * Abbreviations:
+ * dbs: used as a shortform for demand based switching It helps to keep variable
+ *	names smaller, simpler
+ * cdbs: common dbs
+ * on_*: On-demand governor
+ * cs_*: Conservative governor
+ */
+
+/* Per cpu structures */
+struct cpu_dbs_common_info {
+	int cpu;
+	u64 prev_cpu_idle;
+	u64 prev_cpu_wall;
+	u64 prev_cpu_nice;
+	struct cpufreq_policy *cur_policy;
+	struct delayed_work work;
+	/*
+	 * percpu mutex that serializes governor limit change with gov_dbs_timer
+	 * invocation. We do not want gov_dbs_timer to run when user is changing
+	 * the governor or limits.
+	 */
+	struct mutex timer_mutex;
+};
+
+struct od_cpu_dbs_info_s {
+	struct cpu_dbs_common_info cdbs;
+	u64 prev_cpu_iowait;
+	struct cpufreq_frequency_table *freq_table;
+	unsigned int freq_lo;
+	unsigned int freq_lo_jiffies;
+	unsigned int freq_hi_jiffies;
+	unsigned int rate_mult;
+	unsigned int sample_type:1;
+};
+
+struct cs_cpu_dbs_info_s {
+	struct cpu_dbs_common_info cdbs;
+	unsigned int down_skip;
+	unsigned int requested_freq;
+	unsigned int enable:1;
+};
+
+/* Governers sysfs tunables */
+struct od_dbs_tuners {
+	unsigned int ignore_nice;
+	unsigned int sampling_rate;
+	unsigned int sampling_down_factor;
+	unsigned int up_threshold;
+	unsigned int down_differential;
+	unsigned int powersave_bias;
+	unsigned int io_is_busy;
+};
+
+struct cs_dbs_tuners {
+	unsigned int ignore_nice;
+	unsigned int sampling_rate;
+	unsigned int sampling_down_factor;
+	unsigned int up_threshold;
+	unsigned int down_threshold;
+	unsigned int freq_step;
+};
+
+/* Per Governer data */
+struct dbs_data {
+	/* Common across governors */
+	#define GOV_ONDEMAND		0
+	#define GOV_CONSERVATIVE	1
+	int governor;
+	unsigned int min_sampling_rate;
+	unsigned int enable; /* number of CPUs using this policy */
+	struct attribute_group *attr_group;
+	void *tuners;
+
+	/* dbs_mutex protects dbs_enable in governor start/stop */
+	struct mutex mutex;
+
+	struct cpu_dbs_common_info *(*get_cpu_cdbs)(int cpu);
+	void *(*get_cpu_dbs_info_s)(int cpu);
+	void (*gov_dbs_timer)(struct work_struct *work);
+	void (*gov_check_cpu)(int cpu, unsigned int load);
+
+	/* Governor specific ops, see below */
+	void *gov_ops;
+};
+
+/* Governor specific ops, will be passed to dbs_data->gov_ops */
+struct od_ops {
+	int (*io_busy)(void);
+	void (*powersave_bias_init_cpu)(int cpu);
+	unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy,
+			unsigned int freq_next, unsigned int relation);
+	void (*freq_increase)(struct cpufreq_policy *p, unsigned int freq);
+};
+
+struct cs_ops {
+	struct notifier_block *notifier_block;
+};
+
+static inline int delay_for_sampling_rate(unsigned int sampling_rate)
+{
+	int delay = usecs_to_jiffies(sampling_rate);
+
+	/* We want all CPUs to do sampling nearly on same jiffy */
+	if (num_online_cpus() > 1)
+		delay -= jiffies % delay;
+
+	return delay;
+}
+
+u64 get_cpu_idle_time(unsigned int cpu, u64 *wall);
+void dbs_check_cpu(struct dbs_data *dbs_data, int cpu);
+int cpufreq_governor_dbs(struct dbs_data *dbs_data,
+		struct cpufreq_policy *policy, unsigned int event);
+#endif /* _CPUFREQ_GOVERNER_H */
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 396322f..7731f7c 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -10,24 +10,23 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/cpufreq.h>
-#include <linux/cpu.h>
-#include <linux/jiffies.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/kernel_stat.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
-#include <linux/hrtimer.h>
+#include <linux/percpu-defs.h>
+#include <linux/sysfs.h>
 #include <linux/tick.h>
-#include <linux/ktime.h>
-#include <linux/sched.h>
+#include <linux/types.h>
 
-/*
- * dbs is used in this file as a shortform for demandbased switching
- * It helps to keep variable names smaller, simpler
- */
+#include "cpufreq_governor.h"
 
+/* On-demand governor macors */
 #define DEF_FREQUENCY_DOWN_DIFFERENTIAL		(10)
 #define DEF_FREQUENCY_UP_THRESHOLD		(80)
 #define DEF_SAMPLING_DOWN_FACTOR		(1)
@@ -38,80 +37,14 @@
 #define MIN_FREQUENCY_UP_THRESHOLD		(11)
 #define MAX_FREQUENCY_UP_THRESHOLD		(100)
 
-/*
- * The polling frequency of this governor depends on the capability of
- * the processor. Default polling frequency is 1000 times the transition
- * latency of the processor. The governor will work on any processor with
- * transition latency <= 10mS, using appropriate sampling
- * rate.
- * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
- * this governor will not work.
- * All times here are in uS.
- */
-#define MIN_SAMPLING_RATE_RATIO			(2)
-
-static unsigned int min_sampling_rate;
-
-#define LATENCY_MULTIPLIER			(1000)
-#define MIN_LATENCY_MULTIPLIER			(100)
-#define TRANSITION_LATENCY_LIMIT		(10 * 1000 * 1000)
-
-static void do_dbs_timer(struct work_struct *work);
-static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
-				unsigned int event);
+static struct dbs_data od_dbs_data;
+static DEFINE_PER_CPU(struct od_cpu_dbs_info_s, od_cpu_dbs_info);
 
 #ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
-static
+static struct cpufreq_governor cpufreq_gov_ondemand;
 #endif
-struct cpufreq_governor cpufreq_gov_ondemand = {
-       .name                   = "ondemand",
-       .governor               = cpufreq_governor_dbs,
-       .max_transition_latency = TRANSITION_LATENCY_LIMIT,
-       .owner                  = THIS_MODULE,
-};
 
-/* Sampling types */
-enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
-
-struct cpu_dbs_info_s {
-	cputime64_t prev_cpu_idle;
-	cputime64_t prev_cpu_iowait;
-	cputime64_t prev_cpu_wall;
-	cputime64_t prev_cpu_nice;
-	struct cpufreq_policy *cur_policy;
-	struct delayed_work work;
-	struct cpufreq_frequency_table *freq_table;
-	unsigned int freq_lo;
-	unsigned int freq_lo_jiffies;
-	unsigned int freq_hi_jiffies;
-	unsigned int rate_mult;
-	int cpu;
-	unsigned int sample_type:1;
-	/*
-	 * percpu mutex that serializes governor limit change with
-	 * do_dbs_timer invocation. We do not want do_dbs_timer to run
-	 * when user is changing the governor or limits.
-	 */
-	struct mutex timer_mutex;
-};
-static DEFINE_PER_CPU(struct cpu_dbs_info_s, od_cpu_dbs_info);
-
-static unsigned int dbs_enable;	/* number of CPUs using this policy */
-
-/*
- * dbs_mutex protects dbs_enable in governor start/stop.
- */
-static DEFINE_MUTEX(dbs_mutex);
-
-static struct dbs_tuners {
-	unsigned int sampling_rate;
-	unsigned int up_threshold;
-	unsigned int down_differential;
-	unsigned int ignore_nice;
-	unsigned int sampling_down_factor;
-	unsigned int powersave_bias;
-	unsigned int io_is_busy;
-} dbs_tuners_ins = {
+static struct od_dbs_tuners od_tuners = {
 	.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
 	.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
 	.down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL,
@@ -119,48 +52,35 @@ static struct dbs_tuners {
 	.powersave_bias = 0,
 };
 
-static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
-{
-	u64 idle_time;
-	u64 cur_wall_time;
-	u64 busy_time;
-
-	cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
-
-	busy_time  = kcpustat_cpu(cpu).cpustat[CPUTIME_USER];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE];
-
-	idle_time = cur_wall_time - busy_time;
-	if (wall)
-		*wall = jiffies_to_usecs(cur_wall_time);
-
-	return jiffies_to_usecs(idle_time);
-}
-
-static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
+static void ondemand_powersave_bias_init_cpu(int cpu)
 {
-	u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
-
-	if (idle_time == -1ULL)
-		return get_cpu_idle_time_jiffy(cpu, wall);
-	else
-		idle_time += get_cpu_iowait_time_us(cpu, wall);
+	struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
 
-	return idle_time;
+	dbs_info->freq_table = cpufreq_frequency_get_table(cpu);
+	dbs_info->freq_lo = 0;
 }
 
-static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wall)
+/*
+ * Not all CPUs want IO time to be accounted as busy; this depends on how
+ * efficient idling at a higher frequency/voltage is.
+ * Pavel Machek says this is not so for various generations of AMD and old
+ * Intel systems.
+ * Mike Chan (androidlcom) calis this is also not true for ARM.
+ * Because of this, whitelist specific known (series) of CPUs by default, and
+ * leave all others up to the user.
+ */
+static int should_io_be_busy(void)
 {
-	u64 iowait_time = get_cpu_iowait_time_us(cpu, wall);
-
-	if (iowait_time == -1ULL)
-		return 0;
-
-	return iowait_time;
+#if defined(CONFIG_X86)
+	/*
+	 * For Intel, Core 2 (model 15) andl later have an efficient idle.
+	 */
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+			boot_cpu_data.x86 == 6 &&
+			boot_cpu_data.x86_model >= 15)
+		return 1;
+#endif
+	return 0;
 }
 
 /*
@@ -169,14 +89,13 @@ static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wal
  * freq_lo, and freq_lo_jiffies in percpu area for averaging freqs.
  */
 static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
-					  unsigned int freq_next,
-					  unsigned int relation)
+		unsigned int freq_next, unsigned int relation)
 {
 	unsigned int freq_req, freq_reduc, freq_avg;
 	unsigned int freq_hi, freq_lo;
 	unsigned int index = 0;
 	unsigned int jiffies_total, jiffies_hi, jiffies_lo;
-	struct cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
+	struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
 						   policy->cpu);
 
 	if (!dbs_info->freq_table) {
@@ -188,7 +107,7 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
 	cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next,
 			relation, &index);
 	freq_req = dbs_info->freq_table[index].frequency;
-	freq_reduc = freq_req * dbs_tuners_ins.powersave_bias / 1000;
+	freq_reduc = freq_req * od_tuners.powersave_bias / 1000;
 	freq_avg = freq_req - freq_reduc;
 
 	/* Find freq bounds for freq_avg in freq_table */
@@ -207,7 +126,7 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
 		dbs_info->freq_lo_jiffies = 0;
 		return freq_lo;
 	}
-	jiffies_total = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
+	jiffies_total = usecs_to_jiffies(od_tuners.sampling_rate);
 	jiffies_hi = (freq_avg - freq_lo) * jiffies_total;
 	jiffies_hi += ((freq_hi - freq_lo) / 2);
 	jiffies_hi /= (freq_hi - freq_lo);
@@ -218,13 +137,6 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
 	return freq_hi;
 }
 
-static void ondemand_powersave_bias_init_cpu(int cpu)
-{
-	struct cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
-	dbs_info->freq_table = cpufreq_frequency_get_table(cpu);
-	dbs_info->freq_lo = 0;
-}
-
 static void ondemand_powersave_bias_init(void)
 {
 	int i;
@@ -233,83 +145,173 @@ static void ondemand_powersave_bias_init(void)
 	}
 }
 
-/************************** sysfs interface ************************/
+static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq)
+{
+	if (od_tuners.powersave_bias)
+		freq = powersave_bias_target(p, freq, CPUFREQ_RELATION_H);
+	else if (p->cur == p->max)
+		return;
 
-static ssize_t show_sampling_rate_min(struct kobject *kobj,
-				      struct attribute *attr, char *buf)
+	__cpufreq_driver_target(p, freq, od_tuners.powersave_bias ?
+			CPUFREQ_RELATION_L : CPUFREQ_RELATION_H);
+}
+
+/*
+ * Every sampling_rate, we check, if current idle time is less than 20%
+ * (default), then we try to increase frequency Every sampling_rate, we look for
+ * a the lowest frequency which can sustain the load while keeping idle time
+ * over 30%. If such a frequency exist, we try to decrease to this frequency.
+ *
+ * Any frequency increase takes it to the maximum frequency. Frequency reduction
+ * happens at minimum steps of 5% (default) of current frequency
+ */
+static void od_check_cpu(int cpu, unsigned int load_freq)
 {
-	return sprintf(buf, "%u\n", min_sampling_rate);
+	struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
+	struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
+
+	dbs_info->freq_lo = 0;
+
+	/* Check for frequency increase */
+	if (load_freq > od_tuners.up_threshold * policy->cur) {
+		/* If switching to max speed, apply sampling_down_factor */
+		if (policy->cur < policy->max)
+			dbs_info->rate_mult =
+				od_tuners.sampling_down_factor;
+		dbs_freq_increase(policy, policy->max);
+		return;
+	}
+
+	/* Check for frequency decrease */
+	/* if we cannot reduce the frequency anymore, break out early */
+	if (policy->cur == policy->min)
+		return;
+
+	/*
+	 * The optimal frequency is the frequency that is the lowest that can
+	 * support the current CPU usage without triggering the up policy. To be
+	 * safe, we focus 10 points under the threshold.
+	 */
+	if (load_freq < (od_tuners.up_threshold - od_tuners.down_differential) *
+			policy->cur) {
+		unsigned int freq_next;
+		freq_next = load_freq / (od_tuners.up_threshold -
+				od_tuners.down_differential);
+
+		/* No longer fully busy, reset rate_mult */
+		dbs_info->rate_mult = 1;
+
+		if (freq_next < policy->min)
+			freq_next = policy->min;
+
+		if (!od_tuners.powersave_bias) {
+			__cpufreq_driver_target(policy, freq_next,
+					CPUFREQ_RELATION_L);
+		} else {
+			int freq = powersave_bias_target(policy, freq_next,
+					CPUFREQ_RELATION_L);
+			__cpufreq_driver_target(policy, freq,
+					CPUFREQ_RELATION_L);
+		}
+	}
 }
 
-define_one_global_ro(sampling_rate_min);
+static void od_dbs_timer(struct work_struct *work)
+{
+	struct od_cpu_dbs_info_s *dbs_info =
+		container_of(work, struct od_cpu_dbs_info_s, cdbs.work.work);
+	unsigned int cpu = dbs_info->cdbs.cpu;
+	int delay, sample_type = dbs_info->sample_type;
+
+	mutex_lock(&dbs_info->cdbs.timer_mutex);
+
+	/* Common NORMAL_SAMPLE setup */
+	dbs_info->sample_type = OD_NORMAL_SAMPLE;
+	if (sample_type == OD_SUB_SAMPLE) {
+		delay = dbs_info->freq_lo_jiffies;
+		__cpufreq_driver_target(dbs_info->cdbs.cur_policy,
+			dbs_info->freq_lo, CPUFREQ_RELATION_H);
+	} else {
+		dbs_check_cpu(&od_dbs_data, cpu);
+		if (dbs_info->freq_lo) {
+			/* Setup timer for SUB_SAMPLE */
+			dbs_info->sample_type = OD_SUB_SAMPLE;
+			delay = dbs_info->freq_hi_jiffies;
+		} else {
+			delay = delay_for_sampling_rate(od_tuners.sampling_rate
+						* dbs_info->rate_mult);
+		}
+	}
+
+	schedule_delayed_work_on(cpu, &dbs_info->cdbs.work, delay);
+	mutex_unlock(&dbs_info->cdbs.timer_mutex);
+}
+
+/************************** sysfs interface ************************/
 
-/* cpufreq_ondemand Governor Tunables */
-#define show_one(file_name, object)					\
-static ssize_t show_##file_name						\
-(struct kobject *kobj, struct attribute *attr, char *buf)              \
-{									\
-	return sprintf(buf, "%u\n", dbs_tuners_ins.object);		\
+static ssize_t show_sampling_rate_min(struct kobject *kobj,
+				      struct attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u\n", od_dbs_data.min_sampling_rate);
 }
-show_one(sampling_rate, sampling_rate);
-show_one(io_is_busy, io_is_busy);
-show_one(up_threshold, up_threshold);
-show_one(sampling_down_factor, sampling_down_factor);
-show_one(ignore_nice_load, ignore_nice);
-show_one(powersave_bias, powersave_bias);
 
 /**
  * update_sampling_rate - update sampling rate effective immediately if needed.
  * @new_rate: new sampling rate
  *
  * If new rate is smaller than the old, simply updaing
- * dbs_tuners_int.sampling_rate might not be appropriate. For example,
- * if the original sampling_rate was 1 second and the requested new sampling
- * rate is 10 ms because the user needs immediate reaction from ondemand
- * governor, but not sure if higher frequency will be required or not,
- * then, the governor may change the sampling rate too late; up to 1 second
- * later. Thus, if we are reducing the sampling rate, we need to make the
- * new value effective immediately.
+ * dbs_tuners_int.sampling_rate might not be appropriate. For example, if the
+ * original sampling_rate was 1 second and the requested new sampling rate is 10
+ * ms because the user needs immediate reaction from ondemand governor, but not
+ * sure if higher frequency will be required or not, then, the governor may
+ * change the sampling rate too late; up to 1 second later. Thus, if we are
+ * reducing the sampling rate, we need to make the new value effective
+ * immediately.
  */
 static void update_sampling_rate(unsigned int new_rate)
 {
 	int cpu;
 
-	dbs_tuners_ins.sampling_rate = new_rate
-				     = max(new_rate, min_sampling_rate);
+	od_tuners.sampling_rate = new_rate = max(new_rate,
+			od_dbs_data.min_sampling_rate);
 
 	for_each_online_cpu(cpu) {
 		struct cpufreq_policy *policy;
-		struct cpu_dbs_info_s *dbs_info;
+		struct od_cpu_dbs_info_s *dbs_info;
 		unsigned long next_sampling, appointed_at;
 
 		policy = cpufreq_cpu_get(cpu);
 		if (!policy)
 			continue;
+		if (policy->governor != &cpufreq_gov_ondemand) {
+			cpufreq_cpu_put(policy);
+			continue;
+		}
 		dbs_info = &per_cpu(od_cpu_dbs_info, policy->cpu);
 		cpufreq_cpu_put(policy);
 
-		mutex_lock(&dbs_info->timer_mutex);
+		mutex_lock(&dbs_info->cdbs.timer_mutex);
 
-		if (!delayed_work_pending(&dbs_info->work)) {
-			mutex_unlock(&dbs_info->timer_mutex);
+		if (!delayed_work_pending(&dbs_info->cdbs.work)) {
+			mutex_unlock(&dbs_info->cdbs.timer_mutex);
 			continue;
 		}
 
-		next_sampling  = jiffies + usecs_to_jiffies(new_rate);
-		appointed_at = dbs_info->work.timer.expires;
-
+		next_sampling = jiffies + usecs_to_jiffies(new_rate);
+		appointed_at = dbs_info->cdbs.work.timer.expires;
 
 		if (time_before(next_sampling, appointed_at)) {
 
-			mutex_unlock(&dbs_info->timer_mutex);
-			cancel_delayed_work_sync(&dbs_info->work);
-			mutex_lock(&dbs_info->timer_mutex);
+			mutex_unlock(&dbs_info->cdbs.timer_mutex);
+			cancel_delayed_work_sync(&dbs_info->cdbs.work);
+			mutex_lock(&dbs_info->cdbs.timer_mutex);
 
-			schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work,
-						 usecs_to_jiffies(new_rate));
+			schedule_delayed_work_on(dbs_info->cdbs.cpu,
+					&dbs_info->cdbs.work,
+					usecs_to_jiffies(new_rate));
 
 		}
-		mutex_unlock(&dbs_info->timer_mutex);
+		mutex_unlock(&dbs_info->cdbs.timer_mutex);
 	}
 }
 
@@ -334,7 +336,7 @@ static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b,
 	ret = sscanf(buf, "%u", &input);
 	if (ret != 1)
 		return -EINVAL;
-	dbs_tuners_ins.io_is_busy = !!input;
+	od_tuners.io_is_busy = !!input;
 	return count;
 }
 
@@ -349,7 +351,7 @@ static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
 			input < MIN_FREQUENCY_UP_THRESHOLD) {
 		return -EINVAL;
 	}
-	dbs_tuners_ins.up_threshold = input;
+	od_tuners.up_threshold = input;
 	return count;
 }
 
@@ -362,12 +364,12 @@ static ssize_t store_sampling_down_factor(struct kobject *a,
 
 	if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
 		return -EINVAL;
-	dbs_tuners_ins.sampling_down_factor = input;
+	od_tuners.sampling_down_factor = input;
 
 	/* Reset down sampling multiplier in case it was active */
 	for_each_online_cpu(j) {
-		struct cpu_dbs_info_s *dbs_info;
-		dbs_info = &per_cpu(od_cpu_dbs_info, j);
+		struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
+				j);
 		dbs_info->rate_mult = 1;
 	}
 	return count;
@@ -388,19 +390,20 @@ static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
 	if (input > 1)
 		input = 1;
 
-	if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */
+	if (input == od_tuners.ignore_nice) { /* nothing to do */
 		return count;
 	}
-	dbs_tuners_ins.ignore_nice = input;
+	od_tuners.ignore_nice = input;
 
 	/* we need to re-evaluate prev_cpu_idle */
 	for_each_online_cpu(j) {
-		struct cpu_dbs_info_s *dbs_info;
+		struct od_cpu_dbs_info_s *dbs_info;
 		dbs_info = &per_cpu(od_cpu_dbs_info, j);
-		dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
-						&dbs_info->prev_cpu_wall);
-		if (dbs_tuners_ins.ignore_nice)
-			dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+		dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
+						&dbs_info->cdbs.prev_cpu_wall);
+		if (od_tuners.ignore_nice)
+			dbs_info->cdbs.prev_cpu_nice =
+				kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 
 	}
 	return count;
@@ -419,17 +422,25 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b,
 	if (input > 1000)
 		input = 1000;
 
-	dbs_tuners_ins.powersave_bias = input;
+	od_tuners.powersave_bias = input;
 	ondemand_powersave_bias_init();
 	return count;
 }
 
+show_one(od, sampling_rate, sampling_rate);
+show_one(od, io_is_busy, io_is_busy);
+show_one(od, up_threshold, up_threshold);
+show_one(od, sampling_down_factor, sampling_down_factor);
+show_one(od, ignore_nice_load, ignore_nice);
+show_one(od, powersave_bias, powersave_bias);
+
 define_one_global_rw(sampling_rate);
 define_one_global_rw(io_is_busy);
 define_one_global_rw(up_threshold);
 define_one_global_rw(sampling_down_factor);
 define_one_global_rw(ignore_nice_load);
 define_one_global_rw(powersave_bias);
+define_one_global_ro(sampling_rate_min);
 
 static struct attribute *dbs_attributes[] = {
 	&sampling_rate_min.attr,
@@ -442,354 +453,71 @@ static struct attribute *dbs_attributes[] = {
 	NULL
 };
 
-static struct attribute_group dbs_attr_group = {
+static struct attribute_group od_attr_group = {
 	.attrs = dbs_attributes,
 	.name = "ondemand",
 };
 
 /************************** sysfs end ************************/
 
-static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq)
-{
-	if (dbs_tuners_ins.powersave_bias)
-		freq = powersave_bias_target(p, freq, CPUFREQ_RELATION_H);
-	else if (p->cur == p->max)
-		return;
-
-	__cpufreq_driver_target(p, freq, dbs_tuners_ins.powersave_bias ?
-			CPUFREQ_RELATION_L : CPUFREQ_RELATION_H);
-}
-
-static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
-{
-	unsigned int max_load_freq;
-
-	struct cpufreq_policy *policy;
-	unsigned int j;
-
-	this_dbs_info->freq_lo = 0;
-	policy = this_dbs_info->cur_policy;
-
-	/*
-	 * Every sampling_rate, we check, if current idle time is less
-	 * than 20% (default), then we try to increase frequency
-	 * Every sampling_rate, we look for a the lowest
-	 * frequency which can sustain the load while keeping idle time over
-	 * 30%. If such a frequency exist, we try to decrease to this frequency.
-	 *
-	 * Any frequency increase takes it to the maximum frequency.
-	 * Frequency reduction happens at minimum steps of
-	 * 5% (default) of current frequency
-	 */
-
-	/* Get Absolute Load - in terms of freq */
-	max_load_freq = 0;
-
-	for_each_cpu(j, policy->cpus) {
-		struct cpu_dbs_info_s *j_dbs_info;
-		cputime64_t cur_wall_time, cur_idle_time, cur_iowait_time;
-		unsigned int idle_time, wall_time, iowait_time;
-		unsigned int load, load_freq;
-		int freq_avg;
-
-		j_dbs_info = &per_cpu(od_cpu_dbs_info, j);
-
-		cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
-		cur_iowait_time = get_cpu_iowait_time(j, &cur_wall_time);
-
-		wall_time = (unsigned int)
-			(cur_wall_time - j_dbs_info->prev_cpu_wall);
-		j_dbs_info->prev_cpu_wall = cur_wall_time;
-
-		idle_time = (unsigned int)
-			(cur_idle_time - j_dbs_info->prev_cpu_idle);
-		j_dbs_info->prev_cpu_idle = cur_idle_time;
-
-		iowait_time = (unsigned int)
-			(cur_iowait_time - j_dbs_info->prev_cpu_iowait);
-		j_dbs_info->prev_cpu_iowait = cur_iowait_time;
-
-		if (dbs_tuners_ins.ignore_nice) {
-			u64 cur_nice;
-			unsigned long cur_nice_jiffies;
-
-			cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] -
-					 j_dbs_info->prev_cpu_nice;
-			/*
-			 * Assumption: nice time between sampling periods will
-			 * be less than 2^32 jiffies for 32 bit sys
-			 */
-			cur_nice_jiffies = (unsigned long)
-					cputime64_to_jiffies64(cur_nice);
-
-			j_dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
-			idle_time += jiffies_to_usecs(cur_nice_jiffies);
-		}
-
-		/*
-		 * For the purpose of ondemand, waiting for disk IO is an
-		 * indication that you're performance critical, and not that
-		 * the system is actually idle. So subtract the iowait time
-		 * from the cpu idle time.
-		 */
-
-		if (dbs_tuners_ins.io_is_busy && idle_time >= iowait_time)
-			idle_time -= iowait_time;
-
-		if (unlikely(!wall_time || wall_time < idle_time))
-			continue;
-
-		load = 100 * (wall_time - idle_time) / wall_time;
-
-		freq_avg = __cpufreq_driver_getavg(policy, j);
-		if (freq_avg <= 0)
-			freq_avg = policy->cur;
-
-		load_freq = load * freq_avg;
-		if (load_freq > max_load_freq)
-			max_load_freq = load_freq;
-	}
+define_get_cpu_dbs_routines(od_cpu_dbs_info);
 
-	/* Check for frequency increase */
-	if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) {
-		/* If switching to max speed, apply sampling_down_factor */
-		if (policy->cur < policy->max)
-			this_dbs_info->rate_mult =
-				dbs_tuners_ins.sampling_down_factor;
-		dbs_freq_increase(policy, policy->max);
-		return;
-	}
-
-	/* Check for frequency decrease */
-	/* if we cannot reduce the frequency anymore, break out early */
-	if (policy->cur == policy->min)
-		return;
-
-	/*
-	 * The optimal frequency is the frequency that is the lowest that
-	 * can support the current CPU usage without triggering the up
-	 * policy. To be safe, we focus 10 points under the threshold.
-	 */
-	if (max_load_freq <
-	    (dbs_tuners_ins.up_threshold - dbs_tuners_ins.down_differential) *
-	     policy->cur) {
-		unsigned int freq_next;
-		freq_next = max_load_freq /
-				(dbs_tuners_ins.up_threshold -
-				 dbs_tuners_ins.down_differential);
-
-		/* No longer fully busy, reset rate_mult */
-		this_dbs_info->rate_mult = 1;
-
-		if (freq_next < policy->min)
-			freq_next = policy->min;
-
-		if (!dbs_tuners_ins.powersave_bias) {
-			__cpufreq_driver_target(policy, freq_next,
-					CPUFREQ_RELATION_L);
-		} else {
-			int freq = powersave_bias_target(policy, freq_next,
-					CPUFREQ_RELATION_L);
-			__cpufreq_driver_target(policy, freq,
-				CPUFREQ_RELATION_L);
-		}
-	}
-}
-
-static void do_dbs_timer(struct work_struct *work)
-{
-	struct cpu_dbs_info_s *dbs_info =
-		container_of(work, struct cpu_dbs_info_s, work.work);
-	unsigned int cpu = dbs_info->cpu;
-	int sample_type = dbs_info->sample_type;
-
-	int delay;
-
-	mutex_lock(&dbs_info->timer_mutex);
-
-	/* Common NORMAL_SAMPLE setup */
-	dbs_info->sample_type = DBS_NORMAL_SAMPLE;
-	if (!dbs_tuners_ins.powersave_bias ||
-	    sample_type == DBS_NORMAL_SAMPLE) {
-		dbs_check_cpu(dbs_info);
-		if (dbs_info->freq_lo) {
-			/* Setup timer for SUB_SAMPLE */
-			dbs_info->sample_type = DBS_SUB_SAMPLE;
-			delay = dbs_info->freq_hi_jiffies;
-		} else {
-			/* We want all CPUs to do sampling nearly on
-			 * same jiffy
-			 */
-			delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate
-				* dbs_info->rate_mult);
-
-			if (num_online_cpus() > 1)
-				delay -= jiffies % delay;
-		}
-	} else {
-		__cpufreq_driver_target(dbs_info->cur_policy,
-			dbs_info->freq_lo, CPUFREQ_RELATION_H);
-		delay = dbs_info->freq_lo_jiffies;
-	}
-	schedule_delayed_work_on(cpu, &dbs_info->work, delay);
-	mutex_unlock(&dbs_info->timer_mutex);
-}
-
-static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
-{
-	/* We want all CPUs to do sampling nearly on same jiffy */
-	int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
-
-	if (num_online_cpus() > 1)
-		delay -= jiffies % delay;
+static struct od_ops od_ops = {
+	.io_busy = should_io_be_busy,
+	.powersave_bias_init_cpu = ondemand_powersave_bias_init_cpu,
+	.powersave_bias_target = powersave_bias_target,
+	.freq_increase = dbs_freq_increase,
+};
 
-	dbs_info->sample_type = DBS_NORMAL_SAMPLE;
-	INIT_DEFERRABLE_WORK(&dbs_info->work, do_dbs_timer);
-	schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay);
-}
+static struct dbs_data od_dbs_data = {
+	.governor = GOV_ONDEMAND,
+	.attr_group = &od_attr_group,
+	.tuners = &od_tuners,
+	.get_cpu_cdbs = get_cpu_cdbs,
+	.get_cpu_dbs_info_s = get_cpu_dbs_info_s,
+	.gov_dbs_timer = od_dbs_timer,
+	.gov_check_cpu = od_check_cpu,
+	.gov_ops = &od_ops,
+};
 
-static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
+static int od_cpufreq_governor_dbs(struct cpufreq_policy *policy,
+		unsigned int event)
 {
-	cancel_delayed_work_sync(&dbs_info->work);
+	return cpufreq_governor_dbs(&od_dbs_data, policy, event);
 }
 
-/*
- * Not all CPUs want IO time to be accounted as busy; this dependson how
- * efficient idling at a higher frequency/voltage is.
- * Pavel Machek says this is not so for various generations of AMD and old
- * Intel systems.
- * Mike Chan (androidlcom) calis this is also not true for ARM.
- * Because of this, whitelist specific known (series) of CPUs by default, and
- * leave all others up to the user.
- */
-static int should_io_be_busy(void)
-{
-#if defined(CONFIG_X86)
-	/*
-	 * For Intel, Core 2 (model 15) andl later have an efficient idle.
-	 */
-	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
-	    boot_cpu_data.x86 == 6 &&
-	    boot_cpu_data.x86_model >= 15)
-		return 1;
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
+static
 #endif
-	return 0;
-}
-
-static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
-				   unsigned int event)
-{
-	unsigned int cpu = policy->cpu;
-	struct cpu_dbs_info_s *this_dbs_info;
-	unsigned int j;
-	int rc;
-
-	this_dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
-
-	switch (event) {
-	case CPUFREQ_GOV_START:
-		if ((!cpu_online(cpu)) || (!policy->cur))
-			return -EINVAL;
-
-		mutex_lock(&dbs_mutex);
-
-		dbs_enable++;
-		for_each_cpu(j, policy->cpus) {
-			struct cpu_dbs_info_s *j_dbs_info;
-			j_dbs_info = &per_cpu(od_cpu_dbs_info, j);
-			j_dbs_info->cur_policy = policy;
-
-			j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
-						&j_dbs_info->prev_cpu_wall);
-			if (dbs_tuners_ins.ignore_nice)
-				j_dbs_info->prev_cpu_nice =
-						kcpustat_cpu(j).cpustat[CPUTIME_NICE];
-		}
-		this_dbs_info->cpu = cpu;
-		this_dbs_info->rate_mult = 1;
-		ondemand_powersave_bias_init_cpu(cpu);
-		/*
-		 * Start the timerschedule work, when this governor
-		 * is used for first time
-		 */
-		if (dbs_enable == 1) {
-			unsigned int latency;
-
-			rc = sysfs_create_group(cpufreq_global_kobject,
-						&dbs_attr_group);
-			if (rc) {
-				mutex_unlock(&dbs_mutex);
-				return rc;
-			}
-
-			/* policy latency is in nS. Convert it to uS first */
-			latency = policy->cpuinfo.transition_latency / 1000;
-			if (latency == 0)
-				latency = 1;
-			/* Bring kernel and HW constraints together */
-			min_sampling_rate = max(min_sampling_rate,
-					MIN_LATENCY_MULTIPLIER * latency);
-			dbs_tuners_ins.sampling_rate =
-				max(min_sampling_rate,
-				    latency * LATENCY_MULTIPLIER);
-			dbs_tuners_ins.io_is_busy = should_io_be_busy();
-		}
-		mutex_unlock(&dbs_mutex);
-
-		mutex_init(&this_dbs_info->timer_mutex);
-		dbs_timer_init(this_dbs_info);
-		break;
-
-	case CPUFREQ_GOV_STOP:
-		dbs_timer_exit(this_dbs_info);
-
-		mutex_lock(&dbs_mutex);
-		mutex_destroy(&this_dbs_info->timer_mutex);
-		dbs_enable--;
-		mutex_unlock(&dbs_mutex);
-		if (!dbs_enable)
-			sysfs_remove_group(cpufreq_global_kobject,
-					   &dbs_attr_group);
-
-		break;
-
-	case CPUFREQ_GOV_LIMITS:
-		mutex_lock(&this_dbs_info->timer_mutex);
-		if (policy->max < this_dbs_info->cur_policy->cur)
-			__cpufreq_driver_target(this_dbs_info->cur_policy,
-				policy->max, CPUFREQ_RELATION_H);
-		else if (policy->min > this_dbs_info->cur_policy->cur)
-			__cpufreq_driver_target(this_dbs_info->cur_policy,
-				policy->min, CPUFREQ_RELATION_L);
-		dbs_check_cpu(this_dbs_info);
-		mutex_unlock(&this_dbs_info->timer_mutex);
-		break;
-	}
-	return 0;
-}
+struct cpufreq_governor cpufreq_gov_ondemand = {
+	.name			= "ondemand",
+	.governor		= od_cpufreq_governor_dbs,
+	.max_transition_latency	= TRANSITION_LATENCY_LIMIT,
+	.owner			= THIS_MODULE,
+};
 
 static int __init cpufreq_gov_dbs_init(void)
 {
 	u64 idle_time;
 	int cpu = get_cpu();
 
+	mutex_init(&od_dbs_data.mutex);
 	idle_time = get_cpu_idle_time_us(cpu, NULL);
 	put_cpu();
 	if (idle_time != -1ULL) {
 		/* Idle micro accounting is supported. Use finer thresholds */
-		dbs_tuners_ins.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
-		dbs_tuners_ins.down_differential =
-					MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
+		od_tuners.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
+		od_tuners.down_differential = MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
 		/*
 		 * In nohz/micro accounting case we set the minimum frequency
 		 * not depending on HZ, but fixed (very low). The deferred
 		 * timer might skip some samples if idle/sleeping as needed.
 		*/
-		min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
+		od_dbs_data.min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
 	} else {
 		/* For correct statistics, we need 10 ticks for each measure */
-		min_sampling_rate =
-			MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10);
+		od_dbs_data.min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
+			jiffies_to_usecs(10);
 	}
 
 	return cpufreq_register_governor(&cpufreq_gov_ondemand);
@@ -800,7 +528,6 @@ static void __exit cpufreq_gov_dbs_exit(void)
 	cpufreq_unregister_governor(&cpufreq_gov_ondemand);
 }
 
-
 MODULE_AUTHOR("Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>");
 MODULE_AUTHOR("Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>");
 MODULE_DESCRIPTION("'cpufreq_ondemand' - A dynamic cpufreq governor for "
diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c
index f13a8a9..ceee068 100644
--- a/drivers/cpufreq/cpufreq_performance.c
+++ b/drivers/cpufreq/cpufreq_performance.c
@@ -10,6 +10,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/cpufreq.h>
diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c
index 4c2eb51..2d948a1 100644
--- a/drivers/cpufreq/cpufreq_powersave.c
+++ b/drivers/cpufreq/cpufreq_powersave.c
@@ -10,6 +10,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/cpufreq.h>
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 3998316..e40e508 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -37,7 +37,7 @@ struct cpufreq_stats {
 	unsigned int max_state;
 	unsigned int state_num;
 	unsigned int last_index;
-	cputime64_t *time_in_state;
+	u64 *time_in_state;
 	unsigned int *freq_table;
 #ifdef CONFIG_CPU_FREQ_STAT_DETAILS
 	unsigned int *trans_table;
@@ -223,7 +223,7 @@ static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
 		count++;
 	}
 
-	alloc_size = count * sizeof(int) + count * sizeof(cputime64_t);
+	alloc_size = count * sizeof(int) + count * sizeof(u64);
 
 #ifdef CONFIG_CPU_FREQ_STAT_DETAILS
 	alloc_size += count * count * sizeof(int);
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index bedac1a..c8c3d29 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -11,6 +11,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/smp.h>
diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c
index 74b830b..4f154bc 100644
--- a/drivers/cpufreq/db8500-cpufreq.c
+++ b/drivers/cpufreq/db8500-cpufreq.c
@@ -8,43 +8,17 @@
  * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
  *
  */
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/cpufreq.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
 #include <mach/id.h>
 
-static struct cpufreq_frequency_table freq_table[] = {
-	[0] = {
-		.index = 0,
-		.frequency = 200000,
-	},
-	[1] = {
-		.index = 1,
-		.frequency = 400000,
-	},
-	[2] = {
-		.index = 2,
-		.frequency = 800000,
-	},
-	[3] = {
-		/* Used for MAX_OPP, if available */
-		.index = 3,
-		.frequency = CPUFREQ_TABLE_END,
-	},
-	[4] = {
-		.index = 4,
-		.frequency = CPUFREQ_TABLE_END,
-	},
-};
-
-static enum arm_opp idx2opp[] = {
-	ARM_EXTCLK,
-	ARM_50_OPP,
-	ARM_100_OPP,
-	ARM_MAX_OPP
-};
+static struct cpufreq_frequency_table *freq_table;
+static struct clk *armss_clk;
 
 static struct freq_attr *db8500_cpufreq_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
@@ -85,9 +59,9 @@ static int db8500_cpufreq_target(struct cpufreq_policy *policy,
 	for_each_cpu(freqs.cpu, policy->cpus)
 		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
-	/* request the PRCM unit for opp change */
-	if (prcmu_set_arm_opp(idx2opp[idx])) {
-		pr_err("db8500-cpufreq:  Failed to set OPP level\n");
+	/* update armss clk frequency */
+	if (clk_set_rate(armss_clk, freq_table[idx].frequency * 1000)) {
+		pr_err("db8500-cpufreq: Failed to update armss clk\n");
 		return -EINVAL;
 	}
 
@@ -100,25 +74,36 @@ static int db8500_cpufreq_target(struct cpufreq_policy *policy,
 
 static unsigned int db8500_cpufreq_getspeed(unsigned int cpu)
 {
-	int i;
-	/* request the prcm to get the current ARM opp */
-	for (i = 0; prcmu_get_arm_opp() != idx2opp[i]; i++)
-		;
-	return freq_table[i].frequency;
+	int i = 0;
+	unsigned long freq = clk_get_rate(armss_clk) / 1000;
+
+	while (freq_table[i].frequency != CPUFREQ_TABLE_END) {
+		if (freq <= freq_table[i].frequency)
+			return freq_table[i].frequency;
+		i++;
+	}
+
+	/* We could not find a corresponding frequency. */
+	pr_err("db8500-cpufreq: Failed to find cpufreq speed\n");
+	return 0;
 }
 
 static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
 {
-	int i, res;
-
-	BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table));
+	int i = 0;
+	int res;
 
-	if (prcmu_has_arm_maxopp())
-		freq_table[3].frequency = 1000000;
+	armss_clk = clk_get(NULL, "armss");
+	if (IS_ERR(armss_clk)) {
+		pr_err("db8500-cpufreq : Failed to get armss clk\n");
+		return PTR_ERR(armss_clk);
+	}
 
 	pr_info("db8500-cpufreq : Available frequencies:\n");
-	for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
+	while (freq_table[i].frequency != CPUFREQ_TABLE_END) {
 		pr_info("  %d Mhz\n", freq_table[i].frequency/1000);
+		i++;
+	}
 
 	/* get policy fields based on the table */
 	res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
@@ -126,6 +111,7 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
 		cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
 	else {
 		pr_err("db8500-cpufreq : Failed to read policy table\n");
+		clk_put(armss_clk);
 		return res;
 	}
 
@@ -159,12 +145,35 @@ static struct cpufreq_driver db8500_cpufreq_driver = {
 	.attr   = db8500_cpufreq_attr,
 };
 
+static int db8500_cpufreq_probe(struct platform_device *pdev)
+{
+	freq_table = dev_get_platdata(&pdev->dev);
+
+	if (!freq_table) {
+		pr_err("db8500-cpufreq: Failed to fetch cpufreq table\n");
+		return -ENODEV;
+	}
+
+	return cpufreq_register_driver(&db8500_cpufreq_driver);
+}
+
+static struct platform_driver db8500_cpufreq_plat_driver = {
+	.driver = {
+		.name = "cpufreq-u8500",
+		.owner = THIS_MODULE,
+	},
+	.probe = db8500_cpufreq_probe,
+};
+
 static int __init db8500_cpufreq_register(void)
 {
 	if (!cpu_is_u8500_family())
 		return -ENODEV;
 
 	pr_info("cpufreq for DB8500 started\n");
-	return cpufreq_register_driver(&db8500_cpufreq_driver);
+	return platform_driver_register(&db8500_cpufreq_plat_driver);
 }
 device_initcall(db8500_cpufreq_register);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("cpufreq driver for DB8500");
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index af2d81e..7012ea8 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -31,13 +31,13 @@ static unsigned int locking_frequency;
 static bool frequency_locked;
 static DEFINE_MUTEX(cpufreq_lock);
 
-int exynos_verify_speed(struct cpufreq_policy *policy)
+static int exynos_verify_speed(struct cpufreq_policy *policy)
 {
 	return cpufreq_frequency_table_verify(policy,
 					      exynos_info->freq_table);
 }
 
-unsigned int exynos_getspeed(unsigned int cpu)
+static unsigned int exynos_getspeed(unsigned int cpu)
 {
 	return clk_get_rate(exynos_info->cpu_clk) / 1000;
 }
@@ -100,7 +100,8 @@ static int exynos_target(struct cpufreq_policy *policy,
 	}
 	arm_volt = volt_table[index];
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	for_each_cpu(freqs.cpu, policy->cpus)
+		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
 	/* When the new frequency is higher than current frequency */
 	if ((freqs.new > freqs.old) && !safe_arm_volt) {
@@ -115,7 +116,8 @@ static int exynos_target(struct cpufreq_policy *policy,
 	if (freqs.new != freqs.old)
 		exynos_info->set_freq(old_index, index);
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	for_each_cpu(freqs.cpu, policy->cpus)
+		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
 	/* When the new frequency is lower than current frequency */
 	if ((freqs.new < freqs.old) ||
@@ -235,6 +237,7 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		cpumask_copy(policy->related_cpus, cpu_possible_mask);
 		cpumask_copy(policy->cpus, cpu_online_mask);
 	} else {
+		policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
 		cpumask_setall(policy->cpus);
 	}
 
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index 90431cb..49cda25 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -9,6 +9,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c
index 53ddbc7..f1fa500 100644
--- a/drivers/cpufreq/longhaul.c
+++ b/drivers/cpufreq/longhaul.c
@@ -930,7 +930,7 @@ static int __cpuinit longhaul_cpu_init(struct cpufreq_policy *policy)
 	return 0;
 }
 
-static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy)
+static int longhaul_cpu_exit(struct cpufreq_policy *policy)
 {
 	cpufreq_frequency_table_put_attr(policy->cpu);
 	return 0;
@@ -946,7 +946,7 @@ static struct cpufreq_driver longhaul_driver = {
 	.target	= longhaul_target,
 	.get	= longhaul_get,
 	.init	= longhaul_cpu_init,
-	.exit	= __devexit_p(longhaul_cpu_exit),
+	.exit	= longhaul_cpu_exit,
 	.name	= "longhaul",
 	.owner	= THIS_MODULE,
 	.attr	= longhaul_attr,
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index e3ebb4f..056faf6 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -1186,7 +1186,7 @@ err_out:
 	return -ENODEV;
 }
 
-static int __devexit powernowk8_cpu_exit(struct cpufreq_policy *pol)
+static int powernowk8_cpu_exit(struct cpufreq_policy *pol)
 {
 	struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
 
@@ -1242,7 +1242,7 @@ static struct cpufreq_driver cpufreq_amd64_driver = {
 	.target		= powernowk8_target,
 	.bios_limit	= acpi_processor_get_bios_limit,
 	.init		= powernowk8_cpu_init,
-	.exit		= __devexit_p(powernowk8_cpu_exit),
+	.exit		= powernowk8_cpu_exit,
 	.get		= powernowk8_get,
 	.name		= "powernow-k8",
 	.owner		= THIS_MODULE,
diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c
new file mode 100644
index 0000000..4575cfe
--- /dev/null
+++ b/drivers/cpufreq/spear-cpufreq.c
@@ -0,0 +1,291 @@
+/*
+ * drivers/cpufreq/spear-cpufreq.c
+ *
+ * CPU Frequency Scaling for SPEAr platform
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Deepak Sikri <deepak.sikri@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+/* SPEAr CPUFreq driver data structure */
+static struct {
+	struct clk *clk;
+	unsigned int transition_latency;
+	struct cpufreq_frequency_table *freq_tbl;
+	u32 cnt;
+} spear_cpufreq;
+
+int spear_cpufreq_verify(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, spear_cpufreq.freq_tbl);
+}
+
+static unsigned int spear_cpufreq_get(unsigned int cpu)
+{
+	return clk_get_rate(spear_cpufreq.clk) / 1000;
+}
+
+static struct clk *spear1340_cpu_get_possible_parent(unsigned long newfreq)
+{
+	struct clk *sys_pclk;
+	int pclk;
+	/*
+	 * In SPEAr1340, cpu clk's parent sys clk can take input from
+	 * following sources
+	 */
+	const char *sys_clk_src[] = {
+		"sys_syn_clk",
+		"pll1_clk",
+		"pll2_clk",
+		"pll3_clk",
+	};
+
+	/*
+	 * As sys clk can have multiple source with their own range
+	 * limitation so we choose possible sources accordingly
+	 */
+	if (newfreq <= 300000000)
+		pclk = 0; /* src is sys_syn_clk */
+	else if (newfreq > 300000000 && newfreq <= 500000000)
+		pclk = 3; /* src is pll3_clk */
+	else if (newfreq == 600000000)
+		pclk = 1; /* src is pll1_clk */
+	else
+		return ERR_PTR(-EINVAL);
+
+	/* Get parent to sys clock */
+	sys_pclk = clk_get(NULL, sys_clk_src[pclk]);
+	if (IS_ERR(sys_pclk))
+		pr_err("Failed to get %s clock\n", sys_clk_src[pclk]);
+
+	return sys_pclk;
+}
+
+/*
+ * In SPEAr1340, we cannot use newfreq directly because we need to actually
+ * access a source clock (clk) which might not be ancestor of cpu at present.
+ * Hence in SPEAr1340 we would operate on source clock directly before switching
+ * cpu clock to it.
+ */
+static int spear1340_set_cpu_rate(struct clk *sys_pclk, unsigned long newfreq)
+{
+	struct clk *sys_clk;
+	int ret = 0;
+
+	sys_clk = clk_get_parent(spear_cpufreq.clk);
+	if (IS_ERR(sys_clk)) {
+		pr_err("failed to get cpu's parent (sys) clock\n");
+		return PTR_ERR(sys_clk);
+	}
+
+	/* Set the rate of the source clock before changing the parent */
+	ret = clk_set_rate(sys_pclk, newfreq);
+	if (ret) {
+		pr_err("Failed to set sys clk rate to %lu\n", newfreq);
+		return ret;
+	}
+
+	ret = clk_set_parent(sys_clk, sys_pclk);
+	if (ret) {
+		pr_err("Failed to set sys clk parent\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int spear_cpufreq_target(struct cpufreq_policy *policy,
+		unsigned int target_freq, unsigned int relation)
+{
+	struct cpufreq_freqs freqs;
+	unsigned long newfreq;
+	struct clk *srcclk;
+	int index, ret, mult = 1;
+
+	if (cpufreq_frequency_table_target(policy, spear_cpufreq.freq_tbl,
+				target_freq, relation, &index))
+		return -EINVAL;
+
+	freqs.cpu = policy->cpu;
+	freqs.old = spear_cpufreq_get(0);
+
+	newfreq = spear_cpufreq.freq_tbl[index].frequency * 1000;
+	if (of_machine_is_compatible("st,spear1340")) {
+		/*
+		 * SPEAr1340 is special in the sense that due to the possibility
+		 * of multiple clock sources for cpu clk's parent we can have
+		 * different clock source for different frequency of cpu clk.
+		 * Hence we need to choose one from amongst these possible clock
+		 * sources.
+		 */
+		srcclk = spear1340_cpu_get_possible_parent(newfreq);
+		if (IS_ERR(srcclk)) {
+			pr_err("Failed to get src clk\n");
+			return PTR_ERR(srcclk);
+		}
+
+		/* SPEAr1340: src clk is always 2 * intended cpu clk */
+		mult = 2;
+	} else {
+		/*
+		 * src clock to be altered is ancestor of cpu clock. Hence we
+		 * can directly work on cpu clk
+		 */
+		srcclk = spear_cpufreq.clk;
+	}
+
+	newfreq = clk_round_rate(srcclk, newfreq * mult);
+	if (newfreq < 0) {
+		pr_err("clk_round_rate failed for cpu src clock\n");
+		return newfreq;
+	}
+
+	freqs.new = newfreq / 1000;
+	freqs.new /= mult;
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	if (mult == 2)
+		ret = spear1340_set_cpu_rate(srcclk, newfreq);
+	else
+		ret = clk_set_rate(spear_cpufreq.clk, newfreq);
+
+	/* Get current rate after clk_set_rate, in case of failure */
+	if (ret) {
+		pr_err("CPU Freq: cpu clk_set_rate failed: %d\n", ret);
+		freqs.new = clk_get_rate(spear_cpufreq.clk) / 1000;
+	}
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	return ret;
+}
+
+static int spear_cpufreq_init(struct cpufreq_policy *policy)
+{
+	int ret;
+
+	ret = cpufreq_frequency_table_cpuinfo(policy, spear_cpufreq.freq_tbl);
+	if (ret) {
+		pr_err("cpufreq_frequency_table_cpuinfo() failed");
+		return ret;
+	}
+
+	cpufreq_frequency_table_get_attr(spear_cpufreq.freq_tbl, policy->cpu);
+	policy->cpuinfo.transition_latency = spear_cpufreq.transition_latency;
+	policy->cur = spear_cpufreq_get(0);
+
+	cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu));
+	cpumask_copy(policy->related_cpus, policy->cpus);
+
+	return 0;
+}
+
+static int spear_cpufreq_exit(struct cpufreq_policy *policy)
+{
+	cpufreq_frequency_table_put_attr(policy->cpu);
+	return 0;
+}
+
+static struct freq_attr *spear_cpufreq_attr[] = {
+	 &cpufreq_freq_attr_scaling_available_freqs,
+	 NULL,
+};
+
+static struct cpufreq_driver spear_cpufreq_driver = {
+	.name		= "cpufreq-spear",
+	.flags		= CPUFREQ_STICKY,
+	.verify		= spear_cpufreq_verify,
+	.target		= spear_cpufreq_target,
+	.get		= spear_cpufreq_get,
+	.init		= spear_cpufreq_init,
+	.exit		= spear_cpufreq_exit,
+	.attr		= spear_cpufreq_attr,
+};
+
+static int spear_cpufreq_driver_init(void)
+{
+	struct device_node *np;
+	const struct property *prop;
+	struct cpufreq_frequency_table *freq_tbl;
+	const __be32 *val;
+	int cnt, i, ret;
+
+	np = of_find_node_by_path("/cpus/cpu@0");
+	if (!np) {
+		pr_err("No cpu node found");
+		return -ENODEV;
+	}
+
+	if (of_property_read_u32(np, "clock-latency",
+				&spear_cpufreq.transition_latency))
+		spear_cpufreq.transition_latency = CPUFREQ_ETERNAL;
+
+	prop = of_find_property(np, "cpufreq_tbl", NULL);
+	if (!prop || !prop->value) {
+		pr_err("Invalid cpufreq_tbl");
+		ret = -ENODEV;
+		goto out_put_node;
+	}
+
+	cnt = prop->length / sizeof(u32);
+	val = prop->value;
+
+	freq_tbl = kmalloc(sizeof(*freq_tbl) * (cnt + 1), GFP_KERNEL);
+	if (!freq_tbl) {
+		ret = -ENOMEM;
+		goto out_put_node;
+	}
+
+	for (i = 0; i < cnt; i++) {
+		freq_tbl[i].index = i;
+		freq_tbl[i].frequency = be32_to_cpup(val++);
+	}
+
+	freq_tbl[i].index = i;
+	freq_tbl[i].frequency = CPUFREQ_TABLE_END;
+
+	spear_cpufreq.freq_tbl = freq_tbl;
+
+	of_node_put(np);
+
+	spear_cpufreq.clk = clk_get(NULL, "cpu_clk");
+	if (IS_ERR(spear_cpufreq.clk)) {
+		pr_err("Unable to get CPU clock\n");
+		ret = PTR_ERR(spear_cpufreq.clk);
+		goto out_put_mem;
+	}
+
+	ret = cpufreq_register_driver(&spear_cpufreq_driver);
+	if (!ret)
+		return 0;
+
+	pr_err("failed register driver: %d\n", ret);
+	clk_put(spear_cpufreq.clk);
+
+out_put_mem:
+	kfree(freq_tbl);
+	return ret;
+
+out_put_node:
+	of_node_put(np);
+	return ret;
+}
+late_initcall(spear_cpufreq_driver_init);
+
+MODULE_AUTHOR("Deepak Sikri <deepak.sikri@st.com>");
+MODULE_DESCRIPTION("SPEAr CPUFreq driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index a76b689..c4cc27e 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -9,6 +9,15 @@ config CPU_IDLE
 
 	  If you're using an ACPI-enabled platform, you should say Y here.
 
+config CPU_IDLE_MULTIPLE_DRIVERS
+        bool "Support multiple cpuidle drivers"
+        depends on CPU_IDLE
+        default n
+        help
+         Allows the cpuidle framework to use different drivers for each CPU.
+         This is useful if you have a system with different CPU latencies and
+         states. If unsure say N.
+
 config CPU_IDLE_GOV_LADDER
 	bool
 	depends on CPU_IDLE
@@ -21,3 +30,13 @@ config CPU_IDLE_GOV_MENU
 
 config ARCH_NEEDS_CPU_IDLE_COUPLED
 	def_bool n
+
+if CPU_IDLE
+
+config CPU_IDLE_CALXEDA
+	bool "CPU Idle Driver for Calxeda processors"
+	depends on ARCH_HIGHBANK
+	help
+	  Select this to enable cpuidle on Calxeda processors.
+
+endif
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index 38c8f69..03ee874 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -4,3 +4,5 @@
 
 obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
 obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
+
+obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o
diff --git a/drivers/cpuidle/cpuidle-calxeda.c b/drivers/cpuidle/cpuidle-calxeda.c
new file mode 100644
index 0000000..e1aab38
--- /dev/null
+++ b/drivers/cpuidle/cpuidle-calxeda.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2012 Calxeda, Inc.
+ *
+ * Based on arch/arm/plat-mxc/cpuidle.c:
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012 Linaro 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/cpuidle.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 <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 *scu_base_addr;
+
+static struct cpuidle_device __percpu *calxeda_idle_cpuidle_devices;
+
+static inline unsigned int get_auxcr(void)
+{
+	unsigned int val;
+	asm("mrc p15, 0, %0, c1, c0, 1	@ get AUXCR" : "=r" (val) : : "cc");
+	return val;
+}
+
+static inline void set_auxcr(unsigned int val)
+{
+	asm volatile("mcr p15, 0, %0, c1, c0, 1	@ set AUXCR"
+	  : : "r" (val) : "cc");
+	isb();
+}
+
+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);
+}
+
+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;
+}
+
+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_suspend(0, calxeda_idle_finish);
+	return index;
+}
+
+static void calxeda_idle_cpuidle_devices_uninit(void)
+{
+	int i;
+	struct cpuidle_device *dev;
+
+	for_each_possible_cpu(i) {
+		dev = per_cpu_ptr(calxeda_idle_cpuidle_devices, i);
+		cpuidle_unregister_device(dev);
+	}
+
+	free_percpu(calxeda_idle_cpuidle_devices);
+}
+
+static struct cpuidle_driver calxeda_idle_driver = {
+	.name = "calxeda_idle",
+	.en_core_tk_irqen = 1,
+	.states = {
+		ARM_CPUIDLE_WFI_STATE,
+		{
+			.name = "PG",
+			.desc = "Power Gate",
+			.flags = CPUIDLE_FLAG_TIME_VALID,
+			.exit_latency = 30,
+			.power_usage = 50,
+			.target_residency = 200,
+			.enter = calxeda_pwrdown_idle,
+		},
+	},
+	.state_count = 2,
+};
+
+static int __init calxeda_cpuidle_init(void)
+{
+	int cpu_id;
+	int ret;
+	struct cpuidle_device *dev;
+	struct cpuidle_driver *drv = &calxeda_idle_driver;
+
+	if (!of_machine_is_compatible("calxeda,highbank"))
+		return -ENODEV;
+
+	ret = cpuidle_register_driver(drv);
+	if (ret)
+		return ret;
+
+	calxeda_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
+	if (calxeda_idle_cpuidle_devices == NULL) {
+		ret = -ENOMEM;
+		goto unregister_drv;
+	}
+
+	/* initialize state data for each cpuidle_device */
+	for_each_possible_cpu(cpu_id) {
+		dev = per_cpu_ptr(calxeda_idle_cpuidle_devices, cpu_id);
+		dev->cpu = cpu_id;
+		dev->state_count = drv->state_count;
+
+		ret = cpuidle_register_device(dev);
+		if (ret) {
+			pr_err("Failed to register cpu %u, error: %d\n",
+			       cpu_id, ret);
+			goto uninit;
+		}
+	}
+
+	return 0;
+
+uninit:
+	calxeda_idle_cpuidle_devices_uninit();
+unregister_drv:
+	cpuidle_unregister_driver(drv);
+	return ret;
+}
+module_init(calxeda_cpuidle_init);
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 7f15b85..8df53dd 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -68,7 +68,7 @@ static cpuidle_enter_t cpuidle_enter_ops;
 int cpuidle_play_dead(void)
 {
 	struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
-	struct cpuidle_driver *drv = cpuidle_get_driver();
+	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
 	int i, dead_state = -1;
 	int power_usage = -1;
 
@@ -109,8 +109,7 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
 		/* This can be moved to within driver enter routine
 		 * but that results in multiple copies of same code.
 		 */
-		dev->states_usage[entered_state].time +=
-				(unsigned long long)dev->last_residency;
+		dev->states_usage[entered_state].time += dev->last_residency;
 		dev->states_usage[entered_state].usage++;
 	} else {
 		dev->last_residency = 0;
@@ -128,7 +127,7 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
 int cpuidle_idle_call(void)
 {
 	struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
-	struct cpuidle_driver *drv = cpuidle_get_driver();
+	struct cpuidle_driver *drv;
 	int next_state, entered_state;
 
 	if (off)
@@ -141,9 +140,15 @@ int cpuidle_idle_call(void)
 	if (!dev || !dev->enabled)
 		return -EBUSY;
 
+	drv = cpuidle_get_cpu_driver(dev);
+
 	/* ask the governor for the next state */
 	next_state = cpuidle_curr_governor->select(drv, dev);
 	if (need_resched()) {
+		dev->last_residency = 0;
+		/* give the governor an opportunity to reflect on the outcome */
+		if (cpuidle_curr_governor->reflect)
+			cpuidle_curr_governor->reflect(dev, next_state);
 		local_irq_enable();
 		return 0;
 	}
@@ -308,15 +313,19 @@ static void poll_idle_init(struct cpuidle_driver *drv) {}
 int cpuidle_enable_device(struct cpuidle_device *dev)
 {
 	int ret, i;
-	struct cpuidle_driver *drv = cpuidle_get_driver();
+	struct cpuidle_driver *drv;
 
 	if (!dev)
 		return -EINVAL;
 
 	if (dev->enabled)
 		return 0;
+
+	drv = cpuidle_get_cpu_driver(dev);
+
 	if (!drv || !cpuidle_curr_governor)
 		return -EIO;
+
 	if (!dev->state_count)
 		dev->state_count = drv->state_count;
 
@@ -331,7 +340,8 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
 
 	poll_idle_init(drv);
 
-	if ((ret = cpuidle_add_state_sysfs(dev)))
+	ret = cpuidle_add_device_sysfs(dev);
+	if (ret)
 		return ret;
 
 	if (cpuidle_curr_governor->enable &&
@@ -352,7 +362,7 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
 	return 0;
 
 fail_sysfs:
-	cpuidle_remove_state_sysfs(dev);
+	cpuidle_remove_device_sysfs(dev);
 
 	return ret;
 }
@@ -368,17 +378,20 @@ EXPORT_SYMBOL_GPL(cpuidle_enable_device);
  */
 void cpuidle_disable_device(struct cpuidle_device *dev)
 {
+	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
+
 	if (!dev || !dev->enabled)
 		return;
-	if (!cpuidle_get_driver() || !cpuidle_curr_governor)
+
+	if (!drv || !cpuidle_curr_governor)
 		return;
 
 	dev->enabled = 0;
 
 	if (cpuidle_curr_governor->disable)
-		cpuidle_curr_governor->disable(cpuidle_get_driver(), dev);
+		cpuidle_curr_governor->disable(drv, dev);
 
-	cpuidle_remove_state_sysfs(dev);
+	cpuidle_remove_device_sysfs(dev);
 	enabled_devices--;
 }
 
@@ -394,17 +407,14 @@ EXPORT_SYMBOL_GPL(cpuidle_disable_device);
 static int __cpuidle_register_device(struct cpuidle_device *dev)
 {
 	int ret;
-	struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
-	struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();
+	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
 
-	if (!try_module_get(cpuidle_driver->owner))
+	if (!try_module_get(drv->owner))
 		return -EINVAL;
 
-	init_completion(&dev->kobj_unregister);
-
 	per_cpu(cpuidle_devices, dev->cpu) = dev;
 	list_add(&dev->device_list, &cpuidle_detected_devices);
-	ret = cpuidle_add_sysfs(cpu_dev);
+	ret = cpuidle_add_sysfs(dev);
 	if (ret)
 		goto err_sysfs;
 
@@ -416,12 +426,11 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
 	return 0;
 
 err_coupled:
-	cpuidle_remove_sysfs(cpu_dev);
-	wait_for_completion(&dev->kobj_unregister);
+	cpuidle_remove_sysfs(dev);
 err_sysfs:
 	list_del(&dev->device_list);
 	per_cpu(cpuidle_devices, dev->cpu) = NULL;
-	module_put(cpuidle_driver->owner);
+	module_put(drv->owner);
 	return ret;
 }
 
@@ -460,8 +469,7 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device);
  */
 void cpuidle_unregister_device(struct cpuidle_device *dev)
 {
-	struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
-	struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();
+	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
 
 	if (dev->registered == 0)
 		return;
@@ -470,16 +478,15 @@ void cpuidle_unregister_device(struct cpuidle_device *dev)
 
 	cpuidle_disable_device(dev);
 
-	cpuidle_remove_sysfs(cpu_dev);
+	cpuidle_remove_sysfs(dev);
 	list_del(&dev->device_list);
-	wait_for_completion(&dev->kobj_unregister);
 	per_cpu(cpuidle_devices, dev->cpu) = NULL;
 
 	cpuidle_coupled_unregister_device(dev);
 
 	cpuidle_resume_and_unlock();
 
-	module_put(cpuidle_driver->owner);
+	module_put(drv->owner);
 }
 
 EXPORT_SYMBOL_GPL(cpuidle_unregister_device);
diff --git a/drivers/cpuidle/cpuidle.h b/drivers/cpuidle/cpuidle.h
index 76e7f69..ee97e96 100644
--- a/drivers/cpuidle/cpuidle.h
+++ b/drivers/cpuidle/cpuidle.h
@@ -5,8 +5,6 @@
 #ifndef __DRIVER_CPUIDLE_H
 #define __DRIVER_CPUIDLE_H
 
-#include <linux/device.h>
-
 /* For internal use only */
 extern struct cpuidle_governor *cpuidle_curr_governor;
 extern struct list_head cpuidle_governors;
@@ -25,12 +23,15 @@ extern void cpuidle_uninstall_idle_handler(void);
 extern int cpuidle_switch_governor(struct cpuidle_governor *gov);
 
 /* sysfs */
+
+struct device;
+
 extern int cpuidle_add_interface(struct device *dev);
 extern void cpuidle_remove_interface(struct device *dev);
-extern int cpuidle_add_state_sysfs(struct cpuidle_device *device);
-extern void cpuidle_remove_state_sysfs(struct cpuidle_device *device);
-extern int cpuidle_add_sysfs(struct device *dev);
-extern void cpuidle_remove_sysfs(struct device *dev);
+extern int cpuidle_add_device_sysfs(struct cpuidle_device *device);
+extern void cpuidle_remove_device_sysfs(struct cpuidle_device *device);
+extern int cpuidle_add_sysfs(struct cpuidle_device *dev);
+extern void cpuidle_remove_sysfs(struct cpuidle_device *dev);
 
 #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
 bool cpuidle_state_is_coupled(struct cpuidle_device *dev,
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index 87db387..3af841f 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -14,9 +14,10 @@
 
 #include "cpuidle.h"
 
-static struct cpuidle_driver *cpuidle_curr_driver;
 DEFINE_SPINLOCK(cpuidle_driver_lock);
-int cpuidle_driver_refcount;
+
+static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu);
+static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu);
 
 static void set_power_states(struct cpuidle_driver *drv)
 {
@@ -40,11 +41,15 @@ static void set_power_states(struct cpuidle_driver *drv)
 		drv->states[i].power_usage = -1 - i;
 }
 
-/**
- * cpuidle_register_driver - registers a driver
- * @drv: the driver
- */
-int cpuidle_register_driver(struct cpuidle_driver *drv)
+static void __cpuidle_driver_init(struct cpuidle_driver *drv)
+{
+	drv->refcnt = 0;
+
+	if (!drv->power_specified)
+		set_power_states(drv);
+}
+
+static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu)
 {
 	if (!drv || !drv->state_count)
 		return -EINVAL;
@@ -52,31 +57,145 @@ int cpuidle_register_driver(struct cpuidle_driver *drv)
 	if (cpuidle_disabled())
 		return -ENODEV;
 
-	spin_lock(&cpuidle_driver_lock);
-	if (cpuidle_curr_driver) {
-		spin_unlock(&cpuidle_driver_lock);
+	if (__cpuidle_get_cpu_driver(cpu))
 		return -EBUSY;
+
+	__cpuidle_driver_init(drv);
+
+	__cpuidle_set_cpu_driver(drv, cpu);
+
+	return 0;
+}
+
+static void __cpuidle_unregister_driver(struct cpuidle_driver *drv, int cpu)
+{
+	if (drv != __cpuidle_get_cpu_driver(cpu))
+		return;
+
+	if (!WARN_ON(drv->refcnt > 0))
+		__cpuidle_set_cpu_driver(NULL, cpu);
+}
+
+#ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS
+
+static DEFINE_PER_CPU(struct cpuidle_driver *, cpuidle_drivers);
+
+static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu)
+{
+	per_cpu(cpuidle_drivers, cpu) = drv;
+}
+
+static struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu)
+{
+	return per_cpu(cpuidle_drivers, cpu);
+}
+
+static void __cpuidle_unregister_all_cpu_driver(struct cpuidle_driver *drv)
+{
+	int cpu;
+	for_each_present_cpu(cpu)
+		__cpuidle_unregister_driver(drv, cpu);
+}
+
+static int __cpuidle_register_all_cpu_driver(struct cpuidle_driver *drv)
+{
+	int ret = 0;
+	int i, cpu;
+
+	for_each_present_cpu(cpu) {
+		ret = __cpuidle_register_driver(drv, cpu);
+		if (ret)
+			break;
 	}
 
-	if (!drv->power_specified)
-		set_power_states(drv);
+	if (ret)
+		for_each_present_cpu(i) {
+			if (i == cpu)
+				break;
+			__cpuidle_unregister_driver(drv, i);
+		}
 
-	cpuidle_curr_driver = drv;
 
+	return ret;
+}
+
+int cpuidle_register_cpu_driver(struct cpuidle_driver *drv, int cpu)
+{
+	int ret;
+
+	spin_lock(&cpuidle_driver_lock);
+	ret = __cpuidle_register_driver(drv, cpu);
 	spin_unlock(&cpuidle_driver_lock);
 
-	return 0;
+	return ret;
+}
+
+void cpuidle_unregister_cpu_driver(struct cpuidle_driver *drv, int cpu)
+{
+	spin_lock(&cpuidle_driver_lock);
+	__cpuidle_unregister_driver(drv, cpu);
+	spin_unlock(&cpuidle_driver_lock);
+}
+
+/**
+ * cpuidle_register_driver - registers a driver
+ * @drv: the driver
+ */
+int cpuidle_register_driver(struct cpuidle_driver *drv)
+{
+	int ret;
+
+	spin_lock(&cpuidle_driver_lock);
+	ret = __cpuidle_register_all_cpu_driver(drv);
+	spin_unlock(&cpuidle_driver_lock);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(cpuidle_register_driver);
 
 /**
- * cpuidle_get_driver - return the current driver
+ * cpuidle_unregister_driver - unregisters a driver
+ * @drv: the driver
  */
-struct cpuidle_driver *cpuidle_get_driver(void)
+void cpuidle_unregister_driver(struct cpuidle_driver *drv)
+{
+	spin_lock(&cpuidle_driver_lock);
+	__cpuidle_unregister_all_cpu_driver(drv);
+	spin_unlock(&cpuidle_driver_lock);
+}
+EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
+
+#else
+
+static struct cpuidle_driver *cpuidle_curr_driver;
+
+static inline void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu)
+{
+	cpuidle_curr_driver = drv;
+}
+
+static inline struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu)
 {
 	return cpuidle_curr_driver;
 }
-EXPORT_SYMBOL_GPL(cpuidle_get_driver);
+
+/**
+ * cpuidle_register_driver - registers a driver
+ * @drv: the driver
+ */
+int cpuidle_register_driver(struct cpuidle_driver *drv)
+{
+	int ret, cpu;
+
+	cpu = get_cpu();
+	spin_lock(&cpuidle_driver_lock);
+	ret = __cpuidle_register_driver(drv, cpu);
+	spin_unlock(&cpuidle_driver_lock);
+	put_cpu();
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cpuidle_register_driver);
 
 /**
  * cpuidle_unregister_driver - unregisters a driver
@@ -84,20 +203,50 @@ EXPORT_SYMBOL_GPL(cpuidle_get_driver);
  */
 void cpuidle_unregister_driver(struct cpuidle_driver *drv)
 {
-	if (drv != cpuidle_curr_driver) {
-		WARN(1, "invalid cpuidle_unregister_driver(%s)\n",
-			drv->name);
-		return;
-	}
+	int cpu;
 
+	cpu = get_cpu();
 	spin_lock(&cpuidle_driver_lock);
+	__cpuidle_unregister_driver(drv, cpu);
+	spin_unlock(&cpuidle_driver_lock);
+	put_cpu();
+}
+EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
+#endif
+
+/**
+ * cpuidle_get_driver - return the current driver
+ */
+struct cpuidle_driver *cpuidle_get_driver(void)
+{
+	struct cpuidle_driver *drv;
+	int cpu;
 
-	if (!WARN_ON(cpuidle_driver_refcount > 0))
-		cpuidle_curr_driver = NULL;
+	cpu = get_cpu();
+	drv = __cpuidle_get_cpu_driver(cpu);
+	put_cpu();
 
+	return drv;
+}
+EXPORT_SYMBOL_GPL(cpuidle_get_driver);
+
+/**
+ * cpuidle_get_cpu_driver - return the driver tied with a cpu
+ */
+struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev)
+{
+	struct cpuidle_driver *drv;
+
+	if (!dev)
+		return NULL;
+
+	spin_lock(&cpuidle_driver_lock);
+	drv = __cpuidle_get_cpu_driver(dev->cpu);
 	spin_unlock(&cpuidle_driver_lock);
+
+	return drv;
 }
-EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
+EXPORT_SYMBOL_GPL(cpuidle_get_cpu_driver);
 
 struct cpuidle_driver *cpuidle_driver_ref(void)
 {
@@ -105,8 +254,8 @@ struct cpuidle_driver *cpuidle_driver_ref(void)
 
 	spin_lock(&cpuidle_driver_lock);
 
-	drv = cpuidle_curr_driver;
-	cpuidle_driver_refcount++;
+	drv = cpuidle_get_driver();
+	drv->refcnt++;
 
 	spin_unlock(&cpuidle_driver_lock);
 	return drv;
@@ -114,10 +263,12 @@ struct cpuidle_driver *cpuidle_driver_ref(void)
 
 void cpuidle_driver_unref(void)
 {
+	struct cpuidle_driver *drv = cpuidle_get_driver();
+
 	spin_lock(&cpuidle_driver_lock);
 
-	if (!WARN_ON(cpuidle_driver_refcount <= 0))
-		cpuidle_driver_refcount--;
+	if (drv && !WARN_ON(drv->refcnt <= 0))
+		drv->refcnt--;
 
 	spin_unlock(&cpuidle_driver_lock);
 }
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 5b1f2c3..bd40b94 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -28,6 +28,13 @@
 #define MAX_INTERESTING 50000
 #define STDDEV_THRESH 400
 
+/* 60 * 60 > STDDEV_THRESH * INTERVALS = 400 * 8 */
+#define MAX_DEVIATION 60
+
+static DEFINE_PER_CPU(struct hrtimer, menu_hrtimer);
+static DEFINE_PER_CPU(int, hrtimer_status);
+/* menu hrtimer mode */
+enum {MENU_HRTIMER_STOP, MENU_HRTIMER_REPEAT, MENU_HRTIMER_GENERAL};
 
 /*
  * Concepts and ideas behind the menu governor
@@ -109,6 +116,13 @@
  *
  */
 
+/*
+ * The C-state residency is so long that is is worthwhile to exit
+ * from the shallow C-state and re-enter into a deeper C-state.
+ */
+static unsigned int perfect_cstate_ms __read_mostly = 30;
+module_param(perfect_cstate_ms, uint, 0000);
+
 struct menu_device {
 	int		last_state_idx;
 	int             needs_update;
@@ -191,40 +205,102 @@ static u64 div_round64(u64 dividend, u32 divisor)
 	return div_u64(dividend + (divisor / 2), divisor);
 }
 
+/* Cancel the hrtimer if it is not triggered yet */
+void menu_hrtimer_cancel(void)
+{
+	int cpu = smp_processor_id();
+	struct hrtimer *hrtmr = &per_cpu(menu_hrtimer, cpu);
+
+	/* The timer is still not time out*/
+	if (per_cpu(hrtimer_status, cpu)) {
+		hrtimer_cancel(hrtmr);
+		per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP;
+	}
+}
+EXPORT_SYMBOL_GPL(menu_hrtimer_cancel);
+
+/* Call back for hrtimer is triggered */
+static enum hrtimer_restart menu_hrtimer_notify(struct hrtimer *hrtimer)
+{
+	int cpu = smp_processor_id();
+	struct menu_device *data = &per_cpu(menu_devices, cpu);
+
+	/* In general case, the expected residency is much larger than
+	 *  deepest C-state target residency, but prediction logic still
+	 *  predicts a small predicted residency, so the prediction
+	 *  history is totally broken if the timer is triggered.
+	 *  So reset the correction factor.
+	 */
+	if (per_cpu(hrtimer_status, cpu) == MENU_HRTIMER_GENERAL)
+		data->correction_factor[data->bucket] = RESOLUTION * DECAY;
+
+	per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP;
+
+	return HRTIMER_NORESTART;
+}
+
 /*
  * Try detecting repeating patterns by keeping track of the last 8
  * intervals, and checking if the standard deviation of that set
  * of points is below a threshold. If it is... then use the
  * average of these 8 points as the estimated value.
  */
-static void detect_repeating_patterns(struct menu_device *data)
+static u32 get_typical_interval(struct menu_device *data)
 {
-	int i;
-	uint64_t avg = 0;
-	uint64_t stddev = 0; /* contains the square of the std deviation */
-
-	/* first calculate average and standard deviation of the past */
-	for (i = 0; i < INTERVALS; i++)
-		avg += data->intervals[i];
-	avg = avg / INTERVALS;
+	int i = 0, divisor = 0;
+	uint64_t max = 0, avg = 0, stddev = 0;
+	int64_t thresh = LLONG_MAX; /* Discard outliers above this value. */
+	unsigned int ret = 0;
 
-	/* if the avg is beyond the known next tick, it's worthless */
-	if (avg > data->expected_us)
-		return;
+again:
 
-	for (i = 0; i < INTERVALS; i++)
-		stddev += (data->intervals[i] - avg) *
-			  (data->intervals[i] - avg);
-
-	stddev = stddev / INTERVALS;
+	/* first calculate average and standard deviation of the past */
+	max = avg = divisor = stddev = 0;
+	for (i = 0; i < INTERVALS; i++) {
+		int64_t value = data->intervals[i];
+		if (value <= thresh) {
+			avg += value;
+			divisor++;
+			if (value > max)
+				max = value;
+		}
+	}
+	do_div(avg, divisor);
 
+	for (i = 0; i < INTERVALS; i++) {
+		int64_t value = data->intervals[i];
+		if (value <= thresh) {
+			int64_t diff = value - avg;
+			stddev += diff * diff;
+		}
+	}
+	do_div(stddev, divisor);
+	stddev = int_sqrt(stddev);
 	/*
-	 * now.. if stddev is small.. then assume we have a
-	 * repeating pattern and predict we keep doing this.
+	 * If we have outliers to the upside in our distribution, discard
+	 * those by setting the threshold to exclude these outliers, then
+	 * calculate the average and standard deviation again. Once we get
+	 * down to the bottom 3/4 of our samples, stop excluding samples.
+	 *
+	 * This can deal with workloads that have long pauses interspersed
+	 * with sporadic activity with a bunch of short pauses.
+	 *
+	 * The typical interval is obtained when standard deviation is small
+	 * or standard deviation is small compared to the average interval.
 	 */
-
-	if (avg && stddev < STDDEV_THRESH)
+	if (((avg > stddev * 6) && (divisor * 4 >= INTERVALS * 3))
+							|| stddev <= 20) {
 		data->predicted_us = avg;
+		ret = 1;
+		return ret;
+
+	} else if ((divisor * 4) > INTERVALS * 3) {
+		/* Exclude the max interval */
+		thresh = max - 1;
+		goto again;
+	}
+
+	return ret;
 }
 
 /**
@@ -240,6 +316,9 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 	int i;
 	int multiplier;
 	struct timespec t;
+	int repeat = 0, low_predicted = 0;
+	int cpu = smp_processor_id();
+	struct hrtimer *hrtmr = &per_cpu(menu_hrtimer, cpu);
 
 	if (data->needs_update) {
 		menu_update(drv, dev);
@@ -274,7 +353,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 	data->predicted_us = div_round64(data->expected_us * data->correction_factor[data->bucket],
 					 RESOLUTION * DECAY);
 
-	detect_repeating_patterns(data);
+	repeat = get_typical_interval(data);
 
 	/*
 	 * We want to default to C1 (hlt), not to busy polling
@@ -295,8 +374,10 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 
 		if (s->disabled || su->disable)
 			continue;
-		if (s->target_residency > data->predicted_us)
+		if (s->target_residency > data->predicted_us) {
+			low_predicted = 1;
 			continue;
+		}
 		if (s->exit_latency > latency_req)
 			continue;
 		if (s->exit_latency * multiplier > data->predicted_us)
@@ -309,6 +390,44 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 		}
 	}
 
+	/* not deepest C-state chosen for low predicted residency */
+	if (low_predicted) {
+		unsigned int timer_us = 0;
+		unsigned int perfect_us = 0;
+
+		/*
+		 * Set a timer to detect whether this sleep is much
+		 * longer than repeat mode predicted.  If the timer
+		 * triggers, the code will evaluate whether to put
+		 * the CPU into a deeper C-state.
+		 * The timer is cancelled on CPU wakeup.
+		 */
+		timer_us = 2 * (data->predicted_us + MAX_DEVIATION);
+
+		perfect_us = perfect_cstate_ms * 1000;
+
+		if (repeat && (4 * timer_us < data->expected_us)) {
+			RCU_NONIDLE(hrtimer_start(hrtmr,
+				ns_to_ktime(1000 * timer_us),
+				HRTIMER_MODE_REL_PINNED));
+			/* In repeat case, menu hrtimer is started */
+			per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_REPEAT;
+		} else if (perfect_us < data->expected_us) {
+			/*
+			 * The next timer is long. This could be because
+			 * we did not make a useful prediction.
+			 * In that case, it makes sense to re-enter
+			 * into a deeper C-state after some time.
+			 */
+			RCU_NONIDLE(hrtimer_start(hrtmr,
+				ns_to_ktime(1000 * timer_us),
+				HRTIMER_MODE_REL_PINNED));
+			/* In general case, menu hrtimer is started */
+			per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_GENERAL;
+		}
+
+	}
+
 	return data->last_state_idx;
 }
 
@@ -399,6 +518,9 @@ static int menu_enable_device(struct cpuidle_driver *drv,
 				struct cpuidle_device *dev)
 {
 	struct menu_device *data = &per_cpu(menu_devices, dev->cpu);
+	struct hrtimer *t = &per_cpu(menu_hrtimer, dev->cpu);
+	hrtimer_init(t, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	t->function = menu_hrtimer_notify;
 
 	memset(data, 0, sizeof(struct menu_device));
 
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index 5f809e3..3409429 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/cpu.h>
 #include <linux/capability.h>
+#include <linux/device.h>
 
 #include "cpuidle.h"
 
@@ -297,6 +298,13 @@ static struct attribute *cpuidle_state_default_attrs[] = {
 	NULL
 };
 
+struct cpuidle_state_kobj {
+	struct cpuidle_state *state;
+	struct cpuidle_state_usage *state_usage;
+	struct completion kobj_unregister;
+	struct kobject kobj;
+};
+
 #define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
 #define kobj_to_state(k) (kobj_to_state_obj(k)->state)
 #define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
@@ -356,17 +364,17 @@ static inline void cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
 }
 
 /**
- * cpuidle_add_driver_sysfs - adds driver-specific sysfs attributes
+ * cpuidle_add_state_sysfs - adds cpuidle states sysfs attributes
  * @device: the target device
  */
-int cpuidle_add_state_sysfs(struct cpuidle_device *device)
+static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
 {
 	int i, ret = -ENOMEM;
 	struct cpuidle_state_kobj *kobj;
-	struct cpuidle_driver *drv = cpuidle_get_driver();
+	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
 
 	/* state statistics */
-	for (i = 0; i < device->state_count; i++) {
+	for (i = 0; i < drv->state_count; i++) {
 		kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
 		if (!kobj)
 			goto error_state;
@@ -374,8 +382,8 @@ int cpuidle_add_state_sysfs(struct cpuidle_device *device)
 		kobj->state_usage = &device->states_usage[i];
 		init_completion(&kobj->kobj_unregister);
 
-		ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, &device->kobj,
-					   "state%d", i);
+		ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle,
+					   &device->kobj, "state%d", i);
 		if (ret) {
 			kfree(kobj);
 			goto error_state;
@@ -393,10 +401,10 @@ error_state:
 }
 
 /**
- * cpuidle_remove_driver_sysfs - removes driver-specific sysfs attributes
+ * cpuidle_remove_driver_sysfs - removes the cpuidle states sysfs attributes
  * @device: the target device
  */
-void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
+static void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
 {
 	int i;
 
@@ -404,17 +412,179 @@ void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
 		cpuidle_free_state_kobj(device, i);
 }
 
+#ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS
+#define kobj_to_driver_kobj(k) container_of(k, struct cpuidle_driver_kobj, kobj)
+#define attr_to_driver_attr(a) container_of(a, struct cpuidle_driver_attr, attr)
+
+#define define_one_driver_ro(_name, show)                       \
+	static struct cpuidle_driver_attr attr_driver_##_name = \
+		__ATTR(_name, 0644, show, NULL)
+
+struct cpuidle_driver_kobj {
+	struct cpuidle_driver *drv;
+	struct completion kobj_unregister;
+	struct kobject kobj;
+};
+
+struct cpuidle_driver_attr {
+	struct attribute attr;
+	ssize_t (*show)(struct cpuidle_driver *, char *);
+	ssize_t (*store)(struct cpuidle_driver *, const char *, size_t);
+};
+
+static ssize_t show_driver_name(struct cpuidle_driver *drv, char *buf)
+{
+	ssize_t ret;
+
+	spin_lock(&cpuidle_driver_lock);
+	ret = sprintf(buf, "%s\n", drv ? drv->name : "none");
+	spin_unlock(&cpuidle_driver_lock);
+
+	return ret;
+}
+
+static void cpuidle_driver_sysfs_release(struct kobject *kobj)
+{
+	struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj);
+	complete(&driver_kobj->kobj_unregister);
+}
+
+static ssize_t cpuidle_driver_show(struct kobject *kobj, struct attribute * attr,
+				   char * buf)
+{
+	int ret = -EIO;
+	struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj);
+	struct cpuidle_driver_attr *dattr = attr_to_driver_attr(attr);
+
+	if (dattr->show)
+		ret = dattr->show(driver_kobj->drv, buf);
+
+	return ret;
+}
+
+static ssize_t cpuidle_driver_store(struct kobject *kobj, struct attribute *attr,
+				    const char *buf, size_t size)
+{
+	int ret = -EIO;
+	struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj);
+	struct cpuidle_driver_attr *dattr = attr_to_driver_attr(attr);
+
+	if (dattr->store)
+		ret = dattr->store(driver_kobj->drv, buf, size);
+
+	return ret;
+}
+
+define_one_driver_ro(name, show_driver_name);
+
+static const struct sysfs_ops cpuidle_driver_sysfs_ops = {
+	.show = cpuidle_driver_show,
+	.store = cpuidle_driver_store,
+};
+
+static struct attribute *cpuidle_driver_default_attrs[] = {
+	&attr_driver_name.attr,
+	NULL
+};
+
+static struct kobj_type ktype_driver_cpuidle = {
+	.sysfs_ops = &cpuidle_driver_sysfs_ops,
+	.default_attrs = cpuidle_driver_default_attrs,
+	.release = cpuidle_driver_sysfs_release,
+};
+
+/**
+ * cpuidle_add_driver_sysfs - adds the driver name sysfs attribute
+ * @device: the target device
+ */
+static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
+{
+	struct cpuidle_driver_kobj *kdrv;
+	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
+	int ret;
+
+	kdrv = kzalloc(sizeof(*kdrv), GFP_KERNEL);
+	if (!kdrv)
+		return -ENOMEM;
+
+	kdrv->drv = drv;
+	init_completion(&kdrv->kobj_unregister);
+
+	ret = kobject_init_and_add(&kdrv->kobj, &ktype_driver_cpuidle,
+				   &dev->kobj, "driver");
+	if (ret) {
+		kfree(kdrv);
+		return ret;
+	}
+
+	kobject_uevent(&kdrv->kobj, KOBJ_ADD);
+	dev->kobj_driver = kdrv;
+
+	return ret;
+}
+
+/**
+ * cpuidle_remove_driver_sysfs - removes the driver name sysfs attribute
+ * @device: the target device
+ */
+static void cpuidle_remove_driver_sysfs(struct cpuidle_device *dev)
+{
+	struct cpuidle_driver_kobj *kdrv = dev->kobj_driver;
+	kobject_put(&kdrv->kobj);
+	wait_for_completion(&kdrv->kobj_unregister);
+	kfree(kdrv);
+}
+#else
+static inline int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
+{
+	return 0;
+}
+
+static inline void cpuidle_remove_driver_sysfs(struct cpuidle_device *dev)
+{
+	;
+}
+#endif
+
+/**
+ * cpuidle_add_device_sysfs - adds device specific sysfs attributes
+ * @device: the target device
+ */
+int cpuidle_add_device_sysfs(struct cpuidle_device *device)
+{
+	int ret;
+
+	ret = cpuidle_add_state_sysfs(device);
+	if (ret)
+		return ret;
+
+	ret = cpuidle_add_driver_sysfs(device);
+	if (ret)
+		cpuidle_remove_state_sysfs(device);
+	return ret;
+}
+
+/**
+ * cpuidle_remove_device_sysfs : removes device specific sysfs attributes
+ * @device : the target device
+ */
+void cpuidle_remove_device_sysfs(struct cpuidle_device *device)
+{
+	cpuidle_remove_driver_sysfs(device);
+	cpuidle_remove_state_sysfs(device);
+}
+
 /**
  * cpuidle_add_sysfs - creates a sysfs instance for the target device
  * @dev: the target device
  */
-int cpuidle_add_sysfs(struct device *cpu_dev)
+int cpuidle_add_sysfs(struct cpuidle_device *dev)
 {
-	int cpu = cpu_dev->id;
-	struct cpuidle_device *dev;
+	struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
 	int error;
 
-	dev = per_cpu(cpuidle_devices, cpu);
+	init_completion(&dev->kobj_unregister);
+
 	error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
 				     "cpuidle");
 	if (!error)
@@ -426,11 +596,8 @@ int cpuidle_add_sysfs(struct device *cpu_dev)
  * cpuidle_remove_sysfs - deletes a sysfs instance on the target device
  * @dev: the target device
  */
-void cpuidle_remove_sysfs(struct device *cpu_dev)
+void cpuidle_remove_sysfs(struct cpuidle_device *dev)
 {
-	int cpu = cpu_dev->id;
-	struct cpuidle_device *dev;
-
-	dev = per_cpu(cpuidle_devices, cpu);
 	kobject_put(&dev->kobj);
+	wait_for_completion(&dev->kobj_unregister);
 }
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 308c7fb..87ec4d0 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -224,7 +224,7 @@ config CRYPTO_DEV_TALITOS
 
 config CRYPTO_DEV_IXP4XX
 	tristate "Driver for IXP4xx crypto hardware acceleration"
-	depends on ARCH_IXP4XX
+	depends on ARCH_IXP4XX && IXP4XX_QMGR && IXP4XX_NPE
 	select CRYPTO_DES
 	select CRYPTO_ALGAPI
 	select CRYPTO_AUTHENC
@@ -254,6 +254,7 @@ config CRYPTO_DEV_OMAP_AES
 	tristate "Support for OMAP AES hw engine"
 	depends on ARCH_OMAP2 || ARCH_OMAP3
 	select CRYPTO_AES
+	select CRYPTO_BLKCIPHER2
 	help
 	  OMAP processors have AES module accelerator. Select this if you
 	  want to use the OMAP module for AES algorithms.
diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c
index 8f3f74c..21180d6 100644
--- a/drivers/crypto/ixp4xx_crypto.c
+++ b/drivers/crypto/ixp4xx_crypto.c
@@ -750,12 +750,12 @@ static int setup_cipher(struct crypto_tfm *tfm, int encrypt,
 	}
 	if (cipher_cfg & MOD_AES) {
 		switch (key_len) {
-			case 16: keylen_cfg = MOD_AES128 | KEYLEN_128; break;
-			case 24: keylen_cfg = MOD_AES192 | KEYLEN_192; break;
-			case 32: keylen_cfg = MOD_AES256 | KEYLEN_256; break;
-			default:
-				*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
-				return -EINVAL;
+		case 16: keylen_cfg = MOD_AES128; break;
+		case 24: keylen_cfg = MOD_AES192; break;
+		case 32: keylen_cfg = MOD_AES256; break;
+		default:
+			*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+			return -EINVAL;
 		}
 		cipher_cfg |= keylen_cfg;
 	} else if (cipher_cfg & MOD_3DES) {
diff --git a/drivers/crypto/nx/nx-842.c b/drivers/crypto/nx/nx-842.c
index 0ce6257..6c4c000 100644
--- a/drivers/crypto/nx/nx-842.c
+++ b/drivers/crypto/nx/nx-842.c
@@ -28,7 +28,6 @@
 #include <linux/slab.h>
 
 #include <asm/page.h>
-#include <asm/pSeries_reconfig.h>
 #include <asm/vio.h>
 
 #include "nx_csbcpb.h" /* struct nx_csbcpb */
@@ -1014,26 +1013,23 @@ error_out:
  *	NOTIFY_BAD encoded with error number on failure, use
  *		notifier_to_errno() to decode this value
  */
-static int nx842_OF_notifier(struct notifier_block *np,
-					unsigned long action,
-					void *update)
+static int nx842_OF_notifier(struct notifier_block *np, unsigned long action,
+			     void *update)
 {
-	struct pSeries_reconfig_prop_update *upd;
+	struct of_prop_reconfig *upd = update;
 	struct nx842_devdata *local_devdata;
 	struct device_node *node = NULL;
 
-	upd = (struct pSeries_reconfig_prop_update *)update;
-
 	rcu_read_lock();
 	local_devdata = rcu_dereference(devdata);
 	if (local_devdata)
 		node = local_devdata->dev->of_node;
 
 	if (local_devdata &&
-			action == PSERIES_UPDATE_PROPERTY &&
-			!strcmp(upd->node->name, node->name)) {
+			action == OF_RECONFIG_UPDATE_PROPERTY &&
+			!strcmp(upd->dn->name, node->name)) {
 		rcu_read_unlock();
-		nx842_OF_upd(upd->property);
+		nx842_OF_upd(upd->prop);
 	} else
 		rcu_read_unlock();
 
@@ -1182,7 +1178,7 @@ static int __init nx842_probe(struct vio_dev *viodev,
 	synchronize_rcu();
 	kfree(old_devdata);
 
-	pSeries_reconfig_notifier_register(&nx842_of_nb);
+	of_reconfig_notifier_register(&nx842_of_nb);
 
 	ret = nx842_OF_upd(NULL);
 	if (ret && ret != -ENODEV) {
@@ -1228,7 +1224,7 @@ static int __exit nx842_remove(struct vio_dev *viodev)
 	spin_lock_irqsave(&devdata_mutex, flags);
 	old_devdata = rcu_dereference_check(devdata,
 			lockdep_is_held(&devdata_mutex));
-	pSeries_reconfig_notifier_unregister(&nx842_of_nb);
+	of_reconfig_notifier_unregister(&nx842_of_nb);
 	rcu_assign_pointer(devdata, NULL);
 	spin_unlock_irqrestore(&devdata_mutex, flags);
 	synchronize_rcu();
diff --git a/drivers/crypto/nx/nx.c b/drivers/crypto/nx/nx.c
index 638110e..f7a8a16 100644
--- a/drivers/crypto/nx/nx.c
+++ b/drivers/crypto/nx/nx.c
@@ -33,7 +33,6 @@
 #include <linux/scatterlist.h>
 #include <linux/device.h>
 #include <linux/of.h>
-#include <asm/pSeries_reconfig.h>
 #include <asm/hvcall.h>
 #include <asm/vio.h>
 
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 093a8af..649a146 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -29,8 +29,7 @@
 #include <crypto/scatterwalk.h>
 #include <crypto/aes.h>
 
-#include <plat/cpu.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 
 /* OMAP TRM gives bitfields as start:end, where start is the higher bit
    number. For example 7:0 */
@@ -941,11 +940,6 @@ static int __init omap_aes_mod_init(void)
 {
 	pr_info("loading %s driver\n", "omap-aes");
 
-	if (!cpu_class_is_omap2() || omap_type() != OMAP2_DEVICE_TYPE_SEC) {
-		pr_err("Unsupported cpu\n");
-		return -ENODEV;
-	}
-
 	return  platform_driver_register(&omap_aes_driver);
 }
 
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index a3fd6fc..d76fe06 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -37,8 +37,7 @@
 #include <crypto/hash.h>
 #include <crypto/internal/hash.h>
 
-#include <plat/cpu.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 #include <mach/irqs.h>
 
 #define SHA_REG_DIGEST(x)		(0x00 + ((x) * 0x04))
@@ -1289,13 +1288,6 @@ static int __init omap_sham_mod_init(void)
 {
 	pr_info("loading %s driver\n", "omap-sham");
 
-	if (!cpu_class_is_omap2() ||
-		(omap_type() != OMAP2_DEVICE_TYPE_SEC &&
-			omap_type() != OMAP2_DEVICE_TYPE_EMU)) {
-		pr_err("Unsupported cpu\n");
-		return -ENODEV;
-	}
-
 	return platform_driver_register(&omap_sham_driver);
 }
 
diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c
index 410a03c..c983f86 100644
--- a/drivers/crypto/picoxcell_crypto.c
+++ b/drivers/crypto/picoxcell_crypto.c
@@ -1863,6 +1863,7 @@ static int __devexit spacc_remove(struct platform_device *pdev)
 static const struct platform_device_id spacc_id_table[] = {
 	{ "picochip,spacc-ipsec", },
 	{ "picochip,spacc-l2", },
+	{ }
 };
 
 static struct platform_driver spacc_driver = {
diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c
index a227144..49ad8cb 100644
--- a/drivers/crypto/s5p-sss.c
+++ b/drivers/crypto/s5p-sss.c
@@ -30,7 +30,7 @@
 #include <crypto/ctr.h>
 
 #include <plat/cpu.h>
-#include <plat/dma.h>
+#include <mach/dma.h>
 
 #define _SBF(s, v)                      ((v) << (s))
 #define _BIT(b)                         _SBF(b, 1)
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index da11127..09b184a 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -936,8 +936,7 @@ static int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
 		sg_count--;
 		link_tbl_ptr--;
 	}
-	link_tbl_ptr->len = cpu_to_be16(be16_to_cpu(link_tbl_ptr->len)
-					+ cryptlen);
+	be16_add_cpu(&link_tbl_ptr->len, cryptlen);
 
 	/* tag end of link table */
 	link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
diff --git a/drivers/crypto/tegra-aes.c b/drivers/crypto/tegra-aes.c
index 37185e6..eb32fd8 100644
--- a/drivers/crypto/tegra-aes.c
+++ b/drivers/crypto/tegra-aes.c
@@ -41,8 +41,6 @@
 #include <linux/completion.h>
 #include <linux/workqueue.h>
 
-#include <mach/clk.h>
-
 #include <crypto/scatterwalk.h>
 #include <crypto/aes.h>
 #include <crypto/internal/rng.h>
@@ -674,8 +672,10 @@ static int tegra_aes_get_random(struct crypto_rng *tfm, u8 *rdata,
 	mutex_lock(&aes_lock);
 
 	ret = clk_prepare_enable(dd->aes_clk);
-	if (ret)
+	if (ret) {
+		mutex_unlock(&aes_lock);
 		return ret;
+	}
 
 	ctx->dd = dd;
 	dd->ctx = ctx;
@@ -759,8 +759,10 @@ static int tegra_aes_rng_reset(struct crypto_rng *tfm, u8 *seed,
 	dd->flags = FLAGS_ENCRYPT | FLAGS_RNG;
 
 	ret = clk_prepare_enable(dd->aes_clk);
-	if (ret)
+	if (ret) {
+		mutex_unlock(&aes_lock);
 		return ret;
+	}
 
 	aes_set_key(dd);
 
@@ -1031,7 +1033,7 @@ out:
 	if (dd->buf_out)
 		dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
 			dd->buf_out, dd->dma_buf_out);
-	if (IS_ERR(dd->aes_clk))
+	if (!IS_ERR(dd->aes_clk))
 		clk_put(dd->aes_clk);
 	if (aes_wq)
 		destroy_workqueue(aes_wq);
diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c
index bc615cc..8bc5fef 100644
--- a/drivers/crypto/ux500/cryp/cryp_core.c
+++ b/drivers/crypto/ux500/cryp/cryp_core.c
@@ -23,6 +23,7 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/semaphore.h>
+#include <linux/platform_data/dma-ste-dma40.h>
 
 #include <crypto/aes.h>
 #include <crypto/algapi.h>
@@ -30,8 +31,6 @@
 #include <crypto/des.h>
 #include <crypto/scatterwalk.h>
 
-#include <plat/ste_dma40.h>
-
 #include <linux/platform_data/crypto-ux500.h>
 #include <mach/hardware.h>
 
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index b146d76..4fa1a22 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -656,14 +656,14 @@ struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq,
 		opp = opp_find_freq_floor(dev, freq);
 
 		/* If not available, use the closest opp */
-		if (opp == ERR_PTR(-ENODEV))
+		if (opp == ERR_PTR(-ERANGE))
 			opp = opp_find_freq_ceil(dev, freq);
 	} else {
 		/* The freq is an lower bound. opp should be higher */
 		opp = opp_find_freq_ceil(dev, freq);
 
 		/* If not available, use the closest opp */
-		if (opp == ERR_PTR(-ENODEV))
+		if (opp == ERR_PTR(-ERANGE))
 			opp = opp_find_freq_floor(dev, freq);
 	}
 
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index d4c1218..6761cc8 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -51,7 +51,7 @@ config ASYNC_TX_ENABLE_CHANNEL_SWITCH
 
 config AMBA_PL08X
 	bool "ARM PrimeCell PL080 or PL081 support"
-	depends on ARM_AMBA && EXPERIMENTAL
+	depends on ARM_AMBA
 	select DMA_ENGINE
 	select DMA_VIRTUAL_CHANNELS
 	help
@@ -83,7 +83,6 @@ config INTEL_IOP_ADMA
 
 config DW_DMAC
 	tristate "Synopsys DesignWare AHB DMA support"
-	depends on HAVE_CLK
 	select DMA_ENGINE
 	default y if CPU_AT32AP7000
 	help
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index d1cc579..6eb6a5c 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -1096,15 +1096,9 @@ static void pl08x_free_txd_list(struct pl08x_driver_data *pl08x,
 				struct pl08x_dma_chan *plchan)
 {
 	LIST_HEAD(head);
-	struct pl08x_txd *txd;
 
 	vchan_get_all_descriptors(&plchan->vc, &head);
-
-	while (!list_empty(&head)) {
-		txd = list_first_entry(&head, struct pl08x_txd, vd.node);
-		list_del(&txd->vd.node);
-		pl08x_desc_free(&txd->vd);
-	}
+	vchan_dma_desc_free_list(&plchan->vc, &head);
 }
 
 /*
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
index 116e4ad..0eb3c13 100644
--- a/drivers/dma/at_hdmac_regs.h
+++ b/drivers/dma/at_hdmac_regs.h
@@ -369,10 +369,10 @@ static void vdbg_dump_regs(struct at_dma_chan *atchan) {}
 
 static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli)
 {
-	dev_printk(KERN_CRIT, chan2dev(&atchan->chan_common),
-			"  desc: s0x%x d0x%x ctrl0x%x:0x%x l0x%x\n",
-			lli->saddr, lli->daddr,
-			lli->ctrla, lli->ctrlb, lli->dscr);
+	dev_crit(chan2dev(&atchan->chan_common),
+		 "  desc: s0x%x d0x%x ctrl0x%x:0x%x l0x%x\n",
+		 lli->saddr, lli->daddr,
+		 lli->ctrla, lli->ctrlb, lli->dscr);
 }
 
 
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index a815d44..d37cf95 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -62,6 +62,7 @@
 #include <linux/rculist.h>
 #include <linux/idr.h>
 #include <linux/slab.h>
+#include <linux/of_dma.h>
 
 static DEFINE_MUTEX(dma_list_mutex);
 static DEFINE_IDR(dma_idr);
@@ -546,6 +547,21 @@ struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, v
 }
 EXPORT_SYMBOL_GPL(__dma_request_channel);
 
+/**
+ * dma_request_slave_channel - try to allocate an exclusive slave channel
+ * @dev:	pointer to client device structure
+ * @name:	slave channel name
+ */
+struct dma_chan *dma_request_slave_channel(struct device *dev, char *name)
+{
+	/* If device-tree is present get slave info from here */
+	if (dev->of_node)
+		return of_dma_request_slave_channel(dev->of_node, name);
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(dma_request_slave_channel);
+
 void dma_release_channel(struct dma_chan *chan)
 {
 	mutex_lock(&dma_list_mutex);
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 24225f0..8f130d4e 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -228,6 +228,13 @@ static void dmatest_callback(void *arg)
 	wake_up_all(done->wait);
 }
 
+static unsigned int min_odd(unsigned int x, unsigned int y)
+{
+	unsigned int val = min(x, y);
+
+	return val % 2 ? val : val - 1;
+}
+
 /*
  * This function repeatedly tests DMA transfers of various lengths and
  * offsets for a given operation type until it is told to exit by
@@ -248,6 +255,7 @@ static int dmatest_func(void *data)
 	struct dmatest_thread	*thread = data;
 	struct dmatest_done	done = { .wait = &done_wait };
 	struct dma_chan		*chan;
+	struct dma_device	*dev;
 	const char		*thread_name;
 	unsigned int		src_off, dst_off, len;
 	unsigned int		error_count;
@@ -269,13 +277,16 @@ static int dmatest_func(void *data)
 
 	smp_rmb();
 	chan = thread->chan;
+	dev = chan->device;
 	if (thread->type == DMA_MEMCPY)
 		src_cnt = dst_cnt = 1;
 	else if (thread->type == DMA_XOR) {
-		src_cnt = xor_sources | 1; /* force odd to ensure dst = src */
+		/* force odd to ensure dst = src */
+		src_cnt = min_odd(xor_sources | 1, dev->max_xor);
 		dst_cnt = 1;
 	} else if (thread->type == DMA_PQ) {
-		src_cnt = pq_sources | 1; /* force odd to ensure dst = src */
+		/* force odd to ensure dst = src */
+		src_cnt = min_odd(pq_sources | 1, dma_maxpq(dev, 0));
 		dst_cnt = 2;
 		for (i = 0; i < src_cnt; i++)
 			pq_coefs[i] = 1;
@@ -313,7 +324,6 @@ static int dmatest_func(void *data)
 
 	while (!kthread_should_stop()
 	       && !(iterations && total_tests >= iterations)) {
-		struct dma_device *dev = chan->device;
 		struct dma_async_tx_descriptor *tx = NULL;
 		dma_addr_t dma_srcs[src_cnt];
 		dma_addr_t dma_dsts[dst_cnt];
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index c4b0eb3..0c2513a 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -1,6 +1,5 @@
 /*
- * Driver for the Synopsys DesignWare DMA Controller (aka DMACA on
- * AVR32 systems.)
+ * Core driver for the Synopsys DesignWare DMA Controller
  *
  * Copyright (C) 2007-2008 Atmel Corporation
  * Copyright (C) 2010-2011 ST Microelectronics
@@ -9,6 +8,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
 #include <linux/bitops.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
@@ -93,7 +93,7 @@ static struct device *chan2parent(struct dma_chan *chan)
 
 static struct dw_desc *dwc_first_active(struct dw_dma_chan *dwc)
 {
-	return list_entry(dwc->active_list.next, struct dw_desc, desc_node);
+	return to_dw_desc(dwc->active_list.next);
 }
 
 static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc)
@@ -222,7 +222,6 @@ static inline void dwc_dump_chan_regs(struct dw_dma_chan *dwc)
 		channel_readl(dwc, CTL_LO));
 }
 
-
 static inline void dwc_chan_disable(struct dw_dma *dw, struct dw_dma_chan *dwc)
 {
 	channel_clear_bit(dw, CH_EN, dwc->mask);
@@ -457,9 +456,8 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
 
 static inline void dwc_dump_lli(struct dw_dma_chan *dwc, struct dw_lli *lli)
 {
-	dev_printk(KERN_CRIT, chan2dev(&dwc->chan),
-			"  desc: s0x%x d0x%x l0x%x c0x%x:%x\n",
-			lli->sar, lli->dar, lli->llp, lli->ctlhi, lli->ctllo);
+	dev_crit(chan2dev(&dwc->chan), "  desc: s0x%x d0x%x l0x%x c0x%x:%x\n",
+		 lli->sar, lli->dar, lli->llp, lli->ctlhi, lli->ctllo);
 }
 
 static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc)
@@ -487,16 +485,14 @@ static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc)
 		dwc_dostart(dwc, dwc_first_active(dwc));
 
 	/*
-	 * KERN_CRITICAL may seem harsh, but since this only happens
+	 * WARN may seem harsh, but since this only happens
 	 * when someone submits a bad physical address in a
 	 * descriptor, we should consider ourselves lucky that the
 	 * controller flagged an error instead of scribbling over
 	 * random memory locations.
 	 */
-	dev_printk(KERN_CRIT, chan2dev(&dwc->chan),
-			"Bad descriptor submitted for DMA!\n");
-	dev_printk(KERN_CRIT, chan2dev(&dwc->chan),
-			"  cookie: %d\n", bad_desc->txd.cookie);
+	dev_WARN(chan2dev(&dwc->chan), "Bad descriptor submitted for DMA!\n"
+				       "  cookie: %d\n", bad_desc->txd.cookie);
 	dwc_dump_lli(dwc, &bad_desc->lli);
 	list_for_each_entry(child, &bad_desc->tx_list, desc_node)
 		dwc_dump_lli(dwc, &child->lli);
@@ -604,9 +600,7 @@ static void dw_dma_tasklet(unsigned long data)
 			if (test_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags)) {
 				if (dwc->tx_node_active != dwc->tx_list) {
 					struct dw_desc *desc =
-						list_entry(dwc->tx_node_active,
-							   struct dw_desc,
-							   desc_node);
+						to_dw_desc(dwc->tx_node_active);
 
 					dma_writel(dw, CLEAR.XFER, dwc->mask);
 
@@ -1179,6 +1173,50 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
 	dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
 }
 
+bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
+{
+	struct dw_dma *dw = to_dw_dma(chan->device);
+	static struct dw_dma *last_dw;
+	static char *last_bus_id;
+	int i = -1;
+
+	/*
+	 * dmaengine framework calls this routine for all channels of all dma
+	 * controller, until true is returned. If 'param' bus_id is not
+	 * registered with a dma controller (dw), then there is no need of
+	 * running below function for all channels of dw.
+	 *
+	 * This block of code does this by saving the parameters of last
+	 * failure. If dw and param are same, i.e. trying on same dw with
+	 * different channel, return false.
+	 */
+	if ((last_dw == dw) && (last_bus_id == param))
+		return false;
+	/*
+	 * Return true:
+	 * - If dw_dma's platform data is not filled with slave info, then all
+	 *   dma controllers are fine for transfer.
+	 * - Or if param is NULL
+	 */
+	if (!dw->sd || !param)
+		return true;
+
+	while (++i < dw->sd_count) {
+		if (!strcmp(dw->sd[i].bus_id, param)) {
+			chan->private = &dw->sd[i];
+			last_dw = NULL;
+			last_bus_id = NULL;
+
+			return true;
+		}
+	}
+
+	last_dw = dw;
+	last_bus_id = param;
+	return false;
+}
+EXPORT_SYMBOL(dw_dma_generic_filter);
+
 /* --------------------- Cyclic DMA API extensions -------------------- */
 
 /**
@@ -1462,7 +1500,92 @@ static void dw_dma_off(struct dw_dma *dw)
 		dw->chan[i].initialized = false;
 }
 
-static int __devinit dw_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static struct dw_dma_platform_data *
+__devinit dw_dma_parse_dt(struct platform_device *pdev)
+{
+	struct device_node *sn, *cn, *np = pdev->dev.of_node;
+	struct dw_dma_platform_data *pdata;
+	struct dw_dma_slave *sd;
+	u32 tmp, arr[4];
+
+	if (!np) {
+		dev_err(&pdev->dev, "Missing DT data\n");
+		return NULL;
+	}
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return NULL;
+
+	if (of_property_read_u32(np, "nr_channels", &pdata->nr_channels))
+		return NULL;
+
+	if (of_property_read_bool(np, "is_private"))
+		pdata->is_private = true;
+
+	if (!of_property_read_u32(np, "chan_allocation_order", &tmp))
+		pdata->chan_allocation_order = (unsigned char)tmp;
+
+	if (!of_property_read_u32(np, "chan_priority", &tmp))
+		pdata->chan_priority = tmp;
+
+	if (!of_property_read_u32(np, "block_size", &tmp))
+		pdata->block_size = tmp;
+
+	if (!of_property_read_u32(np, "nr_masters", &tmp)) {
+		if (tmp > 4)
+			return NULL;
+
+		pdata->nr_masters = tmp;
+	}
+
+	if (!of_property_read_u32_array(np, "data_width", arr,
+				pdata->nr_masters))
+		for (tmp = 0; tmp < pdata->nr_masters; tmp++)
+			pdata->data_width[tmp] = arr[tmp];
+
+	/* parse slave data */
+	sn = of_find_node_by_name(np, "slave_info");
+	if (!sn)
+		return pdata;
+
+	/* calculate number of slaves */
+	tmp = of_get_child_count(sn);
+	if (!tmp)
+		return NULL;
+
+	sd = devm_kzalloc(&pdev->dev, sizeof(*sd) * tmp, GFP_KERNEL);
+	if (!sd)
+		return NULL;
+
+	pdata->sd = sd;
+	pdata->sd_count = tmp;
+
+	for_each_child_of_node(sn, cn) {
+		sd->dma_dev = &pdev->dev;
+		of_property_read_string(cn, "bus_id", &sd->bus_id);
+		of_property_read_u32(cn, "cfg_hi", &sd->cfg_hi);
+		of_property_read_u32(cn, "cfg_lo", &sd->cfg_lo);
+		if (!of_property_read_u32(cn, "src_master", &tmp))
+			sd->src_master = tmp;
+
+		if (!of_property_read_u32(cn, "dst_master", &tmp))
+			sd->dst_master = tmp;
+		sd++;
+	}
+
+	return pdata;
+}
+#else
+static inline struct dw_dma_platform_data *
+dw_dma_parse_dt(struct platform_device *pdev)
+{
+	return NULL;
+}
+#endif
+
+static int dw_probe(struct platform_device *pdev)
 {
 	struct dw_dma_platform_data *pdata;
 	struct resource		*io;
@@ -1478,6 +1601,9 @@ static int __devinit dw_probe(struct platform_device *pdev)
 	int			i;
 
 	pdata = dev_get_platdata(&pdev->dev);
+	if (!pdata)
+		pdata = dw_dma_parse_dt(pdev);
+
 	if (!pdata || pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS)
 		return -EINVAL;
 
@@ -1512,6 +1638,8 @@ static int __devinit dw_probe(struct platform_device *pdev)
 	clk_prepare_enable(dw->clk);
 
 	dw->regs = regs;
+	dw->sd = pdata->sd;
+	dw->sd_count = pdata->sd_count;
 
 	/* get hardware configuration parameters */
 	if (autocfg) {
@@ -1626,8 +1754,8 @@ static int __devinit dw_probe(struct platform_device *pdev)
 
 	dma_writel(dw, CFG, DW_CFG_DMA_EN);
 
-	printk(KERN_INFO "%s: DesignWare DMA Controller, %d channels\n",
-			dev_name(&pdev->dev), nr_channels);
+	dev_info(&pdev->dev, "DesignWare DMA Controller, %d channels\n",
+		 nr_channels);
 
 	dma_async_device_register(&dw->dma);
 
@@ -1657,7 +1785,7 @@ static void dw_shutdown(struct platform_device *pdev)
 {
 	struct dw_dma	*dw = platform_get_drvdata(pdev);
 
-	dw_dma_off(platform_get_drvdata(pdev));
+	dw_dma_off(dw);
 	clk_disable_unprepare(dw->clk);
 }
 
@@ -1666,7 +1794,7 @@ static int dw_suspend_noirq(struct device *dev)
 	struct platform_device *pdev = to_platform_device(dev);
 	struct dw_dma	*dw = platform_get_drvdata(pdev);
 
-	dw_dma_off(platform_get_drvdata(pdev));
+	dw_dma_off(dw);
 	clk_disable_unprepare(dw->clk);
 
 	return 0;
@@ -1679,6 +1807,7 @@ static int dw_resume_noirq(struct device *dev)
 
 	clk_prepare_enable(dw->clk);
 	dma_writel(dw, CFG, DW_CFG_DMA_EN);
+
 	return 0;
 }
 
@@ -1700,7 +1829,7 @@ MODULE_DEVICE_TABLE(of, dw_dma_id_table);
 #endif
 
 static struct platform_driver dw_driver = {
-	.remove		= __devexit_p(dw_remove),
+	.remove		= dw_remove,
 	.shutdown	= dw_shutdown,
 	.driver = {
 		.name	= "dw_dmac",
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 8896559..8881e9b 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -239,6 +239,10 @@ struct dw_dma {
 	struct tasklet_struct	tasklet;
 	struct clk		*clk;
 
+	/* slave information */
+	struct dw_dma_slave	*sd;
+	unsigned int		sd_count;
+
 	u8			all_chan_mask;
 
 	/* hardware configuration */
@@ -295,6 +299,8 @@ struct dw_desc {
 	size_t				len;
 };
 
+#define to_dw_desc(h)	list_entry(h, struct dw_desc, desc_node)
+
 static inline struct dw_desc *
 txd_to_dw_desc(struct dma_async_tx_descriptor *txd)
 {
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index 05aea3c..232b458 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -545,7 +545,7 @@ static void edma_dma_init(struct edma_cc *ecc, struct dma_device *dma,
 	INIT_LIST_HEAD(&dma->channels);
 }
 
-static int __devinit edma_probe(struct platform_device *pdev)
+static int edma_probe(struct platform_device *pdev)
 {
 	struct edma_cc *ecc;
 	int ret;
@@ -598,7 +598,7 @@ static int __devexit edma_remove(struct platform_device *pdev)
 
 static struct platform_driver edma_driver = {
 	.probe		= edma_probe,
-	.remove		= __devexit_p(edma_remove),
+	.remove		= edma_remove,
 	.driver = {
 		.name = "edma-dma-engine",
 		.owner = THIS_MODULE,
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 094437b..4fc2980 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -1221,7 +1221,7 @@ out_unwind:
 /* OpenFirmware Subsystem                                                     */
 /*----------------------------------------------------------------------------*/
 
-static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
+static int fsl_dma_chan_probe(struct fsldma_device *fdev,
 	struct device_node *node, u32 feature, const char *compatible)
 {
 	struct fsldma_chan *chan;
@@ -1324,7 +1324,7 @@ static void fsl_dma_chan_remove(struct fsldma_chan *chan)
 	kfree(chan);
 }
 
-static int __devinit fsldma_of_probe(struct platform_device *op)
+static int fsldma_of_probe(struct platform_device *op)
 {
 	struct fsldma_device *fdev;
 	struct device_node *child;
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index 7d9554c..dbf0e6f 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -29,7 +29,6 @@
 
 #include <asm/irq.h>
 #include <linux/platform_data/dma-imx.h>
-#include <mach/hardware.h>
 
 #include "dmaengine.h"
 #define IMXDMA_MAX_CHAN_DESCRIPTORS	16
@@ -167,6 +166,12 @@ struct imxdma_channel {
 	int				slot_2d;
 };
 
+enum imx_dma_type {
+	IMX1_DMA,
+	IMX21_DMA,
+	IMX27_DMA,
+};
+
 struct imxdma_engine {
 	struct device			*dev;
 	struct device_dma_parameters	dma_parms;
@@ -177,7 +182,39 @@ struct imxdma_engine {
 	spinlock_t			lock;
 	struct imx_dma_2d_config	slots_2d[IMX_DMA_2D_SLOTS];
 	struct imxdma_channel		channel[IMX_DMA_CHANNELS];
+	enum imx_dma_type		devtype;
+};
+
+static struct platform_device_id imx_dma_devtype[] = {
+	{
+		.name = "imx1-dma",
+		.driver_data = IMX1_DMA,
+	}, {
+		.name = "imx21-dma",
+		.driver_data = IMX21_DMA,
+	}, {
+		.name = "imx27-dma",
+		.driver_data = IMX27_DMA,
+	}, {
+		/* sentinel */
+	}
 };
+MODULE_DEVICE_TABLE(platform, imx_dma_devtype);
+
+static inline int is_imx1_dma(struct imxdma_engine *imxdma)
+{
+	return imxdma->devtype == IMX1_DMA;
+}
+
+static inline int is_imx21_dma(struct imxdma_engine *imxdma)
+{
+	return imxdma->devtype == IMX21_DMA;
+}
+
+static inline int is_imx27_dma(struct imxdma_engine *imxdma)
+{
+	return imxdma->devtype == IMX27_DMA;
+}
 
 static struct imxdma_channel *to_imxdma_chan(struct dma_chan *chan)
 {
@@ -212,7 +249,9 @@ static unsigned imx_dmav1_readl(struct imxdma_engine *imxdma, unsigned offset)
 
 static int imxdma_hw_chain(struct imxdma_channel *imxdmac)
 {
-	if (cpu_is_mx27())
+	struct imxdma_engine *imxdma = imxdmac->imxdma;
+
+	if (is_imx27_dma(imxdma))
 		return imxdmac->hw_chaining;
 	else
 		return 0;
@@ -267,7 +306,7 @@ static void imxdma_enable_hw(struct imxdma_desc *d)
 	imx_dmav1_writel(imxdma, imx_dmav1_readl(imxdma, DMA_CCR(channel)) |
 			 CCR_CEN | CCR_ACRPT, DMA_CCR(channel));
 
-	if ((cpu_is_mx21() || cpu_is_mx27()) &&
+	if (!is_imx1_dma(imxdma) &&
 			d->sg && imxdma_hw_chain(imxdmac)) {
 		d->sg = sg_next(d->sg);
 		if (d->sg) {
@@ -436,7 +475,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 	struct imxdma_engine *imxdma = dev_id;
 	int i, disr;
 
-	if (cpu_is_mx21() || cpu_is_mx27())
+	if (!is_imx1_dma(imxdma))
 		imxdma_err_handler(irq, dev_id);
 
 	disr = imx_dmav1_readl(imxdma, DMA_DISR);
@@ -961,35 +1000,32 @@ static void imxdma_issue_pending(struct dma_chan *chan)
 static int __init imxdma_probe(struct platform_device *pdev)
 	{
 	struct imxdma_engine *imxdma;
+	struct resource *res;
 	int ret, i;
+	int irq, irq_err;
 
-
-	imxdma = kzalloc(sizeof(*imxdma), GFP_KERNEL);
+	imxdma = devm_kzalloc(&pdev->dev, sizeof(*imxdma), GFP_KERNEL);
 	if (!imxdma)
 		return -ENOMEM;
 
-	if (cpu_is_mx1()) {
-		imxdma->base = MX1_IO_ADDRESS(MX1_DMA_BASE_ADDR);
-	} else if (cpu_is_mx21()) {
-		imxdma->base = MX21_IO_ADDRESS(MX21_DMA_BASE_ADDR);
-	} else if (cpu_is_mx27()) {
-		imxdma->base = MX27_IO_ADDRESS(MX27_DMA_BASE_ADDR);
-	} else {
-		kfree(imxdma);
-		return 0;
-	}
+	imxdma->devtype = pdev->id_entry->driver_data;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	imxdma->base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!imxdma->base)
+		return -EADDRNOTAVAIL;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
 
 	imxdma->dma_ipg = devm_clk_get(&pdev->dev, "ipg");
-	if (IS_ERR(imxdma->dma_ipg)) {
-		ret = PTR_ERR(imxdma->dma_ipg);
-		goto err_clk;
-	}
+	if (IS_ERR(imxdma->dma_ipg))
+		return PTR_ERR(imxdma->dma_ipg);
 
 	imxdma->dma_ahb = devm_clk_get(&pdev->dev, "ahb");
-	if (IS_ERR(imxdma->dma_ahb)) {
-		ret = PTR_ERR(imxdma->dma_ahb);
-		goto err_clk;
-	}
+	if (IS_ERR(imxdma->dma_ahb))
+		return PTR_ERR(imxdma->dma_ahb);
 
 	clk_prepare_enable(imxdma->dma_ipg);
 	clk_prepare_enable(imxdma->dma_ahb);
@@ -997,18 +1033,25 @@ static int __init imxdma_probe(struct platform_device *pdev)
 	/* reset DMA module */
 	imx_dmav1_writel(imxdma, DCR_DRST, DMA_DCR);
 
-	if (cpu_is_mx1()) {
-		ret = request_irq(MX1_DMA_INT, dma_irq_handler, 0, "DMA", imxdma);
+	if (is_imx1_dma(imxdma)) {
+		ret = devm_request_irq(&pdev->dev, irq,
+				       dma_irq_handler, 0, "DMA", imxdma);
 		if (ret) {
 			dev_warn(imxdma->dev, "Can't register IRQ for DMA\n");
-			goto err_enable;
+			goto err;
+		}
+
+		irq_err = platform_get_irq(pdev, 1);
+		if (irq_err < 0) {
+			ret = irq_err;
+			goto err;
 		}
 
-		ret = request_irq(MX1_DMA_ERR, imxdma_err_handler, 0, "DMA", imxdma);
+		ret = devm_request_irq(&pdev->dev, irq_err,
+				       imxdma_err_handler, 0, "DMA", imxdma);
 		if (ret) {
 			dev_warn(imxdma->dev, "Can't register ERRIRQ for DMA\n");
-			free_irq(MX1_DMA_INT, NULL);
-			goto err_enable;
+			goto err;
 		}
 	}
 
@@ -1038,14 +1081,14 @@ static int __init imxdma_probe(struct platform_device *pdev)
 	for (i = 0; i < IMX_DMA_CHANNELS; i++) {
 		struct imxdma_channel *imxdmac = &imxdma->channel[i];
 
-		if (cpu_is_mx21() || cpu_is_mx27()) {
-			ret = request_irq(MX2x_INT_DMACH0 + i,
+		if (!is_imx1_dma(imxdma)) {
+			ret = devm_request_irq(&pdev->dev, irq + i,
 					dma_irq_handler, 0, "DMA", imxdma);
 			if (ret) {
 				dev_warn(imxdma->dev, "Can't register IRQ %d "
 					 "for DMA channel %d\n",
-					 MX2x_INT_DMACH0 + i, i);
-				goto err_init;
+					 irq + i, i);
+				goto err;
 			}
 			init_timer(&imxdmac->watchdog);
 			imxdmac->watchdog.function = &imxdma_watchdog;
@@ -1091,46 +1134,25 @@ static int __init imxdma_probe(struct platform_device *pdev)
 	ret = dma_async_device_register(&imxdma->dma_device);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to register\n");
-		goto err_init;
+		goto err;
 	}
 
 	return 0;
 
-err_init:
-
-	if (cpu_is_mx21() || cpu_is_mx27()) {
-		while (--i >= 0)
-			free_irq(MX2x_INT_DMACH0 + i, NULL);
-	} else if cpu_is_mx1() {
-		free_irq(MX1_DMA_INT, NULL);
-		free_irq(MX1_DMA_ERR, NULL);
-	}
-err_enable:
+err:
 	clk_disable_unprepare(imxdma->dma_ipg);
 	clk_disable_unprepare(imxdma->dma_ahb);
-err_clk:
-	kfree(imxdma);
 	return ret;
 }
 
 static int __exit imxdma_remove(struct platform_device *pdev)
 {
 	struct imxdma_engine *imxdma = platform_get_drvdata(pdev);
-	int i;
 
         dma_async_device_unregister(&imxdma->dma_device);
 
-	if (cpu_is_mx21() || cpu_is_mx27()) {
-		for (i = 0; i < IMX_DMA_CHANNELS; i++)
-			free_irq(MX2x_INT_DMACH0 + i, NULL);
-	} else if cpu_is_mx1() {
-		free_irq(MX1_DMA_INT, NULL);
-		free_irq(MX1_DMA_ERR, NULL);
-	}
-
 	clk_disable_unprepare(imxdma->dma_ipg);
 	clk_disable_unprepare(imxdma->dma_ahb);
-	kfree(imxdma);
 
         return 0;
 }
@@ -1139,6 +1161,7 @@ static struct platform_driver imxdma_driver = {
 	.driver		= {
 		.name	= "imx-dma",
 	},
+	.id_table	= imx_dma_devtype,
 	.remove		= __exit_p(imxdma_remove),
 };
 
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index c099ca0..f082aa3 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -40,7 +40,6 @@
 #include <asm/irq.h>
 #include <linux/platform_data/dma-imx-sdma.h>
 #include <linux/platform_data/dma-imx.h>
-#include <mach/hardware.h>
 
 #include "dmaengine.h"
 
diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c
index 02b21d7..bc764af 100644
--- a/drivers/dma/intel_mid_dma.c
+++ b/drivers/dma/intel_mid_dma.c
@@ -1225,7 +1225,7 @@ static void middma_shutdown(struct pci_dev *pdev)
  * Initialize the PCI device, map BARs, query driver data.
  * Call setup_dma to complete contoller and chan initilzation
  */
-static int __devinit intel_mid_dma_probe(struct pci_dev *pdev,
+static int intel_mid_dma_probe(struct pci_dev *pdev,
 					const struct pci_device_id *id)
 {
 	struct middma_device *device;
@@ -1432,7 +1432,7 @@ static struct pci_driver intel_mid_dma_pci_driver = {
 	.name		=	"Intel MID DMA",
 	.id_table	=	intel_mid_dma_ids,
 	.probe		=	intel_mid_dma_probe,
-	.remove		=	__devexit_p(intel_mid_dma_remove),
+	.remove		=	intel_mid_dma_remove,
 #ifdef CONFIG_PM
 	.driver = {
 		.pm = &intel_mid_dma_pm,
diff --git a/drivers/dma/ioat/dca.c b/drivers/dma/ioat/dca.c
index abd9038..d666807 100644
--- a/drivers/dma/ioat/dca.c
+++ b/drivers/dma/ioat/dca.c
@@ -604,6 +604,23 @@ static int ioat3_dca_count_dca_slots(void *iobase, u16 dca_offset)
 	return slots;
 }
 
+static inline int dca3_tag_map_invalid(u8 *tag_map)
+{
+	/*
+	 * If the tag map is not programmed by the BIOS the default is:
+	 * 0x80 0x80 0x80 0x80 0x80 0x00 0x00 0x00
+	 *
+	 * This an invalid map and will result in only 2 possible tags
+	 * 0x1F and 0x00.  0x00 is an invalid DCA tag so we know that
+	 * this entire definition is invalid.
+	 */
+	return ((tag_map[0] == DCA_TAG_MAP_VALID) &&
+		(tag_map[1] == DCA_TAG_MAP_VALID) &&
+		(tag_map[2] == DCA_TAG_MAP_VALID) &&
+		(tag_map[3] == DCA_TAG_MAP_VALID) &&
+		(tag_map[4] == DCA_TAG_MAP_VALID));
+}
+
 struct dca_provider * __devinit
 ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase)
 {
@@ -674,6 +691,12 @@ ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase)
 		ioatdca->tag_map[i] = bit & DCA_TAG_MAP_MASK;
 	}
 
+	if (dca3_tag_map_invalid(ioatdca->tag_map)) {
+		dev_err(&pdev->dev, "APICID_TAG_MAP set incorrectly by BIOS, disabling DCA\n");
+		free_dca_provider(dca);
+		return NULL;
+	}
+
 	err = register_dca_provider(dca, &pdev->dev);
 	if (err) {
 		free_dca_provider(dca);
diff --git a/drivers/dma/ioat/pci.c b/drivers/dma/ioat/pci.c
index c057306..bfa9a35 100644
--- a/drivers/dma/ioat/pci.c
+++ b/drivers/dma/ioat/pci.c
@@ -125,7 +125,7 @@ static struct pci_driver ioat_pci_driver = {
 	.name		= DRV_NAME,
 	.id_table	= ioat_pci_tbl,
 	.probe		= ioat_pci_probe,
-	.remove		= __devexit_p(ioat_remove),
+	.remove		= ioat_remove,
 };
 
 static struct ioatdma_device *
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 79e3eba..62a59fd 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -936,7 +936,7 @@ static irqreturn_t iop_adma_err_handler(int irq, void *data)
 	struct iop_adma_chan *chan = data;
 	unsigned long status = iop_chan_get_status(chan);
 
-	dev_printk(KERN_ERR, chan->device->common.dev,
+	dev_err(chan->device->common.dev,
 		"error ( %s%s%s%s%s%s%s)\n",
 		iop_is_err_int_parity(status, chan) ? "int_parity " : "",
 		iop_is_err_mcu_abort(status, chan) ? "mcu_abort " : "",
@@ -968,7 +968,7 @@ static void iop_adma_issue_pending(struct dma_chan *chan)
  */
 #define IOP_ADMA_TEST_SIZE 2000
 
-static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
+static int iop_adma_memcpy_self_test(struct iop_adma_device *device)
 {
 	int i;
 	void *src, *dest;
@@ -1017,7 +1017,7 @@ static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
 
 	if (iop_adma_status(dma_chan, cookie, NULL) !=
 			DMA_SUCCESS) {
-		dev_printk(KERN_ERR, dma_chan->device->dev,
+		dev_err(dma_chan->device->dev,
 			"Self-test copy timed out, disabling\n");
 		err = -ENODEV;
 		goto free_resources;
@@ -1027,7 +1027,7 @@ static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
 	dma_sync_single_for_cpu(&iop_chan->device->pdev->dev, dest_dma,
 		IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE);
 	if (memcmp(src, dest, IOP_ADMA_TEST_SIZE)) {
-		dev_printk(KERN_ERR, dma_chan->device->dev,
+		dev_err(dma_chan->device->dev,
 			"Self-test copy failed compare, disabling\n");
 		err = -ENODEV;
 		goto free_resources;
@@ -1042,7 +1042,7 @@ out:
 }
 
 #define IOP_ADMA_NUM_SRC_TEST 4 /* must be <= 15 */
-static int __devinit
+static int
 iop_adma_xor_val_self_test(struct iop_adma_device *device)
 {
 	int i, src_idx;
@@ -1117,7 +1117,7 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device)
 
 	if (iop_adma_status(dma_chan, cookie, NULL) !=
 		DMA_SUCCESS) {
-		dev_printk(KERN_ERR, dma_chan->device->dev,
+		dev_err(dma_chan->device->dev,
 			"Self-test xor timed out, disabling\n");
 		err = -ENODEV;
 		goto free_resources;
@@ -1129,7 +1129,7 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device)
 	for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) {
 		u32 *ptr = page_address(dest);
 		if (ptr[i] != cmp_word) {
-			dev_printk(KERN_ERR, dma_chan->device->dev,
+			dev_err(dma_chan->device->dev,
 				"Self-test xor failed compare, disabling\n");
 			err = -ENODEV;
 			goto free_resources;
@@ -1163,14 +1163,14 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device)
 	msleep(8);
 
 	if (iop_adma_status(dma_chan, cookie, NULL) != DMA_SUCCESS) {
-		dev_printk(KERN_ERR, dma_chan->device->dev,
+		dev_err(dma_chan->device->dev,
 			"Self-test zero sum timed out, disabling\n");
 		err = -ENODEV;
 		goto free_resources;
 	}
 
 	if (zero_sum_result != 0) {
-		dev_printk(KERN_ERR, dma_chan->device->dev,
+		dev_err(dma_chan->device->dev,
 			"Self-test zero sum failed compare, disabling\n");
 		err = -ENODEV;
 		goto free_resources;
@@ -1187,7 +1187,7 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device)
 	msleep(8);
 
 	if (iop_adma_status(dma_chan, cookie, NULL) != DMA_SUCCESS) {
-		dev_printk(KERN_ERR, dma_chan->device->dev,
+		dev_err(dma_chan->device->dev,
 			"Self-test memset timed out, disabling\n");
 		err = -ENODEV;
 		goto free_resources;
@@ -1196,7 +1196,7 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device)
 	for (i = 0; i < PAGE_SIZE/sizeof(u32); i++) {
 		u32 *ptr = page_address(dest);
 		if (ptr[i]) {
-			dev_printk(KERN_ERR, dma_chan->device->dev,
+			dev_err(dma_chan->device->dev,
 				"Self-test memset failed compare, disabling\n");
 			err = -ENODEV;
 			goto free_resources;
@@ -1219,14 +1219,14 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device)
 	msleep(8);
 
 	if (iop_adma_status(dma_chan, cookie, NULL) != DMA_SUCCESS) {
-		dev_printk(KERN_ERR, dma_chan->device->dev,
+		dev_err(dma_chan->device->dev,
 			"Self-test non-zero sum timed out, disabling\n");
 		err = -ENODEV;
 		goto free_resources;
 	}
 
 	if (zero_sum_result != 1) {
-		dev_printk(KERN_ERR, dma_chan->device->dev,
+		dev_err(dma_chan->device->dev,
 			"Self-test non-zero sum failed compare, disabling\n");
 		err = -ENODEV;
 		goto free_resources;
@@ -1243,7 +1243,7 @@ out:
 }
 
 #ifdef CONFIG_RAID6_PQ
-static int __devinit
+static int
 iop_adma_pq_zero_sum_self_test(struct iop_adma_device *device)
 {
 	/* combined sources, software pq results, and extra hw pq results */
@@ -1429,7 +1429,7 @@ static int __devexit iop_adma_remove(struct platform_device *dev)
 	return 0;
 }
 
-static int __devinit iop_adma_probe(struct platform_device *pdev)
+static int iop_adma_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	int ret = 0, i;
@@ -1579,15 +1579,14 @@ static int __devinit iop_adma_probe(struct platform_device *pdev)
 			goto err_free_iop_chan;
 	}
 
-	dev_printk(KERN_INFO, &pdev->dev, "Intel(R) IOP: "
-	  "( %s%s%s%s%s%s%s)\n",
-	  dma_has_cap(DMA_PQ, dma_dev->cap_mask) ? "pq " : "",
-	  dma_has_cap(DMA_PQ_VAL, dma_dev->cap_mask) ? "pq_val " : "",
-	  dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "",
-	  dma_has_cap(DMA_XOR_VAL, dma_dev->cap_mask) ? "xor_val " : "",
-	  dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)  ? "fill " : "",
-	  dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "",
-	  dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : "");
+	dev_info(&pdev->dev, "Intel(R) IOP: ( %s%s%s%s%s%s%s)\n",
+		 dma_has_cap(DMA_PQ, dma_dev->cap_mask) ? "pq " : "",
+		 dma_has_cap(DMA_PQ_VAL, dma_dev->cap_mask) ? "pq_val " : "",
+		 dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "",
+		 dma_has_cap(DMA_XOR_VAL, dma_dev->cap_mask) ? "xor_val " : "",
+		 dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)  ? "fill " : "",
+		 dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "",
+		 dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : "");
 
 	dma_async_device_register(dma_dev);
 	goto out;
@@ -1651,8 +1650,8 @@ static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan)
 		/* run the descriptor */
 		iop_chan_enable(iop_chan);
 	} else
-		dev_printk(KERN_ERR, iop_chan->device->common.dev,
-			 "failed to allocate null descriptor\n");
+		dev_err(iop_chan->device->common.dev,
+			"failed to allocate null descriptor\n");
 	spin_unlock_bh(&iop_chan->lock);
 }
 
@@ -1704,14 +1703,14 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
 		/* run the descriptor */
 		iop_chan_enable(iop_chan);
 	} else
-		dev_printk(KERN_ERR, iop_chan->device->common.dev,
+		dev_err(iop_chan->device->common.dev,
 			"failed to allocate null descriptor\n");
 	spin_unlock_bh(&iop_chan->lock);
 }
 
 static struct platform_driver iop_adma_driver = {
 	.probe		= iop_adma_probe,
-	.remove		= __devexit_p(iop_adma_remove),
+	.remove		= iop_adma_remove,
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= "iop-adma",
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index c7573e5..6585537 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -22,8 +22,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
-
-#include <mach/ipu.h>
+#include <linux/dma/ipu-dma.h>
 
 #include "../dmaengine.h"
 #include "ipu_intern.h"
diff --git a/drivers/dma/ipu/ipu_irq.c b/drivers/dma/ipu/ipu_irq.c
index fa95bcc..a5ee37d 100644
--- a/drivers/dma/ipu/ipu_irq.c
+++ b/drivers/dma/ipu/ipu_irq.c
@@ -15,8 +15,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/module.h>
-
-#include <mach/ipu.h>
+#include <linux/dma/ipu-dma.h>
 
 #include "ipu_intern.h"
 
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index 14da1f4..13bdf4a 100644
--- a/drivers/dma/mmp_pdma.c
+++ b/drivers/dma/mmp_pdma.c
@@ -720,7 +720,7 @@ static int __devexit mmp_pdma_remove(struct platform_device *op)
 	return 0;
 }
 
-static int __devinit mmp_pdma_chan_init(struct mmp_pdma_device *pdev,
+static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev,
 							int idx, int irq)
 {
 	struct mmp_pdma_phy *phy  = &pdev->phy[idx];
@@ -764,7 +764,7 @@ static struct of_device_id mmp_pdma_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, mmp_pdma_dt_ids);
 
-static int __devinit mmp_pdma_probe(struct platform_device *op)
+static int mmp_pdma_probe(struct platform_device *op)
 {
 	struct mmp_pdma_device *pdev;
 	const struct of_device_id *of_id;
@@ -865,7 +865,7 @@ static struct platform_driver mmp_pdma_driver = {
 	},
 	.id_table	= mmp_pdma_id_table,
 	.probe		= mmp_pdma_probe,
-	.remove		= __devexit_p(mmp_pdma_remove),
+	.remove		= mmp_pdma_remove,
 };
 
 module_platform_driver(mmp_pdma_driver);
diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c
index f3e8d71..323821c 100644
--- a/drivers/dma/mmp_tdma.c
+++ b/drivers/dma/mmp_tdma.c
@@ -475,7 +475,7 @@ static int __devexit mmp_tdma_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devinit mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
+static int mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
 						int idx, int irq, int type)
 {
 	struct mmp_tdma_chan *tdmac;
@@ -515,7 +515,7 @@ static struct of_device_id mmp_tdma_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, mmp_tdma_dt_ids);
 
-static int __devinit mmp_tdma_probe(struct platform_device *pdev)
+static int mmp_tdma_probe(struct platform_device *pdev)
 {
 	enum mmp_tdma_type type;
 	const struct of_device_id *of_id;
@@ -609,7 +609,7 @@ static struct platform_driver mmp_tdma_driver = {
 	},
 	.id_table	= mmp_tdma_id_table,
 	.probe		= mmp_tdma_probe,
-	.remove		= __devexit_p(mmp_tdma_remove),
+	.remove		= mmp_tdma_remove,
 };
 
 module_platform_driver(mmp_tdma_driver);
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 2ab0a3d..2cd024a 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -641,7 +641,7 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
 	return &mdesc->desc;
 }
 
-static int __devinit mpc_dma_probe(struct platform_device *op)
+static int mpc_dma_probe(struct platform_device *op)
 {
 	struct device_node *dn = op->dev.of_node;
 	struct device *dev = &op->dev;
@@ -818,7 +818,7 @@ static struct of_device_id mpc_dma_match[] = {
 
 static struct platform_driver mpc_dma_driver = {
 	.probe		= mpc_dma_probe,
-	.remove		= __devexit_p(mpc_dma_remove),
+	.remove		= mpc_dma_remove,
 	.driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index e362e2b..3ef4095 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -206,9 +206,9 @@ static void mv_set_mode(struct mv_xor_chan *chan,
 		op_mode = XOR_OPERATION_MODE_MEMSET;
 		break;
 	default:
-		dev_printk(KERN_ERR, chan->device->common.dev,
-			   "error: unsupported operation %d.\n",
-			   type);
+		dev_err(chan->device->common.dev,
+			"error: unsupported operation %d\n",
+			type);
 		BUG();
 		return;
 	}
@@ -828,28 +828,22 @@ static void mv_dump_xor_regs(struct mv_xor_chan *chan)
 	u32 val;
 
 	val = __raw_readl(XOR_CONFIG(chan));
-	dev_printk(KERN_ERR, chan->device->common.dev,
-		   "config       0x%08x.\n", val);
+	dev_err(chan->device->common.dev, "config       0x%08x\n", val);
 
 	val = __raw_readl(XOR_ACTIVATION(chan));
-	dev_printk(KERN_ERR, chan->device->common.dev,
-		   "activation   0x%08x.\n", val);
+	dev_err(chan->device->common.dev, "activation   0x%08x\n", val);
 
 	val = __raw_readl(XOR_INTR_CAUSE(chan));
-	dev_printk(KERN_ERR, chan->device->common.dev,
-		   "intr cause   0x%08x.\n", val);
+	dev_err(chan->device->common.dev, "intr cause   0x%08x\n", val);
 
 	val = __raw_readl(XOR_INTR_MASK(chan));
-	dev_printk(KERN_ERR, chan->device->common.dev,
-		   "intr mask    0x%08x.\n", val);
+	dev_err(chan->device->common.dev, "intr mask    0x%08x\n", val);
 
 	val = __raw_readl(XOR_ERROR_CAUSE(chan));
-	dev_printk(KERN_ERR, chan->device->common.dev,
-		   "error cause  0x%08x.\n", val);
+	dev_err(chan->device->common.dev, "error cause  0x%08x\n", val);
 
 	val = __raw_readl(XOR_ERROR_ADDR(chan));
-	dev_printk(KERN_ERR, chan->device->common.dev,
-		   "error addr   0x%08x.\n", val);
+	dev_err(chan->device->common.dev, "error addr   0x%08x\n", val);
 }
 
 static void mv_xor_err_interrupt_handler(struct mv_xor_chan *chan,
@@ -861,9 +855,9 @@ static void mv_xor_err_interrupt_handler(struct mv_xor_chan *chan,
 	     return;
 	}
 
-	dev_printk(KERN_ERR, chan->device->common.dev,
-		   "error on chan %d. intr cause 0x%08x.\n",
-		   chan->idx, intr_cause);
+	dev_err(chan->device->common.dev,
+		"error on chan %d. intr cause 0x%08x\n",
+		chan->idx, intr_cause);
 
 	mv_dump_xor_regs(chan);
 	BUG();
@@ -901,7 +895,7 @@ static void mv_xor_issue_pending(struct dma_chan *chan)
  */
 #define MV_XOR_TEST_SIZE 2000
 
-static int __devinit mv_xor_memcpy_self_test(struct mv_xor_device *device)
+static int mv_xor_memcpy_self_test(struct mv_xor_device *device)
 {
 	int i;
 	void *src, *dest;
@@ -950,8 +944,8 @@ static int __devinit mv_xor_memcpy_self_test(struct mv_xor_device *device)
 
 	if (mv_xor_status(dma_chan, cookie, NULL) !=
 	    DMA_SUCCESS) {
-		dev_printk(KERN_ERR, dma_chan->device->dev,
-			   "Self-test copy timed out, disabling\n");
+		dev_err(dma_chan->device->dev,
+			"Self-test copy timed out, disabling\n");
 		err = -ENODEV;
 		goto free_resources;
 	}
@@ -960,8 +954,8 @@ static int __devinit mv_xor_memcpy_self_test(struct mv_xor_device *device)
 	dma_sync_single_for_cpu(&mv_chan->device->pdev->dev, dest_dma,
 				MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
 	if (memcmp(src, dest, MV_XOR_TEST_SIZE)) {
-		dev_printk(KERN_ERR, dma_chan->device->dev,
-			   "Self-test copy failed compare, disabling\n");
+		dev_err(dma_chan->device->dev,
+			"Self-test copy failed compare, disabling\n");
 		err = -ENODEV;
 		goto free_resources;
 	}
@@ -975,7 +969,7 @@ out:
 }
 
 #define MV_XOR_NUM_SRC_TEST 4 /* must be <= 15 */
-static int __devinit
+static int
 mv_xor_xor_self_test(struct mv_xor_device *device)
 {
 	int i, src_idx;
@@ -1048,8 +1042,8 @@ mv_xor_xor_self_test(struct mv_xor_device *device)
 
 	if (mv_xor_status(dma_chan, cookie, NULL) !=
 	    DMA_SUCCESS) {
-		dev_printk(KERN_ERR, dma_chan->device->dev,
-			   "Self-test xor timed out, disabling\n");
+		dev_err(dma_chan->device->dev,
+			"Self-test xor timed out, disabling\n");
 		err = -ENODEV;
 		goto free_resources;
 	}
@@ -1060,10 +1054,9 @@ mv_xor_xor_self_test(struct mv_xor_device *device)
 	for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) {
 		u32 *ptr = page_address(dest);
 		if (ptr[i] != cmp_word) {
-			dev_printk(KERN_ERR, dma_chan->device->dev,
-				   "Self-test xor failed compare, disabling."
-				   " index %d, data %x, expected %x\n", i,
-				   ptr[i], cmp_word);
+			dev_err(dma_chan->device->dev,
+				"Self-test xor failed compare, disabling. index %d, data %x, expected %x\n",
+				i, ptr[i], cmp_word);
 			err = -ENODEV;
 			goto free_resources;
 		}
@@ -1100,7 +1093,7 @@ static int __devexit mv_xor_remove(struct platform_device *dev)
 	return 0;
 }
 
-static int __devinit mv_xor_probe(struct platform_device *pdev)
+static int mv_xor_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 	int irq;
@@ -1212,12 +1205,11 @@ static int __devinit mv_xor_probe(struct platform_device *pdev)
 			goto err_free_dma;
 	}
 
-	dev_printk(KERN_INFO, &pdev->dev, "Marvell XOR: "
-	  "( %s%s%s%s)\n",
-	  dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "",
-	  dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)  ? "fill " : "",
-	  dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "",
-	  dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : "");
+	dev_info(&pdev->dev, "Marvell XOR: ( %s%s%s%s)\n",
+		 dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "",
+		 dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)  ? "fill " : "",
+		 dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "",
+		 dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : "");
 
 	dma_async_device_register(dma_dev);
 	goto out;
@@ -1262,7 +1254,7 @@ mv_xor_conf_mbus_windows(struct mv_xor_shared_private *msp,
 
 static struct platform_driver mv_xor_driver = {
 	.probe		= mv_xor_probe,
-	.remove		= __devexit_p(mv_xor_remove),
+	.remove		= mv_xor_remove,
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= MV_XOR_NAME,
@@ -1275,7 +1267,7 @@ static int mv_xor_shared_probe(struct platform_device *pdev)
 	struct mv_xor_shared_private *msp;
 	struct resource *res;
 
-	dev_printk(KERN_NOTICE, &pdev->dev, "Marvell shared XOR driver\n");
+	dev_notice(&pdev->dev, "Marvell shared XOR driver\n");
 
 	msp = devm_kzalloc(&pdev->dev, sizeof(*msp), GFP_KERNEL);
 	if (!msp)
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index bb2d8e7..7d35c23 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -19,8 +19,7 @@
 
 #include "virt-dma.h"
 
-#include <plat/cpu.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 
 struct omap_dmadev {
 	struct dma_device ddev;
@@ -438,7 +437,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
 		omap_disable_dma_irq(c->dma_ch, OMAP_DMA_BLOCK_IRQ);
 	}
 
-	if (!cpu_class_is_omap1()) {
+	if (dma_omap2plus()) {
 		omap_set_dma_src_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16);
 		omap_set_dma_dest_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16);
 	}
diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c
index 987ab5c..aed6e0c 100644
--- a/drivers/dma/pch_dma.c
+++ b/drivers/dma/pch_dma.c
@@ -843,7 +843,7 @@ static int pch_dma_resume(struct pci_dev *pdev)
 }
 #endif
 
-static int __devinit pch_dma_probe(struct pci_dev *pdev,
+static int pch_dma_probe(struct pci_dev *pdev,
 				   const struct pci_device_id *id)
 {
 	struct pch_dma *pd;
@@ -1022,25 +1022,14 @@ static struct pci_driver pch_dma_driver = {
 	.name		= DRV_NAME,
 	.id_table	= pch_dma_id_table,
 	.probe		= pch_dma_probe,
-	.remove		= __devexit_p(pch_dma_remove),
+	.remove		= pch_dma_remove,
 #ifdef CONFIG_PM
 	.suspend	= pch_dma_suspend,
 	.resume		= pch_dma_resume,
 #endif
 };
 
-static int __init pch_dma_init(void)
-{
-	return pci_register_driver(&pch_dma_driver);
-}
-
-static void __exit pch_dma_exit(void)
-{
-	pci_unregister_driver(&pch_dma_driver);
-}
-
-module_init(pch_dma_init);
-module_exit(pch_dma_exit);
+module_pci_driver(pch_dma_driver);
 
 MODULE_DESCRIPTION("Intel EG20T PCH / LAPIS Semicon ML7213/ML7223/ML7831 IOH "
 		   "DMA controller driver");
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 665668b..95555f3 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2851,7 +2851,7 @@ static irqreturn_t pl330_irq_handler(int irq, void *data)
 		return IRQ_NONE;
 }
 
-static int __devinit
+static int
 pl330_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	struct dma_pl330_platdata *pdat;
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index f72348d..b94afc3 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -4361,7 +4361,7 @@ static void ppc440spe_adma_release_irqs(struct ppc440spe_adma_device *adev,
 /**
  * ppc440spe_adma_probe - probe the asynch device
  */
-static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev)
+static int ppc440spe_adma_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct resource res;
@@ -4914,7 +4914,7 @@ MODULE_DEVICE_TABLE(of, ppc440spe_adma_of_match);
 
 static struct platform_driver ppc440spe_adma_driver = {
 	.probe = ppc440spe_adma_probe,
-	.remove = __devexit_p(ppc440spe_adma_remove),
+	.remove = ppc440spe_adma_remove,
 	.driver = {
 		.name = "PPC440SP(E)-ADMA",
 		.owner = THIS_MODULE,
diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c
index b893159..2ad628d 100644
--- a/drivers/dma/sa11x0-dma.c
+++ b/drivers/dma/sa11x0-dma.c
@@ -826,7 +826,7 @@ static const struct sa11x0_dma_channel_desc chan_desc[] = {
 	CD(Ser4SSPRc, DDAR_RW),
 };
 
-static int __devinit sa11x0_dma_init_dmadev(struct dma_device *dmadev,
+static int sa11x0_dma_init_dmadev(struct dma_device *dmadev,
 	struct device *dev)
 {
 	unsigned i;
@@ -891,7 +891,7 @@ static void sa11x0_dma_free_channels(struct dma_device *dmadev)
 	}
 }
 
-static int __devinit sa11x0_dma_probe(struct platform_device *pdev)
+static int sa11x0_dma_probe(struct platform_device *pdev)
 {
 	struct sa11x0_dma_dev *d;
 	struct resource *res;
@@ -1072,7 +1072,7 @@ static struct platform_driver sa11x0_dma_driver = {
 		.pm	= &sa11x0_dma_pm_ops,
 	},
 	.probe		= sa11x0_dma_probe,
-	.remove		= __devexit_p(sa11x0_dma_remove),
+	.remove		= sa11x0_dma_remove,
 };
 
 bool sa11x0_dma_filter_fn(struct dma_chan *chan, void *param)
diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
index f41bcc5..8201bb4 100644
--- a/drivers/dma/sh/shdma.c
+++ b/drivers/dma/sh/shdma.c
@@ -483,7 +483,7 @@ static struct notifier_block sh_dmae_nmi_notifier __read_mostly = {
 	.priority	= 1,
 };
 
-static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id,
+static int sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id,
 					int irq, unsigned long flags)
 {
 	const struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id];
@@ -646,7 +646,7 @@ static const struct shdma_ops sh_dmae_shdma_ops = {
 	.get_partial = sh_dmae_get_partial,
 };
 
-static int __devinit sh_dmae_probe(struct platform_device *pdev)
+static int sh_dmae_probe(struct platform_device *pdev)
 {
 	struct sh_dmae_pdata *pdata = pdev->dev.platform_data;
 	unsigned long irqflags = IRQF_DISABLED,
@@ -926,7 +926,7 @@ static struct platform_driver sh_dmae_driver = {
 		.pm	= &sh_dmae_pm,
 		.name	= SH_DMAE_DRV_NAME,
 	},
-	.remove		= __devexit_p(sh_dmae_remove),
+	.remove		= sh_dmae_remove,
 	.shutdown	= sh_dmae_shutdown,
 };
 
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
index d451caa..c3de6ed 100644
--- a/drivers/dma/sirf-dma.c
+++ b/drivers/dma/sirf-dma.c
@@ -550,7 +550,7 @@ bool sirfsoc_dma_filter_id(struct dma_chan *chan, void *chan_id)
 }
 EXPORT_SYMBOL(sirfsoc_dma_filter_id);
 
-static int __devinit sirfsoc_dma_probe(struct platform_device *op)
+static int sirfsoc_dma_probe(struct platform_device *op)
 {
 	struct device_node *dn = op->dev.of_node;
 	struct device *dev = &op->dev;
@@ -673,7 +673,7 @@ static struct of_device_id sirfsoc_dma_match[] = {
 
 static struct platform_driver sirfsoc_dma_driver = {
 	.probe		= sirfsoc_dma_probe,
-	.remove		= __devexit_p(sirfsoc_dma_remove),
+	.remove		= sirfsoc_dma_remove,
 	.driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index ae55091..23c5573 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -19,8 +19,7 @@
 #include <linux/err.h>
 #include <linux/amba/bus.h>
 #include <linux/regulator/consumer.h>
-
-#include <plat/ste_dma40.h>
+#include <linux/platform_data/dma-ste-dma40.h>
 
 #include "dmaengine.h"
 #include "ste_dma40_ll.h"
diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c
index cad9e1d..851ad56 100644
--- a/drivers/dma/ste_dma40_ll.c
+++ b/drivers/dma/ste_dma40_ll.c
@@ -6,7 +6,7 @@
  */
 
 #include <linux/kernel.h>
-#include <plat/ste_dma40.h>
+#include <linux/platform_data/dma-ste-dma40.h>
 
 #include "ste_dma40_ll.h"
 
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index 528c62d..efdfffa 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -1197,7 +1197,7 @@ static const struct of_device_id tegra_dma_of_match[] __devinitconst = {
 MODULE_DEVICE_TABLE(of, tegra_dma_of_match);
 #endif
 
-static int __devinit tegra_dma_probe(struct platform_device *pdev)
+static int tegra_dma_probe(struct platform_device *pdev)
 {
 	struct resource	*res;
 	struct tegra_dma *tdma;
@@ -1418,7 +1418,7 @@ static struct platform_driver tegra_dmac_driver = {
 		.of_match_table = of_match_ptr(tegra_dma_of_match),
 	},
 	.probe		= tegra_dma_probe,
-	.remove		= __devexit_p(tegra_dma_remove),
+	.remove		= tegra_dma_remove,
 };
 
 module_platform_driver(tegra_dmac_driver);
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
index 4e0dff5..98cf51e 100644
--- a/drivers/dma/timb_dma.c
+++ b/drivers/dma/timb_dma.c
@@ -667,7 +667,7 @@ static irqreturn_t td_irq(int irq, void *devid)
 }
 
 
-static int __devinit td_probe(struct platform_device *pdev)
+static int td_probe(struct platform_device *pdev)
 {
 	struct timb_dma_platform_data *pdata = pdev->dev.platform_data;
 	struct timb_dma *td;
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 409b92b..4c6c876 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -7,7 +7,7 @@
 menuconfig EDAC
 	bool "EDAC (Error Detection And Correction) reporting"
 	depends on HAS_IOMEM
-	depends on X86 || PPC || TILE || ARM
+	depends on X86 || PPC || TILE || ARM || EDAC_SUPPORT
 	help
 	  EDAC is designed to report errors in the core system.
 	  These are low-level errors that are reported in the CPU or
@@ -27,6 +27,9 @@ menuconfig EDAC
 	  There is also a mailing list for the EDAC project, which can
 	  be found via the sourceforge page.
 
+config EDAC_SUPPORT
+	bool
+
 if EDAC
 
 comment "Reporting subsystems"
@@ -42,10 +45,10 @@ config EDAC_LEGACY_SYSFS
 config EDAC_DEBUG
 	bool "Debugging"
 	help
-	  This turns on debugging information for the entire EDAC
-	  sub-system. You can insert module with "debug_level=x", current
-	  there're four debug levels (x=0,1,2,3 from low to high).
-	  Usually you should select 'N'.
+	  This turns on debugging information for the entire EDAC subsystem.
+	  You do so by inserting edac_module with "edac_debug_level=x." Valid
+	  levels are 0-4 (from low to high) and by default it is set to 2.
+	  Usually you should select 'N' here.
 
 config EDAC_DECODE_MCE
 	tristate "Decode MCEs in human-readable form (only on AMD for now)"
@@ -316,4 +319,32 @@ config EDAC_HIGHBANK_L2
 	  Support for error detection and correction on the
 	  Calxeda Highbank memory controller.
 
+config EDAC_OCTEON_PC
+	tristate "Cavium Octeon Primary Caches"
+	depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON
+	help
+	  Support for error detection and correction on the primary caches of
+	  the cnMIPS cores of Cavium Octeon family SOCs.
+
+config EDAC_OCTEON_L2C
+	tristate "Cavium Octeon Secondary Caches (L2C)"
+	depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON
+	help
+	  Support for error detection and correction on the
+	  Cavium Octeon family of SOCs.
+
+config EDAC_OCTEON_LMC
+	tristate "Cavium Octeon DRAM Memory Controller (LMC)"
+	depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON
+	help
+	  Support for error detection and correction on the
+	  Cavium Octeon family of SOCs.
+
+config EDAC_OCTEON_PCI
+	tristate "Cavium Octeon PCI Controller"
+	depends on EDAC_MM_EDAC && PCI && CPU_CAVIUM_OCTEON
+	help
+	  Support for error detection and correction on the
+	  Cavium Octeon family of SOCs.
+
 endif # EDAC
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index 7e5129a..5608a9b 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -58,3 +58,8 @@ obj-$(CONFIG_EDAC_TILE)			+= tile_edac.o
 
 obj-$(CONFIG_EDAC_HIGHBANK_MC)	+= highbank_mc_edac.o
 obj-$(CONFIG_EDAC_HIGHBANK_L2)	+= highbank_l2_edac.o
+
+obj-$(CONFIG_EDAC_OCTEON_PC)		+= octeon_edac-pc.o
+obj-$(CONFIG_EDAC_OCTEON_L2C)		+= octeon_edac-l2c.o
+obj-$(CONFIG_EDAC_OCTEON_LMC)		+= octeon_edac-lmc.o
+obj-$(CONFIG_EDAC_OCTEON_PCI)		+= octeon_edac-pci.o
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index cc8e7c7..f74a684 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -60,8 +60,8 @@ struct scrubrate {
 	{ 0x00, 0UL},        /* scrubbing off */
 };
 
-static int __amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
-				      u32 *val, const char *func)
+int __amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
+			       u32 *val, const char *func)
 {
 	int err = 0;
 
@@ -423,7 +423,6 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
 			     u64 *hole_offset, u64 *hole_size)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
-	u64 base;
 
 	/* only revE and later have the DRAM Hole Address Register */
 	if (boot_cpu_data.x86 == 0xf && pvt->ext_model < K8_REV_E) {
@@ -462,10 +461,8 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
 	 * addresses in the hole so that they start at 0x100000000.
 	 */
 
-	base = dhar_base(pvt);
-
-	*hole_base = base;
-	*hole_size = (0x1ull << 32) - base;
+	*hole_base = dhar_base(pvt);
+	*hole_size = (1ULL << 32) - *hole_base;
 
 	if (boot_cpu_data.x86 > 0xf)
 		*hole_offset = f10_dhar_offset(pvt);
@@ -513,15 +510,15 @@ static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
 	u64 dram_base, hole_base, hole_offset, hole_size, dram_addr;
-	int ret = 0;
+	int ret;
 
 	dram_base = get_dram_base(pvt, pvt->mc_node_id);
 
 	ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset,
 				      &hole_size);
 	if (!ret) {
-		if ((sys_addr >= (1ull << 32)) &&
-		    (sys_addr < ((1ull << 32) + hole_size))) {
+		if ((sys_addr >= (1ULL << 32)) &&
+		    (sys_addr < ((1ULL << 32) + hole_size))) {
 			/* use DHAR to translate SysAddr to DramAddr */
 			dram_addr = sys_addr - hole_offset;
 
@@ -712,10 +709,10 @@ static inline u64 input_addr_to_sys_addr(struct mem_ctl_info *mci,
 
 /* Map the Error address to a PAGE and PAGE OFFSET. */
 static inline void error_address_to_page_and_offset(u64 error_address,
-						    u32 *page, u32 *offset)
+						    struct err_info *err)
 {
-	*page = (u32) (error_address >> PAGE_SHIFT);
-	*offset = ((u32) error_address) & ~PAGE_MASK;
+	err->page = (u32) (error_address >> PAGE_SHIFT);
+	err->offset = ((u32) error_address) & ~PAGE_MASK;
 }
 
 /*
@@ -1026,59 +1023,44 @@ static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range)
 }
 
 static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
-				    u16 syndrome)
+				    struct err_info *err)
 {
-	struct mem_ctl_info *src_mci;
 	struct amd64_pvt *pvt = mci->pvt_info;
-	int channel, csrow;
-	u32 page, offset;
 
-	error_address_to_page_and_offset(sys_addr, &page, &offset);
+	error_address_to_page_and_offset(sys_addr, err);
 
 	/*
 	 * Find out which node the error address belongs to. This may be
 	 * different from the node that detected the error.
 	 */
-	src_mci = find_mc_by_sys_addr(mci, sys_addr);
-	if (!src_mci) {
+	err->src_mci = find_mc_by_sys_addr(mci, sys_addr);
+	if (!err->src_mci) {
 		amd64_mc_err(mci, "failed to map error addr 0x%lx to a node\n",
 			     (unsigned long)sys_addr);
-		edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
-				     page, offset, syndrome,
-				     -1, -1, -1,
-				     "failed to map error addr to a node",
-				     "");
+		err->err_code = ERR_NODE;
 		return;
 	}
 
 	/* Now map the sys_addr to a CSROW */
-	csrow = sys_addr_to_csrow(src_mci, sys_addr);
-	if (csrow < 0) {
-		edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
-				     page, offset, syndrome,
-				     -1, -1, -1,
-				     "failed to map error addr to a csrow",
-				     "");
+	err->csrow = sys_addr_to_csrow(err->src_mci, sys_addr);
+	if (err->csrow < 0) {
+		err->err_code = ERR_CSROW;
 		return;
 	}
 
 	/* CHIPKILL enabled */
 	if (pvt->nbcfg & NBCFG_CHIPKILL) {
-		channel = get_channel_from_ecc_syndrome(mci, syndrome);
-		if (channel < 0) {
+		err->channel = get_channel_from_ecc_syndrome(mci, err->syndrome);
+		if (err->channel < 0) {
 			/*
 			 * Syndrome didn't map, so we don't know which of the
 			 * 2 DIMMs is in error. So we need to ID 'both' of them
 			 * as suspect.
 			 */
-			amd64_mc_warn(src_mci, "unknown syndrome 0x%04x - "
+			amd64_mc_warn(err->src_mci, "unknown syndrome 0x%04x - "
 				      "possible error reporting race\n",
-				      syndrome);
-			edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
-					     page, offset, syndrome,
-					     csrow, -1, -1,
-					     "unknown syndrome - possible error reporting race",
-					     "");
+				      err->syndrome);
+			err->err_code = ERR_CHANNEL;
 			return;
 		}
 	} else {
@@ -1090,13 +1072,8 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
 		 * was obtained from email communication with someone at AMD.
 		 * (Wish the email was placed in this comment - norsk)
 		 */
-		channel = ((sys_addr & BIT(3)) != 0);
+		err->channel = ((sys_addr & BIT(3)) != 0);
 	}
-
-	edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, src_mci, 1,
-			     page, offset, syndrome,
-			     csrow, channel, -1,
-			     "", "");
 }
 
 static int ddr2_cs_size(unsigned i, bool dct_width)
@@ -1482,7 +1459,7 @@ static u64 f1x_swap_interleaved_region(struct amd64_pvt *pvt, u64 sys_addr)
 
 /* For a given @dram_range, check if @sys_addr falls within it. */
 static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range,
-				  u64 sys_addr, int *nid, int *chan_sel)
+				  u64 sys_addr, int *chan_sel)
 {
 	int cs_found = -EINVAL;
 	u64 chan_addr;
@@ -1555,15 +1532,14 @@ static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range,
 
 	cs_found = f1x_lookup_addr_in_dct(chan_addr, node_id, channel);
 
-	if (cs_found >= 0) {
-		*nid = node_id;
+	if (cs_found >= 0)
 		*chan_sel = channel;
-	}
+
 	return cs_found;
 }
 
 static int f1x_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr,
-				       int *node, int *chan_sel)
+				       int *chan_sel)
 {
 	int cs_found = -EINVAL;
 	unsigned range;
@@ -1577,8 +1553,7 @@ static int f1x_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr,
 		    (get_dram_limit(pvt, range) >= sys_addr)) {
 
 			cs_found = f1x_match_to_this_node(pvt, range,
-							  sys_addr, node,
-							  chan_sel);
+							  sys_addr, chan_sel);
 			if (cs_found >= 0)
 				break;
 		}
@@ -1594,22 +1569,15 @@ static int f1x_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr,
  * (MCX_ADDR).
  */
 static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
-				     u16 syndrome)
+				     struct err_info *err)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
-	u32 page, offset;
-	int nid, csrow, chan = 0;
 
-	error_address_to_page_and_offset(sys_addr, &page, &offset);
+	error_address_to_page_and_offset(sys_addr, err);
 
-	csrow = f1x_translate_sysaddr_to_cs(pvt, sys_addr, &nid, &chan);
-
-	if (csrow < 0) {
-		edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
-				     page, offset, syndrome,
-				     -1, -1, -1,
-				     "failed to map error addr to a csrow",
-				     "");
+	err->csrow = f1x_translate_sysaddr_to_cs(pvt, sys_addr, &err->channel);
+	if (err->csrow < 0) {
+		err->err_code = ERR_CSROW;
 		return;
 	}
 
@@ -1619,12 +1587,7 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
 	 * this point.
 	 */
 	if (dct_ganging_enabled(pvt))
-		chan = get_channel_from_ecc_syndrome(mci, syndrome);
-
-	edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
-			     page, offset, syndrome,
-			     csrow, chan, -1,
-			     "", "");
+		err->channel = get_channel_from_ecc_syndrome(mci, err->syndrome);
 }
 
 /*
@@ -1633,14 +1596,11 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
  */
 static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
 {
-	int dimm, size0, size1, factor = 0;
+	int dimm, size0, size1;
 	u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases;
 	u32 dbam  = ctrl ? pvt->dbam1 : pvt->dbam0;
 
 	if (boot_cpu_data.x86 == 0xf) {
-		if (pvt->dclr0 & WIDTH_128)
-			factor = 1;
-
 		/* K8 families < revF not supported yet */
 	       if (pvt->ext_model < K8_REV_F)
 			return;
@@ -1671,8 +1631,8 @@ static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
 						     DBAM_DIMM(dimm, dbam));
 
 		amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
-				dimm * 2,     size0 << factor,
-				dimm * 2 + 1, size1 << factor);
+				dimm * 2,     size0,
+				dimm * 2 + 1, size1);
 	}
 }
 
@@ -1893,101 +1853,56 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *mci, u16 syndrome)
 	return map_err_sym_to_channel(err_sym, pvt->ecc_sym_sz);
 }
 
-/*
- * Handle any Correctable Errors (CEs) that have occurred. Check for valid ERROR
- * ADDRESS and process.
- */
-static void amd64_handle_ce(struct mem_ctl_info *mci, struct mce *m)
-{
-	struct amd64_pvt *pvt = mci->pvt_info;
-	u64 sys_addr;
-	u16 syndrome;
-
-	/* Ensure that the Error Address is VALID */
-	if (!(m->status & MCI_STATUS_ADDRV)) {
-		amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n");
-		edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
-				     0, 0, 0,
-				     -1, -1, -1,
-				     "HW has no ERROR_ADDRESS available",
-				     "");
-		return;
-	}
-
-	sys_addr = get_error_address(m);
-	syndrome = extract_syndrome(m->status);
-
-	amd64_mc_err(mci, "CE ERROR_ADDRESS= 0x%llx\n", sys_addr);
-
-	pvt->ops->map_sysaddr_to_csrow(mci, sys_addr, syndrome);
-}
-
-/* Handle any Un-correctable Errors (UEs) */
-static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m)
+static void __log_bus_error(struct mem_ctl_info *mci, struct err_info *err,
+			    u8 ecc_type)
 {
-	struct mem_ctl_info *log_mci, *src_mci = NULL;
-	int csrow;
-	u64 sys_addr;
-	u32 page, offset;
-
-	log_mci = mci;
+	enum hw_event_mc_err_type err_type;
+	const char *string;
 
-	if (!(m->status & MCI_STATUS_ADDRV)) {
-		amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n");
-		edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
-				     0, 0, 0,
-				     -1, -1, -1,
-				     "HW has no ERROR_ADDRESS available",
-				     "");
+	if (ecc_type == 2)
+		err_type = HW_EVENT_ERR_CORRECTED;
+	else if (ecc_type == 1)
+		err_type = HW_EVENT_ERR_UNCORRECTED;
+	else {
+		WARN(1, "Something is rotten in the state of Denmark.\n");
 		return;
 	}
 
-	sys_addr = get_error_address(m);
-	error_address_to_page_and_offset(sys_addr, &page, &offset);
-
-	/*
-	 * Find out which node the error address belongs to. This may be
-	 * different from the node that detected the error.
-	 */
-	src_mci = find_mc_by_sys_addr(mci, sys_addr);
-	if (!src_mci) {
-		amd64_mc_err(mci, "ERROR ADDRESS (0x%lx) NOT mapped to a MC\n",
-				  (unsigned long)sys_addr);
-		edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
-				     page, offset, 0,
-				     -1, -1, -1,
-				     "ERROR ADDRESS NOT mapped to a MC",
-				     "");
-		return;
+	switch (err->err_code) {
+	case DECODE_OK:
+		string = "";
+		break;
+	case ERR_NODE:
+		string = "Failed to map error addr to a node";
+		break;
+	case ERR_CSROW:
+		string = "Failed to map error addr to a csrow";
+		break;
+	case ERR_CHANNEL:
+		string = "unknown syndrome - possible error reporting race";
+		break;
+	default:
+		string = "WTF error";
+		break;
 	}
 
-	log_mci = src_mci;
-
-	csrow = sys_addr_to_csrow(log_mci, sys_addr);
-	if (csrow < 0) {
-		amd64_mc_err(mci, "ERROR_ADDRESS (0x%lx) NOT mapped to CS\n",
-				  (unsigned long)sys_addr);
-		edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
-				     page, offset, 0,
-				     -1, -1, -1,
-				     "ERROR ADDRESS NOT mapped to CS",
-				     "");
-	} else {
-		edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
-				     page, offset, 0,
-				     csrow, -1, -1,
-				     "", "");
-	}
+	edac_mc_handle_error(err_type, mci, 1,
+			     err->page, err->offset, err->syndrome,
+			     err->csrow, err->channel, -1,
+			     string, "");
 }
 
 static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
 					    struct mce *m)
 {
-	u16 ec = EC(m->status);
-	u8 xec = XEC(m->status, 0x1f);
+	struct amd64_pvt *pvt = mci->pvt_info;
 	u8 ecc_type = (m->status >> 45) & 0x3;
+	u8 xec = XEC(m->status, 0x1f);
+	u16 ec = EC(m->status);
+	u64 sys_addr;
+	struct err_info err;
 
-	/* Bail early out if this was an 'observed' error */
+	/* Bail out early if this was an 'observed' error */
 	if (PP(ec) == NBSL_PP_OBS)
 		return;
 
@@ -1995,10 +1910,16 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
 	if (xec && xec != F10_NBSL_EXT_ERR_ECC)
 		return;
 
+	memset(&err, 0, sizeof(err));
+
+	sys_addr = get_error_address(m);
+
 	if (ecc_type == 2)
-		amd64_handle_ce(mci, m);
-	else if (ecc_type == 1)
-		amd64_handle_ue(mci, m);
+		err.syndrome = extract_syndrome(m->status);
+
+	pvt->ops->map_sysaddr_to_csrow(mci, sys_addr, &err);
+
+	__log_bus_error(mci, &err, ecc_type);
 }
 
 void amd64_decode_bus_error(int node_id, struct mce *m)
@@ -2166,6 +2087,7 @@ static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
 	u32 cs_mode, nr_pages;
 	u32 dbam = dct ? pvt->dbam1 : pvt->dbam0;
 
+
 	/*
 	 * The math on this doesn't look right on the surface because x/2*4 can
 	 * be simplified to x*2 but this expression makes use of the fact that
@@ -2173,13 +2095,13 @@ static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
 	 * number of bits to shift the DBAM register to extract the proper CSROW
 	 * field.
 	 */
-	cs_mode =  (dbam >> ((csrow_nr / 2) * 4)) & 0xF;
+	cs_mode = DBAM_DIMM(csrow_nr / 2, dbam);
 
 	nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode) << (20 - PAGE_SHIFT);
 
-	edac_dbg(0, "  (csrow=%d) DBAM map index= %d\n", csrow_nr, cs_mode);
-	edac_dbg(0, "    nr_pages/channel= %u  channel-count = %d\n",
-		 nr_pages, pvt->channel_count);
+	edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n",
+		    csrow_nr, dct,  cs_mode);
+	edac_dbg(0, "nr_pages/channel: %u\n", nr_pages);
 
 	return nr_pages;
 }
@@ -2190,15 +2112,14 @@ static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
  */
 static int init_csrows(struct mem_ctl_info *mci)
 {
+	struct amd64_pvt *pvt = mci->pvt_info;
 	struct csrow_info *csrow;
 	struct dimm_info *dimm;
-	struct amd64_pvt *pvt = mci->pvt_info;
-	u64 base, mask;
-	u32 val;
-	int i, j, empty = 1;
-	enum mem_type mtype;
 	enum edac_type edac_mode;
+	enum mem_type mtype;
+	int i, j, empty = 1;
 	int nr_pages = 0;
+	u32 val;
 
 	amd64_read_pci_cfg(pvt->F3, NBCFG, &val);
 
@@ -2208,29 +2129,35 @@ static int init_csrows(struct mem_ctl_info *mci)
 		 pvt->mc_node_id, val,
 		 !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE));
 
+	/*
+	 * We iterate over DCT0 here but we look at DCT1 in parallel, if needed.
+	 */
 	for_each_chip_select(i, 0, pvt) {
-		csrow = mci->csrows[i];
+		bool row_dct0 = !!csrow_enabled(i, 0, pvt);
+		bool row_dct1 = false;
+
+		if (boot_cpu_data.x86 != 0xf)
+			row_dct1 = !!csrow_enabled(i, 1, pvt);
 
-		if (!csrow_enabled(i, 0, pvt) && !csrow_enabled(i, 1, pvt)) {
-			edac_dbg(1, "----CSROW %d VALID for MC node %d\n",
-				 i, pvt->mc_node_id);
+		if (!row_dct0 && !row_dct1)
 			continue;
-		}
 
+		csrow = mci->csrows[i];
 		empty = 0;
-		if (csrow_enabled(i, 0, pvt))
+
+		edac_dbg(1, "MC node: %d, csrow: %d\n",
+			    pvt->mc_node_id, i);
+
+		if (row_dct0)
 			nr_pages = amd64_csrow_nr_pages(pvt, 0, i);
-		if (csrow_enabled(i, 1, pvt))
-			nr_pages += amd64_csrow_nr_pages(pvt, 1, i);
 
-		get_cs_base_and_mask(pvt, i, 0, &base, &mask);
-		/* 8 bytes of resolution */
+		/* K8 has only one DCT */
+		if (boot_cpu_data.x86 != 0xf && row_dct1)
+			nr_pages += amd64_csrow_nr_pages(pvt, 1, i);
 
 		mtype = amd64_determine_memory_type(pvt, i);
 
-		edac_dbg(1, "  for MC node %d csrow %d:\n", pvt->mc_node_id, i);
-		edac_dbg(1, "    nr_pages: %u\n",
-			 nr_pages * pvt->channel_count);
+		edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages);
 
 		/*
 		 * determine whether CHIPKILL or JUST ECC or NO ECC is operating
@@ -2247,6 +2174,7 @@ static int init_csrows(struct mem_ctl_info *mci)
 			dimm->edac_mode = edac_mode;
 			dimm->nr_pages = nr_pages;
 		}
+		csrow->nr_pages = nr_pages;
 	}
 
 	return empty;
@@ -2591,6 +2519,7 @@ static int amd64_init_one_instance(struct pci_dev *F2)
 
 	mci->pvt_info = pvt;
 	mci->pdev = &pvt->F2->dev;
+	mci->csbased = 1;
 
 	setup_mci_misc_attrs(mci, fam_type);
 
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index 8c41396..e864f40 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -219,7 +219,7 @@
 #define DBAM1				0x180
 
 /* Extract the DIMM 'type' on the i'th DIMM from the DBAM reg value passed */
-#define DBAM_DIMM(i, reg)		((((reg) >> (4*i))) & 0xF)
+#define DBAM_DIMM(i, reg)		((((reg) >> (4*(i)))) & 0xF)
 
 #define DBAM_MAX_VALUE			11
 
@@ -267,18 +267,20 @@
 #define online_spare_bad_dramcs(pvt, c)	(((pvt)->online_spare >> (4 + 4 * (c))) & 0x7)
 
 #define F10_NB_ARRAY_ADDR		0xB8
-#define F10_NB_ARRAY_DRAM_ECC		BIT(31)
+#define F10_NB_ARRAY_DRAM		BIT(31)
 
 /* Bits [2:1] are used to select 16-byte section within a 64-byte cacheline  */
-#define SET_NB_ARRAY_ADDRESS(section)	(((section) & 0x3) << 1)
+#define SET_NB_ARRAY_ADDR(section)	(((section) & 0x3) << 1)
 
 #define F10_NB_ARRAY_DATA		0xBC
-#define SET_NB_DRAM_INJECTION_WRITE(word, bits)  \
-					(BIT(((word) & 0xF) + 20) | \
-					BIT(17) | bits)
-#define SET_NB_DRAM_INJECTION_READ(word, bits)  \
-					(BIT(((word) & 0xF) + 20) | \
-					BIT(16) |  bits)
+#define F10_NB_ARR_ECC_WR_REQ		BIT(17)
+#define SET_NB_DRAM_INJECTION_WRITE(inj)  \
+					(BIT(((inj.word) & 0xF) + 20) | \
+					F10_NB_ARR_ECC_WR_REQ | inj.bit_map)
+#define SET_NB_DRAM_INJECTION_READ(inj)  \
+					(BIT(((inj.word) & 0xF) + 20) | \
+					BIT(16) |  inj.bit_map)
+
 
 #define NBCAP				0xE8
 #define NBCAP_CHIPKILL			BIT(4)
@@ -305,9 +307,9 @@ enum amd_families {
 
 /* Error injection control structure */
 struct error_injection {
-	u32	section;
-	u32	word;
-	u32	bit_map;
+	u32	 section;
+	u32	 word;
+	u32	 bit_map;
 };
 
 /* low and high part of PCI config space regs */
@@ -374,6 +376,23 @@ struct amd64_pvt {
 	struct error_injection injection;
 };
 
+enum err_codes {
+	DECODE_OK	=  0,
+	ERR_NODE	= -1,
+	ERR_CSROW	= -2,
+	ERR_CHANNEL	= -3,
+};
+
+struct err_info {
+	int err_code;
+	struct mem_ctl_info *src_mci;
+	int csrow;
+	int channel;
+	u16 syndrome;
+	u32 page;
+	u32 offset;
+};
+
 static inline u64 get_dram_base(struct amd64_pvt *pvt, unsigned i)
 {
 	u64 addr = ((u64)pvt->ranges[i].base.lo & 0xffff0000) << 8;
@@ -447,7 +466,7 @@ static inline void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci)
 struct low_ops {
 	int (*early_channel_count)	(struct amd64_pvt *pvt);
 	void (*map_sysaddr_to_csrow)	(struct mem_ctl_info *mci, u64 sys_addr,
-					 u16 syndrome);
+					 struct err_info *);
 	int (*dbam_to_cs)		(struct amd64_pvt *pvt, u8 dct, unsigned cs_mode);
 	int (*read_dct_pci_cfg)		(struct amd64_pvt *pvt, int offset,
 					 u32 *val, const char *func);
@@ -459,6 +478,8 @@ struct amd64_family_type {
 	struct low_ops ops;
 };
 
+int __amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
+			       u32 *val, const char *func);
 int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset,
 				u32 val, const char *func);
 
@@ -475,3 +496,15 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
 			     u64 *hole_offset, u64 *hole_size);
 
 #define to_mci(k) container_of(k, struct mem_ctl_info, dev)
+
+/* Injection helpers */
+static inline void disable_caches(void *dummy)
+{
+	write_cr0(read_cr0() | X86_CR0_CD);
+	wbinvd();
+}
+
+static inline void enable_caches(void *dummy)
+{
+	write_cr0(read_cr0() & ~X86_CR0_CD);
+}
diff --git a/drivers/edac/amd64_edac_inj.c b/drivers/edac/amd64_edac_inj.c
index 53d972e..8c171fa 100644
--- a/drivers/edac/amd64_edac_inj.c
+++ b/drivers/edac/amd64_edac_inj.c
@@ -22,20 +22,19 @@ static ssize_t amd64_inject_section_store(struct device *dev,
 	struct mem_ctl_info *mci = to_mci(dev);
 	struct amd64_pvt *pvt = mci->pvt_info;
 	unsigned long value;
-	int ret = 0;
+	int ret;
 
 	ret = strict_strtoul(data, 10, &value);
-	if (ret != -EINVAL) {
+	if (ret < 0)
+		return ret;
 
-		if (value > 3) {
-			amd64_warn("%s: invalid section 0x%lx\n", __func__, value);
-			return -EINVAL;
-		}
-
-		pvt->injection.section = (u32) value;
-		return count;
+	if (value > 3) {
+		amd64_warn("%s: invalid section 0x%lx\n", __func__, value);
+		return -EINVAL;
 	}
-	return ret;
+
+	pvt->injection.section = (u32) value;
+	return count;
 }
 
 static ssize_t amd64_inject_word_show(struct device *dev,
@@ -60,20 +59,19 @@ static ssize_t amd64_inject_word_store(struct device *dev,
 	struct mem_ctl_info *mci = to_mci(dev);
 	struct amd64_pvt *pvt = mci->pvt_info;
 	unsigned long value;
-	int ret = 0;
+	int ret;
 
 	ret = strict_strtoul(data, 10, &value);
-	if (ret != -EINVAL) {
+	if (ret < 0)
+		return ret;
 
-		if (value > 8) {
-			amd64_warn("%s: invalid word 0x%lx\n", __func__, value);
-			return -EINVAL;
-		}
-
-		pvt->injection.word = (u32) value;
-		return count;
+	if (value > 8) {
+		amd64_warn("%s: invalid word 0x%lx\n", __func__, value);
+		return -EINVAL;
 	}
-	return ret;
+
+	pvt->injection.word = (u32) value;
+	return count;
 }
 
 static ssize_t amd64_inject_ecc_vector_show(struct device *dev,
@@ -97,21 +95,19 @@ static ssize_t amd64_inject_ecc_vector_store(struct device *dev,
 	struct mem_ctl_info *mci = to_mci(dev);
 	struct amd64_pvt *pvt = mci->pvt_info;
 	unsigned long value;
-	int ret = 0;
+	int ret;
 
 	ret = strict_strtoul(data, 16, &value);
-	if (ret != -EINVAL) {
+	if (ret < 0)
+		return ret;
 
-		if (value & 0xFFFF0000) {
-			amd64_warn("%s: invalid EccVector: 0x%lx\n",
-				   __func__, value);
-			return -EINVAL;
-		}
-
-		pvt->injection.bit_map = (u32) value;
-		return count;
+	if (value & 0xFFFF0000) {
+		amd64_warn("%s: invalid EccVector: 0x%lx\n", __func__, value);
+		return -EINVAL;
 	}
-	return ret;
+
+	pvt->injection.bit_map = (u32) value;
+	return count;
 }
 
 /*
@@ -126,28 +122,25 @@ static ssize_t amd64_inject_read_store(struct device *dev,
 	struct amd64_pvt *pvt = mci->pvt_info;
 	unsigned long value;
 	u32 section, word_bits;
-	int ret = 0;
+	int ret;
 
 	ret = strict_strtoul(data, 10, &value);
-	if (ret != -EINVAL) {
+	if (ret < 0)
+		return ret;
 
-		/* Form value to choose 16-byte section of cacheline */
-		section = F10_NB_ARRAY_DRAM_ECC |
-				SET_NB_ARRAY_ADDRESS(pvt->injection.section);
-		amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section);
+	/* Form value to choose 16-byte section of cacheline */
+	section = F10_NB_ARRAY_DRAM | SET_NB_ARRAY_ADDR(pvt->injection.section);
 
-		word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection.word,
-						pvt->injection.bit_map);
+	amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section);
 
-		/* Issue 'word' and 'bit' along with the READ request */
-		amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
+	word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection);
 
-		edac_dbg(0, "section=0x%x word_bits=0x%x\n",
-			 section, word_bits);
+	/* Issue 'word' and 'bit' along with the READ request */
+	amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
 
-		return count;
-	}
-	return ret;
+	edac_dbg(0, "section=0x%x word_bits=0x%x\n", section, word_bits);
+
+	return count;
 }
 
 /*
@@ -160,30 +153,43 @@ static ssize_t amd64_inject_write_store(struct device *dev,
 {
 	struct mem_ctl_info *mci = to_mci(dev);
 	struct amd64_pvt *pvt = mci->pvt_info;
+	u32 section, word_bits, tmp;
 	unsigned long value;
-	u32 section, word_bits;
-	int ret = 0;
+	int ret;
 
 	ret = strict_strtoul(data, 10, &value);
-	if (ret != -EINVAL) {
+	if (ret < 0)
+		return ret;
+
+	/* Form value to choose 16-byte section of cacheline */
+	section = F10_NB_ARRAY_DRAM | SET_NB_ARRAY_ADDR(pvt->injection.section);
+
+	amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section);
 
-		/* Form value to choose 16-byte section of cacheline */
-		section = F10_NB_ARRAY_DRAM_ECC |
-				SET_NB_ARRAY_ADDRESS(pvt->injection.section);
-		amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section);
+	word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection);
 
-		word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word,
-						pvt->injection.bit_map);
+	pr_notice_once("Don't forget to decrease MCE polling interval in\n"
+			"/sys/bus/machinecheck/devices/machinecheck<CPUNUM>/check_interval\n"
+			"so that you can get the error report faster.\n");
 
-		/* Issue 'word' and 'bit' along with the READ request */
-		amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
+	on_each_cpu(disable_caches, NULL, 1);
 
-		edac_dbg(0, "section=0x%x word_bits=0x%x\n",
-			 section, word_bits);
+	/* Issue 'word' and 'bit' along with the READ request */
+	amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
 
-		return count;
+ retry:
+	/* wait until injection happens */
+	amd64_read_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, &tmp);
+	if (tmp & F10_NB_ARR_ECC_WR_REQ) {
+		cpu_relax();
+		goto retry;
 	}
-	return ret;
+
+	on_each_cpu(enable_caches, NULL, 1);
+
+	edac_dbg(0, "section=0x%x word_bits=0x%x\n", section, word_bits);
+
+	return count;
 }
 
 /*
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 90f0b73..e5753bd 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -416,10 +416,18 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
 		dimm->cschannel = chn;
 
 		/* Increment csrow location */
-		row++;
-		if (row == tot_csrows) {
-			row = 0;
+		if (layers[0].is_virt_csrow) {
 			chn++;
+			if (chn == tot_channels) {
+				chn = 0;
+				row++;
+			}
+		} else {
+			row++;
+			if (row == tot_csrows) {
+				row = 0;
+				chn++;
+			}
 		}
 
 		/* Increment dimm location */
@@ -433,13 +441,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
 
 	mci->op_state = OP_ALLOC;
 
-	/* at this point, the root kobj is valid, and in order to
-	 * 'free' the object, then the function:
-	 *      edac_mc_unregister_sysfs_main_kobj() must be called
-	 * which will perform kobj unregistration and the actual free
-	 * will occur during the kobject callback operation
-	 */
-
 	return mci;
 
 error:
@@ -966,20 +967,22 @@ static void edac_ce_error(struct mem_ctl_info *mci,
 			  long grain)
 {
 	unsigned long remapped_page;
+	char *msg_aux = "";
+
+	if (*msg)
+		msg_aux = " ";
 
 	if (edac_mc_get_log_ce()) {
 		if (other_detail && *other_detail)
 			edac_mc_printk(mci, KERN_WARNING,
-				       "%d CE %s on %s (%s %s - %s)\n",
-				       error_count,
-				       msg, label, location,
-				       detail, other_detail);
+				       "%d CE %s%son %s (%s %s - %s)\n",
+				       error_count, msg, msg_aux, label,
+				       location, detail, other_detail);
 		else
 			edac_mc_printk(mci, KERN_WARNING,
-				       "%d CE %s on %s (%s %s)\n",
-				       error_count,
-				       msg, label, location,
-				       detail);
+				       "%d CE %s%son %s (%s %s)\n",
+				       error_count, msg, msg_aux, label,
+				       location, detail);
 	}
 	edac_inc_ce_error(mci, enable_per_layer_report, pos, error_count);
 
@@ -1014,27 +1017,31 @@ static void edac_ue_error(struct mem_ctl_info *mci,
 			  const char *other_detail,
 			  const bool enable_per_layer_report)
 {
+	char *msg_aux = "";
+
+	if (*msg)
+		msg_aux = " ";
+
 	if (edac_mc_get_log_ue()) {
 		if (other_detail && *other_detail)
 			edac_mc_printk(mci, KERN_WARNING,
-				       "%d UE %s on %s (%s %s - %s)\n",
-				       error_count,
-			               msg, label, location, detail,
-				       other_detail);
+				       "%d UE %s%son %s (%s %s - %s)\n",
+				       error_count, msg, msg_aux, label,
+				       location, detail, other_detail);
 		else
 			edac_mc_printk(mci, KERN_WARNING,
-				       "%d UE %s on %s (%s %s)\n",
-				       error_count,
-			               msg, label, location, detail);
+				       "%d UE %s%son %s (%s %s)\n",
+				       error_count, msg, msg_aux, label,
+				       location, detail);
 	}
 
 	if (edac_mc_get_panic_on_ue()) {
 		if (other_detail && *other_detail)
-			panic("UE %s on %s (%s%s - %s)\n",
-			      msg, label, location, detail, other_detail);
+			panic("UE %s%son %s (%s%s - %s)\n",
+			      msg, msg_aux, label, location, detail, other_detail);
 		else
-			panic("UE %s on %s (%s%s)\n",
-			      msg, label, location, detail);
+			panic("UE %s%son %s (%s%s)\n",
+			      msg, msg_aux, label, location, detail);
 	}
 
 	edac_inc_ue_error(mci, enable_per_layer_report, pos, error_count);
@@ -1093,10 +1100,6 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
 	 */
 	for (i = 0; i < mci->n_layers; i++) {
 		if (pos[i] >= (int)mci->layers[i].size) {
-			if (type == HW_EVENT_ERR_CORRECTED)
-				p = "CE";
-			else
-				p = "UE";
 
 			edac_mc_printk(mci, KERN_ERR,
 				       "INTERNAL ERROR: %s value is out of range (%d >= %d)\n",
@@ -1128,6 +1131,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
 	grain = 0;
 	p = label;
 	*p = '\0';
+
 	for (i = 0; i < mci->tot_dimms; i++) {
 		struct dimm_info *dimm = mci->dimms[i];
 
@@ -1179,6 +1183,12 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
 	if (!enable_per_layer_report) {
 		strcpy(label, "any memory");
 	} else {
+
+		if (mci->csbased) {
+			row  = top_layer;
+			chan = mid_layer;
+		}
+
 		edac_dbg(4, "csrow/channel to increment: (%d,%d)\n", row, chan);
 		if (p == label)
 			strcpy(label, "unknown memory");
@@ -1195,6 +1205,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
 
 	/* Fill the RAM location data */
 	p = location;
+
 	for (i = 0; i < mci->n_layers; i++) {
 		if (pos[i] < 0)
 			continue;
@@ -1207,7 +1218,6 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
 		*(p - 1) = '\0';
 
 	/* Report the error via the trace interface */
-
 	grain_bits = fls_long(grain) + 1;
 	trace_mc_event(type, msg, label, error_count,
 		       mci->mc_idx, top_layer, mid_layer, low_layer,
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index ed0bc07..de2df92 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -180,6 +180,9 @@ static ssize_t csrow_size_show(struct device *dev,
 	int i;
 	u32 nr_pages = 0;
 
+	if (csrow->mci->csbased)
+		return sprintf(data, "%u\n", PAGES_TO_MiB(csrow->nr_pages));
+
 	for (i = 0; i < csrow->nr_channels; i++)
 		nr_pages += csrow->channels[i]->dimm->nr_pages;
 	return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages));
@@ -373,6 +376,7 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
 	csrow->dev.bus = &mci->bus;
 	device_initialize(&csrow->dev);
 	csrow->dev.parent = &mci->dev;
+	csrow->mci = mci;
 	dev_set_name(&csrow->dev, "csrow%d", index);
 	dev_set_drvdata(&csrow->dev, csrow);
 
@@ -777,10 +781,14 @@ static ssize_t mci_size_mb_show(struct device *dev,
 	for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) {
 		struct csrow_info *csrow = mci->csrows[csrow_idx];
 
-		for (j = 0; j < csrow->nr_channels; j++) {
-			struct dimm_info *dimm = csrow->channels[j]->dimm;
+		if (csrow->mci->csbased) {
+			total_pages += csrow->nr_pages;
+		} else {
+			for (j = 0; j < csrow->nr_channels; j++) {
+				struct dimm_info *dimm = csrow->channels[j]->dimm;
 
-			total_pages += dimm->nr_pages;
+				total_pages += dimm->nr_pages;
+			}
 		}
 	}
 
@@ -838,14 +846,8 @@ static ssize_t edac_fake_inject_write(struct file *file,
 	return count;
 }
 
-static int debugfs_open(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
 static const struct file_operations debug_fake_inject_fops = {
-	.open = debugfs_open,
+	.open = simple_open,
 	.write = edac_fake_inject_write,
 	.llseek = generic_file_llseek,
 };
@@ -1124,10 +1126,15 @@ int __init edac_mc_sysfs_init(void)
 	edac_subsys = edac_get_sysfs_subsys();
 	if (edac_subsys == NULL) {
 		edac_dbg(1, "no edac_subsys\n");
-		return -EINVAL;
+		err = -EINVAL;
+		goto out;
 	}
 
 	mci_pdev = kzalloc(sizeof(*mci_pdev), GFP_KERNEL);
+	if (!mci_pdev) {
+		err = -ENOMEM;
+		goto out_put_sysfs;
+	}
 
 	mci_pdev->bus = edac_subsys;
 	mci_pdev->type = &mc_attr_type;
@@ -1136,11 +1143,18 @@ int __init edac_mc_sysfs_init(void)
 
 	err = device_add(mci_pdev);
 	if (err < 0)
-		return err;
+		goto out_dev_free;
 
 	edac_dbg(0, "device %s created\n", dev_name(mci_pdev));
 
 	return 0;
+
+ out_dev_free:
+	kfree(mci_pdev);
+ out_put_sysfs:
+	edac_put_sysfs_subsys();
+ out:
+	return err;
 }
 
 void __exit edac_mc_sysfs_exit(void)
@@ -1148,4 +1162,5 @@ void __exit edac_mc_sysfs_exit(void)
 	put_device(mci_pdev);
 	device_del(mci_pdev);
 	edac_put_sysfs_subsys();
+	kfree(mci_pdev);
 }
diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c
index 58a28d8..12c951a 100644
--- a/drivers/edac/edac_module.c
+++ b/drivers/edac/edac_module.c
@@ -18,9 +18,29 @@
 #define EDAC_VERSION "Ver: 3.0.0"
 
 #ifdef CONFIG_EDAC_DEBUG
+
+static int edac_set_debug_level(const char *buf, struct kernel_param *kp)
+{
+	unsigned long val;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &val);
+	if (ret)
+		return ret;
+
+	if (val < 0 || val > 4)
+		return -EINVAL;
+
+	return param_set_int(buf, kp);
+}
+
 /* Values of 0 to 4 will generate output */
 int edac_debug_level = 2;
 EXPORT_SYMBOL_GPL(edac_debug_level);
+
+module_param_call(edac_debug_level, edac_set_debug_level, param_get_int,
+		  &edac_debug_level, 0644);
+MODULE_PARM_DESC(edac_debug_level, "EDAC debug level: [0-4], default: 2");
 #endif
 
 /* scope is to module level only */
@@ -132,10 +152,3 @@ module_exit(edac_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Doug Thompson www.softwarebitmaker.com, et al");
 MODULE_DESCRIPTION("Core library routines for EDAC reporting");
-
-/* refer to *_sysfs.c files for parameters that are exported via sysfs */
-
-#ifdef CONFIG_EDAC_DEBUG
-module_param(edac_debug_level, int, 0644);
-MODULE_PARM_DESC(edac_debug_level, "Debug level");
-#endif
diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c
index ee87ef9..dd370f9 100644
--- a/drivers/edac/edac_pci.c
+++ b/drivers/edac/edac_pci.c
@@ -470,7 +470,8 @@ struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev,
 
 	pci->mod_name = mod_name;
 	pci->ctl_name = EDAC_PCI_GENCTL_NAME;
-	pci->edac_check = edac_pci_generic_check;
+	if (edac_op_state == EDAC_OPSTATE_POLL)
+		pci->edac_check = edac_pci_generic_check;
 
 	pdata->edac_idx = edac_pci_idx++;
 
diff --git a/drivers/edac/highbank_mc_edac.c b/drivers/edac/highbank_mc_edac.c
index c769f47..7ea4cc2 100644
--- a/drivers/edac/highbank_mc_edac.c
+++ b/drivers/edac/highbank_mc_edac.c
@@ -113,14 +113,8 @@ static ssize_t highbank_mc_err_inject_write(struct file *file,
 	return count;
 }
 
-static int debugfs_open(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
 static const struct file_operations highbank_mc_debug_inject_fops = {
-	.open = debugfs_open,
+	.open = simple_open,
 	.write = highbank_mc_err_inject_write,
 	.llseek = generic_file_llseek,
 };
diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c
index a09d066..9d669cd 100644
--- a/drivers/edac/i7300_edac.c
+++ b/drivers/edac/i7300_edac.c
@@ -197,8 +197,8 @@ static const char *ferr_fat_fbd_name[] = {
 	[0]  = "Memory Write error on non-redundant retry or "
 	       "FBD configuration Write error on retry",
 };
-#define GET_FBD_FAT_IDX(fbderr)	(fbderr & (3 << 28))
-#define FERR_FAT_FBD_ERR_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3))
+#define GET_FBD_FAT_IDX(fbderr)	(((fbderr) >> 28) & 3)
+#define FERR_FAT_FBD_ERR_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 22))
 
 #define FERR_NF_FBD	0xa0
 static const char *ferr_nf_fbd_name[] = {
@@ -225,7 +225,7 @@ static const char *ferr_nf_fbd_name[] = {
 	[1]  = "Aliased Uncorrectable Non-Mirrored Demand Data ECC",
 	[0]  = "Uncorrectable Data ECC on Replay",
 };
-#define GET_FBD_NF_IDX(fbderr)	(fbderr & (3 << 28))
+#define GET_FBD_NF_IDX(fbderr)	(((fbderr) >> 28) & 3)
 #define FERR_NF_FBD_ERR_MASK ((1 << 24) | (1 << 23) | (1 << 22) | (1 << 21) |\
 			      (1 << 18) | (1 << 17) | (1 << 16) | (1 << 15) |\
 			      (1 << 14) | (1 << 13) | (1 << 11) | (1 << 10) |\
@@ -464,7 +464,7 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
 		errnum = find_first_bit(&errors,
 					ARRAY_SIZE(ferr_nf_fbd_name));
 		specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum);
-		branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0;
+		branch = (GET_FBD_NF_IDX(error_reg) == 2) ? 1 : 0;
 
 		pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
 			REDMEMA, &syndrome);
diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c
index 069e26c..082e91e 100644
--- a/drivers/edac/i82975x_edac.c
+++ b/drivers/edac/i82975x_edac.c
@@ -6,7 +6,17 @@
  * GNU General Public License.
  *
  * Written by Arvind R.
- *   Copied from i82875p_edac.c source:
+ *   Copied from i82875p_edac.c source,
+ *
+ * (c) 2012 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *	Driver re-written in order to fix lots of issues on it:
+ *		- Fix Single Mode;
+ *		- Add support for Asymetrical mode
+ *		- Fix several issues with Interleaved mode
+ *		- Fix memory label logic
+ *
+ * Intel datasheet: Intel(R) 975X Express Chipset Datasheet
+ *	http://www.intel.com/assets/pdf/datasheet/310158.pdf
  */
 
 #include <linux/module.h>
@@ -29,8 +39,8 @@
 #define PCI_DEVICE_ID_INTEL_82975_0	0x277c
 #endif				/* PCI_DEVICE_ID_INTEL_82975_0 */
 
-#define I82975X_NR_DIMMS		8
-#define I82975X_NR_CSROWS(nr_chans)	(I82975X_NR_DIMMS / (nr_chans))
+#define DIMMS_PER_CHANNEL	4
+#define NUM_CHANNELS		2
 
 /* Intel 82975X register addresses - device 0 function 0 - DRAM Controller */
 #define I82975X_EAP		0x58	/* Dram Error Address Pointer (32b)
@@ -112,7 +122,7 @@ NOTE: Only ONE of the three must be enabled
 /* NOTE: Following addresses have to indexed using MCHBAR offset (44h, 32b) */
 /* Intel 82975x memory mapped register space */
 
-#define I82975X_DRB_SHIFT 25	/* fixed 32MiB grain */
+#define I82975X_DRB_SHIFT 25	/* fixed 2^25 = 32 MiB grain */
 
 #define I82975X_DRB		0x100	/* DRAM Row Boundary (8b x 8)
 					 *
@@ -152,6 +162,10 @@ NOTE: Only ONE of the three must be enabled
 #define I82975X_DRA_CH1R01		0x188
 #define I82975X_DRA_CH1R23		0x189
 
+/* Channels 0/1 DRAM Timing Register 1 */
+#define I82975X_C0DRT1			0x114
+#define I82975X_C1DRT1			0x194
+
 
 #define I82975X_BNKARC	0x10e /* Type of device in each rank - Bank Arch (16b)
 					 *
@@ -206,8 +220,16 @@ enum i82975x_chips {
 	I82975X = 0,
 };
 
+struct mem_range {
+	u32 start, end;
+};
+
 struct i82975x_pvt {
-	void __iomem *mch_window;
+	void __iomem		*mch_window;
+	int 			num_channels;
+	bool			is_symetric;
+	u8			drb[DIMMS_PER_CHANNEL][NUM_CHANNELS];
+	struct mem_range	page[DIMMS_PER_CHANNEL][NUM_CHANNELS];
 };
 
 struct i82975x_dev_info {
@@ -278,8 +300,10 @@ static void i82975x_get_error_info(struct mem_ctl_info *mci,
 static int i82975x_process_error_info(struct mem_ctl_info *mci,
 		struct i82975x_error_info *info, int handle_errors)
 {
-	int row, chan;
-	unsigned long offst, page;
+	struct i82975x_pvt *pvt = mci->pvt_info;
+	struct mem_range	*range;
+	unsigned int		row, chan, grain;
+	unsigned long		offst, page;
 
 	if (!(info->errsts2 & 0x0003))
 		return 0;
@@ -293,36 +317,70 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci,
 		info->errsts = info->errsts2;
 	}
 
+	/* Calculate page and offset of the error */
+
 	page = (unsigned long) info->eap;
 	page >>= 1;
+
 	if (info->xeap & 1)
 		page |= 0x80000000;
 	page >>= (PAGE_SHIFT - 1);
-	row = edac_mc_find_csrow_by_page(mci, page);
-
-	if (row == -1)	{
-		i82975x_mc_printk(mci, KERN_ERR, "error processing EAP:\n"
-			"\tXEAP=%u\n"
-			"\t EAP=0x%08x\n"
-			"\tPAGE=0x%08x\n",
-			(info->xeap & 1) ? 1 : 0, info->eap, (unsigned int) page);
-		return 0;
+
+	if (pvt->is_symetric)
+		grain = 1 << 7;
+	else
+		grain = 1 << 6;
+
+	offst = info->eap & ((1 << PAGE_SHIFT) - (1 << grain));
+
+	/*
+	 * Search for the DIMM chip that match the error page.
+	 *
+	 * On Symmetric mode, this will always return channel = 0, as
+	 * both channel A and B ranges are identical.
+	 * A latter logic will determinte the channel on symetric mode
+	 *
+	 * On asymetric mode or single mode, there will be just one match,
+	 * that will point to the csrow with the error.
+	 */
+	for (chan = 0; chan < pvt->num_channels; chan++) {
+		for (row = 0; row < DIMMS_PER_CHANNEL; row++) {
+			range = &pvt->page[row][chan];
+
+			if (page >= range->start && page <= range->end)
+				goto found;
+		}
 	}
-	chan = (mci->csrows[row]->nr_channels == 1) ? 0 : info->eap & 1;
-	offst = info->eap
-			& ((1 << PAGE_SHIFT) -
-			   (1 << mci->csrows[row]->channels[chan]->dimm->grain));
+	chan = -1;
+	row = -1;
 
-	if (info->errsts & 0x0002)
+found:
+	if (info->errsts & 0x0002) {
+		/*
+		 * On uncorrected error, ECC doesn't allow do determine the
+		 * channel where the error has occurred.
+		 */
 		edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
 				     page, offst, 0,
 				     row, -1, -1,
 				     "i82975x UE", "");
-	else
-		edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
-				     page, offst, info->derrsyn,
-				     row, chan ? chan : 0, -1,
-				     "i82975x CE", "");
+		return 1;
+	}
+
+	if (pvt->is_symetric && row >= 0) {
+		/*
+		 * On Symetric mode, the memory switch happens after each
+		 * cache line (64 byte boundary). Channel 0 goes first.
+		 */
+		if (info->eap & (1 << 6))
+			chan = 1;
+		else
+			chan = 0;
+	}
+	edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
+				page, offst, info->derrsyn,
+				row, chan, -1,
+				"i82975x CE", "");
 
 	return 1;
 }
@@ -331,162 +389,214 @@ static void i82975x_check(struct mem_ctl_info *mci)
 {
 	struct i82975x_error_info info;
 
-	edac_dbg(1, "MC%d\n", mci->mc_idx);
+	edac_dbg(4, "MC%d\n", mci->mc_idx);
 	i82975x_get_error_info(mci, &info);
 	i82975x_process_error_info(mci, &info, 1);
 }
 
-/* Return 1 if dual channel mode is active.  Else return 0. */
-static int dual_channel_active(void __iomem *mch_window)
+/**
+ * detect_memory_style - Detect on what mode the memory controller is programmed
+ *
+ * @pvt:		pointer to the private structure
+ *
+ * This function detects how many channels are in use, and if the memory
+ * controller is in symetric (interleaved) or asymetric mode. There's no
+ * need to distinguish between asymetric and single mode, as the routines
+ * that fill the csrows data and handle error are written in order to handle
+ * both at the same way.
+ */
+static void detect_memory_style(struct i82975x_pvt *pvt)
 {
-	/*
-	 * We treat interleaved-symmetric configuration as dual-channel - EAP's
-	 * bit-0 giving the channel of the error location.
-	 *
-	 * All other configurations are treated as single channel - the EAP's
-	 * bit-0 will resolve ok in symmetric area of mixed
-	 * (symmetric/asymmetric) configurations
-	 */
-	u8	drb[4][2];
 	int	row;
-	int    dualch;
+	bool has_chan_a = false;
+	bool has_chan_b = false;
 
-	for (dualch = 1, row = 0; dualch && (row < 4); row++) {
-		drb[row][0] = readb(mch_window + I82975X_DRB + row);
-		drb[row][1] = readb(mch_window + I82975X_DRB + row + 0x80);
-		dualch = dualch && (drb[row][0] == drb[row][1]);
+	pvt->is_symetric = true;
+	pvt->num_channels = 0;
+
+	for (row = 0; row < DIMMS_PER_CHANNEL; row++) {
+		pvt->drb[row][0] = readb(pvt->mch_window + I82975X_DRB + row);
+		pvt->drb[row][1] = readb(pvt->mch_window + I82975X_DRB + row + 0x80);
+
+		/* On symetric mode, both channels have the same boundaries */
+		if (pvt->drb[row][0] != pvt->drb[row][1])
+			pvt->is_symetric = false;
+
+		if (pvt->drb[row][0])
+			has_chan_a = true;
+		if (pvt->drb[row][1])
+			has_chan_b = true;
 	}
-	return dualch;
-}
 
-static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank)
-{
-	/*
-	 * ECC is possible on i92975x ONLY with DEV_X8
-	 */
-	return DEV_X8;
+	if (has_chan_a)
+		pvt->num_channels++;
+
+	if (has_chan_b)
+		pvt->num_channels++;
 }
 
 static void i82975x_init_csrows(struct mem_ctl_info *mci,
-		struct pci_dev *pdev, void __iomem *mch_window)
+				struct i82975x_pvt *pvt,
+				struct pci_dev *pdev)
 {
-	static const char *labels[4] = {
-							"DIMM A1", "DIMM A2",
-							"DIMM B1", "DIMM B2"
-						};
-	struct csrow_info *csrow;
-	unsigned long last_cumul_size;
-	u8 value;
-	u32 cumul_size, nr_pages;
-	int index, chan;
-	struct dimm_info *dimm;
-	enum dev_type dtype;
-
-	last_cumul_size = 0;
+	struct dimm_info	*dimm;
+	struct mem_range	*range;
+	u8			boundary;
+	u32			initial_page = 0, last_page;
+	int			row, chan;
 
 	/*
-	 * 82875 comment:
-	 * The dram row boundary (DRB) reg values are boundary address
-	 * for each DRAM row with a granularity of 32 or 64MB (single/dual
-	 * channel operation).  DRB regs are cumulative; therefore DRB7 will
-	 * contain the total memory contained in all rows.
-	 *
+	 * This chipset provides 3 address modes:
+	 * Single channel - either Channel A or channel B is filled
+	 * Dual channel, interleaved: Memory is organized in pairs,
+	 * 	where channel A gets the lower address for each pair
+	 * Dual channel, asymmetric: Channel A memory goes first.
+	 * In order to cover all modes, we need to start describing
+	 * memories considering the dual channel, asymmetric one.
 	 */
 
-	for (index = 0; index < mci->nr_csrows; index++) {
-		csrow = mci->csrows[index];
-
-		value = readb(mch_window + I82975X_DRB + index +
-					((index >= 4) ? 0x80 : 0));
-		cumul_size = value;
-		cumul_size <<= (I82975X_DRB_SHIFT - PAGE_SHIFT);
-		/*
-		 * Adjust cumul_size w.r.t number of channels
-		 *
-		 */
-		if (csrow->nr_channels > 1)
-			cumul_size <<= 1;
-		edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size);
-
-		nr_pages = cumul_size - last_cumul_size;
-		if (!nr_pages)
-			continue;
-
+	for (chan = 0; chan < pvt->num_channels; chan++) {
 		/*
-		 * Initialise dram labels
-		 * index values:
-		 *   [0-7] for single-channel; i.e. csrow->nr_channels = 1
-		 *   [0-3] for dual-channel; i.e. csrow->nr_channels = 2
+		 * On symetric mode, both channels start from address 0
 		 */
-		dtype = i82975x_dram_type(mch_window, index);
-		for (chan = 0; chan < csrow->nr_channels; chan++) {
-			dimm = mci->csrows[index]->channels[chan]->dimm;
-
-			dimm->nr_pages = nr_pages / csrow->nr_channels;
-			strncpy(csrow->channels[chan]->dimm->label,
-					labels[(index >> 1) + (chan * 2)],
-					EDAC_MC_LABEL_LEN);
-			dimm->grain = 1 << 7;	/* 128Byte cache-line resolution */
-			dimm->dtype = i82975x_dram_type(mch_window, index);
+		if (pvt->is_symetric)
+			initial_page = 0;
+
+		for (row = 0; row < DIMMS_PER_CHANNEL; row++) {
+			boundary = pvt->drb[row][chan];
+			dimm = mci->csrows[row]->channels[chan]->dimm;
+
+			last_page = boundary << (I82975X_DRB_SHIFT - PAGE_SHIFT);
+			dimm->nr_pages = last_page - initial_page;
+			if (!dimm->nr_pages)
+				continue;
+
+			range = &pvt->page[row][chan];
+			range->start = initial_page;
+			range->end = range->start + dimm->nr_pages - 1;
+
+			/*
+			 * Grain is one cache-line:
+			 * On dual symetric mode, it is 128 Bytes;
+			 * On single mode or asymetric, it is 64 bytes.
+			 */
+			if (pvt->is_symetric) {
+				dimm->grain = 1 << 7;
+
+				/*
+				 * In dual interleaved mode, the addresses
+				 * need to be multiplied by 2, as both
+				 * channels are interlaced, and the boundary
+				 * limit there actually match each DIMM size
+				 */
+				range->start <<= 1;
+				range->end <<= 1;
+			} else {
+				dimm->grain = 1 << 6;
+			}
+
+			snprintf(dimm->label,
+				 EDAC_MC_LABEL_LEN, "DIMM %c%d",
+				 (chan == 0) ? 'A' : 'B', row);
 			dimm->mtype = MEM_DDR2; /* I82975x supports only DDR2 */
 			dimm->edac_mode = EDAC_SECDED; /* only supported */
-		}
 
-		csrow->first_page = last_cumul_size;
-		csrow->last_page = cumul_size - 1;
-		last_cumul_size = cumul_size;
+			/*
+			 * This chipset supports both x8 and x16 memories,
+			 * but datasheet doesn't describe how to distinguish
+			 * between them.
+			 *
+			 * Also, the "Rank" comment at initial_page 17 says that
+			 * ECC is only available with x8 memories. As this
+			 * driver doesn't even initialize without ECC, better
+			 * to assume that everything is x8. This is not
+			 * actually true, on a mixed ECC/non-ECC scenario.
+			 */
+			dimm->dtype = DEV_X8;
+
+			edac_dbg(1,
+				 "%s: from page 0x%08x to 0x%08x (size: 0x%08x pages)\n",
+				 dimm->label,
+				 range->start, range->end,
+				 dimm->nr_pages);
+			initial_page = last_page;
+		}
 	}
 }
 
-/* #define  i82975x_DEBUG_IOMEM */
-
-#ifdef i82975x_DEBUG_IOMEM
-static void i82975x_print_dram_timings(void __iomem *mch_window)
+static void i82975x_print_dram_config(struct i82975x_pvt *pvt,
+				      u32 mchbar, u32 *drc)
 {
+#ifdef CONFIG_EDAC_DEBUG
 	/*
 	 * The register meanings are from Intel specs;
 	 * (shows 13-5-5-5 for 800-DDR2)
 	 * Asus P5W Bios reports 15-5-4-4
 	 * What's your religion?
 	 */
-	static const int caslats[4] = { 5, 4, 3, 6 };
-	u32	dtreg[2];
-
-	dtreg[0] = readl(mch_window + 0x114);
-	dtreg[1] = readl(mch_window + 0x194);
-	i82975x_printk(KERN_INFO, "DRAM Timings :     Ch0    Ch1\n"
-		"                RAS Active Min = %d     %d\n"
-		"                CAS latency    =  %d      %d\n"
-		"                RAS to CAS     =  %d      %d\n"
-		"                RAS precharge  =  %d      %d\n",
-		(dtreg[0] >> 19 ) & 0x0f,
-			(dtreg[1] >> 19) & 0x0f,
-		caslats[(dtreg[0] >> 8) & 0x03],
-			caslats[(dtreg[1] >> 8) & 0x03],
-		((dtreg[0] >> 4) & 0x07) + 2,
-			((dtreg[1] >> 4) & 0x07) + 2,
-		(dtreg[0] & 0x07) + 2,
-			(dtreg[1] & 0x07) + 2
-	);
+	static const int	caslats[4] = { 5, 4, 3, 6 };
+	u32			dtreg[2];
+	int			row;
 
-}
+	/* Show memory config if debug level is 1 or upper */
+	if (!edac_debug_level)
+		return;
+
+	i82975x_printk(KERN_INFO, "MCHBAR real = %0x, remapped = %p\n",
+		       mchbar, pvt->mch_window);
+
+	for (row = 0; row < DIMMS_PER_CHANNEL; row++) {
+		if (row)
+			/* Only show if at least one bank is filled */
+			if ((pvt->drb[row][0] == pvt->drb[row-1][0]) &&
+			    (pvt->drb[row][1] == pvt->drb[row-1][1]))
+				continue;
+
+		i82975x_printk(KERN_INFO,
+			       "DRAM%i Rank Boundary Address: Channel A: 0x%08x; Channel B: 0x%08x\n",
+			       row,
+			       pvt->drb[row][0],
+			       pvt->drb[row][1]);
+	}
+
+	i82975x_printk(KERN_INFO, "DRAM Controller mode Channel A: = 0x%08x (%s); Channel B: 0x%08x (%s)\n",
+		       drc[0],
+		       ((drc[0] >> 21) & 3) == 1 ?
+		       "ECC enabled" : "ECC disabled",
+		       drc[1],
+		       ((drc[1] >> 21) & 3) == 1 ?
+		       "ECC enabled" : "ECC disabled");
+
+	i82975x_printk(KERN_INFO, "Bank Architecture Channel A: 0x%08x, Channel B: 0x%08x\n",
+		       readw(pvt->mch_window + I82975X_C0BNKARC),
+		       readw(pvt->mch_window + I82975X_C1BNKARC));
+
+	dtreg[0] = readl(pvt->mch_window + I82975X_C0DRT1);
+	dtreg[1] = readl(pvt->mch_window + I82975X_C1DRT1);
+	i82975x_printk(KERN_INFO, "DRAM Timings :      ChA    ChB\n");
+	i82975x_printk(KERN_INFO, "  RAS Active Min =  %2d      %2d\n",
+		       (dtreg[0] >> 19 ) & 0x0f,(dtreg[1] >> 19) & 0x0f);
+	i82975x_printk(KERN_INFO, "  CAS latency    =  %2d      %2d\n",
+		       caslats[(dtreg[0] >> 8) & 0x03],
+		       caslats[(dtreg[1] >> 8) & 0x03]);
+	i82975x_printk(KERN_INFO, "  RAS to CAS     =  %2d      %2d\n",
+		       ((dtreg[0] >> 4) & 0x07) + 2,
+		       ((dtreg[1] >> 4) & 0x07) + 2);
+	i82975x_printk(KERN_INFO, "  RAS precharge  =  %2d      %2d\n",
+		(dtreg[0] & 0x07) + 2,
+		(dtreg[1] & 0x07) + 2);
 #endif
+}
 
 static int i82975x_probe1(struct pci_dev *pdev, int dev_idx)
 {
 	int rc = -ENODEV;
 	struct mem_ctl_info *mci;
 	struct edac_mc_layer layers[2];
-	struct i82975x_pvt *pvt;
-	void __iomem *mch_window;
+	struct i82975x_pvt tmp_pvt, *pvt;
 	u32 mchbar;
 	u32 drc[2];
 	struct i82975x_error_info discard;
-	int	chans;
-#ifdef i82975x_DEBUG_IOMEM
-	u8 c0drb[4];
-	u8 c1drb[4];
-#endif
 
 	edac_dbg(0, "\n");
 
@@ -496,60 +606,35 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx)
 		goto fail0;
 	}
 	mchbar &= 0xffffc000;	/* bits 31:14 used for 16K window */
-	mch_window = ioremap_nocache(mchbar, 0x1000);
+	tmp_pvt.mch_window = ioremap_nocache(mchbar, 0x1000);
+	if (!tmp_pvt.mch_window) {
+		i82975x_printk(KERN_ERR, "Couldn't map MCHBAR registers.\n");
+		rc = -ENOMEM;
+		goto fail0;
+	}
 
-#ifdef i82975x_DEBUG_IOMEM
-	i82975x_printk(KERN_INFO, "MCHBAR real = %0x, remapped = %p\n",
-					mchbar, mch_window);
-
-	c0drb[0] = readb(mch_window + I82975X_DRB_CH0R0);
-	c0drb[1] = readb(mch_window + I82975X_DRB_CH0R1);
-	c0drb[2] = readb(mch_window + I82975X_DRB_CH0R2);
-	c0drb[3] = readb(mch_window + I82975X_DRB_CH0R3);
-	c1drb[0] = readb(mch_window + I82975X_DRB_CH1R0);
-	c1drb[1] = readb(mch_window + I82975X_DRB_CH1R1);
-	c1drb[2] = readb(mch_window + I82975X_DRB_CH1R2);
-	c1drb[3] = readb(mch_window + I82975X_DRB_CH1R3);
-	i82975x_printk(KERN_INFO, "DRBCH0R0 = 0x%02x\n", c0drb[0]);
-	i82975x_printk(KERN_INFO, "DRBCH0R1 = 0x%02x\n", c0drb[1]);
-	i82975x_printk(KERN_INFO, "DRBCH0R2 = 0x%02x\n", c0drb[2]);
-	i82975x_printk(KERN_INFO, "DRBCH0R3 = 0x%02x\n", c0drb[3]);
-	i82975x_printk(KERN_INFO, "DRBCH1R0 = 0x%02x\n", c1drb[0]);
-	i82975x_printk(KERN_INFO, "DRBCH1R1 = 0x%02x\n", c1drb[1]);
-	i82975x_printk(KERN_INFO, "DRBCH1R2 = 0x%02x\n", c1drb[2]);
-	i82975x_printk(KERN_INFO, "DRBCH1R3 = 0x%02x\n", c1drb[3]);
-#endif
+	drc[0] = readl(tmp_pvt.mch_window + I82975X_DRC_CH0M0);
+	drc[1] = readl(tmp_pvt.mch_window + I82975X_DRC_CH1M0);
+
+	detect_memory_style(&tmp_pvt);
+	if (!tmp_pvt.num_channels) {
+		edac_dbg(3, "No memories installed? This shouldn't be running!\n");
+		goto fail0;
+	}
+
+	i82975x_print_dram_config(&tmp_pvt, mchbar, drc);
 
-	drc[0] = readl(mch_window + I82975X_DRC_CH0M0);
-	drc[1] = readl(mch_window + I82975X_DRC_CH1M0);
-#ifdef i82975x_DEBUG_IOMEM
-	i82975x_printk(KERN_INFO, "DRC_CH0 = %0x, %s\n", drc[0],
-			((drc[0] >> 21) & 3) == 1 ?
-				"ECC enabled" : "ECC disabled");
-	i82975x_printk(KERN_INFO, "DRC_CH1 = %0x, %s\n", drc[1],
-			((drc[1] >> 21) & 3) == 1 ?
-				"ECC enabled" : "ECC disabled");
-
-	i82975x_printk(KERN_INFO, "C0 BNKARC = %0x\n",
-		readw(mch_window + I82975X_C0BNKARC));
-	i82975x_printk(KERN_INFO, "C1 BNKARC = %0x\n",
-		readw(mch_window + I82975X_C1BNKARC));
-	i82975x_print_dram_timings(mch_window);
-	goto fail1;
-#endif
 	if (!(((drc[0] >> 21) & 3) == 1 || ((drc[1] >> 21) & 3) == 1)) {
 		i82975x_printk(KERN_INFO, "ECC disabled on both channels.\n");
 		goto fail1;
 	}
 
-	chans = dual_channel_active(mch_window) + 1;
-
 	/* assuming only one controller, index thus is 0 */
 	layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
-	layers[0].size = I82975X_NR_DIMMS;
+	layers[0].size = DIMMS_PER_CHANNEL;
 	layers[0].is_virt_csrow = true;
 	layers[1].type = EDAC_MC_LAYER_CHANNEL;
-	layers[1].size = I82975X_NR_CSROWS(chans);
+	layers[1].size = tmp_pvt.num_channels;
 	layers[1].is_virt_csrow = false;
 	mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt));
 	if (!mci) {
@@ -568,10 +653,12 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx)
 	mci->dev_name = pci_name(pdev);
 	mci->edac_check = i82975x_check;
 	mci->ctl_page_to_phys = NULL;
+
 	edac_dbg(3, "init pvt\n");
 	pvt = (struct i82975x_pvt *) mci->pvt_info;
-	pvt->mch_window = mch_window;
-	i82975x_init_csrows(mci, pdev, mch_window);
+	*pvt = tmp_pvt;
+
+	i82975x_init_csrows(mci, pvt, pdev);
 	mci->scrub_mode = SCRUB_HW_SRC;
 	i82975x_get_error_info(mci, &discard);  /* clear counters */
 
@@ -589,7 +676,7 @@ fail2:
 	edac_mc_free(mci);
 
 fail1:
-	iounmap(mch_window);
+	iounmap(tmp_pvt.mch_window);
 fail0:
 	return rc;
 }
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index d0c372e..ad63757 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -64,7 +64,7 @@ EXPORT_SYMBOL_GPL(to_msgs);
 const char * const ii_msgs[] = { "MEM", "RESV", "IO", "GEN" };
 EXPORT_SYMBOL_GPL(ii_msgs);
 
-static const char * const f15h_ic_mce_desc[] = {
+static const char * const f15h_mc1_mce_desc[] = {
 	"UC during a demand linefill from L2",
 	"Parity error during data load from IC",
 	"Parity error for IC valid bit",
@@ -84,7 +84,7 @@ static const char * const f15h_ic_mce_desc[] = {
 	"fetch address FIFO"
 };
 
-static const char * const f15h_cu_mce_desc[] = {
+static const char * const f15h_mc2_mce_desc[] = {
 	"Fill ECC error on data fills",			/* xec = 0x4 */
 	"Fill parity error on insn fills",
 	"Prefetcher request FIFO parity error",
@@ -101,7 +101,7 @@ static const char * const f15h_cu_mce_desc[] = {
 	"PRB address parity error"
 };
 
-static const char * const nb_mce_desc[] = {
+static const char * const mc4_mce_desc[] = {
 	"DRAM ECC error detected on the NB",
 	"CRC error detected on HT link",
 	"Link-defined sync error packets detected on HT link",
@@ -123,7 +123,7 @@ static const char * const nb_mce_desc[] = {
 	"ECC Error in the Probe Filter directory"
 };
 
-static const char * const fr_ex_mce_desc[] = {
+static const char * const mc5_mce_desc[] = {
 	"CPU Watchdog timer expire",
 	"Wakeup array dest tag",
 	"AG payload array",
@@ -139,7 +139,7 @@ static const char * const fr_ex_mce_desc[] = {
 	"DE error occurred"
 };
 
-static bool f12h_dc_mce(u16 ec, u8 xec)
+static bool f12h_mc0_mce(u16 ec, u8 xec)
 {
 	bool ret = false;
 
@@ -157,26 +157,26 @@ static bool f12h_dc_mce(u16 ec, u8 xec)
 	return ret;
 }
 
-static bool f10h_dc_mce(u16 ec, u8 xec)
+static bool f10h_mc0_mce(u16 ec, u8 xec)
 {
 	if (R4(ec) == R4_GEN && LL(ec) == LL_L1) {
 		pr_cont("during data scrub.\n");
 		return true;
 	}
-	return f12h_dc_mce(ec, xec);
+	return f12h_mc0_mce(ec, xec);
 }
 
-static bool k8_dc_mce(u16 ec, u8 xec)
+static bool k8_mc0_mce(u16 ec, u8 xec)
 {
 	if (BUS_ERROR(ec)) {
 		pr_cont("during system linefill.\n");
 		return true;
 	}
 
-	return f10h_dc_mce(ec, xec);
+	return f10h_mc0_mce(ec, xec);
 }
 
-static bool f14h_dc_mce(u16 ec, u8 xec)
+static bool f14h_mc0_mce(u16 ec, u8 xec)
 {
 	u8 r4	 = R4(ec);
 	bool ret = true;
@@ -228,7 +228,7 @@ static bool f14h_dc_mce(u16 ec, u8 xec)
 	return ret;
 }
 
-static bool f15h_dc_mce(u16 ec, u8 xec)
+static bool f15h_mc0_mce(u16 ec, u8 xec)
 {
 	bool ret = true;
 
@@ -275,12 +275,12 @@ static bool f15h_dc_mce(u16 ec, u8 xec)
 	return ret;
 }
 
-static void amd_decode_dc_mce(struct mce *m)
+static void decode_mc0_mce(struct mce *m)
 {
 	u16 ec = EC(m->status);
 	u8 xec = XEC(m->status, xec_mask);
 
-	pr_emerg(HW_ERR "Data Cache Error: ");
+	pr_emerg(HW_ERR "MC0 Error: ");
 
 	/* TLB error signatures are the same across families */
 	if (TLB_ERROR(ec)) {
@@ -290,13 +290,13 @@ static void amd_decode_dc_mce(struct mce *m)
 					    : (xec ? "multimatch" : "parity")));
 			return;
 		}
-	} else if (fam_ops->dc_mce(ec, xec))
+	} else if (fam_ops->mc0_mce(ec, xec))
 		;
 	else
-		pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
+		pr_emerg(HW_ERR "Corrupted MC0 MCE info?\n");
 }
 
-static bool k8_ic_mce(u16 ec, u8 xec)
+static bool k8_mc1_mce(u16 ec, u8 xec)
 {
 	u8 ll	 = LL(ec);
 	bool ret = true;
@@ -330,7 +330,7 @@ static bool k8_ic_mce(u16 ec, u8 xec)
 	return ret;
 }
 
-static bool f14h_ic_mce(u16 ec, u8 xec)
+static bool f14h_mc1_mce(u16 ec, u8 xec)
 {
 	u8 r4    = R4(ec);
 	bool ret = true;
@@ -349,7 +349,7 @@ static bool f14h_ic_mce(u16 ec, u8 xec)
 	return ret;
 }
 
-static bool f15h_ic_mce(u16 ec, u8 xec)
+static bool f15h_mc1_mce(u16 ec, u8 xec)
 {
 	bool ret = true;
 
@@ -358,19 +358,19 @@ static bool f15h_ic_mce(u16 ec, u8 xec)
 
 	switch (xec) {
 	case 0x0 ... 0xa:
-		pr_cont("%s.\n", f15h_ic_mce_desc[xec]);
+		pr_cont("%s.\n", f15h_mc1_mce_desc[xec]);
 		break;
 
 	case 0xd:
-		pr_cont("%s.\n", f15h_ic_mce_desc[xec-2]);
+		pr_cont("%s.\n", f15h_mc1_mce_desc[xec-2]);
 		break;
 
 	case 0x10:
-		pr_cont("%s.\n", f15h_ic_mce_desc[xec-4]);
+		pr_cont("%s.\n", f15h_mc1_mce_desc[xec-4]);
 		break;
 
 	case 0x11 ... 0x14:
-		pr_cont("Decoder %s parity error.\n", f15h_ic_mce_desc[xec-4]);
+		pr_cont("Decoder %s parity error.\n", f15h_mc1_mce_desc[xec-4]);
 		break;
 
 	default:
@@ -379,12 +379,12 @@ static bool f15h_ic_mce(u16 ec, u8 xec)
 	return ret;
 }
 
-static void amd_decode_ic_mce(struct mce *m)
+static void decode_mc1_mce(struct mce *m)
 {
 	u16 ec = EC(m->status);
 	u8 xec = XEC(m->status, xec_mask);
 
-	pr_emerg(HW_ERR "Instruction Cache Error: ");
+	pr_emerg(HW_ERR "MC1 Error: ");
 
 	if (TLB_ERROR(ec))
 		pr_cont("%s TLB %s.\n", LL_MSG(ec),
@@ -393,18 +393,18 @@ static void amd_decode_ic_mce(struct mce *m)
 		bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
 
 		pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
-	} else if (fam_ops->ic_mce(ec, xec))
+	} else if (fam_ops->mc1_mce(ec, xec))
 		;
 	else
-		pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
+		pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n");
 }
 
-static void amd_decode_bu_mce(struct mce *m)
+static void decode_mc2_mce(struct mce *m)
 {
 	u16 ec = EC(m->status);
 	u8 xec = XEC(m->status, xec_mask);
 
-	pr_emerg(HW_ERR "Bus Unit Error");
+	pr_emerg(HW_ERR "MC2 Error");
 
 	if (xec == 0x1)
 		pr_cont(" in the write data buffers.\n");
@@ -429,24 +429,24 @@ static void amd_decode_bu_mce(struct mce *m)
 				pr_cont(": %s parity/ECC error during data "
 					"access from L2.\n", R4_MSG(ec));
 			else
-				goto wrong_bu_mce;
+				goto wrong_mc2_mce;
 		} else
-			goto wrong_bu_mce;
+			goto wrong_mc2_mce;
 	} else
-		goto wrong_bu_mce;
+		goto wrong_mc2_mce;
 
 	return;
 
-wrong_bu_mce:
-	pr_emerg(HW_ERR "Corrupted BU MCE info?\n");
+ wrong_mc2_mce:
+	pr_emerg(HW_ERR "Corrupted MC2 MCE info?\n");
 }
 
-static void amd_decode_cu_mce(struct mce *m)
+static void decode_f15_mc2_mce(struct mce *m)
 {
 	u16 ec = EC(m->status);
 	u8 xec = XEC(m->status, xec_mask);
 
-	pr_emerg(HW_ERR "Combined Unit Error: ");
+	pr_emerg(HW_ERR "MC2 Error: ");
 
 	if (TLB_ERROR(ec)) {
 		if (xec == 0x0)
@@ -454,63 +454,63 @@ static void amd_decode_cu_mce(struct mce *m)
 		else if (xec == 0x1)
 			pr_cont("Poison data provided for TLB fill.\n");
 		else
-			goto wrong_cu_mce;
+			goto wrong_f15_mc2_mce;
 	} else if (BUS_ERROR(ec)) {
 		if (xec > 2)
-			goto wrong_cu_mce;
+			goto wrong_f15_mc2_mce;
 
 		pr_cont("Error during attempted NB data read.\n");
 	} else if (MEM_ERROR(ec)) {
 		switch (xec) {
 		case 0x4 ... 0xc:
-			pr_cont("%s.\n", f15h_cu_mce_desc[xec - 0x4]);
+			pr_cont("%s.\n", f15h_mc2_mce_desc[xec - 0x4]);
 			break;
 
 		case 0x10 ... 0x14:
-			pr_cont("%s.\n", f15h_cu_mce_desc[xec - 0x7]);
+			pr_cont("%s.\n", f15h_mc2_mce_desc[xec - 0x7]);
 			break;
 
 		default:
-			goto wrong_cu_mce;
+			goto wrong_f15_mc2_mce;
 		}
 	}
 
 	return;
 
-wrong_cu_mce:
-	pr_emerg(HW_ERR "Corrupted CU MCE info?\n");
+ wrong_f15_mc2_mce:
+	pr_emerg(HW_ERR "Corrupted MC2 MCE info?\n");
 }
 
-static void amd_decode_ls_mce(struct mce *m)
+static void decode_mc3_mce(struct mce *m)
 {
 	u16 ec = EC(m->status);
 	u8 xec = XEC(m->status, xec_mask);
 
 	if (boot_cpu_data.x86 >= 0x14) {
-		pr_emerg("You shouldn't be seeing an LS MCE on this cpu family,"
+		pr_emerg("You shouldn't be seeing MC3 MCE on this cpu family,"
 			 " please report on LKML.\n");
 		return;
 	}
 
-	pr_emerg(HW_ERR "Load Store Error");
+	pr_emerg(HW_ERR "MC3 Error");
 
 	if (xec == 0x0) {
 		u8 r4 = R4(ec);
 
 		if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
-			goto wrong_ls_mce;
+			goto wrong_mc3_mce;
 
 		pr_cont(" during %s.\n", R4_MSG(ec));
 	} else
-		goto wrong_ls_mce;
+		goto wrong_mc3_mce;
 
 	return;
 
-wrong_ls_mce:
-	pr_emerg(HW_ERR "Corrupted LS MCE info?\n");
+ wrong_mc3_mce:
+	pr_emerg(HW_ERR "Corrupted MC3 MCE info?\n");
 }
 
-void amd_decode_nb_mce(struct mce *m)
+static void decode_mc4_mce(struct mce *m)
 {
 	struct cpuinfo_x86 *c = &boot_cpu_data;
 	int node_id = amd_get_nb_id(m->extcpu);
@@ -518,7 +518,7 @@ void amd_decode_nb_mce(struct mce *m)
 	u8 xec = XEC(m->status, 0x1f);
 	u8 offset = 0;
 
-	pr_emerg(HW_ERR "Northbridge Error (node %d): ", node_id);
+	pr_emerg(HW_ERR "MC4 Error (node %d): ", node_id);
 
 	switch (xec) {
 	case 0x0 ... 0xe:
@@ -527,9 +527,9 @@ void amd_decode_nb_mce(struct mce *m)
 		if (xec == 0x0 || xec == 0x8) {
 			/* no ECCs on F11h */
 			if (c->x86 == 0x11)
-				goto wrong_nb_mce;
+				goto wrong_mc4_mce;
 
-			pr_cont("%s.\n", nb_mce_desc[xec]);
+			pr_cont("%s.\n", mc4_mce_desc[xec]);
 
 			if (nb_bus_decoder)
 				nb_bus_decoder(node_id, m);
@@ -543,14 +543,14 @@ void amd_decode_nb_mce(struct mce *m)
 		else if (BUS_ERROR(ec))
 			pr_cont("DMA Exclusion Vector Table Walk error.\n");
 		else
-			goto wrong_nb_mce;
+			goto wrong_mc4_mce;
 		return;
 
 	case 0x19:
 		if (boot_cpu_data.x86 == 0x15)
 			pr_cont("Compute Unit Data Error.\n");
 		else
-			goto wrong_nb_mce;
+			goto wrong_mc4_mce;
 		return;
 
 	case 0x1c ... 0x1f:
@@ -558,46 +558,44 @@ void amd_decode_nb_mce(struct mce *m)
 		break;
 
 	default:
-		goto wrong_nb_mce;
+		goto wrong_mc4_mce;
 	}
 
-	pr_cont("%s.\n", nb_mce_desc[xec - offset]);
+	pr_cont("%s.\n", mc4_mce_desc[xec - offset]);
 	return;
 
-wrong_nb_mce:
-	pr_emerg(HW_ERR "Corrupted NB MCE info?\n");
+ wrong_mc4_mce:
+	pr_emerg(HW_ERR "Corrupted MC4 MCE info?\n");
 }
-EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
 
-static void amd_decode_fr_mce(struct mce *m)
+static void decode_mc5_mce(struct mce *m)
 {
 	struct cpuinfo_x86 *c = &boot_cpu_data;
 	u8 xec = XEC(m->status, xec_mask);
 
 	if (c->x86 == 0xf || c->x86 == 0x11)
-		goto wrong_fr_mce;
+		goto wrong_mc5_mce;
 
-	pr_emerg(HW_ERR "%s Error: ",
-		 (c->x86 == 0x15 ? "Execution Unit" : "FIROB"));
+	pr_emerg(HW_ERR "MC5 Error: ");
 
 	if (xec == 0x0 || xec == 0xc)
-		pr_cont("%s.\n", fr_ex_mce_desc[xec]);
+		pr_cont("%s.\n", mc5_mce_desc[xec]);
 	else if (xec < 0xd)
-		pr_cont("%s parity error.\n", fr_ex_mce_desc[xec]);
+		pr_cont("%s parity error.\n", mc5_mce_desc[xec]);
 	else
-		goto wrong_fr_mce;
+		goto wrong_mc5_mce;
 
 	return;
 
-wrong_fr_mce:
-	pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
+ wrong_mc5_mce:
+	pr_emerg(HW_ERR "Corrupted MC5 MCE info?\n");
 }
 
-static void amd_decode_fp_mce(struct mce *m)
+static void decode_mc6_mce(struct mce *m)
 {
 	u8 xec = XEC(m->status, xec_mask);
 
-	pr_emerg(HW_ERR "Floating Point Unit Error: ");
+	pr_emerg(HW_ERR "MC6 Error: ");
 
 	switch (xec) {
 	case 0x1:
@@ -621,7 +619,7 @@ static void amd_decode_fp_mce(struct mce *m)
 		break;
 
 	default:
-		goto wrong_fp_mce;
+		goto wrong_mc6_mce;
 		break;
 	}
 
@@ -629,8 +627,8 @@ static void amd_decode_fp_mce(struct mce *m)
 
 	return;
 
-wrong_fp_mce:
-	pr_emerg(HW_ERR "Corrupted FP MCE info?\n");
+ wrong_mc6_mce:
+	pr_emerg(HW_ERR "Corrupted MC6 MCE info?\n");
 }
 
 static inline void amd_decode_err_code(u16 ec)
@@ -669,74 +667,94 @@ static bool amd_filter_mce(struct mce *m)
 	return false;
 }
 
+static const char *decode_error_status(struct mce *m)
+{
+	if (m->status & MCI_STATUS_UC) {
+		if (m->status & MCI_STATUS_PCC)
+			return "System Fatal error.";
+		if (m->mcgstatus & MCG_STATUS_RIPV)
+			return "Uncorrected, software restartable error.";
+		return "Uncorrected, software containable error.";
+	}
+
+	if (m->status & MCI_STATUS_DEFERRED)
+		return "Deferred error.";
+
+	return "Corrected error, no action required.";
+}
+
 int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
 {
 	struct mce *m = (struct mce *)data;
-	struct cpuinfo_x86 *c = &boot_cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(m->extcpu);
 	int ecc;
 
 	if (amd_filter_mce(m))
 		return NOTIFY_STOP;
 
-	pr_emerg(HW_ERR "CPU:%d\tMC%d_STATUS[%s|%s|%s|%s|%s",
-		m->extcpu, m->bank,
-		((m->status & MCI_STATUS_OVER)	? "Over"  : "-"),
-		((m->status & MCI_STATUS_UC)	? "UE"	  : "CE"),
-		((m->status & MCI_STATUS_MISCV)	? "MiscV" : "-"),
-		((m->status & MCI_STATUS_PCC)	? "PCC"	  : "-"),
-		((m->status & MCI_STATUS_ADDRV)	? "AddrV" : "-"));
-
-	if (c->x86 == 0x15)
-		pr_cont("|%s|%s",
-			((m->status & BIT_64(44)) ? "Deferred" : "-"),
-			((m->status & BIT_64(43)) ? "Poison"   : "-"));
-
-	/* do the two bits[14:13] together */
-	ecc = (m->status >> 45) & 0x3;
-	if (ecc)
-		pr_cont("|%sECC", ((ecc == 2) ? "C" : "U"));
-
-	pr_cont("]: 0x%016llx\n", m->status);
-
-	if (m->status & MCI_STATUS_ADDRV)
-		pr_emerg(HW_ERR "\tMC%d_ADDR: 0x%016llx\n", m->bank, m->addr);
-
 	switch (m->bank) {
 	case 0:
-		amd_decode_dc_mce(m);
+		decode_mc0_mce(m);
 		break;
 
 	case 1:
-		amd_decode_ic_mce(m);
+		decode_mc1_mce(m);
 		break;
 
 	case 2:
 		if (c->x86 == 0x15)
-			amd_decode_cu_mce(m);
+			decode_f15_mc2_mce(m);
 		else
-			amd_decode_bu_mce(m);
+			decode_mc2_mce(m);
 		break;
 
 	case 3:
-		amd_decode_ls_mce(m);
+		decode_mc3_mce(m);
 		break;
 
 	case 4:
-		amd_decode_nb_mce(m);
+		decode_mc4_mce(m);
 		break;
 
 	case 5:
-		amd_decode_fr_mce(m);
+		decode_mc5_mce(m);
 		break;
 
 	case 6:
-		amd_decode_fp_mce(m);
+		decode_mc6_mce(m);
 		break;
 
 	default:
 		break;
 	}
 
+	pr_emerg(HW_ERR "Error Status: %s\n", decode_error_status(m));
+
+	pr_emerg(HW_ERR "CPU:%d (%x:%x:%x) MC%d_STATUS[%s|%s|%s|%s|%s",
+		m->extcpu,
+		c->x86, c->x86_model, c->x86_mask,
+		m->bank,
+		((m->status & MCI_STATUS_OVER)	? "Over"  : "-"),
+		((m->status & MCI_STATUS_UC)	? "UE"	  : "CE"),
+		((m->status & MCI_STATUS_MISCV)	? "MiscV" : "-"),
+		((m->status & MCI_STATUS_PCC)	? "PCC"	  : "-"),
+		((m->status & MCI_STATUS_ADDRV)	? "AddrV" : "-"));
+
+	if (c->x86 == 0x15)
+		pr_cont("|%s|%s",
+			((m->status & MCI_STATUS_DEFERRED) ? "Deferred" : "-"),
+			((m->status & MCI_STATUS_POISON)   ? "Poison"   : "-"));
+
+	/* do the two bits[14:13] together */
+	ecc = (m->status >> 45) & 0x3;
+	if (ecc)
+		pr_cont("|%sECC", ((ecc == 2) ? "C" : "U"));
+
+	pr_cont("]: 0x%016llx\n", m->status);
+
+	if (m->status & MCI_STATUS_ADDRV)
+		pr_emerg(HW_ERR "MC%d_ADDR: 0x%016llx\n", m->bank, m->addr);
+
 	amd_decode_err_code(m->status & 0xffff);
 
 	return NOTIFY_STOP;
@@ -763,35 +781,35 @@ static int __init mce_amd_init(void)
 
 	switch (c->x86) {
 	case 0xf:
-		fam_ops->dc_mce = k8_dc_mce;
-		fam_ops->ic_mce = k8_ic_mce;
+		fam_ops->mc0_mce = k8_mc0_mce;
+		fam_ops->mc1_mce = k8_mc1_mce;
 		break;
 
 	case 0x10:
-		fam_ops->dc_mce = f10h_dc_mce;
-		fam_ops->ic_mce = k8_ic_mce;
+		fam_ops->mc0_mce = f10h_mc0_mce;
+		fam_ops->mc1_mce = k8_mc1_mce;
 		break;
 
 	case 0x11:
-		fam_ops->dc_mce = k8_dc_mce;
-		fam_ops->ic_mce = k8_ic_mce;
+		fam_ops->mc0_mce = k8_mc0_mce;
+		fam_ops->mc1_mce = k8_mc1_mce;
 		break;
 
 	case 0x12:
-		fam_ops->dc_mce = f12h_dc_mce;
-		fam_ops->ic_mce = k8_ic_mce;
+		fam_ops->mc0_mce = f12h_mc0_mce;
+		fam_ops->mc1_mce = k8_mc1_mce;
 		break;
 
 	case 0x14:
 		nb_err_cpumask  = 0x3;
-		fam_ops->dc_mce = f14h_dc_mce;
-		fam_ops->ic_mce = f14h_ic_mce;
+		fam_ops->mc0_mce = f14h_mc0_mce;
+		fam_ops->mc1_mce = f14h_mc1_mce;
 		break;
 
 	case 0x15:
 		xec_mask = 0x1f;
-		fam_ops->dc_mce = f15h_dc_mce;
-		fam_ops->ic_mce = f15h_ic_mce;
+		fam_ops->mc0_mce = f15h_mc0_mce;
+		fam_ops->mc1_mce = f15h_mc1_mce;
 		break;
 
 	default:
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h
index 8c87a5e..6796799 100644
--- a/drivers/edac/mce_amd.h
+++ b/drivers/edac/mce_amd.h
@@ -29,10 +29,8 @@
 #define R4(x)				(((x) >> 4) & 0xf)
 #define R4_MSG(x)			((R4(x) < 9) ?  rrrr_msgs[R4(x)] : "Wrong R4!")
 
-/*
- * F3x4C bits (MCi_STATUS' high half)
- */
-#define NBSH_ERR_CPU_VAL		BIT(24)
+#define MCI_STATUS_DEFERRED		BIT_64(44)
+#define MCI_STATUS_POISON		BIT_64(43)
 
 enum tt_ids {
 	TT_INSTR = 0,
@@ -78,14 +76,13 @@ extern const char * const ii_msgs[];
  * per-family decoder ops
  */
 struct amd_decoder_ops {
-	bool (*dc_mce)(u16, u8);
-	bool (*ic_mce)(u16, u8);
+	bool (*mc0_mce)(u16, u8);
+	bool (*mc1_mce)(u16, u8);
 };
 
 void amd_report_gart_errors(bool);
 void amd_register_ecc_decoder(void (*f)(int, struct mce *));
 void amd_unregister_ecc_decoder(void (*f)(int, struct mce *));
-void amd_decode_nb_mce(struct mce *);
 int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data);
 
 #endif /* _EDAC_MCE_AMD_H */
diff --git a/drivers/edac/octeon_edac-l2c.c b/drivers/edac/octeon_edac-l2c.c
new file mode 100644
index 0000000..5f459aa
--- /dev/null
+++ b/drivers/edac/octeon_edac-l2c.c
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/edac.h>
+
+#include <asm/octeon/cvmx.h>
+
+#include "edac_core.h"
+#include "edac_module.h"
+
+#define EDAC_MOD_STR "octeon-l2c"
+
+static void co_l2c_poll(struct edac_device_ctl_info *l2c)
+{
+	union cvmx_l2t_err l2t_err;
+
+	l2t_err.u64 = cvmx_read_csr(CVMX_L2T_ERR);
+	if (l2t_err.s.sec_err) {
+		edac_device_handle_ce(l2c, 0, 0,
+				      "Single bit error (corrected)");
+		l2t_err.s.sec_err = 1;		/* Reset */
+		cvmx_write_csr(CVMX_L2T_ERR, l2t_err.u64);
+	}
+	if (l2t_err.s.ded_err) {
+		edac_device_handle_ue(l2c, 0, 0,
+				      "Double bit error (corrected)");
+		l2t_err.s.ded_err = 1;		/* Reset */
+		cvmx_write_csr(CVMX_L2T_ERR, l2t_err.u64);
+	}
+}
+
+static int __devinit co_l2c_probe(struct platform_device *pdev)
+{
+	struct edac_device_ctl_info *l2c;
+	union cvmx_l2t_err l2t_err;
+	int res = 0;
+
+	l2c = edac_device_alloc_ctl_info(0, "l2c", 1, NULL, 0, 0,
+					 NULL, 0, edac_device_alloc_index());
+	if (!l2c)
+		return -ENOMEM;
+
+	l2c->dev = &pdev->dev;
+	platform_set_drvdata(pdev, l2c);
+	l2c->dev_name = dev_name(&pdev->dev);
+
+	l2c->mod_name = "octeon-l2c";
+	l2c->ctl_name = "octeon_l2c_err";
+	l2c->edac_check = co_l2c_poll;
+
+	if (edac_device_add_device(l2c) > 0) {
+		pr_err("%s: edac_device_add_device() failed\n", __func__);
+		goto err;
+	}
+
+	l2t_err.u64 = cvmx_read_csr(CVMX_L2T_ERR);
+	l2t_err.s.sec_intena = 0;	/* We poll */
+	l2t_err.s.ded_intena = 0;
+	l2t_err.s.sec_err = 1;		/* Clear, just in case */
+	l2t_err.s.ded_err = 1;
+	cvmx_write_csr(CVMX_L2T_ERR, l2t_err.u64);
+
+	return 0;
+
+err:
+	edac_device_free_ctl_info(l2c);
+
+	return res;
+}
+
+static int co_l2c_remove(struct platform_device *pdev)
+{
+	struct edac_device_ctl_info *l2c = platform_get_drvdata(pdev);
+
+	edac_device_del_device(&pdev->dev);
+	edac_device_free_ctl_info(l2c);
+
+	return 0;
+}
+
+static struct platform_driver co_l2c_driver = {
+	.probe = co_l2c_probe,
+	.remove = co_l2c_remove,
+	.driver = {
+		   .name = "co_l2c_edac",
+	}
+};
+
+static int __init co_edac_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&co_l2c_driver);
+	if (ret)
+		pr_warning(EDAC_MOD_STR " EDAC failed to register\n");
+
+	return ret;
+}
+
+static void __exit co_edac_exit(void)
+{
+	platform_driver_unregister(&co_l2c_driver);
+}
+
+module_init(co_edac_init);
+module_exit(co_edac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
diff --git a/drivers/edac/octeon_edac-lmc.c b/drivers/edac/octeon_edac-lmc.c
new file mode 100644
index 0000000..e0c1e44
--- /dev/null
+++ b/drivers/edac/octeon_edac-lmc.c
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/edac.h>
+
+#include <asm/octeon/cvmx.h>
+
+#include "edac_core.h"
+#include "edac_module.h"
+#include "octeon_edac-lmc.h"
+
+#define EDAC_MOD_STR "octeon"
+
+static struct mem_ctl_info *mc_cavium;
+static void *lmc_base;
+
+static void co_lmc_poll(struct mem_ctl_info *mci)
+{
+	union lmc_mem_cfg0 cfg0;
+	union lmc_fadr fadr;
+	char msg[64];
+
+	fadr.u64 = readq(lmc_base + LMC_FADR);
+	cfg0.u64 = readq(lmc_base + LMC_MEM_CFG0);
+	snprintf(msg, sizeof(msg), "DIMM %d rank %d bank %d row %d col %d",
+		fadr.fdimm, fadr.fbunk, fadr.fbank, fadr.frow, fadr.fcol);
+
+	if (cfg0.sec_err) {
+		edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, -1, -1, -1,
+				     msg, "");
+
+		cfg0.intr_sec_ena = -1;		/* Done, re-arm */
+	}
+
+	if (cfg0.ded_err) {
+		edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1,
+				     msg, "");
+		cfg0.intr_ded_ena = -1;		/* Done, re-arm */
+	}
+
+	writeq(cfg0.u64, lmc_base + LMC_MEM_CFG0);
+}
+
+static int __devinit co_lmc_probe(struct platform_device *pdev)
+{
+	struct mem_ctl_info *mci;
+	union lmc_mem_cfg0 cfg0;
+	int res = 0;
+
+	mci = edac_mc_alloc(0, 0, 0, 0);
+	if (!mci)
+		return -ENOMEM;
+
+	mci->pdev = &pdev->dev;
+	platform_set_drvdata(pdev, mci);
+	mci->dev_name = dev_name(&pdev->dev);
+
+	mci->mod_name = "octeon-lmc";
+	mci->ctl_name = "co_lmc_err";
+	mci->edac_check = co_lmc_poll;
+
+	if (edac_mc_add_mc(mci) > 0) {
+		pr_err("%s: edac_mc_add_mc() failed\n", __func__);
+		goto err;
+	}
+
+	cfg0.u64 = readq(lmc_base + LMC_MEM_CFG0);	/* We poll */
+	cfg0.intr_ded_ena = 0;
+	cfg0.intr_sec_ena = 0;
+	writeq(cfg0.u64, lmc_base + LMC_MEM_CFG0);
+
+	mc_cavium = mci;
+
+	return 0;
+
+err:
+	edac_mc_free(mci);
+
+	return res;
+}
+
+static int co_lmc_remove(struct platform_device *pdev)
+{
+	struct mem_ctl_info *mci = platform_get_drvdata(pdev);
+
+	mc_cavium = NULL;
+	edac_mc_del_mc(&pdev->dev);
+	edac_mc_free(mci);
+
+	return 0;
+}
+
+static struct platform_driver co_lmc_driver = {
+	.probe = co_lmc_probe,
+	.remove = co_lmc_remove,
+	.driver = {
+		   .name = "co_lmc_edac",
+	}
+};
+
+static int __init co_edac_init(void)
+{
+	union lmc_mem_cfg0 cfg0;
+	int ret;
+
+	lmc_base = ioremap_nocache(LMC_BASE, LMC_SIZE);
+	if (!lmc_base)
+		return -ENOMEM;
+
+	cfg0.u64 = readq(lmc_base + LMC_MEM_CFG0);
+	if (!cfg0.ecc_ena) {
+		pr_info(EDAC_MOD_STR " LMC EDAC: ECC disabled, good bye\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	ret = platform_driver_register(&co_lmc_driver);
+	if (ret) {
+		pr_warning(EDAC_MOD_STR " LMC EDAC failed to register\n");
+		goto out;
+	}
+
+	return ret;
+
+out:
+	iounmap(lmc_base);
+
+	return ret;
+}
+
+static void __exit co_edac_exit(void)
+{
+	platform_driver_unregister(&co_lmc_driver);
+	iounmap(lmc_base);
+}
+
+module_init(co_edac_init);
+module_exit(co_edac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
diff --git a/drivers/edac/octeon_edac-lmc.h b/drivers/edac/octeon_edac-lmc.h
new file mode 100644
index 0000000..246dc52
--- /dev/null
+++ b/drivers/edac/octeon_edac-lmc.h
@@ -0,0 +1,78 @@
+/*
+ * LMC Registers, see chapter 2.5
+ *
+ * These are RSL Type registers and are accessed indirectly across the
+ * I/O bus, so accesses are slowish.  Not that it matters.  Any size load is
+ * ok but stores must be 64-bit.
+ */
+#define LMC_BASE		0x0001180088000000
+#define LMC_SIZE		0xb8
+
+#define LMC_MEM_CFG0		0x0000000000000000
+#define LMC_MEM_CFG1		0x0000000000000008
+#define LMC_CTL			0x0000000000000010
+#define LMC_DDR2_CTL		0x0000000000000018
+#define LMC_FADR		0x0000000000000020
+#define   LMC_FADR_FDIMM
+#define   LMC_FADR_FBUNK
+#define   LMC_FADR_FBANK
+#define   LMC_FADR_FROW
+#define   LMC_FADR_FCOL
+#define LMC_COMP_CTL		0x0000000000000028
+#define LMC_WODT_CTL		0x0000000000000030
+#define LMC_ECC_SYND		0x0000000000000038
+#define LMC_IFB_CNT_LO		0x0000000000000048
+#define LMC_IFB_CNT_HI		0x0000000000000050
+#define LMC_OPS_CNT_LO		0x0000000000000058
+#define LMC_OPS_CNT_HI		0x0000000000000060
+#define LMC_DCLK_CNT_LO		0x0000000000000068
+#define LMC_DCLK_CNT_HI		0x0000000000000070
+#define LMC_DELAY_CFG		0x0000000000000088
+#define LMC_CTL1		0x0000000000000090
+#define LMC_DUAL_MEM_CONFIG	0x0000000000000098
+#define LMC_RODT_COMP_CTL	0x00000000000000A0
+#define LMC_PLL_CTL		0x00000000000000A8
+#define LMC_PLL_STATUS		0x00000000000000B0
+
+union lmc_mem_cfg0 {
+	uint64_t u64;
+	struct {
+		uint64_t reserved_32_63:32;
+		uint64_t reset:1;
+		uint64_t silo_qc:1;
+		uint64_t bunk_ena:1;
+		uint64_t ded_err:4;
+		uint64_t sec_err:4;
+		uint64_t intr_ded_ena:1;
+		uint64_t intr_sec_ena:1;
+		uint64_t reserved_15_18:4;
+		uint64_t ref_int:5;
+		uint64_t pbank_lsb:4;
+		uint64_t row_lsb:3;
+		uint64_t ecc_ena:1;
+		uint64_t init_start:1;
+	};
+};
+
+union lmc_fadr {
+	uint64_t u64;
+	struct {
+		uint64_t reserved_32_63:32;
+		uint64_t fdimm:2;
+		uint64_t fbunk:1;
+		uint64_t fbank:3;
+		uint64_t frow:14;
+		uint64_t fcol:12;
+	};
+};
+
+union lmc_ecc_synd {
+	uint64_t u64;
+	struct {
+		uint64_t reserved_32_63:32;
+		uint64_t mrdsyn3:8;
+		uint64_t mrdsyn2:8;
+		uint64_t mrdsyn1:8;
+		uint64_t mrdsyn0:8;
+	};
+};
diff --git a/drivers/edac/octeon_edac-pc.c b/drivers/edac/octeon_edac-pc.c
new file mode 100644
index 0000000..9d13061
--- /dev/null
+++ b/drivers/edac/octeon_edac-pc.c
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/edac.h>
+
+#include "edac_core.h"
+#include "edac_module.h"
+
+#include <asm/octeon/cvmx.h>
+#include <asm/mipsregs.h>
+
+#define EDAC_MOD_STR "octeon"
+
+extern int register_co_cache_error_notifier(struct notifier_block *nb);
+extern int unregister_co_cache_error_notifier(struct notifier_block *nb);
+
+extern unsigned long long cache_err_dcache[NR_CPUS];
+
+static struct edac_device_ctl_info *ed_cavium;
+
+/*
+ * EDAC CPU cache error callback
+ *
+ */
+
+static int  co_cache_error_event(struct notifier_block *this,
+	unsigned long event, void *ptr)
+{
+	unsigned int core = cvmx_get_core_num();
+	unsigned int cpu = smp_processor_id();
+	uint64_t icache_err = read_octeon_c0_icacheerr();
+	struct edac_device_ctl_info *ed = ed_cavium;
+
+	edac_device_printk(ed, KERN_ERR,
+			   "Cache error exception on core %d / processor %d:\n",
+			   core, cpu);
+	edac_device_printk(ed, KERN_ERR,
+			   "cp0_errorepc == %lx\n", read_c0_errorepc());
+	if (icache_err & 1) {
+		edac_device_printk(ed, KERN_ERR, "CacheErr (Icache) == %llx\n",
+				   (unsigned long long)icache_err);
+		write_octeon_c0_icacheerr(0);
+		edac_device_handle_ce(ed, 0, 0, ed->ctl_name);
+	}
+	if (cache_err_dcache[core] & 1) {
+		edac_device_printk(ed, KERN_ERR, "CacheErr (Dcache) == %llx\n",
+				   (unsigned long long)cache_err_dcache[core]);
+		cache_err_dcache[core] = 0;
+		edac_device_handle_ue(ed, 0, 0, ed->ctl_name);
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block co_cache_error_notifier = {
+	.notifier_call = co_cache_error_event,
+};
+
+static int __devinit co_cache_error_probe(struct platform_device *pdev)
+{
+	struct edac_device_ctl_info *ed;
+	int res = 0;
+
+	ed = edac_device_alloc_ctl_info(0, "cpu", 1, NULL, 0, 0, NULL, 0,
+					edac_device_alloc_index());
+
+	ed->dev = &pdev->dev;
+	platform_set_drvdata(pdev, ed);
+	ed->dev_name = dev_name(&pdev->dev);
+
+	ed->mod_name = "octeon-cpu";
+	ed->ctl_name = "co_cpu_err";
+
+	if (edac_device_add_device(ed) > 0) {
+		pr_err("%s: edac_device_add_device() failed\n", __func__);
+		goto err;
+	}
+
+	register_co_cache_error_notifier(&co_cache_error_notifier);
+	ed_cavium = ed;
+
+	return 0;
+
+err:
+	edac_device_free_ctl_info(ed);
+
+	return res;
+}
+
+static int co_cache_error_remove(struct platform_device *pdev)
+{
+	struct edac_device_ctl_info *ed = platform_get_drvdata(pdev);
+
+	unregister_co_cache_error_notifier(&co_cache_error_notifier);
+	ed_cavium = NULL;
+	edac_device_del_device(&pdev->dev);
+	edac_device_free_ctl_info(ed);
+
+	return 0;
+}
+
+static struct platform_driver co_cache_error_driver = {
+	.probe = co_cache_error_probe,
+	.remove = co_cache_error_remove,
+	.driver = {
+		   .name = "co_pc_edac",
+	}
+};
+
+static int __init co_edac_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&co_cache_error_driver);
+	if (ret)
+		pr_warning(EDAC_MOD_STR "CPU err failed to register\n");
+
+	return ret;
+}
+
+static void __exit co_edac_exit(void)
+{
+	platform_driver_unregister(&co_cache_error_driver);
+}
+
+module_init(co_edac_init);
+module_exit(co_edac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
diff --git a/drivers/edac/octeon_edac-pci.c b/drivers/edac/octeon_edac-pci.c
new file mode 100644
index 0000000..e72b96e
--- /dev/null
+++ b/drivers/edac/octeon_edac-pci.c
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/edac.h>
+
+#include <asm/octeon/cvmx.h>
+#include <asm/octeon/cvmx-npi-defs.h>
+#include <asm/octeon/cvmx-pci-defs.h>
+#include <asm/octeon/octeon.h>
+
+#include "edac_core.h"
+#include "edac_module.h"
+
+#define EDAC_MOD_STR "octeon"
+
+static void co_pci_poll(struct edac_pci_ctl_info *pci)
+{
+	union cvmx_pci_cfg01 cfg01;
+
+	cfg01.u32 = octeon_npi_read32(CVMX_NPI_PCI_CFG01);
+	if (cfg01.s.dpe) {		/* Detected parity error */
+		edac_pci_handle_pe(pci, pci->ctl_name);
+		cfg01.s.dpe = 1;		/* Reset  */
+		octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+	}
+	if (cfg01.s.sse) {
+		edac_pci_handle_npe(pci, "Signaled System Error");
+		cfg01.s.sse = 1;		/* Reset */
+		octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+	}
+	if (cfg01.s.rma) {
+		edac_pci_handle_npe(pci, "Received Master Abort");
+		cfg01.s.rma = 1;		/* Reset */
+		octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+	}
+	if (cfg01.s.rta) {
+		edac_pci_handle_npe(pci, "Received Target Abort");
+		cfg01.s.rta = 1;		/* Reset */
+		octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+	}
+	if (cfg01.s.sta) {
+		edac_pci_handle_npe(pci, "Signaled Target Abort");
+		cfg01.s.sta = 1;		/* Reset */
+		octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+	}
+	if (cfg01.s.mdpe) {
+		edac_pci_handle_npe(pci, "Master Data Parity Error");
+		cfg01.s.mdpe = 1;		/* Reset */
+		octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+	}
+	if (cfg01.s.mdpe) {
+		edac_pci_handle_npe(pci, "Master Data Parity Error");
+		cfg01.s.mdpe = 1;		/* Reset */
+		octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+	}
+}
+
+static int __devinit co_pci_probe(struct platform_device *pdev)
+{
+	struct edac_pci_ctl_info *pci;
+	int res = 0;
+
+	pci = edac_pci_alloc_ctl_info(0, "octeon_pci_err");
+	if (!pci)
+		return -ENOMEM;
+
+	pci->dev = &pdev->dev;
+	platform_set_drvdata(pdev, pci);
+	pci->dev_name = dev_name(&pdev->dev);
+
+	pci->mod_name = "octeon-pci";
+	pci->ctl_name = "octeon_pci_err";
+	pci->edac_check = co_pci_poll;
+
+	if (edac_pci_add_device(pci, 0) > 0) {
+		pr_err("%s: edac_pci_add_device() failed\n", __func__);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	edac_pci_free_ctl_info(pci);
+
+	return res;
+}
+
+static int co_pci_remove(struct platform_device *pdev)
+{
+	struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev);
+
+	edac_pci_del_device(&pdev->dev);
+	edac_pci_free_ctl_info(pci);
+
+	return 0;
+}
+
+static struct platform_driver co_pci_driver = {
+	.probe = co_pci_probe,
+	.remove = co_pci_remove,
+	.driver = {
+		   .name = "co_pci_edac",
+	}
+};
+
+static int __init co_edac_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&co_pci_driver);
+	if (ret)
+		pr_warning(EDAC_MOD_STR " PCI EDAC failed to register\n");
+
+	return ret;
+}
+
+static void __exit co_edac_exit(void)
+{
+	platform_driver_unregister(&co_pci_driver);
+}
+
+module_init(co_edac_init);
+module_exit(co_edac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 5715b7c..9ad2424 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -639,7 +639,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
 	tmp_mb = (1 + pvt->tohm) >> 20;
 
 	mb = div_u64_rem(tmp_mb, 1000, &kb);
-	edac_dbg(0, "TOHM: %u.%03u GB (0x%016Lx)", mb, kb, (u64)pvt->tohm);
+	edac_dbg(0, "TOHM: %u.%03u GB (0x%016Lx)\n", mb, kb, (u64)pvt->tohm);
 
 	/*
 	 * Step 2) Get SAD range and SAD Interleave list
diff --git a/drivers/eisa/eisa.ids b/drivers/eisa/eisa.ids
index 6cbb7a5..2d864b4 100644
--- a/drivers/eisa/eisa.ids
+++ b/drivers/eisa/eisa.ids
@@ -985,8 +985,8 @@ ISABD00 "Racal-Interlan NP600A Ethernet 16bit"
 ISABD02 "Racal-Interlan NI5210/8 Ethernet"
 ISABD03 "Racal-Interlan NI5210/16 Ethernet"
 ISABE00 "Qua Tech PXB-1608 Parallel Expansion Board"
-ISABE01 "Qua Tech ES-100 8 Channel Asyncronous"
-ISABE02 "Qua Tech QS-100M 4 Channel Asyncronous"
+ISABE01 "Qua Tech ES-100 8 Channel Asynchronous"
+ISABE02 "Qua Tech QS-100M 4 Channel Asynchronous"
 ISABE03 "Qua Tech MXI-100 IEEE 488 GPIB"
 ISABE04 "Qua Tech DS-201 Dual Channel RS-422"
 ISABE05 "Qua Tech PXB-721 Parallel Expansion"
diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c
index e87196f..eda2a1a 100644
--- a/drivers/extcon/extcon-adc-jack.c
+++ b/drivers/extcon/extcon-adc-jack.c
@@ -91,7 +91,7 @@ static irqreturn_t adc_jack_irq_thread(int irq, void *_data)
 	return IRQ_HANDLED;
 }
 
-static int __devinit adc_jack_probe(struct platform_device *pdev)
+static int adc_jack_probe(struct platform_device *pdev)
 {
 	struct adc_jack_data *data;
 	struct adc_jack_pdata *pdata = pdev->dev.platform_data;
@@ -175,7 +175,7 @@ out:
 	return err;
 }
 
-static int __devexit adc_jack_remove(struct platform_device *pdev)
+static int adc_jack_remove(struct platform_device *pdev)
 {
 	struct adc_jack_data *data = platform_get_drvdata(pdev);
 
@@ -188,7 +188,7 @@ static int __devexit adc_jack_remove(struct platform_device *pdev)
 
 static struct platform_driver adc_jack_driver = {
 	.probe          = adc_jack_probe,
-	.remove         = __devexit_p(adc_jack_remove),
+	.remove         = adc_jack_remove,
 	.driver         = {
 		.name   = "adc-jack",
 		.owner  = THIS_MODULE,
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index cdab9e5..414aed5 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -166,6 +166,7 @@ static irqreturn_t arizona_micdet(int irq, void *data)
 	ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
 	if (ret != 0) {
 		dev_err(arizona->dev, "Failed to read MICDET: %d\n", ret);
+		mutex_unlock(&info->lock);
 		return IRQ_NONE;
 	}
 
@@ -337,7 +338,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int __devinit arizona_extcon_probe(struct platform_device *pdev)
+static int arizona_extcon_probe(struct platform_device *pdev)
 {
 	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
 	struct arizona_pdata *pdata;
@@ -517,7 +518,7 @@ err:
 	return ret;
 }
 
-static int __devexit arizona_extcon_remove(struct platform_device *pdev)
+static int arizona_extcon_remove(struct platform_device *pdev)
 {
 	struct arizona_extcon_info *info = platform_get_drvdata(pdev);
 	struct arizona *arizona = info->arizona;
@@ -544,7 +545,7 @@ static struct platform_driver arizona_extcon_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= arizona_extcon_probe,
-	.remove		= __devexit_p(arizona_extcon_remove),
+	.remove		= arizona_extcon_remove,
 };
 
 module_platform_driver(arizona_extcon_driver);
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c
index d398821..60adc04 100644
--- a/drivers/extcon/extcon-class.c
+++ b/drivers/extcon/extcon-class.c
@@ -472,7 +472,7 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
 
 		obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
 		if (obj->cable_index < 0)
-			return -ENODEV;
+			return obj->cable_index;
 
 		obj->user_nb = nb;
 
diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c
index 71d3ab7..1b14bfc 100644
--- a/drivers/extcon/extcon-gpio.c
+++ b/drivers/extcon/extcon-gpio.c
@@ -76,7 +76,7 @@ static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf)
 	return -EINVAL;
 }
 
-static int __devinit gpio_extcon_probe(struct platform_device *pdev)
+static int gpio_extcon_probe(struct platform_device *pdev)
 {
 	struct gpio_extcon_platform_data *pdata = pdev->dev.platform_data;
 	struct gpio_extcon_data *extcon_data;
@@ -137,7 +137,7 @@ err:
 	return ret;
 }
 
-static int __devexit gpio_extcon_remove(struct platform_device *pdev)
+static int gpio_extcon_remove(struct platform_device *pdev)
 {
 	struct gpio_extcon_data *extcon_data = platform_get_drvdata(pdev);
 
@@ -150,7 +150,7 @@ static int __devexit gpio_extcon_remove(struct platform_device *pdev)
 
 static struct platform_driver gpio_extcon_driver = {
 	.probe		= gpio_extcon_probe,
-	.remove		= __devexit_p(gpio_extcon_remove),
+	.remove		= gpio_extcon_remove,
 	.driver		= {
 		.name	= "extcon-gpio",
 		.owner	= THIS_MODULE,
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index a17d0d9..8c17b65 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -648,7 +648,7 @@ out:
 	return ret;
 }
 
-static int __devinit max77693_muic_probe(struct platform_device *pdev)
+static int max77693_muic_probe(struct platform_device *pdev)
 {
 	struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
 	struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev);
@@ -657,17 +657,17 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)
 	int ret, i;
 	u8 id;
 
-	info = kzalloc(sizeof(struct max77693_muic_info), GFP_KERNEL);
+	info = devm_kzalloc(&pdev->dev, sizeof(struct max77693_muic_info),
+				   GFP_KERNEL);
 	if (!info) {
 		dev_err(&pdev->dev, "failed to allocate memory\n");
-		ret = -ENOMEM;
-		goto err_kfree;
+		return -ENOMEM;
 	}
 	info->dev = &pdev->dev;
 	info->max77693 = max77693;
-	if (info->max77693->regmap_muic)
+	if (info->max77693->regmap_muic) {
 		dev_dbg(&pdev->dev, "allocate register map\n");
-	else {
+	} else {
 		info->max77693->regmap_muic = devm_regmap_init_i2c(
 						info->max77693->muic,
 						&max77693_muic_regmap_config);
@@ -675,7 +675,7 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)
 			ret = PTR_ERR(info->max77693->regmap_muic);
 			dev_err(max77693->dev,
 				"failed to allocate register map: %d\n", ret);
-			goto err_regmap;
+			return ret;
 		}
 	}
 	platform_set_drvdata(pdev, info);
@@ -686,11 +686,13 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)
 	/* Support irq domain for MAX77693 MUIC device */
 	for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) {
 		struct max77693_muic_irq *muic_irq = &muic_irqs[i];
-		int virq = 0;
+		unsigned int virq = 0;
 
 		virq = irq_create_mapping(max77693->irq_domain, muic_irq->irq);
-		if (!virq)
+		if (!virq) {
+			ret = -EINVAL;
 			goto err_irq;
+		}
 		muic_irq->virq = virq;
 
 		ret = request_threaded_irq(virq, NULL,
@@ -702,14 +704,13 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)
 				" error :%d)\n",
 				muic_irq->irq, ret);
 
-			for (i = i - 1; i >= 0; i--)
-				free_irq(muic_irq->virq, info);
 			goto err_irq;
 		}
 	}
 
 	/* Initialize extcon device */
-	info->edev = kzalloc(sizeof(struct extcon_dev), GFP_KERNEL);
+	info->edev = devm_kzalloc(&pdev->dev, sizeof(struct extcon_dev),
+				  GFP_KERNEL);
 	if (!info->edev) {
 		dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
 		ret = -ENOMEM;
@@ -720,7 +721,7 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)
 	ret = extcon_dev_register(info->edev, NULL);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register extcon device\n");
-		goto err_extcon;
+		goto err_irq;
 	}
 
 	/* Initialize MUIC register by using platform data */
@@ -753,7 +754,7 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)
 			MAX77693_MUIC_REG_ID, &id);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to read revision number\n");
-		goto err_extcon;
+		goto err_irq;
 	}
 	dev_info(info->dev, "device ID : 0x%x\n", id);
 
@@ -765,16 +766,13 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)
 
 	return ret;
 
-err_extcon:
-	kfree(info->edev);
 err_irq:
-err_regmap:
-	kfree(info);
-err_kfree:
+	while (--i >= 0)
+		free_irq(muic_irqs[i].virq, info);
 	return ret;
 }
 
-static int __devexit max77693_muic_remove(struct platform_device *pdev)
+static int max77693_muic_remove(struct platform_device *pdev)
 {
 	struct max77693_muic_info *info = platform_get_drvdata(pdev);
 	int i;
@@ -783,8 +781,6 @@ static int __devexit max77693_muic_remove(struct platform_device *pdev)
 		free_irq(muic_irqs[i].virq, info);
 	cancel_work_sync(&info->irq_work);
 	extcon_dev_unregister(info->edev);
-	kfree(info->edev);
-	kfree(info);
 
 	return 0;
 }
@@ -795,7 +791,7 @@ static struct platform_driver max77693_muic_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= max77693_muic_probe,
-	.remove		= __devexit_p(max77693_muic_remove),
+	.remove		= max77693_muic_remove,
 };
 
 module_platform_driver(max77693_muic_driver);
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index 77b66b0..93009fe 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -1,7 +1,7 @@
 /*
  * extcon-max8997.c - MAX8997 extcon driver to support MAX8997 MUIC
  *
- *  Copyright (C) 2012 Samsung Electrnoics
+ *  Copyright (C) 2012 Samsung Electronics
  *  Donggeun Kim <dg77.kim@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -426,18 +426,18 @@ static void max8997_muic_detect_dev(struct max8997_muic_info *info)
 	max8997_muic_handle_charger_type(info, chg_type);
 }
 
-static int __devinit max8997_muic_probe(struct platform_device *pdev)
+static int max8997_muic_probe(struct platform_device *pdev)
 {
 	struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent);
 	struct max8997_platform_data *pdata = dev_get_platdata(max8997->dev);
 	struct max8997_muic_info *info;
 	int ret, i;
 
-	info = kzalloc(sizeof(struct max8997_muic_info), GFP_KERNEL);
+	info = devm_kzalloc(&pdev->dev, sizeof(struct max8997_muic_info),
+			    GFP_KERNEL);
 	if (!info) {
 		dev_err(&pdev->dev, "failed to allocate memory\n");
-		ret = -ENOMEM;
-		goto err_kfree;
+		return -ENOMEM;
 	}
 
 	info->dev = &pdev->dev;
@@ -450,14 +450,16 @@ static int __devinit max8997_muic_probe(struct platform_device *pdev)
 
 	for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) {
 		struct max8997_muic_irq *muic_irq = &muic_irqs[i];
-		int virq = 0;
+		unsigned int virq = 0;
 
 		virq = irq_create_mapping(max8997->irq_domain, muic_irq->irq);
-		if (!virq)
+		if (!virq) {
+			ret = -EINVAL;
 			goto err_irq;
+		}
 		muic_irq->virq = virq;
 
-		ret = request_threaded_irq(virq, NULL,max8997_muic_irq_handler,
+		ret = request_threaded_irq(virq, NULL, max8997_muic_irq_handler,
 				0, muic_irq->name, info);
 		if (ret) {
 			dev_err(&pdev->dev,
@@ -469,7 +471,8 @@ static int __devinit max8997_muic_probe(struct platform_device *pdev)
 	}
 
 	/* External connector */
-	info->edev = kzalloc(sizeof(struct extcon_dev), GFP_KERNEL);
+	info->edev = devm_kzalloc(&pdev->dev, sizeof(struct extcon_dev),
+				  GFP_KERNEL);
 	if (!info->edev) {
 		dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
 		ret = -ENOMEM;
@@ -480,7 +483,7 @@ static int __devinit max8997_muic_probe(struct platform_device *pdev)
 	ret = extcon_dev_register(info->edev, NULL);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register extcon device\n");
-		goto err_extcon;
+		goto err_irq;
 	}
 
 	/* Initialize registers according to platform data */
@@ -498,17 +501,13 @@ static int __devinit max8997_muic_probe(struct platform_device *pdev)
 
 	return ret;
 
-err_extcon:
-	kfree(info->edev);
 err_irq:
 	while (--i >= 0)
 		free_irq(muic_irqs[i].virq, info);
-	kfree(info);
-err_kfree:
 	return ret;
 }
 
-static int __devexit max8997_muic_remove(struct platform_device *pdev)
+static int max8997_muic_remove(struct platform_device *pdev)
 {
 	struct max8997_muic_info *info = platform_get_drvdata(pdev);
 	int i;
@@ -519,9 +518,6 @@ static int __devexit max8997_muic_remove(struct platform_device *pdev)
 
 	extcon_dev_unregister(info->edev);
 
-	kfree(info->edev);
-	kfree(info);
-
 	return 0;
 }
 
@@ -531,7 +527,7 @@ static struct platform_driver max8997_muic_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= max8997_muic_probe,
-	.remove		= __devexit_p(max8997_muic_remove),
+	.remove		= max8997_muic_remove,
 };
 
 module_platform_driver(max8997_muic_driver);
diff --git a/drivers/firewire/init_ohci1394_dma.c b/drivers/firewire/init_ohci1394_dma.c
index a9a347a..2cc89ce 100644
--- a/drivers/firewire/init_ohci1394_dma.c
+++ b/drivers/firewire/init_ohci1394_dma.c
@@ -149,10 +149,10 @@ static inline void __init init_ohci1394_initialize(struct ohci *ohci)
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
 	reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
 
-	/* Accept asyncronous transfer requests from all nodes for now */
+	/* Accept asynchronous transfer requests from all nodes for now */
 	reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
 
-	/* Specify asyncronous transfer retries */
+	/* Specify asynchronous transfer retries */
 	reg_write(ohci, OHCI1394_ATRetries,
 		  OHCI1394_MAX_AT_REQ_RETRIES |
 		  (OHCI1394_MAX_AT_RESP_RETRIES<<4) |
diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c
index 4ebfb22..76b2d39 100644
--- a/drivers/firewire/nosy.c
+++ b/drivers/firewire/nosy.c
@@ -529,7 +529,7 @@ remove_card(struct pci_dev *dev)
 
 #define RCV_BUFFER_SIZE (16 * 1024)
 
-static int __devinit
+static int
 add_card(struct pci_dev *dev, const struct pci_device_id *unused)
 {
 	struct pcilynx *lynx;
@@ -683,7 +683,7 @@ fail_disable:
 	return ret;
 }
 
-static struct pci_device_id pci_table[] __devinitdata = {
+static struct pci_device_id pci_table[] = {
 	{
 		.vendor =    PCI_VENDOR_ID_TI,
 		.device =    PCI_DEVICE_ID_TI_PCILYNX,
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 834e71d..6ce6e07 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -1281,7 +1281,7 @@ static int at_context_queue_packet(struct context *ctx,
 	d[0].res_count = cpu_to_le16(packet->timestamp);
 
 	/*
-	 * The DMA format for asyncronous link packets is different
+	 * The DMA format for asynchronous link packets is different
 	 * from the IEEE1394 layout, so shift the fields around
 	 * accordingly.
 	 */
@@ -3537,7 +3537,7 @@ static inline void pmac_ohci_on(struct pci_dev *dev) {}
 static inline void pmac_ohci_off(struct pci_dev *dev) {}
 #endif /* CONFIG_PPC_PMAC */
 
-static int __devinit pci_probe(struct pci_dev *dev,
+static int pci_probe(struct pci_dev *dev,
 			       const struct pci_device_id *ent)
 {
 	struct fw_ohci *ohci;
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index b298158..fd3ae62 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -16,6 +16,7 @@
  */
 static char dmi_empty_string[] = "        ";
 
+static u16 __initdata dmi_ver;
 /*
  * Catch too early calls to dmi_check_system():
  */
@@ -118,12 +119,12 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
 	return 0;
 }
 
-static int __init dmi_checksum(const u8 *buf)
+static int __init dmi_checksum(const u8 *buf, u8 len)
 {
 	u8 sum = 0;
 	int a;
 
-	for (a = 0; a < 15; a++)
+	for (a = 0; a < len; a++)
 		sum += buf[a];
 
 	return sum == 0;
@@ -161,8 +162,10 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int inde
 		return;
 
 	for (i = 0; i < 16 && (is_ff || is_00); i++) {
-		if(d[i] != 0x00) is_ff = 0;
-		if(d[i] != 0xFF) is_00 = 0;
+		if (d[i] != 0x00)
+			is_00 = 0;
+		if (d[i] != 0xFF)
+			is_ff = 0;
 	}
 
 	if (is_ff || is_00)
@@ -172,7 +175,15 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int inde
 	if (!s)
 		return;
 
-	sprintf(s, "%pUB", d);
+	/*
+	 * As of version 2.6 of the SMBIOS specification, the first 3 fields of
+	 * the UUID are supposed to be little-endian encoded.  The specification
+	 * says that this is the defacto standard.
+	 */
+	if (dmi_ver >= 0x0206)
+		sprintf(s, "%pUL", d);
+	else
+		sprintf(s, "%pUB", d);
 
         dmi_ident[slot] = s;
 }
@@ -404,29 +415,57 @@ static int __init dmi_present(const char __iomem *p)
 	u8 buf[15];
 
 	memcpy_fromio(buf, p, 15);
-	if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
+	if (dmi_checksum(buf, 15)) {
 		dmi_num = (buf[13] << 8) | buf[12];
 		dmi_len = (buf[7] << 8) | buf[6];
 		dmi_base = (buf[11] << 24) | (buf[10] << 16) |
 			(buf[9] << 8) | buf[8];
 
-		/*
-		 * DMI version 0.0 means that the real version is taken from
-		 * the SMBIOS version, which we don't know at this point.
-		 */
-		if (buf[14] != 0)
-			printk(KERN_INFO "DMI %d.%d present.\n",
-			       buf[14] >> 4, buf[14] & 0xF);
-		else
-			printk(KERN_INFO "DMI present.\n");
 		if (dmi_walk_early(dmi_decode) == 0) {
+			if (dmi_ver)
+				pr_info("SMBIOS %d.%d present.\n",
+				       dmi_ver >> 8, dmi_ver & 0xFF);
+			else {
+				dmi_ver = (buf[14] & 0xF0) << 4 |
+					   (buf[14] & 0x0F);
+				pr_info("Legacy DMI %d.%d present.\n",
+				       dmi_ver >> 8, dmi_ver & 0xFF);
+			}
 			dmi_dump_ids();
 			return 0;
 		}
 	}
+	dmi_ver = 0;
 	return 1;
 }
 
+static int __init smbios_present(const char __iomem *p)
+{
+	u8 buf[32];
+	int offset = 0;
+
+	memcpy_fromio(buf, p, 32);
+	if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) {
+		dmi_ver = (buf[6] << 8) + buf[7];
+
+		/* Some BIOS report weird SMBIOS version, fix that up */
+		switch (dmi_ver) {
+		case 0x021F:
+		case 0x0221:
+			pr_debug("SMBIOS version fixup(2.%d->2.%d)\n",
+			       dmi_ver & 0xFF, 3);
+			dmi_ver = 0x0203;
+			break;
+		case 0x0233:
+			pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6);
+			dmi_ver = 0x0206;
+			break;
+		}
+		offset = 16;
+	}
+	return dmi_present(buf + offset);
+}
+
 void __init dmi_scan_machine(void)
 {
 	char __iomem *p, *q;
@@ -444,7 +483,7 @@ void __init dmi_scan_machine(void)
 		if (p == NULL)
 			goto error;
 
-		rc = dmi_present(p + 0x10); /* offset of _DMI_ string */
+		rc = smbios_present(p);
 		dmi_iounmap(p, 32);
 		if (!rc) {
 			dmi_available = 1;
@@ -462,7 +501,12 @@ void __init dmi_scan_machine(void)
 			goto error;
 
 		for (q = p; q < p + 0x10000; q += 16) {
-			rc = dmi_present(q);
+			if (memcmp(q, "_SM_", 4) == 0 && q - p <= 0xFFE0)
+				rc = smbios_present(q);
+			else if (memcmp(q, "_DMI_", 5) == 0)
+				rc = dmi_present(q);
+			else
+				continue;
 			if (!rc) {
 				dmi_available = 1;
 				dmi_iounmap(p, 0x10000);
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index d10c987..6e51c1e 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -658,13 +658,14 @@ static int efi_pstore_close(struct pstore_info *psi)
 }
 
 static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
-			       struct timespec *timespec,
+			       int *count, struct timespec *timespec,
 			       char **buf, struct pstore_info *psi)
 {
 	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
 	struct efivars *efivars = psi->data;
 	char name[DUMP_NAME_LEN];
 	int i;
+	int cnt;
 	unsigned int part, size;
 	unsigned long time;
 
@@ -674,21 +675,41 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
 			for (i = 0; i < DUMP_NAME_LEN; i++) {
 				name[i] = efivars->walk_entry->var.VariableName[i];
 			}
-			if (sscanf(name, "dump-type%u-%u-%lu", type, &part, &time) == 3) {
+			if (sscanf(name, "dump-type%u-%u-%d-%lu",
+				   type, &part, &cnt, &time) == 4) {
+				*id = part;
+				*count = cnt;
+				timespec->tv_sec = time;
+				timespec->tv_nsec = 0;
+			} else if (sscanf(name, "dump-type%u-%u-%lu",
+				   type, &part, &time) == 3) {
+				/*
+				 * Check if an old format,
+				 * which doesn't support holding
+				 * multiple logs, remains.
+				 */
 				*id = part;
+				*count = 0;
 				timespec->tv_sec = time;
 				timespec->tv_nsec = 0;
-				get_var_data_locked(efivars, &efivars->walk_entry->var);
-				size = efivars->walk_entry->var.DataSize;
-				*buf = kmalloc(size, GFP_KERNEL);
-				if (*buf == NULL)
-					return -ENOMEM;
-				memcpy(*buf, efivars->walk_entry->var.Data,
-				       size);
-				efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
-					           struct efivar_entry, list);
-				return size;
+			} else {
+				efivars->walk_entry = list_entry(
+						efivars->walk_entry->list.next,
+						struct efivar_entry, list);
+				continue;
 			}
+
+			get_var_data_locked(efivars, &efivars->walk_entry->var);
+			size = efivars->walk_entry->var.DataSize;
+			*buf = kmalloc(size, GFP_KERNEL);
+			if (*buf == NULL)
+				return -ENOMEM;
+			memcpy(*buf, efivars->walk_entry->var.Data,
+			       size);
+			efivars->walk_entry = list_entry(
+					efivars->walk_entry->list.next,
+					struct efivar_entry, list);
+			return size;
 		}
 		efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
 						 struct efivar_entry, list);
@@ -698,26 +719,77 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
 
 static int efi_pstore_write(enum pstore_type_id type,
 		enum kmsg_dump_reason reason, u64 *id,
-		unsigned int part, size_t size, struct pstore_info *psi)
+		unsigned int part, int count, size_t size,
+		struct pstore_info *psi)
 {
 	char name[DUMP_NAME_LEN];
-	char stub_name[DUMP_NAME_LEN];
 	efi_char16_t efi_name[DUMP_NAME_LEN];
 	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
 	struct efivars *efivars = psi->data;
-	struct efivar_entry *entry, *found = NULL;
 	int i, ret = 0;
+	u64 storage_space, remaining_space, max_variable_size;
+	efi_status_t status = EFI_NOT_FOUND;
+
+	spin_lock(&efivars->lock);
+
+	/*
+	 * Check if there is a space enough to log.
+	 * size: a size of logging data
+	 * DUMP_NAME_LEN * 2: a maximum size of variable name
+	 */
+	status = efivars->ops->query_variable_info(PSTORE_EFI_ATTRIBUTES,
+						   &storage_space,
+						   &remaining_space,
+						   &max_variable_size);
+	if (status || remaining_space < size + DUMP_NAME_LEN * 2) {
+		spin_unlock(&efivars->lock);
+		*id = part;
+		return -ENOSPC;
+	}
+
+	sprintf(name, "dump-type%u-%u-%d-%lu", type, part, count,
+		get_seconds());
+
+	for (i = 0; i < DUMP_NAME_LEN; i++)
+		efi_name[i] = name[i];
+
+	efivars->ops->set_variable(efi_name, &vendor, PSTORE_EFI_ATTRIBUTES,
+				   size, psi->buf);
+
+	spin_unlock(&efivars->lock);
+
+	if (size)
+		ret = efivar_create_sysfs_entry(efivars,
+					  utf16_strsize(efi_name,
+							DUMP_NAME_LEN * 2),
+					  efi_name, &vendor);
+
+	*id = part;
+	return ret;
+};
+
+static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
+			    struct timespec time, struct pstore_info *psi)
+{
+	char name[DUMP_NAME_LEN];
+	efi_char16_t efi_name[DUMP_NAME_LEN];
+	char name_old[DUMP_NAME_LEN];
+	efi_char16_t efi_name_old[DUMP_NAME_LEN];
+	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
+	struct efivars *efivars = psi->data;
+	struct efivar_entry *entry, *found = NULL;
+	int i;
 
-	sprintf(stub_name, "dump-type%u-%u-", type, part);
-	sprintf(name, "%s%lu", stub_name, get_seconds());
+	sprintf(name, "dump-type%u-%u-%d-%lu", type, (unsigned int)id, count,
+		time.tv_sec);
 
 	spin_lock(&efivars->lock);
 
 	for (i = 0; i < DUMP_NAME_LEN; i++)
-		efi_name[i] = stub_name[i];
+		efi_name[i] = name[i];
 
 	/*
-	 * Clean up any entries with the same name
+	 * Clean up an entry with the same name
 	 */
 
 	list_for_each_entry(entry, &efivars->list, list) {
@@ -726,11 +798,22 @@ static int efi_pstore_write(enum pstore_type_id type,
 		if (efi_guidcmp(entry->var.VendorGuid, vendor))
 			continue;
 		if (utf16_strncmp(entry->var.VariableName, efi_name,
-				  utf16_strlen(efi_name)))
-			continue;
-		/* Needs to be a prefix */
-		if (entry->var.VariableName[utf16_strlen(efi_name)] == 0)
-			continue;
+				  utf16_strlen(efi_name))) {
+			/*
+			 * Check if an old format,
+			 * which doesn't support holding
+			 * multiple logs, remains.
+			 */
+			sprintf(name_old, "dump-type%u-%u-%lu", type,
+				(unsigned int)id, time.tv_sec);
+
+			for (i = 0; i < DUMP_NAME_LEN; i++)
+				efi_name_old[i] = name_old[i];
+
+			if (utf16_strncmp(entry->var.VariableName, efi_name_old,
+					  utf16_strlen(efi_name_old)))
+				continue;
+		}
 
 		/* found */
 		found = entry;
@@ -738,37 +821,17 @@ static int efi_pstore_write(enum pstore_type_id type,
 					   &entry->var.VendorGuid,
 					   PSTORE_EFI_ATTRIBUTES,
 					   0, NULL);
+		break;
 	}
 
 	if (found)
 		list_del(&found->list);
 
-	for (i = 0; i < DUMP_NAME_LEN; i++)
-		efi_name[i] = name[i];
-
-	efivars->ops->set_variable(efi_name, &vendor, PSTORE_EFI_ATTRIBUTES,
-				   size, psi->buf);
-
 	spin_unlock(&efivars->lock);
 
 	if (found)
 		efivar_unregister(found);
 
-	if (size)
-		ret = efivar_create_sysfs_entry(efivars,
-					  utf16_strsize(efi_name,
-							DUMP_NAME_LEN * 2),
-					  efi_name, &vendor);
-
-	*id = part;
-	return ret;
-};
-
-static int efi_pstore_erase(enum pstore_type_id type, u64 id,
-			    struct pstore_info *psi)
-{
-	efi_pstore_write(type, 0, &id, (unsigned int)id, 0, psi);
-
 	return 0;
 }
 #else
@@ -782,7 +845,7 @@ static int efi_pstore_close(struct pstore_info *psi)
 	return 0;
 }
 
-static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
+static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, int *count,
 			       struct timespec *timespec,
 			       char **buf, struct pstore_info *psi)
 {
@@ -791,13 +854,14 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
 
 static int efi_pstore_write(enum pstore_type_id type,
 		enum kmsg_dump_reason reason, u64 *id,
-		unsigned int part, size_t size, struct pstore_info *psi)
+		unsigned int part, int count, size_t size,
+		struct pstore_info *psi)
 {
 	return 0;
 }
 
-static int efi_pstore_erase(enum pstore_type_id type, u64 id,
-			    struct pstore_info *psi)
+static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
+			    struct timespec time, struct pstore_info *psi)
 {
 	return 0;
 }
@@ -1237,6 +1301,7 @@ efivars_init(void)
 	ops.get_variable = efi.get_variable;
 	ops.set_variable = efi.set_variable;
 	ops.get_next_variable = efi.get_next_variable;
+	ops.query_variable_info = efi.query_variable_info;
 	error = register_efivars(&__efivars, &ops, efi_kobj);
 	if (error)
 		goto err_put;
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 47150f5..2af4a84 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -49,6 +49,10 @@ config OF_GPIO
 	def_bool y
 	depends on OF
 
+config GPIO_ACPI
+	def_bool y
+	depends on ACPI
+
 config DEBUG_GPIO
 	bool "Debug GPIO calls"
 	depends on DEBUG_KERNEL
@@ -86,11 +90,26 @@ config GPIO_DA9052
 	help
 	  Say yes here to enable the GPIO driver for the DA9052 chip.
 
+config GPIO_DA9055
+	tristate "Dialog Semiconductor DA9055 GPIO"
+	depends on MFD_DA9055
+	help
+	  Say yes here to enable the GPIO driver for the DA9055 chip.
+
+	  The Dialog DA9055 PMIC chip has 3 GPIO pins that can be
+	  be controller by this driver.
+
+	  If driver is built as a module it will be called gpio-da9055.
+
 config GPIO_MAX730X
 	tristate
 
 comment "Memory mapped GPIO drivers:"
 
+config GPIO_CLPS711X
+	def_bool y
+	depends on ARCH_CLPS711X
+
 config GPIO_GENERIC_PLATFORM
 	tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
 	select GPIO_GENERIC
@@ -152,7 +171,7 @@ config GPIO_MSM_V2
 
 config GPIO_MVEBU
 	def_bool y
-	depends on ARCH_MVEBU
+	depends on PLAT_ORION
 	select GPIO_GENERIC
 	select GENERIC_IRQ_CHIP
 
@@ -181,6 +200,13 @@ config GPIO_PXA
 	help
 	  Say yes here to support the PXA GPIO device
 
+config GPIO_SPEAR_SPICS
+	bool "ST SPEAr13xx SPI Chip Select as GPIO support"
+	depends on PLAT_SPEAR
+	select GENERIC_IRQ_CHIP
+	help
+	  Say yes here to support ST SPEAr SPI Chip Select as GPIO device
+
 config GPIO_STA2X11
 	bool "STA2x11/ConneXt GPIO support"
 	depends on MFD_STA2X11
@@ -649,4 +675,17 @@ config GPIO_MSIC
 	  Enable support for GPIO on intel MSIC controllers found in
 	  intel MID devices
 
+comment "USB GPIO expanders:"
+
+config GPIO_VIPERBOARD
+	tristate "Viperboard GPIO a & b support"
+	depends on MFD_VIPERBOARD && USB
+	help
+	  Say yes here to access the GPIO signals of Nano River
+	  Technologies Viperboard. There are two GPIO chips on the
+	  board: gpioa and gpiob.
+          See viperboard API specification and Nano
+          River Tech's viperboard.h for detailed meaning
+          of the module parameters.
+
 endif
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 9aeed67..1d49aa7 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -4,6 +4,7 @@ ccflags-$(CONFIG_DEBUG_GPIO)	+= -DDEBUG
 
 obj-$(CONFIG_GPIOLIB)		+= gpiolib.o devres.o
 obj-$(CONFIG_OF_GPIO)		+= gpiolib-of.o
+obj-$(CONFIG_GPIO_ACPI)		+= gpiolib-acpi.o
 
 # Device drivers. Generally keep list sorted alphabetically
 obj-$(CONFIG_GPIO_GENERIC)	+= gpio-generic.o
@@ -16,8 +17,10 @@ obj-$(CONFIG_GPIO_ADP5588)	+= gpio-adp5588.o
 obj-$(CONFIG_GPIO_AMD8111)	+= gpio-amd8111.o
 obj-$(CONFIG_GPIO_ARIZONA)	+= gpio-arizona.o
 obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o
+obj-$(CONFIG_GPIO_CLPS711X)	+= gpio-clps711x.o
 obj-$(CONFIG_GPIO_CS5535)	+= gpio-cs5535.o
 obj-$(CONFIG_GPIO_DA9052)	+= gpio-da9052.o
+obj-$(CONFIG_GPIO_DA9055)	+= gpio-da9055.o
 obj-$(CONFIG_ARCH_DAVINCI)	+= gpio-davinci.o
 obj-$(CONFIG_GPIO_EM)		+= gpio-em.o
 obj-$(CONFIG_GPIO_EP93XX)	+= gpio-ep93xx.o
@@ -57,6 +60,7 @@ obj-$(CONFIG_PLAT_SAMSUNG)	+= gpio-samsung.o
 obj-$(CONFIG_ARCH_SA1100)	+= gpio-sa1100.o
 obj-$(CONFIG_GPIO_SCH)		+= gpio-sch.o
 obj-$(CONFIG_GPIO_SODAVILLE)	+= gpio-sodaville.o
+obj-$(CONFIG_GPIO_SPEAR_SPICS)	+= gpio-spear-spics.o
 obj-$(CONFIG_GPIO_STA2X11)	+= gpio-sta2x11.o
 obj-$(CONFIG_GPIO_STMPE)	+= gpio-stmpe.o
 obj-$(CONFIG_GPIO_STP_XWAY)	+= gpio-stp-xway.o
@@ -71,6 +75,7 @@ obj-$(CONFIG_GPIO_TPS65912)	+= gpio-tps65912.o
 obj-$(CONFIG_GPIO_TWL4030)	+= gpio-twl4030.o
 obj-$(CONFIG_GPIO_TWL6040)	+= gpio-twl6040.o
 obj-$(CONFIG_GPIO_UCB1400)	+= gpio-ucb1400.o
+obj-$(CONFIG_GPIO_VIPERBOARD)	+= gpio-viperboard.o
 obj-$(CONFIG_GPIO_VR41XX)	+= gpio-vr41xx.o
 obj-$(CONFIG_GPIO_VT8500)	+= gpio-vt8500.o
 obj-$(CONFIG_GPIO_VX855)	+= gpio-vx855.o
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index f05e542..464be96 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -105,7 +105,7 @@ static int gen_74x164_direction_output(struct gpio_chip *gc,
 	return 0;
 }
 
-static int __devinit gen_74x164_probe(struct spi_device *spi)
+static int gen_74x164_probe(struct spi_device *spi)
 {
 	struct gen_74x164_chip *chip;
 	struct gen_74x164_chip_platform_data *pdata;
@@ -181,7 +181,7 @@ exit_destroy:
 	return ret;
 }
 
-static int __devexit gen_74x164_remove(struct spi_device *spi)
+static int gen_74x164_remove(struct spi_device *spi)
 {
 	struct gen_74x164_chip *chip;
 	int ret;
@@ -215,7 +215,7 @@ static struct spi_driver gen_74x164_driver = {
 		.of_match_table	= of_match_ptr(gen_74x164_dt_ids),
 	},
 	.probe		= gen_74x164_probe,
-	.remove		= __devexit_p(gen_74x164_remove),
+	.remove		= gen_74x164_remove,
 };
 module_spi_driver(gen_74x164_driver);
 
diff --git a/drivers/gpio/gpio-ab8500.c b/drivers/gpio/gpio-ab8500.c
index 050c05d..983ad42 100644
--- a/drivers/gpio/gpio-ab8500.c
+++ b/drivers/gpio/gpio-ab8500.c
@@ -402,7 +402,7 @@ static void ab8500_gpio_irq_remove(struct ab8500_gpio *ab8500_gpio)
 	}
 }
 
-static int __devinit ab8500_gpio_probe(struct platform_device *pdev)
+static int ab8500_gpio_probe(struct platform_device *pdev)
 {
 	struct ab8500_platform_data *ab8500_pdata =
 				dev_get_platdata(pdev->dev.parent);
@@ -474,7 +474,7 @@ out_free:
  * ab8500_gpio_remove() - remove Ab8500-gpio driver
  * @pdev :	Platform device registered
  */
-static int __devexit ab8500_gpio_remove(struct platform_device *pdev)
+static int ab8500_gpio_remove(struct platform_device *pdev)
 {
 	struct ab8500_gpio *ab8500_gpio = platform_get_drvdata(pdev);
 	int ret;
@@ -499,7 +499,7 @@ static struct platform_driver ab8500_gpio_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ab8500_gpio_probe,
-	.remove = __devexit_p(ab8500_gpio_remove),
+	.remove = ab8500_gpio_remove,
 };
 
 static int __init ab8500_gpio_init(void)
diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
index 3df8833..e60567f 100644
--- a/drivers/gpio/gpio-adnp.c
+++ b/drivers/gpio/gpio-adnp.c
@@ -516,7 +516,7 @@ static void adnp_irq_teardown(struct adnp *adnp)
 	irq_domain_remove(adnp->domain);
 }
 
-static __devinit int adnp_i2c_probe(struct i2c_client *client,
+static int adnp_i2c_probe(struct i2c_client *client,
 				    const struct i2c_device_id *id)
 {
 	struct device_node *np = client->dev.of_node;
@@ -563,7 +563,7 @@ teardown:
 	return err;
 }
 
-static __devexit int adnp_i2c_remove(struct i2c_client *client)
+static int adnp_i2c_remove(struct i2c_client *client)
 {
 	struct adnp *adnp = i2c_get_clientdata(client);
 	struct device_node *np = client->dev.of_node;
@@ -582,13 +582,13 @@ static __devexit int adnp_i2c_remove(struct i2c_client *client)
 	return 0;
 }
 
-static const struct i2c_device_id adnp_i2c_id[] __devinitconst = {
+static const struct i2c_device_id adnp_i2c_id[] = {
 	{ "gpio-adnp" },
 	{ },
 };
 MODULE_DEVICE_TABLE(i2c, adnp_i2c_id);
 
-static const struct of_device_id adnp_of_match[] __devinitconst = {
+static const struct of_device_id adnp_of_match[] = {
 	{ .compatible = "ad,gpio-adnp", },
 	{ },
 };
@@ -601,7 +601,7 @@ static struct i2c_driver adnp_i2c_driver = {
 		.of_match_table = of_match_ptr(adnp_of_match),
 	},
 	.probe = adnp_i2c_probe,
-	.remove = __devexit_p(adnp_i2c_remove),
+	.remove = adnp_i2c_remove,
 	.id_table = adnp_i2c_id,
 };
 module_i2c_driver(adnp_i2c_driver);
diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c
index 2f263cc..8afa95f 100644
--- a/drivers/gpio/gpio-adp5520.c
+++ b/drivers/gpio/gpio-adp5520.c
@@ -87,7 +87,7 @@ static int adp5520_gpio_direction_output(struct gpio_chip *chip,
 	return ret;
 }
 
-static int __devinit adp5520_gpio_probe(struct platform_device *pdev)
+static int adp5520_gpio_probe(struct platform_device *pdev)
 {
 	struct adp5520_gpio_platform_data *pdata = pdev->dev.platform_data;
 	struct adp5520_gpio *dev;
@@ -167,7 +167,7 @@ err:
 	return ret;
 }
 
-static int __devexit adp5520_gpio_remove(struct platform_device *pdev)
+static int adp5520_gpio_remove(struct platform_device *pdev)
 {
 	struct adp5520_gpio *dev;
 	int ret;
@@ -190,7 +190,7 @@ static struct platform_driver adp5520_gpio_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= adp5520_gpio_probe,
-	.remove		= __devexit_p(adp5520_gpio_remove),
+	.remove		= adp5520_gpio_remove,
 };
 
 module_platform_driver(adp5520_gpio_driver);
diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c
index eeedad4..2ba5698 100644
--- a/drivers/gpio/gpio-adp5588.c
+++ b/drivers/gpio/gpio-adp5588.c
@@ -346,7 +346,7 @@ static void adp5588_irq_teardown(struct adp5588_gpio *dev)
 }
 #endif /* CONFIG_GPIO_ADP5588_IRQ */
 
-static int __devinit adp5588_gpio_probe(struct i2c_client *client,
+static int adp5588_gpio_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
@@ -438,7 +438,7 @@ err:
 	return ret;
 }
 
-static int __devexit adp5588_gpio_remove(struct i2c_client *client)
+static int adp5588_gpio_remove(struct i2c_client *client)
 {
 	struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
 	struct adp5588_gpio *dev = i2c_get_clientdata(client);
@@ -479,7 +479,7 @@ static struct i2c_driver adp5588_gpio_driver = {
 		   .name = DRV_NAME,
 		   },
 	.probe = adp5588_gpio_probe,
-	.remove = __devexit_p(adp5588_gpio_remove),
+	.remove = adp5588_gpio_remove,
 	.id_table = adp5588_gpio_id,
 };
 
diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
index 8740d2e..0ea853f 100644
--- a/drivers/gpio/gpio-arizona.c
+++ b/drivers/gpio/gpio-arizona.c
@@ -94,7 +94,7 @@ static struct gpio_chip template_chip = {
 	.can_sleep		= 1,
 };
 
-static int __devinit arizona_gpio_probe(struct platform_device *pdev)
+static int arizona_gpio_probe(struct platform_device *pdev)
 {
 	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
 	struct arizona_pdata *pdata = arizona->dev->platform_data;
@@ -141,7 +141,7 @@ err:
 	return ret;
 }
 
-static int __devexit arizona_gpio_remove(struct platform_device *pdev)
+static int arizona_gpio_remove(struct platform_device *pdev)
 {
 	struct arizona_gpio *arizona_gpio = platform_get_drvdata(pdev);
 
@@ -152,7 +152,7 @@ static struct platform_driver arizona_gpio_driver = {
 	.driver.name	= "arizona-gpio",
 	.driver.owner	= THIS_MODULE,
 	.probe		= arizona_gpio_probe,
-	.remove		= __devexit_p(arizona_gpio_remove),
+	.remove		= arizona_gpio_remove,
 };
 
 module_platform_driver(arizona_gpio_driver);
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c
new file mode 100644
index 0000000..ce63b75
--- /dev/null
+++ b/drivers/gpio/gpio-clps711x.c
@@ -0,0 +1,199 @@
+/*
+ *  CLPS711X GPIO driver
+ *
+ *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/io.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+
+#include <mach/hardware.h>
+
+#define CLPS711X_GPIO_PORTS	5
+#define CLPS711X_GPIO_NAME	"gpio-clps711x"
+
+struct clps711x_gpio {
+	struct gpio_chip	chip[CLPS711X_GPIO_PORTS];
+	spinlock_t		lock;
+};
+
+static void __iomem *clps711x_ports[] = {
+	CLPS711X_VIRT_BASE + PADR,
+	CLPS711X_VIRT_BASE + PBDR,
+	CLPS711X_VIRT_BASE + PCDR,
+	CLPS711X_VIRT_BASE + PDDR,
+	CLPS711X_VIRT_BASE + PEDR,
+};
+
+static void __iomem *clps711x_pdirs[] = {
+	CLPS711X_VIRT_BASE + PADDR,
+	CLPS711X_VIRT_BASE + PBDDR,
+	CLPS711X_VIRT_BASE + PCDDR,
+	CLPS711X_VIRT_BASE + PDDDR,
+	CLPS711X_VIRT_BASE + PEDDR,
+};
+
+#define clps711x_port(x)	clps711x_ports[x->base / 8]
+#define clps711x_pdir(x)	clps711x_pdirs[x->base / 8]
+
+static int gpio_clps711x_get(struct gpio_chip *chip, unsigned offset)
+{
+	return !!(readb(clps711x_port(chip)) & (1 << offset));
+}
+
+static void gpio_clps711x_set(struct gpio_chip *chip, unsigned offset,
+			      int value)
+{
+	int tmp;
+	unsigned long flags;
+	struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+	spin_lock_irqsave(&gpio->lock, flags);
+	tmp = readb(clps711x_port(chip)) & ~(1 << offset);
+	if (value)
+		tmp |= 1 << offset;
+	writeb(tmp, clps711x_port(chip));
+	spin_unlock_irqrestore(&gpio->lock, flags);
+}
+
+static int gpio_clps711x_dir_in(struct gpio_chip *chip, unsigned offset)
+{
+	int tmp;
+	unsigned long flags;
+	struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+	spin_lock_irqsave(&gpio->lock, flags);
+	tmp = readb(clps711x_pdir(chip)) & ~(1 << offset);
+	writeb(tmp, clps711x_pdir(chip));
+	spin_unlock_irqrestore(&gpio->lock, flags);
+
+	return 0;
+}
+
+static int gpio_clps711x_dir_out(struct gpio_chip *chip, unsigned offset,
+				 int value)
+{
+	int tmp;
+	unsigned long flags;
+	struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+	spin_lock_irqsave(&gpio->lock, flags);
+	tmp = readb(clps711x_pdir(chip)) | (1 << offset);
+	writeb(tmp, clps711x_pdir(chip));
+	tmp = readb(clps711x_port(chip)) & ~(1 << offset);
+	if (value)
+		tmp |= 1 << offset;
+	writeb(tmp, clps711x_port(chip));
+	spin_unlock_irqrestore(&gpio->lock, flags);
+
+	return 0;
+}
+
+static int gpio_clps711x_dir_in_inv(struct gpio_chip *chip, unsigned offset)
+{
+	int tmp;
+	unsigned long flags;
+	struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+	spin_lock_irqsave(&gpio->lock, flags);
+	tmp = readb(clps711x_pdir(chip)) | (1 << offset);
+	writeb(tmp, clps711x_pdir(chip));
+	spin_unlock_irqrestore(&gpio->lock, flags);
+
+	return 0;
+}
+
+static int gpio_clps711x_dir_out_inv(struct gpio_chip *chip, unsigned offset,
+				     int value)
+{
+	int tmp;
+	unsigned long flags;
+	struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+	spin_lock_irqsave(&gpio->lock, flags);
+	tmp = readb(clps711x_pdir(chip)) & ~(1 << offset);
+	writeb(tmp, clps711x_pdir(chip));
+	tmp = readb(clps711x_port(chip)) & ~(1 << offset);
+	if (value)
+		tmp |= 1 << offset;
+	writeb(tmp, clps711x_port(chip));
+	spin_unlock_irqrestore(&gpio->lock, flags);
+
+	return 0;
+}
+
+static struct {
+	char	*name;
+	int	nr;
+	int	inv_dir;
+} clps711x_gpio_ports[] __initconst = {
+	{ "PORTA", 8, 0, },
+	{ "PORTB", 8, 0, },
+	{ "PORTC", 8, 0, },
+	{ "PORTD", 8, 1, },
+	{ "PORTE", 3, 0, },
+};
+
+static int __init gpio_clps711x_init(void)
+{
+	int i;
+	struct platform_device *pdev;
+	struct clps711x_gpio *gpio;
+
+	pdev = platform_device_alloc(CLPS711X_GPIO_NAME, 0);
+	if (!pdev) {
+		pr_err("Cannot create platform device: %s\n",
+		       CLPS711X_GPIO_NAME);
+		return -ENOMEM;
+	}
+
+	platform_device_add(pdev);
+
+	gpio = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_gpio),
+			    GFP_KERNEL);
+	if (!gpio) {
+		dev_err(&pdev->dev, "GPIO allocating memory error\n");
+		platform_device_unregister(pdev);
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, gpio);
+
+	spin_lock_init(&gpio->lock);
+
+	for (i = 0; i < CLPS711X_GPIO_PORTS; i++) {
+		gpio->chip[i].owner		= THIS_MODULE;
+		gpio->chip[i].dev		= &pdev->dev;
+		gpio->chip[i].label		= clps711x_gpio_ports[i].name;
+		gpio->chip[i].base		= i * 8;
+		gpio->chip[i].ngpio		= clps711x_gpio_ports[i].nr;
+		gpio->chip[i].get		= gpio_clps711x_get;
+		gpio->chip[i].set		= gpio_clps711x_set;
+		if (!clps711x_gpio_ports[i].inv_dir) {
+			gpio->chip[i].direction_input = gpio_clps711x_dir_in;
+			gpio->chip[i].direction_output = gpio_clps711x_dir_out;
+		} else {
+			gpio->chip[i].direction_input = gpio_clps711x_dir_in_inv;
+			gpio->chip[i].direction_output = gpio_clps711x_dir_out_inv;
+		}
+		WARN_ON(gpiochip_add(&gpio->chip[i]));
+	}
+
+	dev_info(&pdev->dev, "GPIO driver initialized\n");
+
+	return 0;
+}
+arch_initcall(gpio_clps711x_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
+MODULE_DESCRIPTION("CLPS711X GPIO driver");
diff --git a/drivers/gpio/gpio-cs5535.c b/drivers/gpio/gpio-cs5535.c
index 19eda1b..c0a3aeb 100644
--- a/drivers/gpio/gpio-cs5535.c
+++ b/drivers/gpio/gpio-cs5535.c
@@ -300,7 +300,7 @@ static struct cs5535_gpio_chip cs5535_gpio_chip = {
 	},
 };
 
-static int __devinit cs5535_gpio_probe(struct platform_device *pdev)
+static int cs5535_gpio_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	int err = -EIO;
@@ -355,7 +355,7 @@ done:
 	return err;
 }
 
-static int __devexit cs5535_gpio_remove(struct platform_device *pdev)
+static int cs5535_gpio_remove(struct platform_device *pdev)
 {
 	struct resource *r;
 	int err;
@@ -378,7 +378,7 @@ static struct platform_driver cs5535_gpio_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = cs5535_gpio_probe,
-	.remove = __devexit_p(cs5535_gpio_remove),
+	.remove = cs5535_gpio_remove,
 };
 
 module_platform_driver(cs5535_gpio_driver);
diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c
index 24b8c29..29b11e9 100644
--- a/drivers/gpio/gpio-da9052.c
+++ b/drivers/gpio/gpio-da9052.c
@@ -185,10 +185,14 @@ static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset)
 	struct da9052_gpio *gpio = to_da9052_gpio(gc);
 	struct da9052 *da9052 = gpio->da9052;
 
-	return da9052->irq_base + DA9052_IRQ_GPI0 + offset;
+	int irq;
+
+	irq = regmap_irq_get_virq(da9052->irq_data, DA9052_IRQ_GPI0 + offset);
+
+	return irq;
 }
 
-static struct gpio_chip reference_gp __devinitdata = {
+static struct gpio_chip reference_gp = {
 	.label = "da9052-gpio",
 	.owner = THIS_MODULE,
 	.get = da9052_gpio_get,
@@ -201,7 +205,7 @@ static struct gpio_chip reference_gp __devinitdata = {
 	.base = -1,
 };
 
-static int __devinit da9052_gpio_probe(struct platform_device *pdev)
+static int da9052_gpio_probe(struct platform_device *pdev)
 {
 	struct da9052_gpio *gpio;
 	struct da9052_pdata *pdata;
@@ -229,7 +233,7 @@ static int __devinit da9052_gpio_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit da9052_gpio_remove(struct platform_device *pdev)
+static int da9052_gpio_remove(struct platform_device *pdev)
 {
 	struct da9052_gpio *gpio = platform_get_drvdata(pdev);
 
@@ -238,7 +242,7 @@ static int __devexit da9052_gpio_remove(struct platform_device *pdev)
 
 static struct platform_driver da9052_gpio_driver = {
 	.probe = da9052_gpio_probe,
-	.remove = __devexit_p(da9052_gpio_remove),
+	.remove = da9052_gpio_remove,
 	.driver = {
 		.name	= "da9052-gpio",
 		.owner	= THIS_MODULE,
diff --git a/drivers/gpio/gpio-da9055.c b/drivers/gpio/gpio-da9055.c
new file mode 100644
index 0000000..55d83c7
--- /dev/null
+++ b/drivers/gpio/gpio-da9055.c
@@ -0,0 +1,204 @@
+/*
+ * GPIO Driver for Dialog DA9055 PMICs.
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the 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/platform_device.h>
+#include <linux/gpio.h>
+
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/reg.h>
+#include <linux/mfd/da9055/pdata.h>
+
+#define DA9055_VDD_IO			0x0
+#define DA9055_PUSH_PULL		0x3
+#define DA9055_ACT_LOW			0x0
+#define DA9055_GPI			0x1
+#define DA9055_PORT_MASK		0x3
+#define DA9055_PORT_SHIFT(offset)	(4 * (offset % 2))
+
+#define DA9055_INPUT			DA9055_GPI
+#define DA9055_OUTPUT			DA9055_PUSH_PULL
+#define DA9055_IRQ_GPI0			3
+
+struct da9055_gpio {
+	struct da9055 *da9055;
+	struct gpio_chip gp;
+};
+
+static inline struct da9055_gpio *to_da9055_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct da9055_gpio, gp);
+}
+
+static int da9055_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+	struct da9055_gpio *gpio = to_da9055_gpio(gc);
+	int gpio_direction = 0;
+	int ret;
+
+	/* Get GPIO direction */
+	ret = da9055_reg_read(gpio->da9055, (offset >> 1) + DA9055_REG_GPIO0_1);
+	if (ret < 0)
+		return ret;
+
+	gpio_direction = ret & (DA9055_PORT_MASK) << DA9055_PORT_SHIFT(offset);
+	gpio_direction >>= DA9055_PORT_SHIFT(offset);
+	switch (gpio_direction) {
+	case DA9055_INPUT:
+		ret = da9055_reg_read(gpio->da9055, DA9055_REG_STATUS_B);
+		if (ret < 0)
+			return ret;
+		break;
+	case DA9055_OUTPUT:
+		ret = da9055_reg_read(gpio->da9055, DA9055_REG_GPIO_MODE0_2);
+		if (ret < 0)
+			return ret;
+	}
+
+	return ret & (1 << offset);
+
+}
+
+static void da9055_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+{
+	struct da9055_gpio *gpio = to_da9055_gpio(gc);
+
+	da9055_reg_update(gpio->da9055,
+			DA9055_REG_GPIO_MODE0_2,
+			1 << offset,
+			value << offset);
+}
+
+static int da9055_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+	struct da9055_gpio *gpio = to_da9055_gpio(gc);
+	unsigned char reg_byte;
+
+	reg_byte = (DA9055_ACT_LOW | DA9055_GPI)
+				<< DA9055_PORT_SHIFT(offset);
+
+	return da9055_reg_update(gpio->da9055, (offset >> 1) +
+				DA9055_REG_GPIO0_1,
+				DA9055_PORT_MASK <<
+				DA9055_PORT_SHIFT(offset),
+				reg_byte);
+}
+
+static int da9055_gpio_direction_output(struct gpio_chip *gc,
+					unsigned offset, int value)
+{
+	struct da9055_gpio *gpio = to_da9055_gpio(gc);
+	unsigned char reg_byte;
+	int ret;
+
+	reg_byte = (DA9055_VDD_IO | DA9055_PUSH_PULL)
+					<< DA9055_PORT_SHIFT(offset);
+
+	ret = da9055_reg_update(gpio->da9055, (offset >> 1) +
+				DA9055_REG_GPIO0_1,
+				DA9055_PORT_MASK <<
+				DA9055_PORT_SHIFT(offset),
+				reg_byte);
+	if (ret < 0)
+		return ret;
+
+	da9055_gpio_set(gc, offset, value);
+
+	return 0;
+}
+
+static int da9055_gpio_to_irq(struct gpio_chip *gc, u32 offset)
+{
+	struct da9055_gpio *gpio = to_da9055_gpio(gc);
+	struct da9055 *da9055 = gpio->da9055;
+
+	return regmap_irq_get_virq(da9055->irq_data,
+				  DA9055_IRQ_GPI0 + offset);
+}
+
+static struct gpio_chip reference_gp __devinitdata = {
+	.label = "da9055-gpio",
+	.owner = THIS_MODULE,
+	.get = da9055_gpio_get,
+	.set = da9055_gpio_set,
+	.direction_input = da9055_gpio_direction_input,
+	.direction_output = da9055_gpio_direction_output,
+	.to_irq = da9055_gpio_to_irq,
+	.can_sleep = 1,
+	.ngpio = 3,
+	.base = -1,
+};
+
+static int __devinit da9055_gpio_probe(struct platform_device *pdev)
+{
+	struct da9055_gpio *gpio;
+	struct da9055_pdata *pdata;
+	int ret;
+
+	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+	if (gpio == NULL)
+		return -ENOMEM;
+
+	gpio->da9055 = dev_get_drvdata(pdev->dev.parent);
+	pdata = gpio->da9055->dev->platform_data;
+
+	gpio->gp = reference_gp;
+	if (pdata && pdata->gpio_base)
+		gpio->gp.base = pdata->gpio_base;
+
+	ret = gpiochip_add(&gpio->gp);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
+		goto err_mem;
+	}
+
+	platform_set_drvdata(pdev, gpio);
+
+	return 0;
+
+err_mem:
+	return ret;
+}
+
+static int __devexit da9055_gpio_remove(struct platform_device *pdev)
+{
+	struct da9055_gpio *gpio = platform_get_drvdata(pdev);
+
+	return gpiochip_remove(&gpio->gp);
+}
+
+static struct platform_driver da9055_gpio_driver = {
+	.probe = da9055_gpio_probe,
+	.remove = __devexit_p(da9055_gpio_remove),
+	.driver = {
+		.name	= "da9055-gpio",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init da9055_gpio_init(void)
+{
+	return platform_driver_register(&da9055_gpio_driver);
+}
+subsys_initcall(da9055_gpio_init);
+
+static void __exit da9055_gpio_exit(void)
+{
+	platform_driver_unregister(&da9055_gpio_driver);
+}
+module_exit(da9055_gpio_exit);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("DA9055 GPIO Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9055-gpio");
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
index efb4c2d..bdc8302 100644
--- a/drivers/gpio/gpio-em.c
+++ b/drivers/gpio/gpio-em.c
@@ -35,7 +35,6 @@
 struct em_gio_priv {
 	void __iomem *base0;
 	void __iomem *base1;
-	unsigned int irq_base;
 	spinlock_t sense_lock;
 	struct platform_device *pdev;
 	struct gpio_chip gpio_chip;
@@ -214,7 +213,7 @@ static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset,
 
 static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
-	return irq_find_mapping(gpio_to_priv(chip)->irq_domain, offset);
+	return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset);
 }
 
 static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq,
@@ -234,41 +233,7 @@ static struct irq_domain_ops em_gio_irq_domain_ops = {
 	.map	= em_gio_irq_domain_map,
 };
 
-static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p)
-{
-	struct platform_device *pdev = p->pdev;
-	struct gpio_em_config *pdata = pdev->dev.platform_data;
-
-	p->irq_base = irq_alloc_descs(pdata->irq_base, 0,
-				      pdata->number_of_pins, numa_node_id());
-	if (p->irq_base < 0) {
-		dev_err(&pdev->dev, "cannot get irq_desc\n");
-		return p->irq_base;
-	}
-	pr_debug("gio: hw base = %d, nr = %d, sw base = %d\n",
-		 pdata->gpio_base, pdata->number_of_pins, p->irq_base);
-
-	p->irq_domain = irq_domain_add_legacy(pdev->dev.of_node,
-					      pdata->number_of_pins,
-					      p->irq_base, 0,
-					      &em_gio_irq_domain_ops, p);
-	if (!p->irq_domain) {
-		irq_free_descs(p->irq_base, pdata->number_of_pins);
-		return -ENXIO;
-	}
-
-	return 0;
-}
-
-static void em_gio_irq_domain_cleanup(struct em_gio_priv *p)
-{
-	struct gpio_em_config *pdata = p->pdev->dev.platform_data;
-
-	irq_free_descs(p->irq_base, pdata->number_of_pins);
-	/* FIXME: irq domain wants to be freed! */
-}
-
-static int __devinit em_gio_probe(struct platform_device *pdev)
+static int em_gio_probe(struct platform_device *pdev)
 {
 	struct gpio_em_config *pdata = pdev->dev.platform_data;
 	struct em_gio_priv *p;
@@ -334,8 +299,11 @@ static int __devinit em_gio_probe(struct platform_device *pdev)
 	irq_chip->irq_set_type = em_gio_irq_set_type;
 	irq_chip->flags	= IRQCHIP_SKIP_SET_WAKE;
 
-	ret = em_gio_irq_domain_init(p);
-	if (ret) {
+	p->irq_domain = irq_domain_add_linear(pdev->dev.of_node,
+					      pdata->number_of_pins,
+					      &em_gio_irq_domain_ops, p);
+	if (!p->irq_domain) {
+		ret = -ENXIO;
 		dev_err(&pdev->dev, "cannot initialize irq domain\n");
 		goto err3;
 	}
@@ -364,7 +332,7 @@ err6:
 err5:
 	free_irq(irq[0]->start, pdev);
 err4:
-	em_gio_irq_domain_cleanup(p);
+	irq_domain_remove(p->irq_domain);
 err3:
 	iounmap(p->base1);
 err2:
@@ -375,7 +343,7 @@ err0:
 	return ret;
 }
 
-static int __devexit em_gio_remove(struct platform_device *pdev)
+static int em_gio_remove(struct platform_device *pdev)
 {
 	struct em_gio_priv *p = platform_get_drvdata(pdev);
 	struct resource *irq[2];
@@ -390,7 +358,7 @@ static int __devexit em_gio_remove(struct platform_device *pdev)
 
 	free_irq(irq[1]->start, pdev);
 	free_irq(irq[0]->start, pdev);
-	em_gio_irq_domain_cleanup(p);
+	irq_domain_remove(p->irq_domain);
 	iounmap(p->base1);
 	iounmap(p->base0);
 	kfree(p);
@@ -399,7 +367,7 @@ static int __devexit em_gio_remove(struct platform_device *pdev)
 
 static struct platform_driver em_gio_device_driver = {
 	.probe		= em_gio_probe,
-	.remove		= __devexit_p(em_gio_remove),
+	.remove		= em_gio_remove,
 	.driver		= {
 		.name	= "em_gio",
 	}
diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c
index 9fe5b8fe..56b98ee 100644
--- a/drivers/gpio/gpio-ep93xx.c
+++ b/drivers/gpio/gpio-ep93xx.c
@@ -340,7 +340,7 @@ static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev,
 	return gpiochip_add(&bgc->gc);
 }
 
-static int __devinit ep93xx_gpio_probe(struct platform_device *pdev)
+static int ep93xx_gpio_probe(struct platform_device *pdev)
 {
 	struct ep93xx_gpio *ep93xx_gpio;
 	struct resource *res;
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
index 82e2e4f..05fcc0f 100644
--- a/drivers/gpio/gpio-generic.c
+++ b/drivers/gpio/gpio-generic.c
@@ -444,7 +444,7 @@ static void __iomem *bgpio_map(struct platform_device *pdev,
 	return ret;
 }
 
-static int __devinit bgpio_pdev_probe(struct platform_device *pdev)
+static int bgpio_pdev_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct resource *r;
@@ -507,7 +507,7 @@ static int __devinit bgpio_pdev_probe(struct platform_device *pdev)
 	return gpiochip_add(&bgc->gc);
 }
 
-static int __devexit bgpio_pdev_remove(struct platform_device *pdev)
+static int bgpio_pdev_remove(struct platform_device *pdev)
 {
 	struct bgpio_chip *bgc = platform_get_drvdata(pdev);
 
@@ -527,7 +527,7 @@ static struct platform_driver bgpio_driver = {
 	},
 	.id_table = bgpio_id_table,
 	.probe = bgpio_pdev_probe,
-	.remove = __devexit_p(bgpio_pdev_remove),
+	.remove = bgpio_pdev_remove,
 };
 
 module_platform_driver(bgpio_driver);
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c
index d4d6179..6cc87ac 100644
--- a/drivers/gpio/gpio-ich.c
+++ b/drivers/gpio/gpio-ich.c
@@ -238,7 +238,7 @@ static void ichx_gpio_set(struct gpio_chip *chip, unsigned nr, int val)
 	ichx_write_bit(GPIO_LVL, nr, val, 0);
 }
 
-static void __devinit ichx_gpiolib_setup(struct gpio_chip *chip)
+static void ichx_gpiolib_setup(struct gpio_chip *chip)
 {
 	chip->owner = THIS_MODULE;
 	chip->label = DRV_NAME;
@@ -313,7 +313,7 @@ static struct ichx_desc intel5_desc = {
 	.ngpio = 76,
 };
 
-static int __devinit ichx_gpio_request_regions(struct resource *res_base,
+static int ichx_gpio_request_regions(struct resource *res_base,
 						const char *name, u8 use_gpio)
 {
 	int i;
@@ -353,7 +353,7 @@ static void ichx_gpio_release_regions(struct resource *res_base, u8 use_gpio)
 	}
 }
 
-static int __devinit ichx_gpio_probe(struct platform_device *pdev)
+static int ichx_gpio_probe(struct platform_device *pdev)
 {
 	struct resource *res_base, *res_pm;
 	int err;
@@ -442,7 +442,7 @@ add_err:
 	return err;
 }
 
-static int __devexit ichx_gpio_remove(struct platform_device *pdev)
+static int ichx_gpio_remove(struct platform_device *pdev)
 {
 	int err;
 
@@ -467,7 +467,7 @@ static struct platform_driver ichx_gpio_driver = {
 		.name	= DRV_NAME,
 	},
 	.probe		= ichx_gpio_probe,
-	.remove		= __devexit_p(ichx_gpio_remove),
+	.remove		= ichx_gpio_remove,
 };
 
 module_platform_driver(ichx_gpio_driver);
diff --git a/drivers/gpio/gpio-janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c
index f2f000d..7d0a041 100644
--- a/drivers/gpio/gpio-janz-ttl.c
+++ b/drivers/gpio/gpio-janz-ttl.c
@@ -108,13 +108,13 @@ static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value)
 	spin_unlock(&mod->lock);
 }
 
-static void __devinit ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
+static void ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
 {
 	iowrite16be(reg, &mod->regs->control);
 	iowrite16be(val, &mod->regs->control);
 }
 
-static void __devinit ttl_setup_device(struct ttl_module *mod)
+static void ttl_setup_device(struct ttl_module *mod)
 {
 	/* reset the device to a known state */
 	iowrite16be(0x0000, &mod->regs->control);
@@ -140,7 +140,7 @@ static void __devinit ttl_setup_device(struct ttl_module *mod)
 	ttl_write_reg(mod, MASTER_CONF_CTL, CONF_PAE | CONF_PBE | CONF_PCE);
 }
 
-static int __devinit ttl_probe(struct platform_device *pdev)
+static int ttl_probe(struct platform_device *pdev)
 {
 	struct janz_platform_data *pdata;
 	struct device *dev = &pdev->dev;
@@ -211,7 +211,7 @@ out_return:
 	return ret;
 }
 
-static int __devexit ttl_remove(struct platform_device *pdev)
+static int ttl_remove(struct platform_device *pdev)
 {
 	struct ttl_module *mod = platform_get_drvdata(pdev);
 	struct device *dev = &pdev->dev;
@@ -234,7 +234,7 @@ static struct platform_driver ttl_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= ttl_probe,
-	.remove		= __devexit_p(ttl_remove),
+	.remove		= ttl_remove,
 };
 
 module_platform_driver(ttl_driver);
diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c
index 202a992..e77b2b3 100644
--- a/drivers/gpio/gpio-langwell.c
+++ b/drivers/gpio/gpio-langwell.c
@@ -332,7 +332,7 @@ static const struct dev_pm_ops lnw_gpio_pm_ops = {
 	.runtime_idle = lnw_gpio_runtime_idle,
 };
 
-static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
+static int lnw_gpio_probe(struct pci_dev *pdev,
 			const struct pci_device_id *id)
 {
 	void *base;
@@ -435,7 +435,7 @@ static struct pci_driver lnw_gpio_driver = {
 };
 
 
-static int __devinit wp_gpio_probe(struct platform_device *pdev)
+static int wp_gpio_probe(struct platform_device *pdev)
 {
 	struct lnw_gpio *lnw;
 	struct gpio_chip *gc;
@@ -484,7 +484,7 @@ err_kmalloc:
 	return retval;
 }
 
-static int __devexit wp_gpio_remove(struct platform_device *pdev)
+static int wp_gpio_remove(struct platform_device *pdev)
 {
 	struct lnw_gpio *lnw = platform_get_drvdata(pdev);
 	int err;
@@ -499,7 +499,7 @@ static int __devexit wp_gpio_remove(struct platform_device *pdev)
 
 static struct platform_driver wp_gpio_driver = {
 	.probe		= wp_gpio_probe,
-	.remove		= __devexit_p(wp_gpio_remove),
+	.remove		= wp_gpio_remove,
 	.driver		= {
 		.name	= "wp_gpio",
 		.owner	= THIS_MODULE,
diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c
index 3644e0d..36d7dee 100644
--- a/drivers/gpio/gpio-lpc32xx.c
+++ b/drivers/gpio/gpio-lpc32xx.c
@@ -542,7 +542,7 @@ static int lpc32xx_of_xlate(struct gpio_chip *gc,
 	return gpiospec->args[1];
 }
 
-static int __devinit lpc32xx_gpio_probe(struct platform_device *pdev)
+static int lpc32xx_gpio_probe(struct platform_device *pdev)
 {
 	int i;
 
@@ -559,7 +559,7 @@ static int __devinit lpc32xx_gpio_probe(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_OF
-static struct of_device_id lpc32xx_gpio_of_match[] __devinitdata = {
+static struct of_device_id lpc32xx_gpio_of_match[] = {
 	{ .compatible = "nxp,lpc3220-gpio", },
 	{ },
 };
diff --git a/drivers/gpio/gpio-max7300.c b/drivers/gpio/gpio-max7300.c
index a5ca0ab..4b6b9a0 100644
--- a/drivers/gpio/gpio-max7300.c
+++ b/drivers/gpio/gpio-max7300.c
@@ -31,7 +31,7 @@ static int max7300_i2c_read(struct device *dev, unsigned int reg)
 	return i2c_smbus_read_byte_data(client, reg);
 }
 
-static int __devinit max7300_probe(struct i2c_client *client,
+static int max7300_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct max7301 *ts;
@@ -55,7 +55,7 @@ static int __devinit max7300_probe(struct i2c_client *client,
 	return ret;
 }
 
-static int __devexit max7300_remove(struct i2c_client *client)
+static int max7300_remove(struct i2c_client *client)
 {
 	return __max730x_remove(&client->dev);
 }
@@ -72,7 +72,7 @@ static struct i2c_driver max7300_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = max7300_probe,
-	.remove = __devexit_p(max7300_remove),
+	.remove = max7300_remove,
 	.id_table = max7300_id,
 };
 
diff --git a/drivers/gpio/gpio-max7301.c b/drivers/gpio/gpio-max7301.c
index 741acfc..c6c535c 100644
--- a/drivers/gpio/gpio-max7301.c
+++ b/drivers/gpio/gpio-max7301.c
@@ -50,7 +50,7 @@ static int max7301_spi_read(struct device *dev, unsigned int reg)
 	return word & 0xff;
 }
 
-static int __devinit max7301_probe(struct spi_device *spi)
+static int max7301_probe(struct spi_device *spi)
 {
 	struct max7301 *ts;
 	int ret;
@@ -75,7 +75,7 @@ static int __devinit max7301_probe(struct spi_device *spi)
 	return ret;
 }
 
-static int __devexit max7301_remove(struct spi_device *spi)
+static int max7301_remove(struct spi_device *spi)
 {
 	return __max730x_remove(&spi->dev);
 }
@@ -92,7 +92,7 @@ static struct spi_driver max7301_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = max7301_probe,
-	.remove = __devexit_p(max7301_remove),
+	.remove = max7301_remove,
 	.id_table = max7301_id,
 };
 
diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c
index 05e2dac..0009234 100644
--- a/drivers/gpio/gpio-max730x.c
+++ b/drivers/gpio/gpio-max730x.c
@@ -160,17 +160,13 @@ static void max7301_set(struct gpio_chip *chip, unsigned offset, int value)
 	mutex_unlock(&ts->lock);
 }
 
-int __devinit __max730x_probe(struct max7301 *ts)
+int __max730x_probe(struct max7301 *ts)
 {
 	struct device *dev = ts->dev;
 	struct max7301_platform_data *pdata;
 	int i, ret;
 
 	pdata = dev->platform_data;
-	if (!pdata || !pdata->base) {
-		dev_err(dev, "incorrect or missing platform data\n");
-		return -EINVAL;
-	}
 
 	mutex_init(&ts->lock);
 	dev_set_drvdata(dev, ts);
@@ -178,7 +174,12 @@ int __devinit __max730x_probe(struct max7301 *ts)
 	/* Power up the chip and disable IRQ output */
 	ts->write(dev, 0x04, 0x01);
 
-	ts->input_pullup_active = pdata->input_pullup_active;
+	if (pdata) {
+		ts->input_pullup_active = pdata->input_pullup_active;
+		ts->chip.base = pdata->base;
+	} else {
+		ts->chip.base = -1;
+	}
 	ts->chip.label = dev->driver->name;
 
 	ts->chip.direction_input = max7301_direction_input;
@@ -186,7 +187,6 @@ int __devinit __max730x_probe(struct max7301 *ts)
 	ts->chip.direction_output = max7301_direction_output;
 	ts->chip.set = max7301_set;
 
-	ts->chip.base = pdata->base;
 	ts->chip.ngpio = PIN_NUMBER;
 	ts->chip.can_sleep = 1;
 	ts->chip.dev = dev;
@@ -226,7 +226,7 @@ exit_destroy:
 }
 EXPORT_SYMBOL_GPL(__max730x_probe);
 
-int __devexit __max730x_remove(struct device *dev)
+int __max730x_remove(struct device *dev)
 {
 	struct max7301 *ts = dev_get_drvdata(dev);
 	int ret;
diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c
index 9504120..1e0467c 100644
--- a/drivers/gpio/gpio-max732x.c
+++ b/drivers/gpio/gpio-max732x.c
@@ -526,7 +526,7 @@ static void max732x_irq_teardown(struct max732x_chip *chip)
 }
 #endif
 
-static int __devinit max732x_setup_gpio(struct max732x_chip *chip,
+static int max732x_setup_gpio(struct max732x_chip *chip,
 					const struct i2c_device_id *id,
 					unsigned gpio_start)
 {
@@ -574,7 +574,7 @@ static int __devinit max732x_setup_gpio(struct max732x_chip *chip,
 	return port;
 }
 
-static int __devinit max732x_probe(struct i2c_client *client,
+static int max732x_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
 	struct max732x_platform_data *pdata;
@@ -651,7 +651,7 @@ out_failed:
 	return ret;
 }
 
-static int __devexit max732x_remove(struct i2c_client *client)
+static int max732x_remove(struct i2c_client *client)
 {
 	struct max732x_platform_data *pdata = client->dev.platform_data;
 	struct max732x_chip *chip = i2c_get_clientdata(client);
@@ -690,7 +690,7 @@ static struct i2c_driver max732x_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= max732x_probe,
-	.remove		= __devexit_p(max732x_remove),
+	.remove		= max732x_remove,
 	.id_table	= max732x_id,
 };
 
diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c
index 2de57ce..6a8fdc2 100644
--- a/drivers/gpio/gpio-mc33880.c
+++ b/drivers/gpio/gpio-mc33880.c
@@ -80,7 +80,7 @@ static void mc33880_set(struct gpio_chip *chip, unsigned offset, int value)
 	mutex_unlock(&mc->lock);
 }
 
-static int __devinit mc33880_probe(struct spi_device *spi)
+static int mc33880_probe(struct spi_device *spi)
 {
 	struct mc33880 *mc;
 	struct mc33880_platform_data *pdata;
@@ -147,7 +147,7 @@ exit_destroy:
 	return ret;
 }
 
-static int __devexit mc33880_remove(struct spi_device *spi)
+static int mc33880_remove(struct spi_device *spi)
 {
 	struct mc33880 *mc;
 	int ret;
@@ -175,7 +175,7 @@ static struct spi_driver mc33880_driver = {
 		.owner		= THIS_MODULE,
 	},
 	.probe		= mc33880_probe,
-	.remove		= __devexit_p(mc33880_remove),
+	.remove		= mc33880_remove,
 };
 
 static int __init mc33880_init(void)
diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c
index ce1c847..3cea0ea 100644
--- a/drivers/gpio/gpio-mcp23s08.c
+++ b/drivers/gpio/gpio-mcp23s08.c
@@ -475,7 +475,7 @@ fail:
 
 #if IS_ENABLED(CONFIG_I2C)
 
-static int __devinit mcp230xx_probe(struct i2c_client *client,
+static int mcp230xx_probe(struct i2c_client *client,
 				    const struct i2c_device_id *id)
 {
 	struct mcp23s08_platform_data *pdata;
@@ -508,7 +508,7 @@ fail:
 	return status;
 }
 
-static int __devexit mcp230xx_remove(struct i2c_client *client)
+static int mcp230xx_remove(struct i2c_client *client)
 {
 	struct mcp23s08 *mcp = i2c_get_clientdata(client);
 	int status;
@@ -533,7 +533,7 @@ static struct i2c_driver mcp230xx_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= mcp230xx_probe,
-	.remove		= __devexit_p(mcp230xx_remove),
+	.remove		= mcp230xx_remove,
 	.id_table	= mcp230xx_id,
 };
 
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
index 6a29ee1..b733665 100644
--- a/drivers/gpio/gpio-ml-ioh.c
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -385,7 +385,7 @@ static irqreturn_t ioh_gpio_handler(int irq, void *dev_id)
 	return ret;
 }
 
-static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
+static void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
 				unsigned int irq_start, unsigned int num)
 {
 	struct irq_chip_generic *gc;
@@ -406,7 +406,7 @@ static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
 			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 }
 
-static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
+static int ioh_gpio_probe(struct pci_dev *pdev,
 				    const struct pci_device_id *id)
 {
 	int ret;
@@ -517,7 +517,7 @@ err_pci_enable:
 	return ret;
 }
 
-static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
+static void ioh_gpio_remove(struct pci_dev *pdev)
 {
 	int err;
 	int i;
@@ -606,7 +606,7 @@ static struct pci_driver ioh_gpio_driver = {
 	.name = "ml_ioh_gpio",
 	.id_table = ioh_gpio_pcidev_id,
 	.probe = ioh_gpio_probe,
-	.remove = __devexit_p(ioh_gpio_remove),
+	.remove = ioh_gpio_remove,
 	.suspend = ioh_gpio_suspend,
 	.resume = ioh_gpio_resume
 };
diff --git a/drivers/gpio/gpio-mpc5200.c b/drivers/gpio/gpio-mpc5200.c
index 2c7cef3..42647f2 100644
--- a/drivers/gpio/gpio-mpc5200.c
+++ b/drivers/gpio/gpio-mpc5200.c
@@ -148,7 +148,7 @@ mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 	return 0;
 }
 
-static int __devinit mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
+static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
 {
 	struct mpc52xx_gpiochip *chip;
 	struct mpc52xx_gpio_wkup __iomem *regs;
@@ -308,7 +308,7 @@ mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 	return 0;
 }
 
-static int __devinit mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
+static int mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
 {
 	struct mpc52xx_gpiochip *chip;
 	struct gpio_chip *gc;
diff --git a/drivers/gpio/gpio-msic.c b/drivers/gpio/gpio-msic.c
index b389862..27ea7b9 100644
--- a/drivers/gpio/gpio-msic.c
+++ b/drivers/gpio/gpio-msic.c
@@ -256,7 +256,7 @@ static void msic_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 	chip->irq_eoi(data);
 }
 
-static int __devinit platform_msic_gpio_probe(struct platform_device *pdev)
+static int platform_msic_gpio_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct intel_msic_gpio_pdata *pdata = dev->platform_data;
diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c
index 38305be..55a7e77 100644
--- a/drivers/gpio/gpio-msm-v2.c
+++ b/drivers/gpio/gpio-msm-v2.c
@@ -352,7 +352,7 @@ static struct irq_chip msm_gpio_irq_chip = {
 	.irq_set_wake	= msm_gpio_irq_set_wake,
 };
 
-static int __devinit msm_gpio_probe(struct platform_device *dev)
+static int msm_gpio_probe(struct platform_device *dev)
 {
 	int i, irq, ret;
 
@@ -376,7 +376,7 @@ static int __devinit msm_gpio_probe(struct platform_device *dev)
 	return 0;
 }
 
-static int __devexit msm_gpio_remove(struct platform_device *dev)
+static int msm_gpio_remove(struct platform_device *dev)
 {
 	int ret = gpiochip_remove(&msm_gpio.gpio_chip);
 
@@ -390,7 +390,7 @@ static int __devexit msm_gpio_remove(struct platform_device *dev)
 
 static struct platform_driver msm_gpio_driver = {
 	.probe = msm_gpio_probe,
-	.remove = __devexit_p(msm_gpio_remove),
+	.remove = msm_gpio_remove,
 	.driver = {
 		.name = "msmgpio",
 		.owner = THIS_MODULE,
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index be65c04..d767b53 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -168,12 +168,12 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
  * Functions implementing the gpio_chip methods
  */
 
-int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin)
+static int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin)
 {
 	return pinctrl_request_gpio(chip->base + pin);
 }
 
-void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin)
+static void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin)
 {
 	pinctrl_free_gpio(chip->base + pin);
 }
@@ -482,7 +482,7 @@ static struct platform_device_id mvebu_gpio_ids[] = {
 };
 MODULE_DEVICE_TABLE(platform, mvebu_gpio_ids);
 
-static struct of_device_id mvebu_gpio_of_match[] __devinitdata = {
+static struct of_device_id mvebu_gpio_of_match[] = {
 	{
 		.compatible = "marvell,orion-gpio",
 		.data       = (void*) MVEBU_GPIO_SOC_VARIANT_ORION,
@@ -501,7 +501,7 @@ static struct of_device_id mvebu_gpio_of_match[] __devinitdata = {
 };
 MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match);
 
-static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
+static int mvebu_gpio_probe(struct platform_device *pdev)
 {
 	struct mvebu_gpio_chip *mvchip;
 	const struct of_device_id *match;
@@ -546,6 +546,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
 	mvchip->chip.label = dev_name(&pdev->dev);
 	mvchip->chip.dev = &pdev->dev;
 	mvchip->chip.request = mvebu_gpio_request;
+	mvchip->chip.free = mvebu_gpio_free;
 	mvchip->chip.direction_input = mvebu_gpio_direction_input;
 	mvchip->chip.get = mvebu_gpio_get;
 	mvchip->chip.direction_output = mvebu_gpio_direction_output;
@@ -673,8 +674,8 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
 			       IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
 
 	/* Setup irq domain on top of the generic chip. */
-	mvchip->domain = irq_domain_add_legacy(np, mvchip->chip.ngpio,
-					       mvchip->irqbase, 0,
+	mvchip->domain = irq_domain_add_simple(np, mvchip->chip.ngpio,
+					       mvchip->irqbase,
 					       &irq_domain_simple_ops,
 					       mvchip);
 	if (!mvchip->domain) {
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 80f44bb..7877335 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -356,7 +356,7 @@ static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
 			       IRQ_NOREQUEST, 0);
 }
 
-static void __devinit mxc_gpio_get_hw(struct platform_device *pdev)
+static void mxc_gpio_get_hw(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id =
 			of_match_device(mxc_gpio_dt_ids, &pdev->dev);
@@ -395,7 +395,7 @@ static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
 	return irq_find_mapping(port->domain, offset);
 }
 
-static int __devinit mxc_gpio_probe(struct platform_device *pdev)
+static int mxc_gpio_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct mxc_gpio_port *port;
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
index 796fb13..fa2a63c 100644
--- a/drivers/gpio/gpio-mxs.c
+++ b/drivers/gpio/gpio-mxs.c
@@ -214,7 +214,7 @@ static const struct of_device_id mxs_gpio_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, mxs_gpio_dt_ids);
 
-static int __devinit mxs_gpio_probe(struct platform_device *pdev)
+static int mxs_gpio_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id =
 			of_match_device(mxs_gpio_dt_ids, &pdev->dev);
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index d335af1..f1fbedb2 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -1012,7 +1012,7 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
 		dev_err(bank->dev, "Could not get gpio dbck\n");
 }
 
-static __devinit void
+static void
 omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
 		    unsigned int num)
 {
@@ -1041,7 +1041,7 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
 			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 }
 
-static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
+static void omap_gpio_chip_init(struct gpio_bank *bank)
 {
 	int j;
 	static int gpio;
@@ -1089,7 +1089,7 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
 
 static const struct of_device_id omap_gpio_match[];
 
-static int __devinit omap_gpio_probe(struct platform_device *pdev)
+static int omap_gpio_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *node = dev->of_node;
@@ -1105,7 +1105,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
 	if (!pdata)
 		return -EINVAL;
 
-	bank = devm_kzalloc(&pdev->dev, sizeof(struct gpio_bank), GFP_KERNEL);
+	bank = devm_kzalloc(dev, sizeof(struct gpio_bank), GFP_KERNEL);
 	if (!bank) {
 		dev_err(dev, "Memory alloc failed\n");
 		return -ENOMEM;
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 9c693ae..cc102d2 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -16,6 +16,7 @@
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pca953x.h>
 #include <linux/slab.h>
@@ -83,6 +84,7 @@ struct pca953x_chip {
 	u32 irq_trig_raise;
 	u32 irq_trig_fall;
 	int	 irq_base;
+	struct irq_domain *domain;
 #endif
 
 	struct i2c_client *client;
@@ -333,14 +335,14 @@ static void pca953x_irq_mask(struct irq_data *d)
 {
 	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
 
-	chip->irq_mask &= ~(1 << (d->irq - chip->irq_base));
+	chip->irq_mask &= ~(1 << d->hwirq);
 }
 
 static void pca953x_irq_unmask(struct irq_data *d)
 {
 	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
 
-	chip->irq_mask |= 1 << (d->irq - chip->irq_base);
+	chip->irq_mask |= 1 << d->hwirq;
 }
 
 static void pca953x_irq_bus_lock(struct irq_data *d)
@@ -372,8 +374,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
 static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
 {
 	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
-	u32 level = d->irq - chip->irq_base;
-	u32 mask = 1 << level;
+	u32 mask = 1 << d->hwirq;
 
 	if (!(type & IRQ_TYPE_EDGE_BOTH)) {
 		dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
@@ -454,7 +455,7 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
 
 	do {
 		level = __ffs(pending);
-		handle_nested_irq(level + chip->irq_base);
+		handle_nested_irq(irq_find_mapping(chip->domain, level));
 
 		pending &= ~(1 << level);
 	} while (pending);
@@ -499,6 +500,17 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
 		if (chip->irq_base < 0)
 			goto out_failed;
 
+		chip->domain = irq_domain_add_legacy(client->dev.of_node,
+						chip->gpio_chip.ngpio,
+						chip->irq_base,
+						0,
+						&irq_domain_simple_ops,
+						NULL);
+		if (!chip->domain) {
+			ret = -ENODEV;
+			goto out_irqdesc_free;
+		}
+
 		for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
 			int irq = lvl + chip->irq_base;
 
@@ -521,7 +533,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
 		if (ret) {
 			dev_err(&client->dev, "failed to request irq %d\n",
 				client->irq);
-			goto out_failed;
+			goto out_irqdesc_free;
 		}
 
 		chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
@@ -529,6 +541,8 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
 
 	return 0;
 
+out_irqdesc_free:
+	irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio);
 out_failed:
 	chip->irq_base = -1;
 	return ret;
@@ -602,7 +616,7 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert)
 }
 #endif
 
-static int __devinit device_pca953x_init(struct pca953x_chip *chip, u32 invert)
+static int device_pca953x_init(struct pca953x_chip *chip, u32 invert)
 {
 	int ret;
 
@@ -621,7 +635,7 @@ out:
 	return ret;
 }
 
-static int __devinit device_pca957x_init(struct pca953x_chip *chip, u32 invert)
+static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
 {
 	int ret;
 	u32 val = 0;
@@ -652,7 +666,7 @@ out:
 	return ret;
 }
 
-static int __devinit pca953x_probe(struct i2c_client *client,
+static int pca953x_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
 	struct pca953x_platform_data *pdata;
@@ -751,9 +765,38 @@ static int pca953x_remove(struct i2c_client *client)
 	return 0;
 }
 
+static const struct of_device_id pca953x_dt_ids[] = {
+	{ .compatible = "nxp,pca9534", },
+	{ .compatible = "nxp,pca9535", },
+	{ .compatible = "nxp,pca9536", },
+	{ .compatible = "nxp,pca9537", },
+	{ .compatible = "nxp,pca9538", },
+	{ .compatible = "nxp,pca9539", },
+	{ .compatible = "nxp,pca9554", },
+	{ .compatible = "nxp,pca9555", },
+	{ .compatible = "nxp,pca9556", },
+	{ .compatible = "nxp,pca9557", },
+	{ .compatible = "nxp,pca9574", },
+	{ .compatible = "nxp,pca9575", },
+
+	{ .compatible = "maxim,max7310", },
+	{ .compatible = "maxim,max7312", },
+	{ .compatible = "maxim,max7313", },
+	{ .compatible = "maxim,max7315", },
+
+	{ .compatible = "ti,pca6107", },
+	{ .compatible = "ti,tca6408", },
+	{ .compatible = "ti,tca6416", },
+	{ .compatible = "ti,tca6424", },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, pca953x_dt_ids);
+
 static struct i2c_driver pca953x_driver = {
 	.driver = {
 		.name	= "pca953x",
+		.of_match_table = pca953x_dt_ids,
 	},
 	.probe		= pca953x_probe,
 	.remove		= pca953x_remove,
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
index 4ad0c4f..cdf5996 100644
--- a/drivers/gpio/gpio-pch.c
+++ b/drivers/gpio/gpio-pch.c
@@ -215,6 +215,7 @@ static void pch_gpio_setup(struct pch_gpio *chip)
 	struct gpio_chip *gpio = &chip->gpio;
 
 	gpio->label = dev_name(chip->dev);
+	gpio->dev = chip->dev;
 	gpio->owner = THIS_MODULE;
 	gpio->direction_input = pch_gpio_direction_input;
 	gpio->get = pch_gpio_get;
@@ -325,7 +326,7 @@ static irqreturn_t pch_gpio_handler(int irq, void *dev_id)
 	return ret;
 }
 
-static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
+static void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
 				unsigned int irq_start, unsigned int num)
 {
 	struct irq_chip_generic *gc;
@@ -345,7 +346,7 @@ static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
 			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 }
 
-static int __devinit pch_gpio_probe(struct pci_dev *pdev,
+static int pch_gpio_probe(struct pci_dev *pdev,
 				    const struct pci_device_id *id)
 {
 	s32 ret;
@@ -442,7 +443,7 @@ err_pci_enable:
 	return ret;
 }
 
-static void __devexit pch_gpio_remove(struct pci_dev *pdev)
+static void pch_gpio_remove(struct pci_dev *pdev)
 {
 	int err;
 	struct pch_gpio *chip = pci_get_drvdata(pdev);
@@ -531,7 +532,7 @@ static struct pci_driver pch_gpio_driver = {
 	.name = "pch_gpio",
 	.id_table = pch_gpio_pcidev_id,
 	.probe = pch_gpio_probe,
-	.remove = __devexit_p(pch_gpio_remove),
+	.remove = pch_gpio_remove,
 	.suspend = pch_gpio_suspend,
 	.resume = pch_gpio_resume
 };
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index b4b5da4..31d9c9e 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -216,39 +216,34 @@ static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base)
 			       IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
 }
 
-static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
+static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 {
-	struct pl061_platform_data *pdata;
+	struct device *dev = &adev->dev;
+	struct pl061_platform_data *pdata = dev->platform_data;
 	struct pl061_gpio *chip;
 	int ret, irq, i;
 
-	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
-	pdata = dev->dev.platform_data;
 	if (pdata) {
 		chip->gc.base = pdata->gpio_base;
 		chip->irq_base = pdata->irq_base;
-	} else if (dev->dev.of_node) {
+	} else if (adev->dev.of_node) {
 		chip->gc.base = -1;
 		chip->irq_base = 0;
-	} else {
-		ret = -ENODEV;
-		goto free_mem;
-	}
+	} else
+		return -ENODEV;
 
-	if (!request_mem_region(dev->res.start,
-				resource_size(&dev->res), "pl061")) {
-		ret = -EBUSY;
-		goto free_mem;
-	}
+	if (!devm_request_mem_region(dev, adev->res.start,
+				resource_size(&adev->res), "pl061"))
+		return -EBUSY;
 
-	chip->base = ioremap(dev->res.start, resource_size(&dev->res));
-	if (chip->base == NULL) {
-		ret = -ENOMEM;
-		goto release_region;
-	}
+	chip->base = devm_ioremap(dev, adev->res.start,
+				resource_size(&adev->res));
+	if (chip->base == NULL)
+		return -ENOMEM;
 
 	spin_lock_init(&chip->lock);
 
@@ -258,13 +253,13 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
 	chip->gc.set = pl061_set_value;
 	chip->gc.to_irq = pl061_to_irq;
 	chip->gc.ngpio = PL061_GPIO_NR;
-	chip->gc.label = dev_name(&dev->dev);
-	chip->gc.dev = &dev->dev;
+	chip->gc.label = dev_name(dev);
+	chip->gc.dev = dev;
 	chip->gc.owner = THIS_MODULE;
 
 	ret = gpiochip_add(&chip->gc);
 	if (ret)
-		goto iounmap;
+		return ret;
 
 	/*
 	 * irq_chip support
@@ -276,11 +271,10 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
 	pl061_init_gc(chip, chip->irq_base);
 
 	writeb(0, chip->base + GPIOIE); /* disable irqs */
-	irq = dev->irq[0];
-	if (irq < 0) {
-		ret = -ENODEV;
-		goto iounmap;
-	}
+	irq = adev->irq[0];
+	if (irq < 0)
+		return -ENODEV;
+
 	irq_set_chained_handler(irq, pl061_irq_handler);
 	irq_set_handler_data(irq, chip);
 
@@ -294,18 +288,9 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
 		}
 	}
 
-	amba_set_drvdata(dev, chip);
+	amba_set_drvdata(adev, chip);
 
 	return 0;
-
-iounmap:
-	iounmap(chip->base);
-release_region:
-	release_mem_region(dev->res.start, resource_size(&dev->res));
-free_mem:
-	kfree(chip);
-
-	return ret;
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index 98d52cb..8325f58 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -250,7 +250,7 @@ static int pxa_gpio_of_xlate(struct gpio_chip *gc,
 }
 #endif
 
-static int __devinit pxa_init_gpio_chip(int gpio_end,
+static int pxa_init_gpio_chip(int gpio_end,
 					int (*set_wake)(unsigned int, unsigned int))
 {
 	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
@@ -448,7 +448,7 @@ static int pxa_gpio_nums(void)
 	} else if (cpu_is_pxa27x()) {
 		count = 120;
 		gpio_type = PXA27X_GPIO;
-	} else if (cpu_is_pxa93x() || cpu_is_pxa95x()) {
+	} else if (cpu_is_pxa93x()) {
 		count = 191;
 		gpio_type = PXA93X_GPIO;
 	} else if (cpu_is_pxa3xx()) {
@@ -490,7 +490,7 @@ const struct irq_domain_ops pxa_irq_domain_ops = {
 	.xlate	= irq_domain_xlate_twocell,
 };
 
-static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev)
+static int pxa_gpio_probe_dt(struct platform_device *pdev)
 {
 	int ret, nr_banks, nr_gpios;
 	struct device_node *prev, *next, *np = pdev->dev.of_node;
@@ -537,7 +537,7 @@ err:
 #define pxa_gpio_probe_dt(pdev)		(-1)
 #endif
 
-static int __devinit pxa_gpio_probe(struct platform_device *pdev)
+static int pxa_gpio_probe(struct platform_device *pdev)
 {
 	struct pxa_gpio_chip *c;
 	struct resource *res;
diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c
index 08428bf..e63d6a3 100644
--- a/drivers/gpio/gpio-rc5t583.c
+++ b/drivers/gpio/gpio-rc5t583.c
@@ -111,7 +111,7 @@ static void rc5t583_gpio_free(struct gpio_chip *gc, unsigned offset)
 	rc5t583_set_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset));
 }
 
-static int __devinit rc5t583_gpio_probe(struct platform_device *pdev)
+static int rc5t583_gpio_probe(struct platform_device *pdev)
 {
 	struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
 	struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
@@ -146,7 +146,7 @@ static int __devinit rc5t583_gpio_probe(struct platform_device *pdev)
 	return gpiochip_add(&rc5t583_gpio->gpio_chip);
 }
 
-static int __devexit rc5t583_gpio_remove(struct platform_device *pdev)
+static int rc5t583_gpio_remove(struct platform_device *pdev)
 {
 	struct rc5t583_gpio *rc5t583_gpio = platform_get_drvdata(pdev);
 
@@ -159,7 +159,7 @@ static struct platform_driver rc5t583_gpio_driver = {
 		.owner   = THIS_MODULE,
 	},
 	.probe		= rc5t583_gpio_probe,
-	.remove		= __devexit_p(rc5t583_gpio_remove),
+	.remove		= rc5t583_gpio_remove,
 };
 
 static int __init rc5t583_gpio_init(void)
diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c
index b62d443..1bf55f6 100644
--- a/drivers/gpio/gpio-rdc321x.c
+++ b/drivers/gpio/gpio-rdc321x.c
@@ -128,7 +128,7 @@ static int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
 /*
  * Cache the initial value of both GPIO data registers
  */
-static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
+static int rdc321x_gpio_probe(struct platform_device *pdev)
 {
 	int err;
 	struct resource *r;
@@ -206,7 +206,7 @@ out_free:
 	return err;
 }
 
-static int __devexit rdc321x_gpio_remove(struct platform_device *pdev)
+static int rdc321x_gpio_remove(struct platform_device *pdev)
 {
 	int ret;
 	struct rdc321x_gpio *rdc321x_gpio_dev = platform_get_drvdata(pdev);
@@ -225,7 +225,7 @@ static struct platform_driver rdc321x_gpio_driver = {
 	.driver.name	= "rdc321x-gpio",
 	.driver.owner	= THIS_MODULE,
 	.probe		= rdc321x_gpio_probe,
-	.remove		= __devexit_p(rdc321x_gpio_remove),
+	.remove		= rdc321x_gpio_remove,
 };
 
 module_platform_driver(rdc321x_gpio_driver);
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index a006f0d..01f7fe9 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -42,12 +42,6 @@
 #include <plat/gpio-fns.h>
 #include <plat/pm.h>
 
-#ifndef DEBUG_GPIO
-#define gpio_dbg(x...) do { } while (0)
-#else
-#define gpio_dbg(x...) printk(KERN_DEBUG x)
-#endif
-
 int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
 				unsigned int off, samsung_gpio_pull_t pull)
 {
@@ -596,10 +590,13 @@ static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
 	unsigned long con;
 
 	con = __raw_readl(base + GPIOCON_OFF);
-	con &= ~(0xf << con_4bit_shift(offset));
+	if (ourchip->bitmap_gpio_int & BIT(offset))
+		con |= 0xf << con_4bit_shift(offset);
+	else
+		con &= ~(0xf << con_4bit_shift(offset));
 	__raw_writel(con, base + GPIOCON_OFF);
 
-	gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
+	pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
 
 	return 0;
 }
@@ -627,7 +624,7 @@ static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
 	__raw_writel(con, base + GPIOCON_OFF);
 	__raw_writel(dat, base + GPIODAT_OFF);
 
-	gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+	pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
 
 	return 0;
 }
@@ -671,7 +668,7 @@ static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
 	con &= ~(0xf << con_4bit_shift(offset));
 	__raw_writel(con, regcon);
 
-	gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
+	pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
 
 	return 0;
 }
@@ -706,7 +703,7 @@ static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
 	__raw_writel(con, regcon);
 	__raw_writel(dat, base + GPIODAT_OFF);
 
-	gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+	pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
 
 	return 0;
 }
@@ -926,10 +923,10 @@ static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
 #ifdef CONFIG_PM
 	if (chip->pm != NULL) {
 		if (!chip->pm->save || !chip->pm->resume)
-			printk(KERN_ERR "gpio: %s has missing PM functions\n",
+			pr_err("gpio: %s has missing PM functions\n",
 			       gc->label);
 	} else
-		printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
+		pr_err("gpio: %s has no PM function\n", gc->label);
 #endif
 
 	/* gpiochip_add() prints own failure message on error. */
@@ -1081,6 +1078,8 @@ static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip
 		if ((base != NULL) && (chip->base == NULL))
 			chip->base = base + ((i) * 0x20);
 
+		chip->bitmap_gpio_int = 0;
+
 		samsung_gpiolib_add(chip);
 	}
 }
@@ -2797,27 +2796,6 @@ static __init void exynos4_gpiolib_init(void)
 	int group = 0;
 	void __iomem *gpx_base;
 
-#ifdef CONFIG_PINCTRL_SAMSUNG
-		/*
-		 * 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;
-		const char *pctrl_compat = "samsung,pinctrl-exynos4210";
-		pctrl_np = of_find_compatible_node(NULL, NULL, pctrl_compat);
-		if (pctrl_np)
-			if (of_device_is_available(pctrl_np))
-				return;
-#endif
-
 	/* gpio part1 */
 	gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K);
 	if (gpio_base1 == NULL) {
@@ -3032,6 +3010,28 @@ static __init int samsung_gpiolib_init(void)
 	int i, nr_chips;
 	int group = 0;
 
+#ifdef CONFIG_PINCTRL_SAMSUNG
+	/*
+	* 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,pinctrl-exynos4210", },
+		{ .compatible = "samsung,pinctrl-exynos4x12", },
+	};
+	for_each_matching_node(pctrl_np, exynos_pinctrl_ids)
+		if (pctrl_np && of_device_is_available(pctrl_np))
+			return -ENODEV;
+#endif
+
 	samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
 
 	if (soc_is_s3c24xx()) {
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
index 8707d45..edae963 100644
--- a/drivers/gpio/gpio-sch.c
+++ b/drivers/gpio/gpio-sch.c
@@ -185,7 +185,7 @@ static struct gpio_chip sch_gpio_resume = {
 	.set			= sch_gpio_resume_set,
 };
 
-static int __devinit sch_gpio_probe(struct platform_device *pdev)
+static int sch_gpio_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	int err, id;
@@ -271,7 +271,7 @@ err_sch_gpio_core:
 	return err;
 }
 
-static int __devexit sch_gpio_remove(struct platform_device *pdev)
+static int sch_gpio_remove(struct platform_device *pdev)
 {
 	struct resource *res;
 	if (gpio_ba) {
@@ -303,7 +303,7 @@ static struct platform_driver sch_gpio_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe		= sch_gpio_probe,
-	.remove		= __devexit_p(sch_gpio_remove),
+	.remove		= sch_gpio_remove,
 };
 
 module_platform_driver(sch_gpio_driver);
diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c
index e25f731..88f374a 100644
--- a/drivers/gpio/gpio-sodaville.c
+++ b/drivers/gpio/gpio-sodaville.c
@@ -129,7 +129,7 @@ static struct irq_domain_ops irq_domain_sdv_ops = {
 	.xlate = sdv_xlate,
 };
 
-static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
+static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
 		struct pci_dev *pdev)
 {
 	struct irq_chip_type *ct;
@@ -186,7 +186,7 @@ out_free_desc:
 	return ret;
 }
 
-static int __devinit sdv_gpio_probe(struct pci_dev *pdev,
+static int sdv_gpio_probe(struct pci_dev *pdev,
 					const struct pci_device_id *pci_id)
 {
 	struct sdv_gpio_chip_data *sd;
diff --git a/drivers/gpio/gpio-spear-spics.c b/drivers/gpio/gpio-spear-spics.c
new file mode 100644
index 0000000..5f45fc4
--- /dev/null
+++ b/drivers/gpio/gpio-spear-spics.c
@@ -0,0 +1,217 @@
+/*
+ * SPEAr platform SPI chipselect abstraction over gpiolib
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Shiraz Hashim <shiraz.hashim@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+/* maximum chipselects */
+#define NUM_OF_GPIO	4
+
+/*
+ * Provision is available on some SPEAr SoCs to control ARM PL022 spi cs
+ * through system registers. This register lies outside spi (pl022)
+ * address space into system registers.
+ *
+ * It provides control for spi chip select lines so that any chipselect
+ * (out of 4 possible chipselects in pl022) can be made low to select
+ * the particular slave.
+ */
+
+/**
+ * struct spear_spics - represents spi chip select control
+ * @base: base address
+ * @perip_cfg: configuration register
+ * @sw_enable_bit: bit to enable s/w control over chipselects
+ * @cs_value_bit: bit to program high or low chipselect
+ * @cs_enable_mask: mask to select bits required to select chipselect
+ * @cs_enable_shift: bit pos of cs_enable_mask
+ * @use_count: use count of a spi controller cs lines
+ * @last_off: stores last offset caller of set_value()
+ * @chip: gpio_chip abstraction
+ */
+struct spear_spics {
+	void __iomem		*base;
+	u32			perip_cfg;
+	u32			sw_enable_bit;
+	u32			cs_value_bit;
+	u32			cs_enable_mask;
+	u32			cs_enable_shift;
+	unsigned long		use_count;
+	int			last_off;
+	struct gpio_chip	chip;
+};
+
+/* gpio framework specific routines */
+static int spics_get_value(struct gpio_chip *chip, unsigned offset)
+{
+	return -ENXIO;
+}
+
+static void spics_set_value(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct spear_spics *spics = container_of(chip, struct spear_spics,
+			chip);
+	u32 tmp;
+
+	/* select chip select from register */
+	tmp = readl_relaxed(spics->base + spics->perip_cfg);
+	if (spics->last_off != offset) {
+		spics->last_off = offset;
+		tmp &= ~(spics->cs_enable_mask << spics->cs_enable_shift);
+		tmp |= offset << spics->cs_enable_shift;
+	}
+
+	/* toggle chip select line */
+	tmp &= ~(0x1 << spics->cs_value_bit);
+	tmp |= value << spics->cs_value_bit;
+	writel_relaxed(tmp, spics->base + spics->perip_cfg);
+}
+
+static int spics_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	return -ENXIO;
+}
+
+static int spics_direction_output(struct gpio_chip *chip, unsigned offset,
+		int value)
+{
+	spics_set_value(chip, offset, value);
+	return 0;
+}
+
+static int spics_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct spear_spics *spics = container_of(chip, struct spear_spics,
+			chip);
+	u32 tmp;
+
+	if (!spics->use_count++) {
+		tmp = readl_relaxed(spics->base + spics->perip_cfg);
+		tmp |= 0x1 << spics->sw_enable_bit;
+		tmp |= 0x1 << spics->cs_value_bit;
+		writel_relaxed(tmp, spics->base + spics->perip_cfg);
+	}
+
+	return 0;
+}
+
+static void spics_free(struct gpio_chip *chip, unsigned offset)
+{
+	struct spear_spics *spics = container_of(chip, struct spear_spics,
+			chip);
+	u32 tmp;
+
+	if (!--spics->use_count) {
+		tmp = readl_relaxed(spics->base + spics->perip_cfg);
+		tmp &= ~(0x1 << spics->sw_enable_bit);
+		writel_relaxed(tmp, spics->base + spics->perip_cfg);
+	}
+}
+
+static int spics_gpio_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct spear_spics *spics;
+	struct resource *res;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n");
+		return -EBUSY;
+	}
+
+	spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL);
+	if (!spics) {
+		dev_err(&pdev->dev, "memory allocation fail\n");
+		return -ENOMEM;
+	}
+
+	spics->base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!spics->base) {
+		dev_err(&pdev->dev, "request and ioremap fail\n");
+		return -ENOMEM;
+	}
+
+	if (of_property_read_u32(np, "st-spics,peripcfg-reg",
+				&spics->perip_cfg))
+		goto err_dt_data;
+	if (of_property_read_u32(np, "st-spics,sw-enable-bit",
+				&spics->sw_enable_bit))
+		goto err_dt_data;
+	if (of_property_read_u32(np, "st-spics,cs-value-bit",
+				&spics->cs_value_bit))
+		goto err_dt_data;
+	if (of_property_read_u32(np, "st-spics,cs-enable-mask",
+				&spics->cs_enable_mask))
+		goto err_dt_data;
+	if (of_property_read_u32(np, "st-spics,cs-enable-shift",
+				&spics->cs_enable_shift))
+		goto err_dt_data;
+
+	platform_set_drvdata(pdev, spics);
+
+	spics->chip.ngpio = NUM_OF_GPIO;
+	spics->chip.base = -1;
+	spics->chip.request = spics_request;
+	spics->chip.free = spics_free;
+	spics->chip.direction_input = spics_direction_input;
+	spics->chip.direction_output = spics_direction_output;
+	spics->chip.get = spics_get_value;
+	spics->chip.set = spics_set_value;
+	spics->chip.label = dev_name(&pdev->dev);
+	spics->chip.dev = &pdev->dev;
+	spics->chip.owner = THIS_MODULE;
+	spics->last_off = -1;
+
+	ret = gpiochip_add(&spics->chip);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to add gpio chip\n");
+		return ret;
+	}
+
+	dev_info(&pdev->dev, "spear spics registered\n");
+	return 0;
+
+err_dt_data:
+	dev_err(&pdev->dev, "DT probe failed\n");
+	return -EINVAL;
+}
+
+static const struct of_device_id spics_gpio_of_match[] = {
+	{ .compatible = "st,spear-spics-gpio" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, spics_gpio_of_match);
+
+static struct platform_driver spics_gpio_driver = {
+	.probe = spics_gpio_probe,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "spear-spics-gpio",
+		.of_match_table = spics_gpio_of_match,
+	},
+};
+
+static int __init spics_gpio_init(void)
+{
+	return platform_driver_register(&spics_gpio_driver);
+}
+subsys_initcall(spics_gpio_init);
+
+MODULE_AUTHOR("Shiraz Hashim <shiraz.hashim@st.com>");
+MODULE_DESCRIPTION("ST Microlectronics SPEAr SPI Chip Select Abstraction");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c
index 6064fb3..5585425 100644
--- a/drivers/gpio/gpio-sta2x11.c
+++ b/drivers/gpio/gpio-sta2x11.c
@@ -320,7 +320,7 @@ static irqreturn_t gsta_gpio_handler(int irq, void *dev_id)
 	return ret;
 }
 
-static __devinit void gsta_alloc_irq_chip(struct gsta_gpio *chip)
+static void gsta_alloc_irq_chip(struct gsta_gpio *chip)
 {
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
@@ -353,7 +353,7 @@ static __devinit void gsta_alloc_irq_chip(struct gsta_gpio *chip)
 }
 
 /* The platform device used here is instantiated by the MFD device */
-static int __devinit gsta_probe(struct platform_device *dev)
+static int gsta_probe(struct platform_device *dev)
 {
 	int i, err;
 	struct pci_dev *pdev;
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
index dce3472..6dff78b 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/gpio-stmpe.c
@@ -267,7 +267,7 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
-static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
+static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
 {
 	int base = stmpe_gpio->irq_base;
 	int irq;
@@ -301,7 +301,7 @@ static void stmpe_gpio_irq_remove(struct stmpe_gpio *stmpe_gpio)
 	}
 }
 
-static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
+static int stmpe_gpio_probe(struct platform_device *pdev)
 {
 	struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
 	struct stmpe_gpio_platform_data *pdata;
@@ -378,7 +378,7 @@ out_free:
 	return ret;
 }
 
-static int __devexit stmpe_gpio_remove(struct platform_device *pdev)
+static int stmpe_gpio_remove(struct platform_device *pdev)
 {
 	struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev);
 	struct stmpe *stmpe = stmpe_gpio->stmpe;
@@ -412,7 +412,7 @@ static struct platform_driver stmpe_gpio_driver = {
 	.driver.name	= "stmpe-gpio",
 	.driver.owner	= THIS_MODULE,
 	.probe		= stmpe_gpio_probe,
-	.remove		= __devexit_p(stmpe_gpio_remove),
+	.remove		= stmpe_gpio_remove,
 };
 
 static int __init stmpe_gpio_init(void)
diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c
index 8bead0b..85841ee7 100644
--- a/drivers/gpio/gpio-stp-xway.c
+++ b/drivers/gpio/gpio-stp-xway.c
@@ -197,7 +197,7 @@ static int xway_stp_hw_init(struct xway_stp *chip)
 	return 0;
 }
 
-static int __devinit xway_stp_probe(struct platform_device *pdev)
+static int xway_stp_probe(struct platform_device *pdev)
 {
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	const __be32 *shadow, *groups, *dsl, *phy;
diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c
index eb3e215..796b6c4 100644
--- a/drivers/gpio/gpio-sx150x.c
+++ b/drivers/gpio/gpio-sx150x.c
@@ -575,7 +575,7 @@ static void sx150x_remove_irq_chip(struct sx150x_chip *chip)
 	}
 }
 
-static int __devinit sx150x_probe(struct i2c_client *client,
+static int sx150x_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
 	static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA |
@@ -622,7 +622,7 @@ probe_fail_pre_gpiochip_add:
 	return rc;
 }
 
-static int __devexit sx150x_remove(struct i2c_client *client)
+static int sx150x_remove(struct i2c_client *client)
 {
 	struct sx150x_chip *chip;
 	int rc;
@@ -646,7 +646,7 @@ static struct i2c_driver sx150x_driver = {
 		.owner = THIS_MODULE
 	},
 	.probe    = sx150x_probe,
-	.remove   = __devexit_p(sx150x_remove),
+	.remove   = sx150x_remove,
 	.id_table = sx150x_id,
 };
 
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
index 1e48317..c0595bb 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -292,17 +292,15 @@ static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio,
 {
 	int base = tc3589x_gpio->irq_base;
 
-	if (base) {
-		tc3589x_gpio->domain = irq_domain_add_legacy(
-			NULL, tc3589x_gpio->chip.ngpio, base,
-			0, &tc3589x_irq_ops, tc3589x_gpio);
-	}
-	else {
-		tc3589x_gpio->domain = irq_domain_add_linear(
-			np, tc3589x_gpio->chip.ngpio,
-			&tc3589x_irq_ops, tc3589x_gpio);
-	}
-
+	/*
+	 * If this results in a linear domain, irq_create_mapping() will
+	 * take care of allocating IRQ descriptors at runtime. When a base
+	 * is provided, the IRQ descriptors will be allocated when the
+	 * domain is instantiated.
+	 */
+	tc3589x_gpio->domain = irq_domain_add_simple(np,
+			tc3589x_gpio->chip.ngpio, base, &tc3589x_irq_ops,
+			tc3589x_gpio);
 	if (!tc3589x_gpio->domain) {
 		dev_err(tc3589x_gpio->dev, "Failed to create irqdomain\n");
 		return -ENOSYS;
@@ -311,7 +309,7 @@ static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio,
 	return 0;
 }
 
-static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
+static int tc3589x_gpio_probe(struct platform_device *pdev)
 {
 	struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
 	struct tc3589x_gpio_platform_data *pdata;
@@ -389,7 +387,7 @@ out_free:
 	return ret;
 }
 
-static int __devexit tc3589x_gpio_remove(struct platform_device *pdev)
+static int tc3589x_gpio_remove(struct platform_device *pdev)
 {
 	struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
 	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
@@ -419,7 +417,7 @@ static struct platform_driver tc3589x_gpio_driver = {
 	.driver.name	= "tc3589x-gpio",
 	.driver.owner	= THIS_MODULE,
 	.probe		= tc3589x_gpio_probe,
-	.remove		= __devexit_p(tc3589x_gpio_remove),
+	.remove		= tc3589x_gpio_remove,
 };
 
 static int __init tc3589x_gpio_init(void)
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index d982593..63cb643 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/irqdomain.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/pm.h>
 
 #include <asm/mach/irq.h>
 
@@ -64,7 +65,7 @@ struct tegra_gpio_bank {
 	int bank;
 	int irq;
 	spinlock_t lvl_lock[4];
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 	u32 cnf[4];
 	u32 out[4];
 	u32 oe[4];
@@ -109,20 +110,18 @@ static void tegra_gpio_enable(int gpio)
 {
 	tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
 }
-EXPORT_SYMBOL_GPL(tegra_gpio_enable);
 
 static void tegra_gpio_disable(int gpio)
 {
 	tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
 }
-EXPORT_SYMBOL_GPL(tegra_gpio_disable);
 
-int tegra_gpio_request(struct gpio_chip *chip, unsigned offset)
+static int tegra_gpio_request(struct gpio_chip *chip, unsigned offset)
 {
 	return pinctrl_request_gpio(offset);
 }
 
-void tegra_gpio_free(struct gpio_chip *chip, unsigned offset)
+static void tegra_gpio_free(struct gpio_chip *chip, unsigned offset)
 {
 	pinctrl_free_gpio(offset);
 	tegra_gpio_disable(offset);
@@ -135,6 +134,11 @@ static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 
 static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
+	/* If gpio is in output mode then read from the out value */
+	if ((tegra_gpio_readl(GPIO_OE(offset)) >> GPIO_BIT(offset)) & 1)
+		return (tegra_gpio_readl(GPIO_OUT(offset)) >>
+				GPIO_BIT(offset)) & 0x1;
+
 	return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
 }
 
@@ -285,8 +289,8 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 
 }
 
-#ifdef CONFIG_PM
-void tegra_gpio_resume(void)
+#ifdef CONFIG_PM_SLEEP
+static int tegra_gpio_resume(struct device *dev)
 {
 	unsigned long flags;
 	int b;
@@ -308,9 +312,10 @@ void tegra_gpio_resume(void)
 	}
 
 	local_irq_restore(flags);
+	return 0;
 }
 
-void tegra_gpio_suspend(void)
+static int tegra_gpio_suspend(struct device *dev)
 {
 	unsigned long flags;
 	int b;
@@ -330,6 +335,7 @@ void tegra_gpio_suspend(void)
 		}
 	}
 	local_irq_restore(flags);
+	return 0;
 }
 
 static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)
@@ -345,11 +351,15 @@ static struct irq_chip tegra_gpio_irq_chip = {
 	.irq_mask	= tegra_gpio_irq_mask,
 	.irq_unmask	= tegra_gpio_irq_unmask,
 	.irq_set_type	= tegra_gpio_irq_set_type,
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 	.irq_set_wake	= tegra_gpio_wake_enable,
 #endif
 };
 
+static const struct dev_pm_ops tegra_gpio_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume)
+};
+
 struct tegra_gpio_soc_config {
 	u32 bank_stride;
 	u32 upper_offset;
@@ -365,7 +375,7 @@ static struct tegra_gpio_soc_config tegra30_gpio_config = {
 	.upper_offset = 0x80,
 };
 
-static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
+static struct of_device_id tegra_gpio_of_match[] = {
 	{ .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config },
 	{ .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config },
 	{ },
@@ -376,11 +386,10 @@ static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
  */
 static struct lock_class_key gpio_lock_class;
 
-static int __devinit tegra_gpio_probe(struct platform_device *pdev)
+static int tegra_gpio_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *match;
 	struct tegra_gpio_soc_config *config;
-	int irq_base;
 	struct resource *res;
 	struct tegra_gpio_bank *bank;
 	int gpio;
@@ -417,14 +426,11 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	irq_base = irq_alloc_descs(-1, 0, tegra_gpio_chip.ngpio, 0);
-	if (irq_base < 0) {
-		dev_err(&pdev->dev, "Couldn't allocate IRQ numbers\n");
-		return -ENODEV;
-	}
-	irq_domain = irq_domain_add_legacy(pdev->dev.of_node,
-					   tegra_gpio_chip.ngpio, irq_base, 0,
+	irq_domain = irq_domain_add_linear(pdev->dev.of_node,
+					   tegra_gpio_chip.ngpio,
 					   &irq_domain_simple_ops, NULL);
+	if (!irq_domain)
+		return -ENODEV;
 
 	for (i = 0; i < tegra_gpio_bank_count; i++) {
 		res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
@@ -464,7 +470,7 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
 	gpiochip_add(&tegra_gpio_chip);
 
 	for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) {
-		int irq = irq_find_mapping(irq_domain, gpio);
+		int irq = irq_create_mapping(irq_domain, gpio);
 		/* No validity check; all Tegra GPIOs are valid IRQs */
 
 		bank = &tegra_gpio_banks[GPIO_BANK(gpio)];
@@ -493,6 +499,7 @@ static struct platform_driver tegra_gpio_driver = {
 	.driver		= {
 		.name	= "tegra-gpio",
 		.owner	= THIS_MODULE,
+		.pm	= &tegra_gpio_pm_ops,
 		.of_match_table = tegra_gpio_of_match,
 	},
 	.probe		= tegra_gpio_probe,
diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c
index 1a3e2b9..702cca9 100644
--- a/drivers/gpio/gpio-timberdale.c
+++ b/drivers/gpio/gpio-timberdale.c
@@ -222,7 +222,7 @@ static struct irq_chip timbgpio_irqchip = {
 	.irq_set_type	= timbgpio_irq_type,
 };
 
-static int __devinit timbgpio_probe(struct platform_device *pdev)
+static int timbgpio_probe(struct platform_device *pdev)
 {
 	int err, i;
 	struct gpio_chip *gc;
@@ -316,7 +316,7 @@ err_mem:
 	return err;
 }
 
-static int __devexit timbgpio_remove(struct platform_device *pdev)
+static int timbgpio_remove(struct platform_device *pdev)
 {
 	int err;
 	struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c
index 2526b3b..29e8e75 100644
--- a/drivers/gpio/gpio-tps6586x.c
+++ b/drivers/gpio/gpio-tps6586x.c
@@ -80,7 +80,15 @@ static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset,
 				val, mask);
 }
 
-static int __devinit tps6586x_gpio_probe(struct platform_device *pdev)
+static int tps6586x_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+	struct tps6586x_gpio *tps6586x_gpio = to_tps6586x_gpio(gc);
+
+	return tps6586x_irq_get_virq(tps6586x_gpio->parent,
+				TPS6586X_INT_PLDO_0 + offset);
+}
+
+static int tps6586x_gpio_probe(struct platform_device *pdev)
 {
 	struct tps6586x_platform_data *pdata;
 	struct tps6586x_gpio *tps6586x_gpio;
@@ -106,6 +114,7 @@ static int __devinit tps6586x_gpio_probe(struct platform_device *pdev)
 	tps6586x_gpio->gpio_chip.direction_output = tps6586x_gpio_output;
 	tps6586x_gpio->gpio_chip.set	= tps6586x_gpio_set;
 	tps6586x_gpio->gpio_chip.get	= tps6586x_gpio_get;
+	tps6586x_gpio->gpio_chip.to_irq	= tps6586x_gpio_to_irq;
 
 #ifdef CONFIG_OF_GPIO
 	tps6586x_gpio->gpio_chip.of_node = pdev->dev.parent->of_node;
@@ -126,7 +135,7 @@ static int __devinit tps6586x_gpio_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit tps6586x_gpio_remove(struct platform_device *pdev)
+static int tps6586x_gpio_remove(struct platform_device *pdev)
 {
 	struct tps6586x_gpio *tps6586x_gpio = platform_get_drvdata(pdev);
 
@@ -137,7 +146,7 @@ static struct platform_driver tps6586x_gpio_driver = {
 	.driver.name	= "tps6586x-gpio",
 	.driver.owner	= THIS_MODULE,
 	.probe		= tps6586x_gpio_probe,
-	.remove		= __devexit_p(tps6586x_gpio_remove),
+	.remove		= tps6586x_gpio_remove,
 };
 
 static int __init tps6586x_gpio_init(void)
diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c
index 11f29c8..5083825 100644
--- a/drivers/gpio/gpio-tps65910.c
+++ b/drivers/gpio/gpio-tps65910.c
@@ -113,7 +113,7 @@ static struct tps65910_board *tps65910_parse_dt_for_gpio(struct device *dev,
 }
 #endif
 
-static int __devinit tps65910_gpio_probe(struct platform_device *pdev)
+static int tps65910_gpio_probe(struct platform_device *pdev)
 {
 	struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
 	struct tps65910_board *pdata = dev_get_platdata(tps65910->dev);
@@ -188,7 +188,7 @@ skip_init:
 	return ret;
 }
 
-static int __devexit tps65910_gpio_remove(struct platform_device *pdev)
+static int tps65910_gpio_remove(struct platform_device *pdev)
 {
 	struct tps65910_gpio *tps65910_gpio = platform_get_drvdata(pdev);
 
@@ -199,7 +199,7 @@ static struct platform_driver tps65910_gpio_driver = {
 	.driver.name    = "tps65910-gpio",
 	.driver.owner   = THIS_MODULE,
 	.probe		= tps65910_gpio_probe,
-	.remove		= __devexit_p(tps65910_gpio_remove),
+	.remove		= tps65910_gpio_remove,
 };
 
 static int __init tps65910_gpio_init(void)
diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c
index 99106d1..30a5844 100644
--- a/drivers/gpio/gpio-tps65912.c
+++ b/drivers/gpio/gpio-tps65912.c
@@ -84,7 +84,7 @@ static struct gpio_chip template_chip = {
 	.base			= -1,
 };
 
-static int __devinit tps65912_gpio_probe(struct platform_device *pdev)
+static int tps65912_gpio_probe(struct platform_device *pdev)
 {
 	struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
 	struct tps65912_board *pdata = tps65912->dev->platform_data;
@@ -113,7 +113,7 @@ static int __devinit tps65912_gpio_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit tps65912_gpio_remove(struct platform_device *pdev)
+static int tps65912_gpio_remove(struct platform_device *pdev)
 {
 	struct tps65912_gpio_data  *tps65912_gpio = platform_get_drvdata(pdev);
 
@@ -126,7 +126,7 @@ static struct platform_driver tps65912_gpio_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = tps65912_gpio_probe,
-	.remove = __devexit_p(tps65912_gpio_remove),
+	.remove = tps65912_gpio_remove,
 };
 
 static int __init tps65912_gpio_init(void)
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
index c5f8ca2..9572aa1 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -88,11 +88,15 @@ static inline int gpio_twl4030_write(u8 address, u8 data)
 /*----------------------------------------------------------------------*/
 
 /*
- * LED register offsets (use TWL4030_MODULE_{LED,PWMA,PWMB}))
+ * LED register offsets from TWL_MODULE_LED base
  * PWMs A and B are dedicated to LEDs A and B, respectively.
  */
 
-#define TWL4030_LED_LEDEN	0x0
+#define TWL4030_LED_LEDEN_REG	0x00
+#define TWL4030_PWMAON_REG	0x01
+#define TWL4030_PWMAOFF_REG	0x02
+#define TWL4030_PWMBON_REG	0x03
+#define TWL4030_PWMBOFF_REG	0x04
 
 /* LEDEN bits */
 #define LEDEN_LEDAON		BIT(0)
@@ -104,9 +108,6 @@ static inline int gpio_twl4030_write(u8 address, u8 data)
 #define LEDEN_PWM_LENGTHA	BIT(6)
 #define LEDEN_PWM_LENGTHB	BIT(7)
 
-#define TWL4030_PWMx_PWMxON	0x0
-#define TWL4030_PWMx_PWMxOFF	0x1
-
 #define PWMxON_LENGTH		BIT(7)
 
 /*----------------------------------------------------------------------*/
@@ -145,7 +146,7 @@ static void twl4030_led_set_value(int led, int value)
 	else
 		cached_leden |= mask;
 	status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
-			TWL4030_LED_LEDEN);
+				  TWL4030_LED_LEDEN_REG);
 	mutex_unlock(&gpio_lock);
 }
 
@@ -216,33 +217,33 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)
 	if (offset >= TWL4030_GPIO_MAX) {
 		u8	ledclr_mask = LEDEN_LEDAON | LEDEN_LEDAEXT
 				| LEDEN_LEDAPWM | LEDEN_PWM_LENGTHA;
-		u8	module = TWL4030_MODULE_PWMA;
+		u8	reg = TWL4030_PWMAON_REG;
 
 		offset -= TWL4030_GPIO_MAX;
 		if (offset) {
 			ledclr_mask <<= 1;
-			module = TWL4030_MODULE_PWMB;
+			reg = TWL4030_PWMBON_REG;
 		}
 
 		/* initialize PWM to always-drive */
-		status = twl_i2c_write_u8(module, 0x7f,
-				TWL4030_PWMx_PWMxOFF);
+		/* Configure PWM OFF register first */
+		status = twl_i2c_write_u8(TWL4030_MODULE_LED, 0x7f, reg + 1);
 		if (status < 0)
 			goto done;
-		status = twl_i2c_write_u8(module, 0x7f,
-				TWL4030_PWMx_PWMxON);
+
+		/* Followed by PWM ON register */
+		status = twl_i2c_write_u8(TWL4030_MODULE_LED, 0x7f, reg);
 		if (status < 0)
 			goto done;
 
 		/* init LED to not-driven (high) */
-		module = TWL4030_MODULE_LED;
-		status = twl_i2c_read_u8(module, &cached_leden,
-				TWL4030_LED_LEDEN);
+		status = twl_i2c_read_u8(TWL4030_MODULE_LED, &cached_leden,
+					 TWL4030_LED_LEDEN_REG);
 		if (status < 0)
 			goto done;
 		cached_leden &= ~ledclr_mask;
-		status = twl_i2c_write_u8(module, cached_leden,
-				TWL4030_LED_LEDEN);
+		status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
+					  TWL4030_LED_LEDEN_REG);
 		if (status < 0)
 			goto done;
 
@@ -352,15 +353,15 @@ static struct gpio_chip twl_gpiochip = {
 
 /*----------------------------------------------------------------------*/
 
-static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
+static int gpio_twl4030_pulls(u32 ups, u32 downs)
 {
-	u8		message[6];
+	u8		message[5];
 	unsigned	i, gpio_bit;
 
 	/* For most pins, a pulldown was enabled by default.
 	 * We should have data that's specific to this board.
 	 */
-	for (gpio_bit = 1, i = 1; i < 6; i++) {
+	for (gpio_bit = 1, i = 0; i < 5; i++) {
 		u8		bit_mask;
 		unsigned	j;
 
@@ -377,18 +378,18 @@ static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
 				REG_GPIOPUPDCTR1, 5);
 }
 
-static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
+static int gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
 {
-	u8		message[4];
+	u8		message[3];
 
 	/* 30 msec of debouncing is always used for MMC card detect,
 	 * and is optional for everything else.
 	 */
-	message[1] = (debounce & 0xff) | (mmc_cd & 0x03);
+	message[0] = (debounce & 0xff) | (mmc_cd & 0x03);
 	debounce >>= 8;
-	message[2] = (debounce & 0xff);
+	message[1] = (debounce & 0xff);
 	debounce >>= 8;
-	message[3] = (debounce & 0x03);
+	message[2] = (debounce & 0x03);
 
 	return twl_i2c_write(TWL4030_MODULE_GPIO, message,
 				REG_GPIO_DEBEN1, 3);
@@ -419,7 +420,7 @@ static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev)
 	return omap_twl_info;
 }
 
-static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
+static int gpio_twl4030_probe(struct platform_device *pdev)
 {
 	struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
 	struct device_node *node = pdev->dev.of_node;
@@ -505,7 +506,7 @@ out:
 	return ret;
 }
 
-/* Cannot use __devexit as gpio_twl4030_probe() calls us */
+/* Cannot use as gpio_twl4030_probe() calls us */
 static int gpio_twl4030_remove(struct platform_device *pdev)
 {
 	struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
diff --git a/drivers/gpio/gpio-twl6040.c b/drivers/gpio/gpio-twl6040.c
index dd58e8b..0be82c6 100644
--- a/drivers/gpio/gpio-twl6040.c
+++ b/drivers/gpio/gpio-twl6040.c
@@ -82,7 +82,7 @@ static struct gpio_chip twl6040gpo_chip = {
 
 /*----------------------------------------------------------------------*/
 
-static int __devinit gpo_twl6040_probe(struct platform_device *pdev)
+static int gpo_twl6040_probe(struct platform_device *pdev)
 {
 	struct twl6040_gpo_data *pdata = pdev->dev.platform_data;
 	struct device *twl6040_core_dev = pdev->dev.parent;
@@ -113,7 +113,7 @@ static int __devinit gpo_twl6040_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit gpo_twl6040_remove(struct platform_device *pdev)
+static int gpo_twl6040_remove(struct platform_device *pdev)
 {
 	return gpiochip_remove(&twl6040gpo_chip);
 }
diff --git a/drivers/gpio/gpio-viperboard.c b/drivers/gpio/gpio-viperboard.c
new file mode 100644
index 0000000..1377299
--- /dev/null
+++ b/drivers/gpio/gpio-viperboard.c
@@ -0,0 +1,517 @@
+/*
+ *  Nano River Technologies viperboard GPIO lib driver
+ *
+ *  (C) 2012 by Lemonage GmbH
+ *  Author: Lars Poeschel <poeschel@lemonage.de>
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#include <linux/usb.h>
+#include <linux/gpio.h>
+
+#include <linux/mfd/viperboard.h>
+
+#define VPRBRD_GPIOA_CLK_1MHZ		0
+#define VPRBRD_GPIOA_CLK_100KHZ		1
+#define VPRBRD_GPIOA_CLK_10KHZ		2
+#define VPRBRD_GPIOA_CLK_1KHZ		3
+#define VPRBRD_GPIOA_CLK_100HZ		4
+#define VPRBRD_GPIOA_CLK_10HZ		5
+
+#define VPRBRD_GPIOA_FREQ_DEFAULT	1000
+
+#define VPRBRD_GPIOA_CMD_CONT		0x00
+#define VPRBRD_GPIOA_CMD_PULSE		0x01
+#define VPRBRD_GPIOA_CMD_PWM		0x02
+#define VPRBRD_GPIOA_CMD_SETOUT		0x03
+#define VPRBRD_GPIOA_CMD_SETIN		0x04
+#define VPRBRD_GPIOA_CMD_SETINT		0x05
+#define VPRBRD_GPIOA_CMD_GETIN		0x06
+
+#define VPRBRD_GPIOB_CMD_SETDIR		0x00
+#define VPRBRD_GPIOB_CMD_SETVAL		0x01
+
+struct vprbrd_gpioa_msg {
+	u8 cmd;
+	u8 clk;
+	u8 offset;
+	u8 t1;
+	u8 t2;
+	u8 invert;
+	u8 pwmlevel;
+	u8 outval;
+	u8 risefall;
+	u8 answer;
+	u8 __fill;
+} __packed;
+
+struct vprbrd_gpiob_msg {
+	u8 cmd;
+	u16 val;
+	u16 mask;
+} __packed;
+
+struct vprbrd_gpio {
+	struct gpio_chip gpioa; /* gpio a related things */
+	u32 gpioa_out;
+	u32 gpioa_val;
+	struct gpio_chip gpiob; /* gpio b related things */
+	u32 gpiob_out;
+	u32 gpiob_val;
+	struct vprbrd *vb;
+};
+
+/* gpioa sampling clock module parameter */
+static unsigned char gpioa_clk;
+static unsigned int gpioa_freq = VPRBRD_GPIOA_FREQ_DEFAULT;
+module_param(gpioa_freq, uint, 0);
+MODULE_PARM_DESC(gpioa_freq,
+	"gpio-a sampling freq in Hz (default is 1000Hz) valid values: 10, 100, 1000, 10000, 100000, 1000000");
+
+/* ----- begin of gipo a chip -------------------------------------------- */
+
+static int vprbrd_gpioa_get(struct gpio_chip *chip,
+		unsigned offset)
+{
+	int ret, answer, error = 0;
+	struct vprbrd_gpio *gpio =
+			container_of(chip, struct vprbrd_gpio, gpioa);
+	struct vprbrd *vb = gpio->vb;
+	struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf;
+
+	/* if io is set to output, just return the saved value */
+	if (gpio->gpioa_out & (1 << offset))
+		return gpio->gpioa_val & (1 << offset);
+
+	mutex_lock(&vb->lock);
+
+	gamsg->cmd = VPRBRD_GPIOA_CMD_GETIN;
+	gamsg->clk = 0x00;
+	gamsg->offset = offset;
+	gamsg->t1 = 0x00;
+	gamsg->t2 = 0x00;
+	gamsg->invert = 0x00;
+	gamsg->pwmlevel = 0x00;
+	gamsg->outval = 0x00;
+	gamsg->risefall = 0x00;
+	gamsg->answer = 0x00;
+	gamsg->__fill = 0x00;
+
+	ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0),
+		VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT, 0x0000,
+		0x0000, gamsg, sizeof(struct vprbrd_gpioa_msg),
+		VPRBRD_USB_TIMEOUT_MS);
+	if (ret != sizeof(struct vprbrd_gpioa_msg))
+		error = -EREMOTEIO;
+
+	ret = usb_control_msg(vb->usb_dev, usb_rcvctrlpipe(vb->usb_dev, 0),
+		VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_IN, 0x0000,
+		0x0000, gamsg, sizeof(struct vprbrd_gpioa_msg),
+		VPRBRD_USB_TIMEOUT_MS);
+	answer = gamsg->answer & 0x01;
+
+	mutex_unlock(&vb->lock);
+
+	if (ret != sizeof(struct vprbrd_gpioa_msg))
+		error = -EREMOTEIO;
+
+	if (error)
+		return error;
+
+	return answer;
+}
+
+static void vprbrd_gpioa_set(struct gpio_chip *chip,
+		unsigned offset, int value)
+{
+	int ret;
+	struct vprbrd_gpio *gpio =
+			container_of(chip, struct vprbrd_gpio, gpioa);
+	struct vprbrd *vb = gpio->vb;
+	struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf;
+
+	if (gpio->gpioa_out & (1 << offset)) {
+		if (value)
+			gpio->gpioa_val |= (1 << offset);
+		else
+			gpio->gpioa_val &= ~(1 << offset);
+
+		mutex_lock(&vb->lock);
+
+		gamsg->cmd = VPRBRD_GPIOA_CMD_SETOUT;
+		gamsg->clk = 0x00;
+		gamsg->offset = offset;
+		gamsg->t1 = 0x00;
+		gamsg->t2 = 0x00;
+		gamsg->invert = 0x00;
+		gamsg->pwmlevel = 0x00;
+		gamsg->outval = value;
+		gamsg->risefall = 0x00;
+		gamsg->answer = 0x00;
+		gamsg->__fill = 0x00;
+
+		ret = usb_control_msg(vb->usb_dev,
+			usb_sndctrlpipe(vb->usb_dev, 0),
+			VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT,
+			0x0000,	0x0000, gamsg,
+			sizeof(struct vprbrd_gpioa_msg), VPRBRD_USB_TIMEOUT_MS);
+
+		mutex_unlock(&vb->lock);
+
+		if (ret != sizeof(struct vprbrd_gpioa_msg))
+			dev_err(chip->dev, "usb error setting pin value\n");
+	}
+}
+
+static int vprbrd_gpioa_direction_input(struct gpio_chip *chip,
+			unsigned offset)
+{
+	int ret;
+	struct vprbrd_gpio *gpio =
+			container_of(chip, struct vprbrd_gpio, gpioa);
+	struct vprbrd *vb = gpio->vb;
+	struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf;
+
+	gpio->gpioa_out &= ~(1 << offset);
+
+	mutex_lock(&vb->lock);
+
+	gamsg->cmd = VPRBRD_GPIOA_CMD_SETIN;
+	gamsg->clk = gpioa_clk;
+	gamsg->offset = offset;
+	gamsg->t1 = 0x00;
+	gamsg->t2 = 0x00;
+	gamsg->invert = 0x00;
+	gamsg->pwmlevel = 0x00;
+	gamsg->outval = 0x00;
+	gamsg->risefall = 0x00;
+	gamsg->answer = 0x00;
+	gamsg->__fill = 0x00;
+
+	ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0),
+		VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT, 0x0000,
+		0x0000, gamsg, sizeof(struct vprbrd_gpioa_msg),
+		VPRBRD_USB_TIMEOUT_MS);
+
+	mutex_unlock(&vb->lock);
+
+	if (ret != sizeof(struct vprbrd_gpioa_msg))
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int vprbrd_gpioa_direction_output(struct gpio_chip *chip,
+			unsigned offset, int value)
+{
+	int ret;
+	struct vprbrd_gpio *gpio =
+			container_of(chip, struct vprbrd_gpio, gpioa);
+	struct vprbrd *vb = gpio->vb;
+	struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf;
+
+	gpio->gpioa_out |= (1 << offset);
+	if (value)
+		gpio->gpioa_val |= (1 << offset);
+	else
+		gpio->gpioa_val &= ~(1 << offset);
+
+	mutex_lock(&vb->lock);
+
+	gamsg->cmd = VPRBRD_GPIOA_CMD_SETOUT;
+	gamsg->clk = 0x00;
+	gamsg->offset = offset;
+	gamsg->t1 = 0x00;
+	gamsg->t2 = 0x00;
+	gamsg->invert = 0x00;
+	gamsg->pwmlevel = 0x00;
+	gamsg->outval = value;
+	gamsg->risefall = 0x00;
+	gamsg->answer = 0x00;
+	gamsg->__fill = 0x00;
+
+	ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0),
+		VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT, 0x0000,
+		0x0000, gamsg, sizeof(struct vprbrd_gpioa_msg),
+		VPRBRD_USB_TIMEOUT_MS);
+
+	mutex_unlock(&vb->lock);
+
+	if (ret != sizeof(struct vprbrd_gpioa_msg))
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+/* ----- end of gpio a chip ---------------------------------------------- */
+
+/* ----- begin of gipo b chip -------------------------------------------- */
+
+static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned offset,
+	unsigned dir)
+{
+	struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf;
+	int ret;
+
+	gbmsg->cmd = VPRBRD_GPIOB_CMD_SETDIR;
+	gbmsg->val = cpu_to_be16(dir << offset);
+	gbmsg->mask = cpu_to_be16(0x0001 << offset);
+
+	ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0),
+		VPRBRD_USB_REQUEST_GPIOB, VPRBRD_USB_TYPE_OUT, 0x0000,
+		0x0000, gbmsg, sizeof(struct vprbrd_gpiob_msg),
+		VPRBRD_USB_TIMEOUT_MS);
+
+	if (ret != sizeof(struct vprbrd_gpiob_msg))
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int vprbrd_gpiob_get(struct gpio_chip *chip,
+		unsigned offset)
+{
+	int ret;
+	u16 val;
+	struct vprbrd_gpio *gpio =
+			container_of(chip, struct vprbrd_gpio, gpiob);
+	struct vprbrd *vb = gpio->vb;
+	struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf;
+
+	/* if io is set to output, just return the saved value */
+	if (gpio->gpiob_out & (1 << offset))
+		return gpio->gpiob_val & (1 << offset);
+
+	mutex_lock(&vb->lock);
+
+	ret = usb_control_msg(vb->usb_dev, usb_rcvctrlpipe(vb->usb_dev, 0),
+		VPRBRD_USB_REQUEST_GPIOB, VPRBRD_USB_TYPE_IN, 0x0000,
+		0x0000, gbmsg,	sizeof(struct vprbrd_gpiob_msg),
+		VPRBRD_USB_TIMEOUT_MS);
+	val = gbmsg->val;
+
+	mutex_unlock(&vb->lock);
+
+	if (ret != sizeof(struct vprbrd_gpiob_msg))
+		return ret;
+
+	/* cache the read values */
+	gpio->gpiob_val = be16_to_cpu(val);
+
+	return (gpio->gpiob_val >> offset) & 0x1;
+}
+
+static void vprbrd_gpiob_set(struct gpio_chip *chip,
+		unsigned offset, int value)
+{
+	int ret;
+	struct vprbrd_gpio *gpio =
+			container_of(chip, struct vprbrd_gpio, gpiob);
+	struct vprbrd *vb = gpio->vb;
+	struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf;
+
+	if (gpio->gpiob_out & (1 << offset)) {
+		if (value)
+			gpio->gpiob_val |= (1 << offset);
+		else
+			gpio->gpiob_val &= ~(1 << offset);
+
+		mutex_lock(&vb->lock);
+
+		gbmsg->cmd = VPRBRD_GPIOB_CMD_SETVAL;
+		gbmsg->val = cpu_to_be16(value << offset);
+		gbmsg->mask = cpu_to_be16(0x0001 << offset);
+
+		ret = usb_control_msg(vb->usb_dev,
+			usb_sndctrlpipe(vb->usb_dev, 0),
+			VPRBRD_USB_REQUEST_GPIOB, VPRBRD_USB_TYPE_OUT,
+			0x0000,	0x0000, gbmsg,
+			sizeof(struct vprbrd_gpiob_msg), VPRBRD_USB_TIMEOUT_MS);
+
+		mutex_unlock(&vb->lock);
+
+		if (ret != sizeof(struct vprbrd_gpiob_msg))
+			dev_err(chip->dev, "usb error setting pin value\n");
+	}
+}
+
+static int vprbrd_gpiob_direction_input(struct gpio_chip *chip,
+			unsigned offset)
+{
+	int ret;
+	struct vprbrd_gpio *gpio =
+			container_of(chip, struct vprbrd_gpio, gpiob);
+	struct vprbrd *vb = gpio->vb;
+
+	gpio->gpiob_out &= ~(1 << offset);
+
+	mutex_lock(&vb->lock);
+
+	ret = vprbrd_gpiob_setdir(vb, offset, 0);
+
+	mutex_unlock(&vb->lock);
+
+	if (ret)
+		dev_err(chip->dev, "usb error setting pin to input\n");
+
+	return ret;
+}
+
+static int vprbrd_gpiob_direction_output(struct gpio_chip *chip,
+			unsigned offset, int value)
+{
+	int ret;
+	struct vprbrd_gpio *gpio =
+			container_of(chip, struct vprbrd_gpio, gpiob);
+	struct vprbrd *vb = gpio->vb;
+
+	gpio->gpiob_out |= (1 << offset);
+	if (value)
+		gpio->gpiob_val |= (1 << offset);
+	else
+		gpio->gpiob_val &= ~(1 << offset);
+
+	mutex_lock(&vb->lock);
+
+	ret = vprbrd_gpiob_setdir(vb, offset, 1);
+	if (ret)
+		dev_err(chip->dev, "usb error setting pin to output\n");
+
+	mutex_unlock(&vb->lock);
+
+	vprbrd_gpiob_set(chip, offset, value);
+
+	return ret;
+}
+
+/* ----- end of gpio b chip ---------------------------------------------- */
+
+static int __devinit vprbrd_gpio_probe(struct platform_device *pdev)
+{
+	struct vprbrd *vb = dev_get_drvdata(pdev->dev.parent);
+	struct vprbrd_gpio *vb_gpio;
+	int ret;
+
+	vb_gpio = devm_kzalloc(&pdev->dev, sizeof(*vb_gpio), GFP_KERNEL);
+	if (vb_gpio == NULL)
+		return -ENOMEM;
+
+	vb_gpio->vb = vb;
+	/* registering gpio a */
+	vb_gpio->gpioa.label = "viperboard gpio a";
+	vb_gpio->gpioa.dev = &pdev->dev;
+	vb_gpio->gpioa.owner = THIS_MODULE;
+	vb_gpio->gpioa.base = -1;
+	vb_gpio->gpioa.ngpio = 16;
+	vb_gpio->gpioa.can_sleep = 1;
+	vb_gpio->gpioa.set = vprbrd_gpioa_set;
+	vb_gpio->gpioa.get = vprbrd_gpioa_get;
+	vb_gpio->gpioa.direction_input = vprbrd_gpioa_direction_input;
+	vb_gpio->gpioa.direction_output = vprbrd_gpioa_direction_output;
+	ret = gpiochip_add(&vb_gpio->gpioa);
+	if (ret < 0) {
+		dev_err(vb_gpio->gpioa.dev, "could not add gpio a");
+		goto err_gpioa;
+	}
+
+	/* registering gpio b */
+	vb_gpio->gpiob.label = "viperboard gpio b";
+	vb_gpio->gpiob.dev = &pdev->dev;
+	vb_gpio->gpiob.owner = THIS_MODULE;
+	vb_gpio->gpiob.base = -1;
+	vb_gpio->gpiob.ngpio = 16;
+	vb_gpio->gpiob.can_sleep = 1;
+	vb_gpio->gpiob.set = vprbrd_gpiob_set;
+	vb_gpio->gpiob.get = vprbrd_gpiob_get;
+	vb_gpio->gpiob.direction_input = vprbrd_gpiob_direction_input;
+	vb_gpio->gpiob.direction_output = vprbrd_gpiob_direction_output;
+	ret = gpiochip_add(&vb_gpio->gpiob);
+	if (ret < 0) {
+		dev_err(vb_gpio->gpiob.dev, "could not add gpio b");
+		goto err_gpiob;
+	}
+
+	platform_set_drvdata(pdev, vb_gpio);
+
+	return ret;
+
+err_gpiob:
+	ret = gpiochip_remove(&vb_gpio->gpioa);
+
+err_gpioa:
+	return ret;
+}
+
+static int __devexit vprbrd_gpio_remove(struct platform_device *pdev)
+{
+	struct vprbrd_gpio *vb_gpio = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = gpiochip_remove(&vb_gpio->gpiob);
+	if (ret == 0)
+		ret = gpiochip_remove(&vb_gpio->gpioa);
+
+	return ret;
+}
+
+static struct platform_driver vprbrd_gpio_driver = {
+	.driver.name	= "viperboard-gpio",
+	.driver.owner	= THIS_MODULE,
+	.probe		= vprbrd_gpio_probe,
+	.remove		= __devexit_p(vprbrd_gpio_remove),
+};
+
+static int __init vprbrd_gpio_init(void)
+{
+	switch (gpioa_freq) {
+	case 1000000:
+		gpioa_clk = VPRBRD_GPIOA_CLK_1MHZ;
+		break;
+	case 100000:
+		gpioa_clk = VPRBRD_GPIOA_CLK_100KHZ;
+		break;
+	case 10000:
+		gpioa_clk = VPRBRD_GPIOA_CLK_10KHZ;
+		break;
+	case 1000:
+		gpioa_clk = VPRBRD_GPIOA_CLK_1KHZ;
+		break;
+	case 100:
+		gpioa_clk = VPRBRD_GPIOA_CLK_100HZ;
+		break;
+	case 10:
+		gpioa_clk = VPRBRD_GPIOA_CLK_10HZ;
+		break;
+	default:
+		pr_warn("invalid gpioa_freq (%d)\n", gpioa_freq);
+		gpioa_clk = VPRBRD_GPIOA_CLK_1KHZ;
+	}
+
+	return platform_driver_register(&vprbrd_gpio_driver);
+}
+subsys_initcall(vprbrd_gpio_init);
+
+static void __exit vprbrd_gpio_exit(void)
+{
+	platform_driver_unregister(&vprbrd_gpio_driver);
+}
+module_exit(vprbrd_gpio_exit);
+
+MODULE_AUTHOR("Lars Poeschel <poeschel@lemonage.de>");
+MODULE_DESCRIPTION("GPIO driver for Nano River Techs Viperboard");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:viperboard-gpio");
diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/gpio-vr41xx.c
index 82d5c20..9902732 100644
--- a/drivers/gpio/gpio-vr41xx.c
+++ b/drivers/gpio/gpio-vr41xx.c
@@ -490,7 +490,7 @@ static struct gpio_chip vr41xx_gpio_chip = {
 	.to_irq			= vr41xx_gpio_to_irq,
 };
 
-static int __devinit giu_probe(struct platform_device *pdev)
+static int giu_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	unsigned int trigger, i, pin;
@@ -552,7 +552,7 @@ static int __devinit giu_probe(struct platform_device *pdev)
 	return cascade_irq(irq, giu_get_irq);
 }
 
-static int __devexit giu_remove(struct platform_device *pdev)
+static int giu_remove(struct platform_device *pdev)
 {
 	if (giu_base) {
 		iounmap(giu_base);
@@ -564,7 +564,7 @@ static int __devexit giu_remove(struct platform_device *pdev)
 
 static struct platform_driver giu_device_driver = {
 	.probe		= giu_probe,
-	.remove		= __devexit_p(giu_remove),
+	.remove		= giu_remove,
 	.driver		= {
 		.name	= "GIU",
 		.owner	= THIS_MODULE,
diff --git a/drivers/gpio/gpio-vt8500.c b/drivers/gpio/gpio-vt8500.c
index bcd8e4a..b53320a 100644
--- a/drivers/gpio/gpio-vt8500.c
+++ b/drivers/gpio/gpio-vt8500.c
@@ -96,6 +96,7 @@ static struct vt8500_gpio_data wm8505_data = {
 		VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12),
 		VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16),
 		VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22),
+		VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),
 	},
 };
 
@@ -115,6 +116,7 @@ static struct vt8500_gpio_data wm8650_data = {
 		VT8500_BANK(0x58, 0x98, 0xD8, 0x18, 32),
 		VT8500_BANK(0x5C, 0x9C, 0xDC, 0x1C, 32),
 		VT8500_BANK(0x7C, 0xBC, 0xFC, 0x3C, 32),
+		VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),
 	},
 };
 
@@ -269,7 +271,7 @@ static struct of_device_id vt8500_gpio_dt_ids[] = {
 	{ /* Sentinel */ },
 };
 
-static int __devinit vt8500_gpio_probe(struct platform_device *pdev)
+static int vt8500_gpio_probe(struct platform_device *pdev)
 {
 	void __iomem *gpio_base;
 	struct device_node *np;
diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c
index 76ebfe5..2b7252c 100644
--- a/drivers/gpio/gpio-vx855.c
+++ b/drivers/gpio/gpio-vx855.c
@@ -219,7 +219,7 @@ static void vx855gpio_gpio_setup(struct vx855_gpio *vg)
 }
 
 /* This platform device is ordinarily registered by the vx855 mfd driver */
-static __devinit int vx855gpio_probe(struct platform_device *pdev)
+static int vx855gpio_probe(struct platform_device *pdev)
 {
 	struct resource *res_gpi;
 	struct resource *res_gpo;
@@ -284,7 +284,7 @@ out_release:
 	return ret;
 }
 
-static int __devexit vx855gpio_remove(struct platform_device *pdev)
+static int vx855gpio_remove(struct platform_device *pdev)
 {
 	struct vx855_gpio *vg = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -312,7 +312,7 @@ static struct platform_driver vx855gpio_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= vx855gpio_probe,
-	.remove		= __devexit_p(vx855gpio_remove),
+	.remove		= vx855gpio_remove,
 };
 
 module_platform_driver(vx855gpio_driver);
diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c
index b6eda35..2a743e1 100644
--- a/drivers/gpio/gpio-wm831x.c
+++ b/drivers/gpio/gpio-wm831x.c
@@ -243,7 +243,7 @@ static struct gpio_chip template_chip = {
 	.can_sleep		= 1,
 };
 
-static int __devinit wm831x_gpio_probe(struct platform_device *pdev)
+static int wm831x_gpio_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -275,7 +275,7 @@ static int __devinit wm831x_gpio_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit wm831x_gpio_remove(struct platform_device *pdev)
+static int wm831x_gpio_remove(struct platform_device *pdev)
 {
 	struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev);
 
@@ -286,7 +286,7 @@ static struct platform_driver wm831x_gpio_driver = {
 	.driver.name	= "wm831x-gpio",
 	.driver.owner	= THIS_MODULE,
 	.probe		= wm831x_gpio_probe,
-	.remove		= __devexit_p(wm831x_gpio_remove),
+	.remove		= wm831x_gpio_remove,
 };
 
 static int __init wm831x_gpio_init(void)
diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c
index fb42938..0b598cf 100644
--- a/drivers/gpio/gpio-wm8350.c
+++ b/drivers/gpio/gpio-wm8350.c
@@ -109,7 +109,7 @@ static struct gpio_chip template_chip = {
 	.can_sleep		= 1,
 };
 
-static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
+static int wm8350_gpio_probe(struct platform_device *pdev)
 {
 	struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent);
 	struct wm8350_platform_data *pdata = wm8350->dev->platform_data;
@@ -141,7 +141,7 @@ static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit wm8350_gpio_remove(struct platform_device *pdev)
+static int wm8350_gpio_remove(struct platform_device *pdev)
 {
 	struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
 
@@ -152,7 +152,7 @@ static struct platform_driver wm8350_gpio_driver = {
 	.driver.name	= "wm8350-gpio",
 	.driver.owner	= THIS_MODULE,
 	.probe		= wm8350_gpio_probe,
-	.remove		= __devexit_p(wm8350_gpio_remove),
+	.remove		= wm8350_gpio_remove,
 };
 
 static int __init wm8350_gpio_init(void)
diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c
index 1c764e7..ae409fd 100644
--- a/drivers/gpio/gpio-wm8994.c
+++ b/drivers/gpio/gpio-wm8994.c
@@ -245,7 +245,7 @@ static struct gpio_chip template_chip = {
 	.can_sleep		= 1,
 };
 
-static int __devinit wm8994_gpio_probe(struct platform_device *pdev)
+static int wm8994_gpio_probe(struct platform_device *pdev)
 {
 	struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
 	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
@@ -281,7 +281,7 @@ err:
 	return ret;
 }
 
-static int __devexit wm8994_gpio_remove(struct platform_device *pdev)
+static int wm8994_gpio_remove(struct platform_device *pdev)
 {
 	struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev);
 
@@ -292,7 +292,7 @@ static struct platform_driver wm8994_gpio_driver = {
 	.driver.name	= "wm8994-gpio",
 	.driver.owner	= THIS_MODULE,
 	.probe		= wm8994_gpio_probe,
-	.remove		= __devexit_p(wm8994_gpio_remove),
+	.remove		= wm8994_gpio_remove,
 };
 
 static int __init wm8994_gpio_init(void)
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c
index 79b0fe8..9ae7aa8 100644
--- a/drivers/gpio/gpio-xilinx.c
+++ b/drivers/gpio/gpio-xilinx.c
@@ -159,7 +159,7 @@ static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc)
  * driver data structure. It returns 0, if the driver is bound to the GPIO
  * device, or a negative value if there is an error.
  */
-static int __devinit xgpio_of_probe(struct device_node *np)
+static int xgpio_of_probe(struct device_node *np)
 {
 	struct xgpio_instance *chip;
 	int status = 0;
@@ -209,7 +209,7 @@ static int __devinit xgpio_of_probe(struct device_node *np)
 	return 0;
 }
 
-static struct of_device_id xgpio_of_match[] __devinitdata = {
+static struct of_device_id xgpio_of_match[] = {
 	{ .compatible = "xlnx,xps-gpio-1.00.a", },
 	{ /* end of list */ },
 };
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
new file mode 100644
index 0000000..cbad6e9
--- /dev/null
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -0,0 +1,54 @@
+/*
+ * ACPI helpers for GPIO API
+ *
+ * Copyright (C) 2012, Intel Corporation
+ * Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
+ *          Mika Westerberg <mika.westerberg@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/export.h>
+#include <linux/acpi_gpio.h>
+#include <linux/acpi.h>
+
+static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
+{
+	if (!gc->dev)
+		return false;
+
+	return ACPI_HANDLE(gc->dev) == data;
+}
+
+/**
+ * acpi_get_gpio() - Translate ACPI GPIO pin to GPIO number 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
+ */
+
+int acpi_get_gpio(char *path, int pin)
+{
+	struct gpio_chip *chip;
+	acpi_handle handle;
+	acpi_status status;
+
+	status = acpi_get_handle(NULL, path, &handle);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	chip = gpiochip_find(handle, acpi_gpiochip_find);
+	if (!chip)
+		return -ENODEV;
+
+	if (!gpio_is_valid(chip->base + pin))
+		return -EINVAL;
+
+	return chip->base + pin;
+}
+EXPORT_SYMBOL_GPL(acpi_get_gpio);
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index f1a4599..d542a14 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_gpio.h>
+#include <linux/pinctrl/pinctrl.h>
 #include <linux/slab.h>
 
 /* Private data structure for of_gpiochip_find_and_xlate */
@@ -216,6 +217,54 @@ err0:
 }
 EXPORT_SYMBOL(of_mm_gpiochip_add);
 
+#ifdef CONFIG_PINCTRL
+static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
+{
+	struct device_node *np = chip->of_node;
+	struct of_phandle_args pinspec;
+	struct pinctrl_dev *pctldev;
+	int index = 0, ret;
+
+	if (!np)
+		return;
+
+	do {
+		ret = of_parse_phandle_with_args(np, "gpio-ranges",
+				"#gpio-range-cells", index, &pinspec);
+		if (ret)
+			break;
+
+		pctldev = of_pinctrl_get(pinspec.np);
+		if (!pctldev)
+			break;
+
+		/*
+		 * This assumes that the n GPIO pins are consecutive in the
+		 * GPIO number space, and that the pins are also consecutive
+		 * in their local number space. Currently it is not possible
+		 * to add different ranges for one and the same GPIO chip,
+		 * as the code assumes that we have one consecutive range
+		 * on both, mapping 1-to-1.
+		 *
+		 * TODO: make the OF bindings handle multiple sparse ranges
+		 * on the same GPIO chip.
+		 */
+		ret = gpiochip_add_pin_range(chip,
+					     pinctrl_dev_get_name(pctldev),
+					     0, /* offset in gpiochip */
+					     pinspec.args[0],
+					     pinspec.args[1]);
+
+		if (ret)
+			break;
+
+	} while (index++);
+}
+
+#else
+static void of_gpiochip_add_pin_range(struct gpio_chip *chip) {}
+#endif
+
 void of_gpiochip_add(struct gpio_chip *chip)
 {
 	if ((!chip->of_node) && (chip->dev))
@@ -229,11 +278,14 @@ void of_gpiochip_add(struct gpio_chip *chip)
 		chip->of_xlate = of_gpio_simple_xlate;
 	}
 
+	of_gpiochip_add_pin_range(chip);
 	of_node_get(chip->of_node);
 }
 
 void of_gpiochip_remove(struct gpio_chip *chip)
 {
+	gpiochip_remove_pin_ranges(chip);
+
 	if (chip->of_node)
 		of_node_put(chip->of_node);
 }
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 1c8d9e3..199fca1 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -191,6 +191,32 @@ err:
 	return ret;
 }
 
+/* caller ensures gpio is valid and requested, chip->get_direction may sleep  */
+static int gpio_get_direction(unsigned gpio)
+{
+	struct gpio_chip	*chip;
+	struct gpio_desc	*desc = &gpio_desc[gpio];
+	int			status = -EINVAL;
+
+	chip = gpio_to_chip(gpio);
+	gpio -= chip->base;
+
+	if (!chip->get_direction)
+		return status;
+
+	status = chip->get_direction(chip, gpio);
+	if (status > 0) {
+		/* GPIOF_DIR_IN, or other positive */
+		status = 1;
+		clear_bit(FLAG_IS_OUT, &desc->flags);
+	}
+	if (status == 0) {
+		/* GPIOF_DIR_OUT */
+		set_bit(FLAG_IS_OUT, &desc->flags);
+	}
+	return status;
+}
+
 #ifdef CONFIG_GPIO_SYSFS
 
 /* lock protects against unexport_gpio() being called while
@@ -223,6 +249,7 @@ static ssize_t gpio_direction_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	const struct gpio_desc	*desc = dev_get_drvdata(dev);
+	unsigned		gpio = desc - gpio_desc;
 	ssize_t			status;
 
 	mutex_lock(&sysfs_lock);
@@ -230,6 +257,7 @@ static ssize_t gpio_direction_show(struct device *dev,
 	if (!test_bit(FLAG_EXPORT, &desc->flags))
 		status = -EIO;
 	else
+		gpio_get_direction(gpio);
 		status = sprintf(buf, "%s\n",
 			test_bit(FLAG_IS_OUT, &desc->flags)
 				? "out" : "in");
@@ -704,8 +732,9 @@ int gpio_export(unsigned gpio, bool direction_may_change)
 {
 	unsigned long		flags;
 	struct gpio_desc	*desc;
-	int			status = -EINVAL;
+	int			status;
 	const char		*ioname = NULL;
+	struct device		*dev;
 
 	/* can't export until sysfs is available ... */
 	if (!gpio_class.p) {
@@ -713,59 +742,66 @@ int gpio_export(unsigned gpio, bool direction_may_change)
 		return -ENOENT;
 	}
 
-	if (!gpio_is_valid(gpio))
-		goto done;
+	if (!gpio_is_valid(gpio)) {
+		pr_debug("%s: gpio %d is not valid\n", __func__, gpio);
+		return -EINVAL;
+	}
 
 	mutex_lock(&sysfs_lock);
 
 	spin_lock_irqsave(&gpio_lock, flags);
 	desc = &gpio_desc[gpio];
-	if (test_bit(FLAG_REQUESTED, &desc->flags)
-			&& !test_bit(FLAG_EXPORT, &desc->flags)) {
-		status = 0;
-		if (!desc->chip->direction_input
-				|| !desc->chip->direction_output)
-			direction_may_change = false;
+	if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
+	     test_bit(FLAG_EXPORT, &desc->flags)) {
+		spin_unlock_irqrestore(&gpio_lock, flags);
+		pr_debug("%s: gpio %d unavailable (requested=%d, exported=%d)\n",
+				__func__, gpio,
+				test_bit(FLAG_REQUESTED, &desc->flags),
+				test_bit(FLAG_EXPORT, &desc->flags));
+		status = -EPERM;
+		goto fail_unlock;
 	}
+
+	if (!desc->chip->direction_input || !desc->chip->direction_output)
+		direction_may_change = false;
 	spin_unlock_irqrestore(&gpio_lock, flags);
 
 	if (desc->chip->names && desc->chip->names[gpio - desc->chip->base])
 		ioname = desc->chip->names[gpio - desc->chip->base];
 
-	if (status == 0) {
-		struct device	*dev;
-
-		dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
-				desc, ioname ? ioname : "gpio%u", gpio);
-		if (!IS_ERR(dev)) {
-			status = sysfs_create_group(&dev->kobj,
-						&gpio_attr_group);
-
-			if (!status && direction_may_change)
-				status = device_create_file(dev,
-						&dev_attr_direction);
-
-			if (!status && gpio_to_irq(gpio) >= 0
-					&& (direction_may_change
-						|| !test_bit(FLAG_IS_OUT,
-							&desc->flags)))
-				status = device_create_file(dev,
-						&dev_attr_edge);
-
-			if (status != 0)
-				device_unregister(dev);
-		} else
-			status = PTR_ERR(dev);
-		if (status == 0)
-			set_bit(FLAG_EXPORT, &desc->flags);
+	dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
+			    desc, ioname ? ioname : "gpio%u", gpio);
+	if (IS_ERR(dev)) {
+		status = PTR_ERR(dev);
+		goto fail_unlock;
 	}
 
-	mutex_unlock(&sysfs_lock);
-
-done:
+	status = sysfs_create_group(&dev->kobj, &gpio_attr_group);
 	if (status)
-		pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
+		goto fail_unregister_device;
+
+	if (direction_may_change) {
+		status = device_create_file(dev, &dev_attr_direction);
+		if (status)
+			goto fail_unregister_device;
+	}
+
+	if (gpio_to_irq(gpio) >= 0 && (direction_may_change ||
+				       !test_bit(FLAG_IS_OUT, &desc->flags))) {
+		status = device_create_file(dev, &dev_attr_edge);
+		if (status)
+			goto fail_unregister_device;
+	}
+
+	set_bit(FLAG_EXPORT, &desc->flags);
+	mutex_unlock(&sysfs_lock);
+	return 0;
 
+fail_unregister_device:
+	device_unregister(dev);
+fail_unlock:
+	mutex_unlock(&sysfs_lock);
+	pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
 	return status;
 }
 EXPORT_SYMBOL_GPL(gpio_export);
@@ -1075,6 +1111,7 @@ int gpiochip_add(struct gpio_chip *chip)
 			 * inputs (often with pullups enabled) so power
 			 * usage is minimized.  Linux code should set the
 			 * gpio direction first thing; but until it does,
+			 * and in case chip->get_direction is not set,
 			 * we may expose the wrong direction in sysfs.
 			 */
 			gpio_desc[id].flags = !chip->direction_input
@@ -1083,6 +1120,10 @@ int gpiochip_add(struct gpio_chip *chip)
 		}
 	}
 
+#ifdef CONFIG_PINCTRL
+	INIT_LIST_HEAD(&chip->pin_ranges);
+#endif
+
 	of_gpiochip_add(chip);
 
 unlock:
@@ -1123,6 +1164,7 @@ int gpiochip_remove(struct gpio_chip *chip)
 
 	spin_lock_irqsave(&gpio_lock, flags);
 
+	gpiochip_remove_pin_ranges(chip);
 	of_gpiochip_remove(chip);
 
 	for (id = chip->base; id < chip->base + chip->ngpio; id++) {
@@ -1180,6 +1222,77 @@ struct gpio_chip *gpiochip_find(void *data,
 }
 EXPORT_SYMBOL_GPL(gpiochip_find);
 
+#ifdef CONFIG_PINCTRL
+
+/**
+ * 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
+ * @gpio_offset: the start offset in the current gpio_chip number space
+ * @pin_offset: the start offset in the pin controller number space
+ * @npins: the number of pins from the offset of each pin space (GPIO and
+ *	pin controller) to accumulate in this range
+ */
+int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+			   unsigned int gpio_offset, unsigned int pin_offset,
+			   unsigned int npins)
+{
+	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->range.pin_base = pin_offset;
+	pin_range->range.npins = npins;
+	pin_range->pctldev = pinctrl_find_and_add_gpio_range(pinctl_name,
+			&pin_range->range);
+	if (IS_ERR(pin_range->pctldev)) {
+		ret = PTR_ERR(pin_range->pctldev);
+		pr_err("%s: GPIO chip: could not create pin range\n",
+		       chip->label);
+		kfree(pin_range);
+		return ret;
+	}
+	pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PIN %d->%d\n",
+		 chip->label, gpio_offset, gpio_offset + npins - 1,
+		 pinctl_name,
+		 pin_offset, pin_offset + npins - 1);
+
+	list_add_tail(&pin_range->node, &chip->pin_ranges);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(gpiochip_add_pin_range);
+
+/**
+ * gpiochip_remove_pin_ranges() - remove all the GPIO <-> pin mappings
+ * @chip: the chip to remove all the mappings for
+ */
+void gpiochip_remove_pin_ranges(struct gpio_chip *chip)
+{
+	struct gpio_pin_range *pin_range, *tmp;
+
+	list_for_each_entry_safe(pin_range, tmp, &chip->pin_ranges, node) {
+		list_del(&pin_range->node);
+		pinctrl_remove_gpio_range(pin_range->pctldev,
+				&pin_range->range);
+		kfree(pin_range);
+	}
+}
+EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges);
+
+#endif /* CONFIG_PINCTRL */
+
 /* These "optional" allocation calls help prevent drivers from stomping
  * on each other, and help provide better diagnostics in debugfs.
  * They're called even less than the "set direction" calls.
@@ -1228,9 +1341,15 @@ int gpio_request(unsigned gpio, const char *label)
 			desc_set_label(desc, NULL);
 			module_put(chip->owner);
 			clear_bit(FLAG_REQUESTED, &desc->flags);
+			goto done;
 		}
 	}
-
+	if (chip->get_direction) {
+		/* chip->get_direction may sleep */
+		spin_unlock_irqrestore(&gpio_lock, flags);
+		gpio_get_direction(gpio);
+		spin_lock_irqsave(&gpio_lock, flags);
+	}
 done:
 	if (status)
 		pr_debug("gpio_request: gpio-%d (%s) status %d\n",
@@ -1766,6 +1885,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 		if (!test_bit(FLAG_REQUESTED, &gdesc->flags))
 			continue;
 
+		gpio_get_direction(gpio);
 		is_out = test_bit(FLAG_IS_OUT, &gdesc->flags);
 		seq_printf(s, " gpio-%-3d (%-20.20s) %s %s",
 			gpio, gdesc->label,
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 18321b68b..983201b 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -210,3 +210,5 @@ source "drivers/gpu/drm/mgag200/Kconfig"
 source "drivers/gpu/drm/cirrus/Kconfig"
 
 source "drivers/gpu/drm/shmobile/Kconfig"
+
+source "drivers/gpu/drm/tegra/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 2ff5cef..6f58c81 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -8,7 +8,7 @@ drm-y       :=	drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
 		drm_context.o drm_dma.o \
 		drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
 		drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
-		drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
+		drm_agpsupport.o drm_scatter.o drm_pci.o \
 		drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
 		drm_crtc.o drm_modes.o drm_edid.o \
 		drm_info.o drm_debugfs.o drm_encoder_slave.o \
@@ -16,10 +16,11 @@ drm-y       :=	drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
+drm-$(CONFIG_PCI) += ati_pcigart.o
 
 drm-usb-y   := drm_usb.o
 
-drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_i2c_helper.o
+drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_helper.o
 drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
 drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
 
@@ -48,4 +49,5 @@ obj-$(CONFIG_DRM_GMA500) += gma500/
 obj-$(CONFIG_DRM_UDL) += udl/
 obj-$(CONFIG_DRM_AST) += ast/
 obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
+obj-$(CONFIG_DRM_TEGRA) += tegra/
 obj-y			+= i2c/
diff --git a/drivers/gpu/drm/ast/ast_ttm.c b/drivers/gpu/drm/ast/ast_ttm.c
index 1a026ac..0a54f65 100644
--- a/drivers/gpu/drm/ast/ast_ttm.c
+++ b/drivers/gpu/drm/ast/ast_ttm.c
@@ -356,7 +356,7 @@ int ast_bo_create(struct drm_device *dev, int size, int align,
 
 	ret = ttm_bo_init(&ast->ttm.bdev, &astbo->bo, size,
 			  ttm_bo_type_device, &astbo->placement,
-			  align >> PAGE_SHIFT, 0, false, NULL, acc_size,
+			  align >> PAGE_SHIFT, false, NULL, acc_size,
 			  NULL, ast_bo_ttm_destroy);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c
index 101e423..dcd1a8c 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.c
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.c
@@ -35,12 +35,15 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
 };
 
 
-static void cirrus_kick_out_firmware_fb(struct pci_dev *pdev)
+static int cirrus_kick_out_firmware_fb(struct pci_dev *pdev)
 {
 	struct apertures_struct *ap;
 	bool primary = false;
 
 	ap = alloc_apertures(1);
+	if (!ap)
+		return -ENOMEM;
+
 	ap->ranges[0].base = pci_resource_start(pdev, 0);
 	ap->ranges[0].size = pci_resource_len(pdev, 0);
 
@@ -49,12 +52,18 @@ static void cirrus_kick_out_firmware_fb(struct pci_dev *pdev)
 #endif
 	remove_conflicting_framebuffers(ap, "cirrusdrmfb", primary);
 	kfree(ap);
+
+	return 0;
 }
 
 static int __devinit
 cirrus_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	cirrus_kick_out_firmware_fb(pdev);
+	int ret;
+
+	ret = cirrus_kick_out_firmware_fb(pdev);
+	if (ret)
+		return ret;
 
 	return drm_get_pci_dev(pdev, ent, &driver);
 }
diff --git a/drivers/gpu/drm/cirrus/cirrus_ttm.c b/drivers/gpu/drm/cirrus/cirrus_ttm.c
index bc83f83..90d7701 100644
--- a/drivers/gpu/drm/cirrus/cirrus_ttm.c
+++ b/drivers/gpu/drm/cirrus/cirrus_ttm.c
@@ -361,7 +361,7 @@ int cirrus_bo_create(struct drm_device *dev, int size, int align,
 
 	ret = ttm_bo_init(&cirrus->ttm.bdev, &cirrusbo->bo, size,
 			  ttm_bo_type_device, &cirrusbo->placement,
-			  align >> PAGE_SHIFT, 0, false, NULL, acc_size,
+			  align >> PAGE_SHIFT, false, NULL, acc_size,
 			  NULL, cirrus_bo_ttm_destroy);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index ef1b221..d6d0072 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -470,10 +470,8 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 
-	if (crtc->gamma_store) {
-		kfree(crtc->gamma_store);
-		crtc->gamma_store = NULL;
-	}
+	kfree(crtc->gamma_store);
+	crtc->gamma_store = NULL;
 
 	drm_mode_object_put(dev, &crtc->base);
 	list_del(&crtc->head);
@@ -555,6 +553,7 @@ int drm_connector_init(struct drm_device *dev,
 	INIT_LIST_HEAD(&connector->probed_modes);
 	INIT_LIST_HEAD(&connector->modes);
 	connector->edid_blob_ptr = NULL;
+	connector->status = connector_status_unknown;
 
 	list_add_tail(&connector->head, &dev->mode_config.connector_list);
 	dev->mode_config.num_connector++;
@@ -2280,13 +2279,21 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
 
 	for (i = 0; i < num_planes; i++) {
 		unsigned int width = r->width / (i != 0 ? hsub : 1);
+		unsigned int height = r->height / (i != 0 ? vsub : 1);
+		unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
 
 		if (!r->handles[i]) {
 			DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
 			return -EINVAL;
 		}
 
-		if (r->pitches[i] < drm_format_plane_cpp(r->pixel_format, i) * width) {
+		if ((uint64_t) width * cpp > UINT_MAX)
+			return -ERANGE;
+
+		if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX)
+			return -ERANGE;
+
+		if (r->pitches[i] < width * cpp) {
 			DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
 			return -EINVAL;
 		}
@@ -2323,6 +2330,11 @@ int drm_mode_addfb2(struct drm_device *dev,
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
 
+	if (r->flags & ~DRM_MODE_FB_INTERLACED) {
+		DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
+		return -EINVAL;
+	}
+
 	if ((config->min_width > r->width) || (r->width > config->max_width)) {
 		DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
 			  r->width, config->min_width, config->max_width);
@@ -3180,6 +3192,8 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
 	size = EDID_LENGTH * (1 + edid->extensions);
 	connector->edid_blob_ptr = drm_property_create_blob(connector->dev,
 							    size, edid);
+	if (!connector->edid_blob_ptr)
+		return -EINVAL;
 
 	ret = drm_connector_property_set_value(connector,
 					       dev->mode_config.edid_property,
@@ -3204,6 +3218,9 @@ static bool drm_property_change_is_valid(struct drm_property *property,
 		for (i = 0; i < property->num_values; i++)
 			valid_mask |= (1ULL << property->values[i]);
 		return !(value & ~valid_mask);
+	} else if (property->flags & DRM_MODE_PROP_BLOB) {
+		/* Only the driver knows */
+		return true;
 	} else {
 		int i;
 		for (i = 0; i < property->num_values; i++)
@@ -3656,9 +3673,12 @@ void drm_mode_config_reset(struct drm_device *dev)
 		if (encoder->funcs->reset)
 			encoder->funcs->reset(encoder);
 
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		connector->status = connector_status_unknown;
+
 		if (connector->funcs->reset)
 			connector->funcs->reset(connector);
+	}
 }
 EXPORT_SYMBOL(drm_mode_config_reset);
 
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 1227adf..7b2d378 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -39,6 +39,35 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_edid.h>
 
+/**
+ * drm_helper_move_panel_connectors_to_head() - move panels to the front in the
+ * 						connector list
+ * @dev: drm device to operate on
+ *
+ * Some userspace presumes that the first connected connector is the main
+ * display, where it's supposed to display e.g. the login screen. For
+ * laptops, this should be the main panel. Use this function to sort all
+ * (eDP/LVDS) panels to the front of the connector list, instead of
+ * painstakingly trying to initialize them in the right order.
+ */
+void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
+{
+	struct drm_connector *connector, *tmp;
+	struct list_head panel_list;
+
+	INIT_LIST_HEAD(&panel_list);
+
+	list_for_each_entry_safe(connector, tmp,
+				 &dev->mode_config.connector_list, head) {
+		if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+		    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+			list_move_tail(&connector->head, &panel_list);
+	}
+
+	list_splice(&panel_list, &dev->mode_config.connector_list);
+}
+EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
+
 static bool drm_kms_helper_poll = true;
 module_param_named(poll, drm_kms_helper_poll, bool, 0600);
 
@@ -64,22 +93,21 @@ static void drm_mode_validate_flag(struct drm_connector *connector,
 
 /**
  * drm_helper_probe_single_connector_modes - get complete set of display modes
- * @dev: DRM device
+ * @connector: connector to probe
  * @maxX: max width for modes
  * @maxY: max height for modes
  *
  * LOCKING:
  * Caller must hold mode config lock.
  *
- * Based on @dev's mode_config layout, scan all the connectors and try to detect
- * modes on them.  Modes will first be added to the connector's probed_modes
- * list, then culled (based on validity and the @maxX, @maxY parameters) and
- * put into the normal modes list.
+ * Based on the helper callbacks implemented by @connector try to detect all
+ * valid modes.  Modes will first be added to the connector's probed_modes list,
+ * then culled (based on validity and the @maxX, @maxY parameters) and put into
+ * the normal modes list.
  *
- * Intended to be used either at bootup time or when major configuration
- * changes have occurred.
- *
- * FIXME: take into account monitor limits
+ * Intended to be use as a generic implementation of the ->probe() @connector
+ * callback for drivers that use the crtc helpers for output mode filtering and
+ * detection.
  *
  * RETURNS:
  * Number of modes found on @connector.
@@ -109,9 +137,14 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
 			connector->funcs->force(connector);
 	} else {
 		connector->status = connector->funcs->detect(connector, true);
-		drm_kms_helper_poll_enable(dev);
 	}
 
+	/* Re-enable polling in case the global poll config changed. */
+	if (drm_kms_helper_poll != dev->mode_config.poll_running)
+		drm_kms_helper_poll_enable(dev);
+
+	dev->mode_config.poll_running = drm_kms_helper_poll;
+
 	if (connector->status == connector_status_disconnected) {
 		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
 			connector->base.id, drm_get_connector_name(connector));
@@ -325,17 +358,24 @@ drm_crtc_prepare_encoders(struct drm_device *dev)
 }
 
 /**
- * drm_crtc_set_mode - set a mode
+ * drm_crtc_helper_set_mode - internal helper to set a mode
  * @crtc: CRTC to program
  * @mode: mode to use
- * @x: width of mode
- * @y: height of mode
+ * @x: horizontal offset into the surface
+ * @y: vertical offset into the surface
+ * @old_fb: old framebuffer, for cleanup
  *
  * LOCKING:
  * Caller must hold mode config lock.
  *
  * Try to set @mode on @crtc.  Give @crtc and its associated connectors a chance
- * to fixup or reject the mode prior to trying to set it.
+ * to fixup or reject the mode prior to trying to set it. This is an internal
+ * helper that drivers could e.g. use to update properties that require the
+ * entire output pipe to be disabled and re-enabled in a new configuration. For
+ * example for changing whether audio is enabled on a hdmi link or for changing
+ * panel fitter or dither attributes. It is also called by the
+ * drm_crtc_helper_set_config() helper function to drive the mode setting
+ * sequence.
  *
  * RETURNS:
  * True if the mode was set successfully, or false otherwise.
@@ -491,20 +531,19 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
 
 /**
  * drm_crtc_helper_set_config - set a new config from userspace
- * @crtc: CRTC to setup
- * @crtc_info: user provided configuration
- * @new_mode: new mode to set
- * @connector_set: set of connectors for the new config
- * @fb: new framebuffer
+ * @set: mode set configuration
  *
  * LOCKING:
  * Caller must hold mode config lock.
  *
- * Setup a new configuration, provided by the user in @crtc_info, and enable
- * it.
+ * Setup a new configuration, provided by the upper layers (either an ioctl call
+ * from userspace or internally e.g. from the fbdev suppport code) in @set, and
+ * enable it. This is the main helper functions for drivers that implement
+ * kernel mode setting with the crtc helper functions and the assorted
+ * ->prepare(), ->modeset() and ->commit() helper callbacks.
  *
  * RETURNS:
- * Zero. (FIXME)
+ * Returns 0 on success, -ERRNO on failure.
  */
 int drm_crtc_helper_set_config(struct drm_mode_set *set)
 {
@@ -800,12 +839,14 @@ static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
 }
 
 /**
- * drm_helper_connector_dpms
- * @connector affected connector
- * @mode DPMS mode
+ * drm_helper_connector_dpms() - connector dpms helper implementation
+ * @connector: affected connector
+ * @mode: DPMS mode
  *
- * Calls the low-level connector DPMS function, then
- * calls appropriate encoder and crtc DPMS functions as well
+ * This is the main helper function provided by the crtc helper framework for
+ * implementing the DPMS connector attribute. It computes the new desired DPMS
+ * state for all encoders and crtcs in the output mesh and calls the ->dpms()
+ * callback provided by the driver appropriately.
  */
 void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
 {
@@ -918,6 +959,15 @@ int drm_helper_resume_force_mode(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_helper_resume_force_mode);
 
+void drm_kms_helper_hotplug_event(struct drm_device *dev)
+{
+	/* send a uevent + call fbdev */
+	drm_sysfs_hotplug_event(dev);
+	if (dev->mode_config.funcs->output_poll_changed)
+		dev->mode_config.funcs->output_poll_changed(dev);
+}
+EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
+
 #define DRM_OUTPUT_POLL_PERIOD (10*HZ)
 static void output_poll_execute(struct work_struct *work)
 {
@@ -933,20 +983,22 @@ static void output_poll_execute(struct work_struct *work)
 	mutex_lock(&dev->mode_config.mutex);
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 
-		/* if this is HPD or polled don't check it -
-		   TV out for instance */
-		if (!connector->polled)
+		/* Ignore forced connectors. */
+		if (connector->force)
 			continue;
 
-		else if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT))
-			repoll = true;
+		/* Ignore HPD capable connectors and connectors where we don't
+		 * want any hotplug detection at all for polling. */
+		if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD)
+			continue;
+
+		repoll = true;
 
 		old_status = connector->status;
 		/* if we are connected and don't want to poll for disconnect
 		   skip it */
 		if (old_status == connector_status_connected &&
-		    !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT) &&
-		    !(connector->polled & DRM_CONNECTOR_POLL_HPD))
+		    !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT))
 			continue;
 
 		connector->status = connector->funcs->detect(connector, false);
@@ -960,12 +1012,8 @@ static void output_poll_execute(struct work_struct *work)
 
 	mutex_unlock(&dev->mode_config.mutex);
 
-	if (changed) {
-		/* send a uevent + call fbdev */
-		drm_sysfs_hotplug_event(dev);
-		if (dev->mode_config.funcs->output_poll_changed)
-			dev->mode_config.funcs->output_poll_changed(dev);
-	}
+	if (changed)
+		drm_kms_helper_hotplug_event(dev);
 
 	if (repoll)
 		schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD);
@@ -988,7 +1036,8 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
 		return;
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		if (connector->polled)
+		if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
+					 DRM_CONNECTOR_POLL_DISCONNECT))
 			poll = true;
 	}
 
@@ -1014,12 +1063,34 @@ EXPORT_SYMBOL(drm_kms_helper_poll_fini);
 
 void drm_helper_hpd_irq_event(struct drm_device *dev)
 {
+	struct drm_connector *connector;
+	enum drm_connector_status old_status;
+	bool changed = false;
+
 	if (!dev->mode_config.poll_enabled)
 		return;
 
-	/* kill timer and schedule immediate execution, this doesn't block */
-	cancel_delayed_work(&dev->mode_config.output_poll_work);
-	if (drm_kms_helper_poll)
-		schedule_delayed_work(&dev->mode_config.output_poll_work, 0);
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+
+		/* Only handle HPD capable connectors. */
+		if (!(connector->polled & DRM_CONNECTOR_POLL_HPD))
+			continue;
+
+		old_status = connector->status;
+
+		connector->status = connector->funcs->detect(connector, false);
+		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
+			      connector->base.id,
+			      drm_get_connector_name(connector),
+			      old_status, connector->status);
+		if (old_status != connector->status)
+			changed = true;
+	}
+
+	mutex_unlock(&dev->mode_config.mutex);
+
+	if (changed)
+		drm_kms_helper_hotplug_event(dev);
 }
 EXPORT_SYMBOL(drm_helper_hpd_irq_event);
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
new file mode 100644
index 0000000..89e1966
--- /dev/null
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -0,0 +1,348 @@
+/*
+ * Copyright © 2009 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/i2c.h>
+#include <drm/drm_dp_helper.h>
+#include <drm/drmP.h>
+
+/**
+ * DOC: dp helpers
+ *
+ * These functions contain some common logic and helpers at various abstraction
+ * levels to deal with Display Port sink devices and related things like DP aux
+ * channel transfers, EDID reading over DP aux channels, decoding certain DPCD
+ * blocks, ...
+ */
+
+/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
+static int
+i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
+			    uint8_t write_byte, uint8_t *read_byte)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	int ret;
+
+	ret = (*algo_data->aux_ch)(adapter, mode,
+				   write_byte, read_byte);
+	return ret;
+}
+
+/*
+ * I2C over AUX CH
+ */
+
+/*
+ * Send the address. If the I2C link is running, this 'restarts'
+ * the connection with the new address, this is used for doing
+ * a write followed by a read (as needed for DDC)
+ */
+static int
+i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	int mode = MODE_I2C_START;
+	int ret;
+
+	if (reading)
+		mode |= MODE_I2C_READ;
+	else
+		mode |= MODE_I2C_WRITE;
+	algo_data->address = address;
+	algo_data->running = true;
+	ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
+	return ret;
+}
+
+/*
+ * Stop the I2C transaction. This closes out the link, sending
+ * a bare address packet with the MOT bit turned off
+ */
+static void
+i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	int mode = MODE_I2C_STOP;
+
+	if (reading)
+		mode |= MODE_I2C_READ;
+	else
+		mode |= MODE_I2C_WRITE;
+	if (algo_data->running) {
+		(void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
+		algo_data->running = false;
+	}
+}
+
+/*
+ * Write a single byte to the current I2C address, the
+ * the I2C link must be running or this returns -EIO
+ */
+static int
+i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	int ret;
+
+	if (!algo_data->running)
+		return -EIO;
+
+	ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
+	return ret;
+}
+
+/*
+ * Read a single byte from the current I2C address, the
+ * I2C link must be running or this returns -EIO
+ */
+static int
+i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	int ret;
+
+	if (!algo_data->running)
+		return -EIO;
+
+	ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
+	return ret;
+}
+
+static int
+i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter,
+		     struct i2c_msg *msgs,
+		     int num)
+{
+	int ret = 0;
+	bool reading = false;
+	int m;
+	int b;
+
+	for (m = 0; m < num; m++) {
+		u16 len = msgs[m].len;
+		u8 *buf = msgs[m].buf;
+		reading = (msgs[m].flags & I2C_M_RD) != 0;
+		ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading);
+		if (ret < 0)
+			break;
+		if (reading) {
+			for (b = 0; b < len; b++) {
+				ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]);
+				if (ret < 0)
+					break;
+			}
+		} else {
+			for (b = 0; b < len; b++) {
+				ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]);
+				if (ret < 0)
+					break;
+			}
+		}
+		if (ret < 0)
+			break;
+	}
+	if (ret >= 0)
+		ret = num;
+	i2c_algo_dp_aux_stop(adapter, reading);
+	DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret);
+	return ret;
+}
+
+static u32
+i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+	       I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+	       I2C_FUNC_10BIT_ADDR;
+}
+
+static const struct i2c_algorithm i2c_dp_aux_algo = {
+	.master_xfer	= i2c_algo_dp_aux_xfer,
+	.functionality	= i2c_algo_dp_aux_functionality,
+};
+
+static void
+i2c_dp_aux_reset_bus(struct i2c_adapter *adapter)
+{
+	(void) i2c_algo_dp_aux_address(adapter, 0, false);
+	(void) i2c_algo_dp_aux_stop(adapter, false);
+}
+
+static int
+i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter)
+{
+	adapter->algo = &i2c_dp_aux_algo;
+	adapter->retries = 3;
+	i2c_dp_aux_reset_bus(adapter);
+	return 0;
+}
+
+/**
+ * i2c_dp_aux_add_bus() - register an i2c adapter using the aux ch helper
+ * @adapter: i2c adapter to register
+ *
+ * This registers an i2c adapater that uses dp aux channel as it's underlaying
+ * transport. The driver needs to fill out the &i2c_algo_dp_aux_data structure
+ * and store it in the algo_data member of the @adapter argument. This will be
+ * used by the i2c over dp aux algorithm to drive the hardware.
+ *
+ * RETURNS:
+ * 0 on success, -ERRNO on failure.
+ */
+int
+i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
+{
+	int error;
+
+	error = i2c_dp_aux_prepare_bus(adapter);
+	if (error)
+		return error;
+	error = i2c_add_adapter(adapter);
+	return error;
+}
+EXPORT_SYMBOL(i2c_dp_aux_add_bus);
+
+/* Helpers for DP link training */
+static u8 dp_link_status(u8 link_status[DP_LINK_STATUS_SIZE], int r)
+{
+	return link_status[r - DP_LANE0_1_STATUS];
+}
+
+static u8 dp_get_lane_status(u8 link_status[DP_LINK_STATUS_SIZE],
+			     int lane)
+{
+	int i = DP_LANE0_1_STATUS + (lane >> 1);
+	int s = (lane & 1) * 4;
+	u8 l = dp_link_status(link_status, i);
+	return (l >> s) & 0xf;
+}
+
+bool drm_dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE],
+			  int lane_count)
+{
+	u8 lane_align;
+	u8 lane_status;
+	int lane;
+
+	lane_align = dp_link_status(link_status,
+				    DP_LANE_ALIGN_STATUS_UPDATED);
+	if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
+		return false;
+	for (lane = 0; lane < lane_count; lane++) {
+		lane_status = dp_get_lane_status(link_status, lane);
+		if ((lane_status & DP_CHANNEL_EQ_BITS) != DP_CHANNEL_EQ_BITS)
+			return false;
+	}
+	return true;
+}
+EXPORT_SYMBOL(drm_dp_channel_eq_ok);
+
+bool drm_dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE],
+			      int lane_count)
+{
+	int lane;
+	u8 lane_status;
+
+	for (lane = 0; lane < lane_count; lane++) {
+		lane_status = dp_get_lane_status(link_status, lane);
+		if ((lane_status & DP_LANE_CR_DONE) == 0)
+			return false;
+	}
+	return true;
+}
+EXPORT_SYMBOL(drm_dp_clock_recovery_ok);
+
+u8 drm_dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE],
+				     int lane)
+{
+	int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
+	int s = ((lane & 1) ?
+		 DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
+		 DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
+	u8 l = dp_link_status(link_status, i);
+
+	return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
+}
+EXPORT_SYMBOL(drm_dp_get_adjust_request_voltage);
+
+u8 drm_dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE],
+					  int lane)
+{
+	int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
+	int s = ((lane & 1) ?
+		 DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
+		 DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
+	u8 l = dp_link_status(link_status, i);
+
+	return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
+}
+EXPORT_SYMBOL(drm_dp_get_adjust_request_pre_emphasis);
+
+void drm_dp_link_train_clock_recovery_delay(u8 dpcd[DP_RECEIVER_CAP_SIZE]) {
+	if (dpcd[DP_TRAINING_AUX_RD_INTERVAL] == 0)
+		udelay(100);
+	else
+		mdelay(dpcd[DP_TRAINING_AUX_RD_INTERVAL] * 4);
+}
+EXPORT_SYMBOL(drm_dp_link_train_clock_recovery_delay);
+
+void drm_dp_link_train_channel_eq_delay(u8 dpcd[DP_RECEIVER_CAP_SIZE]) {
+	if (dpcd[DP_TRAINING_AUX_RD_INTERVAL] == 0)
+		udelay(400);
+	else
+		mdelay(dpcd[DP_TRAINING_AUX_RD_INTERVAL] * 4);
+}
+EXPORT_SYMBOL(drm_dp_link_train_channel_eq_delay);
+
+u8 drm_dp_link_rate_to_bw_code(int link_rate)
+{
+	switch (link_rate) {
+	case 162000:
+	default:
+		return DP_LINK_BW_1_62;
+	case 270000:
+		return DP_LINK_BW_2_7;
+	case 540000:
+		return DP_LINK_BW_5_4;
+	}
+}
+EXPORT_SYMBOL(drm_dp_link_rate_to_bw_code);
+
+int drm_dp_bw_code_to_link_rate(u8 link_bw)
+{
+	switch (link_bw) {
+	case DP_LINK_BW_1_62:
+	default:
+		return 162000;
+	case DP_LINK_BW_2_7:
+		return 270000;
+	case DP_LINK_BW_5_4:
+		return 540000;
+	}
+}
+EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate);
diff --git a/drivers/gpu/drm/drm_dp_i2c_helper.c b/drivers/gpu/drm/drm_dp_i2c_helper.c
deleted file mode 100644
index 7f246f2..0000000
--- a/drivers/gpu/drm/drm_dp_i2c_helper.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright © 2009 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission.  The copyright holders make no representations
- * about the suitability of this software for any purpose.  It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/i2c.h>
-#include <drm/drm_dp_helper.h>
-#include <drm/drmP.h>
-
-/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
-static int
-i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
-			    uint8_t write_byte, uint8_t *read_byte)
-{
-	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
-	int ret;
-	
-	ret = (*algo_data->aux_ch)(adapter, mode,
-				   write_byte, read_byte);
-	return ret;
-}
-
-/*
- * I2C over AUX CH
- */
-
-/*
- * Send the address. If the I2C link is running, this 'restarts'
- * the connection with the new address, this is used for doing
- * a write followed by a read (as needed for DDC)
- */
-static int
-i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
-{
-	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
-	int mode = MODE_I2C_START;
-	int ret;
-
-	if (reading)
-		mode |= MODE_I2C_READ;
-	else
-		mode |= MODE_I2C_WRITE;
-	algo_data->address = address;
-	algo_data->running = true;
-	ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
-	return ret;
-}
-
-/*
- * Stop the I2C transaction. This closes out the link, sending
- * a bare address packet with the MOT bit turned off
- */
-static void
-i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading)
-{
-	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
-	int mode = MODE_I2C_STOP;
-
-	if (reading)
-		mode |= MODE_I2C_READ;
-	else
-		mode |= MODE_I2C_WRITE;
-	if (algo_data->running) {
-		(void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
-		algo_data->running = false;
-	}
-}
-
-/*
- * Write a single byte to the current I2C address, the
- * the I2C link must be running or this returns -EIO
- */
-static int
-i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
-{
-	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
-	int ret;
-
-	if (!algo_data->running)
-		return -EIO;
-
-	ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
-	return ret;
-}
-
-/*
- * Read a single byte from the current I2C address, the
- * I2C link must be running or this returns -EIO
- */
-static int
-i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
-{
-	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
-	int ret;
-
-	if (!algo_data->running)
-		return -EIO;
-
-	ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
-	return ret;
-}
-
-static int
-i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter,
-		     struct i2c_msg *msgs,
-		     int num)
-{
-	int ret = 0;
-	bool reading = false;
-	int m;
-	int b;
-
-	for (m = 0; m < num; m++) {
-		u16 len = msgs[m].len;
-		u8 *buf = msgs[m].buf;
-		reading = (msgs[m].flags & I2C_M_RD) != 0;
-		ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading);
-		if (ret < 0)
-			break;
-		if (reading) {
-			for (b = 0; b < len; b++) {
-				ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]);
-				if (ret < 0)
-					break;
-			}
-		} else {
-			for (b = 0; b < len; b++) {
-				ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]);
-				if (ret < 0)
-					break;
-			}
-		}
-		if (ret < 0)
-			break;
-	}
-	if (ret >= 0)
-		ret = num;
-	i2c_algo_dp_aux_stop(adapter, reading);
-	DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret);
-	return ret;
-}
-
-static u32
-i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
-	       I2C_FUNC_SMBUS_READ_BLOCK_DATA |
-	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
-	       I2C_FUNC_10BIT_ADDR;
-}
-
-static const struct i2c_algorithm i2c_dp_aux_algo = {
-	.master_xfer	= i2c_algo_dp_aux_xfer,
-	.functionality	= i2c_algo_dp_aux_functionality,
-};
-
-static void
-i2c_dp_aux_reset_bus(struct i2c_adapter *adapter)
-{
-	(void) i2c_algo_dp_aux_address(adapter, 0, false);
-	(void) i2c_algo_dp_aux_stop(adapter, false);
-					   
-}
-
-static int
-i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter)
-{
-	adapter->algo = &i2c_dp_aux_algo;
-	adapter->retries = 3;
-	i2c_dp_aux_reset_bus(adapter);
-	return 0;
-}
-
-int
-i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
-{
-	int error;
-	
-	error = i2c_dp_aux_prepare_bus(adapter);
-	if (error)
-		return error;
-	error = i2c_add_adapter(adapter);
-	return error;
-}
-EXPORT_SYMBOL(i2c_dp_aux_add_bus);
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index fadcd44..484c36a 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -307,12 +307,9 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
 
 static bool drm_edid_is_zero(u8 *in_edid, int length)
 {
-	int i;
-	u32 *raw_edid = (u32 *)in_edid;
+	if (memchr_inv(in_edid, 0, length))
+		return false;
 
-	for (i = 0; i < length / 4; i++)
-		if (*(raw_edid + i) != 0)
-			return false;
 	return true;
 }
 
@@ -1516,6 +1513,26 @@ u8 *drm_find_cea_extension(struct edid *edid)
 }
 EXPORT_SYMBOL(drm_find_cea_extension);
 
+/*
+ * Looks for a CEA mode matching given drm_display_mode.
+ * Returns its CEA Video ID code, or 0 if not found.
+ */
+u8 drm_match_cea_mode(struct drm_display_mode *to_match)
+{
+	struct drm_display_mode *cea_mode;
+	u8 mode;
+
+	for (mode = 0; mode < drm_num_cea_modes; mode++) {
+		cea_mode = (struct drm_display_mode *)&edid_cea_modes[mode];
+
+		if (drm_mode_equal(to_match, cea_mode))
+			return mode + 1;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(drm_match_cea_mode);
+
+
 static int
 do_cea_modes (struct drm_connector *connector, u8 *db, u8 len)
 {
@@ -1622,7 +1639,7 @@ parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db)
 	if (len >= 12)
 		connector->audio_latency[1] = db[12];
 
-	DRM_LOG_KMS("HDMI: DVI dual %d, "
+	DRM_DEBUG_KMS("HDMI: DVI dual %d, "
 		    "max TMDS clock %d, "
 		    "latency present %d %d, "
 		    "video latency %d %d, "
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 4d58d7e..05e623a 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -27,6 +27,8 @@
  *      Dave Airlie <airlied@linux.ie>
  *      Jesse Barnes <jesse.barnes@intel.com>
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/sysrq.h>
 #include <linux/slab.h>
@@ -43,6 +45,15 @@ MODULE_LICENSE("GPL and additional rights");
 
 static LIST_HEAD(kernel_fb_helper_list);
 
+/**
+ * DOC: fbdev helpers
+ *
+ * The fb helper functions are useful to provide an fbdev on top of a drm kernel
+ * mode setting driver. They can be used mostly independantely from the crtc
+ * helper functions used by many drivers to implement the kernel mode setting
+ * interfaces.
+ */
+
 /* simple single crtc case helper function */
 int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
 {
@@ -95,10 +106,16 @@ static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
 			if (mode->force) {
 				const char *s;
 				switch (mode->force) {
-				case DRM_FORCE_OFF: s = "OFF"; break;
-				case DRM_FORCE_ON_DIGITAL: s = "ON - dig"; break;
+				case DRM_FORCE_OFF:
+					s = "OFF";
+					break;
+				case DRM_FORCE_ON_DIGITAL:
+					s = "ON - dig";
+					break;
 				default:
-				case DRM_FORCE_ON: s = "ON"; break;
+				case DRM_FORCE_ON:
+					s = "ON";
+					break;
 				}
 
 				DRM_INFO("forcing %s connector %s\n",
@@ -265,7 +282,7 @@ int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed,
 	if (panic_timeout < 0)
 		return 0;
 
-	printk(KERN_ERR "panic occurred, switching back to text console\n");
+	pr_err("panic occurred, switching back to text console\n");
 	return drm_fb_helper_force_kernel_mode();
 }
 EXPORT_SYMBOL(drm_fb_helper_panic);
@@ -433,7 +450,7 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
 	if (!list_empty(&fb_helper->kernel_fb_list)) {
 		list_del(&fb_helper->kernel_fb_list);
 		if (list_empty(&kernel_fb_helper_list)) {
-			printk(KERN_INFO "drm: unregistered panic notifier\n");
+			pr_info("drm: unregistered panic notifier\n");
 			atomic_notifier_chain_unregister(&panic_notifier_list,
 							 &paniced);
 			unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
@@ -724,9 +741,9 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
 
 	/* if driver picks 8 or 16 by default use that
 	   for both depth/bpp */
-	if (preferred_bpp != sizes.surface_bpp) {
+	if (preferred_bpp != sizes.surface_bpp)
 		sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
-	}
+
 	/* first up get a count of crtcs now in use and new min/maxes width/heights */
 	for (i = 0; i < fb_helper->connector_count; i++) {
 		struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
@@ -794,18 +811,16 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
 	info = fb_helper->fbdev;
 
 	/* set the fb pointer */
-	for (i = 0; i < fb_helper->crtc_count; i++) {
+	for (i = 0; i < fb_helper->crtc_count; i++)
 		fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
-	}
 
 	if (new_fb) {
 		info->var.pixclock = 0;
-		if (register_framebuffer(info) < 0) {
+		if (register_framebuffer(info) < 0)
 			return -EINVAL;
-		}
 
-		printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
-		       info->fix.id);
+		dev_info(fb_helper->dev->dev, "fb%d: %s frame buffer device\n",
+				info->node, info->fix.id);
 
 	} else {
 		drm_fb_helper_set_par(info);
@@ -814,7 +829,7 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
 	/* Switch back to kernel console on panic */
 	/* multi card linked list maybe */
 	if (list_empty(&kernel_fb_helper_list)) {
-		printk(KERN_INFO "drm: registered panic notifier\n");
+		dev_info(fb_helper->dev->dev, "registered panic notifier\n");
 		atomic_notifier_chain_register(&panic_notifier_list,
 					       &paniced);
 		register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
@@ -1002,11 +1017,11 @@ static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
 {
 	bool enable;
 
-	if (strict) {
+	if (strict)
 		enable = connector->status == connector_status_connected;
-	} else {
+	else
 		enable = connector->status != connector_status_disconnected;
-	}
+
 	return enable;
 }
 
@@ -1191,9 +1206,8 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
 	for (c = 0; c < fb_helper->crtc_count; c++) {
 		crtc = &fb_helper->crtc_info[c];
 
-		if ((encoder->possible_crtcs & (1 << c)) == 0) {
+		if ((encoder->possible_crtcs & (1 << c)) == 0)
 			continue;
-		}
 
 		for (o = 0; o < n; o++)
 			if (best_crtcs[o] == crtc)
@@ -1246,6 +1260,11 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
 			sizeof(struct drm_display_mode *), GFP_KERNEL);
 	enabled = kcalloc(dev->mode_config.num_connector,
 			  sizeof(bool), GFP_KERNEL);
+	if (!crtcs || !modes || !enabled) {
+		DRM_ERROR("Memory allocation failed\n");
+		goto out;
+	}
+
 
 	drm_enable_connectors(fb_helper, enabled);
 
@@ -1284,6 +1303,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
 		}
 	}
 
+out:
 	kfree(crtcs);
 	kfree(modes);
 	kfree(enabled);
@@ -1291,12 +1311,14 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
 
 /**
  * drm_helper_initial_config - setup a sane initial connector configuration
- * @dev: DRM device
+ * @fb_helper: fb_helper device struct
+ * @bpp_sel: bpp value to use for the framebuffer configuration
  *
  * LOCKING:
- * Called at init time, must take mode config lock.
+ * Called at init time by the driver to set up the @fb_helper initial
+ * configuration, must take the mode config lock.
  *
- * Scan the CRTCs and connectors and try to put together an initial setup.
+ * Scans the CRTCs and connectors and tries to put together an initial setup.
  * At the moment, this is a cloned configuration across all heads with
  * a new framebuffer object as the backing store.
  *
@@ -1319,9 +1341,9 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
 	/*
 	 * we shouldn't end up with no modes here.
 	 */
-	if (count == 0) {
-		printk(KERN_INFO "No connectors reported connected with modes\n");
-	}
+	if (count == 0)
+		dev_info(fb_helper->dev->dev, "No connectors reported connected with modes\n");
+
 	drm_setup_crtcs(fb_helper);
 
 	return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
@@ -1330,7 +1352,7 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config);
 
 /**
  * drm_fb_helper_hotplug_event - respond to a hotplug notification by
- *                               probing all the outputs attached to the fb.
+ *                               probing all the outputs attached to the fb
  * @fb_helper: the drm_fb_helper
  *
  * LOCKING:
diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c
index c3745c4..8025454 100644
--- a/drivers/gpu/drm/drm_hashtab.c
+++ b/drivers/gpu/drm/drm_hashtab.c
@@ -67,10 +67,8 @@ void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key)
 	hashed_key = hash_long(key, ht->order);
 	DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
 	h_list = &ht->table[hashed_key];
-	hlist_for_each(list, h_list) {
-		entry = hlist_entry(list, struct drm_hash_item, head);
+	hlist_for_each_entry(entry, list, h_list, head)
 		DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
-	}
 }
 
 static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht,
@@ -83,8 +81,7 @@ static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht,
 
 	hashed_key = hash_long(key, ht->order);
 	h_list = &ht->table[hashed_key];
-	hlist_for_each(list, h_list) {
-		entry = hlist_entry(list, struct drm_hash_item, head);
+	hlist_for_each_entry(entry, list, h_list, head) {
 		if (entry->key == key)
 			return list;
 		if (entry->key > key)
@@ -93,6 +90,24 @@ static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht,
 	return NULL;
 }
 
+static struct hlist_node *drm_ht_find_key_rcu(struct drm_open_hash *ht,
+					      unsigned long key)
+{
+	struct drm_hash_item *entry;
+	struct hlist_head *h_list;
+	struct hlist_node *list;
+	unsigned int hashed_key;
+
+	hashed_key = hash_long(key, ht->order);
+	h_list = &ht->table[hashed_key];
+	hlist_for_each_entry_rcu(entry, list, h_list, head) {
+		if (entry->key == key)
+			return list;
+		if (entry->key > key)
+			break;
+	}
+	return NULL;
+}
 
 int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
 {
@@ -105,8 +120,7 @@ int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
 	hashed_key = hash_long(key, ht->order);
 	h_list = &ht->table[hashed_key];
 	parent = NULL;
-	hlist_for_each(list, h_list) {
-		entry = hlist_entry(list, struct drm_hash_item, head);
+	hlist_for_each_entry(entry, list, h_list, head) {
 		if (entry->key == key)
 			return -EINVAL;
 		if (entry->key > key)
@@ -114,9 +128,9 @@ int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
 		parent = list;
 	}
 	if (parent) {
-		hlist_add_after(parent, &item->head);
+		hlist_add_after_rcu(parent, &item->head);
 	} else {
-		hlist_add_head(&item->head, h_list);
+		hlist_add_head_rcu(&item->head, h_list);
 	}
 	return 0;
 }
@@ -156,7 +170,7 @@ int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
 {
 	struct hlist_node *list;
 
-	list = drm_ht_find_key(ht, key);
+	list = drm_ht_find_key_rcu(ht, key);
 	if (!list)
 		return -EINVAL;
 
@@ -171,7 +185,7 @@ int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
 
 	list = drm_ht_find_key(ht, key);
 	if (list) {
-		hlist_del_init(list);
+		hlist_del_init_rcu(list);
 		return 0;
 	}
 	return -EINVAL;
@@ -179,7 +193,7 @@ int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
 
 int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item)
 {
-	hlist_del_init(&item->head);
+	hlist_del_init_rcu(&item->head);
 	return 0;
 }
 EXPORT_SYMBOL(drm_ht_remove_item);
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 23dd975..e77bd8b 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -287,6 +287,9 @@ int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
 		req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0;
 		req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0;
 		break;
+	case DRM_CAP_TIMESTAMP_MONOTONIC:
+		req->value = drm_timestamp_monotonic;
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 3a3d0ce..2ba9d7f 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -106,6 +106,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
 	s64 diff_ns;
 	int vblrc;
 	struct timeval tvblank;
+	int count = DRM_TIMESTAMP_MAXRETRIES;
 
 	/* Prevent vblank irq processing while disabling vblank irqs,
 	 * so no updates of timestamps or count can happen after we've
@@ -131,7 +132,10 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
 	do {
 		dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc);
 		vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0);
-	} while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc));
+	} while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc);
+
+	if (!count)
+		vblrc = 0;
 
 	/* Compute time difference to stored timestamp of last vblank
 	 * as updated by last invocation of drm_handle_vblank() in vblank irq.
@@ -576,7 +580,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
 					  unsigned flags,
 					  struct drm_crtc *refcrtc)
 {
-	struct timeval stime, raw_time;
+	ktime_t stime, etime, mono_time_offset;
+	struct timeval tv_etime;
 	struct drm_display_mode *mode;
 	int vbl_status, vtotal, vdisplay;
 	int vpos, hpos, i;
@@ -625,13 +630,15 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
 		preempt_disable();
 
 		/* Get system timestamp before query. */
-		do_gettimeofday(&stime);
+		stime = ktime_get();
 
 		/* Get vertical and horizontal scanout pos. vpos, hpos. */
 		vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos, &hpos);
 
 		/* Get system timestamp after query. */
-		do_gettimeofday(&raw_time);
+		etime = ktime_get();
+		if (!drm_timestamp_monotonic)
+			mono_time_offset = ktime_get_monotonic_offset();
 
 		preempt_enable();
 
@@ -642,7 +649,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
 			return -EIO;
 		}
 
-		duration_ns = timeval_to_ns(&raw_time) - timeval_to_ns(&stime);
+		duration_ns = ktime_to_ns(etime) - ktime_to_ns(stime);
 
 		/* Accept result with <  max_error nsecs timing uncertainty. */
 		if (duration_ns <= (s64) *max_error)
@@ -689,14 +696,20 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
 		vbl_status |= 0x8;
 	}
 
+	if (!drm_timestamp_monotonic)
+		etime = ktime_sub(etime, mono_time_offset);
+
+	/* save this only for debugging purposes */
+	tv_etime = ktime_to_timeval(etime);
 	/* Subtract time delta from raw timestamp to get final
 	 * vblank_time timestamp for end of vblank.
 	 */
-	*vblank_time = ns_to_timeval(timeval_to_ns(&raw_time) - delta_ns);
+	etime = ktime_sub_ns(etime, delta_ns);
+	*vblank_time = ktime_to_timeval(etime);
 
 	DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
 		  crtc, (int)vbl_status, hpos, vpos,
-		  (long)raw_time.tv_sec, (long)raw_time.tv_usec,
+		  (long)tv_etime.tv_sec, (long)tv_etime.tv_usec,
 		  (long)vblank_time->tv_sec, (long)vblank_time->tv_usec,
 		  (int)duration_ns/1000, i);
 
@@ -708,6 +721,17 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
 }
 EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos);
 
+static struct timeval get_drm_timestamp(void)
+{
+	ktime_t now;
+
+	now = ktime_get();
+	if (!drm_timestamp_monotonic)
+		now = ktime_sub(now, ktime_get_monotonic_offset());
+
+	return ktime_to_timeval(now);
+}
+
 /**
  * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent
  * vblank interval.
@@ -745,9 +769,9 @@ u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
 	}
 
 	/* GPU high precision timestamp query unsupported or failed.
-	 * Return gettimeofday timestamp as best estimate.
+	 * Return current monotonic/gettimeofday timestamp as best estimate.
 	 */
-	do_gettimeofday(tvblank);
+	*tvblank = get_drm_timestamp();
 
 	return 0;
 }
@@ -802,6 +826,47 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
 }
 EXPORT_SYMBOL(drm_vblank_count_and_time);
 
+static void send_vblank_event(struct drm_device *dev,
+		struct drm_pending_vblank_event *e,
+		unsigned long seq, struct timeval *now)
+{
+	WARN_ON_SMP(!spin_is_locked(&dev->event_lock));
+	e->event.sequence = seq;
+	e->event.tv_sec = now->tv_sec;
+	e->event.tv_usec = now->tv_usec;
+
+	list_add_tail(&e->base.link,
+		      &e->base.file_priv->event_list);
+	wake_up_interruptible(&e->base.file_priv->event_wait);
+	trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
+					 e->event.sequence);
+}
+
+/**
+ * drm_send_vblank_event - helper to send vblank event after pageflip
+ * @dev: DRM device
+ * @crtc: CRTC in question
+ * @e: the event to send
+ *
+ * Updates sequence # and timestamp on event, and sends it to userspace.
+ * Caller must hold event lock.
+ */
+void drm_send_vblank_event(struct drm_device *dev, int crtc,
+		struct drm_pending_vblank_event *e)
+{
+	struct timeval now;
+	unsigned int seq;
+	if (crtc >= 0) {
+		seq = drm_vblank_count_and_time(dev, crtc, &now);
+	} else {
+		seq = 0;
+
+		now = get_drm_timestamp();
+	}
+	send_vblank_event(dev, e, seq, &now);
+}
+EXPORT_SYMBOL(drm_send_vblank_event);
+
 /**
  * drm_update_vblank_count - update the master vblank counter
  * @dev: DRM device
@@ -936,6 +1001,13 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
 }
 EXPORT_SYMBOL(drm_vblank_put);
 
+/**
+ * drm_vblank_off - disable vblank events on a CRTC
+ * @dev: DRM device
+ * @crtc: CRTC in question
+ *
+ * Caller must hold event lock.
+ */
 void drm_vblank_off(struct drm_device *dev, int crtc)
 {
 	struct drm_pending_vblank_event *e, *t;
@@ -955,15 +1027,9 @@ void drm_vblank_off(struct drm_device *dev, int crtc)
 		DRM_DEBUG("Sending premature vblank event on disable: \
 			  wanted %d, current %d\n",
 			  e->event.sequence, seq);
-
-		e->event.sequence = seq;
-		e->event.tv_sec = now.tv_sec;
-		e->event.tv_usec = now.tv_usec;
+		list_del(&e->base.link);
 		drm_vblank_put(dev, e->pipe);
-		list_move_tail(&e->base.link, &e->base.file_priv->event_list);
-		wake_up_interruptible(&e->base.file_priv->event_wait);
-		trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
-						 e->event.sequence);
+		send_vblank_event(dev, e, seq, &now);
 	}
 
 	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
@@ -1107,15 +1173,9 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
 
 	e->event.sequence = vblwait->request.sequence;
 	if ((seq - vblwait->request.sequence) <= (1 << 23)) {
-		e->event.sequence = seq;
-		e->event.tv_sec = now.tv_sec;
-		e->event.tv_usec = now.tv_usec;
 		drm_vblank_put(dev, pipe);
-		list_add_tail(&e->base.link, &e->base.file_priv->event_list);
-		wake_up_interruptible(&e->base.file_priv->event_wait);
+		send_vblank_event(dev, e, seq, &now);
 		vblwait->reply.sequence = seq;
-		trace_drm_vblank_event_delivered(current->pid, pipe,
-						 vblwait->request.sequence);
 	} else {
 		/* drm_handle_vblank_events will call drm_vblank_put */
 		list_add_tail(&e->base.link, &dev->vblank_event_list);
@@ -1256,14 +1316,9 @@ static void drm_handle_vblank_events(struct drm_device *dev, int crtc)
 		DRM_DEBUG("vblank event on %d, current %d\n",
 			  e->event.sequence, seq);
 
-		e->event.sequence = seq;
-		e->event.tv_sec = now.tv_sec;
-		e->event.tv_usec = now.tv_usec;
+		list_del(&e->base.link);
 		drm_vblank_put(dev, e->pipe);
-		list_move_tail(&e->base.link, &e->base.file_priv->event_list);
-		wake_up_interruptible(&e->base.file_priv->event_wait);
-		trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
-						 e->event.sequence);
+		send_vblank_event(dev, e, seq, &now);
 	}
 
 	spin_unlock_irqrestore(&dev->event_lock, flags);
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 59450f3..d8da30e 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -46,7 +46,7 @@
  *
  * Describe @mode using DRM_DEBUG.
  */
-void drm_mode_debug_printmodeline(struct drm_display_mode *mode)
+void drm_mode_debug_printmodeline(const struct drm_display_mode *mode)
 {
 	DRM_DEBUG_KMS("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d "
 			"0x%x 0x%x\n",
@@ -558,7 +558,7 @@ EXPORT_SYMBOL(drm_mode_list_concat);
  * RETURNS:
  * @mode->hdisplay
  */
-int drm_mode_width(struct drm_display_mode *mode)
+int drm_mode_width(const struct drm_display_mode *mode)
 {
 	return mode->hdisplay;
 
@@ -579,7 +579,7 @@ EXPORT_SYMBOL(drm_mode_width);
  * RETURNS:
  * @mode->vdisplay
  */
-int drm_mode_height(struct drm_display_mode *mode)
+int drm_mode_height(const struct drm_display_mode *mode)
 {
 	return mode->vdisplay;
 }
@@ -768,7 +768,7 @@ EXPORT_SYMBOL(drm_mode_duplicate);
  * RETURNS:
  * True if the modes are equal, false otherwise.
  */
-bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2)
+bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2)
 {
 	/* do clock check convert to PICOS so fb modes get matched
 	 * the same */
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index c236fd2..200e104 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -46,16 +46,24 @@ EXPORT_SYMBOL(drm_vblank_offdelay);
 unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
 EXPORT_SYMBOL(drm_timestamp_precision);
 
+/*
+ * Default to use monotonic timestamps for wait-for-vblank and page-flip
+ * complete events.
+ */
+unsigned int drm_timestamp_monotonic = 1;
+
 MODULE_AUTHOR(CORE_AUTHOR);
 MODULE_DESCRIPTION(CORE_DESC);
 MODULE_LICENSE("GPL and additional rights");
 MODULE_PARM_DESC(debug, "Enable debug output");
 MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
 MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
+MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
 
 module_param_named(debug, drm_debug, int, 0600);
 module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
 module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
+module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
 
 struct idr drm_minors_idr;
 
@@ -221,20 +229,20 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
 	if (!file_priv->master)
 		return -EINVAL;
 
-	if (!file_priv->minor->master &&
-	    file_priv->minor->master != file_priv->master) {
-		mutex_lock(&dev->struct_mutex);
-		file_priv->minor->master = drm_master_get(file_priv->master);
-		file_priv->is_master = 1;
-		if (dev->driver->master_set) {
-			ret = dev->driver->master_set(dev, file_priv, false);
-			if (unlikely(ret != 0)) {
-				file_priv->is_master = 0;
-				drm_master_put(&file_priv->minor->master);
-			}
+	if (file_priv->minor->master)
+		return -EINVAL;
+
+	mutex_lock(&dev->struct_mutex);
+	file_priv->minor->master = drm_master_get(file_priv->master);
+	file_priv->is_master = 1;
+	if (dev->driver->master_set) {
+		ret = dev->driver->master_set(dev, file_priv, false);
+		if (unlikely(ret != 0)) {
+			file_priv->is_master = 0;
+			drm_master_put(&file_priv->minor->master);
 		}
-		mutex_unlock(&dev->struct_mutex);
 	}
+	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
 }
@@ -492,10 +500,7 @@ void drm_put_dev(struct drm_device *dev)
 	drm_put_minor(&dev->primary);
 
 	list_del(&dev->driver_item);
-	if (dev->devname) {
-		kfree(dev->devname);
-		dev->devname = NULL;
-	}
+	kfree(dev->devname);
 	kfree(dev);
 }
 EXPORT_SYMBOL(drm_put_dev);
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
index 32dba2a..637dd84 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
@@ -506,7 +506,7 @@ void mdfld_dsi_output_init(struct drm_device *dev,
 
 	dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe);
 
-	if (!dev || ((pipe != 0) && (pipe != 2))) {
+	if (pipe != 0 && pipe != 2) {
 		DRM_ERROR("Invalid parameter\n");
 		return;
 	}
diff --git a/drivers/gpu/drm/gma500/oaktrail.h b/drivers/gpu/drm/gma500/oaktrail.h
index f2f9f38..30adbbe 100644
--- a/drivers/gpu/drm/gma500/oaktrail.h
+++ b/drivers/gpu/drm/gma500/oaktrail.h
@@ -249,3 +249,9 @@ extern void oaktrail_hdmi_i2c_exit(struct pci_dev *dev);
 extern void oaktrail_hdmi_save(struct drm_device *dev);
 extern void oaktrail_hdmi_restore(struct drm_device *dev);
 extern void oaktrail_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev);
+extern int oaktrail_crtc_hdmi_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
+						struct drm_display_mode *adjusted_mode, int x, int y,
+						struct drm_framebuffer *old_fb);
+extern void oaktrail_crtc_hdmi_dpms(struct drm_crtc *crtc, int mode);
+
+
diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c
index cdafd2a..4ec2962 100644
--- a/drivers/gpu/drm/gma500/oaktrail_crtc.c
+++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c
@@ -168,6 +168,11 @@ static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode)
 	const struct psb_offset *map = &dev_priv->regmap[pipe];
 	u32 temp;
 
+	if (pipe == 1) {
+		oaktrail_crtc_hdmi_dpms(crtc, mode);
+		return;
+	}
+
 	if (!gma_power_begin(dev, true))
 		return;
 
@@ -302,6 +307,9 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc,
 	uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
 	struct drm_connector *connector;
 
+	if (pipe == 1)
+		return oaktrail_crtc_hdmi_mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
+
 	if (!gma_power_begin(dev, true))
 		return 0;
 
diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c
index 010b8207..08747fd 100644
--- a/drivers/gpu/drm/gma500/oaktrail_device.c
+++ b/drivers/gpu/drm/gma500/oaktrail_device.c
@@ -544,7 +544,7 @@ const struct psb_ops oaktrail_chip_ops = {
 	.accel_2d = 1,
 	.pipes = 2,
 	.crtcs = 2,
-	.hdmi_mask = (1 << 0),
+	.hdmi_mask = (1 << 1),
 	.lvds_mask = (1 << 0),
 	.cursor_needs_phys = 0,
 	.sgx_offset = MRST_SGX_OFFSET,
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
index 69e51e9..f036f1f 100644
--- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c
+++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
@@ -155,6 +155,345 @@ static void oaktrail_hdmi_audio_disable(struct drm_device *dev)
 	HDMI_READ(HDMI_HCR);
 }
 
+static void wait_for_vblank(struct drm_device *dev)
+{
+	/* Wait for 20ms, i.e. one cycle at 50hz. */
+	mdelay(20);
+}
+
+static unsigned int htotal_calculate(struct drm_display_mode *mode)
+{
+	u32 htotal, new_crtc_htotal;
+
+	htotal = (mode->crtc_hdisplay - 1) | ((mode->crtc_htotal - 1) << 16);
+
+	/*
+	 * 1024 x 768  new_crtc_htotal = 0x1024;
+	 * 1280 x 1024 new_crtc_htotal = 0x0c34;
+	 */
+	new_crtc_htotal = (mode->crtc_htotal - 1) * 200 * 1000 / mode->clock;
+
+	DRM_DEBUG_KMS("new crtc htotal 0x%4x\n", new_crtc_htotal);
+	return (mode->crtc_hdisplay - 1) | (new_crtc_htotal << 16);
+}
+
+static void oaktrail_hdmi_find_dpll(struct drm_crtc *crtc, int target,
+				int refclk, struct oaktrail_hdmi_clock *best_clock)
+{
+	int np_min, np_max, nr_min, nr_max;
+	int np, nr, nf;
+
+	np_min = DIV_ROUND_UP(oaktrail_hdmi_limit.vco.min, target * 10);
+	np_max = oaktrail_hdmi_limit.vco.max / (target * 10);
+	if (np_min < oaktrail_hdmi_limit.np.min)
+		np_min = oaktrail_hdmi_limit.np.min;
+	if (np_max > oaktrail_hdmi_limit.np.max)
+		np_max = oaktrail_hdmi_limit.np.max;
+
+	nr_min = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_max));
+	nr_max = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_min));
+	if (nr_min < oaktrail_hdmi_limit.nr.min)
+		nr_min = oaktrail_hdmi_limit.nr.min;
+	if (nr_max > oaktrail_hdmi_limit.nr.max)
+		nr_max = oaktrail_hdmi_limit.nr.max;
+
+	np = DIV_ROUND_UP((refclk * 1000), (target * 10 * nr_max));
+	nr = DIV_ROUND_UP((refclk * 1000), (target * 10 * np));
+	nf = DIV_ROUND_CLOSEST((target * 10 * np * nr), refclk);
+	DRM_DEBUG_KMS("np, nr, nf %d %d %d\n", np, nr, nf);
+
+	/*
+	 * 1024 x 768  np = 1; nr = 0x26; nf = 0x0fd8000;
+	 * 1280 x 1024 np = 1; nr = 0x17; nf = 0x1034000;
+	 */
+	best_clock->np = np;
+	best_clock->nr = nr - 1;
+	best_clock->nf = (nf << 14);
+}
+
+static void scu_busy_loop(void __iomem *scu_base)
+{
+	u32 status = 0;
+	u32 loop_count = 0;
+
+	status = readl(scu_base + 0x04);
+	while (status & 1) {
+		udelay(1); /* scu processing time is in few u secods */
+		status = readl(scu_base + 0x04);
+		loop_count++;
+		/* break if scu doesn't reset busy bit after huge retry */
+		if (loop_count > 1000) {
+			DRM_DEBUG_KMS("SCU IPC timed out");
+			return;
+		}
+	}
+}
+
+/*
+ *	You don't want to know, you really really don't want to know....
+ *
+ *	This is magic. However it's safe magic because of the way the platform
+ *	works and it is necessary magic.
+ */
+static void oaktrail_hdmi_reset(struct drm_device *dev)
+{
+	void __iomem *base;
+	unsigned long scu_ipc_mmio = 0xff11c000UL;
+	int scu_len = 1024;
+
+	base = ioremap((resource_size_t)scu_ipc_mmio, scu_len);
+	if (base == NULL) {
+		DRM_ERROR("failed to map scu mmio\n");
+		return;
+	}
+
+	/* scu ipc: assert hdmi controller reset */
+	writel(0xff11d118, base + 0x0c);
+	writel(0x7fffffdf, base + 0x80);
+	writel(0x42005, base + 0x0);
+	scu_busy_loop(base);
+
+	/* scu ipc: de-assert hdmi controller reset */
+	writel(0xff11d118, base + 0x0c);
+	writel(0x7fffffff, base + 0x80);
+	writel(0x42005, base + 0x0);
+	scu_busy_loop(base);
+
+	iounmap(base);
+}
+
+int oaktrail_crtc_hdmi_mode_set(struct drm_crtc *crtc,
+			    struct drm_display_mode *mode,
+			    struct drm_display_mode *adjusted_mode,
+			    int x, int y,
+			    struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+	int pipe = 1;
+	int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
+	int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
+	int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
+	int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
+	int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
+	int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
+	int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
+	int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
+	int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
+	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+	int refclk;
+	struct oaktrail_hdmi_clock clock;
+	u32 dspcntr, pipeconf, dpll, temp;
+	int dspcntr_reg = DSPBCNTR;
+
+	if (!gma_power_begin(dev, true))
+		return 0;
+
+	/* Disable the VGA plane that we never use */
+	REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+
+	/* Disable dpll if necessary */
+	dpll = REG_READ(DPLL_CTRL);
+	if ((dpll & DPLL_PWRDN) == 0) {
+		REG_WRITE(DPLL_CTRL, dpll | (DPLL_PWRDN | DPLL_RESET));
+		REG_WRITE(DPLL_DIV_CTRL, 0x00000000);
+		REG_WRITE(DPLL_STATUS, 0x1);
+	}
+	udelay(150);
+
+	/* Reset controller */
+	oaktrail_hdmi_reset(dev);
+
+	/* program and enable dpll */
+	refclk = 25000;
+	oaktrail_hdmi_find_dpll(crtc, adjusted_mode->clock, refclk, &clock);
+
+	/* Set the DPLL */
+	dpll = REG_READ(DPLL_CTRL);
+	dpll &= ~DPLL_PDIV_MASK;
+	dpll &= ~(DPLL_PWRDN | DPLL_RESET);
+	REG_WRITE(DPLL_CTRL, 0x00000008);
+	REG_WRITE(DPLL_DIV_CTRL, ((clock.nf << 6) | clock.nr));
+	REG_WRITE(DPLL_ADJUST, ((clock.nf >> 14) - 1));
+	REG_WRITE(DPLL_CTRL, (dpll | (clock.np << DPLL_PDIV_SHIFT) | DPLL_ENSTAT | DPLL_DITHEN));
+	REG_WRITE(DPLL_UPDATE, 0x80000000);
+	REG_WRITE(DPLL_CLK_ENABLE, 0x80050102);
+	udelay(150);
+
+	/* configure HDMI */
+	HDMI_WRITE(0x1004, 0x1fd);
+	HDMI_WRITE(0x2000, 0x1);
+	HDMI_WRITE(0x2008, 0x0);
+	HDMI_WRITE(0x3130, 0x8);
+	HDMI_WRITE(0x101c, 0x1800810);
+
+	temp = htotal_calculate(adjusted_mode);
+	REG_WRITE(htot_reg, temp);
+	REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16));
+	REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16));
+	REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16));
+	REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16));
+	REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16));
+	REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) |  (mode->crtc_vdisplay - 1));
+
+	REG_WRITE(PCH_HTOTAL_B, (adjusted_mode->crtc_hdisplay - 1) | ((adjusted_mode->crtc_htotal - 1) << 16));
+	REG_WRITE(PCH_HBLANK_B, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16));
+	REG_WRITE(PCH_HSYNC_B, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16));
+	REG_WRITE(PCH_VTOTAL_B, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16));
+	REG_WRITE(PCH_VBLANK_B, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16));
+	REG_WRITE(PCH_VSYNC_B, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16));
+	REG_WRITE(PCH_PIPEBSRC, ((mode->crtc_hdisplay - 1) << 16) |  (mode->crtc_vdisplay - 1));
+
+	temp = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start;
+	HDMI_WRITE(HDMI_HBLANK_A, ((adjusted_mode->crtc_hdisplay - 1) << 16) |  temp);
+
+	REG_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
+	REG_WRITE(dsppos_reg, 0);
+
+	/* Flush the plane changes */
+	{
+		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+		crtc_funcs->mode_set_base(crtc, x, y, old_fb);
+	}
+
+	/* Set up the display plane register */
+	dspcntr = REG_READ(dspcntr_reg);
+	dspcntr |= DISPPLANE_GAMMA_ENABLE;
+	dspcntr |= DISPPLANE_SEL_PIPE_B;
+	dspcntr |= DISPLAY_PLANE_ENABLE;
+
+	/* setup pipeconf */
+	pipeconf = REG_READ(pipeconf_reg);
+	pipeconf |= PIPEACONF_ENABLE;
+
+	REG_WRITE(pipeconf_reg, pipeconf);
+	REG_READ(pipeconf_reg);
+
+	REG_WRITE(PCH_PIPEBCONF, pipeconf);
+	REG_READ(PCH_PIPEBCONF);
+	wait_for_vblank(dev);
+
+	REG_WRITE(dspcntr_reg, dspcntr);
+	wait_for_vblank(dev);
+
+	gma_power_end(dev);
+
+	return 0;
+}
+
+void oaktrail_crtc_hdmi_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct drm_device *dev = crtc->dev;
+	u32 temp;
+
+	DRM_DEBUG_KMS("%s %d\n", __func__, mode);
+
+	switch (mode) {
+	case DRM_MODE_DPMS_OFF:
+		REG_WRITE(VGACNTRL, 0x80000000);
+
+		/* Disable plane */
+		temp = REG_READ(DSPBCNTR);
+		if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+			REG_WRITE(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
+			REG_READ(DSPBCNTR);
+			/* Flush the plane changes */
+			REG_WRITE(DSPBSURF, REG_READ(DSPBSURF));
+			REG_READ(DSPBSURF);
+		}
+
+		/* Disable pipe B */
+		temp = REG_READ(PIPEBCONF);
+		if ((temp & PIPEACONF_ENABLE) != 0) {
+			REG_WRITE(PIPEBCONF, temp & ~PIPEACONF_ENABLE);
+			REG_READ(PIPEBCONF);
+		}
+
+		/* Disable LNW Pipes, etc */
+		temp = REG_READ(PCH_PIPEBCONF);
+		if ((temp & PIPEACONF_ENABLE) != 0) {
+			REG_WRITE(PCH_PIPEBCONF, temp & ~PIPEACONF_ENABLE);
+			REG_READ(PCH_PIPEBCONF);
+		}
+
+		/* wait for pipe off */
+		udelay(150);
+
+		/* Disable dpll */
+		temp = REG_READ(DPLL_CTRL);
+		if ((temp & DPLL_PWRDN) == 0) {
+			REG_WRITE(DPLL_CTRL, temp | (DPLL_PWRDN | DPLL_RESET));
+			REG_WRITE(DPLL_STATUS, 0x1);
+		}
+
+		/* wait for dpll off */
+		udelay(150);
+
+		break;
+	case DRM_MODE_DPMS_ON:
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+		/* Enable dpll */
+		temp = REG_READ(DPLL_CTRL);
+		if ((temp & DPLL_PWRDN) != 0) {
+			REG_WRITE(DPLL_CTRL, temp & ~(DPLL_PWRDN | DPLL_RESET));
+			temp = REG_READ(DPLL_CLK_ENABLE);
+			REG_WRITE(DPLL_CLK_ENABLE, temp | DPLL_EN_DISP | DPLL_SEL_HDMI | DPLL_EN_HDMI);
+			REG_READ(DPLL_CLK_ENABLE);
+		}
+		/* wait for dpll warm up */
+		udelay(150);
+
+		/* Enable pipe B */
+		temp = REG_READ(PIPEBCONF);
+		if ((temp & PIPEACONF_ENABLE) == 0) {
+			REG_WRITE(PIPEBCONF, temp | PIPEACONF_ENABLE);
+			REG_READ(PIPEBCONF);
+		}
+
+		/* Enable LNW Pipe B */
+		temp = REG_READ(PCH_PIPEBCONF);
+		if ((temp & PIPEACONF_ENABLE) == 0) {
+			REG_WRITE(PCH_PIPEBCONF, temp | PIPEACONF_ENABLE);
+			REG_READ(PCH_PIPEBCONF);
+		}
+
+		wait_for_vblank(dev);
+
+		/* Enable plane */
+		temp = REG_READ(DSPBCNTR);
+		if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
+			REG_WRITE(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE);
+			/* Flush the plane changes */
+			REG_WRITE(DSPBSURF, REG_READ(DSPBSURF));
+			REG_READ(DSPBSURF);
+		}
+
+		psb_intel_crtc_load_lut(crtc);
+	}
+
+	/* DSPARB */
+	REG_WRITE(DSPARB, 0x00003fbf);
+
+	/* FW1 */
+	REG_WRITE(0x70034, 0x3f880a0a);
+
+	/* FW2 */
+	REG_WRITE(0x70038, 0x0b060808);
+
+	/* FW4 */
+	REG_WRITE(0x70050, 0x08030404);
+
+	/* FW5 */
+	REG_WRITE(0x70054, 0x04040404);
+
+	/* LNC Chicken Bits - Squawk! */
+	REG_WRITE(0x70400, 0x4000);
+
+	return;
+}
+
 static void oaktrail_hdmi_dpms(struct drm_encoder *encoder, int mode)
 {
 	static int dpms_mode = -1;
@@ -233,13 +572,15 @@ static const unsigned char raw_edid[] = {
 
 static int oaktrail_hdmi_get_modes(struct drm_connector *connector)
 {
-	struct drm_device *dev = connector->dev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
 	struct i2c_adapter *i2c_adap;
 	struct edid *edid;
-	struct drm_display_mode *mode, *t;
-	int i = 0, ret = 0;
+	int ret = 0;
 
+	/*
+	 *	FIXME: We need to figure this lot out. In theory we can
+	 *	read the EDID somehow but I've yet to find working reference
+	 *	code.
+	 */
 	i2c_adap = i2c_get_adapter(3);
 	if (i2c_adap == NULL) {
 		DRM_ERROR("No ddc adapter available!\n");
@@ -253,17 +594,7 @@ static int oaktrail_hdmi_get_modes(struct drm_connector *connector)
 		drm_mode_connector_update_edid_property(connector, edid);
 		ret = drm_add_edid_modes(connector, edid);
 	}
-
-	/*
-	 * prune modes that require frame buffer bigger than stolen mem
-	 */
-	list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
-		if ((mode->hdisplay * mode->vdisplay * 4) >= dev_priv->vram_stolen_size) {
-			i++;
-			drm_mode_remove(connector, mode);
-		}
-	}
-	return ret - i;
+	return ret;
 }
 
 static void oaktrail_hdmi_mode_set(struct drm_encoder *encoder,
@@ -349,6 +680,7 @@ void oaktrail_hdmi_init(struct drm_device *dev,
 	connector->interlace_allowed = false;
 	connector->doublescan_allowed = false;
 	drm_sysfs_connector_add(connector);
+	dev_info(dev->dev, "HDMI initialised.\n");
 
 	return;
 
@@ -403,6 +735,9 @@ void oaktrail_hdmi_setup(struct drm_device *dev)
 
 	dev_priv->hdmi_priv = hdmi_dev;
 	oaktrail_hdmi_audio_disable(dev);
+
+	dev_info(dev->dev, "HDMI hardware present.\n");
+
 	return;
 
 free:
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index dde8b50..4568e7d 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1068,7 +1068,7 @@ static int gen6_drpc_info(struct seq_file *m)
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 rpmodectl1, gt_core_status, rcctl1;
+	u32 rpmodectl1, gt_core_status, rcctl1, rc6vids = 0;
 	unsigned forcewake_count;
 	int count=0, ret;
 
@@ -1097,6 +1097,9 @@ static int gen6_drpc_info(struct seq_file *m)
 	rpmodectl1 = I915_READ(GEN6_RP_CONTROL);
 	rcctl1 = I915_READ(GEN6_RC_CONTROL);
 	mutex_unlock(&dev->struct_mutex);
+	mutex_lock(&dev_priv->rps.hw_lock);
+	sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
+	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	seq_printf(m, "Video Turbo Mode: %s\n",
 		   yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO));
@@ -1148,6 +1151,12 @@ static int gen6_drpc_info(struct seq_file *m)
 	seq_printf(m, "RC6++ residency since boot: %u\n",
 		   I915_READ(GEN6_GT_GFX_RC6pp));
 
+	seq_printf(m, "RC6   voltage: %dmV\n",
+		   GEN6_DECODE_RC6_VID(((rc6vids >> 0) & 0xff)));
+	seq_printf(m, "RC6+  voltage: %dmV\n",
+		   GEN6_DECODE_RC6_VID(((rc6vids >> 8) & 0xff)));
+	seq_printf(m, "RC6++ voltage: %dmV\n",
+		   GEN6_DECODE_RC6_VID(((rc6vids >> 16) & 0xff)));
 	return 0;
 }
 
@@ -1273,7 +1282,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
 		return 0;
 	}
 
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
 	if (ret)
 		return ret;
 
@@ -1282,19 +1291,14 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
 	for (gpu_freq = dev_priv->rps.min_delay;
 	     gpu_freq <= dev_priv->rps.max_delay;
 	     gpu_freq++) {
-		I915_WRITE(GEN6_PCODE_DATA, gpu_freq);
-		I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY |
-			   GEN6_PCODE_READ_MIN_FREQ_TABLE);
-		if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) &
-			      GEN6_PCODE_READY) == 0, 10)) {
-			DRM_ERROR("pcode read of freq table timed out\n");
-			continue;
-		}
-		ia_freq = I915_READ(GEN6_PCODE_DATA);
+		ia_freq = gpu_freq;
+		sandybridge_pcode_read(dev_priv,
+				       GEN6_PCODE_READ_MIN_FREQ_TABLE,
+				       &ia_freq);
 		seq_printf(m, "%d\t\t%d\n", gpu_freq * GT_FREQUENCY_MULTIPLIER, ia_freq * 100);
 	}
 
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return 0;
 }
@@ -1398,15 +1402,15 @@ static int i915_context_status(struct seq_file *m, void *unused)
 	if (ret)
 		return ret;
 
-	if (dev_priv->pwrctx) {
+	if (dev_priv->ips.pwrctx) {
 		seq_printf(m, "power context ");
-		describe_obj(m, dev_priv->pwrctx);
+		describe_obj(m, dev_priv->ips.pwrctx);
 		seq_printf(m, "\n");
 	}
 
-	if (dev_priv->renderctx) {
+	if (dev_priv->ips.renderctx) {
 		seq_printf(m, "render context ");
-		describe_obj(m, dev_priv->renderctx);
+		describe_obj(m, dev_priv->ips.renderctx);
 		seq_printf(m, "\n");
 	}
 
@@ -1711,13 +1715,13 @@ i915_max_freq_read(struct file *filp,
 	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
 		return -ENODEV;
 
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
 	if (ret)
 		return ret;
 
 	len = snprintf(buf, sizeof(buf),
 		       "max freq: %d\n", dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER);
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	if (len > sizeof(buf))
 		len = sizeof(buf);
@@ -1752,7 +1756,7 @@ i915_max_freq_write(struct file *filp,
 
 	DRM_DEBUG_DRIVER("Manually setting max freq to %d\n", val);
 
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
 	if (ret)
 		return ret;
 
@@ -1762,7 +1766,7 @@ i915_max_freq_write(struct file *filp,
 	dev_priv->rps.max_delay = val / GT_FREQUENCY_MULTIPLIER;
 
 	gen6_set_rps(dev, val / GT_FREQUENCY_MULTIPLIER);
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return cnt;
 }
@@ -1787,13 +1791,13 @@ i915_min_freq_read(struct file *filp, char __user *ubuf, size_t max,
 	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
 		return -ENODEV;
 
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
 	if (ret)
 		return ret;
 
 	len = snprintf(buf, sizeof(buf),
 		       "min freq: %d\n", dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER);
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	if (len > sizeof(buf))
 		len = sizeof(buf);
@@ -1826,7 +1830,7 @@ i915_min_freq_write(struct file *filp, const char __user *ubuf, size_t cnt,
 
 	DRM_DEBUG_DRIVER("Manually setting min freq to %d\n", val);
 
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
 	if (ret)
 		return ret;
 
@@ -1836,7 +1840,7 @@ i915_min_freq_write(struct file *filp, const char __user *ubuf, size_t cnt,
 	dev_priv->rps.min_delay = val / GT_FREQUENCY_MULTIPLIER;
 
 	gen6_set_rps(dev, val / GT_FREQUENCY_MULTIPLIER);
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return cnt;
 }
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 61ae104..a48e491 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -104,32 +104,6 @@ static void i915_write_hws_pga(struct drm_device *dev)
 }
 
 /**
- * Sets up the hardware status page for devices that need a physical address
- * in the register.
- */
-static int i915_init_phys_hws(struct drm_device *dev)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-
-	/* Program Hardware Status Page */
-	dev_priv->status_page_dmah =
-		drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE);
-
-	if (!dev_priv->status_page_dmah) {
-		DRM_ERROR("Can not allocate hardware status page\n");
-		return -ENOMEM;
-	}
-
-	memset_io((void __force __iomem *)dev_priv->status_page_dmah->vaddr,
-		  0, PAGE_SIZE);
-
-	i915_write_hws_pga(dev);
-
-	DRM_DEBUG_DRIVER("Enabled hardware status page\n");
-	return 0;
-}
-
-/**
  * Frees the hardware status page, whether it's a physical address or a virtual
  * address set up by the X Server.
  */
@@ -451,16 +425,16 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
 
-	dev_priv->counter++;
-	if (dev_priv->counter > 0x7FFFFFFFUL)
-		dev_priv->counter = 0;
+	dev_priv->dri1.counter++;
+	if (dev_priv->dri1.counter > 0x7FFFFFFFUL)
+		dev_priv->dri1.counter = 0;
 	if (master_priv->sarea_priv)
-		master_priv->sarea_priv->last_enqueue = dev_priv->counter;
+		master_priv->sarea_priv->last_enqueue = dev_priv->dri1.counter;
 
 	if (BEGIN_LP_RING(4) == 0) {
 		OUT_RING(MI_STORE_DWORD_INDEX);
 		OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-		OUT_RING(dev_priv->counter);
+		OUT_RING(dev_priv->dri1.counter);
 		OUT_RING(0);
 		ADVANCE_LP_RING();
 	}
@@ -602,12 +576,12 @@ static int i915_dispatch_flip(struct drm_device * dev)
 
 	ADVANCE_LP_RING();
 
-	master_priv->sarea_priv->last_enqueue = dev_priv->counter++;
+	master_priv->sarea_priv->last_enqueue = dev_priv->dri1.counter++;
 
 	if (BEGIN_LP_RING(4) == 0) {
 		OUT_RING(MI_STORE_DWORD_INDEX);
 		OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-		OUT_RING(dev_priv->counter);
+		OUT_RING(dev_priv->dri1.counter);
 		OUT_RING(0);
 		ADVANCE_LP_RING();
 	}
@@ -775,21 +749,21 @@ static int i915_emit_irq(struct drm_device * dev)
 
 	DRM_DEBUG_DRIVER("\n");
 
-	dev_priv->counter++;
-	if (dev_priv->counter > 0x7FFFFFFFUL)
-		dev_priv->counter = 1;
+	dev_priv->dri1.counter++;
+	if (dev_priv->dri1.counter > 0x7FFFFFFFUL)
+		dev_priv->dri1.counter = 1;
 	if (master_priv->sarea_priv)
-		master_priv->sarea_priv->last_enqueue = dev_priv->counter;
+		master_priv->sarea_priv->last_enqueue = dev_priv->dri1.counter;
 
 	if (BEGIN_LP_RING(4) == 0) {
 		OUT_RING(MI_STORE_DWORD_INDEX);
 		OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-		OUT_RING(dev_priv->counter);
+		OUT_RING(dev_priv->dri1.counter);
 		OUT_RING(MI_USER_INTERRUPT);
 		ADVANCE_LP_RING();
 	}
 
-	return dev_priv->counter;
+	return dev_priv->dri1.counter;
 }
 
 static int i915_wait_irq(struct drm_device * dev, int irq_nr)
@@ -820,7 +794,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
 
 	if (ret == -EBUSY) {
 		DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
-			  READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
+			  READ_BREADCRUMB(dev_priv), (int)dev_priv->dri1.counter);
 	}
 
 	return ret;
@@ -1014,6 +988,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
 	case I915_PARAM_HAS_PRIME_VMAP_FLUSH:
 		value = 1;
 		break;
+	case I915_PARAM_HAS_SECURE_BATCHES:
+		value = capable(CAP_SYS_ADMIN);
+		break;
 	default:
 		DRM_DEBUG_DRIVER("Unknown parameter %d\n",
 				 param->param);
@@ -1326,6 +1303,8 @@ static int i915_load_modeset_init(struct drm_device *dev)
 
 	intel_modeset_gem_init(dev);
 
+	INIT_WORK(&dev_priv->console_resume_work, intel_console_resume);
+
 	ret = drm_irq_install(dev);
 	if (ret)
 		goto cleanup_gem;
@@ -1491,19 +1470,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 		goto free_priv;
 	}
 
-	ret = intel_gmch_probe(dev_priv->bridge_dev, dev->pdev, NULL);
-	if (!ret) {
-		DRM_ERROR("failed to set up gmch\n");
-		ret = -EIO;
+	ret = i915_gem_gtt_init(dev);
+	if (ret)
 		goto put_bridge;
-	}
-
-	dev_priv->mm.gtt = intel_gtt_get();
-	if (!dev_priv->mm.gtt) {
-		DRM_ERROR("Failed to initialize GTT\n");
-		ret = -ENODEV;
-		goto put_gmch;
-	}
 
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
 		i915_kick_out_firmware_fb(dev_priv);
@@ -1590,18 +1559,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	intel_setup_gmbus(dev);
 	intel_opregion_setup(dev);
 
-	/* Make sure the bios did its job and set up vital registers */
 	intel_setup_bios(dev);
 
 	i915_gem_load(dev);
 
-	/* Init HWS */
-	if (!I915_NEED_GFX_HWS(dev)) {
-		ret = i915_init_phys_hws(dev);
-		if (ret)
-			goto out_gem_unload;
-	}
-
 	/* On the 945G/GM, the chipset reports the MSI capability on the
 	 * integrated graphics even though the support isn't actually there
 	 * according to the published specs.  It doesn't appear to function
@@ -1621,6 +1582,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	spin_lock_init(&dev_priv->rps.lock);
 	spin_lock_init(&dev_priv->dpio_lock);
 
+	mutex_init(&dev_priv->rps.hw_lock);
+
 	if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
 		dev_priv->num_pipe = 3;
 	else if (IS_MOBILE(dev) || !IS_GEN2(dev))
@@ -1678,7 +1641,7 @@ out_mtrrfree:
 out_rmmap:
 	pci_iounmap(dev->pdev, dev_priv->regs);
 put_gmch:
-	intel_gmch_remove();
+	i915_gem_gtt_fini(dev);
 put_bridge:
 	pci_dev_put(dev_priv->bridge_dev);
 free_priv:
@@ -1721,6 +1684,7 @@ int i915_driver_unload(struct drm_device *dev)
 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 		intel_fbdev_fini(dev);
 		intel_modeset_cleanup(dev);
+		cancel_work_sync(&dev_priv->console_resume_work);
 
 		/*
 		 * free the memory space allocated for the child device
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 6770ee6..f85e8b0 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -423,19 +423,23 @@ void intel_detect_pch(struct drm_device *dev)
 				dev_priv->pch_type = PCH_IBX;
 				dev_priv->num_pch_pll = 2;
 				DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
+				WARN_ON(!IS_GEN5(dev));
 			} else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
 				dev_priv->pch_type = PCH_CPT;
 				dev_priv->num_pch_pll = 2;
 				DRM_DEBUG_KMS("Found CougarPoint PCH\n");
+				WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
 			} else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
 				/* PantherPoint is CPT compatible */
 				dev_priv->pch_type = PCH_CPT;
 				dev_priv->num_pch_pll = 2;
 				DRM_DEBUG_KMS("Found PatherPoint PCH\n");
+				WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
 			} else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
 				dev_priv->pch_type = PCH_LPT;
 				dev_priv->num_pch_pll = 0;
 				DRM_DEBUG_KMS("Found LynxPoint PCH\n");
+				WARN_ON(!IS_HASWELL(dev));
 			}
 			BUG_ON(dev_priv->num_pch_pll > I915_NUM_PLLS);
 		}
@@ -477,6 +481,8 @@ static int i915_drm_freeze(struct drm_device *dev)
 			return error;
 		}
 
+		cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
+
 		intel_modeset_disable(dev);
 
 		drm_irq_uninstall(dev);
@@ -526,17 +532,23 @@ int i915_suspend(struct drm_device *dev, pm_message_t state)
 	return 0;
 }
 
-static int i915_drm_thaw(struct drm_device *dev)
+void intel_console_resume(struct work_struct *work)
+{
+	struct drm_i915_private *dev_priv =
+		container_of(work, struct drm_i915_private,
+			     console_resume_work);
+	struct drm_device *dev = dev_priv->dev;
+
+	console_lock();
+	intel_fbdev_set_suspend(dev, 0);
+	console_unlock();
+}
+
+static int __i915_drm_thaw(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int error = 0;
 
-	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		mutex_lock(&dev->struct_mutex);
-		i915_gem_restore_gtt_mappings(dev);
-		mutex_unlock(&dev->struct_mutex);
-	}
-
 	i915_restore_state(dev);
 	intel_opregion_setup(dev);
 
@@ -553,7 +565,6 @@ static int i915_drm_thaw(struct drm_device *dev)
 
 		intel_modeset_init_hw(dev);
 		intel_modeset_setup_hw_state(dev);
-		drm_mode_config_reset(dev);
 		drm_irq_install(dev);
 	}
 
@@ -561,14 +572,41 @@ static int i915_drm_thaw(struct drm_device *dev)
 
 	dev_priv->modeset_on_lid = 0;
 
-	console_lock();
-	intel_fbdev_set_suspend(dev, 0);
-	console_unlock();
+	/*
+	 * The console lock can be pretty contented on resume due
+	 * to all the printk activity.  Try to keep it out of the hot
+	 * path of resume if possible.
+	 */
+	if (console_trylock()) {
+		intel_fbdev_set_suspend(dev, 0);
+		console_unlock();
+	} else {
+		schedule_work(&dev_priv->console_resume_work);
+	}
+
+	return error;
+}
+
+static int i915_drm_thaw(struct drm_device *dev)
+{
+	int error = 0;
+
+	intel_gt_reset(dev);
+
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		mutex_lock(&dev->struct_mutex);
+		i915_gem_restore_gtt_mappings(dev);
+		mutex_unlock(&dev->struct_mutex);
+	}
+
+	__i915_drm_thaw(dev);
+
 	return error;
 }
 
 int i915_resume(struct drm_device *dev)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
 	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
@@ -579,7 +617,20 @@ int i915_resume(struct drm_device *dev)
 
 	pci_set_master(dev->pdev);
 
-	ret = i915_drm_thaw(dev);
+	intel_gt_reset(dev);
+
+	/*
+	 * Platforms with opregion should have sane BIOS, older ones (gen3 and
+	 * earlier) need this since the BIOS might clear all our scratch PTEs.
+	 */
+	if (drm_core_check_feature(dev, DRIVER_MODESET) &&
+	    !dev_priv->opregion.header) {
+		mutex_lock(&dev->struct_mutex);
+		i915_gem_restore_gtt_mappings(dev);
+		mutex_unlock(&dev->struct_mutex);
+	}
+
+	ret = __i915_drm_thaw(dev);
 	if (ret)
 		return ret;
 
@@ -1140,12 +1191,40 @@ static bool IS_DISPLAYREG(u32 reg)
 	if (reg == GEN6_GDRST)
 		return false;
 
+	switch (reg) {
+	case _3D_CHICKEN3:
+	case IVB_CHICKEN3:
+	case GEN7_COMMON_SLICE_CHICKEN1:
+	case GEN7_L3CNTLREG1:
+	case GEN7_L3_CHICKEN_MODE_REGISTER:
+	case GEN7_ROW_CHICKEN2:
+	case GEN7_L3SQCREG4:
+	case GEN7_SQ_CHICKEN_MBCUNIT_CONFIG:
+	case GEN7_HALF_SLICE_CHICKEN1:
+	case GEN6_MBCTL:
+	case GEN6_UCGCTL2:
+		return false;
+	default:
+		break;
+	}
+
 	return true;
 }
 
+static void
+ilk_dummy_write(struct drm_i915_private *dev_priv)
+{
+	/* WaIssueDummyWriteToWakeupFromRC6: Issue a dummy write to wake up the
+	 * chip from rc6 before touching it for real. MI_MODE is masked, hence
+	 * harmless to write 0 into. */
+	I915_WRITE_NOTRACE(MI_MODE, 0);
+}
+
 #define __i915_read(x, y) \
 u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
 	u##x val = 0; \
+	if (IS_GEN5(dev_priv->dev)) \
+		ilk_dummy_write(dev_priv); \
 	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
 		unsigned long irqflags; \
 		spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \
@@ -1177,6 +1256,8 @@ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
 	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
 		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
 	} \
+	if (IS_GEN5(dev_priv->dev)) \
+		ilk_dummy_write(dev_priv); \
 	if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \
 		write##y(val, dev_priv->regs + reg + 0x180000);		\
 	} else {							\
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index f511fa2..4b83e5f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -58,6 +58,14 @@ enum pipe {
 };
 #define pipe_name(p) ((p) + 'A')
 
+enum transcoder {
+	TRANSCODER_A = 0,
+	TRANSCODER_B,
+	TRANSCODER_C,
+	TRANSCODER_EDP = 0xF,
+};
+#define transcoder_name(t) ((t) + 'A')
+
 enum plane {
 	PLANE_A = 0,
 	PLANE_B,
@@ -93,6 +101,12 @@ struct intel_pch_pll {
 };
 #define I915_NUM_PLLS 2
 
+struct intel_ddi_plls {
+	int spll_refcount;
+	int wrpll1_refcount;
+	int wrpll2_refcount;
+};
+
 /* Interface history:
  *
  * 1.1: Original.
@@ -123,14 +137,6 @@ struct drm_i915_gem_phys_object {
 	struct drm_i915_gem_object *cur_obj;
 };
 
-struct mem_block {
-	struct mem_block *next;
-	struct mem_block *prev;
-	int start;
-	int size;
-	struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */
-};
-
 struct opregion_header;
 struct opregion_acpi;
 struct opregion_swsci;
@@ -251,6 +257,7 @@ struct drm_i915_display_funcs {
 				 uint32_t sprite_width, int pixel_size);
 	void (*update_linetime_wm)(struct drm_device *dev, int pipe,
 				 struct drm_display_mode *mode);
+	void (*modeset_global_resources)(struct drm_device *dev);
 	int (*crtc_mode_set)(struct drm_crtc *crtc,
 			     struct drm_display_mode *mode,
 			     struct drm_display_mode *adjusted_mode,
@@ -263,7 +270,6 @@ struct drm_i915_display_funcs {
 			  struct drm_crtc *crtc);
 	void (*fdi_link_train)(struct drm_crtc *crtc);
 	void (*init_clock_gating)(struct drm_device *dev);
-	void (*init_pch_clock_gating)(struct drm_device *dev);
 	int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc,
 			  struct drm_framebuffer *fb,
 			  struct drm_i915_gem_object *obj);
@@ -338,6 +344,7 @@ struct intel_device_info {
 #define I915_PPGTT_PD_ENTRIES 512
 #define I915_PPGTT_PT_ENTRIES 1024
 struct i915_hw_ppgtt {
+	struct drm_device *dev;
 	unsigned num_pd_entries;
 	struct page **pt_pages;
 	uint32_t pd_offset;
@@ -383,149 +390,14 @@ struct intel_fbc_work;
 
 struct intel_gmbus {
 	struct i2c_adapter adapter;
-	bool force_bit;
+	u32 force_bit;
 	u32 reg0;
 	u32 gpio_reg;
 	struct i2c_algo_bit_data bit_algo;
 	struct drm_i915_private *dev_priv;
 };
 
-typedef struct drm_i915_private {
-	struct drm_device *dev;
-
-	const struct intel_device_info *info;
-
-	int relative_constants_mode;
-
-	void __iomem *regs;
-
-	struct drm_i915_gt_funcs gt;
-	/** gt_fifo_count and the subsequent register write are synchronized
-	 * with dev->struct_mutex. */
-	unsigned gt_fifo_count;
-	/** forcewake_count is protected by gt_lock */
-	unsigned forcewake_count;
-	/** gt_lock is also taken in irq contexts. */
-	struct spinlock gt_lock;
-
-	struct intel_gmbus gmbus[GMBUS_NUM_PORTS];
-
-	/** gmbus_mutex protects against concurrent usage of the single hw gmbus
-	 * controller on different i2c buses. */
-	struct mutex gmbus_mutex;
-
-	/**
-	 * Base address of the gmbus and gpio block.
-	 */
-	uint32_t gpio_mmio_base;
-
-	struct pci_dev *bridge_dev;
-	struct intel_ring_buffer ring[I915_NUM_RINGS];
-	uint32_t next_seqno;
-
-	drm_dma_handle_t *status_page_dmah;
-	uint32_t counter;
-	struct drm_i915_gem_object *pwrctx;
-	struct drm_i915_gem_object *renderctx;
-
-	struct resource mch_res;
-
-	atomic_t irq_received;
-
-	/* protects the irq masks */
-	spinlock_t irq_lock;
-
-	/* DPIO indirect register protection */
-	spinlock_t dpio_lock;
-
-	/** Cached value of IMR to avoid reads in updating the bitfield */
-	u32 pipestat[2];
-	u32 irq_mask;
-	u32 gt_irq_mask;
-	u32 pch_irq_mask;
-
-	u32 hotplug_supported_mask;
-	struct work_struct hotplug_work;
-
-	int num_pipe;
-	int num_pch_pll;
-
-	/* For hangcheck timer */
-#define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
-	struct timer_list hangcheck_timer;
-	int hangcheck_count;
-	uint32_t last_acthd[I915_NUM_RINGS];
-	uint32_t prev_instdone[I915_NUM_INSTDONE_REG];
-
-	unsigned int stop_rings;
-
-	unsigned long cfb_size;
-	unsigned int cfb_fb;
-	enum plane cfb_plane;
-	int cfb_y;
-	struct intel_fbc_work *fbc_work;
-
-	struct intel_opregion opregion;
-
-	/* overlay */
-	struct intel_overlay *overlay;
-	bool sprite_scaling_enabled;
-
-	/* LVDS info */
-	int backlight_level;  /* restore backlight to this value */
-	bool backlight_enabled;
-	struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
-	struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
-
-	/* Feature bits from the VBIOS */
-	unsigned int int_tv_support:1;
-	unsigned int lvds_dither:1;
-	unsigned int lvds_vbt:1;
-	unsigned int int_crt_support:1;
-	unsigned int lvds_use_ssc:1;
-	unsigned int display_clock_mode:1;
-	int lvds_ssc_freq;
-	unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
-	unsigned int lvds_val; /* used for checking LVDS channel mode */
-	struct {
-		int rate;
-		int lanes;
-		int preemphasis;
-		int vswing;
-
-		bool initialized;
-		bool support;
-		int bpp;
-		struct edp_power_seq pps;
-	} edp;
-	bool no_aux_handshake;
-
-	struct notifier_block lid_notifier;
-
-	int crt_ddc_pin;
-	struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */
-	int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
-	int num_fence_regs; /* 8 on pre-965, 16 otherwise */
-
-	unsigned int fsb_freq, mem_freq, is_ddr3;
-
-	spinlock_t error_lock;
-	/* Protected by dev->error_lock. */
-	struct drm_i915_error_state *first_error;
-	struct work_struct error_work;
-	struct completion error_completion;
-	struct workqueue_struct *wq;
-
-	/* Display functions */
-	struct drm_i915_display_funcs display;
-
-	/* PCH chipset type */
-	enum intel_pch pch_type;
-
-	unsigned long quirks;
-
-	/* Register state */
-	bool modeset_on_lid;
+struct i915_suspend_saved_registers {
 	u8 saveLBB;
 	u32 saveDSPACNTR;
 	u32 saveDSPBCNTR;
@@ -676,10 +548,205 @@ typedef struct drm_i915_private {
 	u32 savePIPEB_LINK_N1;
 	u32 saveMCHBAR_RENDER_STANDBY;
 	u32 savePCH_PORT_HOTPLUG;
+};
+
+struct intel_gen6_power_mgmt {
+	struct work_struct work;
+	u32 pm_iir;
+	/* lock - irqsave spinlock that protectects the work_struct and
+	 * pm_iir. */
+	spinlock_t lock;
+
+	/* The below variables an all the rps hw state are protected by
+	 * dev->struct mutext. */
+	u8 cur_delay;
+	u8 min_delay;
+	u8 max_delay;
+
+	struct delayed_work delayed_resume_work;
+
+	/*
+	 * Protects RPS/RC6 register access and PCU communication.
+	 * Must be taken after struct_mutex if nested.
+	 */
+	struct mutex hw_lock;
+};
+
+struct intel_ilk_power_mgmt {
+	u8 cur_delay;
+	u8 min_delay;
+	u8 max_delay;
+	u8 fmax;
+	u8 fstart;
+
+	u64 last_count1;
+	unsigned long last_time1;
+	unsigned long chipset_power;
+	u64 last_count2;
+	struct timespec last_time2;
+	unsigned long gfx_power;
+	u8 corr;
+
+	int c_m;
+	int r_t;
+
+	struct drm_i915_gem_object *pwrctx;
+	struct drm_i915_gem_object *renderctx;
+};
+
+struct i915_dri1_state {
+	unsigned allow_batchbuffer : 1;
+	u32 __iomem *gfx_hws_cpu_addr;
+
+	unsigned int cpp;
+	int back_offset;
+	int front_offset;
+	int current_page;
+	int page_flipping;
+
+	uint32_t counter;
+};
+
+struct intel_l3_parity {
+	u32 *remap_info;
+	struct work_struct error_work;
+};
+
+typedef struct drm_i915_private {
+	struct drm_device *dev;
+
+	const struct intel_device_info *info;
+
+	int relative_constants_mode;
+
+	void __iomem *regs;
+
+	struct drm_i915_gt_funcs gt;
+	/** gt_fifo_count and the subsequent register write are synchronized
+	 * with dev->struct_mutex. */
+	unsigned gt_fifo_count;
+	/** forcewake_count is protected by gt_lock */
+	unsigned forcewake_count;
+	/** gt_lock is also taken in irq contexts. */
+	struct spinlock gt_lock;
+
+	struct intel_gmbus gmbus[GMBUS_NUM_PORTS];
+
+	/** gmbus_mutex protects against concurrent usage of the single hw gmbus
+	 * controller on different i2c buses. */
+	struct mutex gmbus_mutex;
+
+	/**
+	 * Base address of the gmbus and gpio block.
+	 */
+	uint32_t gpio_mmio_base;
+
+	struct pci_dev *bridge_dev;
+	struct intel_ring_buffer ring[I915_NUM_RINGS];
+	uint32_t next_seqno;
+
+	drm_dma_handle_t *status_page_dmah;
+	struct resource mch_res;
+
+	atomic_t irq_received;
+
+	/* protects the irq masks */
+	spinlock_t irq_lock;
+
+	/* DPIO indirect register protection */
+	spinlock_t dpio_lock;
+
+	/** Cached value of IMR to avoid reads in updating the bitfield */
+	u32 pipestat[2];
+	u32 irq_mask;
+	u32 gt_irq_mask;
+	u32 pch_irq_mask;
+
+	u32 hotplug_supported_mask;
+	struct work_struct hotplug_work;
+
+	int num_pipe;
+	int num_pch_pll;
+
+	/* For hangcheck timer */
+#define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
+#define DRM_I915_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)
+	struct timer_list hangcheck_timer;
+	int hangcheck_count;
+	uint32_t last_acthd[I915_NUM_RINGS];
+	uint32_t prev_instdone[I915_NUM_INSTDONE_REG];
+
+	unsigned int stop_rings;
+
+	unsigned long cfb_size;
+	unsigned int cfb_fb;
+	enum plane cfb_plane;
+	int cfb_y;
+	struct intel_fbc_work *fbc_work;
+
+	struct intel_opregion opregion;
+
+	/* overlay */
+	struct intel_overlay *overlay;
+	bool sprite_scaling_enabled;
+
+	/* LVDS info */
+	int backlight_level;  /* restore backlight to this value */
+	bool backlight_enabled;
+	struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
+	struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
+
+	/* Feature bits from the VBIOS */
+	unsigned int int_tv_support:1;
+	unsigned int lvds_dither:1;
+	unsigned int lvds_vbt:1;
+	unsigned int int_crt_support:1;
+	unsigned int lvds_use_ssc:1;
+	unsigned int display_clock_mode:1;
+	int lvds_ssc_freq;
+	unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
+	unsigned int lvds_val; /* used for checking LVDS channel mode */
+	struct {
+		int rate;
+		int lanes;
+		int preemphasis;
+		int vswing;
+
+		bool initialized;
+		bool support;
+		int bpp;
+		struct edp_power_seq pps;
+	} edp;
+	bool no_aux_handshake;
+
+	int crt_ddc_pin;
+	struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */
+	int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
+	int num_fence_regs; /* 8 on pre-965, 16 otherwise */
+
+	unsigned int fsb_freq, mem_freq, is_ddr3;
+
+	spinlock_t error_lock;
+	/* Protected by dev->error_lock. */
+	struct drm_i915_error_state *first_error;
+	struct work_struct error_work;
+	struct completion error_completion;
+	struct workqueue_struct *wq;
+
+	/* Display functions */
+	struct drm_i915_display_funcs display;
+
+	/* PCH chipset type */
+	enum intel_pch pch_type;
+
+	unsigned long quirks;
+
+	/* Register state */
+	bool modeset_on_lid;
 
 	struct {
 		/** Bridge to intel-gtt-ko */
-		const struct intel_gtt *gtt;
+		struct intel_gtt *gtt;
 		/** Memory allocator for GTT stolen memory */
 		struct drm_mm stolen;
 		/** Memory allocator for GTT */
@@ -706,8 +773,6 @@ typedef struct drm_i915_private {
 		/** PPGTT used for aliasing the PPGTT with the GTT */
 		struct i915_hw_ppgtt *aliasing_ppgtt;
 
-		u32 *l3_remap_info;
-
 		struct shrinker inactive_shrinker;
 
 		/**
@@ -785,19 +850,6 @@ typedef struct drm_i915_private {
 		u32 object_count;
 	} mm;
 
-	/* Old dri1 support infrastructure, beware the dragons ya fools entering
-	 * here! */
-	struct {
-		unsigned allow_batchbuffer : 1;
-		u32 __iomem *gfx_hws_cpu_addr;
-
-		unsigned int cpp;
-		int back_offset;
-		int front_offset;
-		int current_page;
-		int page_flipping;
-	} dri1;
-
 	/* Kernel Modesetting */
 
 	struct sdvo_device_mapping sdvo_mappings[2];
@@ -811,6 +863,7 @@ typedef struct drm_i915_private {
 	wait_queue_head_t pending_flip_queue;
 
 	struct intel_pch_pll pch_plls[I915_NUM_PLLS];
+	struct intel_ddi_plls ddi_plls;
 
 	/* Reclocking support */
 	bool render_reclock_avail;
@@ -820,46 +873,17 @@ typedef struct drm_i915_private {
 	u16 orig_clock;
 	int child_dev_num;
 	struct child_device_config *child_dev;
-	struct drm_connector *int_lvds_connector;
-	struct drm_connector *int_edp_connector;
 
 	bool mchbar_need_disable;
 
+	struct intel_l3_parity l3_parity;
+
 	/* gen6+ rps state */
-	struct {
-		struct work_struct work;
-		u32 pm_iir;
-		/* lock - irqsave spinlock that protectects the work_struct and
-		 * pm_iir. */
-		spinlock_t lock;
-
-		/* The below variables an all the rps hw state are protected by
-		 * dev->struct mutext. */
-		u8 cur_delay;
-		u8 min_delay;
-		u8 max_delay;
-	} rps;
+	struct intel_gen6_power_mgmt rps;
 
 	/* ilk-only ips/rps state. Everything in here is protected by the global
 	 * mchdev_lock in intel_pm.c */
-	struct {
-		u8 cur_delay;
-		u8 min_delay;
-		u8 max_delay;
-		u8 fmax;
-		u8 fstart;
-
-		u64 last_count1;
-		unsigned long last_time1;
-		unsigned long chipset_power;
-		u64 last_count2;
-		struct timespec last_time2;
-		unsigned long gfx_power;
-		u8 corr;
-
-		int c_m;
-		int r_t;
-	} ips;
+	struct intel_ilk_power_mgmt ips;
 
 	enum no_fbc_reason no_fbc_reason;
 
@@ -871,14 +895,25 @@ typedef struct drm_i915_private {
 	/* list of fbdev register on this device */
 	struct intel_fbdev *fbdev;
 
+	/*
+	 * The console may be contended at resume, but we don't
+	 * want it to block on it.
+	 */
+	struct work_struct console_resume_work;
+
 	struct backlight_device *backlight;
 
 	struct drm_property *broadcast_rgb_property;
 	struct drm_property *force_audio_property;
 
-	struct work_struct parity_error_work;
 	bool hw_contexts_disabled;
 	uint32_t hw_context_size;
+
+	struct i915_suspend_saved_registers regfile;
+
+	/* Old dri1 support infrastructure, beware the dragons ya fools entering
+	 * here! */
+	struct i915_dri1_state dri1;
 } drm_i915_private_t;
 
 /* Iterate over initialised rings */
@@ -1120,6 +1155,9 @@ struct drm_i915_file_private {
 #define IS_IRONLAKE_D(dev)	((dev)->pci_device == 0x0042)
 #define IS_IRONLAKE_M(dev)	((dev)->pci_device == 0x0046)
 #define IS_IVYBRIDGE(dev)	(INTEL_INFO(dev)->is_ivybridge)
+#define IS_IVB_GT1(dev)		((dev)->pci_device == 0x0156 || \
+				 (dev)->pci_device == 0x0152 ||	\
+				 (dev)->pci_device == 0x015a)
 #define IS_VALLEYVIEW(dev)	(INTEL_INFO(dev)->is_valleyview)
 #define IS_HASWELL(dev)	(INTEL_INFO(dev)->is_haswell)
 #define IS_MOBILE(dev)		(INTEL_INFO(dev)->is_mobile)
@@ -1250,6 +1288,7 @@ extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
 extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
 extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
 
+extern void intel_console_resume(struct work_struct *work);
 
 /* i915_irq.c */
 void i915_hangcheck_elapsed(unsigned long data);
@@ -1257,6 +1296,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged);
 
 extern void intel_irq_init(struct drm_device *dev);
 extern void intel_gt_init(struct drm_device *dev);
+extern void intel_gt_reset(struct drm_device *dev);
 
 void i915_error_state_free(struct kref *error_ref);
 
@@ -1499,6 +1539,14 @@ void i915_gem_init_global_gtt(struct drm_device *dev,
 			      unsigned long start,
 			      unsigned long mappable_end,
 			      unsigned long end);
+int i915_gem_gtt_init(struct drm_device *dev);
+void i915_gem_gtt_fini(struct drm_device *dev);
+extern inline void i915_gem_chipset_flush(struct drm_device *dev)
+{
+	if (INTEL_INFO(dev)->gen < 6)
+		intel_gtt_chipset_flush();
+}
+
 
 /* i915_gem_evict.c */
 int __must_check i915_gem_evict_something(struct drm_device *dev, int min_size,
@@ -1628,6 +1676,9 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv);
 void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);
 int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv);
 
+int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val);
+int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val);
+
 #define __i915_read(x, y) \
 	u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);
 
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 107f09b..a2f1b86 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -845,12 +845,12 @@ out:
 		 * domain anymore. */
 		if (obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
 			i915_gem_clflush_object(obj);
-			intel_gtt_chipset_flush();
+			i915_gem_chipset_flush(dev);
 		}
 	}
 
 	if (needs_clflush_after)
-		intel_gtt_chipset_flush();
+		i915_gem_chipset_flush(dev);
 
 	return ret;
 }
@@ -2022,12 +2022,12 @@ i915_add_request(struct intel_ring_buffer *ring,
 	if (!dev_priv->mm.suspended) {
 		if (i915_enable_hangcheck) {
 			mod_timer(&dev_priv->hangcheck_timer,
-				  jiffies +
-				  msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+				  round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES));
 		}
 		if (was_empty) {
 			queue_delayed_work(dev_priv->wq,
-					   &dev_priv->mm.retire_work, HZ);
+					   &dev_priv->mm.retire_work,
+					   round_jiffies_up_relative(HZ));
 			intel_mark_busy(dev_priv->dev);
 		}
 	}
@@ -2218,7 +2218,8 @@ i915_gem_retire_work_handler(struct work_struct *work)
 
 	/* Come back later if the device is busy... */
 	if (!mutex_trylock(&dev->struct_mutex)) {
-		queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
+		queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work,
+				   round_jiffies_up_relative(HZ));
 		return;
 	}
 
@@ -2236,7 +2237,8 @@ i915_gem_retire_work_handler(struct work_struct *work)
 	}
 
 	if (!dev_priv->mm.suspended && !idle)
-		queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
+		queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work,
+				   round_jiffies_up_relative(HZ));
 	if (idle)
 		intel_mark_idle(dev);
 
@@ -3059,7 +3061,7 @@ i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj)
 		return;
 
 	i915_gem_clflush_object(obj);
-	intel_gtt_chipset_flush();
+	i915_gem_chipset_flush(obj->base.dev);
 	old_write_domain = obj->base.write_domain;
 	obj->base.write_domain = 0;
 
@@ -3832,7 +3834,7 @@ void i915_gem_l3_remap(struct drm_device *dev)
 	if (!IS_IVYBRIDGE(dev))
 		return;
 
-	if (!dev_priv->mm.l3_remap_info)
+	if (!dev_priv->l3_parity.remap_info)
 		return;
 
 	misccpctl = I915_READ(GEN7_MISCCPCTL);
@@ -3841,12 +3843,12 @@ void i915_gem_l3_remap(struct drm_device *dev)
 
 	for (i = 0; i < GEN7_L3LOG_SIZE; i += 4) {
 		u32 remap = I915_READ(GEN7_L3LOG_BASE + i);
-		if (remap && remap != dev_priv->mm.l3_remap_info[i/4])
+		if (remap && remap != dev_priv->l3_parity.remap_info[i/4])
 			DRM_DEBUG("0x%x was already programmed to %x\n",
 				  GEN7_L3LOG_BASE + i, remap);
-		if (remap && !dev_priv->mm.l3_remap_info[i/4])
+		if (remap && !dev_priv->l3_parity.remap_info[i/4])
 			DRM_DEBUG_DRIVER("Clearing remapped register\n");
-		I915_WRITE(GEN7_L3LOG_BASE + i, dev_priv->mm.l3_remap_info[i/4]);
+		I915_WRITE(GEN7_L3LOG_BASE + i, dev_priv->l3_parity.remap_info[i/4]);
 	}
 
 	/* Make sure all the writes land before disabling dop clock gating */
@@ -3876,68 +3878,6 @@ void i915_gem_init_swizzling(struct drm_device *dev)
 		I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB));
 }
 
-void i915_gem_init_ppgtt(struct drm_device *dev)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	uint32_t pd_offset;
-	struct intel_ring_buffer *ring;
-	struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
-	uint32_t __iomem *pd_addr;
-	uint32_t pd_entry;
-	int i;
-
-	if (!dev_priv->mm.aliasing_ppgtt)
-		return;
-
-
-	pd_addr = dev_priv->mm.gtt->gtt + ppgtt->pd_offset/sizeof(uint32_t);
-	for (i = 0; i < ppgtt->num_pd_entries; i++) {
-		dma_addr_t pt_addr;
-
-		if (dev_priv->mm.gtt->needs_dmar)
-			pt_addr = ppgtt->pt_dma_addr[i];
-		else
-			pt_addr = page_to_phys(ppgtt->pt_pages[i]);
-
-		pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr);
-		pd_entry |= GEN6_PDE_VALID;
-
-		writel(pd_entry, pd_addr + i);
-	}
-	readl(pd_addr);
-
-	pd_offset = ppgtt->pd_offset;
-	pd_offset /= 64; /* in cachelines, */
-	pd_offset <<= 16;
-
-	if (INTEL_INFO(dev)->gen == 6) {
-		uint32_t ecochk, gab_ctl, ecobits;
-
-		ecobits = I915_READ(GAC_ECO_BITS); 
-		I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B);
-
-		gab_ctl = I915_READ(GAB_CTL);
-		I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT);
-
-		ecochk = I915_READ(GAM_ECOCHK);
-		I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT |
-				       ECOCHK_PPGTT_CACHE64B);
-		I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
-	} else if (INTEL_INFO(dev)->gen >= 7) {
-		I915_WRITE(GAM_ECOCHK, ECOCHK_PPGTT_CACHE64B);
-		/* GFX_MODE is per-ring on gen7+ */
-	}
-
-	for_each_ring(ring, dev_priv, i) {
-		if (INTEL_INFO(dev)->gen >= 7)
-			I915_WRITE(RING_MODE_GEN7(ring),
-				   _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
-
-		I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
-		I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset);
-	}
-}
-
 static bool
 intel_enable_blt(struct drm_device *dev)
 {
@@ -3960,7 +3900,7 @@ i915_gem_init_hw(struct drm_device *dev)
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	int ret;
 
-	if (!intel_enable_gtt())
+	if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt())
 		return -EIO;
 
 	if (IS_HASWELL(dev) && (I915_READ(0x120010) == 1))
@@ -4295,7 +4235,7 @@ void i915_gem_detach_phys_object(struct drm_device *dev,
 			page_cache_release(page);
 		}
 	}
-	intel_gtt_chipset_flush();
+	i915_gem_chipset_flush(dev);
 
 	obj->phys_obj->cur_obj = NULL;
 	obj->phys_obj = NULL;
@@ -4382,7 +4322,7 @@ i915_gem_phys_pwrite(struct drm_device *dev,
 			return -EFAULT;
 	}
 
-	intel_gtt_chipset_flush();
+	i915_gem_chipset_flush(dev);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 05ed42f..0e510df 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -146,7 +146,7 @@ create_hw_context(struct drm_device *dev,
 	struct i915_hw_context *ctx;
 	int ret, id;
 
-	ctx = kzalloc(sizeof(struct drm_i915_file_private), GFP_KERNEL);
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 	if (ctx == NULL)
 		return ERR_PTR(-ENOMEM);
 
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 3eea143..d80e9dd 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -672,7 +672,7 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
 	}
 
 	if (flush_domains & I915_GEM_DOMAIN_CPU)
-		intel_gtt_chipset_flush();
+		i915_gem_chipset_flush(ring->dev);
 
 	if (flush_domains & I915_GEM_DOMAIN_GTT)
 		wmb();
@@ -800,6 +800,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	u32 exec_start, exec_len;
 	u32 seqno;
 	u32 mask;
+	u32 flags;
 	int ret, mode, i;
 
 	if (!i915_gem_check_execbuffer(args)) {
@@ -811,6 +812,14 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	if (ret)
 		return ret;
 
+	flags = 0;
+	if (args->flags & I915_EXEC_SECURE) {
+		if (!file->is_master || !capable(CAP_SYS_ADMIN))
+		    return -EPERM;
+
+		flags |= I915_DISPATCH_SECURE;
+	}
+
 	switch (args->flags & I915_EXEC_RING_MASK) {
 	case I915_EXEC_DEFAULT:
 	case I915_EXEC_RENDER:
@@ -983,6 +992,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	}
 	batch_obj->base.pending_read_domains |= I915_GEM_DOMAIN_COMMAND;
 
+	/* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure
+	 * batch" bit. Hence we need to pin secure batches into the global gtt.
+	 * hsw should have this fixed, but let's be paranoid and do it
+	 * unconditionally for now. */
+	if (flags & I915_DISPATCH_SECURE && !batch_obj->has_global_gtt_mapping)
+		i915_gem_gtt_bind_object(batch_obj, batch_obj->cache_level);
+
 	ret = i915_gem_execbuffer_move_to_gpu(ring, &objects);
 	if (ret)
 		goto err;
@@ -1028,7 +1044,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 			goto err;
 	}
 
-	trace_i915_gem_ring_dispatch(ring, seqno);
+	trace_i915_gem_ring_dispatch(ring, seqno, flags);
 
 	exec_start = batch_obj->gtt_offset + args->batch_start_offset;
 	exec_len = args->batch_len;
@@ -1040,12 +1056,15 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 				goto err;
 
 			ret = ring->dispatch_execbuffer(ring,
-							exec_start, exec_len);
+							exec_start, exec_len,
+							flags);
 			if (ret)
 				goto err;
 		}
 	} else {
-		ret = ring->dispatch_execbuffer(ring, exec_start, exec_len);
+		ret = ring->dispatch_execbuffer(ring,
+						exec_start, exec_len,
+						flags);
 		if (ret)
 			goto err;
 	}
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index df470b5..35fec1e 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -28,19 +28,67 @@
 #include "i915_trace.h"
 #include "intel_drv.h"
 
+typedef uint32_t gtt_pte_t;
+
+/* PPGTT stuff */
+#define GEN6_GTT_ADDR_ENCODE(addr)	((addr) | (((addr) >> 28) & 0xff0))
+
+#define GEN6_PDE_VALID			(1 << 0)
+/* gen6+ has bit 11-4 for physical addr bit 39-32 */
+#define GEN6_PDE_ADDR_ENCODE(addr)	GEN6_GTT_ADDR_ENCODE(addr)
+
+#define GEN6_PTE_VALID			(1 << 0)
+#define GEN6_PTE_UNCACHED		(1 << 1)
+#define HSW_PTE_UNCACHED		(0)
+#define GEN6_PTE_CACHE_LLC		(2 << 1)
+#define GEN6_PTE_CACHE_LLC_MLC		(3 << 1)
+#define GEN6_PTE_ADDR_ENCODE(addr)	GEN6_GTT_ADDR_ENCODE(addr)
+
+static inline gtt_pte_t pte_encode(struct drm_device *dev,
+				   dma_addr_t addr,
+				   enum i915_cache_level level)
+{
+	gtt_pte_t pte = GEN6_PTE_VALID;
+	pte |= GEN6_PTE_ADDR_ENCODE(addr);
+
+	switch (level) {
+	case I915_CACHE_LLC_MLC:
+		/* Haswell doesn't set L3 this way */
+		if (IS_HASWELL(dev))
+			pte |= GEN6_PTE_CACHE_LLC;
+		else
+			pte |= GEN6_PTE_CACHE_LLC_MLC;
+		break;
+	case I915_CACHE_LLC:
+		pte |= GEN6_PTE_CACHE_LLC;
+		break;
+	case I915_CACHE_NONE:
+		if (IS_HASWELL(dev))
+			pte |= HSW_PTE_UNCACHED;
+		else
+			pte |= GEN6_PTE_UNCACHED;
+		break;
+	default:
+		BUG();
+	}
+
+
+	return pte;
+}
+
 /* PPGTT support for Sandybdrige/Gen6 and later */
 static void i915_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
 				   unsigned first_entry,
 				   unsigned num_entries)
 {
-	uint32_t *pt_vaddr;
-	uint32_t scratch_pte;
+	gtt_pte_t *pt_vaddr;
+	gtt_pte_t scratch_pte;
 	unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES;
 	unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
 	unsigned last_pte, i;
 
-	scratch_pte = GEN6_PTE_ADDR_ENCODE(ppgtt->scratch_page_dma_addr);
-	scratch_pte |= GEN6_PTE_VALID | GEN6_PTE_CACHE_LLC;
+	scratch_pte = pte_encode(ppgtt->dev, ppgtt->scratch_page_dma_addr,
+				 I915_CACHE_LLC);
 
 	while (num_entries) {
 		last_pte = first_pte + num_entries;
@@ -77,6 +125,7 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
 	if (!ppgtt)
 		return ret;
 
+	ppgtt->dev = dev;
 	ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES;
 	ppgtt->pt_pages = kzalloc(sizeof(struct page *)*ppgtt->num_pd_entries,
 				  GFP_KERNEL);
@@ -118,7 +167,7 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
 	i915_ppgtt_clear_range(ppgtt, 0,
 			       ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES);
 
-	ppgtt->pd_offset = (first_pd_entry_in_global_pt)*sizeof(uint32_t);
+	ppgtt->pd_offset = (first_pd_entry_in_global_pt)*sizeof(gtt_pte_t);
 
 	dev_priv->mm.aliasing_ppgtt = ppgtt;
 
@@ -168,9 +217,9 @@ void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev)
 static void i915_ppgtt_insert_sg_entries(struct i915_hw_ppgtt *ppgtt,
 					 const struct sg_table *pages,
 					 unsigned first_entry,
-					 uint32_t pte_flags)
+					 enum i915_cache_level cache_level)
 {
-	uint32_t *pt_vaddr, pte;
+	gtt_pte_t *pt_vaddr;
 	unsigned act_pd = first_entry / I915_PPGTT_PT_ENTRIES;
 	unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
 	unsigned i, j, m, segment_len;
@@ -188,8 +237,8 @@ static void i915_ppgtt_insert_sg_entries(struct i915_hw_ppgtt *ppgtt,
 
 		for (j = first_pte; j < I915_PPGTT_PT_ENTRIES; j++) {
 			page_addr = sg_dma_address(sg) + (m << PAGE_SHIFT);
-			pte = GEN6_PTE_ADDR_ENCODE(page_addr);
-			pt_vaddr[j] = pte | pte_flags;
+			pt_vaddr[j] = pte_encode(ppgtt->dev, page_addr,
+						 cache_level);
 
 			/* grab the next page */
 			if (++m == segment_len) {
@@ -213,29 +262,10 @@ void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,
 			    struct drm_i915_gem_object *obj,
 			    enum i915_cache_level cache_level)
 {
-	uint32_t pte_flags = GEN6_PTE_VALID;
-
-	switch (cache_level) {
-	case I915_CACHE_LLC_MLC:
-		pte_flags |= GEN6_PTE_CACHE_LLC_MLC;
-		break;
-	case I915_CACHE_LLC:
-		pte_flags |= GEN6_PTE_CACHE_LLC;
-		break;
-	case I915_CACHE_NONE:
-		if (IS_HASWELL(obj->base.dev))
-			pte_flags |= HSW_PTE_UNCACHED;
-		else
-			pte_flags |= GEN6_PTE_UNCACHED;
-		break;
-	default:
-		BUG();
-	}
-
 	i915_ppgtt_insert_sg_entries(ppgtt,
 				     obj->pages,
 				     obj->gtt_space->start >> PAGE_SHIFT,
-				     pte_flags);
+				     cache_level);
 }
 
 void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
@@ -246,23 +276,65 @@ void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
 			       obj->base.size >> PAGE_SHIFT);
 }
 
-/* XXX kill agp_type! */
-static unsigned int cache_level_to_agp_type(struct drm_device *dev,
-					    enum i915_cache_level cache_level)
+void i915_gem_init_ppgtt(struct drm_device *dev)
 {
-	switch (cache_level) {
-	case I915_CACHE_LLC_MLC:
-		if (INTEL_INFO(dev)->gen >= 6)
-			return AGP_USER_CACHED_MEMORY_LLC_MLC;
-		/* Older chipsets do not have this extra level of CPU
-		 * cacheing, so fallthrough and request the PTE simply
-		 * as cached.
-		 */
-	case I915_CACHE_LLC:
-		return AGP_USER_CACHED_MEMORY;
-	default:
-	case I915_CACHE_NONE:
-		return AGP_USER_MEMORY;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	uint32_t pd_offset;
+	struct intel_ring_buffer *ring;
+	struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
+	uint32_t __iomem *pd_addr;
+	uint32_t pd_entry;
+	int i;
+
+	if (!dev_priv->mm.aliasing_ppgtt)
+		return;
+
+
+	pd_addr = dev_priv->mm.gtt->gtt + ppgtt->pd_offset/sizeof(uint32_t);
+	for (i = 0; i < ppgtt->num_pd_entries; i++) {
+		dma_addr_t pt_addr;
+
+		if (dev_priv->mm.gtt->needs_dmar)
+			pt_addr = ppgtt->pt_dma_addr[i];
+		else
+			pt_addr = page_to_phys(ppgtt->pt_pages[i]);
+
+		pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr);
+		pd_entry |= GEN6_PDE_VALID;
+
+		writel(pd_entry, pd_addr + i);
+	}
+	readl(pd_addr);
+
+	pd_offset = ppgtt->pd_offset;
+	pd_offset /= 64; /* in cachelines, */
+	pd_offset <<= 16;
+
+	if (INTEL_INFO(dev)->gen == 6) {
+		uint32_t ecochk, gab_ctl, ecobits;
+
+		ecobits = I915_READ(GAC_ECO_BITS);
+		I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B);
+
+		gab_ctl = I915_READ(GAB_CTL);
+		I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT);
+
+		ecochk = I915_READ(GAM_ECOCHK);
+		I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT |
+				       ECOCHK_PPGTT_CACHE64B);
+		I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
+	} else if (INTEL_INFO(dev)->gen >= 7) {
+		I915_WRITE(GAM_ECOCHK, ECOCHK_PPGTT_CACHE64B);
+		/* GFX_MODE is per-ring on gen7+ */
+	}
+
+	for_each_ring(ring, dev_priv, i) {
+		if (INTEL_INFO(dev)->gen >= 7)
+			I915_WRITE(RING_MODE_GEN7(ring),
+				   _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
+
+		I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
+		I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset);
 	}
 }
 
@@ -288,13 +360,38 @@ static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible)
 		dev_priv->mm.interruptible = interruptible;
 }
 
+
+static void i915_ggtt_clear_range(struct drm_device *dev,
+				 unsigned first_entry,
+				 unsigned num_entries)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	gtt_pte_t scratch_pte;
+	volatile void __iomem *gtt_base = dev_priv->mm.gtt->gtt + first_entry;
+	const int max_entries = dev_priv->mm.gtt->gtt_total_entries - first_entry;
+
+	if (INTEL_INFO(dev)->gen < 6) {
+		intel_gtt_clear_range(first_entry, num_entries);
+		return;
+	}
+
+	if (WARN(num_entries > max_entries,
+		 "First entry = %d; Num entries = %d (max=%d)\n",
+		 first_entry, num_entries, max_entries))
+		num_entries = max_entries;
+
+	scratch_pte = pte_encode(dev, dev_priv->mm.gtt->scratch_page_dma, I915_CACHE_LLC);
+	memset_io(gtt_base, scratch_pte, num_entries * sizeof(scratch_pte));
+	readl(gtt_base);
+}
+
 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;
 
 	/* First fill our portion of the GTT with scratch pages */
-	intel_gtt_clear_range(dev_priv->mm.gtt_start / PAGE_SIZE,
+	i915_ggtt_clear_range(dev, dev_priv->mm.gtt_start / PAGE_SIZE,
 			      (dev_priv->mm.gtt_end - dev_priv->mm.gtt_start) / PAGE_SIZE);
 
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
@@ -302,7 +399,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
 		i915_gem_gtt_bind_object(obj, obj->cache_level);
 	}
 
-	intel_gtt_chipset_flush();
+	i915_gem_chipset_flush(dev);
 }
 
 int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj)
@@ -318,21 +415,76 @@ int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj)
 	return 0;
 }
 
+/*
+ * Binds an object into the global gtt with the specified cache level. The object
+ * will be accessible to the GPU via commands whose operands reference offsets
+ * within the global GTT as well as accessible by the GPU through the GMADR
+ * mapped BAR (dev_priv->mm.gtt->gtt).
+ */
+static void gen6_ggtt_bind_object(struct drm_i915_gem_object *obj,
+				  enum i915_cache_level level)
+{
+	struct drm_device *dev = obj->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct sg_table *st = obj->pages;
+	struct scatterlist *sg = st->sgl;
+	const int first_entry = obj->gtt_space->start >> PAGE_SHIFT;
+	const int max_entries = dev_priv->mm.gtt->gtt_total_entries - first_entry;
+	gtt_pte_t __iomem *gtt_entries = dev_priv->mm.gtt->gtt + first_entry;
+	int unused, i = 0;
+	unsigned int len, m = 0;
+	dma_addr_t addr;
+
+	for_each_sg(st->sgl, sg, st->nents, unused) {
+		len = sg_dma_len(sg) >> PAGE_SHIFT;
+		for (m = 0; m < len; m++) {
+			addr = sg_dma_address(sg) + (m << PAGE_SHIFT);
+			iowrite32(pte_encode(dev, addr, level), &gtt_entries[i]);
+			i++;
+		}
+	}
+
+	BUG_ON(i > max_entries);
+	BUG_ON(i != obj->base.size / PAGE_SIZE);
+
+	/* XXX: This serves as a posting read to make sure that the PTE has
+	 * actually been updated. There is some concern that even though
+	 * registers and PTEs are within the same BAR that they are potentially
+	 * of NUMA access patterns. Therefore, even with the way we assume
+	 * hardware should work, we must keep this posting read for paranoia.
+	 */
+	if (i != 0)
+		WARN_ON(readl(&gtt_entries[i-1]) != pte_encode(dev, addr, level));
+
+	/* 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
+	 * have finished.
+	 */
+	I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
+	POSTING_READ(GFX_FLSH_CNTL_GEN6);
+}
+
 void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,
 			      enum i915_cache_level cache_level)
 {
 	struct drm_device *dev = obj->base.dev;
-	unsigned int agp_type = cache_level_to_agp_type(dev, cache_level);
+	if (INTEL_INFO(dev)->gen < 6) {
+		unsigned int flags = (cache_level == I915_CACHE_NONE) ?
+			AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
+		intel_gtt_insert_sg_entries(obj->pages,
+					    obj->gtt_space->start >> PAGE_SHIFT,
+					    flags);
+	} else {
+		gen6_ggtt_bind_object(obj, cache_level);
+	}
 
-	intel_gtt_insert_sg_entries(obj->pages,
-				    obj->gtt_space->start >> PAGE_SHIFT,
-				    agp_type);
 	obj->has_global_gtt_mapping = 1;
 }
 
 void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
 {
-	intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT,
+	i915_ggtt_clear_range(obj->base.dev,
+			      obj->gtt_space->start >> PAGE_SHIFT,
 			      obj->base.size >> PAGE_SHIFT);
 
 	obj->has_global_gtt_mapping = 0;
@@ -390,5 +542,165 @@ void i915_gem_init_global_gtt(struct drm_device *dev,
 	dev_priv->mm.mappable_gtt_total = min(end, mappable_end) - start;
 
 	/* ... but ensure that we clear the entire range. */
-	intel_gtt_clear_range(start / PAGE_SIZE, (end-start) / PAGE_SIZE);
+	i915_ggtt_clear_range(dev, start / PAGE_SIZE, (end-start) / PAGE_SIZE);
+}
+
+static int setup_scratch_page(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct page *page;
+	dma_addr_t dma_addr;
+
+	page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);
+	if (page == NULL)
+		return -ENOMEM;
+	get_page(page);
+	set_pages_uc(page, 1);
+
+#ifdef CONFIG_INTEL_IOMMU
+	dma_addr = pci_map_page(dev->pdev, page, 0, PAGE_SIZE,
+				PCI_DMA_BIDIRECTIONAL);
+	if (pci_dma_mapping_error(dev->pdev, dma_addr))
+		return -EINVAL;
+#else
+	dma_addr = page_to_phys(page);
+#endif
+	dev_priv->mm.gtt->scratch_page = page;
+	dev_priv->mm.gtt->scratch_page_dma = dma_addr;
+
+	return 0;
+}
+
+static void teardown_scratch_page(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	set_pages_wb(dev_priv->mm.gtt->scratch_page, 1);
+	pci_unmap_page(dev->pdev, dev_priv->mm.gtt->scratch_page_dma,
+		       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+	put_page(dev_priv->mm.gtt->scratch_page);
+	__free_page(dev_priv->mm.gtt->scratch_page);
+}
+
+static inline unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl)
+{
+	snb_gmch_ctl >>= SNB_GMCH_GGMS_SHIFT;
+	snb_gmch_ctl &= SNB_GMCH_GGMS_MASK;
+	return snb_gmch_ctl << 20;
+}
+
+static inline unsigned int gen6_get_stolen_size(u16 snb_gmch_ctl)
+{
+	snb_gmch_ctl >>= SNB_GMCH_GMS_SHIFT;
+	snb_gmch_ctl &= SNB_GMCH_GMS_MASK;
+	return snb_gmch_ctl << 25; /* 32 MB units */
+}
+
+static inline unsigned int gen7_get_stolen_size(u16 snb_gmch_ctl)
+{
+	static const int stolen_decoder[] = {
+		0, 0, 0, 0, 0, 32, 48, 64, 128, 256, 96, 160, 224, 352};
+	snb_gmch_ctl >>= IVB_GMCH_GMS_SHIFT;
+	snb_gmch_ctl &= IVB_GMCH_GMS_MASK;
+	return stolen_decoder[snb_gmch_ctl] << 20;
+}
+
+int i915_gem_gtt_init(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	phys_addr_t gtt_bus_addr;
+	u16 snb_gmch_ctl;
+	u32 tmp;
+	int ret;
+
+	/* On modern platforms we need not worry ourself with the legacy
+	 * hostbridge query stuff. Skip it entirely
+	 */
+	if (INTEL_INFO(dev)->gen < 6) {
+		ret = intel_gmch_probe(dev_priv->bridge_dev, dev->pdev, NULL);
+		if (!ret) {
+			DRM_ERROR("failed to set up gmch\n");
+			return -EIO;
+		}
+
+		dev_priv->mm.gtt = intel_gtt_get();
+		if (!dev_priv->mm.gtt) {
+			DRM_ERROR("Failed to initialize GTT\n");
+			intel_gmch_remove();
+			return -ENODEV;
+		}
+		return 0;
+	}
+
+	dev_priv->mm.gtt = kzalloc(sizeof(*dev_priv->mm.gtt), GFP_KERNEL);
+	if (!dev_priv->mm.gtt)
+		return -ENOMEM;
+
+	if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(40)))
+		pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(40));
+
+	pci_read_config_dword(dev->pdev, PCI_BASE_ADDRESS_0, &tmp);
+	/* For GEN6+ the PTEs for the ggtt live at 2MB + BAR0 */
+	gtt_bus_addr = (tmp & PCI_BASE_ADDRESS_MEM_MASK) + (2<<20);
+
+	pci_read_config_dword(dev->pdev, PCI_BASE_ADDRESS_2, &tmp);
+	dev_priv->mm.gtt->gma_bus_addr = tmp & PCI_BASE_ADDRESS_MEM_MASK;
+
+	/* i9xx_setup */
+	pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
+	dev_priv->mm.gtt->gtt_total_entries =
+		gen6_get_total_gtt_size(snb_gmch_ctl) / sizeof(gtt_pte_t);
+	if (INTEL_INFO(dev)->gen < 7)
+		dev_priv->mm.gtt->stolen_size = gen6_get_stolen_size(snb_gmch_ctl);
+	else
+		dev_priv->mm.gtt->stolen_size = gen7_get_stolen_size(snb_gmch_ctl);
+
+	dev_priv->mm.gtt->gtt_mappable_entries = pci_resource_len(dev->pdev, 2) >> PAGE_SHIFT;
+	/* 64/512MB is the current min/max we actually know of, but this is just a
+	 * coarse sanity check.
+	 */
+	if ((dev_priv->mm.gtt->gtt_mappable_entries >> 8) < 64 ||
+	    dev_priv->mm.gtt->gtt_mappable_entries > dev_priv->mm.gtt->gtt_total_entries) {
+		DRM_ERROR("Unknown GMADR entries (%d)\n",
+			  dev_priv->mm.gtt->gtt_mappable_entries);
+		ret = -ENXIO;
+		goto err_out;
+	}
+
+	ret = setup_scratch_page(dev);
+	if (ret) {
+		DRM_ERROR("Scratch setup failed\n");
+		goto err_out;
+	}
+
+	dev_priv->mm.gtt->gtt = ioremap_wc(gtt_bus_addr,
+					   dev_priv->mm.gtt->gtt_total_entries * sizeof(gtt_pte_t));
+	if (!dev_priv->mm.gtt->gtt) {
+		DRM_ERROR("Failed to map the gtt page table\n");
+		teardown_scratch_page(dev);
+		ret = -ENOMEM;
+		goto err_out;
+	}
+
+	/* GMADR is the PCI aperture used by SW to access tiled GFX surfaces in a linear fashion. */
+	DRM_INFO("Memory usable by graphics device = %dM\n", dev_priv->mm.gtt->gtt_total_entries >> 8);
+	DRM_DEBUG_DRIVER("GMADR size = %dM\n", dev_priv->mm.gtt->gtt_mappable_entries >> 8);
+	DRM_DEBUG_DRIVER("GTT stolen size = %dM\n", dev_priv->mm.gtt->stolen_size >> 20);
+
+	return 0;
+
+err_out:
+	kfree(dev_priv->mm.gtt);
+	if (INTEL_INFO(dev)->gen < 6)
+		intel_gmch_remove();
+	return ret;
+}
+
+void i915_gem_gtt_fini(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	iounmap(dev_priv->mm.gtt->gtt);
+	teardown_scratch_page(dev);
+	if (INTEL_INFO(dev)->gen < 6)
+		intel_gmch_remove();
+	kfree(dev_priv->mm.gtt);
 }
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 32e1bda..2604867 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -122,7 +122,10 @@ static int
 i915_pipe_enabled(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	return I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE;
+	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
+								      pipe);
+
+	return I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE;
 }
 
 /* Called from drm generic code, passed a 'crtc', which
@@ -182,6 +185,8 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
 	int vbl_start, vbl_end, htotal, vtotal;
 	bool in_vbl = true;
 	int ret = 0;
+	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
+								      pipe);
 
 	if (!i915_pipe_enabled(dev, pipe)) {
 		DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled "
@@ -190,7 +195,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
 	}
 
 	/* Get vtotal. */
-	vtotal = 1 + ((I915_READ(VTOTAL(pipe)) >> 16) & 0x1fff);
+	vtotal = 1 + ((I915_READ(VTOTAL(cpu_transcoder)) >> 16) & 0x1fff);
 
 	if (INTEL_INFO(dev)->gen >= 4) {
 		/* No obvious pixelcount register. Only query vertical
@@ -210,13 +215,13 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
 		 */
 		position = (I915_READ(PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT;
 
-		htotal = 1 + ((I915_READ(HTOTAL(pipe)) >> 16) & 0x1fff);
+		htotal = 1 + ((I915_READ(HTOTAL(cpu_transcoder)) >> 16) & 0x1fff);
 		*vpos = position / htotal;
 		*hpos = position - (*vpos * htotal);
 	}
 
 	/* Query vblank area. */
-	vbl = I915_READ(VBLANK(pipe));
+	vbl = I915_READ(VBLANK(cpu_transcoder));
 
 	/* Test position against vblank region. */
 	vbl_start = vbl & 0x1fff;
@@ -352,8 +357,7 @@ static void notify_ring(struct drm_device *dev,
 	if (i915_enable_hangcheck) {
 		dev_priv->hangcheck_count = 0;
 		mod_timer(&dev_priv->hangcheck_timer,
-			  jiffies +
-			  msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+			  round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES));
 	}
 }
 
@@ -374,7 +378,7 @@ static void gen6_pm_rps_work(struct work_struct *work)
 	if ((pm_iir & GEN6_PM_DEFERRED_EVENTS) == 0)
 		return;
 
-	mutex_lock(&dev_priv->dev->struct_mutex);
+	mutex_lock(&dev_priv->rps.hw_lock);
 
 	if (pm_iir & GEN6_PM_RP_UP_THRESHOLD)
 		new_delay = dev_priv->rps.cur_delay + 1;
@@ -389,7 +393,7 @@ static void gen6_pm_rps_work(struct work_struct *work)
 		gen6_set_rps(dev_priv->dev, new_delay);
 	}
 
-	mutex_unlock(&dev_priv->dev->struct_mutex);
+	mutex_unlock(&dev_priv->rps.hw_lock);
 }
 
 
@@ -405,7 +409,7 @@ static void gen6_pm_rps_work(struct work_struct *work)
 static void ivybridge_parity_work(struct work_struct *work)
 {
 	drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
-						    parity_error_work);
+						    l3_parity.error_work);
 	u32 error_status, row, bank, subbank;
 	char *parity_event[5];
 	uint32_t misccpctl;
@@ -469,7 +473,7 @@ static void ivybridge_handle_parity_error(struct drm_device *dev)
 	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
-	queue_work(dev_priv->wq, &dev_priv->parity_error_work);
+	queue_work(dev_priv->wq, &dev_priv->l3_parity.error_work);
 }
 
 static void snb_gt_irq_handler(struct drm_device *dev,
@@ -520,7 +524,7 @@ static void gen6_queue_rps_work(struct drm_i915_private *dev_priv,
 	queue_work(dev_priv->wq, &dev_priv->rps.work);
 }
 
-static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
+static irqreturn_t valleyview_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -606,6 +610,9 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir)
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int pipe;
 
+	if (pch_iir & SDE_HOTPLUG_MASK)
+		queue_work(dev_priv->wq, &dev_priv->hotplug_work);
+
 	if (pch_iir & SDE_AUDIO_POWER_MASK)
 		DRM_DEBUG_DRIVER("PCH audio power change on port %d\n",
 				 (pch_iir & SDE_AUDIO_POWER_MASK) >>
@@ -646,6 +653,9 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int pipe;
 
+	if (pch_iir & SDE_HOTPLUG_MASK_CPT)
+		queue_work(dev_priv->wq, &dev_priv->hotplug_work);
+
 	if (pch_iir & SDE_AUDIO_POWER_MASK_CPT)
 		DRM_DEBUG_DRIVER("PCH audio power change on port %d\n",
 				 (pch_iir & SDE_AUDIO_POWER_MASK_CPT) >>
@@ -670,7 +680,7 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
 					 I915_READ(FDI_RX_IIR(pipe)));
 }
 
-static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
+static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -709,8 +719,6 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
 		if (de_iir & DE_PCH_EVENT_IVB) {
 			u32 pch_iir = I915_READ(SDEIIR);
 
-			if (pch_iir & SDE_HOTPLUG_MASK_CPT)
-				queue_work(dev_priv->wq, &dev_priv->hotplug_work);
 			cpt_irq_handler(dev, pch_iir);
 
 			/* clear PCH hotplug event before clear CPU irq */
@@ -745,13 +753,12 @@ static void ilk_gt_irq_handler(struct drm_device *dev,
 		notify_ring(dev, &dev_priv->ring[VCS]);
 }
 
-static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
+static irqreturn_t ironlake_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int ret = IRQ_NONE;
 	u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir;
-	u32 hotplug_mask;
 
 	atomic_inc(&dev_priv->irq_received);
 
@@ -769,11 +776,6 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
 	    (!IS_GEN6(dev) || pm_iir == 0))
 		goto done;
 
-	if (HAS_PCH_CPT(dev))
-		hotplug_mask = SDE_HOTPLUG_MASK_CPT;
-	else
-		hotplug_mask = SDE_HOTPLUG_MASK;
-
 	ret = IRQ_HANDLED;
 
 	if (IS_GEN5(dev))
@@ -802,8 +804,6 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
 
 	/* check event from PCH */
 	if (de_iir & DE_PCH_EVENT) {
-		if (pch_iir & hotplug_mask)
-			queue_work(dev_priv->wq, &dev_priv->hotplug_work);
 		if (HAS_PCH_CPT(dev))
 			cpt_irq_handler(dev, pch_iir);
 		else
@@ -1751,7 +1751,7 @@ void i915_hangcheck_elapsed(unsigned long data)
 repeat:
 	/* Reset timer case chip hangs without another request being added */
 	mod_timer(&dev_priv->hangcheck_timer,
-		  jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+		  round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES));
 }
 
 /* drm_dma.h hooks
@@ -1956,6 +1956,7 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 	u32 enable_mask;
 	u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
 	u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV;
+	u32 render_irqs;
 	u16 msid;
 
 	enable_mask = I915_DISPLAY_PORT_INTERRUPT;
@@ -1995,21 +1996,12 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 	I915_WRITE(VLV_IIR, 0xffffffff);
 	I915_WRITE(VLV_IIR, 0xffffffff);
 
-	dev_priv->gt_irq_mask = ~0;
-
-	I915_WRITE(GTIIR, I915_READ(GTIIR));
 	I915_WRITE(GTIIR, I915_READ(GTIIR));
 	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
-	I915_WRITE(GTIER, GT_GEN6_BLT_FLUSHDW_NOTIFY_INTERRUPT |
-		   GT_GEN6_BLT_CS_ERROR_INTERRUPT |
-		   GT_GEN6_BLT_USER_INTERRUPT |
-		   GT_GEN6_BSD_USER_INTERRUPT |
-		   GT_GEN6_BSD_CS_ERROR_INTERRUPT |
-		   GT_GEN7_L3_PARITY_ERROR_INTERRUPT |
-		   GT_PIPE_NOTIFY |
-		   GT_RENDER_CS_ERROR_INTERRUPT |
-		   GT_SYNC_STATUS |
-		   GT_USER_INTERRUPT);
+
+	render_irqs = GT_USER_INTERRUPT | GEN6_BSD_USER_INTERRUPT |
+		GEN6_BLITTER_USER_INTERRUPT;
+	I915_WRITE(GTIER, render_irqs);
 	POSTING_READ(GTIER);
 
 	/* ack & enable invalid PTE error interrupts */
@@ -2019,7 +2011,6 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 #endif
 
 	I915_WRITE(VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
-#if 0 /* FIXME: check register definitions; some have moved */
 	/* Note HDMI and DP share bits */
 	if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
 		hotplug_en |= HDMIB_HOTPLUG_INT_EN;
@@ -2027,15 +2018,14 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 		hotplug_en |= HDMIC_HOTPLUG_INT_EN;
 	if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
 		hotplug_en |= HDMID_HOTPLUG_INT_EN;
-	if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
+	if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I915)
 		hotplug_en |= SDVOC_HOTPLUG_INT_EN;
-	if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
+	if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I915)
 		hotplug_en |= SDVOB_HOTPLUG_INT_EN;
 	if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
 		hotplug_en |= CRT_HOTPLUG_INT_EN;
 		hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
 	}
-#endif
 
 	I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
 
@@ -2129,7 +2119,7 @@ static int i8xx_irq_postinstall(struct drm_device *dev)
 	return 0;
 }
 
-static irqreturn_t i8xx_irq_handler(DRM_IRQ_ARGS)
+static irqreturn_t i8xx_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -2307,7 +2297,7 @@ static int i915_irq_postinstall(struct drm_device *dev)
 	return 0;
 }
 
-static irqreturn_t i915_irq_handler(DRM_IRQ_ARGS)
+static irqreturn_t i915_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -2545,7 +2535,7 @@ static int i965_irq_postinstall(struct drm_device *dev)
 	return 0;
 }
 
-static irqreturn_t i965_irq_handler(DRM_IRQ_ARGS)
+static irqreturn_t i965_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -2691,7 +2681,7 @@ void intel_irq_init(struct drm_device *dev)
 	INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
 	INIT_WORK(&dev_priv->error_work, i915_error_work_func);
 	INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work);
-	INIT_WORK(&dev_priv->parity_error_work, ivybridge_parity_work);
+	INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work);
 
 	dev->driver->get_vblank_counter = i915_get_vblank_counter;
 	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index a4162dd..9118bd1 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -26,6 +26,7 @@
 #define _I915_REG_H_
 
 #define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a)))
+#define _TRANSCODER(tran, a, b) ((a) + (tran)*((b)-(a)))
 
 #define _PORT(port, a, b) ((a) + (port)*((b)-(a)))
 
@@ -40,6 +41,14 @@
  */
 #define INTEL_GMCH_CTRL		0x52
 #define INTEL_GMCH_VGA_DISABLE  (1 << 1)
+#define SNB_GMCH_CTRL		0x50
+#define    SNB_GMCH_GGMS_SHIFT	8 /* GTT Graphics Memory Size */
+#define    SNB_GMCH_GGMS_MASK	0x3
+#define    SNB_GMCH_GMS_SHIFT   3 /* Graphics Mode Select */
+#define    SNB_GMCH_GMS_MASK    0x1f
+#define    IVB_GMCH_GMS_SHIFT   4
+#define    IVB_GMCH_GMS_MASK    0xf
+
 
 /* PCI config space */
 
@@ -105,23 +114,6 @@
 #define  GEN6_GRDOM_MEDIA		(1 << 2)
 #define  GEN6_GRDOM_BLT			(1 << 3)
 
-/* PPGTT stuff */
-#define GEN6_GTT_ADDR_ENCODE(addr)	((addr) | (((addr) >> 28) & 0xff0))
-
-#define GEN6_PDE_VALID			(1 << 0)
-#define GEN6_PDE_LARGE_PAGE		(2 << 0) /* use 32kb pages */
-/* gen6+ has bit 11-4 for physical addr bit 39-32 */
-#define GEN6_PDE_ADDR_ENCODE(addr)	GEN6_GTT_ADDR_ENCODE(addr)
-
-#define GEN6_PTE_VALID			(1 << 0)
-#define GEN6_PTE_UNCACHED		(1 << 1)
-#define HSW_PTE_UNCACHED		(0)
-#define GEN6_PTE_CACHE_LLC		(2 << 1)
-#define GEN6_PTE_CACHE_LLC_MLC		(3 << 1)
-#define GEN6_PTE_CACHE_BITS		(3 << 1)
-#define GEN6_PTE_GFDT			(1 << 3)
-#define GEN6_PTE_ADDR_ENCODE(addr)	GEN6_GTT_ADDR_ENCODE(addr)
-
 #define RING_PP_DIR_BASE(ring)		((ring)->mmio_base+0x228)
 #define RING_PP_DIR_BASE_READ(ring)	((ring)->mmio_base+0x518)
 #define RING_PP_DIR_DCLV(ring)		((ring)->mmio_base+0x220)
@@ -241,11 +233,18 @@
  */
 #define MI_LOAD_REGISTER_IMM(x)	MI_INSTR(0x22, 2*x-1)
 #define MI_FLUSH_DW		MI_INSTR(0x26, 1) /* for GEN6 */
-#define   MI_INVALIDATE_TLB	(1<<18)
-#define   MI_INVALIDATE_BSD	(1<<7)
+#define   MI_FLUSH_DW_STORE_INDEX	(1<<21)
+#define   MI_INVALIDATE_TLB		(1<<18)
+#define   MI_FLUSH_DW_OP_STOREDW	(1<<14)
+#define   MI_INVALIDATE_BSD		(1<<7)
+#define   MI_FLUSH_DW_USE_GTT		(1<<2)
+#define   MI_FLUSH_DW_USE_PPGTT		(0<<2)
 #define MI_BATCH_BUFFER		MI_INSTR(0x30, 1)
-#define   MI_BATCH_NON_SECURE	(1)
-#define   MI_BATCH_NON_SECURE_I965 (1<<8)
+#define   MI_BATCH_NON_SECURE		(1)
+/* for snb/ivb/vlv this also means "batch in ppgtt" when ppgtt is enabled. */
+#define   MI_BATCH_NON_SECURE_I965 	(1<<8)
+#define   MI_BATCH_PPGTT_HSW		(1<<8)
+#define   MI_BATCH_NON_SECURE_HSW 	(1<<13)
 #define MI_BATCH_BUFFER_START	MI_INSTR(0x31, 0)
 #define   MI_BATCH_GTT		    (2<<6) /* aliased with (1<<7) on gen4 */
 #define MI_SEMAPHORE_MBOX	MI_INSTR(0x16, 1) /* gen6+ */
@@ -369,6 +368,7 @@
 #define   DPIO_PLL_MODESEL_SHIFT	24 /* 3 bits */
 #define   DPIO_BIAS_CURRENT_CTL_SHIFT	21 /* 3 bits, always 0x7 */
 #define   DPIO_PLL_REFCLK_SEL_SHIFT	16 /* 2 bits */
+#define   DPIO_PLL_REFCLK_SEL_MASK	3
 #define   DPIO_DRIVER_CTL_SHIFT		12 /* always set to 0x8 */
 #define   DPIO_CLK_BIAS_CTL_SHIFT	8 /* always set to 0x5 */
 #define _DPIO_REFSFR_B			0x8034
@@ -384,6 +384,9 @@
 
 #define DPIO_FASTCLK_DISABLE		0x8100
 
+#define DPIO_DATA_CHANNEL1		0x8220
+#define DPIO_DATA_CHANNEL2		0x8420
+
 /*
  * Fence registers
  */
@@ -521,6 +524,7 @@
  */
 # define _3D_CHICKEN2_WM_READ_PIPELINED			(1 << 14)
 #define _3D_CHICKEN3	0x02090
+#define  _3D_CHICKEN_SF_DISABLE_OBJEND_CULL		(1 << 10)
 #define  _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL		(1 << 5)
 
 #define MI_MODE		0x0209c
@@ -547,6 +551,8 @@
 #define IIR		0x020a4
 #define IMR		0x020a8
 #define ISR		0x020ac
+#define VLV_GUNIT_CLOCK_GATE	0x182060
+#define   GCFG_DIS		(1<<8)
 #define VLV_IIR_RW	0x182084
 #define VLV_IER		0x1820a0
 #define VLV_IIR		0x1820a4
@@ -661,6 +667,7 @@
 #define   MI_ARB_DISPLAY_PRIORITY_B_A		(1 << 0)	/* display B > display A */
 
 #define CACHE_MODE_0	0x02120 /* 915+ only */
+#define   CM0_PIPELINED_RENDER_FLUSH_DISABLE (1<<8)
 #define   CM0_IZ_OPT_DISABLE      (1<<6)
 #define   CM0_ZR_OPT_DISABLE      (1<<5)
 #define	  CM0_STC_EVICT_DISABLE_LRA_SNB	(1<<5)
@@ -670,6 +677,8 @@
 #define   CM0_RC_OP_FLUSH_DISABLE (1<<0)
 #define BB_ADDR		0x02140 /* 8 bytes */
 #define GFX_FLSH_CNTL	0x02170 /* 915+ only */
+#define GFX_FLSH_CNTL_GEN6	0x101008
+#define   GFX_FLSH_CNTL_EN	(1<<0)
 #define ECOSKPD		0x021d0
 #define   ECO_GATING_CX_ONLY	(1<<3)
 #define   ECO_FLIP_DONE		(1<<0)
@@ -1559,14 +1568,14 @@
 #define _VSYNCSHIFT_B	0x61028
 
 
-#define HTOTAL(pipe) _PIPE(pipe, _HTOTAL_A, _HTOTAL_B)
-#define HBLANK(pipe) _PIPE(pipe, _HBLANK_A, _HBLANK_B)
-#define HSYNC(pipe) _PIPE(pipe, _HSYNC_A, _HSYNC_B)
-#define VTOTAL(pipe) _PIPE(pipe, _VTOTAL_A, _VTOTAL_B)
-#define VBLANK(pipe) _PIPE(pipe, _VBLANK_A, _VBLANK_B)
-#define VSYNC(pipe) _PIPE(pipe, _VSYNC_A, _VSYNC_B)
+#define HTOTAL(trans) _TRANSCODER(trans, _HTOTAL_A, _HTOTAL_B)
+#define HBLANK(trans) _TRANSCODER(trans, _HBLANK_A, _HBLANK_B)
+#define HSYNC(trans) _TRANSCODER(trans, _HSYNC_A, _HSYNC_B)
+#define VTOTAL(trans) _TRANSCODER(trans, _VTOTAL_A, _VTOTAL_B)
+#define VBLANK(trans) _TRANSCODER(trans, _VBLANK_A, _VBLANK_B)
+#define VSYNC(trans) _TRANSCODER(trans, _VSYNC_A, _VSYNC_B)
 #define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B)
-#define VSYNCSHIFT(pipe) _PIPE(pipe, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
+#define VSYNCSHIFT(trans) _TRANSCODER(trans, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
 
 /* VGA port control */
 #define ADPA			0x61100
@@ -2641,6 +2650,7 @@
 #define   PIPECONF_GAMMA		(1<<24)
 #define   PIPECONF_FORCE_BORDER	(1<<25)
 #define   PIPECONF_INTERLACE_MASK	(7 << 21)
+#define   PIPECONF_INTERLACE_MASK_HSW	(3 << 21)
 /* Note that pre-gen3 does not support interlaced display directly. Panel
  * fitting must be disabled on pre-ilk for interlaced. */
 #define   PIPECONF_PROGRESSIVE			(0 << 21)
@@ -2711,7 +2721,7 @@
 #define   PIPE_12BPC				(3 << 5)
 
 #define PIPESRC(pipe) _PIPE(pipe, _PIPEASRC, _PIPEBSRC)
-#define PIPECONF(pipe) _PIPE(pipe, _PIPEACONF, _PIPEBCONF)
+#define PIPECONF(tran) _TRANSCODER(tran, _PIPEACONF, _PIPEBCONF)
 #define PIPEDSL(pipe)  _PIPE(pipe, _PIPEADSL, _PIPEBDSL)
 #define PIPEFRAME(pipe) _PIPE(pipe, _PIPEAFRAMEHIGH, _PIPEBFRAMEHIGH)
 #define PIPEFRAMEPIXEL(pipe)  _PIPE(pipe, _PIPEAFRAMEPIXEL, _PIPEBFRAMEPIXEL)
@@ -2998,12 +3008,19 @@
 #define   DISPPLANE_GAMMA_ENABLE		(1<<30)
 #define   DISPPLANE_GAMMA_DISABLE		0
 #define   DISPPLANE_PIXFORMAT_MASK		(0xf<<26)
+#define   DISPPLANE_YUV422			(0x0<<26)
 #define   DISPPLANE_8BPP			(0x2<<26)
-#define   DISPPLANE_15_16BPP			(0x4<<26)
-#define   DISPPLANE_16BPP			(0x5<<26)
-#define   DISPPLANE_32BPP_NO_ALPHA		(0x6<<26)
-#define   DISPPLANE_32BPP			(0x7<<26)
-#define   DISPPLANE_32BPP_30BIT_NO_ALPHA	(0xa<<26)
+#define   DISPPLANE_BGRA555			(0x3<<26)
+#define   DISPPLANE_BGRX555			(0x4<<26)
+#define   DISPPLANE_BGRX565			(0x5<<26)
+#define   DISPPLANE_BGRX888			(0x6<<26)
+#define   DISPPLANE_BGRA888			(0x7<<26)
+#define   DISPPLANE_RGBX101010			(0x8<<26)
+#define   DISPPLANE_RGBA101010			(0x9<<26)
+#define   DISPPLANE_BGRX101010			(0xa<<26)
+#define   DISPPLANE_RGBX161616			(0xc<<26)
+#define   DISPPLANE_RGBX888			(0xe<<26)
+#define   DISPPLANE_RGBA888			(0xf<<26)
 #define   DISPPLANE_STEREO_ENABLE		(1<<25)
 #define   DISPPLANE_STEREO_DISABLE		0
 #define   DISPPLANE_SEL_PIPE_SHIFT		24
@@ -3024,6 +3041,8 @@
 #define _DSPASIZE		0x70190
 #define _DSPASURF		0x7019C /* 965+ only */
 #define _DSPATILEOFF		0x701A4 /* 965+ only */
+#define _DSPAOFFSET		0x701A4 /* HSW */
+#define _DSPASURFLIVE		0x701AC
 
 #define DSPCNTR(plane) _PIPE(plane, _DSPACNTR, _DSPBCNTR)
 #define DSPADDR(plane) _PIPE(plane, _DSPAADDR, _DSPBADDR)
@@ -3033,6 +3052,8 @@
 #define DSPSURF(plane) _PIPE(plane, _DSPASURF, _DSPBSURF)
 #define DSPTILEOFF(plane) _PIPE(plane, _DSPATILEOFF, _DSPBTILEOFF)
 #define DSPLINOFF(plane) DSPADDR(plane)
+#define DSPOFFSET(plane) _PIPE(plane, _DSPAOFFSET, _DSPBOFFSET)
+#define DSPSURFLIVE(plane) _PIPE(plane, _DSPASURFLIVE, _DSPBSURFLIVE)
 
 /* Display/Sprite base address macros */
 #define DISP_BASEADDR_MASK	(0xfffff000)
@@ -3078,6 +3099,8 @@
 #define _DSPBSIZE		0x71190
 #define _DSPBSURF		0x7119C
 #define _DSPBTILEOFF		0x711A4
+#define _DSPBOFFSET		0x711A4
+#define _DSPBSURFLIVE		0x711AC
 
 /* Sprite A control */
 #define _DVSACNTR		0x72180
@@ -3143,6 +3166,7 @@
 #define DVSTILEOFF(pipe) _PIPE(pipe, _DVSATILEOFF, _DVSBTILEOFF)
 #define DVSKEYVAL(pipe) _PIPE(pipe, _DVSAKEYVAL, _DVSBKEYVAL)
 #define DVSKEYMSK(pipe) _PIPE(pipe, _DVSAKEYMSK, _DVSBKEYMSK)
+#define DVSSURFLIVE(pipe) _PIPE(pipe, _DVSASURFLIVE, _DVSBSURFLIVE)
 
 #define _SPRA_CTL		0x70280
 #define   SPRITE_ENABLE			(1<<31)
@@ -3177,6 +3201,8 @@
 #define _SPRA_SURF		0x7029c
 #define _SPRA_KEYMAX		0x702a0
 #define _SPRA_TILEOFF		0x702a4
+#define _SPRA_OFFSET		0x702a4
+#define _SPRA_SURFLIVE		0x702ac
 #define _SPRA_SCALE		0x70304
 #define   SPRITE_SCALE_ENABLE	(1<<31)
 #define   SPRITE_FILTER_MASK	(3<<29)
@@ -3197,6 +3223,8 @@
 #define _SPRB_SURF		0x7129c
 #define _SPRB_KEYMAX		0x712a0
 #define _SPRB_TILEOFF		0x712a4
+#define _SPRB_OFFSET		0x712a4
+#define _SPRB_SURFLIVE		0x712ac
 #define _SPRB_SCALE		0x71304
 #define _SPRB_GAMC		0x71400
 
@@ -3210,8 +3238,10 @@
 #define SPRSURF(pipe) _PIPE(pipe, _SPRA_SURF, _SPRB_SURF)
 #define SPRKEYMAX(pipe) _PIPE(pipe, _SPRA_KEYMAX, _SPRB_KEYMAX)
 #define SPRTILEOFF(pipe) _PIPE(pipe, _SPRA_TILEOFF, _SPRB_TILEOFF)
+#define SPROFFSET(pipe) _PIPE(pipe, _SPRA_OFFSET, _SPRB_OFFSET)
 #define SPRSCALE(pipe) _PIPE(pipe, _SPRA_SCALE, _SPRB_SCALE)
 #define SPRGAMC(pipe) _PIPE(pipe, _SPRA_GAMC, _SPRB_GAMC)
+#define SPRSURFLIVE(pipe) _PIPE(pipe, _SPRA_SURFLIVE, _SPRB_SURFLIVE)
 
 /* VBIOS regs */
 #define VGACNTRL		0x71400
@@ -3246,12 +3276,6 @@
 #define DISPLAY_PORT_PLL_BIOS_1         0x46010
 #define DISPLAY_PORT_PLL_BIOS_2         0x46014
 
-#define PCH_DSPCLK_GATE_D	0x42020
-# define DPFCUNIT_CLOCK_GATE_DISABLE		(1 << 9)
-# define DPFCRUNIT_CLOCK_GATE_DISABLE		(1 << 8)
-# define DPFDUNIT_CLOCK_GATE_DISABLE		(1 << 7)
-# define DPARBUNIT_CLOCK_GATE_DISABLE		(1 << 5)
-
 #define PCH_3DCGDIS0		0x46020
 # define MARIUNIT_CLOCK_GATE_DISABLE		(1 << 18)
 # define SVSMUNIT_CLOCK_GATE_DISABLE		(1 << 1)
@@ -3301,14 +3325,14 @@
 #define _PIPEB_LINK_M2           0x61048
 #define _PIPEB_LINK_N2           0x6104c
 
-#define PIPE_DATA_M1(pipe) _PIPE(pipe, _PIPEA_DATA_M1, _PIPEB_DATA_M1)
-#define PIPE_DATA_N1(pipe) _PIPE(pipe, _PIPEA_DATA_N1, _PIPEB_DATA_N1)
-#define PIPE_DATA_M2(pipe) _PIPE(pipe, _PIPEA_DATA_M2, _PIPEB_DATA_M2)
-#define PIPE_DATA_N2(pipe) _PIPE(pipe, _PIPEA_DATA_N2, _PIPEB_DATA_N2)
-#define PIPE_LINK_M1(pipe) _PIPE(pipe, _PIPEA_LINK_M1, _PIPEB_LINK_M1)
-#define PIPE_LINK_N1(pipe) _PIPE(pipe, _PIPEA_LINK_N1, _PIPEB_LINK_N1)
-#define PIPE_LINK_M2(pipe) _PIPE(pipe, _PIPEA_LINK_M2, _PIPEB_LINK_M2)
-#define PIPE_LINK_N2(pipe) _PIPE(pipe, _PIPEA_LINK_N2, _PIPEB_LINK_N2)
+#define PIPE_DATA_M1(tran) _TRANSCODER(tran, _PIPEA_DATA_M1, _PIPEB_DATA_M1)
+#define PIPE_DATA_N1(tran) _TRANSCODER(tran, _PIPEA_DATA_N1, _PIPEB_DATA_N1)
+#define PIPE_DATA_M2(tran) _TRANSCODER(tran, _PIPEA_DATA_M2, _PIPEB_DATA_M2)
+#define PIPE_DATA_N2(tran) _TRANSCODER(tran, _PIPEA_DATA_N2, _PIPEB_DATA_N2)
+#define PIPE_LINK_M1(tran) _TRANSCODER(tran, _PIPEA_LINK_M1, _PIPEB_LINK_M1)
+#define PIPE_LINK_N1(tran) _TRANSCODER(tran, _PIPEA_LINK_N1, _PIPEB_LINK_N1)
+#define PIPE_LINK_M2(tran) _TRANSCODER(tran, _PIPEA_LINK_M2, _PIPEB_LINK_M2)
+#define PIPE_LINK_N2(tran) _TRANSCODER(tran, _PIPEA_LINK_N2, _PIPEB_LINK_N2)
 
 /* CPU panel fitter */
 /* IVB+ has 3 fitters, 0 is 7x5 capable, the other two only 3x3 */
@@ -3423,15 +3447,13 @@
 #define  ILK_HDCP_DISABLE		(1<<25)
 #define  ILK_eDP_A_DISABLE		(1<<24)
 #define  ILK_DESKTOP			(1<<23)
-#define ILK_DSPCLK_GATE		0x42020
-#define  IVB_VRHUNIT_CLK_GATE	(1<<28)
-#define  ILK_DPARB_CLK_GATE	(1<<5)
-#define  ILK_DPFD_CLK_GATE	(1<<7)
 
-/* According to spec this bit 7/8/9 of 0x42020 should be set to enable FBC */
-#define   ILK_CLK_FBC		(1<<7)
-#define   ILK_DPFC_DIS1		(1<<8)
-#define   ILK_DPFC_DIS2		(1<<9)
+#define ILK_DSPCLK_GATE_D			0x42020
+#define   ILK_VRHUNIT_CLOCK_GATE_DISABLE	(1 << 28)
+#define   ILK_DPFCUNIT_CLOCK_GATE_DISABLE	(1 << 9)
+#define   ILK_DPFCRUNIT_CLOCK_GATE_DISABLE	(1 << 8)
+#define   ILK_DPFDUNIT_CLOCK_GATE_ENABLE	(1 << 7)
+#define   ILK_DPARBUNIT_CLOCK_GATE_ENABLE	(1 << 5)
 
 #define IVB_CHICKEN3	0x4200c
 # define CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE	(1 << 5)
@@ -3447,14 +3469,21 @@
 
 #define GEN7_L3CNTLREG1				0xB01C
 #define  GEN7_WA_FOR_GEN7_L3_CONTROL			0x3C4FFF8C
+#define  GEN7_L3AGDIS				(1<<19)
 
 #define GEN7_L3_CHICKEN_MODE_REGISTER		0xB030
 #define  GEN7_WA_L3_CHICKEN_MODE				0x20000000
 
+#define GEN7_L3SQCREG4				0xb034
+#define  L3SQ_URB_READ_CAM_MATCH_DISABLE	(1<<27)
+
 /* WaCatErrorRejectionIssue */
 #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG		0x9030
 #define  GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB	(1<<11)
 
+#define HSW_FUSE_STRAP		0x42014
+#define  HSW_CDCLK_LIMIT	(1 << 24)
+
 /* PCH */
 
 /* south display engine interrupt: IBX */
@@ -3686,7 +3715,7 @@
 #define TVIDEO_DIP_DATA(pipe) _PIPE(pipe, _VIDEO_DIP_DATA_A, _VIDEO_DIP_DATA_B)
 #define TVIDEO_DIP_GCP(pipe) _PIPE(pipe, _VIDEO_DIP_GCP_A, _VIDEO_DIP_GCP_B)
 
-#define VLV_VIDEO_DIP_CTL_A		0x60220
+#define VLV_VIDEO_DIP_CTL_A		0x60200
 #define VLV_VIDEO_DIP_DATA_A		0x60208
 #define VLV_VIDEO_DIP_GDCP_PAYLOAD_A	0x60210
 
@@ -3795,16 +3824,22 @@
 #define  TRANS_6BPC             (2<<5)
 #define  TRANS_12BPC            (3<<5)
 
+#define _TRANSA_CHICKEN1	 0xf0060
+#define _TRANSB_CHICKEN1	 0xf1060
+#define TRANS_CHICKEN1(pipe) _PIPE(pipe, _TRANSA_CHICKEN1, _TRANSB_CHICKEN1)
+#define  TRANS_CHICKEN1_DP0UNIT_GC_DISABLE	(1<<4)
 #define _TRANSA_CHICKEN2	 0xf0064
 #define _TRANSB_CHICKEN2	 0xf1064
 #define TRANS_CHICKEN2(pipe) _PIPE(pipe, _TRANSA_CHICKEN2, _TRANSB_CHICKEN2)
-#define   TRANS_AUTOTRAIN_GEN_STALL_DIS	(1<<31)
+#define  TRANS_CHICKEN2_TIMING_OVERRIDE		(1<<31)
+
 
 #define SOUTH_CHICKEN1		0xc2000
 #define  FDIA_PHASE_SYNC_SHIFT_OVR	19
 #define  FDIA_PHASE_SYNC_SHIFT_EN	18
-#define FDI_PHASE_SYNC_OVR(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_OVR - ((pipe) * 2)))
-#define FDI_PHASE_SYNC_EN(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2)))
+#define  FDI_PHASE_SYNC_OVR(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_OVR - ((pipe) * 2)))
+#define  FDI_PHASE_SYNC_EN(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2)))
+#define  FDI_BC_BIFURCATION_SELECT	(1 << 12)
 #define SOUTH_CHICKEN2		0xc2004
 #define  DPLS_EDP_PPS_FIX_DIS	(1<<0)
 
@@ -3901,16 +3936,21 @@
 #define  FDI_PORT_WIDTH_2X_LPT			(1<<19)
 #define  FDI_PORT_WIDTH_1X_LPT			(0<<19)
 
-#define _FDI_RXA_MISC            0xf0010
-#define _FDI_RXB_MISC            0xf1010
+#define _FDI_RXA_MISC			0xf0010
+#define _FDI_RXB_MISC			0xf1010
+#define  FDI_RX_PWRDN_LANE1_MASK	(3<<26)
+#define  FDI_RX_PWRDN_LANE1_VAL(x)	((x)<<26)
+#define  FDI_RX_PWRDN_LANE0_MASK	(3<<24)
+#define  FDI_RX_PWRDN_LANE0_VAL(x)	((x)<<24)
+#define  FDI_RX_TP1_TO_TP2_48		(2<<20)
+#define  FDI_RX_TP1_TO_TP2_64		(3<<20)
+#define  FDI_RX_FDI_DELAY_90		(0x90<<0)
+#define FDI_RX_MISC(pipe) _PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC)
+
 #define _FDI_RXA_TUSIZE1         0xf0030
 #define _FDI_RXA_TUSIZE2         0xf0038
 #define _FDI_RXB_TUSIZE1         0xf1030
 #define _FDI_RXB_TUSIZE2         0xf1038
-#define  FDI_RX_TP1_TO_TP2_48	(2<<20)
-#define  FDI_RX_TP1_TO_TP2_64	(3<<20)
-#define  FDI_RX_FDI_DELAY_90	(0x90<<0)
-#define FDI_RX_MISC(pipe) _PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC)
 #define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1)
 #define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2)
 
@@ -4003,6 +4043,11 @@
 #define  PANEL_LIGHT_ON_DELAY_SHIFT	0
 
 #define PCH_PP_OFF_DELAYS	0xc720c
+#define  PANEL_POWER_PORT_SELECT_MASK	(0x3 << 30)
+#define  PANEL_POWER_PORT_LVDS		(0 << 30)
+#define  PANEL_POWER_PORT_DP_A		(1 << 30)
+#define  PANEL_POWER_PORT_DP_C		(2 << 30)
+#define  PANEL_POWER_PORT_DP_D		(3 << 30)
 #define  PANEL_POWER_DOWN_DELAY_MASK	(0x1fff0000)
 #define  PANEL_POWER_DOWN_DELAY_SHIFT	16
 #define  PANEL_LIGHT_OFF_DELAY_MASK	(0x1fff)
@@ -4050,7 +4095,7 @@
 #define TRANS_DP_CTL_A		0xe0300
 #define TRANS_DP_CTL_B		0xe1300
 #define TRANS_DP_CTL_C		0xe2300
-#define TRANS_DP_CTL(pipe)	(TRANS_DP_CTL_A + (pipe) * 0x01000)
+#define TRANS_DP_CTL(pipe)	_PIPE(pipe, TRANS_DP_CTL_A, TRANS_DP_CTL_B)
 #define  TRANS_DP_OUTPUT_ENABLE	(1<<31)
 #define  TRANS_DP_PORT_SEL_B	(0<<29)
 #define  TRANS_DP_PORT_SEL_C	(1<<29)
@@ -4108,6 +4153,8 @@
 #define  FORCEWAKE_ACK_HSW			0x130044
 #define  FORCEWAKE_ACK				0x130090
 #define  FORCEWAKE_MT				0xa188 /* multi-threaded */
+#define   FORCEWAKE_KERNEL			0x1
+#define   FORCEWAKE_USER			0x2
 #define  FORCEWAKE_MT_ACK			0x130040
 #define  ECOBUS					0xa180
 #define    FORCEWAKE_MT_ENABLE			(1<<5)
@@ -4220,6 +4267,10 @@
 #define   GEN6_READ_OC_PARAMS			0xc
 #define   GEN6_PCODE_WRITE_MIN_FREQ_TABLE	0x8
 #define   GEN6_PCODE_READ_MIN_FREQ_TABLE	0x9
+#define	  GEN6_PCODE_WRITE_RC6VIDS		0x4
+#define	  GEN6_PCODE_READ_RC6VIDS		0x5
+#define   GEN6_ENCODE_RC6_VID(mv)		(((mv) / 5) - 245) < 0 ?: 0
+#define   GEN6_DECODE_RC6_VID(vids)		(((vids) * 5) > 0 ? ((vids) * 5) + 245 : 0)
 #define GEN6_PCODE_DATA				0x138128
 #define   GEN6_PCODE_FREQ_IA_RATIO_SHIFT	8
 
@@ -4251,6 +4302,15 @@
 #define GEN7_L3LOG_BASE			0xB070
 #define GEN7_L3LOG_SIZE			0x80
 
+#define GEN7_HALF_SLICE_CHICKEN1	0xe100 /* IVB GT1 + VLV */
+#define GEN7_HALF_SLICE_CHICKEN1_GT2	0xf100
+#define   GEN7_MAX_PS_THREAD_DEP		(8<<12)
+#define   GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE	(1<<3)
+
+#define GEN7_ROW_CHICKEN2		0xe4f4
+#define GEN7_ROW_CHICKEN2_GT2		0xf4f4
+#define   DOP_CLOCK_GATING_DISABLE	(1<<0)
+
 #define G4X_AUD_VID_DID			0x62020
 #define INTEL_AUDIO_DEVCL		0x808629FB
 #define INTEL_AUDIO_DEVBLC		0x80862801
@@ -4380,33 +4440,39 @@
 #define HSW_PWR_WELL_CTL6			0x45414
 
 /* Per-pipe DDI Function Control */
-#define PIPE_DDI_FUNC_CTL_A		0x60400
-#define PIPE_DDI_FUNC_CTL_B		0x61400
-#define PIPE_DDI_FUNC_CTL_C		0x62400
-#define PIPE_DDI_FUNC_CTL_EDP		0x6F400
-#define DDI_FUNC_CTL(pipe) _PIPE(pipe, PIPE_DDI_FUNC_CTL_A, \
-				       PIPE_DDI_FUNC_CTL_B)
-#define  PIPE_DDI_FUNC_ENABLE		(1<<31)
+#define TRANS_DDI_FUNC_CTL_A		0x60400
+#define TRANS_DDI_FUNC_CTL_B		0x61400
+#define TRANS_DDI_FUNC_CTL_C		0x62400
+#define TRANS_DDI_FUNC_CTL_EDP		0x6F400
+#define TRANS_DDI_FUNC_CTL(tran) _TRANSCODER(tran, TRANS_DDI_FUNC_CTL_A, \
+						   TRANS_DDI_FUNC_CTL_B)
+#define  TRANS_DDI_FUNC_ENABLE		(1<<31)
 /* Those bits are ignored by pipe EDP since it can only connect to DDI A */
-#define  PIPE_DDI_PORT_MASK		(7<<28)
-#define  PIPE_DDI_SELECT_PORT(x)	((x)<<28)
-#define  PIPE_DDI_MODE_SELECT_MASK	(7<<24)
-#define  PIPE_DDI_MODE_SELECT_HDMI	(0<<24)
-#define  PIPE_DDI_MODE_SELECT_DVI	(1<<24)
-#define  PIPE_DDI_MODE_SELECT_DP_SST	(2<<24)
-#define  PIPE_DDI_MODE_SELECT_DP_MST	(3<<24)
-#define  PIPE_DDI_MODE_SELECT_FDI	(4<<24)
-#define  PIPE_DDI_BPC_MASK		(7<<20)
-#define  PIPE_DDI_BPC_8			(0<<20)
-#define  PIPE_DDI_BPC_10		(1<<20)
-#define  PIPE_DDI_BPC_6			(2<<20)
-#define  PIPE_DDI_BPC_12		(3<<20)
-#define  PIPE_DDI_PVSYNC		(1<<17)
-#define  PIPE_DDI_PHSYNC		(1<<16)
-#define  PIPE_DDI_BFI_ENABLE		(1<<4)
-#define  PIPE_DDI_PORT_WIDTH_X1		(0<<1)
-#define  PIPE_DDI_PORT_WIDTH_X2		(1<<1)
-#define  PIPE_DDI_PORT_WIDTH_X4		(3<<1)
+#define  TRANS_DDI_PORT_MASK		(7<<28)
+#define  TRANS_DDI_SELECT_PORT(x)	((x)<<28)
+#define  TRANS_DDI_PORT_NONE		(0<<28)
+#define  TRANS_DDI_MODE_SELECT_MASK	(7<<24)
+#define  TRANS_DDI_MODE_SELECT_HDMI	(0<<24)
+#define  TRANS_DDI_MODE_SELECT_DVI	(1<<24)
+#define  TRANS_DDI_MODE_SELECT_DP_SST	(2<<24)
+#define  TRANS_DDI_MODE_SELECT_DP_MST	(3<<24)
+#define  TRANS_DDI_MODE_SELECT_FDI	(4<<24)
+#define  TRANS_DDI_BPC_MASK		(7<<20)
+#define  TRANS_DDI_BPC_8		(0<<20)
+#define  TRANS_DDI_BPC_10		(1<<20)
+#define  TRANS_DDI_BPC_6		(2<<20)
+#define  TRANS_DDI_BPC_12		(3<<20)
+#define  TRANS_DDI_PVSYNC		(1<<17)
+#define  TRANS_DDI_PHSYNC		(1<<16)
+#define  TRANS_DDI_EDP_INPUT_MASK	(7<<12)
+#define  TRANS_DDI_EDP_INPUT_A_ON	(0<<12)
+#define  TRANS_DDI_EDP_INPUT_A_ONOFF	(4<<12)
+#define  TRANS_DDI_EDP_INPUT_B_ONOFF	(5<<12)
+#define  TRANS_DDI_EDP_INPUT_C_ONOFF	(6<<12)
+#define  TRANS_DDI_BFI_ENABLE		(1<<4)
+#define  TRANS_DDI_PORT_WIDTH_X1	(0<<1)
+#define  TRANS_DDI_PORT_WIDTH_X2	(1<<1)
+#define  TRANS_DDI_PORT_WIDTH_X4	(3<<1)
 
 /* DisplayPort Transport Control */
 #define DP_TP_CTL_A			0x64040
@@ -4420,12 +4486,16 @@
 #define  DP_TP_CTL_LINK_TRAIN_MASK		(7<<8)
 #define  DP_TP_CTL_LINK_TRAIN_PAT1		(0<<8)
 #define  DP_TP_CTL_LINK_TRAIN_PAT2		(1<<8)
+#define  DP_TP_CTL_LINK_TRAIN_PAT3		(4<<8)
+#define  DP_TP_CTL_LINK_TRAIN_IDLE		(2<<8)
 #define  DP_TP_CTL_LINK_TRAIN_NORMAL		(3<<8)
+#define  DP_TP_CTL_SCRAMBLE_DISABLE		(1<<7)
 
 /* DisplayPort Transport Status */
 #define DP_TP_STATUS_A			0x64044
 #define DP_TP_STATUS_B			0x64144
 #define DP_TP_STATUS(port) _PORT(port, DP_TP_STATUS_A, DP_TP_STATUS_B)
+#define  DP_TP_STATUS_IDLE_DONE		(1<<25)
 #define  DP_TP_STATUS_AUTOTRAIN_DONE	(1<<12)
 
 /* DDI Buffer Control */
@@ -4490,8 +4560,8 @@
 /* SPLL */
 #define SPLL_CTL			0x46020
 #define  SPLL_PLL_ENABLE		(1<<31)
-#define  SPLL_PLL_SCC			(1<<28)
-#define  SPLL_PLL_NON_SCC		(2<<28)
+#define  SPLL_PLL_SSC			(1<<28)
+#define  SPLL_PLL_NON_SSC		(2<<28)
 #define  SPLL_PLL_FREQ_810MHz		(0<<26)
 #define  SPLL_PLL_FREQ_1350MHz		(1<<26)
 
@@ -4500,7 +4570,7 @@
 #define WRPLL_CTL2			0x46060
 #define  WRPLL_PLL_ENABLE		(1<<31)
 #define  WRPLL_PLL_SELECT_SSC		(0x01<<28)
-#define  WRPLL_PLL_SELECT_NON_SCC	(0x02<<28)
+#define  WRPLL_PLL_SELECT_NON_SSC	(0x02<<28)
 #define  WRPLL_PLL_SELECT_LCPLL_2700	(0x03<<28)
 /* WRPLL divider programming */
 #define  WRPLL_DIVIDER_REFERENCE(x)	((x)<<0)
@@ -4517,21 +4587,36 @@
 #define  PORT_CLK_SEL_SPLL		(3<<29)
 #define  PORT_CLK_SEL_WRPLL1		(4<<29)
 #define  PORT_CLK_SEL_WRPLL2		(5<<29)
-
-/* Pipe clock selection */
-#define PIPE_CLK_SEL_A			0x46140
-#define PIPE_CLK_SEL_B			0x46144
-#define PIPE_CLK_SEL(pipe) _PIPE(pipe, PIPE_CLK_SEL_A, PIPE_CLK_SEL_B)
-/* For each pipe, we need to select the corresponding port clock */
-#define  PIPE_CLK_SEL_DISABLED		(0x0<<29)
-#define  PIPE_CLK_SEL_PORT(x)		((x+1)<<29)
+#define  PORT_CLK_SEL_NONE		(7<<29)
+
+/* Transcoder clock selection */
+#define TRANS_CLK_SEL_A			0x46140
+#define TRANS_CLK_SEL_B			0x46144
+#define TRANS_CLK_SEL(tran) _TRANSCODER(tran, TRANS_CLK_SEL_A, TRANS_CLK_SEL_B)
+/* For each transcoder, we need to select the corresponding port clock */
+#define  TRANS_CLK_SEL_DISABLED		(0x0<<29)
+#define  TRANS_CLK_SEL_PORT(x)		((x+1)<<29)
+
+#define _TRANSA_MSA_MISC		0x60410
+#define _TRANSB_MSA_MISC		0x61410
+#define TRANS_MSA_MISC(tran) _TRANSCODER(tran, _TRANSA_MSA_MISC, \
+					       _TRANSB_MSA_MISC)
+#define  TRANS_MSA_SYNC_CLK		(1<<0)
+#define  TRANS_MSA_6_BPC		(0<<5)
+#define  TRANS_MSA_8_BPC		(1<<5)
+#define  TRANS_MSA_10_BPC		(2<<5)
+#define  TRANS_MSA_12_BPC		(3<<5)
+#define  TRANS_MSA_16_BPC		(4<<5)
 
 /* LCPLL Control */
 #define LCPLL_CTL			0x130040
 #define  LCPLL_PLL_DISABLE		(1<<31)
 #define  LCPLL_PLL_LOCK			(1<<30)
+#define  LCPLL_CLK_FREQ_MASK		(3<<26)
+#define  LCPLL_CLK_FREQ_450		(0<<26)
 #define  LCPLL_CD_CLOCK_DISABLE		(1<<25)
 #define  LCPLL_CD2X_CLOCK_DISABLE	(1<<23)
+#define  LCPLL_CD_SOURCE_FCLK		(1<<21)
 
 /* Pipe WM_LINETIME - watermark line time */
 #define PIPE_WM_LINETIME_A		0x45270
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 5854bdd..a818eba 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -60,9 +60,9 @@ static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
 		reg = (pipe == PIPE_A) ? _LGC_PALETTE_A : _LGC_PALETTE_B;
 
 	if (pipe == PIPE_A)
-		array = dev_priv->save_palette_a;
+		array = dev_priv->regfile.save_palette_a;
 	else
-		array = dev_priv->save_palette_b;
+		array = dev_priv->regfile.save_palette_b;
 
 	for (i = 0; i < 256; i++)
 		array[i] = I915_READ(reg + (i << 2));
@@ -82,9 +82,9 @@ static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
 		reg = (pipe == PIPE_A) ? _LGC_PALETTE_A : _LGC_PALETTE_B;
 
 	if (pipe == PIPE_A)
-		array = dev_priv->save_palette_a;
+		array = dev_priv->regfile.save_palette_a;
 	else
-		array = dev_priv->save_palette_b;
+		array = dev_priv->regfile.save_palette_b;
 
 	for (i = 0; i < 256; i++)
 		I915_WRITE(reg + (i << 2), array[i]);
@@ -131,11 +131,11 @@ static void i915_save_vga(struct drm_device *dev)
 	u16 cr_index, cr_data, st01;
 
 	/* VGA color palette registers */
-	dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK);
+	dev_priv->regfile.saveDACMASK = I915_READ8(VGA_DACMASK);
 
 	/* MSR bits */
-	dev_priv->saveMSR = I915_READ8(VGA_MSR_READ);
-	if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
+	dev_priv->regfile.saveMSR = I915_READ8(VGA_MSR_READ);
+	if (dev_priv->regfile.saveMSR & VGA_MSR_CGA_MODE) {
 		cr_index = VGA_CR_INDEX_CGA;
 		cr_data = VGA_CR_DATA_CGA;
 		st01 = VGA_ST01_CGA;
@@ -150,35 +150,35 @@ static void i915_save_vga(struct drm_device *dev)
 			   i915_read_indexed(dev, cr_index, cr_data, 0x11) &
 			   (~0x80));
 	for (i = 0; i <= 0x24; i++)
-		dev_priv->saveCR[i] =
+		dev_priv->regfile.saveCR[i] =
 			i915_read_indexed(dev, cr_index, cr_data, i);
 	/* Make sure we don't turn off CR group 0 writes */
-	dev_priv->saveCR[0x11] &= ~0x80;
+	dev_priv->regfile.saveCR[0x11] &= ~0x80;
 
 	/* Attribute controller registers */
 	I915_READ8(st01);
-	dev_priv->saveAR_INDEX = I915_READ8(VGA_AR_INDEX);
+	dev_priv->regfile.saveAR_INDEX = I915_READ8(VGA_AR_INDEX);
 	for (i = 0; i <= 0x14; i++)
-		dev_priv->saveAR[i] = i915_read_ar(dev, st01, i, 0);
+		dev_priv->regfile.saveAR[i] = i915_read_ar(dev, st01, i, 0);
 	I915_READ8(st01);
-	I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX);
+	I915_WRITE8(VGA_AR_INDEX, dev_priv->regfile.saveAR_INDEX);
 	I915_READ8(st01);
 
 	/* Graphics controller registers */
 	for (i = 0; i < 9; i++)
-		dev_priv->saveGR[i] =
+		dev_priv->regfile.saveGR[i] =
 			i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i);
 
-	dev_priv->saveGR[0x10] =
+	dev_priv->regfile.saveGR[0x10] =
 		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10);
-	dev_priv->saveGR[0x11] =
+	dev_priv->regfile.saveGR[0x11] =
 		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11);
-	dev_priv->saveGR[0x18] =
+	dev_priv->regfile.saveGR[0x18] =
 		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18);
 
 	/* Sequencer registers */
 	for (i = 0; i < 8; i++)
-		dev_priv->saveSR[i] =
+		dev_priv->regfile.saveSR[i] =
 			i915_read_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i);
 }
 
@@ -189,8 +189,8 @@ static void i915_restore_vga(struct drm_device *dev)
 	u16 cr_index, cr_data, st01;
 
 	/* MSR bits */
-	I915_WRITE8(VGA_MSR_WRITE, dev_priv->saveMSR);
-	if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
+	I915_WRITE8(VGA_MSR_WRITE, dev_priv->regfile.saveMSR);
+	if (dev_priv->regfile.saveMSR & VGA_MSR_CGA_MODE) {
 		cr_index = VGA_CR_INDEX_CGA;
 		cr_data = VGA_CR_DATA_CGA;
 		st01 = VGA_ST01_CGA;
@@ -203,36 +203,36 @@ static void i915_restore_vga(struct drm_device *dev)
 	/* Sequencer registers, don't write SR07 */
 	for (i = 0; i < 7; i++)
 		i915_write_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i,
-				   dev_priv->saveSR[i]);
+				   dev_priv->regfile.saveSR[i]);
 
 	/* CRT controller regs */
 	/* Enable CR group 0 writes */
-	i915_write_indexed(dev, cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]);
+	i915_write_indexed(dev, cr_index, cr_data, 0x11, dev_priv->regfile.saveCR[0x11]);
 	for (i = 0; i <= 0x24; i++)
-		i915_write_indexed(dev, cr_index, cr_data, i, dev_priv->saveCR[i]);
+		i915_write_indexed(dev, cr_index, cr_data, i, dev_priv->regfile.saveCR[i]);
 
 	/* Graphics controller regs */
 	for (i = 0; i < 9; i++)
 		i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i,
-				   dev_priv->saveGR[i]);
+				   dev_priv->regfile.saveGR[i]);
 
 	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10,
-			   dev_priv->saveGR[0x10]);
+			   dev_priv->regfile.saveGR[0x10]);
 	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11,
-			   dev_priv->saveGR[0x11]);
+			   dev_priv->regfile.saveGR[0x11]);
 	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18,
-			   dev_priv->saveGR[0x18]);
+			   dev_priv->regfile.saveGR[0x18]);
 
 	/* Attribute controller registers */
 	I915_READ8(st01); /* switch back to index mode */
 	for (i = 0; i <= 0x14; i++)
-		i915_write_ar(dev, st01, i, dev_priv->saveAR[i], 0);
+		i915_write_ar(dev, st01, i, dev_priv->regfile.saveAR[i], 0);
 	I915_READ8(st01); /* switch back to index mode */
-	I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX | 0x20);
+	I915_WRITE8(VGA_AR_INDEX, dev_priv->regfile.saveAR_INDEX | 0x20);
 	I915_READ8(st01);
 
 	/* VGA color palette registers */
-	I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
+	I915_WRITE8(VGA_DACMASK, dev_priv->regfile.saveDACMASK);
 }
 
 static void i915_save_modeset_reg(struct drm_device *dev)
@@ -244,156 +244,162 @@ static void i915_save_modeset_reg(struct drm_device *dev)
 		return;
 
 	/* Cursor state */
-	dev_priv->saveCURACNTR = I915_READ(_CURACNTR);
-	dev_priv->saveCURAPOS = I915_READ(_CURAPOS);
-	dev_priv->saveCURABASE = I915_READ(_CURABASE);
-	dev_priv->saveCURBCNTR = I915_READ(_CURBCNTR);
-	dev_priv->saveCURBPOS = I915_READ(_CURBPOS);
-	dev_priv->saveCURBBASE = I915_READ(_CURBBASE);
+	dev_priv->regfile.saveCURACNTR = I915_READ(_CURACNTR);
+	dev_priv->regfile.saveCURAPOS = I915_READ(_CURAPOS);
+	dev_priv->regfile.saveCURABASE = I915_READ(_CURABASE);
+	dev_priv->regfile.saveCURBCNTR = I915_READ(_CURBCNTR);
+	dev_priv->regfile.saveCURBPOS = I915_READ(_CURBPOS);
+	dev_priv->regfile.saveCURBBASE = I915_READ(_CURBBASE);
 	if (IS_GEN2(dev))
-		dev_priv->saveCURSIZE = I915_READ(CURSIZE);
+		dev_priv->regfile.saveCURSIZE = I915_READ(CURSIZE);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL);
-		dev_priv->saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL);
+		dev_priv->regfile.savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL);
+		dev_priv->regfile.saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL);
 	}
 
 	/* Pipe & plane A info */
-	dev_priv->savePIPEACONF = I915_READ(_PIPEACONF);
-	dev_priv->savePIPEASRC = I915_READ(_PIPEASRC);
+	dev_priv->regfile.savePIPEACONF = I915_READ(_PIPEACONF);
+	dev_priv->regfile.savePIPEASRC = I915_READ(_PIPEASRC);
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->saveFPA0 = I915_READ(_PCH_FPA0);
-		dev_priv->saveFPA1 = I915_READ(_PCH_FPA1);
-		dev_priv->saveDPLL_A = I915_READ(_PCH_DPLL_A);
+		dev_priv->regfile.saveFPA0 = I915_READ(_PCH_FPA0);
+		dev_priv->regfile.saveFPA1 = I915_READ(_PCH_FPA1);
+		dev_priv->regfile.saveDPLL_A = I915_READ(_PCH_DPLL_A);
 	} else {
-		dev_priv->saveFPA0 = I915_READ(_FPA0);
-		dev_priv->saveFPA1 = I915_READ(_FPA1);
-		dev_priv->saveDPLL_A = I915_READ(_DPLL_A);
+		dev_priv->regfile.saveFPA0 = I915_READ(_FPA0);
+		dev_priv->regfile.saveFPA1 = I915_READ(_FPA1);
+		dev_priv->regfile.saveDPLL_A = I915_READ(_DPLL_A);
 	}
 	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
-		dev_priv->saveDPLL_A_MD = I915_READ(_DPLL_A_MD);
-	dev_priv->saveHTOTAL_A = I915_READ(_HTOTAL_A);
-	dev_priv->saveHBLANK_A = I915_READ(_HBLANK_A);
-	dev_priv->saveHSYNC_A = I915_READ(_HSYNC_A);
-	dev_priv->saveVTOTAL_A = I915_READ(_VTOTAL_A);
-	dev_priv->saveVBLANK_A = I915_READ(_VBLANK_A);
-	dev_priv->saveVSYNC_A = I915_READ(_VSYNC_A);
+		dev_priv->regfile.saveDPLL_A_MD = I915_READ(_DPLL_A_MD);
+	dev_priv->regfile.saveHTOTAL_A = I915_READ(_HTOTAL_A);
+	dev_priv->regfile.saveHBLANK_A = I915_READ(_HBLANK_A);
+	dev_priv->regfile.saveHSYNC_A = I915_READ(_HSYNC_A);
+	dev_priv->regfile.saveVTOTAL_A = I915_READ(_VTOTAL_A);
+	dev_priv->regfile.saveVBLANK_A = I915_READ(_VBLANK_A);
+	dev_priv->regfile.saveVSYNC_A = I915_READ(_VSYNC_A);
 	if (!HAS_PCH_SPLIT(dev))
-		dev_priv->saveBCLRPAT_A = I915_READ(_BCLRPAT_A);
+		dev_priv->regfile.saveBCLRPAT_A = I915_READ(_BCLRPAT_A);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->savePIPEA_DATA_M1 = I915_READ(_PIPEA_DATA_M1);
-		dev_priv->savePIPEA_DATA_N1 = I915_READ(_PIPEA_DATA_N1);
-		dev_priv->savePIPEA_LINK_M1 = I915_READ(_PIPEA_LINK_M1);
-		dev_priv->savePIPEA_LINK_N1 = I915_READ(_PIPEA_LINK_N1);
-
-		dev_priv->saveFDI_TXA_CTL = I915_READ(_FDI_TXA_CTL);
-		dev_priv->saveFDI_RXA_CTL = I915_READ(_FDI_RXA_CTL);
-
-		dev_priv->savePFA_CTL_1 = I915_READ(_PFA_CTL_1);
-		dev_priv->savePFA_WIN_SZ = I915_READ(_PFA_WIN_SZ);
-		dev_priv->savePFA_WIN_POS = I915_READ(_PFA_WIN_POS);
-
-		dev_priv->saveTRANSACONF = I915_READ(_TRANSACONF);
-		dev_priv->saveTRANS_HTOTAL_A = I915_READ(_TRANS_HTOTAL_A);
-		dev_priv->saveTRANS_HBLANK_A = I915_READ(_TRANS_HBLANK_A);
-		dev_priv->saveTRANS_HSYNC_A = I915_READ(_TRANS_HSYNC_A);
-		dev_priv->saveTRANS_VTOTAL_A = I915_READ(_TRANS_VTOTAL_A);
-		dev_priv->saveTRANS_VBLANK_A = I915_READ(_TRANS_VBLANK_A);
-		dev_priv->saveTRANS_VSYNC_A = I915_READ(_TRANS_VSYNC_A);
-	}
-
-	dev_priv->saveDSPACNTR = I915_READ(_DSPACNTR);
-	dev_priv->saveDSPASTRIDE = I915_READ(_DSPASTRIDE);
-	dev_priv->saveDSPASIZE = I915_READ(_DSPASIZE);
-	dev_priv->saveDSPAPOS = I915_READ(_DSPAPOS);
-	dev_priv->saveDSPAADDR = I915_READ(_DSPAADDR);
+		dev_priv->regfile.savePIPEA_DATA_M1 = I915_READ(_PIPEA_DATA_M1);
+		dev_priv->regfile.savePIPEA_DATA_N1 = I915_READ(_PIPEA_DATA_N1);
+		dev_priv->regfile.savePIPEA_LINK_M1 = I915_READ(_PIPEA_LINK_M1);
+		dev_priv->regfile.savePIPEA_LINK_N1 = I915_READ(_PIPEA_LINK_N1);
+
+		dev_priv->regfile.saveFDI_TXA_CTL = I915_READ(_FDI_TXA_CTL);
+		dev_priv->regfile.saveFDI_RXA_CTL = I915_READ(_FDI_RXA_CTL);
+
+		dev_priv->regfile.savePFA_CTL_1 = I915_READ(_PFA_CTL_1);
+		dev_priv->regfile.savePFA_WIN_SZ = I915_READ(_PFA_WIN_SZ);
+		dev_priv->regfile.savePFA_WIN_POS = I915_READ(_PFA_WIN_POS);
+
+		dev_priv->regfile.saveTRANSACONF = I915_READ(_TRANSACONF);
+		dev_priv->regfile.saveTRANS_HTOTAL_A = I915_READ(_TRANS_HTOTAL_A);
+		dev_priv->regfile.saveTRANS_HBLANK_A = I915_READ(_TRANS_HBLANK_A);
+		dev_priv->regfile.saveTRANS_HSYNC_A = I915_READ(_TRANS_HSYNC_A);
+		dev_priv->regfile.saveTRANS_VTOTAL_A = I915_READ(_TRANS_VTOTAL_A);
+		dev_priv->regfile.saveTRANS_VBLANK_A = I915_READ(_TRANS_VBLANK_A);
+		dev_priv->regfile.saveTRANS_VSYNC_A = I915_READ(_TRANS_VSYNC_A);
+	}
+
+	dev_priv->regfile.saveDSPACNTR = I915_READ(_DSPACNTR);
+	dev_priv->regfile.saveDSPASTRIDE = I915_READ(_DSPASTRIDE);
+	dev_priv->regfile.saveDSPASIZE = I915_READ(_DSPASIZE);
+	dev_priv->regfile.saveDSPAPOS = I915_READ(_DSPAPOS);
+	dev_priv->regfile.saveDSPAADDR = I915_READ(_DSPAADDR);
 	if (INTEL_INFO(dev)->gen >= 4) {
-		dev_priv->saveDSPASURF = I915_READ(_DSPASURF);
-		dev_priv->saveDSPATILEOFF = I915_READ(_DSPATILEOFF);
+		dev_priv->regfile.saveDSPASURF = I915_READ(_DSPASURF);
+		dev_priv->regfile.saveDSPATILEOFF = I915_READ(_DSPATILEOFF);
 	}
 	i915_save_palette(dev, PIPE_A);
-	dev_priv->savePIPEASTAT = I915_READ(_PIPEASTAT);
+	dev_priv->regfile.savePIPEASTAT = I915_READ(_PIPEASTAT);
 
 	/* Pipe & plane B info */
-	dev_priv->savePIPEBCONF = I915_READ(_PIPEBCONF);
-	dev_priv->savePIPEBSRC = I915_READ(_PIPEBSRC);
+	dev_priv->regfile.savePIPEBCONF = I915_READ(_PIPEBCONF);
+	dev_priv->regfile.savePIPEBSRC = I915_READ(_PIPEBSRC);
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->saveFPB0 = I915_READ(_PCH_FPB0);
-		dev_priv->saveFPB1 = I915_READ(_PCH_FPB1);
-		dev_priv->saveDPLL_B = I915_READ(_PCH_DPLL_B);
+		dev_priv->regfile.saveFPB0 = I915_READ(_PCH_FPB0);
+		dev_priv->regfile.saveFPB1 = I915_READ(_PCH_FPB1);
+		dev_priv->regfile.saveDPLL_B = I915_READ(_PCH_DPLL_B);
 	} else {
-		dev_priv->saveFPB0 = I915_READ(_FPB0);
-		dev_priv->saveFPB1 = I915_READ(_FPB1);
-		dev_priv->saveDPLL_B = I915_READ(_DPLL_B);
+		dev_priv->regfile.saveFPB0 = I915_READ(_FPB0);
+		dev_priv->regfile.saveFPB1 = I915_READ(_FPB1);
+		dev_priv->regfile.saveDPLL_B = I915_READ(_DPLL_B);
 	}
 	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
-		dev_priv->saveDPLL_B_MD = I915_READ(_DPLL_B_MD);
-	dev_priv->saveHTOTAL_B = I915_READ(_HTOTAL_B);
-	dev_priv->saveHBLANK_B = I915_READ(_HBLANK_B);
-	dev_priv->saveHSYNC_B = I915_READ(_HSYNC_B);
-	dev_priv->saveVTOTAL_B = I915_READ(_VTOTAL_B);
-	dev_priv->saveVBLANK_B = I915_READ(_VBLANK_B);
-	dev_priv->saveVSYNC_B = I915_READ(_VSYNC_B);
+		dev_priv->regfile.saveDPLL_B_MD = I915_READ(_DPLL_B_MD);
+	dev_priv->regfile.saveHTOTAL_B = I915_READ(_HTOTAL_B);
+	dev_priv->regfile.saveHBLANK_B = I915_READ(_HBLANK_B);
+	dev_priv->regfile.saveHSYNC_B = I915_READ(_HSYNC_B);
+	dev_priv->regfile.saveVTOTAL_B = I915_READ(_VTOTAL_B);
+	dev_priv->regfile.saveVBLANK_B = I915_READ(_VBLANK_B);
+	dev_priv->regfile.saveVSYNC_B = I915_READ(_VSYNC_B);
 	if (!HAS_PCH_SPLIT(dev))
-		dev_priv->saveBCLRPAT_B = I915_READ(_BCLRPAT_B);
+		dev_priv->regfile.saveBCLRPAT_B = I915_READ(_BCLRPAT_B);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->savePIPEB_DATA_M1 = I915_READ(_PIPEB_DATA_M1);
-		dev_priv->savePIPEB_DATA_N1 = I915_READ(_PIPEB_DATA_N1);
-		dev_priv->savePIPEB_LINK_M1 = I915_READ(_PIPEB_LINK_M1);
-		dev_priv->savePIPEB_LINK_N1 = I915_READ(_PIPEB_LINK_N1);
-
-		dev_priv->saveFDI_TXB_CTL = I915_READ(_FDI_TXB_CTL);
-		dev_priv->saveFDI_RXB_CTL = I915_READ(_FDI_RXB_CTL);
-
-		dev_priv->savePFB_CTL_1 = I915_READ(_PFB_CTL_1);
-		dev_priv->savePFB_WIN_SZ = I915_READ(_PFB_WIN_SZ);
-		dev_priv->savePFB_WIN_POS = I915_READ(_PFB_WIN_POS);
-
-		dev_priv->saveTRANSBCONF = I915_READ(_TRANSBCONF);
-		dev_priv->saveTRANS_HTOTAL_B = I915_READ(_TRANS_HTOTAL_B);
-		dev_priv->saveTRANS_HBLANK_B = I915_READ(_TRANS_HBLANK_B);
-		dev_priv->saveTRANS_HSYNC_B = I915_READ(_TRANS_HSYNC_B);
-		dev_priv->saveTRANS_VTOTAL_B = I915_READ(_TRANS_VTOTAL_B);
-		dev_priv->saveTRANS_VBLANK_B = I915_READ(_TRANS_VBLANK_B);
-		dev_priv->saveTRANS_VSYNC_B = I915_READ(_TRANS_VSYNC_B);
-	}
-
-	dev_priv->saveDSPBCNTR = I915_READ(_DSPBCNTR);
-	dev_priv->saveDSPBSTRIDE = I915_READ(_DSPBSTRIDE);
-	dev_priv->saveDSPBSIZE = I915_READ(_DSPBSIZE);
-	dev_priv->saveDSPBPOS = I915_READ(_DSPBPOS);
-	dev_priv->saveDSPBADDR = I915_READ(_DSPBADDR);
+		dev_priv->regfile.savePIPEB_DATA_M1 = I915_READ(_PIPEB_DATA_M1);
+		dev_priv->regfile.savePIPEB_DATA_N1 = I915_READ(_PIPEB_DATA_N1);
+		dev_priv->regfile.savePIPEB_LINK_M1 = I915_READ(_PIPEB_LINK_M1);
+		dev_priv->regfile.savePIPEB_LINK_N1 = I915_READ(_PIPEB_LINK_N1);
+
+		dev_priv->regfile.saveFDI_TXB_CTL = I915_READ(_FDI_TXB_CTL);
+		dev_priv->regfile.saveFDI_RXB_CTL = I915_READ(_FDI_RXB_CTL);
+
+		dev_priv->regfile.savePFB_CTL_1 = I915_READ(_PFB_CTL_1);
+		dev_priv->regfile.savePFB_WIN_SZ = I915_READ(_PFB_WIN_SZ);
+		dev_priv->regfile.savePFB_WIN_POS = I915_READ(_PFB_WIN_POS);
+
+		dev_priv->regfile.saveTRANSBCONF = I915_READ(_TRANSBCONF);
+		dev_priv->regfile.saveTRANS_HTOTAL_B = I915_READ(_TRANS_HTOTAL_B);
+		dev_priv->regfile.saveTRANS_HBLANK_B = I915_READ(_TRANS_HBLANK_B);
+		dev_priv->regfile.saveTRANS_HSYNC_B = I915_READ(_TRANS_HSYNC_B);
+		dev_priv->regfile.saveTRANS_VTOTAL_B = I915_READ(_TRANS_VTOTAL_B);
+		dev_priv->regfile.saveTRANS_VBLANK_B = I915_READ(_TRANS_VBLANK_B);
+		dev_priv->regfile.saveTRANS_VSYNC_B = I915_READ(_TRANS_VSYNC_B);
+	}
+
+	dev_priv->regfile.saveDSPBCNTR = I915_READ(_DSPBCNTR);
+	dev_priv->regfile.saveDSPBSTRIDE = I915_READ(_DSPBSTRIDE);
+	dev_priv->regfile.saveDSPBSIZE = I915_READ(_DSPBSIZE);
+	dev_priv->regfile.saveDSPBPOS = I915_READ(_DSPBPOS);
+	dev_priv->regfile.saveDSPBADDR = I915_READ(_DSPBADDR);
 	if (INTEL_INFO(dev)->gen >= 4) {
-		dev_priv->saveDSPBSURF = I915_READ(_DSPBSURF);
-		dev_priv->saveDSPBTILEOFF = I915_READ(_DSPBTILEOFF);
+		dev_priv->regfile.saveDSPBSURF = I915_READ(_DSPBSURF);
+		dev_priv->regfile.saveDSPBTILEOFF = I915_READ(_DSPBTILEOFF);
 	}
 	i915_save_palette(dev, PIPE_B);
-	dev_priv->savePIPEBSTAT = I915_READ(_PIPEBSTAT);
+	dev_priv->regfile.savePIPEBSTAT = I915_READ(_PIPEBSTAT);
 
 	/* Fences */
 	switch (INTEL_INFO(dev)->gen) {
 	case 7:
 	case 6:
 		for (i = 0; i < 16; i++)
-			dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
+			dev_priv->regfile.saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
 		break;
 	case 5:
 	case 4:
 		for (i = 0; i < 16; i++)
-			dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_965_0 + (i * 8));
+			dev_priv->regfile.saveFENCE[i] = I915_READ64(FENCE_REG_965_0 + (i * 8));
 		break;
 	case 3:
 		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
 			for (i = 0; i < 8; i++)
-				dev_priv->saveFENCE[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4));
+				dev_priv->regfile.saveFENCE[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4));
 	case 2:
 		for (i = 0; i < 8; i++)
-			dev_priv->saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
+			dev_priv->regfile.saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
 		break;
 	}
 
+	/* CRT state */
+	if (HAS_PCH_SPLIT(dev))
+		dev_priv->regfile.saveADPA = I915_READ(PCH_ADPA);
+	else
+		dev_priv->regfile.saveADPA = I915_READ(ADPA);
+
 	return;
 }
 
@@ -412,20 +418,20 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
 	case 7:
 	case 6:
 		for (i = 0; i < 16; i++)
-			I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]);
+			I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->regfile.saveFENCE[i]);
 		break;
 	case 5:
 	case 4:
 		for (i = 0; i < 16; i++)
-			I915_WRITE64(FENCE_REG_965_0 + (i * 8), dev_priv->saveFENCE[i]);
+			I915_WRITE64(FENCE_REG_965_0 + (i * 8), dev_priv->regfile.saveFENCE[i]);
 		break;
 	case 3:
 	case 2:
 		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
 			for (i = 0; i < 8; i++)
-				I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]);
+				I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->regfile.saveFENCE[i+8]);
 		for (i = 0; i < 8; i++)
-			I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->saveFENCE[i]);
+			I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->regfile.saveFENCE[i]);
 		break;
 	}
 
@@ -447,158 +453,164 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
 	}
 
 	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(PCH_DREF_CONTROL, dev_priv->savePCH_DREF_CONTROL);
-		I915_WRITE(DISP_ARB_CTL, dev_priv->saveDISP_ARB_CTL);
+		I915_WRITE(PCH_DREF_CONTROL, dev_priv->regfile.savePCH_DREF_CONTROL);
+		I915_WRITE(DISP_ARB_CTL, dev_priv->regfile.saveDISP_ARB_CTL);
 	}
 
 	/* Pipe & plane A info */
 	/* Prime the clock */
-	if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
-		I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A &
+	if (dev_priv->regfile.saveDPLL_A & DPLL_VCO_ENABLE) {
+		I915_WRITE(dpll_a_reg, dev_priv->regfile.saveDPLL_A &
 			   ~DPLL_VCO_ENABLE);
 		POSTING_READ(dpll_a_reg);
 		udelay(150);
 	}
-	I915_WRITE(fpa0_reg, dev_priv->saveFPA0);
-	I915_WRITE(fpa1_reg, dev_priv->saveFPA1);
+	I915_WRITE(fpa0_reg, dev_priv->regfile.saveFPA0);
+	I915_WRITE(fpa1_reg, dev_priv->regfile.saveFPA1);
 	/* Actually enable it */
-	I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A);
+	I915_WRITE(dpll_a_reg, dev_priv->regfile.saveDPLL_A);
 	POSTING_READ(dpll_a_reg);
 	udelay(150);
 	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(_DPLL_A_MD, dev_priv->saveDPLL_A_MD);
+		I915_WRITE(_DPLL_A_MD, dev_priv->regfile.saveDPLL_A_MD);
 		POSTING_READ(_DPLL_A_MD);
 	}
 	udelay(150);
 
 	/* Restore mode */
-	I915_WRITE(_HTOTAL_A, dev_priv->saveHTOTAL_A);
-	I915_WRITE(_HBLANK_A, dev_priv->saveHBLANK_A);
-	I915_WRITE(_HSYNC_A, dev_priv->saveHSYNC_A);
-	I915_WRITE(_VTOTAL_A, dev_priv->saveVTOTAL_A);
-	I915_WRITE(_VBLANK_A, dev_priv->saveVBLANK_A);
-	I915_WRITE(_VSYNC_A, dev_priv->saveVSYNC_A);
+	I915_WRITE(_HTOTAL_A, dev_priv->regfile.saveHTOTAL_A);
+	I915_WRITE(_HBLANK_A, dev_priv->regfile.saveHBLANK_A);
+	I915_WRITE(_HSYNC_A, dev_priv->regfile.saveHSYNC_A);
+	I915_WRITE(_VTOTAL_A, dev_priv->regfile.saveVTOTAL_A);
+	I915_WRITE(_VBLANK_A, dev_priv->regfile.saveVBLANK_A);
+	I915_WRITE(_VSYNC_A, dev_priv->regfile.saveVSYNC_A);
 	if (!HAS_PCH_SPLIT(dev))
-		I915_WRITE(_BCLRPAT_A, dev_priv->saveBCLRPAT_A);
+		I915_WRITE(_BCLRPAT_A, dev_priv->regfile.saveBCLRPAT_A);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(_PIPEA_DATA_M1, dev_priv->savePIPEA_DATA_M1);
-		I915_WRITE(_PIPEA_DATA_N1, dev_priv->savePIPEA_DATA_N1);
-		I915_WRITE(_PIPEA_LINK_M1, dev_priv->savePIPEA_LINK_M1);
-		I915_WRITE(_PIPEA_LINK_N1, dev_priv->savePIPEA_LINK_N1);
+		I915_WRITE(_PIPEA_DATA_M1, dev_priv->regfile.savePIPEA_DATA_M1);
+		I915_WRITE(_PIPEA_DATA_N1, dev_priv->regfile.savePIPEA_DATA_N1);
+		I915_WRITE(_PIPEA_LINK_M1, dev_priv->regfile.savePIPEA_LINK_M1);
+		I915_WRITE(_PIPEA_LINK_N1, dev_priv->regfile.savePIPEA_LINK_N1);
 
-		I915_WRITE(_FDI_RXA_CTL, dev_priv->saveFDI_RXA_CTL);
-		I915_WRITE(_FDI_TXA_CTL, dev_priv->saveFDI_TXA_CTL);
+		I915_WRITE(_FDI_RXA_CTL, dev_priv->regfile.saveFDI_RXA_CTL);
+		I915_WRITE(_FDI_TXA_CTL, dev_priv->regfile.saveFDI_TXA_CTL);
 
-		I915_WRITE(_PFA_CTL_1, dev_priv->savePFA_CTL_1);
-		I915_WRITE(_PFA_WIN_SZ, dev_priv->savePFA_WIN_SZ);
-		I915_WRITE(_PFA_WIN_POS, dev_priv->savePFA_WIN_POS);
+		I915_WRITE(_PFA_CTL_1, dev_priv->regfile.savePFA_CTL_1);
+		I915_WRITE(_PFA_WIN_SZ, dev_priv->regfile.savePFA_WIN_SZ);
+		I915_WRITE(_PFA_WIN_POS, dev_priv->regfile.savePFA_WIN_POS);
 
-		I915_WRITE(_TRANSACONF, dev_priv->saveTRANSACONF);
-		I915_WRITE(_TRANS_HTOTAL_A, dev_priv->saveTRANS_HTOTAL_A);
-		I915_WRITE(_TRANS_HBLANK_A, dev_priv->saveTRANS_HBLANK_A);
-		I915_WRITE(_TRANS_HSYNC_A, dev_priv->saveTRANS_HSYNC_A);
-		I915_WRITE(_TRANS_VTOTAL_A, dev_priv->saveTRANS_VTOTAL_A);
-		I915_WRITE(_TRANS_VBLANK_A, dev_priv->saveTRANS_VBLANK_A);
-		I915_WRITE(_TRANS_VSYNC_A, dev_priv->saveTRANS_VSYNC_A);
+		I915_WRITE(_TRANSACONF, dev_priv->regfile.saveTRANSACONF);
+		I915_WRITE(_TRANS_HTOTAL_A, dev_priv->regfile.saveTRANS_HTOTAL_A);
+		I915_WRITE(_TRANS_HBLANK_A, dev_priv->regfile.saveTRANS_HBLANK_A);
+		I915_WRITE(_TRANS_HSYNC_A, dev_priv->regfile.saveTRANS_HSYNC_A);
+		I915_WRITE(_TRANS_VTOTAL_A, dev_priv->regfile.saveTRANS_VTOTAL_A);
+		I915_WRITE(_TRANS_VBLANK_A, dev_priv->regfile.saveTRANS_VBLANK_A);
+		I915_WRITE(_TRANS_VSYNC_A, dev_priv->regfile.saveTRANS_VSYNC_A);
 	}
 
 	/* Restore plane info */
-	I915_WRITE(_DSPASIZE, dev_priv->saveDSPASIZE);
-	I915_WRITE(_DSPAPOS, dev_priv->saveDSPAPOS);
-	I915_WRITE(_PIPEASRC, dev_priv->savePIPEASRC);
-	I915_WRITE(_DSPAADDR, dev_priv->saveDSPAADDR);
-	I915_WRITE(_DSPASTRIDE, dev_priv->saveDSPASTRIDE);
+	I915_WRITE(_DSPASIZE, dev_priv->regfile.saveDSPASIZE);
+	I915_WRITE(_DSPAPOS, dev_priv->regfile.saveDSPAPOS);
+	I915_WRITE(_PIPEASRC, dev_priv->regfile.savePIPEASRC);
+	I915_WRITE(_DSPAADDR, dev_priv->regfile.saveDSPAADDR);
+	I915_WRITE(_DSPASTRIDE, dev_priv->regfile.saveDSPASTRIDE);
 	if (INTEL_INFO(dev)->gen >= 4) {
-		I915_WRITE(_DSPASURF, dev_priv->saveDSPASURF);
-		I915_WRITE(_DSPATILEOFF, dev_priv->saveDSPATILEOFF);
+		I915_WRITE(_DSPASURF, dev_priv->regfile.saveDSPASURF);
+		I915_WRITE(_DSPATILEOFF, dev_priv->regfile.saveDSPATILEOFF);
 	}
 
-	I915_WRITE(_PIPEACONF, dev_priv->savePIPEACONF);
+	I915_WRITE(_PIPEACONF, dev_priv->regfile.savePIPEACONF);
 
 	i915_restore_palette(dev, PIPE_A);
 	/* Enable the plane */
-	I915_WRITE(_DSPACNTR, dev_priv->saveDSPACNTR);
+	I915_WRITE(_DSPACNTR, dev_priv->regfile.saveDSPACNTR);
 	I915_WRITE(_DSPAADDR, I915_READ(_DSPAADDR));
 
 	/* Pipe & plane B info */
-	if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
-		I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B &
+	if (dev_priv->regfile.saveDPLL_B & DPLL_VCO_ENABLE) {
+		I915_WRITE(dpll_b_reg, dev_priv->regfile.saveDPLL_B &
 			   ~DPLL_VCO_ENABLE);
 		POSTING_READ(dpll_b_reg);
 		udelay(150);
 	}
-	I915_WRITE(fpb0_reg, dev_priv->saveFPB0);
-	I915_WRITE(fpb1_reg, dev_priv->saveFPB1);
+	I915_WRITE(fpb0_reg, dev_priv->regfile.saveFPB0);
+	I915_WRITE(fpb1_reg, dev_priv->regfile.saveFPB1);
 	/* Actually enable it */
-	I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B);
+	I915_WRITE(dpll_b_reg, dev_priv->regfile.saveDPLL_B);
 	POSTING_READ(dpll_b_reg);
 	udelay(150);
 	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(_DPLL_B_MD, dev_priv->saveDPLL_B_MD);
+		I915_WRITE(_DPLL_B_MD, dev_priv->regfile.saveDPLL_B_MD);
 		POSTING_READ(_DPLL_B_MD);
 	}
 	udelay(150);
 
 	/* Restore mode */
-	I915_WRITE(_HTOTAL_B, dev_priv->saveHTOTAL_B);
-	I915_WRITE(_HBLANK_B, dev_priv->saveHBLANK_B);
-	I915_WRITE(_HSYNC_B, dev_priv->saveHSYNC_B);
-	I915_WRITE(_VTOTAL_B, dev_priv->saveVTOTAL_B);
-	I915_WRITE(_VBLANK_B, dev_priv->saveVBLANK_B);
-	I915_WRITE(_VSYNC_B, dev_priv->saveVSYNC_B);
+	I915_WRITE(_HTOTAL_B, dev_priv->regfile.saveHTOTAL_B);
+	I915_WRITE(_HBLANK_B, dev_priv->regfile.saveHBLANK_B);
+	I915_WRITE(_HSYNC_B, dev_priv->regfile.saveHSYNC_B);
+	I915_WRITE(_VTOTAL_B, dev_priv->regfile.saveVTOTAL_B);
+	I915_WRITE(_VBLANK_B, dev_priv->regfile.saveVBLANK_B);
+	I915_WRITE(_VSYNC_B, dev_priv->regfile.saveVSYNC_B);
 	if (!HAS_PCH_SPLIT(dev))
-		I915_WRITE(_BCLRPAT_B, dev_priv->saveBCLRPAT_B);
+		I915_WRITE(_BCLRPAT_B, dev_priv->regfile.saveBCLRPAT_B);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(_PIPEB_DATA_M1, dev_priv->savePIPEB_DATA_M1);
-		I915_WRITE(_PIPEB_DATA_N1, dev_priv->savePIPEB_DATA_N1);
-		I915_WRITE(_PIPEB_LINK_M1, dev_priv->savePIPEB_LINK_M1);
-		I915_WRITE(_PIPEB_LINK_N1, dev_priv->savePIPEB_LINK_N1);
+		I915_WRITE(_PIPEB_DATA_M1, dev_priv->regfile.savePIPEB_DATA_M1);
+		I915_WRITE(_PIPEB_DATA_N1, dev_priv->regfile.savePIPEB_DATA_N1);
+		I915_WRITE(_PIPEB_LINK_M1, dev_priv->regfile.savePIPEB_LINK_M1);
+		I915_WRITE(_PIPEB_LINK_N1, dev_priv->regfile.savePIPEB_LINK_N1);
 
-		I915_WRITE(_FDI_RXB_CTL, dev_priv->saveFDI_RXB_CTL);
-		I915_WRITE(_FDI_TXB_CTL, dev_priv->saveFDI_TXB_CTL);
+		I915_WRITE(_FDI_RXB_CTL, dev_priv->regfile.saveFDI_RXB_CTL);
+		I915_WRITE(_FDI_TXB_CTL, dev_priv->regfile.saveFDI_TXB_CTL);
 
-		I915_WRITE(_PFB_CTL_1, dev_priv->savePFB_CTL_1);
-		I915_WRITE(_PFB_WIN_SZ, dev_priv->savePFB_WIN_SZ);
-		I915_WRITE(_PFB_WIN_POS, dev_priv->savePFB_WIN_POS);
+		I915_WRITE(_PFB_CTL_1, dev_priv->regfile.savePFB_CTL_1);
+		I915_WRITE(_PFB_WIN_SZ, dev_priv->regfile.savePFB_WIN_SZ);
+		I915_WRITE(_PFB_WIN_POS, dev_priv->regfile.savePFB_WIN_POS);
 
-		I915_WRITE(_TRANSBCONF, dev_priv->saveTRANSBCONF);
-		I915_WRITE(_TRANS_HTOTAL_B, dev_priv->saveTRANS_HTOTAL_B);
-		I915_WRITE(_TRANS_HBLANK_B, dev_priv->saveTRANS_HBLANK_B);
-		I915_WRITE(_TRANS_HSYNC_B, dev_priv->saveTRANS_HSYNC_B);
-		I915_WRITE(_TRANS_VTOTAL_B, dev_priv->saveTRANS_VTOTAL_B);
-		I915_WRITE(_TRANS_VBLANK_B, dev_priv->saveTRANS_VBLANK_B);
-		I915_WRITE(_TRANS_VSYNC_B, dev_priv->saveTRANS_VSYNC_B);
+		I915_WRITE(_TRANSBCONF, dev_priv->regfile.saveTRANSBCONF);
+		I915_WRITE(_TRANS_HTOTAL_B, dev_priv->regfile.saveTRANS_HTOTAL_B);
+		I915_WRITE(_TRANS_HBLANK_B, dev_priv->regfile.saveTRANS_HBLANK_B);
+		I915_WRITE(_TRANS_HSYNC_B, dev_priv->regfile.saveTRANS_HSYNC_B);
+		I915_WRITE(_TRANS_VTOTAL_B, dev_priv->regfile.saveTRANS_VTOTAL_B);
+		I915_WRITE(_TRANS_VBLANK_B, dev_priv->regfile.saveTRANS_VBLANK_B);
+		I915_WRITE(_TRANS_VSYNC_B, dev_priv->regfile.saveTRANS_VSYNC_B);
 	}
 
 	/* Restore plane info */
-	I915_WRITE(_DSPBSIZE, dev_priv->saveDSPBSIZE);
-	I915_WRITE(_DSPBPOS, dev_priv->saveDSPBPOS);
-	I915_WRITE(_PIPEBSRC, dev_priv->savePIPEBSRC);
-	I915_WRITE(_DSPBADDR, dev_priv->saveDSPBADDR);
-	I915_WRITE(_DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
+	I915_WRITE(_DSPBSIZE, dev_priv->regfile.saveDSPBSIZE);
+	I915_WRITE(_DSPBPOS, dev_priv->regfile.saveDSPBPOS);
+	I915_WRITE(_PIPEBSRC, dev_priv->regfile.savePIPEBSRC);
+	I915_WRITE(_DSPBADDR, dev_priv->regfile.saveDSPBADDR);
+	I915_WRITE(_DSPBSTRIDE, dev_priv->regfile.saveDSPBSTRIDE);
 	if (INTEL_INFO(dev)->gen >= 4) {
-		I915_WRITE(_DSPBSURF, dev_priv->saveDSPBSURF);
-		I915_WRITE(_DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
+		I915_WRITE(_DSPBSURF, dev_priv->regfile.saveDSPBSURF);
+		I915_WRITE(_DSPBTILEOFF, dev_priv->regfile.saveDSPBTILEOFF);
 	}
 
-	I915_WRITE(_PIPEBCONF, dev_priv->savePIPEBCONF);
+	I915_WRITE(_PIPEBCONF, dev_priv->regfile.savePIPEBCONF);
 
 	i915_restore_palette(dev, PIPE_B);
 	/* Enable the plane */
-	I915_WRITE(_DSPBCNTR, dev_priv->saveDSPBCNTR);
+	I915_WRITE(_DSPBCNTR, dev_priv->regfile.saveDSPBCNTR);
 	I915_WRITE(_DSPBADDR, I915_READ(_DSPBADDR));
 
 	/* Cursor state */
-	I915_WRITE(_CURAPOS, dev_priv->saveCURAPOS);
-	I915_WRITE(_CURACNTR, dev_priv->saveCURACNTR);
-	I915_WRITE(_CURABASE, dev_priv->saveCURABASE);
-	I915_WRITE(_CURBPOS, dev_priv->saveCURBPOS);
-	I915_WRITE(_CURBCNTR, dev_priv->saveCURBCNTR);
-	I915_WRITE(_CURBBASE, dev_priv->saveCURBBASE);
+	I915_WRITE(_CURAPOS, dev_priv->regfile.saveCURAPOS);
+	I915_WRITE(_CURACNTR, dev_priv->regfile.saveCURACNTR);
+	I915_WRITE(_CURABASE, dev_priv->regfile.saveCURABASE);
+	I915_WRITE(_CURBPOS, dev_priv->regfile.saveCURBPOS);
+	I915_WRITE(_CURBCNTR, dev_priv->regfile.saveCURBCNTR);
+	I915_WRITE(_CURBBASE, dev_priv->regfile.saveCURBBASE);
 	if (IS_GEN2(dev))
-		I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);
+		I915_WRITE(CURSIZE, dev_priv->regfile.saveCURSIZE);
+
+	/* CRT state */
+	if (HAS_PCH_SPLIT(dev))
+		I915_WRITE(PCH_ADPA, dev_priv->regfile.saveADPA);
+	else
+		I915_WRITE(ADPA, dev_priv->regfile.saveADPA);
 
 	return;
 }
@@ -608,89 +620,84 @@ static void i915_save_display(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	/* Display arbitration control */
-	dev_priv->saveDSPARB = I915_READ(DSPARB);
+	dev_priv->regfile.saveDSPARB = I915_READ(DSPARB);
 
 	/* This is only meaningful in non-KMS mode */
-	/* Don't save them in KMS mode */
+	/* Don't regfile.save them in KMS mode */
 	i915_save_modeset_reg(dev);
 
-	/* CRT state */
-	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->saveADPA = I915_READ(PCH_ADPA);
-	} else {
-		dev_priv->saveADPA = I915_READ(ADPA);
-	}
-
 	/* LVDS state */
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
-		dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1);
-		dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
-		dev_priv->saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL);
-		dev_priv->saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2);
-		dev_priv->saveLVDS = I915_READ(PCH_LVDS);
+		dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
+		dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1);
+		dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
+		dev_priv->regfile.saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL);
+		dev_priv->regfile.saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2);
+		dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS);
 	} else {
-		dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
-		dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
-		dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
-		dev_priv->saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL);
+		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
+		dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
+		dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+		dev_priv->regfile.saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL);
 		if (INTEL_INFO(dev)->gen >= 4)
-			dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
+			dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
 		if (IS_MOBILE(dev) && !IS_I830(dev))
-			dev_priv->saveLVDS = I915_READ(LVDS);
+			dev_priv->regfile.saveLVDS = I915_READ(LVDS);
 	}
 
 	if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
-		dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
+		dev_priv->regfile.savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
-		dev_priv->savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
-		dev_priv->savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
+		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
+		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
+		dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
 	} else {
-		dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
-		dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
-		dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
-	}
-
-	/* Display Port state */
-	if (SUPPORTS_INTEGRATED_DP(dev)) {
-		dev_priv->saveDP_B = I915_READ(DP_B);
-		dev_priv->saveDP_C = I915_READ(DP_C);
-		dev_priv->saveDP_D = I915_READ(DP_D);
-		dev_priv->savePIPEA_GMCH_DATA_M = I915_READ(_PIPEA_GMCH_DATA_M);
-		dev_priv->savePIPEB_GMCH_DATA_M = I915_READ(_PIPEB_GMCH_DATA_M);
-		dev_priv->savePIPEA_GMCH_DATA_N = I915_READ(_PIPEA_GMCH_DATA_N);
-		dev_priv->savePIPEB_GMCH_DATA_N = I915_READ(_PIPEB_GMCH_DATA_N);
-		dev_priv->savePIPEA_DP_LINK_M = I915_READ(_PIPEA_DP_LINK_M);
-		dev_priv->savePIPEB_DP_LINK_M = I915_READ(_PIPEB_DP_LINK_M);
-		dev_priv->savePIPEA_DP_LINK_N = I915_READ(_PIPEA_DP_LINK_N);
-		dev_priv->savePIPEB_DP_LINK_N = I915_READ(_PIPEB_DP_LINK_N);
-	}
-	/* FIXME: save TV & SDVO state */
-
-	/* Only save FBC state on the platform that supports FBC */
+		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
+		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
+		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR);
+	}
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
+		/* Display Port state */
+		if (SUPPORTS_INTEGRATED_DP(dev)) {
+			dev_priv->regfile.saveDP_B = I915_READ(DP_B);
+			dev_priv->regfile.saveDP_C = I915_READ(DP_C);
+			dev_priv->regfile.saveDP_D = I915_READ(DP_D);
+			dev_priv->regfile.savePIPEA_GMCH_DATA_M = I915_READ(_PIPEA_GMCH_DATA_M);
+			dev_priv->regfile.savePIPEB_GMCH_DATA_M = I915_READ(_PIPEB_GMCH_DATA_M);
+			dev_priv->regfile.savePIPEA_GMCH_DATA_N = I915_READ(_PIPEA_GMCH_DATA_N);
+			dev_priv->regfile.savePIPEB_GMCH_DATA_N = I915_READ(_PIPEB_GMCH_DATA_N);
+			dev_priv->regfile.savePIPEA_DP_LINK_M = I915_READ(_PIPEA_DP_LINK_M);
+			dev_priv->regfile.savePIPEB_DP_LINK_M = I915_READ(_PIPEB_DP_LINK_M);
+			dev_priv->regfile.savePIPEA_DP_LINK_N = I915_READ(_PIPEA_DP_LINK_N);
+			dev_priv->regfile.savePIPEB_DP_LINK_N = I915_READ(_PIPEB_DP_LINK_N);
+		}
+		/* FIXME: regfile.save TV & SDVO state */
+	}
+
+	/* Only regfile.save FBC state on the platform that supports FBC */
 	if (I915_HAS_FBC(dev)) {
 		if (HAS_PCH_SPLIT(dev)) {
-			dev_priv->saveDPFC_CB_BASE = I915_READ(ILK_DPFC_CB_BASE);
+			dev_priv->regfile.saveDPFC_CB_BASE = I915_READ(ILK_DPFC_CB_BASE);
 		} else if (IS_GM45(dev)) {
-			dev_priv->saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE);
+			dev_priv->regfile.saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE);
 		} else {
-			dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
-			dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
-			dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
-			dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
+			dev_priv->regfile.saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
+			dev_priv->regfile.saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
+			dev_priv->regfile.saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
+			dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL);
 		}
 	}
 
 	/* VGA state */
-	dev_priv->saveVGA0 = I915_READ(VGA0);
-	dev_priv->saveVGA1 = I915_READ(VGA1);
-	dev_priv->saveVGA_PD = I915_READ(VGA_PD);
+	dev_priv->regfile.saveVGA0 = I915_READ(VGA0);
+	dev_priv->regfile.saveVGA1 = I915_READ(VGA1);
+	dev_priv->regfile.saveVGA_PD = I915_READ(VGA_PD);
 	if (HAS_PCH_SPLIT(dev))
-		dev_priv->saveVGACNTRL = I915_READ(CPU_VGACNTRL);
+		dev_priv->regfile.saveVGACNTRL = I915_READ(CPU_VGACNTRL);
 	else
-		dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
+		dev_priv->regfile.saveVGACNTRL = I915_READ(VGACNTRL);
 
 	i915_save_vga(dev);
 }
@@ -700,97 +707,95 @@ static void i915_restore_display(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	/* Display arbitration */
-	I915_WRITE(DSPARB, dev_priv->saveDSPARB);
-
-	/* Display port ratios (must be done before clock is set) */
-	if (SUPPORTS_INTEGRATED_DP(dev)) {
-		I915_WRITE(_PIPEA_GMCH_DATA_M, dev_priv->savePIPEA_GMCH_DATA_M);
-		I915_WRITE(_PIPEB_GMCH_DATA_M, dev_priv->savePIPEB_GMCH_DATA_M);
-		I915_WRITE(_PIPEA_GMCH_DATA_N, dev_priv->savePIPEA_GMCH_DATA_N);
-		I915_WRITE(_PIPEB_GMCH_DATA_N, dev_priv->savePIPEB_GMCH_DATA_N);
-		I915_WRITE(_PIPEA_DP_LINK_M, dev_priv->savePIPEA_DP_LINK_M);
-		I915_WRITE(_PIPEB_DP_LINK_M, dev_priv->savePIPEB_DP_LINK_M);
-		I915_WRITE(_PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N);
-		I915_WRITE(_PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N);
+	I915_WRITE(DSPARB, dev_priv->regfile.saveDSPARB);
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
+		/* Display port ratios (must be done before clock is set) */
+		if (SUPPORTS_INTEGRATED_DP(dev)) {
+			I915_WRITE(_PIPEA_GMCH_DATA_M, dev_priv->regfile.savePIPEA_GMCH_DATA_M);
+			I915_WRITE(_PIPEB_GMCH_DATA_M, dev_priv->regfile.savePIPEB_GMCH_DATA_M);
+			I915_WRITE(_PIPEA_GMCH_DATA_N, dev_priv->regfile.savePIPEA_GMCH_DATA_N);
+			I915_WRITE(_PIPEB_GMCH_DATA_N, dev_priv->regfile.savePIPEB_GMCH_DATA_N);
+			I915_WRITE(_PIPEA_DP_LINK_M, dev_priv->regfile.savePIPEA_DP_LINK_M);
+			I915_WRITE(_PIPEB_DP_LINK_M, dev_priv->regfile.savePIPEB_DP_LINK_M);
+			I915_WRITE(_PIPEA_DP_LINK_N, dev_priv->regfile.savePIPEA_DP_LINK_N);
+			I915_WRITE(_PIPEB_DP_LINK_N, dev_priv->regfile.savePIPEB_DP_LINK_N);
+		}
 	}
 
 	/* This is only meaningful in non-KMS mode */
 	/* Don't restore them in KMS mode */
 	i915_restore_modeset_reg(dev);
 
-	/* CRT state */
-	if (HAS_PCH_SPLIT(dev))
-		I915_WRITE(PCH_ADPA, dev_priv->saveADPA);
-	else
-		I915_WRITE(ADPA, dev_priv->saveADPA);
-
 	/* LVDS state */
 	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
-		I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
+		I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(PCH_LVDS, dev_priv->saveLVDS);
+		I915_WRITE(PCH_LVDS, dev_priv->regfile.saveLVDS);
 	} else if (IS_MOBILE(dev) && !IS_I830(dev))
-		I915_WRITE(LVDS, dev_priv->saveLVDS);
+		I915_WRITE(LVDS, dev_priv->regfile.saveLVDS);
 
 	if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
-		I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
+		I915_WRITE(PFIT_CONTROL, dev_priv->regfile.savePFIT_CONTROL);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->saveBLC_PWM_CTL);
-		I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->saveBLC_PWM_CTL2);
+		I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->regfile.saveBLC_PWM_CTL);
+		I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
 		/* NOTE: BLC_PWM_CPU_CTL must be written after BLC_PWM_CPU_CTL2;
 		 * otherwise we get blank eDP screen after S3 on some machines
 		 */
-		I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->saveBLC_CPU_PWM_CTL2);
-		I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->saveBLC_CPU_PWM_CTL);
-		I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
-		I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
-		I915_WRITE(PCH_PP_DIVISOR, dev_priv->savePP_DIVISOR);
-		I915_WRITE(PCH_PP_CONTROL, dev_priv->savePP_CONTROL);
+		I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->regfile.saveBLC_CPU_PWM_CTL2);
+		I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->regfile.saveBLC_CPU_PWM_CTL);
+		I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
+		I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
+		I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
+		I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
 		I915_WRITE(RSTDBYCTL,
-			   dev_priv->saveMCHBAR_RENDER_STANDBY);
+			   dev_priv->regfile.saveMCHBAR_RENDER_STANDBY);
 	} else {
-		I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
-		I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
-		I915_WRITE(BLC_HIST_CTL, dev_priv->saveBLC_HIST_CTL);
-		I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
-		I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
-		I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
-		I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
-	}
-
-	/* Display Port state */
-	if (SUPPORTS_INTEGRATED_DP(dev)) {
-		I915_WRITE(DP_B, dev_priv->saveDP_B);
-		I915_WRITE(DP_C, dev_priv->saveDP_C);
-		I915_WRITE(DP_D, dev_priv->saveDP_D);
+		I915_WRITE(PFIT_PGM_RATIOS, dev_priv->regfile.savePFIT_PGM_RATIOS);
+		I915_WRITE(BLC_PWM_CTL, dev_priv->regfile.saveBLC_PWM_CTL);
+		I915_WRITE(BLC_HIST_CTL, dev_priv->regfile.saveBLC_HIST_CTL);
+		I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
+		I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
+		I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
+		I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
+	}
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
+		/* Display Port state */
+		if (SUPPORTS_INTEGRATED_DP(dev)) {
+			I915_WRITE(DP_B, dev_priv->regfile.saveDP_B);
+			I915_WRITE(DP_C, dev_priv->regfile.saveDP_C);
+			I915_WRITE(DP_D, dev_priv->regfile.saveDP_D);
+		}
+		/* FIXME: restore TV & SDVO state */
 	}
-	/* FIXME: restore TV & SDVO state */
 
 	/* only restore FBC info on the platform that supports FBC*/
 	intel_disable_fbc(dev);
 	if (I915_HAS_FBC(dev)) {
 		if (HAS_PCH_SPLIT(dev)) {
-			I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
+			I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->regfile.saveDPFC_CB_BASE);
 		} else if (IS_GM45(dev)) {
-			I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
+			I915_WRITE(DPFC_CB_BASE, dev_priv->regfile.saveDPFC_CB_BASE);
 		} else {
-			I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
-			I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
-			I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
-			I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
+			I915_WRITE(FBC_CFB_BASE, dev_priv->regfile.saveFBC_CFB_BASE);
+			I915_WRITE(FBC_LL_BASE, dev_priv->regfile.saveFBC_LL_BASE);
+			I915_WRITE(FBC_CONTROL2, dev_priv->regfile.saveFBC_CONTROL2);
+			I915_WRITE(FBC_CONTROL, dev_priv->regfile.saveFBC_CONTROL);
 		}
 	}
 	/* VGA state */
 	if (HAS_PCH_SPLIT(dev))
-		I915_WRITE(CPU_VGACNTRL, dev_priv->saveVGACNTRL);
+		I915_WRITE(CPU_VGACNTRL, dev_priv->regfile.saveVGACNTRL);
 	else
-		I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
+		I915_WRITE(VGACNTRL, dev_priv->regfile.saveVGACNTRL);
 
-	I915_WRITE(VGA0, dev_priv->saveVGA0);
-	I915_WRITE(VGA1, dev_priv->saveVGA1);
-	I915_WRITE(VGA_PD, dev_priv->saveVGA_PD);
+	I915_WRITE(VGA0, dev_priv->regfile.saveVGA0);
+	I915_WRITE(VGA1, dev_priv->regfile.saveVGA1);
+	I915_WRITE(VGA_PD, dev_priv->regfile.saveVGA_PD);
 	POSTING_READ(VGA_PD);
 	udelay(150);
 
@@ -802,46 +807,49 @@ int i915_save_state(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int i;
 
-	pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
+	pci_read_config_byte(dev->pdev, LBB, &dev_priv->regfile.saveLBB);
 
 	mutex_lock(&dev->struct_mutex);
 
 	/* Hardware status page */
-	dev_priv->saveHWS = I915_READ(HWS_PGA);
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		dev_priv->regfile.saveHWS = I915_READ(HWS_PGA);
 
 	i915_save_display(dev);
 
-	/* Interrupt state */
-	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->saveDEIER = I915_READ(DEIER);
-		dev_priv->saveDEIMR = I915_READ(DEIMR);
-		dev_priv->saveGTIER = I915_READ(GTIER);
-		dev_priv->saveGTIMR = I915_READ(GTIMR);
-		dev_priv->saveFDI_RXA_IMR = I915_READ(_FDI_RXA_IMR);
-		dev_priv->saveFDI_RXB_IMR = I915_READ(_FDI_RXB_IMR);
-		dev_priv->saveMCHBAR_RENDER_STANDBY =
-			I915_READ(RSTDBYCTL);
-		dev_priv->savePCH_PORT_HOTPLUG = I915_READ(PCH_PORT_HOTPLUG);
-	} else {
-		dev_priv->saveIER = I915_READ(IER);
-		dev_priv->saveIMR = I915_READ(IMR);
+	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
+		/* Interrupt state */
+		if (HAS_PCH_SPLIT(dev)) {
+			dev_priv->regfile.saveDEIER = I915_READ(DEIER);
+			dev_priv->regfile.saveDEIMR = I915_READ(DEIMR);
+			dev_priv->regfile.saveGTIER = I915_READ(GTIER);
+			dev_priv->regfile.saveGTIMR = I915_READ(GTIMR);
+			dev_priv->regfile.saveFDI_RXA_IMR = I915_READ(_FDI_RXA_IMR);
+			dev_priv->regfile.saveFDI_RXB_IMR = I915_READ(_FDI_RXB_IMR);
+			dev_priv->regfile.saveMCHBAR_RENDER_STANDBY =
+				I915_READ(RSTDBYCTL);
+			dev_priv->regfile.savePCH_PORT_HOTPLUG = I915_READ(PCH_PORT_HOTPLUG);
+		} else {
+			dev_priv->regfile.saveIER = I915_READ(IER);
+			dev_priv->regfile.saveIMR = I915_READ(IMR);
+		}
 	}
 
 	intel_disable_gt_powersave(dev);
 
 	/* Cache mode state */
-	dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
+	dev_priv->regfile.saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
 
 	/* Memory Arbitration state */
-	dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
+	dev_priv->regfile.saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
 
 	/* Scratch space */
 	for (i = 0; i < 16; i++) {
-		dev_priv->saveSWF0[i] = I915_READ(SWF00 + (i << 2));
-		dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));
+		dev_priv->regfile.saveSWF0[i] = I915_READ(SWF00 + (i << 2));
+		dev_priv->regfile.saveSWF1[i] = I915_READ(SWF10 + (i << 2));
 	}
 	for (i = 0; i < 3; i++)
-		dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
+		dev_priv->regfile.saveSWF2[i] = I915_READ(SWF30 + (i << 2));
 
 	mutex_unlock(&dev->struct_mutex);
 
@@ -853,41 +861,44 @@ int i915_restore_state(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int i;
 
-	pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
+	pci_write_config_byte(dev->pdev, LBB, dev_priv->regfile.saveLBB);
 
 	mutex_lock(&dev->struct_mutex);
 
 	/* Hardware status page */
-	I915_WRITE(HWS_PGA, dev_priv->saveHWS);
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		I915_WRITE(HWS_PGA, dev_priv->regfile.saveHWS);
 
 	i915_restore_display(dev);
 
-	/* Interrupt state */
-	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(DEIER, dev_priv->saveDEIER);
-		I915_WRITE(DEIMR, dev_priv->saveDEIMR);
-		I915_WRITE(GTIER, dev_priv->saveGTIER);
-		I915_WRITE(GTIMR, dev_priv->saveGTIMR);
-		I915_WRITE(_FDI_RXA_IMR, dev_priv->saveFDI_RXA_IMR);
-		I915_WRITE(_FDI_RXB_IMR, dev_priv->saveFDI_RXB_IMR);
-		I915_WRITE(PCH_PORT_HOTPLUG, dev_priv->savePCH_PORT_HOTPLUG);
-	} else {
-		I915_WRITE(IER, dev_priv->saveIER);
-		I915_WRITE(IMR, dev_priv->saveIMR);
+	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
+		/* Interrupt state */
+		if (HAS_PCH_SPLIT(dev)) {
+			I915_WRITE(DEIER, dev_priv->regfile.saveDEIER);
+			I915_WRITE(DEIMR, dev_priv->regfile.saveDEIMR);
+			I915_WRITE(GTIER, dev_priv->regfile.saveGTIER);
+			I915_WRITE(GTIMR, dev_priv->regfile.saveGTIMR);
+			I915_WRITE(_FDI_RXA_IMR, dev_priv->regfile.saveFDI_RXA_IMR);
+			I915_WRITE(_FDI_RXB_IMR, dev_priv->regfile.saveFDI_RXB_IMR);
+			I915_WRITE(PCH_PORT_HOTPLUG, dev_priv->regfile.savePCH_PORT_HOTPLUG);
+		} else {
+			I915_WRITE(IER, dev_priv->regfile.saveIER);
+			I915_WRITE(IMR, dev_priv->regfile.saveIMR);
+		}
 	}
 
 	/* Cache mode state */
-	I915_WRITE(CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
+	I915_WRITE(CACHE_MODE_0, dev_priv->regfile.saveCACHE_MODE_0 | 0xffff0000);
 
 	/* Memory arbitration state */
-	I915_WRITE(MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
+	I915_WRITE(MI_ARB_STATE, dev_priv->regfile.saveMI_ARB_STATE | 0xffff0000);
 
 	for (i = 0; i < 16; i++) {
-		I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
-		I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i]);
+		I915_WRITE(SWF00 + (i << 2), dev_priv->regfile.saveSWF0[i]);
+		I915_WRITE(SWF10 + (i << 2), dev_priv->regfile.saveSWF1[i]);
 	}
 	for (i = 0; i < 3; i++)
-		I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
+		I915_WRITE(SWF30 + (i << 2), dev_priv->regfile.saveSWF2[i]);
 
 	mutex_unlock(&dev->struct_mutex);
 
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 903eebd..3bf51d5 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -162,7 +162,7 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
 	if (ret)
 		return ret;
 
-	if (!dev_priv->mm.l3_remap_info) {
+	if (!dev_priv->l3_parity.remap_info) {
 		temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL);
 		if (!temp) {
 			mutex_unlock(&drm_dev->struct_mutex);
@@ -182,9 +182,9 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
 	 * at this point it is left as a TODO.
 	*/
 	if (temp)
-		dev_priv->mm.l3_remap_info = temp;
+		dev_priv->l3_parity.remap_info = temp;
 
-	memcpy(dev_priv->mm.l3_remap_info + (offset/4),
+	memcpy(dev_priv->l3_parity.remap_info + (offset/4),
 	       buf + (offset/4),
 	       count);
 
@@ -211,12 +211,9 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
-	ret = i915_mutex_lock_interruptible(dev);
-	if (ret)
-		return ret;
-
+	mutex_lock(&dev_priv->rps.hw_lock);
 	ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER;
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return snprintf(buf, PAGE_SIZE, "%d", ret);
 }
@@ -228,12 +225,9 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
-	ret = i915_mutex_lock_interruptible(dev);
-	if (ret)
-		return ret;
-
+	mutex_lock(&dev_priv->rps.hw_lock);
 	ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return snprintf(buf, PAGE_SIZE, "%d", ret);
 }
@@ -254,16 +248,14 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 
 	val /= GT_FREQUENCY_MULTIPLIER;
 
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
-	if (ret)
-		return ret;
+	mutex_lock(&dev_priv->rps.hw_lock);
 
 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
 	hw_max = (rp_state_cap & 0xff);
 	hw_min = ((rp_state_cap & 0xff0000) >> 16);
 
 	if (val < hw_min || val > hw_max || val < dev_priv->rps.min_delay) {
-		mutex_unlock(&dev->struct_mutex);
+		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
 
@@ -272,7 +264,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 
 	dev_priv->rps.max_delay = val;
 
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return count;
 }
@@ -284,12 +276,9 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
-	ret = i915_mutex_lock_interruptible(dev);
-	if (ret)
-		return ret;
-
+	mutex_lock(&dev_priv->rps.hw_lock);
 	ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return snprintf(buf, PAGE_SIZE, "%d", ret);
 }
@@ -310,16 +299,14 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 
 	val /= GT_FREQUENCY_MULTIPLIER;
 
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
-	if (ret)
-		return ret;
+	mutex_lock(&dev_priv->rps.hw_lock);
 
 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
 	hw_max = (rp_state_cap & 0xff);
 	hw_min = ((rp_state_cap & 0xff0000) >> 16);
 
 	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) {
-		mutex_unlock(&dev->struct_mutex);
+		mutex_unlock(&dev_priv->rps.hw_lock);
 		return -EINVAL;
 	}
 
@@ -328,7 +315,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 
 	dev_priv->rps.min_delay = val;
 
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return count;
 
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 8134421..3db4a68 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -229,24 +229,26 @@ TRACE_EVENT(i915_gem_evict_everything,
 );
 
 TRACE_EVENT(i915_gem_ring_dispatch,
-	    TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
-	    TP_ARGS(ring, seqno),
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 seqno, u32 flags),
+	    TP_ARGS(ring, seqno, flags),
 
 	    TP_STRUCT__entry(
 			     __field(u32, dev)
 			     __field(u32, ring)
 			     __field(u32, seqno)
+			     __field(u32, flags)
 			     ),
 
 	    TP_fast_assign(
 			   __entry->dev = ring->dev->primary->index;
 			   __entry->ring = ring->id;
 			   __entry->seqno = seqno;
+			   __entry->flags = flags;
 			   i915_trace_irq_get(ring, seqno);
 			   ),
 
-	    TP_printk("dev=%u, ring=%u, seqno=%u",
-		      __entry->dev, __entry->ring, __entry->seqno)
+	    TP_printk("dev=%u, ring=%u, seqno=%u, flags=%x",
+		      __entry->dev, __entry->ring, __entry->seqno, __entry->flags)
 );
 
 TRACE_EVENT(i915_gem_ring_flush,
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 6345878..5829b3a 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -221,14 +221,20 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 adpa;
 
-	adpa = ADPA_HOTPLUG_BITS;
+	if (HAS_PCH_SPLIT(dev))
+		adpa = ADPA_HOTPLUG_BITS;
+	else
+		adpa = 0;
+
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
 		adpa |= ADPA_HSYNC_ACTIVE_HIGH;
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
 		adpa |= ADPA_VSYNC_ACTIVE_HIGH;
 
 	/* For CPT allow 3 pipe config, for others just use A or B */
-	if (HAS_PCH_CPT(dev))
+	if (HAS_PCH_LPT(dev))
+		; /* Those bits don't exist here */
+	else if (HAS_PCH_CPT(dev))
 		adpa |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
 	else if (intel_crtc->pipe == 0)
 		adpa |= ADPA_PIPE_A_SELECT;
@@ -401,12 +407,16 @@ static int intel_crt_ddc_get_modes(struct drm_connector *connector,
 				struct i2c_adapter *adapter)
 {
 	struct edid *edid;
+	int ret;
 
 	edid = intel_crt_get_edid(connector, adapter);
 	if (!edid)
 		return 0;
 
-	return intel_connector_update_modes(connector, edid);
+	ret = intel_connector_update_modes(connector, edid);
+	kfree(edid);
+
+	return ret;
 }
 
 static bool intel_crt_detect_ddc(struct drm_connector *connector)
@@ -644,10 +654,22 @@ static int intel_crt_set_property(struct drm_connector *connector,
 static void intel_crt_reset(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crt *crt = intel_attached_crt(connector);
 
-	if (HAS_PCH_SPLIT(dev))
+	if (HAS_PCH_SPLIT(dev)) {
+		u32 adpa;
+
+		adpa = I915_READ(PCH_ADPA);
+		adpa &= ~ADPA_CRT_HOTPLUG_MASK;
+		adpa |= ADPA_HOTPLUG_BITS;
+		I915_WRITE(PCH_ADPA, adpa);
+		POSTING_READ(PCH_ADPA);
+
+		DRM_DEBUG_KMS("pch crt adpa set to 0x%x\n", adpa);
 		crt->force_hotplug_required = 1;
+	}
+
 }
 
 /*
@@ -749,7 +771,10 @@ void intel_crt_init(struct drm_device *dev)
 
 	crt->base.disable = intel_disable_crt;
 	crt->base.enable = intel_enable_crt;
-	crt->base.get_hw_state = intel_crt_get_hw_state;
+	if (IS_HASWELL(dev))
+		crt->base.get_hw_state = intel_ddi_get_hw_state;
+	else
+		crt->base.get_hw_state = intel_crt_get_hw_state;
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
 
 	drm_encoder_helper_add(&crt->base.base, &crt_encoder_funcs);
@@ -766,18 +791,6 @@ void intel_crt_init(struct drm_device *dev)
 	 * Configure the automatic hotplug detection stuff
 	 */
 	crt->force_hotplug_required = 0;
-	if (HAS_PCH_SPLIT(dev)) {
-		u32 adpa;
-
-		adpa = I915_READ(PCH_ADPA);
-		adpa &= ~ADPA_CRT_HOTPLUG_MASK;
-		adpa |= ADPA_HOTPLUG_BITS;
-		I915_WRITE(PCH_ADPA, adpa);
-		POSTING_READ(PCH_ADPA);
-
-		DRM_DEBUG_KMS("pch crt adpa set to 0x%x\n", adpa);
-		crt->force_hotplug_required = 1;
-	}
 
 	dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS;
 }
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index bfe3754..58f50eb 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -58,6 +58,26 @@ static const u32 hsw_ddi_translations_fdi[] = {
 	0x00FFFFFF, 0x00040006		/* HDMI parameters */
 };
 
+static enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
+{
+	struct drm_encoder *encoder = &intel_encoder->base;
+	int type = intel_encoder->type;
+
+	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP ||
+	    type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_UNKNOWN) {
+		struct intel_digital_port *intel_dig_port =
+			enc_to_dig_port(encoder);
+		return intel_dig_port->port;
+
+	} else if (type == INTEL_OUTPUT_ANALOG) {
+		return PORT_E;
+
+	} else {
+		DRM_ERROR("Invalid DDI encoder type %d\n", type);
+		BUG();
+	}
+}
+
 /* On Haswell, DDI port buffers must be programmed with correct values
  * in advance. The buffer values are different for FDI and DP modes,
  * but the HDMI/DVI fields are shared among those. So we program the DDI
@@ -133,25 +153,34 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
-	u32 reg, temp, i;
-
-	/* Configure CPU PLL, wait for warmup */
-	I915_WRITE(SPLL_CTL,
-			SPLL_PLL_ENABLE |
-			SPLL_PLL_FREQ_1350MHz |
-			SPLL_PLL_SCC);
+	u32 temp, i, rx_ctl_val;
 
-	/* Use SPLL to drive the output when in FDI mode */
-	I915_WRITE(PORT_CLK_SEL(PORT_E),
-			PORT_CLK_SEL_SPLL);
-	I915_WRITE(PIPE_CLK_SEL(pipe),
-			PIPE_CLK_SEL_PORT(PORT_E));
-
-	udelay(20);
-
-	/* Start the training iterating through available voltages and emphasis */
-	for (i=0; i < ARRAY_SIZE(hsw_ddi_buf_ctl_values); i++) {
+	/* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the
+	 * mode set "sequence for CRT port" document:
+	 * - TP1 to TP2 time with the default value
+	 * - FDI delay to 90h
+	 */
+	I915_WRITE(_FDI_RXA_MISC, FDI_RX_PWRDN_LANE1_VAL(2) |
+				  FDI_RX_PWRDN_LANE0_VAL(2) |
+				  FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
+
+	/* Enable the PCH Receiver FDI PLL */
+	rx_ctl_val = FDI_RX_PLL_ENABLE | FDI_RX_ENHANCE_FRAME_ENABLE |
+		     ((intel_crtc->fdi_lanes - 1) << 19);
+	I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
+	POSTING_READ(_FDI_RXA_CTL);
+	udelay(220);
+
+	/* Switch from Rawclk to PCDclk */
+	rx_ctl_val |= FDI_PCDCLK;
+	I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
+
+	/* Configure Port Clock Select */
+	I915_WRITE(PORT_CLK_SEL(PORT_E), intel_crtc->ddi_pll_sel);
+
+	/* Start the training iterating through available voltages and emphasis,
+	 * testing each value twice. */
+	for (i = 0; i < ARRAY_SIZE(hsw_ddi_buf_ctl_values) * 2; i++) {
 		/* Configure DP_TP_CTL with auto-training */
 		I915_WRITE(DP_TP_CTL(PORT_E),
 					DP_TP_CTL_FDI_AUTOTRAIN |
@@ -160,103 +189,63 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
 					DP_TP_CTL_ENABLE);
 
 		/* Configure and enable DDI_BUF_CTL for DDI E with next voltage */
-		temp = I915_READ(DDI_BUF_CTL(PORT_E));
-		temp = (temp & ~DDI_BUF_EMP_MASK);
 		I915_WRITE(DDI_BUF_CTL(PORT_E),
-				temp |
-				DDI_BUF_CTL_ENABLE |
-				DDI_PORT_WIDTH_X2 |
-				hsw_ddi_buf_ctl_values[i]);
+			   DDI_BUF_CTL_ENABLE |
+			   ((intel_crtc->fdi_lanes - 1) << 1) |
+			   hsw_ddi_buf_ctl_values[i / 2]);
+		POSTING_READ(DDI_BUF_CTL(PORT_E));
 
 		udelay(600);
 
-		/* We need to program FDI_RX_MISC with the default TP1 to TP2
-		 * values before enabling the receiver, and configure the delay
-		 * for the FDI timing generator to 90h. Luckily, all the other
-		 * bits are supposed to be zeroed, so we can write those values
-		 * directly.
-		 */
-		I915_WRITE(FDI_RX_MISC(pipe), FDI_RX_TP1_TO_TP2_48 |
-				FDI_RX_FDI_DELAY_90);
-
-		/* Enable CPU FDI Receiver with auto-training */
-		reg = FDI_RX_CTL(pipe);
-		I915_WRITE(reg,
-				I915_READ(reg) |
-					FDI_LINK_TRAIN_AUTO |
-					FDI_RX_ENABLE |
-					FDI_LINK_TRAIN_PATTERN_1_CPT |
-					FDI_RX_ENHANCE_FRAME_ENABLE |
-					FDI_PORT_WIDTH_2X_LPT |
-					FDI_RX_PLL_ENABLE);
-		POSTING_READ(reg);
-		udelay(100);
+		/* Program PCH FDI Receiver TU */
+		I915_WRITE(_FDI_RXA_TUSIZE1, TU_SIZE(64));
+
+		/* Enable PCH FDI Receiver with auto-training */
+		rx_ctl_val |= FDI_RX_ENABLE | FDI_LINK_TRAIN_AUTO;
+		I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
+		POSTING_READ(_FDI_RXA_CTL);
+
+		/* Wait for FDI receiver lane calibration */
+		udelay(30);
+
+		/* Unset FDI_RX_MISC pwrdn lanes */
+		temp = I915_READ(_FDI_RXA_MISC);
+		temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK);
+		I915_WRITE(_FDI_RXA_MISC, temp);
+		POSTING_READ(_FDI_RXA_MISC);
+
+		/* Wait for FDI auto training time */
+		udelay(5);
 
 		temp = I915_READ(DP_TP_STATUS(PORT_E));
 		if (temp & DP_TP_STATUS_AUTOTRAIN_DONE) {
-			DRM_DEBUG_DRIVER("BUF_CTL training done on %d step\n", i);
+			DRM_DEBUG_KMS("FDI link training done on step %d\n", i);
 
 			/* Enable normal pixel sending for FDI */
 			I915_WRITE(DP_TP_CTL(PORT_E),
-						DP_TP_CTL_FDI_AUTOTRAIN |
-						DP_TP_CTL_LINK_TRAIN_NORMAL |
-						DP_TP_CTL_ENHANCED_FRAME_ENABLE |
-						DP_TP_CTL_ENABLE);
-
-			/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in FDI mode */
-			temp = I915_READ(DDI_FUNC_CTL(pipe));
-			temp &= ~PIPE_DDI_PORT_MASK;
-			temp |= PIPE_DDI_SELECT_PORT(PORT_E) |
-					PIPE_DDI_MODE_SELECT_FDI |
-					PIPE_DDI_FUNC_ENABLE |
-					PIPE_DDI_PORT_WIDTH_X2;
-			I915_WRITE(DDI_FUNC_CTL(pipe),
-					temp);
-			break;
-		} else {
-			DRM_ERROR("Error training BUF_CTL %d\n", i);
+				   DP_TP_CTL_FDI_AUTOTRAIN |
+				   DP_TP_CTL_LINK_TRAIN_NORMAL |
+				   DP_TP_CTL_ENHANCED_FRAME_ENABLE |
+				   DP_TP_CTL_ENABLE);
 
-			/* Disable DP_TP_CTL and FDI_RX_CTL) and retry */
-			I915_WRITE(DP_TP_CTL(PORT_E),
-					I915_READ(DP_TP_CTL(PORT_E)) &
-						~DP_TP_CTL_ENABLE);
-			I915_WRITE(FDI_RX_CTL(pipe),
-					I915_READ(FDI_RX_CTL(pipe)) &
-						~FDI_RX_PLL_ENABLE);
-			continue;
+			return;
 		}
-	}
 
-	DRM_DEBUG_KMS("FDI train done.\n");
-}
+		/* Disable DP_TP_CTL and FDI_RX_CTL and retry */
+		I915_WRITE(DP_TP_CTL(PORT_E),
+			   I915_READ(DP_TP_CTL(PORT_E)) & ~DP_TP_CTL_ENABLE);
 
-/* For DDI connections, it is possible to support different outputs over the
- * same DDI port, such as HDMI or DP or even VGA via FDI. So we don't know by
- * the time the output is detected what exactly is on the other end of it. This
- * function aims at providing support for this detection and proper output
- * configuration.
- */
-void intel_ddi_init(struct drm_device *dev, enum port port)
-{
-	/* For now, we don't do any proper output detection and assume that we
-	 * handle HDMI only */
+		rx_ctl_val &= ~FDI_RX_ENABLE;
+		I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
 
-	switch(port){
-	case PORT_A:
-		/* We don't handle eDP and DP yet */
-		DRM_DEBUG_DRIVER("Found digital output on DDI port A\n");
-		break;
-	/* Assume that the  ports B, C and D are working in HDMI mode for now */
-	case PORT_B:
-	case PORT_C:
-	case PORT_D:
-		intel_hdmi_init(dev, DDI_BUF_CTL(port), port);
-		break;
-	default:
-		DRM_DEBUG_DRIVER("No handlers defined for port %d, skipping DDI initialization\n",
-				port);
-		break;
+		/* Reset FDI_RX_MISC pwrdn lanes */
+		temp = I915_READ(_FDI_RXA_MISC);
+		temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK);
+		temp |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2);
+		I915_WRITE(_FDI_RXA_MISC, temp);
 	}
+
+	DRM_ERROR("FDI link training failed!\n");
 }
 
 /* WRPLL clock dividers */
@@ -645,116 +634,426 @@ static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = {
 	{298000,	2,	21,	19},
 };
 
-void intel_ddi_mode_set(struct drm_encoder *encoder,
-				struct drm_display_mode *mode,
-				struct drm_display_mode *adjusted_mode)
+static void intel_ddi_mode_set(struct drm_encoder *encoder,
+			       struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode)
 {
-	struct drm_device *dev = encoder->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc = encoder->crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
-	int port = intel_hdmi->ddi_port;
+	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+	int port = intel_ddi_get_encoder_port(intel_encoder);
 	int pipe = intel_crtc->pipe;
-	int p, n2, r2;
-	u32 temp, i;
+	int type = intel_encoder->type;
 
-	/* On Haswell, we need to enable the clocks and prepare DDI function to
-	 * work in HDMI mode for this pipe.
-	 */
-	DRM_DEBUG_KMS("Preparing HDMI DDI mode for Haswell on port %c, pipe %c\n", port_name(port), pipe_name(pipe));
+	DRM_DEBUG_KMS("Preparing DDI mode for Haswell on port %c, pipe %c\n",
+		      port_name(port), pipe_name(pipe));
+
+	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+		intel_dp->DP = DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
+		switch (intel_dp->lane_count) {
+		case 1:
+			intel_dp->DP |= DDI_PORT_WIDTH_X1;
+			break;
+		case 2:
+			intel_dp->DP |= DDI_PORT_WIDTH_X2;
+			break;
+		case 4:
+			intel_dp->DP |= DDI_PORT_WIDTH_X4;
+			break;
+		default:
+			intel_dp->DP |= DDI_PORT_WIDTH_X4;
+			WARN(1, "Unexpected DP lane count %d\n",
+			     intel_dp->lane_count);
+			break;
+		}
+
+		intel_dp_init_link_config(intel_dp);
+
+	} else if (type == INTEL_OUTPUT_HDMI) {
+		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+
+		if (intel_hdmi->has_audio) {
+			/* Proper support for digital audio needs a new logic
+			 * and a new set of registers, so we leave it for future
+			 * patch bombing.
+			 */
+			DRM_DEBUG_DRIVER("HDMI audio on pipe %c on DDI\n",
+					 pipe_name(intel_crtc->pipe));
+
+			/* write eld */
+			DRM_DEBUG_DRIVER("HDMI audio: write eld information\n");
+			intel_write_eld(encoder, adjusted_mode);
+		}
+
+		intel_hdmi->set_infoframes(encoder, adjusted_mode);
+	}
+}
+
+static struct intel_encoder *
+intel_ddi_get_crtc_encoder(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *intel_encoder, *ret = NULL;
+	int num_encoders = 0;
+
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
+		ret = intel_encoder;
+		num_encoders++;
+	}
+
+	if (num_encoders != 1)
+		WARN(1, "%d encoders on crtc for pipe %d\n", num_encoders,
+		     intel_crtc->pipe);
+
+	BUG_ON(ret == NULL);
+	return ret;
+}
+
+void intel_ddi_put_crtc_pll(struct drm_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	uint32_t val;
+
+	switch (intel_crtc->ddi_pll_sel) {
+	case PORT_CLK_SEL_SPLL:
+		plls->spll_refcount--;
+		if (plls->spll_refcount == 0) {
+			DRM_DEBUG_KMS("Disabling SPLL\n");
+			val = I915_READ(SPLL_CTL);
+			WARN_ON(!(val & SPLL_PLL_ENABLE));
+			I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
+			POSTING_READ(SPLL_CTL);
+		}
+		break;
+	case PORT_CLK_SEL_WRPLL1:
+		plls->wrpll1_refcount--;
+		if (plls->wrpll1_refcount == 0) {
+			DRM_DEBUG_KMS("Disabling WRPLL 1\n");
+			val = I915_READ(WRPLL_CTL1);
+			WARN_ON(!(val & WRPLL_PLL_ENABLE));
+			I915_WRITE(WRPLL_CTL1, val & ~WRPLL_PLL_ENABLE);
+			POSTING_READ(WRPLL_CTL1);
+		}
+		break;
+	case PORT_CLK_SEL_WRPLL2:
+		plls->wrpll2_refcount--;
+		if (plls->wrpll2_refcount == 0) {
+			DRM_DEBUG_KMS("Disabling WRPLL 2\n");
+			val = I915_READ(WRPLL_CTL2);
+			WARN_ON(!(val & WRPLL_PLL_ENABLE));
+			I915_WRITE(WRPLL_CTL2, val & ~WRPLL_PLL_ENABLE);
+			POSTING_READ(WRPLL_CTL2);
+		}
+		break;
+	}
+
+	WARN(plls->spll_refcount < 0, "Invalid SPLL refcount\n");
+	WARN(plls->wrpll1_refcount < 0, "Invalid WRPLL1 refcount\n");
+	WARN(plls->wrpll2_refcount < 0, "Invalid WRPLL2 refcount\n");
+
+	intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE;
+}
+
+static void intel_ddi_calculate_wrpll(int clock, int *p, int *n2, int *r2)
+{
+	u32 i;
 
 	for (i = 0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++)
-		if (crtc->mode.clock <= wrpll_tmds_clock_table[i].clock)
+		if (clock <= wrpll_tmds_clock_table[i].clock)
 			break;
 
 	if (i == ARRAY_SIZE(wrpll_tmds_clock_table))
 		i--;
 
-	p = wrpll_tmds_clock_table[i].p;
-	n2 = wrpll_tmds_clock_table[i].n2;
-	r2 = wrpll_tmds_clock_table[i].r2;
+	*p = wrpll_tmds_clock_table[i].p;
+	*n2 = wrpll_tmds_clock_table[i].n2;
+	*r2 = wrpll_tmds_clock_table[i].r2;
 
-	if (wrpll_tmds_clock_table[i].clock != crtc->mode.clock)
-		DRM_INFO("WR PLL: using settings for %dKHz on %dKHz mode\n",
-			 wrpll_tmds_clock_table[i].clock, crtc->mode.clock);
+	if (wrpll_tmds_clock_table[i].clock != clock)
+		DRM_INFO("WRPLL: using settings for %dKHz on %dKHz mode\n",
+			 wrpll_tmds_clock_table[i].clock, clock);
 
-	DRM_DEBUG_KMS("WR PLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
-		      crtc->mode.clock, p, n2, r2);
+	DRM_DEBUG_KMS("WRPLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
+		      clock, *p, *n2, *r2);
+}
 
-	/* Enable LCPLL if disabled */
-	temp = I915_READ(LCPLL_CTL);
-	if (temp & LCPLL_PLL_DISABLE)
-		I915_WRITE(LCPLL_CTL,
-				temp & ~LCPLL_PLL_DISABLE);
+bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
+	struct drm_encoder *encoder = &intel_encoder->base;
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
+	int type = intel_encoder->type;
+	enum pipe pipe = intel_crtc->pipe;
+	uint32_t reg, val;
 
-	/* Configure WR PLL 1, program the correct divider values for
-	 * the desired frequency and wait for warmup */
-	I915_WRITE(WRPLL_CTL1,
-			WRPLL_PLL_ENABLE |
-			WRPLL_PLL_SELECT_LCPLL_2700 |
-			WRPLL_DIVIDER_REFERENCE(r2) |
-			WRPLL_DIVIDER_FEEDBACK(n2) |
-			WRPLL_DIVIDER_POST(p));
+	/* TODO: reuse PLLs when possible (compare values) */
 
-	udelay(20);
+	intel_ddi_put_crtc_pll(crtc);
 
-	/* Use WRPLL1 clock to drive the output to the port, and tell the pipe to use
-	 * this port for connection.
-	 */
-	I915_WRITE(PORT_CLK_SEL(port),
-			PORT_CLK_SEL_WRPLL1);
-	I915_WRITE(PIPE_CLK_SEL(pipe),
-			PIPE_CLK_SEL_PORT(port));
+	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+		switch (intel_dp->link_bw) {
+		case DP_LINK_BW_1_62:
+			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810;
+			break;
+		case DP_LINK_BW_2_7:
+			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350;
+			break;
+		case DP_LINK_BW_5_4:
+			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700;
+			break;
+		default:
+			DRM_ERROR("Link bandwidth %d unsupported\n",
+				  intel_dp->link_bw);
+			return false;
+		}
+
+		/* We don't need to turn any PLL on because we'll use LCPLL. */
+		return true;
+
+	} else if (type == INTEL_OUTPUT_HDMI) {
+		int p, n2, r2;
+
+		if (plls->wrpll1_refcount == 0) {
+			DRM_DEBUG_KMS("Using WRPLL 1 on pipe %c\n",
+				      pipe_name(pipe));
+			plls->wrpll1_refcount++;
+			reg = WRPLL_CTL1;
+			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1;
+		} else if (plls->wrpll2_refcount == 0) {
+			DRM_DEBUG_KMS("Using WRPLL 2 on pipe %c\n",
+				      pipe_name(pipe));
+			plls->wrpll2_refcount++;
+			reg = WRPLL_CTL2;
+			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2;
+		} else {
+			DRM_ERROR("No WRPLLs available!\n");
+			return false;
+		}
+
+		WARN(I915_READ(reg) & WRPLL_PLL_ENABLE,
+		     "WRPLL already enabled\n");
 
+		intel_ddi_calculate_wrpll(clock, &p, &n2, &r2);
+
+		val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
+		      WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
+		      WRPLL_DIVIDER_POST(p);
+
+	} else if (type == INTEL_OUTPUT_ANALOG) {
+		if (plls->spll_refcount == 0) {
+			DRM_DEBUG_KMS("Using SPLL on pipe %c\n",
+				      pipe_name(pipe));
+			plls->spll_refcount++;
+			reg = SPLL_CTL;
+			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL;
+		}
+
+		WARN(I915_READ(reg) & SPLL_PLL_ENABLE,
+		     "SPLL already enabled\n");
+
+		val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
+
+	} else {
+		WARN(1, "Invalid DDI encoder type %d\n", type);
+		return false;
+	}
+
+	I915_WRITE(reg, val);
 	udelay(20);
 
-	if (intel_hdmi->has_audio) {
-		/* Proper support for digital audio needs a new logic and a new set
-		 * of registers, so we leave it for future patch bombing.
-		 */
-		DRM_DEBUG_DRIVER("HDMI audio on pipe %c on DDI\n",
-				 pipe_name(intel_crtc->pipe));
+	return true;
+}
+
+void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
+	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
+	int type = intel_encoder->type;
+	uint32_t temp;
 
-		/* write eld */
-		DRM_DEBUG_DRIVER("HDMI audio: write eld information\n");
-		intel_write_eld(encoder, adjusted_mode);
+	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
+
+		temp = TRANS_MSA_SYNC_CLK;
+		switch (intel_crtc->bpp) {
+		case 18:
+			temp |= TRANS_MSA_6_BPC;
+			break;
+		case 24:
+			temp |= TRANS_MSA_8_BPC;
+			break;
+		case 30:
+			temp |= TRANS_MSA_10_BPC;
+			break;
+		case 36:
+			temp |= TRANS_MSA_12_BPC;
+			break;
+		default:
+			temp |= TRANS_MSA_8_BPC;
+			WARN(1, "%d bpp unsupported by DDI function\n",
+			     intel_crtc->bpp);
+		}
+		I915_WRITE(TRANS_MSA_MISC(cpu_transcoder), temp);
 	}
+}
 
-	/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in HDMI mode */
-	temp = PIPE_DDI_FUNC_ENABLE | PIPE_DDI_SELECT_PORT(port);
+void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
+	struct drm_encoder *encoder = &intel_encoder->base;
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	enum pipe pipe = intel_crtc->pipe;
+	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
+	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+	int type = intel_encoder->type;
+	uint32_t temp;
+
+	/* Enable TRANS_DDI_FUNC_CTL for the pipe to work in HDMI mode */
+	temp = TRANS_DDI_FUNC_ENABLE;
+	temp |= TRANS_DDI_SELECT_PORT(port);
 
 	switch (intel_crtc->bpp) {
 	case 18:
-		temp |= PIPE_DDI_BPC_6;
+		temp |= TRANS_DDI_BPC_6;
 		break;
 	case 24:
-		temp |= PIPE_DDI_BPC_8;
+		temp |= TRANS_DDI_BPC_8;
 		break;
 	case 30:
-		temp |= PIPE_DDI_BPC_10;
+		temp |= TRANS_DDI_BPC_10;
 		break;
 	case 36:
-		temp |= PIPE_DDI_BPC_12;
+		temp |= TRANS_DDI_BPC_12;
 		break;
 	default:
-		WARN(1, "%d bpp unsupported by pipe DDI function\n",
+		WARN(1, "%d bpp unsupported by transcoder DDI function\n",
 		     intel_crtc->bpp);
 	}
 
-	if (intel_hdmi->has_hdmi_sink)
-		temp |= PIPE_DDI_MODE_SELECT_HDMI;
+	if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC)
+		temp |= TRANS_DDI_PVSYNC;
+	if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
+		temp |= TRANS_DDI_PHSYNC;
+
+	if (cpu_transcoder == TRANSCODER_EDP) {
+		switch (pipe) {
+		case PIPE_A:
+			temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
+			break;
+		case PIPE_B:
+			temp |= TRANS_DDI_EDP_INPUT_B_ONOFF;
+			break;
+		case PIPE_C:
+			temp |= TRANS_DDI_EDP_INPUT_C_ONOFF;
+			break;
+		default:
+			BUG();
+			break;
+		}
+	}
+
+	if (type == INTEL_OUTPUT_HDMI) {
+		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+
+		if (intel_hdmi->has_hdmi_sink)
+			temp |= TRANS_DDI_MODE_SELECT_HDMI;
+		else
+			temp |= TRANS_DDI_MODE_SELECT_DVI;
+
+	} else if (type == INTEL_OUTPUT_ANALOG) {
+		temp |= TRANS_DDI_MODE_SELECT_FDI;
+		temp |= (intel_crtc->fdi_lanes - 1) << 1;
+
+	} else if (type == INTEL_OUTPUT_DISPLAYPORT ||
+		   type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+		temp |= TRANS_DDI_MODE_SELECT_DP_SST;
+
+		switch (intel_dp->lane_count) {
+		case 1:
+			temp |= TRANS_DDI_PORT_WIDTH_X1;
+			break;
+		case 2:
+			temp |= TRANS_DDI_PORT_WIDTH_X2;
+			break;
+		case 4:
+			temp |= TRANS_DDI_PORT_WIDTH_X4;
+			break;
+		default:
+			temp |= TRANS_DDI_PORT_WIDTH_X4;
+			WARN(1, "Unsupported lane count %d\n",
+			     intel_dp->lane_count);
+		}
+
+	} else {
+		WARN(1, "Invalid encoder type %d for pipe %d\n",
+		     intel_encoder->type, pipe);
+	}
+
+	I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp);
+}
+
+void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
+				       enum transcoder cpu_transcoder)
+{
+	uint32_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
+	uint32_t val = I915_READ(reg);
+
+	val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK);
+	val |= TRANS_DDI_PORT_NONE;
+	I915_WRITE(reg, val);
+}
+
+bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
+{
+	struct drm_device *dev = intel_connector->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *intel_encoder = intel_connector->encoder;
+	int type = intel_connector->base.connector_type;
+	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+	enum pipe pipe = 0;
+	enum transcoder cpu_transcoder;
+	uint32_t tmp;
+
+	if (!intel_encoder->get_hw_state(intel_encoder, &pipe))
+		return false;
+
+	if (port == PORT_A)
+		cpu_transcoder = TRANSCODER_EDP;
 	else
-		temp |= PIPE_DDI_MODE_SELECT_DVI;
+		cpu_transcoder = pipe;
+
+	tmp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
 
-	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
-		temp |= PIPE_DDI_PVSYNC;
-	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
-		temp |= PIPE_DDI_PHSYNC;
+	switch (tmp & TRANS_DDI_MODE_SELECT_MASK) {
+	case TRANS_DDI_MODE_SELECT_HDMI:
+	case TRANS_DDI_MODE_SELECT_DVI:
+		return (type == DRM_MODE_CONNECTOR_HDMIA);
+
+	case TRANS_DDI_MODE_SELECT_DP_SST:
+		if (type == DRM_MODE_CONNECTOR_eDP)
+			return true;
+	case TRANS_DDI_MODE_SELECT_DP_MST:
+		return (type == DRM_MODE_CONNECTOR_DisplayPort);
 
-	I915_WRITE(DDI_FUNC_CTL(pipe), temp);
+	case TRANS_DDI_MODE_SELECT_FDI:
+		return (type == DRM_MODE_CONNECTOR_VGA);
 
-	intel_hdmi->set_infoframes(encoder, adjusted_mode);
+	default:
+		return false;
+	}
 }
 
 bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
@@ -762,58 +1061,430 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 {
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+	enum port port = intel_ddi_get_encoder_port(encoder);
 	u32 tmp;
 	int i;
 
-	tmp = I915_READ(DDI_BUF_CTL(intel_hdmi->ddi_port));
+	tmp = I915_READ(DDI_BUF_CTL(port));
 
 	if (!(tmp & DDI_BUF_CTL_ENABLE))
 		return false;
 
-	for_each_pipe(i) {
-		tmp = I915_READ(DDI_FUNC_CTL(i));
+	if (port == PORT_A) {
+		tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
 
-		if ((tmp & PIPE_DDI_PORT_MASK)
-		    == PIPE_DDI_SELECT_PORT(intel_hdmi->ddi_port)) {
-			*pipe = i;
-			return true;
+		switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
+		case TRANS_DDI_EDP_INPUT_A_ON:
+		case TRANS_DDI_EDP_INPUT_A_ONOFF:
+			*pipe = PIPE_A;
+			break;
+		case TRANS_DDI_EDP_INPUT_B_ONOFF:
+			*pipe = PIPE_B;
+			break;
+		case TRANS_DDI_EDP_INPUT_C_ONOFF:
+			*pipe = PIPE_C;
+			break;
+		}
+
+		return true;
+	} else {
+		for (i = TRANSCODER_A; i <= TRANSCODER_C; i++) {
+			tmp = I915_READ(TRANS_DDI_FUNC_CTL(i));
+
+			if ((tmp & TRANS_DDI_PORT_MASK)
+			    == TRANS_DDI_SELECT_PORT(port)) {
+				*pipe = i;
+				return true;
+			}
 		}
 	}
 
-	DRM_DEBUG_KMS("No pipe for ddi port %i found\n", intel_hdmi->ddi_port);
+	DRM_DEBUG_KMS("No pipe for ddi port %i found\n", port);
 
 	return true;
 }
 
-void intel_enable_ddi(struct intel_encoder *encoder)
+static uint32_t intel_ddi_get_crtc_pll(struct drm_i915_private *dev_priv,
+				       enum pipe pipe)
+{
+	uint32_t temp, ret;
+	enum port port;
+	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
+								      pipe);
+	int i;
+
+	if (cpu_transcoder == TRANSCODER_EDP) {
+		port = PORT_A;
+	} else {
+		temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
+		temp &= TRANS_DDI_PORT_MASK;
+
+		for (i = PORT_B; i <= PORT_E; i++)
+			if (temp == TRANS_DDI_SELECT_PORT(i))
+				port = i;
+	}
+
+	ret = I915_READ(PORT_CLK_SEL(port));
+
+	DRM_DEBUG_KMS("Pipe %c connected to port %c using clock 0x%08x\n",
+		      pipe_name(pipe), port_name(port), ret);
+
+	return ret;
+}
+
+void intel_ddi_setup_hw_pll_state(struct drm_device *dev)
 {
-	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
-	int port = intel_hdmi->ddi_port;
-	u32 temp;
+	enum pipe pipe;
+	struct intel_crtc *intel_crtc;
 
-	temp = I915_READ(DDI_BUF_CTL(port));
-	temp |= DDI_BUF_CTL_ENABLE;
+	for_each_pipe(pipe) {
+		intel_crtc =
+			to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
 
-	/* Enable DDI_BUF_CTL. In HDMI/DVI mode, the port width,
-	 * and swing/emphasis values are ignored so nothing special needs
-	 * to be done besides enabling the port.
-	 */
-	I915_WRITE(DDI_BUF_CTL(port), temp);
+		if (!intel_crtc->active)
+			continue;
+
+		intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv,
+								 pipe);
+
+		switch (intel_crtc->ddi_pll_sel) {
+		case PORT_CLK_SEL_SPLL:
+			dev_priv->ddi_plls.spll_refcount++;
+			break;
+		case PORT_CLK_SEL_WRPLL1:
+			dev_priv->ddi_plls.wrpll1_refcount++;
+			break;
+		case PORT_CLK_SEL_WRPLL2:
+			dev_priv->ddi_plls.wrpll2_refcount++;
+			break;
+		}
+	}
 }
 
-void intel_disable_ddi(struct intel_encoder *encoder)
+void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc)
+{
+	struct drm_crtc *crtc = &intel_crtc->base;
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
+	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
+
+	if (cpu_transcoder != TRANSCODER_EDP)
+		I915_WRITE(TRANS_CLK_SEL(cpu_transcoder),
+			   TRANS_CLK_SEL_PORT(port));
+}
+
+void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc)
+{
+	struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
+	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
+
+	if (cpu_transcoder != TRANSCODER_EDP)
+		I915_WRITE(TRANS_CLK_SEL(cpu_transcoder),
+			   TRANS_CLK_SEL_DISABLED);
+}
+
+static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
+{
+	struct drm_encoder *encoder = &intel_encoder->base;
+	struct drm_crtc *crtc = encoder->crtc;
+	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+	int type = intel_encoder->type;
+
+	if (type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+		ironlake_edp_panel_vdd_on(intel_dp);
+		ironlake_edp_panel_on(intel_dp);
+		ironlake_edp_panel_vdd_off(intel_dp, true);
+	}
+
+	WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
+	I915_WRITE(PORT_CLK_SEL(port), intel_crtc->ddi_pll_sel);
+
+	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
+		intel_dp_start_link_train(intel_dp);
+		intel_dp_complete_link_train(intel_dp);
+	}
+}
+
+static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
+				    enum port port)
+{
+	uint32_t reg = DDI_BUF_CTL(port);
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		udelay(1);
+		if (I915_READ(reg) & DDI_BUF_IS_IDLE)
+			return;
+	}
+	DRM_ERROR("Timeout waiting for DDI BUF %c idle bit\n", port_name(port));
+}
+
+static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
+{
+	struct drm_encoder *encoder = &intel_encoder->base;
+	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+	int type = intel_encoder->type;
+	uint32_t val;
+	bool wait = false;
+
+	val = I915_READ(DDI_BUF_CTL(port));
+	if (val & DDI_BUF_CTL_ENABLE) {
+		val &= ~DDI_BUF_CTL_ENABLE;
+		I915_WRITE(DDI_BUF_CTL(port), val);
+		wait = true;
+	}
+
+	val = I915_READ(DP_TP_CTL(port));
+	val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK);
+	val |= DP_TP_CTL_LINK_TRAIN_PAT1;
+	I915_WRITE(DP_TP_CTL(port), val);
+
+	if (wait)
+		intel_wait_ddi_buf_idle(dev_priv, port);
+
+	if (type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+		ironlake_edp_panel_vdd_on(intel_dp);
+		ironlake_edp_panel_off(intel_dp);
+	}
+
+	I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
+}
+
+static void intel_enable_ddi(struct intel_encoder *intel_encoder)
+{
+	struct drm_encoder *encoder = &intel_encoder->base;
+	struct drm_device *dev = encoder->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+	int type = intel_encoder->type;
+
+	if (type == INTEL_OUTPUT_HDMI) {
+		/* In HDMI/DVI mode, the port width, and swing/emphasis values
+		 * are ignored so nothing special needs to be done besides
+		 * enabling the port.
+		 */
+		I915_WRITE(DDI_BUF_CTL(port), DDI_BUF_CTL_ENABLE);
+	} else if (type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+		ironlake_edp_backlight_on(intel_dp);
+	}
+}
+
+static void intel_disable_ddi(struct intel_encoder *intel_encoder)
+{
+	struct drm_encoder *encoder = &intel_encoder->base;
+	int type = intel_encoder->type;
+
+	if (type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+		ironlake_edp_backlight_off(intel_dp);
+	}
+}
+
+int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv)
+{
+	if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT)
+		return 450;
+	else if ((I915_READ(LCPLL_CTL) & LCPLL_CLK_FREQ_MASK) ==
+		 LCPLL_CLK_FREQ_450)
+		return 450;
+	else
+		return 540;
+}
+
+void intel_ddi_pll_init(struct drm_device *dev)
 {
-	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
-	int port = intel_hdmi->ddi_port;
-	u32 temp;
+	uint32_t val = I915_READ(LCPLL_CTL);
+
+	/* The LCPLL register should be turned on by the BIOS. For now let's
+	 * just check its state and print errors in case something is wrong.
+	 * Don't even try to turn it on.
+	 */
+
+	DRM_DEBUG_KMS("CDCLK running at %dMHz\n",
+		      intel_ddi_get_cdclk_freq(dev_priv));
+
+	if (val & LCPLL_CD_SOURCE_FCLK)
+		DRM_ERROR("CDCLK source is not LCPLL\n");
+
+	if (val & LCPLL_PLL_DISABLE)
+		DRM_ERROR("LCPLL is disabled\n");
+}
+
+void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder)
+{
+	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+	enum port port = intel_dig_port->port;
+	bool wait;
+	uint32_t val;
+
+	if (I915_READ(DP_TP_CTL(port)) & DP_TP_CTL_ENABLE) {
+		val = I915_READ(DDI_BUF_CTL(port));
+		if (val & DDI_BUF_CTL_ENABLE) {
+			val &= ~DDI_BUF_CTL_ENABLE;
+			I915_WRITE(DDI_BUF_CTL(port), val);
+			wait = true;
+		}
+
+		val = I915_READ(DP_TP_CTL(port));
+		val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK);
+		val |= DP_TP_CTL_LINK_TRAIN_PAT1;
+		I915_WRITE(DP_TP_CTL(port), val);
+		POSTING_READ(DP_TP_CTL(port));
+
+		if (wait)
+			intel_wait_ddi_buf_idle(dev_priv, port);
+	}
+
+	val = DP_TP_CTL_ENABLE | DP_TP_CTL_MODE_SST |
+	      DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE;
+	if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN)
+		val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
+	I915_WRITE(DP_TP_CTL(port), val);
+	POSTING_READ(DP_TP_CTL(port));
+
+	intel_dp->DP |= DDI_BUF_CTL_ENABLE;
+	I915_WRITE(DDI_BUF_CTL(port), intel_dp->DP);
+	POSTING_READ(DDI_BUF_CTL(port));
+
+	udelay(600);
+}
+
+void intel_ddi_fdi_disable(struct drm_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
+	uint32_t val;
+
+	intel_ddi_post_disable(intel_encoder);
+
+	val = I915_READ(_FDI_RXA_CTL);
+	val &= ~FDI_RX_ENABLE;
+	I915_WRITE(_FDI_RXA_CTL, val);
+
+	val = I915_READ(_FDI_RXA_MISC);
+	val &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK);
+	val |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2);
+	I915_WRITE(_FDI_RXA_MISC, val);
+
+	val = I915_READ(_FDI_RXA_CTL);
+	val &= ~FDI_PCDCLK;
+	I915_WRITE(_FDI_RXA_CTL, val);
+
+	val = I915_READ(_FDI_RXA_CTL);
+	val &= ~FDI_RX_PLL_ENABLE;
+	I915_WRITE(_FDI_RXA_CTL, val);
+}
+
+static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder)
+{
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+	int type = intel_encoder->type;
+
+	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP)
+		intel_dp_check_link_status(intel_dp);
+}
+
+static void intel_ddi_destroy(struct drm_encoder *encoder)
+{
+	/* HDMI has nothing special to destroy, so we can go with this. */
+	intel_dp_encoder_destroy(encoder);
+}
+
+static bool intel_ddi_mode_fixup(struct drm_encoder *encoder,
+				 const struct drm_display_mode *mode,
+				 struct drm_display_mode *adjusted_mode)
+{
+	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+	int type = intel_encoder->type;
+
+	WARN(type == INTEL_OUTPUT_UNKNOWN, "mode_fixup() on unknown output!\n");
+
+	if (type == INTEL_OUTPUT_HDMI)
+		return intel_hdmi_mode_fixup(encoder, mode, adjusted_mode);
+	else
+		return intel_dp_mode_fixup(encoder, mode, adjusted_mode);
+}
+
+static const struct drm_encoder_funcs intel_ddi_funcs = {
+	.destroy = intel_ddi_destroy,
+};
+
+static const struct drm_encoder_helper_funcs intel_ddi_helper_funcs = {
+	.mode_fixup = intel_ddi_mode_fixup,
+	.mode_set = intel_ddi_mode_set,
+	.disable = intel_encoder_noop,
+};
+
+void intel_ddi_init(struct drm_device *dev, enum port port)
+{
+	struct intel_digital_port *intel_dig_port;
+	struct intel_encoder *intel_encoder;
+	struct drm_encoder *encoder;
+	struct intel_connector *hdmi_connector = NULL;
+	struct intel_connector *dp_connector = NULL;
+
+	intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL);
+	if (!intel_dig_port)
+		return;
+
+	dp_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
+	if (!dp_connector) {
+		kfree(intel_dig_port);
+		return;
+	}
+
+	if (port != PORT_A) {
+		hdmi_connector = kzalloc(sizeof(struct intel_connector),
+					 GFP_KERNEL);
+		if (!hdmi_connector) {
+			kfree(dp_connector);
+			kfree(intel_dig_port);
+			return;
+		}
+	}
+
+	intel_encoder = &intel_dig_port->base;
+	encoder = &intel_encoder->base;
+
+	drm_encoder_init(dev, encoder, &intel_ddi_funcs,
+			 DRM_MODE_ENCODER_TMDS);
+	drm_encoder_helper_add(encoder, &intel_ddi_helper_funcs);
+
+	intel_encoder->enable = intel_enable_ddi;
+	intel_encoder->pre_enable = intel_ddi_pre_enable;
+	intel_encoder->disable = intel_disable_ddi;
+	intel_encoder->post_disable = intel_ddi_post_disable;
+	intel_encoder->get_hw_state = intel_ddi_get_hw_state;
+
+	intel_dig_port->port = port;
+	if (hdmi_connector)
+		intel_dig_port->hdmi.sdvox_reg = DDI_BUF_CTL(port);
+	else
+		intel_dig_port->hdmi.sdvox_reg = 0;
+	intel_dig_port->dp.output_reg = DDI_BUF_CTL(port);
 
-	temp = I915_READ(DDI_BUF_CTL(port));
-	temp &= ~DDI_BUF_CTL_ENABLE;
+	intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
+	intel_encoder->crtc_mask =  (1 << 0) | (1 << 1) | (1 << 2);
+	intel_encoder->cloneable = false;
+	intel_encoder->hot_plug = intel_ddi_hot_plug;
 
-	I915_WRITE(DDI_BUF_CTL(port), temp);
+	if (hdmi_connector)
+		intel_hdmi_init_connector(intel_dig_port, hdmi_connector);
+	intel_dp_init_connector(intel_dig_port, dp_connector);
 }
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4154bcd..3f94cb4 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -41,8 +41,6 @@
 #include <drm/drm_crtc_helper.h>
 #include <linux/dma_remapping.h>
 
-#define HAS_eDP (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
-
 bool intel_pipe_has_type(struct drm_crtc *crtc, int type);
 static void intel_increase_pllclock(struct drm_crtc *crtc);
 static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on);
@@ -80,6 +78,16 @@ struct intel_limit {
 /* FDI */
 #define IRONLAKE_FDI_FREQ		2700000 /* in kHz for mode->clock */
 
+int
+intel_pch_rawclk(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	WARN_ON(!HAS_PCH_SPLIT(dev));
+
+	return I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK;
+}
+
 static bool
 intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 		    int target, int refclk, intel_clock_t *match_clock,
@@ -380,7 +388,7 @@ static const intel_limit_t intel_limits_vlv_dac = {
 
 static const intel_limit_t intel_limits_vlv_hdmi = {
 	.dot = { .min = 20000, .max = 165000 },
-	.vco = { .min = 5994000, .max = 4000000 },
+	.vco = { .min = 4000000, .max = 5994000},
 	.n = { .min = 1, .max = 7 },
 	.m = { .min = 60, .max = 300 }, /* guess */
 	.m1 = { .min = 2, .max = 3 },
@@ -393,10 +401,10 @@ static const intel_limit_t intel_limits_vlv_hdmi = {
 };
 
 static const intel_limit_t intel_limits_vlv_dp = {
-	.dot = { .min = 162000, .max = 270000 },
-	.vco = { .min = 5994000, .max = 4000000 },
+	.dot = { .min = 25000, .max = 270000 },
+	.vco = { .min = 4000000, .max = 6000000 },
 	.n = { .min = 1, .max = 7 },
-	.m = { .min = 60, .max = 300 }, /* guess */
+	.m = { .min = 22, .max = 450 },
 	.m1 = { .min = 2, .max = 3 },
 	.m2 = { .min = 11, .max = 156 },
 	.p = { .min = 10, .max = 30 },
@@ -531,7 +539,7 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
 				limit = &intel_limits_ironlake_single_lvds;
 		}
 	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
-			HAS_eDP)
+		   intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
 		limit = &intel_limits_ironlake_display_port;
 	else
 		limit = &intel_limits_ironlake_dac;
@@ -927,6 +935,15 @@ intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,
 	return true;
 }
 
+enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
+					     enum pipe pipe)
+{
+	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	return intel_crtc->cpu_transcoder;
+}
+
 static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -999,9 +1016,11 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
 void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
+								      pipe);
 
 	if (INTEL_INFO(dev)->gen >= 4) {
-		int reg = PIPECONF(pipe);
+		int reg = PIPECONF(cpu_transcoder);
 
 		/* Wait for the Pipe State to go off */
 		if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0,
@@ -1103,12 +1122,14 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv,
 	int reg;
 	u32 val;
 	bool cur_state;
+	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
+								      pipe);
 
 	if (IS_HASWELL(dev_priv->dev)) {
 		/* On Haswell, DDI is used instead of FDI_TX_CTL */
-		reg = DDI_FUNC_CTL(pipe);
+		reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
 		val = I915_READ(reg);
-		cur_state = !!(val & PIPE_DDI_FUNC_ENABLE);
+		cur_state = !!(val & TRANS_DDI_FUNC_ENABLE);
 	} else {
 		reg = FDI_TX_CTL(pipe);
 		val = I915_READ(reg);
@@ -1212,12 +1233,14 @@ void assert_pipe(struct drm_i915_private *dev_priv,
 	int reg;
 	u32 val;
 	bool cur_state;
+	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
+								      pipe);
 
 	/* if we need the pipe A quirk it must be always on */
 	if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
 		state = true;
 
-	reg = PIPECONF(pipe);
+	reg = PIPECONF(cpu_transcoder);
 	val = I915_READ(reg);
 	cur_state = !!(val & PIPECONF_ENABLE);
 	WARN(cur_state != state,
@@ -1554,14 +1577,14 @@ out_unlock:
 }
 
 /**
- * intel_enable_pch_pll - enable PCH PLL
+ * ironlake_enable_pch_pll - enable PCH PLL
  * @dev_priv: i915 private structure
  * @pipe: pipe PLL to enable
  *
  * The PCH PLL needs to be enabled before the PCH transcoder, since it
  * drives the transcoder clock.
  */
-static void intel_enable_pch_pll(struct intel_crtc *intel_crtc)
+static void ironlake_enable_pch_pll(struct intel_crtc *intel_crtc)
 {
 	struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
 	struct intel_pch_pll *pll;
@@ -1645,12 +1668,12 @@ static void intel_disable_pch_pll(struct intel_crtc *intel_crtc)
 	pll->on = false;
 }
 
-static void intel_enable_transcoder(struct drm_i915_private *dev_priv,
-				    enum pipe pipe)
+static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
+					   enum pipe pipe)
 {
-	int reg;
-	u32 val, pipeconf_val;
+	struct drm_device *dev = dev_priv->dev;
 	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+	uint32_t reg, val, pipeconf_val;
 
 	/* PCH only available on ILK+ */
 	BUG_ON(dev_priv->info->gen < 5);
@@ -1664,10 +1687,15 @@ static void intel_enable_transcoder(struct drm_i915_private *dev_priv,
 	assert_fdi_tx_enabled(dev_priv, pipe);
 	assert_fdi_rx_enabled(dev_priv, pipe);
 
-	if (IS_HASWELL(dev_priv->dev) && pipe > 0) {
-		DRM_ERROR("Attempting to enable transcoder on Haswell with pipe > 0\n");
-		return;
+	if (HAS_PCH_CPT(dev)) {
+		/* Workaround: Set the timing override bit before enabling the
+		 * pch transcoder. */
+		reg = TRANS_CHICKEN2(pipe);
+		val = I915_READ(reg);
+		val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
+		I915_WRITE(reg, val);
 	}
+
 	reg = TRANSCONF(pipe);
 	val = I915_READ(reg);
 	pipeconf_val = I915_READ(PIPECONF(pipe));
@@ -1696,11 +1724,42 @@ static void intel_enable_transcoder(struct drm_i915_private *dev_priv,
 		DRM_ERROR("failed to enable transcoder %d\n", pipe);
 }
 
-static void intel_disable_transcoder(struct drm_i915_private *dev_priv,
-				     enum pipe pipe)
+static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
+				      enum transcoder cpu_transcoder)
 {
-	int reg;
-	u32 val;
+	u32 val, pipeconf_val;
+
+	/* PCH only available on ILK+ */
+	BUG_ON(dev_priv->info->gen < 5);
+
+	/* FDI must be feeding us bits for PCH ports */
+	assert_fdi_tx_enabled(dev_priv, cpu_transcoder);
+	assert_fdi_rx_enabled(dev_priv, TRANSCODER_A);
+
+	/* Workaround: set timing override bit. */
+	val = I915_READ(_TRANSA_CHICKEN2);
+	val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
+	I915_WRITE(_TRANSA_CHICKEN2, val);
+
+	val = TRANS_ENABLE;
+	pipeconf_val = I915_READ(PIPECONF(cpu_transcoder));
+
+	if ((pipeconf_val & PIPECONF_INTERLACE_MASK_HSW) ==
+	    PIPECONF_INTERLACED_ILK)
+		val |= TRANS_INTERLACED;
+	else
+		val |= TRANS_PROGRESSIVE;
+
+	I915_WRITE(TRANSCONF(TRANSCODER_A), val);
+	if (wait_for(I915_READ(_TRANSACONF) & TRANS_STATE_ENABLE, 100))
+		DRM_ERROR("Failed to enable PCH transcoder\n");
+}
+
+static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
+					    enum pipe pipe)
+{
+	struct drm_device *dev = dev_priv->dev;
+	uint32_t reg, val;
 
 	/* FDI relies on the transcoder */
 	assert_fdi_tx_disabled(dev_priv, pipe);
@@ -1716,6 +1775,31 @@ static void intel_disable_transcoder(struct drm_i915_private *dev_priv,
 	/* wait for PCH transcoder off, transcoder state */
 	if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50))
 		DRM_ERROR("failed to disable transcoder %d\n", pipe);
+
+	if (!HAS_PCH_IBX(dev)) {
+		/* Workaround: Clear the timing override chicken bit again. */
+		reg = TRANS_CHICKEN2(pipe);
+		val = I915_READ(reg);
+		val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE;
+		I915_WRITE(reg, val);
+	}
+}
+
+static void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv)
+{
+	u32 val;
+
+	val = I915_READ(_TRANSACONF);
+	val &= ~TRANS_ENABLE;
+	I915_WRITE(_TRANSACONF, val);
+	/* wait for PCH transcoder off, transcoder state */
+	if (wait_for((I915_READ(_TRANSACONF) & TRANS_STATE_ENABLE) == 0, 50))
+		DRM_ERROR("Failed to disable PCH transcoder\n");
+
+	/* Workaround: clear timing override bit. */
+	val = I915_READ(_TRANSA_CHICKEN2);
+	val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE;
+	I915_WRITE(_TRANSA_CHICKEN2, val);
 }
 
 /**
@@ -1735,6 +1819,8 @@ static void intel_disable_transcoder(struct drm_i915_private *dev_priv,
 static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
 			      bool pch_port)
 {
+	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
+								      pipe);
 	int reg;
 	u32 val;
 
@@ -1754,7 +1840,7 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
 		/* FIXME: assert CPU port conditions for SNB+ */
 	}
 
-	reg = PIPECONF(pipe);
+	reg = PIPECONF(cpu_transcoder);
 	val = I915_READ(reg);
 	if (val & PIPECONF_ENABLE)
 		return;
@@ -1778,6 +1864,8 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
 static void intel_disable_pipe(struct drm_i915_private *dev_priv,
 			       enum pipe pipe)
 {
+	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
+								      pipe);
 	int reg;
 	u32 val;
 
@@ -1791,7 +1879,7 @@ static void intel_disable_pipe(struct drm_i915_private *dev_priv,
 	if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
 		return;
 
-	reg = PIPECONF(pipe);
+	reg = PIPECONF(cpu_transcoder);
 	val = I915_READ(reg);
 	if ((val & PIPECONF_ENABLE) == 0)
 		return;
@@ -1807,8 +1895,10 @@ static void intel_disable_pipe(struct drm_i915_private *dev_priv,
 void intel_flush_display_plane(struct drm_i915_private *dev_priv,
 				      enum plane plane)
 {
-	I915_WRITE(DSPADDR(plane), I915_READ(DSPADDR(plane)));
-	I915_WRITE(DSPSURF(plane), I915_READ(DSPSURF(plane)));
+	if (dev_priv->info->gen >= 4)
+		I915_WRITE(DSPSURF(plane), I915_READ(DSPSURF(plane)));
+	else
+		I915_WRITE(DSPADDR(plane), I915_READ(DSPADDR(plane)));
 }
 
 /**
@@ -1926,9 +2016,9 @@ void intel_unpin_fb_obj(struct drm_i915_gem_object *obj)
 
 /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
  * is assumed to be a power-of-two. */
-static unsigned long gen4_compute_dspaddr_offset_xtiled(int *x, int *y,
-							unsigned int bpp,
-							unsigned int pitch)
+unsigned long intel_gen4_compute_offset_xtiled(int *x, int *y,
+					       unsigned int bpp,
+					       unsigned int pitch)
 {
 	int tile_rows, tiles;
 
@@ -1969,24 +2059,38 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 	dspcntr = I915_READ(reg);
 	/* Mask out pixel format bits in case we change it */
 	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
-	switch (fb->bits_per_pixel) {
-	case 8:
+	switch (fb->pixel_format) {
+	case DRM_FORMAT_C8:
 		dspcntr |= DISPPLANE_8BPP;
 		break;
-	case 16:
-		if (fb->depth == 15)
-			dspcntr |= DISPPLANE_15_16BPP;
-		else
-			dspcntr |= DISPPLANE_16BPP;
+	case DRM_FORMAT_XRGB1555:
+	case DRM_FORMAT_ARGB1555:
+		dspcntr |= DISPPLANE_BGRX555;
 		break;
-	case 24:
-	case 32:
-		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+	case DRM_FORMAT_RGB565:
+		dspcntr |= DISPPLANE_BGRX565;
+		break;
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+		dspcntr |= DISPPLANE_BGRX888;
+		break;
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+		dspcntr |= DISPPLANE_RGBX888;
+		break;
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_ARGB2101010:
+		dspcntr |= DISPPLANE_BGRX101010;
+		break;
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_ABGR2101010:
+		dspcntr |= DISPPLANE_RGBX101010;
 		break;
 	default:
-		DRM_ERROR("Unknown color depth %d\n", fb->bits_per_pixel);
+		DRM_ERROR("Unknown pixel format 0x%08x\n", fb->pixel_format);
 		return -EINVAL;
 	}
+
 	if (INTEL_INFO(dev)->gen >= 4) {
 		if (obj->tiling_mode != I915_TILING_NONE)
 			dspcntr |= DISPPLANE_TILED;
@@ -2000,9 +2104,9 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 
 	if (INTEL_INFO(dev)->gen >= 4) {
 		intel_crtc->dspaddr_offset =
-			gen4_compute_dspaddr_offset_xtiled(&x, &y,
-							   fb->bits_per_pixel / 8,
-							   fb->pitches[0]);
+			intel_gen4_compute_offset_xtiled(&x, &y,
+							 fb->bits_per_pixel / 8,
+							 fb->pitches[0]);
 		linear_offset -= intel_crtc->dspaddr_offset;
 	} else {
 		intel_crtc->dspaddr_offset = linear_offset;
@@ -2053,27 +2157,31 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
 	dspcntr = I915_READ(reg);
 	/* Mask out pixel format bits in case we change it */
 	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
-	switch (fb->bits_per_pixel) {
-	case 8:
+	switch (fb->pixel_format) {
+	case DRM_FORMAT_C8:
 		dspcntr |= DISPPLANE_8BPP;
 		break;
-	case 16:
-		if (fb->depth != 16)
-			return -EINVAL;
-
-		dspcntr |= DISPPLANE_16BPP;
+	case DRM_FORMAT_RGB565:
+		dspcntr |= DISPPLANE_BGRX565;
 		break;
-	case 24:
-	case 32:
-		if (fb->depth == 24)
-			dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
-		else if (fb->depth == 30)
-			dspcntr |= DISPPLANE_32BPP_30BIT_NO_ALPHA;
-		else
-			return -EINVAL;
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+		dspcntr |= DISPPLANE_BGRX888;
+		break;
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+		dspcntr |= DISPPLANE_RGBX888;
+		break;
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_ARGB2101010:
+		dspcntr |= DISPPLANE_BGRX101010;
+		break;
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_ABGR2101010:
+		dspcntr |= DISPPLANE_RGBX101010;
 		break;
 	default:
-		DRM_ERROR("Unknown color depth %d\n", fb->bits_per_pixel);
+		DRM_ERROR("Unknown pixel format 0x%08x\n", fb->pixel_format);
 		return -EINVAL;
 	}
 
@@ -2089,9 +2197,9 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
 
 	linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
 	intel_crtc->dspaddr_offset =
-		gen4_compute_dspaddr_offset_xtiled(&x, &y,
-						   fb->bits_per_pixel / 8,
-						   fb->pitches[0]);
+		intel_gen4_compute_offset_xtiled(&x, &y,
+						 fb->bits_per_pixel / 8,
+						 fb->pitches[0]);
 	linear_offset -= intel_crtc->dspaddr_offset;
 
 	DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n",
@@ -2099,8 +2207,12 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
 	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
 	I915_MODIFY_DISPBASE(DSPSURF(plane),
 			     obj->gtt_offset + intel_crtc->dspaddr_offset);
-	I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
-	I915_WRITE(DSPLINOFF(plane), linear_offset);
+	if (IS_HASWELL(dev)) {
+		I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
+	} else {
+		I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
+		I915_WRITE(DSPLINOFF(plane), linear_offset);
+	}
 	POSTING_READ(reg);
 
 	return 0;
@@ -2148,13 +2260,39 @@ intel_finish_fb(struct drm_framebuffer *old_fb)
 	return ret;
 }
 
+static void intel_crtc_update_sarea_pos(struct drm_crtc *crtc, int x, int y)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_master_private *master_priv;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	if (!dev->primary->master)
+		return;
+
+	master_priv = dev->primary->master->driver_priv;
+	if (!master_priv->sarea_priv)
+		return;
+
+	switch (intel_crtc->pipe) {
+	case 0:
+		master_priv->sarea_priv->pipeA_x = x;
+		master_priv->sarea_priv->pipeA_y = y;
+		break;
+	case 1:
+		master_priv->sarea_priv->pipeB_x = x;
+		master_priv->sarea_priv->pipeB_y = y;
+		break;
+	default:
+		break;
+	}
+}
+
 static int
 intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 		    struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_master_private *master_priv;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_framebuffer *old_fb;
 	int ret;
@@ -2206,20 +2344,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 	intel_update_fbc(dev);
 	mutex_unlock(&dev->struct_mutex);
 
-	if (!dev->primary->master)
-		return 0;
-
-	master_priv = dev->primary->master->driver_priv;
-	if (!master_priv->sarea_priv)
-		return 0;
-
-	if (intel_crtc->pipe) {
-		master_priv->sarea_priv->pipeB_x = x;
-		master_priv->sarea_priv->pipeB_y = y;
-	} else {
-		master_priv->sarea_priv->pipeA_x = x;
-		master_priv->sarea_priv->pipeA_y = y;
-	}
+	intel_crtc_update_sarea_pos(crtc, x, y);
 
 	return 0;
 }
@@ -2314,6 +2439,29 @@ static void cpt_phase_pointer_enable(struct drm_device *dev, int pipe)
 	POSTING_READ(SOUTH_CHICKEN1);
 }
 
+static void ivb_modeset_global_resources(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *pipe_B_crtc =
+		to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]);
+	struct intel_crtc *pipe_C_crtc =
+		to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_C]);
+	uint32_t temp;
+
+	/* When everything is off disable fdi C so that we could enable fdi B
+	 * with all lanes. XXX: This misses the case where a pipe is not using
+	 * any pch resources and so doesn't need any fdi lanes. */
+	if (!pipe_B_crtc->base.enabled && !pipe_C_crtc->base.enabled) {
+		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 = I915_READ(SOUTH_CHICKEN1);
+		temp &= ~FDI_BC_BIFURCATION_SELECT;
+		DRM_DEBUG_KMS("disabling fdi C rx\n");
+		I915_WRITE(SOUTH_CHICKEN1, temp);
+	}
+}
+
 /* The FDI link training functions for ILK/Ibexpeak. */
 static void ironlake_fdi_link_train(struct drm_crtc *crtc)
 {
@@ -2357,11 +2505,9 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc)
 	udelay(150);
 
 	/* Ironlake workaround, enable clock pointer after FDI enable*/
-	if (HAS_PCH_IBX(dev)) {
-		I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR);
-		I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR |
-			   FDI_RX_PHASE_SYNC_POINTER_EN);
-	}
+	I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR);
+	I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR |
+		   FDI_RX_PHASE_SYNC_POINTER_EN);
 
 	reg = FDI_RX_IIR(pipe);
 	for (tries = 0; tries < 5; tries++) {
@@ -2450,6 +2596,9 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
 	temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
 	I915_WRITE(reg, temp | FDI_TX_ENABLE);
 
+	I915_WRITE(FDI_RX_MISC(pipe),
+		   FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
+
 	reg = FDI_RX_CTL(pipe);
 	temp = I915_READ(reg);
 	if (HAS_PCH_CPT(dev)) {
@@ -2464,8 +2613,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
 	POSTING_READ(reg);
 	udelay(150);
 
-	if (HAS_PCH_CPT(dev))
-		cpt_phase_pointer_enable(dev, pipe);
+	cpt_phase_pointer_enable(dev, pipe);
 
 	for (i = 0; i < 4; i++) {
 		reg = FDI_TX_CTL(pipe);
@@ -2570,6 +2718,9 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
 	POSTING_READ(reg);
 	udelay(150);
 
+	DRM_DEBUG_KMS("FDI_RX_IIR before link train 0x%x\n",
+		      I915_READ(FDI_RX_IIR(pipe)));
+
 	/* enable CPU FDI TX and PCH FDI RX */
 	reg = FDI_TX_CTL(pipe);
 	temp = I915_READ(reg);
@@ -2582,6 +2733,9 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
 	temp |= FDI_COMPOSITE_SYNC;
 	I915_WRITE(reg, temp | FDI_TX_ENABLE);
 
+	I915_WRITE(FDI_RX_MISC(pipe),
+		   FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
+
 	reg = FDI_RX_CTL(pipe);
 	temp = I915_READ(reg);
 	temp &= ~FDI_LINK_TRAIN_AUTO;
@@ -2593,8 +2747,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
 	POSTING_READ(reg);
 	udelay(150);
 
-	if (HAS_PCH_CPT(dev))
-		cpt_phase_pointer_enable(dev, pipe);
+	cpt_phase_pointer_enable(dev, pipe);
 
 	for (i = 0; i < 4; i++) {
 		reg = FDI_TX_CTL(pipe);
@@ -2613,7 +2766,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
 		if (temp & FDI_RX_BIT_LOCK ||
 		    (I915_READ(reg) & FDI_RX_BIT_LOCK)) {
 			I915_WRITE(reg, temp | FDI_RX_BIT_LOCK);
-			DRM_DEBUG_KMS("FDI train 1 done.\n");
+			DRM_DEBUG_KMS("FDI train 1 done, level %i.\n", i);
 			break;
 		}
 	}
@@ -2654,7 +2807,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
 
 		if (temp & FDI_RX_SYMBOL_LOCK) {
 			I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK);
-			DRM_DEBUG_KMS("FDI train 2 done.\n");
+			DRM_DEBUG_KMS("FDI train 2 done, level %i.\n", i);
 			break;
 		}
 	}
@@ -2671,9 +2824,6 @@ static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)
 	int pipe = intel_crtc->pipe;
 	u32 reg, temp;
 
-	/* Write the TU size bits so error detection works */
-	I915_WRITE(FDI_RX_TUSIZE1(pipe),
-		   I915_READ(PIPE_DATA_M1(pipe)) & TU_SIZE_MASK);
 
 	/* enable PCH FDI RX PLL, wait warmup plus DMI latency */
 	reg = FDI_RX_CTL(pipe);
@@ -2839,7 +2989,7 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
 	mutex_unlock(&dev->struct_mutex);
 }
 
-static bool intel_crtc_driving_pch(struct drm_crtc *crtc)
+static bool ironlake_crtc_driving_pch(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct intel_encoder *intel_encoder;
@@ -2849,23 +2999,6 @@ static bool intel_crtc_driving_pch(struct drm_crtc *crtc)
 	 * must be driven by its own crtc; no sharing is possible.
 	 */
 	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
-
-		/* On Haswell, LPT PCH handles the VGA connection via FDI, and Haswell
-		 * CPU handles all others */
-		if (IS_HASWELL(dev)) {
-			/* It is still unclear how this will work on PPT, so throw up a warning */
-			WARN_ON(!HAS_PCH_LPT(dev));
-
-			if (intel_encoder->type == INTEL_OUTPUT_ANALOG) {
-				DRM_DEBUG_KMS("Haswell detected DAC encoder, assuming is PCH\n");
-				return true;
-			} else {
-				DRM_DEBUG_KMS("Haswell detected encoder %d, assuming is CPU\n",
-					      intel_encoder->type);
-				return false;
-			}
-		}
-
 		switch (intel_encoder->type) {
 		case INTEL_OUTPUT_EDP:
 			if (!intel_encoder_is_pch_edp(&intel_encoder->base))
@@ -2877,6 +3010,11 @@ static bool intel_crtc_driving_pch(struct drm_crtc *crtc)
 	return true;
 }
 
+static bool haswell_crtc_driving_pch(struct drm_crtc *crtc)
+{
+	return intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG);
+}
+
 /* Program iCLKIP clock to the desired frequency */
 static void lpt_program_iclkip(struct drm_crtc *crtc)
 {
@@ -2986,15 +3124,24 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
 
 	assert_transcoder_disabled(dev_priv, pipe);
 
+	/* Write the TU size bits before fdi link training, so that error
+	 * detection works. */
+	I915_WRITE(FDI_RX_TUSIZE1(pipe),
+		   I915_READ(PIPE_DATA_M1(pipe)) & TU_SIZE_MASK);
+
 	/* For PCH output, training FDI link */
 	dev_priv->display.fdi_link_train(crtc);
 
-	intel_enable_pch_pll(intel_crtc);
+	/* XXX: pch pll's can be enabled any time before we enable the PCH
+	 * transcoder, and we actually should do this to not upset any PCH
+	 * transcoder that already use the clock when we share it.
+	 *
+	 * Note that enable_pch_pll tries to do the right thing, but get_pch_pll
+	 * unconditionally resets the pll - we need that to have the right LVDS
+	 * enable sequence. */
+	ironlake_enable_pch_pll(intel_crtc);
 
-	if (HAS_PCH_LPT(dev)) {
-		DRM_DEBUG_KMS("LPT detected: programming iCLKIP\n");
-		lpt_program_iclkip(crtc);
-	} else if (HAS_PCH_CPT(dev)) {
+	if (HAS_PCH_CPT(dev)) {
 		u32 sel;
 
 		temp = I915_READ(PCH_DPLL_SEL);
@@ -3031,8 +3178,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
 	I915_WRITE(TRANS_VSYNC(pipe),  I915_READ(VSYNC(pipe)));
 	I915_WRITE(TRANS_VSYNCSHIFT(pipe),  I915_READ(VSYNCSHIFT(pipe)));
 
-	if (!IS_HASWELL(dev))
-		intel_fdi_normal_train(crtc);
+	intel_fdi_normal_train(crtc);
 
 	/* For PCH DP, enable TRANS_DP_CTL */
 	if (HAS_PCH_CPT(dev) &&
@@ -3064,15 +3210,37 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
 			temp |= TRANS_DP_PORT_SEL_D;
 			break;
 		default:
-			DRM_DEBUG_KMS("Wrong PCH DP port return. Guess port B\n");
-			temp |= TRANS_DP_PORT_SEL_B;
-			break;
+			BUG();
 		}
 
 		I915_WRITE(reg, temp);
 	}
 
-	intel_enable_transcoder(dev_priv, pipe);
+	ironlake_enable_pch_transcoder(dev_priv, pipe);
+}
+
+static void lpt_pch_enable(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
+
+	assert_transcoder_disabled(dev_priv, TRANSCODER_A);
+
+	lpt_program_iclkip(crtc);
+
+	/* Set transcoder timing. */
+	I915_WRITE(_TRANS_HTOTAL_A, I915_READ(HTOTAL(cpu_transcoder)));
+	I915_WRITE(_TRANS_HBLANK_A, I915_READ(HBLANK(cpu_transcoder)));
+	I915_WRITE(_TRANS_HSYNC_A,  I915_READ(HSYNC(cpu_transcoder)));
+
+	I915_WRITE(_TRANS_VTOTAL_A, I915_READ(VTOTAL(cpu_transcoder)));
+	I915_WRITE(_TRANS_VBLANK_A, I915_READ(VBLANK(cpu_transcoder)));
+	I915_WRITE(_TRANS_VSYNC_A,  I915_READ(VSYNC(cpu_transcoder)));
+	I915_WRITE(_TRANS_VSYNCSHIFT_A, I915_READ(VSYNCSHIFT(cpu_transcoder)));
+
+	lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
 }
 
 static void intel_put_pch_pll(struct intel_crtc *intel_crtc)
@@ -3165,16 +3333,12 @@ prepare: /* separate function? */
 void intel_cpt_verify_modeset(struct drm_device *dev, int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int dslreg = PIPEDSL(pipe), tc2reg = TRANS_CHICKEN2(pipe);
+	int dslreg = PIPEDSL(pipe);
 	u32 temp;
 
 	temp = I915_READ(dslreg);
 	udelay(500);
 	if (wait_for(I915_READ(dslreg) != temp, 5)) {
-		/* Without this, mode sets may fail silently on FDI */
-		I915_WRITE(tc2reg, TRANS_AUTOTRAIN_GEN_STALL_DIS);
-		udelay(250);
-		I915_WRITE(tc2reg, 0);
 		if (wait_for(I915_READ(dslreg) != temp, 5))
 			DRM_ERROR("mode set failed: pipe %d stuck\n", pipe);
 	}
@@ -3205,9 +3369,12 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 			I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN);
 	}
 
-	is_pch_port = intel_crtc_driving_pch(crtc);
+	is_pch_port = ironlake_crtc_driving_pch(crtc);
 
 	if (is_pch_port) {
+		/* Note: FDI PLL enabling _must_ be done before we enable the
+		 * cpu pipes, hence this is separate from all the other fdi/pch
+		 * enabling. */
 		ironlake_fdi_pll_enable(intel_crtc);
 	} else {
 		assert_fdi_tx_disabled(dev_priv, pipe);
@@ -3220,7 +3387,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
 	/* Enable panel fitting for LVDS */
 	if (dev_priv->pch_pf_size &&
-	    (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || HAS_eDP)) {
+	    (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) ||
+	     intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
 		/* Force use of hard-coded filter coefficients
 		 * as some pre-programmed values are broken,
 		 * e.g. x201.
@@ -3265,6 +3433,82 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	intel_wait_for_vblank(dev, intel_crtc->pipe);
 }
 
+static void haswell_crtc_enable(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *encoder;
+	int pipe = intel_crtc->pipe;
+	int plane = intel_crtc->plane;
+	bool is_pch_port;
+
+	WARN_ON(!crtc->enabled);
+
+	if (intel_crtc->active)
+		return;
+
+	intel_crtc->active = true;
+	intel_update_watermarks(dev);
+
+	is_pch_port = haswell_crtc_driving_pch(crtc);
+
+	if (is_pch_port)
+		dev_priv->display.fdi_link_train(crtc);
+
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		if (encoder->pre_enable)
+			encoder->pre_enable(encoder);
+
+	intel_ddi_enable_pipe_clock(intel_crtc);
+
+	/* Enable panel fitting for eDP */
+	if (dev_priv->pch_pf_size &&
+	    intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
+		/* Force use of hard-coded filter coefficients
+		 * as some pre-programmed values are broken,
+		 * e.g. x201.
+		 */
+		I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3);
+		I915_WRITE(PF_WIN_POS(pipe), dev_priv->pch_pf_pos);
+		I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size);
+	}
+
+	/*
+	 * On ILK+ LUT must be loaded before the pipe is running but with
+	 * clocks enabled
+	 */
+	intel_crtc_load_lut(crtc);
+
+	intel_ddi_set_pipe_settings(crtc);
+	intel_ddi_enable_pipe_func(crtc);
+
+	intel_enable_pipe(dev_priv, pipe, is_pch_port);
+	intel_enable_plane(dev_priv, plane, pipe);
+
+	if (is_pch_port)
+		lpt_pch_enable(crtc);
+
+	mutex_lock(&dev->struct_mutex);
+	intel_update_fbc(dev);
+	mutex_unlock(&dev->struct_mutex);
+
+	intel_crtc_update_cursor(crtc, true);
+
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->enable(encoder);
+
+	/*
+	 * There seems to be a race in PCH platform hw (at least on some
+	 * outputs) where an enabled pipe still completes any pageflip right
+	 * away (as if the pipe is off) instead of waiting for vblank. As soon
+	 * as the first vblank happend, everything works as expected. Hence just
+	 * wait for one vblank before returning to avoid strange things
+	 * happening.
+	 */
+	intel_wait_for_vblank(dev, intel_crtc->pipe);
+}
+
 static void ironlake_crtc_disable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -3303,7 +3547,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
 	ironlake_fdi_disable(crtc);
 
-	intel_disable_transcoder(dev_priv, pipe);
+	ironlake_disable_pch_transcoder(dev_priv, pipe);
 
 	if (HAS_PCH_CPT(dev)) {
 		/* disable TRANS_DP_CTL */
@@ -3345,15 +3589,81 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	mutex_unlock(&dev->struct_mutex);
 }
 
-static void ironlake_crtc_off(struct drm_crtc *crtc)
+static void haswell_crtc_disable(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	intel_put_pch_pll(intel_crtc);
-}
+	struct intel_encoder *encoder;
+	int pipe = intel_crtc->pipe;
+	int plane = intel_crtc->plane;
+	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
+	bool is_pch_port;
 
-static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
-{
-	if (!enable && intel_crtc->overlay) {
+	if (!intel_crtc->active)
+		return;
+
+	is_pch_port = haswell_crtc_driving_pch(crtc);
+
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->disable(encoder);
+
+	intel_crtc_wait_for_pending_flips(crtc);
+	drm_vblank_off(dev, pipe);
+	intel_crtc_update_cursor(crtc, false);
+
+	intel_disable_plane(dev_priv, plane, pipe);
+
+	if (dev_priv->cfb_plane == plane)
+		intel_disable_fbc(dev);
+
+	intel_disable_pipe(dev_priv, pipe);
+
+	intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
+
+	/* Disable PF */
+	I915_WRITE(PF_CTL(pipe), 0);
+	I915_WRITE(PF_WIN_SZ(pipe), 0);
+
+	intel_ddi_disable_pipe_clock(intel_crtc);
+
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		if (encoder->post_disable)
+			encoder->post_disable(encoder);
+
+	if (is_pch_port) {
+		lpt_disable_pch_transcoder(dev_priv);
+		intel_ddi_fdi_disable(crtc);
+	}
+
+	intel_crtc->active = false;
+	intel_update_watermarks(dev);
+
+	mutex_lock(&dev->struct_mutex);
+	intel_update_fbc(dev);
+	mutex_unlock(&dev->struct_mutex);
+}
+
+static void ironlake_crtc_off(struct drm_crtc *crtc)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	intel_put_pch_pll(intel_crtc);
+}
+
+static void haswell_crtc_off(struct drm_crtc *crtc)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	/* Stop saying we're using TRANSCODER_EDP because some other CRTC might
+	 * start using it. */
+	intel_crtc->cpu_transcoder = intel_crtc->pipe;
+
+	intel_ddi_put_crtc_pll(crtc);
+}
+
+static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
+{
+	if (!enable && intel_crtc->overlay) {
 		struct drm_device *dev = intel_crtc->base.dev;
 		struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -4061,7 +4371,7 @@ static void vlv_update_pll(struct drm_crtc *crtc,
 			   struct drm_display_mode *mode,
 			   struct drm_display_mode *adjusted_mode,
 			   intel_clock_t *clock, intel_clock_t *reduced_clock,
-			   int refclk, int num_connectors)
+			   int num_connectors)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4069,9 +4379,19 @@ static void vlv_update_pll(struct drm_crtc *crtc,
 	int pipe = intel_crtc->pipe;
 	u32 dpll, mdiv, pdiv;
 	u32 bestn, bestm1, bestm2, bestp1, bestp2;
-	bool is_hdmi;
+	bool is_sdvo;
+	u32 temp;
 
-	is_hdmi = intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI);
+	is_sdvo = intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ||
+		intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI);
+
+	dpll = DPLL_VGA_MODE_DIS;
+	dpll |= DPLL_EXT_BUFFER_ENABLE_VLV;
+	dpll |= DPLL_REFA_CLK_ENABLE_VLV;
+	dpll |= DPLL_INTEGRATED_CLOCK_VLV;
+
+	I915_WRITE(DPLL(pipe), dpll);
+	POSTING_READ(DPLL(pipe));
 
 	bestn = clock->n;
 	bestm1 = clock->m1;
@@ -4079,12 +4399,10 @@ static void vlv_update_pll(struct drm_crtc *crtc,
 	bestp1 = clock->p1;
 	bestp2 = clock->p2;
 
-	/* Enable DPIO clock input */
-	dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV |
-		DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV;
-	I915_WRITE(DPLL(pipe), dpll);
-	POSTING_READ(DPLL(pipe));
-
+	/*
+	 * In Valleyview PLL and program lane counter registers are exposed
+	 * through DPIO interface
+	 */
 	mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK));
 	mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT));
 	mdiv |= ((bestn << DPIO_N_SHIFT));
@@ -4095,12 +4413,13 @@ static void vlv_update_pll(struct drm_crtc *crtc,
 
 	intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), 0x01000000);
 
-	pdiv = DPIO_REFSEL_OVERRIDE | (5 << DPIO_PLL_MODESEL_SHIFT) |
+	pdiv = (1 << DPIO_REFSEL_OVERRIDE) | (5 << DPIO_PLL_MODESEL_SHIFT) |
 		(3 << DPIO_BIAS_CURRENT_CTL_SHIFT) | (1<<20) |
-		(8 << DPIO_DRIVER_CTL_SHIFT) | (5 << DPIO_CLK_BIAS_CTL_SHIFT);
+		(7 << DPIO_PLL_REFCLK_SEL_SHIFT) | (8 << DPIO_DRIVER_CTL_SHIFT) |
+		(5 << DPIO_CLK_BIAS_CTL_SHIFT);
 	intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), pdiv);
 
-	intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), 0x009f0051);
+	intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), 0x005f003b);
 
 	dpll |= DPLL_VCO_ENABLE;
 	I915_WRITE(DPLL(pipe), dpll);
@@ -4108,19 +4427,44 @@ static void vlv_update_pll(struct drm_crtc *crtc,
 	if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
 		DRM_ERROR("DPLL %d failed to lock\n", pipe);
 
-	if (is_hdmi) {
-		u32 temp = intel_mode_get_pixel_multiplier(adjusted_mode);
+	intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x620);
+
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
+		intel_dp_set_m_n(crtc, mode, adjusted_mode);
+
+	I915_WRITE(DPLL(pipe), dpll);
+
+	/* Wait for the clocks to stabilize. */
+	POSTING_READ(DPLL(pipe));
+	udelay(150);
 
+	temp = 0;
+	if (is_sdvo) {
+		temp = intel_mode_get_pixel_multiplier(adjusted_mode);
 		if (temp > 1)
 			temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
 		else
 			temp = 0;
-
-		I915_WRITE(DPLL_MD(pipe), temp);
-		POSTING_READ(DPLL_MD(pipe));
 	}
+	I915_WRITE(DPLL_MD(pipe), temp);
+	POSTING_READ(DPLL_MD(pipe));
 
-	intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x641); /* ??? */
+	/* Now program lane control registers */
+	if(intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)
+			|| intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI))
+	{
+		temp = 0x1000C4;
+		if(pipe == 1)
+			temp |= (1 << 21);
+		intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL1, temp);
+	}
+	if(intel_pipe_has_type(crtc,INTEL_OUTPUT_EDP))
+	{
+		temp = 0x1000C4;
+		if(pipe == 1)
+			temp |= (1 << 21);
+		intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL2, temp);
+	}
 }
 
 static void i9xx_update_pll(struct drm_crtc *crtc,
@@ -4136,6 +4480,8 @@ static void i9xx_update_pll(struct drm_crtc *crtc,
 	u32 dpll;
 	bool is_sdvo;
 
+	i9xx_update_pll_dividers(crtc, clock, reduced_clock);
+
 	is_sdvo = intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ||
 		intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI);
 
@@ -4236,7 +4582,7 @@ static void i9xx_update_pll(struct drm_crtc *crtc,
 
 static void i8xx_update_pll(struct drm_crtc *crtc,
 			    struct drm_display_mode *adjusted_mode,
-			    intel_clock_t *clock,
+			    intel_clock_t *clock, intel_clock_t *reduced_clock,
 			    int num_connectors)
 {
 	struct drm_device *dev = crtc->dev;
@@ -4245,6 +4591,8 @@ static void i8xx_update_pll(struct drm_crtc *crtc,
 	int pipe = intel_crtc->pipe;
 	u32 dpll;
 
+	i9xx_update_pll_dividers(crtc, clock, reduced_clock);
+
 	dpll = DPLL_VGA_MODE_DIS;
 
 	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
@@ -4294,6 +4642,64 @@ static void i8xx_update_pll(struct drm_crtc *crtc,
 	I915_WRITE(DPLL(pipe), dpll);
 }
 
+static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum pipe pipe = intel_crtc->pipe;
+	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
+	uint32_t vsyncshift;
+
+	if (!IS_GEN2(dev) && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
+		/* the chip adds 2 halflines automatically */
+		adjusted_mode->crtc_vtotal -= 1;
+		adjusted_mode->crtc_vblank_end -= 1;
+		vsyncshift = adjusted_mode->crtc_hsync_start
+			     - adjusted_mode->crtc_htotal / 2;
+	} else {
+		vsyncshift = 0;
+	}
+
+	if (INTEL_INFO(dev)->gen > 3)
+		I915_WRITE(VSYNCSHIFT(cpu_transcoder), vsyncshift);
+
+	I915_WRITE(HTOTAL(cpu_transcoder),
+		   (adjusted_mode->crtc_hdisplay - 1) |
+		   ((adjusted_mode->crtc_htotal - 1) << 16));
+	I915_WRITE(HBLANK(cpu_transcoder),
+		   (adjusted_mode->crtc_hblank_start - 1) |
+		   ((adjusted_mode->crtc_hblank_end - 1) << 16));
+	I915_WRITE(HSYNC(cpu_transcoder),
+		   (adjusted_mode->crtc_hsync_start - 1) |
+		   ((adjusted_mode->crtc_hsync_end - 1) << 16));
+
+	I915_WRITE(VTOTAL(cpu_transcoder),
+		   (adjusted_mode->crtc_vdisplay - 1) |
+		   ((adjusted_mode->crtc_vtotal - 1) << 16));
+	I915_WRITE(VBLANK(cpu_transcoder),
+		   (adjusted_mode->crtc_vblank_start - 1) |
+		   ((adjusted_mode->crtc_vblank_end - 1) << 16));
+	I915_WRITE(VSYNC(cpu_transcoder),
+		   (adjusted_mode->crtc_vsync_start - 1) |
+		   ((adjusted_mode->crtc_vsync_end - 1) << 16));
+
+	/* Workaround: when the EDP input selection is B, the VTOTAL_B must be
+	 * programmed with the VTOTAL_EDP value. Same for VTOTAL_C. This is
+	 * documented on the DDI_FUNC_CTL register description, EDP Input Select
+	 * bits. */
+	if (IS_HASWELL(dev) && cpu_transcoder == TRANSCODER_EDP &&
+	    (pipe == PIPE_B || pipe == PIPE_C))
+		I915_WRITE(VTOTAL(pipe), I915_READ(VTOTAL(cpu_transcoder)));
+
+	/* pipesrc controls the size that is scaled from, which should
+	 * always be the user's requested size.
+	 */
+	I915_WRITE(PIPESRC(pipe),
+		   ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
+}
+
 static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 			      struct drm_display_mode *mode,
 			      struct drm_display_mode *adjusted_mode,
@@ -4307,7 +4713,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 	int plane = intel_crtc->plane;
 	int refclk, num_connectors = 0;
 	intel_clock_t clock, reduced_clock;
-	u32 dspcntr, pipeconf, vsyncshift;
+	u32 dspcntr, pipeconf;
 	bool ok, has_reduced_clock = false, is_sdvo = false;
 	bool is_lvds = false, is_tv = false, is_dp = false;
 	struct intel_encoder *encoder;
@@ -4371,14 +4777,14 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 	if (is_sdvo && is_tv)
 		i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock);
 
-	i9xx_update_pll_dividers(crtc, &clock, has_reduced_clock ?
-				 &reduced_clock : NULL);
-
 	if (IS_GEN2(dev))
-		i8xx_update_pll(crtc, adjusted_mode, &clock, num_connectors);
+		i8xx_update_pll(crtc, adjusted_mode, &clock,
+				has_reduced_clock ? &reduced_clock : NULL,
+				num_connectors);
 	else if (IS_VALLEYVIEW(dev))
-		vlv_update_pll(crtc, mode,adjusted_mode, &clock, NULL,
-			       refclk, num_connectors);
+		vlv_update_pll(crtc, mode, adjusted_mode, &clock,
+				has_reduced_clock ? &reduced_clock : NULL,
+				num_connectors);
 	else
 		i9xx_update_pll(crtc, mode, adjusted_mode, &clock,
 				has_reduced_clock ? &reduced_clock : NULL,
@@ -4419,6 +4825,14 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 		}
 	}
 
+	if (IS_VALLEYVIEW(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
+		if (adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
+			pipeconf |= PIPECONF_BPP_6 |
+					PIPECONF_ENABLE |
+					I965_PIPECONF_ACTIVE;
+		}
+	}
+
 	DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
 	drm_mode_debug_printmodeline(mode);
 
@@ -4434,40 +4848,12 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 
 	pipeconf &= ~PIPECONF_INTERLACE_MASK;
 	if (!IS_GEN2(dev) &&
-	    adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
+	    adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
 		pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
-		/* the chip adds 2 halflines automatically */
-		adjusted_mode->crtc_vtotal -= 1;
-		adjusted_mode->crtc_vblank_end -= 1;
-		vsyncshift = adjusted_mode->crtc_hsync_start
-			     - adjusted_mode->crtc_htotal/2;
-	} else {
+	else
 		pipeconf |= PIPECONF_PROGRESSIVE;
-		vsyncshift = 0;
-	}
-
-	if (!IS_GEN3(dev))
-		I915_WRITE(VSYNCSHIFT(pipe), vsyncshift);
 
-	I915_WRITE(HTOTAL(pipe),
-		   (adjusted_mode->crtc_hdisplay - 1) |
-		   ((adjusted_mode->crtc_htotal - 1) << 16));
-	I915_WRITE(HBLANK(pipe),
-		   (adjusted_mode->crtc_hblank_start - 1) |
-		   ((adjusted_mode->crtc_hblank_end - 1) << 16));
-	I915_WRITE(HSYNC(pipe),
-		   (adjusted_mode->crtc_hsync_start - 1) |
-		   ((adjusted_mode->crtc_hsync_end - 1) << 16));
-
-	I915_WRITE(VTOTAL(pipe),
-		   (adjusted_mode->crtc_vdisplay - 1) |
-		   ((adjusted_mode->crtc_vtotal - 1) << 16));
-	I915_WRITE(VBLANK(pipe),
-		   (adjusted_mode->crtc_vblank_start - 1) |
-		   ((adjusted_mode->crtc_vblank_end - 1) << 16));
-	I915_WRITE(VSYNC(pipe),
-		   (adjusted_mode->crtc_vsync_start - 1) |
-		   ((adjusted_mode->crtc_vsync_end - 1) << 16));
+	intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
 
 	/* pipesrc and dspsize control the size that is scaled from,
 	 * which should always be the user's requested size.
@@ -4476,8 +4862,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 		   ((mode->vdisplay - 1) << 16) |
 		   (mode->hdisplay - 1));
 	I915_WRITE(DSPPOS(plane), 0);
-	I915_WRITE(PIPESRC(pipe),
-		   ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
 
 	I915_WRITE(PIPECONF(pipe), pipeconf);
 	POSTING_READ(PIPECONF(pipe));
@@ -4668,8 +5052,8 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,
 		val |= PIPE_12BPC;
 		break;
 	default:
-		val |= PIPE_8BPC;
-		break;
+		/* Case prevented by intel_choose_pipe_bpp_dither. */
+		BUG();
 	}
 
 	val &= ~(PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_MASK);
@@ -4686,6 +5070,31 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,
 	POSTING_READ(PIPECONF(pipe));
 }
 
+static void haswell_set_pipeconf(struct drm_crtc *crtc,
+				 struct drm_display_mode *adjusted_mode,
+				 bool dither)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
+	uint32_t val;
+
+	val = I915_READ(PIPECONF(cpu_transcoder));
+
+	val &= ~(PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_MASK);
+	if (dither)
+		val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
+
+	val &= ~PIPECONF_INTERLACE_MASK_HSW;
+	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
+		val |= PIPECONF_INTERLACED_ILK;
+	else
+		val |= PIPECONF_PROGRESSIVE;
+
+	I915_WRITE(PIPECONF(cpu_transcoder), val);
+	POSTING_READ(PIPECONF(cpu_transcoder));
+}
+
 static bool ironlake_compute_clocks(struct drm_crtc *crtc,
 				    struct drm_display_mode *adjusted_mode,
 				    intel_clock_t *clock,
@@ -4749,74 +5158,115 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc,
 	return true;
 }
 
-static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
-				  struct drm_display_mode *mode,
-				  struct drm_display_mode *adjusted_mode,
-				  int x, int y,
-				  struct drm_framebuffer *fb)
+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 bool ironlake_check_fdi_lanes(struct intel_crtc *intel_crtc)
+{
+	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *pipe_B_crtc =
+		to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]);
+
+	DRM_DEBUG_KMS("checking fdi config on pipe %i, lanes %i\n",
+		      intel_crtc->pipe, intel_crtc->fdi_lanes);
+	if (intel_crtc->fdi_lanes > 4) {
+		DRM_DEBUG_KMS("invalid fdi lane config on pipe %i: %i lanes\n",
+			      intel_crtc->pipe, intel_crtc->fdi_lanes);
+		/* Clamp lanes to avoid programming the hw with bogus values. */
+		intel_crtc->fdi_lanes = 4;
+
+		return false;
+	}
+
+	if (dev_priv->num_pipe == 2)
+		return true;
+
+	switch (intel_crtc->pipe) {
+	case PIPE_A:
+		return true;
+	case PIPE_B:
+		if (dev_priv->pipe_to_crtc_mapping[PIPE_C]->enabled &&
+		    intel_crtc->fdi_lanes > 2) {
+			DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %i: %i lanes\n",
+				      intel_crtc->pipe, intel_crtc->fdi_lanes);
+			/* Clamp lanes to avoid programming the hw with bogus values. */
+			intel_crtc->fdi_lanes = 2;
+
+			return false;
+		}
+
+		if (intel_crtc->fdi_lanes > 2)
+			WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT);
+		else
+			cpt_enable_fdi_bc_bifurcation(dev);
+
+		return true;
+	case PIPE_C:
+		if (!pipe_B_crtc->base.enabled || pipe_B_crtc->fdi_lanes <= 2) {
+			if (intel_crtc->fdi_lanes > 2) {
+				DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %i: %i lanes\n",
+					      intel_crtc->pipe, intel_crtc->fdi_lanes);
+				/* Clamp lanes to avoid programming the hw with bogus values. */
+				intel_crtc->fdi_lanes = 2;
+
+				return false;
+			}
+		} else {
+			DRM_DEBUG_KMS("fdi link B uses too many lanes to enable link C\n");
+			return false;
+		}
+
+		cpt_enable_fdi_bc_bifurcation(dev);
+
+		return true;
+	default:
+		BUG();
+	}
+}
+
+static void ironlake_set_m_n(struct drm_crtc *crtc,
+			     struct drm_display_mode *mode,
+			     struct drm_display_mode *adjusted_mode)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
-	int plane = intel_crtc->plane;
-	int num_connectors = 0;
-	intel_clock_t clock, reduced_clock;
-	u32 dpll, fp = 0, fp2 = 0;
-	bool ok, has_reduced_clock = false, is_sdvo = false;
-	bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
-	struct intel_encoder *encoder, *edp_encoder = NULL;
-	int ret;
+	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
+	struct intel_encoder *intel_encoder, *edp_encoder = NULL;
 	struct fdi_m_n m_n = {0};
-	u32 temp;
-	int target_clock, pixel_multiplier, lane, link_bw, factor;
-	unsigned int pipe_bpp;
-	bool dither;
-	bool is_cpu_edp = false, is_pch_edp = false;
+	int target_clock, pixel_multiplier, lane, link_bw;
+	bool is_dp = false, is_cpu_edp = false;
 
-	for_each_encoder_on_crtc(dev, crtc, encoder) {
-		switch (encoder->type) {
-		case INTEL_OUTPUT_LVDS:
-			is_lvds = true;
-			break;
-		case INTEL_OUTPUT_SDVO:
-		case INTEL_OUTPUT_HDMI:
-			is_sdvo = true;
-			if (encoder->needs_tv_clock)
-				is_tv = true;
-			break;
-		case INTEL_OUTPUT_TVOUT:
-			is_tv = true;
-			break;
-		case INTEL_OUTPUT_ANALOG:
-			is_crt = true;
-			break;
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
+		switch (intel_encoder->type) {
 		case INTEL_OUTPUT_DISPLAYPORT:
 			is_dp = true;
 			break;
 		case INTEL_OUTPUT_EDP:
 			is_dp = true;
-			if (intel_encoder_is_pch_edp(&encoder->base))
-				is_pch_edp = true;
-			else
+			if (!intel_encoder_is_pch_edp(&intel_encoder->base))
 				is_cpu_edp = true;
-			edp_encoder = encoder;
+			edp_encoder = intel_encoder;
 			break;
 		}
-
-		num_connectors++;
-	}
-
-	ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
-				     &has_reduced_clock, &reduced_clock);
-	if (!ok) {
-		DRM_ERROR("Couldn't find PLL settings for mode!\n");
-		return -EINVAL;
 	}
 
-	/* Ensure that the cursor is valid for the new mode before changing... */
-	intel_crtc_update_cursor(crtc, true);
-
 	/* FDI link */
 	pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
 	lane = 0;
@@ -4843,20 +5293,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	else
 		target_clock = adjusted_mode->clock;
 
-	/* determine panel color depth */
-	dither = intel_choose_pipe_bpp_dither(crtc, fb, &pipe_bpp,
-					      adjusted_mode);
-	if (is_lvds && dev_priv->lvds_dither)
-		dither = true;
-
-	if (pipe_bpp != 18 && pipe_bpp != 24 && pipe_bpp != 30 &&
-	    pipe_bpp != 36) {
-		WARN(1, "intel_choose_pipe_bpp returned invalid value %d\n",
-		     pipe_bpp);
-		pipe_bpp = 24;
-	}
-	intel_crtc->bpp = pipe_bpp;
-
 	if (!lane) {
 		/*
 		 * Account for spread spectrum to avoid
@@ -4874,10 +5310,51 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
 			     &m_n);
 
-	fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
-	if (has_reduced_clock)
-		fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
-			reduced_clock.m2;
+	I915_WRITE(PIPE_DATA_M1(cpu_transcoder), TU_SIZE(m_n.tu) | m_n.gmch_m);
+	I915_WRITE(PIPE_DATA_N1(cpu_transcoder), m_n.gmch_n);
+	I915_WRITE(PIPE_LINK_M1(cpu_transcoder), m_n.link_m);
+	I915_WRITE(PIPE_LINK_N1(cpu_transcoder), m_n.link_n);
+}
+
+static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
+				      struct drm_display_mode *adjusted_mode,
+				      intel_clock_t *clock, u32 fp)
+{
+	struct drm_crtc *crtc = &intel_crtc->base;
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *intel_encoder;
+	uint32_t dpll;
+	int factor, pixel_multiplier, num_connectors = 0;
+	bool is_lvds = false, is_sdvo = false, is_tv = false;
+	bool is_dp = false, is_cpu_edp = false;
+
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
+		switch (intel_encoder->type) {
+		case INTEL_OUTPUT_LVDS:
+			is_lvds = true;
+			break;
+		case INTEL_OUTPUT_SDVO:
+		case INTEL_OUTPUT_HDMI:
+			is_sdvo = true;
+			if (intel_encoder->needs_tv_clock)
+				is_tv = true;
+			break;
+		case INTEL_OUTPUT_TVOUT:
+			is_tv = true;
+			break;
+		case INTEL_OUTPUT_DISPLAYPORT:
+			is_dp = true;
+			break;
+		case INTEL_OUTPUT_EDP:
+			is_dp = true;
+			if (!intel_encoder_is_pch_edp(&intel_encoder->base))
+				is_cpu_edp = true;
+			break;
+		}
+
+		num_connectors++;
+	}
 
 	/* Enable autotuning of the PLL clock (if permissible) */
 	factor = 21;
@@ -4889,7 +5366,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	} else if (is_sdvo && is_tv)
 		factor = 20;
 
-	if (clock.m < factor * clock.n)
+	if (clock->m < factor * clock->n)
 		fp |= FP_CB_TUNE;
 
 	dpll = 0;
@@ -4899,55 +5376,119 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	else
 		dpll |= DPLLB_MODE_DAC_SERIAL;
 	if (is_sdvo) {
-		int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
+		pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
 		if (pixel_multiplier > 1) {
 			dpll |= (pixel_multiplier - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
 		}
-		dpll |= DPLL_DVO_HIGH_SPEED;
+		dpll |= DPLL_DVO_HIGH_SPEED;
+	}
+	if (is_dp && !is_cpu_edp)
+		dpll |= DPLL_DVO_HIGH_SPEED;
+
+	/* compute bitmask from p1 value */
+	dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+	/* also FPA1 */
+	dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
+
+	switch (clock->p2) {
+	case 5:
+		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
+		break;
+	case 7:
+		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
+		break;
+	case 10:
+		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
+		break;
+	case 14:
+		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
+		break;
+	}
+
+	if (is_sdvo && is_tv)
+		dpll |= PLL_REF_INPUT_TVCLKINBC;
+	else if (is_tv)
+		/* XXX: just matching BIOS for now */
+		/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
+		dpll |= 3;
+	else if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2)
+		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
+	else
+		dpll |= PLL_REF_INPUT_DREFCLK;
+
+	return dpll;
+}
+
+static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
+				  struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode,
+				  int x, int y,
+				  struct drm_framebuffer *fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	int plane = intel_crtc->plane;
+	int num_connectors = 0;
+	intel_clock_t clock, reduced_clock;
+	u32 dpll, fp = 0, fp2 = 0;
+	bool ok, has_reduced_clock = false;
+	bool is_lvds = false, is_dp = false, is_cpu_edp = false;
+	struct intel_encoder *encoder;
+	u32 temp;
+	int ret;
+	bool dither, fdi_config_ok;
+
+	for_each_encoder_on_crtc(dev, crtc, encoder) {
+		switch (encoder->type) {
+		case INTEL_OUTPUT_LVDS:
+			is_lvds = true;
+			break;
+		case INTEL_OUTPUT_DISPLAYPORT:
+			is_dp = true;
+			break;
+		case INTEL_OUTPUT_EDP:
+			is_dp = true;
+			if (!intel_encoder_is_pch_edp(&encoder->base))
+				is_cpu_edp = true;
+			break;
+		}
+
+		num_connectors++;
 	}
-	if (is_dp && !is_cpu_edp)
-		dpll |= DPLL_DVO_HIGH_SPEED;
 
-	/* compute bitmask from p1 value */
-	dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
-	/* also FPA1 */
-	dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
+	WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)),
+	     "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev));
 
-	switch (clock.p2) {
-	case 5:
-		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
-		break;
-	case 7:
-		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
-		break;
-	case 10:
-		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
-		break;
-	case 14:
-		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
-		break;
+	ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
+				     &has_reduced_clock, &reduced_clock);
+	if (!ok) {
+		DRM_ERROR("Couldn't find PLL settings for mode!\n");
+		return -EINVAL;
 	}
 
-	if (is_sdvo && is_tv)
-		dpll |= PLL_REF_INPUT_TVCLKINBC;
-	else if (is_tv)
-		/* XXX: just matching BIOS for now */
-		/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
-		dpll |= 3;
-	else if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2)
-		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
-	else
-		dpll |= PLL_REF_INPUT_DREFCLK;
+	/* Ensure that the cursor is valid for the new mode before changing... */
+	intel_crtc_update_cursor(crtc, true);
+
+	/* determine panel color depth */
+	dither = intel_choose_pipe_bpp_dither(crtc, fb, &intel_crtc->bpp,
+					      adjusted_mode);
+	if (is_lvds && dev_priv->lvds_dither)
+		dither = true;
+
+	fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
+	if (has_reduced_clock)
+		fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
+			reduced_clock.m2;
+
+	dpll = ironlake_compute_dpll(intel_crtc, adjusted_mode, &clock, fp);
 
 	DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
 	drm_mode_debug_printmodeline(mode);
 
-	/* CPU eDP is the only output that doesn't need a PCH PLL of its own on
-	 * pre-Haswell/LPT generation */
-	if (HAS_PCH_LPT(dev)) {
-		DRM_DEBUG_KMS("LPT detected: no PLL for pipe %d necessary\n",
-				pipe);
-	} else if (!is_cpu_edp) {
+	/* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
+	if (!is_cpu_edp) {
 		struct intel_pch_pll *pll;
 
 		pll = intel_get_pch_pll(intel_crtc, dpll, fp);
@@ -5033,47 +5574,13 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 		}
 	}
 
-	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
-		/* the chip adds 2 halflines automatically */
-		adjusted_mode->crtc_vtotal -= 1;
-		adjusted_mode->crtc_vblank_end -= 1;
-		I915_WRITE(VSYNCSHIFT(pipe),
-			   adjusted_mode->crtc_hsync_start
-			   - adjusted_mode->crtc_htotal/2);
-	} else {
-		I915_WRITE(VSYNCSHIFT(pipe), 0);
-	}
-
-	I915_WRITE(HTOTAL(pipe),
-		   (adjusted_mode->crtc_hdisplay - 1) |
-		   ((adjusted_mode->crtc_htotal - 1) << 16));
-	I915_WRITE(HBLANK(pipe),
-		   (adjusted_mode->crtc_hblank_start - 1) |
-		   ((adjusted_mode->crtc_hblank_end - 1) << 16));
-	I915_WRITE(HSYNC(pipe),
-		   (adjusted_mode->crtc_hsync_start - 1) |
-		   ((adjusted_mode->crtc_hsync_end - 1) << 16));
-
-	I915_WRITE(VTOTAL(pipe),
-		   (adjusted_mode->crtc_vdisplay - 1) |
-		   ((adjusted_mode->crtc_vtotal - 1) << 16));
-	I915_WRITE(VBLANK(pipe),
-		   (adjusted_mode->crtc_vblank_start - 1) |
-		   ((adjusted_mode->crtc_vblank_end - 1) << 16));
-	I915_WRITE(VSYNC(pipe),
-		   (adjusted_mode->crtc_vsync_start - 1) |
-		   ((adjusted_mode->crtc_vsync_end - 1) << 16));
+	intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
 
-	/* pipesrc controls the size that is scaled from, which should
-	 * always be the user's requested size.
-	 */
-	I915_WRITE(PIPESRC(pipe),
-		   ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
+	/* Note, this also computes intel_crtc->fdi_lanes which is used below in
+	 * ironlake_check_fdi_lanes. */
+	ironlake_set_m_n(crtc, mode, adjusted_mode);
 
-	I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
-	I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n);
-	I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m);
-	I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n);
+	fdi_config_ok = ironlake_check_fdi_lanes(intel_crtc);
 
 	if (is_cpu_edp)
 		ironlake_set_pll_edp(crtc, adjusted_mode->clock);
@@ -5092,6 +5599,217 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 
 	intel_update_linetime_watermarks(dev, pipe, adjusted_mode);
 
+	return fdi_config_ok ? ret : -EINVAL;
+}
+
+static int haswell_crtc_mode_set(struct drm_crtc *crtc,
+				 struct drm_display_mode *mode,
+				 struct drm_display_mode *adjusted_mode,
+				 int x, int y,
+				 struct drm_framebuffer *fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	int plane = intel_crtc->plane;
+	int num_connectors = 0;
+	intel_clock_t clock, reduced_clock;
+	u32 dpll = 0, fp = 0, fp2 = 0;
+	bool ok, has_reduced_clock = false;
+	bool is_lvds = false, is_dp = false, is_cpu_edp = false;
+	struct intel_encoder *encoder;
+	u32 temp;
+	int ret;
+	bool dither;
+
+	for_each_encoder_on_crtc(dev, crtc, encoder) {
+		switch (encoder->type) {
+		case INTEL_OUTPUT_LVDS:
+			is_lvds = true;
+			break;
+		case INTEL_OUTPUT_DISPLAYPORT:
+			is_dp = true;
+			break;
+		case INTEL_OUTPUT_EDP:
+			is_dp = true;
+			if (!intel_encoder_is_pch_edp(&encoder->base))
+				is_cpu_edp = true;
+			break;
+		}
+
+		num_connectors++;
+	}
+
+	if (is_cpu_edp)
+		intel_crtc->cpu_transcoder = TRANSCODER_EDP;
+	else
+		intel_crtc->cpu_transcoder = pipe;
+
+	/* We are not sure yet this won't happen. */
+	WARN(!HAS_PCH_LPT(dev), "Unexpected PCH type %d\n",
+	     INTEL_PCH_TYPE(dev));
+
+	WARN(num_connectors != 1, "%d connectors attached to pipe %c\n",
+	     num_connectors, pipe_name(pipe));
+
+	WARN_ON(I915_READ(PIPECONF(intel_crtc->cpu_transcoder)) &
+		(PIPECONF_ENABLE | I965_PIPECONF_ACTIVE));
+
+	WARN_ON(I915_READ(DSPCNTR(plane)) & DISPLAY_PLANE_ENABLE);
+
+	if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
+		return -EINVAL;
+
+	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+		ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
+					     &has_reduced_clock,
+					     &reduced_clock);
+		if (!ok) {
+			DRM_ERROR("Couldn't find PLL settings for mode!\n");
+			return -EINVAL;
+		}
+	}
+
+	/* Ensure that the cursor is valid for the new mode before changing... */
+	intel_crtc_update_cursor(crtc, true);
+
+	/* determine panel color depth */
+	dither = intel_choose_pipe_bpp_dither(crtc, fb, &intel_crtc->bpp,
+					      adjusted_mode);
+	if (is_lvds && dev_priv->lvds_dither)
+		dither = true;
+
+	DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
+	drm_mode_debug_printmodeline(mode);
+
+	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+		fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
+		if (has_reduced_clock)
+			fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
+			      reduced_clock.m2;
+
+		dpll = ironlake_compute_dpll(intel_crtc, adjusted_mode, &clock,
+					     fp);
+
+		/* CPU eDP is the only output that doesn't need a PCH PLL of its
+		 * own on pre-Haswell/LPT generation */
+		if (!is_cpu_edp) {
+			struct intel_pch_pll *pll;
+
+			pll = intel_get_pch_pll(intel_crtc, dpll, fp);
+			if (pll == NULL) {
+				DRM_DEBUG_DRIVER("failed to find PLL for pipe %d\n",
+						 pipe);
+				return -EINVAL;
+			}
+		} else
+			intel_put_pch_pll(intel_crtc);
+
+		/* The LVDS pin pair needs to be on before the DPLLs are
+		 * enabled.  This is an exception to the general rule that
+		 * mode_set doesn't turn things on.
+		 */
+		if (is_lvds) {
+			temp = I915_READ(PCH_LVDS);
+			temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
+			if (HAS_PCH_CPT(dev)) {
+				temp &= ~PORT_TRANS_SEL_MASK;
+				temp |= PORT_TRANS_SEL_CPT(pipe);
+			} else {
+				if (pipe == 1)
+					temp |= LVDS_PIPEB_SELECT;
+				else
+					temp &= ~LVDS_PIPEB_SELECT;
+			}
+
+			/* set the corresponsding LVDS_BORDER bit */
+			temp |= dev_priv->lvds_border_bits;
+			/* Set the B0-B3 data pairs corresponding to whether
+			 * we're going to set the DPLLs for dual-channel mode or
+			 * not.
+			 */
+			if (clock.p2 == 7)
+				temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
+			else
+				temp &= ~(LVDS_B0B3_POWER_UP |
+					  LVDS_CLKB_POWER_UP);
+
+			/* It would be nice to set 24 vs 18-bit mode
+			 * (LVDS_A3_POWER_UP) appropriately here, but we need to
+			 * look more thoroughly into how panels behave in the
+			 * two modes.
+			 */
+			temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
+			if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
+				temp |= LVDS_HSYNC_POLARITY;
+			if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
+				temp |= LVDS_VSYNC_POLARITY;
+			I915_WRITE(PCH_LVDS, temp);
+		}
+	}
+
+	if (is_dp && !is_cpu_edp) {
+		intel_dp_set_m_n(crtc, mode, adjusted_mode);
+	} else {
+		if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+			/* For non-DP output, clear any trans DP clock recovery
+			 * setting.*/
+			I915_WRITE(TRANSDATA_M1(pipe), 0);
+			I915_WRITE(TRANSDATA_N1(pipe), 0);
+			I915_WRITE(TRANSDPLINK_M1(pipe), 0);
+			I915_WRITE(TRANSDPLINK_N1(pipe), 0);
+		}
+	}
+
+	intel_crtc->lowfreq_avail = false;
+	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+		if (intel_crtc->pch_pll) {
+			I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
+
+			/* Wait for the clocks to stabilize. */
+			POSTING_READ(intel_crtc->pch_pll->pll_reg);
+			udelay(150);
+
+			/* The pixel multiplier can only be updated once the
+			 * DPLL is enabled and the clocks are stable.
+			 *
+			 * So write it again.
+			 */
+			I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
+		}
+
+		if (intel_crtc->pch_pll) {
+			if (is_lvds && has_reduced_clock && i915_powersave) {
+				I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2);
+				intel_crtc->lowfreq_avail = true;
+			} else {
+				I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp);
+			}
+		}
+	}
+
+	intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
+
+	if (!is_dp || is_cpu_edp)
+		ironlake_set_m_n(crtc, mode, adjusted_mode);
+
+	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+		if (is_cpu_edp)
+			ironlake_set_pll_edp(crtc, adjusted_mode->clock);
+
+	haswell_set_pipeconf(crtc, adjusted_mode, dither);
+
+	/* Set up the display plane register */
+	I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
+	POSTING_READ(DSPCNTR(plane));
+
+	ret = intel_pipe_set_base(crtc, x, y, fb);
+
+	intel_update_watermarks(dev);
+
+	intel_update_linetime_watermarks(dev, pipe, adjusted_mode);
+
 	return ret;
 }
 
@@ -5103,6 +5821,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_encoder_helper_funcs *encoder_funcs;
+	struct intel_encoder *encoder;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
 	int ret;
@@ -5113,7 +5833,19 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 					      x, y, fb);
 	drm_vblank_post_modeset(dev, pipe);
 
-	return ret;
+	if (ret != 0)
+		return ret;
+
+	for_each_encoder_on_crtc(dev, crtc, encoder) {
+		DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
+			encoder->base.base.id,
+			drm_get_encoder_name(&encoder->base),
+			mode->base.id, mode->name);
+		encoder_funcs = encoder->base.helper_private;
+		encoder_funcs->mode_set(&encoder->base, mode, adjusted_mode);
+	}
+
+	return 0;
 }
 
 static bool intel_eld_uptodate(struct drm_connector *connector,
@@ -5749,7 +6481,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
 				  int depth, int bpp)
 {
 	struct drm_i915_gem_object *obj;
-	struct drm_mode_fb_cmd2 mode_cmd;
+	struct drm_mode_fb_cmd2 mode_cmd = { 0 };
 
 	obj = i915_gem_alloc_object(dev,
 				    intel_framebuffer_size_for_mode(mode, bpp));
@@ -5879,24 +6611,19 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 		DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
 	if (IS_ERR(fb)) {
 		DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
-		goto fail;
+		return false;
 	}
 
 	if (!intel_set_mode(crtc, mode, 0, 0, fb)) {
 		DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
 		if (old->release_fb)
 			old->release_fb->funcs->destroy(old->release_fb);
-		goto fail;
+		return false;
 	}
 
 	/* let the connector get through one full cycle before testing */
 	intel_wait_for_vblank(dev, intel_crtc->pipe);
-
 	return true;
-fail:
-	connector->encoder = NULL;
-	encoder->crtc = NULL;
-	return false;
 }
 
 void intel_release_load_detect_pipe(struct drm_connector *connector,
@@ -6021,12 +6748,12 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
+	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
 	struct drm_display_mode *mode;
-	int htot = I915_READ(HTOTAL(pipe));
-	int hsync = I915_READ(HSYNC(pipe));
-	int vtot = I915_READ(VTOTAL(pipe));
-	int vsync = I915_READ(VSYNC(pipe));
+	int htot = I915_READ(HTOTAL(cpu_transcoder));
+	int hsync = I915_READ(HSYNC(cpu_transcoder));
+	int vtot = I915_READ(VTOTAL(cpu_transcoder));
+	int vsync = I915_READ(VSYNC(cpu_transcoder));
 
 	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
 	if (!mode)
@@ -7015,8 +7742,6 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	struct drm_device *dev = crtc->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
-	struct drm_encoder_helper_funcs *encoder_funcs;
-	struct drm_encoder *encoder;
 	struct intel_crtc *intel_crtc;
 	unsigned disable_pipes, prepare_pipes, modeset_pipes;
 	bool ret = true;
@@ -7061,6 +7786,9 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	 * update the the output configuration. */
 	intel_modeset_update_state(dev, prepare_pipes);
 
+	if (dev_priv->display.modeset_global_resources)
+		dev_priv->display.modeset_global_resources(dev);
+
 	/* Set up the DPLL and any encoders state that needs to adjust or depend
 	 * on the DPLL.
 	 */
@@ -7070,18 +7798,6 @@ bool intel_set_mode(struct drm_crtc *crtc,
 					   x, y, fb);
 		if (!ret)
 		    goto done;
-
-		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-
-			if (encoder->crtc != &intel_crtc->base)
-				continue;
-
-			DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
-				encoder->base.id, drm_get_encoder_name(encoder),
-				mode->base.id, mode->name);
-			encoder_funcs = encoder->helper_private;
-			encoder_funcs->mode_set(encoder, mode, adjusted_mode);
-		}
 	}
 
 	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
@@ -7420,6 +8136,12 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
 	.page_flip = intel_crtc_page_flip,
 };
 
+static void intel_cpu_pll_init(struct drm_device *dev)
+{
+	if (IS_HASWELL(dev))
+		intel_ddi_pll_init(dev);
+}
+
 static void intel_pch_pll_init(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -7459,6 +8181,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 	/* Swap pipes & planes for FBC on pre-965 */
 	intel_crtc->pipe = pipe;
 	intel_crtc->plane = pipe;
+	intel_crtc->cpu_transcoder = pipe;
 	if (IS_MOBILE(dev) && IS_GEN3(dev)) {
 		DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
 		intel_crtc->plane = !pipe;
@@ -7551,16 +8274,6 @@ static void intel_setup_outputs(struct drm_device *dev)
 		I915_WRITE(PFIT_CONTROL, 0);
 	}
 
-	if (HAS_PCH_SPLIT(dev)) {
-		dpd_is_edp = intel_dpd_is_edp(dev);
-
-		if (has_edp_a(dev))
-			intel_dp_init(dev, DP_A, PORT_A);
-
-		if (dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED))
-			intel_dp_init(dev, PCH_DP_D, PORT_D);
-	}
-
 	intel_crt_init(dev);
 
 	if (IS_HASWELL(dev)) {
@@ -7584,6 +8297,10 @@ static void intel_setup_outputs(struct drm_device *dev)
 			intel_ddi_init(dev, PORT_D);
 	} else if (HAS_PCH_SPLIT(dev)) {
 		int found;
+		dpd_is_edp = intel_dpd_is_edp(dev);
+
+		if (has_edp_a(dev))
+			intel_dp_init(dev, DP_A, PORT_A);
 
 		if (I915_READ(HDMIB) & PORT_DETECTED) {
 			/* PCH SDVOB multiplex with HDMIB */
@@ -7603,11 +8320,15 @@ static void intel_setup_outputs(struct drm_device *dev)
 		if (I915_READ(PCH_DP_C) & DP_DETECTED)
 			intel_dp_init(dev, PCH_DP_C, PORT_C);
 
-		if (!dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED))
+		if (I915_READ(PCH_DP_D) & DP_DETECTED)
 			intel_dp_init(dev, PCH_DP_D, PORT_D);
 	} else if (IS_VALLEYVIEW(dev)) {
 		int found;
 
+		/* Check for built-in panel first. Shares lanes with HDMI on SDVOC */
+		if (I915_READ(DP_C) & DP_DETECTED)
+			intel_dp_init(dev, DP_C, PORT_C);
+
 		if (I915_READ(SDVOB) & PORT_DETECTED) {
 			/* SDVOB multiplex with HDMIB */
 			found = intel_sdvo_init(dev, SDVOB, true);
@@ -7620,9 +8341,6 @@ static void intel_setup_outputs(struct drm_device *dev)
 		if (I915_READ(SDVOC) & PORT_DETECTED)
 			intel_hdmi_init(dev, SDVOC, PORT_C);
 
-		/* Shares lanes with HDMI on SDVOC */
-		if (I915_READ(DP_C) & DP_DETECTED)
-			intel_dp_init(dev, DP_C, PORT_C);
 	} else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) {
 		bool found = false;
 
@@ -7678,6 +8396,8 @@ static void intel_setup_outputs(struct drm_device *dev)
 
 	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
 		ironlake_init_pch_refclk(dev);
+
+	drm_helper_move_panel_connectors_to_head(dev);
 }
 
 static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
@@ -7718,27 +8438,51 @@ int intel_framebuffer_init(struct drm_device *dev,
 	if (mode_cmd->pitches[0] & 63)
 		return -EINVAL;
 
+	/* FIXME <= Gen4 stride limits are bit unclear */
+	if (mode_cmd->pitches[0] > 32768)
+		return -EINVAL;
+
+	if (obj->tiling_mode != I915_TILING_NONE &&
+	    mode_cmd->pitches[0] != obj->stride)
+		return -EINVAL;
+
+	/* Reject formats not supported by any plane early. */
 	switch (mode_cmd->pixel_format) {
-	case DRM_FORMAT_RGB332:
+	case DRM_FORMAT_C8:
 	case DRM_FORMAT_RGB565:
 	case DRM_FORMAT_XRGB8888:
-	case DRM_FORMAT_XBGR8888:
 	case DRM_FORMAT_ARGB8888:
+		break;
+	case DRM_FORMAT_XRGB1555:
+	case DRM_FORMAT_ARGB1555:
+		if (INTEL_INFO(dev)->gen > 3)
+			return -EINVAL;
+		break;
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
 	case DRM_FORMAT_XRGB2101010:
 	case DRM_FORMAT_ARGB2101010:
-		/* RGB formats are common across chipsets */
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_ABGR2101010:
+		if (INTEL_INFO(dev)->gen < 4)
+			return -EINVAL;
 		break;
 	case DRM_FORMAT_YUYV:
 	case DRM_FORMAT_UYVY:
 	case DRM_FORMAT_YVYU:
 	case DRM_FORMAT_VYUY:
+		if (INTEL_INFO(dev)->gen < 6)
+			return -EINVAL;
 		break;
 	default:
-		DRM_DEBUG_KMS("unsupported pixel format %u\n",
-				mode_cmd->pixel_format);
+		DRM_DEBUG_KMS("unsupported pixel format 0x%08x\n", mode_cmd->pixel_format);
 		return -EINVAL;
 	}
 
+	/* FIXME need to adjust LINOFF/TILEOFF accordingly. */
+	if (mode_cmd->offsets[0] != 0)
+		return -EINVAL;
+
 	ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
 	if (ret) {
 		DRM_ERROR("framebuffer init failed %d\n", ret);
@@ -7776,7 +8520,13 @@ static void intel_init_display(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	/* We always want a DPMS function */
-	if (HAS_PCH_SPLIT(dev)) {
+	if (IS_HASWELL(dev)) {
+		dev_priv->display.crtc_mode_set = haswell_crtc_mode_set;
+		dev_priv->display.crtc_enable = haswell_crtc_enable;
+		dev_priv->display.crtc_disable = haswell_crtc_disable;
+		dev_priv->display.off = haswell_crtc_off;
+		dev_priv->display.update_plane = ironlake_update_plane;
+	} else if (HAS_PCH_SPLIT(dev)) {
 		dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
 		dev_priv->display.crtc_enable = ironlake_crtc_enable;
 		dev_priv->display.crtc_disable = ironlake_crtc_disable;
@@ -7827,6 +8577,8 @@ static void intel_init_display(struct drm_device *dev)
 			/* FIXME: detect B0+ stepping and use auto training */
 			dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
 			dev_priv->display.write_eld = ironlake_write_eld;
+			dev_priv->display.modeset_global_resources =
+				ivb_modeset_global_resources;
 		} else if (IS_HASWELL(dev)) {
 			dev_priv->display.fdi_link_train = hsw_fdi_link_train;
 			dev_priv->display.write_eld = haswell_write_eld;
@@ -8058,6 +8810,7 @@ void intel_modeset_init(struct drm_device *dev)
 			DRM_DEBUG_KMS("plane %d init failed: %d\n", i, ret);
 	}
 
+	intel_cpu_pll_init(dev);
 	intel_pch_pll_init(dev);
 
 	/* Just disable it once at startup */
@@ -8127,7 +8880,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
 	u32 reg;
 
 	/* Clear any frame start delays used for debugging left by the BIOS */
-	reg = PIPECONF(crtc->pipe);
+	reg = PIPECONF(crtc->cpu_transcoder);
 	I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
 
 	/* We need to sanitize the plane -> pipe mapping first because this will
@@ -8255,10 +9008,35 @@ void intel_modeset_setup_hw_state(struct drm_device *dev)
 	struct intel_encoder *encoder;
 	struct intel_connector *connector;
 
+	if (IS_HASWELL(dev)) {
+		tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
+
+		if (tmp & TRANS_DDI_FUNC_ENABLE) {
+			switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
+			case TRANS_DDI_EDP_INPUT_A_ON:
+			case TRANS_DDI_EDP_INPUT_A_ONOFF:
+				pipe = PIPE_A;
+				break;
+			case TRANS_DDI_EDP_INPUT_B_ONOFF:
+				pipe = PIPE_B;
+				break;
+			case TRANS_DDI_EDP_INPUT_C_ONOFF:
+				pipe = PIPE_C;
+				break;
+			}
+
+			crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+			crtc->cpu_transcoder = TRANSCODER_EDP;
+
+			DRM_DEBUG_KMS("Pipe %c using transcoder EDP\n",
+				      pipe_name(pipe));
+		}
+	}
+
 	for_each_pipe(pipe) {
 		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
 
-		tmp = I915_READ(PIPECONF(pipe));
+		tmp = I915_READ(PIPECONF(crtc->cpu_transcoder));
 		if (tmp & PIPECONF_ENABLE)
 			crtc->active = true;
 		else
@@ -8271,6 +9049,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev)
 			      crtc->active ? "enabled" : "disabled");
 	}
 
+	if (IS_HASWELL(dev))
+		intel_ddi_setup_hw_pll_state(dev);
+
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
 			    base.head) {
 		pipe = 0;
@@ -8320,6 +9101,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev)
 	intel_modeset_update_staged_output_state(dev);
 
 	intel_modeset_check_state(dev);
+
+	drm_mode_config_reset(dev);
 }
 
 void intel_modeset_gem_init(struct drm_device *dev)
@@ -8447,6 +9230,7 @@ intel_display_capture_error_state(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_display_error_state *error;
+	enum transcoder cpu_transcoder;
 	int i;
 
 	error = kmalloc(sizeof(*error), GFP_ATOMIC);
@@ -8454,6 +9238,8 @@ intel_display_capture_error_state(struct drm_device *dev)
 		return NULL;
 
 	for_each_pipe(i) {
+		cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, i);
+
 		error->cursor[i].control = I915_READ(CURCNTR(i));
 		error->cursor[i].position = I915_READ(CURPOS(i));
 		error->cursor[i].base = I915_READ(CURBASE(i));
@@ -8468,14 +9254,14 @@ intel_display_capture_error_state(struct drm_device *dev)
 			error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i));
 		}
 
-		error->pipe[i].conf = I915_READ(PIPECONF(i));
+		error->pipe[i].conf = I915_READ(PIPECONF(cpu_transcoder));
 		error->pipe[i].source = I915_READ(PIPESRC(i));
-		error->pipe[i].htotal = I915_READ(HTOTAL(i));
-		error->pipe[i].hblank = I915_READ(HBLANK(i));
-		error->pipe[i].hsync = I915_READ(HSYNC(i));
-		error->pipe[i].vtotal = I915_READ(VTOTAL(i));
-		error->pipe[i].vblank = I915_READ(VBLANK(i));
-		error->pipe[i].vsync = I915_READ(VSYNC(i));
+		error->pipe[i].htotal = I915_READ(HTOTAL(cpu_transcoder));
+		error->pipe[i].hblank = I915_READ(HBLANK(cpu_transcoder));
+		error->pipe[i].hsync = I915_READ(HSYNC(cpu_transcoder));
+		error->pipe[i].vtotal = I915_READ(VTOTAL(cpu_transcoder));
+		error->pipe[i].vblank = I915_READ(VBLANK(cpu_transcoder));
+		error->pipe[i].vsync = I915_READ(VSYNC(cpu_transcoder));
 	}
 
 	return error;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 368ed8e..a9ba88a 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -36,8 +36,6 @@
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
-#define DP_RECEIVER_CAP_SIZE	0xf
-#define DP_LINK_STATUS_SIZE	6
 #define DP_LINK_CHECK_TIMEOUT	(10 * 1000)
 
 /**
@@ -49,7 +47,9 @@
  */
 static bool is_edp(struct intel_dp *intel_dp)
 {
-	return intel_dp->base.type == INTEL_OUTPUT_EDP;
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+
+	return intel_dig_port->base.type == INTEL_OUTPUT_EDP;
 }
 
 /**
@@ -76,15 +76,16 @@ static bool is_cpu_edp(struct intel_dp *intel_dp)
 	return is_edp(intel_dp) && !is_pch_edp(intel_dp);
 }
 
-static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
+static struct drm_device *intel_dp_to_dev(struct intel_dp *intel_dp)
 {
-	return container_of(encoder, struct intel_dp, base.base);
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+
+	return intel_dig_port->base.base.dev;
 }
 
 static struct intel_dp *intel_attached_dp(struct drm_connector *connector)
 {
-	return container_of(intel_attached_encoder(connector),
-			    struct intel_dp, base);
+	return enc_to_intel_dp(&intel_attached_encoder(connector)->base);
 }
 
 /**
@@ -106,49 +107,32 @@ bool intel_encoder_is_pch_edp(struct drm_encoder *encoder)
 	return is_pch_edp(intel_dp);
 }
 
-static void intel_dp_start_link_train(struct intel_dp *intel_dp);
-static void intel_dp_complete_link_train(struct intel_dp *intel_dp);
 static void intel_dp_link_down(struct intel_dp *intel_dp);
 
 void
 intel_edp_link_config(struct intel_encoder *intel_encoder,
 		       int *lane_num, int *link_bw)
 {
-	struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
 
 	*lane_num = intel_dp->lane_count;
-	if (intel_dp->link_bw == DP_LINK_BW_1_62)
-		*link_bw = 162000;
-	else if (intel_dp->link_bw == DP_LINK_BW_2_7)
-		*link_bw = 270000;
+	*link_bw = drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
 }
 
 int
 intel_edp_target_clock(struct intel_encoder *intel_encoder,
 		       struct drm_display_mode *mode)
 {
-	struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+	struct intel_connector *intel_connector = intel_dp->attached_connector;
 
-	if (intel_dp->panel_fixed_mode)
-		return intel_dp->panel_fixed_mode->clock;
+	if (intel_connector->panel.fixed_mode)
+		return intel_connector->panel.fixed_mode->clock;
 	else
 		return mode->clock;
 }
 
 static int
-intel_dp_max_lane_count(struct intel_dp *intel_dp)
-{
-	int max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f;
-	switch (max_lane_count) {
-	case 1: case 2: case 4:
-		break;
-	default:
-		max_lane_count = 4;
-	}
-	return max_lane_count;
-}
-
-static int
 intel_dp_max_link_bw(struct intel_dp *intel_dp)
 {
 	int max_link_bw = intel_dp->dpcd[DP_MAX_LINK_RATE];
@@ -208,7 +192,7 @@ intel_dp_adjust_dithering(struct intel_dp *intel_dp,
 			  bool adjust_mode)
 {
 	int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp));
-	int max_lanes = intel_dp_max_lane_count(intel_dp);
+	int max_lanes = drm_dp_max_lane_count(intel_dp->dpcd);
 	int max_rate, mode_rate;
 
 	mode_rate = intel_dp_link_required(mode->clock, 24);
@@ -234,12 +218,14 @@ intel_dp_mode_valid(struct drm_connector *connector,
 		    struct drm_display_mode *mode)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
+	struct intel_connector *intel_connector = to_intel_connector(connector);
+	struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
 
-	if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
-		if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay)
+	if (is_edp(intel_dp) && fixed_mode) {
+		if (mode->hdisplay > fixed_mode->hdisplay)
 			return MODE_PANEL;
 
-		if (mode->vdisplay > intel_dp->panel_fixed_mode->vdisplay)
+		if (mode->vdisplay > fixed_mode->vdisplay)
 			return MODE_PANEL;
 	}
 
@@ -285,6 +271,10 @@ intel_hrawclk(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t clkcfg;
 
+	/* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */
+	if (IS_VALLEYVIEW(dev))
+		return 200;
+
 	clkcfg = I915_READ(CLKCFG);
 	switch (clkcfg & CLKCFG_FSB_MASK) {
 	case CLKCFG_FSB_400:
@@ -310,7 +300,7 @@ intel_hrawclk(struct drm_device *dev)
 
 static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	return (I915_READ(PCH_PP_STATUS) & PP_ON) != 0;
@@ -318,7 +308,7 @@ static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
 
 static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	return (I915_READ(PCH_PP_CONTROL) & EDP_FORCE_VDD) != 0;
@@ -327,7 +317,7 @@ static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
 static void
 intel_dp_check_edp(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (!is_edp(intel_dp))
@@ -346,7 +336,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 		uint8_t *recv, int recv_size)
 {
 	uint32_t output_reg = intel_dp->output_reg;
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t ch_ctl = output_reg + 0x10;
 	uint32_t ch_data = ch_ctl + 4;
@@ -356,6 +347,29 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	uint32_t aux_clock_divider;
 	int try, precharge;
 
+	if (IS_HASWELL(dev)) {
+		switch (intel_dig_port->port) {
+		case PORT_A:
+			ch_ctl = DPA_AUX_CH_CTL;
+			ch_data = DPA_AUX_CH_DATA1;
+			break;
+		case PORT_B:
+			ch_ctl = PCH_DPB_AUX_CH_CTL;
+			ch_data = PCH_DPB_AUX_CH_DATA1;
+			break;
+		case PORT_C:
+			ch_ctl = PCH_DPC_AUX_CH_CTL;
+			ch_data = PCH_DPC_AUX_CH_DATA1;
+			break;
+		case PORT_D:
+			ch_ctl = PCH_DPD_AUX_CH_CTL;
+			ch_data = PCH_DPD_AUX_CH_DATA1;
+			break;
+		default:
+			BUG();
+		}
+	}
+
 	intel_dp_check_edp(intel_dp);
 	/* The clock divider is based off the hrawclk,
 	 * and would like to run at 2MHz. So, take the
@@ -365,12 +379,16 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	 * clock divider.
 	 */
 	if (is_cpu_edp(intel_dp)) {
-		if (IS_GEN6(dev) || IS_GEN7(dev))
+		if (IS_HASWELL(dev))
+			aux_clock_divider = intel_ddi_get_cdclk_freq(dev_priv) >> 1;
+		else if (IS_VALLEYVIEW(dev))
+			aux_clock_divider = 100;
+		else if (IS_GEN6(dev) || IS_GEN7(dev))
 			aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */
 		else
 			aux_clock_divider = 225; /* eDP input clock at 450Mhz */
 	} else if (HAS_PCH_SPLIT(dev))
-		aux_clock_divider = 63; /* IRL input clock fixed at 125Mhz */
+		aux_clock_divider = DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
 	else
 		aux_clock_divider = intel_hrawclk(dev) / 2;
 
@@ -642,9 +660,6 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 	return -EREMOTEIO;
 }
 
-static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
-static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
-
 static int
 intel_dp_i2c_init(struct intel_dp *intel_dp,
 		  struct intel_connector *intel_connector, const char *name)
@@ -670,22 +685,25 @@ intel_dp_i2c_init(struct intel_dp *intel_dp,
 	return ret;
 }
 
-static bool
+bool
 intel_dp_mode_fixup(struct drm_encoder *encoder,
 		    const struct drm_display_mode *mode,
 		    struct drm_display_mode *adjusted_mode)
 {
 	struct drm_device *dev = encoder->dev;
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+	struct intel_connector *intel_connector = intel_dp->attached_connector;
 	int lane_count, clock;
-	int max_lane_count = intel_dp_max_lane_count(intel_dp);
+	int max_lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
 	int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
 	int bpp, mode_rate;
 	static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
 
-	if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
-		intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode);
-		intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN,
+	if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
+		intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
+				       adjusted_mode);
+		intel_pch_panel_fitting(dev,
+					intel_connector->panel.fitting_mode,
 					mode, adjusted_mode);
 	}
 
@@ -762,21 +780,23 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 		 struct drm_display_mode *adjusted_mode)
 {
 	struct drm_device *dev = crtc->dev;
-	struct intel_encoder *encoder;
+	struct intel_encoder *intel_encoder;
+	struct intel_dp *intel_dp;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int lane_count = 4;
 	struct intel_dp_m_n m_n;
 	int pipe = intel_crtc->pipe;
+	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
 
 	/*
 	 * Find the lane count in the intel_encoder private
 	 */
-	for_each_encoder_on_crtc(dev, crtc, encoder) {
-		struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
+		intel_dp = enc_to_intel_dp(&intel_encoder->base);
 
-		if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT ||
-		    intel_dp->base.type == INTEL_OUTPUT_EDP)
+		if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+		    intel_encoder->type == INTEL_OUTPUT_EDP)
 		{
 			lane_count = intel_dp->lane_count;
 			break;
@@ -791,23 +811,46 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	intel_dp_compute_m_n(intel_crtc->bpp, lane_count,
 			     mode->clock, adjusted_mode->clock, &m_n);
 
-	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(TRANSDATA_M1(pipe),
-			   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
-			   m_n.gmch_m);
+	if (IS_HASWELL(dev)) {
+		I915_WRITE(PIPE_DATA_M1(cpu_transcoder),
+			   TU_SIZE(m_n.tu) | m_n.gmch_m);
+		I915_WRITE(PIPE_DATA_N1(cpu_transcoder), m_n.gmch_n);
+		I915_WRITE(PIPE_LINK_M1(cpu_transcoder), m_n.link_m);
+		I915_WRITE(PIPE_LINK_N1(cpu_transcoder), m_n.link_n);
+	} else if (HAS_PCH_SPLIT(dev)) {
+		I915_WRITE(TRANSDATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
 		I915_WRITE(TRANSDATA_N1(pipe), m_n.gmch_n);
 		I915_WRITE(TRANSDPLINK_M1(pipe), m_n.link_m);
 		I915_WRITE(TRANSDPLINK_N1(pipe), m_n.link_n);
+	} else if (IS_VALLEYVIEW(dev)) {
+		I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
+		I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n);
+		I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m);
+		I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n);
 	} else {
 		I915_WRITE(PIPE_GMCH_DATA_M(pipe),
-			   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
-			   m_n.gmch_m);
+			   TU_SIZE(m_n.tu) | m_n.gmch_m);
 		I915_WRITE(PIPE_GMCH_DATA_N(pipe), m_n.gmch_n);
 		I915_WRITE(PIPE_DP_LINK_M(pipe), m_n.link_m);
 		I915_WRITE(PIPE_DP_LINK_N(pipe), m_n.link_n);
 	}
 }
 
+void intel_dp_init_link_config(struct intel_dp *intel_dp)
+{
+	memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
+	intel_dp->link_configuration[0] = intel_dp->link_bw;
+	intel_dp->link_configuration[1] = intel_dp->lane_count;
+	intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B;
+	/*
+	 * Check for DPCD version > 1.1 and enhanced framing support
+	 */
+	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
+	    (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {
+		intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+	}
+}
+
 static void
 intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		  struct drm_display_mode *adjusted_mode)
@@ -815,7 +858,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-	struct drm_crtc *crtc = intel_dp->base.base.crtc;
+	struct drm_crtc *crtc = encoder->crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
 	/*
@@ -860,21 +903,12 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
 		intel_write_eld(encoder, adjusted_mode);
 	}
-	memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
-	intel_dp->link_configuration[0] = intel_dp->link_bw;
-	intel_dp->link_configuration[1] = intel_dp->lane_count;
-	intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B;
-	/*
-	 * Check for DPCD version > 1.1 and enhanced framing support
-	 */
-	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
-	    (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {
-		intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
-	}
+
+	intel_dp_init_link_config(intel_dp);
 
 	/* Split out the IBX/CPU vs CPT settings */
 
-	if (is_cpu_edp(intel_dp) && IS_GEN7(dev)) {
+	if (is_cpu_edp(intel_dp) && IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) {
 		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
 			intel_dp->DP |= DP_SYNC_HS_HIGH;
 		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
@@ -931,7 +965,7 @@ static void ironlake_wait_panel_status(struct intel_dp *intel_dp,
 				       u32 mask,
 				       u32 value)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	DRM_DEBUG_KMS("mask %08x value %08x status %08x control %08x\n",
@@ -978,9 +1012,9 @@ static  u32 ironlake_get_pp_control(struct drm_i915_private *dev_priv)
 	return control;
 }
 
-static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
+void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
@@ -1019,7 +1053,7 @@ static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
 
 static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
@@ -1041,14 +1075,14 @@ static void ironlake_panel_vdd_work(struct work_struct *__work)
 {
 	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
 						 struct intel_dp, panel_vdd_work);
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 
 	mutex_lock(&dev->mode_config.mutex);
 	ironlake_panel_vdd_off_sync(intel_dp);
 	mutex_unlock(&dev->mode_config.mutex);
 }
 
-static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
+void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
 	if (!is_edp(intel_dp))
 		return;
@@ -1071,9 +1105,9 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 	}
 }
 
-static void ironlake_edp_panel_on(struct intel_dp *intel_dp)
+void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
@@ -1113,9 +1147,9 @@ static void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 	}
 }
 
-static void ironlake_edp_panel_off(struct intel_dp *intel_dp)
+void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
@@ -1138,10 +1172,12 @@ static void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 	ironlake_wait_panel_off(intel_dp);
 }
 
-static void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
+void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	int pipe = to_intel_crtc(intel_dig_port->base.base.crtc)->pipe;
 	u32 pp;
 
 	if (!is_edp(intel_dp))
@@ -1159,17 +1195,21 @@ static void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
 	pp |= EDP_BLC_ENABLE;
 	I915_WRITE(PCH_PP_CONTROL, pp);
 	POSTING_READ(PCH_PP_CONTROL);
+
+	intel_panel_enable_backlight(dev, pipe);
 }
 
-static void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
+void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
 	if (!is_edp(intel_dp))
 		return;
 
+	intel_panel_disable_backlight(dev);
+
 	DRM_DEBUG_KMS("\n");
 	pp = ironlake_get_pp_control(dev_priv);
 	pp &= ~EDP_BLC_ENABLE;
@@ -1180,8 +1220,9 @@ static void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
 
 static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
-	struct drm_crtc *crtc = intel_dp->base.base.crtc;
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_crtc *crtc = intel_dig_port->base.base.crtc;
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 dpa_ctl;
 
@@ -1205,8 +1246,9 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
 
 static void ironlake_edp_pll_off(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
-	struct drm_crtc *crtc = intel_dp->base.base.crtc;
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_crtc *crtc = intel_dig_port->base.base.crtc;
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 dpa_ctl;
 
@@ -1228,7 +1270,7 @@ static void ironlake_edp_pll_off(struct intel_dp *intel_dp)
 }
 
 /* If the sink supports it, try to set the power state appropriately */
-static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
+void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
 {
 	int ret, i;
 
@@ -1298,9 +1340,10 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
 				return true;
 			}
 		}
-	}
 
-	DRM_DEBUG_KMS("No pipe for dp port 0x%x found\n", intel_dp->output_reg);
+		DRM_DEBUG_KMS("No pipe for dp port 0x%x found\n",
+			      intel_dp->output_reg);
+	}
 
 	return true;
 }
@@ -1396,38 +1439,6 @@ intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_
 					      DP_LINK_STATUS_SIZE);
 }
 
-static uint8_t
-intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
-		     int r)
-{
-	return link_status[r - DP_LANE0_1_STATUS];
-}
-
-static uint8_t
-intel_get_adjust_request_voltage(uint8_t adjust_request[2],
-				 int lane)
-{
-	int	    s = ((lane & 1) ?
-			 DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
-			 DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
-	uint8_t l = adjust_request[lane>>1];
-
-	return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
-}
-
-static uint8_t
-intel_get_adjust_request_pre_emphasis(uint8_t adjust_request[2],
-				      int lane)
-{
-	int	    s = ((lane & 1) ?
-			 DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
-			 DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
-	uint8_t l = adjust_request[lane>>1];
-
-	return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
-}
-
-
 #if 0
 static char	*voltage_names[] = {
 	"0.4V", "0.6V", "0.8V", "1.2V"
@@ -1448,7 +1459,7 @@ static char	*link_train_names[] = {
 static uint8_t
 intel_dp_voltage_max(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 
 	if (IS_GEN7(dev) && is_cpu_edp(intel_dp))
 		return DP_TRAIN_VOLTAGE_SWING_800;
@@ -1461,9 +1472,21 @@ intel_dp_voltage_max(struct intel_dp *intel_dp)
 static uint8_t
 intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 
-	if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+	if (IS_HASWELL(dev)) {
+		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
+		case DP_TRAIN_VOLTAGE_SWING_400:
+			return DP_TRAIN_PRE_EMPHASIS_9_5;
+		case DP_TRAIN_VOLTAGE_SWING_600:
+			return DP_TRAIN_PRE_EMPHASIS_6;
+		case DP_TRAIN_VOLTAGE_SWING_800:
+			return DP_TRAIN_PRE_EMPHASIS_3_5;
+		case DP_TRAIN_VOLTAGE_SWING_1200:
+		default:
+			return DP_TRAIN_PRE_EMPHASIS_0;
+		}
+	} else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) {
 		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
 		case DP_TRAIN_VOLTAGE_SWING_400:
 			return DP_TRAIN_PRE_EMPHASIS_6;
@@ -1494,13 +1517,12 @@ intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_ST
 	uint8_t v = 0;
 	uint8_t p = 0;
 	int lane;
-	uint8_t	*adjust_request = link_status + (DP_ADJUST_REQUEST_LANE0_1 - DP_LANE0_1_STATUS);
 	uint8_t voltage_max;
 	uint8_t preemph_max;
 
 	for (lane = 0; lane < intel_dp->lane_count; lane++) {
-		uint8_t this_v = intel_get_adjust_request_voltage(adjust_request, lane);
-		uint8_t this_p = intel_get_adjust_request_pre_emphasis(adjust_request, lane);
+		uint8_t this_v = drm_dp_get_adjust_request_voltage(link_status, lane);
+		uint8_t this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
 
 		if (this_v > v)
 			v = this_v;
@@ -1617,52 +1639,38 @@ intel_gen7_edp_signal_levels(uint8_t train_set)
 	}
 }
 
-static uint8_t
-intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
-		      int lane)
-{
-	int s = (lane & 1) * 4;
-	uint8_t l = link_status[lane>>1];
-
-	return (l >> s) & 0xf;
-}
-
-/* Check for clock recovery is done on all channels */
-static bool
-intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
+/* Gen7.5's (HSW) DP voltage swing and pre-emphasis control */
+static uint32_t
+intel_dp_signal_levels_hsw(uint8_t train_set)
 {
-	int lane;
-	uint8_t lane_status;
-
-	for (lane = 0; lane < lane_count; lane++) {
-		lane_status = intel_get_lane_status(link_status, lane);
-		if ((lane_status & DP_LANE_CR_DONE) == 0)
-			return false;
-	}
-	return true;
-}
+	int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
+					 DP_TRAIN_PRE_EMPHASIS_MASK);
+	switch (signal_levels) {
+	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0:
+		return DDI_BUF_EMP_400MV_0DB_HSW;
+	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5:
+		return DDI_BUF_EMP_400MV_3_5DB_HSW;
+	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
+		return DDI_BUF_EMP_400MV_6DB_HSW;
+	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_9_5:
+		return DDI_BUF_EMP_400MV_9_5DB_HSW;
 
-/* Check to see if channel eq is done on all channels */
-#define CHANNEL_EQ_BITS (DP_LANE_CR_DONE|\
-			 DP_LANE_CHANNEL_EQ_DONE|\
-			 DP_LANE_SYMBOL_LOCKED)
-static bool
-intel_channel_eq_ok(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
-{
-	uint8_t lane_align;
-	uint8_t lane_status;
-	int lane;
+	case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0:
+		return DDI_BUF_EMP_600MV_0DB_HSW;
+	case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
+		return DDI_BUF_EMP_600MV_3_5DB_HSW;
+	case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6:
+		return DDI_BUF_EMP_600MV_6DB_HSW;
 
-	lane_align = intel_dp_link_status(link_status,
-					  DP_LANE_ALIGN_STATUS_UPDATED);
-	if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
-		return false;
-	for (lane = 0; lane < intel_dp->lane_count; lane++) {
-		lane_status = intel_get_lane_status(link_status, lane);
-		if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
-			return false;
+	case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
+		return DDI_BUF_EMP_800MV_0DB_HSW;
+	case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5:
+		return DDI_BUF_EMP_800MV_3_5DB_HSW;
+	default:
+		DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:"
+			      "0x%x\n", signal_levels);
+		return DDI_BUF_EMP_400MV_0DB_HSW;
 	}
-	return true;
 }
 
 static bool
@@ -1670,11 +1678,49 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 			uint32_t dp_reg_value,
 			uint8_t dp_train_pat)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum port port = intel_dig_port->port;
 	int ret;
+	uint32_t temp;
 
-	if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) {
+	if (IS_HASWELL(dev)) {
+		temp = I915_READ(DP_TP_CTL(port));
+
+		if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
+			temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
+		else
+			temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE;
+
+		temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
+		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
+		case DP_TRAINING_PATTERN_DISABLE:
+			temp |= DP_TP_CTL_LINK_TRAIN_IDLE;
+			I915_WRITE(DP_TP_CTL(port), temp);
+
+			if (wait_for((I915_READ(DP_TP_STATUS(port)) &
+				      DP_TP_STATUS_IDLE_DONE), 1))
+				DRM_ERROR("Timed out waiting for DP idle patterns\n");
+
+			temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
+			temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
+
+			break;
+		case DP_TRAINING_PATTERN_1:
+			temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
+			break;
+		case DP_TRAINING_PATTERN_2:
+			temp |= DP_TP_CTL_LINK_TRAIN_PAT2;
+			break;
+		case DP_TRAINING_PATTERN_3:
+			temp |= DP_TP_CTL_LINK_TRAIN_PAT3;
+			break;
+		}
+		I915_WRITE(DP_TP_CTL(port), temp);
+
+	} else if (HAS_PCH_CPT(dev) &&
+		   (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) {
 		dp_reg_value &= ~DP_LINK_TRAIN_MASK_CPT;
 
 		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
@@ -1734,16 +1780,20 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 }
 
 /* Enable corresponding port and start training pattern 1 */
-static void
+void
 intel_dp_start_link_train(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_encoder *encoder = &dp_to_dig_port(intel_dp)->base.base;
+	struct drm_device *dev = encoder->dev;
 	int i;
 	uint8_t voltage;
 	bool clock_recovery = false;
 	int voltage_tries, loop_tries;
 	uint32_t DP = intel_dp->DP;
 
+	if (IS_HASWELL(dev))
+		intel_ddi_prepare_link_retrain(encoder);
+
 	/* Write the link configuration data */
 	intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
 				  intel_dp->link_configuration,
@@ -1761,8 +1811,11 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
 		uint8_t	    link_status[DP_LINK_STATUS_SIZE];
 		uint32_t    signal_levels;
 
-
-		if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+		if (IS_HASWELL(dev)) {
+			signal_levels = intel_dp_signal_levels_hsw(
+							intel_dp->train_set[0]);
+			DP = (DP & ~DDI_BUF_EMP_MASK) | signal_levels;
+		} else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) {
 			signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]);
 			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels;
 		} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
@@ -1770,23 +1823,24 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
 			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
 		} else {
 			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]);
-			DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n", signal_levels);
 			DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
 		}
+		DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n",
+			      signal_levels);
 
+		/* Set training pattern 1 */
 		if (!intel_dp_set_link_train(intel_dp, DP,
 					     DP_TRAINING_PATTERN_1 |
 					     DP_LINK_SCRAMBLING_DISABLE))
 			break;
-		/* Set training pattern 1 */
 
-		udelay(100);
+		drm_dp_link_train_clock_recovery_delay(intel_dp->dpcd);
 		if (!intel_dp_get_link_status(intel_dp, link_status)) {
 			DRM_ERROR("failed to get link status\n");
 			break;
 		}
 
-		if (intel_clock_recovery_ok(link_status, intel_dp->lane_count)) {
+		if (drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) {
 			DRM_DEBUG_KMS("clock recovery OK\n");
 			clock_recovery = true;
 			break;
@@ -1825,10 +1879,10 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
 	intel_dp->DP = DP;
 }
 
-static void
+void
 intel_dp_complete_link_train(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	bool channel_eq = false;
 	int tries, cr_tries;
 	uint32_t DP = intel_dp->DP;
@@ -1848,7 +1902,10 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 			break;
 		}
 
-		if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+		if (IS_HASWELL(dev)) {
+			signal_levels = intel_dp_signal_levels_hsw(intel_dp->train_set[0]);
+			DP = (DP & ~DDI_BUF_EMP_MASK) | signal_levels;
+		} else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) {
 			signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]);
 			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels;
 		} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
@@ -1865,18 +1922,18 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 					     DP_LINK_SCRAMBLING_DISABLE))
 			break;
 
-		udelay(400);
+		drm_dp_link_train_channel_eq_delay(intel_dp->dpcd);
 		if (!intel_dp_get_link_status(intel_dp, link_status))
 			break;
 
 		/* Make sure clock is still ok */
-		if (!intel_clock_recovery_ok(link_status, intel_dp->lane_count)) {
+		if (!drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) {
 			intel_dp_start_link_train(intel_dp);
 			cr_tries++;
 			continue;
 		}
 
-		if (intel_channel_eq_ok(intel_dp, link_status)) {
+		if (drm_dp_channel_eq_ok(link_status, intel_dp->lane_count)) {
 			channel_eq = true;
 			break;
 		}
@@ -1895,16 +1952,38 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 		++tries;
 	}
 
+	if (channel_eq)
+		DRM_DEBUG_KMS("Channel EQ done. DP Training successfull\n");
+
 	intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_DISABLE);
 }
 
 static void
 intel_dp_link_down(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t DP = intel_dp->DP;
 
+	/*
+	 * DDI code has a strict mode set sequence and we should try to respect
+	 * it, otherwise we might hang the machine in many different ways. So we
+	 * really should be disabling the port only on a complete crtc_disable
+	 * sequence. This function is just called under two conditions on DDI
+	 * code:
+	 * - Link train failed while doing crtc_enable, and on this case we
+	 *   really should respect the mode set sequence and wait for a
+	 *   crtc_disable.
+	 * - Someone turned the monitor off and intel_dp_check_link_status
+	 *   called us. We don't need to disable the whole port on this case, so
+	 *   when someone turns the monitor on again,
+	 *   intel_ddi_prepare_link_retrain will take care of redoing the link
+	 *   train.
+	 */
+	if (IS_HASWELL(dev))
+		return;
+
 	if (WARN_ON((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0))
 		return;
 
@@ -1923,7 +2002,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 
 	if (HAS_PCH_IBX(dev) &&
 	    I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
-		struct drm_crtc *crtc = intel_dp->base.base.crtc;
+		struct drm_crtc *crtc = intel_dig_port->base.base.crtc;
 
 		/* Hardware workaround: leaving our transcoder select
 		 * set to transcoder B while it's off will prevent the
@@ -2024,7 +2103,7 @@ static void
 intel_dp_handle_test_request(struct intel_dp *intel_dp)
 {
 	/* NAK by default */
-	intel_dp_aux_native_write_1(intel_dp, DP_TEST_RESPONSE, DP_TEST_ACK);
+	intel_dp_aux_native_write_1(intel_dp, DP_TEST_RESPONSE, DP_TEST_NAK);
 }
 
 /*
@@ -2036,16 +2115,17 @@ intel_dp_handle_test_request(struct intel_dp *intel_dp)
  *  4. Check link status on receipt of hot-plug interrupt
  */
 
-static void
+void
 intel_dp_check_link_status(struct intel_dp *intel_dp)
 {
+	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
 	u8 sink_irq_vector;
 	u8 link_status[DP_LINK_STATUS_SIZE];
 
-	if (!intel_dp->base.connectors_active)
+	if (!intel_encoder->connectors_active)
 		return;
 
-	if (WARN_ON(!intel_dp->base.base.crtc))
+	if (WARN_ON(!intel_encoder->base.crtc))
 		return;
 
 	/* Try to read receiver status if the link appears to be up */
@@ -2074,9 +2154,9 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
 			DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
 	}
 
-	if (!intel_channel_eq_ok(intel_dp, link_status)) {
+	if (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count)) {
 		DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
-			      drm_get_encoder_name(&intel_dp->base.base));
+			      drm_get_encoder_name(&intel_encoder->base));
 		intel_dp_start_link_train(intel_dp);
 		intel_dp_complete_link_train(intel_dp);
 	}
@@ -2125,11 +2205,12 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
 static enum drm_connector_status
 ironlake_dp_detect(struct intel_dp *intel_dp)
 {
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	enum drm_connector_status status;
 
 	/* Can't disconnect eDP, but you can close the lid... */
 	if (is_edp(intel_dp)) {
-		status = intel_panel_detect(intel_dp->base.base.dev);
+		status = intel_panel_detect(dev);
 		if (status == connector_status_unknown)
 			status = connector_status_connected;
 		return status;
@@ -2141,7 +2222,7 @@ ironlake_dp_detect(struct intel_dp *intel_dp)
 static enum drm_connector_status
 g4x_dp_detect(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t bit;
 
@@ -2168,44 +2249,45 @@ g4x_dp_detect(struct intel_dp *intel_dp)
 static struct edid *
 intel_dp_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
 {
-	struct intel_dp *intel_dp = intel_attached_dp(connector);
-	struct edid	*edid;
-	int size;
+	struct intel_connector *intel_connector = to_intel_connector(connector);
 
-	if (is_edp(intel_dp)) {
-		if (!intel_dp->edid)
+	/* use cached edid if we have one */
+	if (intel_connector->edid) {
+		struct edid *edid;
+		int size;
+
+		/* invalid edid */
+		if (IS_ERR(intel_connector->edid))
 			return NULL;
 
-		size = (intel_dp->edid->extensions + 1) * EDID_LENGTH;
+		size = (intel_connector->edid->extensions + 1) * EDID_LENGTH;
 		edid = kmalloc(size, GFP_KERNEL);
 		if (!edid)
 			return NULL;
 
-		memcpy(edid, intel_dp->edid, size);
+		memcpy(edid, intel_connector->edid, size);
 		return edid;
 	}
 
-	edid = drm_get_edid(connector, adapter);
-	return edid;
+	return drm_get_edid(connector, adapter);
 }
 
 static int
 intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter *adapter)
 {
-	struct intel_dp *intel_dp = intel_attached_dp(connector);
-	int	ret;
+	struct intel_connector *intel_connector = to_intel_connector(connector);
 
-	if (is_edp(intel_dp)) {
-		drm_mode_connector_update_edid_property(connector,
-							intel_dp->edid);
-		ret = drm_add_edid_modes(connector, intel_dp->edid);
-		drm_edid_to_eld(connector,
-				intel_dp->edid);
-		return intel_dp->edid_mode_count;
+	/* use cached edid if we have one */
+	if (intel_connector->edid) {
+		/* invalid edid */
+		if (IS_ERR(intel_connector->edid))
+			return 0;
+
+		return intel_connector_update_modes(connector,
+						    intel_connector->edid);
 	}
 
-	ret = intel_ddc_get_modes(connector, adapter);
-	return ret;
+	return intel_ddc_get_modes(connector, adapter);
 }
 
 
@@ -2219,9 +2301,12 @@ static enum drm_connector_status
 intel_dp_detect(struct drm_connector *connector, bool force)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
+	struct drm_device *dev = connector->dev;
 	enum drm_connector_status status;
 	struct edid *edid = NULL;
+	char dpcd_hex_dump[sizeof(intel_dp->dpcd) * 3];
 
 	intel_dp->has_audio = false;
 
@@ -2230,10 +2315,9 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 	else
 		status = g4x_dp_detect(intel_dp);
 
-	DRM_DEBUG_KMS("DPCD: %02hx%02hx%02hx%02hx%02hx%02hx%02hx%02hx\n",
-		      intel_dp->dpcd[0], intel_dp->dpcd[1], intel_dp->dpcd[2],
-		      intel_dp->dpcd[3], intel_dp->dpcd[4], intel_dp->dpcd[5],
-		      intel_dp->dpcd[6], intel_dp->dpcd[7]);
+	hex_dump_to_buffer(intel_dp->dpcd, sizeof(intel_dp->dpcd),
+			   32, 1, dpcd_hex_dump, sizeof(dpcd_hex_dump), false);
+	DRM_DEBUG_KMS("DPCD: %s\n", dpcd_hex_dump);
 
 	if (status != connector_status_connected)
 		return status;
@@ -2250,49 +2334,31 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 		}
 	}
 
+	if (intel_encoder->type != INTEL_OUTPUT_EDP)
+		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
 	return connector_status_connected;
 }
 
 static int intel_dp_get_modes(struct drm_connector *connector)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
-	struct drm_device *dev = intel_dp->base.base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_connector *intel_connector = to_intel_connector(connector);
+	struct drm_device *dev = connector->dev;
 	int ret;
 
 	/* We should parse the EDID data and find out if it has an audio sink
 	 */
 
 	ret = intel_dp_get_edid_modes(connector, &intel_dp->adapter);
-	if (ret) {
-		if (is_edp(intel_dp) && !intel_dp->panel_fixed_mode) {
-			struct drm_display_mode *newmode;
-			list_for_each_entry(newmode, &connector->probed_modes,
-					    head) {
-				if ((newmode->type & DRM_MODE_TYPE_PREFERRED)) {
-					intel_dp->panel_fixed_mode =
-						drm_mode_duplicate(dev, newmode);
-					break;
-				}
-			}
-		}
+	if (ret)
 		return ret;
-	}
 
-	/* if eDP has no EDID, try to use fixed panel mode from VBT */
-	if (is_edp(intel_dp)) {
-		/* initialize panel mode from VBT if available for eDP */
-		if (intel_dp->panel_fixed_mode == NULL && dev_priv->lfp_lvds_vbt_mode != NULL) {
-			intel_dp->panel_fixed_mode =
-				drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
-			if (intel_dp->panel_fixed_mode) {
-				intel_dp->panel_fixed_mode->type |=
-					DRM_MODE_TYPE_PREFERRED;
-			}
-		}
-		if (intel_dp->panel_fixed_mode) {
-			struct drm_display_mode *mode;
-			mode = drm_mode_duplicate(dev, intel_dp->panel_fixed_mode);
+	/* if eDP has no EDID, fall back to fixed mode */
+	if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
+		struct drm_display_mode *mode;
+		mode = drm_mode_duplicate(dev,
+					  intel_connector->panel.fixed_mode);
+		if (mode) {
 			drm_mode_probed_add(connector, mode);
 			return 1;
 		}
@@ -2322,7 +2388,9 @@ intel_dp_set_property(struct drm_connector *connector,
 		      uint64_t val)
 {
 	struct drm_i915_private *dev_priv = connector->dev->dev_private;
-	struct intel_dp *intel_dp = intel_attached_dp(connector);
+	struct intel_connector *intel_connector = to_intel_connector(connector);
+	struct intel_encoder *intel_encoder = intel_attached_encoder(connector);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
 	int ret;
 
 	ret = drm_connector_property_set_value(connector, property, val);
@@ -2358,11 +2426,27 @@ intel_dp_set_property(struct drm_connector *connector,
 		goto done;
 	}
 
+	if (is_edp(intel_dp) &&
+	    property == connector->dev->mode_config.scaling_mode_property) {
+		if (val == DRM_MODE_SCALE_NONE) {
+			DRM_DEBUG_KMS("no scaling not supported\n");
+			return -EINVAL;
+		}
+
+		if (intel_connector->panel.fitting_mode == val) {
+			/* the eDP scaling property is not changed */
+			return 0;
+		}
+		intel_connector->panel.fitting_mode = val;
+
+		goto done;
+	}
+
 	return -EINVAL;
 
 done:
-	if (intel_dp->base.base.crtc) {
-		struct drm_crtc *crtc = intel_dp->base.base.crtc;
+	if (intel_encoder->base.crtc) {
+		struct drm_crtc *crtc = intel_encoder->base.crtc;
 		intel_set_mode(crtc, &crtc->mode,
 			       crtc->x, crtc->y, crtc->fb);
 	}
@@ -2375,27 +2459,33 @@ intel_dp_destroy(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
+	struct intel_connector *intel_connector = to_intel_connector(connector);
 
-	if (is_edp(intel_dp))
+	if (!IS_ERR_OR_NULL(intel_connector->edid))
+		kfree(intel_connector->edid);
+
+	if (is_edp(intel_dp)) {
 		intel_panel_destroy_backlight(dev);
+		intel_panel_fini(&intel_connector->panel);
+	}
 
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
 	kfree(connector);
 }
 
-static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
+void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 {
-	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
 
 	i2c_del_adapter(&intel_dp->adapter);
 	drm_encoder_cleanup(encoder);
 	if (is_edp(intel_dp)) {
-		kfree(intel_dp->edid);
 		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
 		ironlake_panel_vdd_off_sync(intel_dp);
 	}
-	kfree(intel_dp);
+	kfree(intel_dig_port);
 }
 
 static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
@@ -2425,7 +2515,7 @@ static const struct drm_encoder_funcs intel_dp_enc_funcs = {
 static void
 intel_dp_hot_plug(struct intel_encoder *intel_encoder)
 {
-	struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
 
 	intel_dp_check_link_status(intel_dp);
 }
@@ -2435,13 +2525,14 @@ int
 intel_trans_dp_port_sel(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
-	struct intel_encoder *encoder;
+	struct intel_encoder *intel_encoder;
+	struct intel_dp *intel_dp;
 
-	for_each_encoder_on_crtc(dev, crtc, encoder) {
-		struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
+		intel_dp = enc_to_intel_dp(&intel_encoder->base);
 
-		if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT ||
-		    intel_dp->base.type == INTEL_OUTPUT_EDP)
+		if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+		    intel_encoder->type == INTEL_OUTPUT_EDP)
 			return intel_dp->output_reg;
 	}
 
@@ -2471,78 +2562,191 @@ bool intel_dpd_is_edp(struct drm_device *dev)
 static void
 intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector)
 {
+	struct intel_connector *intel_connector = to_intel_connector(connector);
+
 	intel_attach_force_audio_property(connector);
 	intel_attach_broadcast_rgb_property(connector);
+
+	if (is_edp(intel_dp)) {
+		drm_mode_create_scaling_mode_property(connector->dev);
+		drm_connector_attach_property(
+			connector,
+			connector->dev->mode_config.scaling_mode_property,
+			DRM_MODE_SCALE_ASPECT);
+		intel_connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT;
+	}
+}
+
+static void
+intel_dp_init_panel_power_sequencer(struct drm_device *dev,
+				    struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct edp_power_seq cur, vbt, spec, final;
+	u32 pp_on, pp_off, pp_div, pp;
+
+	/* Workaround: Need to write PP_CONTROL with the unlock key as
+	 * the very first thing. */
+	pp = ironlake_get_pp_control(dev_priv);
+	I915_WRITE(PCH_PP_CONTROL, pp);
+
+	pp_on = I915_READ(PCH_PP_ON_DELAYS);
+	pp_off = I915_READ(PCH_PP_OFF_DELAYS);
+	pp_div = I915_READ(PCH_PP_DIVISOR);
+
+	/* Pull timing values out of registers */
+	cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
+		PANEL_POWER_UP_DELAY_SHIFT;
+
+	cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >>
+		PANEL_LIGHT_ON_DELAY_SHIFT;
+
+	cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >>
+		PANEL_LIGHT_OFF_DELAY_SHIFT;
+
+	cur.t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >>
+		PANEL_POWER_DOWN_DELAY_SHIFT;
+
+	cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >>
+		       PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000;
+
+	DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
+		      cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12);
+
+	vbt = dev_priv->edp.pps;
+
+	/* Upper limits from eDP 1.3 spec. Note that we use the clunky units of
+	 * our hw here, which are all in 100usec. */
+	spec.t1_t3 = 210 * 10;
+	spec.t8 = 50 * 10; /* no limit for t8, use t7 instead */
+	spec.t9 = 50 * 10; /* no limit for t9, make it symmetric with t8 */
+	spec.t10 = 500 * 10;
+	/* This one is special and actually in units of 100ms, but zero
+	 * based in the hw (so we need to add 100 ms). But the sw vbt
+	 * table multiplies it with 1000 to make it in units of 100usec,
+	 * too. */
+	spec.t11_t12 = (510 + 100) * 10;
+
+	DRM_DEBUG_KMS("vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
+		      vbt.t1_t3, vbt.t8, vbt.t9, vbt.t10, vbt.t11_t12);
+
+	/* Use the max of the register settings and vbt. If both are
+	 * unset, fall back to the spec limits. */
+#define assign_final(field)	final.field = (max(cur.field, vbt.field) == 0 ? \
+				       spec.field : \
+				       max(cur.field, vbt.field))
+	assign_final(t1_t3);
+	assign_final(t8);
+	assign_final(t9);
+	assign_final(t10);
+	assign_final(t11_t12);
+#undef assign_final
+
+#define get_delay(field)	(DIV_ROUND_UP(final.field, 10))
+	intel_dp->panel_power_up_delay = get_delay(t1_t3);
+	intel_dp->backlight_on_delay = get_delay(t8);
+	intel_dp->backlight_off_delay = get_delay(t9);
+	intel_dp->panel_power_down_delay = get_delay(t10);
+	intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
+#undef get_delay
+
+	/* And finally store the new values in the power sequencer. */
+	pp_on = (final.t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
+		(final.t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
+	pp_off = (final.t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
+		 (final.t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
+	/* Compute the divisor for the pp clock, simply match the Bspec
+	 * formula. */
+	pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1)
+			<< PP_REFERENCE_DIVIDER_SHIFT;
+	pp_div |= (DIV_ROUND_UP(final.t11_t12, 1000)
+			<< PANEL_POWER_CYCLE_DELAY_SHIFT);
+
+	/* Haswell doesn't have any port selection bits for the panel
+	 * power sequencer any more. */
+	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+		if (is_cpu_edp(intel_dp))
+			pp_on |= PANEL_POWER_PORT_DP_A;
+		else
+			pp_on |= PANEL_POWER_PORT_DP_D;
+	}
+
+	I915_WRITE(PCH_PP_ON_DELAYS, pp_on);
+	I915_WRITE(PCH_PP_OFF_DELAYS, pp_off);
+	I915_WRITE(PCH_PP_DIVISOR, pp_div);
+
+
+	DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
+		      intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
+		      intel_dp->panel_power_cycle_delay);
+
+	DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
+		      intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
+
+	DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
+		      I915_READ(PCH_PP_ON_DELAYS),
+		      I915_READ(PCH_PP_OFF_DELAYS),
+		      I915_READ(PCH_PP_DIVISOR));
 }
 
 void
-intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
+intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
+			struct intel_connector *intel_connector)
 {
+	struct drm_connector *connector = &intel_connector->base;
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
+	struct drm_device *dev = intel_encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_connector *connector;
-	struct intel_dp *intel_dp;
-	struct intel_encoder *intel_encoder;
-	struct intel_connector *intel_connector;
+	struct drm_display_mode *fixed_mode = NULL;
+	enum port port = intel_dig_port->port;
 	const char *name = NULL;
 	int type;
 
-	intel_dp = kzalloc(sizeof(struct intel_dp), GFP_KERNEL);
-	if (!intel_dp)
-		return;
-
-	intel_dp->output_reg = output_reg;
-	intel_dp->port = port;
 	/* Preserve the current hw state. */
 	intel_dp->DP = I915_READ(intel_dp->output_reg);
+	intel_dp->attached_connector = intel_connector;
 
-	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
-	if (!intel_connector) {
-		kfree(intel_dp);
-		return;
-	}
-	intel_encoder = &intel_dp->base;
-
-	if (HAS_PCH_SPLIT(dev) && output_reg == PCH_DP_D)
+	if (HAS_PCH_SPLIT(dev) && port == PORT_D)
 		if (intel_dpd_is_edp(dev))
 			intel_dp->is_pch_edp = true;
 
-	if (output_reg == DP_A || is_pch_edp(intel_dp)) {
+	/*
+	 * FIXME : We need to initialize built-in panels before external panels.
+	 * For X0, DP_C is fixed as eDP. Revisit this as part of VLV eDP cleanup
+	 */
+	if (IS_VALLEYVIEW(dev) && port == PORT_C) {
+		type = DRM_MODE_CONNECTOR_eDP;
+		intel_encoder->type = INTEL_OUTPUT_EDP;
+	} else if (port == PORT_A || is_pch_edp(intel_dp)) {
 		type = DRM_MODE_CONNECTOR_eDP;
 		intel_encoder->type = INTEL_OUTPUT_EDP;
 	} else {
+		/* The intel_encoder->type value may be INTEL_OUTPUT_UNKNOWN for
+		 * DDI or INTEL_OUTPUT_DISPLAYPORT for the older gens, so don't
+		 * rewrite it.
+		 */
 		type = DRM_MODE_CONNECTOR_DisplayPort;
-		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
 	}
 
-	connector = &intel_connector->base;
 	drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);
 	drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
 
 	connector->polled = DRM_CONNECTOR_POLL_HPD;
-
-	intel_encoder->cloneable = false;
-
-	INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
-			  ironlake_panel_vdd_work);
-
-	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
-
 	connector->interlace_allowed = true;
 	connector->doublescan_allowed = 0;
 
-	drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
-			 DRM_MODE_ENCODER_TMDS);
-	drm_encoder_helper_add(&intel_encoder->base, &intel_dp_helper_funcs);
+	INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
+			  ironlake_panel_vdd_work);
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	drm_sysfs_connector_add(connector);
 
-	intel_encoder->enable = intel_enable_dp;
-	intel_encoder->pre_enable = intel_pre_enable_dp;
-	intel_encoder->disable = intel_disable_dp;
-	intel_encoder->post_disable = intel_post_disable_dp;
-	intel_encoder->get_hw_state = intel_dp_get_hw_state;
-	intel_connector->get_hw_state = intel_connector_get_hw_state;
+	if (IS_HASWELL(dev))
+		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
+	else
+		intel_connector->get_hw_state = intel_connector_get_hw_state;
+
 
 	/* Set up the DDC bus. */
 	switch (port) {
@@ -2566,66 +2770,15 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 		break;
 	}
 
-	/* Cache some DPCD data in the eDP case */
-	if (is_edp(intel_dp)) {
-		struct edp_power_seq	cur, vbt;
-		u32 pp_on, pp_off, pp_div;
-
-		pp_on = I915_READ(PCH_PP_ON_DELAYS);
-		pp_off = I915_READ(PCH_PP_OFF_DELAYS);
-		pp_div = I915_READ(PCH_PP_DIVISOR);
-
-		if (!pp_on || !pp_off || !pp_div) {
-			DRM_INFO("bad panel power sequencing delays, disabling panel\n");
-			intel_dp_encoder_destroy(&intel_dp->base.base);
-			intel_dp_destroy(&intel_connector->base);
-			return;
-		}
-
-		/* Pull timing values out of registers */
-		cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
-			PANEL_POWER_UP_DELAY_SHIFT;
-
-		cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >>
-			PANEL_LIGHT_ON_DELAY_SHIFT;
-
-		cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >>
-			PANEL_LIGHT_OFF_DELAY_SHIFT;
-
-		cur.t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >>
-			PANEL_POWER_DOWN_DELAY_SHIFT;
-
-		cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >>
-			       PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000;
-
-		DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
-			      cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12);
-
-		vbt = dev_priv->edp.pps;
-
-		DRM_DEBUG_KMS("vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
-			      vbt.t1_t3, vbt.t8, vbt.t9, vbt.t10, vbt.t11_t12);
-
-#define get_delay(field)	((max(cur.field, vbt.field) + 9) / 10)
-
-		intel_dp->panel_power_up_delay = get_delay(t1_t3);
-		intel_dp->backlight_on_delay = get_delay(t8);
-		intel_dp->backlight_off_delay = get_delay(t9);
-		intel_dp->panel_power_down_delay = get_delay(t10);
-		intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
-
-		DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
-			      intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
-			      intel_dp->panel_power_cycle_delay);
-
-		DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
-			      intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
-	}
+	if (is_edp(intel_dp))
+		intel_dp_init_panel_power_sequencer(dev, intel_dp);
 
 	intel_dp_i2c_init(intel_dp, intel_connector, name);
 
+	/* Cache DPCD and EDID for edp. */
 	if (is_edp(intel_dp)) {
 		bool ret;
+		struct drm_display_mode *scan;
 		struct edid *edid;
 
 		ironlake_edp_panel_vdd_on(intel_dp);
@@ -2640,29 +2793,47 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 		} else {
 			/* if this fails, presume the device is a ghost */
 			DRM_INFO("failed to retrieve link info, disabling eDP\n");
-			intel_dp_encoder_destroy(&intel_dp->base.base);
-			intel_dp_destroy(&intel_connector->base);
+			intel_dp_encoder_destroy(&intel_encoder->base);
+			intel_dp_destroy(connector);
 			return;
 		}
 
 		ironlake_edp_panel_vdd_on(intel_dp);
 		edid = drm_get_edid(connector, &intel_dp->adapter);
 		if (edid) {
-			drm_mode_connector_update_edid_property(connector,
-								edid);
-			intel_dp->edid_mode_count =
-				drm_add_edid_modes(connector, edid);
-			drm_edid_to_eld(connector, edid);
-			intel_dp->edid = edid;
+			if (drm_add_edid_modes(connector, edid)) {
+				drm_mode_connector_update_edid_property(connector, edid);
+				drm_edid_to_eld(connector, edid);
+			} else {
+				kfree(edid);
+				edid = ERR_PTR(-EINVAL);
+			}
+		} else {
+			edid = ERR_PTR(-ENOENT);
+		}
+		intel_connector->edid = edid;
+
+		/* prefer fixed mode from EDID if available */
+		list_for_each_entry(scan, &connector->probed_modes, head) {
+			if ((scan->type & DRM_MODE_TYPE_PREFERRED)) {
+				fixed_mode = drm_mode_duplicate(dev, scan);
+				break;
+			}
 		}
+
+		/* fallback to VBT if available for eDP */
+		if (!fixed_mode && dev_priv->lfp_lvds_vbt_mode) {
+			fixed_mode = drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
+			if (fixed_mode)
+				fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
+		}
+
 		ironlake_edp_panel_vdd_off(intel_dp, false);
 	}
 
-	intel_encoder->hot_plug = intel_dp_hot_plug;
-
 	if (is_edp(intel_dp)) {
-		dev_priv->int_edp_connector = connector;
-		intel_panel_setup_backlight(dev);
+		intel_panel_init(&intel_connector->panel, fixed_mode);
+		intel_panel_setup_backlight(connector);
 	}
 
 	intel_dp_add_properties(intel_dp, connector);
@@ -2676,3 +2847,45 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
 	}
 }
+
+void
+intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
+{
+	struct intel_digital_port *intel_dig_port;
+	struct intel_encoder *intel_encoder;
+	struct drm_encoder *encoder;
+	struct intel_connector *intel_connector;
+
+	intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL);
+	if (!intel_dig_port)
+		return;
+
+	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
+	if (!intel_connector) {
+		kfree(intel_dig_port);
+		return;
+	}
+
+	intel_encoder = &intel_dig_port->base;
+	encoder = &intel_encoder->base;
+
+	drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
+			 DRM_MODE_ENCODER_TMDS);
+	drm_encoder_helper_add(&intel_encoder->base, &intel_dp_helper_funcs);
+
+	intel_encoder->enable = intel_enable_dp;
+	intel_encoder->pre_enable = intel_pre_enable_dp;
+	intel_encoder->disable = intel_disable_dp;
+	intel_encoder->post_disable = intel_post_disable_dp;
+	intel_encoder->get_hw_state = intel_dp_get_hw_state;
+
+	intel_dig_port->port = port;
+	intel_dig_port->dp.output_reg = output_reg;
+
+	intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
+	intel_encoder->cloneable = false;
+	intel_encoder->hot_plug = intel_dp_hot_plug;
+
+	intel_dp_init_connector(intel_dig_port, intel_connector);
+}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index fe71425..bcc5241 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -94,6 +94,7 @@
 #define INTEL_OUTPUT_HDMI 6
 #define INTEL_OUTPUT_DISPLAYPORT 7
 #define INTEL_OUTPUT_EDP 8
+#define INTEL_OUTPUT_UNKNOWN 9
 
 #define INTEL_DVO_CHIP_NONE 0
 #define INTEL_DVO_CHIP_LVDS 1
@@ -163,6 +164,11 @@ struct intel_encoder {
 	int crtc_mask;
 };
 
+struct intel_panel {
+	struct drm_display_mode *fixed_mode;
+	int fitting_mode;
+};
+
 struct intel_connector {
 	struct drm_connector base;
 	/*
@@ -179,12 +185,19 @@ struct intel_connector {
 	/* Reads out the current hw, returning true if the connector is enabled
 	 * and active (i.e. dpms ON state). */
 	bool (*get_hw_state)(struct intel_connector *);
+
+	/* Panel info for eDP and LVDS */
+	struct intel_panel panel;
+
+	/* Cached EDID for eDP and LVDS. May hold ERR_PTR for invalid EDID. */
+	struct edid *edid;
 };
 
 struct intel_crtc {
 	struct drm_crtc base;
 	enum pipe pipe;
 	enum plane plane;
+	enum transcoder cpu_transcoder;
 	u8 lut_r[256], lut_g[256], lut_b[256];
 	/*
 	 * Whether the crtc and the connected output pipeline is active. Implies
@@ -212,12 +225,14 @@ struct intel_crtc {
 
 	/* We can share PLLs across outputs if the timings match */
 	struct intel_pch_pll *pch_pll;
+	uint32_t ddi_pll_sel;
 };
 
 struct intel_plane {
 	struct drm_plane base;
 	enum pipe pipe;
 	struct drm_i915_gem_object *obj;
+	bool can_scale;
 	int max_downscale;
 	u32 lut_r[1024], lut_g[1024], lut_b[1024];
 	void (*update_plane)(struct drm_plane *plane,
@@ -317,10 +332,8 @@ struct dip_infoframe {
 } __attribute__((packed));
 
 struct intel_hdmi {
-	struct intel_encoder base;
 	u32 sdvox_reg;
 	int ddc_bus;
-	int ddi_port;
 	uint32_t color_range;
 	bool has_hdmi_sink;
 	bool has_audio;
@@ -331,18 +344,15 @@ struct intel_hdmi {
 			       struct drm_display_mode *adjusted_mode);
 };
 
-#define DP_RECEIVER_CAP_SIZE		0xf
 #define DP_MAX_DOWNSTREAM_PORTS		0x10
 #define DP_LINK_CONFIGURATION_SIZE	9
 
 struct intel_dp {
-	struct intel_encoder base;
 	uint32_t output_reg;
 	uint32_t DP;
 	uint8_t  link_configuration[DP_LINK_CONFIGURATION_SIZE];
 	bool has_audio;
 	enum hdmi_force_audio force_audio;
-	enum port port;
 	uint32_t color_range;
 	uint8_t link_bw;
 	uint8_t lane_count;
@@ -357,11 +367,16 @@ struct intel_dp {
 	int panel_power_cycle_delay;
 	int backlight_on_delay;
 	int backlight_off_delay;
-	struct drm_display_mode *panel_fixed_mode;  /* for eDP */
 	struct delayed_work panel_vdd_work;
 	bool want_panel_vdd;
-	struct edid *edid; /* cached EDID for eDP */
-	int edid_mode_count;
+	struct intel_connector *attached_connector;
+};
+
+struct intel_digital_port {
+	struct intel_encoder base;
+	enum port port;
+	struct intel_dp dp;
+	struct intel_hdmi hdmi;
 };
 
 static inline struct drm_crtc *
@@ -395,6 +410,8 @@ struct intel_fbc_work {
 	int interval;
 };
 
+int intel_pch_rawclk(struct drm_device *dev);
+
 int intel_connector_update_modes(struct drm_connector *connector,
 				struct edid *edid);
 int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
@@ -405,7 +422,12 @@ extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector)
 extern void intel_crt_init(struct drm_device *dev);
 extern void intel_hdmi_init(struct drm_device *dev,
 			    int sdvox_reg, enum port port);
+extern void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
+				      struct intel_connector *intel_connector);
 extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
+extern bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
+				  const struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode);
 extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
 extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
 			    bool is_sdvob);
@@ -418,10 +440,27 @@ extern void intel_mark_fb_idle(struct drm_i915_gem_object *obj);
 extern bool intel_lvds_init(struct drm_device *dev);
 extern void intel_dp_init(struct drm_device *dev, int output_reg,
 			  enum port port);
+extern void intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
+				    struct intel_connector *intel_connector);
 void
 intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 		 struct drm_display_mode *adjusted_mode);
+extern void intel_dp_init_link_config(struct intel_dp *intel_dp);
+extern void intel_dp_start_link_train(struct intel_dp *intel_dp);
+extern void intel_dp_complete_link_train(struct intel_dp *intel_dp);
+extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
+extern void intel_dp_encoder_destroy(struct drm_encoder *encoder);
+extern void intel_dp_check_link_status(struct intel_dp *intel_dp);
+extern bool intel_dp_mode_fixup(struct drm_encoder *encoder,
+				const struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode);
 extern bool intel_dpd_is_edp(struct drm_device *dev);
+extern void ironlake_edp_backlight_on(struct intel_dp *intel_dp);
+extern void ironlake_edp_backlight_off(struct intel_dp *intel_dp);
+extern void ironlake_edp_panel_on(struct intel_dp *intel_dp);
+extern void ironlake_edp_panel_off(struct intel_dp *intel_dp);
+extern void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
+extern void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
 extern void intel_edp_link_config(struct intel_encoder *, int *, int *);
 extern int intel_edp_target_clock(struct intel_encoder *,
 				  struct drm_display_mode *mode);
@@ -431,6 +470,10 @@ extern void intel_flush_display_plane(struct drm_i915_private *dev_priv,
 				      enum plane plane);
 
 /* intel_panel.c */
+extern int intel_panel_init(struct intel_panel *panel,
+			    struct drm_display_mode *fixed_mode);
+extern void intel_panel_fini(struct intel_panel *panel);
+
 extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
 				   struct drm_display_mode *adjusted_mode);
 extern void intel_pch_panel_fitting(struct drm_device *dev,
@@ -439,7 +482,7 @@ extern void intel_pch_panel_fitting(struct drm_device *dev,
 				    struct drm_display_mode *adjusted_mode);
 extern u32 intel_panel_get_max_backlight(struct drm_device *dev);
 extern void intel_panel_set_backlight(struct drm_device *dev, u32 level);
-extern int intel_panel_setup_backlight(struct drm_device *dev);
+extern int intel_panel_setup_backlight(struct drm_connector *connector);
 extern void intel_panel_enable_backlight(struct drm_device *dev,
 					 enum pipe pipe);
 extern void intel_panel_disable_backlight(struct drm_device *dev);
@@ -473,6 +516,31 @@ static inline struct intel_encoder *intel_attached_encoder(struct drm_connector
 	return to_intel_connector(connector)->encoder;
 }
 
+static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
+{
+	struct intel_digital_port *intel_dig_port =
+		container_of(encoder, struct intel_digital_port, base.base);
+	return &intel_dig_port->dp;
+}
+
+static inline struct intel_digital_port *
+enc_to_dig_port(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct intel_digital_port, base.base);
+}
+
+static inline struct intel_digital_port *
+dp_to_dig_port(struct intel_dp *intel_dp)
+{
+	return container_of(intel_dp, struct intel_digital_port, dp);
+}
+
+static inline struct intel_digital_port *
+hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)
+{
+	return container_of(intel_hdmi, struct intel_digital_port, hdmi);
+}
+
 extern void intel_connector_attach_encoder(struct intel_connector *connector,
 					   struct intel_encoder *encoder);
 extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector);
@@ -481,6 +549,9 @@ extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
 						    struct drm_crtc *crtc);
 int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
+extern enum transcoder
+intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
+			     enum pipe pipe);
 extern void intel_wait_for_vblank(struct drm_device *dev, int pipe);
 extern void intel_wait_for_pipe_off(struct drm_device *dev, int pipe);
 
@@ -550,6 +621,10 @@ extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
 extern void intel_update_linetime_watermarks(struct drm_device *dev, int pipe,
 			 struct drm_display_mode *mode);
 
+extern unsigned long intel_gen4_compute_offset_xtiled(int *x, int *y,
+						      unsigned int bpp,
+						      unsigned int pitch);
+
 extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
 				     struct drm_file *file_priv);
 extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
@@ -573,12 +648,22 @@ extern void intel_disable_gt_powersave(struct drm_device *dev);
 extern void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv);
 extern void ironlake_teardown_rc6(struct drm_device *dev);
 
-extern void intel_enable_ddi(struct intel_encoder *encoder);
-extern void intel_disable_ddi(struct intel_encoder *encoder);
 extern bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 				   enum pipe *pipe);
-extern void intel_ddi_mode_set(struct drm_encoder *encoder,
-				struct drm_display_mode *mode,
-				struct drm_display_mode *adjusted_mode);
+extern int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv);
+extern void intel_ddi_pll_init(struct drm_device *dev);
+extern void intel_ddi_enable_pipe_func(struct drm_crtc *crtc);
+extern void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
+					      enum transcoder cpu_transcoder);
+extern void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
+extern void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
+extern void intel_ddi_setup_hw_pll_state(struct drm_device *dev);
+extern bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock);
+extern void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
+extern void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
+extern void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
+extern bool
+intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
+extern void intel_ddi_fdi_disable(struct drm_crtc *crtc);
 
 #endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 9ba0aae..1dcfd5b 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -36,10 +36,15 @@
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
+static struct drm_device *intel_hdmi_to_dev(struct intel_hdmi *intel_hdmi)
+{
+	return hdmi_to_dig_port(intel_hdmi)->base.base.dev;
+}
+
 static void
 assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi)
 {
-	struct drm_device *dev = intel_hdmi->base.base.dev;
+	struct drm_device *dev = intel_hdmi_to_dev(intel_hdmi);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t enabled_bits;
 
@@ -51,13 +56,14 @@ assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi)
 
 struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder)
 {
-	return container_of(encoder, struct intel_hdmi, base.base);
+	struct intel_digital_port *intel_dig_port =
+		container_of(encoder, struct intel_digital_port, base.base);
+	return &intel_dig_port->hdmi;
 }
 
 static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector)
 {
-	return container_of(intel_attached_encoder(connector),
-			    struct intel_hdmi, base);
+	return enc_to_intel_hdmi(&intel_attached_encoder(connector)->base);
 }
 
 void intel_dip_infoframe_csum(struct dip_infoframe *frame)
@@ -754,16 +760,16 @@ static int intel_hdmi_mode_valid(struct drm_connector *connector,
 	return MODE_OK;
 }
 
-static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
-				  const struct drm_display_mode *mode,
-				  struct drm_display_mode *adjusted_mode)
+bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
+			   const struct drm_display_mode *mode,
+			   struct drm_display_mode *adjusted_mode)
 {
 	return true;
 }
 
 static bool g4x_hdmi_connected(struct intel_hdmi *intel_hdmi)
 {
-	struct drm_device *dev = intel_hdmi->base.base.dev;
+	struct drm_device *dev = intel_hdmi_to_dev(intel_hdmi);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t bit;
 
@@ -786,6 +792,9 @@ static enum drm_connector_status
 intel_hdmi_detect(struct drm_connector *connector, bool force)
 {
 	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+	struct intel_digital_port *intel_dig_port =
+		hdmi_to_dig_port(intel_hdmi);
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
 	struct drm_i915_private *dev_priv = connector->dev->dev_private;
 	struct edid *edid;
 	enum drm_connector_status status = connector_status_disconnected;
@@ -814,6 +823,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
 		if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO)
 			intel_hdmi->has_audio =
 				(intel_hdmi->force_audio == HDMI_AUDIO_ON);
+		intel_encoder->type = INTEL_OUTPUT_HDMI;
 	}
 
 	return status;
@@ -859,6 +869,8 @@ intel_hdmi_set_property(struct drm_connector *connector,
 			uint64_t val)
 {
 	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+	struct intel_digital_port *intel_dig_port =
+		hdmi_to_dig_port(intel_hdmi);
 	struct drm_i915_private *dev_priv = connector->dev->dev_private;
 	int ret;
 
@@ -898,8 +910,8 @@ intel_hdmi_set_property(struct drm_connector *connector,
 	return -EINVAL;
 
 done:
-	if (intel_hdmi->base.base.crtc) {
-		struct drm_crtc *crtc = intel_hdmi->base.base.crtc;
+	if (intel_dig_port->base.base.crtc) {
+		struct drm_crtc *crtc = intel_dig_port->base.base.crtc;
 		intel_set_mode(crtc, &crtc->mode,
 			       crtc->x, crtc->y, crtc->fb);
 	}
@@ -914,12 +926,6 @@ static void intel_hdmi_destroy(struct drm_connector *connector)
 	kfree(connector);
 }
 
-static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs_hsw = {
-	.mode_fixup = intel_hdmi_mode_fixup,
-	.mode_set = intel_ddi_mode_set,
-	.disable = intel_encoder_noop,
-};
-
 static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
 	.mode_fixup = intel_hdmi_mode_fixup,
 	.mode_set = intel_hdmi_mode_set,
@@ -951,43 +957,24 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c
 	intel_attach_broadcast_rgb_property(connector);
 }
 
-void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
+void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
+			       struct intel_connector *intel_connector)
 {
+	struct drm_connector *connector = &intel_connector->base;
+	struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
+	struct drm_device *dev = intel_encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_connector *connector;
-	struct intel_encoder *intel_encoder;
-	struct intel_connector *intel_connector;
-	struct intel_hdmi *intel_hdmi;
+	enum port port = intel_dig_port->port;
 
-	intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL);
-	if (!intel_hdmi)
-		return;
-
-	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
-	if (!intel_connector) {
-		kfree(intel_hdmi);
-		return;
-	}
-
-	intel_encoder = &intel_hdmi->base;
-	drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs,
-			 DRM_MODE_ENCODER_TMDS);
-
-	connector = &intel_connector->base;
 	drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
 			   DRM_MODE_CONNECTOR_HDMIA);
 	drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
 
-	intel_encoder->type = INTEL_OUTPUT_HDMI;
-
 	connector->polled = DRM_CONNECTOR_POLL_HPD;
 	connector->interlace_allowed = 1;
 	connector->doublescan_allowed = 0;
-	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
-
-	intel_encoder->cloneable = false;
 
-	intel_hdmi->ddi_port = port;
 	switch (port) {
 	case PORT_B:
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
@@ -1007,8 +994,6 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 		BUG();
 	}
 
-	intel_hdmi->sdvox_reg = sdvox_reg;
-
 	if (!HAS_PCH_SPLIT(dev)) {
 		intel_hdmi->write_infoframe = g4x_write_infoframe;
 		intel_hdmi->set_infoframes = g4x_set_infoframes;
@@ -1026,21 +1011,10 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 		intel_hdmi->set_infoframes = cpt_set_infoframes;
 	}
 
-	if (IS_HASWELL(dev)) {
-		intel_encoder->enable = intel_enable_ddi;
-		intel_encoder->disable = intel_disable_ddi;
-		intel_encoder->get_hw_state = intel_ddi_get_hw_state;
-		drm_encoder_helper_add(&intel_encoder->base,
-				       &intel_hdmi_helper_funcs_hsw);
-	} else {
-		intel_encoder->enable = intel_enable_hdmi;
-		intel_encoder->disable = intel_disable_hdmi;
-		intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
-		drm_encoder_helper_add(&intel_encoder->base,
-				       &intel_hdmi_helper_funcs);
-	}
-	intel_connector->get_hw_state = intel_connector_get_hw_state;
-
+	if (IS_HASWELL(dev))
+		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
+	else
+		intel_connector->get_hw_state = intel_connector_get_hw_state;
 
 	intel_hdmi_add_properties(intel_hdmi, connector);
 
@@ -1056,3 +1030,42 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
 	}
 }
+
+void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
+{
+	struct intel_digital_port *intel_dig_port;
+	struct intel_encoder *intel_encoder;
+	struct drm_encoder *encoder;
+	struct intel_connector *intel_connector;
+
+	intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL);
+	if (!intel_dig_port)
+		return;
+
+	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
+	if (!intel_connector) {
+		kfree(intel_dig_port);
+		return;
+	}
+
+	intel_encoder = &intel_dig_port->base;
+	encoder = &intel_encoder->base;
+
+	drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs,
+			 DRM_MODE_ENCODER_TMDS);
+	drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
+
+	intel_encoder->enable = intel_enable_hdmi;
+	intel_encoder->disable = intel_disable_hdmi;
+	intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
+
+	intel_encoder->type = INTEL_OUTPUT_HDMI;
+	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
+	intel_encoder->cloneable = false;
+
+	intel_dig_port->port = port;
+	intel_dig_port->hdmi.sdvox_reg = sdvox_reg;
+	intel_dig_port->dp.output_reg = 0;
+
+	intel_hdmi_init_connector(intel_dig_port, intel_connector);
+}
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index c2c6dbc..3ef5af1 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -432,7 +432,7 @@ timeout:
 	I915_WRITE(GMBUS0 + reg_offset, 0);
 
 	/* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */
-	bus->force_bit = true;
+	bus->force_bit = 1;
 	ret = i2c_bit_algo.master_xfer(adapter, msgs, num);
 
 out:
@@ -491,7 +491,7 @@ int intel_setup_gmbus(struct drm_device *dev)
 
 		/* gmbus seems to be broken on i830 */
 		if (IS_I830(dev))
-			bus->force_bit = true;
+			bus->force_bit = 1;
 
 		intel_gpio_setup(bus, port);
 
@@ -532,7 +532,10 @@ void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
 {
 	struct intel_gmbus *bus = to_intel_gmbus(adapter);
 
-	bus->force_bit = force_bit;
+	bus->force_bit += force_bit ? 1 : -1;
+	DRM_DEBUG_KMS("%sabling bit-banging on %s. force bit now %d\n",
+		      force_bit ? "en" : "dis", adapter->name,
+		      bus->force_bit);
 }
 
 void intel_teardown_gmbus(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index edba93b..d831882 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -40,28 +40,30 @@
 #include <linux/acpi.h>
 
 /* Private structure for the integrated LVDS support */
-struct intel_lvds {
-	struct intel_encoder base;
+struct intel_lvds_connector {
+	struct intel_connector base;
 
-	struct edid *edid;
+	struct notifier_block lid_notifier;
+};
+
+struct intel_lvds_encoder {
+	struct intel_encoder base;
 
-	int fitting_mode;
 	u32 pfit_control;
 	u32 pfit_pgm_ratios;
 	bool pfit_dirty;
 
-	struct drm_display_mode *fixed_mode;
+	struct intel_lvds_connector *attached_connector;
 };
 
-static struct intel_lvds *to_intel_lvds(struct drm_encoder *encoder)
+static struct intel_lvds_encoder *to_lvds_encoder(struct drm_encoder *encoder)
 {
-	return container_of(encoder, struct intel_lvds, base.base);
+	return container_of(encoder, struct intel_lvds_encoder, base.base);
 }
 
-static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector)
+static struct intel_lvds_connector *to_lvds_connector(struct drm_connector *connector)
 {
-	return container_of(intel_attached_encoder(connector),
-			    struct intel_lvds, base);
+	return container_of(connector, struct intel_lvds_connector, base.base);
 }
 
 static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
@@ -96,7 +98,7 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
 static void intel_enable_lvds(struct intel_encoder *encoder)
 {
 	struct drm_device *dev = encoder->base.dev;
-	struct intel_lvds *intel_lvds = to_intel_lvds(&encoder->base);
+	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 ctl_reg, lvds_reg, stat_reg;
@@ -113,7 +115,7 @@ static void intel_enable_lvds(struct intel_encoder *encoder)
 
 	I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN);
 
-	if (intel_lvds->pfit_dirty) {
+	if (lvds_encoder->pfit_dirty) {
 		/*
 		 * Enable automatic panel scaling so that non-native modes
 		 * fill the screen.  The panel fitter should only be
@@ -121,12 +123,12 @@ static void intel_enable_lvds(struct intel_encoder *encoder)
 		 * register description and PRM.
 		 */
 		DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
-			      intel_lvds->pfit_control,
-			      intel_lvds->pfit_pgm_ratios);
+			      lvds_encoder->pfit_control,
+			      lvds_encoder->pfit_pgm_ratios);
 
-		I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
-		I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control);
-		intel_lvds->pfit_dirty = false;
+		I915_WRITE(PFIT_PGM_RATIOS, lvds_encoder->pfit_pgm_ratios);
+		I915_WRITE(PFIT_CONTROL, lvds_encoder->pfit_control);
+		lvds_encoder->pfit_dirty = false;
 	}
 
 	I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
@@ -140,7 +142,7 @@ static void intel_enable_lvds(struct intel_encoder *encoder)
 static void intel_disable_lvds(struct intel_encoder *encoder)
 {
 	struct drm_device *dev = encoder->base.dev;
-	struct intel_lvds *intel_lvds = to_intel_lvds(&encoder->base);
+	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 ctl_reg, lvds_reg, stat_reg;
 
@@ -160,9 +162,9 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
 	if (wait_for((I915_READ(stat_reg) & PP_ON) == 0, 1000))
 		DRM_ERROR("timed out waiting for panel to power off\n");
 
-	if (intel_lvds->pfit_control) {
+	if (lvds_encoder->pfit_control) {
 		I915_WRITE(PFIT_CONTROL, 0);
-		intel_lvds->pfit_dirty = true;
+		lvds_encoder->pfit_dirty = true;
 	}
 
 	I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN);
@@ -172,8 +174,8 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
 static int intel_lvds_mode_valid(struct drm_connector *connector,
 				 struct drm_display_mode *mode)
 {
-	struct intel_lvds *intel_lvds = intel_attached_lvds(connector);
-	struct drm_display_mode *fixed_mode = intel_lvds->fixed_mode;
+	struct intel_connector *intel_connector = to_intel_connector(connector);
+	struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
 
 	if (mode->hdisplay > fixed_mode->hdisplay)
 		return MODE_PANEL;
@@ -249,8 +251,10 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
-	struct intel_crtc *intel_crtc = intel_lvds->base.new_crtc;
+	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);
+	struct intel_connector *intel_connector =
+		&lvds_encoder->attached_connector->base;
+	struct intel_crtc *intel_crtc = lvds_encoder->base.new_crtc;
 	u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
 	int pipe;
 
@@ -260,7 +264,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 		return false;
 	}
 
-	if (intel_encoder_check_is_cloned(&intel_lvds->base))
+	if (intel_encoder_check_is_cloned(&lvds_encoder->base))
 		return false;
 
 	/*
@@ -269,10 +273,12 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 	 * with the panel scaling set up to source from the H/VDisplay
 	 * of the original mode.
 	 */
-	intel_fixed_panel_mode(intel_lvds->fixed_mode, adjusted_mode);
+	intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
+			       adjusted_mode);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		intel_pch_panel_fitting(dev, intel_lvds->fitting_mode,
+		intel_pch_panel_fitting(dev,
+					intel_connector->panel.fitting_mode,
 					mode, adjusted_mode);
 		return true;
 	}
@@ -298,7 +304,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 
 	drm_mode_set_crtcinfo(adjusted_mode, 0);
 
-	switch (intel_lvds->fitting_mode) {
+	switch (intel_connector->panel.fitting_mode) {
 	case DRM_MODE_SCALE_CENTER:
 		/*
 		 * For centered modes, we have to calculate border widths &
@@ -396,11 +402,11 @@ out:
 	if (INTEL_INFO(dev)->gen < 4 && dev_priv->lvds_dither)
 		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
 
-	if (pfit_control != intel_lvds->pfit_control ||
-	    pfit_pgm_ratios != intel_lvds->pfit_pgm_ratios) {
-		intel_lvds->pfit_control = pfit_control;
-		intel_lvds->pfit_pgm_ratios = pfit_pgm_ratios;
-		intel_lvds->pfit_dirty = true;
+	if (pfit_control != lvds_encoder->pfit_control ||
+	    pfit_pgm_ratios != lvds_encoder->pfit_pgm_ratios) {
+		lvds_encoder->pfit_control = pfit_control;
+		lvds_encoder->pfit_pgm_ratios = pfit_pgm_ratios;
+		lvds_encoder->pfit_dirty = true;
 	}
 	dev_priv->lvds_border_bits = border;
 
@@ -449,14 +455,20 @@ intel_lvds_detect(struct drm_connector *connector, bool force)
  */
 static int intel_lvds_get_modes(struct drm_connector *connector)
 {
-	struct intel_lvds *intel_lvds = intel_attached_lvds(connector);
+	struct intel_lvds_connector *lvds_connector = to_lvds_connector(connector);
 	struct drm_device *dev = connector->dev;
 	struct drm_display_mode *mode;
 
-	if (intel_lvds->edid)
-		return drm_add_edid_modes(connector, intel_lvds->edid);
+	/* use cached edid if we have one */
+	if (lvds_connector->base.edid) {
+		/* invalid edid */
+		if (IS_ERR(lvds_connector->base.edid))
+			return 0;
+
+		return drm_add_edid_modes(connector, lvds_connector->base.edid);
+	}
 
-	mode = drm_mode_duplicate(dev, intel_lvds->fixed_mode);
+	mode = drm_mode_duplicate(dev, lvds_connector->base.panel.fixed_mode);
 	if (mode == NULL)
 		return 0;
 
@@ -496,10 +508,11 @@ static const struct dmi_system_id intel_no_modeset_on_lid[] = {
 static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
 			    void *unused)
 {
-	struct drm_i915_private *dev_priv =
-		container_of(nb, struct drm_i915_private, lid_notifier);
-	struct drm_device *dev = dev_priv->dev;
-	struct drm_connector *connector = dev_priv->int_lvds_connector;
+	struct intel_lvds_connector *lvds_connector =
+		container_of(nb, struct intel_lvds_connector, lid_notifier);
+	struct drm_connector *connector = &lvds_connector->base.base;
+	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
 		return NOTIFY_OK;
@@ -508,9 +521,7 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
 	 * check and update the status of LVDS connector after receiving
 	 * the LID nofication event.
 	 */
-	if (connector)
-		connector->status = connector->funcs->detect(connector,
-							     false);
+	connector->status = connector->funcs->detect(connector, false);
 
 	/* Don't force modeset on machines where it causes a GPU lockup */
 	if (dmi_check_system(intel_no_modeset_on_lid))
@@ -541,13 +552,18 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
  */
 static void intel_lvds_destroy(struct drm_connector *connector)
 {
-	struct drm_device *dev = connector->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_lvds_connector *lvds_connector =
+		to_lvds_connector(connector);
 
-	intel_panel_destroy_backlight(dev);
+	if (lvds_connector->lid_notifier.notifier_call)
+		acpi_lid_notifier_unregister(&lvds_connector->lid_notifier);
+
+	if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
+		kfree(lvds_connector->base.edid);
+
+	intel_panel_destroy_backlight(connector->dev);
+	intel_panel_fini(&lvds_connector->base.panel);
 
-	if (dev_priv->lid_notifier.notifier_call)
-		acpi_lid_notifier_unregister(&dev_priv->lid_notifier);
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
 	kfree(connector);
@@ -557,22 +573,24 @@ static int intel_lvds_set_property(struct drm_connector *connector,
 				   struct drm_property *property,
 				   uint64_t value)
 {
-	struct intel_lvds *intel_lvds = intel_attached_lvds(connector);
+	struct intel_connector *intel_connector = to_intel_connector(connector);
 	struct drm_device *dev = connector->dev;
 
 	if (property == dev->mode_config.scaling_mode_property) {
-		struct drm_crtc *crtc = intel_lvds->base.base.crtc;
+		struct drm_crtc *crtc;
 
 		if (value == DRM_MODE_SCALE_NONE) {
 			DRM_DEBUG_KMS("no scaling not supported\n");
 			return -EINVAL;
 		}
 
-		if (intel_lvds->fitting_mode == value) {
+		if (intel_connector->panel.fitting_mode == value) {
 			/* the LVDS scaling property is not changed */
 			return 0;
 		}
-		intel_lvds->fitting_mode = value;
+		intel_connector->panel.fitting_mode = value;
+
+		crtc = intel_attached_encoder(connector)->base.crtc;
 		if (crtc && crtc->enabled) {
 			/*
 			 * If the CRTC is enabled, the display will be changed
@@ -912,12 +930,15 @@ static bool intel_lvds_supported(struct drm_device *dev)
 bool intel_lvds_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_lvds *intel_lvds;
+	struct intel_lvds_encoder *lvds_encoder;
 	struct intel_encoder *intel_encoder;
+	struct intel_lvds_connector *lvds_connector;
 	struct intel_connector *intel_connector;
 	struct drm_connector *connector;
 	struct drm_encoder *encoder;
 	struct drm_display_mode *scan; /* *modes, *bios_mode; */
+	struct drm_display_mode *fixed_mode = NULL;
+	struct edid *edid;
 	struct drm_crtc *crtc;
 	u32 lvds;
 	int pipe;
@@ -945,23 +966,25 @@ bool intel_lvds_init(struct drm_device *dev)
 		}
 	}
 
-	intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL);
-	if (!intel_lvds) {
+	lvds_encoder = kzalloc(sizeof(struct intel_lvds_encoder), GFP_KERNEL);
+	if (!lvds_encoder)
 		return false;
-	}
 
-	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
-	if (!intel_connector) {
-		kfree(intel_lvds);
+	lvds_connector = kzalloc(sizeof(struct intel_lvds_connector), GFP_KERNEL);
+	if (!lvds_connector) {
+		kfree(lvds_encoder);
 		return false;
 	}
 
+	lvds_encoder->attached_connector = lvds_connector;
+
 	if (!HAS_PCH_SPLIT(dev)) {
-		intel_lvds->pfit_control = I915_READ(PFIT_CONTROL);
+		lvds_encoder->pfit_control = I915_READ(PFIT_CONTROL);
 	}
 
-	intel_encoder = &intel_lvds->base;
+	intel_encoder = &lvds_encoder->base;
 	encoder = &intel_encoder->base;
+	intel_connector = &lvds_connector->base;
 	connector = &intel_connector->base;
 	drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs,
 			   DRM_MODE_CONNECTOR_LVDS);
@@ -993,14 +1016,10 @@ bool intel_lvds_init(struct drm_device *dev)
 
 	/* create the scaling mode property */
 	drm_mode_create_scaling_mode_property(dev);
-	/*
-	 * the initial panel fitting mode will be FULL_SCREEN.
-	 */
-
 	drm_connector_attach_property(&intel_connector->base,
 				      dev->mode_config.scaling_mode_property,
 				      DRM_MODE_SCALE_ASPECT);
-	intel_lvds->fitting_mode = DRM_MODE_SCALE_ASPECT;
+	intel_connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT;
 	/*
 	 * LVDS discovery:
 	 * 1) check for EDID on DDC
@@ -1015,20 +1034,21 @@ bool intel_lvds_init(struct drm_device *dev)
 	 * Attempt to get the fixed panel mode from DDC.  Assume that the
 	 * preferred mode is the right one.
 	 */
-	intel_lvds->edid = drm_get_edid(connector,
-					intel_gmbus_get_adapter(dev_priv,
-								pin));
-	if (intel_lvds->edid) {
-		if (drm_add_edid_modes(connector,
-				       intel_lvds->edid)) {
+	edid = drm_get_edid(connector, intel_gmbus_get_adapter(dev_priv, pin));
+	if (edid) {
+		if (drm_add_edid_modes(connector, edid)) {
 			drm_mode_connector_update_edid_property(connector,
-								intel_lvds->edid);
+								edid);
 		} else {
-			kfree(intel_lvds->edid);
-			intel_lvds->edid = NULL;
+			kfree(edid);
+			edid = ERR_PTR(-EINVAL);
 		}
+	} else {
+		edid = ERR_PTR(-ENOENT);
 	}
-	if (!intel_lvds->edid) {
+	lvds_connector->base.edid = edid;
+
+	if (IS_ERR_OR_NULL(edid)) {
 		/* Didn't get an EDID, so
 		 * Set wide sync ranges so we get all modes
 		 * handed to valid_mode for checking
@@ -1041,22 +1061,17 @@ bool intel_lvds_init(struct drm_device *dev)
 
 	list_for_each_entry(scan, &connector->probed_modes, head) {
 		if (scan->type & DRM_MODE_TYPE_PREFERRED) {
-			intel_lvds->fixed_mode =
-				drm_mode_duplicate(dev, scan);
-			intel_find_lvds_downclock(dev,
-						  intel_lvds->fixed_mode,
-						  connector);
+			fixed_mode = drm_mode_duplicate(dev, scan);
+			intel_find_lvds_downclock(dev, fixed_mode, connector);
 			goto out;
 		}
 	}
 
 	/* Failed to get EDID, what about VBT? */
 	if (dev_priv->lfp_lvds_vbt_mode) {
-		intel_lvds->fixed_mode =
-			drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
-		if (intel_lvds->fixed_mode) {
-			intel_lvds->fixed_mode->type |=
-				DRM_MODE_TYPE_PREFERRED;
+		fixed_mode = drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
+		if (fixed_mode) {
+			fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
 			goto out;
 		}
 	}
@@ -1076,16 +1091,15 @@ bool intel_lvds_init(struct drm_device *dev)
 	crtc = intel_get_crtc_for_pipe(dev, pipe);
 
 	if (crtc && (lvds & LVDS_PORT_EN)) {
-		intel_lvds->fixed_mode = intel_crtc_mode_get(dev, crtc);
-		if (intel_lvds->fixed_mode) {
-			intel_lvds->fixed_mode->type |=
-				DRM_MODE_TYPE_PREFERRED;
+		fixed_mode = intel_crtc_mode_get(dev, crtc);
+		if (fixed_mode) {
+			fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
 			goto out;
 		}
 	}
 
 	/* If we still don't have a mode after all that, give up. */
-	if (!intel_lvds->fixed_mode)
+	if (!fixed_mode)
 		goto failed;
 
 out:
@@ -1100,16 +1114,15 @@ out:
 		I915_WRITE(PP_CONTROL,
 			   I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
 	}
-	dev_priv->lid_notifier.notifier_call = intel_lid_notify;
-	if (acpi_lid_notifier_register(&dev_priv->lid_notifier)) {
+	lvds_connector->lid_notifier.notifier_call = intel_lid_notify;
+	if (acpi_lid_notifier_register(&lvds_connector->lid_notifier)) {
 		DRM_DEBUG_KMS("lid notifier registration failed\n");
-		dev_priv->lid_notifier.notifier_call = NULL;
+		lvds_connector->lid_notifier.notifier_call = NULL;
 	}
-	/* keep the LVDS connector */
-	dev_priv->int_lvds_connector = connector;
 	drm_sysfs_connector_add(connector);
 
-	intel_panel_setup_backlight(dev);
+	intel_panel_init(&intel_connector->panel, fixed_mode);
+	intel_panel_setup_backlight(connector);
 
 	return true;
 
@@ -1117,7 +1130,9 @@ failed:
 	DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
 	drm_connector_cleanup(connector);
 	drm_encoder_cleanup(encoder);
-	kfree(intel_lvds);
-	kfree(intel_connector);
+	if (fixed_mode)
+		drm_mode_destroy(dev, fixed_mode);
+	kfree(lvds_encoder);
+	kfree(lvds_connector);
 	return false;
 }
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c
index cabd84b..d49985f 100644
--- a/drivers/gpu/drm/i915/intel_modes.c
+++ b/drivers/gpu/drm/i915/intel_modes.c
@@ -45,7 +45,6 @@ int intel_connector_update_modes(struct drm_connector *connector,
 	drm_mode_connector_update_edid_property(connector, edid);
 	ret = drm_add_edid_modes(connector, edid);
 	drm_edid_to_eld(connector, edid);
-	kfree(edid);
 
 	return ret;
 }
@@ -61,12 +60,16 @@ int intel_ddc_get_modes(struct drm_connector *connector,
 			struct i2c_adapter *adapter)
 {
 	struct edid *edid;
+	int ret;
 
 	edid = drm_get_edid(connector, adapter);
 	if (!edid)
 		return 0;
 
-	return intel_connector_update_modes(connector, edid);
+	ret = intel_connector_update_modes(connector, edid);
+	kfree(edid);
+
+	return ret;
 }
 
 static const struct drm_prop_enum_list force_audio_names[] = {
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index 5530413..7741c22 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -154,6 +154,8 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
 	struct opregion_asle __iomem *asle = dev_priv->opregion.asle;
 	u32 max;
 
+	DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
+
 	if (!(bclp & ASLE_BCLP_VALID))
 		return ASLE_BACKLIGHT_FAILED;
 
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index e2aacd3..41d4635 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -138,24 +138,24 @@ static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv)
 
 	if (HAS_PCH_SPLIT(dev_priv->dev)) {
 		val = I915_READ(BLC_PWM_PCH_CTL2);
-		if (dev_priv->saveBLC_PWM_CTL2 == 0) {
-			dev_priv->saveBLC_PWM_CTL2 = val;
+		if (dev_priv->regfile.saveBLC_PWM_CTL2 == 0) {
+			dev_priv->regfile.saveBLC_PWM_CTL2 = val;
 		} else if (val == 0) {
 			I915_WRITE(BLC_PWM_PCH_CTL2,
-				   dev_priv->saveBLC_PWM_CTL2);
-			val = dev_priv->saveBLC_PWM_CTL2;
+				   dev_priv->regfile.saveBLC_PWM_CTL2);
+			val = dev_priv->regfile.saveBLC_PWM_CTL2;
 		}
 	} else {
 		val = I915_READ(BLC_PWM_CTL);
-		if (dev_priv->saveBLC_PWM_CTL == 0) {
-			dev_priv->saveBLC_PWM_CTL = val;
-			dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
+		if (dev_priv->regfile.saveBLC_PWM_CTL == 0) {
+			dev_priv->regfile.saveBLC_PWM_CTL = val;
+			dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
 		} else if (val == 0) {
 			I915_WRITE(BLC_PWM_CTL,
-				   dev_priv->saveBLC_PWM_CTL);
+				   dev_priv->regfile.saveBLC_PWM_CTL);
 			I915_WRITE(BLC_PWM_CTL2,
-				   dev_priv->saveBLC_PWM_CTL2);
-			val = dev_priv->saveBLC_PWM_CTL;
+				   dev_priv->regfile.saveBLC_PWM_CTL2);
+			val = dev_priv->regfile.saveBLC_PWM_CTL;
 		}
 	}
 
@@ -416,21 +416,14 @@ static const struct backlight_ops intel_panel_bl_ops = {
 	.get_brightness = intel_panel_get_brightness,
 };
 
-int intel_panel_setup_backlight(struct drm_device *dev)
+int intel_panel_setup_backlight(struct drm_connector *connector)
 {
+	struct drm_device *dev = connector->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct backlight_properties props;
-	struct drm_connector *connector;
 
 	intel_panel_init_backlight(dev);
 
-	if (dev_priv->int_lvds_connector)
-		connector = dev_priv->int_lvds_connector;
-	else if (dev_priv->int_edp_connector)
-		connector = dev_priv->int_edp_connector;
-	else
-		return -ENODEV;
-
 	memset(&props, 0, sizeof(props));
 	props.type = BACKLIGHT_RAW;
 	props.max_brightness = _intel_panel_get_max_backlight(dev);
@@ -460,9 +453,9 @@ void intel_panel_destroy_backlight(struct drm_device *dev)
 		backlight_device_unregister(dev_priv->backlight);
 }
 #else
-int intel_panel_setup_backlight(struct drm_device *dev)
+int intel_panel_setup_backlight(struct drm_connector *connector)
 {
-	intel_panel_init_backlight(dev);
+	intel_panel_init_backlight(connector->dev);
 	return 0;
 }
 
@@ -471,3 +464,20 @@ void intel_panel_destroy_backlight(struct drm_device *dev)
 	return;
 }
 #endif
+
+int intel_panel_init(struct intel_panel *panel,
+		     struct drm_display_mode *fixed_mode)
+{
+	panel->fixed_mode = fixed_mode;
+
+	return 0;
+}
+
+void intel_panel_fini(struct intel_panel *panel)
+{
+	struct intel_connector *intel_connector =
+		container_of(panel, struct intel_connector, panel);
+
+	if (panel->fixed_mode)
+		drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
+}
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 72f41aa..0edb549 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1468,9 +1468,12 @@ static void i9xx_update_wm(struct drm_device *dev)
 	fifo_size = dev_priv->display.get_fifo_size(dev, 0);
 	crtc = intel_get_crtc_for_plane(dev, 0);
 	if (crtc->enabled && crtc->fb) {
+		int cpp = crtc->fb->bits_per_pixel / 8;
+		if (IS_GEN2(dev))
+			cpp = 4;
+
 		planea_wm = intel_calculate_wm(crtc->mode.clock,
-					       wm_info, fifo_size,
-					       crtc->fb->bits_per_pixel / 8,
+					       wm_info, fifo_size, cpp,
 					       latency_ns);
 		enabled = crtc;
 	} else
@@ -1479,9 +1482,12 @@ static void i9xx_update_wm(struct drm_device *dev)
 	fifo_size = dev_priv->display.get_fifo_size(dev, 1);
 	crtc = intel_get_crtc_for_plane(dev, 1);
 	if (crtc->enabled && crtc->fb) {
+		int cpp = crtc->fb->bits_per_pixel / 8;
+		if (IS_GEN2(dev))
+			cpp = 4;
+
 		planeb_wm = intel_calculate_wm(crtc->mode.clock,
-					       wm_info, fifo_size,
-					       crtc->fb->bits_per_pixel / 8,
+					       wm_info, fifo_size, cpp,
 					       latency_ns);
 		if (enabled == NULL)
 			enabled = crtc;
@@ -1571,8 +1577,7 @@ static void i830_update_wm(struct drm_device *dev)
 
 	planea_wm = intel_calculate_wm(crtc->mode.clock, &i830_wm_info,
 				       dev_priv->display.get_fifo_size(dev, 0),
-				       crtc->fb->bits_per_pixel / 8,
-				       latency_ns);
+				       4, latency_ns);
 	fwater_lo = I915_READ(FW_BLC) & ~0xfff;
 	fwater_lo |= (3<<8) | planea_wm;
 
@@ -2323,7 +2328,7 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 limits = gen6_rps_limits(dev_priv, &val);
 
-	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
 	WARN_ON(val > dev_priv->rps.max_delay);
 	WARN_ON(val < dev_priv->rps.min_delay);
 
@@ -2404,12 +2409,12 @@ static void gen6_enable_rps(struct drm_device *dev)
 	struct intel_ring_buffer *ring;
 	u32 rp_state_cap;
 	u32 gt_perf_status;
-	u32 pcu_mbox, rc6_mask = 0;
+	u32 rc6vids, pcu_mbox, rc6_mask = 0;
 	u32 gtfifodbg;
 	int rc6_mode;
-	int i;
+	int i, ret;
 
-	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
 
 	/* Here begins a magic sequence of register writes to enable
 	 * auto-downclocking.
@@ -2503,30 +2508,16 @@ static void gen6_enable_rps(struct drm_device *dev)
 		   GEN6_RP_UP_BUSY_AVG |
 		   (IS_HASWELL(dev) ? GEN7_RP_DOWN_IDLE_AVG : GEN6_RP_DOWN_IDLE_CONT));
 
-	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
-		     500))
-		DRM_ERROR("timeout waiting for pcode mailbox to become idle\n");
-
-	I915_WRITE(GEN6_PCODE_DATA, 0);
-	I915_WRITE(GEN6_PCODE_MAILBOX,
-		   GEN6_PCODE_READY |
-		   GEN6_PCODE_WRITE_MIN_FREQ_TABLE);
-	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
-		     500))
-		DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
-
-	/* Check for overclock support */
-	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
-		     500))
-		DRM_ERROR("timeout waiting for pcode mailbox to become idle\n");
-	I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_READ_OC_PARAMS);
-	pcu_mbox = I915_READ(GEN6_PCODE_DATA);
-	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
-		     500))
-		DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
-	if (pcu_mbox & (1<<31)) { /* OC supported */
-		dev_priv->rps.max_delay = pcu_mbox & 0xff;
-		DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50);
+	ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0);
+	if (!ret) {
+		pcu_mbox = 0;
+		ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox);
+		if (ret && pcu_mbox & (1<<31)) { /* OC supported */
+			dev_priv->rps.max_delay = pcu_mbox & 0xff;
+			DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50);
+		}
+	} else {
+		DRM_DEBUG_DRIVER("Failed to set the min frequency\n");
 	}
 
 	gen6_set_rps(dev_priv->dev, (gt_perf_status & 0xff00) >> 8);
@@ -2540,6 +2531,20 @@ static void gen6_enable_rps(struct drm_device *dev)
 	/* enable all PM interrupts */
 	I915_WRITE(GEN6_PMINTRMSK, 0);
 
+	rc6vids = 0;
+	ret = sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
+	if (IS_GEN6(dev) && ret) {
+		DRM_DEBUG_DRIVER("Couldn't check for BIOS workaround\n");
+	} else if (IS_GEN6(dev) && (GEN6_DECODE_RC6_VID(rc6vids & 0xff) < 450)) {
+		DRM_DEBUG_DRIVER("You should update your BIOS. Correcting minimum rc6 voltage (%dmV->%dmV)\n",
+			  GEN6_DECODE_RC6_VID(rc6vids & 0xff), 450);
+		rc6vids &= 0xffff00;
+		rc6vids |= GEN6_ENCODE_RC6_VID(450);
+		ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_RC6VIDS, rc6vids);
+		if (ret)
+			DRM_ERROR("Couldn't fix incorrect rc6 voltage\n");
+	}
+
 	gen6_gt_force_wake_put(dev_priv);
 }
 
@@ -2547,10 +2552,11 @@ static void gen6_update_ring_freq(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int min_freq = 15;
-	int gpu_freq, ia_freq, max_ia_freq;
+	int gpu_freq;
+	unsigned int ia_freq, max_ia_freq;
 	int scaling_factor = 180;
 
-	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
 
 	max_ia_freq = cpufreq_quick_get_max(0);
 	/*
@@ -2581,17 +2587,11 @@ static void gen6_update_ring_freq(struct drm_device *dev)
 		else
 			ia_freq = max_ia_freq - ((diff * scaling_factor) / 2);
 		ia_freq = DIV_ROUND_CLOSEST(ia_freq, 100);
+		ia_freq <<= GEN6_PCODE_FREQ_IA_RATIO_SHIFT;
 
-		I915_WRITE(GEN6_PCODE_DATA,
-			   (ia_freq << GEN6_PCODE_FREQ_IA_RATIO_SHIFT) |
-			   gpu_freq);
-		I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY |
-			   GEN6_PCODE_WRITE_MIN_FREQ_TABLE);
-		if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) &
-			      GEN6_PCODE_READY) == 0, 10)) {
-			DRM_ERROR("pcode write of freq table timed out\n");
-			continue;
-		}
+		sandybridge_pcode_write(dev_priv,
+					GEN6_PCODE_WRITE_MIN_FREQ_TABLE,
+					ia_freq | gpu_freq);
 	}
 }
 
@@ -2599,16 +2599,16 @@ void ironlake_teardown_rc6(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (dev_priv->renderctx) {
-		i915_gem_object_unpin(dev_priv->renderctx);
-		drm_gem_object_unreference(&dev_priv->renderctx->base);
-		dev_priv->renderctx = NULL;
+	if (dev_priv->ips.renderctx) {
+		i915_gem_object_unpin(dev_priv->ips.renderctx);
+		drm_gem_object_unreference(&dev_priv->ips.renderctx->base);
+		dev_priv->ips.renderctx = NULL;
 	}
 
-	if (dev_priv->pwrctx) {
-		i915_gem_object_unpin(dev_priv->pwrctx);
-		drm_gem_object_unreference(&dev_priv->pwrctx->base);
-		dev_priv->pwrctx = NULL;
+	if (dev_priv->ips.pwrctx) {
+		i915_gem_object_unpin(dev_priv->ips.pwrctx);
+		drm_gem_object_unreference(&dev_priv->ips.pwrctx->base);
+		dev_priv->ips.pwrctx = NULL;
 	}
 }
 
@@ -2634,14 +2634,14 @@ static int ironlake_setup_rc6(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (dev_priv->renderctx == NULL)
-		dev_priv->renderctx = intel_alloc_context_page(dev);
-	if (!dev_priv->renderctx)
+	if (dev_priv->ips.renderctx == NULL)
+		dev_priv->ips.renderctx = intel_alloc_context_page(dev);
+	if (!dev_priv->ips.renderctx)
 		return -ENOMEM;
 
-	if (dev_priv->pwrctx == NULL)
-		dev_priv->pwrctx = intel_alloc_context_page(dev);
-	if (!dev_priv->pwrctx) {
+	if (dev_priv->ips.pwrctx == NULL)
+		dev_priv->ips.pwrctx = intel_alloc_context_page(dev);
+	if (!dev_priv->ips.pwrctx) {
 		ironlake_teardown_rc6(dev);
 		return -ENOMEM;
 	}
@@ -2679,7 +2679,7 @@ static void ironlake_enable_rc6(struct drm_device *dev)
 
 	intel_ring_emit(ring, MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN);
 	intel_ring_emit(ring, MI_SET_CONTEXT);
-	intel_ring_emit(ring, dev_priv->renderctx->gtt_offset |
+	intel_ring_emit(ring, dev_priv->ips.renderctx->gtt_offset |
 			MI_MM_SPACE_GTT |
 			MI_SAVE_EXT_STATE_EN |
 			MI_RESTORE_EXT_STATE_EN |
@@ -2701,7 +2701,7 @@ static void ironlake_enable_rc6(struct drm_device *dev)
 		return;
 	}
 
-	I915_WRITE(PWRCTXA, dev_priv->pwrctx->gtt_offset | PWRCTX_EN);
+	I915_WRITE(PWRCTXA, dev_priv->ips.pwrctx->gtt_offset | PWRCTX_EN);
 	I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
 }
 
@@ -3310,37 +3310,72 @@ static void intel_init_emon(struct drm_device *dev)
 
 void intel_disable_gt_powersave(struct drm_device *dev)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
 	if (IS_IRONLAKE_M(dev)) {
 		ironlake_disable_drps(dev);
 		ironlake_disable_rc6(dev);
 	} else if (INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev)) {
+		cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
+		mutex_lock(&dev_priv->rps.hw_lock);
 		gen6_disable_rps(dev);
+		mutex_unlock(&dev_priv->rps.hw_lock);
 	}
 }
 
+static void intel_gen6_powersave_work(struct work_struct *work)
+{
+	struct drm_i915_private *dev_priv =
+		container_of(work, struct drm_i915_private,
+			     rps.delayed_resume_work.work);
+	struct drm_device *dev = dev_priv->dev;
+
+	mutex_lock(&dev_priv->rps.hw_lock);
+	gen6_enable_rps(dev);
+	gen6_update_ring_freq(dev);
+	mutex_unlock(&dev_priv->rps.hw_lock);
+}
+
 void intel_enable_gt_powersave(struct drm_device *dev)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
 	if (IS_IRONLAKE_M(dev)) {
 		ironlake_enable_drps(dev);
 		ironlake_enable_rc6(dev);
 		intel_init_emon(dev);
 	} else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) {
-		gen6_enable_rps(dev);
-		gen6_update_ring_freq(dev);
+		/*
+		 * PCU communication is slow and this doesn't need to be
+		 * done at any specific time, so do this out of our fast path
+		 * to make resume and init faster.
+		 */
+		schedule_delayed_work(&dev_priv->rps.delayed_resume_work,
+				      round_jiffies_up_relative(HZ));
 	}
 }
 
+static void ibx_init_clock_gating(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	/*
+	 * On Ibex Peak and Cougar Point, we need to disable clock
+	 * 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);
+}
+
 static void ironlake_init_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
+	uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE;
 
 	/* Required for FBC */
-	dspclk_gate |= DPFCUNIT_CLOCK_GATE_DISABLE |
-		DPFCRUNIT_CLOCK_GATE_DISABLE |
-		DPFDUNIT_CLOCK_GATE_DISABLE;
-	/* Required for CxSR */
-	dspclk_gate |= DPARBUNIT_CLOCK_GATE_DISABLE;
+	dspclk_gate |= ILK_DPFCRUNIT_CLOCK_GATE_DISABLE |
+		   ILK_DPFCUNIT_CLOCK_GATE_DISABLE |
+		   ILK_DPFDUNIT_CLOCK_GATE_ENABLE;
 
 	I915_WRITE(PCH_3DCGDIS0,
 		   MARIUNIT_CLOCK_GATE_DISABLE |
@@ -3348,8 +3383,6 @@ static void ironlake_init_clock_gating(struct drm_device *dev)
 	I915_WRITE(PCH_3DCGDIS1,
 		   VFMUNIT_CLOCK_GATE_DISABLE);
 
-	I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
-
 	/*
 	 * According to the spec the following bits should be set in
 	 * order to enable memory self-refresh
@@ -3360,9 +3393,7 @@ static void ironlake_init_clock_gating(struct drm_device *dev)
 	I915_WRITE(ILK_DISPLAY_CHICKEN2,
 		   (I915_READ(ILK_DISPLAY_CHICKEN2) |
 		    ILK_DPARB_GATE | ILK_VSDPFD_FULL));
-	I915_WRITE(ILK_DSPCLK_GATE,
-		   (I915_READ(ILK_DSPCLK_GATE) |
-		    ILK_DPARB_CLK_GATE));
+	dspclk_gate |= ILK_DPARBUNIT_CLOCK_GATE_ENABLE;
 	I915_WRITE(DISP_ARB_CTL,
 		   (I915_READ(DISP_ARB_CTL) |
 		    DISP_FBC_WM_DIS));
@@ -3384,28 +3415,51 @@ static void ironlake_init_clock_gating(struct drm_device *dev)
 		I915_WRITE(ILK_DISPLAY_CHICKEN2,
 			   I915_READ(ILK_DISPLAY_CHICKEN2) |
 			   ILK_DPARB_GATE);
-		I915_WRITE(ILK_DSPCLK_GATE,
-			   I915_READ(ILK_DSPCLK_GATE) |
-			   ILK_DPFC_DIS1 |
-			   ILK_DPFC_DIS2 |
-			   ILK_CLK_FBC);
 	}
 
+	I915_WRITE(ILK_DSPCLK_GATE_D, dspclk_gate);
+
 	I915_WRITE(ILK_DISPLAY_CHICKEN2,
 		   I915_READ(ILK_DISPLAY_CHICKEN2) |
 		   ILK_ELPIN_409_SELECT);
 	I915_WRITE(_3D_CHICKEN2,
 		   _3D_CHICKEN2_WM_READ_PIPELINED << 16 |
 		   _3D_CHICKEN2_WM_READ_PIPELINED);
+
+	/* WaDisableRenderCachePipelinedFlush */
+	I915_WRITE(CACHE_MODE_0,
+		   _MASKED_BIT_ENABLE(CM0_PIPELINED_RENDER_FLUSH_DISABLE));
+
+	ibx_init_clock_gating(dev);
+}
+
+static void cpt_init_clock_gating(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int pipe;
+
+	/*
+	 * On Ibex Peak and Cougar Point, we need to disable clock
+	 * 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_CHICKEN2, I915_READ(SOUTH_CHICKEN2) |
+		   DPLS_EDP_PPS_FIX_DIS);
+	/* WADP0ClockGatingDisable */
+	for_each_pipe(pipe) {
+		I915_WRITE(TRANS_CHICKEN1(pipe),
+			   TRANS_CHICKEN1_DP0UNIT_GC_DISABLE);
+	}
 }
 
 static void gen6_init_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int pipe;
-	uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
+	uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE;
 
-	I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
+	I915_WRITE(ILK_DSPCLK_GATE_D, dspclk_gate);
 
 	I915_WRITE(ILK_DISPLAY_CHICKEN2,
 		   I915_READ(ILK_DISPLAY_CHICKEN2) |
@@ -3460,10 +3514,10 @@ static void gen6_init_clock_gating(struct drm_device *dev)
 	I915_WRITE(ILK_DISPLAY_CHICKEN2,
 		   I915_READ(ILK_DISPLAY_CHICKEN2) |
 		   ILK_DPARB_GATE | ILK_VSDPFD_FULL);
-	I915_WRITE(ILK_DSPCLK_GATE,
-		   I915_READ(ILK_DSPCLK_GATE) |
-		   ILK_DPARB_CLK_GATE  |
-		   ILK_DPFD_CLK_GATE);
+	I915_WRITE(ILK_DSPCLK_GATE_D,
+		   I915_READ(ILK_DSPCLK_GATE_D) |
+		   ILK_DPARBUNIT_CLOCK_GATE_ENABLE  |
+		   ILK_DPFDUNIT_CLOCK_GATE_ENABLE);
 
 	I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) |
 		   GEN6_MBCTL_ENABLE_BOOT_FETCH);
@@ -3479,6 +3533,8 @@ static void gen6_init_clock_gating(struct drm_device *dev)
 	 * platforms I checked have a 0 for this. (Maybe BIOS overrides?) */
 	I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_DISABLE(0xffff));
 	I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_ENABLE(GEN6_GT_MODE_HI));
+
+	cpt_init_clock_gating(dev);
 }
 
 static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
@@ -3497,9 +3553,6 @@ static void haswell_init_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int pipe;
-	uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
-
-	I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
 
 	I915_WRITE(WM3_LP_ILK, 0);
 	I915_WRITE(WM2_LP_ILK, 0);
@@ -3510,12 +3563,6 @@ static void haswell_init_clock_gating(struct drm_device *dev)
 	 */
 	I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE);
 
-	I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE);
-
-	I915_WRITE(IVB_CHICKEN3,
-		   CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
-		   CHICKEN3_DGMG_DONE_FIX_DISABLE);
-
 	/* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */
 	I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
 		   GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
@@ -3559,21 +3606,31 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int pipe;
-	uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
 	uint32_t snpcr;
 
-	I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
-
 	I915_WRITE(WM3_LP_ILK, 0);
 	I915_WRITE(WM2_LP_ILK, 0);
 	I915_WRITE(WM1_LP_ILK, 0);
 
-	I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE);
+	I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE);
+
+	/* WaDisableEarlyCull */
+	I915_WRITE(_3D_CHICKEN3,
+		   _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL));
 
+	/* WaDisableBackToBackFlipFix */
 	I915_WRITE(IVB_CHICKEN3,
 		   CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
 		   CHICKEN3_DGMG_DONE_FIX_DISABLE);
 
+	/* WaDisablePSDDualDispatchEnable */
+	if (IS_IVB_GT1(dev))
+		I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
+			   _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
+	else
+		I915_WRITE(GEN7_HALF_SLICE_CHICKEN1_GT2,
+			   _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
+
 	/* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */
 	I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
 		   GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
@@ -3582,7 +3639,18 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
 	I915_WRITE(GEN7_L3CNTLREG1,
 			GEN7_WA_FOR_GEN7_L3_CONTROL);
 	I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER,
-			GEN7_WA_L3_CHICKEN_MODE);
+		   GEN7_WA_L3_CHICKEN_MODE);
+	if (IS_IVB_GT1(dev))
+		I915_WRITE(GEN7_ROW_CHICKEN2,
+			   _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
+	else
+		I915_WRITE(GEN7_ROW_CHICKEN2_GT2,
+			   _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
+
+
+	/* WaForceL3Serialization */
+	I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) &
+		   ~L3SQ_URB_READ_CAM_MATCH_DISABLE);
 
 	/* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock
 	 * gating disable must be set.  Failure to set it results in
@@ -3626,34 +3694,53 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
 	snpcr &= ~GEN6_MBC_SNPCR_MASK;
 	snpcr |= GEN6_MBC_SNPCR_MED;
 	I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
+
+	cpt_init_clock_gating(dev);
 }
 
 static void valleyview_init_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int pipe;
-	uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
-
-	I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
 
 	I915_WRITE(WM3_LP_ILK, 0);
 	I915_WRITE(WM2_LP_ILK, 0);
 	I915_WRITE(WM1_LP_ILK, 0);
 
-	I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE);
+	I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE);
+
+	/* WaDisableEarlyCull */
+	I915_WRITE(_3D_CHICKEN3,
+		   _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL));
 
+	/* WaDisableBackToBackFlipFix */
 	I915_WRITE(IVB_CHICKEN3,
 		   CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
 		   CHICKEN3_DGMG_DONE_FIX_DISABLE);
 
+	I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
+		   _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
+
 	/* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */
 	I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
 		   GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
 
 	/* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */
-	I915_WRITE(GEN7_L3CNTLREG1, GEN7_WA_FOR_GEN7_L3_CONTROL);
+	I915_WRITE(GEN7_L3CNTLREG1, I915_READ(GEN7_L3CNTLREG1) | GEN7_L3AGDIS);
 	I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, GEN7_WA_L3_CHICKEN_MODE);
 
+	/* WaForceL3Serialization */
+	I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) &
+		   ~L3SQ_URB_READ_CAM_MATCH_DISABLE);
+
+	/* WaDisableDopClockGating */
+	I915_WRITE(GEN7_ROW_CHICKEN2,
+		   _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
+
+	/* WaForceL3Serialization */
+	I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) &
+		   ~L3SQ_URB_READ_CAM_MATCH_DISABLE);
+
 	/* This is required by WaCatErrorRejectionIssue */
 	I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
 		   I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
@@ -3710,6 +3797,13 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
 		   PIPEA_HLINE_INT_EN | PIPEA_VBLANK_INT_EN |
 		   SPRITEB_FLIPDONE_INT_EN | SPRITEA_FLIPDONE_INT_EN |
 		   PLANEA_FLIPDONE_INT_EN);
+
+	/*
+	 * WaDisableVLVClockGating_VBIIssue
+	 * Disable clock gating on th GCFG unit to prevent a delay
+	 * in the reporting of vblank events.
+	 */
+	I915_WRITE(VLV_GUNIT_CLOCK_GATE, GCFG_DIS);
 }
 
 static void g4x_init_clock_gating(struct drm_device *dev)
@@ -3728,6 +3822,10 @@ static void g4x_init_clock_gating(struct drm_device *dev)
 	if (IS_GM45(dev))
 		dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE;
 	I915_WRITE(DSPCLK_GATE_D, dspclk_gate);
+
+	/* WaDisableRenderCachePipelinedFlush */
+	I915_WRITE(CACHE_MODE_0,
+		   _MASKED_BIT_ENABLE(CM0_PIPELINED_RENDER_FLUSH_DISABLE));
 }
 
 static void crestline_init_clock_gating(struct drm_device *dev)
@@ -3783,44 +3881,11 @@ static void i830_init_clock_gating(struct drm_device *dev)
 	I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
 }
 
-static void ibx_init_clock_gating(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	/*
-	 * On Ibex Peak and Cougar Point, we need to disable clock
-	 * 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);
-}
-
-static void cpt_init_clock_gating(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int pipe;
-
-	/*
-	 * On Ibex Peak and Cougar Point, we need to disable clock
-	 * 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_CHICKEN2, I915_READ(SOUTH_CHICKEN2) |
-		   DPLS_EDP_PPS_FIX_DIS);
-	/* Without this, mode sets may fail silently on FDI */
-	for_each_pipe(pipe)
-		I915_WRITE(TRANS_CHICKEN2(pipe), TRANS_AUTOTRAIN_GEN_STALL_DIS);
-}
-
 void intel_init_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	dev_priv->display.init_clock_gating(dev);
-
-	if (dev_priv->display.init_pch_clock_gating)
-		dev_priv->display.init_pch_clock_gating(dev);
 }
 
 /* Starting with Haswell, we have different power wells for
@@ -3846,7 +3911,7 @@ void intel_init_power_wells(struct drm_device *dev)
 
 		if ((well & HSW_PWR_WELL_STATE) == 0) {
 			I915_WRITE(power_wells[i], well & HSW_PWR_WELL_ENABLE);
-			if (wait_for(I915_READ(power_wells[i] & HSW_PWR_WELL_STATE), 20))
+			if (wait_for((I915_READ(power_wells[i]) & HSW_PWR_WELL_STATE), 20))
 				DRM_ERROR("Error enabling power well %lx\n", power_wells[i]);
 		}
 	}
@@ -3884,11 +3949,6 @@ void intel_init_pm(struct drm_device *dev)
 
 	/* For FIFO watermark updates */
 	if (HAS_PCH_SPLIT(dev)) {
-		if (HAS_PCH_IBX(dev))
-			dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating;
-		else if (HAS_PCH_CPT(dev))
-			dev_priv->display.init_pch_clock_gating = cpt_init_clock_gating;
-
 		if (IS_GEN5(dev)) {
 			if (I915_READ(MLTR_ILK) & ILK_SRLT_MASK)
 				dev_priv->display.update_wm = ironlake_update_wm;
@@ -3999,6 +4059,12 @@ static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv)
 		DRM_ERROR("GT thread status wait timed out\n");
 }
 
+static void __gen6_gt_force_wake_reset(struct drm_i915_private *dev_priv)
+{
+	I915_WRITE_NOTRACE(FORCEWAKE, 0);
+	POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
+}
+
 static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
 {
 	u32 forcewake_ack;
@@ -4012,7 +4078,7 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
 			    FORCEWAKE_ACK_TIMEOUT_MS))
 		DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
 
-	I915_WRITE_NOTRACE(FORCEWAKE, 1);
+	I915_WRITE_NOTRACE(FORCEWAKE, FORCEWAKE_KERNEL);
 	POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
 
 	if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1),
@@ -4022,6 +4088,12 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
 	__gen6_gt_wait_for_thread_c0(dev_priv);
 }
 
+static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv)
+{
+	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff));
+	POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
+}
+
 static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
 {
 	u32 forcewake_ack;
@@ -4035,7 +4107,7 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
 			    FORCEWAKE_ACK_TIMEOUT_MS))
 		DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
 
-	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1));
+	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
 	POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
 
 	if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1),
@@ -4079,7 +4151,7 @@ static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
 
 static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
 {
-	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1));
+	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
 	/* gen6_gt_check_fifodbg doubles as the POSTING_READ */
 	gen6_gt_check_fifodbg(dev_priv);
 }
@@ -4117,13 +4189,18 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
 	return ret;
 }
 
+static void vlv_force_wake_reset(struct drm_i915_private *dev_priv)
+{
+	I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff));
+}
+
 static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
 {
 	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1) == 0,
 			    FORCEWAKE_ACK_TIMEOUT_MS))
 		DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
 
-	I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_ENABLE(1));
+	I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
 
 	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1),
 			    FORCEWAKE_ACK_TIMEOUT_MS))
@@ -4134,49 +4211,89 @@ static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
 
 static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
 {
-	I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(1));
+	I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
 	/* The below doubles as a POSTING_READ */
 	gen6_gt_check_fifodbg(dev_priv);
 }
 
+void intel_gt_reset(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (IS_VALLEYVIEW(dev)) {
+		vlv_force_wake_reset(dev_priv);
+	} else if (INTEL_INFO(dev)->gen >= 6) {
+		__gen6_gt_force_wake_reset(dev_priv);
+		if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
+			__gen6_gt_force_wake_mt_reset(dev_priv);
+	}
+}
+
 void intel_gt_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	spin_lock_init(&dev_priv->gt_lock);
 
+	intel_gt_reset(dev);
+
 	if (IS_VALLEYVIEW(dev)) {
 		dev_priv->gt.force_wake_get = vlv_force_wake_get;
 		dev_priv->gt.force_wake_put = vlv_force_wake_put;
-	} else if (INTEL_INFO(dev)->gen >= 6) {
+	} else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
+		dev_priv->gt.force_wake_get = __gen6_gt_force_wake_mt_get;
+		dev_priv->gt.force_wake_put = __gen6_gt_force_wake_mt_put;
+	} else if (IS_GEN6(dev)) {
 		dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get;
 		dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put;
+	}
+	INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work,
+			  intel_gen6_powersave_work);
+}
 
-		/* IVB configs may use multi-threaded forcewake */
-		if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
-			u32 ecobus;
-
-			/* A small trick here - if the bios hasn't configured
-			 * MT forcewake, and if the device is in RC6, then
-			 * force_wake_mt_get will not wake the device and the
-			 * ECOBUS read will return zero. Which will be
-			 * (correctly) interpreted by the test below as MT
-			 * forcewake being disabled.
-			 */
-			mutex_lock(&dev->struct_mutex);
-			__gen6_gt_force_wake_mt_get(dev_priv);
-			ecobus = I915_READ_NOTRACE(ECOBUS);
-			__gen6_gt_force_wake_mt_put(dev_priv);
-			mutex_unlock(&dev->struct_mutex);
-
-			if (ecobus & FORCEWAKE_MT_ENABLE) {
-				DRM_DEBUG_KMS("Using MT version of forcewake\n");
-				dev_priv->gt.force_wake_get =
-					__gen6_gt_force_wake_mt_get;
-				dev_priv->gt.force_wake_put =
-					__gen6_gt_force_wake_mt_put;
-			}
-		}
+int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val)
+{
+	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+
+	if (I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) {
+		DRM_DEBUG_DRIVER("warning: pcode (read) mailbox access failed\n");
+		return -EAGAIN;
 	}
+
+	I915_WRITE(GEN6_PCODE_DATA, *val);
+	I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY | mbox);
+
+	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
+		     500)) {
+		DRM_ERROR("timeout waiting for pcode read (%d) to finish\n", mbox);
+		return -ETIMEDOUT;
+	}
+
+	*val = I915_READ(GEN6_PCODE_DATA);
+	I915_WRITE(GEN6_PCODE_DATA, 0);
+
+	return 0;
 }
 
+int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val)
+{
+	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+
+	if (I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) {
+		DRM_DEBUG_DRIVER("warning: pcode (write) mailbox access failed\n");
+		return -EAGAIN;
+	}
+
+	I915_WRITE(GEN6_PCODE_DATA, val);
+	I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY | mbox);
+
+	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
+		     500)) {
+		DRM_ERROR("timeout waiting for pcode write (%d) to finish\n", mbox);
+		return -ETIMEDOUT;
+	}
+
+	I915_WRITE(GEN6_PCODE_DATA, 0);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index ecbc5c5..1aa7689 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -245,7 +245,7 @@ gen6_render_ring_flush(struct intel_ring_buffer *ring,
 		/*
 		 * TLB invalidate requires a post-sync write.
 		 */
-		flags |= PIPE_CONTROL_QW_WRITE;
+		flags |= PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_CS_STALL;
 	}
 
 	ret = intel_ring_begin(ring, 4);
@@ -964,7 +964,9 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring)
 }
 
 static int
-i965_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 length)
+i965_dispatch_execbuffer(struct intel_ring_buffer *ring,
+			 u32 offset, u32 length,
+			 unsigned flags)
 {
 	int ret;
 
@@ -975,7 +977,7 @@ i965_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 length)
 	intel_ring_emit(ring,
 			MI_BATCH_BUFFER_START |
 			MI_BATCH_GTT |
-			MI_BATCH_NON_SECURE_I965);
+			(flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965));
 	intel_ring_emit(ring, offset);
 	intel_ring_advance(ring);
 
@@ -984,7 +986,8 @@ i965_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 length)
 
 static int
 i830_dispatch_execbuffer(struct intel_ring_buffer *ring,
-				u32 offset, u32 len)
+				u32 offset, u32 len,
+				unsigned flags)
 {
 	int ret;
 
@@ -993,7 +996,7 @@ i830_dispatch_execbuffer(struct intel_ring_buffer *ring,
 		return ret;
 
 	intel_ring_emit(ring, MI_BATCH_BUFFER);
-	intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE);
+	intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE));
 	intel_ring_emit(ring, offset + len - 8);
 	intel_ring_emit(ring, 0);
 	intel_ring_advance(ring);
@@ -1003,7 +1006,8 @@ i830_dispatch_execbuffer(struct intel_ring_buffer *ring,
 
 static int
 i915_dispatch_execbuffer(struct intel_ring_buffer *ring,
-				u32 offset, u32 len)
+			 u32 offset, u32 len,
+			 unsigned flags)
 {
 	int ret;
 
@@ -1012,7 +1016,7 @@ i915_dispatch_execbuffer(struct intel_ring_buffer *ring,
 		return ret;
 
 	intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
-	intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE);
+	intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE));
 	intel_ring_advance(ring);
 
 	return 0;
@@ -1075,6 +1079,29 @@ err:
 	return ret;
 }
 
+static int init_phys_hws_pga(struct intel_ring_buffer *ring)
+{
+	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	u32 addr;
+
+	if (!dev_priv->status_page_dmah) {
+		dev_priv->status_page_dmah =
+			drm_pci_alloc(ring->dev, PAGE_SIZE, PAGE_SIZE);
+		if (!dev_priv->status_page_dmah)
+			return -ENOMEM;
+	}
+
+	addr = dev_priv->status_page_dmah->busaddr;
+	if (INTEL_INFO(ring->dev)->gen >= 4)
+		addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0;
+	I915_WRITE(HWS_PGA, addr);
+
+	ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
+	memset(ring->status_page.page_addr, 0, PAGE_SIZE);
+
+	return 0;
+}
+
 static int intel_init_ring_buffer(struct drm_device *dev,
 				  struct intel_ring_buffer *ring)
 {
@@ -1093,6 +1120,11 @@ static int intel_init_ring_buffer(struct drm_device *dev,
 		ret = init_status_page(ring);
 		if (ret)
 			return ret;
+	} else {
+		BUG_ON(ring->id != RCS);
+		ret = init_phys_hws_pga(ring);
+		if (ret)
+			return ret;
 	}
 
 	obj = i915_gem_alloc_object(dev, ring->size);
@@ -1391,10 +1423,17 @@ static int gen6_ring_flush(struct intel_ring_buffer *ring,
 		return ret;
 
 	cmd = MI_FLUSH_DW;
+	/*
+	 * Bspec vol 1c.5 - video engine command streamer:
+	 * "If ENABLED, all TLBs will be invalidated once the flush
+	 * operation is complete. This bit is only valid when the
+	 * Post-Sync Operation field is a value of 1h or 3h."
+	 */
 	if (invalidate & I915_GEM_GPU_DOMAINS)
-		cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD;
+		cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD |
+			MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW;
 	intel_ring_emit(ring, cmd);
-	intel_ring_emit(ring, 0);
+	intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
 	intel_ring_emit(ring, 0);
 	intel_ring_emit(ring, MI_NOOP);
 	intel_ring_advance(ring);
@@ -1402,8 +1441,30 @@ static int gen6_ring_flush(struct intel_ring_buffer *ring,
 }
 
 static int
+hsw_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
+			      u32 offset, u32 len,
+			      unsigned flags)
+{
+	int ret;
+
+	ret = intel_ring_begin(ring, 2);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(ring,
+			MI_BATCH_BUFFER_START | MI_BATCH_PPGTT_HSW |
+			(flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_HSW));
+	/* bit0-7 is the length on GEN6+ */
+	intel_ring_emit(ring, offset);
+	intel_ring_advance(ring);
+
+	return 0;
+}
+
+static int
 gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
-			      u32 offset, u32 len)
+			      u32 offset, u32 len,
+			      unsigned flags)
 {
 	int ret;
 
@@ -1411,7 +1472,9 @@ gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965);
+	intel_ring_emit(ring,
+			MI_BATCH_BUFFER_START |
+			(flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965));
 	/* bit0-7 is the length on GEN6+ */
 	intel_ring_emit(ring, offset);
 	intel_ring_advance(ring);
@@ -1432,10 +1495,17 @@ static int blt_ring_flush(struct intel_ring_buffer *ring,
 		return ret;
 
 	cmd = MI_FLUSH_DW;
+	/*
+	 * Bspec vol 1c.3 - blitter engine command streamer:
+	 * "If ENABLED, all TLBs will be invalidated once the flush
+	 * operation is complete. This bit is only valid when the
+	 * Post-Sync Operation field is a value of 1h or 3h."
+	 */
 	if (invalidate & I915_GEM_DOMAIN_RENDER)
-		cmd |= MI_INVALIDATE_TLB;
+		cmd |= MI_INVALIDATE_TLB | MI_FLUSH_DW_STORE_INDEX |
+			MI_FLUSH_DW_OP_STOREDW;
 	intel_ring_emit(ring, cmd);
-	intel_ring_emit(ring, 0);
+	intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
 	intel_ring_emit(ring, 0);
 	intel_ring_emit(ring, MI_NOOP);
 	intel_ring_advance(ring);
@@ -1490,7 +1560,9 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
 		ring->irq_enable_mask = I915_USER_INTERRUPT;
 	}
 	ring->write_tail = ring_write_tail;
-	if (INTEL_INFO(dev)->gen >= 6)
+	if (IS_HASWELL(dev))
+		ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer;
+	else if (INTEL_INFO(dev)->gen >= 6)
 		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
 	else if (INTEL_INFO(dev)->gen >= 4)
 		ring->dispatch_execbuffer = i965_dispatch_execbuffer;
@@ -1501,12 +1573,6 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
 	ring->init = init_render_ring;
 	ring->cleanup = render_ring_cleanup;
 
-
-	if (!I915_NEED_GFX_HWS(dev)) {
-		ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
-		memset(ring->status_page.page_addr, 0, PAGE_SIZE);
-	}
-
 	return intel_init_ring_buffer(dev, ring);
 }
 
@@ -1514,6 +1580,7 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
+	int ret;
 
 	ring->name = "render ring";
 	ring->id = RCS;
@@ -1551,16 +1618,13 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)
 	ring->init = init_render_ring;
 	ring->cleanup = render_ring_cleanup;
 
-	if (!I915_NEED_GFX_HWS(dev))
-		ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
-
 	ring->dev = dev;
 	INIT_LIST_HEAD(&ring->active_list);
 	INIT_LIST_HEAD(&ring->request_list);
 
 	ring->size = size;
 	ring->effective_size = ring->size;
-	if (IS_I830(ring->dev))
+	if (IS_I830(ring->dev) || IS_845G(ring->dev))
 		ring->effective_size -= 128;
 
 	ring->virtual_start = ioremap_wc(start, size);
@@ -1570,6 +1634,12 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)
 		return -ENOMEM;
 	}
 
+	if (!I915_NEED_GFX_HWS(dev)) {
+		ret = init_phys_hws_pga(ring);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
@@ -1618,7 +1688,6 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)
 	}
 	ring->init = init_ring_common;
 
-
 	return intel_init_ring_buffer(dev, ring);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 2ea7a31..5af65b8 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -81,7 +81,9 @@ struct  intel_ring_buffer {
 	u32		(*get_seqno)(struct intel_ring_buffer *ring,
 				     bool lazy_coherency);
 	int		(*dispatch_execbuffer)(struct intel_ring_buffer *ring,
-					       u32 offset, u32 length);
+					       u32 offset, u32 length,
+					       unsigned flags);
+#define I915_DISPATCH_SECURE 0x1
 	void		(*cleanup)(struct intel_ring_buffer *ring);
 	int		(*sync_to)(struct intel_ring_buffer *ring,
 				   struct intel_ring_buffer *to,
@@ -181,6 +183,8 @@ intel_read_status_page(struct intel_ring_buffer *ring,
  * The area from dword 0x20 to 0x3ff is available for driver usage.
  */
 #define I915_GEM_HWS_INDEX		0x20
+#define I915_GEM_HWS_SCRATCH_INDEX	0x30
+#define I915_GEM_HWS_SCRATCH_ADDR (I915_GEM_HWS_SCRATCH_INDEX << MI_STORE_DWORD_INDEX_SHIFT)
 
 void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring);
 
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index c600fb0..d6a5fb9 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2072,17 +2072,24 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
 	else
 		mapping = &dev_priv->sdvo_mappings[1];
 
-	pin = GMBUS_PORT_DPB;
-	if (mapping->initialized)
+	if (mapping->initialized && intel_gmbus_is_port_valid(mapping->i2c_pin))
 		pin = mapping->i2c_pin;
+	else
+		pin = GMBUS_PORT_DPB;
 
-	if (intel_gmbus_is_port_valid(pin)) {
-		sdvo->i2c = intel_gmbus_get_adapter(dev_priv, pin);
-		intel_gmbus_set_speed(sdvo->i2c, GMBUS_RATE_1MHZ);
-		intel_gmbus_force_bit(sdvo->i2c, true);
-	} else {
-		sdvo->i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB);
-	}
+	sdvo->i2c = intel_gmbus_get_adapter(dev_priv, pin);
+
+	/* With gmbus we should be able to drive sdvo i2c at 2MHz, but somehow
+	 * our code totally fails once we start using gmbus. Hence fall back to
+	 * bit banging for now. */
+	intel_gmbus_force_bit(sdvo->i2c, true);
+}
+
+/* undo any changes intel_sdvo_select_i2c_bus() did to sdvo->i2c */
+static void
+intel_sdvo_unselect_i2c_bus(struct intel_sdvo *sdvo)
+{
+	intel_gmbus_force_bit(sdvo->i2c, false);
 }
 
 static bool
@@ -2670,10 +2677,8 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
 	intel_sdvo->is_sdvob = is_sdvob;
 	intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, intel_sdvo) >> 1;
 	intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo, sdvo_reg);
-	if (!intel_sdvo_init_ddc_proxy(intel_sdvo, dev)) {
-		kfree(intel_sdvo);
-		return false;
-	}
+	if (!intel_sdvo_init_ddc_proxy(intel_sdvo, dev))
+		goto err_i2c_bus;
 
 	/* encoder type will be decided later */
 	intel_encoder = &intel_sdvo->base;
@@ -2762,6 +2767,8 @@ err_output:
 err:
 	drm_encoder_cleanup(&intel_encoder->base);
 	i2c_del_adapter(&intel_sdvo->ddc);
+err_i2c_bus:
+	intel_sdvo_unselect_i2c_bus(intel_sdvo);
 	kfree(intel_sdvo);
 
 	return false;
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 82f5e5c..827dcd4 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -48,7 +48,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 	struct intel_plane *intel_plane = to_intel_plane(plane);
 	int pipe = intel_plane->pipe;
 	u32 sprctl, sprscale = 0;
-	int pixel_size;
+	unsigned long sprsurf_offset, linear_offset;
+	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 
 	sprctl = I915_READ(SPRCTL(pipe));
 
@@ -61,33 +62,24 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 	switch (fb->pixel_format) {
 	case DRM_FORMAT_XBGR8888:
 		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
-		pixel_size = 4;
 		break;
 	case DRM_FORMAT_XRGB8888:
 		sprctl |= SPRITE_FORMAT_RGBX888;
-		pixel_size = 4;
 		break;
 	case DRM_FORMAT_YUYV:
 		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
-		pixel_size = 2;
 		break;
 	case DRM_FORMAT_YVYU:
 		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
-		pixel_size = 2;
 		break;
 	case DRM_FORMAT_UYVY:
 		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
-		pixel_size = 2;
 		break;
 	case DRM_FORMAT_VYUY:
 		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
-		pixel_size = 2;
 		break;
 	default:
-		DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
-		sprctl |= SPRITE_FORMAT_RGBX888;
-		pixel_size = 4;
-		break;
+		BUG();
 	}
 
 	if (obj->tiling_mode != I915_TILING_NONE)
@@ -127,18 +119,28 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 
 	I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
 	I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
-	if (obj->tiling_mode != I915_TILING_NONE) {
+
+	linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+	sprsurf_offset =
+		intel_gen4_compute_offset_xtiled(&x, &y,
+						 fb->bits_per_pixel / 8,
+						 fb->pitches[0]);
+	linear_offset -= sprsurf_offset;
+
+	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
+	 * register */
+	if (IS_HASWELL(dev))
+		I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
+	else if (obj->tiling_mode != I915_TILING_NONE)
 		I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
-	} else {
-		unsigned long offset;
+	else
+		I915_WRITE(SPRLINOFF(pipe), linear_offset);
 
-		offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
-		I915_WRITE(SPRLINOFF(pipe), offset);
-	}
 	I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
-	I915_WRITE(SPRSCALE(pipe), sprscale);
+	if (intel_plane->can_scale)
+		I915_WRITE(SPRSCALE(pipe), sprscale);
 	I915_WRITE(SPRCTL(pipe), sprctl);
-	I915_MODIFY_DISPBASE(SPRSURF(pipe), obj->gtt_offset);
+	I915_MODIFY_DISPBASE(SPRSURF(pipe), obj->gtt_offset + sprsurf_offset);
 	POSTING_READ(SPRSURF(pipe));
 }
 
@@ -152,7 +154,8 @@ ivb_disable_plane(struct drm_plane *plane)
 
 	I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
 	/* Can't leave the scaler enabled... */
-	I915_WRITE(SPRSCALE(pipe), 0);
+	if (intel_plane->can_scale)
+		I915_WRITE(SPRSCALE(pipe), 0);
 	/* Activate double buffered register update */
 	I915_MODIFY_DISPBASE(SPRSURF(pipe), 0);
 	POSTING_READ(SPRSURF(pipe));
@@ -225,8 +228,10 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
-	int pipe = intel_plane->pipe, pixel_size;
+	int pipe = intel_plane->pipe;
+	unsigned long dvssurf_offset, linear_offset;
 	u32 dvscntr, dvsscale;
+	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 
 	dvscntr = I915_READ(DVSCNTR(pipe));
 
@@ -239,33 +244,24 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 	switch (fb->pixel_format) {
 	case DRM_FORMAT_XBGR8888:
 		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
-		pixel_size = 4;
 		break;
 	case DRM_FORMAT_XRGB8888:
 		dvscntr |= DVS_FORMAT_RGBX888;
-		pixel_size = 4;
 		break;
 	case DRM_FORMAT_YUYV:
 		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
-		pixel_size = 2;
 		break;
 	case DRM_FORMAT_YVYU:
 		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
-		pixel_size = 2;
 		break;
 	case DRM_FORMAT_UYVY:
 		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
-		pixel_size = 2;
 		break;
 	case DRM_FORMAT_VYUY:
 		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
-		pixel_size = 2;
 		break;
 	default:
-		DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
-		dvscntr |= DVS_FORMAT_RGBX888;
-		pixel_size = 4;
-		break;
+		BUG();
 	}
 
 	if (obj->tiling_mode != I915_TILING_NONE)
@@ -289,18 +285,23 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 
 	I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
 	I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
-	if (obj->tiling_mode != I915_TILING_NONE) {
+
+	linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+	dvssurf_offset =
+		intel_gen4_compute_offset_xtiled(&x, &y,
+						 fb->bits_per_pixel / 8,
+						 fb->pitches[0]);
+	linear_offset -= dvssurf_offset;
+
+	if (obj->tiling_mode != I915_TILING_NONE)
 		I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
-	} else {
-		unsigned long offset;
+	else
+		I915_WRITE(DVSLINOFF(pipe), linear_offset);
 
-		offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
-		I915_WRITE(DVSLINOFF(pipe), offset);
-	}
 	I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
 	I915_WRITE(DVSSCALE(pipe), dvsscale);
 	I915_WRITE(DVSCNTR(pipe), dvscntr);
-	I915_MODIFY_DISPBASE(DVSSURF(pipe), obj->gtt_offset);
+	I915_MODIFY_DISPBASE(DVSSURF(pipe), obj->gtt_offset + dvssurf_offset);
 	POSTING_READ(DVSSURF(pipe));
 }
 
@@ -422,6 +423,8 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	struct intel_framebuffer *intel_fb;
 	struct drm_i915_gem_object *obj, *old_obj;
 	int pipe = intel_plane->pipe;
+	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
+								      pipe);
 	int ret = 0;
 	int x = src_x >> 16, y = src_y >> 16;
 	int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay;
@@ -436,7 +439,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	src_h = src_h >> 16;
 
 	/* Pipe must be running... */
-	if (!(I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE))
+	if (!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE))
 		return -EINVAL;
 
 	if (crtc_x >= primary_w || crtc_y >= primary_h)
@@ -446,6 +449,15 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	if (intel_plane->pipe != intel_crtc->pipe)
 		return -EINVAL;
 
+	/* Sprite planes can be linear or x-tiled surfaces */
+	switch (obj->tiling_mode) {
+		case I915_TILING_NONE:
+		case I915_TILING_X:
+			break;
+		default:
+			return -EINVAL;
+	}
+
 	/*
 	 * Clamp the width & height into the visible area.  Note we don't
 	 * try to scale the source if part of the visible region is offscreen.
@@ -473,6 +485,12 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		goto out;
 
 	/*
+	 * We may not have a scaler, eg. HSW does not have it any more
+	 */
+	if (!intel_plane->can_scale && (crtc_w != src_w || crtc_h != src_h))
+		return -EINVAL;
+
+	/*
 	 * We can take a larger source and scale it down, but
 	 * only so much...  16x is the max on SNB.
 	 */
@@ -665,6 +683,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe)
 	switch (INTEL_INFO(dev)->gen) {
 	case 5:
 	case 6:
+		intel_plane->can_scale = true;
 		intel_plane->max_downscale = 16;
 		intel_plane->update_plane = ilk_update_plane;
 		intel_plane->disable_plane = ilk_disable_plane;
@@ -681,6 +700,10 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe)
 		break;
 
 	case 7:
+		if (IS_HASWELL(dev) || IS_VALLEYVIEW(dev))
+			intel_plane->can_scale = false;
+		else
+			intel_plane->can_scale = true;
 		intel_plane->max_downscale = 2;
 		intel_plane->update_plane = ivb_update_plane;
 		intel_plane->disable_plane = ivb_disable_plane;
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 62bb048..86d5c20 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1088,13 +1088,11 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		int dspcntr_reg = DSPCNTR(intel_crtc->plane);
 		int pipeconf = I915_READ(pipeconf_reg);
 		int dspcntr = I915_READ(dspcntr_reg);
-		int dspbase_reg = DSPADDR(intel_crtc->plane);
 		int xpos = 0x0, ypos = 0x0;
 		unsigned int xsize, ysize;
 		/* Pipe must be off here */
 		I915_WRITE(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE);
-		/* Flush the plane changes */
-		I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
+		intel_flush_display_plane(dev_priv, intel_crtc->plane);
 
 		/* Wait for vblank for the disable to take effect */
 		if (IS_GEN2(dev))
@@ -1123,8 +1121,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 
 		I915_WRITE(pipeconf_reg, pipeconf);
 		I915_WRITE(dspcntr_reg, dspcntr);
-		/* Flush the plane changes */
-		I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
+		intel_flush_display_plane(dev_priv, intel_crtc->plane);
 	}
 
 	j = 0;
diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c
index d6a1aae..70dd3c5 100644
--- a/drivers/gpu/drm/mgag200/mgag200_main.c
+++ b/drivers/gpu/drm/mgag200/mgag200_main.c
@@ -133,6 +133,8 @@ static int mga_vram_init(struct mga_device *mdev)
 {
 	void __iomem *mem;
 	struct apertures_struct *aper = alloc_apertures(1);
+	if (!aper)
+		return -ENOMEM;
 
 	/* BAR 0 is VRAM */
 	mdev->mc.vram_base = pci_resource_start(mdev->dev->pdev, 0);
@@ -140,9 +142,9 @@ static int mga_vram_init(struct mga_device *mdev)
 
 	aper->ranges[0].base = mdev->mc.vram_base;
 	aper->ranges[0].size = mdev->mc.vram_window;
-	aper->count = 1;
 
 	remove_conflicting_framebuffers(aper, "mgafb", true);
+	kfree(aper);
 
 	if (!request_mem_region(mdev->mc.vram_base, mdev->mc.vram_window,
 				"mgadrmfb_vram")) {
diff --git a/drivers/gpu/drm/mgag200/mgag200_ttm.c b/drivers/gpu/drm/mgag200/mgag200_ttm.c
index 1504699..49d60a6 100644
--- a/drivers/gpu/drm/mgag200/mgag200_ttm.c
+++ b/drivers/gpu/drm/mgag200/mgag200_ttm.c
@@ -355,7 +355,7 @@ int mgag200_bo_create(struct drm_device *dev, int size, int align,
 
 	ret = ttm_bo_init(&mdev->ttm.bdev, &mgabo->bo, size,
 			  ttm_bo_type_device, &mgabo->placement,
-			  align >> PAGE_SHIFT, 0, false, NULL, acc_size,
+			  align >> PAGE_SHIFT, false, NULL, acc_size,
 			  NULL, mgag200_bo_ttm_destroy);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 35ac57f..4c950b4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -225,7 +225,7 @@ nouveau_bo_new(struct drm_device *dev, int size, int align,
 
 	ret = ttm_bo_init(&drm->ttm.bdev, &nvbo->bo, size,
 			  type, &nvbo->placement,
-			  align >> PAGE_SHIFT, 0, false, NULL, acc_size, sg,
+			  align >> PAGE_SHIFT, false, NULL, acc_size, sg,
 			  nouveau_bo_del_ttm);
 	if (ret) {
 		/* ttm will call nouveau_bo_del_ttm if it fails.. */
@@ -566,7 +566,7 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
 	if (ret)
 		return ret;
 
-	ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, evict,
+	ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, evict,
 					no_wait_reserve, no_wait_gpu, new_mem);
 	nouveau_fence_unref(&fence);
 	return ret;
@@ -1472,19 +1472,19 @@ nouveau_bo_fence_ref(void *sync_obj)
 }
 
 static bool
-nouveau_bo_fence_signalled(void *sync_obj, void *sync_arg)
+nouveau_bo_fence_signalled(void *sync_obj)
 {
 	return nouveau_fence_done(sync_obj);
 }
 
 static int
-nouveau_bo_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr)
+nouveau_bo_fence_wait(void *sync_obj, bool lazy, bool intr)
 {
 	return nouveau_fence_wait(sync_obj, lazy, intr);
 }
 
 static int
-nouveau_bo_fence_flush(void *sync_obj, void *sync_arg)
+nouveau_bo_fence_flush(void *sync_obj)
 {
 	return 0;
 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 8503b2e..2dd555b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -224,6 +224,7 @@ nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent)
 	boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
 #endif
 	remove_conflicting_framebuffers(aper, "nouveaufb", boot);
+	kfree(aper);
 
 	ret = nouveau_device_create(pdev, nouveau_name(pdev), pci_name(pdev),
 				    nouveau_config, nouveau_debug, &device);
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index d5699fe..064023b 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -34,8 +34,7 @@
 
 /* move these to drm_dp_helper.c/h */
 #define DP_LINK_CONFIGURATION_SIZE 9
-#define DP_LINK_STATUS_SIZE	   6
-#define DP_DPCD_SIZE	           8
+#define DP_DPCD_SIZE DP_RECEIVER_CAP_SIZE
 
 static char *voltage_names[] = {
         "0.4V", "0.6V", "0.8V", "1.2V"
@@ -290,78 +289,6 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 
 /***** general DP utility functions *****/
 
-static u8 dp_link_status(u8 link_status[DP_LINK_STATUS_SIZE], int r)
-{
-	return link_status[r - DP_LANE0_1_STATUS];
-}
-
-static u8 dp_get_lane_status(u8 link_status[DP_LINK_STATUS_SIZE],
-			     int lane)
-{
-	int i = DP_LANE0_1_STATUS + (lane >> 1);
-	int s = (lane & 1) * 4;
-	u8 l = dp_link_status(link_status, i);
-	return (l >> s) & 0xf;
-}
-
-static bool dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE],
-				 int lane_count)
-{
-	int lane;
-	u8 lane_status;
-
-	for (lane = 0; lane < lane_count; lane++) {
-		lane_status = dp_get_lane_status(link_status, lane);
-		if ((lane_status & DP_LANE_CR_DONE) == 0)
-			return false;
-	}
-	return true;
-}
-
-static bool dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE],
-			     int lane_count)
-{
-	u8 lane_align;
-	u8 lane_status;
-	int lane;
-
-	lane_align = dp_link_status(link_status,
-				    DP_LANE_ALIGN_STATUS_UPDATED);
-	if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
-		return false;
-	for (lane = 0; lane < lane_count; lane++) {
-		lane_status = dp_get_lane_status(link_status, lane);
-		if ((lane_status & DP_CHANNEL_EQ_BITS) != DP_CHANNEL_EQ_BITS)
-			return false;
-	}
-	return true;
-}
-
-static u8 dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE],
-					int lane)
-
-{
-	int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
-	int s = ((lane & 1) ?
-		 DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
-		 DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
-	u8 l = dp_link_status(link_status, i);
-
-	return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
-}
-
-static u8 dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE],
-					     int lane)
-{
-	int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
-	int s = ((lane & 1) ?
-		 DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
-		 DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
-	u8 l = dp_link_status(link_status, i);
-
-	return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
-}
-
 #define DP_VOLTAGE_MAX         DP_TRAIN_VOLTAGE_SWING_1200
 #define DP_PRE_EMPHASIS_MAX    DP_TRAIN_PRE_EMPHASIS_9_5
 
@@ -374,8 +301,8 @@ static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE],
 	int lane;
 
 	for (lane = 0; lane < lane_count; lane++) {
-		u8 this_v = dp_get_adjust_request_voltage(link_status, lane);
-		u8 this_p = dp_get_adjust_request_pre_emphasis(link_status, lane);
+		u8 this_v = drm_dp_get_adjust_request_voltage(link_status, lane);
+		u8 this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
 
 		DRM_DEBUG_KMS("requested signal parameters: lane %d voltage %s pre_emph %s\n",
 			  lane,
@@ -420,37 +347,6 @@ static int dp_get_max_dp_pix_clock(int link_rate,
 	return (link_rate * lane_num * 8) / bpp;
 }
 
-static int dp_get_max_link_rate(u8 dpcd[DP_DPCD_SIZE])
-{
-	switch (dpcd[DP_MAX_LINK_RATE]) {
-	case DP_LINK_BW_1_62:
-	default:
-		return 162000;
-	case DP_LINK_BW_2_7:
-		return 270000;
-	case DP_LINK_BW_5_4:
-		return 540000;
-	}
-}
-
-static u8 dp_get_max_lane_number(u8 dpcd[DP_DPCD_SIZE])
-{
-	return dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;
-}
-
-static u8 dp_get_dp_link_rate_coded(int link_rate)
-{
-	switch (link_rate) {
-	case 162000:
-	default:
-		return DP_LINK_BW_1_62;
-	case 270000:
-		return DP_LINK_BW_2_7;
-	case 540000:
-		return DP_LINK_BW_5_4;
-	}
-}
-
 /***** radeon specific DP functions *****/
 
 /* First get the min lane# when low rate is used according to pixel clock
@@ -462,8 +358,8 @@ static int radeon_dp_get_dp_lane_number(struct drm_connector *connector,
 					int pix_clock)
 {
 	int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector));
-	int max_link_rate = dp_get_max_link_rate(dpcd);
-	int max_lane_num = dp_get_max_lane_number(dpcd);
+	int max_link_rate = drm_dp_max_link_rate(dpcd);
+	int max_lane_num = drm_dp_max_lane_count(dpcd);
 	int lane_num;
 	int max_dp_pix_clock;
 
@@ -500,7 +396,7 @@ static int radeon_dp_get_dp_link_clock(struct drm_connector *connector,
 			return 540000;
 	}
 
-	return dp_get_max_link_rate(dpcd);
+	return drm_dp_max_link_rate(dpcd);
 }
 
 static u8 radeon_dp_encoder_service(struct radeon_device *rdev,
@@ -551,14 +447,15 @@ static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector)
 bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector)
 {
 	struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
-	u8 msg[25];
+	u8 msg[DP_DPCD_SIZE];
 	int ret, i;
 
-	ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, msg, 8, 0);
+	ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, msg,
+					DP_DPCD_SIZE, 0);
 	if (ret > 0) {
-		memcpy(dig_connector->dpcd, msg, 8);
+		memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE);
 		DRM_DEBUG_KMS("DPCD: ");
-		for (i = 0; i < 8; i++)
+		for (i = 0; i < DP_DPCD_SIZE; i++)
 			DRM_DEBUG_KMS("%02x ", msg[i]);
 		DRM_DEBUG_KMS("\n");
 
@@ -664,7 +561,7 @@ bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector)
 
 	if (!radeon_dp_get_link_status(radeon_connector, link_status))
 		return false;
-	if (dp_channel_eq_ok(link_status, dig->dp_lane_count))
+	if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count))
 		return false;
 	return true;
 }
@@ -677,9 +574,8 @@ struct radeon_dp_link_train_info {
 	int enc_id;
 	int dp_clock;
 	int dp_lane_count;
-	int rd_interval;
 	bool tp3_supported;
-	u8 dpcd[8];
+	u8 dpcd[DP_RECEIVER_CAP_SIZE];
 	u8 train_set[4];
 	u8 link_status[DP_LINK_STATUS_SIZE];
 	u8 tries;
@@ -765,7 +661,7 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
 	radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp);
 
 	/* set the link rate on the sink */
-	tmp = dp_get_dp_link_rate_coded(dp_info->dp_clock);
+	tmp = drm_dp_link_rate_to_bw_code(dp_info->dp_clock);
 	radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp);
 
 	/* start training on the source */
@@ -821,17 +717,14 @@ static int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info)
 	dp_info->tries = 0;
 	voltage = 0xff;
 	while (1) {
-		if (dp_info->rd_interval == 0)
-			udelay(100);
-		else
-			mdelay(dp_info->rd_interval * 4);
+		drm_dp_link_train_clock_recovery_delay(dp_info->dpcd);
 
 		if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) {
 			DRM_ERROR("displayport link status failed\n");
 			break;
 		}
 
-		if (dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) {
+		if (drm_dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) {
 			clock_recovery = true;
 			break;
 		}
@@ -886,17 +779,14 @@ static int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info)
 	dp_info->tries = 0;
 	channel_eq = false;
 	while (1) {
-		if (dp_info->rd_interval == 0)
-			udelay(400);
-		else
-			mdelay(dp_info->rd_interval * 4);
+		drm_dp_link_train_channel_eq_delay(dp_info->dpcd);
 
 		if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) {
 			DRM_ERROR("displayport link status failed\n");
 			break;
 		}
 
-		if (dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) {
+		if (drm_dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) {
 			channel_eq = true;
 			break;
 		}
@@ -974,14 +864,13 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
 	else
 		dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A;
 
-	dp_info.rd_interval = radeon_read_dpcd_reg(radeon_connector, DP_TRAINING_AUX_RD_INTERVAL);
 	tmp = radeon_read_dpcd_reg(radeon_connector, DP_MAX_LANE_COUNT);
 	if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED))
 		dp_info.tp3_supported = true;
 	else
 		dp_info.tp3_supported = false;
 
-	memcpy(dp_info.dpcd, dig_connector->dpcd, 8);
+	memcpy(dp_info.dpcd, dig_connector->dpcd, DP_RECEIVER_CAP_SIZE);
 	dp_info.rdev = rdev;
 	dp_info.encoder = encoder;
 	dp_info.connector = connector;
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 219942c..5d1d21a 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1650,7 +1650,7 @@ static int evergreen_cp_resume(struct radeon_device *rdev)
 	ring->wptr = 0;
 	WREG32(CP_RB_WPTR, ring->wptr);
 
-	/* set the wb address wether it's enabled or not */
+	/* set the wb address whether it's enabled or not */
 	WREG32(CP_RB_RPTR_ADDR,
 	       ((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC));
 	WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 81e6a56..cda01f8 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1059,7 +1059,7 @@ static int cayman_cp_resume(struct radeon_device *rdev)
 
 	WREG32(CP_DEBUG, (1 << 27));
 
-	/* set the wb address wether it's enabled or not */
+	/* set the wb address whether it's enabled or not */
 	WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
 	WREG32(SCRATCH_UMSK, 0xff);
 
@@ -1076,7 +1076,7 @@ static int cayman_cp_resume(struct radeon_device *rdev)
 #endif
 		WREG32(cp_rb_cntl[i], rb_cntl);
 
-		/* set the wb address wether it's enabled or not */
+		/* set the wb address whether it's enabled or not */
 		addr = rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET;
 		WREG32(cp_rb_rptr_addr[i], addr & 0xFFFFFFFC);
 		WREG32(cp_rb_rptr_addr_hi[i], upper_32_bits(addr) & 0xFF);
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index cda280d..169ecc9 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -1424,13 +1424,7 @@ u32 r6xx_remap_render_backend(struct radeon_device *rdev,
 
 int r600_count_pipe_bits(uint32_t val)
 {
-	int i, ret = 0;
-
-	for (i = 0; i < 32; i++) {
-		ret += val & 1;
-		val >>= 1;
-	}
-	return ret;
+	return hweight32(val);
 }
 
 static void r600_gpu_init(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c
index 2514123..be85f75 100644
--- a/drivers/gpu/drm/radeon/r600_cp.c
+++ b/drivers/gpu/drm/radeon/r600_cp.c
@@ -721,12 +721,7 @@ static u32 r600_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
 
 static int r600_count_pipe_bits(uint32_t val)
 {
-	int i, ret = 0;
-	for (i = 0; i < 32; i++) {
-		ret += val & 1;
-		val >>= 1;
-	}
-	return ret;
+	return hweight32(val);
 }
 
 static void r600_gfx_init(struct drm_device *dev,
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 07eb84e..8c1a83c 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -281,12 +281,15 @@ static struct drm_driver driver_old = {
 
 static struct drm_driver kms_driver;
 
-static void radeon_kick_out_firmware_fb(struct pci_dev *pdev)
+static int radeon_kick_out_firmware_fb(struct pci_dev *pdev)
 {
 	struct apertures_struct *ap;
 	bool primary = false;
 
 	ap = alloc_apertures(1);
+	if (!ap)
+		return -ENOMEM;
+
 	ap->ranges[0].base = pci_resource_start(pdev, 0);
 	ap->ranges[0].size = pci_resource_len(pdev, 0);
 
@@ -295,13 +298,19 @@ static void radeon_kick_out_firmware_fb(struct pci_dev *pdev)
 #endif
 	remove_conflicting_framebuffers(ap, "radeondrmfb", primary);
 	kfree(ap);
+
+	return 0;
 }
 
 static int __devinit
 radeon_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
+	int ret;
+
 	/* Get rid of things like offb */
-	radeon_kick_out_firmware_fb(pdev);
+	ret = radeon_kick_out_firmware_fb(pdev);
+	if (ret)
+		return ret;
 
 	return drm_get_pci_dev(pdev, ent, &kms_driver);
 }
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
index 4debd60..8690be7 100644
--- a/drivers/gpu/drm/radeon/radeon_gart.c
+++ b/drivers/gpu/drm/radeon/radeon_gart.c
@@ -1237,7 +1237,7 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev,
 {
 	struct radeon_bo_va *bo_va;
 
-	BUG_ON(!atomic_read(&bo->tbo.reserved));
+	BUG_ON(!radeon_bo_is_reserved(bo));
 	list_for_each_entry(bo_va, &bo->va, bo_list) {
 		bo_va->valid = false;
 	}
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 92c5f47..d818b50 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -427,7 +427,7 @@ struct radeon_connector_atom_dig {
 	uint32_t igp_lane_info;
 	/* displayport */
 	struct radeon_i2c_chan *dp_i2c_bus;
-	u8 dpcd[8];
+	u8 dpcd[DP_RECEIVER_CAP_SIZE];
 	u8 dp_sink_type;
 	int dp_clock;
 	int dp_lane_count;
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index b91118c..7c4b4bb 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -140,7 +140,7 @@ int radeon_bo_create(struct radeon_device *rdev,
 	/* Kernel allocation are uninterruptible */
 	down_read(&rdev->pm.mclk_lock);
 	r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type,
-			&bo->placement, page_align, 0, !kernel, NULL,
+			&bo->placement, page_align, !kernel, NULL,
 			acc_size, sg, &radeon_ttm_bo_destroy);
 	up_read(&rdev->pm.mclk_lock);
 	if (unlikely(r != 0)) {
@@ -384,7 +384,7 @@ int radeon_bo_get_surface_reg(struct radeon_bo *bo)
 	int steal;
 	int i;
 
-	BUG_ON(!atomic_read(&bo->tbo.reserved));
+	BUG_ON(!radeon_bo_is_reserved(bo));
 
 	if (!bo->tiling_flags)
 		return 0;
@@ -510,7 +510,7 @@ void radeon_bo_get_tiling_flags(struct radeon_bo *bo,
 				uint32_t *tiling_flags,
 				uint32_t *pitch)
 {
-	BUG_ON(!atomic_read(&bo->tbo.reserved));
+	BUG_ON(!radeon_bo_is_reserved(bo));
 	if (tiling_flags)
 		*tiling_flags = bo->tiling_flags;
 	if (pitch)
@@ -520,7 +520,7 @@ void radeon_bo_get_tiling_flags(struct radeon_bo *bo,
 int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved,
 				bool force_drop)
 {
-	BUG_ON(!atomic_read(&bo->tbo.reserved));
+	BUG_ON(!radeon_bo_is_reserved(bo));
 
 	if (!(bo->tiling_flags & RADEON_TILING_SURFACE))
 		return 0;
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h
index 93cd491..5fc86b0 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -80,7 +80,7 @@ static inline unsigned long radeon_bo_size(struct radeon_bo *bo)
 
 static inline bool radeon_bo_is_reserved(struct radeon_bo *bo)
 {
-	return !!atomic_read(&bo->tbo.reserved);
+	return ttm_bo_is_reserved(&bo->tbo);
 }
 
 static inline unsigned radeon_bo_ngpu_pages(struct radeon_bo *bo)
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 47634f2..ebd6956 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -459,7 +459,7 @@ void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *r
  *
  * @ring: radeon_ring structure holding ring information
  *
- * Reset the driver's copy of the wtpr (all asics).
+ * Reset the driver's copy of the wptr (all asics).
  */
 void radeon_ring_undo(struct radeon_ring *ring)
 {
@@ -503,7 +503,7 @@ void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *
 }
 
 /**
- * radeon_ring_force_activity - update lockup variables
+ * radeon_ring_lockup_update - update lockup variables
  *
  * @ring: radeon_ring structure holding ring information
  *
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 5ebe1b3..563c8ed 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -265,7 +265,7 @@ static int radeon_move_blit(struct ttm_buffer_object *bo,
 			new_mem->num_pages * (PAGE_SIZE / RADEON_GPU_PAGE_SIZE), /* GPU pages */
 			&fence);
 	/* FIXME: handle copy error */
-	r = ttm_bo_move_accel_cleanup(bo, (void *)fence, NULL,
+	r = ttm_bo_move_accel_cleanup(bo, (void *)fence,
 				      evict, no_wait_reserve, no_wait_gpu, new_mem);
 	radeon_fence_unref(&fence);
 	return r;
@@ -471,13 +471,12 @@ static void radeon_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_re
 {
 }
 
-static int radeon_sync_obj_wait(void *sync_obj, void *sync_arg,
-				bool lazy, bool interruptible)
+static int radeon_sync_obj_wait(void *sync_obj, bool lazy, bool interruptible)
 {
 	return radeon_fence_wait((struct radeon_fence *)sync_obj, interruptible);
 }
 
-static int radeon_sync_obj_flush(void *sync_obj, void *sync_arg)
+static int radeon_sync_obj_flush(void *sync_obj)
 {
 	return 0;
 }
@@ -492,7 +491,7 @@ static void *radeon_sync_obj_ref(void *sync_obj)
 	return radeon_fence_ref((struct radeon_fence *)sync_obj);
 }
 
-static bool radeon_sync_obj_signaled(void *sync_obj, void *sync_arg)
+static bool radeon_sync_obj_signaled(void *sync_obj)
 {
 	return radeon_fence_signaled((struct radeon_fence *)sync_obj);
 }
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 4422d63..010156d 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -2007,7 +2007,7 @@ static int si_cp_resume(struct radeon_device *rdev)
 	ring->wptr = 0;
 	WREG32(CP_RB0_WPTR, ring->wptr);
 
-	/* set the wb address wether it's enabled or not */
+	/* set the wb address whether it's enabled or not */
 	WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC);
 	WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
 
@@ -2040,7 +2040,7 @@ static int si_cp_resume(struct radeon_device *rdev)
 	ring->wptr = 0;
 	WREG32(CP_RB1_WPTR, ring->wptr);
 
-	/* set the wb address wether it's enabled or not */
+	/* set the wb address whether it's enabled or not */
 	WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC);
 	WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF);
 
@@ -2066,7 +2066,7 @@ static int si_cp_resume(struct radeon_device *rdev)
 	ring->wptr = 0;
 	WREG32(CP_RB2_WPTR, ring->wptr);
 
-	/* set the wb address wether it's enabled or not */
+	/* set the wb address whether it's enabled or not */
 	WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC);
 	WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF);
 
diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig
new file mode 100644
index 0000000..be1daf7
--- /dev/null
+++ b/drivers/gpu/drm/tegra/Kconfig
@@ -0,0 +1,23 @@
+config DRM_TEGRA
+	tristate "NVIDIA Tegra DRM"
+	depends on DRM && OF && ARCH_TEGRA
+	select DRM_KMS_HELPER
+	select DRM_GEM_CMA_HELPER
+	select DRM_KMS_CMA_HELPER
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  Choose this option if you have an NVIDIA Tegra SoC.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called tegra-drm.
+
+if DRM_TEGRA
+
+config DRM_TEGRA_DEBUG
+	bool "NVIDIA Tegra DRM debug support"
+	help
+	  Say yes here to enable debugging support.
+
+endif
diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile
new file mode 100644
index 0000000..80f73d1
--- /dev/null
+++ b/drivers/gpu/drm/tegra/Makefile
@@ -0,0 +1,7 @@
+ccflags-y := -Iinclude/drm
+ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG
+
+tegra-drm-y := drm.o fb.o dc.o host1x.o
+tegra-drm-y += output.o rgb.o hdmi.o
+
+obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
new file mode 100644
index 0000000..0744103
--- /dev/null
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -0,0 +1,834 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include <mach/clk.h>
+
+#include "drm.h"
+#include "dc.h"
+
+struct tegra_dc_window {
+	fixed20_12 x;
+	fixed20_12 y;
+	fixed20_12 w;
+	fixed20_12 h;
+	unsigned int outx;
+	unsigned int outy;
+	unsigned int outw;
+	unsigned int outh;
+	unsigned int stride;
+	unsigned int fmt;
+};
+
+static const struct drm_crtc_funcs tegra_crtc_funcs = {
+	.set_config = drm_crtc_helper_set_config,
+	.destroy = drm_crtc_cleanup,
+};
+
+static void tegra_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+}
+
+static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
+				  const struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted)
+{
+	return true;
+}
+
+static inline u32 compute_dda_inc(fixed20_12 inf, unsigned int out, bool v,
+				  unsigned int bpp)
+{
+	fixed20_12 outf = dfixed_init(out);
+	u32 dda_inc;
+	int max;
+
+	if (v)
+		max = 15;
+	else {
+		switch (bpp) {
+		case 2:
+			max = 8;
+			break;
+
+		default:
+			WARN_ON_ONCE(1);
+			/* fallthrough */
+		case 4:
+			max = 4;
+			break;
+		}
+	}
+
+	outf.full = max_t(u32, outf.full - dfixed_const(1), dfixed_const(1));
+	inf.full -= dfixed_const(1);
+
+	dda_inc = dfixed_div(inf, outf);
+	dda_inc = min_t(u32, dda_inc, dfixed_const(max));
+
+	return dda_inc;
+}
+
+static inline u32 compute_initial_dda(fixed20_12 in)
+{
+	return dfixed_frac(in);
+}
+
+static int tegra_dc_set_timings(struct tegra_dc *dc,
+				struct drm_display_mode *mode)
+{
+	/* TODO: For HDMI compliance, h & v ref_to_sync should be set to 1 */
+	unsigned int h_ref_to_sync = 0;
+	unsigned int v_ref_to_sync = 0;
+	unsigned long value;
+
+	tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
+
+	value = (v_ref_to_sync << 16) | h_ref_to_sync;
+	tegra_dc_writel(dc, value, DC_DISP_REF_TO_SYNC);
+
+	value = ((mode->vsync_end - mode->vsync_start) << 16) |
+		((mode->hsync_end - mode->hsync_start) <<  0);
+	tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH);
+
+	value = ((mode->vsync_start - mode->vdisplay) << 16) |
+		((mode->hsync_start - mode->hdisplay) <<  0);
+	tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH);
+
+	value = ((mode->vtotal - mode->vsync_end) << 16) |
+		((mode->htotal - mode->hsync_end) <<  0);
+	tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH);
+
+	value = (mode->vdisplay << 16) | mode->hdisplay;
+	tegra_dc_writel(dc, value, DC_DISP_ACTIVE);
+
+	return 0;
+}
+
+static int tegra_crtc_setup_clk(struct drm_crtc *crtc,
+				struct drm_display_mode *mode,
+				unsigned long *div)
+{
+	unsigned long pclk = mode->clock * 1000, rate;
+	struct tegra_dc *dc = to_tegra_dc(crtc);
+	struct tegra_output *output = NULL;
+	struct drm_encoder *encoder;
+	long err;
+
+	list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list, head)
+		if (encoder->crtc == crtc) {
+			output = encoder_to_output(encoder);
+			break;
+		}
+
+	if (!output)
+		return -ENODEV;
+
+	/*
+	 * This assumes that the display controller will divide its parent
+	 * clock by 2 to generate the pixel clock.
+	 */
+	err = tegra_output_setup_clock(output, dc->clk, pclk * 2);
+	if (err < 0) {
+		dev_err(dc->dev, "failed to setup clock: %ld\n", err);
+		return err;
+	}
+
+	rate = clk_get_rate(dc->clk);
+	*div = (rate * 2 / pclk) - 2;
+
+	DRM_DEBUG_KMS("rate: %lu, div: %lu\n", rate, *div);
+
+	return 0;
+}
+
+static int tegra_crtc_mode_set(struct drm_crtc *crtc,
+			       struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted,
+			       int x, int y, struct drm_framebuffer *old_fb)
+{
+	struct tegra_framebuffer *fb = to_tegra_fb(crtc->fb);
+	struct tegra_dc *dc = to_tegra_dc(crtc);
+	unsigned int h_dda, v_dda, bpp;
+	struct tegra_dc_window win;
+	unsigned long div, value;
+	int err;
+
+	err = tegra_crtc_setup_clk(crtc, mode, &div);
+	if (err) {
+		dev_err(dc->dev, "failed to setup clock for CRTC: %d\n", err);
+		return err;
+	}
+
+	/* program display mode */
+	tegra_dc_set_timings(dc, mode);
+
+	value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL;
+	tegra_dc_writel(dc, value, DC_DISP_DATA_ENABLE_OPTIONS);
+
+	value = tegra_dc_readl(dc, DC_COM_PIN_OUTPUT_POLARITY(1));
+	value &= ~LVS_OUTPUT_POLARITY_LOW;
+	value &= ~LHS_OUTPUT_POLARITY_LOW;
+	tegra_dc_writel(dc, value, DC_COM_PIN_OUTPUT_POLARITY(1));
+
+	value = DISP_DATA_FORMAT_DF1P1C | DISP_ALIGNMENT_MSB |
+		DISP_ORDER_RED_BLUE;
+	tegra_dc_writel(dc, value, DC_DISP_DISP_INTERFACE_CONTROL);
+
+	tegra_dc_writel(dc, 0x00010001, DC_DISP_SHIFT_CLOCK_OPTIONS);
+
+	value = SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER_PCD1;
+	tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
+
+	/* setup window parameters */
+	memset(&win, 0, sizeof(win));
+	win.x.full = dfixed_const(0);
+	win.y.full = dfixed_const(0);
+	win.w.full = dfixed_const(mode->hdisplay);
+	win.h.full = dfixed_const(mode->vdisplay);
+	win.outx = 0;
+	win.outy = 0;
+	win.outw = mode->hdisplay;
+	win.outh = mode->vdisplay;
+
+	switch (crtc->fb->pixel_format) {
+	case DRM_FORMAT_XRGB8888:
+		win.fmt = WIN_COLOR_DEPTH_B8G8R8A8;
+		break;
+
+	case DRM_FORMAT_RGB565:
+		win.fmt = WIN_COLOR_DEPTH_B5G6R5;
+		break;
+
+	default:
+		win.fmt = WIN_COLOR_DEPTH_B8G8R8A8;
+		WARN_ON(1);
+		break;
+	}
+
+	bpp = crtc->fb->bits_per_pixel / 8;
+	win.stride = crtc->fb->pitches[0];
+
+	/* program window registers */
+	value = tegra_dc_readl(dc, DC_CMD_DISPLAY_WINDOW_HEADER);
+	value |= WINDOW_A_SELECT;
+	tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
+
+	tegra_dc_writel(dc, win.fmt, DC_WIN_COLOR_DEPTH);
+	tegra_dc_writel(dc, 0, DC_WIN_BYTE_SWAP);
+
+	value = V_POSITION(win.outy) | H_POSITION(win.outx);
+	tegra_dc_writel(dc, value, DC_WIN_POSITION);
+
+	value = V_SIZE(win.outh) | H_SIZE(win.outw);
+	tegra_dc_writel(dc, value, DC_WIN_SIZE);
+
+	value = V_PRESCALED_SIZE(dfixed_trunc(win.h)) |
+		H_PRESCALED_SIZE(dfixed_trunc(win.w) * bpp);
+	tegra_dc_writel(dc, value, DC_WIN_PRESCALED_SIZE);
+
+	h_dda = compute_dda_inc(win.w, win.outw, false, bpp);
+	v_dda = compute_dda_inc(win.h, win.outh, true, bpp);
+
+	value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda);
+	tegra_dc_writel(dc, value, DC_WIN_DDA_INC);
+
+	h_dda = compute_initial_dda(win.x);
+	v_dda = compute_initial_dda(win.y);
+
+	tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
+	tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
+
+	tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
+	tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
+
+	tegra_dc_writel(dc, fb->obj->paddr, DC_WINBUF_START_ADDR);
+	tegra_dc_writel(dc, win.stride, DC_WIN_LINE_STRIDE);
+	tegra_dc_writel(dc, dfixed_trunc(win.x) * bpp,
+			DC_WINBUF_ADDR_H_OFFSET);
+	tegra_dc_writel(dc, dfixed_trunc(win.y), DC_WINBUF_ADDR_V_OFFSET);
+
+	value = WIN_ENABLE;
+
+	if (bpp < 24)
+		value |= COLOR_EXPAND;
+
+	tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
+
+	tegra_dc_writel(dc, 0xff00, DC_WIN_BLEND_NOKEY);
+	tegra_dc_writel(dc, 0xff00, DC_WIN_BLEND_1WIN);
+
+	return 0;
+}
+
+static void tegra_crtc_prepare(struct drm_crtc *crtc)
+{
+	struct tegra_dc *dc = to_tegra_dc(crtc);
+	unsigned int syncpt;
+	unsigned long value;
+
+	/* hardware initialization */
+	tegra_periph_reset_deassert(dc->clk);
+	usleep_range(10000, 20000);
+
+	if (dc->pipe)
+		syncpt = SYNCPT_VBLANK1;
+	else
+		syncpt = SYNCPT_VBLANK0;
+
+	/* initialize display controller */
+	tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
+	tegra_dc_writel(dc, 0x100 | syncpt, DC_CMD_CONT_SYNCPT_VSYNC);
+
+	value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | WIN_A_OF_INT;
+	tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
+
+	value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
+		WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
+	tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
+
+	value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
+		PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
+	tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
+
+	value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
+	value |= DISP_CTRL_MODE_C_DISPLAY;
+	tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
+
+	/* initialize timer */
+	value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
+		WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
+	tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY);
+
+	value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(1) |
+		WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1);
+	tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
+
+	value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
+	tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
+
+	value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
+	tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
+}
+
+static void tegra_crtc_commit(struct drm_crtc *crtc)
+{
+	struct tegra_dc *dc = to_tegra_dc(crtc);
+	unsigned long update_mask;
+	unsigned long value;
+
+	update_mask = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
+
+	tegra_dc_writel(dc, update_mask << 8, DC_CMD_STATE_CONTROL);
+
+	value = tegra_dc_readl(dc, DC_CMD_INT_ENABLE);
+	value |= FRAME_END_INT;
+	tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
+
+	value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
+	value |= FRAME_END_INT;
+	tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
+
+	tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL);
+}
+
+static void tegra_crtc_load_lut(struct drm_crtc *crtc)
+{
+}
+
+static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
+	.dpms = tegra_crtc_dpms,
+	.mode_fixup = tegra_crtc_mode_fixup,
+	.mode_set = tegra_crtc_mode_set,
+	.prepare = tegra_crtc_prepare,
+	.commit = tegra_crtc_commit,
+	.load_lut = tegra_crtc_load_lut,
+};
+
+static irqreturn_t tegra_drm_irq(int irq, void *data)
+{
+	struct tegra_dc *dc = data;
+	unsigned long status;
+
+	status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
+	tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
+
+	if (status & FRAME_END_INT) {
+		/*
+		dev_dbg(dc->dev, "%s(): frame end\n", __func__);
+		*/
+	}
+
+	if (status & VBLANK_INT) {
+		/*
+		dev_dbg(dc->dev, "%s(): vertical blank\n", __func__);
+		*/
+		drm_handle_vblank(dc->base.dev, dc->pipe);
+	}
+
+	if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) {
+		/*
+		dev_dbg(dc->dev, "%s(): underflow\n", __func__);
+		*/
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int tegra_dc_show_regs(struct seq_file *s, void *data)
+{
+	struct drm_info_node *node = s->private;
+	struct tegra_dc *dc = node->info_ent->data;
+
+#define DUMP_REG(name)						\
+	seq_printf(s, "%-40s %#05x %08lx\n", #name, name,	\
+		   tegra_dc_readl(dc, name))
+
+	DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT);
+	DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
+	DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_ERROR);
+	DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT);
+	DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_CNTRL);
+	DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_ERROR);
+	DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT);
+	DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_CNTRL);
+	DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_ERROR);
+	DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT);
+	DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_CNTRL);
+	DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_ERROR);
+	DUMP_REG(DC_CMD_CONT_SYNCPT_VSYNC);
+	DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0);
+	DUMP_REG(DC_CMD_DISPLAY_COMMAND);
+	DUMP_REG(DC_CMD_SIGNAL_RAISE);
+	DUMP_REG(DC_CMD_DISPLAY_POWER_CONTROL);
+	DUMP_REG(DC_CMD_INT_STATUS);
+	DUMP_REG(DC_CMD_INT_MASK);
+	DUMP_REG(DC_CMD_INT_ENABLE);
+	DUMP_REG(DC_CMD_INT_TYPE);
+	DUMP_REG(DC_CMD_INT_POLARITY);
+	DUMP_REG(DC_CMD_SIGNAL_RAISE1);
+	DUMP_REG(DC_CMD_SIGNAL_RAISE2);
+	DUMP_REG(DC_CMD_SIGNAL_RAISE3);
+	DUMP_REG(DC_CMD_STATE_ACCESS);
+	DUMP_REG(DC_CMD_STATE_CONTROL);
+	DUMP_REG(DC_CMD_DISPLAY_WINDOW_HEADER);
+	DUMP_REG(DC_CMD_REG_ACT_CONTROL);
+	DUMP_REG(DC_COM_CRC_CONTROL);
+	DUMP_REG(DC_COM_CRC_CHECKSUM);
+	DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(0));
+	DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(1));
+	DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(2));
+	DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(3));
+	DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(0));
+	DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(1));
+	DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(2));
+	DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(3));
+	DUMP_REG(DC_COM_PIN_OUTPUT_DATA(0));
+	DUMP_REG(DC_COM_PIN_OUTPUT_DATA(1));
+	DUMP_REG(DC_COM_PIN_OUTPUT_DATA(2));
+	DUMP_REG(DC_COM_PIN_OUTPUT_DATA(3));
+	DUMP_REG(DC_COM_PIN_INPUT_ENABLE(0));
+	DUMP_REG(DC_COM_PIN_INPUT_ENABLE(1));
+	DUMP_REG(DC_COM_PIN_INPUT_ENABLE(2));
+	DUMP_REG(DC_COM_PIN_INPUT_ENABLE(3));
+	DUMP_REG(DC_COM_PIN_INPUT_DATA(0));
+	DUMP_REG(DC_COM_PIN_INPUT_DATA(1));
+	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(0));
+	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(1));
+	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(2));
+	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(3));
+	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(4));
+	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(5));
+	DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(6));
+	DUMP_REG(DC_COM_PIN_MISC_CONTROL);
+	DUMP_REG(DC_COM_PIN_PM0_CONTROL);
+	DUMP_REG(DC_COM_PIN_PM0_DUTY_CYCLE);
+	DUMP_REG(DC_COM_PIN_PM1_CONTROL);
+	DUMP_REG(DC_COM_PIN_PM1_DUTY_CYCLE);
+	DUMP_REG(DC_COM_SPI_CONTROL);
+	DUMP_REG(DC_COM_SPI_START_BYTE);
+	DUMP_REG(DC_COM_HSPI_WRITE_DATA_AB);
+	DUMP_REG(DC_COM_HSPI_WRITE_DATA_CD);
+	DUMP_REG(DC_COM_HSPI_CS_DC);
+	DUMP_REG(DC_COM_SCRATCH_REGISTER_A);
+	DUMP_REG(DC_COM_SCRATCH_REGISTER_B);
+	DUMP_REG(DC_COM_GPIO_CTRL);
+	DUMP_REG(DC_COM_GPIO_DEBOUNCE_COUNTER);
+	DUMP_REG(DC_COM_CRC_CHECKSUM_LATCHED);
+	DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS0);
+	DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS1);
+	DUMP_REG(DC_DISP_DISP_WIN_OPTIONS);
+	DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY);
+	DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
+	DUMP_REG(DC_DISP_DISP_TIMING_OPTIONS);
+	DUMP_REG(DC_DISP_REF_TO_SYNC);
+	DUMP_REG(DC_DISP_SYNC_WIDTH);
+	DUMP_REG(DC_DISP_BACK_PORCH);
+	DUMP_REG(DC_DISP_ACTIVE);
+	DUMP_REG(DC_DISP_FRONT_PORCH);
+	DUMP_REG(DC_DISP_H_PULSE0_CONTROL);
+	DUMP_REG(DC_DISP_H_PULSE0_POSITION_A);
+	DUMP_REG(DC_DISP_H_PULSE0_POSITION_B);
+	DUMP_REG(DC_DISP_H_PULSE0_POSITION_C);
+	DUMP_REG(DC_DISP_H_PULSE0_POSITION_D);
+	DUMP_REG(DC_DISP_H_PULSE1_CONTROL);
+	DUMP_REG(DC_DISP_H_PULSE1_POSITION_A);
+	DUMP_REG(DC_DISP_H_PULSE1_POSITION_B);
+	DUMP_REG(DC_DISP_H_PULSE1_POSITION_C);
+	DUMP_REG(DC_DISP_H_PULSE1_POSITION_D);
+	DUMP_REG(DC_DISP_H_PULSE2_CONTROL);
+	DUMP_REG(DC_DISP_H_PULSE2_POSITION_A);
+	DUMP_REG(DC_DISP_H_PULSE2_POSITION_B);
+	DUMP_REG(DC_DISP_H_PULSE2_POSITION_C);
+	DUMP_REG(DC_DISP_H_PULSE2_POSITION_D);
+	DUMP_REG(DC_DISP_V_PULSE0_CONTROL);
+	DUMP_REG(DC_DISP_V_PULSE0_POSITION_A);
+	DUMP_REG(DC_DISP_V_PULSE0_POSITION_B);
+	DUMP_REG(DC_DISP_V_PULSE0_POSITION_C);
+	DUMP_REG(DC_DISP_V_PULSE1_CONTROL);
+	DUMP_REG(DC_DISP_V_PULSE1_POSITION_A);
+	DUMP_REG(DC_DISP_V_PULSE1_POSITION_B);
+	DUMP_REG(DC_DISP_V_PULSE1_POSITION_C);
+	DUMP_REG(DC_DISP_V_PULSE2_CONTROL);
+	DUMP_REG(DC_DISP_V_PULSE2_POSITION_A);
+	DUMP_REG(DC_DISP_V_PULSE3_CONTROL);
+	DUMP_REG(DC_DISP_V_PULSE3_POSITION_A);
+	DUMP_REG(DC_DISP_M0_CONTROL);
+	DUMP_REG(DC_DISP_M1_CONTROL);
+	DUMP_REG(DC_DISP_DI_CONTROL);
+	DUMP_REG(DC_DISP_PP_CONTROL);
+	DUMP_REG(DC_DISP_PP_SELECT_A);
+	DUMP_REG(DC_DISP_PP_SELECT_B);
+	DUMP_REG(DC_DISP_PP_SELECT_C);
+	DUMP_REG(DC_DISP_PP_SELECT_D);
+	DUMP_REG(DC_DISP_DISP_CLOCK_CONTROL);
+	DUMP_REG(DC_DISP_DISP_INTERFACE_CONTROL);
+	DUMP_REG(DC_DISP_DISP_COLOR_CONTROL);
+	DUMP_REG(DC_DISP_SHIFT_CLOCK_OPTIONS);
+	DUMP_REG(DC_DISP_DATA_ENABLE_OPTIONS);
+	DUMP_REG(DC_DISP_SERIAL_INTERFACE_OPTIONS);
+	DUMP_REG(DC_DISP_LCD_SPI_OPTIONS);
+	DUMP_REG(DC_DISP_BORDER_COLOR);
+	DUMP_REG(DC_DISP_COLOR_KEY0_LOWER);
+	DUMP_REG(DC_DISP_COLOR_KEY0_UPPER);
+	DUMP_REG(DC_DISP_COLOR_KEY1_LOWER);
+	DUMP_REG(DC_DISP_COLOR_KEY1_UPPER);
+	DUMP_REG(DC_DISP_CURSOR_FOREGROUND);
+	DUMP_REG(DC_DISP_CURSOR_BACKGROUND);
+	DUMP_REG(DC_DISP_CURSOR_START_ADDR);
+	DUMP_REG(DC_DISP_CURSOR_START_ADDR_NS);
+	DUMP_REG(DC_DISP_CURSOR_POSITION);
+	DUMP_REG(DC_DISP_CURSOR_POSITION_NS);
+	DUMP_REG(DC_DISP_INIT_SEQ_CONTROL);
+	DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_A);
+	DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_B);
+	DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_C);
+	DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_D);
+	DUMP_REG(DC_DISP_DC_MCCIF_FIFOCTRL);
+	DUMP_REG(DC_DISP_MCCIF_DISPLAY0A_HYST);
+	DUMP_REG(DC_DISP_MCCIF_DISPLAY0B_HYST);
+	DUMP_REG(DC_DISP_MCCIF_DISPLAY1A_HYST);
+	DUMP_REG(DC_DISP_MCCIF_DISPLAY1B_HYST);
+	DUMP_REG(DC_DISP_DAC_CRT_CTRL);
+	DUMP_REG(DC_DISP_DISP_MISC_CONTROL);
+	DUMP_REG(DC_DISP_SD_CONTROL);
+	DUMP_REG(DC_DISP_SD_CSC_COEFF);
+	DUMP_REG(DC_DISP_SD_LUT(0));
+	DUMP_REG(DC_DISP_SD_LUT(1));
+	DUMP_REG(DC_DISP_SD_LUT(2));
+	DUMP_REG(DC_DISP_SD_LUT(3));
+	DUMP_REG(DC_DISP_SD_LUT(4));
+	DUMP_REG(DC_DISP_SD_LUT(5));
+	DUMP_REG(DC_DISP_SD_LUT(6));
+	DUMP_REG(DC_DISP_SD_LUT(7));
+	DUMP_REG(DC_DISP_SD_LUT(8));
+	DUMP_REG(DC_DISP_SD_FLICKER_CONTROL);
+	DUMP_REG(DC_DISP_DC_PIXEL_COUNT);
+	DUMP_REG(DC_DISP_SD_HISTOGRAM(0));
+	DUMP_REG(DC_DISP_SD_HISTOGRAM(1));
+	DUMP_REG(DC_DISP_SD_HISTOGRAM(2));
+	DUMP_REG(DC_DISP_SD_HISTOGRAM(3));
+	DUMP_REG(DC_DISP_SD_HISTOGRAM(4));
+	DUMP_REG(DC_DISP_SD_HISTOGRAM(5));
+	DUMP_REG(DC_DISP_SD_HISTOGRAM(6));
+	DUMP_REG(DC_DISP_SD_HISTOGRAM(7));
+	DUMP_REG(DC_DISP_SD_BL_TF(0));
+	DUMP_REG(DC_DISP_SD_BL_TF(1));
+	DUMP_REG(DC_DISP_SD_BL_TF(2));
+	DUMP_REG(DC_DISP_SD_BL_TF(3));
+	DUMP_REG(DC_DISP_SD_BL_CONTROL);
+	DUMP_REG(DC_DISP_SD_HW_K_VALUES);
+	DUMP_REG(DC_DISP_SD_MAN_K_VALUES);
+	DUMP_REG(DC_WIN_WIN_OPTIONS);
+	DUMP_REG(DC_WIN_BYTE_SWAP);
+	DUMP_REG(DC_WIN_BUFFER_CONTROL);
+	DUMP_REG(DC_WIN_COLOR_DEPTH);
+	DUMP_REG(DC_WIN_POSITION);
+	DUMP_REG(DC_WIN_SIZE);
+	DUMP_REG(DC_WIN_PRESCALED_SIZE);
+	DUMP_REG(DC_WIN_H_INITIAL_DDA);
+	DUMP_REG(DC_WIN_V_INITIAL_DDA);
+	DUMP_REG(DC_WIN_DDA_INC);
+	DUMP_REG(DC_WIN_LINE_STRIDE);
+	DUMP_REG(DC_WIN_BUF_STRIDE);
+	DUMP_REG(DC_WIN_UV_BUF_STRIDE);
+	DUMP_REG(DC_WIN_BUFFER_ADDR_MODE);
+	DUMP_REG(DC_WIN_DV_CONTROL);
+	DUMP_REG(DC_WIN_BLEND_NOKEY);
+	DUMP_REG(DC_WIN_BLEND_1WIN);
+	DUMP_REG(DC_WIN_BLEND_2WIN_X);
+	DUMP_REG(DC_WIN_BLEND_2WIN_Y);
+	DUMP_REG(DC_WIN_BLEND32WIN_XY);
+	DUMP_REG(DC_WIN_HP_FETCH_CONTROL);
+	DUMP_REG(DC_WINBUF_START_ADDR);
+	DUMP_REG(DC_WINBUF_START_ADDR_NS);
+	DUMP_REG(DC_WINBUF_START_ADDR_U);
+	DUMP_REG(DC_WINBUF_START_ADDR_U_NS);
+	DUMP_REG(DC_WINBUF_START_ADDR_V);
+	DUMP_REG(DC_WINBUF_START_ADDR_V_NS);
+	DUMP_REG(DC_WINBUF_ADDR_H_OFFSET);
+	DUMP_REG(DC_WINBUF_ADDR_H_OFFSET_NS);
+	DUMP_REG(DC_WINBUF_ADDR_V_OFFSET);
+	DUMP_REG(DC_WINBUF_ADDR_V_OFFSET_NS);
+	DUMP_REG(DC_WINBUF_UFLOW_STATUS);
+	DUMP_REG(DC_WINBUF_AD_UFLOW_STATUS);
+	DUMP_REG(DC_WINBUF_BD_UFLOW_STATUS);
+	DUMP_REG(DC_WINBUF_CD_UFLOW_STATUS);
+
+#undef DUMP_REG
+
+	return 0;
+}
+
+static struct drm_info_list debugfs_files[] = {
+	{ "regs", tegra_dc_show_regs, 0, NULL },
+};
+
+static int tegra_dc_debugfs_init(struct tegra_dc *dc, struct drm_minor *minor)
+{
+	unsigned int i;
+	char *name;
+	int err;
+
+	name = kasprintf(GFP_KERNEL, "dc.%d", dc->pipe);
+	dc->debugfs = debugfs_create_dir(name, minor->debugfs_root);
+	kfree(name);
+
+	if (!dc->debugfs)
+		return -ENOMEM;
+
+	dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
+				    GFP_KERNEL);
+	if (!dc->debugfs_files) {
+		err = -ENOMEM;
+		goto remove;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
+		dc->debugfs_files[i].data = dc;
+
+	err = drm_debugfs_create_files(dc->debugfs_files,
+				       ARRAY_SIZE(debugfs_files),
+				       dc->debugfs, minor);
+	if (err < 0)
+		goto free;
+
+	dc->minor = minor;
+
+	return 0;
+
+free:
+	kfree(dc->debugfs_files);
+	dc->debugfs_files = NULL;
+remove:
+	debugfs_remove(dc->debugfs);
+	dc->debugfs = NULL;
+
+	return err;
+}
+
+static int tegra_dc_debugfs_exit(struct tegra_dc *dc)
+{
+	drm_debugfs_remove_files(dc->debugfs_files, ARRAY_SIZE(debugfs_files),
+				 dc->minor);
+	dc->minor = NULL;
+
+	kfree(dc->debugfs_files);
+	dc->debugfs_files = NULL;
+
+	debugfs_remove(dc->debugfs);
+	dc->debugfs = NULL;
+
+	return 0;
+}
+
+static int tegra_dc_drm_init(struct host1x_client *client,
+			     struct drm_device *drm)
+{
+	struct tegra_dc *dc = host1x_client_to_dc(client);
+	int err;
+
+	dc->pipe = drm->mode_config.num_crtc;
+
+	drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs);
+	drm_mode_crtc_set_gamma_size(&dc->base, 256);
+	drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
+
+	err = tegra_dc_rgb_init(drm, dc);
+	if (err < 0 && err != -ENODEV) {
+		dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
+		return err;
+	}
+
+	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
+		err = tegra_dc_debugfs_init(dc, drm->primary);
+		if (err < 0)
+			dev_err(dc->dev, "debugfs setup failed: %d\n", err);
+	}
+
+	err = devm_request_irq(dc->dev, dc->irq, tegra_drm_irq, 0,
+			       dev_name(dc->dev), dc);
+	if (err < 0) {
+		dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq,
+			err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int tegra_dc_drm_exit(struct host1x_client *client)
+{
+	struct tegra_dc *dc = host1x_client_to_dc(client);
+	int err;
+
+	devm_free_irq(dc->dev, dc->irq, dc);
+
+	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
+		err = tegra_dc_debugfs_exit(dc);
+		if (err < 0)
+			dev_err(dc->dev, "debugfs cleanup failed: %d\n", err);
+	}
+
+	err = tegra_dc_rgb_exit(dc);
+	if (err) {
+		dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static const struct host1x_client_ops dc_client_ops = {
+	.drm_init = tegra_dc_drm_init,
+	.drm_exit = tegra_dc_drm_exit,
+};
+
+static int tegra_dc_probe(struct platform_device *pdev)
+{
+	struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
+	struct resource *regs;
+	struct tegra_dc *dc;
+	int err;
+
+	dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
+	if (!dc)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&dc->list);
+	dc->dev = &pdev->dev;
+
+	dc->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dc->clk)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		return PTR_ERR(dc->clk);
+	}
+
+	err = clk_prepare_enable(dc->clk);
+	if (err < 0)
+		return err;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs) {
+		dev_err(&pdev->dev, "failed to get registers\n");
+		return -ENXIO;
+	}
+
+	dc->regs = devm_request_and_ioremap(&pdev->dev, regs);
+	if (!dc->regs) {
+		dev_err(&pdev->dev, "failed to remap registers\n");
+		return -ENXIO;
+	}
+
+	dc->irq = platform_get_irq(pdev, 0);
+	if (dc->irq < 0) {
+		dev_err(&pdev->dev, "failed to get IRQ\n");
+		return -ENXIO;
+	}
+
+	INIT_LIST_HEAD(&dc->client.list);
+	dc->client.ops = &dc_client_ops;
+	dc->client.dev = &pdev->dev;
+
+	err = tegra_dc_rgb_probe(dc);
+	if (err < 0 && err != -ENODEV) {
+		dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err);
+		return err;
+	}
+
+	err = host1x_register_client(host1x, &dc->client);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
+			err);
+		return err;
+	}
+
+	platform_set_drvdata(pdev, dc);
+
+	return 0;
+}
+
+static int tegra_dc_remove(struct platform_device *pdev)
+{
+	struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
+	struct tegra_dc *dc = platform_get_drvdata(pdev);
+	int err;
+
+	err = host1x_unregister_client(host1x, &dc->client);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
+			err);
+		return err;
+	}
+
+	clk_disable_unprepare(dc->clk);
+
+	return 0;
+}
+
+static struct of_device_id tegra_dc_of_match[] = {
+	{ .compatible = "nvidia,tegra30-dc", },
+	{ .compatible = "nvidia,tegra20-dc", },
+	{ },
+};
+
+struct platform_driver tegra_dc_driver = {
+	.driver = {
+		.name = "tegra-dc",
+		.owner = THIS_MODULE,
+		.of_match_table = tegra_dc_of_match,
+	},
+	.probe = tegra_dc_probe,
+	.remove = tegra_dc_remove,
+};
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
new file mode 100644
index 0000000..99977b5
--- /dev/null
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef TEGRA_DC_H
+#define TEGRA_DC_H 1
+
+#define DC_CMD_GENERAL_INCR_SYNCPT		0x000
+#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL	0x001
+#define DC_CMD_GENERAL_INCR_SYNCPT_ERROR	0x002
+#define DC_CMD_WIN_A_INCR_SYNCPT		0x008
+#define DC_CMD_WIN_A_INCR_SYNCPT_CNTRL		0x009
+#define DC_CMD_WIN_A_INCR_SYNCPT_ERROR		0x00a
+#define DC_CMD_WIN_B_INCR_SYNCPT		0x010
+#define DC_CMD_WIN_B_INCR_SYNCPT_CNTRL		0x011
+#define DC_CMD_WIN_B_INCR_SYNCPT_ERROR		0x012
+#define DC_CMD_WIN_C_INCR_SYNCPT		0x018
+#define DC_CMD_WIN_C_INCR_SYNCPT_CNTRL		0x019
+#define DC_CMD_WIN_C_INCR_SYNCPT_ERROR		0x01a
+#define DC_CMD_CONT_SYNCPT_VSYNC		0x028
+#define DC_CMD_DISPLAY_COMMAND_OPTION0		0x031
+#define DC_CMD_DISPLAY_COMMAND			0x032
+#define DISP_CTRL_MODE_STOP (0 << 5)
+#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
+#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
+#define DC_CMD_SIGNAL_RAISE			0x033
+#define DC_CMD_DISPLAY_POWER_CONTROL		0x036
+#define PW0_ENABLE (1 <<  0)
+#define PW1_ENABLE (1 <<  2)
+#define PW2_ENABLE (1 <<  4)
+#define PW3_ENABLE (1 <<  6)
+#define PW4_ENABLE (1 <<  8)
+#define PM0_ENABLE (1 << 16)
+#define PM1_ENABLE (1 << 18)
+
+#define DC_CMD_INT_STATUS			0x037
+#define DC_CMD_INT_MASK				0x038
+#define DC_CMD_INT_ENABLE			0x039
+#define DC_CMD_INT_TYPE				0x03a
+#define DC_CMD_INT_POLARITY			0x03b
+#define CTXSW_INT     (1 << 0)
+#define FRAME_END_INT (1 << 1)
+#define VBLANK_INT    (1 << 2)
+#define WIN_A_UF_INT  (1 << 8)
+#define WIN_B_UF_INT  (1 << 9)
+#define WIN_C_UF_INT  (1 << 10)
+#define WIN_A_OF_INT  (1 << 14)
+#define WIN_B_OF_INT  (1 << 15)
+#define WIN_C_OF_INT  (1 << 16)
+
+#define DC_CMD_SIGNAL_RAISE1			0x03c
+#define DC_CMD_SIGNAL_RAISE2			0x03d
+#define DC_CMD_SIGNAL_RAISE3			0x03e
+
+#define DC_CMD_STATE_ACCESS			0x040
+
+#define DC_CMD_STATE_CONTROL			0x041
+#define GENERAL_ACT_REQ (1 <<  0)
+#define WIN_A_ACT_REQ   (1 <<  1)
+#define WIN_B_ACT_REQ   (1 <<  2)
+#define WIN_C_ACT_REQ   (1 <<  3)
+#define GENERAL_UPDATE  (1 <<  8)
+#define WIN_A_UPDATE    (1 <<  9)
+#define WIN_B_UPDATE    (1 << 10)
+#define WIN_C_UPDATE    (1 << 11)
+#define NC_HOST_TRIG    (1 << 24)
+
+#define DC_CMD_DISPLAY_WINDOW_HEADER		0x042
+#define WINDOW_A_SELECT (1 << 4)
+#define WINDOW_B_SELECT (1 << 5)
+#define WINDOW_C_SELECT (1 << 6)
+
+#define DC_CMD_REG_ACT_CONTROL			0x043
+
+#define DC_COM_CRC_CONTROL			0x300
+#define DC_COM_CRC_CHECKSUM			0x301
+#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
+#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
+#define LVS_OUTPUT_POLARITY_LOW (1 << 28)
+#define LHS_OUTPUT_POLARITY_LOW (1 << 30)
+#define DC_COM_PIN_OUTPUT_DATA(x) (0x30a + (x))
+#define DC_COM_PIN_INPUT_ENABLE(x) (0x30e + (x))
+#define DC_COM_PIN_INPUT_DATA(x) (0x312 + (x))
+#define DC_COM_PIN_OUTPUT_SELECT(x) (0x314 + (x))
+
+#define DC_COM_PIN_MISC_CONTROL			0x31b
+#define DC_COM_PIN_PM0_CONTROL			0x31c
+#define DC_COM_PIN_PM0_DUTY_CYCLE		0x31d
+#define DC_COM_PIN_PM1_CONTROL			0x31e
+#define DC_COM_PIN_PM1_DUTY_CYCLE		0x31f
+
+#define DC_COM_SPI_CONTROL			0x320
+#define DC_COM_SPI_START_BYTE			0x321
+#define DC_COM_HSPI_WRITE_DATA_AB		0x322
+#define DC_COM_HSPI_WRITE_DATA_CD		0x323
+#define DC_COM_HSPI_CS_DC			0x324
+#define DC_COM_SCRATCH_REGISTER_A		0x325
+#define DC_COM_SCRATCH_REGISTER_B		0x326
+#define DC_COM_GPIO_CTRL			0x327
+#define DC_COM_GPIO_DEBOUNCE_COUNTER		0x328
+#define DC_COM_CRC_CHECKSUM_LATCHED		0x329
+
+#define DC_DISP_DISP_SIGNAL_OPTIONS0		0x400
+#define H_PULSE_0_ENABLE (1 <<  8)
+#define H_PULSE_1_ENABLE (1 << 10)
+#define H_PULSE_2_ENABLE (1 << 12)
+
+#define DC_DISP_DISP_SIGNAL_OPTIONS1		0x401
+
+#define DC_DISP_DISP_WIN_OPTIONS		0x402
+#define HDMI_ENABLE (1 << 30)
+
+#define DC_DISP_DISP_MEM_HIGH_PRIORITY		0x403
+#define CURSOR_THRESHOLD(x)   (((x) & 0x03) << 24)
+#define WINDOW_A_THRESHOLD(x) (((x) & 0x7f) << 16)
+#define WINDOW_B_THRESHOLD(x) (((x) & 0x7f) <<  8)
+#define WINDOW_C_THRESHOLD(x) (((x) & 0xff) <<  0)
+
+#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER	0x404
+#define CURSOR_DELAY(x)   (((x) & 0x3f) << 24)
+#define WINDOW_A_DELAY(x) (((x) & 0x3f) << 16)
+#define WINDOW_B_DELAY(x) (((x) & 0x3f) <<  8)
+#define WINDOW_C_DELAY(x) (((x) & 0x3f) <<  0)
+
+#define DC_DISP_DISP_TIMING_OPTIONS		0x405
+#define VSYNC_H_POSITION(x) ((x) & 0xfff)
+
+#define DC_DISP_REF_TO_SYNC			0x406
+#define DC_DISP_SYNC_WIDTH			0x407
+#define DC_DISP_BACK_PORCH			0x408
+#define DC_DISP_ACTIVE				0x409
+#define DC_DISP_FRONT_PORCH			0x40a
+#define DC_DISP_H_PULSE0_CONTROL		0x40b
+#define DC_DISP_H_PULSE0_POSITION_A		0x40c
+#define DC_DISP_H_PULSE0_POSITION_B		0x40d
+#define DC_DISP_H_PULSE0_POSITION_C		0x40e
+#define DC_DISP_H_PULSE0_POSITION_D		0x40f
+#define DC_DISP_H_PULSE1_CONTROL		0x410
+#define DC_DISP_H_PULSE1_POSITION_A		0x411
+#define DC_DISP_H_PULSE1_POSITION_B		0x412
+#define DC_DISP_H_PULSE1_POSITION_C		0x413
+#define DC_DISP_H_PULSE1_POSITION_D		0x414
+#define DC_DISP_H_PULSE2_CONTROL		0x415
+#define DC_DISP_H_PULSE2_POSITION_A		0x416
+#define DC_DISP_H_PULSE2_POSITION_B		0x417
+#define DC_DISP_H_PULSE2_POSITION_C		0x418
+#define DC_DISP_H_PULSE2_POSITION_D		0x419
+#define DC_DISP_V_PULSE0_CONTROL		0x41a
+#define DC_DISP_V_PULSE0_POSITION_A		0x41b
+#define DC_DISP_V_PULSE0_POSITION_B		0x41c
+#define DC_DISP_V_PULSE0_POSITION_C		0x41d
+#define DC_DISP_V_PULSE1_CONTROL		0x41e
+#define DC_DISP_V_PULSE1_POSITION_A		0x41f
+#define DC_DISP_V_PULSE1_POSITION_B		0x420
+#define DC_DISP_V_PULSE1_POSITION_C		0x421
+#define DC_DISP_V_PULSE2_CONTROL		0x422
+#define DC_DISP_V_PULSE2_POSITION_A		0x423
+#define DC_DISP_V_PULSE3_CONTROL		0x424
+#define DC_DISP_V_PULSE3_POSITION_A		0x425
+#define DC_DISP_M0_CONTROL			0x426
+#define DC_DISP_M1_CONTROL			0x427
+#define DC_DISP_DI_CONTROL			0x428
+#define DC_DISP_PP_CONTROL			0x429
+#define DC_DISP_PP_SELECT_A			0x42a
+#define DC_DISP_PP_SELECT_B			0x42b
+#define DC_DISP_PP_SELECT_C			0x42c
+#define DC_DISP_PP_SELECT_D			0x42d
+
+#define PULSE_MODE_NORMAL    (0 << 3)
+#define PULSE_MODE_ONE_CLOCK (1 << 3)
+#define PULSE_POLARITY_HIGH  (0 << 4)
+#define PULSE_POLARITY_LOW   (1 << 4)
+#define PULSE_QUAL_ALWAYS    (0 << 6)
+#define PULSE_QUAL_VACTIVE   (2 << 6)
+#define PULSE_QUAL_VACTIVE1  (3 << 6)
+#define PULSE_LAST_START_A   (0 << 8)
+#define PULSE_LAST_END_A     (1 << 8)
+#define PULSE_LAST_START_B   (2 << 8)
+#define PULSE_LAST_END_B     (3 << 8)
+#define PULSE_LAST_START_C   (4 << 8)
+#define PULSE_LAST_END_C     (5 << 8)
+#define PULSE_LAST_START_D   (6 << 8)
+#define PULSE_LAST_END_D     (7 << 8)
+
+#define PULSE_START(x) (((x) & 0xfff) <<  0)
+#define PULSE_END(x)   (((x) & 0xfff) << 16)
+
+#define DC_DISP_DISP_CLOCK_CONTROL		0x42e
+#define PIXEL_CLK_DIVIDER_PCD1  (0 << 8)
+#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8)
+#define PIXEL_CLK_DIVIDER_PCD2  (2 << 8)
+#define PIXEL_CLK_DIVIDER_PCD3  (3 << 8)
+#define PIXEL_CLK_DIVIDER_PCD4  (4 << 8)
+#define PIXEL_CLK_DIVIDER_PCD6  (5 << 8)
+#define PIXEL_CLK_DIVIDER_PCD8  (6 << 8)
+#define PIXEL_CLK_DIVIDER_PCD9  (7 << 8)
+#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8)
+#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8)
+#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8)
+#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8)
+#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8)
+#define SHIFT_CLK_DIVIDER(x)    ((x) & 0xff)
+
+#define DC_DISP_DISP_INTERFACE_CONTROL		0x42f
+#define DISP_DATA_FORMAT_DF1P1C    (0 << 0)
+#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0)
+#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0)
+#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0)
+#define DISP_DATA_FORMAT_DF2S      (4 << 0)
+#define DISP_DATA_FORMAT_DF3S      (5 << 0)
+#define DISP_DATA_FORMAT_DFSPI     (6 << 0)
+#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0)
+#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0)
+#define DISP_ALIGNMENT_MSB         (0 << 8)
+#define DISP_ALIGNMENT_LSB         (1 << 8)
+#define DISP_ORDER_RED_BLUE        (0 << 9)
+#define DISP_ORDER_BLUE_RED        (1 << 9)
+
+#define DC_DISP_DISP_COLOR_CONTROL		0x430
+#define BASE_COLOR_SIZE666     (0 << 0)
+#define BASE_COLOR_SIZE111     (1 << 0)
+#define BASE_COLOR_SIZE222     (2 << 0)
+#define BASE_COLOR_SIZE333     (3 << 0)
+#define BASE_COLOR_SIZE444     (4 << 0)
+#define BASE_COLOR_SIZE555     (5 << 0)
+#define BASE_COLOR_SIZE565     (6 << 0)
+#define BASE_COLOR_SIZE332     (7 << 0)
+#define BASE_COLOR_SIZE888     (8 << 0)
+#define DITHER_CONTROL_DISABLE (0 << 8)
+#define DITHER_CONTROL_ORDERED (2 << 8)
+#define DITHER_CONTROL_ERRDIFF (3 << 8)
+
+#define DC_DISP_SHIFT_CLOCK_OPTIONS		0x431
+
+#define DC_DISP_DATA_ENABLE_OPTIONS		0x432
+#define DE_SELECT_ACTIVE_BLANK  (0 << 0)
+#define DE_SELECT_ACTIVE        (1 << 0)
+#define DE_SELECT_ACTIVE_IS     (2 << 0)
+#define DE_CONTROL_ONECLK       (0 << 2)
+#define DE_CONTROL_NORMAL       (1 << 2)
+#define DE_CONTROL_EARLY_EXT    (2 << 2)
+#define DE_CONTROL_EARLY        (3 << 2)
+#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
+
+#define DC_DISP_SERIAL_INTERFACE_OPTIONS	0x433
+#define DC_DISP_LCD_SPI_OPTIONS			0x434
+#define DC_DISP_BORDER_COLOR			0x435
+#define DC_DISP_COLOR_KEY0_LOWER		0x436
+#define DC_DISP_COLOR_KEY0_UPPER		0x437
+#define DC_DISP_COLOR_KEY1_LOWER		0x438
+#define DC_DISP_COLOR_KEY1_UPPER		0x439
+
+#define DC_DISP_CURSOR_FOREGROUND		0x43c
+#define DC_DISP_CURSOR_BACKGROUND		0x43d
+
+#define DC_DISP_CURSOR_START_ADDR		0x43e
+#define DC_DISP_CURSOR_START_ADDR_NS		0x43f
+
+#define DC_DISP_CURSOR_POSITION			0x440
+#define DC_DISP_CURSOR_POSITION_NS		0x441
+
+#define DC_DISP_INIT_SEQ_CONTROL		0x442
+#define DC_DISP_SPI_INIT_SEQ_DATA_A		0x443
+#define DC_DISP_SPI_INIT_SEQ_DATA_B		0x444
+#define DC_DISP_SPI_INIT_SEQ_DATA_C		0x445
+#define DC_DISP_SPI_INIT_SEQ_DATA_D		0x446
+
+#define DC_DISP_DC_MCCIF_FIFOCTRL		0x480
+#define DC_DISP_MCCIF_DISPLAY0A_HYST		0x481
+#define DC_DISP_MCCIF_DISPLAY0B_HYST		0x482
+#define DC_DISP_MCCIF_DISPLAY1A_HYST		0x483
+#define DC_DISP_MCCIF_DISPLAY1B_HYST		0x484
+
+#define DC_DISP_DAC_CRT_CTRL			0x4c0
+#define DC_DISP_DISP_MISC_CONTROL		0x4c1
+#define DC_DISP_SD_CONTROL			0x4c2
+#define DC_DISP_SD_CSC_COEFF			0x4c3
+#define DC_DISP_SD_LUT(x)			(0x4c4 + (x))
+#define DC_DISP_SD_FLICKER_CONTROL		0x4cd
+#define DC_DISP_DC_PIXEL_COUNT			0x4ce
+#define DC_DISP_SD_HISTOGRAM(x)			(0x4cf + (x))
+#define DC_DISP_SD_BL_PARAMETERS		0x4d7
+#define DC_DISP_SD_BL_TF(x)			(0x4d8 + (x))
+#define DC_DISP_SD_BL_CONTROL			0x4dc
+#define DC_DISP_SD_HW_K_VALUES			0x4dd
+#define DC_DISP_SD_MAN_K_VALUES			0x4de
+
+#define DC_WIN_WIN_OPTIONS			0x700
+#define COLOR_EXPAND (1 <<  6)
+#define WIN_ENABLE   (1 << 30)
+
+#define DC_WIN_BYTE_SWAP			0x701
+#define BYTE_SWAP_NOSWAP  (0 << 0)
+#define BYTE_SWAP_SWAP2   (1 << 0)
+#define BYTE_SWAP_SWAP4   (2 << 0)
+#define BYTE_SWAP_SWAP4HW (3 << 0)
+
+#define DC_WIN_BUFFER_CONTROL			0x702
+#define BUFFER_CONTROL_HOST  (0 << 0)
+#define BUFFER_CONTROL_VI    (1 << 0)
+#define BUFFER_CONTROL_EPP   (2 << 0)
+#define BUFFER_CONTROL_MPEGE (3 << 0)
+#define BUFFER_CONTROL_SB2D  (4 << 0)
+
+#define DC_WIN_COLOR_DEPTH			0x703
+#define WIN_COLOR_DEPTH_P1              0
+#define WIN_COLOR_DEPTH_P2              1
+#define WIN_COLOR_DEPTH_P4              2
+#define WIN_COLOR_DEPTH_P8              3
+#define WIN_COLOR_DEPTH_B4G4R4A4        4
+#define WIN_COLOR_DEPTH_B5G5R5A         5
+#define WIN_COLOR_DEPTH_B5G6R5          6
+#define WIN_COLOR_DEPTH_AB5G5R5         7
+#define WIN_COLOR_DEPTH_B8G8R8A8       12
+#define WIN_COLOR_DEPTH_R8G8B8A8       13
+#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 14
+#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 15
+#define WIN_COLOR_DEPTH_YCbCr422       16
+#define WIN_COLOR_DEPTH_YUV422         17
+#define WIN_COLOR_DEPTH_YCbCr420P      18
+#define WIN_COLOR_DEPTH_YUV420P        19
+#define WIN_COLOR_DEPTH_YCbCr422P      20
+#define WIN_COLOR_DEPTH_YUV422P        21
+#define WIN_COLOR_DEPTH_YCbCr422R      22
+#define WIN_COLOR_DEPTH_YUV422R        23
+#define WIN_COLOR_DEPTH_YCbCr422RA     24
+#define WIN_COLOR_DEPTH_YUV422RA       25
+
+#define DC_WIN_POSITION				0x704
+#define H_POSITION(x) (((x) & 0x1fff) <<  0)
+#define V_POSITION(x) (((x) & 0x1fff) << 16)
+
+#define DC_WIN_SIZE				0x705
+#define H_SIZE(x) (((x) & 0x1fff) <<  0)
+#define V_SIZE(x) (((x) & 0x1fff) << 16)
+
+#define DC_WIN_PRESCALED_SIZE			0x706
+#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) <<  0)
+#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16)
+
+#define DC_WIN_H_INITIAL_DDA			0x707
+#define DC_WIN_V_INITIAL_DDA			0x708
+#define DC_WIN_DDA_INC				0x709
+#define H_DDA_INC(x) (((x) & 0xffff) <<  0)
+#define V_DDA_INC(x) (((x) & 0xffff) << 16)
+
+#define DC_WIN_LINE_STRIDE			0x70a
+#define DC_WIN_BUF_STRIDE			0x70b
+#define DC_WIN_UV_BUF_STRIDE			0x70c
+#define DC_WIN_BUFFER_ADDR_MODE			0x70d
+#define DC_WIN_DV_CONTROL			0x70e
+
+#define DC_WIN_BLEND_NOKEY			0x70f
+#define DC_WIN_BLEND_1WIN			0x710
+#define DC_WIN_BLEND_2WIN_X			0x711
+#define DC_WIN_BLEND_2WIN_Y			0x712
+#define DC_WIN_BLEND32WIN_XY			0x713
+
+#define DC_WIN_HP_FETCH_CONTROL			0x714
+
+#define DC_WINBUF_START_ADDR			0x800
+#define DC_WINBUF_START_ADDR_NS			0x801
+#define DC_WINBUF_START_ADDR_U			0x802
+#define DC_WINBUF_START_ADDR_U_NS		0x803
+#define DC_WINBUF_START_ADDR_V			0x804
+#define DC_WINBUF_START_ADDR_V_NS		0x805
+
+#define DC_WINBUF_ADDR_H_OFFSET			0x806
+#define DC_WINBUF_ADDR_H_OFFSET_NS		0x807
+#define DC_WINBUF_ADDR_V_OFFSET			0x808
+#define DC_WINBUF_ADDR_V_OFFSET_NS		0x809
+
+#define DC_WINBUF_UFLOW_STATUS			0x80a
+
+#define DC_WINBUF_AD_UFLOW_STATUS		0xbca
+#define DC_WINBUF_BD_UFLOW_STATUS		0xdca
+#define DC_WINBUF_CD_UFLOW_STATUS		0xfca
+
+/* synchronization points */
+#define SYNCPT_VBLANK0 26
+#define SYNCPT_VBLANK1 27
+
+#endif /* TEGRA_DC_H */
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
new file mode 100644
index 0000000..3a503c9
--- /dev/null
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+
+#include <mach/clk.h>
+#include <linux/dma-mapping.h>
+#include <asm/dma-iommu.h>
+
+#include "drm.h"
+
+#define DRIVER_NAME "tegra"
+#define DRIVER_DESC "NVIDIA Tegra graphics"
+#define DRIVER_DATE "20120330"
+#define DRIVER_MAJOR 0
+#define DRIVER_MINOR 0
+#define DRIVER_PATCHLEVEL 0
+
+static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
+{
+	struct device *dev = drm->dev;
+	struct host1x *host1x;
+	int err;
+
+	host1x = dev_get_drvdata(dev);
+	drm->dev_private = host1x;
+	host1x->drm = drm;
+
+	drm_mode_config_init(drm);
+
+	err = host1x_drm_init(host1x, drm);
+	if (err < 0)
+		return err;
+
+	err = tegra_drm_fb_init(drm);
+	if (err < 0)
+		return err;
+
+	drm_kms_helper_poll_init(drm);
+
+	return 0;
+}
+
+static int tegra_drm_unload(struct drm_device *drm)
+{
+	drm_kms_helper_poll_fini(drm);
+	tegra_drm_fb_exit(drm);
+
+	drm_mode_config_cleanup(drm);
+
+	return 0;
+}
+
+static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
+{
+	return 0;
+}
+
+static void tegra_drm_lastclose(struct drm_device *drm)
+{
+	struct host1x *host1x = drm->dev_private;
+
+	drm_fbdev_cma_restore_mode(host1x->fbdev);
+}
+
+static struct drm_ioctl_desc tegra_drm_ioctls[] = {
+};
+
+static const struct file_operations tegra_drm_fops = {
+	.owner = THIS_MODULE,
+	.open = drm_open,
+	.release = drm_release,
+	.unlocked_ioctl = drm_ioctl,
+	.mmap = drm_gem_cma_mmap,
+	.poll = drm_poll,
+	.fasync = drm_fasync,
+	.read = drm_read,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = drm_compat_ioctl,
+#endif
+	.llseek = noop_llseek,
+};
+
+struct drm_driver tegra_drm_driver = {
+	.driver_features = DRIVER_BUS_PLATFORM | DRIVER_MODESET | DRIVER_GEM,
+	.load = tegra_drm_load,
+	.unload = tegra_drm_unload,
+	.open = tegra_drm_open,
+	.lastclose = tegra_drm_lastclose,
+
+	.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_cma_dumb_destroy,
+
+	.ioctls = tegra_drm_ioctls,
+	.num_ioctls = ARRAY_SIZE(tegra_drm_ioctls),
+	.fops = &tegra_drm_fops,
+
+	.name = DRIVER_NAME,
+	.desc = DRIVER_DESC,
+	.date = DRIVER_DATE,
+	.major = DRIVER_MAJOR,
+	.minor = DRIVER_MINOR,
+	.patchlevel = DRIVER_PATCHLEVEL,
+};
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
new file mode 100644
index 0000000..3a843a7
--- /dev/null
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef TEGRA_DRM_H
+#define TEGRA_DRM_H 1
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fixed.h>
+
+struct tegra_framebuffer {
+	struct drm_framebuffer base;
+	struct drm_gem_cma_object *obj;
+};
+
+static inline struct tegra_framebuffer *to_tegra_fb(struct drm_framebuffer *fb)
+{
+	return container_of(fb, struct tegra_framebuffer, base);
+}
+
+struct host1x {
+	struct drm_device *drm;
+	struct device *dev;
+	void __iomem *regs;
+	struct clk *clk;
+	int syncpt;
+	int irq;
+
+	struct mutex drm_clients_lock;
+	struct list_head drm_clients;
+	struct list_head drm_active;
+
+	struct mutex clients_lock;
+	struct list_head clients;
+
+	struct drm_fbdev_cma *fbdev;
+	struct tegra_framebuffer fb;
+};
+
+struct host1x_client;
+
+struct host1x_client_ops {
+	int (*drm_init)(struct host1x_client *client, struct drm_device *drm);
+	int (*drm_exit)(struct host1x_client *client);
+};
+
+struct host1x_client {
+	struct host1x *host1x;
+	struct device *dev;
+
+	const struct host1x_client_ops *ops;
+
+	struct list_head list;
+};
+
+extern int host1x_drm_init(struct host1x *host1x, struct drm_device *drm);
+extern int host1x_drm_exit(struct host1x *host1x);
+
+extern int host1x_register_client(struct host1x *host1x,
+				  struct host1x_client *client);
+extern int host1x_unregister_client(struct host1x *host1x,
+				    struct host1x_client *client);
+
+struct tegra_output;
+
+struct tegra_dc {
+	struct host1x_client client;
+
+	struct host1x *host1x;
+	struct device *dev;
+
+	struct drm_crtc base;
+	int pipe;
+
+	struct clk *clk;
+
+	void __iomem *regs;
+	int irq;
+
+	struct tegra_output *rgb;
+
+	struct list_head list;
+
+	struct drm_info_list *debugfs_files;
+	struct drm_minor *minor;
+	struct dentry *debugfs;
+};
+
+static inline struct tegra_dc *host1x_client_to_dc(struct host1x_client *client)
+{
+	return container_of(client, struct tegra_dc, client);
+}
+
+static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc)
+{
+	return container_of(crtc, struct tegra_dc, base);
+}
+
+static inline void tegra_dc_writel(struct tegra_dc *dc, unsigned long value,
+				   unsigned long reg)
+{
+	writel(value, dc->regs + (reg << 2));
+}
+
+static inline unsigned long tegra_dc_readl(struct tegra_dc *dc,
+					   unsigned long reg)
+{
+	return readl(dc->regs + (reg << 2));
+}
+
+struct tegra_output_ops {
+	int (*enable)(struct tegra_output *output);
+	int (*disable)(struct tegra_output *output);
+	int (*setup_clock)(struct tegra_output *output, struct clk *clk,
+			   unsigned long pclk);
+	int (*check_mode)(struct tegra_output *output,
+			  struct drm_display_mode *mode,
+			  enum drm_mode_status *status);
+};
+
+enum tegra_output_type {
+	TEGRA_OUTPUT_RGB,
+	TEGRA_OUTPUT_HDMI,
+};
+
+struct tegra_output {
+	struct device_node *of_node;
+	struct device *dev;
+
+	const struct tegra_output_ops *ops;
+	enum tegra_output_type type;
+
+	struct i2c_adapter *ddc;
+	const struct edid *edid;
+	unsigned int hpd_irq;
+	int hpd_gpio;
+
+	struct drm_encoder encoder;
+	struct drm_connector connector;
+};
+
+static inline struct tegra_output *encoder_to_output(struct drm_encoder *e)
+{
+	return container_of(e, struct tegra_output, encoder);
+}
+
+static inline struct tegra_output *connector_to_output(struct drm_connector *c)
+{
+	return container_of(c, struct tegra_output, connector);
+}
+
+static inline int tegra_output_enable(struct tegra_output *output)
+{
+	if (output && output->ops && output->ops->enable)
+		return output->ops->enable(output);
+
+	return output ? -ENOSYS : -EINVAL;
+}
+
+static inline int tegra_output_disable(struct tegra_output *output)
+{
+	if (output && output->ops && output->ops->disable)
+		return output->ops->disable(output);
+
+	return output ? -ENOSYS : -EINVAL;
+}
+
+static inline int tegra_output_setup_clock(struct tegra_output *output,
+					   struct clk *clk, unsigned long pclk)
+{
+	if (output && output->ops && output->ops->setup_clock)
+		return output->ops->setup_clock(output, clk, pclk);
+
+	return output ? -ENOSYS : -EINVAL;
+}
+
+static inline int tegra_output_check_mode(struct tegra_output *output,
+					  struct drm_display_mode *mode,
+					  enum drm_mode_status *status)
+{
+	if (output && output->ops && output->ops->check_mode)
+		return output->ops->check_mode(output, mode, status);
+
+	return output ? -ENOSYS : -EINVAL;
+}
+
+/* from rgb.c */
+extern int tegra_dc_rgb_probe(struct tegra_dc *dc);
+extern int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc);
+extern int tegra_dc_rgb_exit(struct tegra_dc *dc);
+
+/* from output.c */
+extern int tegra_output_parse_dt(struct tegra_output *output);
+extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output);
+extern int tegra_output_exit(struct tegra_output *output);
+
+/* from gem.c */
+extern struct tegra_gem_object *tegra_gem_alloc(struct drm_device *drm,
+						size_t size);
+extern int tegra_gem_handle_create(struct drm_device *drm,
+				   struct drm_file *file, size_t size,
+				   unsigned long flags, uint32_t *handle);
+extern int tegra_gem_dumb_create(struct drm_file *file, struct drm_device *drm,
+				 struct drm_mode_create_dumb *args);
+extern int tegra_gem_dumb_map_offset(struct drm_file *file,
+				     struct drm_device *drm, uint32_t handle,
+				     uint64_t *offset);
+extern int tegra_gem_dumb_destroy(struct drm_file *file,
+				  struct drm_device *drm, uint32_t handle);
+extern int tegra_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
+extern int tegra_gem_init_object(struct drm_gem_object *obj);
+extern void tegra_gem_free_object(struct drm_gem_object *obj);
+extern struct vm_operations_struct tegra_gem_vm_ops;
+
+/* from fb.c */
+extern int tegra_drm_fb_init(struct drm_device *drm);
+extern void tegra_drm_fb_exit(struct drm_device *drm);
+
+extern struct platform_driver tegra_host1x_driver;
+extern struct platform_driver tegra_hdmi_driver;
+extern struct platform_driver tegra_dc_driver;
+extern struct drm_driver tegra_drm_driver;
+
+#endif /* TEGRA_DRM_H */
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
new file mode 100644
index 0000000..97993c6
--- /dev/null
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "drm.h"
+
+static void tegra_drm_fb_output_poll_changed(struct drm_device *drm)
+{
+	struct host1x *host1x = drm->dev_private;
+
+	drm_fbdev_cma_hotplug_event(host1x->fbdev);
+}
+
+static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
+	.fb_create = drm_fb_cma_create,
+	.output_poll_changed = tegra_drm_fb_output_poll_changed,
+};
+
+int tegra_drm_fb_init(struct drm_device *drm)
+{
+	struct host1x *host1x = drm->dev_private;
+	struct drm_fbdev_cma *fbdev;
+
+	drm->mode_config.min_width = 0;
+	drm->mode_config.min_height = 0;
+
+	drm->mode_config.max_width = 4096;
+	drm->mode_config.max_height = 4096;
+
+	drm->mode_config.funcs = &tegra_drm_mode_funcs;
+
+	fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc,
+				   drm->mode_config.num_connector);
+	if (IS_ERR(fbdev))
+		return PTR_ERR(fbdev);
+
+#ifndef CONFIG_FRAMEBUFFER_CONSOLE
+	drm_fbdev_cma_restore_mode(fbdev);
+#endif
+
+	host1x->fbdev = fbdev;
+
+	return 0;
+}
+
+void tegra_drm_fb_exit(struct drm_device *drm)
+{
+	struct host1x *host1x = drm->dev_private;
+
+	drm_fbdev_cma_fini(host1x->fbdev);
+}
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
new file mode 100644
index 0000000..ab40164
--- /dev/null
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -0,0 +1,1334 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/clk.h>
+
+#include "hdmi.h"
+#include "drm.h"
+#include "dc.h"
+
+struct tegra_hdmi {
+	struct host1x_client client;
+	struct tegra_output output;
+	struct device *dev;
+
+	struct regulator *vdd;
+	struct regulator *pll;
+
+	void __iomem *regs;
+	unsigned int irq;
+
+	struct clk *clk_parent;
+	struct clk *clk;
+
+	unsigned int audio_source;
+	unsigned int audio_freq;
+	bool stereo;
+	bool dvi;
+
+	struct drm_info_list *debugfs_files;
+	struct drm_minor *minor;
+	struct dentry *debugfs;
+};
+
+static inline struct tegra_hdmi *
+host1x_client_to_hdmi(struct host1x_client *client)
+{
+	return container_of(client, struct tegra_hdmi, client);
+}
+
+static inline struct tegra_hdmi *to_hdmi(struct tegra_output *output)
+{
+	return container_of(output, struct tegra_hdmi, output);
+}
+
+#define HDMI_AUDIOCLK_FREQ 216000000
+#define HDMI_REKEY_DEFAULT 56
+
+enum {
+	AUTO = 0,
+	SPDIF,
+	HDA,
+};
+
+static inline unsigned long tegra_hdmi_readl(struct tegra_hdmi *hdmi,
+					     unsigned long reg)
+{
+	return readl(hdmi->regs + (reg << 2));
+}
+
+static inline void tegra_hdmi_writel(struct tegra_hdmi *hdmi, unsigned long val,
+				     unsigned long reg)
+{
+	writel(val, hdmi->regs + (reg << 2));
+}
+
+struct tegra_hdmi_audio_config {
+	unsigned int pclk;
+	unsigned int n;
+	unsigned int cts;
+	unsigned int aval;
+};
+
+static const struct tegra_hdmi_audio_config tegra_hdmi_audio_32k[] = {
+	{  25200000, 4096,  25200, 24000 },
+	{  27000000, 4096,  27000, 24000 },
+	{  74250000, 4096,  74250, 24000 },
+	{ 148500000, 4096, 148500, 24000 },
+	{         0,    0,      0,     0 },
+};
+
+static const struct tegra_hdmi_audio_config tegra_hdmi_audio_44_1k[] = {
+	{  25200000, 5880,  26250, 25000 },
+	{  27000000, 5880,  28125, 25000 },
+	{  74250000, 4704,  61875, 20000 },
+	{ 148500000, 4704, 123750, 20000 },
+	{         0,    0,      0,     0 },
+};
+
+static const struct tegra_hdmi_audio_config tegra_hdmi_audio_48k[] = {
+	{  25200000, 6144,  25200, 24000 },
+	{  27000000, 6144,  27000, 24000 },
+	{  74250000, 6144,  74250, 24000 },
+	{ 148500000, 6144, 148500, 24000 },
+	{         0,    0,      0,     0 },
+};
+
+static const struct tegra_hdmi_audio_config tegra_hdmi_audio_88_2k[] = {
+	{  25200000, 11760,  26250, 25000 },
+	{  27000000, 11760,  28125, 25000 },
+	{  74250000,  9408,  61875, 20000 },
+	{ 148500000,  9408, 123750, 20000 },
+	{         0,     0,      0,     0 },
+};
+
+static const struct tegra_hdmi_audio_config tegra_hdmi_audio_96k[] = {
+	{  25200000, 12288,  25200, 24000 },
+	{  27000000, 12288,  27000, 24000 },
+	{  74250000, 12288,  74250, 24000 },
+	{ 148500000, 12288, 148500, 24000 },
+	{         0,     0,      0,     0 },
+};
+
+static const struct tegra_hdmi_audio_config tegra_hdmi_audio_176_4k[] = {
+	{  25200000, 23520,  26250, 25000 },
+	{  27000000, 23520,  28125, 25000 },
+	{  74250000, 18816,  61875, 20000 },
+	{ 148500000, 18816, 123750, 20000 },
+	{         0,     0,      0,     0 },
+};
+
+static const struct tegra_hdmi_audio_config tegra_hdmi_audio_192k[] = {
+	{  25200000, 24576,  25200, 24000 },
+	{  27000000, 24576,  27000, 24000 },
+	{  74250000, 24576,  74250, 24000 },
+	{ 148500000, 24576, 148500, 24000 },
+	{         0,     0,      0,     0 },
+};
+
+struct tmds_config {
+	unsigned int pclk;
+	u32 pll0;
+	u32 pll1;
+	u32 pe_current;
+	u32 drive_current;
+};
+
+static const struct tmds_config tegra2_tmds_config[] = {
+	{ /* 480p modes */
+		.pclk = 27000000,
+		.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
+			SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
+			SOR_PLL_TX_REG_LOAD(3),
+		.pll1 = SOR_PLL_TMDS_TERM_ENABLE,
+		.pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
+			PE_CURRENT1(PE_CURRENT_0_0_mA) |
+			PE_CURRENT2(PE_CURRENT_0_0_mA) |
+			PE_CURRENT3(PE_CURRENT_0_0_mA),
+		.drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
+			DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
+			DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
+			DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
+	}, { /* 720p modes */
+		.pclk = 74250000,
+		.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
+			SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
+			SOR_PLL_TX_REG_LOAD(3),
+		.pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
+		.pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) |
+			PE_CURRENT1(PE_CURRENT_6_0_mA) |
+			PE_CURRENT2(PE_CURRENT_6_0_mA) |
+			PE_CURRENT3(PE_CURRENT_6_0_mA),
+		.drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
+			DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
+			DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
+			DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
+	}, { /* 1080p modes */
+		.pclk = UINT_MAX,
+		.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
+			SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
+			SOR_PLL_TX_REG_LOAD(3),
+		.pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
+		.pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) |
+			PE_CURRENT1(PE_CURRENT_6_0_mA) |
+			PE_CURRENT2(PE_CURRENT_6_0_mA) |
+			PE_CURRENT3(PE_CURRENT_6_0_mA),
+		.drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
+			DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
+			DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
+			DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
+	},
+};
+
+static const struct tmds_config tegra3_tmds_config[] = {
+	{ /* 480p modes */
+		.pclk = 27000000,
+		.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
+			SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
+			SOR_PLL_TX_REG_LOAD(0),
+		.pll1 = SOR_PLL_TMDS_TERM_ENABLE,
+		.pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
+			PE_CURRENT1(PE_CURRENT_0_0_mA) |
+			PE_CURRENT2(PE_CURRENT_0_0_mA) |
+			PE_CURRENT3(PE_CURRENT_0_0_mA),
+		.drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
+			DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
+			DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
+			DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
+	}, { /* 720p modes */
+		.pclk = 74250000,
+		.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
+			SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
+			SOR_PLL_TX_REG_LOAD(0),
+		.pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
+		.pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
+			PE_CURRENT1(PE_CURRENT_5_0_mA) |
+			PE_CURRENT2(PE_CURRENT_5_0_mA) |
+			PE_CURRENT3(PE_CURRENT_5_0_mA),
+		.drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
+			DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
+			DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
+			DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
+	}, { /* 1080p modes */
+		.pclk = UINT_MAX,
+		.pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
+			SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(3) |
+			SOR_PLL_TX_REG_LOAD(0),
+		.pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
+		.pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
+			PE_CURRENT1(PE_CURRENT_5_0_mA) |
+			PE_CURRENT2(PE_CURRENT_5_0_mA) |
+			PE_CURRENT3(PE_CURRENT_5_0_mA),
+		.drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
+			DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
+			DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
+			DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
+	},
+};
+
+static const struct tegra_hdmi_audio_config *
+tegra_hdmi_get_audio_config(unsigned int audio_freq, unsigned int pclk)
+{
+	const struct tegra_hdmi_audio_config *table;
+
+	switch (audio_freq) {
+	case 32000:
+		table = tegra_hdmi_audio_32k;
+		break;
+
+	case 44100:
+		table = tegra_hdmi_audio_44_1k;
+		break;
+
+	case 48000:
+		table = tegra_hdmi_audio_48k;
+		break;
+
+	case 88200:
+		table = tegra_hdmi_audio_88_2k;
+		break;
+
+	case 96000:
+		table = tegra_hdmi_audio_96k;
+		break;
+
+	case 176400:
+		table = tegra_hdmi_audio_176_4k;
+		break;
+
+	case 192000:
+		table = tegra_hdmi_audio_192k;
+		break;
+
+	default:
+		return NULL;
+	}
+
+	while (table->pclk) {
+		if (table->pclk == pclk)
+			return table;
+
+		table++;
+	}
+
+	return NULL;
+}
+
+static void tegra_hdmi_setup_audio_fs_tables(struct tegra_hdmi *hdmi)
+{
+	const unsigned int freqs[] = {
+		32000, 44100, 48000, 88200, 96000, 176400, 192000
+	};
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(freqs); i++) {
+		unsigned int f = freqs[i];
+		unsigned int eight_half;
+		unsigned long value;
+		unsigned int delta;
+
+		if (f > 96000)
+			delta = 2;
+		else if (f > 480000)
+			delta = 6;
+		else
+			delta = 9;
+
+		eight_half = (8 * HDMI_AUDIOCLK_FREQ) / (f * 128);
+		value = AUDIO_FS_LOW(eight_half - delta) |
+			AUDIO_FS_HIGH(eight_half + delta);
+		tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_FS(i));
+	}
+}
+
+static int tegra_hdmi_setup_audio(struct tegra_hdmi *hdmi, unsigned int pclk)
+{
+	struct device_node *node = hdmi->dev->of_node;
+	const struct tegra_hdmi_audio_config *config;
+	unsigned int offset = 0;
+	unsigned long value;
+
+	switch (hdmi->audio_source) {
+	case HDA:
+		value = AUDIO_CNTRL0_SOURCE_SELECT_HDAL;
+		break;
+
+	case SPDIF:
+		value = AUDIO_CNTRL0_SOURCE_SELECT_SPDIF;
+		break;
+
+	default:
+		value = AUDIO_CNTRL0_SOURCE_SELECT_AUTO;
+		break;
+	}
+
+	if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
+		value |= AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
+			 AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0);
+		tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
+	} else {
+		value |= AUDIO_CNTRL0_INJECT_NULLSMPL;
+		tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
+
+		value = AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
+			AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0);
+		tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
+	}
+
+	config = tegra_hdmi_get_audio_config(hdmi->audio_freq, pclk);
+	if (!config) {
+		dev_err(hdmi->dev, "cannot set audio to %u at %u pclk\n",
+			hdmi->audio_freq, pclk);
+		return -EINVAL;
+	}
+
+	tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_HDMI_ACR_CTRL);
+
+	value = AUDIO_N_RESETF | AUDIO_N_GENERATE_ALTERNATE |
+		AUDIO_N_VALUE(config->n - 1);
+	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
+
+	tegra_hdmi_writel(hdmi, ACR_SUBPACK_N(config->n) | ACR_ENABLE,
+			  HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
+
+	value = ACR_SUBPACK_CTS(config->cts);
+	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
+
+	value = SPARE_HW_CTS | SPARE_FORCE_SW_CTS | SPARE_CTS_RESET_VAL(1);
+	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_SPARE);
+
+	value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_AUDIO_N);
+	value &= ~AUDIO_N_RESETF;
+	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
+
+	if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
+		switch (hdmi->audio_freq) {
+		case 32000:
+			offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320;
+			break;
+
+		case 44100:
+			offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441;
+			break;
+
+		case 48000:
+			offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480;
+			break;
+
+		case 88200:
+			offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882;
+			break;
+
+		case 96000:
+			offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960;
+			break;
+
+		case 176400:
+			offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764;
+			break;
+
+		case 192000:
+			offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920;
+			break;
+		}
+
+		tegra_hdmi_writel(hdmi, config->aval, offset);
+	}
+
+	tegra_hdmi_setup_audio_fs_tables(hdmi);
+
+	return 0;
+}
+
+static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi,
+				      unsigned int offset, u8 type,
+				      u8 version, void *data, size_t size)
+{
+	unsigned long value;
+	u8 *ptr = data;
+	u32 subpack[2];
+	size_t i;
+	u8 csum;
+
+	/* first byte of data is the checksum */
+	csum = type + version + size - 1;
+
+	for (i = 1; i < size; i++)
+		csum += ptr[i];
+
+	ptr[0] = 0x100 - csum;
+
+	value = INFOFRAME_HEADER_TYPE(type) |
+		INFOFRAME_HEADER_VERSION(version) |
+		INFOFRAME_HEADER_LEN(size - 1);
+	tegra_hdmi_writel(hdmi, value, offset);
+
+	/* The audio inforame only has one set of subpack registers.  The hdmi
+	 * block pads the rest of the data as per the spec so we have to fixup
+	 * the length before filling in the subpacks.
+	 */
+	if (offset == HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER)
+		size = 6;
+
+	/* each subpack 7 bytes devided into:
+	 *   subpack_low - bytes 0 - 3
+	 *   subpack_high - bytes 4 - 6 (with byte 7 padded to 0x00)
+	 */
+	for (i = 0; i < size; i++) {
+		size_t index = i % 7;
+
+		if (index == 0)
+			memset(subpack, 0x0, sizeof(subpack));
+
+		((u8 *)subpack)[index] = ptr[i];
+
+		if (index == 6 || (i + 1 == size)) {
+			unsigned int reg = offset + 1 + (i / 7) * 2;
+
+			tegra_hdmi_writel(hdmi, subpack[0], reg);
+			tegra_hdmi_writel(hdmi, subpack[1], reg + 1);
+		}
+	}
+}
+
+static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
+					   struct drm_display_mode *mode)
+{
+	struct hdmi_avi_infoframe frame;
+	unsigned int h_front_porch;
+	unsigned int hsize = 16;
+	unsigned int vsize = 9;
+
+	if (hdmi->dvi) {
+		tegra_hdmi_writel(hdmi, 0,
+				  HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
+		return;
+	}
+
+	h_front_porch = mode->htotal - mode->hsync_end;
+	memset(&frame, 0, sizeof(frame));
+	frame.r = HDMI_AVI_R_SAME;
+
+	switch (mode->vdisplay) {
+	case 480:
+		if (mode->hdisplay == 640) {
+			frame.m = HDMI_AVI_M_4_3;
+			frame.vic = 1;
+		} else {
+			frame.m = HDMI_AVI_M_16_9;
+			frame.vic = 3;
+		}
+		break;
+
+	case 576:
+		if (((hsize * 10) / vsize) > 14) {
+			frame.m = HDMI_AVI_M_16_9;
+			frame.vic = 18;
+		} else {
+			frame.m = HDMI_AVI_M_4_3;
+			frame.vic = 17;
+		}
+		break;
+
+	case 720:
+	case 1470: /* stereo mode */
+		frame.m = HDMI_AVI_M_16_9;
+
+		if (h_front_porch == 110)
+			frame.vic = 4;
+		else
+			frame.vic = 19;
+		break;
+
+	case 1080:
+	case 2205: /* stereo mode */
+		frame.m = HDMI_AVI_M_16_9;
+
+		switch (h_front_porch) {
+		case 88:
+			frame.vic = 16;
+			break;
+
+		case 528:
+			frame.vic = 31;
+			break;
+
+		default:
+			frame.vic = 32;
+			break;
+		}
+		break;
+
+	default:
+		frame.m = HDMI_AVI_M_16_9;
+		frame.vic = 0;
+		break;
+	}
+
+	tegra_hdmi_write_infopack(hdmi, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER,
+				  HDMI_INFOFRAME_TYPE_AVI, HDMI_AVI_VERSION,
+				  &frame, sizeof(frame));
+
+	tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
+			  HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
+}
+
+static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi)
+{
+	struct hdmi_audio_infoframe frame;
+
+	if (hdmi->dvi) {
+		tegra_hdmi_writel(hdmi, 0,
+				  HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
+		return;
+	}
+
+	memset(&frame, 0, sizeof(frame));
+	frame.cc = HDMI_AUDIO_CC_2;
+
+	tegra_hdmi_write_infopack(hdmi,
+				  HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER,
+				  HDMI_INFOFRAME_TYPE_AUDIO,
+				  HDMI_AUDIO_VERSION,
+				  &frame, sizeof(frame));
+
+	tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
+			  HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
+}
+
+static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi)
+{
+	struct hdmi_stereo_infoframe frame;
+	unsigned long value;
+
+	if (!hdmi->stereo) {
+		value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+		value &= ~GENERIC_CTRL_ENABLE;
+		tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+		return;
+	}
+
+	memset(&frame, 0, sizeof(frame));
+	frame.regid0 = 0x03;
+	frame.regid1 = 0x0c;
+	frame.regid2 = 0x00;
+	frame.hdmi_video_format = 2;
+
+	/* TODO: 74 MHz limit? */
+	if (1) {
+		frame._3d_structure = 0;
+	} else {
+		frame._3d_structure = 8;
+		frame._3d_ext_data = 0;
+	}
+
+	tegra_hdmi_write_infopack(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_HEADER,
+				  HDMI_INFOFRAME_TYPE_VENDOR,
+				  HDMI_VENDOR_VERSION, &frame, 6);
+
+	value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+	value |= GENERIC_CTRL_ENABLE;
+	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+}
+
+static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,
+				  const struct tmds_config *tmds)
+{
+	unsigned long value;
+
+	tegra_hdmi_writel(hdmi, tmds->pll0, HDMI_NV_PDISP_SOR_PLL0);
+	tegra_hdmi_writel(hdmi, tmds->pll1, HDMI_NV_PDISP_SOR_PLL1);
+	tegra_hdmi_writel(hdmi, tmds->pe_current, HDMI_NV_PDISP_PE_CURRENT);
+
+	value = tmds->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE;
+	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
+}
+
+static int tegra_output_hdmi_enable(struct tegra_output *output)
+{
+	unsigned int h_sync_width, h_front_porch, h_back_porch, i, rekey;
+	struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+	struct drm_display_mode *mode = &dc->base.mode;
+	struct tegra_hdmi *hdmi = to_hdmi(output);
+	struct device_node *node = hdmi->dev->of_node;
+	unsigned int pulse_start, div82, pclk;
+	const struct tmds_config *tmds;
+	unsigned int num_tmds;
+	unsigned long value;
+	int retries = 1000;
+	int err;
+
+	pclk = mode->clock * 1000;
+	h_sync_width = mode->hsync_end - mode->hsync_start;
+	h_front_porch = mode->htotal - mode->hsync_end;
+	h_back_porch = mode->hsync_start - mode->hdisplay;
+
+	err = regulator_enable(hdmi->vdd);
+	if (err < 0) {
+		dev_err(hdmi->dev, "failed to enable VDD regulator: %d\n", err);
+		return err;
+	}
+
+	err = regulator_enable(hdmi->pll);
+	if (err < 0) {
+		dev_err(hdmi->dev, "failed to enable PLL regulator: %d\n", err);
+		return err;
+	}
+
+	/*
+	 * This assumes that the display controller will divide its parent
+	 * clock by 2 to generate the pixel clock.
+	 */
+	err = tegra_output_setup_clock(output, hdmi->clk, pclk * 2);
+	if (err < 0) {
+		dev_err(hdmi->dev, "failed to setup clock: %d\n", err);
+		return err;
+	}
+
+	err = clk_set_rate(hdmi->clk, pclk);
+	if (err < 0)
+		return err;
+
+	err = clk_enable(hdmi->clk);
+	if (err < 0) {
+		dev_err(hdmi->dev, "failed to enable clock: %d\n", err);
+		return err;
+	}
+
+	tegra_periph_reset_assert(hdmi->clk);
+	usleep_range(1000, 2000);
+	tegra_periph_reset_deassert(hdmi->clk);
+
+	tegra_dc_writel(dc, VSYNC_H_POSITION(1),
+			DC_DISP_DISP_TIMING_OPTIONS);
+	tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE888,
+			DC_DISP_DISP_COLOR_CONTROL);
+
+	/* video_preamble uses h_pulse2 */
+	pulse_start = 1 + h_sync_width + h_back_porch - 10;
+
+	tegra_dc_writel(dc, H_PULSE_2_ENABLE, DC_DISP_DISP_SIGNAL_OPTIONS0);
+
+	value = PULSE_MODE_NORMAL | PULSE_POLARITY_HIGH | PULSE_QUAL_VACTIVE |
+		PULSE_LAST_END_A;
+	tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL);
+
+	value = PULSE_START(pulse_start) | PULSE_END(pulse_start + 8);
+	tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A);
+
+	value = VSYNC_WINDOW_END(0x210) | VSYNC_WINDOW_START(0x200) |
+		VSYNC_WINDOW_ENABLE;
+	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
+
+	if (dc->pipe)
+		value = HDMI_SRC_DISPLAYB;
+	else
+		value = HDMI_SRC_DISPLAYA;
+
+	if ((mode->hdisplay == 720) && ((mode->vdisplay == 480) ||
+					(mode->vdisplay == 576)))
+		tegra_hdmi_writel(hdmi,
+				  value | ARM_VIDEO_RANGE_FULL,
+				  HDMI_NV_PDISP_INPUT_CONTROL);
+	else
+		tegra_hdmi_writel(hdmi,
+				  value | ARM_VIDEO_RANGE_LIMITED,
+				  HDMI_NV_PDISP_INPUT_CONTROL);
+
+	div82 = clk_get_rate(hdmi->clk) / 1000000 * 4;
+	value = SOR_REFCLK_DIV_INT(div82 >> 2) | SOR_REFCLK_DIV_FRAC(div82);
+	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_REFCLK);
+
+	if (!hdmi->dvi) {
+		err = tegra_hdmi_setup_audio(hdmi, pclk);
+		if (err < 0)
+			hdmi->dvi = true;
+	}
+
+	if (of_device_is_compatible(node, "nvidia,tegra20-hdmi")) {
+		/*
+		 * TODO: add ELD support
+		 */
+	}
+
+	rekey = HDMI_REKEY_DEFAULT;
+	value = HDMI_CTRL_REKEY(rekey);
+	value |= HDMI_CTRL_MAX_AC_PACKET((h_sync_width + h_back_porch +
+					  h_front_porch - rekey - 18) / 32);
+
+	if (!hdmi->dvi)
+		value |= HDMI_CTRL_ENABLE;
+
+	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_CTRL);
+
+	if (hdmi->dvi)
+		tegra_hdmi_writel(hdmi, 0x0,
+				  HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+	else
+		tegra_hdmi_writel(hdmi, GENERIC_CTRL_AUDIO,
+				  HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+
+	tegra_hdmi_setup_avi_infoframe(hdmi, mode);
+	tegra_hdmi_setup_audio_infoframe(hdmi);
+	tegra_hdmi_setup_stereo_infoframe(hdmi);
+
+	/* TMDS CONFIG */
+	if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
+		num_tmds = ARRAY_SIZE(tegra3_tmds_config);
+		tmds = tegra3_tmds_config;
+	} else {
+		num_tmds = ARRAY_SIZE(tegra2_tmds_config);
+		tmds = tegra2_tmds_config;
+	}
+
+	for (i = 0; i < num_tmds; i++) {
+		if (pclk <= tmds[i].pclk) {
+			tegra_hdmi_setup_tmds(hdmi, &tmds[i]);
+			break;
+		}
+	}
+
+	tegra_hdmi_writel(hdmi,
+			  SOR_SEQ_CTL_PU_PC(0) |
+			  SOR_SEQ_PU_PC_ALT(0) |
+			  SOR_SEQ_PD_PC(8) |
+			  SOR_SEQ_PD_PC_ALT(8),
+			  HDMI_NV_PDISP_SOR_SEQ_CTL);
+
+	value = SOR_SEQ_INST_WAIT_TIME(1) |
+		SOR_SEQ_INST_WAIT_UNITS_VSYNC |
+		SOR_SEQ_INST_HALT |
+		SOR_SEQ_INST_PIN_A_LOW |
+		SOR_SEQ_INST_PIN_B_LOW |
+		SOR_SEQ_INST_DRIVE_PWM_OUT_LO;
+
+	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(0));
+	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(8));
+
+	value = 0x1c800;
+	value &= ~SOR_CSTM_ROTCLK(~0);
+	value |= SOR_CSTM_ROTCLK(2);
+	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_CSTM);
+
+	tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND);
+	tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
+	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+
+	/* start SOR */
+	tegra_hdmi_writel(hdmi,
+			  SOR_PWR_NORMAL_STATE_PU |
+			  SOR_PWR_NORMAL_START_NORMAL |
+			  SOR_PWR_SAFE_STATE_PD |
+			  SOR_PWR_SETTING_NEW_TRIGGER,
+			  HDMI_NV_PDISP_SOR_PWR);
+	tegra_hdmi_writel(hdmi,
+			  SOR_PWR_NORMAL_STATE_PU |
+			  SOR_PWR_NORMAL_START_NORMAL |
+			  SOR_PWR_SAFE_STATE_PD |
+			  SOR_PWR_SETTING_NEW_DONE,
+			  HDMI_NV_PDISP_SOR_PWR);
+
+	do {
+		BUG_ON(--retries < 0);
+		value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_PWR);
+	} while (value & SOR_PWR_SETTING_NEW_PENDING);
+
+	value = SOR_STATE_ASY_CRCMODE_COMPLETE |
+		SOR_STATE_ASY_OWNER_HEAD0 |
+		SOR_STATE_ASY_SUBOWNER_BOTH |
+		SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A |
+		SOR_STATE_ASY_DEPOL_POS;
+
+	/* setup sync polarities */
+	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+		value |= SOR_STATE_ASY_HSYNCPOL_POS;
+
+	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+		value |= SOR_STATE_ASY_HSYNCPOL_NEG;
+
+	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+		value |= SOR_STATE_ASY_VSYNCPOL_POS;
+
+	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+		value |= SOR_STATE_ASY_VSYNCPOL_NEG;
+
+	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE2);
+
+	value = SOR_STATE_ASY_HEAD_OPMODE_AWAKE | SOR_STATE_ASY_ORMODE_NORMAL;
+	tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE1);
+
+	tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
+	tegra_hdmi_writel(hdmi, SOR_STATE_UPDATE, HDMI_NV_PDISP_SOR_STATE0);
+	tegra_hdmi_writel(hdmi, value | SOR_STATE_ATTACHED,
+			  HDMI_NV_PDISP_SOR_STATE1);
+	tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
+
+	tegra_dc_writel(dc, HDMI_ENABLE, DC_DISP_DISP_WIN_OPTIONS);
+
+	value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
+		PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
+	tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
+
+	value = DISP_CTRL_MODE_C_DISPLAY;
+	tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
+
+	tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
+	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+
+	/* TODO: add HDCP support */
+
+	return 0;
+}
+
+static int tegra_output_hdmi_disable(struct tegra_output *output)
+{
+	struct tegra_hdmi *hdmi = to_hdmi(output);
+
+	tegra_periph_reset_assert(hdmi->clk);
+	clk_disable(hdmi->clk);
+	regulator_disable(hdmi->pll);
+	regulator_disable(hdmi->vdd);
+
+	return 0;
+}
+
+static int tegra_output_hdmi_setup_clock(struct tegra_output *output,
+					 struct clk *clk, unsigned long pclk)
+{
+	struct tegra_hdmi *hdmi = to_hdmi(output);
+	struct clk *base;
+	int err;
+
+	err = clk_set_parent(clk, hdmi->clk_parent);
+	if (err < 0) {
+		dev_err(output->dev, "failed to set parent: %d\n", err);
+		return err;
+	}
+
+	base = clk_get_parent(hdmi->clk_parent);
+
+	/*
+	 * This assumes that the parent clock is pll_d_out0 or pll_d2_out
+	 * respectively, each of which divides the base pll_d by 2.
+	 */
+	err = clk_set_rate(base, pclk * 2);
+	if (err < 0)
+		dev_err(output->dev,
+			"failed to set base clock rate to %lu Hz\n",
+			pclk * 2);
+
+	return 0;
+}
+
+static int tegra_output_hdmi_check_mode(struct tegra_output *output,
+					struct drm_display_mode *mode,
+					enum drm_mode_status *status)
+{
+	struct tegra_hdmi *hdmi = to_hdmi(output);
+	unsigned long pclk = mode->clock * 1000;
+	struct clk *parent;
+	long err;
+
+	parent = clk_get_parent(hdmi->clk_parent);
+
+	err = clk_round_rate(parent, pclk * 4);
+	if (err < 0)
+		*status = MODE_NOCLOCK;
+	else
+		*status = MODE_OK;
+
+	return 0;
+}
+
+static const struct tegra_output_ops hdmi_ops = {
+	.enable = tegra_output_hdmi_enable,
+	.disable = tegra_output_hdmi_disable,
+	.setup_clock = tegra_output_hdmi_setup_clock,
+	.check_mode = tegra_output_hdmi_check_mode,
+};
+
+static int tegra_hdmi_show_regs(struct seq_file *s, void *data)
+{
+	struct drm_info_node *node = s->private;
+	struct tegra_hdmi *hdmi = node->info_ent->data;
+
+#define DUMP_REG(name)						\
+	seq_printf(s, "%-56s %#05x %08lx\n", #name, name,	\
+		tegra_hdmi_readl(hdmi, name))
+
+	DUMP_REG(HDMI_CTXSW);
+	DUMP_REG(HDMI_NV_PDISP_SOR_STATE0);
+	DUMP_REG(HDMI_NV_PDISP_SOR_STATE1);
+	DUMP_REG(HDMI_NV_PDISP_SOR_STATE2);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_MSB);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_LSB);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_MSB);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_LSB);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_MSB);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_LSB);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_MSB);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_LSB);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_MSB);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_LSB);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_MSB);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_LSB);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CTRL);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CMODE);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_RI);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_MSB);
+	DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_LSB);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU0);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU1);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU2);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_STATUS);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_HEADER);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_CTRL);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_CTRL);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_CTRL);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_STATUS);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_SUBPACK);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_EMU0);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1_RDATA);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_SPARE);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2);
+	DUMP_REG(HDMI_NV_PDISP_HDMI_HDCPRIF_ROM_CTRL);
+	DUMP_REG(HDMI_NV_PDISP_SOR_CAP);
+	DUMP_REG(HDMI_NV_PDISP_SOR_PWR);
+	DUMP_REG(HDMI_NV_PDISP_SOR_TEST);
+	DUMP_REG(HDMI_NV_PDISP_SOR_PLL0);
+	DUMP_REG(HDMI_NV_PDISP_SOR_PLL1);
+	DUMP_REG(HDMI_NV_PDISP_SOR_PLL2);
+	DUMP_REG(HDMI_NV_PDISP_SOR_CSTM);
+	DUMP_REG(HDMI_NV_PDISP_SOR_LVDS);
+	DUMP_REG(HDMI_NV_PDISP_SOR_CRCA);
+	DUMP_REG(HDMI_NV_PDISP_SOR_CRCB);
+	DUMP_REG(HDMI_NV_PDISP_SOR_BLANK);
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_CTL);
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(0));
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(1));
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(2));
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(3));
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(4));
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(5));
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(6));
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(7));
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(8));
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(9));
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(10));
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(11));
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(12));
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(13));
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(14));
+	DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(15));
+	DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA0);
+	DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA1);
+	DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA0);
+	DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA1);
+	DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA0);
+	DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA1);
+	DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA0);
+	DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA1);
+	DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA0);
+	DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA1);
+	DUMP_REG(HDMI_NV_PDISP_SOR_TRIG);
+	DUMP_REG(HDMI_NV_PDISP_SOR_MSCHECK);
+	DUMP_REG(HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
+	DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG0);
+	DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG1);
+	DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG2);
+	DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(0));
+	DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(1));
+	DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(2));
+	DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(3));
+	DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(4));
+	DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(5));
+	DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(6));
+	DUMP_REG(HDMI_NV_PDISP_AUDIO_PULSE_WIDTH);
+	DUMP_REG(HDMI_NV_PDISP_AUDIO_THRESHOLD);
+	DUMP_REG(HDMI_NV_PDISP_AUDIO_CNTRL0);
+	DUMP_REG(HDMI_NV_PDISP_AUDIO_N);
+	DUMP_REG(HDMI_NV_PDISP_HDCPRIF_ROM_TIMING);
+	DUMP_REG(HDMI_NV_PDISP_SOR_REFCLK);
+	DUMP_REG(HDMI_NV_PDISP_CRC_CONTROL);
+	DUMP_REG(HDMI_NV_PDISP_INPUT_CONTROL);
+	DUMP_REG(HDMI_NV_PDISP_SCRATCH);
+	DUMP_REG(HDMI_NV_PDISP_PE_CURRENT);
+	DUMP_REG(HDMI_NV_PDISP_KEY_CTRL);
+	DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG0);
+	DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG1);
+	DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG2);
+	DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_0);
+	DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_1);
+	DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_2);
+	DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_3);
+	DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG);
+	DUMP_REG(HDMI_NV_PDISP_KEY_SKEY_INDEX);
+	DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
+	DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR);
+	DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE);
+
+#undef DUMP_REG
+
+	return 0;
+}
+
+static struct drm_info_list debugfs_files[] = {
+	{ "regs", tegra_hdmi_show_regs, 0, NULL },
+};
+
+static int tegra_hdmi_debugfs_init(struct tegra_hdmi *hdmi,
+				   struct drm_minor *minor)
+{
+	unsigned int i;
+	int err;
+
+	hdmi->debugfs = debugfs_create_dir("hdmi", minor->debugfs_root);
+	if (!hdmi->debugfs)
+		return -ENOMEM;
+
+	hdmi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
+				      GFP_KERNEL);
+	if (!hdmi->debugfs_files) {
+		err = -ENOMEM;
+		goto remove;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
+		hdmi->debugfs_files[i].data = hdmi;
+
+	err = drm_debugfs_create_files(hdmi->debugfs_files,
+				       ARRAY_SIZE(debugfs_files),
+				       hdmi->debugfs, minor);
+	if (err < 0)
+		goto free;
+
+	hdmi->minor = minor;
+
+	return 0;
+
+free:
+	kfree(hdmi->debugfs_files);
+	hdmi->debugfs_files = NULL;
+remove:
+	debugfs_remove(hdmi->debugfs);
+	hdmi->debugfs = NULL;
+
+	return err;
+}
+
+static int tegra_hdmi_debugfs_exit(struct tegra_hdmi *hdmi)
+{
+	drm_debugfs_remove_files(hdmi->debugfs_files, ARRAY_SIZE(debugfs_files),
+				 hdmi->minor);
+	hdmi->minor = NULL;
+
+	kfree(hdmi->debugfs_files);
+	hdmi->debugfs_files = NULL;
+
+	debugfs_remove(hdmi->debugfs);
+	hdmi->debugfs = NULL;
+
+	return 0;
+}
+
+static int tegra_hdmi_drm_init(struct host1x_client *client,
+			       struct drm_device *drm)
+{
+	struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
+	int err;
+
+	hdmi->output.type = TEGRA_OUTPUT_HDMI;
+	hdmi->output.dev = client->dev;
+	hdmi->output.ops = &hdmi_ops;
+
+	err = tegra_output_init(drm, &hdmi->output);
+	if (err < 0) {
+		dev_err(client->dev, "output setup failed: %d\n", err);
+		return err;
+	}
+
+	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
+		err = tegra_hdmi_debugfs_init(hdmi, drm->primary);
+		if (err < 0)
+			dev_err(client->dev, "debugfs setup failed: %d\n", err);
+	}
+
+	return 0;
+}
+
+static int tegra_hdmi_drm_exit(struct host1x_client *client)
+{
+	struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
+	int err;
+
+	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
+		err = tegra_hdmi_debugfs_exit(hdmi);
+		if (err < 0)
+			dev_err(client->dev, "debugfs cleanup failed: %d\n",
+				err);
+	}
+
+	err = tegra_output_disable(&hdmi->output);
+	if (err < 0) {
+		dev_err(client->dev, "output failed to disable: %d\n", err);
+		return err;
+	}
+
+	err = tegra_output_exit(&hdmi->output);
+	if (err < 0) {
+		dev_err(client->dev, "output cleanup failed: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static const struct host1x_client_ops hdmi_client_ops = {
+	.drm_init = tegra_hdmi_drm_init,
+	.drm_exit = tegra_hdmi_drm_exit,
+};
+
+static int tegra_hdmi_probe(struct platform_device *pdev)
+{
+	struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
+	struct tegra_hdmi *hdmi;
+	struct resource *regs;
+	int err;
+
+	hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
+	if (!hdmi)
+		return -ENOMEM;
+
+	hdmi->dev = &pdev->dev;
+	hdmi->audio_source = AUTO;
+	hdmi->audio_freq = 44100;
+	hdmi->stereo = false;
+	hdmi->dvi = false;
+
+	hdmi->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(hdmi->clk)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		return PTR_ERR(hdmi->clk);
+	}
+
+	err = clk_prepare(hdmi->clk);
+	if (err < 0)
+		return err;
+
+	hdmi->clk_parent = devm_clk_get(&pdev->dev, "parent");
+	if (IS_ERR(hdmi->clk_parent))
+		return PTR_ERR(hdmi->clk_parent);
+
+	err = clk_prepare(hdmi->clk_parent);
+	if (err < 0)
+		return err;
+
+	err = clk_set_parent(hdmi->clk, hdmi->clk_parent);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to setup clocks: %d\n", err);
+		return err;
+	}
+
+	hdmi->vdd = devm_regulator_get(&pdev->dev, "vdd");
+	if (IS_ERR(hdmi->vdd)) {
+		dev_err(&pdev->dev, "failed to get VDD regulator\n");
+		return PTR_ERR(hdmi->vdd);
+	}
+
+	hdmi->pll = devm_regulator_get(&pdev->dev, "pll");
+	if (IS_ERR(hdmi->pll)) {
+		dev_err(&pdev->dev, "failed to get PLL regulator\n");
+		return PTR_ERR(hdmi->pll);
+	}
+
+	hdmi->output.dev = &pdev->dev;
+
+	err = tegra_output_parse_dt(&hdmi->output);
+	if (err < 0)
+		return err;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs)
+		return -ENXIO;
+
+	hdmi->regs = devm_request_and_ioremap(&pdev->dev, regs);
+	if (!hdmi->regs)
+		return -EADDRNOTAVAIL;
+
+	err = platform_get_irq(pdev, 0);
+	if (err < 0)
+		return err;
+
+	hdmi->irq = err;
+
+	hdmi->client.ops = &hdmi_client_ops;
+	INIT_LIST_HEAD(&hdmi->client.list);
+	hdmi->client.dev = &pdev->dev;
+
+	err = host1x_register_client(host1x, &hdmi->client);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
+			err);
+		return err;
+	}
+
+	platform_set_drvdata(pdev, hdmi);
+
+	return 0;
+}
+
+static int tegra_hdmi_remove(struct platform_device *pdev)
+{
+	struct host1x *host1x = dev_get_drvdata(pdev->dev.parent);
+	struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
+	int err;
+
+	err = host1x_unregister_client(host1x, &hdmi->client);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
+			err);
+		return err;
+	}
+
+	clk_unprepare(hdmi->clk_parent);
+	clk_unprepare(hdmi->clk);
+
+	return 0;
+}
+
+static struct of_device_id tegra_hdmi_of_match[] = {
+	{ .compatible = "nvidia,tegra30-hdmi", },
+	{ .compatible = "nvidia,tegra20-hdmi", },
+	{ },
+};
+
+struct platform_driver tegra_hdmi_driver = {
+	.driver = {
+		.name = "tegra-hdmi",
+		.owner = THIS_MODULE,
+		.of_match_table = tegra_hdmi_of_match,
+	},
+	.probe = tegra_hdmi_probe,
+	.remove = tegra_hdmi_remove,
+};
diff --git a/drivers/gpu/drm/tegra/hdmi.h b/drivers/gpu/drm/tegra/hdmi.h
new file mode 100644
index 0000000..1477f36
--- /dev/null
+++ b/drivers/gpu/drm/tegra/hdmi.h
@@ -0,0 +1,575 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef TEGRA_HDMI_H
+#define TEGRA_HDMI_H 1
+
+#define HDMI_INFOFRAME_TYPE_VENDOR   0x81
+#define HDMI_INFOFRAME_TYPE_AVI      0x82
+#define HDMI_INFOFRAME_TYPE_SPD      0x83
+#define HDMI_INFOFRAME_TYPE_AUDIO    0x84
+#define HDMI_INFOFRAME_TYPE_MPEG_SRC 0x85
+#define HDMI_INFOFRAME_TYPE_NTSC_VBI 0x86
+
+/* all fields little endian */
+struct hdmi_avi_infoframe {
+	/* PB0 */
+	u8 csum;
+
+	/* PB1 */
+	unsigned s:2; /* scan information */
+	unsigned b:2; /* bar info data valid */
+	unsigned a:1; /* active info present */
+	unsigned y:2; /* RGB or YCbCr */
+	unsigned res1:1;
+
+	/* PB2 */
+	unsigned r:4; /* active format aspect ratio */
+	unsigned m:2; /* picture aspect ratio */
+	unsigned c:2; /* colorimetry */
+
+	/* PB3 */
+	unsigned sc:2;  /* scan information */
+	unsigned q:2;   /* quantization range */
+	unsigned ec:3;  /* extended colorimetry */
+	unsigned itc:1; /* it content */
+
+	/* PB4 */
+	unsigned vic:7; /* video format id code */
+	unsigned res4:1;
+
+	/* PB5 */
+	unsigned pr:4; /* pixel repetition factor */
+	unsigned cn:2; /* it content type*/
+	unsigned yq:2; /* ycc quantization range */
+
+	/* PB6-7 */
+	u16 top_bar_end_line;
+
+	/* PB8-9 */
+	u16 bot_bar_start_line;
+
+	/* PB10-11 */
+	u16 left_bar_end_pixel;
+
+	/* PB12-13 */
+	u16 right_bar_start_pixel;
+} __packed;
+
+#define HDMI_AVI_VERSION 0x02
+
+#define HDMI_AVI_Y_RGB       0x0
+#define HDMI_AVI_Y_YCBCR_422 0x1
+#define HDMI_AVI_Y_YCBCR_444 0x2
+
+#define HDMI_AVI_B_VERT  0x1
+#define HDMI_AVI_B_HORIZ 0x2
+
+#define HDMI_AVI_S_NONE      0x0
+#define HDMI_AVI_S_OVERSCAN  0x1
+#define HDMI_AVI_S_UNDERSCAN 0x2
+
+#define HDMI_AVI_C_NONE     0x0
+#define HDMI_AVI_C_SMPTE    0x1
+#define HDMI_AVI_C_ITU_R    0x2
+#define HDMI_AVI_C_EXTENDED 0x4
+
+#define HDMI_AVI_M_4_3  0x1
+#define HDMI_AVI_M_16_9 0x2
+
+#define HDMI_AVI_R_SAME        0x8
+#define HDMI_AVI_R_4_3_CENTER  0x9
+#define HDMI_AVI_R_16_9_CENTER 0xa
+#define HDMI_AVI_R_14_9_CENTER 0xb
+
+/* all fields little endian */
+struct hdmi_audio_infoframe {
+	/* PB0 */
+	u8 csum;
+
+	/* PB1 */
+	unsigned cc:3; /* channel count */
+	unsigned res1:1;
+	unsigned ct:4; /* coding type */
+
+	/* PB2 */
+	unsigned ss:2; /* sample size */
+	unsigned sf:3; /* sample frequency */
+	unsigned res2:3;
+
+	/* PB3 */
+	unsigned cxt:5; /* coding extention type */
+	unsigned res3:3;
+
+	/* PB4 */
+	u8 ca; /* channel/speaker allocation */
+
+	/* PB5 */
+	unsigned res5:3;
+	unsigned lsv:4; /* level shift value */
+	unsigned dm_inh:1; /* downmix inhibit */
+
+	/* PB6-10 reserved */
+	u8 res6;
+	u8 res7;
+	u8 res8;
+	u8 res9;
+	u8 res10;
+} __packed;
+
+#define HDMI_AUDIO_VERSION 0x01
+
+#define HDMI_AUDIO_CC_STREAM 0x0 /* specified by audio stream */
+#define HDMI_AUDIO_CC_2      0x1
+#define HDMI_AUDIO_CC_3      0x2
+#define HDMI_AUDIO_CC_4      0x3
+#define HDMI_AUDIO_CC_5      0x4
+#define HDMI_AUDIO_CC_6      0x5
+#define HDMI_AUDIO_CC_7      0x6
+#define HDMI_AUDIO_CC_8      0x7
+
+#define HDMI_AUDIO_CT_STREAM  0x0 /* specified by audio stream */
+#define HDMI_AUDIO_CT_PCM     0x1
+#define HDMI_AUDIO_CT_AC3     0x2
+#define HDMI_AUDIO_CT_MPEG1   0x3
+#define HDMI_AUDIO_CT_MP3     0x4
+#define HDMI_AUDIO_CT_MPEG2   0x5
+#define HDMI_AUDIO_CT_AAC_LC  0x6
+#define HDMI_AUDIO_CT_DTS     0x7
+#define HDMI_AUDIO_CT_ATRAC   0x8
+#define HDMI_AUDIO_CT_DSD     0x9
+#define HDMI_AUDIO_CT_E_AC3   0xa
+#define HDMI_AUDIO_CT_DTS_HD  0xb
+#define HDMI_AUDIO_CT_MLP     0xc
+#define HDMI_AUDIO_CT_DST     0xd
+#define HDMI_AUDIO_CT_WMA_PRO 0xe
+#define HDMI_AUDIO_CT_CXT     0xf
+
+#define HDMI_AUDIO_SF_STREAM 0x0 /* specified by audio stream */
+#define HDMI_AUIDO_SF_32K    0x1
+#define HDMI_AUDIO_SF_44_1K  0x2
+#define HDMI_AUDIO_SF_48K    0x3
+#define HDMI_AUDIO_SF_88_2K  0x4
+#define HDMI_AUDIO_SF_96K    0x5
+#define HDMI_AUDIO_SF_176_4K 0x6
+#define HDMI_AUDIO_SF_192K   0x7
+
+#define HDMI_AUDIO_SS_STREAM 0x0 /* specified by audio stream */
+#define HDMI_AUDIO_SS_16BIT  0x1
+#define HDMI_AUDIO_SS_20BIT  0x2
+#define HDMI_AUDIO_SS_24BIT  0x3
+
+#define HDMI_AUDIO_CXT_CT            0x0 /* refer to coding in CT */
+#define HDMI_AUDIO_CXT_HE_AAC        0x1
+#define HDMI_AUDIO_CXT_HE_AAC_V2     0x2
+#define HDMI_AUDIO_CXT_MPEG_SURROUND 0x3
+
+/* all fields little endian */
+struct hdmi_stereo_infoframe {
+	/* PB0 */
+	u8 csum;
+
+	/* PB1 */
+	u8 regid0;
+
+	/* PB2 */
+	u8 regid1;
+
+	/* PB3 */
+	u8 regid2;
+
+	/* PB4 */
+	unsigned res1:5;
+	unsigned hdmi_video_format:3;
+
+	/* PB5 */
+	unsigned res2:4;
+	unsigned _3d_structure:4;
+
+	/* PB6*/
+	unsigned res3:4;
+	unsigned _3d_ext_data:4;
+} __packed;
+
+#define HDMI_VENDOR_VERSION 0x01
+
+/* register definitions */
+#define HDMI_CTXSW						0x00
+
+#define HDMI_NV_PDISP_SOR_STATE0				0x01
+#define SOR_STATE_UPDATE (1 << 0)
+
+#define HDMI_NV_PDISP_SOR_STATE1				0x02
+#define SOR_STATE_ASY_HEAD_OPMODE_AWAKE (2 << 0)
+#define SOR_STATE_ASY_ORMODE_NORMAL     (1 << 2)
+#define SOR_STATE_ATTACHED              (1 << 3)
+
+#define HDMI_NV_PDISP_SOR_STATE2				0x03
+#define SOR_STATE_ASY_OWNER_NONE         (0 <<  0)
+#define SOR_STATE_ASY_OWNER_HEAD0        (1 <<  0)
+#define SOR_STATE_ASY_SUBOWNER_NONE      (0 <<  4)
+#define SOR_STATE_ASY_SUBOWNER_SUBHEAD0  (1 <<  4)
+#define SOR_STATE_ASY_SUBOWNER_SUBHEAD1  (2 <<  4)
+#define SOR_STATE_ASY_SUBOWNER_BOTH      (3 <<  4)
+#define SOR_STATE_ASY_CRCMODE_ACTIVE     (0 <<  6)
+#define SOR_STATE_ASY_CRCMODE_COMPLETE   (1 <<  6)
+#define SOR_STATE_ASY_CRCMODE_NON_ACTIVE (2 <<  6)
+#define SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A (1 << 8)
+#define SOR_STATE_ASY_PROTOCOL_CUSTOM        (15 << 8)
+#define SOR_STATE_ASY_HSYNCPOL_POS       (0 << 12)
+#define SOR_STATE_ASY_HSYNCPOL_NEG       (1 << 12)
+#define SOR_STATE_ASY_VSYNCPOL_POS       (0 << 13)
+#define SOR_STATE_ASY_VSYNCPOL_NEG       (1 << 13)
+#define SOR_STATE_ASY_DEPOL_POS          (0 << 14)
+#define SOR_STATE_ASY_DEPOL_NEG          (1 << 14)
+
+#define HDMI_NV_PDISP_RG_HDCP_AN_MSB				0x04
+#define HDMI_NV_PDISP_RG_HDCP_AN_LSB				0x05
+#define HDMI_NV_PDISP_RG_HDCP_CN_MSB				0x06
+#define HDMI_NV_PDISP_RG_HDCP_CN_LSB				0x07
+#define HDMI_NV_PDISP_RG_HDCP_AKSV_MSB				0x08
+#define HDMI_NV_PDISP_RG_HDCP_AKSV_LSB				0x09
+#define HDMI_NV_PDISP_RG_HDCP_BKSV_MSB				0x0a
+#define HDMI_NV_PDISP_RG_HDCP_BKSV_LSB				0x0b
+#define HDMI_NV_PDISP_RG_HDCP_CKSV_MSB				0x0c
+#define HDMI_NV_PDISP_RG_HDCP_CKSV_LSB				0x0d
+#define HDMI_NV_PDISP_RG_HDCP_DKSV_MSB				0x0e
+#define HDMI_NV_PDISP_RG_HDCP_DKSV_LSB				0x0f
+#define HDMI_NV_PDISP_RG_HDCP_CTRL				0x10
+#define HDMI_NV_PDISP_RG_HDCP_CMODE				0x11
+#define HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB			0x12
+#define HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB			0x13
+#define HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB			0x14
+#define HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2			0x15
+#define HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1			0x16
+#define HDMI_NV_PDISP_RG_HDCP_RI				0x17
+#define HDMI_NV_PDISP_RG_HDCP_CS_MSB				0x18
+#define HDMI_NV_PDISP_RG_HDCP_CS_LSB				0x19
+#define HDMI_NV_PDISP_HDMI_AUDIO_EMU0				0x1a
+#define HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0			0x1b
+#define HDMI_NV_PDISP_HDMI_AUDIO_EMU1				0x1c
+#define HDMI_NV_PDISP_HDMI_AUDIO_EMU2				0x1d
+
+#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL			0x1e
+#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS		0x1f
+#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER		0x20
+#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW		0x21
+#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH	0x22
+#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL			0x23
+#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS			0x24
+#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER			0x25
+#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW		0x26
+#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH		0x27
+#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW		0x28
+#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH		0x29
+
+#define INFOFRAME_CTRL_ENABLE (1 << 0)
+
+#define INFOFRAME_HEADER_TYPE(x)    (((x) & 0xff) <<  0)
+#define INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) <<  8)
+#define INFOFRAME_HEADER_LEN(x)     (((x) & 0x0f) << 16)
+
+#define HDMI_NV_PDISP_HDMI_GENERIC_CTRL				0x2a
+#define GENERIC_CTRL_ENABLE (1 <<  0)
+#define GENERIC_CTRL_OTHER  (1 <<  4)
+#define GENERIC_CTRL_SINGLE (1 <<  8)
+#define GENERIC_CTRL_HBLANK (1 << 12)
+#define GENERIC_CTRL_AUDIO  (1 << 16)
+
+#define HDMI_NV_PDISP_HDMI_GENERIC_STATUS			0x2b
+#define HDMI_NV_PDISP_HDMI_GENERIC_HEADER			0x2c
+#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW			0x2d
+#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH		0x2e
+#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW			0x2f
+#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH		0x30
+#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW			0x31
+#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH		0x32
+#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW			0x33
+#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH		0x34
+
+#define HDMI_NV_PDISP_HDMI_ACR_CTRL				0x35
+#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW			0x36
+#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH		0x37
+#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW			0x38
+#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH		0x39
+#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW			0x3a
+#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH		0x3b
+#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW			0x3c
+#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH		0x3d
+#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW			0x3e
+#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH		0x3f
+#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW			0x40
+#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH		0x41
+#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW			0x42
+#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH		0x43
+
+#define ACR_SUBPACK_CTS(x) (((x) & 0xffffff) << 8)
+#define ACR_SUBPACK_N(x)   (((x) & 0xffffff) << 0)
+#define ACR_ENABLE         (1 << 31)
+
+#define HDMI_NV_PDISP_HDMI_CTRL					0x44
+#define HDMI_CTRL_REKEY(x)         (((x) & 0x7f) <<  0)
+#define HDMI_CTRL_MAX_AC_PACKET(x) (((x) & 0x1f) << 16)
+#define HDMI_CTRL_ENABLE           (1 << 30)
+
+#define HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT			0x45
+#define HDMI_NV_PDISP_HDMI_VSYNC_WINDOW				0x46
+#define VSYNC_WINDOW_END(x)   (((x) & 0x3ff) <<  0)
+#define VSYNC_WINDOW_START(x) (((x) & 0x3ff) << 16)
+#define VSYNC_WINDOW_ENABLE   (1 << 31)
+
+#define HDMI_NV_PDISP_HDMI_GCP_CTRL				0x47
+#define HDMI_NV_PDISP_HDMI_GCP_STATUS				0x48
+#define HDMI_NV_PDISP_HDMI_GCP_SUBPACK				0x49
+#define HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1			0x4a
+#define HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2			0x4b
+#define HDMI_NV_PDISP_HDMI_EMU0					0x4c
+#define HDMI_NV_PDISP_HDMI_EMU1					0x4d
+#define HDMI_NV_PDISP_HDMI_EMU1_RDATA				0x4e
+
+#define HDMI_NV_PDISP_HDMI_SPARE				0x4f
+#define SPARE_HW_CTS           (1 << 0)
+#define SPARE_FORCE_SW_CTS     (1 << 1)
+#define SPARE_CTS_RESET_VAL(x) (((x) & 0x7) << 16)
+
+#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1			0x50
+#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2			0x51
+#define HDMI_NV_PDISP_HDMI_HDCPRIF_ROM_CTRL			0x53
+#define HDMI_NV_PDISP_SOR_CAP					0x54
+#define HDMI_NV_PDISP_SOR_PWR					0x55
+#define SOR_PWR_NORMAL_STATE_PD     (0 <<  0)
+#define SOR_PWR_NORMAL_STATE_PU     (1 <<  0)
+#define SOR_PWR_NORMAL_START_NORMAL (0 <<  1)
+#define SOR_PWR_NORMAL_START_ALT    (1 <<  1)
+#define SOR_PWR_SAFE_STATE_PD       (0 << 16)
+#define SOR_PWR_SAFE_STATE_PU       (1 << 16)
+#define SOR_PWR_SETTING_NEW_DONE    (0 << 31)
+#define SOR_PWR_SETTING_NEW_PENDING (1 << 31)
+#define SOR_PWR_SETTING_NEW_TRIGGER (1 << 31)
+
+#define HDMI_NV_PDISP_SOR_TEST					0x56
+#define HDMI_NV_PDISP_SOR_PLL0					0x57
+#define SOR_PLL_PWR            (1 << 0)
+#define SOR_PLL_PDBG           (1 << 1)
+#define SOR_PLL_VCAPD          (1 << 2)
+#define SOR_PLL_PDPORT         (1 << 3)
+#define SOR_PLL_RESISTORSEL    (1 << 4)
+#define SOR_PLL_PULLDOWN       (1 << 5)
+#define SOR_PLL_VCOCAP(x)      (((x) & 0xf) <<  8)
+#define SOR_PLL_BG_V17_S(x)    (((x) & 0xf) << 12)
+#define SOR_PLL_FILTER(x)      (((x) & 0xf) << 16)
+#define SOR_PLL_ICHPMP(x)      (((x) & 0xf) << 24)
+#define SOR_PLL_TX_REG_LOAD(x) (((x) & 0xf) << 28)
+
+#define HDMI_NV_PDISP_SOR_PLL1					0x58
+#define SOR_PLL_TMDS_TERM_ENABLE (1 << 8)
+#define SOR_PLL_TMDS_TERMADJ(x)  (((x) & 0xf) <<  9)
+#define SOR_PLL_LOADADJ(x)       (((x) & 0xf) << 20)
+#define SOR_PLL_PE_EN            (1 << 28)
+#define SOR_PLL_HALF_FULL_PE     (1 << 29)
+#define SOR_PLL_S_D_PIN_PE       (1 << 30)
+
+#define HDMI_NV_PDISP_SOR_PLL2					0x59
+
+#define HDMI_NV_PDISP_SOR_CSTM					0x5a
+#define SOR_CSTM_ROTCLK(x) (((x) & 0xf) << 24)
+
+#define HDMI_NV_PDISP_SOR_LVDS					0x5b
+#define HDMI_NV_PDISP_SOR_CRCA					0x5c
+#define HDMI_NV_PDISP_SOR_CRCB					0x5d
+#define HDMI_NV_PDISP_SOR_BLANK					0x5e
+#define HDMI_NV_PDISP_SOR_SEQ_CTL				0x5f
+#define SOR_SEQ_CTL_PU_PC(x) (((x) & 0xf) <<  0)
+#define SOR_SEQ_PU_PC_ALT(x) (((x) & 0xf) <<  4)
+#define SOR_SEQ_PD_PC(x)     (((x) & 0xf) <<  8)
+#define SOR_SEQ_PD_PC_ALT(x) (((x) & 0xf) << 12)
+#define SOR_SEQ_PC(x)        (((x) & 0xf) << 16)
+#define SOR_SEQ_STATUS       (1 << 28)
+#define SOR_SEQ_SWITCH       (1 << 30)
+
+#define HDMI_NV_PDISP_SOR_SEQ_INST(x)				(0x60 + (x))
+
+#define SOR_SEQ_INST_WAIT_TIME(x)     (((x) & 0x3ff) << 0)
+#define SOR_SEQ_INST_WAIT_UNITS_VSYNC (2 << 12)
+#define SOR_SEQ_INST_HALT             (1 << 15)
+#define SOR_SEQ_INST_PIN_A_LOW        (0 << 21)
+#define SOR_SEQ_INST_PIN_A_HIGH       (1 << 21)
+#define SOR_SEQ_INST_PIN_B_LOW        (0 << 22)
+#define SOR_SEQ_INST_PIN_B_HIGH       (1 << 22)
+#define SOR_SEQ_INST_DRIVE_PWM_OUT_LO (1 << 23)
+
+#define HDMI_NV_PDISP_SOR_VCRCA0				0x72
+#define HDMI_NV_PDISP_SOR_VCRCA1				0x73
+#define HDMI_NV_PDISP_SOR_CCRCA0				0x74
+#define HDMI_NV_PDISP_SOR_CCRCA1				0x75
+#define HDMI_NV_PDISP_SOR_EDATAA0				0x76
+#define HDMI_NV_PDISP_SOR_EDATAA1				0x77
+#define HDMI_NV_PDISP_SOR_COUNTA0				0x78
+#define HDMI_NV_PDISP_SOR_COUNTA1				0x79
+#define HDMI_NV_PDISP_SOR_DEBUGA0				0x7a
+#define HDMI_NV_PDISP_SOR_DEBUGA1				0x7b
+#define HDMI_NV_PDISP_SOR_TRIG					0x7c
+#define HDMI_NV_PDISP_SOR_MSCHECK				0x7d
+
+#define HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT			0x7e
+#define DRIVE_CURRENT_LANE0(x)      (((x) & 0x3f) <<  0)
+#define DRIVE_CURRENT_LANE1(x)      (((x) & 0x3f) <<  8)
+#define DRIVE_CURRENT_LANE2(x)      (((x) & 0x3f) << 16)
+#define DRIVE_CURRENT_LANE3(x)      (((x) & 0x3f) << 24)
+#define DRIVE_CURRENT_FUSE_OVERRIDE (1 << 31)
+
+#define DRIVE_CURRENT_1_500_mA  0x00
+#define DRIVE_CURRENT_1_875_mA  0x01
+#define DRIVE_CURRENT_2_250_mA  0x02
+#define DRIVE_CURRENT_2_625_mA  0x03
+#define DRIVE_CURRENT_3_000_mA  0x04
+#define DRIVE_CURRENT_3_375_mA  0x05
+#define DRIVE_CURRENT_3_750_mA  0x06
+#define DRIVE_CURRENT_4_125_mA  0x07
+#define DRIVE_CURRENT_4_500_mA  0x08
+#define DRIVE_CURRENT_4_875_mA  0x09
+#define DRIVE_CURRENT_5_250_mA  0x0a
+#define DRIVE_CURRENT_5_625_mA  0x0b
+#define DRIVE_CURRENT_6_000_mA  0x0c
+#define DRIVE_CURRENT_6_375_mA  0x0d
+#define DRIVE_CURRENT_6_750_mA  0x0e
+#define DRIVE_CURRENT_7_125_mA  0x0f
+#define DRIVE_CURRENT_7_500_mA  0x10
+#define DRIVE_CURRENT_7_875_mA  0x11
+#define DRIVE_CURRENT_8_250_mA  0x12
+#define DRIVE_CURRENT_8_625_mA  0x13
+#define DRIVE_CURRENT_9_000_mA  0x14
+#define DRIVE_CURRENT_9_375_mA  0x15
+#define DRIVE_CURRENT_9_750_mA  0x16
+#define DRIVE_CURRENT_10_125_mA 0x17
+#define DRIVE_CURRENT_10_500_mA 0x18
+#define DRIVE_CURRENT_10_875_mA 0x19
+#define DRIVE_CURRENT_11_250_mA 0x1a
+#define DRIVE_CURRENT_11_625_mA 0x1b
+#define DRIVE_CURRENT_12_000_mA 0x1c
+#define DRIVE_CURRENT_12_375_mA 0x1d
+#define DRIVE_CURRENT_12_750_mA 0x1e
+#define DRIVE_CURRENT_13_125_mA 0x1f
+#define DRIVE_CURRENT_13_500_mA 0x20
+#define DRIVE_CURRENT_13_875_mA 0x21
+#define DRIVE_CURRENT_14_250_mA 0x22
+#define DRIVE_CURRENT_14_625_mA 0x23
+#define DRIVE_CURRENT_15_000_mA 0x24
+#define DRIVE_CURRENT_15_375_mA 0x25
+#define DRIVE_CURRENT_15_750_mA 0x26
+#define DRIVE_CURRENT_16_125_mA 0x27
+#define DRIVE_CURRENT_16_500_mA 0x28
+#define DRIVE_CURRENT_16_875_mA 0x29
+#define DRIVE_CURRENT_17_250_mA 0x2a
+#define DRIVE_CURRENT_17_625_mA 0x2b
+#define DRIVE_CURRENT_18_000_mA 0x2c
+#define DRIVE_CURRENT_18_375_mA 0x2d
+#define DRIVE_CURRENT_18_750_mA 0x2e
+#define DRIVE_CURRENT_19_125_mA 0x2f
+#define DRIVE_CURRENT_19_500_mA 0x30
+#define DRIVE_CURRENT_19_875_mA 0x31
+#define DRIVE_CURRENT_20_250_mA 0x32
+#define DRIVE_CURRENT_20_625_mA 0x33
+#define DRIVE_CURRENT_21_000_mA 0x34
+#define DRIVE_CURRENT_21_375_mA 0x35
+#define DRIVE_CURRENT_21_750_mA 0x36
+#define DRIVE_CURRENT_22_125_mA 0x37
+#define DRIVE_CURRENT_22_500_mA 0x38
+#define DRIVE_CURRENT_22_875_mA 0x39
+#define DRIVE_CURRENT_23_250_mA 0x3a
+#define DRIVE_CURRENT_23_625_mA 0x3b
+#define DRIVE_CURRENT_24_000_mA 0x3c
+#define DRIVE_CURRENT_24_375_mA 0x3d
+#define DRIVE_CURRENT_24_750_mA 0x3e
+
+#define HDMI_NV_PDISP_AUDIO_DEBUG0				0x7f
+#define HDMI_NV_PDISP_AUDIO_DEBUG1				0x80
+#define HDMI_NV_PDISP_AUDIO_DEBUG2				0x81
+
+#define HDMI_NV_PDISP_AUDIO_FS(x)				(0x82 + (x))
+#define AUDIO_FS_LOW(x)  (((x) & 0xfff) <<  0)
+#define AUDIO_FS_HIGH(x) (((x) & 0xfff) << 16)
+
+#define HDMI_NV_PDISP_AUDIO_PULSE_WIDTH				0x89
+#define HDMI_NV_PDISP_AUDIO_THRESHOLD				0x8a
+#define HDMI_NV_PDISP_AUDIO_CNTRL0				0x8b
+#define AUDIO_CNTRL0_ERROR_TOLERANCE(x)  (((x) & 0xff) << 0)
+#define AUDIO_CNTRL0_SOURCE_SELECT_AUTO  (0 << 20)
+#define AUDIO_CNTRL0_SOURCE_SELECT_SPDIF (1 << 20)
+#define AUDIO_CNTRL0_SOURCE_SELECT_HDAL  (2 << 20)
+#define AUDIO_CNTRL0_FRAMES_PER_BLOCK(x) (((x) & 0xff) << 24)
+
+#define HDMI_NV_PDISP_AUDIO_N					0x8c
+#define AUDIO_N_VALUE(x)           (((x) & 0xfffff) << 0)
+#define AUDIO_N_RESETF             (1 << 20)
+#define AUDIO_N_GENERATE_NORMAL    (0 << 24)
+#define AUDIO_N_GENERATE_ALTERNATE (1 << 24)
+
+#define HDMI_NV_PDISP_HDCPRIF_ROM_TIMING			0x94
+#define HDMI_NV_PDISP_SOR_REFCLK				0x95
+#define SOR_REFCLK_DIV_INT(x)  (((x) & 0xff) << 8)
+#define SOR_REFCLK_DIV_FRAC(x) (((x) & 0x03) << 6)
+
+#define HDMI_NV_PDISP_CRC_CONTROL				0x96
+#define HDMI_NV_PDISP_INPUT_CONTROL				0x97
+#define HDMI_SRC_DISPLAYA       (0 << 0)
+#define HDMI_SRC_DISPLAYB       (1 << 0)
+#define ARM_VIDEO_RANGE_FULL    (0 << 1)
+#define ARM_VIDEO_RANGE_LIMITED (1 << 1)
+
+#define HDMI_NV_PDISP_SCRATCH					0x98
+#define HDMI_NV_PDISP_PE_CURRENT				0x99
+#define PE_CURRENT0(x) (((x) & 0xf) << 0)
+#define PE_CURRENT1(x) (((x) & 0xf) << 8)
+#define PE_CURRENT2(x) (((x) & 0xf) << 16)
+#define PE_CURRENT3(x) (((x) & 0xf) << 24)
+
+#define PE_CURRENT_0_0_mA 0x0
+#define PE_CURRENT_0_5_mA 0x1
+#define PE_CURRENT_1_0_mA 0x2
+#define PE_CURRENT_1_5_mA 0x3
+#define PE_CURRENT_2_0_mA 0x4
+#define PE_CURRENT_2_5_mA 0x5
+#define PE_CURRENT_3_0_mA 0x6
+#define PE_CURRENT_3_5_mA 0x7
+#define PE_CURRENT_4_0_mA 0x8
+#define PE_CURRENT_4_5_mA 0x9
+#define PE_CURRENT_5_0_mA 0xa
+#define PE_CURRENT_5_5_mA 0xb
+#define PE_CURRENT_6_0_mA 0xc
+#define PE_CURRENT_6_5_mA 0xd
+#define PE_CURRENT_7_0_mA 0xe
+#define PE_CURRENT_7_5_mA 0xf
+
+#define HDMI_NV_PDISP_KEY_CTRL					0x9a
+#define HDMI_NV_PDISP_KEY_DEBUG0				0x9b
+#define HDMI_NV_PDISP_KEY_DEBUG1				0x9c
+#define HDMI_NV_PDISP_KEY_DEBUG2				0x9d
+#define HDMI_NV_PDISP_KEY_HDCP_KEY_0				0x9e
+#define HDMI_NV_PDISP_KEY_HDCP_KEY_1				0x9f
+#define HDMI_NV_PDISP_KEY_HDCP_KEY_2				0xa0
+#define HDMI_NV_PDISP_KEY_HDCP_KEY_3				0xa1
+#define HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG				0xa2
+#define HDMI_NV_PDISP_KEY_SKEY_INDEX				0xa3
+
+#define HDMI_NV_PDISP_SOR_AUDIO_CNTRL0				0xac
+#define AUDIO_CNTRL0_INJECT_NULLSMPL (1 << 29)
+#define HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR			0xbc
+#define HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE			0xbd
+
+#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320    0xbf
+#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441    0xc0
+#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882    0xc1
+#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764    0xc2
+#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480    0xc3
+#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960    0xc4
+#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920    0xc5
+#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_DEFAULT 0xc5
+
+#endif /* TEGRA_HDMI_H */
diff --git a/drivers/gpu/drm/tegra/host1x.c b/drivers/gpu/drm/tegra/host1x.c
new file mode 100644
index 0000000..bdb97a5
--- /dev/null
+++ b/drivers/gpu/drm/tegra/host1x.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "drm.h"
+
+struct host1x_drm_client {
+	struct host1x_client *client;
+	struct device_node *np;
+	struct list_head list;
+};
+
+static int host1x_add_drm_client(struct host1x *host1x, struct device_node *np)
+{
+	struct host1x_drm_client *client;
+
+	client = kzalloc(sizeof(*client), GFP_KERNEL);
+	if (!client)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&client->list);
+	client->np = of_node_get(np);
+
+	list_add_tail(&client->list, &host1x->drm_clients);
+
+	return 0;
+}
+
+static int host1x_activate_drm_client(struct host1x *host1x,
+				      struct host1x_drm_client *drm,
+				      struct host1x_client *client)
+{
+	mutex_lock(&host1x->drm_clients_lock);
+	list_del_init(&drm->list);
+	list_add_tail(&drm->list, &host1x->drm_active);
+	drm->client = client;
+	mutex_unlock(&host1x->drm_clients_lock);
+
+	return 0;
+}
+
+static int host1x_remove_drm_client(struct host1x *host1x,
+				    struct host1x_drm_client *client)
+{
+	mutex_lock(&host1x->drm_clients_lock);
+	list_del_init(&client->list);
+	mutex_unlock(&host1x->drm_clients_lock);
+
+	of_node_put(client->np);
+	kfree(client);
+
+	return 0;
+}
+
+static int host1x_parse_dt(struct host1x *host1x)
+{
+	static const char * const compat[] = {
+		"nvidia,tegra20-dc",
+		"nvidia,tegra20-hdmi",
+		"nvidia,tegra30-dc",
+		"nvidia,tegra30-hdmi",
+	};
+	unsigned int i;
+	int err;
+
+	for (i = 0; i < ARRAY_SIZE(compat); i++) {
+		struct device_node *np;
+
+		for_each_child_of_node(host1x->dev->of_node, np) {
+			if (of_device_is_compatible(np, compat[i]) &&
+			    of_device_is_available(np)) {
+				err = host1x_add_drm_client(host1x, np);
+				if (err < 0)
+					return err;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int tegra_host1x_probe(struct platform_device *pdev)
+{
+	struct host1x *host1x;
+	struct resource *regs;
+	int err;
+
+	host1x = devm_kzalloc(&pdev->dev, sizeof(*host1x), GFP_KERNEL);
+	if (!host1x)
+		return -ENOMEM;
+
+	mutex_init(&host1x->drm_clients_lock);
+	INIT_LIST_HEAD(&host1x->drm_clients);
+	INIT_LIST_HEAD(&host1x->drm_active);
+	mutex_init(&host1x->clients_lock);
+	INIT_LIST_HEAD(&host1x->clients);
+	host1x->dev = &pdev->dev;
+
+	err = host1x_parse_dt(host1x);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to parse DT: %d\n", err);
+		return err;
+	}
+
+	host1x->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(host1x->clk))
+		return PTR_ERR(host1x->clk);
+
+	err = clk_prepare_enable(host1x->clk);
+	if (err < 0)
+		return err;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs) {
+		err = -ENXIO;
+		goto err;
+	}
+
+	err = platform_get_irq(pdev, 0);
+	if (err < 0)
+		goto err;
+
+	host1x->syncpt = err;
+
+	err = platform_get_irq(pdev, 1);
+	if (err < 0)
+		goto err;
+
+	host1x->irq = err;
+
+	host1x->regs = devm_request_and_ioremap(&pdev->dev, regs);
+	if (!host1x->regs) {
+		err = -EADDRNOTAVAIL;
+		goto err;
+	}
+
+	platform_set_drvdata(pdev, host1x);
+
+	return 0;
+
+err:
+	clk_disable_unprepare(host1x->clk);
+	return err;
+}
+
+static int tegra_host1x_remove(struct platform_device *pdev)
+{
+	struct host1x *host1x = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(host1x->clk);
+
+	return 0;
+}
+
+int host1x_drm_init(struct host1x *host1x, struct drm_device *drm)
+{
+	struct host1x_client *client;
+
+	mutex_lock(&host1x->clients_lock);
+
+	list_for_each_entry(client, &host1x->clients, list) {
+		if (client->ops && client->ops->drm_init) {
+			int err = client->ops->drm_init(client, drm);
+			if (err < 0) {
+				dev_err(host1x->dev,
+					"DRM setup failed for %s: %d\n",
+					dev_name(client->dev), err);
+				return err;
+			}
+		}
+	}
+
+	mutex_unlock(&host1x->clients_lock);
+
+	return 0;
+}
+
+int host1x_drm_exit(struct host1x *host1x)
+{
+	struct platform_device *pdev = to_platform_device(host1x->dev);
+	struct host1x_client *client;
+
+	if (!host1x->drm)
+		return 0;
+
+	mutex_lock(&host1x->clients_lock);
+
+	list_for_each_entry_reverse(client, &host1x->clients, list) {
+		if (client->ops && client->ops->drm_exit) {
+			int err = client->ops->drm_exit(client);
+			if (err < 0) {
+				dev_err(host1x->dev,
+					"DRM cleanup failed for %s: %d\n",
+					dev_name(client->dev), err);
+				return err;
+			}
+		}
+	}
+
+	mutex_unlock(&host1x->clients_lock);
+
+	drm_platform_exit(&tegra_drm_driver, pdev);
+	host1x->drm = NULL;
+
+	return 0;
+}
+
+int host1x_register_client(struct host1x *host1x, struct host1x_client *client)
+{
+	struct host1x_drm_client *drm, *tmp;
+	int err;
+
+	mutex_lock(&host1x->clients_lock);
+	list_add_tail(&client->list, &host1x->clients);
+	mutex_unlock(&host1x->clients_lock);
+
+	list_for_each_entry_safe(drm, tmp, &host1x->drm_clients, list)
+		if (drm->np == client->dev->of_node)
+			host1x_activate_drm_client(host1x, drm, client);
+
+	if (list_empty(&host1x->drm_clients)) {
+		struct platform_device *pdev = to_platform_device(host1x->dev);
+
+		err = drm_platform_init(&tegra_drm_driver, pdev);
+		if (err < 0) {
+			dev_err(host1x->dev, "drm_platform_init(): %d\n", err);
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+int host1x_unregister_client(struct host1x *host1x,
+			     struct host1x_client *client)
+{
+	struct host1x_drm_client *drm, *tmp;
+	int err;
+
+	list_for_each_entry_safe(drm, tmp, &host1x->drm_active, list) {
+		if (drm->client == client) {
+			err = host1x_drm_exit(host1x);
+			if (err < 0) {
+				dev_err(host1x->dev, "host1x_drm_exit(): %d\n",
+					err);
+				return err;
+			}
+
+			host1x_remove_drm_client(host1x, drm);
+			break;
+		}
+	}
+
+	mutex_lock(&host1x->clients_lock);
+	list_del_init(&client->list);
+	mutex_unlock(&host1x->clients_lock);
+
+	return 0;
+}
+
+static struct of_device_id tegra_host1x_of_match[] = {
+	{ .compatible = "nvidia,tegra30-host1x", },
+	{ .compatible = "nvidia,tegra20-host1x", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, tegra_host1x_of_match);
+
+struct platform_driver tegra_host1x_driver = {
+	.driver = {
+		.name = "tegra-host1x",
+		.owner = THIS_MODULE,
+		.of_match_table = tegra_host1x_of_match,
+	},
+	.probe = tegra_host1x_probe,
+	.remove = tegra_host1x_remove,
+};
+
+static int __init tegra_host1x_init(void)
+{
+	int err;
+
+	err = platform_driver_register(&tegra_host1x_driver);
+	if (err < 0)
+		return err;
+
+	err = platform_driver_register(&tegra_dc_driver);
+	if (err < 0)
+		goto unregister_host1x;
+
+	err = platform_driver_register(&tegra_hdmi_driver);
+	if (err < 0)
+		goto unregister_dc;
+
+	return 0;
+
+unregister_dc:
+	platform_driver_unregister(&tegra_dc_driver);
+unregister_host1x:
+	platform_driver_unregister(&tegra_host1x_driver);
+	return err;
+}
+module_init(tegra_host1x_init);
+
+static void __exit tegra_host1x_exit(void)
+{
+	platform_driver_unregister(&tegra_hdmi_driver);
+	platform_driver_unregister(&tegra_dc_driver);
+	platform_driver_unregister(&tegra_host1x_driver);
+}
+module_exit(tegra_host1x_exit);
+
+MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
+MODULE_DESCRIPTION("NVIDIA Tegra DRM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
new file mode 100644
index 0000000..8140fc6
--- /dev/null
+++ b/drivers/gpu/drm/tegra/output.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/of_i2c.h>
+
+#include "drm.h"
+
+static int tegra_connector_get_modes(struct drm_connector *connector)
+{
+	struct tegra_output *output = connector_to_output(connector);
+	struct edid *edid = NULL;
+	int err = 0;
+
+	if (output->edid)
+		edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL);
+	else if (output->ddc)
+		edid = drm_get_edid(connector, output->ddc);
+
+	drm_mode_connector_update_edid_property(connector, edid);
+
+	if (edid) {
+		err = drm_add_edid_modes(connector, edid);
+		kfree(edid);
+	}
+
+	return err;
+}
+
+static int tegra_connector_mode_valid(struct drm_connector *connector,
+				      struct drm_display_mode *mode)
+{
+	struct tegra_output *output = connector_to_output(connector);
+	enum drm_mode_status status = MODE_OK;
+	int err;
+
+	err = tegra_output_check_mode(output, mode, &status);
+	if (err < 0)
+		return MODE_ERROR;
+
+	return status;
+}
+
+static struct drm_encoder *
+tegra_connector_best_encoder(struct drm_connector *connector)
+{
+	struct tegra_output *output = connector_to_output(connector);
+
+	return &output->encoder;
+}
+
+static const struct drm_connector_helper_funcs connector_helper_funcs = {
+	.get_modes = tegra_connector_get_modes,
+	.mode_valid = tegra_connector_mode_valid,
+	.best_encoder = tegra_connector_best_encoder,
+};
+
+static enum drm_connector_status
+tegra_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct tegra_output *output = connector_to_output(connector);
+	enum drm_connector_status status = connector_status_unknown;
+
+	if (gpio_is_valid(output->hpd_gpio)) {
+		if (gpio_get_value(output->hpd_gpio) == 0)
+			status = connector_status_disconnected;
+		else
+			status = connector_status_connected;
+	} else {
+		if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
+			status = connector_status_connected;
+	}
+
+	return status;
+}
+
+static void tegra_connector_destroy(struct drm_connector *connector)
+{
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.detect = tegra_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = tegra_connector_destroy,
+};
+
+static void tegra_encoder_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs encoder_funcs = {
+	.destroy = tegra_encoder_destroy,
+};
+
+static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+}
+
+static bool tegra_encoder_mode_fixup(struct drm_encoder *encoder,
+				     const struct drm_display_mode *mode,
+				     struct drm_display_mode *adjusted)
+{
+	return true;
+}
+
+static void tegra_encoder_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void tegra_encoder_commit(struct drm_encoder *encoder)
+{
+}
+
+static void tegra_encoder_mode_set(struct drm_encoder *encoder,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted)
+{
+	struct tegra_output *output = encoder_to_output(encoder);
+	int err;
+
+	err = tegra_output_enable(output);
+	if (err < 0)
+		dev_err(encoder->dev->dev, "tegra_output_enable(): %d\n", err);
+}
+
+static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
+	.dpms = tegra_encoder_dpms,
+	.mode_fixup = tegra_encoder_mode_fixup,
+	.prepare = tegra_encoder_prepare,
+	.commit = tegra_encoder_commit,
+	.mode_set = tegra_encoder_mode_set,
+};
+
+static irqreturn_t hpd_irq(int irq, void *data)
+{
+	struct tegra_output *output = data;
+
+	drm_helper_hpd_irq_event(output->connector.dev);
+
+	return IRQ_HANDLED;
+}
+
+int tegra_output_parse_dt(struct tegra_output *output)
+{
+	enum of_gpio_flags flags;
+	struct device_node *ddc;
+	size_t size;
+	int err;
+
+	if (!output->of_node)
+		output->of_node = output->dev->of_node;
+
+	output->edid = of_get_property(output->of_node, "nvidia,edid", &size);
+
+	ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0);
+	if (ddc) {
+		output->ddc = of_find_i2c_adapter_by_node(ddc);
+		if (!output->ddc) {
+			err = -EPROBE_DEFER;
+			of_node_put(ddc);
+			return err;
+		}
+
+		of_node_put(ddc);
+	}
+
+	if (!output->edid && !output->ddc)
+		return -ENODEV;
+
+	output->hpd_gpio = of_get_named_gpio_flags(output->of_node,
+						   "nvidia,hpd-gpio", 0,
+						   &flags);
+
+	return 0;
+}
+
+int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
+{
+	int connector, encoder, err;
+
+	if (gpio_is_valid(output->hpd_gpio)) {
+		unsigned long flags;
+
+		err = gpio_request_one(output->hpd_gpio, GPIOF_DIR_IN,
+				       "HDMI hotplug detect");
+		if (err < 0) {
+			dev_err(output->dev, "gpio_request_one(): %d\n", err);
+			return err;
+		}
+
+		err = gpio_to_irq(output->hpd_gpio);
+		if (err < 0) {
+			dev_err(output->dev, "gpio_to_irq(): %d\n", err);
+			goto free_hpd;
+		}
+
+		output->hpd_irq = err;
+
+		flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+			IRQF_ONESHOT;
+
+		err = request_threaded_irq(output->hpd_irq, NULL, hpd_irq,
+					   flags, "hpd", output);
+		if (err < 0) {
+			dev_err(output->dev, "failed to request IRQ#%u: %d\n",
+				output->hpd_irq, err);
+			goto free_hpd;
+		}
+
+		output->connector.polled = DRM_CONNECTOR_POLL_HPD;
+	}
+
+	switch (output->type) {
+	case TEGRA_OUTPUT_RGB:
+		connector = DRM_MODE_CONNECTOR_LVDS;
+		encoder = DRM_MODE_ENCODER_LVDS;
+		break;
+
+	case TEGRA_OUTPUT_HDMI:
+		connector = DRM_MODE_CONNECTOR_HDMIA;
+		encoder = DRM_MODE_ENCODER_TMDS;
+		break;
+
+	default:
+		connector = DRM_MODE_CONNECTOR_Unknown;
+		encoder = DRM_MODE_ENCODER_NONE;
+		break;
+	}
+
+	drm_connector_init(drm, &output->connector, &connector_funcs,
+			   connector);
+	drm_connector_helper_add(&output->connector, &connector_helper_funcs);
+
+	drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder);
+	drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs);
+
+	drm_mode_connector_attach_encoder(&output->connector, &output->encoder);
+	drm_sysfs_connector_add(&output->connector);
+
+	output->encoder.possible_crtcs = 0x3;
+
+	return 0;
+
+free_hpd:
+	gpio_free(output->hpd_gpio);
+
+	return err;
+}
+
+int tegra_output_exit(struct tegra_output *output)
+{
+	if (gpio_is_valid(output->hpd_gpio)) {
+		free_irq(output->hpd_irq, output);
+		gpio_free(output->hpd_gpio);
+	}
+
+	if (output->ddc)
+		put_device(&output->ddc->dev);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c
new file mode 100644
index 0000000..ed4416f
--- /dev/null
+++ b/drivers/gpu/drm/tegra/rgb.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "drm.h"
+#include "dc.h"
+
+struct tegra_rgb {
+	struct tegra_output output;
+	struct clk *clk_parent;
+	struct clk *clk;
+};
+
+static inline struct tegra_rgb *to_rgb(struct tegra_output *output)
+{
+	return container_of(output, struct tegra_rgb, output);
+}
+
+struct reg_entry {
+	unsigned long offset;
+	unsigned long value;
+};
+
+static const struct reg_entry rgb_enable[] = {
+	{ DC_COM_PIN_OUTPUT_ENABLE(0),   0x00000000 },
+	{ DC_COM_PIN_OUTPUT_ENABLE(1),   0x00000000 },
+	{ DC_COM_PIN_OUTPUT_ENABLE(2),   0x00000000 },
+	{ DC_COM_PIN_OUTPUT_ENABLE(3),   0x00000000 },
+	{ DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 },
+	{ DC_COM_PIN_OUTPUT_POLARITY(1), 0x01000000 },
+	{ DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 },
+	{ DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 },
+	{ DC_COM_PIN_OUTPUT_DATA(0),     0x00000000 },
+	{ DC_COM_PIN_OUTPUT_DATA(1),     0x00000000 },
+	{ DC_COM_PIN_OUTPUT_DATA(2),     0x00000000 },
+	{ DC_COM_PIN_OUTPUT_DATA(3),     0x00000000 },
+	{ DC_COM_PIN_OUTPUT_SELECT(0),   0x00000000 },
+	{ DC_COM_PIN_OUTPUT_SELECT(1),   0x00000000 },
+	{ DC_COM_PIN_OUTPUT_SELECT(2),   0x00000000 },
+	{ DC_COM_PIN_OUTPUT_SELECT(3),   0x00000000 },
+	{ DC_COM_PIN_OUTPUT_SELECT(4),   0x00210222 },
+	{ DC_COM_PIN_OUTPUT_SELECT(5),   0x00002200 },
+	{ DC_COM_PIN_OUTPUT_SELECT(6),   0x00020000 },
+};
+
+static const struct reg_entry rgb_disable[] = {
+	{ DC_COM_PIN_OUTPUT_SELECT(6),   0x00000000 },
+	{ DC_COM_PIN_OUTPUT_SELECT(5),   0x00000000 },
+	{ DC_COM_PIN_OUTPUT_SELECT(4),   0x00000000 },
+	{ DC_COM_PIN_OUTPUT_SELECT(3),   0x00000000 },
+	{ DC_COM_PIN_OUTPUT_SELECT(2),   0x00000000 },
+	{ DC_COM_PIN_OUTPUT_SELECT(1),   0x00000000 },
+	{ DC_COM_PIN_OUTPUT_SELECT(0),   0x00000000 },
+	{ DC_COM_PIN_OUTPUT_DATA(3),     0xaaaaaaaa },
+	{ DC_COM_PIN_OUTPUT_DATA(2),     0xaaaaaaaa },
+	{ DC_COM_PIN_OUTPUT_DATA(1),     0xaaaaaaaa },
+	{ DC_COM_PIN_OUTPUT_DATA(0),     0xaaaaaaaa },
+	{ DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 },
+	{ DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 },
+	{ DC_COM_PIN_OUTPUT_POLARITY(1), 0x00000000 },
+	{ DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 },
+	{ DC_COM_PIN_OUTPUT_ENABLE(3),   0x55555555 },
+	{ DC_COM_PIN_OUTPUT_ENABLE(2),   0x55555555 },
+	{ DC_COM_PIN_OUTPUT_ENABLE(1),   0x55150005 },
+	{ DC_COM_PIN_OUTPUT_ENABLE(0),   0x55555555 },
+};
+
+static void tegra_dc_write_regs(struct tegra_dc *dc,
+				const struct reg_entry *table,
+				unsigned int num)
+{
+	unsigned int i;
+
+	for (i = 0; i < num; i++)
+		tegra_dc_writel(dc, table[i].value, table[i].offset);
+}
+
+static int tegra_output_rgb_enable(struct tegra_output *output)
+{
+	struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+
+	tegra_dc_write_regs(dc, rgb_enable, ARRAY_SIZE(rgb_enable));
+
+	return 0;
+}
+
+static int tegra_output_rgb_disable(struct tegra_output *output)
+{
+	struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+
+	tegra_dc_write_regs(dc, rgb_disable, ARRAY_SIZE(rgb_disable));
+
+	return 0;
+}
+
+static int tegra_output_rgb_setup_clock(struct tegra_output *output,
+					struct clk *clk, unsigned long pclk)
+{
+	struct tegra_rgb *rgb = to_rgb(output);
+
+	return clk_set_parent(clk, rgb->clk_parent);
+}
+
+static int tegra_output_rgb_check_mode(struct tegra_output *output,
+				       struct drm_display_mode *mode,
+				       enum drm_mode_status *status)
+{
+	/*
+	 * FIXME: For now, always assume that the mode is okay. There are
+	 * unresolved issues with clk_round_rate(), which doesn't always
+	 * reliably report whether a frequency can be set or not.
+	 */
+
+	*status = MODE_OK;
+
+	return 0;
+}
+
+static const struct tegra_output_ops rgb_ops = {
+	.enable = tegra_output_rgb_enable,
+	.disable = tegra_output_rgb_disable,
+	.setup_clock = tegra_output_rgb_setup_clock,
+	.check_mode = tegra_output_rgb_check_mode,
+};
+
+int tegra_dc_rgb_probe(struct tegra_dc *dc)
+{
+	struct device_node *np;
+	struct tegra_rgb *rgb;
+	int err;
+
+	np = of_get_child_by_name(dc->dev->of_node, "rgb");
+	if (!np || !of_device_is_available(np))
+		return -ENODEV;
+
+	rgb = devm_kzalloc(dc->dev, sizeof(*rgb), GFP_KERNEL);
+	if (!rgb)
+		return -ENOMEM;
+
+	rgb->clk = devm_clk_get(dc->dev, NULL);
+	if (IS_ERR(rgb->clk)) {
+		dev_err(dc->dev, "failed to get clock\n");
+		return PTR_ERR(rgb->clk);
+	}
+
+	rgb->clk_parent = devm_clk_get(dc->dev, "parent");
+	if (IS_ERR(rgb->clk_parent)) {
+		dev_err(dc->dev, "failed to get parent clock\n");
+		return PTR_ERR(rgb->clk_parent);
+	}
+
+	err = clk_set_parent(rgb->clk, rgb->clk_parent);
+	if (err < 0) {
+		dev_err(dc->dev, "failed to set parent clock: %d\n", err);
+		return err;
+	}
+
+	rgb->output.dev = dc->dev;
+	rgb->output.of_node = np;
+
+	err = tegra_output_parse_dt(&rgb->output);
+	if (err < 0)
+		return err;
+
+	dc->rgb = &rgb->output;
+
+	return 0;
+}
+
+int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc)
+{
+	struct tegra_rgb *rgb = to_rgb(dc->rgb);
+	int err;
+
+	if (!dc->rgb)
+		return -ENODEV;
+
+	rgb->output.type = TEGRA_OUTPUT_RGB;
+	rgb->output.ops = &rgb_ops;
+
+	err = tegra_output_init(dc->base.dev, &rgb->output);
+	if (err < 0) {
+		dev_err(dc->dev, "output setup failed: %d\n", err);
+		return err;
+	}
+
+	/*
+	 * By default, outputs can be associated with each display controller.
+	 * RGB outputs are an exception, so we make sure they can be attached
+	 * to only their parent display controller.
+	 */
+	rgb->output.encoder.possible_crtcs = 1 << dc->pipe;
+
+	return 0;
+}
+
+int tegra_dc_rgb_exit(struct tegra_dc *dc)
+{
+	if (dc->rgb) {
+		int err;
+
+		err = tegra_output_disable(dc->rgb);
+		if (err < 0) {
+			dev_err(dc->dev, "output failed to disable: %d\n", err);
+			return err;
+		}
+
+		err = tegra_output_exit(dc->rgb);
+		if (err < 0) {
+			dev_err(dc->dev, "output cleanup failed: %d\n", err);
+			return err;
+		}
+
+		dc->rgb = NULL;
+	}
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index bf6e4b5..2c54c3d 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -162,9 +162,9 @@ int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo, bool interruptible)
 {
 	if (interruptible) {
 		return wait_event_interruptible(bo->event_queue,
-					       atomic_read(&bo->reserved) == 0);
+					       !ttm_bo_is_reserved(bo));
 	} else {
-		wait_event(bo->event_queue, atomic_read(&bo->reserved) == 0);
+		wait_event(bo->event_queue, !ttm_bo_is_reserved(bo));
 		return 0;
 	}
 }
@@ -175,7 +175,7 @@ void ttm_bo_add_to_lru(struct ttm_buffer_object *bo)
 	struct ttm_bo_device *bdev = bo->bdev;
 	struct ttm_mem_type_manager *man;
 
-	BUG_ON(!atomic_read(&bo->reserved));
+	BUG_ON(!ttm_bo_is_reserved(bo));
 
 	if (!(bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) {
 
@@ -220,7 +220,7 @@ int ttm_bo_reserve_locked(struct ttm_buffer_object *bo,
 	struct ttm_bo_global *glob = bo->glob;
 	int ret;
 
-	while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) {
+	while (unlikely(atomic_read(&bo->reserved) != 0)) {
 		/**
 		 * Deadlock avoidance for multi-bo reserving.
 		 */
@@ -249,6 +249,7 @@ int ttm_bo_reserve_locked(struct ttm_buffer_object *bo,
 			return ret;
 	}
 
+	atomic_set(&bo->reserved, 1);
 	if (use_sequence) {
 		/**
 		 * Wake up waiters that may need to recheck for deadlock,
@@ -501,7 +502,6 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)
 	struct ttm_bo_global *glob = bo->glob;
 	struct ttm_bo_driver *driver;
 	void *sync_obj = NULL;
-	void *sync_obj_arg;
 	int put_count;
 	int ret;
 
@@ -537,7 +537,6 @@ queue:
 	driver = bdev->driver;
 	if (bo->sync_obj)
 		sync_obj = driver->sync_obj_ref(bo->sync_obj);
-	sync_obj_arg = bo->sync_obj_arg;
 
 	kref_get(&bo->list_kref);
 	list_add_tail(&bo->ddestroy, &bdev->ddestroy);
@@ -545,7 +544,7 @@ queue:
 	spin_unlock(&bdev->fence_lock);
 
 	if (sync_obj) {
-		driver->sync_obj_flush(sync_obj, sync_obj_arg);
+		driver->sync_obj_flush(sync_obj);
 		driver->sync_obj_unref(&sync_obj);
 	}
 	schedule_delayed_work(&bdev->wq,
@@ -697,6 +696,7 @@ static void ttm_bo_release(struct kref *kref)
 	struct ttm_bo_device *bdev = bo->bdev;
 	struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type];
 
+	write_lock(&bdev->vm_lock);
 	if (likely(bo->vm_node != NULL)) {
 		rb_erase(&bo->vm_rb, &bdev->addr_space_rb);
 		drm_mm_put_block(bo->vm_node);
@@ -708,18 +708,14 @@ static void ttm_bo_release(struct kref *kref)
 	ttm_mem_io_unlock(man);
 	ttm_bo_cleanup_refs_or_queue(bo);
 	kref_put(&bo->list_kref, ttm_bo_release_list);
-	write_lock(&bdev->vm_lock);
 }
 
 void ttm_bo_unref(struct ttm_buffer_object **p_bo)
 {
 	struct ttm_buffer_object *bo = *p_bo;
-	struct ttm_bo_device *bdev = bo->bdev;
 
 	*p_bo = NULL;
-	write_lock(&bdev->vm_lock);
 	kref_put(&bo->kref, ttm_bo_release);
-	write_unlock(&bdev->vm_lock);
 }
 EXPORT_SYMBOL(ttm_bo_unref);
 
@@ -756,7 +752,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible,
 		goto out;
 	}
 
-	BUG_ON(!atomic_read(&bo->reserved));
+	BUG_ON(!ttm_bo_is_reserved(bo));
 
 	evict_mem = bo->mem;
 	evict_mem.mm_node = NULL;
@@ -1054,16 +1050,6 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
 }
 EXPORT_SYMBOL(ttm_bo_mem_space);
 
-int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool no_wait)
-{
-	if ((atomic_read(&bo->cpu_writers) > 0) && no_wait)
-		return -EBUSY;
-
-	return wait_event_interruptible(bo->event_queue,
-					atomic_read(&bo->cpu_writers) == 0);
-}
-EXPORT_SYMBOL(ttm_bo_wait_cpu);
-
 int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
 			struct ttm_placement *placement,
 			bool interruptible, bool no_wait_reserve,
@@ -1073,7 +1059,7 @@ int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
 	struct ttm_mem_reg mem;
 	struct ttm_bo_device *bdev = bo->bdev;
 
-	BUG_ON(!atomic_read(&bo->reserved));
+	BUG_ON(!ttm_bo_is_reserved(bo));
 
 	/*
 	 * FIXME: It's possible to pipeline buffer moves.
@@ -1130,7 +1116,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
 {
 	int ret;
 
-	BUG_ON(!atomic_read(&bo->reserved));
+	BUG_ON(!ttm_bo_is_reserved(bo));
 	/* Check that range is valid */
 	if (placement->lpfn || placement->fpfn)
 		if (placement->fpfn > placement->lpfn ||
@@ -1179,7 +1165,6 @@ int ttm_bo_init(struct ttm_bo_device *bdev,
 		enum ttm_bo_type type,
 		struct ttm_placement *placement,
 		uint32_t page_alignment,
-		unsigned long buffer_start,
 		bool interruptible,
 		struct file *persistent_swap_storage,
 		size_t acc_size,
@@ -1200,7 +1185,6 @@ int ttm_bo_init(struct ttm_bo_device *bdev,
 		return -ENOMEM;
 	}
 
-	size += buffer_start & ~PAGE_MASK;
 	num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	if (num_pages == 0) {
 		pr_err("Illegal buffer object size\n");
@@ -1233,7 +1217,6 @@ int ttm_bo_init(struct ttm_bo_device *bdev,
 	bo->mem.page_alignment = page_alignment;
 	bo->mem.bus.io_reserved_vm = false;
 	bo->mem.bus.io_reserved_count = 0;
-	bo->buffer_start = buffer_start & PAGE_MASK;
 	bo->priv_flags = 0;
 	bo->mem.placement = (TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED);
 	bo->seq_valid = false;
@@ -1306,7 +1289,6 @@ int ttm_bo_create(struct ttm_bo_device *bdev,
 			enum ttm_bo_type type,
 			struct ttm_placement *placement,
 			uint32_t page_alignment,
-			unsigned long buffer_start,
 			bool interruptible,
 			struct file *persistent_swap_storage,
 			struct ttm_buffer_object **p_bo)
@@ -1321,8 +1303,8 @@ int ttm_bo_create(struct ttm_bo_device *bdev,
 
 	acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct ttm_buffer_object));
 	ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment,
-				buffer_start, interruptible,
-			  persistent_swap_storage, acc_size, NULL, NULL);
+			  interruptible, persistent_swap_storage, acc_size,
+			  NULL, NULL);
 	if (likely(ret == 0))
 		*p_bo = bo;
 
@@ -1577,7 +1559,6 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev,
 		goto out_no_addr_mm;
 
 	INIT_DELAYED_WORK(&bdev->wq, ttm_bo_delayed_workqueue);
-	bdev->nice_mode = true;
 	INIT_LIST_HEAD(&bdev->ddestroy);
 	bdev->dev_mapping = NULL;
 	bdev->glob = glob;
@@ -1721,7 +1702,6 @@ int ttm_bo_wait(struct ttm_buffer_object *bo,
 	struct ttm_bo_driver *driver = bo->bdev->driver;
 	struct ttm_bo_device *bdev = bo->bdev;
 	void *sync_obj;
-	void *sync_obj_arg;
 	int ret = 0;
 
 	if (likely(bo->sync_obj == NULL))
@@ -1729,7 +1709,7 @@ int ttm_bo_wait(struct ttm_buffer_object *bo,
 
 	while (bo->sync_obj) {
 
-		if (driver->sync_obj_signaled(bo->sync_obj, bo->sync_obj_arg)) {
+		if (driver->sync_obj_signaled(bo->sync_obj)) {
 			void *tmp_obj = bo->sync_obj;
 			bo->sync_obj = NULL;
 			clear_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags);
@@ -1743,9 +1723,8 @@ int ttm_bo_wait(struct ttm_buffer_object *bo,
 			return -EBUSY;
 
 		sync_obj = driver->sync_obj_ref(bo->sync_obj);
-		sync_obj_arg = bo->sync_obj_arg;
 		spin_unlock(&bdev->fence_lock);
-		ret = driver->sync_obj_wait(sync_obj, sync_obj_arg,
+		ret = driver->sync_obj_wait(sync_obj,
 					    lazy, interruptible);
 		if (unlikely(ret != 0)) {
 			driver->sync_obj_unref(&sync_obj);
@@ -1753,8 +1732,7 @@ int ttm_bo_wait(struct ttm_buffer_object *bo,
 			return ret;
 		}
 		spin_lock(&bdev->fence_lock);
-		if (likely(bo->sync_obj == sync_obj &&
-			   bo->sync_obj_arg == sync_obj_arg)) {
+		if (likely(bo->sync_obj == sync_obj)) {
 			void *tmp_obj = bo->sync_obj;
 			bo->sync_obj = NULL;
 			clear_bit(TTM_BO_PRIV_FLAG_MOVING,
@@ -1797,8 +1775,7 @@ EXPORT_SYMBOL(ttm_bo_synccpu_write_grab);
 
 void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo)
 {
-	if (atomic_dec_and_test(&bo->cpu_writers))
-		wake_up_all(&bo->event_queue);
+	atomic_dec(&bo->cpu_writers);
 }
 EXPORT_SYMBOL(ttm_bo_synccpu_write_release);
 
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index 2026060..b9c4e51 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -611,7 +611,6 @@ EXPORT_SYMBOL(ttm_bo_kunmap);
 
 int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
 			      void *sync_obj,
-			      void *sync_obj_arg,
 			      bool evict, bool no_wait_reserve,
 			      bool no_wait_gpu,
 			      struct ttm_mem_reg *new_mem)
@@ -630,7 +629,6 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
 		bo->sync_obj = NULL;
 	}
 	bo->sync_obj = driver->sync_obj_ref(sync_obj);
-	bo->sync_obj_arg = sync_obj_arg;
 	if (evict) {
 		ret = ttm_bo_wait(bo, false, false, false);
 		spin_unlock(&bdev->fence_lock);
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index 3ba72db..74705f3 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -259,8 +259,8 @@ int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma,
 	read_lock(&bdev->vm_lock);
 	bo = ttm_bo_vm_lookup_rb(bdev, vma->vm_pgoff,
 				 (vma->vm_end - vma->vm_start) >> PAGE_SHIFT);
-	if (likely(bo != NULL))
-		ttm_bo_reference(bo);
+	if (likely(bo != NULL) && !kref_get_unless_zero(&bo->kref))
+		bo = NULL;
 	read_unlock(&bdev->vm_lock);
 
 	if (unlikely(bo == NULL)) {
diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
index 1937069..1986d00 100644
--- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c
+++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
@@ -185,10 +185,7 @@ retry_this_bo:
 			ttm_eu_backoff_reservation_locked(list);
 			spin_unlock(&glob->lru_lock);
 			ttm_eu_list_ref_sub(list);
-			ret = ttm_bo_wait_cpu(bo, false);
-			if (ret)
-				return ret;
-			goto retry;
+			return -EBUSY;
 		}
 	}
 
@@ -223,7 +220,6 @@ void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj)
 		bo = entry->bo;
 		entry->old_sync_obj = bo->sync_obj;
 		bo->sync_obj = driver->sync_obj_ref(sync_obj);
-		bo->sync_obj_arg = entry->new_sync_obj_arg;
 		ttm_bo_unreserve_locked(bo);
 		entry->reserved = false;
 	}
diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c
index 479c6b0..dbc2def 100644
--- a/drivers/gpu/drm/ttm/ttm_memory.c
+++ b/drivers/gpu/drm/ttm/ttm_memory.c
@@ -367,7 +367,6 @@ int ttm_mem_global_init(struct ttm_mem_global *glob)
 	spin_lock_init(&glob->lock);
 	glob->swap_queue = create_singlethread_workqueue("ttm_swap");
 	INIT_WORK(&glob->work, ttm_shrink_work);
-	init_waitqueue_head(&glob->queue);
 	ret = kobject_init_and_add(
 		&glob->kobj, &ttm_mem_glob_kobj_type, ttm_get_kobj(), "memory_accounting");
 	if (unlikely(ret != 0)) {
diff --git a/drivers/gpu/drm/ttm/ttm_object.c b/drivers/gpu/drm/ttm/ttm_object.c
index c785787..58a5f32 100644
--- a/drivers/gpu/drm/ttm/ttm_object.c
+++ b/drivers/gpu/drm/ttm/ttm_object.c
@@ -80,7 +80,7 @@ struct ttm_object_file {
  */
 
 struct ttm_object_device {
-	rwlock_t object_lock;
+	spinlock_t object_lock;
 	struct drm_open_hash object_hash;
 	atomic_t object_count;
 	struct ttm_mem_global *mem_glob;
@@ -157,12 +157,12 @@ int ttm_base_object_init(struct ttm_object_file *tfile,
 	base->refcount_release = refcount_release;
 	base->ref_obj_release = ref_obj_release;
 	base->object_type = object_type;
-	write_lock(&tdev->object_lock);
 	kref_init(&base->refcount);
-	ret = drm_ht_just_insert_please(&tdev->object_hash,
-					&base->hash,
-					(unsigned long)base, 31, 0, 0);
-	write_unlock(&tdev->object_lock);
+	spin_lock(&tdev->object_lock);
+	ret = drm_ht_just_insert_please_rcu(&tdev->object_hash,
+					    &base->hash,
+					    (unsigned long)base, 31, 0, 0);
+	spin_unlock(&tdev->object_lock);
 	if (unlikely(ret != 0))
 		goto out_err0;
 
@@ -174,7 +174,9 @@ int ttm_base_object_init(struct ttm_object_file *tfile,
 
 	return 0;
 out_err1:
-	(void)drm_ht_remove_item(&tdev->object_hash, &base->hash);
+	spin_lock(&tdev->object_lock);
+	(void)drm_ht_remove_item_rcu(&tdev->object_hash, &base->hash);
+	spin_unlock(&tdev->object_lock);
 out_err0:
 	return ret;
 }
@@ -186,30 +188,29 @@ static void ttm_release_base(struct kref *kref)
 	    container_of(kref, struct ttm_base_object, refcount);
 	struct ttm_object_device *tdev = base->tfile->tdev;
 
-	(void)drm_ht_remove_item(&tdev->object_hash, &base->hash);
-	write_unlock(&tdev->object_lock);
+	spin_lock(&tdev->object_lock);
+	(void)drm_ht_remove_item_rcu(&tdev->object_hash, &base->hash);
+	spin_unlock(&tdev->object_lock);
+
+	/*
+	 * Note: We don't use synchronize_rcu() here because it's far
+	 * too slow. It's up to the user to free the object using
+	 * call_rcu() or ttm_base_object_kfree().
+	 */
+
 	if (base->refcount_release) {
 		ttm_object_file_unref(&base->tfile);
 		base->refcount_release(&base);
 	}
-	write_lock(&tdev->object_lock);
 }
 
 void ttm_base_object_unref(struct ttm_base_object **p_base)
 {
 	struct ttm_base_object *base = *p_base;
-	struct ttm_object_device *tdev = base->tfile->tdev;
 
 	*p_base = NULL;
 
-	/*
-	 * Need to take the lock here to avoid racing with
-	 * users trying to look up the object.
-	 */
-
-	write_lock(&tdev->object_lock);
 	kref_put(&base->refcount, ttm_release_base);
-	write_unlock(&tdev->object_lock);
 }
 EXPORT_SYMBOL(ttm_base_object_unref);
 
@@ -221,14 +222,14 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
 	struct drm_hash_item *hash;
 	int ret;
 
-	read_lock(&tdev->object_lock);
-	ret = drm_ht_find_item(&tdev->object_hash, key, &hash);
+	rcu_read_lock();
+	ret = drm_ht_find_item_rcu(&tdev->object_hash, key, &hash);
 
 	if (likely(ret == 0)) {
 		base = drm_hash_entry(hash, struct ttm_base_object, hash);
-		kref_get(&base->refcount);
+		ret = kref_get_unless_zero(&base->refcount) ? 0 : -EINVAL;
 	}
-	read_unlock(&tdev->object_lock);
+	rcu_read_unlock();
 
 	if (unlikely(ret != 0))
 		return NULL;
@@ -426,7 +427,7 @@ struct ttm_object_device *ttm_object_device_init(struct ttm_mem_global
 		return NULL;
 
 	tdev->mem_glob = mem_glob;
-	rwlock_init(&tdev->object_lock);
+	spin_lock_init(&tdev->object_lock);
 	atomic_set(&tdev->object_count, 0);
 	ret = drm_ht_create(&tdev->object_hash, hash_order);
 
@@ -444,9 +445,9 @@ void ttm_object_device_release(struct ttm_object_device **p_tdev)
 
 	*p_tdev = NULL;
 
-	write_lock(&tdev->object_lock);
+	spin_lock(&tdev->object_lock);
 	drm_ht_remove(&tdev->object_hash);
-	write_unlock(&tdev->object_lock);
+	spin_unlock(&tdev->object_lock);
 
 	kfree(tdev);
 }
diff --git a/drivers/gpu/drm/udl/Kconfig b/drivers/gpu/drm/udl/Kconfig
index 56e0bf3..6222af1 100644
--- a/drivers/gpu/drm/udl/Kconfig
+++ b/drivers/gpu/drm/udl/Kconfig
@@ -1,6 +1,6 @@
 config DRM_UDL
 	tristate "DisplayLink"
-	depends on DRM && EXPERIMENTAL
+	depends on DRM
 	depends on USB_ARCH_HAS_HCD
 	select DRM_USB
 	select FB_SYS_FILLRECT
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
index b3b2ced..25b93de 100644
--- a/drivers/gpu/drm/udl/udl_connector.c
+++ b/drivers/gpu/drm/udl/udl_connector.c
@@ -84,7 +84,8 @@ udl_detect(struct drm_connector *connector, bool force)
 	return connector_status_connected;
 }
 
-struct drm_encoder *udl_best_single_encoder(struct drm_connector *connector)
+static struct drm_encoder*
+udl_best_single_encoder(struct drm_connector *connector)
 {
 	int enc_id = connector->encoder_ids[0];
 	struct drm_mode_object *obj;
@@ -97,8 +98,9 @@ struct drm_encoder *udl_best_single_encoder(struct drm_connector *connector)
 	return encoder;
 }
 
-int udl_connector_set_property(struct drm_connector *connector, struct drm_property *property,
-			       uint64_t val)
+static int udl_connector_set_property(struct drm_connector *connector,
+				      struct drm_property *property,
+				      uint64_t val)
 {
 	return 0;
 }
@@ -110,13 +112,13 @@ static void udl_connector_destroy(struct drm_connector *connector)
 	kfree(connector);
 }
 
-struct drm_connector_helper_funcs udl_connector_helper_funcs = {
+static struct drm_connector_helper_funcs udl_connector_helper_funcs = {
 	.get_modes = udl_get_modes,
 	.mode_valid = udl_mode_valid,
 	.best_encoder = udl_best_single_encoder,
 };
 
-struct drm_connector_funcs udl_connector_funcs = {
+static struct drm_connector_funcs udl_connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
 	.detect = udl_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile
index 586869c..2cc6cd9 100644
--- a/drivers/gpu/drm/vmwgfx/Makefile
+++ b/drivers/gpu/drm/vmwgfx/Makefile
@@ -5,6 +5,7 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
 	    vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \
 	    vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
 	    vmwgfx_overlay.o vmwgfx_marker.o vmwgfx_gmrid_manager.o \
-	    vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o
+	    vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o vmwgfx_context.o \
+	    vmwgfx_surface.o
 
 obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
diff --git a/drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h b/drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h
new file mode 100644
index 0000000..8369c3b
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h
@@ -0,0 +1,909 @@
+/**************************************************************************
+ *
+ * Copyright © 2008-2012 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifdef __KERNEL__
+
+#include <drm/vmwgfx_drm.h>
+#define surf_size_struct struct drm_vmw_size
+
+#else /* __KERNEL__ */
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(_A) (sizeof(_A) / sizeof((_A)[0]))
+#endif /* ARRAY_SIZE */
+
+#define DIV_ROUND_UP(x, y)  (((x) + (y) - 1) / (y))
+#define max_t(type, x, y)  ((x) > (y) ? (x) : (y))
+#define surf_size_struct SVGA3dSize
+#define u32 uint32
+
+#endif /* __KERNEL__ */
+
+#include "svga3d_reg.h"
+
+/*
+ * enum svga3d_block_desc describes the active data channels in a block.
+ *
+ * There can be at-most four active channels in a block:
+ *    1. Red, bump W, luminance and depth are stored in the first channel.
+ *    2. Green, bump V and stencil are stored in the second channel.
+ *    3. Blue and bump U are stored in the third channel.
+ *    4. Alpha and bump Q are stored in the fourth channel.
+ *
+ * Block channels can be used to store compressed and buffer data:
+ *    1. For compressed formats, only the data channel is used and its size
+ *       is equal to that of a singular block in the compression scheme.
+ *    2. For buffer formats, only the data channel is used and its size is
+ *       exactly one byte in length.
+ *    3. In each case the bit depth represent the size of a singular block.
+ *
+ * Note: Compressed and IEEE formats do not use the bitMask structure.
+ */
+
+enum svga3d_block_desc {
+	SVGA3DBLOCKDESC_NONE        = 0,         /* No channels are active */
+	SVGA3DBLOCKDESC_BLUE        = 1 << 0,    /* Block with red channel
+						    data */
+	SVGA3DBLOCKDESC_U           = 1 << 0,    /* Block with bump U channel
+						    data */
+	SVGA3DBLOCKDESC_UV_VIDEO    = 1 << 7,    /* Block with alternating video
+						    U and V */
+	SVGA3DBLOCKDESC_GREEN       = 1 << 1,    /* Block with green channel
+						    data */
+	SVGA3DBLOCKDESC_V           = 1 << 1,    /* Block with bump V channel
+						    data */
+	SVGA3DBLOCKDESC_STENCIL     = 1 << 1,    /* Block with a stencil
+						    channel */
+	SVGA3DBLOCKDESC_RED         = 1 << 2,    /* Block with blue channel
+						    data */
+	SVGA3DBLOCKDESC_W           = 1 << 2,    /* Block with bump W channel
+						    data */
+	SVGA3DBLOCKDESC_LUMINANCE   = 1 << 2,    /* Block with luminance channel
+						    data */
+	SVGA3DBLOCKDESC_Y           = 1 << 2,    /* Block with video luminance
+						    data */
+	SVGA3DBLOCKDESC_DEPTH       = 1 << 2,    /* Block with depth channel */
+	SVGA3DBLOCKDESC_ALPHA       = 1 << 3,    /* Block with an alpha
+						    channel */
+	SVGA3DBLOCKDESC_Q           = 1 << 3,    /* Block with bump Q channel
+						    data */
+	SVGA3DBLOCKDESC_BUFFER      = 1 << 4,    /* Block stores 1 byte of
+						    data */
+	SVGA3DBLOCKDESC_COMPRESSED  = 1 << 5,    /* Block stores n bytes of
+						    data depending on the
+						    compression method used */
+	SVGA3DBLOCKDESC_IEEE_FP     = 1 << 6,    /* Block stores data in an IEEE
+						    floating point
+						    representation in
+						    all channels */
+	SVGA3DBLOCKDESC_PLANAR_YUV  = 1 << 8,    /* Three separate blocks store
+						    data. */
+	SVGA3DBLOCKDESC_U_VIDEO     = 1 << 9,    /* Block with U video data */
+	SVGA3DBLOCKDESC_V_VIDEO     = 1 << 10,   /* Block with V video data */
+	SVGA3DBLOCKDESC_EXP         = 1 << 11,   /* Shared exponent */
+	SVGA3DBLOCKDESC_SRGB        = 1 << 12,   /* Data is in sRGB format */
+	SVGA3DBLOCKDESC_2PLANAR_YUV = 1 << 13,   /* 2 planes of Y, UV,
+						    e.g., NV12. */
+	SVGA3DBLOCKDESC_3PLANAR_YUV = 1 << 14,   /* 3 planes of separate
+						    Y, U, V, e.g., YV12. */
+
+	SVGA3DBLOCKDESC_RG         = SVGA3DBLOCKDESC_RED |
+	SVGA3DBLOCKDESC_GREEN,
+	SVGA3DBLOCKDESC_RGB        = SVGA3DBLOCKDESC_RG |
+	SVGA3DBLOCKDESC_BLUE,
+	SVGA3DBLOCKDESC_RGB_SRGB   = SVGA3DBLOCKDESC_RGB |
+	SVGA3DBLOCKDESC_SRGB,
+	SVGA3DBLOCKDESC_RGBA       = SVGA3DBLOCKDESC_RGB |
+	SVGA3DBLOCKDESC_ALPHA,
+	SVGA3DBLOCKDESC_RGBA_SRGB  = SVGA3DBLOCKDESC_RGBA |
+	SVGA3DBLOCKDESC_SRGB,
+	SVGA3DBLOCKDESC_UV         = SVGA3DBLOCKDESC_U |
+	SVGA3DBLOCKDESC_V,
+	SVGA3DBLOCKDESC_UVL        = SVGA3DBLOCKDESC_UV |
+	SVGA3DBLOCKDESC_LUMINANCE,
+	SVGA3DBLOCKDESC_UVW        = SVGA3DBLOCKDESC_UV |
+	SVGA3DBLOCKDESC_W,
+	SVGA3DBLOCKDESC_UVWA       = SVGA3DBLOCKDESC_UVW |
+	SVGA3DBLOCKDESC_ALPHA,
+	SVGA3DBLOCKDESC_UVWQ       = SVGA3DBLOCKDESC_U |
+	SVGA3DBLOCKDESC_V |
+	SVGA3DBLOCKDESC_W |
+	SVGA3DBLOCKDESC_Q,
+	SVGA3DBLOCKDESC_LA         = SVGA3DBLOCKDESC_LUMINANCE |
+	SVGA3DBLOCKDESC_ALPHA,
+	SVGA3DBLOCKDESC_R_FP       = SVGA3DBLOCKDESC_RED |
+	SVGA3DBLOCKDESC_IEEE_FP,
+	SVGA3DBLOCKDESC_RG_FP      = SVGA3DBLOCKDESC_R_FP |
+	SVGA3DBLOCKDESC_GREEN,
+	SVGA3DBLOCKDESC_RGB_FP     = SVGA3DBLOCKDESC_RG_FP |
+	SVGA3DBLOCKDESC_BLUE,
+	SVGA3DBLOCKDESC_RGBA_FP    = SVGA3DBLOCKDESC_RGB_FP |
+	SVGA3DBLOCKDESC_ALPHA,
+	SVGA3DBLOCKDESC_DS         = SVGA3DBLOCKDESC_DEPTH |
+	SVGA3DBLOCKDESC_STENCIL,
+	SVGA3DBLOCKDESC_YUV        = SVGA3DBLOCKDESC_UV_VIDEO |
+	SVGA3DBLOCKDESC_Y,
+	SVGA3DBLOCKDESC_AYUV       = SVGA3DBLOCKDESC_ALPHA |
+	SVGA3DBLOCKDESC_Y |
+	SVGA3DBLOCKDESC_U_VIDEO |
+	SVGA3DBLOCKDESC_V_VIDEO,
+	SVGA3DBLOCKDESC_RGBE       = SVGA3DBLOCKDESC_RGB |
+	SVGA3DBLOCKDESC_EXP,
+	SVGA3DBLOCKDESC_COMPRESSED_SRGB = SVGA3DBLOCKDESC_COMPRESSED |
+	SVGA3DBLOCKDESC_SRGB,
+	SVGA3DBLOCKDESC_NV12       = SVGA3DBLOCKDESC_PLANAR_YUV |
+	SVGA3DBLOCKDESC_2PLANAR_YUV,
+	SVGA3DBLOCKDESC_YV12       = SVGA3DBLOCKDESC_PLANAR_YUV |
+	SVGA3DBLOCKDESC_3PLANAR_YUV,
+};
+
+/*
+ * SVGA3dSurfaceDesc describes the actual pixel data.
+ *
+ * This structure provides the following information:
+ *    1. Block description.
+ *    2. Dimensions of a block in the surface.
+ *    3. Size of block in bytes.
+ *    4. Bit depth of the pixel data.
+ *    5. Channel bit depths and masks (if applicable).
+ */
+#define SVGA3D_CHANNEL_DEF(type)		\
+	struct {				\
+		union {				\
+			type blue;              \
+			type u;                 \
+			type uv_video;          \
+			type u_video;           \
+		};				\
+		union {				\
+			type green;             \
+			type v;                 \
+			type stencil;           \
+			type v_video;           \
+		};				\
+		union {				\
+			type red;               \
+			type w;                 \
+			type luminance;         \
+			type y;                 \
+			type depth;             \
+			type data;              \
+		};				\
+		union {				\
+			type alpha;             \
+			type q;                 \
+			type exp;               \
+		};				\
+	}
+
+struct svga3d_surface_desc {
+	enum svga3d_block_desc block_desc;
+	surf_size_struct block_size;
+	u32 bytes_per_block;
+	u32 pitch_bytes_per_block;
+
+	struct {
+		u32 total;
+		SVGA3D_CHANNEL_DEF(uint8);
+	} bit_depth;
+
+	struct {
+		SVGA3D_CHANNEL_DEF(uint8);
+	} bit_offset;
+};
+
+static const struct svga3d_surface_desc svga3d_surface_descs[] = {
+	{SVGA3DBLOCKDESC_NONE,
+	 {1, 1, 1},  0, 0, {0, {{0}, {0}, {0}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_FORMAT_INVALID */
+
+	{SVGA3DBLOCKDESC_RGB,
+	 {1, 1, 1},  4, 4, {24, {{8}, {8}, {8}, {0} } },
+	 {{{0}, {8}, {16}, {24} } } },   /* SVGA3D_X8R8G8B8 */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
+	 {{{0}, {8}, {16}, {24} } } },   /* SVGA3D_A8R8G8B8 */
+
+	{SVGA3DBLOCKDESC_RGB,
+	 {1, 1, 1},  2, 2, {16, {{5}, {6}, {5}, {0} } },
+	 {{{0}, {5}, {11}, {0} } } },    /* SVGA3D_R5G6B5 */
+
+	{SVGA3DBLOCKDESC_RGB,
+	 {1, 1, 1},  2, 2, {15, {{5}, {5}, {5}, {0} } },
+	 {{{0}, {5}, {10}, {0} } } },    /* SVGA3D_X1R5G5B5 */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  2, 2, {16, {{5}, {5}, {5}, {1} } },
+	 {{{0}, {5}, {10}, {15} } } },   /* SVGA3D_A1R5G5B5 */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  2, 2, {16, {{4}, {4}, {4}, {4} } },
+	 {{{0}, {4}, {8}, {12} } } },    /* SVGA3D_A4R4G4B4 */
+
+	{SVGA3DBLOCKDESC_DEPTH,
+	 {1, 1, 1},  4, 4, {32, {{0}, {0}, {32}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_Z_D32 */
+
+	{SVGA3DBLOCKDESC_DEPTH,
+	 {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_Z_D16 */
+
+	{SVGA3DBLOCKDESC_DS,
+	 {1, 1, 1},  4, 4, {32, {{0}, {8}, {24}, {0} } },
+	 {{{0}, {24}, {0}, {0} } } },    /* SVGA3D_Z_D24S8 */
+
+	{SVGA3DBLOCKDESC_DS,
+	 {1, 1, 1},  2, 2, {16, {{0}, {1}, {15}, {0} } },
+	 {{{0}, {15}, {0}, {0} } } },    /* SVGA3D_Z_D15S1 */
+
+	{SVGA3DBLOCKDESC_LUMINANCE,
+	 {1, 1, 1},  1, 1, {8, {{0}, {0}, {8}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_LUMINANCE8 */
+
+	{SVGA3DBLOCKDESC_LA,
+	 {1, 1, 1},  1, 1, {8, {{0}, {0}, {4}, {4} } },
+	 {{{0}, {0}, {0}, {4} } } },     /* SVGA3D_LUMINANCE4_ALPHA4 */
+
+	{SVGA3DBLOCKDESC_LUMINANCE,
+	 {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_LUMINANCE16 */
+
+	{SVGA3DBLOCKDESC_LA,
+	 {1, 1, 1},  2, 2, {16, {{0}, {0}, {8}, {8} } },
+	 {{{0}, {0}, {0}, {8} } } },     /* SVGA3D_LUMINANCE8_ALPHA8 */
+
+	{SVGA3DBLOCKDESC_COMPRESSED,
+	 {4, 4, 1},  8, 8, {64, {{0}, {0}, {64}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_DXT1 */
+
+	{SVGA3DBLOCKDESC_COMPRESSED,
+	 {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_DXT2 */
+
+	{SVGA3DBLOCKDESC_COMPRESSED,
+	 {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_DXT3 */
+
+	{SVGA3DBLOCKDESC_COMPRESSED,
+	 {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_DXT4 */
+
+	{SVGA3DBLOCKDESC_COMPRESSED,
+	 {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_DXT5 */
+
+	{SVGA3DBLOCKDESC_UV,
+	 {1, 1, 1},  2, 2, {16, {{0}, {0}, {8}, {8} } },
+	 {{{0}, {0}, {0}, {8} } } },     /* SVGA3D_BUMPU8V8 */
+
+	{SVGA3DBLOCKDESC_UVL,
+	 {1, 1, 1},  2, 2, {16, {{5}, {5}, {6}, {0} } },
+	 {{{11}, {6}, {0}, {0} } } },    /* SVGA3D_BUMPL6V5U5 */
+
+	{SVGA3DBLOCKDESC_UVL,
+	 {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {0} } },
+	 {{{16}, {8}, {0}, {0} } } },    /* SVGA3D_BUMPX8L8V8U8 */
+
+	{SVGA3DBLOCKDESC_UVL,
+	 {1, 1, 1},  3, 3, {24, {{8}, {8}, {8}, {0} } },
+	 {{{16}, {8}, {0}, {0} } } },    /* SVGA3D_BUMPL8V8U8 */
+
+	{SVGA3DBLOCKDESC_RGBA_FP,
+	 {1, 1, 1},  8, 8, {64, {{16}, {16}, {16}, {16} } },
+	 {{{32}, {16}, {0}, {48} } } },  /* SVGA3D_ARGB_S10E5 */
+
+	{SVGA3DBLOCKDESC_RGBA_FP,
+	 {1, 1, 1},  16, 16, {128, {{32}, {32}, {32}, {32} } },
+	 {{{64}, {32}, {0}, {96} } } },  /* SVGA3D_ARGB_S23E8 */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  4, 4, {32, {{10}, {10}, {10}, {2} } },
+	 {{{0}, {10}, {20}, {30} } } },  /* SVGA3D_A2R10G10B10 */
+
+	{SVGA3DBLOCKDESC_UV,
+	 {1, 1, 1},  2, 2, {16, {{8}, {8}, {0}, {0} } },
+	 {{{8}, {0}, {0}, {0} } } },     /* SVGA3D_V8U8 */
+
+	{SVGA3DBLOCKDESC_UVWQ,
+	 {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
+	 {{{24}, {16}, {8}, {0} } } },   /* SVGA3D_Q8W8V8U8 */
+
+	{SVGA3DBLOCKDESC_UV,
+	 {1, 1, 1},  2, 2, {16, {{8}, {8}, {0}, {0} } },
+	 {{{8}, {0}, {0}, {0} } } },     /* SVGA3D_CxV8U8 */
+
+	{SVGA3DBLOCKDESC_UVL,
+	 {1, 1, 1},  4, 4, {24, {{8}, {8}, {8}, {0} } },
+	 {{{16}, {8}, {0}, {0} } } },    /* SVGA3D_X8L8V8U8 */
+
+	{SVGA3DBLOCKDESC_UVWA,
+	 {1, 1, 1},  4, 4, {32, {{10}, {10}, {10}, {2} } },
+	 {{{0}, {10}, {20}, {30} } } },  /* SVGA3D_A2W10V10U10 */
+
+	{SVGA3DBLOCKDESC_ALPHA,
+	 {1, 1, 1},  1, 1, {8, {{0}, {0}, {0}, {8} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_ALPHA8 */
+
+	{SVGA3DBLOCKDESC_R_FP,
+	 {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R_S10E5 */
+
+	{SVGA3DBLOCKDESC_R_FP,
+	 {1, 1, 1},  4, 4, {32, {{0}, {0}, {32}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R_S23E8 */
+
+	{SVGA3DBLOCKDESC_RG_FP,
+	 {1, 1, 1},  4, 4, {32, {{0}, {16}, {16}, {0} } },
+	 {{{0}, {16}, {0}, {0} } } },    /* SVGA3D_RG_S10E5 */
+
+	{SVGA3DBLOCKDESC_RG_FP,
+	 {1, 1, 1},  8, 8, {64, {{0}, {32}, {32}, {0} } },
+	 {{{0}, {32}, {0}, {0} } } },    /* SVGA3D_RG_S23E8 */
+
+	{SVGA3DBLOCKDESC_BUFFER,
+	 {1, 1, 1},  1, 1, {8, {{0}, {0}, {8}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BUFFER */
+
+	{SVGA3DBLOCKDESC_DEPTH,
+	 {1, 1, 1},  4, 4, {32, {{0}, {0}, {24}, {0} } },
+	 {{{0}, {24}, {0}, {0} } } },    /* SVGA3D_Z_D24X8 */
+
+	{SVGA3DBLOCKDESC_UV,
+	 {1, 1, 1},  4, 4, {32, {{16}, {16}, {0}, {0} } },
+	 {{{16}, {0}, {0}, {0} } } },    /* SVGA3D_V16U16 */
+
+	{SVGA3DBLOCKDESC_RG,
+	 {1, 1, 1},  4, 4, {32, {{0}, {16}, {16}, {0} } },
+	 {{{0}, {0}, {16}, {0} } } },    /* SVGA3D_G16R16 */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  8, 8, {64, {{16}, {16}, {16}, {16} } },
+	 {{{32}, {16}, {0}, {48} } } },  /* SVGA3D_A16B16G16R16 */
+
+	{SVGA3DBLOCKDESC_YUV,
+	 {1, 1, 1},  2, 2, {16, {{8}, {0}, {8}, {0} } },
+	 {{{0}, {0}, {8}, {0} } } },     /* SVGA3D_UYVY */
+
+	{SVGA3DBLOCKDESC_YUV,
+	 {1, 1, 1},  2, 2, {16, {{8}, {0}, {8}, {0} } },
+	 {{{8}, {0}, {0}, {0} } } },     /* SVGA3D_YUY2 */
+
+	{SVGA3DBLOCKDESC_NV12,
+	 {2, 2, 1},  6, 2, {48, {{0}, {0}, {48}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_NV12 */
+
+	{SVGA3DBLOCKDESC_AYUV,
+	 {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
+	 {{{0}, {8}, {16}, {24} } } },   /* SVGA3D_AYUV */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  16, 16, {128, {{32}, {32}, {32}, {32} } },
+	 {{{64}, {32}, {0}, {96} } } },  /* SVGA3D_R32G32B32A32_TYPELESS */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  16, 16, {128, {{32}, {32}, {32}, {32} } },
+	 {{{64}, {32}, {0}, {96} } } },  /* SVGA3D_R32G32B32A32_UINT */
+
+	{SVGA3DBLOCKDESC_UVWQ,
+	 {1, 1, 1},  16, 16, {128, {{32}, {32}, {32}, {32} } },
+	 {{{64}, {32}, {0}, {96} } } },  /* SVGA3D_R32G32B32A32_SINT */
+
+	{SVGA3DBLOCKDESC_RGB,
+	 {1, 1, 1},  12, 12, {96, {{32}, {32}, {32}, {0} } },
+	 {{{64}, {32}, {0}, {0} } } },   /* SVGA3D_R32G32B32_TYPELESS */
+
+	{SVGA3DBLOCKDESC_RGB_FP,
+	 {1, 1, 1},  12, 12, {96, {{32}, {32}, {32}, {0} } },
+	 {{{64}, {32}, {0}, {0} } } },   /* SVGA3D_R32G32B32_FLOAT */
+
+	{SVGA3DBLOCKDESC_RGB,
+	 {1, 1, 1},  12, 12, {96, {{32}, {32}, {32}, {0} } },
+	 {{{64}, {32}, {0}, {0} } } },   /* SVGA3D_R32G32B32_UINT */
+
+	{SVGA3DBLOCKDESC_UVW,
+	 {1, 1, 1},  12, 12, {96, {{32}, {32}, {32}, {0} } },
+	 {{{64}, {32}, {0}, {0} } } },   /* SVGA3D_R32G32B32_SINT */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  8, 8, {64, {{16}, {16}, {16}, {16} } },
+	 {{{32}, {16}, {0}, {48} } } },  /* SVGA3D_R16G16B16A16_TYPELESS */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  8, 8, {64, {{16}, {16}, {16}, {16} } },
+	 {{{32}, {16}, {0}, {48} } } },  /* SVGA3D_R16G16B16A16_UINT */
+
+	{SVGA3DBLOCKDESC_UVWQ,
+	 {1, 1, 1},  8, 8, {64, {{16}, {16}, {16}, {16} } },
+	 {{{32}, {16}, {0}, {48} } } },  /* SVGA3D_R16G16B16A16_SNORM */
+
+	{SVGA3DBLOCKDESC_UVWQ,
+	 {1, 1, 1},  8, 8, {64, {{16}, {16}, {16}, {16} } },
+	 {{{32}, {16}, {0}, {48} } } },  /* SVGA3D_R16G16B16A16_SINT */
+
+	{SVGA3DBLOCKDESC_RG,
+	 {1, 1, 1},  8, 8, {64, {{0}, {32}, {32}, {0} } },
+	 {{{0}, {32}, {0}, {0} } } },    /* SVGA3D_R32G32_TYPELESS */
+
+	{SVGA3DBLOCKDESC_RG,
+	 {1, 1, 1},  8, 8, {64, {{0}, {32}, {32}, {0} } },
+	 {{{0}, {32}, {0}, {0} } } },    /* SVGA3D_R32G32_UINT */
+
+	{SVGA3DBLOCKDESC_UV,
+	 {1, 1, 1},  8, 8, {64, {{0}, {32}, {32}, {0} } },
+	 {{{0}, {32}, {0}, {0} } } },    /* SVGA3D_R32G32_SINT */
+
+	{SVGA3DBLOCKDESC_RG,
+	 {1, 1, 1},  8, 8, {64, {{0}, {8}, {32}, {0} } },
+	 {{{0}, {32}, {0}, {0} } } },    /* SVGA3D_R32G8X24_TYPELESS */
+
+	{SVGA3DBLOCKDESC_DS,
+	 {1, 1, 1},  8, 8, {64, {{0}, {8}, {32}, {0} } },
+	 {{{0}, {32}, {0}, {0} } } },    /* SVGA3D_D32_FLOAT_S8X24_UINT */
+
+	{SVGA3DBLOCKDESC_R_FP,
+	 {1, 1, 1},  8, 8, {64, {{0}, {0}, {32}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },    /* SVGA3D_R32_FLOAT_X8_X24_TYPELESS */
+
+	{SVGA3DBLOCKDESC_GREEN,
+	 {1, 1, 1},  8, 8, {64, {{0}, {8}, {0}, {0} } },
+	 {{{0}, {32}, {0}, {0} } } },    /* SVGA3D_X32_TYPELESS_G8X24_UINT */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  4, 4, {32, {{10}, {10}, {10}, {2} } },
+	 {{{0}, {10}, {20}, {30} } } },  /* SVGA3D_R10G10B10A2_TYPELESS */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  4, 4, {32, {{10}, {10}, {10}, {2} } },
+	 {{{0}, {10}, {20}, {30} } } },  /* SVGA3D_R10G10B10A2_UINT */
+
+	{SVGA3DBLOCKDESC_RGB_FP,
+	 {1, 1, 1},  4, 4, {32, {{10}, {11}, {11}, {0} } },
+	 {{{0}, {10}, {21}, {0} } } },  /* SVGA3D_R11G11B10_FLOAT */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
+	 {{{16}, {8}, {0}, {24} } } },   /* SVGA3D_R8G8B8A8_TYPELESS */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
+	 {{{16}, {8}, {0}, {24} } } },   /* SVGA3D_R8G8B8A8_UNORM */
+
+	{SVGA3DBLOCKDESC_RGBA_SRGB,
+	 {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
+	 {{{16}, {8}, {0}, {24} } } },   /* SVGA3D_R8G8B8A8_UNORM_SRGB */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
+	 {{{16}, {8}, {0}, {24} } } },   /* SVGA3D_R8G8B8A8_UINT */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
+	 {{{16}, {8}, {0}, {24} } } },   /* SVGA3D_R8G8B8A8_SINT */
+
+	{SVGA3DBLOCKDESC_RG,
+	 {1, 1, 1},  4, 4, {32, {{0}, {16}, {16}, {0} } },
+	 {{{0}, {16}, {0}, {0} } } },    /* SVGA3D_R16G16_TYPELESS */
+
+	{SVGA3DBLOCKDESC_RG_FP,
+	 {1, 1, 1},  4, 4, {32, {{0}, {16}, {16}, {0} } },
+	 {{{0}, {16}, {0}, {0} } } },    /* SVGA3D_R16G16_UINT */
+
+	{SVGA3DBLOCKDESC_UV,
+	 {1, 1, 1},  4, 4, {32, {{0}, {16}, {16}, {0} } },
+	 {{{0}, {16}, {0}, {0} } } },    /* SVGA3D_R16G16_SINT */
+
+	{SVGA3DBLOCKDESC_RED,
+	 {1, 1, 1},  4, 4, {32, {{0}, {0}, {32}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R32_TYPELESS */
+
+	{SVGA3DBLOCKDESC_DEPTH,
+	 {1, 1, 1},  4, 4, {32, {{0}, {0}, {32}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_D32_FLOAT */
+
+	{SVGA3DBLOCKDESC_RED,
+	 {1, 1, 1},  4, 4, {32, {{0}, {0}, {32}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R32_UINT */
+
+	{SVGA3DBLOCKDESC_RED,
+	 {1, 1, 1},  4, 4, {32, {{0}, {0}, {32}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R32_SINT */
+
+	{SVGA3DBLOCKDESC_RG,
+	 {1, 1, 1},  4, 4, {32, {{0}, {8}, {24}, {0} } },
+	 {{{0}, {24}, {0}, {0} } } },    /* SVGA3D_R24G8_TYPELESS */
+
+	{SVGA3DBLOCKDESC_DS,
+	 {1, 1, 1},  4, 4, {32, {{0}, {8}, {24}, {0} } },
+	 {{{0}, {24}, {0}, {0} } } },    /* SVGA3D_D24_UNORM_S8_UINT */
+
+	{SVGA3DBLOCKDESC_RED,
+	 {1, 1, 1},  4, 4, {32, {{0}, {0}, {24}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R24_UNORM_X8_TYPELESS */
+
+	{SVGA3DBLOCKDESC_GREEN,
+	 {1, 1, 1},  4, 4, {32, {{0}, {8}, {0}, {0} } },
+	 {{{0}, {24}, {0}, {0} } } },    /* SVGA3D_X24_TYPELESS_G8_UINT */
+
+	{SVGA3DBLOCKDESC_RG,
+	 {1, 1, 1},  2, 2, {16, {{0}, {8}, {8}, {0} } },
+	 {{{0}, {8}, {0}, {0} } } },     /* SVGA3D_R8G8_TYPELESS */
+
+	{SVGA3DBLOCKDESC_RG,
+	 {1, 1, 1},  2, 2, {16, {{0}, {8}, {8}, {0} } },
+	 {{{0}, {8}, {0}, {0} } } },     /* SVGA3D_R8G8_UNORM */
+
+	{SVGA3DBLOCKDESC_RG,
+	 {1, 1, 1},  2, 2, {16, {{0}, {8}, {8}, {0} } },
+	 {{{0}, {8}, {0}, {0} } } },     /* SVGA3D_R8G8_UINT */
+
+	{SVGA3DBLOCKDESC_UV,
+	 {1, 1, 1},  2, 2, {16, {{0}, {8}, {8}, {0} } },
+	 {{{0}, {8}, {0}, {0} } } },     /* SVGA3D_R8G8_SINT */
+
+	{SVGA3DBLOCKDESC_RED,
+	 {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R16_TYPELESS */
+
+	{SVGA3DBLOCKDESC_RED,
+	 {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R16_UNORM */
+
+	{SVGA3DBLOCKDESC_RED,
+	 {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R16_UINT */
+
+	{SVGA3DBLOCKDESC_U,
+	 {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R16_SNORM */
+
+	{SVGA3DBLOCKDESC_U,
+	 {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R16_SINT */
+
+	{SVGA3DBLOCKDESC_RED,
+	 {1, 1, 1},  1, 1, {8, {{0}, {0}, {8}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R8_TYPELESS */
+
+	{SVGA3DBLOCKDESC_RED,
+	 {1, 1, 1},  1, 1, {8, {{0}, {0}, {8}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R8_UNORM */
+
+	{SVGA3DBLOCKDESC_RED,
+	 {1, 1, 1},  1, 1, {8, {{0}, {0}, {8}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R8_UINT */
+
+	{SVGA3DBLOCKDESC_U,
+	 {1, 1, 1},  1, 1, {8, {{0}, {0}, {8}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R8_SNORM */
+
+	{SVGA3DBLOCKDESC_U,
+	 {1, 1, 1},  1, 1, {8, {{0}, {0}, {8}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R8_SINT */
+
+	{SVGA3DBLOCKDESC_RED,
+	 {8, 1, 1},  1, 1, {8, {{0}, {0}, {8}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_R1_UNORM */
+
+	{SVGA3DBLOCKDESC_RGBE,
+	 {1, 1, 1},  4, 4, {32, {{9}, {9}, {9}, {5} } },
+	 {{{18}, {9}, {0}, {27} } } },   /* SVGA3D_R9G9B9E5_SHAREDEXP */
+
+	{SVGA3DBLOCKDESC_RG,
+	 {1, 1, 1},  2, 2, {16, {{0}, {8}, {8}, {0} } },
+	 {{{0}, {8}, {0}, {0} } } },     /* SVGA3D_R8G8_B8G8_UNORM */
+
+	{SVGA3DBLOCKDESC_RG,
+	 {1, 1, 1},  2, 2, {16, {{0}, {8}, {8}, {0} } },
+	 {{{0}, {8}, {0}, {0} } } },     /* SVGA3D_G8R8_G8B8_UNORM */
+
+	{SVGA3DBLOCKDESC_COMPRESSED,
+	 {4, 4, 1},  8, 8, {64, {{0}, {0}, {64}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC1_TYPELESS */
+
+	{SVGA3DBLOCKDESC_COMPRESSED_SRGB,
+	 {4, 4, 1},  8, 8, {64, {{0}, {0}, {64}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC1_UNORM_SRGB */
+
+	{SVGA3DBLOCKDESC_COMPRESSED,
+	 {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC2_TYPELESS */
+
+	{SVGA3DBLOCKDESC_COMPRESSED_SRGB,
+	 {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC2_UNORM_SRGB */
+
+	{SVGA3DBLOCKDESC_COMPRESSED,
+	 {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC3_TYPELESS */
+
+	{SVGA3DBLOCKDESC_COMPRESSED_SRGB,
+	 {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC3_UNORM_SRGB */
+
+	{SVGA3DBLOCKDESC_COMPRESSED,
+	 {4, 4, 1},  8, 8, {64, {{0}, {0}, {64}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC4_TYPELESS */
+
+	{SVGA3DBLOCKDESC_COMPRESSED,
+	 {4, 4, 1},  8, 8, {64, {{0}, {0}, {64}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC4_UNORM */
+
+	{SVGA3DBLOCKDESC_COMPRESSED,
+	 {4, 4, 1},  8, 8, {64, {{0}, {0}, {64}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC4_SNORM */
+
+	{SVGA3DBLOCKDESC_COMPRESSED,
+	 {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC5_TYPELESS */
+
+	{SVGA3DBLOCKDESC_COMPRESSED,
+	 {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC5_UNORM */
+
+	{SVGA3DBLOCKDESC_COMPRESSED,
+	 {4, 4, 1},  16, 16, {128, {{0}, {0}, {128}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_BC5_SNORM */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  4, 4, {32, {{10}, {10}, {10}, {2} } },
+	 {{{0}, {10}, {20}, {30} } } },  /* SVGA3D_R10G10B10_XR_BIAS_A2_UNORM */
+
+	{SVGA3DBLOCKDESC_RGBA,
+	 {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
+	 {{{0}, {8}, {16}, {24} } } },   /* SVGA3D_B8G8R8A8_TYPELESS */
+
+	{SVGA3DBLOCKDESC_RGBA_SRGB,
+	 {1, 1, 1},  4, 4, {32, {{8}, {8}, {8}, {8} } },
+	 {{{0}, {8}, {16}, {24} } } },   /* SVGA3D_B8G8R8A8_UNORM_SRGB */
+
+	{SVGA3DBLOCKDESC_RGB,
+	 {1, 1, 1},  4, 4, {24, {{8}, {8}, {8}, {0} } },
+	 {{{0}, {8}, {16}, {24} } } },   /* SVGA3D_B8G8R8X8_TYPELESS */
+
+	{SVGA3DBLOCKDESC_RGB_SRGB,
+	 {1, 1, 1},  4, 4, {24, {{8}, {8}, {8}, {0} } },
+	 {{{0}, {8}, {16}, {24} } } },   /* SVGA3D_B8G8R8X8_UNORM_SRGB */
+
+	{SVGA3DBLOCKDESC_DEPTH,
+	 {1, 1, 1},  2, 2, {16, {{0}, {0}, {16}, {0} } },
+	 {{{0}, {0}, {0}, {0} } } },     /* SVGA3D_Z_DF16 */
+
+	{SVGA3DBLOCKDESC_DS,
+	 {1, 1, 1},  4, 4, {32, {{0}, {8}, {24}, {0} } },
+	 {{{0}, {24}, {0}, {0} } } },    /* SVGA3D_Z_DF24 */
+
+	{SVGA3DBLOCKDESC_DS,
+	 {1, 1, 1},  4, 4, {32, {{0}, {8}, {24}, {0} } },
+	 {{{0}, {24}, {0}, {0} } } },    /* SVGA3D_Z_D24S8_INT */
+};
+
+static inline u32 clamped_umul32(u32 a, u32 b)
+{
+	uint64_t tmp = (uint64_t) a*b;
+	return (tmp > (uint64_t) ((u32) -1)) ? (u32) -1 : tmp;
+}
+
+static inline const struct svga3d_surface_desc *
+svga3dsurface_get_desc(SVGA3dSurfaceFormat format)
+{
+	if (format < ARRAY_SIZE(svga3d_surface_descs))
+		return &svga3d_surface_descs[format];
+
+	return &svga3d_surface_descs[SVGA3D_FORMAT_INVALID];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * svga3dsurface_get_mip_size --
+ *
+ *      Given a base level size and the mip level, compute the size of
+ *      the mip level.
+ *
+ * Results:
+ *      See above.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static inline surf_size_struct
+svga3dsurface_get_mip_size(surf_size_struct base_level, u32 mip_level)
+{
+	surf_size_struct size;
+
+	size.width = max_t(u32, base_level.width >> mip_level, 1);
+	size.height = max_t(u32, base_level.height >> mip_level, 1);
+	size.depth = max_t(u32, base_level.depth >> mip_level, 1);
+	return size;
+}
+
+static inline void
+svga3dsurface_get_size_in_blocks(const struct svga3d_surface_desc *desc,
+				 const surf_size_struct *pixel_size,
+				 surf_size_struct *block_size)
+{
+	block_size->width = DIV_ROUND_UP(pixel_size->width,
+					 desc->block_size.width);
+	block_size->height = DIV_ROUND_UP(pixel_size->height,
+					  desc->block_size.height);
+	block_size->depth = DIV_ROUND_UP(pixel_size->depth,
+					 desc->block_size.depth);
+}
+
+static inline bool
+svga3dsurface_is_planar_surface(const struct svga3d_surface_desc *desc)
+{
+	return (desc->block_desc & SVGA3DBLOCKDESC_PLANAR_YUV) != 0;
+}
+
+static inline u32
+svga3dsurface_calculate_pitch(const struct svga3d_surface_desc *desc,
+			      const surf_size_struct *size)
+{
+	u32 pitch;
+	surf_size_struct blocks;
+
+	svga3dsurface_get_size_in_blocks(desc, size, &blocks);
+
+	pitch = blocks.width * desc->pitch_bytes_per_block;
+
+	return pitch;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * svga3dsurface_get_image_buffer_size --
+ *
+ *      Return the number of bytes of buffer space required to store
+ *      one image of a surface, optionally using the specified pitch.
+ *
+ *      If pitch is zero, it is assumed that rows are tightly packed.
+ *
+ *      This function is overflow-safe. If the result would have
+ *      overflowed, instead we return MAX_UINT32.
+ *
+ * Results:
+ *      Byte count.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static inline u32
+svga3dsurface_get_image_buffer_size(const struct svga3d_surface_desc *desc,
+				    const surf_size_struct *size,
+				    u32 pitch)
+{
+	surf_size_struct image_blocks;
+	u32 slice_size, total_size;
+
+	svga3dsurface_get_size_in_blocks(desc, size, &image_blocks);
+
+	if (svga3dsurface_is_planar_surface(desc)) {
+		total_size = clamped_umul32(image_blocks.width,
+					    image_blocks.height);
+		total_size = clamped_umul32(total_size, image_blocks.depth);
+		total_size = clamped_umul32(total_size, desc->bytes_per_block);
+		return total_size;
+	}
+
+	if (pitch == 0)
+		pitch = svga3dsurface_calculate_pitch(desc, size);
+
+	slice_size = clamped_umul32(image_blocks.height, pitch);
+	total_size = clamped_umul32(slice_size, image_blocks.depth);
+
+	return total_size;
+}
+
+static inline u32
+svga3dsurface_get_serialized_size(SVGA3dSurfaceFormat format,
+				  surf_size_struct base_level_size,
+				  u32 num_mip_levels,
+				  bool cubemap)
+{
+	const struct svga3d_surface_desc *desc = svga3dsurface_get_desc(format);
+	u32 total_size = 0;
+	u32 mip;
+
+	for (mip = 0; mip < num_mip_levels; mip++) {
+		surf_size_struct size =
+			svga3dsurface_get_mip_size(base_level_size, mip);
+		total_size += svga3dsurface_get_image_buffer_size(desc,
+								  &size, 0);
+	}
+
+	if (cubemap)
+		total_size *= SVGA3D_MAX_SURFACE_FACES;
+
+	return total_size;
+}
+
+
+/**
+ * svga3dsurface_get_pixel_offset - Compute the offset (in bytes) to a pixel
+ * in an image (or volume).
+ *
+ * @width: The image width in pixels.
+ * @height: The image height in pixels
+ */
+static inline u32
+svga3dsurface_get_pixel_offset(SVGA3dSurfaceFormat format,
+			       u32 width, u32 height,
+			       u32 x, u32 y, u32 z)
+{
+	const struct svga3d_surface_desc *desc = svga3dsurface_get_desc(format);
+	const u32 bw = desc->block_size.width, bh = desc->block_size.height;
+	const u32 bd = desc->block_size.depth;
+	const u32 rowstride = DIV_ROUND_UP(width, bw) * desc->bytes_per_block;
+	const u32 imgstride = DIV_ROUND_UP(height, bh) * rowstride;
+	const u32 offset = (z / bd * imgstride +
+			    y / bh * rowstride +
+			    x / bw * desc->bytes_per_block);
+	return offset;
+}
+
+
+static inline u32
+svga3dsurface_get_image_offset(SVGA3dSurfaceFormat format,
+			       surf_size_struct baseLevelSize,
+			       u32 numMipLevels,
+			       u32 face,
+			       u32 mip)
+
+{
+	u32 offset;
+	u32 mipChainBytes;
+	u32 mipChainBytesToLevel;
+	u32 i;
+	const struct svga3d_surface_desc *desc;
+	surf_size_struct mipSize;
+	u32 bytes;
+
+	desc = svga3dsurface_get_desc(format);
+
+	mipChainBytes = 0;
+	mipChainBytesToLevel = 0;
+	for (i = 0; i < numMipLevels; i++) {
+		mipSize = svga3dsurface_get_mip_size(baseLevelSize, i);
+		bytes = svga3dsurface_get_image_buffer_size(desc, &mipSize, 0);
+		mipChainBytes += bytes;
+		if (i < mip)
+			mipChainBytesToLevel += bytes;
+	}
+
+	offset = mipChainBytes * face + mipChainBytesToLevel;
+
+	return offset;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
index 9826fbc..96dc84d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
@@ -248,13 +248,12 @@ void vmw_evict_flags(struct ttm_buffer_object *bo,
 	*placement = vmw_sys_placement;
 }
 
-/**
- * FIXME: Proper access checks on buffers.
- */
-
 static int vmw_verify_access(struct ttm_buffer_object *bo, struct file *filp)
 {
-	return 0;
+	struct ttm_object_file *tfile =
+		vmw_fpriv((struct drm_file *)filp->private_data)->tfile;
+
+	return vmw_user_dmabuf_verify_access(bo, tfile);
 }
 
 static int vmw_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
@@ -310,27 +309,23 @@ static void vmw_sync_obj_unref(void **sync_obj)
 	vmw_fence_obj_unreference((struct vmw_fence_obj **) sync_obj);
 }
 
-static int vmw_sync_obj_flush(void *sync_obj, void *sync_arg)
+static int vmw_sync_obj_flush(void *sync_obj)
 {
 	vmw_fence_obj_flush((struct vmw_fence_obj *) sync_obj);
 	return 0;
 }
 
-static bool vmw_sync_obj_signaled(void *sync_obj, void *sync_arg)
+static bool vmw_sync_obj_signaled(void *sync_obj)
 {
-	unsigned long flags = (unsigned long) sync_arg;
 	return	vmw_fence_obj_signaled((struct vmw_fence_obj *) sync_obj,
-				       (uint32_t) flags);
+				       DRM_VMW_FENCE_FLAG_EXEC);
 
 }
 
-static int vmw_sync_obj_wait(void *sync_obj, void *sync_arg,
-			     bool lazy, bool interruptible)
+static int vmw_sync_obj_wait(void *sync_obj, bool lazy, bool interruptible)
 {
-	unsigned long flags = (unsigned long) sync_arg;
-
 	return vmw_fence_obj_wait((struct vmw_fence_obj *) sync_obj,
-				  (uint32_t) flags,
+				  DRM_VMW_FENCE_FLAG_EXEC,
 				  lazy, interruptible,
 				  VMW_FENCE_WAIT_TIMEOUT);
 }
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
new file mode 100644
index 0000000..00ae092
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
@@ -0,0 +1,274 @@
+/**************************************************************************
+ *
+ * Copyright © 2009-2012 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_drv.h"
+#include "vmwgfx_resource_priv.h"
+#include "ttm/ttm_placement.h"
+
+struct vmw_user_context {
+	struct ttm_base_object base;
+	struct vmw_resource res;
+};
+
+static void vmw_user_context_free(struct vmw_resource *res);
+static struct vmw_resource *
+vmw_user_context_base_to_res(struct ttm_base_object *base);
+
+static uint64_t vmw_user_context_size;
+
+static const struct vmw_user_resource_conv user_context_conv = {
+	.object_type = VMW_RES_CONTEXT,
+	.base_obj_to_res = vmw_user_context_base_to_res,
+	.res_free = vmw_user_context_free
+};
+
+const struct vmw_user_resource_conv *user_context_converter =
+	&user_context_conv;
+
+
+static const struct vmw_res_func vmw_legacy_context_func = {
+	.res_type = vmw_res_context,
+	.needs_backup = false,
+	.may_evict = false,
+	.type_name = "legacy contexts",
+	.backup_placement = NULL,
+	.create = NULL,
+	.destroy = NULL,
+	.bind = NULL,
+	.unbind = NULL
+};
+
+/**
+ * Context management:
+ */
+
+static void vmw_hw_context_destroy(struct vmw_resource *res)
+{
+
+	struct vmw_private *dev_priv = res->dev_priv;
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdDestroyContext body;
+	} *cmd;
+
+
+	vmw_execbuf_release_pinned_bo(dev_priv);
+	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed reserving FIFO space for surface "
+			  "destruction.\n");
+		return;
+	}
+
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DESTROY);
+	cmd->header.size = cpu_to_le32(sizeof(cmd->body));
+	cmd->body.cid = cpu_to_le32(res->id);
+
+	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+	vmw_3d_resource_dec(dev_priv, false);
+}
+
+static int vmw_context_init(struct vmw_private *dev_priv,
+			    struct vmw_resource *res,
+			    void (*res_free) (struct vmw_resource *res))
+{
+	int ret;
+
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdDefineContext body;
+	} *cmd;
+
+	ret = vmw_resource_init(dev_priv, res, false,
+				res_free, &vmw_legacy_context_func);
+
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed to allocate a resource id.\n");
+		goto out_early;
+	}
+
+	if (unlikely(res->id >= SVGA3D_MAX_CONTEXT_IDS)) {
+		DRM_ERROR("Out of hw context ids.\n");
+		vmw_resource_unreference(&res);
+		return -ENOMEM;
+	}
+
+	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed.\n");
+		vmw_resource_unreference(&res);
+		return -ENOMEM;
+	}
+
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DEFINE);
+	cmd->header.size = cpu_to_le32(sizeof(cmd->body));
+	cmd->body.cid = cpu_to_le32(res->id);
+
+	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+	(void) vmw_3d_resource_inc(dev_priv, false);
+	vmw_resource_activate(res, vmw_hw_context_destroy);
+	return 0;
+
+out_early:
+	if (res_free == NULL)
+		kfree(res);
+	else
+		res_free(res);
+	return ret;
+}
+
+struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv)
+{
+	struct vmw_resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
+	int ret;
+
+	if (unlikely(res == NULL))
+		return NULL;
+
+	ret = vmw_context_init(dev_priv, res, NULL);
+
+	return (ret == 0) ? res : NULL;
+}
+
+/**
+ * User-space context management:
+ */
+
+static struct vmw_resource *
+vmw_user_context_base_to_res(struct ttm_base_object *base)
+{
+	return &(container_of(base, struct vmw_user_context, base)->res);
+}
+
+static void vmw_user_context_free(struct vmw_resource *res)
+{
+	struct vmw_user_context *ctx =
+	    container_of(res, struct vmw_user_context, res);
+	struct vmw_private *dev_priv = res->dev_priv;
+
+	ttm_base_object_kfree(ctx, base);
+	ttm_mem_global_free(vmw_mem_glob(dev_priv),
+			    vmw_user_context_size);
+}
+
+/**
+ * This function is called when user space has no more references on the
+ * base object. It releases the base-object's reference on the resource object.
+ */
+
+static void vmw_user_context_base_release(struct ttm_base_object **p_base)
+{
+	struct ttm_base_object *base = *p_base;
+	struct vmw_user_context *ctx =
+	    container_of(base, struct vmw_user_context, base);
+	struct vmw_resource *res = &ctx->res;
+
+	*p_base = NULL;
+	vmw_resource_unreference(&res);
+}
+
+int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv)
+{
+	struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+
+	return ttm_ref_object_base_unref(tfile, arg->cid, TTM_REF_USAGE);
+}
+
+int vmw_context_define_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_user_context *ctx;
+	struct vmw_resource *res;
+	struct vmw_resource *tmp;
+	struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	int ret;
+
+
+	/*
+	 * Approximate idr memory usage with 128 bytes. It will be limited
+	 * by maximum number_of contexts anyway.
+	 */
+
+	if (unlikely(vmw_user_context_size == 0))
+		vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128;
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+				   vmw_user_context_size,
+				   false, true);
+	if (unlikely(ret != 0)) {
+		if (ret != -ERESTARTSYS)
+			DRM_ERROR("Out of graphics memory for context"
+				  " creation.\n");
+		goto out_unlock;
+	}
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (unlikely(ctx == NULL)) {
+		ttm_mem_global_free(vmw_mem_glob(dev_priv),
+				    vmw_user_context_size);
+		ret = -ENOMEM;
+		goto out_unlock;
+	}
+
+	res = &ctx->res;
+	ctx->base.shareable = false;
+	ctx->base.tfile = NULL;
+
+	/*
+	 * From here on, the destructor takes over resource freeing.
+	 */
+
+	ret = vmw_context_init(dev_priv, res, vmw_user_context_free);
+	if (unlikely(ret != 0))
+		goto out_unlock;
+
+	tmp = vmw_resource_reference(&ctx->res);
+	ret = ttm_base_object_init(tfile, &ctx->base, false, VMW_RES_CONTEXT,
+				   &vmw_user_context_base_release, NULL);
+
+	if (unlikely(ret != 0)) {
+		vmw_resource_unreference(&tmp);
+		goto out_err;
+	}
+
+	arg->cid = ctx->base.hash.key;
+out_err:
+	vmw_resource_unreference(&res);
+out_unlock:
+	ttm_read_unlock(&vmaster->lock);
+	return ret;
+
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
index d1498bf..e88b0eb 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
@@ -60,7 +60,7 @@ int vmw_dmabuf_to_placement(struct vmw_private *dev_priv,
 	if (unlikely(ret != 0))
 		return ret;
 
-	vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
+	vmw_execbuf_release_pinned_bo(dev_priv);
 
 	ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
 	if (unlikely(ret != 0))
@@ -105,7 +105,7 @@ int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv,
 		return ret;
 
 	if (pin)
-		vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
+		vmw_execbuf_release_pinned_bo(dev_priv);
 
 	ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
 	if (unlikely(ret != 0))
@@ -214,8 +214,7 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *dev_priv,
 		return ret;
 
 	if (pin)
-		vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
-
+		vmw_execbuf_release_pinned_bo(dev_priv);
 	ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
 	if (unlikely(ret != 0))
 		goto err_unlock;
@@ -304,7 +303,7 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin)
 	uint32_t old_mem_type = bo->mem.mem_type;
 	int ret;
 
-	BUG_ON(!atomic_read(&bo->reserved));
+	BUG_ON(!ttm_bo_is_reserved(bo));
 	BUG_ON(old_mem_type != TTM_PL_VRAM &&
 	       old_mem_type != VMW_PL_GMR);
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 2dd185e..161f8b2 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -292,7 +292,7 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
 			     PAGE_SIZE,
 			     ttm_bo_type_device,
 			     &vmw_vram_sys_placement,
-			     0, 0, false, NULL,
+			     0, false, NULL,
 			     &dev_priv->dummy_query_bo);
 }
 
@@ -432,6 +432,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 	struct vmw_private *dev_priv;
 	int ret;
 	uint32_t svga_id;
+	enum vmw_res_type i;
 
 	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
 	if (unlikely(dev_priv == NULL)) {
@@ -448,15 +449,18 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 	mutex_init(&dev_priv->cmdbuf_mutex);
 	mutex_init(&dev_priv->release_mutex);
 	rwlock_init(&dev_priv->resource_lock);
-	idr_init(&dev_priv->context_idr);
-	idr_init(&dev_priv->surface_idr);
-	idr_init(&dev_priv->stream_idr);
+
+	for (i = vmw_res_context; i < vmw_res_max; ++i) {
+		idr_init(&dev_priv->res_idr[i]);
+		INIT_LIST_HEAD(&dev_priv->res_lru[i]);
+	}
+
 	mutex_init(&dev_priv->init_mutex);
 	init_waitqueue_head(&dev_priv->fence_queue);
 	init_waitqueue_head(&dev_priv->fifo_queue);
 	dev_priv->fence_queue_waiters = 0;
 	atomic_set(&dev_priv->fifo_queue_waiters, 0);
-	INIT_LIST_HEAD(&dev_priv->surface_lru);
+
 	dev_priv->used_memory_size = 0;
 
 	dev_priv->io_start = pci_resource_start(dev->pdev, 0);
@@ -609,14 +613,18 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 		}
 	}
 
+	if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
+		ret = drm_irq_install(dev);
+		if (ret != 0) {
+			DRM_ERROR("Failed installing irq: %d\n", ret);
+			goto out_no_irq;
+		}
+	}
+
 	dev_priv->fman = vmw_fence_manager_init(dev_priv);
 	if (unlikely(dev_priv->fman == NULL))
 		goto out_no_fman;
 
-	/* Need to start the fifo to check if we can do screen objects */
-	ret = vmw_3d_resource_inc(dev_priv, true);
-	if (unlikely(ret != 0))
-		goto out_no_fifo;
 	vmw_kms_save_vga(dev_priv);
 
 	/* Start kms and overlay systems, needs fifo. */
@@ -625,25 +633,11 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 		goto out_no_kms;
 	vmw_overlay_init(dev_priv);
 
-	/* 3D Depends on Screen Objects being used. */
-	DRM_INFO("Detected %sdevice 3D availability.\n",
-		 vmw_fifo_have_3d(dev_priv) ?
-		 "" : "no ");
-
-	/* We might be done with the fifo now */
 	if (dev_priv->enable_fb) {
+		ret = vmw_3d_resource_inc(dev_priv, true);
+		if (unlikely(ret != 0))
+			goto out_no_fifo;
 		vmw_fb_init(dev_priv);
-	} else {
-		vmw_kms_restore_vga(dev_priv);
-		vmw_3d_resource_dec(dev_priv, true);
-	}
-
-	if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
-		ret = drm_irq_install(dev);
-		if (unlikely(ret != 0)) {
-			DRM_ERROR("Failed installing irq: %d\n", ret);
-			goto out_no_irq;
-		}
 	}
 
 	dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
@@ -651,20 +645,16 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 
 	return 0;
 
-out_no_irq:
-	if (dev_priv->enable_fb)
-		vmw_fb_close(dev_priv);
+out_no_fifo:
 	vmw_overlay_close(dev_priv);
 	vmw_kms_close(dev_priv);
 out_no_kms:
-	/* We still have a 3D resource reference held */
-	if (dev_priv->enable_fb) {
-		vmw_kms_restore_vga(dev_priv);
-		vmw_3d_resource_dec(dev_priv, false);
-	}
-out_no_fifo:
+	vmw_kms_restore_vga(dev_priv);
 	vmw_fence_manager_takedown(dev_priv->fman);
 out_no_fman:
+	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
+		drm_irq_uninstall(dev_priv->dev);
+out_no_irq:
 	if (dev_priv->stealth)
 		pci_release_region(dev->pdev, 2);
 	else
@@ -684,9 +674,9 @@ out_err2:
 out_err1:
 	vmw_ttm_global_release(dev_priv);
 out_err0:
-	idr_destroy(&dev_priv->surface_idr);
-	idr_destroy(&dev_priv->context_idr);
-	idr_destroy(&dev_priv->stream_idr);
+	for (i = vmw_res_context; i < vmw_res_max; ++i)
+		idr_destroy(&dev_priv->res_idr[i]);
+
 	kfree(dev_priv);
 	return ret;
 }
@@ -694,13 +684,14 @@ out_err0:
 static int vmw_driver_unload(struct drm_device *dev)
 {
 	struct vmw_private *dev_priv = vmw_priv(dev);
+	enum vmw_res_type i;
 
 	unregister_pm_notifier(&dev_priv->pm_nb);
 
+	if (dev_priv->ctx.res_ht_initialized)
+		drm_ht_remove(&dev_priv->ctx.res_ht);
 	if (dev_priv->ctx.cmd_bounce)
 		vfree(dev_priv->ctx.cmd_bounce);
-	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
-		drm_irq_uninstall(dev_priv->dev);
 	if (dev_priv->enable_fb) {
 		vmw_fb_close(dev_priv);
 		vmw_kms_restore_vga(dev_priv);
@@ -709,6 +700,8 @@ static int vmw_driver_unload(struct drm_device *dev)
 	vmw_kms_close(dev_priv);
 	vmw_overlay_close(dev_priv);
 	vmw_fence_manager_takedown(dev_priv->fman);
+	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
+		drm_irq_uninstall(dev_priv->dev);
 	if (dev_priv->stealth)
 		pci_release_region(dev->pdev, 2);
 	else
@@ -723,9 +716,9 @@ static int vmw_driver_unload(struct drm_device *dev)
 	(void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
 	(void)ttm_bo_device_release(&dev_priv->bdev);
 	vmw_ttm_global_release(dev_priv);
-	idr_destroy(&dev_priv->surface_idr);
-	idr_destroy(&dev_priv->context_idr);
-	idr_destroy(&dev_priv->stream_idr);
+
+	for (i = vmw_res_context; i < vmw_res_max; ++i)
+		idr_destroy(&dev_priv->res_idr[i]);
 
 	kfree(dev_priv);
 
@@ -924,11 +917,11 @@ static int vmw_master_set(struct drm_device *dev,
 
 out_no_active_lock:
 	if (!dev_priv->enable_fb) {
+		vmw_kms_restore_vga(dev_priv);
+		vmw_3d_resource_dec(dev_priv, true);
 		mutex_lock(&dev_priv->hw_mutex);
 		vmw_write(dev_priv, SVGA_REG_TRACES, 1);
 		mutex_unlock(&dev_priv->hw_mutex);
-		vmw_kms_restore_vga(dev_priv);
-		vmw_3d_resource_dec(dev_priv, true);
 	}
 	return ret;
 }
@@ -949,7 +942,7 @@ static void vmw_master_drop(struct drm_device *dev,
 
 	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, false, 0);
+	vmw_execbuf_release_pinned_bo(dev_priv);
 
 	if (unlikely((ret != 0))) {
 		DRM_ERROR("Unable to lock TTM at VT switch.\n");
@@ -962,11 +955,11 @@ static void vmw_master_drop(struct drm_device *dev,
 		ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM);
 		if (unlikely(ret != 0))
 			DRM_ERROR("Unable to clean VRAM on master drop.\n");
+		vmw_kms_restore_vga(dev_priv);
+		vmw_3d_resource_dec(dev_priv, true);
 		mutex_lock(&dev_priv->hw_mutex);
 		vmw_write(dev_priv, SVGA_REG_TRACES, 1);
 		mutex_unlock(&dev_priv->hw_mutex);
-		vmw_kms_restore_vga(dev_priv);
-		vmw_3d_resource_dec(dev_priv, true);
 	}
 
 	dev_priv->active_master = &dev_priv->fbdev_master;
@@ -1001,7 +994,8 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
 		 * This empties VRAM and unbinds all GMR bindings.
 		 * Buffer contents is moved to swappable memory.
 		 */
-		vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
+		vmw_execbuf_release_pinned_bo(dev_priv);
+		vmw_resource_evict_all(dev_priv);
 		ttm_bo_swapout_all(&dev_priv->bdev);
 
 		break;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 88a179e..13aeda7 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -67,31 +67,46 @@ struct vmw_fpriv {
 
 struct vmw_dma_buffer {
 	struct ttm_buffer_object base;
-	struct list_head validate_list;
-	bool gmr_bound;
-	uint32_t cur_validate_node;
-	bool on_validate_list;
+	struct list_head res_list;
 };
 
+/**
+ * struct vmw_validate_buffer - Carries validation info about buffers.
+ *
+ * @base: Validation info for TTM.
+ * @hash: Hash entry for quick lookup of the TTM buffer object.
+ *
+ * This structure contains also driver private validation info
+ * on top of the info needed by TTM.
+ */
+struct vmw_validate_buffer {
+	struct ttm_validate_buffer base;
+	struct drm_hash_item hash;
+};
+
+struct vmw_res_func;
 struct vmw_resource {
 	struct kref kref;
 	struct vmw_private *dev_priv;
-	struct idr *idr;
 	int id;
-	enum ttm_object_type res_type;
 	bool avail;
-	void (*remove_from_lists) (struct vmw_resource *res);
-	void (*hw_destroy) (struct vmw_resource *res);
+	unsigned long backup_size;
+	bool res_dirty; /* Protected by backup buffer reserved */
+	bool backup_dirty; /* Protected by backup buffer reserved */
+	struct vmw_dma_buffer *backup;
+	unsigned long backup_offset;
+	const struct vmw_res_func *func;
+	struct list_head lru_head; /* Protected by the resource lock */
+	struct list_head mob_head; /* Protected by @backup reserved */
 	void (*res_free) (struct vmw_resource *res);
-	struct list_head validate_head;
-	struct list_head query_head; /* Protected by the cmdbuf mutex */
-	/* TODO is a generic snooper needed? */
-#if 0
-	void (*snoop)(struct vmw_resource *res,
-		      struct ttm_object_file *tfile,
-		      SVGA3dCmdHeader *header);
-	void *snoop_priv;
-#endif
+	void (*hw_destroy) (struct vmw_resource *res);
+};
+
+enum vmw_res_type {
+	vmw_res_context,
+	vmw_res_surface,
+	vmw_res_stream,
+	vmw_res_max
 };
 
 struct vmw_cursor_snooper {
@@ -105,20 +120,18 @@ struct vmw_surface_offset;
 
 struct vmw_surface {
 	struct vmw_resource res;
-	struct list_head lru_head; /* Protected by the resource lock */
 	uint32_t flags;
 	uint32_t format;
 	uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES];
+	struct drm_vmw_size base_size;
 	struct drm_vmw_size *sizes;
 	uint32_t num_sizes;
-
 	bool scanout;
-
 	/* TODO so far just a extra pointer */
 	struct vmw_cursor_snooper snooper;
-	struct ttm_buffer_object *backup;
 	struct vmw_surface_offset *offsets;
-	uint32_t backup_size;
+	SVGA3dTextureFilter autogen_filter;
+	uint32_t multisample_count;
 };
 
 struct vmw_marker_queue {
@@ -145,29 +158,46 @@ struct vmw_relocation {
 	uint32_t index;
 };
 
+/**
+ * struct vmw_res_cache_entry - resource information cache entry
+ *
+ * @valid: Whether the entry is valid, which also implies that the execbuf
+ * code holds a reference to the resource, and it's placed on the
+ * validation list.
+ * @handle: User-space handle of a resource.
+ * @res: Non-ref-counted pointer to the resource.
+ *
+ * Used to avoid frequent repeated user-space handle lookups of the
+ * same resource.
+ */
+struct vmw_res_cache_entry {
+	bool valid;
+	uint32_t handle;
+	struct vmw_resource *res;
+	struct vmw_resource_val_node *node;
+};
+
 struct vmw_sw_context{
-	struct ida bo_list;
-	uint32_t last_cid;
-	bool cid_valid;
+	struct drm_open_hash res_ht;
+	bool res_ht_initialized;
 	bool kernel; /**< is the called made from the kernel */
-	struct vmw_resource *cur_ctx;
-	uint32_t last_sid;
-	uint32_t sid_translation;
-	bool sid_valid;
 	struct ttm_object_file *tfile;
 	struct list_head validate_nodes;
 	struct vmw_relocation relocs[VMWGFX_MAX_RELOCATIONS];
 	uint32_t cur_reloc;
-	struct ttm_validate_buffer val_bufs[VMWGFX_MAX_VALIDATIONS];
+	struct vmw_validate_buffer val_bufs[VMWGFX_MAX_VALIDATIONS];
 	uint32_t cur_val_buf;
 	uint32_t *cmd_bounce;
 	uint32_t cmd_bounce_size;
 	struct list_head resource_list;
 	uint32_t fence_flags;
-	struct list_head query_list;
 	struct ttm_buffer_object *cur_query_bo;
-	uint32_t cur_query_cid;
-	bool query_cid_valid;
+	struct list_head res_relocations;
+	uint32_t *buf_start;
+	struct vmw_res_cache_entry res_cache[vmw_res_max];
+	struct vmw_resource *last_query_ctx;
+	bool needs_post_query_barrier;
+	struct vmw_resource *error_resource;
 };
 
 struct vmw_legacy_display;
@@ -242,10 +272,7 @@ struct vmw_private {
 	 */
 
 	rwlock_t resource_lock;
-	struct idr context_idr;
-	struct idr surface_idr;
-	struct idr stream_idr;
-
+	struct idr res_idr[vmw_res_max];
 	/*
 	 * Block lastclose from racing with firstopen.
 	 */
@@ -320,6 +347,7 @@ struct vmw_private {
 	struct ttm_buffer_object *dummy_query_bo;
 	struct ttm_buffer_object *pinned_bo;
 	uint32_t query_cid;
+	uint32_t query_cid_valid;
 	bool dummy_query_bo_pinned;
 
 	/*
@@ -329,10 +357,15 @@ struct vmw_private {
 	 * protected by the cmdbuf mutex for simplicity.
 	 */
 
-	struct list_head surface_lru;
+	struct list_head res_lru[vmw_res_max];
 	uint32_t used_memory_size;
 };
 
+static inline struct vmw_surface *vmw_res_to_srf(struct vmw_resource *res)
+{
+	return container_of(res, struct vmw_surface, res);
+}
+
 static inline struct vmw_private *vmw_priv(struct drm_device *dev)
 {
 	return (struct vmw_private *)dev->dev_private;
@@ -381,10 +414,16 @@ extern void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id);
 /**
  * Resource utilities - vmwgfx_resource.c
  */
+struct vmw_user_resource_conv;
+extern const struct vmw_user_resource_conv *user_surface_converter;
+extern const struct vmw_user_resource_conv *user_context_converter;
 
 extern struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv);
 extern void vmw_resource_unreference(struct vmw_resource **p_res);
 extern struct vmw_resource *vmw_resource_reference(struct vmw_resource *res);
+extern int vmw_resource_validate(struct vmw_resource *res);
+extern int vmw_resource_reserve(struct vmw_resource *res, bool no_backup);
+extern bool vmw_resource_needs_backup(const struct vmw_resource *res);
 extern int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
 				     struct drm_file *file_priv);
 extern int vmw_context_define_ioctl(struct drm_device *dev, void *data,
@@ -398,14 +437,13 @@ extern int vmw_user_lookup_handle(struct vmw_private *dev_priv,
 				  uint32_t handle,
 				  struct vmw_surface **out_surf,
 				  struct vmw_dma_buffer **out_buf);
+extern int vmw_user_resource_lookup_handle(
+	struct vmw_private *dev_priv,
+	struct ttm_object_file *tfile,
+	uint32_t handle,
+	const struct vmw_user_resource_conv *converter,
+	struct vmw_resource **p_res);
 extern void vmw_surface_res_free(struct vmw_resource *res);
-extern int vmw_surface_init(struct vmw_private *dev_priv,
-			    struct vmw_surface *srf,
-			    void (*res_free) (struct vmw_resource *res));
-extern int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv,
-					  struct ttm_object_file *tfile,
-					  uint32_t handle,
-					  struct vmw_surface **out);
 extern int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
 				     struct drm_file *file_priv);
 extern int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
@@ -423,6 +461,8 @@ extern int vmw_dmabuf_init(struct vmw_private *dev_priv,
 			   size_t size, struct ttm_placement *placement,
 			   bool interuptable,
 			   void (*bo_free) (struct ttm_buffer_object *bo));
+extern int vmw_user_dmabuf_verify_access(struct ttm_buffer_object *bo,
+				  struct ttm_object_file *tfile);
 extern int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
 				  struct drm_file *file_priv);
 extern int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data,
@@ -440,7 +480,14 @@ extern int vmw_user_stream_lookup(struct vmw_private *dev_priv,
 				  struct ttm_object_file *tfile,
 				  uint32_t *inout_id,
 				  struct vmw_resource **out);
-extern void vmw_resource_unreserve(struct list_head *list);
+extern void vmw_resource_unreserve(struct vmw_resource *res,
+				   struct vmw_dma_buffer *new_backup,
+				   unsigned long new_backup_offset);
+extern void vmw_resource_move_notify(struct ttm_buffer_object *bo,
+				     struct ttm_mem_reg *mem);
+extern void vmw_fence_single_bo(struct ttm_buffer_object *bo,
+				struct vmw_fence_obj *fence);
+extern void vmw_resource_evict_all(struct vmw_private *dev_priv);
 
 /**
  * DMA buffer helper routines - vmwgfx_dmabuf.c
@@ -538,10 +585,9 @@ extern int vmw_execbuf_process(struct drm_file *file_priv,
 			       struct drm_vmw_fence_rep __user
 			       *user_fence_rep,
 			       struct vmw_fence_obj **out_fence);
-
-extern void
-vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
-			      bool only_on_cid_match, uint32_t cid);
+extern void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
+					    struct vmw_fence_obj *fence);
+extern void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv);
 
 extern int vmw_execbuf_fence_commands(struct drm_file *file_priv,
 				      struct vmw_private *dev_priv,
@@ -699,10 +745,13 @@ static inline struct vmw_surface *vmw_surface_reference(struct vmw_surface *srf)
 static inline void vmw_dmabuf_unreference(struct vmw_dma_buffer **buf)
 {
 	struct vmw_dma_buffer *tmp_buf = *buf;
-	struct ttm_buffer_object *bo = &tmp_buf->base;
+
 	*buf = NULL;
+	if (tmp_buf != NULL) {
+		struct ttm_buffer_object *bo = &tmp_buf->base;
 
-	ttm_bo_unref(&bo);
+		ttm_bo_unref(&bo);
+	}
 }
 
 static inline struct vmw_dma_buffer *vmw_dmabuf_reference(struct vmw_dma_buffer *buf)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 30654b4..534c967 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -30,6 +30,181 @@
 #include <drm/ttm/ttm_bo_api.h>
 #include <drm/ttm/ttm_placement.h>
 
+#define VMW_RES_HT_ORDER 12
+
+/**
+ * struct vmw_resource_relocation - Relocation info for resources
+ *
+ * @head: List head for the software context's relocation list.
+ * @res: Non-ref-counted pointer to the resource.
+ * @offset: Offset of 4 byte entries into the command buffer where the
+ * id that needs fixup is located.
+ */
+struct vmw_resource_relocation {
+	struct list_head head;
+	const struct vmw_resource *res;
+	unsigned long offset;
+};
+
+/**
+ * struct vmw_resource_val_node - Validation info for resources
+ *
+ * @head: List head for the software context's resource list.
+ * @hash: Hash entry for quick resouce to val_node lookup.
+ * @res: Ref-counted pointer to the resource.
+ * @switch_backup: Boolean whether to switch backup buffer on unreserve.
+ * @new_backup: Refcounted pointer to the new backup buffer.
+ * @new_backup_offset: New backup buffer offset if @new_backup is non-NUll.
+ * @first_usage: Set to true the first time the resource is referenced in
+ * the command stream.
+ * @no_buffer_needed: Resources do not need to allocate buffer backup on
+ * reservation. The command stream will provide one.
+ */
+struct vmw_resource_val_node {
+	struct list_head head;
+	struct drm_hash_item hash;
+	struct vmw_resource *res;
+	struct vmw_dma_buffer *new_backup;
+	unsigned long new_backup_offset;
+	bool first_usage;
+	bool no_buffer_needed;
+};
+
+/**
+ * vmw_resource_unreserve - unreserve resources previously reserved for
+ * command submission.
+ *
+ * @list_head: list of resources to unreserve.
+ * @backoff: Whether command submission failed.
+ */
+static void vmw_resource_list_unreserve(struct list_head *list,
+					bool backoff)
+{
+	struct vmw_resource_val_node *val;
+
+	list_for_each_entry(val, list, head) {
+		struct vmw_resource *res = val->res;
+		struct vmw_dma_buffer *new_backup =
+			backoff ? NULL : val->new_backup;
+
+		vmw_resource_unreserve(res, new_backup,
+			val->new_backup_offset);
+		vmw_dmabuf_unreference(&val->new_backup);
+	}
+}
+
+
+/**
+ * vmw_resource_val_add - Add a resource to the software context's
+ * resource list if it's not already on it.
+ *
+ * @sw_context: Pointer to the software context.
+ * @res: Pointer to the resource.
+ * @p_node On successful return points to a valid pointer to a
+ * struct vmw_resource_val_node, if non-NULL on entry.
+ */
+static int vmw_resource_val_add(struct vmw_sw_context *sw_context,
+				struct vmw_resource *res,
+				struct vmw_resource_val_node **p_node)
+{
+	struct vmw_resource_val_node *node;
+	struct drm_hash_item *hash;
+	int ret;
+
+	if (likely(drm_ht_find_item(&sw_context->res_ht, (unsigned long) res,
+				    &hash) == 0)) {
+		node = container_of(hash, struct vmw_resource_val_node, hash);
+		node->first_usage = false;
+		if (unlikely(p_node != NULL))
+			*p_node = node;
+		return 0;
+	}
+
+	node = kzalloc(sizeof(*node), GFP_KERNEL);
+	if (unlikely(node == NULL)) {
+		DRM_ERROR("Failed to allocate a resource validation "
+			  "entry.\n");
+		return -ENOMEM;
+	}
+
+	node->hash.key = (unsigned long) res;
+	ret = drm_ht_insert_item(&sw_context->res_ht, &node->hash);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed to initialize a resource validation "
+			  "entry.\n");
+		kfree(node);
+		return ret;
+	}
+	list_add_tail(&node->head, &sw_context->resource_list);
+	node->res = vmw_resource_reference(res);
+	node->first_usage = true;
+
+	if (unlikely(p_node != NULL))
+		*p_node = node;
+
+	return 0;
+}
+
+/**
+ * vmw_resource_relocation_add - Add a relocation to the relocation list
+ *
+ * @list: Pointer to head of relocation list.
+ * @res: The resource.
+ * @offset: Offset into the command buffer currently being parsed where the
+ * id that needs fixup is located. Granularity is 4 bytes.
+ */
+static int vmw_resource_relocation_add(struct list_head *list,
+				       const struct vmw_resource *res,
+				       unsigned long offset)
+{
+	struct vmw_resource_relocation *rel;
+
+	rel = kmalloc(sizeof(*rel), GFP_KERNEL);
+	if (unlikely(rel == NULL)) {
+		DRM_ERROR("Failed to allocate a resource relocation.\n");
+		return -ENOMEM;
+	}
+
+	rel->res = res;
+	rel->offset = offset;
+	list_add_tail(&rel->head, list);
+
+	return 0;
+}
+
+/**
+ * vmw_resource_relocations_free - Free all relocations on a list
+ *
+ * @list: Pointer to the head of the relocation list.
+ */
+static void vmw_resource_relocations_free(struct list_head *list)
+{
+	struct vmw_resource_relocation *rel, *n;
+
+	list_for_each_entry_safe(rel, n, list, head) {
+		list_del(&rel->head);
+		kfree(rel);
+	}
+}
+
+/**
+ * vmw_resource_relocations_apply - Apply all relocations on a list
+ *
+ * @cb: Pointer to the start of the command buffer bein patch. This need
+ * not be the same buffer as the one being parsed when the relocation
+ * list was built, but the contents must be the same modulo the
+ * resource ids.
+ * @list: Pointer to the head of the relocation list.
+ */
+static void vmw_resource_relocations_apply(uint32_t *cb,
+					   struct list_head *list)
+{
+	struct vmw_resource_relocation *rel;
+
+	list_for_each_entry(rel, list, head)
+		cb[rel->offset] = rel->res->id;
+}
+
 static int vmw_cmd_invalid(struct vmw_private *dev_priv,
 			   struct vmw_sw_context *sw_context,
 			   SVGA3dCmdHeader *header)
@@ -44,25 +219,11 @@ static int vmw_cmd_ok(struct vmw_private *dev_priv,
 	return 0;
 }
 
-static void vmw_resource_to_validate_list(struct vmw_sw_context *sw_context,
-					  struct vmw_resource **p_res)
-{
-	struct vmw_resource *res = *p_res;
-
-	if (list_empty(&res->validate_head)) {
-		list_add_tail(&res->validate_head, &sw_context->resource_list);
-		*p_res = NULL;
-	} else
-		vmw_resource_unreference(p_res);
-}
-
 /**
  * vmw_bo_to_validate_list - add a bo to a validate list
  *
  * @sw_context: The software context used for this command submission batch.
  * @bo: The buffer object to add.
- * @fence_flags: Fence flags to be or'ed with any other fence flags for
- * this buffer on this submission batch.
  * @p_val_node: If non-NULL Will be updated with the validate node number
  * on return.
  *
@@ -71,31 +232,43 @@ static void vmw_resource_to_validate_list(struct vmw_sw_context *sw_context,
  */
 static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
 				   struct ttm_buffer_object *bo,
-				   uint32_t fence_flags,
 				   uint32_t *p_val_node)
 {
 	uint32_t val_node;
+	struct vmw_validate_buffer *vval_buf;
 	struct ttm_validate_buffer *val_buf;
+	struct drm_hash_item *hash;
+	int ret;
 
-	val_node = vmw_dmabuf_validate_node(bo, sw_context->cur_val_buf);
-
-	if (unlikely(val_node >= VMWGFX_MAX_VALIDATIONS)) {
-		DRM_ERROR("Max number of DMA buffers per submission"
-			  " exceeded.\n");
-		return -EINVAL;
-	}
-
-	val_buf = &sw_context->val_bufs[val_node];
-	if (unlikely(val_node == sw_context->cur_val_buf)) {
-		val_buf->new_sync_obj_arg = NULL;
+	if (likely(drm_ht_find_item(&sw_context->res_ht, (unsigned long) bo,
+				    &hash) == 0)) {
+		vval_buf = container_of(hash, struct vmw_validate_buffer,
+					hash);
+		val_buf = &vval_buf->base;
+		val_node = vval_buf - sw_context->val_bufs;
+	} else {
+		val_node = sw_context->cur_val_buf;
+		if (unlikely(val_node >= VMWGFX_MAX_VALIDATIONS)) {
+			DRM_ERROR("Max number of DMA buffers per submission "
+				  "exceeded.\n");
+			return -EINVAL;
+		}
+		vval_buf = &sw_context->val_bufs[val_node];
+		vval_buf->hash.key = (unsigned long) bo;
+		ret = drm_ht_insert_item(&sw_context->res_ht, &vval_buf->hash);
+		if (unlikely(ret != 0)) {
+			DRM_ERROR("Failed to initialize a buffer validation "
+				  "entry.\n");
+			return ret;
+		}
+		++sw_context->cur_val_buf;
+		val_buf = &vval_buf->base;
 		val_buf->bo = ttm_bo_reference(bo);
+		val_buf->reserved = false;
 		list_add_tail(&val_buf->head, &sw_context->validate_nodes);
-		++sw_context->cur_val_buf;
 	}
 
-	val_buf->new_sync_obj_arg = (void *)
-		((unsigned long) val_buf->new_sync_obj_arg | fence_flags);
-	sw_context->fence_flags |= fence_flags;
+	sw_context->fence_flags |= DRM_VMW_FENCE_FLAG_EXEC;
 
 	if (p_val_node)
 		*p_val_node = val_node;
@@ -103,85 +276,174 @@ static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
 	return 0;
 }
 
-static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
-			     struct vmw_sw_context *sw_context,
-			     SVGA3dCmdHeader *header)
+/**
+ * vmw_resources_reserve - Reserve all resources on the sw_context's
+ * resource list.
+ *
+ * @sw_context: Pointer to the software context.
+ *
+ * Note that since vmware's command submission currently is protected by
+ * the cmdbuf mutex, no fancy deadlock avoidance is required for resources,
+ * since only a single thread at once will attempt this.
+ */
+static int vmw_resources_reserve(struct vmw_sw_context *sw_context)
 {
-	struct vmw_resource *ctx;
-
-	struct vmw_cid_cmd {
-		SVGA3dCmdHeader header;
-		__le32 cid;
-	} *cmd;
+	struct vmw_resource_val_node *val;
 	int ret;
 
-	cmd = container_of(header, struct vmw_cid_cmd, header);
-	if (likely(sw_context->cid_valid && cmd->cid == sw_context->last_cid))
-		return 0;
+	list_for_each_entry(val, &sw_context->resource_list, head) {
+		struct vmw_resource *res = val->res;
 
-	ret = vmw_context_check(dev_priv, sw_context->tfile, cmd->cid,
-				&ctx);
-	if (unlikely(ret != 0)) {
-		DRM_ERROR("Could not find or use context %u\n",
-			  (unsigned) cmd->cid);
-		return ret;
+		ret = vmw_resource_reserve(res, val->no_buffer_needed);
+		if (unlikely(ret != 0))
+			return ret;
+
+		if (res->backup) {
+			struct ttm_buffer_object *bo = &res->backup->base;
+
+			ret = vmw_bo_to_validate_list
+				(sw_context, bo, NULL);
+
+			if (unlikely(ret != 0))
+				return ret;
+		}
 	}
+	return 0;
+}
 
-	sw_context->last_cid = cmd->cid;
-	sw_context->cid_valid = true;
-	sw_context->cur_ctx = ctx;
-	vmw_resource_to_validate_list(sw_context, &ctx);
+/**
+ * vmw_resources_validate - Validate all resources on the sw_context's
+ * resource list.
+ *
+ * @sw_context: Pointer to the software context.
+ *
+ * Before this function is called, all resource backup buffers must have
+ * been validated.
+ */
+static int vmw_resources_validate(struct vmw_sw_context *sw_context)
+{
+	struct vmw_resource_val_node *val;
+	int ret;
+
+	list_for_each_entry(val, &sw_context->resource_list, head) {
+		struct vmw_resource *res = val->res;
 
+		ret = vmw_resource_validate(res);
+		if (unlikely(ret != 0)) {
+			if (ret != -ERESTARTSYS)
+				DRM_ERROR("Failed to validate resource.\n");
+			return ret;
+		}
+	}
 	return 0;
 }
 
-static int vmw_cmd_sid_check(struct vmw_private *dev_priv,
+/**
+ * vmw_cmd_res_check - Check that a resource is present and if so, put it
+ * on the resource validate list unless it's already there.
+ *
+ * @dev_priv: Pointer to a device private structure.
+ * @sw_context: Pointer to the software context.
+ * @res_type: Resource type.
+ * @converter: User-space visisble type specific information.
+ * @id: Pointer to the location in the command buffer currently being
+ * parsed from where the user-space resource id handle is located.
+ */
+static int vmw_cmd_res_check(struct vmw_private *dev_priv,
 			     struct vmw_sw_context *sw_context,
-			     uint32_t *sid)
+			     enum vmw_res_type res_type,
+			     const struct vmw_user_resource_conv *converter,
+			     uint32_t *id,
+			     struct vmw_resource_val_node **p_val)
 {
-	struct vmw_surface *srf;
-	int ret;
+	struct vmw_res_cache_entry *rcache =
+		&sw_context->res_cache[res_type];
 	struct vmw_resource *res;
+	struct vmw_resource_val_node *node;
+	int ret;
 
-	if (*sid == SVGA3D_INVALID_ID)
+	if (*id == SVGA3D_INVALID_ID)
 		return 0;
 
-	if (likely((sw_context->sid_valid  &&
-		      *sid == sw_context->last_sid))) {
-		*sid = sw_context->sid_translation;
-		return 0;
-	}
+	/*
+	 * Fastpath in case of repeated commands referencing the same
+	 * resource
+	 */
 
-	ret = vmw_user_surface_lookup_handle(dev_priv,
-					     sw_context->tfile,
-					     *sid, &srf);
-	if (unlikely(ret != 0)) {
-		DRM_ERROR("Could ot find or use surface 0x%08x "
-			  "address 0x%08lx\n",
-			  (unsigned int) *sid,
-			  (unsigned long) sid);
-		return ret;
+	if (likely(rcache->valid && *id == rcache->handle)) {
+		const struct vmw_resource *res = rcache->res;
+
+		rcache->node->first_usage = false;
+		if (p_val)
+			*p_val = rcache->node;
+
+		return vmw_resource_relocation_add
+			(&sw_context->res_relocations, res,
+			 id - sw_context->buf_start);
 	}
 
-	ret = vmw_surface_validate(dev_priv, srf);
+	ret = vmw_user_resource_lookup_handle(dev_priv,
+					      sw_context->tfile,
+					      *id,
+					      converter,
+					      &res);
 	if (unlikely(ret != 0)) {
-		if (ret != -ERESTARTSYS)
-			DRM_ERROR("Could not validate surface.\n");
-		vmw_surface_unreference(&srf);
+		DRM_ERROR("Could not find or use resource 0x%08x.\n",
+			  (unsigned) *id);
+		dump_stack();
 		return ret;
 	}
 
-	sw_context->last_sid = *sid;
-	sw_context->sid_valid = true;
-	sw_context->sid_translation = srf->res.id;
-	*sid = sw_context->sid_translation;
+	rcache->valid = true;
+	rcache->res = res;
+	rcache->handle = *id;
 
-	res = &srf->res;
-	vmw_resource_to_validate_list(sw_context, &res);
+	ret = vmw_resource_relocation_add(&sw_context->res_relocations,
+					  res,
+					  id - sw_context->buf_start);
+	if (unlikely(ret != 0))
+		goto out_no_reloc;
+
+	ret = vmw_resource_val_add(sw_context, res, &node);
+	if (unlikely(ret != 0))
+		goto out_no_reloc;
 
+	rcache->node = node;
+	if (p_val)
+		*p_val = node;
+	vmw_resource_unreference(&res);
 	return 0;
+
+out_no_reloc:
+	BUG_ON(sw_context->error_resource != NULL);
+	sw_context->error_resource = res;
+
+	return ret;
 }
 
+/**
+ * vmw_cmd_cid_check - Check a command header for valid context information.
+ *
+ * @dev_priv: Pointer to a device private structure.
+ * @sw_context: Pointer to the software context.
+ * @header: A command header with an embedded user-space context handle.
+ *
+ * Convenience function: Call vmw_cmd_res_check with the user-space context
+ * handle embedded in @header.
+ */
+static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
+			     struct vmw_sw_context *sw_context,
+			     SVGA3dCmdHeader *header)
+{
+	struct vmw_cid_cmd {
+		SVGA3dCmdHeader header;
+		__le32 cid;
+	} *cmd;
+
+	cmd = container_of(header, struct vmw_cid_cmd, header);
+	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
+				 user_context_converter, &cmd->cid, NULL);
+}
 
 static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv,
 					   struct vmw_sw_context *sw_context,
@@ -198,7 +460,9 @@ static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv,
 		return ret;
 
 	cmd = container_of(header, struct vmw_sid_cmd, header);
-	ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.target.sid);
+	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+				user_surface_converter,
+				&cmd->body.target.sid, NULL);
 	return ret;
 }
 
@@ -213,10 +477,14 @@ static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv,
 	int ret;
 
 	cmd = container_of(header, struct vmw_sid_cmd, header);
-	ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.src.sid);
+	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+				user_surface_converter,
+				&cmd->body.src.sid, NULL);
 	if (unlikely(ret != 0))
 		return ret;
-	return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.dest.sid);
+	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+				 user_surface_converter,
+				 &cmd->body.dest.sid, NULL);
 }
 
 static int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv,
@@ -230,10 +498,14 @@ static int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv,
 	int ret;
 
 	cmd = container_of(header, struct vmw_sid_cmd, header);
-	ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.src.sid);
+	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+				user_surface_converter,
+				&cmd->body.src.sid, NULL);
 	if (unlikely(ret != 0))
 		return ret;
-	return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.dest.sid);
+	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+				 user_surface_converter,
+				 &cmd->body.dest.sid, NULL);
 }
 
 static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv,
@@ -252,7 +524,9 @@ static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv,
 		return -EPERM;
 	}
 
-	return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.srcImage.sid);
+	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+				 user_surface_converter,
+				 &cmd->body.srcImage.sid, NULL);
 }
 
 static int vmw_cmd_present_check(struct vmw_private *dev_priv,
@@ -272,14 +546,15 @@ static int vmw_cmd_present_check(struct vmw_private *dev_priv,
 		return -EPERM;
 	}
 
-	return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.sid);
+	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+				 user_surface_converter, &cmd->body.sid,
+				 NULL);
 }
 
 /**
  * vmw_query_bo_switch_prepare - Prepare to switch pinned buffer for queries.
  *
  * @dev_priv: The device private structure.
- * @cid: The hardware context for the next query.
  * @new_query_bo: The new buffer holding query results.
  * @sw_context: The software context used for this command submission.
  *
@@ -287,18 +562,18 @@ static int vmw_cmd_present_check(struct vmw_private *dev_priv,
  * query results, and if another buffer currently is pinned for query
  * results. If so, the function prepares the state of @sw_context for
  * switching pinned buffers after successful submission of the current
- * command batch. It also checks whether we're using a new query context.
- * In that case, it makes sure we emit a query barrier for the old
- * context before the current query buffer is fenced.
+ * command batch.
  */
 static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
-				       uint32_t cid,
 				       struct ttm_buffer_object *new_query_bo,
 				       struct vmw_sw_context *sw_context)
 {
+	struct vmw_res_cache_entry *ctx_entry =
+		&sw_context->res_cache[vmw_res_context];
 	int ret;
-	bool add_cid = false;
-	uint32_t cid_to_add;
+
+	BUG_ON(!ctx_entry->valid);
+	sw_context->last_query_ctx = ctx_entry->res;
 
 	if (unlikely(new_query_bo != sw_context->cur_query_bo)) {
 
@@ -308,12 +583,9 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
 		}
 
 		if (unlikely(sw_context->cur_query_bo != NULL)) {
-			BUG_ON(!sw_context->query_cid_valid);
-			add_cid = true;
-			cid_to_add = sw_context->cur_query_cid;
+			sw_context->needs_post_query_barrier = true;
 			ret = vmw_bo_to_validate_list(sw_context,
 						      sw_context->cur_query_bo,
-						      DRM_VMW_FENCE_FLAG_EXEC,
 						      NULL);
 			if (unlikely(ret != 0))
 				return ret;
@@ -322,35 +594,12 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
 
 		ret = vmw_bo_to_validate_list(sw_context,
 					      dev_priv->dummy_query_bo,
-					      DRM_VMW_FENCE_FLAG_EXEC,
 					      NULL);
 		if (unlikely(ret != 0))
 			return ret;
 
 	}
 
-	if (unlikely(cid != sw_context->cur_query_cid &&
-		     sw_context->query_cid_valid)) {
-		add_cid = true;
-		cid_to_add = sw_context->cur_query_cid;
-	}
-
-	sw_context->cur_query_cid = cid;
-	sw_context->query_cid_valid = true;
-
-	if (add_cid) {
-		struct vmw_resource *ctx = sw_context->cur_ctx;
-
-		if (list_empty(&ctx->query_head))
-			list_add_tail(&ctx->query_head,
-				      &sw_context->query_list);
-		ret = vmw_bo_to_validate_list(sw_context,
-					      dev_priv->dummy_query_bo,
-					      DRM_VMW_FENCE_FLAG_EXEC,
-					      NULL);
-		if (unlikely(ret != 0))
-			return ret;
-	}
 	return 0;
 }
 
@@ -362,10 +611,9 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
  * @sw_context: The software context used for this command submission batch.
  *
  * This function will check if we're switching query buffers, and will then,
- * if no other query waits are issued this command submission batch,
  * issue a dummy occlusion query wait used as a query barrier. When the fence
  * object following that query wait has signaled, we are sure that all
- * preseding queries have finished, and the old query buffer can be unpinned.
+ * preceding queries have finished, and the old query buffer can be unpinned.
  * However, since both the new query buffer and the old one are fenced with
  * that fence, we can do an asynchronus unpin now, and be sure that the
  * old query buffer won't be moved until the fence has signaled.
@@ -376,20 +624,19 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
 static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv,
 				     struct vmw_sw_context *sw_context)
 {
-
-	struct vmw_resource *ctx, *next_ctx;
-	int ret;
-
 	/*
 	 * The validate list should still hold references to all
 	 * contexts here.
 	 */
 
-	list_for_each_entry_safe(ctx, next_ctx, &sw_context->query_list,
-				 query_head) {
-		list_del_init(&ctx->query_head);
+	if (sw_context->needs_post_query_barrier) {
+		struct vmw_res_cache_entry *ctx_entry =
+			&sw_context->res_cache[vmw_res_context];
+		struct vmw_resource *ctx;
+		int ret;
 
-		BUG_ON(list_empty(&ctx->validate_head));
+		BUG_ON(!ctx_entry->valid);
+		ctx = ctx_entry->res;
 
 		ret = vmw_fifo_emit_dummy_query(dev_priv, ctx->id);
 
@@ -403,40 +650,46 @@ static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv,
 			ttm_bo_unref(&dev_priv->pinned_bo);
 		}
 
-		vmw_bo_pin(sw_context->cur_query_bo, true);
+		if (!sw_context->needs_post_query_barrier) {
+			vmw_bo_pin(sw_context->cur_query_bo, true);
 
-		/*
-		 * We pin also the dummy_query_bo buffer so that we
-		 * don't need to validate it when emitting
-		 * dummy queries in context destroy paths.
-		 */
+			/*
+			 * We pin also the dummy_query_bo buffer so that we
+			 * don't need to validate it when emitting
+			 * dummy queries in context destroy paths.
+			 */
 
-		vmw_bo_pin(dev_priv->dummy_query_bo, true);
-		dev_priv->dummy_query_bo_pinned = true;
+			vmw_bo_pin(dev_priv->dummy_query_bo, true);
+			dev_priv->dummy_query_bo_pinned = true;
 
-		dev_priv->query_cid = sw_context->cur_query_cid;
-		dev_priv->pinned_bo =
-			ttm_bo_reference(sw_context->cur_query_bo);
+			BUG_ON(sw_context->last_query_ctx == NULL);
+			dev_priv->query_cid = sw_context->last_query_ctx->id;
+			dev_priv->query_cid_valid = true;
+			dev_priv->pinned_bo =
+				ttm_bo_reference(sw_context->cur_query_bo);
+		}
 	}
 }
 
 /**
- * vmw_query_switch_backoff - clear query barrier list
- * @sw_context: The sw context used for this submission batch.
+ * vmw_translate_guest_pointer - Prepare to translate a user-space buffer
+ * handle to a valid SVGAGuestPtr
  *
- * This function is used as part of an error path, where a previously
- * set up list of query barriers needs to be cleared.
+ * @dev_priv: Pointer to a device private structure.
+ * @sw_context: The software context used for this command batch validation.
+ * @ptr: Pointer to the user-space handle to be translated.
+ * @vmw_bo_p: Points to a location that, on successful return will carry
+ * a reference-counted pointer to the DMA buffer identified by the
+ * user-space handle in @id.
  *
+ * This function saves information needed to translate a user-space buffer
+ * handle to a valid SVGAGuestPtr. The translation does not take place
+ * immediately, but during a call to vmw_apply_relocations().
+ * This function builds a relocation list and a list of buffers to validate.
+ * The former needs to be freed using either vmw_apply_relocations() or
+ * vmw_free_relocations(). The latter needs to be freed using
+ * vmw_clear_validations.
  */
-static void vmw_query_switch_backoff(struct vmw_sw_context *sw_context)
-{
-	struct list_head *list, *next;
-
-	list_for_each_safe(list, next, &sw_context->query_list) {
-		list_del_init(list);
-	}
-}
-
 static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
 				   struct vmw_sw_context *sw_context,
 				   SVGAGuestPtr *ptr,
@@ -465,8 +718,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
 	reloc = &sw_context->relocs[sw_context->cur_reloc++];
 	reloc->location = ptr;
 
-	ret = vmw_bo_to_validate_list(sw_context, bo, DRM_VMW_FENCE_FLAG_EXEC,
-				      &reloc->index);
+	ret = vmw_bo_to_validate_list(sw_context, bo, &reloc->index);
 	if (unlikely(ret != 0))
 		goto out_no_reloc;
 
@@ -479,6 +731,37 @@ out_no_reloc:
 	return ret;
 }
 
+/**
+ * vmw_cmd_begin_query - validate a  SVGA_3D_CMD_BEGIN_QUERY command.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context used for this command submission.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_begin_query(struct vmw_private *dev_priv,
+			       struct vmw_sw_context *sw_context,
+			       SVGA3dCmdHeader *header)
+{
+	struct vmw_begin_query_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdBeginQuery q;
+	} *cmd;
+
+	cmd = container_of(header, struct vmw_begin_query_cmd,
+			   header);
+
+	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
+				 user_context_converter, &cmd->q.cid,
+				 NULL);
+}
+
+/**
+ * vmw_cmd_end_query - validate a  SVGA_3D_CMD_END_QUERY command.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context used for this command submission.
+ * @header: Pointer to the command header in the command stream.
+ */
 static int vmw_cmd_end_query(struct vmw_private *dev_priv,
 			     struct vmw_sw_context *sw_context,
 			     SVGA3dCmdHeader *header)
@@ -501,13 +784,19 @@ static int vmw_cmd_end_query(struct vmw_private *dev_priv,
 	if (unlikely(ret != 0))
 		return ret;
 
-	ret = vmw_query_bo_switch_prepare(dev_priv, cmd->q.cid,
-					  &vmw_bo->base, sw_context);
+	ret = vmw_query_bo_switch_prepare(dev_priv, &vmw_bo->base, sw_context);
 
 	vmw_dmabuf_unreference(&vmw_bo);
 	return ret;
 }
 
+/*
+ * vmw_cmd_wait_query - validate a  SVGA_3D_CMD_WAIT_QUERY command.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context used for this command submission.
+ * @header: Pointer to the command header in the command stream.
+ */
 static int vmw_cmd_wait_query(struct vmw_private *dev_priv,
 			      struct vmw_sw_context *sw_context,
 			      SVGA3dCmdHeader *header)
@@ -518,7 +807,6 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv,
 		SVGA3dCmdWaitForQuery q;
 	} *cmd;
 	int ret;
-	struct vmw_resource *ctx;
 
 	cmd = container_of(header, struct vmw_query_cmd, header);
 	ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
@@ -532,16 +820,6 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv,
 		return ret;
 
 	vmw_dmabuf_unreference(&vmw_bo);
-
-	/*
-	 * This wait will act as a barrier for previous waits for this
-	 * context.
-	 */
-
-	ctx = sw_context->cur_ctx;
-	if (!list_empty(&ctx->query_head))
-		list_del_init(&ctx->query_head);
-
 	return 0;
 }
 
@@ -550,14 +828,12 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
 		       SVGA3dCmdHeader *header)
 {
 	struct vmw_dma_buffer *vmw_bo = NULL;
-	struct ttm_buffer_object *bo;
 	struct vmw_surface *srf = NULL;
 	struct vmw_dma_cmd {
 		SVGA3dCmdHeader header;
 		SVGA3dCmdSurfaceDMA dma;
 	} *cmd;
 	int ret;
-	struct vmw_resource *res;
 
 	cmd = container_of(header, struct vmw_dma_cmd, header);
 	ret = vmw_translate_guest_ptr(dev_priv, sw_context,
@@ -566,37 +842,20 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
 	if (unlikely(ret != 0))
 		return ret;
 
-	bo = &vmw_bo->base;
-	ret = vmw_user_surface_lookup_handle(dev_priv, sw_context->tfile,
-					     cmd->dma.host.sid, &srf);
-	if (ret) {
-		DRM_ERROR("could not find surface\n");
-		goto out_no_reloc;
-	}
-
-	ret = vmw_surface_validate(dev_priv, srf);
+	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+				user_surface_converter, &cmd->dma.host.sid,
+				NULL);
 	if (unlikely(ret != 0)) {
-		if (ret != -ERESTARTSYS)
-			DRM_ERROR("Culd not validate surface.\n");
-		goto out_no_validate;
+		if (unlikely(ret != -ERESTARTSYS))
+			DRM_ERROR("could not find surface for DMA.\n");
+		goto out_no_surface;
 	}
 
-	/*
-	 * Patch command stream with device SID.
-	 */
-	cmd->dma.host.sid = srf->res.id;
-	vmw_kms_cursor_snoop(srf, sw_context->tfile, bo, header);
-
-	vmw_dmabuf_unreference(&vmw_bo);
-
-	res = &srf->res;
-	vmw_resource_to_validate_list(sw_context, &res);
+	srf = vmw_res_to_srf(sw_context->res_cache[vmw_res_surface].res);
 
-	return 0;
+	vmw_kms_cursor_snoop(srf, sw_context->tfile, &vmw_bo->base, header);
 
-out_no_validate:
-	vmw_surface_unreference(&srf);
-out_no_reloc:
+out_no_surface:
 	vmw_dmabuf_unreference(&vmw_bo);
 	return ret;
 }
@@ -629,8 +888,9 @@ static int vmw_cmd_draw(struct vmw_private *dev_priv,
 	}
 
 	for (i = 0; i < cmd->body.numVertexDecls; ++i, ++decl) {
-		ret = vmw_cmd_sid_check(dev_priv, sw_context,
-					&decl->array.surfaceId);
+		ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+					user_surface_converter,
+					&decl->array.surfaceId, NULL);
 		if (unlikely(ret != 0))
 			return ret;
 	}
@@ -644,8 +904,9 @@ static int vmw_cmd_draw(struct vmw_private *dev_priv,
 
 	range = (SVGA3dPrimitiveRange *) decl;
 	for (i = 0; i < cmd->body.numRanges; ++i, ++range) {
-		ret = vmw_cmd_sid_check(dev_priv, sw_context,
-					&range->indexArray.surfaceId);
+		ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+					user_surface_converter,
+					&range->indexArray.surfaceId, NULL);
 		if (unlikely(ret != 0))
 			return ret;
 	}
@@ -676,8 +937,9 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv,
 		if (likely(cur_state->name != SVGA3D_TS_BIND_TEXTURE))
 			continue;
 
-		ret = vmw_cmd_sid_check(dev_priv, sw_context,
-					&cur_state->value);
+		ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+					user_surface_converter,
+					&cur_state->value, NULL);
 		if (unlikely(ret != 0))
 			return ret;
 	}
@@ -708,6 +970,34 @@ static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv,
 	return ret;
 }
 
+/**
+ * vmw_cmd_set_shader - Validate an SVGA_3D_CMD_SET_SHADER
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
+			      struct vmw_sw_context *sw_context,
+			      SVGA3dCmdHeader *header)
+{
+	struct vmw_set_shader_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdSetShader body;
+	} *cmd;
+	int ret;
+
+	cmd = container_of(header, struct vmw_set_shader_cmd,
+			   header);
+
+	ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+	if (unlikely(ret != 0))
+		return ret;
+
+	return 0;
+}
+
 static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv,
 				struct vmw_sw_context *sw_context,
 				void *buf, uint32_t *size)
@@ -781,16 +1071,20 @@ static vmw_cmd_func vmw_cmd_funcs[SVGA_3D_CMD_MAX] = {
 	VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check),
 	VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_cid_check),
 	VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check),
-	VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_set_shader),
 	VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check),
 	VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw),
 	VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check),
-	VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_begin_query),
 	VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_end_query),
 	VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_wait_query),
 	VMW_CMD_DEF(SVGA_3D_CMD_PRESENT_READBACK, &vmw_cmd_ok),
 	VMW_CMD_DEF(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN,
-		    &vmw_cmd_blt_surf_screen_check)
+		    &vmw_cmd_blt_surf_screen_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE_V2, &vmw_cmd_invalid),
+	VMW_CMD_DEF(SVGA_3D_CMD_GENERATE_MIPMAPS, &vmw_cmd_invalid),
+	VMW_CMD_DEF(SVGA_3D_CMD_ACTIVATE_SURFACE, &vmw_cmd_invalid),
+	VMW_CMD_DEF(SVGA_3D_CMD_DEACTIVATE_SURFACE, &vmw_cmd_invalid),
 };
 
 static int vmw_cmd_check(struct vmw_private *dev_priv,
@@ -837,6 +1131,8 @@ static int vmw_cmd_check_all(struct vmw_private *dev_priv,
 	int32_t cur_size = size;
 	int ret;
 
+	sw_context->buf_start = buf;
+
 	while (cur_size > 0) {
 		size = cur_size;
 		ret = vmw_cmd_check(dev_priv, sw_context, buf, &size);
@@ -868,43 +1164,63 @@ static void vmw_apply_relocations(struct vmw_sw_context *sw_context)
 
 	for (i = 0; i < sw_context->cur_reloc; ++i) {
 		reloc = &sw_context->relocs[i];
-		validate = &sw_context->val_bufs[reloc->index];
+		validate = &sw_context->val_bufs[reloc->index].base;
 		bo = validate->bo;
-		if (bo->mem.mem_type == TTM_PL_VRAM) {
+		switch (bo->mem.mem_type) {
+		case TTM_PL_VRAM:
 			reloc->location->offset += bo->offset;
 			reloc->location->gmrId = SVGA_GMR_FRAMEBUFFER;
-		} else
+			break;
+		case VMW_PL_GMR:
 			reloc->location->gmrId = bo->mem.start;
+			break;
+		default:
+			BUG();
+		}
 	}
 	vmw_free_relocations(sw_context);
 }
 
+/**
+ * vmw_resource_list_unrefererence - Free up a resource list and unreference
+ * all resources referenced by it.
+ *
+ * @list: The resource list.
+ */
+static void vmw_resource_list_unreference(struct list_head *list)
+{
+	struct vmw_resource_val_node *val, *val_next;
+
+	/*
+	 * Drop references to resources held during command submission.
+	 */
+
+	list_for_each_entry_safe(val, val_next, list, head) {
+		list_del_init(&val->head);
+		vmw_resource_unreference(&val->res);
+		kfree(val);
+	}
+}
+
 static void vmw_clear_validations(struct vmw_sw_context *sw_context)
 {
-	struct ttm_validate_buffer *entry, *next;
-	struct vmw_resource *res, *res_next;
+	struct vmw_validate_buffer *entry, *next;
+	struct vmw_resource_val_node *val;
 
 	/*
 	 * Drop references to DMA buffers held during command submission.
 	 */
 	list_for_each_entry_safe(entry, next, &sw_context->validate_nodes,
-				 head) {
-		list_del(&entry->head);
-		vmw_dmabuf_validate_clear(entry->bo);
-		ttm_bo_unref(&entry->bo);
+				 base.head) {
+		list_del(&entry->base.head);
+		ttm_bo_unref(&entry->base.bo);
+		(void) drm_ht_remove_item(&sw_context->res_ht, &entry->hash);
 		sw_context->cur_val_buf--;
 	}
 	BUG_ON(sw_context->cur_val_buf != 0);
 
-	/*
-	 * Drop references to resources held during command submission.
-	 */
-	vmw_resource_unreserve(&sw_context->resource_list);
-	list_for_each_entry_safe(res, res_next, &sw_context->resource_list,
-				 validate_head) {
-		list_del_init(&res->validate_head);
-		vmw_resource_unreference(&res);
-	}
+	list_for_each_entry(val, &sw_context->resource_list, head)
+		(void) drm_ht_remove_item(&sw_context->res_ht, &val->hash);
 }
 
 static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
@@ -947,11 +1263,11 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
 static int vmw_validate_buffers(struct vmw_private *dev_priv,
 				struct vmw_sw_context *sw_context)
 {
-	struct ttm_validate_buffer *entry;
+	struct vmw_validate_buffer *entry;
 	int ret;
 
-	list_for_each_entry(entry, &sw_context->validate_nodes, head) {
-		ret = vmw_validate_single_buffer(dev_priv, entry->bo);
+	list_for_each_entry(entry, &sw_context->validate_nodes, base.head) {
+		ret = vmw_validate_single_buffer(dev_priv, entry->base.bo);
 		if (unlikely(ret != 0))
 			return ret;
 	}
@@ -1114,6 +1430,8 @@ int vmw_execbuf_process(struct drm_file *file_priv,
 {
 	struct vmw_sw_context *sw_context = &dev_priv->ctx;
 	struct vmw_fence_obj *fence = NULL;
+	struct vmw_resource *error_resource;
+	struct list_head resource_list;
 	uint32_t handle;
 	void *cmd;
 	int ret;
@@ -1143,24 +1461,33 @@ int vmw_execbuf_process(struct drm_file *file_priv,
 		sw_context->kernel = true;
 
 	sw_context->tfile = vmw_fpriv(file_priv)->tfile;
-	sw_context->cid_valid = false;
-	sw_context->sid_valid = false;
 	sw_context->cur_reloc = 0;
 	sw_context->cur_val_buf = 0;
 	sw_context->fence_flags = 0;
-	INIT_LIST_HEAD(&sw_context->query_list);
 	INIT_LIST_HEAD(&sw_context->resource_list);
 	sw_context->cur_query_bo = dev_priv->pinned_bo;
-	sw_context->cur_query_cid = dev_priv->query_cid;
-	sw_context->query_cid_valid = (dev_priv->pinned_bo != NULL);
-
+	sw_context->last_query_ctx = NULL;
+	sw_context->needs_post_query_barrier = false;
+	memset(sw_context->res_cache, 0, sizeof(sw_context->res_cache));
 	INIT_LIST_HEAD(&sw_context->validate_nodes);
+	INIT_LIST_HEAD(&sw_context->res_relocations);
+	if (!sw_context->res_ht_initialized) {
+		ret = drm_ht_create(&sw_context->res_ht, VMW_RES_HT_ORDER);
+		if (unlikely(ret != 0))
+			goto out_unlock;
+		sw_context->res_ht_initialized = true;
+	}
 
+	INIT_LIST_HEAD(&resource_list);
 	ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands,
 				command_size);
 	if (unlikely(ret != 0))
 		goto out_err;
 
+	ret = vmw_resources_reserve(sw_context);
+	if (unlikely(ret != 0))
+		goto out_err;
+
 	ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes);
 	if (unlikely(ret != 0))
 		goto out_err;
@@ -1169,24 +1496,31 @@ int vmw_execbuf_process(struct drm_file *file_priv,
 	if (unlikely(ret != 0))
 		goto out_err;
 
-	vmw_apply_relocations(sw_context);
+	ret = vmw_resources_validate(sw_context);
+	if (unlikely(ret != 0))
+		goto out_err;
 
 	if (throttle_us) {
 		ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.marker_queue,
 				   throttle_us);
 
 		if (unlikely(ret != 0))
-			goto out_throttle;
+			goto out_err;
 	}
 
 	cmd = vmw_fifo_reserve(dev_priv, command_size);
 	if (unlikely(cmd == NULL)) {
 		DRM_ERROR("Failed reserving fifo space for commands.\n");
 		ret = -ENOMEM;
-		goto out_throttle;
+		goto out_err;
 	}
 
+	vmw_apply_relocations(sw_context);
 	memcpy(cmd, kernel_commands, command_size);
+
+	vmw_resource_relocations_apply(cmd, &sw_context->res_relocations);
+	vmw_resource_relocations_free(&sw_context->res_relocations);
+
 	vmw_fifo_commit(dev_priv, command_size);
 
 	vmw_query_bo_switch_commit(dev_priv, sw_context);
@@ -1202,9 +1536,14 @@ int vmw_execbuf_process(struct drm_file *file_priv,
 	if (ret != 0)
 		DRM_ERROR("Fence submission error. Syncing.\n");
 
+	vmw_resource_list_unreserve(&sw_context->resource_list, false);
 	ttm_eu_fence_buffer_objects(&sw_context->validate_nodes,
 				    (void *) fence);
 
+	if (unlikely(dev_priv->pinned_bo != NULL &&
+		     !dev_priv->query_cid_valid))
+		__vmw_execbuf_release_pinned_bo(dev_priv, fence);
+
 	vmw_clear_validations(sw_context);
 	vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret,
 				    user_fence_rep, fence, handle);
@@ -1217,17 +1556,40 @@ int vmw_execbuf_process(struct drm_file *file_priv,
 		vmw_fence_obj_unreference(&fence);
 	}
 
+	list_splice_init(&sw_context->resource_list, &resource_list);
 	mutex_unlock(&dev_priv->cmdbuf_mutex);
+
+	/*
+	 * Unreference resources outside of the cmdbuf_mutex to
+	 * avoid deadlocks in resource destruction paths.
+	 */
+	vmw_resource_list_unreference(&resource_list);
+
 	return 0;
 
 out_err:
+	vmw_resource_relocations_free(&sw_context->res_relocations);
 	vmw_free_relocations(sw_context);
-out_throttle:
-	vmw_query_switch_backoff(sw_context);
 	ttm_eu_backoff_reservation(&sw_context->validate_nodes);
+	vmw_resource_list_unreserve(&sw_context->resource_list, true);
 	vmw_clear_validations(sw_context);
+	if (unlikely(dev_priv->pinned_bo != NULL &&
+		     !dev_priv->query_cid_valid))
+		__vmw_execbuf_release_pinned_bo(dev_priv, NULL);
 out_unlock:
+	list_splice_init(&sw_context->resource_list, &resource_list);
+	error_resource = sw_context->error_resource;
+	sw_context->error_resource = NULL;
 	mutex_unlock(&dev_priv->cmdbuf_mutex);
+
+	/*
+	 * Unreference resources outside of the cmdbuf_mutex to
+	 * avoid deadlocks in resource destruction paths.
+	 */
+	vmw_resource_list_unreference(&resource_list);
+	if (unlikely(error_resource != NULL))
+		vmw_resource_unreference(&error_resource);
+
 	return ret;
 }
 
@@ -1252,13 +1614,13 @@ static void vmw_execbuf_unpin_panic(struct vmw_private *dev_priv)
 
 
 /**
- * vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned
+ * __vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned
  * query bo.
  *
  * @dev_priv: The device private structure.
- * @only_on_cid_match: Only flush and unpin if the current active query cid
- * matches @cid.
- * @cid: Optional context id to match.
+ * @fence: If non-NULL should point to a struct vmw_fence_obj issued
+ * _after_ a query barrier that flushes all queries touching the current
+ * buffer pointed to by @dev_priv->pinned_bo
  *
  * This function should be used to unpin the pinned query bo, or
  * as a query barrier when we need to make sure that all queries have
@@ -1271,31 +1633,26 @@ static void vmw_execbuf_unpin_panic(struct vmw_private *dev_priv)
  *
  * The function will synchronize on the previous query barrier, and will
  * thus not finish until that barrier has executed.
+ *
+ * the @dev_priv->cmdbuf_mutex needs to be held by the current thread
+ * before calling this function.
  */
-void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
-				   bool only_on_cid_match, uint32_t cid)
+void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
+				     struct vmw_fence_obj *fence)
 {
 	int ret = 0;
 	struct list_head validate_list;
 	struct ttm_validate_buffer pinned_val, query_val;
-	struct vmw_fence_obj *fence;
-
-	mutex_lock(&dev_priv->cmdbuf_mutex);
+	struct vmw_fence_obj *lfence = NULL;
 
 	if (dev_priv->pinned_bo == NULL)
 		goto out_unlock;
 
-	if (only_on_cid_match && cid != dev_priv->query_cid)
-		goto out_unlock;
-
 	INIT_LIST_HEAD(&validate_list);
 
-	pinned_val.new_sync_obj_arg = (void *)(unsigned long)
-		DRM_VMW_FENCE_FLAG_EXEC;
 	pinned_val.bo = ttm_bo_reference(dev_priv->pinned_bo);
 	list_add_tail(&pinned_val.head, &validate_list);
 
-	query_val.new_sync_obj_arg = pinned_val.new_sync_obj_arg;
 	query_val.bo = ttm_bo_reference(dev_priv->dummy_query_bo);
 	list_add_tail(&query_val.head, &validate_list);
 
@@ -1308,25 +1665,34 @@ void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
 		goto out_no_reserve;
 	}
 
-	ret = vmw_fifo_emit_dummy_query(dev_priv, dev_priv->query_cid);
-	if (unlikely(ret != 0)) {
-		vmw_execbuf_unpin_panic(dev_priv);
-		goto out_no_emit;
+	if (dev_priv->query_cid_valid) {
+		BUG_ON(fence != NULL);
+		ret = vmw_fifo_emit_dummy_query(dev_priv, dev_priv->query_cid);
+		if (unlikely(ret != 0)) {
+			vmw_execbuf_unpin_panic(dev_priv);
+			goto out_no_emit;
+		}
+		dev_priv->query_cid_valid = false;
 	}
 
 	vmw_bo_pin(dev_priv->pinned_bo, false);
 	vmw_bo_pin(dev_priv->dummy_query_bo, false);
 	dev_priv->dummy_query_bo_pinned = false;
 
-	(void) vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
+	if (fence == NULL) {
+		(void) vmw_execbuf_fence_commands(NULL, dev_priv, &lfence,
+						  NULL);
+		fence = lfence;
+	}
 	ttm_eu_fence_buffer_objects(&validate_list, (void *) fence);
+	if (lfence != NULL)
+		vmw_fence_obj_unreference(&lfence);
 
 	ttm_bo_unref(&query_val.bo);
 	ttm_bo_unref(&pinned_val.bo);
 	ttm_bo_unref(&dev_priv->pinned_bo);
 
 out_unlock:
-	mutex_unlock(&dev_priv->cmdbuf_mutex);
 	return;
 
 out_no_emit:
@@ -1335,6 +1701,31 @@ out_no_reserve:
 	ttm_bo_unref(&query_val.bo);
 	ttm_bo_unref(&pinned_val.bo);
 	ttm_bo_unref(&dev_priv->pinned_bo);
+}
+
+/**
+ * vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned
+ * query bo.
+ *
+ * @dev_priv: The device private structure.
+ *
+ * This function should be used to unpin the pinned query bo, or
+ * as a query barrier when we need to make sure that all queries have
+ * finished before the next fifo command. (For example on hardware
+ * context destructions where the hardware may otherwise leak unfinished
+ * queries).
+ *
+ * This function does not return any failure codes, but make attempts
+ * to do safe unpinning in case of errors.
+ *
+ * The function will synchronize on the previous query barrier, and will
+ * thus not finish until that barrier has executed.
+ */
+void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv)
+{
+	mutex_lock(&dev_priv->cmdbuf_mutex);
+	if (dev_priv->query_cid_valid)
+		__vmw_execbuf_release_pinned_bo(dev_priv, NULL);
 	mutex_unlock(&dev_priv->cmdbuf_mutex);
 }
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
index bc187fa..c62d20e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
@@ -537,7 +537,7 @@ static void vmw_user_fence_destroy(struct vmw_fence_obj *fence)
 		container_of(fence, struct vmw_user_fence, fence);
 	struct vmw_fence_manager *fman = fence->fman;
 
-	kfree(ufence);
+	ttm_base_object_kfree(ufence, base);
 	/*
 	 * Free kernel space accounting.
 	 */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
index 7290811..d9fbbe1 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -133,6 +133,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data,
 	struct drm_vmw_rect *clips = NULL;
 	struct drm_mode_object *obj;
 	struct vmw_framebuffer *vfb;
+	struct vmw_resource *res;
 	uint32_t num_clips;
 	int ret;
 
@@ -180,11 +181,13 @@ int vmw_present_ioctl(struct drm_device *dev, void *data,
 	if (unlikely(ret != 0))
 		goto out_no_ttm_lock;
 
-	ret = vmw_user_surface_lookup_handle(dev_priv, tfile, arg->sid,
-					     &surface);
+	ret = vmw_user_resource_lookup_handle(dev_priv, tfile, arg->sid,
+					      user_surface_converter,
+					      &res);
 	if (ret)
 		goto out_no_surface;
 
+	surface = vmw_res_to_srf(res);
 	ret = vmw_kms_present(dev_priv, file_priv,
 			      vfb, surface, arg->sid,
 			      arg->dest_x, arg->dest_y,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
index cb55b7b..87e39f6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
@@ -35,6 +35,7 @@
 #include "svga_escape.h"
 
 #define VMW_MAX_NUM_STREAMS 1
+#define VMW_OVERLAY_CAP_MASK (SVGA_FIFO_CAP_VIDEO | SVGA_FIFO_CAP_ESCAPE)
 
 struct vmw_stream {
 	struct vmw_dma_buffer *buf;
@@ -449,6 +450,14 @@ int vmw_overlay_pause_all(struct vmw_private *dev_priv)
 	return 0;
 }
 
+
+static bool vmw_overlay_available(const struct vmw_private *dev_priv)
+{
+	return (dev_priv->overlay_priv != NULL && 
+		((dev_priv->fifo.capabilities & VMW_OVERLAY_CAP_MASK) ==
+		 VMW_OVERLAY_CAP_MASK));
+}
+
 int vmw_overlay_ioctl(struct drm_device *dev, void *data,
 		      struct drm_file *file_priv)
 {
@@ -461,7 +470,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data,
 	struct vmw_resource *res;
 	int ret;
 
-	if (!overlay)
+	if (!vmw_overlay_available(dev_priv))
 		return -ENOSYS;
 
 	ret = vmw_user_stream_lookup(dev_priv, tfile, &arg->stream_id, &res);
@@ -492,7 +501,7 @@ out_unlock:
 
 int vmw_overlay_num_overlays(struct vmw_private *dev_priv)
 {
-	if (!dev_priv->overlay_priv)
+	if (!vmw_overlay_available(dev_priv))
 		return 0;
 
 	return VMW_MAX_NUM_STREAMS;
@@ -503,7 +512,7 @@ int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv)
 	struct vmw_overlay *overlay = dev_priv->overlay_priv;
 	int i, k;
 
-	if (!overlay)
+	if (!vmw_overlay_available(dev_priv))
 		return 0;
 
 	mutex_lock(&overlay->mutex);
@@ -569,12 +578,6 @@ int vmw_overlay_init(struct vmw_private *dev_priv)
 	if (dev_priv->overlay_priv)
 		return -EINVAL;
 
-	if (!(dev_priv->fifo.capabilities & SVGA_FIFO_CAP_VIDEO) &&
-	     (dev_priv->fifo.capabilities & SVGA_FIFO_CAP_ESCAPE)) {
-		DRM_INFO("hardware doesn't support overlays\n");
-		return -ENOSYS;
-	}
-
 	overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
 	if (!overlay)
 		return -ENOMEM;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index da3c6b5..0def4ff 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -30,17 +30,7 @@
 #include <drm/ttm/ttm_object.h>
 #include <drm/ttm/ttm_placement.h>
 #include <drm/drmP.h>
-
-struct vmw_user_context {
-	struct ttm_base_object base;
-	struct vmw_resource res;
-};
-
-struct vmw_user_surface {
-	struct ttm_base_object base;
-	struct vmw_surface srf;
-	uint32_t size;
-};
+#include "vmwgfx_resource_priv.h"
 
 struct vmw_user_dma_buffer {
 	struct ttm_base_object base;
@@ -62,17 +52,21 @@ struct vmw_user_stream {
 	struct vmw_stream stream;
 };
 
-struct vmw_surface_offset {
-	uint32_t face;
-	uint32_t mip;
-	uint32_t bo_offset;
-};
-
 
-static uint64_t vmw_user_context_size;
-static uint64_t vmw_user_surface_size;
 static uint64_t vmw_user_stream_size;
 
+static const struct vmw_res_func vmw_stream_func = {
+	.res_type = vmw_res_stream,
+	.needs_backup = false,
+	.may_evict = false,
+	.type_name = "video streams",
+	.backup_placement = NULL,
+	.create = NULL,
+	.destroy = NULL,
+	.bind = NULL,
+	.unbind = NULL
+};
+
 static inline struct vmw_dma_buffer *
 vmw_dma_buffer(struct ttm_buffer_object *bo)
 {
@@ -100,13 +94,14 @@ struct vmw_resource *vmw_resource_reference(struct vmw_resource *res)
  *
  * Release the resource id to the resource id manager and set it to -1
  */
-static void vmw_resource_release_id(struct vmw_resource *res)
+void vmw_resource_release_id(struct vmw_resource *res)
 {
 	struct vmw_private *dev_priv = res->dev_priv;
+	struct idr *idr = &dev_priv->res_idr[res->func->res_type];
 
 	write_lock(&dev_priv->resource_lock);
 	if (res->id != -1)
-		idr_remove(res->idr, res->id);
+		idr_remove(idr, res->id);
 	res->id = -1;
 	write_unlock(&dev_priv->resource_lock);
 }
@@ -116,17 +111,33 @@ static void vmw_resource_release(struct kref *kref)
 	struct vmw_resource *res =
 	    container_of(kref, struct vmw_resource, kref);
 	struct vmw_private *dev_priv = res->dev_priv;
-	int id = res->id;
-	struct idr *idr = res->idr;
+	int id;
+	struct idr *idr = &dev_priv->res_idr[res->func->res_type];
 
 	res->avail = false;
-	if (res->remove_from_lists != NULL)
-		res->remove_from_lists(res);
+	list_del_init(&res->lru_head);
 	write_unlock(&dev_priv->resource_lock);
+	if (res->backup) {
+		struct ttm_buffer_object *bo = &res->backup->base;
+
+		ttm_bo_reserve(bo, false, false, false, 0);
+		if (!list_empty(&res->mob_head) &&
+		    res->func->unbind != NULL) {
+			struct ttm_validate_buffer val_buf;
+
+			val_buf.bo = bo;
+			res->func->unbind(res, false, &val_buf);
+		}
+		res->backup_dirty = false;
+		list_del_init(&res->mob_head);
+		ttm_bo_unreserve(bo);
+		vmw_dmabuf_unreference(&res->backup);
+	}
 
 	if (likely(res->hw_destroy != NULL))
 		res->hw_destroy(res);
 
+	id = res->id;
 	if (res->res_free != NULL)
 		res->res_free(res);
 	else
@@ -153,25 +164,25 @@ void vmw_resource_unreference(struct vmw_resource **p_res)
 /**
  * vmw_resource_alloc_id - release a resource id to the id manager.
  *
- * @dev_priv: Pointer to the device private structure.
  * @res: Pointer to the resource.
  *
  * Allocate the lowest free resource from the resource manager, and set
  * @res->id to that id. Returns 0 on success and -ENOMEM on failure.
  */
-static int vmw_resource_alloc_id(struct vmw_private *dev_priv,
-				 struct vmw_resource *res)
+int vmw_resource_alloc_id(struct vmw_resource *res)
 {
+	struct vmw_private *dev_priv = res->dev_priv;
 	int ret;
+	struct idr *idr = &dev_priv->res_idr[res->func->res_type];
 
 	BUG_ON(res->id != -1);
 
 	do {
-		if (unlikely(idr_pre_get(res->idr, GFP_KERNEL) == 0))
+		if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
 			return -ENOMEM;
 
 		write_lock(&dev_priv->resource_lock);
-		ret = idr_get_new_above(res->idr, res, 1, &res->id);
+		ret = idr_get_new_above(idr, res, 1, &res->id);
 		write_unlock(&dev_priv->resource_lock);
 
 	} while (ret == -EAGAIN);
@@ -179,31 +190,39 @@ static int vmw_resource_alloc_id(struct vmw_private *dev_priv,
 	return ret;
 }
 
-
-static int vmw_resource_init(struct vmw_private *dev_priv,
-			     struct vmw_resource *res,
-			     struct idr *idr,
-			     enum ttm_object_type obj_type,
-			     bool delay_id,
-			     void (*res_free) (struct vmw_resource *res),
-			     void (*remove_from_lists)
-			     (struct vmw_resource *res))
+/**
+ * vmw_resource_init - initialize a struct vmw_resource
+ *
+ * @dev_priv:       Pointer to a device private struct.
+ * @res:            The struct vmw_resource to initialize.
+ * @obj_type:       Resource object type.
+ * @delay_id:       Boolean whether to defer device id allocation until
+ *                  the first validation.
+ * @res_free:       Resource destructor.
+ * @func:           Resource function table.
+ */
+int vmw_resource_init(struct vmw_private *dev_priv, struct vmw_resource *res,
+		      bool delay_id,
+		      void (*res_free) (struct vmw_resource *res),
+		      const struct vmw_res_func *func)
 {
 	kref_init(&res->kref);
 	res->hw_destroy = NULL;
 	res->res_free = res_free;
-	res->remove_from_lists = remove_from_lists;
-	res->res_type = obj_type;
-	res->idr = idr;
 	res->avail = false;
 	res->dev_priv = dev_priv;
-	INIT_LIST_HEAD(&res->query_head);
-	INIT_LIST_HEAD(&res->validate_head);
+	res->func = func;
+	INIT_LIST_HEAD(&res->lru_head);
+	INIT_LIST_HEAD(&res->mob_head);
 	res->id = -1;
+	res->backup = NULL;
+	res->backup_offset = 0;
+	res->backup_dirty = false;
+	res->res_dirty = false;
 	if (delay_id)
 		return 0;
 	else
-		return vmw_resource_alloc_id(dev_priv, res);
+		return vmw_resource_alloc_id(res);
 }
 
 /**
@@ -218,9 +237,8 @@ static int vmw_resource_init(struct vmw_private *dev_priv,
  * Activate basically means that the function vmw_resource_lookup will
  * find it.
  */
-
-static void vmw_resource_activate(struct vmw_resource *res,
-				  void (*hw_destroy) (struct vmw_resource *))
+void vmw_resource_activate(struct vmw_resource *res,
+			   void (*hw_destroy) (struct vmw_resource *))
 {
 	struct vmw_private *dev_priv = res->dev_priv;
 
@@ -250,1396 +268,245 @@ struct vmw_resource *vmw_resource_lookup(struct vmw_private *dev_priv,
 }
 
 /**
- * Context management:
+ * vmw_user_resource_lookup_handle - lookup a struct resource from a
+ * TTM user-space handle and perform basic type checks
+ *
+ * @dev_priv:     Pointer to a device private struct
+ * @tfile:        Pointer to a struct ttm_object_file identifying the caller
+ * @handle:       The TTM user-space handle
+ * @converter:    Pointer to an object describing the resource type
+ * @p_res:        On successful return the location pointed to will contain
+ *                a pointer to a refcounted struct vmw_resource.
+ *
+ * If the handle can't be found or is associated with an incorrect resource
+ * type, -EINVAL will be returned.
  */
-
-static void vmw_hw_context_destroy(struct vmw_resource *res)
-{
-
-	struct vmw_private *dev_priv = res->dev_priv;
-	struct {
-		SVGA3dCmdHeader header;
-		SVGA3dCmdDestroyContext body;
-	} *cmd;
-
-
-	vmw_execbuf_release_pinned_bo(dev_priv, true, res->id);
-
-	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
-	if (unlikely(cmd == NULL)) {
-		DRM_ERROR("Failed reserving FIFO space for surface "
-			  "destruction.\n");
-		return;
-	}
-
-	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DESTROY);
-	cmd->header.size = cpu_to_le32(sizeof(cmd->body));
-	cmd->body.cid = cpu_to_le32(res->id);
-
-	vmw_fifo_commit(dev_priv, sizeof(*cmd));
-	vmw_3d_resource_dec(dev_priv, false);
-}
-
-static int vmw_context_init(struct vmw_private *dev_priv,
-			    struct vmw_resource *res,
-			    void (*res_free) (struct vmw_resource *res))
+int vmw_user_resource_lookup_handle(struct vmw_private *dev_priv,
+				    struct ttm_object_file *tfile,
+				    uint32_t handle,
+				    const struct vmw_user_resource_conv
+				    *converter,
+				    struct vmw_resource **p_res)
 {
-	int ret;
+	struct ttm_base_object *base;
+	struct vmw_resource *res;
+	int ret = -EINVAL;
 
-	struct {
-		SVGA3dCmdHeader header;
-		SVGA3dCmdDefineContext body;
-	} *cmd;
+	base = ttm_base_object_lookup(tfile, handle);
+	if (unlikely(base == NULL))
+		return -EINVAL;
 
-	ret = vmw_resource_init(dev_priv, res, &dev_priv->context_idr,
-				VMW_RES_CONTEXT, false, res_free, NULL);
+	if (unlikely(base->object_type != converter->object_type))
+		goto out_bad_resource;
 
-	if (unlikely(ret != 0)) {
-		DRM_ERROR("Failed to allocate a resource id.\n");
-		goto out_early;
-	}
+	res = converter->base_obj_to_res(base);
 
-	if (unlikely(res->id >= SVGA3D_MAX_CONTEXT_IDS)) {
-		DRM_ERROR("Out of hw context ids.\n");
-		vmw_resource_unreference(&res);
-		return -ENOMEM;
+	read_lock(&dev_priv->resource_lock);
+	if (!res->avail || res->res_free != converter->res_free) {
+		read_unlock(&dev_priv->resource_lock);
+		goto out_bad_resource;
 	}
 
-	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
-	if (unlikely(cmd == NULL)) {
-		DRM_ERROR("Fifo reserve failed.\n");
-		vmw_resource_unreference(&res);
-		return -ENOMEM;
-	}
+	kref_get(&res->kref);
+	read_unlock(&dev_priv->resource_lock);
 
-	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DEFINE);
-	cmd->header.size = cpu_to_le32(sizeof(cmd->body));
-	cmd->body.cid = cpu_to_le32(res->id);
+	*p_res = res;
+	ret = 0;
 
-	vmw_fifo_commit(dev_priv, sizeof(*cmd));
-	(void) vmw_3d_resource_inc(dev_priv, false);
-	vmw_resource_activate(res, vmw_hw_context_destroy);
-	return 0;
+out_bad_resource:
+	ttm_base_object_unref(&base);
 
-out_early:
-	if (res_free == NULL)
-		kfree(res);
-	else
-		res_free(res);
 	return ret;
 }
 
-struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv)
+/**
+ * Helper function that looks either a surface or dmabuf.
+ *
+ * The pointer this pointed at by out_surf and out_buf needs to be null.
+ */
+int vmw_user_lookup_handle(struct vmw_private *dev_priv,
+			   struct ttm_object_file *tfile,
+			   uint32_t handle,
+			   struct vmw_surface **out_surf,
+			   struct vmw_dma_buffer **out_buf)
 {
-	struct vmw_resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
+	struct vmw_resource *res;
 	int ret;
 
-	if (unlikely(res == NULL))
-		return NULL;
-
-	ret = vmw_context_init(dev_priv, res, NULL);
-	return (ret == 0) ? res : NULL;
-}
-
-/**
- * User-space context management:
- */
+	BUG_ON(*out_surf || *out_buf);
 
-static void vmw_user_context_free(struct vmw_resource *res)
-{
-	struct vmw_user_context *ctx =
-	    container_of(res, struct vmw_user_context, res);
-	struct vmw_private *dev_priv = res->dev_priv;
+	ret = vmw_user_resource_lookup_handle(dev_priv, tfile, handle,
+					      user_surface_converter,
+					      &res);
+	if (!ret) {
+		*out_surf = vmw_res_to_srf(res);
+		return 0;
+	}
 
-	kfree(ctx);
-	ttm_mem_global_free(vmw_mem_glob(dev_priv),
-			    vmw_user_context_size);
+	*out_surf = NULL;
+	ret = vmw_user_dmabuf_lookup(tfile, handle, out_buf);
+	return ret;
 }
 
 /**
- * This function is called when user space has no more references on the
- * base object. It releases the base-object's reference on the resource object.
+ * Buffer management.
  */
-
-static void vmw_user_context_base_release(struct ttm_base_object **p_base)
+void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
 {
-	struct ttm_base_object *base = *p_base;
-	struct vmw_user_context *ctx =
-	    container_of(base, struct vmw_user_context, base);
-	struct vmw_resource *res = &ctx->res;
+	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
 
-	*p_base = NULL;
-	vmw_resource_unreference(&res);
+	kfree(vmw_bo);
 }
 
-int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
-			      struct drm_file *file_priv)
+int vmw_dmabuf_init(struct vmw_private *dev_priv,
+		    struct vmw_dma_buffer *vmw_bo,
+		    size_t size, struct ttm_placement *placement,
+		    bool interruptible,
+		    void (*bo_free) (struct ttm_buffer_object *bo))
 {
-	struct vmw_private *dev_priv = vmw_priv(dev);
-	struct vmw_resource *res;
-	struct vmw_user_context *ctx;
-	struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
-	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
-	int ret = 0;
+	struct ttm_bo_device *bdev = &dev_priv->bdev;
+	size_t acc_size;
+	int ret;
 
-	res = vmw_resource_lookup(dev_priv, &dev_priv->context_idr, arg->cid);
-	if (unlikely(res == NULL))
-		return -EINVAL;
+	BUG_ON(!bo_free);
 
-	if (res->res_free != &vmw_user_context_free) {
-		ret = -EINVAL;
-		goto out;
-	}
+	acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct vmw_dma_buffer));
+	memset(vmw_bo, 0, sizeof(*vmw_bo));
 
-	ctx = container_of(res, struct vmw_user_context, res);
-	if (ctx->base.tfile != tfile && !ctx->base.shareable) {
-		ret = -EPERM;
-		goto out;
-	}
+	INIT_LIST_HEAD(&vmw_bo->res_list);
 
-	ttm_ref_object_base_unref(tfile, ctx->base.hash.key, TTM_REF_USAGE);
-out:
-	vmw_resource_unreference(&res);
+	ret = ttm_bo_init(bdev, &vmw_bo->base, size,
+			  ttm_bo_type_device, placement,
+			  0, interruptible,
+			  NULL, acc_size, NULL, bo_free);
 	return ret;
 }
 
-int vmw_context_define_ioctl(struct drm_device *dev, void *data,
-			     struct drm_file *file_priv)
+static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo)
 {
-	struct vmw_private *dev_priv = vmw_priv(dev);
-	struct vmw_user_context *ctx;
-	struct vmw_resource *res;
-	struct vmw_resource *tmp;
-	struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
-	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
-	struct vmw_master *vmaster = vmw_master(file_priv->master);
-	int ret;
-
-
-	/*
-	 * Approximate idr memory usage with 128 bytes. It will be limited
-	 * by maximum number_of contexts anyway.
-	 */
-
-	if (unlikely(vmw_user_context_size == 0))
-		vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128;
-
-	ret = ttm_read_lock(&vmaster->lock, true);
-	if (unlikely(ret != 0))
-		return ret;
-
-	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
-				   vmw_user_context_size,
-				   false, true);
-	if (unlikely(ret != 0)) {
-		if (ret != -ERESTARTSYS)
-			DRM_ERROR("Out of graphics memory for context"
-				  " creation.\n");
-		goto out_unlock;
-	}
-
-	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
-	if (unlikely(ctx == NULL)) {
-		ttm_mem_global_free(vmw_mem_glob(dev_priv),
-				    vmw_user_context_size);
-		ret = -ENOMEM;
-		goto out_unlock;
-	}
-
-	res = &ctx->res;
-	ctx->base.shareable = false;
-	ctx->base.tfile = NULL;
-
-	/*
-	 * From here on, the destructor takes over resource freeing.
-	 */
-
-	ret = vmw_context_init(dev_priv, res, vmw_user_context_free);
-	if (unlikely(ret != 0))
-		goto out_unlock;
-
-	tmp = vmw_resource_reference(&ctx->res);
-	ret = ttm_base_object_init(tfile, &ctx->base, false, VMW_RES_CONTEXT,
-				   &vmw_user_context_base_release, NULL);
-
-	if (unlikely(ret != 0)) {
-		vmw_resource_unreference(&tmp);
-		goto out_err;
-	}
-
-	arg->cid = res->id;
-out_err:
-	vmw_resource_unreference(&res);
-out_unlock:
-	ttm_read_unlock(&vmaster->lock);
-	return ret;
+	struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo);
 
+	ttm_base_object_kfree(vmw_user_bo, base);
 }
 
-int vmw_context_check(struct vmw_private *dev_priv,
-		      struct ttm_object_file *tfile,
-		      int id,
-		      struct vmw_resource **p_res)
+static void vmw_user_dmabuf_release(struct ttm_base_object **p_base)
 {
-	struct vmw_resource *res;
-	int ret = 0;
-
-	read_lock(&dev_priv->resource_lock);
-	res = idr_find(&dev_priv->context_idr, id);
-	if (res && res->avail) {
-		struct vmw_user_context *ctx =
-			container_of(res, struct vmw_user_context, res);
-		if (ctx->base.tfile != tfile && !ctx->base.shareable)
-			ret = -EPERM;
-		if (p_res)
-			*p_res = vmw_resource_reference(res);
-	} else
-		ret = -EINVAL;
-	read_unlock(&dev_priv->resource_lock);
-
-	return ret;
-}
+	struct vmw_user_dma_buffer *vmw_user_bo;
+	struct ttm_base_object *base = *p_base;
+	struct ttm_buffer_object *bo;
 
-struct vmw_bpp {
-	uint8_t bpp;
-	uint8_t s_bpp;
-};
+	*p_base = NULL;
 
-/*
- * Size table for the supported SVGA3D surface formats. It consists of
- * two values. The bpp value and the s_bpp value which is short for
- * "stride bits per pixel" The values are given in such a way that the
- * minimum stride for the image is calculated using
- *
- * min_stride = w*s_bpp
- *
- * and the total memory requirement for the image is
- *
- * h*min_stride*bpp/s_bpp
- *
- */
-static const struct vmw_bpp vmw_sf_bpp[] = {
-	[SVGA3D_FORMAT_INVALID] = {0, 0},
-	[SVGA3D_X8R8G8B8] = {32, 32},
-	[SVGA3D_A8R8G8B8] = {32, 32},
-	[SVGA3D_R5G6B5] = {16, 16},
-	[SVGA3D_X1R5G5B5] = {16, 16},
-	[SVGA3D_A1R5G5B5] = {16, 16},
-	[SVGA3D_A4R4G4B4] = {16, 16},
-	[SVGA3D_Z_D32] = {32, 32},
-	[SVGA3D_Z_D16] = {16, 16},
-	[SVGA3D_Z_D24S8] = {32, 32},
-	[SVGA3D_Z_D15S1] = {16, 16},
-	[SVGA3D_LUMINANCE8] = {8, 8},
-	[SVGA3D_LUMINANCE4_ALPHA4] = {8, 8},
-	[SVGA3D_LUMINANCE16] = {16, 16},
-	[SVGA3D_LUMINANCE8_ALPHA8] = {16, 16},
-	[SVGA3D_DXT1] = {4, 16},
-	[SVGA3D_DXT2] = {8, 32},
-	[SVGA3D_DXT3] = {8, 32},
-	[SVGA3D_DXT4] = {8, 32},
-	[SVGA3D_DXT5] = {8, 32},
-	[SVGA3D_BUMPU8V8] = {16, 16},
-	[SVGA3D_BUMPL6V5U5] = {16, 16},
-	[SVGA3D_BUMPX8L8V8U8] = {32, 32},
-	[SVGA3D_ARGB_S10E5] = {16, 16},
-	[SVGA3D_ARGB_S23E8] = {32, 32},
-	[SVGA3D_A2R10G10B10] = {32, 32},
-	[SVGA3D_V8U8] = {16, 16},
-	[SVGA3D_Q8W8V8U8] = {32, 32},
-	[SVGA3D_CxV8U8] = {16, 16},
-	[SVGA3D_X8L8V8U8] = {32, 32},
-	[SVGA3D_A2W10V10U10] = {32, 32},
-	[SVGA3D_ALPHA8] = {8, 8},
-	[SVGA3D_R_S10E5] = {16, 16},
-	[SVGA3D_R_S23E8] = {32, 32},
-	[SVGA3D_RG_S10E5] = {16, 16},
-	[SVGA3D_RG_S23E8] = {32, 32},
-	[SVGA3D_BUFFER] = {8, 8},
-	[SVGA3D_Z_D24X8] = {32, 32},
-	[SVGA3D_V16U16] = {32, 32},
-	[SVGA3D_G16R16] = {32, 32},
-	[SVGA3D_A16B16G16R16] = {64,  64},
-	[SVGA3D_UYVY] = {12, 12},
-	[SVGA3D_YUY2] = {12, 12},
-	[SVGA3D_NV12] = {12, 8},
-	[SVGA3D_AYUV] = {32, 32},
-	[SVGA3D_BC4_UNORM] = {4,  16},
-	[SVGA3D_BC5_UNORM] = {8,  32},
-	[SVGA3D_Z_DF16] = {16,  16},
-	[SVGA3D_Z_DF24] = {24,  24},
-	[SVGA3D_Z_D24S8_INT] = {32,  32}
-};
+	if (unlikely(base == NULL))
+		return;
 
+	vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, base);
+	bo = &vmw_user_bo->dma.base;
+	ttm_bo_unref(&bo);
+}
 
 /**
- * Surface management.
+ * vmw_user_dmabuf_alloc - Allocate a user dma buffer
+ *
+ * @dev_priv: Pointer to a struct device private.
+ * @tfile: Pointer to a struct ttm_object_file on which to register the user
+ * object.
+ * @size: Size of the dma buffer.
+ * @shareable: Boolean whether the buffer is shareable with other open files.
+ * @handle: Pointer to where the handle value should be assigned.
+ * @p_dma_buf: Pointer to where the refcounted struct vmw_dma_buffer pointer
+ * should be assigned.
  */
+int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv,
+			  struct ttm_object_file *tfile,
+			  uint32_t size,
+			  bool shareable,
+			  uint32_t *handle,
+			  struct vmw_dma_buffer **p_dma_buf)
+{
+	struct vmw_user_dma_buffer *user_bo;
+	struct ttm_buffer_object *tmp;
+	int ret;
 
-struct vmw_surface_dma {
-	SVGA3dCmdHeader header;
-	SVGA3dCmdSurfaceDMA body;
-	SVGA3dCopyBox cb;
-	SVGA3dCmdSurfaceDMASuffix suffix;
-};
+	user_bo = kzalloc(sizeof(*user_bo), GFP_KERNEL);
+	if (unlikely(user_bo == NULL)) {
+		DRM_ERROR("Failed to allocate a buffer.\n");
+		return -ENOMEM;
+	}
 
-struct vmw_surface_define {
-	SVGA3dCmdHeader header;
-	SVGA3dCmdDefineSurface body;
-};
+	ret = vmw_dmabuf_init(dev_priv, &user_bo->dma, size,
+			      &vmw_vram_sys_placement, true,
+			      &vmw_user_dmabuf_destroy);
+	if (unlikely(ret != 0))
+		return ret;
 
-struct vmw_surface_destroy {
-	SVGA3dCmdHeader header;
-	SVGA3dCmdDestroySurface body;
-};
+	tmp = ttm_bo_reference(&user_bo->dma.base);
+	ret = ttm_base_object_init(tfile,
+				   &user_bo->base,
+				   shareable,
+				   ttm_buffer_type,
+				   &vmw_user_dmabuf_release, NULL);
+	if (unlikely(ret != 0)) {
+		ttm_bo_unref(&tmp);
+		goto out_no_base_object;
+	}
 
+	*p_dma_buf = &user_bo->dma;
+	*handle = user_bo->base.hash.key;
 
-/**
- * vmw_surface_dma_size - Compute fifo size for a dma command.
- *
- * @srf: Pointer to a struct vmw_surface
- *
- * Computes the required size for a surface dma command for backup or
- * restoration of the surface represented by @srf.
- */
-static inline uint32_t vmw_surface_dma_size(const struct vmw_surface *srf)
-{
-	return srf->num_sizes * sizeof(struct vmw_surface_dma);
+out_no_base_object:
+	return ret;
 }
 
-
 /**
- * vmw_surface_define_size - Compute fifo size for a surface define command.
- *
- * @srf: Pointer to a struct vmw_surface
+ * vmw_user_dmabuf_verify_access - verify access permissions on this
+ * buffer object.
  *
- * Computes the required size for a surface define command for the definition
- * of the surface represented by @srf.
+ * @bo: Pointer to the buffer object being accessed
+ * @tfile: Identifying the caller.
  */
-static inline uint32_t vmw_surface_define_size(const struct vmw_surface *srf)
+int vmw_user_dmabuf_verify_access(struct ttm_buffer_object *bo,
+				  struct ttm_object_file *tfile)
 {
-	return sizeof(struct vmw_surface_define) + srf->num_sizes *
-		sizeof(SVGA3dSize);
-}
+	struct vmw_user_dma_buffer *vmw_user_bo;
 
+	if (unlikely(bo->destroy != vmw_user_dmabuf_destroy))
+		return -EPERM;
 
-/**
- * vmw_surface_destroy_size - Compute fifo size for a surface destroy command.
- *
- * Computes the required size for a surface destroy command for the destruction
- * of a hw surface.
- */
-static inline uint32_t vmw_surface_destroy_size(void)
-{
-	return sizeof(struct vmw_surface_destroy);
+	vmw_user_bo = vmw_user_dma_buffer(bo);
+	return (vmw_user_bo->base.tfile == tfile ||
+	vmw_user_bo->base.shareable) ? 0 : -EPERM;
 }
 
-/**
- * vmw_surface_destroy_encode - Encode a surface_destroy command.
- *
- * @id: The surface id
- * @cmd_space: Pointer to memory area in which the commands should be encoded.
- */
-static void vmw_surface_destroy_encode(uint32_t id,
-				       void *cmd_space)
+int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
 {
-	struct vmw_surface_destroy *cmd = (struct vmw_surface_destroy *)
-		cmd_space;
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	union drm_vmw_alloc_dmabuf_arg *arg =
+	    (union drm_vmw_alloc_dmabuf_arg *)data;
+	struct drm_vmw_alloc_dmabuf_req *req = &arg->req;
+	struct drm_vmw_dmabuf_rep *rep = &arg->rep;
+	struct vmw_dma_buffer *dma_buf;
+	uint32_t handle;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	int ret;
 
-	cmd->header.id = SVGA_3D_CMD_SURFACE_DESTROY;
-	cmd->header.size = sizeof(cmd->body);
-	cmd->body.sid = id;
-}
-
-/**
- * vmw_surface_define_encode - Encode a surface_define command.
- *
- * @srf: Pointer to a struct vmw_surface object.
- * @cmd_space: Pointer to memory area in which the commands should be encoded.
- */
-static void vmw_surface_define_encode(const struct vmw_surface *srf,
-				      void *cmd_space)
-{
-	struct vmw_surface_define *cmd = (struct vmw_surface_define *)
-		cmd_space;
-	struct drm_vmw_size *src_size;
-	SVGA3dSize *cmd_size;
-	uint32_t cmd_len;
-	int i;
-
-	cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize);
-
-	cmd->header.id = SVGA_3D_CMD_SURFACE_DEFINE;
-	cmd->header.size = cmd_len;
-	cmd->body.sid = srf->res.id;
-	cmd->body.surfaceFlags = srf->flags;
-	cmd->body.format = cpu_to_le32(srf->format);
-	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
-		cmd->body.face[i].numMipLevels = srf->mip_levels[i];
-
-	cmd += 1;
-	cmd_size = (SVGA3dSize *) cmd;
-	src_size = srf->sizes;
-
-	for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) {
-		cmd_size->width = src_size->width;
-		cmd_size->height = src_size->height;
-		cmd_size->depth = src_size->depth;
-	}
-}
-
-
-/**
- * vmw_surface_dma_encode - Encode a surface_dma command.
- *
- * @srf: Pointer to a struct vmw_surface object.
- * @cmd_space: Pointer to memory area in which the commands should be encoded.
- * @ptr: Pointer to an SVGAGuestPtr indicating where the surface contents
- * should be placed or read from.
- * @to_surface: Boolean whether to DMA to the surface or from the surface.
- */
-static void vmw_surface_dma_encode(struct vmw_surface *srf,
-				   void *cmd_space,
-				   const SVGAGuestPtr *ptr,
-				   bool to_surface)
-{
-	uint32_t i;
-	uint32_t bpp = vmw_sf_bpp[srf->format].bpp;
-	uint32_t stride_bpp = vmw_sf_bpp[srf->format].s_bpp;
-	struct vmw_surface_dma *cmd = (struct vmw_surface_dma *)cmd_space;
-
-	for (i = 0; i < srf->num_sizes; ++i) {
-		SVGA3dCmdHeader *header = &cmd->header;
-		SVGA3dCmdSurfaceDMA *body = &cmd->body;
-		SVGA3dCopyBox *cb = &cmd->cb;
-		SVGA3dCmdSurfaceDMASuffix *suffix = &cmd->suffix;
-		const struct vmw_surface_offset *cur_offset = &srf->offsets[i];
-		const struct drm_vmw_size *cur_size = &srf->sizes[i];
-
-		header->id = SVGA_3D_CMD_SURFACE_DMA;
-		header->size = sizeof(*body) + sizeof(*cb) + sizeof(*suffix);
-
-		body->guest.ptr = *ptr;
-		body->guest.ptr.offset += cur_offset->bo_offset;
-		body->guest.pitch = (cur_size->width * stride_bpp + 7) >> 3;
-		body->host.sid = srf->res.id;
-		body->host.face = cur_offset->face;
-		body->host.mipmap = cur_offset->mip;
-		body->transfer = ((to_surface) ?  SVGA3D_WRITE_HOST_VRAM :
-				  SVGA3D_READ_HOST_VRAM);
-		cb->x = 0;
-		cb->y = 0;
-		cb->z = 0;
-		cb->srcx = 0;
-		cb->srcy = 0;
-		cb->srcz = 0;
-		cb->w = cur_size->width;
-		cb->h = cur_size->height;
-		cb->d = cur_size->depth;
-
-		suffix->suffixSize = sizeof(*suffix);
-		suffix->maximumOffset = body->guest.pitch*cur_size->height*
-			cur_size->depth*bpp / stride_bpp;
-		suffix->flags.discard = 0;
-		suffix->flags.unsynchronized = 0;
-		suffix->flags.reserved = 0;
-		++cmd;
-	}
-};
-
-
-static void vmw_hw_surface_destroy(struct vmw_resource *res)
-{
-
-	struct vmw_private *dev_priv = res->dev_priv;
-	struct vmw_surface *srf;
-	void *cmd;
-
-	if (res->id != -1) {
-
-		cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size());
-		if (unlikely(cmd == NULL)) {
-			DRM_ERROR("Failed reserving FIFO space for surface "
-				  "destruction.\n");
-			return;
-		}
-
-		vmw_surface_destroy_encode(res->id, cmd);
-		vmw_fifo_commit(dev_priv, vmw_surface_destroy_size());
-
-		/*
-		 * used_memory_size_atomic, or separate lock
-		 * to avoid taking dev_priv::cmdbuf_mutex in
-		 * the destroy path.
-		 */
-
-		mutex_lock(&dev_priv->cmdbuf_mutex);
-		srf = container_of(res, struct vmw_surface, res);
-		dev_priv->used_memory_size -= srf->backup_size;
-		mutex_unlock(&dev_priv->cmdbuf_mutex);
-
-	}
-	vmw_3d_resource_dec(dev_priv, false);
-}
-
-void vmw_surface_res_free(struct vmw_resource *res)
-{
-	struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
-
-	if (srf->backup)
-		ttm_bo_unref(&srf->backup);
-	kfree(srf->offsets);
-	kfree(srf->sizes);
-	kfree(srf->snooper.image);
-	kfree(srf);
-}
-
-
-/**
- * vmw_surface_do_validate - make a surface available to the device.
- *
- * @dev_priv: Pointer to a device private struct.
- * @srf: Pointer to a struct vmw_surface.
- *
- * If the surface doesn't have a hw id, allocate one, and optionally
- * DMA the backed up surface contents to the device.
- *
- * Returns -EBUSY if there wasn't sufficient device resources to
- * complete the validation. Retry after freeing up resources.
- *
- * May return other errors if the kernel is out of guest resources.
- */
-int vmw_surface_do_validate(struct vmw_private *dev_priv,
-			    struct vmw_surface *srf)
-{
-	struct vmw_resource *res = &srf->res;
-	struct list_head val_list;
-	struct ttm_validate_buffer val_buf;
-	uint32_t submit_size;
-	uint8_t *cmd;
-	int ret;
-
-	if (likely(res->id != -1))
-		return 0;
-
-	if (unlikely(dev_priv->used_memory_size + srf->backup_size >=
-		     dev_priv->memory_size))
-		return -EBUSY;
-
-	/*
-	 * Reserve- and validate the backup DMA bo.
-	 */
-
-	if (srf->backup) {
-		INIT_LIST_HEAD(&val_list);
-		val_buf.bo = ttm_bo_reference(srf->backup);
-		val_buf.new_sync_obj_arg = (void *)((unsigned long)
-						    DRM_VMW_FENCE_FLAG_EXEC);
-		list_add_tail(&val_buf.head, &val_list);
-		ret = ttm_eu_reserve_buffers(&val_list);
-		if (unlikely(ret != 0))
-			goto out_no_reserve;
-
-		ret = ttm_bo_validate(srf->backup, &vmw_srf_placement,
-				      true, false, false);
-		if (unlikely(ret != 0))
-			goto out_no_validate;
-	}
-
-	/*
-	 * Alloc id for the resource.
-	 */
-
-	ret = vmw_resource_alloc_id(dev_priv, res);
-	if (unlikely(ret != 0)) {
-		DRM_ERROR("Failed to allocate a surface id.\n");
-		goto out_no_id;
-	}
-	if (unlikely(res->id >= SVGA3D_MAX_SURFACE_IDS)) {
-		ret = -EBUSY;
-		goto out_no_fifo;
-	}
-
-
-	/*
-	 * Encode surface define- and dma commands.
-	 */
-
-	submit_size = vmw_surface_define_size(srf);
-	if (srf->backup)
-		submit_size += vmw_surface_dma_size(srf);
-
-	cmd = vmw_fifo_reserve(dev_priv, submit_size);
-	if (unlikely(cmd == NULL)) {
-		DRM_ERROR("Failed reserving FIFO space for surface "
-			  "validation.\n");
-		ret = -ENOMEM;
-		goto out_no_fifo;
-	}
-
-	vmw_surface_define_encode(srf, cmd);
-	if (srf->backup) {
-		SVGAGuestPtr ptr;
-
-		cmd += vmw_surface_define_size(srf);
-		vmw_bo_get_guest_ptr(srf->backup, &ptr);
-		vmw_surface_dma_encode(srf, cmd, &ptr, true);
-	}
-
-	vmw_fifo_commit(dev_priv, submit_size);
-
-	/*
-	 * Create a fence object and fence the backup buffer.
-	 */
-
-	if (srf->backup) {
-		struct vmw_fence_obj *fence;
-
-		(void) vmw_execbuf_fence_commands(NULL, dev_priv,
-						  &fence, NULL);
-		ttm_eu_fence_buffer_objects(&val_list, fence);
-		if (likely(fence != NULL))
-			vmw_fence_obj_unreference(&fence);
-		ttm_bo_unref(&val_buf.bo);
-		ttm_bo_unref(&srf->backup);
-	}
-
-	/*
-	 * Surface memory usage accounting.
-	 */
-
-	dev_priv->used_memory_size += srf->backup_size;
-
-	return 0;
-
-out_no_fifo:
-	vmw_resource_release_id(res);
-out_no_id:
-out_no_validate:
-	if (srf->backup)
-		ttm_eu_backoff_reservation(&val_list);
-out_no_reserve:
-	if (srf->backup)
-		ttm_bo_unref(&val_buf.bo);
-	return ret;
-}
-
-/**
- * vmw_surface_evict - Evict a hw surface.
- *
- * @dev_priv: Pointer to a device private struct.
- * @srf: Pointer to a struct vmw_surface
- *
- * DMA the contents of a hw surface to a backup guest buffer object,
- * and destroy the hw surface, releasing its id.
- */
-int vmw_surface_evict(struct vmw_private *dev_priv,
-		      struct vmw_surface *srf)
-{
-	struct vmw_resource *res = &srf->res;
-	struct list_head val_list;
-	struct ttm_validate_buffer val_buf;
-	uint32_t submit_size;
-	uint8_t *cmd;
-	int ret;
-	struct vmw_fence_obj *fence;
-	SVGAGuestPtr ptr;
-
-	BUG_ON(res->id == -1);
-
-	/*
-	 * Create a surface backup buffer object.
-	 */
-
-	if (!srf->backup) {
-		ret = ttm_bo_create(&dev_priv->bdev, srf->backup_size,
-				    ttm_bo_type_device,
-				    &vmw_srf_placement, 0, 0, true,
-				    NULL, &srf->backup);
-		if (unlikely(ret != 0))
-			return ret;
-	}
-
-	/*
-	 * Reserve- and validate the backup DMA bo.
-	 */
-
-	INIT_LIST_HEAD(&val_list);
-	val_buf.bo = ttm_bo_reference(srf->backup);
-	val_buf.new_sync_obj_arg = (void *)(unsigned long)
-		DRM_VMW_FENCE_FLAG_EXEC;
-	list_add_tail(&val_buf.head, &val_list);
-	ret = ttm_eu_reserve_buffers(&val_list);
-	if (unlikely(ret != 0))
-		goto out_no_reserve;
-
-	ret = ttm_bo_validate(srf->backup, &vmw_srf_placement,
-			      true, false, false);
-	if (unlikely(ret != 0))
-		goto out_no_validate;
-
-
-	/*
-	 * Encode the dma- and surface destroy commands.
-	 */
-
-	submit_size = vmw_surface_dma_size(srf) + vmw_surface_destroy_size();
-	cmd = vmw_fifo_reserve(dev_priv, submit_size);
-	if (unlikely(cmd == NULL)) {
-		DRM_ERROR("Failed reserving FIFO space for surface "
-			  "eviction.\n");
-		ret = -ENOMEM;
-		goto out_no_fifo;
-	}
-
-	vmw_bo_get_guest_ptr(srf->backup, &ptr);
-	vmw_surface_dma_encode(srf, cmd, &ptr, false);
-	cmd += vmw_surface_dma_size(srf);
-	vmw_surface_destroy_encode(res->id, cmd);
-	vmw_fifo_commit(dev_priv, submit_size);
-
-	/*
-	 * Surface memory usage accounting.
-	 */
-
-	dev_priv->used_memory_size -= srf->backup_size;
-
-	/*
-	 * Create a fence object and fence the DMA buffer.
-	 */
-
-	(void) vmw_execbuf_fence_commands(NULL, dev_priv,
-					  &fence, NULL);
-	ttm_eu_fence_buffer_objects(&val_list, fence);
-	if (likely(fence != NULL))
-		vmw_fence_obj_unreference(&fence);
-	ttm_bo_unref(&val_buf.bo);
-
-	/*
-	 * Release the surface ID.
-	 */
-
-	vmw_resource_release_id(res);
-
-	return 0;
-
-out_no_fifo:
-out_no_validate:
-	if (srf->backup)
-		ttm_eu_backoff_reservation(&val_list);
-out_no_reserve:
-	ttm_bo_unref(&val_buf.bo);
-	ttm_bo_unref(&srf->backup);
-	return ret;
-}
-
-
-/**
- * vmw_surface_validate - make a surface available to the device, evicting
- * other surfaces if needed.
- *
- * @dev_priv: Pointer to a device private struct.
- * @srf: Pointer to a struct vmw_surface.
- *
- * Try to validate a surface and if it fails due to limited device resources,
- * repeatedly try to evict other surfaces until the request can be
- * acommodated.
- *
- * May return errors if out of resources.
- */
-int vmw_surface_validate(struct vmw_private *dev_priv,
-			 struct vmw_surface *srf)
-{
-	int ret;
-	struct vmw_surface *evict_srf;
-
-	do {
-		write_lock(&dev_priv->resource_lock);
-		list_del_init(&srf->lru_head);
-		write_unlock(&dev_priv->resource_lock);
-
-		ret = vmw_surface_do_validate(dev_priv, srf);
-		if (likely(ret != -EBUSY))
-			break;
-
-		write_lock(&dev_priv->resource_lock);
-		if (list_empty(&dev_priv->surface_lru)) {
-			DRM_ERROR("Out of device memory for surfaces.\n");
-			ret = -EBUSY;
-			write_unlock(&dev_priv->resource_lock);
-			break;
-		}
-
-		evict_srf = vmw_surface_reference
-			(list_first_entry(&dev_priv->surface_lru,
-					  struct vmw_surface,
-					  lru_head));
-		list_del_init(&evict_srf->lru_head);
-
-		write_unlock(&dev_priv->resource_lock);
-		(void) vmw_surface_evict(dev_priv, evict_srf);
-
-		vmw_surface_unreference(&evict_srf);
-
-	} while (1);
-
-	if (unlikely(ret != 0 && srf->res.id != -1)) {
-		write_lock(&dev_priv->resource_lock);
-		list_add_tail(&srf->lru_head, &dev_priv->surface_lru);
-		write_unlock(&dev_priv->resource_lock);
-	}
-
-	return ret;
-}
-
-
-/**
- * vmw_surface_remove_from_lists - Remove surface resources from lookup lists
- *
- * @res: Pointer to a struct vmw_resource embedded in a struct vmw_surface
- *
- * As part of the resource destruction, remove the surface from any
- * lookup lists.
- */
-static void vmw_surface_remove_from_lists(struct vmw_resource *res)
-{
-	struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
-
-	list_del_init(&srf->lru_head);
-}
-
-int vmw_surface_init(struct vmw_private *dev_priv,
-		     struct vmw_surface *srf,
-		     void (*res_free) (struct vmw_resource *res))
-{
-	int ret;
-	struct vmw_resource *res = &srf->res;
-
-	BUG_ON(res_free == NULL);
-	INIT_LIST_HEAD(&srf->lru_head);
-	ret = vmw_resource_init(dev_priv, res, &dev_priv->surface_idr,
-				VMW_RES_SURFACE, true, res_free,
-				vmw_surface_remove_from_lists);
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
 
+	ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile,
+				    req->size, false, &handle, &dma_buf);
 	if (unlikely(ret != 0))
-		res_free(res);
-
-	/*
-	 * The surface won't be visible to hardware until a
-	 * surface validate.
-	 */
-
-	(void) vmw_3d_resource_inc(dev_priv, false);
-	vmw_resource_activate(res, vmw_hw_surface_destroy);
-	return ret;
-}
-
-static void vmw_user_surface_free(struct vmw_resource *res)
-{
-	struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
-	struct vmw_user_surface *user_srf =
-	    container_of(srf, struct vmw_user_surface, srf);
-	struct vmw_private *dev_priv = srf->res.dev_priv;
-	uint32_t size = user_srf->size;
-
-	if (srf->backup)
-		ttm_bo_unref(&srf->backup);
-	kfree(srf->offsets);
-	kfree(srf->sizes);
-	kfree(srf->snooper.image);
-	kfree(user_srf);
-	ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
-}
-
-/**
- * vmw_resource_unreserve - unreserve resources previously reserved for
- * command submission.
- *
- * @list_head: list of resources to unreserve.
- *
- * Currently only surfaces are considered, and unreserving a surface
- * means putting it back on the device's surface lru list,
- * so that it can be evicted if necessary.
- * This function traverses the resource list and
- * checks whether resources are surfaces, and in that case puts them back
- * on the device's surface LRU list.
- */
-void vmw_resource_unreserve(struct list_head *list)
-{
-	struct vmw_resource *res;
-	struct vmw_surface *srf;
-	rwlock_t *lock = NULL;
-
-	list_for_each_entry(res, list, validate_head) {
-
-		if (res->res_free != &vmw_surface_res_free &&
-		    res->res_free != &vmw_user_surface_free)
-			continue;
-
-		if (unlikely(lock == NULL)) {
-			lock = &res->dev_priv->resource_lock;
-			write_lock(lock);
-		}
-
-		srf = container_of(res, struct vmw_surface, res);
-		list_del_init(&srf->lru_head);
-		list_add_tail(&srf->lru_head, &res->dev_priv->surface_lru);
-	}
-
-	if (lock != NULL)
-		write_unlock(lock);
-}
-
-/**
- * Helper function that looks either a surface or dmabuf.
- *
- * The pointer this pointed at by out_surf and out_buf needs to be null.
- */
-int vmw_user_lookup_handle(struct vmw_private *dev_priv,
-			   struct ttm_object_file *tfile,
-			   uint32_t handle,
-			   struct vmw_surface **out_surf,
-			   struct vmw_dma_buffer **out_buf)
-{
-	int ret;
-
-	BUG_ON(*out_surf || *out_buf);
-
-	ret = vmw_user_surface_lookup_handle(dev_priv, tfile, handle, out_surf);
-	if (!ret)
-		return 0;
-
-	ret = vmw_user_dmabuf_lookup(tfile, handle, out_buf);
-	return ret;
-}
-
-
-int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv,
-				   struct ttm_object_file *tfile,
-				   uint32_t handle, struct vmw_surface **out)
-{
-	struct vmw_resource *res;
-	struct vmw_surface *srf;
-	struct vmw_user_surface *user_srf;
-	struct ttm_base_object *base;
-	int ret = -EINVAL;
-
-	base = ttm_base_object_lookup(tfile, handle);
-	if (unlikely(base == NULL))
-		return -EINVAL;
-
-	if (unlikely(base->object_type != VMW_RES_SURFACE))
-		goto out_bad_resource;
-
-	user_srf = container_of(base, struct vmw_user_surface, base);
-	srf = &user_srf->srf;
-	res = &srf->res;
-
-	read_lock(&dev_priv->resource_lock);
-
-	if (!res->avail || res->res_free != &vmw_user_surface_free) {
-		read_unlock(&dev_priv->resource_lock);
-		goto out_bad_resource;
-	}
-
-	kref_get(&res->kref);
-	read_unlock(&dev_priv->resource_lock);
-
-	*out = srf;
-	ret = 0;
-
-out_bad_resource:
-	ttm_base_object_unref(&base);
-
-	return ret;
-}
-
-static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
-{
-	struct ttm_base_object *base = *p_base;
-	struct vmw_user_surface *user_srf =
-	    container_of(base, struct vmw_user_surface, base);
-	struct vmw_resource *res = &user_srf->srf.res;
-
-	*p_base = NULL;
-	vmw_resource_unreference(&res);
-}
-
-int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
-			      struct drm_file *file_priv)
-{
-	struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data;
-	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
-
-	return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE);
-}
-
-int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
-			     struct drm_file *file_priv)
-{
-	struct vmw_private *dev_priv = vmw_priv(dev);
-	struct vmw_user_surface *user_srf;
-	struct vmw_surface *srf;
-	struct vmw_resource *res;
-	struct vmw_resource *tmp;
-	union drm_vmw_surface_create_arg *arg =
-	    (union drm_vmw_surface_create_arg *)data;
-	struct drm_vmw_surface_create_req *req = &arg->req;
-	struct drm_vmw_surface_arg *rep = &arg->rep;
-	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
-	struct drm_vmw_size __user *user_sizes;
-	int ret;
-	int i, j;
-	uint32_t cur_bo_offset;
-	struct drm_vmw_size *cur_size;
-	struct vmw_surface_offset *cur_offset;
-	uint32_t stride_bpp;
-	uint32_t bpp;
-	uint32_t num_sizes;
-	uint32_t size;
-	struct vmw_master *vmaster = vmw_master(file_priv->master);
-
-	if (unlikely(vmw_user_surface_size == 0))
-		vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
-			128;
-
-	num_sizes = 0;
-	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
-		num_sizes += req->mip_levels[i];
-
-	if (num_sizes > DRM_VMW_MAX_SURFACE_FACES *
-	    DRM_VMW_MAX_MIP_LEVELS)
-		return -EINVAL;
-
-	size = vmw_user_surface_size + 128 +
-		ttm_round_pot(num_sizes * sizeof(struct drm_vmw_size)) +
-		ttm_round_pot(num_sizes * sizeof(struct vmw_surface_offset));
-
-
-	ret = ttm_read_lock(&vmaster->lock, true);
-	if (unlikely(ret != 0))
-		return ret;
-
-	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
-				   size, false, true);
-	if (unlikely(ret != 0)) {
-		if (ret != -ERESTARTSYS)
-			DRM_ERROR("Out of graphics memory for surface"
-				  " creation.\n");
-		goto out_unlock;
-	}
-
-	user_srf = kmalloc(sizeof(*user_srf), GFP_KERNEL);
-	if (unlikely(user_srf == NULL)) {
-		ret = -ENOMEM;
-		goto out_no_user_srf;
-	}
-
-	srf = &user_srf->srf;
-	res = &srf->res;
-
-	srf->flags = req->flags;
-	srf->format = req->format;
-	srf->scanout = req->scanout;
-	srf->backup = NULL;
-
-	memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
-	srf->num_sizes = num_sizes;
-	user_srf->size = size;
-
-	srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL);
-	if (unlikely(srf->sizes == NULL)) {
-		ret = -ENOMEM;
-		goto out_no_sizes;
-	}
-	srf->offsets = kmalloc(srf->num_sizes * sizeof(*srf->offsets),
-			       GFP_KERNEL);
-	if (unlikely(srf->sizes == NULL)) {
-		ret = -ENOMEM;
-		goto out_no_offsets;
-	}
-
-	user_sizes = (struct drm_vmw_size __user *)(unsigned long)
-	    req->size_addr;
-
-	ret = copy_from_user(srf->sizes, user_sizes,
-			     srf->num_sizes * sizeof(*srf->sizes));
-	if (unlikely(ret != 0)) {
-		ret = -EFAULT;
-		goto out_no_copy;
-	}
-
-	cur_bo_offset = 0;
-	cur_offset = srf->offsets;
-	cur_size = srf->sizes;
-
-	bpp = vmw_sf_bpp[srf->format].bpp;
-	stride_bpp = vmw_sf_bpp[srf->format].s_bpp;
-
-	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
-		for (j = 0; j < srf->mip_levels[i]; ++j) {
-			uint32_t stride =
-				(cur_size->width * stride_bpp + 7) >> 3;
-
-			cur_offset->face = i;
-			cur_offset->mip = j;
-			cur_offset->bo_offset = cur_bo_offset;
-			cur_bo_offset += stride * cur_size->height *
-				cur_size->depth * bpp / stride_bpp;
-			++cur_offset;
-			++cur_size;
-		}
-	}
-	srf->backup_size = cur_bo_offset;
-
-	if (srf->scanout &&
-	    srf->num_sizes == 1 &&
-	    srf->sizes[0].width == 64 &&
-	    srf->sizes[0].height == 64 &&
-	    srf->format == SVGA3D_A8R8G8B8) {
-
-		/* allocate image area and clear it */
-		srf->snooper.image = kzalloc(64 * 64 * 4, GFP_KERNEL);
-		if (!srf->snooper.image) {
-			DRM_ERROR("Failed to allocate cursor_image\n");
-			ret = -ENOMEM;
-			goto out_no_copy;
-		}
-	} else {
-		srf->snooper.image = NULL;
-	}
-	srf->snooper.crtc = NULL;
-
-	user_srf->base.shareable = false;
-	user_srf->base.tfile = NULL;
-
-	/**
-	 * From this point, the generic resource management functions
-	 * destroy the object on failure.
-	 */
-
-	ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
-	if (unlikely(ret != 0))
-		goto out_unlock;
-
-	tmp = vmw_resource_reference(&srf->res);
-	ret = ttm_base_object_init(tfile, &user_srf->base,
-				   req->shareable, VMW_RES_SURFACE,
-				   &vmw_user_surface_base_release, NULL);
-
-	if (unlikely(ret != 0)) {
-		vmw_resource_unreference(&tmp);
-		vmw_resource_unreference(&res);
-		goto out_unlock;
-	}
-
-	rep->sid = user_srf->base.hash.key;
-	if (rep->sid == SVGA3D_INVALID_ID)
-		DRM_ERROR("Created bad Surface ID.\n");
-
-	vmw_resource_unreference(&res);
-
-	ttm_read_unlock(&vmaster->lock);
-	return 0;
-out_no_copy:
-	kfree(srf->offsets);
-out_no_offsets:
-	kfree(srf->sizes);
-out_no_sizes:
-	kfree(user_srf);
-out_no_user_srf:
-	ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
-out_unlock:
-	ttm_read_unlock(&vmaster->lock);
-	return ret;
-}
-
-int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
-				struct drm_file *file_priv)
-{
-	union drm_vmw_surface_reference_arg *arg =
-	    (union drm_vmw_surface_reference_arg *)data;
-	struct drm_vmw_surface_arg *req = &arg->req;
-	struct drm_vmw_surface_create_req *rep = &arg->rep;
-	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
-	struct vmw_surface *srf;
-	struct vmw_user_surface *user_srf;
-	struct drm_vmw_size __user *user_sizes;
-	struct ttm_base_object *base;
-	int ret = -EINVAL;
-
-	base = ttm_base_object_lookup(tfile, req->sid);
-	if (unlikely(base == NULL)) {
-		DRM_ERROR("Could not find surface to reference.\n");
-		return -EINVAL;
-	}
-
-	if (unlikely(base->object_type != VMW_RES_SURFACE))
-		goto out_bad_resource;
-
-	user_srf = container_of(base, struct vmw_user_surface, base);
-	srf = &user_srf->srf;
-
-	ret = ttm_ref_object_add(tfile, &user_srf->base, TTM_REF_USAGE, NULL);
-	if (unlikely(ret != 0)) {
-		DRM_ERROR("Could not add a reference to a surface.\n");
-		goto out_no_reference;
-	}
-
-	rep->flags = srf->flags;
-	rep->format = srf->format;
-	memcpy(rep->mip_levels, srf->mip_levels, sizeof(srf->mip_levels));
-	user_sizes = (struct drm_vmw_size __user *)(unsigned long)
-	    rep->size_addr;
-
-	if (user_sizes)
-		ret = copy_to_user(user_sizes, srf->sizes,
-				   srf->num_sizes * sizeof(*srf->sizes));
-	if (unlikely(ret != 0)) {
-		DRM_ERROR("copy_to_user failed %p %u\n",
-			  user_sizes, srf->num_sizes);
-		ret = -EFAULT;
-	}
-out_bad_resource:
-out_no_reference:
-	ttm_base_object_unref(&base);
-
-	return ret;
-}
-
-int vmw_surface_check(struct vmw_private *dev_priv,
-		      struct ttm_object_file *tfile,
-		      uint32_t handle, int *id)
-{
-	struct ttm_base_object *base;
-	struct vmw_user_surface *user_srf;
-
-	int ret = -EPERM;
-
-	base = ttm_base_object_lookup(tfile, handle);
-	if (unlikely(base == NULL))
-		return -EINVAL;
-
-	if (unlikely(base->object_type != VMW_RES_SURFACE))
-		goto out_bad_surface;
-
-	user_srf = container_of(base, struct vmw_user_surface, base);
-	*id = user_srf->srf.res.id;
-	ret = 0;
-
-out_bad_surface:
-	/**
-	 * FIXME: May deadlock here when called from the
-	 * command parsing code.
-	 */
-
-	ttm_base_object_unref(&base);
-	return ret;
-}
-
-/**
- * Buffer management.
- */
-void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
-{
-	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
-
-	kfree(vmw_bo);
-}
-
-int vmw_dmabuf_init(struct vmw_private *dev_priv,
-		    struct vmw_dma_buffer *vmw_bo,
-		    size_t size, struct ttm_placement *placement,
-		    bool interruptible,
-		    void (*bo_free) (struct ttm_buffer_object *bo))
-{
-	struct ttm_bo_device *bdev = &dev_priv->bdev;
-	size_t acc_size;
-	int ret;
-
-	BUG_ON(!bo_free);
-
-	acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct vmw_dma_buffer));
-	memset(vmw_bo, 0, sizeof(*vmw_bo));
-
-	INIT_LIST_HEAD(&vmw_bo->validate_list);
-
-	ret = ttm_bo_init(bdev, &vmw_bo->base, size,
-			  ttm_bo_type_device, placement,
-			  0, 0, interruptible,
-			  NULL, acc_size, NULL, bo_free);
-	return ret;
-}
-
-static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo)
-{
-	struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo);
-
-	kfree(vmw_user_bo);
-}
-
-static void vmw_user_dmabuf_release(struct ttm_base_object **p_base)
-{
-	struct vmw_user_dma_buffer *vmw_user_bo;
-	struct ttm_base_object *base = *p_base;
-	struct ttm_buffer_object *bo;
-
-	*p_base = NULL;
-
-	if (unlikely(base == NULL))
-		return;
-
-	vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, base);
-	bo = &vmw_user_bo->dma.base;
-	ttm_bo_unref(&bo);
-}
-
-int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
-			   struct drm_file *file_priv)
-{
-	struct vmw_private *dev_priv = vmw_priv(dev);
-	union drm_vmw_alloc_dmabuf_arg *arg =
-	    (union drm_vmw_alloc_dmabuf_arg *)data;
-	struct drm_vmw_alloc_dmabuf_req *req = &arg->req;
-	struct drm_vmw_dmabuf_rep *rep = &arg->rep;
-	struct vmw_user_dma_buffer *vmw_user_bo;
-	struct ttm_buffer_object *tmp;
-	struct vmw_master *vmaster = vmw_master(file_priv->master);
-	int ret;
-
-	vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL);
-	if (unlikely(vmw_user_bo == NULL))
-		return -ENOMEM;
-
-	ret = ttm_read_lock(&vmaster->lock, true);
-	if (unlikely(ret != 0)) {
-		kfree(vmw_user_bo);
-		return ret;
-	}
-
-	ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, req->size,
-			      &vmw_vram_sys_placement, true,
-			      &vmw_user_dmabuf_destroy);
-	if (unlikely(ret != 0))
-		goto out_no_dmabuf;
-
-	tmp = ttm_bo_reference(&vmw_user_bo->dma.base);
-	ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile,
-				   &vmw_user_bo->base,
-				   false,
-				   ttm_buffer_type,
-				   &vmw_user_dmabuf_release, NULL);
-	if (unlikely(ret != 0))
-		goto out_no_base_object;
-	else {
-		rep->handle = vmw_user_bo->base.hash.key;
-		rep->map_handle = vmw_user_bo->dma.base.addr_space_offset;
-		rep->cur_gmr_id = vmw_user_bo->base.hash.key;
-		rep->cur_gmr_offset = 0;
-	}
+		goto out_no_dmabuf;
+
+	rep->handle = handle;
+	rep->map_handle = dma_buf->base.addr_space_offset;
+	rep->cur_gmr_id = handle;
+	rep->cur_gmr_offset = 0;
+
+	vmw_dmabuf_unreference(&dma_buf);
 
-out_no_base_object:
-	ttm_bo_unref(&tmp);
 out_no_dmabuf:
 	ttm_read_unlock(&vmaster->lock);
 
@@ -1657,27 +524,6 @@ int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data,
 					 TTM_REF_USAGE);
 }
 
-uint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo,
-				  uint32_t cur_validate_node)
-{
-	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
-
-	if (likely(vmw_bo->on_validate_list))
-		return vmw_bo->cur_validate_node;
-
-	vmw_bo->cur_validate_node = cur_validate_node;
-	vmw_bo->on_validate_list = true;
-
-	return cur_validate_node;
-}
-
-void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo)
-{
-	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
-
-	vmw_bo->on_validate_list = false;
-}
-
 int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
 			   uint32_t handle, struct vmw_dma_buffer **out)
 {
@@ -1706,6 +552,18 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
 	return 0;
 }
 
+int vmw_user_dmabuf_reference(struct ttm_object_file *tfile,
+			      struct vmw_dma_buffer *dma_buf)
+{
+	struct vmw_user_dma_buffer *user_bo;
+
+	if (dma_buf->base.destroy != vmw_user_dmabuf_destroy)
+		return -EINVAL;
+
+	user_bo = container_of(dma_buf, struct vmw_user_dma_buffer, dma);
+	return ttm_ref_object_add(tfile, &user_bo->base, TTM_REF_USAGE, NULL);
+}
+
 /*
  * Stream management
  */
@@ -1730,8 +588,8 @@ static int vmw_stream_init(struct vmw_private *dev_priv,
 	struct vmw_resource *res = &stream->res;
 	int ret;
 
-	ret = vmw_resource_init(dev_priv, res, &dev_priv->stream_idr,
-				VMW_RES_STREAM, false, res_free, NULL);
+	ret = vmw_resource_init(dev_priv, res, false, res_free,
+				&vmw_stream_func);
 
 	if (unlikely(ret != 0)) {
 		if (res_free == NULL)
@@ -1753,17 +611,13 @@ static int vmw_stream_init(struct vmw_private *dev_priv,
 	return 0;
 }
 
-/**
- * User-space context management:
- */
-
 static void vmw_user_stream_free(struct vmw_resource *res)
 {
 	struct vmw_user_stream *stream =
 	    container_of(res, struct vmw_user_stream, stream.res);
 	struct vmw_private *dev_priv = res->dev_priv;
 
-	kfree(stream);
+	ttm_base_object_kfree(stream, base);
 	ttm_mem_global_free(vmw_mem_glob(dev_priv),
 			    vmw_user_stream_size);
 }
@@ -1792,9 +646,11 @@ int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
 	struct vmw_user_stream *stream;
 	struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data;
 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct idr *idr = &dev_priv->res_idr[vmw_res_stream];
 	int ret = 0;
 
-	res = vmw_resource_lookup(dev_priv, &dev_priv->stream_idr, arg->stream_id);
+
+	res = vmw_resource_lookup(dev_priv, idr, arg->stream_id);
 	if (unlikely(res == NULL))
 		return -EINVAL;
 
@@ -1895,7 +751,8 @@ int vmw_user_stream_lookup(struct vmw_private *dev_priv,
 	struct vmw_resource *res;
 	int ret;
 
-	res = vmw_resource_lookup(dev_priv, &dev_priv->stream_idr, *inout_id);
+	res = vmw_resource_lookup(dev_priv, &dev_priv->res_idr[vmw_res_stream],
+				  *inout_id);
 	if (unlikely(res == NULL))
 		return -EINVAL;
 
@@ -1990,3 +847,453 @@ int vmw_dumb_destroy(struct drm_file *file_priv,
 	return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
 					 handle, TTM_REF_USAGE);
 }
+
+/**
+ * vmw_resource_buf_alloc - Allocate a backup buffer for a resource.
+ *
+ * @res:            The resource for which to allocate a backup buffer.
+ * @interruptible:  Whether any sleeps during allocation should be
+ *                  performed while interruptible.
+ */
+static int vmw_resource_buf_alloc(struct vmw_resource *res,
+				  bool interruptible)
+{
+	unsigned long size =
+		(res->backup_size + PAGE_SIZE - 1) & PAGE_MASK;
+	struct vmw_dma_buffer *backup;
+	int ret;
+
+	if (likely(res->backup)) {
+		BUG_ON(res->backup->base.num_pages * PAGE_SIZE < size);
+		return 0;
+	}
+
+	backup = kzalloc(sizeof(*backup), GFP_KERNEL);
+	if (unlikely(backup == NULL))
+		return -ENOMEM;
+
+	ret = vmw_dmabuf_init(res->dev_priv, backup, res->backup_size,
+			      res->func->backup_placement,
+			      interruptible,
+			      &vmw_dmabuf_bo_free);
+	if (unlikely(ret != 0))
+		goto out_no_dmabuf;
+
+	res->backup = backup;
+
+out_no_dmabuf:
+	return ret;
+}
+
+/**
+ * vmw_resource_do_validate - Make a resource up-to-date and visible
+ *                            to the device.
+ *
+ * @res:            The resource to make visible to the device.
+ * @val_buf:        Information about a buffer possibly
+ *                  containing backup data if a bind operation is needed.
+ *
+ * On hardware resource shortage, this function returns -EBUSY and
+ * should be retried once resources have been freed up.
+ */
+static int vmw_resource_do_validate(struct vmw_resource *res,
+				    struct ttm_validate_buffer *val_buf)
+{
+	int ret = 0;
+	const struct vmw_res_func *func = res->func;
+
+	if (unlikely(res->id == -1)) {
+		ret = func->create(res);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+
+	if (func->bind &&
+	    ((func->needs_backup && list_empty(&res->mob_head) &&
+	      val_buf->bo != NULL) ||
+	     (!func->needs_backup && val_buf->bo != NULL))) {
+		ret = func->bind(res, val_buf);
+		if (unlikely(ret != 0))
+			goto out_bind_failed;
+		if (func->needs_backup)
+			list_add_tail(&res->mob_head, &res->backup->res_list);
+	}
+
+	/*
+	 * Only do this on write operations, and move to
+	 * vmw_resource_unreserve if it can be called after
+	 * backup buffers have been unreserved. Otherwise
+	 * sort out locking.
+	 */
+	res->res_dirty = true;
+
+	return 0;
+
+out_bind_failed:
+	func->destroy(res);
+
+	return ret;
+}
+
+/**
+ * vmw_resource_unreserve - Unreserve a resource previously reserved for
+ * command submission.
+ *
+ * @res:               Pointer to the struct vmw_resource to unreserve.
+ * @new_backup:        Pointer to new backup buffer if command submission
+ *                     switched.
+ * @new_backup_offset: New backup offset if @new_backup is !NULL.
+ *
+ * Currently unreserving a resource means putting it back on the device's
+ * resource lru list, so that it can be evicted if necessary.
+ */
+void vmw_resource_unreserve(struct vmw_resource *res,
+			    struct vmw_dma_buffer *new_backup,
+			    unsigned long new_backup_offset)
+{
+	struct vmw_private *dev_priv = res->dev_priv;
+
+	if (!list_empty(&res->lru_head))
+		return;
+
+	if (new_backup && new_backup != res->backup) {
+
+		if (res->backup) {
+			BUG_ON(atomic_read(&res->backup->base.reserved) == 0);
+			list_del_init(&res->mob_head);
+			vmw_dmabuf_unreference(&res->backup);
+		}
+
+		res->backup = vmw_dmabuf_reference(new_backup);
+		BUG_ON(atomic_read(&new_backup->base.reserved) == 0);
+		list_add_tail(&res->mob_head, &new_backup->res_list);
+	}
+	if (new_backup)
+		res->backup_offset = new_backup_offset;
+
+	if (!res->func->may_evict)
+		return;
+
+	write_lock(&dev_priv->resource_lock);
+	list_add_tail(&res->lru_head,
+		      &res->dev_priv->res_lru[res->func->res_type]);
+	write_unlock(&dev_priv->resource_lock);
+}
+
+/**
+ * vmw_resource_check_buffer - Check whether a backup buffer is needed
+ *                             for a resource and in that case, allocate
+ *                             one, reserve and validate it.
+ *
+ * @res:            The resource for which to allocate a backup buffer.
+ * @interruptible:  Whether any sleeps during allocation should be
+ *                  performed while interruptible.
+ * @val_buf:        On successful return contains data about the
+ *                  reserved and validated backup buffer.
+ */
+int vmw_resource_check_buffer(struct vmw_resource *res,
+			      bool interruptible,
+			      struct ttm_validate_buffer *val_buf)
+{
+	struct list_head val_list;
+	bool backup_dirty = false;
+	int ret;
+
+	if (unlikely(res->backup == NULL)) {
+		ret = vmw_resource_buf_alloc(res, interruptible);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+
+	INIT_LIST_HEAD(&val_list);
+	val_buf->bo = ttm_bo_reference(&res->backup->base);
+	list_add_tail(&val_buf->head, &val_list);
+	ret = ttm_eu_reserve_buffers(&val_list);
+	if (unlikely(ret != 0))
+		goto out_no_reserve;
+
+	if (res->func->needs_backup && list_empty(&res->mob_head))
+		return 0;
+
+	backup_dirty = res->backup_dirty;
+	ret = ttm_bo_validate(&res->backup->base,
+			      res->func->backup_placement,
+			      true, false, false);
+
+	if (unlikely(ret != 0))
+		goto out_no_validate;
+
+	return 0;
+
+out_no_validate:
+	ttm_eu_backoff_reservation(&val_list);
+out_no_reserve:
+	ttm_bo_unref(&val_buf->bo);
+	if (backup_dirty)
+		vmw_dmabuf_unreference(&res->backup);
+
+	return ret;
+}
+
+/**
+ * vmw_resource_reserve - Reserve a resource for command submission
+ *
+ * @res:            The resource to reserve.
+ *
+ * This function takes the resource off the LRU list and make sure
+ * a backup buffer is present for guest-backed resources. However,
+ * the buffer may not be bound to the resource at this point.
+ *
+ */
+int vmw_resource_reserve(struct vmw_resource *res, bool no_backup)
+{
+	struct vmw_private *dev_priv = res->dev_priv;
+	int ret;
+
+	write_lock(&dev_priv->resource_lock);
+	list_del_init(&res->lru_head);
+	write_unlock(&dev_priv->resource_lock);
+
+	if (res->func->needs_backup && res->backup == NULL &&
+	    !no_backup) {
+		ret = vmw_resource_buf_alloc(res, true);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * vmw_resource_backoff_reservation - Unreserve and unreference a
+ *                                    backup buffer
+ *.
+ * @val_buf:        Backup buffer information.
+ */
+void vmw_resource_backoff_reservation(struct ttm_validate_buffer *val_buf)
+{
+	struct list_head val_list;
+
+	if (likely(val_buf->bo == NULL))
+		return;
+
+	INIT_LIST_HEAD(&val_list);
+	list_add_tail(&val_buf->head, &val_list);
+	ttm_eu_backoff_reservation(&val_list);
+	ttm_bo_unref(&val_buf->bo);
+}
+
+/**
+ * vmw_resource_do_evict - Evict a resource, and transfer its data
+ *                         to a backup buffer.
+ *
+ * @res:            The resource to evict.
+ */
+int vmw_resource_do_evict(struct vmw_resource *res)
+{
+	struct ttm_validate_buffer val_buf;
+	const struct vmw_res_func *func = res->func;
+	int ret;
+
+	BUG_ON(!func->may_evict);
+
+	val_buf.bo = NULL;
+	ret = vmw_resource_check_buffer(res, true, &val_buf);
+	if (unlikely(ret != 0))
+		return ret;
+
+	if (unlikely(func->unbind != NULL &&
+		     (!func->needs_backup || !list_empty(&res->mob_head)))) {
+		ret = func->unbind(res, res->res_dirty, &val_buf);
+		if (unlikely(ret != 0))
+			goto out_no_unbind;
+		list_del_init(&res->mob_head);
+	}
+	ret = func->destroy(res);
+	res->backup_dirty = true;
+	res->res_dirty = false;
+out_no_unbind:
+	vmw_resource_backoff_reservation(&val_buf);
+
+	return ret;
+}
+
+
+/**
+ * vmw_resource_validate - Make a resource up-to-date and visible
+ *                         to the device.
+ *
+ * @res:            The resource to make visible to the device.
+ *
+ * On succesful return, any backup DMA buffer pointed to by @res->backup will
+ * be reserved and validated.
+ * On hardware resource shortage, this function will repeatedly evict
+ * resources of the same type until the validation succeeds.
+ */
+int vmw_resource_validate(struct vmw_resource *res)
+{
+	int ret;
+	struct vmw_resource *evict_res;
+	struct vmw_private *dev_priv = res->dev_priv;
+	struct list_head *lru_list = &dev_priv->res_lru[res->func->res_type];
+	struct ttm_validate_buffer val_buf;
+
+	if (likely(!res->func->may_evict))
+		return 0;
+
+	val_buf.bo = NULL;
+	if (res->backup)
+		val_buf.bo = &res->backup->base;
+	do {
+		ret = vmw_resource_do_validate(res, &val_buf);
+		if (likely(ret != -EBUSY))
+			break;
+
+		write_lock(&dev_priv->resource_lock);
+		if (list_empty(lru_list) || !res->func->may_evict) {
+			DRM_ERROR("Out of device device id entries "
+				  "for %s.\n", res->func->type_name);
+			ret = -EBUSY;
+			write_unlock(&dev_priv->resource_lock);
+			break;
+		}
+
+		evict_res = vmw_resource_reference
+			(list_first_entry(lru_list, struct vmw_resource,
+					  lru_head));
+		list_del_init(&evict_res->lru_head);
+
+		write_unlock(&dev_priv->resource_lock);
+		vmw_resource_do_evict(evict_res);
+		vmw_resource_unreference(&evict_res);
+	} while (1);
+
+	if (unlikely(ret != 0))
+		goto out_no_validate;
+	else if (!res->func->needs_backup && res->backup) {
+		list_del_init(&res->mob_head);
+		vmw_dmabuf_unreference(&res->backup);
+	}
+
+	return 0;
+
+out_no_validate:
+	return ret;
+}
+
+/**
+ * vmw_fence_single_bo - Utility function to fence a single TTM buffer
+ *                       object without unreserving it.
+ *
+ * @bo:             Pointer to the struct ttm_buffer_object to fence.
+ * @fence:          Pointer to the fence. If NULL, this function will
+ *                  insert a fence into the command stream..
+ *
+ * Contrary to the ttm_eu version of this function, it takes only
+ * a single buffer object instead of a list, and it also doesn't
+ * unreserve the buffer object, which needs to be done separately.
+ */
+void vmw_fence_single_bo(struct ttm_buffer_object *bo,
+			 struct vmw_fence_obj *fence)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	struct ttm_bo_driver *driver = bdev->driver;
+	struct vmw_fence_obj *old_fence_obj;
+	struct vmw_private *dev_priv =
+		container_of(bdev, struct vmw_private, bdev);
+
+	if (fence == NULL)
+		vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
+	else
+		driver->sync_obj_ref(fence);
+
+	spin_lock(&bdev->fence_lock);
+
+	old_fence_obj = bo->sync_obj;
+	bo->sync_obj = fence;
+
+	spin_unlock(&bdev->fence_lock);
+
+	if (old_fence_obj)
+		vmw_fence_obj_unreference(&old_fence_obj);
+}
+
+/**
+ * vmw_resource_move_notify - TTM move_notify_callback
+ *
+ * @bo:             The TTM buffer object about to move.
+ * @mem:            The truct ttm_mem_reg indicating to what memory
+ *                  region the move is taking place.
+ *
+ * For now does nothing.
+ */
+void vmw_resource_move_notify(struct ttm_buffer_object *bo,
+			      struct ttm_mem_reg *mem)
+{
+}
+
+/**
+ * vmw_resource_needs_backup - Return whether a resource needs a backup buffer.
+ *
+ * @res:            The resource being queried.
+ */
+bool vmw_resource_needs_backup(const struct vmw_resource *res)
+{
+	return res->func->needs_backup;
+}
+
+/**
+ * vmw_resource_evict_type - Evict all resources of a specific type
+ *
+ * @dev_priv:       Pointer to a device private struct
+ * @type:           The resource type to evict
+ *
+ * To avoid thrashing starvation or as part of the hibernation sequence,
+ * evict all evictable resources of a specific type.
+ */
+static void vmw_resource_evict_type(struct vmw_private *dev_priv,
+				    enum vmw_res_type type)
+{
+	struct list_head *lru_list = &dev_priv->res_lru[type];
+	struct vmw_resource *evict_res;
+
+	do {
+		write_lock(&dev_priv->resource_lock);
+
+		if (list_empty(lru_list))
+			goto out_unlock;
+
+		evict_res = vmw_resource_reference(
+			list_first_entry(lru_list, struct vmw_resource,
+					 lru_head));
+		list_del_init(&evict_res->lru_head);
+		write_unlock(&dev_priv->resource_lock);
+		vmw_resource_do_evict(evict_res);
+		vmw_resource_unreference(&evict_res);
+	} while (1);
+
+out_unlock:
+	write_unlock(&dev_priv->resource_lock);
+}
+
+/**
+ * vmw_resource_evict_all - Evict all evictable resources
+ *
+ * @dev_priv:       Pointer to a device private struct
+ *
+ * To avoid thrashing starvation or as part of the hibernation sequence,
+ * evict all evictable resources. In particular this means that all
+ * guest-backed resources that are registered with the device are
+ * evicted and the OTable becomes clean.
+ */
+void vmw_resource_evict_all(struct vmw_private *dev_priv)
+{
+	enum vmw_res_type type;
+
+	mutex_lock(&dev_priv->cmdbuf_mutex);
+
+	for (type = 0; type < vmw_res_max; ++type)
+		vmw_resource_evict_type(dev_priv, type);
+
+	mutex_unlock(&dev_priv->cmdbuf_mutex);
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h
new file mode 100644
index 0000000..f3adeed
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h
@@ -0,0 +1,84 @@
+/**************************************************************************
+ *
+ * Copyright © 2012 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef _VMWGFX_RESOURCE_PRIV_H_
+#define _VMWGFX_RESOURCE_PRIV_H_
+
+#include "vmwgfx_drv.h"
+
+/**
+ * struct vmw_user_resource_conv - Identify a derived user-exported resource
+ * type and provide a function to convert its ttm_base_object pointer to
+ * a struct vmw_resource
+ */
+struct vmw_user_resource_conv {
+	enum ttm_object_type object_type;
+	struct vmw_resource *(*base_obj_to_res)(struct ttm_base_object *base);
+	void (*res_free) (struct vmw_resource *res);
+};
+
+/**
+ * struct vmw_res_func - members and functions common for a resource type
+ *
+ * @res_type:          Enum that identifies the lru list to use for eviction.
+ * @needs_backup:      Whether the resource is guest-backed and needs
+ *                     persistent buffer storage.
+ * @type_name:         String that identifies the resource type.
+ * @backup_placement:  TTM placement for backup buffers.
+ * @may_evict          Whether the resource may be evicted.
+ * @create:            Create a hardware resource.
+ * @destroy:           Destroy a hardware resource.
+ * @bind:              Bind a hardware resource to persistent buffer storage.
+ * @unbind:            Unbind a hardware resource from persistent
+ *                     buffer storage.
+ */
+
+struct vmw_res_func {
+	enum vmw_res_type res_type;
+	bool needs_backup;
+	const char *type_name;
+	struct ttm_placement *backup_placement;
+	bool may_evict;
+
+	int (*create) (struct vmw_resource *res);
+	int (*destroy) (struct vmw_resource *res);
+	int (*bind) (struct vmw_resource *res,
+		     struct ttm_validate_buffer *val_buf);
+	int (*unbind) (struct vmw_resource *res,
+		       bool readback,
+		       struct ttm_validate_buffer *val_buf);
+};
+
+int vmw_resource_alloc_id(struct vmw_resource *res);
+void vmw_resource_release_id(struct vmw_resource *res);
+int vmw_resource_init(struct vmw_private *dev_priv, struct vmw_resource *res,
+		      bool delay_id,
+		      void (*res_free) (struct vmw_resource *res),
+		      const struct vmw_res_func *func);
+void vmw_resource_activate(struct vmw_resource *res,
+			   void (*hw_destroy) (struct vmw_resource *));
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index 6deaf2f..60f1285 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -485,7 +485,7 @@ int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv)
 		return -EINVAL;
 	}
 
-	if (!(dev_priv->fifo.capabilities & SVGA_FIFO_CAP_SCREEN_OBJECT_2)) {
+	if (!(dev_priv->capabilities & SVGA_CAP_SCREEN_OBJECT_2)) {
 		DRM_INFO("Not using screen objects,"
 			 " missing cap SCREEN_OBJECT_2\n");
 		return -ENOSYS;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
new file mode 100644
index 0000000..5828143
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -0,0 +1,893 @@
+/**************************************************************************
+ *
+ * Copyright © 2009-2012 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_drv.h"
+#include "vmwgfx_resource_priv.h"
+#include <ttm/ttm_placement.h>
+#include "svga3d_surfacedefs.h"
+
+/**
+ * struct vmw_user_surface - User-space visible surface resource
+ *
+ * @base:           The TTM base object handling user-space visibility.
+ * @srf:            The surface metadata.
+ * @size:           TTM accounting size for the surface.
+ */
+struct vmw_user_surface {
+	struct ttm_base_object base;
+	struct vmw_surface srf;
+	uint32_t size;
+	uint32_t backup_handle;
+};
+
+/**
+ * struct vmw_surface_offset - Backing store mip level offset info
+ *
+ * @face:           Surface face.
+ * @mip:            Mip level.
+ * @bo_offset:      Offset into backing store of this mip level.
+ *
+ */
+struct vmw_surface_offset {
+	uint32_t face;
+	uint32_t mip;
+	uint32_t bo_offset;
+};
+
+static void vmw_user_surface_free(struct vmw_resource *res);
+static struct vmw_resource *
+vmw_user_surface_base_to_res(struct ttm_base_object *base);
+static int vmw_legacy_srf_bind(struct vmw_resource *res,
+			       struct ttm_validate_buffer *val_buf);
+static int vmw_legacy_srf_unbind(struct vmw_resource *res,
+				 bool readback,
+				 struct ttm_validate_buffer *val_buf);
+static int vmw_legacy_srf_create(struct vmw_resource *res);
+static int vmw_legacy_srf_destroy(struct vmw_resource *res);
+
+static const struct vmw_user_resource_conv user_surface_conv = {
+	.object_type = VMW_RES_SURFACE,
+	.base_obj_to_res = vmw_user_surface_base_to_res,
+	.res_free = vmw_user_surface_free
+};
+
+const struct vmw_user_resource_conv *user_surface_converter =
+	&user_surface_conv;
+
+
+static uint64_t vmw_user_surface_size;
+
+static const struct vmw_res_func vmw_legacy_surface_func = {
+	.res_type = vmw_res_surface,
+	.needs_backup = false,
+	.may_evict = true,
+	.type_name = "legacy surfaces",
+	.backup_placement = &vmw_srf_placement,
+	.create = &vmw_legacy_srf_create,
+	.destroy = &vmw_legacy_srf_destroy,
+	.bind = &vmw_legacy_srf_bind,
+	.unbind = &vmw_legacy_srf_unbind
+};
+
+/**
+ * struct vmw_surface_dma - SVGA3D DMA command
+ */
+struct vmw_surface_dma {
+	SVGA3dCmdHeader header;
+	SVGA3dCmdSurfaceDMA body;
+	SVGA3dCopyBox cb;
+	SVGA3dCmdSurfaceDMASuffix suffix;
+};
+
+/**
+ * struct vmw_surface_define - SVGA3D Surface Define command
+ */
+struct vmw_surface_define {
+	SVGA3dCmdHeader header;
+	SVGA3dCmdDefineSurface body;
+};
+
+/**
+ * struct vmw_surface_destroy - SVGA3D Surface Destroy command
+ */
+struct vmw_surface_destroy {
+	SVGA3dCmdHeader header;
+	SVGA3dCmdDestroySurface body;
+};
+
+
+/**
+ * vmw_surface_dma_size - Compute fifo size for a dma command.
+ *
+ * @srf: Pointer to a struct vmw_surface
+ *
+ * Computes the required size for a surface dma command for backup or
+ * restoration of the surface represented by @srf.
+ */
+static inline uint32_t vmw_surface_dma_size(const struct vmw_surface *srf)
+{
+	return srf->num_sizes * sizeof(struct vmw_surface_dma);
+}
+
+
+/**
+ * vmw_surface_define_size - Compute fifo size for a surface define command.
+ *
+ * @srf: Pointer to a struct vmw_surface
+ *
+ * Computes the required size for a surface define command for the definition
+ * of the surface represented by @srf.
+ */
+static inline uint32_t vmw_surface_define_size(const struct vmw_surface *srf)
+{
+	return sizeof(struct vmw_surface_define) + srf->num_sizes *
+		sizeof(SVGA3dSize);
+}
+
+
+/**
+ * vmw_surface_destroy_size - Compute fifo size for a surface destroy command.
+ *
+ * Computes the required size for a surface destroy command for the destruction
+ * of a hw surface.
+ */
+static inline uint32_t vmw_surface_destroy_size(void)
+{
+	return sizeof(struct vmw_surface_destroy);
+}
+
+/**
+ * vmw_surface_destroy_encode - Encode a surface_destroy command.
+ *
+ * @id: The surface id
+ * @cmd_space: Pointer to memory area in which the commands should be encoded.
+ */
+static void vmw_surface_destroy_encode(uint32_t id,
+				       void *cmd_space)
+{
+	struct vmw_surface_destroy *cmd = (struct vmw_surface_destroy *)
+		cmd_space;
+
+	cmd->header.id = SVGA_3D_CMD_SURFACE_DESTROY;
+	cmd->header.size = sizeof(cmd->body);
+	cmd->body.sid = id;
+}
+
+/**
+ * vmw_surface_define_encode - Encode a surface_define command.
+ *
+ * @srf: Pointer to a struct vmw_surface object.
+ * @cmd_space: Pointer to memory area in which the commands should be encoded.
+ */
+static void vmw_surface_define_encode(const struct vmw_surface *srf,
+				      void *cmd_space)
+{
+	struct vmw_surface_define *cmd = (struct vmw_surface_define *)
+		cmd_space;
+	struct drm_vmw_size *src_size;
+	SVGA3dSize *cmd_size;
+	uint32_t cmd_len;
+	int i;
+
+	cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize);
+
+	cmd->header.id = SVGA_3D_CMD_SURFACE_DEFINE;
+	cmd->header.size = cmd_len;
+	cmd->body.sid = srf->res.id;
+	cmd->body.surfaceFlags = srf->flags;
+	cmd->body.format = cpu_to_le32(srf->format);
+	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
+		cmd->body.face[i].numMipLevels = srf->mip_levels[i];
+
+	cmd += 1;
+	cmd_size = (SVGA3dSize *) cmd;
+	src_size = srf->sizes;
+
+	for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) {
+		cmd_size->width = src_size->width;
+		cmd_size->height = src_size->height;
+		cmd_size->depth = src_size->depth;
+	}
+}
+
+/**
+ * vmw_surface_dma_encode - Encode a surface_dma command.
+ *
+ * @srf: Pointer to a struct vmw_surface object.
+ * @cmd_space: Pointer to memory area in which the commands should be encoded.
+ * @ptr: Pointer to an SVGAGuestPtr indicating where the surface contents
+ * should be placed or read from.
+ * @to_surface: Boolean whether to DMA to the surface or from the surface.
+ */
+static void vmw_surface_dma_encode(struct vmw_surface *srf,
+				   void *cmd_space,
+				   const SVGAGuestPtr *ptr,
+				   bool to_surface)
+{
+	uint32_t i;
+	struct vmw_surface_dma *cmd = (struct vmw_surface_dma *)cmd_space;
+	const struct svga3d_surface_desc *desc =
+		svga3dsurface_get_desc(srf->format);
+
+	for (i = 0; i < srf->num_sizes; ++i) {
+		SVGA3dCmdHeader *header = &cmd->header;
+		SVGA3dCmdSurfaceDMA *body = &cmd->body;
+		SVGA3dCopyBox *cb = &cmd->cb;
+		SVGA3dCmdSurfaceDMASuffix *suffix = &cmd->suffix;
+		const struct vmw_surface_offset *cur_offset = &srf->offsets[i];
+		const struct drm_vmw_size *cur_size = &srf->sizes[i];
+
+		header->id = SVGA_3D_CMD_SURFACE_DMA;
+		header->size = sizeof(*body) + sizeof(*cb) + sizeof(*suffix);
+
+		body->guest.ptr = *ptr;
+		body->guest.ptr.offset += cur_offset->bo_offset;
+		body->guest.pitch = svga3dsurface_calculate_pitch(desc,
+								  cur_size);
+		body->host.sid = srf->res.id;
+		body->host.face = cur_offset->face;
+		body->host.mipmap = cur_offset->mip;
+		body->transfer = ((to_surface) ?  SVGA3D_WRITE_HOST_VRAM :
+				  SVGA3D_READ_HOST_VRAM);
+		cb->x = 0;
+		cb->y = 0;
+		cb->z = 0;
+		cb->srcx = 0;
+		cb->srcy = 0;
+		cb->srcz = 0;
+		cb->w = cur_size->width;
+		cb->h = cur_size->height;
+		cb->d = cur_size->depth;
+
+		suffix->suffixSize = sizeof(*suffix);
+		suffix->maximumOffset =
+			svga3dsurface_get_image_buffer_size(desc, cur_size,
+							    body->guest.pitch);
+		suffix->flags.discard = 0;
+		suffix->flags.unsynchronized = 0;
+		suffix->flags.reserved = 0;
+		++cmd;
+	}
+};
+
+
+/**
+ * vmw_hw_surface_destroy - destroy a Device surface
+ *
+ * @res:        Pointer to a struct vmw_resource embedded in a struct
+ *              vmw_surface.
+ *
+ * Destroys a the device surface associated with a struct vmw_surface if
+ * any, and adjusts accounting and resource count accordingly.
+ */
+static void vmw_hw_surface_destroy(struct vmw_resource *res)
+{
+
+	struct vmw_private *dev_priv = res->dev_priv;
+	struct vmw_surface *srf;
+	void *cmd;
+
+	if (res->id != -1) {
+
+		cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size());
+		if (unlikely(cmd == NULL)) {
+			DRM_ERROR("Failed reserving FIFO space for surface "
+				  "destruction.\n");
+			return;
+		}
+
+		vmw_surface_destroy_encode(res->id, cmd);
+		vmw_fifo_commit(dev_priv, vmw_surface_destroy_size());
+
+		/*
+		 * used_memory_size_atomic, or separate lock
+		 * to avoid taking dev_priv::cmdbuf_mutex in
+		 * the destroy path.
+		 */
+
+		mutex_lock(&dev_priv->cmdbuf_mutex);
+		srf = vmw_res_to_srf(res);
+		dev_priv->used_memory_size -= res->backup_size;
+		mutex_unlock(&dev_priv->cmdbuf_mutex);
+	}
+	vmw_3d_resource_dec(dev_priv, false);
+}
+
+/**
+ * vmw_legacy_srf_create - Create a device surface as part of the
+ * resource validation process.
+ *
+ * @res: Pointer to a struct vmw_surface.
+ *
+ * If the surface doesn't have a hw id.
+ *
+ * Returns -EBUSY if there wasn't sufficient device resources to
+ * complete the validation. Retry after freeing up resources.
+ *
+ * May return other errors if the kernel is out of guest resources.
+ */
+static int vmw_legacy_srf_create(struct vmw_resource *res)
+{
+	struct vmw_private *dev_priv = res->dev_priv;
+	struct vmw_surface *srf;
+	uint32_t submit_size;
+	uint8_t *cmd;
+	int ret;
+
+	if (likely(res->id != -1))
+		return 0;
+
+	srf = vmw_res_to_srf(res);
+	if (unlikely(dev_priv->used_memory_size + res->backup_size >=
+		     dev_priv->memory_size))
+		return -EBUSY;
+
+	/*
+	 * Alloc id for the resource.
+	 */
+
+	ret = vmw_resource_alloc_id(res);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed to allocate a surface id.\n");
+		goto out_no_id;
+	}
+
+	if (unlikely(res->id >= SVGA3D_MAX_SURFACE_IDS)) {
+		ret = -EBUSY;
+		goto out_no_fifo;
+	}
+
+	/*
+	 * Encode surface define- commands.
+	 */
+
+	submit_size = vmw_surface_define_size(srf);
+	cmd = vmw_fifo_reserve(dev_priv, submit_size);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed reserving FIFO space for surface "
+			  "creation.\n");
+		ret = -ENOMEM;
+		goto out_no_fifo;
+	}
+
+	vmw_surface_define_encode(srf, cmd);
+	vmw_fifo_commit(dev_priv, submit_size);
+	/*
+	 * Surface memory usage accounting.
+	 */
+
+	dev_priv->used_memory_size += res->backup_size;
+	return 0;
+
+out_no_fifo:
+	vmw_resource_release_id(res);
+out_no_id:
+	return ret;
+}
+
+/**
+ * vmw_legacy_srf_dma - Copy backup data to or from a legacy surface.
+ *
+ * @res:            Pointer to a struct vmw_res embedded in a struct
+ *                  vmw_surface.
+ * @val_buf:        Pointer to a struct ttm_validate_buffer containing
+ *                  information about the backup buffer.
+ * @bind:           Boolean wether to DMA to the surface.
+ *
+ * Transfer backup data to or from a legacy surface as part of the
+ * validation process.
+ * May return other errors if the kernel is out of guest resources.
+ * The backup buffer will be fenced or idle upon successful completion,
+ * and if the surface needs persistent backup storage, the backup buffer
+ * will also be returned reserved iff @bind is true.
+ */
+static int vmw_legacy_srf_dma(struct vmw_resource *res,
+			      struct ttm_validate_buffer *val_buf,
+			      bool bind)
+{
+	SVGAGuestPtr ptr;
+	struct vmw_fence_obj *fence;
+	uint32_t submit_size;
+	struct vmw_surface *srf = vmw_res_to_srf(res);
+	uint8_t *cmd;
+	struct vmw_private *dev_priv = res->dev_priv;
+
+	BUG_ON(val_buf->bo == NULL);
+
+	submit_size = vmw_surface_dma_size(srf);
+	cmd = vmw_fifo_reserve(dev_priv, submit_size);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed reserving FIFO space for surface "
+			  "DMA.\n");
+		return -ENOMEM;
+	}
+	vmw_bo_get_guest_ptr(val_buf->bo, &ptr);
+	vmw_surface_dma_encode(srf, cmd, &ptr, bind);
+
+	vmw_fifo_commit(dev_priv, submit_size);
+
+	/*
+	 * Create a fence object and fence the backup buffer.
+	 */
+
+	(void) vmw_execbuf_fence_commands(NULL, dev_priv,
+					  &fence, NULL);
+
+	vmw_fence_single_bo(val_buf->bo, fence);
+
+	if (likely(fence != NULL))
+		vmw_fence_obj_unreference(&fence);
+
+	return 0;
+}
+
+/**
+ * vmw_legacy_srf_bind - Perform a legacy surface bind as part of the
+ *                       surface validation process.
+ *
+ * @res:            Pointer to a struct vmw_res embedded in a struct
+ *                  vmw_surface.
+ * @val_buf:        Pointer to a struct ttm_validate_buffer containing
+ *                  information about the backup buffer.
+ *
+ * This function will copy backup data to the surface if the
+ * backup buffer is dirty.
+ */
+static int vmw_legacy_srf_bind(struct vmw_resource *res,
+			       struct ttm_validate_buffer *val_buf)
+{
+	if (!res->backup_dirty)
+		return 0;
+
+	return vmw_legacy_srf_dma(res, val_buf, true);
+}
+
+
+/**
+ * vmw_legacy_srf_unbind - Perform a legacy surface unbind as part of the
+ *                         surface eviction process.
+ *
+ * @res:            Pointer to a struct vmw_res embedded in a struct
+ *                  vmw_surface.
+ * @val_buf:        Pointer to a struct ttm_validate_buffer containing
+ *                  information about the backup buffer.
+ *
+ * This function will copy backup data from the surface.
+ */
+static int vmw_legacy_srf_unbind(struct vmw_resource *res,
+				 bool readback,
+				 struct ttm_validate_buffer *val_buf)
+{
+	if (unlikely(readback))
+		return vmw_legacy_srf_dma(res, val_buf, false);
+	return 0;
+}
+
+/**
+ * vmw_legacy_srf_destroy - Destroy a device surface as part of a
+ *                          resource eviction process.
+ *
+ * @res:            Pointer to a struct vmw_res embedded in a struct
+ *                  vmw_surface.
+ */
+static int vmw_legacy_srf_destroy(struct vmw_resource *res)
+{
+	struct vmw_private *dev_priv = res->dev_priv;
+	uint32_t submit_size;
+	uint8_t *cmd;
+
+	BUG_ON(res->id == -1);
+
+	/*
+	 * Encode the dma- and surface destroy commands.
+	 */
+
+	submit_size = vmw_surface_destroy_size();
+	cmd = vmw_fifo_reserve(dev_priv, submit_size);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed reserving FIFO space for surface "
+			  "eviction.\n");
+		return -ENOMEM;
+	}
+
+	vmw_surface_destroy_encode(res->id, cmd);
+	vmw_fifo_commit(dev_priv, submit_size);
+
+	/*
+	 * Surface memory usage accounting.
+	 */
+
+	dev_priv->used_memory_size -= res->backup_size;
+
+	/*
+	 * Release the surface ID.
+	 */
+
+	vmw_resource_release_id(res);
+
+	return 0;
+}
+
+
+/**
+ * vmw_surface_init - initialize a struct vmw_surface
+ *
+ * @dev_priv:       Pointer to a device private struct.
+ * @srf:            Pointer to the struct vmw_surface to initialize.
+ * @res_free:       Pointer to a resource destructor used to free
+ *                  the object.
+ */
+static int vmw_surface_init(struct vmw_private *dev_priv,
+			    struct vmw_surface *srf,
+			    void (*res_free) (struct vmw_resource *res))
+{
+	int ret;
+	struct vmw_resource *res = &srf->res;
+
+	BUG_ON(res_free == NULL);
+	(void) vmw_3d_resource_inc(dev_priv, false);
+	ret = vmw_resource_init(dev_priv, res, true, res_free,
+				&vmw_legacy_surface_func);
+
+	if (unlikely(ret != 0)) {
+		vmw_3d_resource_dec(dev_priv, false);
+		res_free(res);
+		return ret;
+	}
+
+	/*
+	 * The surface won't be visible to hardware until a
+	 * surface validate.
+	 */
+
+	vmw_resource_activate(res, vmw_hw_surface_destroy);
+	return ret;
+}
+
+/**
+ * vmw_user_surface_base_to_res - TTM base object to resource converter for
+ *                                user visible surfaces
+ *
+ * @base:           Pointer to a TTM base object
+ *
+ * Returns the struct vmw_resource embedded in a struct vmw_surface
+ * for the user-visible object identified by the TTM base object @base.
+ */
+static struct vmw_resource *
+vmw_user_surface_base_to_res(struct ttm_base_object *base)
+{
+	return &(container_of(base, struct vmw_user_surface, base)->srf.res);
+}
+
+/**
+ * vmw_user_surface_free - User visible surface resource destructor
+ *
+ * @res:            A struct vmw_resource embedded in a struct vmw_surface.
+ */
+static void vmw_user_surface_free(struct vmw_resource *res)
+{
+	struct vmw_surface *srf = vmw_res_to_srf(res);
+	struct vmw_user_surface *user_srf =
+	    container_of(srf, struct vmw_user_surface, srf);
+	struct vmw_private *dev_priv = srf->res.dev_priv;
+	uint32_t size = user_srf->size;
+
+	kfree(srf->offsets);
+	kfree(srf->sizes);
+	kfree(srf->snooper.image);
+	ttm_base_object_kfree(user_srf, base);
+	ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
+}
+
+/**
+ * vmw_user_surface_free - User visible surface TTM base object destructor
+ *
+ * @p_base:         Pointer to a pointer to a TTM base object
+ *                  embedded in a struct vmw_user_surface.
+ *
+ * Drops the base object's reference on its resource, and the
+ * pointer pointed to by *p_base is set to NULL.
+ */
+static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
+{
+	struct ttm_base_object *base = *p_base;
+	struct vmw_user_surface *user_srf =
+	    container_of(base, struct vmw_user_surface, base);
+	struct vmw_resource *res = &user_srf->srf.res;
+
+	*p_base = NULL;
+	vmw_resource_unreference(&res);
+}
+
+/**
+ * vmw_user_surface_destroy_ioctl - Ioctl function implementing
+ *                                  the user surface destroy functionality.
+ *
+ * @dev:            Pointer to a struct drm_device.
+ * @data:           Pointer to data copied from / to user-space.
+ * @file_priv:      Pointer to a drm file private structure.
+ */
+int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv)
+{
+	struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+
+	return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE);
+}
+
+/**
+ * vmw_user_surface_define_ioctl - Ioctl function implementing
+ *                                  the user surface define functionality.
+ *
+ * @dev:            Pointer to a struct drm_device.
+ * @data:           Pointer to data copied from / to user-space.
+ * @file_priv:      Pointer to a drm file private structure.
+ */
+int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_user_surface *user_srf;
+	struct vmw_surface *srf;
+	struct vmw_resource *res;
+	struct vmw_resource *tmp;
+	union drm_vmw_surface_create_arg *arg =
+	    (union drm_vmw_surface_create_arg *)data;
+	struct drm_vmw_surface_create_req *req = &arg->req;
+	struct drm_vmw_surface_arg *rep = &arg->rep;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct drm_vmw_size __user *user_sizes;
+	int ret;
+	int i, j;
+	uint32_t cur_bo_offset;
+	struct drm_vmw_size *cur_size;
+	struct vmw_surface_offset *cur_offset;
+	uint32_t num_sizes;
+	uint32_t size;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	const struct svga3d_surface_desc *desc;
+
+	if (unlikely(vmw_user_surface_size == 0))
+		vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
+			128;
+
+	num_sizes = 0;
+	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
+		num_sizes += req->mip_levels[i];
+
+	if (num_sizes > DRM_VMW_MAX_SURFACE_FACES *
+	    DRM_VMW_MAX_MIP_LEVELS)
+		return -EINVAL;
+
+	size = vmw_user_surface_size + 128 +
+		ttm_round_pot(num_sizes * sizeof(struct drm_vmw_size)) +
+		ttm_round_pot(num_sizes * sizeof(struct vmw_surface_offset));
+
+
+	desc = svga3dsurface_get_desc(req->format);
+	if (unlikely(desc->block_desc == SVGA3DBLOCKDESC_NONE)) {
+		DRM_ERROR("Invalid surface format for surface creation.\n");
+		return -EINVAL;
+	}
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+				   size, false, true);
+	if (unlikely(ret != 0)) {
+		if (ret != -ERESTARTSYS)
+			DRM_ERROR("Out of graphics memory for surface"
+				  " creation.\n");
+		goto out_unlock;
+	}
+
+	user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
+	if (unlikely(user_srf == NULL)) {
+		ret = -ENOMEM;
+		goto out_no_user_srf;
+	}
+
+	srf = &user_srf->srf;
+	res = &srf->res;
+
+	srf->flags = req->flags;
+	srf->format = req->format;
+	srf->scanout = req->scanout;
+
+	memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
+	srf->num_sizes = num_sizes;
+	user_srf->size = size;
+
+	srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL);
+	if (unlikely(srf->sizes == NULL)) {
+		ret = -ENOMEM;
+		goto out_no_sizes;
+	}
+	srf->offsets = kmalloc(srf->num_sizes * sizeof(*srf->offsets),
+			       GFP_KERNEL);
+	if (unlikely(srf->sizes == NULL)) {
+		ret = -ENOMEM;
+		goto out_no_offsets;
+	}
+
+	user_sizes = (struct drm_vmw_size __user *)(unsigned long)
+	    req->size_addr;
+
+	ret = copy_from_user(srf->sizes, user_sizes,
+			     srf->num_sizes * sizeof(*srf->sizes));
+	if (unlikely(ret != 0)) {
+		ret = -EFAULT;
+		goto out_no_copy;
+	}
+
+	srf->base_size = *srf->sizes;
+	srf->autogen_filter = SVGA3D_TEX_FILTER_NONE;
+	srf->multisample_count = 1;
+
+	cur_bo_offset = 0;
+	cur_offset = srf->offsets;
+	cur_size = srf->sizes;
+
+	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
+		for (j = 0; j < srf->mip_levels[i]; ++j) {
+			uint32_t stride = svga3dsurface_calculate_pitch
+				(desc, cur_size);
+
+			cur_offset->face = i;
+			cur_offset->mip = j;
+			cur_offset->bo_offset = cur_bo_offset;
+			cur_bo_offset += svga3dsurface_get_image_buffer_size
+				(desc, cur_size, stride);
+			++cur_offset;
+			++cur_size;
+		}
+	}
+	res->backup_size = cur_bo_offset;
+	if (srf->scanout &&
+	    srf->num_sizes == 1 &&
+	    srf->sizes[0].width == 64 &&
+	    srf->sizes[0].height == 64 &&
+	    srf->format == SVGA3D_A8R8G8B8) {
+
+		srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL);
+		/* clear the image */
+		if (srf->snooper.image) {
+			memset(srf->snooper.image, 0x00, 64 * 64 * 4);
+		} else {
+			DRM_ERROR("Failed to allocate cursor_image\n");
+			ret = -ENOMEM;
+			goto out_no_copy;
+		}
+	} else {
+		srf->snooper.image = NULL;
+	}
+	srf->snooper.crtc = NULL;
+
+	user_srf->base.shareable = false;
+	user_srf->base.tfile = NULL;
+
+	/**
+	 * From this point, the generic resource management functions
+	 * destroy the object on failure.
+	 */
+
+	ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
+	if (unlikely(ret != 0))
+		goto out_unlock;
+
+	tmp = vmw_resource_reference(&srf->res);
+	ret = ttm_base_object_init(tfile, &user_srf->base,
+				   req->shareable, VMW_RES_SURFACE,
+				   &vmw_user_surface_base_release, NULL);
+
+	if (unlikely(ret != 0)) {
+		vmw_resource_unreference(&tmp);
+		vmw_resource_unreference(&res);
+		goto out_unlock;
+	}
+
+	rep->sid = user_srf->base.hash.key;
+	vmw_resource_unreference(&res);
+
+	ttm_read_unlock(&vmaster->lock);
+	return 0;
+out_no_copy:
+	kfree(srf->offsets);
+out_no_offsets:
+	kfree(srf->sizes);
+out_no_sizes:
+	ttm_base_object_kfree(user_srf, base);
+out_no_user_srf:
+	ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
+out_unlock:
+	ttm_read_unlock(&vmaster->lock);
+	return ret;
+}
+
+/**
+ * vmw_user_surface_define_ioctl - Ioctl function implementing
+ *                                  the user surface reference functionality.
+ *
+ * @dev:            Pointer to a struct drm_device.
+ * @data:           Pointer to data copied from / to user-space.
+ * @file_priv:      Pointer to a drm file private structure.
+ */
+int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv)
+{
+	union drm_vmw_surface_reference_arg *arg =
+	    (union drm_vmw_surface_reference_arg *)data;
+	struct drm_vmw_surface_arg *req = &arg->req;
+	struct drm_vmw_surface_create_req *rep = &arg->rep;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_surface *srf;
+	struct vmw_user_surface *user_srf;
+	struct drm_vmw_size __user *user_sizes;
+	struct ttm_base_object *base;
+	int ret = -EINVAL;
+
+	base = ttm_base_object_lookup(tfile, req->sid);
+	if (unlikely(base == NULL)) {
+		DRM_ERROR("Could not find surface to reference.\n");
+		return -EINVAL;
+	}
+
+	if (unlikely(base->object_type != VMW_RES_SURFACE))
+		goto out_bad_resource;
+
+	user_srf = container_of(base, struct vmw_user_surface, base);
+	srf = &user_srf->srf;
+
+	ret = ttm_ref_object_add(tfile, &user_srf->base, TTM_REF_USAGE, NULL);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Could not add a reference to a surface.\n");
+		goto out_no_reference;
+	}
+
+	rep->flags = srf->flags;
+	rep->format = srf->format;
+	memcpy(rep->mip_levels, srf->mip_levels, sizeof(srf->mip_levels));
+	user_sizes = (struct drm_vmw_size __user *)(unsigned long)
+	    rep->size_addr;
+
+	if (user_sizes)
+		ret = copy_to_user(user_sizes, srf->sizes,
+				   srf->num_sizes * sizeof(*srf->sizes));
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("copy_to_user failed %p %u\n",
+			  user_sizes, srf->num_sizes);
+		ret = -EFAULT;
+	}
+out_bad_resource:
+out_no_reference:
+	ttm_base_object_unref(&base);
+
+	return ret;
+}
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index e25cf31..fa60add 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -18,7 +18,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/dmi.h>
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
 #include <linux/fs.h>
@@ -376,7 +375,6 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
 			     size_t cnt, loff_t *ppos)
 {
 	char usercmd[64];
-	const char *pdev_name;
 	int ret;
 	bool delay = false, can_switch;
 	bool just_mux = false;
@@ -468,7 +466,6 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
 		goto out;
 
 	if (can_switch) {
-		pdev_name = pci_name(client->pdev);
 		ret = vga_switchto_stage1(client);
 		if (ret)
 			printk(KERN_ERR "vga_switcheroo: switching failed stage 1 %d\n", ret);
@@ -540,7 +537,6 @@ fail:
 int vga_switcheroo_process_delayed_switch(void)
 {
 	struct vga_switcheroo_client *client;
-	const char *pdev_name;
 	int ret;
 	int err = -EINVAL;
 
@@ -555,7 +551,6 @@ int vga_switcheroo_process_delayed_switch(void)
 	if (!client || !check_can_switch())
 		goto err;
 
-	pdev_name = pci_name(client->pdev);
 	ret = vga_switchto_stage2(client);
 	if (ret)
 		printk(KERN_ERR "vga_switcheroo: delayed switching failed stage 2 %d\n", ret);
@@ -567,4 +562,3 @@ err:
 	return err;
 }
 EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch);
-
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 1630150..e7d6a13 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -265,6 +265,15 @@ config HID_GYRATION
 	---help---
 	Support for Gyration remote control.
 
+config HID_ICADE
+	tristate "ION iCade arcade controller"
+	depends on BT_HIDP
+	---help---
+	Support for the ION iCade arcade controller to work as a joystick.
+
+	To compile this driver as a module, choose M here: the
+	module will be called hid-icade.
+
 config HID_TWINHAN
 	tristate "Twinhan IR remote control"
 	depends on USB_HID
@@ -728,4 +737,6 @@ endif # HID
 
 source "drivers/hid/usbhid/Kconfig"
 
+source "drivers/hid/i2c-hid/Kconfig"
+
 endmenu
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index cef68ca..b622157 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_HID_GYRATION)	+= hid-gyration.o
 obj-$(CONFIG_HID_HOLTEK)	+= hid-holtek-kbd.o
 obj-$(CONFIG_HID_HOLTEK)	+= hid-holtekff.o
 obj-$(CONFIG_HID_HYPERV_MOUSE)	+= hid-hyperv.o
+obj-$(CONFIG_HID_ICADE)		+= hid-icade.o
 obj-$(CONFIG_HID_KENSINGTON)	+= hid-kensington.o
 obj-$(CONFIG_HID_KEYTOUCH)	+= hid-keytouch.o
 obj-$(CONFIG_HID_KYE)		+= hid-kye.o
@@ -93,8 +94,8 @@ obj-$(CONFIG_HID_PRIMAX)	+= hid-primax.o
 obj-$(CONFIG_HID_PS3REMOTE)	+= hid-ps3remote.o
 obj-$(CONFIG_HID_ROCCAT)	+= hid-roccat.o hid-roccat-common.o \
 	hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
-	hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o \
-	hid-roccat-savu.o
+	hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-lua.o \
+	hid-roccat-pyra.o hid-roccat-savu.o
 obj-$(CONFIG_HID_SAITEK)	+= hid-saitek.o
 obj-$(CONFIG_HID_SAMSUNG)	+= hid-samsung.o
 obj-$(CONFIG_HID_SMARTJOYPLUS)	+= hid-sjoy.o
@@ -118,3 +119,4 @@ obj-$(CONFIG_USB_HID)		+= usbhid/
 obj-$(CONFIG_USB_MOUSE)		+= usbhid/
 obj-$(CONFIG_USB_KBD)		+= usbhid/
 
+obj-$(CONFIG_I2C_HID)		+= i2c-hid/
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index fd7722a..d0f7662 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -439,7 +439,8 @@ static const struct hid_device_id apple_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO),
-		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
+		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+			APPLE_ISO_KEYBOARD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
 			APPLE_RDESC_JIS },
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index f4109fd..fb21efd 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -92,6 +92,7 @@ EXPORT_SYMBOL_GPL(hid_register_report);
 static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
 {
 	struct hid_field *field;
+	int i;
 
 	if (report->maxfield == HID_MAX_FIELDS) {
 		hid_err(report->device, "too many fields in report\n");
@@ -110,6 +111,9 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
 	field->value = (s32 *)(field->usage + usages);
 	field->report = report;
 
+	for (i = 0; i < usages; i++)
+		field->usage[i].usage_index = i;
+
 	return field;
 }
 
@@ -315,6 +319,7 @@ static s32 item_sdata(struct hid_item *item)
 
 static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
 {
+	__u32 raw_value;
 	switch (item->tag) {
 	case HID_GLOBAL_ITEM_TAG_PUSH:
 
@@ -365,7 +370,14 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
 		return 0;
 
 	case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
-		parser->global.unit_exponent = item_sdata(item);
+		/* 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);
+		if (!(raw_value & 0xfffffff0))
+			parser->global.unit_exponent = hid_snto32(raw_value, 4);
+		else
+			parser->global.unit_exponent = raw_value;
 		return 0;
 
 	case HID_GLOBAL_ITEM_TAG_UNIT:
@@ -865,6 +877,12 @@ static s32 snto32(__u32 value, unsigned n)
 	return value & (1 << (n - 1)) ? value | (-1 << n) : value;
 }
 
+s32 hid_snto32(__u32 value, unsigned n)
+{
+	return snto32(value, n);
+}
+EXPORT_SYMBOL_GPL(hid_snto32);
+
 /*
  * Convert a signed 32-bit integer to a signed n-bit integer.
  */
@@ -1575,6 +1593,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_09FA) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_1020) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_09FA) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
@@ -1658,6 +1677,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) },
@@ -2188,7 +2208,16 @@ static bool hid_ignore(struct hid_device *hdev)
 		if (hdev->product == USB_DEVICE_ID_JESS_YUREX &&
 				hdev->type == HID_TYPE_USBNONE)
 			return true;
-	break;
+		break;
+	case USB_VENDOR_ID_DWAV:
+		/* These are handled by usbtouchscreen. hdev->type is probably
+		 * HID_TYPE_USBNONE, but we say !HID_TYPE_USBMOUSE to match
+		 * usbtouchscreen. */
+		if ((hdev->product == USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER ||
+		     hdev->product == USB_DEVICE_ID_DWAV_TOUCHCONTROLLER) &&
+		    hdev->type != HID_TYPE_USBMOUSE)
+			return true;
+		break;
 	}
 
 	if (hdev->type == HID_TYPE_USBMOUSE &&
diff --git a/drivers/hid/hid-icade.c b/drivers/hid/hid-icade.c
new file mode 100644
index 0000000..1d6565e
--- /dev/null
+++ b/drivers/hid/hid-icade.c
@@ -0,0 +1,259 @@
+/*
+ *  ION iCade input driver
+ *
+ *  Copyright (c) 2012 Bastien Nocera <hadess@hadess.net>
+ *  Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+/*
+ *   ↑      A C Y L
+ *  ← →
+ *   ↓      B X Z R
+ *
+ *
+ *  UP ON,OFF  = w,e
+ *  RT ON,OFF  = d,c
+ *  DN ON,OFF  = x,z
+ *  LT ON,OFF  = a,q
+ *  A  ON,OFF  = y,t
+ *  B  ON,OFF  = h,r
+ *  C  ON,OFF  = u,f
+ *  X  ON,OFF  = j,n
+ *  Y  ON,OFF  = i,m
+ *  Z  ON,OFF  = k,p
+ *  L  ON,OFF  = o,g
+ *  R  ON,OFF  = l,v
+ */
+
+/* The translation code uses HID usage instead of input layer
+ * keys. This code generates a lookup table that makes
+ * translation quick.
+ *
+ * #include <linux/input.h>
+ * #include <stdio.h>
+ * #include <assert.h>
+ *
+ * #define unk     KEY_UNKNOWN
+ *
+ * < copy of hid_keyboard[] from hid-input.c >
+ *
+ * struct icade_key_translation {
+ *     int         from;
+ *     const char *to;
+ *     int         press;
+ * };
+ *
+ * static const struct icade_key_translation icade_keys[] = {
+ *    { KEY_W,        "KEY_UP",         1 },
+ *    { KEY_E,        "KEY_UP",         0 },
+ *    { KEY_D,        "KEY_RIGHT",      1 },
+ *    { KEY_C,        "KEY_RIGHT",      0 },
+ *    { KEY_X,        "KEY_DOWN",       1 },
+ *    { KEY_Z,        "KEY_DOWN",       0 },
+ *    { KEY_A,        "KEY_LEFT",       1 },
+ *    { KEY_Q,        "KEY_LEFT",       0 },
+ *    { KEY_Y,        "BTN_A",          1 },
+ *    { KEY_T,        "BTN_A",          0 },
+ *    { KEY_H,        "BTN_B",          1 },
+ *    { KEY_R,        "BTN_B",          0 },
+ *    { KEY_U,        "BTN_C",          1 },
+ *    { KEY_F,        "BTN_C",          0 },
+ *    { KEY_J,        "BTN_X",          1 },
+ *    { KEY_N,        "BTN_X",          0 },
+ *    { KEY_I,        "BTN_Y",          1 },
+ *    { KEY_M,        "BTN_Y",          0 },
+ *    { KEY_K,        "BTN_Z",          1 },
+ *    { KEY_P,        "BTN_Z",          0 },
+ *    { KEY_O,        "BTN_THUMBL",     1 },
+ *    { KEY_G,        "BTN_THUMBL",     0 },
+ *    { KEY_L,        "BTN_THUMBR",     1 },
+ *    { KEY_V,        "BTN_THUMBR",     0 },
+ *
+ *    { }
+ * };
+ *
+ * static int
+ * usage_for_key (int key)
+ * {
+ *     int i;
+ *     for (i = 0; i < 256; i++) {
+ *     if (hid_keyboard[i] == key)
+ *         return i;
+ *     }
+ *     assert(0);
+ * }
+ *
+ * int main (int argc, char **argv)
+ * {
+ *     const struct icade_key_translation *trans;
+ *     int max_usage = 0;
+ *
+ *     for (trans = icade_keys; trans->from; trans++) {
+ *         int usage = usage_for_key (trans->from);
+ *         max_usage = usage > max_usage ? usage : max_usage;
+ *     }
+ *
+ *     printf ("#define ICADE_MAX_USAGE %d\n\n", max_usage);
+ *     printf ("struct icade_key {\n");
+ *     printf ("\tu16 to;\n");
+ *     printf ("\tu8 press:1;\n");
+ *     printf ("};\n\n");
+ *     printf ("static const struct icade_key "
+ *             "icade_usage_table[%d] = {\n", max_usage + 1);
+ *     for (trans = icade_keys; trans->from; trans++) {
+ *         printf ("\t[%d] = { %s, %d },\n",
+ *                 usage_for_key (trans->from), trans->to, trans->press);
+ *     }
+ *     printf ("};\n");
+ *
+ *     return 0;
+ * }
+ */
+
+#define ICADE_MAX_USAGE 29
+
+struct icade_key {
+	u16 to;
+	u8 press:1;
+};
+
+static const struct icade_key icade_usage_table[30] = {
+	[26] = { KEY_UP, 1 },
+	[8] = { KEY_UP, 0 },
+	[7] = { KEY_RIGHT, 1 },
+	[6] = { KEY_RIGHT, 0 },
+	[27] = { KEY_DOWN, 1 },
+	[29] = { KEY_DOWN, 0 },
+	[4] = { KEY_LEFT, 1 },
+	[20] = { KEY_LEFT, 0 },
+	[28] = { BTN_A, 1 },
+	[23] = { BTN_A, 0 },
+	[11] = { BTN_B, 1 },
+	[21] = { BTN_B, 0 },
+	[24] = { BTN_C, 1 },
+	[9] = { BTN_C, 0 },
+	[13] = { BTN_X, 1 },
+	[17] = { BTN_X, 0 },
+	[12] = { BTN_Y, 1 },
+	[16] = { BTN_Y, 0 },
+	[14] = { BTN_Z, 1 },
+	[19] = { BTN_Z, 0 },
+	[18] = { BTN_THUMBL, 1 },
+	[10] = { BTN_THUMBL, 0 },
+	[15] = { BTN_THUMBR, 1 },
+	[25] = { BTN_THUMBR, 0 },
+};
+
+static const struct icade_key *icade_find_translation(u16 from)
+{
+	if (from < 0 || from > ICADE_MAX_USAGE)
+		return NULL;
+	return &icade_usage_table[from];
+}
+
+static int icade_event(struct hid_device *hdev, struct hid_field *field,
+		struct hid_usage *usage, __s32 value)
+{
+	const struct icade_key *trans;
+
+	if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
+			!usage->type)
+		return 0;
+
+	/* We ignore the fake key up, and act only on key down */
+	if (!value)
+		return 1;
+
+	trans = icade_find_translation(usage->hid & HID_USAGE);
+
+	if (!trans)
+		return 1;
+
+	input_event(field->hidinput->input, usage->type,
+			trans->to, trans->press);
+
+	return 1;
+}
+
+static int icade_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	const struct icade_key *trans;
+
+	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_KEYBOARD) {
+		trans = icade_find_translation(usage->hid & HID_USAGE);
+
+		if (!trans)
+			return -1;
+
+		hid_map_usage(hi, usage, bit, max, EV_KEY, trans->to);
+		set_bit(trans->to, hi->input->keybit);
+
+		return 1;
+	}
+
+	/* ignore others */
+	return -1;
+
+}
+
+static int icade_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	if (usage->type == EV_KEY)
+		set_bit(usage->type, hi->input->evbit);
+
+	return -1;
+}
+
+static const struct hid_device_id icade_devices[] = {
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
+
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, icade_devices);
+
+static struct hid_driver icade_driver = {
+	.name = "icade",
+	.id_table = icade_devices,
+	.event = icade_event,
+	.input_mapped = icade_input_mapped,
+	.input_mapping = icade_input_mapping,
+};
+
+static int __init icade_init(void)
+{
+	int ret;
+
+	ret = hid_register_driver(&icade_driver);
+	if (ret)
+		pr_err("can't register icade driver\n");
+
+	return ret;
+}
+
+static void __exit icade_exit(void)
+{
+	hid_unregister_driver(&icade_driver);
+}
+
+module_init(icade_init);
+module_exit(icade_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
+MODULE_DESCRIPTION("ION iCade input driver");
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 9d7a428..c147dc0 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -257,6 +257,7 @@
 
 #define USB_VENDOR_ID_DWAV		0x0eef
 #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER	0x0001
+#define USB_DEVICE_ID_DWAV_TOUCHCONTROLLER	0x0002
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D	0x480d
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E	0x480e
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7207	0x7207
@@ -423,6 +424,9 @@
 #define USB_VENDOR_ID_ILITEK		0x222a
 #define USB_DEVICE_ID_ILITEK_MULTITOUCH	0x0001
 
+#define USB_VENDOR_ID_ION		0x15e4
+#define USB_DEVICE_ID_ICADE		0x0132
+
 #define USB_VENDOR_ID_HOLTEK		0x1241
 #define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP	0x5015
 
@@ -677,7 +681,9 @@
 #define USB_DEVICE_ID_ROCCAT_ISKU	0x319c
 #define USB_DEVICE_ID_ROCCAT_KONE	0x2ced
 #define USB_DEVICE_ID_ROCCAT_KONEPLUS	0x2d51
+#define USB_DEVICE_ID_ROCCAT_KONEXTD	0x2e22
 #define USB_DEVICE_ID_ROCCAT_KOVAPLUS	0x2d50
+#define USB_DEVICE_ID_ROCCAT_LUA	0x2c2e
 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED	0x2c24
 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS	0x2cf6
 #define USB_DEVICE_ID_ROCCAT_SAVU	0x2d5a
@@ -696,6 +702,9 @@
 #define USB_VENDOR_ID_SIGMA_MICRO	0x1c4f
 #define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD	0x0002
 
+#define USB_VENDOR_ID_SIGMATEL		0x066F
+#define USB_DEVICE_ID_SIGMATEL_STMP3780	0x3780
+
 #define USB_VENDOR_ID_SKYCABLE			0x1223
 #define	USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER	0x3F07
 
@@ -762,6 +771,9 @@
 #define USB_VENDOR_ID_TOUCHPACK		0x1bfd
 #define USB_DEVICE_ID_TOUCHPACK_RTS	0x1688
 
+#define USB_VENDOR_ID_TPV		0x25aa
+#define USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN	0x8883
+
 #define USB_VENDOR_ID_TURBOX		0x062a
 #define USB_DEVICE_ID_TURBOX_KEYBOARD	0x0201
 #define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART	0x7100
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index d917c0d..edb1635 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -192,7 +192,6 @@ static int hidinput_setkeycode(struct input_dev *dev,
 	return -EINVAL;
 }
 
-
 /**
  * hidinput_calc_abs_res - calculate an absolute axis resolution
  * @field: the HID report field to calculate resolution for
@@ -208,7 +207,7 @@ static int hidinput_setkeycode(struct input_dev *dev,
  * Only exponent 1 length units are processed. Centimeters and inches are
  * converted to millimeters. Degrees are converted to radians.
  */
-static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
+__s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
 {
 	__s32 unit_exponent = field->unit_exponent;
 	__s32 logical_extents = field->logical_maximum -
@@ -229,17 +228,29 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
 	case ABS_X:
 	case ABS_Y:
 	case ABS_Z:
-		if (field->unit == 0x11) {		/* If centimeters */
+	case ABS_MT_POSITION_X:
+	case ABS_MT_POSITION_Y:
+	case ABS_MT_TOOL_X:
+	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 */
 			/* Convert to millimeters */
 			unit_exponent += 1;
-		} else if (field->unit == 0x13) {	/* If inches */
+			break;
+		case 0x3:				/* If inches */
 			/* Convert to millimeters */
 			prev = physical_extents;
 			physical_extents *= 254;
 			if (physical_extents < prev)
 				return 0;
 			unit_exponent -= 1;
-		} else {
+			break;
+		default:
 			return 0;
 		}
 		break;
@@ -281,8 +292,9 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
 	}
 
 	/* Calculate resolution */
-	return logical_extents / physical_extents;
+	return DIV_ROUND_CLOSEST(logical_extents, physical_extents);
 }
+EXPORT_SYMBOL_GPL(hidinput_calc_abs_res);
 
 #ifdef CONFIG_HID_BATTERY_STRENGTH
 static enum power_supply_property hidinput_battery_props[] = {
@@ -299,6 +311,9 @@ static enum power_supply_property hidinput_battery_props[] = {
 
 static const struct hid_device_id hid_battery_quirks[] = {
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
+			USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
+	HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
 			       USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
 	  HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
@@ -502,9 +517,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
 				if (code <= 0xf)
 					code += BTN_JOYSTICK;
 				else
-					code += BTN_TRIGGER_HAPPY;
+					code += BTN_TRIGGER_HAPPY - 0x10;
+				break;
+		case HID_GD_GAMEPAD:
+				if (code <= 0xf)
+					code += BTN_GAMEPAD;
+				else
+					code += BTN_TRIGGER_HAPPY - 0x10;
 				break;
-		case HID_GD_GAMEPAD:  code += BTN_GAMEPAD; break;
 		default:
 			switch (field->physical) {
 			case HID_GD_MOUSE:
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 7867d69..61543c0 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -52,11 +52,14 @@ MODULE_LICENSE("GPL");
 #define MT_QUIRK_VALID_IS_CONFIDENCE	(1 << 6)
 #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE	(1 << 8)
 #define MT_QUIRK_NO_AREA		(1 << 9)
+#define MT_QUIRK_IGNORE_DUPLICATES	(1 << 10)
+#define MT_QUIRK_HOVERING		(1 << 11)
 
 struct mt_slot {
-	__s32 x, y, p, w, h;
+	__s32 x, y, cx, cy, p, w, h;
 	__s32 contactid;	/* the device ContactID assigned to this slot */
 	bool touch_state;	/* is the touch valid? */
+	bool inrange_state;	/* is the finger in proximity of the sensor? */
 };
 
 struct mt_class {
@@ -121,6 +124,7 @@ struct mt_device {
 #define MT_CLS_GENERALTOUCH_PWT_TENFINGERS	0x0109
 
 #define MT_DEFAULT_MAXCONTACT	10
+#define MT_MAX_MAXCONTACT	250
 
 #define MT_USB_DEVICE(v, p)	HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH, v, p)
 #define MT_BT_DEVICE(v, p)	HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH, v, p)
@@ -282,11 +286,26 @@ static void mt_feature_mapping(struct hid_device *hdev,
 	case HID_DG_CONTACTMAX:
 		td->maxcontact_report_id = field->report->id;
 		td->maxcontacts = field->value[0];
+		if (!td->maxcontacts &&
+		    field->logical_maximum <= MT_MAX_MAXCONTACT)
+			td->maxcontacts = field->logical_maximum;
 		if (td->mtclass.maxcontacts)
 			/* check if the maxcontacts is given by the class */
 			td->maxcontacts = td->mtclass.maxcontacts;
 
 		break;
+	case 0xff0000c5:
+		if (field->report_count == 256 && field->report_size == 8) {
+			/* Win 8 devices need special quirks */
+			__s32 *quirks = &td->mtclass.quirks;
+			*quirks |= MT_QUIRK_ALWAYS_VALID;
+			*quirks |= MT_QUIRK_IGNORE_DUPLICATES;
+			*quirks |= MT_QUIRK_HOVERING;
+			*quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP;
+			*quirks &= ~MT_QUIRK_VALID_IS_INRANGE;
+			*quirks &= ~MT_QUIRK_VALID_IS_CONFIDENCE;
+		}
+		break;
 	}
 }
 
@@ -297,6 +316,7 @@ static void set_abs(struct input_dev *input, unsigned int code,
 	int fmax = field->logical_maximum;
 	int fuzz = snratio ? (fmax - fmin) / snratio : 0;
 	input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
+	input_abs_set_res(input, code, hidinput_calc_abs_res(field, code));
 }
 
 static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
@@ -317,6 +337,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 	struct mt_device *td = hid_get_drvdata(hdev);
 	struct mt_class *cls = &td->mtclass;
 	int code;
+	struct hid_usage *prev_usage = NULL;
 
 	/* Only map fields from TouchScreen or TouchPad collections.
 	* We need to ignore fields that belong to other collections
@@ -339,23 +360,42 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 	if (field->physical == HID_DG_STYLUS)
 		return -1;
 
+	if (usage->usage_index)
+		prev_usage = &field->usage[usage->usage_index - 1];
+
 	switch (usage->hid & HID_USAGE_PAGE) {
 
 	case HID_UP_GENDESK:
 		switch (usage->hid) {
 		case HID_GD_X:
-			hid_map_usage(hi, usage, bit, max,
+			if (prev_usage && (prev_usage->hid == usage->hid)) {
+				hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TOOL_X);
+				set_abs(hi->input, ABS_MT_TOOL_X, field,
+					cls->sn_move);
+			} else {
+				hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_POSITION_X);
-			set_abs(hi->input, ABS_MT_POSITION_X, field,
-				cls->sn_move);
+				set_abs(hi->input, ABS_MT_POSITION_X, field,
+					cls->sn_move);
+			}
+
 			mt_store_field(usage, td, hi);
 			td->last_field_index = field->index;
 			return 1;
 		case HID_GD_Y:
-			hid_map_usage(hi, usage, bit, max,
+			if (prev_usage && (prev_usage->hid == usage->hid)) {
+				hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TOOL_Y);
+				set_abs(hi->input, ABS_MT_TOOL_Y, field,
+					cls->sn_move);
+			} else {
+				hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_POSITION_Y);
-			set_abs(hi->input, ABS_MT_POSITION_Y, field,
-				cls->sn_move);
+				set_abs(hi->input, ABS_MT_POSITION_Y, field,
+					cls->sn_move);
+			}
+
 			mt_store_field(usage, td, hi);
 			td->last_field_index = field->index;
 			return 1;
@@ -365,6 +405,12 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 	case HID_UP_DIGITIZER:
 		switch (usage->hid) {
 		case HID_DG_INRANGE:
+			if (cls->quirks & MT_QUIRK_HOVERING) {
+				hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_DISTANCE);
+				input_set_abs_params(hi->input,
+					ABS_MT_DISTANCE, 0, 1, 0, 0);
+			}
 			mt_store_field(usage, td, hi);
 			td->last_field_index = field->index;
 			return 1;
@@ -477,18 +523,26 @@ static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
  */
 static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
 {
-	if (td->curvalid) {
+	if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
 		int slotnum = mt_compute_slot(td, input);
 		struct mt_slot *s = &td->curdata;
+		struct input_mt *mt = input->mt;
 
 		if (slotnum < 0 || slotnum >= td->maxcontacts)
 			return;
 
+		if ((td->mtclass.quirks & MT_QUIRK_IGNORE_DUPLICATES) && mt) {
+			struct input_mt_slot *slot = &mt->slots[slotnum];
+			if (input_mt_is_active(slot) &&
+			    input_mt_is_used(mt, slot))
+				return;
+		}
+
 		input_mt_slot(input, slotnum);
 		input_mt_report_slot_state(input, MT_TOOL_FINGER,
-			s->touch_state);
-		if (s->touch_state) {
-			/* this finger is on the screen */
+			s->touch_state || s->inrange_state);
+		if (s->touch_state || s->inrange_state) {
+			/* this finger is in proximity of the sensor */
 			int wide = (s->w > s->h);
 			/* divided by two to match visual scale of touch */
 			int major = max(s->w, s->h) >> 1;
@@ -496,6 +550,10 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
 
 			input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x);
 			input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
+			input_event(input, EV_ABS, ABS_MT_TOOL_X, s->cx);
+			input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy);
+			input_event(input, EV_ABS, ABS_MT_DISTANCE,
+				!s->touch_state);
 			input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
 			input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
 			input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
@@ -526,10 +584,10 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
 	if (hid->claimed & HID_CLAIMED_INPUT) {
 		switch (usage->hid) {
 		case HID_DG_INRANGE:
-			if (quirks & MT_QUIRK_ALWAYS_VALID)
-				td->curvalid = true;
-			else if (quirks & MT_QUIRK_VALID_IS_INRANGE)
+			if (quirks & MT_QUIRK_VALID_IS_INRANGE)
 				td->curvalid = value;
+			if (quirks & MT_QUIRK_HOVERING)
+				td->curdata.inrange_state = value;
 			break;
 		case HID_DG_TIPSWITCH:
 			if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
@@ -547,10 +605,16 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
 			td->curdata.p = value;
 			break;
 		case HID_GD_X:
-			td->curdata.x = value;
+			if (usage->code == ABS_MT_TOOL_X)
+				td->curdata.cx = value;
+			else
+				td->curdata.x = value;
 			break;
 		case HID_GD_Y:
-			td->curdata.y = value;
+			if (usage->code == ABS_MT_TOOL_Y)
+				td->curdata.cy = value;
+			else
+				td->curdata.y = value;
 			break;
 		case HID_DG_WIDTH:
 			td->curdata.w = value;
@@ -575,12 +639,15 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
 			return 0;
 		}
 
-		if (usage->hid == td->last_slot_field)
-			mt_complete_slot(td, field->hidinput->input);
+		if (usage->usage_index + 1 == field->report_count) {
+			/* we only take into account the last report. */
+			if (usage->hid == td->last_slot_field)
+				mt_complete_slot(td, field->hidinput->input);
 
-		if (field->index == td->last_field_index
-			&& td->num_received >= td->num_expected)
-			mt_sync_frame(td, field->hidinput->input);
+			if (field->index == td->last_field_index
+				&& td->num_received >= td->num_expected)
+				mt_sync_frame(td, field->hidinput->input);
+		}
 
 	}
 
diff --git a/drivers/hid/hid-picolcd_cir.c b/drivers/hid/hid-picolcd_cir.c
index 13ca919..a79e95b 100644
--- a/drivers/hid/hid-picolcd_cir.c
+++ b/drivers/hid/hid-picolcd_cir.c
@@ -116,7 +116,7 @@ int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report)
 
 	rdev->priv             = data;
 	rdev->driver_type      = RC_DRIVER_IR_RAW;
-	rdev->allowed_protos   = RC_TYPE_ALL;
+	rdev->allowed_protos   = RC_BIT_ALL;
 	rdev->open             = picolcd_cir_open;
 	rdev->close            = picolcd_cir_close;
 	rdev->input_name       = data->hdev->name;
diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c
index 5669916..1219998 100644
--- a/drivers/hid/hid-roccat-isku.c
+++ b/drivers/hid/hid-roccat-isku.c
@@ -167,7 +167,7 @@ static ssize_t isku_sysfs_write_ ## thingy(struct file *fp, struct kobject *kobj
 		loff_t off, size_t count) \
 { \
 	return isku_sysfs_write(fp, kobj, buf, off, count, \
-			sizeof(struct isku_ ## thingy), ISKU_COMMAND_ ## THINGY); \
+			ISKU_SIZE_ ## THINGY, ISKU_COMMAND_ ## THINGY); \
 }
 
 #define ISKU_SYSFS_R(thingy, THINGY) \
@@ -176,32 +176,32 @@ static ssize_t isku_sysfs_read_ ## thingy(struct file *fp, struct kobject *kobj,
 		loff_t off, size_t count) \
 { \
 	return isku_sysfs_read(fp, kobj, buf, off, count, \
-			sizeof(struct isku_ ## thingy), ISKU_COMMAND_ ## THINGY); \
+			ISKU_SIZE_ ## THINGY, ISKU_COMMAND_ ## THINGY); \
 }
 
 #define ISKU_SYSFS_RW(thingy, THINGY) \
 ISKU_SYSFS_R(thingy, THINGY) \
 ISKU_SYSFS_W(thingy, THINGY)
 
-#define ISKU_BIN_ATTR_RW(thingy) \
+#define ISKU_BIN_ATTR_RW(thingy, THINGY) \
 { \
 	.attr = { .name = #thingy, .mode = 0660 }, \
-	.size = sizeof(struct isku_ ## thingy), \
+	.size = ISKU_SIZE_ ## THINGY, \
 	.read = isku_sysfs_read_ ## thingy, \
 	.write = isku_sysfs_write_ ## thingy \
 }
 
-#define ISKU_BIN_ATTR_R(thingy) \
+#define ISKU_BIN_ATTR_R(thingy, THINGY) \
 { \
 	.attr = { .name = #thingy, .mode = 0440 }, \
-	.size = sizeof(struct isku_ ## thingy), \
+	.size = ISKU_SIZE_ ## THINGY, \
 	.read = isku_sysfs_read_ ## thingy, \
 }
 
-#define ISKU_BIN_ATTR_W(thingy) \
+#define ISKU_BIN_ATTR_W(thingy, THINGY) \
 { \
 	.attr = { .name = #thingy, .mode = 0220 }, \
-	.size = sizeof(struct isku_ ## thingy), \
+	.size = ISKU_SIZE_ ## THINGY, \
 	.write = isku_sysfs_write_ ## thingy \
 }
 
@@ -218,21 +218,23 @@ ISKU_SYSFS_RW(last_set, LAST_SET)
 ISKU_SYSFS_W(talk, TALK)
 ISKU_SYSFS_R(info, INFO)
 ISKU_SYSFS_W(control, CONTROL)
+ISKU_SYSFS_W(reset, RESET)
 
 static struct bin_attribute isku_bin_attributes[] = {
-	ISKU_BIN_ATTR_RW(macro),
-	ISKU_BIN_ATTR_RW(keys_function),
-	ISKU_BIN_ATTR_RW(keys_easyzone),
-	ISKU_BIN_ATTR_RW(keys_media),
-	ISKU_BIN_ATTR_RW(keys_thumbster),
-	ISKU_BIN_ATTR_RW(keys_macro),
-	ISKU_BIN_ATTR_RW(keys_capslock),
-	ISKU_BIN_ATTR_RW(light),
-	ISKU_BIN_ATTR_RW(key_mask),
-	ISKU_BIN_ATTR_RW(last_set),
-	ISKU_BIN_ATTR_W(talk),
-	ISKU_BIN_ATTR_R(info),
-	ISKU_BIN_ATTR_W(control),
+	ISKU_BIN_ATTR_RW(macro, MACRO),
+	ISKU_BIN_ATTR_RW(keys_function, KEYS_FUNCTION),
+	ISKU_BIN_ATTR_RW(keys_easyzone, KEYS_EASYZONE),
+	ISKU_BIN_ATTR_RW(keys_media, KEYS_MEDIA),
+	ISKU_BIN_ATTR_RW(keys_thumbster, KEYS_THUMBSTER),
+	ISKU_BIN_ATTR_RW(keys_macro, KEYS_MACRO),
+	ISKU_BIN_ATTR_RW(keys_capslock, KEYS_CAPSLOCK),
+	ISKU_BIN_ATTR_RW(light, LIGHT),
+	ISKU_BIN_ATTR_RW(key_mask, KEY_MASK),
+	ISKU_BIN_ATTR_RW(last_set, LAST_SET),
+	ISKU_BIN_ATTR_W(talk, TALK),
+	ISKU_BIN_ATTR_R(info, INFO),
+	ISKU_BIN_ATTR_W(control, CONTROL),
+	ISKU_BIN_ATTR_W(reset, RESET),
 	__ATTR_NULL
 };
 
diff --git a/drivers/hid/hid-roccat-isku.h b/drivers/hid/hid-roccat-isku.h
index 605b3ce..cf6896c 100644
--- a/drivers/hid/hid-roccat-isku.h
+++ b/drivers/hid/hid-roccat-isku.h
@@ -15,76 +15,33 @@
 #include <linux/types.h>
 
 enum {
+	ISKU_SIZE_CONTROL = 0x03,
+	ISKU_SIZE_INFO = 0x06,
+	ISKU_SIZE_KEY_MASK = 0x06,
+	ISKU_SIZE_KEYS_FUNCTION = 0x29,
+	ISKU_SIZE_KEYS_EASYZONE = 0x41,
+	ISKU_SIZE_KEYS_MEDIA = 0x1d,
+	ISKU_SIZE_KEYS_THUMBSTER = 0x17,
+	ISKU_SIZE_KEYS_MACRO = 0x23,
+	ISKU_SIZE_KEYS_CAPSLOCK = 0x06,
+	ISKU_SIZE_LAST_SET = 0x14,
+	ISKU_SIZE_LIGHT = 0x0a,
+	ISKU_SIZE_MACRO = 0x823,
+	ISKU_SIZE_RESET = 0x03,
+	ISKU_SIZE_TALK = 0x10,
+};
+
+enum {
 	ISKU_PROFILE_NUM = 5,
 	ISKU_USB_INTERFACE_PROTOCOL = 0,
 };
 
-struct isku_control {
-	uint8_t command; /* ISKU_COMMAND_CONTROL */
-	uint8_t value;
-	uint8_t request;
-} __packed;
-
 struct isku_actual_profile {
 	uint8_t command; /* ISKU_COMMAND_ACTUAL_PROFILE */
 	uint8_t size; /* always 3 */
 	uint8_t actual_profile;
 } __packed;
 
-struct isku_key_mask {
-	uint8_t command; /* ISKU_COMMAND_KEY_MASK */
-	uint8_t size; /* 6 */
-	uint8_t profile_number; /* 0-4 */
-	uint8_t mask;
-	uint16_t checksum;
-} __packed;
-
-struct isku_keys_function {
-	uint8_t data[0x29];
-} __packed;
-
-struct isku_keys_easyzone {
-	uint8_t data[0x41];
-} __packed;
-
-struct isku_keys_media {
-	uint8_t data[0x1d];
-} __packed;
-
-struct isku_keys_thumbster {
-	uint8_t data[0x17];
-} __packed;
-
-struct isku_keys_macro {
-	uint8_t data[0x23];
-} __packed;
-
-struct isku_keys_capslock {
-	uint8_t data[0x6];
-} __packed;
-
-struct isku_macro {
-	uint8_t data[0x823];
-} __packed;
-
-struct isku_light {
-	uint8_t data[0xa];
-} __packed;
-
-struct isku_info {
-	uint8_t data[2];
-	uint8_t firmware_version;
-	uint8_t unknown[3];
-} __packed;
-
-struct isku_talk {
-	uint8_t data[0x10];
-} __packed;
-
-struct isku_last_set {
-	uint8_t data[0x14];
-} __packed;
-
 enum isku_commands {
 	ISKU_COMMAND_CONTROL = 0x4,
 	ISKU_COMMAND_ACTUAL_PROFILE = 0x5,
@@ -97,6 +54,7 @@ enum isku_commands {
 	ISKU_COMMAND_MACRO = 0xe,
 	ISKU_COMMAND_INFO = 0xf,
 	ISKU_COMMAND_LIGHT = 0x10,
+	ISKU_COMMAND_RESET = 0x11,
 	ISKU_COMMAND_KEYS_CAPSLOCK = 0x13,
 	ISKU_COMMAND_LAST_SET = 0x14,
 	ISKU_COMMAND_15 = 0x15,
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c
index f5602fe..6a48fa3 100644
--- a/drivers/hid/hid-roccat-koneplus.c
+++ b/drivers/hid/hid-roccat-koneplus.c
@@ -14,6 +14,7 @@
 /*
  * Roccat Kone[+] is an updated/improved version of the Kone with more memory
  * and functionality and without the non-standard behaviours the Kone had.
+ * KoneXTD has same capabilities but updated sensor.
  */
 
 #include <linux/device.h>
@@ -55,56 +56,6 @@ static int koneplus_send_control(struct usb_device *usb_dev, uint value,
 			&control, sizeof(struct roccat_common2_control));
 }
 
-static int koneplus_get_info(struct usb_device *usb_dev,
-		struct koneplus_info *buf)
-{
-	return roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_INFO,
-			buf, sizeof(struct koneplus_info));
-}
-
-static int koneplus_get_profile_settings(struct usb_device *usb_dev,
-		struct koneplus_profile_settings *buf, uint number)
-{
-	int retval;
-
-	retval = koneplus_send_control(usb_dev, number,
-			KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
-	if (retval)
-		return retval;
-
-	return roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS,
-			buf, sizeof(struct koneplus_profile_settings));
-}
-
-static int koneplus_set_profile_settings(struct usb_device *usb_dev,
-		struct koneplus_profile_settings const *settings)
-{
-	return roccat_common2_send_with_status(usb_dev,
-			KONEPLUS_COMMAND_PROFILE_SETTINGS,
-			settings, sizeof(struct koneplus_profile_settings));
-}
-
-static int koneplus_get_profile_buttons(struct usb_device *usb_dev,
-		struct koneplus_profile_buttons *buf, int number)
-{
-	int retval;
-
-	retval = koneplus_send_control(usb_dev, number,
-			KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
-	if (retval)
-		return retval;
-
-	return roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS,
-			buf, sizeof(struct koneplus_profile_buttons));
-}
-
-static int koneplus_set_profile_buttons(struct usb_device *usb_dev,
-		struct koneplus_profile_buttons const *buttons)
-{
-	return roccat_common2_send_with_status(usb_dev,
-			KONEPLUS_COMMAND_PROFILE_BUTTONS,
-			buttons, sizeof(struct koneplus_profile_buttons));
-}
 
 /* retval is 0-4 on success, < 0 on error */
 static int koneplus_get_actual_profile(struct usb_device *usb_dev)
@@ -113,7 +64,7 @@ static int koneplus_get_actual_profile(struct usb_device *usb_dev)
 	int retval;
 
 	retval = roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE,
-			&buf, sizeof(struct koneplus_actual_profile));
+			&buf, KONEPLUS_SIZE_ACTUAL_PROFILE);
 
 	return retval ? retval : buf.actual_profile;
 }
@@ -124,12 +75,12 @@ static int koneplus_set_actual_profile(struct usb_device *usb_dev,
 	struct koneplus_actual_profile buf;
 
 	buf.command = KONEPLUS_COMMAND_ACTUAL_PROFILE;
-	buf.size = sizeof(struct koneplus_actual_profile);
+	buf.size = KONEPLUS_SIZE_ACTUAL_PROFILE;
 	buf.actual_profile = new_profile;
 
 	return roccat_common2_send_with_status(usb_dev,
 			KONEPLUS_COMMAND_ACTUAL_PROFILE,
-			&buf, sizeof(struct koneplus_actual_profile));
+			&buf, KONEPLUS_SIZE_ACTUAL_PROFILE);
 }
 
 static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
@@ -182,111 +133,77 @@ static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj,
 	return real_size;
 }
 
-static ssize_t koneplus_sysfs_write_talk(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	return koneplus_sysfs_write(fp, kobj, buf, off, count,
-			sizeof(struct koneplus_talk), KONEPLUS_COMMAND_TALK);
+#define KONEPLUS_SYSFS_W(thingy, THINGY) \
+static ssize_t koneplus_sysfs_write_ ## thingy(struct file *fp, \
+		struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+		loff_t off, size_t count) \
+{ \
+	return koneplus_sysfs_write(fp, kobj, buf, off, count, \
+			KONEPLUS_SIZE_ ## THINGY, KONEPLUS_COMMAND_ ## THINGY); \
 }
 
-static ssize_t koneplus_sysfs_write_macro(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	return koneplus_sysfs_write(fp, kobj, buf, off, count,
-			sizeof(struct koneplus_macro), KONEPLUS_COMMAND_MACRO);
+#define KONEPLUS_SYSFS_R(thingy, THINGY) \
+static ssize_t koneplus_sysfs_read_ ## thingy(struct file *fp, \
+		struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+		loff_t off, size_t count) \
+{ \
+	return koneplus_sysfs_read(fp, kobj, buf, off, count, \
+			KONEPLUS_SIZE_ ## THINGY, KONEPLUS_COMMAND_ ## THINGY); \
 }
 
-static ssize_t koneplus_sysfs_read_sensor(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	return koneplus_sysfs_read(fp, kobj, buf, off, count,
-			sizeof(struct koneplus_sensor), KONEPLUS_COMMAND_SENSOR);
-}
+#define KONEPLUS_SYSFS_RW(thingy, THINGY) \
+KONEPLUS_SYSFS_W(thingy, THINGY) \
+KONEPLUS_SYSFS_R(thingy, THINGY)
 
-static ssize_t koneplus_sysfs_write_sensor(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	return koneplus_sysfs_write(fp, kobj, buf, off, count,
-			sizeof(struct koneplus_sensor), KONEPLUS_COMMAND_SENSOR);
+#define KONEPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \
+{ \
+	.attr = { .name = #thingy, .mode = 0660 }, \
+	.size = KONEPLUS_SIZE_ ## THINGY, \
+	.read = koneplus_sysfs_read_ ## thingy, \
+	.write = koneplus_sysfs_write_ ## thingy \
 }
 
-static ssize_t koneplus_sysfs_write_tcu(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	return koneplus_sysfs_write(fp, kobj, buf, off, count,
-			sizeof(struct koneplus_tcu), KONEPLUS_COMMAND_TCU);
+#define KONEPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \
+{ \
+	.attr = { .name = #thingy, .mode = 0440 }, \
+	.size = KONEPLUS_SIZE_ ## THINGY, \
+	.read = koneplus_sysfs_read_ ## thingy, \
 }
 
-static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	return koneplus_sysfs_read(fp, kobj, buf, off, count,
-			sizeof(struct koneplus_tcu_image), KONEPLUS_COMMAND_TCU);
+#define KONEPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \
+{ \
+	.attr = { .name = #thingy, .mode = 0220 }, \
+	.size = KONEPLUS_SIZE_ ## THINGY, \
+	.write = koneplus_sysfs_write_ ## thingy \
 }
 
-static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	struct device *dev =
-			container_of(kobj, struct device, kobj)->parent->parent;
-	struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
-
-	if (off >= sizeof(struct koneplus_profile_settings))
-		return 0;
+KONEPLUS_SYSFS_W(control, CONTROL)
+KONEPLUS_SYSFS_RW(info, INFO)
+KONEPLUS_SYSFS_W(talk, TALK)
+KONEPLUS_SYSFS_W(macro, MACRO)
+KONEPLUS_SYSFS_RW(sensor, SENSOR)
+KONEPLUS_SYSFS_RW(tcu, TCU)
+KONEPLUS_SYSFS_R(tcu_image, TCU_IMAGE)
+KONEPLUS_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
+KONEPLUS_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
 
-	if (off + count > sizeof(struct koneplus_profile_settings))
-		count = sizeof(struct koneplus_profile_settings) - off;
-
-	mutex_lock(&koneplus->koneplus_lock);
-	memcpy(buf, ((char const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off,
-			count);
-	mutex_unlock(&koneplus->koneplus_lock);
-
-	return count;
-}
-
-static ssize_t koneplus_sysfs_write_profile_settings(struct file *fp,
+static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
 		loff_t off, size_t count)
 {
 	struct device *dev =
 			container_of(kobj, struct device, kobj)->parent->parent;
-	struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
 	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
-	int retval = 0;
-	int difference;
-	int profile_number;
-	struct koneplus_profile_settings *profile_settings;
-
-	if (off != 0 || count != sizeof(struct koneplus_profile_settings))
-		return -EINVAL;
-
-	profile_number = ((struct koneplus_profile_settings const *)buf)->number;
-	profile_settings = &koneplus->profile_settings[profile_number];
-
-	mutex_lock(&koneplus->koneplus_lock);
-	difference = memcmp(buf, profile_settings,
-			sizeof(struct koneplus_profile_settings));
-	if (difference) {
-		retval = koneplus_set_profile_settings(usb_dev,
-				(struct koneplus_profile_settings const *)buf);
-		if (!retval)
-			memcpy(profile_settings, buf,
-					sizeof(struct koneplus_profile_settings));
-	}
-	mutex_unlock(&koneplus->koneplus_lock);
+	ssize_t retval;
 
+	retval = koneplus_send_control(usb_dev, *(uint *)(attr->private),
+			KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
 	if (retval)
 		return retval;
 
-	return sizeof(struct koneplus_profile_settings);
+	return koneplus_sysfs_read(fp, kobj, buf, off, count,
+			KONEPLUS_SIZE_PROFILE_SETTINGS,
+			KONEPLUS_COMMAND_PROFILE_SETTINGS);
 }
 
 static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
@@ -295,57 +212,17 @@ static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
 {
 	struct device *dev =
 			container_of(kobj, struct device, kobj)->parent->parent;
-	struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
-
-	if (off >= sizeof(struct koneplus_profile_buttons))
-		return 0;
-
-	if (off + count > sizeof(struct koneplus_profile_buttons))
-		count = sizeof(struct koneplus_profile_buttons) - off;
-
-	mutex_lock(&koneplus->koneplus_lock);
-	memcpy(buf, ((char const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off,
-			count);
-	mutex_unlock(&koneplus->koneplus_lock);
-
-	return count;
-}
-
-static ssize_t koneplus_sysfs_write_profile_buttons(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	struct device *dev =
-			container_of(kobj, struct device, kobj)->parent->parent;
-	struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
 	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
-	int retval = 0;
-	int difference;
-	uint profile_number;
-	struct koneplus_profile_buttons *profile_buttons;
-
-	if (off != 0 || count != sizeof(struct koneplus_profile_buttons))
-		return -EINVAL;
-
-	profile_number = ((struct koneplus_profile_buttons const *)buf)->number;
-	profile_buttons = &koneplus->profile_buttons[profile_number];
-
-	mutex_lock(&koneplus->koneplus_lock);
-	difference = memcmp(buf, profile_buttons,
-			sizeof(struct koneplus_profile_buttons));
-	if (difference) {
-		retval = koneplus_set_profile_buttons(usb_dev,
-				(struct koneplus_profile_buttons const *)buf);
-		if (!retval)
-			memcpy(profile_buttons, buf,
-					sizeof(struct koneplus_profile_buttons));
-	}
-	mutex_unlock(&koneplus->koneplus_lock);
+	ssize_t retval;
 
+	retval = koneplus_send_control(usb_dev, *(uint *)(attr->private),
+			KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
 	if (retval)
 		return retval;
 
-	return sizeof(struct koneplus_profile_buttons);
+	return koneplus_sysfs_read(fp, kobj, buf, off, count,
+			KONEPLUS_SIZE_PROFILE_BUTTONS,
+			KONEPLUS_COMMAND_PROFILE_BUTTONS);
 }
 
 static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev,
@@ -401,9 +278,20 @@ static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev,
 static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct koneplus_device *koneplus =
-			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
-	return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->info.firmware_version);
+	struct koneplus_device *koneplus;
+	struct usb_device *usb_dev;
+	struct koneplus_info info;
+
+	dev = dev->parent->parent;
+	koneplus = hid_get_drvdata(dev_get_drvdata(dev));
+	usb_dev = interface_to_usbdev(to_usb_interface(dev));
+
+	mutex_lock(&koneplus->koneplus_lock);
+	roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_INFO,
+			&info, KONEPLUS_SIZE_INFO);
+	mutex_unlock(&koneplus->koneplus_lock);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
 }
 
 static struct device_attribute koneplus_attributes[] = {
@@ -419,132 +307,85 @@ static struct device_attribute koneplus_attributes[] = {
 };
 
 static struct bin_attribute koneplus_bin_attributes[] = {
-	{
-		.attr = { .name = "sensor", .mode = 0660 },
-		.size = sizeof(struct koneplus_sensor),
-		.read = koneplus_sysfs_read_sensor,
-		.write = koneplus_sysfs_write_sensor
-	},
-	{
-		.attr = { .name = "tcu", .mode = 0220 },
-		.size = sizeof(struct koneplus_tcu),
-		.write = koneplus_sysfs_write_tcu
-	},
-	{
-		.attr = { .name = "tcu_image", .mode = 0440 },
-		.size = sizeof(struct koneplus_tcu_image),
-		.read = koneplus_sysfs_read_tcu_image
-	},
-	{
-		.attr = { .name = "profile_settings", .mode = 0220 },
-		.size = sizeof(struct koneplus_profile_settings),
-		.write = koneplus_sysfs_write_profile_settings
-	},
+	KONEPLUS_BIN_ATTRIBUTE_W(control, CONTROL),
+	KONEPLUS_BIN_ATTRIBUTE_RW(info, INFO),
+	KONEPLUS_BIN_ATTRIBUTE_W(talk, TALK),
+	KONEPLUS_BIN_ATTRIBUTE_W(macro, MACRO),
+	KONEPLUS_BIN_ATTRIBUTE_RW(sensor, SENSOR),
+	KONEPLUS_BIN_ATTRIBUTE_RW(tcu, TCU),
+	KONEPLUS_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE),
+	KONEPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
+	KONEPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
 	{
 		.attr = { .name = "profile1_settings", .mode = 0440 },
-		.size = sizeof(struct koneplus_profile_settings),
+		.size = KONEPLUS_SIZE_PROFILE_SETTINGS,
 		.read = koneplus_sysfs_read_profilex_settings,
 		.private = &profile_numbers[0]
 	},
 	{
 		.attr = { .name = "profile2_settings", .mode = 0440 },
-		.size = sizeof(struct koneplus_profile_settings),
+		.size = KONEPLUS_SIZE_PROFILE_SETTINGS,
 		.read = koneplus_sysfs_read_profilex_settings,
 		.private = &profile_numbers[1]
 	},
 	{
 		.attr = { .name = "profile3_settings", .mode = 0440 },
-		.size = sizeof(struct koneplus_profile_settings),
+		.size = KONEPLUS_SIZE_PROFILE_SETTINGS,
 		.read = koneplus_sysfs_read_profilex_settings,
 		.private = &profile_numbers[2]
 	},
 	{
 		.attr = { .name = "profile4_settings", .mode = 0440 },
-		.size = sizeof(struct koneplus_profile_settings),
+		.size = KONEPLUS_SIZE_PROFILE_SETTINGS,
 		.read = koneplus_sysfs_read_profilex_settings,
 		.private = &profile_numbers[3]
 	},
 	{
 		.attr = { .name = "profile5_settings", .mode = 0440 },
-		.size = sizeof(struct koneplus_profile_settings),
+		.size = KONEPLUS_SIZE_PROFILE_SETTINGS,
 		.read = koneplus_sysfs_read_profilex_settings,
 		.private = &profile_numbers[4]
 	},
 	{
-		.attr = { .name = "profile_buttons", .mode = 0220 },
-		.size = sizeof(struct koneplus_profile_buttons),
-		.write = koneplus_sysfs_write_profile_buttons
-	},
-	{
 		.attr = { .name = "profile1_buttons", .mode = 0440 },
-		.size = sizeof(struct koneplus_profile_buttons),
+		.size = KONEPLUS_SIZE_PROFILE_BUTTONS,
 		.read = koneplus_sysfs_read_profilex_buttons,
 		.private = &profile_numbers[0]
 	},
 	{
 		.attr = { .name = "profile2_buttons", .mode = 0440 },
-		.size = sizeof(struct koneplus_profile_buttons),
+		.size = KONEPLUS_SIZE_PROFILE_BUTTONS,
 		.read = koneplus_sysfs_read_profilex_buttons,
 		.private = &profile_numbers[1]
 	},
 	{
 		.attr = { .name = "profile3_buttons", .mode = 0440 },
-		.size = sizeof(struct koneplus_profile_buttons),
+		.size = KONEPLUS_SIZE_PROFILE_BUTTONS,
 		.read = koneplus_sysfs_read_profilex_buttons,
 		.private = &profile_numbers[2]
 	},
 	{
 		.attr = { .name = "profile4_buttons", .mode = 0440 },
-		.size = sizeof(struct koneplus_profile_buttons),
+		.size = KONEPLUS_SIZE_PROFILE_BUTTONS,
 		.read = koneplus_sysfs_read_profilex_buttons,
 		.private = &profile_numbers[3]
 	},
 	{
 		.attr = { .name = "profile5_buttons", .mode = 0440 },
-		.size = sizeof(struct koneplus_profile_buttons),
+		.size = KONEPLUS_SIZE_PROFILE_BUTTONS,
 		.read = koneplus_sysfs_read_profilex_buttons,
 		.private = &profile_numbers[4]
 	},
-	{
-		.attr = { .name = "macro", .mode = 0220 },
-		.size = sizeof(struct koneplus_macro),
-		.write = koneplus_sysfs_write_macro
-	},
-	{
-		.attr = { .name = "talk", .mode = 0220 },
-		.size = sizeof(struct koneplus_talk),
-		.write = koneplus_sysfs_write_talk
-	},
 	__ATTR_NULL
 };
 
 static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
 		struct koneplus_device *koneplus)
 {
-	int retval, i;
-	static uint wait = 200;
+	int retval;
 
 	mutex_init(&koneplus->koneplus_lock);
 
-	retval = koneplus_get_info(usb_dev, &koneplus->info);
-	if (retval)
-		return retval;
-
-	for (i = 0; i < 5; ++i) {
-		msleep(wait);
-		retval = koneplus_get_profile_settings(usb_dev,
-				&koneplus->profile_settings[i], i);
-		if (retval)
-			return retval;
-
-		msleep(wait);
-		retval = koneplus_get_profile_buttons(usb_dev,
-				&koneplus->profile_buttons[i], i);
-		if (retval)
-			return retval;
-	}
-
-	msleep(wait);
 	retval = koneplus_get_actual_profile(usb_dev);
 	if (retval < 0)
 		return retval;
@@ -709,6 +550,7 @@ static int koneplus_raw_event(struct hid_device *hdev,
 
 static const struct hid_device_id koneplus_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEXTD) },
 	{ }
 };
 
@@ -749,5 +591,5 @@ module_init(koneplus_init);
 module_exit(koneplus_exit);
 
 MODULE_AUTHOR("Stefan Achatz");
-MODULE_DESCRIPTION("USB Roccat Kone[+] driver");
+MODULE_DESCRIPTION("USB Roccat Kone[+]/XTD driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-koneplus.h b/drivers/hid/hid-roccat-koneplus.h
index 7074b2a..af7f57e 100644
--- a/drivers/hid/hid-roccat-koneplus.h
+++ b/drivers/hid/hid-roccat-koneplus.h
@@ -14,11 +14,19 @@
 
 #include <linux/types.h>
 
-struct koneplus_talk {
-	uint8_t command; /* KONEPLUS_COMMAND_TALK */
-	uint8_t size; /* always 0x10 */
-	uint8_t data[14];
-} __packed;
+enum {
+	KONEPLUS_SIZE_ACTUAL_PROFILE = 0x03,
+	KONEPLUS_SIZE_CONTROL = 0x03,
+	KONEPLUS_SIZE_FIRMWARE_WRITE = 0x0402,
+	KONEPLUS_SIZE_INFO = 0x06,
+	KONEPLUS_SIZE_MACRO = 0x0822,
+	KONEPLUS_SIZE_PROFILE_SETTINGS = 0x2b,
+	KONEPLUS_SIZE_PROFILE_BUTTONS = 0x4d,
+	KONEPLUS_SIZE_SENSOR = 0x06,
+	KONEPLUS_SIZE_TALK = 0x10,
+	KONEPLUS_SIZE_TCU = 0x04,
+	KONEPLUS_SIZE_TCU_IMAGE = 0x0404,
+};
 
 enum koneplus_control_requests {
 	KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x80,
@@ -31,45 +39,6 @@ struct koneplus_actual_profile {
 	uint8_t actual_profile; /* Range 0-4! */
 } __attribute__ ((__packed__));
 
-struct koneplus_profile_settings {
-	uint8_t command; /* KONEPLUS_COMMAND_PROFILE_SETTINGS */
-	uint8_t size; /* always 43 */
-	uint8_t number; /* range 0-4 */
-	uint8_t advanced_sensitivity;
-	uint8_t sensitivity_x;
-	uint8_t sensitivity_y;
-	uint8_t cpi_levels_enabled;
-	uint8_t cpi_levels_x[5];
-	uint8_t cpi_startup_level; /* range 0-4 */
-	uint8_t cpi_levels_y[5]; /* range 1-60 means 100-6000 cpi */
-	uint8_t unknown1;
-	uint8_t polling_rate;
-	uint8_t lights_enabled;
-	uint8_t light_effect_mode;
-	uint8_t color_flow_effect;
-	uint8_t light_effect_type;
-	uint8_t light_effect_speed;
-	uint8_t lights[16];
-	uint16_t checksum;
-} __attribute__ ((__packed__));
-
-struct koneplus_profile_buttons {
-	uint8_t command; /* KONEPLUS_COMMAND_PROFILE_BUTTONS */
-	uint8_t size; /* always 77 */
-	uint8_t number; /* range 0-4 */
-	uint8_t data[72];
-	uint16_t checksum;
-} __attribute__ ((__packed__));
-
-struct koneplus_macro {
-	uint8_t command; /* KONEPLUS_COMMAND_MACRO */
-	uint16_t size; /* always 0x822 little endian */
-	uint8_t profile; /* range 0-4 */
-	uint8_t button; /* range 0-23 */
-	uint8_t data[2075];
-	uint16_t checksum;
-} __attribute__ ((__packed__));
-
 struct koneplus_info {
 	uint8_t command; /* KONEPLUS_COMMAND_INFO */
 	uint8_t size; /* always 6 */
@@ -77,51 +46,15 @@ struct koneplus_info {
 	uint8_t unknown[3];
 } __attribute__ ((__packed__));
 
-struct koneplus_e {
-	uint8_t command; /* KONEPLUS_COMMAND_E */
-	uint8_t size; /* always 3 */
-	uint8_t unknown; /* TODO 1; 0 before firmware update */
-} __attribute__ ((__packed__));
-
-struct koneplus_sensor {
-	uint8_t command;  /* KONEPLUS_COMMAND_SENSOR */
-	uint8_t size; /* always 6 */
-	uint8_t data[4];
-} __attribute__ ((__packed__));
-
-struct koneplus_firmware_write {
-	uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE */
-	uint8_t unknown[1025];
-} __attribute__ ((__packed__));
-
-struct koneplus_firmware_write_control {
-	uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL */
-	/*
-	 * value is 1 on success
-	 * 3 means "not finished yet"
-	 */
-	uint8_t value;
-	uint8_t unknown; /* always 0x75 */
-} __attribute__ ((__packed__));
-
-struct koneplus_tcu {
-	uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */
-	uint8_t data[2];
-} __attribute__ ((__packed__));
-
-struct koneplus_tcu_image {
-	uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */
-	uint8_t data[1024];
-	uint16_t checksum;
-} __attribute__ ((__packed__));
-
 enum koneplus_commands {
 	KONEPLUS_COMMAND_ACTUAL_PROFILE = 0x5,
+	KONEPLUS_COMMAND_CONTROL = 0x4,
 	KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
 	KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
 	KONEPLUS_COMMAND_MACRO = 0x8,
 	KONEPLUS_COMMAND_INFO = 0x9,
 	KONEPLUS_COMMAND_TCU = 0xc,
+	KONEPLUS_COMMAND_TCU_IMAGE = 0xc,
 	KONEPLUS_COMMAND_E = 0xe,
 	KONEPLUS_COMMAND_SENSOR = 0xf,
 	KONEPLUS_COMMAND_TALK = 0x10,
@@ -187,10 +120,6 @@ struct koneplus_device {
 	int chrdev_minor;
 
 	struct mutex koneplus_lock;
-
-	struct koneplus_info info;
-	struct koneplus_profile_settings profile_settings[5];
-	struct koneplus_profile_buttons profile_buttons[5];
 };
 
 #endif
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c
index ca6527a..b8b3778 100644
--- a/drivers/hid/hid-roccat-kovaplus.c
+++ b/drivers/hid/hid-roccat-kovaplus.c
@@ -70,13 +70,6 @@ static int kovaplus_select_profile(struct usb_device *usb_dev, uint number,
 	return kovaplus_send_control(usb_dev, number, request);
 }
 
-static int kovaplus_get_info(struct usb_device *usb_dev,
-		struct kovaplus_info *buf)
-{
-	return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_INFO,
-			buf, sizeof(struct kovaplus_info));
-}
-
 static int kovaplus_get_profile_settings(struct usb_device *usb_dev,
 		struct kovaplus_profile_settings *buf, uint number)
 {
@@ -88,15 +81,7 @@ static int kovaplus_get_profile_settings(struct usb_device *usb_dev,
 		return retval;
 
 	return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS,
-			buf, sizeof(struct kovaplus_profile_settings));
-}
-
-static int kovaplus_set_profile_settings(struct usb_device *usb_dev,
-		struct kovaplus_profile_settings const *settings)
-{
-	return roccat_common2_send_with_status(usb_dev,
-			KOVAPLUS_COMMAND_PROFILE_SETTINGS,
-			settings, sizeof(struct kovaplus_profile_settings));
+			buf, KOVAPLUS_SIZE_PROFILE_SETTINGS);
 }
 
 static int kovaplus_get_profile_buttons(struct usb_device *usb_dev,
@@ -110,15 +95,7 @@ static int kovaplus_get_profile_buttons(struct usb_device *usb_dev,
 		return retval;
 
 	return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS,
-			buf, sizeof(struct kovaplus_profile_buttons));
-}
-
-static int kovaplus_set_profile_buttons(struct usb_device *usb_dev,
-		struct kovaplus_profile_buttons const *buttons)
-{
-	return roccat_common2_send_with_status(usb_dev,
-			KOVAPLUS_COMMAND_PROFILE_BUTTONS,
-			buttons, sizeof(struct kovaplus_profile_buttons));
+			buf, KOVAPLUS_SIZE_PROFILE_BUTTONS);
 }
 
 /* retval is 0-4 on success, < 0 on error */
@@ -147,122 +124,141 @@ static int kovaplus_set_actual_profile(struct usb_device *usb_dev,
 			&buf, sizeof(struct kovaplus_actual_profile));
 }
 
-static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
+static ssize_t kovaplus_sysfs_read(struct file *fp, struct kobject *kobj,
+		char *buf, loff_t off, size_t count,
+		size_t real_size, uint command)
 {
 	struct device *dev =
 			container_of(kobj, struct device, kobj)->parent->parent;
 	struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval;
 
-	if (off >= sizeof(struct kovaplus_profile_settings))
+	if (off >= real_size)
 		return 0;
 
-	if (off + count > sizeof(struct kovaplus_profile_settings))
-		count = sizeof(struct kovaplus_profile_settings) - off;
+	if (off != 0 || count != real_size)
+		return -EINVAL;
 
 	mutex_lock(&kovaplus->kovaplus_lock);
-	memcpy(buf, ((char const *)&kovaplus->profile_settings[*(uint *)(attr->private)]) + off,
-			count);
+	retval = roccat_common2_receive(usb_dev, command, buf, real_size);
 	mutex_unlock(&kovaplus->kovaplus_lock);
 
-	return count;
+	if (retval)
+		return retval;
+
+	return real_size;
 }
 
-static ssize_t kovaplus_sysfs_write_profile_settings(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
+static ssize_t kovaplus_sysfs_write(struct file *fp, struct kobject *kobj,
+		void const *buf, loff_t off, size_t count,
+		size_t real_size, uint command)
 {
 	struct device *dev =
 			container_of(kobj, struct device, kobj)->parent->parent;
 	struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
 	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
-	int retval = 0;
-	int difference;
-	int profile_index;
-	struct kovaplus_profile_settings *profile_settings;
+	int retval;
 
-	if (off != 0 || count != sizeof(struct kovaplus_profile_settings))
+	if (off != 0 || count != real_size)
 		return -EINVAL;
 
-	profile_index = ((struct kovaplus_profile_settings const *)buf)->profile_index;
-	profile_settings = &kovaplus->profile_settings[profile_index];
-
 	mutex_lock(&kovaplus->kovaplus_lock);
-	difference = memcmp(buf, profile_settings,
-			sizeof(struct kovaplus_profile_settings));
-	if (difference) {
-		retval = kovaplus_set_profile_settings(usb_dev,
-				(struct kovaplus_profile_settings const *)buf);
-		if (!retval)
-			memcpy(profile_settings, buf,
-					sizeof(struct kovaplus_profile_settings));
-	}
+	retval = roccat_common2_send_with_status(usb_dev, command,
+			buf, real_size);
 	mutex_unlock(&kovaplus->kovaplus_lock);
 
 	if (retval)
 		return retval;
 
-	return sizeof(struct kovaplus_profile_settings);
+	return real_size;
 }
 
-static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	struct device *dev =
-			container_of(kobj, struct device, kobj)->parent->parent;
-	struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+#define KOVAPLUS_SYSFS_W(thingy, THINGY) \
+static ssize_t kovaplus_sysfs_write_ ## thingy(struct file *fp, \
+		struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+		loff_t off, size_t count) \
+{ \
+	return kovaplus_sysfs_write(fp, kobj, buf, off, count, \
+			KOVAPLUS_SIZE_ ## THINGY, KOVAPLUS_COMMAND_ ## THINGY); \
+}
 
-	if (off >= sizeof(struct kovaplus_profile_buttons))
-		return 0;
+#define KOVAPLUS_SYSFS_R(thingy, THINGY) \
+static ssize_t kovaplus_sysfs_read_ ## thingy(struct file *fp, \
+		struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+		loff_t off, size_t count) \
+{ \
+	return kovaplus_sysfs_read(fp, kobj, buf, off, count, \
+			KOVAPLUS_SIZE_ ## THINGY, KOVAPLUS_COMMAND_ ## THINGY); \
+}
 
-	if (off + count > sizeof(struct kovaplus_profile_buttons))
-		count = sizeof(struct kovaplus_profile_buttons) - off;
+#define KOVAPLUS_SYSFS_RW(thingy, THINGY) \
+KOVAPLUS_SYSFS_W(thingy, THINGY) \
+KOVAPLUS_SYSFS_R(thingy, THINGY)
 
-	mutex_lock(&kovaplus->kovaplus_lock);
-	memcpy(buf, ((char const *)&kovaplus->profile_buttons[*(uint *)(attr->private)]) + off,
-			count);
-	mutex_unlock(&kovaplus->kovaplus_lock);
+#define KOVAPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \
+{ \
+	.attr = { .name = #thingy, .mode = 0660 }, \
+	.size = KOVAPLUS_SIZE_ ## THINGY, \
+	.read = kovaplus_sysfs_read_ ## thingy, \
+	.write = kovaplus_sysfs_write_ ## thingy \
+}
+
+#define KOVAPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \
+{ \
+	.attr = { .name = #thingy, .mode = 0440 }, \
+	.size = KOVAPLUS_SIZE_ ## THINGY, \
+	.read = kovaplus_sysfs_read_ ## thingy, \
+}
 
-	return count;
+#define KOVAPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \
+{ \
+	.attr = { .name = #thingy, .mode = 0220 }, \
+	.size = KOVAPLUS_SIZE_ ## THINGY, \
+	.write = kovaplus_sysfs_write_ ## thingy \
 }
 
-static ssize_t kovaplus_sysfs_write_profile_buttons(struct file *fp,
+KOVAPLUS_SYSFS_W(control, CONTROL)
+KOVAPLUS_SYSFS_RW(info, INFO)
+KOVAPLUS_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
+KOVAPLUS_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
+
+static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp,
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
 		loff_t off, size_t count)
 {
 	struct device *dev =
 			container_of(kobj, struct device, kobj)->parent->parent;
-	struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
 	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
-	int retval = 0;
-	int difference;
-	uint profile_index;
-	struct kovaplus_profile_buttons *profile_buttons;
+	ssize_t retval;
 
-	if (off != 0 || count != sizeof(struct kovaplus_profile_buttons))
-		return -EINVAL;
+	retval = kovaplus_select_profile(usb_dev, *(uint *)(attr->private),
+			KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
+	if (retval)
+		return retval;
 
-	profile_index = ((struct kovaplus_profile_buttons const *)buf)->profile_index;
-	profile_buttons = &kovaplus->profile_buttons[profile_index];
+	return kovaplus_sysfs_read(fp, kobj, buf, off, count,
+			KOVAPLUS_SIZE_PROFILE_SETTINGS,
+			KOVAPLUS_COMMAND_PROFILE_SETTINGS);
+}
 
-	mutex_lock(&kovaplus->kovaplus_lock);
-	difference = memcmp(buf, profile_buttons,
-			sizeof(struct kovaplus_profile_buttons));
-	if (difference) {
-		retval = kovaplus_set_profile_buttons(usb_dev,
-				(struct kovaplus_profile_buttons const *)buf);
-		if (!retval)
-			memcpy(profile_buttons, buf,
-					sizeof(struct kovaplus_profile_buttons));
-	}
-	mutex_unlock(&kovaplus->kovaplus_lock);
+static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	ssize_t retval;
 
+	retval = kovaplus_select_profile(usb_dev, *(uint *)(attr->private),
+			KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
 	if (retval)
 		return retval;
 
-	return sizeof(struct kovaplus_profile_buttons);
+	return kovaplus_sysfs_read(fp, kobj, buf, off, count,
+			KOVAPLUS_SIZE_PROFILE_BUTTONS,
+			KOVAPLUS_COMMAND_PROFILE_BUTTONS);
 }
 
 static ssize_t kovaplus_sysfs_show_actual_profile(struct device *dev,
@@ -342,9 +338,20 @@ static ssize_t kovaplus_sysfs_show_actual_sensitivity_y(struct device *dev,
 static ssize_t kovaplus_sysfs_show_firmware_version(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct kovaplus_device *kovaplus =
-			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
-	return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->info.firmware_version);
+	struct kovaplus_device *kovaplus;
+	struct usb_device *usb_dev;
+	struct kovaplus_info info;
+
+	dev = dev->parent->parent;
+	kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+	usb_dev = interface_to_usbdev(to_usb_interface(dev));
+
+	mutex_lock(&kovaplus->kovaplus_lock);
+	roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_INFO,
+			&info, KOVAPLUS_SIZE_INFO);
+	mutex_unlock(&kovaplus->kovaplus_lock);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
 }
 
 static struct device_attribute kovaplus_attributes[] = {
@@ -363,73 +370,67 @@ static struct device_attribute kovaplus_attributes[] = {
 };
 
 static struct bin_attribute kovaplus_bin_attributes[] = {
-	{
-		.attr = { .name = "profile_settings", .mode = 0220 },
-		.size = sizeof(struct kovaplus_profile_settings),
-		.write = kovaplus_sysfs_write_profile_settings
-	},
+	KOVAPLUS_BIN_ATTRIBUTE_W(control, CONTROL),
+	KOVAPLUS_BIN_ATTRIBUTE_RW(info, INFO),
+	KOVAPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
+	KOVAPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
 	{
 		.attr = { .name = "profile1_settings", .mode = 0440 },
-		.size = sizeof(struct kovaplus_profile_settings),
+		.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
 		.read = kovaplus_sysfs_read_profilex_settings,
 		.private = &profile_numbers[0]
 	},
 	{
 		.attr = { .name = "profile2_settings", .mode = 0440 },
-		.size = sizeof(struct kovaplus_profile_settings),
+		.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
 		.read = kovaplus_sysfs_read_profilex_settings,
 		.private = &profile_numbers[1]
 	},
 	{
 		.attr = { .name = "profile3_settings", .mode = 0440 },
-		.size = sizeof(struct kovaplus_profile_settings),
+		.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
 		.read = kovaplus_sysfs_read_profilex_settings,
 		.private = &profile_numbers[2]
 	},
 	{
 		.attr = { .name = "profile4_settings", .mode = 0440 },
-		.size = sizeof(struct kovaplus_profile_settings),
+		.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
 		.read = kovaplus_sysfs_read_profilex_settings,
 		.private = &profile_numbers[3]
 	},
 	{
 		.attr = { .name = "profile5_settings", .mode = 0440 },
-		.size = sizeof(struct kovaplus_profile_settings),
+		.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
 		.read = kovaplus_sysfs_read_profilex_settings,
 		.private = &profile_numbers[4]
 	},
 	{
-		.attr = { .name = "profile_buttons", .mode = 0220 },
-		.size = sizeof(struct kovaplus_profile_buttons),
-		.write = kovaplus_sysfs_write_profile_buttons
-	},
-	{
 		.attr = { .name = "profile1_buttons", .mode = 0440 },
-		.size = sizeof(struct kovaplus_profile_buttons),
+		.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
 		.read = kovaplus_sysfs_read_profilex_buttons,
 		.private = &profile_numbers[0]
 	},
 	{
 		.attr = { .name = "profile2_buttons", .mode = 0440 },
-		.size = sizeof(struct kovaplus_profile_buttons),
+		.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
 		.read = kovaplus_sysfs_read_profilex_buttons,
 		.private = &profile_numbers[1]
 	},
 	{
 		.attr = { .name = "profile3_buttons", .mode = 0440 },
-		.size = sizeof(struct kovaplus_profile_buttons),
+		.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
 		.read = kovaplus_sysfs_read_profilex_buttons,
 		.private = &profile_numbers[2]
 	},
 	{
 		.attr = { .name = "profile4_buttons", .mode = 0440 },
-		.size = sizeof(struct kovaplus_profile_buttons),
+		.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
 		.read = kovaplus_sysfs_read_profilex_buttons,
 		.private = &profile_numbers[3]
 	},
 	{
 		.attr = { .name = "profile5_buttons", .mode = 0440 },
-		.size = sizeof(struct kovaplus_profile_buttons),
+		.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
 		.read = kovaplus_sysfs_read_profilex_buttons,
 		.private = &profile_numbers[4]
 	},
@@ -444,10 +445,6 @@ static int kovaplus_init_kovaplus_device_struct(struct usb_device *usb_dev,
 
 	mutex_init(&kovaplus->kovaplus_lock);
 
-	retval = kovaplus_get_info(usb_dev, &kovaplus->info);
-	if (retval)
-		return retval;
-
 	for (i = 0; i < 5; ++i) {
 		msleep(wait);
 		retval = kovaplus_get_profile_settings(usb_dev,
diff --git a/drivers/hid/hid-roccat-kovaplus.h b/drivers/hid/hid-roccat-kovaplus.h
index f82daa1..fbb7a16 100644
--- a/drivers/hid/hid-roccat-kovaplus.h
+++ b/drivers/hid/hid-roccat-kovaplus.h
@@ -14,6 +14,13 @@
 
 #include <linux/types.h>
 
+enum {
+	KOVAPLUS_SIZE_CONTROL = 0x03,
+	KOVAPLUS_SIZE_INFO = 0x06,
+	KOVAPLUS_SIZE_PROFILE_SETTINGS = 0x10,
+	KOVAPLUS_SIZE_PROFILE_BUTTONS = 0x17,
+};
+
 enum kovaplus_control_requests {
 	/* write; value = profile number range 0-4 */
 	KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10,
@@ -53,15 +60,9 @@ struct kovaplus_info {
 	uint8_t unknown[3];
 } __packed;
 
-/* writes 1 on plugin */
-struct kovaplus_a {
-	uint8_t command; /* KOVAPLUS_COMMAND_A */
-	uint8_t size; /* 3 */
-	uint8_t unknown;
-} __packed;
-
 enum kovaplus_commands {
 	KOVAPLUS_COMMAND_ACTUAL_PROFILE = 0x5,
+	KOVAPLUS_COMMAND_CONTROL = 0x4,
 	KOVAPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
 	KOVAPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
 	KOVAPLUS_COMMAND_INFO = 0x9,
@@ -125,7 +126,6 @@ struct kovaplus_device {
 	int roccat_claimed;
 	int chrdev_minor;
 	struct mutex kovaplus_lock;
-	struct kovaplus_info info;
 	struct kovaplus_profile_settings profile_settings[5];
 	struct kovaplus_profile_buttons profile_buttons[5];
 };
diff --git a/drivers/hid/hid-roccat-lua.c b/drivers/hid/hid-roccat-lua.c
new file mode 100644
index 0000000..5084fb4
--- /dev/null
+++ b/drivers/hid/hid-roccat-lua.c
@@ -0,0 +1,227 @@
+/*
+ * Roccat Lua driver for Linux
+ *
+ * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+/*
+ * Roccat Lua is a gamer mouse which cpi, button and light settings can be
+ * configured.
+ */
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/hid-roccat.h>
+#include "hid-ids.h"
+#include "hid-roccat-common.h"
+#include "hid-roccat-lua.h"
+
+static ssize_t lua_sysfs_read(struct file *fp, struct kobject *kobj,
+		char *buf, loff_t off, size_t count,
+		size_t real_size, uint command)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval;
+
+	if (off >= real_size)
+		return 0;
+
+	if (off != 0 || count != real_size)
+		return -EINVAL;
+
+	mutex_lock(&lua->lua_lock);
+	retval = roccat_common2_receive(usb_dev, command, buf, real_size);
+	mutex_unlock(&lua->lua_lock);
+
+	return retval ? retval : real_size;
+}
+
+static ssize_t lua_sysfs_write(struct file *fp, struct kobject *kobj,
+		void const *buf, loff_t off, size_t count,
+		size_t real_size, uint command)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval;
+
+	if (off != 0 || count != real_size)
+		return -EINVAL;
+
+	mutex_lock(&lua->lua_lock);
+	retval = roccat_common2_send(usb_dev, command, (void *)buf, real_size);
+	mutex_unlock(&lua->lua_lock);
+
+	return retval ? retval : real_size;
+}
+
+#define LUA_SYSFS_W(thingy, THINGY) \
+static ssize_t lua_sysfs_write_ ## thingy(struct file *fp, \
+		struct kobject *kobj, struct bin_attribute *attr, \
+		char *buf, loff_t off, size_t count) \
+{ \
+	return lua_sysfs_write(fp, kobj, buf, off, count, \
+			LUA_SIZE_ ## THINGY, LUA_COMMAND_ ## THINGY); \
+}
+
+#define LUA_SYSFS_R(thingy, THINGY) \
+static ssize_t lua_sysfs_read_ ## thingy(struct file *fp, \
+		struct kobject *kobj, struct bin_attribute *attr, \
+		char *buf, loff_t off, size_t count) \
+{ \
+	return lua_sysfs_read(fp, kobj, buf, off, count, \
+			LUA_SIZE_ ## THINGY, LUA_COMMAND_ ## THINGY); \
+}
+
+#define LUA_BIN_ATTRIBUTE_RW(thingy, THINGY) \
+LUA_SYSFS_W(thingy, THINGY) \
+LUA_SYSFS_R(thingy, THINGY) \
+static struct bin_attribute lua_ ## thingy ## _attr = { \
+	.attr = { .name = #thingy, .mode = 0660 }, \
+	.size = LUA_SIZE_ ## THINGY, \
+	.read = lua_sysfs_read_ ## thingy, \
+	.write = lua_sysfs_write_ ## thingy \
+};
+
+LUA_BIN_ATTRIBUTE_RW(control, CONTROL)
+
+static int lua_create_sysfs_attributes(struct usb_interface *intf)
+{
+	return sysfs_create_bin_file(&intf->dev.kobj, &lua_control_attr);
+}
+
+static void lua_remove_sysfs_attributes(struct usb_interface *intf)
+{
+	sysfs_remove_bin_file(&intf->dev.kobj, &lua_control_attr);
+}
+
+static int lua_init_lua_device_struct(struct usb_device *usb_dev,
+		struct lua_device *lua)
+{
+	mutex_init(&lua->lua_lock);
+
+	return 0;
+}
+
+static int lua_init_specials(struct hid_device *hdev)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct usb_device *usb_dev = interface_to_usbdev(intf);
+	struct lua_device *lua;
+	int retval;
+
+	lua = kzalloc(sizeof(*lua), GFP_KERNEL);
+	if (!lua) {
+		hid_err(hdev, "can't alloc device descriptor\n");
+		return -ENOMEM;
+	}
+	hid_set_drvdata(hdev, lua);
+
+	retval = lua_init_lua_device_struct(usb_dev, lua);
+	if (retval) {
+		hid_err(hdev, "couldn't init struct lua_device\n");
+		goto exit;
+	}
+
+	retval = lua_create_sysfs_attributes(intf);
+	if (retval) {
+		hid_err(hdev, "cannot create sysfs files\n");
+		goto exit;
+	}
+
+	return 0;
+exit:
+	kfree(lua);
+	return retval;
+}
+
+static void lua_remove_specials(struct hid_device *hdev)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct lua_device *lua;
+
+	lua_remove_sysfs_attributes(intf);
+
+	lua = hid_get_drvdata(hdev);
+	kfree(lua);
+}
+
+static int lua_probe(struct hid_device *hdev,
+		const struct hid_device_id *id)
+{
+	int retval;
+
+	retval = hid_parse(hdev);
+	if (retval) {
+		hid_err(hdev, "parse failed\n");
+		goto exit;
+	}
+
+	retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (retval) {
+		hid_err(hdev, "hw start failed\n");
+		goto exit;
+	}
+
+	retval = lua_init_specials(hdev);
+	if (retval) {
+		hid_err(hdev, "couldn't install mouse\n");
+		goto exit_stop;
+	}
+
+	return 0;
+
+exit_stop:
+	hid_hw_stop(hdev);
+exit:
+	return retval;
+}
+
+static void lua_remove(struct hid_device *hdev)
+{
+	lua_remove_specials(hdev);
+	hid_hw_stop(hdev);
+}
+
+static const struct hid_device_id lua_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(hid, lua_devices);
+
+static struct hid_driver lua_driver = {
+		.name = "lua",
+		.id_table = lua_devices,
+		.probe = lua_probe,
+		.remove = lua_remove
+};
+
+static int __init lua_init(void)
+{
+	return hid_register_driver(&lua_driver);
+}
+
+static void __exit lua_exit(void)
+{
+	hid_unregister_driver(&lua_driver);
+}
+
+module_init(lua_init);
+module_exit(lua_exit);
+
+MODULE_AUTHOR("Stefan Achatz");
+MODULE_DESCRIPTION("USB Roccat Lua driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-lua.h b/drivers/hid/hid-roccat-lua.h
new file mode 100644
index 0000000..547d77a
--- /dev/null
+++ b/drivers/hid/hid-roccat-lua.h
@@ -0,0 +1,29 @@
+#ifndef __HID_ROCCAT_LUA_H
+#define __HID_ROCCAT_LUA_H
+
+/*
+ * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/types.h>
+
+enum {
+	LUA_SIZE_CONTROL = 8,
+};
+
+enum lua_commands {
+	LUA_COMMAND_CONTROL = 3,
+};
+
+struct lua_device {
+	struct mutex lua_lock;
+};
+
+#endif
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c
index 1317c17..d4f1e3b 100644
--- a/drivers/hid/hid-roccat-pyra.c
+++ b/drivers/hid/hid-roccat-pyra.c
@@ -66,48 +66,14 @@ static int pyra_get_profile_settings(struct usb_device *usb_dev,
 	if (retval)
 		return retval;
 	return roccat_common2_receive(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS,
-			buf, sizeof(struct pyra_profile_settings));
-}
-
-static int pyra_get_profile_buttons(struct usb_device *usb_dev,
-		struct pyra_profile_buttons *buf, int number)
-{
-	int retval;
-	retval = pyra_send_control(usb_dev, number,
-			PYRA_CONTROL_REQUEST_PROFILE_BUTTONS);
-	if (retval)
-		return retval;
-	return roccat_common2_receive(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS,
-			buf, sizeof(struct pyra_profile_buttons));
+			buf, PYRA_SIZE_PROFILE_SETTINGS);
 }
 
 static int pyra_get_settings(struct usb_device *usb_dev,
 		struct pyra_settings *buf)
 {
 	return roccat_common2_receive(usb_dev, PYRA_COMMAND_SETTINGS,
-			buf, sizeof(struct pyra_settings));
-}
-
-static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf)
-{
-	return roccat_common2_receive(usb_dev, PYRA_COMMAND_INFO,
-			buf, sizeof(struct pyra_info));
-}
-
-static int pyra_set_profile_settings(struct usb_device *usb_dev,
-		struct pyra_profile_settings const *settings)
-{
-	return roccat_common2_send_with_status(usb_dev,
-			PYRA_COMMAND_PROFILE_SETTINGS, settings,
-			sizeof(struct pyra_profile_settings));
-}
-
-static int pyra_set_profile_buttons(struct usb_device *usb_dev,
-		struct pyra_profile_buttons const *buttons)
-{
-	return roccat_common2_send_with_status(usb_dev,
-			PYRA_COMMAND_PROFILE_BUTTONS, buttons,
-			sizeof(struct pyra_profile_buttons));
+			buf, PYRA_SIZE_SETTINGS);
 }
 
 static int pyra_set_settings(struct usb_device *usb_dev,
@@ -115,146 +81,144 @@ static int pyra_set_settings(struct usb_device *usb_dev,
 {
 	return roccat_common2_send_with_status(usb_dev,
 			PYRA_COMMAND_SETTINGS, settings,
-			sizeof(struct pyra_settings));
+			PYRA_SIZE_SETTINGS);
 }
 
-static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
+static ssize_t pyra_sysfs_read(struct file *fp, struct kobject *kobj,
+		char *buf, loff_t off, size_t count,
+		size_t real_size, uint command)
 {
 	struct device *dev =
 			container_of(kobj, struct device, kobj)->parent->parent;
 	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval;
 
-	if (off >= sizeof(struct pyra_profile_settings))
+	if (off >= real_size)
 		return 0;
 
-	if (off + count > sizeof(struct pyra_profile_settings))
-		count = sizeof(struct pyra_profile_settings) - off;
+	if (off != 0 || count != real_size)
+		return -EINVAL;
 
 	mutex_lock(&pyra->pyra_lock);
-	memcpy(buf, ((char const *)&pyra->profile_settings[*(uint *)(attr->private)]) + off,
-			count);
+	retval = roccat_common2_receive(usb_dev, command, buf, real_size);
 	mutex_unlock(&pyra->pyra_lock);
 
-	return count;
+	if (retval)
+		return retval;
+
+	return real_size;
 }
 
-static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
+static ssize_t pyra_sysfs_write(struct file *fp, struct kobject *kobj,
+		void const *buf, loff_t off, size_t count,
+		size_t real_size, uint command)
 {
 	struct device *dev =
 			container_of(kobj, struct device, kobj)->parent->parent;
 	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval;
 
-	if (off >= sizeof(struct pyra_profile_buttons))
-		return 0;
-
-	if (off + count > sizeof(struct pyra_profile_buttons))
-		count = sizeof(struct pyra_profile_buttons) - off;
+	if (off != 0 || count != real_size)
+		return -EINVAL;
 
 	mutex_lock(&pyra->pyra_lock);
-	memcpy(buf, ((char const *)&pyra->profile_buttons[*(uint *)(attr->private)]) + off,
-			count);
+	retval = roccat_common2_send_with_status(usb_dev, command, (void *)buf, real_size);
 	mutex_unlock(&pyra->pyra_lock);
 
-	return count;
+	if (retval)
+		return retval;
+
+	return real_size;
 }
 
-static ssize_t pyra_sysfs_write_profile_settings(struct file *fp,
-		struct kobject *kobj, struct bin_attribute *attr, char *buf,
-		loff_t off, size_t count)
-{
-	struct device *dev =
-			container_of(kobj, struct device, kobj)->parent->parent;
-	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
-	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
-	int retval = 0;
-	int difference;
-	int profile_number;
-	struct pyra_profile_settings *profile_settings;
+#define PYRA_SYSFS_W(thingy, THINGY) \
+static ssize_t pyra_sysfs_write_ ## thingy(struct file *fp, \
+		struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+		loff_t off, size_t count) \
+{ \
+	return pyra_sysfs_write(fp, kobj, buf, off, count, \
+			PYRA_SIZE_ ## THINGY, PYRA_COMMAND_ ## THINGY); \
+}
 
-	if (off != 0 || count != sizeof(struct pyra_profile_settings))
-		return -EINVAL;
+#define PYRA_SYSFS_R(thingy, THINGY) \
+static ssize_t pyra_sysfs_read_ ## thingy(struct file *fp, \
+		struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+		loff_t off, size_t count) \
+{ \
+	return pyra_sysfs_read(fp, kobj, buf, off, count, \
+			PYRA_SIZE_ ## THINGY, PYRA_COMMAND_ ## THINGY); \
+}
 
-	profile_number = ((struct pyra_profile_settings const *)buf)->number;
-	profile_settings = &pyra->profile_settings[profile_number];
+#define PYRA_SYSFS_RW(thingy, THINGY) \
+PYRA_SYSFS_W(thingy, THINGY) \
+PYRA_SYSFS_R(thingy, THINGY)
 
-	mutex_lock(&pyra->pyra_lock);
-	difference = memcmp(buf, profile_settings,
-			sizeof(struct pyra_profile_settings));
-	if (difference) {
-		retval = pyra_set_profile_settings(usb_dev,
-				(struct pyra_profile_settings const *)buf);
-		if (!retval)
-			memcpy(profile_settings, buf,
-					sizeof(struct pyra_profile_settings));
-	}
-	mutex_unlock(&pyra->pyra_lock);
+#define PYRA_BIN_ATTRIBUTE_RW(thingy, THINGY) \
+{ \
+	.attr = { .name = #thingy, .mode = 0660 }, \
+	.size = PYRA_SIZE_ ## THINGY, \
+	.read = pyra_sysfs_read_ ## thingy, \
+	.write = pyra_sysfs_write_ ## thingy \
+}
 
-	if (retval)
-		return retval;
+#define PYRA_BIN_ATTRIBUTE_R(thingy, THINGY) \
+{ \
+	.attr = { .name = #thingy, .mode = 0440 }, \
+	.size = PYRA_SIZE_ ## THINGY, \
+	.read = pyra_sysfs_read_ ## thingy, \
+}
 
-	return sizeof(struct pyra_profile_settings);
+#define PYRA_BIN_ATTRIBUTE_W(thingy, THINGY) \
+{ \
+	.attr = { .name = #thingy, .mode = 0220 }, \
+	.size = PYRA_SIZE_ ## THINGY, \
+	.write = pyra_sysfs_write_ ## thingy \
 }
 
-static ssize_t pyra_sysfs_write_profile_buttons(struct file *fp,
+PYRA_SYSFS_W(control, CONTROL)
+PYRA_SYSFS_RW(info, INFO)
+PYRA_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
+PYRA_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
+PYRA_SYSFS_R(settings, SETTINGS)
+
+static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
 		loff_t off, size_t count)
 {
 	struct device *dev =
 			container_of(kobj, struct device, kobj)->parent->parent;
-	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
 	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
-	int retval = 0;
-	int difference;
-	int profile_number;
-	struct pyra_profile_buttons *profile_buttons;
-
-	if (off != 0 || count != sizeof(struct pyra_profile_buttons))
-		return -EINVAL;
-
-	profile_number = ((struct pyra_profile_buttons const *)buf)->number;
-	profile_buttons = &pyra->profile_buttons[profile_number];
-
-	mutex_lock(&pyra->pyra_lock);
-	difference = memcmp(buf, profile_buttons,
-			sizeof(struct pyra_profile_buttons));
-	if (difference) {
-		retval = pyra_set_profile_buttons(usb_dev,
-				(struct pyra_profile_buttons const *)buf);
-		if (!retval)
-			memcpy(profile_buttons, buf,
-					sizeof(struct pyra_profile_buttons));
-	}
-	mutex_unlock(&pyra->pyra_lock);
+	ssize_t retval;
 
+	retval = pyra_send_control(usb_dev, *(uint *)(attr->private),
+			PYRA_CONTROL_REQUEST_PROFILE_SETTINGS);
 	if (retval)
 		return retval;
 
-	return sizeof(struct pyra_profile_buttons);
+	return pyra_sysfs_read(fp, kobj, buf, off, count,
+			PYRA_SIZE_PROFILE_SETTINGS,
+			PYRA_COMMAND_PROFILE_SETTINGS);
 }
 
-static ssize_t pyra_sysfs_read_settings(struct file *fp,
+static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp,
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
 		loff_t off, size_t count)
 {
 	struct device *dev =
 			container_of(kobj, struct device, kobj)->parent->parent;
-	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
-
-	if (off >= sizeof(struct pyra_settings))
-		return 0;
-
-	if (off + count > sizeof(struct pyra_settings))
-		count = sizeof(struct pyra_settings) - off;
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	ssize_t retval;
 
-	mutex_lock(&pyra->pyra_lock);
-	memcpy(buf, ((char const *)&pyra->settings) + off, count);
-	mutex_unlock(&pyra->pyra_lock);
+	retval = pyra_send_control(usb_dev, *(uint *)(attr->private),
+			PYRA_CONTROL_REQUEST_PROFILE_BUTTONS);
+	if (retval)
+		return retval;
 
-	return count;
+	return pyra_sysfs_read(fp, kobj, buf, off, count,
+			PYRA_SIZE_PROFILE_BUTTONS,
+			PYRA_COMMAND_PROFILE_BUTTONS);
 }
 
 static ssize_t pyra_sysfs_write_settings(struct file *fp,
@@ -266,35 +230,32 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp,
 	struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
 	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
 	int retval = 0;
-	int difference;
 	struct pyra_roccat_report roccat_report;
+	struct pyra_settings const *settings;
 
-	if (off != 0 || count != sizeof(struct pyra_settings))
+	if (off != 0 || count != PYRA_SIZE_SETTINGS)
 		return -EINVAL;
 
 	mutex_lock(&pyra->pyra_lock);
-	difference = memcmp(buf, &pyra->settings, sizeof(struct pyra_settings));
-	if (difference) {
-		retval = pyra_set_settings(usb_dev,
-				(struct pyra_settings const *)buf);
-		if (retval) {
-			mutex_unlock(&pyra->pyra_lock);
-			return retval;
-		}
-
-		memcpy(&pyra->settings, buf,
-				sizeof(struct pyra_settings));
 
-		profile_activated(pyra, pyra->settings.startup_profile);
+	settings = (struct pyra_settings const *)buf;
 
-		roccat_report.type = PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2;
-		roccat_report.value = pyra->settings.startup_profile + 1;
-		roccat_report.key = 0;
-		roccat_report_event(pyra->chrdev_minor,
-				(uint8_t const *)&roccat_report);
+	retval = pyra_set_settings(usb_dev, settings);
+	if (retval) {
+		mutex_unlock(&pyra->pyra_lock);
+		return retval;
 	}
+
+	profile_activated(pyra, settings->startup_profile);
+
+	roccat_report.type = PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2;
+	roccat_report.value = settings->startup_profile + 1;
+	roccat_report.key = 0;
+	roccat_report_event(pyra->chrdev_minor,
+			(uint8_t const *)&roccat_report);
+
 	mutex_unlock(&pyra->pyra_lock);
-	return sizeof(struct pyra_settings);
+	return PYRA_SIZE_SETTINGS;
 }
 
 
@@ -311,23 +272,34 @@ static ssize_t pyra_sysfs_show_actual_profile(struct device *dev,
 {
 	struct pyra_device *pyra =
 			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
-	return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_profile);
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	struct pyra_settings settings;
+
+	mutex_lock(&pyra->pyra_lock);
+	roccat_common2_receive(usb_dev, PYRA_COMMAND_SETTINGS,
+			&settings, PYRA_SIZE_SETTINGS);
+	mutex_unlock(&pyra->pyra_lock);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", settings.startup_profile);
 }
 
 static ssize_t pyra_sysfs_show_firmware_version(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct pyra_device *pyra =
-			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
-	return snprintf(buf, PAGE_SIZE, "%d\n", pyra->firmware_version);
-}
+	struct pyra_device *pyra;
+	struct usb_device *usb_dev;
+	struct pyra_info info;
 
-static ssize_t pyra_sysfs_show_startup_profile(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct pyra_device *pyra =
-			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
-	return snprintf(buf, PAGE_SIZE, "%d\n", pyra->settings.startup_profile);
+	dev = dev->parent->parent;
+	pyra = hid_get_drvdata(dev_get_drvdata(dev));
+	usb_dev = interface_to_usbdev(to_usb_interface(dev));
+
+	mutex_lock(&pyra->pyra_lock);
+	roccat_common2_receive(usb_dev, PYRA_COMMAND_INFO,
+			&info, PYRA_SIZE_INFO);
+	mutex_unlock(&pyra->pyra_lock);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
 }
 
 static struct device_attribute pyra_attributes[] = {
@@ -336,105 +308,88 @@ static struct device_attribute pyra_attributes[] = {
 	__ATTR(firmware_version, 0440,
 			pyra_sysfs_show_firmware_version, NULL),
 	__ATTR(startup_profile, 0440,
-			pyra_sysfs_show_startup_profile, NULL),
+			pyra_sysfs_show_actual_profile, NULL),
 	__ATTR_NULL
 };
 
 static struct bin_attribute pyra_bin_attributes[] = {
-	{
-		.attr = { .name = "profile_settings", .mode = 0220 },
-		.size = sizeof(struct pyra_profile_settings),
-		.write = pyra_sysfs_write_profile_settings
-	},
+	PYRA_BIN_ATTRIBUTE_W(control, CONTROL),
+	PYRA_BIN_ATTRIBUTE_RW(info, INFO),
+	PYRA_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
+	PYRA_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
+	PYRA_BIN_ATTRIBUTE_RW(settings, SETTINGS),
 	{
 		.attr = { .name = "profile1_settings", .mode = 0440 },
-		.size = sizeof(struct pyra_profile_settings),
+		.size = PYRA_SIZE_PROFILE_SETTINGS,
 		.read = pyra_sysfs_read_profilex_settings,
 		.private = &profile_numbers[0]
 	},
 	{
 		.attr = { .name = "profile2_settings", .mode = 0440 },
-		.size = sizeof(struct pyra_profile_settings),
+		.size = PYRA_SIZE_PROFILE_SETTINGS,
 		.read = pyra_sysfs_read_profilex_settings,
 		.private = &profile_numbers[1]
 	},
 	{
 		.attr = { .name = "profile3_settings", .mode = 0440 },
-		.size = sizeof(struct pyra_profile_settings),
+		.size = PYRA_SIZE_PROFILE_SETTINGS,
 		.read = pyra_sysfs_read_profilex_settings,
 		.private = &profile_numbers[2]
 	},
 	{
 		.attr = { .name = "profile4_settings", .mode = 0440 },
-		.size = sizeof(struct pyra_profile_settings),
+		.size = PYRA_SIZE_PROFILE_SETTINGS,
 		.read = pyra_sysfs_read_profilex_settings,
 		.private = &profile_numbers[3]
 	},
 	{
 		.attr = { .name = "profile5_settings", .mode = 0440 },
-		.size = sizeof(struct pyra_profile_settings),
+		.size = PYRA_SIZE_PROFILE_SETTINGS,
 		.read = pyra_sysfs_read_profilex_settings,
 		.private = &profile_numbers[4]
 	},
 	{
-		.attr = { .name = "profile_buttons", .mode = 0220 },
-		.size = sizeof(struct pyra_profile_buttons),
-		.write = pyra_sysfs_write_profile_buttons
-	},
-	{
 		.attr = { .name = "profile1_buttons", .mode = 0440 },
-		.size = sizeof(struct pyra_profile_buttons),
+		.size = PYRA_SIZE_PROFILE_BUTTONS,
 		.read = pyra_sysfs_read_profilex_buttons,
 		.private = &profile_numbers[0]
 	},
 	{
 		.attr = { .name = "profile2_buttons", .mode = 0440 },
-		.size = sizeof(struct pyra_profile_buttons),
+		.size = PYRA_SIZE_PROFILE_BUTTONS,
 		.read = pyra_sysfs_read_profilex_buttons,
 		.private = &profile_numbers[1]
 	},
 	{
 		.attr = { .name = "profile3_buttons", .mode = 0440 },
-		.size = sizeof(struct pyra_profile_buttons),
+		.size = PYRA_SIZE_PROFILE_BUTTONS,
 		.read = pyra_sysfs_read_profilex_buttons,
 		.private = &profile_numbers[2]
 	},
 	{
 		.attr = { .name = "profile4_buttons", .mode = 0440 },
-		.size = sizeof(struct pyra_profile_buttons),
+		.size = PYRA_SIZE_PROFILE_BUTTONS,
 		.read = pyra_sysfs_read_profilex_buttons,
 		.private = &profile_numbers[3]
 	},
 	{
 		.attr = { .name = "profile5_buttons", .mode = 0440 },
-		.size = sizeof(struct pyra_profile_buttons),
+		.size = PYRA_SIZE_PROFILE_BUTTONS,
 		.read = pyra_sysfs_read_profilex_buttons,
 		.private = &profile_numbers[4]
 	},
-	{
-		.attr = { .name = "settings", .mode = 0660 },
-		.size = sizeof(struct pyra_settings),
-		.read = pyra_sysfs_read_settings,
-		.write = pyra_sysfs_write_settings
-	},
 	__ATTR_NULL
 };
 
 static int pyra_init_pyra_device_struct(struct usb_device *usb_dev,
 		struct pyra_device *pyra)
 {
-	struct pyra_info info;
+	struct pyra_settings settings;
 	int retval, i;
 
 	mutex_init(&pyra->pyra_lock);
 
-	retval = pyra_get_info(usb_dev, &info);
-	if (retval)
-		return retval;
-
-	pyra->firmware_version = info.firmware_version;
-
-	retval = pyra_get_settings(usb_dev, &pyra->settings);
+	retval = pyra_get_settings(usb_dev, &settings);
 	if (retval)
 		return retval;
 
@@ -443,14 +398,9 @@ static int pyra_init_pyra_device_struct(struct usb_device *usb_dev,
 				&pyra->profile_settings[i], i);
 		if (retval)
 			return retval;
-
-		retval = pyra_get_profile_buttons(usb_dev,
-				&pyra->profile_buttons[i], i);
-		if (retval)
-			return retval;
 	}
 
-	profile_activated(pyra, pyra->settings.startup_profile);
+	profile_activated(pyra, settings.startup_profile);
 
 	return 0;
 }
diff --git a/drivers/hid/hid-roccat-pyra.h b/drivers/hid/hid-roccat-pyra.h
index eada783..beedcf0 100644
--- a/drivers/hid/hid-roccat-pyra.h
+++ b/drivers/hid/hid-roccat-pyra.h
@@ -14,11 +14,13 @@
 
 #include <linux/types.h>
 
-struct pyra_b {
-	uint8_t command; /* PYRA_COMMAND_B */
-	uint8_t size; /* always 3 */
-	uint8_t unknown; /* 1 */
-} __attribute__ ((__packed__));
+enum {
+	PYRA_SIZE_CONTROL = 0x03,
+	PYRA_SIZE_INFO = 0x06,
+	PYRA_SIZE_PROFILE_SETTINGS = 0x0d,
+	PYRA_SIZE_PROFILE_BUTTONS = 0x13,
+	PYRA_SIZE_SETTINGS = 0x03,
+};
 
 enum pyra_control_requests {
 	PYRA_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10,
@@ -46,14 +48,6 @@ struct pyra_profile_settings {
 	uint16_t checksum; /* byte sum */
 } __attribute__ ((__packed__));
 
-struct pyra_profile_buttons {
-	uint8_t command; /* PYRA_COMMAND_PROFILE_BUTTONS */
-	uint8_t size; /* always 0x13 */
-	uint8_t number; /* Range 0-4 */
-	uint8_t buttons[14];
-	uint16_t checksum; /* byte sum */
-} __attribute__ ((__packed__));
-
 struct pyra_info {
 	uint8_t command; /* PYRA_COMMAND_INFO */
 	uint8_t size; /* always 6 */
@@ -64,6 +58,7 @@ struct pyra_info {
 } __attribute__ ((__packed__));
 
 enum pyra_commands {
+	PYRA_COMMAND_CONTROL = 0x4,
 	PYRA_COMMAND_SETTINGS = 0x5,
 	PYRA_COMMAND_PROFILE_SETTINGS = 0x6,
 	PYRA_COMMAND_PROFILE_BUTTONS = 0x7,
@@ -148,13 +143,10 @@ struct pyra_roccat_report {
 struct pyra_device {
 	int actual_profile;
 	int actual_cpi;
-	int firmware_version;
 	int roccat_claimed;
 	int chrdev_minor;
 	struct mutex pyra_lock;
-	struct pyra_settings settings;
 	struct pyra_profile_settings profile_settings[5];
-	struct pyra_profile_buttons profile_buttons[5];
 };
 
 #endif
diff --git a/drivers/hid/hid-roccat-savu.c b/drivers/hid/hid-roccat-savu.c
index 014afba..31747a2 100644
--- a/drivers/hid/hid-roccat-savu.c
+++ b/drivers/hid/hid-roccat-savu.c
@@ -120,7 +120,7 @@ SAVU_SYSFS_RW(profile, PROFILE)
 SAVU_SYSFS_RW(general, GENERAL)
 SAVU_SYSFS_RW(buttons, BUTTONS)
 SAVU_SYSFS_RW(macro, MACRO)
-SAVU_SYSFS_R(info, INFO)
+SAVU_SYSFS_RW(info, INFO)
 SAVU_SYSFS_RW(sensor, SENSOR)
 
 static struct bin_attribute savu_bin_attributes[] = {
@@ -129,7 +129,7 @@ static struct bin_attribute savu_bin_attributes[] = {
 	SAVU_BIN_ATTRIBUTE_RW(general, GENERAL),
 	SAVU_BIN_ATTRIBUTE_RW(buttons, BUTTONS),
 	SAVU_BIN_ATTRIBUTE_RW(macro, MACRO),
-	SAVU_BIN_ATTRIBUTE_R(info, INFO),
+	SAVU_BIN_ATTRIBUTE_RW(info, INFO),
 	SAVU_BIN_ATTRIBUTE_RW(sensor, SENSOR),
 	__ATTR_NULL
 };
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index d9d73e9..4ff2497 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -437,9 +437,6 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
 	ptr = raw_data;
 	ptr++; /*Skip report id*/
 
-	if (!report)
-		goto err_report;
-
 	spin_lock_irqsave(&pdata->lock, flags);
 
 	for (i = 0; i < report->maxfield; ++i) {
@@ -485,7 +482,6 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
 				callback->pdev);
 	spin_unlock_irqrestore(&pdata->lock, flags);
 
-err_report:
 	return 1;
 }
 
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 7c47fc3..413a731 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -57,10 +57,6 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count,
 			set_current_state(TASK_INTERRUPTIBLE);
 
 			while (list->head == list->tail) {
-				if (file->f_flags & O_NONBLOCK) {
-					ret = -EAGAIN;
-					break;
-				}
 				if (signal_pending(current)) {
 					ret = -ERESTARTSYS;
 					break;
@@ -69,6 +65,10 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count,
 					ret = -EIO;
 					break;
 				}
+				if (file->f_flags & O_NONBLOCK) {
+					ret = -EAGAIN;
+					break;
+				}
 
 				/* allow O_NONBLOCK to work well from other threads */
 				mutex_unlock(&list->read_mutex);
@@ -295,6 +295,13 @@ out:
 
 }
 
+static int hidraw_fasync(int fd, struct file *file, int on)
+{
+	struct hidraw_list *list = file->private_data;
+
+	return fasync_helper(fd, file, on, &list->fasync);
+}
+
 static int hidraw_release(struct inode * inode, struct file * file)
 {
 	unsigned int minor = iminor(inode);
@@ -438,6 +445,7 @@ static const struct file_operations hidraw_ops = {
 	.open =         hidraw_open,
 	.release =      hidraw_release,
 	.unlocked_ioctl = hidraw_ioctl,
+	.fasync =	hidraw_fasync,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl   = hidraw_ioctl,
 #endif
diff --git a/drivers/hid/i2c-hid/Kconfig b/drivers/hid/i2c-hid/Kconfig
new file mode 100644
index 0000000..5b7d4d8
--- /dev/null
+++ b/drivers/hid/i2c-hid/Kconfig
@@ -0,0 +1,21 @@
+menu "I2C HID support"
+	depends on I2C
+
+config I2C_HID
+	tristate "HID over I2C transport layer"
+	default n
+	depends on I2C && INPUT
+	select HID
+	---help---
+	  Say Y here if you want to use the HID over i2c protocol
+	  implementation.
+
+	  If unsure, say N.
+
+	  This support is also available as a module.  If so, the module
+	  will be called i2c-hid.
+
+comment "Input core support is needed for HID over I2C input layer"
+	depends on I2C_HID && INPUT=n
+
+endmenu
diff --git a/drivers/hid/i2c-hid/Makefile b/drivers/hid/i2c-hid/Makefile
new file mode 100644
index 0000000..832d8f9
--- /dev/null
+++ b/drivers/hid/i2c-hid/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the I2C input drivers
+#
+
+obj-$(CONFIG_I2C_HID)				+= i2c-hid.o
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
new file mode 100644
index 0000000..67ab5b7
--- /dev/null
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -0,0 +1,975 @@
+/*
+ * HID over I2C protocol implementation
+ *
+ * Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+ * Copyright (c) 2012 Ecole Nationale de l'Aviation Civile, France
+ * Copyright (c) 2012 Red Hat, Inc
+ *
+ * This code is partly based on "USB HID support for Linux":
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2007-2008 Oliver Neukum
+ *  Copyright (c) 2006-2010 Jiri Kosina
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/hid.h>
+
+#include <linux/i2c/i2c-hid.h>
+
+/* flags */
+#define I2C_HID_STARTED		(1 << 0)
+#define I2C_HID_RESET_PENDING	(1 << 1)
+#define I2C_HID_READ_PENDING	(1 << 2)
+
+#define I2C_HID_PWR_ON		0x00
+#define I2C_HID_PWR_SLEEP	0x01
+
+/* debug option */
+static bool debug = false;
+module_param(debug, bool, 0444);
+MODULE_PARM_DESC(debug, "print a lot of debug information");
+
+#define i2c_hid_dbg(ihid, fmt, arg...)	\
+	if (debug)			\
+		dev_printk(KERN_DEBUG, &(ihid)->client->dev, fmt, ##arg)
+
+struct i2c_hid_desc {
+	__le16 wHIDDescLength;
+	__le16 bcdVersion;
+	__le16 wReportDescLength;
+	__le16 wReportDescRegister;
+	__le16 wInputRegister;
+	__le16 wMaxInputLength;
+	__le16 wOutputRegister;
+	__le16 wMaxOutputLength;
+	__le16 wCommandRegister;
+	__le16 wDataRegister;
+	__le16 wVendorID;
+	__le16 wProductID;
+	__le16 wVersionID;
+} __packed;
+
+struct i2c_hid_cmd {
+	unsigned int registerIndex;
+	__u8 opcode;
+	unsigned int length;
+	bool wait;
+};
+
+union command {
+	u8 data[0];
+	struct cmd {
+		__le16 reg;
+		__u8 reportTypeID;
+		__u8 opcode;
+	} __packed c;
+};
+
+#define I2C_HID_CMD(opcode_) \
+	.opcode = opcode_, .length = 4, \
+	.registerIndex = offsetof(struct i2c_hid_desc, wCommandRegister)
+
+/* fetch HID descriptor */
+static const struct i2c_hid_cmd hid_descr_cmd = { .length = 2 };
+/* fetch report descriptors */
+static const struct i2c_hid_cmd hid_report_descr_cmd = {
+		.registerIndex = offsetof(struct i2c_hid_desc,
+			wReportDescRegister),
+		.opcode = 0x00,
+		.length = 2 };
+/* commands */
+static const struct i2c_hid_cmd hid_reset_cmd =		{ I2C_HID_CMD(0x01),
+							  .wait = true };
+static const struct i2c_hid_cmd hid_get_report_cmd =	{ I2C_HID_CMD(0x02) };
+static const struct i2c_hid_cmd hid_set_report_cmd =	{ I2C_HID_CMD(0x03) };
+static const struct i2c_hid_cmd hid_get_idle_cmd =	{ I2C_HID_CMD(0x04) };
+static const struct i2c_hid_cmd hid_set_idle_cmd =	{ I2C_HID_CMD(0x05) };
+static const struct i2c_hid_cmd hid_get_protocol_cmd =	{ I2C_HID_CMD(0x06) };
+static const struct i2c_hid_cmd hid_set_protocol_cmd =	{ I2C_HID_CMD(0x07) };
+static const struct i2c_hid_cmd hid_set_power_cmd =	{ I2C_HID_CMD(0x08) };
+/* read/write data register */
+static const struct i2c_hid_cmd hid_data_cmd = {
+		.registerIndex = offsetof(struct i2c_hid_desc, wDataRegister),
+		.opcode = 0x00,
+		.length = 2 };
+/* write output reports */
+static const struct i2c_hid_cmd hid_out_cmd = {
+		.registerIndex = offsetof(struct i2c_hid_desc,
+			wOutputRegister),
+		.opcode = 0x00,
+		.length = 2 };
+
+/* The main device structure */
+struct i2c_hid {
+	struct i2c_client	*client;	/* i2c client */
+	struct hid_device	*hid;	/* pointer to corresponding HID dev */
+	union {
+		__u8 hdesc_buffer[sizeof(struct i2c_hid_desc)];
+		struct i2c_hid_desc hdesc;	/* the HID Descriptor */
+	};
+	__le16			wHIDDescRegister; /* location of the i2c
+						   * register of the HID
+						   * descriptor. */
+	unsigned int		bufsize;	/* i2c buffer size */
+	char			*inbuf;		/* Input buffer */
+	char			*cmdbuf;	/* Command buffer */
+	char			*argsbuf;	/* Command arguments buffer */
+
+	unsigned long		flags;		/* device flags */
+
+	int			irq;		/* the interrupt line irq */
+
+	wait_queue_head_t	wait;		/* For waiting the interrupt */
+};
+
+static int __i2c_hid_command(struct i2c_client *client,
+		const struct i2c_hid_cmd *command, u8 reportID,
+		u8 reportType, u8 *args, int args_len,
+		unsigned char *buf_recv, int data_len)
+{
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	union command *cmd = (union command *)ihid->cmdbuf;
+	int ret;
+	struct i2c_msg msg[2];
+	int msg_num = 1;
+
+	int length = command->length;
+	bool wait = command->wait;
+	unsigned int registerIndex = command->registerIndex;
+
+	/* special case for hid_descr_cmd */
+	if (command == &hid_descr_cmd) {
+		cmd->c.reg = ihid->wHIDDescRegister;
+	} else {
+		cmd->data[0] = ihid->hdesc_buffer[registerIndex];
+		cmd->data[1] = ihid->hdesc_buffer[registerIndex + 1];
+	}
+
+	if (length > 2) {
+		cmd->c.opcode = command->opcode;
+		cmd->c.reportTypeID = reportID | reportType << 4;
+	}
+
+	memcpy(cmd->data + length, args, args_len);
+	length += args_len;
+
+	i2c_hid_dbg(ihid, "%s: cmd=%*ph\n", __func__, length, cmd->data);
+
+	msg[0].addr = client->addr;
+	msg[0].flags = client->flags & I2C_M_TEN;
+	msg[0].len = length;
+	msg[0].buf = cmd->data;
+	if (data_len > 0) {
+		msg[1].addr = client->addr;
+		msg[1].flags = client->flags & I2C_M_TEN;
+		msg[1].flags |= I2C_M_RD;
+		msg[1].len = data_len;
+		msg[1].buf = buf_recv;
+		msg_num = 2;
+		set_bit(I2C_HID_READ_PENDING, &ihid->flags);
+	}
+
+	if (wait)
+		set_bit(I2C_HID_RESET_PENDING, &ihid->flags);
+
+	ret = i2c_transfer(client->adapter, msg, msg_num);
+
+	if (data_len > 0)
+		clear_bit(I2C_HID_READ_PENDING, &ihid->flags);
+
+	if (ret != msg_num)
+		return ret < 0 ? ret : -EIO;
+
+	ret = 0;
+
+	if (wait) {
+		i2c_hid_dbg(ihid, "%s: waiting...\n", __func__);
+		if (!wait_event_timeout(ihid->wait,
+				!test_bit(I2C_HID_RESET_PENDING, &ihid->flags),
+				msecs_to_jiffies(5000)))
+			ret = -ENODATA;
+		i2c_hid_dbg(ihid, "%s: finished.\n", __func__);
+	}
+
+	return ret;
+}
+
+static int i2c_hid_command(struct i2c_client *client,
+		const struct i2c_hid_cmd *command,
+		unsigned char *buf_recv, int data_len)
+{
+	return __i2c_hid_command(client, command, 0, 0, NULL, 0,
+				buf_recv, data_len);
+}
+
+static int i2c_hid_get_report(struct i2c_client *client, u8 reportType,
+		u8 reportID, unsigned char *buf_recv, int data_len)
+{
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	u8 args[3];
+	int ret;
+	int args_len = 0;
+	u16 readRegister = le16_to_cpu(ihid->hdesc.wDataRegister);
+
+	i2c_hid_dbg(ihid, "%s\n", __func__);
+
+	if (reportID >= 0x0F) {
+		args[args_len++] = reportID;
+		reportID = 0x0F;
+	}
+
+	args[args_len++] = readRegister & 0xFF;
+	args[args_len++] = readRegister >> 8;
+
+	ret = __i2c_hid_command(client, &hid_get_report_cmd, reportID,
+		reportType, args, args_len, buf_recv, data_len);
+	if (ret) {
+		dev_err(&client->dev,
+			"failed to retrieve report from device.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int i2c_hid_set_report(struct i2c_client *client, u8 reportType,
+		u8 reportID, unsigned char *buf, size_t data_len)
+{
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	u8 *args = ihid->argsbuf;
+	int ret;
+	u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister);
+
+	/* hidraw already checked that data_len < HID_MAX_BUFFER_SIZE */
+	u16 size =	2			/* size */ +
+			(reportID ? 1 : 0)	/* reportID */ +
+			data_len		/* buf */;
+	int args_len =	(reportID >= 0x0F ? 1 : 0) /* optional third byte */ +
+			2			/* dataRegister */ +
+			size			/* args */;
+	int index = 0;
+
+	i2c_hid_dbg(ihid, "%s\n", __func__);
+
+	if (reportID >= 0x0F) {
+		args[index++] = reportID;
+		reportID = 0x0F;
+	}
+
+	args[index++] = dataRegister & 0xFF;
+	args[index++] = dataRegister >> 8;
+
+	args[index++] = size & 0xFF;
+	args[index++] = size >> 8;
+
+	if (reportID)
+		args[index++] = reportID;
+
+	memcpy(&args[index], buf, data_len);
+
+	ret = __i2c_hid_command(client, &hid_set_report_cmd, reportID,
+		reportType, args, args_len, NULL, 0);
+	if (ret) {
+		dev_err(&client->dev, "failed to set a report to device.\n");
+		return -EINVAL;
+	}
+
+	return data_len;
+}
+
+static int i2c_hid_set_power(struct i2c_client *client, int power_state)
+{
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	int ret;
+
+	i2c_hid_dbg(ihid, "%s\n", __func__);
+
+	ret = __i2c_hid_command(client, &hid_set_power_cmd, power_state,
+		0, NULL, 0, NULL, 0);
+	if (ret)
+		dev_err(&client->dev, "failed to change power setting.\n");
+
+	return ret;
+}
+
+static int i2c_hid_hwreset(struct i2c_client *client)
+{
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	int ret;
+
+	i2c_hid_dbg(ihid, "%s\n", __func__);
+
+	ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
+	if (ret)
+		return ret;
+
+	i2c_hid_dbg(ihid, "resetting...\n");
+
+	ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
+	if (ret) {
+		dev_err(&client->dev, "failed to reset device.\n");
+		i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int i2c_hid_get_input(struct i2c_hid *ihid)
+{
+	int ret, ret_size;
+	int size = le16_to_cpu(ihid->hdesc.wMaxInputLength);
+
+	ret = i2c_master_recv(ihid->client, ihid->inbuf, size);
+	if (ret != size) {
+		if (ret < 0)
+			return ret;
+
+		dev_err(&ihid->client->dev, "%s: got %d data instead of %d\n",
+			__func__, ret, size);
+		return ret;
+	}
+
+	ret_size = ihid->inbuf[0] | ihid->inbuf[1] << 8;
+
+	if (!ret_size) {
+		/* host or device initiated RESET completed */
+		if (test_and_clear_bit(I2C_HID_RESET_PENDING, &ihid->flags))
+			wake_up(&ihid->wait);
+		return 0;
+	}
+
+	if (ret_size > size) {
+		dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
+			__func__, size, ret_size);
+		return -EIO;
+	}
+
+	i2c_hid_dbg(ihid, "input: %*ph\n", ret_size, ihid->inbuf);
+
+	if (test_bit(I2C_HID_STARTED, &ihid->flags))
+		hid_input_report(ihid->hid, HID_INPUT_REPORT, ihid->inbuf + 2,
+				ret_size - 2, 1);
+
+	return 0;
+}
+
+static irqreturn_t i2c_hid_irq(int irq, void *dev_id)
+{
+	struct i2c_hid *ihid = dev_id;
+
+	if (test_bit(I2C_HID_READ_PENDING, &ihid->flags))
+		return IRQ_HANDLED;
+
+	i2c_hid_get_input(ihid);
+
+	return IRQ_HANDLED;
+}
+
+static int i2c_hid_get_report_length(struct hid_report *report)
+{
+	return ((report->size - 1) >> 3) + 1 +
+		report->device->report_enum[report->type].numbered + 2;
+}
+
+static void i2c_hid_init_report(struct hid_report *report, u8 *buffer,
+	size_t bufsize)
+{
+	struct hid_device *hid = report->device;
+	struct i2c_client *client = hid->driver_data;
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	unsigned int size, ret_size;
+
+	size = i2c_hid_get_report_length(report);
+	i2c_hid_get_report(client,
+			report->type == HID_FEATURE_REPORT ? 0x03 : 0x01,
+			report->id, buffer, size);
+
+	i2c_hid_dbg(ihid, "report (len=%d): %*ph\n", size, size, ihid->inbuf);
+
+	ret_size = buffer[0] | (buffer[1] << 8);
+
+	if (ret_size != size) {
+		dev_err(&client->dev, "error in %s size:%d / ret_size:%d\n",
+			__func__, size, ret_size);
+		return;
+	}
+
+	/* hid->driver_lock is held as we are in probe function,
+	 * we just need to setup the input fields, so using
+	 * hid_report_raw_event is safe. */
+	hid_report_raw_event(hid, report->type, buffer + 2, size - 2, 1);
+}
+
+/*
+ * Initialize all reports
+ */
+static void i2c_hid_init_reports(struct hid_device *hid)
+{
+	struct hid_report *report;
+	struct i2c_client *client = hid->driver_data;
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	u8 *inbuf = kzalloc(ihid->bufsize, GFP_KERNEL);
+
+	if (!inbuf)
+		return;
+
+	list_for_each_entry(report,
+		&hid->report_enum[HID_INPUT_REPORT].report_list, list)
+		i2c_hid_init_report(report, inbuf, ihid->bufsize);
+
+	list_for_each_entry(report,
+		&hid->report_enum[HID_FEATURE_REPORT].report_list, list)
+		i2c_hid_init_report(report, inbuf, ihid->bufsize);
+
+	kfree(inbuf);
+}
+
+/*
+ * Traverse the supplied list of reports and find the longest
+ */
+static void i2c_hid_find_max_report(struct hid_device *hid, unsigned int type,
+		unsigned int *max)
+{
+	struct hid_report *report;
+	unsigned int size;
+
+	/* We should not rely on wMaxInputLength, as some devices may set it to
+	 * a wrong length. */
+	list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
+		size = i2c_hid_get_report_length(report);
+		if (*max < size)
+			*max = size;
+	}
+}
+
+static int i2c_hid_alloc_buffers(struct i2c_hid *ihid)
+{
+	/* the worst case is computed from the set_report command with a
+	 * reportID > 15 and the maximum report length */
+	int args_len = sizeof(__u8) + /* optional ReportID byte */
+		       sizeof(__u16) + /* data register */
+		       sizeof(__u16) + /* size of the report */
+		       ihid->bufsize; /* report */
+
+	ihid->inbuf = kzalloc(ihid->bufsize, GFP_KERNEL);
+
+	if (!ihid->inbuf)
+		return -ENOMEM;
+
+	ihid->argsbuf = kzalloc(args_len, GFP_KERNEL);
+
+	if (!ihid->argsbuf) {
+		kfree(ihid->inbuf);
+		return -ENOMEM;
+	}
+
+	ihid->cmdbuf = kzalloc(sizeof(union command) + args_len, GFP_KERNEL);
+
+	if (!ihid->cmdbuf) {
+		kfree(ihid->inbuf);
+		kfree(ihid->argsbuf);
+		ihid->inbuf = NULL;
+		ihid->argsbuf = NULL;
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void i2c_hid_free_buffers(struct i2c_hid *ihid)
+{
+	kfree(ihid->inbuf);
+	kfree(ihid->argsbuf);
+	kfree(ihid->cmdbuf);
+	ihid->inbuf = NULL;
+	ihid->cmdbuf = NULL;
+	ihid->argsbuf = NULL;
+}
+
+static int i2c_hid_get_raw_report(struct hid_device *hid,
+		unsigned char report_number, __u8 *buf, size_t count,
+		unsigned char report_type)
+{
+	struct i2c_client *client = hid->driver_data;
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	int ret;
+
+	if (report_type == HID_OUTPUT_REPORT)
+		return -EINVAL;
+
+	if (count > ihid->bufsize)
+		count = ihid->bufsize;
+
+	ret = i2c_hid_get_report(client,
+			report_type == HID_FEATURE_REPORT ? 0x03 : 0x01,
+			report_number, ihid->inbuf, count);
+
+	if (ret < 0)
+		return ret;
+
+	count = ihid->inbuf[0] | (ihid->inbuf[1] << 8);
+
+	memcpy(buf, ihid->inbuf + 2, count);
+
+	return count;
+}
+
+static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
+		size_t count, unsigned char report_type)
+{
+	struct i2c_client *client = hid->driver_data;
+	int report_id = buf[0];
+
+	if (report_type == HID_INPUT_REPORT)
+		return -EINVAL;
+
+	return i2c_hid_set_report(client,
+				report_type == HID_FEATURE_REPORT ? 0x03 : 0x02,
+				report_id, buf, count);
+}
+
+static int i2c_hid_parse(struct hid_device *hid)
+{
+	struct i2c_client *client = hid->driver_data;
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	struct i2c_hid_desc *hdesc = &ihid->hdesc;
+	unsigned int rsize;
+	char *rdesc;
+	int ret;
+	int tries = 3;
+
+	i2c_hid_dbg(ihid, "entering %s\n", __func__);
+
+	rsize = le16_to_cpu(hdesc->wReportDescLength);
+	if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
+		dbg_hid("weird size of report descriptor (%u)\n", rsize);
+		return -EINVAL;
+	}
+
+	do {
+		ret = i2c_hid_hwreset(client);
+		if (ret)
+			msleep(1000);
+	} while (tries-- > 0 && ret);
+
+	if (ret)
+		return ret;
+
+	rdesc = kzalloc(rsize, GFP_KERNEL);
+
+	if (!rdesc) {
+		dbg_hid("couldn't allocate rdesc memory\n");
+		return -ENOMEM;
+	}
+
+	i2c_hid_dbg(ihid, "asking HID report descriptor\n");
+
+	ret = i2c_hid_command(client, &hid_report_descr_cmd, rdesc, rsize);
+	if (ret) {
+		hid_err(hid, "reading report descriptor failed\n");
+		kfree(rdesc);
+		return -EIO;
+	}
+
+	i2c_hid_dbg(ihid, "Report Descriptor: %*ph\n", rsize, rdesc);
+
+	ret = hid_parse_report(hid, rdesc, rsize);
+	kfree(rdesc);
+	if (ret) {
+		dbg_hid("parsing report descriptor failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int i2c_hid_start(struct hid_device *hid)
+{
+	struct i2c_client *client = hid->driver_data;
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	int ret;
+	int old_bufsize = ihid->bufsize;
+
+	ihid->bufsize = HID_MIN_BUFFER_SIZE;
+	i2c_hid_find_max_report(hid, HID_INPUT_REPORT, &ihid->bufsize);
+	i2c_hid_find_max_report(hid, HID_OUTPUT_REPORT, &ihid->bufsize);
+	i2c_hid_find_max_report(hid, HID_FEATURE_REPORT, &ihid->bufsize);
+
+	if (ihid->bufsize > old_bufsize || !ihid->inbuf || !ihid->cmdbuf) {
+		i2c_hid_free_buffers(ihid);
+
+		ret = i2c_hid_alloc_buffers(ihid);
+
+		if (ret) {
+			ihid->bufsize = old_bufsize;
+			return ret;
+		}
+	}
+
+	if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS))
+		i2c_hid_init_reports(hid);
+
+	return 0;
+}
+
+static void i2c_hid_stop(struct hid_device *hid)
+{
+	struct i2c_client *client = hid->driver_data;
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+
+	hid->claimed = 0;
+
+	i2c_hid_free_buffers(ihid);
+}
+
+static int i2c_hid_open(struct hid_device *hid)
+{
+	struct i2c_client *client = hid->driver_data;
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	int ret;
+
+	if (!hid->open++) {
+		ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
+		if (ret) {
+			hid->open--;
+			return -EIO;
+		}
+		set_bit(I2C_HID_STARTED, &ihid->flags);
+	}
+	return 0;
+}
+
+static void i2c_hid_close(struct hid_device *hid)
+{
+	struct i2c_client *client = hid->driver_data;
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+
+	/* protecting hid->open to make sure we don't restart
+	 * data acquistion due to a resumption we no longer
+	 * care about
+	 */
+	if (!--hid->open) {
+		clear_bit(I2C_HID_STARTED, &ihid->flags);
+
+		/* Save some power */
+		i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+	}
+}
+
+static int i2c_hid_power(struct hid_device *hid, int lvl)
+{
+	struct i2c_client *client = hid->driver_data;
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	int ret = 0;
+
+	i2c_hid_dbg(ihid, "%s lvl:%d\n", __func__, lvl);
+
+	switch (lvl) {
+	case PM_HINT_FULLON:
+		ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
+		break;
+	case PM_HINT_NORMAL:
+		ret = i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+		break;
+	}
+	return ret;
+}
+
+static int i2c_hid_hidinput_input_event(struct input_dev *dev,
+		unsigned int type, unsigned int code, int value)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct hid_field *field;
+	int offset;
+
+	if (type == EV_FF)
+		return input_ff_event(dev, type, code, value);
+
+	if (type != EV_LED)
+		return -1;
+
+	offset = hidinput_find_field(hid, type, code, &field);
+
+	if (offset == -1) {
+		hid_warn(dev, "event field not found\n");
+		return -1;
+	}
+
+	hid_set_field(field, offset, value);
+
+	return 0;
+}
+
+static struct hid_ll_driver i2c_hid_ll_driver = {
+	.parse = i2c_hid_parse,
+	.start = i2c_hid_start,
+	.stop = i2c_hid_stop,
+	.open = i2c_hid_open,
+	.close = i2c_hid_close,
+	.power = i2c_hid_power,
+	.hidinput_input_event = i2c_hid_hidinput_input_event,
+};
+
+static int __devinit i2c_hid_init_irq(struct i2c_client *client)
+{
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	int ret;
+
+	dev_dbg(&client->dev, "Requesting IRQ: %d\n", client->irq);
+
+	ret = request_threaded_irq(client->irq, NULL, i2c_hid_irq,
+			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+			client->name, ihid);
+	if (ret < 0) {
+		dev_dbg(&client->dev,
+			"Could not register for %s interrupt, irq = %d,"
+			" ret = %d\n",
+		client->name, client->irq, ret);
+
+		return ret;
+	}
+
+	ihid->irq = client->irq;
+
+	return 0;
+}
+
+static int __devinit i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid)
+{
+	struct i2c_client *client = ihid->client;
+	struct i2c_hid_desc *hdesc = &ihid->hdesc;
+	unsigned int dsize;
+	int ret;
+
+	/* Fetch the length of HID description, retrieve the 4 first bytes:
+	 * bytes 0-1 -> length
+	 * bytes 2-3 -> bcdVersion (has to be 1.00) */
+	ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer, 4);
+
+	i2c_hid_dbg(ihid, "%s, ihid->hdesc_buffer: %*ph\n",
+			__func__, 4, ihid->hdesc_buffer);
+
+	if (ret) {
+		dev_err(&client->dev, "HID_DESCR_LENGTH_CMD Fail (ret=%d)\n",
+			ret);
+		return -ENODEV;
+	}
+
+	dsize = le16_to_cpu(hdesc->wHIDDescLength);
+	if (!dsize || dsize > HID_MAX_DESCRIPTOR_SIZE) {
+		dev_err(&client->dev, "weird size of HID descriptor (%u)\n",
+			dsize);
+		return -ENODEV;
+	}
+
+	/* check bcdVersion == 1.0 */
+	if (le16_to_cpu(hdesc->bcdVersion) != 0x0100) {
+		dev_err(&client->dev,
+			"unexpected HID descriptor bcdVersion (0x%04x)\n",
+			le16_to_cpu(hdesc->bcdVersion));
+		return -ENODEV;
+	}
+
+	i2c_hid_dbg(ihid, "Fetching the HID descriptor\n");
+
+	ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer,
+				dsize);
+	if (ret) {
+		dev_err(&client->dev, "hid_descr_cmd Fail\n");
+		return -ENODEV;
+	}
+
+	i2c_hid_dbg(ihid, "HID Descriptor: %*ph\n", dsize, ihid->hdesc_buffer);
+
+	return 0;
+}
+
+static int __devinit i2c_hid_probe(struct i2c_client *client,
+		const struct i2c_device_id *dev_id)
+{
+	int ret;
+	struct i2c_hid *ihid;
+	struct hid_device *hid;
+	__u16 hidRegister;
+	struct i2c_hid_platform_data *platform_data = client->dev.platform_data;
+
+	dbg_hid("HID probe called for i2c 0x%02x\n", client->addr);
+
+	if (!platform_data) {
+		dev_err(&client->dev, "HID register address not provided\n");
+		return -EINVAL;
+	}
+
+	if (!client->irq) {
+		dev_err(&client->dev,
+			"HID over i2c has not been provided an Int IRQ\n");
+		return -EINVAL;
+	}
+
+	ihid = kzalloc(sizeof(struct i2c_hid), GFP_KERNEL);
+	if (!ihid)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, ihid);
+
+	ihid->client = client;
+
+	hidRegister = platform_data->hid_descriptor_address;
+	ihid->wHIDDescRegister = cpu_to_le16(hidRegister);
+
+	init_waitqueue_head(&ihid->wait);
+
+	/* we need to allocate the command buffer without knowing the maximum
+	 * size of the reports. Let's use HID_MIN_BUFFER_SIZE, then we do the
+	 * real computation later. */
+	ihid->bufsize = HID_MIN_BUFFER_SIZE;
+	i2c_hid_alloc_buffers(ihid);
+
+	ret = i2c_hid_fetch_hid_descriptor(ihid);
+	if (ret < 0)
+		goto err;
+
+	ret = i2c_hid_init_irq(client);
+	if (ret < 0)
+		goto err;
+
+	hid = hid_allocate_device();
+	if (IS_ERR(hid)) {
+		ret = PTR_ERR(hid);
+		goto err;
+	}
+
+	ihid->hid = hid;
+
+	hid->driver_data = client;
+	hid->ll_driver = &i2c_hid_ll_driver;
+	hid->hid_get_raw_report = i2c_hid_get_raw_report;
+	hid->hid_output_raw_report = i2c_hid_output_raw_report;
+	hid->dev.parent = &client->dev;
+	hid->bus = BUS_I2C;
+	hid->version = le16_to_cpu(ihid->hdesc.bcdVersion);
+	hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID);
+	hid->product = le16_to_cpu(ihid->hdesc.wProductID);
+
+	snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X",
+		 client->name, hid->vendor, hid->product);
+
+	ret = hid_add_device(hid);
+	if (ret) {
+		if (ret != -ENODEV)
+			hid_err(client, "can't add hid device: %d\n", ret);
+		goto err_mem_free;
+	}
+
+	return 0;
+
+err_mem_free:
+	hid_destroy_device(hid);
+
+err:
+	if (ihid->irq)
+		free_irq(ihid->irq, ihid);
+
+	i2c_hid_free_buffers(ihid);
+	kfree(ihid);
+	return ret;
+}
+
+static int __devexit i2c_hid_remove(struct i2c_client *client)
+{
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	struct hid_device *hid;
+
+	if (WARN_ON(!ihid))
+		return -1;
+
+	hid = ihid->hid;
+	hid_destroy_device(hid);
+
+	free_irq(client->irq, ihid);
+
+	kfree(ihid);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int i2c_hid_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+
+	if (device_may_wakeup(&client->dev))
+		enable_irq_wake(ihid->irq);
+
+	/* Save some power */
+	i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+
+	return 0;
+}
+
+static int i2c_hid_resume(struct device *dev)
+{
+	int ret;
+	struct i2c_client *client = to_i2c_client(dev);
+
+	ret = i2c_hid_hwreset(client);
+	if (ret)
+		return ret;
+
+	if (device_may_wakeup(&client->dev))
+		disable_irq_wake(client->irq);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(i2c_hid_pm, i2c_hid_suspend, i2c_hid_resume);
+
+static const struct i2c_device_id i2c_hid_id_table[] = {
+	{ "i2c_hid", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, i2c_hid_id_table);
+
+
+static struct i2c_driver i2c_hid_driver = {
+	.driver = {
+		.name	= "i2c_hid",
+		.owner	= THIS_MODULE,
+		.pm	= &i2c_hid_pm,
+	},
+
+	.probe		= i2c_hid_probe,
+	.remove		= __devexit_p(i2c_hid_remove),
+
+	.id_table	= i2c_hid_id_table,
+};
+
+module_i2c_driver(i2c_hid_driver);
+
+MODULE_DESCRIPTION("HID over I2C core driver");
+MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 11c7932..3715043 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -79,9 +79,11 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT },
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 14599e2..87bd649 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -361,10 +361,6 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
 			prepare_to_wait(&list->hiddev->wait, &wait, TASK_INTERRUPTIBLE);
 
 			while (list->head == list->tail) {
-				if (file->f_flags & O_NONBLOCK) {
-					retval = -EAGAIN;
-					break;
-				}
 				if (signal_pending(current)) {
 					retval = -ERESTARTSYS;
 					break;
@@ -373,6 +369,10 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
 					retval = -EIO;
 					break;
 				}
+				if (file->f_flags & O_NONBLOCK) {
+					retval = -EAGAIN;
+					break;
+				}
 
 				/* let O_NONBLOCK tasks run */
 				mutex_unlock(&list->thread_lock);
@@ -625,7 +625,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		break;
 
 	case HIDIOCAPPLICATION:
-		if (arg < 0 || arg >= hid->maxapplication)
+		if (arg >= hid->maxapplication)
 			break;
 
 		for (i = 0; i < hid->maxcollection; i++)
diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
index 70f5dde..b38ef6d 100644
--- a/drivers/hv/Kconfig
+++ b/drivers/hv/Kconfig
@@ -13,4 +13,10 @@ config HYPERV_UTILS
 	help
 	  Select this option to enable the Hyper-V Utilities.
 
+config HYPERV_BALLOON
+	tristate "Microsoft Hyper-V Balloon driver"
+	depends on HYPERV
+	help
+	  Select this option to enable Hyper-V Balloon driver.
+
 endmenu
diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile
index a23938b..e6abfa0 100644
--- a/drivers/hv/Makefile
+++ b/drivers/hv/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_HYPERV)		+= hv_vmbus.o
 obj-$(CONFIG_HYPERV_UTILS)	+= hv_utils.o
+obj-$(CONFIG_HYPERV_BALLOON)	+= hv_balloon.o
 
 hv_vmbus-y := vmbus_drv.o \
 		 hv.o connection.o channel.o \
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index f4c3d28..773a2f2 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -33,14 +33,6 @@
 #define NUM_PAGES_SPANNED(addr, len) \
 ((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))
 
-/* Internal routines */
-static int create_gpadl_header(
-	void *kbuffer,	/* must be phys and virt contiguous */
-	u32 size,	/* page-size multiple */
-	struct vmbus_channel_msginfo **msginfo,
-	u32 *messagecount);
-static void vmbus_setevent(struct vmbus_channel *channel);
-
 /*
  * vmbus_setevent- Trigger an event notification on the specified
  * channel.
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 2b8b8d4..2f84c5c 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -265,14 +265,9 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
 {
 	struct vmbus_channel_offer_channel *offer;
 	struct vmbus_channel *newchannel;
-	uuid_le *guidtype;
-	uuid_le *guidinstance;
 
 	offer = (struct vmbus_channel_offer_channel *)hdr;
 
-	guidtype = &offer->offer.if_type;
-	guidinstance = &offer->offer.if_instance;
-
 	/* Allocate the channel object and save this offer. */
 	newchannel = alloc_channel();
 	if (!newchannel) {
@@ -470,7 +465,6 @@ static void vmbus_onversion_response(
 {
 	struct vmbus_channel_msginfo *msginfo;
 	struct vmbus_channel_message_header *requestheader;
-	struct vmbus_channel_initiate_contact *initiate;
 	struct vmbus_channel_version_response *version_response;
 	unsigned long flags;
 
@@ -484,8 +478,6 @@ static void vmbus_onversion_response(
 
 		if (requestheader->msgtype ==
 		    CHANNELMSG_INITIATE_CONTACT) {
-			initiate =
-			(struct vmbus_channel_initiate_contact *)requestheader;
 			memcpy(&msginfo->response.version_response,
 			      version_response,
 			      sizeof(struct vmbus_channel_version_response));
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
new file mode 100644
index 0000000..f6c0011
--- /dev/null
+++ b/drivers/hv/hv_balloon.c
@@ -0,0 +1,1041 @@
+/*
+ * Copyright (c) 2012, Microsoft Corporation.
+ *
+ * Author:
+ *   K. Y. Srinivasan <kys@microsoft.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, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/mman.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/completion.h>
+#include <linux/memory_hotplug.h>
+#include <linux/memory.h>
+#include <linux/notifier.h>
+#include <linux/mman.h>
+#include <linux/percpu_counter.h>
+
+#include <linux/hyperv.h>
+
+/*
+ * We begin with definitions supporting the Dynamic Memory protocol
+ * with the host.
+ *
+ * Begin protocol definitions.
+ */
+
+
+
+/*
+ * Protocol versions. The low word is the minor version, the high word the major
+ * version.
+ *
+ * History:
+ * Initial version 1.0
+ * Changed to 0.1 on 2009/03/25
+ * Changes to 0.2 on 2009/05/14
+ * Changes to 0.3 on 2009/12/03
+ * Changed to 1.0 on 2011/04/05
+ */
+
+#define DYNMEM_MAKE_VERSION(Major, Minor) ((__u32)(((Major) << 16) | (Minor)))
+#define DYNMEM_MAJOR_VERSION(Version) ((__u32)(Version) >> 16)
+#define DYNMEM_MINOR_VERSION(Version) ((__u32)(Version) & 0xff)
+
+enum {
+	DYNMEM_PROTOCOL_VERSION_1 = DYNMEM_MAKE_VERSION(0, 3),
+	DYNMEM_PROTOCOL_VERSION_2 = DYNMEM_MAKE_VERSION(1, 0),
+
+	DYNMEM_PROTOCOL_VERSION_WIN7 = DYNMEM_PROTOCOL_VERSION_1,
+	DYNMEM_PROTOCOL_VERSION_WIN8 = DYNMEM_PROTOCOL_VERSION_2,
+
+	DYNMEM_PROTOCOL_VERSION_CURRENT = DYNMEM_PROTOCOL_VERSION_WIN8
+};
+
+
+
+/*
+ * Message Types
+ */
+
+enum dm_message_type {
+	/*
+	 * Version 0.3
+	 */
+	DM_ERROR			= 0,
+	DM_VERSION_REQUEST		= 1,
+	DM_VERSION_RESPONSE		= 2,
+	DM_CAPABILITIES_REPORT		= 3,
+	DM_CAPABILITIES_RESPONSE	= 4,
+	DM_STATUS_REPORT		= 5,
+	DM_BALLOON_REQUEST		= 6,
+	DM_BALLOON_RESPONSE		= 7,
+	DM_UNBALLOON_REQUEST		= 8,
+	DM_UNBALLOON_RESPONSE		= 9,
+	DM_MEM_HOT_ADD_REQUEST		= 10,
+	DM_MEM_HOT_ADD_RESPONSE		= 11,
+	DM_VERSION_03_MAX		= 11,
+	/*
+	 * Version 1.0.
+	 */
+	DM_INFO_MESSAGE			= 12,
+	DM_VERSION_1_MAX		= 12
+};
+
+
+/*
+ * Structures defining the dynamic memory management
+ * protocol.
+ */
+
+union dm_version {
+	struct {
+		__u16 minor_version;
+		__u16 major_version;
+	};
+	__u32 version;
+} __packed;
+
+
+union dm_caps {
+	struct {
+		__u64 balloon:1;
+		__u64 hot_add:1;
+		__u64 reservedz:62;
+	} cap_bits;
+	__u64 caps;
+} __packed;
+
+union dm_mem_page_range {
+	struct  {
+		/*
+		 * The PFN number of the first page in the range.
+		 * 40 bits is the architectural limit of a PFN
+		 * number for AMD64.
+		 */
+		__u64 start_page:40;
+		/*
+		 * The number of pages in the range.
+		 */
+		__u64 page_cnt:24;
+	} finfo;
+	__u64  page_range;
+} __packed;
+
+
+
+/*
+ * The header for all dynamic memory messages:
+ *
+ * type: Type of the message.
+ * size: Size of the message in bytes; including the header.
+ * trans_id: The guest is responsible for manufacturing this ID.
+ */
+
+struct dm_header {
+	__u16 type;
+	__u16 size;
+	__u32 trans_id;
+} __packed;
+
+/*
+ * A generic message format for dynamic memory.
+ * Specific message formats are defined later in the file.
+ */
+
+struct dm_message {
+	struct dm_header hdr;
+	__u8 data[]; /* enclosed message */
+} __packed;
+
+
+/*
+ * Specific message types supporting the dynamic memory protocol.
+ */
+
+/*
+ * Version negotiation message. Sent from the guest to the host.
+ * The guest is free to try different versions until the host
+ * accepts the version.
+ *
+ * dm_version: The protocol version requested.
+ * is_last_attempt: If TRUE, this is the last version guest will request.
+ * reservedz: Reserved field, set to zero.
+ */
+
+struct dm_version_request {
+	struct dm_header hdr;
+	union dm_version version;
+	__u32 is_last_attempt:1;
+	__u32 reservedz:31;
+} __packed;
+
+/*
+ * Version response message; Host to Guest and indicates
+ * if the host has accepted the version sent by the guest.
+ *
+ * is_accepted: If TRUE, host has accepted the version and the guest
+ * should proceed to the next stage of the protocol. FALSE indicates that
+ * guest should re-try with a different version.
+ *
+ * reservedz: Reserved field, set to zero.
+ */
+
+struct dm_version_response {
+	struct dm_header hdr;
+	__u64 is_accepted:1;
+	__u64 reservedz:63;
+} __packed;
+
+/*
+ * Message reporting capabilities. This is sent from the guest to the
+ * host.
+ */
+
+struct dm_capabilities {
+	struct dm_header hdr;
+	union dm_caps caps;
+	__u64 min_page_cnt;
+	__u64 max_page_number;
+} __packed;
+
+/*
+ * Response to the capabilities message. This is sent from the host to the
+ * guest. This message notifies if the host has accepted the guest's
+ * capabilities. If the host has not accepted, the guest must shutdown
+ * the service.
+ *
+ * is_accepted: Indicates if the host has accepted guest's capabilities.
+ * reservedz: Must be 0.
+ */
+
+struct dm_capabilities_resp_msg {
+	struct dm_header hdr;
+	__u64 is_accepted:1;
+	__u64 reservedz:63;
+} __packed;
+
+/*
+ * This message is used to report memory pressure from the guest.
+ * This message is not part of any transaction and there is no
+ * response to this message.
+ *
+ * num_avail: Available memory in pages.
+ * num_committed: Committed memory in pages.
+ * page_file_size: The accumulated size of all page files
+ *		   in the system in pages.
+ * zero_free: The nunber of zero and free pages.
+ * page_file_writes: The writes to the page file in pages.
+ * io_diff: An indicator of file cache efficiency or page file activity,
+ *	    calculated as File Cache Page Fault Count - Page Read Count.
+ *	    This value is in pages.
+ *
+ * Some of these metrics are Windows specific and fortunately
+ * the algorithm on the host side that computes the guest memory
+ * pressure only uses num_committed value.
+ */
+
+struct dm_status {
+	struct dm_header hdr;
+	__u64 num_avail;
+	__u64 num_committed;
+	__u64 page_file_size;
+	__u64 zero_free;
+	__u32 page_file_writes;
+	__u32 io_diff;
+} __packed;
+
+
+/*
+ * Message to ask the guest to allocate memory - balloon up message.
+ * This message is sent from the host to the guest. The guest may not be
+ * able to allocate as much memory as requested.
+ *
+ * num_pages: number of pages to allocate.
+ */
+
+struct dm_balloon {
+	struct dm_header hdr;
+	__u32 num_pages;
+	__u32 reservedz;
+} __packed;
+
+
+/*
+ * Balloon response message; this message is sent from the guest
+ * to the host in response to the balloon message.
+ *
+ * reservedz: Reserved; must be set to zero.
+ * more_pages: If FALSE, this is the last message of the transaction.
+ * if TRUE there will atleast one more message from the guest.
+ *
+ * range_count: The number of ranges in the range array.
+ *
+ * range_array: An array of page ranges returned to the host.
+ *
+ */
+
+struct dm_balloon_response {
+	struct dm_header hdr;
+	__u32 reservedz;
+	__u32 more_pages:1;
+	__u32 range_count:31;
+	union dm_mem_page_range range_array[];
+} __packed;
+
+/*
+ * Un-balloon message; this message is sent from the host
+ * to the guest to give guest more memory.
+ *
+ * more_pages: If FALSE, this is the last message of the transaction.
+ * if TRUE there will atleast one more message from the guest.
+ *
+ * reservedz: Reserved; must be set to zero.
+ *
+ * range_count: The number of ranges in the range array.
+ *
+ * range_array: An array of page ranges returned to the host.
+ *
+ */
+
+struct dm_unballoon_request {
+	struct dm_header hdr;
+	__u32 more_pages:1;
+	__u32 reservedz:31;
+	__u32 range_count;
+	union dm_mem_page_range range_array[];
+} __packed;
+
+/*
+ * Un-balloon response message; this message is sent from the guest
+ * to the host in response to an unballoon request.
+ *
+ */
+
+struct dm_unballoon_response {
+	struct dm_header hdr;
+} __packed;
+
+
+/*
+ * Hot add request message. Message sent from the host to the guest.
+ *
+ * mem_range: Memory range to hot add.
+ *
+ * On Linux we currently don't support this since we cannot hot add
+ * arbitrary granularity of memory.
+ */
+
+struct dm_hot_add {
+	struct dm_header hdr;
+	union dm_mem_page_range range;
+} __packed;
+
+/*
+ * Hot add response message.
+ * This message is sent by the guest to report the status of a hot add request.
+ * If page_count is less than the requested page count, then the host should
+ * assume all further hot add requests will fail, since this indicates that
+ * the guest has hit an upper physical memory barrier.
+ *
+ * Hot adds may also fail due to low resources; in this case, the guest must
+ * not complete this message until the hot add can succeed, and the host must
+ * not send a new hot add request until the response is sent.
+ * If VSC fails to hot add memory DYNMEM_NUMBER_OF_UNSUCCESSFUL_HOTADD_ATTEMPTS
+ * times it fails the request.
+ *
+ *
+ * page_count: number of pages that were successfully hot added.
+ *
+ * result: result of the operation 1: success, 0: failure.
+ *
+ */
+
+struct dm_hot_add_response {
+	struct dm_header hdr;
+	__u32 page_count;
+	__u32 result;
+} __packed;
+
+/*
+ * Types of information sent from host to the guest.
+ */
+
+enum dm_info_type {
+	INFO_TYPE_MAX_PAGE_CNT = 0,
+	MAX_INFO_TYPE
+};
+
+
+/*
+ * Header for the information message.
+ */
+
+struct dm_info_header {
+	enum dm_info_type type;
+	__u32 data_size;
+} __packed;
+
+/*
+ * This message is sent from the host to the guest to pass
+ * some relevant information (win8 addition).
+ *
+ * reserved: no used.
+ * info_size: size of the information blob.
+ * info: information blob.
+ */
+
+struct dm_info_msg {
+	struct dm_info_header header;
+	__u32 reserved;
+	__u32 info_size;
+	__u8  info[];
+};
+
+/*
+ * End protocol definitions.
+ */
+
+static bool hot_add;
+static bool do_hot_add;
+
+module_param(hot_add, bool, (S_IRUGO | S_IWUSR));
+MODULE_PARM_DESC(hot_add, "If set attempt memory hot_add");
+
+static atomic_t trans_id = ATOMIC_INIT(0);
+
+static int dm_ring_size = (5 * PAGE_SIZE);
+
+/*
+ * Driver specific state.
+ */
+
+enum hv_dm_state {
+	DM_INITIALIZING = 0,
+	DM_INITIALIZED,
+	DM_BALLOON_UP,
+	DM_BALLOON_DOWN,
+	DM_HOT_ADD,
+	DM_INIT_ERROR
+};
+
+
+static __u8 recv_buffer[PAGE_SIZE];
+static __u8 *send_buffer;
+#define PAGES_IN_2M	512
+
+struct hv_dynmem_device {
+	struct hv_device *dev;
+	enum hv_dm_state state;
+	struct completion host_event;
+	struct completion config_event;
+
+	/*
+	 * Number of pages we have currently ballooned out.
+	 */
+	unsigned int num_pages_ballooned;
+
+	/*
+	 * This thread handles both balloon/hot-add
+	 * requests from the host as well as notifying
+	 * the host with regards to memory pressure in
+	 * the guest.
+	 */
+	struct task_struct *thread;
+
+	/*
+	 * We start with the highest version we can support
+	 * and downgrade based on the host; we save here the
+	 * next version to try.
+	 */
+	__u32 next_version;
+};
+
+static struct hv_dynmem_device dm_device;
+
+static void hot_add_req(struct hv_dynmem_device *dm, struct dm_hot_add *msg)
+{
+
+	struct dm_hot_add_response resp;
+
+	if (do_hot_add) {
+
+		pr_info("Memory hot add not supported\n");
+
+		/*
+		 * Currently we do not support hot add.
+		 * Just fail the request.
+		 */
+	}
+
+	memset(&resp, 0, sizeof(struct dm_hot_add_response));
+	resp.hdr.type = DM_MEM_HOT_ADD_RESPONSE;
+	resp.hdr.size = sizeof(struct dm_hot_add_response);
+	resp.hdr.trans_id = atomic_inc_return(&trans_id);
+
+	resp.page_count = 0;
+	resp.result = 0;
+
+	dm->state = DM_INITIALIZED;
+	vmbus_sendpacket(dm->dev->channel, &resp,
+			sizeof(struct dm_hot_add_response),
+			(unsigned long)NULL,
+			VM_PKT_DATA_INBAND, 0);
+
+}
+
+static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg)
+{
+	switch (msg->header.type) {
+	case INFO_TYPE_MAX_PAGE_CNT:
+		pr_info("Received INFO_TYPE_MAX_PAGE_CNT\n");
+		pr_info("Data Size is %d\n", msg->header.data_size);
+		break;
+	default:
+		pr_info("Received Unknown type: %d\n", msg->header.type);
+	}
+}
+
+/*
+ * Post our status as it relates memory pressure to the
+ * host. Host expects the guests to post this status
+ * periodically at 1 second intervals.
+ *
+ * The metrics specified in this protocol are very Windows
+ * specific and so we cook up numbers here to convey our memory
+ * pressure.
+ */
+
+static void post_status(struct hv_dynmem_device *dm)
+{
+	struct dm_status status;
+
+
+	memset(&status, 0, sizeof(struct dm_status));
+	status.hdr.type = DM_STATUS_REPORT;
+	status.hdr.size = sizeof(struct dm_status);
+	status.hdr.trans_id = atomic_inc_return(&trans_id);
+
+
+	status.num_committed = vm_memory_committed();
+
+	vmbus_sendpacket(dm->dev->channel, &status,
+				sizeof(struct dm_status),
+				(unsigned long)NULL,
+				VM_PKT_DATA_INBAND, 0);
+
+}
+
+
+
+static void free_balloon_pages(struct hv_dynmem_device *dm,
+			 union dm_mem_page_range *range_array)
+{
+	int num_pages = range_array->finfo.page_cnt;
+	__u64 start_frame = range_array->finfo.start_page;
+	struct page *pg;
+	int i;
+
+	for (i = 0; i < num_pages; i++) {
+		pg = pfn_to_page(i + start_frame);
+		__free_page(pg);
+		dm->num_pages_ballooned--;
+	}
+}
+
+
+
+static int  alloc_balloon_pages(struct hv_dynmem_device *dm, int num_pages,
+			 struct dm_balloon_response *bl_resp, int alloc_unit,
+			 bool *alloc_error)
+{
+	int i = 0;
+	struct page *pg;
+
+	if (num_pages < alloc_unit)
+		return 0;
+
+	for (i = 0; (i * alloc_unit) < num_pages; i++) {
+		if (bl_resp->hdr.size + sizeof(union dm_mem_page_range) >
+			PAGE_SIZE)
+			return i * alloc_unit;
+
+		/*
+		 * We execute this code in a thread context. Furthermore,
+		 * we don't want the kernel to try too hard.
+		 */
+		pg = alloc_pages(GFP_HIGHUSER | __GFP_NORETRY |
+				__GFP_NOMEMALLOC | __GFP_NOWARN,
+				get_order(alloc_unit << PAGE_SHIFT));
+
+		if (!pg) {
+			*alloc_error = true;
+			return i * alloc_unit;
+		}
+
+
+		dm->num_pages_ballooned += alloc_unit;
+
+		bl_resp->range_count++;
+		bl_resp->range_array[i].finfo.start_page =
+			page_to_pfn(pg);
+		bl_resp->range_array[i].finfo.page_cnt = alloc_unit;
+		bl_resp->hdr.size += sizeof(union dm_mem_page_range);
+
+	}
+
+	return num_pages;
+}
+
+
+
+static void balloon_up(struct hv_dynmem_device *dm, struct dm_balloon *req)
+{
+	int num_pages = req->num_pages;
+	int num_ballooned = 0;
+	struct dm_balloon_response *bl_resp;
+	int alloc_unit;
+	int ret;
+	bool alloc_error = false;
+	bool done = false;
+	int i;
+
+
+	/*
+	 * Currently, we only support 4k allocations.
+	 */
+	alloc_unit = 1;
+
+	while (!done) {
+		bl_resp = (struct dm_balloon_response *)send_buffer;
+		memset(send_buffer, 0, PAGE_SIZE);
+		bl_resp->hdr.type = DM_BALLOON_RESPONSE;
+		bl_resp->hdr.trans_id = atomic_inc_return(&trans_id);
+		bl_resp->hdr.size = sizeof(struct dm_balloon_response);
+		bl_resp->more_pages = 1;
+
+
+		num_pages -= num_ballooned;
+		num_ballooned = alloc_balloon_pages(dm, num_pages,
+						bl_resp, alloc_unit,
+						 &alloc_error);
+
+		if ((alloc_error) || (num_ballooned == num_pages)) {
+			bl_resp->more_pages = 0;
+			done = true;
+			dm->state = DM_INITIALIZED;
+		}
+
+		/*
+		 * We are pushing a lot of data through the channel;
+		 * deal with transient failures caused because of the
+		 * lack of space in the ring buffer.
+		 */
+
+		do {
+			ret = vmbus_sendpacket(dm_device.dev->channel,
+						bl_resp,
+						bl_resp->hdr.size,
+						(unsigned long)NULL,
+						VM_PKT_DATA_INBAND, 0);
+
+			if (ret == -EAGAIN)
+				msleep(20);
+
+		} while (ret == -EAGAIN);
+
+		if (ret) {
+			/*
+			 * Free up the memory we allocatted.
+			 */
+			pr_info("Balloon response failed\n");
+
+			for (i = 0; i < bl_resp->range_count; i++)
+				free_balloon_pages(dm,
+						 &bl_resp->range_array[i]);
+
+			done = true;
+		}
+	}
+
+}
+
+static void balloon_down(struct hv_dynmem_device *dm,
+			struct dm_unballoon_request *req)
+{
+	union dm_mem_page_range *range_array = req->range_array;
+	int range_count = req->range_count;
+	struct dm_unballoon_response resp;
+	int i;
+
+	for (i = 0; i < range_count; i++)
+		free_balloon_pages(dm, &range_array[i]);
+
+	if (req->more_pages == 1)
+		return;
+
+	memset(&resp, 0, sizeof(struct dm_unballoon_response));
+	resp.hdr.type = DM_UNBALLOON_RESPONSE;
+	resp.hdr.trans_id = atomic_inc_return(&trans_id);
+	resp.hdr.size = sizeof(struct dm_unballoon_response);
+
+	vmbus_sendpacket(dm_device.dev->channel, &resp,
+				sizeof(struct dm_unballoon_response),
+				(unsigned long)NULL,
+				VM_PKT_DATA_INBAND, 0);
+
+	dm->state = DM_INITIALIZED;
+}
+
+static void balloon_onchannelcallback(void *context);
+
+static int dm_thread_func(void *dm_dev)
+{
+	struct hv_dynmem_device *dm = dm_dev;
+	int t;
+	unsigned long  scan_start;
+
+	while (!kthread_should_stop()) {
+		t = wait_for_completion_timeout(&dm_device.config_event, 1*HZ);
+		/*
+		 * The host expects us to post information on the memory
+		 * pressure every second.
+		 */
+
+		if (t == 0)
+			post_status(dm);
+
+		scan_start = jiffies;
+		switch (dm->state) {
+		case DM_BALLOON_UP:
+			balloon_up(dm, (struct dm_balloon *)recv_buffer);
+			break;
+
+		case DM_HOT_ADD:
+			hot_add_req(dm, (struct dm_hot_add *)recv_buffer);
+			break;
+		default:
+			break;
+		}
+
+		if (!time_in_range(jiffies, scan_start, scan_start + HZ))
+			post_status(dm);
+
+	}
+
+	return 0;
+}
+
+
+static void version_resp(struct hv_dynmem_device *dm,
+			struct dm_version_response *vresp)
+{
+	struct dm_version_request version_req;
+	int ret;
+
+	if (vresp->is_accepted) {
+		/*
+		 * We are done; wakeup the
+		 * context waiting for version
+		 * negotiation.
+		 */
+		complete(&dm->host_event);
+		return;
+	}
+	/*
+	 * If there are more versions to try, continue
+	 * with negotiations; if not
+	 * shutdown the service since we are not able
+	 * to negotiate a suitable version number
+	 * with the host.
+	 */
+	if (dm->next_version == 0)
+		goto version_error;
+
+	dm->next_version = 0;
+	memset(&version_req, 0, sizeof(struct dm_version_request));
+	version_req.hdr.type = DM_VERSION_REQUEST;
+	version_req.hdr.size = sizeof(struct dm_version_request);
+	version_req.hdr.trans_id = atomic_inc_return(&trans_id);
+	version_req.version.version = DYNMEM_PROTOCOL_VERSION_WIN7;
+	version_req.is_last_attempt = 1;
+
+	ret = vmbus_sendpacket(dm->dev->channel, &version_req,
+				sizeof(struct dm_version_request),
+				(unsigned long)NULL,
+				VM_PKT_DATA_INBAND, 0);
+
+	if (ret)
+		goto version_error;
+
+	return;
+
+version_error:
+	dm->state = DM_INIT_ERROR;
+	complete(&dm->host_event);
+}
+
+static void cap_resp(struct hv_dynmem_device *dm,
+			struct dm_capabilities_resp_msg *cap_resp)
+{
+	if (!cap_resp->is_accepted) {
+		pr_info("Capabilities not accepted by host\n");
+		dm->state = DM_INIT_ERROR;
+	}
+	complete(&dm->host_event);
+}
+
+static void balloon_onchannelcallback(void *context)
+{
+	struct hv_device *dev = context;
+	u32 recvlen;
+	u64 requestid;
+	struct dm_message *dm_msg;
+	struct dm_header *dm_hdr;
+	struct hv_dynmem_device *dm = hv_get_drvdata(dev);
+
+	memset(recv_buffer, 0, sizeof(recv_buffer));
+	vmbus_recvpacket(dev->channel, recv_buffer,
+			 PAGE_SIZE, &recvlen, &requestid);
+
+	if (recvlen > 0) {
+		dm_msg = (struct dm_message *)recv_buffer;
+		dm_hdr = &dm_msg->hdr;
+
+		switch (dm_hdr->type) {
+		case DM_VERSION_RESPONSE:
+			version_resp(dm,
+				 (struct dm_version_response *)dm_msg);
+			break;
+
+		case DM_CAPABILITIES_RESPONSE:
+			cap_resp(dm,
+				 (struct dm_capabilities_resp_msg *)dm_msg);
+			break;
+
+		case DM_BALLOON_REQUEST:
+			dm->state = DM_BALLOON_UP;
+			complete(&dm->config_event);
+			break;
+
+		case DM_UNBALLOON_REQUEST:
+			dm->state = DM_BALLOON_DOWN;
+			balloon_down(dm,
+				 (struct dm_unballoon_request *)recv_buffer);
+			break;
+
+		case DM_MEM_HOT_ADD_REQUEST:
+			dm->state = DM_HOT_ADD;
+			complete(&dm->config_event);
+			break;
+
+		case DM_INFO_MESSAGE:
+			process_info(dm, (struct dm_info_msg *)dm_msg);
+			break;
+
+		default:
+			pr_err("Unhandled message: type: %d\n", dm_hdr->type);
+
+		}
+	}
+
+}
+
+static int balloon_probe(struct hv_device *dev,
+			const struct hv_vmbus_device_id *dev_id)
+{
+	int ret, t;
+	struct dm_version_request version_req;
+	struct dm_capabilities cap_msg;
+
+	do_hot_add = hot_add;
+
+	/*
+	 * First allocate a send buffer.
+	 */
+
+	send_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!send_buffer)
+		return -ENOMEM;
+
+	ret = vmbus_open(dev->channel, dm_ring_size, dm_ring_size, NULL, 0,
+			balloon_onchannelcallback, dev);
+
+	if (ret)
+		return ret;
+
+	dm_device.dev = dev;
+	dm_device.state = DM_INITIALIZING;
+	dm_device.next_version = DYNMEM_PROTOCOL_VERSION_WIN7;
+	init_completion(&dm_device.host_event);
+	init_completion(&dm_device.config_event);
+
+	dm_device.thread =
+		 kthread_run(dm_thread_func, &dm_device, "hv_balloon");
+	if (IS_ERR(dm_device.thread)) {
+		ret = PTR_ERR(dm_device.thread);
+		goto probe_error0;
+	}
+
+	hv_set_drvdata(dev, &dm_device);
+	/*
+	 * Initiate the hand shake with the host and negotiate
+	 * a version that the host can support. We start with the
+	 * highest version number and go down if the host cannot
+	 * support it.
+	 */
+	memset(&version_req, 0, sizeof(struct dm_version_request));
+	version_req.hdr.type = DM_VERSION_REQUEST;
+	version_req.hdr.size = sizeof(struct dm_version_request);
+	version_req.hdr.trans_id = atomic_inc_return(&trans_id);
+	version_req.version.version = DYNMEM_PROTOCOL_VERSION_WIN8;
+	version_req.is_last_attempt = 0;
+
+	ret = vmbus_sendpacket(dev->channel, &version_req,
+				sizeof(struct dm_version_request),
+				(unsigned long)NULL,
+				VM_PKT_DATA_INBAND,
+				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	if (ret)
+		goto probe_error1;
+
+	t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto probe_error1;
+	}
+
+	/*
+	 * If we could not negotiate a compatible version with the host
+	 * fail the probe function.
+	 */
+	if (dm_device.state == DM_INIT_ERROR) {
+		ret = -ETIMEDOUT;
+		goto probe_error1;
+	}
+	/*
+	 * Now submit our capabilities to the host.
+	 */
+	memset(&cap_msg, 0, sizeof(struct dm_capabilities));
+	cap_msg.hdr.type = DM_CAPABILITIES_REPORT;
+	cap_msg.hdr.size = sizeof(struct dm_capabilities);
+	cap_msg.hdr.trans_id = atomic_inc_return(&trans_id);
+
+	cap_msg.caps.cap_bits.balloon = 1;
+	/*
+	 * While we currently don't support hot-add,
+	 * we still advertise this capability since the
+	 * host requires that guests partcipating in the
+	 * dynamic memory protocol support hot add.
+	 */
+	cap_msg.caps.cap_bits.hot_add = 1;
+
+	/*
+	 * Currently the host does not use these
+	 * values and we set them to what is done in the
+	 * Windows driver.
+	 */
+	cap_msg.min_page_cnt = 0;
+	cap_msg.max_page_number = -1;
+
+	ret = vmbus_sendpacket(dev->channel, &cap_msg,
+				sizeof(struct dm_capabilities),
+				(unsigned long)NULL,
+				VM_PKT_DATA_INBAND,
+				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	if (ret)
+		goto probe_error1;
+
+	t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ);
+	if (t == 0) {
+		ret = -ETIMEDOUT;
+		goto probe_error1;
+	}
+
+	/*
+	 * If the host does not like our capabilities,
+	 * fail the probe function.
+	 */
+	if (dm_device.state == DM_INIT_ERROR) {
+		ret = -ETIMEDOUT;
+		goto probe_error1;
+	}
+
+	dm_device.state = DM_INITIALIZED;
+
+	return 0;
+
+probe_error1:
+	kthread_stop(dm_device.thread);
+
+probe_error0:
+	vmbus_close(dev->channel);
+	return ret;
+}
+
+static int balloon_remove(struct hv_device *dev)
+{
+	struct hv_dynmem_device *dm = hv_get_drvdata(dev);
+
+	if (dm->num_pages_ballooned != 0)
+		pr_warn("Ballooned pages: %d\n", dm->num_pages_ballooned);
+
+	vmbus_close(dev->channel);
+	kthread_stop(dm->thread);
+
+	return 0;
+}
+
+static const struct hv_vmbus_device_id id_table[] = {
+	/* Dynamic Memory Class ID */
+	/* 525074DC-8985-46e2-8057-A307DC18A502 */
+	{ VMBUS_DEVICE(0xdc, 0x74, 0x50, 0X52, 0x85, 0x89, 0xe2, 0x46,
+		       0x80, 0x57, 0xa3, 0x07, 0xdc, 0x18, 0xa5, 0x02)
+	},
+	{ },
+};
+
+MODULE_DEVICE_TABLE(vmbus, id_table);
+
+static  struct hv_driver balloon_drv = {
+	.name = "hv_balloon",
+	.id_table = id_table,
+	.probe =  balloon_probe,
+	.remove =  balloon_remove,
+};
+
+static int __init init_balloon_drv(void)
+{
+
+	return vmbus_driver_register(&balloon_drv);
+}
+
+static void exit_balloon_drv(void)
+{
+
+	vmbus_driver_unregister(&balloon_drv);
+}
+
+module_init(init_balloon_drv);
+module_exit(exit_balloon_drv);
+
+MODULE_DESCRIPTION("Hyper-V Balloon");
+MODULE_VERSION(HV_DRV_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index c4633de..32f238f 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -334,6 +334,16 @@ config SENSORS_DA9052_ADC
 	  This driver can also be built as module. If so, the module
 	  will be called da9052-hwmon.
 
+config SENSORS_DA9055
+	tristate "Dialog Semiconductor DA9055 ADC"
+	depends on MFD_DA9055
+	help
+	  If you say yes here you get support for ADC on the Dialog
+	  Semiconductor DA9055 PMIC.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called da9055-hwmon.
+
 config SENSORS_I5K_AMB
 	tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets"
 	depends on PCI
@@ -455,7 +465,7 @@ config SENSORS_HIH6130
 
 config SENSORS_CORETEMP
 	tristate "Intel Core/Core2/Atom temperature sensor"
-	depends on X86 && PCI
+	depends on X86
 	help
 	  If you say yes here you get support for the temperature
 	  sensor inside your CPU. Most of the family 6 CPUs
@@ -1106,11 +1116,12 @@ config SENSORS_ADS1015
 	  will be called ads1015.
 
 config SENSORS_ADS7828
-	tristate "Texas Instruments ADS7828"
+	tristate "Texas Instruments ADS7828 and compatibles"
 	depends on I2C
 	help
-	  If you say yes here you get support for Texas Instruments ADS7828
-	  12-bit 8-channel ADC device.
+	  If you say yes here you get support for Texas Instruments ADS7828 and
+	  ADS7830 8-channel A/D converters. ADS7828 resolution is 12-bit, while
+	  it is 8-bit on ADS7830.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called ads7828.
@@ -1197,6 +1208,14 @@ config SENSORS_TWL4030_MADC
 	This driver can also be built as a module. If so it will be called
 	twl4030-madc-hwmon.
 
+config SENSORS_VEXPRESS
+	tristate "Versatile Express"
+	depends on VEXPRESS_CONFIG
+	help
+	  This driver provides support for hardware sensors available on
+	  the ARM Ltd's Versatile Express platform. It can provide wide
+	  range of information like temperature, power, energy.
+
 config SENSORS_VIA_CPUTEMP
 	tristate "VIA CPU temperature sensor"
 	depends on X86
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 8d5fcb5..5da2874 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_SENSORS_ASC7621)	+= asc7621.o
 obj-$(CONFIG_SENSORS_ATXP1)	+= atxp1.o
 obj-$(CONFIG_SENSORS_CORETEMP)	+= coretemp.o
 obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o
+obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o
 obj-$(CONFIG_SENSORS_DME1737)	+= dme1737.o
 obj-$(CONFIG_SENSORS_DS620)	+= ds620.o
 obj-$(CONFIG_SENSORS_DS1621)	+= ds1621.o
@@ -121,6 +122,7 @@ obj-$(CONFIG_SENSORS_TMP102)	+= tmp102.o
 obj-$(CONFIG_SENSORS_TMP401)	+= tmp401.o
 obj-$(CONFIG_SENSORS_TMP421)	+= tmp421.o
 obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o
+obj-$(CONFIG_SENSORS_VEXPRESS)	+= vexpress.o
 obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
 obj-$(CONFIG_SENSORS_VT1211)	+= vt1211.o
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
index 78b8179..6119ff8 100644
--- a/drivers/hwmon/abituguru.c
+++ b/drivers/hwmon/abituguru.c
@@ -478,7 +478,7 @@ static int abituguru_write(struct abituguru_data *data,
  * alarm for sensor type X and then enabling the sensor as sensor type
  * X, if we then get an alarm it is a sensor of type X.
  */
-static int __devinit
+static int
 abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
 				   u8 sensor_addr)
 {
@@ -635,7 +635,7 @@ abituguru_detect_bank1_sensor_type_exit:
  * read/write test would be feasible because of the reaction above, I've
  * however opted to stay on the safe side.
  */
-static void __devinit
+static void
 abituguru_detect_no_bank2_sensors(struct abituguru_data *data)
 {
 	int i;
@@ -691,7 +691,7 @@ abituguru_detect_no_bank2_sensors(struct abituguru_data *data)
 		(int)data->bank2_sensors);
 }
 
-static void __devinit
+static void
 abituguru_detect_no_pwms(struct abituguru_data *data)
 {
 	int i, j;
@@ -1264,7 +1264,7 @@ static struct sensor_device_attribute_2 abituguru_sysfs_attr[] = {
 	SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0),
 };
 
-static int __devinit abituguru_probe(struct platform_device *pdev)
+static int abituguru_probe(struct platform_device *pdev)
 {
 	struct abituguru_data *data;
 	int i, j, used, sysfs_names_free, sysfs_attr_i, res = -ENODEV;
@@ -1434,7 +1434,7 @@ abituguru_probe_error:
 	return res;
 }
 
-static int __devexit abituguru_remove(struct platform_device *pdev)
+static int abituguru_remove(struct platform_device *pdev)
 {
 	int i;
 	struct abituguru_data *data = platform_get_drvdata(pdev);
@@ -1545,7 +1545,7 @@ static struct platform_driver abituguru_driver = {
 		.pm	= ABIT_UGURU_PM,
 	},
 	.probe		= abituguru_probe,
-	.remove		= __devexit_p(abituguru_remove),
+	.remove		= abituguru_remove,
 };
 
 static int __init abituguru_detect(void)
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index b174b8b..205327d 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -966,7 +966,7 @@ static struct sensor_device_attribute_2 abituguru3_sysfs_attr[] = {
 	SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0),
 };
 
-static int __devinit abituguru3_probe(struct platform_device *pdev)
+static int abituguru3_probe(struct platform_device *pdev)
 {
 	const int no_sysfs_attr[3] = { 10, 8, 7 };
 	int sensor_index[3] = { 0, 1, 1 };
@@ -1072,7 +1072,7 @@ abituguru3_probe_error:
 	return res;
 }
 
-static int __devexit abituguru3_remove(struct platform_device *pdev)
+static int abituguru3_remove(struct platform_device *pdev)
 {
 	int i;
 	struct abituguru3_data *data = platform_get_drvdata(pdev);
@@ -1171,7 +1171,7 @@ static struct platform_driver abituguru3_driver = {
 		.pm	= ABIT_UGURU3_PM
 	},
 	.probe	= abituguru3_probe,
-	.remove	= __devexit_p(abituguru3_remove),
+	.remove	= abituguru3_remove,
 };
 
 static int __init abituguru3_dmi_detect(void)
diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c
index 37c01e7..a57584d 100644
--- a/drivers/hwmon/ad7314.c
+++ b/drivers/hwmon/ad7314.c
@@ -107,7 +107,7 @@ static const struct attribute_group ad7314_group = {
 	.attrs = ad7314_attributes,
 };
 
-static int __devinit ad7314_probe(struct spi_device *spi_dev)
+static int ad7314_probe(struct spi_device *spi_dev)
 {
 	int ret;
 	struct ad7314_data *chip;
@@ -135,7 +135,7 @@ error_remove_group:
 	return ret;
 }
 
-static int __devexit ad7314_remove(struct spi_device *spi_dev)
+static int ad7314_remove(struct spi_device *spi_dev)
 {
 	struct ad7314_data *chip = dev_get_drvdata(&spi_dev->dev);
 
@@ -159,7 +159,7 @@ static struct spi_driver ad7314_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ad7314_probe,
-	.remove = __devexit_p(ad7314_remove),
+	.remove = ad7314_remove,
 	.id_table = ad7314_id,
 };
 
diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c
index b420fb3..f3a5d47 100644
--- a/drivers/hwmon/ad7414.c
+++ b/drivers/hwmon/ad7414.c
@@ -226,7 +226,7 @@ exit_remove:
 	return err;
 }
 
-static int __devexit ad7414_remove(struct i2c_client *client)
+static int ad7414_remove(struct i2c_client *client)
 {
 	struct ad7414_data *data = i2c_get_clientdata(client);
 
@@ -246,7 +246,7 @@ static struct i2c_driver ad7414_driver = {
 		.name	= "ad7414",
 	},
 	.probe	= ad7414_probe,
-	.remove	= __devexit_p(ad7414_remove),
+	.remove	= ad7414_remove,
 	.id_table = ad7414_id,
 };
 
diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c
index f4c5867..751b1f0 100644
--- a/drivers/hwmon/adcxx.c
+++ b/drivers/hwmon/adcxx.c
@@ -161,7 +161,7 @@ static struct sensor_device_attribute ad_input[] = {
 
 /*----------------------------------------------------------------------*/
 
-static int __devinit adcxx_probe(struct spi_device *spi)
+static int adcxx_probe(struct spi_device *spi)
 {
 	int channels = spi_get_device_id(spi)->driver_data;
 	struct adcxx *adc;
@@ -208,7 +208,7 @@ out_err:
 	return status;
 }
 
-static int __devexit adcxx_remove(struct spi_device *spi)
+static int adcxx_remove(struct spi_device *spi)
 {
 	struct adcxx *adc = spi_get_drvdata(spi);
 	int i;
@@ -240,7 +240,7 @@ static struct spi_driver adcxx_driver = {
 	},
 	.id_table = adcxx_ids,
 	.probe	= adcxx_probe,
-	.remove	= __devexit_p(adcxx_remove),
+	.remove	= adcxx_remove,
 };
 
 module_spi_driver(adcxx_driver);
diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
index 1f9e8af..409b5c1 100644
--- a/drivers/hwmon/ads7828.c
+++ b/drivers/hwmon/ads7828.c
@@ -1,12 +1,14 @@
 /*
- * ads7828.c - lm_sensors driver for ads7828 12-bit 8-channel ADC
+ * ads7828.c - driver for TI ADS7828 8-channel A/D converter and compatibles
  * (C) 2007 EADS Astrium
  *
  * This driver is based on the lm75 and other lm_sensors/hwmon drivers
  *
  * Written by Steve Hardy <shardy@redhat.com>
  *
- * Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads7828.pdf
+ * ADS7830 support, by Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
+ *
+ * For further information, see the Documentation/hwmon/ads7828 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
@@ -23,63 +25,48 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <linux/i2c.h>
+#include <linux/err.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/platform_data/ads7828.h>
+#include <linux/slab.h>
 
 /* The ADS7828 registers */
-#define ADS7828_NCH 8 /* 8 channels of 12-bit A-D supported */
-#define ADS7828_CMD_SD_SE 0x80 /* Single ended inputs */
-#define ADS7828_CMD_SD_DIFF 0x00 /* Differential inputs */
-#define ADS7828_CMD_PD0 0x0 /* Power Down between A-D conversions */
-#define ADS7828_CMD_PD1 0x04 /* Internal ref OFF && A-D ON */
-#define ADS7828_CMD_PD2 0x08 /* Internal ref ON && A-D OFF */
-#define ADS7828_CMD_PD3 0x0C /* Internal ref ON && A-D ON */
-#define ADS7828_INT_VREF_MV 2500 /* Internal vref is 2.5V, 2500mV */
-
-/* Addresses to scan */
-static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
-	I2C_CLIENT_END };
-
-/* Module parameters */
-static bool se_input = 1; /* Default is SE, 0 == diff */
-static bool int_vref = 1; /* Default is internal ref ON */
-static int vref_mv = ADS7828_INT_VREF_MV; /* set if vref != 2.5V */
-module_param(se_input, bool, S_IRUGO);
-module_param(int_vref, bool, S_IRUGO);
-module_param(vref_mv, int, S_IRUGO);
-
-/* Global Variables */
-static u8 ads7828_cmd_byte; /* cmd byte without channel bits */
-static unsigned int ads7828_lsb_resol; /* resolution of the ADC sample lsb */
-
-/* Each client has this additional data */
+#define ADS7828_NCH		8	/* 8 channels supported */
+#define ADS7828_CMD_SD_SE	0x80	/* Single ended inputs */
+#define ADS7828_CMD_PD1		0x04	/* Internal vref OFF && A/D ON */
+#define ADS7828_CMD_PD3		0x0C	/* Internal vref ON && A/D ON */
+#define ADS7828_INT_VREF_MV	2500	/* Internal vref is 2.5V, 2500mV */
+#define ADS7828_EXT_VREF_MV_MIN	50	/* External vref min value 0.05V */
+#define ADS7828_EXT_VREF_MV_MAX	5250	/* External vref max value 5.25V */
+
+/* List of supported devices */
+enum ads7828_chips { ads7828, ads7830 };
+
+/* Client specific data */
 struct ads7828_data {
 	struct device *hwmon_dev;
-	struct mutex update_lock; /* mutex protect updates */
-	char valid; /* !=0 if following fields are valid */
-	unsigned long last_updated; /* In jiffies */
-	u16 adc_input[ADS7828_NCH]; /* ADS7828_NCH 12-bit samples */
+	struct mutex update_lock;	/* Mutex protecting updates */
+	unsigned long last_updated;	/* Last updated time (in jiffies) */
+	u16 adc_input[ADS7828_NCH];	/* ADS7828_NCH samples */
+	bool valid;			/* Validity flag */
+	bool diff_input;		/* Differential input */
+	bool ext_vref;			/* External voltage reference */
+	unsigned int vref_mv;		/* voltage reference value */
+	u8 cmd_byte;			/* Command byte without channel bits */
+	unsigned int lsb_resol;		/* Resolution of the ADC sample LSB */
+	s32 (*read_channel)(const struct i2c_client *client, u8 command);
 };
 
-/* Function declaration - necessary due to function dependencies */
-static int ads7828_detect(struct i2c_client *client,
-			  struct i2c_board_info *info);
-static int ads7828_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id);
-
-static inline u8 channel_cmd_byte(int ch)
+/* Command byte C2,C1,C0 - see datasheet */
+static inline u8 ads7828_cmd_byte(u8 cmd, int ch)
 {
-	/* cmd byte C2,C1,C0 - see datasheet */
-	u8 cmd = (((ch>>1) | (ch&0x01)<<2)<<4);
-	cmd |= ads7828_cmd_byte;
-	return cmd;
+	return cmd | (((ch >> 1) | (ch & 0x01) << 2) << 4);
 }
 
 /* Update data for the device (all 8 channels) */
@@ -96,12 +83,11 @@ static struct ads7828_data *ads7828_update_device(struct device *dev)
 		dev_dbg(&client->dev, "Starting ads7828 update\n");
 
 		for (ch = 0; ch < ADS7828_NCH; ch++) {
-			u8 cmd = channel_cmd_byte(ch);
-			data->adc_input[ch] =
-				i2c_smbus_read_word_swapped(client, cmd);
+			u8 cmd = ads7828_cmd_byte(data->cmd_byte, ch);
+			data->adc_input[ch] = data->read_channel(client, cmd);
 		}
 		data->last_updated = jiffies;
-		data->valid = 1;
+		data->valid = true;
 	}
 
 	mutex_unlock(&data->update_lock);
@@ -110,28 +96,25 @@ static struct ads7828_data *ads7828_update_device(struct device *dev)
 }
 
 /* sysfs callback function */
-static ssize_t show_in(struct device *dev, struct device_attribute *da,
-	char *buf)
+static ssize_t ads7828_show_in(struct device *dev, struct device_attribute *da,
+			       char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	struct ads7828_data *data = ads7828_update_device(dev);
-	/* Print value (in mV as specified in sysfs-interface documentation) */
-	return sprintf(buf, "%d\n", (data->adc_input[attr->index] *
-		ads7828_lsb_resol)/1000);
-}
+	unsigned int value = DIV_ROUND_CLOSEST(data->adc_input[attr->index] *
+					       data->lsb_resol, 1000);
 
-#define in_reg(offset)\
-static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in,\
-	NULL, offset)
+	return sprintf(buf, "%d\n", value);
+}
 
-in_reg(0);
-in_reg(1);
-in_reg(2);
-in_reg(3);
-in_reg(4);
-in_reg(5);
-in_reg(6);
-in_reg(7);
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ads7828_show_in, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ads7828_show_in, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ads7828_show_in, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, ads7828_show_in, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, ads7828_show_in, NULL, 4);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, ads7828_show_in, NULL, 5);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, ads7828_show_in, NULL, 6);
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, ads7828_show_in, NULL, 7);
 
 static struct attribute *ads7828_attributes[] = {
 	&sensor_dev_attr_in0_input.dev_attr.attr,
@@ -152,60 +135,9 @@ static const struct attribute_group ads7828_group = {
 static int ads7828_remove(struct i2c_client *client)
 {
 	struct ads7828_data *data = i2c_get_clientdata(client);
+
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &ads7828_group);
-	return 0;
-}
-
-static const struct i2c_device_id ads7828_id[] = {
-	{ "ads7828", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, ads7828_id);
-
-/* This is the driver that will be inserted */
-static struct i2c_driver ads7828_driver = {
-	.class = I2C_CLASS_HWMON,
-	.driver = {
-		.name = "ads7828",
-	},
-	.probe = ads7828_probe,
-	.remove = ads7828_remove,
-	.id_table = ads7828_id,
-	.detect = ads7828_detect,
-	.address_list = normal_i2c,
-};
-
-/* Return 0 if detection is successful, -ENODEV otherwise */
-static int ads7828_detect(struct i2c_client *client,
-			  struct i2c_board_info *info)
-{
-	struct i2c_adapter *adapter = client->adapter;
-	int ch;
-
-	/* Check we have a valid client */
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA))
-		return -ENODEV;
-
-	/*
-	 * Now, we do the remaining detection. There is no identification
-	 * dedicated register so attempt to sanity check using knowledge of
-	 * the chip
-	 * - Read from the 8 channel addresses
-	 * - Check the top 4 bits of each result are not set (12 data bits)
-	 */
-	for (ch = 0; ch < ADS7828_NCH; ch++) {
-		u16 in_data;
-		u8 cmd = channel_cmd_byte(ch);
-		in_data = i2c_smbus_read_word_swapped(client, cmd);
-		if (in_data & 0xF000) {
-			pr_debug("%s : Doesn't look like an ads7828 device\n",
-				 __func__);
-			return -ENODEV;
-		}
-	}
-
-	strlcpy(info->type, "ads7828", I2C_NAME_SIZE);
 
 	return 0;
 }
@@ -213,6 +145,7 @@ static int ads7828_detect(struct i2c_client *client,
 static int ads7828_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
+	struct ads7828_platform_data *pdata = client->dev.platform_data;
 	struct ads7828_data *data;
 	int err;
 
@@ -221,10 +154,37 @@ static int ads7828_probe(struct i2c_client *client,
 	if (!data)
 		return -ENOMEM;
 
+	if (pdata) {
+		data->diff_input = pdata->diff_input;
+		data->ext_vref = pdata->ext_vref;
+		if (data->ext_vref)
+			data->vref_mv = pdata->vref_mv;
+	}
+
+	/* Bound Vref with min/max values if it was provided */
+	if (data->vref_mv)
+		data->vref_mv = SENSORS_LIMIT(data->vref_mv,
+					      ADS7828_EXT_VREF_MV_MIN,
+					      ADS7828_EXT_VREF_MV_MAX);
+	else
+		data->vref_mv = ADS7828_INT_VREF_MV;
+
+	/* ADS7828 uses 12-bit samples, while ADS7830 is 8-bit */
+	if (id->driver_data == ads7828) {
+		data->lsb_resol = DIV_ROUND_CLOSEST(data->vref_mv * 1000, 4096);
+		data->read_channel = i2c_smbus_read_word_swapped;
+	} else {
+		data->lsb_resol = DIV_ROUND_CLOSEST(data->vref_mv * 1000, 256);
+		data->read_channel = i2c_smbus_read_byte_data;
+	}
+
+	data->cmd_byte = data->ext_vref ? ADS7828_CMD_PD1 : ADS7828_CMD_PD3;
+	if (!data->diff_input)
+		data->cmd_byte |= ADS7828_CMD_SD_SE;
+
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
 
-	/* Register sysfs hooks */
 	err = sysfs_create_group(&client->dev.kobj, &ads7828_group);
 	if (err)
 		return err;
@@ -232,38 +192,35 @@ static int ads7828_probe(struct i2c_client *client,
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
 		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove;
+		goto error;
 	}
 
 	return 0;
 
-exit_remove:
+error:
 	sysfs_remove_group(&client->dev.kobj, &ads7828_group);
 	return err;
 }
 
-static int __init sensors_ads7828_init(void)
-{
-	/* Initialize the command byte according to module parameters */
-	ads7828_cmd_byte = se_input ?
-		ADS7828_CMD_SD_SE : ADS7828_CMD_SD_DIFF;
-	ads7828_cmd_byte |= int_vref ?
-		ADS7828_CMD_PD3 : ADS7828_CMD_PD1;
+static const struct i2c_device_id ads7828_device_ids[] = {
+	{ "ads7828", ads7828 },
+	{ "ads7830", ads7830 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ads7828_device_ids);
 
-	/* Calculate the LSB resolution */
-	ads7828_lsb_resol = (vref_mv*1000)/4096;
+static struct i2c_driver ads7828_driver = {
+	.driver = {
+		.name = "ads7828",
+	},
 
-	return i2c_add_driver(&ads7828_driver);
-}
+	.id_table = ads7828_device_ids,
+	.probe = ads7828_probe,
+	.remove = ads7828_remove,
+};
 
-static void __exit sensors_ads7828_exit(void)
-{
-	i2c_del_driver(&ads7828_driver);
-}
+module_i2c_driver(ads7828_driver);
 
-MODULE_AUTHOR("Steve Hardy <shardy@redhat.com>");
-MODULE_DESCRIPTION("ADS7828 driver");
 MODULE_LICENSE("GPL");
-
-module_init(sensors_ads7828_init);
-module_exit(sensors_ads7828_exit);
+MODULE_AUTHOR("Steve Hardy <shardy@redhat.com>");
+MODULE_DESCRIPTION("Driver for TI ADS7828 A/D converter and compatibles");
diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c
index 1b53aa4..a798759 100644
--- a/drivers/hwmon/ads7871.c
+++ b/drivers/hwmon/ads7871.c
@@ -173,7 +173,7 @@ static const struct attribute_group ads7871_group = {
 	.attrs = ads7871_attributes,
 };
 
-static int __devinit ads7871_probe(struct spi_device *spi)
+static int ads7871_probe(struct spi_device *spi)
 {
 	int ret, err;
 	uint8_t val;
@@ -225,7 +225,7 @@ error_remove:
 	return err;
 }
 
-static int __devexit ads7871_remove(struct spi_device *spi)
+static int ads7871_remove(struct spi_device *spi)
 {
 	struct ads7871_data *pdata = spi_get_drvdata(spi);
 
@@ -241,7 +241,7 @@ static struct spi_driver ads7871_driver = {
 	},
 
 	.probe = ads7871_probe,
-	.remove = __devexit_p(ads7871_remove),
+	.remove = ads7871_remove,
 };
 
 module_spi_driver(ads7871_driver);
diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c
index 517f185..34ff03a 100644
--- a/drivers/hwmon/adt7411.c
+++ b/drivers/hwmon/adt7411.c
@@ -276,7 +276,7 @@ static int adt7411_detect(struct i2c_client *client,
 	return 0;
 }
 
-static int __devinit adt7411_probe(struct i2c_client *client,
+static int adt7411_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
 	struct adt7411_data *data;
@@ -317,7 +317,7 @@ static int __devinit adt7411_probe(struct i2c_client *client,
 	return ret;
 }
 
-static int __devexit adt7411_remove(struct i2c_client *client)
+static int adt7411_remove(struct i2c_client *client)
 {
 	struct adt7411_data *data = i2c_get_clientdata(client);
 
@@ -337,7 +337,7 @@ static struct i2c_driver adt7411_driver = {
 		.name		= "adt7411",
 	},
 	.probe  = adt7411_probe,
-	.remove	= __devexit_p(adt7411_remove),
+	.remove	= adt7411_remove,
 	.id_table = adt7411_id,
 	.detect = adt7411_detect,
 	.address_list = normal_i2c,
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 47b8d84..d64923d 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -34,7 +34,6 @@
 #include <linux/list.h>
 #include <linux/platform_device.h>
 #include <linux/cpu.h>
-#include <linux/pci.h>
 #include <linux/smp.h>
 #include <linux/moduleparam.h>
 #include <asm/msr.h>
@@ -197,14 +196,6 @@ struct tjmax {
 };
 
 static const struct tjmax __cpuinitconst tjmax_table[] = {
-	{ "CPU D410", 100000 },
-	{ "CPU D425", 100000 },
-	{ "CPU D510", 100000 },
-	{ "CPU D525", 100000 },
-	{ "CPU N450", 100000 },
-	{ "CPU N455", 100000 },
-	{ "CPU N470", 100000 },
-	{ "CPU N475", 100000 },
 	{ "CPU  230", 100000 },		/* Model 0x1c, stepping 2	*/
 	{ "CPU  330", 125000 },		/* Model 0x1c, stepping 2	*/
 	{ "CPU CE4110", 110000 },	/* Model 0x1c, stepping 10	*/
@@ -212,6 +203,28 @@ static const struct tjmax __cpuinitconst tjmax_table[] = {
 	{ "CPU CE4170", 110000 },	/* Model 0x1c, stepping 10	*/
 };
 
+struct tjmax_model {
+	u8 model;
+	u8 mask;
+	int tjmax;
+};
+
+#define ANY 0xff
+
+static const struct tjmax_model __cpuinitconst tjmax_model_table[] = {
+	{ 0x1c, 10, 100000 },	/* D4xx, N4xx, D5xx, N5xx */
+	{ 0x1c, ANY, 90000 },	/* Z5xx, N2xx, possibly others
+				 * Note: Also matches 230 and 330,
+				 * which are covered by tjmax_table
+				 */
+	{ 0x26, ANY, 90000 },	/* Atom Tunnel Creek (Exx), Lincroft (Z6xx)
+				 * Note: TjMax for E6xxT is 110C, but CPU type
+				 * is undetectable by software
+				 */
+	{ 0x27, ANY, 90000 },	/* Atom Medfield (Z2460) */
+	{ 0x36, ANY, 100000 },	/* Atom Cedar Trail/Cedarview (N2xxx, D2xxx) */
+};
+
 static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id,
 				  struct device *dev)
 {
@@ -222,7 +235,6 @@ static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id,
 	int usemsr_ee = 1;
 	int err;
 	u32 eax, edx;
-	struct pci_dev *host_bridge;
 	int i;
 
 	/* explicit tjmax table entries override heuristics */
@@ -231,32 +243,18 @@ static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id,
 			return tjmax_table[i].tjmax;
 	}
 
+	for (i = 0; i < ARRAY_SIZE(tjmax_model_table); i++) {
+		const struct tjmax_model *tm = &tjmax_model_table[i];
+		if (c->x86_model == tm->model &&
+		    (tm->mask == ANY || c->x86_mask == tm->mask))
+			return tm->tjmax;
+	}
+
 	/* Early chips have no MSR for TjMax */
 
 	if (c->x86_model == 0xf && c->x86_mask < 4)
 		usemsr_ee = 0;
 
-	/* Atom CPUs */
-
-	if (c->x86_model == 0x1c || c->x86_model == 0x26
-	    || c->x86_model == 0x27) {
-		usemsr_ee = 0;
-
-		host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
-
-		if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL
-		    && (host_bridge->device == 0xa000	/* NM10 based nettop */
-		    || host_bridge->device == 0xa010))	/* NM10 based netbook */
-			tjmax = 100000;
-		else
-			tjmax = 90000;
-
-		pci_dev_put(host_bridge);
-	} else if (c->x86_model == 0x36) {
-		usemsr_ee = 0;
-		tjmax = 100000;
-	}
-
 	if (c->x86_model > 0xe && usemsr_ee) {
 		u8 platform_id;
 
@@ -358,7 +356,7 @@ static int __cpuinit get_tjmax(struct cpuinfo_x86 *c, u32 id,
 	return adjust_tjmax(c, id, dev);
 }
 
-static int __devinit create_name_attr(struct platform_data *pdata,
+static int create_name_attr(struct platform_data *pdata,
 				      struct device *dev)
 {
 	sysfs_attr_init(&pdata->name_attr.attr);
@@ -553,7 +551,7 @@ static void coretemp_remove_core(struct platform_data *pdata,
 	pdata->core_data[indx] = NULL;
 }
 
-static int __devinit coretemp_probe(struct platform_device *pdev)
+static int coretemp_probe(struct platform_device *pdev)
 {
 	struct platform_data *pdata;
 	int err;
@@ -586,7 +584,7 @@ exit_free:
 	return err;
 }
 
-static int __devexit coretemp_remove(struct platform_device *pdev)
+static int coretemp_remove(struct platform_device *pdev)
 {
 	struct platform_data *pdata = platform_get_drvdata(pdev);
 	int i;
@@ -608,7 +606,7 @@ static struct platform_driver coretemp_driver = {
 		.name = DRVNAME,
 	},
 	.probe = coretemp_probe,
-	.remove = __devexit_p(coretemp_remove),
+	.remove = coretemp_remove,
 };
 
 static int __cpuinit coretemp_device_add(unsigned int cpu)
diff --git a/drivers/hwmon/da9052-hwmon.c b/drivers/hwmon/da9052-hwmon.c
index b8d01c5..ab4452c 100644
--- a/drivers/hwmon/da9052-hwmon.c
+++ b/drivers/hwmon/da9052-hwmon.c
@@ -60,30 +60,17 @@ static inline int vbbat_reg_to_mV(int value)
 	return DIV_ROUND_CLOSEST(value * 2500, 512);
 }
 
-static int da9052_enable_vddout_channel(struct da9052 *da9052)
+static inline int da9052_enable_vddout_channel(struct da9052 *da9052)
 {
-	int ret;
-
-	ret = da9052_reg_read(da9052, DA9052_ADC_CONT_REG);
-	if (ret < 0)
-		return ret;
-
-	ret |= DA9052_ADCCONT_AUTOVDDEN;
-
-	return da9052_reg_write(da9052, DA9052_ADC_CONT_REG, ret);
+	return da9052_reg_update(da9052, DA9052_ADC_CONT_REG,
+				 DA9052_ADCCONT_AUTOVDDEN,
+				 DA9052_ADCCONT_AUTOVDDEN);
 }
 
-static int da9052_disable_vddout_channel(struct da9052 *da9052)
+static inline int da9052_disable_vddout_channel(struct da9052 *da9052)
 {
-	int ret;
-
-	ret = da9052_reg_read(da9052, DA9052_ADC_CONT_REG);
-	if (ret < 0)
-		return ret;
-
-	ret &= ~DA9052_ADCCONT_AUTOVDDEN;
-
-	return da9052_reg_write(da9052, DA9052_ADC_CONT_REG, ret);
+	return da9052_reg_update(da9052, DA9052_ADC_CONT_REG,
+				 DA9052_ADCCONT_AUTOVDDEN, 0);
 }
 
 static ssize_t da9052_read_vddout(struct device *dev,
@@ -283,7 +270,7 @@ static struct attribute *da9052_attr[] = {
 
 static const struct attribute_group da9052_attr_group = {.attrs = da9052_attr};
 
-static int __devinit da9052_hwmon_probe(struct platform_device *pdev)
+static int da9052_hwmon_probe(struct platform_device *pdev)
 {
 	struct da9052_hwmon *hwmon;
 	int ret;
@@ -316,7 +303,7 @@ err_mem:
 	return ret;
 }
 
-static int __devexit da9052_hwmon_remove(struct platform_device *pdev)
+static int da9052_hwmon_remove(struct platform_device *pdev)
 {
 	struct da9052_hwmon *hwmon = platform_get_drvdata(pdev);
 
@@ -328,7 +315,7 @@ static int __devexit da9052_hwmon_remove(struct platform_device *pdev)
 
 static struct platform_driver da9052_hwmon_driver = {
 	.probe = da9052_hwmon_probe,
-	.remove = __devexit_p(da9052_hwmon_remove),
+	.remove = da9052_hwmon_remove,
 	.driver = {
 		.name = "da9052-hwmon",
 		.owner = THIS_MODULE,
diff --git a/drivers/hwmon/da9055-hwmon.c b/drivers/hwmon/da9055-hwmon.c
new file mode 100644
index 0000000..9465c05
--- /dev/null
+++ b/drivers/hwmon/da9055-hwmon.c
@@ -0,0 +1,336 @@
+/*
+ * HWMON Driver for Dialog DA9055
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the 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/delay.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/reg.h>
+
+#define DA9055_ADCIN_DIV	102
+#define DA9055_VSYS_DIV	85
+
+#define DA9055_ADC_VSYS	0
+#define DA9055_ADC_ADCIN1	1
+#define DA9055_ADC_ADCIN2	2
+#define DA9055_ADC_ADCIN3	3
+#define DA9055_ADC_TJUNC	4
+
+struct da9055_hwmon {
+	struct da9055	*da9055;
+	struct device	*class_device;
+	struct mutex	hwmon_lock;
+	struct mutex	irq_lock;
+	struct completion done;
+};
+
+static const char * const input_names[] = {
+	[DA9055_ADC_VSYS]	= "VSYS",
+	[DA9055_ADC_ADCIN1]	= "ADC IN1",
+	[DA9055_ADC_ADCIN2]	= "ADC IN2",
+	[DA9055_ADC_ADCIN3]	= "ADC IN3",
+	[DA9055_ADC_TJUNC]	= "CHIP TEMP",
+};
+
+static const u8 chan_mux[DA9055_ADC_TJUNC + 1] = {
+	[DA9055_ADC_VSYS]	= DA9055_ADC_MUX_VSYS,
+	[DA9055_ADC_ADCIN1]	= DA9055_ADC_MUX_ADCIN1,
+	[DA9055_ADC_ADCIN2]	= DA9055_ADC_MUX_ADCIN2,
+	[DA9055_ADC_ADCIN3]	= DA9055_ADC_MUX_ADCIN3,
+	[DA9055_ADC_TJUNC]	= DA9055_ADC_MUX_T_SENSE,
+};
+
+static int da9055_adc_manual_read(struct da9055_hwmon *hwmon,
+					unsigned char channel)
+{
+	int ret;
+	unsigned short calc_data;
+	unsigned short data;
+	unsigned char mux_sel;
+	struct da9055 *da9055 = hwmon->da9055;
+
+	if (channel > DA9055_ADC_TJUNC)
+		return -EINVAL;
+
+	mutex_lock(&hwmon->irq_lock);
+
+	/* Selects desired MUX for manual conversion */
+	mux_sel = chan_mux[channel] | DA9055_ADC_MAN_CONV;
+
+	ret = da9055_reg_write(da9055, DA9055_REG_ADC_MAN, mux_sel);
+	if (ret < 0)
+		goto err;
+
+	/* Wait for an interrupt */
+	if (!wait_for_completion_timeout(&hwmon->done,
+					msecs_to_jiffies(500))) {
+		dev_err(da9055->dev,
+			"timeout waiting for ADC conversion interrupt\n");
+		ret = -ETIMEDOUT;
+		goto err;
+	}
+
+	ret = da9055_reg_read(da9055, DA9055_REG_ADC_RES_H);
+	if (ret < 0)
+		goto err;
+
+	calc_data = (unsigned short)ret;
+	data = calc_data << 2;
+
+	ret = da9055_reg_read(da9055, DA9055_REG_ADC_RES_L);
+	if (ret < 0)
+		goto err;
+
+	calc_data = (unsigned short)(ret & DA9055_ADC_LSB_MASK);
+	data |= calc_data;
+
+	ret = data;
+
+err:
+	mutex_unlock(&hwmon->irq_lock);
+	return ret;
+}
+
+static irqreturn_t da9055_auxadc_irq(int irq, void *irq_data)
+{
+	struct da9055_hwmon *hwmon = irq_data;
+
+	complete(&hwmon->done);
+
+	return IRQ_HANDLED;
+}
+
+/* Conversion function for VSYS and ADCINx */
+static inline int volt_reg_to_mV(int value, int channel)
+{
+	if (channel == DA9055_ADC_VSYS)
+		return DIV_ROUND_CLOSEST(value * 1000, DA9055_VSYS_DIV) + 2500;
+	else
+		return DIV_ROUND_CLOSEST(value * 1000, DA9055_ADCIN_DIV);
+}
+
+static int da9055_enable_auto_mode(struct da9055 *da9055, int channel)
+{
+
+	return da9055_reg_update(da9055, DA9055_REG_ADC_CONT, 1 << channel,
+				1 << channel);
+
+}
+
+static int da9055_disable_auto_mode(struct da9055 *da9055, int channel)
+{
+
+	return da9055_reg_update(da9055, DA9055_REG_ADC_CONT, 1 << channel, 0);
+}
+
+static ssize_t da9055_read_auto_ch(struct device *dev,
+				struct device_attribute *devattr, char *buf)
+{
+	struct da9055_hwmon *hwmon = dev_get_drvdata(dev);
+	int ret, adc;
+	int channel = to_sensor_dev_attr(devattr)->index;
+
+	mutex_lock(&hwmon->hwmon_lock);
+
+	ret = da9055_enable_auto_mode(hwmon->da9055, channel);
+	if (ret < 0)
+		goto hwmon_err;
+
+	usleep_range(10000, 10500);
+
+	adc = da9055_reg_read(hwmon->da9055, DA9055_REG_VSYS_RES + channel);
+	if (adc < 0) {
+		ret = adc;
+		goto hwmon_err_release;
+	}
+
+	ret = da9055_disable_auto_mode(hwmon->da9055, channel);
+	if (ret < 0)
+		goto hwmon_err;
+
+	mutex_unlock(&hwmon->hwmon_lock);
+
+	return sprintf(buf, "%d\n", volt_reg_to_mV(adc, channel));
+
+hwmon_err_release:
+	da9055_disable_auto_mode(hwmon->da9055, channel);
+hwmon_err:
+	mutex_unlock(&hwmon->hwmon_lock);
+	return ret;
+}
+
+static ssize_t da9055_read_tjunc(struct device *dev,
+				 struct device_attribute *devattr, char *buf)
+{
+	struct da9055_hwmon *hwmon = dev_get_drvdata(dev);
+	int tjunc;
+	int toffset;
+
+	tjunc = da9055_adc_manual_read(hwmon, DA9055_ADC_TJUNC);
+	if (tjunc < 0)
+		return tjunc;
+
+	toffset = da9055_reg_read(hwmon->da9055, DA9055_REG_T_OFFSET);
+	if (toffset < 0)
+		return toffset;
+
+	/*
+	 * Degrees celsius = -0.4084 * (ADC_RES - T_OFFSET) + 307.6332
+	 * T_OFFSET is a trim value used to improve accuracy of the result
+	 */
+	return sprintf(buf, "%d\n", DIV_ROUND_CLOSEST(-4084 * (tjunc - toffset)
+							+ 3076332, 10000));
+}
+
+static ssize_t da9055_hwmon_show_name(struct device *dev,
+				      struct device_attribute *devattr,
+				      char *buf)
+{
+	return sprintf(buf, "da9055-hwmon\n");
+}
+
+static ssize_t show_label(struct device *dev,
+			  struct device_attribute *devattr, char *buf)
+{
+	return sprintf(buf, "%s\n",
+		       input_names[to_sensor_dev_attr(devattr)->index]);
+}
+
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, da9055_read_auto_ch, NULL,
+			  DA9055_ADC_VSYS);
+static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, show_label, NULL,
+			  DA9055_ADC_VSYS);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, da9055_read_auto_ch, NULL,
+			  DA9055_ADC_ADCIN1);
+static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_label, NULL,
+			  DA9055_ADC_ADCIN1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, da9055_read_auto_ch, NULL,
+			  DA9055_ADC_ADCIN2);
+static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_label, NULL,
+			  DA9055_ADC_ADCIN2);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, da9055_read_auto_ch, NULL,
+			  DA9055_ADC_ADCIN3);
+static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL,
+			  DA9055_ADC_ADCIN3);
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, da9055_read_tjunc, NULL,
+			  DA9055_ADC_TJUNC);
+static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL,
+			  DA9055_ADC_TJUNC);
+
+static DEVICE_ATTR(name, S_IRUGO, da9055_hwmon_show_name, NULL);
+
+static struct attribute *da9055_attr[] = {
+	&dev_attr_name.attr,
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in0_label.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in1_label.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in2_label.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in3_label.dev_attr.attr,
+
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_label.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group da9055_attr_group = {.attrs = da9055_attr};
+
+static int da9055_hwmon_probe(struct platform_device *pdev)
+{
+	struct da9055_hwmon *hwmon;
+	int hwmon_irq, ret;
+
+	hwmon = devm_kzalloc(&pdev->dev, sizeof(struct da9055_hwmon),
+			     GFP_KERNEL);
+	if (!hwmon)
+		return -ENOMEM;
+
+	mutex_init(&hwmon->hwmon_lock);
+	mutex_init(&hwmon->irq_lock);
+
+	init_completion(&hwmon->done);
+	hwmon->da9055 = dev_get_drvdata(pdev->dev.parent);
+
+	platform_set_drvdata(pdev, hwmon);
+
+	hwmon_irq = platform_get_irq_byname(pdev, "HWMON");
+	if (hwmon_irq < 0)
+		return hwmon_irq;
+
+	hwmon_irq = regmap_irq_get_virq(hwmon->da9055->irq_data, hwmon_irq);
+	if (hwmon_irq < 0)
+		return hwmon_irq;
+
+	ret = devm_request_threaded_irq(&pdev->dev, hwmon_irq,
+					NULL, da9055_auxadc_irq,
+					IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+					"adc-irq", hwmon);
+	if (ret != 0) {
+		dev_err(hwmon->da9055->dev, "DA9055 ADC IRQ failed ret=%d\n",
+			ret);
+		return ret;
+	}
+
+	ret = sysfs_create_group(&pdev->dev.kobj, &da9055_attr_group);
+	if (ret)
+		return ret;
+
+	hwmon->class_device = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(hwmon->class_device)) {
+		ret = PTR_ERR(hwmon->class_device);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	sysfs_remove_group(&pdev->dev.kobj, &da9055_attr_group);
+	return ret;
+}
+
+static int da9055_hwmon_remove(struct platform_device *pdev)
+{
+	struct da9055_hwmon *hwmon = platform_get_drvdata(pdev);
+
+	sysfs_remove_group(&pdev->dev.kobj, &da9055_attr_group);
+	hwmon_device_unregister(hwmon->class_device);
+
+	return 0;
+}
+
+static struct platform_driver da9055_hwmon_driver = {
+	.probe = da9055_hwmon_probe,
+	.remove = da9055_hwmon_remove,
+	.driver = {
+		.name = "da9055-hwmon",
+		.owner = THIS_MODULE,
+	},
+};
+
+module_platform_driver(da9055_hwmon_driver);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("DA9055 HWMON driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9055-hwmon");
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index fe0eeec..7430f70 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -2630,7 +2630,7 @@ exit:
 	return err;
 }
 
-static int __devinit dme1737_isa_probe(struct platform_device *pdev)
+static int dme1737_isa_probe(struct platform_device *pdev)
 {
 	u8 company, device;
 	struct resource *res;
@@ -2718,7 +2718,7 @@ exit_remove_files:
 	return err;
 }
 
-static int __devexit dme1737_isa_remove(struct platform_device *pdev)
+static int dme1737_isa_remove(struct platform_device *pdev)
 {
 	struct dme1737_data *data = platform_get_drvdata(pdev);
 
@@ -2734,7 +2734,7 @@ static struct platform_driver dme1737_isa_driver = {
 		.name = "dme1737",
 	},
 	.probe = dme1737_isa_probe,
-	.remove = __devexit_p(dme1737_isa_remove),
+	.remove = dme1737_isa_remove,
 };
 
 /* ---------------------------------------------------------------------
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index 4dd7723..a981697 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -1343,7 +1343,7 @@ static struct attribute *f71805f_attr_pwm[] = {
  * Device registration and initialization
  */
 
-static void __devinit f71805f_init_device(struct f71805f_data *data)
+static void f71805f_init_device(struct f71805f_data *data)
 {
 	u8 reg;
 	int i;
@@ -1374,7 +1374,7 @@ static void __devinit f71805f_init_device(struct f71805f_data *data)
 	}
 }
 
-static int __devinit f71805f_probe(struct platform_device *pdev)
+static int f71805f_probe(struct platform_device *pdev)
 {
 	struct f71805f_sio_data *sio_data = pdev->dev.platform_data;
 	struct f71805f_data *data;
@@ -1490,7 +1490,7 @@ exit_remove_files:
 	return err;
 }
 
-static int __devexit f71805f_remove(struct platform_device *pdev)
+static int f71805f_remove(struct platform_device *pdev)
 {
 	struct f71805f_data *data = platform_get_drvdata(pdev);
 	int i;
@@ -1510,7 +1510,7 @@ static struct platform_driver f71805f_driver = {
 		.name	= DRVNAME,
 	},
 	.probe		= f71805f_probe,
-	.remove		= __devexit_p(f71805f_remove),
+	.remove		= f71805f_remove,
 };
 
 static int __init f71805f_device_add(unsigned short address,
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index 50e4ce2..bb7275c 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -364,7 +364,7 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev,
 static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
 	char *buf);
 
-static int __devinit f71882fg_probe(struct platform_device *pdev);
+static int f71882fg_probe(struct platform_device *pdev);
 static int f71882fg_remove(struct platform_device *pdev);
 
 static struct platform_driver f71882fg_driver = {
@@ -2145,7 +2145,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
 	return sprintf(buf, "%s\n", f71882fg_names[data->type]);
 }
 
-static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev,
+static int f71882fg_create_sysfs_files(struct platform_device *pdev,
 	struct sensor_device_attribute_2 *attr, int count)
 {
 	int err, i;
@@ -2167,7 +2167,7 @@ static void f71882fg_remove_sysfs_files(struct platform_device *pdev,
 		device_remove_file(&pdev->dev, &attr[i].dev_attr);
 }
 
-static int __devinit f71882fg_create_fan_sysfs_files(
+static int f71882fg_create_fan_sysfs_files(
 	struct platform_device *pdev, int idx)
 {
 	struct f71882fg_data *data = platform_get_drvdata(pdev);
@@ -2265,7 +2265,7 @@ static int __devinit f71882fg_create_fan_sysfs_files(
 	return err;
 }
 
-static int __devinit f71882fg_probe(struct platform_device *pdev)
+static int f71882fg_probe(struct platform_device *pdev)
 {
 	struct f71882fg_data *data;
 	struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index 4f41104..5cec685 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -111,7 +111,7 @@ static const struct attribute_group fam15h_power_attr_group = {
 	.attrs	= fam15h_power_attrs,
 };
 
-static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4)
+static bool fam15h_power_is_internal_node0(struct pci_dev *f4)
 {
 	u32 val;
 
@@ -168,7 +168,7 @@ static int fam15h_power_resume(struct pci_dev *pdev)
 #define fam15h_power_resume NULL
 #endif
 
-static void __devinit fam15h_power_init_data(struct pci_dev *f4,
+static void fam15h_power_init_data(struct pci_dev *f4,
 					     struct fam15h_power_data *data)
 {
 	u32 val;
@@ -194,7 +194,7 @@ static void __devinit fam15h_power_init_data(struct pci_dev *f4,
 	data->processor_pwr_watts = (tmp * 15625) >> 10;
 }
 
-static int __devinit fam15h_power_probe(struct pci_dev *pdev,
+static int fam15h_power_probe(struct pci_dev *pdev,
 					const struct pci_device_id *id)
 {
 	struct fam15h_power_data *data;
@@ -235,7 +235,7 @@ exit_remove_group:
 	return err;
 }
 
-static void __devexit fam15h_power_remove(struct pci_dev *pdev)
+static void fam15h_power_remove(struct pci_dev *pdev)
 {
 	struct device *dev;
 	struct fam15h_power_data *data;
@@ -256,7 +256,7 @@ static struct pci_driver fam15h_power_driver = {
 	.name = "fam15h_power",
 	.id_table = fam15h_power_id_table,
 	.probe = fam15h_power_probe,
-	.remove = __devexit_p(fam15h_power_remove),
+	.remove = fam15h_power_remove,
 	.resume = fam15h_power_resume,
 };
 
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
index 1381a2e..4e04c12 100644
--- a/drivers/hwmon/gpio-fan.c
+++ b/drivers/hwmon/gpio-fan.c
@@ -499,13 +499,13 @@ static int gpio_fan_get_of_pdata(struct device *dev,
 	return 0;
 }
 
-static struct of_device_id of_gpio_fan_match[] __devinitdata = {
+static struct of_device_id of_gpio_fan_match[] = {
 	{ .compatible = "gpio-fan", },
 	{},
 };
 #endif /* CONFIG_OF_GPIO */
 
-static int __devinit gpio_fan_probe(struct platform_device *pdev)
+static int gpio_fan_probe(struct platform_device *pdev)
 {
 	int err;
 	struct gpio_fan_data *fan_data;
@@ -581,7 +581,7 @@ err_free_alarm:
 	return err;
 }
 
-static int __devexit gpio_fan_remove(struct platform_device *pdev)
+static int gpio_fan_remove(struct platform_device *pdev)
 {
 	struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
 
@@ -626,7 +626,7 @@ static SIMPLE_DEV_PM_OPS(gpio_fan_pm, gpio_fan_suspend, gpio_fan_resume);
 
 static struct platform_driver gpio_fan_driver = {
 	.probe		= gpio_fan_probe,
-	.remove		= __devexit_p(gpio_fan_remove),
+	.remove		= gpio_fan_remove,
 	.driver	= {
 		.name	= "gpio-fan",
 		.pm	= GPIO_FAN_PM,
diff --git a/drivers/hwmon/hih6130.c b/drivers/hwmon/hih6130.c
index 9a675ef..2dc37c7 100644
--- a/drivers/hwmon/hih6130.c
+++ b/drivers/hwmon/hih6130.c
@@ -220,7 +220,7 @@ static const struct attribute_group hih6130_attr_group = {
  * device's name.
  * Returns 0 on success.
  */
-static int __devinit hih6130_probe(struct i2c_client *client,
+static int hih6130_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
 	struct hih6130 *hih6130;
@@ -263,7 +263,7 @@ fail_remove_sysfs:
  * hih6130_remove() - remove device
  * @client: I2C client device
  */
-static int __devexit hih6130_remove(struct i2c_client *client)
+static int hih6130_remove(struct i2c_client *client)
 {
 	struct hih6130 *hih6130 = i2c_get_clientdata(client);
 
@@ -283,7 +283,7 @@ MODULE_DEVICE_TABLE(i2c, hih6130_id);
 static struct i2c_driver hih6130_driver = {
 	.driver.name = "hih6130",
 	.probe       = hih6130_probe,
-	.remove      = __devexit_p(hih6130_remove),
+	.remove      = hih6130_remove,
 	.id_table    = hih6130_id,
 };
 
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index c3c471c..646314f 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -84,19 +84,21 @@ static void __init hwmon_pci_quirks(void)
 
 	/* Open access to 0x295-0x296 on MSI MS-7031 */
 	sb = pci_get_device(PCI_VENDOR_ID_ATI, 0x436c, NULL);
-	if (sb &&
-	    (sb->subsystem_vendor == 0x1462 &&	/* MSI */
-	     sb->subsystem_device == 0x0031)) {	/* MS-7031 */
-
-		pci_read_config_byte(sb, 0x48, &enable);
-		pci_read_config_word(sb, 0x64, &base);
-
-		if (base == 0 && !(enable & BIT(2))) {
-			dev_info(&sb->dev,
-				 "Opening wide generic port at 0x295\n");
-			pci_write_config_word(sb, 0x64, 0x295);
-			pci_write_config_byte(sb, 0x48, enable | BIT(2));
+	if (sb) {
+		if (sb->subsystem_vendor == 0x1462 &&	/* MSI */
+		    sb->subsystem_device == 0x0031) {	/* MS-7031 */
+			pci_read_config_byte(sb, 0x48, &enable);
+			pci_read_config_word(sb, 0x64, &base);
+
+			if (base == 0 && !(enable & BIT(2))) {
+				dev_info(&sb->dev,
+					 "Opening wide generic port at 0x295\n");
+				pci_write_config_word(sb, 0x64, 0x295);
+				pci_write_config_byte(sb, 0x48,
+						      enable | BIT(2));
+			}
 		}
+		pci_dev_put(sb);
 	}
 #endif
 }
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
index 46141ab..b87c2cc 100644
--- a/drivers/hwmon/i5k_amb.c
+++ b/drivers/hwmon/i5k_amb.c
@@ -260,7 +260,7 @@ static ssize_t show_label(struct device *dev,
 		       attr->index & DIMM_MASK);
 }
 
-static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
+static int i5k_amb_hwmon_init(struct platform_device *pdev)
 {
 	int i, j, k, d = 0;
 	u16 c;
@@ -406,7 +406,7 @@ exit_remove:
 	return res;
 }
 
-static int __devinit i5k_amb_add(void)
+static int i5k_amb_add(void)
 {
 	int res = -ENODEV;
 
@@ -425,7 +425,7 @@ err:
 	return res;
 }
 
-static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data,
+static int i5k_find_amb_registers(struct i5k_amb_data *data,
 					    unsigned long devid)
 {
 	struct pci_dev *pcidev;
@@ -459,7 +459,7 @@ out:
 	return res;
 }
 
-static int __devinit i5k_channel_probe(u16 *amb_present, unsigned long dev_id)
+static int i5k_channel_probe(u16 *amb_present, unsigned long dev_id)
 {
 	struct pci_dev *pcidev;
 	u16 val16;
@@ -488,14 +488,14 @@ out:
 static struct {
 	unsigned long err;
 	unsigned long fbd0;
-} chipset_ids[] __devinitdata  = {
+} chipset_ids[]  = {
 	{ PCI_DEVICE_ID_INTEL_5000_ERR, PCI_DEVICE_ID_INTEL_5000_FBD0 },
 	{ PCI_DEVICE_ID_INTEL_5400_ERR, PCI_DEVICE_ID_INTEL_5400_FBD0 },
 	{ 0, 0 }
 };
 
 #ifdef MODULE
-static struct pci_device_id i5k_amb_ids[] __devinitdata = {
+static struct pci_device_id i5k_amb_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR) },
 	{ 0, }
@@ -503,7 +503,7 @@ static struct pci_device_id i5k_amb_ids[] __devinitdata = {
 MODULE_DEVICE_TABLE(pci, i5k_amb_ids);
 #endif
 
-static int __devinit i5k_amb_probe(struct platform_device *pdev)
+static int i5k_amb_probe(struct platform_device *pdev)
 {
 	struct i5k_amb_data *data;
 	struct resource *reso;
@@ -564,7 +564,7 @@ err:
 	return res;
 }
 
-static int __devexit i5k_amb_remove(struct platform_device *pdev)
+static int i5k_amb_remove(struct platform_device *pdev)
 {
 	int i;
 	struct i5k_amb_data *data = platform_get_drvdata(pdev);
@@ -587,7 +587,7 @@ static struct platform_driver i5k_amb_driver = {
 		.name = DRVNAME,
 	},
 	.probe = i5k_amb_probe,
-	.remove = __devexit_p(i5k_amb_remove),
+	.remove = i5k_amb_remove,
 };
 
 static int __init i5k_amb_init(void)
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index 2b72634..8e7158c 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -302,19 +302,8 @@ static struct i2c_driver ina2xx_driver = {
 	.id_table	= ina2xx_id,
 };
 
-static int __init ina2xx_init(void)
-{
-	return i2c_add_driver(&ina2xx_driver);
-}
-
-static void __exit ina2xx_exit(void)
-{
-	i2c_del_driver(&ina2xx_driver);
-}
+module_i2c_driver(ina2xx_driver);
 
 MODULE_AUTHOR("Lothar Felten <l-felten@ti.com>");
 MODULE_DESCRIPTION("ina2xx driver");
 MODULE_LICENSE("GPL");
-
-module_init(ina2xx_init);
-module_exit(ina2xx_exit);
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index f1de397..117d66f 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -203,6 +203,8 @@ static const u8 IT87_REG_FAN[]		= { 0x0d, 0x0e, 0x0f, 0x80, 0x82 };
 static const u8 IT87_REG_FAN_MIN[]	= { 0x10, 0x11, 0x12, 0x84, 0x86 };
 static const u8 IT87_REG_FANX[]		= { 0x18, 0x19, 0x1a, 0x81, 0x83 };
 static const u8 IT87_REG_FANX_MIN[]	= { 0x1b, 0x1c, 0x1d, 0x85, 0x87 };
+static const u8 IT87_REG_TEMP_OFFSET[]	= { 0x56, 0x57, 0x59 };
+
 #define IT87_REG_FAN_MAIN_CTRL 0x13
 #define IT87_REG_FAN_CTL       0x14
 #define IT87_REG_PWM(nr)       (0x15 + (nr))
@@ -226,6 +228,83 @@ static const u8 IT87_REG_FANX_MIN[]	= { 0x1b, 0x1c, 0x1d, 0x85, 0x87 };
 #define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i))
 #define IT87_REG_AUTO_PWM(nr, i)  (0x65 + (nr) * 8 + (i))
 
+struct it87_devices {
+	const char *name;
+	u16 features;
+	u8 peci_mask;
+	u8 old_peci_mask;
+};
+
+#define FEAT_12MV_ADC		(1 << 0)
+#define FEAT_NEWER_AUTOPWM	(1 << 1)
+#define FEAT_OLD_AUTOPWM	(1 << 2)
+#define FEAT_16BIT_FANS		(1 << 3)
+#define FEAT_TEMP_OFFSET	(1 << 4)
+#define FEAT_TEMP_PECI		(1 << 5)
+#define FEAT_TEMP_OLD_PECI	(1 << 6)
+
+static const struct it87_devices it87_devices[] = {
+	[it87] = {
+		.name = "it87",
+		.features = FEAT_OLD_AUTOPWM,	/* may need to overwrite */
+	},
+	[it8712] = {
+		.name = "it8712",
+		.features = FEAT_OLD_AUTOPWM,	/* may need to overwrite */
+	},
+	[it8716] = {
+		.name = "it8716",
+		.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET,
+	},
+	[it8718] = {
+		.name = "it8718",
+		.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
+		  | FEAT_TEMP_OLD_PECI,
+		.old_peci_mask = 0x4,
+	},
+	[it8720] = {
+		.name = "it8720",
+		.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
+		  | FEAT_TEMP_OLD_PECI,
+		.old_peci_mask = 0x4,
+	},
+	[it8721] = {
+		.name = "it8721",
+		.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
+		  | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI,
+		.peci_mask = 0x05,
+		.old_peci_mask = 0x02,	/* Actually reports PCH */
+	},
+	[it8728] = {
+		.name = "it8728",
+		.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
+		  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
+		.peci_mask = 0x07,
+	},
+	[it8782] = {
+		.name = "it8782",
+		.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
+		  | FEAT_TEMP_OLD_PECI,
+		.old_peci_mask = 0x4,
+	},
+	[it8783] = {
+		.name = "it8783",
+		.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
+		  | FEAT_TEMP_OLD_PECI,
+		.old_peci_mask = 0x4,
+	},
+};
+
+#define has_16bit_fans(data)	((data)->features & FEAT_16BIT_FANS)
+#define has_12mv_adc(data)	((data)->features & FEAT_12MV_ADC)
+#define has_newer_autopwm(data)	((data)->features & FEAT_NEWER_AUTOPWM)
+#define has_old_autopwm(data)	((data)->features & FEAT_OLD_AUTOPWM)
+#define has_temp_offset(data)	((data)->features & FEAT_TEMP_OFFSET)
+#define has_temp_peci(data, nr)	(((data)->features & FEAT_TEMP_PECI) && \
+				 ((data)->peci_mask & (1 << nr)))
+#define has_temp_old_peci(data, nr) \
+				(((data)->features & FEAT_TEMP_OLD_PECI) && \
+				 ((data)->old_peci_mask & (1 << nr)))
 
 struct it87_sio_data {
 	enum chips type;
@@ -249,7 +328,9 @@ struct it87_sio_data {
 struct it87_data {
 	struct device *hwmon_dev;
 	enum chips type;
-	u8 revision;
+	u16 features;
+	u8 peci_mask;
+	u8 old_peci_mask;
 
 	unsigned short addr;
 	const char *name;
@@ -258,17 +339,13 @@ struct it87_data {
 	unsigned long last_updated;	/* In jiffies */
 
 	u16 in_scaled;		/* Internal voltage sensors are scaled */
-	u8 in[9];		/* Register value */
-	u8 in_max[8];		/* Register value */
-	u8 in_min[8];		/* Register value */
+	u8 in[9][3];		/* [nr][0]=in, [1]=min, [2]=max */
 	u8 has_fan;		/* Bitfield, fans enabled */
-	u16 fan[5];		/* Register values, possibly combined */
-	u16 fan_min[5];		/* Register values, possibly combined */
+	u16 fan[5][2];		/* Register values, [nr][0]=fan, [1]=min */
 	u8 has_temp;		/* Bitfield, temp sensors enabled */
-	s8 temp[3];		/* Register value */
-	s8 temp_high[3];	/* Register value */
-	s8 temp_low[3];		/* Register value */
-	u8 sensor;		/* Register value */
+	s8 temp[3][4];		/* [nr][0]=temp, [1]=min, [2]=max, [3]=offset */
+	u8 sensor;		/* Register value (IT87_REG_TEMP_ENABLE) */
+	u8 extra;		/* Register value (IT87_REG_TEMP_EXTRA) */
 	u8 fan_div[3];		/* Register encoding, shifted right */
 	u8 vid;			/* Register encoding, combined */
 	u8 vrm;
@@ -296,26 +373,6 @@ struct it87_data {
 	s8 auto_temp[3][5];	/* [nr][0] is point1_temp_hyst */
 };
 
-static inline int has_12mv_adc(const struct it87_data *data)
-{
-	/*
-	 * IT8721F and later have a 12 mV ADC, also with internal scaling
-	 * on selected inputs.
-	 */
-	return data->type == it8721
-	    || data->type == it8728;
-}
-
-static inline int has_newer_autopwm(const struct it87_data *data)
-{
-	/*
-	 * IT8721F and later have separate registers for the temperature
-	 * mapping and the manual duty cycle.
-	 */
-	return data->type == it8721
-	    || data->type == it8728;
-}
-
 static int adc_lsb(const struct it87_data *data, int nr)
 {
 	int lsb = has_12mv_adc(data) ? 12 : 16;
@@ -398,37 +455,8 @@ static const unsigned int pwm_freq[8] = {
 	750000 / 128,
 };
 
-static inline int has_16bit_fans(const struct it87_data *data)
-{
-	/*
-	 * IT8705F Datasheet 0.4.1, 3h == Version G.
-	 * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J.
-	 * These are the first revisions with 16-bit tachometer support.
-	 */
-	return (data->type == it87 && data->revision >= 0x03)
-	    || (data->type == it8712 && data->revision >= 0x08)
-	    || data->type == it8716
-	    || data->type == it8718
-	    || data->type == it8720
-	    || data->type == it8721
-	    || data->type == it8728
-	    || data->type == it8782
-	    || data->type == it8783;
-}
-
-static inline int has_old_autopwm(const struct it87_data *data)
-{
-	/*
-	 * The old automatic fan speed control interface is implemented
-	 * by IT8705F chips up to revision F and IT8712F chips up to
-	 * revision G.
-	 */
-	return (data->type == it87 && data->revision < 0x03)
-	    || (data->type == it8712 && data->revision < 0x08);
-}
-
 static int it87_probe(struct platform_device *pdev);
-static int __devexit it87_remove(struct platform_device *pdev);
+static int it87_remove(struct platform_device *pdev);
 
 static int it87_read_value(struct it87_data *data, u8 reg);
 static void it87_write_value(struct it87_data *data, u8 reg, u8 value);
@@ -443,63 +471,26 @@ static struct platform_driver it87_driver = {
 		.name	= DRVNAME,
 	},
 	.probe	= it87_probe,
-	.remove	= __devexit_p(it87_remove),
+	.remove	= it87_remove,
 };
 
 static ssize_t show_in(struct device *dev, struct device_attribute *attr,
-		char *buf)
-{
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
-
-	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in[nr]));
-}
-
-static ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
-		char *buf)
+		       char *buf)
 {
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
 
 	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in_min[nr]));
+	return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in[nr][index]));
 }
 
-static ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
-		char *buf)
-{
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
-
-	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in_max[nr]));
-}
-
-static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
-
-	struct it87_data *data = dev_get_drvdata(dev);
-	unsigned long val;
-
-	if (kstrtoul(buf, 10, &val) < 0)
-		return -EINVAL;
-
-	mutex_lock(&data->update_lock);
-	data->in_min[nr] = in_to_reg(data, nr, val);
-	it87_write_value(data, IT87_REG_VIN_MIN(nr),
-			data->in_min[nr]);
-	mutex_unlock(&data->update_lock);
-	return count;
-}
-static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
+static ssize_t set_in(struct device *dev, struct device_attribute *attr,
+		      const char *buf, size_t count)
 {
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
 
 	struct it87_data *data = dev_get_drvdata(dev);
 	unsigned long val;
@@ -508,140 +499,167 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
-	data->in_max[nr] = in_to_reg(data, nr, val);
-	it87_write_value(data, IT87_REG_VIN_MAX(nr),
-			data->in_max[nr]);
+	data->in[nr][index] = in_to_reg(data, nr, val);
+	it87_write_value(data,
+			 index == 1 ? IT87_REG_VIN_MIN(nr)
+				    : IT87_REG_VIN_MAX(nr),
+			 data->in[nr][index]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
-#define show_in_offset(offset)					\
-static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
-		show_in, NULL, offset);
-
-#define limit_in_offset(offset)					\
-static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,	\
-		show_in_min, set_in_min, offset);		\
-static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,	\
-		show_in_max, set_in_max, offset);
-
-show_in_offset(0);
-limit_in_offset(0);
-show_in_offset(1);
-limit_in_offset(1);
-show_in_offset(2);
-limit_in_offset(2);
-show_in_offset(3);
-limit_in_offset(3);
-show_in_offset(4);
-limit_in_offset(4);
-show_in_offset(5);
-limit_in_offset(5);
-show_in_offset(6);
-limit_in_offset(6);
-show_in_offset(7);
-limit_in_offset(7);
-show_in_offset(8);
+static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0);
+static SENSOR_DEVICE_ATTR_2(in0_min, S_IRUGO | S_IWUSR, show_in, set_in,
+			    0, 1);
+static SENSOR_DEVICE_ATTR_2(in0_max, S_IRUGO | S_IWUSR, show_in, set_in,
+			    0, 2);
+
+static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 1, 0);
+static SENSOR_DEVICE_ATTR_2(in1_min, S_IRUGO | S_IWUSR, show_in, set_in,
+			    1, 1);
+static SENSOR_DEVICE_ATTR_2(in1_max, S_IRUGO | S_IWUSR, show_in, set_in,
+			    1, 2);
+
+static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 2, 0);
+static SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_in, set_in,
+			    2, 1);
+static SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_in, set_in,
+			    2, 2);
+
+static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 3, 0);
+static SENSOR_DEVICE_ATTR_2(in3_min, S_IRUGO | S_IWUSR, show_in, set_in,
+			    3, 1);
+static SENSOR_DEVICE_ATTR_2(in3_max, S_IRUGO | S_IWUSR, show_in, set_in,
+			    3, 2);
+
+static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 4, 0);
+static SENSOR_DEVICE_ATTR_2(in4_min, S_IRUGO | S_IWUSR, show_in, set_in,
+			    4, 1);
+static SENSOR_DEVICE_ATTR_2(in4_max, S_IRUGO | S_IWUSR, show_in, set_in,
+			    4, 2);
+
+static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 5, 0);
+static SENSOR_DEVICE_ATTR_2(in5_min, S_IRUGO | S_IWUSR, show_in, set_in,
+			    5, 1);
+static SENSOR_DEVICE_ATTR_2(in5_max, S_IRUGO | S_IWUSR, show_in, set_in,
+			    5, 2);
+
+static SENSOR_DEVICE_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 6, 0);
+static SENSOR_DEVICE_ATTR_2(in6_min, S_IRUGO | S_IWUSR, show_in, set_in,
+			    6, 1);
+static SENSOR_DEVICE_ATTR_2(in6_max, S_IRUGO | S_IWUSR, show_in, set_in,
+			    6, 2);
+
+static SENSOR_DEVICE_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 7, 0);
+static SENSOR_DEVICE_ATTR_2(in7_min, S_IRUGO | S_IWUSR, show_in, set_in,
+			    7, 1);
+static SENSOR_DEVICE_ATTR_2(in7_max, S_IRUGO | S_IWUSR, show_in, set_in,
+			    7, 2);
+
+static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 8, 0);
 
 /* 3 temperatures */
 static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
-		char *buf)
+			 char *buf)
 {
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
-
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
 	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
-}
-static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
-		char *buf)
-{
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
 
-	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr]));
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr][index]));
 }
-static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
-		char *buf)
-{
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
 
-	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr]));
-}
-static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
+static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
 {
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
-
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
 	struct it87_data *data = dev_get_drvdata(dev);
 	long val;
+	u8 reg, regval;
 
 	if (kstrtol(buf, 10, &val) < 0)
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
-	data->temp_high[nr] = TEMP_TO_REG(val);
-	it87_write_value(data, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]);
-	mutex_unlock(&data->update_lock);
-	return count;
-}
-static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
 
-	struct it87_data *data = dev_get_drvdata(dev);
-	long val;
-
-	if (kstrtol(buf, 10, &val) < 0)
-		return -EINVAL;
+	switch (index) {
+	default:
+	case 1:
+		reg = IT87_REG_TEMP_LOW(nr);
+		break;
+	case 2:
+		reg = IT87_REG_TEMP_HIGH(nr);
+		break;
+	case 3:
+		regval = it87_read_value(data, IT87_REG_BEEP_ENABLE);
+		if (!(regval & 0x80)) {
+			regval |= 0x80;
+			it87_write_value(data, IT87_REG_BEEP_ENABLE, regval);
+		}
+		data->valid = 0;
+		reg = IT87_REG_TEMP_OFFSET[nr];
+		break;
+	}
 
-	mutex_lock(&data->update_lock);
-	data->temp_low[nr] = TEMP_TO_REG(val);
-	it87_write_value(data, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]);
+	data->temp[nr][index] = TEMP_TO_REG(val);
+	it87_write_value(data, reg, data->temp[nr][index]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-#define show_temp_offset(offset)					\
-static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
-		show_temp, NULL, offset - 1);				\
-static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
-		show_temp_max, set_temp_max, offset - 1);		\
-static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
-		show_temp_min, set_temp_min, offset - 1);
-
-show_temp_offset(1);
-show_temp_offset(2);
-show_temp_offset(3);
-
-static ssize_t show_sensor(struct device *dev, struct device_attribute *attr,
-		char *buf)
+
+static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
+			    0, 1);
+static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
+			    0, 2);
+static SENSOR_DEVICE_ATTR_2(temp1_offset, S_IRUGO | S_IWUSR, show_temp,
+			    set_temp, 0, 3);
+static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0);
+static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
+			    1, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
+			    1, 2);
+static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IRUGO | S_IWUSR, show_temp,
+			    set_temp, 1, 3);
+static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, 0);
+static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
+			    2, 1);
+static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
+			    2, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_offset, S_IRUGO | S_IWUSR, show_temp,
+			    set_temp, 2, 3);
+
+static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr,
+			      char *buf)
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct it87_data *data = it87_update_device(dev);
 	u8 reg = data->sensor;	    /* In case value is updated while used */
+	u8 extra = data->extra;
 
+	if ((has_temp_peci(data, nr) && (reg >> 6 == nr + 1))
+	    || (has_temp_old_peci(data, nr) && (extra & 0x80)))
+		return sprintf(buf, "6\n");  /* Intel PECI */
 	if (reg & (1 << nr))
 		return sprintf(buf, "3\n");  /* thermal diode */
 	if (reg & (8 << nr))
 		return sprintf(buf, "4\n");  /* thermistor */
 	return sprintf(buf, "0\n");      /* disabled */
 }
-static ssize_t set_sensor(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
+
+static ssize_t set_temp_type(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 
 	struct it87_data *data = dev_get_drvdata(dev);
 	long val;
-	u8 reg;
+	u8 reg, extra;
 
 	if (kstrtol(buf, 10, &val) < 0)
 		return -EINVAL;
@@ -649,33 +667,45 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr,
 	reg = it87_read_value(data, IT87_REG_TEMP_ENABLE);
 	reg &= ~(1 << nr);
 	reg &= ~(8 << nr);
+	if (has_temp_peci(data, nr) && (reg >> 6 == nr + 1 || val == 6))
+		reg &= 0x3f;
+	extra = it87_read_value(data, IT87_REG_TEMP_EXTRA);
+	if (has_temp_old_peci(data, nr) && ((extra & 0x80) || val == 6))
+		extra &= 0x7f;
 	if (val == 2) {	/* backwards compatibility */
-		dev_warn(dev, "Sensor type 2 is deprecated, please use 4 "
-			 "instead\n");
+		dev_warn(dev,
+			 "Sensor type 2 is deprecated, please use 4 instead\n");
 		val = 4;
 	}
-	/* 3 = thermal diode; 4 = thermistor; 0 = disabled */
+	/* 3 = thermal diode; 4 = thermistor; 6 = Intel PECI; 0 = disabled */
 	if (val == 3)
 		reg |= 1 << nr;
 	else if (val == 4)
 		reg |= 8 << nr;
+	else if (has_temp_peci(data, nr) && val == 6)
+		reg |= (nr + 1) << 6;
+	else if (has_temp_old_peci(data, nr) && val == 6)
+		extra |= 0x80;
 	else if (val != 0)
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
 	data->sensor = reg;
+	data->extra = extra;
 	it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor);
+	if (has_temp_old_peci(data, nr))
+		it87_write_value(data, IT87_REG_TEMP_EXTRA, data->extra);
 	data->valid = 0;	/* Force cache refresh */
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-#define show_sensor_offset(offset)					\
-static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR,	\
-		show_sensor, set_sensor, offset - 1);
 
-show_sensor_offset(1);
-show_sensor_offset(2);
-show_sensor_offset(3);
+static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO | S_IWUSR, show_temp_type,
+			  set_temp_type, 0);
+static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR, show_temp_type,
+			  set_temp_type, 1);
+static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, show_temp_type,
+			  set_temp_type, 2);
 
 /* 3 Fans */
 
@@ -692,25 +722,21 @@ static int pwm_mode(const struct it87_data *data, int nr)
 }
 
 static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
-		char *buf)
+			char *buf)
 {
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
-
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	int speed;
 	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
-				DIV_FROM_REG(data->fan_div[nr])));
-}
-static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
-		char *buf)
-{
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
 
-	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
-				DIV_FROM_REG(data->fan_div[nr])));
+	speed = has_16bit_fans(data) ?
+		FAN16_FROM_REG(data->fan[nr][index]) :
+		FAN_FROM_REG(data->fan[nr][index],
+			     DIV_FROM_REG(data->fan_div[nr]));
+	return sprintf(buf, "%d\n", speed);
 }
+
 static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
 		char *buf)
 {
@@ -747,11 +773,13 @@ static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr,
 
 	return sprintf(buf, "%u\n", pwm_freq[index]);
 }
-static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
+
+static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
 {
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
 
 	struct it87_data *data = dev_get_drvdata(dev);
 	long val;
@@ -761,24 +789,36 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
-	reg = it87_read_value(data, IT87_REG_FAN_DIV);
-	switch (nr) {
-	case 0:
-		data->fan_div[nr] = reg & 0x07;
-		break;
-	case 1:
-		data->fan_div[nr] = (reg >> 3) & 0x07;
-		break;
-	case 2:
-		data->fan_div[nr] = (reg & 0x40) ? 3 : 1;
-		break;
+
+	if (has_16bit_fans(data)) {
+		data->fan[nr][index] = FAN16_TO_REG(val);
+		it87_write_value(data, IT87_REG_FAN_MIN[nr],
+				 data->fan[nr][index] & 0xff);
+		it87_write_value(data, IT87_REG_FANX_MIN[nr],
+				 data->fan[nr][index] >> 8);
+	} else {
+		reg = it87_read_value(data, IT87_REG_FAN_DIV);
+		switch (nr) {
+		case 0:
+			data->fan_div[nr] = reg & 0x07;
+			break;
+		case 1:
+			data->fan_div[nr] = (reg >> 3) & 0x07;
+			break;
+		case 2:
+			data->fan_div[nr] = (reg & 0x40) ? 3 : 1;
+			break;
+		}
+		data->fan[nr][index] =
+		  FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
+		it87_write_value(data, IT87_REG_FAN_MIN[nr],
+				 data->fan[nr][index]);
 	}
 
-	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
-	it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan_min[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
+
 static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
@@ -797,7 +837,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 	old = it87_read_value(data, IT87_REG_FAN_DIV);
 
 	/* Save fan min limit */
-	min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
+	min = FAN_FROM_REG(data->fan[nr][1], DIV_FROM_REG(data->fan_div[nr]));
 
 	switch (nr) {
 	case 0:
@@ -818,8 +858,8 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 	it87_write_value(data, IT87_REG_FAN_DIV, val);
 
 	/* Restore fan min limit */
-	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
-	it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan_min[nr]);
+	data->fan[nr][1] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
+	it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan[nr][1]);
 
 	mutex_unlock(&data->update_lock);
 	return count;
@@ -843,8 +883,8 @@ static int check_trip_points(struct device *dev, int nr)
 	}
 
 	if (err) {
-		dev_err(dev, "Inconsistent trip points, not switching to "
-			"automatic mode\n");
+		dev_err(dev,
+			"Inconsistent trip points, not switching to automatic mode\n");
 		dev_err(dev, "Adjust the trip points and try again\n");
 	}
 	return err;
@@ -1092,118 +1132,106 @@ static ssize_t set_auto_temp(struct device *dev,
 	return count;
 }
 
-#define show_fan_offset(offset)					\
-static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,		\
-		show_fan, NULL, offset - 1);			\
-static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
-		show_fan_min, set_fan_min, offset - 1);		\
-static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
-		show_fan_div, set_fan_div, offset - 1);
-
-show_fan_offset(1);
-show_fan_offset(2);
-show_fan_offset(3);
-
-#define show_pwm_offset(offset)						\
-static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR,	\
-		show_pwm_enable, set_pwm_enable, offset - 1);		\
-static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR,		\
-		show_pwm, set_pwm, offset - 1);				\
-static DEVICE_ATTR(pwm##offset##_freq,					\
-		(offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO),		\
-		show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL));	\
-static SENSOR_DEVICE_ATTR(pwm##offset##_auto_channels_temp,		\
-		S_IRUGO | S_IWUSR, show_pwm_temp_map, set_pwm_temp_map,	\
-		offset - 1);						\
-static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_pwm,		\
-		S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm,		\
-		offset - 1, 0);						\
-static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_pwm,		\
-		S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm,		\
-		offset - 1, 1);						\
-static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_pwm,		\
-		S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm,		\
-		offset - 1, 2);						\
-static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_pwm,		\
-		S_IRUGO, show_auto_pwm, NULL, offset - 1, 3);		\
-static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp,		\
-		S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp,	\
-		offset - 1, 1);						\
-static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp_hyst,	\
-		S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp,	\
-		offset - 1, 0);						\
-static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_temp,		\
-		S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp,	\
-		offset - 1, 2);						\
-static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_temp,		\
-		S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp,	\
-		offset - 1, 3);						\
-static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_temp,		\
-		S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp,	\
-		offset - 1, 4);
-
-show_pwm_offset(1);
-show_pwm_offset(2);
-show_pwm_offset(3);
-
-/* A different set of callbacks for 16-bit fans */
-static ssize_t show_fan16(struct device *dev, struct device_attribute *attr,
-		char *buf)
-{
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
-	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", FAN16_FROM_REG(data->fan[nr]));
-}
-
-static ssize_t show_fan16_min(struct device *dev, struct device_attribute *attr,
-		char *buf)
-{
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
-	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", FAN16_FROM_REG(data->fan_min[nr]));
-}
-
-static ssize_t set_fan16_min(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
-	struct it87_data *data = dev_get_drvdata(dev);
-	long val;
-
-	if (kstrtol(buf, 10, &val) < 0)
-		return -EINVAL;
-
-	mutex_lock(&data->update_lock);
-	data->fan_min[nr] = FAN16_TO_REG(val);
-	it87_write_value(data, IT87_REG_FAN_MIN[nr],
-			 data->fan_min[nr] & 0xff);
-	it87_write_value(data, IT87_REG_FANX_MIN[nr],
-			 data->fan_min[nr] >> 8);
-	mutex_unlock(&data->update_lock);
-	return count;
-}
-
-/*
- * We want to use the same sysfs file names as 8-bit fans, but we need
- * different variable names, so we have to use SENSOR_ATTR instead of
- * SENSOR_DEVICE_ATTR.
- */
-#define show_fan16_offset(offset) \
-static struct sensor_device_attribute sensor_dev_attr_fan##offset##_input16 \
-	= SENSOR_ATTR(fan##offset##_input, S_IRUGO,		\
-		show_fan16, NULL, offset - 1);			\
-static struct sensor_device_attribute sensor_dev_attr_fan##offset##_min16 \
-	= SENSOR_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,	\
-		show_fan16_min, set_fan16_min, offset - 1)
-
-show_fan16_offset(1);
-show_fan16_offset(2);
-show_fan16_offset(3);
-show_fan16_offset(4);
-show_fan16_offset(5);
+static SENSOR_DEVICE_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0);
+static SENSOR_DEVICE_ATTR_2(fan1_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
+			    0, 1);
+static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, show_fan_div,
+			  set_fan_div, 0);
+
+static SENSOR_DEVICE_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 1, 0);
+static SENSOR_DEVICE_ATTR_2(fan2_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
+			    1, 1);
+static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, show_fan_div,
+			  set_fan_div, 1);
+
+static SENSOR_DEVICE_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 2, 0);
+static SENSOR_DEVICE_ATTR_2(fan3_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
+			    2, 1);
+static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO | S_IWUSR, show_fan_div,
+			  set_fan_div, 2);
+
+static SENSOR_DEVICE_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 3, 0);
+static SENSOR_DEVICE_ATTR_2(fan4_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
+			    3, 1);
+
+static SENSOR_DEVICE_ATTR_2(fan5_input, S_IRUGO, show_fan, NULL, 4, 0);
+static SENSOR_DEVICE_ATTR_2(fan5_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
+			    4, 1);
+
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
+			  show_pwm_enable, set_pwm_enable, 0);
+static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0);
+static DEVICE_ATTR(pwm1_freq, S_IRUGO | S_IWUSR, show_pwm_freq, set_pwm_freq);
+static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IRUGO | S_IWUSR,
+			  show_pwm_temp_map, set_pwm_temp_map, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO | S_IWUSR,
+			    show_auto_pwm, set_auto_pwm, 0, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO | S_IWUSR,
+			    show_auto_pwm, set_auto_pwm, 0, 1);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO | S_IWUSR,
+			    show_auto_pwm, set_auto_pwm, 0, 2);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO,
+			    show_auto_pwm, NULL, 0, 3);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 0, 1);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 0, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 0, 2);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 0, 3);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point4_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 0, 4);
+
+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR,
+			  show_pwm_enable, set_pwm_enable, 1);
+static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1);
+static DEVICE_ATTR(pwm2_freq, S_IRUGO, show_pwm_freq, NULL);
+static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IRUGO | S_IWUSR,
+			  show_pwm_temp_map, set_pwm_temp_map, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO | S_IWUSR,
+			    show_auto_pwm, set_auto_pwm, 1, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO | S_IWUSR,
+			    show_auto_pwm, set_auto_pwm, 1, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO | S_IWUSR,
+			    show_auto_pwm, set_auto_pwm, 1, 2);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO,
+			    show_auto_pwm, NULL, 1, 3);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 1, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 1, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 1, 2);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 1, 3);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point4_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 1, 4);
+
+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR,
+			  show_pwm_enable, set_pwm_enable, 2);
+static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 2);
+static DEVICE_ATTR(pwm3_freq, S_IRUGO, show_pwm_freq, NULL);
+static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IRUGO | S_IWUSR,
+			  show_pwm_temp_map, set_pwm_temp_map, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO | S_IWUSR,
+			    show_auto_pwm, set_auto_pwm, 2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO | S_IWUSR,
+			    show_auto_pwm, set_auto_pwm, 2, 1);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO | S_IWUSR,
+			    show_auto_pwm, set_auto_pwm, 2, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO,
+			    show_auto_pwm, NULL, 2, 3);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 1);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 3);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point4_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 4);
 
 /* Alarms */
 static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
@@ -1471,6 +1499,12 @@ static const struct attribute_group it87_group_temp[3] = {
 	{ .attrs = it87_attributes_temp[2] },
 };
 
+static struct attribute *it87_attributes_temp_offset[] = {
+	&sensor_dev_attr_temp1_offset.dev_attr.attr,
+	&sensor_dev_attr_temp2_offset.dev_attr.attr,
+	&sensor_dev_attr_temp3_offset.dev_attr.attr,
+};
+
 static struct attribute *it87_attributes[] = {
 	&dev_attr_alarms.attr,
 	&sensor_dev_attr_intrusion0_alarm.dev_attr.attr,
@@ -1500,73 +1534,47 @@ static struct attribute *it87_attributes_temp_beep[] = {
 	&sensor_dev_attr_temp3_beep.dev_attr.attr,
 };
 
-static struct attribute *it87_attributes_fan16[5][3+1] = { {
-	&sensor_dev_attr_fan1_input16.dev_attr.attr,
-	&sensor_dev_attr_fan1_min16.dev_attr.attr,
+static struct attribute *it87_attributes_fan[5][3+1] = { {
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
 	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
 	NULL
 }, {
-	&sensor_dev_attr_fan2_input16.dev_attr.attr,
-	&sensor_dev_attr_fan2_min16.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
 	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
 	NULL
 }, {
-	&sensor_dev_attr_fan3_input16.dev_attr.attr,
-	&sensor_dev_attr_fan3_min16.dev_attr.attr,
+	&sensor_dev_attr_fan3_input.dev_attr.attr,
+	&sensor_dev_attr_fan3_min.dev_attr.attr,
 	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
 	NULL
 }, {
-	&sensor_dev_attr_fan4_input16.dev_attr.attr,
-	&sensor_dev_attr_fan4_min16.dev_attr.attr,
+	&sensor_dev_attr_fan4_input.dev_attr.attr,
+	&sensor_dev_attr_fan4_min.dev_attr.attr,
 	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
 	NULL
 }, {
-	&sensor_dev_attr_fan5_input16.dev_attr.attr,
-	&sensor_dev_attr_fan5_min16.dev_attr.attr,
+	&sensor_dev_attr_fan5_input.dev_attr.attr,
+	&sensor_dev_attr_fan5_min.dev_attr.attr,
 	&sensor_dev_attr_fan5_alarm.dev_attr.attr,
 	NULL
 } };
 
-static const struct attribute_group it87_group_fan16[5] = {
-	{ .attrs = it87_attributes_fan16[0] },
-	{ .attrs = it87_attributes_fan16[1] },
-	{ .attrs = it87_attributes_fan16[2] },
-	{ .attrs = it87_attributes_fan16[3] },
-	{ .attrs = it87_attributes_fan16[4] },
+static const struct attribute_group it87_group_fan[5] = {
+	{ .attrs = it87_attributes_fan[0] },
+	{ .attrs = it87_attributes_fan[1] },
+	{ .attrs = it87_attributes_fan[2] },
+	{ .attrs = it87_attributes_fan[3] },
+	{ .attrs = it87_attributes_fan[4] },
 };
 
-static struct attribute *it87_attributes_fan[3][4+1] = { {
-	&sensor_dev_attr_fan1_input.dev_attr.attr,
-	&sensor_dev_attr_fan1_min.dev_attr.attr,
+static const struct attribute *it87_attributes_fan_div[] = {
 	&sensor_dev_attr_fan1_div.dev_attr.attr,
-	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
-	NULL
-}, {
-	&sensor_dev_attr_fan2_input.dev_attr.attr,
-	&sensor_dev_attr_fan2_min.dev_attr.attr,
 	&sensor_dev_attr_fan2_div.dev_attr.attr,
-	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
-	NULL
-}, {
-	&sensor_dev_attr_fan3_input.dev_attr.attr,
-	&sensor_dev_attr_fan3_min.dev_attr.attr,
 	&sensor_dev_attr_fan3_div.dev_attr.attr,
-	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
-	NULL
-} };
-
-static const struct attribute_group it87_group_fan[3] = {
-	{ .attrs = it87_attributes_fan[0] },
-	{ .attrs = it87_attributes_fan[1] },
-	{ .attrs = it87_attributes_fan[2] },
 };
 
-static const struct attribute_group *
-it87_get_fan_group(const struct it87_data *data)
-{
-	return has_16bit_fans(data) ? it87_group_fan16 : it87_group_fan;
-}
-
 static struct attribute *it87_attributes_pwm[3][4+1] = { {
 	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
 	&sensor_dev_attr_pwm1.dev_attr.attr,
@@ -1925,7 +1933,6 @@ static void it87_remove_files(struct device *dev)
 {
 	struct it87_data *data = platform_get_drvdata(pdev);
 	struct it87_sio_data *sio_data = dev->platform_data;
-	const struct attribute_group *fan_group = it87_get_fan_group(data);
 	int i;
 
 	sysfs_remove_group(&dev->kobj, &it87_group);
@@ -1941,6 +1948,9 @@ static void it87_remove_files(struct device *dev)
 		if (!(data->has_temp & (1 << i)))
 			continue;
 		sysfs_remove_group(&dev->kobj, &it87_group_temp[i]);
+		if (has_temp_offset(data))
+			sysfs_remove_file(&dev->kobj,
+					  it87_attributes_temp_offset[i]);
 		if (sio_data->beep_pin)
 			sysfs_remove_file(&dev->kobj,
 					  it87_attributes_temp_beep[i]);
@@ -1948,10 +1958,13 @@ static void it87_remove_files(struct device *dev)
 	for (i = 0; i < 5; i++) {
 		if (!(data->has_fan & (1 << i)))
 			continue;
-		sysfs_remove_group(&dev->kobj, &fan_group[i]);
+		sysfs_remove_group(&dev->kobj, &it87_group_fan[i]);
 		if (sio_data->beep_pin)
 			sysfs_remove_file(&dev->kobj,
 					  it87_attributes_fan_beep[i]);
+		if (i < 3 && !has_16bit_fans(data))
+			sysfs_remove_file(&dev->kobj,
+					  it87_attributes_fan_div[i]);
 	}
 	for (i = 0; i < 3; i++) {
 		if (sio_data->skip_pwm & (1 << 0))
@@ -1966,27 +1979,15 @@ static void it87_remove_files(struct device *dev)
 	sysfs_remove_group(&dev->kobj, &it87_group_label);
 }
 
-static int __devinit it87_probe(struct platform_device *pdev)
+static int it87_probe(struct platform_device *pdev)
 {
 	struct it87_data *data;
 	struct resource *res;
 	struct device *dev = &pdev->dev;
 	struct it87_sio_data *sio_data = dev->platform_data;
-	const struct attribute_group *fan_group;
 	int err = 0, i;
 	int enable_pwm_interface;
 	int fan_beep_need_rw;
-	static const char * const names[] = {
-		"it87",
-		"it8712",
-		"it8716",
-		"it8718",
-		"it8720",
-		"it8721",
-		"it8728",
-		"it8782",
-		"it8783",
-	};
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT,
@@ -2003,8 +2004,31 @@ static int __devinit it87_probe(struct platform_device *pdev)
 
 	data->addr = res->start;
 	data->type = sio_data->type;
-	data->revision = sio_data->revision;
-	data->name = names[sio_data->type];
+	data->features = it87_devices[sio_data->type].features;
+	data->peci_mask = it87_devices[sio_data->type].peci_mask;
+	data->old_peci_mask = it87_devices[sio_data->type].old_peci_mask;
+	data->name = it87_devices[sio_data->type].name;
+	/*
+	 * IT8705F Datasheet 0.4.1, 3h == Version G.
+	 * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J.
+	 * These are the first revisions with 16-bit tachometer support.
+	 */
+	switch (data->type) {
+	case it87:
+		if (sio_data->revision >= 0x03) {
+			data->features &= ~FEAT_OLD_AUTOPWM;
+			data->features |= FEAT_16BIT_FANS;
+		}
+		break;
+	case it8712:
+		if (sio_data->revision >= 0x08) {
+			data->features &= ~FEAT_OLD_AUTOPWM;
+			data->features |= FEAT_16BIT_FANS;
+		}
+		break;
+	default:
+		break;
+	}
 
 	/* Now, we do the remaining detection. */
 	if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80)
@@ -2068,6 +2092,12 @@ static int __devinit it87_probe(struct platform_device *pdev)
 		err = sysfs_create_group(&dev->kobj, &it87_group_temp[i]);
 		if (err)
 			goto error;
+		if (has_temp_offset(data)) {
+			err = sysfs_create_file(&dev->kobj,
+						it87_attributes_temp_offset[i]);
+			if (err)
+				goto error;
+		}
 		if (sio_data->beep_pin) {
 			err = sysfs_create_file(&dev->kobj,
 						it87_attributes_temp_beep[i]);
@@ -2077,15 +2107,21 @@ static int __devinit it87_probe(struct platform_device *pdev)
 	}
 
 	/* Do not create fan files for disabled fans */
-	fan_group = it87_get_fan_group(data);
 	fan_beep_need_rw = 1;
 	for (i = 0; i < 5; i++) {
 		if (!(data->has_fan & (1 << i)))
 			continue;
-		err = sysfs_create_group(&dev->kobj, &fan_group[i]);
+		err = sysfs_create_group(&dev->kobj, &it87_group_fan[i]);
 		if (err)
 			goto error;
 
+		if (i < 3 && !has_16bit_fans(data)) {
+			err = sysfs_create_file(&dev->kobj,
+						it87_attributes_fan_div[i]);
+			if (err)
+				goto error;
+		}
+
 		if (sio_data->beep_pin) {
 			err = sysfs_create_file(&dev->kobj,
 						it87_attributes_fan_beep[i]);
@@ -2158,7 +2194,7 @@ error:
 	return err;
 }
 
-static int __devexit it87_remove(struct platform_device *pdev)
+static int it87_remove(struct platform_device *pdev)
 {
 	struct it87_data *data = platform_get_drvdata(pdev);
 
@@ -2191,7 +2227,7 @@ static void it87_write_value(struct it87_data *data, u8 reg, u8 value)
 }
 
 /* Return 1 if and only if the PWM interface is safe to use */
-static int __devinit it87_check_pwm(struct device *dev)
+static int it87_check_pwm(struct device *dev)
 {
 	struct it87_data *data = dev_get_drvdata(dev);
 	/*
@@ -2221,8 +2257,8 @@ static int __devinit it87_check_pwm(struct device *dev)
 			 * PWM interface).
 			 */
 			if (!((pwm[0] | pwm[1] | pwm[2]) & 0x80)) {
-				dev_info(dev, "Reconfiguring PWM to "
-					 "active high polarity\n");
+				dev_info(dev,
+					 "Reconfiguring PWM to active high polarity\n");
 				it87_write_value(data, IT87_REG_FAN_CTL,
 						 tmp | 0x87);
 				for (i = 0; i < 3; i++)
@@ -2232,23 +2268,23 @@ static int __devinit it87_check_pwm(struct device *dev)
 				return 1;
 			}
 
-			dev_info(dev, "PWM configuration is "
-				 "too broken to be fixed\n");
+			dev_info(dev,
+				 "PWM configuration is too broken to be fixed\n");
 		}
 
-		dev_info(dev, "Detected broken BIOS "
-			 "defaults, disabling PWM interface\n");
+		dev_info(dev,
+			 "Detected broken BIOS defaults, disabling PWM interface\n");
 		return 0;
 	} else if (fix_pwm_polarity) {
-		dev_info(dev, "PWM configuration looks "
-			 "sane, won't touch\n");
+		dev_info(dev,
+			 "PWM configuration looks sane, won't touch\n");
 	}
 
 	return 1;
 }
 
 /* Called when we have found a new IT87. */
-static void __devinit it87_init_device(struct platform_device *pdev)
+static void it87_init_device(struct platform_device *pdev)
 {
 	struct it87_sio_data *sio_data = pdev->dev.platform_data;
 	struct it87_data *data = platform_get_drvdata(pdev);
@@ -2389,42 +2425,46 @@ static struct it87_data *it87_update_device(struct device *dev)
 				it87_read_value(data, IT87_REG_CONFIG) | 0x40);
 		}
 		for (i = 0; i <= 7; i++) {
-			data->in[i] =
+			data->in[i][0] =
 				it87_read_value(data, IT87_REG_VIN(i));
-			data->in_min[i] =
+			data->in[i][1] =
 				it87_read_value(data, IT87_REG_VIN_MIN(i));
-			data->in_max[i] =
+			data->in[i][2] =
 				it87_read_value(data, IT87_REG_VIN_MAX(i));
 		}
 		/* in8 (battery) has no limit registers */
-		data->in[8] = it87_read_value(data, IT87_REG_VIN(8));
+		data->in[8][0] = it87_read_value(data, IT87_REG_VIN(8));
 
 		for (i = 0; i < 5; i++) {
 			/* Skip disabled fans */
 			if (!(data->has_fan & (1 << i)))
 				continue;
 
-			data->fan_min[i] =
+			data->fan[i][1] =
 				it87_read_value(data, IT87_REG_FAN_MIN[i]);
-			data->fan[i] = it87_read_value(data,
+			data->fan[i][0] = it87_read_value(data,
 				       IT87_REG_FAN[i]);
 			/* Add high byte if in 16-bit mode */
 			if (has_16bit_fans(data)) {
-				data->fan[i] |= it87_read_value(data,
+				data->fan[i][0] |= it87_read_value(data,
 						IT87_REG_FANX[i]) << 8;
-				data->fan_min[i] |= it87_read_value(data,
+				data->fan[i][1] |= it87_read_value(data,
 						IT87_REG_FANX_MIN[i]) << 8;
 			}
 		}
 		for (i = 0; i < 3; i++) {
 			if (!(data->has_temp & (1 << i)))
 				continue;
-			data->temp[i] =
+			data->temp[i][0] =
 				it87_read_value(data, IT87_REG_TEMP(i));
-			data->temp_high[i] =
-				it87_read_value(data, IT87_REG_TEMP_HIGH(i));
-			data->temp_low[i] =
+			data->temp[i][1] =
 				it87_read_value(data, IT87_REG_TEMP_LOW(i));
+			data->temp[i][2] =
+				it87_read_value(data, IT87_REG_TEMP_HIGH(i));
+			if (has_temp_offset(data))
+				data->temp[i][3] =
+				  it87_read_value(data,
+						  IT87_REG_TEMP_OFFSET[i]);
 		}
 
 		/* Newer chips don't have clock dividers */
@@ -2448,6 +2488,7 @@ static struct it87_data *it87_update_device(struct device *dev)
 			it87_update_pwm_ctrl(data, i);
 
 		data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE);
+		data->extra = it87_read_value(data, IT87_REG_TEMP_EXTRA);
 		/*
 		 * The IT8705F does not have VID capability.
 		 * The IT8718F and later don't use IT87_REG_VID for the
@@ -2549,8 +2590,7 @@ static void __exit sm_it87_exit(void)
 }
 
 
-MODULE_AUTHOR("Chris Gauthron, "
-	      "Jean Delvare <khali@linux-fr.org>");
+MODULE_AUTHOR("Chris Gauthron, Jean Delvare <khali@linux-fr.org>");
 MODULE_DESCRIPTION("IT8705F/IT871xF/IT872xF hardware monitoring driver");
 module_param(update_vbat, bool, 0);
 MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c
index dee9eec..e0d66b9 100644
--- a/drivers/hwmon/jz4740-hwmon.c
+++ b/drivers/hwmon/jz4740-hwmon.c
@@ -102,7 +102,7 @@ static const struct attribute_group jz4740_hwmon_attr_group = {
 	.attrs = jz4740_hwmon_attributes,
 };
 
-static int __devinit jz4740_hwmon_probe(struct platform_device *pdev)
+static int jz4740_hwmon_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct jz4740_hwmon *hwmon;
@@ -172,7 +172,7 @@ err_remove_file:
 	return ret;
 }
 
-static int __devexit jz4740_hwmon_remove(struct platform_device *pdev)
+static int jz4740_hwmon_remove(struct platform_device *pdev)
 {
 	struct jz4740_hwmon *hwmon = platform_get_drvdata(pdev);
 
@@ -184,7 +184,7 @@ static int __devexit jz4740_hwmon_remove(struct platform_device *pdev)
 
 static struct platform_driver jz4740_hwmon_driver = {
 	.probe	= jz4740_hwmon_probe,
-	.remove = __devexit_p(jz4740_hwmon_remove),
+	.remove = jz4740_hwmon_remove,
 	.driver = {
 		.name = "jz4740-hwmon",
 		.owner = THIS_MODULE,
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index f2fe807..e3b037c 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -95,7 +95,7 @@ static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1);
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
-static bool __devinit has_erratum_319(struct pci_dev *pdev)
+static bool has_erratum_319(struct pci_dev *pdev)
 {
 	u32 pkg_type, reg_dram_cfg;
 
@@ -129,7 +129,7 @@ static bool __devinit has_erratum_319(struct pci_dev *pdev)
 	       (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_mask <= 2);
 }
 
-static int __devinit k10temp_probe(struct pci_dev *pdev,
+static int k10temp_probe(struct pci_dev *pdev,
 				   const struct pci_device_id *id)
 {
 	struct device *hwmon_dev;
@@ -192,7 +192,7 @@ exit:
 	return err;
 }
 
-static void __devexit k10temp_remove(struct pci_dev *pdev)
+static void k10temp_remove(struct pci_dev *pdev)
 {
 	hwmon_device_unregister(pci_get_drvdata(pdev));
 	device_remove_file(&pdev->dev, &dev_attr_name);
@@ -219,7 +219,7 @@ static struct pci_driver k10temp_driver = {
 	.name = "k10temp",
 	.id_table = k10temp_id_table,
 	.probe = k10temp_probe,
-	.remove = __devexit_p(k10temp_remove),
+	.remove = k10temp_remove,
 };
 
 module_pci_driver(k10temp_driver);
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index e8c7fb0..9f3c0ae 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -142,7 +142,7 @@ static DEFINE_PCI_DEVICE_TABLE(k8temp_ids) = {
 
 MODULE_DEVICE_TABLE(pci, k8temp_ids);
 
-static int __devinit is_rev_g_desktop(u8 model)
+static int is_rev_g_desktop(u8 model)
 {
 	u32 brandidx;
 
@@ -173,7 +173,7 @@ static int __devinit is_rev_g_desktop(u8 model)
 	return 1;
 }
 
-static int __devinit k8temp_probe(struct pci_dev *pdev,
+static int k8temp_probe(struct pci_dev *pdev,
 				  const struct pci_device_id *id)
 {
 	int err;
@@ -304,7 +304,7 @@ exit_remove:
 	return err;
 }
 
-static void __devexit k8temp_remove(struct pci_dev *pdev)
+static void k8temp_remove(struct pci_dev *pdev)
 {
 	struct k8temp_data *data = pci_get_drvdata(pdev);
 
@@ -324,7 +324,7 @@ static struct pci_driver k8temp_driver = {
 	.name = "k8temp",
 	.id_table = k8temp_ids,
 	.probe = k8temp_probe,
-	.remove = __devexit_p(k8temp_remove),
+	.remove = k8temp_remove,
 };
 
 module_pci_driver(k8temp_driver);
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index 2d1777a..016efa2 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -131,7 +131,7 @@ static DEVICE_ATTR(name, S_IRUGO, lm70_show_name, NULL);
 
 /*----------------------------------------------------------------------*/
 
-static int __devinit lm70_probe(struct spi_device *spi)
+static int lm70_probe(struct spi_device *spi)
 {
 	int chip = spi_get_device_id(spi)->driver_data;
 	struct lm70 *p_lm70;
@@ -178,7 +178,7 @@ out_dev_create_temp_file_failed:
 	return status;
 }
 
-static int __devexit lm70_remove(struct spi_device *spi)
+static int lm70_remove(struct spi_device *spi)
 {
 	struct lm70 *p_lm70 = spi_get_drvdata(spi);
 
@@ -207,7 +207,7 @@ static struct spi_driver lm70_driver = {
 	},
 	.id_table = lm70_ids,
 	.probe	= lm70_probe,
-	.remove	= __devexit_p(lm70_remove),
+	.remove	= lm70_remove,
 };
 
 module_spi_driver(lm70_driver);
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index c6ffafe..53d6ee8 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -833,7 +833,7 @@ static struct lm78_data *lm78_update_device(struct device *dev)
 }
 
 #ifdef CONFIG_ISA
-static int __devinit lm78_isa_probe(struct platform_device *pdev)
+static int lm78_isa_probe(struct platform_device *pdev)
 {
 	int err;
 	struct lm78_data *data;
@@ -886,7 +886,7 @@ static int __devinit lm78_isa_probe(struct platform_device *pdev)
 	return err;
 }
 
-static int __devexit lm78_isa_remove(struct platform_device *pdev)
+static int lm78_isa_remove(struct platform_device *pdev)
 {
 	struct lm78_data *data = platform_get_drvdata(pdev);
 
@@ -903,7 +903,7 @@ static struct platform_driver lm78_isa_driver = {
 		.name	= "lm78",
 	},
 	.probe		= lm78_isa_probe,
-	.remove		= __devexit_p(lm78_isa_remove),
+	.remove		= lm78_isa_remove,
 };
 
 /* return 1 if a supported chip is found, 0 otherwise */
diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c
index b4eb088..eda077d 100644
--- a/drivers/hwmon/max1111.c
+++ b/drivers/hwmon/max1111.c
@@ -157,7 +157,7 @@ static const struct attribute_group max1110_attr_group = {
 	.attrs	= max1110_attributes,
 };
 
-static int __devinit setup_transfer(struct max1111_data *data)
+static int setup_transfer(struct max1111_data *data)
 {
 	struct spi_message *m;
 	struct spi_transfer *x;
@@ -179,7 +179,7 @@ static int __devinit setup_transfer(struct max1111_data *data)
 	return 0;
 }
 
-static int __devinit max1111_probe(struct spi_device *spi)
+static int max1111_probe(struct spi_device *spi)
 {
 	enum chips chip = spi_get_device_id(spi)->driver_data;
 	struct max1111_data *data;
@@ -256,7 +256,7 @@ err_remove:
 	return err;
 }
 
-static int __devexit max1111_remove(struct spi_device *spi)
+static int max1111_remove(struct spi_device *spi)
 {
 	struct max1111_data *data = spi_get_drvdata(spi);
 
@@ -283,7 +283,7 @@ static struct spi_driver max1111_driver = {
 	},
 	.id_table	= max1111_ids,
 	.probe		= max1111_probe,
-	.remove		= __devexit_p(max1111_remove),
+	.remove		= max1111_remove,
 };
 
 module_spi_driver(max1111_driver);
diff --git a/drivers/hwmon/max197.c b/drivers/hwmon/max197.c
index 6304f26..b5ebb91 100644
--- a/drivers/hwmon/max197.c
+++ b/drivers/hwmon/max197.c
@@ -257,7 +257,7 @@ static const struct attribute_group max197_sysfs_group = {
 	},
 };
 
-static int __devinit max197_probe(struct platform_device *pdev)
+static int max197_probe(struct platform_device *pdev)
 {
 	int ch, ret;
 	struct max197_data *data;
@@ -316,7 +316,7 @@ error:
 	return ret;
 }
 
-static int __devexit max197_remove(struct platform_device *pdev)
+static int max197_remove(struct platform_device *pdev)
 {
 	struct max197_data *data = platform_get_drvdata(pdev);
 
@@ -339,7 +339,7 @@ static struct platform_driver max197_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = max197_probe,
-	.remove = __devexit_p(max197_remove),
+	.remove = max197_remove,
 	.id_table = max197_device_ids,
 };
 module_platform_driver(max197_driver);
diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c
index cf47a59..2a7f331 100644
--- a/drivers/hwmon/mc13783-adc.c
+++ b/drivers/hwmon/mc13783-adc.c
@@ -233,7 +233,7 @@ out_err_create_16chans:
 	return ret;
 }
 
-static int __devexit mc13783_adc_remove(struct platform_device *pdev)
+static int mc13783_adc_remove(struct platform_device *pdev)
 {
 	struct mc13783_adc_priv *priv = platform_get_drvdata(pdev);
 	kernel_ulong_t driver_data = platform_get_device_id(pdev)->driver_data;
@@ -265,7 +265,7 @@ static const struct platform_device_id mc13783_adc_idtable[] = {
 MODULE_DEVICE_TABLE(platform, mc13783_adc_idtable);
 
 static struct platform_driver mc13783_adc_driver = {
-	.remove		= __devexit_p(mc13783_adc_remove),
+	.remove		= mc13783_adc_remove,
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= DRIVER_NAME,
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index 74a6c58..a87eb89 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -309,7 +309,7 @@ static const struct attribute_group ntc_attr_group = {
 	.attrs = ntc_attributes,
 };
 
-static int __devinit ntc_thermistor_probe(struct platform_device *pdev)
+static int ntc_thermistor_probe(struct platform_device *pdev)
 {
 	struct ntc_data *data;
 	struct ntc_thermistor_platform_data *pdata = pdev->dev.platform_data;
@@ -393,7 +393,7 @@ err_after_sysfs:
 	return ret;
 }
 
-static int __devexit ntc_thermistor_remove(struct platform_device *pdev)
+static int ntc_thermistor_remove(struct platform_device *pdev)
 {
 	struct ntc_data *data = platform_get_drvdata(pdev);
 
@@ -419,7 +419,7 @@ static struct platform_driver ntc_thermistor_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ntc_thermistor_probe,
-	.remove = __devexit_p(ntc_thermistor_remove),
+	.remove = ntc_thermistor_remove,
 	.id_table = ntc_thermistor_id,
 };
 
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 91d5b2a..e35856b 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -228,7 +228,7 @@ struct pc87360_data {
  */
 
 static int pc87360_probe(struct platform_device *pdev);
-static int __devexit pc87360_remove(struct platform_device *pdev);
+static int pc87360_remove(struct platform_device *pdev);
 
 static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
 			      u8 reg);
@@ -248,7 +248,7 @@ static struct platform_driver pc87360_driver = {
 		.name	= "pc87360",
 	},
 	.probe		= pc87360_probe,
-	.remove		= __devexit_p(pc87360_remove),
+	.remove		= pc87360_remove,
 };
 
 /*
@@ -1221,7 +1221,7 @@ static void pc87360_remove_files(struct device *dev)
 	sysfs_remove_group(&dev->kobj, &pc8736x_vin_group);
 }
 
-static int __devinit pc87360_probe(struct platform_device *pdev)
+static int pc87360_probe(struct platform_device *pdev)
 {
 	int i;
 	struct pc87360_data *data;
@@ -1375,7 +1375,7 @@ error:
 	return err;
 }
 
-static int __devexit pc87360_remove(struct platform_device *pdev)
+static int pc87360_remove(struct platform_device *pdev)
 {
 	struct pc87360_data *data = platform_get_drvdata(pdev);
 
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
index f185b1f..6086ad0 100644
--- a/drivers/hwmon/pc87427.c
+++ b/drivers/hwmon/pc87427.c
@@ -956,7 +956,7 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
  * Device detection, attach and detach
  */
 
-static int __devinit pc87427_request_regions(struct platform_device *pdev,
+static int pc87427_request_regions(struct platform_device *pdev,
 					     int count)
 {
 	struct resource *res;
@@ -980,7 +980,7 @@ static int __devinit pc87427_request_regions(struct platform_device *pdev,
 	return 0;
 }
 
-static void __devinit pc87427_init_device(struct device *dev)
+static void pc87427_init_device(struct device *dev)
 {
 	struct pc87427_sio_data *sio_data = dev->platform_data;
 	struct pc87427_data *data = dev_get_drvdata(dev);
@@ -1072,7 +1072,7 @@ static void pc87427_remove_files(struct device *dev)
 	}
 }
 
-static int __devinit pc87427_probe(struct platform_device *pdev)
+static int pc87427_probe(struct platform_device *pdev)
 {
 	struct pc87427_sio_data *sio_data = pdev->dev.platform_data;
 	struct pc87427_data *data;
@@ -1141,7 +1141,7 @@ exit_remove_files:
 	return err;
 }
 
-static int __devexit pc87427_remove(struct platform_device *pdev)
+static int pc87427_remove(struct platform_device *pdev)
 {
 	struct pc87427_data *data = platform_get_drvdata(pdev);
 
@@ -1158,7 +1158,7 @@ static struct platform_driver pc87427_driver = {
 		.name	= DRVNAME,
 	},
 	.probe		= pc87427_probe,
-	.remove		= __devexit_p(pc87427_remove),
+	.remove		= pc87427_remove,
 };
 
 static int __init pc87427_device_add(const struct pc87427_sio_data *sio_data)
diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c
index bcecd02..ff2ae02 100644
--- a/drivers/hwmon/s3c-hwmon.c
+++ b/drivers/hwmon/s3c-hwmon.c
@@ -275,7 +275,7 @@ static void s3c_hwmon_remove_attr(struct device *dev,
  * s3c_hwmon_probe - device probe entry.
  * @dev: The device being probed.
 */
-static int __devinit s3c_hwmon_probe(struct platform_device *dev)
+static int s3c_hwmon_probe(struct platform_device *dev)
 {
 	struct s3c_hwmon_pdata *pdata = dev->dev.platform_data;
 	struct s3c_hwmon *hwmon;
@@ -364,7 +364,7 @@ static int __devinit s3c_hwmon_probe(struct platform_device *dev)
 	return ret;
 }
 
-static int __devexit s3c_hwmon_remove(struct platform_device *dev)
+static int s3c_hwmon_remove(struct platform_device *dev)
 {
 	struct s3c_hwmon *hwmon = platform_get_drvdata(dev);
 	int i;
@@ -386,7 +386,7 @@ static struct platform_driver s3c_hwmon_driver = {
 		.owner		= THIS_MODULE,
 	},
 	.probe		= s3c_hwmon_probe,
-	.remove		= __devexit_p(s3c_hwmon_remove),
+	.remove		= s3c_hwmon_remove,
 };
 
 module_platform_driver(s3c_hwmon_driver);
diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c
index 49f6230..0cc99fd 100644
--- a/drivers/hwmon/sch5627.c
+++ b/drivers/hwmon/sch5627.c
@@ -153,7 +153,7 @@ abort:
 	return ret;
 }
 
-static int __devinit sch5627_read_limits(struct sch5627_data *data)
+static int sch5627_read_limits(struct sch5627_data *data)
 {
 	int i, val;
 
@@ -465,7 +465,7 @@ static int sch5627_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devinit sch5627_probe(struct platform_device *pdev)
+static int sch5627_probe(struct platform_device *pdev)
 {
 	struct sch5627_data *data;
 	int err, build_code, build_id, hwmon_rev, val;
diff --git a/drivers/hwmon/sch5636.c b/drivers/hwmon/sch5636.c
index 5171180..547b5c9 100644
--- a/drivers/hwmon/sch5636.c
+++ b/drivers/hwmon/sch5636.c
@@ -405,7 +405,7 @@ static int sch5636_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devinit sch5636_probe(struct platform_device *pdev)
+static int sch5636_probe(struct platform_device *pdev)
 {
 	struct sch5636_data *data;
 	int i, err, val, revision[2];
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
index 07a0c1a..1c85d39 100644
--- a/drivers/hwmon/sht15.c
+++ b/drivers/hwmon/sht15.c
@@ -884,7 +884,7 @@ static int sht15_invalidate_voltage(struct notifier_block *nb,
 	return NOTIFY_OK;
 }
 
-static int __devinit sht15_probe(struct platform_device *pdev)
+static int sht15_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct sht15_data *data;
@@ -1002,7 +1002,7 @@ err_release_reg:
 	return ret;
 }
 
-static int __devexit sht15_remove(struct platform_device *pdev)
+static int sht15_remove(struct platform_device *pdev)
 {
 	struct sht15_data *data = platform_get_drvdata(pdev);
 
@@ -1043,7 +1043,7 @@ static struct platform_driver sht15_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = sht15_probe,
-	.remove = __devexit_p(sht15_remove),
+	.remove = sht15_remove,
 	.id_table = sht15_device_ids,
 };
 module_platform_driver(sht15_driver);
diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c
index 5f67546..2e9f957 100644
--- a/drivers/hwmon/sht21.c
+++ b/drivers/hwmon/sht21.c
@@ -187,7 +187,7 @@ static const struct attribute_group sht21_attr_group = {
  * device's name.
  * Returns 0 on success.
  */
-static int __devinit sht21_probe(struct i2c_client *client,
+static int sht21_probe(struct i2c_client *client,
 	const struct i2c_device_id *id)
 {
 	struct sht21 *sht21;
@@ -233,7 +233,7 @@ fail_remove_sysfs:
  * sht21_remove() - remove device
  * @client: I2C client device
  */
-static int __devexit sht21_remove(struct i2c_client *client)
+static int sht21_remove(struct i2c_client *client)
 {
 	struct sht21 *sht21 = i2c_get_clientdata(client);
 
@@ -253,7 +253,7 @@ MODULE_DEVICE_TABLE(i2c, sht21_id);
 static struct i2c_driver sht21_driver = {
 	.driver.name = "sht21",
 	.probe       = sht21_probe,
-	.remove      = __devexit_p(sht21_remove),
+	.remove      = sht21_remove,
 	.id_table    = sht21_id,
 };
 
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 8275f0e..06ce3c9 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -204,7 +204,7 @@ struct sis5595_data {
 static struct pci_dev *s_bridge;	/* pointer to the (only) sis5595 */
 
 static int sis5595_probe(struct platform_device *pdev);
-static int __devexit sis5595_remove(struct platform_device *pdev);
+static int sis5595_remove(struct platform_device *pdev);
 
 static int sis5595_read_value(struct sis5595_data *data, u8 reg);
 static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value);
@@ -217,7 +217,7 @@ static struct platform_driver sis5595_driver = {
 		.name	= "sis5595",
 	},
 	.probe		= sis5595_probe,
-	.remove		= __devexit_p(sis5595_remove),
+	.remove		= sis5595_remove,
 };
 
 /* 4 Voltages */
@@ -583,7 +583,7 @@ static const struct attribute_group sis5595_group_temp1 = {
 };
 
 /* This is called when the module is loaded */
-static int __devinit sis5595_probe(struct platform_device *pdev)
+static int sis5595_probe(struct platform_device *pdev)
 {
 	int err = 0;
 	int i;
@@ -659,7 +659,7 @@ exit_remove_files:
 	return err;
 }
 
-static int __devexit sis5595_remove(struct platform_device *pdev)
+static int sis5595_remove(struct platform_device *pdev)
 {
 	struct sis5595_data *data = platform_get_drvdata(pdev);
 
@@ -693,7 +693,7 @@ static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value)
 }
 
 /* Called when we have found a new SIS5595. */
-static void __devinit sis5595_init_device(struct sis5595_data *data)
+static void sis5595_init_device(struct sis5595_data *data)
 {
 	u8 config = sis5595_read_value(data, SIS5595_REG_CONFIG);
 	if (!(config & 0x01))
@@ -758,7 +758,7 @@ static DEFINE_PCI_DEVICE_TABLE(sis5595_pci_ids) = {
 
 MODULE_DEVICE_TABLE(pci, sis5595_pci_ids);
 
-static int blacklist[] __devinitdata = {
+static int blacklist[] = {
 	PCI_DEVICE_ID_SI_540,
 	PCI_DEVICE_ID_SI_550,
 	PCI_DEVICE_ID_SI_630,
@@ -774,7 +774,7 @@ static int blacklist[] __devinitdata = {
 	PCI_DEVICE_ID_SI_5598,
 	0 };
 
-static int __devinit sis5595_device_add(unsigned short address)
+static int sis5595_device_add(unsigned short address)
 {
 	struct resource res = {
 		.start	= address,
@@ -815,7 +815,7 @@ exit:
 	return err;
 }
 
-static int __devinit sis5595_pci_probe(struct pci_dev *dev,
+static int sis5595_pci_probe(struct pci_dev *dev,
 				       const struct pci_device_id *id)
 {
 	u16 address;
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index 65b07de..81348fa 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -228,7 +228,7 @@ static const struct attribute_group smsc47b397_group = {
 	.attrs = smsc47b397_attributes,
 };
 
-static int __devexit smsc47b397_remove(struct platform_device *pdev)
+static int smsc47b397_remove(struct platform_device *pdev)
 {
 	struct smsc47b397_data *data = platform_get_drvdata(pdev);
 
@@ -246,10 +246,10 @@ static struct platform_driver smsc47b397_driver = {
 		.name	= DRVNAME,
 	},
 	.probe		= smsc47b397_probe,
-	.remove		= __devexit_p(smsc47b397_remove),
+	.remove		= smsc47b397_remove,
 };
 
-static int __devinit smsc47b397_probe(struct platform_device *pdev)
+static int smsc47b397_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct smsc47b397_data *data;
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
index b8777e5..b10c3d3 100644
--- a/drivers/hwmon/tmp102.c
+++ b/drivers/hwmon/tmp102.c
@@ -147,7 +147,7 @@ static const struct attribute_group tmp102_attr_group = {
 #define TMP102_CONFIG  (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1)
 #define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL)
 
-static int __devinit tmp102_probe(struct i2c_client *client,
+static int tmp102_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
 	struct tmp102 *tmp102;
@@ -216,7 +216,7 @@ fail_restore_config:
 	return status;
 }
 
-static int __devexit tmp102_remove(struct i2c_client *client)
+static int tmp102_remove(struct i2c_client *client)
 {
 	struct tmp102 *tmp102 = i2c_get_clientdata(client);
 
@@ -283,7 +283,7 @@ static struct i2c_driver tmp102_driver = {
 	.driver.name	= DRIVER_NAME,
 	.driver.pm	= TMP102_DEV_PM_OPS,
 	.probe		= tmp102_probe,
-	.remove		= __devexit_p(tmp102_remove),
+	.remove		= tmp102_remove,
 	.id_table	= tmp102_id,
 };
 
diff --git a/drivers/hwmon/twl4030-madc-hwmon.c b/drivers/hwmon/twl4030-madc-hwmon.c
index 1a174f0..149d44a 100644
--- a/drivers/hwmon/twl4030-madc-hwmon.c
+++ b/drivers/hwmon/twl4030-madc-hwmon.c
@@ -96,7 +96,7 @@ static const struct attribute_group twl4030_madc_group = {
 	.attrs = twl4030_madc_attributes,
 };
 
-static int __devinit twl4030_madc_hwmon_probe(struct platform_device *pdev)
+static int twl4030_madc_hwmon_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct device *hwmon;
@@ -120,7 +120,7 @@ err_sysfs:
 	return ret;
 }
 
-static int __devexit twl4030_madc_hwmon_remove(struct platform_device *pdev)
+static int twl4030_madc_hwmon_remove(struct platform_device *pdev)
 {
 	hwmon_device_unregister(&pdev->dev);
 	sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group);
diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c
index 44136bb..fb3e693 100644
--- a/drivers/hwmon/ultra45_env.c
+++ b/drivers/hwmon/ultra45_env.c
@@ -250,7 +250,7 @@ static const struct attribute_group env_group = {
 	.attrs = env_attributes,
 };
 
-static int __devinit env_probe(struct platform_device *op)
+static int env_probe(struct platform_device *op)
 {
 	struct env *p = kzalloc(sizeof(*p), GFP_KERNEL);
 	int err = -ENOMEM;
@@ -291,7 +291,7 @@ out_free:
 	goto out;
 }
 
-static int __devexit env_remove(struct platform_device *op)
+static int env_remove(struct platform_device *op)
 {
 	struct env *p = platform_get_drvdata(op);
 
@@ -321,7 +321,7 @@ static struct platform_driver env_driver = {
 		.of_match_table = env_match,
 	},
 	.probe		= env_probe,
-	.remove		= __devexit_p(env_remove),
+	.remove		= env_remove,
 };
 
 module_platform_driver(env_driver);
diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c
new file mode 100644
index 0000000..59fd126
--- /dev/null
+++ b/drivers/hwmon/vexpress.c
@@ -0,0 +1,229 @@
+/*
+ * This program is free software; you can 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#define DRVNAME "vexpress-hwmon"
+#define pr_fmt(fmt) DRVNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/vexpress.h>
+
+struct vexpress_hwmon_data {
+	struct device *hwmon_dev;
+	struct vexpress_config_func *func;
+};
+
+static ssize_t vexpress_hwmon_name_show(struct device *dev,
+		struct device_attribute *dev_attr, char *buffer)
+{
+	const char *compatible = of_get_property(dev->of_node, "compatible",
+			NULL);
+
+	return sprintf(buffer, "%s\n", compatible);
+}
+
+static ssize_t vexpress_hwmon_label_show(struct device *dev,
+		struct device_attribute *dev_attr, char *buffer)
+{
+	const char *label = of_get_property(dev->of_node, "label", NULL);
+
+	if (!label)
+		return -ENOENT;
+
+	return snprintf(buffer, PAGE_SIZE, "%s\n", label);
+}
+
+static ssize_t vexpress_hwmon_u32_show(struct device *dev,
+		struct device_attribute *dev_attr, char *buffer)
+{
+	struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
+	int err;
+	u32 value;
+
+	err = vexpress_config_read(data->func, 0, &value);
+	if (err)
+		return err;
+
+	return snprintf(buffer, PAGE_SIZE, "%u\n", value /
+			to_sensor_dev_attr(dev_attr)->index);
+}
+
+static ssize_t vexpress_hwmon_u64_show(struct device *dev,
+		struct device_attribute *dev_attr, char *buffer)
+{
+	struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
+	int err;
+	u32 value_hi, value_lo;
+
+	err = vexpress_config_read(data->func, 0, &value_lo);
+	if (err)
+		return err;
+
+	err = vexpress_config_read(data->func, 1, &value_hi);
+	if (err)
+		return err;
+
+	return snprintf(buffer, PAGE_SIZE, "%llu\n",
+			div_u64(((u64)value_hi << 32) | value_lo,
+			to_sensor_dev_attr(dev_attr)->index));
+}
+
+static DEVICE_ATTR(name, S_IRUGO, vexpress_hwmon_name_show, NULL);
+
+#define VEXPRESS_HWMON_ATTRS(_name, _label_attr, _input_attr)	\
+struct attribute *vexpress_hwmon_attrs_##_name[] = {		\
+	&dev_attr_name.attr,					\
+	&dev_attr_##_label_attr.attr,				\
+	&sensor_dev_attr_##_input_attr.dev_attr.attr,		\
+	NULL							\
+}
+
+#if !defined(CONFIG_REGULATOR_VEXPRESS)
+static DEVICE_ATTR(in1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, vexpress_hwmon_u32_show,
+		NULL, 1000);
+static VEXPRESS_HWMON_ATTRS(volt, in1_label, in1_input);
+static struct attribute_group vexpress_hwmon_group_volt = {
+	.attrs = vexpress_hwmon_attrs_volt,
+};
+#endif
+
+static DEVICE_ATTR(curr1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, vexpress_hwmon_u32_show,
+		NULL, 1000);
+static VEXPRESS_HWMON_ATTRS(amp, curr1_label, curr1_input);
+static struct attribute_group vexpress_hwmon_group_amp = {
+	.attrs = vexpress_hwmon_attrs_amp,
+};
+
+static DEVICE_ATTR(temp1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, vexpress_hwmon_u32_show,
+		NULL, 1000);
+static VEXPRESS_HWMON_ATTRS(temp, temp1_label, temp1_input);
+static struct attribute_group vexpress_hwmon_group_temp = {
+	.attrs = vexpress_hwmon_attrs_temp,
+};
+
+static DEVICE_ATTR(power1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, vexpress_hwmon_u32_show,
+		NULL, 1);
+static VEXPRESS_HWMON_ATTRS(power, power1_label, power1_input);
+static struct attribute_group vexpress_hwmon_group_power = {
+	.attrs = vexpress_hwmon_attrs_power,
+};
+
+static DEVICE_ATTR(energy1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, vexpress_hwmon_u64_show,
+		NULL, 1);
+static VEXPRESS_HWMON_ATTRS(energy, energy1_label, energy1_input);
+static struct attribute_group vexpress_hwmon_group_energy = {
+	.attrs = vexpress_hwmon_attrs_energy,
+};
+
+static struct of_device_id vexpress_hwmon_of_match[] = {
+#if !defined(CONFIG_REGULATOR_VEXPRESS)
+	{
+		.compatible = "arm,vexpress-volt",
+		.data = &vexpress_hwmon_group_volt,
+	},
+#endif
+	{
+		.compatible = "arm,vexpress-amp",
+		.data = &vexpress_hwmon_group_amp,
+	}, {
+		.compatible = "arm,vexpress-temp",
+		.data = &vexpress_hwmon_group_temp,
+	}, {
+		.compatible = "arm,vexpress-power",
+		.data = &vexpress_hwmon_group_power,
+	}, {
+		.compatible = "arm,vexpress-energy",
+		.data = &vexpress_hwmon_group_energy,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, vexpress_hwmon_of_match);
+
+static int vexpress_hwmon_probe(struct platform_device *pdev)
+{
+	int err;
+	const struct of_device_id *match;
+	struct vexpress_hwmon_data *data;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, data);
+
+	match = of_match_device(vexpress_hwmon_of_match, &pdev->dev);
+	if (!match)
+		return -ENODEV;
+
+	data->func = vexpress_config_func_get_by_dev(&pdev->dev);
+	if (!data->func)
+		return -ENODEV;
+
+	err = sysfs_create_group(&pdev->dev.kobj, match->data);
+	if (err)
+		goto error;
+
+	data->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		goto error;
+	}
+
+	return 0;
+
+error:
+	sysfs_remove_group(&pdev->dev.kobj, match->data);
+	vexpress_config_func_put(data->func);
+	return err;
+}
+
+static int __devexit vexpress_hwmon_remove(struct platform_device *pdev)
+{
+	struct vexpress_hwmon_data *data = platform_get_drvdata(pdev);
+	const struct of_device_id *match;
+
+	hwmon_device_unregister(data->hwmon_dev);
+
+	match = of_match_device(vexpress_hwmon_of_match, &pdev->dev);
+	sysfs_remove_group(&pdev->dev.kobj, match->data);
+
+	vexpress_config_func_put(data->func);
+
+	return 0;
+}
+
+static struct platform_driver vexpress_hwmon_driver = {
+	.probe = vexpress_hwmon_probe,
+	.remove = __devexit_p(vexpress_hwmon_remove),
+	.driver	= {
+		.name = DRVNAME,
+		.owner = THIS_MODULE,
+		.of_match_table = vexpress_hwmon_of_match,
+	},
+};
+
+module_platform_driver(vexpress_hwmon_driver);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_DESCRIPTION("Versatile Express hwmon sensors driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:vexpress-hwmon");
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
index 4cddee0..76f157b 100644
--- a/drivers/hwmon/via-cputemp.c
+++ b/drivers/hwmon/via-cputemp.c
@@ -121,7 +121,7 @@ static const struct attribute_group via_cputemp_group = {
 /* Optional attributes */
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_cpu_vid, NULL);
 
-static int __devinit via_cputemp_probe(struct platform_device *pdev)
+static int via_cputemp_probe(struct platform_device *pdev)
 {
 	struct via_cputemp_data *data;
 	struct cpuinfo_x86 *c = &cpu_data(pdev->id);
@@ -192,7 +192,7 @@ exit_remove:
 	return err;
 }
 
-static int __devexit via_cputemp_remove(struct platform_device *pdev)
+static int via_cputemp_remove(struct platform_device *pdev)
 {
 	struct via_cputemp_data *data = platform_get_drvdata(pdev);
 
@@ -209,7 +209,7 @@ static struct platform_driver via_cputemp_driver = {
 		.name = DRVNAME,
 	},
 	.probe = via_cputemp_probe,
-	.remove = __devexit_p(via_cputemp_remove),
+	.remove = via_cputemp_remove,
 };
 
 struct pdev_entry {
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 299399a..e0e14a9 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -339,7 +339,7 @@ struct via686a_data {
 static struct pci_dev *s_bridge;	/* pointer to the (only) via686a */
 
 static int via686a_probe(struct platform_device *pdev);
-static int __devexit via686a_remove(struct platform_device *pdev);
+static int via686a_remove(struct platform_device *pdev);
 
 static inline int via686a_read_value(struct via686a_data *data, u8 reg)
 {
@@ -677,12 +677,12 @@ static struct platform_driver via686a_driver = {
 		.name	= "via686a",
 	},
 	.probe		= via686a_probe,
-	.remove		= __devexit_p(via686a_remove),
+	.remove		= via686a_remove,
 };
 
 
 /* This is called when the module is loaded */
-static int __devinit via686a_probe(struct platform_device *pdev)
+static int via686a_probe(struct platform_device *pdev)
 {
 	struct via686a_data *data;
 	struct resource *res;
@@ -728,7 +728,7 @@ exit_remove_files:
 	return err;
 }
 
-static int __devexit via686a_remove(struct platform_device *pdev)
+static int via686a_remove(struct platform_device *pdev)
 {
 	struct via686a_data *data = platform_get_drvdata(pdev);
 
@@ -745,7 +745,7 @@ static void via686a_update_fan_div(struct via686a_data *data)
 	data->fan_div[1] = reg >> 6;
 }
 
-static void __devinit via686a_init_device(struct via686a_data *data)
+static void via686a_init_device(struct via686a_data *data)
 {
 	u8 reg;
 
@@ -833,7 +833,7 @@ static DEFINE_PCI_DEVICE_TABLE(via686a_pci_ids) = {
 };
 MODULE_DEVICE_TABLE(pci, via686a_pci_ids);
 
-static int __devinit via686a_device_add(unsigned short address)
+static int via686a_device_add(unsigned short address)
 {
 	struct resource res = {
 		.start	= address,
@@ -874,7 +874,7 @@ exit:
 	return err;
 }
 
-static int __devinit via686a_pci_probe(struct pci_dev *dev,
+static int via686a_pci_probe(struct pci_dev *dev,
 				       const struct pci_device_id *id)
 {
 	u16 address, val;
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
index f2c6115..7517030 100644
--- a/drivers/hwmon/vt1211.c
+++ b/drivers/hwmon/vt1211.c
@@ -1086,7 +1086,7 @@ static struct device_attribute vt1211_sysfs_misc[] = {
  * Device registration and initialization
  * --------------------------------------------------------------------- */
 
-static void __devinit vt1211_init_device(struct vt1211_data *data)
+static void vt1211_init_device(struct vt1211_data *data)
 {
 	/* set VRM */
 	data->vrm = vid_which_vrm();
@@ -1141,7 +1141,7 @@ static void vt1211_remove_sysfs(struct platform_device *pdev)
 		device_remove_file(dev, &vt1211_sysfs_misc[i]);
 }
 
-static int __devinit vt1211_probe(struct platform_device *pdev)
+static int vt1211_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct vt1211_data *data;
@@ -1217,7 +1217,7 @@ EXIT_DEV_REMOVE_SILENT:
 	return err;
 }
 
-static int __devexit vt1211_remove(struct platform_device *pdev)
+static int vt1211_remove(struct platform_device *pdev)
 {
 	struct vt1211_data *data = platform_get_drvdata(pdev);
 
@@ -1233,7 +1233,7 @@ static struct platform_driver vt1211_driver = {
 		.name  = DRVNAME,
 	},
 	.probe  = vt1211_probe,
-	.remove = __devexit_p(vt1211_remove),
+	.remove = vt1211_remove,
 };
 
 static int __init vt1211_device_add(unsigned short address)
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index 84e3dc5..a56355c 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -176,7 +176,7 @@ struct vt8231_data {
 
 static struct pci_dev *s_bridge;
 static int vt8231_probe(struct platform_device *pdev);
-static int __devexit vt8231_remove(struct platform_device *pdev);
+static int vt8231_remove(struct platform_device *pdev);
 static struct vt8231_data *vt8231_update_device(struct device *dev);
 static void vt8231_init_device(struct vt8231_data *data);
 
@@ -762,7 +762,7 @@ static struct platform_driver vt8231_driver = {
 		.name	= "vt8231",
 	},
 	.probe	= vt8231_probe,
-	.remove	= __devexit_p(vt8231_remove),
+	.remove	= vt8231_remove,
 };
 
 static DEFINE_PCI_DEVICE_TABLE(vt8231_pci_ids) = {
@@ -772,7 +772,7 @@ static DEFINE_PCI_DEVICE_TABLE(vt8231_pci_ids) = {
 
 MODULE_DEVICE_TABLE(pci, vt8231_pci_ids);
 
-static int __devinit vt8231_pci_probe(struct pci_dev *dev,
+static int vt8231_pci_probe(struct pci_dev *dev,
 				      const struct pci_device_id *id);
 
 static struct pci_driver vt8231_pci_driver = {
@@ -851,7 +851,7 @@ exit_remove_files:
 	return err;
 }
 
-static int __devexit vt8231_remove(struct platform_device *pdev)
+static int vt8231_remove(struct platform_device *pdev)
 {
 	struct vt8231_data *data = platform_get_drvdata(pdev);
 	int i;
@@ -943,7 +943,7 @@ static struct vt8231_data *vt8231_update_device(struct device *dev)
 	return data;
 }
 
-static int __devinit vt8231_device_add(unsigned short address)
+static int vt8231_device_add(unsigned short address)
 {
 	struct resource res = {
 		.start	= address,
@@ -984,7 +984,7 @@ exit:
 	return err;
 }
 
-static int __devinit vt8231_pci_probe(struct pci_dev *dev,
+static int vt8231_pci_probe(struct pci_dev *dev,
 				const struct pci_device_id *id)
 {
 	u16 address, val;
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index de3c7e0..0e8ffd6 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -1,7 +1,7 @@
 /*
  *  w83627ehf - Driver for the hardware monitoring functionality of
  *		the Winbond W83627EHF Super-I/O chip
- *  Copyright (C) 2005-2011  Jean Delvare <khali@linux-fr.org>
+ *  Copyright (C) 2005-2012  Jean Delvare <khali@linux-fr.org>
  *  Copyright (C) 2006  Yuan Mu (Winbond),
  *			Rudolf Marek <r.marek@assembler.cz>
  *			David Hubbard <david.c.hubbard@gmail.com>
@@ -502,6 +502,13 @@ struct w83627ehf_data {
 	u16 have_temp_offset;
 	u8 in6_skip:1;
 	u8 temp3_val_only:1;
+
+#ifdef CONFIG_PM
+	/* Remember extra register values over suspend/resume */
+	u8 vbat;
+	u8 fandiv1;
+	u8 fandiv2;
+#endif
 };
 
 struct w83627ehf_sio_data {
@@ -898,6 +905,8 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
 				data->temp_max_hyst[i]
 				  = w83627ehf_read_temp(data,
 						data->reg_temp_hyst[i]);
+			if (i > 2)
+				continue;
 			if (data->have_temp_offset & (1 << i))
 				data->temp_offset[i]
 				  = w83627ehf_read_value(data,
@@ -1866,7 +1875,7 @@ static void w83627ehf_device_remove_files(struct device *dev)
 }
 
 /* Get the monitoring functions started */
-static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data,
+static inline void w83627ehf_init_device(struct w83627ehf_data *data,
 						   enum kinds kind)
 {
 	int i;
@@ -1952,7 +1961,7 @@ static void w82627ehf_swap_tempreg(struct w83627ehf_data *data,
 	data->reg_temp_config[r2] = tmp;
 }
 
-static void __devinit
+static void
 w83627ehf_set_temp_reg_ehf(struct w83627ehf_data *data, int n_temp)
 {
 	int i;
@@ -1965,7 +1974,7 @@ w83627ehf_set_temp_reg_ehf(struct w83627ehf_data *data, int n_temp)
 	}
 }
 
-static void __devinit
+static void
 w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
 			   struct w83627ehf_data *data)
 {
@@ -2054,7 +2063,7 @@ w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
 	}
 }
 
-static int __devinit w83627ehf_probe(struct platform_device *pdev)
+static int w83627ehf_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct w83627ehf_sio_data *sio_data = dev->platform_data;
@@ -2596,7 +2605,7 @@ exit:
 	return err;
 }
 
-static int __devexit w83627ehf_remove(struct platform_device *pdev)
+static int w83627ehf_remove(struct platform_device *pdev)
 {
 	struct w83627ehf_data *data = platform_get_drvdata(pdev);
 
@@ -2608,13 +2617,101 @@ static int __devexit w83627ehf_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int w83627ehf_suspend(struct device *dev)
+{
+	struct w83627ehf_data *data = w83627ehf_update_device(dev);
+	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+
+	mutex_lock(&data->update_lock);
+	data->vbat = w83627ehf_read_value(data, W83627EHF_REG_VBAT);
+	if (sio_data->kind == nct6775) {
+		data->fandiv1 = w83627ehf_read_value(data, NCT6775_REG_FANDIV1);
+		data->fandiv2 = w83627ehf_read_value(data, NCT6775_REG_FANDIV2);
+	}
+	mutex_unlock(&data->update_lock);
+
+	return 0;
+}
+
+static int w83627ehf_resume(struct device *dev)
+{
+	struct w83627ehf_data *data = dev_get_drvdata(dev);
+	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+	int i;
+
+	mutex_lock(&data->update_lock);
+	data->bank = 0xff;		/* Force initial bank selection */
+
+	/* Restore limits */
+	for (i = 0; i < data->in_num; i++) {
+		if ((i == 6) && data->in6_skip)
+			continue;
+
+		w83627ehf_write_value(data, W83627EHF_REG_IN_MIN(i),
+				      data->in_min[i]);
+		w83627ehf_write_value(data, W83627EHF_REG_IN_MAX(i),
+				      data->in_max[i]);
+	}
+
+	for (i = 0; i < 5; i++) {
+		if (!(data->has_fan_min & (1 << i)))
+			continue;
+
+		w83627ehf_write_value(data, data->REG_FAN_MIN[i],
+				      data->fan_min[i]);
+	}
+
+	for (i = 0; i < NUM_REG_TEMP; i++) {
+		if (!(data->have_temp & (1 << i)))
+			continue;
+
+		if (data->reg_temp_over[i])
+			w83627ehf_write_temp(data, data->reg_temp_over[i],
+					     data->temp_max[i]);
+		if (data->reg_temp_hyst[i])
+			w83627ehf_write_temp(data, data->reg_temp_hyst[i],
+					     data->temp_max_hyst[i]);
+		if (i > 2)
+			continue;
+		if (data->have_temp_offset & (1 << i))
+			w83627ehf_write_value(data,
+					      W83627EHF_REG_TEMP_OFFSET[i],
+					      data->temp_offset[i]);
+	}
+
+	/* Restore other settings */
+	w83627ehf_write_value(data, W83627EHF_REG_VBAT, data->vbat);
+	if (sio_data->kind == nct6775) {
+		w83627ehf_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
+		w83627ehf_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
+	}
+
+	/* Force re-reading all values */
+	data->valid = 0;
+	mutex_unlock(&data->update_lock);
+
+	return 0;
+}
+
+static const struct dev_pm_ops w83627ehf_dev_pm_ops = {
+	.suspend = w83627ehf_suspend,
+	.resume = w83627ehf_resume,
+};
+
+#define W83627EHF_DEV_PM_OPS	(&w83627ehf_dev_pm_ops)
+#else
+#define W83627EHF_DEV_PM_OPS	NULL
+#endif /* CONFIG_PM */
+
 static struct platform_driver w83627ehf_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
 		.name	= DRVNAME,
+		.pm	= W83627EHF_DEV_PM_OPS,
 	},
 	.probe		= w83627ehf_probe,
-	.remove		= __devexit_p(w83627ehf_remove),
+	.remove		= w83627ehf_remove,
 };
 
 /* w83627ehf_find() looks for a '627 in the Super-I/O config space */
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index af15899..81f4865 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -5,7 +5,7 @@
  *			      Philip Edelbrock <phil@netroedge.com>,
  *			      and Mark Studebaker <mdsxyz123@yahoo.com>
  * Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org>
- * Copyright (c) 2007  Jean Delvare <khali@linux-fr.org>
+ * Copyright (c) 2007 - 1012  Jean Delvare <khali@linux-fr.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -389,11 +389,17 @@ struct w83627hf_data {
 				 */
 	u8 vrm;
 	u8 vrm_ovt;		/* Register value, 627THF/637HF/687THF only */
+
+#ifdef CONFIG_PM
+	/* Remember extra register values over suspend/resume */
+	u8 scfg1;
+	u8 scfg2;
+#endif
 };
 
 
 static int w83627hf_probe(struct platform_device *pdev);
-static int __devexit w83627hf_remove(struct platform_device *pdev);
+static int w83627hf_remove(struct platform_device *pdev);
 
 static int w83627hf_read_value(struct w83627hf_data *data, u16 reg);
 static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value);
@@ -401,13 +407,80 @@ static void w83627hf_update_fan_div(struct w83627hf_data *data);
 static struct w83627hf_data *w83627hf_update_device(struct device *dev);
 static void w83627hf_init_device(struct platform_device *pdev);
 
+#ifdef CONFIG_PM
+static int w83627hf_suspend(struct device *dev)
+{
+	struct w83627hf_data *data = w83627hf_update_device(dev);
+
+	mutex_lock(&data->update_lock);
+	data->scfg1 = w83627hf_read_value(data, W83781D_REG_SCFG1);
+	data->scfg2 = w83627hf_read_value(data, W83781D_REG_SCFG2);
+	mutex_unlock(&data->update_lock);
+
+	return 0;
+}
+
+static int w83627hf_resume(struct device *dev)
+{
+	struct w83627hf_data *data = dev_get_drvdata(dev);
+	int i, num_temps = (data->type == w83697hf) ? 2 : 3;
+
+	/* Restore limits */
+	mutex_lock(&data->update_lock);
+	for (i = 0; i <= 8; i++) {
+		/* skip missing sensors */
+		if (((data->type == w83697hf) && (i == 1)) ||
+		    ((data->type != w83627hf && data->type != w83697hf)
+		    && (i == 5 || i == 6)))
+			continue;
+		w83627hf_write_value(data, W83781D_REG_IN_MAX(i),
+				     data->in_max[i]);
+		w83627hf_write_value(data, W83781D_REG_IN_MIN(i),
+				     data->in_min[i]);
+	}
+	for (i = 0; i <= 2; i++)
+		w83627hf_write_value(data, W83627HF_REG_FAN_MIN(i),
+				     data->fan_min[i]);
+	for (i = 0; i < num_temps; i++) {
+		w83627hf_write_value(data, w83627hf_reg_temp_over[i],
+				     data->temp_max[i]);
+		w83627hf_write_value(data, w83627hf_reg_temp_hyst[i],
+				     data->temp_max_hyst[i]);
+	}
+
+	/* Fixup BIOS bugs */
+	if (data->type == w83627thf || data->type == w83637hf ||
+	    data->type == w83687thf)
+		w83627hf_write_value(data, W83627THF_REG_VRM_OVT_CFG,
+				     data->vrm_ovt);
+	w83627hf_write_value(data, W83781D_REG_SCFG1, data->scfg1);
+	w83627hf_write_value(data, W83781D_REG_SCFG2, data->scfg2);
+
+	/* Force re-reading all values */
+	data->valid = 0;
+	mutex_unlock(&data->update_lock);
+
+	return 0;
+}
+
+static const struct dev_pm_ops w83627hf_dev_pm_ops = {
+	.suspend = w83627hf_suspend,
+	.resume = w83627hf_resume,
+};
+
+#define W83627HF_DEV_PM_OPS	(&w83627hf_dev_pm_ops)
+#else
+#define W83627HF_DEV_PM_OPS	NULL
+#endif /* CONFIG_PM */
+
 static struct platform_driver w83627hf_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
 		.name	= DRVNAME,
+		.pm	= W83627HF_DEV_PM_OPS,
 	},
 	.probe		= w83627hf_probe,
-	.remove		= __devexit_p(w83627hf_remove),
+	.remove		= w83627hf_remove,
 };
 
 static ssize_t
@@ -1342,7 +1415,7 @@ static const struct attribute_group w83627hf_group_opt = {
 	.attrs = w83627hf_attributes_opt,
 };
 
-static int __devinit w83627hf_probe(struct platform_device *pdev)
+static int w83627hf_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct w83627hf_sio_data *sio_data = dev->platform_data;
@@ -1508,7 +1581,7 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
 	return err;
 }
 
-static int __devexit w83627hf_remove(struct platform_device *pdev)
+static int w83627hf_remove(struct platform_device *pdev)
 {
 	struct w83627hf_data *data = platform_get_drvdata(pdev);
 
@@ -1564,7 +1637,7 @@ static int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
 	return res;
 }
 
-static int __devinit w83627thf_read_gpio5(struct platform_device *pdev)
+static int w83627thf_read_gpio5(struct platform_device *pdev)
 {
 	struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
 	int res = 0xff, sel;
@@ -1597,7 +1670,7 @@ exit:
 	return res;
 }
 
-static int __devinit w83687thf_read_vid(struct platform_device *pdev)
+static int w83687thf_read_vid(struct platform_device *pdev)
 {
 	struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
 	int res = 0xff;
@@ -1649,7 +1722,7 @@ static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value)
 	return 0;
 }
 
-static void __devinit w83627hf_init_device(struct platform_device *pdev)
+static void w83627hf_init_device(struct platform_device *pdev)
 {
 	struct w83627hf_data *data = platform_get_drvdata(pdev);
 	int i;
@@ -1659,8 +1732,10 @@ static void __devinit w83627hf_init_device(struct platform_device *pdev)
 	/* Minimize conflicts with other winbond i2c-only clients...  */
 	/* disable i2c subclients... how to disable main i2c client?? */
 	/* force i2c address to relatively uncommon address */
-	w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89);
-	w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c);
+	if (type == w83627hf) {
+		w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89);
+		w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c);
+	}
 
 	/* Read VID only once */
 	if (type == w83627hf || type == w83637hf) {
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 20f11d3..93bd286 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -1764,7 +1764,7 @@ w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value)
 	return 0;
 }
 
-static int __devinit
+static int
 w83781d_isa_probe(struct platform_device *pdev)
 {
 	int err, reg;
@@ -1824,7 +1824,7 @@ w83781d_isa_probe(struct platform_device *pdev)
 	return err;
 }
 
-static int __devexit
+static int
 w83781d_isa_remove(struct platform_device *pdev)
 {
 	struct w83781d_data *data = platform_get_drvdata(pdev);
@@ -1842,7 +1842,7 @@ static struct platform_driver w83781d_isa_driver = {
 		.name = "w83781d",
 	},
 	.probe = w83781d_isa_probe,
-	.remove = __devexit_p(w83781d_isa_remove),
+	.remove = w83781d_isa_remove,
 };
 
 /* return 1 if a supported chip is found, 0 otherwise */
diff --git a/drivers/hwmon/wm831x-hwmon.c b/drivers/hwmon/wm831x-hwmon.c
index d0db1f2..df6ceaf 100644
--- a/drivers/hwmon/wm831x-hwmon.c
+++ b/drivers/hwmon/wm831x-hwmon.c
@@ -157,7 +157,7 @@ static const struct attribute_group wm831x_attr_group = {
 	.attrs	= wm831x_attributes,
 };
 
-static int __devinit wm831x_hwmon_probe(struct platform_device *pdev)
+static int wm831x_hwmon_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 	struct wm831x_hwmon *hwmon;
@@ -189,7 +189,7 @@ err_sysfs:
 	return ret;
 }
 
-static int __devexit wm831x_hwmon_remove(struct platform_device *pdev)
+static int wm831x_hwmon_remove(struct platform_device *pdev)
 {
 	struct wm831x_hwmon *hwmon = platform_get_drvdata(pdev);
 
@@ -201,7 +201,7 @@ static int __devexit wm831x_hwmon_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_hwmon_driver = {
 	.probe = wm831x_hwmon_probe,
-	.remove = __devexit_p(wm831x_hwmon_remove),
+	.remove = wm831x_hwmon_remove,
 	.driver = {
 		.name = "wm831x-hwmon",
 		.owner = THIS_MODULE,
diff --git a/drivers/hwmon/wm8350-hwmon.c b/drivers/hwmon/wm8350-hwmon.c
index b955756..64bf75c 100644
--- a/drivers/hwmon/wm8350-hwmon.c
+++ b/drivers/hwmon/wm8350-hwmon.c
@@ -91,7 +91,7 @@ static const struct attribute_group wm8350_attr_group = {
 	.attrs	= wm8350_attributes,
 };
 
-static int __devinit wm8350_hwmon_probe(struct platform_device *pdev)
+static int wm8350_hwmon_probe(struct platform_device *pdev)
 {
 	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
 	int ret;
@@ -114,7 +114,7 @@ err:
 	return ret;
 }
 
-static int __devexit wm8350_hwmon_remove(struct platform_device *pdev)
+static int wm8350_hwmon_remove(struct platform_device *pdev)
 {
 	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
 
@@ -126,7 +126,7 @@ static int __devexit wm8350_hwmon_remove(struct platform_device *pdev)
 
 static struct platform_driver wm8350_hwmon_driver = {
 	.probe = wm8350_hwmon_probe,
-	.remove = __devexit_p(wm8350_hwmon_remove),
+	.remove = wm8350_hwmon_remove,
 	.driver = {
 		.name = "wm8350-hwmon",
 		.owner = THIS_MODULE,
diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c
index 887d34e..292869c 100644
--- a/drivers/hwspinlock/omap_hwspinlock.c
+++ b/drivers/hwspinlock/omap_hwspinlock.c
@@ -78,7 +78,7 @@ static const struct hwspinlock_ops omap_hwspinlock_ops = {
 	.relax = omap_hwspinlock_relax,
 };
 
-static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
+static int omap_hwspinlock_probe(struct platform_device *pdev)
 {
 	struct hwspinlock_pdata *pdata = pdev->dev.platform_data;
 	struct hwspinlock_device *bank;
@@ -142,7 +142,7 @@ iounmap_base:
 	return ret;
 }
 
-static int __devexit omap_hwspinlock_remove(struct platform_device *pdev)
+static int omap_hwspinlock_remove(struct platform_device *pdev)
 {
 	struct hwspinlock_device *bank = platform_get_drvdata(pdev);
 	void __iomem *io_base = bank->lock[0].priv - LOCK_BASE_OFFSET;
@@ -163,7 +163,7 @@ static int __devexit omap_hwspinlock_remove(struct platform_device *pdev)
 
 static struct platform_driver omap_hwspinlock_driver = {
 	.probe		= omap_hwspinlock_probe,
-	.remove		= __devexit_p(omap_hwspinlock_remove),
+	.remove		= omap_hwspinlock_remove,
 	.driver		= {
 		.name	= "omap_hwspinlock",
 		.owner	= THIS_MODULE,
diff --git a/drivers/hwspinlock/u8500_hsem.c b/drivers/hwspinlock/u8500_hsem.c
index 86980fe..401c33b 100644
--- a/drivers/hwspinlock/u8500_hsem.c
+++ b/drivers/hwspinlock/u8500_hsem.c
@@ -91,7 +91,7 @@ static const struct hwspinlock_ops u8500_hwspinlock_ops = {
 	.relax		= u8500_hsem_relax,
 };
 
-static int __devinit u8500_hsem_probe(struct platform_device *pdev)
+static int u8500_hsem_probe(struct platform_device *pdev)
 {
 	struct hwspinlock_pdata *pdata = pdev->dev.platform_data;
 	struct hwspinlock_device *bank;
@@ -148,7 +148,7 @@ iounmap_base:
 	return ret;
 }
 
-static int __devexit u8500_hsem_remove(struct platform_device *pdev)
+static int u8500_hsem_remove(struct platform_device *pdev)
 {
 	struct hwspinlock_device *bank = platform_get_drvdata(pdev);
 	void __iomem *io_base = bank->lock[0].priv - HSEM_REGISTER_OFFSET;
@@ -172,7 +172,7 @@ static int __devexit u8500_hsem_remove(struct platform_device *pdev)
 
 static struct platform_driver u8500_hsem_driver = {
 	.probe		= u8500_hsem_probe,
-	.remove		= __devexit_p(u8500_hsem_remove),
+	.remove		= u8500_hsem_remove,
 	.driver		= {
 		.name	= "u8500_hsem",
 		.owner	= THIS_MODULE,
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index e9df461..bdca511 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -337,6 +337,16 @@ config I2C_BLACKFIN_TWI_CLK_KHZ
 	help
 	  The unit of the TWI clock is kHz.
 
+config I2C_CBUS_GPIO
+	tristate "CBUS I2C driver"
+	depends on GENERIC_GPIO
+	help
+	  Support for CBUS access using I2C API. Mostly relevant for Nokia
+	  Internet Tablets (770, N800 and N810).
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-cbus-gpio.
+
 config I2C_CPM
 	tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)"
 	depends on (CPM1 || CPM2) && OF_I2C
@@ -818,6 +828,16 @@ config I2C_TINY_USB
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-tiny-usb.
 
+config I2C_VIPERBOARD
+	tristate "Viperboard I2C master support"
+	depends on MFD_VIPERBOARD && USB
+	help
+	  Say yes here to access the I2C part of the Nano River
+	  Technologies Viperboard as I2C master.
+          See viperboard API specification and Nano
+          River Tech's viperboard.h for detailed meaning
+          of the module parameters.
+
 comment "Other I2C/SMBus bus drivers"
 
 config I2C_ACORN
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 395b516..6181f3f 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_I2C_POWERMAC)	+= i2c-powermac.o
 obj-$(CONFIG_I2C_AT91)		+= i2c-at91.o
 obj-$(CONFIG_I2C_AU1550)	+= i2c-au1550.o
 obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
+obj-$(CONFIG_I2C_CBUS_GPIO)	+= i2c-cbus-gpio.o
 obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
 obj-$(CONFIG_I2C_DAVINCI)	+= i2c-davinci.o
 obj-$(CONFIG_I2C_DESIGNWARE_CORE)	+= i2c-designware-core.o
@@ -79,6 +80,7 @@ obj-$(CONFIG_I2C_PARPORT)	+= i2c-parport.o
 obj-$(CONFIG_I2C_PARPORT_LIGHT)	+= i2c-parport-light.o
 obj-$(CONFIG_I2C_TAOS_EVM)	+= i2c-taos-evm.o
 obj-$(CONFIG_I2C_TINY_USB)	+= i2c-tiny-usb.o
+obj-$(CONFIG_I2C_VIPERBOARD)	+= i2c-viperboard.o
 
 # Other I2C/SMBus bus drivers
 obj-$(CONFIG_I2C_ACORN)		+= i2c-acorn.o
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index c02bf20..b4575ee 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -19,6 +19,8 @@
 
 #include <linux/clk.h>
 #include <linux/completion.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
@@ -29,9 +31,11 @@
 #include <linux/of_i2c.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/platform_data/dma-atmel.h>
 
 #define TWI_CLK_HZ		100000			/* max 400 Kbits/s */
 #define AT91_I2C_TIMEOUT	msecs_to_jiffies(100)	/* transfer timeout */
+#define AT91_I2C_DMA_THRESHOLD	8			/* enable DMA if transfer size is bigger than this threshold */
 
 /* AT91 TWI register definitions */
 #define	AT91_TWI_CR		0x0000	/* Control Register */
@@ -66,24 +70,39 @@
 #define	AT91_TWI_THR		0x0034	/* Transmit Holding Register */
 
 struct at91_twi_pdata {
-	unsigned	clk_max_div;
-	unsigned	clk_offset;
-	bool		has_unre_flag;
+	unsigned clk_max_div;
+	unsigned clk_offset;
+	bool has_unre_flag;
+	bool has_dma_support;
+	struct at_dma_slave dma_slave;
+};
+
+struct at91_twi_dma {
+	struct dma_chan *chan_rx;
+	struct dma_chan *chan_tx;
+	struct scatterlist sg;
+	struct dma_async_tx_descriptor *data_desc;
+	enum dma_data_direction direction;
+	bool buf_mapped;
+	bool xfer_in_progress;
 };
 
 struct at91_twi_dev {
-	struct device		*dev;
-	void __iomem		*base;
-	struct completion	cmd_complete;
-	struct clk		*clk;
-	u8			*buf;
-	size_t			buf_len;
-	struct i2c_msg		*msg;
-	int			irq;
-	unsigned		transfer_status;
-	struct i2c_adapter	adapter;
-	unsigned		twi_cwgr_reg;
-	struct at91_twi_pdata	*pdata;
+	struct device *dev;
+	void __iomem *base;
+	struct completion cmd_complete;
+	struct clk *clk;
+	u8 *buf;
+	size_t buf_len;
+	struct i2c_msg *msg;
+	int irq;
+	unsigned imr;
+	unsigned transfer_status;
+	struct i2c_adapter adapter;
+	unsigned twi_cwgr_reg;
+	struct at91_twi_pdata *pdata;
+	bool use_dma;
+	struct at91_twi_dma dma;
 };
 
 static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg)
@@ -102,6 +121,17 @@ static void at91_disable_twi_interrupts(struct at91_twi_dev *dev)
 		       AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY);
 }
 
+static void at91_twi_irq_save(struct at91_twi_dev *dev)
+{
+	dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & 0x7;
+	at91_disable_twi_interrupts(dev);
+}
+
+static void at91_twi_irq_restore(struct at91_twi_dev *dev)
+{
+	at91_twi_write(dev, AT91_TWI_IER, dev->imr);
+}
+
 static void at91_init_twi_bus(struct at91_twi_dev *dev)
 {
 	at91_disable_twi_interrupts(dev);
@@ -138,6 +168,28 @@ static void __devinit at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
 	dev_dbg(dev->dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv);
 }
 
+static void at91_twi_dma_cleanup(struct at91_twi_dev *dev)
+{
+	struct at91_twi_dma *dma = &dev->dma;
+
+	at91_twi_irq_save(dev);
+
+	if (dma->xfer_in_progress) {
+		if (dma->direction == DMA_FROM_DEVICE)
+			dmaengine_terminate_all(dma->chan_rx);
+		else
+			dmaengine_terminate_all(dma->chan_tx);
+		dma->xfer_in_progress = false;
+	}
+	if (dma->buf_mapped) {
+		dma_unmap_single(dev->dev, sg_dma_address(&dma->sg),
+				 dev->buf_len, dma->direction);
+		dma->buf_mapped = false;
+	}
+
+	at91_twi_irq_restore(dev);
+}
+
 static void at91_twi_write_next_byte(struct at91_twi_dev *dev)
 {
 	if (dev->buf_len <= 0)
@@ -154,6 +206,60 @@ static void at91_twi_write_next_byte(struct at91_twi_dev *dev)
 	++dev->buf;
 }
 
+static void at91_twi_write_data_dma_callback(void *data)
+{
+	struct at91_twi_dev *dev = (struct at91_twi_dev *)data;
+
+	dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
+			 dev->buf_len, DMA_MEM_TO_DEV);
+
+	at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
+}
+
+static void at91_twi_write_data_dma(struct at91_twi_dev *dev)
+{
+	dma_addr_t dma_addr;
+	struct dma_async_tx_descriptor *txdesc;
+	struct at91_twi_dma *dma = &dev->dma;
+	struct dma_chan *chan_tx = dma->chan_tx;
+
+	if (dev->buf_len <= 0)
+		return;
+
+	dma->direction = DMA_TO_DEVICE;
+
+	at91_twi_irq_save(dev);
+	dma_addr = dma_map_single(dev->dev, dev->buf, dev->buf_len,
+				  DMA_TO_DEVICE);
+	if (dma_mapping_error(dev->dev, dma_addr)) {
+		dev_err(dev->dev, "dma map failed\n");
+		return;
+	}
+	dma->buf_mapped = true;
+	at91_twi_irq_restore(dev);
+	sg_dma_len(&dma->sg) = dev->buf_len;
+	sg_dma_address(&dma->sg) = dma_addr;
+
+	txdesc = dmaengine_prep_slave_sg(chan_tx, &dma->sg, 1, DMA_MEM_TO_DEV,
+					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!txdesc) {
+		dev_err(dev->dev, "dma prep slave sg failed\n");
+		goto error;
+	}
+
+	txdesc->callback = at91_twi_write_data_dma_callback;
+	txdesc->callback_param = dev;
+
+	dma->xfer_in_progress = true;
+	dmaengine_submit(txdesc);
+	dma_async_issue_pending(chan_tx);
+
+	return;
+
+error:
+	at91_twi_dma_cleanup(dev);
+}
+
 static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
 {
 	if (dev->buf_len <= 0)
@@ -179,6 +285,61 @@ static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
 	++dev->buf;
 }
 
+static void at91_twi_read_data_dma_callback(void *data)
+{
+	struct at91_twi_dev *dev = (struct at91_twi_dev *)data;
+
+	dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
+			 dev->buf_len, DMA_DEV_TO_MEM);
+
+	/* The last two bytes have to be read without using dma */
+	dev->buf += dev->buf_len - 2;
+	dev->buf_len = 2;
+	at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_RXRDY);
+}
+
+static void at91_twi_read_data_dma(struct at91_twi_dev *dev)
+{
+	dma_addr_t dma_addr;
+	struct dma_async_tx_descriptor *rxdesc;
+	struct at91_twi_dma *dma = &dev->dma;
+	struct dma_chan *chan_rx = dma->chan_rx;
+
+	dma->direction = DMA_FROM_DEVICE;
+
+	/* Keep in mind that we won't use dma to read the last two bytes */
+	at91_twi_irq_save(dev);
+	dma_addr = dma_map_single(dev->dev, dev->buf, dev->buf_len - 2,
+				  DMA_FROM_DEVICE);
+	if (dma_mapping_error(dev->dev, dma_addr)) {
+		dev_err(dev->dev, "dma map failed\n");
+		return;
+	}
+	dma->buf_mapped = true;
+	at91_twi_irq_restore(dev);
+	dma->sg.dma_address = dma_addr;
+	sg_dma_len(&dma->sg) = dev->buf_len - 2;
+
+	rxdesc = dmaengine_prep_slave_sg(chan_rx, &dma->sg, 1, DMA_DEV_TO_MEM,
+					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!rxdesc) {
+		dev_err(dev->dev, "dma prep slave sg failed\n");
+		goto error;
+	}
+
+	rxdesc->callback = at91_twi_read_data_dma_callback;
+	rxdesc->callback_param = dev;
+
+	dma->xfer_in_progress = true;
+	dmaengine_submit(rxdesc);
+	dma_async_issue_pending(dma->chan_rx);
+
+	return;
+
+error:
+	at91_twi_dma_cleanup(dev);
+}
+
 static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id)
 {
 	struct at91_twi_dev *dev = dev_id;
@@ -229,12 +390,36 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
 		if (dev->buf_len <= 1 && !(dev->msg->flags & I2C_M_RECV_LEN))
 			start_flags |= AT91_TWI_STOP;
 		at91_twi_write(dev, AT91_TWI_CR, start_flags);
-		at91_twi_write(dev, AT91_TWI_IER,
+		/*
+		 * When using dma, the last byte has to be read manually in
+		 * order to not send the stop command too late and then
+		 * to receive extra data. In practice, there are some issues
+		 * if you use the dma to read n-1 bytes because of latency.
+		 * Reading n-2 bytes with dma and the two last ones manually
+		 * seems to be the best solution.
+		 */
+		if (dev->use_dma && (dev->buf_len > AT91_I2C_DMA_THRESHOLD)) {
+			at91_twi_read_data_dma(dev);
+			/*
+			 * It is important to enable TXCOMP irq here because
+			 * doing it only when transferring the last two bytes
+			 * will mask NACK errors since TXCOMP is set when a
+			 * NACK occurs.
+			 */
+			at91_twi_write(dev, AT91_TWI_IER,
+			       AT91_TWI_TXCOMP);
+		} else
+			at91_twi_write(dev, AT91_TWI_IER,
 			       AT91_TWI_TXCOMP | AT91_TWI_RXRDY);
 	} else {
-		at91_twi_write_next_byte(dev);
-		at91_twi_write(dev, AT91_TWI_IER,
-			       AT91_TWI_TXCOMP | AT91_TWI_TXRDY);
+		if (dev->use_dma && (dev->buf_len > AT91_I2C_DMA_THRESHOLD)) {
+			at91_twi_write_data_dma(dev);
+			at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP);
+		} else {
+			at91_twi_write_next_byte(dev);
+			at91_twi_write(dev, AT91_TWI_IER,
+				AT91_TWI_TXCOMP | AT91_TWI_TXRDY);
+		}
 	}
 
 	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
@@ -242,23 +427,31 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
 	if (ret == 0) {
 		dev_err(dev->dev, "controller timed out\n");
 		at91_init_twi_bus(dev);
-		return -ETIMEDOUT;
+		ret = -ETIMEDOUT;
+		goto error;
 	}
 	if (dev->transfer_status & AT91_TWI_NACK) {
 		dev_dbg(dev->dev, "received nack\n");
-		return -EREMOTEIO;
+		ret = -EREMOTEIO;
+		goto error;
 	}
 	if (dev->transfer_status & AT91_TWI_OVRE) {
 		dev_err(dev->dev, "overrun while reading\n");
-		return -EIO;
+		ret = -EIO;
+		goto error;
 	}
 	if (has_unre_flag && dev->transfer_status & AT91_TWI_UNRE) {
 		dev_err(dev->dev, "underrun while writing\n");
-		return -EIO;
+		ret = -EIO;
+		goto error;
 	}
 	dev_dbg(dev->dev, "transfer complete\n");
 
 	return 0;
+
+error:
+	at91_twi_dma_cleanup(dev);
+	return ret;
 }
 
 static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
@@ -329,36 +522,42 @@ static struct at91_twi_pdata at91rm9200_config = {
 	.clk_max_div = 5,
 	.clk_offset = 3,
 	.has_unre_flag = true,
+	.has_dma_support = false,
 };
 
 static struct at91_twi_pdata at91sam9261_config = {
 	.clk_max_div = 5,
 	.clk_offset = 4,
 	.has_unre_flag = false,
+	.has_dma_support = false,
 };
 
 static struct at91_twi_pdata at91sam9260_config = {
 	.clk_max_div = 7,
 	.clk_offset = 4,
 	.has_unre_flag = false,
+	.has_dma_support = false,
 };
 
 static struct at91_twi_pdata at91sam9g20_config = {
 	.clk_max_div = 7,
 	.clk_offset = 4,
 	.has_unre_flag = false,
+	.has_dma_support = false,
 };
 
 static struct at91_twi_pdata at91sam9g10_config = {
 	.clk_max_div = 7,
 	.clk_offset = 4,
 	.has_unre_flag = false,
+	.has_dma_support = false,
 };
 
 static struct at91_twi_pdata at91sam9x5_config = {
 	.clk_max_div = 7,
 	.clk_offset = 4,
 	.has_unre_flag = false,
+	.has_dma_support = true,
 };
 
 static const struct platform_device_id at91_twi_devtypes[] = {
@@ -405,6 +604,90 @@ MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids);
 #define atmel_twi_dt_ids NULL
 #endif
 
+static bool __devinit filter(struct dma_chan *chan, void *slave)
+{
+	struct at_dma_slave *sl = slave;
+
+	if (sl->dma_dev == chan->device->dev) {
+		chan->private = sl;
+		return true;
+	} else {
+		return false;
+	}
+}
+
+static int __devinit at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr)
+{
+	int ret = 0;
+	struct at_dma_slave *sdata;
+	struct dma_slave_config slave_config;
+	struct at91_twi_dma *dma = &dev->dma;
+
+	sdata = &dev->pdata->dma_slave;
+
+	memset(&slave_config, 0, sizeof(slave_config));
+	slave_config.src_addr = (dma_addr_t)phy_addr + AT91_TWI_RHR;
+	slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	slave_config.src_maxburst = 1;
+	slave_config.dst_addr = (dma_addr_t)phy_addr + AT91_TWI_THR;
+	slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	slave_config.dst_maxburst = 1;
+	slave_config.device_fc = false;
+
+	if (sdata && sdata->dma_dev) {
+		dma_cap_mask_t mask;
+
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+		dma->chan_tx = dma_request_channel(mask, filter, sdata);
+		if (!dma->chan_tx) {
+			dev_err(dev->dev, "no DMA channel available for tx\n");
+			ret = -EBUSY;
+			goto error;
+		}
+		dma->chan_rx = dma_request_channel(mask, filter, sdata);
+		if (!dma->chan_rx) {
+			dev_err(dev->dev, "no DMA channel available for rx\n");
+			ret = -EBUSY;
+			goto error;
+		}
+	} else {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	slave_config.direction = DMA_MEM_TO_DEV;
+	if (dmaengine_slave_config(dma->chan_tx, &slave_config)) {
+		dev_err(dev->dev, "failed to configure tx channel\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	slave_config.direction = DMA_DEV_TO_MEM;
+	if (dmaengine_slave_config(dma->chan_rx, &slave_config)) {
+		dev_err(dev->dev, "failed to configure rx channel\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	sg_init_table(&dma->sg, 1);
+	dma->buf_mapped = false;
+	dma->xfer_in_progress = false;
+
+	dev_info(dev->dev, "using %s (tx) and %s (rx) for DMA transfers\n",
+		 dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx));
+
+	return ret;
+
+error:
+	dev_info(dev->dev, "can't use DMA\n");
+	if (dma->chan_rx)
+		dma_release_channel(dma->chan_rx);
+	if (dma->chan_tx)
+		dma_release_channel(dma->chan_tx);
+	return ret;
+}
+
 static struct at91_twi_pdata * __devinit at91_twi_get_driver_data(
 					struct platform_device *pdev)
 {
@@ -413,7 +696,7 @@ static struct at91_twi_pdata * __devinit at91_twi_get_driver_data(
 		match = of_match_node(atmel_twi_dt_ids, pdev->dev.of_node);
 		if (!match)
 			return NULL;
-		return match->data;
+		return (struct at91_twi_pdata *)match->data;
 	}
 	return (struct at91_twi_pdata *) platform_get_device_id(pdev)->driver_data;
 }
@@ -423,6 +706,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
 	struct at91_twi_dev *dev;
 	struct resource *mem;
 	int rc;
+	u32 phy_addr;
 
 	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
 	if (!dev)
@@ -433,6 +717,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem)
 		return -ENODEV;
+	phy_addr = mem->start;
 
 	dev->pdata = at91_twi_get_driver_data(pdev);
 	if (!dev->pdata)
@@ -462,6 +747,11 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
 	}
 	clk_prepare_enable(dev->clk);
 
+	if (dev->pdata->has_dma_support) {
+		if (at91_twi_configure_dma(dev, phy_addr) == 0)
+			dev->use_dma = true;
+	}
+
 	at91_calc_twi_clock(dev, TWI_CLK_HZ);
 	at91_init_twi_bus(dev);
 
diff --git a/drivers/i2c/busses/i2c-cbus-gpio.c b/drivers/i2c/busses/i2c-cbus-gpio.c
new file mode 100644
index 0000000..98386d6
--- /dev/null
+++ b/drivers/i2c/busses/i2c-cbus-gpio.c
@@ -0,0 +1,300 @@
+/*
+ * CBUS I2C driver for Nokia Internet Tablets.
+ *
+ * Copyright (C) 2004-2010 Nokia Corporation
+ *
+ * Based on code written by Juha Yrjölä, David Weinehall, Mikko Ylinen and
+ * Felipe Balbi. Converted to I2C driver by Aaro Koskinen.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/i2c-cbus-gpio.h>
+
+/*
+ * Bit counts are derived from Nokia implementation. These should be checked
+ * if other CBUS implementations appear.
+ */
+#define CBUS_ADDR_BITS	3
+#define CBUS_REG_BITS	5
+
+struct cbus_host {
+	spinlock_t	lock;		/* host lock */
+	struct device	*dev;
+	int		clk_gpio;
+	int		dat_gpio;
+	int		sel_gpio;
+};
+
+/**
+ * cbus_send_bit - sends one bit over the bus
+ * @host: the host we're using
+ * @bit: one bit of information to send
+ */
+static void cbus_send_bit(struct cbus_host *host, unsigned bit)
+{
+	gpio_set_value(host->dat_gpio, bit ? 1 : 0);
+	gpio_set_value(host->clk_gpio, 1);
+	gpio_set_value(host->clk_gpio, 0);
+}
+
+/**
+ * cbus_send_data - sends @len amount of data over the bus
+ * @host: the host we're using
+ * @data: the data to send
+ * @len: size of the transfer
+ */
+static void cbus_send_data(struct cbus_host *host, unsigned data, unsigned len)
+{
+	int i;
+
+	for (i = len; i > 0; i--)
+		cbus_send_bit(host, data & (1 << (i - 1)));
+}
+
+/**
+ * cbus_receive_bit - receives one bit from the bus
+ * @host: the host we're using
+ */
+static int cbus_receive_bit(struct cbus_host *host)
+{
+	int ret;
+
+	gpio_set_value(host->clk_gpio, 1);
+	ret = gpio_get_value(host->dat_gpio);
+	gpio_set_value(host->clk_gpio, 0);
+	return ret;
+}
+
+/**
+ * cbus_receive_word - receives 16-bit word from the bus
+ * @host: the host we're using
+ */
+static int cbus_receive_word(struct cbus_host *host)
+{
+	int ret = 0;
+	int i;
+
+	for (i = 16; i > 0; i--) {
+		int bit = cbus_receive_bit(host);
+
+		if (bit < 0)
+			return bit;
+
+		if (bit)
+			ret |= 1 << (i - 1);
+	}
+	return ret;
+}
+
+/**
+ * cbus_transfer - transfers data over the bus
+ * @host: the host we're using
+ * @rw: read/write flag
+ * @dev: device address
+ * @reg: register address
+ * @data: if @rw == I2C_SBUS_WRITE data to send otherwise 0
+ */
+static int cbus_transfer(struct cbus_host *host, char rw, unsigned dev,
+			 unsigned reg, unsigned data)
+{
+	unsigned long flags;
+	int ret;
+
+	/* We don't want interrupts disturbing our transfer */
+	spin_lock_irqsave(&host->lock, flags);
+
+	/* Reset state and start of transfer, SEL stays down during transfer */
+	gpio_set_value(host->sel_gpio, 0);
+
+	/* Set the DAT pin to output */
+	gpio_direction_output(host->dat_gpio, 1);
+
+	/* Send the device address */
+	cbus_send_data(host, dev, CBUS_ADDR_BITS);
+
+	/* Send the rw flag */
+	cbus_send_bit(host, rw == I2C_SMBUS_READ);
+
+	/* Send the register address */
+	cbus_send_data(host, reg, CBUS_REG_BITS);
+
+	if (rw == I2C_SMBUS_WRITE) {
+		cbus_send_data(host, data, 16);
+		ret = 0;
+	} else {
+		ret = gpio_direction_input(host->dat_gpio);
+		if (ret) {
+			dev_dbg(host->dev, "failed setting direction\n");
+			goto out;
+		}
+		gpio_set_value(host->clk_gpio, 1);
+
+		ret = cbus_receive_word(host);
+		if (ret < 0) {
+			dev_dbg(host->dev, "failed receiving data\n");
+			goto out;
+		}
+	}
+
+	/* Indicate end of transfer, SEL goes up until next transfer */
+	gpio_set_value(host->sel_gpio, 1);
+	gpio_set_value(host->clk_gpio, 1);
+	gpio_set_value(host->clk_gpio, 0);
+
+out:
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	return ret;
+}
+
+static int cbus_i2c_smbus_xfer(struct i2c_adapter	*adapter,
+			       u16			addr,
+			       unsigned short		flags,
+			       char			read_write,
+			       u8			command,
+			       int			size,
+			       union i2c_smbus_data	*data)
+{
+	struct cbus_host *chost = i2c_get_adapdata(adapter);
+	int ret;
+
+	if (size != I2C_SMBUS_WORD_DATA)
+		return -EINVAL;
+
+	ret = cbus_transfer(chost, read_write == I2C_SMBUS_READ, addr,
+			    command, data->word);
+	if (ret < 0)
+		return ret;
+
+	if (read_write == I2C_SMBUS_READ)
+		data->word = ret;
+
+	return 0;
+}
+
+static u32 cbus_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA;
+}
+
+static const struct i2c_algorithm cbus_i2c_algo = {
+	.smbus_xfer	= cbus_i2c_smbus_xfer,
+	.functionality	= cbus_i2c_func,
+};
+
+static int cbus_i2c_remove(struct platform_device *pdev)
+{
+	struct i2c_adapter *adapter = platform_get_drvdata(pdev);
+
+	return i2c_del_adapter(adapter);
+}
+
+static int cbus_i2c_probe(struct platform_device *pdev)
+{
+	struct i2c_adapter *adapter;
+	struct cbus_host *chost;
+	int ret;
+
+	adapter = devm_kzalloc(&pdev->dev, sizeof(struct i2c_adapter),
+			       GFP_KERNEL);
+	if (!adapter)
+		return -ENOMEM;
+
+	chost = devm_kzalloc(&pdev->dev, sizeof(*chost), GFP_KERNEL);
+	if (!chost)
+		return -ENOMEM;
+
+	if (pdev->dev.of_node) {
+		struct device_node *dnode = pdev->dev.of_node;
+		if (of_gpio_count(dnode) != 3)
+			return -ENODEV;
+		chost->clk_gpio = of_get_gpio(dnode, 0);
+		chost->dat_gpio = of_get_gpio(dnode, 1);
+		chost->sel_gpio = of_get_gpio(dnode, 2);
+	} else if (pdev->dev.platform_data) {
+		struct i2c_cbus_platform_data *pdata = pdev->dev.platform_data;
+		chost->clk_gpio = pdata->clk_gpio;
+		chost->dat_gpio = pdata->dat_gpio;
+		chost->sel_gpio = pdata->sel_gpio;
+	} else {
+		return -ENODEV;
+	}
+
+	adapter->owner		= THIS_MODULE;
+	adapter->class		= I2C_CLASS_HWMON;
+	adapter->dev.parent	= &pdev->dev;
+	adapter->nr		= pdev->id;
+	adapter->timeout	= HZ;
+	adapter->algo		= &cbus_i2c_algo;
+	strlcpy(adapter->name, "CBUS I2C adapter", sizeof(adapter->name));
+
+	spin_lock_init(&chost->lock);
+	chost->dev = &pdev->dev;
+
+	ret = devm_gpio_request_one(&pdev->dev, chost->clk_gpio,
+				    GPIOF_OUT_INIT_LOW, "CBUS clk");
+	if (ret)
+		return ret;
+
+	ret = devm_gpio_request_one(&pdev->dev, chost->dat_gpio, GPIOF_IN,
+				    "CBUS data");
+	if (ret)
+		return ret;
+
+	ret = devm_gpio_request_one(&pdev->dev, chost->sel_gpio,
+				    GPIOF_OUT_INIT_HIGH, "CBUS sel");
+	if (ret)
+		return ret;
+
+	i2c_set_adapdata(adapter, chost);
+	platform_set_drvdata(pdev, adapter);
+
+	return i2c_add_numbered_adapter(adapter);
+}
+
+#if defined(CONFIG_OF)
+static const struct of_device_id i2c_cbus_dt_ids[] = {
+	{ .compatible = "i2c-cbus-gpio", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, i2c_cbus_dt_ids);
+#endif
+
+static struct platform_driver cbus_i2c_driver = {
+	.probe	= cbus_i2c_probe,
+	.remove	= cbus_i2c_remove,
+	.driver	= {
+		.owner	= THIS_MODULE,
+		.name	= "i2c-cbus-gpio",
+	},
+};
+module_platform_driver(cbus_i2c_driver);
+
+MODULE_ALIAS("platform:i2c-cbus-gpio");
+MODULE_DESCRIPTION("CBUS I2C driver");
+MODULE_AUTHOR("Juha Yrjölä");
+MODULE_AUTHOR("David Weinehall");
+MODULE_AUTHOR("Mikko Ylinen");
+MODULE_AUTHOR("Felipe Balbi");
+MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index e62d2d9..257299a 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -184,7 +184,11 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev)
 	bit_data->data = pdata;
 
 	adap->owner = THIS_MODULE;
-	snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
+	if (pdev->dev.of_node)
+		strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));
+	else
+		snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
+
 	adap->algo_data = bit_data;
 	adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
 	adap->dev.parent = &pdev->dev;
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 6abc00d..1e73638 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -81,6 +81,7 @@
 #include <linux/slab.h>
 #include <linux/wait.h>
 #include <linux/err.h>
+#include <linux/of_i2c.h>
 
 #if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
 		defined CONFIG_DMI
@@ -1108,6 +1109,7 @@ static int __devinit i801_probe(struct pci_dev *dev,
 		/* fall through */
 	default:
 		priv->features |= FEATURE_I2C_BLOCK_READ;
+		priv->features |= FEATURE_IRQ;
 		/* fall through */
 	case PCI_DEVICE_ID_INTEL_82801DB_3:
 		priv->features |= FEATURE_SMBUS_PEC;
@@ -1120,16 +1122,6 @@ static int __devinit i801_probe(struct pci_dev *dev,
 		break;
 	}
 
-	/* IRQ processing tested on CougarPoint PCH, ICH5, ICH7-M and ICH10 */
-	if (dev->device == PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS ||
-	    dev->device == PCI_DEVICE_ID_INTEL_82801EB_3 ||
-	    dev->device == PCI_DEVICE_ID_INTEL_ICH7_17 ||
-	    dev->device == PCI_DEVICE_ID_INTEL_ICH8_5 ||
-	    dev->device == PCI_DEVICE_ID_INTEL_ICH9_6 ||
-	    dev->device == PCI_DEVICE_ID_INTEL_ICH10_4 ||
-	    dev->device == PCI_DEVICE_ID_INTEL_ICH10_5)
-		priv->features |= FEATURE_IRQ;
-
 	/* Disable features on user request */
 	for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) {
 		if (priv->features & disable_features & (1 << i))
@@ -1215,6 +1207,7 @@ static int __devinit i801_probe(struct pci_dev *dev,
 		goto exit_free_irq;
 	}
 
+	of_i2c_register_devices(&priv->adapter);
 	i801_probe_optional_slaves(priv);
 	/* We ignore errors - multiplexing is optional */
 	i801_add_mux(priv);
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 2ef162d..b973474 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -52,8 +52,6 @@
 #include <linux/of_device.h>
 #include <linux/of_i2c.h>
 #include <linux/pinctrl/consumer.h>
-
-#include <mach/hardware.h>
 #include <linux/platform_data/i2c-imx.h>
 
 /** Defines ********************************************************************
@@ -115,6 +113,11 @@ static u16 __initdata i2c_clk_div[50][2] = {
 	{ 3072,	0x1E }, { 3840,	0x1F }
 };
 
+enum imx_i2c_type {
+	IMX1_I2C,
+	IMX21_I2C,
+};
+
 struct imx_i2c_struct {
 	struct i2c_adapter	adapter;
 	struct clk		*clk;
@@ -124,13 +127,33 @@ struct imx_i2c_struct {
 	unsigned int 		disable_delay;
 	int			stopped;
 	unsigned int		ifdr; /* IMX_I2C_IFDR */
+	enum imx_i2c_type	devtype;
+};
+
+static struct platform_device_id imx_i2c_devtype[] = {
+	{
+		.name = "imx1-i2c",
+		.driver_data = IMX1_I2C,
+	}, {
+		.name = "imx21-i2c",
+		.driver_data = IMX21_I2C,
+	}, {
+		/* sentinel */
+	}
 };
+MODULE_DEVICE_TABLE(platform, imx_i2c_devtype);
 
 static const struct of_device_id i2c_imx_dt_ids[] = {
-	{ .compatible = "fsl,imx1-i2c", },
+	{ .compatible = "fsl,imx1-i2c", .data = &imx_i2c_devtype[IMX1_I2C], },
+	{ .compatible = "fsl,imx21-i2c", .data = &imx_i2c_devtype[IMX21_I2C], },
 	{ /* sentinel */ }
 };
 
+static inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx)
+{
+	return i2c_imx->devtype == IMX1_I2C;
+}
+
 /** Functions for IMX I2C adapter driver ***************************************
 *******************************************************************************/
 
@@ -223,7 +246,7 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
 		temp &= ~(I2CR_MSTA | I2CR_MTX);
 		writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
 	}
-	if (cpu_is_mx1()) {
+	if (is_imx1_i2c(i2c_imx)) {
 		/*
 		 * This delay caused by an i.MXL hardware bug.
 		 * If no (or too short) delay, no "STOP" bit will be generated.
@@ -465,6 +488,8 @@ static struct i2c_algorithm i2c_imx_algo = {
 
 static int __init i2c_imx_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *of_id = of_match_device(i2c_imx_dt_ids,
+							   &pdev->dev);
 	struct imx_i2c_struct *i2c_imx;
 	struct resource *res;
 	struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
@@ -497,6 +522,10 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
+	if (of_id)
+		pdev->id_entry = of_id->data;
+	i2c_imx->devtype = pdev->id_entry->driver_data;
+
 	/* Setup i2c_imx driver structure */
 	strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name));
 	i2c_imx->adapter.owner		= THIS_MODULE;
@@ -593,7 +622,8 @@ static struct platform_driver i2c_imx_driver = {
 		.name	= DRIVER_NAME,
 		.owner	= THIS_MODULE,
 		.of_match_table = i2c_imx_dt_ids,
-	}
+	},
+	.id_table	= imx_i2c_devtype,
 };
 
 static int __init i2c_adap_imx_init(void)
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 0670da7..6ed53da 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -359,7 +359,7 @@ static int mxs_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
 
 static u32 mxs_i2c_func(struct i2c_adapter *adap)
 {
-	return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
 static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
index 02c3115..8b2ffcf 100644
--- a/drivers/i2c/busses/i2c-nomadik.c
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -435,13 +435,6 @@ static int read_i2c(struct nmk_i2c_dev *dev, u16 flags)
 	timeout = wait_for_completion_timeout(
 		&dev->xfer_complete, dev->adap.timeout);
 
-	if (timeout < 0) {
-		dev_err(&dev->adev->dev,
-			"wait_for_completion_timeout "
-			"returned %d waiting for event\n", timeout);
-		status = timeout;
-	}
-
 	if (timeout == 0) {
 		/* Controller timed out */
 		dev_err(&dev->adev->dev, "read from slave 0x%x timed out\n",
@@ -523,13 +516,6 @@ static int write_i2c(struct nmk_i2c_dev *dev, u16 flags)
 	timeout = wait_for_completion_timeout(
 		&dev->xfer_complete, dev->adap.timeout);
 
-	if (timeout < 0) {
-		dev_err(&dev->adev->dev,
-			"wait_for_completion_timeout "
-			"returned %d waiting for event\n", timeout);
-		status = timeout;
-	}
-
 	if (timeout == 0) {
 		/* Controller timed out */
 		dev_err(&dev->adev->dev, "write to slave 0x%x timed out\n",
diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c
index f41502e..a23b91b 100644
--- a/drivers/i2c/busses/i2c-nuc900.c
+++ b/drivers/i2c/busses/i2c-nuc900.c
@@ -304,7 +304,7 @@ retry_write:
 
 	case STATE_READ:
 		/* we have a byte of data in the data register, do
-		 * something with it, and then work out wether we are
+		 * something with it, and then work out whether we are
 		 * going to do any more read/write
 		 */
 
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index bffd550..9b35c9f 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -4,15 +4,14 @@
  *
  * Peter Korsgaard <jacmet@sunsite.dk>
  *
+ * Support for the GRLIB port of the controller by
+ * Andreas Larsson <andreas@gaisler.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.
  */
 
-/*
- * This driver can be used from the device tree, see
- *     Documentation/devicetree/bindings/i2c/ocore-i2c.txt
- */
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -38,6 +37,8 @@ struct ocores_i2c {
 	int nmsgs;
 	int state; /* see STATE_ */
 	int clock_khz;
+	void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value);
+	u8 (*getreg)(struct ocores_i2c *i2c, int reg);
 };
 
 /* registers */
@@ -71,24 +72,47 @@ struct ocores_i2c {
 #define STATE_READ		3
 #define STATE_ERROR		4
 
+#define TYPE_OCORES		0
+#define TYPE_GRLIB		1
+
+static void oc_setreg_8(struct ocores_i2c *i2c, int reg, u8 value)
+{
+	iowrite8(value, i2c->base + (reg << i2c->reg_shift));
+}
+
+static void oc_setreg_16(struct ocores_i2c *i2c, int reg, u8 value)
+{
+	iowrite16(value, i2c->base + (reg << i2c->reg_shift));
+}
+
+static void oc_setreg_32(struct ocores_i2c *i2c, int reg, u8 value)
+{
+	iowrite32(value, i2c->base + (reg << i2c->reg_shift));
+}
+
+static inline u8 oc_getreg_8(struct ocores_i2c *i2c, int reg)
+{
+	return ioread8(i2c->base + (reg << i2c->reg_shift));
+}
+
+static inline u8 oc_getreg_16(struct ocores_i2c *i2c, int reg)
+{
+	return ioread16(i2c->base + (reg << i2c->reg_shift));
+}
+
+static inline u8 oc_getreg_32(struct ocores_i2c *i2c, int reg)
+{
+	return ioread32(i2c->base + (reg << i2c->reg_shift));
+}
+
 static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value)
 {
-	if (i2c->reg_io_width == 4)
-		iowrite32(value, i2c->base + (reg << i2c->reg_shift));
-	else if (i2c->reg_io_width == 2)
-		iowrite16(value, i2c->base + (reg << i2c->reg_shift));
-	else
-		iowrite8(value, i2c->base + (reg << i2c->reg_shift));
+	i2c->setreg(i2c, reg, value);
 }
 
 static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg)
 {
-	if (i2c->reg_io_width == 4)
-		return ioread32(i2c->base + (reg << i2c->reg_shift));
-	else if (i2c->reg_io_width == 2)
-		return ioread16(i2c->base + (reg << i2c->reg_shift));
-	else
-		return ioread8(i2c->base + (reg << i2c->reg_shift));
+	return i2c->getreg(i2c, reg);
 }
 
 static void ocores_process(struct ocores_i2c *i2c)
@@ -227,11 +251,59 @@ static struct i2c_adapter ocores_adapter = {
 	.algo		= &ocores_algorithm,
 };
 
+static struct of_device_id ocores_i2c_match[] = {
+	{
+		.compatible = "opencores,i2c-ocores",
+		.data = (void *)TYPE_OCORES,
+	},
+	{
+		.compatible = "aeroflexgaisler,i2cmst",
+		.data = (void *)TYPE_GRLIB,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, ocores_i2c_match);
+
 #ifdef CONFIG_OF
+/* Read and write functions for the GRLIB port of the controller. Registers are
+ * 32-bit big endian and the PRELOW and PREHIGH registers are merged into one
+ * register. The subsequent registers has their offset decreased accordingly. */
+static u8 oc_getreg_grlib(struct ocores_i2c *i2c, int reg)
+{
+	u32 rd;
+	int rreg = reg;
+	if (reg != OCI2C_PRELOW)
+		rreg--;
+	rd = ioread32be(i2c->base + (rreg << i2c->reg_shift));
+	if (reg == OCI2C_PREHIGH)
+		return (u8)(rd >> 8);
+	else
+		return (u8)rd;
+}
+
+static void oc_setreg_grlib(struct ocores_i2c *i2c, int reg, u8 value)
+{
+	u32 curr, wr;
+	int rreg = reg;
+	if (reg != OCI2C_PRELOW)
+		rreg--;
+	if (reg == OCI2C_PRELOW || reg == OCI2C_PREHIGH) {
+		curr = ioread32be(i2c->base + (rreg << i2c->reg_shift));
+		if (reg == OCI2C_PRELOW)
+			wr = (curr & 0xff00) | value;
+		else
+			wr = (((u32)value) << 8) | (curr & 0xff);
+	} else {
+		wr = value;
+	}
+	iowrite32be(wr, i2c->base + (rreg << i2c->reg_shift));
+}
+
 static int ocores_i2c_of_probe(struct platform_device *pdev,
 				struct ocores_i2c *i2c)
 {
 	struct device_node *np = pdev->dev.of_node;
+	const struct of_device_id *match;
 	u32 val;
 
 	if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) {
@@ -257,6 +329,14 @@ static int ocores_i2c_of_probe(struct platform_device *pdev,
 
 	of_property_read_u32(pdev->dev.of_node, "reg-io-width",
 				&i2c->reg_io_width);
+
+	match = of_match_node(ocores_i2c_match, pdev->dev.of_node);
+	if (match && (int)match->data == TYPE_GRLIB) {
+		dev_dbg(&pdev->dev, "GRLIB variant of i2c-ocores\n");
+		i2c->setreg = oc_setreg_grlib;
+		i2c->getreg = oc_getreg_grlib;
+	}
+
 	return 0;
 }
 #else
@@ -267,7 +347,8 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
 {
 	struct ocores_i2c *i2c;
 	struct ocores_i2c_platform_data *pdata;
-	struct resource *res, *res2;
+	struct resource *res;
+	int irq;
 	int ret;
 	int i;
 
@@ -275,26 +356,17 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
 	if (!res)
 		return -ENODEV;
 
-	res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res2)
-		return -ENODEV;
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
 
 	i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
 	if (!i2c)
 		return -ENOMEM;
 
-	if (!devm_request_mem_region(&pdev->dev, res->start,
-				     resource_size(res), pdev->name)) {
-		dev_err(&pdev->dev, "Memory region busy\n");
-		return -EBUSY;
-	}
-
-	i2c->base = devm_ioremap_nocache(&pdev->dev, res->start,
-					 resource_size(res));
-	if (!i2c->base) {
-		dev_err(&pdev->dev, "Unable to map registers\n");
-		return -EIO;
-	}
+	i2c->base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!i2c->base)
+		return -EADDRNOTAVAIL;
 
 	pdata = pdev->dev.platform_data;
 	if (pdata) {
@@ -310,10 +382,34 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
 	if (i2c->reg_io_width == 0)
 		i2c->reg_io_width = 1; /* Set to default value */
 
+	if (!i2c->setreg || !i2c->getreg) {
+		switch (i2c->reg_io_width) {
+		case 1:
+			i2c->setreg = oc_setreg_8;
+			i2c->getreg = oc_getreg_8;
+			break;
+
+		case 2:
+			i2c->setreg = oc_setreg_16;
+			i2c->getreg = oc_getreg_16;
+			break;
+
+		case 4:
+			i2c->setreg = oc_setreg_32;
+			i2c->getreg = oc_getreg_32;
+			break;
+
+		default:
+			dev_err(&pdev->dev, "Unsupported I/O width (%d)\n",
+				i2c->reg_io_width);
+			return -EINVAL;
+		}
+	}
+
 	ocores_init(i2c);
 
 	init_waitqueue_head(&i2c->wait);
-	ret = devm_request_irq(&pdev->dev, res2->start, ocores_isr, 0,
+	ret = devm_request_irq(&pdev->dev, irq, ocores_isr, 0,
 			       pdev->name, i2c);
 	if (ret) {
 		dev_err(&pdev->dev, "Cannot claim IRQ\n");
@@ -387,12 +483,6 @@ static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume);
 #define OCORES_I2C_PM	NULL
 #endif
 
-static struct of_device_id ocores_i2c_match[] = {
-	{ .compatible = "opencores,i2c-ocores", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, ocores_i2c_match);
-
 static struct platform_driver ocores_i2c_driver = {
 	.probe   = ocores_i2c_probe,
 	.remove  = __devexit_p(ocores_i2c_remove),
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 3525c9e..2482801 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -43,14 +43,16 @@
 #include <linux/slab.h>
 #include <linux/i2c-omap.h>
 #include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
 
 /* I2C controller revisions */
 #define OMAP_I2C_OMAP1_REV_2		0x20
 
 /* I2C controller revisions present on specific hardware */
-#define OMAP_I2C_REV_ON_2430		0x36
-#define OMAP_I2C_REV_ON_3430_3530	0x3C
-#define OMAP_I2C_REV_ON_3630_4430	0x40
+#define OMAP_I2C_REV_ON_2430		0x00000036
+#define OMAP_I2C_REV_ON_3430_3530	0x0000003C
+#define OMAP_I2C_REV_ON_3630		0x00000040
+#define OMAP_I2C_REV_ON_4430_PLUS	0x50400002
 
 /* timeout waiting for the controller to respond */
 #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
@@ -190,7 +192,6 @@ struct omap_i2c_dev {
 	void			(*set_mpu_wkup_lat)(struct device *dev,
 						    long latency);
 	u32			speed;		/* Speed of bus in kHz */
-	u32			dtrev;		/* extra revision from DT */
 	u32			flags;
 	u16			cmd_err;
 	u8			*buf;
@@ -202,17 +203,18 @@ struct omap_i2c_dev {
 						 * fifo_size==0 implies no fifo
 						 * if set, should be trsh+1
 						 */
-	u8			rev;
+	u32			rev;
 	unsigned		b_hw:1;		/* bad h/w fixes */
 	unsigned		receiver:1;	/* true when we're in receiver mode */
 	u16			iestate;	/* Saved interrupt register */
 	u16			pscstate;
 	u16			scllstate;
 	u16			sclhstate;
-	u16			bufstate;
 	u16			syscstate;
 	u16			westate;
 	u16			errata;
+
+	struct pinctrl		*pins;
 };
 
 static const u8 reg_map_ip_v1[] = {
@@ -275,16 +277,39 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
 				(i2c_dev->regs[reg] << i2c_dev->reg_shift));
 }
 
-static int omap_i2c_init(struct omap_i2c_dev *dev)
+static void __omap_i2c_init(struct omap_i2c_dev *dev)
+{
+
+	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
+
+	/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
+	omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate);
+
+	/* SCL low and high time values */
+	omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate);
+	omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, dev->sclhstate);
+	if (dev->rev >= OMAP_I2C_REV_ON_3430_3530)
+		omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
+
+	/* Take the I2C module out of reset: */
+	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
+
+	/*
+	 * Don't write to this register if the IE state is 0 as it can
+	 * cause deadlock.
+	 */
+	if (dev->iestate)
+		omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
+}
+
+static int omap_i2c_reset(struct omap_i2c_dev *dev)
 {
-	u16 psc = 0, scll = 0, sclh = 0, buf = 0;
-	u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0;
-	unsigned long fclk_rate = 12000000;
 	unsigned long timeout;
-	unsigned long internal_clk = 0;
-	struct clk *fclk;
+	u16 sysc;
 
 	if (dev->rev >= OMAP_I2C_OMAP1_REV_2) {
+		sysc = omap_i2c_read_reg(dev, OMAP_I2C_SYSC_REG);
+
 		/* Disable I2C controller before soft reset */
 		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
 			omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) &
@@ -306,32 +331,28 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 		}
 
 		/* SYSC register is cleared by the reset; rewrite it */
-		if (dev->rev == OMAP_I2C_REV_ON_2430) {
-
-			omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
-					   SYSC_AUTOIDLE_MASK);
-
-		} else if (dev->rev >= OMAP_I2C_REV_ON_3430_3530) {
-			dev->syscstate = SYSC_AUTOIDLE_MASK;
-			dev->syscstate |= SYSC_ENAWAKEUP_MASK;
-			dev->syscstate |= (SYSC_IDLEMODE_SMART <<
-			      __ffs(SYSC_SIDLEMODE_MASK));
-			dev->syscstate |= (SYSC_CLOCKACTIVITY_FCLK <<
-			      __ffs(SYSC_CLOCKACTIVITY_MASK));
-
-			omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
-							dev->syscstate);
-			/*
-			 * Enabling all wakup sources to stop I2C freezing on
-			 * WFI instruction.
-			 * REVISIT: Some wkup sources might not be needed.
-			 */
-			dev->westate = OMAP_I2C_WE_ALL;
-			omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
-							dev->westate);
-		}
+		omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, sysc);
+
+	}
+	return 0;
+}
+
+static int omap_i2c_init(struct omap_i2c_dev *dev)
+{
+	u16 psc = 0, scll = 0, sclh = 0;
+	u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0;
+	unsigned long fclk_rate = 12000000;
+	unsigned long internal_clk = 0;
+	struct clk *fclk;
+
+	if (dev->rev >= OMAP_I2C_REV_ON_3430_3530) {
+		/*
+		 * Enabling all wakup sources to stop I2C freezing on
+		 * WFI instruction.
+		 * REVISIT: Some wkup sources might not be needed.
+		 */
+		dev->westate = OMAP_I2C_WE_ALL;
 	}
-	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
 
 	if (dev->flags & OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK) {
 		/*
@@ -416,28 +437,17 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 		sclh = fclk_rate / (dev->speed * 2) - 7 + psc;
 	}
 
-	/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
-	omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc);
-
-	/* SCL low and high time values */
-	omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
-	omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
-
-	/* Take the I2C module out of reset: */
-	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
-
-	/* Enable interrupts */
 	dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
 			OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
 			OMAP_I2C_IE_AL)  | ((dev->fifo_size) ?
 				(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0);
-	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
-	if (dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
-		dev->pscstate = psc;
-		dev->scllstate = scll;
-		dev->sclhstate = sclh;
-		dev->bufstate = buf;
-	}
+
+	dev->pscstate = psc;
+	dev->scllstate = scll;
+	dev->sclhstate = sclh;
+
+	__omap_i2c_init(dev);
+
 	return 0;
 }
 
@@ -490,7 +500,7 @@ static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx)
 
 	omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf);
 
-	if (dev->rev < OMAP_I2C_REV_ON_3630_4430)
+	if (dev->rev < OMAP_I2C_REV_ON_3630)
 		dev->b_hw = 1; /* Enable hardware fixes */
 
 	/* calculate wakeup latency constraint for MPU */
@@ -586,7 +596,8 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
 						OMAP_I2C_TIMEOUT);
 	if (timeout == 0) {
 		dev_err(dev->dev, "controller timed out\n");
-		omap_i2c_init(dev);
+		omap_i2c_reset(dev);
+		__omap_i2c_init(dev);
 		return -ETIMEDOUT;
 	}
 
@@ -596,7 +607,8 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
 	/* We have an error */
 	if (dev->cmd_err & (OMAP_I2C_STAT_AL | OMAP_I2C_STAT_ROVR |
 			    OMAP_I2C_STAT_XUDF)) {
-		omap_i2c_init(dev);
+		omap_i2c_reset(dev);
+		__omap_i2c_init(dev);
 		return -EIO;
 	}
 
@@ -642,13 +654,14 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 			break;
 	}
 
-	if (dev->set_mpu_wkup_lat != NULL)
-		dev->set_mpu_wkup_lat(dev->dev, -1);
-
 	if (r == 0)
 		r = num;
 
 	omap_i2c_wait_for_bb(dev);
+
+	if (dev->set_mpu_wkup_lat != NULL)
+		dev->set_mpu_wkup_lat(dev->dev, -1);
+
 out:
 	pm_runtime_mark_last_busy(dev->dev);
 	pm_runtime_put_autosuspend(dev->dev);
@@ -1025,8 +1038,7 @@ static const struct i2c_algorithm omap_i2c_algo = {
 #ifdef CONFIG_OF
 static struct omap_i2c_bus_platform_data omap3_pdata = {
 	.rev = OMAP_I2C_IP_VERSION_1,
-	.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
-		 OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
+	.flags = OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
 		 OMAP_I2C_FLAG_BUS_SHIFT_2,
 };
 
@@ -1048,6 +1060,16 @@ static const struct of_device_id omap_i2c_of_match[] = {
 MODULE_DEVICE_TABLE(of, omap_i2c_of_match);
 #endif
 
+#define OMAP_I2C_SCHEME(rev)		((rev & 0xc000) >> 14)
+
+#define OMAP_I2C_REV_SCHEME_0_MAJOR(rev) (rev >> 4)
+#define OMAP_I2C_REV_SCHEME_0_MINOR(rev) (rev & 0xf)
+
+#define OMAP_I2C_REV_SCHEME_1_MAJOR(rev) ((rev & 0x0700) >> 7)
+#define OMAP_I2C_REV_SCHEME_1_MINOR(rev) (rev & 0x1f)
+#define OMAP_I2C_SCHEME_0		0
+#define OMAP_I2C_SCHEME_1		1
+
 static int __devinit
 omap_i2c_probe(struct platform_device *pdev)
 {
@@ -1060,6 +1082,8 @@ omap_i2c_probe(struct platform_device *pdev)
 	const struct of_device_id *match;
 	int irq;
 	int r;
+	u32 rev;
+	u16 minor, major, scheme;
 
 	/* NOTE: driver uses the static register mapping */
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1091,7 +1115,6 @@ omap_i2c_probe(struct platform_device *pdev)
 		u32 freq = 100000; /* default to 100000 Hz */
 
 		pdata = match->data;
-		dev->dtrev = pdata->rev;
 		dev->flags = pdata->flags;
 
 		of_property_read_u32(node, "clock-frequency", &freq);
@@ -1101,7 +1124,16 @@ omap_i2c_probe(struct platform_device *pdev)
 		dev->speed = pdata->clkrate;
 		dev->flags = pdata->flags;
 		dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
-		dev->dtrev = pdata->rev;
+	}
+
+	dev->pins = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(dev->pins)) {
+		if (PTR_ERR(dev->pins) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		dev_warn(&pdev->dev, "did not get pins for i2c error: %li\n",
+			 PTR_ERR(dev->pins));
+		dev->pins = NULL;
 	}
 
 	dev->dev = &pdev->dev;
@@ -1114,11 +1146,6 @@ omap_i2c_probe(struct platform_device *pdev)
 
 	dev->reg_shift = (dev->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3;
 
-	if (dev->dtrev == OMAP_I2C_IP_VERSION_2)
-		dev->regs = (u8 *)reg_map_ip_v2;
-	else
-		dev->regs = (u8 *)reg_map_ip_v1;
-
 	pm_runtime_enable(dev->dev);
 	pm_runtime_set_autosuspend_delay(dev->dev, OMAP_I2C_PM_TIMEOUT);
 	pm_runtime_use_autosuspend(dev->dev);
@@ -1127,11 +1154,37 @@ omap_i2c_probe(struct platform_device *pdev)
 	if (IS_ERR_VALUE(r))
 		goto err_free_mem;
 
-	dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
+	/*
+	 * Read the Rev hi bit-[15:14] ie scheme this is 1 indicates ver2.
+	 * On omap1/3/2 Offset 4 is IE Reg the bit [15:14] is 0 at reset.
+	 * Also since the omap_i2c_read_reg uses reg_map_ip_* a
+	 * raw_readw is done.
+	 */
+	rev = __raw_readw(dev->base + 0x04);
+
+	scheme = OMAP_I2C_SCHEME(rev);
+	switch (scheme) {
+	case OMAP_I2C_SCHEME_0:
+		dev->regs = (u8 *)reg_map_ip_v1;
+		dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG);
+		minor = OMAP_I2C_REV_SCHEME_0_MAJOR(dev->rev);
+		major = OMAP_I2C_REV_SCHEME_0_MAJOR(dev->rev);
+		break;
+	case OMAP_I2C_SCHEME_1:
+		/* FALLTHROUGH */
+	default:
+		dev->regs = (u8 *)reg_map_ip_v2;
+		rev = (rev << 16) |
+			omap_i2c_read_reg(dev, OMAP_I2C_IP_V2_REVNB_LO);
+		minor = OMAP_I2C_REV_SCHEME_1_MINOR(rev);
+		major = OMAP_I2C_REV_SCHEME_1_MAJOR(rev);
+		dev->rev = rev;
+	}
 
 	dev->errata = 0;
 
-	if (dev->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207)
+	if (dev->rev >= OMAP_I2C_REV_ON_2430 &&
+			dev->rev < OMAP_I2C_REV_ON_4430_PLUS)
 		dev->errata |= I2C_OMAP_ERRATA_I207;
 
 	if (dev->rev <= OMAP_I2C_REV_ON_3430_3530)
@@ -1152,7 +1205,7 @@ omap_i2c_probe(struct platform_device *pdev)
 
 		dev->fifo_size = (dev->fifo_size / 2);
 
-		if (dev->rev < OMAP_I2C_REV_ON_3630_4430)
+		if (dev->rev < OMAP_I2C_REV_ON_3630)
 			dev->b_hw = 1; /* Enable hardware fixes */
 
 		/* calculate wakeup latency constraint for MPU */
@@ -1195,8 +1248,8 @@ omap_i2c_probe(struct platform_device *pdev)
 		goto err_unuse_clocks;
 	}
 
-	dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", adap->nr,
-		 dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
+	dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n", adap->nr,
+		 major, minor, dev->speed);
 
 	of_i2c_register_devices(adap);
 
@@ -1239,14 +1292,13 @@ static int omap_i2c_runtime_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct omap_i2c_dev *_dev = platform_get_drvdata(pdev);
-	u16 iv;
 
 	_dev->iestate = omap_i2c_read_reg(_dev, OMAP_I2C_IE_REG);
 
 	omap_i2c_write_reg(_dev, OMAP_I2C_IE_REG, 0);
 
 	if (_dev->rev < OMAP_I2C_OMAP1_REV_2) {
-		iv = omap_i2c_read_reg(_dev, OMAP_I2C_IV_REG); /* Read clears */
+		omap_i2c_read_reg(_dev, OMAP_I2C_IV_REG); /* Read clears */
 	} else {
 		omap_i2c_write_reg(_dev, OMAP_I2C_STAT_REG, _dev->iestate);
 
@@ -1262,23 +1314,10 @@ static int omap_i2c_runtime_resume(struct device *dev)
 	struct platform_device *pdev = to_platform_device(dev);
 	struct omap_i2c_dev *_dev = platform_get_drvdata(pdev);
 
-	if (_dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
-		omap_i2c_write_reg(_dev, OMAP_I2C_CON_REG, 0);
-		omap_i2c_write_reg(_dev, OMAP_I2C_PSC_REG, _dev->pscstate);
-		omap_i2c_write_reg(_dev, OMAP_I2C_SCLL_REG, _dev->scllstate);
-		omap_i2c_write_reg(_dev, OMAP_I2C_SCLH_REG, _dev->sclhstate);
-		omap_i2c_write_reg(_dev, OMAP_I2C_BUF_REG, _dev->bufstate);
-		omap_i2c_write_reg(_dev, OMAP_I2C_SYSC_REG, _dev->syscstate);
-		omap_i2c_write_reg(_dev, OMAP_I2C_WE_REG, _dev->westate);
-		omap_i2c_write_reg(_dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
-	}
+	if (!_dev->regs)
+		return 0;
 
-	/*
-	 * Don't write to this register if the IE state is 0 as it can
-	 * cause deadlock.
-	 */
-	if (_dev->iestate)
-		omap_i2c_write_reg(_dev, OMAP_I2C_IE_REG, _dev->iestate);
+	__omap_i2c_init(_dev);
 
 	return 0;
 }
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 8bbd6ec..f7216ed 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -204,9 +204,8 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
 			 */
 			pci_write_config_byte(PIIX4_dev, SMBHSTCFG,
 					      temp | 1);
-			dev_printk(KERN_NOTICE, &PIIX4_dev->dev,
-				"WARNING: SMBus interface has been "
-				"FORCEFULLY ENABLED!\n");
+			dev_notice(&PIIX4_dev->dev,
+				   "WARNING: SMBus interface has been FORCEFULLY ENABLED!\n");
 		} else {
 			dev_err(&PIIX4_dev->dev,
 				"Host SMBus controller not enabled!\n");
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index f9399d1..72a8071 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -642,7 +642,7 @@ static int __devinit rcar_i2c_probe(struct platform_device *pdev)
 	if (ret < 0)
 		return ret;
 
-	priv->io = devm_ioremap(dev, res->start, resource_size(res));
+	priv->io = devm_request_and_ioremap(dev, res);
 	if (!priv->io) {
 		dev_err(dev, "cannot ioremap\n");
 		return -ENODEV;
@@ -693,7 +693,7 @@ static int __devexit rcar_i2c_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static struct platform_driver rcar_i2c_drv = {
+static struct platform_driver rcar_i2c_driver = {
 	.driver	= {
 		.name	= "i2c-rcar",
 		.owner	= THIS_MODULE,
@@ -702,7 +702,7 @@ static struct platform_driver rcar_i2c_drv = {
 	.remove		= __devexit_p(rcar_i2c_remove),
 };
 
-module_platform_driver(rcar_i2c_drv);
+module_platform_driver(rcar_i2c_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Renesas R-Car I2C bus driver");
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 9d90272..a290d08 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -38,6 +38,7 @@
 #include <linux/io.h>
 #include <linux/of_i2c.h>
 #include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
 
 #include <asm/irq.h>
 
@@ -49,6 +50,9 @@
 #define QUIRK_HDMIPHY		(1 << 1)
 #define QUIRK_NO_GPIO		(1 << 2)
 
+/* Max time to wait for bus to become idle after a xfer (in us) */
+#define S3C2410_IDLE_TIMEOUT	5000
+
 /* i2c controller state */
 enum s3c24xx_i2c_state {
 	STATE_IDLE,
@@ -59,7 +63,6 @@ enum s3c24xx_i2c_state {
 };
 
 struct s3c24xx_i2c {
-	spinlock_t		lock;
 	wait_queue_head_t	wait;
 	unsigned int            quirks;
 	unsigned int		suspended:1;
@@ -78,11 +81,11 @@ struct s3c24xx_i2c {
 	void __iomem		*regs;
 	struct clk		*clk;
 	struct device		*dev;
-	struct resource		*ioarea;
 	struct i2c_adapter	adap;
 
 	struct s3c2410_platform_i2c	*pdata;
 	int			gpios[2];
+	struct pinctrl          *pctrl;
 #ifdef CONFIG_CPU_FREQ
 	struct notifier_block	freq_transition;
 #endif
@@ -208,7 +211,7 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
 	if (msg->flags & I2C_M_REV_DIR_ADDR)
 		addr ^= 1;
 
-	/* todo - check for wether ack wanted or not */
+	/* todo - check for whether ack wanted or not */
 	s3c24xx_i2c_enable_ack(i2c);
 
 	iiccon = readl(i2c->regs + S3C2410_IICCON);
@@ -235,8 +238,47 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
 
 	dev_dbg(i2c->dev, "STOP\n");
 
-	/* stop the transfer */
-	iicstat &= ~S3C2410_IICSTAT_START;
+	/*
+	 * The datasheet says that the STOP sequence should be:
+	 *  1) I2CSTAT.5 = 0	- Clear BUSY (or 'generate STOP')
+	 *  2) I2CCON.4 = 0	- Clear IRQPEND
+	 *  3) Wait until the stop condition takes effect.
+	 *  4*) I2CSTAT.4 = 0	- Clear TXRXEN
+	 *
+	 * Where, step "4*" is only for buses with the "HDMIPHY" quirk.
+	 *
+	 * However, after much experimentation, it appears that:
+	 * a) normal buses automatically clear BUSY and transition from
+	 *    Master->Slave when they complete generating a STOP condition.
+	 *    Therefore, step (3) can be done in doxfer() by polling I2CCON.4
+	 *    after starting the STOP generation here.
+	 * b) HDMIPHY bus does neither, so there is no way to do step 3.
+	 *    There is no indication when this bus has finished generating
+	 *    STOP.
+	 *
+	 * In fact, we have found that as soon as the IRQPEND bit is cleared in
+	 * step 2, the HDMIPHY bus generates the STOP condition, and then
+	 * immediately starts transferring another data byte, even though the
+	 * bus is supposedly stopped.  This is presumably because the bus is
+	 * still in "Master" mode, and its BUSY bit is still set.
+	 *
+	 * To avoid these extra post-STOP transactions on HDMI phy devices, we
+	 * just disable Serial Output on the bus (I2CSTAT.4 = 0) directly,
+	 * instead of first generating a proper STOP condition.  This should
+	 * float SDA & SCK terminating the transfer.  Subsequent transfers
+	 *  start with a proper START condition, and proceed normally.
+	 *
+	 * The HDMIPHY bus is an internal bus that always has exactly two
+	 * devices, the host as Master and the HDMIPHY device as the slave.
+	 * Skipping the STOP condition has been tested on this bus and works.
+	 */
+	if (i2c->quirks & QUIRK_HDMIPHY) {
+		/* Stop driving the I2C pins */
+		iicstat &= ~S3C2410_IICSTAT_TXRXEN;
+	} else {
+		/* stop the transfer */
+		iicstat &= ~S3C2410_IICSTAT_START;
+	}
 	writel(iicstat, i2c->regs + S3C2410_IICSTAT);
 
 	i2c->state = STATE_STOP;
@@ -397,7 +439,7 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
 
 	case STATE_READ:
 		/* we have a byte of data in the data register, do
-		 * something with it, and then work out wether we are
+		 * something with it, and then work out whether we are
 		 * going to do any more read/write
 		 */
 
@@ -490,13 +532,6 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
 	unsigned long iicstat;
 	int timeout = 400;
 
-	/* the timeout for HDMIPHY is reduced to 10 ms because
-	 * the hangup is expected to happen, so waiting 400 ms
-	 * causes only unnecessary system hangup
-	 */
-	if (i2c->quirks & QUIRK_HDMIPHY)
-		timeout = 10;
-
 	while (timeout-- > 0) {
 		iicstat = readl(i2c->regs + S3C2410_IICSTAT);
 
@@ -506,16 +541,61 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
 		msleep(1);
 	}
 
-	/* hang-up of bus dedicated for HDMIPHY occurred, resetting */
-	if (i2c->quirks & QUIRK_HDMIPHY) {
-		writel(0, i2c->regs + S3C2410_IICCON);
-		writel(0, i2c->regs + S3C2410_IICSTAT);
-		writel(0, i2c->regs + S3C2410_IICDS);
+	return -ETIMEDOUT;
+}
 
-		return 0;
+/* s3c24xx_i2c_wait_idle
+ *
+ * wait for the i2c bus to become idle.
+*/
+
+static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c)
+{
+	unsigned long iicstat;
+	ktime_t start, now;
+	unsigned long delay;
+	int spins;
+
+	/* ensure the stop has been through the bus */
+
+	dev_dbg(i2c->dev, "waiting for bus idle\n");
+
+	start = now = ktime_get();
+
+	/*
+	 * Most of the time, the bus is already idle within a few usec of the
+	 * end of a transaction.  However, really slow i2c devices can stretch
+	 * the clock, delaying STOP generation.
+	 *
+	 * On slower SoCs this typically happens within a very small number of
+	 * instructions so busy wait briefly to avoid scheduling overhead.
+	 */
+	spins = 3;
+	iicstat = readl(i2c->regs + S3C2410_IICSTAT);
+	while ((iicstat & S3C2410_IICSTAT_START) && --spins) {
+		cpu_relax();
+		iicstat = readl(i2c->regs + S3C2410_IICSTAT);
 	}
 
-	return -ETIMEDOUT;
+	/*
+	 * If we do get an appreciable delay as a compromise between idle
+	 * detection latency for the normal, fast case, and system load in the
+	 * slow device case, use an exponential back off in the polling loop,
+	 * up to 1/10th of the total timeout, then continue to poll at a
+	 * constant rate up to the timeout.
+	 */
+	delay = 1;
+	while ((iicstat & S3C2410_IICSTAT_START) &&
+	       ktime_us_delta(now, start) < S3C2410_IDLE_TIMEOUT) {
+		usleep_range(delay, 2 * delay);
+		if (delay < S3C2410_IDLE_TIMEOUT / 10)
+			delay <<= 1;
+		now = ktime_get();
+		iicstat = readl(i2c->regs + S3C2410_IICSTAT);
+	}
+
+	if (iicstat & S3C2410_IICSTAT_START)
+		dev_warn(i2c->dev, "timeout waiting for bus idle\n");
 }
 
 /* s3c24xx_i2c_doxfer
@@ -526,8 +606,7 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
 static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
 			      struct i2c_msg *msgs, int num)
 {
-	unsigned long iicstat, timeout;
-	int spins = 20;
+	unsigned long timeout;
 	int ret;
 
 	if (i2c->suspended)
@@ -540,8 +619,6 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
 		goto out;
 	}
 
-	spin_lock_irq(&i2c->lock);
-
 	i2c->msg     = msgs;
 	i2c->msg_num = num;
 	i2c->msg_ptr = 0;
@@ -550,7 +627,6 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
 
 	s3c24xx_i2c_enable_irq(i2c);
 	s3c24xx_i2c_message_start(i2c, msgs);
-	spin_unlock_irq(&i2c->lock);
 
 	timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
 
@@ -564,24 +640,11 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
 	else if (ret != num)
 		dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
 
-	/* ensure the stop has been through the bus */
-
-	dev_dbg(i2c->dev, "waiting for bus idle\n");
-
-	/* first, try busy waiting briefly */
-	do {
-		cpu_relax();
-		iicstat = readl(i2c->regs + S3C2410_IICSTAT);
-	} while ((iicstat & S3C2410_IICSTAT_START) && --spins);
-
-	/* if that timed out sleep */
-	if (!spins) {
-		msleep(1);
-		iicstat = readl(i2c->regs + S3C2410_IICSTAT);
-	}
+	/* For QUIRK_HDMIPHY, bus is already disabled */
+	if (i2c->quirks & QUIRK_HDMIPHY)
+		goto out;
 
-	if (iicstat & S3C2410_IICSTAT_START)
-		dev_warn(i2c->dev, "timeout waiting for bus idle\n");
+	s3c24xx_i2c_wait_idle(i2c);
 
  out:
 	return ret;
@@ -740,7 +803,6 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb,
 					  unsigned long val, void *data)
 {
 	struct s3c24xx_i2c *i2c = freq_to_i2c(nb);
-	unsigned long flags;
 	unsigned int got;
 	int delta_f;
 	int ret;
@@ -754,9 +816,9 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb,
 
 	if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) ||
 	    (val == CPUFREQ_PRECHANGE && delta_f > 0)) {
-		spin_lock_irqsave(&i2c->lock, flags);
+		i2c_lock_adapter(&i2c->adap);
 		ret = s3c24xx_i2c_clockrate(i2c, &got);
-		spin_unlock_irqrestore(&i2c->lock, flags);
+		i2c_unlock_adapter(&i2c->adap);
 
 		if (ret < 0)
 			dev_err(i2c->dev, "cannot find frequency\n");
@@ -858,14 +920,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
 
 	pdata = i2c->pdata;
 
-	/* inititalise the gpio */
-
-	if (pdata->cfg_gpio)
-		pdata->cfg_gpio(to_platform_device(i2c->dev));
-	else
-		if (s3c24xx_i2c_parse_dt_gpio(i2c))
-			return -EINVAL;
-
 	/* write slave address */
 
 	writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD);
@@ -963,7 +1017,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
 	i2c->adap.class   = I2C_CLASS_HWMON | I2C_CLASS_SPD;
 	i2c->tx_setup     = 50;
 
-	spin_lock_init(&i2c->lock);
 	init_waitqueue_head(&i2c->wait);
 
 	/* find the clock and enable it */
@@ -989,36 +1042,38 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
 		goto err_clk;
 	}
 
-	i2c->ioarea = request_mem_region(res->start, resource_size(res),
-					 pdev->name);
-
-	if (i2c->ioarea == NULL) {
-		dev_err(&pdev->dev, "cannot request IO\n");
-		ret = -ENXIO;
-		goto err_clk;
-	}
-
-	i2c->regs = ioremap(res->start, resource_size(res));
+	i2c->regs = devm_request_and_ioremap(&pdev->dev, res);
 
 	if (i2c->regs == NULL) {
 		dev_err(&pdev->dev, "cannot map IO\n");
 		ret = -ENXIO;
-		goto err_ioarea;
+		goto err_clk;
 	}
 
-	dev_dbg(&pdev->dev, "registers %p (%p, %p)\n",
-		i2c->regs, i2c->ioarea, res);
+	dev_dbg(&pdev->dev, "registers %p (%p)\n",
+		i2c->regs, res);
 
 	/* setup info block for the i2c core */
 
 	i2c->adap.algo_data = i2c;
 	i2c->adap.dev.parent = &pdev->dev;
 
+	i2c->pctrl = devm_pinctrl_get_select_default(i2c->dev);
+
+	/* inititalise the i2c gpio lines */
+
+	if (i2c->pdata->cfg_gpio) {
+		i2c->pdata->cfg_gpio(to_platform_device(i2c->dev));
+	} else if (IS_ERR(i2c->pctrl) && s3c24xx_i2c_parse_dt_gpio(i2c)) {
+		ret = -EINVAL;
+		goto err_clk;
+	}
+
 	/* initialise the i2c controller */
 
 	ret = s3c24xx_i2c_init(i2c);
 	if (ret != 0)
-		goto err_iomap;
+		goto err_clk;
 
 	/* find the IRQ for this unit (note, this relies on the init call to
 	 * ensure no current IRQs pending
@@ -1027,7 +1082,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
 	i2c->irq = ret = platform_get_irq(pdev, 0);
 	if (ret <= 0) {
 		dev_err(&pdev->dev, "cannot find IRQ\n");
-		goto err_iomap;
+		goto err_clk;
 	}
 
 	ret = request_irq(i2c->irq, s3c24xx_i2c_irq, 0,
@@ -1035,7 +1090,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
 
 	if (ret != 0) {
 		dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
-		goto err_iomap;
+		goto err_clk;
 	}
 
 	ret = s3c24xx_i2c_register_cpufreq(i2c);
@@ -1075,13 +1130,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
  err_irq:
 	free_irq(i2c->irq, i2c);
 
- err_iomap:
-	iounmap(i2c->regs);
-
- err_ioarea:
-	release_resource(i2c->ioarea);
-	kfree(i2c->ioarea);
-
  err_clk:
 	clk_disable_unprepare(i2c->clk);
 	clk_put(i2c->clk);
@@ -1110,16 +1158,13 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
 	clk_disable_unprepare(i2c->clk);
 	clk_put(i2c->clk);
 
-	iounmap(i2c->regs);
-
-	release_resource(i2c->ioarea);
-	s3c24xx_i2c_dt_gpio_free(i2c);
-	kfree(i2c->ioarea);
+	if (pdev->dev.of_node && IS_ERR(i2c->pctrl))
+		s3c24xx_i2c_dt_gpio_free(i2c);
 
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int s3c24xx_i2c_suspend_noirq(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -1142,10 +1187,14 @@ static int s3c24xx_i2c_resume(struct device *dev)
 
 	return 0;
 }
+#endif
 
+#ifdef CONFIG_PM
 static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = {
+#ifdef CONFIG_PM_SLEEP
 	.suspend_noirq = s3c24xx_i2c_suspend_noirq,
 	.resume = s3c24xx_i2c_resume,
+#endif
 };
 
 #define S3C24XX_DEV_PM_OPS (&s3c24xx_i2c_dev_pm_ops)
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index 8110ca4..9411c1b 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -120,11 +120,12 @@ struct sh_mobile_i2c_data {
 	void __iomem *reg;
 	struct i2c_adapter adap;
 	unsigned long bus_speed;
+	unsigned int clks_per_count;
 	struct clk *clk;
 	u_int8_t icic;
-	u_int8_t iccl;
-	u_int8_t icch;
 	u_int8_t flags;
+	u_int16_t iccl;
+	u_int16_t icch;
 
 	spinlock_t lock;
 	wait_queue_head_t wait;
@@ -135,7 +136,8 @@ struct sh_mobile_i2c_data {
 
 #define IIC_FLAG_HAS_ICIC67	(1 << 0)
 
-#define NORMAL_SPEED		100000 /* FAST_SPEED 400000 */
+#define STANDARD_MODE		100000
+#define FAST_MODE		400000
 
 /* Register offsets */
 #define ICDR			0x00
@@ -187,57 +189,90 @@ static void iic_set_clr(struct sh_mobile_i2c_data *pd, int offs,
 	iic_wr(pd, offs, (iic_rd(pd, offs) | set) & ~clr);
 }
 
-static void activate_ch(struct sh_mobile_i2c_data *pd)
+static u32 sh_mobile_i2c_iccl(unsigned long count_khz, u32 tLOW, u32 tf, int offset)
 {
-	unsigned long i2c_clk;
-	u_int32_t num;
-	u_int32_t denom;
-	u_int32_t tmp;
-
-	/* Wake up device and enable clock */
-	pm_runtime_get_sync(pd->dev);
-	clk_enable(pd->clk);
-
-	/* Get clock rate after clock is enabled */
-	i2c_clk = clk_get_rate(pd->clk);
+	/*
+	 * Conditional expression:
+	 *   ICCL >= COUNT_CLK * (tLOW + tf)
+	 *
+	 * SH-Mobile IIC hardware starts counting the LOW period of
+	 * the SCL signal (tLOW) as soon as it pulls the SCL line.
+	 * In order to meet the tLOW timing spec, we need to take into
+	 * account the fall time of SCL signal (tf).  Default tf value
+	 * should be 0.3 us, for safety.
+	 */
+	return (((count_khz * (tLOW + tf)) + 5000) / 10000) + offset;
+}
 
-	/* Calculate the value for iccl. From the data sheet:
-	 * iccl = (p clock / transfer rate) * (L / (L + H))
-	 * where L and H are the SCL low/high ratio (5/4 in this case).
-	 * We also round off the result.
+static u32 sh_mobile_i2c_icch(unsigned long count_khz, u32 tHIGH, u32 tf, int offset)
+{
+	/*
+	 * Conditional expression:
+	 *   ICCH >= COUNT_CLK * (tHIGH + tf)
+	 *
+	 * SH-Mobile IIC hardware is aware of SCL transition period 'tr',
+	 * and can ignore it.  SH-Mobile IIC controller starts counting
+	 * the HIGH period of the SCL signal (tHIGH) after the SCL input
+	 * voltage increases at VIH.
+	 *
+	 * Afterward it turned out calculating ICCH using only tHIGH spec
+	 * will result in violation of the tHD;STA timing spec.  We need
+	 * to take into account the fall time of SDA signal (tf) at START
+	 * condition, in order to meet both tHIGH and tHD;STA specs.
 	 */
-	num = i2c_clk * 5;
-	denom = pd->bus_speed * 9;
-	tmp = num * 10 / denom;
-	if (tmp % 10 >= 5)
-		pd->iccl = (u_int8_t)((num/denom) + 1);
-	else
-		pd->iccl = (u_int8_t)(num/denom);
+	return (((count_khz * (tHIGH + tf)) + 5000) / 10000) + offset;
+}
 
-	/* one more bit of ICCL in ICIC */
-	if (pd->flags & IIC_FLAG_HAS_ICIC67) {
-		if ((num/denom) > 0xff)
-			pd->icic |= ICIC_ICCLB8;
-		else
-			pd->icic &= ~ICIC_ICCLB8;
+static void sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd)
+{
+	unsigned long i2c_clk_khz;
+	u32 tHIGH, tLOW, tf;
+	int offset;
+
+	/* Get clock rate after clock is enabled */
+	clk_enable(pd->clk);
+	i2c_clk_khz = clk_get_rate(pd->clk) / 1000;
+	i2c_clk_khz /= pd->clks_per_count;
+
+	if (pd->bus_speed == STANDARD_MODE) {
+		tLOW	= 47;	/* tLOW = 4.7 us */
+		tHIGH	= 40;	/* tHD;STA = tHIGH = 4.0 us */
+		tf	= 3;	/* tf = 0.3 us */
+		offset	= 0;	/* No offset */
+	} else if (pd->bus_speed == FAST_MODE) {
+		tLOW	= 13;	/* tLOW = 1.3 us */
+		tHIGH	= 6;	/* tHD;STA = tHIGH = 0.6 us */
+		tf	= 3;	/* tf = 0.3 us */
+		offset	= 0;	/* No offset */
+	} else {
+		dev_err(pd->dev, "unrecognized bus speed %lu Hz\n",
+			pd->bus_speed);
+		goto out;
 	}
 
-	/* Calculate the value for icch. From the data sheet:
-	   icch = (p clock / transfer rate) * (H / (L + H)) */
-	num = i2c_clk * 4;
-	tmp = num * 10 / denom;
-	if (tmp % 10 >= 5)
-		pd->icch = (u_int8_t)((num/denom) + 1);
+	pd->iccl = sh_mobile_i2c_iccl(i2c_clk_khz, tLOW, tf, offset);
+	/* one more bit of ICCL in ICIC */
+	if ((pd->iccl > 0xff) && (pd->flags & IIC_FLAG_HAS_ICIC67))
+		pd->icic |= ICIC_ICCLB8;
 	else
-		pd->icch = (u_int8_t)(num/denom);
+		pd->icic &= ~ICIC_ICCLB8;
 
+	pd->icch = sh_mobile_i2c_icch(i2c_clk_khz, tHIGH, tf, offset);
 	/* one more bit of ICCH in ICIC */
-	if (pd->flags & IIC_FLAG_HAS_ICIC67) {
-		if ((num/denom) > 0xff)
-			pd->icic |= ICIC_ICCHB8;
-		else
-			pd->icic &= ~ICIC_ICCHB8;
-	}
+	if ((pd->icch > 0xff) && (pd->flags & IIC_FLAG_HAS_ICIC67))
+		pd->icic |= ICIC_ICCHB8;
+	else
+		pd->icic &= ~ICIC_ICCHB8;
+
+out:
+	clk_disable(pd->clk);
+}
+
+static void activate_ch(struct sh_mobile_i2c_data *pd)
+{
+	/* Wake up device and enable clock */
+	pm_runtime_get_sync(pd->dev);
+	clk_enable(pd->clk);
 
 	/* Enable channel and configure rx ack */
 	iic_set_clr(pd, ICCR, ICCR_ICE, 0);
@@ -246,8 +281,8 @@ static void activate_ch(struct sh_mobile_i2c_data *pd)
 	iic_wr(pd, ICIC, 0);
 
 	/* Set the clock */
-	iic_wr(pd, ICCL, pd->iccl);
-	iic_wr(pd, ICCH, pd->icch);
+	iic_wr(pd, ICCL, pd->iccl & 0xff);
+	iic_wr(pd, ICCH, pd->icch & 0xff);
 }
 
 static void deactivate_ch(struct sh_mobile_i2c_data *pd)
@@ -434,6 +469,9 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
 		wake_up(&pd->wait);
 	}
 
+	/* defeat write posting to avoid spurious WAIT interrupts */
+	iic_rd(pd, ICSR);
+
 	return IRQ_HANDLED;
 }
 
@@ -451,8 +489,8 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg)
 	iic_set_clr(pd, ICCR, ICCR_ICE, 0);
 
 	/* Set the clock */
-	iic_wr(pd, ICCL, pd->iccl);
-	iic_wr(pd, ICCH, pd->icch);
+	iic_wr(pd, ICCL, pd->iccl & 0xff);
+	iic_wr(pd, ICCH, pd->icch & 0xff);
 
 	pd->msg = usr_msg;
 	pd->pos = -1;
@@ -621,10 +659,13 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
 		goto err_irq;
 	}
 
-	/* Use platformd data bus speed or NORMAL_SPEED */
-	pd->bus_speed = NORMAL_SPEED;
+	/* Use platform data bus speed or STANDARD_MODE */
+	pd->bus_speed = STANDARD_MODE;
 	if (pdata && pdata->bus_speed)
 		pd->bus_speed = pdata->bus_speed;
+	pd->clks_per_count = 1;
+	if (pdata && pdata->clks_per_count)
+		pd->clks_per_count = pdata->clks_per_count;
 
 	/* The IIC blocks on SH-Mobile ARM processors
 	 * come with two new bits in ICIC.
@@ -632,6 +673,8 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
 	if (size > 0x17)
 		pd->flags |= IIC_FLAG_HAS_ICIC67;
 
+	sh_mobile_i2c_init(pd);
+
 	/* Enable Runtime PM for this device.
 	 *
 	 * Also tell the Runtime PM core to ignore children
@@ -667,8 +710,9 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
 		goto err_all;
 	}
 
-	dev_info(&dev->dev, "I2C adapter %d with bus speed %lu Hz\n",
-		 adap->nr, pd->bus_speed);
+	dev_info(&dev->dev,
+		 "I2C adapter %d with bus speed %lu Hz (L/H=%x/%x)\n",
+		 adap->nr, pd->bus_speed, pd->iccl, pd->icch);
 
 	of_i2c_register_devices(adap);
 	return 0;
diff --git a/drivers/i2c/busses/i2c-viperboard.c b/drivers/i2c/busses/i2c-viperboard.c
new file mode 100644
index 0000000..f5fa20d
--- /dev/null
+++ b/drivers/i2c/busses/i2c-viperboard.c
@@ -0,0 +1,480 @@
+/*
+ *  Nano River Technologies viperboard i2c master driver
+ *
+ *  (C) 2012 by Lemonage GmbH
+ *  Author: Lars Poeschel <poeschel@lemonage.de>
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#include <linux/usb.h>
+#include <linux/i2c.h>
+
+#include <linux/mfd/viperboard.h>
+
+struct vprbrd_i2c {
+	struct i2c_adapter i2c;
+	u8 bus_freq_param;
+};
+
+/* i2c bus frequency module parameter */
+static u8 i2c_bus_param;
+static unsigned int i2c_bus_freq = 100;
+module_param(i2c_bus_freq, int, 0);
+MODULE_PARM_DESC(i2c_bus_freq,
+	"i2c bus frequency in khz (default is 100) valid values: 10, 100, 200, 400, 1000, 3000, 6000");
+
+static int vprbrd_i2c_status(struct i2c_adapter *i2c,
+	struct vprbrd_i2c_status *status, bool prev_error)
+{
+	u16 bytes_xfer;
+	int ret;
+	struct vprbrd *vb = (struct vprbrd *)i2c->algo_data;
+
+	/* check for protocol error */
+	bytes_xfer = sizeof(struct vprbrd_i2c_status);
+
+	ret = usb_control_msg(vb->usb_dev, usb_rcvctrlpipe(vb->usb_dev, 0),
+		VPRBRD_USB_REQUEST_I2C, VPRBRD_USB_TYPE_IN, 0x0000, 0x0000,
+		status, bytes_xfer, VPRBRD_USB_TIMEOUT_MS);
+
+	if (ret != bytes_xfer)
+		prev_error = true;
+
+	if (prev_error) {
+		dev_err(&i2c->dev, "failure in usb communication\n");
+		return -EREMOTEIO;
+	}
+
+	dev_dbg(&i2c->dev, "  status = %d\n", status->status);
+	if (status->status != 0x00) {
+		dev_err(&i2c->dev, "failure: i2c protocol error\n");
+		return -EPROTO;
+	}
+	return 0;
+}
+
+static int vprbrd_i2c_receive(struct usb_device *usb_dev,
+	struct vprbrd_i2c_read_msg *rmsg, int bytes_xfer)
+{
+	int ret, bytes_actual;
+	int error = 0;
+
+	/* send the read request */
+	ret = usb_bulk_msg(usb_dev,
+		usb_sndbulkpipe(usb_dev, VPRBRD_EP_OUT), rmsg,
+		sizeof(struct vprbrd_i2c_read_hdr), &bytes_actual,
+		VPRBRD_USB_TIMEOUT_MS);
+
+	if ((ret < 0)
+		|| (bytes_actual != sizeof(struct vprbrd_i2c_read_hdr))) {
+		dev_err(&usb_dev->dev, "failure transmitting usb\n");
+		error = -EREMOTEIO;
+	}
+
+	/* read the actual data */
+	ret = usb_bulk_msg(usb_dev,
+		usb_rcvbulkpipe(usb_dev, VPRBRD_EP_IN), rmsg,
+		bytes_xfer, &bytes_actual, VPRBRD_USB_TIMEOUT_MS);
+
+	if ((ret < 0) || (bytes_xfer != bytes_actual)) {
+		dev_err(&usb_dev->dev, "failure receiving usb\n");
+		error = -EREMOTEIO;
+	}
+	return error;
+}
+
+static int vprbrd_i2c_addr(struct usb_device *usb_dev,
+	struct vprbrd_i2c_addr_msg *amsg)
+{
+	int ret, bytes_actual;
+
+	ret = usb_bulk_msg(usb_dev,
+		usb_sndbulkpipe(usb_dev, VPRBRD_EP_OUT), amsg,
+		sizeof(struct vprbrd_i2c_addr_msg), &bytes_actual,
+		VPRBRD_USB_TIMEOUT_MS);
+
+	if ((ret < 0) ||
+			(sizeof(struct vprbrd_i2c_addr_msg) != bytes_actual)) {
+		dev_err(&usb_dev->dev, "failure transmitting usb\n");
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+static int vprbrd_i2c_read(struct vprbrd *vb, struct i2c_msg *msg)
+{
+	int ret;
+	u16 remain_len, bytes_xfer, len1, len2,
+		start = 0x0000;
+	struct vprbrd_i2c_read_msg *rmsg =
+		(struct vprbrd_i2c_read_msg *)vb->buf;
+
+	remain_len = msg->len;
+	rmsg->header.cmd = VPRBRD_I2C_CMD_READ;
+	while (remain_len > 0) {
+		rmsg->header.addr = cpu_to_le16(start + 0x4000);
+		if (remain_len <= 255) {
+			len1 = remain_len;
+			len2 = 0x00;
+			rmsg->header.len0 = remain_len;
+			rmsg->header.len1 = 0x00;
+			rmsg->header.len2 = 0x00;
+			rmsg->header.len3 = 0x00;
+			rmsg->header.len4 = 0x00;
+			rmsg->header.len5 = 0x00;
+			remain_len = 0;
+		} else if (remain_len <= 510) {
+			len1 = remain_len;
+			len2 = 0x00;
+			rmsg->header.len0 = remain_len - 255;
+			rmsg->header.len1 = 0xff;
+			rmsg->header.len2 = 0x00;
+			rmsg->header.len3 = 0x00;
+			rmsg->header.len4 = 0x00;
+			rmsg->header.len5 = 0x00;
+			remain_len = 0;
+		} else if (remain_len <= 512) {
+			len1 = remain_len;
+			len2 = 0x00;
+			rmsg->header.len0 = remain_len - 510;
+			rmsg->header.len1 = 0xff;
+			rmsg->header.len2 = 0xff;
+			rmsg->header.len3 = 0x00;
+			rmsg->header.len4 = 0x00;
+			rmsg->header.len5 = 0x00;
+			remain_len = 0;
+		} else if (remain_len <= 767) {
+			len1 = 512;
+			len2 = remain_len - 512;
+			rmsg->header.len0 = 0x02;
+			rmsg->header.len1 = 0xff;
+			rmsg->header.len2 = 0xff;
+			rmsg->header.len3 = remain_len - 512;
+			rmsg->header.len4 = 0x00;
+			rmsg->header.len5 = 0x00;
+			bytes_xfer = remain_len;
+			remain_len = 0;
+		} else if (remain_len <= 1022) {
+			len1 = 512;
+			len2 = remain_len - 512;
+			rmsg->header.len0 = 0x02;
+			rmsg->header.len1 = 0xff;
+			rmsg->header.len2 = 0xff;
+			rmsg->header.len3 = remain_len - 767;
+			rmsg->header.len4 = 0xff;
+			rmsg->header.len5 = 0x00;
+			remain_len = 0;
+		} else if (remain_len <= 1024) {
+			len1 = 512;
+			len2 = remain_len - 512;
+			rmsg->header.len0 = 0x02;
+			rmsg->header.len1 = 0xff;
+			rmsg->header.len2 = 0xff;
+			rmsg->header.len3 = remain_len - 1022;
+			rmsg->header.len4 = 0xff;
+			rmsg->header.len5 = 0xff;
+			remain_len = 0;
+		} else {
+			len1 = 512;
+			len2 = 512;
+			rmsg->header.len0 = 0x02;
+			rmsg->header.len1 = 0xff;
+			rmsg->header.len2 = 0xff;
+			rmsg->header.len3 = 0x02;
+			rmsg->header.len4 = 0xff;
+			rmsg->header.len5 = 0xff;
+			remain_len -= 1024;
+			start += 1024;
+		}
+		rmsg->header.tf1 = cpu_to_le16(len1);
+		rmsg->header.tf2 = cpu_to_le16(len2);
+
+		/* first read transfer */
+		ret = vprbrd_i2c_receive(vb->usb_dev, rmsg, len1);
+		if (ret < 0)
+			return ret;
+		/* copy the received data */
+		memcpy(msg->buf + start, rmsg, len1);
+
+		/* second read transfer if neccessary */
+		if (len2 > 0) {
+			ret = vprbrd_i2c_receive(vb->usb_dev, rmsg, len2);
+			if (ret < 0)
+				return ret;
+			/* copy the received data */
+			memcpy(msg->buf + start + 512, rmsg, len2);
+		}
+	}
+	return 0;
+}
+
+static int vprbrd_i2c_write(struct vprbrd *vb, struct i2c_msg *msg)
+{
+	int ret, bytes_actual;
+	u16 remain_len, bytes_xfer,
+		start = 0x0000;
+	struct vprbrd_i2c_write_msg *wmsg =
+		(struct vprbrd_i2c_write_msg *)vb->buf;
+
+	remain_len = msg->len;
+	wmsg->header.cmd = VPRBRD_I2C_CMD_WRITE;
+	wmsg->header.last = 0x00;
+	wmsg->header.chan = 0x00;
+	wmsg->header.spi = 0x0000;
+	while (remain_len > 0) {
+		wmsg->header.addr = cpu_to_le16(start + 0x4000);
+		if (remain_len > 503) {
+			wmsg->header.len1 = 0xff;
+			wmsg->header.len2 = 0xf8;
+			remain_len -= 503;
+			bytes_xfer = 503 + sizeof(struct vprbrd_i2c_write_hdr);
+			start += 503;
+		} else if (remain_len > 255) {
+			wmsg->header.len1 = 0xff;
+			wmsg->header.len2 = (remain_len - 255);
+			bytes_xfer = remain_len +
+				sizeof(struct vprbrd_i2c_write_hdr);
+			remain_len = 0;
+		} else {
+			wmsg->header.len1 = remain_len;
+			wmsg->header.len2 = 0x00;
+			bytes_xfer = remain_len +
+				sizeof(struct vprbrd_i2c_write_hdr);
+			remain_len = 0;
+		}
+		memcpy(wmsg->data, msg->buf + start,
+			bytes_xfer - sizeof(struct vprbrd_i2c_write_hdr));
+
+		ret = usb_bulk_msg(vb->usb_dev,
+			usb_sndbulkpipe(vb->usb_dev,
+			VPRBRD_EP_OUT), wmsg,
+			bytes_xfer, &bytes_actual, VPRBRD_USB_TIMEOUT_MS);
+		if ((ret < 0) || (bytes_xfer != bytes_actual))
+			return -EREMOTEIO;
+	}
+	return 0;
+}
+
+static int vprbrd_i2c_xfer(struct i2c_adapter *i2c, struct i2c_msg *msgs,
+		int num)
+{
+	struct i2c_msg *pmsg;
+	int i, ret,
+		error = 0;
+	struct vprbrd *vb = (struct vprbrd *)i2c->algo_data;
+	struct vprbrd_i2c_addr_msg *amsg =
+		(struct vprbrd_i2c_addr_msg *)vb->buf;
+	struct vprbrd_i2c_status *smsg = (struct vprbrd_i2c_status *)vb->buf;
+
+	dev_dbg(&i2c->dev, "master xfer %d messages:\n", num);
+
+	for (i = 0 ; i < num ; i++) {
+		pmsg = &msgs[i];
+
+		dev_dbg(&i2c->dev,
+			"  %d: %s (flags %d) %d bytes to 0x%02x\n",
+			i, pmsg->flags & I2C_M_RD ? "read" : "write",
+			pmsg->flags, pmsg->len, pmsg->addr);
+
+		/* msgs longer than 2048 bytes are not supported by adapter */
+		if (pmsg->len > 2048)
+			return -EINVAL;
+
+		mutex_lock(&vb->lock);
+		/* directly send the message */
+		if (pmsg->flags & I2C_M_RD) {
+			/* read data */
+			amsg->cmd = VPRBRD_I2C_CMD_ADDR;
+			amsg->unknown2 = 0x00;
+			amsg->unknown3 = 0x00;
+			amsg->addr = pmsg->addr;
+			amsg->unknown1 = 0x01;
+			amsg->len = cpu_to_le16(pmsg->len);
+			/* send the addr and len, we're interested to board */
+			ret = vprbrd_i2c_addr(vb->usb_dev, amsg);
+			if (ret < 0)
+				error = ret;
+
+			ret = vprbrd_i2c_read(vb, pmsg);
+			if (ret < 0)
+				error = ret;
+
+			ret = vprbrd_i2c_status(i2c, smsg, error);
+			if (ret < 0)
+				error = ret;
+			/* in case of protocol error, return the error */
+			if (error < 0)
+				goto error;
+		} else {
+			/* write data */
+			ret = vprbrd_i2c_write(vb, pmsg);
+
+			amsg->cmd = VPRBRD_I2C_CMD_ADDR;
+			amsg->unknown2 = 0x00;
+			amsg->unknown3 = 0x00;
+			amsg->addr = pmsg->addr;
+			amsg->unknown1 = 0x00;
+			amsg->len = cpu_to_le16(pmsg->len);
+			/* send the addr, the data goes to to board */
+			ret = vprbrd_i2c_addr(vb->usb_dev, amsg);
+			if (ret < 0)
+				error = ret;
+
+			ret = vprbrd_i2c_status(i2c, smsg, error);
+			if (ret < 0)
+				error = ret;
+
+			if (error < 0)
+				goto error;
+		}
+		mutex_unlock(&vb->lock);
+	}
+	return 0;
+error:
+	mutex_unlock(&vb->lock);
+	return error;
+}
+
+static u32 vprbrd_i2c_func(struct i2c_adapter *i2c)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+/* This is the actual algorithm we define */
+static const struct i2c_algorithm vprbrd_algorithm = {
+	.master_xfer	= vprbrd_i2c_xfer,
+	.functionality	= vprbrd_i2c_func,
+};
+
+static int __devinit vprbrd_i2c_probe(struct platform_device *pdev)
+{
+	struct vprbrd *vb = dev_get_drvdata(pdev->dev.parent);
+	struct vprbrd_i2c *vb_i2c;
+	int ret;
+	int pipe;
+
+	vb_i2c = kzalloc(sizeof(*vb_i2c), GFP_KERNEL);
+	if (vb_i2c == NULL)
+		return -ENOMEM;
+
+	/* setup i2c adapter description */
+	vb_i2c->i2c.owner = THIS_MODULE;
+	vb_i2c->i2c.class = I2C_CLASS_HWMON;
+	vb_i2c->i2c.algo = &vprbrd_algorithm;
+	vb_i2c->i2c.algo_data = vb;
+	/* save the param in usb capabable memory */
+	vb_i2c->bus_freq_param = i2c_bus_param;
+
+	snprintf(vb_i2c->i2c.name, sizeof(vb_i2c->i2c.name),
+		 "viperboard at bus %03d device %03d",
+		 vb->usb_dev->bus->busnum, vb->usb_dev->devnum);
+
+	/* setting the bus frequency */
+	if ((i2c_bus_param <= VPRBRD_I2C_FREQ_10KHZ)
+		&& (i2c_bus_param >= VPRBRD_I2C_FREQ_6MHZ)) {
+		pipe = usb_sndctrlpipe(vb->usb_dev, 0);
+		ret = usb_control_msg(vb->usb_dev, pipe,
+			VPRBRD_USB_REQUEST_I2C_FREQ, VPRBRD_USB_TYPE_OUT,
+			0x0000, 0x0000, &vb_i2c->bus_freq_param, 1,
+			VPRBRD_USB_TIMEOUT_MS);
+	    if (ret != 1) {
+		dev_err(&pdev->dev,
+			"failure setting i2c_bus_freq to %d\n", i2c_bus_freq);
+		ret = -EIO;
+		goto error;
+	    }
+	} else {
+		dev_err(&pdev->dev,
+			"invalid i2c_bus_freq setting:%d\n", i2c_bus_freq);
+		ret = -EIO;
+		goto error;
+	}
+
+	vb_i2c->i2c.dev.parent = &pdev->dev;
+
+	/* attach to i2c layer */
+	i2c_add_adapter(&vb_i2c->i2c);
+
+	platform_set_drvdata(pdev, vb_i2c);
+
+	return 0;
+
+error:
+	kfree(vb_i2c);
+	return ret;
+}
+
+static int __devexit vprbrd_i2c_remove(struct platform_device *pdev)
+{
+	struct vprbrd_i2c *vb_i2c = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = i2c_del_adapter(&vb_i2c->i2c);
+
+	return ret;
+}
+
+static struct platform_driver vprbrd_i2c_driver = {
+	.driver.name	= "viperboard-i2c",
+	.driver.owner	= THIS_MODULE,
+	.probe		= vprbrd_i2c_probe,
+	.remove		= __devexit_p(vprbrd_i2c_remove),
+};
+
+static int __init vprbrd_i2c_init(void)
+{
+	switch (i2c_bus_freq) {
+	case 6000:
+		i2c_bus_param = VPRBRD_I2C_FREQ_6MHZ;
+		break;
+	case 3000:
+		i2c_bus_param = VPRBRD_I2C_FREQ_3MHZ;
+		break;
+	case 1000:
+		i2c_bus_param = VPRBRD_I2C_FREQ_1MHZ;
+		break;
+	case 400:
+		i2c_bus_param = VPRBRD_I2C_FREQ_400KHZ;
+		break;
+	case 200:
+		i2c_bus_param = VPRBRD_I2C_FREQ_200KHZ;
+		break;
+	case 100:
+		i2c_bus_param = VPRBRD_I2C_FREQ_100KHZ;
+		break;
+	case 10:
+		i2c_bus_param = VPRBRD_I2C_FREQ_10KHZ;
+		break;
+	default:
+		pr_warn("invalid i2c_bus_freq (%d)\n", i2c_bus_freq);
+		i2c_bus_param = VPRBRD_I2C_FREQ_100KHZ;
+	}
+
+	return platform_driver_register(&vprbrd_i2c_driver);
+}
+subsys_initcall(vprbrd_i2c_init);
+
+static void __exit vprbrd_i2c_exit(void)
+{
+	platform_driver_unregister(&vprbrd_i2c_driver);
+}
+module_exit(vprbrd_i2c_exit);
+
+MODULE_AUTHOR("Lars Poeschel <poeschel@lemonage.de>");
+MODULE_DESCRIPTION("I2C master driver for Nano River Techs Viperboard");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:viperboard-i2c");
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index a7edf98..e388590 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -39,6 +39,7 @@
 #include <linux/irqflags.h>
 #include <linux/rwsem.h>
 #include <linux/pm_runtime.h>
+#include <linux/acpi.h>
 #include <asm/uaccess.h>
 
 #include "i2c-core.h"
@@ -78,6 +79,10 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
 	if (of_driver_match_device(dev, drv))
 		return 1;
 
+	/* Then ACPI style match */
+	if (acpi_driver_match_device(dev, drv))
+		return 1;
+
 	driver = to_i2c_driver(drv);
 	/* match on an id table if there is one */
 	if (driver->id_table)
@@ -539,6 +544,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
 	client->dev.bus = &i2c_bus_type;
 	client->dev.type = &i2c_client_type;
 	client->dev.of_node = info->of_node;
+	ACPI_HANDLE_SET(&client->dev, info->acpi_node.handle);
 
 	/* For 10-bit clients, add an arbitrary offset to avoid collisions */
 	dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index a0edd98..0be5b83 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -19,7 +19,6 @@ config I2C_MUX_GPIO
 
 config I2C_MUX_PCA9541
 	tristate "NXP PCA9541 I2C Master Selector"
-	depends on EXPERIMENTAL
 	help
 	  If you say yes here you get support for the NXP PCA9541
 	  I2C Master Selector.
@@ -29,7 +28,6 @@ config I2C_MUX_PCA9541
 
 config I2C_MUX_PCA954x
 	tristate "Philips PCA954x I2C Mux/switches"
-	depends on EXPERIMENTAL
 	help
 	  If you say yes here you get support for the Philips PCA954x
 	  I2C mux/switch devices.
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index 566a675..3b7bc06 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -16,6 +16,8 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
+#include <linux/of_i2c.h>
+#include <linux/of_gpio.h>
 
 struct gpiomux {
 	struct i2c_adapter *parent;
@@ -57,29 +59,110 @@ static int __devinit match_gpio_chip_by_label(struct gpio_chip *chip,
 	return !strcmp(chip->label, data);
 }
 
+#ifdef CONFIG_OF
+static int __devinit i2c_mux_gpio_probe_dt(struct gpiomux *mux,
+					struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *adapter_np, *child;
+	struct i2c_adapter *adapter;
+	unsigned *values, *gpios;
+	int i = 0;
+
+	if (!np)
+		return -ENODEV;
+
+	adapter_np = of_parse_phandle(np, "i2c-parent", 0);
+	if (!adapter_np) {
+		dev_err(&pdev->dev, "Cannot parse i2c-parent\n");
+		return -ENODEV;
+	}
+	adapter = of_find_i2c_adapter_by_node(adapter_np);
+	if (!adapter) {
+		dev_err(&pdev->dev, "Cannot find parent bus\n");
+		return -ENODEV;
+	}
+	mux->data.parent = i2c_adapter_id(adapter);
+	put_device(&adapter->dev);
+
+	mux->data.n_values = of_get_child_count(np);
+
+	values = devm_kzalloc(&pdev->dev,
+			      sizeof(*mux->data.values) * mux->data.n_values,
+			      GFP_KERNEL);
+	if (!values) {
+		dev_err(&pdev->dev, "Cannot allocate values array");
+		return -ENOMEM;
+	}
+
+	for_each_child_of_node(np, child) {
+		of_property_read_u32(child, "reg", values + i);
+		i++;
+	}
+	mux->data.values = values;
+
+	if (of_property_read_u32(np, "idle-state", &mux->data.idle))
+		mux->data.idle = I2C_MUX_GPIO_NO_IDLE;
+
+	mux->data.n_gpios = of_gpio_named_count(np, "mux-gpios");
+	if (mux->data.n_gpios < 0) {
+		dev_err(&pdev->dev, "Missing mux-gpios property in the DT.\n");
+		return -EINVAL;
+	}
+
+	gpios = devm_kzalloc(&pdev->dev,
+			     sizeof(*mux->data.gpios) * mux->data.n_gpios, GFP_KERNEL);
+	if (!gpios) {
+		dev_err(&pdev->dev, "Cannot allocate gpios array");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < mux->data.n_gpios; i++)
+		gpios[i] = of_get_named_gpio(np, "mux-gpios", i);
+
+	mux->data.gpios = gpios;
+
+	return 0;
+}
+#else
+static int __devinit i2c_mux_gpio_probe_dt(struct gpiomux *mux,
+					struct platform_device *pdev)
+{
+	return 0;
+}
+#endif
+
 static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
 {
 	struct gpiomux *mux;
-	struct i2c_mux_gpio_platform_data *pdata;
 	struct i2c_adapter *parent;
 	int (*deselect) (struct i2c_adapter *, void *, u32);
 	unsigned initial_state, gpio_base;
 	int i, ret;
 
-	pdata = pdev->dev.platform_data;
-	if (!pdata) {
-		dev_err(&pdev->dev, "Missing platform data\n");
-		return -ENODEV;
+	mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
+	if (!mux) {
+		dev_err(&pdev->dev, "Cannot allocate gpiomux structure");
+		return -ENOMEM;
 	}
 
+	platform_set_drvdata(pdev, mux);
+
+	if (!pdev->dev.platform_data) {
+		ret = i2c_mux_gpio_probe_dt(mux, pdev);
+		if (ret < 0)
+			return ret;
+	} else
+		memcpy(&mux->data, pdev->dev.platform_data, sizeof(mux->data));
+
 	/*
 	 * If a GPIO chip name is provided, the GPIO pin numbers provided are
 	 * relative to its base GPIO number. Otherwise they are absolute.
 	 */
-	if (pdata->gpio_chip) {
+	if (mux->data.gpio_chip) {
 		struct gpio_chip *gpio;
 
-		gpio = gpiochip_find(pdata->gpio_chip,
+		gpio = gpiochip_find(mux->data.gpio_chip,
 				     match_gpio_chip_by_label);
 		if (!gpio)
 			return -EPROBE_DEFER;
@@ -89,49 +172,44 @@ static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
 		gpio_base = 0;
 	}
 
-	parent = i2c_get_adapter(pdata->parent);
+	parent = i2c_get_adapter(mux->data.parent);
 	if (!parent) {
 		dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
-			pdata->parent);
+			mux->data.parent);
 		return -ENODEV;
 	}
 
-	mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
-	if (!mux) {
-		ret = -ENOMEM;
-		goto alloc_failed;
-	}
-
 	mux->parent = parent;
-	mux->data = *pdata;
 	mux->gpio_base = gpio_base;
+
 	mux->adap = devm_kzalloc(&pdev->dev,
-				 sizeof(*mux->adap) * pdata->n_values,
+				 sizeof(*mux->adap) * mux->data.n_values,
 				 GFP_KERNEL);
 	if (!mux->adap) {
+		dev_err(&pdev->dev, "Cannot allocate i2c_adapter structure");
 		ret = -ENOMEM;
 		goto alloc_failed;
 	}
 
-	if (pdata->idle != I2C_MUX_GPIO_NO_IDLE) {
-		initial_state = pdata->idle;
+	if (mux->data.idle != I2C_MUX_GPIO_NO_IDLE) {
+		initial_state = mux->data.idle;
 		deselect = i2c_mux_gpio_deselect;
 	} else {
-		initial_state = pdata->values[0];
+		initial_state = mux->data.values[0];
 		deselect = NULL;
 	}
 
-	for (i = 0; i < pdata->n_gpios; i++) {
-		ret = gpio_request(gpio_base + pdata->gpios[i], "i2c-mux-gpio");
+	for (i = 0; i < mux->data.n_gpios; i++) {
+		ret = gpio_request(gpio_base + mux->data.gpios[i], "i2c-mux-gpio");
 		if (ret)
 			goto err_request_gpio;
-		gpio_direction_output(gpio_base + pdata->gpios[i],
+		gpio_direction_output(gpio_base + mux->data.gpios[i],
 				      initial_state & (1 << i));
 	}
 
-	for (i = 0; i < pdata->n_values; i++) {
-		u32 nr = pdata->base_nr ? (pdata->base_nr + i) : 0;
-		unsigned int class = pdata->classes ? pdata->classes[i] : 0;
+	for (i = 0; i < mux->data.n_values; i++) {
+		u32 nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0;
+		unsigned int class = mux->data.classes ? mux->data.classes[i] : 0;
 
 		mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr,
 						   i, class,
@@ -144,19 +222,17 @@ static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
 	}
 
 	dev_info(&pdev->dev, "%d port mux on %s adapter\n",
-		 pdata->n_values, parent->name);
-
-	platform_set_drvdata(pdev, mux);
+		 mux->data.n_values, parent->name);
 
 	return 0;
 
 add_adapter_failed:
 	for (; i > 0; i--)
 		i2c_del_mux_adapter(mux->adap[i - 1]);
-	i = pdata->n_gpios;
+	i = mux->data.n_gpios;
 err_request_gpio:
 	for (; i > 0; i--)
-		gpio_free(gpio_base + pdata->gpios[i - 1]);
+		gpio_free(gpio_base + mux->data.gpios[i - 1]);
 alloc_failed:
 	i2c_put_adapter(parent);
 
@@ -180,12 +256,19 @@ static int __devexit i2c_mux_gpio_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct of_device_id i2c_mux_gpio_of_match[] __devinitconst = {
+	{ .compatible = "i2c-mux-gpio", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, i2c_mux_gpio_of_match);
+
 static struct platform_driver i2c_mux_gpio_driver = {
 	.probe	= i2c_mux_gpio_probe,
 	.remove	= __devexit_p(i2c_mux_gpio_remove),
 	.driver	= {
 		.owner	= THIS_MODULE,
 		.name	= "i2c-mux-gpio",
+		.of_match_table = of_match_ptr(i2c_mux_gpio_of_match),
 	},
 };
 
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 5a26584..3c4417a 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -322,8 +322,7 @@ config BLK_DEV_GENERIC
           which otherwise might not be supported.
 
 config BLK_DEV_OPTI621
-	tristate "OPTi 82C621 chipset enhanced support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	tristate "OPTi 82C621 chipset enhanced support"
 	select BLK_DEV_IDEPCI
 	help
 	  This is a driver for the OPTi 82C621 EIDE controller.
@@ -417,7 +416,6 @@ config BLK_DEV_CY82C693
 
 config BLK_DEV_CS5520
 	tristate "Cyrix CS5510/20 MediaGX chipset support (VERY EXPERIMENTAL)"
-	depends on EXPERIMENTAL
 	select BLK_DEV_IDEDMA_PCI
 	help
 	  Include support for PIO tuning and virtual DMA on the Cyrix MediaGX
@@ -761,8 +759,8 @@ config BLK_DEV_GAYLE
 	  use Gayle IDE interfaces on the Zorro expansion bus.
 
 config BLK_DEV_BUDDHA
-	tristate "Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)"
-	depends on ZORRO && EXPERIMENTAL
+	tristate "Buddha/Catweasel/X-Surf IDE interface support"
+	depends on ZORRO
 	help
 	  This is the IDE driver for the IDE interfaces on the Buddha, Catweasel
 	  and X-Surf expansion boards.  It supports up to two interfaces on the
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index b0f6b4c..c49c04d 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -56,7 +56,6 @@
 #include <linux/kernel.h>
 #include <linux/cpuidle.h>
 #include <linux/clockchips.h>
-#include <linux/hrtimer.h>	/* ktime_get_real() */
 #include <trace/events/power.h>
 #include <linux/sched.h>
 #include <linux/notifier.h>
@@ -72,6 +71,7 @@
 static struct cpuidle_driver intel_idle_driver = {
 	.name = "intel_idle",
 	.owner = THIS_MODULE,
+	.en_core_tk_irqen = 1,
 };
 /* intel_idle.max_cstate=0 disables driver */
 static int max_cstate = MWAIT_MAX_NUM_CSTATES - 1;
@@ -281,8 +281,6 @@ static int intel_idle(struct cpuidle_device *dev,
 	struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
 	unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage);
 	unsigned int cstate;
-	ktime_t kt_before, kt_after;
-	s64 usec_delta;
 	int cpu = smp_processor_id();
 
 	cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1;
@@ -297,8 +295,6 @@ static int intel_idle(struct cpuidle_device *dev,
 	if (!(lapic_timer_reliable_states & (1 << (cstate))))
 		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
 
-	kt_before = ktime_get_real();
-
 	stop_critical_timings();
 	if (!need_resched()) {
 
@@ -310,17 +306,9 @@ static int intel_idle(struct cpuidle_device *dev,
 
 	start_critical_timings();
 
-	kt_after = ktime_get_real();
-	usec_delta = ktime_to_us(ktime_sub(kt_after, kt_before));
-
-	local_irq_enable();
-
 	if (!(lapic_timer_reliable_states & (1 << (cstate))))
 		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
 
-	/* Update cpuidle counters */
-	dev->last_residency = (int)usec_delta;
-
 	return index;
 }
 
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index fc937ac..b2f963b 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -20,6 +20,12 @@ config IIO_BUFFER
 
 if IIO_BUFFER
 
+config IIO_BUFFER_CB
+boolean "IIO callback buffer used for push in-kernel interfaces"
+	help
+	  Should be selected by any drivers that do-inkernel push
+	  usage.  That is, those where the data is pushed to the consumer.
+
 config IIO_KFIFO_BUF
 	select IIO_TRIGGER
 	tristate "Industrial I/O buffering based on kfifo"
@@ -57,11 +63,12 @@ config IIO_CONSUMERS_PER_TRIGGER
 source "drivers/iio/accel/Kconfig"
 source "drivers/iio/adc/Kconfig"
 source "drivers/iio/amplifiers/Kconfig"
-source "drivers/iio/light/Kconfig"
-source "drivers/iio/frequency/Kconfig"
-source "drivers/iio/dac/Kconfig"
 source "drivers/iio/common/Kconfig"
+source "drivers/iio/dac/Kconfig"
+source "drivers/iio/frequency/Kconfig"
 source "drivers/iio/gyro/Kconfig"
+source "drivers/iio/imu/Kconfig"
+source "drivers/iio/light/Kconfig"
 source "drivers/iio/magnetometer/Kconfig"
 
 endif # IIO
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index 761f2b6..a0e8cdd 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_IIO) += industrialio.o
 industrialio-y := industrialio-core.o industrialio-event.o inkern.o
 industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o
 industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o
+industrialio-$(CONFIG_IIO_BUFFER_CB) += buffer_cb.o
 
 obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o
 obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
@@ -13,9 +14,10 @@ obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
 obj-y += accel/
 obj-y += adc/
 obj-y += amplifiers/
-obj-y += light/
-obj-y += frequency/
-obj-y += dac/
 obj-y += common/
+obj-y += dac/
 obj-y += gyro/
+obj-y += frequency/
+obj-y += imu/
+obj-y += light/
 obj-y += magnetometer/
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index b2510c4..fe4bcd7 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -8,7 +8,7 @@ config HID_SENSOR_ACCEL_3D
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
 	select HID_SENSOR_IIO_COMMON
-	tristate "HID Acelerometers 3D"
+	tristate "HID Accelerometers 3D"
 	help
 	  Say yes here to build support for the HID SENSOR
 	  accelerometers 3D.
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 314a405..e67bb91 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -197,21 +197,8 @@ static const struct iio_info accel_3d_info = {
 /* Function to push data to buffer */
 static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
 {
-	struct iio_buffer *buffer = indio_dev->buffer;
-	int datum_sz;
-
 	dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
-	if (!buffer) {
-		dev_err(&indio_dev->dev, "Buffer == NULL\n");
-		return;
-	}
-	datum_sz = buffer->access->get_bytes_per_datum(buffer);
-	if (len > datum_sz) {
-		dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len,
-				datum_sz);
-		return;
-	}
-	iio_push_to_buffer(buffer, (u8 *)data);
+	iio_push_to_buffers(indio_dev, (u8 *)data);
 }
 
 /* Callback handler to send event after all samples are received and captured */
@@ -319,10 +306,10 @@ static int __devinit hid_accel_3d_probe(struct platform_device *pdev)
 		goto error_free_dev;
 	}
 
-	channels = kmemdup(accel_3d_channels,
-					sizeof(accel_3d_channels),
-					GFP_KERNEL);
+	channels = kmemdup(accel_3d_channels, sizeof(accel_3d_channels),
+			   GFP_KERNEL);
 	if (!channels) {
+		ret = -ENOMEM;
 		dev_err(&pdev->dev, "failed to duplicate channels\n");
 		goto error_free_dev;
 	}
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 4927581..3f6c354 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -18,6 +18,18 @@ config AD7266
 	  Say yes here to build support for Analog Devices AD7265 and AD7266
 	  ADCs.
 
+config AD7298
+	tristate "Analog Devices AD7298 ADC driver"
+	depends on SPI
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	help
+	  Say yes here to build support for Analog Devices AD7298
+	  8 Channel ADC with temperature sensor.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad7298.
+
 config AD7791
 	tristate "Analog Devices AD7791 ADC driver"
 	depends on SPI
@@ -45,6 +57,19 @@ config AD7476
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad7476.
 
+config AD7887
+	tristate "Analog Devices AD7887 ADC driver"
+	depends on SPI
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	help
+	  Say yes here to build support for Analog Devices
+	  AD7887 SPI analog to digital converter (ADC).
+	  If unsure, say N (but it's safe to say "Y").
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad7887.
+
 config AT91_ADC
 	tristate "Atmel AT91 ADC"
 	depends on ARCH_AT91
@@ -60,4 +85,36 @@ config LP8788_ADC
 	help
 	  Say yes here to build support for TI LP8788 ADC.
 
+config TI_AM335X_ADC
+	tristate "TI's ADC driver"
+	depends on MFD_TI_AM335X_TSCADC
+	help
+	  Say yes here to build support for Texas Instruments ADC
+	  driver which is also a MFD client.
+
+config VIPERBOARD_ADC
+	tristate "Viperboard ADC support"
+	depends on MFD_VIPERBOARD && USB
+	help
+	  Say yes here to access the ADC part of the Nano River
+	  Technologies Viperboard.
+
+config MAX1363
+	tristate "Maxim max1363 ADC driver"
+	depends on I2C
+	select IIO_TRIGGER
+	select MAX1363_RING_BUFFER
+	select IIO_BUFFER
+	select IIO_KFIFO_BUF
+	help
+	  Say yes here to build support for many Maxim i2c analog to digital
+	  converters (ADC). (max1361, max1362, max1363, max1364, max1036,
+	  max1037, max1038, max1039, max1136, max1136, max1137, max1138,
+	  max1139, max1236, max1237, max11238, max1239, max11600, max11601,
+	  max11602, max11603, max11604, max11605, max11606, max11607,
+	  max11608, max11609, max11610, max11611, max11612, max11613,
+	  max11614, max11615, max11616, max11617, max11644, max11645,
+	  max11646, max11647) Provides direct access via sysfs and buffered
+	  data via the iio dev interface.
+
 endmenu
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 900995d..0633507 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -4,7 +4,12 @@
 
 obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
 obj-$(CONFIG_AD7266) += ad7266.o
+obj-$(CONFIG_AD7298) += ad7298.o
 obj-$(CONFIG_AD7476) += ad7476.o
 obj-$(CONFIG_AD7791) += ad7791.o
+obj-$(CONFIG_AD7887) += ad7887.o
 obj-$(CONFIG_AT91_ADC) += at91_adc.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
+obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
+obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
+obj-$(CONFIG_MAX1363) += max1363.o
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index b11f214..a6f4fc5 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -91,7 +91,6 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
-	struct iio_buffer *buffer = indio_dev->buffer;
 	struct ad7266_state *st = iio_priv(indio_dev);
 	int ret;
 
@@ -99,7 +98,7 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p)
 	if (ret == 0) {
 		if (indio_dev->scan_timestamp)
 			((s64 *)st->data)[1] = pf->timestamp;
-		iio_push_to_buffer(buffer, (u8 *)st->data);
+		iio_push_to_buffers(indio_dev, (u8 *)st->data);
 	}
 
 	iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c
new file mode 100644
index 0000000..2364807
--- /dev/null
+++ b/drivers/iio/adc/ad7298.c
@@ -0,0 +1,408 @@
+/*
+ * AD7298 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#include <linux/platform_data/ad7298.h>
+
+#define AD7298_WRITE	(1 << 15) /* write to the control register */
+#define AD7298_REPEAT	(1 << 14) /* repeated conversion enable */
+#define AD7298_CH(x)	(1 << (13 - (x))) /* channel select */
+#define AD7298_TSENSE	(1 << 5) /* temperature conversion enable */
+#define AD7298_EXTREF	(1 << 2) /* external reference enable */
+#define AD7298_TAVG	(1 << 1) /* temperature sensor averaging enable */
+#define AD7298_PDD	(1 << 0) /* partial power down enable */
+
+#define AD7298_MAX_CHAN		8
+#define AD7298_BITS		12
+#define AD7298_STORAGE_BITS	16
+#define AD7298_INTREF_mV	2500
+
+#define AD7298_CH_TEMP		9
+
+#define RES_MASK(bits)	((1 << (bits)) - 1)
+
+struct ad7298_state {
+	struct spi_device		*spi;
+	struct regulator		*reg;
+	unsigned			ext_ref;
+	struct spi_transfer		ring_xfer[10];
+	struct spi_transfer		scan_single_xfer[3];
+	struct spi_message		ring_msg;
+	struct spi_message		scan_single_msg;
+	/*
+	 * DMA (thus cache coherency maintenance) requires the
+	 * transfer buffers to live in their own cache lines.
+	 */
+	__be16				rx_buf[12] ____cacheline_aligned;
+	__be16				tx_buf[2];
+};
+
+#define AD7298_V_CHAN(index)						\
+	{								\
+		.type = IIO_VOLTAGE,					\
+		.indexed = 1,						\
+		.channel = index,					\
+		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |		\
+		IIO_CHAN_INFO_SCALE_SHARED_BIT,				\
+		.address = index,					\
+		.scan_index = index,					\
+		.scan_type = {						\
+			.sign = 'u',					\
+			.realbits = 12,					\
+			.storagebits = 16,				\
+			.endianness = IIO_BE,				\
+		},							\
+	}
+
+static const struct iio_chan_spec ad7298_channels[] = {
+	{
+		.type = IIO_TEMP,
+		.indexed = 1,
+		.channel = 0,
+		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+			IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+			IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
+		.address = AD7298_CH_TEMP,
+		.scan_index = -1,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 32,
+			.storagebits = 32,
+		},
+	},
+	AD7298_V_CHAN(0),
+	AD7298_V_CHAN(1),
+	AD7298_V_CHAN(2),
+	AD7298_V_CHAN(3),
+	AD7298_V_CHAN(4),
+	AD7298_V_CHAN(5),
+	AD7298_V_CHAN(6),
+	AD7298_V_CHAN(7),
+	IIO_CHAN_SOFT_TIMESTAMP(8),
+};
+
+/**
+ * ad7298_update_scan_mode() setup the spi transfer buffer for the new scan mask
+ **/
+static int ad7298_update_scan_mode(struct iio_dev *indio_dev,
+	const unsigned long *active_scan_mask)
+{
+	struct ad7298_state *st = iio_priv(indio_dev);
+	int i, m;
+	unsigned short command;
+	int scan_count;
+
+	/* Now compute overall size */
+	scan_count = bitmap_weight(active_scan_mask, indio_dev->masklength);
+
+	command = AD7298_WRITE | st->ext_ref;
+
+	for (i = 0, m = AD7298_CH(0); i < AD7298_MAX_CHAN; i++, m >>= 1)
+		if (test_bit(i, active_scan_mask))
+			command |= m;
+
+	st->tx_buf[0] = cpu_to_be16(command);
+
+	/* build spi ring message */
+	st->ring_xfer[0].tx_buf = &st->tx_buf[0];
+	st->ring_xfer[0].len = 2;
+	st->ring_xfer[0].cs_change = 1;
+	st->ring_xfer[1].tx_buf = &st->tx_buf[1];
+	st->ring_xfer[1].len = 2;
+	st->ring_xfer[1].cs_change = 1;
+
+	spi_message_init(&st->ring_msg);
+	spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg);
+	spi_message_add_tail(&st->ring_xfer[1], &st->ring_msg);
+
+	for (i = 0; i < scan_count; i++) {
+		st->ring_xfer[i + 2].rx_buf = &st->rx_buf[i];
+		st->ring_xfer[i + 2].len = 2;
+		st->ring_xfer[i + 2].cs_change = 1;
+		spi_message_add_tail(&st->ring_xfer[i + 2], &st->ring_msg);
+	}
+	/* make sure last transfer cs_change is not set */
+	st->ring_xfer[i + 1].cs_change = 0;
+
+	return 0;
+}
+
+/**
+ * ad7298_trigger_handler() bh of trigger launched polling to ring buffer
+ *
+ * Currently there is no option in this driver to disable the saving of
+ * timestamps within the ring.
+ **/
+static irqreturn_t ad7298_trigger_handler(int irq, void *p)
+{
+	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);
+
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch)
+{
+	int ret;
+	st->tx_buf[0] = cpu_to_be16(AD7298_WRITE | st->ext_ref |
+				   (AD7298_CH(0) >> ch));
+
+	ret = spi_sync(st->spi, &st->scan_single_msg);
+	if (ret)
+		return ret;
+
+	return be16_to_cpu(st->rx_buf[0]);
+}
+
+static int ad7298_scan_temp(struct ad7298_state *st, int *val)
+{
+	int ret;
+	__be16 buf;
+
+	buf = cpu_to_be16(AD7298_WRITE | AD7298_TSENSE |
+			  AD7298_TAVG | st->ext_ref);
+
+	ret = spi_write(st->spi, (u8 *)&buf, 2);
+	if (ret)
+		return ret;
+
+	buf = cpu_to_be16(0);
+
+	ret = spi_write(st->spi, (u8 *)&buf, 2);
+	if (ret)
+		return ret;
+
+	usleep_range(101, 1000); /* sleep > 100us */
+
+	ret = spi_read(st->spi, (u8 *)&buf, 2);
+	if (ret)
+		return ret;
+
+	*val = sign_extend32(be16_to_cpu(buf), 11);
+
+	return 0;
+}
+
+static int ad7298_get_ref_voltage(struct ad7298_state *st)
+{
+	int vref;
+
+	if (st->ext_ref) {
+		vref = regulator_get_voltage(st->reg);
+		if (vref < 0)
+			return vref;
+
+		return vref / 1000;
+	} else {
+		return AD7298_INTREF_mV;
+	}
+}
+
+static int ad7298_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val,
+			   int *val2,
+			   long m)
+{
+	int ret;
+	struct ad7298_state *st = iio_priv(indio_dev);
+
+	switch (m) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&indio_dev->mlock);
+		if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
+			ret = -EBUSY;
+		} else {
+			if (chan->address == AD7298_CH_TEMP)
+				ret = ad7298_scan_temp(st, val);
+			else
+				ret = ad7298_scan_direct(st, chan->address);
+		}
+		mutex_unlock(&indio_dev->mlock);
+
+		if (ret < 0)
+			return ret;
+
+		if (chan->address != AD7298_CH_TEMP)
+			*val = ret & RES_MASK(AD7298_BITS);
+
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_VOLTAGE:
+			*val = ad7298_get_ref_voltage(st);
+			*val2 = chan->scan_type.realbits;
+			return IIO_VAL_FRACTIONAL_LOG2;
+		case IIO_TEMP:
+			*val = ad7298_get_ref_voltage(st);
+			*val2 = 10;
+			return IIO_VAL_FRACTIONAL;
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_OFFSET:
+		*val = 1093 - 2732500 / ad7298_get_ref_voltage(st);
+		return IIO_VAL_INT;
+	}
+	return -EINVAL;
+}
+
+static const struct iio_info ad7298_info = {
+	.read_raw = &ad7298_read_raw,
+	.update_scan_mode = ad7298_update_scan_mode,
+	.driver_module = THIS_MODULE,
+};
+
+static int __devinit ad7298_probe(struct spi_device *spi)
+{
+	struct ad7298_platform_data *pdata = spi->dev.platform_data;
+	struct ad7298_state *st;
+	struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+	int ret;
+
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
+	st = iio_priv(indio_dev);
+
+	if (pdata && pdata->ext_ref)
+		st->ext_ref = AD7298_EXTREF;
+
+	if (st->ext_ref) {
+		st->reg = regulator_get(&spi->dev, "vref");
+		if (IS_ERR(st->reg)) {
+			ret = PTR_ERR(st->reg);
+			goto error_free;
+		}
+		ret = regulator_enable(st->reg);
+		if (ret)
+			goto error_put_reg;
+	}
+
+	spi_set_drvdata(spi, indio_dev);
+
+	st->spi = spi;
+
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = ad7298_channels;
+	indio_dev->num_channels = ARRAY_SIZE(ad7298_channels);
+	indio_dev->info = &ad7298_info;
+
+	/* Setup default message */
+
+	st->scan_single_xfer[0].tx_buf = &st->tx_buf[0];
+	st->scan_single_xfer[0].len = 2;
+	st->scan_single_xfer[0].cs_change = 1;
+	st->scan_single_xfer[1].tx_buf = &st->tx_buf[1];
+	st->scan_single_xfer[1].len = 2;
+	st->scan_single_xfer[1].cs_change = 1;
+	st->scan_single_xfer[2].rx_buf = &st->rx_buf[0];
+	st->scan_single_xfer[2].len = 2;
+
+	spi_message_init(&st->scan_single_msg);
+	spi_message_add_tail(&st->scan_single_xfer[0], &st->scan_single_msg);
+	spi_message_add_tail(&st->scan_single_xfer[1], &st->scan_single_msg);
+	spi_message_add_tail(&st->scan_single_xfer[2], &st->scan_single_msg);
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+			&ad7298_trigger_handler, NULL);
+	if (ret)
+		goto error_disable_reg;
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_cleanup_ring;
+
+	return 0;
+
+error_cleanup_ring:
+	iio_triggered_buffer_cleanup(indio_dev);
+error_disable_reg:
+	if (st->ext_ref)
+		regulator_disable(st->reg);
+error_put_reg:
+	if (st->ext_ref)
+		regulator_put(st->reg);
+error_free:
+	iio_device_free(indio_dev);
+
+	return ret;
+}
+
+static int __devexit ad7298_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ad7298_state *st = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+	if (st->ext_ref) {
+		regulator_disable(st->reg);
+		regulator_put(st->reg);
+	}
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+static const struct spi_device_id ad7298_id[] = {
+	{"ad7298", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(spi, ad7298_id);
+
+static struct spi_driver ad7298_driver = {
+	.driver = {
+		.name	= "ad7298",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ad7298_probe,
+	.remove		= __devexit_p(ad7298_remove),
+	.id_table	= ad7298_id,
+};
+module_spi_driver(ad7298_driver);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD7298 ADC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c
index 7f2f45a..330248b 100644
--- a/drivers/iio/adc/ad7476.c
+++ b/drivers/iio/adc/ad7476.c
@@ -76,7 +76,7 @@ static irqreturn_t ad7476_trigger_handler(int irq, void  *p)
 	if (indio_dev->scan_timestamp)
 		((s64 *)st->data)[1] = time_ns;
 
-	iio_push_to_buffer(indio_dev->buffer, st->data);
+	iio_push_to_buffers(indio_dev, st->data);
 done:
 	iio_trigger_notify_done(indio_dev->trig);
 
diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c
new file mode 100644
index 0000000..81153fa
--- /dev/null
+++ b/drivers/iio/adc/ad7887.c
@@ -0,0 +1,378 @@
+/*
+ * AD7887 SPI ADC driver
+ *
+ * Copyright 2010-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#include <linux/platform_data/ad7887.h>
+
+#define AD7887_REF_DIS		(1 << 5) /* on-chip reference disable */
+#define AD7887_DUAL		(1 << 4) /* dual-channel mode */
+#define AD7887_CH_AIN1		(1 << 3) /* convert on channel 1, DUAL=1 */
+#define AD7887_CH_AIN0		(0 << 3) /* convert on channel 0, DUAL=0,1 */
+#define AD7887_PM_MODE1		(0)	 /* CS based shutdown */
+#define AD7887_PM_MODE2		(1)	 /* full on */
+#define AD7887_PM_MODE3		(2)	 /* auto shutdown after conversion */
+#define AD7887_PM_MODE4		(3)	 /* standby mode */
+
+enum ad7887_channels {
+	AD7887_CH0,
+	AD7887_CH0_CH1,
+	AD7887_CH1,
+};
+
+#define RES_MASK(bits)	((1 << (bits)) - 1)
+
+/**
+ * struct ad7887_chip_info - chip specifc information
+ * @int_vref_mv:	the internal reference voltage
+ * @channel:		channel specification
+ */
+struct ad7887_chip_info {
+	u16				int_vref_mv;
+	struct iio_chan_spec		channel[3];
+};
+
+struct ad7887_state {
+	struct spi_device		*spi;
+	const struct ad7887_chip_info	*chip_info;
+	struct regulator		*reg;
+	struct spi_transfer		xfer[4];
+	struct spi_message		msg[3];
+	struct spi_message		*ring_msg;
+	unsigned char			tx_cmd_buf[4];
+
+	/*
+	 * DMA (thus cache coherency maintenance) requires the
+	 * transfer buffers to live in their own cache lines.
+	 * Buffer needs to be large enough to hold two 16 bit samples and a
+	 * 64 bit aligned 64 bit timestamp.
+	 */
+	unsigned char data[ALIGN(4, sizeof(s64)) + sizeof(s64)]
+		____cacheline_aligned;
+};
+
+enum ad7887_supported_device_ids {
+	ID_AD7887
+};
+
+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) {
+	case (1 << 0):
+		st->ring_msg = &st->msg[AD7887_CH0];
+		break;
+	case (1 << 1):
+		st->ring_msg = &st->msg[AD7887_CH1];
+		/* Dummy read: push CH1 setting down to hardware */
+		spi_sync(st->spi, st->ring_msg);
+		break;
+	case ((1 << 1) | (1 << 0)):
+		st->ring_msg = &st->msg[AD7887_CH0_CH1];
+		break;
+	}
+
+	return 0;
+}
+
+static int ad7887_ring_postdisable(struct iio_dev *indio_dev)
+{
+	struct ad7887_state *st = iio_priv(indio_dev);
+
+	/* dummy read: restore default CH0 settin */
+	return spi_sync(st->spi, &st->msg[AD7887_CH0]);
+}
+
+/**
+ * ad7887_trigger_handler() bh of trigger launched polling to ring buffer
+ *
+ * Currently there is no option in this driver to disable the saving of
+ * timestamps within the ring.
+ **/
+static irqreturn_t ad7887_trigger_handler(int irq, void *p)
+{
+	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);
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static const struct iio_buffer_setup_ops ad7887_ring_setup_ops = {
+	.preenable = &ad7887_ring_preenable,
+	.postenable = &iio_triggered_buffer_postenable,
+	.predisable = &iio_triggered_buffer_predisable,
+	.postdisable = &ad7887_ring_postdisable,
+};
+
+static int ad7887_scan_direct(struct ad7887_state *st, unsigned ch)
+{
+	int ret = spi_sync(st->spi, &st->msg[ch]);
+	if (ret)
+		return ret;
+
+	return (st->data[(ch * 2)] << 8) | st->data[(ch * 2) + 1];
+}
+
+static int ad7887_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val,
+			   int *val2,
+			   long m)
+{
+	int ret;
+	struct ad7887_state *st = iio_priv(indio_dev);
+
+	switch (m) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&indio_dev->mlock);
+		if (iio_buffer_enabled(indio_dev))
+			ret = -EBUSY;
+		else
+			ret = ad7887_scan_direct(st, chan->address);
+		mutex_unlock(&indio_dev->mlock);
+
+		if (ret < 0)
+			return ret;
+		*val = ret >> chan->scan_type.shift;
+		*val &= RES_MASK(chan->scan_type.realbits);
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		if (st->reg) {
+			*val = regulator_get_voltage(st->reg);
+			if (*val < 0)
+				return *val;
+			*val /= 1000;
+		} else {
+			*val = st->chip_info->int_vref_mv;
+		}
+
+		*val2 = chan->scan_type.realbits;
+
+		return IIO_VAL_FRACTIONAL_LOG2;
+	}
+	return -EINVAL;
+}
+
+
+static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
+	/*
+	 * More devices added in future
+	 */
+	[ID_AD7887] = {
+		.channel[0] = {
+			.type = IIO_VOLTAGE,
+			.indexed = 1,
+			.channel = 1,
+			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+			IIO_CHAN_INFO_SCALE_SHARED_BIT,
+			.address = 1,
+			.scan_index = 1,
+			.scan_type = IIO_ST('u', 12, 16, 0),
+		},
+		.channel[1] = {
+			.type = IIO_VOLTAGE,
+			.indexed = 1,
+			.channel = 0,
+			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+			IIO_CHAN_INFO_SCALE_SHARED_BIT,
+			.address = 0,
+			.scan_index = 0,
+			.scan_type = IIO_ST('u', 12, 16, 0),
+		},
+		.channel[2] = IIO_CHAN_SOFT_TIMESTAMP(2),
+		.int_vref_mv = 2500,
+	},
+};
+
+static const struct iio_info ad7887_info = {
+	.read_raw = &ad7887_read_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int __devinit ad7887_probe(struct spi_device *spi)
+{
+	struct ad7887_platform_data *pdata = spi->dev.platform_data;
+	struct ad7887_state *st;
+	struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+	uint8_t mode;
+	int ret;
+
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
+	st = iio_priv(indio_dev);
+
+	if (!pdata || !pdata->use_onchip_ref) {
+		st->reg = regulator_get(&spi->dev, "vref");
+		if (IS_ERR(st->reg)) {
+			ret = PTR_ERR(st->reg);
+			goto error_free;
+		}
+
+		ret = regulator_enable(st->reg);
+		if (ret)
+			goto error_put_reg;
+	}
+
+	st->chip_info =
+		&ad7887_chip_info_tbl[spi_get_device_id(spi)->driver_data];
+
+	spi_set_drvdata(spi, indio_dev);
+	st->spi = spi;
+
+	/* Estabilish that the iio_dev is a child of the spi device */
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->info = &ad7887_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	/* Setup default message */
+
+	mode = AD7887_PM_MODE4;
+	if (!pdata || !pdata->use_onchip_ref)
+		mode |= AD7887_REF_DIS;
+	if (pdata && pdata->en_dual)
+		mode |= AD7887_DUAL;
+
+	st->tx_cmd_buf[0] = AD7887_CH_AIN0 | mode;
+
+	st->xfer[0].rx_buf = &st->data[0];
+	st->xfer[0].tx_buf = &st->tx_cmd_buf[0];
+	st->xfer[0].len = 2;
+
+	spi_message_init(&st->msg[AD7887_CH0]);
+	spi_message_add_tail(&st->xfer[0], &st->msg[AD7887_CH0]);
+
+	if (pdata && pdata->en_dual) {
+		st->tx_cmd_buf[2] = AD7887_CH_AIN1 | mode;
+
+		st->xfer[1].rx_buf = &st->data[0];
+		st->xfer[1].tx_buf = &st->tx_cmd_buf[2];
+		st->xfer[1].len = 2;
+
+		st->xfer[2].rx_buf = &st->data[2];
+		st->xfer[2].tx_buf = &st->tx_cmd_buf[0];
+		st->xfer[2].len = 2;
+
+		spi_message_init(&st->msg[AD7887_CH0_CH1]);
+		spi_message_add_tail(&st->xfer[1], &st->msg[AD7887_CH0_CH1]);
+		spi_message_add_tail(&st->xfer[2], &st->msg[AD7887_CH0_CH1]);
+
+		st->xfer[3].rx_buf = &st->data[2];
+		st->xfer[3].tx_buf = &st->tx_cmd_buf[2];
+		st->xfer[3].len = 2;
+
+		spi_message_init(&st->msg[AD7887_CH1]);
+		spi_message_add_tail(&st->xfer[3], &st->msg[AD7887_CH1]);
+
+		indio_dev->channels = st->chip_info->channel;
+		indio_dev->num_channels = 3;
+	} else {
+		indio_dev->channels = &st->chip_info->channel[1];
+		indio_dev->num_channels = 2;
+	}
+
+	ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+			&ad7887_trigger_handler, &ad7887_ring_setup_ops);
+	if (ret)
+		goto error_disable_reg;
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_unregister_ring;
+
+	return 0;
+error_unregister_ring:
+	iio_triggered_buffer_cleanup(indio_dev);
+error_disable_reg:
+	if (st->reg)
+		regulator_disable(st->reg);
+error_put_reg:
+	if (st->reg)
+		regulator_put(st->reg);
+error_free:
+	iio_device_free(indio_dev);
+
+	return ret;
+}
+
+static int __devexit ad7887_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ad7887_state *st = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+	if (st->reg) {
+		regulator_disable(st->reg);
+		regulator_put(st->reg);
+	}
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+static const struct spi_device_id ad7887_id[] = {
+	{"ad7887", ID_AD7887},
+	{}
+};
+MODULE_DEVICE_TABLE(spi, ad7887_id);
+
+static struct spi_driver ad7887_driver = {
+	.driver = {
+		.name	= "ad7887",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ad7887_probe,
+	.remove		= __devexit_p(ad7887_remove),
+	.id_table	= ad7887_id,
+};
+module_spi_driver(ad7887_driver);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD7887 ADC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index 67baa13..afe6d78 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -391,7 +391,7 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
 		break;
 	}
 
-	iio_push_to_buffer(indio_dev->buffer, (uint8_t *)data);
+	iio_push_to_buffers(indio_dev, (uint8_t *)data);
 
 	iio_trigger_notify_done(indio_dev->trig);
 	sigma_delta->irq_dis = false;
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 3ed94bf..03b8594 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -46,7 +46,6 @@ struct at91_adc_state {
 	struct clk		*clk;
 	bool			done;
 	int			irq;
-	bool			irq_enabled;
 	u16			last_value;
 	struct mutex		lock;
 	u8			num_channels;
@@ -66,7 +65,6 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
 	struct iio_poll_func *pf = p;
 	struct iio_dev *idev = pf->indio_dev;
 	struct at91_adc_state *st = iio_priv(idev);
-	struct iio_buffer *buffer = idev->buffer;
 	int i, j = 0;
 
 	for (i = 0; i < idev->masklength; i++) {
@@ -82,10 +80,9 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
 		*timestamp = pf->timestamp;
 	}
 
-	buffer->access->store_to(buffer, (u8 *)st->buffer);
+	iio_push_to_buffers(indio_dev, (u8 *)st->buffer);
 
 	iio_trigger_notify_done(idev->trig);
-	st->irq_enabled = true;
 
 	/* Needed to ACK the DRDY interruption */
 	at91_adc_readl(st, AT91_ADC_LCDR);
@@ -106,7 +103,6 @@ static irqreturn_t at91_adc_eoc_trigger(int irq, void *private)
 
 	if (iio_buffer_enabled(idev)) {
 		disable_irq_nosync(irq);
-		st->irq_enabled = false;
 		iio_trigger_poll(idev->trig, iio_get_time_ns());
 	} else {
 		st->last_value = at91_adc_readl(st, AT91_ADC_LCDR);
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
new file mode 100644
index 0000000..1e84b5b
--- /dev/null
+++ b/drivers/iio/adc/max1363.c
@@ -0,0 +1,1700 @@
+ /*
+  * iio/adc/max1363.c
+  * Copyright (C) 2008-2010 Jonathan Cameron
+  *
+  * based on linux/drivers/i2c/chips/max123x
+  * Copyright (C) 2002-2004 Stefan Eletzhofer
+  *
+  * based on linux/drivers/acron/char/pcf8583.c
+  * Copyright (C) 2000 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.
+  *
+  * max1363.c
+  *
+  * Partial support for max1363 and similar chips.
+  *
+  * Not currently implemented.
+  *
+  * - Control of internal reference.
+  */
+
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/sysfs.h>
+#include <linux/list.h>
+#include <linux/i2c.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/module.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/driver.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger_consumer.h>
+
+#define MAX1363_SETUP_BYTE(a) ((a) | 0x80)
+
+/* There is a fair bit more defined here than currently
+ * used, but the intention is to support everything these
+ * chips do in the long run */
+
+/* see data sheets */
+/* max1363 and max1236, max1237, max1238, max1239 */
+#define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD	0x00
+#define MAX1363_SETUP_AIN3_IS_REF_EXT_TO_REF	0x20
+#define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_INT	0x40
+#define MAX1363_SETUP_AIN3_IS_REF_REF_IS_INT	0x60
+#define MAX1363_SETUP_POWER_UP_INT_REF		0x10
+#define MAX1363_SETUP_POWER_DOWN_INT_REF	0x00
+
+/* think about includeing max11600 etc - more settings */
+#define MAX1363_SETUP_EXT_CLOCK			0x08
+#define MAX1363_SETUP_INT_CLOCK			0x00
+#define MAX1363_SETUP_UNIPOLAR			0x00
+#define MAX1363_SETUP_BIPOLAR			0x04
+#define MAX1363_SETUP_RESET			0x00
+#define MAX1363_SETUP_NORESET			0x02
+/* max1363 only - though don't care on others.
+ * For now monitor modes are not implemented as the relevant
+ * line is not connected on my test board.
+ * The definitions are here as I intend to add this soon.
+ */
+#define MAX1363_SETUP_MONITOR_SETUP		0x01
+
+/* Specific to the max1363 */
+#define MAX1363_MON_RESET_CHAN(a) (1 << ((a) + 4))
+#define MAX1363_MON_INT_ENABLE			0x01
+
+/* defined for readability reasons */
+/* All chips */
+#define MAX1363_CONFIG_BYTE(a) ((a))
+
+#define MAX1363_CONFIG_SE			0x01
+#define MAX1363_CONFIG_DE			0x00
+#define MAX1363_CONFIG_SCAN_TO_CS		0x00
+#define MAX1363_CONFIG_SCAN_SINGLE_8		0x20
+#define MAX1363_CONFIG_SCAN_MONITOR_MODE	0x40
+#define MAX1363_CONFIG_SCAN_SINGLE_1		0x60
+/* max123{6-9} only */
+#define MAX1236_SCAN_MID_TO_CHANNEL		0x40
+
+/* max1363 only - merely part of channel selects or don't care for others*/
+#define MAX1363_CONFIG_EN_MON_MODE_READ 0x18
+
+#define MAX1363_CHANNEL_SEL(a) ((a) << 1)
+
+/* max1363 strictly 0x06 - but doesn't matter */
+#define MAX1363_CHANNEL_SEL_MASK		0x1E
+#define MAX1363_SCAN_MASK			0x60
+#define MAX1363_SE_DE_MASK			0x01
+
+#define MAX1363_MAX_CHANNELS 25
+/**
+ * struct max1363_mode - scan mode information
+ * @conf:	The corresponding value of the configuration register
+ * @modemask:	Bit mask corresponding to channels enabled in this mode
+ */
+struct max1363_mode {
+	int8_t		conf;
+	DECLARE_BITMAP(modemask, MAX1363_MAX_CHANNELS);
+};
+
+/* This must be maintained along side the max1363_mode_table in max1363_core */
+enum max1363_modes {
+	/* Single read of a single channel */
+	_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11,
+	/* Differential single read */
+	d0m1, d2m3, d4m5, d6m7, d8m9, d10m11,
+	d1m0, d3m2, d5m4, d7m6, d9m8, d11m10,
+	/* Scan to channel and mid to channel where overlapping */
+	s0to1, s0to2, s2to3, s0to3, s0to4, s0to5, s0to6,
+	s6to7, s0to7, s6to8, s0to8, s6to9,
+	s0to9, s6to10, s0to10, s6to11, s0to11,
+	/* Differential scan to channel and mid to channel where overlapping */
+	d0m1to2m3, d0m1to4m5, d0m1to6m7, d6m7to8m9,
+	d0m1to8m9, d6m7to10m11, d0m1to10m11, d1m0to3m2,
+	d1m0to5m4, d1m0to7m6, d7m6to9m8, d1m0to9m8,
+	d7m6to11m10, d1m0to11m10,
+};
+
+/**
+ * struct max1363_chip_info - chip specifc information
+ * @info:		iio core function callbacks structure
+ * @channels:		channel specification
+ * @num_channels:       number of channels
+ * @mode_list:		array of available scan modes
+ * @default_mode:	the scan mode in which the chip starts up
+ * @int_vref_mv:	the internal reference voltage
+ * @num_channels:	number of channels
+ * @bits:		accuracy of the adc in bits
+ */
+struct max1363_chip_info {
+	const struct iio_info		*info;
+	const struct iio_chan_spec	*channels;
+	int				num_channels;
+	const enum max1363_modes	*mode_list;
+	enum max1363_modes		default_mode;
+	u16				int_vref_mv;
+	u8				num_modes;
+	u8				bits;
+};
+
+/**
+ * struct max1363_state - driver instance specific data
+ * @client:		i2c_client
+ * @setupbyte:		cache of current device setup byte
+ * @configbyte:		cache of current device config byte
+ * @chip_info:		chip model specific constants, available modes etc
+ * @current_mode:	the scan mode of this chip
+ * @requestedmask:	a valid requested set of channels
+ * @reg:		supply regulator
+ * @monitor_on:		whether monitor mode is enabled
+ * @monitor_speed:	parameter corresponding to device monitor speed setting
+ * @mask_high:		bitmask for enabled high thresholds
+ * @mask_low:		bitmask for enabled low thresholds
+ * @thresh_high:	high threshold values
+ * @thresh_low:		low threshold values
+ */
+struct max1363_state {
+	struct i2c_client		*client;
+	u8				setupbyte;
+	u8				configbyte;
+	const struct max1363_chip_info	*chip_info;
+	const struct max1363_mode	*current_mode;
+	u32				requestedmask;
+	struct regulator		*reg;
+
+	/* Using monitor modes and buffer at the same time is
+	   currently not supported */
+	bool				monitor_on;
+	unsigned int			monitor_speed:3;
+	u8				mask_high;
+	u8				mask_low;
+	/* 4x unipolar first then the fours bipolar ones */
+	s16				thresh_high[8];
+	s16				thresh_low[8];
+};
+
+#define MAX1363_MODE_SINGLE(_num, _mask) {				\
+		.conf = MAX1363_CHANNEL_SEL(_num)			\
+			| MAX1363_CONFIG_SCAN_SINGLE_1			\
+			| MAX1363_CONFIG_SE,				\
+			.modemask[0] = _mask,				\
+			}
+
+#define MAX1363_MODE_SCAN_TO_CHANNEL(_num, _mask) {			\
+		.conf = MAX1363_CHANNEL_SEL(_num)			\
+			| MAX1363_CONFIG_SCAN_TO_CS			\
+			| MAX1363_CONFIG_SE,				\
+			.modemask[0] = _mask,				\
+			}
+
+/* note not available for max1363 hence naming */
+#define MAX1236_MODE_SCAN_MID_TO_CHANNEL(_mid, _num, _mask) {		\
+		.conf = MAX1363_CHANNEL_SEL(_num)			\
+			| MAX1236_SCAN_MID_TO_CHANNEL			\
+			| MAX1363_CONFIG_SE,				\
+			.modemask[0] = _mask				\
+}
+
+#define MAX1363_MODE_DIFF_SINGLE(_nump, _numm, _mask) {			\
+		.conf = MAX1363_CHANNEL_SEL(_nump)			\
+			| MAX1363_CONFIG_SCAN_SINGLE_1			\
+			| MAX1363_CONFIG_DE,				\
+			.modemask[0] = _mask				\
+			}
+
+/* Can't think how to automate naming so specify for now */
+#define MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(_num, _numvals, _mask) {	\
+		.conf = MAX1363_CHANNEL_SEL(_num)			\
+			| MAX1363_CONFIG_SCAN_TO_CS			\
+			| MAX1363_CONFIG_DE,				\
+			.modemask[0] = _mask				\
+			}
+
+/* note only available for max1363 hence naming */
+#define MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(_num, _numvals, _mask) {	\
+		.conf = MAX1363_CHANNEL_SEL(_num)			\
+			| MAX1236_SCAN_MID_TO_CHANNEL			\
+			| MAX1363_CONFIG_SE,				\
+			.modemask[0] = _mask				\
+}
+
+static const struct max1363_mode max1363_mode_table[] = {
+	/* All of the single channel options first */
+	MAX1363_MODE_SINGLE(0, 1 << 0),
+	MAX1363_MODE_SINGLE(1, 1 << 1),
+	MAX1363_MODE_SINGLE(2, 1 << 2),
+	MAX1363_MODE_SINGLE(3, 1 << 3),
+	MAX1363_MODE_SINGLE(4, 1 << 4),
+	MAX1363_MODE_SINGLE(5, 1 << 5),
+	MAX1363_MODE_SINGLE(6, 1 << 6),
+	MAX1363_MODE_SINGLE(7, 1 << 7),
+	MAX1363_MODE_SINGLE(8, 1 << 8),
+	MAX1363_MODE_SINGLE(9, 1 << 9),
+	MAX1363_MODE_SINGLE(10, 1 << 10),
+	MAX1363_MODE_SINGLE(11, 1 << 11),
+
+	MAX1363_MODE_DIFF_SINGLE(0, 1, 1 << 12),
+	MAX1363_MODE_DIFF_SINGLE(2, 3, 1 << 13),
+	MAX1363_MODE_DIFF_SINGLE(4, 5, 1 << 14),
+	MAX1363_MODE_DIFF_SINGLE(6, 7, 1 << 15),
+	MAX1363_MODE_DIFF_SINGLE(8, 9, 1 << 16),
+	MAX1363_MODE_DIFF_SINGLE(10, 11, 1 << 17),
+	MAX1363_MODE_DIFF_SINGLE(1, 0, 1 << 18),
+	MAX1363_MODE_DIFF_SINGLE(3, 2, 1 << 19),
+	MAX1363_MODE_DIFF_SINGLE(5, 4, 1 << 20),
+	MAX1363_MODE_DIFF_SINGLE(7, 6, 1 << 21),
+	MAX1363_MODE_DIFF_SINGLE(9, 8, 1 << 22),
+	MAX1363_MODE_DIFF_SINGLE(11, 10, 1 << 23),
+
+	/* The multichannel scans next */
+	MAX1363_MODE_SCAN_TO_CHANNEL(1, 0x003),
+	MAX1363_MODE_SCAN_TO_CHANNEL(2, 0x007),
+	MAX1236_MODE_SCAN_MID_TO_CHANNEL(2, 3, 0x00C),
+	MAX1363_MODE_SCAN_TO_CHANNEL(3, 0x00F),
+	MAX1363_MODE_SCAN_TO_CHANNEL(4, 0x01F),
+	MAX1363_MODE_SCAN_TO_CHANNEL(5, 0x03F),
+	MAX1363_MODE_SCAN_TO_CHANNEL(6, 0x07F),
+	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 7, 0x0C0),
+	MAX1363_MODE_SCAN_TO_CHANNEL(7, 0x0FF),
+	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 8, 0x1C0),
+	MAX1363_MODE_SCAN_TO_CHANNEL(8, 0x1FF),
+	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 9, 0x3C0),
+	MAX1363_MODE_SCAN_TO_CHANNEL(9, 0x3FF),
+	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 10, 0x7C0),
+	MAX1363_MODE_SCAN_TO_CHANNEL(10, 0x7FF),
+	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 11, 0xFC0),
+	MAX1363_MODE_SCAN_TO_CHANNEL(11, 0xFFF),
+
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(2, 2, 0x003000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(4, 3, 0x007000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(6, 4, 0x00F000),
+	MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(8, 2, 0x018000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(8, 5, 0x01F000),
+	MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(10, 3, 0x038000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(10, 6, 0x3F000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(3, 2, 0x0C0000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(5, 3, 0x1C0000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(7, 4, 0x3C0000),
+	MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(9, 2, 0x600000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(9, 5, 0x7C0000),
+	MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(11, 3, 0xE00000),
+	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(11, 6, 0xFC0000),
+};
+
+static const struct max1363_mode
+*max1363_match_mode(const unsigned long *mask,
+const struct max1363_chip_info *ci)
+{
+	int i;
+	if (mask)
+		for (i = 0; i < ci->num_modes; i++)
+			if (bitmap_subset(mask,
+					  max1363_mode_table[ci->mode_list[i]].
+					  modemask,
+					  MAX1363_MAX_CHANNELS))
+				return &max1363_mode_table[ci->mode_list[i]];
+	return NULL;
+}
+
+static int max1363_write_basic_config(struct i2c_client *client,
+				      unsigned char d1,
+				      unsigned char d2)
+{
+	u8 tx_buf[2] = {d1, d2};
+
+	return i2c_master_send(client, tx_buf, 2);
+}
+
+static int max1363_set_scan_mode(struct max1363_state *st)
+{
+	st->configbyte &= ~(MAX1363_CHANNEL_SEL_MASK
+			    | MAX1363_SCAN_MASK
+			    | MAX1363_SE_DE_MASK);
+	st->configbyte |= st->current_mode->conf;
+
+	return max1363_write_basic_config(st->client,
+					  st->setupbyte,
+					  st->configbyte);
+}
+
+static int max1363_read_single_chan(struct iio_dev *indio_dev,
+				    struct iio_chan_spec const *chan,
+				    int *val,
+				    long m)
+{
+	int ret = 0;
+	s32 data;
+	char rxbuf[2];
+	struct max1363_state *st = iio_priv(indio_dev);
+	struct i2c_client *client = st->client;
+
+	mutex_lock(&indio_dev->mlock);
+	/*
+	 * If monitor mode is enabled, the method for reading a single
+	 * channel will have to be rather different and has not yet
+	 * been implemented.
+	 *
+	 * Also, cannot read directly if buffered capture enabled.
+	 */
+	if (st->monitor_on || iio_buffer_enabled(indio_dev)) {
+		ret = -EBUSY;
+		goto error_ret;
+	}
+
+	/* Check to see if current scan mode is correct */
+	if (st->current_mode != &max1363_mode_table[chan->address]) {
+		/* Update scan mode if needed */
+		st->current_mode = &max1363_mode_table[chan->address];
+		ret = max1363_set_scan_mode(st);
+		if (ret < 0)
+			goto error_ret;
+	}
+	if (st->chip_info->bits != 8) {
+		/* Get reading */
+		data = i2c_master_recv(client, rxbuf, 2);
+		if (data < 0) {
+			ret = data;
+			goto error_ret;
+		}
+		data = (s32)(rxbuf[1]) | ((s32)(rxbuf[0] & 0x0F)) << 8;
+	} else {
+		/* Get reading */
+		data = i2c_master_recv(client, rxbuf, 1);
+		if (data < 0) {
+			ret = data;
+			goto error_ret;
+		}
+		data = rxbuf[0];
+	}
+	*val = data;
+error_ret:
+	mutex_unlock(&indio_dev->mlock);
+	return ret;
+
+}
+
+static int max1363_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int *val,
+			    int *val2,
+			    long m)
+{
+	struct max1363_state *st = iio_priv(indio_dev);
+	int ret;
+	switch (m) {
+	case IIO_CHAN_INFO_RAW:
+		ret = max1363_read_single_chan(indio_dev, chan, val, m);
+		if (ret < 0)
+			return ret;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		if ((1 << (st->chip_info->bits + 1)) >
+		    st->chip_info->int_vref_mv) {
+			*val = 0;
+			*val2 = 500000;
+			return IIO_VAL_INT_PLUS_MICRO;
+		} else {
+			*val = (st->chip_info->int_vref_mv)
+				>> st->chip_info->bits;
+			return IIO_VAL_INT;
+		}
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* Applies to max1363 */
+static const enum max1363_modes max1363_mode_list[] = {
+	_s0, _s1, _s2, _s3,
+	s0to1, s0to2, s0to3,
+	d0m1, d2m3, d1m0, d3m2,
+	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))
+#define MAX1363_INFO_MASK (IIO_CHAN_INFO_RAW_SEPARATE_BIT |	\
+			   IIO_CHAN_INFO_SCALE_SHARED_BIT)
+#define MAX1363_CHAN_U(num, addr, si, bits, evmask)			\
+	{								\
+		.type = IIO_VOLTAGE,					\
+		.indexed = 1,						\
+		.channel = num,						\
+		.address = addr,					\
+		.info_mask = MAX1363_INFO_MASK,				\
+		.datasheet_name = "AIN"#num,				\
+		.scan_type = {						\
+			.sign = 'u',					\
+			.realbits = bits,				\
+			.storagebits = (bits > 8) ? 16 : 8,		\
+			.endianness = IIO_BE,				\
+		},							\
+		.scan_index = si,					\
+		.event_mask = evmask,					\
+	}
+
+/* bipolar channel */
+#define MAX1363_CHAN_B(num, num2, addr, si, bits, evmask)		\
+	{								\
+		.type = IIO_VOLTAGE,					\
+		.differential = 1,					\
+		.indexed = 1,						\
+		.channel = num,						\
+		.channel2 = num2,					\
+		.address = addr,					\
+		.info_mask = MAX1363_INFO_MASK,				\
+		.datasheet_name = "AIN"#num"-AIN"#num2,			\
+		.scan_type = {						\
+			.sign = 's',					\
+			.realbits = bits,				\
+			.storagebits = (bits > 8) ? 16 : 8,		\
+			.endianness = IIO_BE,				\
+		},							\
+		.scan_index = si,					\
+		.event_mask = evmask,					\
+	}
+
+#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)			\
+	}
+
+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 max1361_channels[] =
+	MAX1363_4X_CHANS(10, MAX1363_EV_M);
+static const struct iio_chan_spec max1363_channels[] =
+	MAX1363_4X_CHANS(12, MAX1363_EV_M);
+
+/* Applies to max1236, max1237 */
+static const enum max1363_modes max1236_mode_list[] = {
+	_s0, _s1, _s2, _s3,
+	s0to1, s0to2, s0to3,
+	d0m1, d2m3, d1m0, d3m2,
+	d0m1to2m3, d1m0to3m2,
+	s2to3,
+};
+
+/* Applies to max1238, max1239 */
+static const enum max1363_modes max1238_mode_list[] = {
+	_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11,
+	s0to1, s0to2, s0to3, s0to4, s0to5, s0to6,
+	s0to7, s0to8, s0to9, s0to10, s0to11,
+	d0m1, d2m3, d4m5, d6m7, d8m9, d10m11,
+	d1m0, d3m2, d5m4, d7m6, d9m8, d11m10,
+	d0m1to2m3, d0m1to4m5, d0m1to6m7, d0m1to8m9, d0m1to10m11,
+	d1m0to3m2, d1m0to5m4, d1m0to7m6, d1m0to9m8, d1m0to11m10,
+	s6to7, s6to8, s6to9, s6to10, s6to11,
+	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)			\
+	}
+static const struct iio_chan_spec max1038_channels[] = MAX1363_12X_CHANS(8);
+static const struct iio_chan_spec max1138_channels[] = MAX1363_12X_CHANS(10);
+static const struct iio_chan_spec max1238_channels[] = MAX1363_12X_CHANS(12);
+
+static const enum max1363_modes max11607_mode_list[] = {
+	_s0, _s1, _s2, _s3,
+	s0to1, s0to2, s0to3,
+	s2to3,
+	d0m1, d2m3, d1m0, d3m2,
+	d0m1to2m3, d1m0to3m2,
+};
+
+static const enum max1363_modes max11608_mode_list[] = {
+	_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7,
+	s0to1, s0to2, s0to3, s0to4, s0to5, s0to6, s0to7,
+	s6to7,
+	d0m1, d2m3, d4m5, d6m7,
+	d1m0, d3m2, d5m4, d7m6,
+	d0m1to2m3, d0m1to4m5, d0m1to6m7,
+	d1m0to3m2, d1m0to5m4, d1m0to7m6,
+};
+
+#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),	\
+	IIO_CHAN_SOFT_TIMESTAMP(16)			\
+}
+static const struct iio_chan_spec max11602_channels[] = MAX1363_8X_CHANS(8);
+static const struct iio_chan_spec max11608_channels[] = MAX1363_8X_CHANS(10);
+static const struct iio_chan_spec max11614_channels[] = MAX1363_8X_CHANS(12);
+
+static const enum max1363_modes max11644_mode_list[] = {
+	_s0, _s1, s0to1, d0m1, d1m0,
+};
+
+#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),	\
+	IIO_CHAN_SOFT_TIMESTAMP(4)			\
+	}
+
+static const struct iio_chan_spec max11646_channels[] = MAX1363_2X_CHANS(10);
+static const struct iio_chan_spec max11644_channels[] = MAX1363_2X_CHANS(12);
+
+enum { max1361,
+       max1362,
+       max1363,
+       max1364,
+       max1036,
+       max1037,
+       max1038,
+       max1039,
+       max1136,
+       max1137,
+       max1138,
+       max1139,
+       max1236,
+       max1237,
+       max1238,
+       max1239,
+       max11600,
+       max11601,
+       max11602,
+       max11603,
+       max11604,
+       max11605,
+       max11606,
+       max11607,
+       max11608,
+       max11609,
+       max11610,
+       max11611,
+       max11612,
+       max11613,
+       max11614,
+       max11615,
+       max11616,
+       max11617,
+       max11644,
+       max11645,
+       max11646,
+       max11647
+};
+
+static const int max1363_monitor_speeds[] = { 133000, 665000, 33300, 16600,
+					      8300, 4200, 2000, 1000 };
+
+static ssize_t max1363_monitor_show_freq(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct max1363_state *st = iio_priv(dev_to_iio_dev(dev));
+	return sprintf(buf, "%d\n", max1363_monitor_speeds[st->monitor_speed]);
+}
+
+static ssize_t max1363_monitor_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 max1363_state *st = iio_priv(indio_dev);
+	int i, ret;
+	unsigned long val;
+	bool found = false;
+
+	ret = strict_strtoul(buf, 10, &val);
+	if (ret)
+		return -EINVAL;
+	for (i = 0; i < ARRAY_SIZE(max1363_monitor_speeds); i++)
+		if (val == max1363_monitor_speeds[i]) {
+			found = true;
+			break;
+		}
+	if (!found)
+		return -EINVAL;
+
+	mutex_lock(&indio_dev->mlock);
+	st->monitor_speed = i;
+	mutex_unlock(&indio_dev->mlock);
+
+	return 0;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR,
+			max1363_monitor_show_freq,
+			max1363_monitor_store_freq);
+
+static IIO_CONST_ATTR(sampling_frequency_available,
+		"133000 665000 33300 16600 8300 4200 2000 1000");
+
+static int max1363_read_thresh(struct iio_dev *indio_dev,
+			       u64 event_code,
+			       int *val)
+{
+	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)];
+	else
+		*val = st->thresh_high[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)];
+	return 0;
+}
+
+static int max1363_write_thresh(struct iio_dev *indio_dev,
+				u64 event_code,
+				int val)
+{
+	struct max1363_state *st = iio_priv(indio_dev);
+	/* make it handle signed correctly as well */
+	switch (st->chip_info->bits) {
+	case 10:
+		if (val > 0x3FF)
+			return -EINVAL;
+		break;
+	case 12:
+		if (val > 0xFFF)
+			return -EINVAL;
+		break;
+	}
+
+	switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
+	case IIO_EV_DIR_FALLING:
+		st->thresh_low[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)] = val;
+		break;
+	case IIO_EV_DIR_RISING:
+		st->thresh_high[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)] = val;
+		break;
+	}
+
+	return 0;
+}
+
+static const u64 max1363_event_codes[] = {
+	IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0,
+			     IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
+	IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 1,
+			     IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
+	IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 2,
+			     IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
+	IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 3,
+			     IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
+	IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0,
+			     IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
+	IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 1,
+			     IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
+	IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 2,
+			     IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
+	IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 3,
+			     IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
+};
+
+static irqreturn_t max1363_event_handler(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct max1363_state *st = iio_priv(indio_dev);
+	s64 timestamp = iio_get_time_ns();
+	unsigned long mask, loc;
+	u8 rx;
+	u8 tx[2] = { st->setupbyte,
+		     MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0 };
+
+	i2c_master_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);
+
+	return IRQ_HANDLED;
+}
+
+static int max1363_read_event_config(struct iio_dev *indio_dev,
+				     u64 event_code)
+{
+	struct max1363_state *st = iio_priv(indio_dev);
+	int val;
+	int number = IIO_EVENT_CODE_EXTRACT_CHAN(event_code);
+
+	mutex_lock(&indio_dev->mlock);
+	if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING)
+		val = (1 << number) & st->mask_low;
+	else
+		val = (1 << number) & st->mask_high;
+	mutex_unlock(&indio_dev->mlock);
+
+	return val;
+}
+
+static int max1363_monitor_mode_update(struct max1363_state *st, int enabled)
+{
+	u8 *tx_buf;
+	int ret, i = 3, j;
+	unsigned long numelements;
+	int len;
+	const long *modemask;
+
+	if (!enabled) {
+		/* transition to buffered capture is not currently supported */
+		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);
+	}
+
+	/* Ensure we are in the relevant mode */
+	st->setupbyte |= MAX1363_SETUP_MONITOR_SETUP;
+	st->configbyte &= ~(MAX1363_CHANNEL_SEL_MASK
+			    | MAX1363_SCAN_MASK
+			| MAX1363_SE_DE_MASK);
+	st->configbyte |= MAX1363_CONFIG_SCAN_MONITOR_MODE;
+	if ((st->mask_low | st->mask_high) & 0x0F) {
+		st->configbyte |= max1363_mode_table[s0to3].conf;
+		modemask = max1363_mode_table[s0to3].modemask;
+	} else if ((st->mask_low | st->mask_high) & 0x30) {
+		st->configbyte |= max1363_mode_table[d0m1to2m3].conf;
+		modemask = max1363_mode_table[d0m1to2m3].modemask;
+	} else {
+		st->configbyte |= max1363_mode_table[d1m0to3m2].conf;
+		modemask = max1363_mode_table[d1m0to3m2].modemask;
+	}
+	numelements = bitmap_weight(modemask, MAX1363_MAX_CHANNELS);
+	len = 3 * numelements + 3;
+	tx_buf = kmalloc(len, GFP_KERNEL);
+	if (!tx_buf) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	tx_buf[0] = st->configbyte;
+	tx_buf[1] = st->setupbyte;
+	tx_buf[2] = (st->monitor_speed << 1);
+
+	/*
+	 * So we need to do yet another bit of nefarious scan mode
+	 * setup to match what we need.
+	 */
+	for (j = 0; j < 8; j++)
+		if (test_bit(j, modemask)) {
+			/* Establish the mode is in the scan */
+			if (st->mask_low & (1 << j)) {
+				tx_buf[i] = (st->thresh_low[j] >> 4) & 0xFF;
+				tx_buf[i + 1] = (st->thresh_low[j] << 4) & 0xF0;
+			} else if (j < 4) {
+				tx_buf[i] = 0;
+				tx_buf[i + 1] = 0;
+			} else {
+				tx_buf[i] = 0x80;
+				tx_buf[i + 1] = 0;
+			}
+			if (st->mask_high & (1 << j)) {
+				tx_buf[i + 1] |=
+					(st->thresh_high[j] >> 8) & 0x0F;
+				tx_buf[i + 2] = st->thresh_high[j] & 0xFF;
+			} else if (j < 4) {
+				tx_buf[i + 1] |= 0x0F;
+				tx_buf[i + 2] = 0xFF;
+			} else {
+				tx_buf[i + 1] |= 0x07;
+				tx_buf[i + 2] = 0xFF;
+			}
+			i += 3;
+		}
+
+
+	ret = i2c_master_send(st->client, tx_buf, len);
+	if (ret < 0)
+		goto error_ret;
+	if (ret != len) {
+		ret = -EIO;
+		goto error_ret;
+	}
+
+	/*
+	 * Now that we hopefully have sensible thresholds in place it is
+	 * time to turn the interrupts on.
+	 * It is unclear from the data sheet if this should be necessary
+	 * (i.e. whether monitor mode setup is atomic) but it appears to
+	 * be in practice.
+	 */
+	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);
+	if (ret < 0)
+		goto error_ret;
+	if (ret != 2) {
+		ret = -EIO;
+		goto error_ret;
+	}
+	ret = 0;
+	st->monitor_on = true;
+error_ret:
+
+	kfree(tx_buf);
+
+	return ret;
+}
+
+/*
+ * To keep this manageable we always use one of 3 scan modes.
+ * Scan 0...3, 0-1,2-3 and 1-0,3-2
+ */
+
+static inline int __max1363_check_event_mask(int thismask, int checkmask)
+{
+	int ret = 0;
+	/* Is it unipolar */
+	if (thismask < 4) {
+		if (checkmask & ~0x0F) {
+			ret = -EBUSY;
+			goto error_ret;
+		}
+	} else if (thismask < 6) {
+		if (checkmask & ~0x30) {
+			ret = -EBUSY;
+			goto error_ret;
+		}
+	} else if (checkmask & ~0xC0)
+		ret = -EBUSY;
+error_ret:
+	return ret;
+}
+
+static int max1363_write_event_config(struct iio_dev *indio_dev,
+				      u64 event_code,
+				      int state)
+{
+	int ret = 0;
+	struct max1363_state *st = iio_priv(indio_dev);
+	u16 unifiedmask;
+	int number = IIO_EVENT_CODE_EXTRACT_CHAN(event_code);
+
+	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 (state == 0)
+			st->mask_low &= ~(1 << number);
+		else {
+			ret = __max1363_check_event_mask((1 << number),
+							 unifiedmask);
+			if (ret)
+				goto error_ret;
+			st->mask_low |= (1 << number);
+		}
+	} else {
+		if (state == 0)
+			st->mask_high &= ~(1 << number);
+		else {
+			ret = __max1363_check_event_mask((1 << number),
+							 unifiedmask);
+			if (ret)
+				goto error_ret;
+			st->mask_high |= (1 << number);
+		}
+	}
+
+	max1363_monitor_mode_update(st, !!(st->mask_high | st->mask_low));
+error_ret:
+	mutex_unlock(&indio_dev->mlock);
+
+	return ret;
+}
+
+/*
+ * As with scan_elements, only certain sets of these can
+ * be combined.
+ */
+static struct attribute *max1363_event_attributes[] = {
+	&iio_dev_attr_sampling_frequency.dev_attr.attr,
+	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
+	NULL,
+};
+
+static struct attribute_group max1363_event_attribute_group = {
+	.attrs = max1363_event_attributes,
+	.name = "events",
+};
+
+static int max1363_update_scan_mode(struct iio_dev *indio_dev,
+				    const unsigned long *scan_mask)
+{
+	struct max1363_state *st = iio_priv(indio_dev);
+
+	/*
+	 * Need to figure out the current mode based upon the requested
+	 * scan mask in iio_dev
+	 */
+	st->current_mode = max1363_match_mode(scan_mask, st->chip_info);
+	if (!st->current_mode)
+		return -EINVAL;
+	max1363_set_scan_mode(st);
+	return 0;
+}
+
+static const struct iio_info max1238_info = {
+	.read_raw = &max1363_read_raw,
+	.driver_module = THIS_MODULE,
+	.update_scan_mode = &max1363_update_scan_mode,
+};
+
+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_raw = &max1363_read_raw,
+	.update_scan_mode = &max1363_update_scan_mode,
+	.driver_module = THIS_MODULE,
+	.event_attrs = &max1363_event_attribute_group,
+};
+
+/* max1363 and max1368 tested - rest from data sheet */
+static const struct max1363_chip_info max1363_chip_info_tbl[] = {
+	[max1361] = {
+		.bits = 10,
+		.int_vref_mv = 2048,
+		.mode_list = max1363_mode_list,
+		.num_modes = ARRAY_SIZE(max1363_mode_list),
+		.default_mode = s0to3,
+		.channels = max1361_channels,
+		.num_channels = ARRAY_SIZE(max1361_channels),
+		.info = &max1363_info,
+	},
+	[max1362] = {
+		.bits = 10,
+		.int_vref_mv = 4096,
+		.mode_list = max1363_mode_list,
+		.num_modes = ARRAY_SIZE(max1363_mode_list),
+		.default_mode = s0to3,
+		.channels = max1361_channels,
+		.num_channels = ARRAY_SIZE(max1361_channels),
+		.info = &max1363_info,
+	},
+	[max1363] = {
+		.bits = 12,
+		.int_vref_mv = 2048,
+		.mode_list = max1363_mode_list,
+		.num_modes = ARRAY_SIZE(max1363_mode_list),
+		.default_mode = s0to3,
+		.channels = max1363_channels,
+		.num_channels = ARRAY_SIZE(max1363_channels),
+		.info = &max1363_info,
+	},
+	[max1364] = {
+		.bits = 12,
+		.int_vref_mv = 4096,
+		.mode_list = max1363_mode_list,
+		.num_modes = ARRAY_SIZE(max1363_mode_list),
+		.default_mode = s0to3,
+		.channels = max1363_channels,
+		.num_channels = ARRAY_SIZE(max1363_channels),
+		.info = &max1363_info,
+	},
+	[max1036] = {
+		.bits = 8,
+		.int_vref_mv = 4096,
+		.mode_list = max1236_mode_list,
+		.num_modes = ARRAY_SIZE(max1236_mode_list),
+		.default_mode = s0to3,
+		.info = &max1238_info,
+		.channels = max1036_channels,
+		.num_channels = ARRAY_SIZE(max1036_channels),
+	},
+	[max1037] = {
+		.bits = 8,
+		.int_vref_mv = 2048,
+		.mode_list = max1236_mode_list,
+		.num_modes = ARRAY_SIZE(max1236_mode_list),
+		.default_mode = s0to3,
+		.info = &max1238_info,
+		.channels = max1036_channels,
+		.num_channels = ARRAY_SIZE(max1036_channels),
+	},
+	[max1038] = {
+		.bits = 8,
+		.int_vref_mv = 4096,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.info = &max1238_info,
+		.channels = max1038_channels,
+		.num_channels = ARRAY_SIZE(max1038_channels),
+	},
+	[max1039] = {
+		.bits = 8,
+		.int_vref_mv = 2048,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.info = &max1238_info,
+		.channels = max1038_channels,
+		.num_channels = ARRAY_SIZE(max1038_channels),
+	},
+	[max1136] = {
+		.bits = 10,
+		.int_vref_mv = 4096,
+		.mode_list = max1236_mode_list,
+		.num_modes = ARRAY_SIZE(max1236_mode_list),
+		.default_mode = s0to3,
+		.info = &max1238_info,
+		.channels = max1136_channels,
+		.num_channels = ARRAY_SIZE(max1136_channels),
+	},
+	[max1137] = {
+		.bits = 10,
+		.int_vref_mv = 2048,
+		.mode_list = max1236_mode_list,
+		.num_modes = ARRAY_SIZE(max1236_mode_list),
+		.default_mode = s0to3,
+		.info = &max1238_info,
+		.channels = max1136_channels,
+		.num_channels = ARRAY_SIZE(max1136_channels),
+	},
+	[max1138] = {
+		.bits = 10,
+		.int_vref_mv = 4096,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.info = &max1238_info,
+		.channels = max1138_channels,
+		.num_channels = ARRAY_SIZE(max1138_channels),
+	},
+	[max1139] = {
+		.bits = 10,
+		.int_vref_mv = 2048,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.info = &max1238_info,
+		.channels = max1138_channels,
+		.num_channels = ARRAY_SIZE(max1138_channels),
+	},
+	[max1236] = {
+		.bits = 12,
+		.int_vref_mv = 4096,
+		.mode_list = max1236_mode_list,
+		.num_modes = ARRAY_SIZE(max1236_mode_list),
+		.default_mode = s0to3,
+		.info = &max1238_info,
+		.channels = max1236_channels,
+		.num_channels = ARRAY_SIZE(max1236_channels),
+	},
+	[max1237] = {
+		.bits = 12,
+		.int_vref_mv = 2048,
+		.mode_list = max1236_mode_list,
+		.num_modes = ARRAY_SIZE(max1236_mode_list),
+		.default_mode = s0to3,
+		.info = &max1238_info,
+		.channels = max1236_channels,
+		.num_channels = ARRAY_SIZE(max1236_channels),
+	},
+	[max1238] = {
+		.bits = 12,
+		.int_vref_mv = 4096,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.info = &max1238_info,
+		.channels = max1238_channels,
+		.num_channels = ARRAY_SIZE(max1238_channels),
+	},
+	[max1239] = {
+		.bits = 12,
+		.int_vref_mv = 2048,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.info = &max1238_info,
+		.channels = max1238_channels,
+		.num_channels = ARRAY_SIZE(max1238_channels),
+	},
+	[max11600] = {
+		.bits = 8,
+		.int_vref_mv = 4096,
+		.mode_list = max11607_mode_list,
+		.num_modes = ARRAY_SIZE(max11607_mode_list),
+		.default_mode = s0to3,
+		.info = &max1238_info,
+		.channels = max1036_channels,
+		.num_channels = ARRAY_SIZE(max1036_channels),
+	},
+	[max11601] = {
+		.bits = 8,
+		.int_vref_mv = 2048,
+		.mode_list = max11607_mode_list,
+		.num_modes = ARRAY_SIZE(max11607_mode_list),
+		.default_mode = s0to3,
+		.info = &max1238_info,
+		.channels = max1036_channels,
+		.num_channels = ARRAY_SIZE(max1036_channels),
+	},
+	[max11602] = {
+		.bits = 8,
+		.int_vref_mv = 4096,
+		.mode_list = max11608_mode_list,
+		.num_modes = ARRAY_SIZE(max11608_mode_list),
+		.default_mode = s0to7,
+		.info = &max1238_info,
+		.channels = max11602_channels,
+		.num_channels = ARRAY_SIZE(max11602_channels),
+	},
+	[max11603] = {
+		.bits = 8,
+		.int_vref_mv = 2048,
+		.mode_list = max11608_mode_list,
+		.num_modes = ARRAY_SIZE(max11608_mode_list),
+		.default_mode = s0to7,
+		.info = &max1238_info,
+		.channels = max11602_channels,
+		.num_channels = ARRAY_SIZE(max11602_channels),
+	},
+	[max11604] = {
+		.bits = 8,
+		.int_vref_mv = 4098,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.info = &max1238_info,
+		.channels = max1238_channels,
+		.num_channels = ARRAY_SIZE(max1238_channels),
+	},
+	[max11605] = {
+		.bits = 8,
+		.int_vref_mv = 2048,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.info = &max1238_info,
+		.channels = max1238_channels,
+		.num_channels = ARRAY_SIZE(max1238_channels),
+	},
+	[max11606] = {
+		.bits = 10,
+		.int_vref_mv = 4096,
+		.mode_list = max11607_mode_list,
+		.num_modes = ARRAY_SIZE(max11607_mode_list),
+		.default_mode = s0to3,
+		.info = &max1238_info,
+		.channels = max1136_channels,
+		.num_channels = ARRAY_SIZE(max1136_channels),
+	},
+	[max11607] = {
+		.bits = 10,
+		.int_vref_mv = 2048,
+		.mode_list = max11607_mode_list,
+		.num_modes = ARRAY_SIZE(max11607_mode_list),
+		.default_mode = s0to3,
+		.info = &max1238_info,
+		.channels = max1136_channels,
+		.num_channels = ARRAY_SIZE(max1136_channels),
+	},
+	[max11608] = {
+		.bits = 10,
+		.int_vref_mv = 4096,
+		.mode_list = max11608_mode_list,
+		.num_modes = ARRAY_SIZE(max11608_mode_list),
+		.default_mode = s0to7,
+		.info = &max1238_info,
+		.channels = max11608_channels,
+		.num_channels = ARRAY_SIZE(max11608_channels),
+	},
+	[max11609] = {
+		.bits = 10,
+		.int_vref_mv = 2048,
+		.mode_list = max11608_mode_list,
+		.num_modes = ARRAY_SIZE(max11608_mode_list),
+		.default_mode = s0to7,
+		.info = &max1238_info,
+		.channels = max11608_channels,
+		.num_channels = ARRAY_SIZE(max11608_channels),
+	},
+	[max11610] = {
+		.bits = 10,
+		.int_vref_mv = 4098,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.info = &max1238_info,
+		.channels = max1238_channels,
+		.num_channels = ARRAY_SIZE(max1238_channels),
+	},
+	[max11611] = {
+		.bits = 10,
+		.int_vref_mv = 2048,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.info = &max1238_info,
+		.channels = max1238_channels,
+		.num_channels = ARRAY_SIZE(max1238_channels),
+	},
+	[max11612] = {
+		.bits = 12,
+		.int_vref_mv = 4096,
+		.mode_list = max11607_mode_list,
+		.num_modes = ARRAY_SIZE(max11607_mode_list),
+		.default_mode = s0to3,
+		.info = &max1238_info,
+		.channels = max1363_channels,
+		.num_channels = ARRAY_SIZE(max1363_channels),
+	},
+	[max11613] = {
+		.bits = 12,
+		.int_vref_mv = 2048,
+		.mode_list = max11607_mode_list,
+		.num_modes = ARRAY_SIZE(max11607_mode_list),
+		.default_mode = s0to3,
+		.info = &max1238_info,
+		.channels = max1363_channels,
+		.num_channels = ARRAY_SIZE(max1363_channels),
+	},
+	[max11614] = {
+		.bits = 12,
+		.int_vref_mv = 4096,
+		.mode_list = max11608_mode_list,
+		.num_modes = ARRAY_SIZE(max11608_mode_list),
+		.default_mode = s0to7,
+		.info = &max1238_info,
+		.channels = max11614_channels,
+		.num_channels = ARRAY_SIZE(max11614_channels),
+	},
+	[max11615] = {
+		.bits = 12,
+		.int_vref_mv = 2048,
+		.mode_list = max11608_mode_list,
+		.num_modes = ARRAY_SIZE(max11608_mode_list),
+		.default_mode = s0to7,
+		.info = &max1238_info,
+		.channels = max11614_channels,
+		.num_channels = ARRAY_SIZE(max11614_channels),
+	},
+	[max11616] = {
+		.bits = 12,
+		.int_vref_mv = 4098,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.info = &max1238_info,
+		.channels = max1238_channels,
+		.num_channels = ARRAY_SIZE(max1238_channels),
+	},
+	[max11617] = {
+		.bits = 12,
+		.int_vref_mv = 2048,
+		.mode_list = max1238_mode_list,
+		.num_modes = ARRAY_SIZE(max1238_mode_list),
+		.default_mode = s0to11,
+		.info = &max1238_info,
+		.channels = max1238_channels,
+		.num_channels = ARRAY_SIZE(max1238_channels),
+	},
+	[max11644] = {
+		.bits = 12,
+		.int_vref_mv = 2048,
+		.mode_list = max11644_mode_list,
+		.num_modes = ARRAY_SIZE(max11644_mode_list),
+		.default_mode = s0to1,
+		.info = &max1238_info,
+		.channels = max11644_channels,
+		.num_channels = ARRAY_SIZE(max11644_channels),
+	},
+	[max11645] = {
+		.bits = 12,
+		.int_vref_mv = 4096,
+		.mode_list = max11644_mode_list,
+		.num_modes = ARRAY_SIZE(max11644_mode_list),
+		.default_mode = s0to1,
+		.info = &max1238_info,
+		.channels = max11644_channels,
+		.num_channels = ARRAY_SIZE(max11644_channels),
+	},
+	[max11646] = {
+		.bits = 10,
+		.int_vref_mv = 2048,
+		.mode_list = max11644_mode_list,
+		.num_modes = ARRAY_SIZE(max11644_mode_list),
+		.default_mode = s0to1,
+		.info = &max1238_info,
+		.channels = max11646_channels,
+		.num_channels = ARRAY_SIZE(max11646_channels),
+	},
+	[max11647] = {
+		.bits = 10,
+		.int_vref_mv = 4096,
+		.mode_list = max11644_mode_list,
+		.num_modes = ARRAY_SIZE(max11644_mode_list),
+		.default_mode = s0to1,
+		.info = &max1238_info,
+		.channels = max11646_channels,
+		.num_channels = ARRAY_SIZE(max11646_channels),
+	},
+};
+
+static int max1363_initial_setup(struct max1363_state *st)
+{
+	st->setupbyte = MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD
+		| MAX1363_SETUP_POWER_UP_INT_REF
+		| MAX1363_SETUP_INT_CLOCK
+		| MAX1363_SETUP_UNIPOLAR
+		| MAX1363_SETUP_NORESET;
+
+	/* Set scan mode writes the config anyway so wait until then*/
+	st->setupbyte = MAX1363_SETUP_BYTE(st->setupbyte);
+	st->current_mode = &max1363_mode_table[st->chip_info->default_mode];
+	st->configbyte = MAX1363_CONFIG_BYTE(st->configbyte);
+
+	return max1363_set_scan_mode(st);
+}
+
+static int __devinit max1363_alloc_scan_masks(struct iio_dev *indio_dev)
+{
+	struct max1363_state *st = iio_priv(indio_dev);
+	unsigned long *masks;
+	int i;
+
+	masks = kzalloc(BITS_TO_LONGS(MAX1363_MAX_CHANNELS)*sizeof(long)*
+			  (st->chip_info->num_modes + 1), GFP_KERNEL);
+	if (!masks)
+		return -ENOMEM;
+
+	for (i = 0; i < st->chip_info->num_modes; i++)
+		bitmap_copy(masks + BITS_TO_LONGS(MAX1363_MAX_CHANNELS)*i,
+			    max1363_mode_table[st->chip_info->mode_list[i]]
+			    .modemask, MAX1363_MAX_CHANNELS);
+
+	indio_dev->available_scan_masks = masks;
+
+	return 0;
+}
+
+
+static irqreturn_t max1363_trigger_handler(int irq, void *p)
+{
+	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;
+	unsigned long numvals = bitmap_weight(st->current_mode->modemask,
+					      MAX1363_MAX_CHANNELS);
+
+	/* Ensure the timestamp is 8 byte aligned */
+	if (st->chip_info->bits != 8)
+		d_size = numvals*2;
+	else
+		d_size = numvals;
+	if (indio_dev->scan_timestamp) {
+		d_size += sizeof(s64);
+		if (d_size % sizeof(s64))
+			d_size += sizeof(s64) - (d_size % sizeof(s64));
+	}
+	/* Monitor mode prevents reading. Whilst not currently implemented
+	 * might as well have this test in here in the meantime as it does
+	 * no harm.
+	 */
+	if (numvals == 0)
+		goto done;
+
+	rxbuf = kmalloc(d_size,	GFP_KERNEL);
+	if (rxbuf == NULL)
+		goto done;
+	if (st->chip_info->bits != 8)
+		b_sent = i2c_master_recv(st->client, rxbuf, numvals*2);
+	else
+		b_sent = i2c_master_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);
+
+done_free:
+	kfree(rxbuf);
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	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_register_buffered_funcs_and_init(struct iio_dev *indio_dev)
+{
+	struct max1363_state *st = iio_priv(indio_dev);
+	int ret = 0;
+
+	indio_dev->buffer = iio_kfifo_allocate(indio_dev);
+	if (!indio_dev->buffer) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	indio_dev->pollfunc = iio_alloc_pollfunc(NULL,
+						 &max1363_trigger_handler,
+						 IRQF_ONESHOT,
+						 indio_dev,
+						 "%s_consumer%d",
+						 st->client->name,
+						 indio_dev->id);
+	if (indio_dev->pollfunc == NULL) {
+		ret = -ENOMEM;
+		goto error_deallocate_sw_rb;
+	}
+	/* Buffer functions - here trigger setup related */
+	indio_dev->setup_ops = &max1363_buffered_setup_ops;
+
+	/* Flag that polled buffering is possible */
+	indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
+
+	return 0;
+
+error_deallocate_sw_rb:
+	iio_kfifo_free(indio_dev->buffer);
+error_ret:
+	return ret;
+}
+
+static void max1363_buffer_cleanup(struct iio_dev *indio_dev)
+{
+	/* ensure that the trigger has been detached */
+	iio_dealloc_pollfunc(indio_dev->pollfunc);
+	iio_kfifo_free(indio_dev->buffer);
+}
+
+static int __devinit max1363_probe(struct i2c_client *client,
+				   const struct i2c_device_id *id)
+{
+	int ret;
+	struct max1363_state *st;
+	struct iio_dev *indio_dev;
+
+	indio_dev = iio_device_alloc(sizeof(struct max1363_state));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_out;
+	}
+
+	ret = iio_map_array_register(indio_dev, client->dev.platform_data);
+	if (ret < 0)
+		goto error_free_device;
+
+	st = iio_priv(indio_dev);
+
+	st->reg = regulator_get(&client->dev, "vcc");
+	if (IS_ERR(st->reg)) {
+		ret = PTR_ERR(st->reg);
+		goto error_unregister_map;
+	}
+
+	ret = regulator_enable(st->reg);
+	if (ret)
+		goto error_put_reg;
+
+	/* this is only used for device removal purposes */
+	i2c_set_clientdata(client, indio_dev);
+
+	st->chip_info = &max1363_chip_info_tbl[id->driver_data];
+	st->client = client;
+
+	ret = max1363_alloc_scan_masks(indio_dev);
+	if (ret)
+		goto error_disable_reg;
+
+	/* Estabilish that the iio_dev is a child of the i2c device */
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->name = id->name;
+	indio_dev->channels = st->chip_info->channels;
+	indio_dev->num_channels = st->chip_info->num_channels;
+	indio_dev->info = st->chip_info->info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = st->chip_info->channels;
+	indio_dev->num_channels = st->chip_info->num_channels;
+	ret = max1363_initial_setup(st);
+	if (ret < 0)
+		goto error_free_available_scan_masks;
+
+	ret = max1363_register_buffered_funcs_and_init(indio_dev);
+	if (ret)
+		goto error_free_available_scan_masks;
+
+	ret = iio_buffer_register(indio_dev,
+				  st->chip_info->channels,
+				  st->chip_info->num_channels);
+	if (ret)
+		goto error_cleanup_buffer;
+
+	if (client->irq) {
+		ret = request_threaded_irq(st->client->irq,
+					   NULL,
+					   &max1363_event_handler,
+					   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+					   "max1363_event",
+					   indio_dev);
+
+		if (ret)
+			goto error_uninit_buffer;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0)
+		goto error_free_irq;
+
+	return 0;
+error_free_irq:
+	free_irq(st->client->irq, indio_dev);
+error_uninit_buffer:
+	iio_buffer_unregister(indio_dev);
+error_cleanup_buffer:
+	max1363_buffer_cleanup(indio_dev);
+error_free_available_scan_masks:
+	kfree(indio_dev->available_scan_masks);
+error_unregister_map:
+	iio_map_array_unregister(indio_dev, client->dev.platform_data);
+error_disable_reg:
+	regulator_disable(st->reg);
+error_put_reg:
+	regulator_put(st->reg);
+error_free_device:
+	iio_device_free(indio_dev);
+error_out:
+	return ret;
+}
+
+static int __devexit max1363_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct max1363_state *st = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	if (client->irq)
+		free_irq(st->client->irq, indio_dev);
+	iio_buffer_unregister(indio_dev);
+	max1363_buffer_cleanup(indio_dev);
+	kfree(indio_dev->available_scan_masks);
+	if (!IS_ERR(st->reg)) {
+		regulator_disable(st->reg);
+		regulator_put(st->reg);
+	}
+	iio_map_array_unregister(indio_dev, client->dev.platform_data);
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+static const struct i2c_device_id max1363_id[] = {
+	{ "max1361", max1361 },
+	{ "max1362", max1362 },
+	{ "max1363", max1363 },
+	{ "max1364", max1364 },
+	{ "max1036", max1036 },
+	{ "max1037", max1037 },
+	{ "max1038", max1038 },
+	{ "max1039", max1039 },
+	{ "max1136", max1136 },
+	{ "max1137", max1137 },
+	{ "max1138", max1138 },
+	{ "max1139", max1139 },
+	{ "max1236", max1236 },
+	{ "max1237", max1237 },
+	{ "max1238", max1238 },
+	{ "max1239", max1239 },
+	{ "max11600", max11600 },
+	{ "max11601", max11601 },
+	{ "max11602", max11602 },
+	{ "max11603", max11603 },
+	{ "max11604", max11604 },
+	{ "max11605", max11605 },
+	{ "max11606", max11606 },
+	{ "max11607", max11607 },
+	{ "max11608", max11608 },
+	{ "max11609", max11609 },
+	{ "max11610", max11610 },
+	{ "max11611", max11611 },
+	{ "max11612", max11612 },
+	{ "max11613", max11613 },
+	{ "max11614", max11614 },
+	{ "max11615", max11615 },
+	{ "max11616", max11616 },
+	{ "max11617", max11617 },
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, max1363_id);
+
+static struct i2c_driver max1363_driver = {
+	.driver = {
+		.name = "max1363",
+	},
+	.probe = max1363_probe,
+	.remove = __devexit_p(max1363_remove),
+	.id_table = max1363_id,
+};
+module_i2c_driver(max1363_driver);
+
+MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
+MODULE_DESCRIPTION("Maxim 1363 ADC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
new file mode 100644
index 0000000..02a43c8
--- /dev/null
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -0,0 +1,260 @@
+/*
+ * TI ADC MFD driver
+ *
+ * Copyright (C) 2012 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.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/iio/iio.h>
+
+#include <linux/mfd/ti_am335x_tscadc.h>
+#include <linux/platform_data/ti_am335x_adc.h>
+
+struct tiadc_device {
+	struct ti_tscadc_dev *mfd_tscadc;
+	int channels;
+};
+
+static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
+{
+	return readl(adc->mfd_tscadc->tscadc_base + reg);
+}
+
+static void tiadc_writel(struct tiadc_device *adc, unsigned int reg,
+					unsigned int val)
+{
+	writel(val, adc->mfd_tscadc->tscadc_base + reg);
+}
+
+static void tiadc_step_config(struct tiadc_device *adc_dev)
+{
+	unsigned int stepconfig;
+	int i, channels = 0, steps;
+
+	/*
+	 * There are 16 configurable steps and 8 analog input
+	 * lines available which are shared between Touchscreen and ADC.
+	 *
+	 * Steps backwards i.e. from 16 towards 0 are used by ADC
+	 * depending on number of input lines needed.
+	 * Channel would represent which analog input
+	 * needs to be given to ADC to digitalize data.
+	 */
+
+	steps = TOTAL_STEPS - adc_dev->channels;
+	channels = TOTAL_CHANNELS - adc_dev->channels;
+
+	stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
+
+	for (i = (steps + 1); i <= TOTAL_STEPS; i++) {
+		tiadc_writel(adc_dev, REG_STEPCONFIG(i),
+				stepconfig | STEPCONFIG_INP(channels));
+		tiadc_writel(adc_dev, REG_STEPDELAY(i),
+				STEPCONFIG_OPENDLY);
+		channels++;
+	}
+	tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
+}
+
+static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
+{
+	struct iio_chan_spec *chan_array;
+	int i;
+
+	indio_dev->num_channels = channels;
+	chan_array = kcalloc(indio_dev->num_channels,
+			sizeof(struct iio_chan_spec), GFP_KERNEL);
+
+	if (chan_array == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < (indio_dev->num_channels); i++) {
+		struct iio_chan_spec *chan = chan_array + i;
+		chan->type = IIO_VOLTAGE;
+		chan->indexed = 1;
+		chan->channel = i;
+		chan->info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT;
+	}
+
+	indio_dev->channels = chan_array;
+
+	return indio_dev->num_channels;
+}
+
+static void tiadc_channels_remove(struct iio_dev *indio_dev)
+{
+	kfree(indio_dev->channels);
+}
+
+static int tiadc_read_raw(struct iio_dev *indio_dev,
+		struct iio_chan_spec const *chan,
+		int *val, int *val2, long mask)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int i;
+	unsigned int fifo1count, readx1;
+
+	/*
+	 * When the sub-system is first enabled,
+	 * the sequencer will always start with the
+	 * lowest step (1) and continue until step (16).
+	 * For ex: If we have enabled 4 ADC channels and
+	 * currently use only 1 out of them, the
+	 * sequencer still configures all the 4 steps,
+	 * leading to 3 unwanted data.
+	 * Hence we need to flush out this data.
+	 */
+
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (i = 0; i < fifo1count; i++) {
+		readx1 = tiadc_readl(adc_dev, REG_FIFO1);
+		if (i == chan->channel)
+			*val = readx1 & 0xfff;
+	}
+	tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
+
+	return IIO_VAL_INT;
+}
+
+static const struct iio_info tiadc_info = {
+	.read_raw = &tiadc_read_raw,
+};
+
+static int __devinit tiadc_probe(struct platform_device *pdev)
+{
+	struct iio_dev		*indio_dev;
+	struct tiadc_device	*adc_dev;
+	struct ti_tscadc_dev	*tscadc_dev = pdev->dev.platform_data;
+	struct mfd_tscadc_board	*pdata;
+	int			err;
+
+	pdata = tscadc_dev->dev->platform_data;
+	if (!pdata || !pdata->adc_init) {
+		dev_err(&pdev->dev, "Could not find platform data\n");
+		return -EINVAL;
+	}
+
+	indio_dev = iio_device_alloc(sizeof(struct tiadc_device));
+	if (indio_dev == NULL) {
+		dev_err(&pdev->dev, "failed to allocate iio device\n");
+		err = -ENOMEM;
+		goto err_ret;
+	}
+	adc_dev = iio_priv(indio_dev);
+
+	adc_dev->mfd_tscadc = tscadc_dev;
+	adc_dev->channels = pdata->adc_init->adc_channels;
+
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->name = dev_name(&pdev->dev);
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->info = &tiadc_info;
+
+	tiadc_step_config(adc_dev);
+
+	err = tiadc_channel_init(indio_dev, adc_dev->channels);
+	if (err < 0)
+		goto err_free_device;
+
+	err = iio_device_register(indio_dev);
+	if (err)
+		goto err_free_channels;
+
+	platform_set_drvdata(pdev, indio_dev);
+
+	return 0;
+
+err_free_channels:
+	tiadc_channels_remove(indio_dev);
+err_free_device:
+	iio_device_free(indio_dev);
+err_ret:
+	return err;
+}
+
+static int __devexit tiadc_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+	iio_device_unregister(indio_dev);
+	tiadc_channels_remove(indio_dev);
+
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int tiadc_suspend(struct device *dev)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
+	unsigned int idle;
+
+	if (!device_may_wakeup(tscadc_dev->dev)) {
+		idle = tiadc_readl(adc_dev, REG_CTRL);
+		idle &= ~(CNTRLREG_TSCSSENB);
+		tiadc_writel(adc_dev, REG_CTRL, (idle |
+				CNTRLREG_POWERDOWN));
+	}
+
+	return 0;
+}
+
+static int tiadc_resume(struct device *dev)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	unsigned int restore;
+
+	/* Make sure ADC is powered up */
+	restore = tiadc_readl(adc_dev, REG_CTRL);
+	restore &= ~(CNTRLREG_POWERDOWN);
+	tiadc_writel(adc_dev, REG_CTRL, restore);
+
+	tiadc_step_config(adc_dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops tiadc_pm_ops = {
+	.suspend = tiadc_suspend,
+	.resume = tiadc_resume,
+};
+#define TIADC_PM_OPS (&tiadc_pm_ops)
+#else
+#define TIADC_PM_OPS NULL
+#endif
+
+static struct platform_driver tiadc_driver = {
+	.driver = {
+		.name   = "tiadc",
+		.owner	= THIS_MODULE,
+		.pm	= TIADC_PM_OPS,
+	},
+	.probe	= tiadc_probe,
+	.remove	= __devexit_p(tiadc_remove),
+};
+
+module_platform_driver(tiadc_driver);
+
+MODULE_DESCRIPTION("TI ADC controller driver");
+MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/adc/viperboard_adc.c b/drivers/iio/adc/viperboard_adc.c
new file mode 100644
index 0000000..10136a8
--- /dev/null
+++ b/drivers/iio/adc/viperboard_adc.c
@@ -0,0 +1,181 @@
+/*
+ *  Nano River Technologies viperboard IIO ADC driver
+ *
+ *  (C) 2012 by Lemonage GmbH
+ *  Author: Lars Poeschel <poeschel@lemonage.de>
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#include <linux/usb.h>
+#include <linux/iio/iio.h>
+
+#include <linux/mfd/viperboard.h>
+
+#define VPRBRD_ADC_CMD_GET		0x00
+
+struct vprbrd_adc_msg {
+	u8 cmd;
+	u8 chan;
+	u8 val;
+} __packed;
+
+struct vprbrd_adc {
+	struct vprbrd *vb;
+};
+
+#define VPRBRD_ADC_CHANNEL(_index) {			\
+	.type = IIO_VOLTAGE,				\
+	.indexed = 1,					\
+	.channel = _index,				\
+	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,	\
+	.scan_index = _index,				\
+	.scan_type = {					\
+		.sign = 'u',				\
+		.realbits = 8,				\
+		.storagebits = 8,			\
+	},						\
+}
+
+static struct iio_chan_spec const vprbrd_adc_iio_channels[] = {
+	VPRBRD_ADC_CHANNEL(0),
+	VPRBRD_ADC_CHANNEL(1),
+	VPRBRD_ADC_CHANNEL(2),
+	VPRBRD_ADC_CHANNEL(3),
+};
+
+static int vprbrd_iio_read_raw(struct iio_dev *iio_dev,
+				struct iio_chan_spec const *chan,
+				int *val,
+				int *val2,
+				long info)
+{
+	int ret, error = 0;
+	struct vprbrd_adc *adc = iio_priv(iio_dev);
+	struct vprbrd *vb = adc->vb;
+	struct vprbrd_adc_msg *admsg = (struct vprbrd_adc_msg *)vb->buf;
+
+	switch (info) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&vb->lock);
+
+		admsg->cmd = VPRBRD_ADC_CMD_GET;
+		admsg->chan = chan->scan_index;
+		admsg->val = 0x00;
+
+		ret = usb_control_msg(vb->usb_dev,
+			usb_sndctrlpipe(vb->usb_dev, 0), VPRBRD_USB_REQUEST_ADC,
+			VPRBRD_USB_TYPE_OUT, 0x0000, 0x0000, admsg,
+			sizeof(struct vprbrd_adc_msg), VPRBRD_USB_TIMEOUT_MS);
+		if (ret != sizeof(struct vprbrd_adc_msg)) {
+			dev_err(&iio_dev->dev, "usb send error on adc read\n");
+			error = -EREMOTEIO;
+		}
+
+		ret = usb_control_msg(vb->usb_dev,
+			usb_rcvctrlpipe(vb->usb_dev, 0), VPRBRD_USB_REQUEST_ADC,
+			VPRBRD_USB_TYPE_IN, 0x0000, 0x0000, admsg,
+			sizeof(struct vprbrd_adc_msg), VPRBRD_USB_TIMEOUT_MS);
+
+		*val = admsg->val;
+
+		mutex_unlock(&vb->lock);
+
+		if (ret != sizeof(struct vprbrd_adc_msg)) {
+			dev_err(&iio_dev->dev, "usb recv error on adc read\n");
+			error = -EREMOTEIO;
+		}
+
+		if (error)
+			goto error;
+
+		return IIO_VAL_INT;
+	default:
+		error = -EINVAL;
+		break;
+	}
+error:
+	return error;
+}
+
+static const struct iio_info vprbrd_adc_iio_info = {
+	.read_raw = &vprbrd_iio_read_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int __devinit vprbrd_adc_probe(struct platform_device *pdev)
+{
+	struct vprbrd *vb = dev_get_drvdata(pdev->dev.parent);
+	struct vprbrd_adc *adc;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	/* registering iio */
+	indio_dev = iio_device_alloc(sizeof(*adc));
+	if (!indio_dev) {
+		dev_err(&pdev->dev, "failed allocating iio device\n");
+		return -ENOMEM;
+	}
+
+	adc = iio_priv(indio_dev);
+	adc->vb = vb;
+	indio_dev->name = "viperboard adc";
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->info = &vprbrd_adc_iio_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = vprbrd_adc_iio_channels;
+	indio_dev->num_channels = ARRAY_SIZE(vprbrd_adc_iio_channels);
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "could not register iio (adc)");
+		goto error;
+	}
+
+	platform_set_drvdata(pdev, indio_dev);
+
+	return 0;
+
+error:
+	iio_device_free(indio_dev);
+	return ret;
+}
+
+static int __devexit vprbrd_adc_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+	iio_device_unregister(indio_dev);
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+static struct platform_driver vprbrd_adc_driver = {
+	.driver = {
+		.name	= "viperboard-adc",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= vprbrd_adc_probe,
+	.remove		= __devexit_p(vprbrd_adc_remove),
+};
+
+module_platform_driver(vprbrd_adc_driver);
+
+MODULE_AUTHOR("Lars Poeschel <poeschel@lemonage.de>");
+MODULE_DESCRIPTION("IIO ADC driver for Nano River Techs Viperboard");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:viperboard-adc");
diff --git a/drivers/iio/buffer_cb.c b/drivers/iio/buffer_cb.c
new file mode 100644
index 0000000..4d40e24
--- /dev/null
+++ b/drivers/iio/buffer_cb.c
@@ -0,0 +1,113 @@
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/consumer.h>
+
+struct iio_cb_buffer {
+	struct iio_buffer buffer;
+	int (*cb)(u8 *data, void *private);
+	void *private;
+	struct iio_channel *channels;
+};
+
+static int iio_buffer_cb_store_to(struct iio_buffer *buffer, u8 *data)
+{
+	struct iio_cb_buffer *cb_buff = container_of(buffer,
+						     struct iio_cb_buffer,
+						     buffer);
+
+	return cb_buff->cb(data, cb_buff->private);
+}
+
+static struct iio_buffer_access_funcs iio_cb_access = {
+	.store_to = &iio_buffer_cb_store_to,
+};
+
+struct iio_cb_buffer *iio_channel_get_all_cb(const char *name,
+					     int (*cb)(u8 *data,
+						       void *private),
+					     void *private)
+{
+	int ret;
+	struct iio_cb_buffer *cb_buff;
+	struct iio_dev *indio_dev;
+	struct iio_channel *chan;
+
+	cb_buff = kzalloc(sizeof(*cb_buff), GFP_KERNEL);
+	if (cb_buff == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+
+	cb_buff->private = private;
+	cb_buff->cb = cb;
+	cb_buff->buffer.access = &iio_cb_access;
+	INIT_LIST_HEAD(&cb_buff->buffer.demux_list);
+
+	cb_buff->channels = iio_channel_get_all(name);
+	if (IS_ERR(cb_buff->channels)) {
+		ret = PTR_ERR(cb_buff->channels);
+		goto error_free_cb_buff;
+	}
+
+	indio_dev = cb_buff->channels[0].indio_dev;
+	cb_buff->buffer.scan_mask
+		= kcalloc(BITS_TO_LONGS(indio_dev->masklength), sizeof(long),
+			  GFP_KERNEL);
+	if (cb_buff->buffer.scan_mask == NULL) {
+		ret = -ENOMEM;
+		goto error_release_channels;
+	}
+	chan = &cb_buff->channels[0];
+	while (chan->indio_dev) {
+		if (chan->indio_dev != indio_dev) {
+			ret = -EINVAL;
+			goto error_release_channels;
+		}
+		set_bit(chan->channel->scan_index,
+			cb_buff->buffer.scan_mask);
+		chan++;
+	}
+
+	return cb_buff;
+
+error_release_channels:
+	iio_channel_release_all(cb_buff->channels);
+error_free_cb_buff:
+	kfree(cb_buff);
+error_ret:
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(iio_channel_get_all_cb);
+
+int iio_channel_start_all_cb(struct iio_cb_buffer *cb_buff)
+{
+	return iio_update_buffers(cb_buff->channels[0].indio_dev,
+				  &cb_buff->buffer,
+				  NULL);
+}
+EXPORT_SYMBOL_GPL(iio_channel_start_all_cb);
+
+void iio_channel_stop_all_cb(struct iio_cb_buffer *cb_buff)
+{
+	iio_update_buffers(cb_buff->channels[0].indio_dev,
+			   NULL,
+			   &cb_buff->buffer);
+}
+EXPORT_SYMBOL_GPL(iio_channel_stop_all_cb);
+
+void iio_channel_release_all_cb(struct iio_cb_buffer *cb_buff)
+{
+	iio_channel_release_all(cb_buff->channels);
+	kfree(cb_buff);
+}
+EXPORT_SYMBOL_GPL(iio_channel_release_all_cb);
+
+struct iio_channel
+*iio_channel_cb_get_channels(const struct iio_cb_buffer *cb_buffer)
+{
+	return cb_buffer->channels;
+}
+EXPORT_SYMBOL_GPL(iio_channel_cb_get_channels);
diff --git a/drivers/iio/common/hid-sensors/Kconfig b/drivers/iio/common/hid-sensors/Kconfig
index 8e63d81..ae10778 100644
--- a/drivers/iio/common/hid-sensors/Kconfig
+++ b/drivers/iio/common/hid-sensors/Kconfig
@@ -15,7 +15,7 @@ config HID_SENSOR_IIO_COMMON
 	  attributes.
 
 config HID_SENSOR_ENUM_BASE_QUIRKS
-	tristate "ENUM base quirks for HID Sensor IIO drivers"
+	bool "ENUM base quirks for HID Sensor IIO drivers"
 	depends on HID_SENSOR_IIO_COMMON
 	help
 	  Say yes here to build support for sensor hub FW using
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
index d4b790d..d60198a 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -36,10 +36,8 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
 	int state_val;
 
 	state_val = state ? 1 : 0;
-#if (defined CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS) || \
-	(defined CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS_MODULE)
-	++state_val;
-#endif
+	if (IS_ENABLED(CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS))
+		++state_val;
 	st->data_ready = state;
 	sensor_hub_set_feature(st->hsdev, st->power_state.report_id,
 					st->power_state.index,
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index b1c0ee5..f4a6f08 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -67,6 +67,16 @@ config AD5446
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad5446.
 
+config AD5449
+	tristate "Analog Device AD5449 and similar DACs driver"
+	depends on SPI_MASTER
+	help
+	  Say yes here to build support for Analog Devices AD5415, AD5426, AD5429,
+	  AD5432, AD5439, AD5443, AD5449 Digital to Analog Converters.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad5449.
+
 config AD5504
 	tristate "Analog Devices AD5504/AD5501 DAC SPI driver"
 	depends on SPI
@@ -122,7 +132,7 @@ config AD5686
 
 config MAX517
 	tristate "Maxim MAX517/518/519 DAC driver"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for the Maxim chips MAX517,
 	  MAX518 and MAX519 (I2C 8-Bit DACs with rail-to-rail outputs).
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index c0d333b..5b528eb 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o
 obj-$(CONFIG_AD5064) += ad5064.o
 obj-$(CONFIG_AD5504) += ad5504.o
 obj-$(CONFIG_AD5446) += ad5446.o
+obj-$(CONFIG_AD5449) += ad5449.o
 obj-$(CONFIG_AD5755) += ad5755.o
 obj-$(CONFIG_AD5764) += ad5764.o
 obj-$(CONFIG_AD5791) += ad5791.o
diff --git a/drivers/iio/dac/ad5449.c b/drivers/iio/dac/ad5449.c
new file mode 100644
index 0000000..0ee6f8e
--- /dev/null
+++ b/drivers/iio/dac/ad5449.c
@@ -0,0 +1,376 @@
+/*
+ * AD5415, AD5426, AD5429, AD5432, AD5439, AD5443, AD5449 Digital to Analog
+ * Converter driver.
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *  Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/regulator/consumer.h>
+#include <asm/unaligned.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#include <linux/platform_data/ad5449.h>
+
+#define AD5449_MAX_CHANNELS		2
+#define AD5449_MAX_VREFS		2
+
+#define AD5449_CMD_NOOP			0x0
+#define AD5449_CMD_LOAD_AND_UPDATE(x)	(0x1 + (x) * 3)
+#define AD5449_CMD_READ(x)		(0x2 + (x) * 3)
+#define AD5449_CMD_LOAD(x)		(0x3 + (x) * 3)
+#define AD5449_CMD_CTRL			13
+
+#define AD5449_CTRL_SDO_OFFSET		10
+#define AD5449_CTRL_DAISY_CHAIN		BIT(9)
+#define AD5449_CTRL_HCLR_TO_MIDSCALE	BIT(8)
+#define AD5449_CTRL_SAMPLE_RISING	BIT(7)
+
+/**
+ * struct ad5449_chip_info - chip specific information
+ * @channels:		Channel specification
+ * @num_channels:	Number of channels
+ * @has_ctrl:		Chip has a control register
+ */
+struct ad5449_chip_info {
+	const struct iio_chan_spec *channels;
+	unsigned int num_channels;
+	bool has_ctrl;
+};
+
+/**
+ * struct ad5449 - driver instance specific data
+ * @spi:		the SPI device for this driver instance
+ * @chip_info:		chip model specific constants, available modes etc
+ * @vref_reg:		vref supply regulators
+ * @has_sdo:		whether the SDO line is connected
+ * @dac_cache:		Cache for the DAC values
+ * @data:		spi transfer buffers
+ */
+struct ad5449 {
+	struct spi_device		*spi;
+	const struct ad5449_chip_info	*chip_info;
+	struct regulator_bulk_data	vref_reg[AD5449_MAX_VREFS];
+
+	bool has_sdo;
+	uint16_t dac_cache[AD5449_MAX_CHANNELS];
+
+	/*
+	 * DMA (thus cache coherency maintenance) requires the
+	 * transfer buffers to live in their own cache lines.
+	 */
+	__be16 data[2] ____cacheline_aligned;
+};
+
+enum ad5449_type {
+	ID_AD5426,
+	ID_AD5429,
+	ID_AD5432,
+	ID_AD5439,
+	ID_AD5443,
+	ID_AD5449,
+};
+
+static int ad5449_write(struct iio_dev *indio_dev, unsigned int addr,
+	unsigned int val)
+{
+	struct ad5449 *st = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&indio_dev->mlock);
+	st->data[0] = cpu_to_be16((addr << 12) | val);
+	ret = spi_write(st->spi, st->data, 2);
+	mutex_unlock(&indio_dev->mlock);
+
+	return ret;
+}
+
+static int ad5449_read(struct iio_dev *indio_dev, unsigned int addr,
+	unsigned int *val)
+{
+	struct ad5449 *st = iio_priv(indio_dev);
+	int ret;
+	struct spi_message msg;
+	struct spi_transfer t[] = {
+		{
+			.tx_buf = &st->data[0],
+			.len = 2,
+			.cs_change = 1,
+		}, {
+			.tx_buf = &st->data[1],
+			.rx_buf = &st->data[1],
+			.len = 2,
+		},
+	};
+
+	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);
+	if (ret < 0)
+		goto out_unlock;
+
+	*val = be16_to_cpu(st->data[1]);
+
+out_unlock:
+	mutex_unlock(&indio_dev->mlock);
+	return ret;
+}
+
+static int ad5449_read_raw(struct iio_dev *indio_dev,
+	struct iio_chan_spec const *chan, int *val, int *val2, long info)
+{
+	struct ad5449 *st = iio_priv(indio_dev);
+	struct regulator_bulk_data *reg;
+	int scale_uv;
+	int ret;
+
+	switch (info) {
+	case IIO_CHAN_INFO_RAW:
+		if (st->has_sdo) {
+			ret = ad5449_read(indio_dev,
+				AD5449_CMD_READ(chan->address), val);
+			if (ret)
+				return ret;
+			*val &= 0xfff;
+		} else {
+			*val = st->dac_cache[chan->address];
+		}
+
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		reg = &st->vref_reg[chan->channel];
+		scale_uv = regulator_get_voltage(reg->consumer);
+		if (scale_uv < 0)
+			return scale_uv;
+
+		*val = scale_uv / 1000;
+		*val2 = chan->scan_type.realbits;
+
+		return IIO_VAL_FRACTIONAL_LOG2;
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static int ad5449_write_raw(struct iio_dev *indio_dev,
+	struct iio_chan_spec const *chan, int val, int val2, long info)
+{
+	struct ad5449 *st = iio_priv(indio_dev);
+	int ret;
+
+	switch (info) {
+	case IIO_CHAN_INFO_RAW:
+		if (val < 0 || val >= (1 << chan->scan_type.realbits))
+			return -EINVAL;
+
+		ret = ad5449_write(indio_dev,
+			AD5449_CMD_LOAD_AND_UPDATE(chan->address),
+			val << chan->scan_type.shift);
+		if (ret == 0)
+			st->dac_cache[chan->address] = val;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static const struct iio_info ad5449_info = {
+	.read_raw = ad5449_read_raw,
+	.write_raw = ad5449_write_raw,
+	.driver_module = THIS_MODULE,
+};
+
+#define AD5449_CHANNEL(chan, bits) {				\
+	.type = IIO_VOLTAGE,					\
+	.indexed = 1,						\
+	.output = 1,						\
+	.channel = (chan),					\
+	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |		\
+		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,		\
+	.address = (chan),					\
+	.scan_type = IIO_ST('u', (bits), 16, 12 - (bits)),	\
+}
+
+#define DECLARE_AD5449_CHANNELS(name, bits) \
+const struct iio_chan_spec name[] = { \
+	AD5449_CHANNEL(0, bits), \
+	AD5449_CHANNEL(1, bits), \
+}
+
+static DECLARE_AD5449_CHANNELS(ad5429_channels, 8);
+static DECLARE_AD5449_CHANNELS(ad5439_channels, 10);
+static DECLARE_AD5449_CHANNELS(ad5449_channels, 12);
+
+static const struct ad5449_chip_info ad5449_chip_info[] = {
+	[ID_AD5426] = {
+		.channels = ad5429_channels,
+		.num_channels = 1,
+		.has_ctrl = false,
+	},
+	[ID_AD5429] = {
+		.channels = ad5429_channels,
+		.num_channels = 2,
+		.has_ctrl = true,
+	},
+	[ID_AD5432] = {
+		.channels = ad5439_channels,
+		.num_channels = 1,
+		.has_ctrl = false,
+	},
+	[ID_AD5439] = {
+		.channels = ad5439_channels,
+		.num_channels = 2,
+		.has_ctrl = true,
+	},
+	[ID_AD5443] = {
+		.channels = ad5449_channels,
+		.num_channels = 1,
+		.has_ctrl = false,
+	},
+	[ID_AD5449] = {
+		.channels = ad5449_channels,
+		.num_channels = 2,
+		.has_ctrl = true,
+	},
+};
+
+static const char *ad5449_vref_name(struct ad5449 *st, int n)
+{
+	if (st->chip_info->num_channels == 1)
+		return "VREF";
+
+	if (n == 0)
+		return "VREFA";
+	else
+		return "VREFB";
+}
+
+static int __devinit ad5449_spi_probe(struct spi_device *spi)
+{
+	struct ad5449_platform_data *pdata = spi->dev.platform_data;
+	const struct spi_device_id *id = spi_get_device_id(spi);
+	struct iio_dev *indio_dev;
+	struct ad5449 *st;
+	unsigned int i;
+	int ret;
+
+	indio_dev = iio_device_alloc(sizeof(*st));
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
+	st = iio_priv(indio_dev);
+	spi_set_drvdata(spi, indio_dev);
+
+	st->chip_info = &ad5449_chip_info[id->driver_data];
+	st->spi = spi;
+
+	for (i = 0; i < st->chip_info->num_channels; ++i)
+		st->vref_reg[i].supply = ad5449_vref_name(st, i);
+
+	ret = regulator_bulk_get(&spi->dev, st->chip_info->num_channels,
+				st->vref_reg);
+	if (ret)
+		goto error_free;
+
+	ret = regulator_bulk_enable(st->chip_info->num_channels, st->vref_reg);
+	if (ret)
+		goto error_free_reg;
+
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = id->name;
+	indio_dev->info = &ad5449_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = st->chip_info->channels;
+	indio_dev->num_channels = st->chip_info->num_channels;
+
+	if (st->chip_info->has_ctrl) {
+		unsigned int ctrl = 0x00;
+		if (pdata) {
+			if (pdata->hardware_clear_to_midscale)
+				ctrl |= AD5449_CTRL_HCLR_TO_MIDSCALE;
+			ctrl |= pdata->sdo_mode << AD5449_CTRL_SDO_OFFSET;
+			st->has_sdo = pdata->sdo_mode != AD5449_SDO_DISABLED;
+		} else {
+			st->has_sdo = true;
+		}
+		ad5449_write(indio_dev, AD5449_CMD_CTRL, ctrl);
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_disable_reg;
+
+	return 0;
+
+error_disable_reg:
+	regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg);
+error_free_reg:
+	regulator_bulk_free(st->chip_info->num_channels, st->vref_reg);
+error_free:
+	iio_device_free(indio_dev);
+
+	return ret;
+}
+
+static int __devexit ad5449_spi_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ad5449 *st = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+
+	regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg);
+	regulator_bulk_free(st->chip_info->num_channels, st->vref_reg);
+
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+static const struct spi_device_id ad5449_spi_ids[] = {
+	{ "ad5415", ID_AD5449 },
+	{ "ad5426", ID_AD5426 },
+	{ "ad5429", ID_AD5429 },
+	{ "ad5432", ID_AD5432 },
+	{ "ad5439", ID_AD5439 },
+	{ "ad5443", ID_AD5443 },
+	{ "ad5449", ID_AD5449 },
+	{}
+};
+MODULE_DEVICE_TABLE(spi, ad5449_spi_ids);
+
+static struct spi_driver ad5449_spi_driver = {
+	.driver = {
+		.name = "ad5449",
+		.owner = THIS_MODULE,
+	},
+	.probe = ad5449_spi_probe,
+	.remove = __devexit_p(ad5449_spi_remove),
+	.id_table = ad5449_spi_ids,
+};
+module_spi_driver(ad5449_spi_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Devices AD5449 and similar DACs");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 6948d75..bc92ff9 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -188,7 +188,7 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
 	if (ret)
 		return ret;
 
-	if (readin == true)
+	if (readin)
 		st->pwr_down_mask |= (0x3 << (chan->channel * 2));
 	else
 		st->pwr_down_mask &= ~(0x3 << (chan->channel * 2));
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
index 21e27e2..48ed148 100644
--- a/drivers/iio/gyro/Kconfig
+++ b/drivers/iio/gyro/Kconfig
@@ -3,6 +3,15 @@
 #
 menu "Digital gyroscope sensors"
 
+config ADIS16136
+	tristate "Analog devices ADIS16136 and similar gyroscopes driver"
+	depends on SPI_MASTER
+	select IIO_ADIS_LIB
+	select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
+	help
+	  Say yes here to build support for the Analog Devices ADIS16133, ADIS16135,
+	  ADIS16136 gyroscope devices.
+
 config HID_SENSOR_GYRO_3D
 	depends on HID_SENSOR_HUB
 	select IIO_BUFFER
diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile
index 8a895d9..702a058 100644
--- a/drivers/iio/gyro/Makefile
+++ b/drivers/iio/gyro/Makefile
@@ -2,4 +2,5 @@
 # Makefile for industrial I/O gyroscope sensor drivers
 #
 
+obj-$(CONFIG_ADIS16136) += adis16136.o
 obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o
diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c
new file mode 100644
index 0000000..05486df
--- /dev/null
+++ b/drivers/iio/gyro/adis16136.c
@@ -0,0 +1,581 @@
+/*
+ * ADIS16133/ADIS16135/ADIS16136 gyroscope driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *   Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
+
+#include <linux/iio/iio.h>
+#include <linux/debugfs.h>
+
+#define ADIS16136_REG_FLASH_CNT		0x00
+#define ADIS16136_REG_TEMP_OUT		0x02
+#define ADIS16136_REG_GYRO_OUT2		0x04
+#define ADIS16136_REG_GYRO_OUT		0x06
+#define ADIS16136_REG_GYRO_OFF2		0x08
+#define ADIS16136_REG_GYRO_OFF		0x0A
+#define ADIS16136_REG_ALM_MAG1		0x10
+#define ADIS16136_REG_ALM_MAG2		0x12
+#define ADIS16136_REG_ALM_SAMPL1	0x14
+#define ADIS16136_REG_ALM_SAMPL2	0x16
+#define ADIS16136_REG_ALM_CTRL		0x18
+#define ADIS16136_REG_GPIO_CTRL		0x1A
+#define ADIS16136_REG_MSC_CTRL		0x1C
+#define ADIS16136_REG_SMPL_PRD		0x1E
+#define ADIS16136_REG_AVG_CNT		0x20
+#define ADIS16136_REG_DEC_RATE		0x22
+#define ADIS16136_REG_SLP_CTRL		0x24
+#define ADIS16136_REG_DIAG_STAT		0x26
+#define ADIS16136_REG_GLOB_CMD		0x28
+#define ADIS16136_REG_LOT1		0x32
+#define ADIS16136_REG_LOT2		0x34
+#define ADIS16136_REG_LOT3		0x36
+#define ADIS16136_REG_PROD_ID		0x38
+#define ADIS16136_REG_SERIAL_NUM	0x3A
+
+#define ADIS16136_DIAG_STAT_FLASH_UPDATE_FAIL	2
+#define ADIS16136_DIAG_STAT_SPI_FAIL		3
+#define ADIS16136_DIAG_STAT_SELF_TEST_FAIL	5
+#define ADIS16136_DIAG_STAT_FLASH_CHKSUM_FAIL	6
+
+#define ADIS16136_MSC_CTRL_MEMORY_TEST BIT(11)
+#define ADIS16136_MSC_CTRL_SELF_TEST BIT(10)
+
+struct adis16136_chip_info {
+	unsigned int precision;
+	unsigned int fullscale;
+};
+
+struct adis16136 {
+	const struct adis16136_chip_info *chip_info;
+
+	struct adis adis;
+};
+
+#ifdef CONFIG_DEBUG_FS
+
+static ssize_t adis16136_show_serial(struct file *file,
+		char __user *userbuf, size_t count, loff_t *ppos)
+{
+	struct adis16136 *adis16136 = file->private_data;
+	uint16_t lot1, lot2, lot3, serial;
+	char buf[20];
+	size_t len;
+	int ret;
+
+	ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SERIAL_NUM,
+		&serial);
+	if (ret < 0)
+		return ret;
+
+	ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT1, &lot1);
+	if (ret < 0)
+		return ret;
+
+	ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT2, &lot2);
+	if (ret < 0)
+		return ret;
+
+	ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT3, &lot3);
+	if (ret < 0)
+		return ret;
+
+	len = snprintf(buf, sizeof(buf), "%.4x%.4x%.4x-%.4x\n", lot1, lot2,
+		lot3, serial);
+
+	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+
+static const struct file_operations adis16136_serial_fops = {
+	.open = simple_open,
+	.read = adis16136_show_serial,
+	.llseek = default_llseek,
+	.owner = THIS_MODULE,
+};
+
+static int adis16136_show_product_id(void *arg, u64 *val)
+{
+	struct adis16136 *adis16136 = arg;
+	u16 prod_id;
+	int ret;
+
+	ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_PROD_ID,
+		&prod_id);
+	if (ret < 0)
+		return ret;
+
+	*val = prod_id;
+
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(adis16136_product_id_fops,
+	adis16136_show_product_id, NULL, "%llu\n");
+
+static int adis16136_show_flash_count(void *arg, u64 *val)
+{
+	struct adis16136 *adis16136 = arg;
+	uint16_t flash_count;
+	int ret;
+
+	ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_FLASH_CNT,
+		&flash_count);
+	if (ret < 0)
+		return ret;
+
+	*val = flash_count;
+
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(adis16136_flash_count_fops,
+	adis16136_show_flash_count, NULL, "%lld\n");
+
+static int adis16136_debugfs_init(struct iio_dev *indio_dev)
+{
+	struct adis16136 *adis16136 = iio_priv(indio_dev);
+
+	debugfs_create_file("serial_number", 0400, indio_dev->debugfs_dentry,
+		adis16136, &adis16136_serial_fops);
+	debugfs_create_file("product_id", 0400, indio_dev->debugfs_dentry,
+		adis16136, &adis16136_product_id_fops);
+	debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry,
+		adis16136, &adis16136_flash_count_fops);
+
+	return 0;
+}
+
+#else
+
+static int adis16136_debugfs_init(struct iio_dev *indio_dev)
+{
+	return 0;
+}
+
+#endif
+
+static int adis16136_set_freq(struct adis16136 *adis16136, unsigned int freq)
+{
+	unsigned int t;
+
+	t = 32768 / freq;
+	if (t < 0xf)
+		t = 0xf;
+	else if (t > 0xffff)
+		t = 0xffff;
+	else
+		t--;
+
+	return adis_write_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, t);
+}
+
+static int adis16136_get_freq(struct adis16136 *adis16136, unsigned int *freq)
+{
+	uint16_t t;
+	int ret;
+
+	ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, &t);
+	if (ret < 0)
+		return ret;
+
+	*freq = 32768 / (t + 1);
+
+	return 0;
+}
+
+static ssize_t adis16136_write_frequency(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t len)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct adis16136 *adis16136 = iio_priv(indio_dev);
+	long val;
+	int ret;
+
+	ret = kstrtol(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	if (val == 0)
+		return -EINVAL;
+
+	ret = adis16136_set_freq(adis16136, val);
+
+	return ret ? ret : len;
+}
+
+static ssize_t adis16136_read_frequency(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct adis16136 *adis16136 = iio_priv(indio_dev);
+	unsigned int freq;
+	int ret;
+
+	ret = adis16136_get_freq(adis16136, &freq);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%d\n", freq);
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+				  adis16136_read_frequency,
+				  adis16136_write_frequency);
+
+static const unsigned adis16136_3db_divisors[] = {
+	[0] = 2, /* Special case */
+	[1] = 6,
+	[2] = 12,
+	[3] = 25,
+	[4] = 50,
+	[5] = 100,
+	[6] = 200,
+	[7] = 200, /* Not a valid setting */
+};
+
+static int adis16136_set_filter(struct iio_dev *indio_dev, int val)
+{
+	struct adis16136 *adis16136 = iio_priv(indio_dev);
+	unsigned int freq;
+	int i, ret;
+
+	ret = adis16136_get_freq(adis16136, &freq);
+	if (ret < 0)
+		return ret;
+
+	for (i = ARRAY_SIZE(adis16136_3db_divisors) - 1; i >= 1; i--) {
+		if (freq / adis16136_3db_divisors[i] >= val)
+			break;
+	}
+
+	return adis_write_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, i);
+}
+
+static int adis16136_get_filter(struct iio_dev *indio_dev, int *val)
+{
+	struct adis16136 *adis16136 = iio_priv(indio_dev);
+	unsigned int freq;
+	uint16_t val16;
+	int ret;
+
+	mutex_lock(&indio_dev->mlock);
+
+	ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, &val16);
+	if (ret < 0)
+		goto err_unlock;
+
+	ret = adis16136_get_freq(adis16136, &freq);
+	if (ret < 0)
+		goto err_unlock;
+
+	*val = freq / adis16136_3db_divisors[val16 & 0x07];
+
+err_unlock:
+	mutex_unlock(&indio_dev->mlock);
+
+	return ret ? ret : IIO_VAL_INT;
+}
+
+static int adis16136_read_raw(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, int *val, int *val2, long info)
+{
+	struct adis16136 *adis16136 = iio_priv(indio_dev);
+	uint32_t val32;
+	int ret;
+
+	switch (info) {
+	case IIO_CHAN_INFO_RAW:
+		return adis_single_conversion(indio_dev, chan, 0, val);
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_ANGL_VEL:
+			*val = adis16136->chip_info->precision;
+			*val2 = (adis16136->chip_info->fullscale << 16);
+			return IIO_VAL_FRACTIONAL;
+		case IIO_TEMP:
+			*val = 10;
+			*val2 = 697000; /* 0.010697 degree Celsius */
+			return IIO_VAL_INT_PLUS_MICRO;
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_CALIBBIAS:
+		ret = adis_read_reg_32(&adis16136->adis,
+			ADIS16136_REG_GYRO_OFF2, &val32);
+		if (ret < 0)
+			return ret;
+
+		*val = sign_extend32(val32, 31);
+
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+		return adis16136_get_filter(indio_dev, val);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int adis16136_write_raw(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, int val, int val2, long info)
+{
+	struct adis16136 *adis16136 = iio_priv(indio_dev);
+
+	switch (info) {
+	case IIO_CHAN_INFO_CALIBBIAS:
+		return adis_write_reg_32(&adis16136->adis,
+			ADIS16136_REG_GYRO_OFF2, val);
+	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+		return adis16136_set_filter(indio_dev, val);
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+enum {
+	ADIS16136_SCAN_GYRO,
+	ADIS16136_SCAN_TEMP,
+};
+
+static const struct iio_chan_spec adis16136_channels[] = {
+	{
+		.type = IIO_ANGL_VEL,
+		.modified = 1,
+		.channel2 = IIO_MOD_X,
+		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+			IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+			IIO_CHAN_INFO_SCALE_SHARED_BIT |
+			IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT,
+		.address = ADIS16136_REG_GYRO_OUT2,
+		.scan_index = ADIS16136_SCAN_GYRO,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 32,
+			.storagebits = 32,
+			.endianness = IIO_BE,
+		},
+	}, {
+		.type = IIO_TEMP,
+		.indexed = 1,
+		.channel = 0,
+		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+			IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.address = ADIS16136_REG_TEMP_OUT,
+		.scan_index = ADIS16136_SCAN_TEMP,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 16,
+			.storagebits = 16,
+			.endianness = IIO_BE,
+		},
+	},
+	IIO_CHAN_SOFT_TIMESTAMP(2),
+};
+
+static struct attribute *adis16136_attributes[] = {
+	&iio_dev_attr_sampling_frequency.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group adis16136_attribute_group = {
+	.attrs = adis16136_attributes,
+};
+
+static const struct iio_info adis16136_info = {
+	.driver_module = THIS_MODULE,
+	.attrs = &adis16136_attribute_group,
+	.read_raw = &adis16136_read_raw,
+	.write_raw = &adis16136_write_raw,
+	.update_scan_mode = adis_update_scan_mode,
+	.debugfs_reg_access = adis_debugfs_reg_access,
+};
+
+static int adis16136_stop_device(struct iio_dev *indio_dev)
+{
+	struct adis16136 *adis16136 = iio_priv(indio_dev);
+	int ret;
+
+	ret = adis_write_reg_16(&adis16136->adis, ADIS16136_REG_SLP_CTRL, 0xff);
+	if (ret)
+		dev_err(&indio_dev->dev,
+			"Could not power down device: %d\n", ret);
+
+	return ret;
+}
+
+static int adis16136_initial_setup(struct iio_dev *indio_dev)
+{
+	struct adis16136 *adis16136 = iio_priv(indio_dev);
+	unsigned int device_id;
+	uint16_t prod_id;
+	int ret;
+
+	ret = adis_initial_startup(&adis16136->adis);
+	if (ret)
+		return ret;
+
+	ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_PROD_ID,
+		&prod_id);
+	if (ret)
+		return ret;
+
+	sscanf(indio_dev->name, "adis%u\n", &device_id);
+
+	if (prod_id != device_id)
+		dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.",
+				device_id, prod_id);
+
+	return 0;
+}
+
+static const char * const adis16136_status_error_msgs[] = {
+	[ADIS16136_DIAG_STAT_FLASH_UPDATE_FAIL] = "Flash update failed",
+	[ADIS16136_DIAG_STAT_SPI_FAIL] = "SPI failure",
+	[ADIS16136_DIAG_STAT_SELF_TEST_FAIL] = "Self test error",
+	[ADIS16136_DIAG_STAT_FLASH_CHKSUM_FAIL] = "Flash checksum error",
+};
+
+static const struct adis_data adis16136_data = {
+	.diag_stat_reg = ADIS16136_REG_DIAG_STAT,
+	.glob_cmd_reg = ADIS16136_REG_GLOB_CMD,
+	.msc_ctrl_reg = ADIS16136_REG_MSC_CTRL,
+
+	.self_test_mask = ADIS16136_MSC_CTRL_SELF_TEST,
+	.startup_delay = 80,
+
+	.read_delay = 10,
+	.write_delay = 10,
+
+	.status_error_msgs = adis16136_status_error_msgs,
+	.status_error_mask = BIT(ADIS16136_DIAG_STAT_FLASH_UPDATE_FAIL) |
+		BIT(ADIS16136_DIAG_STAT_SPI_FAIL) |
+		BIT(ADIS16136_DIAG_STAT_SELF_TEST_FAIL) |
+		BIT(ADIS16136_DIAG_STAT_FLASH_CHKSUM_FAIL),
+};
+
+enum adis16136_id {
+	ID_ADIS16133,
+	ID_ADIS16135,
+	ID_ADIS16136,
+};
+
+static const struct adis16136_chip_info adis16136_chip_info[] = {
+	[ID_ADIS16133] = {
+		.precision = IIO_DEGREE_TO_RAD(1200),
+		.fullscale = 24000,
+	},
+	[ID_ADIS16135] = {
+		.precision = IIO_DEGREE_TO_RAD(300),
+		.fullscale = 24000,
+	},
+	[ID_ADIS16136] = {
+		.precision = IIO_DEGREE_TO_RAD(450),
+		.fullscale = 24623,
+	},
+};
+
+static int adis16136_probe(struct spi_device *spi)
+{
+	const struct spi_device_id *id = spi_get_device_id(spi);
+	struct adis16136 *adis16136;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = iio_device_alloc(sizeof(*adis16136));
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
+	spi_set_drvdata(spi, indio_dev);
+
+	adis16136 = iio_priv(indio_dev);
+
+	adis16136->chip_info = &adis16136_chip_info[id->driver_data];
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->channels = adis16136_channels;
+	indio_dev->num_channels = ARRAY_SIZE(adis16136_channels);
+	indio_dev->info = &adis16136_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = adis_init(&adis16136->adis, indio_dev, spi, &adis16136_data);
+	if (ret)
+		goto error_free_dev;
+
+	ret = adis_setup_buffer_and_trigger(&adis16136->adis, indio_dev, NULL);
+	if (ret)
+		goto error_free_dev;
+
+	ret = adis16136_initial_setup(indio_dev);
+	if (ret)
+		goto error_cleanup_buffer;
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_stop_device;
+
+	adis16136_debugfs_init(indio_dev);
+
+	return 0;
+
+error_stop_device:
+	adis16136_stop_device(indio_dev);
+error_cleanup_buffer:
+	adis_cleanup_buffer_and_trigger(&adis16136->adis, indio_dev);
+error_free_dev:
+	iio_device_free(indio_dev);
+	return ret;
+}
+
+static int adis16136_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct adis16136 *adis16136 = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	adis16136_stop_device(indio_dev);
+
+	adis_cleanup_buffer_and_trigger(&adis16136->adis, indio_dev);
+
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+static const struct spi_device_id adis16136_ids[] = {
+	{ "adis16133", ID_ADIS16133 },
+	{ "adis16135", ID_ADIS16135 },
+	{ "adis16136", ID_ADIS16136 },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, adis16136_ids);
+
+static struct spi_driver adis16136_driver = {
+	.driver = {
+		.name = "adis16136",
+		.owner = THIS_MODULE,
+	},
+	.id_table = adis16136_ids,
+	.probe = adis16136_probe,
+	.remove = adis16136_remove,
+};
+module_spi_driver(adis16136_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Devices ADIS16133/ADIS16135/ADIS16136 gyroscope driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index 4c56ada..4c8b158 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -197,21 +197,8 @@ static const struct iio_info gyro_3d_info = {
 /* Function to push data to buffer */
 static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
 {
-	struct iio_buffer *buffer = indio_dev->buffer;
-	int datum_sz;
-
 	dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
-	if (!buffer) {
-		dev_err(&indio_dev->dev, "Buffer == NULL\n");
-		return;
-	}
-	datum_sz = buffer->access->get_bytes_per_datum(buffer);
-	if (len > datum_sz) {
-		dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len,
-				datum_sz);
-		return;
-	}
-	iio_push_to_buffer(buffer, (u8 *)data);
+	iio_push_to_buffers(indio_dev, (u8 *)data);
 }
 
 /* Callback handler to send event after all samples are received and captured */
@@ -319,10 +306,10 @@ static int __devinit hid_gyro_3d_probe(struct platform_device *pdev)
 		goto error_free_dev;
 	}
 
-	channels = kmemdup(gyro_3d_channels,
-					sizeof(gyro_3d_channels),
-					GFP_KERNEL);
+	channels = kmemdup(gyro_3d_channels, sizeof(gyro_3d_channels),
+			   GFP_KERNEL);
 	if (!channels) {
+		ret = -ENOMEM;
 		dev_err(&pdev->dev, "failed to duplicate channels\n");
 		goto error_free_dev;
 	}
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
new file mode 100644
index 0000000..3d79a40
--- /dev/null
+++ b/drivers/iio/imu/Kconfig
@@ -0,0 +1,27 @@
+#
+# IIO imu drivers configuration
+#
+menu "Inertial measurement units"
+
+config ADIS16480
+	tristate "Analog Devices ADIS16480 and similar IMU driver"
+	depends on SPI
+	select IIO_ADIS_LIB
+	select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
+	help
+	  Say yes here to build support for Analog Devices ADIS16375, ADIS16480,
+	  ADIS16485, ADIS16488 inertial sensors.
+
+endmenu
+
+config IIO_ADIS_LIB
+	tristate
+	help
+	  A set of IO helper functions for the Analog Devices ADIS* device family.
+
+config IIO_ADIS_LIB_BUFFER
+	bool
+	select IIO_TRIGGERED_BUFFER
+	help
+	  A set of buffer helper functions for the Analog Devices ADIS* device
+	  family.
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
new file mode 100644
index 0000000..cfe5763
--- /dev/null
+++ b/drivers/iio/imu/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for Inertial Measurement Units
+#
+
+obj-$(CONFIG_ADIS16480) += adis16480.o
+
+adis_lib-y += adis.o
+adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o
+adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
+obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c
new file mode 100644
index 0000000..911255d
--- /dev/null
+++ b/drivers/iio/imu/adis.c
@@ -0,0 +1,440 @@
+/*
+ * Common library for ADIS16XXX devices
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *   Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <asm/unaligned.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
+
+#define ADIS_MSC_CTRL_DATA_RDY_EN	BIT(2)
+#define ADIS_MSC_CTRL_DATA_RDY_POL_HIGH	BIT(1)
+#define ADIS_MSC_CTRL_DATA_RDY_DIO2	BIT(0)
+#define ADIS_GLOB_CMD_SW_RESET		BIT(7)
+
+int adis_write_reg(struct adis *adis, unsigned int reg,
+	unsigned int value, unsigned int size)
+{
+	unsigned int page = reg / ADIS_PAGE_SIZE;
+	int ret, i;
+	struct spi_message msg;
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = adis->tx,
+			.bits_per_word = 8,
+			.len = 2,
+			.cs_change = 1,
+			.delay_usecs = adis->data->write_delay,
+		}, {
+			.tx_buf = adis->tx + 2,
+			.bits_per_word = 8,
+			.len = 2,
+			.cs_change = 1,
+			.delay_usecs = adis->data->write_delay,
+		}, {
+			.tx_buf = adis->tx + 4,
+			.bits_per_word = 8,
+			.len = 2,
+			.cs_change = 1,
+			.delay_usecs = adis->data->write_delay,
+		}, {
+			.tx_buf = adis->tx + 6,
+			.bits_per_word = 8,
+			.len = 2,
+			.delay_usecs = adis->data->write_delay,
+		}, {
+			.tx_buf = adis->tx + 8,
+			.bits_per_word = 8,
+			.len = 2,
+			.delay_usecs = adis->data->write_delay,
+		},
+	};
+
+	mutex_lock(&adis->txrx_lock);
+
+	spi_message_init(&msg);
+
+	if (adis->current_page != page) {
+		adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID);
+		adis->tx[1] = page;
+		spi_message_add_tail(&xfers[0], &msg);
+	}
+
+	switch (size) {
+	case 4:
+		adis->tx[8] = ADIS_WRITE_REG(reg + 3);
+		adis->tx[9] = (value >> 24) & 0xff;
+		adis->tx[6] = ADIS_WRITE_REG(reg + 2);
+		adis->tx[7] = (value >> 16) & 0xff;
+	case 2:
+		adis->tx[4] = ADIS_WRITE_REG(reg + 1);
+		adis->tx[5] = (value >> 8) & 0xff;
+	case 1:
+		adis->tx[2] = ADIS_WRITE_REG(reg);
+		adis->tx[3] = value & 0xff;
+		break;
+	default:
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	xfers[size].cs_change = 0;
+
+	for (i = 1; i <= size; i++)
+		spi_message_add_tail(&xfers[i], &msg);
+
+	ret = spi_sync(adis->spi, &msg);
+	if (ret) {
+		dev_err(&adis->spi->dev, "Failed to write register 0x%02X: %d\n",
+				reg, ret);
+	} else {
+		adis->current_page = page;
+	}
+
+out_unlock:
+	mutex_unlock(&adis->txrx_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(adis_write_reg);
+
+/**
+ * adis_read_reg() - read 2 bytes from a 16-bit register
+ * @adis: The adis device
+ * @reg: The address of the lower of the two registers
+ * @val: The value read back from the device
+ */
+int adis_read_reg(struct adis *adis, unsigned int reg,
+	unsigned int *val, unsigned int size)
+{
+	unsigned int page = reg / ADIS_PAGE_SIZE;
+	struct spi_message msg;
+	int ret;
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = adis->tx,
+			.bits_per_word = 8,
+			.len = 2,
+			.cs_change = 1,
+			.delay_usecs = adis->data->write_delay,
+		}, {
+			.tx_buf = adis->tx + 2,
+			.bits_per_word = 8,
+			.len = 2,
+			.cs_change = 1,
+			.delay_usecs = adis->data->read_delay,
+		}, {
+			.tx_buf = adis->tx + 4,
+			.rx_buf = adis->rx,
+			.bits_per_word = 8,
+			.len = 2,
+			.cs_change = 1,
+			.delay_usecs = adis->data->read_delay,
+		}, {
+			.rx_buf = adis->rx + 2,
+			.bits_per_word = 8,
+			.len = 2,
+			.delay_usecs = adis->data->read_delay,
+		},
+	};
+
+	mutex_lock(&adis->txrx_lock);
+	spi_message_init(&msg);
+
+	if (adis->current_page != page) {
+		adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID);
+		adis->tx[1] = page;
+		spi_message_add_tail(&xfers[0], &msg);
+	}
+
+	switch (size) {
+	case 4:
+		adis->tx[2] = ADIS_READ_REG(reg + 2);
+		adis->tx[3] = 0;
+		spi_message_add_tail(&xfers[1], &msg);
+	case 2:
+		adis->tx[4] = ADIS_READ_REG(reg);
+		adis->tx[5] = 0;
+		spi_message_add_tail(&xfers[2], &msg);
+		spi_message_add_tail(&xfers[3], &msg);
+		break;
+	default:
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	ret = spi_sync(adis->spi, &msg);
+	if (ret) {
+		dev_err(&adis->spi->dev, "Failed to read register 0x%02X: %d\n",
+				reg, ret);
+		goto out_unlock;
+	} else {
+		adis->current_page = page;
+	}
+
+	switch (size) {
+	case 4:
+		*val = get_unaligned_be32(adis->rx);
+		break;
+	case 2:
+		*val = get_unaligned_be16(adis->rx + 2);
+		break;
+	}
+
+out_unlock:
+	mutex_unlock(&adis->txrx_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(adis_read_reg);
+
+#ifdef CONFIG_DEBUG_FS
+
+int adis_debugfs_reg_access(struct iio_dev *indio_dev,
+	unsigned int reg, unsigned int writeval, unsigned int *readval)
+{
+	struct adis *adis = iio_device_get_drvdata(indio_dev);
+
+	if (readval) {
+		uint16_t val16;
+		int ret;
+
+		ret = adis_read_reg_16(adis, reg, &val16);
+		*readval = val16;
+
+		return ret;
+	} else {
+		return adis_write_reg_16(adis, reg, writeval);
+	}
+}
+EXPORT_SYMBOL(adis_debugfs_reg_access);
+
+#endif
+
+/**
+ * adis_enable_irq() - Enable or disable data ready IRQ
+ * @adis: The adis device
+ * @enable: Whether to enable the IRQ
+ *
+ * Returns 0 on success, negative error code otherwise
+ */
+int adis_enable_irq(struct adis *adis, bool enable)
+{
+	int ret = 0;
+	uint16_t msc;
+
+	if (adis->data->enable_irq)
+		return adis->data->enable_irq(adis, enable);
+
+	ret = adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc);
+	if (ret)
+		goto error_ret;
+
+	msc |= ADIS_MSC_CTRL_DATA_RDY_POL_HIGH;
+	msc &= ~ADIS_MSC_CTRL_DATA_RDY_DIO2;
+	if (enable)
+		msc |= ADIS_MSC_CTRL_DATA_RDY_EN;
+	else
+		msc &= ~ADIS_MSC_CTRL_DATA_RDY_EN;
+
+	ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc);
+
+error_ret:
+	return ret;
+}
+EXPORT_SYMBOL(adis_enable_irq);
+
+/**
+ * adis_check_status() - Check the device for error conditions
+ * @adis: The adis device
+ *
+ * Returns 0 on success, a negative error code otherwise
+ */
+int adis_check_status(struct adis *adis)
+{
+	uint16_t status;
+	int ret;
+	int i;
+
+	ret = adis_read_reg_16(adis, adis->data->diag_stat_reg, &status);
+	if (ret < 0)
+		return ret;
+
+	status &= adis->data->status_error_mask;
+
+	if (status == 0)
+		return 0;
+
+	for (i = 0; i < 16; ++i) {
+		if (status & BIT(i)) {
+			dev_err(&adis->spi->dev, "%s.\n",
+				adis->data->status_error_msgs[i]);
+		}
+	}
+
+	return -EIO;
+}
+EXPORT_SYMBOL_GPL(adis_check_status);
+
+/**
+ * adis_reset() - Reset the device
+ * @adis: The adis device
+ *
+ * Returns 0 on success, a negative error code otherwise
+ */
+int adis_reset(struct adis *adis)
+{
+	int ret;
+
+	ret = adis_write_reg_8(adis, adis->data->glob_cmd_reg,
+			ADIS_GLOB_CMD_SW_RESET);
+	if (ret)
+		dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(adis_reset);
+
+static int adis_self_test(struct adis *adis)
+{
+	int ret;
+
+	ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg,
+			adis->data->self_test_mask);
+	if (ret) {
+		dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n",
+			ret);
+		return ret;
+	}
+
+	msleep(adis->data->startup_delay);
+
+	return adis_check_status(adis);
+}
+
+/**
+ * adis_inital_startup() - Performs device self-test
+ * @adis: The adis device
+ *
+ * Returns 0 if the device is operational, a negative error code otherwise.
+ *
+ * This function should be called early on in the device initialization sequence
+ * to ensure that the device is in a sane and known state and that it is usable.
+ */
+int adis_initial_startup(struct adis *adis)
+{
+	int ret;
+
+	ret = adis_self_test(adis);
+	if (ret) {
+		dev_err(&adis->spi->dev, "Self-test failed, trying reset.\n");
+		adis_reset(adis);
+		msleep(adis->data->startup_delay);
+		ret = adis_self_test(adis);
+		if (ret) {
+			dev_err(&adis->spi->dev, "Second self-test failed, giving up.\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(adis_initial_startup);
+
+/**
+ * adis_single_conversion() - Performs a single sample conversion
+ * @indio_dev: The IIO device
+ * @chan: The IIO channel
+ * @error_mask: Mask for the error bit
+ * @val: Result of the conversion
+ *
+ * Returns IIO_VAL_INT on success, a negative error code otherwise.
+ *
+ * The function performs a single conversion on a given channel and post
+ * processes the value accordingly to the channel spec. If a error_mask is given
+ * the function will check if the mask is set in the returned raw value. If it
+ * is set the function will perform a self-check. If the device does not report
+ * a error bit in the channels raw value set error_mask to 0.
+ */
+int adis_single_conversion(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, unsigned int error_mask, int *val)
+{
+	struct adis *adis = iio_device_get_drvdata(indio_dev);
+	unsigned int uval;
+	int ret;
+
+	mutex_lock(&indio_dev->mlock);
+
+	ret = adis_read_reg(adis, chan->address, &uval,
+			chan->scan_type.storagebits / 8);
+	if (ret)
+		goto err_unlock;
+
+	if (uval & error_mask) {
+		ret = adis_check_status(adis);
+		if (ret)
+			goto err_unlock;
+	}
+
+	if (chan->scan_type.sign == 's')
+		*val = sign_extend32(uval, chan->scan_type.realbits - 1);
+	else
+		*val = uval & ((1 << chan->scan_type.realbits) - 1);
+
+	ret = IIO_VAL_INT;
+err_unlock:
+	mutex_unlock(&indio_dev->mlock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(adis_single_conversion);
+
+/**
+ * adis_init() - Initialize adis device structure
+ * @adis:	The adis device
+ * @indio_dev:	The iio device
+ * @spi:	The spi device
+ * @data:	Chip specific data
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function must be called, before any other adis helper function may be
+ * called.
+ */
+int adis_init(struct adis *adis, struct iio_dev *indio_dev,
+	struct spi_device *spi, const struct adis_data *data)
+{
+	mutex_init(&adis->txrx_lock);
+	adis->spi = spi;
+	adis->data = data;
+	iio_device_set_drvdata(indio_dev, adis);
+
+	if (data->has_paging) {
+		/* Need to set the page before first read/write */
+		adis->current_page = -1;
+	} else {
+		/* Page will always be 0 */
+		adis->current_page = 0;
+	}
+
+	return adis_enable_irq(adis, false);
+}
+EXPORT_SYMBOL_GPL(adis_init);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Common library code for ADIS16XXX devices");
diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c
new file mode 100644
index 0000000..a080b35
--- /dev/null
+++ b/drivers/iio/imu/adis16480.c
@@ -0,0 +1,925 @@
+/*
+ * ADIS16480 and similar IMUs driver
+ *
+ * Copyright 2012 Analog Devices 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/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
+
+#include <linux/iio/iio.h>
+#include <linux/debugfs.h>
+
+#define ADIS16480_PAGE_SIZE 0x80
+
+#define ADIS16480_REG(page, reg) ((page) * ADIS16480_PAGE_SIZE + (reg))
+
+#define ADIS16480_REG_PAGE_ID 0x00 /* Same address on each page */
+#define ADIS16480_REG_SEQ_CNT			ADIS16480_REG(0x00, 0x06)
+#define ADIS16480_REG_SYS_E_FLA			ADIS16480_REG(0x00, 0x08)
+#define ADIS16480_REG_DIAG_STS			ADIS16480_REG(0x00, 0x0A)
+#define ADIS16480_REG_ALM_STS			ADIS16480_REG(0x00, 0x0C)
+#define ADIS16480_REG_TEMP_OUT			ADIS16480_REG(0x00, 0x0E)
+#define ADIS16480_REG_X_GYRO_OUT		ADIS16480_REG(0x00, 0x10)
+#define ADIS16480_REG_Y_GYRO_OUT		ADIS16480_REG(0x00, 0x14)
+#define ADIS16480_REG_Z_GYRO_OUT		ADIS16480_REG(0x00, 0x18)
+#define ADIS16480_REG_X_ACCEL_OUT		ADIS16480_REG(0x00, 0x1C)
+#define ADIS16480_REG_Y_ACCEL_OUT		ADIS16480_REG(0x00, 0x20)
+#define ADIS16480_REG_Z_ACCEL_OUT		ADIS16480_REG(0x00, 0x24)
+#define ADIS16480_REG_X_MAGN_OUT		ADIS16480_REG(0x00, 0x28)
+#define ADIS16480_REG_Y_MAGN_OUT		ADIS16480_REG(0x00, 0x2A)
+#define ADIS16480_REG_Z_MAGN_OUT		ADIS16480_REG(0x00, 0x2C)
+#define ADIS16480_REG_BAROM_OUT			ADIS16480_REG(0x00, 0x2E)
+#define ADIS16480_REG_X_DELTAANG_OUT		ADIS16480_REG(0x00, 0x40)
+#define ADIS16480_REG_Y_DELTAANG_OUT		ADIS16480_REG(0x00, 0x44)
+#define ADIS16480_REG_Z_DELTAANG_OUT		ADIS16480_REG(0x00, 0x48)
+#define ADIS16480_REG_X_DELTAVEL_OUT		ADIS16480_REG(0x00, 0x4C)
+#define ADIS16480_REG_Y_DELTAVEL_OUT		ADIS16480_REG(0x00, 0x50)
+#define ADIS16480_REG_Z_DELTAVEL_OUT		ADIS16480_REG(0x00, 0x54)
+#define ADIS16480_REG_PROD_ID			ADIS16480_REG(0x00, 0x7E)
+
+#define ADIS16480_REG_X_GYRO_SCALE		ADIS16480_REG(0x02, 0x04)
+#define ADIS16480_REG_Y_GYRO_SCALE		ADIS16480_REG(0x02, 0x06)
+#define ADIS16480_REG_Z_GYRO_SCALE		ADIS16480_REG(0x02, 0x08)
+#define ADIS16480_REG_X_ACCEL_SCALE		ADIS16480_REG(0x02, 0x0A)
+#define ADIS16480_REG_Y_ACCEL_SCALE		ADIS16480_REG(0x02, 0x0C)
+#define ADIS16480_REG_Z_ACCEL_SCALE		ADIS16480_REG(0x02, 0x0E)
+#define ADIS16480_REG_X_GYRO_BIAS		ADIS16480_REG(0x02, 0x10)
+#define ADIS16480_REG_Y_GYRO_BIAS		ADIS16480_REG(0x02, 0x14)
+#define ADIS16480_REG_Z_GYRO_BIAS		ADIS16480_REG(0x02, 0x18)
+#define ADIS16480_REG_X_ACCEL_BIAS		ADIS16480_REG(0x02, 0x1C)
+#define ADIS16480_REG_Y_ACCEL_BIAS		ADIS16480_REG(0x02, 0x20)
+#define ADIS16480_REG_Z_ACCEL_BIAS		ADIS16480_REG(0x02, 0x24)
+#define ADIS16480_REG_X_HARD_IRON		ADIS16480_REG(0x02, 0x28)
+#define ADIS16480_REG_Y_HARD_IRON		ADIS16480_REG(0x02, 0x2A)
+#define ADIS16480_REG_Z_HARD_IRON		ADIS16480_REG(0x02, 0x2C)
+#define ADIS16480_REG_BAROM_BIAS		ADIS16480_REG(0x02, 0x40)
+#define ADIS16480_REG_FLASH_CNT			ADIS16480_REG(0x02, 0x7C)
+
+#define ADIS16480_REG_GLOB_CMD			ADIS16480_REG(0x03, 0x02)
+#define ADIS16480_REG_FNCTIO_CTRL		ADIS16480_REG(0x03, 0x06)
+#define ADIS16480_REG_GPIO_CTRL			ADIS16480_REG(0x03, 0x08)
+#define ADIS16480_REG_CONFIG			ADIS16480_REG(0x03, 0x0A)
+#define ADIS16480_REG_DEC_RATE			ADIS16480_REG(0x03, 0x0C)
+#define ADIS16480_REG_SLP_CNT			ADIS16480_REG(0x03, 0x10)
+#define ADIS16480_REG_FILTER_BNK0		ADIS16480_REG(0x03, 0x16)
+#define ADIS16480_REG_FILTER_BNK1		ADIS16480_REG(0x03, 0x18)
+#define ADIS16480_REG_ALM_CNFG0			ADIS16480_REG(0x03, 0x20)
+#define ADIS16480_REG_ALM_CNFG1			ADIS16480_REG(0x03, 0x22)
+#define ADIS16480_REG_ALM_CNFG2			ADIS16480_REG(0x03, 0x24)
+#define ADIS16480_REG_XG_ALM_MAGN		ADIS16480_REG(0x03, 0x28)
+#define ADIS16480_REG_YG_ALM_MAGN		ADIS16480_REG(0x03, 0x2A)
+#define ADIS16480_REG_ZG_ALM_MAGN		ADIS16480_REG(0x03, 0x2C)
+#define ADIS16480_REG_XA_ALM_MAGN		ADIS16480_REG(0x03, 0x2E)
+#define ADIS16480_REG_YA_ALM_MAGN		ADIS16480_REG(0x03, 0x30)
+#define ADIS16480_REG_ZA_ALM_MAGN		ADIS16480_REG(0x03, 0x32)
+#define ADIS16480_REG_XM_ALM_MAGN		ADIS16480_REG(0x03, 0x34)
+#define ADIS16480_REG_YM_ALM_MAGN		ADIS16480_REG(0x03, 0x36)
+#define ADIS16480_REG_ZM_ALM_MAGN		ADIS16480_REG(0x03, 0x38)
+#define ADIS16480_REG_BR_ALM_MAGN		ADIS16480_REG(0x03, 0x3A)
+#define ADIS16480_REG_FIRM_REV			ADIS16480_REG(0x03, 0x78)
+#define ADIS16480_REG_FIRM_DM			ADIS16480_REG(0x03, 0x7A)
+#define ADIS16480_REG_FIRM_Y			ADIS16480_REG(0x03, 0x7C)
+
+#define ADIS16480_REG_SERIAL_NUM		ADIS16480_REG(0x04, 0x20)
+
+/* Each filter coefficent bank spans two pages */
+#define ADIS16480_FIR_COEF(page) (x < 60 ? ADIS16480_REG(page, (x) + 8) : \
+		ADIS16480_REG((page) + 1, (x) - 60 + 8))
+#define ADIS16480_FIR_COEF_A(x)			ADIS16480_FIR_COEF(0x05, (x))
+#define ADIS16480_FIR_COEF_B(x)			ADIS16480_FIR_COEF(0x07, (x))
+#define ADIS16480_FIR_COEF_C(x)			ADIS16480_FIR_COEF(0x09, (x))
+#define ADIS16480_FIR_COEF_D(x)			ADIS16480_FIR_COEF(0x0B, (x))
+
+struct adis16480_chip_info {
+	unsigned int num_channels;
+	const struct iio_chan_spec *channels;
+};
+
+struct adis16480 {
+	const struct adis16480_chip_info *chip_info;
+
+	struct adis adis;
+};
+
+#ifdef CONFIG_DEBUG_FS
+
+static ssize_t adis16480_show_firmware_revision(struct file *file,
+		char __user *userbuf, size_t count, loff_t *ppos)
+{
+	struct adis16480 *adis16480 = file->private_data;
+	char buf[6];
+	size_t len;
+	u16 rev;
+	int ret;
+
+	ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_FIRM_REV, &rev);
+	if (ret < 0)
+		return ret;
+
+	len = snprintf(buf, sizeof(buf), "%x.%x\n", rev >> 8, rev & 0xff);
+
+	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+
+static const struct file_operations adis16480_firmware_revision_fops = {
+	.open = simple_open,
+	.read = adis16480_show_firmware_revision,
+	.llseek = default_llseek,
+	.owner = THIS_MODULE,
+};
+
+static ssize_t adis16480_show_firmware_date(struct file *file,
+		char __user *userbuf, size_t count, loff_t *ppos)
+{
+	struct adis16480 *adis16480 = file->private_data;
+	u16 md, year;
+	char buf[12];
+	size_t len;
+	int ret;
+
+	ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_FIRM_Y, &year);
+	if (ret < 0)
+		return ret;
+
+	ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_FIRM_DM, &md);
+	if (ret < 0)
+		return ret;
+
+	len = snprintf(buf, sizeof(buf), "%.2x-%.2x-%.4x\n",
+			md >> 8, md & 0xff, year);
+
+	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+
+static const struct file_operations adis16480_firmware_date_fops = {
+	.open = simple_open,
+	.read = adis16480_show_firmware_date,
+	.llseek = default_llseek,
+	.owner = THIS_MODULE,
+};
+
+static int adis16480_show_serial_number(void *arg, u64 *val)
+{
+	struct adis16480 *adis16480 = arg;
+	u16 serial;
+	int ret;
+
+	ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_SERIAL_NUM,
+		&serial);
+	if (ret < 0)
+		return ret;
+
+	*val = serial;
+
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(adis16480_serial_number_fops,
+	adis16480_show_serial_number, NULL, "0x%.4llx\n");
+
+static int adis16480_show_product_id(void *arg, u64 *val)
+{
+	struct adis16480 *adis16480 = arg;
+	u16 prod_id;
+	int ret;
+
+	ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_PROD_ID,
+		&prod_id);
+	if (ret < 0)
+		return ret;
+
+	*val = prod_id;
+
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(adis16480_product_id_fops,
+	adis16480_show_product_id, NULL, "%llu\n");
+
+static int adis16480_show_flash_count(void *arg, u64 *val)
+{
+	struct adis16480 *adis16480 = arg;
+	u32 flash_count;
+	int ret;
+
+	ret = adis_read_reg_32(&adis16480->adis, ADIS16480_REG_FLASH_CNT,
+		&flash_count);
+	if (ret < 0)
+		return ret;
+
+	*val = flash_count;
+
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(adis16480_flash_count_fops,
+	adis16480_show_flash_count, NULL, "%lld\n");
+
+static int adis16480_debugfs_init(struct iio_dev *indio_dev)
+{
+	struct adis16480 *adis16480 = iio_priv(indio_dev);
+
+	debugfs_create_file("firmware_revision", 0400,
+		indio_dev->debugfs_dentry, adis16480,
+		&adis16480_firmware_revision_fops);
+	debugfs_create_file("firmware_date", 0400, indio_dev->debugfs_dentry,
+		adis16480, &adis16480_firmware_date_fops);
+	debugfs_create_file("serial_number", 0400, indio_dev->debugfs_dentry,
+		adis16480, &adis16480_serial_number_fops);
+	debugfs_create_file("product_id", 0400, indio_dev->debugfs_dentry,
+		adis16480, &adis16480_product_id_fops);
+	debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry,
+		adis16480, &adis16480_flash_count_fops);
+
+	return 0;
+}
+
+#else
+
+static int adis16480_debugfs_init(struct iio_dev *indio_dev)
+{
+	return 0;
+}
+
+#endif
+
+static int adis16480_set_freq(struct adis16480 *st, unsigned int freq)
+{
+	unsigned int t;
+
+	t = 2460000 / freq;
+	if (t > 2048)
+		t = 2048;
+
+	if (t != 0)
+		t--;
+
+	return adis_write_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, t);
+}
+
+static int adis16480_get_freq(struct adis16480 *st, unsigned int *freq)
+{
+	uint16_t t;
+	int ret;
+
+	ret = adis_read_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, &t);
+	if (ret < 0)
+		return ret;
+
+	*freq = 2460000 / (t + 1);
+
+	return 0;
+}
+
+static ssize_t adis16480_read_frequency(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct adis16480 *st = iio_priv(indio_dev);
+	unsigned int freq;
+	int ret;
+
+	ret = adis16480_get_freq(st, &freq);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%d.%.3d\n", freq / 1000, freq % 1000);
+}
+
+static ssize_t adis16480_write_frequency(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t len)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct adis16480 *st = iio_priv(indio_dev);
+	int freq_int, freq_fract;
+	long val;
+	int ret;
+
+	ret = iio_str_to_fixpoint(buf, 100, &freq_int, &freq_fract);
+	if (ret)
+		return ret;
+
+	val = freq_int * 1000 + freq_fract;
+
+	if (val <= 0)
+		return -EINVAL;
+
+	ret = adis16480_set_freq(st, val);
+
+	return ret ? ret : len;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+			      adis16480_read_frequency,
+			      adis16480_write_frequency);
+
+enum {
+	ADIS16480_SCAN_GYRO_X,
+	ADIS16480_SCAN_GYRO_Y,
+	ADIS16480_SCAN_GYRO_Z,
+	ADIS16480_SCAN_ACCEL_X,
+	ADIS16480_SCAN_ACCEL_Y,
+	ADIS16480_SCAN_ACCEL_Z,
+	ADIS16480_SCAN_MAGN_X,
+	ADIS16480_SCAN_MAGN_Y,
+	ADIS16480_SCAN_MAGN_Z,
+	ADIS16480_SCAN_BARO,
+	ADIS16480_SCAN_TEMP,
+};
+
+static const unsigned int adis16480_calibbias_regs[] = {
+	[ADIS16480_SCAN_GYRO_X] = ADIS16480_REG_X_GYRO_BIAS,
+	[ADIS16480_SCAN_GYRO_Y] = ADIS16480_REG_Y_GYRO_BIAS,
+	[ADIS16480_SCAN_GYRO_Z] = ADIS16480_REG_Z_GYRO_BIAS,
+	[ADIS16480_SCAN_ACCEL_X] = ADIS16480_REG_X_ACCEL_BIAS,
+	[ADIS16480_SCAN_ACCEL_Y] = ADIS16480_REG_Y_ACCEL_BIAS,
+	[ADIS16480_SCAN_ACCEL_Z] = ADIS16480_REG_Z_ACCEL_BIAS,
+	[ADIS16480_SCAN_MAGN_X] = ADIS16480_REG_X_HARD_IRON,
+	[ADIS16480_SCAN_MAGN_Y] = ADIS16480_REG_Y_HARD_IRON,
+	[ADIS16480_SCAN_MAGN_Z] = ADIS16480_REG_Z_HARD_IRON,
+	[ADIS16480_SCAN_BARO] = ADIS16480_REG_BAROM_BIAS,
+};
+
+static const unsigned int adis16480_calibscale_regs[] = {
+	[ADIS16480_SCAN_GYRO_X] = ADIS16480_REG_X_GYRO_SCALE,
+	[ADIS16480_SCAN_GYRO_Y] = ADIS16480_REG_Y_GYRO_SCALE,
+	[ADIS16480_SCAN_GYRO_Z] = ADIS16480_REG_Z_GYRO_SCALE,
+	[ADIS16480_SCAN_ACCEL_X] = ADIS16480_REG_X_ACCEL_SCALE,
+	[ADIS16480_SCAN_ACCEL_Y] = ADIS16480_REG_Y_ACCEL_SCALE,
+	[ADIS16480_SCAN_ACCEL_Z] = ADIS16480_REG_Z_ACCEL_SCALE,
+};
+
+static int adis16480_set_calibbias(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, int bias)
+{
+	unsigned int reg = adis16480_calibbias_regs[chan->scan_index];
+	struct adis16480 *st = iio_priv(indio_dev);
+
+	switch (chan->type) {
+	case IIO_MAGN:
+	case IIO_PRESSURE:
+		if (bias < -0x8000 || bias >= 0x8000)
+			return -EINVAL;
+		return adis_write_reg_16(&st->adis, reg, bias);
+	case IIO_ANGL_VEL:
+	case IIO_ACCEL:
+		return adis_write_reg_32(&st->adis, reg, bias);
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static int adis16480_get_calibbias(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, int *bias)
+{
+	unsigned int reg = adis16480_calibbias_regs[chan->scan_index];
+	struct adis16480 *st = iio_priv(indio_dev);
+	uint16_t val16;
+	uint32_t val32;
+	int ret;
+
+	switch (chan->type) {
+	case IIO_MAGN:
+	case IIO_PRESSURE:
+		ret = adis_read_reg_16(&st->adis, reg, &val16);
+		*bias = sign_extend32(val16, 15);
+		break;
+	case IIO_ANGL_VEL:
+	case IIO_ACCEL:
+		ret = adis_read_reg_32(&st->adis, reg, &val32);
+		*bias = sign_extend32(val32, 31);
+		break;
+	default:
+			ret = -EINVAL;
+	}
+
+	if (ret < 0)
+		return ret;
+
+	return IIO_VAL_INT;
+}
+
+static int adis16480_set_calibscale(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, int scale)
+{
+	unsigned int reg = adis16480_calibscale_regs[chan->scan_index];
+	struct adis16480 *st = iio_priv(indio_dev);
+
+	if (scale < -0x8000 || scale >= 0x8000)
+		return -EINVAL;
+
+	return adis_write_reg_16(&st->adis, reg, scale);
+}
+
+static int adis16480_get_calibscale(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, int *scale)
+{
+	unsigned int reg = adis16480_calibscale_regs[chan->scan_index];
+	struct adis16480 *st = iio_priv(indio_dev);
+	uint16_t val16;
+	int ret;
+
+	ret = adis_read_reg_16(&st->adis, reg, &val16);
+	if (ret < 0)
+		return ret;
+
+	*scale = sign_extend32(val16, 15);
+	return IIO_VAL_INT;
+}
+
+static const unsigned int adis16480_def_filter_freqs[] = {
+	310,
+	55,
+	275,
+	63,
+};
+
+static const unsigned int ad16480_filter_data[][2] = {
+	[ADIS16480_SCAN_GYRO_X]		= { ADIS16480_REG_FILTER_BNK0, 0 },
+	[ADIS16480_SCAN_GYRO_Y]		= { ADIS16480_REG_FILTER_BNK0, 3 },
+	[ADIS16480_SCAN_GYRO_Z]		= { ADIS16480_REG_FILTER_BNK0, 6 },
+	[ADIS16480_SCAN_ACCEL_X]	= { ADIS16480_REG_FILTER_BNK0, 9 },
+	[ADIS16480_SCAN_ACCEL_Y]	= { ADIS16480_REG_FILTER_BNK0, 12 },
+	[ADIS16480_SCAN_ACCEL_Z]	= { ADIS16480_REG_FILTER_BNK1, 0 },
+	[ADIS16480_SCAN_MAGN_X]		= { ADIS16480_REG_FILTER_BNK1, 3 },
+	[ADIS16480_SCAN_MAGN_Y]		= { ADIS16480_REG_FILTER_BNK1, 6 },
+	[ADIS16480_SCAN_MAGN_Z]		= { ADIS16480_REG_FILTER_BNK1, 9 },
+};
+
+static int adis16480_get_filter_freq(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, int *freq)
+{
+	struct adis16480 *st = iio_priv(indio_dev);
+	unsigned int enable_mask, offset, reg;
+	uint16_t val;
+	int ret;
+
+	reg = ad16480_filter_data[chan->scan_index][0];
+	offset = ad16480_filter_data[chan->scan_index][1];
+	enable_mask = BIT(offset + 2);
+
+	ret = adis_read_reg_16(&st->adis, reg, &val);
+	if (ret < 0)
+		return ret;
+
+	if (!(val & enable_mask))
+		*freq = 0;
+	else
+		*freq = adis16480_def_filter_freqs[(val >> offset) & 0x3];
+
+	return IIO_VAL_INT;
+}
+
+static int adis16480_set_filter_freq(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, unsigned int freq)
+{
+	struct adis16480 *st = iio_priv(indio_dev);
+	unsigned int enable_mask, offset, reg;
+	unsigned int diff, best_diff;
+	unsigned int i, best_freq;
+	uint16_t val;
+	int ret;
+
+	reg = ad16480_filter_data[chan->scan_index][0];
+	offset = ad16480_filter_data[chan->scan_index][1];
+	enable_mask = BIT(offset + 2);
+
+	ret = adis_read_reg_16(&st->adis, reg, &val);
+	if (ret < 0)
+		return ret;
+
+	if (freq == 0) {
+		val &= ~enable_mask;
+	} else {
+		best_freq = 0;
+		best_diff = 310;
+		for (i = 0; i < ARRAY_SIZE(adis16480_def_filter_freqs); i++) {
+			if (adis16480_def_filter_freqs[i] >= freq) {
+				diff = adis16480_def_filter_freqs[i] - freq;
+				if (diff < best_diff) {
+					best_diff = diff;
+					best_freq = i;
+				}
+			}
+		}
+
+		val &= ~(0x3 << offset);
+		val |= best_freq << offset;
+		val |= enable_mask;
+	}
+
+	return adis_write_reg_16(&st->adis, reg, val);
+}
+
+static int adis16480_read_raw(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, int *val, int *val2, long info)
+{
+	switch (info) {
+	case IIO_CHAN_INFO_RAW:
+		return adis_single_conversion(indio_dev, chan, 0, val);
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_ANGL_VEL:
+			*val = 0;
+			*val2 = IIO_DEGREE_TO_RAD(20000); /* 0.02 degree/sec */
+			return IIO_VAL_INT_PLUS_MICRO;
+		case IIO_ACCEL:
+			*val = 0;
+			*val2 = IIO_G_TO_M_S_2(800); /* 0.8 mg */
+			return IIO_VAL_INT_PLUS_MICRO;
+		case IIO_MAGN:
+			*val = 0;
+			*val2 = 100; /* 0.0001 gauss */
+			return IIO_VAL_INT_PLUS_MICRO;
+		case IIO_TEMP:
+			*val = 5;
+			*val2 = 650000; /* 5.65 milli degree Celsius */
+			return IIO_VAL_INT_PLUS_MICRO;
+		case IIO_PRESSURE:
+			*val = 0;
+			*val2 = 4000; /* 40ubar = 0.004 kPa */
+			return IIO_VAL_INT_PLUS_MICRO;
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_OFFSET:
+		/* Only the temperature channel has a offset */
+		*val = 4425; /* 25 degree Celsius = 0x0000 */
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_CALIBBIAS:
+		return adis16480_get_calibbias(indio_dev, chan, val);
+	case IIO_CHAN_INFO_CALIBSCALE:
+		return adis16480_get_calibscale(indio_dev, chan, val);
+	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+		return adis16480_get_filter_freq(indio_dev, chan, val);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int adis16480_write_raw(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, int val, int val2, long info)
+{
+	switch (info) {
+	case IIO_CHAN_INFO_CALIBBIAS:
+		return adis16480_set_calibbias(indio_dev, chan, val);
+	case IIO_CHAN_INFO_CALIBSCALE:
+		return adis16480_set_calibscale(indio_dev, chan, val);
+	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+		return adis16480_set_filter_freq(indio_dev, chan, val);
+	default:
+		return -EINVAL;
+	}
+}
+
+#define ADIS16480_MOD_CHANNEL(_type, _mod, _address, _si, _info, _bits) \
+	{ \
+		.type = (_type), \
+		.modified = 1, \
+		.channel2 = (_mod), \
+		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+			IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
+			IIO_CHAN_INFO_SCALE_SHARED_BIT | \
+			_info, \
+		.address = (_address), \
+		.scan_index = (_si), \
+		.scan_type = { \
+			.sign = 's', \
+			.realbits = (_bits), \
+			.storagebits = (_bits), \
+			.endianness = IIO_BE, \
+		}, \
+	}
+
+#define ADIS16480_GYRO_CHANNEL(_mod) \
+	ADIS16480_MOD_CHANNEL(IIO_ANGL_VEL, IIO_MOD_ ## _mod, \
+	ADIS16480_REG_ ## _mod ## _GYRO_OUT, ADIS16480_SCAN_GYRO_ ## _mod, \
+	IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT | \
+	IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, \
+	32)
+
+#define ADIS16480_ACCEL_CHANNEL(_mod) \
+	ADIS16480_MOD_CHANNEL(IIO_ACCEL, IIO_MOD_ ## _mod, \
+	ADIS16480_REG_ ## _mod ## _ACCEL_OUT, ADIS16480_SCAN_ACCEL_ ## _mod, \
+	IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT | \
+	IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, \
+	32)
+
+#define ADIS16480_MAGN_CHANNEL(_mod) \
+	ADIS16480_MOD_CHANNEL(IIO_MAGN, IIO_MOD_ ## _mod, \
+	ADIS16480_REG_ ## _mod ## _MAGN_OUT, ADIS16480_SCAN_MAGN_ ## _mod, \
+	IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT, \
+	16)
+
+#define ADIS16480_PRESSURE_CHANNEL() \
+	{ \
+		.type = IIO_PRESSURE, \
+		.indexed = 1, \
+		.channel = 0, \
+		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+			IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
+			IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+		.address = ADIS16480_REG_BAROM_OUT, \
+		.scan_index = ADIS16480_SCAN_BARO, \
+		.scan_type = { \
+			.sign = 's', \
+			.realbits = 32, \
+			.storagebits = 32, \
+			.endianness = IIO_BE, \
+		}, \
+	}
+
+#define ADIS16480_TEMP_CHANNEL() { \
+		.type = IIO_TEMP, \
+		.indexed = 1, \
+		.channel = 0, \
+		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+			IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
+			IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, \
+		.address = ADIS16480_REG_TEMP_OUT, \
+		.scan_index = ADIS16480_SCAN_TEMP, \
+		.scan_type = { \
+			.sign = 's', \
+			.realbits = 16, \
+			.storagebits = 16, \
+			.endianness = IIO_BE, \
+		}, \
+	}
+
+static const struct iio_chan_spec adis16480_channels[] = {
+	ADIS16480_GYRO_CHANNEL(X),
+	ADIS16480_GYRO_CHANNEL(Y),
+	ADIS16480_GYRO_CHANNEL(Z),
+	ADIS16480_ACCEL_CHANNEL(X),
+	ADIS16480_ACCEL_CHANNEL(Y),
+	ADIS16480_ACCEL_CHANNEL(Z),
+	ADIS16480_MAGN_CHANNEL(X),
+	ADIS16480_MAGN_CHANNEL(Y),
+	ADIS16480_MAGN_CHANNEL(Z),
+	ADIS16480_PRESSURE_CHANNEL(),
+	ADIS16480_TEMP_CHANNEL(),
+	IIO_CHAN_SOFT_TIMESTAMP(11)
+};
+
+static const struct iio_chan_spec adis16485_channels[] = {
+	ADIS16480_GYRO_CHANNEL(X),
+	ADIS16480_GYRO_CHANNEL(Y),
+	ADIS16480_GYRO_CHANNEL(Z),
+	ADIS16480_ACCEL_CHANNEL(X),
+	ADIS16480_ACCEL_CHANNEL(Y),
+	ADIS16480_ACCEL_CHANNEL(Z),
+	ADIS16480_TEMP_CHANNEL(),
+	IIO_CHAN_SOFT_TIMESTAMP(7)
+};
+
+enum adis16480_variant {
+	ADIS16375,
+	ADIS16480,
+	ADIS16485,
+	ADIS16488,
+};
+
+static const struct adis16480_chip_info adis16480_chip_info[] = {
+	[ADIS16375] = {
+		.channels = adis16485_channels,
+		.num_channels = ARRAY_SIZE(adis16485_channels),
+	},
+	[ADIS16480] = {
+		.channels = adis16480_channels,
+		.num_channels = ARRAY_SIZE(adis16480_channels),
+	},
+	[ADIS16485] = {
+		.channels = adis16485_channels,
+		.num_channels = ARRAY_SIZE(adis16485_channels),
+	},
+	[ADIS16488] = {
+		.channels = adis16480_channels,
+		.num_channels = ARRAY_SIZE(adis16480_channels),
+	},
+};
+
+static struct attribute *adis16480_attributes[] = {
+	&iio_dev_attr_sampling_frequency.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group adis16480_attribute_group = {
+	.attrs = adis16480_attributes,
+};
+
+static const struct iio_info adis16480_info = {
+	.attrs = &adis16480_attribute_group,
+	.read_raw = &adis16480_read_raw,
+	.write_raw = &adis16480_write_raw,
+	.update_scan_mode = adis_update_scan_mode,
+	.driver_module = THIS_MODULE,
+};
+
+static int adis16480_stop_device(struct iio_dev *indio_dev)
+{
+	struct adis16480 *st = iio_priv(indio_dev);
+	int ret;
+
+	ret = adis_write_reg_16(&st->adis, ADIS16480_REG_SLP_CNT, BIT(9));
+	if (ret)
+		dev_err(&indio_dev->dev,
+			"Could not power down device: %d\n", ret);
+
+	return ret;
+}
+
+static int adis16480_enable_irq(struct adis *adis, bool enable)
+{
+	return adis_write_reg_16(adis, ADIS16480_REG_FNCTIO_CTRL,
+		enable ? BIT(3) : 0);
+}
+
+static int adis16480_initial_setup(struct iio_dev *indio_dev)
+{
+	struct adis16480 *st = iio_priv(indio_dev);
+	uint16_t prod_id;
+	unsigned int device_id;
+	int ret;
+
+	adis_reset(&st->adis);
+	msleep(70);
+
+	ret = adis_write_reg_16(&st->adis, ADIS16480_REG_GLOB_CMD, BIT(1));
+	if (ret)
+		return ret;
+	msleep(30);
+
+	ret = adis_check_status(&st->adis);
+	if (ret)
+		return ret;
+
+	ret = adis_read_reg_16(&st->adis, ADIS16480_REG_PROD_ID, &prod_id);
+	if (ret)
+		return ret;
+
+	sscanf(indio_dev->name, "adis%u\n", &device_id);
+
+	if (prod_id != device_id)
+		dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.",
+				device_id, prod_id);
+
+	return 0;
+}
+
+#define ADIS16480_DIAG_STAT_XGYRO_FAIL 0
+#define ADIS16480_DIAG_STAT_YGYRO_FAIL 1
+#define ADIS16480_DIAG_STAT_ZGYRO_FAIL 2
+#define ADIS16480_DIAG_STAT_XACCL_FAIL 3
+#define ADIS16480_DIAG_STAT_YACCL_FAIL 4
+#define ADIS16480_DIAG_STAT_ZACCL_FAIL 5
+#define ADIS16480_DIAG_STAT_XMAGN_FAIL 8
+#define ADIS16480_DIAG_STAT_YMAGN_FAIL 9
+#define ADIS16480_DIAG_STAT_ZMAGN_FAIL 10
+#define ADIS16480_DIAG_STAT_BARO_FAIL 11
+
+static const char * const adis16480_status_error_msgs[] = {
+	[ADIS16480_DIAG_STAT_XGYRO_FAIL] = "X-axis gyroscope self-test failure",
+	[ADIS16480_DIAG_STAT_YGYRO_FAIL] = "Y-axis gyroscope self-test failure",
+	[ADIS16480_DIAG_STAT_ZGYRO_FAIL] = "Z-axis gyroscope self-test failure",
+	[ADIS16480_DIAG_STAT_XACCL_FAIL] = "X-axis accelerometer self-test failure",
+	[ADIS16480_DIAG_STAT_YACCL_FAIL] = "Y-axis accelerometer self-test failure",
+	[ADIS16480_DIAG_STAT_ZACCL_FAIL] = "Z-axis accelerometer self-test failure",
+	[ADIS16480_DIAG_STAT_XMAGN_FAIL] = "X-axis magnetometer self-test failure",
+	[ADIS16480_DIAG_STAT_YMAGN_FAIL] = "Y-axis magnetometer self-test failure",
+	[ADIS16480_DIAG_STAT_ZMAGN_FAIL] = "Z-axis magnetometer self-test failure",
+	[ADIS16480_DIAG_STAT_BARO_FAIL] = "Barometer self-test failure",
+};
+
+static const struct adis_data adis16480_data = {
+	.diag_stat_reg = ADIS16480_REG_DIAG_STS,
+	.glob_cmd_reg = ADIS16480_REG_GLOB_CMD,
+	.has_paging = true,
+
+	.read_delay = 5,
+	.write_delay = 5,
+
+	.status_error_msgs = adis16480_status_error_msgs,
+	.status_error_mask = BIT(ADIS16480_DIAG_STAT_XGYRO_FAIL) |
+		BIT(ADIS16480_DIAG_STAT_YGYRO_FAIL) |
+		BIT(ADIS16480_DIAG_STAT_ZGYRO_FAIL) |
+		BIT(ADIS16480_DIAG_STAT_XACCL_FAIL) |
+		BIT(ADIS16480_DIAG_STAT_YACCL_FAIL) |
+		BIT(ADIS16480_DIAG_STAT_ZACCL_FAIL) |
+		BIT(ADIS16480_DIAG_STAT_XMAGN_FAIL) |
+		BIT(ADIS16480_DIAG_STAT_YMAGN_FAIL) |
+		BIT(ADIS16480_DIAG_STAT_ZMAGN_FAIL) |
+		BIT(ADIS16480_DIAG_STAT_BARO_FAIL),
+
+	.enable_irq = adis16480_enable_irq,
+};
+
+static int adis16480_probe(struct spi_device *spi)
+{
+	const struct spi_device_id *id = spi_get_device_id(spi);
+	struct iio_dev *indio_dev;
+	struct adis16480 *st;
+	int ret;
+
+	indio_dev = iio_device_alloc(sizeof(*st));
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
+	spi_set_drvdata(spi, indio_dev);
+
+	st = iio_priv(indio_dev);
+
+	st->chip_info = &adis16480_chip_info[id->driver_data];
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->channels = st->chip_info->channels;
+	indio_dev->num_channels = st->chip_info->num_channels;
+	indio_dev->info = &adis16480_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = adis_init(&st->adis, indio_dev, spi, &adis16480_data);
+	if (ret)
+		goto error_free_dev;
+
+	ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL);
+	if (ret)
+		goto error_free_dev;
+
+	ret = adis16480_initial_setup(indio_dev);
+	if (ret)
+		goto error_cleanup_buffer;
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_stop_device;
+
+	adis16480_debugfs_init(indio_dev);
+
+	return 0;
+
+error_stop_device:
+	adis16480_stop_device(indio_dev);
+error_cleanup_buffer:
+	adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
+error_free_dev:
+	iio_device_free(indio_dev);
+	return ret;
+}
+
+static int adis16480_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct adis16480 *st = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	adis16480_stop_device(indio_dev);
+
+	adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
+
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+static const struct spi_device_id adis16480_ids[] = {
+	{ "adis16375", ADIS16375 },
+	{ "adis16480", ADIS16480 },
+	{ "adis16485", ADIS16485 },
+	{ "adis16488", ADIS16488 },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, adis16480_ids);
+
+static struct spi_driver adis16480_driver = {
+	.driver = {
+		.name = "adis16480",
+		.owner = THIS_MODULE,
+	},
+	.id_table = adis16480_ids,
+	.probe = adis16480_probe,
+	.remove = adis16480_remove,
+};
+module_spi_driver(adis16480_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Devices ADIS16480 IMU driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c
new file mode 100644
index 0000000..99d8e0b
--- /dev/null
+++ b/drivers/iio/imu/adis_buffer.c
@@ -0,0 +1,176 @@
+/*
+ * Common library for ADIS16XXX devices
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *   Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/export.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/imu/adis.h>
+
+int adis_update_scan_mode(struct iio_dev *indio_dev,
+	const unsigned long *scan_mask)
+{
+	struct adis *adis = iio_device_get_drvdata(indio_dev);
+	const struct iio_chan_spec *chan;
+	unsigned int scan_count;
+	unsigned int i, j;
+	__be16 *tx, *rx;
+
+	kfree(adis->xfer);
+	kfree(adis->buffer);
+
+	scan_count = indio_dev->scan_bytes / 2;
+
+	adis->xfer = kcalloc(scan_count + 1, sizeof(*adis->xfer), GFP_KERNEL);
+	if (!adis->xfer)
+		return -ENOMEM;
+
+	adis->buffer = kzalloc(indio_dev->scan_bytes * 2, GFP_KERNEL);
+	if (!adis->buffer)
+		return -ENOMEM;
+
+	rx = adis->buffer;
+	tx = rx + indio_dev->scan_bytes;
+
+	spi_message_init(&adis->msg);
+
+	for (j = 0; j <= scan_count; j++) {
+		adis->xfer[j].bits_per_word = 8;
+		if (j != scan_count)
+			adis->xfer[j].cs_change = 1;
+		adis->xfer[j].len = 2;
+		adis->xfer[j].delay_usecs = adis->data->read_delay;
+		if (j < scan_count)
+			adis->xfer[j].tx_buf = &tx[j];
+		if (j >= 1)
+			adis->xfer[j].rx_buf = &rx[j - 1];
+		spi_message_add_tail(&adis->xfer[j], &adis->msg);
+	}
+
+	chan = indio_dev->channels;
+	for (i = 0; i < indio_dev->num_channels; i++, chan++) {
+		if (!test_bit(chan->scan_index, scan_mask))
+			continue;
+		if (chan->scan_type.storagebits == 32)
+			*tx++ = cpu_to_be16((chan->address + 2) << 8);
+		*tx++ = cpu_to_be16(chan->address << 8);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(adis_update_scan_mode);
+
+static irqreturn_t adis_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct adis *adis = iio_device_get_drvdata(indio_dev);
+	int ret;
+
+	if (!adis->buffer)
+		return -ENOMEM;
+
+	if (adis->data->has_paging) {
+		mutex_lock(&adis->txrx_lock);
+		if (adis->current_page != 0) {
+			adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID);
+			adis->tx[1] = 0;
+			spi_write(adis->spi, adis->tx, 2);
+		}
+	}
+
+	ret = spi_sync(adis->spi, &adis->msg);
+	if (ret)
+		dev_err(&adis->spi->dev, "Failed to read data: %d", ret);
+
+
+	if (adis->data->has_paging) {
+		adis->current_page = 0;
+		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_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * adis_setup_buffer_and_trigger() - Sets up buffer and trigger for the adis device
+ * @adis: The adis device.
+ * @indio_dev: The IIO device.
+ * @trigger_handler: Optional trigger handler, may be NULL.
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function sets up the buffer and trigger for a adis devices.  If
+ * 'trigger_handler' is NULL the default trigger handler will be used. The
+ * default trigger handler will simply read the registers assigned to the
+ * currently active channels.
+ *
+ * adis_cleanup_buffer_and_trigger() should be called to free the resources
+ * allocated by this function.
+ */
+int adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev,
+	irqreturn_t (*trigger_handler)(int, void *))
+{
+	int ret;
+
+	if (!trigger_handler)
+		trigger_handler = adis_trigger_handler;
+
+	ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+		trigger_handler, NULL);
+	if (ret)
+		return ret;
+
+	if (adis->spi->irq) {
+		ret = adis_probe_trigger(adis, indio_dev);
+		if (ret)
+			goto error_buffer_cleanup;
+	}
+	return 0;
+
+error_buffer_cleanup:
+	iio_triggered_buffer_cleanup(indio_dev);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(adis_setup_buffer_and_trigger);
+
+/**
+ * adis_cleanup_buffer_and_trigger() - Free buffer and trigger resources
+ * @adis: The adis device.
+ * @indio_dev: The IIO device.
+ *
+ * Frees resources allocated by adis_setup_buffer_and_trigger()
+ */
+void adis_cleanup_buffer_and_trigger(struct adis *adis,
+	struct iio_dev *indio_dev)
+{
+	if (adis->spi->irq)
+		adis_remove_trigger(adis);
+	kfree(adis->buffer);
+	kfree(adis->xfer);
+	iio_triggered_buffer_cleanup(indio_dev);
+}
+EXPORT_SYMBOL_GPL(adis_cleanup_buffer_and_trigger);
diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
new file mode 100644
index 0000000..5a24c9c
--- /dev/null
+++ b/drivers/iio/imu/adis_trigger.c
@@ -0,0 +1,89 @@
+/*
+ * Common library for ADIS16XXX devices
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *   Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/export.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/imu/adis.h>
+
+static int adis_data_rdy_trigger_set_state(struct iio_trigger *trig,
+						bool state)
+{
+	struct adis *adis = trig->private_data;
+
+	return adis_enable_irq(adis, state);
+}
+
+static const struct iio_trigger_ops adis_trigger_ops = {
+	.owner = THIS_MODULE,
+	.set_trigger_state = &adis_data_rdy_trigger_set_state,
+};
+
+/**
+ * adis_probe_trigger() - Sets up trigger for a adis device
+ * @adis: The adis device
+ * @indio_dev: The IIO device
+ *
+ * Returns 0 on success or a negative error code
+ *
+ * adis_remove_trigger() should be used to free the trigger.
+ */
+int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
+{
+	int ret;
+
+	adis->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name,
+					indio_dev->id);
+	if (adis->trig == NULL)
+		return -ENOMEM;
+
+	ret = request_irq(adis->spi->irq,
+			  &iio_trigger_generic_data_rdy_poll,
+			  IRQF_TRIGGER_RISING,
+			  indio_dev->name,
+			  adis->trig);
+	if (ret)
+		goto error_free_trig;
+
+	adis->trig->dev.parent = &adis->spi->dev;
+	adis->trig->ops = &adis_trigger_ops;
+	adis->trig->private_data = adis;
+	ret = iio_trigger_register(adis->trig);
+
+	indio_dev->trig = adis->trig;
+	if (ret)
+		goto error_free_irq;
+
+	return 0;
+
+error_free_irq:
+	free_irq(adis->spi->irq, adis->trig);
+error_free_trig:
+	iio_trigger_free(adis->trig);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(adis_probe_trigger);
+
+/**
+ * adis_remove_trigger() - Remove trigger for a adis devices
+ * @adis: The adis device
+ *
+ * Removes the trigger previously registered with adis_probe_trigger().
+ */
+void adis_remove_trigger(struct adis *adis)
+{
+	iio_trigger_unregister(adis->trig);
+	free_irq(adis->spi->irq, adis->trig);
+	iio_trigger_free(adis->trig);
+}
+EXPORT_SYMBOL_GPL(adis_remove_trigger);
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index d4ad374..aaadd32 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -31,6 +31,18 @@ static const char * const iio_endian_prefix[] = {
 	[IIO_LE] = "le",
 };
 
+static bool iio_buffer_is_active(struct iio_dev *indio_dev,
+				 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;
+}
+
 /**
  * iio_buffer_read_first_n_outer() - chrdev read for buffer access
  *
@@ -134,7 +146,7 @@ static ssize_t iio_scan_el_store(struct device *dev,
 	if (ret < 0)
 		return ret;
 	mutex_lock(&indio_dev->mlock);
-	if (iio_buffer_enabled(indio_dev)) {
+	if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
 		ret = -EBUSY;
 		goto error_ret;
 	}
@@ -180,12 +192,11 @@ static ssize_t iio_scan_el_ts_store(struct device *dev,
 		return ret;
 
 	mutex_lock(&indio_dev->mlock);
-	if (iio_buffer_enabled(indio_dev)) {
+	if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
 		ret = -EBUSY;
 		goto error_ret;
 	}
 	indio_dev->buffer->scan_timestamp = state;
-	indio_dev->scan_timestamp = state;
 error_ret:
 	mutex_unlock(&indio_dev->mlock);
 
@@ -371,12 +382,12 @@ ssize_t iio_buffer_write_length(struct device *dev,
 				const char *buf,
 				size_t len)
 {
-	int ret;
-	ulong val;
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct iio_buffer *buffer = indio_dev->buffer;
+	unsigned int val;
+	int ret;
 
-	ret = strict_strtoul(buf, 10, &val);
+	ret = kstrtouint(buf, 10, &val);
 	if (ret)
 		return ret;
 
@@ -385,7 +396,7 @@ ssize_t iio_buffer_write_length(struct device *dev,
 			return len;
 
 	mutex_lock(&indio_dev->mlock);
-	if (iio_buffer_enabled(indio_dev)) {
+	if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
 		ret = -EBUSY;
 	} else {
 		if (buffer->access->set_length)
@@ -398,102 +409,14 @@ ssize_t iio_buffer_write_length(struct device *dev,
 }
 EXPORT_SYMBOL(iio_buffer_write_length);
 
-ssize_t iio_buffer_store_enable(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf,
-				size_t len)
-{
-	int ret;
-	bool requested_state, current_state;
-	int previous_mode;
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct iio_buffer *buffer = indio_dev->buffer;
-
-	mutex_lock(&indio_dev->mlock);
-	previous_mode = indio_dev->currentmode;
-	requested_state = !(buf[0] == '0');
-	current_state = iio_buffer_enabled(indio_dev);
-	if (current_state == requested_state) {
-		printk(KERN_INFO "iio-buffer, current state requested again\n");
-		goto done;
-	}
-	if (requested_state) {
-		if (indio_dev->setup_ops->preenable) {
-			ret = indio_dev->setup_ops->preenable(indio_dev);
-			if (ret) {
-				printk(KERN_ERR
-				       "Buffer not started: "
-				       "buffer preenable failed\n");
-				goto error_ret;
-			}
-		}
-		if (buffer->access->request_update) {
-			ret = buffer->access->request_update(buffer);
-			if (ret) {
-				printk(KERN_INFO
-				       "Buffer not started: "
-				       "buffer parameter update failed\n");
-				goto error_ret;
-			}
-		}
-		/* 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");
-				ret = -EINVAL;
-				goto error_ret;
-			}
-			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 */
-			ret = -EINVAL;
-			goto error_ret;
-		}
-
-		if (indio_dev->setup_ops->postenable) {
-			ret = indio_dev->setup_ops->postenable(indio_dev);
-			if (ret) {
-				printk(KERN_INFO
-				       "Buffer not started: "
-				       "postenable failed\n");
-				indio_dev->currentmode = previous_mode;
-				if (indio_dev->setup_ops->postdisable)
-					indio_dev->setup_ops->
-						postdisable(indio_dev);
-				goto error_ret;
-			}
-		}
-	} else {
-		if (indio_dev->setup_ops->predisable) {
-			ret = indio_dev->setup_ops->predisable(indio_dev);
-			if (ret)
-				goto error_ret;
-		}
-		indio_dev->currentmode = INDIO_DIRECT_MODE;
-		if (indio_dev->setup_ops->postdisable) {
-			ret = indio_dev->setup_ops->postdisable(indio_dev);
-			if (ret)
-				goto error_ret;
-		}
-	}
-done:
-	mutex_unlock(&indio_dev->mlock);
-	return len;
-
-error_ret:
-	mutex_unlock(&indio_dev->mlock);
-	return ret;
-}
-EXPORT_SYMBOL(iio_buffer_store_enable);
-
 ssize_t iio_buffer_show_enable(struct device *dev,
 			       struct device_attribute *attr,
 			       char *buf)
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	return sprintf(buf, "%d\n", iio_buffer_enabled(indio_dev));
+	return sprintf(buf, "%d\n",
+		       iio_buffer_is_active(indio_dev,
+					    indio_dev->buffer));
 }
 EXPORT_SYMBOL(iio_buffer_show_enable);
 
@@ -537,35 +460,220 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask,
 	return bytes;
 }
 
-int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
+int iio_update_buffers(struct iio_dev *indio_dev,
+		       struct iio_buffer *insert_buffer,
+		       struct iio_buffer *remove_buffer)
 {
-	struct iio_buffer *buffer = indio_dev->buffer;
-	dev_dbg(&indio_dev->dev, "%s\n", __func__);
+	int ret;
+	int success = 0;
+	struct iio_buffer *buffer;
+	unsigned long *compound_mask;
+	const unsigned long *old_mask;
 
-	/* How much space will the demuxed element take? */
-	indio_dev->scan_bytes =
-		iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
-				       buffer->scan_timestamp);
-	buffer->access->set_bytes_per_datum(buffer, indio_dev->scan_bytes);
+	/* Wind down existing buffers - iff there are any */
+	if (!list_empty(&indio_dev->buffer_list)) {
+		if (indio_dev->setup_ops->predisable) {
+			ret = indio_dev->setup_ops->predisable(indio_dev);
+			if (ret)
+				goto error_ret;
+		}
+		indio_dev->currentmode = INDIO_DIRECT_MODE;
+		if (indio_dev->setup_ops->postdisable) {
+			ret = indio_dev->setup_ops->postdisable(indio_dev);
+			if (ret)
+				goto error_ret;
+		}
+	}
+	/* Keep a copy of current setup to allow roll back */
+	old_mask = indio_dev->active_scan_mask;
+	if (!indio_dev->available_scan_masks)
+		indio_dev->active_scan_mask = NULL;
+
+	if (remove_buffer)
+		list_del(&remove_buffer->buffer_list);
+	if (insert_buffer)
+		list_add(&insert_buffer->buffer_list, &indio_dev->buffer_list);
+
+	/* If no buffers in list, we are done */
+	if (list_empty(&indio_dev->buffer_list)) {
+		indio_dev->currentmode = INDIO_DIRECT_MODE;
+		if (indio_dev->available_scan_masks == NULL)
+			kfree(old_mask);
+		return 0;
+	}
 
 	/* What scan mask do we actually have ?*/
-	if (indio_dev->available_scan_masks)
+	compound_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength),
+				sizeof(long), GFP_KERNEL);
+	if (compound_mask == NULL) {
+		if (indio_dev->available_scan_masks == NULL)
+			kfree(old_mask);
+		return -ENOMEM;
+	}
+	indio_dev->scan_timestamp = 0;
+
+	list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) {
+		bitmap_or(compound_mask, compound_mask, buffer->scan_mask,
+			  indio_dev->masklength);
+		indio_dev->scan_timestamp |= buffer->scan_timestamp;
+	}
+	if (indio_dev->available_scan_masks) {
 		indio_dev->active_scan_mask =
 			iio_scan_mask_match(indio_dev->available_scan_masks,
 					    indio_dev->masklength,
-					    buffer->scan_mask);
-	else
-		indio_dev->active_scan_mask = buffer->scan_mask;
-
-	if (indio_dev->active_scan_mask == NULL)
-		return -EINVAL;
+					    compound_mask);
+		if (indio_dev->active_scan_mask == NULL) {
+			/*
+			 * Roll back.
+			 * Note can only occur when adding a buffer.
+			 */
+			list_del(&insert_buffer->buffer_list);
+			indio_dev->active_scan_mask = old_mask;
+			success = -EINVAL;
+		}
+	} else {
+		indio_dev->active_scan_mask = compound_mask;
+	}
 
 	iio_update_demux(indio_dev);
 
-	if (indio_dev->info->update_scan_mode)
-		return indio_dev->info
+	/* Wind up again */
+	if (indio_dev->setup_ops->preenable) {
+		ret = indio_dev->setup_ops->preenable(indio_dev);
+		if (ret) {
+			printk(KERN_ERR
+			       "Buffer not started:"
+			       "buffer preenable failed\n");
+			goto error_remove_inserted;
+		}
+	}
+	indio_dev->scan_bytes =
+		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)
+		if (buffer->access->request_update) {
+			ret = buffer->access->request_update(buffer);
+			if (ret) {
+				printk(KERN_INFO
+				       "Buffer not started:"
+				       "buffer parameter update failed\n");
+				goto error_run_postdisable;
+			}
+		}
+	if (indio_dev->info->update_scan_mode) {
+		ret = indio_dev->info
 			->update_scan_mode(indio_dev,
 					   indio_dev->active_scan_mask);
+		if (ret < 0) {
+			printk(KERN_INFO "update scan mode failed\n");
+			goto error_run_postdisable;
+		}
+	}
+	/* 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");
+			ret = -EINVAL;
+			/* Can only occur on first buffer */
+			goto error_run_postdisable;
+		}
+		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 */
+		ret = -EINVAL;
+		goto error_run_postdisable;
+	}
+
+	if (indio_dev->setup_ops->postenable) {
+		ret = indio_dev->setup_ops->postenable(indio_dev);
+		if (ret) {
+			printk(KERN_INFO
+			       "Buffer not started: postenable failed\n");
+			indio_dev->currentmode = INDIO_DIRECT_MODE;
+			if (indio_dev->setup_ops->postdisable)
+				indio_dev->setup_ops->postdisable(indio_dev);
+			goto error_disable_all_buffers;
+		}
+	}
+
+	if (indio_dev->available_scan_masks)
+		kfree(compound_mask);
+	else
+		kfree(old_mask);
+
+	return success;
+
+error_disable_all_buffers:
+	indio_dev->currentmode = INDIO_DIRECT_MODE;
+error_run_postdisable:
+	if (indio_dev->setup_ops->postdisable)
+		indio_dev->setup_ops->postdisable(indio_dev);
+error_remove_inserted:
+
+	if (insert_buffer)
+		list_del(&insert_buffer->buffer_list);
+	indio_dev->active_scan_mask = old_mask;
+	kfree(compound_mask);
+error_ret:
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(iio_update_buffers);
+
+ssize_t iio_buffer_store_enable(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf,
+				size_t len)
+{
+	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);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&indio_dev->mlock);
+
+	/* Find out if it is in the list */
+	inlist = iio_buffer_is_active(indio_dev, pbuf);
+	/* Already in desired state */
+	if (inlist == requested_state)
+		goto done;
+
+	if (requested_state)
+		ret = iio_update_buffers(indio_dev,
+					 indio_dev->buffer, NULL);
+	else
+		ret = iio_update_buffers(indio_dev,
+					 NULL, indio_dev->buffer);
+
+	if (ret < 0)
+		goto done;
+done:
+	mutex_unlock(&indio_dev->mlock);
+	return (ret < 0) ? ret : len;
+}
+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);
@@ -599,7 +707,11 @@ static bool iio_validate_scan_mask(struct iio_dev *indio_dev,
  * iio_scan_mask_set() - set particular bit in the scan mask
  * @buffer: the buffer whose scan mask we are interested in
  * @bit: the bit to be set.
- **/
+ *
+ * Note that at this point we have no way of knowing what other
+ * buffers might request, hence this code only verifies that the
+ * individual buffers request is plausible.
+ */
 int iio_scan_mask_set(struct iio_dev *indio_dev,
 		      struct iio_buffer *buffer, int bit)
 {
@@ -682,13 +794,12 @@ static unsigned char *iio_demux(struct iio_buffer *buffer,
 	return buffer->demux_bounce;
 }
 
-int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data)
+static int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data)
 {
 	unsigned char *dataout = iio_demux(buffer, data);
 
 	return buffer->access->store_to(buffer, dataout);
 }
-EXPORT_SYMBOL_GPL(iio_push_to_buffer);
 
 static void iio_buffer_demux_free(struct iio_buffer *buffer)
 {
@@ -699,10 +810,26 @@ static void iio_buffer_demux_free(struct iio_buffer *buffer)
 	}
 }
 
-int iio_update_demux(struct iio_dev *indio_dev)
+
+int iio_push_to_buffers(struct iio_dev *indio_dev, unsigned char *data)
+{
+	int ret;
+	struct iio_buffer *buf;
+
+	list_for_each_entry(buf, &indio_dev->buffer_list, buffer_list) {
+		ret = iio_push_to_buffer(buf, data);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iio_push_to_buffers);
+
+static int iio_buffer_update_demux(struct iio_dev *indio_dev,
+				   struct iio_buffer *buffer)
 {
 	const struct iio_chan_spec *ch;
-	struct iio_buffer *buffer = indio_dev->buffer;
 	int ret, in_ind = -1, out_ind, length;
 	unsigned in_loc = 0, out_loc = 0;
 	struct iio_demux_table *p;
@@ -787,4 +914,23 @@ error_clear_mux_table:
 
 	return ret;
 }
+
+int iio_update_demux(struct iio_dev *indio_dev)
+{
+	struct iio_buffer *buffer;
+	int ret;
+
+	list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) {
+		ret = iio_buffer_update_demux(indio_dev, buffer);
+		if (ret < 0)
+			goto error_clear_mux_table;
+	}
+	return 0;
+
+error_clear_mux_table:
+	list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list)
+		iio_buffer_demux_free(buffer);
+
+	return ret;
+}
 EXPORT_SYMBOL_GPL(iio_update_demux);
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 6eb24db..8848f16 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -65,6 +65,7 @@ static const char * const iio_chan_type_name_spec[] = {
 	[IIO_CAPACITANCE] = "capacitance",
 	[IIO_ALTVOLTAGE] = "altvoltage",
 	[IIO_CCT] = "cct",
+	[IIO_PRESSURE] = "pressure",
 };
 
 static const char * const iio_modifier_names[] = {
@@ -397,11 +398,74 @@ static ssize_t iio_read_channel_info(struct device *dev,
 		val2 = do_div(tmp, 1000000000LL);
 		val = tmp;
 		return sprintf(buf, "%d.%09u\n", val, val2);
+	case IIO_VAL_FRACTIONAL_LOG2:
+		tmp = (s64)val * 1000000000LL >> val2;
+		val2 = do_div(tmp, 1000000000LL);
+		val = tmp;
+		return sprintf(buf, "%d.%09u\n", val, val2);
 	default:
 		return 0;
 	}
 }
 
+/**
+ * iio_str_to_fixpoint() - Parse a fixed-point number from a string
+ * @str: The string to parse
+ * @fract_mult: Multiplier for the first decimal place, should be a power of 10
+ * @integer: The integer part of the number
+ * @fract: The fractional part of the number
+ *
+ * Returns 0 on success, or a negative error code if the string could not be
+ * parsed.
+ */
+int iio_str_to_fixpoint(const char *str, int fract_mult,
+	int *integer, int *fract)
+{
+	int i = 0, f = 0;
+	bool integer_part = true, negative = false;
+
+	if (str[0] == '-') {
+		negative = true;
+		str++;
+	} else if (str[0] == '+') {
+		str++;
+	}
+
+	while (*str) {
+		if ('0' <= *str && *str <= '9') {
+			if (integer_part) {
+				i = i * 10 + *str - '0';
+			} else {
+				f += fract_mult * (*str - '0');
+				fract_mult /= 10;
+			}
+		} else if (*str == '\n') {
+			if (*(str + 1) == '\0')
+				break;
+			else
+				return -EINVAL;
+		} else if (*str == '.' && integer_part) {
+			integer_part = false;
+		} else {
+			return -EINVAL;
+		}
+		str++;
+	}
+
+	if (negative) {
+		if (i)
+			i = -i;
+		else
+			f = -f;
+	}
+
+	*integer = i;
+	*fract = f;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iio_str_to_fixpoint);
+
 static ssize_t iio_write_channel_info(struct device *dev,
 				      struct device_attribute *attr,
 				      const char *buf,
@@ -409,8 +473,8 @@ static ssize_t iio_write_channel_info(struct device *dev,
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	int ret, integer = 0, fract = 0, fract_mult = 100000;
-	bool integer_part = true, negative = false;
+	int ret, fract_mult = 100000;
+	int integer, fract;
 
 	/* Assumes decimal - precision based on number of digits */
 	if (!indio_dev->info->write_raw)
@@ -429,39 +493,9 @@ static ssize_t iio_write_channel_info(struct device *dev,
 			return -EINVAL;
 		}
 
-	if (buf[0] == '-') {
-		negative = true;
-		buf++;
-	}
-
-	while (*buf) {
-		if ('0' <= *buf && *buf <= '9') {
-			if (integer_part)
-				integer = integer*10 + *buf - '0';
-			else {
-				fract += fract_mult*(*buf - '0');
-				if (fract_mult == 1)
-					break;
-				fract_mult /= 10;
-			}
-		} else if (*buf == '\n') {
-			if (*(buf + 1) == '\0')
-				break;
-			else
-				return -EINVAL;
-		} else if (*buf == '.') {
-			integer_part = false;
-		} else {
-			return -EINVAL;
-		}
-		buf++;
-	}
-	if (negative) {
-		if (integer)
-			integer = -integer;
-		else
-			fract = -fract;
-	}
+	ret = iio_str_to_fixpoint(buf, fract_mult, &integer, &fract);
+	if (ret)
+		return ret;
 
 	ret = indio_dev->info->write_raw(indio_dev, this_attr->c,
 					 integer, fract, this_attr->address);
@@ -851,6 +885,7 @@ struct iio_dev *iio_device_alloc(int sizeof_priv)
 			return NULL;
 		}
 		dev_set_name(&dev->dev, "iio:device%d", dev->id);
+		INIT_LIST_HEAD(&dev->buffer_list);
 	}
 
 	return dev;
diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c
index fa6543b..261cae0 100644
--- a/drivers/iio/industrialio-event.c
+++ b/drivers/iio/industrialio-event.c
@@ -239,13 +239,13 @@ static ssize_t iio_ev_value_store(struct device *dev,
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	unsigned long val;
+	int val;
 	int ret;
 
 	if (!indio_dev->info->write_event_value)
 		return -EINVAL;
 
-	ret = strict_strtoul(buf, 10, &val);
+	ret = kstrtoint(buf, 10, &val);
 	if (ret)
 		return ret;
 
@@ -350,15 +350,10 @@ static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev)
 		ret = iio_device_add_event_sysfs(indio_dev,
 						 &indio_dev->channels[j]);
 		if (ret < 0)
-			goto error_clear_attrs;
+			return ret;
 		attrcount += ret;
 	}
 	return attrcount;
-
-error_clear_attrs:
-	__iio_remove_event_config_attrs(indio_dev);
-
-	return ret;
 }
 
 static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev)
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index f2b78d4..d55e98f 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -78,7 +78,7 @@ int iio_map_array_unregister(struct iio_dev *indio_dev,
 				found_it = true;
 				break;
 			}
-		if (found_it == false) {
+		if (!found_it) {
 			ret = -ENODEV;
 			goto error_ret;
 		}
@@ -203,6 +203,7 @@ struct iio_channel *iio_channel_get_all(const char *name)
 		if (name && strcmp(name, c->map->consumer_dev_name) != 0)
 			continue;
 		chans[mapind].indio_dev = c->indio_dev;
+		chans[mapind].data = c->map->consumer_data;
 		chans[mapind].channel =
 			iio_chan_spec_from_name(chans[mapind].indio_dev,
 						c->map->adc_channel_label);
@@ -314,6 +315,9 @@ static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan,
 		*processed = div_s64(raw64 * (s64)scale_val * scale,
 				     scale_val2);
 		break;
+	case IIO_VAL_FRACTIONAL_LOG2:
+		*processed = (raw64 * (s64)scale_val * scale) >> scale_val2;
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c
index 164b62b..36d210a 100644
--- a/drivers/iio/light/adjd_s311.c
+++ b/drivers/iio/light/adjd_s311.c
@@ -164,7 +164,6 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct adjd_s311_data *data = iio_priv(indio_dev);
-	struct iio_buffer *buffer = indio_dev->buffer;
 	s64 time_ns = iio_get_time_ns();
 	int len = 0;
 	int i, j = 0;
@@ -187,7 +186,7 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
 	if (indio_dev->scan_timestamp)
 		*(s64 *)((u8 *)data->buffer + ALIGN(len, sizeof(s64)))
 			= time_ns;
-	iio_push_to_buffer(buffer, (u8 *)data->buffer);
+	iio_push_to_buffers(indio_dev, (u8 *)data->buffer);
 
 done:
 	iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index 96e3691..23eeeef 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -176,21 +176,8 @@ static const struct iio_info als_info = {
 /* Function to push data to buffer */
 static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
 {
-	struct iio_buffer *buffer = indio_dev->buffer;
-	int datum_sz;
-
 	dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
-	if (!buffer) {
-		dev_err(&indio_dev->dev, "Buffer == NULL\n");
-		return;
-	}
-	datum_sz = buffer->access->get_bytes_per_datum(buffer);
-	if (len > datum_sz) {
-		dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len,
-				datum_sz);
-		return;
-	}
-	iio_push_to_buffer(buffer, (u8 *)data);
+	iio_push_to_buffers(indio_dev, (u8 *)data);
 }
 
 /* Callback handler to send event after all samples are received and captured */
@@ -285,10 +272,9 @@ static int __devinit hid_als_probe(struct platform_device *pdev)
 		goto error_free_dev;
 	}
 
-	channels = kmemdup(als_channels,
-					sizeof(als_channels),
-					GFP_KERNEL);
+	channels = kmemdup(als_channels, sizeof(als_channels), GFP_KERNEL);
 	if (!channels) {
+		ret = -ENOMEM;
 		dev_err(&pdev->dev, "failed to duplicate channels\n");
 		goto error_free_dev;
 	}
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index c4f0d27..8e75eb7 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -198,21 +198,8 @@ static const struct iio_info magn_3d_info = {
 /* Function to push data to buffer */
 static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
 {
-	struct iio_buffer *buffer = indio_dev->buffer;
-	int datum_sz;
-
 	dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
-	if (!buffer) {
-		dev_err(&indio_dev->dev, "Buffer == NULL\n");
-		return;
-	}
-	datum_sz = buffer->access->get_bytes_per_datum(buffer);
-	if (len > datum_sz) {
-		dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len,
-				datum_sz);
-		return;
-	}
-	iio_push_to_buffer(buffer, (u8 *)data);
+	iio_push_to_buffers(indio_dev, (u8 *)data);
 }
 
 /* Callback handler to send event after all samples are received and captured */
@@ -320,10 +307,10 @@ static int __devinit hid_magn_3d_probe(struct platform_device *pdev)
 		goto error_free_dev;
 	}
 
-	channels = kmemdup(magn_3d_channels,
-					sizeof(magn_3d_channels),
-					GFP_KERNEL);
+	channels = kmemdup(magn_3d_channels, sizeof(magn_3d_channels),
+			   GFP_KERNEL);
 	if (!channels) {
+		ret = -ENOMEM;
 		dev_err(&pdev->dev, "failed to duplicate channels\n");
 		goto error_free_dev;
 	}
diff --git a/drivers/infiniband/hw/amso1100/c2_ae.c b/drivers/infiniband/hw/amso1100/c2_ae.c
index 32d34e8..706cf97 100644
--- a/drivers/infiniband/hw/amso1100/c2_ae.c
+++ b/drivers/infiniband/hw/amso1100/c2_ae.c
@@ -311,6 +311,7 @@ void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
 		if (cq->ibcq.event_handler)
 			cq->ibcq.event_handler(&ib_event,
 					       cq->ibcq.cq_context);
+		break;
 	}
 
 	default:
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index aaf88ef9..3e094cd 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -128,9 +128,8 @@ static void stop_ep_timer(struct iwch_ep *ep)
 {
 	PDBG("%s ep %p\n", __func__, ep);
 	if (!timer_pending(&ep->timer)) {
-		printk(KERN_ERR "%s timer stopped when its not running!  ep %p state %u\n",
+		WARN(1, "%s timer stopped when its not running!  ep %p state %u\n",
 			__func__, ep, ep->com.state);
-		WARN_ON(1);
 		return;
 	}
 	del_timer_sync(&ep->timer);
@@ -1756,9 +1755,8 @@ static void ep_timeout(unsigned long arg)
 		__state_set(&ep->com, ABORTING);
 		break;
 	default:
-		printk(KERN_ERR "%s unexpected state ep %p state %u\n",
+		WARN(1, "%s unexpected state ep %p state %u\n",
 			__func__, ep, ep->com.state);
-		WARN_ON(1);
 		abort = 0;
 	}
 	spin_unlock_irqrestore(&ep->com.lock, flags);
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 6cfd4d8..5de8696 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -151,9 +151,8 @@ static void stop_ep_timer(struct c4iw_ep *ep)
 {
 	PDBG("%s ep %p\n", __func__, ep);
 	if (!timer_pending(&ep->timer)) {
-		printk(KERN_ERR "%s timer stopped when its not running! "
+		WARN(1, "%s timer stopped when its not running! "
 		       "ep %p state %u\n", __func__, ep, ep->com.state);
-		WARN_ON(1);
 		return;
 	}
 	del_timer_sync(&ep->timer);
@@ -2551,9 +2550,8 @@ static void process_timeout(struct c4iw_ep *ep)
 		__state_set(&ep->com, ABORTING);
 		break;
 	default:
-		printk(KERN_ERR "%s unexpected state ep %p tid %u state %u\n",
+		WARN(1, "%s unexpected state ep %p tid %u state %u\n",
 			__func__, ep, ep->hwtid, ep->com.state);
-		WARN_ON(1);
 		abort = 0;
 	}
 	mutex_unlock(&ep->com.mutex);
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
index 2d41d04..89517ff 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -90,26 +90,6 @@
 
 static DEFINE_SPINLOCK(hcall_lock);
 
-static u32 get_longbusy_msecs(int longbusy_rc)
-{
-	switch (longbusy_rc) {
-	case H_LONG_BUSY_ORDER_1_MSEC:
-		return 1;
-	case H_LONG_BUSY_ORDER_10_MSEC:
-		return 10;
-	case H_LONG_BUSY_ORDER_100_MSEC:
-		return 100;
-	case H_LONG_BUSY_ORDER_1_SEC:
-		return 1000;
-	case H_LONG_BUSY_ORDER_10_SEC:
-		return 10000;
-	case H_LONG_BUSY_ORDER_100_SEC:
-		return 100000;
-	default:
-		return 1;
-	}
-}
-
 static long ehca_plpar_hcall_norets(unsigned long opcode,
 				    unsigned long arg1,
 				    unsigned long arg2,
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
index 49b09c6..be2a60e 100644
--- a/drivers/infiniband/hw/ipath/ipath_init_chip.c
+++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
@@ -719,16 +719,6 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
 		goto done;
 
 	/*
-	 * we ignore most issues after reporting them, but have to specially
-	 * handle hardware-disabled chips.
-	 */
-	if (ret == 2) {
-		/* unique error, known to ipath_init_one */
-		ret = -EPERM;
-		goto done;
-	}
-
-	/*
 	 * We could bump this to allow for full rcvegrcnt + rcvtidcnt,
 	 * but then it no longer nicely fits power of two, and since
 	 * we now use routines that backend onto __get_free_pages, the
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index c9eb6a6..ae67df3 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -66,7 +66,7 @@ static void mlx4_ib_cq_event(struct mlx4_cq *cq, enum mlx4_event type)
 
 static void *get_cqe_from_buf(struct mlx4_ib_cq_buf *buf, int n)
 {
-	return mlx4_buf_offset(&buf->buf, n * sizeof (struct mlx4_cqe));
+	return mlx4_buf_offset(&buf->buf, n * buf->entry_size);
 }
 
 static void *get_cqe(struct mlx4_ib_cq *cq, int n)
@@ -77,8 +77,9 @@ static void *get_cqe(struct mlx4_ib_cq *cq, int n)
 static void *get_sw_cqe(struct mlx4_ib_cq *cq, int n)
 {
 	struct mlx4_cqe *cqe = get_cqe(cq, n & cq->ibcq.cqe);
+	struct mlx4_cqe *tcqe = ((cq->buf.entry_size == 64) ? (cqe + 1) : cqe);
 
-	return (!!(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK) ^
+	return (!!(tcqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK) ^
 		!!(n & (cq->ibcq.cqe + 1))) ? NULL : cqe;
 }
 
@@ -99,12 +100,13 @@ static int mlx4_ib_alloc_cq_buf(struct mlx4_ib_dev *dev, struct mlx4_ib_cq_buf *
 {
 	int err;
 
-	err = mlx4_buf_alloc(dev->dev, nent * sizeof(struct mlx4_cqe),
+	err = mlx4_buf_alloc(dev->dev, nent * dev->dev->caps.cqe_size,
 			     PAGE_SIZE * 2, &buf->buf);
 
 	if (err)
 		goto out;
 
+	buf->entry_size = dev->dev->caps.cqe_size;
 	err = mlx4_mtt_init(dev->dev, buf->buf.npages, buf->buf.page_shift,
 				    &buf->mtt);
 	if (err)
@@ -120,8 +122,7 @@ err_mtt:
 	mlx4_mtt_cleanup(dev->dev, &buf->mtt);
 
 err_buf:
-	mlx4_buf_free(dev->dev, nent * sizeof(struct mlx4_cqe),
-			      &buf->buf);
+	mlx4_buf_free(dev->dev, nent * buf->entry_size, &buf->buf);
 
 out:
 	return err;
@@ -129,7 +130,7 @@ out:
 
 static void mlx4_ib_free_cq_buf(struct mlx4_ib_dev *dev, struct mlx4_ib_cq_buf *buf, int cqe)
 {
-	mlx4_buf_free(dev->dev, (cqe + 1) * sizeof(struct mlx4_cqe), &buf->buf);
+	mlx4_buf_free(dev->dev, (cqe + 1) * buf->entry_size, &buf->buf);
 }
 
 static int mlx4_ib_get_cq_umem(struct mlx4_ib_dev *dev, struct ib_ucontext *context,
@@ -137,8 +138,9 @@ static int mlx4_ib_get_cq_umem(struct mlx4_ib_dev *dev, struct ib_ucontext *cont
 			       u64 buf_addr, int cqe)
 {
 	int err;
+	int cqe_size = dev->dev->caps.cqe_size;
 
-	*umem = ib_umem_get(context, buf_addr, cqe * sizeof (struct mlx4_cqe),
+	*umem = ib_umem_get(context, buf_addr, cqe * cqe_size,
 			    IB_ACCESS_LOCAL_WRITE, 1);
 	if (IS_ERR(*umem))
 		return PTR_ERR(*umem);
@@ -331,16 +333,23 @@ static void mlx4_ib_cq_resize_copy_cqes(struct mlx4_ib_cq *cq)
 {
 	struct mlx4_cqe *cqe, *new_cqe;
 	int i;
+	int cqe_size = cq->buf.entry_size;
+	int cqe_inc = cqe_size == 64 ? 1 : 0;
 
 	i = cq->mcq.cons_index;
 	cqe = get_cqe(cq, i & cq->ibcq.cqe);
+	cqe += cqe_inc;
+
 	while ((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) != MLX4_CQE_OPCODE_RESIZE) {
 		new_cqe = get_cqe_from_buf(&cq->resize_buf->buf,
 					   (i + 1) & cq->resize_buf->cqe);
-		memcpy(new_cqe, get_cqe(cq, i & cq->ibcq.cqe), sizeof(struct mlx4_cqe));
+		memcpy(new_cqe, get_cqe(cq, i & cq->ibcq.cqe), cqe_size);
+		new_cqe += cqe_inc;
+
 		new_cqe->owner_sr_opcode = (cqe->owner_sr_opcode & ~MLX4_CQE_OWNER_MASK) |
 			(((i + 1) & (cq->resize_buf->cqe + 1)) ? MLX4_CQE_OWNER_MASK : 0);
 		cqe = get_cqe(cq, ++i & cq->ibcq.cqe);
+		cqe += cqe_inc;
 	}
 	++cq->mcq.cons_index;
 }
@@ -438,6 +447,7 @@ err_buf:
 
 out:
 	mutex_unlock(&cq->resize_mutex);
+
 	return err;
 }
 
@@ -586,6 +596,9 @@ repoll:
 	if (!cqe)
 		return -EAGAIN;
 
+	if (cq->buf.entry_size == 64)
+		cqe++;
+
 	++cq->mcq.cons_index;
 
 	/*
@@ -807,6 +820,7 @@ void __mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq)
 	int nfreed = 0;
 	struct mlx4_cqe *cqe, *dest;
 	u8 owner_bit;
+	int cqe_inc = cq->buf.entry_size == 64 ? 1 : 0;
 
 	/*
 	 * First we need to find the current producer index, so we
@@ -825,12 +839,16 @@ void __mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq)
 	 */
 	while ((int) --prod_index - (int) cq->mcq.cons_index >= 0) {
 		cqe = get_cqe(cq, prod_index & cq->ibcq.cqe);
+		cqe += cqe_inc;
+
 		if ((be32_to_cpu(cqe->vlan_my_qpn) & MLX4_CQE_QPN_MASK) == qpn) {
 			if (srq && !(cqe->owner_sr_opcode & MLX4_CQE_IS_SEND_MASK))
 				mlx4_ib_free_srq_wqe(srq, be16_to_cpu(cqe->wqe_index));
 			++nfreed;
 		} else if (nfreed) {
 			dest = get_cqe(cq, (prod_index + nfreed) & cq->ibcq.cqe);
+			dest += cqe_inc;
+
 			owner_bit = dest->owner_sr_opcode & MLX4_CQE_OWNER_MASK;
 			memcpy(dest, cqe, sizeof *cqe);
 			dest->owner_sr_opcode = owner_bit |
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 718ec6b..e7d81c0 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -563,15 +563,24 @@ static struct ib_ucontext *mlx4_ib_alloc_ucontext(struct ib_device *ibdev,
 {
 	struct mlx4_ib_dev *dev = to_mdev(ibdev);
 	struct mlx4_ib_ucontext *context;
+	struct mlx4_ib_alloc_ucontext_resp_v3 resp_v3;
 	struct mlx4_ib_alloc_ucontext_resp resp;
 	int err;
 
 	if (!dev->ib_active)
 		return ERR_PTR(-EAGAIN);
 
-	resp.qp_tab_size      = dev->dev->caps.num_qps;
-	resp.bf_reg_size      = dev->dev->caps.bf_reg_size;
-	resp.bf_regs_per_page = dev->dev->caps.bf_regs_per_page;
+	if (ibdev->uverbs_abi_ver == MLX4_IB_UVERBS_NO_DEV_CAPS_ABI_VERSION) {
+		resp_v3.qp_tab_size      = dev->dev->caps.num_qps;
+		resp_v3.bf_reg_size      = dev->dev->caps.bf_reg_size;
+		resp_v3.bf_regs_per_page = dev->dev->caps.bf_regs_per_page;
+	} else {
+		resp.dev_caps	      = dev->dev->caps.userspace_caps;
+		resp.qp_tab_size      = dev->dev->caps.num_qps;
+		resp.bf_reg_size      = dev->dev->caps.bf_reg_size;
+		resp.bf_regs_per_page = dev->dev->caps.bf_regs_per_page;
+		resp.cqe_size	      = dev->dev->caps.cqe_size;
+	}
 
 	context = kmalloc(sizeof *context, GFP_KERNEL);
 	if (!context)
@@ -586,7 +595,11 @@ static struct ib_ucontext *mlx4_ib_alloc_ucontext(struct ib_device *ibdev,
 	INIT_LIST_HEAD(&context->db_page_list);
 	mutex_init(&context->db_page_mutex);
 
-	err = ib_copy_to_udata(udata, &resp, sizeof resp);
+	if (ibdev->uverbs_abi_ver == MLX4_IB_UVERBS_NO_DEV_CAPS_ABI_VERSION)
+		err = ib_copy_to_udata(udata, &resp_v3, sizeof(resp_v3));
+	else
+		err = ib_copy_to_udata(udata, &resp, sizeof(resp));
+
 	if (err) {
 		mlx4_uar_free(to_mdev(ibdev)->dev, &context->uar);
 		kfree(context);
@@ -1342,7 +1355,11 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
 	ibdev->ib_dev.num_comp_vectors	= dev->caps.num_comp_vectors;
 	ibdev->ib_dev.dma_device	= &dev->pdev->dev;
 
-	ibdev->ib_dev.uverbs_abi_ver	= MLX4_IB_UVERBS_ABI_VERSION;
+	if (dev->caps.userspace_caps)
+		ibdev->ib_dev.uverbs_abi_ver = MLX4_IB_UVERBS_ABI_VERSION;
+	else
+		ibdev->ib_dev.uverbs_abi_ver = MLX4_IB_UVERBS_NO_DEV_CAPS_ABI_VERSION;
+
 	ibdev->ib_dev.uverbs_cmd_mask	=
 		(1ull << IB_USER_VERBS_CMD_GET_CONTEXT)		|
 		(1ull << IB_USER_VERBS_CMD_QUERY_DEVICE)	|
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index e04cbc9..dcd845b 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -90,6 +90,7 @@ struct mlx4_ib_xrcd {
 struct mlx4_ib_cq_buf {
 	struct mlx4_buf		buf;
 	struct mlx4_mtt		mtt;
+	int			entry_size;
 };
 
 struct mlx4_ib_cq_resize {
diff --git a/drivers/infiniband/hw/mlx4/user.h b/drivers/infiniband/hw/mlx4/user.h
index 13beede..07e6769 100644
--- a/drivers/infiniband/hw/mlx4/user.h
+++ b/drivers/infiniband/hw/mlx4/user.h
@@ -40,7 +40,9 @@
  * Increment this value if any changes that break userspace ABI
  * compatibility are made.
  */
-#define MLX4_IB_UVERBS_ABI_VERSION	3
+
+#define MLX4_IB_UVERBS_NO_DEV_CAPS_ABI_VERSION	3
+#define MLX4_IB_UVERBS_ABI_VERSION		4
 
 /*
  * Make sure that all structs defined in this file remain laid out so
@@ -50,10 +52,18 @@
  * instead.
  */
 
+struct mlx4_ib_alloc_ucontext_resp_v3 {
+	__u32	qp_tab_size;
+	__u16	bf_reg_size;
+	__u16	bf_regs_per_page;
+};
+
 struct mlx4_ib_alloc_ucontext_resp {
+	__u32	dev_caps;
 	__u32	qp_tab_size;
 	__u16	bf_reg_size;
 	__u16	bf_regs_per_page;
+	__u32	cqe_size;
 };
 
 struct mlx4_ib_alloc_pd_resp {
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index cfaacaf..feb41e7 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -629,11 +629,9 @@ static void build_rdma0_msg(struct nes_cm_node *cm_node, struct nes_qp **nesqp_a
 
 	case SEND_RDMA_READ_ZERO:
 	default:
-		if (cm_node->send_rdma0_op != SEND_RDMA_READ_ZERO) {
-			printk(KERN_ERR "%s[%u]: Unsupported RDMA0 len operation=%u\n",
-				 __func__, __LINE__, cm_node->send_rdma0_op);
-			WARN_ON(1);
-		}
+		if (cm_node->send_rdma0_op != SEND_RDMA_READ_ZERO)
+			WARN(1, "Unsupported RDMA0 len operation=%u\n",
+			     cm_node->send_rdma0_op);
 		nes_debug(NES_DBG_CM, "Sending first rdma operation.\n");
 		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
 			cpu_to_le32(NES_IWARP_SQ_OP_RDMAR);
diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c
index 3ba7be3..4166452 100644
--- a/drivers/infiniband/hw/nes/nes_mgt.c
+++ b/drivers/infiniband/hw/nes/nes_mgt.c
@@ -210,6 +210,9 @@ static struct sk_buff *nes_get_next_skb(struct nes_device *nesdev, struct nes_qp
 	}
 
 	while (1) {
+		if (skb_queue_empty(&nesqp->pau_list))
+			goto out;
+
 		seq = nes_get_seq(skb, ack, wnd, fin_rcvd, rst_rcvd);
 		if (seq == nextseq) {
 			if (skb->len || processacks)
@@ -218,14 +221,13 @@ static struct sk_buff *nes_get_next_skb(struct nes_device *nesdev, struct nes_qp
 			goto out;
 		}
 
-		if (skb->next == (struct sk_buff *)&nesqp->pau_list)
-			goto out;
-
 		old_skb = skb;
 		skb = skb->next;
 		skb_unlink(old_skb, &nesqp->pau_list);
 		nes_mgt_free_skb(nesdev, old_skb, PCI_DMA_TODEVICE);
 		nes_rem_ref_cm_node(nesqp->cm_node);
+		if (skb == (struct sk_buff *)&nesqp->pau_list)
+			goto out;
 	}
 	return skb;
 
@@ -245,7 +247,6 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
 	struct nes_rskb_cb *cb;
 	struct pau_fpdu_info *fpdu_info = NULL;
 	struct pau_fpdu_frag frags[MAX_FPDU_FRAGS];
-	unsigned long flags;
 	u32 fpdu_len = 0;
 	u32 tmp_len;
 	int frag_cnt = 0;
@@ -260,12 +261,10 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
 
 	*pau_fpdu_info = NULL;
 
-	spin_lock_irqsave(&nesqp->pau_lock, flags);
 	skb = nes_get_next_skb(nesdev, nesqp, NULL, nesqp->pau_rcv_nxt, &ack, &wnd, &fin_rcvd, &rst_rcvd);
-	if (!skb) {
-		spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+	if (!skb)
 		goto out;
-	}
+
 	cb = (struct nes_rskb_cb *)&skb->cb[0];
 	if (skb->len) {
 		fpdu_len = be16_to_cpu(*(__be16 *) skb->data) + MPA_FRAMING;
@@ -290,10 +289,9 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
 
 			skb = nes_get_next_skb(nesdev, nesqp, skb,
 					       nesqp->pau_rcv_nxt + frag_tot, &ack, &wnd, &fin_rcvd, &rst_rcvd);
-			if (!skb) {
-				spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+			if (!skb)
 				goto out;
-			} else if (rst_rcvd) {
+			if (rst_rcvd) {
 				/* rst received in the middle of fpdu */
 				for (; i >= 0; i--) {
 					skb_unlink(frags[i].skb, &nesqp->pau_list);
@@ -320,8 +318,6 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
 		frag_cnt = 1;
 	}
 
-	spin_unlock_irqrestore(&nesqp->pau_lock, flags);
-
 	/* Found one */
 	fpdu_info = kzalloc(sizeof(*fpdu_info), GFP_ATOMIC);
 	if (fpdu_info == NULL) {
@@ -383,9 +379,8 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
 
 		if (frags[i].skb->len == 0) {
 			/* Pull skb off the list - it will be freed in the callback */
-			spin_lock_irqsave(&nesqp->pau_lock, flags);
-			skb_unlink(frags[i].skb, &nesqp->pau_list);
-			spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+			if (!skb_queue_empty(&nesqp->pau_list))
+				skb_unlink(frags[i].skb, &nesqp->pau_list);
 		} else {
 			/* Last skb still has data so update the seq */
 			iph = (struct iphdr *)(cb->data_start + ETH_HLEN);
@@ -414,14 +409,18 @@ static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
 	struct pau_fpdu_info *fpdu_info;
 	struct nes_hw_cqp_wqe *cqp_wqe;
 	struct nes_cqp_request *cqp_request;
+	unsigned long flags;
 	u64 u64tmp;
 	u32 u32tmp;
 	int rc;
 
 	while (1) {
+		spin_lock_irqsave(&nesqp->pau_lock, flags);
 		rc = get_fpdu_info(nesdev, nesqp, &fpdu_info);
-		if (fpdu_info == NULL)
+		if (rc || (fpdu_info == NULL)) {
+			spin_unlock_irqrestore(&nesqp->pau_lock, flags);
 			return rc;
+		}
 
 		cqp_request = fpdu_info->cqp_request;
 		cqp_wqe = &cqp_request->cqp_wqe;
@@ -447,7 +446,7 @@ static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
 		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX,
 				    lower_32_bits(u64tmp));
 		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_HIGH_IDX,
-				    upper_32_bits(u64tmp >> 32));
+				    upper_32_bits(u64tmp));
 
 		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX,
 				    lower_32_bits(fpdu_info->frags[0].physaddr));
@@ -475,6 +474,7 @@ static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
 
 		atomic_set(&cqp_request->refcount, 1);
 		nes_post_cqp_request(nesdev, cqp_request);
+		spin_unlock_irqrestore(&nesqp->pau_lock, flags);
 	}
 
 	return 0;
@@ -649,11 +649,9 @@ static void nes_chg_qh_handler(struct nes_device *nesdev, struct nes_cqp_request
 	nesqp = qh_chg->nesqp;
 
 	/* Should we handle the bad completion */
-	if (cqp_request->major_code) {
-		printk(KERN_ERR PFX "Invalid cqp_request major_code=0x%x\n",
+	if (cqp_request->major_code)
+		WARN(1, PFX "Invalid cqp_request major_code=0x%x\n",
 		       cqp_request->major_code);
-		WARN_ON(1);
-	}
 
 	switch (nesqp->pau_state) {
 	case PAU_DEL_QH:
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index 0564be7..9542e16 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -944,12 +944,13 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
 					  addr,
 					  perfect_filter_register_address+(mc_index * 8),
 					  mc_nic_index);
-				macaddr_high  = ((u16) addr[0]) << 8;
-				macaddr_high += (u16) addr[1];
-				macaddr_low   = ((u32) addr[2]) << 24;
-				macaddr_low  += ((u32) addr[3]) << 16;
-				macaddr_low  += ((u32) addr[4]) << 8;
-				macaddr_low  += (u32) addr[5];
+				macaddr_high  = ((u8) addr[0]) << 8;
+				macaddr_high += (u8) addr[1];
+				macaddr_low   = ((u8) addr[2]) << 24;
+				macaddr_low  += ((u8) addr[3]) << 16;
+				macaddr_low  += ((u8) addr[4]) << 8;
+				macaddr_low  += (u8) addr[5];
+
 				nes_write_indexed(nesdev,
 						perfect_filter_register_address+(mc_index * 8),
 						macaddr_low);
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index cf23c46..c09d41b 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -1269,7 +1269,6 @@ static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch)
 		return ioctx;
 
 	BUG_ON(ioctx->ch != ch);
-	kref_init(&ioctx->kref);
 	spin_lock_init(&ioctx->spinlock);
 	ioctx->state = SRPT_STATE_NEW;
 	ioctx->n_rbuf = 0;
@@ -1291,39 +1290,6 @@ static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch)
 }
 
 /**
- * srpt_put_send_ioctx() - Free up resources.
- */
-static void srpt_put_send_ioctx(struct srpt_send_ioctx *ioctx)
-{
-	struct srpt_rdma_ch *ch;
-	unsigned long flags;
-
-	BUG_ON(!ioctx);
-	ch = ioctx->ch;
-	BUG_ON(!ch);
-
-	WARN_ON(srpt_get_cmd_state(ioctx) != SRPT_STATE_DONE);
-
-	srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx);
-	transport_generic_free_cmd(&ioctx->cmd, 0);
-
-	if (ioctx->n_rbuf > 1) {
-		kfree(ioctx->rbufs);
-		ioctx->rbufs = NULL;
-		ioctx->n_rbuf = 0;
-	}
-
-	spin_lock_irqsave(&ch->spinlock, flags);
-	list_add(&ioctx->free_list, &ch->free_list);
-	spin_unlock_irqrestore(&ch->spinlock, flags);
-}
-
-static void srpt_put_send_ioctx_kref(struct kref *kref)
-{
-	srpt_put_send_ioctx(container_of(kref, struct srpt_send_ioctx, kref));
-}
-
-/**
  * srpt_abort_cmd() - Abort a SCSI command.
  * @ioctx:   I/O context associated with the SCSI command.
  * @context: Preferred execution context.
@@ -1359,8 +1325,14 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx)
 	}
 	spin_unlock_irqrestore(&ioctx->spinlock, flags);
 
-	if (state == SRPT_STATE_DONE)
+	if (state == SRPT_STATE_DONE) {
+		struct srpt_rdma_ch *ch = ioctx->ch;
+
+		BUG_ON(ch->sess == NULL);
+
+		target_put_sess_cmd(ch->sess, &ioctx->cmd);
 		goto out;
+	}
 
 	pr_debug("Aborting cmd with state %d and tag %lld\n", state,
 		 ioctx->tag);
@@ -1395,11 +1367,11 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx)
 		spin_lock_irqsave(&ioctx->cmd.t_state_lock, flags);
 		ioctx->cmd.transport_state |= CMD_T_LUN_STOP;
 		spin_unlock_irqrestore(&ioctx->cmd.t_state_lock, flags);
-		kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
+		target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd);
 		break;
 	case SRPT_STATE_MGMT_RSP_SENT:
 		srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
-		kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
+		target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd);
 		break;
 	default:
 		WARN_ON("ERROR: unexpected command state");
@@ -1457,11 +1429,13 @@ static void srpt_handle_send_comp(struct srpt_rdma_ch *ch,
 		    && state != SRPT_STATE_DONE))
 		pr_debug("state = %d\n", state);
 
-	if (state != SRPT_STATE_DONE)
-		kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
-	else
+	if (state != SRPT_STATE_DONE) {
+		srpt_unmap_sg_to_ib_sge(ch, ioctx);
+		transport_generic_free_cmd(&ioctx->cmd, 0);
+	} else {
 		printk(KERN_ERR "IB completion has been received too late for"
 		       " wr_id = %u.\n", ioctx->ioctx.index);
+	}
 }
 
 /**
@@ -1712,10 +1686,10 @@ out_err:
 
 static int srpt_check_stop_free(struct se_cmd *cmd)
 {
-	struct srpt_send_ioctx *ioctx;
+	struct srpt_send_ioctx *ioctx = container_of(cmd,
+				struct srpt_send_ioctx, cmd);
 
-	ioctx = container_of(cmd, struct srpt_send_ioctx, cmd);
-	return kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
+	return target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd);
 }
 
 /**
@@ -1730,12 +1704,12 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch,
 	uint64_t unpacked_lun;
 	u64 data_len;
 	enum dma_data_direction dir;
-	int ret;
+	sense_reason_t ret;
+	int rc;
 
 	BUG_ON(!send_ioctx);
 
 	srp_cmd = recv_ioctx->ioctx.buf;
-	kref_get(&send_ioctx->kref);
 	cmd = &send_ioctx->cmd;
 	send_ioctx->tag = srp_cmd->tag;
 
@@ -1755,40 +1729,26 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch,
 		break;
 	}
 
-	ret = srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len);
-	if (ret) {
+	if (srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len)) {
 		printk(KERN_ERR "0x%llx: parsing SRP descriptor table failed.\n",
 		       srp_cmd->tag);
-		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
+		ret = TCM_INVALID_CDB_FIELD;
 		goto send_sense;
 	}
 
-	cmd->data_length = data_len;
-	cmd->data_direction = dir;
 	unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun,
 				       sizeof(srp_cmd->lun));
-	if (transport_lookup_cmd_lun(cmd, unpacked_lun) < 0) {
-		kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
+	rc = target_submit_cmd(cmd, ch->sess, srp_cmd->cdb,
+			&send_ioctx->sense_data[0], unpacked_lun, data_len,
+			MSG_SIMPLE_TAG, dir, TARGET_SCF_ACK_KREF);
+	if (rc != 0) {
+		ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 		goto send_sense;
 	}
-	ret = target_setup_cmd_from_cdb(cmd, srp_cmd->cdb);
-	if (ret < 0) {
-		kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
-		if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT) {
-			srpt_queue_status(cmd);
-			return 0;
-		} else
-			goto send_sense;
-	}
-
-	transport_handle_cdb_direct(cmd);
 	return 0;
 
 send_sense:
-	transport_send_check_condition_and_sense(cmd, cmd->scsi_sense_reason,
-						 0);
+	transport_send_check_condition_and_sense(cmd, ret, 0);
 	return -1;
 }
 
@@ -1865,9 +1825,11 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
 {
 	struct srp_tsk_mgmt *srp_tsk;
 	struct se_cmd *cmd;
+	struct se_session *sess = ch->sess;
 	uint64_t unpacked_lun;
+	uint32_t tag = 0;
 	int tcm_tmr;
-	int res;
+	int rc;
 
 	BUG_ON(!send_ioctx);
 
@@ -1882,39 +1844,32 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
 	send_ioctx->tag = srp_tsk->tag;
 	tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func);
 	if (tcm_tmr < 0) {
-		send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
 		send_ioctx->cmd.se_tmr_req->response =
 			TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED;
-		goto process_tmr;
-	}
-	res = core_tmr_alloc_req(cmd, NULL, tcm_tmr, GFP_KERNEL);
-	if (res < 0) {
-		send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED;
-		goto process_tmr;
+		goto fail;
 	}
-
 	unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun,
 				       sizeof(srp_tsk->lun));
-	res = transport_lookup_tmr_lun(&send_ioctx->cmd, unpacked_lun);
-	if (res) {
-		pr_debug("rejecting TMR for LUN %lld\n", unpacked_lun);
-		send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		send_ioctx->cmd.se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
-		goto process_tmr;
-	}
-
-	if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK)
-		srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag);
-
-process_tmr:
-	kref_get(&send_ioctx->kref);
-	if (!(send_ioctx->cmd.se_cmd_flags & SCF_SCSI_CDB_EXCEPTION))
-		transport_generic_handle_tmr(&send_ioctx->cmd);
-	else
-		transport_send_check_condition_and_sense(cmd,
-						cmd->scsi_sense_reason, 0);
 
+	if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK) {
+		rc = srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag);
+		if (rc < 0) {
+			send_ioctx->cmd.se_tmr_req->response =
+					TMR_TASK_DOES_NOT_EXIST;
+			goto fail;
+		}
+		tag = srp_tsk->task_tag;
+	}
+	rc = target_submit_tmr(&send_ioctx->cmd, sess, NULL, unpacked_lun,
+				srp_tsk, tcm_tmr, GFP_KERNEL, tag,
+				TARGET_SCF_ACK_KREF);
+	if (rc != 0) {
+		send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED;
+		goto fail;
+	}
+	return;
+fail:
+	transport_send_check_condition_and_sense(cmd, 0, 0); // XXX:
 }
 
 /**
@@ -1956,10 +1911,6 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
 		}
 	}
 
-	transport_init_se_cmd(&send_ioctx->cmd, &srpt_target->tf_ops, ch->sess,
-			      0, DMA_NONE, MSG_SIMPLE_TAG,
-			      send_ioctx->sense_data);
-
 	switch (srp_cmd->opcode) {
 	case SRP_CMD:
 		srpt_handle_cmd(ch, recv_ioctx, send_ioctx);
@@ -2365,6 +2316,7 @@ static void srpt_release_channel_work(struct work_struct *w)
 {
 	struct srpt_rdma_ch *ch;
 	struct srpt_device *sdev;
+	struct se_session *se_sess;
 
 	ch = container_of(w, struct srpt_rdma_ch, release_work);
 	pr_debug("ch = %p; ch->sess = %p; release_done = %p\n", ch, ch->sess,
@@ -2373,8 +2325,13 @@ static void srpt_release_channel_work(struct work_struct *w)
 	sdev = ch->sport->sdev;
 	BUG_ON(!sdev);
 
-	transport_deregister_session_configfs(ch->sess);
-	transport_deregister_session(ch->sess);
+	se_sess = ch->sess;
+	BUG_ON(!se_sess);
+
+	target_wait_for_sess_cmds(se_sess, 0);
+
+	transport_deregister_session_configfs(se_sess);
+	transport_deregister_session(se_sess);
 	ch->sess = NULL;
 
 	srpt_destroy_ch_ib(ch);
@@ -3099,7 +3056,7 @@ static int srpt_queue_response(struct se_cmd *cmd)
 		       ioctx->tag);
 		srpt_unmap_sg_to_ib_sge(ch, ioctx);
 		srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
-		kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
+		target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd);
 	}
 
 out:
@@ -3490,6 +3447,23 @@ static u32 srpt_tpg_get_inst_index(struct se_portal_group *se_tpg)
 
 static void srpt_release_cmd(struct se_cmd *se_cmd)
 {
+	struct srpt_send_ioctx *ioctx = container_of(se_cmd,
+				struct srpt_send_ioctx, cmd);
+	struct srpt_rdma_ch *ch = ioctx->ch;
+	unsigned long flags;
+
+	WARN_ON(ioctx->state != SRPT_STATE_DONE);
+	WARN_ON(ioctx->mapped_sg_count != 0);
+
+	if (ioctx->n_rbuf > 1) {
+		kfree(ioctx->rbufs);
+		ioctx->rbufs = NULL;
+		ioctx->n_rbuf = 0;
+	}
+
+	spin_lock_irqsave(&ch->spinlock, flags);
+	list_add(&ioctx->free_list, &ch->free_list);
+	spin_unlock_irqrestore(&ch->spinlock, flags);
 }
 
 /**
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h
index 61e52b8..4caf55c 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.h
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.h
@@ -228,7 +228,6 @@ struct srpt_recv_ioctx {
 struct srpt_send_ioctx {
 	struct srpt_ioctx	ioctx;
 	struct srpt_rdma_ch	*ch;
-	struct kref		 kref;
 	struct rdma_iu		*rdma_ius;
 	struct srp_direct_buf	*rbufs;
 	struct srp_direct_buf	single_rbuf;
diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
index daceafe..fa7a95c 100644
--- a/drivers/input/gameport/emu10k1-gp.c
+++ b/drivers/input/gameport/emu10k1-gp.c
@@ -57,7 +57,7 @@ static const struct pci_device_id emu_tbl[] = {
 
 MODULE_DEVICE_TABLE(pci, emu_tbl);
 
-static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct emu *emu;
 	struct gameport *port;
@@ -107,7 +107,7 @@ static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id
 	return error;
 }
 
-static void __devexit emu_remove(struct pci_dev *pdev)
+static void emu_remove(struct pci_dev *pdev)
 {
 	struct emu *emu = pci_get_drvdata(pdev);
 
@@ -122,7 +122,7 @@ static struct pci_driver emu_driver = {
         .name =         "Emu10k1_gameport",
         .id_table =     emu_tbl,
         .probe =        emu_probe,
-        .remove =       __devexit_p(emu_remove),
+	.remove =	emu_remove,
 };
 
 module_pci_driver(emu_driver);
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
index 48ad382..ae912d3 100644
--- a/drivers/input/gameport/fm801-gp.c
+++ b/drivers/input/gameport/fm801-gp.c
@@ -78,7 +78,7 @@ static int fm801_gp_open(struct gameport *gameport, int mode)
 	return 0;
 }
 
-static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device_id *id)
+static int fm801_gp_probe(struct pci_dev *pci, const struct pci_device_id *id)
 {
 	struct fm801_gp *gp;
 	struct gameport *port;
@@ -129,7 +129,7 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device
 	return error;
 }
 
-static void __devexit fm801_gp_remove(struct pci_dev *pci)
+static void fm801_gp_remove(struct pci_dev *pci)
 {
 	struct fm801_gp *gp = pci_get_drvdata(pci);
 
@@ -150,7 +150,7 @@ static struct pci_driver fm801_gp_driver = {
 	.name =		"FM801_gameport",
 	.id_table =	fm801_gp_id_table,
 	.probe =	fm801_gp_probe,
-	.remove =	__devexit_p(fm801_gp_remove),
+	.remove =	fm801_gp_remove,
 };
 
 module_pci_driver(fm801_gp_driver);
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index 1abbc17..47a6009 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -194,7 +194,7 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
 	if (!mt)
 		return;
 
-	oldest = 0;
+	oldest = NULL;
 	oldid = mt->trkid;
 	count = 0;
 
@@ -251,7 +251,7 @@ void input_mt_sync_frame(struct input_dev *dev)
 
 	if (mt->flags & INPUT_MT_DROP_UNUSED) {
 		for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
-			if (s->frame == mt->frame)
+			if (input_mt_is_used(mt, s))
 				continue;
 			input_mt_slot(dev, s - mt->slots);
 			input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 53a0dde..ce01332f 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -534,8 +534,11 @@ EXPORT_SYMBOL(input_grab_device);
 static void __input_release_device(struct input_handle *handle)
 {
 	struct input_dev *dev = handle->dev;
+	struct input_handle *grabber;
 
-	if (dev->grab == handle) {
+	grabber = rcu_dereference_protected(dev->grab,
+					    lockdep_is_held(&dev->mutex));
+	if (grabber == handle) {
 		rcu_assign_pointer(dev->grab, NULL);
 		/* Make sure input_pass_event() notices that grab is gone */
 		synchronize_rcu();
@@ -1723,7 +1726,7 @@ EXPORT_SYMBOL_GPL(input_class);
 /**
  * input_allocate_device - allocate memory for new input device
  *
- * Returns prepared struct input_dev or NULL.
+ * Returns prepared struct input_dev or %NULL.
  *
  * NOTE: Use input_free_device() to free devices that have not been
  * registered; input_unregister_device() should be used for already
@@ -1750,6 +1753,70 @@ struct input_dev *input_allocate_device(void)
 }
 EXPORT_SYMBOL(input_allocate_device);
 
+struct input_devres {
+	struct input_dev *input;
+};
+
+static int devm_input_device_match(struct device *dev, void *res, void *data)
+{
+	struct input_devres *devres = res;
+
+	return devres->input == data;
+}
+
+static void devm_input_device_release(struct device *dev, void *res)
+{
+	struct input_devres *devres = res;
+	struct input_dev *input = devres->input;
+
+	dev_dbg(dev, "%s: dropping reference to %s\n",
+		__func__, dev_name(&input->dev));
+	input_put_device(input);
+}
+
+/**
+ * devm_input_allocate_device - allocate managed input device
+ * @dev: device owning the input device being created
+ *
+ * Returns prepared struct input_dev or %NULL.
+ *
+ * Managed input devices do not need to be explicitly unregistered or
+ * freed as it will be done automatically when owner device unbinds from
+ * its driver (or binding fails). Once managed input device is allocated,
+ * it is ready to be set up and registered in the same fashion as regular
+ * input device. There are no special devm_input_device_[un]register()
+ * variants, regular ones work with both managed and unmanaged devices.
+ *
+ * NOTE: the owner device is set up as parent of input device and users
+ * should not override it.
+ */
+
+struct input_dev *devm_input_allocate_device(struct device *dev)
+{
+	struct input_dev *input;
+	struct input_devres *devres;
+
+	devres = devres_alloc(devm_input_device_release,
+			      sizeof(struct input_devres), GFP_KERNEL);
+	if (!devres)
+		return NULL;
+
+	input = input_allocate_device();
+	if (!input) {
+		devres_free(devres);
+		return NULL;
+	}
+
+	input->dev.parent = dev;
+	input->devres_managed = true;
+
+	devres->input = input;
+	devres_add(dev, devres);
+
+	return input;
+}
+EXPORT_SYMBOL(devm_input_allocate_device);
+
 /**
  * input_free_device - free memory occupied by input_dev structure
  * @dev: input device to free
@@ -1766,8 +1833,14 @@ EXPORT_SYMBOL(input_allocate_device);
  */
 void input_free_device(struct input_dev *dev)
 {
-	if (dev)
+	if (dev) {
+		if (dev->devres_managed)
+			WARN_ON(devres_destroy(dev->dev.parent,
+						devm_input_device_release,
+						devm_input_device_match,
+						dev));
 		input_put_device(dev);
+	}
 }
 EXPORT_SYMBOL(input_free_device);
 
@@ -1888,6 +1961,38 @@ static void input_cleanse_bitmasks(struct input_dev *dev)
 	INPUT_CLEANSE_BITMASK(dev, SW, sw);
 }
 
+static void __input_unregister_device(struct input_dev *dev)
+{
+	struct input_handle *handle, *next;
+
+	input_disconnect_device(dev);
+
+	mutex_lock(&input_mutex);
+
+	list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
+		handle->handler->disconnect(handle);
+	WARN_ON(!list_empty(&dev->h_list));
+
+	del_timer_sync(&dev->timer);
+	list_del_init(&dev->node);
+
+	input_wakeup_procfs_readers();
+
+	mutex_unlock(&input_mutex);
+
+	device_del(&dev->dev);
+}
+
+static void devm_input_device_unregister(struct device *dev, void *res)
+{
+	struct input_devres *devres = res;
+	struct input_dev *input = devres->input;
+
+	dev_dbg(dev, "%s: unregistering device %s\n",
+		__func__, dev_name(&input->dev));
+	__input_unregister_device(input);
+}
+
 /**
  * input_register_device - register device with input core
  * @dev: device to be registered
@@ -1903,11 +2008,21 @@ static void input_cleanse_bitmasks(struct input_dev *dev)
 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;
 	const char *path;
 	int error;
 
+	if (dev->devres_managed) {
+		devres = devres_alloc(devm_input_device_unregister,
+				      sizeof(struct input_devres), GFP_KERNEL);
+		if (!devres)
+			return -ENOMEM;
+
+		devres->input = dev;
+	}
+
 	/* Every input device generates EV_SYN/SYN_REPORT events. */
 	__set_bit(EV_SYN, dev->evbit);
 
@@ -1923,8 +2038,10 @@ int input_register_device(struct input_dev *dev)
 
 	dev->max_vals = max(dev->hint_events_per_packet, packet_size) + 2;
 	dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL);
-	if (!dev->vals)
-		return -ENOMEM;
+	if (!dev->vals) {
+		error = -ENOMEM;
+		goto err_devres_free;
+	}
 
 	/*
 	 * If delay and period are pre-set by the driver, then autorepeating
@@ -1949,7 +2066,7 @@ int input_register_device(struct input_dev *dev)
 
 	error = device_add(&dev->dev);
 	if (error)
-		return error;
+		goto err_free_vals;
 
 	path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
 	pr_info("%s as %s\n",
@@ -1958,10 +2075,8 @@ int input_register_device(struct input_dev *dev)
 	kfree(path);
 
 	error = mutex_lock_interruptible(&input_mutex);
-	if (error) {
-		device_del(&dev->dev);
-		return error;
-	}
+	if (error)
+		goto err_device_del;
 
 	list_add_tail(&dev->node, &input_dev_list);
 
@@ -1972,7 +2087,21 @@ int input_register_device(struct input_dev *dev)
 
 	mutex_unlock(&input_mutex);
 
+	if (dev->devres_managed) {
+		dev_dbg(dev->dev.parent, "%s: registering %s with devres.\n",
+			__func__, dev_name(&dev->dev));
+		devres_add(dev->dev.parent, devres);
+	}
 	return 0;
+
+err_device_del:
+	device_del(&dev->dev);
+err_free_vals:
+	kfree(dev->vals);
+	dev->vals = NULL;
+err_devres_free:
+	devres_free(devres);
+	return error;
 }
 EXPORT_SYMBOL(input_register_device);
 
@@ -1985,24 +2114,20 @@ EXPORT_SYMBOL(input_register_device);
  */
 void input_unregister_device(struct input_dev *dev)
 {
-	struct input_handle *handle, *next;
-
-	input_disconnect_device(dev);
-
-	mutex_lock(&input_mutex);
-
-	list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
-		handle->handler->disconnect(handle);
-	WARN_ON(!list_empty(&dev->h_list));
-
-	del_timer_sync(&dev->timer);
-	list_del_init(&dev->node);
-
-	input_wakeup_procfs_readers();
-
-	mutex_unlock(&input_mutex);
-
-	device_unregister(&dev->dev);
+	if (dev->devres_managed) {
+		WARN_ON(devres_destroy(dev->dev.parent,
+					devm_input_device_unregister,
+					devm_input_device_match,
+					dev));
+		__input_unregister_device(dev);
+		/*
+		 * We do not do input_put_device() here because it will be done
+		 * when 2nd devres fires up.
+		 */
+	} else {
+		__input_unregister_device(dev);
+		input_put_device(dev);
+	}
 }
 EXPORT_SYMBOL(input_unregister_device);
 
diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c
index c96653b..121cd63 100644
--- a/drivers/input/joystick/as5011.c
+++ b/drivers/input/joystick/as5011.c
@@ -85,7 +85,10 @@ static int as5011_i2c_write(struct i2c_client *client,
 {
 	uint8_t data[2] = { aregaddr, avalue };
 	struct i2c_msg msg = {
-		client->addr, I2C_M_IGNORE_NAK, 2, (uint8_t *)data
+		.addr = client->addr,
+		.flags = I2C_M_IGNORE_NAK,
+		.len = 2,
+		.buf = (uint8_t *)data
 	};
 	int error;
 
@@ -98,8 +101,18 @@ static int as5011_i2c_read(struct i2c_client *client,
 {
 	uint8_t data[2] = { aregaddr };
 	struct i2c_msg msg_set[2] = {
-		{ client->addr, I2C_M_REV_DIR_ADDR, 1, (uint8_t *)data },
-		{ client->addr, I2C_M_RD | I2C_M_NOSTART, 1, (uint8_t *)data }
+		{
+			.addr = client->addr,
+			.flags = I2C_M_REV_DIR_ADDR,
+			.len = 1,
+			.buf = (uint8_t *)data
+		},
+		{
+			.addr = client->addr,
+			.flags = I2C_M_RD | I2C_M_NOSTART,
+			.len = 1,
+			.buf = (uint8_t *)data
+		}
 	};
 	int error;
 
@@ -144,7 +157,7 @@ out:
 	return IRQ_HANDLED;
 }
 
-static int __devinit as5011_configure_chip(struct as5011_device *as5011,
+static int as5011_configure_chip(struct as5011_device *as5011,
 				const struct as5011_platform_data *plat_dat)
 {
 	struct i2c_client *client = as5011->i2c_client;
@@ -212,8 +225,8 @@ static int __devinit as5011_configure_chip(struct as5011_device *as5011,
 	return 0;
 }
 
-static int __devinit as5011_probe(struct i2c_client *client,
-				const struct i2c_device_id *id)
+static int as5011_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
 {
 	const struct as5011_platform_data *plat_data;
 	struct as5011_device *as5011;
@@ -328,7 +341,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit as5011_remove(struct i2c_client *client)
+static int as5011_remove(struct i2c_client *client)
 {
 	struct as5011_device *as5011 = i2c_get_clientdata(client);
 
@@ -353,7 +366,7 @@ static struct i2c_driver as5011_driver = {
 		.name = "as5011",
 	},
 	.probe		= as5011_probe,
-	.remove		= __devexit_p(as5011_remove),
+	.remove		= as5011_remove,
 	.id_table	= as5011_id,
 };
 
diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c
index 77cfde5..59c10ec 100644
--- a/drivers/input/joystick/maplecontrol.c
+++ b/drivers/input/joystick/maplecontrol.c
@@ -78,7 +78,7 @@ static void dc_pad_close(struct input_dev *dev)
 }
 
 /* allow the controller to be used */
-static int __devinit probe_maple_controller(struct device *dev)
+static int probe_maple_controller(struct device *dev)
 {
 	static const short btn_bit[32] = {
 		BTN_C, BTN_B, BTN_A, BTN_START, -1, -1, -1, -1,
@@ -157,7 +157,7 @@ fail:
 	return error;
 }
 
-static int __devexit remove_maple_controller(struct device *dev)
+static int remove_maple_controller(struct device *dev)
 {
 	struct maple_device *mdev = to_maple_dev(dev);
 	struct dc_pad *pad = maple_get_drvdata(mdev);
@@ -175,7 +175,7 @@ static struct maple_driver dc_pad_driver = {
 	.drv = {
 		.name	= "Dreamcast_controller",
 		.probe	= probe_maple_controller,
-		.remove	= __devexit_p(remove_maple_controller),
+		.remove	= remove_maple_controller,
 	},
 };
 
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index de08740..7ccd652 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -134,7 +134,7 @@ config KEYBOARD_QT1070
 
 config KEYBOARD_QT2160
 	tristate "Atmel AT42QT2160 Touch Sensor Chip"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for Atmel AT42QT2160 Touch
 	  Sensor chip as a keyboard input.
@@ -409,7 +409,7 @@ config KEYBOARD_NEWTON
 
 config KEYBOARD_NOMADIK
 	tristate "ST-Ericsson Nomadik SKE keyboard"
-	depends on PLAT_NOMADIK
+	depends on (ARCH_NOMADIK || ARCH_U8500)
 	select INPUT_MATRIXKMAP
 	help
 	  Say Y here if you want to use a keypad provided on the SKE controller
diff --git a/drivers/input/keyboard/adp5520-keys.c b/drivers/input/keyboard/adp5520-keys.c
index e9e8674..ef26b17 100644
--- a/drivers/input/keyboard/adp5520-keys.c
+++ b/drivers/input/keyboard/adp5520-keys.c
@@ -69,7 +69,7 @@ static int adp5520_keys_notifier(struct notifier_block *nb,
 	return 0;
 }
 
-static int __devinit adp5520_keys_probe(struct platform_device *pdev)
+static int adp5520_keys_probe(struct platform_device *pdev)
 {
 	struct adp5520_keys_platform_data *pdata = pdev->dev.platform_data;
 	struct input_dev *input;
@@ -182,7 +182,7 @@ err:
 	return ret;
 }
 
-static int __devexit adp5520_keys_remove(struct platform_device *pdev)
+static int adp5520_keys_remove(struct platform_device *pdev)
 {
 	struct adp5520_keys *dev = platform_get_drvdata(pdev);
 
@@ -200,7 +200,7 @@ static struct platform_driver adp5520_keys_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= adp5520_keys_probe,
-	.remove		= __devexit_p(adp5520_keys_remove),
+	.remove		= adp5520_keys_remove,
 };
 module_platform_driver(adp5520_keys_driver);
 
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
index b083bf1..dbd2047 100644
--- a/drivers/input/keyboard/adp5588-keys.c
+++ b/drivers/input/keyboard/adp5588-keys.c
@@ -145,7 +145,7 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip,
 	return ret;
 }
 
-static int __devinit adp5588_build_gpiomap(struct adp5588_kpad *kpad,
+static int adp5588_build_gpiomap(struct adp5588_kpad *kpad,
 				const struct adp5588_kpad_platform_data *pdata)
 {
 	bool pin_used[ADP5588_MAXGPIO];
@@ -170,7 +170,7 @@ static int __devinit adp5588_build_gpiomap(struct adp5588_kpad *kpad,
 	return n_unused;
 }
 
-static int __devinit adp5588_gpio_add(struct adp5588_kpad *kpad)
+static int adp5588_gpio_add(struct adp5588_kpad *kpad)
 {
 	struct device *dev = &kpad->client->dev;
 	const struct adp5588_kpad_platform_data *pdata = dev->platform_data;
@@ -224,7 +224,7 @@ static int __devinit adp5588_gpio_add(struct adp5588_kpad *kpad)
 	return 0;
 }
 
-static void __devexit adp5588_gpio_remove(struct adp5588_kpad *kpad)
+static void adp5588_gpio_remove(struct adp5588_kpad *kpad)
 {
 	struct device *dev = &kpad->client->dev;
 	const struct adp5588_kpad_platform_data *pdata = dev->platform_data;
@@ -319,7 +319,7 @@ static irqreturn_t adp5588_irq(int irq, void *handle)
 	return IRQ_HANDLED;
 }
 
-static int __devinit adp5588_setup(struct i2c_client *client)
+static int adp5588_setup(struct i2c_client *client)
 {
 	const struct adp5588_kpad_platform_data *pdata = client->dev.platform_data;
 	const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;
@@ -382,7 +382,7 @@ static int __devinit adp5588_setup(struct i2c_client *client)
 	return 0;
 }
 
-static void __devinit adp5588_report_switch_state(struct adp5588_kpad *kpad)
+static void adp5588_report_switch_state(struct adp5588_kpad *kpad)
 {
 	int gpi_stat1 = adp5588_read(kpad->client, GPIO_DAT_STAT1);
 	int gpi_stat2 = adp5588_read(kpad->client, GPIO_DAT_STAT2);
@@ -420,8 +420,8 @@ static void __devinit adp5588_report_switch_state(struct adp5588_kpad *kpad)
 }
 
 
-static int __devinit adp5588_probe(struct i2c_client *client,
-					const struct i2c_device_id *id)
+static int adp5588_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
 {
 	struct adp5588_kpad *kpad;
 	const struct adp5588_kpad_platform_data *pdata = client->dev.platform_data;
@@ -587,7 +587,7 @@ static int __devinit adp5588_probe(struct i2c_client *client,
 	return error;
 }
 
-static int __devexit adp5588_remove(struct i2c_client *client)
+static int adp5588_remove(struct i2c_client *client)
 {
 	struct adp5588_kpad *kpad = i2c_get_clientdata(client);
 
@@ -650,7 +650,7 @@ static struct i2c_driver adp5588_driver = {
 #endif
 	},
 	.probe    = adp5588_probe,
-	.remove   = __devexit_p(adp5588_remove),
+	.remove   = adp5588_remove,
 	.id_table = adp5588_id,
 };
 
diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c
index 74e6032..67d12b3 100644
--- a/drivers/input/keyboard/adp5589-keys.c
+++ b/drivers/input/keyboard/adp5589-keys.c
@@ -464,7 +464,7 @@ static int adp5589_gpio_direction_output(struct gpio_chip *chip,
 	return ret;
 }
 
-static int __devinit adp5589_build_gpiomap(struct adp5589_kpad *kpad,
+static int adp5589_build_gpiomap(struct adp5589_kpad *kpad,
 				const struct adp5589_kpad_platform_data *pdata)
 {
 	bool pin_used[ADP5589_MAXGPIO];
@@ -496,7 +496,7 @@ static int __devinit adp5589_build_gpiomap(struct adp5589_kpad *kpad,
 	return n_unused;
 }
 
-static int __devinit adp5589_gpio_add(struct adp5589_kpad *kpad)
+static int adp5589_gpio_add(struct adp5589_kpad *kpad)
 {
 	struct device *dev = &kpad->client->dev;
 	const struct adp5589_kpad_platform_data *pdata = dev->platform_data;
@@ -550,7 +550,7 @@ static int __devinit adp5589_gpio_add(struct adp5589_kpad *kpad)
 	return 0;
 }
 
-static void __devexit adp5589_gpio_remove(struct adp5589_kpad *kpad)
+static void adp5589_gpio_remove(struct adp5589_kpad *kpad)
 {
 	struct device *dev = &kpad->client->dev;
 	const struct adp5589_kpad_platform_data *pdata = dev->platform_data;
@@ -641,8 +641,7 @@ static irqreturn_t adp5589_irq(int irq, void *handle)
 	return IRQ_HANDLED;
 }
 
-static int __devinit adp5589_get_evcode(struct adp5589_kpad *kpad,
-					unsigned short key)
+static int adp5589_get_evcode(struct adp5589_kpad *kpad, unsigned short key)
 {
 	int i;
 
@@ -655,7 +654,7 @@ static int __devinit adp5589_get_evcode(struct adp5589_kpad *kpad,
 	return -EINVAL;
 }
 
-static int __devinit adp5589_setup(struct adp5589_kpad *kpad)
+static int adp5589_setup(struct adp5589_kpad *kpad)
 {
 	struct i2c_client *client = kpad->client;
 	const struct adp5589_kpad_platform_data *pdata =
@@ -820,7 +819,7 @@ static int __devinit adp5589_setup(struct adp5589_kpad *kpad)
 	return 0;
 }
 
-static void __devinit adp5589_report_switch_state(struct adp5589_kpad *kpad)
+static void adp5589_report_switch_state(struct adp5589_kpad *kpad)
 {
 	int gpi_stat_tmp, pin_loc;
 	int i;
@@ -860,8 +859,8 @@ static void __devinit adp5589_report_switch_state(struct adp5589_kpad *kpad)
 	input_sync(kpad->input);
 }
 
-static int __devinit adp5589_probe(struct i2c_client *client,
-				   const struct i2c_device_id *id)
+static int adp5589_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
 {
 	struct adp5589_kpad *kpad;
 	const struct adp5589_kpad_platform_data *pdata =
@@ -1045,7 +1044,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit adp5589_remove(struct i2c_client *client)
+static int adp5589_remove(struct i2c_client *client)
 {
 	struct adp5589_kpad *kpad = i2c_get_clientdata(client);
 
@@ -1104,7 +1103,7 @@ static struct i2c_driver adp5589_driver = {
 		.pm = &adp5589_dev_pm_ops,
 	},
 	.probe = adp5589_probe,
-	.remove = __devexit_p(adp5589_remove),
+	.remove = adp5589_remove,
 	.id_table = adp5589_id,
 };
 
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c
index 8eb9116..20b9fa9 100644
--- a/drivers/input/keyboard/bf54x-keys.c
+++ b/drivers/input/keyboard/bf54x-keys.c
@@ -177,7 +177,7 @@ static irqreturn_t bfin_kpad_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit bfin_kpad_probe(struct platform_device *pdev)
+static int bfin_kpad_probe(struct platform_device *pdev)
 {
 	struct bf54x_kpad *bf54x_kpad;
 	struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data;
@@ -331,7 +331,7 @@ out:
 	return error;
 }
 
-static int __devexit bfin_kpad_remove(struct platform_device *pdev)
+static int bfin_kpad_remove(struct platform_device *pdev)
 {
 	struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data;
 	struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
@@ -390,7 +390,7 @@ static struct platform_driver bfin_kpad_device_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= bfin_kpad_probe,
-	.remove		= __devexit_p(bfin_kpad_remove),
+	.remove		= bfin_kpad_remove,
 	.suspend	= bfin_kpad_suspend,
 	.resume		= bfin_kpad_resume,
 };
diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c
index d5bacbb..4e4e453 100644
--- a/drivers/input/keyboard/davinci_keyscan.c
+++ b/drivers/input/keyboard/davinci_keyscan.c
@@ -303,7 +303,7 @@ fail1:
 	return error;
 }
 
-static int __devexit davinci_ks_remove(struct platform_device *pdev)
+static int davinci_ks_remove(struct platform_device *pdev)
 {
 	struct davinci_ks *davinci_ks = platform_get_drvdata(pdev);
 
@@ -326,7 +326,7 @@ static struct platform_driver davinci_ks_driver = {
 		.name = "davinci_keyscan",
 		.owner = THIS_MODULE,
 	},
-	.remove	= __devexit_p(davinci_ks_remove),
+	.remove	= davinci_ks_remove,
 };
 
 static int __init davinci_ks_init(void)
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c
index 7363402..9857e8f 100644
--- a/drivers/input/keyboard/ep93xx_keypad.c
+++ b/drivers/input/keyboard/ep93xx_keypad.c
@@ -232,7 +232,7 @@ static int ep93xx_keypad_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops,
 			 ep93xx_keypad_suspend, ep93xx_keypad_resume);
 
-static int __devinit ep93xx_keypad_probe(struct platform_device *pdev)
+static int ep93xx_keypad_probe(struct platform_device *pdev)
 {
 	struct ep93xx_keypad *keypad;
 	const struct matrix_keymap_data *keymap_data;
@@ -346,7 +346,7 @@ failed_free:
 	return err;
 }
 
-static int __devexit ep93xx_keypad_remove(struct platform_device *pdev)
+static int ep93xx_keypad_remove(struct platform_device *pdev)
 {
 	struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -380,7 +380,7 @@ static struct platform_driver ep93xx_keypad_driver = {
 		.pm	= &ep93xx_keypad_pm_ops,
 	},
 	.probe		= ep93xx_keypad_probe,
-	.remove		= __devexit_p(ep93xx_keypad_remove),
+	.remove		= ep93xx_keypad_remove,
 };
 module_platform_driver(ep93xx_keypad_driver);
 
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 6a68041..79435de 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -423,10 +423,10 @@ out:
 	return IRQ_HANDLED;
 }
 
-static int __devinit gpio_keys_setup_key(struct platform_device *pdev,
-					 struct input_dev *input,
-					 struct gpio_button_data *bdata,
-					 const struct gpio_keys_button *button)
+static int gpio_keys_setup_key(struct platform_device *pdev,
+				struct input_dev *input,
+				struct gpio_button_data *bdata,
+				const struct gpio_keys_button *button)
 {
 	const char *desc = button->desc ? button->desc : "gpio_keys";
 	struct device *dev = &pdev->dev;
@@ -526,12 +526,35 @@ fail:
 	return error;
 }
 
+static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata)
+{
+	struct input_dev *input = ddata->input;
+	int i;
+
+	for (i = 0; i < ddata->pdata->nbuttons; i++) {
+		struct gpio_button_data *bdata = &ddata->data[i];
+		if (gpio_is_valid(bdata->button->gpio))
+			gpio_keys_gpio_report_event(bdata);
+	}
+	input_sync(input);
+}
+
 static int gpio_keys_open(struct input_dev *input)
 {
 	struct gpio_keys_drvdata *ddata = input_get_drvdata(input);
 	const struct gpio_keys_platform_data *pdata = ddata->pdata;
+	int error;
+
+	if (pdata->enable) {
+		error = pdata->enable(input->dev.parent);
+		if (error)
+			return error;
+	}
+
+	/* Report current state of buttons that are connected to GPIOs */
+	gpio_keys_report_state(ddata);
 
-	return pdata->enable ? pdata->enable(input->dev.parent) : 0;
+	return 0;
 }
 
 static void gpio_keys_close(struct input_dev *input)
@@ -551,7 +574,7 @@ static void gpio_keys_close(struct input_dev *input)
 /*
  * Translate OpenFirmware node properties into platform_data
  */
-static struct gpio_keys_platform_data * __devinit
+static struct gpio_keys_platform_data *
 gpio_keys_get_devtree_pdata(struct device *dev)
 {
 	struct device_node *node, *pp;
@@ -658,7 +681,7 @@ static void gpio_remove_key(struct gpio_button_data *bdata)
 		gpio_free(bdata->button->gpio);
 }
 
-static int __devinit gpio_keys_probe(struct platform_device *pdev)
+static int gpio_keys_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
@@ -731,14 +754,6 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
 		goto fail3;
 	}
 
-	/* get current state of buttons that are connected to GPIOs */
-	for (i = 0; i < pdata->nbuttons; i++) {
-		struct gpio_button_data *bdata = &ddata->data[i];
-		if (gpio_is_valid(bdata->button->gpio))
-			gpio_keys_gpio_report_event(bdata);
-	}
-	input_sync(input);
-
 	device_init_wakeup(&pdev->dev, wakeup);
 
 	return 0;
@@ -760,7 +775,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
 	return error;
 }
 
-static int __devexit gpio_keys_remove(struct platform_device *pdev)
+static int gpio_keys_remove(struct platform_device *pdev)
 {
 	struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
 	struct input_dev *input = ddata->input;
@@ -788,6 +803,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
 static int gpio_keys_suspend(struct device *dev)
 {
 	struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
+	struct input_dev *input = ddata->input;
 	int i;
 
 	if (device_may_wakeup(dev)) {
@@ -796,6 +812,11 @@ static int gpio_keys_suspend(struct device *dev)
 			if (bdata->button->wakeup)
 				enable_irq_wake(bdata->irq);
 		}
+	} else {
+		mutex_lock(&input->mutex);
+		if (input->users)
+			gpio_keys_close(input);
+		mutex_unlock(&input->mutex);
 	}
 
 	return 0;
@@ -804,18 +825,27 @@ static int gpio_keys_suspend(struct device *dev)
 static int gpio_keys_resume(struct device *dev)
 {
 	struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
+	struct input_dev *input = ddata->input;
+	int error = 0;
 	int i;
 
-	for (i = 0; i < ddata->pdata->nbuttons; i++) {
-		struct gpio_button_data *bdata = &ddata->data[i];
-		if (bdata->button->wakeup && device_may_wakeup(dev))
-			disable_irq_wake(bdata->irq);
-
-		if (gpio_is_valid(bdata->button->gpio))
-			gpio_keys_gpio_report_event(bdata);
+	if (device_may_wakeup(dev)) {
+		for (i = 0; i < ddata->pdata->nbuttons; i++) {
+			struct gpio_button_data *bdata = &ddata->data[i];
+			if (bdata->button->wakeup)
+				disable_irq_wake(bdata->irq);
+		}
+	} else {
+		mutex_lock(&input->mutex);
+		if (input->users)
+			error = gpio_keys_open(input);
+		mutex_unlock(&input->mutex);
 	}
-	input_sync(ddata->input);
 
+	if (error)
+		return error;
+
+	gpio_keys_report_state(ddata);
 	return 0;
 }
 #endif
@@ -824,7 +854,7 @@ static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
 
 static struct platform_driver gpio_keys_device_driver = {
 	.probe		= gpio_keys_probe,
-	.remove		= __devexit_p(gpio_keys_remove),
+	.remove		= gpio_keys_remove,
 	.driver		= {
 		.name	= "gpio-keys",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
index f2142de..32e5087 100644
--- a/drivers/input/keyboard/gpio_keys_polled.c
+++ b/drivers/input/keyboard/gpio_keys_polled.c
@@ -103,8 +103,7 @@ static void gpio_keys_polled_close(struct input_polled_dev *dev)
 }
 
 #ifdef CONFIG_OF
-static struct gpio_keys_platform_data * __devinit
-gpio_keys_polled_get_devtree_pdata(struct device *dev)
+static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct device *dev)
 {
 	struct device_node *node, *pp;
 	struct gpio_keys_platform_data *pdata;
@@ -196,7 +195,7 @@ gpio_keys_polled_get_devtree_pdata(struct device *dev)
 }
 #endif
 
-static int __devinit gpio_keys_polled_probe(struct platform_device *pdev)
+static int gpio_keys_polled_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
@@ -329,7 +328,7 @@ err_free_pdata:
 	return error;
 }
 
-static int __devexit gpio_keys_polled_remove(struct platform_device *pdev)
+static int gpio_keys_polled_remove(struct platform_device *pdev)
 {
 	struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev);
 	const struct gpio_keys_platform_data *pdata = bdev->pdata;
@@ -357,7 +356,7 @@ static int __devexit gpio_keys_polled_remove(struct platform_device *pdev)
 
 static struct platform_driver gpio_keys_polled_driver = {
 	.probe	= gpio_keys_polled_probe,
-	.remove	= __devexit_p(gpio_keys_polled_remove),
+	.remove	= gpio_keys_polled_remove,
 	.driver	= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
index 5f72440..198dc07 100644
--- a/drivers/input/keyboard/hilkbd.c
+++ b/drivers/input/keyboard/hilkbd.c
@@ -200,7 +200,7 @@ static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
 
 
 /* initialize HIL */
-static int __devinit hil_keyb_init(void)
+static int hil_keyb_init(void)
 {
 	unsigned char c;
 	unsigned int i, kbid;
@@ -286,7 +286,7 @@ err1:
 	return err;
 }
 
-static void __devexit hil_keyb_exit(void)
+static void hil_keyb_exit(void)
 {
 	if (HIL_IRQ)
 		free_irq(HIL_IRQ, hil_dev.dev_id);
@@ -299,7 +299,7 @@ static void __devexit hil_keyb_exit(void)
 }
 
 #if defined(CONFIG_PARISC)
-static int __devinit hil_probe_chip(struct parisc_device *dev)
+static int hil_probe_chip(struct parisc_device *dev)
 {
 	/* Only allow one HIL keyboard */
 	if (hil_dev.dev)
@@ -320,7 +320,7 @@ static int __devinit hil_probe_chip(struct parisc_device *dev)
 	return hil_keyb_init();
 }
 
-static int __devexit hil_remove_chip(struct parisc_device *dev)
+static int hil_remove_chip(struct parisc_device *dev)
 {
 	hil_keyb_exit();
 
@@ -341,7 +341,7 @@ static struct parisc_driver hil_driver = {
 	.name		= "hil",
 	.id_table	= hil_tbl,
 	.probe		= hil_probe_chip,
-	.remove		= __devexit_p(hil_remove_chip),
+	.remove		= hil_remove_chip,
 };
 
 static int __init hil_init(void)
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
index cdc2526..6d150e3 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -362,7 +362,8 @@ static void imx_keypad_inhibit(struct imx_keypad *keypad)
 	writew(reg_val, keypad->mmio_base + KPSR);
 
 	/* Colums as open drain and disable all rows */
-	writew(0xff00, keypad->mmio_base + KPCR);
+	reg_val = (keypad->cols_en_mask & 0xff) << 8;
+	writew(reg_val, keypad->mmio_base + KPCR);
 }
 
 static void imx_keypad_close(struct input_dev *dev)
@@ -413,7 +414,7 @@ open_err:
 	return -EIO;
 }
 
-static int __devinit imx_keypad_probe(struct platform_device *pdev)
+static int imx_keypad_probe(struct platform_device *pdev)
 {
 	const struct matrix_keymap_data *keymap_data = pdev->dev.platform_data;
 	struct imx_keypad *keypad;
@@ -554,7 +555,7 @@ failed_rel_mem:
 	return error;
 }
 
-static int __devexit imx_keypad_remove(struct platform_device *pdev)
+static int imx_keypad_remove(struct platform_device *pdev)
 {
 	struct imx_keypad *keypad = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -632,7 +633,7 @@ static struct platform_driver imx_keypad_driver = {
 		.pm	= &imx_kbd_pm_ops,
 	},
 	.probe		= imx_keypad_probe,
-	.remove		= __devexit_p(imx_keypad_remove),
+	.remove		= imx_keypad_remove,
 };
 module_platform_driver(imx_keypad_driver);
 
diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c
index 24f3ea0..74e75a6 100644
--- a/drivers/input/keyboard/jornada680_kbd.c
+++ b/drivers/input/keyboard/jornada680_kbd.c
@@ -179,7 +179,7 @@ static void jornadakbd680_poll(struct input_polled_dev *dev)
 	memcpy(jornadakbd->old_scan, jornadakbd->new_scan, JORNADA_SCAN_SIZE);
 }
 
-static int __devinit jornada680kbd_probe(struct platform_device *pdev)
+static int jornada680kbd_probe(struct platform_device *pdev)
 {
 	struct jornadakbd *jornadakbd;
 	struct input_polled_dev *poll_dev;
@@ -240,7 +240,7 @@ static int __devinit jornada680kbd_probe(struct platform_device *pdev)
 
 }
 
-static int __devexit jornada680kbd_remove(struct platform_device *pdev)
+static int jornada680kbd_remove(struct platform_device *pdev)
 {
 	struct jornadakbd *jornadakbd = platform_get_drvdata(pdev);
 
@@ -258,7 +258,7 @@ static struct platform_driver jornada680kbd_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe	= jornada680kbd_probe,
-	.remove	= __devexit_p(jornada680kbd_remove),
+	.remove	= jornada680kbd_remove,
 };
 module_platform_driver(jornada680kbd_driver);
 
diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c
index 9d639fa..5ceef63 100644
--- a/drivers/input/keyboard/jornada720_kbd.c
+++ b/drivers/input/keyboard/jornada720_kbd.c
@@ -94,7 +94,7 @@ static irqreturn_t jornada720_kbd_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 };
 
-static int __devinit jornada720_kbd_probe(struct platform_device *pdev)
+static int jornada720_kbd_probe(struct platform_device *pdev)
 {
 	struct jornadakbd *jornadakbd;
 	struct input_dev *input_dev;
@@ -152,7 +152,7 @@ static int __devinit jornada720_kbd_probe(struct platform_device *pdev)
 	return err;
 };
 
-static int __devexit jornada720_kbd_remove(struct platform_device *pdev)
+static int jornada720_kbd_remove(struct platform_device *pdev)
 {
 	struct jornadakbd *jornadakbd = platform_get_drvdata(pdev);
 
@@ -173,6 +173,6 @@ static struct platform_driver jornada720_kbd_driver = {
 		.owner	= THIS_MODULE,
 	 },
 	.probe   = jornada720_kbd_probe,
-	.remove  = __devexit_p(jornada720_kbd_remove),
+	.remove  = jornada720_kbd_remove,
 };
 module_platform_driver(jornada720_kbd_driver);
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
index 39ac278..93c8126 100644
--- a/drivers/input/keyboard/lm8323.c
+++ b/drivers/input/keyboard/lm8323.c
@@ -624,7 +624,7 @@ static ssize_t lm8323_set_disable(struct device *dev,
 }
 static DEVICE_ATTR(disable_kp, 0644, lm8323_show_disable, lm8323_set_disable);
 
-static int __devinit lm8323_probe(struct i2c_client *client,
+static int lm8323_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
 	struct lm8323_platform_data *pdata = client->dev.platform_data;
@@ -764,7 +764,7 @@ fail1:
 	return err;
 }
 
-static int __devexit lm8323_remove(struct i2c_client *client)
+static int lm8323_remove(struct i2c_client *client)
 {
 	struct lm8323_chip *lm = i2c_get_clientdata(client);
 	int i;
@@ -846,7 +846,7 @@ static struct i2c_driver lm8323_i2c_driver = {
 		.pm	= &lm8323_pm_ops,
 	},
 	.probe		= lm8323_probe,
-	.remove		= __devexit_p(lm8323_remove),
+	.remove		= lm8323_remove,
 	.id_table	= lm8323_id,
 };
 MODULE_DEVICE_TABLE(i2c, lm8323_id);
diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c
index 081fd9e..5a8ca35 100644
--- a/drivers/input/keyboard/lm8333.c
+++ b/drivers/input/keyboard/lm8333.c
@@ -128,7 +128,7 @@ static irqreturn_t lm8333_irq_thread(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int __devinit lm8333_probe(struct i2c_client *client,
+static int lm8333_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
 	const struct lm8333_platform_data *pdata = client->dev.platform_data;
@@ -202,7 +202,7 @@ static int __devinit lm8333_probe(struct i2c_client *client,
 	return err;
 }
 
-static int __devexit lm8333_remove(struct i2c_client *client)
+static int lm8333_remove(struct i2c_client *client)
 {
 	struct lm8333 *lm8333 = i2c_get_clientdata(client);
 
@@ -225,7 +225,7 @@ static struct i2c_driver lm8333_driver = {
 		.owner		= THIS_MODULE,
 	},
 	.probe		= lm8333_probe,
-	.remove		= __devexit_p(lm8333_remove),
+	.remove		= lm8333_remove,
 	.id_table	= lm8333_id,
 };
 module_i2c_driver(lm8333_driver);
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
index b1ab298..c94d610 100644
--- a/drivers/input/keyboard/locomokbd.c
+++ b/drivers/input/keyboard/locomokbd.c
@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL");
 #define KEY_CENTER		KEY_F15
 
 static const unsigned char
-locomokbd_keycode[LOCOMOKBD_NUMKEYS] __devinitconst = {
+locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
 	0, KEY_ESC, KEY_ACTIVITY, 0, 0, 0, 0, 0, 0, 0,				/* 0 - 9 */
 	0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_HOME, KEY_CONTACT,			/* 10 - 19 */
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,						/* 20 - 29 */
@@ -236,7 +236,7 @@ static void locomokbd_close(struct input_dev *dev)
 	locomo_writel(r, locomokbd->base + LOCOMO_KIC);
 }
 
-static int __devinit locomokbd_probe(struct locomo_dev *dev)
+static int locomokbd_probe(struct locomo_dev *dev)
 {
 	struct locomokbd *locomokbd;
 	struct input_dev *input_dev;
@@ -321,7 +321,7 @@ static int __devinit locomokbd_probe(struct locomo_dev *dev)
 	return err;
 }
 
-static int __devexit locomokbd_remove(struct locomo_dev *dev)
+static int locomokbd_remove(struct locomo_dev *dev)
 {
 	struct locomokbd *locomokbd = locomo_get_drvdata(dev);
 
@@ -345,7 +345,7 @@ static struct locomo_driver keyboard_driver = {
 	},
 	.devid	= LOCOMO_DEVID_KEYBOARD,
 	.probe	= locomokbd_probe,
-	.remove	= __devexit_p(locomokbd_remove),
+	.remove	= locomokbd_remove,
 };
 
 static int __init locomokbd_init(void)
diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c
index dd786c8..1b8add6 100644
--- a/drivers/input/keyboard/lpc32xx-keys.c
+++ b/drivers/input/keyboard/lpc32xx-keys.c
@@ -139,7 +139,7 @@ static void lpc32xx_kscan_close(struct input_dev *dev)
 	clk_disable_unprepare(kscandat->clk);
 }
 
-static int __devinit lpc32xx_parse_dt(struct device *dev,
+static int lpc32xx_parse_dt(struct device *dev,
 				      struct lpc32xx_kscan_drv *kscandat)
 {
 	struct device_node *np = dev->of_node;
@@ -166,7 +166,7 @@ static int __devinit lpc32xx_parse_dt(struct device *dev,
 	return 0;
 }
 
-static int __devinit lpc32xx_kscan_probe(struct platform_device *pdev)
+static int lpc32xx_kscan_probe(struct platform_device *pdev)
 {
 	struct lpc32xx_kscan_drv *kscandat;
 	struct input_dev *input;
@@ -310,7 +310,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit lpc32xx_kscan_remove(struct platform_device *pdev)
+static int lpc32xx_kscan_remove(struct platform_device *pdev)
 {
 	struct lpc32xx_kscan_drv *kscandat = platform_get_drvdata(pdev);
 
@@ -377,7 +377,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_kscan_match);
 
 static struct platform_driver lpc32xx_kscan_driver = {
 	.probe		= lpc32xx_kscan_probe,
-	.remove		= __devexit_p(lpc32xx_kscan_remove),
+	.remove		= lpc32xx_kscan_remove,
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
index 18b7237..f4ff0dd 100644
--- a/drivers/input/keyboard/matrix_keypad.c
+++ b/drivers/input/keyboard/matrix_keypad.c
@@ -23,6 +23,9 @@
 #include <linux/gpio.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
 
 struct matrix_keypad {
 	const struct matrix_keypad_platform_data *pdata;
@@ -37,8 +40,6 @@ struct matrix_keypad {
 	bool scan_pending;
 	bool stopped;
 	bool gpio_all_disabled;
-
-	unsigned short keycodes[];
 };
 
 /*
@@ -118,6 +119,7 @@ static void matrix_keypad_scan(struct work_struct *work)
 	struct matrix_keypad *keypad =
 		container_of(work, struct matrix_keypad, work.work);
 	struct input_dev *input_dev = keypad->input_dev;
+	const unsigned short *keycodes = input_dev->keycode;
 	const struct matrix_keypad_platform_data *pdata = keypad->pdata;
 	uint32_t new_state[MATRIX_MAX_COLS];
 	int row, col, code;
@@ -153,7 +155,7 @@ static void matrix_keypad_scan(struct work_struct *work)
 			code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
 			input_event(input_dev, EV_MSC, MSC_SCAN, code);
 			input_report_key(input_dev,
-					 keypad->keycodes[code],
+					 keycodes[code],
 					 new_state[col] & (1 << row));
 		}
 	}
@@ -299,8 +301,8 @@ static int matrix_keypad_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops,
 			 matrix_keypad_suspend, matrix_keypad_resume);
 
-static int __devinit matrix_keypad_init_gpio(struct platform_device *pdev,
-					     struct matrix_keypad *keypad)
+static int matrix_keypad_init_gpio(struct platform_device *pdev,
+				   struct matrix_keypad *keypad)
 {
 	const struct matrix_keypad_platform_data *pdata = keypad->pdata;
 	int i, err;
@@ -394,33 +396,95 @@ static void matrix_keypad_free_gpio(struct matrix_keypad *keypad)
 		gpio_free(pdata->col_gpios[i]);
 }
 
-static int __devinit matrix_keypad_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static struct matrix_keypad_platform_data *
+matrix_keypad_parse_dt(struct device *dev)
+{
+	struct matrix_keypad_platform_data *pdata;
+	struct device_node *np = dev->of_node;
+	unsigned int *gpios;
+	int i;
+
+	if (!np) {
+		dev_err(dev, "device lacks DT data\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		dev_err(dev, "could not allocate memory for platform data\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pdata->num_row_gpios = of_gpio_named_count(np, "row-gpios");
+	pdata->num_col_gpios = of_gpio_named_count(np, "col-gpios");
+	if (!pdata->num_row_gpios || !pdata->num_col_gpios) {
+		dev_err(dev, "number of keypad rows/columns not specified\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_get_property(np, "linux,no-autorepeat", NULL))
+		pdata->no_autorepeat = true;
+	if (of_get_property(np, "linux,wakeup", NULL))
+		pdata->wakeup = true;
+	if (of_get_property(np, "gpio-activelow", NULL))
+		pdata->active_low = true;
+
+	of_property_read_u32(np, "debounce-delay-ms", &pdata->debounce_ms);
+	of_property_read_u32(np, "col-scan-delay-us",
+						&pdata->col_scan_delay_us);
+
+	gpios = devm_kzalloc(dev,
+			     sizeof(unsigned int) *
+				(pdata->num_row_gpios + pdata->num_col_gpios),
+			     GFP_KERNEL);
+	if (!gpios) {
+		dev_err(dev, "could not allocate memory for gpios\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	for (i = 0; i < pdata->num_row_gpios; i++)
+		gpios[i] = of_get_named_gpio(np, "row-gpios", i);
+
+	for (i = 0; i < pdata->num_col_gpios; i++)
+		gpios[pdata->num_row_gpios + i] =
+			of_get_named_gpio(np, "col-gpios", i);
+
+	pdata->row_gpios = gpios;
+	pdata->col_gpios = &gpios[pdata->num_row_gpios];
+
+	return pdata;
+}
+#else
+static inline struct matrix_keypad_platform_data *
+matrix_keypad_parse_dt(struct device *dev)
+{
+	dev_err(dev, "no platform data defined\n");
+
+	return ERR_PTR(-EINVAL);
+}
+#endif
+
+static int matrix_keypad_probe(struct platform_device *pdev)
 {
 	const struct matrix_keypad_platform_data *pdata;
-	const struct matrix_keymap_data *keymap_data;
 	struct matrix_keypad *keypad;
 	struct input_dev *input_dev;
-	unsigned int row_shift;
-	size_t keymap_size;
 	int err;
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	if (!pdata) {
-		dev_err(&pdev->dev, "no platform data defined\n");
-		return -EINVAL;
-	}
-
-	keymap_data = pdata->keymap_data;
-	if (!keymap_data) {
+		pdata = matrix_keypad_parse_dt(&pdev->dev);
+		if (IS_ERR(pdata)) {
+			dev_err(&pdev->dev, "no platform data defined\n");
+			return PTR_ERR(pdata);
+		}
+	} else if (!pdata->keymap_data) {
 		dev_err(&pdev->dev, "no keymap data defined\n");
 		return -EINVAL;
 	}
 
-	row_shift = get_count_order(pdata->num_col_gpios);
-	keymap_size = (pdata->num_row_gpios << row_shift) *
-			sizeof(keypad->keycodes[0]);
-	keypad = kzalloc(sizeof(struct matrix_keypad) + keymap_size,
-			 GFP_KERNEL);
+	keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!keypad || !input_dev) {
 		err = -ENOMEM;
@@ -429,7 +493,7 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev)
 
 	keypad->input_dev = input_dev;
 	keypad->pdata = pdata;
-	keypad->row_shift = row_shift;
+	keypad->row_shift = get_count_order(pdata->num_col_gpios);
 	keypad->stopped = true;
 	INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
 	spin_lock_init(&keypad->lock);
@@ -440,12 +504,14 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev)
 	input_dev->open		= matrix_keypad_start;
 	input_dev->close	= matrix_keypad_stop;
 
-	err = matrix_keypad_build_keymap(keymap_data, NULL,
+	err = matrix_keypad_build_keymap(pdata->keymap_data, NULL,
 					 pdata->num_row_gpios,
 					 pdata->num_col_gpios,
-					 keypad->keycodes, input_dev);
-	if (err)
+					 NULL, input_dev);
+	if (err) {
+		dev_err(&pdev->dev, "failed to build keymap\n");
 		goto err_free_mem;
+	}
 
 	if (!pdata->no_autorepeat)
 		__set_bit(EV_REP, input_dev->evbit);
@@ -473,7 +539,7 @@ err_free_mem:
 	return err;
 }
 
-static int __devexit matrix_keypad_remove(struct platform_device *pdev)
+static int matrix_keypad_remove(struct platform_device *pdev)
 {
 	struct matrix_keypad *keypad = platform_get_drvdata(pdev);
 
@@ -488,13 +554,22 @@ static int __devexit matrix_keypad_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id matrix_keypad_dt_match[] = {
+	{ .compatible = "gpio-matrix-keypad" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, matrix_keypad_dt_match);
+#endif
+
 static struct platform_driver matrix_keypad_driver = {
 	.probe		= matrix_keypad_probe,
-	.remove		= __devexit_p(matrix_keypad_remove),
+	.remove		= matrix_keypad_remove,
 	.driver		= {
 		.name	= "matrix-keypad",
 		.owner	= THIS_MODULE,
 		.pm	= &matrix_keypad_pm_ops,
+		.of_match_table = of_match_ptr(matrix_keypad_dt_match),
 	},
 };
 module_platform_driver(matrix_keypad_driver);
diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c
index 8edada8..7c7af2b 100644
--- a/drivers/input/keyboard/max7359_keypad.c
+++ b/drivers/input/keyboard/max7359_keypad.c
@@ -179,7 +179,7 @@ static void max7359_initialize(struct i2c_client *client)
 	max7359_fall_deepsleep(client);
 }
 
-static int __devinit max7359_probe(struct i2c_client *client,
+static int max7359_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	const struct matrix_keymap_data *keymap_data = client->dev.platform_data;
@@ -260,7 +260,7 @@ failed_free_mem:
 	return error;
 }
 
-static int __devexit max7359_remove(struct i2c_client *client)
+static int max7359_remove(struct i2c_client *client)
 {
 	struct max7359_keypad *keypad = i2c_get_clientdata(client);
 
@@ -312,7 +312,7 @@ static struct i2c_driver max7359_i2c_driver = {
 		.pm   = &max7359_pm,
 	},
 	.probe		= max7359_probe,
-	.remove		= __devexit_p(max7359_remove),
+	.remove		= max7359_remove,
 	.id_table	= max7359_ids,
 };
 
diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c
index 0d77f6c..7c236f9 100644
--- a/drivers/input/keyboard/mcs_touchkey.c
+++ b/drivers/input/keyboard/mcs_touchkey.c
@@ -97,7 +97,7 @@ static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit mcs_touchkey_probe(struct i2c_client *client,
+static int mcs_touchkey_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	const struct mcs_platform_data *pdata;
@@ -200,7 +200,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit mcs_touchkey_remove(struct i2c_client *client)
+static int mcs_touchkey_remove(struct i2c_client *client)
 {
 	struct mcs_touchkey_data *data = i2c_get_clientdata(client);
 
@@ -270,7 +270,7 @@ static struct i2c_driver mcs_touchkey_driver = {
 		.pm	= &mcs_touchkey_pm_ops,
 	},
 	.probe		= mcs_touchkey_probe,
-	.remove		= __devexit_p(mcs_touchkey_remove),
+	.remove		= mcs_touchkey_remove,
 	.shutdown       = mcs_touchkey_shutdown,
 	.id_table	= mcs_touchkey_id,
 };
diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
index 7613f1c..f7f3e9a 100644
--- a/drivers/input/keyboard/mpr121_touchkey.c
+++ b/drivers/input/keyboard/mpr121_touchkey.c
@@ -71,7 +71,7 @@ struct mpr121_init_register {
 	u8 val;
 };
 
-static const struct mpr121_init_register init_reg_table[] __devinitconst = {
+static const struct mpr121_init_register init_reg_table[] = {
 	{ MHD_RISING_ADDR,	0x1 },
 	{ NHD_RISING_ADDR,	0x1 },
 	{ MHD_FALLING_ADDR,	0x1 },
@@ -123,7 +123,7 @@ out:
 	return IRQ_HANDLED;
 }
 
-static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata,
+static int mpr121_phys_init(const struct mpr121_platform_data *pdata,
 				      struct mpr121_touchkey *mpr121,
 				      struct i2c_client *client)
 {
@@ -185,8 +185,8 @@ err_i2c_write:
 	return ret;
 }
 
-static int __devinit mpr_touchkey_probe(struct i2c_client *client,
-					const struct i2c_device_id *id)
+static int mpr_touchkey_probe(struct i2c_client *client,
+			      const struct i2c_device_id *id)
 {
 	const struct mpr121_platform_data *pdata = client->dev.platform_data;
 	struct mpr121_touchkey *mpr121;
@@ -272,7 +272,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit mpr_touchkey_remove(struct i2c_client *client)
+static int mpr_touchkey_remove(struct i2c_client *client)
 {
 	struct mpr121_touchkey *mpr121 = i2c_get_clientdata(client);
 
@@ -327,7 +327,7 @@ static struct i2c_driver mpr_touchkey_driver = {
 	},
 	.id_table	= mpr121_id,
 	.probe		= mpr_touchkey_probe,
-	.remove		= __devexit_p(mpr_touchkey_remove),
+	.remove		= mpr_touchkey_remove,
 };
 
 module_i2c_driver(mpr_touchkey_driver);
diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c
index 49f5fa6..0e6a815 100644
--- a/drivers/input/keyboard/nomadik-ske-keypad.c
+++ b/drivers/input/keyboard/nomadik-ske-keypad.c
@@ -67,6 +67,7 @@ struct ske_keypad {
 	const struct ske_keypad_platform_data *board;
 	unsigned short keymap[SKE_KPD_NUM_ROWS * SKE_KPD_NUM_COLS];
 	struct clk *clk;
+	struct clk *pclk;
 	spinlock_t ske_keypad_lock;
 };
 
@@ -271,11 +272,18 @@ static int __init ske_keypad_probe(struct platform_device *pdev)
 		goto err_free_mem_region;
 	}
 
+	keypad->pclk = clk_get(&pdev->dev, "apb_pclk");
+	if (IS_ERR(keypad->pclk)) {
+		dev_err(&pdev->dev, "failed to get pclk\n");
+		error = PTR_ERR(keypad->pclk);
+		goto err_iounmap;
+	}
+
 	keypad->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(keypad->clk)) {
 		dev_err(&pdev->dev, "failed to get clk\n");
 		error = PTR_ERR(keypad->clk);
-		goto err_iounmap;
+		goto err_pclk;
 	}
 
 	input->id.bustype = BUS_HOST;
@@ -287,14 +295,25 @@ static int __init ske_keypad_probe(struct platform_device *pdev)
 					   keypad->keymap, input);
 	if (error) {
 		dev_err(&pdev->dev, "Failed to build keymap\n");
-		goto err_iounmap;
+		goto err_clk;
 	}
 
 	input_set_capability(input, EV_MSC, MSC_SCAN);
 	if (!plat->no_autorepeat)
 		__set_bit(EV_REP, input->evbit);
 
-	clk_enable(keypad->clk);
+	error = clk_prepare_enable(keypad->pclk);
+	if (error) {
+		dev_err(&pdev->dev, "Failed to prepare/enable pclk\n");
+		goto err_clk;
+	}
+
+	error = clk_prepare_enable(keypad->clk);
+	if (error) {
+		dev_err(&pdev->dev, "Failed to prepare/enable clk\n");
+		goto err_pclk_disable;
+	}
+
 
 	/* go through board initialization helpers */
 	if (keypad->board->init)
@@ -330,8 +349,13 @@ static int __init ske_keypad_probe(struct platform_device *pdev)
 err_free_irq:
 	free_irq(keypad->irq, keypad);
 err_clk_disable:
-	clk_disable(keypad->clk);
+	clk_disable_unprepare(keypad->clk);
+err_pclk_disable:
+	clk_disable_unprepare(keypad->pclk);
+err_clk:
 	clk_put(keypad->clk);
+err_pclk:
+	clk_put(keypad->pclk);
 err_iounmap:
 	iounmap(keypad->reg_base);
 err_free_mem_region:
@@ -342,7 +366,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit ske_keypad_remove(struct platform_device *pdev)
+static int ske_keypad_remove(struct platform_device *pdev)
 {
 	struct ske_keypad *keypad = platform_get_drvdata(pdev);
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -351,7 +375,7 @@ static int __devexit ske_keypad_remove(struct platform_device *pdev)
 
 	input_unregister_device(keypad->input);
 
-	clk_disable(keypad->clk);
+	clk_disable_unprepare(keypad->clk);
 	clk_put(keypad->clk);
 
 	if (keypad->board->exit)
@@ -403,7 +427,7 @@ static struct platform_driver ske_keypad_driver = {
 		.owner  = THIS_MODULE,
 		.pm = &ske_keypad_dev_pm_ops,
 	},
-	.remove = __devexit_p(ske_keypad_remove),
+	.remove = ske_keypad_remove,
 };
 
 static int __init ske_keypad_init(void)
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
index 4a5fcc8..d0d5226 100644
--- a/drivers/input/keyboard/omap-keypad.c
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -244,7 +244,7 @@ static int omap_kp_resume(struct platform_device *dev)
 #define omap_kp_resume	NULL
 #endif
 
-static int __devinit omap_kp_probe(struct platform_device *pdev)
+static int omap_kp_probe(struct platform_device *pdev)
 {
 	struct omap_kp *omap_kp;
 	struct input_dev *input_dev;
@@ -357,7 +357,7 @@ err2:
 	return -EINVAL;
 }
 
-static int __devexit omap_kp_remove(struct platform_device *pdev)
+static int omap_kp_remove(struct platform_device *pdev)
 {
 	struct omap_kp *omap_kp = platform_get_drvdata(pdev);
 
@@ -379,7 +379,7 @@ static int __devexit omap_kp_remove(struct platform_device *pdev)
 
 static struct platform_driver omap_kp_driver = {
 	.probe		= omap_kp_probe,
-	.remove		= __devexit_p(omap_kp_remove),
+	.remove		= omap_kp_remove,
 	.suspend	= omap_kp_suspend,
 	.resume		= omap_kp_resume,
 	.driver		= {
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
index c05f98c..e25b022 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -211,8 +211,8 @@ static void omap4_keypad_close(struct input_dev *input)
 }
 
 #ifdef CONFIG_OF
-static int __devinit omap4_keypad_parse_dt(struct device *dev,
-					   struct omap4_keypad *keypad_data)
+static int omap4_keypad_parse_dt(struct device *dev,
+				 struct omap4_keypad *keypad_data)
 {
 	struct device_node *np = dev->of_node;
 
@@ -241,7 +241,7 @@ static inline int omap4_keypad_parse_dt(struct device *dev,
 }
 #endif
 
-static int __devinit omap4_keypad_probe(struct platform_device *pdev)
+static int omap4_keypad_probe(struct platform_device *pdev)
 {
 	const struct omap4_keypad_platform_data *pdata =
 				dev_get_platdata(&pdev->dev);
@@ -406,7 +406,7 @@ err_free_keypad:
 	return error;
 }
 
-static int __devexit omap4_keypad_remove(struct platform_device *pdev)
+static int omap4_keypad_remove(struct platform_device *pdev)
 {
 	struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -440,7 +440,7 @@ MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
 
 static struct platform_driver omap4_keypad_driver = {
 	.probe		= omap4_keypad_probe,
-	.remove		= __devexit_p(omap4_keypad_remove),
+	.remove		= omap4_keypad_remove,
 	.driver		= {
 		.name	= "omap4-keypad",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/keyboard/opencores-kbd.c b/drivers/input/keyboard/opencores-kbd.c
index abe728c..7ac5f17 100644
--- a/drivers/input/keyboard/opencores-kbd.c
+++ b/drivers/input/keyboard/opencores-kbd.c
@@ -37,7 +37,7 @@ static irqreturn_t opencores_kbd_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit opencores_kbd_probe(struct platform_device *pdev)
+static int opencores_kbd_probe(struct platform_device *pdev)
 {
 	struct input_dev *input;
 	struct opencores_kbd *opencores_kbd;
@@ -139,7 +139,7 @@ static int __devinit opencores_kbd_probe(struct platform_device *pdev)
 	return error;
 }
 
-static int __devexit opencores_kbd_remove(struct platform_device *pdev)
+static int opencores_kbd_remove(struct platform_device *pdev)
 {
 	struct opencores_kbd *opencores_kbd = platform_get_drvdata(pdev);
 
@@ -158,7 +158,7 @@ static int __devexit opencores_kbd_remove(struct platform_device *pdev)
 
 static struct platform_driver opencores_kbd_device_driver = {
 	.probe    = opencores_kbd_probe,
-	.remove   = __devexit_p(opencores_kbd_remove),
+	.remove   = opencores_kbd_remove,
 	.driver   = {
 		.name = "opencores-kbd",
 	},
diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c
index 52c3465..74339e1 100644
--- a/drivers/input/keyboard/pmic8xxx-keypad.c
+++ b/drivers/input/keyboard/pmic8xxx-keypad.c
@@ -397,7 +397,7 @@ static irqreturn_t pmic8xxx_kp_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int __devinit pmic8xxx_kpd_init(struct pmic8xxx_kp *kp)
+static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp)
 {
 	int bits, rc, cycles;
 	u8 scan_val = 0, ctrl_val = 0;
@@ -447,7 +447,7 @@ static int __devinit pmic8xxx_kpd_init(struct pmic8xxx_kp *kp)
 
 }
 
-static int  __devinit pmic8xxx_kp_config_gpio(int gpio_start, int num_gpios,
+static int  pmic8xxx_kp_config_gpio(int gpio_start, int num_gpios,
 			struct pmic8xxx_kp *kp, struct pm_gpio *gpio_config)
 {
 	int	rc, i;
@@ -518,7 +518,7 @@ static void pmic8xxx_kp_close(struct input_dev *dev)
  * - set irq edge type.
  * - enable the keypad controller.
  */
-static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev)
+static int pmic8xxx_kp_probe(struct platform_device *pdev)
 {
 	const struct pm8xxx_keypad_platform_data *pdata =
 					dev_get_platdata(&pdev->dev);
@@ -712,7 +712,7 @@ err_alloc_device:
 	return rc;
 }
 
-static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev)
+static int pmic8xxx_kp_remove(struct platform_device *pdev)
 {
 	struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);
 
@@ -773,7 +773,7 @@ static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops,
 
 static struct platform_driver pmic8xxx_kp_driver = {
 	.probe		= pmic8xxx_kp_probe,
-	.remove		= __devexit_p(pmic8xxx_kp_remove),
+	.remove		= pmic8xxx_kp_remove,
 	.driver		= {
 		.name = PM8XXX_KEYPAD_DEV_NAME,
 		.owner = THIS_MODULE,
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index cad9d5d..5330d8f 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -482,7 +482,7 @@ static const struct dev_pm_ops pxa27x_keypad_pm_ops = {
 };
 #endif
 
-static int __devinit pxa27x_keypad_probe(struct platform_device *pdev)
+static int pxa27x_keypad_probe(struct platform_device *pdev)
 {
 	struct pxa27x_keypad_platform_data *pdata = pdev->dev.platform_data;
 	struct pxa27x_keypad *keypad;
@@ -595,7 +595,7 @@ failed_free:
 	return error;
 }
 
-static int __devexit pxa27x_keypad_remove(struct platform_device *pdev)
+static int pxa27x_keypad_remove(struct platform_device *pdev)
 {
 	struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -620,7 +620,7 @@ MODULE_ALIAS("platform:pxa27x-keypad");
 
 static struct platform_driver pxa27x_keypad_driver = {
 	.probe		= pxa27x_keypad_probe,
-	.remove		= __devexit_p(pxa27x_keypad_remove),
+	.remove		= pxa27x_keypad_remove,
 	.driver		= {
 		.name	= "pxa27x-keypad",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c
index 41488f9..bcad95b 100644
--- a/drivers/input/keyboard/pxa930_rotary.c
+++ b/drivers/input/keyboard/pxa930_rotary.c
@@ -82,7 +82,7 @@ static void pxa930_rotary_close(struct input_dev *dev)
 	clear_sbcr(r);
 }
 
-static int __devinit pxa930_rotary_probe(struct platform_device *pdev)
+static int pxa930_rotary_probe(struct platform_device *pdev)
 {
 	struct pxa930_rotary_platform_data *pdata = pdev->dev.platform_data;
 	struct pxa930_rotary *r;
@@ -174,7 +174,7 @@ failed_free:
 	return err;
 }
 
-static int __devexit pxa930_rotary_remove(struct platform_device *pdev)
+static int pxa930_rotary_remove(struct platform_device *pdev)
 {
 	struct pxa930_rotary *r = platform_get_drvdata(pdev);
 
@@ -193,7 +193,7 @@ static struct platform_driver pxa930_rotary_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= pxa930_rotary_probe,
-	.remove		= __devexit_p(pxa930_rotary_remove),
+	.remove		= pxa930_rotary_remove,
 };
 module_platform_driver(pxa930_rotary_driver);
 
diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c
index ca68f29..42b773b 100644
--- a/drivers/input/keyboard/qt1070.c
+++ b/drivers/input/keyboard/qt1070.c
@@ -91,7 +91,7 @@ static int qt1070_write(struct i2c_client *client, u8 reg, u8 data)
 	return ret;
 }
 
-static bool __devinit qt1070_identify(struct i2c_client *client)
+static bool qt1070_identify(struct i2c_client *client)
 {
 	int id, ver;
 
@@ -140,7 +140,7 @@ static irqreturn_t qt1070_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit qt1070_probe(struct i2c_client *client,
+static int qt1070_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
 	struct qt1070_data *data;
@@ -230,7 +230,7 @@ err_free_mem:
 	return err;
 }
 
-static int __devexit qt1070_remove(struct i2c_client *client)
+static int qt1070_remove(struct i2c_client *client)
 {
 	struct qt1070_data *data = i2c_get_clientdata(client);
 
@@ -256,7 +256,7 @@ static struct i2c_driver qt1070_driver = {
 	},
 	.id_table	= qt1070_id,
 	.probe		= qt1070_probe,
-	.remove		= __devexit_p(qt1070_remove),
+	.remove		= qt1070_remove,
 };
 
 module_i2c_driver(qt1070_driver);
diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c
index 76b7d43..3dc2b0f 100644
--- a/drivers/input/keyboard/qt2160.c
+++ b/drivers/input/keyboard/qt2160.c
@@ -183,7 +183,7 @@ static void qt2160_worker(struct work_struct *work)
 	qt2160_schedule_read(qt2160);
 }
 
-static int __devinit qt2160_read(struct i2c_client *client, u8 reg)
+static int qt2160_read(struct i2c_client *client, u8 reg)
 {
 	int ret;
 
@@ -204,29 +204,20 @@ static int __devinit qt2160_read(struct i2c_client *client, u8 reg)
 	return ret;
 }
 
-static int __devinit qt2160_write(struct i2c_client *client, u8 reg, u8 data)
+static int qt2160_write(struct i2c_client *client, u8 reg, u8 data)
 {
-	int error;
-
-	error = i2c_smbus_write_byte(client, reg);
-	if (error) {
-		dev_err(&client->dev,
-			"couldn't send request. Returned %d\n", error);
-		return error;
-	}
+	int ret;
 
-	error = i2c_smbus_write_byte(client, data);
-	if (error) {
+	ret = i2c_smbus_write_byte_data(client, reg, data);
+	if (ret < 0)
 		dev_err(&client->dev,
-			"couldn't write data. Returned %d\n", error);
-		return error;
-	}
+			"couldn't write data. Returned %d\n", ret);
 
-	return error;
+	return ret;
 }
 
 
-static bool __devinit qt2160_identify(struct i2c_client *client)
+static bool qt2160_identify(struct i2c_client *client)
 {
 	int id, ver, rev;
 
@@ -257,7 +248,7 @@ static bool __devinit qt2160_identify(struct i2c_client *client)
 	return true;
 }
 
-static int __devinit qt2160_probe(struct i2c_client *client,
+static int qt2160_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
 	struct qt2160_data *qt2160;
@@ -344,7 +335,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit qt2160_remove(struct i2c_client *client)
+static int qt2160_remove(struct i2c_client *client)
 {
 	struct qt2160_data *qt2160 = i2c_get_clientdata(client);
 
@@ -375,7 +366,7 @@ static struct i2c_driver qt2160_driver = {
 
 	.id_table	= qt2160_idtable,
 	.probe		= qt2160_probe,
-	.remove		= __devexit_p(qt2160_remove),
+	.remove		= qt2160_remove,
 };
 
 module_i2c_driver(qt2160_driver);
diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c
index 9d7a111..22e357b 100644
--- a/drivers/input/keyboard/samsung-keypad.c
+++ b/drivers/input/keyboard/samsung-keypad.c
@@ -309,7 +309,7 @@ static void samsung_keypad_parse_dt_gpio(struct device *dev,
 				struct samsung_keypad *keypad)
 {
 	struct device_node *np = dev->of_node;
-	int gpio, ret, row, col;
+	int gpio, error, row, col;
 
 	for (row = 0; row < keypad->rows; row++) {
 		gpio = of_get_named_gpio(np, "row-gpios", row);
@@ -320,10 +320,11 @@ static void samsung_keypad_parse_dt_gpio(struct device *dev,
 			continue;
 		}
 
-		ret = gpio_request(gpio, "keypad-row");
-		if (ret)
-			dev_err(dev, "keypad row[%d] gpio request failed\n",
-					row);
+		error = devm_gpio_request(dev, gpio, "keypad-row");
+		if (error)
+			dev_err(dev,
+				"keypad row[%d] gpio request failed: %d\n",
+				row, error);
 	}
 
 	for (col = 0; col < keypad->cols; col++) {
@@ -335,38 +336,22 @@ static void samsung_keypad_parse_dt_gpio(struct device *dev,
 			continue;
 		}
 
-		ret = gpio_request(gpio, "keypad-col");
-		if (ret)
-			dev_err(dev, "keypad column[%d] gpio request failed\n",
-					col);
+		error = devm_gpio_request(dev, gpio, "keypad-col");
+		if (error)
+			dev_err(dev,
+				"keypad column[%d] gpio request failed: %d\n",
+				col, error);
 	}
 }
-
-static void samsung_keypad_dt_gpio_free(struct samsung_keypad *keypad)
-{
-	int cnt;
-
-	for (cnt = 0; cnt < keypad->rows; cnt++)
-		if (gpio_is_valid(keypad->row_gpios[cnt]))
-			gpio_free(keypad->row_gpios[cnt]);
-
-	for (cnt = 0; cnt < keypad->cols; cnt++)
-		if (gpio_is_valid(keypad->col_gpios[cnt]))
-			gpio_free(keypad->col_gpios[cnt]);
-}
 #else
 static
 struct samsung_keypad_platdata *samsung_keypad_parse_dt(struct device *dev)
 {
 	return NULL;
 }
-
-static void samsung_keypad_dt_gpio_free(struct samsung_keypad *keypad)
-{
-}
 #endif
 
-static int __devinit samsung_keypad_probe(struct platform_device *pdev)
+static int samsung_keypad_probe(struct platform_device *pdev)
 {
 	const struct samsung_keypad_platdata *pdata;
 	const struct matrix_keymap_data *keymap_data;
@@ -405,36 +390,30 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev)
 	row_shift = get_count_order(pdata->cols);
 	keymap_size = (pdata->rows << row_shift) * sizeof(keypad->keycodes[0]);
 
-	keypad = kzalloc(sizeof(*keypad) + keymap_size, GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!keypad || !input_dev) {
-		error = -ENOMEM;
-		goto err_free_mem;
-	}
+	keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad) + keymap_size,
+			      GFP_KERNEL);
+	input_dev = devm_input_allocate_device(&pdev->dev);
+	if (!keypad || !input_dev)
+		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		error = -ENODEV;
-		goto err_free_mem;
-	}
+	if (!res)
+		return -ENODEV;
 
-	keypad->base = ioremap(res->start, resource_size(res));
-	if (!keypad->base) {
-		error = -EBUSY;
-		goto err_free_mem;
-	}
+	keypad->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!keypad->base)
+		return -EBUSY;
 
-	keypad->clk = clk_get(&pdev->dev, "keypad");
+	keypad->clk = devm_clk_get(&pdev->dev, "keypad");
 	if (IS_ERR(keypad->clk)) {
 		dev_err(&pdev->dev, "failed to get keypad clk\n");
-		error = PTR_ERR(keypad->clk);
-		goto err_unmap_base;
+		return PTR_ERR(keypad->clk);
 	}
 
 	error = clk_prepare(keypad->clk);
 	if (error) {
 		dev_err(&pdev->dev, "keypad clock prepare failed\n");
-		goto err_put_clk;
+		return error;
 	}
 
 	keypad->input_dev = input_dev;
@@ -479,14 +458,15 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev)
 	keypad->irq = platform_get_irq(pdev, 0);
 	if (keypad->irq < 0) {
 		error = keypad->irq;
-		goto err_put_clk;
+		goto err_unprepare_clk;
 	}
 
-	error = request_threaded_irq(keypad->irq, NULL, samsung_keypad_irq,
-			IRQF_ONESHOT, dev_name(&pdev->dev), keypad);
+	error = devm_request_threaded_irq(&pdev->dev, keypad->irq, NULL,
+					  samsung_keypad_irq, IRQF_ONESHOT,
+					  dev_name(&pdev->dev), keypad);
 	if (error) {
 		dev_err(&pdev->dev, "failed to register keypad interrupt\n");
-		goto err_put_clk;
+		goto err_unprepare_clk;
 	}
 
 	device_init_wakeup(&pdev->dev, pdata->wakeup);
@@ -495,7 +475,7 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev)
 
 	error = input_register_device(keypad->input_dev);
 	if (error)
-		goto err_free_irq;
+		goto err_disable_runtime_pm;
 
 	if (pdev->dev.of_node) {
 		devm_kfree(&pdev->dev, (void *)pdata->keymap_data->keymap);
@@ -504,26 +484,16 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev)
 	}
 	return 0;
 
-err_free_irq:
-	free_irq(keypad->irq, keypad);
+err_disable_runtime_pm:
 	pm_runtime_disable(&pdev->dev);
 	device_init_wakeup(&pdev->dev, 0);
 	platform_set_drvdata(pdev, NULL);
 err_unprepare_clk:
 	clk_unprepare(keypad->clk);
-err_put_clk:
-	clk_put(keypad->clk);
-	samsung_keypad_dt_gpio_free(keypad);
-err_unmap_base:
-	iounmap(keypad->base);
-err_free_mem:
-	input_free_device(input_dev);
-	kfree(keypad);
-
 	return error;
 }
 
-static int __devexit samsung_keypad_remove(struct platform_device *pdev)
+static int samsung_keypad_remove(struct platform_device *pdev)
 {
 	struct samsung_keypad *keypad = platform_get_drvdata(pdev);
 
@@ -533,18 +503,7 @@ static int __devexit samsung_keypad_remove(struct platform_device *pdev)
 
 	input_unregister_device(keypad->input_dev);
 
-	/*
-	 * It is safe to free IRQ after unregistering device because
-	 * samsung_keypad_close will shut off interrupts.
-	 */
-	free_irq(keypad->irq, keypad);
-
 	clk_unprepare(keypad->clk);
-	clk_put(keypad->clk);
-	samsung_keypad_dt_gpio_free(keypad);
-
-	iounmap(keypad->base);
-	kfree(keypad);
 
 	return 0;
 }
@@ -685,7 +644,7 @@ MODULE_DEVICE_TABLE(platform, samsung_keypad_driver_ids);
 
 static struct platform_driver samsung_keypad_driver = {
 	.probe		= samsung_keypad_probe,
-	.remove		= __devexit_p(samsung_keypad_remove),
+	.remove		= samsung_keypad_remove,
 	.driver		= {
 		.name	= "samsung-keypad",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c
index da54ad5..fdb9eb2 100644
--- a/drivers/input/keyboard/sh_keysc.c
+++ b/drivers/input/keyboard/sh_keysc.c
@@ -162,7 +162,7 @@ static irqreturn_t sh_keysc_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit sh_keysc_probe(struct platform_device *pdev)
+static int sh_keysc_probe(struct platform_device *pdev)
 {
 	struct sh_keysc_priv *priv;
 	struct sh_keysc_info *pdata;
@@ -272,7 +272,7 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev)
 	return error;
 }
 
-static int __devexit sh_keysc_remove(struct platform_device *pdev)
+static int sh_keysc_remove(struct platform_device *pdev)
 {
 	struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
 
@@ -331,7 +331,7 @@ static SIMPLE_DEV_PM_OPS(sh_keysc_dev_pm_ops,
 
 static struct platform_driver sh_keysc_device_driver = {
 	.probe		= sh_keysc_probe,
-	.remove		= __devexit_p(sh_keysc_remove),
+	.remove		= sh_keysc_remove,
 	.driver		= {
 		.name	= "sh_keysc",
 		.pm	= &sh_keysc_dev_pm_ops,
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c
index c7ca97f..695d237 100644
--- a/drivers/input/keyboard/spear-keyboard.c
+++ b/drivers/input/keyboard/spear-keyboard.c
@@ -55,15 +55,15 @@
 
 struct spear_kbd {
 	struct input_dev *input;
-	struct resource *res;
 	void __iomem *io_base;
 	struct clk *clk;
 	unsigned int irq;
 	unsigned int mode;
+	unsigned int suspended_rate;
 	unsigned short last_key;
 	unsigned short keycodes[NUM_ROWS * NUM_COLS];
 	bool rep;
-	unsigned int suspended_rate;
+	bool irq_wake_enabled;
 	u32 mode_ctl_reg;
 };
 
@@ -146,7 +146,7 @@ static void spear_kbd_close(struct input_dev *dev)
 }
 
 #ifdef CONFIG_OF
-static int __devinit spear_kbd_parse_dt(struct platform_device *pdev,
+static int spear_kbd_parse_dt(struct platform_device *pdev,
                                         struct spear_kbd *kbd)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -181,7 +181,7 @@ static inline int spear_kbd_parse_dt(struct platform_device *pdev,
 }
 #endif
 
-static int __devinit spear_kbd_probe(struct platform_device *pdev)
+static int spear_kbd_probe(struct platform_device *pdev)
 {
 	struct kbd_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	const struct matrix_keymap_data *keymap = pdata ? pdata->keymap : NULL;
@@ -203,12 +203,16 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev)
 		return irq;
 	}
 
-	kbd = kzalloc(sizeof(*kbd), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!kbd || !input_dev) {
-		dev_err(&pdev->dev, "out of memory\n");
-		error = -ENOMEM;
-		goto err_free_mem;
+	kbd = devm_kzalloc(&pdev->dev, sizeof(*kbd), GFP_KERNEL);
+	if (!kbd) {
+		dev_err(&pdev->dev, "not enough memory for driver data\n");
+		return -ENOMEM;
+	}
+
+	input_dev = devm_input_allocate_device(&pdev->dev);
+	if (!input_dev) {
+		dev_err(&pdev->dev, "unable to allocate input device\n");
+		return -ENOMEM;
 	}
 
 	kbd->input = input_dev;
@@ -217,37 +221,25 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev)
 	if (!pdata) {
 		error = spear_kbd_parse_dt(pdev, kbd);
 		if (error)
-			goto err_free_mem;
+			return error;
 	} else {
 		kbd->mode = pdata->mode;
 		kbd->rep = pdata->rep;
 		kbd->suspended_rate = pdata->suspended_rate;
 	}
 
-	kbd->res = request_mem_region(res->start, resource_size(res),
-				      pdev->name);
-	if (!kbd->res) {
-		dev_err(&pdev->dev, "keyboard region already claimed\n");
-		error = -EBUSY;
-		goto err_free_mem;
-	}
-
-	kbd->io_base = ioremap(res->start, resource_size(res));
+	kbd->io_base = devm_request_and_ioremap(&pdev->dev, res);
 	if (!kbd->io_base) {
-		dev_err(&pdev->dev, "ioremap failed for kbd_region\n");
-		error = -ENOMEM;
-		goto err_release_mem_region;
+		dev_err(&pdev->dev, "request-ioremap failed for kbd_region\n");
+		return -ENOMEM;
 	}
 
-	kbd->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(kbd->clk)) {
-		error = PTR_ERR(kbd->clk);
-		goto err_iounmap;
-	}
+	kbd->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(kbd->clk))
+		return PTR_ERR(kbd->clk);
 
 	input_dev->name = "Spear Keyboard";
 	input_dev->phys = "keyboard/input0";
-	input_dev->dev.parent = &pdev->dev;
 	input_dev->id.bustype = BUS_HOST;
 	input_dev->id.vendor = 0x0001;
 	input_dev->id.product = 0x0001;
@@ -259,7 +251,7 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev)
 					   kbd->keycodes, input_dev);
 	if (error) {
 		dev_err(&pdev->dev, "Failed to build keymap\n");
-		goto err_put_clk;
+		return error;
 	}
 
 	if (kbd->rep)
@@ -268,48 +260,36 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev)
 
 	input_set_drvdata(input_dev, kbd);
 
-	error = request_irq(irq, spear_kbd_interrupt, 0, "keyboard", kbd);
+	error = devm_request_irq(&pdev->dev, irq, spear_kbd_interrupt, 0,
+			"keyboard", kbd);
 	if (error) {
-		dev_err(&pdev->dev, "request_irq fail\n");
-		goto err_put_clk;
+		dev_err(&pdev->dev, "request_irq failed\n");
+		return error;
 	}
 
+	error = clk_prepare(kbd->clk);
+	if (error)
+		return error;
+
 	error = input_register_device(input_dev);
 	if (error) {
 		dev_err(&pdev->dev, "Unable to register keyboard device\n");
-		goto err_free_irq;
+		clk_unprepare(kbd->clk);
+		return error;
 	}
 
 	device_init_wakeup(&pdev->dev, 1);
 	platform_set_drvdata(pdev, kbd);
 
 	return 0;
-
-err_free_irq:
-	free_irq(kbd->irq, kbd);
-err_put_clk:
-	clk_put(kbd->clk);
-err_iounmap:
-	iounmap(kbd->io_base);
-err_release_mem_region:
-	release_mem_region(res->start, resource_size(res));
-err_free_mem:
-	input_free_device(input_dev);
-	kfree(kbd);
-
-	return error;
 }
 
-static int __devexit spear_kbd_remove(struct platform_device *pdev)
+static int spear_kbd_remove(struct platform_device *pdev)
 {
 	struct spear_kbd *kbd = platform_get_drvdata(pdev);
 
-	free_irq(kbd->irq, kbd);
 	input_unregister_device(kbd->input);
-	clk_put(kbd->clk);
-	iounmap(kbd->io_base);
-	release_mem_region(kbd->res->start, resource_size(kbd->res));
-	kfree(kbd);
+	clk_unprepare(kbd->clk);
 
 	device_init_wakeup(&pdev->dev, 0);
 	platform_set_drvdata(pdev, NULL);
@@ -333,7 +313,8 @@ static int spear_kbd_suspend(struct device *dev)
 	mode_ctl_reg = readl_relaxed(kbd->io_base + MODE_CTL_REG);
 
 	if (device_may_wakeup(&pdev->dev)) {
-		enable_irq_wake(kbd->irq);
+		if (!enable_irq_wake(kbd->irq))
+			kbd->irq_wake_enabled = true;
 
 		/*
 		 * reprogram the keyboard operating frequency as on some
@@ -379,7 +360,10 @@ static int spear_kbd_resume(struct device *dev)
 	mutex_lock(&input_dev->mutex);
 
 	if (device_may_wakeup(&pdev->dev)) {
-		disable_irq_wake(kbd->irq);
+		if (kbd->irq_wake_enabled) {
+			kbd->irq_wake_enabled = false;
+			disable_irq_wake(kbd->irq);
+		}
 	} else {
 		if (input_dev->users)
 			clk_enable(kbd->clk);
@@ -407,7 +391,7 @@ MODULE_DEVICE_TABLE(of, spear_kbd_id_table);
 
 static struct platform_driver spear_kbd_driver = {
 	.probe		= spear_kbd_probe,
-	.remove		= __devexit_p(spear_kbd_remove),
+	.remove		= spear_kbd_remove,
 	.driver		= {
 		.name	= "keyboard",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c
index 470a877..5cbec56 100644
--- a/drivers/input/keyboard/stmpe-keypad.c
+++ b/drivers/input/keyboard/stmpe-keypad.c
@@ -166,7 +166,7 @@ static irqreturn_t stmpe_keypad_irq(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
-static int __devinit stmpe_keypad_altfunc_init(struct stmpe_keypad *keypad)
+static int stmpe_keypad_altfunc_init(struct stmpe_keypad *keypad)
 {
 	const struct stmpe_keypad_variant *variant = keypad->variant;
 	unsigned int col_gpios = variant->col_gpios;
@@ -207,7 +207,7 @@ static int __devinit stmpe_keypad_altfunc_init(struct stmpe_keypad *keypad)
 	return stmpe_set_altfunc(stmpe, pins, STMPE_BLOCK_KEYPAD);
 }
 
-static int __devinit stmpe_keypad_chip_init(struct stmpe_keypad *keypad)
+static int stmpe_keypad_chip_init(struct stmpe_keypad *keypad)
 {
 	const struct stmpe_keypad_platform_data *plat = keypad->plat;
 	const struct stmpe_keypad_variant *variant = keypad->variant;
@@ -257,105 +257,131 @@ static int __devinit stmpe_keypad_chip_init(struct stmpe_keypad *keypad)
 			      (plat->debounce_ms << 1));
 }
 
-static int __devinit stmpe_keypad_probe(struct platform_device *pdev)
+static void stmpe_keypad_fill_used_pins(struct stmpe_keypad *keypad)
 {
-	struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
+	int row, col;
+
+	for (row = 0; row < STMPE_KEYPAD_MAX_ROWS; row++) {
+		for (col = 0; col < STMPE_KEYPAD_MAX_COLS; col++) {
+			int code = MATRIX_SCAN_CODE(row, col,
+						STMPE_KEYPAD_ROW_SHIFT);
+			if (keypad->keymap[code] != KEY_RESERVED) {
+				keypad->rows |= 1 << row;
+				keypad->cols |= 1 << col;
+			}
+		}
+	}
+}
+
+#ifdef CONFIG_OF
+static const struct stmpe_keypad_platform_data *
+stmpe_keypad_of_probe(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
 	struct stmpe_keypad_platform_data *plat;
+
+	if (!np)
+		return ERR_PTR(-ENODEV);
+
+	plat = devm_kzalloc(dev, sizeof(*plat), GFP_KERNEL);
+	if (!plat)
+		return ERR_PTR(-ENOMEM);
+
+	of_property_read_u32(np, "debounce-interval", &plat->debounce_ms);
+	of_property_read_u32(np, "st,scan-count", &plat->scan_count);
+
+	plat->no_autorepeat = of_property_read_bool(np, "st,no-autorepeat");
+
+	return plat;
+}
+#else
+static inline const struct stmpe_keypad_platform_data *
+stmpe_keypad_of_probe(struct device *dev)
+{
+	return ERR_PTR(-EINVAL);
+}
+#endif
+
+static int stmpe_keypad_probe(struct platform_device *pdev)
+{
+	struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
+	const struct stmpe_keypad_platform_data *plat;
 	struct stmpe_keypad *keypad;
 	struct input_dev *input;
-	int ret;
+	int error;
 	int irq;
-	int i;
 
 	plat = stmpe->pdata->keypad;
-	if (!plat)
-		return -ENODEV;
+	if (!plat) {
+		plat = stmpe_keypad_of_probe(&pdev->dev);
+		if (IS_ERR(plat))
+			return PTR_ERR(plat);
+	}
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
 		return irq;
 
-	keypad = kzalloc(sizeof(struct stmpe_keypad), GFP_KERNEL);
+	keypad = devm_kzalloc(&pdev->dev, sizeof(struct stmpe_keypad),
+			      GFP_KERNEL);
 	if (!keypad)
 		return -ENOMEM;
 
-	input = input_allocate_device();
-	if (!input) {
-		ret = -ENOMEM;
-		goto out_freekeypad;
-	}
+	input = devm_input_allocate_device(&pdev->dev);
+	if (!input)
+		return -ENOMEM;
 
 	input->name = "STMPE keypad";
 	input->id.bustype = BUS_I2C;
 	input->dev.parent = &pdev->dev;
 
-	ret = matrix_keypad_build_keymap(plat->keymap_data, NULL,
-					 STMPE_KEYPAD_MAX_ROWS,
-					 STMPE_KEYPAD_MAX_COLS,
-					 keypad->keymap, input);
-	if (ret)
-		goto out_freeinput;
+	error = matrix_keypad_build_keymap(plat->keymap_data, NULL,
+					   STMPE_KEYPAD_MAX_ROWS,
+					   STMPE_KEYPAD_MAX_COLS,
+					   keypad->keymap, input);
+	if (error)
+		return error;
 
 	input_set_capability(input, EV_MSC, MSC_SCAN);
 	if (!plat->no_autorepeat)
 		__set_bit(EV_REP, input->evbit);
 
-	for (i = 0; i < plat->keymap_data->keymap_size; i++) {
-		unsigned int key = plat->keymap_data->keymap[i];
-
-		keypad->cols |= 1 << KEY_COL(key);
-		keypad->rows |= 1 << KEY_ROW(key);
-	}
+	stmpe_keypad_fill_used_pins(keypad);
 
 	keypad->stmpe = stmpe;
 	keypad->plat = plat;
 	keypad->input = input;
 	keypad->variant = &stmpe_keypad_variants[stmpe->partnum];
 
-	ret = stmpe_keypad_chip_init(keypad);
-	if (ret < 0)
-		goto out_freeinput;
+	error = stmpe_keypad_chip_init(keypad);
+	if (error < 0)
+		return error;
 
-	ret = input_register_device(input);
-	if (ret) {
-		dev_err(&pdev->dev,
-			"unable to register input device: %d\n", ret);
-		goto out_freeinput;
+	error = devm_request_threaded_irq(&pdev->dev, irq,
+					  NULL, stmpe_keypad_irq,
+					  IRQF_ONESHOT, "stmpe-keypad", keypad);
+	if (error) {
+		dev_err(&pdev->dev, "unable to get irq: %d\n", error);
+		return error;
 	}
 
-	ret = request_threaded_irq(irq, NULL, stmpe_keypad_irq, IRQF_ONESHOT,
-				   "stmpe-keypad", keypad);
-	if (ret) {
-		dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
-		goto out_unregisterinput;
+	error = input_register_device(input);
+	if (error) {
+		dev_err(&pdev->dev,
+			"unable to register input device: %d\n", error);
+		return error;
 	}
 
 	platform_set_drvdata(pdev, keypad);
 
 	return 0;
-
-out_unregisterinput:
-	input_unregister_device(input);
-	input = NULL;
-out_freeinput:
-	input_free_device(input);
-out_freekeypad:
-	kfree(keypad);
-	return ret;
 }
 
-static int __devexit stmpe_keypad_remove(struct platform_device *pdev)
+static int stmpe_keypad_remove(struct platform_device *pdev)
 {
 	struct stmpe_keypad *keypad = platform_get_drvdata(pdev);
-	struct stmpe *stmpe = keypad->stmpe;
-	int irq = platform_get_irq(pdev, 0);
-
-	stmpe_disable(stmpe, STMPE_BLOCK_KEYPAD);
 
-	free_irq(irq, keypad);
-	input_unregister_device(keypad->input);
-	platform_set_drvdata(pdev, NULL);
-	kfree(keypad);
+	stmpe_disable(keypad->stmpe, STMPE_BLOCK_KEYPAD);
 
 	return 0;
 }
@@ -364,7 +390,7 @@ static struct platform_driver stmpe_keypad_driver = {
 	.driver.name	= "stmpe-keypad",
 	.driver.owner	= THIS_MODULE,
 	.probe		= stmpe_keypad_probe,
-	.remove		= __devexit_p(stmpe_keypad_remove),
+	.remove		= stmpe_keypad_remove,
 };
 module_platform_driver(stmpe_keypad_driver);
 
diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c
index 7d498e6..2fb0d76 100644
--- a/drivers/input/keyboard/tc3589x-keypad.c
+++ b/drivers/input/keyboard/tc3589x-keypad.c
@@ -299,7 +299,7 @@ static void tc3589x_keypad_close(struct input_dev *input)
 	tc3589x_keypad_disable(keypad);
 }
 
-static int __devinit tc3589x_keypad_probe(struct platform_device *pdev)
+static int tc3589x_keypad_probe(struct platform_device *pdev)
 {
 	struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
 	struct tc_keypad *keypad;
@@ -382,7 +382,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit tc3589x_keypad_remove(struct platform_device *pdev)
+static int tc3589x_keypad_remove(struct platform_device *pdev)
 {
 	struct tc_keypad *keypad = platform_get_drvdata(pdev);
 	int irq = platform_get_irq(pdev, 0);
@@ -448,7 +448,7 @@ static struct platform_driver tc3589x_keypad_driver = {
 		.pm	= &tc3589x_keypad_dev_pm_ops,
 	},
 	.probe	= tc3589x_keypad_probe,
-	.remove	= __devexit_p(tc3589x_keypad_remove),
+	.remove	= tc3589x_keypad_remove,
 };
 module_platform_driver(tc3589x_keypad_driver);
 
diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c
index c355cdd..bfc832c 100644
--- a/drivers/input/keyboard/tca6416-keypad.c
+++ b/drivers/input/keyboard/tca6416-keypad.c
@@ -166,7 +166,7 @@ static void tca6416_keys_close(struct input_dev *dev)
 		disable_irq(chip->irqnum);
 }
 
-static int __devinit tca6416_setup_registers(struct tca6416_keypad_chip *chip)
+static int tca6416_setup_registers(struct tca6416_keypad_chip *chip)
 {
 	int error;
 
@@ -197,7 +197,7 @@ static int __devinit tca6416_setup_registers(struct tca6416_keypad_chip *chip)
 	return 0;
 }
 
-static int __devinit tca6416_keypad_probe(struct i2c_client *client,
+static int tca6416_keypad_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
 	struct tca6416_keys_platform_data *pdata;
@@ -313,7 +313,7 @@ fail1:
 	return error;
 }
 
-static int __devexit tca6416_keypad_remove(struct i2c_client *client)
+static int tca6416_keypad_remove(struct i2c_client *client)
 {
 	struct tca6416_keypad_chip *chip = i2c_get_clientdata(client);
 
@@ -361,7 +361,7 @@ static struct i2c_driver tca6416_keypad_driver = {
 		.pm	= &tca6416_keypad_dev_pm_ops,
 	},
 	.probe		= tca6416_keypad_probe,
-	.remove		= __devexit_p(tca6416_keypad_remove),
+	.remove		= tca6416_keypad_remove,
 	.id_table	= tca6416_id,
 };
 
diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c
index 893869b..f1e966b 100644
--- a/drivers/input/keyboard/tca8418_keypad.c
+++ b/drivers/input/keyboard/tca8418_keypad.c
@@ -241,7 +241,7 @@ exit:
 /*
  * Configure the TCA8418 for keypad operation
  */
-static int __devinit tca8418_configure(struct tca8418_keypad *keypad_data)
+static int tca8418_configure(struct tca8418_keypad *keypad_data)
 {
 	int reg, error;
 
@@ -270,7 +270,7 @@ static int __devinit tca8418_configure(struct tca8418_keypad *keypad_data)
 	return error;
 }
 
-static int __devinit tca8418_keypad_probe(struct i2c_client *client,
+static int tca8418_keypad_probe(struct i2c_client *client,
 					  const struct i2c_device_id *id)
 {
 	const struct tca8418_keypad_platform_data *pdata =
@@ -388,7 +388,7 @@ fail1:
 	return error;
 }
 
-static int __devexit tca8418_keypad_remove(struct i2c_client *client)
+static int tca8418_keypad_remove(struct i2c_client *client)
 {
 	struct tca8418_keypad *keypad_data = i2c_get_clientdata(client);
 
@@ -408,7 +408,7 @@ static struct i2c_driver tca8418_keypad_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= tca8418_keypad_probe,
-	.remove		= __devexit_p(tca8418_keypad_remove),
+	.remove		= tca8418_keypad_remove,
 	.id_table	= tca8418_id,
 };
 
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index 5faaf25..c76f968 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -87,7 +87,7 @@ struct tegra_kbc {
 	struct clk *clk;
 };
 
-static const u32 tegra_kbc_default_keymap[] __devinitdata = {
+static const u32 tegra_kbc_default_keymap[] = {
 	KEY(0, 2, KEY_W),
 	KEY(0, 3, KEY_S),
 	KEY(0, 4, KEY_A),
@@ -223,7 +223,7 @@ static const u32 tegra_kbc_default_keymap[] __devinitdata = {
 };
 
 static const
-struct matrix_keymap_data tegra_kbc_default_keymap_data __devinitdata = {
+struct matrix_keymap_data tegra_kbc_default_keymap_data = {
 	.keymap		= tegra_kbc_default_keymap,
 	.keymap_size	= ARRAY_SIZE(tegra_kbc_default_keymap),
 };
@@ -573,7 +573,7 @@ static void tegra_kbc_close(struct input_dev *dev)
 	return tegra_kbc_stop(kbc);
 }
 
-static bool __devinit
+static bool
 tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata,
 			struct device *dev, unsigned int *num_rows)
 {
@@ -619,7 +619,7 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata,
 }
 
 #ifdef CONFIG_OF
-static struct tegra_kbc_platform_data * __devinit tegra_kbc_dt_parse_pdata(
+static struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata(
 	struct platform_device *pdev)
 {
 	struct tegra_kbc_platform_data *pdata;
@@ -670,7 +670,7 @@ static inline struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata(
 }
 #endif
 
-static int __devinit tegra_kbd_setup_keymap(struct tegra_kbc *kbc)
+static int tegra_kbd_setup_keymap(struct tegra_kbc *kbc)
 {
 	const struct tegra_kbc_platform_data *pdata = kbc->pdata;
 	const struct matrix_keymap_data *keymap_data = pdata->keymap_data;
@@ -697,7 +697,7 @@ static int __devinit tegra_kbd_setup_keymap(struct tegra_kbc *kbc)
 	return retval;
 }
 
-static int __devinit tegra_kbc_probe(struct platform_device *pdev)
+static int tegra_kbc_probe(struct platform_device *pdev)
 {
 	const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data;
 	struct tegra_kbc *kbc;
@@ -838,7 +838,7 @@ err_free_pdata:
 	return err;
 }
 
-static int __devexit tegra_kbc_remove(struct platform_device *pdev)
+static int tegra_kbc_remove(struct platform_device *pdev)
 {
 	struct tegra_kbc *kbc = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -954,7 +954,7 @@ MODULE_DEVICE_TABLE(of, tegra_kbc_of_match);
 
 static struct platform_driver tegra_kbc_driver = {
 	.probe		= tegra_kbc_probe,
-	.remove		= __devexit_p(tegra_kbc_remove),
+	.remove		= tegra_kbc_remove,
 	.driver	= {
 		.name	= "tegra-kbc",
 		.owner  = THIS_MODULE,
diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c
index 4c34f21..ee16350 100644
--- a/drivers/input/keyboard/tnetv107x-keypad.c
+++ b/drivers/input/keyboard/tnetv107x-keypad.c
@@ -153,7 +153,7 @@ static void keypad_stop(struct input_dev *dev)
 	clk_disable(kp->clk);
 }
 
-static int __devinit keypad_probe(struct platform_device *pdev)
+static int keypad_probe(struct platform_device *pdev)
 {
 	const struct matrix_keypad_platform_data *pdata;
 	const struct matrix_keymap_data *keymap_data;
@@ -301,7 +301,7 @@ error_res:
 	return error;
 }
 
-static int __devexit keypad_remove(struct platform_device *pdev)
+static int keypad_remove(struct platform_device *pdev)
 {
 	struct keypad_data *kp = platform_get_drvdata(pdev);
 
@@ -319,7 +319,7 @@ static int __devexit keypad_remove(struct platform_device *pdev)
 
 static struct platform_driver keypad_driver = {
 	.probe		= keypad_probe,
-	.remove		= __devexit_p(keypad_remove),
+	.remove		= keypad_remove,
 	.driver.name	= "tnetv107x-keypad",
 	.driver.owner	= THIS_MODULE,
 };
diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c
index a2c6f79..04f84fd 100644
--- a/drivers/input/keyboard/twl4030_keypad.c
+++ b/drivers/input/keyboard/twl4030_keypad.c
@@ -271,7 +271,7 @@ static irqreturn_t do_kp_irq(int irq, void *_kp)
 	return IRQ_HANDLED;
 }
 
-static int __devinit twl4030_kp_program(struct twl4030_keypad *kp)
+static int twl4030_kp_program(struct twl4030_keypad *kp)
 {
 	u8 reg;
 	int i;
@@ -328,7 +328,7 @@ static int __devinit twl4030_kp_program(struct twl4030_keypad *kp)
  * Registers keypad device with input subsystem
  * and configures TWL4030 keypad registers
  */
-static int __devinit twl4030_kp_probe(struct platform_device *pdev)
+static int twl4030_kp_probe(struct platform_device *pdev)
 {
 	struct twl4030_keypad_data *pdata = pdev->dev.platform_data;
 	const struct matrix_keymap_data *keymap_data;
@@ -432,7 +432,7 @@ err1:
 	return error;
 }
 
-static int __devexit twl4030_kp_remove(struct platform_device *pdev)
+static int twl4030_kp_remove(struct platform_device *pdev)
 {
 	struct twl4030_keypad *kp = platform_get_drvdata(pdev);
 
@@ -452,7 +452,7 @@ static int __devexit twl4030_kp_remove(struct platform_device *pdev)
 
 static struct platform_driver twl4030_kp_driver = {
 	.probe		= twl4030_kp_probe,
-	.remove		= __devexit_p(twl4030_kp_remove),
+	.remove		= twl4030_kp_remove,
 	.driver		= {
 		.name	= "twl4030_keypad",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c
index e0f6cd1..ee163be 100644
--- a/drivers/input/keyboard/w90p910_keypad.c
+++ b/drivers/input/keyboard/w90p910_keypad.c
@@ -118,7 +118,7 @@ static void w90p910_keypad_close(struct input_dev *dev)
 	clk_disable(keypad->clk);
 }
 
-static int __devinit w90p910_keypad_probe(struct platform_device *pdev)
+static int w90p910_keypad_probe(struct platform_device *pdev)
 {
 	const struct w90p910_keypad_platform_data *pdata =
 						pdev->dev.platform_data;
@@ -234,7 +234,7 @@ failed_free:
 	return error;
 }
 
-static int __devexit w90p910_keypad_remove(struct platform_device *pdev)
+static int w90p910_keypad_remove(struct platform_device *pdev)
 {
 	struct w90p910_keypad *keypad = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -257,7 +257,7 @@ static int __devexit w90p910_keypad_remove(struct platform_device *pdev)
 
 static struct platform_driver w90p910_keypad_driver = {
 	.probe		= w90p910_keypad_probe,
-	.remove		= __devexit_p(w90p910_keypad_remove),
+	.remove		= w90p910_keypad_remove,
 	.driver		= {
 		.name	= "nuc900-kpi",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/matrix-keymap.c b/drivers/input/matrix-keymap.c
index 443ad64b..419cb6b 100644
--- a/drivers/input/matrix-keymap.c
+++ b/drivers/input/matrix-keymap.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/gfp.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/input.h>
@@ -122,6 +123,11 @@ static int matrix_keypad_parse_of_keymap(const char *propname,
  * it will attempt load the keymap from property specified by @keymap_name
  * argument (or "linux,keymap" if @keymap_name is %NULL).
  *
+ * If @keymap is %NULL the function will automatically allocate managed
+ * block of memory to store the keymap. This memory will be associated with
+ * the parent device and automatically freed when device unbinds from the
+ * driver.
+ *
  * Callers are expected to set up input_dev->dev.parent before calling this
  * function.
  */
@@ -132,12 +138,27 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
 			       struct input_dev *input_dev)
 {
 	unsigned int row_shift = get_count_order(cols);
+	size_t max_keys = rows << row_shift;
 	int i;
 	int error;
 
+	if (WARN_ON(!input_dev->dev.parent))
+		return -EINVAL;
+
+	if (!keymap) {
+		keymap = devm_kzalloc(input_dev->dev.parent,
+				      max_keys * sizeof(*keymap),
+				      GFP_KERNEL);
+		if (!keymap) {
+			dev_err(input_dev->dev.parent,
+				"Unable to allocate memory for keymap");
+			return -ENOMEM;
+		}
+	}
+
 	input_dev->keycode = keymap;
 	input_dev->keycodesize = sizeof(*keymap);
-	input_dev->keycodemax = rows << row_shift;
+	input_dev->keycodemax = max_keys;
 
 	__set_bit(EV_KEY, input_dev->evbit);
 
diff --git a/drivers/input/misc/88pm80x_onkey.c b/drivers/input/misc/88pm80x_onkey.c
index 7f26e7b..ee43e5b 100644
--- a/drivers/input/misc/88pm80x_onkey.c
+++ b/drivers/input/misc/88pm80x_onkey.c
@@ -62,7 +62,7 @@ static irqreturn_t pm80x_onkey_handler(int irq, void *data)
 static SIMPLE_DEV_PM_OPS(pm80x_onkey_pm_ops, pm80x_dev_suspend,
 			 pm80x_dev_resume);
 
-static int __devinit pm80x_onkey_probe(struct platform_device *pdev)
+static int pm80x_onkey_probe(struct platform_device *pdev)
 {
 
 	struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);
@@ -139,7 +139,7 @@ out:
 	return err;
 }
 
-static int __devexit pm80x_onkey_remove(struct platform_device *pdev)
+static int pm80x_onkey_remove(struct platform_device *pdev)
 {
 	struct pm80x_onkey_info *info = platform_get_drvdata(pdev);
 
@@ -157,7 +157,7 @@ static struct platform_driver pm80x_onkey_driver = {
 		   .pm = &pm80x_onkey_pm_ops,
 		   },
 	.probe = pm80x_onkey_probe,
-	.remove = __devexit_p(pm80x_onkey_remove),
+	.remove = pm80x_onkey_remove,
 };
 
 module_platform_driver(pm80x_onkey_driver);
diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c
index f9ce183..abd8453 100644
--- a/drivers/input/misc/88pm860x_onkey.c
+++ b/drivers/input/misc/88pm860x_onkey.c
@@ -56,7 +56,7 @@ static irqreturn_t pm860x_onkey_handler(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int __devinit pm860x_onkey_probe(struct platform_device *pdev)
+static int pm860x_onkey_probe(struct platform_device *pdev)
 {
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct pm860x_onkey_info *info;
@@ -121,7 +121,7 @@ out:
 	return ret;
 }
 
-static int __devexit pm860x_onkey_remove(struct platform_device *pdev)
+static int pm860x_onkey_remove(struct platform_device *pdev)
 {
 	struct pm860x_onkey_info *info = platform_get_drvdata(pdev);
 
@@ -161,7 +161,7 @@ static struct platform_driver pm860x_onkey_driver = {
 		.pm	= &pm860x_onkey_pm_ops,
 	},
 	.probe		= pm860x_onkey_probe,
-	.remove		= __devexit_p(pm860x_onkey_remove),
+	.remove		= pm860x_onkey_remove,
 };
 module_platform_driver(pm860x_onkey_driver);
 
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 7c0f1ec..259ef31 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -72,6 +72,16 @@ config INPUT_AD714X_SPI
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad714x-spi.
 
+config INPUT_ARIZONA_HAPTICS
+	tristate "Arizona haptics support"
+	depends on MFD_ARIZONA && SND_SOC
+	select INPUT_FF_MEMLESS
+	help
+	  Say Y to enable support for the haptics module in Arizona CODECs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called arizona-haptics.
+
 config INPUT_BMA150
 	tristate "BMA150/SMB380 acceleration sensor support"
 	depends on I2C
@@ -290,8 +300,7 @@ config INPUT_ATI_REMOTE2
 	  called ati_remote2.
 
 config INPUT_KEYSPAN_REMOTE
-	tristate "Keyspan DMR USB remote control (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	tristate "Keyspan DMR USB remote control"
 	depends on USB_ARCH_HAS_HCD
 	select USB
 	help
@@ -340,7 +349,6 @@ config INPUT_POWERMATE
 
 config INPUT_YEALINK
 	tristate "Yealink usb-p1k voip phone"
-	depends on EXPERIMENTAL
 	depends on USB_ARCH_HAS_HCD
 	select USB
 	help
@@ -356,7 +364,6 @@ config INPUT_YEALINK
 
 config INPUT_CM109
 	tristate "C-Media CM109 USB I/O Controller"
-	depends on EXPERIMENTAL
 	depends on USB_ARCH_HAS_HCD
 	select USB
 	help
@@ -367,6 +374,16 @@ config INPUT_CM109
 	  To compile this driver as a module, choose M here: the module will be
 	  called cm109.
 
+config INPUT_RETU_PWRBUTTON
+	tristate "Retu Power button Driver"
+	depends on MFD_RETU
+	help
+	  Say Y here if you want to enable power key reporting via the
+	  Retu chips found in Nokia Internet Tablets (770, N800, N810).
+
+	  To compile this driver as a module, choose M here. The module will
+	  be called retu-pwrbutton.
+
 config INPUT_TWL4030_PWRBUTTON
 	tristate "TWL4030 Power button Driver"
 	depends on TWL4030_CORE
@@ -434,7 +451,7 @@ config INPUT_PCF50633_PMU
 
 config INPUT_PCF8574
 	tristate "PCF8574 Keypad input device"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  Say Y here if you want to support a keypad connected via I2C
 	  with a PCF8574.
@@ -444,7 +461,7 @@ config INPUT_PCF8574
 
 config INPUT_PWM_BEEPER
 	tristate "PWM beeper support"
-	depends on HAVE_PWM
+	depends on HAVE_PWM || PWM
 	help
 	  Say Y here to get support for PWM based beeper devices.
 
@@ -486,6 +503,16 @@ config INPUT_DA9052_ONKEY
 	  To compile this driver as a module, choose M here: the
 	  module will be called da9052_onkey.
 
+config INPUT_DA9055_ONKEY
+	tristate "Dialog Semiconductor DA9055 ONKEY"
+	depends on MFD_DA9055
+	help
+	  Support the ONKEY of DA9055 PMICs as an input device
+	  reporting power button status.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called da9055_onkey.
+
 config INPUT_DM355EVM
 	tristate "TI DaVinci DM355 EVM Keypad and IR Remote"
 	depends on MFD_DM355EVM_MSP
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 83fe6f5..1f1e1b1 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_INPUT_ADXL34X)		+= adxl34x.o
 obj-$(CONFIG_INPUT_ADXL34X_I2C)		+= adxl34x-i2c.o
 obj-$(CONFIG_INPUT_ADXL34X_SPI)		+= adxl34x-spi.o
 obj-$(CONFIG_INPUT_APANEL)		+= apanel.o
+obj-$(CONFIG_INPUT_ARIZONA_HAPTICS)	+= arizona-haptics.o
 obj-$(CONFIG_INPUT_ATI_REMOTE2)		+= ati_remote2.o
 obj-$(CONFIG_INPUT_ATLAS_BTNS)		+= atlas_btns.o
 obj-$(CONFIG_INPUT_BFIN_ROTARY)		+= bfin_rotary.o
@@ -23,6 +24,7 @@ obj-$(CONFIG_INPUT_CMA3000)		+= cma3000_d0x.o
 obj-$(CONFIG_INPUT_CMA3000_I2C)		+= cma3000_d0x_i2c.o
 obj-$(CONFIG_INPUT_COBALT_BTNS)		+= cobalt_btns.o
 obj-$(CONFIG_INPUT_DA9052_ONKEY)	+= da9052_onkey.o
+obj-$(CONFIG_INPUT_DA9055_ONKEY)	+= da9055_onkey.o
 obj-$(CONFIG_INPUT_DM355EVM)		+= dm355evm_keys.o
 obj-$(CONFIG_INPUT_GP2A)		+= gp2ap002a00f.o
 obj-$(CONFIG_INPUT_GPIO_TILT_POLLED)	+= gpio_tilt_polled.o
@@ -45,6 +47,7 @@ obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY)	+= pmic8xxx-pwrkey.o
 obj-$(CONFIG_INPUT_POWERMATE)		+= powermate.o
 obj-$(CONFIG_INPUT_PWM_BEEPER)		+= pwm-beeper.o
 obj-$(CONFIG_INPUT_RB532_BUTTON)	+= rb532_button.o
+obj-$(CONFIG_INPUT_RETU_PWRBUTTON)	+= retu-pwrbutton.o
 obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER)	+= rotary_encoder.o
 obj-$(CONFIG_INPUT_SGI_BTNS)		+= sgi_btns.o
 obj-$(CONFIG_INPUT_SPARCSPKR)		+= sparcspkr.o
diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c
index 84ec691..2f090b4 100644
--- a/drivers/input/misc/ab8500-ponkey.c
+++ b/drivers/input/misc/ab8500-ponkey.c
@@ -45,7 +45,7 @@ static irqreturn_t ab8500_ponkey_handler(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int __devinit ab8500_ponkey_probe(struct platform_device *pdev)
+static int ab8500_ponkey_probe(struct platform_device *pdev)
 {
 	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
 	struct ab8500_ponkey *ponkey;
@@ -118,7 +118,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit ab8500_ponkey_remove(struct platform_device *pdev)
+static int ab8500_ponkey_remove(struct platform_device *pdev)
 {
 	struct ab8500_ponkey *ponkey = platform_get_drvdata(pdev);
 
@@ -146,7 +146,7 @@ static struct platform_driver ab8500_ponkey_driver = {
 		.of_match_table = of_match_ptr(ab8500_ponkey_match),
 	},
 	.probe		= ab8500_ponkey_probe,
-	.remove		= __devexit_p(ab8500_ponkey_remove),
+	.remove		= ab8500_ponkey_remove,
 };
 module_platform_driver(ab8500_ponkey_driver);
 
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c
index c8a7901..29d2064 100644
--- a/drivers/input/misc/ad714x-i2c.c
+++ b/drivers/input/misc/ad714x-i2c.c
@@ -72,7 +72,7 @@ static int ad714x_i2c_read(struct ad714x_chip *chip,
 	return 0;
 }
 
-static int __devinit ad714x_i2c_probe(struct i2c_client *client,
+static int ad714x_i2c_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	struct ad714x_chip *chip;
@@ -87,7 +87,7 @@ static int __devinit ad714x_i2c_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int __devexit ad714x_i2c_remove(struct i2c_client *client)
+static int ad714x_i2c_remove(struct i2c_client *client)
 {
 	struct ad714x_chip *chip = i2c_get_clientdata(client);
 
@@ -112,7 +112,7 @@ static struct i2c_driver ad714x_i2c_driver = {
 		.pm   = &ad714x_i2c_pm,
 	},
 	.probe    = ad714x_i2c_probe,
-	.remove   = __devexit_p(ad714x_i2c_remove),
+	.remove   = ad714x_i2c_remove,
 	.id_table = ad714x_id,
 };
 
diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c
index 75f6136..bdccca4 100644
--- a/drivers/input/misc/ad714x-spi.c
+++ b/drivers/input/misc/ad714x-spi.c
@@ -83,7 +83,7 @@ static int ad714x_spi_write(struct ad714x_chip *chip,
 	return 0;
 }
 
-static int __devinit ad714x_spi_probe(struct spi_device *spi)
+static int ad714x_spi_probe(struct spi_device *spi)
 {
 	struct ad714x_chip *chip;
 	int err;
@@ -103,7 +103,7 @@ static int __devinit ad714x_spi_probe(struct spi_device *spi)
 	return 0;
 }
 
-static int __devexit ad714x_spi_remove(struct spi_device *spi)
+static int ad714x_spi_remove(struct spi_device *spi)
 {
 	struct ad714x_chip *chip = spi_get_drvdata(spi);
 
@@ -120,7 +120,7 @@ static struct spi_driver ad714x_spi_driver = {
 		.pm	= &ad714x_spi_pm,
 	},
 	.probe		= ad714x_spi_probe,
-	.remove		= __devexit_p(ad714x_spi_remove),
+	.remove		= ad714x_spi_remove,
 };
 
 module_spi_driver(ad714x_spi_driver);
diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c
index dd1d1c1..535dda4 100644
--- a/drivers/input/misc/adxl34x-i2c.c
+++ b/drivers/input/misc/adxl34x-i2c.c
@@ -73,7 +73,7 @@ static const struct adxl34x_bus_ops adxl34x_i2c_bops = {
 	.read_block	= adxl34x_i2c_read_block,
 };
 
-static int __devinit adxl34x_i2c_probe(struct i2c_client *client,
+static int adxl34x_i2c_probe(struct i2c_client *client,
 				       const struct i2c_device_id *id)
 {
 	struct adxl34x *ac;
@@ -98,7 +98,7 @@ static int __devinit adxl34x_i2c_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int __devexit adxl34x_i2c_remove(struct i2c_client *client)
+static int adxl34x_i2c_remove(struct i2c_client *client)
 {
 	struct adxl34x *ac = i2c_get_clientdata(client);
 
@@ -144,7 +144,7 @@ static struct i2c_driver adxl34x_driver = {
 		.pm = &adxl34x_i2c_pm,
 	},
 	.probe    = adxl34x_i2c_probe,
-	.remove   = __devexit_p(adxl34x_i2c_remove),
+	.remove   = adxl34x_i2c_remove,
 	.id_table = adxl34x_id,
 };
 
diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c
index 820a802..ad5f40d 100644
--- a/drivers/input/misc/adxl34x-spi.c
+++ b/drivers/input/misc/adxl34x-spi.c
@@ -65,7 +65,7 @@ static const struct adxl34x_bus_ops adxl34x_spi_bops = {
 	.read_block	= adxl34x_spi_read_block,
 };
 
-static int __devinit adxl34x_spi_probe(struct spi_device *spi)
+static int adxl34x_spi_probe(struct spi_device *spi)
 {
 	struct adxl34x *ac;
 
@@ -87,7 +87,7 @@ static int __devinit adxl34x_spi_probe(struct spi_device *spi)
 	return 0;
 }
 
-static int __devexit adxl34x_spi_remove(struct spi_device *spi)
+static int adxl34x_spi_remove(struct spi_device *spi)
 {
 	struct adxl34x *ac = dev_get_drvdata(&spi->dev);
 
@@ -126,7 +126,7 @@ static struct spi_driver adxl34x_driver = {
 		.pm = &adxl34x_spi_pm,
 	},
 	.probe   = adxl34x_spi_probe,
-	.remove  = __devexit_p(adxl34x_spi_remove),
+	.remove  = adxl34x_spi_remove,
 };
 
 module_spi_driver(adxl34x_driver);
diff --git a/drivers/input/misc/arizona-haptics.c b/drivers/input/misc/arizona-haptics.c
new file mode 100644
index 0000000..7a04f54
--- /dev/null
+++ b/drivers/input/misc/arizona-haptics.c
@@ -0,0 +1,255 @@
+/*
+ * Arizona haptics driver
+ *
+ * Copyright 2012 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 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <linux/mfd/arizona/core.h>
+#include <linux/mfd/arizona/pdata.h>
+#include <linux/mfd/arizona/registers.h>
+
+struct arizona_haptics {
+	struct arizona *arizona;
+	struct input_dev *input_dev;
+	struct work_struct work;
+
+	struct mutex mutex;
+	u8 intensity;
+};
+
+static void arizona_haptics_work(struct work_struct *work)
+{
+	struct arizona_haptics *haptics = container_of(work,
+						       struct arizona_haptics,
+						       work);
+	struct arizona *arizona = haptics->arizona;
+	struct mutex *dapm_mutex = &arizona->dapm->card->dapm_mutex;
+	int ret;
+
+	if (!haptics->arizona->dapm) {
+		dev_err(arizona->dev, "No DAPM context\n");
+		return;
+	}
+
+	if (haptics->intensity) {
+		ret = regmap_update_bits(arizona->regmap,
+					 ARIZONA_HAPTICS_PHASE_2_INTENSITY,
+					 ARIZONA_PHASE2_INTENSITY_MASK,
+					 haptics->intensity);
+		if (ret != 0) {
+			dev_err(arizona->dev, "Failed to set intensity: %d\n",
+				ret);
+			return;
+		}
+
+		/* This enable sequence will be a noop if already enabled */
+		ret = regmap_update_bits(arizona->regmap,
+					 ARIZONA_HAPTICS_CONTROL_1,
+					 ARIZONA_HAP_CTRL_MASK,
+					 1 << ARIZONA_HAP_CTRL_SHIFT);
+		if (ret != 0) {
+			dev_err(arizona->dev, "Failed to start haptics: %d\n",
+				ret);
+			return;
+		}
+
+		mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+		ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS");
+		if (ret != 0) {
+			dev_err(arizona->dev, "Failed to start HAPTICS: %d\n",
+				ret);
+			mutex_unlock(dapm_mutex);
+			return;
+		}
+
+		ret = snd_soc_dapm_sync(arizona->dapm);
+		if (ret != 0) {
+			dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
+				ret);
+			mutex_unlock(dapm_mutex);
+			return;
+		}
+
+		mutex_unlock(dapm_mutex);
+
+	} else {
+		/* This disable sequence will be a noop if already enabled */
+		mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+		ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS");
+		if (ret != 0) {
+			dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n",
+				ret);
+			mutex_unlock(dapm_mutex);
+			return;
+		}
+
+		ret = snd_soc_dapm_sync(arizona->dapm);
+		if (ret != 0) {
+			dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
+				ret);
+			mutex_unlock(dapm_mutex);
+			return;
+		}
+
+		mutex_unlock(dapm_mutex);
+
+		ret = regmap_update_bits(arizona->regmap,
+					 ARIZONA_HAPTICS_CONTROL_1,
+					 ARIZONA_HAP_CTRL_MASK,
+					 1 << ARIZONA_HAP_CTRL_SHIFT);
+		if (ret != 0) {
+			dev_err(arizona->dev, "Failed to stop haptics: %d\n",
+				ret);
+			return;
+		}
+	}
+}
+
+static int arizona_haptics_play(struct input_dev *input, void *data,
+				struct ff_effect *effect)
+{
+	struct arizona_haptics *haptics = input_get_drvdata(input);
+	struct arizona *arizona = haptics->arizona;
+
+	if (!arizona->dapm) {
+		dev_err(arizona->dev, "No DAPM context\n");
+		return -EBUSY;
+	}
+
+	if (effect->u.rumble.strong_magnitude) {
+		/* Scale the magnitude into the range the device supports */
+		if (arizona->pdata.hap_act) {
+			haptics->intensity =
+				effect->u.rumble.strong_magnitude >> 9;
+			if (effect->direction < 0x8000)
+				haptics->intensity += 0x7f;
+		} else {
+			haptics->intensity =
+				effect->u.rumble.strong_magnitude >> 8;
+		}
+	} else {
+		haptics->intensity = 0;
+	}
+
+	schedule_work(&haptics->work);
+
+	return 0;
+}
+
+static void arizona_haptics_close(struct input_dev *input)
+{
+	struct arizona_haptics *haptics = input_get_drvdata(input);
+	struct mutex *dapm_mutex = &haptics->arizona->dapm->card->dapm_mutex;
+
+	cancel_work_sync(&haptics->work);
+
+	mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+	if (haptics->arizona->dapm)
+		snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS");
+
+	mutex_unlock(dapm_mutex);
+}
+
+static int arizona_haptics_probe(struct platform_device *pdev)
+{
+	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+	struct arizona_haptics *haptics;
+	int ret;
+
+	haptics = devm_kzalloc(&pdev->dev, sizeof(*haptics), GFP_KERNEL);
+	if (!haptics)
+		return -ENOMEM;
+
+	haptics->arizona = arizona;
+
+	ret = regmap_update_bits(arizona->regmap, ARIZONA_HAPTICS_CONTROL_1,
+				 ARIZONA_HAP_ACT, arizona->pdata.hap_act);
+	if (ret != 0) {
+		dev_err(arizona->dev, "Failed to set haptics actuator: %d\n",
+			ret);
+		return ret;
+	}
+
+	INIT_WORK(&haptics->work, arizona_haptics_work);
+
+	haptics->input_dev = input_allocate_device();
+	if (haptics->input_dev == NULL) {
+		dev_err(arizona->dev, "Failed to allocate input device\n");
+		return -ENOMEM;
+	}
+
+	input_set_drvdata(haptics->input_dev, haptics);
+
+	haptics->input_dev->name = "arizona:haptics";
+	haptics->input_dev->dev.parent = pdev->dev.parent;
+	haptics->input_dev->close = arizona_haptics_close;
+	__set_bit(FF_RUMBLE, haptics->input_dev->ffbit);
+
+	ret = input_ff_create_memless(haptics->input_dev, NULL,
+				      arizona_haptics_play);
+	if (ret < 0) {
+		dev_err(arizona->dev, "input_ff_create_memless() failed: %d\n",
+			ret);
+		goto err_ialloc;
+	}
+
+	ret = input_register_device(haptics->input_dev);
+	if (ret < 0) {
+		dev_err(arizona->dev, "couldn't register input device: %d\n",
+			ret);
+		goto err_iff;
+	}
+
+	platform_set_drvdata(pdev, haptics);
+
+	return 0;
+
+err_iff:
+	if (haptics->input_dev)
+		input_ff_destroy(haptics->input_dev);
+err_ialloc:
+	input_free_device(haptics->input_dev);
+
+	return ret;
+}
+
+static int arizona_haptics_remove(struct platform_device *pdev)
+{
+	struct arizona_haptics *haptics = platform_get_drvdata(pdev);
+
+	input_unregister_device(haptics->input_dev);
+
+	return 0;
+}
+
+static struct platform_driver arizona_haptics_driver = {
+	.probe		= arizona_haptics_probe,
+	.remove		= arizona_haptics_remove,
+	.driver		= {
+		.name	= "arizona-haptics",
+		.owner	= THIS_MODULE,
+	},
+};
+module_platform_driver(arizona_haptics_driver);
+
+MODULE_ALIAS("platform:arizona-haptics");
+MODULE_DESCRIPTION("Arizona haptics driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c
index 1c4146f..a6666e1 100644
--- a/drivers/input/misc/bfin_rotary.c
+++ b/drivers/input/misc/bfin_rotary.c
@@ -90,7 +90,7 @@ static irqreturn_t bfin_rotary_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit bfin_rotary_probe(struct platform_device *pdev)
+static int bfin_rotary_probe(struct platform_device *pdev)
 {
 	struct bfin_rotary_platform_data *pdata = pdev->dev.platform_data;
 	struct bfin_rot *rotary;
@@ -196,7 +196,7 @@ out1:
 	return error;
 }
 
-static int __devexit bfin_rotary_remove(struct platform_device *pdev)
+static int bfin_rotary_remove(struct platform_device *pdev)
 {
 	struct bfin_rot *rotary = platform_get_drvdata(pdev);
 
@@ -255,7 +255,7 @@ static const struct dev_pm_ops bfin_rotary_pm_ops = {
 
 static struct platform_driver bfin_rotary_device_driver = {
 	.probe		= bfin_rotary_probe,
-	.remove		= __devexit_p(bfin_rotary_remove),
+	.remove		= bfin_rotary_remove,
 	.driver		= {
 		.name	= "bfin-rotary",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c
index e2f1e9f..08ffcab 100644
--- a/drivers/input/misc/bma150.c
+++ b/drivers/input/misc/bma150.c
@@ -158,7 +158,7 @@ struct bma150_data {
  * are stated and verified by Bosch Sensortec where they are configured
  * to provide a generic sensitivity performance.
  */
-static struct bma150_cfg default_cfg __devinitdata = {
+static struct bma150_cfg default_cfg = {
 	.any_motion_int = 1,
 	.hg_int = 1,
 	.lg_int = 1,
@@ -224,7 +224,7 @@ static int bma150_set_mode(struct bma150_data *bma150, u8 mode)
 	return 0;
 }
 
-static int __devinit bma150_soft_reset(struct bma150_data *bma150)
+static int bma150_soft_reset(struct bma150_data *bma150)
 {
 	int error;
 
@@ -237,19 +237,19 @@ static int __devinit bma150_soft_reset(struct bma150_data *bma150)
 	return 0;
 }
 
-static int __devinit bma150_set_range(struct bma150_data *bma150, u8 range)
+static int bma150_set_range(struct bma150_data *bma150, u8 range)
 {
 	return bma150_set_reg_bits(bma150->client, range, BMA150_RANGE_POS,
 				BMA150_RANGE_MSK, BMA150_RANGE_REG);
 }
 
-static int __devinit bma150_set_bandwidth(struct bma150_data *bma150, u8 bw)
+static int bma150_set_bandwidth(struct bma150_data *bma150, u8 bw)
 {
 	return bma150_set_reg_bits(bma150->client, bw, BMA150_BANDWIDTH_POS,
 				BMA150_BANDWIDTH_MSK, BMA150_BANDWIDTH_REG);
 }
 
-static int __devinit bma150_set_low_g_interrupt(struct bma150_data *bma150,
+static int bma150_set_low_g_interrupt(struct bma150_data *bma150,
 					u8 enable, u8 hyst, u8 dur, u8 thres)
 {
 	int error;
@@ -273,7 +273,7 @@ static int __devinit bma150_set_low_g_interrupt(struct bma150_data *bma150,
 				BMA150_LOW_G_EN_REG);
 }
 
-static int __devinit bma150_set_high_g_interrupt(struct bma150_data *bma150,
+static int bma150_set_high_g_interrupt(struct bma150_data *bma150,
 					u8 enable, u8 hyst, u8 dur, u8 thres)
 {
 	int error;
@@ -300,7 +300,7 @@ static int __devinit bma150_set_high_g_interrupt(struct bma150_data *bma150,
 }
 
 
-static int __devinit bma150_set_any_motion_interrupt(struct bma150_data *bma150,
+static int bma150_set_any_motion_interrupt(struct bma150_data *bma150,
 						u8 enable, u8 dur, u8 thres)
 {
 	int error;
@@ -424,7 +424,7 @@ static void bma150_poll_close(struct input_polled_dev *ipoll_dev)
 	bma150_close(bma150);
 }
 
-static int __devinit bma150_initialize(struct bma150_data *bma150,
+static int bma150_initialize(struct bma150_data *bma150,
 				       const struct bma150_cfg *cfg)
 {
 	int error;
@@ -465,7 +465,7 @@ static int __devinit bma150_initialize(struct bma150_data *bma150,
 	return bma150_set_mode(bma150, BMA150_MODE_SLEEP);
 }
 
-static void __devinit bma150_init_input_device(struct bma150_data *bma150,
+static void bma150_init_input_device(struct bma150_data *bma150,
 						struct input_dev *idev)
 {
 	idev->name = BMA150_DRIVER;
@@ -479,7 +479,7 @@ static void __devinit bma150_init_input_device(struct bma150_data *bma150,
 	input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
 }
 
-static int __devinit bma150_register_input_device(struct bma150_data *bma150)
+static int bma150_register_input_device(struct bma150_data *bma150)
 {
 	struct input_dev *idev;
 	int error;
@@ -504,7 +504,7 @@ static int __devinit bma150_register_input_device(struct bma150_data *bma150)
 	return 0;
 }
 
-static int __devinit bma150_register_polled_device(struct bma150_data *bma150)
+static int bma150_register_polled_device(struct bma150_data *bma150)
 {
 	struct input_polled_dev *ipoll_dev;
 	int error;
@@ -535,7 +535,7 @@ static int __devinit bma150_register_polled_device(struct bma150_data *bma150)
 	return 0;
 }
 
-static int __devinit bma150_probe(struct i2c_client *client,
+static int bma150_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
 	const struct bma150_platform_data *pdata = client->dev.platform_data;
@@ -613,7 +613,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit bma150_remove(struct i2c_client *client)
+static int bma150_remove(struct i2c_client *client)
 {
 	struct bma150_data *bma150 = i2c_get_clientdata(client);
 
@@ -670,7 +670,7 @@ static struct i2c_driver bma150_driver = {
 	.class		= I2C_CLASS_HWMON,
 	.id_table	= bma150_id,
 	.probe		= bma150_probe,
-	.remove		= __devexit_p(bma150_remove),
+	.remove		= bma150_remove,
 };
 
 module_i2c_driver(bma150_driver);
diff --git a/drivers/input/misc/cma3000_d0x_i2c.c b/drivers/input/misc/cma3000_d0x_i2c.c
index fe9b85f..4fdef98 100644
--- a/drivers/input/misc/cma3000_d0x_i2c.c
+++ b/drivers/input/misc/cma3000_d0x_i2c.c
@@ -55,7 +55,7 @@ static const struct cma3000_bus_ops cma3000_i2c_bops = {
 	.write		= cma3000_i2c_set,
 };
 
-static int __devinit cma3000_i2c_probe(struct i2c_client *client,
+static int cma3000_i2c_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	struct cma3000_accl_data *data;
@@ -69,7 +69,7 @@ static int __devinit cma3000_i2c_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int __devexit cma3000_i2c_remove(struct i2c_client *client)
+static int cma3000_i2c_remove(struct i2c_client *client)
 {
 	struct cma3000_accl_data *data = i2c_get_clientdata(client);
 
@@ -114,7 +114,7 @@ MODULE_DEVICE_TABLE(i2c, cma3000_i2c_id);
 
 static struct i2c_driver cma3000_i2c_driver = {
 	.probe		= cma3000_i2c_probe,
-	.remove		= __devexit_p(cma3000_i2c_remove),
+	.remove		= cma3000_i2c_remove,
 	.id_table	= cma3000_i2c_id,
 	.driver = {
 		.name	= "cma3000_i2c_accl",
diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c
index 53e43d2..4f77f87 100644
--- a/drivers/input/misc/cobalt_btns.c
+++ b/drivers/input/misc/cobalt_btns.c
@@ -73,7 +73,7 @@ static void handle_buttons(struct input_polled_dev *dev)
 	}
 }
 
-static int __devinit cobalt_buttons_probe(struct platform_device *pdev)
+static int cobalt_buttons_probe(struct platform_device *pdev)
 {
 	struct buttons_dev *bdev;
 	struct input_polled_dev *poll_dev;
@@ -135,7 +135,7 @@ static int __devinit cobalt_buttons_probe(struct platform_device *pdev)
 	return error;
 }
 
-static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
+static int cobalt_buttons_remove(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct buttons_dev *bdev = dev_get_drvdata(dev);
@@ -157,7 +157,7 @@ MODULE_ALIAS("platform:Cobalt buttons");
 
 static struct platform_driver cobalt_buttons_driver = {
 	.probe	= cobalt_buttons_probe,
-	.remove	= __devexit_p(cobalt_buttons_remove),
+	.remove	= cobalt_buttons_remove,
 	.driver	= {
 		.name	= "Cobalt buttons",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c
index 3c843cd..020569a 100644
--- a/drivers/input/misc/da9052_onkey.c
+++ b/drivers/input/misc/da9052_onkey.c
@@ -24,7 +24,6 @@ struct da9052_onkey {
 	struct da9052 *da9052;
 	struct input_dev *input;
 	struct delayed_work work;
-	unsigned int irq;
 };
 
 static void da9052_onkey_query(struct da9052_onkey *onkey)
@@ -71,12 +70,11 @@ static irqreturn_t da9052_onkey_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int __devinit da9052_onkey_probe(struct platform_device *pdev)
+static int da9052_onkey_probe(struct platform_device *pdev)
 {
 	struct da9052 *da9052 = dev_get_drvdata(pdev->dev.parent);
 	struct da9052_onkey *onkey;
 	struct input_dev *input_dev;
-	int irq;
 	int error;
 
 	if (!da9052) {
@@ -84,13 +82,6 @@ static int __devinit da9052_onkey_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	irq = platform_get_irq_byname(pdev, "ONKEY");
-	if (irq < 0) {
-		dev_err(&pdev->dev,
-			"Failed to get an IRQ for input device, %d\n", irq);
-		return -EINVAL;
-	}
-
 	onkey = kzalloc(sizeof(*onkey), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!onkey || !input_dev) {
@@ -101,7 +92,6 @@ static int __devinit da9052_onkey_probe(struct platform_device *pdev)
 
 	onkey->input = input_dev;
 	onkey->da9052 = da9052;
-	onkey->irq = irq;
 	INIT_DELAYED_WORK(&onkey->work, da9052_onkey_work);
 
 	input_dev->name = "da9052-onkey";
@@ -111,13 +101,11 @@ static int __devinit da9052_onkey_probe(struct platform_device *pdev)
 	input_dev->evbit[0] = BIT_MASK(EV_KEY);
 	__set_bit(KEY_POWER, input_dev->keybit);
 
-	error = request_threaded_irq(onkey->irq, NULL, da9052_onkey_irq,
-				     IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-				     "ONKEY", onkey);
+	error = da9052_request_irq(onkey->da9052, DA9052_IRQ_NONKEY, "ONKEY",
+			    da9052_onkey_irq, onkey);
 	if (error < 0) {
 		dev_err(onkey->da9052->dev,
-			"Failed to register ONKEY IRQ %d, error = %d\n",
-			onkey->irq, error);
+			"Failed to register ONKEY IRQ: %d\n", error);
 		goto err_free_mem;
 	}
 
@@ -132,7 +120,7 @@ static int __devinit da9052_onkey_probe(struct platform_device *pdev)
 	return 0;
 
 err_free_irq:
-	free_irq(onkey->irq, onkey);
+	da9052_free_irq(onkey->da9052, DA9052_IRQ_NONKEY, onkey);
 	cancel_delayed_work_sync(&onkey->work);
 err_free_mem:
 	input_free_device(input_dev);
@@ -141,11 +129,11 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit da9052_onkey_remove(struct platform_device *pdev)
+static int da9052_onkey_remove(struct platform_device *pdev)
 {
 	struct da9052_onkey *onkey = platform_get_drvdata(pdev);
 
-	free_irq(onkey->irq, onkey);
+	da9052_free_irq(onkey->da9052, DA9052_IRQ_NONKEY, onkey);
 	cancel_delayed_work_sync(&onkey->work);
 
 	input_unregister_device(onkey->input);
@@ -156,7 +144,7 @@ static int __devexit da9052_onkey_remove(struct platform_device *pdev)
 
 static struct platform_driver da9052_onkey_driver = {
 	.probe	= da9052_onkey_probe,
-	.remove	= __devexit_p(da9052_onkey_remove),
+	.remove	= da9052_onkey_remove,
 	.driver = {
 		.name	= "da9052-onkey",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/misc/da9055_onkey.c b/drivers/input/misc/da9055_onkey.c
new file mode 100644
index 0000000..ee6ae3a
--- /dev/null
+++ b/drivers/input/misc/da9055_onkey.c
@@ -0,0 +1,171 @@
+/*
+ * ON pin driver for Dialog DA9055 PMICs
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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/input.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/reg.h>
+
+struct da9055_onkey {
+	struct da9055 *da9055;
+	struct input_dev *input;
+	struct delayed_work work;
+};
+
+static void da9055_onkey_query(struct da9055_onkey *onkey)
+{
+	int key_stat;
+
+	key_stat = da9055_reg_read(onkey->da9055, DA9055_REG_STATUS_A);
+	if (key_stat < 0) {
+		dev_err(onkey->da9055->dev,
+			"Failed to read onkey event %d\n", key_stat);
+	} else {
+		key_stat &= DA9055_NOKEY_STS;
+		/*
+		 * Onkey status bit is cleared when onkey button is relased.
+		 */
+		if (!key_stat) {
+			input_report_key(onkey->input, KEY_POWER, 0);
+			input_sync(onkey->input);
+		}
+	}
+
+	/*
+	 * Interrupt is generated only when the ONKEY pin is asserted.
+	 * Hence the deassertion of the pin is simulated through work queue.
+	 */
+	if (key_stat)
+		schedule_delayed_work(&onkey->work, msecs_to_jiffies(10));
+
+}
+
+static void da9055_onkey_work(struct work_struct *work)
+{
+	struct da9055_onkey *onkey = container_of(work, struct da9055_onkey,
+						  work.work);
+
+	da9055_onkey_query(onkey);
+}
+
+static irqreturn_t da9055_onkey_irq(int irq, void *data)
+{
+	struct da9055_onkey *onkey = data;
+
+	input_report_key(onkey->input, KEY_POWER, 1);
+	input_sync(onkey->input);
+
+	da9055_onkey_query(onkey);
+
+	return IRQ_HANDLED;
+}
+
+static int da9055_onkey_probe(struct platform_device *pdev)
+{
+	struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent);
+	struct da9055_onkey *onkey;
+	struct input_dev *input_dev;
+	int irq, err;
+
+	irq = platform_get_irq_byname(pdev, "ONKEY");
+	if (irq < 0) {
+		dev_err(&pdev->dev,
+			"Failed to get an IRQ for input device, %d\n", irq);
+		return -EINVAL;
+	}
+
+	onkey = devm_kzalloc(&pdev->dev, sizeof(*onkey), GFP_KERNEL);
+	if (!onkey) {
+		dev_err(&pdev->dev, "Failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	input_dev = input_allocate_device();
+	if (!input_dev) {
+		dev_err(&pdev->dev, "Failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	onkey->input = input_dev;
+	onkey->da9055 = da9055;
+	input_dev->name = "da9055-onkey";
+	input_dev->phys = "da9055-onkey/input0";
+	input_dev->dev.parent = &pdev->dev;
+
+	input_dev->evbit[0] = BIT_MASK(EV_KEY);
+	__set_bit(KEY_POWER, input_dev->keybit);
+
+	INIT_DELAYED_WORK(&onkey->work, da9055_onkey_work);
+
+	irq = regmap_irq_get_virq(da9055->irq_data, irq);
+	err = request_threaded_irq(irq, NULL, da9055_onkey_irq,
+				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+				   "ONKEY", onkey);
+	if (err < 0) {
+		dev_err(&pdev->dev,
+			"Failed to register ONKEY IRQ %d, error = %d\n",
+			irq, err);
+		goto err_free_input;
+	}
+
+	err = input_register_device(input_dev);
+	if (err) {
+		dev_err(&pdev->dev, "Unable to register input device, %d\n",
+			err);
+		goto err_free_irq;
+	}
+
+	platform_set_drvdata(pdev, onkey);
+
+	return 0;
+
+err_free_irq:
+	free_irq(irq, onkey);
+	cancel_delayed_work_sync(&onkey->work);
+err_free_input:
+	input_free_device(input_dev);
+
+	return err;
+}
+
+static int da9055_onkey_remove(struct platform_device *pdev)
+{
+	struct da9055_onkey *onkey = platform_get_drvdata(pdev);
+	int irq = platform_get_irq_byname(pdev, "ONKEY");
+
+	irq = regmap_irq_get_virq(onkey->da9055->irq_data, irq);
+	free_irq(irq, onkey);
+	cancel_delayed_work_sync(&onkey->work);
+	input_unregister_device(onkey->input);
+
+	return 0;
+}
+
+static struct platform_driver da9055_onkey_driver = {
+	.probe	= da9055_onkey_probe,
+	.remove	= da9055_onkey_remove,
+	.driver = {
+		.name	= "da9055-onkey",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(da9055_onkey_driver);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("Onkey driver for DA9055");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9055-onkey");
diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c
index c1313d8..a309a5c 100644
--- a/drivers/input/misc/dm355evm_keys.c
+++ b/drivers/input/misc/dm355evm_keys.c
@@ -173,7 +173,7 @@ static irqreturn_t dm355evm_keys_irq(int irq, void *_keys)
 
 /*----------------------------------------------------------------------*/
 
-static int __devinit dm355evm_keys_probe(struct platform_device *pdev)
+static int dm355evm_keys_probe(struct platform_device *pdev)
 {
 	struct dm355evm_keys	*keys;
 	struct input_dev	*input;
@@ -239,7 +239,7 @@ fail1:
 	return status;
 }
 
-static int __devexit dm355evm_keys_remove(struct platform_device *pdev)
+static int dm355evm_keys_remove(struct platform_device *pdev)
 {
 	struct dm355evm_keys	*keys = platform_get_drvdata(pdev);
 
@@ -262,7 +262,7 @@ static int __devexit dm355evm_keys_remove(struct platform_device *pdev)
  */
 static struct platform_driver dm355evm_keys_driver = {
 	.probe		= dm355evm_keys_probe,
-	.remove		= __devexit_p(dm355evm_keys_remove),
+	.remove		= dm355evm_keys_remove,
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= "dm355evm_keys",
diff --git a/drivers/input/misc/gp2ap002a00f.c b/drivers/input/misc/gp2ap002a00f.c
index b6664cf..fe30bd0 100644
--- a/drivers/input/misc/gp2ap002a00f.c
+++ b/drivers/input/misc/gp2ap002a00f.c
@@ -98,7 +98,7 @@ static void gp2a_device_close(struct input_dev *dev)
 			"unable to deactivate, err %d\n", error);
 }
 
-static int __devinit gp2a_initialize(struct gp2a_data *dt)
+static int gp2a_initialize(struct gp2a_data *dt)
 {
 	int error;
 
@@ -122,7 +122,7 @@ static int __devinit gp2a_initialize(struct gp2a_data *dt)
 	return error;
 }
 
-static int __devinit gp2a_probe(struct i2c_client *client,
+static int gp2a_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
 	const struct gp2a_platform_data *pdata = client->dev.platform_data;
@@ -205,7 +205,7 @@ err_hw_shutdown:
 	return error;
 }
 
-static int __devexit gp2a_remove(struct i2c_client *client)
+static int gp2a_remove(struct i2c_client *client)
 {
 	struct gp2a_data *dt = i2c_get_clientdata(client);
 	const struct gp2a_platform_data *pdata = dt->pdata;
@@ -277,7 +277,7 @@ static struct i2c_driver gp2a_i2c_driver = {
 		.pm	= &gp2a_pm,
 	},
 	.probe		= gp2a_probe,
-	.remove		= __devexit_p(gp2a_remove),
+	.remove		= gp2a_remove,
 	.id_table	= gp2a_i2c_id,
 };
 
diff --git a/drivers/input/misc/gpio_tilt_polled.c b/drivers/input/misc/gpio_tilt_polled.c
index 277a057..da05cca 100644
--- a/drivers/input/misc/gpio_tilt_polled.c
+++ b/drivers/input/misc/gpio_tilt_polled.c
@@ -96,7 +96,7 @@ static void gpio_tilt_polled_close(struct input_polled_dev *dev)
 		pdata->disable(tdev->dev);
 }
 
-static int __devinit gpio_tilt_polled_probe(struct platform_device *pdev)
+static int gpio_tilt_polled_probe(struct platform_device *pdev)
 {
 	const struct gpio_tilt_platform_data *pdata = pdev->dev.platform_data;
 	struct device *dev = &pdev->dev;
@@ -179,7 +179,7 @@ err_free_tdev:
 	return error;
 }
 
-static int __devexit gpio_tilt_polled_remove(struct platform_device *pdev)
+static int gpio_tilt_polled_remove(struct platform_device *pdev)
 {
 	struct gpio_tilt_polled_dev *tdev = platform_get_drvdata(pdev);
 	const struct gpio_tilt_platform_data *pdata = tdev->pdata;
@@ -198,7 +198,7 @@ static int __devexit gpio_tilt_polled_remove(struct platform_device *pdev)
 
 static struct platform_driver gpio_tilt_polled_driver = {
 	.probe	= gpio_tilt_polled_probe,
-	.remove	= __devexit_p(gpio_tilt_polled_remove),
+	.remove	= gpio_tilt_polled_remove,
 	.driver	= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
index 50e2830..6ab3dec 100644
--- a/drivers/input/misc/ixp4xx-beeper.c
+++ b/drivers/input/misc/ixp4xx-beeper.c
@@ -87,7 +87,7 @@ static irqreturn_t ixp4xx_spkr_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit ixp4xx_spkr_probe(struct platform_device *dev)
+static int ixp4xx_spkr_probe(struct platform_device *dev)
 {
 	struct input_dev *input_dev;
 	int err;
@@ -132,7 +132,7 @@ static int __devinit ixp4xx_spkr_probe(struct platform_device *dev)
 	return err;
 }
 
-static int __devexit ixp4xx_spkr_remove(struct platform_device *dev)
+static int ixp4xx_spkr_remove(struct platform_device *dev)
 {
 	struct input_dev *input_dev = platform_get_drvdata(dev);
 	unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
@@ -165,7 +165,7 @@ static struct platform_driver ixp4xx_spkr_platform_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= ixp4xx_spkr_probe,
-	.remove		= __devexit_p(ixp4xx_spkr_remove),
+	.remove		= ixp4xx_spkr_remove,
 	.shutdown	= ixp4xx_spkr_shutdown,
 };
 module_platform_driver(ixp4xx_spkr_platform_driver);
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index f46139f..a993b67 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -295,7 +295,7 @@ static void kxtj9_input_close(struct input_dev *dev)
 	kxtj9_disable(tj9);
 }
 
-static void __devinit kxtj9_init_input_device(struct kxtj9_data *tj9,
+static void kxtj9_init_input_device(struct kxtj9_data *tj9,
 					      struct input_dev *input_dev)
 {
 	__set_bit(EV_ABS, input_dev->evbit);
@@ -308,7 +308,7 @@ static void __devinit kxtj9_init_input_device(struct kxtj9_data *tj9,
 	input_dev->dev.parent = &tj9->client->dev;
 }
 
-static int __devinit kxtj9_setup_input_device(struct kxtj9_data *tj9)
+static int kxtj9_setup_input_device(struct kxtj9_data *tj9)
 {
 	struct input_dev *input_dev;
 	int err;
@@ -433,7 +433,7 @@ static void kxtj9_polled_input_close(struct input_polled_dev *dev)
 	kxtj9_disable(tj9);
 }
 
-static int __devinit kxtj9_setup_polled_device(struct kxtj9_data *tj9)
+static int kxtj9_setup_polled_device(struct kxtj9_data *tj9)
 {
 	int err;
 	struct input_polled_dev *poll_dev;
@@ -466,7 +466,7 @@ static int __devinit kxtj9_setup_polled_device(struct kxtj9_data *tj9)
 	return 0;
 }
 
-static void __devexit kxtj9_teardown_polled_device(struct kxtj9_data *tj9)
+static void kxtj9_teardown_polled_device(struct kxtj9_data *tj9)
 {
 	input_unregister_polled_device(tj9->poll_dev);
 	input_free_polled_device(tj9->poll_dev);
@@ -485,7 +485,7 @@ static inline void kxtj9_teardown_polled_device(struct kxtj9_data *tj9)
 
 #endif
 
-static int __devinit kxtj9_verify(struct kxtj9_data *tj9)
+static int kxtj9_verify(struct kxtj9_data *tj9)
 {
 	int retval;
 
@@ -506,7 +506,7 @@ out:
 	return retval;
 }
 
-static int __devinit kxtj9_probe(struct i2c_client *client,
+static int kxtj9_probe(struct i2c_client *client,
 				 const struct i2c_device_id *id)
 {
 	const struct kxtj9_platform_data *pdata = client->dev.platform_data;
@@ -594,7 +594,7 @@ err_free_mem:
 	return err;
 }
 
-static int __devexit kxtj9_remove(struct i2c_client *client)
+static int kxtj9_remove(struct i2c_client *client)
 {
 	struct kxtj9_data *tj9 = i2c_get_clientdata(client);
 
@@ -663,7 +663,7 @@ static struct i2c_driver kxtj9_driver = {
 		.pm	= &kxtj9_pm_ops,
 	},
 	.probe		= kxtj9_probe,
-	.remove		= __devexit_p(kxtj9_remove),
+	.remove		= kxtj9_remove,
 	.id_table	= kxtj9_id,
 };
 
diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c
index 0c64d9b..b40ee4b 100644
--- a/drivers/input/misc/m68kspkr.c
+++ b/drivers/input/misc/m68kspkr.c
@@ -48,7 +48,7 @@ static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int
 	return 0;
 }
 
-static int __devinit m68kspkr_probe(struct platform_device *dev)
+static int m68kspkr_probe(struct platform_device *dev)
 {
 	struct input_dev *input_dev;
 	int err;
@@ -80,7 +80,7 @@ static int __devinit m68kspkr_probe(struct platform_device *dev)
 	return 0;
 }
 
-static int __devexit m68kspkr_remove(struct platform_device *dev)
+static int m68kspkr_remove(struct platform_device *dev)
 {
 	struct input_dev *input_dev = platform_get_drvdata(dev);
 
@@ -104,7 +104,7 @@ static struct platform_driver m68kspkr_platform_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= m68kspkr_probe,
-	.remove		= __devexit_p(m68kspkr_remove),
+	.remove		= m68kspkr_remove,
 	.shutdown	= m68kspkr_shutdown,
 };
 
diff --git a/drivers/input/misc/max8925_onkey.c b/drivers/input/misc/max8925_onkey.c
index 0a12b74..369a39d 100644
--- a/drivers/input/misc/max8925_onkey.c
+++ b/drivers/input/misc/max8925_onkey.c
@@ -62,7 +62,7 @@ static irqreturn_t max8925_onkey_handler(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int __devinit max8925_onkey_probe(struct platform_device *pdev)
+static int max8925_onkey_probe(struct platform_device *pdev)
 {
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct max8925_onkey_info *info;
@@ -141,7 +141,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit max8925_onkey_remove(struct platform_device *pdev)
+static int max8925_onkey_remove(struct platform_device *pdev)
 {
 	struct max8925_onkey_info *info = platform_get_drvdata(pdev);
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
@@ -195,7 +195,7 @@ static struct platform_driver max8925_onkey_driver = {
 		.pm	= &max8925_onkey_pm_ops,
 	},
 	.probe		= max8925_onkey_probe,
-	.remove		= __devexit_p(max8925_onkey_remove),
+	.remove		= max8925_onkey_remove,
 };
 module_platform_driver(max8925_onkey_driver);
 
diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
index 05b7b8b..e973133 100644
--- a/drivers/input/misc/max8997_haptic.c
+++ b/drivers/input/misc/max8997_haptic.c
@@ -241,7 +241,7 @@ static void max8997_haptic_close(struct input_dev *dev)
 	max8997_haptic_disable(chip);
 }
 
-static int __devinit max8997_haptic_probe(struct platform_device *pdev)
+static int max8997_haptic_probe(struct platform_device *pdev)
 {
 	struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 	const struct max8997_platform_data *pdata =
@@ -354,7 +354,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit max8997_haptic_remove(struct platform_device *pdev)
+static int max8997_haptic_remove(struct platform_device *pdev)
 {
 	struct max8997_haptic *chip = platform_get_drvdata(pdev);
 
@@ -396,7 +396,7 @@ static struct platform_driver max8997_haptic_driver = {
 		.pm	= &max8997_haptic_pm_ops,
 	},
 	.probe		= max8997_haptic_probe,
-	.remove		= __devexit_p(max8997_haptic_remove),
+	.remove		= max8997_haptic_remove,
 	.id_table	= max8997_haptic_id,
 };
 module_platform_driver(max8997_haptic_driver);
diff --git a/drivers/input/misc/mc13783-pwrbutton.c b/drivers/input/misc/mc13783-pwrbutton.c
index 8428f1e..0906ca5 100644
--- a/drivers/input/misc/mc13783-pwrbutton.c
+++ b/drivers/input/misc/mc13783-pwrbutton.c
@@ -89,7 +89,7 @@ static irqreturn_t button_irq(int irq, void *_priv)
 	return IRQ_HANDLED;
 }
 
-static int __devinit mc13783_pwrbutton_probe(struct platform_device *pdev)
+static int mc13783_pwrbutton_probe(struct platform_device *pdev)
 {
 	const struct mc13xxx_buttons_platform_data *pdata;
 	struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
@@ -230,7 +230,7 @@ free_input_dev:
 	return err;
 }
 
-static int __devexit mc13783_pwrbutton_remove(struct platform_device *pdev)
+static int mc13783_pwrbutton_remove(struct platform_device *pdev)
 {
 	struct mc13783_pwrb *priv = platform_get_drvdata(pdev);
 	const struct mc13xxx_buttons_platform_data *pdata;
@@ -257,7 +257,7 @@ static int __devexit mc13783_pwrbutton_remove(struct platform_device *pdev)
 
 static struct platform_driver mc13783_pwrbutton_driver = {
 	.probe		= mc13783_pwrbutton_probe,
-	.remove		= __devexit_p(mc13783_pwrbutton_remove),
+	.remove		= mc13783_pwrbutton_remove,
 	.driver		= {
 		.name	= "mc13783-pwrbutton",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c
index 873ebce..480557f 100644
--- a/drivers/input/misc/mma8450.c
+++ b/drivers/input/misc/mma8450.c
@@ -167,7 +167,7 @@ static void mma8450_close(struct input_polled_dev *dev)
 /*
  * I2C init/probing/exit functions
  */
-static int __devinit mma8450_probe(struct i2c_client *c,
+static int mma8450_probe(struct i2c_client *c,
 				   const struct i2c_device_id *id)
 {
 	struct input_polled_dev *idev;
@@ -212,7 +212,7 @@ err_free_mem:
 	return err;
 }
 
-static int __devexit mma8450_remove(struct i2c_client *c)
+static int mma8450_remove(struct i2c_client *c)
 {
 	struct mma8450 *m = i2c_get_clientdata(c);
 	struct input_polled_dev *idev = m->idev;
@@ -243,7 +243,7 @@ static struct i2c_driver mma8450_driver = {
 		.of_match_table = mma8450_dt_ids,
 	},
 	.probe		= mma8450_probe,
-	.remove		= __devexit_p(mma8450_remove),
+	.remove		= mma8450_remove,
 	.id_table	= mma8450_id,
 };
 
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index 306f84c..dce0d95 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -257,7 +257,7 @@ static irqreturn_t mpu3050_interrupt_thread(int irq, void *data)
  *
  *	Called during device probe; configures the sampling method.
  */
-static int __devinit mpu3050_hw_init(struct mpu3050_sensor *sensor)
+static int mpu3050_hw_init(struct mpu3050_sensor *sensor)
 {
 	struct i2c_client *client = sensor->client;
 	int ret;
@@ -306,7 +306,7 @@ static int __devinit mpu3050_hw_init(struct mpu3050_sensor *sensor)
  *
  *	If present install the relevant sysfs interfaces and input device.
  */
-static int __devinit mpu3050_probe(struct i2c_client *client,
+static int mpu3050_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
 	struct mpu3050_sensor *sensor;
@@ -402,7 +402,7 @@ err_free_mem:
  *
  *	Our sensor is going away, clean up the resources.
  */
-static int __devexit mpu3050_remove(struct i2c_client *client)
+static int mpu3050_remove(struct i2c_client *client)
 {
 	struct mpu3050_sensor *sensor = i2c_get_clientdata(client);
 
@@ -471,7 +471,7 @@ static struct i2c_driver mpu3050_i2c_driver = {
 		.of_match_table = mpu3050_of_match,
 	},
 	.probe		= mpu3050_probe,
-	.remove		= __devexit_p(mpu3050_remove),
+	.remove		= mpu3050_remove,
 	.id_table	= mpu3050_ids,
 };
 
diff --git a/drivers/input/misc/pcap_keys.c b/drivers/input/misc/pcap_keys.c
index e09b4fe..40ac9a5 100644
--- a/drivers/input/misc/pcap_keys.c
+++ b/drivers/input/misc/pcap_keys.c
@@ -48,7 +48,7 @@ static irqreturn_t pcap_keys_handler(int irq, void *_pcap_keys)
 	return IRQ_HANDLED;
 }
 
-static int __devinit pcap_keys_probe(struct platform_device *pdev)
+static int pcap_keys_probe(struct platform_device *pdev)
 {
 	int err = -ENOMEM;
 	struct pcap_keys *pcap_keys;
@@ -104,7 +104,7 @@ fail:
 	return err;
 }
 
-static int __devexit pcap_keys_remove(struct platform_device *pdev)
+static int pcap_keys_remove(struct platform_device *pdev)
 {
 	struct pcap_keys *pcap_keys = platform_get_drvdata(pdev);
 
@@ -119,7 +119,7 @@ static int __devexit pcap_keys_remove(struct platform_device *pdev)
 
 static struct platform_driver pcap_keys_device_driver = {
 	.probe		= pcap_keys_probe,
-	.remove		= __devexit_p(pcap_keys_remove),
+	.remove		= pcap_keys_remove,
 	.driver		= {
 		.name	= "pcap-keys",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c
index 53891de..73b13eb 100644
--- a/drivers/input/misc/pcf50633-input.c
+++ b/drivers/input/misc/pcf50633-input.c
@@ -53,7 +53,7 @@ pcf50633_input_irq(int irq, void *data)
 	input_sync(input->input_dev);
 }
 
-static int __devinit pcf50633_input_probe(struct platform_device *pdev)
+static int pcf50633_input_probe(struct platform_device *pdev)
 {
 	struct pcf50633_input *input;
 	struct input_dev *input_dev;
@@ -93,7 +93,7 @@ static int __devinit pcf50633_input_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit pcf50633_input_remove(struct platform_device *pdev)
+static int pcf50633_input_remove(struct platform_device *pdev)
 {
 	struct pcf50633_input *input  = platform_get_drvdata(pdev);
 
@@ -111,7 +111,7 @@ static struct platform_driver pcf50633_input_driver = {
 		.name = "pcf50633-input",
 	},
 	.probe = pcf50633_input_probe,
-	.remove = __devexit_p(pcf50633_input_remove),
+	.remove = pcf50633_input_remove,
 };
 module_platform_driver(pcf50633_input_driver);
 
diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c
index 544c663..e373929 100644
--- a/drivers/input/misc/pcf8574_keypad.c
+++ b/drivers/input/misc/pcf8574_keypad.c
@@ -82,7 +82,7 @@ static irqreturn_t pcf8574_kp_irq_handler(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit pcf8574_kp_probe(struct i2c_client *client, const struct i2c_device_id *id)
+static int pcf8574_kp_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	int i, ret;
 	struct input_dev *idev;
@@ -156,7 +156,7 @@ static int __devinit pcf8574_kp_probe(struct i2c_client *client, const struct i2
 	return ret;
 }
 
-static int __devexit pcf8574_kp_remove(struct i2c_client *client)
+static int pcf8574_kp_remove(struct i2c_client *client)
 {
 	struct kp_data *lp = i2c_get_clientdata(client);
 
@@ -212,7 +212,7 @@ static struct i2c_driver pcf8574_kp_driver = {
 #endif
 	},
 	.probe    = pcf8574_kp_probe,
-	.remove   = __devexit_p(pcf8574_kp_remove),
+	.remove   = pcf8574_kp_remove,
 	.id_table = pcf8574_kp_id,
 };
 
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index b2484aa..199db78 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -63,7 +63,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c
 	return 0;
 }
 
-static int __devinit pcspkr_probe(struct platform_device *dev)
+static int pcspkr_probe(struct platform_device *dev)
 {
 	struct input_dev *pcspkr_dev;
 	int err;
@@ -95,7 +95,7 @@ static int __devinit pcspkr_probe(struct platform_device *dev)
 	return 0;
 }
 
-static int __devexit pcspkr_remove(struct platform_device *dev)
+static int pcspkr_remove(struct platform_device *dev)
 {
 	struct input_dev *pcspkr_dev = platform_get_drvdata(dev);
 
@@ -131,7 +131,7 @@ static struct platform_driver pcspkr_platform_driver = {
 		.pm	= &pcspkr_pm_ops,
 	},
 	.probe		= pcspkr_probe,
-	.remove		= __devexit_p(pcspkr_remove),
+	.remove		= pcspkr_remove,
 	.shutdown	= pcspkr_shutdown,
 };
 module_platform_driver(pcspkr_platform_driver);
diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c
index dfbfb46..a9da65e 100644
--- a/drivers/input/misc/pm8xxx-vibrator.c
+++ b/drivers/input/misc/pm8xxx-vibrator.c
@@ -178,7 +178,7 @@ static int pm8xxx_vib_play_effect(struct input_dev *dev, void *data,
 	return 0;
 }
 
-static int __devinit pm8xxx_vib_probe(struct platform_device *pdev)
+static int pm8xxx_vib_probe(struct platform_device *pdev)
 
 {
 	struct pm8xxx_vib *vib;
@@ -242,7 +242,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit pm8xxx_vib_remove(struct platform_device *pdev)
+static int pm8xxx_vib_remove(struct platform_device *pdev)
 {
 	struct pm8xxx_vib *vib = platform_get_drvdata(pdev);
 
@@ -270,7 +270,7 @@ static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL);
 
 static struct platform_driver pm8xxx_vib_driver = {
 	.probe		= pm8xxx_vib_probe,
-	.remove		= __devexit_p(pm8xxx_vib_remove),
+	.remove		= pm8xxx_vib_remove,
 	.driver		= {
 		.name	= "pm8xxx-vib",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c
index 0f83d0f..4b811be 100644
--- a/drivers/input/misc/pmic8xxx-pwrkey.c
+++ b/drivers/input/misc/pmic8xxx-pwrkey.c
@@ -81,7 +81,7 @@ static int pmic8xxx_pwrkey_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(pm8xxx_pwr_key_pm_ops,
 		pmic8xxx_pwrkey_suspend, pmic8xxx_pwrkey_resume);
 
-static int __devinit pmic8xxx_pwrkey_probe(struct platform_device *pdev)
+static int pmic8xxx_pwrkey_probe(struct platform_device *pdev)
 {
 	struct input_dev *pwr;
 	int key_release_irq = platform_get_irq(pdev, 0);
@@ -187,7 +187,7 @@ free_pwrkey:
 	return err;
 }
 
-static int __devexit pmic8xxx_pwrkey_remove(struct platform_device *pdev)
+static int pmic8xxx_pwrkey_remove(struct platform_device *pdev)
 {
 	struct pmic8xxx_pwrkey *pwrkey = platform_get_drvdata(pdev);
 	int key_release_irq = platform_get_irq(pdev, 0);
@@ -206,7 +206,7 @@ static int __devexit pmic8xxx_pwrkey_remove(struct platform_device *pdev)
 
 static struct platform_driver pmic8xxx_pwrkey_driver = {
 	.probe		= pmic8xxx_pwrkey_probe,
-	.remove		= __devexit_p(pmic8xxx_pwrkey_remove),
+	.remove		= pmic8xxx_pwrkey_remove,
 	.driver		= {
 		.name	= PM8XXX_PWRKEY_DEV_NAME,
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c
index fc84c8a..0808868 100644
--- a/drivers/input/misc/pwm-beeper.c
+++ b/drivers/input/misc/pwm-beeper.c
@@ -65,7 +65,7 @@ static int pwm_beeper_event(struct input_dev *input,
 	return 0;
 }
 
-static int __devinit pwm_beeper_probe(struct platform_device *pdev)
+static int pwm_beeper_probe(struct platform_device *pdev)
 {
 	unsigned long pwm_id = (unsigned long)pdev->dev.platform_data;
 	struct pwm_beeper *beeper;
@@ -75,7 +75,11 @@ static int __devinit pwm_beeper_probe(struct platform_device *pdev)
 	if (!beeper)
 		return -ENOMEM;
 
-	beeper->pwm = pwm_request(pwm_id, "pwm beeper");
+	beeper->pwm = pwm_get(&pdev->dev, NULL);
+	if (IS_ERR(beeper->pwm)) {
+		dev_dbg(&pdev->dev, "unable to request PWM, trying legacy API\n");
+		beeper->pwm = pwm_request(pwm_id, "pwm beeper");
+	}
 
 	if (IS_ERR(beeper->pwm)) {
 		error = PTR_ERR(beeper->pwm);
@@ -125,7 +129,7 @@ err_free:
 	return error;
 }
 
-static int __devexit pwm_beeper_remove(struct platform_device *pdev)
+static int pwm_beeper_remove(struct platform_device *pdev)
 {
 	struct pwm_beeper *beeper = platform_get_drvdata(pdev);
 
@@ -171,13 +175,21 @@ static SIMPLE_DEV_PM_OPS(pwm_beeper_pm_ops,
 #define PWM_BEEPER_PM_OPS NULL
 #endif
 
+#ifdef CONFIG_OF
+static const struct of_device_id pwm_beeper_match[] = {
+	{ .compatible = "pwm-beeper", },
+	{ },
+};
+#endif
+
 static struct platform_driver pwm_beeper_driver = {
 	.probe	= pwm_beeper_probe,
-	.remove = __devexit_p(pwm_beeper_remove),
+	.remove = pwm_beeper_remove,
 	.driver = {
 		.name	= "pwm-beeper",
 		.owner	= THIS_MODULE,
 		.pm	= PWM_BEEPER_PM_OPS,
+		.of_match_table = of_match_ptr(pwm_beeper_match),
 	},
 };
 module_platform_driver(pwm_beeper_driver);
diff --git a/drivers/input/misc/rb532_button.c b/drivers/input/misc/rb532_button.c
index aeb02bc..fb4f8ac 100644
--- a/drivers/input/misc/rb532_button.c
+++ b/drivers/input/misc/rb532_button.c
@@ -51,7 +51,7 @@ static void rb532_button_poll(struct input_polled_dev *poll_dev)
 	input_sync(poll_dev->input);
 }
 
-static int __devinit rb532_button_probe(struct platform_device *pdev)
+static int rb532_button_probe(struct platform_device *pdev)
 {
 	struct input_polled_dev *poll_dev;
 	int error;
@@ -81,7 +81,7 @@ static int __devinit rb532_button_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit rb532_button_remove(struct platform_device *pdev)
+static int rb532_button_remove(struct platform_device *pdev)
 {
 	struct input_polled_dev *poll_dev = dev_get_drvdata(&pdev->dev);
 
@@ -94,7 +94,7 @@ static int __devexit rb532_button_remove(struct platform_device *pdev)
 
 static struct platform_driver rb532_button_driver = {
 	.probe = rb532_button_probe,
-	.remove = __devexit_p(rb532_button_remove),
+	.remove = rb532_button_remove,
 	.driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
diff --git a/drivers/input/misc/retu-pwrbutton.c b/drivers/input/misc/retu-pwrbutton.c
new file mode 100644
index 0000000..7ca09ba
--- /dev/null
+++ b/drivers/input/misc/retu-pwrbutton.c
@@ -0,0 +1,99 @@
+/*
+ * Retu power button driver.
+ *
+ * Copyright (C) 2004-2010 Nokia Corporation
+ *
+ * Original code written by Ari Saastamoinen, Juha Yrjölä and Felipe Balbi.
+ * Rewritten by Aaro Koskinen.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mfd/retu.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#define RETU_STATUS_PWRONX (1 << 5)
+
+static irqreturn_t retu_pwrbutton_irq(int irq, void *_pwr)
+{
+	struct input_dev *idev = _pwr;
+	struct retu_dev *rdev = input_get_drvdata(idev);
+	bool state;
+
+	state = !(retu_read(rdev, RETU_REG_STATUS) & RETU_STATUS_PWRONX);
+	input_report_key(idev, KEY_POWER, state);
+	input_sync(idev);
+
+	return IRQ_HANDLED;
+}
+
+static int retu_pwrbutton_probe(struct platform_device *pdev)
+{
+	struct retu_dev *rdev = dev_get_drvdata(pdev->dev.parent);
+	struct input_dev *idev;
+	int irq;
+	int error;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	idev = devm_input_allocate_device(&pdev->dev);
+	if (!idev)
+		return -ENOMEM;
+
+	idev->name = "retu-pwrbutton";
+	idev->dev.parent = &pdev->dev;
+
+	input_set_capability(idev, EV_KEY, KEY_POWER);
+	input_set_drvdata(idev, rdev);
+
+	error = devm_request_threaded_irq(&pdev->dev, irq,
+					  NULL, retu_pwrbutton_irq, 0,
+					  "retu-pwrbutton", idev);
+	if (error)
+		return error;
+
+	error = input_register_device(idev);
+	if (error)
+		return error;
+
+	return 0;
+}
+
+static int retu_pwrbutton_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct platform_driver retu_pwrbutton_driver = {
+	.probe		= retu_pwrbutton_probe,
+	.remove		= retu_pwrbutton_remove,
+	.driver		= {
+		.name	= "retu-pwrbutton",
+		.owner	= THIS_MODULE,
+	},
+};
+module_platform_driver(retu_pwrbutton_driver);
+
+MODULE_ALIAS("platform:retu-pwrbutton");
+MODULE_DESCRIPTION("Retu Power Button");
+MODULE_AUTHOR("Ari Saastamoinen");
+MODULE_AUTHOR("Felipe Balbi");
+MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
index 99a49e4..aff47b2 100644
--- a/drivers/input/misc/rotary_encoder.c
+++ b/drivers/input/misc/rotary_encoder.c
@@ -149,8 +149,7 @@ static struct of_device_id rotary_encoder_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, rotary_encoder_of_match);
 
-static struct rotary_encoder_platform_data * __devinit
-rotary_encoder_parse_dt(struct device *dev)
+static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct device *dev)
 {
 	const struct of_device_id *of_id =
 				of_match_device(rotary_encoder_of_match, dev);
@@ -192,7 +191,7 @@ rotary_encoder_parse_dt(struct device *dev)
 }
 #endif
 
-static int __devinit rotary_encoder_probe(struct platform_device *pdev)
+static int rotary_encoder_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	const struct rotary_encoder_platform_data *pdata = dev_get_platdata(dev);
@@ -302,7 +301,7 @@ exit_free_mem:
 	return err;
 }
 
-static int __devexit rotary_encoder_remove(struct platform_device *pdev)
+static int rotary_encoder_remove(struct platform_device *pdev)
 {
 	struct rotary_encoder *encoder = platform_get_drvdata(pdev);
 	const struct rotary_encoder_platform_data *pdata = encoder->pdata;
@@ -325,7 +324,7 @@ static int __devexit rotary_encoder_remove(struct platform_device *pdev)
 
 static struct platform_driver rotary_encoder_driver = {
 	.probe		= rotary_encoder_probe,
-	.remove		= __devexit_p(rotary_encoder_remove),
+	.remove		= rotary_encoder_remove,
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c
index 5d9fd55..ad6415c 100644
--- a/drivers/input/misc/sgi_btns.c
+++ b/drivers/input/misc/sgi_btns.c
@@ -91,7 +91,7 @@ static void handle_buttons(struct input_polled_dev *dev)
 	}
 }
 
-static int __devinit sgi_buttons_probe(struct platform_device *pdev)
+static int sgi_buttons_probe(struct platform_device *pdev)
 {
 	struct buttons_dev *bdev;
 	struct input_polled_dev *poll_dev;
@@ -143,7 +143,7 @@ static int __devinit sgi_buttons_probe(struct platform_device *pdev)
 	return error;
 }
 
-static int __devexit sgi_buttons_remove(struct platform_device *pdev)
+static int sgi_buttons_remove(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct buttons_dev *bdev = dev_get_drvdata(dev);
@@ -158,7 +158,7 @@ static int __devexit sgi_buttons_remove(struct platform_device *pdev)
 
 static struct platform_driver sgi_buttons_driver = {
 	.probe	= sgi_buttons_probe,
-	.remove	= __devexit_p(sgi_buttons_remove),
+	.remove	= sgi_buttons_remove,
 	.driver	= {
 		.name	= "sgibtns",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index 0122f53..a53586a 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -139,7 +139,7 @@ static int grover_spkr_event(struct input_dev *dev, unsigned int type, unsigned
 	return 0;
 }
 
-static int __devinit sparcspkr_probe(struct device *dev)
+static int sparcspkr_probe(struct device *dev)
 {
 	struct sparcspkr_state *state = dev_get_drvdata(dev);
 	struct input_dev *input_dev;
@@ -182,7 +182,7 @@ static void sparcspkr_shutdown(struct platform_device *dev)
 	state->event(input_dev, EV_SND, SND_BELL, 0);
 }
 
-static int __devinit bbc_beep_probe(struct platform_device *op)
+static int bbc_beep_probe(struct platform_device *op)
 {
 	struct sparcspkr_state *state;
 	struct bbc_beep_info *info;
@@ -229,7 +229,7 @@ out_err:
 	return err;
 }
 
-static int __devexit bbc_remove(struct platform_device *op)
+static int bbc_remove(struct platform_device *op)
 {
 	struct sparcspkr_state *state = dev_get_drvdata(&op->dev);
 	struct input_dev *input_dev = state->input_dev;
@@ -263,11 +263,11 @@ static struct platform_driver bbc_beep_driver = {
 		.of_match_table = bbc_beep_match,
 	},
 	.probe		= bbc_beep_probe,
-	.remove		= __devexit_p(bbc_remove),
+	.remove		= bbc_remove,
 	.shutdown	= sparcspkr_shutdown,
 };
 
-static int __devinit grover_beep_probe(struct platform_device *op)
+static int grover_beep_probe(struct platform_device *op)
 {
 	struct sparcspkr_state *state;
 	struct grover_beep_info *info;
@@ -310,7 +310,7 @@ out_err:
 	return err;
 }
 
-static int __devexit grover_remove(struct platform_device *op)
+static int grover_remove(struct platform_device *op)
 {
 	struct sparcspkr_state *state = dev_get_drvdata(&op->dev);
 	struct grover_beep_info *info = &state->u.grover;
@@ -345,7 +345,7 @@ static struct platform_driver grover_beep_driver = {
 		.of_match_table = grover_beep_match,
 	},
 	.probe		= grover_beep_probe,
-	.remove		= __devexit_p(grover_remove),
+	.remove		= grover_remove,
 	.shutdown	= sparcspkr_shutdown,
 };
 
diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c
index b3dd96d..27c2bc8 100644
--- a/drivers/input/misc/twl4030-pwrbutton.c
+++ b/drivers/input/misc/twl4030-pwrbutton.c
@@ -39,8 +39,7 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr)
 	int err;
 	u8 value;
 
-	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value,
-				STS_HW_CONDITIONS);
+	err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &value, STS_HW_CONDITIONS);
 	if (!err)  {
 		pm_wakeup_event(pwr->dev.parent, 0);
 		input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ);
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c
index 2194a3c..78eb6b3 100644
--- a/drivers/input/misc/twl4030-vibra.c
+++ b/drivers/input/misc/twl4030-vibra.c
@@ -207,7 +207,7 @@ static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata,
 	return false;
 }
 
-static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
+static int twl4030_vibra_probe(struct platform_device *pdev)
 {
 	struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
 	struct device_node *twl4030_core_node = pdev->dev.parent->of_node;
@@ -269,7 +269,7 @@ err_kzalloc:
 	return ret;
 }
 
-static int __devexit twl4030_vibra_remove(struct platform_device *pdev)
+static int twl4030_vibra_remove(struct platform_device *pdev)
 {
 	struct vibra_info *info = platform_get_drvdata(pdev);
 
@@ -283,7 +283,7 @@ static int __devexit twl4030_vibra_remove(struct platform_device *pdev)
 
 static struct platform_driver twl4030_vibra_driver = {
 	.probe		= twl4030_vibra_probe,
-	.remove		= __devexit_p(twl4030_vibra_remove),
+	.remove		= twl4030_vibra_remove,
 	.driver		= {
 		.name	= "twl4030-vibra",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
index c8a288a..71a28ee 100644
--- a/drivers/input/misc/twl6040-vibra.c
+++ b/drivers/input/misc/twl6040-vibra.c
@@ -255,7 +255,7 @@ static int twl6040_vibra_suspend(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL);
 
-static int __devinit twl6040_vibra_probe(struct platform_device *pdev)
+static int twl6040_vibra_probe(struct platform_device *pdev)
 {
 	struct twl6040_vibra_data *pdata = pdev->dev.platform_data;
 	struct device *twl6040_core_dev = pdev->dev.parent;
@@ -418,7 +418,7 @@ err_kzalloc:
 	return ret;
 }
 
-static int __devexit twl6040_vibra_remove(struct platform_device *pdev)
+static int twl6040_vibra_remove(struct platform_device *pdev)
 {
 	struct vibra_info *info = platform_get_drvdata(pdev);
 
@@ -433,7 +433,7 @@ static int __devexit twl6040_vibra_remove(struct platform_device *pdev)
 
 static struct platform_driver twl6040_vibra_driver = {
 	.probe		= twl6040_vibra_probe,
-	.remove		= __devexit_p(twl6040_vibra_remove),
+	.remove		= twl6040_vibra_remove,
 	.driver		= {
 		.name	= "twl6040-vibra",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index e2bdfd4..56536f4 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -170,7 +170,7 @@ static u16 bios_pop_queue(void)
 	return regs.eax;
 }
 
-static void __devinit bios_attach(void)
+static void bios_attach(void)
 {
 	struct regs regs;
 
@@ -190,7 +190,7 @@ static void bios_detach(void)
 	call_bios(&regs);
 }
 
-static u8 __devinit bios_get_cmos_address(void)
+static u8 bios_get_cmos_address(void)
 {
 	struct regs regs;
 
@@ -202,7 +202,7 @@ static u8 __devinit bios_get_cmos_address(void)
 	return regs.ecx;
 }
 
-static u16 __devinit bios_get_default_setting(u8 subsys)
+static u16 bios_get_default_setting(u8 subsys)
 {
 	struct regs regs;
 
@@ -1052,7 +1052,7 @@ static struct led_classdev wistron_wifi_led = {
 	.brightness_set		= wistron_wifi_led_set,
 };
 
-static void __devinit wistron_led_init(struct device *parent)
+static void wistron_led_init(struct device *parent)
 {
 	if (leds_present & FE_WIFI_LED) {
 		u16 wifi = bios_get_default_setting(WIFI);
@@ -1077,7 +1077,7 @@ static void __devinit wistron_led_init(struct device *parent)
 	}
 }
 
-static void __devexit wistron_led_remove(void)
+static void wistron_led_remove(void)
 {
 	if (leds_present & FE_MAIL_LED)
 		led_classdev_unregister(&wistron_mail_led);
@@ -1168,7 +1168,7 @@ static void wistron_poll(struct input_polled_dev *dev)
 		dev->poll_interval = POLL_INTERVAL_DEFAULT;
 }
 
-static int __devinit wistron_setup_keymap(struct input_dev *dev,
+static int wistron_setup_keymap(struct input_dev *dev,
 					  struct key_entry *entry)
 {
 	switch (entry->type) {
@@ -1199,7 +1199,7 @@ static int __devinit wistron_setup_keymap(struct input_dev *dev,
 	return 0;
 }
 
-static int __devinit setup_input_dev(void)
+static int setup_input_dev(void)
 {
 	struct input_dev *input_dev;
 	int error;
@@ -1237,7 +1237,7 @@ static int __devinit setup_input_dev(void)
 
 /* Driver core */
 
-static int __devinit wistron_probe(struct platform_device *dev)
+static int wistron_probe(struct platform_device *dev)
 {
 	int err;
 
@@ -1277,7 +1277,7 @@ static int __devinit wistron_probe(struct platform_device *dev)
 	return 0;
 }
 
-static int __devexit wistron_remove(struct platform_device *dev)
+static int wistron_remove(struct platform_device *dev)
 {
 	wistron_led_remove();
 	input_unregister_polled_device(wistron_idev);
@@ -1334,7 +1334,7 @@ static struct platform_driver wistron_driver = {
 #endif
 	},
 	.probe		= wistron_probe,
-	.remove		= __devexit_p(wistron_remove),
+	.remove		= wistron_remove,
 };
 
 static int __init wb_module_init(void)
diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c
index 6790a81..558767d 100644
--- a/drivers/input/misc/wm831x-on.c
+++ b/drivers/input/misc/wm831x-on.c
@@ -69,14 +69,15 @@ static irqreturn_t wm831x_on_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int __devinit wm831x_on_probe(struct platform_device *pdev)
+static int wm831x_on_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 	struct wm831x_on *wm831x_on;
 	int irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0));
 	int ret;
 
-	wm831x_on = kzalloc(sizeof(struct wm831x_on), GFP_KERNEL);
+	wm831x_on = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_on),
+				 GFP_KERNEL);
 	if (!wm831x_on) {
 		dev_err(&pdev->dev, "Can't allocate data\n");
 		return -ENOMEM;
@@ -120,11 +121,10 @@ err_irq:
 err_input_dev:
 	input_free_device(wm831x_on->dev);
 err:
-	kfree(wm831x_on);
 	return ret;
 }
 
-static int __devexit wm831x_on_remove(struct platform_device *pdev)
+static int wm831x_on_remove(struct platform_device *pdev)
 {
 	struct wm831x_on *wm831x_on = platform_get_drvdata(pdev);
 	int irq = platform_get_irq(pdev, 0);
@@ -132,14 +132,13 @@ static int __devexit wm831x_on_remove(struct platform_device *pdev)
 	free_irq(irq, wm831x_on);
 	cancel_delayed_work_sync(&wm831x_on->work);
 	input_unregister_device(wm831x_on->dev);
-	kfree(wm831x_on);
 
 	return 0;
 }
 
 static struct platform_driver wm831x_on_driver = {
 	.probe		= wm831x_on_probe,
-	.remove		= __devexit_p(wm831x_on_remove),
+	.remove		= wm831x_on_remove,
 	.driver		= {
 		.name	= "wm831x-on",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c
index 6f7d990..e21c181 100644
--- a/drivers/input/misc/xen-kbdfront.c
+++ b/drivers/input/misc/xen-kbdfront.c
@@ -104,7 +104,7 @@ static irqreturn_t input_handler(int rq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit xenkbd_probe(struct xenbus_device *dev,
+static int xenkbd_probe(struct xenbus_device *dev,
 				  const struct xenbus_device_id *id)
 {
 	int ret, i, abs;
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index cf5af1f..e229fa3 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -767,9 +767,8 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
 		      psmouse->packet[5]) & 0x80) ||
 		    (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) {
 			psmouse_dbg(psmouse,
-				    "refusing packet %x %x %x %x (suspected interleaved ps/2)\n",
-				    psmouse->packet[3], psmouse->packet[4],
-				    psmouse->packet[5], psmouse->packet[6]);
+				    "refusing packet %4ph (suspected interleaved ps/2)\n",
+				    psmouse->packet + 3);
 			return PSMOUSE_BAD_DATA;
 		}
 
@@ -831,9 +830,8 @@ static void alps_flush_packet(unsigned long data)
 		     psmouse->packet[4] |
 		     psmouse->packet[5]) & 0x80) {
 			psmouse_dbg(psmouse,
-				    "refusing packet %x %x %x (suspected interleaved ps/2)\n",
-				    psmouse->packet[3], psmouse->packet[4],
-				    psmouse->packet[5]);
+				    "refusing packet %3ph (suspected interleaved ps/2)\n",
+				    psmouse->packet + 3);
 		} else {
 			alps_process_packet(psmouse);
 		}
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
index 39fe9b7..532eaca 100644
--- a/drivers/input/mouse/gpio_mouse.c
+++ b/drivers/input/mouse/gpio_mouse.c
@@ -46,7 +46,7 @@ static void gpio_mouse_scan(struct input_polled_dev *dev)
 	input_sync(input);
 }
 
-static int __devinit gpio_mouse_probe(struct platform_device *pdev)
+static int gpio_mouse_probe(struct platform_device *pdev)
 {
 	struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data;
 	struct input_polled_dev *input_poll;
@@ -150,7 +150,7 @@ static int __devinit gpio_mouse_probe(struct platform_device *pdev)
 	return error;
 }
 
-static int __devexit gpio_mouse_remove(struct platform_device *pdev)
+static int gpio_mouse_remove(struct platform_device *pdev)
 {
 	struct input_polled_dev *input = platform_get_drvdata(pdev);
 	struct gpio_mouse_platform_data *pdata = input->private;
@@ -172,7 +172,7 @@ static int __devexit gpio_mouse_remove(struct platform_device *pdev)
 
 static struct platform_driver gpio_mouse_device_driver = {
 	.probe		= gpio_mouse_probe,
-	.remove		= __devexit_p(gpio_mouse_remove),
+	.remove		= gpio_mouse_remove,
 	.driver		= {
 		.name	= "gpio_mouse",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c
index 5f27817..0a60717 100644
--- a/drivers/input/mouse/maplemouse.c
+++ b/drivers/input/mouse/maplemouse.c
@@ -64,7 +64,7 @@ static void dc_mouse_close(struct input_dev *dev)
 }
 
 /* allow the mouse to be used */
-static int __devinit probe_maple_mouse(struct device *dev)
+static int probe_maple_mouse(struct device *dev)
 {
 	struct maple_device *mdev = to_maple_dev(dev);
 	struct maple_driver *mdrv = to_maple_driver(dev->driver);
@@ -114,7 +114,7 @@ fail:
 	return error;
 }
 
-static int __devexit remove_maple_mouse(struct device *dev)
+static int remove_maple_mouse(struct device *dev)
 {
 	struct maple_device *mdev = to_maple_dev(dev);
 	struct dc_mouse *mse = maple_get_drvdata(mdev);
@@ -132,7 +132,7 @@ static struct maple_driver dc_mouse_driver = {
 	.drv = {
 		.name = "Dreamcast_mouse",
 		.probe = probe_maple_mouse,
-		.remove = __devexit_p(remove_maple_mouse),
+		.remove = remove_maple_mouse,
 	},
 };
 
diff --git a/drivers/input/mouse/navpoint.c b/drivers/input/mouse/navpoint.c
index c29ae76..8e1b98e 100644
--- a/drivers/input/mouse/navpoint.c
+++ b/drivers/input/mouse/navpoint.c
@@ -206,7 +206,7 @@ static void navpoint_close(struct input_dev *input)
 	navpoint_down(navpoint);
 }
 
-static int __devinit navpoint_probe(struct platform_device *pdev)
+static int navpoint_probe(struct platform_device *pdev)
 {
 	const struct navpoint_platform_data *pdata =
 					dev_get_platdata(&pdev->dev);
@@ -299,7 +299,7 @@ err_free_gpio:
 	return error;
 }
 
-static int __devexit navpoint_remove(struct platform_device *pdev)
+static int navpoint_remove(struct platform_device *pdev)
 {
 	const struct navpoint_platform_data *pdata =
 					dev_get_platdata(&pdev->dev);
@@ -353,7 +353,7 @@ static SIMPLE_DEV_PM_OPS(navpoint_pm_ops, navpoint_suspend, navpoint_resume);
 
 static struct platform_driver navpoint_driver = {
 	.probe		= navpoint_probe,
-	.remove		= __devexit_p(navpoint_remove),
+	.remove		= navpoint_remove,
 	.driver = {
 		.name	= "navpoint",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c
index 4fe055f..0ecb9e7 100644
--- a/drivers/input/mouse/pxa930_trkball.c
+++ b/drivers/input/mouse/pxa930_trkball.c
@@ -143,7 +143,7 @@ static void pxa930_trkball_close(struct input_dev *dev)
 	pxa930_trkball_disable(trkball);
 }
 
-static int __devinit pxa930_trkball_probe(struct platform_device *pdev)
+static int pxa930_trkball_probe(struct platform_device *pdev)
 {
 	struct pxa930_trkball *trkball;
 	struct input_dev *input;
@@ -230,7 +230,7 @@ failed:
 	return error;
 }
 
-static int __devexit pxa930_trkball_remove(struct platform_device *pdev)
+static int pxa930_trkball_remove(struct platform_device *pdev)
 {
 	struct pxa930_trkball *trkball = platform_get_drvdata(pdev);
 	int irq = platform_get_irq(pdev, 0);
@@ -248,7 +248,7 @@ static struct platform_driver pxa930_trkball_driver = {
 		.name	= "pxa930-trkball",
 	},
 	.probe		= pxa930_trkball_probe,
-	.remove		= __devexit_p(pxa930_trkball_remove),
+	.remove		= pxa930_trkball_remove,
 };
 module_platform_driver(pxa930_trkball_driver);
 
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
index 063a174..ad82260 100644
--- a/drivers/input/mouse/synaptics_i2c.c
+++ b/drivers/input/mouse/synaptics_i2c.c
@@ -535,7 +535,7 @@ static struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *clien
 	return touch;
 }
 
-static int __devinit synaptics_i2c_probe(struct i2c_client *client,
+static int synaptics_i2c_probe(struct i2c_client *client,
 			       const struct i2c_device_id *dev_id)
 {
 	int ret;
@@ -601,7 +601,7 @@ err_mem_free:
 	return ret;
 }
 
-static int __devexit synaptics_i2c_remove(struct i2c_client *client)
+static int synaptics_i2c_remove(struct i2c_client *client)
 {
 	struct synaptics_i2c *touch = i2c_get_clientdata(client);
 
@@ -662,7 +662,7 @@ static struct i2c_driver synaptics_i2c_driver = {
 	},
 
 	.probe		= synaptics_i2c_probe,
-	.remove		= __devexit_p(synaptics_i2c_remove),
+	.remove		= synaptics_i2c_remove,
 
 	.id_table	= synaptics_i2c_id_table,
 };
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 55f2c22..4a4e182 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -234,4 +234,13 @@ config SERIO_PS2MULT
 	  To compile this driver as a module, choose M here: the
 	  module will be called ps2mult.
 
+config SERIO_ARC_PS2
+	tristate "ARC PS/2 support"
+	help
+	  Say Y here if you have an ARC FPGA platform with a PS/2
+	  controller in it.
+
+	  To compile this driver as a module, choose M here; the module
+	  will be called arc_ps2.
+
 endif
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index dbbe376..4b0c8f8 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_SERIO_RAW)		+= serio_raw.o
 obj-$(CONFIG_SERIO_AMS_DELTA)	+= ams_delta_serio.o
 obj-$(CONFIG_SERIO_XILINX_XPS_PS2)	+= xilinx_ps2.o
 obj-$(CONFIG_SERIO_ALTERA_PS2)	+= altera_ps2.o
+obj-$(CONFIG_SERIO_ARC_PS2)	+= arc_ps2.o
diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c
index cc11f4e..479ce5f 100644
--- a/drivers/input/serio/altera_ps2.c
+++ b/drivers/input/serio/altera_ps2.c
@@ -81,7 +81,7 @@ static void altera_ps2_close(struct serio *io)
 /*
  * Add one device to this driver.
  */
-static int __devinit altera_ps2_probe(struct platform_device *pdev)
+static int altera_ps2_probe(struct platform_device *pdev)
 {
 	struct ps2if *ps2if;
 	struct serio *serio;
@@ -159,7 +159,7 @@ static int __devinit altera_ps2_probe(struct platform_device *pdev)
 /*
  * Remove one device from this driver.
  */
-static int __devexit altera_ps2_remove(struct platform_device *pdev)
+static int altera_ps2_remove(struct platform_device *pdev)
 {
 	struct ps2if *ps2if = platform_get_drvdata(pdev);
 
@@ -187,7 +187,7 @@ MODULE_DEVICE_TABLE(of, altera_ps2_match);
  */
 static struct platform_driver altera_ps2_driver = {
 	.probe		= altera_ps2_probe,
-	.remove		= __devexit_p(altera_ps2_remove),
+	.remove		= altera_ps2_remove,
 	.driver	= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
index 2e77246..4e2fd44 100644
--- a/drivers/input/serio/ambakmi.c
+++ b/drivers/input/serio/ambakmi.c
@@ -107,7 +107,7 @@ static void amba_kmi_close(struct serio *io)
 	clk_disable_unprepare(kmi->clk);
 }
 
-static int __devinit amba_kmi_probe(struct amba_device *dev,
+static int amba_kmi_probe(struct amba_device *dev,
 	const struct amba_id *id)
 {
 	struct amba_kmi_port *kmi;
@@ -163,7 +163,7 @@ static int __devinit amba_kmi_probe(struct amba_device *dev,
 	return ret;
 }
 
-static int __devexit amba_kmi_remove(struct amba_device *dev)
+static int amba_kmi_remove(struct amba_device *dev)
 {
 	struct amba_kmi_port *kmi = amba_get_drvdata(dev);
 
@@ -204,7 +204,7 @@ static struct amba_driver ambakmi_driver = {
 	},
 	.id_table	= amba_kmi_idtable,
 	.probe		= amba_kmi_probe,
-	.remove		= __devexit_p(amba_kmi_remove),
+	.remove		= amba_kmi_remove,
 	.resume		= amba_kmi_resume,
 };
 
diff --git a/drivers/input/serio/arc_ps2.c b/drivers/input/serio/arc_ps2.c
new file mode 100644
index 0000000..b571eb3
--- /dev/null
+++ b/drivers/input/serio/arc_ps2.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2004, 2007-2010, 2011-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.
+ *
+ * Driver is originally developed by Pavel Sokolov <psokolov@synopsys.com>
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#define ARC_PS2_PORTS                   2
+
+#define ARC_ARC_PS2_ID                  0x0001f609
+
+#define STAT_TIMEOUT                    128
+
+#define PS2_STAT_RX_FRM_ERR             (1)
+#define PS2_STAT_RX_BUF_OVER            (1 << 1)
+#define PS2_STAT_RX_INT_EN              (1 << 2)
+#define PS2_STAT_RX_VAL                 (1 << 3)
+#define PS2_STAT_TX_ISNOT_FUL           (1 << 4)
+#define PS2_STAT_TX_INT_EN              (1 << 5)
+
+struct arc_ps2_port {
+	void __iomem *data_addr;
+	void __iomem *status_addr;
+	struct serio *io;
+};
+
+struct arc_ps2_data {
+	struct arc_ps2_port port[ARC_PS2_PORTS];
+	void __iomem *addr;
+	unsigned int frame_error;
+	unsigned int buf_overflow;
+	unsigned int total_int;
+};
+
+static void arc_ps2_check_rx(struct arc_ps2_data *arc_ps2,
+			     struct arc_ps2_port *port)
+{
+	unsigned int timeout = 1000;
+	unsigned int flag, status;
+	unsigned char data;
+
+	do {
+		status = ioread32(port->status_addr);
+		if (!(status & PS2_STAT_RX_VAL))
+			return;
+
+		data = ioread32(port->data_addr) & 0xff;
+
+		flag = 0;
+		arc_ps2->total_int++;
+		if (status & PS2_STAT_RX_FRM_ERR) {
+			arc_ps2->frame_error++;
+			flag |= SERIO_PARITY;
+		} else if (status & PS2_STAT_RX_BUF_OVER) {
+			arc_ps2->buf_overflow++;
+			flag |= SERIO_FRAME;
+		}
+
+		serio_interrupt(port->io, data, flag);
+	} while (--timeout);
+
+	dev_err(&port->io->dev, "PS/2 hardware stuck\n");
+}
+
+static irqreturn_t arc_ps2_interrupt(int irq, void *dev)
+{
+	struct arc_ps2_data *arc_ps2 = dev;
+	int i;
+
+	for (i = 0; i < ARC_PS2_PORTS; i++)
+		arc_ps2_check_rx(arc_ps2, &arc_ps2->port[i]);
+
+	return IRQ_HANDLED;
+}
+
+static int arc_ps2_write(struct serio *io, unsigned char val)
+{
+	unsigned status;
+	struct arc_ps2_port *port = io->port_data;
+	int timeout = STAT_TIMEOUT;
+
+	do {
+		status = ioread32(port->status_addr);
+		cpu_relax();
+
+		if (status & PS2_STAT_TX_ISNOT_FUL) {
+			iowrite32(val & 0xff, port->data_addr);
+			return 0;
+		}
+
+	} while (--timeout);
+
+	dev_err(&io->dev, "write timeout\n");
+	return -ETIMEDOUT;
+}
+
+static int arc_ps2_open(struct serio *io)
+{
+	struct arc_ps2_port *port = io->port_data;
+
+	iowrite32(PS2_STAT_RX_INT_EN, port->status_addr);
+
+	return 0;
+}
+
+static void arc_ps2_close(struct serio *io)
+{
+	struct arc_ps2_port *port = io->port_data;
+
+	iowrite32(ioread32(port->status_addr) & ~PS2_STAT_RX_INT_EN,
+		  port->status_addr);
+}
+
+static void __iomem *arc_ps2_calc_addr(struct arc_ps2_data *arc_ps2,
+						  int index, bool status)
+{
+	void __iomem *addr;
+
+	addr = arc_ps2->addr + 4 + 4 * index;
+	if (status)
+		addr += ARC_PS2_PORTS * 4;
+
+	return addr;
+}
+
+static void arc_ps2_inhibit_ports(struct arc_ps2_data *arc_ps2)
+{
+	void __iomem *addr;
+	u32 val;
+	int i;
+
+	for (i = 0; i < ARC_PS2_PORTS; i++) {
+		addr = arc_ps2_calc_addr(arc_ps2, i, true);
+		val = ioread32(addr);
+		val &= ~(PS2_STAT_RX_INT_EN | PS2_STAT_TX_INT_EN);
+		iowrite32(val, addr);
+	}
+}
+
+static int arc_ps2_create_port(struct platform_device *pdev,
+					 struct arc_ps2_data *arc_ps2,
+					 int index)
+{
+	struct arc_ps2_port *port = &arc_ps2->port[index];
+	struct serio *io;
+
+	io = kzalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!io)
+		return -ENOMEM;
+
+	io->id.type = SERIO_8042;
+	io->write = arc_ps2_write;
+	io->open = arc_ps2_open;
+	io->close = arc_ps2_close;
+	snprintf(io->name, sizeof(io->name), "ARC PS/2 port%d", index);
+	snprintf(io->phys, sizeof(io->phys), "arc/serio%d", index);
+	io->port_data = port;
+
+	port->io = io;
+
+	port->data_addr = arc_ps2_calc_addr(arc_ps2, index, false);
+	port->status_addr = arc_ps2_calc_addr(arc_ps2, index, true);
+
+	dev_dbg(&pdev->dev, "port%d is allocated (data = 0x%p, status = 0x%p)\n",
+		index, port->data_addr, port->status_addr);
+
+	serio_register_port(port->io);
+	return 0;
+}
+
+static int arc_ps2_probe(struct platform_device *pdev)
+{
+	struct arc_ps2_data *arc_ps2;
+	struct resource *res;
+	int irq;
+	int error, id, i;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "no IO memory defined\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_irq_byname(pdev, "arc_ps2_irq");
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no IRQ defined\n");
+		return -EINVAL;
+	}
+
+	arc_ps2 = devm_kzalloc(&pdev->dev, sizeof(struct arc_ps2_data),
+				GFP_KERNEL);
+	if (!arc_ps2) {
+		dev_err(&pdev->dev, "out of memory\n");
+		return -ENOMEM;
+	}
+
+	arc_ps2->addr = devm_request_and_ioremap(&pdev->dev, res);
+	if (!arc_ps2->addr)
+		return -EBUSY;
+
+	dev_info(&pdev->dev, "irq = %d, address = 0x%p, ports = %i\n",
+		 irq, arc_ps2->addr, ARC_PS2_PORTS);
+
+	id = ioread32(arc_ps2->addr);
+	if (id != ARC_ARC_PS2_ID) {
+		dev_err(&pdev->dev, "device id does not match\n");
+		return -ENXIO;
+	}
+
+	arc_ps2_inhibit_ports(arc_ps2);
+
+	error = devm_request_irq(&pdev->dev, irq, arc_ps2_interrupt,
+				 0, "arc_ps2", arc_ps2);
+	if (error) {
+		dev_err(&pdev->dev, "Could not allocate IRQ\n");
+		return error;
+	}
+
+	for (i = 0; i < ARC_PS2_PORTS; i++) {
+		error = arc_ps2_create_port(pdev, arc_ps2, i);
+		if (error) {
+			while (--i >= 0)
+				serio_unregister_port(arc_ps2->port[i].io);
+			return error;
+		}
+	}
+
+	platform_set_drvdata(pdev, arc_ps2);
+
+	return 0;
+}
+
+static int arc_ps2_remove(struct platform_device *pdev)
+{
+	struct arc_ps2_data *arc_ps2 = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < ARC_PS2_PORTS; i++)
+		serio_unregister_port(arc_ps2->port[i].io);
+
+	dev_dbg(&pdev->dev, "interrupt count = %i\n", arc_ps2->total_int);
+	dev_dbg(&pdev->dev, "frame error count = %i\n", arc_ps2->frame_error);
+	dev_dbg(&pdev->dev, "buffer overflow count = %i\n",
+		arc_ps2->buf_overflow);
+
+	return 0;
+}
+
+static struct platform_driver arc_ps2_driver = {
+	.driver	= {
+		.name	= "arc_ps2",
+		.owner	= THIS_MODULE,
+	},
+	.probe	= arc_ps2_probe,
+	.remove	= arc_ps2_remove,
+};
+
+module_platform_driver(arc_ps2_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pavel Sokolov <psokolov@synopsys.com>");
+MODULE_DESCRIPTION("ARC PS/2 Driver");
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
index 8528165..cfe549d 100644
--- a/drivers/input/serio/ct82c710.c
+++ b/drivers/input/serio/ct82c710.c
@@ -175,7 +175,7 @@ static int __init ct82c710_detect(void)
 	return 0;
 }
 
-static int __devinit ct82c710_probe(struct platform_device *dev)
+static int ct82c710_probe(struct platform_device *dev)
 {
 	ct82c710_port = kzalloc(sizeof(struct serio), GFP_KERNEL);
 	if (!ct82c710_port)
@@ -199,7 +199,7 @@ static int __devinit ct82c710_probe(struct platform_device *dev)
 	return 0;
 }
 
-static int __devexit ct82c710_remove(struct platform_device *dev)
+static int ct82c710_remove(struct platform_device *dev)
 {
 	serio_unregister_port(ct82c710_port);
 
@@ -212,7 +212,7 @@ static struct platform_driver ct82c710_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= ct82c710_probe,
-	.remove		= __devexit_p(ct82c710_remove),
+	.remove		= ct82c710_remove,
 };
 
 
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
index 4225f5d..8d9ba0c 100644
--- a/drivers/input/serio/gscps2.c
+++ b/drivers/input/serio/gscps2.c
@@ -327,7 +327,7 @@ static void gscps2_close(struct serio *port)
  * @return: success/error report
  */
 
-static int __devinit gscps2_probe(struct parisc_device *dev)
+static int gscps2_probe(struct parisc_device *dev)
 {
 	struct gscps2port *ps2port;
 	struct serio *serio;
@@ -414,7 +414,7 @@ fail_nomem:
  * @return: success/error report
  */
 
-static int __devexit gscps2_remove(struct parisc_device *dev)
+static int gscps2_remove(struct parisc_device *dev)
 {
 	struct gscps2port *ps2port = dev_get_drvdata(&dev->dev);
 
@@ -444,7 +444,7 @@ static struct parisc_driver parisc_ps2_driver = {
 	.name		= "gsc_ps2",
 	.id_table	= gscps2_device_tbl,
 	.probe		= gscps2_probe,
-	.remove		= __devexit_p(gscps2_remove),
+	.remove		= gscps2_remove,
 };
 
 static int __init gscps2_init(void)
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index bfd3865..65605e4 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -686,13 +686,12 @@ static int hilse_donode(hil_mlc *mlc)
 		write_lock_irqsave(&mlc->lock, flags);
 		pack = node->object.packet;
 	out:
-		if (mlc->istarted)
-			goto out2;
-		/* Prepare to receive input */
-		if ((node + 1)->act & HILSE_IN)
-			hilse_setup_input(mlc, node + 1);
+		if (!mlc->istarted) {
+			/* Prepare to receive input */
+			if ((node + 1)->act & HILSE_IN)
+				hilse_setup_input(mlc, node + 1);
+		}
 
-	out2:
 		write_unlock_irqrestore(&mlc->lock, flags);
 
 		if (down_trylock(&mlc->osem)) {
@@ -1010,8 +1009,6 @@ static int __init hil_mlc_init(void)
 static void __exit hil_mlc_exit(void)
 {
 	del_timer_sync(&hil_mlcs_kicker);
-
-	tasklet_disable(&hil_mlcs_tasklet);
 	tasklet_kill(&hil_mlcs_tasklet);
 }
 
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
index 5d48bb6..a5eed2a 100644
--- a/drivers/input/serio/i8042-io.h
+++ b/drivers/input/serio/i8042-io.h
@@ -76,7 +76,7 @@ static inline int i8042_platform_init(void)
 	if (check_legacy_ioport(I8042_DATA_REG))
 		return -ENODEV;
 #endif
-#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__)
+#if !defined(__sh__) && !defined(__alpha__)
 	if (!request_region(I8042_DATA_REG, 16, "i8042"))
 		return -EBUSY;
 #endif
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
index 395a9af..d6aa4c6 100644
--- a/drivers/input/serio/i8042-sparcio.h
+++ b/drivers/input/serio/i8042-sparcio.h
@@ -49,7 +49,7 @@ static inline void i8042_write_command(int val)
 #define OBP_PS2MS_NAME1		"kdmouse"
 #define OBP_PS2MS_NAME2		"mouse"
 
-static int __devinit sparc_i8042_probe(struct platform_device *op)
+static int sparc_i8042_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 
@@ -80,7 +80,7 @@ static int __devinit sparc_i8042_probe(struct platform_device *op)
 	return 0;
 }
 
-static int __devexit sparc_i8042_remove(struct platform_device *op)
+static int sparc_i8042_remove(struct platform_device *op)
 {
 	of_iounmap(kbd_res, kbd_iobase, 8);
 
@@ -102,7 +102,7 @@ static struct platform_driver sparc_i8042_driver = {
 		.of_match_table = sparc_i8042_match,
 	},
 	.probe		= sparc_i8042_probe,
-	.remove		= __devexit_p(sparc_i8042_remove),
+	.remove		= sparc_i8042_remove,
 };
 
 static int __init i8042_platform_init(void)
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 8656441..78e4de4 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -1284,7 +1284,7 @@ static void __init i8042_register_ports(void)
 	}
 }
 
-static void __devexit i8042_unregister_ports(void)
+static void i8042_unregister_ports(void)
 {
 	int i;
 
@@ -1437,7 +1437,7 @@ static int __init i8042_probe(struct platform_device *dev)
 	return error;
 }
 
-static int __devexit i8042_remove(struct platform_device *dev)
+static int i8042_remove(struct platform_device *dev)
 {
 	i8042_unregister_ports();
 	i8042_free_irqs();
@@ -1455,7 +1455,7 @@ static struct platform_driver i8042_driver = {
 		.pm	= &i8042_pm_ops,
 #endif
 	},
-	.remove		= __devexit_p(i8042_remove),
+	.remove		= i8042_remove,
 	.shutdown	= i8042_shutdown,
 };
 
diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
index 61da763..bc85e1c 100644
--- a/drivers/input/serio/maceps2.c
+++ b/drivers/input/serio/maceps2.c
@@ -116,7 +116,7 @@ static void maceps2_close(struct serio *dev)
 }
 
 
-static struct serio * __devinit maceps2_allocate_port(int idx)
+static struct serio *maceps2_allocate_port(int idx)
 {
 	struct serio *serio;
 
@@ -135,7 +135,7 @@ static struct serio * __devinit maceps2_allocate_port(int idx)
 	return serio;
 }
 
-static int __devinit maceps2_probe(struct platform_device *dev)
+static int maceps2_probe(struct platform_device *dev)
 {
 	maceps2_port[0] = maceps2_allocate_port(0);
 	maceps2_port[1] = maceps2_allocate_port(1);
@@ -151,7 +151,7 @@ static int __devinit maceps2_probe(struct platform_device *dev)
 	return 0;
 }
 
-static int __devexit maceps2_remove(struct platform_device *dev)
+static int maceps2_remove(struct platform_device *dev)
 {
 	serio_unregister_port(maceps2_port[0]);
 	serio_unregister_port(maceps2_port[1]);
@@ -165,7 +165,7 @@ static struct platform_driver maceps2_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= maceps2_probe,
-	.remove		= __devexit_p(maceps2_remove),
+	.remove		= maceps2_remove,
 };
 
 static int __init maceps2_init(void)
diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c
index 0c42497..76f8383 100644
--- a/drivers/input/serio/pcips2.c
+++ b/drivers/input/serio/pcips2.c
@@ -127,7 +127,7 @@ static void pcips2_close(struct serio *io)
 	free_irq(ps2if->dev->irq, ps2if);
 }
 
-static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	struct pcips2_data *ps2if;
 	struct serio *serio;
@@ -176,7 +176,7 @@ static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_i
 	return ret;
 }
 
-static void __devexit pcips2_remove(struct pci_dev *dev)
+static void pcips2_remove(struct pci_dev *dev)
 {
 	struct pcips2_data *ps2if = pci_get_drvdata(dev);
 
@@ -212,7 +212,7 @@ static struct pci_driver pcips2_driver = {
 	.name			= "pcips2",
 	.id_table		= pcips2_ids,
 	.probe			= pcips2_probe,
-	.remove			= __devexit_p(pcips2_remove),
+	.remove			= pcips2_remove,
 };
 
 module_pci_driver(pcips2_driver);
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
index 0c0df7f..70fe542 100644
--- a/drivers/input/serio/q40kbd.c
+++ b/drivers/input/serio/q40kbd.c
@@ -122,7 +122,7 @@ static void q40kbd_close(struct serio *port)
 	q40kbd_flush(q40kbd);
 }
 
-static int __devinit q40kbd_probe(struct platform_device *pdev)
+static int q40kbd_probe(struct platform_device *pdev)
 {
 	struct q40kbd *q40kbd;
 	struct serio *port;
@@ -168,7 +168,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit q40kbd_remove(struct platform_device *pdev)
+static int q40kbd_remove(struct platform_device *pdev)
 {
 	struct q40kbd *q40kbd = platform_get_drvdata(pdev);
 
@@ -190,7 +190,7 @@ static struct platform_driver q40kbd_driver = {
 		.name	= "q40kbd",
 		.owner	= THIS_MODULE,
 	},
-	.remove		= __devexit_p(q40kbd_remove),
+	.remove		= q40kbd_remove,
 };
 
 static int __init q40kbd_init(void)
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
index 2af5df6..567566a 100644
--- a/drivers/input/serio/rpckbd.c
+++ b/drivers/input/serio/rpckbd.c
@@ -114,7 +114,7 @@ static void rpckbd_close(struct serio *port)
  * Allocate and initialize serio structure for subsequent registration
  * with serio core.
  */
-static int __devinit rpckbd_probe(struct platform_device *dev)
+static int rpckbd_probe(struct platform_device *dev)
 {
 	struct rpckbd_data *rpckbd;
 	struct serio *serio;
@@ -153,7 +153,7 @@ static int __devinit rpckbd_probe(struct platform_device *dev)
 	return 0;
 }
 
-static int __devexit rpckbd_remove(struct platform_device *dev)
+static int rpckbd_remove(struct platform_device *dev)
 {
 	struct serio *serio = platform_get_drvdata(dev);
 	struct rpckbd_data *rpckbd = serio->port_data;
@@ -166,7 +166,7 @@ static int __devexit rpckbd_remove(struct platform_device *dev)
 
 static struct platform_driver rpckbd_driver = {
 	.probe		= rpckbd_probe,
-	.remove		= __devexit_p(rpckbd_remove),
+	.remove		= rpckbd_remove,
 	.driver		= {
 		.name	= "kart",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index 3897667..b3e6889 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -193,7 +193,7 @@ static void ps2_close(struct serio *io)
 /*
  * Clear the input buffer.
  */
-static void __devinit ps2_clear_input(struct ps2if *ps2if)
+static void ps2_clear_input(struct ps2if *ps2if)
 {
 	int maxread = 100;
 
@@ -203,7 +203,7 @@ static void __devinit ps2_clear_input(struct ps2if *ps2if)
 	}
 }
 
-static unsigned int __devinit ps2_test_one(struct ps2if *ps2if,
+static unsigned int ps2_test_one(struct ps2if *ps2if,
 					   unsigned int mask)
 {
 	unsigned int val;
@@ -220,7 +220,7 @@ static unsigned int __devinit ps2_test_one(struct ps2if *ps2if,
  * Test the keyboard interface.  We basically check to make sure that
  * we can drive each line to the keyboard independently of each other.
  */
-static int __devinit ps2_test(struct ps2if *ps2if)
+static int ps2_test(struct ps2if *ps2if)
 {
 	unsigned int stat;
 	int ret = 0;
@@ -251,7 +251,7 @@ static int __devinit ps2_test(struct ps2if *ps2if)
 /*
  * Add one device to this driver.
  */
-static int __devinit ps2_probe(struct sa1111_dev *dev)
+static int ps2_probe(struct sa1111_dev *dev)
 {
 	struct ps2if *ps2if;
 	struct serio *serio;
@@ -334,7 +334,7 @@ static int __devinit ps2_probe(struct sa1111_dev *dev)
 /*
  * Remove one device from this driver.
  */
-static int __devexit ps2_remove(struct sa1111_dev *dev)
+static int ps2_remove(struct sa1111_dev *dev)
 {
 	struct ps2if *ps2if = sa1111_get_drvdata(dev);
 
@@ -357,7 +357,7 @@ static struct sa1111_driver ps2_driver = {
 	},
 	.devid		= SA1111_DEVID_PS2,
 	.probe		= ps2_probe,
-	.remove		= __devexit_p(ps2_remove),
+	.remove		= ps2_remove,
 };
 
 static int __init ps2_init(void)
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index d0f7533..25fc597 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -891,8 +891,6 @@ static int serio_bus_match(struct device *dev, struct device_driver *drv)
 	return serio_match_port(serio_drv->id_table, serio);
 }
 
-#ifdef CONFIG_HOTPLUG
-
 #define SERIO_ADD_UEVENT_VAR(fmt, val...)				\
 	do {								\
 		int err = add_uevent_var(env, fmt, val);		\
@@ -920,15 +918,6 @@ static int serio_uevent(struct device *dev, struct kobj_uevent_env *env)
 }
 #undef SERIO_ADD_UEVENT_VAR
 
-#else
-
-static int serio_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-	return -ENODEV;
-}
-
-#endif /* CONFIG_HOTPLUG */
-
 #ifdef CONFIG_PM
 static int serio_suspend(struct device *dev)
 {
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
index 1e983be..17be859 100644
--- a/drivers/input/serio/xilinx_ps2.c
+++ b/drivers/input/serio/xilinx_ps2.c
@@ -233,7 +233,7 @@ static void sxps2_close(struct serio *pserio)
  * It returns 0, if the driver is bound to the PS/2 device, or a negative
  * value if there is an error.
  */
-static int __devinit xps2_of_probe(struct platform_device *ofdev)
+static int xps2_of_probe(struct platform_device *ofdev)
 {
 	struct resource r_irq; /* Interrupt resources */
 	struct resource r_mem; /* IO mem resources */
@@ -333,7 +333,7 @@ failed1:
  * if the driver module is being unloaded. It frees any resources allocated to
  * the device.
  */
-static int __devexit xps2_of_remove(struct platform_device *of_dev)
+static int xps2_of_remove(struct platform_device *of_dev)
 {
 	struct xps2data *drvdata = platform_get_drvdata(of_dev);
 	struct resource r_mem; /* IO mem resources */
@@ -355,7 +355,7 @@ static int __devexit xps2_of_remove(struct platform_device *of_dev)
 }
 
 /* Match table for of_platform binding */
-static const struct of_device_id xps2_of_match[] __devinitconst = {
+static const struct of_device_id xps2_of_match[] = {
 	{ .compatible = "xlnx,xps-ps2-1.00.a", },
 	{ /* end of list */ },
 };
@@ -368,7 +368,7 @@ static struct platform_driver xps2_of_driver = {
 		.of_match_table = xps2_of_match,
 	},
 	.probe		= xps2_of_probe,
-	.remove		= __devexit_p(xps2_of_remove),
+	.remove		= xps2_of_remove,
 };
 module_platform_driver(xps2_of_driver);
 
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 858ad44..f92d34f 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -386,23 +386,40 @@ static int wacom_parse_hid(struct usb_interface *intf,
 				if (usage == WCM_DESKTOP) {
 					if (finger) {
 						features->device_type = BTN_TOOL_FINGER;
-						if (features->type == TABLETPC2FG) {
-							/* need to reset back */
+
+						switch (features->type) {
+						case TABLETPC2FG:
 							features->pktlen = WACOM_PKGLEN_TPC2FG;
-						}
+							break;
 
-						if (features->type == MTSCREEN || features->type == WACOM_24HDT)
+						case MTSCREEN:
+						case WACOM_24HDT:
 							features->pktlen = WACOM_PKGLEN_MTOUCH;
+							break;
 
-						if (features->type == BAMBOO_PT) {
-							/* need to reset back */
+						case MTTPC:
+							features->pktlen = WACOM_PKGLEN_MTTPC;
+							break;
+
+						case BAMBOO_PT:
 							features->pktlen = WACOM_PKGLEN_BBTOUCH;
+							break;
+
+						default:
+							features->pktlen = WACOM_PKGLEN_GRAPHIRE;
+							break;
+						}
+
+						switch (features->type) {
+						case BAMBOO_PT:
 							features->x_phy =
 								get_unaligned_le16(&report[i + 5]);
 							features->x_max =
 								get_unaligned_le16(&report[i + 8]);
 							i += 15;
-						} else if (features->type == WACOM_24HDT) {
+							break;
+
+						case WACOM_24HDT:
 							features->x_max =
 								get_unaligned_le16(&report[i + 3]);
 							features->x_phy =
@@ -410,7 +427,9 @@ static int wacom_parse_hid(struct usb_interface *intf,
 							features->unit = report[i - 1];
 							features->unitExpo = report[i - 3];
 							i += 12;
-						} else {
+							break;
+
+						default:
 							features->x_max =
 								get_unaligned_le16(&report[i + 3]);
 							features->x_phy =
@@ -418,10 +437,11 @@ static int wacom_parse_hid(struct usb_interface *intf,
 							features->unit = report[i + 9];
 							features->unitExpo = report[i + 11];
 							i += 12;
+							break;
 						}
 					} else if (pen) {
 						/* penabled only accepts exact bytes of data */
-						if (features->type == TABLETPC2FG)
+						if (features->type >= TABLETPC)
 							features->pktlen = WACOM_PKGLEN_GRAPHIRE;
 						features->device_type = BTN_TOOL_PEN;
 						features->x_max =
@@ -434,32 +454,40 @@ static int wacom_parse_hid(struct usb_interface *intf,
 			case HID_USAGE_Y:
 				if (usage == WCM_DESKTOP) {
 					if (finger) {
-						int type = features->type;
-
-						if (type == TABLETPC2FG || type == MTSCREEN) {
+						switch (features->type) {
+						case TABLETPC2FG:
+						case MTSCREEN:
+						case MTTPC:
 							features->y_max =
 								get_unaligned_le16(&report[i + 3]);
 							features->y_phy =
 								get_unaligned_le16(&report[i + 6]);
 							i += 7;
-						} else if (type == WACOM_24HDT) {
+							break;
+
+						case WACOM_24HDT:
 							features->y_max =
 								get_unaligned_le16(&report[i + 3]);
 							features->y_phy =
 								get_unaligned_le16(&report[i - 2]);
 							i += 7;
-						} else if (type == BAMBOO_PT) {
+							break;
+
+						case BAMBOO_PT:
 							features->y_phy =
 								get_unaligned_le16(&report[i + 3]);
 							features->y_max =
 								get_unaligned_le16(&report[i + 6]);
 							i += 12;
-						} else {
+							break;
+
+						default:
 							features->y_max =
 								features->x_max;
 							features->y_phy =
 								get_unaligned_le16(&report[i + 3]);
 							i += 4;
+							break;
 						}
 					} else if (pen) {
 						features->y_max =
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 0a67031..c0f3e91 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -467,9 +467,7 @@ static void wacom_intuos_general(struct wacom_wac *wacom)
 	/* general pen packet */
 	if ((data[1] & 0xb8) == 0xa0) {
 		t = (data[6] << 2) | ((data[7] >> 6) & 3);
-		if ((features->type >= INTUOS4S && features->type <= INTUOS4L) ||
-                    (features->type >= INTUOS5S && features->type <= INTUOS5L) ||
-		    (features->type >= WACOM_21UX2 && features->type <= WACOM_24HD)) {
+		if (features->type >= INTUOS4S && features->type <= WACOM_24HD) {
 			t = (t << 1) | (data[1] & 1);
 		}
 		input_report_abs(input, ABS_PRESSURE, t);
@@ -877,6 +875,11 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
 	int i;
 	int current_num_contacts = data[2];
 	int contacts_to_send = 0;
+	int x_offset = 0;
+
+	/* MTTPC does not support Height and Width */
+	if (wacom->features.type == MTTPC)
+		x_offset = -4;
 
 	/*
 	 * First packet resets the counter since only the first
@@ -889,7 +892,7 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
 	contacts_to_send = min(5, wacom->num_contacts_left);
 
 	for (i = 0; i < contacts_to_send; i++) {
-		int offset = (WACOM_BYTES_PER_MT_PACKET * i) + 3;
+		int offset = (WACOM_BYTES_PER_MT_PACKET + x_offset) * i + 3;
 		bool touch = data[offset] & 0x1;
 		int id = le16_to_cpup((__le16 *)&data[offset + 1]);
 		int slot = find_slot_from_contactid(wacom, id);
@@ -900,8 +903,8 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
 		input_mt_slot(input, slot);
 		input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
 		if (touch) {
-			int x = le16_to_cpup((__le16 *)&data[offset + 7]);
-			int y = le16_to_cpup((__le16 *)&data[offset + 9]);
+			int x = le16_to_cpup((__le16 *)&data[offset + x_offset + 7]);
+			int y = le16_to_cpup((__le16 *)&data[offset + x_offset + 9]);
 			input_report_abs(input, ABS_MT_POSITION_X, x);
 			input_report_abs(input, ABS_MT_POSITION_Y, y);
 		}
@@ -1336,6 +1339,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
 	case TABLETPCE:
 	case TABLETPC2FG:
 	case MTSCREEN:
+	case MTTPC:
 		sync = wacom_tpc_irq(wacom_wac, len);
 		break;
 
@@ -1657,6 +1661,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
 		/* fall through */
 
 	case MTSCREEN:
+	case MTTPC:
 		if (features->device_type == BTN_TOOL_FINGER) {
 			wacom_wac->slots = kmalloc(features->touch_max *
 							sizeof(int),
@@ -2018,6 +2023,15 @@ static const struct wacom_features wacom_features_0xED =
 static const struct wacom_features wacom_features_0xEF =
 	{ "Wacom ISDv4 EF",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
 	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x100 =
+	{ "Wacom ISDv4 100",      WACOM_PKGLEN_MTTPC,     26202, 16325,  255,
+	  0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x101 =
+	{ "Wacom ISDv4 101",      WACOM_PKGLEN_MTTPC,     26202, 16325,  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 };
 static const struct wacom_features wacom_features_0x47 =
 	{ "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023,
 	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -2194,6 +2208,9 @@ const struct usb_device_id wacom_ids[] = {
 	{ USB_DEVICE_WACOM(0xEC) },
 	{ USB_DEVICE_WACOM(0xED) },
 	{ USB_DEVICE_WACOM(0xEF) },
+	{ USB_DEVICE_WACOM(0x100) },
+	{ USB_DEVICE_WACOM(0x101) },
+	{ USB_DEVICE_WACOM(0x4001) },
 	{ USB_DEVICE_WACOM(0x47) },
 	{ USB_DEVICE_WACOM(0xF4) },
 	{ USB_DEVICE_WACOM(0xF8) },
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index 345f1e7..9396d77 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -26,6 +26,7 @@
 #define WACOM_PKGLEN_BBPEN	10
 #define WACOM_PKGLEN_WIRELESS	32
 #define WACOM_PKGLEN_MTOUCH	62
+#define WACOM_PKGLEN_MTTPC	40
 
 /* wacom data size per MT contact */
 #define WACOM_BYTES_PER_MT_PACKET	11
@@ -88,6 +89,7 @@ enum {
 	TABLETPCE,
 	TABLETPC2FG,
 	MTSCREEN,
+	MTTPC,
 	MAX_TYPE
 };
 
diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c
index 326218d..c706894 100644
--- a/drivers/input/touchscreen/88pm860x-ts.c
+++ b/drivers/input/touchscreen/88pm860x-ts.c
@@ -115,7 +115,7 @@ static void pm860x_touch_close(struct input_dev *dev)
 }
 
 #ifdef CONFIG_OF
-static int __devinit pm860x_touch_dt_init(struct platform_device *pdev,
+static int pm860x_touch_dt_init(struct platform_device *pdev,
 					  struct pm860x_chip *chip,
 					  int *res_x)
 {
@@ -169,7 +169,7 @@ static int __devinit pm860x_touch_dt_init(struct platform_device *pdev,
 #define pm860x_touch_dt_init(x, y, z)	(-1)
 #endif
 
-static int __devinit pm860x_touch_probe(struct platform_device *pdev)
+static int pm860x_touch_probe(struct platform_device *pdev)
 {
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct pm860x_touch_pdata *pdata = pdev->dev.platform_data;
@@ -293,7 +293,7 @@ out:
 	return ret;
 }
 
-static int __devexit pm860x_touch_remove(struct platform_device *pdev)
+static int pm860x_touch_remove(struct platform_device *pdev)
 {
 	struct pm860x_touch *touch = platform_get_drvdata(pdev);
 
@@ -310,7 +310,7 @@ static struct platform_driver pm860x_touch_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe	= pm860x_touch_probe,
-	.remove	= __devexit_p(pm860x_touch_remove),
+	.remove	= pm860x_touch_remove,
 };
 module_platform_driver(pm860x_touch_driver);
 
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index f7668b2..515cfe7 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -111,18 +111,6 @@ config TOUCHSCREEN_AUO_PIXCIR
 	  To compile this driver as a module, choose M here: the
 	  module will be called auo-pixcir-ts.
 
-config TOUCHSCREEN_BITSY
-	tristate "Compaq iPAQ H3600 (Bitsy) touchscreen"
-	depends on SA1100_BITSY
-	select SERIO
-	help
-	  Say Y here if you have the h3600 (Bitsy) touchscreen.
-
-	  If unsure, say N.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called h3600_ts_input.
-
 config TOUCHSCREEN_BU21013
 	tristate "BU21013 based touch panel controllers"
 	depends on I2C
@@ -529,9 +517,9 @@ config TOUCHSCREEN_TOUCHWIN
 	  To compile this driver as a module, choose M here: the
 	  module will be called touchwin.
 
-config TOUCHSCREEN_TI_TSCADC
+config TOUCHSCREEN_TI_AM335X_TSC
 	tristate "TI Touchscreen Interface"
-	depends on ARCH_OMAP2PLUS
+	depends on MFD_TI_AM335X_TSCADC
 	help
 	  Say Y here if you have 4/5/8 wire touchscreen controller
 	  to be connected to the ADC controller on your TI AM335x SoC.
@@ -539,7 +527,7 @@ config TOUCHSCREEN_TI_TSCADC
 	  If unsure, say N.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called ti_tscadc.
+	  module will be called ti_am335x_tsc.
 
 config TOUCHSCREEN_ATMEL_TSADCC
 	tristate "Atmel Touchscreen Interface"
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 178eb12..6bfbeab 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -15,7 +15,6 @@ obj-$(CONFIG_TOUCHSCREEN_ADS7846)	+= ads7846.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT)	+= atmel_mxt_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC)	+= atmel_tsadcc.o
 obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR)	+= auo-pixcir-ts.o
-obj-$(CONFIG_TOUCHSCREEN_BITSY)		+= h3600_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_BU21013)	+= bu21013_ts.o
 obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110)	+= cy8ctmg110_ts.o
 obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE)	+= cyttsp_core.o
@@ -52,7 +51,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR)	+= pixcir_i2c_ts.o
 obj-$(CONFIG_TOUCHSCREEN_S3C2410)	+= s3c2410_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ST1232)	+= st1232.o
 obj-$(CONFIG_TOUCHSCREEN_STMPE)		+= stmpe-ts.o
-obj-$(CONFIG_TOUCHSCREEN_TI_TSCADC)	+= ti_tscadc.o
+obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC)	+= ti_am335x_tsc.o
 obj-$(CONFIG_TOUCHSCREEN_TNETV107X)	+= tnetv107x-ts.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)	+= touchit213.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)	+= touchright.o
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
index 2c76921..23fa829b8 100644
--- a/drivers/input/touchscreen/ad7877.c
+++ b/drivers/input/touchscreen/ad7877.c
@@ -682,7 +682,7 @@ static void ad7877_setup_ts_def_msg(struct spi_device *spi, struct ad7877 *ts)
 	}
 }
 
-static int __devinit ad7877_probe(struct spi_device *spi)
+static int ad7877_probe(struct spi_device *spi)
 {
 	struct ad7877			*ts;
 	struct input_dev		*input_dev;
@@ -810,7 +810,7 @@ err_free_mem:
 	return err;
 }
 
-static int __devexit ad7877_remove(struct spi_device *spi)
+static int ad7877_remove(struct spi_device *spi)
 {
 	struct ad7877 *ts = dev_get_drvdata(&spi->dev);
 
@@ -857,7 +857,7 @@ static struct spi_driver ad7877_driver = {
 		.pm	= &ad7877_pm,
 	},
 	.probe		= ad7877_probe,
-	.remove		= __devexit_p(ad7877_remove),
+	.remove		= ad7877_remove,
 };
 
 module_spi_driver(ad7877_driver);
diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c
index 3054354..dcf3907 100644
--- a/drivers/input/touchscreen/ad7879-i2c.c
+++ b/drivers/input/touchscreen/ad7879-i2c.c
@@ -54,7 +54,7 @@ static const struct ad7879_bus_ops ad7879_i2c_bus_ops = {
 	.write		= ad7879_i2c_write,
 };
 
-static int __devinit ad7879_i2c_probe(struct i2c_client *client,
+static int ad7879_i2c_probe(struct i2c_client *client,
 				      const struct i2c_device_id *id)
 {
 	struct ad7879 *ts;
@@ -75,7 +75,7 @@ static int __devinit ad7879_i2c_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int __devexit ad7879_i2c_remove(struct i2c_client *client)
+static int ad7879_i2c_remove(struct i2c_client *client)
 {
 	struct ad7879 *ts = i2c_get_clientdata(client);
 
@@ -98,7 +98,7 @@ static struct i2c_driver ad7879_i2c_driver = {
 		.pm	= &ad7879_pm_ops,
 	},
 	.probe		= ad7879_i2c_probe,
-	.remove		= __devexit_p(ad7879_i2c_remove),
+	.remove		= ad7879_i2c_remove,
 	.id_table	= ad7879_id,
 };
 
diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c
index db49abf..606da5b 100644
--- a/drivers/input/touchscreen/ad7879-spi.c
+++ b/drivers/input/touchscreen/ad7879-spi.c
@@ -110,7 +110,7 @@ static const struct ad7879_bus_ops ad7879_spi_bus_ops = {
 	.write		= ad7879_spi_write,
 };
 
-static int __devinit ad7879_spi_probe(struct spi_device *spi)
+static int ad7879_spi_probe(struct spi_device *spi)
 {
 	struct ad7879 *ts;
 	int err;
@@ -137,7 +137,7 @@ static int __devinit ad7879_spi_probe(struct spi_device *spi)
 	return 0;
 }
 
-static int __devexit ad7879_spi_remove(struct spi_device *spi)
+static int ad7879_spi_remove(struct spi_device *spi)
 {
 	struct ad7879 *ts = spi_get_drvdata(spi);
 
@@ -154,7 +154,7 @@ static struct spi_driver ad7879_spi_driver = {
 		.pm	= &ad7879_pm_ops,
 	},
 	.probe		= ad7879_spi_probe,
-	.remove		= __devexit_p(ad7879_spi_remove),
+	.remove		= ad7879_spi_remove,
 };
 
 module_spi_driver(ad7879_spi_driver);
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 78e5d9a..4f702b3 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -955,7 +955,7 @@ static int ads7846_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume);
 
-static int __devinit ads7846_setup_pendown(struct spi_device *spi,
+static int ads7846_setup_pendown(struct spi_device *spi,
 					   struct ads7846 *ts)
 {
 	struct ads7846_platform_data *pdata = spi->dev.platform_data;
@@ -997,7 +997,7 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi,
  * Set up the transfers to read touchscreen state; this assumes we
  * use formula #2 for pressure, not #3.
  */
-static void __devinit ads7846_setup_spi_msg(struct ads7846 *ts,
+static void ads7846_setup_spi_msg(struct ads7846 *ts,
 				const struct ads7846_platform_data *pdata)
 {
 	struct spi_message *m = &ts->msg[0];
@@ -1196,7 +1196,7 @@ static void __devinit ads7846_setup_spi_msg(struct ads7846 *ts,
 	spi_message_add_tail(x, m);
 }
 
-static int __devinit ads7846_probe(struct spi_device *spi)
+static int ads7846_probe(struct spi_device *spi)
 {
 	struct ads7846 *ts;
 	struct ads7846_packet *packet;
@@ -1390,7 +1390,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
 	return err;
 }
 
-static int __devexit ads7846_remove(struct spi_device *spi)
+static int ads7846_remove(struct spi_device *spi)
 {
 	struct ads7846 *ts = dev_get_drvdata(&spi->dev);
 
@@ -1434,7 +1434,7 @@ static struct spi_driver ads7846_driver = {
 		.pm	= &ads7846_pm,
 	},
 	.probe		= ads7846_probe,
-	.remove		= __devexit_p(ads7846_remove),
+	.remove		= ads7846_remove,
 };
 
 module_spi_driver(ads7846_driver);
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 1df2396..d04f810 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -1095,7 +1095,7 @@ static void mxt_input_close(struct input_dev *dev)
 	mxt_stop(data);
 }
 
-static int __devinit mxt_probe(struct i2c_client *client,
+static int mxt_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	const struct mxt_platform_data *pdata = client->dev.platform_data;
@@ -1200,7 +1200,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit mxt_remove(struct i2c_client *client)
+static int mxt_remove(struct i2c_client *client)
 {
 	struct mxt_data *data = i2c_get_clientdata(client);
 
@@ -1270,7 +1270,7 @@ static struct i2c_driver mxt_driver = {
 		.pm	= &mxt_pm_ops,
 	},
 	.probe		= mxt_probe,
-	.remove		= __devexit_p(mxt_remove),
+	.remove		= mxt_remove,
 	.id_table	= mxt_id,
 };
 
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c
index 201b2d2..95f6785 100644
--- a/drivers/input/touchscreen/atmel_tsadcc.c
+++ b/drivers/input/touchscreen/atmel_tsadcc.c
@@ -22,7 +22,7 @@
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <mach/board.h>
+#include <linux/platform_data/atmel.h>
 #include <mach/cpu.h>
 
 /* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */
@@ -177,7 +177,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
  * The functions for inserting/removing us as a module.
  */
 
-static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
+static int atmel_tsadcc_probe(struct platform_device *pdev)
 {
 	struct atmel_tsadcc	*ts_dev;
 	struct input_dev	*input_dev;
@@ -323,7 +323,7 @@ err_free_mem:
 	return err;
 }
 
-static int __devexit atmel_tsadcc_remove(struct platform_device *pdev)
+static int atmel_tsadcc_remove(struct platform_device *pdev)
 {
 	struct atmel_tsadcc *ts_dev = dev_get_drvdata(&pdev->dev);
 	struct resource *res;
@@ -346,7 +346,7 @@ static int __devexit atmel_tsadcc_remove(struct platform_device *pdev)
 
 static struct platform_driver atmel_tsadcc_driver = {
 	.probe		= atmel_tsadcc_probe,
-	.remove		= __devexit_p(atmel_tsadcc_remove),
+	.remove		= atmel_tsadcc_remove,
 	.driver		= {
 		.name	= "atmel_tsadcc",
 	},
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c
index c7047b6..c6e19a9 100644
--- a/drivers/input/touchscreen/auo-pixcir-ts.c
+++ b/drivers/input/touchscreen/auo-pixcir-ts.c
@@ -286,7 +286,7 @@ static int auo_pixcir_power_mode(struct auo_pixcir_ts *ts, int mode)
 	return 0;
 }
 
-static __devinit int auo_pixcir_int_config(struct auo_pixcir_ts *ts,
+static int auo_pixcir_int_config(struct auo_pixcir_ts *ts,
 					   int int_setting)
 {
 	struct i2c_client *client = ts->client;
@@ -482,7 +482,7 @@ unlock:
 static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops, auo_pixcir_suspend,
 			 auo_pixcir_resume);
 
-static int __devinit auo_pixcir_probe(struct i2c_client *client,
+static int auo_pixcir_probe(struct i2c_client *client,
 				      const struct i2c_device_id *id)
 {
 	const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
@@ -599,7 +599,7 @@ err_gpio_int:
 	return ret;
 }
 
-static int __devexit auo_pixcir_remove(struct i2c_client *client)
+static int auo_pixcir_remove(struct i2c_client *client)
 {
 	struct auo_pixcir_ts *ts = i2c_get_clientdata(client);
 	const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
@@ -631,7 +631,7 @@ static struct i2c_driver auo_pixcir_driver = {
 		.pm	= &auo_pixcir_pm_ops,
 	},
 	.probe		= auo_pixcir_probe,
-	.remove		= __devexit_p(auo_pixcir_remove),
+	.remove		= auo_pixcir_remove,
 	.id_table	= auo_pixcir_idtable,
 };
 
diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c
index 5c487d2..b9b5dda 100644
--- a/drivers/input/touchscreen/bu21013_ts.c
+++ b/drivers/input/touchscreen/bu21013_ts.c
@@ -14,6 +14,9 @@
 #include <linux/slab.h>
 #include <linux/regulator/consumer.h>
 #include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 
 #define PEN_DOWN_INTR	0
 #define MAX_FINGERS	2
@@ -148,11 +151,12 @@
 struct bu21013_ts_data {
 	struct i2c_client *client;
 	wait_queue_head_t wait;
-	bool touch_stopped;
 	const struct bu21013_platform_device *chip;
 	struct input_dev *in_dev;
-	unsigned int intr_pin;
 	struct regulator *regulator;
+	unsigned int irq;
+	unsigned int intr_pin;
+	bool touch_stopped;
 };
 
 /**
@@ -262,7 +266,7 @@ static irqreturn_t bu21013_gpio_irq(int irq, void *device_data)
 			return IRQ_NONE;
 		}
 
-		data->intr_pin = data->chip->irq_read_val();
+		data->intr_pin = gpio_get_value(data->chip->touch_pin);
 		if (data->intr_pin == PEN_DOWN_INTR)
 			wait_event_timeout(data->wait, data->touch_stopped,
 					   msecs_to_jiffies(2));
@@ -418,8 +422,70 @@ static void bu21013_free_irq(struct bu21013_ts_data *bu21013_data)
 {
 	bu21013_data->touch_stopped = true;
 	wake_up(&bu21013_data->wait);
-	free_irq(bu21013_data->chip->irq, bu21013_data);
+	free_irq(bu21013_data->irq, bu21013_data);
+}
+
+/**
+ * bu21013_cs_disable() - deconfigures the touch panel controller
+ * @bu21013_data: device structure pointer
+ *
+ * This function is used to deconfigure the chip selection
+ * for touch panel controller.
+ */
+static void bu21013_cs_disable(struct bu21013_ts_data *bu21013_data)
+{
+	int error;
+
+	error = gpio_direction_output(bu21013_data->chip->cs_pin, 0);
+	if (error < 0)
+		dev_warn(&bu21013_data->client->dev,
+			 "%s: gpio direction failed, error: %d\n",
+			 __func__, error);
+	else
+		gpio_set_value(bu21013_data->chip->cs_pin, 0);
+
+	gpio_free(bu21013_data->chip->cs_pin);
+}
+
+#ifdef CONFIG_OF
+static const struct bu21013_platform_device *
+bu21013_parse_dt(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct bu21013_platform_device *pdata;
+
+	if (!np) {
+		dev_err(dev, "no device tree or platform data\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	pdata->y_flip = pdata->x_flip = false;
+
+	pdata->x_flip = of_property_read_bool(np, "rohm,flip-x");
+	pdata->y_flip = of_property_read_bool(np, "rohm,flip-y");
+
+	of_property_read_u32(np, "rohm,touch-max-x", &pdata->touch_x_max);
+	of_property_read_u32(np, "rohm,touch-max-y", &pdata->touch_y_max);
+
+	pdata->touch_pin = of_get_named_gpio(np, "touch-gpio", 0);
+	pdata->cs_pin = of_get_named_gpio(np, "reset-gpio", 0);
+
+	pdata->ext_clk = false;
+
+	return pdata;
 }
+#else
+static inline const struct bu21013_platform_device *
+bu21013_parse_dt(struct device *dev)
+{
+	dev_err(dev, "no platform data available\n");
+	return ERR_PTR(-EINVAL);
+}
+#endif
 
 /**
  * bu21013_probe() - initializes the i2c-client touchscreen driver
@@ -429,13 +495,13 @@ static void bu21013_free_irq(struct bu21013_ts_data *bu21013_data)
  * This function used to initializes the i2c-client touchscreen
  * driver and returns integer.
  */
-static int __devinit bu21013_probe(struct i2c_client *client,
-					const struct i2c_device_id *id)
+static int bu21013_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
 {
+	const struct bu21013_platform_device *pdata =
+					dev_get_platdata(&client->dev);
 	struct bu21013_ts_data *bu21013_data;
 	struct input_dev *in_dev;
-	const struct bu21013_platform_device *pdata =
-					client->dev.platform_data;
 	int error;
 
 	if (!i2c_check_functionality(client->adapter,
@@ -445,7 +511,13 @@ static int __devinit bu21013_probe(struct i2c_client *client,
 	}
 
 	if (!pdata) {
-		dev_err(&client->dev, "platform data not defined\n");
+		pdata = bu21013_parse_dt(&client->dev);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+	}
+
+	if (!gpio_is_valid(pdata->touch_pin)) {
+		dev_err(&client->dev, "invalid touch_pin supplied\n");
 		return -EINVAL;
 	}
 
@@ -460,8 +532,9 @@ static int __devinit bu21013_probe(struct i2c_client *client,
 	bu21013_data->in_dev = in_dev;
 	bu21013_data->chip = pdata;
 	bu21013_data->client = client;
+	bu21013_data->irq = gpio_to_irq(pdata->touch_pin);
 
-	bu21013_data->regulator = regulator_get(&client->dev, "V-TOUCH");
+	bu21013_data->regulator = regulator_get(&client->dev, "avdd");
 	if (IS_ERR(bu21013_data->regulator)) {
 		dev_err(&client->dev, "regulator_get failed\n");
 		error = PTR_ERR(bu21013_data->regulator);
@@ -478,12 +551,11 @@ static int __devinit bu21013_probe(struct i2c_client *client,
 	init_waitqueue_head(&bu21013_data->wait);
 
 	/* configure the gpio pins */
-	if (pdata->cs_en) {
-		error = pdata->cs_en(pdata->cs_pin);
-		if (error < 0) {
-			dev_err(&client->dev, "chip init failed\n");
-			goto err_disable_regulator;
-		}
+	error = gpio_request_one(pdata->cs_pin, GPIOF_OUT_INIT_HIGH,
+				 "touchp_reset");
+	if (error < 0) {
+		dev_err(&client->dev, "Unable to request gpio reset_pin\n");
+		goto err_disable_regulator;
 	}
 
 	/* configure the touch panel controller */
@@ -508,12 +580,13 @@ static int __devinit bu21013_probe(struct i2c_client *client,
 						pdata->touch_y_max, 0, 0);
 	input_set_drvdata(in_dev, bu21013_data);
 
-	error = request_threaded_irq(pdata->irq, NULL, bu21013_gpio_irq,
+	error = request_threaded_irq(bu21013_data->irq, NULL, bu21013_gpio_irq,
 				     IRQF_TRIGGER_FALLING | IRQF_SHARED |
 					IRQF_ONESHOT,
 				     DRIVER_TP, bu21013_data);
 	if (error) {
-		dev_err(&client->dev, "request irq %d failed\n", pdata->irq);
+		dev_err(&client->dev, "request irq %d failed\n",
+			bu21013_data->irq);
 		goto err_cs_disable;
 	}
 
@@ -531,7 +604,7 @@ static int __devinit bu21013_probe(struct i2c_client *client,
 err_free_irq:
 	bu21013_free_irq(bu21013_data);
 err_cs_disable:
-	pdata->cs_dis(pdata->cs_pin);
+	bu21013_cs_disable(bu21013_data);
 err_disable_regulator:
 	regulator_disable(bu21013_data->regulator);
 err_put_regulator:
@@ -549,13 +622,13 @@ err_free_mem:
  * This function uses to remove the i2c-client
  * touchscreen driver and returns integer.
  */
-static int __devexit bu21013_remove(struct i2c_client *client)
+static int bu21013_remove(struct i2c_client *client)
 {
 	struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client);
 
 	bu21013_free_irq(bu21013_data);
 
-	bu21013_data->chip->cs_dis(bu21013_data->chip->cs_pin);
+	bu21013_cs_disable(bu21013_data);
 
 	input_unregister_device(bu21013_data->in_dev);
 
@@ -584,9 +657,9 @@ static int bu21013_suspend(struct device *dev)
 
 	bu21013_data->touch_stopped = true;
 	if (device_may_wakeup(&client->dev))
-		enable_irq_wake(bu21013_data->chip->irq);
+		enable_irq_wake(bu21013_data->irq);
 	else
-		disable_irq(bu21013_data->chip->irq);
+		disable_irq(bu21013_data->irq);
 
 	regulator_disable(bu21013_data->regulator);
 
@@ -621,9 +694,9 @@ static int bu21013_resume(struct device *dev)
 	bu21013_data->touch_stopped = false;
 
 	if (device_may_wakeup(&client->dev))
-		disable_irq_wake(bu21013_data->chip->irq);
+		disable_irq_wake(bu21013_data->irq);
 	else
-		enable_irq(bu21013_data->chip->irq);
+		enable_irq(bu21013_data->irq);
 
 	return 0;
 }
@@ -649,7 +722,7 @@ static struct i2c_driver bu21013_driver = {
 #endif
 	},
 	.probe		=	bu21013_probe,
-	.remove		=	__devexit_p(bu21013_remove),
+	.remove		=	bu21013_remove,
 	.id_table	=	bu21013_id,
 };
 
diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c
index 464f1bf..96e0eedc 100644
--- a/drivers/input/touchscreen/cy8ctmg110_ts.c
+++ b/drivers/input/touchscreen/cy8ctmg110_ts.c
@@ -99,9 +99,18 @@ static int cy8ctmg110_read_regs(struct cy8ctmg110 *tsc,
 	int ret;
 	struct i2c_msg msg[2] = {
 		/* first write slave position to i2c devices */
-		{ client->addr, 0, 1, &cmd },
+		{
+			.addr = client->addr,
+			.len = 1,
+			.buf = &cmd
+		},
 		/* Second read data from position */
-		{ client->addr, I2C_M_RD, len, data }
+		{
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = len,
+			.buf = data
+		}
 	};
 
 	ret = i2c_transfer(client->adapter, msg, 2);
@@ -166,7 +175,7 @@ static irqreturn_t cy8ctmg110_irq_thread(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit cy8ctmg110_probe(struct i2c_client *client,
+static int cy8ctmg110_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	const struct cy8ctmg110_pdata *pdata = client->dev.platform_data;
@@ -314,7 +323,7 @@ static int cy8ctmg110_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume);
 #endif
 
-static int __devexit cy8ctmg110_remove(struct i2c_client *client)
+static int cy8ctmg110_remove(struct i2c_client *client)
 {
 	struct cy8ctmg110 *ts = i2c_get_clientdata(client);
 
@@ -348,7 +357,7 @@ static struct i2c_driver cy8ctmg110_driver = {
 	},
 	.id_table	= cy8ctmg110_idtable,
 	.probe		= cy8ctmg110_probe,
-	.remove		= __devexit_p(cy8ctmg110_remove),
+	.remove		= cy8ctmg110_remove,
 };
 
 module_i2c_driver(cy8ctmg110_driver);
diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c
index 2af1d0c..4dbdf44 100644
--- a/drivers/input/touchscreen/cyttsp_i2c.c
+++ b/drivers/input/touchscreen/cyttsp_i2c.c
@@ -81,7 +81,7 @@ static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = {
 	.read           = cyttsp_i2c_read_block_data,
 };
 
-static int __devinit cyttsp_i2c_probe(struct i2c_client *client,
+static int cyttsp_i2c_probe(struct i2c_client *client,
 				      const struct i2c_device_id *id)
 {
 	struct cyttsp *ts;
@@ -102,7 +102,7 @@ static int __devinit cyttsp_i2c_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int __devexit cyttsp_i2c_remove(struct i2c_client *client)
+static int cyttsp_i2c_remove(struct i2c_client *client)
 {
 	struct cyttsp *ts = i2c_get_clientdata(client);
 
@@ -124,7 +124,7 @@ static struct i2c_driver cyttsp_i2c_driver = {
 		.pm	= &cyttsp_pm_ops,
 	},
 	.probe		= cyttsp_i2c_probe,
-	.remove		= __devexit_p(cyttsp_i2c_remove),
+	.remove		= cyttsp_i2c_remove,
 	.id_table	= cyttsp_i2c_id,
 };
 
diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c
index 9f26341..638e203 100644
--- a/drivers/input/touchscreen/cyttsp_spi.c
+++ b/drivers/input/touchscreen/cyttsp_spi.c
@@ -147,7 +147,7 @@ static const struct cyttsp_bus_ops cyttsp_spi_bus_ops = {
 	.read		= cyttsp_spi_read_block_data,
 };
 
-static int __devinit cyttsp_spi_probe(struct spi_device *spi)
+static int cyttsp_spi_probe(struct spi_device *spi)
 {
 	struct cyttsp *ts;
 	int error;
@@ -172,7 +172,7 @@ static int __devinit cyttsp_spi_probe(struct spi_device *spi)
 	return 0;
 }
 
-static int __devexit cyttsp_spi_remove(struct spi_device *spi)
+static int cyttsp_spi_remove(struct spi_device *spi)
 {
 	struct cyttsp *ts = spi_get_drvdata(spi);
 
@@ -188,7 +188,7 @@ static struct spi_driver cyttsp_spi_driver = {
 		.pm	= &cyttsp_pm_ops,
 	},
 	.probe  = cyttsp_spi_probe,
-	.remove = __devexit_p(cyttsp_spi_remove),
+	.remove = cyttsp_spi_remove,
 };
 
 module_spi_driver(cyttsp_spi_driver);
diff --git a/drivers/input/touchscreen/da9034-ts.c b/drivers/input/touchscreen/da9034-ts.c
index 36b65cf..34ad841 100644
--- a/drivers/input/touchscreen/da9034-ts.c
+++ b/drivers/input/touchscreen/da9034-ts.c
@@ -297,7 +297,7 @@ static void da9034_touch_close(struct input_dev *dev)
 }
 
 
-static int __devinit da9034_touch_probe(struct platform_device *pdev)
+static int da9034_touch_probe(struct platform_device *pdev)
 {
 	struct da9034_touch_pdata *pdata = pdev->dev.platform_data;
 	struct da9034_touch *touch;
@@ -361,7 +361,7 @@ err_free_touch:
 	return ret;
 }
 
-static int __devexit da9034_touch_remove(struct platform_device *pdev)
+static int da9034_touch_remove(struct platform_device *pdev)
 {
 	struct da9034_touch *touch = platform_get_drvdata(pdev);
 
@@ -377,7 +377,7 @@ static struct platform_driver da9034_touch_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= da9034_touch_probe,
-	.remove		= __devexit_p(da9034_touch_remove),
+	.remove		= da9034_touch_remove,
 };
 module_platform_driver(da9034_touch_driver);
 
diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c
index e8df341..8f561e2 100644
--- a/drivers/input/touchscreen/da9052_tsi.c
+++ b/drivers/input/touchscreen/da9052_tsi.c
@@ -27,8 +27,6 @@ struct da9052_tsi {
 	struct input_dev *dev;
 	struct delayed_work ts_pen_work;
 	struct mutex mutex;
-	unsigned int irq_pendwn;
-	unsigned int irq_datardy;
 	bool stopped;
 	bool adc_on;
 };
@@ -45,8 +43,8 @@ static irqreturn_t da9052_ts_pendwn_irq(int irq, void *data)
 
 	if (!tsi->stopped) {
 		/* Mask PEN_DOWN event and unmask TSI_READY event */
-		disable_irq_nosync(tsi->irq_pendwn);
-		enable_irq(tsi->irq_datardy);
+		da9052_disable_irq_nosync(tsi->da9052, DA9052_IRQ_PENDOWN);
+		da9052_enable_irq(tsi->da9052, DA9052_IRQ_TSIREADY);
 
 		da9052_ts_adc_toggle(tsi, true);
 
@@ -137,13 +135,13 @@ static void da9052_ts_pen_work(struct work_struct *work)
 				return;
 
 			/* Mask TSI_READY event and unmask PEN_DOWN event */
-			disable_irq(tsi->irq_datardy);
-			enable_irq(tsi->irq_pendwn);
+			da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY);
+			da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN);
 		}
 	}
 }
 
-static int __devinit da9052_ts_configure_gpio(struct da9052 *da9052)
+static int da9052_ts_configure_gpio(struct da9052 *da9052)
 {
 	int error;
 
@@ -162,7 +160,7 @@ static int __devinit da9052_ts_configure_gpio(struct da9052 *da9052)
 	return 0;
 }
 
-static int __devinit da9052_configure_tsi(struct da9052_tsi *tsi)
+static int da9052_configure_tsi(struct da9052_tsi *tsi)
 {
 	int error;
 
@@ -197,7 +195,7 @@ static int da9052_ts_input_open(struct input_dev *input_dev)
 	mb();
 
 	/* Unmask PEN_DOWN event */
-	enable_irq(tsi->irq_pendwn);
+	da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN);
 
 	/* Enable Pen Detect Circuit */
 	return da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG,
@@ -210,11 +208,11 @@ static void da9052_ts_input_close(struct input_dev *input_dev)
 
 	tsi->stopped = true;
 	mb();
-	disable_irq(tsi->irq_pendwn);
+	da9052_disable_irq(tsi->da9052, DA9052_IRQ_PENDOWN);
 	cancel_delayed_work_sync(&tsi->ts_pen_work);
 
 	if (tsi->adc_on) {
-		disable_irq(tsi->irq_datardy);
+		da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY);
 		da9052_ts_adc_toggle(tsi, false);
 
 		/*
@@ -222,33 +220,24 @@ static void da9052_ts_input_close(struct input_dev *input_dev)
 		 * twice and we need to enable it to keep enable/disable
 		 * counter balanced. IRQ is still off though.
 		 */
-		enable_irq(tsi->irq_pendwn);
+		da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN);
 	}
 
 	/* Disable Pen Detect Circuit */
 	da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 1 << 1, 0);
 }
 
-static int __devinit da9052_ts_probe(struct platform_device *pdev)
+static int da9052_ts_probe(struct platform_device *pdev)
 {
 	struct da9052 *da9052;
 	struct da9052_tsi *tsi;
 	struct input_dev *input_dev;
-	int irq_pendwn;
-	int irq_datardy;
 	int error;
 
 	da9052 = dev_get_drvdata(pdev->dev.parent);
 	if (!da9052)
 		return -EINVAL;
 
-	irq_pendwn = platform_get_irq_byname(pdev, "PENDWN");
-	irq_datardy = platform_get_irq_byname(pdev, "TSIRDY");
-	if (irq_pendwn < 0 || irq_datardy < 0) {
-		dev_err(da9052->dev, "Unable to determine device interrupts\n");
-		return -ENXIO;
-	}
-
 	tsi = kzalloc(sizeof(struct da9052_tsi), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!tsi || !input_dev) {
@@ -258,8 +247,6 @@ static int __devinit da9052_ts_probe(struct platform_device *pdev)
 
 	tsi->da9052 = da9052;
 	tsi->dev = input_dev;
-	tsi->irq_pendwn = da9052->irq_base + irq_pendwn;
-	tsi->irq_datardy = da9052->irq_base + irq_datardy;
 	tsi->stopped = true;
 	INIT_DELAYED_WORK(&tsi->ts_pen_work, da9052_ts_pen_work);
 
@@ -287,31 +274,25 @@ static int __devinit da9052_ts_probe(struct platform_device *pdev)
 	/* Disable ADC */
 	da9052_ts_adc_toggle(tsi, false);
 
-	error = request_threaded_irq(tsi->irq_pendwn,
-				     NULL, da9052_ts_pendwn_irq,
-				     IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-				     "PENDWN", tsi);
+	error = da9052_request_irq(tsi->da9052, DA9052_IRQ_PENDOWN,
+				"pendown-irq", da9052_ts_pendwn_irq, tsi);
 	if (error) {
 		dev_err(tsi->da9052->dev,
-			"Failed to register PENDWN IRQ %d, error = %d\n",
-			tsi->irq_pendwn, error);
+			"Failed to register PENDWN IRQ: %d\n", error);
 		goto err_free_mem;
 	}
 
-	error = request_threaded_irq(tsi->irq_datardy,
-				     NULL, da9052_ts_datardy_irq,
-				     IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-				     "TSIRDY", tsi);
+	error = da9052_request_irq(tsi->da9052, DA9052_IRQ_TSIREADY,
+				"tsiready-irq", da9052_ts_datardy_irq, tsi);
 	if (error) {
 		dev_err(tsi->da9052->dev,
-			"Failed to register TSIRDY IRQ %d, error = %d\n",
-			tsi->irq_datardy, error);
+			"Failed to register TSIRDY IRQ :%d\n", error);
 		goto err_free_pendwn_irq;
 	}
 
 	/* Mask PEN_DOWN and TSI_READY events */
-	disable_irq(tsi->irq_pendwn);
-	disable_irq(tsi->irq_datardy);
+	da9052_disable_irq(tsi->da9052, DA9052_IRQ_PENDOWN);
+	da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY);
 
 	error = da9052_configure_tsi(tsi);
 	if (error)
@@ -326,9 +307,9 @@ static int __devinit da9052_ts_probe(struct platform_device *pdev)
 	return 0;
 
 err_free_datardy_irq:
-	free_irq(tsi->irq_datardy, tsi);
+	da9052_free_irq(tsi->da9052, DA9052_IRQ_TSIREADY, tsi);
 err_free_pendwn_irq:
-	free_irq(tsi->irq_pendwn, tsi);
+	da9052_free_irq(tsi->da9052, DA9052_IRQ_PENDOWN, tsi);
 err_free_mem:
 	kfree(tsi);
 	input_free_device(input_dev);
@@ -336,14 +317,14 @@ err_free_mem:
 	return error;
 }
 
-static int  __devexit da9052_ts_remove(struct platform_device *pdev)
+static int  da9052_ts_remove(struct platform_device *pdev)
 {
 	struct da9052_tsi *tsi = platform_get_drvdata(pdev);
 
 	da9052_reg_write(tsi->da9052, DA9052_LDO9_REG, 0x19);
 
-	free_irq(tsi->irq_pendwn, tsi);
-	free_irq(tsi->irq_datardy, tsi);
+	da9052_free_irq(tsi->da9052, DA9052_IRQ_TSIREADY, tsi);
+	da9052_free_irq(tsi->da9052, DA9052_IRQ_PENDOWN, tsi);
 
 	input_unregister_device(tsi->dev);
 	kfree(tsi);
@@ -355,7 +336,7 @@ static int  __devexit da9052_ts_remove(struct platform_device *pdev)
 
 static struct platform_driver da9052_tsi_driver = {
 	.probe	= da9052_ts_probe,
-	.remove	= __devexit_p(da9052_ts_remove),
+	.remove	= da9052_ts_remove,
 	.driver	= {
 		.name	= "da9052-tsi",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 099d144..a917015 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -491,14 +491,6 @@ static int edt_ft5x06_debugfs_mode_set(void *data, u64 mode)
 DEFINE_SIMPLE_ATTRIBUTE(debugfs_mode_fops, edt_ft5x06_debugfs_mode_get,
 			edt_ft5x06_debugfs_mode_set, "%llu\n");
 
-static int edt_ft5x06_debugfs_raw_data_open(struct inode *inode,
-					    struct file *file)
-{
-	file->private_data = inode->i_private;
-
-	return 0;
-}
-
 static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
 				char __user *buf, size_t count, loff_t *off)
 {
@@ -579,11 +571,11 @@ out:
 
 
 static const struct file_operations debugfs_raw_data_fops = {
-	.open = edt_ft5x06_debugfs_raw_data_open,
+	.open = simple_open,
 	.read = edt_ft5x06_debugfs_raw_data_read,
 };
 
-static void __devinit
+static void
 edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
 			      const char *debugfs_name)
 {
@@ -600,7 +592,7 @@ edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
 			    tsdata->debug_dir, tsdata, &debugfs_raw_data_fops);
 }
 
-static void __devexit
+static void
 edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
 {
 	if (tsdata->debug_dir)
@@ -625,7 +617,7 @@ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
 
 
 
-static int __devinit edt_ft5x06_ts_reset(struct i2c_client *client,
+static int edt_ft5x06_ts_reset(struct i2c_client *client,
 					 int reset_pin)
 {
 	int error;
@@ -649,7 +641,7 @@ static int __devinit edt_ft5x06_ts_reset(struct i2c_client *client,
 	return 0;
 }
 
-static int __devinit edt_ft5x06_ts_identify(struct i2c_client *client,
+static int edt_ft5x06_ts_identify(struct i2c_client *client,
 					    char *model_name,
 					    char *fw_version)
 {
@@ -683,7 +675,7 @@ static int __devinit edt_ft5x06_ts_identify(struct i2c_client *client,
 	    pdata->name <= edt_ft5x06_attr_##name.limit_high)		\
 		edt_ft5x06_register_write(tsdata, reg, pdata->name)
 
-static void __devinit
+static void
 edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata,
 			   const struct edt_ft5x06_platform_data *pdata)
 {
@@ -697,7 +689,7 @@ edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata,
 	EDT_ATTR_CHECKSET(report_rate, WORK_REGISTER_REPORT_RATE);
 }
 
-static void __devinit
+static void
 edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
 {
 	tsdata->threshold = edt_ft5x06_register_read(tsdata,
@@ -710,7 +702,7 @@ edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
 	tsdata->num_y = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_Y);
 }
 
-static int __devinit edt_ft5x06_ts_probe(struct i2c_client *client,
+static int edt_ft5x06_ts_probe(struct i2c_client *client,
 					 const struct i2c_device_id *id)
 {
 	const struct edt_ft5x06_platform_data *pdata =
@@ -830,7 +822,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit edt_ft5x06_ts_remove(struct i2c_client *client)
+static int edt_ft5x06_ts_remove(struct i2c_client *client)
 {
 	const struct edt_ft5x06_platform_data *pdata =
 						dev_get_platdata(&client->dev);
@@ -891,7 +883,7 @@ static struct i2c_driver edt_ft5x06_ts_driver = {
 	},
 	.id_table = edt_ft5x06_ts_id,
 	.probe    = edt_ft5x06_ts_probe,
-	.remove   = __devexit_p(edt_ft5x06_ts_remove),
+	.remove   = edt_ft5x06_ts_remove,
 };
 
 module_i2c_driver(edt_ft5x06_ts_driver);
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
index 908407e..55255a9 100644
--- a/drivers/input/touchscreen/eeti_ts.c
+++ b/drivers/input/touchscreen/eeti_ts.c
@@ -154,7 +154,7 @@ static void eeti_ts_close(struct input_dev *dev)
 	eeti_ts_stop(priv);
 }
 
-static int __devinit eeti_ts_probe(struct i2c_client *client,
+static int eeti_ts_probe(struct i2c_client *client,
 				   const struct i2c_device_id *idp)
 {
 	struct eeti_ts_platform_data *pdata = client->dev.platform_data;
@@ -248,7 +248,7 @@ err0:
 	return err;
 }
 
-static int __devexit eeti_ts_remove(struct i2c_client *client)
+static int eeti_ts_remove(struct i2c_client *client)
 {
 	struct eeti_ts_priv *priv = i2c_get_clientdata(client);
 
@@ -321,7 +321,7 @@ static struct i2c_driver eeti_ts_driver = {
 #endif
 	},
 	.probe = eeti_ts_probe,
-	.remove = __devexit_p(eeti_ts_remove),
+	.remove = eeti_ts_remove,
 	.id_table = eeti_ts_id,
 };
 
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
index 13fa62f..17c9097 100644
--- a/drivers/input/touchscreen/egalax_ts.c
+++ b/drivers/input/touchscreen/egalax_ts.c
@@ -153,7 +153,7 @@ static int egalax_wake_up_device(struct i2c_client *client)
 	return 0;
 }
 
-static int __devinit egalax_firmware_version(struct i2c_client *client)
+static int egalax_firmware_version(struct i2c_client *client)
 {
 	static const u8 cmd[MAX_I2C_DATA_LEN] = { 0x03, 0x03, 0xa, 0x01, 0x41 };
 	int ret;
@@ -165,7 +165,7 @@ static int __devinit egalax_firmware_version(struct i2c_client *client)
 	return 0;
 }
 
-static int __devinit egalax_ts_probe(struct i2c_client *client,
+static int egalax_ts_probe(struct i2c_client *client,
 				       const struct i2c_device_id *id)
 {
 	struct egalax_ts *ts;
@@ -246,7 +246,7 @@ err_free_ts:
 	return error;
 }
 
-static __devexit int egalax_ts_remove(struct i2c_client *client)
+static int egalax_ts_remove(struct i2c_client *client)
 {
 	struct egalax_ts *ts = i2c_get_clientdata(client);
 
@@ -301,7 +301,7 @@ static struct i2c_driver egalax_ts_driver = {
 	},
 	.id_table	= egalax_ts_id,
 	.probe		= egalax_ts_probe,
-	.remove		= __devexit_p(egalax_ts_remove),
+	.remove		= egalax_ts_remove,
 };
 
 module_i2c_driver(egalax_ts_driver);
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
deleted file mode 100644
index b9e8686..0000000
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ /dev/null
@@ -1,479 +0,0 @@
-/*
- *  Copyright (c) 2001 "Crazy" James Simmons jsimmons@transvirtual.com
- *
- *  Sponsored by Transvirtual Technology.
- *
- *  Derived from the code in h3600_ts.[ch] by Charles Flynn
- */
-
-/*
- * Driver for the h3600 Touch Screen and other Atmel controlled devices.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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
- *
- * Should you need to contact me, the author, you can do so by
- * e-mail - mail your message to <jsimmons@transvirtual.com>.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/serio.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-
-/* SA1100 serial defines */
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-
-#define DRIVER_DESC	"H3600 touchscreen driver"
-
-MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>");
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
-/*
- * Definitions & global arrays.
- */
-
-/* The start and end of frame characters SOF and EOF */
-#define CHAR_SOF                0x02
-#define CHAR_EOF                0x03
-#define FRAME_OVERHEAD          3       /* CHAR_SOF,CHAR_EOF,LENGTH = 3 */
-
-/*
-        Atmel events and response IDs contained in frame.
-        Programmer has no control over these numbers.
-        TODO there are holes - specifically  1,7,0x0a
-*/
-#define VERSION_ID              0       /* Get Version (request/response) */
-#define KEYBD_ID                2       /* Keyboard (event) */
-#define TOUCHS_ID               3       /* Touch Screen (event)*/
-#define EEPROM_READ_ID          4       /* (request/response) */
-#define EEPROM_WRITE_ID         5       /* (request/response) */
-#define THERMAL_ID              6       /* (request/response) */
-#define NOTIFY_LED_ID           8       /* (request/response) */
-#define BATTERY_ID              9       /* (request/response) */
-#define SPI_READ_ID             0x0b    /* ( request/response) */
-#define SPI_WRITE_ID            0x0c    /* ( request/response) */
-#define FLITE_ID                0x0d    /* backlight ( request/response) */
-#define STX_ID                  0xa1    /* extension pack status (req/resp) */
-
-#define MAX_ID                  14
-
-#define H3600_MAX_LENGTH 16
-#define H3600_KEY 0xf
-
-#define H3600_SCANCODE_RECORD	1	 /* 1 -> record button */
-#define H3600_SCANCODE_CALENDAR 2	 /* 2 -> calendar */
-#define H3600_SCANCODE_CONTACTS 3	 /* 3 -> contact */
-#define H3600_SCANCODE_Q	4	 /* 4 -> Q button */
-#define	H3600_SCANCODE_START	5	 /* 5 -> start menu */
-#define	H3600_SCANCODE_UP	6	 /* 6 -> up */
-#define H3600_SCANCODE_RIGHT	7	 /* 7 -> right */
-#define H3600_SCANCODE_LEFT	8	 /* 8 -> left */
-#define H3600_SCANCODE_DOWN	9	 /* 9 -> down */
-
-/*
- * Per-touchscreen data.
- */
-struct h3600_dev {
-	struct input_dev *dev;
-	struct serio *serio;
-	unsigned char event;	/* event ID from packet */
-	unsigned char chksum;
-	unsigned char len;
-	unsigned char idx;
-	unsigned char buf[H3600_MAX_LENGTH];
-	char phys[32];
-};
-
-static irqreturn_t action_button_handler(int irq, void *dev_id)
-{
-	int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1;
-	struct input_dev *dev = dev_id;
-
-	input_report_key(dev, KEY_ENTER, down);
-	input_sync(dev);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t npower_button_handler(int irq, void *dev_id)
-{
-	int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1;
-	struct input_dev *dev = dev_id;
-
-	/*
-	 * This interrupt is only called when we release the key. So we have
-	 * to fake a key press.
-	 */
-	input_report_key(dev, KEY_SUSPEND, 1);
-	input_report_key(dev, KEY_SUSPEND, down);
-	input_sync(dev);
-
-	return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_PM
-
-static int flite_brightness = 25;
-
-enum flite_pwr {
-	FLITE_PWR_OFF = 0,
-	FLITE_PWR_ON = 1
-};
-
-/*
- * h3600_flite_power: enables or disables power to frontlight, using last bright */
-unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr)
-{
-	unsigned char brightness = (pwr == FLITE_PWR_OFF) ? 0 : flite_brightness;
-	struct h3600_dev *ts = input_get_drvdata(dev);
-
-	/* Must be in this order */
-	serio_write(ts->serio, 1);
-	serio_write(ts->serio, pwr);
-	serio_write(ts->serio, brightness);
-
-	return 0;
-}
-
-#endif
-
-/*
- * This function translates the native event packets to linux input event
- * packets. Some packets coming from serial are not touchscreen related. In
- * this case we send them off to be processed elsewhere.
- */
-static void h3600ts_process_packet(struct h3600_dev *ts)
-{
-	struct input_dev *dev = ts->dev;
-	static int touched = 0;
-	int key, down = 0;
-
-	switch (ts->event) {
-		/*
-		   Buttons - returned as a single byte
-			7 6 5 4 3 2 1 0
-			S x x x N N N N
-
-		   S       switch state ( 0=pressed 1=released)
-		   x       Unused.
-		   NNNN    switch number 0-15
-
-		   Note: This is true for non interrupt generated key events.
-		*/
-		case KEYBD_ID:
-			down = (ts->buf[0] & 0x80) ? 0 : 1;
-
-			switch (ts->buf[0] & 0x7f) {
-				case H3600_SCANCODE_RECORD:
-					key = KEY_RECORD;
-					break;
-				case H3600_SCANCODE_CALENDAR:
-					key = KEY_PROG1;
-                                        break;
-				case H3600_SCANCODE_CONTACTS:
-					key = KEY_PROG2;
-					break;
-				case H3600_SCANCODE_Q:
-					key = KEY_Q;
-					break;
-				case H3600_SCANCODE_START:
-					key = KEY_PROG3;
-					break;
-				case H3600_SCANCODE_UP:
-					key = KEY_UP;
-					break;
-				case H3600_SCANCODE_RIGHT:
-					key = KEY_RIGHT;
-					break;
-				case H3600_SCANCODE_LEFT:
-					key = KEY_LEFT;
-					break;
-				case H3600_SCANCODE_DOWN:
-					key = KEY_DOWN;
-					break;
-				default:
-					key = 0;
-			}
-			if (key)
-				input_report_key(dev, key, down);
-			break;
-		/*
-		 * Native touchscreen event data is formatted as shown below:-
-		 *
-		 *      +-------+-------+-------+-------+
-		 *      | Xmsb  | Xlsb  | Ymsb  | Ylsb  |
-		 *      +-------+-------+-------+-------+
-		 *       byte 0    1       2       3
-		 */
-		case TOUCHS_ID:
-			if (!touched) {
-				input_report_key(dev, BTN_TOUCH, 1);
-				touched = 1;
-			}
-
-			if (ts->len) {
-				unsigned short x, y;
-
-				x = ts->buf[0]; x <<= 8; x += ts->buf[1];
-				y = ts->buf[2]; y <<= 8; y += ts->buf[3];
-
-				input_report_abs(dev, ABS_X, x);
-				input_report_abs(dev, ABS_Y, y);
-			} else {
-				input_report_key(dev, BTN_TOUCH, 0);
-				touched = 0;
-			}
-			break;
-		default:
-			/* Send a non input event elsewhere */
-			break;
-	}
-
-	input_sync(dev);
-}
-
-/*
- * h3600ts_event() handles events from the input module.
- */
-static int h3600ts_event(struct input_dev *dev, unsigned int type,
-			 unsigned int code, int value)
-{
-#if 0
-	struct h3600_dev *ts = input_get_drvdata(dev);
-
-	switch (type) {
-		case EV_LED: {
-		//	serio_write(ts->serio, SOME_CMD);
-			return 0;
-		}
-	}
-	return -1;
-#endif
-	return 0;
-}
-
-/*
-        Frame format
-  byte    1       2               3              len + 4
-        +-------+---------------+---------------+--=------------+
-        |SOF    |id     |len    | len bytes     | Chksum        |
-        +-------+---------------+---------------+--=------------+
-  bit   0     7  8    11 12   15 16
-
-        +-------+---------------+-------+
-        |SOF    |id     |0      |Chksum | - Note Chksum does not include SOF
-        +-------+---------------+-------+
-  bit   0     7  8    11 12   15 16
-
-*/
-
-static int state;
-
-/* decode States  */
-#define STATE_SOF       0       /* start of FRAME */
-#define STATE_ID        1       /* state where we decode the ID & len */
-#define STATE_DATA      2       /* state where we decode data */
-#define STATE_EOF       3       /* state where we decode checksum or EOF */
-
-static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data,
-                                     unsigned int flags)
-{
-	struct h3600_dev *ts = serio_get_drvdata(serio);
-
-	/*
-	 * We have a new frame coming in.
-	 */
-	switch (state) {
-		case STATE_SOF:
-			if (data == CHAR_SOF)
-				state = STATE_ID;
-			break;
-		case STATE_ID:
-			ts->event = (data & 0xf0) >> 4;
-			ts->len = (data & 0xf);
-			ts->idx = 0;
-			if (ts->event >= MAX_ID) {
-				state = STATE_SOF;
-				break;
-			}
-			ts->chksum = data;
-			state = (ts->len > 0) ? STATE_DATA : STATE_EOF;
-			break;
-		case STATE_DATA:
-			ts->chksum += data;
-			ts->buf[ts->idx]= data;
-			if (++ts->idx == ts->len)
-				state = STATE_EOF;
-			break;
-		case STATE_EOF:
-			state = STATE_SOF;
-			if (data == CHAR_EOF || data == ts->chksum)
-				h3600ts_process_packet(ts);
-			break;
-		default:
-			printk("Error3\n");
-			break;
-	}
-
-	return IRQ_HANDLED;
-}
-
-/*
- * h3600ts_connect() is the routine that is called when someone adds a
- * new serio device that supports H3600 protocol and registers it as
- * an input device.
- */
-static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
-{
-	struct h3600_dev *ts;
-	struct input_dev *input_dev;
-	int err;
-
-	ts = kzalloc(sizeof(struct h3600_dev), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!ts || !input_dev) {
-		err = -ENOMEM;
-		goto fail1;
-	}
-
-	ts->serio = serio;
-	ts->dev = input_dev;
-	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", serio->phys);
-
-	input_dev->name = "H3600 TouchScreen";
-	input_dev->phys = ts->phys;
-	input_dev->id.bustype = BUS_RS232;
-	input_dev->id.vendor = SERIO_H3600;
-	input_dev->id.product = 0x0666;  /* FIXME !!! We can ask the hardware */
-	input_dev->id.version = 0x0100;
-	input_dev->dev.parent = &serio->dev;
-
-	input_set_drvdata(input_dev, ts);
-
-	input_dev->event = h3600ts_event;
-
-	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) |
-		BIT_MASK(EV_LED) | BIT_MASK(EV_PWR);
-	input_dev->ledbit[0] = BIT_MASK(LED_SLEEP);
-	input_set_abs_params(input_dev, ABS_X, 60, 985, 0, 0);
-	input_set_abs_params(input_dev, ABS_Y, 35, 1024, 0, 0);
-
-	set_bit(KEY_RECORD, input_dev->keybit);
-	set_bit(KEY_Q, input_dev->keybit);
-	set_bit(KEY_PROG1, input_dev->keybit);
-	set_bit(KEY_PROG2, input_dev->keybit);
-	set_bit(KEY_PROG3, input_dev->keybit);
-	set_bit(KEY_UP, input_dev->keybit);
-	set_bit(KEY_RIGHT, input_dev->keybit);
-	set_bit(KEY_LEFT, input_dev->keybit);
-	set_bit(KEY_DOWN, input_dev->keybit);
-	set_bit(KEY_ENTER, input_dev->keybit);
-	set_bit(KEY_SUSPEND, input_dev->keybit);
-	set_bit(BTN_TOUCH, input_dev->keybit);
-
-	/* Device specific stuff */
-	set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES);
-	set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE);
-
-	if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler,
-			IRQF_SHARED, "h3600_action", ts->dev)) {
-		printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
-		err = -EBUSY;
-		goto fail1;
-	}
-
-	if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
-			IRQF_SHARED, "h3600_suspend", ts->dev)) {
-		printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
-		err = -EBUSY;
-		goto fail2;
-	}
-
-	serio_set_drvdata(serio, ts);
-
-	err = serio_open(serio, drv);
-	if (err)
-		goto fail3;
-
-	//h3600_flite_control(1, 25);     /* default brightness */
-	err = input_register_device(ts->dev);
-	if (err)
-		goto fail4;
-
-	return 0;
-
-fail4:	serio_close(serio);
-fail3:	serio_set_drvdata(serio, NULL);
-	free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev);
-fail2:	free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev);
-fail1:	input_free_device(input_dev);
-	kfree(ts);
-	return err;
-}
-
-/*
- * h3600ts_disconnect() is the opposite of h3600ts_connect()
- */
-
-static void h3600ts_disconnect(struct serio *serio)
-{
-	struct h3600_dev *ts = serio_get_drvdata(serio);
-
-	free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev);
-	free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev);
-	input_get_device(ts->dev);
-	input_unregister_device(ts->dev);
-	serio_close(serio);
-	serio_set_drvdata(serio, NULL);
-	input_put_device(ts->dev);
-	kfree(ts);
-}
-
-/*
- * The serio driver structure.
- */
-
-static struct serio_device_id h3600ts_serio_ids[] = {
-	{
-		.type	= SERIO_RS232,
-		.proto	= SERIO_H3600,
-		.id	= SERIO_ANY,
-		.extra	= SERIO_ANY,
-	},
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(serio, h3600ts_serio_ids);
-
-static struct serio_driver h3600ts_drv = {
-	.driver		= {
-		.name	= "h3600ts",
-	},
-	.description	= DRIVER_DESC,
-	.id_table	= h3600ts_serio_ids,
-	.interrupt	= h3600ts_interrupt,
-	.connect	= h3600ts_connect,
-	.disconnect	= h3600ts_disconnect,
-};
-
-module_serio_driver(h3600ts_drv);
diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c
index d13143b..6c4fb84 100644
--- a/drivers/input/touchscreen/htcpen.c
+++ b/drivers/input/touchscreen/htcpen.c
@@ -102,7 +102,7 @@ static void htcpen_close(struct input_dev *dev)
 	synchronize_irq(HTCPEN_IRQ);
 }
 
-static int __devinit htcpen_isa_probe(struct device *dev, unsigned int id)
+static int htcpen_isa_probe(struct device *dev, unsigned int id)
 {
 	struct input_dev *htcpen_dev;
 	int err = -EBUSY;
@@ -174,7 +174,7 @@ static int __devinit htcpen_isa_probe(struct device *dev, unsigned int id)
 	return err;
 }
 
-static int __devexit htcpen_isa_remove(struct device *dev, unsigned int id)
+static int htcpen_isa_remove(struct device *dev, unsigned int id)
 {
 	struct input_dev *htcpen_dev = dev_get_drvdata(dev);
 
@@ -210,7 +210,7 @@ static int htcpen_isa_resume(struct device *dev, unsigned int n)
 
 static struct isa_driver htcpen_isa_driver = {
 	.probe		= htcpen_isa_probe,
-	.remove		= __devexit_p(htcpen_isa_remove),
+	.remove		= htcpen_isa_remove,
 #ifdef CONFIG_PM
 	.suspend	= htcpen_isa_suspend,
 	.resume		= htcpen_isa_resume,
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
index 4ac6976..1418bdd 100644
--- a/drivers/input/touchscreen/ili210x.c
+++ b/drivers/input/touchscreen/ili210x.c
@@ -180,7 +180,7 @@ static const struct attribute_group ili210x_attr_group = {
 	.attrs = ili210x_attributes,
 };
 
-static int __devinit ili210x_i2c_probe(struct i2c_client *client,
+static int ili210x_i2c_probe(struct i2c_client *client,
 				       const struct i2c_device_id *id)
 {
 	struct device *dev = &client->dev;
@@ -298,7 +298,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit ili210x_i2c_remove(struct i2c_client *client)
+static int ili210x_i2c_remove(struct i2c_client *client)
 {
 	struct ili210x *priv = i2c_get_clientdata(client);
 
@@ -350,7 +350,7 @@ static struct i2c_driver ili210x_ts_driver = {
 	},
 	.id_table = ili210x_i2c_id,
 	.probe = ili210x_i2c_probe,
-	.remove = __devexit_p(ili210x_i2c_remove),
+	.remove = ili210x_i2c_remove,
 };
 
 module_i2c_driver(ili210x_ts_driver);
diff --git a/drivers/input/touchscreen/intel-mid-touch.c b/drivers/input/touchscreen/intel-mid-touch.c
index cf29937..465db5d 100644
--- a/drivers/input/touchscreen/intel-mid-touch.c
+++ b/drivers/input/touchscreen/intel-mid-touch.c
@@ -427,7 +427,7 @@ out:
 }
 
 /* Utility to read PMIC ID */
-static int __devinit mrstouch_read_pmic_id(uint *vendor, uint *rev)
+static int mrstouch_read_pmic_id(uint *vendor, uint *rev)
 {
 	int err;
 	u8 r;
@@ -446,7 +446,7 @@ static int __devinit mrstouch_read_pmic_id(uint *vendor, uint *rev)
  * Parse ADC channels to find end of the channel configured by other ADC user
  * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels
  */
-static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev)
+static int mrstouch_chan_parse(struct mrstouch_dev *tsdev)
 {
 	int found = 0;
 	int err, i;
@@ -478,7 +478,7 @@ static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev)
 /*
  * Writes touch screen channels to ADC address selection registers
  */
-static int __devinit mrstouch_ts_chan_set(uint offset)
+static int mrstouch_ts_chan_set(uint offset)
 {
 	u16 chan;
 
@@ -494,7 +494,7 @@ static int __devinit mrstouch_ts_chan_set(uint offset)
 }
 
 /* Initialize ADC */
-static int __devinit mrstouch_adc_init(struct mrstouch_dev *tsdev)
+static int mrstouch_adc_init(struct mrstouch_dev *tsdev)
 {
 	int err, start;
 	u8 ra, rm;
@@ -568,7 +568,7 @@ static int __devinit mrstouch_adc_init(struct mrstouch_dev *tsdev)
 
 
 /* Probe function for touch screen driver */
-static int __devinit mrstouch_probe(struct platform_device *pdev)
+static int mrstouch_probe(struct platform_device *pdev)
 {
 	struct mrstouch_dev *tsdev;
 	struct input_dev *input;
@@ -643,7 +643,7 @@ err_free_mem:
 	return err;
 }
 
-static int __devexit mrstouch_remove(struct platform_device *pdev)
+static int mrstouch_remove(struct platform_device *pdev)
 {
 	struct mrstouch_dev *tsdev = platform_get_drvdata(pdev);
 
@@ -662,7 +662,7 @@ static struct platform_driver mrstouch_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= mrstouch_probe,
-	.remove		= __devexit_p(mrstouch_remove),
+	.remove		= mrstouch_remove,
 };
 module_platform_driver(mrstouch_driver);
 
diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c
index 7f03d1bd..282d7c7 100644
--- a/drivers/input/touchscreen/jornada720_ts.c
+++ b/drivers/input/touchscreen/jornada720_ts.c
@@ -99,7 +99,7 @@ static irqreturn_t jornada720_ts_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit jornada720_ts_probe(struct platform_device *pdev)
+static int jornada720_ts_probe(struct platform_device *pdev)
 {
 	struct jornada_ts *jornada_ts;
 	struct input_dev *input_dev;
@@ -151,7 +151,7 @@ static int __devinit jornada720_ts_probe(struct platform_device *pdev)
 	return error;
 }
 
-static int __devexit jornada720_ts_remove(struct platform_device *pdev)
+static int jornada720_ts_remove(struct platform_device *pdev)
 {
 	struct jornada_ts *jornada_ts = platform_get_drvdata(pdev);
 
@@ -168,7 +168,7 @@ MODULE_ALIAS("platform:jornada_ts");
 
 static struct platform_driver jornada720_ts_driver = {
 	.probe		= jornada720_ts_probe,
-	.remove		= __devexit_p(jornada720_ts_remove),
+	.remove		= jornada720_ts_remove,
 	.driver		= {
 		.name	= "jornada_ts",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c
index 4c2b8ed..9101ee5 100644
--- a/drivers/input/touchscreen/lpc32xx_ts.c
+++ b/drivers/input/touchscreen/lpc32xx_ts.c
@@ -203,7 +203,7 @@ static void lpc32xx_ts_close(struct input_dev *dev)
 	lpc32xx_stop_tsc(tsc);
 }
 
-static int __devinit lpc32xx_ts_probe(struct platform_device *pdev)
+static int lpc32xx_ts_probe(struct platform_device *pdev)
 {
 	struct lpc32xx_tsc *tsc;
 	struct input_dev *input;
@@ -309,7 +309,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit lpc32xx_ts_remove(struct platform_device *pdev)
+static int lpc32xx_ts_remove(struct platform_device *pdev)
 {
 	struct lpc32xx_tsc *tsc = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -394,7 +394,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_tsc_of_match);
 
 static struct platform_driver lpc32xx_ts_driver = {
 	.probe		= lpc32xx_ts_probe,
-	.remove		= __devexit_p(lpc32xx_ts_remove),
+	.remove		= lpc32xx_ts_remove,
 	.driver		= {
 		.name	= MOD_NAME,
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c
index 4eab50b..00bc6ca 100644
--- a/drivers/input/touchscreen/max11801_ts.c
+++ b/drivers/input/touchscreen/max11801_ts.c
@@ -156,7 +156,7 @@ out:
 	return IRQ_HANDLED;
 }
 
-static void __devinit max11801_ts_phy_init(struct max11801_data *data)
+static void max11801_ts_phy_init(struct max11801_data *data)
 {
 	struct i2c_client *client = data->client;
 
@@ -174,7 +174,7 @@ static void __devinit max11801_ts_phy_init(struct max11801_data *data)
 	max11801_write_reg(client, OP_MODE_CONF_REG, 0x36);
 }
 
-static int __devinit max11801_ts_probe(struct i2c_client *client,
+static int max11801_ts_probe(struct i2c_client *client,
 				       const struct i2c_device_id *id)
 {
 	struct max11801_data *data;
@@ -228,7 +228,7 @@ err_free_mem:
 	return error;
 }
 
-static __devexit int max11801_ts_remove(struct i2c_client *client)
+static int max11801_ts_remove(struct i2c_client *client)
 {
 	struct max11801_data *data = i2c_get_clientdata(client);
 
@@ -252,7 +252,7 @@ static struct i2c_driver max11801_ts_driver = {
 	},
 	.id_table	= max11801_ts_id,
 	.probe		= max11801_ts_probe,
-	.remove		= __devexit_p(max11801_ts_remove),
+	.remove		= max11801_ts_remove,
 };
 
 module_i2c_driver(max11801_ts_driver);
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
index 48dc5b0..02103b6 100644
--- a/drivers/input/touchscreen/mc13783_ts.c
+++ b/drivers/input/touchscreen/mc13783_ts.c
@@ -229,7 +229,7 @@ err_free_mem:
 	return ret;
 }
 
-static int __devexit mc13783_ts_remove(struct platform_device *pdev)
+static int mc13783_ts_remove(struct platform_device *pdev)
 {
 	struct mc13783_ts_priv *priv = platform_get_drvdata(pdev);
 
@@ -243,7 +243,7 @@ static int __devexit mc13783_ts_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver mc13783_ts_driver = {
-	.remove		= __devexit_p(mc13783_ts_remove),
+	.remove		= mc13783_ts_remove,
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= MC13783_TS_NAME,
diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c
index b528511..f9f4e0c 100644
--- a/drivers/input/touchscreen/mcs5000_ts.c
+++ b/drivers/input/touchscreen/mcs5000_ts.c
@@ -187,7 +187,7 @@ static void mcs5000_ts_phys_init(struct mcs5000_ts_data *data)
 			OP_MODE_ACTIVE | REPORT_RATE_80);
 }
 
-static int __devinit mcs5000_ts_probe(struct i2c_client *client,
+static int mcs5000_ts_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	struct mcs5000_ts_data *data;
@@ -249,7 +249,7 @@ err_free_mem:
 	return ret;
 }
 
-static int __devexit mcs5000_ts_remove(struct i2c_client *client)
+static int mcs5000_ts_remove(struct i2c_client *client)
 {
 	struct mcs5000_ts_data *data = i2c_get_clientdata(client);
 
@@ -292,7 +292,7 @@ MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id);
 
 static struct i2c_driver mcs5000_ts_driver = {
 	.probe		= mcs5000_ts_probe,
-	.remove		= __devexit_p(mcs5000_ts_remove),
+	.remove		= mcs5000_ts_remove,
 	.driver = {
 		.name = "mcs5000_ts",
 #ifdef CONFIG_PM
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index 560cf09..98841d8 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/of.h>
 #include <linux/i2c.h>
 #include <linux/i2c/mms114.h>
 #include <linux/input/mt.h>
@@ -360,14 +361,63 @@ static void mms114_input_close(struct input_dev *dev)
 	mms114_stop(data);
 }
 
-static int __devinit mms114_probe(struct i2c_client *client,
+#ifdef CONFIG_OF
+static struct mms114_platform_data *mms114_parse_dt(struct device *dev)
+{
+	struct mms114_platform_data *pdata;
+	struct device_node *np = dev->of_node;
+
+	if (!np)
+		return NULL;
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		dev_err(dev, "failed to allocate platform data\n");
+		return NULL;
+	}
+
+	if (of_property_read_u32(np, "x-size", &pdata->x_size)) {
+		dev_err(dev, "failed to get x-size property\n");
+		return NULL;
+	};
+
+	if (of_property_read_u32(np, "y-size", &pdata->y_size)) {
+		dev_err(dev, "failed to get y-size property\n");
+		return NULL;
+	};
+
+	of_property_read_u32(np, "contact-threshold",
+				&pdata->contact_threshold);
+	of_property_read_u32(np, "moving-threshold",
+				&pdata->moving_threshold);
+
+	if (of_find_property(np, "x-invert", NULL))
+		pdata->x_invert = true;
+	if (of_find_property(np, "y-invert", NULL))
+		pdata->y_invert = true;
+
+	return pdata;
+}
+#else
+static inline struct mms114_platform_data *mms114_parse_dt(struct device *dev)
+{
+	return NULL;
+}
+#endif
+
+static int mms114_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
+	const struct mms114_platform_data *pdata;
 	struct mms114_data *data;
 	struct input_dev *input_dev;
 	int error;
 
-	if (!client->dev.platform_data) {
+	pdata = dev_get_platdata(&client->dev);
+	if (!pdata)
+		pdata = mms114_parse_dt(&client->dev);
+
+	if (!pdata) {
 		dev_err(&client->dev, "Need platform data\n");
 		return -EINVAL;
 	}
@@ -389,7 +439,7 @@ static int __devinit mms114_probe(struct i2c_client *client,
 
 	data->client = client;
 	data->input_dev = input_dev;
-	data->pdata = client->dev.platform_data;
+	data->pdata = pdata;
 
 	input_dev->name = "MELPAS MMS114 Touchscreen";
 	input_dev->id.bustype = BUS_I2C;
@@ -458,7 +508,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit mms114_remove(struct i2c_client *client)
+static int mms114_remove(struct i2c_client *client)
 {
 	struct mms114_data *data = i2c_get_clientdata(client);
 
@@ -525,14 +575,22 @@ static const struct i2c_device_id mms114_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, mms114_id);
 
+#ifdef CONFIG_OF
+static struct of_device_id mms114_dt_match[] = {
+	{ .compatible = "melfas,mms114" },
+	{ }
+};
+#endif
+
 static struct i2c_driver mms114_driver = {
 	.driver = {
 		.name	= "mms114",
 		.owner	= THIS_MODULE,
 		.pm	= &mms114_pm_ops,
+		.of_match_table = of_match_ptr(mms114_dt_match),
 	},
 	.probe		= mms114_probe,
-	.remove		= __devexit_p(mms114_remove),
+	.remove		= mms114_remove,
 	.id_table	= mms114_id,
 };
 
diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c
index f57aeb8..f22e04d 100644
--- a/drivers/input/touchscreen/pcap_ts.c
+++ b/drivers/input/touchscreen/pcap_ts.c
@@ -137,7 +137,7 @@ static void pcap_ts_close(struct input_dev *dev)
 				pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT);
 }
 
-static int __devinit pcap_ts_probe(struct platform_device *pdev)
+static int pcap_ts_probe(struct platform_device *pdev)
 {
 	struct input_dev *input_dev;
 	struct pcap_ts *pcap_ts;
@@ -202,7 +202,7 @@ fail:
 	return err;
 }
 
-static int __devexit pcap_ts_remove(struct platform_device *pdev)
+static int pcap_ts_remove(struct platform_device *pdev)
 {
 	struct pcap_ts *pcap_ts = platform_get_drvdata(pdev);
 
@@ -245,7 +245,7 @@ static const struct dev_pm_ops pcap_ts_pm_ops = {
 
 static struct platform_driver pcap_ts_driver = {
 	.probe		= pcap_ts_probe,
-	.remove		= __devexit_p(pcap_ts_remove),
+	.remove		= pcap_ts_remove,
 	.driver		= {
 		.name	= "pcap-ts",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 953b4c1..6cc6b36 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -125,7 +125,7 @@ static int pixcir_i2c_ts_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
 			 pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
 
-static int __devinit pixcir_i2c_ts_probe(struct i2c_client *client,
+static int pixcir_i2c_ts_probe(struct i2c_client *client,
 					 const struct i2c_device_id *id)
 {
 	const struct pixcir_ts_platform_data *pdata = client->dev.platform_data;
@@ -189,7 +189,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit pixcir_i2c_ts_remove(struct i2c_client *client)
+static int pixcir_i2c_ts_remove(struct i2c_client *client)
 {
 	struct pixcir_i2c_ts_data *tsdata = i2c_get_clientdata(client);
 
@@ -218,7 +218,7 @@ static struct i2c_driver pixcir_i2c_ts_driver = {
 		.pm	= &pixcir_dev_pm_ops,
 	},
 	.probe		= pixcir_i2c_ts_probe,
-	.remove		= __devexit_p(pixcir_i2c_ts_remove),
+	.remove		= pixcir_i2c_ts_remove,
 	.id_table	= pixcir_i2c_ts_id,
 };
 
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
index 549fa29..b061af2 100644
--- a/drivers/input/touchscreen/s3c2410_ts.c
+++ b/drivers/input/touchscreen/s3c2410_ts.c
@@ -238,7 +238,7 @@ static void s3c24xx_ts_select(struct s3c_adc_client *client, unsigned select)
  * Initialise, find and allocate any resources we need to run and then
  * register with the ADC and input systems.
  */
-static int __devinit s3c2410ts_probe(struct platform_device *pdev)
+static int s3c2410ts_probe(struct platform_device *pdev)
 {
 	struct s3c2410_ts_mach_info *info;
 	struct device *dev = &pdev->dev;
@@ -365,7 +365,7 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev)
  *
  * Free up our state ready to be removed.
  */
-static int __devexit s3c2410ts_remove(struct platform_device *pdev)
+static int s3c2410ts_remove(struct platform_device *pdev)
 {
 	free_irq(ts.irq_tc, ts.input);
 	del_timer_sync(&touch_timer);
@@ -430,7 +430,7 @@ static struct platform_driver s3c_ts_driver = {
 	},
 	.id_table	= s3cts_driver_ids,
 	.probe		= s3c2410ts_probe,
-	.remove		= __devexit_p(s3c2410ts_remove),
+	.remove		= s3c2410ts_remove,
 };
 module_platform_driver(s3c_ts_driver);
 
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
index 6cb68a1..d9d05e2 100644
--- a/drivers/input/touchscreen/st1232.c
+++ b/drivers/input/touchscreen/st1232.c
@@ -139,7 +139,7 @@ end:
 	return IRQ_HANDLED;
 }
 
-static int __devinit st1232_ts_probe(struct i2c_client *client,
+static int st1232_ts_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	struct st1232_ts_data *ts;
@@ -206,7 +206,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit st1232_ts_remove(struct i2c_client *client)
+static int st1232_ts_remove(struct i2c_client *client)
 {
 	struct st1232_ts_data *ts = i2c_get_clientdata(client);
 
@@ -255,7 +255,7 @@ static const struct i2c_device_id st1232_ts_id[] = {
 MODULE_DEVICE_TABLE(i2c, st1232_ts_id);
 
 #ifdef CONFIG_OF
-static const struct of_device_id st1232_ts_dt_ids[] __devinitconst = {
+static const struct of_device_id st1232_ts_dt_ids[] = {
 	{ .compatible = "sitronix,st1232", },
 	{ }
 };
@@ -264,7 +264,7 @@ MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids);
 
 static struct i2c_driver st1232_ts_driver = {
 	.probe		= st1232_ts_probe,
-	.remove		= __devexit_p(st1232_ts_remove),
+	.remove		= st1232_ts_remove,
 	.id_table	= st1232_ts_id,
 	.driver = {
 		.name	= ST1232_TS_NAME,
diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c
index 692b685..84d884b 100644
--- a/drivers/input/touchscreen/stmpe-ts.c
+++ b/drivers/input/touchscreen/stmpe-ts.c
@@ -1,4 +1,5 @@
-/* STMicroelectronics STMPE811 Touchscreen Driver
+/*
+ * STMicroelectronics STMPE811 Touchscreen Driver
  *
  * (C) 2010 Luotao Fu <l.fu@pengutronix.de>
  * All rights reserved.
@@ -16,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/input.h>
 #include <linux/slab.h>
@@ -166,7 +168,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int __devinit stmpe_init_hw(struct stmpe_touch *ts)
+static int stmpe_init_hw(struct stmpe_touch *ts)
 {
 	int ret;
 	u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask;
@@ -261,41 +263,18 @@ static void stmpe_ts_close(struct input_dev *dev)
 			STMPE_TSC_CTRL_TSC_EN, 0);
 }
 
-static int __devinit stmpe_input_probe(struct platform_device *pdev)
+static void stmpe_ts_get_platform_info(struct platform_device *pdev,
+					struct stmpe_touch *ts)
 {
 	struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
-	struct stmpe_platform_data *pdata = stmpe->pdata;
-	struct stmpe_touch *ts;
-	struct input_dev *idev;
+	struct device_node *np = pdev->dev.of_node;
 	struct stmpe_ts_platform_data *ts_pdata = NULL;
-	int ret;
-	int ts_irq;
-
-	ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
-	if (ts_irq < 0)
-		return ts_irq;
-
-	ts = kzalloc(sizeof(*ts), GFP_KERNEL);
-	if (!ts) {
-		ret = -ENOMEM;
-		goto err_out;
-	}
 
-	idev = input_allocate_device();
-	if (!idev) {
-		ret = -ENOMEM;
-		goto err_free_ts;
-	}
-
-	platform_set_drvdata(pdev, ts);
 	ts->stmpe = stmpe;
-	ts->idev = idev;
-	ts->dev = &pdev->dev;
 
-	if (pdata)
-		ts_pdata = pdata->ts;
+	if (stmpe->pdata && stmpe->pdata->ts) {
+		ts_pdata = stmpe->pdata->ts;
 
-	if (ts_pdata) {
 		ts->sample_time = ts_pdata->sample_time;
 		ts->mod_12b = ts_pdata->mod_12b;
 		ts->ref_sel = ts_pdata->ref_sel;
@@ -305,22 +284,71 @@ static int __devinit stmpe_input_probe(struct platform_device *pdev)
 		ts->settling = ts_pdata->settling;
 		ts->fraction_z = ts_pdata->fraction_z;
 		ts->i_drive = ts_pdata->i_drive;
+	} else if (np) {
+		u32 val;
+
+		if (!of_property_read_u32(np, "st,sample-time", &val))
+			ts->sample_time = val;
+		if (!of_property_read_u32(np, "st,mod-12b", &val))
+			ts->mod_12b = val;
+		if (!of_property_read_u32(np, "st,ref-sel", &val))
+			ts->ref_sel = val;
+		if (!of_property_read_u32(np, "st,adc-freq", &val))
+			ts->adc_freq = val;
+		if (!of_property_read_u32(np, "st,ave-ctrl", &val))
+			ts->ave_ctrl = val;
+		if (!of_property_read_u32(np, "st,touch-det-delay", &val))
+			ts->touch_det_delay = val;
+		if (!of_property_read_u32(np, "st,settling", &val))
+			ts->settling = val;
+		if (!of_property_read_u32(np, "st,fraction-z", &val))
+			ts->fraction_z = val;
+		if (!of_property_read_u32(np, "st,i-drive", &val))
+			ts->i_drive = val;
 	}
+}
+
+static int stmpe_input_probe(struct platform_device *pdev)
+{
+	struct stmpe_touch *ts;
+	struct input_dev *idev;
+	int error;
+	int ts_irq;
+
+	ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
+	if (ts_irq < 0)
+		return ts_irq;
+
+	ts = devm_kzalloc(&pdev->dev, sizeof(*ts), GFP_KERNEL);
+	if (!ts)
+		return -ENOMEM;
+
+	idev = devm_input_allocate_device(&pdev->dev);
+	if (!idev)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, ts);
+	ts->idev = idev;
+	ts->dev = &pdev->dev;
+
+	stmpe_ts_get_platform_info(pdev, ts);
 
 	INIT_DELAYED_WORK(&ts->work, stmpe_work);
 
-	ret = request_threaded_irq(ts_irq, NULL, stmpe_ts_handler,
-			IRQF_ONESHOT, STMPE_TS_NAME, ts);
-	if (ret) {
+	error = devm_request_threaded_irq(&pdev->dev, ts_irq,
+					  NULL, stmpe_ts_handler,
+					  IRQF_ONESHOT, STMPE_TS_NAME, ts);
+	if (error) {
 		dev_err(&pdev->dev, "Failed to request IRQ %d\n", ts_irq);
-		goto err_free_input;
+		return error;
 	}
 
-	ret = stmpe_init_hw(ts);
-	if (ret)
-		goto err_free_irq;
+	error = stmpe_init_hw(ts);
+	if (error)
+		return error;
 
 	idev->name = STMPE_TS_NAME;
+	idev->phys = STMPE_TS_NAME"/input0";
 	idev->id.bustype = BUS_I2C;
 	idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 	idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
@@ -334,40 +362,21 @@ static int __devinit stmpe_input_probe(struct platform_device *pdev)
 	input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0);
 	input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0);
 
-	ret = input_register_device(idev);
-	if (ret) {
+	error = input_register_device(idev);
+	if (error) {
 		dev_err(&pdev->dev, "Could not register input device\n");
-		goto err_free_irq;
+		return error;
 	}
 
-	return ret;
-
-err_free_irq:
-	free_irq(ts_irq, ts);
-err_free_input:
-	input_free_device(idev);
-	platform_set_drvdata(pdev, NULL);
-err_free_ts:
-	kfree(ts);
-err_out:
-	return ret;
+	return 0;
 }
 
-static int __devexit stmpe_ts_remove(struct platform_device *pdev)
+static int stmpe_ts_remove(struct platform_device *pdev)
 {
 	struct stmpe_touch *ts = platform_get_drvdata(pdev);
-	unsigned int ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
 
 	stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN);
 
-	free_irq(ts_irq, ts);
-
-	platform_set_drvdata(pdev, NULL);
-
-	input_unregister_device(ts->idev);
-
-	kfree(ts);
-
 	return 0;
 }
 
@@ -377,7 +386,7 @@ static struct platform_driver stmpe_ts_driver = {
 		   .owner = THIS_MODULE,
 		   },
 	.probe = stmpe_input_probe,
-	.remove = __devexit_p(stmpe_ts_remove),
+	.remove = stmpe_ts_remove,
 };
 module_platform_driver(stmpe_ts_driver);
 
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
new file mode 100644
index 0000000..7a18a8a
--- /dev/null
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -0,0 +1,398 @@
+/*
+ * TI Touch Screen driver
+ *
+ * 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 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/init.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/input/ti_am335x_tsc.h>
+#include <linux/delay.h>
+
+#include <linux/mfd/ti_am335x_tscadc.h>
+
+#define ADCFSM_STEPID		0x10
+#define SEQ_SETTLE		275
+#define MAX_12BIT		((1 << 12) - 1)
+
+struct titsc {
+	struct input_dev	*input;
+	struct ti_tscadc_dev	*mfd_tscadc;
+	unsigned int		irq;
+	unsigned int		wires;
+	unsigned int		x_plate_resistance;
+	bool			pen_down;
+	int			steps_to_configure;
+};
+
+static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
+{
+	return readl(ts->mfd_tscadc->tscadc_base + reg);
+}
+
+static void titsc_writel(struct titsc *tsc, unsigned int reg,
+					unsigned int val)
+{
+	writel(val, tsc->mfd_tscadc->tscadc_base + reg);
+}
+
+static void titsc_step_config(struct titsc *ts_dev)
+{
+	unsigned int	config;
+	int i, total_steps;
+
+	/* Configure the Step registers */
+	total_steps = 2 * ts_dev->steps_to_configure;
+
+	config = STEPCONFIG_MODE_HWSYNC |
+			STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
+	switch (ts_dev->wires) {
+	case 4:
+		config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
+		break;
+	case 5:
+		config |= STEPCONFIG_YNN |
+				STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
+				STEPCONFIG_YPP;
+		break;
+	case 8:
+		config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
+		break;
+	}
+
+	for (i = 1; i <= ts_dev->steps_to_configure; i++) {
+		titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
+		titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
+	}
+
+	config = 0;
+	config = STEPCONFIG_MODE_HWSYNC |
+			STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
+			STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
+	switch (ts_dev->wires) {
+	case 4:
+		config |= STEPCONFIG_YPP;
+		break;
+	case 5:
+		config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
+				STEPCONFIG_XNP | STEPCONFIG_YPN;
+		break;
+	case 8:
+		config |= STEPCONFIG_YPP;
+		break;
+	}
+
+	for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) {
+		titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
+		titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
+	}
+
+	config = 0;
+	/* Charge step configuration */
+	config = STEPCONFIG_XPP | STEPCONFIG_YNN |
+			STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
+			STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1;
+
+	titsc_writel(ts_dev, REG_CHARGECONFIG, config);
+	titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
+
+	config = 0;
+	/* Configure to calculate pressure */
+	config = STEPCONFIG_MODE_HWSYNC |
+			STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
+			STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
+	titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config);
+	titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1),
+			STEPCONFIG_OPENDLY);
+
+	config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
+	titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config);
+	titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
+			STEPCONFIG_OPENDLY);
+
+	titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
+}
+
+static void titsc_read_coordinates(struct titsc *ts_dev,
+				    unsigned int *x, unsigned int *y)
+{
+	unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT);
+	unsigned int prev_val_x = ~0, prev_val_y = ~0;
+	unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
+	unsigned int read, diff;
+	unsigned int i, channel;
+
+	/*
+	 * Delta filter is used to remove large variations in sampled
+	 * values from ADC. The filter tries to predict where the next
+	 * coordinate could be. This is done by taking a previous
+	 * coordinate and subtracting it form current one. Further the
+	 * algorithm compares the difference with that of a present value,
+	 * if true the value is reported to the sub system.
+	 */
+	for (i = 0; i < fifocount - 1; i++) {
+		read = titsc_readl(ts_dev, REG_FIFO0);
+		channel = read & 0xf0000;
+		channel = channel >> 0x10;
+		if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) {
+			read &= 0xfff;
+			diff = abs(read - prev_val_x);
+			if (diff < prev_diff_x) {
+				prev_diff_x = diff;
+				*x = read;
+			}
+			prev_val_x = read;
+		}
+
+		read = titsc_readl(ts_dev, REG_FIFO1);
+		channel = read & 0xf0000;
+		channel = channel >> 0x10;
+		if ((channel >= ts_dev->steps_to_configure) &&
+			(channel < (2 * ts_dev->steps_to_configure - 1))) {
+			read &= 0xfff;
+			diff = abs(read - prev_val_y);
+			if (diff < prev_diff_y) {
+				prev_diff_y = diff;
+				*y = read;
+			}
+			prev_val_y = read;
+		}
+	}
+}
+
+static irqreturn_t titsc_irq(int irq, void *dev)
+{
+	struct titsc *ts_dev = dev;
+	struct input_dev *input_dev = ts_dev->input;
+	unsigned int status, irqclr = 0;
+	unsigned int x = 0, y = 0;
+	unsigned int z1, z2, z;
+	unsigned int fsm;
+	unsigned int fifo1count, fifo0count;
+	int i;
+
+	status = titsc_readl(ts_dev, REG_IRQSTATUS);
+	if (status & IRQENB_FIFO0THRES) {
+		titsc_read_coordinates(ts_dev, &x, &y);
+
+		z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
+		z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
+
+		fifo1count = titsc_readl(ts_dev, REG_FIFO1CNT);
+		for (i = 0; i < fifo1count; i++)
+			titsc_readl(ts_dev, REG_FIFO1);
+
+		fifo0count = titsc_readl(ts_dev, REG_FIFO0CNT);
+		for (i = 0; i < fifo0count; i++)
+			titsc_readl(ts_dev, REG_FIFO0);
+
+		if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
+			/*
+			 * Calculate pressure using formula
+			 * Resistance(touch) = x plate resistance *
+			 * x postion/4096 * ((z2 / z1) - 1)
+			 */
+			z = z2 - z1;
+			z *= x;
+			z *= ts_dev->x_plate_resistance;
+			z /= z1;
+			z = (z + 2047) >> 12;
+
+			if (z <= MAX_12BIT) {
+				input_report_abs(input_dev, ABS_X, x);
+				input_report_abs(input_dev, ABS_Y, y);
+				input_report_abs(input_dev, ABS_PRESSURE, z);
+				input_report_key(input_dev, BTN_TOUCH, 1);
+				input_sync(input_dev);
+			}
+		}
+		irqclr |= IRQENB_FIFO0THRES;
+	}
+
+	/*
+	 * Time for sequencer to settle, to read
+	 * correct state of the sequencer.
+	 */
+	udelay(SEQ_SETTLE);
+
+	status = titsc_readl(ts_dev, REG_RAWIRQSTATUS);
+	if (status & IRQENB_PENUP) {
+		/* Pen up event */
+		fsm = titsc_readl(ts_dev, REG_ADCFSM);
+		if (fsm == ADCFSM_STEPID) {
+			ts_dev->pen_down = false;
+			input_report_key(input_dev, BTN_TOUCH, 0);
+			input_report_abs(input_dev, ABS_PRESSURE, 0);
+			input_sync(input_dev);
+		} else {
+			ts_dev->pen_down = true;
+		}
+		irqclr |= IRQENB_PENUP;
+	}
+
+	titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
+
+	titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
+	return IRQ_HANDLED;
+}
+
+/*
+ * The functions for inserting/removing driver as a module.
+ */
+
+static int __devinit titsc_probe(struct platform_device *pdev)
+{
+	struct titsc *ts_dev;
+	struct input_dev *input_dev;
+	struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
+	struct mfd_tscadc_board	*pdata;
+	int err;
+
+	pdata = tscadc_dev->dev->platform_data;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "Could not find platform data\n");
+		return -EINVAL;
+	}
+
+	/* Allocate memory for device */
+	ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!ts_dev || !input_dev) {
+		dev_err(&pdev->dev, "failed to allocate memory.\n");
+		err = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	tscadc_dev->tsc = ts_dev;
+	ts_dev->mfd_tscadc = tscadc_dev;
+	ts_dev->input = input_dev;
+	ts_dev->irq = tscadc_dev->irq;
+	ts_dev->wires = pdata->tsc_init->wires;
+	ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance;
+	ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure;
+
+	err = request_irq(ts_dev->irq, titsc_irq,
+			  0, pdev->dev.driver->name, ts_dev);
+	if (err) {
+		dev_err(&pdev->dev, "failed to allocate irq.\n");
+		goto err_free_mem;
+	}
+
+	titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
+	titsc_step_config(ts_dev);
+	titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
+
+	input_dev->name = "ti-tsc";
+	input_dev->dev.parent = &pdev->dev;
+
+	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+	input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
+
+	/* register to the input system */
+	err = input_register_device(input_dev);
+	if (err)
+		goto err_free_irq;
+
+	platform_set_drvdata(pdev, ts_dev);
+	return 0;
+
+err_free_irq:
+	free_irq(ts_dev->irq, ts_dev);
+err_free_mem:
+	input_free_device(input_dev);
+	kfree(ts_dev);
+	return err;
+}
+
+static int __devexit titsc_remove(struct platform_device *pdev)
+{
+	struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
+	struct titsc *ts_dev = tscadc_dev->tsc;
+
+	free_irq(ts_dev->irq, ts_dev);
+
+	input_unregister_device(ts_dev->input);
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(ts_dev);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int titsc_suspend(struct device *dev)
+{
+	struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
+	struct titsc *ts_dev = tscadc_dev->tsc;
+	unsigned int idle;
+
+	if (device_may_wakeup(tscadc_dev->dev)) {
+		idle = titsc_readl(ts_dev, REG_IRQENABLE);
+		titsc_writel(ts_dev, REG_IRQENABLE,
+				(idle | IRQENB_HW_PEN));
+		titsc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
+	}
+	return 0;
+}
+
+static int titsc_resume(struct device *dev)
+{
+	struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
+	struct titsc *ts_dev = tscadc_dev->tsc;
+
+	if (device_may_wakeup(tscadc_dev->dev)) {
+		titsc_writel(ts_dev, REG_IRQWAKEUP,
+				0x00);
+		titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
+	}
+	titsc_step_config(ts_dev);
+	titsc_writel(ts_dev, REG_FIFO0THR,
+			ts_dev->steps_to_configure);
+	return 0;
+}
+
+static const struct dev_pm_ops titsc_pm_ops = {
+	.suspend = titsc_suspend,
+	.resume  = titsc_resume,
+};
+#define TITSC_PM_OPS (&titsc_pm_ops)
+#else
+#define TITSC_PM_OPS NULL
+#endif
+
+static struct platform_driver ti_tsc_driver = {
+	.probe	= titsc_probe,
+	.remove	= __devexit_p(titsc_remove),
+	.driver	= {
+		.name   = "tsc",
+		.owner	= THIS_MODULE,
+		.pm	= TITSC_PM_OPS,
+	},
+};
+module_platform_driver(ti_tsc_driver);
+
+MODULE_DESCRIPTION("TI touchscreen controller driver");
+MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c
deleted file mode 100644
index d229c74..0000000
--- a/drivers/input/touchscreen/ti_tscadc.c
+++ /dev/null
@@ -1,486 +0,0 @@
-/*
- * TI Touch Screen driver
- *
- * 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 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/init.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/input.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/input/ti_tscadc.h>
-#include <linux/delay.h>
-
-#define REG_IRQEOI		0x020
-#define REG_RAWIRQSTATUS	0x024
-#define REG_IRQSTATUS		0x028
-#define REG_IRQENABLE		0x02C
-#define REG_IRQWAKEUP		0x034
-#define REG_CTRL		0x040
-#define REG_ADCFSM		0x044
-#define REG_CLKDIV		0x04C
-#define REG_SE			0x054
-#define REG_IDLECONFIG		0x058
-#define REG_CHARGECONFIG	0x05C
-#define REG_CHARGEDELAY		0x060
-#define REG_STEPCONFIG(n)	(0x64 + ((n - 1) * 8))
-#define REG_STEPDELAY(n)	(0x68 + ((n - 1) * 8))
-#define REG_STEPCONFIG13	0x0C4
-#define REG_STEPDELAY13		0x0C8
-#define REG_STEPCONFIG14	0x0CC
-#define REG_STEPDELAY14		0x0D0
-#define REG_FIFO0CNT		0xE4
-#define REG_FIFO1THR		0xF4
-#define REG_FIFO0		0x100
-#define REG_FIFO1		0x200
-
-/*	Register Bitfields	*/
-#define IRQWKUP_ENB		BIT(0)
-#define STPENB_STEPENB		0x7FFF
-#define IRQENB_FIFO1THRES	BIT(5)
-#define IRQENB_PENUP		BIT(9)
-#define STEPCONFIG_MODE_HWSYNC	0x2
-#define STEPCONFIG_SAMPLES_AVG	(1 << 4)
-#define STEPCONFIG_XPP		(1 << 5)
-#define STEPCONFIG_XNN		(1 << 6)
-#define STEPCONFIG_YPP		(1 << 7)
-#define STEPCONFIG_YNN		(1 << 8)
-#define STEPCONFIG_XNP		(1 << 9)
-#define STEPCONFIG_YPN		(1 << 10)
-#define STEPCONFIG_INM		(1 << 18)
-#define STEPCONFIG_INP		(1 << 20)
-#define STEPCONFIG_INP_5	(1 << 21)
-#define STEPCONFIG_FIFO1	(1 << 26)
-#define STEPCONFIG_OPENDLY	0xff
-#define STEPCONFIG_Z1		(3 << 19)
-#define STEPIDLE_INP		(1 << 22)
-#define STEPCHARGE_RFP		(1 << 12)
-#define STEPCHARGE_INM		(1 << 15)
-#define STEPCHARGE_INP		(1 << 19)
-#define STEPCHARGE_RFM		(1 << 23)
-#define STEPCHARGE_DELAY	0x1
-#define CNTRLREG_TSCSSENB	(1 << 0)
-#define CNTRLREG_STEPID		(1 << 1)
-#define CNTRLREG_STEPCONFIGWRT	(1 << 2)
-#define CNTRLREG_4WIRE		(1 << 5)
-#define CNTRLREG_5WIRE		(1 << 6)
-#define CNTRLREG_8WIRE		(3 << 5)
-#define CNTRLREG_TSCENB		(1 << 7)
-#define ADCFSM_STEPID		0x10
-
-#define SEQ_SETTLE		275
-#define ADC_CLK			3000000
-#define MAX_12BIT		((1 << 12) - 1)
-#define TSCADC_DELTA_X		15
-#define TSCADC_DELTA_Y		15
-
-struct tscadc {
-	struct input_dev	*input;
-	struct clk		*tsc_ick;
-	void __iomem		*tsc_base;
-	unsigned int		irq;
-	unsigned int		wires;
-	unsigned int		x_plate_resistance;
-	bool			pen_down;
-};
-
-static unsigned int tscadc_readl(struct tscadc *ts, unsigned int reg)
-{
-	return readl(ts->tsc_base + reg);
-}
-
-static void tscadc_writel(struct tscadc *tsc, unsigned int reg,
-					unsigned int val)
-{
-	writel(val, tsc->tsc_base + reg);
-}
-
-static void tscadc_step_config(struct tscadc *ts_dev)
-{
-	unsigned int	config;
-	int i;
-
-	/* Configure the Step registers */
-
-	config = STEPCONFIG_MODE_HWSYNC |
-			STEPCONFIG_SAMPLES_AVG | STEPCONFIG_XPP;
-	switch (ts_dev->wires) {
-	case 4:
-		config |= STEPCONFIG_INP | STEPCONFIG_XNN;
-		break;
-	case 5:
-		config |= STEPCONFIG_YNN |
-				STEPCONFIG_INP_5 | STEPCONFIG_XNN |
-				STEPCONFIG_YPP;
-		break;
-	case 8:
-		config |= STEPCONFIG_INP | STEPCONFIG_XNN;
-		break;
-	}
-
-	for (i = 1; i < 7; i++) {
-		tscadc_writel(ts_dev, REG_STEPCONFIG(i), config);
-		tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
-	}
-
-	config = 0;
-	config = STEPCONFIG_MODE_HWSYNC |
-			STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YNN |
-			STEPCONFIG_INM | STEPCONFIG_FIFO1;
-	switch (ts_dev->wires) {
-	case 4:
-		config |= STEPCONFIG_YPP;
-		break;
-	case 5:
-		config |= STEPCONFIG_XPP | STEPCONFIG_INP_5 |
-				STEPCONFIG_XNP | STEPCONFIG_YPN;
-		break;
-	case 8:
-		config |= STEPCONFIG_YPP;
-		break;
-	}
-
-	for (i = 7; i < 13; i++) {
-		tscadc_writel(ts_dev, REG_STEPCONFIG(i), config);
-		tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
-	}
-
-	config = 0;
-	/* Charge step configuration */
-	config = STEPCONFIG_XPP | STEPCONFIG_YNN |
-			STEPCHARGE_RFP | STEPCHARGE_RFM |
-			STEPCHARGE_INM | STEPCHARGE_INP;
-
-	tscadc_writel(ts_dev, REG_CHARGECONFIG, config);
-	tscadc_writel(ts_dev, REG_CHARGEDELAY, STEPCHARGE_DELAY);
-
-	config = 0;
-	/* Configure to calculate pressure */
-	config = STEPCONFIG_MODE_HWSYNC |
-			STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YPP |
-			STEPCONFIG_XNN | STEPCONFIG_INM;
-	tscadc_writel(ts_dev, REG_STEPCONFIG13, config);
-	tscadc_writel(ts_dev, REG_STEPDELAY13, STEPCONFIG_OPENDLY);
-
-	config |= STEPCONFIG_Z1 | STEPCONFIG_FIFO1;
-	tscadc_writel(ts_dev, REG_STEPCONFIG14, config);
-	tscadc_writel(ts_dev, REG_STEPDELAY14, STEPCONFIG_OPENDLY);
-
-	tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB);
-}
-
-static void tscadc_idle_config(struct tscadc *ts_config)
-{
-	unsigned int idleconfig;
-
-	idleconfig = STEPCONFIG_YNN |
-			STEPCONFIG_INM |
-			STEPCONFIG_YPN | STEPIDLE_INP;
-	tscadc_writel(ts_config, REG_IDLECONFIG, idleconfig);
-}
-
-static void tscadc_read_coordinates(struct tscadc *ts_dev,
-				    unsigned int *x, unsigned int *y)
-{
-	unsigned int fifocount = tscadc_readl(ts_dev, REG_FIFO0CNT);
-	unsigned int prev_val_x = ~0, prev_val_y = ~0;
-	unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
-	unsigned int read, diff;
-	unsigned int i;
-
-	/*
-	 * Delta filter is used to remove large variations in sampled
-	 * values from ADC. The filter tries to predict where the next
-	 * coordinate could be. This is done by taking a previous
-	 * coordinate and subtracting it form current one. Further the
-	 * algorithm compares the difference with that of a present value,
-	 * if true the value is reported to the sub system.
-	 */
-	for (i = 0; i < fifocount - 1; i++) {
-		read = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff;
-		diff = abs(read - prev_val_x);
-		if (diff < prev_diff_x) {
-			prev_diff_x = diff;
-			*x = read;
-		}
-		prev_val_x = read;
-
-		read = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff;
-		diff = abs(read - prev_val_y);
-		if (diff < prev_diff_y) {
-			prev_diff_y = diff;
-			*y = read;
-		}
-		prev_val_y = read;
-	}
-}
-
-static irqreturn_t tscadc_irq(int irq, void *dev)
-{
-	struct tscadc *ts_dev = dev;
-	struct input_dev *input_dev = ts_dev->input;
-	unsigned int status, irqclr = 0;
-	unsigned int x = 0, y = 0;
-	unsigned int z1, z2, z;
-	unsigned int fsm;
-
-	status = tscadc_readl(ts_dev, REG_IRQSTATUS);
-	if (status & IRQENB_FIFO1THRES) {
-		tscadc_read_coordinates(ts_dev, &x, &y);
-
-		z1 = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff;
-		z2 = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff;
-
-		if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
-			/*
-			 * Calculate pressure using formula
-			 * Resistance(touch) = x plate resistance *
-			 * x postion/4096 * ((z2 / z1) - 1)
-			 */
-			z = z2 - z1;
-			z *= x;
-			z *= ts_dev->x_plate_resistance;
-			z /= z1;
-			z = (z + 2047) >> 12;
-
-			if (z <= MAX_12BIT) {
-				input_report_abs(input_dev, ABS_X, x);
-				input_report_abs(input_dev, ABS_Y, y);
-				input_report_abs(input_dev, ABS_PRESSURE, z);
-				input_report_key(input_dev, BTN_TOUCH, 1);
-				input_sync(input_dev);
-			}
-		}
-		irqclr |= IRQENB_FIFO1THRES;
-	}
-
-	/*
-	 * Time for sequencer to settle, to read
-	 * correct state of the sequencer.
-	 */
-	udelay(SEQ_SETTLE);
-
-	status = tscadc_readl(ts_dev, REG_RAWIRQSTATUS);
-	if (status & IRQENB_PENUP) {
-		/* Pen up event */
-		fsm = tscadc_readl(ts_dev, REG_ADCFSM);
-		if (fsm == ADCFSM_STEPID) {
-			ts_dev->pen_down = false;
-			input_report_key(input_dev, BTN_TOUCH, 0);
-			input_report_abs(input_dev, ABS_PRESSURE, 0);
-			input_sync(input_dev);
-		} else {
-			ts_dev->pen_down = true;
-		}
-		irqclr |= IRQENB_PENUP;
-	}
-
-	tscadc_writel(ts_dev, REG_IRQSTATUS, irqclr);
-	/* check pending interrupts */
-	tscadc_writel(ts_dev, REG_IRQEOI, 0x0);
-
-	tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB);
-	return IRQ_HANDLED;
-}
-
-/*
- * The functions for inserting/removing driver as a module.
- */
-
-static int __devinit tscadc_probe(struct platform_device *pdev)
-{
-	const struct tsc_data *pdata = pdev->dev.platform_data;
-	struct resource *res;
-	struct tscadc *ts_dev;
-	struct input_dev *input_dev;
-	struct clk *clk;
-	int err;
-	int clk_value, ctrl, irq;
-
-	if (!pdata) {
-		dev_err(&pdev->dev, "missing platform data.\n");
-		return -EINVAL;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "no memory resource defined.\n");
-		return -EINVAL;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "no irq ID is specified.\n");
-		return -EINVAL;
-	}
-
-	/* Allocate memory for device */
-	ts_dev = kzalloc(sizeof(struct tscadc), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!ts_dev || !input_dev) {
-		dev_err(&pdev->dev, "failed to allocate memory.\n");
-		err = -ENOMEM;
-		goto err_free_mem;
-	}
-
-	ts_dev->input = input_dev;
-	ts_dev->irq = irq;
-	ts_dev->wires = pdata->wires;
-	ts_dev->x_plate_resistance = pdata->x_plate_resistance;
-
-	res = request_mem_region(res->start, resource_size(res), pdev->name);
-	if (!res) {
-		dev_err(&pdev->dev, "failed to reserve registers.\n");
-		err = -EBUSY;
-		goto err_free_mem;
-	}
-
-	ts_dev->tsc_base = ioremap(res->start, resource_size(res));
-	if (!ts_dev->tsc_base) {
-		dev_err(&pdev->dev, "failed to map registers.\n");
-		err = -ENOMEM;
-		goto err_release_mem_region;
-	}
-
-	err = request_irq(ts_dev->irq, tscadc_irq,
-			  0, pdev->dev.driver->name, ts_dev);
-	if (err) {
-		dev_err(&pdev->dev, "failed to allocate irq.\n");
-		goto err_unmap_regs;
-	}
-
-	ts_dev->tsc_ick = clk_get(&pdev->dev, "adc_tsc_ick");
-	if (IS_ERR(ts_dev->tsc_ick)) {
-		dev_err(&pdev->dev, "failed to get TSC ick\n");
-		goto err_free_irq;
-	}
-	clk_enable(ts_dev->tsc_ick);
-
-	clk = clk_get(&pdev->dev, "adc_tsc_fck");
-	if (IS_ERR(clk)) {
-		dev_err(&pdev->dev, "failed to get TSC fck\n");
-		err = PTR_ERR(clk);
-		goto err_disable_clk;
-	}
-
-	clk_value = clk_get_rate(clk) / ADC_CLK;
-	clk_put(clk);
-
-	if (clk_value < 7) {
-		dev_err(&pdev->dev, "clock input less than min clock requirement\n");
-		goto err_disable_clk;
-	}
-	/* CLKDIV needs to be configured to the value minus 1 */
-	tscadc_writel(ts_dev, REG_CLKDIV, clk_value - 1);
-
-	 /* Enable wake-up of the SoC using touchscreen */
-	tscadc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
-
-	ctrl = CNTRLREG_STEPCONFIGWRT |
-			CNTRLREG_TSCENB |
-			CNTRLREG_STEPID;
-	switch (ts_dev->wires) {
-	case 4:
-		ctrl |= CNTRLREG_4WIRE;
-		break;
-	case 5:
-		ctrl |= CNTRLREG_5WIRE;
-		break;
-	case 8:
-		ctrl |= CNTRLREG_8WIRE;
-		break;
-	}
-	tscadc_writel(ts_dev, REG_CTRL, ctrl);
-
-	tscadc_idle_config(ts_dev);
-	tscadc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
-	tscadc_step_config(ts_dev);
-	tscadc_writel(ts_dev, REG_FIFO1THR, 6);
-
-	ctrl |= CNTRLREG_TSCSSENB;
-	tscadc_writel(ts_dev, REG_CTRL, ctrl);
-
-	input_dev->name = "ti-tsc-adc";
-	input_dev->dev.parent = &pdev->dev;
-
-	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
-
-	input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
-	input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
-
-	/* register to the input system */
-	err = input_register_device(input_dev);
-	if (err)
-		goto err_disable_clk;
-
-	platform_set_drvdata(pdev, ts_dev);
-	return 0;
-
-err_disable_clk:
-	clk_disable(ts_dev->tsc_ick);
-	clk_put(ts_dev->tsc_ick);
-err_free_irq:
-	free_irq(ts_dev->irq, ts_dev);
-err_unmap_regs:
-	iounmap(ts_dev->tsc_base);
-err_release_mem_region:
-	release_mem_region(res->start, resource_size(res));
-err_free_mem:
-	input_free_device(input_dev);
-	kfree(ts_dev);
-	return err;
-}
-
-static int __devexit tscadc_remove(struct platform_device *pdev)
-{
-	struct tscadc *ts_dev = platform_get_drvdata(pdev);
-	struct resource *res;
-
-	free_irq(ts_dev->irq, ts_dev);
-
-	input_unregister_device(ts_dev->input);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	iounmap(ts_dev->tsc_base);
-	release_mem_region(res->start, resource_size(res));
-
-	clk_disable(ts_dev->tsc_ick);
-	clk_put(ts_dev->tsc_ick);
-
-	kfree(ts_dev);
-
-	platform_set_drvdata(pdev, NULL);
-	return 0;
-}
-
-static struct platform_driver ti_tsc_driver = {
-	.probe	= tscadc_probe,
-	.remove	= __devexit_p(tscadc_remove),
-	.driver	= {
-		.name   = "tsc",
-		.owner	= THIS_MODULE,
-	},
-};
-module_platform_driver(ti_tsc_driver);
-
-MODULE_DESCRIPTION("TI touchscreen controller driver");
-MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c
index 368d2c6c..acfb876 100644
--- a/drivers/input/touchscreen/tnetv107x-ts.c
+++ b/drivers/input/touchscreen/tnetv107x-ts.c
@@ -243,7 +243,7 @@ static void tsc_stop(struct input_dev *dev)
 	clk_disable(ts->clk);
 }
 
-static int __devinit tsc_probe(struct platform_device *pdev)
+static int tsc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct tsc_data *ts;
@@ -357,7 +357,7 @@ error_res:
 	return error;
 }
 
-static int __devexit tsc_remove(struct platform_device *pdev)
+static int tsc_remove(struct platform_device *pdev)
 {
 	struct tsc_data *ts = platform_get_drvdata(pdev);
 
@@ -374,7 +374,7 @@ static int __devexit tsc_remove(struct platform_device *pdev)
 
 static struct platform_driver tsc_driver = {
 	.probe		= tsc_probe,
-	.remove		= __devexit_p(tsc_remove),
+	.remove		= tsc_remove,
 	.driver.name	= "tnetv107x-ts",
 	.driver.owner	= THIS_MODULE,
 };
diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c
index f7eda3d..820a066 100644
--- a/drivers/input/touchscreen/tps6507x-ts.c
+++ b/drivers/input/touchscreen/tps6507x-ts.c
@@ -345,7 +345,7 @@ err0:
 	return error;
 }
 
-static int __devexit tps6507x_ts_remove(struct platform_device *pdev)
+static int tps6507x_ts_remove(struct platform_device *pdev)
 {
 	struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
 	struct tps6507x_ts *tsc = tps6507x_dev->ts;
@@ -367,7 +367,7 @@ static struct platform_driver tps6507x_ts_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = tps6507x_ts_probe,
-	.remove = __devexit_p(tps6507x_ts_remove),
+	.remove = tps6507x_ts_remove,
 };
 module_platform_driver(tps6507x_ts_driver);
 
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c
index 5ce3fa8..9c0cdc7 100644
--- a/drivers/input/touchscreen/tsc2005.c
+++ b/drivers/input/touchscreen/tsc2005.c
@@ -555,7 +555,7 @@ static void tsc2005_close(struct input_dev *input)
 	mutex_unlock(&ts->mutex);
 }
 
-static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts)
+static void tsc2005_setup_spi_xfer(struct tsc2005 *ts)
 {
 	tsc2005_setup_read(&ts->spi_x, TSC2005_REG_X, false);
 	tsc2005_setup_read(&ts->spi_y, TSC2005_REG_Y, false);
@@ -569,7 +569,7 @@ static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts)
 	spi_message_add_tail(&ts->spi_z2.spi_xfer, &ts->spi_read_msg);
 }
 
-static int __devinit tsc2005_probe(struct spi_device *spi)
+static int tsc2005_probe(struct spi_device *spi)
 {
 	const struct tsc2005_platform_data *pdata = spi->dev.platform_data;
 	struct tsc2005 *ts;
@@ -686,7 +686,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit tsc2005_remove(struct spi_device *spi)
+static int tsc2005_remove(struct spi_device *spi)
 {
 	struct tsc2005 *ts = spi_get_drvdata(spi);
 
@@ -745,7 +745,7 @@ static struct spi_driver tsc2005_driver = {
 		.pm	= &tsc2005_pm_ops,
 	},
 	.probe	= tsc2005_probe,
-	.remove	= __devexit_p(tsc2005_remove),
+	.remove	= tsc2005_remove,
 };
 
 module_spi_driver(tsc2005_driver);
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
index 1473d23..0b67ba4 100644
--- a/drivers/input/touchscreen/tsc2007.c
+++ b/drivers/input/touchscreen/tsc2007.c
@@ -273,7 +273,7 @@ static void tsc2007_close(struct input_dev *input_dev)
 	tsc2007_stop(ts);
 }
 
-static int __devinit tsc2007_probe(struct i2c_client *client,
+static int tsc2007_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
 	struct tsc2007 *ts;
@@ -366,7 +366,7 @@ static int __devinit tsc2007_probe(struct i2c_client *client,
 	return err;
 }
 
-static int __devexit tsc2007_remove(struct i2c_client *client)
+static int tsc2007_remove(struct i2c_client *client)
 {
 	struct tsc2007	*ts = i2c_get_clientdata(client);
 	struct tsc2007_platform_data *pdata = client->dev.platform_data;
@@ -396,7 +396,7 @@ static struct i2c_driver tsc2007_driver = {
 	},
 	.id_table	= tsc2007_idtable,
 	.probe		= tsc2007_probe,
-	.remove		= __devexit_p(tsc2007_remove),
+	.remove		= tsc2007_remove,
 };
 
 module_i2c_driver(tsc2007_driver);
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index 46e83ad..1271f97 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -274,7 +274,7 @@ static void ucb1400_ts_close(struct input_dev *idev)
  * Try to probe our interrupt, rather than relying on lots of
  * hard-coded machine dependencies.
  */
-static int __devinit ucb1400_ts_detect_irq(struct ucb1400_ts *ucb,
+static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb,
 					   struct platform_device *pdev)
 {
 	unsigned long mask, timeout;
@@ -318,7 +318,7 @@ static int __devinit ucb1400_ts_detect_irq(struct ucb1400_ts *ucb,
 	return 0;
 }
 
-static int __devinit ucb1400_ts_probe(struct platform_device *pdev)
+static int ucb1400_ts_probe(struct platform_device *pdev)
 {
 	struct ucb1400_ts *ucb = pdev->dev.platform_data;
 	int error, x_res, y_res;
@@ -397,7 +397,7 @@ err:
 	return error;
 }
 
-static int __devexit ucb1400_ts_remove(struct platform_device *pdev)
+static int ucb1400_ts_remove(struct platform_device *pdev)
 {
 	struct ucb1400_ts *ucb = pdev->dev.platform_data;
 
@@ -442,7 +442,7 @@ static SIMPLE_DEV_PM_OPS(ucb1400_ts_pm_ops,
 
 static struct platform_driver ucb1400_ts_driver = {
 	.probe	= ucb1400_ts_probe,
-	.remove	= __devexit_p(ucb1400_ts_remove),
+	.remove	= ucb1400_ts_remove,
 	.driver	= {
 		.name	= "ucb1400_ts",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c
index 9396b21..d2ef8f0 100644
--- a/drivers/input/touchscreen/w90p910_ts.c
+++ b/drivers/input/touchscreen/w90p910_ts.c
@@ -215,7 +215,7 @@ static void w90p910_close(struct input_dev *dev)
 	clk_disable(w90p910_ts->clk);
 }
 
-static int __devinit w90x900ts_probe(struct platform_device *pdev)
+static int w90x900ts_probe(struct platform_device *pdev)
 {
 	struct w90p910_ts *w90p910_ts;
 	struct input_dev *input_dev;
@@ -301,7 +301,7 @@ fail1:	input_free_device(input_dev);
 	return err;
 }
 
-static int __devexit w90x900ts_remove(struct platform_device *pdev)
+static int w90x900ts_remove(struct platform_device *pdev)
 {
 	struct w90p910_ts *w90p910_ts = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -325,7 +325,7 @@ static int __devexit w90x900ts_remove(struct platform_device *pdev)
 
 static struct platform_driver w90x900ts_driver = {
 	.probe		= w90x900ts_probe,
-	.remove		= __devexit_p(w90x900ts_remove),
+	.remove		= w90x900ts_remove,
 	.driver		= {
 		.name	= "nuc900-ts",
 		.owner	= THIS_MODULE,
diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
index 0c01657..bf0d076 100644
--- a/drivers/input/touchscreen/wacom_i2c.c
+++ b/drivers/input/touchscreen/wacom_i2c.c
@@ -144,7 +144,7 @@ static void wacom_i2c_close(struct input_dev *dev)
 	disable_irq(client->irq);
 }
 
-static int __devinit wacom_i2c_probe(struct i2c_client *client,
+static int wacom_i2c_probe(struct i2c_client *client,
 				     const struct i2c_device_id *id)
 {
 	struct wacom_i2c *wac_i2c;
@@ -225,7 +225,7 @@ err_free_mem:
 	return error;
 }
 
-static int __devexit wacom_i2c_remove(struct i2c_client *client)
+static int wacom_i2c_remove(struct i2c_client *client)
 {
 	struct wacom_i2c *wac_i2c = i2c_get_clientdata(client);
 
@@ -272,7 +272,7 @@ static struct i2c_driver wacom_i2c_driver = {
 	},
 
 	.probe		= wacom_i2c_probe,
-	.remove		= __devexit_p(wacom_i2c_remove),
+	.remove		= wacom_i2c_remove,
 	.id_table	= wacom_i2c_id,
 };
 module_i2c_driver(wacom_i2c_driver);
diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c
index 52abb98..f88fab5 100644
--- a/drivers/input/touchscreen/wm831x-ts.c
+++ b/drivers/input/touchscreen/wm831x-ts.c
@@ -233,7 +233,7 @@ static void wm831x_ts_input_close(struct input_dev *idev)
 	}
 }
 
-static __devinit int wm831x_ts_probe(struct platform_device *pdev)
+static int wm831x_ts_probe(struct platform_device *pdev)
 {
 	struct wm831x_ts *wm831x_ts;
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
@@ -245,7 +245,8 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev)
 	if (core_pdata)
 		pdata = core_pdata->touch;
 
-	wm831x_ts = kzalloc(sizeof(struct wm831x_ts), GFP_KERNEL);
+	wm831x_ts = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ts),
+				 GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!wm831x_ts || !input_dev) {
 		error = -ENOMEM;
@@ -376,21 +377,18 @@ err_data_irq:
 	free_irq(wm831x_ts->data_irq, wm831x_ts);
 err_alloc:
 	input_free_device(input_dev);
-	kfree(wm831x_ts);
 
 	return error;
 }
 
-static __devexit int wm831x_ts_remove(struct platform_device *pdev)
+static int wm831x_ts_remove(struct platform_device *pdev)
 {
 	struct wm831x_ts *wm831x_ts = platform_get_drvdata(pdev);
 
 	free_irq(wm831x_ts->pd_irq, wm831x_ts);
 	free_irq(wm831x_ts->data_irq, wm831x_ts);
 	input_unregister_device(wm831x_ts->input_dev);
-	kfree(wm831x_ts);
 
-	platform_set_drvdata(pdev, NULL);
 	return 0;
 }
 
@@ -400,7 +398,7 @@ static struct platform_driver wm831x_ts_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = wm831x_ts_probe,
-	.remove = __devexit_p(wm831x_ts_remove),
+	.remove = wm831x_ts_remove,
 };
 module_platform_driver(wm831x_ts_driver);
 
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index e39f9db..64586f1 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -168,7 +168,7 @@ config TEGRA_IOMMU_SMMU
 
 config EXYNOS_IOMMU
 	bool "Exynos IOMMU Support"
-	depends on ARCH_EXYNOS && EXYNOS_DEV_SYSMMU
+	depends on ARCH_EXYNOS
 	select IOMMU_API
 	help
 	  Support for the IOMMU(System MMU) of Samsung Exynos application
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 55074cb..cb63cc5 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -140,6 +140,9 @@ static void free_dev_data(struct iommu_dev_data *dev_data)
 	list_del(&dev_data->dev_data_list);
 	spin_unlock_irqrestore(&dev_data_list_lock, flags);
 
+	if (dev_data->group)
+		iommu_group_put(dev_data->group);
+
 	kfree(dev_data);
 }
 
@@ -274,41 +277,23 @@ static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to)
 	*from = to;
 }
 
-#define REQ_ACS_FLAGS	(PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
-
-static int iommu_init_device(struct device *dev)
+static struct pci_bus *find_hosted_bus(struct pci_bus *bus)
 {
-	struct pci_dev *dma_pdev = NULL, *pdev = to_pci_dev(dev);
-	struct iommu_dev_data *dev_data;
-	struct iommu_group *group;
-	u16 alias;
-	int ret;
-
-	if (dev->archdata.iommu)
-		return 0;
-
-	dev_data = find_dev_data(get_device_id(dev));
-	if (!dev_data)
-		return -ENOMEM;
-
-	alias = amd_iommu_alias_table[dev_data->devid];
-	if (alias != dev_data->devid) {
-		struct iommu_dev_data *alias_data;
+	while (!bus->self) {
+		if (!pci_is_root_bus(bus))
+			bus = bus->parent;
+		else
+			return ERR_PTR(-ENODEV);
+	}
 
-		alias_data = find_dev_data(alias);
-		if (alias_data == NULL) {
-			pr_err("AMD-Vi: Warning: Unhandled device %s\n",
-					dev_name(dev));
-			free_dev_data(dev_data);
-			return -ENOTSUPP;
-		}
-		dev_data->alias_data = alias_data;
+	return bus;
+}
 
-		dma_pdev = pci_get_bus_and_slot(alias >> 8, alias & 0xff);
-	}
+#define REQ_ACS_FLAGS	(PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
 
-	if (dma_pdev == NULL)
-		dma_pdev = pci_dev_get(pdev);
+static struct pci_dev *get_isolation_root(struct pci_dev *pdev)
+{
+	struct pci_dev *dma_pdev = pdev;
 
 	/* Account for quirked devices */
 	swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev));
@@ -330,14 +315,9 @@ static int iommu_init_device(struct device *dev)
 	 * Finding the next device may require skipping virtual buses.
 	 */
 	while (!pci_is_root_bus(dma_pdev->bus)) {
-		struct pci_bus *bus = dma_pdev->bus;
-
-		while (!bus->self) {
-			if (!pci_is_root_bus(bus))
-				bus = bus->parent;
-			else
-				goto root_bus;
-		}
+		struct pci_bus *bus = find_hosted_bus(dma_pdev->bus);
+		if (IS_ERR(bus))
+			break;
 
 		if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS))
 			break;
@@ -345,19 +325,137 @@ static int iommu_init_device(struct device *dev)
 		swap_pci_ref(&dma_pdev, pci_dev_get(bus->self));
 	}
 
-root_bus:
-	group = iommu_group_get(&dma_pdev->dev);
-	pci_dev_put(dma_pdev);
+	return dma_pdev;
+}
+
+static int use_pdev_iommu_group(struct pci_dev *pdev, struct device *dev)
+{
+	struct iommu_group *group = iommu_group_get(&pdev->dev);
+	int ret;
+
 	if (!group) {
 		group = iommu_group_alloc();
 		if (IS_ERR(group))
 			return PTR_ERR(group);
+
+		WARN_ON(&pdev->dev != dev);
 	}
 
 	ret = iommu_group_add_device(group, dev);
-
 	iommu_group_put(group);
+	return ret;
+}
+
+static int use_dev_data_iommu_group(struct iommu_dev_data *dev_data,
+				    struct device *dev)
+{
+	if (!dev_data->group) {
+		struct iommu_group *group = iommu_group_alloc();
+		if (IS_ERR(group))
+			return PTR_ERR(group);
+
+		dev_data->group = group;
+	}
+
+	return iommu_group_add_device(dev_data->group, dev);
+}
+
+static int init_iommu_group(struct device *dev)
+{
+	struct iommu_dev_data *dev_data;
+	struct iommu_group *group;
+	struct pci_dev *dma_pdev;
+	int ret;
+
+	group = iommu_group_get(dev);
+	if (group) {
+		iommu_group_put(group);
+		return 0;
+	}
+
+	dev_data = find_dev_data(get_device_id(dev));
+	if (!dev_data)
+		return -ENOMEM;
+
+	if (dev_data->alias_data) {
+		u16 alias;
+		struct pci_bus *bus;
+
+		if (dev_data->alias_data->group)
+			goto use_group;
+
+		/*
+		 * If the alias device exists, it's effectively just a first
+		 * level quirk for finding the DMA source.
+		 */
+		alias = amd_iommu_alias_table[dev_data->devid];
+		dma_pdev = pci_get_bus_and_slot(alias >> 8, alias & 0xff);
+		if (dma_pdev) {
+			dma_pdev = get_isolation_root(dma_pdev);
+			goto use_pdev;
+		}
+
+		/*
+		 * If the alias is virtual, try to find a parent device
+		 * and test whether the IOMMU group is actualy rooted above
+		 * the alias.  Be careful to also test the parent device if
+		 * we think the alias is the root of the group.
+		 */
+		bus = pci_find_bus(0, alias >> 8);
+		if (!bus)
+			goto use_group;
+
+		bus = find_hosted_bus(bus);
+		if (IS_ERR(bus) || !bus->self)
+			goto use_group;
+
+		dma_pdev = get_isolation_root(pci_dev_get(bus->self));
+		if (dma_pdev != bus->self || (dma_pdev->multifunction &&
+		    !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)))
+			goto use_pdev;
+
+		pci_dev_put(dma_pdev);
+		goto use_group;
+	}
+
+	dma_pdev = get_isolation_root(pci_dev_get(to_pci_dev(dev)));
+use_pdev:
+	ret = use_pdev_iommu_group(dma_pdev, dev);
+	pci_dev_put(dma_pdev);
+	return ret;
+use_group:
+	return use_dev_data_iommu_group(dev_data->alias_data, dev);
+}
+
+static int iommu_init_device(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct iommu_dev_data *dev_data;
+	u16 alias;
+	int ret;
+
+	if (dev->archdata.iommu)
+		return 0;
+
+	dev_data = find_dev_data(get_device_id(dev));
+	if (!dev_data)
+		return -ENOMEM;
+
+	alias = amd_iommu_alias_table[dev_data->devid];
+	if (alias != dev_data->devid) {
+		struct iommu_dev_data *alias_data;
+
+		alias_data = find_dev_data(alias);
+		if (alias_data == NULL) {
+			pr_err("AMD-Vi: Warning: Unhandled device %s\n",
+					dev_name(dev));
+			free_dev_data(dev_data);
+			return -ENOTSUPP;
+		}
+		dev_data->alias_data = alias_data;
+	}
 
+	ret = init_iommu_group(dev);
 	if (ret)
 		return ret;
 
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index c9aa3d0..e38ab43 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -426,6 +426,7 @@ struct iommu_dev_data {
 	struct iommu_dev_data *alias_data;/* The alias dev_data */
 	struct protection_domain *domain; /* Domain the device is bound to */
 	atomic_t bind;			  /* Domain attach reference count */
+	struct iommu_group *group;	  /* IOMMU group for virtual aliases */
 	u16 devid;			  /* PCI Device ID */
 	bool iommu_v2;			  /* Device can make use of IOMMUv2 */
 	bool passthrough;		  /* Default for device is pt_domain */
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 7fe44f8..da1975d 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -25,6 +25,8 @@
 #include <linux/list.h>
 #include <linux/memblock.h>
 #include <linux/export.h>
+#include <linux/of_platform.h>
+#include <linux/of.h>
 
 #include <asm/cacheflush.h>
 #include <asm/pgtable.h>
@@ -576,6 +578,7 @@ static int exynos_sysmmu_probe(struct platform_device *pdev)
 	int i, ret;
 	struct device *dev;
 	struct sysmmu_drvdata *data;
+	struct sysmmu_platform_data *platdata;
 
 	dev = &pdev->dev;
 
@@ -634,9 +637,21 @@ static int exynos_sysmmu_probe(struct platform_device *pdev)
 		}
 	}
 
+	if(dev->of_node) {
+		platdata = devm_kzalloc(dev, sizeof(*platdata), GFP_KERNEL);
+		if (!platdata) {
+			dev_dbg(dev, "memory allocation for pdata failed\n");
+			goto err_irq;
+		}
+
+		platdata->clockname = SYSMMU_CLOCK_NAME;
+		platdata->dbgname = (char *)dev->of_node->name;
+		dev->platform_data = platdata;
+	}
+
 	if (dev_get_platdata(dev)) {
 		char *deli, *beg;
-		struct sysmmu_platform_data *platdata = dev_get_platdata(dev);
+		platdata = dev_get_platdata(dev);
 
 		beg = platdata->clockname;
 
@@ -670,8 +685,7 @@ static int exynos_sysmmu_probe(struct platform_device *pdev)
 
 	__set_fault_handler(data, &default_fault_handler);
 
-	if (dev->parent)
-		pm_runtime_enable(dev);
+	pm_runtime_enable(dev);
 
 	dev_dbg(dev, "(%s) Initialized\n", data->dbgname);
 	return 0;
@@ -693,11 +707,20 @@ err_alloc:
 	return ret;
 }
 
+static struct of_device_id iommu_match_types[] = {
+	{
+		.compatible = "samsung,exynos5-sysmmu",
+	}, {
+		/* end node */
+	}
+};
+
 static struct platform_driver exynos_sysmmu_driver = {
 	.probe		= exynos_sysmmu_probe,
 	.driver		= {
 		.owner		= THIS_MODULE,
 		.name		= "exynos-sysmmu",
+		.of_match_table = iommu_match_types,
 	}
 };
 
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 0badfa4..f7fd3d0 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2320,8 +2320,39 @@ static int domain_add_dev_info(struct dmar_domain *domain,
 	return 0;
 }
 
+static bool device_has_rmrr(struct pci_dev *dev)
+{
+	struct dmar_rmrr_unit *rmrr;
+	int i;
+
+	for_each_rmrr_units(rmrr) {
+		for (i = 0; i < rmrr->devices_cnt; i++) {
+			/*
+			 * Return TRUE if this RMRR contains the device that
+			 * is passed in.
+			 */
+			if (rmrr->devices[i] == dev)
+				return true;
+		}
+	}
+	return false;
+}
+
 static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
 {
+
+	/*
+	 * We want to prevent any device associated with an RMRR from
+	 * getting placed into the SI Domain. This is done because
+	 * problems exist when devices are moved in and out of domains
+	 * and their respective RMRR info is lost. We exempt USB devices
+	 * from this process due to their usage of RMRRs that are known
+	 * to not be needed after BIOS hand-off to OS.
+	 */
+	if (device_has_rmrr(pdev) &&
+	    (pdev->class >> 8) != PCI_CLASS_SERIAL_USB)
+		return 0;
+
 	if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
 		return 1;
 
diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c
index c16e8fc..4c9db62 100644
--- a/drivers/iommu/tegra-gart.c
+++ b/drivers/iommu/tegra-gart.c
@@ -398,6 +398,7 @@ static int tegra_gart_probe(struct platform_device *pdev)
 	do_gart_setup(gart, NULL);
 
 	gart_handle = gart;
+	bus_set_iommu(&platform_bus_type, &gart_iommu_ops);
 	return 0;
 
 fail:
@@ -450,7 +451,6 @@ static struct platform_driver tegra_gart_driver = {
 
 static int __devinit tegra_gart_init(void)
 {
-	bus_set_iommu(&platform_bus_type, &gart_iommu_ops);
 	return platform_driver_register(&tegra_gart_driver);
 }
 
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index c0f7a42..25c1210 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -34,13 +34,11 @@
 #include <linux/of_iommu.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <linux/tegra-ahb.h>
 
 #include <asm/page.h>
 #include <asm/cacheflush.h>
 
-#include <mach/iomap.h>
-#include <mach/tegra-ahb.h>
-
 enum smmu_hwgrp {
 	HWGRP_AFI,
 	HWGRP_AVPC,
@@ -696,10 +694,8 @@ static void __smmu_iommu_unmap(struct smmu_as *as, dma_addr_t iova)
 	*pte = _PTE_VACANT(iova);
 	FLUSH_CPU_DCACHE(pte, page, sizeof(*pte));
 	flush_ptc_and_tlb(as->smmu, as, iova, pte, page, 0);
-	if (!--(*count)) {
+	if (!--(*count))
 		free_ptbl(as, iova);
-		smmu_flush_regs(as->smmu, 0);
-	}
 }
 
 static void __smmu_iommu_map_pfn(struct smmu_as *as, dma_addr_t iova,
@@ -1234,6 +1230,7 @@ static int tegra_smmu_probe(struct platform_device *pdev)
 
 	smmu_debugfs_create(smmu);
 	smmu_handle = smmu;
+	bus_set_iommu(&platform_bus_type, &smmu_iommu_ops);
 	return 0;
 }
 
@@ -1278,7 +1275,6 @@ static struct platform_driver tegra_smmu_driver = {
 
 static int __devinit tegra_smmu_init(void)
 {
-	bus_set_iommu(&platform_bus_type, &smmu_iommu_ops);
 	return platform_driver_register(&tegra_smmu_driver);
 }
 
diff --git a/drivers/ipack/Kconfig b/drivers/ipack/Kconfig
new file mode 100644
index 0000000..3949e55
--- /dev/null
+++ b/drivers/ipack/Kconfig
@@ -0,0 +1,24 @@
+#
+# IPACK configuration.
+#
+
+menuconfig IPACK_BUS
+	tristate "IndustryPack bus support"
+	depends on HAS_IOMEM
+	---help---
+	  This option provides support for the IndustryPack framework.  There
+	  are IndustryPack carrier boards, which interface another bus (such as
+	  PCI) to an IndustryPack bus, and IndustryPack modules, that are
+	  hosted on these buses.  While IndustryPack modules can provide a
+	  large variety of functionality, they are most often found in
+	  industrial control applications.
+
+	  Say N if unsure.
+
+if IPACK_BUS
+
+source "drivers/ipack/carriers/Kconfig"
+
+source "drivers/ipack/devices/Kconfig"
+
+endif # IPACK
diff --git a/drivers/ipack/Makefile b/drivers/ipack/Makefile
new file mode 100644
index 0000000..6f14ade
--- /dev/null
+++ b/drivers/ipack/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the IPACK bridge device drivers.
+#
+obj-$(CONFIG_IPACK_BUS)		+= ipack.o
+obj-y				+= devices/
+obj-y				+= carriers/
diff --git a/drivers/ipack/carriers/Kconfig b/drivers/ipack/carriers/Kconfig
new file mode 100644
index 0000000..922ff5c
--- /dev/null
+++ b/drivers/ipack/carriers/Kconfig
@@ -0,0 +1,7 @@
+config BOARD_TPCI200
+	tristate "Support for the TEWS TPCI-200 IndustryPack carrier board"
+	depends on IPACK_BUS
+	depends on PCI
+	help
+	  This driver adds support for the TEWS TPCI200 IndustryPack carrier board.
+	default n
diff --git a/drivers/ipack/carriers/Makefile b/drivers/ipack/carriers/Makefile
new file mode 100644
index 0000000..d8b7645
--- /dev/null
+++ b/drivers/ipack/carriers/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_BOARD_TPCI200) += tpci200.o
diff --git a/drivers/ipack/carriers/tpci200.c b/drivers/ipack/carriers/tpci200.c
new file mode 100644
index 0000000..0246b1f
--- /dev/null
+++ b/drivers/ipack/carriers/tpci200.c
@@ -0,0 +1,627 @@
+/**
+ * tpci200.c
+ *
+ * driver for the TEWS TPCI-200 device
+ *
+ * Copyright (C) 2009-2012 CERN (www.cern.ch)
+ * Author: Nicolas Serafini, EIC2 SA
+ * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
+ *
+ * This program is free software; 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/module.h>
+#include <linux/slab.h>
+#include "tpci200.h"
+
+static const u16 tpci200_status_timeout[] = {
+	TPCI200_A_TIMEOUT,
+	TPCI200_B_TIMEOUT,
+	TPCI200_C_TIMEOUT,
+	TPCI200_D_TIMEOUT,
+};
+
+static const u16 tpci200_status_error[] = {
+	TPCI200_A_ERROR,
+	TPCI200_B_ERROR,
+	TPCI200_C_ERROR,
+	TPCI200_D_ERROR,
+};
+
+static const size_t tpci200_space_size[IPACK_SPACE_COUNT] = {
+	[IPACK_IO_SPACE]    = TPCI200_IO_SPACE_SIZE,
+	[IPACK_ID_SPACE]    = TPCI200_ID_SPACE_SIZE,
+	[IPACK_INT_SPACE]   = TPCI200_INT_SPACE_SIZE,
+	[IPACK_MEM8_SPACE]  = TPCI200_MEM8_SPACE_SIZE,
+	[IPACK_MEM16_SPACE] = TPCI200_MEM16_SPACE_SIZE,
+};
+
+static const size_t tpci200_space_interval[IPACK_SPACE_COUNT] = {
+	[IPACK_IO_SPACE]    = TPCI200_IO_SPACE_INTERVAL,
+	[IPACK_ID_SPACE]    = TPCI200_ID_SPACE_INTERVAL,
+	[IPACK_INT_SPACE]   = TPCI200_INT_SPACE_INTERVAL,
+	[IPACK_MEM8_SPACE]  = TPCI200_MEM8_SPACE_INTERVAL,
+	[IPACK_MEM16_SPACE] = TPCI200_MEM16_SPACE_INTERVAL,
+};
+
+static struct tpci200_board *check_slot(struct ipack_device *dev)
+{
+	struct tpci200_board *tpci200;
+
+	if (dev == NULL)
+		return NULL;
+
+
+	tpci200 = dev_get_drvdata(dev->bus->parent);
+
+	if (tpci200 == NULL) {
+		dev_info(&dev->dev, "carrier board not found\n");
+		return NULL;
+	}
+
+	if (dev->slot >= TPCI200_NB_SLOT) {
+		dev_info(&dev->dev,
+			 "Slot [%d:%d] doesn't exist! Last tpci200 slot is %d.\n",
+			 dev->bus->bus_nr, dev->slot, TPCI200_NB_SLOT-1);
+		return NULL;
+	}
+
+	return tpci200;
+}
+
+static void tpci200_clear_mask(struct tpci200_board *tpci200,
+			       __le16 __iomem *addr, u16 mask)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&tpci200->regs_lock, flags);
+	iowrite16(ioread16(addr) & (~mask), addr);
+	spin_unlock_irqrestore(&tpci200->regs_lock, flags);
+}
+
+static void tpci200_set_mask(struct tpci200_board *tpci200,
+			     __le16 __iomem *addr, u16 mask)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&tpci200->regs_lock, flags);
+	iowrite16(ioread16(addr) | mask, addr);
+	spin_unlock_irqrestore(&tpci200->regs_lock, flags);
+}
+
+static void tpci200_unregister(struct tpci200_board *tpci200)
+{
+	free_irq(tpci200->info->pdev->irq, (void *) tpci200);
+
+	pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs);
+	pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
+
+	pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
+	pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
+	pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR);
+	pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
+	pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR);
+
+	pci_disable_device(tpci200->info->pdev);
+	pci_dev_put(tpci200->info->pdev);
+}
+
+static void tpci200_enable_irq(struct tpci200_board *tpci200,
+			       int islot)
+{
+	tpci200_set_mask(tpci200,
+			&tpci200->info->interface_regs->control[islot],
+			TPCI200_INT0_EN | TPCI200_INT1_EN);
+}
+
+static void tpci200_disable_irq(struct tpci200_board *tpci200,
+				int islot)
+{
+	tpci200_clear_mask(tpci200,
+			&tpci200->info->interface_regs->control[islot],
+			TPCI200_INT0_EN | TPCI200_INT1_EN);
+}
+
+static irqreturn_t tpci200_slot_irq(struct slot_irq *slot_irq)
+{
+	irqreturn_t ret;
+
+	if (!slot_irq)
+		return -ENODEV;
+	ret = slot_irq->handler(slot_irq->arg);
+
+	return ret;
+}
+
+static irqreturn_t tpci200_interrupt(int irq, void *dev_id)
+{
+	struct tpci200_board *tpci200 = (struct tpci200_board *) dev_id;
+	struct slot_irq *slot_irq;
+	irqreturn_t ret;
+	u16 status_reg;
+	int i;
+
+	/* Read status register */
+	status_reg = ioread16(&tpci200->info->interface_regs->status);
+
+	/* Did we cause the interrupt? */
+	if (!(status_reg & TPCI200_SLOT_INT_MASK))
+		return IRQ_NONE;
+
+	/* callback to the IRQ handler for the corresponding slot */
+	rcu_read_lock();
+	for (i = 0; i < TPCI200_NB_SLOT; i++) {
+		if (!(status_reg & ((TPCI200_A_INT0 | TPCI200_A_INT1) << (2 * i))))
+			continue;
+		slot_irq = rcu_dereference(tpci200->slots[i].irq);
+		ret = tpci200_slot_irq(slot_irq);
+		if (ret == -ENODEV) {
+			dev_info(&tpci200->info->pdev->dev,
+				 "No registered ISR for slot [%d:%d]!. IRQ will be disabled.\n",
+				 tpci200->number, i);
+			tpci200_disable_irq(tpci200, i);
+		}
+	}
+	rcu_read_unlock();
+
+	return IRQ_HANDLED;
+}
+
+static int tpci200_free_irq(struct ipack_device *dev)
+{
+	struct slot_irq *slot_irq;
+	struct tpci200_board *tpci200;
+
+	tpci200 = check_slot(dev);
+	if (tpci200 == NULL)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&tpci200->mutex))
+		return -ERESTARTSYS;
+
+	if (tpci200->slots[dev->slot].irq == NULL) {
+		mutex_unlock(&tpci200->mutex);
+		return -EINVAL;
+	}
+
+	tpci200_disable_irq(tpci200, dev->slot);
+	slot_irq = tpci200->slots[dev->slot].irq;
+	/* uninstall handler */
+	RCU_INIT_POINTER(tpci200->slots[dev->slot].irq, NULL);
+	synchronize_rcu();
+	kfree(slot_irq);
+	mutex_unlock(&tpci200->mutex);
+	return 0;
+}
+
+static int tpci200_request_irq(struct ipack_device *dev,
+			       irqreturn_t (*handler)(void *), void *arg)
+{
+	int res = 0;
+	struct slot_irq *slot_irq;
+	struct tpci200_board *tpci200;
+
+	tpci200 = check_slot(dev);
+	if (tpci200 == NULL)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&tpci200->mutex))
+		return -ERESTARTSYS;
+
+	if (tpci200->slots[dev->slot].irq != NULL) {
+		dev_err(&dev->dev,
+			"Slot [%d:%d] IRQ already registered !\n",
+			dev->bus->bus_nr,
+			dev->slot);
+		res = -EINVAL;
+		goto out_unlock;
+	}
+
+	slot_irq = kzalloc(sizeof(struct slot_irq), GFP_KERNEL);
+	if (slot_irq == NULL) {
+		dev_err(&dev->dev,
+			"Slot [%d:%d] unable to allocate memory for IRQ !\n",
+			dev->bus->bus_nr, dev->slot);
+		res = -ENOMEM;
+		goto out_unlock;
+	}
+
+	/*
+	 * WARNING: Setup Interrupt Vector in the IndustryPack device
+	 * before an IRQ request.
+	 * Read the User Manual of your IndustryPack device to know
+	 * where to write the vector in memory.
+	 */
+	slot_irq->handler = handler;
+	slot_irq->arg = arg;
+	slot_irq->holder = dev;
+
+	rcu_assign_pointer(tpci200->slots[dev->slot].irq, slot_irq);
+	tpci200_enable_irq(tpci200, dev->slot);
+
+out_unlock:
+	mutex_unlock(&tpci200->mutex);
+	return res;
+}
+
+static int tpci200_register(struct tpci200_board *tpci200)
+{
+	int i;
+	int res;
+	phys_addr_t ioidint_base;
+	unsigned short slot_ctrl;
+
+	if (pci_enable_device(tpci200->info->pdev) < 0)
+		return -ENODEV;
+
+	/* Request IP interface register (Bar 2) */
+	res = pci_request_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR,
+				 "Carrier IP interface registers");
+	if (res) {
+		dev_err(&tpci200->info->pdev->dev,
+			"(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 !",
+			tpci200->info->pdev->bus->number,
+			tpci200->info->pdev->devfn);
+		goto out_disable_pci;
+	}
+
+	/* Request IO ID INT space (Bar 3) */
+	res = pci_request_region(tpci200->info->pdev,
+				 TPCI200_IO_ID_INT_SPACES_BAR,
+				 "Carrier IO ID INT space");
+	if (res) {
+		dev_err(&tpci200->info->pdev->dev,
+			"(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 3 !",
+			tpci200->info->pdev->bus->number,
+			tpci200->info->pdev->devfn);
+		goto out_release_ip_space;
+	}
+
+	/* Request MEM8 space (Bar 5) */
+	res = pci_request_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR,
+				 "Carrier MEM8 space");
+	if (res) {
+		dev_err(&tpci200->info->pdev->dev,
+			"(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 5!",
+			tpci200->info->pdev->bus->number,
+			tpci200->info->pdev->devfn);
+		goto out_release_ioid_int_space;
+	}
+
+	/* Request MEM16 space (Bar 4) */
+	res = pci_request_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR,
+				 "Carrier MEM16 space");
+	if (res) {
+		dev_err(&tpci200->info->pdev->dev,
+			"(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!",
+			tpci200->info->pdev->bus->number,
+			tpci200->info->pdev->devfn);
+		goto out_release_mem8_space;
+	}
+
+	/* Map internal tpci200 driver user space */
+	tpci200->info->interface_regs =
+		ioremap_nocache(pci_resource_start(tpci200->info->pdev,
+					   TPCI200_IP_INTERFACE_BAR),
+			TPCI200_IFACE_SIZE);
+
+	/* Initialize lock that protects interface_regs */
+	spin_lock_init(&tpci200->regs_lock);
+
+	ioidint_base = pci_resource_start(tpci200->info->pdev,
+					  TPCI200_IO_ID_INT_SPACES_BAR);
+	tpci200->mod_mem[IPACK_IO_SPACE] = ioidint_base + TPCI200_IO_SPACE_OFF;
+	tpci200->mod_mem[IPACK_ID_SPACE] = ioidint_base + TPCI200_ID_SPACE_OFF;
+	tpci200->mod_mem[IPACK_INT_SPACE] =
+		ioidint_base + TPCI200_INT_SPACE_OFF;
+	tpci200->mod_mem[IPACK_MEM8_SPACE] =
+		pci_resource_start(tpci200->info->pdev,
+				   TPCI200_MEM8_SPACE_BAR);
+	tpci200->mod_mem[IPACK_MEM16_SPACE] =
+		pci_resource_start(tpci200->info->pdev,
+				   TPCI200_MEM16_SPACE_BAR);
+
+	/* Set the default parameters of the slot
+	 * INT0 disabled, level sensitive
+	 * INT1 disabled, level sensitive
+	 * error interrupt disabled
+	 * timeout interrupt disabled
+	 * recover time disabled
+	 * clock rate 8 MHz
+	 */
+	slot_ctrl = 0;
+	for (i = 0; i < TPCI200_NB_SLOT; i++)
+		writew(slot_ctrl, &tpci200->info->interface_regs->control[i]);
+
+	res = request_irq(tpci200->info->pdev->irq,
+			  tpci200_interrupt, IRQF_SHARED,
+			  KBUILD_MODNAME, (void *) tpci200);
+	if (res) {
+		dev_err(&tpci200->info->pdev->dev,
+			"(bn 0x%X, sn 0x%X) unable to register IRQ !",
+			tpci200->info->pdev->bus->number,
+			tpci200->info->pdev->devfn);
+		goto out_release_ioid_int_space;
+	}
+
+	return 0;
+
+out_release_mem8_space:
+	pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
+out_release_ioid_int_space:
+	pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
+out_release_ip_space:
+	pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
+out_disable_pci:
+	pci_disable_device(tpci200->info->pdev);
+	return res;
+}
+
+static int tpci200_get_clockrate(struct ipack_device *dev)
+{
+	struct tpci200_board *tpci200 = check_slot(dev);
+	__le16 __iomem *addr;
+
+	if (!tpci200)
+		return -ENODEV;
+
+	addr = &tpci200->info->interface_regs->control[dev->slot];
+	return (ioread16(addr) & TPCI200_CLK32) ? 32 : 8;
+}
+
+static int tpci200_set_clockrate(struct ipack_device *dev, int mherz)
+{
+	struct tpci200_board *tpci200 = check_slot(dev);
+	__le16 __iomem *addr;
+
+	if (!tpci200)
+		return -ENODEV;
+
+	addr = &tpci200->info->interface_regs->control[dev->slot];
+
+	switch (mherz) {
+	case 8:
+		tpci200_clear_mask(tpci200, addr, TPCI200_CLK32);
+		break;
+	case 32:
+		tpci200_set_mask(tpci200, addr, TPCI200_CLK32);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int tpci200_get_error(struct ipack_device *dev)
+{
+	struct tpci200_board *tpci200 = check_slot(dev);
+	__le16 __iomem *addr;
+	u16 mask;
+
+	if (!tpci200)
+		return -ENODEV;
+
+	addr = &tpci200->info->interface_regs->status;
+	mask = tpci200_status_error[dev->slot];
+	return (ioread16(addr) & mask) ? 1 : 0;
+}
+
+static int tpci200_get_timeout(struct ipack_device *dev)
+{
+	struct tpci200_board *tpci200 = check_slot(dev);
+	__le16 __iomem *addr;
+	u16 mask;
+
+	if (!tpci200)
+		return -ENODEV;
+
+	addr = &tpci200->info->interface_regs->status;
+	mask = tpci200_status_timeout[dev->slot];
+
+	return (ioread16(addr) & mask) ? 1 : 0;
+}
+
+static int tpci200_reset_timeout(struct ipack_device *dev)
+{
+	struct tpci200_board *tpci200 = check_slot(dev);
+	__le16 __iomem *addr;
+	u16 mask;
+
+	if (!tpci200)
+		return -ENODEV;
+
+	addr = &tpci200->info->interface_regs->status;
+	mask = tpci200_status_timeout[dev->slot];
+
+	iowrite16(mask, addr);
+	return 0;
+}
+
+static void tpci200_uninstall(struct tpci200_board *tpci200)
+{
+	tpci200_unregister(tpci200);
+	kfree(tpci200->slots);
+}
+
+static const struct ipack_bus_ops tpci200_bus_ops = {
+	.request_irq = tpci200_request_irq,
+	.free_irq = tpci200_free_irq,
+	.get_clockrate = tpci200_get_clockrate,
+	.set_clockrate = tpci200_set_clockrate,
+	.get_error     = tpci200_get_error,
+	.get_timeout   = tpci200_get_timeout,
+	.reset_timeout = tpci200_reset_timeout,
+};
+
+static int tpci200_install(struct tpci200_board *tpci200)
+{
+	int res;
+
+	tpci200->slots = kzalloc(
+		TPCI200_NB_SLOT * sizeof(struct tpci200_slot), GFP_KERNEL);
+	if (tpci200->slots == NULL)
+		return -ENOMEM;
+
+	res = tpci200_register(tpci200);
+	if (res) {
+		kfree(tpci200->slots);
+		tpci200->slots = NULL;
+		return res;
+	}
+
+	mutex_init(&tpci200->mutex);
+	return 0;
+}
+
+static void tpci200_release_device(struct ipack_device *dev)
+{
+	kfree(dev);
+}
+
+static int tpci200_create_device(struct tpci200_board *tpci200, int i)
+{
+	enum ipack_space space;
+	struct ipack_device *dev =
+		kzalloc(sizeof(struct ipack_device), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+	dev->slot = i;
+	dev->bus = tpci200->info->ipack_bus;
+	dev->release = tpci200_release_device;
+
+	for (space = 0; space < IPACK_SPACE_COUNT; space++) {
+		dev->region[space].start =
+			tpci200->mod_mem[space]
+			+ tpci200_space_interval[space] * i;
+		dev->region[space].size = tpci200_space_size[space];
+	}
+	return ipack_device_register(dev);
+}
+
+static int tpci200_pci_probe(struct pci_dev *pdev,
+			     const struct pci_device_id *id)
+{
+	int ret, i;
+	struct tpci200_board *tpci200;
+	u32 reg32;
+
+	tpci200 = kzalloc(sizeof(struct tpci200_board), GFP_KERNEL);
+	if (!tpci200)
+		return -ENOMEM;
+
+	tpci200->info = kzalloc(sizeof(struct tpci200_infos), GFP_KERNEL);
+	if (!tpci200->info) {
+		ret = -ENOMEM;
+		goto out_err_info;
+	}
+
+	pci_dev_get(pdev);
+
+	/* Obtain a mapping of the carrier's PCI configuration registers */
+	ret = pci_request_region(pdev, TPCI200_CFG_MEM_BAR,
+				 KBUILD_MODNAME " Configuration Memory");
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to allocate PCI Configuration Memory");
+		ret = -EBUSY;
+		goto out_err_pci_request;
+	}
+	tpci200->info->cfg_regs = ioremap_nocache(
+			pci_resource_start(pdev, TPCI200_CFG_MEM_BAR),
+			pci_resource_len(pdev, TPCI200_CFG_MEM_BAR));
+	if (!tpci200->info->cfg_regs) {
+		dev_err(&pdev->dev, "Failed to map PCI Configuration Memory");
+		ret = -EFAULT;
+		goto out_err_ioremap;
+	}
+
+	/* Disable byte swapping for 16 bit IP module access. This will ensure
+	 * that the Industrypack big endian byte order is preserved by the
+	 * carrier. */
+	reg32 = ioread32(tpci200->info->cfg_regs + LAS1_DESC);
+	reg32 |= 1 << LAS_BIT_BIGENDIAN;
+	iowrite32(reg32, tpci200->info->cfg_regs + LAS1_DESC);
+
+	reg32 = ioread32(tpci200->info->cfg_regs + LAS2_DESC);
+	reg32 |= 1 << LAS_BIT_BIGENDIAN;
+	iowrite32(reg32, tpci200->info->cfg_regs + LAS2_DESC);
+
+	/* Save struct pci_dev pointer */
+	tpci200->info->pdev = pdev;
+	tpci200->info->id_table = (struct pci_device_id *)id;
+
+	/* register the device and initialize it */
+	ret = tpci200_install(tpci200);
+	if (ret) {
+		dev_err(&pdev->dev, "error during tpci200 install\n");
+		ret = -ENODEV;
+		goto out_err_install;
+	}
+
+	/* Register the carrier in the industry pack bus driver */
+	tpci200->info->ipack_bus = ipack_bus_register(&pdev->dev,
+						      TPCI200_NB_SLOT,
+						      &tpci200_bus_ops);
+	if (!tpci200->info->ipack_bus) {
+		dev_err(&pdev->dev,
+			"error registering the carrier on ipack driver\n");
+		ret = -EFAULT;
+		goto out_err_bus_register;
+	}
+
+	/* save the bus number given by ipack to logging purpose */
+	tpci200->number = tpci200->info->ipack_bus->bus_nr;
+	dev_set_drvdata(&pdev->dev, tpci200);
+
+	for (i = 0; i < TPCI200_NB_SLOT; i++)
+		tpci200_create_device(tpci200, i);
+	return 0;
+
+out_err_bus_register:
+	tpci200_uninstall(tpci200);
+out_err_install:
+	iounmap(tpci200->info->cfg_regs);
+out_err_ioremap:
+	pci_release_region(pdev, TPCI200_CFG_MEM_BAR);
+out_err_pci_request:
+	pci_dev_put(pdev);
+	kfree(tpci200->info);
+out_err_info:
+	kfree(tpci200);
+	return ret;
+}
+
+static void __tpci200_pci_remove(struct tpci200_board *tpci200)
+{
+	ipack_bus_unregister(tpci200->info->ipack_bus);
+	tpci200_uninstall(tpci200);
+
+	kfree(tpci200->info);
+	kfree(tpci200);
+}
+
+static void tpci200_pci_remove(struct pci_dev *dev)
+{
+	struct tpci200_board *tpci200 = pci_get_drvdata(dev);
+
+	__tpci200_pci_remove(tpci200);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(tpci200_idtable) = {
+	{ TPCI200_VENDOR_ID, TPCI200_DEVICE_ID, TPCI200_SUBVENDOR_ID,
+	  TPCI200_SUBDEVICE_ID },
+	{ 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, tpci200_idtable);
+
+static struct pci_driver tpci200_pci_drv = {
+	.name = "tpci200",
+	.id_table = tpci200_idtable,
+	.probe = tpci200_pci_probe,
+	.remove = tpci200_pci_remove,
+};
+
+module_pci_driver(tpci200_pci_drv);
+
+MODULE_DESCRIPTION("TEWS TPCI-200 device driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ipack/carriers/tpci200.h b/drivers/ipack/carriers/tpci200.h
new file mode 100644
index 0000000..a7a151d
--- /dev/null
+++ b/drivers/ipack/carriers/tpci200.h
@@ -0,0 +1,167 @@
+/**
+ * tpci200.h
+ *
+ * driver for the carrier TEWS TPCI-200
+ *
+ * Copyright (C) 2009-2012 CERN (www.cern.ch)
+ * Author: Nicolas Serafini, EIC2 SA
+ * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
+ *
+ * This program is free software; 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 _TPCI200_H_
+#define _TPCI200_H_
+
+#include <linux/limits.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/swab.h>
+#include <linux/io.h>
+#include <linux/ipack.h>
+
+#define TPCI200_NB_SLOT               0x4
+#define TPCI200_NB_BAR                0x6
+
+#define TPCI200_VENDOR_ID             0x1498
+#define TPCI200_DEVICE_ID             0x30C8
+#define TPCI200_SUBVENDOR_ID          0x1498
+#define TPCI200_SUBDEVICE_ID          0x300A
+
+#define TPCI200_CFG_MEM_BAR           0
+#define TPCI200_IP_INTERFACE_BAR      2
+#define TPCI200_IO_ID_INT_SPACES_BAR  3
+#define TPCI200_MEM16_SPACE_BAR       4
+#define TPCI200_MEM8_SPACE_BAR        5
+
+struct tpci200_regs {
+	__le16	revision;
+	/* writes to control should occur with the mutex held to protect
+	 * read-modify-write operations */
+	__le16  control[4];
+	__le16	reset;
+	__le16	status;
+	u8	reserved[242];
+} __packed;
+
+#define TPCI200_IFACE_SIZE            0x100
+
+#define TPCI200_IO_SPACE_OFF          0x0000
+#define TPCI200_IO_SPACE_INTERVAL     0x0100
+#define TPCI200_IO_SPACE_SIZE         0x0080
+#define TPCI200_ID_SPACE_OFF          0x0080
+#define TPCI200_ID_SPACE_INTERVAL     0x0100
+#define TPCI200_ID_SPACE_SIZE         0x0040
+#define TPCI200_INT_SPACE_OFF         0x00C0
+#define TPCI200_INT_SPACE_INTERVAL    0x0100
+#define TPCI200_INT_SPACE_SIZE        0x0040
+#define TPCI200_IOIDINT_SIZE          0x0400
+
+#define TPCI200_MEM8_SPACE_INTERVAL   0x00400000
+#define TPCI200_MEM8_SPACE_SIZE       0x00400000
+#define TPCI200_MEM16_SPACE_INTERVAL  0x00800000
+#define TPCI200_MEM16_SPACE_SIZE      0x00800000
+
+/* control field in tpci200_regs */
+#define TPCI200_INT0_EN               0x0040
+#define TPCI200_INT1_EN               0x0080
+#define TPCI200_INT0_EDGE             0x0010
+#define TPCI200_INT1_EDGE             0x0020
+#define TPCI200_ERR_INT_EN            0x0008
+#define TPCI200_TIME_INT_EN           0x0004
+#define TPCI200_RECOVER_EN            0x0002
+#define TPCI200_CLK32                 0x0001
+
+/* reset field in tpci200_regs */
+#define TPCI200_A_RESET               0x0001
+#define TPCI200_B_RESET               0x0002
+#define TPCI200_C_RESET               0x0004
+#define TPCI200_D_RESET               0x0008
+
+/* status field in tpci200_regs */
+#define TPCI200_A_TIMEOUT             0x1000
+#define TPCI200_B_TIMEOUT             0x2000
+#define TPCI200_C_TIMEOUT             0x4000
+#define TPCI200_D_TIMEOUT             0x8000
+
+#define TPCI200_A_ERROR               0x0100
+#define TPCI200_B_ERROR               0x0200
+#define TPCI200_C_ERROR               0x0400
+#define TPCI200_D_ERROR               0x0800
+
+#define TPCI200_A_INT0                0x0001
+#define TPCI200_A_INT1                0x0002
+#define TPCI200_B_INT0                0x0004
+#define TPCI200_B_INT1                0x0008
+#define TPCI200_C_INT0                0x0010
+#define TPCI200_C_INT1                0x0020
+#define TPCI200_D_INT0                0x0040
+#define TPCI200_D_INT1                0x0080
+
+#define TPCI200_SLOT_INT_MASK         0x00FF
+
+/* PCI Configuration registers. The PCI bridge is a PLX Technology PCI9030. */
+#define LAS1_DESC		      0x2C
+#define LAS2_DESC		      0x30
+
+/* Bits in the LAS?_DESC registers */
+#define LAS_BIT_BIGENDIAN	      24
+
+#define VME_IOID_SPACE  "IOID"
+#define VME_MEM_SPACE  "MEM"
+
+/**
+ * struct slot_irq - slot IRQ definition.
+ * @vector	Vector number
+ * @handler	Handler called when IRQ arrives
+ * @arg		Handler argument
+ *
+ */
+struct slot_irq {
+	struct ipack_device *holder;
+	int		vector;
+	irqreturn_t	(*handler)(void *);
+	void		*arg;
+};
+
+/**
+ * struct tpci200_slot - data specific to the tpci200 slot.
+ * @slot_id	Slot identification gived to external interface
+ * @irq		Slot IRQ infos
+ * @io_phys	IO physical base address register of the slot
+ * @id_phys	ID physical base address register of the slot
+ * @int_phys	INT physical base address register of the slot
+ * @mem_phys	MEM physical base address register of the slot
+ *
+ */
+struct tpci200_slot {
+	struct slot_irq	    *irq;
+};
+
+/**
+ * struct tpci200_infos - informations specific of the TPCI200 tpci200.
+ * @pci_dev		PCI device
+ * @interface_regs	Pointer to IP interface space (Bar 2)
+ * @ioidint_space	Pointer to IP ID, IO and INT space (Bar 3)
+ * @mem8_space		Pointer to MEM space (Bar 4)
+ *
+ */
+struct tpci200_infos {
+	struct pci_dev			*pdev;
+	struct pci_device_id		*id_table;
+	struct tpci200_regs __iomem	*interface_regs;
+	void __iomem			*cfg_regs;
+	struct ipack_bus_device		*ipack_bus;
+};
+struct tpci200_board {
+	unsigned int		number;
+	struct mutex		mutex;
+	spinlock_t		regs_lock;
+	struct tpci200_slot	*slots;
+	struct tpci200_infos	*info;
+	phys_addr_t             mod_mem[IPACK_SPACE_COUNT];
+};
+
+#endif /* _TPCI200_H_ */
diff --git a/drivers/ipack/devices/Kconfig b/drivers/ipack/devices/Kconfig
new file mode 100644
index 0000000..0b82fdc
--- /dev/null
+++ b/drivers/ipack/devices/Kconfig
@@ -0,0 +1,6 @@
+config SERIAL_IPOCTAL
+	tristate "IndustryPack IP-OCTAL uart support"
+	depends on IPACK_BUS
+	help
+	  This driver supports the IPOCTAL serial port device for the IndustryPack bus.
+	default n
diff --git a/drivers/ipack/devices/Makefile b/drivers/ipack/devices/Makefile
new file mode 100644
index 0000000..6de18bd
--- /dev/null
+++ b/drivers/ipack/devices/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SERIAL_IPOCTAL) += ipoctal.o
diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c
new file mode 100644
index 0000000..576d53d
--- /dev/null
+++ b/drivers/ipack/devices/ipoctal.c
@@ -0,0 +1,753 @@
+/**
+ * ipoctal.c
+ *
+ * driver for the GE IP-OCTAL boards
+ *
+ * Copyright (C) 2009-2012 CERN (www.cern.ch)
+ * Author: Nicolas Serafini, EIC2 SA
+ * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
+ *
+ * This program is free software; 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/device.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/tty_flip.h>
+#include <linux/slab.h>
+#include <linux/atomic.h>
+#include <linux/io.h>
+#include <linux/ipack.h>
+#include "ipoctal.h"
+#include "scc2698.h"
+
+#define IP_OCTAL_ID_SPACE_VECTOR    0x41
+#define IP_OCTAL_NB_BLOCKS          4
+
+static const struct tty_operations ipoctal_fops;
+
+struct ipoctal_channel {
+	struct ipoctal_stats		stats;
+	unsigned int			nb_bytes;
+	wait_queue_head_t		queue;
+	spinlock_t			lock;
+	unsigned int			pointer_read;
+	unsigned int			pointer_write;
+	atomic_t			open;
+	struct tty_port			tty_port;
+	union scc2698_channel __iomem	*regs;
+	union scc2698_block __iomem	*block_regs;
+	unsigned int			board_id;
+	unsigned char			*board_write;
+	u8				isr_rx_rdy_mask;
+	u8				isr_tx_rdy_mask;
+};
+
+struct ipoctal {
+	struct ipack_device		*dev;
+	unsigned int			board_id;
+	struct ipoctal_channel		channel[NR_CHANNELS];
+	unsigned char			write;
+	struct tty_driver		*tty_drv;
+	u8 __iomem			*mem8_space;
+	u8 __iomem			*int_space;
+};
+
+static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty)
+{
+	struct ipoctal_channel *channel;
+
+	channel = dev_get_drvdata(tty->dev);
+
+	iowrite8(CR_ENABLE_RX, &channel->regs->w.cr);
+	return 0;
+}
+
+static int ipoctal_open(struct tty_struct *tty, struct file *file)
+{
+	int res;
+	struct ipoctal_channel *channel;
+
+	channel = dev_get_drvdata(tty->dev);
+
+	if (atomic_read(&channel->open))
+		return -EBUSY;
+
+	tty->driver_data = channel;
+
+	res = tty_port_open(&channel->tty_port, tty, file);
+	if (res)
+		return res;
+
+	atomic_inc(&channel->open);
+	return 0;
+}
+
+static void ipoctal_reset_stats(struct ipoctal_stats *stats)
+{
+	stats->tx = 0;
+	stats->rx = 0;
+	stats->rcv_break = 0;
+	stats->framing_err = 0;
+	stats->overrun_err = 0;
+	stats->parity_err = 0;
+}
+
+static void ipoctal_free_channel(struct ipoctal_channel *channel)
+{
+	ipoctal_reset_stats(&channel->stats);
+	channel->pointer_read = 0;
+	channel->pointer_write = 0;
+	channel->nb_bytes = 0;
+}
+
+static void ipoctal_close(struct tty_struct *tty, struct file *filp)
+{
+	struct ipoctal_channel *channel = tty->driver_data;
+
+	tty_port_close(&channel->tty_port, tty, filp);
+
+	if (atomic_dec_and_test(&channel->open))
+		ipoctal_free_channel(channel);
+}
+
+static int ipoctal_get_icount(struct tty_struct *tty,
+			      struct serial_icounter_struct *icount)
+{
+	struct ipoctal_channel *channel = tty->driver_data;
+
+	icount->cts = 0;
+	icount->dsr = 0;
+	icount->rng = 0;
+	icount->dcd = 0;
+	icount->rx = channel->stats.rx;
+	icount->tx = channel->stats.tx;
+	icount->frame = channel->stats.framing_err;
+	icount->parity = channel->stats.parity_err;
+	icount->brk = channel->stats.rcv_break;
+	return 0;
+}
+
+static void ipoctal_irq_rx(struct ipoctal_channel *channel,
+			   struct tty_struct *tty, u8 sr)
+{
+	unsigned char value;
+	unsigned char flag = TTY_NORMAL;
+	u8 isr;
+
+	do {
+		value = ioread8(&channel->regs->r.rhr);
+		/* Error: count statistics */
+		if (sr & SR_ERROR) {
+			iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr);
+
+			if (sr & SR_OVERRUN_ERROR) {
+				channel->stats.overrun_err++;
+				/* Overrun doesn't affect the current character*/
+				tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+			}
+			if (sr & SR_PARITY_ERROR) {
+				channel->stats.parity_err++;
+				flag = TTY_PARITY;
+			}
+			if (sr & SR_FRAMING_ERROR) {
+				channel->stats.framing_err++;
+				flag = TTY_FRAME;
+			}
+			if (sr & SR_RECEIVED_BREAK) {
+				iowrite8(CR_CMD_RESET_BREAK_CHANGE, &channel->regs->w.cr);
+				channel->stats.rcv_break++;
+				flag = TTY_BREAK;
+			}
+		}
+		tty_insert_flip_char(tty, value, flag);
+
+		/* Check if there are more characters in RX FIFO
+		 * If there are more, the isr register for this channel
+		 * has enabled the RxRDY|FFULL bit.
+		 */
+		isr = ioread8(&channel->block_regs->r.isr);
+		sr = ioread8(&channel->regs->r.sr);
+	} while (isr & channel->isr_rx_rdy_mask);
+
+	tty_flip_buffer_push(tty);
+}
+
+static void ipoctal_irq_tx(struct ipoctal_channel *channel)
+{
+	unsigned char value;
+	unsigned int *pointer_write = &channel->pointer_write;
+
+	if (channel->nb_bytes <= 0) {
+		channel->nb_bytes = 0;
+		return;
+	}
+
+	value = channel->tty_port.xmit_buf[*pointer_write];
+	iowrite8(value, &channel->regs->w.thr);
+	channel->stats.tx++;
+	(*pointer_write)++;
+	*pointer_write = *pointer_write % PAGE_SIZE;
+	channel->nb_bytes--;
+
+	if ((channel->nb_bytes == 0) &&
+	    (waitqueue_active(&channel->queue))) {
+
+		if (channel->board_id != IPACK1_DEVICE_ID_SBS_OCTAL_485) {
+			*channel->board_write = 1;
+			wake_up_interruptible(&channel->queue);
+		}
+	}
+}
+
+static void ipoctal_irq_channel(struct ipoctal_channel *channel)
+{
+	u8 isr, sr;
+	struct tty_struct *tty;
+
+	/* If there is no client, skip the check */
+	if (!atomic_read(&channel->open))
+		return;
+
+	tty = tty_port_tty_get(&channel->tty_port);
+	if (!tty)
+		return;
+	/* The HW is organized in pair of channels.  See which register we need
+	 * to read from */
+	isr = ioread8(&channel->block_regs->r.isr);
+	sr = ioread8(&channel->regs->r.sr);
+
+	/* In case of RS-485, change from TX to RX when finishing TX.
+	 * Half-duplex. */
+	if ((channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) &&
+	    (sr & SR_TX_EMPTY) && (channel->nb_bytes == 0)) {
+		iowrite8(CR_DISABLE_TX, &channel->regs->w.cr);
+		iowrite8(CR_CMD_NEGATE_RTSN, &channel->regs->w.cr);
+		iowrite8(CR_ENABLE_RX, &channel->regs->w.cr);
+		*channel->board_write = 1;
+		wake_up_interruptible(&channel->queue);
+	}
+
+	/* RX data */
+	if ((isr & channel->isr_rx_rdy_mask) && (sr & SR_RX_READY))
+		ipoctal_irq_rx(channel, tty, sr);
+
+	/* TX of each character */
+	if ((isr & channel->isr_tx_rdy_mask) && (sr & SR_TX_READY))
+		ipoctal_irq_tx(channel);
+
+	tty_flip_buffer_push(tty);
+	tty_kref_put(tty);
+}
+
+static irqreturn_t ipoctal_irq_handler(void *arg)
+{
+	unsigned int i;
+	struct ipoctal *ipoctal = (struct ipoctal *) arg;
+
+	/* Check all channels */
+	for (i = 0; i < NR_CHANNELS; i++)
+		ipoctal_irq_channel(&ipoctal->channel[i]);
+
+	/* Clear the IPack device interrupt */
+	readw(ipoctal->int_space + ACK_INT_REQ0);
+	readw(ipoctal->int_space + ACK_INT_REQ1);
+
+	return IRQ_HANDLED;
+}
+
+static const struct tty_port_operations ipoctal_tty_port_ops = {
+	.dtr_rts = NULL,
+	.activate = ipoctal_port_activate,
+};
+
+static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
+			     unsigned int slot)
+{
+	int res;
+	int i;
+	struct tty_driver *tty;
+	char name[20];
+	struct ipoctal_channel *channel;
+	struct ipack_region *region;
+	void __iomem *addr;
+	union scc2698_channel __iomem *chan_regs;
+	union scc2698_block __iomem *block_regs;
+
+	ipoctal->board_id = ipoctal->dev->id_device;
+
+	region = &ipoctal->dev->region[IPACK_IO_SPACE];
+	addr = devm_ioremap_nocache(&ipoctal->dev->dev,
+				    region->start, region->size);
+	if (!addr) {
+		dev_err(&ipoctal->dev->dev,
+			"Unable to map slot [%d:%d] IO space!\n",
+			bus_nr, slot);
+		return -EADDRNOTAVAIL;
+	}
+	/* Save the virtual address to access the registers easily */
+	chan_regs =
+		(union scc2698_channel __iomem *) addr;
+	block_regs =
+		(union scc2698_block __iomem *) addr;
+
+	region = &ipoctal->dev->region[IPACK_INT_SPACE];
+	ipoctal->int_space =
+		devm_ioremap_nocache(&ipoctal->dev->dev,
+				     region->start, region->size);
+	if (!ipoctal->int_space) {
+		dev_err(&ipoctal->dev->dev,
+			"Unable to map slot [%d:%d] INT space!\n",
+			bus_nr, slot);
+		return -EADDRNOTAVAIL;
+	}
+
+	region = &ipoctal->dev->region[IPACK_MEM8_SPACE];
+	ipoctal->mem8_space =
+		devm_ioremap_nocache(&ipoctal->dev->dev,
+				     region->start, 0x8000);
+	if (!addr) {
+		dev_err(&ipoctal->dev->dev,
+			"Unable to map slot [%d:%d] MEM8 space!\n",
+			bus_nr, slot);
+		return -EADDRNOTAVAIL;
+	}
+
+
+	/* Disable RX and TX before touching anything */
+	for (i = 0; i < NR_CHANNELS ; i++) {
+		struct ipoctal_channel *channel = &ipoctal->channel[i];
+		channel->regs = chan_regs + i;
+		channel->block_regs = block_regs + (i >> 1);
+		channel->board_write = &ipoctal->write;
+		channel->board_id = ipoctal->board_id;
+		if (i & 1) {
+			channel->isr_tx_rdy_mask = ISR_TxRDY_B;
+			channel->isr_rx_rdy_mask = ISR_RxRDY_FFULL_B;
+		} else {
+			channel->isr_tx_rdy_mask = ISR_TxRDY_A;
+			channel->isr_rx_rdy_mask = ISR_RxRDY_FFULL_A;
+		}
+
+		iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr);
+		iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
+		iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
+		iowrite8(MR1_CHRL_8_BITS | MR1_ERROR_CHAR | MR1_RxINT_RxRDY,
+			 &channel->regs->w.mr); /* mr1 */
+		iowrite8(0, &channel->regs->w.mr); /* mr2 */
+		iowrite8(TX_CLK_9600  | RX_CLK_9600, &channel->regs->w.csr);
+	}
+
+	for (i = 0; i < IP_OCTAL_NB_BLOCKS; i++) {
+		iowrite8(ACR_BRG_SET2, &block_regs[i].w.acr);
+		iowrite8(OPCR_MPP_OUTPUT | OPCR_MPOa_RTSN | OPCR_MPOb_RTSN,
+			 &block_regs[i].w.opcr);
+		iowrite8(IMR_TxRDY_A | IMR_RxRDY_FFULL_A | IMR_DELTA_BREAK_A |
+			 IMR_TxRDY_B | IMR_RxRDY_FFULL_B | IMR_DELTA_BREAK_B,
+			 &block_regs[i].w.imr);
+	}
+
+	/*
+	 * IP-OCTAL has different addresses to copy its IRQ vector.
+	 * Depending of the carrier these addresses are accesible or not.
+	 * More info in the datasheet.
+	 */
+	ipoctal->dev->bus->ops->request_irq(ipoctal->dev,
+				       ipoctal_irq_handler, ipoctal);
+	/* Dummy write */
+	iowrite8(1, ipoctal->mem8_space + 1);
+
+	/* Register the TTY device */
+
+	/* Each IP-OCTAL channel is a TTY port */
+	tty = alloc_tty_driver(NR_CHANNELS);
+
+	if (!tty)
+		return -ENOMEM;
+
+	/* Fill struct tty_driver with ipoctal data */
+	tty->owner = THIS_MODULE;
+	tty->driver_name = KBUILD_MODNAME;
+	sprintf(name, KBUILD_MODNAME ".%d.%d.", bus_nr, slot);
+	tty->name = name;
+	tty->major = 0;
+
+	tty->minor_start = 0;
+	tty->type = TTY_DRIVER_TYPE_SERIAL;
+	tty->subtype = SERIAL_TYPE_NORMAL;
+	tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	tty->init_termios = tty_std_termios;
+	tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	tty->init_termios.c_ispeed = 9600;
+	tty->init_termios.c_ospeed = 9600;
+
+	tty_set_operations(tty, &ipoctal_fops);
+	res = tty_register_driver(tty);
+	if (res) {
+		dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n");
+		put_tty_driver(tty);
+		return res;
+	}
+
+	/* Save struct tty_driver for use it when uninstalling the device */
+	ipoctal->tty_drv = tty;
+
+	for (i = 0; i < NR_CHANNELS; i++) {
+		struct device *tty_dev;
+
+		channel = &ipoctal->channel[i];
+		tty_port_init(&channel->tty_port);
+		tty_port_alloc_xmit_buf(&channel->tty_port);
+		channel->tty_port.ops = &ipoctal_tty_port_ops;
+
+		ipoctal_reset_stats(&channel->stats);
+		channel->nb_bytes = 0;
+		init_waitqueue_head(&channel->queue);
+
+		spin_lock_init(&channel->lock);
+		channel->pointer_read = 0;
+		channel->pointer_write = 0;
+		tty_dev = tty_port_register_device(&channel->tty_port, tty, i, NULL);
+		if (IS_ERR(tty_dev)) {
+			dev_err(&ipoctal->dev->dev, "Failed to register tty device.\n");
+			tty_port_destroy(&channel->tty_port);
+			continue;
+		}
+		dev_set_drvdata(tty_dev, channel);
+
+		/*
+		 * Enable again the RX. TX will be enabled when
+		 * there is something to send
+		 */
+		iowrite8(CR_ENABLE_RX, &channel->regs->w.cr);
+	}
+
+	return 0;
+}
+
+static inline int ipoctal_copy_write_buffer(struct ipoctal_channel *channel,
+					    const unsigned char *buf,
+					    int count)
+{
+	unsigned long flags;
+	int i;
+	unsigned int *pointer_read = &channel->pointer_read;
+
+	/* Copy the bytes from the user buffer to the internal one */
+	for (i = 0; i < count; i++) {
+		if (i <= (PAGE_SIZE - channel->nb_bytes)) {
+			spin_lock_irqsave(&channel->lock, flags);
+			channel->tty_port.xmit_buf[*pointer_read] = buf[i];
+			*pointer_read = (*pointer_read + 1) % PAGE_SIZE;
+			channel->nb_bytes++;
+			spin_unlock_irqrestore(&channel->lock, flags);
+		} else {
+			break;
+		}
+	}
+	return i;
+}
+
+static int ipoctal_write_tty(struct tty_struct *tty,
+			     const unsigned char *buf, int count)
+{
+	struct ipoctal_channel *channel = tty->driver_data;
+	unsigned int char_copied;
+
+	char_copied = ipoctal_copy_write_buffer(channel, buf, count);
+
+	/* As the IP-OCTAL 485 only supports half duplex, do it manually */
+	if (channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) {
+		iowrite8(CR_DISABLE_RX, &channel->regs->w.cr);
+		iowrite8(CR_CMD_ASSERT_RTSN, &channel->regs->w.cr);
+	}
+
+	/*
+	 * Send a packet and then disable TX to avoid failure after several send
+	 * operations
+	 */
+	iowrite8(CR_ENABLE_TX, &channel->regs->w.cr);
+	wait_event_interruptible(channel->queue, *channel->board_write);
+	iowrite8(CR_DISABLE_TX, &channel->regs->w.cr);
+
+	*channel->board_write = 0;
+	return char_copied;
+}
+
+static int ipoctal_write_room(struct tty_struct *tty)
+{
+	struct ipoctal_channel *channel = tty->driver_data;
+
+	return PAGE_SIZE - channel->nb_bytes;
+}
+
+static int ipoctal_chars_in_buffer(struct tty_struct *tty)
+{
+	struct ipoctal_channel *channel = tty->driver_data;
+
+	return channel->nb_bytes;
+}
+
+static void ipoctal_set_termios(struct tty_struct *tty,
+				struct ktermios *old_termios)
+{
+	unsigned int cflag;
+	unsigned char mr1 = 0;
+	unsigned char mr2 = 0;
+	unsigned char csr = 0;
+	struct ipoctal_channel *channel = tty->driver_data;
+	speed_t baud;
+
+	cflag = tty->termios.c_cflag;
+
+	/* Disable and reset everything before change the setup */
+	iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr);
+	iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
+	iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
+	iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr);
+	iowrite8(CR_CMD_RESET_MR, &channel->regs->w.cr);
+
+	/* Set Bits per chars */
+	switch (cflag & CSIZE) {
+	case CS6:
+		mr1 |= MR1_CHRL_6_BITS;
+		break;
+	case CS7:
+		mr1 |= MR1_CHRL_7_BITS;
+		break;
+	case CS8:
+	default:
+		mr1 |= MR1_CHRL_8_BITS;
+		/* By default, select CS8 */
+		tty->termios.c_cflag = (cflag & ~CSIZE) | CS8;
+		break;
+	}
+
+	/* Set Parity */
+	if (cflag & PARENB)
+		if (cflag & PARODD)
+			mr1 |= MR1_PARITY_ON | MR1_PARITY_ODD;
+		else
+			mr1 |= MR1_PARITY_ON | MR1_PARITY_EVEN;
+	else
+		mr1 |= MR1_PARITY_OFF;
+
+	/* Mark or space parity is not supported */
+	tty->termios.c_cflag &= ~CMSPAR;
+
+	/* Set stop bits */
+	if (cflag & CSTOPB)
+		mr2 |= MR2_STOP_BITS_LENGTH_2;
+	else
+		mr2 |= MR2_STOP_BITS_LENGTH_1;
+
+	/* Set the flow control */
+	switch (channel->board_id) {
+	case IPACK1_DEVICE_ID_SBS_OCTAL_232:
+		if (cflag & CRTSCTS) {
+			mr1 |= MR1_RxRTS_CONTROL_ON;
+			mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_ON;
+		} else {
+			mr1 |= MR1_RxRTS_CONTROL_OFF;
+			mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF;
+		}
+		break;
+	case IPACK1_DEVICE_ID_SBS_OCTAL_422:
+		mr1 |= MR1_RxRTS_CONTROL_OFF;
+		mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF;
+		break;
+	case IPACK1_DEVICE_ID_SBS_OCTAL_485:
+		mr1 |= MR1_RxRTS_CONTROL_OFF;
+		mr2 |= MR2_TxRTS_CONTROL_ON | MR2_CTS_ENABLE_TX_OFF;
+		break;
+	default:
+		return;
+		break;
+	}
+
+	baud = tty_get_baud_rate(tty);
+	tty_termios_encode_baud_rate(&tty->termios, baud, baud);
+
+	/* Set baud rate */
+	switch (baud) {
+	case 75:
+		csr |= TX_CLK_75 | RX_CLK_75;
+		break;
+	case 110:
+		csr |= TX_CLK_110 | RX_CLK_110;
+		break;
+	case 150:
+		csr |= TX_CLK_150 | RX_CLK_150;
+		break;
+	case 300:
+		csr |= TX_CLK_300 | RX_CLK_300;
+		break;
+	case 600:
+		csr |= TX_CLK_600 | RX_CLK_600;
+		break;
+	case 1200:
+		csr |= TX_CLK_1200 | RX_CLK_1200;
+		break;
+	case 1800:
+		csr |= TX_CLK_1800 | RX_CLK_1800;
+		break;
+	case 2000:
+		csr |= TX_CLK_2000 | RX_CLK_2000;
+		break;
+	case 2400:
+		csr |= TX_CLK_2400 | RX_CLK_2400;
+		break;
+	case 4800:
+		csr |= TX_CLK_4800  | RX_CLK_4800;
+		break;
+	case 9600:
+		csr |= TX_CLK_9600  | RX_CLK_9600;
+		break;
+	case 19200:
+		csr |= TX_CLK_19200 | RX_CLK_19200;
+		break;
+	case 38400:
+	default:
+		csr |= TX_CLK_38400 | RX_CLK_38400;
+		/* In case of default, we establish 38400 bps */
+		tty_termios_encode_baud_rate(&tty->termios, 38400, 38400);
+		break;
+	}
+
+	mr1 |= MR1_ERROR_CHAR;
+	mr1 |= MR1_RxINT_RxRDY;
+
+	/* Write the control registers */
+	iowrite8(mr1, &channel->regs->w.mr);
+	iowrite8(mr2, &channel->regs->w.mr);
+	iowrite8(csr, &channel->regs->w.csr);
+
+	/* Enable again the RX */
+	iowrite8(CR_ENABLE_RX, &channel->regs->w.cr);
+}
+
+static void ipoctal_hangup(struct tty_struct *tty)
+{
+	unsigned long flags;
+	struct ipoctal_channel *channel = tty->driver_data;
+
+	if (channel == NULL)
+		return;
+
+	spin_lock_irqsave(&channel->lock, flags);
+	channel->nb_bytes = 0;
+	channel->pointer_read = 0;
+	channel->pointer_write = 0;
+	spin_unlock_irqrestore(&channel->lock, flags);
+
+	tty_port_hangup(&channel->tty_port);
+
+	iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr);
+	iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
+	iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
+	iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr);
+	iowrite8(CR_CMD_RESET_MR, &channel->regs->w.cr);
+
+	clear_bit(ASYNCB_INITIALIZED, &channel->tty_port.flags);
+	wake_up_interruptible(&channel->tty_port.open_wait);
+}
+
+static const struct tty_operations ipoctal_fops = {
+	.ioctl =		NULL,
+	.open =			ipoctal_open,
+	.close =		ipoctal_close,
+	.write =		ipoctal_write_tty,
+	.set_termios =		ipoctal_set_termios,
+	.write_room =		ipoctal_write_room,
+	.chars_in_buffer =	ipoctal_chars_in_buffer,
+	.get_icount =		ipoctal_get_icount,
+	.hangup =		ipoctal_hangup,
+};
+
+static int ipoctal_probe(struct ipack_device *dev)
+{
+	int res;
+	struct ipoctal *ipoctal;
+
+	ipoctal = kzalloc(sizeof(struct ipoctal), GFP_KERNEL);
+	if (ipoctal == NULL)
+		return -ENOMEM;
+
+	ipoctal->dev = dev;
+	res = ipoctal_inst_slot(ipoctal, dev->bus->bus_nr, dev->slot);
+	if (res)
+		goto out_uninst;
+
+	dev_set_drvdata(&dev->dev, ipoctal);
+	return 0;
+
+out_uninst:
+	kfree(ipoctal);
+	return res;
+}
+
+static void __ipoctal_remove(struct ipoctal *ipoctal)
+{
+	int i;
+
+	ipoctal->dev->bus->ops->free_irq(ipoctal->dev);
+
+	for (i = 0; i < NR_CHANNELS; i++) {
+		struct ipoctal_channel *channel = &ipoctal->channel[i];
+		tty_unregister_device(ipoctal->tty_drv, i);
+		tty_port_free_xmit_buf(&channel->tty_port);
+		tty_port_destroy(&channel->tty_port);
+	}
+
+	tty_unregister_driver(ipoctal->tty_drv);
+	put_tty_driver(ipoctal->tty_drv);
+	kfree(ipoctal);
+}
+
+static void ipoctal_remove(struct ipack_device *idev)
+{
+	__ipoctal_remove(dev_get_drvdata(&idev->dev));
+}
+
+static DEFINE_IPACK_DEVICE_TABLE(ipoctal_ids) = {
+	{ IPACK_DEVICE(IPACK_ID_VERSION_1, IPACK1_VENDOR_ID_SBS,
+			IPACK1_DEVICE_ID_SBS_OCTAL_232) },
+	{ IPACK_DEVICE(IPACK_ID_VERSION_1, IPACK1_VENDOR_ID_SBS,
+			IPACK1_DEVICE_ID_SBS_OCTAL_422) },
+	{ IPACK_DEVICE(IPACK_ID_VERSION_1, IPACK1_VENDOR_ID_SBS,
+			IPACK1_DEVICE_ID_SBS_OCTAL_485) },
+	{ 0, },
+};
+
+MODULE_DEVICE_TABLE(ipack, ipoctal_ids);
+
+static const struct ipack_driver_ops ipoctal_drv_ops = {
+	.probe  = ipoctal_probe,
+	.remove = ipoctal_remove,
+};
+
+static struct ipack_driver driver = {
+	.ops      = &ipoctal_drv_ops,
+	.id_table = ipoctal_ids,
+};
+
+static int __init ipoctal_init(void)
+{
+	return ipack_driver_register(&driver, THIS_MODULE, KBUILD_MODNAME);
+}
+
+static void __exit ipoctal_exit(void)
+{
+	ipack_driver_unregister(&driver);
+}
+
+MODULE_DESCRIPTION("IP-Octal 232, 422 and 485 device driver");
+MODULE_LICENSE("GPL");
+
+module_init(ipoctal_init);
+module_exit(ipoctal_exit);
diff --git a/drivers/ipack/devices/ipoctal.h b/drivers/ipack/devices/ipoctal.h
new file mode 100644
index 0000000..28f1c42
--- /dev/null
+++ b/drivers/ipack/devices/ipoctal.h
@@ -0,0 +1,42 @@
+/**
+ * ipoctal.h
+ *
+ * driver for the IPOCTAL boards
+
+ * Copyright (C) 2009-2012 CERN (www.cern.ch)
+ * Author: Nicolas Serafini, EIC2 SA
+ * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
+ *
+ * This program is free software; 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 _IPOCTAL_H
+#define _IPOCTAL_H_
+
+#define NR_CHANNELS		8
+#define IPOCTAL_MAX_BOARDS	16
+#define MAX_DEVICES		(NR_CHANNELS * IPOCTAL_MAX_BOARDS)
+#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+/**
+ * struct ipoctal_stats -- Stats since last reset
+ *
+ * @tx: Number of transmitted bytes
+ * @rx: Number of received bytes
+ * @overrun: Number of overrun errors
+ * @parity_err: Number of parity errors
+ * @framing_err: Number of framing errors
+ * @rcv_break: Number of break received
+ */
+struct ipoctal_stats {
+	unsigned long tx;
+	unsigned long rx;
+	unsigned long overrun_err;
+	unsigned long parity_err;
+	unsigned long framing_err;
+	unsigned long rcv_break;
+};
+
+#endif /* _IPOCTAL_H_ */
diff --git a/drivers/ipack/devices/scc2698.h b/drivers/ipack/devices/scc2698.h
new file mode 100644
index 0000000..2ad6acd
--- /dev/null
+++ b/drivers/ipack/devices/scc2698.h
@@ -0,0 +1,228 @@
+/*
+ * scc2698.h
+ *
+ * driver for the IPOCTAL boards
+ *
+ * Copyright (C) 2009-2012 CERN (www.cern.ch)
+ * Author: Nicolas Serafini, EIC2 SA
+ * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
+ *
+ * This program is free software; 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 SCC2698_H_
+#define SCC2698_H_
+
+/*
+ * union scc2698_channel - Channel access to scc2698 IO
+ *
+ * dn value are only spacer.
+ *
+ */
+union scc2698_channel {
+	struct {
+		u8 d0, mr;  /* Mode register 1/2*/
+		u8 d1, sr;  /* Status register */
+		u8 d2, r1;  /* reserved */
+		u8 d3, rhr; /* Receive holding register (R) */
+		u8 junk[8]; /* other crap for block control */
+	} __packed r; /* Read access */
+	struct {
+		u8 d0, mr;  /* Mode register 1/2 */
+		u8 d1, csr; /* Clock select register */
+		u8 d2, cr;  /* Command register */
+		u8 d3, thr; /* Transmit holding register */
+		u8 junk[8]; /* other crap for block control */
+	} __packed w; /* Write access */
+};
+
+/*
+ * union scc2698_block - Block access to scc2698 IO
+ *
+ * The scc2698 contain 4 block.
+ * Each block containt two channel a and b.
+ * dn value are only spacer.
+ *
+ */
+union scc2698_block {
+	struct {
+		u8 d0, mra;  /* Mode register 1/2 (a) */
+		u8 d1, sra;  /* Status register (a) */
+		u8 d2, r1;   /* reserved */
+		u8 d3, rhra; /* Receive holding register (a) */
+		u8 d4, ipcr; /* Input port change register of block */
+		u8 d5, isr;  /* Interrupt status register of block */
+		u8 d6, ctur; /* Counter timer upper register of block */
+		u8 d7, ctlr; /* Counter timer lower register of block */
+		u8 d8, mrb;  /* Mode register 1/2 (b) */
+		u8 d9, srb;  /* Status register (b) */
+		u8 da, r2;   /* reserved */
+		u8 db, rhrb; /* Receive holding register (b) */
+		u8 dc, r3;   /* reserved */
+		u8 dd, ip;   /* Input port register of block */
+		u8 de, ctg;  /* Start counter timer of block */
+		u8 df, cts;  /* Stop counter timer of block */
+	} __packed r; /* Read access */
+	struct {
+		u8 d0, mra;  /* Mode register 1/2 (a) */
+		u8 d1, csra; /* Clock select register (a) */
+		u8 d2, cra;  /* Command register (a) */
+		u8 d3, thra; /* Transmit holding register (a) */
+		u8 d4, acr;  /* Auxiliary control register of block */
+		u8 d5, imr;  /* Interrupt mask register of block  */
+		u8 d6, ctu;  /* Counter timer upper register of block */
+		u8 d7, ctl;  /* Counter timer lower register of block */
+		u8 d8, mrb;  /* Mode register 1/2 (b) */
+		u8 d9, csrb; /* Clock select register (a) */
+		u8 da, crb;  /* Command register (b) */
+		u8 db, thrb; /* Transmit holding register (b) */
+		u8 dc, r1;   /* reserved */
+		u8 dd, opcr; /* Output port configuration register of block */
+		u8 de, r2;   /* reserved */
+		u8 df, r3;   /* reserved */
+	} __packed w; /* Write access */
+};
+
+#define MR1_CHRL_5_BITS             (0x0 << 0)
+#define MR1_CHRL_6_BITS             (0x1 << 0)
+#define MR1_CHRL_7_BITS             (0x2 << 0)
+#define MR1_CHRL_8_BITS             (0x3 << 0)
+#define MR1_PARITY_EVEN             (0x1 << 2)
+#define MR1_PARITY_ODD              (0x0 << 2)
+#define MR1_PARITY_ON               (0x0 << 3)
+#define MR1_PARITY_FORCE            (0x1 << 3)
+#define MR1_PARITY_OFF              (0x2 << 3)
+#define MR1_PARITY_SPECIAL          (0x3 << 3)
+#define MR1_ERROR_CHAR              (0x0 << 5)
+#define MR1_ERROR_BLOCK             (0x1 << 5)
+#define MR1_RxINT_RxRDY             (0x0 << 6)
+#define MR1_RxINT_FFULL             (0x1 << 6)
+#define MR1_RxRTS_CONTROL_ON        (0x1 << 7)
+#define MR1_RxRTS_CONTROL_OFF       (0x0 << 7)
+
+#define MR2_STOP_BITS_LENGTH_1      (0x7 << 0)
+#define MR2_STOP_BITS_LENGTH_2      (0xF << 0)
+#define MR2_CTS_ENABLE_TX_ON        (0x1 << 4)
+#define MR2_CTS_ENABLE_TX_OFF       (0x0 << 4)
+#define MR2_TxRTS_CONTROL_ON        (0x1 << 5)
+#define MR2_TxRTS_CONTROL_OFF       (0x0 << 5)
+#define MR2_CH_MODE_NORMAL          (0x0 << 6)
+#define MR2_CH_MODE_ECHO            (0x1 << 6)
+#define MR2_CH_MODE_LOCAL           (0x2 << 6)
+#define MR2_CH_MODE_REMOTE          (0x3 << 6)
+
+#define CR_ENABLE_RX                (0x1 << 0)
+#define CR_DISABLE_RX               (0x1 << 1)
+#define CR_ENABLE_TX                (0x1 << 2)
+#define CR_DISABLE_TX               (0x1 << 3)
+#define CR_CMD_RESET_MR             (0x1 << 4)
+#define CR_CMD_RESET_RX             (0x2 << 4)
+#define CR_CMD_RESET_TX             (0x3 << 4)
+#define CR_CMD_RESET_ERR_STATUS     (0x4 << 4)
+#define CR_CMD_RESET_BREAK_CHANGE   (0x5 << 4)
+#define CR_CMD_START_BREAK          (0x6 << 4)
+#define CR_CMD_STOP_BREAK           (0x7 << 4)
+#define CR_CMD_ASSERT_RTSN          (0x8 << 4)
+#define CR_CMD_NEGATE_RTSN          (0x9 << 4)
+#define CR_CMD_SET_TIMEOUT_MODE     (0xA << 4)
+#define CR_CMD_DISABLE_TIMEOUT_MODE (0xC << 4)
+
+#define SR_RX_READY                 (0x1 << 0)
+#define SR_FIFO_FULL                (0x1 << 1)
+#define SR_TX_READY                 (0x1 << 2)
+#define SR_TX_EMPTY                 (0x1 << 3)
+#define SR_OVERRUN_ERROR            (0x1 << 4)
+#define SR_PARITY_ERROR             (0x1 << 5)
+#define SR_FRAMING_ERROR            (0x1 << 6)
+#define SR_RECEIVED_BREAK           (0x1 << 7)
+
+#define SR_ERROR                    (0xF0)
+
+#define ACR_DELTA_IP0_IRQ_EN        (0x1 << 0)
+#define ACR_DELTA_IP1_IRQ_EN        (0x1 << 1)
+#define ACR_DELTA_IP2_IRQ_EN        (0x1 << 2)
+#define ACR_DELTA_IP3_IRQ_EN        (0x1 << 3)
+#define ACR_CT_Mask                 (0x7 << 4)
+#define ACR_CExt                    (0x0 << 4)
+#define ACR_CTxCA                   (0x1 << 4)
+#define ACR_CTxCB                   (0x2 << 4)
+#define ACR_CClk16                  (0x3 << 4)
+#define ACR_TExt                    (0x4 << 4)
+#define ACR_TExt16                  (0x5 << 4)
+#define ACR_TClk                    (0x6 << 4)
+#define ACR_TClk16                  (0x7 << 4)
+#define ACR_BRG_SET1                (0x0 << 7)
+#define ACR_BRG_SET2                (0x1 << 7)
+
+#define TX_CLK_75                   (0x0 << 0)
+#define TX_CLK_110                  (0x1 << 0)
+#define TX_CLK_38400                (0x2 << 0)
+#define TX_CLK_150                  (0x3 << 0)
+#define TX_CLK_300                  (0x4 << 0)
+#define TX_CLK_600                  (0x5 << 0)
+#define TX_CLK_1200                 (0x6 << 0)
+#define TX_CLK_2000                 (0x7 << 0)
+#define TX_CLK_2400                 (0x8 << 0)
+#define TX_CLK_4800                 (0x9 << 0)
+#define TX_CLK_1800                 (0xA << 0)
+#define TX_CLK_9600                 (0xB << 0)
+#define TX_CLK_19200                (0xC << 0)
+#define RX_CLK_75                   (0x0 << 4)
+#define RX_CLK_110                  (0x1 << 4)
+#define RX_CLK_38400                (0x2 << 4)
+#define RX_CLK_150                  (0x3 << 4)
+#define RX_CLK_300                  (0x4 << 4)
+#define RX_CLK_600                  (0x5 << 4)
+#define RX_CLK_1200                 (0x6 << 4)
+#define RX_CLK_2000                 (0x7 << 4)
+#define RX_CLK_2400                 (0x8 << 4)
+#define RX_CLK_4800                 (0x9 << 4)
+#define RX_CLK_1800                 (0xA << 4)
+#define RX_CLK_9600                 (0xB << 4)
+#define RX_CLK_19200                (0xC << 4)
+
+#define OPCR_MPOa_RTSN              (0x0 << 0)
+#define OPCR_MPOa_C_TO              (0x1 << 0)
+#define OPCR_MPOa_TxC1X             (0x2 << 0)
+#define OPCR_MPOa_TxC16X            (0x3 << 0)
+#define OPCR_MPOa_RxC1X             (0x4 << 0)
+#define OPCR_MPOa_RxC16X            (0x5 << 0)
+#define OPCR_MPOa_TxRDY             (0x6 << 0)
+#define OPCR_MPOa_RxRDY_FF          (0x7 << 0)
+
+#define OPCR_MPOb_RTSN              (0x0 << 4)
+#define OPCR_MPOb_C_TO              (0x1 << 4)
+#define OPCR_MPOb_TxC1X             (0x2 << 4)
+#define OPCR_MPOb_TxC16X            (0x3 << 4)
+#define OPCR_MPOb_RxC1X             (0x4 << 4)
+#define OPCR_MPOb_RxC16X            (0x5 << 4)
+#define OPCR_MPOb_TxRDY             (0x6 << 4)
+#define OPCR_MPOb_RxRDY_FF          (0x7 << 4)
+
+#define OPCR_MPP_INPUT              (0x0 << 7)
+#define OPCR_MPP_OUTPUT             (0x1 << 7)
+
+#define IMR_TxRDY_A                 (0x1 << 0)
+#define IMR_RxRDY_FFULL_A           (0x1 << 1)
+#define IMR_DELTA_BREAK_A           (0x1 << 2)
+#define IMR_COUNTER_READY           (0x1 << 3)
+#define IMR_TxRDY_B                 (0x1 << 4)
+#define IMR_RxRDY_FFULL_B           (0x1 << 5)
+#define IMR_DELTA_BREAK_B           (0x1 << 6)
+#define IMR_INPUT_PORT_CHANGE       (0x1 << 7)
+
+#define ISR_TxRDY_A                 (0x1 << 0)
+#define ISR_RxRDY_FFULL_A           (0x1 << 1)
+#define ISR_DELTA_BREAK_A           (0x1 << 2)
+#define ISR_COUNTER_READY           (0x1 << 3)
+#define ISR_TxRDY_B                 (0x1 << 4)
+#define ISR_RxRDY_FFULL_B           (0x1 << 5)
+#define ISR_DELTA_BREAK_B           (0x1 << 6)
+#define ISR_INPUT_PORT_CHANGE       (0x1 << 7)
+
+#define ACK_INT_REQ0			0
+#define ACK_INT_REQ1			2
+
+#endif /* SCC2698_H_ */
diff --git a/drivers/ipack/ipack.c b/drivers/ipack/ipack.c
new file mode 100644
index 0000000..7ec6b20
--- /dev/null
+++ b/drivers/ipack/ipack.c
@@ -0,0 +1,481 @@
+/*
+ * Industry-pack bus support functions.
+ *
+ * Copyright (C) 2011-2012 CERN (www.cern.ch)
+ * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
+ *
+ * This program is free software; 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/module.h>
+#include <linux/slab.h>
+#include <linux/idr.h>
+#include <linux/io.h>
+#include <linux/ipack.h>
+
+#define to_ipack_dev(device) container_of(device, struct ipack_device, dev)
+#define to_ipack_driver(drv) container_of(drv, struct ipack_driver, driver)
+
+static DEFINE_IDA(ipack_ida);
+
+static void ipack_device_release(struct device *dev)
+{
+	struct ipack_device *device = to_ipack_dev(dev);
+	kfree(device->id);
+	device->release(device);
+}
+
+static inline const struct ipack_device_id *
+ipack_match_one_device(const struct ipack_device_id *id,
+		       const struct ipack_device *device)
+{
+	if ((id->format == IPACK_ANY_FORMAT ||
+				id->format == device->id_format) &&
+	    (id->vendor == IPACK_ANY_ID || id->vendor == device->id_vendor) &&
+	    (id->device == IPACK_ANY_ID || id->device == device->id_device))
+		return id;
+	return NULL;
+}
+
+static const struct ipack_device_id *
+ipack_match_id(const struct ipack_device_id *ids, struct ipack_device *idev)
+{
+	if (ids) {
+		while (ids->vendor || ids->device) {
+			if (ipack_match_one_device(ids, idev))
+				return ids;
+			ids++;
+		}
+	}
+	return NULL;
+}
+
+static int ipack_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct ipack_device *idev = to_ipack_dev(dev);
+	struct ipack_driver *idrv = to_ipack_driver(drv);
+	const struct ipack_device_id *found_id;
+
+	found_id = ipack_match_id(idrv->id_table, idev);
+	return found_id ? 1 : 0;
+}
+
+static int ipack_bus_probe(struct device *device)
+{
+	struct ipack_device *dev = to_ipack_dev(device);
+	struct ipack_driver *drv = to_ipack_driver(device->driver);
+
+	if (!drv->ops->probe)
+		return -EINVAL;
+
+	return drv->ops->probe(dev);
+}
+
+static int ipack_bus_remove(struct device *device)
+{
+	struct ipack_device *dev = to_ipack_dev(device);
+	struct ipack_driver *drv = to_ipack_driver(device->driver);
+
+	if (!drv->ops->remove)
+		return -EINVAL;
+
+	drv->ops->remove(dev);
+	return 0;
+}
+
+static int ipack_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	struct ipack_device *idev;
+
+	if (!dev)
+		return -ENODEV;
+
+	idev = to_ipack_dev(dev);
+
+	if (add_uevent_var(env,
+			   "MODALIAS=ipack:f%02Xv%08Xd%08X", idev->id_format,
+			   idev->id_vendor, idev->id_device))
+		return -ENOMEM;
+
+	return 0;
+}
+
+#define ipack_device_attr(field, format_string)				\
+static ssize_t								\
+field##_show(struct device *dev, struct device_attribute *attr,		\
+		char *buf)						\
+{									\
+	struct ipack_device *idev = to_ipack_dev(dev);			\
+	return sprintf(buf, format_string, idev->field);		\
+}
+
+static ssize_t id_show(struct device *dev,
+		       struct device_attribute *attr, char *buf)
+{
+	unsigned int i, c, l, s;
+	struct ipack_device *idev = to_ipack_dev(dev);
+
+
+	switch (idev->id_format) {
+	case IPACK_ID_VERSION_1:
+		l = 0x7; s = 1; break;
+	case IPACK_ID_VERSION_2:
+		l = 0xf; s = 2; break;
+	default:
+		return -EIO;
+	}
+	c = 0;
+	for (i = 0; i < idev->id_avail; i++) {
+		if (i > 0) {
+			if ((i & l) == 0)
+				buf[c++] = '\n';
+			else if ((i & s) == 0)
+				buf[c++] = ' ';
+		}
+		sprintf(&buf[c], "%02x", idev->id[i]);
+		c += 2;
+	}
+	buf[c++] = '\n';
+	return c;
+}
+
+static ssize_t
+id_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct ipack_device *idev = to_ipack_dev(dev);
+	switch (idev->id_format) {
+	case IPACK_ID_VERSION_1:
+		return sprintf(buf, "0x%02x\n", idev->id_vendor);
+	case IPACK_ID_VERSION_2:
+		return sprintf(buf, "0x%06x\n", idev->id_vendor);
+	default:
+		return -EIO;
+	}
+}
+
+static ssize_t
+id_device_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct ipack_device *idev = to_ipack_dev(dev);
+	switch (idev->id_format) {
+	case IPACK_ID_VERSION_1:
+		return sprintf(buf, "0x%02x\n", idev->id_device);
+	case IPACK_ID_VERSION_2:
+		return sprintf(buf, "0x%04x\n", idev->id_device);
+	default:
+		return -EIO;
+	}
+}
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct ipack_device *idev = to_ipack_dev(dev);
+
+	return sprintf(buf, "ipac:f%02Xv%08Xd%08X", idev->id_format,
+		       idev->id_vendor, idev->id_device);
+}
+
+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 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,
+	.uevent	   = ipack_uevent,
+};
+
+struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots,
+					    const struct ipack_bus_ops *ops)
+{
+	int bus_nr;
+	struct ipack_bus_device *bus;
+
+	bus = kzalloc(sizeof(struct ipack_bus_device), GFP_KERNEL);
+	if (!bus)
+		return NULL;
+
+	bus_nr = ida_simple_get(&ipack_ida, 0, 0, GFP_KERNEL);
+	if (bus_nr < 0) {
+		kfree(bus);
+		return NULL;
+	}
+
+	bus->bus_nr = bus_nr;
+	bus->parent = parent;
+	bus->slots = slots;
+	bus->ops = ops;
+	return bus;
+}
+EXPORT_SYMBOL_GPL(ipack_bus_register);
+
+static int ipack_unregister_bus_member(struct device *dev, void *data)
+{
+	struct ipack_device *idev = to_ipack_dev(dev);
+	struct ipack_bus_device *bus = data;
+
+	if (idev->bus == bus)
+		ipack_device_unregister(idev);
+
+	return 1;
+}
+
+int ipack_bus_unregister(struct ipack_bus_device *bus)
+{
+	bus_for_each_dev(&ipack_bus_type, NULL, bus,
+		ipack_unregister_bus_member);
+	ida_simple_remove(&ipack_ida, bus->bus_nr);
+	kfree(bus);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipack_bus_unregister);
+
+int ipack_driver_register(struct ipack_driver *edrv, struct module *owner,
+			  const char *name)
+{
+	edrv->driver.owner = owner;
+	edrv->driver.name = name;
+	edrv->driver.bus = &ipack_bus_type;
+	return driver_register(&edrv->driver);
+}
+EXPORT_SYMBOL_GPL(ipack_driver_register);
+
+void ipack_driver_unregister(struct ipack_driver *edrv)
+{
+	driver_unregister(&edrv->driver);
+}
+EXPORT_SYMBOL_GPL(ipack_driver_unregister);
+
+static u16 ipack_crc_byte(u16 crc, u8 c)
+{
+	int i;
+
+	crc ^= c << 8;
+	for (i = 0; i < 8; i++)
+		crc = (crc << 1) ^ ((crc & 0x8000) ? 0x1021 : 0);
+	return crc;
+}
+
+/*
+ * The algorithm in lib/crc-ccitt.c does not seem to apply since it uses the
+ * opposite bit ordering.
+ */
+static u8 ipack_calc_crc1(struct ipack_device *dev)
+{
+	u8 c;
+	u16 crc;
+	unsigned int i;
+
+	crc = 0xffff;
+	for (i = 0; i < dev->id_avail; i++) {
+		c = (i != 11) ? dev->id[i] : 0;
+		crc = ipack_crc_byte(crc, c);
+	}
+	crc = ~crc;
+	return crc & 0xff;
+}
+
+static u16 ipack_calc_crc2(struct ipack_device *dev)
+{
+	u8 c;
+	u16 crc;
+	unsigned int i;
+
+	crc = 0xffff;
+	for (i = 0; i < dev->id_avail; i++) {
+		c = ((i != 0x18) && (i != 0x19)) ? dev->id[i] : 0;
+		crc = ipack_crc_byte(crc, c);
+	}
+	crc = ~crc;
+	return crc;
+}
+
+static void ipack_parse_id1(struct ipack_device *dev)
+{
+	u8 *id = dev->id;
+	u8 crc;
+
+	dev->id_vendor = id[4];
+	dev->id_device = id[5];
+	dev->speed_8mhz = 1;
+	dev->speed_32mhz = (id[7] == 'H');
+	crc = ipack_calc_crc1(dev);
+	dev->id_crc_correct = (crc == id[11]);
+	if (!dev->id_crc_correct) {
+		dev_warn(&dev->dev, "ID CRC invalid found 0x%x, expected 0x%x.\n",
+				id[11], crc);
+	}
+}
+
+static void ipack_parse_id2(struct ipack_device *dev)
+{
+	__be16 *id = (__be16 *) dev->id;
+	u16 flags, crc;
+
+	dev->id_vendor = ((be16_to_cpu(id[3]) & 0xff) << 16)
+			 + be16_to_cpu(id[4]);
+	dev->id_device = be16_to_cpu(id[5]);
+	flags = be16_to_cpu(id[10]);
+	dev->speed_8mhz = !!(flags & 2);
+	dev->speed_32mhz = !!(flags & 4);
+	crc = ipack_calc_crc2(dev);
+	dev->id_crc_correct = (crc == be16_to_cpu(id[12]));
+	if (!dev->id_crc_correct) {
+		dev_warn(&dev->dev, "ID CRC invalid found 0x%x, expected 0x%x.\n",
+				id[11], crc);
+	}
+}
+
+static int ipack_device_read_id(struct ipack_device *dev)
+{
+	u8 __iomem *idmem;
+	int i;
+	int ret = 0;
+
+	idmem = ioremap(dev->region[IPACK_ID_SPACE].start,
+			dev->region[IPACK_ID_SPACE].size);
+	if (!idmem) {
+		dev_err(&dev->dev, "error mapping memory\n");
+		return -ENOMEM;
+	}
+
+	/* Determine ID PROM Data Format.  If we find the ids "IPAC" or "IPAH"
+	 * we are dealing with a IndustryPack  format 1 device.  If we detect
+	 * "VITA4 " (16 bit big endian formatted) we are dealing with a
+	 * IndustryPack format 2 device */
+	if ((ioread8(idmem + 1) == 'I') &&
+			(ioread8(idmem + 3) == 'P') &&
+			(ioread8(idmem + 5) == 'A') &&
+			((ioread8(idmem + 7) == 'C') ||
+			 (ioread8(idmem + 7) == 'H'))) {
+		dev->id_format = IPACK_ID_VERSION_1;
+		dev->id_avail = ioread8(idmem + 0x15);
+		if ((dev->id_avail < 0x0c) || (dev->id_avail > 0x40)) {
+			dev_warn(&dev->dev, "invalid id size");
+			dev->id_avail = 0x0c;
+		}
+	} else if ((ioread8(idmem + 0) == 'I') &&
+			(ioread8(idmem + 1) == 'V') &&
+			(ioread8(idmem + 2) == 'A') &&
+			(ioread8(idmem + 3) == 'T') &&
+			(ioread8(idmem + 4) == ' ') &&
+			(ioread8(idmem + 5) == '4')) {
+		dev->id_format = IPACK_ID_VERSION_2;
+		dev->id_avail = ioread16be(idmem + 0x16);
+		if ((dev->id_avail < 0x1a) || (dev->id_avail > 0x40)) {
+			dev_warn(&dev->dev, "invalid id size");
+			dev->id_avail = 0x1a;
+		}
+	} else {
+		dev->id_format = IPACK_ID_VERSION_INVALID;
+		dev->id_avail = 0;
+	}
+
+	if (!dev->id_avail) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* Obtain the amount of memory required to store a copy of the complete
+	 * ID ROM contents */
+	dev->id = kmalloc(dev->id_avail, GFP_KERNEL);
+	if (!dev->id) {
+		dev_err(&dev->dev, "dev->id alloc failed.\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+	for (i = 0; i < dev->id_avail; i++) {
+		if (dev->id_format == IPACK_ID_VERSION_1)
+			dev->id[i] = ioread8(idmem + (i << 1) + 1);
+		else
+			dev->id[i] = ioread8(idmem + i);
+	}
+
+	/* now we can finally work with the copy */
+	switch (dev->id_format) {
+	case IPACK_ID_VERSION_1:
+		ipack_parse_id1(dev);
+		break;
+	case IPACK_ID_VERSION_2:
+		ipack_parse_id2(dev);
+		break;
+	}
+
+out:
+	iounmap(idmem);
+
+	return ret;
+}
+
+int ipack_device_register(struct ipack_device *dev)
+{
+	int ret;
+
+	dev->dev.bus = &ipack_bus_type;
+	dev->dev.release = ipack_device_release;
+	dev->dev.parent = dev->bus->parent;
+	dev_set_name(&dev->dev,
+		     "ipack-dev.%u.%u", dev->bus->bus_nr, dev->slot);
+
+	if (dev->bus->ops->set_clockrate(dev, 8))
+		dev_warn(&dev->dev, "failed to switch to 8 MHz operation for reading of device ID.\n");
+	if (dev->bus->ops->reset_timeout(dev))
+		dev_warn(&dev->dev, "failed to reset potential timeout.");
+
+	ret = ipack_device_read_id(dev);
+	if (ret < 0) {
+		dev_err(&dev->dev, "error reading device id section.\n");
+		return ret;
+	}
+
+	/* if the device supports 32 MHz operation, use it. */
+	if (dev->speed_32mhz) {
+		ret = dev->bus->ops->set_clockrate(dev, 32);
+		if (ret < 0)
+			dev_err(&dev->dev, "failed to switch to 32 MHz operation.\n");
+	}
+
+	ret = device_register(&dev->dev);
+	if (ret < 0)
+		kfree(dev->id);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ipack_device_register);
+
+void ipack_device_unregister(struct ipack_device *dev)
+{
+	device_unregister(&dev->dev);
+}
+EXPORT_SYMBOL_GPL(ipack_device_unregister);
+
+static int __init ipack_init(void)
+{
+	ida_init(&ipack_ida);
+	return bus_register(&ipack_bus_type);
+}
+
+static void __exit ipack_exit(void)
+{
+	bus_unregister(&ipack_bus_type);
+	ida_destroy(&ipack_ida);
+}
+
+module_init(ipack_init);
+module_exit(ipack_exit);
+
+MODULE_AUTHOR("Samuel Iglesias Gonsalvez <siglesias@igalia.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Industry-pack bus core");
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 1bb8bf6..62ca575 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -1 +1,8 @@
-# empty
+config VERSATILE_FPGA_IRQ
+	bool
+	select IRQ_DOMAIN
+
+config VERSATILE_FPGA_IRQ_NR
+       int
+       default 4
+       depends on VERSATILE_FPGA_IRQ
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 054321d..fc44067 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -1 +1,4 @@
-obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o
+obj-$(CONFIG_ARCH_BCM2835)		+= irq-bcm2835.o
+obj-$(CONFIG_ARCH_SPEAR3XX)		+= spear-shirq.o
+obj-$(CONFIG_ARCH_SUNXI)   		+= irq-sunxi.o
+obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
diff --git a/drivers/irqchip/irq-sunxi.c b/drivers/irqchip/irq-sunxi.c
new file mode 100644
index 0000000..eef41a4
--- /dev/null
+++ b/drivers/irqchip/irq-sunxi.c
@@ -0,0 +1,150 @@
+/*
+ * Allwinner A1X SoCs IRQ chip driver.
+ *
+ * Copyright (C) 2012 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * Based on code from
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Benn Huang <benn@allwinnertech.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <linux/irqchip/sunxi.h>
+
+#define SUNXI_IRQ_VECTOR_REG		0x00
+#define SUNXI_IRQ_PROTECTION_REG	0x08
+#define SUNXI_IRQ_NMI_CTRL_REG		0x0c
+#define SUNXI_IRQ_PENDING_REG(x)	(0x10 + 0x4 * x)
+#define SUNXI_IRQ_FIQ_PENDING_REG(x)	(0x20 + 0x4 * x)
+#define SUNXI_IRQ_ENABLE_REG(x)		(0x40 + 0x4 * x)
+#define SUNXI_IRQ_MASK_REG(x)		(0x50 + 0x4 * x)
+
+static void __iomem *sunxi_irq_base;
+static struct irq_domain *sunxi_irq_domain;
+
+void sunxi_irq_ack(struct irq_data *irqd)
+{
+	unsigned int irq = irqd_to_hwirq(irqd);
+	unsigned int irq_off = irq % 32;
+	int reg = irq / 32;
+	u32 val;
+
+	val = readl(sunxi_irq_base + SUNXI_IRQ_PENDING_REG(reg));
+	writel(val | (1 << irq_off),
+	       sunxi_irq_base + SUNXI_IRQ_PENDING_REG(reg));
+}
+
+static void sunxi_irq_mask(struct irq_data *irqd)
+{
+	unsigned int irq = irqd_to_hwirq(irqd);
+	unsigned int irq_off = irq % 32;
+	int reg = irq / 32;
+	u32 val;
+
+	val = readl(sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(reg));
+	writel(val & ~(1 << irq_off),
+	       sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(reg));
+}
+
+static void sunxi_irq_unmask(struct irq_data *irqd)
+{
+	unsigned int irq = irqd_to_hwirq(irqd);
+	unsigned int irq_off = irq % 32;
+	int reg = irq / 32;
+	u32 val;
+
+	val = readl(sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(reg));
+	writel(val | (1 << irq_off),
+	       sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(reg));
+}
+
+static struct irq_chip sunxi_irq_chip = {
+	.name		= "sunxi_irq",
+	.irq_ack	= sunxi_irq_ack,
+	.irq_mask	= sunxi_irq_mask,
+	.irq_unmask	= sunxi_irq_unmask,
+};
+
+static int sunxi_irq_map(struct irq_domain *d, unsigned int virq,
+			 irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(virq, &sunxi_irq_chip,
+				 handle_level_irq);
+	set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
+
+	return 0;
+}
+
+static struct irq_domain_ops sunxi_irq_ops = {
+	.map = sunxi_irq_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+static int __init sunxi_of_init(struct device_node *node,
+				struct device_node *parent)
+{
+	sunxi_irq_base = of_iomap(node, 0);
+	if (!sunxi_irq_base)
+		panic("%s: unable to map IC registers\n",
+			node->full_name);
+
+	/* Disable all interrupts */
+	writel(0, sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(0));
+	writel(0, sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(1));
+	writel(0, sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(2));
+
+	/* Mask all the interrupts */
+	writel(0, sunxi_irq_base + SUNXI_IRQ_MASK_REG(0));
+	writel(0, sunxi_irq_base + SUNXI_IRQ_MASK_REG(1));
+	writel(0, sunxi_irq_base + SUNXI_IRQ_MASK_REG(2));
+
+	/* Clear all the pending interrupts */
+	writel(0xffffffff, sunxi_irq_base + SUNXI_IRQ_PENDING_REG(0));
+	writel(0xffffffff, sunxi_irq_base + SUNXI_IRQ_PENDING_REG(1));
+	writel(0xffffffff, sunxi_irq_base + SUNXI_IRQ_PENDING_REG(2));
+
+	/* Enable protection mode */
+	writel(0x01, sunxi_irq_base + SUNXI_IRQ_PROTECTION_REG);
+
+	/* Configure the external interrupt source type */
+	writel(0x00, sunxi_irq_base + SUNXI_IRQ_NMI_CTRL_REG);
+
+	sunxi_irq_domain = irq_domain_add_linear(node, 3 * 32,
+						 &sunxi_irq_ops, NULL);
+	if (!sunxi_irq_domain)
+		panic("%s: unable to create IRQ domain\n", node->full_name);
+
+	return 0;
+}
+
+static struct of_device_id sunxi_irq_dt_ids[] __initconst = {
+	{ .compatible = "allwinner,sunxi-ic", .data = sunxi_of_init }
+};
+
+void __init sunxi_init_irq(void)
+{
+	of_irq_init(sunxi_irq_dt_ids);
+}
+
+asmlinkage void __exception_irq_entry sunxi_handle_irq(struct pt_regs *regs)
+{
+	u32 irq, hwirq;
+
+	hwirq = readl(sunxi_irq_base + SUNXI_IRQ_VECTOR_REG) >> 2;
+	while (hwirq != 0) {
+		irq = irq_find_mapping(sunxi_irq_domain, hwirq);
+		handle_IRQ(irq, regs);
+		hwirq = readl(sunxi_irq_base + SUNXI_IRQ_VECTOR_REG) >> 2;
+	}
+}
diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c
new file mode 100644
index 0000000..789b3e5
--- /dev/null
+++ b/drivers/irqchip/irq-versatile-fpga.c
@@ -0,0 +1,204 @@
+/*
+ *  Support for Versatile FPGA-based IRQ controllers
+ */
+#include <linux/bitops.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/irqchip/versatile-fpga.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/exception.h>
+#include <asm/mach/irq.h>
+
+#define IRQ_STATUS		0x00
+#define IRQ_RAW_STATUS		0x04
+#define IRQ_ENABLE_SET		0x08
+#define IRQ_ENABLE_CLEAR	0x0c
+#define INT_SOFT_SET		0x10
+#define INT_SOFT_CLEAR		0x14
+#define FIQ_STATUS		0x20
+#define FIQ_RAW_STATUS		0x24
+#define FIQ_ENABLE		0x28
+#define FIQ_ENABLE_SET		0x28
+#define FIQ_ENABLE_CLEAR	0x2C
+
+/**
+ * struct fpga_irq_data - irq data container for the FPGA IRQ controller
+ * @base: memory offset in virtual memory
+ * @chip: chip container for this instance
+ * @domain: IRQ domain for this instance
+ * @valid: mask for valid IRQs on this controller
+ * @used_irqs: number of active IRQs on this controller
+ */
+struct fpga_irq_data {
+	void __iomem *base;
+	struct irq_chip chip;
+	u32 valid;
+	struct irq_domain *domain;
+	u8 used_irqs;
+};
+
+/* we cannot allocate memory when the controllers are initially registered */
+static struct fpga_irq_data fpga_irq_devices[CONFIG_VERSATILE_FPGA_IRQ_NR];
+static int fpga_irq_id;
+
+static void fpga_irq_mask(struct irq_data *d)
+{
+	struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
+	u32 mask = 1 << d->hwirq;
+
+	writel(mask, f->base + IRQ_ENABLE_CLEAR);
+}
+
+static void fpga_irq_unmask(struct irq_data *d)
+{
+	struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
+	u32 mask = 1 << d->hwirq;
+
+	writel(mask, f->base + IRQ_ENABLE_SET);
+}
+
+static void fpga_irq_handle(unsigned int irq, struct irq_desc *desc)
+{
+	struct fpga_irq_data *f = irq_desc_get_handler_data(desc);
+	u32 status = readl(f->base + IRQ_STATUS);
+
+	if (status == 0) {
+		do_bad_IRQ(irq, desc);
+		return;
+	}
+
+	do {
+		irq = ffs(status) - 1;
+		status &= ~(1 << irq);
+		generic_handle_irq(irq_find_mapping(f->domain, irq));
+	} while (status);
+}
+
+/*
+ * Handle each interrupt in a single FPGA IRQ controller.  Returns non-zero
+ * if we've handled at least one interrupt.  This does a single read of the
+ * status register and handles all interrupts in order from LSB first.
+ */
+static int handle_one_fpga(struct fpga_irq_data *f, struct pt_regs *regs)
+{
+	int handled = 0;
+	int irq;
+	u32 status;
+
+	while ((status  = readl(f->base + IRQ_STATUS))) {
+		irq = ffs(status) - 1;
+		handle_IRQ(irq_find_mapping(f->domain, irq), regs);
+		handled = 1;
+	}
+
+	return handled;
+}
+
+/*
+ * Keep iterating over all registered FPGA IRQ controllers until there are
+ * no pending interrupts.
+ */
+asmlinkage void __exception_irq_entry fpga_handle_irq(struct pt_regs *regs)
+{
+	int i, handled;
+
+	do {
+		for (i = 0, handled = 0; i < fpga_irq_id; ++i)
+			handled |= handle_one_fpga(&fpga_irq_devices[i], regs);
+	} while (handled);
+}
+
+static int fpga_irqdomain_map(struct irq_domain *d, unsigned int irq,
+		irq_hw_number_t hwirq)
+{
+	struct fpga_irq_data *f = d->host_data;
+
+	/* Skip invalid IRQs, only register handlers for the real ones */
+	if (!(f->valid & BIT(hwirq)))
+		return -ENOTSUPP;
+	irq_set_chip_data(irq, f);
+	irq_set_chip_and_handler(irq, &f->chip,
+				handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
+
+static struct irq_domain_ops fpga_irqdomain_ops = {
+	.map = fpga_irqdomain_map,
+	.xlate = irq_domain_xlate_onetwocell,
+};
+
+void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
+			  int parent_irq, u32 valid, struct device_node *node)
+{
+	struct fpga_irq_data *f;
+	int i;
+
+	if (fpga_irq_id >= ARRAY_SIZE(fpga_irq_devices)) {
+		pr_err("%s: too few FPGA IRQ controllers, increase CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR\n", __func__);
+		return;
+	}
+	f = &fpga_irq_devices[fpga_irq_id];
+	f->base = base;
+	f->chip.name = name;
+	f->chip.irq_ack = fpga_irq_mask;
+	f->chip.irq_mask = fpga_irq_mask;
+	f->chip.irq_unmask = fpga_irq_unmask;
+	f->valid = valid;
+
+	if (parent_irq != -1) {
+		irq_set_handler_data(parent_irq, f);
+		irq_set_chained_handler(parent_irq, fpga_irq_handle);
+	}
+
+	/* This will also allocate irq descriptors */
+	f->domain = irq_domain_add_simple(node, fls(valid), irq_start,
+					  &fpga_irqdomain_ops, f);
+
+	/* This will allocate all valid descriptors in the linear case */
+	for (i = 0; i < fls(valid); i++)
+		if (valid & BIT(i)) {
+			if (!irq_start)
+				irq_create_mapping(f->domain, i);
+			f->used_irqs++;
+		}
+
+	pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n",
+		fpga_irq_id, name, base, f->used_irqs);
+
+	fpga_irq_id++;
+}
+
+#ifdef CONFIG_OF
+int __init fpga_irq_of_init(struct device_node *node,
+			    struct device_node *parent)
+{
+	struct fpga_irq_data *f;
+	void __iomem *base;
+	u32 clear_mask;
+	u32 valid_mask;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	base = of_iomap(node, 0);
+	WARN(!base, "unable to map fpga irq registers\n");
+
+	if (of_property_read_u32(node, "clear-mask", &clear_mask))
+		clear_mask = 0;
+
+	if (of_property_read_u32(node, "valid-mask", &valid_mask))
+		valid_mask = 0;
+
+	fpga_irq_init(base, node->name, 0, -1, valid_mask, node);
+
+	writel(clear_mask, base + IRQ_ENABLE_CLEAR);
+	writel(clear_mask, base + FIQ_ENABLE_CLEAR);
+
+	return 0;
+}
+#endif
diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c
new file mode 100644
index 0000000..80e1d2f
--- /dev/null
+++ b/drivers/irqchip/spear-shirq.c
@@ -0,0 +1,316 @@
+/*
+ * SPEAr platform shared irq layer source file
+ *
+ * Copyright (C) 2009-2012 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.com>
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Shiraz Hashim <shiraz.hashim@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/spear-shirq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/spinlock.h>
+
+static DEFINE_SPINLOCK(lock);
+
+/* spear300 shared irq registers offsets and masks */
+#define SPEAR300_INT_ENB_MASK_REG	0x54
+#define SPEAR300_INT_STS_MASK_REG	0x58
+
+static struct spear_shirq spear300_shirq_ras1 = {
+	.irq_nr = 9,
+	.irq_bit_off = 0,
+	.regs = {
+		.enb_reg = SPEAR300_INT_ENB_MASK_REG,
+		.status_reg = SPEAR300_INT_STS_MASK_REG,
+		.clear_reg = -1,
+	},
+};
+
+static struct spear_shirq *spear300_shirq_blocks[] = {
+	&spear300_shirq_ras1,
+};
+
+/* spear310 shared irq registers offsets and masks */
+#define SPEAR310_INT_STS_MASK_REG	0x04
+
+static struct spear_shirq spear310_shirq_ras1 = {
+	.irq_nr = 8,
+	.irq_bit_off = 0,
+	.regs = {
+		.enb_reg = -1,
+		.status_reg = SPEAR310_INT_STS_MASK_REG,
+		.clear_reg = -1,
+	},
+};
+
+static struct spear_shirq spear310_shirq_ras2 = {
+	.irq_nr = 5,
+	.irq_bit_off = 8,
+	.regs = {
+		.enb_reg = -1,
+		.status_reg = SPEAR310_INT_STS_MASK_REG,
+		.clear_reg = -1,
+	},
+};
+
+static struct spear_shirq spear310_shirq_ras3 = {
+	.irq_nr = 1,
+	.irq_bit_off = 13,
+	.regs = {
+		.enb_reg = -1,
+		.status_reg = SPEAR310_INT_STS_MASK_REG,
+		.clear_reg = -1,
+	},
+};
+
+static struct spear_shirq spear310_shirq_intrcomm_ras = {
+	.irq_nr = 3,
+	.irq_bit_off = 14,
+	.regs = {
+		.enb_reg = -1,
+		.status_reg = SPEAR310_INT_STS_MASK_REG,
+		.clear_reg = -1,
+	},
+};
+
+static struct spear_shirq *spear310_shirq_blocks[] = {
+	&spear310_shirq_ras1,
+	&spear310_shirq_ras2,
+	&spear310_shirq_ras3,
+	&spear310_shirq_intrcomm_ras,
+};
+
+/* spear320 shared irq registers offsets and masks */
+#define SPEAR320_INT_STS_MASK_REG		0x04
+#define SPEAR320_INT_CLR_MASK_REG		0x04
+#define SPEAR320_INT_ENB_MASK_REG		0x08
+
+static struct spear_shirq spear320_shirq_ras1 = {
+	.irq_nr = 3,
+	.irq_bit_off = 7,
+	.regs = {
+		.enb_reg = -1,
+		.status_reg = SPEAR320_INT_STS_MASK_REG,
+		.clear_reg = SPEAR320_INT_CLR_MASK_REG,
+		.reset_to_clear = 1,
+	},
+};
+
+static struct spear_shirq spear320_shirq_ras2 = {
+	.irq_nr = 1,
+	.irq_bit_off = 10,
+	.regs = {
+		.enb_reg = -1,
+		.status_reg = SPEAR320_INT_STS_MASK_REG,
+		.clear_reg = SPEAR320_INT_CLR_MASK_REG,
+		.reset_to_clear = 1,
+	},
+};
+
+static struct spear_shirq spear320_shirq_ras3 = {
+	.irq_nr = 3,
+	.irq_bit_off = 0,
+	.invalid_irq = 1,
+	.regs = {
+		.enb_reg = SPEAR320_INT_ENB_MASK_REG,
+		.reset_to_enb = 1,
+		.status_reg = SPEAR320_INT_STS_MASK_REG,
+		.clear_reg = SPEAR320_INT_CLR_MASK_REG,
+		.reset_to_clear = 1,
+	},
+};
+
+static struct spear_shirq spear320_shirq_intrcomm_ras = {
+	.irq_nr = 11,
+	.irq_bit_off = 11,
+	.regs = {
+		.enb_reg = -1,
+		.status_reg = SPEAR320_INT_STS_MASK_REG,
+		.clear_reg = SPEAR320_INT_CLR_MASK_REG,
+		.reset_to_clear = 1,
+	},
+};
+
+static struct spear_shirq *spear320_shirq_blocks[] = {
+	&spear320_shirq_ras3,
+	&spear320_shirq_ras1,
+	&spear320_shirq_ras2,
+	&spear320_shirq_intrcomm_ras,
+};
+
+static void shirq_irq_mask_unmask(struct irq_data *d, bool mask)
+{
+	struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
+	u32 val, offset = d->irq - shirq->irq_base;
+	unsigned long flags;
+
+	if (shirq->regs.enb_reg == -1)
+		return;
+
+	spin_lock_irqsave(&lock, flags);
+	val = readl(shirq->base + shirq->regs.enb_reg);
+
+	if (mask ^ shirq->regs.reset_to_enb)
+		val &= ~(0x1 << shirq->irq_bit_off << offset);
+	else
+		val |= 0x1 << shirq->irq_bit_off << offset;
+
+	writel(val, shirq->base + shirq->regs.enb_reg);
+	spin_unlock_irqrestore(&lock, flags);
+
+}
+
+static void shirq_irq_mask(struct irq_data *d)
+{
+	shirq_irq_mask_unmask(d, 1);
+}
+
+static void shirq_irq_unmask(struct irq_data *d)
+{
+	shirq_irq_mask_unmask(d, 0);
+}
+
+static struct irq_chip shirq_chip = {
+	.name		= "spear-shirq",
+	.irq_ack	= shirq_irq_mask,
+	.irq_mask	= shirq_irq_mask,
+	.irq_unmask	= shirq_irq_unmask,
+};
+
+static void shirq_handler(unsigned irq, struct irq_desc *desc)
+{
+	u32 i, j, val, mask, tmp;
+	struct irq_chip *chip;
+	struct spear_shirq *shirq = irq_get_handler_data(irq);
+
+	chip = irq_get_chip(irq);
+	chip->irq_ack(&desc->irq_data);
+
+	mask = ((0x1 << shirq->irq_nr) - 1) << shirq->irq_bit_off;
+	while ((val = readl(shirq->base + shirq->regs.status_reg) &
+				mask)) {
+
+		val >>= shirq->irq_bit_off;
+		for (i = 0, j = 1; i < shirq->irq_nr; i++, j <<= 1) {
+
+			if (!(j & val))
+				continue;
+
+			generic_handle_irq(shirq->irq_base + i);
+
+			/* clear interrupt */
+			if (shirq->regs.clear_reg == -1)
+				continue;
+
+			tmp = readl(shirq->base + shirq->regs.clear_reg);
+			if (shirq->regs.reset_to_clear)
+				tmp &= ~(j << shirq->irq_bit_off);
+			else
+				tmp |= (j << shirq->irq_bit_off);
+			writel(tmp, shirq->base + shirq->regs.clear_reg);
+		}
+	}
+	chip->irq_unmask(&desc->irq_data);
+}
+
+static void __init spear_shirq_register(struct spear_shirq *shirq)
+{
+	int i;
+
+	if (shirq->invalid_irq)
+		return;
+
+	irq_set_chained_handler(shirq->irq, shirq_handler);
+	for (i = 0; i < shirq->irq_nr; i++) {
+		irq_set_chip_and_handler(shirq->irq_base + i,
+					 &shirq_chip, handle_simple_irq);
+		set_irq_flags(shirq->irq_base + i, IRQF_VALID);
+		irq_set_chip_data(shirq->irq_base + i, shirq);
+	}
+
+	irq_set_handler_data(shirq->irq, shirq);
+}
+
+static int __init shirq_init(struct spear_shirq **shirq_blocks, int block_nr,
+		struct device_node *np)
+{
+	int i, irq_base, hwirq = 0, irq_nr = 0;
+	static struct irq_domain *shirq_domain;
+	void __iomem *base;
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_err("%s: failed to map shirq registers\n", __func__);
+		return -ENXIO;
+	}
+
+	for (i = 0; i < block_nr; i++)
+		irq_nr += shirq_blocks[i]->irq_nr;
+
+	irq_base = irq_alloc_descs(-1, 0, irq_nr, 0);
+	if (IS_ERR_VALUE(irq_base)) {
+		pr_err("%s: irq desc alloc failed\n", __func__);
+		goto err_unmap;
+	}
+
+	shirq_domain = irq_domain_add_legacy(np, irq_nr, irq_base, 0,
+			&irq_domain_simple_ops, NULL);
+	if (WARN_ON(!shirq_domain)) {
+		pr_warn("%s: irq domain init failed\n", __func__);
+		goto err_free_desc;
+	}
+
+	for (i = 0; i < block_nr; i++) {
+		shirq_blocks[i]->base = base;
+		shirq_blocks[i]->irq_base = irq_find_mapping(shirq_domain,
+				hwirq);
+		shirq_blocks[i]->irq = irq_of_parse_and_map(np, i);
+
+		spear_shirq_register(shirq_blocks[i]);
+		hwirq += shirq_blocks[i]->irq_nr;
+	}
+
+	return 0;
+
+err_free_desc:
+	irq_free_descs(irq_base, irq_nr);
+err_unmap:
+	iounmap(base);
+	return -ENXIO;
+}
+
+int __init spear300_shirq_of_init(struct device_node *np,
+		struct device_node *parent)
+{
+	return shirq_init(spear300_shirq_blocks,
+			ARRAY_SIZE(spear300_shirq_blocks), np);
+}
+
+int __init spear310_shirq_of_init(struct device_node *np,
+		struct device_node *parent)
+{
+	return shirq_init(spear310_shirq_blocks,
+			ARRAY_SIZE(spear310_shirq_blocks), np);
+}
+
+int __init spear320_shirq_of_init(struct device_node *np,
+		struct device_node *parent)
+{
+	return shirq_init(spear320_shirq_blocks,
+			ARRAY_SIZE(spear320_shirq_blocks), np);
+}
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index c679867..89562a8 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -77,8 +77,6 @@ struct ackqueue_entry {
 };
 
 struct capiminor {
-	struct kref kref;
-
 	unsigned int      minor;
 
 	struct capi20_appl	*ap;
@@ -190,7 +188,20 @@ static void capiminor_del_all_ack(struct capiminor *mp)
 
 /* -------- struct capiminor ---------------------------------------- */
 
-static const struct tty_port_operations capiminor_port_ops; /* we have none */
+static void capiminor_destroy(struct tty_port *port)
+{
+	struct capiminor *mp = container_of(port, struct capiminor, port);
+
+	kfree_skb(mp->outskb);
+	skb_queue_purge(&mp->inqueue);
+	skb_queue_purge(&mp->outqueue);
+	capiminor_del_all_ack(mp);
+	kfree(mp);
+}
+
+static const struct tty_port_operations capiminor_port_ops = {
+	.destruct = capiminor_destroy,
+};
 
 static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
 {
@@ -204,8 +215,6 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
 		return NULL;
 	}
 
-	kref_init(&mp->kref);
-
 	mp->ap = ap;
 	mp->ncci = ncci;
 	INIT_LIST_HEAD(&mp->ackqueue);
@@ -247,21 +256,10 @@ err_out2:
 	spin_unlock(&capiminors_lock);
 
 err_out1:
-	kfree(mp);
+	tty_port_put(&mp->port);
 	return NULL;
 }
 
-static void capiminor_destroy(struct kref *kref)
-{
-	struct capiminor *mp = container_of(kref, struct capiminor, kref);
-
-	kfree_skb(mp->outskb);
-	skb_queue_purge(&mp->inqueue);
-	skb_queue_purge(&mp->outqueue);
-	capiminor_del_all_ack(mp);
-	kfree(mp);
-}
-
 static struct capiminor *capiminor_get(unsigned int minor)
 {
 	struct capiminor *mp;
@@ -269,7 +267,7 @@ static struct capiminor *capiminor_get(unsigned int minor)
 	spin_lock(&capiminors_lock);
 	mp = capiminors[minor];
 	if (mp)
-		kref_get(&mp->kref);
+		tty_port_get(&mp->port);
 	spin_unlock(&capiminors_lock);
 
 	return mp;
@@ -277,7 +275,7 @@ static struct capiminor *capiminor_get(unsigned int minor)
 
 static inline void capiminor_put(struct capiminor *mp)
 {
-	kref_put(&mp->kref, capiminor_destroy);
+	tty_port_put(&mp->port);
 }
 
 static void capiminor_free(struct capiminor *mp)
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 30a6b17..6849a11 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -507,6 +507,7 @@ void gigaset_freecs(struct cardstate *cs)
 		gig_dbg(DEBUG_INIT, "clearing at_state");
 		clear_at_state(&cs->at_state);
 		dealloc_temp_at_states(cs);
+		tty_port_destroy(&cs->port);
 
 		/* fall through */
 	case 0:	/* error in basic setup */
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index 81363ff..6e99d73 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -490,7 +490,7 @@ receive_dmsg(struct hfc_pci *hc)
 		    (df->data[le16_to_cpu(zp->z1)])) {
 			if (dch->debug & DEBUG_HW)
 				printk(KERN_DEBUG
-				       "empty_fifo hfcpci paket inv. len "
+				       "empty_fifo hfcpci packet inv. len "
 				       "%d or crc %d\n",
 				       rcnt,
 				       df->data[le16_to_cpu(zp->z1)]);
diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c
index 182ecf0..feafa91 100644
--- a/drivers/isdn/hardware/mISDN/mISDNisar.c
+++ b/drivers/isdn/hardware/mISDN/mISDNisar.c
@@ -1302,7 +1302,7 @@ modeisar(struct isar_ch *ch, u32 bprotocol)
 						   &ch->is->Flags))
 				ch->dpath = 1;
 			else {
-				pr_info("modeisar both pathes in use\n");
+				pr_info("modeisar both paths in use\n");
 				return -EBUSY;
 			}
 			if (bprotocol == ISDN_P_B_HDLC)
diff --git a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c
index 89342f7..525471e 100644
--- a/drivers/isdn/hisax/amd7930_fn.c
+++ b/drivers/isdn/hisax/amd7930_fn.c
@@ -628,7 +628,7 @@ Amd7930_l1hw(struct PStack *st, int pr, void *arg)
 		if ((cs->dc.amd7930.ph_state == 8)) {
 			/* b-channels off, PH-AR cleared
 			 * change to F3 */
-			Amd7930_ph_command(cs, 0x20, "HW_RESET REQEST"); //LMR1 bit 5
+			Amd7930_ph_command(cs, 0x20, "HW_RESET REQUEST"); //LMR1 bit 5
 			spin_unlock_irqrestore(&cs->lock, flags);
 		} else {
 			Amd7930_ph_command(cs, 0x40, "HW_RESET REQUEST");
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
index a47637b..ddec47a 100644
--- a/drivers/isdn/hisax/callc.c
+++ b/drivers/isdn/hisax/callc.c
@@ -35,7 +35,7 @@ static int chancount;
 /* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */
 #define ALERT_REJECT 0
 
-/* Value to delay the sending of the first B-channel paket after CONNECT
+/* Value to delay the sending of the first B-channel packet after CONNECT
  * here is no value given by ITU, but experience shows that 300 ms will
  * work on many networks, if you or your other side is behind local exchanges
  * a greater value may be recommented. If the delay is to short the first paket
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 334fa90..f60d4be 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -354,7 +354,7 @@ receive_dmsg(struct IsdnCardState *cs)
 		if ((rcnt > MAX_DFRAME_LEN + 3) || (rcnt < 4) ||
 		    (df->data[zp->z1])) {
 			if (cs->debug & L1_DEB_WARN)
-				debugl1(cs, "empty_fifo hfcpci paket inv. len %d or crc %d", rcnt, df->data[zp->z1]);
+				debugl1(cs, "empty_fifo hfcpci packet inv. len %d or crc %d", rcnt, df->data[zp->z1]);
 #ifdef ERROR_STATISTIC
 			cs->err_rx++;
 #endif
diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
index 4db846b..4ec279c 100644
--- a/drivers/isdn/hisax/hfc_sx.c
+++ b/drivers/isdn/hisax/hfc_sx.c
@@ -270,7 +270,7 @@ read_fifo(struct IsdnCardState *cs, u_char fifo, int trans_max)
 
 		if ((count > fifo_size) || (count < 4)) {
 			if (cs->debug & L1_DEB_WARN)
-				debugl1(cs, "hfcsx_read_fifo %d paket inv. len %d ", fifo , count);
+				debugl1(cs, "hfcsx_read_fifo %d packet inv. len %d ", fifo , count);
 			while (count) {
 				count--; /* empty fifo */
 				Read_hfc(cs, HFCSX_FIF_DRD);
diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
index ff5e139..7fdf347 100644
--- a/drivers/isdn/hisax/isar.c
+++ b/drivers/isdn/hisax/isar.c
@@ -1417,7 +1417,7 @@ modeisar(struct BCState *bcs, int mode, int bc)
 						   &bcs->hw.isar.reg->Flags))
 				bcs->hw.isar.dpath = 1;
 			else {
-				printk(KERN_WARNING"isar modeisar both pathes in use\n");
+				printk(KERN_WARNING"isar modeisar both paths in use\n");
 				return (1);
 			}
 			break;
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index b817809..e09dc8a 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1849,6 +1849,8 @@ err_unregister:
 		kfree(info->fax);
 #endif
 		kfree(info->port.xmit_buf - 4);
+		info->port.xmit_buf = NULL;
+		tty_port_destroy(&info->port);
 	}
 	tty_unregister_driver(m->tty_modem);
 err:
@@ -1870,6 +1872,8 @@ isdn_tty_exit(void)
 		kfree(info->fax);
 #endif
 		kfree(info->port.xmit_buf - 4);
+		info->port.xmit_buf = NULL;
+		tty_port_destroy(&info->port);
 	}
 	tty_unregister_driver(dev->mdm.tty_modem);
 	put_tty_driver(dev->mdm.tty_modem);
diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c
index db50f78..f8e405c 100644
--- a/drivers/isdn/mISDN/l1oip_core.c
+++ b/drivers/isdn/mISDN/l1oip_core.c
@@ -277,7 +277,6 @@ l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask,
 		  u16 timebase, u8 *buf, int len)
 {
 	u8 *p;
-	int multi = 0;
 	u8 frame[len + 32];
 	struct socket *socket = NULL;
 
@@ -317,9 +316,7 @@ l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask,
 		*p++ = hc->id >> 8;
 		*p++ = hc->id;
 	}
-	*p++ = (multi == 1) ? 0x80 : 0x00 + channel; /* m-flag, channel */
-	if (multi == 1)
-		*p++ = len; /* length */
+	*p++ =  0x00 + channel; /* m-flag, channel */
 	*p++ = timebase >> 8; /* time base */
 	*p++ = timebase;
 
diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c
index a18e639..42ecfef 100644
--- a/drivers/isdn/pcbit/layer2.c
+++ b/drivers/isdn/pcbit/layer2.c
@@ -508,7 +508,7 @@ pcbit_irq_handler(int interrupt, void *devptr)
 		return IRQ_NONE;
 	}
 	if (dev->interrupt) {
-		printk(KERN_DEBUG "pcbit: reentering interrupt hander\n");
+		printk(KERN_DEBUG "pcbit: reentering interrupt handler\n");
 		return IRQ_HANDLED;
 	}
 	dev->interrupt = 1;
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index f508def..b58bc8a 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -379,7 +379,9 @@ config LEDS_NS2
 	tristate "LED support for Network Space v2 GPIO LEDs"
 	depends on LEDS_CLASS
 	depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || \
-		   MACH_NETSPACE_MAX_V2 || MACH_D2NET_V2
+		   MACH_NETSPACE_MAX_V2 || MACH_D2NET_V2 || \
+		   MACH_NETSPACE_V2_DT || MACH_INETSPACE_V2_DT || \
+		   MACH_NETSPACE_MAX_V2_DT || MACH_NETSPACE_MINI_V2_DT
 	default y
 	help
 	  This option enable support for the dual-GPIO LED found on the
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 48cce18..a20752f 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -211,7 +211,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
 	led_trigger_set_default(led_cdev);
 #endif
 
-	printk(KERN_DEBUG "Registered led device: %s\n",
+	dev_dbg(parent, "Registered led device: %s\n",
 			led_cdev->name);
 
 	return 0;
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index 262eb41..3c972b2 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -166,6 +166,19 @@ void led_trigger_set_default(struct led_classdev *led_cdev)
 }
 EXPORT_SYMBOL_GPL(led_trigger_set_default);
 
+void led_trigger_rename_static(const char *name, struct led_trigger *trig)
+{
+	/* new name must be on a temporary string to prevent races */
+	BUG_ON(name == trig->name);
+
+	down_write(&triggers_list_lock);
+	/* this assumes that trig->name was originaly allocated to
+	 * non constant storage */
+	strcpy((char *)trig->name, name);
+	up_write(&triggers_list_lock);
+}
+EXPORT_SYMBOL_GPL(led_trigger_rename_static);
+
 /* LED Trigger Interface */
 
 int led_trigger_register(struct led_trigger *trig)
@@ -300,13 +313,13 @@ void led_trigger_register_simple(const char *name, struct led_trigger **tp)
 		if (err < 0) {
 			kfree(trig);
 			trig = NULL;
-			printk(KERN_WARNING "LED trigger %s failed to register"
-				" (%d)\n", name, err);
+			pr_warn("LED trigger %s failed to register (%d)\n",
+				name, err);
 		}
-	} else
-		printk(KERN_WARNING "LED trigger %s failed to register"
-			" (no memory)\n", name);
-
+	} else {
+		pr_warn("LED trigger %s failed to register (no memory)\n",
+			name);
+	}
 	*tp = trig;
 }
 EXPORT_SYMBOL_GPL(led_trigger_register_simple);
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c
index b7e8cc0..6be2edd4 100644
--- a/drivers/leds/leds-88pm860x.c
+++ b/drivers/leds/leds-88pm860x.c
@@ -165,15 +165,13 @@ static int pm860x_led_probe(struct platform_device *pdev)
 	res = platform_get_resource_byname(pdev, IORESOURCE_REG, "control");
 	if (!res) {
 		dev_err(&pdev->dev, "No REG resource for control\n");
-		ret = -ENXIO;
-		goto out;
+		return -ENXIO;
 	}
 	data->reg_control = res->start;
 	res = platform_get_resource_byname(pdev, IORESOURCE_REG, "blink");
 	if (!res) {
 		dev_err(&pdev->dev, "No REG resource for blink\n");
-		ret = -ENXIO;
-		goto out;
+		return -ENXIO;
 	}
 	data->reg_blink = res->start;
 	memset(data->name, 0, MFD_NAME_SIZE);
@@ -224,9 +222,6 @@ static int pm860x_led_probe(struct platform_device *pdev)
 	}
 	pm860x_led_set(&data->cdev, 0);
 	return 0;
-out:
-	devm_kfree(&pdev->dev, data);
-	return ret;
 }
 
 static int pm860x_led_remove(struct platform_device *pdev)
diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c
index aa56a86..e8072ab 100644
--- a/drivers/leds/leds-adp5520.c
+++ b/drivers/leds/leds-adp5520.c
@@ -5,10 +5,10 @@
  *
  * Loosely derived from leds-da903x:
  * Copyright (C) 2008 Compulab, Ltd.
- * 	Mike Rapoport <mike@compulab.co.il>
+ *	Mike Rapoport <mike@compulab.co.il>
  *
  * Copyright (C) 2006-2008 Marvell International Ltd.
- * 	Eric Miao <eric.miao@marvell.com>
+ *	Eric Miao <eric.miao@marvell.com>
  *
  * Licensed under the GPL-2 or later.
  */
@@ -85,7 +85,7 @@ static int adp5520_led_setup(struct adp5520_led *led)
 	return ret;
 }
 
-static int __devinit adp5520_led_prepare(struct platform_device *pdev)
+static int adp5520_led_prepare(struct platform_device *pdev)
 {
 	struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
 	struct device *dev = pdev->dev.parent;
@@ -101,7 +101,7 @@ static int __devinit adp5520_led_prepare(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devinit adp5520_led_probe(struct platform_device *pdev)
+static int adp5520_led_probe(struct platform_device *pdev)
 {
 	struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
 	struct adp5520_led *led, *led_dat;
@@ -183,7 +183,7 @@ err:
 	return ret;
 }
 
-static int __devexit adp5520_led_remove(struct platform_device *pdev)
+static int adp5520_led_remove(struct platform_device *pdev)
 {
 	struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
 	struct adp5520_led *led;
@@ -208,7 +208,7 @@ static struct platform_driver adp5520_led_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= adp5520_led_probe,
-	.remove		= __devexit_p(adp5520_led_remove),
+	.remove		= adp5520_led_remove,
 };
 
 module_platform_driver(adp5520_led_driver);
diff --git a/drivers/leds/leds-asic3.c b/drivers/leds/leds-asic3.c
index 5de74ff..b474745 100644
--- a/drivers/leds/leds-asic3.c
+++ b/drivers/leds/leds-asic3.c
@@ -92,7 +92,7 @@ static int blink_set(struct led_classdev *cdev,
 	return 0;
 }
 
-static int __devinit asic3_led_probe(struct platform_device *pdev)
+static int asic3_led_probe(struct platform_device *pdev)
 {
 	struct asic3_led *led = pdev->dev.platform_data;
 	int ret;
@@ -125,7 +125,7 @@ out:
 	return ret;
 }
 
-static int __devexit asic3_led_remove(struct platform_device *pdev)
+static int asic3_led_remove(struct platform_device *pdev)
 {
 	struct asic3_led *led = pdev->dev.platform_data;
 
@@ -167,7 +167,7 @@ static const struct dev_pm_ops asic3_led_pm_ops = {
 
 static struct platform_driver asic3_led_driver = {
 	.probe		= asic3_led_probe,
-	.remove		= __devexit_p(asic3_led_remove),
+	.remove		= asic3_led_remove,
 	.driver		= {
 		.name	= "leds-asic3",
 		.owner	= THIS_MODULE,
diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c
index 4543063..3867735 100644
--- a/drivers/leds/leds-atmel-pwm.c
+++ b/drivers/leds/leds-atmel-pwm.c
@@ -35,7 +35,7 @@ static void pwmled_brightness(struct led_classdev *cdev, enum led_brightness b)
  * NOTE:  we reuse the platform_data structure of GPIO leds,
  * but repurpose its "gpio" number as a PWM channel number.
  */
-static int __devinit pwmled_probe(struct platform_device *pdev)
+static int pwmled_probe(struct platform_device *pdev)
 {
 	const struct gpio_led_platform_data	*pdata;
 	struct pwmled				*leds;
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c
index 89ca6a2..8515170 100644
--- a/drivers/leds/leds-bd2802.c
+++ b/drivers/leds/leds-bd2802.c
@@ -26,8 +26,8 @@
 #define BD2802_LED_OFFSET		0xa
 #define BD2802_COLOR_OFFSET		0x3
 
-#define BD2802_REG_CLKSETUP 		0x00
-#define BD2802_REG_CONTROL 		0x01
+#define BD2802_REG_CLKSETUP		0x00
+#define BD2802_REG_CONTROL		0x01
 #define BD2802_REG_HOURSETUP		0x02
 #define BD2802_REG_CURRENT1SETUP	0x03
 #define BD2802_REG_CURRENT2SETUP	0x04
@@ -93,7 +93,7 @@ struct bd2802_led {
 	 * In ADF mode, user can set registers of BD2802GU directly,
 	 * therefore BD2802GU doesn't enter reset state.
 	 */
-	int 				adf_on;
+	int				adf_on;
 
 	enum led_ids			led_id;
 	enum led_colors			color;
@@ -328,7 +328,7 @@ static ssize_t bd2802_store_reg##reg_addr(struct device *dev,		\
 	int ret;							\
 	if (!count)							\
 		return -EINVAL;						\
-	ret = strict_strtoul(buf, 16, &val);				\
+	ret = kstrtoul(buf, 16, &val);					\
 	if (ret)							\
 		return ret;						\
 	down_write(&led->rwsem);					\
@@ -492,7 +492,7 @@ static ssize_t bd2802_store_##attr_name(struct device *dev,		\
 	int ret;							\
 	if (!count)							\
 		return -EINVAL;						\
-	ret = strict_strtoul(buf, 16, &val);				\
+	ret = kstrtoul(buf, 16, &val);					\
 	if (ret)							\
 		return ret;						\
 	down_write(&led->rwsem);					\
@@ -670,7 +670,7 @@ static void bd2802_unregister_led_classdev(struct bd2802_led *led)
 	led_classdev_unregister(&led->cdev_led1r);
 }
 
-static int __devinit bd2802_probe(struct i2c_client *client,
+static int bd2802_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct bd2802_led *led;
diff --git a/drivers/leds/leds-blinkm.c b/drivers/leds/leds-blinkm.c
index f7c3d7f..a502678 100644
--- a/drivers/leds/leds-blinkm.c
+++ b/drivers/leds/leds-blinkm.c
@@ -632,7 +632,7 @@ static int blinkm_detect(struct i2c_client *client, struct i2c_board_info *info)
 	return 0;
 }
 
-static int __devinit blinkm_probe(struct i2c_client *client,
+static int blinkm_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct blinkm_data *data;
@@ -743,7 +743,7 @@ exit:
 	return err;
 }
 
-static int __devexit blinkm_remove(struct i2c_client *client)
+static int blinkm_remove(struct i2c_client *client)
 {
 	struct blinkm_data *data = i2c_get_clientdata(client);
 	int ret = 0;
@@ -801,7 +801,7 @@ static struct i2c_driver blinkm_driver = {
 		   .name = "blinkm",
 		   },
 	.probe = blinkm_probe,
-	.remove = __devexit_p(blinkm_remove),
+	.remove = blinkm_remove,
 	.id_table = blinkm_id,
 	.detect = blinkm_detect,
 	.address_list = normal_i2c,
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
index e024b0b..b025470 100644
--- a/drivers/leds/leds-clevo-mail.c
+++ b/drivers/leds/leds-clevo-mail.c
@@ -153,7 +153,7 @@ static struct led_classdev clevo_mail_led = {
 	.flags			= LED_CORE_SUSPENDRESUME,
 };
 
-static int __devinit clevo_mail_led_probe(struct platform_device *pdev)
+static int clevo_mail_led_probe(struct platform_device *pdev)
 {
 	return led_classdev_register(&pdev->dev, &clevo_mail_led);
 }
diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c
index 6a8725c..8abcb66 100644
--- a/drivers/leds/leds-cobalt-qube.c
+++ b/drivers/leds/leds-cobalt-qube.c
@@ -34,7 +34,7 @@ static struct led_classdev qube_front_led = {
 	.default_trigger	= "default-on",
 };
 
-static int __devinit cobalt_qube_led_probe(struct platform_device *pdev)
+static int cobalt_qube_led_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	int retval;
@@ -43,7 +43,7 @@ static int __devinit cobalt_qube_led_probe(struct platform_device *pdev)
 	if (!res)
 		return -EBUSY;
 
-	led_port = ioremap(res->start, resource_size(res));
+	led_port = devm_ioremap(&pdev->dev, res->start, resource_size(res));
 	if (!led_port)
 		return -ENOMEM;
 
@@ -52,32 +52,29 @@ static int __devinit cobalt_qube_led_probe(struct platform_device *pdev)
 
 	retval = led_classdev_register(&pdev->dev, &qube_front_led);
 	if (retval)
-		goto err_iounmap;
+		goto err_null;
 
 	return 0;
 
-err_iounmap:
-	iounmap(led_port);
+err_null:
 	led_port = NULL;
 
 	return retval;
 }
 
-static int __devexit cobalt_qube_led_remove(struct platform_device *pdev)
+static int cobalt_qube_led_remove(struct platform_device *pdev)
 {
 	led_classdev_unregister(&qube_front_led);
 
-	if (led_port) {
-		iounmap(led_port);
+	if (led_port)
 		led_port = NULL;
-	}
 
 	return 0;
 }
 
 static struct platform_driver cobalt_qube_led_driver = {
 	.probe	= cobalt_qube_led_probe,
-	.remove	= __devexit_p(cobalt_qube_led_remove),
+	.remove	= cobalt_qube_led_remove,
 	.driver	= {
 		.name	= "cobalt-qube-leds",
 		.owner	= THIS_MODULE,
diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c
index aac1c07..001088b 100644
--- a/drivers/leds/leds-cobalt-raq.c
+++ b/drivers/leds/leds-cobalt-raq.c
@@ -76,7 +76,7 @@ static struct led_classdev raq_power_off_led = {
 	.default_trigger	= "power-off",
 };
 
-static int __devinit cobalt_raq_led_probe(struct platform_device *pdev)
+static int cobalt_raq_led_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	int retval;
@@ -85,13 +85,13 @@ static int __devinit cobalt_raq_led_probe(struct platform_device *pdev)
 	if (!res)
 		return -EBUSY;
 
-	led_port = ioremap(res->start, resource_size(res));
+	led_port = devm_ioremap(&pdev->dev, res->start, resource_size(res));
 	if (!led_port)
 		return -ENOMEM;
 
 	retval = led_classdev_register(&pdev->dev, &raq_power_off_led);
 	if (retval)
-		goto err_iounmap;
+		goto err_null;
 
 	retval = led_classdev_register(&pdev->dev, &raq_web_led);
 	if (retval)
@@ -102,29 +102,26 @@ static int __devinit cobalt_raq_led_probe(struct platform_device *pdev)
 err_unregister:
 	led_classdev_unregister(&raq_power_off_led);
 
-err_iounmap:
-	iounmap(led_port);
+err_null:
 	led_port = NULL;
 
 	return retval;
 }
 
-static int __devexit cobalt_raq_led_remove(struct platform_device *pdev)
+static int cobalt_raq_led_remove(struct platform_device *pdev)
 {
 	led_classdev_unregister(&raq_power_off_led);
 	led_classdev_unregister(&raq_web_led);
 
-	if (led_port) {
-		iounmap(led_port);
+	if (led_port)
 		led_port = NULL;
-	}
 
 	return 0;
 }
 
 static struct platform_driver cobalt_raq_led_driver = {
 	.probe	= cobalt_raq_led_probe,
-	.remove	= __devexit_p(cobalt_raq_led_remove),
+	.remove	= cobalt_raq_led_remove,
 	.driver = {
 		.name	= "cobalt-raq-leds",
 		.owner	= THIS_MODULE,
diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c
index cc77c9d..c263a21 100644
--- a/drivers/leds/leds-da903x.c
+++ b/drivers/leds/leds-da903x.c
@@ -2,10 +2,10 @@
  * LEDs driver for Dialog Semiconductor DA9030/DA9034
  *
  * Copyright (C) 2008 Compulab, Ltd.
- * 	Mike Rapoport <mike@compulab.co.il>
+ *	Mike Rapoport <mike@compulab.co.il>
  *
  * Copyright (C) 2006-2008 Marvell International Ltd.
- * 	Eric Miao <eric.miao@marvell.com>
+ *	Eric Miao <eric.miao@marvell.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -85,13 +85,13 @@ static void da903x_led_set(struct led_classdev *led_cdev,
 			   enum led_brightness value)
 {
 	struct da903x_led *led;
-	
+
 	led = container_of(led_cdev, struct da903x_led, cdev);
 	led->new_brightness = value;
 	schedule_work(&led->work);
 }
 
-static int __devinit da903x_led_probe(struct platform_device *pdev)
+static int da903x_led_probe(struct platform_device *pdev)
 {
 	struct led_info *pdata = pdev->dev.platform_data;
 	struct da903x_led *led;
@@ -136,7 +136,7 @@ static int __devinit da903x_led_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit da903x_led_remove(struct platform_device *pdev)
+static int da903x_led_remove(struct platform_device *pdev)
 {
 	struct da903x_led *led = platform_get_drvdata(pdev);
 
@@ -150,13 +150,13 @@ static struct platform_driver da903x_led_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= da903x_led_probe,
-	.remove		= __devexit_p(da903x_led_remove),
+	.remove		= da903x_led_remove,
 };
 
 module_platform_driver(da903x_led_driver);
 
 MODULE_DESCRIPTION("LEDs driver for Dialog Semiconductor DA9030/DA9034");
-MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
-	      "Mike Rapoport <mike@compulab.co.il>");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
+MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:da903x-led");
diff --git a/drivers/leds/leds-da9052.c b/drivers/leds/leds-da9052.c
index 58a5244..efec433 100644
--- a/drivers/leds/leds-da9052.c
+++ b/drivers/leds/leds-da9052.c
@@ -102,7 +102,7 @@ static int da9052_configure_leds(struct da9052 *da9052)
 	return error;
 }
 
-static int __devinit da9052_led_probe(struct platform_device *pdev)
+static int da9052_led_probe(struct platform_device *pdev)
 {
 	struct da9052_pdata *pdata;
 	struct da9052 *da9052;
@@ -176,7 +176,7 @@ err:
 	return error;
 }
 
-static int __devexit da9052_led_remove(struct platform_device *pdev)
+static int da9052_led_remove(struct platform_device *pdev)
 {
 	struct da9052_led *led = platform_get_drvdata(pdev);
 	struct da9052_pdata *pdata;
@@ -204,7 +204,7 @@ static struct platform_driver da9052_led_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= da9052_led_probe,
-	.remove		= __devexit_p(da9052_led_remove),
+	.remove		= da9052_led_remove,
 };
 
 module_platform_driver(da9052_led_driver);
diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c
index b9053fa..b4d5a44 100644
--- a/drivers/leds/leds-fsg.c
+++ b/drivers/leds/leds-fsg.c
@@ -20,8 +20,8 @@
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/module.h>
+#include <linux/io.h>
 #include <mach/hardware.h>
-#include <asm/io.h>
 
 #define FSG_LED_WLAN_BIT	0
 #define FSG_LED_WAN_BIT		1
@@ -149,11 +149,10 @@ static int fsg_led_probe(struct platform_device *pdev)
 	int ret;
 
 	/* Map the LED chip select address space */
-	latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
-	if (!latch_address) {
-		ret = -ENOMEM;
-		goto failremap;
-	}
+	latch_address = (unsigned short *) devm_ioremap(&pdev->dev,
+						IXP4XX_EXP_BUS_BASE(2), 512);
+	if (!latch_address)
+		return -ENOMEM;
 
 	latch_value = 0xffff;
 	*latch_address = latch_value;
@@ -195,8 +194,6 @@ static int fsg_led_probe(struct platform_device *pdev)
  failwan:
 	led_classdev_unregister(&fsg_wlan_led);
  failwlan:
-	iounmap(latch_address);
- failremap:
 
 	return ret;
 }
@@ -210,8 +207,6 @@ static int fsg_led_remove(struct platform_device *pdev)
 	led_classdev_unregister(&fsg_sync_led);
 	led_classdev_unregister(&fsg_ring_led);
 
-	iounmap(latch_address);
-
 	return 0;
 }
 
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 087d1e6..1885a26 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -21,6 +21,7 @@
 #include <linux/workqueue.h>
 #include <linux/module.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/err.h>
 
 struct gpio_led_data {
 	struct led_classdev cdev;
@@ -91,7 +92,7 @@ static int gpio_blink_set(struct led_classdev *led_cdev,
 						delay_on, delay_off);
 }
 
-static int __devinit create_gpio_led(const struct gpio_led *template,
+static int create_gpio_led(const struct gpio_led *template,
 	struct gpio_led_data *led_dat, struct device *parent,
 	int (*blink_set)(unsigned, int, unsigned long *, unsigned long *))
 {
@@ -101,15 +102,11 @@ static int __devinit create_gpio_led(const struct gpio_led *template,
 
 	/* skip leds that aren't available */
 	if (!gpio_is_valid(template->gpio)) {
-		printk(KERN_INFO "Skipping unavailable LED gpio %d (%s)\n",
+		dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
 				template->gpio, template->name);
 		return 0;
 	}
 
-	ret = gpio_request(template->gpio, template->name);
-	if (ret < 0)
-		return ret;
-
 	led_dat->cdev.name = template->name;
 	led_dat->cdev.default_trigger = template->default_trigger;
 	led_dat->gpio = template->gpio;
@@ -129,20 +126,19 @@ static int __devinit create_gpio_led(const struct gpio_led *template,
 	if (!template->retain_state_suspended)
 		led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
-	ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state);
+	ret = devm_gpio_request_one(parent, template->gpio,
+			GPIOF_DIR_OUT | (led_dat->active_low ^ state),
+			template->name);
 	if (ret < 0)
-		goto err;
-		
+		return ret;
+
 	INIT_WORK(&led_dat->work, gpio_led_work);
 
 	ret = led_classdev_register(parent, &led_dat->cdev);
 	if (ret < 0)
-		goto err;
+		return ret;
 
 	return 0;
-err:
-	gpio_free(led_dat->gpio);
-	return ret;
 }
 
 static void delete_gpio_led(struct gpio_led_data *led)
@@ -151,7 +147,6 @@ static void delete_gpio_led(struct gpio_led_data *led)
 		return;
 	led_classdev_unregister(&led->cdev);
 	cancel_work_sync(&led->work);
-	gpio_free(led->gpio);
 }
 
 struct gpio_leds_priv {
@@ -167,7 +162,7 @@ static inline int sizeof_gpio_leds_priv(int num_leds)
 
 /* Code to create from OpenFirmware platform devices */
 #ifdef CONFIG_OF_GPIO
-static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev)
+static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node, *child;
 	struct gpio_leds_priv *priv;
@@ -176,12 +171,16 @@ static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_dev
 	/* count LEDs in this device, so we know how much to allocate */
 	count = of_get_child_count(np);
 	if (!count)
-		return NULL;
+		return ERR_PTR(-ENODEV);
+
+	for_each_child_of_node(np, child)
+		if (of_get_gpio(child, 0) == -EPROBE_DEFER)
+			return ERR_PTR(-EPROBE_DEFER);
 
 	priv = devm_kzalloc(&pdev->dev, sizeof_gpio_leds_priv(count),
 			GFP_KERNEL);
 	if (!priv)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	for_each_child_of_node(np, child) {
 		struct gpio_led led = {};
@@ -216,7 +215,7 @@ static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_dev
 err:
 	for (count = priv->num_leds - 2; count >= 0; count--)
 		delete_gpio_led(&priv->leds[count]);
-	return NULL;
+	return ERR_PTR(-ENODEV);
 }
 
 static const struct of_device_id of_gpio_leds_match[] = {
@@ -224,14 +223,14 @@ static const struct of_device_id of_gpio_leds_match[] = {
 	{},
 };
 #else /* CONFIG_OF_GPIO */
-static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev)
+static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
 {
-	return NULL;
+	return ERR_PTR(-ENODEV);
 }
 #endif /* CONFIG_OF_GPIO */
 
 
-static int __devinit gpio_led_probe(struct platform_device *pdev)
+static int gpio_led_probe(struct platform_device *pdev)
 {
 	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
 	struct gpio_leds_priv *priv;
@@ -264,8 +263,8 @@ static int __devinit gpio_led_probe(struct platform_device *pdev)
 		}
 	} else {
 		priv = gpio_leds_create_of(pdev);
-		if (!priv)
-			return -ENODEV;
+		if (IS_ERR(priv))
+			return PTR_ERR(priv);
 	}
 
 	platform_set_drvdata(pdev, priv);
@@ -273,7 +272,7 @@ static int __devinit gpio_led_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit gpio_led_remove(struct platform_device *pdev)
+static int gpio_led_remove(struct platform_device *pdev)
 {
 	struct gpio_leds_priv *priv = platform_get_drvdata(pdev);
 	int i;
@@ -288,7 +287,7 @@ static int __devexit gpio_led_remove(struct platform_device *pdev)
 
 static struct platform_driver gpio_led_driver = {
 	.probe		= gpio_led_probe,
-	.remove		= __devexit_p(gpio_led_remove),
+	.remove		= gpio_led_remove,
 	.driver		= {
 		.name	= "leds-gpio",
 		.owner	= THIS_MODULE,
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
index b26306f..2141454 100644
--- a/drivers/leds/leds-lm3530.c
+++ b/drivers/leds/leds-lm3530.c
@@ -377,7 +377,7 @@ static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute
 }
 static DEVICE_ATTR(mode, 0644, lm3530_mode_get, lm3530_mode_set);
 
-static int __devinit lm3530_probe(struct i2c_client *client,
+static int lm3530_probe(struct i2c_client *client,
 			   const struct i2c_device_id *id)
 {
 	struct lm3530_platform_data *pdata = client->dev.platform_data;
@@ -452,7 +452,7 @@ err_create_file:
 	return err;
 }
 
-static int __devexit lm3530_remove(struct i2c_client *client)
+static int lm3530_remove(struct i2c_client *client)
 {
 	struct lm3530_data *drvdata = i2c_get_clientdata(client);
 
@@ -472,7 +472,7 @@ MODULE_DEVICE_TABLE(i2c, lm3530_id);
 
 static struct i2c_driver lm3530_i2c_driver = {
 	.probe = lm3530_probe,
-	.remove = __devexit_p(lm3530_remove),
+	.remove = lm3530_remove,
 	.id_table = lm3530_id,
 	.driver = {
 		.name = LM3530_NAME,
diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c
index f6837b9..bbf24d0 100644
--- a/drivers/leds/leds-lm3533.c
+++ b/drivers/leds/leds-lm3533.c
@@ -646,7 +646,7 @@ static struct attribute_group lm3533_led_attribute_group = {
 	.attrs		= lm3533_led_attributes
 };
 
-static int __devinit lm3533_led_setup(struct lm3533_led *led,
+static int lm3533_led_setup(struct lm3533_led *led,
 					struct lm3533_led_platform_data *pdata)
 {
 	int ret;
@@ -658,7 +658,7 @@ static int __devinit lm3533_led_setup(struct lm3533_led *led,
 	return lm3533_ctrlbank_set_pwm(&led->cb, pdata->pwm);
 }
 
-static int __devinit lm3533_led_probe(struct platform_device *pdev)
+static int lm3533_led_probe(struct platform_device *pdev)
 {
 	struct lm3533 *lm3533;
 	struct lm3533_led_platform_data *pdata;
@@ -742,7 +742,7 @@ err_unregister:
 	return ret;
 }
 
-static int __devexit lm3533_led_remove(struct platform_device *pdev)
+static int lm3533_led_remove(struct platform_device *pdev)
 {
 	struct lm3533_led *led = platform_get_drvdata(pdev);
 
@@ -774,7 +774,7 @@ static struct platform_driver lm3533_led_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe		= lm3533_led_probe,
-	.remove		= __devexit_p(lm3533_led_remove),
+	.remove		= lm3533_led_remove,
 	.shutdown	= lm3533_led_shutdown,
 };
 module_platform_driver(lm3533_led_driver);
diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c
index 065ec01..65d7928 100644
--- a/drivers/leds/leds-lm355x.c
+++ b/drivers/leds/leds-lm355x.c
@@ -168,7 +168,7 @@ static char lm355x_name[][I2C_NAME_SIZE] = {
 };
 
 /* chip initialize */
-static int __devinit lm355x_chip_init(struct lm355x_chip_data *chip)
+static int lm355x_chip_init(struct lm355x_chip_data *chip)
 {
 	int ret;
 	unsigned int reg_val;
@@ -408,10 +408,10 @@ static ssize_t lm3556_indicator_pattern_store(struct device *dev,
 	return size;
 out:
 	dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
-	return size;
+	return ret;
 }
 
-static DEVICE_ATTR(pattern, 0666, NULL, lm3556_indicator_pattern_store);
+static DEVICE_ATTR(pattern, S_IWUSR, NULL, lm3556_indicator_pattern_store);
 
 static const struct regmap_config lm355x_regmap = {
 	.reg_bits = 8,
@@ -420,7 +420,7 @@ static const struct regmap_config lm355x_regmap = {
 };
 
 /* module initialize */
-static int __devinit lm355x_probe(struct i2c_client *client,
+static int lm355x_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
 	struct lm355x_platform_data *pdata = client->dev.platform_data;
@@ -526,7 +526,7 @@ err_out:
 	return err;
 }
 
-static int __devexit lm355x_remove(struct i2c_client *client)
+static int lm355x_remove(struct i2c_client *client)
 {
 	struct lm355x_chip_data *chip = i2c_get_clientdata(client);
 	struct lm355x_reg_data *preg = chip->regs;
@@ -560,7 +560,7 @@ static struct i2c_driver lm355x_i2c_driver = {
 		   .pm = NULL,
 		   },
 	.probe = lm355x_probe,
-	.remove = __devexit_p(lm355x_remove),
+	.remove = lm355x_remove,
 	.id_table = lm355x_id,
 };
 
diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c
index 3285006..07b3dde 100644
--- a/drivers/leds/leds-lm3642.c
+++ b/drivers/leds/leds-lm3642.c
@@ -93,7 +93,7 @@ struct lm3642_chip_data {
 };
 
 /* chip initialize */
-static int __devinit lm3642_chip_init(struct lm3642_chip_data *chip)
+static int lm3642_chip_init(struct lm3642_chip_data *chip)
 {
 	int ret;
 	struct lm3642_platform_data *pdata = chip->pdata;
@@ -201,13 +201,13 @@ static ssize_t lm3642_torch_pin_store(struct device *dev,
 	return size;
 out:
 	dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
-	return size;
+	return ret;
 out_strtoint:
 	dev_err(chip->dev, "%s: fail to change str to int\n", __func__);
-	return size;
+	return ret;
 }
 
-static DEVICE_ATTR(torch_pin, 0666, NULL, lm3642_torch_pin_store);
+static DEVICE_ATTR(torch_pin, S_IWUSR, NULL, lm3642_torch_pin_store);
 
 static void lm3642_deferred_torch_brightness_set(struct work_struct *work)
 {
@@ -258,13 +258,13 @@ static ssize_t lm3642_strobe_pin_store(struct device *dev,
 	return size;
 out:
 	dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
-	return size;
+	return ret;
 out_strtoint:
 	dev_err(chip->dev, "%s: fail to change str to int\n", __func__);
-	return size;
+	return ret;
 }
 
-static DEVICE_ATTR(strobe_pin, 0666, NULL, lm3642_strobe_pin_store);
+static DEVICE_ATTR(strobe_pin, S_IWUSR, NULL, lm3642_strobe_pin_store);
 
 static void lm3642_deferred_strobe_brightness_set(struct work_struct *work)
 {
@@ -313,7 +313,7 @@ static const struct regmap_config lm3642_regmap = {
 	.max_register = REG_MAX,
 };
 
-static int __devinit lm3642_probe(struct i2c_client *client,
+static int lm3642_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
 	struct lm3642_platform_data *pdata = client->dev.platform_data;
@@ -420,7 +420,7 @@ err_out:
 	return err;
 }
 
-static int __devexit lm3642_remove(struct i2c_client *client)
+static int lm3642_remove(struct i2c_client *client)
 {
 	struct lm3642_chip_data *chip = i2c_get_clientdata(client);
 
@@ -450,7 +450,7 @@ static struct i2c_driver lm3642_i2c_driver = {
 		   .pm = NULL,
 		   },
 	.probe = lm3642_probe,
-	.remove = __devexit_p(lm3642_remove),
+	.remove = lm3642_remove,
 	.id_table = lm3642_id,
 };
 
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c
index c298f7d..0c4386e 100644
--- a/drivers/leds/leds-lp3944.c
+++ b/drivers/leds/leds-lp3944.c
@@ -86,7 +86,7 @@ static int lp3944_reg_read(struct i2c_client *client, u8 reg, u8 *value)
 
 	tmp = i2c_smbus_read_byte_data(client, reg);
 	if (tmp < 0)
-		return -EINVAL;
+		return tmp;
 
 	*value = tmp;
 
@@ -374,7 +374,7 @@ exit:
 	return err;
 }
 
-static int __devinit lp3944_probe(struct i2c_client *client,
+static int lp3944_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
 	struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data;
@@ -411,7 +411,7 @@ static int __devinit lp3944_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int __devexit lp3944_remove(struct i2c_client *client)
+static int lp3944_remove(struct i2c_client *client)
 {
 	struct lp3944_platform_data *pdata = client->dev.platform_data;
 	struct lp3944_data *data = i2c_get_clientdata(client);
@@ -446,7 +446,7 @@ static struct i2c_driver lp3944_driver = {
 		   .name = "lp3944",
 	},
 	.probe    = lp3944_probe,
-	.remove   = __devexit_p(lp3944_remove),
+	.remove   = lp3944_remove,
 	.id_table = lp3944_id,
 };
 
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
index 2064aef..2bee6b9 100644
--- a/drivers/leds/leds-lp5521.c
+++ b/drivers/leds/leds-lp5521.c
@@ -152,7 +152,7 @@ static int lp5521_read(struct i2c_client *client, u8 reg, u8 *buf)
 
 	ret = i2c_smbus_read_byte_data(client, reg);
 	if (ret < 0)
-		return -EIO;
+		return ret;
 
 	*buf = ret;
 	return 0;
@@ -616,7 +616,7 @@ static ssize_t store_led_pattern(struct device *dev,
 	unsigned long val;
 	int ret;
 
-	ret = strict_strtoul(buf, 16, &val);
+	ret = kstrtoul(buf, 16, &val);
 	if (ret)
 		return ret;
 
@@ -687,7 +687,7 @@ static void lp5521_unregister_sysfs(struct i2c_client *client)
 				&lp5521_led_attribute_group);
 }
 
-static int __devinit lp5521_init_led(struct lp5521_led *led,
+static int lp5521_init_led(struct lp5521_led *led,
 				struct i2c_client *client,
 				int chan, struct lp5521_platform_data *pdata)
 {
@@ -736,7 +736,7 @@ static int __devinit lp5521_init_led(struct lp5521_led *led,
 	return 0;
 }
 
-static int __devinit lp5521_probe(struct i2c_client *client,
+static int lp5521_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct lp5521_chip		*chip;
@@ -855,7 +855,7 @@ fail1:
 	return ret;
 }
 
-static int __devexit lp5521_remove(struct i2c_client *client)
+static int lp5521_remove(struct i2c_client *client)
 {
 	struct lp5521_chip *chip = i2c_get_clientdata(client);
 	int i;
@@ -886,7 +886,7 @@ static struct i2c_driver lp5521_driver = {
 		.name	= "lp5521",
 	},
 	.probe		= lp5521_probe,
-	.remove		= __devexit_p(lp5521_remove),
+	.remove		= lp5521_remove,
 	.id_table	= lp5521_id,
 };
 
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index 97994ff..7f5be89 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -171,7 +171,7 @@ static int lp5523_read(struct i2c_client *client, u8 reg, u8 *buf)
 	s32 ret = i2c_smbus_read_byte_data(client, reg);
 
 	if (ret < 0)
-		return -EIO;
+		return ret;
 
 	*buf = ret;
 	return 0;
@@ -248,7 +248,10 @@ static int lp5523_configure(struct i2c_client *client)
 
 	/* Let the programs run for couple of ms and check the engine status */
 	usleep_range(3000, 6000);
-	lp5523_read(client, LP5523_REG_STATUS, &status);
+	ret = lp5523_read(client, LP5523_REG_STATUS, &status);
+	if (ret < 0)
+		return ret;
+
 	status &= LP5523_ENG_STATUS_MASK;
 
 	if (status == LP5523_ENG_STATUS_MASK) {
@@ -464,10 +467,16 @@ static ssize_t lp5523_selftest(struct device *dev,
 				    LP5523_EN_LEDTEST | 16);
 	usleep_range(3000, 6000); /* ADC conversion time is typically 2.7 ms */
 	ret = lp5523_read(chip->client, LP5523_REG_STATUS, &status);
+	if (ret < 0)
+		goto fail;
+
 	if (!(status & LP5523_LEDTEST_DONE))
 		usleep_range(3000, 6000); /* Was not ready. Wait little bit */
 
-	ret |= lp5523_read(chip->client, LP5523_REG_LED_TEST_ADC, &vdd);
+	ret = lp5523_read(chip->client, LP5523_REG_LED_TEST_ADC, &vdd);
+	if (ret < 0)
+		goto fail;
+
 	vdd--;	/* There may be some fluctuation in measurement */
 
 	for (i = 0; i < LP5523_LEDS; i++) {
@@ -489,9 +498,14 @@ static ssize_t lp5523_selftest(struct device *dev,
 		/* ADC conversion time is 2.7 ms typically */
 		usleep_range(3000, 6000);
 		ret = lp5523_read(chip->client, LP5523_REG_STATUS, &status);
+		if (ret < 0)
+			goto fail;
+
 		if (!(status & LP5523_LEDTEST_DONE))
 			usleep_range(3000, 6000);/* Was not ready. Wait. */
-		ret |= lp5523_read(chip->client, LP5523_REG_LED_TEST_ADC, &adc);
+		ret = lp5523_read(chip->client, LP5523_REG_LED_TEST_ADC, &adc);
+		if (ret < 0)
+			goto fail;
 
 		if (adc >= vdd || adc < LP5523_ADC_SHORTCIRC_LIM)
 			pos += sprintf(buf + pos, "LED %d FAIL\n", i);
@@ -696,7 +710,7 @@ static ssize_t store_current(struct device *dev,
 	ssize_t ret;
 	unsigned long curr;
 
-	if (strict_strtoul(buf, 0, &curr))
+	if (kstrtoul(buf, 0, &curr))
 		return -EINVAL;
 
 	if (curr > led->max_current)
@@ -833,7 +847,7 @@ static int __init lp5523_init_engine(struct lp5523_engine *engine, int id)
 	return 0;
 }
 
-static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
+static int lp5523_init_led(struct lp5523_led *led, struct device *dev,
 			   int chan, struct lp5523_platform_data *pdata,
 			   const char *chip_name)
 {
@@ -882,7 +896,7 @@ static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
 	return 0;
 }
 
-static int __devinit lp5523_probe(struct i2c_client *client,
+static int lp5523_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct lp5523_chip		*chip;
diff --git a/drivers/leds/leds-lp8788.c b/drivers/leds/leds-lp8788.c
index 64009a1..4353942 100644
--- a/drivers/leds/leds-lp8788.c
+++ b/drivers/leds/leds-lp8788.c
@@ -125,7 +125,7 @@ static void lp8788_brightness_set(struct led_classdev *led_cdev,
 	schedule_work(&led->work);
 }
 
-static __devinit int lp8788_led_probe(struct platform_device *pdev)
+static int lp8788_led_probe(struct platform_device *pdev)
 {
 	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
 	struct lp8788_led_platform_data *led_pdata;
@@ -167,7 +167,7 @@ static __devinit int lp8788_led_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit lp8788_led_remove(struct platform_device *pdev)
+static int lp8788_led_remove(struct platform_device *pdev)
 {
 	struct lp8788_led *led = platform_get_drvdata(pdev);
 
@@ -179,7 +179,7 @@ static int __devexit lp8788_led_remove(struct platform_device *pdev)
 
 static struct platform_driver lp8788_led_driver = {
 	.probe = lp8788_led_probe,
-	.remove = __devexit_p(lp8788_led_remove),
+	.remove = lp8788_led_remove,
 	.driver = {
 		.name = LP8788_DEV_KEYLED,
 		.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
index 09a7322..c9b9e1f 100644
--- a/drivers/leds/leds-lt3593.c
+++ b/drivers/leds/leds-lt3593.c
@@ -82,22 +82,18 @@ static void lt3593_led_set(struct led_classdev *led_cdev,
 	schedule_work(&led_dat->work);
 }
 
-static int __devinit create_lt3593_led(const struct gpio_led *template,
+static int create_lt3593_led(const struct gpio_led *template,
 	struct lt3593_led_data *led_dat, struct device *parent)
 {
 	int ret, state;
 
 	/* skip leds on GPIOs that aren't available */
 	if (!gpio_is_valid(template->gpio)) {
-		printk(KERN_INFO "%s: skipping unavailable LT3593 LED at gpio %d (%s)\n",
+		dev_info(parent, "%s: skipping unavailable LT3593 LED at gpio %d (%s)\n",
 				KBUILD_MODNAME, template->gpio, template->name);
 		return 0;
 	}
 
-	ret = gpio_request(template->gpio, template->name);
-	if (ret < 0)
-		return ret;
-
 	led_dat->cdev.name = template->name;
 	led_dat->cdev.default_trigger = template->default_trigger;
 	led_dat->gpio = template->gpio;
@@ -110,24 +106,21 @@ static int __devinit create_lt3593_led(const struct gpio_led *template,
 	if (!template->retain_state_suspended)
 		led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
-	ret = gpio_direction_output(led_dat->gpio, state);
+	ret = devm_gpio_request_one(parent, template->gpio,
+				    GPIOF_DIR_OUT | state, template->name);
 	if (ret < 0)
-		goto err;
+		return ret;
 
 	INIT_WORK(&led_dat->work, lt3593_led_work);
 
 	ret = led_classdev_register(parent, &led_dat->cdev);
 	if (ret < 0)
-		goto err;
+		return ret;
 
-	printk(KERN_INFO "%s: registered LT3593 LED '%s' at GPIO %d\n",
+	dev_info(parent, "%s: registered LT3593 LED '%s' at GPIO %d\n",
 		KBUILD_MODNAME, template->name, template->gpio);
 
 	return 0;
-
-err:
-	gpio_free(led_dat->gpio);
-	return ret;
 }
 
 static void delete_lt3593_led(struct lt3593_led_data *led)
@@ -137,10 +130,9 @@ static void delete_lt3593_led(struct lt3593_led_data *led)
 
 	led_classdev_unregister(&led->cdev);
 	cancel_work_sync(&led->work);
-	gpio_free(led->gpio);
 }
 
-static int __devinit lt3593_led_probe(struct platform_device *pdev)
+static int lt3593_led_probe(struct platform_device *pdev)
 {
 	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
 	struct lt3593_led_data *leds_data;
@@ -173,7 +165,7 @@ err:
 	return ret;
 }
 
-static int __devexit lt3593_led_remove(struct platform_device *pdev)
+static int lt3593_led_remove(struct platform_device *pdev)
 {
 	int i;
 	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
@@ -189,7 +181,7 @@ static int __devexit lt3593_led_remove(struct platform_device *pdev)
 
 static struct platform_driver lt3593_led_driver = {
 	.probe		= lt3593_led_probe,
-	.remove		= __devexit_p(lt3593_led_remove),
+	.remove		= lt3593_led_remove,
 	.driver		= {
 		.name	= "leds-lt3593",
 		.owner	= THIS_MODULE,
diff --git a/drivers/leds/leds-max8997.c b/drivers/leds/leds-max8997.c
index 569e36d..f449a8b 100644
--- a/drivers/leds/leds-max8997.c
+++ b/drivers/leds/leds-max8997.c
@@ -229,7 +229,7 @@ static ssize_t max8997_led_store_mode(struct device *dev,
 
 static DEVICE_ATTR(mode, 0644, max8997_led_show_mode, max8997_led_store_mode);
 
-static int __devinit max8997_led_probe(struct platform_device *pdev)
+static int max8997_led_probe(struct platform_device *pdev)
 {
 	struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 	struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -292,7 +292,7 @@ static int __devinit max8997_led_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit max8997_led_remove(struct platform_device *pdev)
+static int max8997_led_remove(struct platform_device *pdev)
 {
 	struct max8997_led *led = platform_get_drvdata(pdev);
 
@@ -308,7 +308,7 @@ static struct platform_driver max8997_led_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe  = max8997_led_probe,
-	.remove = __devexit_p(max8997_led_remove),
+	.remove = max8997_led_remove,
 };
 
 module_platform_driver(max8997_led_driver);
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
index 2a5d434..e942ada 100644
--- a/drivers/leds/leds-mc13783.c
+++ b/drivers/leds/leds-mc13783.c
@@ -128,7 +128,7 @@ static void mc13783_led_set(struct led_classdev *led_cdev,
 	schedule_work(&led->work);
 }
 
-static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current)
+static int mc13783_led_setup(struct mc13783_led *led, int max_current)
 {
 	int shift = 0;
 	int mask = 0;
@@ -181,7 +181,7 @@ static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current)
 	return ret;
 }
 
-static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
+static int mc13783_leds_prepare(struct platform_device *pdev)
 {
 	struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct mc13xxx *dev = dev_get_drvdata(pdev->dev.parent);
@@ -262,7 +262,7 @@ out:
 	return ret;
 }
 
-static int __devinit mc13783_led_probe(struct platform_device *pdev)
+static int mc13783_led_probe(struct platform_device *pdev)
 {
 	struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct mc13xxx_led_platform_data *led_cur;
@@ -348,7 +348,7 @@ err_register:
 	return ret;
 }
 
-static int __devexit mc13783_led_remove(struct platform_device *pdev)
+static int mc13783_led_remove(struct platform_device *pdev)
 {
 	struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct mc13783_led *led = platform_get_drvdata(pdev);
@@ -381,7 +381,7 @@ static struct platform_driver mc13783_led_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= mc13783_led_probe,
-	.remove		= __devexit_p(mc13783_led_remove),
+	.remove		= mc13783_led_remove,
 };
 
 module_platform_driver(mc13783_led_driver);
diff --git a/drivers/leds/leds-net48xx.c b/drivers/leds/leds-net48xx.c
index f117f73..27d06c5 100644
--- a/drivers/leds/leds-net48xx.c
+++ b/drivers/leds/leds-net48xx.c
@@ -15,7 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/err.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/nsc_gpio.h>
 #include <linux/scx200_gpio.h>
 #include <linux/module.h>
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
index 461bbf9..c61c5eb 100644
--- a/drivers/leds/leds-netxbig.c
+++ b/drivers/leds/leds-netxbig.c
@@ -71,7 +71,7 @@ static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext,
 	spin_unlock_irqrestore(&gpio_ext_lock, flags);
 }
 
-static int __devinit gpio_ext_init(struct netxbig_gpio_ext *gpio_ext)
+static int gpio_ext_init(struct netxbig_gpio_ext *gpio_ext)
 {
 	int err;
 	int i;
@@ -243,7 +243,7 @@ static ssize_t netxbig_led_sata_store(struct device *dev,
 	int mode_val;
 	int ret;
 
-	ret = strict_strtoul(buff, 10, &enable);
+	ret = kstrtoul(buff, 10, &enable);
 	if (ret < 0)
 		return ret;
 
@@ -301,7 +301,7 @@ static void delete_netxbig_led(struct netxbig_led_data *led_dat)
 	led_classdev_unregister(&led_dat->cdev);
 }
 
-static int __devinit
+static int
 create_netxbig_led(struct platform_device *pdev,
 		   struct netxbig_led_data *led_dat,
 		   const struct netxbig_led *template)
@@ -352,7 +352,7 @@ create_netxbig_led(struct platform_device *pdev,
 	return ret;
 }
 
-static int __devinit netxbig_led_probe(struct platform_device *pdev)
+static int netxbig_led_probe(struct platform_device *pdev)
 {
 	struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
 	struct netxbig_led_data *leds_data;
@@ -389,7 +389,7 @@ err_free_leds:
 	return ret;
 }
 
-static int __devexit netxbig_led_remove(struct platform_device *pdev)
+static int netxbig_led_remove(struct platform_device *pdev)
 {
 	struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
 	struct netxbig_led_data *leds_data;
@@ -407,7 +407,7 @@ static int __devexit netxbig_led_remove(struct platform_device *pdev)
 
 static struct platform_driver netxbig_led_driver = {
 	.probe		= netxbig_led_probe,
-	.remove		= __devexit_p(netxbig_led_remove),
+	.remove		= netxbig_led_remove,
 	.driver		= {
 		.name	= "leds-netxbig",
 		.owner	= THIS_MODULE,
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index d176ec8..d978171 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_gpio.h>
 
 /*
  * The Network Space v2 dual-GPIO LED is wired to a CPLD and can blink in
@@ -149,7 +150,7 @@ static ssize_t ns2_led_sata_store(struct device *dev,
 	unsigned long enable;
 	enum ns2_led_modes mode;
 
-	ret = strict_strtoul(buff, 10, &enable);
+	ret = kstrtoul(buff, 10, &enable);
 	if (ret < 0)
 		return ret;
 
@@ -184,36 +185,29 @@ static ssize_t ns2_led_sata_show(struct device *dev,
 
 static DEVICE_ATTR(sata, 0644, ns2_led_sata_show, ns2_led_sata_store);
 
-static int __devinit
+static int
 create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
 	       const struct ns2_led *template)
 {
 	int ret;
 	enum ns2_led_modes mode;
 
-	ret = gpio_request(template->cmd, template->name);
-	if (ret == 0) {
-		ret = gpio_direction_output(template->cmd,
-					    gpio_get_value(template->cmd));
-		if (ret)
-			gpio_free(template->cmd);
-	}
+	ret = devm_gpio_request_one(&pdev->dev, template->cmd,
+			GPIOF_DIR_OUT | gpio_get_value(template->cmd),
+			template->name);
 	if (ret) {
 		dev_err(&pdev->dev, "%s: failed to setup command GPIO\n",
 			template->name);
+		return ret;
 	}
 
-	ret = gpio_request(template->slow, template->name);
-	if (ret == 0) {
-		ret = gpio_direction_output(template->slow,
-					    gpio_get_value(template->slow));
-		if (ret)
-			gpio_free(template->slow);
-	}
+	ret = devm_gpio_request_one(&pdev->dev, template->slow,
+			GPIOF_DIR_OUT | gpio_get_value(template->slow),
+			template->name);
 	if (ret) {
 		dev_err(&pdev->dev, "%s: failed to setup slow GPIO\n",
 			template->name);
-		goto err_free_cmd;
+		return ret;
 	}
 
 	rwlock_init(&led_dat->rw_lock);
@@ -228,7 +222,7 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
 
 	ret = ns2_led_get_mode(led_dat, &mode);
 	if (ret < 0)
-		goto err_free_slow;
+		return ret;
 
 	/* Set LED initial state. */
 	led_dat->sata = (mode == NS_V2_LED_SATA) ? 1 : 0;
@@ -237,7 +231,7 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
 
 	ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
 	if (ret < 0)
-		goto err_free_slow;
+		return ret;
 
 	ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata);
 	if (ret < 0)
@@ -247,11 +241,6 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
 
 err_free_cdev:
 	led_classdev_unregister(&led_dat->cdev);
-err_free_slow:
-	gpio_free(led_dat->slow);
-err_free_cmd:
-	gpio_free(led_dat->cmd);
-
 	return ret;
 }
 
@@ -259,22 +248,90 @@ static void delete_ns2_led(struct ns2_led_data *led_dat)
 {
 	device_remove_file(led_dat->cdev.dev, &dev_attr_sata);
 	led_classdev_unregister(&led_dat->cdev);
-	gpio_free(led_dat->cmd);
-	gpio_free(led_dat->slow);
 }
 
-static int __devinit ns2_led_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF_GPIO
+/*
+ * Translate OpenFirmware node properties into platform_data.
+ */
+static int
+ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata)
+{
+	struct device_node *np = dev->of_node;
+	struct device_node *child;
+	struct ns2_led *leds;
+	int num_leds = 0;
+	int i = 0;
+
+	num_leds = of_get_child_count(np);
+	if (!num_leds)
+		return -ENODEV;
+
+	leds = devm_kzalloc(dev, num_leds * sizeof(struct ns2_led),
+			    GFP_KERNEL);
+	if (!leds)
+		return -ENOMEM;
+
+	for_each_child_of_node(np, child) {
+		const char *string;
+		int ret;
+
+		ret = of_get_named_gpio(child, "cmd-gpio", 0);
+		if (ret < 0)
+			return ret;
+		leds[i].cmd = ret;
+		ret = of_get_named_gpio(child, "slow-gpio", 0);
+		if (ret < 0)
+			return ret;
+		leds[i].slow = ret;
+		ret = of_property_read_string(child, "label", &string);
+		leds[i].name = (ret == 0) ? string : child->name;
+		ret = of_property_read_string(child, "linux,default-trigger",
+					      &string);
+		if (ret == 0)
+			leds[i].default_trigger = string;
+
+		i++;
+	}
+
+	pdata->leds = leds;
+	pdata->num_leds = num_leds;
+
+	return 0;
+}
+
+static const struct of_device_id of_ns2_leds_match[] = {
+	{ .compatible = "lacie,ns2-leds", },
+	{},
+};
+#endif /* CONFIG_OF_GPIO */
+
+static int ns2_led_probe(struct platform_device *pdev)
 {
 	struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
 	struct ns2_led_data *leds_data;
 	int i;
 	int ret;
 
+#ifdef CONFIG_OF_GPIO
+	if (!pdata) {
+		pdata = devm_kzalloc(&pdev->dev,
+				     sizeof(struct ns2_led_platform_data),
+				     GFP_KERNEL);
+		if (!pdata)
+			return -ENOMEM;
+
+		ret = ns2_leds_get_of_pdata(&pdev->dev, pdata);
+		if (ret)
+			return ret;
+	}
+#else
 	if (!pdata)
 		return -EINVAL;
+#endif /* CONFIG_OF_GPIO */
 
 	leds_data = devm_kzalloc(&pdev->dev, sizeof(struct ns2_led_data) *
-			    pdata->num_leds, GFP_KERNEL);
+				 pdata->num_leds, GFP_KERNEL);
 	if (!leds_data)
 		return -ENOMEM;
 
@@ -292,7 +349,7 @@ static int __devinit ns2_led_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit ns2_led_remove(struct platform_device *pdev)
+static int ns2_led_remove(struct platform_device *pdev)
 {
 	int i;
 	struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
@@ -310,10 +367,11 @@ static int __devexit ns2_led_remove(struct platform_device *pdev)
 
 static struct platform_driver ns2_led_driver = {
 	.probe		= ns2_led_probe,
-	.remove		= __devexit_p(ns2_led_remove),
+	.remove		= ns2_led_remove,
 	.driver		= {
-		.name	= "leds-ns2",
-		.owner	= THIS_MODULE,
+		.name		= "leds-ns2",
+		.owner		= THIS_MODULE,
+		.of_match_table	= of_match_ptr(of_ns2_leds_match),
 	},
 };
 
diff --git a/drivers/leds/leds-ot200.c b/drivers/leds/leds-ot200.c
index c464682..ee14662 100644
--- a/drivers/leds/leds-ot200.c
+++ b/drivers/leds/leds-ot200.c
@@ -115,7 +115,7 @@ static void ot200_led_brightness_set(struct led_classdev *led_cdev,
 	spin_unlock_irqrestore(&value_lock, flags);
 }
 
-static int __devinit ot200_led_probe(struct platform_device *pdev)
+static int ot200_led_probe(struct platform_device *pdev)
 {
 	int i;
 	int ret;
@@ -144,7 +144,7 @@ err:
 	return ret;
 }
 
-static int __devexit ot200_led_remove(struct platform_device *pdev)
+static int ot200_led_remove(struct platform_device *pdev)
 {
 	int i;
 
@@ -156,7 +156,7 @@ static int __devexit ot200_led_remove(struct platform_device *pdev)
 
 static struct platform_driver ot200_led_driver = {
 	.probe		= ot200_led_probe,
-	.remove		= __devexit_p(ot200_led_remove),
+	.remove		= ot200_led_remove,
 	.driver		= {
 		.name	= "leds-ot200",
 		.owner	= THIS_MODULE,
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index aef3cf0..edf485b 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -255,7 +255,7 @@ static void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness v
 	schedule_work(&pca955x->work);
 }
 
-static int __devinit pca955x_probe(struct i2c_client *client,
+static int pca955x_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	struct pca955x *pca955x;
@@ -277,7 +277,7 @@ static int __devinit pca955x_probe(struct i2c_client *client,
 		return -ENODEV;
 	}
 
-	printk(KERN_INFO "leds-pca955x: Using %s %d-bit LED driver at "
+	dev_info(&client->dev, "leds-pca955x: Using %s %d-bit LED driver at "
 			"slave address 0x%02x\n",
 			id->name, chip->bits, client->addr);
 
@@ -363,7 +363,7 @@ exit:
 	return err;
 }
 
-static int __devexit pca955x_remove(struct i2c_client *client)
+static int pca955x_remove(struct i2c_client *client)
 {
 	struct pca955x *pca955x = i2c_get_clientdata(client);
 	int i;
@@ -382,7 +382,7 @@ static struct i2c_driver pca955x_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe	= pca955x_probe,
-	.remove	= __devexit_p(pca955x_remove),
+	.remove	= pca955x_remove,
 	.id_table = pca955x_id,
 };
 
diff --git a/drivers/leds/leds-pca9633.c b/drivers/leds/leds-pca9633.c
index 2f2f9c4..9aae567 100644
--- a/drivers/leds/leds-pca9633.c
+++ b/drivers/leds/leds-pca9633.c
@@ -93,7 +93,7 @@ static void pca9633_led_set(struct led_classdev *led_cdev,
 	schedule_work(&pca9633->work);
 }
 
-static int __devinit pca9633_probe(struct i2c_client *client,
+static int pca9633_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	struct pca9633_led *pca9633;
@@ -164,7 +164,7 @@ exit:
 	return err;
 }
 
-static int __devexit pca9633_remove(struct i2c_client *client)
+static int pca9633_remove(struct i2c_client *client)
 {
 	struct pca9633_led *pca9633 = i2c_get_clientdata(client);
 	int i;
@@ -183,7 +183,7 @@ static struct i2c_driver pca9633_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe	= pca9633_probe,
-	.remove	= __devexit_p(pca9633_remove),
+	.remove	= pca9633_remove,
 	.id_table = pca9633_id,
 };
 
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index f2e44c7..2157524 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -26,7 +26,7 @@
 struct led_pwm_data {
 	struct led_classdev	cdev;
 	struct pwm_device	*pwm;
-	unsigned int 		active_low;
+	unsigned int		active_low;
 	unsigned int		period;
 };
 
@@ -107,7 +107,7 @@ err:
 	return ret;
 }
 
-static int __devexit led_pwm_remove(struct platform_device *pdev)
+static int led_pwm_remove(struct platform_device *pdev)
 {
 	int i;
 	struct led_pwm_platform_data *pdata = pdev->dev.platform_data;
@@ -125,7 +125,7 @@ static int __devexit led_pwm_remove(struct platform_device *pdev)
 
 static struct platform_driver led_pwm_driver = {
 	.probe		= led_pwm_probe,
-	.remove		= __devexit_p(led_pwm_remove),
+	.remove		= led_pwm_remove,
 	.driver		= {
 		.name	= "leds_pwm",
 		.owner	= THIS_MODULE,
diff --git a/drivers/leds/leds-rb532.c b/drivers/leds/leds-rb532.c
index a7815b6..9ebdd50 100644
--- a/drivers/leds/leds-rb532.c
+++ b/drivers/leds/leds-rb532.c
@@ -37,12 +37,12 @@ static struct led_classdev rb532_uled = {
 	.default_trigger = "nand-disk",
 };
 
-static int __devinit rb532_led_probe(struct platform_device *pdev)
+static int rb532_led_probe(struct platform_device *pdev)
 {
 	return led_classdev_register(&pdev->dev, &rb532_uled);
 }
 
-static int __devexit rb532_led_remove(struct platform_device *pdev)
+static int rb532_led_remove(struct platform_device *pdev)
 {
 	led_classdev_unregister(&rb532_uled);
 	return 0;
@@ -50,7 +50,7 @@ static int __devexit rb532_led_remove(struct platform_device *pdev)
 
 static struct platform_driver rb532_led_driver = {
 	.probe = rb532_led_probe,
-	.remove = __devexit_p(rb532_led_remove),
+	.remove = rb532_led_remove,
 	.driver = {
 		.name = "rb532-led",
 		.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c
index 25d382d..4253a9b 100644
--- a/drivers/leds/leds-regulator.c
+++ b/drivers/leds/leds-regulator.c
@@ -140,7 +140,7 @@ static void regulator_led_brightness_set(struct led_classdev *led_cdev,
 	schedule_work(&led->work);
 }
 
-static int __devinit regulator_led_probe(struct platform_device *pdev)
+static int regulator_led_probe(struct platform_device *pdev)
 {
 	struct led_regulator_platform_data *pdata = pdev->dev.platform_data;
 	struct regulator_led *led;
@@ -206,7 +206,7 @@ err_vcc:
 	return ret;
 }
 
-static int __devexit regulator_led_remove(struct platform_device *pdev)
+static int regulator_led_remove(struct platform_device *pdev)
 {
 	struct regulator_led *led = platform_get_drvdata(pdev);
 
@@ -223,7 +223,7 @@ static struct platform_driver regulator_led_driver = {
 		   .owner = THIS_MODULE,
 		   },
 	.probe  = regulator_led_probe,
-	.remove = __devexit_p(regulator_led_remove),
+	.remove = regulator_led_remove,
 };
 
 module_platform_driver(regulator_led_driver);
diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c
index 771ea06..e0fff1c 100644
--- a/drivers/leds/leds-renesas-tpu.c
+++ b/drivers/leds/leds-renesas-tpu.c
@@ -204,10 +204,10 @@ static void r_tpu_set_pin(struct r_tpu_priv *p, enum r_tpu_pin new_state,
 	if (p->pin_state == R_TPU_PIN_GPIO_FN)
 		gpio_free(cfg->pin_gpio_fn);
 
-	if (new_state == R_TPU_PIN_GPIO) {
-		gpio_request(cfg->pin_gpio, cfg->name);
-		gpio_direction_output(cfg->pin_gpio, !!brightness);
-	}
+	if (new_state == R_TPU_PIN_GPIO)
+		gpio_request_one(cfg->pin_gpio, GPIOF_DIR_OUT | !!brightness,
+				cfg->name);
+
 	if (new_state == R_TPU_PIN_GPIO_FN)
 		gpio_request(cfg->pin_gpio_fn, cfg->name);
 
@@ -238,7 +238,7 @@ static void r_tpu_set_brightness(struct led_classdev *ldev,
 	schedule_work(&p->work);
 }
 
-static int __devinit r_tpu_probe(struct platform_device *pdev)
+static int r_tpu_probe(struct platform_device *pdev)
 {
 	struct led_renesas_tpu_config *cfg = pdev->dev.platform_data;
 	struct r_tpu_priv *p;
@@ -263,18 +263,18 @@ static int __devinit r_tpu_probe(struct platform_device *pdev)
 	}
 
 	/* map memory, let mapbase point to our channel */
-	p->mapbase = ioremap_nocache(res->start, resource_size(res));
+	p->mapbase = devm_ioremap_nocache(&pdev->dev, res->start,
+					resource_size(res));
 	if (p->mapbase == NULL) {
 		dev_err(&pdev->dev, "failed to remap I/O memory\n");
 		return -ENXIO;
 	}
 
 	/* get hold of clock */
-	p->clk = clk_get(&pdev->dev, NULL);
+	p->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(p->clk)) {
 		dev_err(&pdev->dev, "cannot get clock\n");
-		ret = PTR_ERR(p->clk);
-		goto err0;
+		return PTR_ERR(p->clk);
 	}
 
 	p->pdev = pdev;
@@ -293,7 +293,7 @@ static int __devinit r_tpu_probe(struct platform_device *pdev)
 	p->ldev.flags |= LED_CORE_SUSPENDRESUME;
 	ret = led_classdev_register(&pdev->dev, &p->ldev);
 	if (ret < 0)
-		goto err1;
+		goto err0;
 
 	/* max_brightness may be updated by the LED core code */
 	p->min_rate = p->ldev.max_brightness * p->refresh_rate;
@@ -301,15 +301,12 @@ static int __devinit r_tpu_probe(struct platform_device *pdev)
 	pm_runtime_enable(&pdev->dev);
 	return 0;
 
- err1:
-	r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF);
-	clk_put(p->clk);
  err0:
-	iounmap(p->mapbase);
+	r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF);
 	return ret;
 }
 
-static int __devexit r_tpu_remove(struct platform_device *pdev)
+static int r_tpu_remove(struct platform_device *pdev)
 {
 	struct r_tpu_priv *p = platform_get_drvdata(pdev);
 
@@ -320,15 +317,13 @@ static int __devexit r_tpu_remove(struct platform_device *pdev)
 	r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF);
 
 	pm_runtime_disable(&pdev->dev);
-	clk_put(p->clk);
 
-	iounmap(p->mapbase);
 	return 0;
 }
 
 static struct platform_driver r_tpu_device_driver = {
 	.probe		= r_tpu_probe,
-	.remove		= __devexit_p(r_tpu_remove),
+	.remove		= r_tpu_remove,
 	.driver		= {
 		.name	= "leds-renesas-tpu",
 	}
diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c
index 57371e1..ec9b287 100644
--- a/drivers/leds/leds-ss4200.c
+++ b/drivers/leds/leds-ss4200.c
@@ -263,7 +263,7 @@ static int nasgpio_led_set_blink(struct led_classdev *led_cdev,
  * already taken care of this, but we will do so in a non destructive manner
  * so that we have what we need whether the BIOS did it or not.
  */
-static int __devinit ich7_gpio_init(struct device *dev)
+static int ich7_gpio_init(struct device *dev)
 {
 	int i;
 	u32 config_data = 0;
@@ -342,7 +342,7 @@ static void ich7_lpc_cleanup(struct device *dev)
  * so we can retrive the required operational information and prepare the GPIO.
  */
 static struct pci_dev *nas_gpio_pci_dev;
-static int __devinit ich7_lpc_probe(struct pci_dev *dev,
+static int ich7_lpc_probe(struct pci_dev *dev,
 				    const struct pci_device_id *id)
 {
 	int status;
@@ -459,7 +459,7 @@ static ssize_t nas_led_blink_store(struct device *dev,
 	struct led_classdev *led = dev_get_drvdata(dev);
 	unsigned long blink_state;
 
-	ret = strict_strtoul(buf, 10, &blink_state);
+	ret = kstrtoul(buf, 10, &blink_state);
 	if (ret)
 		return ret;
 
diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c
index 134d9a4..07ff5a3 100644
--- a/drivers/leds/leds-sunfire.c
+++ b/drivers/leds/leds-sunfire.c
@@ -123,7 +123,7 @@ struct sunfire_drvdata {
 	struct sunfire_led	leds[NUM_LEDS_PER_BOARD];
 };
 
-static int __devinit sunfire_led_generic_probe(struct platform_device *pdev,
+static int sunfire_led_generic_probe(struct platform_device *pdev,
 					       struct led_type *types)
 {
 	struct sunfire_drvdata *p;
@@ -165,7 +165,7 @@ static int __devinit sunfire_led_generic_probe(struct platform_device *pdev,
 	return 0;
 }
 
-static int __devexit sunfire_led_generic_remove(struct platform_device *pdev)
+static int sunfire_led_generic_remove(struct platform_device *pdev)
 {
 	struct sunfire_drvdata *p = dev_get_drvdata(&pdev->dev);
 	int i;
@@ -192,7 +192,7 @@ static struct led_type clockboard_led_types[NUM_LEDS_PER_BOARD] = {
 	},
 };
 
-static int __devinit sunfire_clockboard_led_probe(struct platform_device *pdev)
+static int sunfire_clockboard_led_probe(struct platform_device *pdev)
 {
 	return sunfire_led_generic_probe(pdev, clockboard_led_types);
 }
@@ -213,7 +213,7 @@ static struct led_type fhc_led_types[NUM_LEDS_PER_BOARD] = {
 	},
 };
 
-static int __devinit sunfire_fhc_led_probe(struct platform_device *pdev)
+static int sunfire_fhc_led_probe(struct platform_device *pdev)
 {
 	return sunfire_led_generic_probe(pdev, fhc_led_types);
 }
@@ -223,7 +223,7 @@ MODULE_ALIAS("platform:sunfire-fhc-leds");
 
 static struct platform_driver sunfire_clockboard_led_driver = {
 	.probe		= sunfire_clockboard_led_probe,
-	.remove		= __devexit_p(sunfire_led_generic_remove),
+	.remove		= sunfire_led_generic_remove,
 	.driver		= {
 		.name	= "sunfire-clockboard-leds",
 		.owner	= THIS_MODULE,
@@ -232,7 +232,7 @@ static struct platform_driver sunfire_clockboard_led_driver = {
 
 static struct platform_driver sunfire_fhc_led_driver = {
 	.probe		= sunfire_fhc_led_probe,
-	.remove		= __devexit_p(sunfire_led_generic_remove),
+	.remove		= sunfire_led_generic_remove,
 	.driver		= {
 		.name	= "sunfire-fhc-leds",
 		.owner	= THIS_MODULE,
diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c
index dabcf7a..b26a63b 100644
--- a/drivers/leds/leds-tca6507.c
+++ b/drivers/leds/leds-tca6507.c
@@ -667,7 +667,7 @@ static void tca6507_remove_gpio(struct tca6507_chip *tca)
 }
 #endif /* CONFIG_GPIOLIB */
 
-static int __devinit tca6507_probe(struct i2c_client *client,
+static int tca6507_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
 	struct tca6507_chip *tca;
@@ -730,7 +730,7 @@ exit:
 	return err;
 }
 
-static int __devexit tca6507_remove(struct i2c_client *client)
+static int tca6507_remove(struct i2c_client *client)
 {
 	int i;
 	struct tca6507_chip *tca = i2c_get_clientdata(client);
@@ -752,7 +752,7 @@ static struct i2c_driver tca6507_driver = {
 		.owner   = THIS_MODULE,
 	},
 	.probe    = tca6507_probe,
-	.remove   = __devexit_p(tca6507_remove),
+	.remove   = tca6507_remove,
 	.id_table = tca6507_id,
 };
 
diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c
index 88f23f8..ed15157 100644
--- a/drivers/leds/leds-wm8350.c
+++ b/drivers/leds/leds-wm8350.c
@@ -216,13 +216,13 @@ static int wm8350_led_probe(struct platform_device *pdev)
 
 	isink = devm_regulator_get(&pdev->dev, "led_isink");
 	if (IS_ERR(isink)) {
-		printk(KERN_ERR "%s: can't get ISINK\n", __func__);
+		dev_err(&pdev->dev, "%s: can't get ISINK\n", __func__);
 		return PTR_ERR(isink);
 	}
 
 	dcdc = devm_regulator_get(&pdev->dev, "led_vcc");
 	if (IS_ERR(dcdc)) {
-		printk(KERN_ERR "%s: can't get DCDC\n", __func__);
+		dev_err(&pdev->dev, "%s: can't get DCDC\n", __func__);
 		return PTR_ERR(dcdc);
 	}
 
diff --git a/drivers/leds/leds-wrap.c b/drivers/leds/leds-wrap.c
index 6e21e65..b358cc0 100644
--- a/drivers/leds/leds-wrap.c
+++ b/drivers/leds/leds-wrap.c
@@ -15,7 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/err.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/scx200_gpio.h>
 #include <linux/module.h>
 
diff --git a/drivers/leds/ledtrig-backlight.c b/drivers/leds/ledtrig-backlight.c
index b941685..027a2b1 100644
--- a/drivers/leds/ledtrig-backlight.c
+++ b/drivers/leds/ledtrig-backlight.c
@@ -40,7 +40,7 @@ static int fb_notifier_callback(struct notifier_block *p,
 	int new_status = *blank ? BLANK : UNBLANK;
 
 	switch (event) {
-	case FB_EVENT_BLANK :
+	case FB_EVENT_BLANK:
 		if (new_status == n->old_status)
 			break;
 
@@ -76,7 +76,7 @@ static ssize_t bl_trig_invert_store(struct device *dev,
 	unsigned long invert;
 	int ret;
 
-	ret = strict_strtoul(buf, 10, &invert);
+	ret = kstrtoul(buf, 10, &invert);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/leds/ledtrig-gpio.c b/drivers/leds/ledtrig-gpio.c
index ba215dc..72e3ebf 100644
--- a/drivers/leds/ledtrig-gpio.c
+++ b/drivers/leds/ledtrig-gpio.c
@@ -110,7 +110,7 @@ static ssize_t gpio_trig_inverted_store(struct device *dev,
 	unsigned long inverted;
 	int ret;
 
-	ret = strict_strtoul(buf, 10, &inverted);
+	ret = kstrtoul(buf, 10, &inverted);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/lguest/Kconfig b/drivers/lguest/Kconfig
index 34ae49d..6cdcdb0 100644
--- a/drivers/lguest/Kconfig
+++ b/drivers/lguest/Kconfig
@@ -1,6 +1,6 @@
 config LGUEST
 	tristate "Linux hypervisor example code"
-	depends on X86_32 && EXPERIMENTAL && EVENTFD
+	depends on X86_32 && EVENTFD
 	select HVC_DRIVER
 	---help---
 	  This is a very simple module which allows you to run
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index b5fdcb7..a5ebc00 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -225,7 +225,7 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
 			 * eventfd (ie. the appropriate virtqueue thread)?
 			 */
 			if (!send_notify_to_eventfd(cpu)) {
-				/* OK, we tell the main Laucher. */
+				/* OK, we tell the main Launcher. */
 				if (put_user(cpu->pending_notify, user))
 					return -EFAULT;
 				return sizeof(cpu->pending_notify);
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index 7d5a6b4..9c6b964 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -565,7 +565,7 @@ fail_msg_node:
 fail_db_node:
 	of_node_put(smu->db_node);
 fail_bootmem:
-	free_bootmem((unsigned long)smu, sizeof(struct smu_device));
+	free_bootmem(__pa(smu), sizeof(struct smu_device));
 	smu = NULL;
 fail_np:
 	of_node_put(np);
@@ -997,7 +997,7 @@ static struct smu_sdbp_header *smu_create_sdb_partition(int id)
 		       "%02x !\n", id, hdr->id);
 		goto failure;
 	}
-	if (prom_add_property(smu->of_node, prop)) {
+	if (of_add_property(smu->of_node, prop)) {
 		printk(KERN_DEBUG "SMU: Failed creating sdb-partition-%02x "
 		       "property !\n", id);
 		goto failure;
diff --git a/drivers/macintosh/windfarm_fcu_controls.c b/drivers/macintosh/windfarm_fcu_controls.c
index b3411ed..fd6ed15 100644
--- a/drivers/macintosh/windfarm_fcu_controls.c
+++ b/drivers/macintosh/windfarm_fcu_controls.c
@@ -593,19 +593,7 @@ static struct i2c_driver wf_fcu_driver = {
 	.id_table	= wf_fcu_id,
 };
 
-static int __init wf_fcu_init(void)
-{
-	return i2c_add_driver(&wf_fcu_driver);
-}
-
-static void __exit wf_fcu_exit(void)
-{
-	i2c_del_driver(&wf_fcu_driver);
-}
-
-
-module_init(wf_fcu_init);
-module_exit(wf_fcu_exit);
+module_i2c_driver(wf_fcu_driver);
 
 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
 MODULE_DESCRIPTION("FCU control objects for PowerMacs thermal control");
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
index b0c2d36..9ef32b3 100644
--- a/drivers/macintosh/windfarm_lm75_sensor.c
+++ b/drivers/macintosh/windfarm_lm75_sensor.c
@@ -174,19 +174,7 @@ static struct i2c_driver wf_lm75_driver = {
 	.id_table	= wf_lm75_id,
 };
 
-static int __init wf_lm75_sensor_init(void)
-{
-	return i2c_add_driver(&wf_lm75_driver);
-}
-
-static void __exit wf_lm75_sensor_exit(void)
-{
-	i2c_del_driver(&wf_lm75_driver);
-}
-
-
-module_init(wf_lm75_sensor_init);
-module_exit(wf_lm75_sensor_exit);
+module_i2c_driver(wf_lm75_driver);
 
 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
 MODULE_DESCRIPTION("LM75 sensor objects for PowerMacs thermal control");
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c
index 371b058..945a25b 100644
--- a/drivers/macintosh/windfarm_max6690_sensor.c
+++ b/drivers/macintosh/windfarm_max6690_sensor.c
@@ -130,18 +130,7 @@ static struct i2c_driver wf_max6690_driver = {
 	.id_table	= wf_max6690_id,
 };
 
-static int __init wf_max6690_sensor_init(void)
-{
-	return i2c_add_driver(&wf_max6690_driver);
-}
-
-static void __exit wf_max6690_sensor_exit(void)
-{
-	i2c_del_driver(&wf_max6690_driver);
-}
-
-module_init(wf_max6690_sensor_init);
-module_exit(wf_max6690_sensor_exit);
+module_i2c_driver(wf_max6690_driver);
 
 MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
 MODULE_DESCRIPTION("MAX6690 sensor objects for PowerMac thermal control");
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
index 426e810..d87f5ee 100644
--- a/drivers/macintosh/windfarm_smu_sat.c
+++ b/drivers/macintosh/windfarm_smu_sat.c
@@ -364,18 +364,7 @@ static struct i2c_driver wf_sat_driver = {
 	.id_table	= wf_sat_id,
 };
 
-static int __init sat_sensors_init(void)
-{
-	return i2c_add_driver(&wf_sat_driver);
-}
-
-static void __exit sat_sensors_exit(void)
-{
-	i2c_del_driver(&wf_sat_driver);
-}
-
-module_init(sat_sensors_init);
-module_exit(sat_sensors_exit);
+module_i2c_driver(wf_sat_driver);
 
 MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
 MODULE_DESCRIPTION("SMU satellite sensors for PowerMac thermal control");
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index fd61f98..cec5f9b 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -1195,11 +1195,9 @@ static int mirror_map(struct dm_target *ti, struct bio *bio,
 		return -EIO;
 
 	read_record = mempool_alloc(ms->read_record_pool, GFP_NOIO);
-	if (likely(read_record)) {
-		dm_bio_record(&read_record->details, bio);
-		map_context->ptr = read_record;
-		read_record->m = m;
-	}
+	dm_bio_record(&read_record->details, bio);
+	map_context->ptr = read_record;
+	read_record->m = m;
 
 	map_bio(m, bio);
 
@@ -1259,7 +1257,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio,
 			mempool_free(read_record, ms->read_record_pool);
 			map_context->ptr = NULL;
 			queue_bio(ms, bio, rw);
-			return 1;
+			return DM_ENDIO_INCOMPLETE;
 		}
 		DMERR("All replicated volumes dead, failing I/O");
 	}
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index a143921..223e7eb 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -198,14 +198,13 @@ static struct dm_snap_tracked_chunk *track_chunk(struct dm_snapshot *s,
 {
 	struct dm_snap_tracked_chunk *c = mempool_alloc(s->tracked_chunk_pool,
 							GFP_NOIO);
-	unsigned long flags;
 
 	c->chunk = chunk;
 
-	spin_lock_irqsave(&s->tracked_chunk_lock, flags);
+	spin_lock_irq(&s->tracked_chunk_lock);
 	hlist_add_head(&c->node,
 		       &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)]);
-	spin_unlock_irqrestore(&s->tracked_chunk_lock, flags);
+	spin_unlock_irq(&s->tracked_chunk_lock);
 
 	return c;
 }
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 6120071..2e39cae 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -452,7 +452,7 @@ void md_flush_request(struct mddev *mddev, struct bio *bio)
 	spin_lock_irq(&mddev->write_lock);
 	wait_event_lock_irq(mddev->sb_wait,
 			    !mddev->flush_bio,
-			    mddev->write_lock, /*nothing*/);
+			    mddev->write_lock);
 	mddev->flush_bio = bio;
 	spin_unlock_irq(&mddev->write_lock);
 
@@ -603,9 +603,9 @@ static struct mddev * mddev_find(dev_t unit)
 	goto retry;
 }
 
-static inline int mddev_lock(struct mddev * mddev)
+int md_queue_misc_work(struct work_struct *work)
 {
-	return mutex_lock_interruptible(&mddev->reconfig_mutex);
+	return queue_work(md_misc_wq, work);
 }
 
 static inline int mddev_is_locked(struct mddev *mddev)
@@ -620,7 +620,7 @@ static inline int mddev_trylock(struct mddev * mddev)
 
 static struct attribute_group md_redundancy_group;
 
-static void mddev_unlock(struct mddev * mddev)
+void mddev_unlock(struct mddev * mddev)
 {
 	if (mddev->to_remove) {
 		/* These cannot be removed under reconfig_mutex as
@@ -4124,7 +4124,7 @@ static struct md_sysfs_entry md_size =
 __ATTR(component_size, S_IRUGO|S_IWUSR, size_show, size_store);
 
 
-/* Metdata version.
+/* Metadata version.
  * This is one of
  *   'none' for arrays with no metadata (good luck...)
  *   'external' for arrays with externally managed metadata,
@@ -7184,6 +7184,7 @@ void md_done_sync(struct mddev *mddev, int blocks, int ok)
 	wake_up(&mddev->recovery_wait);
 	if (!ok) {
 		set_bit(MD_RECOVERY_INTR, &mddev->recovery);
+		set_bit(MD_RECOVERY_ERROR, &mddev->recovery);
 		md_wakeup_thread(mddev->thread);
 		// stop recovery, signal do_sync ....
 	}
@@ -7281,6 +7282,7 @@ EXPORT_SYMBOL_GPL(md_allow_write);
 
 #define SYNC_MARKS	10
 #define	SYNC_MARK_STEP	(3*HZ)
+#define UPDATE_FREQUENCY (5*60*HZ)
 void md_do_sync(struct md_thread *thread)
 {
 	struct mddev *mddev = thread->mddev;
@@ -7289,6 +7291,7 @@ void md_do_sync(struct md_thread *thread)
 		 window;
 	sector_t max_sectors,j, io_sectors;
 	unsigned long mark[SYNC_MARKS];
+	unsigned long update_time;
 	sector_t mark_cnt[SYNC_MARKS];
 	int last_mark,m;
 	struct list_head *tmp;
@@ -7448,6 +7451,7 @@ void md_do_sync(struct md_thread *thread)
 	mddev->curr_resync_completed = j;
 	sysfs_notify(&mddev->kobj, NULL, "sync_completed");
 	md_new_event(mddev);
+	update_time = jiffies;
 
 	blk_start_plug(&plug);
 	while (j < max_sectors) {
@@ -7459,6 +7463,7 @@ void md_do_sync(struct md_thread *thread)
 		    ((mddev->curr_resync > mddev->curr_resync_completed &&
 		      (mddev->curr_resync - mddev->curr_resync_completed)
 		      > (max_sectors >> 4)) ||
+		     time_after_eq(jiffies, update_time + UPDATE_FREQUENCY) ||
 		     (j - mddev->curr_resync_completed)*2
 		     >= mddev->resync_max - mddev->curr_resync_completed
 			    )) {
@@ -7466,6 +7471,10 @@ void md_do_sync(struct md_thread *thread)
 			wait_event(mddev->recovery_wait,
 				   atomic_read(&mddev->recovery_active) == 0);
 			mddev->curr_resync_completed = j;
+			if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) &&
+			    j > mddev->recovery_cp)
+				mddev->recovery_cp = j;
+			update_time = jiffies;
 			set_bit(MD_CHANGE_CLEAN, &mddev->flags);
 			sysfs_notify(&mddev->kobj, NULL, "sync_completed");
 		}
@@ -7570,8 +7579,13 @@ void md_do_sync(struct md_thread *thread)
 					printk(KERN_INFO
 					       "md: checkpointing %s of %s.\n",
 					       desc, mdname(mddev));
-					mddev->recovery_cp =
-						mddev->curr_resync_completed;
+					if (test_bit(MD_RECOVERY_ERROR,
+						&mddev->recovery))
+						mddev->recovery_cp =
+							mddev->curr_resync_completed;
+					else
+						mddev->recovery_cp =
+							mddev->curr_resync;
 				}
 			} else
 				mddev->recovery_cp = MaxSector;
@@ -8617,6 +8631,8 @@ EXPORT_SYMBOL(md_register_thread);
 EXPORT_SYMBOL(md_unregister_thread);
 EXPORT_SYMBOL(md_wakeup_thread);
 EXPORT_SYMBOL(md_check_recovery);
+EXPORT_SYMBOL(mddev_unlock);
+EXPORT_SYMBOL(md_queue_misc_work);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("MD RAID framework");
 MODULE_ALIAS("md");
diff --git a/drivers/md/md.h b/drivers/md/md.h
index af443ab..2afa1c3 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -307,6 +307,7 @@ struct mddev {
 	 * REQUEST:  user-space has requested a sync (used with SYNC)
 	 * CHECK:    user-space request for check-only, no repair
 	 * RESHAPE:  A reshape is happening
+	 * ERROR:    sync-action interrupted because io-error
 	 *
 	 * If neither SYNC or RESHAPE are set, then it is a recovery.
 	 */
@@ -320,6 +321,7 @@ struct mddev {
 #define	MD_RECOVERY_CHECK	7
 #define MD_RECOVERY_RESHAPE	8
 #define	MD_RECOVERY_FROZEN	9
+#define	MD_RECOVERY_ERROR	10
 
 	unsigned long			recovery;
 	/* If a RAID personality determines that recovery (of a particular
@@ -551,32 +553,6 @@ struct md_thread {
 
 #define THREAD_WAKEUP  0
 
-#define __wait_event_lock_irq(wq, condition, lock, cmd) 		\
-do {									\
-	wait_queue_t __wait;						\
-	init_waitqueue_entry(&__wait, current);				\
-									\
-	add_wait_queue(&wq, &__wait);					\
-	for (;;) {							\
-		set_current_state(TASK_UNINTERRUPTIBLE);		\
-		if (condition)						\
-			break;						\
-		spin_unlock_irq(&lock);					\
-		cmd;							\
-		schedule();						\
-		spin_lock_irq(&lock);					\
-	}								\
-	current->state = TASK_RUNNING;					\
-	remove_wait_queue(&wq, &__wait);				\
-} while (0)
-
-#define wait_event_lock_irq(wq, condition, lock, cmd) 			\
-do {									\
-	if (condition)	 						\
-		break;							\
-	__wait_event_lock_irq(wq, condition, lock, cmd);		\
-} while (0)
-
 static inline void safe_put_page(struct page *p)
 {
 	if (p) put_page(p);
@@ -636,4 +612,12 @@ static inline int mddev_check_plugged(struct mddev *mddev)
 	return !!blk_check_plugged(md_unplug, mddev,
 				   sizeof(struct blk_plug_cb));
 }
+
+static inline int mddev_lock(struct mddev * mddev)
+{
+	return mutex_lock_interruptible(&mddev->reconfig_mutex);
+}
+extern void mddev_unlock(struct mddev *mddev);
+extern int md_queue_misc_work(struct work_struct *work);
+
 #endif /* _MD_MD_H */
diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c
index 5ba2777..a3ae091 100644
--- a/drivers/md/persistent-data/dm-block-manager.c
+++ b/drivers/md/persistent-data/dm-block-manager.c
@@ -25,7 +25,7 @@
  * may be held at once.  This is just an implementation detail.
  *
  * ii) Recursive locking attempts are detected and return EINVAL.  A stack
- * trace is also emitted for the previous lock aquisition.
+ * trace is also emitted for the previous lock acquisition.
  *
  * iii) Priority is given to write locks.
  */
@@ -109,7 +109,7 @@ static int __check_holder(struct block_lock *lock)
 			DMERR("previously held here:");
 			print_stack_trace(lock->traces + i, 4);
 
-			DMERR("subsequent aquisition attempted here:");
+			DMERR("subsequent acquisition attempted here:");
 			t.nr_entries = 0;
 			t.max_entries = MAX_STACK;
 			t.entries = entries;
diff --git a/drivers/md/persistent-data/dm-btree-internal.h b/drivers/md/persistent-data/dm-btree-internal.h
index 5709bfe..accbb05 100644
--- a/drivers/md/persistent-data/dm-btree-internal.h
+++ b/drivers/md/persistent-data/dm-btree-internal.h
@@ -36,13 +36,13 @@ struct node_header {
 	__le32 padding;
 } __packed;
 
-struct node {
+struct btree_node {
 	struct node_header header;
 	__le64 keys[0];
 } __packed;
 
 
-void inc_children(struct dm_transaction_manager *tm, struct node *n,
+void inc_children(struct dm_transaction_manager *tm, struct btree_node *n,
 		  struct dm_btree_value_type *vt);
 
 int new_block(struct dm_btree_info *info, struct dm_block **result);
@@ -64,7 +64,7 @@ struct ro_spine {
 void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info);
 int exit_ro_spine(struct ro_spine *s);
 int ro_step(struct ro_spine *s, dm_block_t new_child);
-struct node *ro_node(struct ro_spine *s);
+struct btree_node *ro_node(struct ro_spine *s);
 
 struct shadow_spine {
 	struct dm_btree_info *info;
@@ -98,17 +98,17 @@ int shadow_root(struct shadow_spine *s);
 /*
  * Some inlines.
  */
-static inline __le64 *key_ptr(struct node *n, uint32_t index)
+static inline __le64 *key_ptr(struct btree_node *n, uint32_t index)
 {
 	return n->keys + index;
 }
 
-static inline void *value_base(struct node *n)
+static inline void *value_base(struct btree_node *n)
 {
 	return &n->keys[le32_to_cpu(n->header.max_entries)];
 }
 
-static inline void *value_ptr(struct node *n, uint32_t index)
+static inline void *value_ptr(struct btree_node *n, uint32_t index)
 {
 	uint32_t value_size = le32_to_cpu(n->header.value_size);
 	return value_base(n) + (value_size * index);
@@ -117,7 +117,7 @@ static inline void *value_ptr(struct node *n, uint32_t index)
 /*
  * Assumes the values are suitably-aligned and converts to core format.
  */
-static inline uint64_t value64(struct node *n, uint32_t index)
+static inline uint64_t value64(struct btree_node *n, uint32_t index)
 {
 	__le64 *values_le = value_base(n);
 
@@ -127,7 +127,7 @@ static inline uint64_t value64(struct node *n, uint32_t index)
 /*
  * Searching for a key within a single node.
  */
-int lower_bound(struct node *n, uint64_t key);
+int lower_bound(struct btree_node *n, uint64_t key);
 
 extern struct dm_block_validator btree_node_validator;
 
diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c
index aa71e23..c4f2813 100644
--- a/drivers/md/persistent-data/dm-btree-remove.c
+++ b/drivers/md/persistent-data/dm-btree-remove.c
@@ -53,7 +53,7 @@
 /*
  * Some little utilities for moving node data around.
  */
-static void node_shift(struct node *n, int shift)
+static void node_shift(struct btree_node *n, int shift)
 {
 	uint32_t nr_entries = le32_to_cpu(n->header.nr_entries);
 	uint32_t value_size = le32_to_cpu(n->header.value_size);
@@ -79,7 +79,7 @@ static void node_shift(struct node *n, int shift)
 	}
 }
 
-static void node_copy(struct node *left, struct node *right, int shift)
+static void node_copy(struct btree_node *left, struct btree_node *right, int shift)
 {
 	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
 	uint32_t value_size = le32_to_cpu(left->header.value_size);
@@ -108,7 +108,7 @@ static void node_copy(struct node *left, struct node *right, int shift)
 /*
  * Delete a specific entry from a leaf node.
  */
-static void delete_at(struct node *n, unsigned index)
+static void delete_at(struct btree_node *n, unsigned index)
 {
 	unsigned nr_entries = le32_to_cpu(n->header.nr_entries);
 	unsigned nr_to_copy = nr_entries - (index + 1);
@@ -128,7 +128,7 @@ static void delete_at(struct node *n, unsigned index)
 	n->header.nr_entries = cpu_to_le32(nr_entries - 1);
 }
 
-static unsigned merge_threshold(struct node *n)
+static unsigned merge_threshold(struct btree_node *n)
 {
 	return le32_to_cpu(n->header.max_entries) / 3;
 }
@@ -136,7 +136,7 @@ static unsigned merge_threshold(struct node *n)
 struct child {
 	unsigned index;
 	struct dm_block *block;
-	struct node *n;
+	struct btree_node *n;
 };
 
 static struct dm_btree_value_type le64_type = {
@@ -147,7 +147,7 @@ static struct dm_btree_value_type le64_type = {
 	.equal = NULL
 };
 
-static int init_child(struct dm_btree_info *info, struct node *parent,
+static int init_child(struct dm_btree_info *info, struct btree_node *parent,
 		      unsigned index, struct child *result)
 {
 	int r, inc;
@@ -177,7 +177,7 @@ static int exit_child(struct dm_btree_info *info, struct child *c)
 	return dm_tm_unlock(info->tm, c->block);
 }
 
-static void shift(struct node *left, struct node *right, int count)
+static void shift(struct btree_node *left, struct btree_node *right, int count)
 {
 	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
 	uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
@@ -203,11 +203,11 @@ static void shift(struct node *left, struct node *right, int count)
 	right->header.nr_entries = cpu_to_le32(nr_right + count);
 }
 
-static void __rebalance2(struct dm_btree_info *info, struct node *parent,
+static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent,
 			 struct child *l, struct child *r)
 {
-	struct node *left = l->n;
-	struct node *right = r->n;
+	struct btree_node *left = l->n;
+	struct btree_node *right = r->n;
 	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
 	uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
 	unsigned threshold = 2 * merge_threshold(left) + 1;
@@ -239,7 +239,7 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
 		      unsigned left_index)
 {
 	int r;
-	struct node *parent;
+	struct btree_node *parent;
 	struct child left, right;
 
 	parent = dm_block_data(shadow_current(s));
@@ -270,9 +270,9 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
  * in right, then rebalance2.  This wastes some cpu, but I want something
  * simple atm.
  */
-static void delete_center_node(struct dm_btree_info *info, struct node *parent,
+static void delete_center_node(struct dm_btree_info *info, struct btree_node *parent,
 			       struct child *l, struct child *c, struct child *r,
-			       struct node *left, struct node *center, struct node *right,
+			       struct btree_node *left, struct btree_node *center, struct btree_node *right,
 			       uint32_t nr_left, uint32_t nr_center, uint32_t nr_right)
 {
 	uint32_t max_entries = le32_to_cpu(left->header.max_entries);
@@ -301,9 +301,9 @@ static void delete_center_node(struct dm_btree_info *info, struct node *parent,
 /*
  * Redistributes entries among 3 sibling nodes.
  */
-static void redistribute3(struct dm_btree_info *info, struct node *parent,
+static void redistribute3(struct dm_btree_info *info, struct btree_node *parent,
 			  struct child *l, struct child *c, struct child *r,
-			  struct node *left, struct node *center, struct node *right,
+			  struct btree_node *left, struct btree_node *center, struct btree_node *right,
 			  uint32_t nr_left, uint32_t nr_center, uint32_t nr_right)
 {
 	int s;
@@ -343,12 +343,12 @@ static void redistribute3(struct dm_btree_info *info, struct node *parent,
 	*key_ptr(parent, r->index) = right->keys[0];
 }
 
-static void __rebalance3(struct dm_btree_info *info, struct node *parent,
+static void __rebalance3(struct dm_btree_info *info, struct btree_node *parent,
 			 struct child *l, struct child *c, struct child *r)
 {
-	struct node *left = l->n;
-	struct node *center = c->n;
-	struct node *right = r->n;
+	struct btree_node *left = l->n;
+	struct btree_node *center = c->n;
+	struct btree_node *right = r->n;
 
 	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
 	uint32_t nr_center = le32_to_cpu(center->header.nr_entries);
@@ -371,7 +371,7 @@ static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
 		      unsigned left_index)
 {
 	int r;
-	struct node *parent = dm_block_data(shadow_current(s));
+	struct btree_node *parent = dm_block_data(shadow_current(s));
 	struct child left, center, right;
 
 	/*
@@ -421,7 +421,7 @@ static int get_nr_entries(struct dm_transaction_manager *tm,
 {
 	int r;
 	struct dm_block *block;
-	struct node *n;
+	struct btree_node *n;
 
 	r = dm_tm_read_lock(tm, b, &btree_node_validator, &block);
 	if (r)
@@ -438,7 +438,7 @@ static int rebalance_children(struct shadow_spine *s,
 {
 	int i, r, has_left_sibling, has_right_sibling;
 	uint32_t child_entries;
-	struct node *n;
+	struct btree_node *n;
 
 	n = dm_block_data(shadow_current(s));
 
@@ -483,7 +483,7 @@ static int rebalance_children(struct shadow_spine *s,
 	return r;
 }
 
-static int do_leaf(struct node *n, uint64_t key, unsigned *index)
+static int do_leaf(struct btree_node *n, uint64_t key, unsigned *index)
 {
 	int i = lower_bound(n, key);
 
@@ -506,7 +506,7 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
 		      uint64_t key, unsigned *index)
 {
 	int i = *index, r;
-	struct node *n;
+	struct btree_node *n;
 
 	for (;;) {
 		r = shadow_step(s, root, vt);
@@ -556,7 +556,7 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
 	unsigned level, last_level = info->levels - 1;
 	int index = 0, r = 0;
 	struct shadow_spine spine;
-	struct node *n;
+	struct btree_node *n;
 
 	init_shadow_spine(&spine, info);
 	for (level = 0; level < info->levels; level++) {
diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persistent-data/dm-btree-spine.c
index d9a7912..2f0805c 100644
--- a/drivers/md/persistent-data/dm-btree-spine.c
+++ b/drivers/md/persistent-data/dm-btree-spine.c
@@ -23,7 +23,7 @@ static void node_prepare_for_write(struct dm_block_validator *v,
 				   struct dm_block *b,
 				   size_t block_size)
 {
-	struct node *n = dm_block_data(b);
+	struct btree_node *n = dm_block_data(b);
 	struct node_header *h = &n->header;
 
 	h->blocknr = cpu_to_le64(dm_block_location(b));
@@ -38,7 +38,7 @@ static int node_check(struct dm_block_validator *v,
 		      struct dm_block *b,
 		      size_t block_size)
 {
-	struct node *n = dm_block_data(b);
+	struct btree_node *n = dm_block_data(b);
 	struct node_header *h = &n->header;
 	size_t value_size;
 	__le32 csum_disk;
@@ -164,7 +164,7 @@ int ro_step(struct ro_spine *s, dm_block_t new_child)
 	return r;
 }
 
-struct node *ro_node(struct ro_spine *s)
+struct btree_node *ro_node(struct ro_spine *s)
 {
 	struct dm_block *block;
 
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c
index d12b2cc..371f3d4 100644
--- a/drivers/md/persistent-data/dm-btree.c
+++ b/drivers/md/persistent-data/dm-btree.c
@@ -38,7 +38,7 @@ static void array_insert(void *base, size_t elt_size, unsigned nr_elts,
 /*----------------------------------------------------------------*/
 
 /* makes the assumption that no two keys are the same. */
-static int bsearch(struct node *n, uint64_t key, int want_hi)
+static int bsearch(struct btree_node *n, uint64_t key, int want_hi)
 {
 	int lo = -1, hi = le32_to_cpu(n->header.nr_entries);
 
@@ -58,12 +58,12 @@ static int bsearch(struct node *n, uint64_t key, int want_hi)
 	return want_hi ? hi : lo;
 }
 
-int lower_bound(struct node *n, uint64_t key)
+int lower_bound(struct btree_node *n, uint64_t key)
 {
 	return bsearch(n, key, 0);
 }
 
-void inc_children(struct dm_transaction_manager *tm, struct node *n,
+void inc_children(struct dm_transaction_manager *tm, struct btree_node *n,
 		  struct dm_btree_value_type *vt)
 {
 	unsigned i;
@@ -77,7 +77,7 @@ void inc_children(struct dm_transaction_manager *tm, struct node *n,
 			vt->inc(vt->context, value_ptr(n, i));
 }
 
-static int insert_at(size_t value_size, struct node *node, unsigned index,
+static int insert_at(size_t value_size, struct btree_node *node, unsigned index,
 		      uint64_t key, void *value)
 		      __dm_written_to_disk(value)
 {
@@ -122,7 +122,7 @@ int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root)
 {
 	int r;
 	struct dm_block *b;
-	struct node *n;
+	struct btree_node *n;
 	size_t block_size;
 	uint32_t max_entries;
 
@@ -154,7 +154,7 @@ EXPORT_SYMBOL_GPL(dm_btree_empty);
 #define MAX_SPINE_DEPTH 64
 struct frame {
 	struct dm_block *b;
-	struct node *n;
+	struct btree_node *n;
 	unsigned level;
 	unsigned nr_children;
 	unsigned current_child;
@@ -295,7 +295,7 @@ EXPORT_SYMBOL_GPL(dm_btree_del);
 /*----------------------------------------------------------------*/
 
 static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key,
-			    int (*search_fn)(struct node *, uint64_t),
+			    int (*search_fn)(struct btree_node *, uint64_t),
 			    uint64_t *result_key, void *v, size_t value_size)
 {
 	int i, r;
@@ -406,7 +406,7 @@ static int btree_split_sibling(struct shadow_spine *s, dm_block_t root,
 	size_t size;
 	unsigned nr_left, nr_right;
 	struct dm_block *left, *right, *parent;
-	struct node *ln, *rn, *pn;
+	struct btree_node *ln, *rn, *pn;
 	__le64 location;
 
 	left = shadow_current(s);
@@ -491,7 +491,7 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
 	size_t size;
 	unsigned nr_left, nr_right;
 	struct dm_block *left, *right, *new_parent;
-	struct node *pn, *ln, *rn;
+	struct btree_node *pn, *ln, *rn;
 	__le64 val;
 
 	new_parent = shadow_current(s);
@@ -576,7 +576,7 @@ static int btree_insert_raw(struct shadow_spine *s, dm_block_t root,
 			    uint64_t key, unsigned *index)
 {
 	int r, i = *index, top = 1;
-	struct node *node;
+	struct btree_node *node;
 
 	for (;;) {
 		r = shadow_step(s, root, vt);
@@ -643,7 +643,7 @@ static int insert(struct dm_btree_info *info, dm_block_t root,
 	unsigned level, index = -1, last_level = info->levels - 1;
 	dm_block_t block = root;
 	struct shadow_spine spine;
-	struct node *n;
+	struct btree_node *n;
 	struct dm_btree_value_type le64_type;
 
 	le64_type.context = NULL;
diff --git a/drivers/md/persistent-data/dm-btree.h b/drivers/md/persistent-data/dm-btree.h
index ae02c84..a2cd5044 100644
--- a/drivers/md/persistent-data/dm-btree.h
+++ b/drivers/md/persistent-data/dm-btree.h
@@ -35,7 +35,7 @@ struct dm_transaction_manager;
  */
 
 /*
- * Infomation about the values stored within the btree.
+ * Information about the values stored within the btree.
  */
 struct dm_btree_value_type {
 	void *context;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 636bae0..d5bddfc 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -822,7 +822,7 @@ static void raise_barrier(struct r1conf *conf)
 
 	/* Wait until no block IO is waiting */
 	wait_event_lock_irq(conf->wait_barrier, !conf->nr_waiting,
-			    conf->resync_lock, );
+			    conf->resync_lock);
 
 	/* block any new IO from starting */
 	conf->barrier++;
@@ -830,7 +830,7 @@ static void raise_barrier(struct r1conf *conf)
 	/* Now wait for all pending IO to complete */
 	wait_event_lock_irq(conf->wait_barrier,
 			    !conf->nr_pending && conf->barrier < RESYNC_DEPTH,
-			    conf->resync_lock, );
+			    conf->resync_lock);
 
 	spin_unlock_irq(&conf->resync_lock);
 }
@@ -864,8 +864,7 @@ static void wait_barrier(struct r1conf *conf)
 				    (conf->nr_pending &&
 				     current->bio_list &&
 				     !bio_list_empty(current->bio_list)),
-				    conf->resync_lock,
-			);
+				    conf->resync_lock);
 		conf->nr_waiting--;
 	}
 	conf->nr_pending++;
@@ -898,10 +897,10 @@ static void freeze_array(struct r1conf *conf)
 	spin_lock_irq(&conf->resync_lock);
 	conf->barrier++;
 	conf->nr_waiting++;
-	wait_event_lock_irq(conf->wait_barrier,
-			    conf->nr_pending == conf->nr_queued+1,
-			    conf->resync_lock,
-			    flush_pending_writes(conf));
+	wait_event_lock_irq_cmd(conf->wait_barrier,
+				conf->nr_pending == conf->nr_queued+1,
+				conf->resync_lock,
+				flush_pending_writes(conf));
 	spin_unlock_irq(&conf->resync_lock);
 }
 static void unfreeze_array(struct r1conf *conf)
@@ -963,7 +962,7 @@ static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule)
 	struct r1conf *conf = mddev->private;
 	struct bio *bio;
 
-	if (from_schedule) {
+	if (from_schedule || current->bio_list) {
 		spin_lock_irq(&conf->device_lock);
 		bio_list_merge(&conf->pending_bio_list, &plug->pending);
 		conf->pending_count += plug->pending_cnt;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 0d5d0ff..64d4824 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -952,7 +952,7 @@ static void raise_barrier(struct r10conf *conf, int force)
 
 	/* Wait until no block IO is waiting (unless 'force') */
 	wait_event_lock_irq(conf->wait_barrier, force || !conf->nr_waiting,
-			    conf->resync_lock, );
+			    conf->resync_lock);
 
 	/* block any new IO from starting */
 	conf->barrier++;
@@ -960,7 +960,7 @@ static void raise_barrier(struct r10conf *conf, int force)
 	/* Now wait for all pending IO to complete */
 	wait_event_lock_irq(conf->wait_barrier,
 			    !conf->nr_pending && conf->barrier < RESYNC_DEPTH,
-			    conf->resync_lock, );
+			    conf->resync_lock);
 
 	spin_unlock_irq(&conf->resync_lock);
 }
@@ -993,8 +993,7 @@ static void wait_barrier(struct r10conf *conf)
 				    (conf->nr_pending &&
 				     current->bio_list &&
 				     !bio_list_empty(current->bio_list)),
-				    conf->resync_lock,
-			);
+				    conf->resync_lock);
 		conf->nr_waiting--;
 	}
 	conf->nr_pending++;
@@ -1027,10 +1026,10 @@ static void freeze_array(struct r10conf *conf)
 	spin_lock_irq(&conf->resync_lock);
 	conf->barrier++;
 	conf->nr_waiting++;
-	wait_event_lock_irq(conf->wait_barrier,
-			    conf->nr_pending == conf->nr_queued+1,
-			    conf->resync_lock,
-			    flush_pending_writes(conf));
+	wait_event_lock_irq_cmd(conf->wait_barrier,
+				conf->nr_pending == conf->nr_queued+1,
+				conf->resync_lock,
+				flush_pending_writes(conf));
 
 	spin_unlock_irq(&conf->resync_lock);
 }
@@ -1069,7 +1068,7 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule)
 	struct r10conf *conf = mddev->private;
 	struct bio *bio;
 
-	if (from_schedule) {
+	if (from_schedule || current->bio_list) {
 		spin_lock_irq(&conf->device_lock);
 		bio_list_merge(&conf->pending_bio_list, &plug->pending);
 		conf->pending_count += plug->pending_cnt;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index a450268..842c747 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -53,6 +53,8 @@
 #include <linux/cpu.h>
 #include <linux/slab.h>
 #include <linux/ratelimit.h>
+#include <trace/events/block.h>
+
 #include "md.h"
 #include "raid5.h"
 #include "raid0.h"
@@ -182,6 +184,8 @@ static void return_io(struct bio *return_bi)
 		return_bi = bi->bi_next;
 		bi->bi_next = NULL;
 		bi->bi_size = 0;
+		trace_block_bio_complete(bdev_get_queue(bi->bi_bdev),
+					 bi, 0);
 		bio_endio(bi, 0);
 		bi = return_bi;
 	}
@@ -196,6 +200,21 @@ static int stripe_operations_active(struct stripe_head *sh)
 	       test_bit(STRIPE_COMPUTE_RUN, &sh->state);
 }
 
+static void raid5_wakeup_stripe_thread(struct stripe_head *sh)
+{
+	struct r5conf *conf = sh->raid_conf;
+	struct raid5_percpu *percpu;
+	int i, orphaned = 1;
+
+	percpu = per_cpu_ptr(conf->percpu, sh->cpu);
+	for_each_cpu(i, &percpu->handle_threads) {
+		md_wakeup_thread(conf->aux_threads[i]->thread);
+		orphaned = 0;
+	}
+	if (orphaned)
+		md_wakeup_thread(conf->mddev->thread);
+}
+
 static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh)
 {
 	BUG_ON(!list_empty(&sh->lru));
@@ -208,9 +227,19 @@ static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh)
 			   sh->bm_seq - conf->seq_write > 0)
 			list_add_tail(&sh->lru, &conf->bitmap_list);
 		else {
+			int cpu = sh->cpu;
+			struct raid5_percpu *percpu;
+			if (!cpu_online(cpu)) {
+				cpu = cpumask_any(cpu_online_mask);
+				sh->cpu = cpu;
+			}
+			percpu = per_cpu_ptr(conf->percpu, cpu);
+
 			clear_bit(STRIPE_DELAYED, &sh->state);
 			clear_bit(STRIPE_BIT_DELAY, &sh->state);
-			list_add_tail(&sh->lru, &conf->handle_list);
+			list_add_tail(&sh->lru, &percpu->handle_list);
+			raid5_wakeup_stripe_thread(sh);
+			return;
 		}
 		md_wakeup_thread(conf->mddev->thread);
 	} else {
@@ -355,6 +384,7 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int previous)
 		raid5_build_block(sh, i, previous);
 	}
 	insert_hash(conf, sh);
+	sh->cpu = smp_processor_id();
 }
 
 static struct stripe_head *__find_stripe(struct r5conf *conf, sector_t sector,
@@ -466,7 +496,7 @@ get_active_stripe(struct r5conf *conf, sector_t sector,
 	do {
 		wait_event_lock_irq(conf->wait_for_stripe,
 				    conf->quiesce == 0 || noquiesce,
-				    conf->device_lock, /* nothing */);
+				    conf->device_lock);
 		sh = __find_stripe(conf, sector, conf->generation - previous);
 		if (!sh) {
 			if (!conf->inactive_blocked)
@@ -480,8 +510,7 @@ get_active_stripe(struct r5conf *conf, sector_t sector,
 						    (atomic_read(&conf->active_stripes)
 						     < (conf->max_nr_stripes *3/4)
 						     || !conf->inactive_blocked),
-						    conf->device_lock,
-						    );
+						    conf->device_lock);
 				conf->inactive_blocked = 0;
 			} else
 				init_stripe(sh, sector, previous);
@@ -671,6 +700,9 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 			bi->bi_next = NULL;
 			if (rrdev)
 				set_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags);
+			trace_block_bio_remap(bdev_get_queue(bi->bi_bdev),
+					      bi, disk_devt(conf->mddev->gendisk),
+					      sh->dev[i].sector);
 			generic_make_request(bi);
 		}
 		if (rrdev) {
@@ -698,6 +730,9 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 			rbi->bi_io_vec[0].bv_offset = 0;
 			rbi->bi_size = STRIPE_SIZE;
 			rbi->bi_next = NULL;
+			trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev),
+					      rbi, disk_devt(conf->mddev->gendisk),
+					      sh->dev[i].sector);
 			generic_make_request(rbi);
 		}
 		if (!rdev && !rrdev) {
@@ -1576,7 +1611,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
 	 * This happens in stages:
 	 * 1/ create a new kmem_cache and allocate the required number of
 	 *    stripe_heads.
-	 * 2/ gather all the old stripe_heads and tranfer the pages across
+	 * 2/ gather all the old stripe_heads and transfer the pages across
 	 *    to the new stripe_heads.  This will have the side effect of
 	 *    freezing the array as once all stripe_heads have been collected,
 	 *    no IO will be possible.  Old stripe heads are freed once their
@@ -1646,8 +1681,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
 		spin_lock_irq(&conf->device_lock);
 		wait_event_lock_irq(conf->wait_for_stripe,
 				    !list_empty(&conf->inactive_list),
-				    conf->device_lock,
-				    );
+				    conf->device_lock);
 		osh = get_free_stripe(conf);
 		spin_unlock_irq(&conf->device_lock);
 		atomic_set(&nsh->count, 1);
@@ -2855,8 +2889,10 @@ static void handle_stripe_dirtying(struct r5conf *conf,
 	pr_debug("for sector %llu, rmw=%d rcw=%d\n",
 		(unsigned long long)sh->sector, rmw, rcw);
 	set_bit(STRIPE_HANDLE, &sh->state);
-	if (rmw < rcw && rmw > 0)
+	if (rmw < rcw && rmw > 0) {
 		/* prefer read-modify-write, but need to get some data */
+		blk_add_trace_msg(conf->mddev->queue, "raid5 rmw %llu %d",
+				  (unsigned long long)sh->sector, rmw);
 		for (i = disks; i--; ) {
 			struct r5dev *dev = &sh->dev[i];
 			if ((dev->towrite || i == sh->pd_idx) &&
@@ -2867,7 +2903,7 @@ static void handle_stripe_dirtying(struct r5conf *conf,
 				if (
 				  test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
 					pr_debug("Read_old block "
-						"%d for r-m-w\n", i);
+						 "%d for r-m-w\n", i);
 					set_bit(R5_LOCKED, &dev->flags);
 					set_bit(R5_Wantread, &dev->flags);
 					s->locked++;
@@ -2877,8 +2913,10 @@ static void handle_stripe_dirtying(struct r5conf *conf,
 				}
 			}
 		}
+	}
 	if (rcw <= rmw && rcw > 0) {
 		/* want reconstruct write, but need to get some data */
+		int qread =0;
 		rcw = 0;
 		for (i = disks; i--; ) {
 			struct r5dev *dev = &sh->dev[i];
@@ -2897,12 +2935,17 @@ static void handle_stripe_dirtying(struct r5conf *conf,
 					set_bit(R5_LOCKED, &dev->flags);
 					set_bit(R5_Wantread, &dev->flags);
 					s->locked++;
+					qread++;
 				} else {
 					set_bit(STRIPE_DELAYED, &sh->state);
 					set_bit(STRIPE_HANDLE, &sh->state);
 				}
 			}
 		}
+		if (rcw)
+			blk_add_trace_msg(conf->mddev->queue, "raid5 rcw %llu %d %d %d",
+					  (unsigned long long)sh->sector,
+					  rcw, qread, test_bit(STRIPE_DELAYED, &sh->state));
 	}
 	/* now if nothing is locked, and if we have enough data,
 	 * we can start a write request
@@ -3224,10 +3267,7 @@ static void handle_stripe_expansion(struct r5conf *conf, struct stripe_head *sh)
 
 		}
 	/* done submitting copies, wait for them to complete */
-	if (tx) {
-		async_tx_ack(tx);
-		dma_wait_for_async_tx(tx);
-	}
+	async_tx_quiesce(&tx);
 }
 
 /*
@@ -3747,12 +3787,19 @@ static void raid5_activate_delayed(struct r5conf *conf)
 		while (!list_empty(&conf->delayed_list)) {
 			struct list_head *l = conf->delayed_list.next;
 			struct stripe_head *sh;
+			int cpu;
 			sh = list_entry(l, struct stripe_head, lru);
 			list_del_init(l);
 			clear_bit(STRIPE_DELAYED, &sh->state);
 			if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
 				atomic_inc(&conf->preread_active_stripes);
 			list_add_tail(&sh->lru, &conf->hold_list);
+			cpu = sh->cpu;
+			if (!cpu_online(cpu)) {
+				cpu = cpumask_any(cpu_online_mask);
+				sh->cpu = cpu;
+			}
+			raid5_wakeup_stripe_thread(sh);
 		}
 	}
 }
@@ -3903,6 +3950,8 @@ static void raid5_align_endio(struct bio *bi, int error)
 	rdev_dec_pending(rdev, conf->mddev);
 
 	if (!error && uptodate) {
+		trace_block_bio_complete(bdev_get_queue(raid_bi->bi_bdev),
+					 raid_bi, 0);
 		bio_endio(raid_bi, 0);
 		if (atomic_dec_and_test(&conf->active_aligned_reads))
 			wake_up(&conf->wait_for_stripe);
@@ -4003,10 +4052,13 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
 		spin_lock_irq(&conf->device_lock);
 		wait_event_lock_irq(conf->wait_for_stripe,
 				    conf->quiesce == 0,
-				    conf->device_lock, /* nothing */);
+				    conf->device_lock);
 		atomic_inc(&conf->active_aligned_reads);
 		spin_unlock_irq(&conf->device_lock);
 
+		trace_block_bio_remap(bdev_get_queue(align_bi->bi_bdev),
+				      align_bi, disk_devt(mddev->gendisk),
+				      raid_bio->bi_sector);
 		generic_make_request(align_bi);
 		return 1;
 	} else {
@@ -4026,18 +4078,29 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
  * head of the hold_list has changed, i.e. the head was promoted to the
  * handle_list.
  */
-static struct stripe_head *__get_priority_stripe(struct r5conf *conf)
-{
-	struct stripe_head *sh;
-
+static struct stripe_head *__get_priority_stripe(struct r5conf *conf,
+	cpumask_t *mask)
+{
+	struct stripe_head *sh = NULL, *tmp;
+	struct list_head *handle_list = NULL;
+	int cpu;
+
+	/* Should we take action to avoid starvation of latter CPUs ? */
+	for_each_cpu(cpu, mask) {
+		struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
+		if (!list_empty(&percpu->handle_list)) {
+			handle_list = &percpu->handle_list;
+			break;
+		}
+	}
 	pr_debug("%s: handle: %s hold: %s full_writes: %d bypass_count: %d\n",
 		  __func__,
-		  list_empty(&conf->handle_list) ? "empty" : "busy",
+		  !handle_list ? "empty" : "busy",
 		  list_empty(&conf->hold_list) ? "empty" : "busy",
 		  atomic_read(&conf->pending_full_writes), conf->bypass_count);
 
-	if (!list_empty(&conf->handle_list)) {
-		sh = list_entry(conf->handle_list.next, typeof(*sh), lru);
+	if (handle_list) {
+		sh = list_entry(handle_list->next, typeof(*sh), lru);
 
 		if (list_empty(&conf->hold_list))
 			conf->bypass_count = 0;
@@ -4055,12 +4118,23 @@ static struct stripe_head *__get_priority_stripe(struct r5conf *conf)
 		   ((conf->bypass_threshold &&
 		     conf->bypass_count > conf->bypass_threshold) ||
 		    atomic_read(&conf->pending_full_writes) == 0)) {
-		sh = list_entry(conf->hold_list.next,
-				typeof(*sh), lru);
-		conf->bypass_count -= conf->bypass_threshold;
-		if (conf->bypass_count < 0)
-			conf->bypass_count = 0;
-	} else
+
+		list_for_each_entry(tmp, &conf->hold_list,  lru) {
+			if (cpumask_test_cpu(tmp->cpu, mask) ||
+			    !cpu_online(tmp->cpu)) {
+				sh = tmp;
+				break;
+			}
+		}
+
+		if (sh) {
+			conf->bypass_count -= conf->bypass_threshold;
+			if (conf->bypass_count < 0)
+				conf->bypass_count = 0;
+		}
+	}
+
+	if (!sh)
 		return NULL;
 
 	list_del_init(&sh->lru);
@@ -4081,6 +4155,7 @@ static void raid5_unplug(struct blk_plug_cb *blk_cb, bool from_schedule)
 	struct stripe_head *sh;
 	struct mddev *mddev = cb->cb.data;
 	struct r5conf *conf = mddev->private;
+	int cnt = 0;
 
 	if (cb->list.next && !list_empty(&cb->list)) {
 		spin_lock_irq(&conf->device_lock);
@@ -4095,9 +4170,11 @@ static void raid5_unplug(struct blk_plug_cb *blk_cb, bool from_schedule)
 			smp_mb__before_clear_bit();
 			clear_bit(STRIPE_ON_UNPLUG_LIST, &sh->state);
 			__release_stripe(conf, sh);
+			cnt++;
 		}
 		spin_unlock_irq(&conf->device_lock);
 	}
+	trace_block_unplug(mddev->queue, cnt, !from_schedule);
 	kfree(cb);
 }
 
@@ -4355,6 +4432,8 @@ static void make_request(struct mddev *mddev, struct bio * bi)
 		if ( rw == WRITE )
 			md_write_end(mddev);
 
+		trace_block_bio_complete(bdev_get_queue(bi->bi_bdev),
+					 bi, 0);
 		bio_endio(bi, 0);
 	}
 }
@@ -4731,21 +4810,24 @@ static int  retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
 		handled++;
 	}
 	remaining = raid5_dec_bi_active_stripes(raid_bio);
-	if (remaining == 0)
+	if (remaining == 0) {
+		trace_block_bio_complete(bdev_get_queue(raid_bio->bi_bdev),
+					 raid_bio, 0);
 		bio_endio(raid_bio, 0);
+	}
 	if (atomic_dec_and_test(&conf->active_aligned_reads))
 		wake_up(&conf->wait_for_stripe);
 	return handled;
 }
 
 #define MAX_STRIPE_BATCH 8
-static int handle_active_stripes(struct r5conf *conf)
+static int handle_active_stripes(struct r5conf *conf, cpumask_t *mask)
 {
 	struct stripe_head *batch[MAX_STRIPE_BATCH], *sh;
 	int i, batch_size = 0;
 
 	while (batch_size < MAX_STRIPE_BATCH &&
-			(sh = __get_priority_stripe(conf)) != NULL)
+			(sh = __get_priority_stripe(conf, mask)) != NULL)
 		batch[batch_size++] = sh;
 
 	if (batch_size == 0)
@@ -4763,6 +4845,35 @@ static int handle_active_stripes(struct r5conf *conf)
 	return batch_size;
 }
 
+static void raid5auxd(struct md_thread *thread)
+{
+	struct mddev *mddev = thread->mddev;
+	struct r5conf *conf = mddev->private;
+	struct blk_plug plug;
+	int handled;
+	struct raid5_auxth *auxth = thread->private;
+
+	pr_debug("+++ raid5auxd active\n");
+
+	blk_start_plug(&plug);
+	handled = 0;
+	spin_lock_irq(&conf->device_lock);
+	while (1) {
+		int batch_size;
+
+		batch_size = handle_active_stripes(conf, &auxth->work_mask);
+		if (!batch_size)
+			break;
+		handled += batch_size;
+	}
+	pr_debug("%d stripes handled\n", handled);
+
+	spin_unlock_irq(&conf->device_lock);
+	blk_finish_plug(&plug);
+
+	pr_debug("--- raid5auxd inactive\n");
+}
+
 /*
  * This is our raid5 kernel thread.
  *
@@ -4810,7 +4921,7 @@ static void raid5d(struct md_thread *thread)
 			handled++;
 		}
 
-		batch_size = handle_active_stripes(conf);
+		batch_size = handle_active_stripes(conf, &conf->work_mask);
 		if (!batch_size)
 			break;
 		handled += batch_size;
@@ -4939,10 +5050,270 @@ stripe_cache_active_show(struct mddev *mddev, char *page)
 static struct md_sysfs_entry
 raid5_stripecache_active = __ATTR_RO(stripe_cache_active);
 
+static void raid5_update_threads_handle_mask(struct mddev *mddev)
+{
+	int cpu, i;
+	struct raid5_percpu *percpu;
+	struct r5conf *conf = mddev->private;
+
+	for_each_online_cpu(cpu) {
+		percpu = per_cpu_ptr(conf->percpu, cpu);
+		cpumask_clear(&percpu->handle_threads);
+	}
+	cpumask_copy(&conf->work_mask, cpu_online_mask);
+
+	for (i = 0; i < conf->aux_thread_num; i++) {
+		cpumask_t *work_mask = &conf->aux_threads[i]->work_mask;
+		for_each_cpu(cpu, work_mask) {
+			percpu = per_cpu_ptr(conf->percpu, cpu);
+			cpumask_set_cpu(i, &percpu->handle_threads);
+		}
+		cpumask_andnot(&conf->work_mask, &conf->work_mask,
+				work_mask);
+	}
+}
+
+struct raid5_auxth_sysfs {
+	struct attribute attr;
+	ssize_t (*show)(struct mddev *, struct raid5_auxth *, char *);
+	ssize_t (*store)(struct mddev *, struct raid5_auxth *,
+		const char *, size_t);
+};
+
+static ssize_t raid5_show_thread_cpulist(struct mddev *mddev,
+	struct raid5_auxth *thread, char *page)
+{
+	if (!mddev->private)
+		return 0;
+	return cpulist_scnprintf(page, PAGE_SIZE, &thread->work_mask);
+}
+
+static ssize_t
+raid5_store_thread_cpulist(struct mddev *mddev, struct raid5_auxth *thread,
+	const char *page, size_t len)
+{
+	struct r5conf *conf = mddev->private;
+	cpumask_var_t mask;
+
+	if (!conf)
+		return -ENODEV;
+	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+		return -ENOMEM;
+
+	if (cpulist_parse(page, mask)) {
+		free_cpumask_var(mask);
+		return -EINVAL;
+	}
+
+	get_online_cpus();
+	spin_lock_irq(&conf->device_lock);
+	cpumask_copy(&thread->work_mask, mask);
+	raid5_update_threads_handle_mask(mddev);
+	spin_unlock_irq(&conf->device_lock);
+	put_online_cpus();
+	set_cpus_allowed_ptr(thread->thread->tsk, mask);
+
+	free_cpumask_var(mask);
+	return len;
+}
+
+static struct raid5_auxth_sysfs thread_cpulist =
+__ATTR(cpulist, S_IRUGO|S_IWUSR, raid5_show_thread_cpulist,
+	raid5_store_thread_cpulist);
+
+static struct attribute *auxth_attrs[] = {
+	&thread_cpulist.attr,
+	NULL,
+};
+
+static ssize_t
+raid5_auxth_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
+{
+	struct raid5_auxth_sysfs *entry = container_of(attr,
+		struct raid5_auxth_sysfs, attr);
+	struct raid5_auxth *thread = container_of(kobj,
+		struct raid5_auxth, kobj);
+	struct mddev *mddev = thread->thread->mddev;
+	ssize_t ret;
+
+	if (!entry->show)
+		return -EIO;
+	mddev_lock(mddev);
+	ret = entry->show(mddev, thread, page);
+	mddev_unlock(mddev);
+	return ret;
+}
+
+static ssize_t
+raid5_auxth_attr_store(struct kobject *kobj, struct attribute *attr,
+	      const char *page, size_t length)
+{
+	struct raid5_auxth_sysfs *entry = container_of(attr,
+		struct raid5_auxth_sysfs, attr);
+	struct raid5_auxth *thread = container_of(kobj,
+		struct raid5_auxth, kobj);
+	struct mddev *mddev = thread->thread->mddev;
+	ssize_t ret;
+
+	if (!entry->store)
+		return -EIO;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+	mddev_lock(mddev);
+	ret = entry->store(mddev, thread, page, length);
+	mddev_unlock(mddev);
+	return ret;
+}
+
+static void raid5_auxth_release(struct kobject *kobj)
+{
+	struct raid5_auxth *thread = container_of(kobj,
+		struct raid5_auxth, kobj);
+	kfree(thread);
+}
+
+static const struct sysfs_ops raid5_auxth_sysfsops = {
+	.show = raid5_auxth_attr_show,
+	.store = raid5_auxth_attr_store,
+};
+static struct kobj_type raid5_auxth_ktype = {
+	.release = raid5_auxth_release,
+	.sysfs_ops = &raid5_auxth_sysfsops,
+	.default_attrs = auxth_attrs,
+};
+
+static ssize_t
+raid5_show_auxthread_number(struct mddev *mddev, char *page)
+{
+	struct r5conf *conf = mddev->private;
+	if (conf)
+		return sprintf(page, "%d\n", conf->aux_thread_num);
+	else
+		return 0;
+}
+
+static void raid5_auxth_delete(struct work_struct *ws)
+{
+	struct raid5_auxth *thread = container_of(ws, struct raid5_auxth,
+		del_work);
+
+	kobject_del(&thread->kobj);
+	kobject_put(&thread->kobj);
+}
+
+static void __free_aux_thread(struct mddev *mddev, struct raid5_auxth *thread)
+{
+	md_unregister_thread(&thread->thread);
+	INIT_WORK(&thread->del_work, raid5_auxth_delete);
+	kobject_get(&thread->kobj);
+	md_queue_misc_work(&thread->del_work);
+}
+
+static struct raid5_auxth *__create_aux_thread(struct mddev *mddev, int i)
+{
+	struct raid5_auxth *thread;
+	char name[10];
+
+	thread = kzalloc(sizeof(*thread), GFP_KERNEL);
+	if (!thread)
+		return NULL;
+	snprintf(name, 10, "aux%d", i);
+	thread->thread = md_register_thread(raid5auxd, mddev, name);
+	if (!thread->thread) {
+		kfree(thread);
+		return NULL;
+	}
+	thread->thread->private = thread;
+
+	cpumask_copy(&thread->work_mask, cpu_online_mask);
+
+	if (kobject_init_and_add(&thread->kobj, &raid5_auxth_ktype,
+	    &mddev->kobj, "auxth%d", i)) {
+		md_unregister_thread(&thread->thread);
+		kfree(thread);
+		return NULL;
+	}
+	return thread;
+}
+
+static ssize_t
+raid5_store_auxthread_number(struct mddev *mddev, const char *page, size_t len)
+{
+	struct r5conf *conf = mddev->private;
+	unsigned long new;
+	int i;
+	struct raid5_auxth **threads;
+
+	if (len >= PAGE_SIZE)
+		return -EINVAL;
+	if (!conf)
+		return -ENODEV;
+
+	if (kstrtoul(page, 10, &new))
+		return -EINVAL;
+
+	if (new == conf->aux_thread_num)
+		return len;
+
+	/* There is no point creating more threads than cpu number */
+	if (new > num_online_cpus())
+		return -EINVAL;
+
+	if (new > conf->aux_thread_num) {
+		threads = kzalloc(sizeof(struct raid5_auxth *) * new,
+				GFP_KERNEL);
+		if (!threads)
+			return -ENOMEM;
+
+		i = conf->aux_thread_num;
+		while (i < new) {
+			threads[i] = __create_aux_thread(mddev, i);
+			if (!threads[i])
+				goto error;
+
+			i++;
+		}
+		memcpy(threads, conf->aux_threads,
+			sizeof(struct raid5_auxth *) * conf->aux_thread_num);
+		get_online_cpus();
+		spin_lock_irq(&conf->device_lock);
+		kfree(conf->aux_threads);
+		conf->aux_threads = threads;
+		conf->aux_thread_num = new;
+		raid5_update_threads_handle_mask(mddev);
+		spin_unlock_irq(&conf->device_lock);
+		put_online_cpus();
+	} else {
+		int old = conf->aux_thread_num;
+
+		get_online_cpus();
+		spin_lock_irq(&conf->device_lock);
+		conf->aux_thread_num = new;
+		raid5_update_threads_handle_mask(mddev);
+		spin_unlock_irq(&conf->device_lock);
+		put_online_cpus();
+		for (i = new; i < old; i++)
+			__free_aux_thread(mddev, conf->aux_threads[i]);
+	}
+
+	return len;
+error:
+	while (--i >= conf->aux_thread_num)
+		__free_aux_thread(mddev, threads[i]);
+	kfree(threads);
+	return -ENOMEM;
+}
+
+static struct md_sysfs_entry
+raid5_auxthread_number = __ATTR(auxthread_number, S_IRUGO|S_IWUSR,
+				raid5_show_auxthread_number,
+				raid5_store_auxthread_number);
+
 static struct attribute *raid5_attrs[] =  {
 	&raid5_stripecache_size.attr,
 	&raid5_stripecache_active.attr,
 	&raid5_preread_bypass_threshold.attr,
+	&raid5_auxthread_number.attr,
 	NULL,
 };
 static struct attribute_group raid5_attrs_group = {
@@ -4990,6 +5361,7 @@ static void raid5_free_percpu(struct r5conf *conf)
 
 static void free_conf(struct r5conf *conf)
 {
+	kfree(conf->aux_threads);
 	shrink_stripes(conf);
 	raid5_free_percpu(conf);
 	kfree(conf->disks);
@@ -5002,7 +5374,7 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
 			      void *hcpu)
 {
 	struct r5conf *conf = container_of(nfb, struct r5conf, cpu_notify);
-	long cpu = (long)hcpu;
+	long cpu = (long)hcpu, anycpu;
 	struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
 
 	switch (action) {
@@ -5021,9 +5393,17 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
 			       __func__, cpu);
 			return notifier_from_errno(-ENOMEM);
 		}
+		INIT_LIST_HEAD(&(percpu->handle_list));
+		cpumask_clear(&percpu->handle_threads);
 		break;
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
+		spin_lock_irq(&conf->device_lock);
+		anycpu = cpumask_any(cpu_online_mask);
+		list_splice_tail_init(&percpu->handle_list,
+			&per_cpu_ptr(conf->percpu, anycpu)->handle_list);
+		spin_unlock_irq(&conf->device_lock);
+
 		safe_put_page(percpu->spare_page);
 		kfree(percpu->scribble);
 		percpu->spare_page = NULL;
@@ -5032,6 +5412,10 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
 	default:
 		break;
 	}
+
+	spin_lock_irq(&conf->device_lock);
+	raid5_update_threads_handle_mask(conf->mddev);
+	spin_unlock_irq(&conf->device_lock);
 	return NOTIFY_OK;
 }
 #endif
@@ -5052,20 +5436,24 @@ static int raid5_alloc_percpu(struct r5conf *conf)
 	get_online_cpus();
 	err = 0;
 	for_each_present_cpu(cpu) {
+		struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
+
 		if (conf->level == 6) {
 			spare_page = alloc_page(GFP_KERNEL);
 			if (!spare_page) {
 				err = -ENOMEM;
 				break;
 			}
-			per_cpu_ptr(conf->percpu, cpu)->spare_page = spare_page;
+			percpu->spare_page = spare_page;
 		}
 		scribble = kmalloc(conf->scribble_len, GFP_KERNEL);
 		if (!scribble) {
 			err = -ENOMEM;
 			break;
 		}
-		per_cpu_ptr(conf->percpu, cpu)->scribble = scribble;
+		percpu->scribble = scribble;
+		INIT_LIST_HEAD(&percpu->handle_list);
+		cpumask_clear(&percpu->handle_threads);
 	}
 #ifdef CONFIG_HOTPLUG_CPU
 	conf->cpu_notify.notifier_call = raid456_cpu_notify;
@@ -5121,7 +5509,6 @@ static struct r5conf *setup_conf(struct mddev *mddev)
 	spin_lock_init(&conf->device_lock);
 	init_waitqueue_head(&conf->wait_for_stripe);
 	init_waitqueue_head(&conf->wait_for_overlap);
-	INIT_LIST_HEAD(&conf->handle_list);
 	INIT_LIST_HEAD(&conf->hold_list);
 	INIT_LIST_HEAD(&conf->delayed_list);
 	INIT_LIST_HEAD(&conf->bitmap_list);
@@ -5132,6 +5519,8 @@ static struct r5conf *setup_conf(struct mddev *mddev)
 	conf->bypass_threshold = BYPASS_THRESHOLD;
 	conf->recovery_disabled = mddev->recovery_disabled - 1;
 
+	cpumask_copy(&conf->work_mask, cpu_online_mask);
+
 	conf->raid_disks = mddev->raid_disks;
 	if (mddev->reshape_position == MaxSector)
 		conf->previous_raid_disks = mddev->raid_disks;
@@ -5588,6 +5977,10 @@ abort:
 static int stop(struct mddev *mddev)
 {
 	struct r5conf *conf = mddev->private;
+	int i;
+
+	for (i = 0; i < conf->aux_thread_num; i++)
+		__free_aux_thread(mddev, conf->aux_threads[i]);
 
 	md_unregister_thread(&mddev->thread);
 	if (mddev->queue)
@@ -6095,7 +6488,7 @@ static void raid5_quiesce(struct mddev *mddev, int state)
 		wait_event_lock_irq(conf->wait_for_stripe,
 				    atomic_read(&conf->active_stripes) == 0 &&
 				    atomic_read(&conf->active_aligned_reads) == 0,
-				    conf->device_lock, /* nothing */);
+				    conf->device_lock);
 		conf->quiesce = 1;
 		spin_unlock_irq(&conf->device_lock);
 		/* allow reshape to continue */
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index 18b2c4a..2afd835 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -211,6 +211,7 @@ struct stripe_head {
 	enum check_states	check_state;
 	enum reconstruct_states reconstruct_state;
 	spinlock_t		stripe_lock;
+	int			cpu;
 	/**
 	 * struct stripe_operations
 	 * @target - STRIPE_OP_COMPUTE_BLK target
@@ -365,6 +366,14 @@ struct disk_info {
 	struct md_rdev	*rdev, *replacement;
 };
 
+struct raid5_auxth {
+	struct md_thread	*thread;
+	/* which CPUs should the auxiliary thread handle stripes from */
+	cpumask_t		work_mask;
+	struct kobject		kobj;
+	struct work_struct	del_work;
+};
+
 struct r5conf {
 	struct hlist_head	*stripe_hashtbl;
 	struct mddev		*mddev;
@@ -433,6 +442,12 @@ struct r5conf {
 					      * lists and performing address
 					      * conversions
 					      */
+		struct list_head handle_list;
+		cpumask_t	handle_threads; /* Which threads can the CPU's
+						 * stripes be handled. It really
+						 * is a bitmap to aux_threads[],
+						 * but has max bits NR_CPUS
+						 */
 	} __percpu *percpu;
 	size_t			scribble_len; /* size of scribble region must be
 					       * associated with conf to handle
@@ -460,6 +475,10 @@ struct r5conf {
 	 * the new thread here until we fully activate the array.
 	 */
 	struct md_thread	*thread;
+	int			aux_thread_num;
+	struct raid5_auxth	**aux_threads;
+	/* which CPUs should raid5d thread handle stripes from */
+	cpumask_t		work_mask;
 };
 
 /*
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index 4ef0d80..8567a7a 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -79,8 +79,7 @@ config MEDIA_RC_SUPPORT
 #
 
 config MEDIA_CONTROLLER
-	bool "Media Controller API (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	bool "Media Controller API"
 	depends on MEDIA_CAMERA_SUPPORT
 	---help---
 	  Enable the media controller API used to query media devices internal
@@ -100,8 +99,8 @@ config VIDEO_DEV
 	default y
 
 config VIDEO_V4L2_SUBDEV_API
-	bool "V4L2 sub-device userspace API (EXPERIMENTAL)"
-	depends on VIDEO_DEV && MEDIA_CONTROLLER && EXPERIMENTAL
+	bool "V4L2 sub-device userspace API"
+	depends on VIDEO_DEV && MEDIA_CONTROLLER
 	---help---
 	  Enables the V4L2 sub-device pad-level userspace API used to configure
 	  video format, size and frame rate between hardware blocks.
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig
index 121b011..d2a436c 100644
--- a/drivers/media/common/Kconfig
+++ b/drivers/media/common/Kconfig
@@ -1,3 +1,10 @@
+# Used by common drivers, when they need to ask questions
+config MEDIA_COMMON_OPTIONS
+	bool
+
+comment "common driver options"
+	depends on MEDIA_COMMON_OPTIONS
+
 source "drivers/media/common/b2c2/Kconfig"
 source "drivers/media/common/saa7146/Kconfig"
 source "drivers/media/common/siano/Kconfig"
diff --git a/drivers/media/common/b2c2/Kconfig b/drivers/media/common/b2c2/Kconfig
index 1df9e57..a8c6cdf 100644
--- a/drivers/media/common/b2c2/Kconfig
+++ b/drivers/media/common/b2c2/Kconfig
@@ -17,11 +17,6 @@ config DVB_B2C2_FLEXCOP
 	select DVB_CX24123 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_TUNER_CX24113 if MEDIA_SUBDRV_AUTOSELECT
-	help
-	  Support for the digital TV receiver chip made by B2C2 Inc. included in
-	  Technisats PCI cards and USB boxes.
-
-	  Say Y if you own such a device and want to use it.
 
 # Selected via the PCI or USB flexcop drivers
 config DVB_B2C2_FLEXCOP_DEBUG
diff --git a/drivers/media/common/siano/Kconfig b/drivers/media/common/siano/Kconfig
index 425aead..68f0f60 100644
--- a/drivers/media/common/siano/Kconfig
+++ b/drivers/media/common/siano/Kconfig
@@ -4,14 +4,16 @@
 
 config SMS_SIANO_MDTV
 	tristate
-	depends on DVB_CORE && RC_CORE && HAS_DMA
+	depends on DVB_CORE && HAS_DMA
+	depends on !RC_CORE || RC_CORE
 	depends on SMS_USB_DRV || SMS_SDIO_DRV
 	default y
-	---help---
-	  Choose Y or M here if you have MDTV receiver with a Siano chipset.
-
-	  To compile this driver as a module, choose M here
-	  (The module will be called smsmdtv).
 
-	  Further documentation on this driver can be found on the WWW
-	  at http://www.siano-ms.com/
+config SMS_SIANO_RC
+	bool "Enable Remote Controller support for Siano devices"
+	depends on SMS_SIANO_MDTV && RC_CORE
+	depends on SMS_USB_DRV || SMS_SDIO_DRV
+	depends on MEDIA_COMMON_OPTIONS
+	default y
+	---help---
+	  Choose Y to select Remote Controller support for Siano driver.
diff --git a/drivers/media/common/siano/Makefile b/drivers/media/common/siano/Makefile
index 2a09279..81b1e98 100644
--- a/drivers/media/common/siano/Makefile
+++ b/drivers/media/common/siano/Makefile
@@ -1,7 +1,11 @@
-smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o
+smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o
 
 obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o
 
+ifeq ($(CONFIG_SMS_SIANO_RC),y)
+  smsmdtv-objs += smsir.o
+endif
+
 ccflags-y += -Idrivers/media/dvb-core
 ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
 
diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c
index 9cc5554..1842e64 100644
--- a/drivers/media/common/siano/smscoreapi.c
+++ b/drivers/media/common/siano/smscoreapi.c
@@ -1092,7 +1092,7 @@ EXPORT_SYMBOL_GPL(smscore_onresponse);
  * @return pointer to descriptor on success, NULL on error.
  */
 
-struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev)
+static struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev)
 {
 	struct smscore_buffer_t *cb = NULL;
 	unsigned long flags;
diff --git a/drivers/media/common/siano/smsir.c b/drivers/media/common/siano/smsir.c
index 37bc5c4..b8c5cad 100644
--- a/drivers/media/common/siano/smsir.c
+++ b/drivers/media/common/siano/smsir.c
@@ -88,7 +88,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
 
 	dev->priv = coredev;
 	dev->driver_type = RC_DRIVER_IR_RAW;
-	dev->allowed_protos = RC_TYPE_ALL;
+	dev->allowed_protos = RC_BIT_ALL;
 	dev->map_name = sms_get_board(board_id)->rc_codes;
 	dev->driver_name = MODULE_NAME;
 
diff --git a/drivers/media/common/siano/smsir.h b/drivers/media/common/siano/smsir.h
index ae92b3a..69b59b9 100644
--- a/drivers/media/common/siano/smsir.h
+++ b/drivers/media/common/siano/smsir.h
@@ -46,10 +46,19 @@ struct ir_t {
 	u32 controller;
 };
 
+#ifdef CONFIG_SMS_SIANO_RC
 int sms_ir_init(struct smscore_device_t *coredev);
 void sms_ir_exit(struct smscore_device_t *coredev);
 void sms_ir_event(struct smscore_device_t *coredev,
 			const char *buf, int len);
+#else
+inline static int sms_ir_init(struct smscore_device_t *coredev) {
+	return 0;
+}
+inline static void sms_ir_exit(struct smscore_device_t *coredev) {};
+inline static void sms_ir_event(struct smscore_device_t *coredev,
+			const char *buf, int len) {};
+#endif
 
 #endif /* __SMS_IR_H__ */
 
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
index 889c9c1..d81dbb2 100644
--- a/drivers/media/dvb-core/dmxdev.c
+++ b/drivers/media/dvb-core/dmxdev.c
@@ -877,7 +877,7 @@ static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev,
 	dvb_dmxdev_filter_stop(dmxdevfilter);
 	dvb_dmxdev_filter_reset(dmxdevfilter);
 
-	if (params->pes_type > DMX_PES_OTHER || params->pes_type < 0)
+	if ((unsigned)params->pes_type > DMX_PES_OTHER)
 		return -EINVAL;
 
 	dmxdevfilter->type = DMXDEV_TYPE_PES;
diff --git a/drivers/media/dvb-core/dmxdev.h b/drivers/media/dvb-core/dmxdev.h
index 02ebe28..48c6cf9 100644
--- a/drivers/media/dvb-core/dmxdev.h
+++ b/drivers/media/dvb-core/dmxdev.h
@@ -26,6 +26,7 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/kernel.h>
+#include <linux/time.h>
 #include <linux/timer.h>
 #include <linux/wait.h>
 #include <linux/fs.h>
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index 7e92793..49d9504 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -1029,12 +1029,6 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
 	/* Get */
 	_DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1),
 	_DTV_CMD(DTV_API_VERSION, 0, 0),
-	_DTV_CMD(DTV_CODE_RATE_HP, 0, 0),
-	_DTV_CMD(DTV_CODE_RATE_LP, 0, 0),
-	_DTV_CMD(DTV_GUARD_INTERVAL, 0, 0),
-	_DTV_CMD(DTV_TRANSMISSION_MODE, 0, 0),
-	_DTV_CMD(DTV_HIERARCHY, 0, 0),
-	_DTV_CMD(DTV_INTERLEAVING, 0, 0),
 
 	_DTV_CMD(DTV_ENUM_DELSYS, 0, 0),
 
@@ -1042,13 +1036,11 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
 	_DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 1, 0),
 
 	_DTV_CMD(DTV_ATSCMH_FIC_VER, 0, 0),
-	_DTV_CMD(DTV_ATSCMH_PARADE_ID, 0, 0),
 	_DTV_CMD(DTV_ATSCMH_NOG, 0, 0),
 	_DTV_CMD(DTV_ATSCMH_TNOG, 0, 0),
 	_DTV_CMD(DTV_ATSCMH_SGN, 0, 0),
 	_DTV_CMD(DTV_ATSCMH_PRC, 0, 0),
 	_DTV_CMD(DTV_ATSCMH_RS_FRAME_MODE, 0, 0),
-	_DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 0, 0),
 	_DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_PRI, 0, 0),
 	_DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_SEC, 0, 0),
 	_DTV_CMD(DTV_ATSCMH_SCCC_BLOCK_MODE, 0, 0),
@@ -1056,8 +1048,6 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
 	_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B, 0, 0),
 	_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C, 0, 0),
 	_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D, 0, 0),
-
-	_DTV_CMD(DTV_LNA, 0, 0),
 };
 
 static void dtv_property_dump(struct dvb_frontend *fe, struct dtv_property *tvp)
diff --git a/drivers/media/dvb-frontends/cx22700.c b/drivers/media/dvb-frontends/cx22700.c
index f2a90f9..3d399d9 100644
--- a/drivers/media/dvb-frontends/cx22700.c
+++ b/drivers/media/dvb-frontends/cx22700.c
@@ -139,7 +139,7 @@ static int cx22700_set_tps(struct cx22700_state *state,
 	if (p->code_rate_HP == FEC_4_5 || p->code_rate_LP == FEC_4_5)
 		return -EINVAL;
 
-	if (p->guard_interval < GUARD_INTERVAL_1_32 ||
+	if ((int)p->guard_interval < GUARD_INTERVAL_1_32 ||
 	    p->guard_interval > GUARD_INTERVAL_1_4)
 		return -EINVAL;
 
@@ -152,7 +152,7 @@ static int cx22700_set_tps(struct cx22700_state *state,
 	    p->modulation != QAM_64)
 		return -EINVAL;
 
-	if (p->hierarchy < HIERARCHY_NONE ||
+	if ((int)p->hierarchy < HIERARCHY_NONE ||
 	    p->hierarchy > HIERARCHY_4)
 		return -EINVAL;
 
diff --git a/drivers/media/dvb-frontends/cx24123.c b/drivers/media/dvb-frontends/cx24123.c
index 7e28b4e..68c88ab 100644
--- a/drivers/media/dvb-frontends/cx24123.c
+++ b/drivers/media/dvb-frontends/cx24123.c
@@ -338,7 +338,7 @@ static int cx24123_set_fec(struct cx24123_state *state, fe_code_rate_t fec)
 {
 	u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07;
 
-	if ((fec < FEC_NONE) || (fec > FEC_AUTO))
+	if (((int)fec < FEC_NONE) || (fec > FEC_AUTO))
 		fec = FEC_AUTO;
 
 	/* Set the soft decision threshold */
diff --git a/drivers/media/dvb-frontends/dib9000.h b/drivers/media/dvb-frontends/dib9000.h
index b5781a4..de1cc91 100644
--- a/drivers/media/dvb-frontends/dib9000.h
+++ b/drivers/media/dvb-frontends/dib9000.h
@@ -97,7 +97,7 @@ static inline int dib9000_set_slave_frontend(struct dvb_frontend *fe, struct dvb
 	return -ENODEV;
 }
 
-int dib9000_remove_slave_frontend(struct dvb_frontend *fe)
+static inline int dib9000_remove_slave_frontend(struct dvb_frontend *fe)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return -ENODEV;
diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c
index 6d98537..e71cc60 100644
--- a/drivers/media/dvb-frontends/drxd_hard.c
+++ b/drivers/media/dvb-frontends/drxd_hard.c
@@ -1748,7 +1748,8 @@ static int DRX_Stop(struct drxd_state *state)
 	return status;
 }
 
-int SetOperationMode(struct drxd_state *state, int oMode)
+#if 0	/* Currently unused */
+static int SetOperationMode(struct drxd_state *state, int oMode)
 {
 	int status;
 
@@ -1788,6 +1789,7 @@ int SetOperationMode(struct drxd_state *state, int oMode)
 		state->operation_mode = oMode;
 	return status;
 }
+#endif
 
 static int StartDiversity(struct drxd_state *state)
 {
@@ -2612,7 +2614,7 @@ static int CDRXD(struct drxd_state *state, u32 IntermediateFrequency)
 	return 0;
 }
 
-int DRXD_init(struct drxd_state *state, const u8 * fw, u32 fw_size)
+static int DRXD_init(struct drxd_state *state, const u8 *fw, u32 fw_size)
 {
 	int status = 0;
 	u32 driverVersion;
@@ -2774,7 +2776,7 @@ int DRXD_init(struct drxd_state *state, const u8 * fw, u32 fw_size)
 	return status;
 }
 
-int DRXD_status(struct drxd_state *state, u32 * pLockStatus)
+static int DRXD_status(struct drxd_state *state, u32 *pLockStatus)
 {
 	DRX_GetLockStatus(state, pLockStatus);
 
diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c
index 8b4c6d5..76a4e5c 100644
--- a/drivers/media/dvb-frontends/drxk_hard.c
+++ b/drivers/media/dvb-frontends/drxk_hard.c
@@ -65,16 +65,6 @@ static bool IsQAM(struct drxk_state *state)
 	    state->m_OperationMode == OM_QAM_ITU_C;
 }
 
-bool IsA1WithPatchCode(struct drxk_state *state)
-{
-	return state->m_DRXK_A1_PATCH_CODE;
-}
-
-bool IsA1WithRomCode(struct drxk_state *state)
-{
-	return state->m_DRXK_A1_ROM_CODE;
-}
-
 #define NOA1ROM 0
 
 #define DRXDAP_FASI_SHORT_FORMAT(addr) (((addr) & 0xFC30FF80) == 0)
@@ -189,7 +179,7 @@ static inline u32 MulDiv32(u32 a, u32 b, u32 c)
 	return (u32) tmp64;
 }
 
-inline u32 Frac28a(u32 a, u32 c)
+static inline u32 Frac28a(u32 a, u32 c)
 {
 	int i = 0;
 	u32 Q1 = 0;
@@ -587,7 +577,7 @@ static int write_block(struct drxk_state *state, u32 Address,
 #define DRXK_MAX_RETRIES_POWERUP 20
 #endif
 
-int PowerUpDevice(struct drxk_state *state)
+static int PowerUpDevice(struct drxk_state *state)
 {
 	int status;
 	u8 data = 0;
@@ -720,11 +710,6 @@ static int init_state(struct drxk_state *state)
 
 	state->m_bPowerDown = (ulPowerDown != 0);
 
-	state->m_DRXK_A1_PATCH_CODE = false;
-	state->m_DRXK_A1_ROM_CODE = false;
-	state->m_DRXK_A2_ROM_CODE = false;
-	state->m_DRXK_A3_ROM_CODE = false;
-	state->m_DRXK_A2_PATCH_CODE = false;
 	state->m_DRXK_A3_PATCH_CODE = false;
 
 	/* Init AGC and PGA parameters */
@@ -921,7 +906,7 @@ static int GetDeviceCapabilities(struct drxk_state *state)
 	status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
 	if (status < 0)
 		goto error;
-	status = write16(state, SIO_TOP_COMM_KEY__A, 0xFABA);
+	status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
 	if (status < 0)
 		goto error;
 	status = read16(state, SIO_PDR_OHW_CFG__A, &sioPdrOhwCfg);
@@ -1217,7 +1202,7 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable)
 		goto error;
 
 	/*  MPEG TS pad configuration */
-	status = write16(state, SIO_TOP_COMM_KEY__A, 0xFABA);
+	status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
 	if (status < 0)
 		goto error;
 
@@ -5461,6 +5446,7 @@ static int QAMDemodulatorCommand(struct drxk_state *state,
 	} else {
 		printk(KERN_WARNING "drxk: Unknown QAM demodulator parameter "
 			"count %d\n", numberOfParameters);
+		status = -EINVAL;
 	}
 
 error:
diff --git a/drivers/media/dvb-frontends/drxk_hard.h b/drivers/media/dvb-frontends/drxk_hard.h
index 6bb9fc4..d18a896 100644
--- a/drivers/media/dvb-frontends/drxk_hard.h
+++ b/drivers/media/dvb-frontends/drxk_hard.h
@@ -320,11 +320,7 @@ struct drxk_state {
 
 	u8               *m_microcode;
 	int               m_microcode_length;
-	bool              m_DRXK_A1_PATCH_CODE;
-	bool              m_DRXK_A1_ROM_CODE;
-	bool              m_DRXK_A2_ROM_CODE;
-	bool              m_DRXK_A3_ROM_CODE;
-	bool              m_DRXK_A2_PATCH_CODE;
+	bool		  m_DRXK_A3_ROM_CODE;
 	bool              m_DRXK_A3_PATCH_CODE;
 
 	bool              m_rfmirror;
diff --git a/drivers/media/dvb-frontends/ds3000.c b/drivers/media/dvb-frontends/ds3000.c
index 5b63908..60a529e 100644
--- a/drivers/media/dvb-frontends/ds3000.c
+++ b/drivers/media/dvb-frontends/ds3000.c
@@ -30,7 +30,6 @@
 #include "ds3000.h"
 
 static int debug;
-static int force_fw_upload;
 
 #define dprintk(args...) \
 	do { \
@@ -234,7 +233,6 @@ struct ds3000_state {
 	struct i2c_adapter *i2c;
 	const struct ds3000_config *config;
 	struct dvb_frontend frontend;
-	u8 skip_fw_load;
 	/* previous uncorrected block counter for DVB-S2 */
 	u16 prevUCBS2;
 };
@@ -397,9 +395,6 @@ static int ds3000_firmware_ondemand(struct dvb_frontend *fe)
 	if (ret < 0)
 		return ret;
 
-	if (state->skip_fw_load || !force_fw_upload)
-		return 0;	/* Firmware already uploaded, skipping */
-
 	/* Load firmware */
 	/* request the firmware, this will block until someone uploads it */
 	printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__,
@@ -413,9 +408,6 @@ static int ds3000_firmware_ondemand(struct dvb_frontend *fe)
 		return ret;
 	}
 
-	/* Make sure we don't recurse back through here during loading */
-	state->skip_fw_load = 1;
-
 	ret = ds3000_load_firmware(fe, fw);
 	if (ret)
 		printk("%s: Writing firmware to device failed\n", __func__);
@@ -425,9 +417,6 @@ static int ds3000_firmware_ondemand(struct dvb_frontend *fe)
 	dprintk("%s: Firmware upload %s\n", __func__,
 			ret == 0 ? "complete" : "failed");
 
-	/* Ensure firmware is always loaded if required */
-	state->skip_fw_load = 0;
-
 	return ret;
 }
 
@@ -1309,10 +1298,8 @@ static struct dvb_frontend_ops ds3000_ops = {
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
 
-module_param(force_fw_upload, int, 0644);
-MODULE_PARM_DESC(force_fw_upload, "Force firmware upload (default:0)");
-
 MODULE_DESCRIPTION("DVB Frontend module for Montage Technology "
 			"DS3000/TS2020 hardware");
 MODULE_AUTHOR("Konstantin Dimitrov");
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(DS3000_DEFAULT_FIRMWARE);
diff --git a/drivers/media/dvb-frontends/l64781.c b/drivers/media/dvb-frontends/l64781.c
index 36fcf55..ddf866c 100644
--- a/drivers/media/dvb-frontends/l64781.c
+++ b/drivers/media/dvb-frontends/l64781.c
@@ -180,11 +180,11 @@ static int apply_frontend_param(struct dvb_frontend *fe)
 	    p->transmission_mode != TRANSMISSION_MODE_8K)
 		return -EINVAL;
 
-	if (p->guard_interval < GUARD_INTERVAL_1_32 ||
+	if ((int)p->guard_interval < GUARD_INTERVAL_1_32 ||
 	    p->guard_interval > GUARD_INTERVAL_1_4)
 		return -EINVAL;
 
-	if (p->hierarchy < HIERARCHY_NONE ||
+	if ((int)p->hierarchy < HIERARCHY_NONE ||
 	    p->hierarchy > HIERARCHY_4)
 		return -EINVAL;
 
diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c
index e20bf13..ec388c1d 100644
--- a/drivers/media/dvb-frontends/mt312.c
+++ b/drivers/media/dvb-frontends/mt312.c
@@ -549,7 +549,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe)
 	    || (p->frequency > fe->ops.info.frequency_max))
 		return -EINVAL;
 
-	if ((p->inversion < INVERSION_OFF)
+	if (((int)p->inversion < INVERSION_OFF)
 	    || (p->inversion > INVERSION_ON))
 		return -EINVAL;
 
@@ -557,7 +557,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe)
 	    || (p->symbol_rate > fe->ops.info.symbol_rate_max))
 		return -EINVAL;
 
-	if ((p->fec_inner < FEC_NONE)
+	if (((int)p->fec_inner < FEC_NONE)
 	    || (p->fec_inner > FEC_AUTO))
 		return -EINVAL;
 
diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c
index b0f6ec0..362d26d 100644
--- a/drivers/media/dvb-frontends/rtl2830.c
+++ b/drivers/media/dvb-frontends/rtl2830.c
@@ -130,7 +130,7 @@ static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val)
 }
 
 /* write single register with mask */
-int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask)
+static int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask)
 {
 	int ret;
 	u8 tmp;
@@ -150,7 +150,7 @@ int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask)
 }
 
 /* read single register with mask */
-int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask)
+static int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask)
 {
 	int ret, i;
 	u8 tmp;
@@ -256,7 +256,7 @@ static int rtl2830_sleep(struct dvb_frontend *fe)
 	return 0;
 }
 
-int rtl2830_get_tune_settings(struct dvb_frontend *fe,
+static int rtl2830_get_tune_settings(struct dvb_frontend *fe,
 	struct dvb_frontend_tune_settings *s)
 {
 	s->min_delay_ms = 500;
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index 80c8e5f..7388769 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -265,7 +265,7 @@ static int rtl2832_rd_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val)
 	return rtl2832_rd_regs(priv, reg, page, val, 1);
 }
 
-int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val)
+static int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val)
 {
 	int ret;
 
@@ -305,7 +305,7 @@ err:
 
 }
 
-int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val)
+static int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val)
 {
 	int ret, i;
 	u8 len;
@@ -510,7 +510,7 @@ static int rtl2832_sleep(struct dvb_frontend *fe)
 	return 0;
 }
 
-int rtl2832_get_tune_settings(struct dvb_frontend *fe,
+static int rtl2832_get_tune_settings(struct dvb_frontend *fe,
 	struct dvb_frontend_tune_settings *s)
 {
 	struct rtl2832_priv *priv = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c
index 79e29de..cc278b3 100644
--- a/drivers/media/dvb-frontends/stb0899_drv.c
+++ b/drivers/media/dvb-frontends/stb0899_drv.c
@@ -1260,7 +1260,7 @@ static inline void CONVERT32(u32 x, char *str)
 	*str	= '\0';
 }
 
-int stb0899_get_dev_id(struct stb0899_state *state)
+static int stb0899_get_dev_id(struct stb0899_state *state)
 {
 	u8 chip_id, release;
 	u16 id;
diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c
index 2a8aaeb..0c8e459 100644
--- a/drivers/media/dvb-frontends/stv0367.c
+++ b/drivers/media/dvb-frontends/stv0367.c
@@ -879,7 +879,8 @@ static u8 stv0367_readbits(struct stv0367_state *state, u32 label)
 	return val;
 }
 
-u8 stv0367_getbits(u8 reg, u32 label)
+#if 0 /* Currently, unused */
+static u8 stv0367_getbits(u8 reg, u32 label)
 {
 	u8 mask, pos;
 
@@ -887,7 +888,7 @@ u8 stv0367_getbits(u8 reg, u32 label)
 
 	return (reg & mask) >> pos;
 }
-
+#endif
 static int stv0367ter_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
 	struct stv0367_state *state = fe->demodulator_priv;
@@ -1263,8 +1264,8 @@ stv0367_ter_signal_type stv0367ter_check_cpamp(struct stv0367_state *state,
 	return CPAMPStatus;
 }
 
-enum
-stv0367_ter_signal_type stv0367ter_lock_algo(struct stv0367_state *state)
+static enum stv0367_ter_signal_type
+stv0367ter_lock_algo(struct stv0367_state *state)
 {
 	enum stv0367_ter_signal_type ret_flag;
 	short int wd, tempo;
@@ -1528,7 +1529,7 @@ static int stv0367ter_sleep(struct dvb_frontend *fe)
 	return stv0367ter_standby(fe, 1);
 }
 
-int stv0367ter_init(struct dvb_frontend *fe)
+static int stv0367ter_init(struct dvb_frontend *fe)
 {
 	struct stv0367_state *state = fe->demodulator_priv;
 	struct stv0367ter_state *ter_state = state->ter_state;
@@ -2378,9 +2379,9 @@ static u32 stv0367cab_get_adc_freq(struct dvb_frontend *fe, u32 ExtClk_Hz)
 	return ADCClk_Hz;
 }
 
-enum stv0367cab_mod stv0367cab_SetQamSize(struct stv0367_state *state,
-					u32 SymbolRate,
-					enum stv0367cab_mod QAMSize)
+static enum stv0367cab_mod stv0367cab_SetQamSize(struct stv0367_state *state,
+						 u32 SymbolRate,
+						 enum stv0367cab_mod QAMSize)
 {
 	/* Set QAM size */
 	stv0367_writebits(state, F367CAB_QAM_MODE, QAMSize);
@@ -2762,7 +2763,7 @@ static int stv0367cab_sleep(struct dvb_frontend *fe)
 	return stv0367cab_standby(fe, 1);
 }
 
-int stv0367cab_init(struct dvb_frontend *fe)
+static int stv0367cab_init(struct dvb_frontend *fe)
 {
 	struct stv0367_state *state = fe->demodulator_priv;
 	struct stv0367cab_state *cab_state = state->cab_state;
diff --git a/drivers/media/dvb-frontends/stv0900_core.c b/drivers/media/dvb-frontends/stv0900_core.c
index 262dfa5..b551ca3 100644
--- a/drivers/media/dvb-frontends/stv0900_core.c
+++ b/drivers/media/dvb-frontends/stv0900_core.c
@@ -300,15 +300,15 @@ static enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32
 {
 	u32 m_div, clk_sel;
 
-	dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk,
-			intp->quartz);
-
 	if (intp == NULL)
 		return STV0900_INVALID_HANDLE;
 
 	if (intp->errs)
 		return STV0900_I2C_ERROR;
 
+	dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk,
+			intp->quartz);
+
 	clk_sel = ((stv0900_get_bits(intp, F0900_SELX1RATIO) == 1) ? 4 : 6);
 	m_div = ((clk_sel * mclk) / intp->quartz) - 1;
 	stv0900_write_bits(intp, F0900_M_DIV, m_div);
diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c
index a83bf68..16a4bc5 100644
--- a/drivers/media/dvb-frontends/tda10071.c
+++ b/drivers/media/dvb-frontends/tda10071.c
@@ -96,7 +96,8 @@ static int tda10071_rd_reg(struct tda10071_priv *priv, u8 reg, u8 *val)
 }
 
 /* write single register with mask */
-int tda10071_wr_reg_mask(struct tda10071_priv *priv, u8 reg, u8 val, u8 mask)
+static int tda10071_wr_reg_mask(struct tda10071_priv *priv,
+				u8 reg, u8 val, u8 mask)
 {
 	int ret;
 	u8 tmp;
@@ -116,7 +117,8 @@ int tda10071_wr_reg_mask(struct tda10071_priv *priv, u8 reg, u8 val, u8 mask)
 }
 
 /* read single register with mask */
-int tda10071_rd_reg_mask(struct tda10071_priv *priv, u8 reg, u8 *val, u8 mask)
+static int tda10071_rd_reg_mask(struct tda10071_priv *priv,
+				u8 reg, u8 *val, u8 mask)
 {
 	int ret, i;
 	u8 tmp;
diff --git a/drivers/media/dvb-frontends/tda18271c2dd.c b/drivers/media/dvb-frontends/tda18271c2dd.c
index ad7c72e..d281f77 100644
--- a/drivers/media/dvb-frontends/tda18271c2dd.c
+++ b/drivers/media/dvb-frontends/tda18271c2dd.c
@@ -32,6 +32,7 @@
 #include <asm/div64.h>
 
 #include "dvb_frontend.h"
+#include "tda18271c2dd.h"
 
 struct SStandardParam {
 	s32   m_IFFrequency;
diff --git a/drivers/media/firewire/firedtv.h b/drivers/media/firewire/firedtv.h
index 4fdcd8c..c2ba085 100644
--- a/drivers/media/firewire/firedtv.h
+++ b/drivers/media/firewire/firedtv.h
@@ -13,6 +13,7 @@
 #ifndef _FIREDTV_H
 #define _FIREDTV_H
 
+#include <linux/time.h>
 #include <linux/dvb/dmx.h>
 #include <linux/dvb/frontend.h>
 #include <linux/list.h>
diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c
index 18a38b3..df16380 100644
--- a/drivers/media/i2c/adp1653.c
+++ b/drivers/media/i2c/adp1653.c
@@ -3,10 +3,10 @@
  *
  * Copyright (C) 2008--2011 Nokia Corporation
  *
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * Contributors:
- *	Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *	Sakari Ailus <sakari.ailus@iki.fi>
  *	Tuukka Toivonen <tuukkat76@gmail.com>
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c
index e1d4c89..10c3c1d 100644
--- a/drivers/media/i2c/adv7183.c
+++ b/drivers/media/i2c/adv7183.c
@@ -681,18 +681,7 @@ static struct i2c_driver adv7183_driver = {
 	.id_table       = adv7183_id,
 };
 
-static __init int adv7183_init(void)
-{
-	return i2c_add_driver(&adv7183_driver);
-}
-
-static __exit void adv7183_exit(void)
-{
-	i2c_del_driver(&adv7183_driver);
-}
-
-module_init(adv7183_init);
-module_exit(adv7183_exit);
+module_i2c_driver(adv7183_driver);
 
 MODULE_DESCRIPTION("Analog Devices ADV7183 video decoder driver");
 MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 109bc9b..f47555b 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -53,8 +53,7 @@ MODULE_LICENSE("GPL");
 /* ADV7604 system clock frequency */
 #define ADV7604_fsc (28636360)
 
-#define DIGITAL_INPUT ((state->prim_mode == ADV7604_PRIM_MODE_HDMI_COMP) || \
-			(state->prim_mode == ADV7604_PRIM_MODE_HDMI_GR))
+#define DIGITAL_INPUT (state->mode == ADV7604_MODE_HDMI)
 
 /*
  **********************************************************************
@@ -68,7 +67,7 @@ struct adv7604_state {
 	struct v4l2_subdev sd;
 	struct media_pad pad;
 	struct v4l2_ctrl_handler hdl;
-	enum adv7604_prim_mode prim_mode;
+	enum adv7604_mode mode;
 	struct v4l2_dv_timings timings;
 	u8 edid[256];
 	unsigned edid_blocks;
@@ -77,6 +76,7 @@ struct adv7604_state {
 	struct workqueue_struct *work_queues;
 	struct delayed_work delayed_work_enable_hotplug;
 	bool connector_hdmi;
+	bool restart_stdi_once;
 
 	/* i2c clients */
 	struct i2c_client *i2c_avlink;
@@ -106,7 +106,6 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
 	V4L2_DV_BT_CEA_720X576P50,
 	V4L2_DV_BT_CEA_1280X720P24,
 	V4L2_DV_BT_CEA_1280X720P25,
-	V4L2_DV_BT_CEA_1280X720P30,
 	V4L2_DV_BT_CEA_1280X720P50,
 	V4L2_DV_BT_CEA_1280X720P60,
 	V4L2_DV_BT_CEA_1920X1080P24,
@@ -115,6 +114,7 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
 	V4L2_DV_BT_CEA_1920X1080P50,
 	V4L2_DV_BT_CEA_1920X1080P60,
 
+	/* sorted by DMT ID */
 	V4L2_DV_BT_DMT_640X350P85,
 	V4L2_DV_BT_DMT_640X400P85,
 	V4L2_DV_BT_DMT_720X400P85,
@@ -164,6 +164,89 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
 	{ },
 };
 
+struct adv7604_video_standards {
+	struct v4l2_dv_timings timings;
+	u8 vid_std;
+	u8 v_freq;
+};
+
+/* sorted by number of lines */
+static const struct adv7604_video_standards adv7604_prim_mode_comp[] = {
+	/* { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 }, TODO flickering */
+	{ V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 },
+	{ V4L2_DV_BT_CEA_1280X720P50, 0x19, 0x01 },
+	{ V4L2_DV_BT_CEA_1280X720P60, 0x19, 0x00 },
+	{ V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 },
+	{ V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 },
+	{ V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 },
+	{ V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 },
+	{ V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 },
+	/* TODO add 1920x1080P60_RB (CVT timing) */
+	{ },
+};
+
+/* sorted by number of lines */
+static const struct adv7604_video_standards adv7604_prim_mode_gr[] = {
+	{ V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 },
+	{ V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 },
+	{ V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 },
+	{ V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 },
+	{ V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 },
+	{ V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 },
+	{ V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 },
+	{ V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 },
+	{ V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 },
+	{ V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 },
+	{ V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 },
+	{ V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 },
+	{ V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 },
+	{ V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 },
+	{ V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 },
+	{ V4L2_DV_BT_DMT_1360X768P60, 0x12, 0x00 },
+	{ V4L2_DV_BT_DMT_1366X768P60, 0x13, 0x00 },
+	{ V4L2_DV_BT_DMT_1400X1050P60, 0x14, 0x00 },
+	{ V4L2_DV_BT_DMT_1400X1050P75, 0x15, 0x00 },
+	{ V4L2_DV_BT_DMT_1600X1200P60, 0x16, 0x00 }, /* TODO not tested */
+	/* TODO add 1600X1200P60_RB (not a DMT timing) */
+	{ V4L2_DV_BT_DMT_1680X1050P60, 0x18, 0x00 },
+	{ V4L2_DV_BT_DMT_1920X1200P60_RB, 0x19, 0x00 }, /* TODO not tested */
+	{ },
+};
+
+/* sorted by number of lines */
+static const struct adv7604_video_standards adv7604_prim_mode_hdmi_comp[] = {
+	{ V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 },
+	{ V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 },
+	{ V4L2_DV_BT_CEA_1280X720P50, 0x13, 0x01 },
+	{ V4L2_DV_BT_CEA_1280X720P60, 0x13, 0x00 },
+	{ V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 },
+	{ V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 },
+	{ V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 },
+	{ V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 },
+	{ V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 },
+	{ },
+};
+
+/* sorted by number of lines */
+static const struct adv7604_video_standards adv7604_prim_mode_hdmi_gr[] = {
+	{ V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 },
+	{ V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 },
+	{ V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 },
+	{ V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 },
+	{ V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 },
+	{ V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 },
+	{ V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 },
+	{ V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 },
+	{ V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 },
+	{ V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 },
+	{ V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 },
+	{ V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 },
+	{ V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 },
+	{ V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 },
+	{ V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 },
+	{ },
+};
+
 /* ----------------------------------------------------------------------- */
 
 static inline struct adv7604_state *to_state(struct v4l2_subdev *sd)
@@ -403,9 +486,19 @@ static inline int edid_read_block(struct v4l2_subdev *sd, unsigned len, u8 *val)
 	struct i2c_client *client = state->i2c_edid;
 	u8 msgbuf0[1] = { 0 };
 	u8 msgbuf1[256];
-	struct i2c_msg msg[2] = { { client->addr, 0, 1, msgbuf0 },
-				  { client->addr, 0 | I2C_M_RD, len, msgbuf1 }
-				};
+	struct i2c_msg msg[2] = {
+		{
+			.addr = client->addr,
+			.len = 1,
+			.buf = msgbuf0
+		},
+		{
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = len,
+			.buf = msgbuf1
+		},
+	};
 
 	if (i2c_transfer(client->adapter, msg, 2) < 0)
 		return -EIO;
@@ -672,64 +765,144 @@ static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
 				((io_read(sd, 0x6f) & 0x10) >> 4));
 }
 
-static void configure_free_run(struct v4l2_subdev *sd, const struct v4l2_bt_timings *timings)
+static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,
+		u8 prim_mode,
+		const struct adv7604_video_standards *predef_vid_timings,
+		const struct v4l2_dv_timings *timings)
 {
+	struct adv7604_state *state = to_state(sd);
+	int i;
+
+	for (i = 0; predef_vid_timings[i].timings.bt.width; i++) {
+		if (!v4l_match_dv_timings(timings, &predef_vid_timings[i].timings,
+					DIGITAL_INPUT ? 250000 : 1000000))
+			continue;
+		io_write(sd, 0x00, predef_vid_timings[i].vid_std); /* video std */
+		io_write(sd, 0x01, (predef_vid_timings[i].v_freq << 4) +
+				prim_mode); /* v_freq and prim mode */
+		return 0;
+	}
+
+	return -1;
+}
+
+static int configure_predefined_video_timings(struct v4l2_subdev *sd,
+		struct v4l2_dv_timings *timings)
+{
+	struct adv7604_state *state = to_state(sd);
+	int err;
+
+	v4l2_dbg(1, debug, sd, "%s", __func__);
+
+	/* reset to default values */
+	io_write(sd, 0x16, 0x43);
+	io_write(sd, 0x17, 0x5a);
+	/* disable embedded syncs for auto graphics mode */
+	cp_write_and_or(sd, 0x81, 0xef, 0x00);
+	cp_write(sd, 0x8f, 0x00);
+	cp_write(sd, 0x90, 0x00);
+	cp_write(sd, 0xa2, 0x00);
+	cp_write(sd, 0xa3, 0x00);
+	cp_write(sd, 0xa4, 0x00);
+	cp_write(sd, 0xa5, 0x00);
+	cp_write(sd, 0xa6, 0x00);
+	cp_write(sd, 0xa7, 0x00);
+	cp_write(sd, 0xab, 0x00);
+	cp_write(sd, 0xac, 0x00);
+
+	switch (state->mode) {
+	case ADV7604_MODE_COMP:
+	case ADV7604_MODE_GR:
+		err = find_and_set_predefined_video_timings(sd,
+				0x01, adv7604_prim_mode_comp, timings);
+		if (err)
+			err = find_and_set_predefined_video_timings(sd,
+					0x02, adv7604_prim_mode_gr, timings);
+		break;
+	case ADV7604_MODE_HDMI:
+		err = find_and_set_predefined_video_timings(sd,
+				0x05, adv7604_prim_mode_hdmi_comp, timings);
+		if (err)
+			err = find_and_set_predefined_video_timings(sd,
+					0x06, adv7604_prim_mode_hdmi_gr, timings);
+		break;
+	default:
+		v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
+				__func__, state->mode);
+		err = -1;
+		break;
+	}
+
+
+	return err;
+}
+
+static void configure_custom_video_timings(struct v4l2_subdev *sd,
+		const struct v4l2_bt_timings *bt)
+{
+	struct adv7604_state *state = to_state(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	u32 width = htotal(timings);
-	u32 height = vtotal(timings);
-	u16 ch1_fr_ll = (((u32)timings->pixelclock / 100) > 0) ?
-		((width * (ADV7604_fsc / 100)) / ((u32)timings->pixelclock / 100)) : 0;
+	u32 width = htotal(bt);
+	u32 height = vtotal(bt);
+	u16 cp_start_sav = bt->hsync + bt->hbackporch - 4;
+	u16 cp_start_eav = width - bt->hfrontporch;
+	u16 cp_start_vbi = height - bt->vfrontporch;
+	u16 cp_end_vbi = bt->vsync + bt->vbackporch;
+	u16 ch1_fr_ll = (((u32)bt->pixelclock / 100) > 0) ?
+		((width * (ADV7604_fsc / 100)) / ((u32)bt->pixelclock / 100)) : 0;
+	const u8 pll[2] = {
+		0xc0 | ((width >> 8) & 0x1f),
+		width & 0xff
+	};
 
 	v4l2_dbg(2, debug, sd, "%s\n", __func__);
 
-	cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7);	/* CH1_FR_LL */
-	cp_write(sd, 0x90, ch1_fr_ll & 0xff);		/* CH1_FR_LL */
-	cp_write(sd, 0xab, (height >> 4) & 0xff); /* CP_LCOUNT_MAX */
-	cp_write(sd, 0xac, (height & 0x0f) << 4); /* CP_LCOUNT_MAX */
-	/* TODO support interlaced */
-	cp_write(sd, 0x91, 0x10);	/* INTERLACED */
-
-	/* Should only be set in auto-graphics mode [REF_02 p. 91-92] */
-	if ((io_read(sd, 0x00) == 0x07) && (io_read(sd, 0x01) == 0x02)) {
-		u16 cp_start_sav, cp_start_eav, cp_start_vbi, cp_end_vbi;
-		const u8 pll[2] = {
-			(0xc0 | ((width >> 8) & 0x1f)),
-			(width & 0xff)
-		};
+	switch (state->mode) {
+	case ADV7604_MODE_COMP:
+	case ADV7604_MODE_GR:
+		/* auto graphics */
+		io_write(sd, 0x00, 0x07); /* video std */
+		io_write(sd, 0x01, 0x02); /* prim mode */
+		/* enable embedded syncs for auto graphics mode */
+		cp_write_and_or(sd, 0x81, 0xef, 0x10);
 
+		/* Should only be set in auto-graphics mode [REF_02, p. 91-92] */
 		/* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */
 		/* IO-map reg. 0x16 and 0x17 should be written in sequence */
 		if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll)) {
 			v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n");
-			return;
+			break;
 		}
 
 		/* active video - horizontal timing */
-		cp_start_sav = timings->hsync + timings->hbackporch - 4;
-		cp_start_eav = width - timings->hfrontporch;
 		cp_write(sd, 0xa2, (cp_start_sav >> 4) & 0xff);
-		cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) | ((cp_start_eav >> 8) & 0x0f));
+		cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) |
+					((cp_start_eav >> 8) & 0x0f));
 		cp_write(sd, 0xa4, cp_start_eav & 0xff);
 
 		/* active video - vertical timing */
-		cp_start_vbi = height - timings->vfrontporch;
-		cp_end_vbi = timings->vsync + timings->vbackporch;
 		cp_write(sd, 0xa5, (cp_start_vbi >> 4) & 0xff);
-		cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) | ((cp_end_vbi >> 8) & 0xf));
+		cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) |
+					((cp_end_vbi >> 8) & 0xf));
 		cp_write(sd, 0xa7, cp_end_vbi & 0xff);
-	} else {
-		/* reset to default values */
-		io_write(sd, 0x16, 0x43);
-		io_write(sd, 0x17, 0x5a);
-		cp_write(sd, 0xa2, 0x00);
-		cp_write(sd, 0xa3, 0x00);
-		cp_write(sd, 0xa4, 0x00);
-		cp_write(sd, 0xa5, 0x00);
-		cp_write(sd, 0xa6, 0x00);
-		cp_write(sd, 0xa7, 0x00);
+		break;
+	case ADV7604_MODE_HDMI:
+		/* set default prim_mode/vid_std for HDMI
+		   accoring to [REF_03, c. 4.2] */
+		io_write(sd, 0x00, 0x02); /* video std */
+		io_write(sd, 0x01, 0x06); /* prim mode */
+		break;
+	default:
+		v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
+				__func__, state->mode);
+		break;
 	}
-}
 
+	cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7);
+	cp_write(sd, 0x90, ch1_fr_ll & 0xff);
+	cp_write(sd, 0xab, (height >> 4) & 0xff);
+	cp_write(sd, 0xac, (height & 0x0f) << 4);
+}
 
 static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 {
@@ -738,12 +911,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 	switch (state->rgb_quantization_range) {
 	case V4L2_DV_RGB_RANGE_AUTO:
 		/* automatic */
-		if ((hdmi_read(sd, 0x05) & 0x80) ||
-				(state->prim_mode == ADV7604_PRIM_MODE_COMP) ||
-				(state->prim_mode == ADV7604_PRIM_MODE_RGB)) {
-			/* receiving HDMI or analog signal */
-			io_write_and_or(sd, 0x02, 0x0f, 0xf0);
-		} else {
+		if (DIGITAL_INPUT && !(hdmi_read(sd, 0x05) & 0x80)) {
 			/* receiving DVI-D signal */
 
 			/* ADV7604 selects RGB limited range regardless of
@@ -756,6 +924,9 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 				/* RGB full range (0-255) */
 				io_write_and_or(sd, 0x02, 0x0f, 0x10);
 			}
+		} else {
+			/* receiving HDMI or analog signal, set automode */
+			io_write_and_or(sd, 0x02, 0x0f, 0xf0);
 		}
 		break;
 	case V4L2_DV_RGB_RANGE_LIMITED:
@@ -967,8 +1138,10 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
 			state->aspect_ratio, timings))
 		return 0;
 
-	v4l2_dbg(2, debug, sd, "%s: No format candidate found for lcf=%d, bl = %d\n",
-			__func__, stdi->lcf, stdi->bl);
+	v4l2_dbg(2, debug, sd,
+		"%s: No format candidate found for lcvs = %d, lcf=%d, bl = %d, %chsync, %cvsync\n",
+		__func__, stdi->lcvs, stdi->lcf, stdi->bl,
+		stdi->hs_pol, stdi->vs_pol);
 	return -1;
 }
 
@@ -1123,7 +1296,7 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
 		adv7604_fill_optional_dv_timings_fields(sd, timings);
 	} else {
 		/* find format
-		 * Since LCVS values are inaccurate (REF_03, page 275-276),
+		 * Since LCVS values are inaccurate [REF_03, p. 275-276],
 		 * stdi2dv_timings() is called with lcvs +-1 if the first attempt fails.
 		 */
 		if (!stdi2dv_timings(sd, &stdi, timings))
@@ -1135,9 +1308,31 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
 		stdi.lcvs -= 2;
 		v4l2_dbg(1, debug, sd, "%s: lcvs - 1 = %d\n", __func__, stdi.lcvs);
 		if (stdi2dv_timings(sd, &stdi, timings)) {
+			/*
+			 * The STDI block may measure wrong values, especially
+			 * for lcvs and lcf. If the driver can not find any
+			 * valid timing, the STDI block is restarted to measure
+			 * the video timings again. The function will return an
+			 * error, but the restart of STDI will generate a new
+			 * STDI interrupt and the format detection process will
+			 * restart.
+			 */
+			if (state->restart_stdi_once) {
+				v4l2_dbg(1, debug, sd, "%s: restart STDI\n", __func__);
+				/* TODO restart STDI for Sync Channel 2 */
+				/* enter one-shot mode */
+				cp_write_and_or(sd, 0x86, 0xf9, 0x00);
+				/* trigger STDI restart */
+				cp_write_and_or(sd, 0x86, 0xf9, 0x04);
+				/* reset to continuous mode */
+				cp_write_and_or(sd, 0x86, 0xf9, 0x02);
+				state->restart_stdi_once = false;
+				return -ENOLINK;
+			}
 			v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__);
 			return -ERANGE;
 		}
+		state->restart_stdi_once = true;
 	}
 found:
 
@@ -1166,6 +1361,7 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
 {
 	struct adv7604_state *state = to_state(sd);
 	struct v4l2_bt_timings *bt;
+	int err;
 
 	if (!timings)
 		return -EINVAL;
@@ -1178,12 +1374,20 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
 				__func__, (u32)bt->pixelclock);
 		return -ERANGE;
 	}
+
 	adv7604_fill_optional_dv_timings_fields(sd, timings);
 
 	state->timings = *timings;
 
-	/* freerun */
-	configure_free_run(sd, bt);
+	cp_write(sd, 0x91, bt->interlaced ? 0x50 : 0x10);
+
+	/* Use prim_mode and vid_std when available */
+	err = configure_predefined_video_timings(sd, timings);
+	if (err) {
+		/* custom settings when the video format
+		 does not have prim_mode/vid_std */
+		configure_custom_video_timings(sd, bt);
+	}
 
 	set_rgb_quantization_range(sd);
 
@@ -1203,24 +1407,25 @@ static int adv7604_g_dv_timings(struct v4l2_subdev *sd,
 	return 0;
 }
 
-static void enable_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode)
+static void enable_input(struct v4l2_subdev *sd)
 {
-	switch (prim_mode) {
-	case ADV7604_PRIM_MODE_COMP:
-	case ADV7604_PRIM_MODE_RGB:
+	struct adv7604_state *state = to_state(sd);
+
+	switch (state->mode) {
+	case ADV7604_MODE_COMP:
+	case ADV7604_MODE_GR:
 		/* enable */
 		io_write(sd, 0x15, 0xb0);   /* Disable Tristate of Pins (no audio) */
 		break;
-	case ADV7604_PRIM_MODE_HDMI_COMP:
-	case ADV7604_PRIM_MODE_HDMI_GR:
+	case ADV7604_MODE_HDMI:
 		/* enable */
 		hdmi_write(sd, 0x1a, 0x0a); /* Unmute audio */
 		hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */
 		io_write(sd, 0x15, 0xa0);   /* Disable Tristate of Pins */
 		break;
 	default:
-		v4l2_err(sd, "%s: reserved primary mode 0x%0x\n",
-				__func__, prim_mode);
+		v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
+				__func__, state->mode);
 		break;
 	}
 }
@@ -1233,17 +1438,13 @@ static void disable_input(struct v4l2_subdev *sd)
 	hdmi_write(sd, 0x01, 0x78); /* Disable HDMI clock terminators */
 }
 
-static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode)
+static void select_input(struct v4l2_subdev *sd)
 {
-	switch (prim_mode) {
-	case ADV7604_PRIM_MODE_COMP:
-	case ADV7604_PRIM_MODE_RGB:
-		/* set mode and select free run resolution */
-		io_write(sd, 0x00, 0x07); /* video std */
-		io_write(sd, 0x01, 0x02); /* prim mode */
-		/* enable embedded syncs for auto graphics mode */
-		cp_write_and_or(sd, 0x81, 0xef, 0x10);
+	struct adv7604_state *state = to_state(sd);
 
+	switch (state->mode) {
+	case ADV7604_MODE_COMP:
+	case ADV7604_MODE_GR:
 		/* reset ADI recommended settings for HDMI: */
 		/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
 		hdmi_write(sd, 0x0d, 0x04); /* HDMI filter optimization */
@@ -1271,16 +1472,7 @@ static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mod
 		cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */
 		break;
 
-	case ADV7604_PRIM_MODE_HDMI_COMP:
-	case ADV7604_PRIM_MODE_HDMI_GR:
-		/* set mode and select free run resolution */
-		/* video std */
-		io_write(sd, 0x00,
-			(prim_mode == ADV7604_PRIM_MODE_HDMI_GR) ? 0x02 : 0x1e);
-		io_write(sd, 0x01, prim_mode); /* prim mode */
-		/* disable embedded syncs for auto graphics mode */
-		cp_write_and_or(sd, 0x81, 0xef, 0x00);
-
+	case ADV7604_MODE_HDMI:
 		/* set ADI recommended settings for HDMI: */
 		/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
 		hdmi_write(sd, 0x0d, 0x84); /* HDMI filter optimization */
@@ -1309,7 +1501,8 @@ static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mod
 
 		break;
 	default:
-		v4l2_err(sd, "%s: reserved primary mode 0x%0x\n", __func__, prim_mode);
+		v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
+				__func__, state->mode);
 		break;
 	}
 }
@@ -1321,26 +1514,13 @@ static int adv7604_s_routing(struct v4l2_subdev *sd,
 
 	v4l2_dbg(2, debug, sd, "%s: input %d", __func__, input);
 
-	switch (input) {
-	case 0:
-		/* TODO select HDMI_COMP or HDMI_GR */
-		state->prim_mode = ADV7604_PRIM_MODE_HDMI_COMP;
-		break;
-	case 1:
-		state->prim_mode = ADV7604_PRIM_MODE_RGB;
-		break;
-	case 2:
-		state->prim_mode = ADV7604_PRIM_MODE_COMP;
-		break;
-	default:
-		return -EINVAL;
-	}
+	state->mode = input;
 
 	disable_input(sd);
 
-	select_input(sd, state->prim_mode);
+	select_input(sd);
 
-	enable_input(sd, state->prim_mode);
+	enable_input(sd);
 
 	return 0;
 }
@@ -1549,8 +1729,9 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
 	v4l2_info(sd, "CP locked: %s\n", no_lock_cp(sd) ? "false" : "true");
 	v4l2_info(sd, "CP free run: %s\n",
 			(!!(cp_read(sd, 0xff) & 0x10) ? "on" : "off"));
-	v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x\n",
-			io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f);
+	v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x, v_freq = 0x%x\n",
+			io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f,
+			(io_read(sd, 0x01) & 0x70) >> 4);
 
 	v4l2_info(sd, "-----Video Timings-----\n");
 	if (read_stdi(sd, &stdi))
@@ -1712,9 +1893,9 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
 	cp_write(sd, 0xba, (pdata->hdmi_free_run_mode << 1) | 0x01); /* HDMI free run */
 	cp_write(sd, 0xf3, 0xdc); /* Low threshold to enter/exit free run mode */
 	cp_write(sd, 0xf9, 0x23); /*  STDI ch. 1 - LCVS change threshold -
-				      ADI recommended setting [REF_01 c. 2.3.3] */
+				      ADI recommended setting [REF_01, c. 2.3.3] */
 	cp_write(sd, 0x45, 0x23); /*  STDI ch. 2 - LCVS change threshold -
-				      ADI recommended setting [REF_01 c. 2.3.3] */
+				      ADI recommended setting [REF_01, c. 2.3.3] */
 	cp_write(sd, 0xc9, 0x2d); /* use prim_mode and vid_std as free run resolution
 				     for digital formats */
 
@@ -1724,11 +1905,6 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
 	afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */
 	io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4);
 
-	state->prim_mode = pdata->prim_mode;
-	select_input(sd, pdata->prim_mode);
-
-	enable_input(sd, pdata->prim_mode);
-
 	/* interrupts */
 	io_write(sd, 0x40, 0xc2); /* Configure INT1 */
 	io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */
@@ -1883,6 +2059,7 @@ static int adv7604_probe(struct i2c_client *client,
 		v4l2_err(sd, "failed to create all i2c clients\n");
 		goto err_i2c;
 	}
+	state->restart_stdi_once = true;
 
 	/* work queues */
 	state->work_queues = create_singlethread_workqueue(client->name);
diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c
index 2cee69e..f4149eb 100644
--- a/drivers/media/i2c/cx25840/cx25840-core.c
+++ b/drivers/media/i2c/cx25840/cx25840-core.c
@@ -2065,7 +2065,7 @@ static int cx25840_irq_handler(struct v4l2_subdev *sd, u32 status,
 #define DIF_BPF_COEFF3435	(0x38c)
 #define DIF_BPF_COEFF36		(0x390)
 
-void cx23885_dif_setup(struct i2c_client *client, u32 ifHz)
+static void cx23885_dif_setup(struct i2c_client *client, u32 ifHz)
 {
 	u64 pll_freq;
 	u32 pll_freq_word;
diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 04f192a..08ae067 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -284,7 +284,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	char *ir_codes = NULL;
 	const char *name = NULL;
-	u64 rc_type = RC_TYPE_UNKNOWN;
+	u64 rc_type = RC_BIT_UNKNOWN;
 	struct IR_i2c *ir;
 	struct rc_dev *rc = NULL;
 	struct i2c_adapter *adap = client->adapter;
@@ -303,7 +303,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	case 0x64:
 		name        = "Pixelview";
 		ir->get_key = get_key_pixelview;
-		rc_type     = RC_TYPE_OTHER;
+		rc_type     = RC_BIT_OTHER;
 		ir_codes    = RC_MAP_EMPTY;
 		break;
 	case 0x18:
@@ -311,31 +311,31 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	case 0x1a:
 		name        = "Hauppauge";
 		ir->get_key = get_key_haup;
-		rc_type     = RC_TYPE_RC5;
+		rc_type     = RC_BIT_RC5;
 		ir_codes    = RC_MAP_HAUPPAUGE;
 		break;
 	case 0x30:
 		name        = "KNC One";
 		ir->get_key = get_key_knc1;
-		rc_type     = RC_TYPE_OTHER;
+		rc_type     = RC_BIT_OTHER;
 		ir_codes    = RC_MAP_EMPTY;
 		break;
 	case 0x6b:
 		name        = "FusionHDTV";
 		ir->get_key = get_key_fusionhdtv;
-		rc_type     = RC_TYPE_RC5;
+		rc_type     = RC_BIT_RC5;
 		ir_codes    = RC_MAP_FUSIONHDTV_MCE;
 		break;
 	case 0x40:
 		name        = "AVerMedia Cardbus remote";
 		ir->get_key = get_key_avermedia_cardbus;
-		rc_type     = RC_TYPE_OTHER;
+		rc_type     = RC_BIT_OTHER;
 		ir_codes    = RC_MAP_AVERMEDIA_CARDBUS;
 		break;
 	case 0x71:
 		name        = "Hauppauge/Zilog Z8";
 		ir->get_key = get_key_haup_xvr;
-		rc_type     = RC_TYPE_RC5;
+		rc_type     = RC_BIT_RC5;
 		ir_codes    = RC_MAP_HAUPPAUGE;
 		break;
 	}
diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c
index 49c1b3a..2750de6 100644
--- a/drivers/media/i2c/s5k4ecgx.c
+++ b/drivers/media/i2c/s5k4ecgx.c
@@ -343,7 +343,7 @@ static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd)
 	}
 	regs_num = le32_to_cpu(get_unaligned_le32(fw->data));
 
-	v4l2_dbg(3, debug, sd, "FW: %s size %d register sets %d\n",
+	v4l2_dbg(3, debug, sd, "FW: %s size %zu register sets %d\n",
 		 S5K4ECGX_FIRMWARE, fw->size, regs_num);
 
 	regs_num++; /* Add header */
diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c
index a577614..d8d5da7 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -58,7 +58,7 @@ static int bounds_check(struct device *dev, uint32_t val,
 	if (val >= min && val <= max)
 		return 0;
 
-	dev_warn(dev, "%s out of bounds: %d (%d--%d)\n", str, val, min, max);
+	dev_dbg(dev, "%s out of bounds: %d (%d--%d)\n", str, val, min, max);
 
 	return -EINVAL;
 }
@@ -87,14 +87,14 @@ static void print_pll(struct device *dev, struct smiapp_pll *pll)
 	dev_dbg(dev, "vt_pix_clk_freq_hz \t%d\n", pll->vt_pix_clk_freq_hz);
 }
 
-int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
-			 struct smiapp_pll *pll)
+static int __smiapp_pll_calculate(struct device *dev,
+				  const struct smiapp_pll_limits *limits,
+				  struct smiapp_pll *pll, uint32_t mul,
+				  uint32_t div, uint32_t lane_op_clock_ratio)
 {
 	uint32_t sys_div;
 	uint32_t best_pix_div = INT_MAX >> 1;
 	uint32_t vt_op_binning_div;
-	uint32_t lane_op_clock_ratio;
-	uint32_t mul, div;
 	uint32_t more_mul_min, more_mul_max;
 	uint32_t more_mul_factor;
 	uint32_t min_vt_div, max_vt_div, vt_div;
@@ -102,54 +102,6 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
 	unsigned int i;
 	int rval;
 
-	if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE)
-		lane_op_clock_ratio = pll->lanes;
-	else
-		lane_op_clock_ratio = 1;
-	dev_dbg(dev, "lane_op_clock_ratio: %d\n", lane_op_clock_ratio);
-
-	dev_dbg(dev, "binning: %dx%d\n", pll->binning_horizontal,
-		pll->binning_vertical);
-
-	/* CSI transfers 2 bits per clock per lane; thus times 2 */
-	pll->pll_op_clk_freq_hz = pll->link_freq * 2
-		* (pll->lanes / lane_op_clock_ratio);
-
-	/* Figure out limits for pre-pll divider based on extclk */
-	dev_dbg(dev, "min / max pre_pll_clk_div: %d / %d\n",
-		limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
-	limits->max_pre_pll_clk_div =
-		min_t(uint16_t, limits->max_pre_pll_clk_div,
-		      clk_div_even(pll->ext_clk_freq_hz /
-				   limits->min_pll_ip_freq_hz));
-	limits->min_pre_pll_clk_div =
-		max_t(uint16_t, limits->min_pre_pll_clk_div,
-		      clk_div_even_up(
-			      DIV_ROUND_UP(pll->ext_clk_freq_hz,
-					   limits->max_pll_ip_freq_hz)));
-	dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %d / %d\n",
-		limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
-
-	i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz);
-	mul = div_u64(pll->pll_op_clk_freq_hz, i);
-	div = pll->ext_clk_freq_hz / i;
-	dev_dbg(dev, "mul %d / div %d\n", mul, div);
-
-	limits->min_pre_pll_clk_div =
-		max_t(uint16_t, limits->min_pre_pll_clk_div,
-		      clk_div_even_up(
-			      DIV_ROUND_UP(mul * pll->ext_clk_freq_hz,
-					   limits->max_pll_op_freq_hz)));
-	dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %d / %d\n",
-		limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
-
-	if (limits->min_pre_pll_clk_div > limits->max_pre_pll_clk_div) {
-		dev_err(dev, "unable to compute pre_pll divisor\n");
-		return -EINVAL;
-	}
-
-	pll->pre_pll_clk_div = limits->min_pre_pll_clk_div;
-
 	/*
 	 * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be
 	 * too high.
@@ -162,7 +114,7 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
 		more_mul_max);
 	/* Don't go above max pll op frequency. */
 	more_mul_max =
-		min_t(int,
+		min_t(uint32_t,
 		      more_mul_max,
 		      limits->max_pll_op_freq_hz
 		      / (pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul));
@@ -170,7 +122,7 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
 		more_mul_max);
 	/* Don't go above the division capability of op sys clock divider. */
 	more_mul_max = min(more_mul_max,
-			   limits->max_op_sys_clk_div * pll->pre_pll_clk_div
+			   limits->op.max_sys_clk_div * pll->pre_pll_clk_div
 			   / div);
 	dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %d\n",
 		more_mul_max);
@@ -193,14 +145,14 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
 		more_mul_min);
 
 	if (more_mul_min > more_mul_max) {
-		dev_warn(dev,
-			 "unable to compute more_mul_min and more_mul_max");
+		dev_dbg(dev,
+			"unable to compute more_mul_min and more_mul_max\n");
 		return -EINVAL;
 	}
 
 	more_mul_factor = lcm(div, pll->pre_pll_clk_div) / div;
 	dev_dbg(dev, "more_mul_factor: %d\n", more_mul_factor);
-	more_mul_factor = lcm(more_mul_factor, limits->min_op_sys_clk_div);
+	more_mul_factor = lcm(more_mul_factor, limits->op.min_sys_clk_div);
 	dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %d\n",
 		more_mul_factor);
 	i = roundup(more_mul_min, more_mul_factor);
@@ -209,7 +161,7 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
 
 	dev_dbg(dev, "final more_mul: %d\n", i);
 	if (i > more_mul_max) {
-		dev_warn(dev, "final more_mul is bad, max %d", more_mul_max);
+		dev_dbg(dev, "final more_mul is bad, max %d\n", more_mul_max);
 		return -EINVAL;
 	}
 
@@ -268,19 +220,19 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
 	dev_dbg(dev, "min_vt_div: %d\n", min_vt_div);
 	min_vt_div = max(min_vt_div,
 			 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
-				      limits->max_vt_pix_clk_freq_hz));
+				      limits->vt.max_pix_clk_freq_hz));
 	dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %d\n",
 		min_vt_div);
 	min_vt_div = max_t(uint32_t, min_vt_div,
-			   limits->min_vt_pix_clk_div
-			   * limits->min_vt_sys_clk_div);
+			   limits->vt.min_pix_clk_div
+			   * limits->vt.min_sys_clk_div);
 	dev_dbg(dev, "min_vt_div: min_vt_clk_div: %d\n", min_vt_div);
 
-	max_vt_div = limits->max_vt_sys_clk_div * limits->max_vt_pix_clk_div;
+	max_vt_div = limits->vt.max_sys_clk_div * limits->vt.max_pix_clk_div;
 	dev_dbg(dev, "max_vt_div: %d\n", max_vt_div);
 	max_vt_div = min(max_vt_div,
 			 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
-				      limits->min_vt_pix_clk_freq_hz));
+				      limits->vt.min_pix_clk_freq_hz));
 	dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %d\n",
 		max_vt_div);
 
@@ -288,28 +240,28 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
 	 * Find limitsits for sys_clk_div. Not all values are possible
 	 * with all values of pix_clk_div.
 	 */
-	min_sys_div = limits->min_vt_sys_clk_div;
+	min_sys_div = limits->vt.min_sys_clk_div;
 	dev_dbg(dev, "min_sys_div: %d\n", min_sys_div);
 	min_sys_div = max(min_sys_div,
 			  DIV_ROUND_UP(min_vt_div,
-				       limits->max_vt_pix_clk_div));
+				       limits->vt.max_pix_clk_div));
 	dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %d\n", min_sys_div);
 	min_sys_div = max(min_sys_div,
 			  pll->pll_op_clk_freq_hz
-			  / limits->max_vt_sys_clk_freq_hz);
+			  / limits->vt.max_sys_clk_freq_hz);
 	dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %d\n", min_sys_div);
 	min_sys_div = clk_div_even_up(min_sys_div);
 	dev_dbg(dev, "min_sys_div: one or even: %d\n", min_sys_div);
 
-	max_sys_div = limits->max_vt_sys_clk_div;
+	max_sys_div = limits->vt.max_sys_clk_div;
 	dev_dbg(dev, "max_sys_div: %d\n", max_sys_div);
 	max_sys_div = min(max_sys_div,
 			  DIV_ROUND_UP(max_vt_div,
-				       limits->min_vt_pix_clk_div));
+				       limits->vt.min_pix_clk_div));
 	dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %d\n", max_sys_div);
 	max_sys_div = min(max_sys_div,
 			  DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
-				       limits->min_vt_pix_clk_freq_hz));
+				       limits->vt.min_pix_clk_freq_hz));
 	dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %d\n", max_sys_div);
 
 	/*
@@ -322,15 +274,15 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
 		for (sys_div = min_sys_div;
 		     sys_div <= max_sys_div;
 		     sys_div += 2 - (sys_div & 1)) {
-			int pix_div = DIV_ROUND_UP(vt_div, sys_div);
+			uint16_t pix_div = DIV_ROUND_UP(vt_div, sys_div);
 
-			if (pix_div < limits->min_vt_pix_clk_div
-			    || pix_div > limits->max_vt_pix_clk_div) {
+			if (pix_div < limits->vt.min_pix_clk_div
+			    || pix_div > limits->vt.max_pix_clk_div) {
 				dev_dbg(dev,
 					"pix_div %d too small or too big (%d--%d)\n",
 					pix_div,
-					limits->min_vt_pix_clk_div,
-					limits->max_vt_pix_clk_div);
+					limits->vt.min_pix_clk_div,
+					limits->vt.max_pix_clk_div);
 				continue;
 			}
 
@@ -354,16 +306,10 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
 	pll->pixel_rate_csi =
 		pll->op_pix_clk_freq_hz * lane_op_clock_ratio;
 
-	print_pll(dev, pll);
-
-	rval = bounds_check(dev, pll->pre_pll_clk_div,
-			    limits->min_pre_pll_clk_div,
-			    limits->max_pre_pll_clk_div, "pre_pll_clk_div");
-	if (!rval)
-		rval = bounds_check(
-			dev, pll->pll_ip_clk_freq_hz,
-			limits->min_pll_ip_freq_hz, limits->max_pll_ip_freq_hz,
-			"pll_ip_clk_freq_hz");
+	rval = bounds_check(dev, pll->pll_ip_clk_freq_hz,
+			    limits->min_pll_ip_freq_hz,
+			    limits->max_pll_ip_freq_hz,
+			    "pll_ip_clk_freq_hz");
 	if (!rval)
 		rval = bounds_check(
 			dev, pll->pll_multiplier,
@@ -377,42 +323,121 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
 	if (!rval)
 		rval = bounds_check(
 			dev, pll->op_sys_clk_div,
-			limits->min_op_sys_clk_div, limits->max_op_sys_clk_div,
+			limits->op.min_sys_clk_div, limits->op.max_sys_clk_div,
 			"op_sys_clk_div");
 	if (!rval)
 		rval = bounds_check(
 			dev, pll->op_pix_clk_div,
-			limits->min_op_pix_clk_div, limits->max_op_pix_clk_div,
+			limits->op.min_pix_clk_div, limits->op.max_pix_clk_div,
 			"op_pix_clk_div");
 	if (!rval)
 		rval = bounds_check(
 			dev, pll->op_sys_clk_freq_hz,
-			limits->min_op_sys_clk_freq_hz,
-			limits->max_op_sys_clk_freq_hz,
+			limits->op.min_sys_clk_freq_hz,
+			limits->op.max_sys_clk_freq_hz,
 			"op_sys_clk_freq_hz");
 	if (!rval)
 		rval = bounds_check(
 			dev, pll->op_pix_clk_freq_hz,
-			limits->min_op_pix_clk_freq_hz,
-			limits->max_op_pix_clk_freq_hz,
+			limits->op.min_pix_clk_freq_hz,
+			limits->op.max_pix_clk_freq_hz,
 			"op_pix_clk_freq_hz");
 	if (!rval)
 		rval = bounds_check(
 			dev, pll->vt_sys_clk_freq_hz,
-			limits->min_vt_sys_clk_freq_hz,
-			limits->max_vt_sys_clk_freq_hz,
+			limits->vt.min_sys_clk_freq_hz,
+			limits->vt.max_sys_clk_freq_hz,
 			"vt_sys_clk_freq_hz");
 	if (!rval)
 		rval = bounds_check(
 			dev, pll->vt_pix_clk_freq_hz,
-			limits->min_vt_pix_clk_freq_hz,
-			limits->max_vt_pix_clk_freq_hz,
+			limits->vt.min_pix_clk_freq_hz,
+			limits->vt.max_pix_clk_freq_hz,
 			"vt_pix_clk_freq_hz");
 
 	return rval;
 }
+
+int smiapp_pll_calculate(struct device *dev,
+			 const struct smiapp_pll_limits *limits,
+			 struct smiapp_pll *pll)
+{
+	uint16_t min_pre_pll_clk_div;
+	uint16_t max_pre_pll_clk_div;
+	uint32_t lane_op_clock_ratio;
+	uint32_t mul, div;
+	unsigned int i;
+	int rval = -EINVAL;
+
+	if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE)
+		lane_op_clock_ratio = pll->csi2.lanes;
+	else
+		lane_op_clock_ratio = 1;
+	dev_dbg(dev, "lane_op_clock_ratio: %d\n", lane_op_clock_ratio);
+
+	dev_dbg(dev, "binning: %dx%d\n", pll->binning_horizontal,
+		pll->binning_vertical);
+
+	switch (pll->bus_type) {
+	case SMIAPP_PLL_BUS_TYPE_CSI2:
+		/* CSI transfers 2 bits per clock per lane; thus times 2 */
+		pll->pll_op_clk_freq_hz = pll->link_freq * 2
+			* (pll->csi2.lanes / lane_op_clock_ratio);
+		break;
+	case SMIAPP_PLL_BUS_TYPE_PARALLEL:
+		pll->pll_op_clk_freq_hz = pll->link_freq * pll->bits_per_pixel
+			/ DIV_ROUND_UP(pll->bits_per_pixel,
+				       pll->parallel.bus_width);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Figure out limits for pre-pll divider based on extclk */
+	dev_dbg(dev, "min / max pre_pll_clk_div: %d / %d\n",
+		limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
+	max_pre_pll_clk_div =
+		min_t(uint16_t, limits->max_pre_pll_clk_div,
+		      clk_div_even(pll->ext_clk_freq_hz /
+				   limits->min_pll_ip_freq_hz));
+	min_pre_pll_clk_div =
+		max_t(uint16_t, limits->min_pre_pll_clk_div,
+		      clk_div_even_up(
+			      DIV_ROUND_UP(pll->ext_clk_freq_hz,
+					   limits->max_pll_ip_freq_hz)));
+	dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %d / %d\n",
+		min_pre_pll_clk_div, max_pre_pll_clk_div);
+
+	i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz);
+	mul = div_u64(pll->pll_op_clk_freq_hz, i);
+	div = pll->ext_clk_freq_hz / i;
+	dev_dbg(dev, "mul %d / div %d\n", mul, div);
+
+	min_pre_pll_clk_div =
+		max_t(uint16_t, min_pre_pll_clk_div,
+		      clk_div_even_up(
+			      DIV_ROUND_UP(mul * pll->ext_clk_freq_hz,
+					   limits->max_pll_op_freq_hz)));
+	dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %d / %d\n",
+		min_pre_pll_clk_div, max_pre_pll_clk_div);
+
+	for (pll->pre_pll_clk_div = min_pre_pll_clk_div;
+	     pll->pre_pll_clk_div <= max_pre_pll_clk_div;
+	     pll->pre_pll_clk_div += 2 - (pll->pre_pll_clk_div & 1)) {
+		rval = __smiapp_pll_calculate(dev, limits, pll, mul, div,
+					      lane_op_clock_ratio);
+		if (rval)
+			continue;
+
+		print_pll(dev, pll);
+		return 0;
+	}
+
+	dev_info(dev, "unable to compute pre_pll divisor\n");
+	return rval;
+}
 EXPORT_SYMBOL_GPL(smiapp_pll_calculate);
 
-MODULE_AUTHOR("Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>");
+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@iki.fi>");
 MODULE_DESCRIPTION("Generic SMIA/SMIA++ PLL calculator");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/smiapp-pll.h b/drivers/media/i2c/smiapp-pll.h
index cb2d2db..a4a6498 100644
--- a/drivers/media/i2c/smiapp-pll.h
+++ b/drivers/media/i2c/smiapp-pll.h
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -27,16 +27,34 @@
 
 #include <linux/device.h>
 
+/* CSI-2 or CCP-2 */
+#define SMIAPP_PLL_BUS_TYPE_CSI2				0x00
+#define SMIAPP_PLL_BUS_TYPE_PARALLEL				0x01
+
+/* op pix clock is for all lanes in total normally */
+#define SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE			(1 << 0)
+#define SMIAPP_PLL_FLAG_NO_OP_CLOCKS				(1 << 1)
+
 struct smiapp_pll {
-	uint8_t lanes;
+	/* input values */
+	uint8_t bus_type;
+	union {
+		struct {
+			uint8_t lanes;
+		} csi2;
+		struct {
+			uint8_t bus_width;
+		} parallel;
+	};
+	uint8_t flags;
 	uint8_t binning_horizontal;
 	uint8_t binning_vertical;
 	uint8_t scale_m;
 	uint8_t scale_n;
 	uint8_t bits_per_pixel;
-	uint16_t flags;
 	uint32_t link_freq;
 
+	/* output values */
 	uint16_t pre_pll_clk_div;
 	uint16_t pll_multiplier;
 	uint16_t op_sys_clk_div;
@@ -55,6 +73,17 @@ struct smiapp_pll {
 	uint32_t pixel_rate_csi;
 };
 
+struct smiapp_pll_branch_limits {
+	uint16_t min_sys_clk_div;
+	uint16_t max_sys_clk_div;
+	uint32_t min_sys_clk_freq_hz;
+	uint32_t max_sys_clk_freq_hz;
+	uint16_t min_pix_clk_div;
+	uint16_t max_pix_clk_div;
+	uint32_t min_pix_clk_freq_hz;
+	uint32_t max_pix_clk_freq_hz;
+};
+
 struct smiapp_pll_limits {
 	/* Strict PLL limits */
 	uint32_t min_ext_clk_freq_hz;
@@ -68,36 +97,18 @@ struct smiapp_pll_limits {
 	uint32_t min_pll_op_freq_hz;
 	uint32_t max_pll_op_freq_hz;
 
-	uint16_t min_vt_sys_clk_div;
-	uint16_t max_vt_sys_clk_div;
-	uint32_t min_vt_sys_clk_freq_hz;
-	uint32_t max_vt_sys_clk_freq_hz;
-	uint16_t min_vt_pix_clk_div;
-	uint16_t max_vt_pix_clk_div;
-	uint32_t min_vt_pix_clk_freq_hz;
-	uint32_t max_vt_pix_clk_freq_hz;
-
-	uint16_t min_op_sys_clk_div;
-	uint16_t max_op_sys_clk_div;
-	uint32_t min_op_sys_clk_freq_hz;
-	uint32_t max_op_sys_clk_freq_hz;
-	uint16_t min_op_pix_clk_div;
-	uint16_t max_op_pix_clk_div;
-	uint32_t min_op_pix_clk_freq_hz;
-	uint32_t max_op_pix_clk_freq_hz;
+	struct smiapp_pll_branch_limits vt;
+	struct smiapp_pll_branch_limits op;
 
 	/* Other relevant limits */
 	uint32_t min_line_length_pck_bin;
 	uint32_t min_line_length_pck;
 };
 
-/* op pix clock is for all lanes in total normally */
-#define SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE			(1 << 0)
-#define SMIAPP_PLL_FLAG_NO_OP_CLOCKS				(1 << 1)
-
 struct device;
 
-int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
+int smiapp_pll_calculate(struct device *dev,
+			 const struct smiapp_pll_limits *limits,
 			 struct smiapp_pll *pll);
 
 #endif /* SMIAPP_PLL_H */
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index e08e588..83c7ed7 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2010--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * Based on smiapp driver by Vimarsh Zutshi
  * Based on jt8ev1.c by Vimarsh Zutshi
@@ -252,23 +252,23 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
 		.min_pll_op_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_PLL_OP_FREQ_HZ],
 		.max_pll_op_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_PLL_OP_FREQ_HZ],
 
-		.min_op_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV],
-		.max_op_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV],
-		.min_op_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_DIV],
-		.max_op_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_DIV],
-		.min_op_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_FREQ_HZ],
-		.max_op_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_FREQ_HZ],
-		.min_op_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_FREQ_HZ],
-		.max_op_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_FREQ_HZ],
-
-		.min_vt_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_VT_SYS_CLK_DIV],
-		.max_vt_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_VT_SYS_CLK_DIV],
-		.min_vt_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_VT_PIX_CLK_DIV],
-		.max_vt_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_VT_PIX_CLK_DIV],
-		.min_vt_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_VT_SYS_CLK_FREQ_HZ],
-		.max_vt_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_VT_SYS_CLK_FREQ_HZ],
-		.min_vt_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_VT_PIX_CLK_FREQ_HZ],
-		.max_vt_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_VT_PIX_CLK_FREQ_HZ],
+		.op.min_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV],
+		.op.max_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV],
+		.op.min_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_DIV],
+		.op.max_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_DIV],
+		.op.min_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_FREQ_HZ],
+		.op.max_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_FREQ_HZ],
+		.op.min_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_FREQ_HZ],
+		.op.max_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_FREQ_HZ],
+
+		.vt.min_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_VT_SYS_CLK_DIV],
+		.vt.max_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_VT_SYS_CLK_DIV],
+		.vt.min_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_VT_PIX_CLK_DIV],
+		.vt.max_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_VT_PIX_CLK_DIV],
+		.vt.min_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_VT_SYS_CLK_FREQ_HZ],
+		.vt.max_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_VT_SYS_CLK_FREQ_HZ],
+		.vt.min_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_VT_PIX_CLK_FREQ_HZ],
+		.vt.max_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_VT_PIX_CLK_FREQ_HZ],
 
 		.min_line_length_pck_bin = sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN],
 		.min_line_length_pck = sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK],
@@ -276,11 +276,6 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
 	struct smiapp_pll *pll = &sensor->pll;
 	int rval;
 
-	memset(&sensor->pll, 0, sizeof(sensor->pll));
-
-	pll->lanes = sensor->platform_data->lanes;
-	pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
-
 	if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) {
 		/*
 		 * Fill in operational clock divisors limits from the
@@ -288,28 +283,14 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
 		 * requirements regarding them are essentially the
 		 * same as on VT ones.
 		 */
-		lim.min_op_sys_clk_div = lim.min_vt_sys_clk_div;
-		lim.max_op_sys_clk_div = lim.max_vt_sys_clk_div;
-		lim.min_op_pix_clk_div = lim.min_vt_pix_clk_div;
-		lim.max_op_pix_clk_div = lim.max_vt_pix_clk_div;
-		lim.min_op_sys_clk_freq_hz = lim.min_vt_sys_clk_freq_hz;
-		lim.max_op_sys_clk_freq_hz = lim.max_vt_sys_clk_freq_hz;
-		lim.min_op_pix_clk_freq_hz = lim.min_vt_pix_clk_freq_hz;
-		lim.max_op_pix_clk_freq_hz = lim.max_vt_pix_clk_freq_hz;
-		/* Profile 0 sensors have no separate OP clock branch. */
-		pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
+		lim.op = lim.vt;
 	}
 
-	if (smiapp_needs_quirk(sensor,
-			       SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE))
-		pll->flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
-
 	pll->binning_horizontal = sensor->binning_horizontal;
 	pll->binning_vertical = sensor->binning_vertical;
 	pll->link_freq =
 		sensor->link_freq->qmenu_int[sensor->link_freq->val];
 	pll->scale_m = sensor->scale_m;
-	pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
 	pll->bits_per_pixel = sensor->csi_format->compressed;
 
 	rval = smiapp_pll_calculate(&client->dev, &lim, pll);
@@ -1010,7 +991,7 @@ static int smiapp_setup_flash_strobe(struct smiapp_sensor *sensor)
 	 * do not change, or if you do at least know what you're
 	 * doing. :-)
 	 *
-	 * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 2010-10-25
+	 * Sakari Ailus <sakari.ailus@iki.fi> 2010-10-25
 	 *
 	 * flash_strobe_length [us] / 10^6 = (tFlash_strobe_width_ctrl
 	 *	/ EXTCLK freq [Hz]) * flash_strobe_adjustment
@@ -2369,6 +2350,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
 {
 	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
 	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	struct smiapp_pll *pll = &sensor->pll;
 	struct smiapp_subdev *last = NULL;
 	u32 tmp;
 	unsigned int i;
@@ -2635,6 +2617,18 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
 	if (rval < 0)
 		goto out_nvm_release;
 
+	/* prepare PLL configuration input values */
+	pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
+	pll->csi2.lanes = sensor->platform_data->lanes;
+	pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
+	/* Profile 0 sensors have no separate OP clock branch. */
+	if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
+		pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
+	if (smiapp_needs_quirk(sensor,
+			       SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE))
+		pll->flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
+	pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
+
 	rval = smiapp_update_mode(sensor);
 	if (rval) {
 		dev_err(&client->dev, "update mode failed\n");
@@ -2893,6 +2887,6 @@ static struct i2c_driver smiapp_i2c_driver = {
 
 module_i2c_driver(smiapp_i2c_driver);
 
-MODULE_AUTHOR("Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>");
+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@iki.fi>");
 MODULE_DESCRIPTION("Generic SMIA/SMIA++ camera module driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/smiapp/smiapp-limits.c b/drivers/media/i2c/smiapp/smiapp-limits.c
index fb2f81a..847cb23 100644
--- a/drivers/media/i2c/smiapp/smiapp-limits.c
+++ b/drivers/media/i2c/smiapp/smiapp-limits.c
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/smiapp/smiapp-limits.h b/drivers/media/i2c/smiapp/smiapp-limits.h
index 9ae765e..343e9c3 100644
--- a/drivers/media/i2c/smiapp/smiapp-limits.h
+++ b/drivers/media/i2c/smiapp/smiapp-limits.h
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.c b/drivers/media/i2c/smiapp/smiapp-quirk.c
index 725cf62..bb8c506 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.c
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.c
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.h b/drivers/media/i2c/smiapp/smiapp-quirk.h
index 86fd3e8..504a6d8 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.h
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.h
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/smiapp/smiapp-reg-defs.h b/drivers/media/i2c/smiapp/smiapp-reg-defs.h
index defa7c5..3aa0ca9 100644
--- a/drivers/media/i2c/smiapp/smiapp-reg-defs.h
+++ b/drivers/media/i2c/smiapp/smiapp-reg-defs.h
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/smiapp/smiapp-reg.h b/drivers/media/i2c/smiapp/smiapp-reg.h
index 54568ca..b0dcbb8 100644
--- a/drivers/media/i2c/smiapp/smiapp-reg.h
+++ b/drivers/media/i2c/smiapp/smiapp-reg.h
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c
index 70e0d8d..4fac32c 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.c
+++ b/drivers/media/i2c/smiapp/smiapp-regs.c
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.h b/drivers/media/i2c/smiapp/smiapp-regs.h
index 7f9013b..eefc6c8 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.h
+++ b/drivers/media/i2c/smiapp/smiapp-regs.h
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/smiapp/smiapp.h b/drivers/media/i2c/smiapp/smiapp.h
index 4182a69..7cc5aae 100644
--- a/drivers/media/i2c/smiapp/smiapp.h
+++ b/drivers/media/i2c/smiapp/smiapp.h
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2010--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c
index 13057b9..d40a885 100644
--- a/drivers/media/i2c/soc_camera/mt9v022.c
+++ b/drivers/media/i2c/soc_camera/mt9v022.c
@@ -15,6 +15,7 @@
 #include <linux/log2.h>
 #include <linux/module.h>
 
+#include <media/mt9v022.h>
 #include <media/soc_camera.h>
 #include <media/soc_mediabus.h>
 #include <media/v4l2-subdev.h>
@@ -50,6 +51,7 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"");
 #define MT9V022_PIXEL_OPERATION_MODE	0x0f
 #define MT9V022_LED_OUT_CONTROL		0x1b
 #define MT9V022_ADC_MODE_CONTROL	0x1c
+#define MT9V022_REG32			0x20
 #define MT9V022_ANALOG_GAIN		0x35
 #define MT9V022_BLACK_LEVEL_CALIB_CTRL	0x47
 #define MT9V022_PIXCLK_FV_LV		0x74
@@ -71,7 +73,15 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"");
 #define MT9V022_COLUMN_SKIP		1
 #define MT9V022_ROW_SKIP		4
 
-#define is_mt9v024(id) (id == 0x1324)
+#define MT9V022_HORIZONTAL_BLANKING_MIN	43
+#define MT9V022_HORIZONTAL_BLANKING_MAX	1023
+#define MT9V022_HORIZONTAL_BLANKING_DEF	94
+#define MT9V022_VERTICAL_BLANKING_MIN	2
+#define MT9V022_VERTICAL_BLANKING_MAX	3000
+#define MT9V022_VERTICAL_BLANKING_DEF	45
+
+#define is_mt9v022_rev3(id)	(id == 0x1313)
+#define is_mt9v024(id)		(id == 0x1324)
 
 /* MT9V022 has only one fixed colorspace per pixelcode */
 struct mt9v022_datafmt {
@@ -136,6 +146,8 @@ struct mt9v022 {
 		struct v4l2_ctrl *autogain;
 		struct v4l2_ctrl *gain;
 	};
+	struct v4l2_ctrl *hblank;
+	struct v4l2_ctrl *vblank;
 	struct v4l2_rect rect;	/* Sensor window */
 	const struct mt9v022_datafmt *fmt;
 	const struct mt9v022_datafmt *fmts;
@@ -143,6 +155,7 @@ struct mt9v022 {
 	int num_fmts;
 	int model;	/* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
 	u16 chip_control;
+	u16 chip_version;
 	unsigned short y_skip_top;	/* Lines to skip at the top */
 };
 
@@ -225,12 +238,32 @@ static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable)
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct mt9v022 *mt9v022 = to_mt9v022(client);
 
-	if (enable)
+	if (enable) {
 		/* Switch to master "normal" mode */
 		mt9v022->chip_control &= ~0x10;
-	else
+		if (is_mt9v022_rev3(mt9v022->chip_version) ||
+		    is_mt9v024(mt9v022->chip_version)) {
+			/*
+			 * Unset snapshot mode specific settings: clear bit 9
+			 * and bit 2 in reg. 0x20 when in normal mode.
+			 */
+			if (reg_clear(client, MT9V022_REG32, 0x204))
+				return -EIO;
+		}
+	} else {
 		/* Switch to snapshot mode */
 		mt9v022->chip_control |= 0x10;
+		if (is_mt9v022_rev3(mt9v022->chip_version) ||
+		    is_mt9v024(mt9v022->chip_version)) {
+			/*
+			 * Required settings for snapshot mode: set bit 9
+			 * (RST enable) and bit 2 (CR enable) in reg. 0x20
+			 * See TechNote TN0960 or TN-09-225.
+			 */
+			if (reg_set(client, MT9V022_REG32, 0x204))
+				return -EIO;
+		}
+	}
 
 	if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0)
 		return -EIO;
@@ -263,9 +296,14 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
 		if (ret & 1) /* Autoexposure */
 			ret = reg_write(client, mt9v022->reg->max_total_shutter_width,
 					rect.height + mt9v022->y_skip_top + 43);
-		else
-			ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
-					rect.height + mt9v022->y_skip_top + 43);
+		/*
+		 * If autoexposure is off, there is no need to set
+		 * MT9V022_TOTAL_SHUTTER_WIDTH here. Autoexposure can be off
+		 * only if the user has set exposure manually, using the
+		 * V4L2_CID_EXPOSURE_AUTO with the value V4L2_EXPOSURE_MANUAL.
+		 * In this case the register MT9V022_TOTAL_SHUTTER_WIDTH
+		 * already contains the correct value.
+		 */
 	}
 	/* Setup frame format: defaults apart from width and height */
 	if (!ret)
@@ -277,11 +315,10 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
 		 * Default 94, Phytec driver says:
 		 * "width + horizontal blank >= 660"
 		 */
-		ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING,
-				rect.width > 660 - 43 ? 43 :
-				660 - rect.width);
+		ret = v4l2_ctrl_s_ctrl(mt9v022->hblank,
+				rect.width > 660 - 43 ? 43 : 660 - rect.width);
 	if (!ret)
-		ret = reg_write(client, MT9V022_VERTICAL_BLANKING, 45);
+		ret = v4l2_ctrl_s_ctrl(mt9v022->vblank, 45);
 	if (!ret)
 		ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width);
 	if (!ret)
@@ -504,6 +541,18 @@ static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 		range = exp->maximum - exp->minimum;
 		exp->val = ((data - 1) * range + 239) / 479 + exp->minimum;
 		return 0;
+	case V4L2_CID_HBLANK:
+		data = reg_read(client, MT9V022_HORIZONTAL_BLANKING);
+		if (data < 0)
+			return -EIO;
+		ctrl->val = data;
+		return 0;
+	case V4L2_CID_VBLANK:
+		data = reg_read(client, MT9V022_VERTICAL_BLANKING);
+		if (data < 0)
+			return -EIO;
+		ctrl->val = data;
+		return 0;
 	}
 	return -EINVAL;
 }
@@ -585,6 +634,16 @@ static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl)
 				return -EIO;
 		}
 		return 0;
+	case V4L2_CID_HBLANK:
+		if (reg_write(client, MT9V022_HORIZONTAL_BLANKING,
+				ctrl->val) < 0)
+			return -EIO;
+		return 0;
+	case V4L2_CID_VBLANK:
+		if (reg_write(client, MT9V022_VERTICAL_BLANKING,
+				ctrl->val) < 0)
+			return -EIO;
+		return 0;
 	}
 	return -EINVAL;
 }
@@ -616,6 +675,8 @@ static int mt9v022_video_probe(struct i2c_client *client)
 		goto ei2c;
 	}
 
+	mt9v022->chip_version = data;
+
 	mt9v022->reg = is_mt9v024(data) ? &mt9v024_register :
 			&mt9v022_register;
 
@@ -814,6 +875,7 @@ static int mt9v022_probe(struct i2c_client *client,
 	struct mt9v022 *mt9v022;
 	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	struct mt9v022_platform_data *pdata = icl->priv;
 	int ret;
 
 	if (!icl) {
@@ -852,10 +914,21 @@ static int mt9v022_probe(struct i2c_client *client,
 	mt9v022->exposure = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
 			V4L2_CID_EXPOSURE, 1, 255, 1, 255);
 
+	mt9v022->hblank = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+			V4L2_CID_HBLANK, MT9V022_HORIZONTAL_BLANKING_MIN,
+			MT9V022_HORIZONTAL_BLANKING_MAX, 1,
+			MT9V022_HORIZONTAL_BLANKING_DEF);
+
+	mt9v022->vblank = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+			V4L2_CID_VBLANK, MT9V022_VERTICAL_BLANKING_MIN,
+			MT9V022_VERTICAL_BLANKING_MAX, 1,
+			MT9V022_VERTICAL_BLANKING_DEF);
+
 	mt9v022->subdev.ctrl_handler = &mt9v022->hdl;
 	if (mt9v022->hdl.error) {
 		int err = mt9v022->hdl.error;
 
+		dev_err(&client->dev, "control initialisation err %d\n", err);
 		kfree(mt9v022);
 		return err;
 	}
@@ -866,10 +939,10 @@ static int mt9v022_probe(struct i2c_client *client,
 	mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
 
 	/*
-	 * MT9V022 _really_ corrupts the first read out line.
-	 * TODO: verify on i.MX31
+	 * On some platforms the first read out line is corrupted.
+	 * Workaround it by skipping if indicated by platform data.
 	 */
-	mt9v022->y_skip_top	= 1;
+	mt9v022->y_skip_top	= pdata ? pdata->y_skip_top : 0;
 	mt9v022->rect.left	= MT9V022_COLUMN_SKIP;
 	mt9v022->rect.top	= MT9V022_ROW_SKIP;
 	mt9v022->rect.width	= MT9V022_MAX_WIDTH;
diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c
index d2d298b..66698a8 100644
--- a/drivers/media/i2c/soc_camera/ov2640.c
+++ b/drivers/media/i2c/soc_camera/ov2640.c
@@ -586,9 +586,20 @@ static const struct regval_list ov2640_format_change_preamble_regs[] = {
 	ENDMARKER,
 };
 
-static const struct regval_list ov2640_yuv422_regs[] = {
+static const struct regval_list ov2640_yuyv_regs[] = {
+	{ IMAGE_MODE, IMAGE_MODE_YUV422 },
+	{ 0xd7, 0x03 },
+	{ 0x33, 0xa0 },
+	{ 0xe5, 0x1f },
+	{ 0xe1, 0x67 },
+	{ RESET,  0x00 },
+	{ R_BYPASS, R_BYPASS_USE_DSP },
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_uyvy_regs[] = {
 	{ IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_YUV422 },
-	{ 0xD7, 0x01 },
+	{ 0xd7, 0x01 },
 	{ 0x33, 0xa0 },
 	{ 0xe1, 0x67 },
 	{ RESET,  0x00 },
@@ -596,7 +607,15 @@ static const struct regval_list ov2640_yuv422_regs[] = {
 	ENDMARKER,
 };
 
-static const struct regval_list ov2640_rgb565_regs[] = {
+static const struct regval_list ov2640_rgb565_be_regs[] = {
+	{ IMAGE_MODE, IMAGE_MODE_RGB565 },
+	{ 0xd7, 0x03 },
+	{ RESET,  0x00 },
+	{ R_BYPASS, R_BYPASS_USE_DSP },
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_rgb565_le_regs[] = {
 	{ IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_RGB565 },
 	{ 0xd7, 0x03 },
 	{ RESET,  0x00 },
@@ -605,7 +624,9 @@ static const struct regval_list ov2640_rgb565_regs[] = {
 };
 
 static enum v4l2_mbus_pixelcode ov2640_codes[] = {
+	V4L2_MBUS_FMT_YUYV8_2X8,
 	V4L2_MBUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_RGB565_2X8_BE,
 	V4L2_MBUS_FMT_RGB565_2X8_LE,
 };
 
@@ -787,14 +808,22 @@ static int ov2640_set_params(struct i2c_client *client, u32 *width, u32 *height,
 	/* select format */
 	priv->cfmt_code = 0;
 	switch (code) {
+	case V4L2_MBUS_FMT_RGB565_2X8_BE:
+		dev_dbg(&client->dev, "%s: Selected cfmt RGB565 BE", __func__);
+		selected_cfmt_regs = ov2640_rgb565_be_regs;
+		break;
 	case V4L2_MBUS_FMT_RGB565_2X8_LE:
-		dev_dbg(&client->dev, "%s: Selected cfmt RGB565", __func__);
-		selected_cfmt_regs = ov2640_rgb565_regs;
+		dev_dbg(&client->dev, "%s: Selected cfmt RGB565 LE", __func__);
+		selected_cfmt_regs = ov2640_rgb565_le_regs;
+		break;
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+		dev_dbg(&client->dev, "%s: Selected cfmt YUYV (YUV422)", __func__);
+		selected_cfmt_regs = ov2640_yuyv_regs;
 		break;
 	default:
 	case V4L2_MBUS_FMT_UYVY8_2X8:
-		dev_dbg(&client->dev, "%s: Selected cfmt YUV422", __func__);
-		selected_cfmt_regs = ov2640_yuv422_regs;
+		dev_dbg(&client->dev, "%s: Selected cfmt UYVY", __func__);
+		selected_cfmt_regs = ov2640_uyvy_regs;
 	}
 
 	/* reset hardware */
@@ -859,10 +888,12 @@ static int ov2640_g_fmt(struct v4l2_subdev *sd,
 	mf->code	= priv->cfmt_code;
 
 	switch (mf->code) {
+	case V4L2_MBUS_FMT_RGB565_2X8_BE:
 	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		mf->colorspace = V4L2_COLORSPACE_SRGB;
 		break;
 	default:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
 	case V4L2_MBUS_FMT_UYVY8_2X8:
 		mf->colorspace = V4L2_COLORSPACE_JPEG;
 	}
@@ -879,11 +910,13 @@ static int ov2640_s_fmt(struct v4l2_subdev *sd,
 
 
 	switch (mf->code) {
+	case V4L2_MBUS_FMT_RGB565_2X8_BE:
 	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		mf->colorspace = V4L2_COLORSPACE_SRGB;
 		break;
 	default:
 		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+	case V4L2_MBUS_FMT_YUYV8_2X8:
 	case V4L2_MBUS_FMT_UYVY8_2X8:
 		mf->colorspace = V4L2_COLORSPACE_JPEG;
 	}
@@ -896,21 +929,21 @@ static int ov2640_s_fmt(struct v4l2_subdev *sd,
 static int ov2640_try_fmt(struct v4l2_subdev *sd,
 			  struct v4l2_mbus_framefmt *mf)
 {
-	const struct ov2640_win_size *win;
-
 	/*
-	 * select suitable win
+	 * select suitable win, but don't store it
 	 */
-	win = ov2640_select_win(&mf->width, &mf->height);
+	ov2640_select_win(&mf->width, &mf->height);
 
 	mf->field	= V4L2_FIELD_NONE;
 
 	switch (mf->code) {
+	case V4L2_MBUS_FMT_RGB565_2X8_BE:
 	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		mf->colorspace = V4L2_COLORSPACE_SRGB;
 		break;
 	default:
 		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+	case V4L2_MBUS_FMT_YUYV8_2X8:
 	case V4L2_MBUS_FMT_UYVY8_2X8:
 		mf->colorspace = V4L2_COLORSPACE_JPEG;
 	}
diff --git a/drivers/media/i2c/vs6624.c b/drivers/media/i2c/vs6624.c
index 42ae9dc..f434a19 100644
--- a/drivers/media/i2c/vs6624.c
+++ b/drivers/media/i2c/vs6624.c
@@ -910,18 +910,7 @@ static struct i2c_driver vs6624_driver = {
 	.id_table       = vs6624_id,
 };
 
-static __init int vs6624_init(void)
-{
-	return i2c_add_driver(&vs6624_driver);
-}
-
-static __exit void vs6624_exit(void)
-{
-	i2c_del_driver(&vs6624_driver);
-}
-
-module_init(vs6624_init);
-module_exit(vs6624_exit);
+module_i2c_driver(vs6624_driver);
 
 MODULE_DESCRIPTION("VS6624 sensor driver");
 MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
diff --git a/drivers/media/mmc/siano/Kconfig b/drivers/media/mmc/siano/Kconfig
index fa62475..aa05ad3 100644
--- a/drivers/media/mmc/siano/Kconfig
+++ b/drivers/media/mmc/siano/Kconfig
@@ -4,7 +4,8 @@
 
 config SMS_SDIO_DRV
 	tristate "Siano SMS1xxx based MDTV via SDIO interface"
-	depends on DVB_CORE && RC_CORE && HAS_DMA
+	depends on DVB_CORE && HAS_DMA
 	depends on MMC
+	select MEDIA_COMMON_OPTIONS
 	---help---
 	  Choose if you would like to have Siano's support for SDIO interface
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index 56c6c77..de6f41f 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -200,7 +200,7 @@ static void flush_request_modules(struct bttv *dev)
 }
 #else
 #define request_modules(dev)
-#define flush_request_modules(dev)
+#define flush_request_modules(dev) do {} while(0)
 #endif /* CONFIG_MODULES */
 
 
@@ -301,11 +301,10 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
 			/* totalwidth */ 1135,
 			/* sqwidth */ 944,
 			/* vdelay */ 0x20,
-			/* sheight */ 576,
-			/* videostart0 */ 23)
 		/* bt878 (and bt848?) can capture another
 		   line below active video. */
-		.cropcap.bounds.height = (576 + 2) + 0x20 - 2,
+			/* sheight */ (576 + 2) + 0x20 - 2,
+			/* videostart0 */ 23)
 	},{
 		.v4l2_id        = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
 		.name           = "NTSC",
diff --git a/drivers/media/pci/cx18/cx18-alsa-main.c b/drivers/media/pci/cx18/cx18-alsa-main.c
index 6d2a982..8e971ff 100644
--- a/drivers/media/pci/cx18/cx18-alsa-main.c
+++ b/drivers/media/pci/cx18/cx18-alsa-main.c
@@ -197,7 +197,7 @@ err_exit:
 	return ret;
 }
 
-int cx18_alsa_load(struct cx18 *cx)
+static int __init cx18_alsa_load(struct cx18 *cx)
 {
 	struct v4l2_device *v4l2_dev = &cx->v4l2_dev;
 	struct cx18_stream *s;
diff --git a/drivers/media/pci/cx18/cx18-alsa-pcm.c b/drivers/media/pci/cx18/cx18-alsa-pcm.c
index 7a5b84a..180077c 100644
--- a/drivers/media/pci/cx18/cx18-alsa-pcm.c
+++ b/drivers/media/pci/cx18/cx18-alsa-pcm.c
@@ -37,6 +37,7 @@
 #include "cx18-streams.h"
 #include "cx18-fileops.h"
 #include "cx18-alsa.h"
+#include "cx18-alsa-pcm.h"
 
 static unsigned int pcm_debug;
 module_param(pcm_debug, int, 0644);
diff --git a/drivers/media/pci/cx18/cx18-i2c.c b/drivers/media/pci/cx18/cx18-i2c.c
index 51609d5..4908eb7 100644
--- a/drivers/media/pci/cx18/cx18-i2c.c
+++ b/drivers/media/pci/cx18/cx18-i2c.c
@@ -98,7 +98,7 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw,
 	case CX18_HW_Z8F0811_IR_RX_HAUP:
 		init_data->ir_codes = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-		init_data->type = RC_TYPE_RC5;
+		init_data->type = RC_BIT_RC5;
 		init_data->name = cx->card_name;
 		info.platform_data = init_data;
 		break;
diff --git a/drivers/media/pci/cx18/cx18-streams.c b/drivers/media/pci/cx18/cx18-streams.c
index 72af9b5..843c62b 100644
--- a/drivers/media/pci/cx18/cx18-streams.c
+++ b/drivers/media/pci/cx18/cx18-streams.c
@@ -97,7 +97,7 @@ static struct {
 };
 
 
-void cx18_dma_free(struct videobuf_queue *q,
+static void cx18_dma_free(struct videobuf_queue *q,
 	struct cx18_stream *s, struct cx18_videobuf_buffer *buf)
 {
 	videobuf_waiton(q, &buf->vb, 0, 0);
diff --git a/drivers/media/pci/cx23885/altera-ci.c b/drivers/media/pci/cx23885/altera-ci.c
index 495781e..2926f7f 100644
--- a/drivers/media/pci/cx23885/altera-ci.c
+++ b/drivers/media/pci/cx23885/altera-ci.c
@@ -263,7 +263,7 @@ static int netup_fpga_op_rw(struct fpga_internal *inter, int addr,
 }
 
 /* flag - mem/io, read - read/write */
-int altera_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
+static int altera_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
 				u8 flag, u8 read, int addr, u8 val)
 {
 
@@ -298,31 +298,32 @@ int altera_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
 	return mem;
 }
 
-int altera_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
-						int slot, int addr)
+static int altera_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
+					int slot, int addr)
 {
 	return altera_ci_op_cam(en50221, slot, 0, NETUP_CI_FLG_RD, addr, 0);
 }
 
-int altera_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
-						int slot, int addr, u8 data)
+static int altera_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
+					 int slot, int addr, u8 data)
 {
 	return altera_ci_op_cam(en50221, slot, 0, 0, addr, data);
 }
 
-int altera_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
+static int altera_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221,
+				  int slot, u8 addr)
 {
 	return altera_ci_op_cam(en50221, slot, NETUP_CI_FLG_CTL,
 						NETUP_CI_FLG_RD, addr, 0);
 }
 
-int altera_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,
-						u8 addr, u8 data)
+static int altera_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,
+				   u8 addr, u8 data)
 {
 	return altera_ci_op_cam(en50221, slot, NETUP_CI_FLG_CTL, 0, addr, data);
 }
 
-int altera_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
+static int altera_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
 {
 	struct altera_ci_state *state = en50221->data;
 	struct fpga_internal *inter = state->internal;
@@ -365,13 +366,13 @@ int altera_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
 	return 0;
 }
 
-int altera_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
+static int altera_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
 {
 	/* not implemented */
 	return 0;
 }
 
-int altera_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)
+static int altera_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)
 {
 	struct altera_ci_state *state = en50221->data;
 	struct fpga_internal *inter = state->internal;
@@ -448,8 +449,8 @@ int altera_ci_irq(void *dev)
 }
 EXPORT_SYMBOL(altera_ci_irq);
 
-int altera_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot,
-								int open)
+static int altera_poll_ci_slot_status(struct dvb_ca_en50221 *en50221,
+				      int slot, int open)
 {
 	struct altera_ci_state *state = en50221->data;
 
@@ -459,7 +460,7 @@ int altera_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot,
 	return state->status;
 }
 
-void altera_hw_filt_release(void *main_dev, int filt_nr)
+static void altera_hw_filt_release(void *main_dev, int filt_nr)
 {
 	struct fpga_inode *temp_int = find_inode(main_dev);
 	struct netup_hw_pid_filter *pid_filt = NULL;
@@ -581,7 +582,7 @@ static void altera_toggle_fullts_streaming(struct netup_hw_pid_filter *pid_filt,
 	mutex_unlock(&inter->fpga_mutex);
 }
 
-int altera_pid_feed_control(void *demux_dev, int filt_nr,
+static int altera_pid_feed_control(void *demux_dev, int filt_nr,
 		struct dvb_demux_feed *feed, int onoff)
 {
 	struct fpga_inode *temp_int = find_dinode(demux_dev);
@@ -603,41 +604,41 @@ int altera_pid_feed_control(void *demux_dev, int filt_nr,
 }
 EXPORT_SYMBOL(altera_pid_feed_control);
 
-int altera_ci_start_feed(struct dvb_demux_feed *feed, int num)
+static int altera_ci_start_feed(struct dvb_demux_feed *feed, int num)
 {
 	altera_pid_feed_control(feed->demux, num, feed, 1);
 
 	return 0;
 }
 
-int altera_ci_stop_feed(struct dvb_demux_feed *feed, int num)
+static int altera_ci_stop_feed(struct dvb_demux_feed *feed, int num)
 {
 	altera_pid_feed_control(feed->demux, num, feed, 0);
 
 	return 0;
 }
 
-int altera_ci_start_feed_1(struct dvb_demux_feed *feed)
+static int altera_ci_start_feed_1(struct dvb_demux_feed *feed)
 {
 	return altera_ci_start_feed(feed, 1);
 }
 
-int altera_ci_stop_feed_1(struct dvb_demux_feed *feed)
+static int altera_ci_stop_feed_1(struct dvb_demux_feed *feed)
 {
 	return altera_ci_stop_feed(feed, 1);
 }
 
-int altera_ci_start_feed_2(struct dvb_demux_feed *feed)
+static int altera_ci_start_feed_2(struct dvb_demux_feed *feed)
 {
 	return altera_ci_start_feed(feed, 2);
 }
 
-int altera_ci_stop_feed_2(struct dvb_demux_feed *feed)
+static int altera_ci_stop_feed_2(struct dvb_demux_feed *feed)
 {
 	return altera_ci_stop_feed(feed, 2);
 }
 
-int altera_hw_filt_init(struct altera_ci_config *config, int hw_filt_nr)
+static int altera_hw_filt_init(struct altera_ci_config *config, int hw_filt_nr)
 {
 	struct netup_hw_pid_filter *pid_filt = NULL;
 	struct fpga_inode *temp_int = find_inode(config->dev);
diff --git a/drivers/media/pci/cx23885/cimax2.c b/drivers/media/pci/cx23885/cimax2.c
index 6617774..7344849 100644
--- a/drivers/media/pci/cx23885/cimax2.c
+++ b/drivers/media/pci/cx23885/cimax2.c
@@ -24,6 +24,7 @@
  */
 
 #include "cx23885.h"
+#include "cimax2.h"
 #include "dvb_ca_en50221.h"
 /**** Bit definitions for MC417_RWD and MC417_OEN registers  ***
   bits 31-16
@@ -87,7 +88,7 @@ struct netup_ci_state {
 };
 
 
-int netup_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
+static int netup_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
 						u8 *buf, int len)
 {
 	int ret;
@@ -120,7 +121,7 @@ int netup_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
 	return 0;
 }
 
-int netup_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
+static int netup_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
 						u8 *buf, int len)
 {
 	int ret;
@@ -147,7 +148,7 @@ int netup_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
 	return 0;
 }
 
-int netup_ci_get_mem(struct cx23885_dev *dev)
+static int netup_ci_get_mem(struct cx23885_dev *dev)
 {
 	int mem;
 	unsigned long timeout = jiffies + msecs_to_jiffies(1);
@@ -166,7 +167,7 @@ int netup_ci_get_mem(struct cx23885_dev *dev)
 	return mem & 0xff;
 }
 
-int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
+static int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
 				u8 flag, u8 read, int addr, u8 data)
 {
 	struct netup_ci_state *state = en50221->data;
@@ -248,7 +249,8 @@ int netup_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
 	return netup_ci_op_cam(en50221, slot, 0, 0, addr, data);
 }
 
-int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
+int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,
+				 u8 addr)
 {
 	return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL,
 							NETUP_CI_RD, addr, 0);
@@ -295,7 +297,7 @@ int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
 	return 0;
 }
 
-int netup_ci_set_irq(struct dvb_ca_en50221 *en50221, u8 irq_mode)
+static int netup_ci_set_irq(struct dvb_ca_en50221 *en50221, u8 irq_mode)
 {
 	struct netup_ci_state *state = en50221->data;
 	int ret;
@@ -399,7 +401,8 @@ int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status)
 	return 1;
 }
 
-int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open)
+int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221,
+				     int slot, int open)
 {
 	struct netup_ci_state *state = en50221->data;
 
diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c b/drivers/media/pci/cx23885/cx23885-alsa.c
index 7951692..c6c9bd5 100644
--- a/drivers/media/pci/cx23885/cx23885-alsa.c
+++ b/drivers/media/pci/cx23885/cx23885-alsa.c
@@ -45,8 +45,10 @@
 
 #define AUDIO_SRAM_CHANNEL	SRAM_CH07
 
-#define dprintk(level, fmt, arg...)	if (audio_debug >= level) \
-	printk(KERN_INFO "%s: " fmt, chip->dev->name , ## arg)
+#define dprintk(level, fmt, arg...) do {				\
+	if (audio_debug + 1 > level)					\
+		printk(KERN_INFO "%s: " fmt, chip->dev->name , ## arg);	\
+} while(0)
 
 #define dprintk_core(level, fmt, arg...)	if (audio_debug >= level) \
 	printk(KERN_DEBUG "%s: " fmt, chip->dev->name , ## arg)
diff --git a/drivers/media/pci/cx23885/cx23885-av.c b/drivers/media/pci/cx23885/cx23885-av.c
index 134ebdd..e958a01 100644
--- a/drivers/media/pci/cx23885/cx23885-av.c
+++ b/drivers/media/pci/cx23885/cx23885-av.c
@@ -22,6 +22,7 @@
  */
 
 #include "cx23885.h"
+#include "cx23885-av.h"
 
 void cx23885_av_work_handler(struct work_struct *work)
 {
diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c
index 5acdf95..6277e145 100644
--- a/drivers/media/pci/cx23885/cx23885-cards.c
+++ b/drivers/media/pci/cx23885/cx23885-cards.c
@@ -1427,7 +1427,7 @@ void cx23885_ir_fini(struct cx23885_dev *dev)
 	}
 }
 
-int netup_jtag_io(void *device, int tms, int tdi, int read_tdo)
+static int netup_jtag_io(void *device, int tms, int tdi, int read_tdo)
 {
 	int data;
 	int tdo = 0;
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
index 697728f..065ecd5 100644
--- a/drivers/media/pci/cx23885/cx23885-core.c
+++ b/drivers/media/pci/cx23885/cx23885-core.c
@@ -303,7 +303,7 @@ static struct sram_channel cx23887_sram_channels[] = {
 	},
 };
 
-void cx23885_irq_add(struct cx23885_dev *dev, u32 mask)
+static void cx23885_irq_add(struct cx23885_dev *dev, u32 mask)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
@@ -1516,8 +1516,7 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
 			buf = list_entry(q->queued.next, struct cx23885_buffer,
 					 vb.queue);
 			if (NULL == prev) {
-				list_del(&buf->vb.queue);
-				list_add_tail(&buf->vb.queue, &q->active);
+				list_move_tail(&buf->vb.queue, &q->active);
 				cx23885_start_dma(port, q, buf);
 				buf->vb.state = VIDEOBUF_ACTIVE;
 				buf->count    = q->count++;
@@ -1528,8 +1527,7 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
 			} else if (prev->vb.width  == buf->vb.width  &&
 				   prev->vb.height == buf->vb.height &&
 				   prev->fmt       == buf->fmt) {
-				list_del(&buf->vb.queue);
-				list_add_tail(&buf->vb.queue, &q->active);
+				list_move_tail(&buf->vb.queue, &q->active);
 				buf->vb.state = VIDEOBUF_ACTIVE;
 				buf->count    = q->count++;
 				prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index 4379d8a..2f5b902 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -659,7 +659,7 @@ static struct mt2063_config terratec_mt2063_config[] = {
 	},
 };
 
-int netup_altera_fpga_rw(void *device, int flag, int data, int read)
+static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
 {
 	struct cx23885_dev *dev = (struct cx23885_dev *)device;
 	unsigned long timeout = jiffies + msecs_to_jiffies(1);
diff --git a/drivers/media/pci/cx23885/cx23885-f300.c b/drivers/media/pci/cx23885/cx23885-f300.c
index 93998f2..5444cc5 100644
--- a/drivers/media/pci/cx23885/cx23885-f300.c
+++ b/drivers/media/pci/cx23885/cx23885-f300.c
@@ -29,6 +29,7 @@
  */
 
 #include "cx23885.h"
+#include "cx23885-f300.h"
 
 #define F300_DATA	GPIO_0
 #define F300_RESET	GPIO_1
diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c
index 2c925f7..4f1055a 100644
--- a/drivers/media/pci/cx23885/cx23885-input.c
+++ b/drivers/media/pci/cx23885/cx23885-input.c
@@ -40,6 +40,7 @@
 #include <media/v4l2-subdev.h>
 
 #include "cx23885.h"
+#include "cx23885-input.h"
 
 #define MODULE_NAME "cx23885"
 
@@ -270,21 +271,21 @@ int cx23885_input_init(struct cx23885_dev *dev)
 	case CX23885_BOARD_HAUPPAUGE_HVR1250:
 		/* Integrated CX2388[58] IR controller */
 		driver_type = RC_DRIVER_IR_RAW;
-		allowed_protos = RC_TYPE_ALL;
+		allowed_protos = RC_BIT_ALL;
 		/* The grey Hauppauge RC-5 remote */
 		rc_map = RC_MAP_HAUPPAUGE;
 		break;
 	case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
 		/* Integrated CX23885 IR controller */
 		driver_type = RC_DRIVER_IR_RAW;
-		allowed_protos = RC_TYPE_NEC;
+		allowed_protos = RC_BIT_NEC;
 		/* The grey Terratec remote with orange buttons */
 		rc_map = RC_MAP_NEC_TERRATEC_CINERGY_XS;
 		break;
 	case CX23885_BOARD_TEVII_S470:
 		/* Integrated CX23885 IR controller */
 		driver_type = RC_DRIVER_IR_RAW;
-		allowed_protos = RC_TYPE_ALL;
+		allowed_protos = RC_BIT_ALL;
 		/* A guess at the remote */
 		rc_map = RC_MAP_TEVII_NEC;
 		break;
diff --git a/drivers/media/pci/cx23885/cx23885-input.h b/drivers/media/pci/cx23885/cx23885-input.h
index 75ef15d..87dc44e 100644
--- a/drivers/media/pci/cx23885/cx23885-input.h
+++ b/drivers/media/pci/cx23885/cx23885-input.h
@@ -23,7 +23,7 @@
 
 #ifndef _CX23885_INPUT_H_
 #define _CX23885_INPUT_H_
-int cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events);
+void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events);
 
 int cx23885_input_init(struct cx23885_dev *dev);
 void cx23885_input_fini(struct cx23885_dev *dev);
diff --git a/drivers/media/pci/cx23885/cx23885-ioctl.c b/drivers/media/pci/cx23885/cx23885-ioctl.c
index 44812ca..ea9a614 100644
--- a/drivers/media/pci/cx23885/cx23885-ioctl.c
+++ b/drivers/media/pci/cx23885/cx23885-ioctl.c
@@ -22,6 +22,8 @@
  */
 
 #include "cx23885.h"
+#include "cx23885-ioctl.h"
+
 #include <media/v4l2-chip-ident.h>
 
 int cx23885_g_chip_ident(struct file *file, void *fh,
diff --git a/drivers/media/pci/cx23885/cx23885-ir.c b/drivers/media/pci/cx23885/cx23885-ir.c
index 7125247..bfef193 100644
--- a/drivers/media/pci/cx23885/cx23885-ir.c
+++ b/drivers/media/pci/cx23885/cx23885-ir.c
@@ -24,6 +24,7 @@
 #include <media/v4l2-device.h>
 
 #include "cx23885.h"
+#include "cx23885-ir.h"
 #include "cx23885-input.h"
 
 #define CX23885_IR_RX_FIFO_SERVICE_REQ		0
diff --git a/drivers/media/pci/cx23885/cx23888-ir.c b/drivers/media/pci/cx23885/cx23888-ir.c
index c2bc39c..c4bd1e9 100644
--- a/drivers/media/pci/cx23885/cx23888-ir.c
+++ b/drivers/media/pci/cx23885/cx23888-ir.c
@@ -29,6 +29,7 @@
 #include <media/rc-core.h>
 
 #include "cx23885.h"
+#include "cx23888-ir.h"
 
 static unsigned int ir_888_debug;
 module_param(ir_888_debug, int, 0644);
diff --git a/drivers/media/pci/cx23885/netup-init.c b/drivers/media/pci/cx23885/netup-init.c
index f4893e6..0044fef 100644
--- a/drivers/media/pci/cx23885/netup-init.c
+++ b/drivers/media/pci/cx23885/netup-init.c
@@ -24,6 +24,7 @@
  */
 
 #include "cx23885.h"
+#include "netup-init.h"
 
 static void i2c_av_write(struct i2c_adapter *i2c, u16 reg, u8 val)
 {
diff --git a/drivers/media/pci/cx25821/Kconfig b/drivers/media/pci/cx25821/Kconfig
index 5f6b542..4017c94 100644
--- a/drivers/media/pci/cx25821/Kconfig
+++ b/drivers/media/pci/cx25821/Kconfig
@@ -18,7 +18,7 @@ config VIDEO_CX25821
 
 config VIDEO_CX25821_ALSA
 	tristate "Conexant 25821 DMA audio support"
-	depends on VIDEO_CX25821 && SND && EXPERIMENTAL
+	depends on VIDEO_CX25821 && SND
 	select SND_PCM
 	---help---
 	  This is a video4linux driver for direct (DMA) audio on
diff --git a/drivers/media/pci/cx25821/cx25821-audio-upstream.c b/drivers/media/pci/cx25821/cx25821-audio-upstream.c
index 8b2a999..87491ca 100644
--- a/drivers/media/pci/cx25821/cx25821-audio-upstream.c
+++ b/drivers/media/pci/cx25821/cx25821-audio-upstream.c
@@ -44,7 +44,7 @@ MODULE_LICENSE("GPL");
 static int _intr_msk = FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF |
 			FLD_AUD_SRC_SYNC | FLD_AUD_SRC_OPC_ERR;
 
-int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev,
+static int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev,
 					      struct sram_channel *ch,
 					      unsigned int bpl, u32 risc)
 {
@@ -133,7 +133,7 @@ static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev,
 	return rp;
 }
 
-int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev,
+static int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev,
 				       struct pci_dev *pci,
 				       unsigned int bpl, unsigned int lines)
 {
@@ -197,7 +197,7 @@ int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev,
 	return 0;
 }
 
-void cx25821_free_memory_audio(struct cx25821_dev *dev)
+static void cx25821_free_memory_audio(struct cx25821_dev *dev)
 {
 	if (dev->_risc_virt_addr) {
 		pci_free_consistent(dev->pci, dev->_audiorisc_size,
@@ -256,7 +256,7 @@ void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev)
 	cx25821_free_memory_audio(dev);
 }
 
-int cx25821_get_audio_data(struct cx25821_dev *dev,
+static int cx25821_get_audio_data(struct cx25821_dev *dev,
 			   struct sram_channel *sram_ch)
 {
 	struct file *myfile;
@@ -351,7 +351,7 @@ static void cx25821_audioups_handler(struct work_struct *work)
 			sram_channels);
 }
 
-int cx25821_openfile_audio(struct cx25821_dev *dev,
+static int cx25821_openfile_audio(struct cx25821_dev *dev,
 			   struct sram_channel *sram_ch)
 {
 	struct file *myfile;
@@ -490,7 +490,7 @@ error:
 	return ret;
 }
 
-int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num,
+static int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num,
 			       u32 status)
 {
 	int i = 0;
@@ -634,8 +634,8 @@ static void cx25821_wait_fifo_enable(struct cx25821_dev *dev,
 
 }
 
-int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev,
-				     struct sram_channel *sram_ch)
+static int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev,
+					    struct sram_channel *sram_ch)
 {
 	u32 tmp = 0;
 	int err = 0;
@@ -700,9 +700,7 @@ fail_irq:
 int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
 {
 	struct sram_channel *sram_ch;
-	int retval = 0;
 	int err = 0;
-	int str_length = 0;
 
 	if (dev->_audio_is_running) {
 		pr_warn("Audio Channel is still running so return!\n");
@@ -731,27 +729,29 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
 	_line_size = AUDIO_LINE_SIZE;
 
 	if (dev->input_audiofilename) {
-		str_length = strlen(dev->input_audiofilename);
-		dev->_audiofilename = kmemdup(dev->input_audiofilename,
-					      str_length + 1, GFP_KERNEL);
+		dev->_audiofilename = kstrdup(dev->input_audiofilename,
+					      GFP_KERNEL);
 
-		if (!dev->_audiofilename)
+		if (!dev->_audiofilename) {
+			err = -ENOMEM;
 			goto error;
+		}
 
 		/* Default if filename is empty string */
 		if (strcmp(dev->input_audiofilename, "") == 0)
 			dev->_audiofilename = "/root/audioGOOD.wav";
 	} else {
-		str_length = strlen(_defaultAudioName);
-		dev->_audiofilename = kmemdup(_defaultAudioName,
-					      str_length + 1, GFP_KERNEL);
+		dev->_audiofilename = kstrdup(_defaultAudioName,
+					      GFP_KERNEL);
 
-		if (!dev->_audiofilename)
+		if (!dev->_audiofilename) {
+			err = -ENOMEM;
 			goto error;
+		}
 	}
 
-	retval = cx25821_sram_channel_setup_upstream_audio(dev, sram_ch,
-							_line_size, 0);
+	cx25821_sram_channel_setup_upstream_audio(dev, sram_ch,
+						  _line_size, 0);
 
 	dev->audio_upstream_riscbuf_size =
 		AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS +
@@ -759,9 +759,9 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
 	dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS;
 
 	/* Allocating buffers and prepare RISC program */
-	retval = cx25821_audio_upstream_buffer_prepare(dev, sram_ch,
+	err = cx25821_audio_upstream_buffer_prepare(dev, sram_ch,
 							_line_size);
-	if (retval < 0) {
+	if (err < 0) {
 		pr_err("%s: Failed to set up Audio upstream buffers!\n",
 			dev->name);
 		goto error;
diff --git a/drivers/media/pci/cx25821/cx25821-biffuncs.h b/drivers/media/pci/cx25821/cx25821-biffuncs.h
index 9326a7c..937f5a7 100644
--- a/drivers/media/pci/cx25821/cx25821-biffuncs.h
+++ b/drivers/media/pci/cx25821/cx25821-biffuncs.h
@@ -25,17 +25,17 @@
 
 #define SetBit(Bit)  (1 << Bit)
 
-inline u8 getBit(u32 sample, u8 index)
+static inline u8 getBit(u32 sample, u8 index)
 {
 	return (u8) ((sample >> index) & 1);
 }
 
-inline u32 clearBitAtPos(u32 value, u8 bit)
+static inline u32 clearBitAtPos(u32 value, u8 bit)
 {
 	return value & ~(1 << bit);
 }
 
-inline u32 setBitAtPos(u32 sample, u8 bit)
+static inline u32 setBitAtPos(u32 sample, u8 bit)
 {
 	sample |= (1 << bit);
 	return sample;
diff --git a/drivers/media/pci/cx25821/cx25821-i2c.c b/drivers/media/pci/cx25821/cx25821-i2c.c
index 9844549..a8dc945 100644
--- a/drivers/media/pci/cx25821/cx25821-i2c.c
+++ b/drivers/media/pci/cx25821/cx25821-i2c.c
@@ -329,7 +329,8 @@ int cx25821_i2c_unregister(struct cx25821_i2c *bus)
 	return 0;
 }
 
-void cx25821_av_clk(struct cx25821_dev *dev, int enable)
+#if 0 /* Currently unused */
+static void cx25821_av_clk(struct cx25821_dev *dev, int enable)
 {
 	/* write 0 to bus 2 addr 0x144 via i2x_xfer() */
 	char buffer[3];
@@ -351,6 +352,7 @@ void cx25821_av_clk(struct cx25821_dev *dev, int enable)
 
 	i2c_xfer(&dev->i2c_bus[0].i2c_adap, &msg, 1);
 }
+#endif
 
 int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value)
 {
diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c b/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c
index d33fc1a..cf2723c 100644
--- a/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c
+++ b/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c
@@ -123,10 +123,11 @@ static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev,
 	return rp;
 }
 
-int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev,
-				     struct pci_dev *pci,
-				     unsigned int top_offset, unsigned int bpl,
-				     unsigned int lines)
+static int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev,
+					    struct pci_dev *pci,
+					    unsigned int top_offset,
+					    unsigned int bpl,
+					    unsigned int lines)
 {
 	__le32 *rp;
 	int fifo_enable = 0;
@@ -255,7 +256,8 @@ void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev)
 	}
 }
 
-int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+static int cx25821_get_frame_ch2(struct cx25821_dev *dev,
+				 struct sram_channel *sram_ch)
 {
 	struct file *myfile;
 	int frame_index_temp = dev->_frame_index_ch2;
@@ -360,7 +362,8 @@ static void cx25821_vidups_handler_ch2(struct work_struct *work)
 			_channel2_upstream_select].sram_channels);
 }
 
-int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+static int cx25821_openfile_ch2(struct cx25821_dev *dev,
+				struct sram_channel *sram_ch)
 {
 	struct file *myfile;
 	int i = 0, j = 0;
@@ -507,8 +510,9 @@ error:
 	return ret;
 }
 
-int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num,
-				   u32 status)
+static int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev,
+					  int chan_num,
+					  u32 status)
 {
 	u32 int_msk_tmp;
 	struct sram_channel *channel = dev->channels[chan_num].sram_channels;
@@ -647,8 +651,8 @@ static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev,
 	cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
 }
 
-int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev,
-					 struct sram_channel *sram_ch)
+static int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev,
+						struct sram_channel *sram_ch)
 {
 	u32 tmp = 0;
 	int err = 0;
@@ -704,11 +708,9 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
 {
 	struct sram_channel *sram_ch;
 	u32 tmp;
-	int retval = 0;
 	int err = 0;
 	int data_frame_size = 0;
 	int risc_buffer_size = 0;
-	int str_length = 0;
 
 	if (dev->_is_running_ch2) {
 		pr_info("Video Channel is still running so return!\n");
@@ -744,20 +746,16 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
 	risc_buffer_size = dev->_isNTSC_ch2 ?
 		NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
 
-	if (dev->input_filename_ch2) {
-		str_length = strlen(dev->input_filename_ch2);
-		dev->_filename_ch2 = kmemdup(dev->input_filename_ch2,
-					     str_length + 1, GFP_KERNEL);
-
-		if (!dev->_filename_ch2)
-			goto error;
-	} else {
-		str_length = strlen(dev->_defaultname_ch2);
-		dev->_filename_ch2 = kmemdup(dev->_defaultname_ch2,
-					     str_length + 1, GFP_KERNEL);
+	if (dev->input_filename_ch2)
+		dev->_filename_ch2 = kstrdup(dev->input_filename_ch2,
+								GFP_KERNEL);
+	else
+		dev->_filename_ch2 = kstrdup(dev->_defaultname_ch2,
+								GFP_KERNEL);
 
-		if (!dev->_filename_ch2)
-			goto error;
+	if (!dev->_filename_ch2) {
+		err = -ENOENT;
+		goto error;
 	}
 
 	/* Default if filename is empty string */
@@ -773,7 +771,7 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
 		}
 	}
 
-	retval = cx25821_sram_channel_setup_upstream(dev, sram_ch,
+	err = cx25821_sram_channel_setup_upstream(dev, sram_ch,
 						dev->_line_size_ch2, 0);
 
 	/* setup fifo + format */
@@ -783,9 +781,9 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
 	dev->upstream_databuf_size_ch2 = data_frame_size * 2;
 
 	/* Allocating buffers and prepare RISC program */
-	retval = cx25821_upstream_buffer_prepare_ch2(dev, sram_ch,
+	err = cx25821_upstream_buffer_prepare_ch2(dev, sram_ch,
 						dev->_line_size_ch2);
-	if (retval < 0) {
+	if (err < 0) {
 		pr_err("%s: Failed to set up Video upstream buffers!\n",
 		       dev->name);
 		goto error;
diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream.c b/drivers/media/pci/cx25821/cx25821-video-upstream.c
index 6759fff..7fc9711 100644
--- a/drivers/media/pci/cx25821/cx25821-video-upstream.c
+++ b/drivers/media/pci/cx25821/cx25821-video-upstream.c
@@ -173,10 +173,10 @@ static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp,
 	return rp;
 }
 
-int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
-				 struct pci_dev *pci,
-				 unsigned int top_offset,
-				 unsigned int bpl, unsigned int lines)
+static int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
+					struct pci_dev *pci,
+					unsigned int top_offset,
+					unsigned int bpl, unsigned int lines)
 {
 	__le32 *rp;
 	int fifo_enable = 0;
@@ -300,7 +300,8 @@ void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev)
 	}
 }
 
-int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+static int cx25821_get_frame(struct cx25821_dev *dev,
+			     struct sram_channel *sram_ch)
 {
 	struct file *myfile;
 	int frame_index_temp = dev->_frame_index;
@@ -405,7 +406,8 @@ static void cx25821_vidups_handler(struct work_struct *work)
 			sram_channels);
 }
 
-int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+static int cx25821_openfile(struct cx25821_dev *dev,
+			    struct sram_channel *sram_ch)
 {
 	struct file *myfile;
 	int i = 0, j = 0;
@@ -486,8 +488,9 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)
 	return 0;
 }
 
-int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
-				    struct sram_channel *sram_ch, int bpl)
+static int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
+					   struct sram_channel *sram_ch,
+					   int bpl)
 {
 	int ret = 0;
 	dma_addr_t dma_addr;
@@ -548,8 +551,8 @@ error:
 	return ret;
 }
 
-int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num,
-			       u32 status)
+static int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num,
+				      u32 status)
 {
 	u32 int_msk_tmp;
 	struct sram_channel *channel = dev->channels[chan_num].sram_channels;
@@ -664,8 +667,9 @@ static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id)
 	return IRQ_RETVAL(handled);
 }
 
-void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch,
-			     int pix_format)
+static void cx25821_set_pixelengine(struct cx25821_dev *dev,
+				    struct sram_channel *ch,
+				    int pix_format)
 {
 	int width = WIDTH_D1;
 	int height = dev->_lines_count;
@@ -696,8 +700,8 @@ void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch,
 	cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
 }
 
-int cx25821_start_video_dma_upstream(struct cx25821_dev *dev,
-				     struct sram_channel *sram_ch)
+static int cx25821_start_video_dma_upstream(struct cx25821_dev *dev,
+					    struct sram_channel *sram_ch)
 {
 	u32 tmp = 0;
 	int err = 0;
@@ -753,7 +757,6 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
 {
 	struct sram_channel *sram_ch;
 	u32 tmp;
-	int retval = 0;
 	int err = 0;
 	int data_frame_size = 0;
 	int risc_buffer_size = 0;
@@ -796,15 +799,19 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
 		dev->_filename = kmemdup(dev->input_filename, str_length + 1,
 					 GFP_KERNEL);
 
-		if (!dev->_filename)
+		if (!dev->_filename) {
+			err = -ENOENT;
 			goto error;
+		}
 	} else {
 		str_length = strlen(dev->_defaultname);
 		dev->_filename = kmemdup(dev->_defaultname, str_length + 1,
 					 GFP_KERNEL);
 
-		if (!dev->_filename)
+		if (!dev->_filename) {
+			err = -ENOENT;
 			goto error;
+		}
 	}
 
 	/* Default if filename is empty string */
@@ -828,7 +835,7 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
 	dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ?
 		(WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
 
-	retval = cx25821_sram_channel_setup_upstream(dev, sram_ch,
+	err = cx25821_sram_channel_setup_upstream(dev, sram_ch,
 			dev->_line_size, 0);
 
 	/* setup fifo + format */
@@ -838,8 +845,8 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
 	dev->upstream_databuf_size = data_frame_size * 2;
 
 	/* Allocating buffers and prepare RISC program */
-	retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size);
-	if (retval < 0) {
+	err = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size);
+	if (err < 0) {
 		pr_err("%s: Failed to set up Video upstream buffers!\n",
 		       dev->name);
 		goto error;
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
index 0a80245..53b16dd 100644
--- a/drivers/media/pci/cx25821/cx25821-video.c
+++ b/drivers/media/pci/cx25821/cx25821-video.c
@@ -291,9 +291,9 @@ int cx25821_start_video_dma(struct cx25821_dev *dev,
 	return 0;
 }
 
-int cx25821_restart_video_queue(struct cx25821_dev *dev,
-				struct cx25821_dmaqueue *q,
-				struct sram_channel *channel)
+static int cx25821_restart_video_queue(struct cx25821_dev *dev,
+				       struct cx25821_dmaqueue *q,
+				       struct sram_channel *channel)
 {
 	struct cx25821_buffer *buf, *prev;
 	struct list_head *item;
@@ -342,7 +342,7 @@ int cx25821_restart_video_queue(struct cx25821_dev *dev,
 	}
 }
 
-void cx25821_vid_timeout(unsigned long data)
+static void cx25821_vid_timeout(unsigned long data)
 {
 	struct cx25821_data *timeout_data = (struct cx25821_data *)data;
 	struct cx25821_dev *dev = timeout_data->dev;
diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c
index 3aa6856..d2de1a9 100644
--- a/drivers/media/pci/cx88/cx88-alsa.c
+++ b/drivers/media/pci/cx88/cx88-alsa.c
@@ -45,11 +45,15 @@
 #include "cx88.h"
 #include "cx88-reg.h"
 
-#define dprintk(level,fmt, arg...)	if (debug >= level) \
-	printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg)
-
-#define dprintk_core(level,fmt, arg...)	if (debug >= level) \
-	printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg)
+#define dprintk(level, fmt, arg...) do {				\
+	if (debug + 1 > level)						\
+		printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg);\
+} while(0)
+
+#define dprintk_core(level, fmt, arg...) do {				\
+	if (debug + 1 > level)						\
+		printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg);\
+} while(0)
 
 /****************************************************************************
 	Data type declarations - Can be moded to a header file later
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index 62184eb..a6ff8a6 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -53,9 +53,10 @@ static unsigned int debug;
 module_param(debug,int,0644);
 MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
 
-#define dprintk(level,fmt, arg...)	if (debug >= level) \
-	printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg)
-
+#define dprintk(level, fmt, arg...) do {				      \
+	if (debug + 1 > level)						      \
+		printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg); \
+} while(0)
 
 /* ------------------------------------------------------------------ */
 
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
index c97b174..19a5875 100644
--- a/drivers/media/pci/cx88/cx88-core.c
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -646,22 +646,22 @@ int cx88_reset(struct cx88_core *core)
 
 /* ------------------------------------------------------------------ */
 
-static unsigned int inline norm_swidth(v4l2_std_id norm)
+static inline unsigned int norm_swidth(v4l2_std_id norm)
 {
 	return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
 }
 
-static unsigned int inline norm_hdelay(v4l2_std_id norm)
+static inline unsigned int norm_hdelay(v4l2_std_id norm)
 {
 	return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
 }
 
-static unsigned int inline norm_vdelay(v4l2_std_id norm)
+static inline unsigned int norm_vdelay(v4l2_std_id norm)
 {
 	return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
 }
 
-static unsigned int inline norm_fsc8(v4l2_std_id norm)
+static inline unsigned int norm_fsc8(v4l2_std_id norm)
 {
 	if (norm & V4L2_STD_PAL_M)
 		return 28604892;      // 3.575611 MHz
@@ -681,7 +681,7 @@ static unsigned int inline norm_fsc8(v4l2_std_id norm)
 	return 35468950;      // 4.43361875 MHz +/- 5 Hz
 }
 
-static unsigned int inline norm_htotal(v4l2_std_id norm)
+static inline unsigned int norm_htotal(v4l2_std_id norm)
 {
 
 	unsigned int fsc4=norm_fsc8(norm)/2;
@@ -692,7 +692,7 @@ static unsigned int inline norm_htotal(v4l2_std_id norm)
 				((fsc4+262)/525*1001+15000)/30000;
 }
 
-static unsigned int inline norm_vbipack(v4l2_std_id norm)
+static inline unsigned int norm_vbipack(v4l2_std_id norm)
 {
 	return (norm & V4L2_STD_625_50) ? 511 : 400;
 }
diff --git a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c
index ebf448c..f29e18c 100644
--- a/drivers/media/pci/cx88/cx88-input.c
+++ b/drivers/media/pci/cx88/cx88-input.c
@@ -248,7 +248,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
 	struct cx88_IR *ir;
 	struct rc_dev *dev;
 	char *ir_codes = NULL;
-	u64 rc_type = RC_TYPE_OTHER;
+	u64 rc_type = RC_BIT_OTHER;
 	int err = -ENOMEM;
 	u32 hardware_mask = 0;	/* For devices with a hardware mask, when
 				 * used with a full-code IR table
@@ -416,7 +416,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
 		break;
 	case CX88_BOARD_TWINHAN_VP1027_DVBS:
 		ir_codes         = RC_MAP_TWINHAN_VP1027_DVBS;
-		rc_type          = RC_TYPE_NEC;
+		rc_type          = RC_BIT_NEC;
 		ir->sampling     = 0xff00; /* address */
 		break;
 	}
@@ -592,7 +592,7 @@ void cx88_i2c_init_ir(struct cx88_core *core)
 	case CX88_BOARD_LEADTEK_PVR2000:
 		addr_list = pvr2000_addr_list;
 		core->init_data.name = "cx88 Leadtek PVR 2000 remote";
-		core->init_data.type = RC_TYPE_UNKNOWN;
+		core->init_data.type = RC_BIT_UNKNOWN;
 		core->init_data.get_key = get_key_pvr2000;
 		core->init_data.ir_codes = RC_MAP_EMPTY;
 		break;
@@ -613,7 +613,7 @@ void cx88_i2c_init_ir(struct cx88_core *core)
 			/* Hauppauge XVR */
 			core->init_data.name = "cx88 Hauppauge XVR remote";
 			core->init_data.ir_codes = RC_MAP_HAUPPAUGE;
-			core->init_data.type = RC_TYPE_RC5;
+			core->init_data.type = RC_BIT_RC5;
 			core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
 
 			info.platform_data = &core->init_data;
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
index d154bc1..d46b008 100644
--- a/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -45,11 +45,15 @@ static unsigned int debug;
 module_param(debug,int,0644);
 MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
 
-#define dprintk(level,fmt, arg...)	if (debug >= level) \
-	printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg)
+#define dprintk(level, fmt, arg...) do {				       \
+	if (debug + 1 > level)						       \
+		printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg); \
+} while(0)
 
-#define mpeg_dbg(level,fmt, arg...)	if (debug >= level) \
-	printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg)
+#define mpeg_dbg(level, fmt, arg...) do {				  \
+	if (debug + 1 > level)						  \
+		printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg); \
+} while(0)
 
 #if defined(CONFIG_MODULES) && defined(MODULE)
 static void request_module_async(struct work_struct *work)
@@ -217,8 +221,7 @@ static int cx8802_restart_queue(struct cx8802_dev    *dev,
 				return 0;
 			buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
 			if (NULL == prev) {
-				list_del(&buf->vb.queue);
-				list_add_tail(&buf->vb.queue,&q->active);
+				list_move_tail(&buf->vb.queue, &q->active);
 				cx8802_start_dma(dev, q, buf);
 				buf->vb.state = VIDEOBUF_ACTIVE;
 				buf->count    = q->count++;
@@ -229,8 +232,7 @@ static int cx8802_restart_queue(struct cx8802_dev    *dev,
 			} else if (prev->vb.width  == buf->vb.width  &&
 				   prev->vb.height == buf->vb.height &&
 				   prev->fmt       == buf->fmt) {
-				list_del(&buf->vb.queue);
-				list_add_tail(&buf->vb.queue,&q->active);
+				list_move_tail(&buf->vb.queue, &q->active);
 				buf->vb.state = VIDEOBUF_ACTIVE;
 				buf->count    = q->count++;
 				prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index 44ffc8b..ba0dba4 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -94,13 +94,13 @@ enum cx8802_board_access {
 /* ----------------------------------------------------------- */
 /* tv norms                                                    */
 
-static unsigned int inline norm_maxw(v4l2_std_id norm)
+static inline unsigned int norm_maxw(v4l2_std_id norm)
 {
 	return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
 }
 
 
-static unsigned int inline norm_maxh(v4l2_std_id norm)
+static inline unsigned int norm_maxh(v4l2_std_id norm)
 {
 	return (norm & V4L2_STD_625_50) ? 576 : 480;
 }
diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c
index a609b3a..f288ffc 100644
--- a/drivers/media/pci/dm1105/dm1105.c
+++ b/drivers/media/pci/dm1105/dm1105.c
@@ -736,7 +736,7 @@ static irqreturn_t dm1105_irq(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
+static int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
 {
 	struct rc_dev *dev;
 	int err = -ENOMEM;
@@ -776,7 +776,7 @@ int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
 	return 0;
 }
 
-void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105)
+static void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105)
 {
 	rc_unregister_device(dm1105->ir.dev);
 }
@@ -1128,8 +1128,10 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
 	INIT_WORK(&dev->work, dm1105_dmx_buffer);
 	sprintf(dev->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num);
 	dev->wq = create_singlethread_workqueue(dev->wqn);
-	if (!dev->wq)
+	if (!dev->wq) {
+		ret = -ENOMEM;
 		goto err_dvb_net;
+	}
 
 	ret = request_irq(pdev->irq, dm1105_irq, IRQF_SHARED,
 						DRIVER_NAME, dev);
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-main.c b/drivers/media/pci/ivtv/ivtv-alsa-main.c
index 8deab16..4a221c6 100644
--- a/drivers/media/pci/ivtv/ivtv-alsa-main.c
+++ b/drivers/media/pci/ivtv/ivtv-alsa-main.c
@@ -205,7 +205,7 @@ err_exit:
 	return ret;
 }
 
-int ivtv_alsa_load(struct ivtv *itv)
+static int __init ivtv_alsa_load(struct ivtv *itv)
 {
 	struct v4l2_device *v4l2_dev = &itv->v4l2_dev;
 	struct ivtv_stream *s;
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-pcm.c b/drivers/media/pci/ivtv/ivtv-alsa-pcm.c
index f7022bd..e1863db 100644
--- a/drivers/media/pci/ivtv/ivtv-alsa-pcm.c
+++ b/drivers/media/pci/ivtv/ivtv-alsa-pcm.c
@@ -37,6 +37,7 @@
 #include "ivtv-streams.h"
 #include "ivtv-fileops.h"
 #include "ivtv-alsa.h"
+#include "ivtv-alsa-pcm.h"
 
 static unsigned int pcm_debug;
 module_param(pcm_debug, int, 0644);
@@ -69,8 +70,9 @@ static struct snd_pcm_hardware snd_ivtv_hw_capture = {
 	.periods_max = 98,		/* 12544, */
 };
 
-void ivtv_alsa_announce_pcm_data(struct snd_ivtv_card *itvsc, u8 *pcm_data,
-				 size_t num_bytes)
+static void ivtv_alsa_announce_pcm_data(struct snd_ivtv_card *itvsc,
+					u8 *pcm_data,
+					size_t num_bytes)
 {
 	struct snd_pcm_substream *substream;
 	struct snd_pcm_runtime *runtime;
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-pcm.h b/drivers/media/pci/ivtv/ivtv-alsa-pcm.h
index 5ab1831..23dfe0d 100644
--- a/drivers/media/pci/ivtv/ivtv-alsa-pcm.h
+++ b/drivers/media/pci/ivtv/ivtv-alsa-pcm.h
@@ -21,7 +21,3 @@
  */
 
 int __init snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc);
-
-/* Used by ivtv driver to announce the PCM data to the module */
-void ivtv_alsa_announce_pcm_data(struct snd_ivtv_card *card, u8 *pcm_data,
-				 size_t num_bytes);
diff --git a/drivers/media/pci/ivtv/ivtv-firmware.c b/drivers/media/pci/ivtv/ivtv-firmware.c
index 6ec7705..68387d4 100644
--- a/drivers/media/pci/ivtv/ivtv-firmware.c
+++ b/drivers/media/pci/ivtv/ivtv-firmware.c
@@ -276,7 +276,7 @@ void ivtv_init_mpeg_decoder(struct ivtv *itv)
 }
 
 /* Try to restart the card & restore previous settings */
-int ivtv_firmware_restart(struct ivtv *itv)
+static int ivtv_firmware_restart(struct ivtv *itv)
 {
 	int rc = 0;
 	v4l2_std_id std;
diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c
index d47f41a..46e262b 100644
--- a/drivers/media/pci/ivtv/ivtv-i2c.c
+++ b/drivers/media/pci/ivtv/ivtv-i2c.c
@@ -200,21 +200,21 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr)
 		init_data->ir_codes = RC_MAP_AVERMEDIA_CARDBUS;
 		init_data->internal_get_key_func =
 					IR_KBD_GET_KEY_AVERMEDIA_CARDBUS;
-		init_data->type = RC_TYPE_OTHER;
+		init_data->type = RC_BIT_OTHER;
 		init_data->name = "AVerMedia AVerTV card";
 		break;
 	case IVTV_HW_I2C_IR_RX_HAUP_EXT:
 	case IVTV_HW_I2C_IR_RX_HAUP_INT:
 		init_data->ir_codes = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
-		init_data->type = RC_TYPE_RC5;
+		init_data->type = RC_BIT_RC5;
 		init_data->name = itv->card_name;
 		break;
 	case IVTV_HW_Z8F0811_IR_RX_HAUP:
 		/* Default to grey remote */
 		init_data->ir_codes = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-		init_data->type = RC_TYPE_RC5;
+		init_data->type = RC_BIT_RC5;
 		init_data->name = itv->card_name;
 		break;
 	case IVTV_HW_I2C_IR_RX_ADAPTEC:
@@ -222,7 +222,7 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr)
 		init_data->name = itv->card_name;
 		/* FIXME: The protocol and RC_MAP needs to be corrected */
 		init_data->ir_codes = RC_MAP_EMPTY;
-		init_data->type = RC_TYPE_UNKNOWN;
+		init_data->type = RC_BIT_UNKNOWN;
 		break;
 	}
 
diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c
index 949ae23..7a8b0d0 100644
--- a/drivers/media/pci/ivtv/ivtv-ioctl.c
+++ b/drivers/media/pci/ivtv/ivtv-ioctl.c
@@ -993,7 +993,7 @@ int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
 	v4l2_std_id std;
 	int i;
 
-	if (inp < 0 || inp >= itv->nof_inputs)
+	if (inp >= itv->nof_inputs)
 		return -EINVAL;
 
 	if (inp == itv->active_input) {
@@ -1168,7 +1168,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
 	}
 }
 
-int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
+static int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
 {
 	struct ivtv *itv = fh2id(fh)->itv;
 
diff --git a/drivers/media/pci/mantis/mantis_input.c b/drivers/media/pci/mantis/mantis_input.c
index db6d54d..0e5252e 100644
--- a/drivers/media/pci/mantis/mantis_input.c
+++ b/drivers/media/pci/mantis/mantis_input.c
@@ -18,6 +18,8 @@
 	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#if 0 /* Currently unused */
+
 #include <media/rc-core.h>
 #include <linux/pci.h>
 
@@ -150,10 +152,11 @@ out:
 	return err;
 }
 
-int mantis_exit(struct mantis_pci *mantis)
+int mantis_init_exit(struct mantis_pci *mantis)
 {
 	rc_unregister_device(mantis->rc);
 	rc_map_unregister(&ir_mantis_map);
 	return 0;
 }
 
+#endif
diff --git a/drivers/media/pci/mantis/mantis_uart.c b/drivers/media/pci/mantis/mantis_uart.c
index 85e9778..a707192 100644
--- a/drivers/media/pci/mantis/mantis_uart.c
+++ b/drivers/media/pci/mantis/mantis_uart.c
@@ -61,7 +61,7 @@ static struct {
 
 #define UART_MAX_BUF			16
 
-int mantis_uart_read(struct mantis_pci *mantis, u8 *data)
+static int mantis_uart_read(struct mantis_pci *mantis, u8 *data)
 {
 	struct mantis_hwconfig *config = mantis->hwconfig;
 	u32 stat = 0, i;
diff --git a/drivers/media/pci/mantis/mantis_vp1033.c b/drivers/media/pci/mantis/mantis_vp1033.c
index ad013e9..115003e 100644
--- a/drivers/media/pci/mantis/mantis_vp1033.c
+++ b/drivers/media/pci/mantis/mantis_vp1033.c
@@ -83,7 +83,7 @@ u8 lgtdqcs001f_inittab[] = {
 #define MANTIS_MODEL_NAME	"VP-1033"
 #define MANTIS_DEV_TYPE		"DVB-S/DSS"
 
-int lgtdqcs001f_tuner_set(struct dvb_frontend *fe)
+static int lgtdqcs001f_tuner_set(struct dvb_frontend *fe)
 {
 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
 	struct mantis_pci *mantis	= fe->dvb->priv;
@@ -115,8 +115,8 @@ int lgtdqcs001f_tuner_set(struct dvb_frontend *fe)
 	return 0;
 }
 
-int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe,
-				u32 srate, u32 ratio)
+static int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe,
+				       u32 srate, u32 ratio)
 {
 	u8 aclk = 0;
 	u8 bclk = 0;
diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c
index e5a76da..ae7d320 100644
--- a/drivers/media/pci/meye/meye.c
+++ b/drivers/media/pci/meye/meye.c
@@ -1945,7 +1945,7 @@ static struct pci_driver meye_driver = {
 static int __init meye_init(void)
 {
 	gbuffers = max(2, min((int)gbuffers, MEYE_MAX_BUFNBRS));
-	if (gbufsize < 0 || gbufsize > MEYE_MAX_BUFSIZE)
+	if (gbufsize > MEYE_MAX_BUFSIZE)
 		gbufsize = MEYE_MAX_BUFSIZE;
 	gbufsize = PAGE_ALIGN(gbufsize);
 	printk(KERN_INFO "meye: using %d buffers with %dk (%dk total) "
diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c
index 96a13ed..b38bce5 100644
--- a/drivers/media/pci/ngene/ngene-cards.c
+++ b/drivers/media/pci/ngene/ngene-cards.c
@@ -425,8 +425,10 @@ static int ReadEEProm(struct i2c_adapter *adapter,
 		status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length);
 		if (!status) {
 			*pLength = EETag[2];
+#if 0
 			if (Length < EETag[2])
-				; /*status=STATUS_BUFFER_OVERFLOW; */
+				status = STATUS_BUFFER_OVERFLOW;
+#endif
 		}
 	}
 	return status;
diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c
index c8e0d5b..8eeec4f 100644
--- a/drivers/media/pci/ngene/ngene-core.c
+++ b/drivers/media/pci/ngene/ngene-core.c
@@ -752,8 +752,8 @@ void set_transfer(struct ngene_channel *chan, int state)
 		if (chan->mode & NGENE_IO_TSIN)
 			chan->pBufferExchange = tsin_exchange;
 		spin_unlock_irq(&chan->state_lock);
-	} else
-		;/* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n",
+	}
+		/* else printk(KERN_INFO DEVICE_NAME ": lock=%08x\n",
 			   ngreadl(0x9310)); */
 
 	ret = ngene_command_stream_control(dev, chan->number,
@@ -1691,7 +1691,8 @@ int __devinit ngene_probe(struct pci_dev *pci_dev,
 	dev->i2c_current_bus = -1;
 
 	/* Register DVB adapters and devices for both channels */
-	if (init_channels(dev) < 0)
+	stat = init_channels(dev);
+	if (stat < 0)
 		goto fail2;
 
 	return 0;
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index f2b37e0..8976d0e 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -944,8 +944,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
 
 	/* board config */
 	dev->board = pci_id->driver_data;
-	if (card[dev->nr] >= 0 &&
-	    card[dev->nr] < saa7134_bcount)
+	if ((unsigned)card[dev->nr] < saa7134_bcount)
 		dev->board = card[dev->nr];
 	if (SAA7134_BOARD_UNKNOWN == dev->board)
 		must_configure_manually(0);
diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c
index 0f78f5e..e761262 100644
--- a/drivers/media/pci/saa7134/saa7134-input.c
+++ b/drivers/media/pci/saa7134/saa7134-input.c
@@ -990,7 +990,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
 		dev->init_data.name = "BeholdTV";
 		dev->init_data.get_key = get_key_beholdm6xx;
 		dev->init_data.ir_codes = RC_MAP_BEHOLD;
-		dev->init_data.type = RC_TYPE_NEC;
+		dev->init_data.type = RC_BIT_NEC;
 		info.addr = 0x2d;
 		break;
 	case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 4a77124..3abf527 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -2511,7 +2511,7 @@ int saa7134_video_init1(struct saa7134_dev *dev)
 	/* sanitycheck insmod options */
 	if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
 		gbuffers = 2;
-	if (gbufsize < 0 || gbufsize > gbufsize_max)
+	if (gbufsize > gbufsize_max)
 		gbufsize = gbufsize_max;
 	gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
 
diff --git a/drivers/media/pci/saa7164/saa7164-api.c b/drivers/media/pci/saa7164/saa7164-api.c
index eff7135..e042963 100644
--- a/drivers/media/pci/saa7164/saa7164-api.c
+++ b/drivers/media/pci/saa7164/saa7164-api.c
@@ -165,7 +165,7 @@ int saa7164_api_set_vbi_format(struct saa7164_port *port)
 	return ret;
 }
 
-int saa7164_api_set_gop_size(struct saa7164_port *port)
+static int saa7164_api_set_gop_size(struct saa7164_port *port)
 {
 	struct saa7164_dev *dev = port->dev;
 	struct tmComResEncVideoGopStructure gs;
@@ -619,7 +619,7 @@ int saa7164_api_get_videomux(struct saa7164_port *port)
 	return ret;
 }
 
-int saa7164_api_set_dif(struct saa7164_port *port, u8 reg, u8 val)
+static int saa7164_api_set_dif(struct saa7164_port *port, u8 reg, u8 val)
 {
 	struct saa7164_dev *dev = port->dev;
 
@@ -822,8 +822,8 @@ int saa7164_api_read_eeprom(struct saa7164_dev *dev, u8 *buf, int buflen)
 		&reg[0], 128, buf);
 }
 
-int saa7164_api_configure_port_vbi(struct saa7164_dev *dev,
-	struct saa7164_port *port)
+static int saa7164_api_configure_port_vbi(struct saa7164_dev *dev,
+					  struct saa7164_port *port)
 {
 	struct tmComResVBIFormatDescrHeader *fmt = &port->vbi_fmt_ntsc;
 
@@ -858,9 +858,10 @@ int saa7164_api_configure_port_vbi(struct saa7164_dev *dev,
 	return 0;
 }
 
-int saa7164_api_configure_port_mpeg2ts(struct saa7164_dev *dev,
-	struct saa7164_port *port,
-	struct tmComResTSFormatDescrHeader *tsfmt)
+static int
+saa7164_api_configure_port_mpeg2ts(struct saa7164_dev *dev,
+				   struct saa7164_port *port,
+				   struct tmComResTSFormatDescrHeader *tsfmt)
 {
 	dprintk(DBGLVL_API, "    bFormatIndex = 0x%x\n", tsfmt->bFormatIndex);
 	dprintk(DBGLVL_API, "    bDataOffset  = 0x%x\n", tsfmt->bDataOffset);
@@ -892,9 +893,10 @@ int saa7164_api_configure_port_mpeg2ts(struct saa7164_dev *dev,
 	return 0;
 }
 
-int saa7164_api_configure_port_mpeg2ps(struct saa7164_dev *dev,
-	struct saa7164_port *port,
-	struct tmComResPSFormatDescrHeader *fmt)
+static int
+saa7164_api_configure_port_mpeg2ps(struct saa7164_dev *dev,
+				   struct saa7164_port *port,
+				   struct tmComResPSFormatDescrHeader *fmt)
 {
 	dprintk(DBGLVL_API, "    bFormatIndex = 0x%x\n", fmt->bFormatIndex);
 	dprintk(DBGLVL_API, "    wPacketLength= 0x%x\n", fmt->wPacketLength);
@@ -925,7 +927,7 @@ int saa7164_api_configure_port_mpeg2ps(struct saa7164_dev *dev,
 	return 0;
 }
 
-int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
+static int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
 {
 	struct saa7164_port *tsport = NULL;
 	struct saa7164_port *encport = NULL;
@@ -1486,7 +1488,7 @@ int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr, u32 datalen,
 	return ret == SAA_OK ? 0 : -EIO;
 }
 
-int saa7164_api_modify_gpio(struct saa7164_dev *dev, u8 unitid,
+static int saa7164_api_modify_gpio(struct saa7164_dev *dev, u8 unitid,
 	u8 pin, u8 state)
 {
 	int ret;
diff --git a/drivers/media/pci/saa7164/saa7164-bus.c b/drivers/media/pci/saa7164/saa7164-bus.c
index a7f58a9..5f6f309 100644
--- a/drivers/media/pci/saa7164/saa7164-bus.c
+++ b/drivers/media/pci/saa7164/saa7164-bus.c
@@ -81,7 +81,7 @@ void saa7164_bus_dump(struct saa7164_dev *dev)
 }
 
 /* Intensionally throw a BUG() if the state of the message bus looks corrupt */
-void saa7164_bus_verify(struct saa7164_dev *dev)
+static void saa7164_bus_verify(struct saa7164_dev *dev)
 {
 	struct tmComResBusInfo *b = &dev->bus;
 	int bug = 0;
@@ -106,8 +106,8 @@ void saa7164_bus_verify(struct saa7164_dev *dev)
 	}
 }
 
-void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo* m,
-	void *buf)
+static void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo *m,
+				void *buf)
 {
 	dprintk(DBGLVL_BUS, "Dumping msg structure:\n");
 	dprintk(DBGLVL_BUS, " .id               = %d\n",   m->id);
diff --git a/drivers/media/pci/saa7164/saa7164-cmd.c b/drivers/media/pci/saa7164/saa7164-cmd.c
index 62fac7f..cfabcba 100644
--- a/drivers/media/pci/saa7164/saa7164-cmd.c
+++ b/drivers/media/pci/saa7164/saa7164-cmd.c
@@ -23,7 +23,7 @@
 
 #include "saa7164.h"
 
-int saa7164_cmd_alloc_seqno(struct saa7164_dev *dev)
+static int saa7164_cmd_alloc_seqno(struct saa7164_dev *dev)
 {
 	int i, ret = -1;
 
@@ -42,7 +42,7 @@ int saa7164_cmd_alloc_seqno(struct saa7164_dev *dev)
 	return ret;
 }
 
-void saa7164_cmd_free_seqno(struct saa7164_dev *dev, u8 seqno)
+static void saa7164_cmd_free_seqno(struct saa7164_dev *dev, u8 seqno)
 {
 	mutex_lock(&dev->lock);
 	if ((dev->cmds[seqno].inuse == 1) &&
@@ -54,7 +54,7 @@ void saa7164_cmd_free_seqno(struct saa7164_dev *dev, u8 seqno)
 	mutex_unlock(&dev->lock);
 }
 
-void saa7164_cmd_timeout_seqno(struct saa7164_dev *dev, u8 seqno)
+static void saa7164_cmd_timeout_seqno(struct saa7164_dev *dev, u8 seqno)
 {
 	mutex_lock(&dev->lock);
 	if ((dev->cmds[seqno].inuse == 1) &&
@@ -64,7 +64,7 @@ void saa7164_cmd_timeout_seqno(struct saa7164_dev *dev, u8 seqno)
 	mutex_unlock(&dev->lock);
 }
 
-u32 saa7164_cmd_timeout_get(struct saa7164_dev *dev, u8 seqno)
+static u32 saa7164_cmd_timeout_get(struct saa7164_dev *dev, u8 seqno)
 {
 	int ret = 0;
 
@@ -132,7 +132,7 @@ int saa7164_irq_dequeue(struct saa7164_dev *dev)
 
 /* Commands to the f/w get marshelled to/from this code then onto the PCI
  * -bus/c running buffer. */
-int saa7164_cmd_dequeue(struct saa7164_dev *dev)
+static int saa7164_cmd_dequeue(struct saa7164_dev *dev)
 {
 	int loop = 1;
 	int ret;
@@ -186,8 +186,8 @@ int saa7164_cmd_dequeue(struct saa7164_dev *dev)
 	return SAA_OK;
 }
 
-int saa7164_cmd_set(struct saa7164_dev *dev, struct tmComResInfo *msg,
-	void *buf)
+static int saa7164_cmd_set(struct saa7164_dev *dev, struct tmComResInfo *msg,
+			   void *buf)
 {
 	struct tmComResBusInfo *bus = &dev->bus;
 	u8 cmd_sent;
@@ -259,7 +259,7 @@ out:
 /* Wait for a signal event, without holding a mutex. Either return TIMEOUT if
  * the event never occurred, or SAA_OK if it was signaled during the wait.
  */
-int saa7164_cmd_wait(struct saa7164_dev *dev, u8 seqno)
+static int saa7164_cmd_wait(struct saa7164_dev *dev, u8 seqno)
 {
 	wait_queue_head_t *q = NULL;
 	int ret = SAA_BUS_TIMEOUT;
diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c
index 2c9ad87..063047f 100644
--- a/drivers/media/pci/saa7164/saa7164-core.c
+++ b/drivers/media/pci/saa7164/saa7164-core.c
@@ -410,7 +410,7 @@ static void saa7164_work_enchandler(struct work_struct *w)
 		} else
 			rp = (port->last_svc_rp + 1) % 8;
 
-		if ((rp < 0) || (rp > (port->hwcfg.buffercount - 1))) {
+		if (rp > (port->hwcfg.buffercount - 1)) {
 			printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
 			break;
 		}
@@ -486,7 +486,7 @@ static void saa7164_work_vbihandler(struct work_struct *w)
 		} else
 			rp = (port->last_svc_rp + 1) % 8;
 
-		if ((rp < 0) || (rp > (port->hwcfg.buffercount - 1))) {
+		if (rp > (port->hwcfg.buffercount - 1)) {
 			printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
 			break;
 		}
diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c
index a9ed686..994018e 100644
--- a/drivers/media/pci/saa7164/saa7164-encoder.c
+++ b/drivers/media/pci/saa7164/saa7164-encoder.c
@@ -1101,7 +1101,8 @@ static int fops_release(struct file *file)
 	return 0;
 }
 
-struct saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port)
+static struct
+saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port)
 {
 	struct saa7164_user_buffer *ubuf = NULL;
 	struct saa7164_dev *dev = port->dev;
@@ -1287,8 +1288,8 @@ static const struct v4l2_file_operations mpeg_fops = {
 	.unlocked_ioctl	= video_ioctl2,
 };
 
-int saa7164_g_chip_ident(struct file *file, void *fh,
-	struct v4l2_dbg_chip_ident *chip)
+static int saa7164_g_chip_ident(struct file *file, void *fh,
+				struct v4l2_dbg_chip_ident *chip)
 {
 	struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port;
 	struct saa7164_dev *dev = port->dev;
@@ -1297,8 +1298,8 @@ int saa7164_g_chip_ident(struct file *file, void *fh,
 	return 0;
 }
 
-int saa7164_g_register(struct file *file, void *fh,
-	struct v4l2_dbg_register *reg)
+static int saa7164_g_register(struct file *file, void *fh,
+			      struct v4l2_dbg_register *reg)
 {
 	struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port;
 	struct saa7164_dev *dev = port->dev;
@@ -1310,8 +1311,8 @@ int saa7164_g_register(struct file *file, void *fh,
 	return 0;
 }
 
-int saa7164_s_register(struct file *file, void *fh,
-	struct v4l2_dbg_register *reg)
+static int saa7164_s_register(struct file *file, void *fh,
+			      struct v4l2_dbg_register *reg)
 {
 	struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port;
 	struct saa7164_dev *dev = port->dev;
diff --git a/drivers/media/pci/saa7164/saa7164-fw.c b/drivers/media/pci/saa7164/saa7164-fw.c
index a266bf0..8676320 100644
--- a/drivers/media/pci/saa7164/saa7164-fw.c
+++ b/drivers/media/pci/saa7164/saa7164-fw.c
@@ -37,7 +37,7 @@ struct fw_header {
 	u32	version;
 };
 
-int saa7164_dl_wait_ack(struct saa7164_dev *dev, u32 reg)
+static int saa7164_dl_wait_ack(struct saa7164_dev *dev, u32 reg)
 {
 	u32 timeout = SAA_DEVICE_TIMEOUT;
 	while ((saa7164_readl(reg) & 0x01) == 0) {
@@ -53,7 +53,7 @@ int saa7164_dl_wait_ack(struct saa7164_dev *dev, u32 reg)
 	return 0;
 }
 
-int saa7164_dl_wait_clr(struct saa7164_dev *dev, u32 reg)
+static int saa7164_dl_wait_clr(struct saa7164_dev *dev, u32 reg)
 {
 	u32 timeout = SAA_DEVICE_TIMEOUT;
 	while (saa7164_readl(reg) & 0x01) {
@@ -71,8 +71,8 @@ int saa7164_dl_wait_clr(struct saa7164_dev *dev, u32 reg)
 
 /* TODO: move dlflags into dev-> and change to write/readl/b */
 /* TODO: Excessive levels of debug */
-int saa7164_downloadimage(struct saa7164_dev *dev, u8 *src, u32 srcsize,
-	u32 dlflags, u8 *dst, u32 dstsize)
+static int saa7164_downloadimage(struct saa7164_dev *dev, u8 *src, u32 srcsize,
+				 u32 dlflags, u8 *dst, u32 dstsize)
 {
 	u32 reg, timeout, offset;
 	u8 *srcbuf = NULL;
diff --git a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c
index d8e6c8f..b453229 100644
--- a/drivers/media/pci/saa7164/saa7164-vbi.c
+++ b/drivers/media/pci/saa7164/saa7164-vbi.c
@@ -984,7 +984,8 @@ out:
 	return ret;
 }
 
-int saa7164_vbi_fmt(struct file *file, void *priv, struct v4l2_format *f)
+static int saa7164_vbi_fmt(struct file *file, void *priv,
+			   struct v4l2_format *f)
 {
 	/* ntsc */
 	f->fmt.vbi.samples_per_line = 1600;
@@ -1047,7 +1048,8 @@ static int fops_release(struct file *file)
 	return 0;
 }
 
-struct saa7164_user_buffer *saa7164_vbi_next_buf(struct saa7164_port *port)
+static struct
+saa7164_user_buffer *saa7164_vbi_next_buf(struct saa7164_port *port)
 {
 	struct saa7164_user_buffer *ubuf = NULL;
 	struct saa7164_dev *dev = port->dev;
diff --git a/drivers/media/pci/ttpci/av7110.h b/drivers/media/pci/ttpci/av7110.h
index 88b3b2d..a378662 100644
--- a/drivers/media/pci/ttpci/av7110.h
+++ b/drivers/media/pci/ttpci/av7110.h
@@ -6,6 +6,7 @@
 #include <linux/netdevice.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
+#include <linux/time.h>
 
 #include <linux/dvb/video.h>
 #include <linux/dvb/audio.h>
diff --git a/drivers/media/pci/ttpci/budget-av.c b/drivers/media/pci/ttpci/budget-av.c
index 12ddb53..1f8b1bb 100644
--- a/drivers/media/pci/ttpci/budget-av.c
+++ b/drivers/media/pci/ttpci/budget-av.c
@@ -1477,8 +1477,8 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
 
 	if (saa7113_init(budget_av) == 0) {
 		budget_av->has_saa7113 = 1;
-
-		if (0 != saa7146_vv_init(dev, &vv_data)) {
+		err = saa7146_vv_init(dev, &vv_data);
+		if (err != 0) {
 			/* fixme: proper cleanup here */
 			ERR("cannot init vv subsystem\n");
 			return err;
diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c
index cb2eb26..ec476ef 100644
--- a/drivers/media/platform/blackfin/bfin_capture.c
+++ b/drivers/media/platform/blackfin/bfin_capture.c
@@ -1050,19 +1050,7 @@ static struct platform_driver bcap_driver = {
 	.probe = bcap_probe,
 	.remove = __devexit_p(bcap_remove),
 };
-
-static __init int bcap_init(void)
-{
-	return platform_driver_register(&bcap_driver);
-}
-
-static __exit void bcap_exit(void)
-{
-	platform_driver_unregister(&bcap_driver);
-}
-
-module_init(bcap_init);
-module_exit(bcap_exit);
+module_platform_driver(bcap_driver);
 
 MODULE_DESCRIPTION("Analog Devices blackfin video capture driver");
 MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c
index cd04ae2..7b8b547 100644
--- a/drivers/media/platform/coda.c
+++ b/drivers/media/platform/coda.c
@@ -1540,7 +1540,7 @@ static irqreturn_t coda_irq_handler(int irq, void *data)
 	u32 wr_ptr, start_ptr;
 	struct coda_ctx *ctx;
 
-	__cancel_delayed_work(&dev->timeout);
+	cancel_delayed_work(&dev->timeout);
 
 	/* read status register to attend the IRQ */
 	coda_read(dev, CODA_REG_BIT_INT_STATUS);
@@ -1877,7 +1877,7 @@ static const struct coda_devtype coda_devdata[] = {
 
 static struct platform_device_id coda_platform_ids[] = {
 	{ .name = "coda-imx27", .driver_data = CODA_IMX27 },
-	{ .name = "coda-imx53", .driver_data = CODA_7541 },
+	{ .name = "coda-imx53", .driver_data = CODA_IMX53 },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(platform, coda_platform_ids);
diff --git a/drivers/media/platform/davinci/Kconfig b/drivers/media/platform/davinci/Kconfig
index 78e26d2..3c56037 100644
--- a/drivers/media/platform/davinci/Kconfig
+++ b/drivers/media/platform/davinci/Kconfig
@@ -101,7 +101,7 @@ config VIDEO_DM644X_VPBE
 	tristate "DM644X VPBE HW module"
 	depends on ARCH_DAVINCI_DM644x
 	select VIDEO_VPSS_SYSTEM
-	select VIDEOBUF_DMA_CONTIG
+	select VIDEOBUF2_DMA_CONTIG
 	help
 	    Enables VPBE modules used for display on a DM644x
 	    SoC.
diff --git a/drivers/media/platform/davinci/dm355_ccdc.c b/drivers/media/platform/davinci/dm355_ccdc.c
index ce0e413..030950d 100644
--- a/drivers/media/platform/davinci/dm355_ccdc.c
+++ b/drivers/media/platform/davinci/dm355_ccdc.c
@@ -1003,7 +1003,7 @@ static int __devinit dm355_ccdc_probe(struct platform_device *pdev)
 		status = PTR_ERR(ccdc_cfg.mclk);
 		goto fail_nomap;
 	}
-	if (clk_enable(ccdc_cfg.mclk)) {
+	if (clk_prepare_enable(ccdc_cfg.mclk)) {
 		status = -ENODEV;
 		goto fail_mclk;
 	}
@@ -1014,7 +1014,7 @@ static int __devinit dm355_ccdc_probe(struct platform_device *pdev)
 		status = PTR_ERR(ccdc_cfg.sclk);
 		goto fail_mclk;
 	}
-	if (clk_enable(ccdc_cfg.sclk)) {
+	if (clk_prepare_enable(ccdc_cfg.sclk)) {
 		status = -ENODEV;
 		goto fail_sclk;
 	}
@@ -1034,8 +1034,10 @@ static int __devinit dm355_ccdc_probe(struct platform_device *pdev)
 	printk(KERN_NOTICE "%s is registered with vpfe.\n", ccdc_hw_dev.name);
 	return 0;
 fail_sclk:
+	clk_disable_unprepare(ccdc_cfg.sclk);
 	clk_put(ccdc_cfg.sclk);
 fail_mclk:
+	clk_disable_unprepare(ccdc_cfg.mclk);
 	clk_put(ccdc_cfg.mclk);
 fail_nomap:
 	iounmap(ccdc_cfg.base_addr);
@@ -1050,6 +1052,8 @@ static int dm355_ccdc_remove(struct platform_device *pdev)
 {
 	struct resource	*res;
 
+	clk_disable_unprepare(ccdc_cfg.sclk);
+	clk_disable_unprepare(ccdc_cfg.mclk);
 	clk_put(ccdc_cfg.mclk);
 	clk_put(ccdc_cfg.sclk);
 	iounmap(ccdc_cfg.base_addr);
diff --git a/drivers/media/platform/davinci/dm644x_ccdc.c b/drivers/media/platform/davinci/dm644x_ccdc.c
index ee7942b..0215ab6 100644
--- a/drivers/media/platform/davinci/dm644x_ccdc.c
+++ b/drivers/media/platform/davinci/dm644x_ccdc.c
@@ -994,7 +994,7 @@ static int __devinit dm644x_ccdc_probe(struct platform_device *pdev)
 		status = PTR_ERR(ccdc_cfg.mclk);
 		goto fail_nomap;
 	}
-	if (clk_enable(ccdc_cfg.mclk)) {
+	if (clk_prepare_enable(ccdc_cfg.mclk)) {
 		status = -ENODEV;
 		goto fail_mclk;
 	}
@@ -1005,7 +1005,7 @@ static int __devinit dm644x_ccdc_probe(struct platform_device *pdev)
 		status = PTR_ERR(ccdc_cfg.sclk);
 		goto fail_mclk;
 	}
-	if (clk_enable(ccdc_cfg.sclk)) {
+	if (clk_prepare_enable(ccdc_cfg.sclk)) {
 		status = -ENODEV;
 		goto fail_sclk;
 	}
@@ -1013,8 +1013,10 @@ static int __devinit dm644x_ccdc_probe(struct platform_device *pdev)
 	printk(KERN_NOTICE "%s is registered with vpfe.\n", ccdc_hw_dev.name);
 	return 0;
 fail_sclk:
+	clk_disable_unprepare(ccdc_cfg.sclk);
 	clk_put(ccdc_cfg.sclk);
 fail_mclk:
+	clk_disable_unprepare(ccdc_cfg.mclk);
 	clk_put(ccdc_cfg.mclk);
 fail_nomap:
 	iounmap(ccdc_cfg.base_addr);
@@ -1029,6 +1031,8 @@ static int dm644x_ccdc_remove(struct platform_device *pdev)
 {
 	struct resource	*res;
 
+	clk_disable_unprepare(ccdc_cfg.mclk);
+	clk_disable_unprepare(ccdc_cfg.sclk);
 	clk_put(ccdc_cfg.mclk);
 	clk_put(ccdc_cfg.sclk);
 	iounmap(ccdc_cfg.base_addr);
@@ -1046,8 +1050,8 @@ static int dm644x_ccdc_suspend(struct device *dev)
 	/* Disable CCDC */
 	ccdc_enable(0);
 	/* Disable both master and slave clock */
-	clk_disable(ccdc_cfg.mclk);
-	clk_disable(ccdc_cfg.sclk);
+	clk_disable_unprepare(ccdc_cfg.mclk);
+	clk_disable_unprepare(ccdc_cfg.sclk);
 
 	return 0;
 }
@@ -1055,8 +1059,8 @@ static int dm644x_ccdc_suspend(struct device *dev)
 static int dm644x_ccdc_resume(struct device *dev)
 {
 	/* Enable both master and slave clock */
-	clk_enable(ccdc_cfg.mclk);
-	clk_enable(ccdc_cfg.sclk);
+	clk_prepare_enable(ccdc_cfg.mclk);
+	clk_prepare_enable(ccdc_cfg.sclk);
 	/* Restore CCDC context */
 	ccdc_restore_context();
 
diff --git a/drivers/media/platform/davinci/isif.c b/drivers/media/platform/davinci/isif.c
index b99d542..2c26c3e 100644
--- a/drivers/media/platform/davinci/isif.c
+++ b/drivers/media/platform/davinci/isif.c
@@ -1053,7 +1053,7 @@ static int __devinit isif_probe(struct platform_device *pdev)
 		status = PTR_ERR(isif_cfg.mclk);
 		goto fail_mclk;
 	}
-	if (clk_enable(isif_cfg.mclk)) {
+	if (clk_prepare_enable(isif_cfg.mclk)) {
 		status = -ENODEV;
 		goto fail_mclk;
 	}
@@ -1125,6 +1125,7 @@ fail_nobase_res:
 		i--;
 	}
 fail_mclk:
+	clk_disable_unprepare(isif_cfg.mclk);
 	clk_put(isif_cfg.mclk);
 	vpfe_unregister_ccdc_device(&isif_hw_dev);
 	return status;
@@ -1145,6 +1146,8 @@ static int isif_remove(struct platform_device *pdev)
 		i++;
 	}
 	vpfe_unregister_ccdc_device(&isif_hw_dev);
+	clk_disable_unprepare(isif_cfg.mclk);
+	clk_put(isif_cfg.mclk);
 	return 0;
 }
 
diff --git a/drivers/media/platform/davinci/vpbe.c b/drivers/media/platform/davinci/vpbe.c
index 69d7a58..7f5cf9b3 100644
--- a/drivers/media/platform/davinci/vpbe.c
+++ b/drivers/media/platform/davinci/vpbe.c
@@ -612,7 +612,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
 			ret =  PTR_ERR(vpbe_dev->dac_clk);
 			goto fail_mutex_unlock;
 		}
-		if (clk_enable(vpbe_dev->dac_clk)) {
+		if (clk_prepare_enable(vpbe_dev->dac_clk)) {
 			ret =  -ENODEV;
 			goto fail_mutex_unlock;
 		}
@@ -759,8 +759,10 @@ fail_kfree_encoders:
 fail_dev_unregister:
 	v4l2_device_unregister(&vpbe_dev->v4l2_dev);
 fail_clk_put:
-	if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0)
+	if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) {
+		clk_disable_unprepare(vpbe_dev->dac_clk);
 		clk_put(vpbe_dev->dac_clk);
+	}
 fail_mutex_unlock:
 	mutex_unlock(&vpbe_dev->lock);
 	return ret;
@@ -777,8 +779,10 @@ fail_mutex_unlock:
 static void vpbe_deinitialize(struct device *dev, struct vpbe_device *vpbe_dev)
 {
 	v4l2_device_unregister(&vpbe_dev->v4l2_dev);
-	if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0)
+	if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) {
+		clk_disable_unprepare(vpbe_dev->dac_clk);
 		clk_put(vpbe_dev->dac_clk);
+	}
 
 	kfree(vpbe_dev->amp);
 	kfree(vpbe_dev->encoders);
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c
index 161c776..2bfde79 100644
--- a/drivers/media/platform/davinci/vpbe_display.c
+++ b/drivers/media/platform/davinci/vpbe_display.c
@@ -47,6 +47,9 @@ static int debug;
 
 module_param(debug, int, 0644);
 
+static int vpbe_set_osd_display_params(struct vpbe_display *disp_dev,
+			struct vpbe_layer *layer);
+
 static int venc_is_second_field(struct vpbe_display *disp_dev)
 {
 	struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
@@ -73,10 +76,11 @@ static void vpbe_isr_even_field(struct vpbe_display *disp_obj,
 	if (layer->cur_frm == layer->next_frm)
 		return;
 	ktime_get_ts(&timevalue);
-	layer->cur_frm->ts.tv_sec = timevalue.tv_sec;
-	layer->cur_frm->ts.tv_usec = timevalue.tv_nsec / NSEC_PER_USEC;
-	layer->cur_frm->state = VIDEOBUF_DONE;
-	wake_up_interruptible(&layer->cur_frm->done);
+	layer->cur_frm->vb.v4l2_buf.timestamp.tv_sec =
+		timevalue.tv_sec;
+	layer->cur_frm->vb.v4l2_buf.timestamp.tv_usec =
+		timevalue.tv_nsec / NSEC_PER_USEC;
+	vb2_buffer_done(&layer->cur_frm->vb, VB2_BUF_STATE_DONE);
 	/* Make cur_frm pointing to next_frm */
 	layer->cur_frm = layer->next_frm;
 }
@@ -99,16 +103,14 @@ static void vpbe_isr_odd_field(struct vpbe_display *disp_obj,
 	 * otherwise hold on current frame
 	 * Get next from the buffer queue
 	 */
-	layer->next_frm = list_entry(
-				layer->dma_queue.next,
-				struct  videobuf_buffer,
-				queue);
+	layer->next_frm = list_entry(layer->dma_queue.next,
+			  struct  vpbe_disp_buffer, list);
 	/* Remove that from the buffer queue */
-	list_del(&layer->next_frm->queue);
+	list_del(&layer->next_frm->list);
 	spin_unlock(&disp_obj->dma_queue_lock);
 	/* Mark state of the frame to active */
-	layer->next_frm->state = VIDEOBUF_ACTIVE;
-	addr = videobuf_to_dma_contig(layer->next_frm);
+	layer->next_frm->vb.state = VB2_BUF_STATE_ACTIVE;
+	addr = vb2_dma_contig_plane_dma_addr(&layer->next_frm->vb, 0);
 	osd_device->ops.start_layer(osd_device,
 			layer->layer_info.id,
 			addr,
@@ -199,39 +201,29 @@ static irqreturn_t venc_isr(int irq, void *arg)
 
 /*
  * vpbe_buffer_prepare()
- * This is the callback function called from videobuf_qbuf() function
+ * This is the callback function called from vb2_qbuf() function
  * the buffer is prepared and user space virtual address is converted into
  * physical address
  */
-static int vpbe_buffer_prepare(struct videobuf_queue *q,
-				  struct videobuf_buffer *vb,
-				  enum v4l2_field field)
+static int vpbe_buffer_prepare(struct vb2_buffer *vb)
 {
-	struct vpbe_fh *fh = q->priv_data;
+	struct vpbe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_queue *q = vb->vb2_queue;
 	struct vpbe_layer *layer = fh->layer;
 	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 	unsigned long addr;
-	int ret;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
 				"vpbe_buffer_prepare\n");
 
-	/* If buffer is not initialized, initialize it */
-	if (VIDEOBUF_NEEDS_INIT == vb->state) {
-		vb->width = layer->pix_fmt.width;
-		vb->height = layer->pix_fmt.height;
-		vb->size = layer->pix_fmt.sizeimage;
-		vb->field = field;
-
-		ret = videobuf_iolock(q, vb, NULL);
-		if (ret < 0) {
-			v4l2_err(&vpbe_dev->v4l2_dev, "Failed to map \
-				user address\n");
+	if (vb->state != VB2_BUF_STATE_ACTIVE &&
+		vb->state != VB2_BUF_STATE_PREPARED) {
+		vb2_set_plane_payload(vb, 0, layer->pix_fmt.sizeimage);
+		if (vb2_plane_vaddr(vb, 0) &&
+		vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
 			return -EINVAL;
-		}
-
-		addr = videobuf_to_dma_contig(vb);
 
+		addr = vb2_dma_contig_plane_dma_addr(vb, 0);
 		if (q->streaming) {
 			if (!IS_ALIGNED(addr, 8)) {
 				v4l2_err(&vpbe_dev->v4l2_dev,
@@ -240,7 +232,6 @@ static int vpbe_buffer_prepare(struct videobuf_queue *q,
 				return -EINVAL;
 			}
 		}
-		vb->state = VIDEOBUF_PREPARED;
 	}
 	return 0;
 }
@@ -249,22 +240,26 @@ static int vpbe_buffer_prepare(struct videobuf_queue *q,
  * vpbe_buffer_setup()
  * This function allocates memory for the buffers
  */
-static int vpbe_buffer_setup(struct videobuf_queue *q,
-				unsigned int *count,
-				unsigned int *size)
+static int
+vpbe_buffer_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+			unsigned int *nbuffers, unsigned int *nplanes,
+			unsigned int sizes[], void *alloc_ctxs[])
+
 {
 	/* Get the file handle object and layer object */
-	struct vpbe_fh *fh = q->priv_data;
+	struct vpbe_fh *fh = vb2_get_drv_priv(vq);
 	struct vpbe_layer *layer = fh->layer;
 	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_buffer_setup\n");
 
-	*size = layer->pix_fmt.sizeimage;
-
 	/* Store number of buffers allocated in numbuffer member */
-	if (*count < VPBE_DEFAULT_NUM_BUFS)
-		*count = layer->numbuffers = VPBE_DEFAULT_NUM_BUFS;
+	if (*nbuffers < VPBE_DEFAULT_NUM_BUFS)
+		*nbuffers = layer->numbuffers = VPBE_DEFAULT_NUM_BUFS;
+
+	*nplanes = 1;
+	sizes[0] = layer->pix_fmt.sizeimage;
+	alloc_ctxs[0] = layer->alloc_ctx;
 
 	return 0;
 }
@@ -273,11 +268,12 @@ static int vpbe_buffer_setup(struct videobuf_queue *q,
  * vpbe_buffer_queue()
  * This function adds the buffer to DMA queue
  */
-static void vpbe_buffer_queue(struct videobuf_queue *q,
-				 struct videobuf_buffer *vb)
+static void vpbe_buffer_queue(struct vb2_buffer *vb)
 {
 	/* Get the file handle object and layer object */
-	struct vpbe_fh *fh = q->priv_data;
+	struct vpbe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
+	struct vpbe_disp_buffer *buf = container_of(vb,
+				struct vpbe_disp_buffer, vb);
 	struct vpbe_layer *layer = fh->layer;
 	struct vpbe_display *disp = fh->disp_dev;
 	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
@@ -288,39 +284,125 @@ static void vpbe_buffer_queue(struct videobuf_queue *q,
 
 	/* add the buffer to the DMA queue */
 	spin_lock_irqsave(&disp->dma_queue_lock, flags);
-	list_add_tail(&vb->queue, &layer->dma_queue);
+	list_add_tail(&buf->list, &layer->dma_queue);
 	spin_unlock_irqrestore(&disp->dma_queue_lock, flags);
-	/* Change state of the buffer */
-	vb->state = VIDEOBUF_QUEUED;
 }
 
 /*
- * vpbe_buffer_release()
- * This function is called from the videobuf layer to free memory allocated to
+ * vpbe_buf_cleanup()
+ * This function is called from the vb2 layer to free memory allocated to
  * the buffers
  */
-static void vpbe_buffer_release(struct videobuf_queue *q,
-				   struct videobuf_buffer *vb)
+static void vpbe_buf_cleanup(struct vb2_buffer *vb)
 {
 	/* Get the file handle object and layer object */
-	struct vpbe_fh *fh = q->priv_data;
+	struct vpbe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
 	struct vpbe_layer *layer = fh->layer;
 	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+	struct vpbe_disp_buffer *buf = container_of(vb,
+					struct vpbe_disp_buffer, vb);
+	unsigned long flags;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
-			"vpbe_buffer_release\n");
+			"vpbe_buf_cleanup\n");
+
+	spin_lock_irqsave(&layer->irqlock, flags);
+	if (vb->state == VB2_BUF_STATE_ACTIVE)
+		list_del_init(&buf->list);
+	spin_unlock_irqrestore(&layer->irqlock, flags);
+}
+
+static void vpbe_wait_prepare(struct vb2_queue *vq)
+{
+	struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+	struct vpbe_layer *layer = fh->layer;
+
+	mutex_unlock(&layer->opslock);
+}
+
+static void vpbe_wait_finish(struct vb2_queue *vq)
+{
+	struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+	struct vpbe_layer *layer = fh->layer;
+
+	mutex_lock(&layer->opslock);
+}
+
+static int vpbe_buffer_init(struct vb2_buffer *vb)
+{
+	struct vpbe_disp_buffer *buf = container_of(vb,
+					struct vpbe_disp_buffer, vb);
+
+	INIT_LIST_HEAD(&buf->list);
+	return 0;
+}
+
+static int vpbe_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+	struct vpbe_layer *layer = fh->layer;
+	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+	int ret;
+
+	/* If buffer queue is empty, return error */
+	if (list_empty(&layer->dma_queue)) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "buffer queue is empty\n");
+		return -EINVAL;
+	}
+	/* Get the next frame from the buffer queue */
+	layer->next_frm = layer->cur_frm = list_entry(layer->dma_queue.next,
+				struct vpbe_disp_buffer, list);
+	/* Remove buffer from the buffer queue */
+	list_del(&layer->cur_frm->list);
+	/* Mark state of the current frame to active */
+	layer->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE;
+	/* Initialize field_id and started member */
+	layer->field_id = 0;
+
+	/* Set parameters in OSD and VENC */
+	ret = vpbe_set_osd_display_params(fh->disp_dev, layer);
+	if (ret < 0)
+		return ret;
 
-	if (V4L2_MEMORY_USERPTR != layer->memory)
-		videobuf_dma_contig_free(q, vb);
+	/*
+	 * if request format is yuv420 semiplanar, need to
+	 * enable both video windows
+	 */
+	layer->started = 1;
+	layer->layer_first_int = 1;
+
+	return ret;
+}
+
+static int vpbe_stop_streaming(struct vb2_queue *vq)
+{
+	struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+	struct vpbe_layer *layer = fh->layer;
+
+	if (!vb2_is_streaming(vq))
+		return 0;
+
+	/* release all active buffers */
+	while (!list_empty(&layer->dma_queue)) {
+		layer->next_frm = list_entry(layer->dma_queue.next,
+						struct vpbe_disp_buffer, list);
+		list_del(&layer->next_frm->list);
+		vb2_buffer_done(&layer->next_frm->vb, VB2_BUF_STATE_ERROR);
+	}
 
-	vb->state = VIDEOBUF_NEEDS_INIT;
+	return 0;
 }
 
-static struct videobuf_queue_ops video_qops = {
-	.buf_setup = vpbe_buffer_setup,
+static struct vb2_ops video_qops = {
+	.queue_setup = vpbe_buffer_queue_setup,
+	.wait_prepare = vpbe_wait_prepare,
+	.wait_finish = vpbe_wait_finish,
+	.buf_init = vpbe_buffer_init,
 	.buf_prepare = vpbe_buffer_prepare,
+	.start_streaming = vpbe_start_streaming,
+	.stop_streaming = vpbe_stop_streaming,
+	.buf_cleanup = vpbe_buf_cleanup,
 	.buf_queue = vpbe_buffer_queue,
-	.buf_release = vpbe_buffer_release,
 };
 
 static
@@ -345,7 +427,7 @@ static int vpbe_set_osd_display_params(struct vpbe_display *disp_dev,
 	unsigned long addr;
 	int ret;
 
-	addr = videobuf_to_dma_contig(layer->cur_frm);
+	addr = vb2_dma_contig_plane_dma_addr(&layer->cur_frm->vb, 0);
 	/* Set address in the display registers */
 	osd_device->ops.start_layer(osd_device,
 				    layer->layer_info.id,
@@ -620,9 +702,12 @@ static int vpbe_display_querycap(struct file *file, void  *priv,
 	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 
 	cap->version = VPBE_DISPLAY_VERSION_CODE;
-	cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
-	strlcpy(cap->driver, VPBE_DISPLAY_DRIVER, sizeof(cap->driver));
-	strlcpy(cap->bus_info, "platform", sizeof(cap->bus_info));
+	cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	snprintf(cap->driver, sizeof(cap->driver), "%s",
+		dev_name(vpbe_dev->pdev));
+	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+		 dev_name(vpbe_dev->pdev));
 	strlcpy(cap->card, vpbe_dev->cfg->module_name, sizeof(cap->card));
 
 	return 0;
@@ -1161,7 +1246,7 @@ static int vpbe_display_streamoff(struct file *file, void *priv,
 	osd_device->ops.disable_layer(osd_device,
 			layer->layer_info.id);
 	layer->started = 0;
-	ret = videobuf_streamoff(&layer->buffer_queue);
+	ret = vb2_streamoff(&layer->buffer_queue, buf_type);
 
 	return ret;
 }
@@ -1199,46 +1284,15 @@ static int vpbe_display_streamon(struct file *file, void *priv,
 	}
 
 	/*
-	 * Call videobuf_streamon to start streaming
+	 * Call vb2_streamon to start streaming
 	 * in videobuf
 	 */
-	ret = videobuf_streamon(&layer->buffer_queue);
+	ret = vb2_streamon(&layer->buffer_queue, buf_type);
 	if (ret) {
 		v4l2_err(&vpbe_dev->v4l2_dev,
-		"error in videobuf_streamon\n");
+		"error in vb2_streamon\n");
 		return ret;
 	}
-	/* If buffer queue is empty, return error */
-	if (list_empty(&layer->dma_queue)) {
-		v4l2_err(&vpbe_dev->v4l2_dev, "buffer queue is empty\n");
-		goto streamoff;
-	}
-	/* Get the next frame from the buffer queue */
-	layer->next_frm = layer->cur_frm = list_entry(layer->dma_queue.next,
-				struct videobuf_buffer, queue);
-	/* Remove buffer from the buffer queue */
-	list_del(&layer->cur_frm->queue);
-	/* Mark state of the current frame to active */
-	layer->cur_frm->state = VIDEOBUF_ACTIVE;
-	/* Initialize field_id and started member */
-	layer->field_id = 0;
-
-	/* Set parameters in OSD and VENC */
-	ret = vpbe_set_osd_display_params(disp_dev, layer);
-	if (ret < 0)
-		goto streamoff;
-
-	/*
-	 * if request format is yuv420 semiplanar, need to
-	 * enable both video windows
-	 */
-	layer->started = 1;
-
-	layer->layer_first_int = 1;
-
-	return ret;
-streamoff:
-	ret = videobuf_streamoff(&layer->buffer_queue);
 	return ret;
 }
 
@@ -1265,10 +1319,10 @@ static int vpbe_display_dqbuf(struct file *file, void *priv,
 	}
 	if (file->f_flags & O_NONBLOCK)
 		/* Call videobuf_dqbuf for non blocking mode */
-		ret = videobuf_dqbuf(&layer->buffer_queue, buf, 1);
+		ret = vb2_dqbuf(&layer->buffer_queue, buf, 1);
 	else
 		/* Call videobuf_dqbuf for blocking mode */
-		ret = videobuf_dqbuf(&layer->buffer_queue, buf, 0);
+		ret = vb2_dqbuf(&layer->buffer_queue, buf, 0);
 
 	return ret;
 }
@@ -1295,7 +1349,7 @@ static int vpbe_display_qbuf(struct file *file, void *priv,
 		return -EACCES;
 	}
 
-	return videobuf_qbuf(&layer->buffer_queue, p);
+	return vb2_qbuf(&layer->buffer_queue, p);
 }
 
 static int vpbe_display_querybuf(struct file *file, void *priv,
@@ -1304,7 +1358,6 @@ static int vpbe_display_querybuf(struct file *file, void *priv,
 	struct vpbe_fh *fh = file->private_data;
 	struct vpbe_layer *layer = fh->layer;
 	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
-	int ret;
 
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
 		"VIDIOC_QUERYBUF, layer id = %d\n",
@@ -1314,11 +1367,8 @@ static int vpbe_display_querybuf(struct file *file, void *priv,
 		v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
 		return -EINVAL;
 	}
-
-	/* Call videobuf_querybuf to get information */
-	ret = videobuf_querybuf(&layer->buffer_queue, buf);
-
-	return ret;
+	/* Call vb2_querybuf to get information */
+	return vb2_querybuf(&layer->buffer_queue, buf);
 }
 
 static int vpbe_display_reqbufs(struct file *file, void *priv,
@@ -1327,8 +1377,8 @@ static int vpbe_display_reqbufs(struct file *file, void *priv,
 	struct vpbe_fh *fh = file->private_data;
 	struct vpbe_layer *layer = fh->layer;
 	struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+	struct vb2_queue *q;
 	int ret;
-
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_reqbufs\n");
 
 	if (V4L2_BUF_TYPE_VIDEO_OUTPUT != req_buf->type) {
@@ -1342,15 +1392,26 @@ static int vpbe_display_reqbufs(struct file *file, void *priv,
 		return -EBUSY;
 	}
 	/* Initialize videobuf queue as per the buffer type */
-	videobuf_queue_dma_contig_init(&layer->buffer_queue,
-				&video_qops,
-				vpbe_dev->pdev,
-				&layer->irqlock,
-				V4L2_BUF_TYPE_VIDEO_OUTPUT,
-				layer->pix_fmt.field,
-				sizeof(struct videobuf_buffer),
-				fh, NULL);
+	layer->alloc_ctx = vb2_dma_contig_init_ctx(vpbe_dev->pdev);
+	if (!layer->alloc_ctx) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "Failed to get the context\n");
+		return -EINVAL;
+	}
+	q = &layer->buffer_queue;
+	memset(q, 0, sizeof(*q));
+	q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+	q->io_modes = VB2_MMAP | VB2_USERPTR;
+	q->drv_priv = fh;
+	q->ops = &video_qops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->buf_struct_size = sizeof(struct vpbe_disp_buffer);
 
+	ret = vb2_queue_init(q);
+	if (ret) {
+		v4l2_err(&vpbe_dev->v4l2_dev, "vb2_queue_init() failed\n");
+		vb2_dma_contig_cleanup_ctx(layer->alloc_ctx);
+		return ret;
+	}
 	/* Set io allowed member of file handle to TRUE */
 	fh->io_allowed = 1;
 	/* Increment io usrs member of layer object to 1 */
@@ -1360,9 +1421,7 @@ static int vpbe_display_reqbufs(struct file *file, void *priv,
 	/* Initialize buffer queue */
 	INIT_LIST_HEAD(&layer->dma_queue);
 	/* Allocate buffers */
-	ret = videobuf_reqbufs(&layer->buffer_queue, req_buf);
-
-	return ret;
+	return vb2_reqbufs(q, req_buf);
 }
 
 /*
@@ -1381,7 +1440,7 @@ static int vpbe_display_mmap(struct file *filep, struct vm_area_struct *vma)
 
 	if (mutex_lock_interruptible(&layer->opslock))
 		return -ERESTARTSYS;
-	ret = videobuf_mmap_mapper(&layer->buffer_queue, vma);
+	ret = vb2_mmap(&layer->buffer_queue, vma);
 	mutex_unlock(&layer->opslock);
 	return ret;
 }
@@ -1398,7 +1457,7 @@ static unsigned int vpbe_display_poll(struct file *filep, poll_table *wait)
 	v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_poll\n");
 	if (layer->started) {
 		mutex_lock(&layer->opslock);
-		err = videobuf_poll_stream(filep, &layer->buffer_queue, wait);
+		err = vb2_poll(&layer->buffer_queue, filep, wait);
 		mutex_unlock(&layer->opslock);
 	}
 	return err;
@@ -1488,8 +1547,8 @@ static int vpbe_display_release(struct file *file)
 				layer->layer_info.id);
 		layer->started = 0;
 		/* Free buffers allocated */
-		videobuf_queue_cancel(&layer->buffer_queue);
-		videobuf_mmap_free(&layer->buffer_queue);
+		vb2_queue_release(&layer->buffer_queue);
+		vb2_dma_contig_cleanup_ctx(&layer->buffer_queue);
 	}
 
 	/* Decrement layer usrs counter */
diff --git a/drivers/media/platform/davinci/vpbe_osd.c b/drivers/media/platform/davinci/vpbe_osd.c
index bba299d..707f243 100644
--- a/drivers/media/platform/davinci/vpbe_osd.c
+++ b/drivers/media/platform/davinci/vpbe_osd.c
@@ -62,7 +62,7 @@ static inline u32 osd_set(struct osd_state *sd, u32 mask, u32 offset)
 {
 	struct osd_state *osd = sd;
 
-	u32 addr = osd->osd_base + offset;
+	void __iomem *addr = osd->osd_base + offset;
 	u32 val = readl(addr) | mask;
 
 	writel(val, addr);
@@ -74,7 +74,7 @@ static inline u32 osd_clear(struct osd_state *sd, u32 mask, u32 offset)
 {
 	struct osd_state *osd = sd;
 
-	u32 addr = osd->osd_base + offset;
+	void __iomem *addr = osd->osd_base + offset;
 	u32 val = readl(addr) & ~mask;
 
 	writel(val, addr);
@@ -87,7 +87,7 @@ static inline u32 osd_modify(struct osd_state *sd, u32 mask, u32 val,
 {
 	struct osd_state *osd = sd;
 
-	u32 addr = osd->osd_base + offset;
+	void __iomem *addr = osd->osd_base + offset;
 	u32 new_val = (readl(addr) & ~mask) | (val & mask);
 
 	writel(new_val, addr);
@@ -1559,8 +1559,7 @@ static int osd_probe(struct platform_device *pdev)
 		ret = -ENODEV;
 		goto free_mem;
 	}
-	osd->osd_base = (unsigned long)ioremap_nocache(res->start,
-							osd->osd_size);
+	osd->osd_base = ioremap_nocache(res->start, osd->osd_size);
 	if (!osd->osd_base) {
 		dev_err(osd->dev, "Unable to map the OSD region\n");
 		ret = -ENODEV;
diff --git a/drivers/media/platform/davinci/vpif.c b/drivers/media/platform/davinci/vpif.c
index cff3c0a..0d6cc8e 100644
--- a/drivers/media/platform/davinci/vpif.c
+++ b/drivers/media/platform/davinci/vpif.c
@@ -444,7 +444,7 @@ static int __devinit vpif_probe(struct platform_device *pdev)
 		status = PTR_ERR(vpif_clk);
 		goto clk_fail;
 	}
-	clk_enable(vpif_clk);
+	clk_prepare_enable(vpif_clk);
 
 	spin_lock_init(&vpif_lock);
 	dev_info(&pdev->dev, "vpif probe success\n");
@@ -460,7 +460,7 @@ fail:
 static int __devexit vpif_remove(struct platform_device *pdev)
 {
 	if (vpif_clk) {
-		clk_disable(vpif_clk);
+		clk_disable_unprepare(vpif_clk);
 		clk_put(vpif_clk);
 	}
 
@@ -472,13 +472,13 @@ static int __devexit vpif_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int vpif_suspend(struct device *dev)
 {
-	clk_disable(vpif_clk);
+	clk_disable_unprepare(vpif_clk);
 	return 0;
 }
 
 static int vpif_resume(struct device *dev)
 {
-	clk_enable(vpif_clk);
+	clk_prepare_enable(vpif_clk);
 	return 0;
 }
 
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index fcabc02..a409cce 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -201,13 +201,16 @@ static void vpif_buffer_queue(struct vb2_buffer *vb)
 	struct vpif_cap_buffer *buf = container_of(vb,
 				struct vpif_cap_buffer, vb);
 	struct common_obj *common;
+	unsigned long flags;
 
 	common = &ch->common[VPIF_VIDEO_INDEX];
 
 	vpif_dbg(2, debug, "vpif_buffer_queue\n");
 
+	spin_lock_irqsave(&common->irqlock, flags);
 	/* add the buffer to the DMA queue */
 	list_add_tail(&buf->list, &common->dma_queue);
+	spin_unlock_irqrestore(&common->irqlock, flags);
 }
 
 /**
@@ -278,10 +281,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
 	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
 	struct vpif_params *vpif = &ch->vpifparams;
 	unsigned long addr = 0;
+	unsigned long flags;
 	int ret;
 
-		/* If buffer queue is empty, return error */
+	/* If buffer queue is empty, return error */
+	spin_lock_irqsave(&common->irqlock, flags);
 	if (list_empty(&common->dma_queue)) {
+		spin_unlock_irqrestore(&common->irqlock, flags);
 		vpif_dbg(1, debug, "buffer queue is empty\n");
 		return -EIO;
 	}
@@ -291,6 +297,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
 				    struct vpif_cap_buffer, list);
 	/* Remove buffer from the buffer queue */
 	list_del(&common->cur_frm->list);
+	spin_unlock_irqrestore(&common->irqlock, flags);
 	/* Mark state of the current frame to active */
 	common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE;
 	/* Initialize field_id and started member */
@@ -362,6 +369,7 @@ static int vpif_stop_streaming(struct vb2_queue *vq)
 	struct vpif_fh *fh = vb2_get_drv_priv(vq);
 	struct channel_obj *ch = fh->channel;
 	struct common_obj *common;
+	unsigned long flags;
 
 	if (!vb2_is_streaming(vq))
 		return 0;
@@ -369,12 +377,14 @@ static int vpif_stop_streaming(struct vb2_queue *vq)
 	common = &ch->common[VPIF_VIDEO_INDEX];
 
 	/* release all active buffers */
+	spin_lock_irqsave(&common->irqlock, flags);
 	while (!list_empty(&common->dma_queue)) {
 		common->next_frm = list_entry(common->dma_queue.next,
 						struct vpif_cap_buffer, list);
 		list_del(&common->next_frm->list);
 		vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR);
 	}
+	spin_unlock_irqrestore(&common->irqlock, flags);
 
 	return 0;
 }
@@ -420,10 +430,12 @@ static void vpif_schedule_next_buffer(struct common_obj *common)
 {
 	unsigned long addr = 0;
 
+	spin_lock(&common->irqlock);
 	common->next_frm = list_entry(common->dma_queue.next,
 				     struct vpif_cap_buffer, list);
 	/* Remove that buffer from the buffer queue */
 	list_del(&common->next_frm->list);
+	spin_unlock(&common->irqlock);
 	common->next_frm->vb.state = VB2_BUF_STATE_ACTIVE;
 	addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb, 0);
 
@@ -468,8 +480,12 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
 		/* Check the field format */
 		if (1 == ch->vpifparams.std_info.frm_fmt) {
 			/* Progressive mode */
-			if (list_empty(&common->dma_queue))
+			spin_lock(&common->irqlock);
+			if (list_empty(&common->dma_queue)) {
+				spin_unlock(&common->irqlock);
 				continue;
+			}
+			spin_unlock(&common->irqlock);
 
 			if (!channel_first_int[i][channel_id])
 				vpif_process_buffer_complete(common);
@@ -513,9 +529,13 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
 				vpif_process_buffer_complete(common);
 			} else if (1 == fid) {
 				/* odd field */
+				spin_lock(&common->irqlock);
 				if (list_empty(&common->dma_queue) ||
-				    (common->cur_frm != common->next_frm))
+				    (common->cur_frm != common->next_frm)) {
+					spin_unlock(&common->irqlock);
 					continue;
+				}
+				spin_unlock(&common->irqlock);
 
 				vpif_schedule_next_buffer(common);
 			}
@@ -1004,9 +1024,9 @@ static int vpif_reqbufs(struct file *file, void *priv,
 
 	/* Initialize videobuf2 queue as per the buffer type */
 	common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev);
-	if (!common->alloc_ctx) {
+	if (IS_ERR(common->alloc_ctx)) {
 		vpif_err("Failed to get the context\n");
-		return -EINVAL;
+		return PTR_ERR(common->alloc_ctx);
 	}
 	q = &common->buffer_queue;
 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -1715,7 +1735,7 @@ vpif_enum_dv_timings(struct file *file, void *priv,
 	int ret;
 
 	ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
-	if (ret == -ENOIOCTLCMD && ret == -ENODEV)
+	if (ret == -ENOIOCTLCMD || ret == -ENODEV)
 		return -EINVAL;
 	return ret;
 }
@@ -1735,7 +1755,7 @@ vpif_query_dv_timings(struct file *file, void *priv,
 	int ret;
 
 	ret = v4l2_subdev_call(ch->sd, video, query_dv_timings, timings);
-	if (ret == -ENOIOCTLCMD && ret == -ENODEV)
+	if (ret == -ENOIOCTLCMD || ret == -ENODEV)
 		return -ENODATA;
 	return ret;
 }
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index b716fbd..9f2b603 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -177,11 +177,14 @@ static void vpif_buffer_queue(struct vb2_buffer *vb)
 				struct vpif_disp_buffer, vb);
 	struct channel_obj *ch = fh->channel;
 	struct common_obj *common;
+	unsigned long flags;
 
 	common = &ch->common[VPIF_VIDEO_INDEX];
 
 	/* add the buffer to the DMA queue */
+	spin_lock_irqsave(&common->irqlock, flags);
 	list_add_tail(&buf->list, &common->dma_queue);
+	spin_unlock_irqrestore(&common->irqlock, flags);
 }
 
 /*
@@ -246,10 +249,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
 	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
 	struct vpif_params *vpif = &ch->vpifparams;
 	unsigned long addr = 0;
+	unsigned long flags;
 	int ret;
 
 	/* If buffer queue is empty, return error */
+	spin_lock_irqsave(&common->irqlock, flags);
 	if (list_empty(&common->dma_queue)) {
+		spin_unlock_irqrestore(&common->irqlock, flags);
 		vpif_err("buffer queue is empty\n");
 		return -EIO;
 	}
@@ -260,6 +266,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
 				       struct vpif_disp_buffer, list);
 
 	list_del(&common->cur_frm->list);
+	spin_unlock_irqrestore(&common->irqlock, flags);
 	/* Mark state of the current frame to active */
 	common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE;
 
@@ -330,6 +337,7 @@ static int vpif_stop_streaming(struct vb2_queue *vq)
 	struct vpif_fh *fh = vb2_get_drv_priv(vq);
 	struct channel_obj *ch = fh->channel;
 	struct common_obj *common;
+	unsigned long flags;
 
 	if (!vb2_is_streaming(vq))
 		return 0;
@@ -337,12 +345,14 @@ static int vpif_stop_streaming(struct vb2_queue *vq)
 	common = &ch->common[VPIF_VIDEO_INDEX];
 
 	/* release all active buffers */
+	spin_lock_irqsave(&common->irqlock, flags);
 	while (!list_empty(&common->dma_queue)) {
 		common->next_frm = list_entry(common->dma_queue.next,
 						struct vpif_disp_buffer, list);
 		list_del(&common->next_frm->list);
 		vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR);
 	}
+	spin_unlock_irqrestore(&common->irqlock, flags);
 
 	return 0;
 }
@@ -363,11 +373,13 @@ static void process_progressive_mode(struct common_obj *common)
 {
 	unsigned long addr = 0;
 
+	spin_lock(&common->irqlock);
 	/* Get the next buffer from buffer queue */
 	common->next_frm = list_entry(common->dma_queue.next,
 				struct vpif_disp_buffer, list);
 	/* Remove that buffer from the buffer queue */
 	list_del(&common->next_frm->list);
+	spin_unlock(&common->irqlock);
 	/* Mark status of the buffer as active */
 	common->next_frm->vb.state = VB2_BUF_STATE_ACTIVE;
 
@@ -398,16 +410,18 @@ static void process_interlaced_mode(int fid, struct common_obj *common)
 		common->cur_frm = common->next_frm;
 
 	} else if (1 == fid) {	/* odd field */
+		spin_lock(&common->irqlock);
 		if (list_empty(&common->dma_queue)
 		    || (common->cur_frm != common->next_frm)) {
+			spin_unlock(&common->irqlock);
 			return;
 		}
+		spin_unlock(&common->irqlock);
 		/* one field is displayed configure the next
 		 * frame if it is available else hold on current
 		 * frame */
 		/* Get next from the buffer queue */
 		process_progressive_mode(common);
-
 	}
 }
 
@@ -437,8 +451,12 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
 			continue;
 
 		if (1 == ch->vpifparams.std_info.frm_fmt) {
-			if (list_empty(&common->dma_queue))
+			spin_lock(&common->irqlock);
+			if (list_empty(&common->dma_queue)) {
+				spin_unlock(&common->irqlock);
 				continue;
+			}
+			spin_unlock(&common->irqlock);
 
 			/* Progressive mode */
 			if (!channel_first_int[i][channel_id]) {
@@ -972,9 +990,9 @@ static int vpif_reqbufs(struct file *file, void *priv,
 	}
 	/* Initialize videobuf2 queue as per the buffer type */
 	common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev);
-	if (!common->alloc_ctx) {
+	if (IS_ERR(common->alloc_ctx)) {
 		vpif_err("Failed to get the context\n");
-		return -EINVAL;
+		return PTR_ERR(common->alloc_ctx);
 	}
 	q = &common->buffer_queue;
 	q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
@@ -1380,7 +1398,7 @@ vpif_enum_dv_timings(struct file *file, void *priv,
 	int ret;
 
 	ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
-	if (ret == -ENOIOCTLCMD && ret == -ENODEV)
+	if (ret == -ENOIOCTLCMD || ret == -ENODEV)
 		return -EINVAL;
 	return ret;
 }
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c
index bfec9e6..cc7b218 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.c
+++ b/drivers/media/platform/exynos-gsc/gsc-core.c
@@ -965,8 +965,10 @@ static struct platform_device_id gsc_driver_ids[] = {
 MODULE_DEVICE_TABLE(platform, gsc_driver_ids);
 
 static const struct of_device_id exynos_gsc_match[] = {
-	{ .compatible = "samsung,exynos5250-gsc",
-	.data = &gsc_v_100_drvdata, },
+	{
+		.compatible = "samsung,exynos5-gsc",
+		.data = &gsc_v_100_drvdata,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, exynos_gsc_match);
@@ -980,7 +982,7 @@ static void *gsc_get_drv_data(struct platform_device *pdev)
 		match = of_match_node(of_match_ptr(exynos_gsc_match),
 					pdev->dev.of_node);
 		if (match)
-			driver_data =  match->data;
+			driver_data = (struct gsc_driverdata *)match->data;
 	} else {
 		driver_data = (struct gsc_driverdata *)
 			platform_get_device_id(pdev)->driver_data;
diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c
index 3c7f005..047f0f0 100644
--- a/drivers/media/platform/exynos-gsc/gsc-m2m.c
+++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c
@@ -122,7 +122,7 @@ static void gsc_m2m_device_run(void *priv)
 	struct gsc_ctx *ctx = priv;
 	struct gsc_dev *gsc;
 	unsigned long flags;
-	u32 ret;
+	int ret;
 	bool is_set = false;
 
 	if (WARN(!ctx, "null hardware context\n"))
diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index 31ac4dc..a8ddb0c 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -352,8 +352,7 @@ static int restart_video_queue(struct viu_dmaqueue *vidq)
 			return 0;
 		buf = list_entry(vidq->queued.next, struct viu_buf, vb.queue);
 		if (prev == NULL) {
-			list_del(&buf->vb.queue);
-			list_add_tail(&buf->vb.queue, &vidq->active);
+			list_move_tail(&buf->vb.queue, &vidq->active);
 
 			dprintk(1, "Restarting video dma\n");
 			viu_stop_dma(vidq->dev);
@@ -367,8 +366,7 @@ static int restart_video_queue(struct viu_dmaqueue *vidq)
 		} else if (prev->vb.width  == buf->vb.width  &&
 			   prev->vb.height == buf->vb.height &&
 			   prev->fmt       == buf->fmt) {
-			list_del(&buf->vb.queue);
-			list_add_tail(&buf->vb.queue, &vidq->active);
+			list_move_tail(&buf->vb.queue, &vidq->active);
 			buf->vb.state = VIDEOBUF_ACTIVE;
 			dprintk(2, "[%p/%d] restart_queue - move to active\n",
 				buf, buf->vb.i);
diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c
index 45164c4..05c560f 100644
--- a/drivers/media/platform/m2m-deinterlace.c
+++ b/drivers/media/platform/m2m-deinterlace.c
@@ -218,15 +218,14 @@ static void dma_callback(void *data)
 static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op,
 				  int do_callback)
 {
-	struct deinterlace_q_data *s_q_data, *d_q_data;
+	struct deinterlace_q_data *s_q_data;
 	struct vb2_buffer *src_buf, *dst_buf;
 	struct deinterlace_dev *pcdev = ctx->dev;
 	struct dma_chan *chan = pcdev->dma_chan;
 	struct dma_device *dmadev = chan->device;
 	struct dma_async_tx_descriptor *tx;
 	unsigned int s_width, s_height;
-	unsigned int d_width, d_height;
-	unsigned int d_size, s_size;
+	unsigned int s_size;
 	dma_addr_t p_in, p_out;
 	enum dma_ctrl_flags flags;
 
@@ -238,11 +237,6 @@ static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op,
 	s_height = s_q_data->height;
 	s_size = s_width * s_height;
 
-	d_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	d_width = d_q_data->width;
-	d_height = d_q_data->height;
-	d_size = d_width * d_height;
-
 	p_in = (dma_addr_t)vb2_dma_contig_plane_dma_addr(src_buf, 0);
 	p_out = (dma_addr_t)vb2_dma_contig_plane_dma_addr(dst_buf, 0);
 	if (!p_in || !p_out) {
@@ -1108,17 +1102,5 @@ static struct platform_driver deinterlace_pdrv = {
 		.owner	= THIS_MODULE,
 	},
 };
-
-static void __exit deinterlace_exit(void)
-{
-	platform_driver_unregister(&deinterlace_pdrv);
-}
-
-static int __init deinterlace_init(void)
-{
-	return platform_driver_register(&deinterlace_pdrv);
-}
-
-module_init(deinterlace_init);
-module_exit(deinterlace_exit);
+module_platform_driver(deinterlace_pdrv);
 
diff --git a/drivers/media/platform/mem2mem_testdev.c b/drivers/media/platform/mem2mem_testdev.c
index 2e2121e..7487d72 100644
--- a/drivers/media/platform/mem2mem_testdev.c
+++ b/drivers/media/platform/mem2mem_testdev.c
@@ -839,7 +839,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *ds
 	int ret;
 
 	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-	src_vq->io_modes = VB2_MMAP;
+	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
 	src_vq->drv_priv = ctx;
 	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 	src_vq->ops = &m2mtest_qops;
@@ -850,7 +850,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *ds
 		return ret;
 
 	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	dst_vq->io_modes = VB2_MMAP;
+	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
 	dst_vq->drv_priv = ctx;
 	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 	dst_vq->ops = &m2mtest_qops;
diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c
index 8f22ce5..c45a9f5 100644
--- a/drivers/media/platform/mx2_emmaprp.c
+++ b/drivers/media/platform/mx2_emmaprp.c
@@ -1013,16 +1013,4 @@ static struct platform_driver emmaprp_pdrv = {
 		.owner	= THIS_MODULE,
 	},
 };
-
-static void __exit emmaprp_exit(void)
-{
-	platform_driver_unregister(&emmaprp_pdrv);
-}
-
-static int __init emmaprp_init(void)
-{
-	return platform_driver_register(&emmaprp_pdrv);
-}
-
-module_init(emmaprp_init);
-module_exit(emmaprp_exit);
+module_platform_driver(emmaprp_pdrv);
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
index a3b1a34..21d55f0 100644
--- a/drivers/media/platform/omap/omap_vout.c
+++ b/drivers/media/platform/omap/omap_vout.c
@@ -45,8 +45,8 @@
 #include <media/v4l2-ioctl.h>
 
 #include <plat/cpu.h>
-#include <plat/dma.h>
-#include <plat/vrfb.h>
+#include <plat-omap/dma-omap.h>
+#include <video/omapvrfb.h>
 #include <video/omapdss.h>
 
 #include "omap_voutlib.h"
@@ -1174,13 +1174,6 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh,
 	/* set default crop and win */
 	omap_vout_new_format(&vout->pix, &vout->fbuf, &vout->crop, &vout->win);
 
-	/* Save the changes in the overlay strcuture */
-	ret = omapvid_init(vout, 0);
-	if (ret) {
-		v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n");
-		goto s_fmt_vid_out_exit;
-	}
-
 	ret = 0;
 
 s_fmt_vid_out_exit:
@@ -1684,20 +1677,6 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
 
 	omap_dispc_register_isr(omap_vout_isr, vout, mask);
 
-	for (j = 0; j < ovid->num_overlays; j++) {
-		struct omap_overlay *ovl = ovid->overlays[j];
-
-		if (ovl->get_device(ovl)) {
-			struct omap_overlay_info info;
-			ovl->get_overlay_info(ovl, &info);
-			info.paddr = addr;
-			if (ovl->set_overlay_info(ovl, &info)) {
-				ret = -EINVAL;
-				goto streamon_err1;
-			}
-		}
-	}
-
 	/* First save the configuration in ovelray structure */
 	ret = omapvid_init(vout, addr);
 	if (ret)
@@ -2094,11 +2073,12 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
 		}
 		video_set_drvdata(vfd, vout);
 
-		/* Configure the overlay structure */
-		ret = omapvid_init(vid_dev->vouts[k], 0);
-		if (!ret)
-			goto success;
+		dev_info(&pdev->dev, ": registered and initialized"
+				" video device %d\n", vfd->minor);
+		if (k == (pdev->num_resources - 1))
+			return 0;
 
+		continue;
 error2:
 		if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
 			omap_vout_release_vrfb(vout);
@@ -2108,12 +2088,6 @@ error1:
 error:
 		kfree(vout);
 		return ret;
-
-success:
-		dev_info(&pdev->dev, ": registered and initialized"
-				" video device %d\n", vfd->minor);
-		if (k == (pdev->num_resources - 1))
-			return 0;
 	}
 
 	return -ENODEV;
diff --git a/drivers/media/platform/omap/omap_vout_vrfb.c b/drivers/media/platform/omap/omap_vout_vrfb.c
index 4be26abf6c..8340445 100644
--- a/drivers/media/platform/omap/omap_vout_vrfb.c
+++ b/drivers/media/platform/omap/omap_vout_vrfb.c
@@ -16,12 +16,14 @@
 #include <media/videobuf-dma-contig.h>
 #include <media/v4l2-device.h>
 
-#include <plat/dma.h>
-#include <plat/vrfb.h>
+#include <plat-omap/dma-omap.h>
+#include <video/omapvrfb.h>
 
 #include "omap_voutdef.h"
 #include "omap_voutlib.h"
 
+#define OMAP_DMA_NO_DEVICE	0
+
 /*
  * Function for allocating video buffers
  */
diff --git a/drivers/media/platform/omap/omap_voutdef.h b/drivers/media/platform/omap/omap_voutdef.h
index 27a95d2..9ccfe1f 100644
--- a/drivers/media/platform/omap/omap_voutdef.h
+++ b/drivers/media/platform/omap/omap_voutdef.h
@@ -12,7 +12,7 @@
 #define OMAP_VOUTDEF_H
 
 #include <video/omapdss.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
 
 #define YUYV_BPP        2
 #define RGB565_BPP      2
diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c
index 60181ab..aa9df9d 100644
--- a/drivers/media/platform/omap3isp/ispccdc.c
+++ b/drivers/media/platform/omap3isp/ispccdc.c
@@ -1706,7 +1706,7 @@ static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 }
 
 static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
-				const struct v4l2_event_subscription *sub)
+				struct v4l2_event_subscription *sub)
 {
 	if (sub->type != V4L2_EVENT_FRAME_SYNC)
 		return -EINVAL;
@@ -1719,7 +1719,7 @@ static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
 }
 
 static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
-				  const struct v4l2_event_subscription *sub)
+				  struct v4l2_event_subscription *sub)
 {
 	return v4l2_event_unsubscribe(fh, sub);
 }
diff --git a/drivers/media/platform/omap3isp/isphist.c b/drivers/media/platform/omap3isp/isphist.c
index d1a8dee..e7f9c42 100644
--- a/drivers/media/platform/omap3isp/isphist.c
+++ b/drivers/media/platform/omap3isp/isphist.c
@@ -34,6 +34,8 @@
 #include "ispreg.h"
 #include "isphist.h"
 
+#define OMAP24XX_DMA_NO_DEVICE		0
+
 #define HIST_CONFIG_DMA	1
 
 #define HIST_USING_DMA(hist) ((hist)->dma_ch >= 0)
diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c
index d7ac76b..b8640be 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -1025,7 +1025,7 @@ void omap3isp_stat_dma_isr(struct ispstat *stat)
 
 int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
 				  struct v4l2_fh *fh,
-				  const struct v4l2_event_subscription *sub)
+				  struct v4l2_event_subscription *sub)
 {
 	struct ispstat *stat = v4l2_get_subdevdata(subdev);
 
@@ -1037,7 +1037,7 @@ int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
 
 int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
 				    struct v4l2_fh *fh,
-				    const struct v4l2_event_subscription *sub)
+				    struct v4l2_event_subscription *sub)
 {
 	return v4l2_event_unsubscribe(fh, sub);
 }
diff --git a/drivers/media/platform/omap3isp/ispstat.h b/drivers/media/platform/omap3isp/ispstat.h
index a6fe653..99cf104 100644
--- a/drivers/media/platform/omap3isp/ispstat.h
+++ b/drivers/media/platform/omap3isp/ispstat.h
@@ -30,7 +30,7 @@
 
 #include <linux/types.h>
 #include <linux/omap3isp.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 #include <media/v4l2-event.h>
 
 #include "isp.h"
@@ -147,10 +147,10 @@ int omap3isp_stat_init(struct ispstat *stat, const char *name,
 void omap3isp_stat_cleanup(struct ispstat *stat);
 int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
 				  struct v4l2_fh *fh,
-				  const struct v4l2_event_subscription *sub);
+				  struct v4l2_event_subscription *sub);
 int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
 				    struct v4l2_fh *fh,
-				    const struct v4l2_event_subscription *sub);
+				    struct v4l2_event_subscription *sub);
 int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable);
 
 int omap3isp_stat_busy(struct ispstat *stat);
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index a0b737fe..b24c100 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -36,7 +36,6 @@
 #include <media/v4l2-ioctl.h>
 #include <plat/iommu.h>
 #include <plat/iovmm.h>
-#include <plat/omap-pm.h>
 
 #include "ispvideo.h"
 #include "isp.h"
@@ -792,7 +791,7 @@ isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop)
 }
 
 static int
-isp_video_set_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+isp_video_set_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
 {
 	struct isp_video *video = video_drvdata(file);
 	struct v4l2_subdev *subdev;
diff --git a/drivers/media/platform/s5p-fimc/Kconfig b/drivers/media/platform/s5p-fimc/Kconfig
index 8f090a8..f997a52 100644
--- a/drivers/media/platform/s5p-fimc/Kconfig
+++ b/drivers/media/platform/s5p-fimc/Kconfig
@@ -2,7 +2,6 @@
 config VIDEO_SAMSUNG_S5P_FIMC
 	bool "Samsung S5P/EXYNOS SoC camera interface driver (experimental)"
 	depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && PLAT_S5P && PM_RUNTIME
-	depends on EXPERIMENTAL
 	help
 	  Say Y here to enable camera host interface devices for
 	  Samsung S5P and EXYNOS SoC series.
@@ -24,6 +23,7 @@ config VIDEO_S5P_FIMC
 config VIDEO_S5P_MIPI_CSIS
 	tristate "S5P/EXYNOS MIPI-CSI2 receiver (MIPI-CSIS) driver"
 	depends on REGULATOR
+	select S5P_SETUP_MIPIPHY
 	help
 	  This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC MIPI-CSI2
 	  receiver (MIPI-CSIS) devices.
diff --git a/drivers/media/platform/s5p-fimc/fimc-capture.c b/drivers/media/platform/s5p-fimc/fimc-capture.c
index 367efd1..0d0aca5 100644
--- a/drivers/media/platform/s5p-fimc/fimc-capture.c
+++ b/drivers/media/platform/s5p-fimc/fimc-capture.c
@@ -1231,6 +1231,14 @@ static int fimc_cap_qbuf(struct file *file, void *priv,
 	return vb2_qbuf(&fimc->vid_cap.vbq, buf);
 }
 
+static int fimc_cap_expbuf(struct file *file, void *priv,
+			  struct v4l2_exportbuffer *eb)
+{
+	struct fimc_dev *fimc = video_drvdata(file);
+
+	return vb2_expbuf(&fimc->vid_cap.vbq, eb);
+}
+
 static int fimc_cap_dqbuf(struct file *file, void *priv,
 			   struct v4l2_buffer *buf)
 {
@@ -1355,6 +1363,7 @@ static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
 
 	.vidioc_qbuf			= fimc_cap_qbuf,
 	.vidioc_dqbuf			= fimc_cap_dqbuf,
+	.vidioc_expbuf			= fimc_cap_expbuf,
 
 	.vidioc_prepare_buf		= fimc_cap_prepare_buf,
 	.vidioc_create_bufs		= fimc_cap_create_bufs,
@@ -1730,13 +1739,15 @@ static int fimc_register_capture_device(struct fimc_dev *fimc,
 	q = &fimc->vid_cap.vbq;
 	memset(q, 0, sizeof(*q));
 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-	q->io_modes = VB2_MMAP | VB2_USERPTR;
+	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
 	q->drv_priv = fimc->vid_cap.ctx;
 	q->ops = &fimc_capture_qops;
 	q->mem_ops = &vb2_dma_contig_memops;
 	q->buf_struct_size = sizeof(struct fimc_vid_buffer);
 
-	vb2_queue_init(q);
+	ret = vb2_queue_init(q);
+	if (ret)
+		goto err_ent;
 
 	vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK;
 	ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0);
diff --git a/drivers/media/platform/s5p-fimc/fimc-lite.c b/drivers/media/platform/s5p-fimc/fimc-lite.c
index 70bcf39..9db246b 100644
--- a/drivers/media/platform/s5p-fimc/fimc-lite.c
+++ b/drivers/media/platform/s5p-fimc/fimc-lite.c
@@ -1253,7 +1253,9 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
 	q->buf_struct_size = sizeof(struct flite_buffer);
 	q->drv_priv = fimc;
 
-	vb2_queue_init(q);
+	ret = vb2_queue_init(q);
+	if (ret < 0)
+		return ret;
 
 	fimc->vd_pad.flags = MEDIA_PAD_FL_SINK;
 	ret = media_entity_init(&vfd->entity, 1, &fimc->vd_pad, 0);
diff --git a/drivers/media/platform/s5p-fimc/fimc-m2m.c b/drivers/media/platform/s5p-fimc/fimc-m2m.c
index 4500e44..26bcf4b 100644
--- a/drivers/media/platform/s5p-fimc/fimc-m2m.c
+++ b/drivers/media/platform/s5p-fimc/fimc-m2m.c
@@ -105,7 +105,7 @@ static void fimc_device_run(void *priv)
 	struct fimc_frame *sf, *df;
 	struct fimc_dev *fimc;
 	unsigned long flags;
-	u32 ret;
+	int ret;
 
 	if (WARN(!ctx, "Null context\n"))
 		return;
@@ -439,6 +439,15 @@ static int fimc_m2m_dqbuf(struct file *file, void *fh,
 	return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
 }
 
+static int fimc_m2m_expbuf(struct file *file, void *fh,
+			    struct v4l2_exportbuffer *eb)
+{
+	struct fimc_ctx *ctx = fh_to_ctx(fh);
+
+	return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb);
+}
+
+
 static int fimc_m2m_streamon(struct file *file, void *fh,
 			     enum v4l2_buf_type type)
 {
@@ -607,6 +616,7 @@ static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
 	.vidioc_querybuf		= fimc_m2m_querybuf,
 	.vidioc_qbuf			= fimc_m2m_qbuf,
 	.vidioc_dqbuf			= fimc_m2m_dqbuf,
+	.vidioc_expbuf			= fimc_m2m_expbuf,
 	.vidioc_streamon		= fimc_m2m_streamon,
 	.vidioc_streamoff		= fimc_m2m_streamoff,
 	.vidioc_g_crop			= fimc_m2m_g_crop,
@@ -622,7 +632,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
 	int ret;
 
 	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-	src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+	src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
 	src_vq->drv_priv = ctx;
 	src_vq->ops = &fimc_qops;
 	src_vq->mem_ops = &vb2_dma_contig_memops;
@@ -633,7 +643,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
 		return ret;
 
 	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-	dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+	dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
 	dst_vq->drv_priv = ctx;
 	dst_vq->ops = &fimc_qops;
 	dst_vq->mem_ops = &vb2_dma_contig_memops;
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
index 80ada58..9bd5dd4 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
@@ -213,7 +213,7 @@ static int fimc_pipeline_close(struct fimc_pipeline *p)
  * @pipeline: video pipeline structure
  * @on: passed as the s_stream call argument
  */
-int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on)
+static int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on)
 {
 	int i, ret;
 
@@ -343,53 +343,50 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
 static int fimc_register_callback(struct device *dev, void *p)
 {
 	struct fimc_dev *fimc = dev_get_drvdata(dev);
-	struct v4l2_subdev *sd = &fimc->vid_cap.subdev;
+	struct v4l2_subdev *sd;
 	struct fimc_md *fmd = p;
-	int ret = 0;
-
-	if (!fimc || !fimc->pdev)
-		return 0;
+	int ret;
 
-	if (fimc->pdev->id < 0 || fimc->pdev->id >= FIMC_MAX_DEVS)
+	if (fimc == NULL || fimc->id >= FIMC_MAX_DEVS)
 		return 0;
 
-	fimc->pipeline_ops = &fimc_pipeline_ops;
-	fmd->fimc[fimc->pdev->id] = fimc;
+	sd = &fimc->vid_cap.subdev;
 	sd->grp_id = FIMC_GROUP_ID;
 
 	ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
 	if (ret) {
 		v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n",
 			 fimc->id, ret);
+		return ret;
 	}
 
-	return ret;
+	fimc->pipeline_ops = &fimc_pipeline_ops;
+	fmd->fimc[fimc->id] = fimc;
+	return 0;
 }
 
 static int fimc_lite_register_callback(struct device *dev, void *p)
 {
 	struct fimc_lite *fimc = dev_get_drvdata(dev);
-	struct v4l2_subdev *sd = &fimc->subdev;
 	struct fimc_md *fmd = p;
 	int ret;
 
-	if (fimc == NULL)
+	if (fimc == NULL || fimc->index >= FIMC_LITE_MAX_DEVS)
 		return 0;
 
-	if (fimc->index >= FIMC_LITE_MAX_DEVS)
-		return 0;
-
-	fimc->pipeline_ops = &fimc_pipeline_ops;
-	fmd->fimc_lite[fimc->index] = fimc;
-	sd->grp_id = FLITE_GROUP_ID;
+	fimc->subdev.grp_id = FLITE_GROUP_ID;
 
-	ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
+	ret = v4l2_device_register_subdev(&fmd->v4l2_dev, &fimc->subdev);
 	if (ret) {
 		v4l2_err(&fmd->v4l2_dev,
 			 "Failed to register FIMC-LITE.%d (%d)\n",
 			 fimc->index, ret);
+		return ret;
 	}
-	return ret;
+
+	fimc->pipeline_ops = &fimc_pipeline_ops;
+	fmd->fimc_lite[fimc->index] = fimc;
+	return 0;
 }
 
 static int csis_register_callback(struct device *dev, void *p)
@@ -407,10 +404,12 @@ static int csis_register_callback(struct device *dev, void *p)
 	v4l2_info(sd, "csis%d sd: %s\n", pdev->id, sd->name);
 
 	id = pdev->id < 0 ? 0 : pdev->id;
-	fmd->csis[id].sd = sd;
 	sd->grp_id = CSIS_GROUP_ID;
+
 	ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
-	if (ret)
+	if (!ret)
+		fmd->csis[id].sd = sd;
+	else
 		v4l2_err(&fmd->v4l2_dev,
 			 "Failed to register CSIS subdevice: %d\n", ret);
 	return ret;
@@ -548,7 +547,7 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
 		if (ret)
 			break;
 
-		v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]",
+		v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]\n",
 			  source->name, flags ? '=' : '-', sink->name);
 
 		if (flags == 0 || sensor == NULL)
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index eb6a70b..6dad9a7 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -636,6 +636,19 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 	return -EINVAL;
 }
 
+/* Export DMA buffer */
+static int vidioc_expbuf(struct file *file, void *priv,
+	struct v4l2_exportbuffer *eb)
+{
+	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+	if (eb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		return vb2_expbuf(&ctx->vq_src, eb);
+	if (eb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		return vb2_expbuf(&ctx->vq_dst, eb);
+	return -EINVAL;
+}
+
 /* Stream on */
 static int vidioc_streamon(struct file *file, void *priv,
 			   enum v4l2_buf_type type)
@@ -813,6 +826,7 @@ static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {
 	.vidioc_querybuf = vidioc_querybuf,
 	.vidioc_qbuf = vidioc_qbuf,
 	.vidioc_dqbuf = vidioc_dqbuf,
+	.vidioc_expbuf = vidioc_expbuf,
 	.vidioc_streamon = vidioc_streamon,
 	.vidioc_streamoff = vidioc_streamoff,
 	.vidioc_g_crop = vidioc_g_crop,
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index 2af6d52..f92f6dd 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -1165,6 +1165,19 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 	return ret;
 }
 
+/* Export DMA buffer */
+static int vidioc_expbuf(struct file *file, void *priv,
+	struct v4l2_exportbuffer *eb)
+{
+	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+	if (eb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		return vb2_expbuf(&ctx->vq_src, eb);
+	if (eb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		return vb2_expbuf(&ctx->vq_dst, eb);
+	return -EINVAL;
+}
+
 /* Stream on */
 static int vidioc_streamon(struct file *file, void *priv,
 			   enum v4l2_buf_type type)
@@ -1542,7 +1555,7 @@ int vidioc_encoder_cmd(struct file *file, void *priv,
 }
 
 static int vidioc_subscribe_event(struct v4l2_fh *fh,
-					struct v4l2_event_subscription *sub)
+				  const struct v4l2_event_subscription *sub)
 {
 	switch (sub->type) {
 	case V4L2_EVENT_EOS:
@@ -1568,6 +1581,7 @@ static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = {
 	.vidioc_querybuf = vidioc_querybuf,
 	.vidioc_qbuf = vidioc_qbuf,
 	.vidioc_dqbuf = vidioc_dqbuf,
+	.vidioc_expbuf = vidioc_expbuf,
 	.vidioc_streamon = vidioc_streamon,
 	.vidioc_streamoff = vidioc_streamoff,
 	.vidioc_s_parm = vidioc_s_parm,
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
index 367db75..2895333 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
@@ -28,7 +28,7 @@ static struct s5p_mfc_pm *pm;
 static struct s5p_mfc_dev *p_dev;
 
 #ifdef CLK_DEBUG
-atomic_t clk_ref;
+static atomic_t clk_ref;
 #endif
 
 int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
diff --git a/drivers/media/platform/s5p-tv/Kconfig b/drivers/media/platform/s5p-tv/Kconfig
index ea11a51..7b659bd 100644
--- a/drivers/media/platform/s5p-tv/Kconfig
+++ b/drivers/media/platform/s5p-tv/Kconfig
@@ -7,9 +7,8 @@
 # Licensed under GPL
 
 config VIDEO_SAMSUNG_S5P_TV
-	bool "Samsung TV driver for S5P platform (experimental)"
+	bool "Samsung TV driver for S5P platform"
 	depends on PLAT_S5P && PM_RUNTIME
-	depends on EXPERIMENTAL
 	default n
 	---help---
 	  Say Y here to enable selecting the TV output devices for
diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c
index 0c1cd89..7379e77 100644
--- a/drivers/media/platform/s5p-tv/mixer_video.c
+++ b/drivers/media/platform/s5p-tv/mixer_video.c
@@ -19,7 +19,6 @@
 #include <linux/videodev2.h>
 #include <linux/mm.h>
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/timer.h>
 #include <media/videobuf2-dma-contig.h>
 
@@ -698,6 +697,15 @@ static int mxr_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
 	return vb2_dqbuf(&layer->vb_queue, p, file->f_flags & O_NONBLOCK);
 }
 
+static int mxr_expbuf(struct file *file, void *priv,
+	struct v4l2_exportbuffer *eb)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+
+	mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+	return vb2_expbuf(&layer->vb_queue, eb);
+}
+
 static int mxr_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 {
 	struct mxr_layer *layer = video_drvdata(file);
@@ -725,6 +733,7 @@ static const struct v4l2_ioctl_ops mxr_ioctl_ops = {
 	.vidioc_querybuf = mxr_querybuf,
 	.vidioc_qbuf = mxr_qbuf,
 	.vidioc_dqbuf = mxr_dqbuf,
+	.vidioc_expbuf = mxr_expbuf,
 	/* Streaming control */
 	.vidioc_streamon = mxr_streamon,
 	.vidioc_streamoff = mxr_streamoff,
@@ -1093,7 +1102,7 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
 
 	layer->vb_queue = (struct vb2_queue) {
 		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
-		.io_modes = VB2_MMAP | VB2_USERPTR,
+		.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF,
 		.drv_priv = layer,
 		.buf_struct_size = sizeof(struct mxr_buffer),
 		.ops = &mxr_video_qops,
diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c
index 85fd312..a1c87f0 100644
--- a/drivers/media/platform/sh_vou.c
+++ b/drivers/media/platform/sh_vou.c
@@ -935,9 +935,10 @@ static int sh_vou_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
 /* Assume a dull encoder, do all the work ourselves. */
 static int sh_vou_s_crop(struct file *file, void *fh, const struct v4l2_crop *a)
 {
+	struct v4l2_crop a_writable = *a;
 	struct video_device *vdev = video_devdata(file);
 	struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
-	struct v4l2_rect *rect = &a->c;
+	struct v4l2_rect *rect = &a_writable.c;
 	struct v4l2_crop sd_crop = {.type = V4L2_BUF_TYPE_VIDEO_OUTPUT};
 	struct v4l2_pix_format *pix = &vou_dev->pix;
 	struct sh_vou_geometry geo;
diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig
index 9afe1e7..cb6791e 100644
--- a/drivers/media/platform/soc_camera/Kconfig
+++ b/drivers/media/platform/soc_camera/Kconfig
@@ -19,6 +19,7 @@ config MX1_VIDEO
 
 config VIDEO_MX1
 	tristate "i.MX1/i.MXL CMOS Sensor Interface driver"
+	depends on BROKEN
 	depends on VIDEO_DEV && ARCH_MX1 && SOC_CAMERA
 	select FIQ
 	select VIDEOBUF_DMA_CONTIG
diff --git a/drivers/media/platform/soc_camera/mx1_camera.c b/drivers/media/platform/soc_camera/mx1_camera.c
index bbe7099..032b8c9 100644
--- a/drivers/media/platform/soc_camera/mx1_camera.c
+++ b/drivers/media/platform/soc_camera/mx1_camera.c
@@ -470,14 +470,6 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd)
 	pcdev->icd = NULL;
 }
 
-static int mx1_camera_set_crop(struct soc_camera_device *icd,
-			       struct v4l2_crop *a)
-{
-	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-
-	return v4l2_subdev_call(sd, video, s_crop, a);
-}
-
 static int mx1_camera_set_bus_param(struct soc_camera_device *icd)
 {
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
@@ -689,7 +681,6 @@ static struct soc_camera_host_ops mx1_soc_camera_host_ops = {
 	.add		= mx1_camera_add_device,
 	.remove		= mx1_camera_remove_device,
 	.set_bus_param	= mx1_camera_set_bus_param,
-	.set_crop	= mx1_camera_set_crop,
 	.set_fmt	= mx1_camera_set_fmt,
 	.try_fmt	= mx1_camera_try_fmt,
 	.init_videobuf	= mx1_camera_init_videobuf,
diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c
index 9fd9d1c..791cd1d 100644
--- a/drivers/media/platform/soc_camera/mx2_camera.c
+++ b/drivers/media/platform/soc_camera/mx2_camera.c
@@ -41,7 +41,6 @@
 #include <linux/videodev2.h>
 
 #include <linux/platform_data/camera-mx2.h>
-#include <mach/hardware.h>
 
 #include <asm/dma.h>
 
@@ -121,11 +120,13 @@
 
 #define CSICR1			0x00
 #define CSICR2			0x04
-#define CSISR			(cpu_is_mx27() ? 0x08 : 0x18)
+#define CSISR_IMX25		0x18
+#define CSISR_IMX27		0x08
 #define CSISTATFIFO		0x0c
 #define CSIRFIFO		0x10
 #define CSIRXCNT		0x14
-#define CSICR3			(cpu_is_mx27() ? 0x1C : 0x08)
+#define CSICR3_IMX25		0x08
+#define CSICR3_IMX27		0x1c
 #define CSIDMASA_STATFIFO	0x20
 #define CSIDMATA_STATFIFO	0x24
 #define CSIDMASA_FB1		0x28
@@ -268,11 +269,17 @@ struct mx2_buffer {
 	struct mx2_buf_internal		internal;
 };
 
+enum mx2_camera_type {
+	IMX25_CAMERA,
+	IMX27_CAMERA,
+};
+
 struct mx2_camera_dev {
 	struct device		*dev;
 	struct soc_camera_host	soc_host;
 	struct soc_camera_device *icd;
-	struct clk		*clk_csi, *clk_emma_ahb, *clk_emma_ipg;
+	struct clk		*clk_emma_ahb, *clk_emma_ipg;
+	struct clk		*clk_csi_ahb, *clk_csi_per;
 
 	void __iomem		*base_csi, *base_emma;
 
@@ -291,6 +298,9 @@ struct mx2_camera_dev {
 	struct mx2_buffer	*fb2_active;
 
 	u32			csicr1;
+	u32			reg_csisr;
+	u32			reg_csicr3;
+	enum mx2_camera_type	devtype;
 
 	struct mx2_buf_internal buf_discard[2];
 	void			*discard_buffer;
@@ -303,6 +313,29 @@ struct mx2_camera_dev {
 	struct vb2_alloc_ctx	*alloc_ctx;
 };
 
+static struct platform_device_id mx2_camera_devtype[] = {
+	{
+		.name = "imx25-camera",
+		.driver_data = IMX25_CAMERA,
+	}, {
+		.name = "imx27-camera",
+		.driver_data = IMX27_CAMERA,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, mx2_camera_devtype);
+
+static inline int is_imx25_camera(struct mx2_camera_dev *pcdev)
+{
+	return pcdev->devtype == IMX25_CAMERA;
+}
+
+static inline int is_imx27_camera(struct mx2_camera_dev *pcdev)
+{
+	return pcdev->devtype == IMX27_CAMERA;
+}
+
 static struct mx2_buffer *mx2_ibuf_to_buf(struct mx2_buf_internal *int_buf)
 {
 	return container_of(int_buf, struct mx2_buffer, internal);
@@ -432,11 +465,12 @@ static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev)
 {
 	unsigned long flags;
 
-	clk_disable_unprepare(pcdev->clk_csi);
+	clk_disable_unprepare(pcdev->clk_csi_ahb);
+	clk_disable_unprepare(pcdev->clk_csi_per);
 	writel(0, pcdev->base_csi + CSICR1);
-	if (cpu_is_mx27()) {
+	if (is_imx27_camera(pcdev)) {
 		writel(0, pcdev->base_emma + PRP_CNTL);
-	} else if (cpu_is_mx25()) {
+	} else if (is_imx25_camera(pcdev)) {
 		spin_lock_irqsave(&pcdev->lock, flags);
 		pcdev->fb1_active = NULL;
 		pcdev->fb2_active = NULL;
@@ -460,13 +494,17 @@ static int mx2_camera_add_device(struct soc_camera_device *icd)
 	if (pcdev->icd)
 		return -EBUSY;
 
-	ret = clk_prepare_enable(pcdev->clk_csi);
+	ret = clk_prepare_enable(pcdev->clk_csi_ahb);
 	if (ret < 0)
 		return ret;
 
+	ret = clk_prepare_enable(pcdev->clk_csi_per);
+	if (ret < 0)
+		goto exit_csi_ahb;
+
 	csicr1 = CSICR1_MCLKEN;
 
-	if (cpu_is_mx27())
+	if (is_imx27_camera(pcdev))
 		csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC |
 			CSICR1_RXFF_LEVEL(0);
 
@@ -480,6 +518,11 @@ static int mx2_camera_add_device(struct soc_camera_device *icd)
 		 icd->devnum);
 
 	return 0;
+
+exit_csi_ahb:
+	clk_disable_unprepare(pcdev->clk_csi_ahb);
+
+	return ret;
 }
 
 static void mx2_camera_remove_device(struct soc_camera_device *icd)
@@ -542,7 +585,7 @@ out:
 static irqreturn_t mx25_camera_irq(int irq_csi, void *data)
 {
 	struct mx2_camera_dev *pcdev = data;
-	u32 status = readl(pcdev->base_csi + CSISR);
+	u32 status = readl(pcdev->base_csi + pcdev->reg_csisr);
 
 	if (status & CSISR_DMA_TSF_FB1_INT)
 		mx25_camera_frame_done(pcdev, 1, MX2_STATE_DONE);
@@ -551,7 +594,7 @@ static irqreturn_t mx25_camera_irq(int irq_csi, void *data)
 
 	/* FIXME: handle CSISR_RFF_OR_INT */
 
-	writel(status, pcdev->base_csi + CSISR);
+	writel(status, pcdev->base_csi + pcdev->reg_csisr);
 
 	return IRQ_HANDLED;
 }
@@ -636,7 +679,7 @@ static void mx2_videobuf_queue(struct vb2_buffer *vb)
 	buf->state = MX2_STATE_QUEUED;
 	list_add_tail(&buf->internal.queue, &pcdev->capture);
 
-	if (cpu_is_mx25()) {
+	if (is_imx25_camera(pcdev)) {
 		u32 csicr3, dma_inten = 0;
 
 		if (pcdev->fb1_active == NULL) {
@@ -655,20 +698,20 @@ static void mx2_videobuf_queue(struct vb2_buffer *vb)
 			list_del(&buf->internal.queue);
 			buf->state = MX2_STATE_ACTIVE;
 
-			csicr3 = readl(pcdev->base_csi + CSICR3);
+			csicr3 = readl(pcdev->base_csi + pcdev->reg_csicr3);
 
 			/* Reflash DMA */
 			writel(csicr3 | CSICR3_DMA_REFLASH_RFF,
-					pcdev->base_csi + CSICR3);
+					pcdev->base_csi + pcdev->reg_csicr3);
 
 			/* clear & enable interrupts */
-			writel(dma_inten, pcdev->base_csi + CSISR);
+			writel(dma_inten, pcdev->base_csi + pcdev->reg_csisr);
 			pcdev->csicr1 |= dma_inten;
 			writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
 
 			/* enable DMA */
 			csicr3 |= CSICR3_DMA_REQ_EN_RFF | CSICR3_RXFF_LEVEL(1);
-			writel(csicr3, pcdev->base_csi + CSICR3);
+			writel(csicr3, pcdev->base_csi + pcdev->reg_csicr3);
 		}
 	}
 
@@ -712,7 +755,7 @@ static void mx2_videobuf_release(struct vb2_buffer *vb)
 	 */
 
 	spin_lock_irqsave(&pcdev->lock, flags);
-	if (cpu_is_mx25() && buf->state == MX2_STATE_ACTIVE) {
+	if (is_imx25_camera(pcdev) && buf->state == MX2_STATE_ACTIVE) {
 		if (pcdev->fb1_active == buf) {
 			pcdev->csicr1 &= ~CSICR1_FB1_DMA_INTEN;
 			writel(0, pcdev->base_csi + CSIDMASA_FB1);
@@ -835,7 +878,7 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
 	unsigned long phys;
 	int bytesperline;
 
-	if (cpu_is_mx27()) {
+	if (is_imx27_camera(pcdev)) {
 		unsigned long flags;
 		if (count < 2)
 			return -EINVAL;
@@ -864,8 +907,10 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
 
 		bytesperline = soc_mbus_bytes_per_line(icd->user_width,
 				icd->current_fmt->host_fmt);
-		if (bytesperline < 0)
+		if (bytesperline < 0) {
+			spin_unlock_irqrestore(&pcdev->lock, flags);
 			return bytesperline;
+		}
 
 		/*
 		 * I didn't manage to properly enable/disable the prp
@@ -878,8 +923,10 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
 		pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev,
 				pcdev->discard_size, &pcdev->discard_buffer_dma,
 				GFP_KERNEL);
-		if (!pcdev->discard_buffer)
+		if (!pcdev->discard_buffer) {
+			spin_unlock_irqrestore(&pcdev->lock, flags);
 			return -ENOMEM;
+		}
 
 		pcdev->buf_discard[0].discard = true;
 		list_add_tail(&pcdev->buf_discard[0].queue,
@@ -930,7 +977,7 @@ static int mx2_stop_streaming(struct vb2_queue *q)
 	void *b;
 	u32 cntl;
 
-	if (cpu_is_mx27()) {
+	if (is_imx27_camera(pcdev)) {
 		spin_lock_irqsave(&pcdev->lock, flags);
 
 		cntl = readl(pcdev->base_emma + PRP_CNTL);
@@ -1082,11 +1129,11 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
 	if (bytesperline < 0)
 		return bytesperline;
 
-	if (cpu_is_mx27()) {
+	if (is_imx27_camera(pcdev)) {
 		ret = mx27_camera_emma_prp_reset(pcdev);
 		if (ret)
 			return ret;
-	} else if (cpu_is_mx25()) {
+	} else if (is_imx25_camera(pcdev)) {
 		writel((bytesperline * icd->user_height) >> 2,
 				pcdev->base_csi + CSIRXCNT);
 		writel((bytesperline << 16) | icd->user_height,
@@ -1099,9 +1146,10 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
 }
 
 static int mx2_camera_set_crop(struct soc_camera_device *icd,
-				struct v4l2_crop *a)
+				const struct v4l2_crop *a)
 {
-	struct v4l2_rect *rect = &a->c;
+	struct v4l2_crop a_writable = *a;
+	struct v4l2_rect *rect = &a_writable.c;
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct v4l2_mbus_framefmt mf;
 	int ret;
@@ -1392,7 +1440,7 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
 	/* FIXME: implement MX27 limits */
 
 	/* limit to MX25 hardware capabilities */
-	if (cpu_is_mx25()) {
+	if (is_imx25_camera(pcdev)) {
 		if (xlate->host_fmt->bits_per_sample <= 8)
 			width_limit = 0xffff * 4;
 		else
@@ -1726,10 +1774,31 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
 		goto exit;
 	}
 
-	pcdev->clk_csi = devm_clk_get(&pdev->dev, "ahb");
-	if (IS_ERR(pcdev->clk_csi)) {
-		dev_err(&pdev->dev, "Could not get csi clock\n");
-		err = PTR_ERR(pcdev->clk_csi);
+	pcdev->devtype = pdev->id_entry->driver_data;
+	switch (pcdev->devtype) {
+	case IMX25_CAMERA:
+		pcdev->reg_csisr = CSISR_IMX25;
+		pcdev->reg_csicr3 = CSICR3_IMX25;
+		break;
+	case IMX27_CAMERA:
+		pcdev->reg_csisr = CSISR_IMX27;
+		pcdev->reg_csicr3 = CSICR3_IMX27;
+		break;
+	default:
+		break;
+	}
+
+	pcdev->clk_csi_ahb = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(pcdev->clk_csi_ahb)) {
+		dev_err(&pdev->dev, "Could not get csi ahb clock\n");
+		err = PTR_ERR(pcdev->clk_csi_ahb);
+		goto exit;
+	}
+
+	pcdev->clk_csi_per = devm_clk_get(&pdev->dev, "per");
+	if (IS_ERR(pcdev->clk_csi_per)) {
+		dev_err(&pdev->dev, "Could not get csi per clock\n");
+		err = PTR_ERR(pcdev->clk_csi_per);
 		goto exit;
 	}
 
@@ -1739,12 +1808,13 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
 
 		pcdev->platform_flags = pcdev->pdata->flags;
 
-		rate = clk_round_rate(pcdev->clk_csi, pcdev->pdata->clk * 2);
+		rate = clk_round_rate(pcdev->clk_csi_per,
+						pcdev->pdata->clk * 2);
 		if (rate <= 0) {
 			err = -ENODEV;
 			goto exit;
 		}
-		err = clk_set_rate(pcdev->clk_csi, rate);
+		err = clk_set_rate(pcdev->clk_csi_per, rate);
 		if (err < 0)
 			goto exit;
 	}
@@ -1763,7 +1833,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
 	pcdev->dev = &pdev->dev;
 	platform_set_drvdata(pdev, pcdev);
 
-	if (cpu_is_mx25()) {
+	if (is_imx25_camera(pcdev)) {
 		err = devm_request_irq(&pdev->dev, irq_csi, mx25_camera_irq, 0,
 				       MX2_CAM_DRV_NAME, pcdev);
 		if (err) {
@@ -1772,7 +1842,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (cpu_is_mx27()) {
+	if (is_imx27_camera(pcdev)) {
 		err = mx27_camera_emma_init(pdev);
 		if (err)
 			goto exit;
@@ -1789,7 +1859,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
 	pcdev->soc_host.priv		= pcdev;
 	pcdev->soc_host.v4l2_dev.dev	= &pdev->dev;
 	pcdev->soc_host.nr		= pdev->id;
-	if (cpu_is_mx25())
+	if (is_imx25_camera(pcdev))
 		pcdev->soc_host.capabilities = SOCAM_HOST_CAP_STRIDE;
 
 	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
@@ -1802,14 +1872,14 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
 		goto exit_free_emma;
 
 	dev_info(&pdev->dev, "MX2 Camera (CSI) driver probed, clock frequency: %ld\n",
-			clk_get_rate(pcdev->clk_csi));
+			clk_get_rate(pcdev->clk_csi_per));
 
 	return 0;
 
 exit_free_emma:
 	vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
 eallocctx:
-	if (cpu_is_mx27()) {
+	if (is_imx27_camera(pcdev)) {
 		clk_disable_unprepare(pcdev->clk_emma_ipg);
 		clk_disable_unprepare(pcdev->clk_emma_ahb);
 	}
@@ -1827,7 +1897,7 @@ static int __devexit mx2_camera_remove(struct platform_device *pdev)
 
 	vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
 
-	if (cpu_is_mx27()) {
+	if (is_imx27_camera(pcdev)) {
 		clk_disable_unprepare(pcdev->clk_emma_ipg);
 		clk_disable_unprepare(pcdev->clk_emma_ahb);
 	}
@@ -1841,6 +1911,7 @@ static struct platform_driver mx2_camera_driver = {
 	.driver 	= {
 		.name	= MX2_CAM_DRV_NAME,
 	},
+	.id_table	= mx2_camera_devtype,
 	.remove		= __devexit_p(mx2_camera_remove),
 };
 
diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c
index 3557ac9..06d16de 100644
--- a/drivers/media/platform/soc_camera/mx3_camera.c
+++ b/drivers/media/platform/soc_camera/mx3_camera.c
@@ -17,6 +17,7 @@
 #include <linux/vmalloc.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
+#include <linux/dma/ipu-dma.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-dev.h>
@@ -24,7 +25,6 @@
 #include <media/soc_camera.h>
 #include <media/soc_mediabus.h>
 
-#include <mach/ipu.h>
 #include <linux/platform_data/camera-mx3.h>
 #include <linux/platform_data/dma-imx.h>
 
@@ -799,9 +799,10 @@ static inline void stride_align(__u32 *width)
  * default g_crop and cropcap from soc_camera.c
  */
 static int mx3_camera_set_crop(struct soc_camera_device *icd,
-			       struct v4l2_crop *a)
+			       const struct v4l2_crop *a)
 {
-	struct v4l2_rect *rect = &a->c;
+	struct v4l2_crop a_writable = *a;
+	struct v4l2_rect *rect = &a_writable.c;
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct mx3_camera_dev *mx3_cam = ici->priv;
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c
index fa08c76..d3cfe65 100644
--- a/drivers/media/platform/soc_camera/omap1_camera.c
+++ b/drivers/media/platform/soc_camera/omap1_camera.c
@@ -34,12 +34,13 @@
 #include <media/videobuf-dma-contig.h>
 #include <media/videobuf-dma-sg.h>
 
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 
 
 #define DRIVER_NAME		"omap1-camera"
 #define DRIVER_VERSION		"0.0.2"
 
+#define OMAP_DMA_CAMERA_IF_RX		20
 
 /*
  * ---------------------------------------------------------------------------
@@ -1215,9 +1216,9 @@ static int set_mbus_format(struct omap1_cam_dev *pcdev, struct device *dev,
 }
 
 static int omap1_cam_set_crop(struct soc_camera_device *icd,
-			       struct v4l2_crop *crop)
+			       const struct v4l2_crop *crop)
 {
-	struct v4l2_rect *rect = &crop->c;
+	const struct v4l2_rect *rect = &crop->c;
 	const struct soc_camera_format_xlate *xlate = icd->current_fmt;
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct device *dev = icd->parent;
diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c
index 1e3776d..3434ffe 100644
--- a/drivers/media/platform/soc_camera/pxa_camera.c
+++ b/drivers/media/platform/soc_camera/pxa_camera.c
@@ -1337,9 +1337,9 @@ static int pxa_camera_check_frame(u32 width, u32 height)
 }
 
 static int pxa_camera_set_crop(struct soc_camera_device *icd,
-			       struct v4l2_crop *a)
+			       const struct v4l2_crop *a)
 {
-	struct v4l2_rect *rect = &a->c;
+	const struct v4l2_rect *rect = &a->c;
 	struct device *dev = icd->parent;
 	struct soc_camera_host *ici = to_soc_camera_host(dev);
 	struct pxa_camera_dev *pcdev = ici->priv;
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index 0a24253..2d8861c 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -1182,13 +1182,13 @@ static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd)
 }
 
 /* Check if any dimension of r1 is smaller than respective one of r2 */
-static bool is_smaller(struct v4l2_rect *r1, struct v4l2_rect *r2)
+static bool is_smaller(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
 {
 	return r1->width < r2->width || r1->height < r2->height;
 }
 
 /* Check if r1 fails to cover r2 */
-static bool is_inside(struct v4l2_rect *r1, struct v4l2_rect *r2)
+static bool is_inside(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
 {
 	return r1->left > r2->left || r1->top > r2->top ||
 		r1->left + r1->width < r2->left + r2->width ||
@@ -1263,7 +1263,7 @@ static void update_subrect(struct sh_mobile_ceu_cam *cam)
  * 3. if (2) failed, try to request the maximum image
  */
 static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop,
-			 const struct v4l2_crop *cam_crop)
+			 struct v4l2_crop *cam_crop)
 {
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c;
@@ -1519,7 +1519,8 @@ static int client_scale(struct soc_camera_device *icd,
 static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
 				  const struct v4l2_crop *a)
 {
-	struct v4l2_rect *rect = &a->c;
+	struct v4l2_crop a_writable = *a;
+	const struct v4l2_rect *rect = &a_writable.c;
 	struct device *dev = icd->parent;
 	struct soc_camera_host *ici = to_soc_camera_host(dev);
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
@@ -1545,7 +1546,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
 	 * 1. - 2. Apply iterative camera S_CROP for new input window, read back
 	 * actual camera rectangle.
 	 */
-	ret = client_s_crop(icd, a, &cam_crop);
+	ret = client_s_crop(icd, &a_writable, &cam_crop);
 	if (ret < 0)
 		return ret;
 
@@ -1946,7 +1947,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
 }
 
 static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd,
-				      struct v4l2_crop *a)
+				      const struct v4l2_crop *a)
 {
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index d3f0b84..4e37356 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -645,11 +645,17 @@ static ssize_t soc_camera_read(struct file *file, char __user *buf,
 			       size_t count, loff_t *ppos)
 {
 	struct soc_camera_device *icd = file->private_data;
-	int err = -EINVAL;
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+
+	dev_dbg(icd->pdev, "read called, buf %p\n", buf);
+
+	if (ici->ops->init_videobuf2 && icd->vb2_vidq.io_modes & VB2_READ)
+		return vb2_read(&icd->vb2_vidq, buf, count, ppos,
+				file->f_flags & O_NONBLOCK);
 
 	dev_err(icd->pdev, "camera device read not implemented\n");
 
-	return err;
+	return -EINVAL;
 }
 
 static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma)
@@ -1048,10 +1054,8 @@ static void scan_add_host(struct soc_camera_host *ici)
 
 	list_for_each_entry(icd, &devices, list) {
 		if (icd->iface == ici->nr) {
-			int ret;
-
 			icd->parent = ici->v4l2_dev.dev;
-			ret = soc_camera_probe(icd);
+			soc_camera_probe(icd);
 		}
 	}
 
diff --git a/drivers/media/platform/vivi.c b/drivers/media/platform/vivi.c
index b366b05..0d59b9d 100644
--- a/drivers/media/platform/vivi.c
+++ b/drivers/media/platform/vivi.c
@@ -39,7 +39,6 @@
 /* Wake up at about 30 fps */
 #define WAKE_NUMERATOR 30
 #define WAKE_DENOMINATOR 1001
-#define BUFFER_TIMEOUT     msecs_to_jiffies(500)  /* 0.5 seconds */
 
 #define MAX_WIDTH 1920
 #define MAX_HEIGHT 1200
@@ -352,11 +351,6 @@ static void precalculate_bars(struct vivi_dev *dev)
 	}
 }
 
-#define TSTAMP_MIN_Y	24
-#define TSTAMP_MAX_Y	(TSTAMP_MIN_Y + 15)
-#define TSTAMP_INPUT_X	10
-#define TSTAMP_MIN_X	(54 + TSTAMP_INPUT_X)
-
 /* 'odd' is true for pixels 1, 3, 5, etc. and false for pixels 0, 2, 4, etc. */
 static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos, bool odd)
 {
@@ -1308,7 +1302,7 @@ static int __init vivi_create_instance(int inst)
 	/* initialize queue */
 	q = &dev->vb_vidq;
 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
 	q->drv_priv = dev;
 	q->buf_struct_size = sizeof(struct vivi_buffer);
 	q->ops = &vivi_video_qops;
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index 12c70e8..a739ad4 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -82,7 +82,7 @@ static struct radio_isa_card *rtrack_alloc(void)
 #define AIMS_BIT_VOL_UP		(1 << 6)	/* active low */
 #define AIMS_BIT_VOL_DN		(1 << 7)	/* active low */
 
-void rtrack_set_pins(void *handle, u8 pins)
+static void rtrack_set_pins(void *handle, u8 pins)
 {
 	struct radio_isa_card *isa = handle;
 	struct rtrack *rt = container_of(isa, struct rtrack, isa);
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 697a421..643d80a 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -645,7 +645,8 @@ static int __init cadet_init(void)
 	set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
 	video_set_drvdata(&dev->vdev, dev);
 
-	if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0)
+	res = video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr);
+	if (res < 0)
 		goto err_hdl;
 	v4l2_info(v4l2_dev, "ADS Cadet Radio Card at 0x%x\n", dev->io);
 	return 0;
diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c
index 3c0067d..84b7b9f 100644
--- a/drivers/media/radio/radio-isa.c
+++ b/drivers/media/radio/radio-isa.c
@@ -191,7 +191,7 @@ static bool radio_isa_valid_io(const struct radio_isa_driver *drv, int io)
 	return false;
 }
 
-struct radio_isa_card *radio_isa_alloc(struct radio_isa_driver *drv,
+static struct radio_isa_card *radio_isa_alloc(struct radio_isa_driver *drv,
 				struct device *pdev)
 {
 	struct v4l2_device *v4l2_dev;
@@ -207,8 +207,9 @@ struct radio_isa_card *radio_isa_alloc(struct radio_isa_driver *drv,
 	return isa;
 }
 
-int radio_isa_common_probe(struct radio_isa_card *isa, struct device *pdev,
-				int radio_nr, unsigned region_size)
+static int radio_isa_common_probe(struct radio_isa_card *isa,
+				  struct device *pdev,
+				  int radio_nr, unsigned region_size)
 {
 	const struct radio_isa_driver *drv = isa->drv;
 	const struct radio_isa_ops *ops = drv->ops;
@@ -287,7 +288,8 @@ err_dev_reg:
 	return res;
 }
 
-int radio_isa_common_remove(struct radio_isa_card *isa, unsigned region_size)
+static int radio_isa_common_remove(struct radio_isa_card *isa,
+				   unsigned region_size)
 {
 	const struct radio_isa_ops *ops = isa->drv->ops;
 
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 227dcdb..c260a2a 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -64,7 +64,7 @@ bool pnp_attached;
 #define FMI_BIT_VOL_SW		(1 << 3)
 #define FMI_BIT_TUN_STRQ	(1 << 4)
 
-void fmi_set_pins(void *handle, u8 pins)
+static void fmi_set_pins(void *handle, u8 pins)
 {
 	struct fmi *fmi = handle;
 	u8 bits = FMI_BIT_TUN_STRQ;
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
index d0c9053..36aec57 100644
--- a/drivers/media/radio/radio-tea5764.c
+++ b/drivers/media/radio/radio-tea5764.c
@@ -145,7 +145,7 @@ struct tea5764_device {
 };
 
 /* I2C code related */
-int tea5764_i2c_read(struct tea5764_device *radio)
+static int tea5764_i2c_read(struct tea5764_device *radio)
 {
 	int i;
 	u16 *p = (u16 *) &radio->regs;
@@ -165,7 +165,7 @@ int tea5764_i2c_read(struct tea5764_device *radio)
 	return 0;
 }
 
-int tea5764_i2c_write(struct tea5764_device *radio)
+static int tea5764_i2c_write(struct tea5764_device *radio)
 {
 	struct tea5764_write_regs wr;
 	struct tea5764_regs *r = &radio->regs;
diff --git a/drivers/media/radio/si4713-i2c.c b/drivers/media/radio/si4713-i2c.c
index e3079c1..bd61b3b 100644
--- a/drivers/media/radio/si4713-i2c.c
+++ b/drivers/media/radio/si4713-i2c.c
@@ -1769,7 +1769,7 @@ exit:
 }
 
 /* si4713_ioctl - deal with private ioctls (only rnl for now) */
-long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+static long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 {
 	struct si4713_device *sdev = to_si4713_device(sd);
 	struct si4713_rnl *rnl = arg;
diff --git a/drivers/media/radio/wl128x/fmdrv.h b/drivers/media/radio/wl128x/fmdrv.h
index d84ad9d..aac0f02 100644
--- a/drivers/media/radio/wl128x/fmdrv.h
+++ b/drivers/media/radio/wl128x/fmdrv.h
@@ -60,7 +60,7 @@
 #define fmdbg(format, ...) \
 	printk(KERN_DEBUG "fmdrv: " format, ## __VA_ARGS__)
 #else /* DEBUG */
-#define fmdbg(format, ...)
+#define fmdbg(format, ...) do {} while(0)
 #endif
 enum {
 	FM_MODE_OFF,
diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c
index bf867a6..602ef7a 100644
--- a/drivers/media/radio/wl128x/fmdrv_common.c
+++ b/drivers/media/radio/wl128x/fmdrv_common.c
@@ -742,7 +742,7 @@ static void fm_irq_handle_rdsdata_getcmd_resp(struct fmdev *fmdev)
 		if ((meta_data & FM_RDS_STATUS_ERR_MASK) != 0)
 			break;
 
-		if (blk_idx < FM_RDS_BLK_IDX_A || blk_idx > FM_RDS_BLK_IDX_D) {
+		if (blk_idx > FM_RDS_BLK_IDX_D) {
 			fmdbg("Block sequence mismatch\n");
 			rds->last_blk_idx = -1;
 			break;
diff --git a/drivers/media/radio/wl128x/fmdrv_rx.c b/drivers/media/radio/wl128x/fmdrv_rx.c
index 3dd9fc0..ebf09a3 100644
--- a/drivers/media/radio/wl128x/fmdrv_rx.c
+++ b/drivers/media/radio/wl128x/fmdrv_rx.c
@@ -305,7 +305,7 @@ int fm_rx_set_volume(struct fmdev *fmdev, u16 vol_to_set)
 	if (fmdev->curr_fmmode != FM_MODE_RX)
 		return -EPERM;
 
-	if (vol_to_set < FM_RX_VOLUME_MIN || vol_to_set > FM_RX_VOLUME_MAX) {
+	if (vol_to_set > FM_RX_VOLUME_MAX) {
 		fmerr("Volume is not within(%d-%d) range\n",
 			   FM_RX_VOLUME_MIN, FM_RX_VOLUME_MAX);
 		return -EINVAL;
diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c
index 49bb356..2d6fb26 100644
--- a/drivers/media/rc/ati_remote.c
+++ b/drivers/media/rc/ati_remote.c
@@ -784,7 +784,7 @@ static void ati_remote_rc_init(struct ati_remote *ati_remote)
 
 	rdev->priv = ati_remote;
 	rdev->driver_type = RC_DRIVER_SCANCODE;
-	rdev->allowed_protos = RC_TYPE_OTHER;
+	rdev->allowed_protos = RC_BIT_OTHER;
 	rdev->driver_name = "ati_remote";
 
 	rdev->open = ati_remote_rc_open;
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
index d05ac15..22231dd 100644
--- a/drivers/media/rc/ene_ir.c
+++ b/drivers/media/rc/ene_ir.c
@@ -329,7 +329,7 @@ static int ene_rx_get_sample_reg(struct ene_device *dev)
 }
 
 /* Sense current received carrier */
-void ene_rx_sense_carrier(struct ene_device *dev)
+static void ene_rx_sense_carrier(struct ene_device *dev)
 {
 	DEFINE_IR_RAW_EVENT(ev);
 
@@ -1003,7 +1003,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
 	dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL);
 	rdev = rc_allocate_device();
 	if (!dev || !rdev)
-		goto error1;
+		goto failure;
 
 	/* validate resources */
 	error = -ENODEV;
@@ -1014,10 +1014,10 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
 
 	if (!pnp_port_valid(pnp_dev, 0) ||
 	    pnp_port_len(pnp_dev, 0) < ENE_IO_SIZE)
-		goto error;
+		goto failure;
 
 	if (!pnp_irq_valid(pnp_dev, 0))
-		goto error;
+		goto failure;
 
 	spin_lock_init(&dev->hw_lock);
 
@@ -1033,7 +1033,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
 	/* detect hardware version and features */
 	error = ene_hw_detect(dev);
 	if (error)
-		goto error;
+		goto failure;
 
 	if (!dev->hw_learning_and_tx_capable && txsim) {
 		dev->hw_learning_and_tx_capable = true;
@@ -1046,7 +1046,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
 		learning_mode_force = false;
 
 	rdev->driver_type = RC_DRIVER_IR_RAW;
-	rdev->allowed_protos = RC_TYPE_ALL;
+	rdev->allowed_protos = RC_BIT_ALL;
 	rdev->priv = dev;
 	rdev->open = ene_open;
 	rdev->close = ene_close;
@@ -1078,30 +1078,27 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
 	/* claim the resources */
 	error = -EBUSY;
 	if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
-		dev->hw_io = -1;
-		dev->irq = -1;
-		goto error;
+		goto failure;
 	}
 
 	dev->irq = pnp_irq(pnp_dev, 0);
 	if (request_irq(dev->irq, ene_isr,
 			IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) {
-		dev->irq = -1;
-		goto error;
+		goto failure2;
 	}
 
 	error = rc_register_device(rdev);
 	if (error < 0)
-		goto error;
+		goto failure3;
 
 	pr_notice("driver has been successfully loaded\n");
 	return 0;
-error:
-	if (dev && dev->irq >= 0)
-		free_irq(dev->irq, dev);
-	if (dev && dev->hw_io >= 0)
-		release_region(dev->hw_io, ENE_IO_SIZE);
-error1:
+
+failure3:
+	free_irq(dev->irq, dev);
+failure2:
+	release_region(dev->hw_io, ENE_IO_SIZE);
+failure:
 	rc_free_device(rdev);
 	kfree(dev);
 	return error;
diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c
index 52fd769..936c3f7 100644
--- a/drivers/media/rc/fintek-cir.c
+++ b/drivers/media/rc/fintek-cir.c
@@ -541,7 +541,7 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id
 	/* Set up the rc device */
 	rdev->priv = fintek;
 	rdev->driver_type = RC_DRIVER_IR_RAW;
-	rdev->allowed_protos = RC_TYPE_ALL;
+	rdev->allowed_protos = RC_BIT_ALL;
 	rdev->open = fintek_open;
 	rdev->close = fintek_close;
 	rdev->input_name = FINTEK_DESCRIPTION;
@@ -684,12 +684,12 @@ static struct pnp_driver fintek_driver = {
 	.shutdown	= fintek_shutdown,
 };
 
-int fintek_init(void)
+static int fintek_init(void)
 {
 	return pnp_register_driver(&fintek_driver);
 }
 
-void fintek_exit(void)
+static void fintek_exit(void)
 {
 	pnp_unregister_driver(&fintek_driver);
 }
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index 04cb272..ba1a1eb 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -95,7 +95,7 @@ static int __devinit gpio_ir_recv_probe(struct platform_device *pdev)
 	if (pdata->allowed_protos)
 		rcdev->allowed_protos = pdata->allowed_protos;
 	else
-		rcdev->allowed_protos = RC_TYPE_ALL;
+		rcdev->allowed_protos = RC_BIT_ALL;
 	rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY;
 
 	gpio_dev->rcdev = rcdev;
diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
index 51d7057..5a9163d 100644
--- a/drivers/media/rc/iguanair.c
+++ b/drivers/media/rc/iguanair.c
@@ -499,7 +499,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
 	usb_to_input_id(ir->udev, &rc->input_id);
 	rc->dev.parent = &intf->dev;
 	rc->driver_type = RC_DRIVER_IR_RAW;
-	rc->allowed_protos = RC_TYPE_ALL;
+	rc->allowed_protos = RC_BIT_ALL;
 	rc->priv = ir;
 	rc->open = iguanair_open;
 	rc->close = iguanair_close;
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index 5dd0386..8f6a289 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -1001,7 +1001,7 @@ static void imon_touch_display_timeout(unsigned long data)
  * it is not, so we must acquire it prior to calling send_packet, which
  * requires that the lock is held.
  */
-static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
+static int imon_ir_change_protocol(struct rc_dev *rc, u64 *rc_type)
 {
 	int retval;
 	struct imon_context *ictx = rc->priv;
@@ -1010,31 +1010,27 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
 	unsigned char ir_proto_packet[] = {
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
 
-	if (rc_type && !(rc_type & rc->allowed_protos))
+	if (*rc_type && !(*rc_type & rc->allowed_protos))
 		dev_warn(dev, "Looks like you're trying to use an IR protocol "
 			 "this device does not support\n");
 
-	switch (rc_type) {
-	case RC_TYPE_RC6:
+	if (*rc_type & RC_BIT_RC6_MCE) {
 		dev_dbg(dev, "Configuring IR receiver for MCE protocol\n");
 		ir_proto_packet[0] = 0x01;
-		break;
-	case RC_TYPE_UNKNOWN:
-	case RC_TYPE_OTHER:
+		*rc_type = RC_BIT_RC6_MCE;
+	} else if (*rc_type & RC_BIT_OTHER) {
 		dev_dbg(dev, "Configuring IR receiver for iMON protocol\n");
 		if (!pad_stabilize)
 			dev_dbg(dev, "PAD stabilize functionality disabled\n");
 		/* ir_proto_packet[0] = 0x00; // already the default */
-		rc_type = RC_TYPE_OTHER;
-		break;
-	default:
+		*rc_type = RC_BIT_OTHER;
+	} else {
 		dev_warn(dev, "Unsupported IR protocol specified, overriding "
 			 "to iMON IR protocol\n");
 		if (!pad_stabilize)
 			dev_dbg(dev, "PAD stabilize functionality disabled\n");
 		/* ir_proto_packet[0] = 0x00; // already the default */
-		rc_type = RC_TYPE_OTHER;
-		break;
+		*rc_type = RC_BIT_OTHER;
 	}
 
 	memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
@@ -1048,7 +1044,7 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
 	if (retval)
 		goto out;
 
-	ictx->rc_type = rc_type;
+	ictx->rc_type = *rc_type;
 	ictx->pad_mouse = false;
 
 out:
@@ -1323,7 +1319,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
 		rel_x = buf[2];
 		rel_y = buf[3];
 
-		if (ictx->rc_type == RC_TYPE_OTHER && pad_stabilize) {
+		if (ictx->rc_type == RC_BIT_OTHER && pad_stabilize) {
 			if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) {
 				dir = stabilize((int)rel_x, (int)rel_y,
 						timeout, threshold);
@@ -1390,7 +1386,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
 		buf[0] = 0x01;
 		buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0;
 
-		if (ictx->rc_type == RC_TYPE_OTHER && pad_stabilize) {
+		if (ictx->rc_type == RC_BIT_OTHER && pad_stabilize) {
 			dir = stabilize((int)rel_x, (int)rel_y,
 					timeout, threshold);
 			if (!dir) {
@@ -1511,7 +1507,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
 		kc = imon_panel_key_lookup(scancode);
 	} else {
 		scancode = be32_to_cpu(*((u32 *)buf));
-		if (ictx->rc_type == RC_TYPE_RC6) {
+		if (ictx->rc_type == RC_BIT_RC6_MCE) {
 			ktype = IMON_KEY_IMON;
 			if (buf[0] == 0x80)
 				ktype = IMON_KEY_MCE;
@@ -1744,7 +1740,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
 {
 	u8 ffdc_cfg_byte = ictx->usb_rx_buf[6];
 	u8 detected_display_type = IMON_DISPLAY_TYPE_NONE;
-	u64 allowed_protos = RC_TYPE_OTHER;
+	u64 allowed_protos = RC_BIT_OTHER;
 
 	switch (ffdc_cfg_byte) {
 	/* iMON Knob, no display, iMON IR + vol knob */
@@ -1775,13 +1771,13 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
 	case 0x9e:
 		dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR");
 		detected_display_type = IMON_DISPLAY_TYPE_VFD;
-		allowed_protos = RC_TYPE_RC6;
+		allowed_protos = RC_BIT_RC6_MCE;
 		break;
 	/* iMON LCD, MCE IR */
 	case 0x9f:
 		dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR");
 		detected_display_type = IMON_DISPLAY_TYPE_LCD;
-		allowed_protos = RC_TYPE_RC6;
+		allowed_protos = RC_BIT_RC6_MCE;
 		break;
 	default:
 		dev_info(ictx->dev, "Unknown 0xffdc device, "
@@ -1789,7 +1785,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
 		detected_display_type = IMON_DISPLAY_TYPE_VFD;
 		/* We don't know which one it is, allow user to set the
 		 * RC6 one from userspace if OTHER wasn't correct. */
-		allowed_protos |= RC_TYPE_RC6;
+		allowed_protos |= RC_BIT_RC6_MCE;
 		break;
 	}
 
@@ -1875,7 +1871,7 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx)
 
 	rdev->priv = ictx;
 	rdev->driver_type = RC_DRIVER_SCANCODE;
-	rdev->allowed_protos = RC_TYPE_OTHER | RC_TYPE_RC6; /* iMON PAD or MCE */
+	rdev->allowed_protos = RC_BIT_OTHER | RC_BIT_RC6_MCE; /* iMON PAD or MCE */
 	rdev->change_protocol = imon_ir_change_protocol;
 	rdev->driver_name = MOD_NAME;
 
@@ -1893,7 +1889,7 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx)
 
 	imon_set_display_type(ictx);
 
-	if (ictx->rc_type == RC_TYPE_RC6)
+	if (ictx->rc_type == RC_BIT_RC6_MCE)
 		rdev->map_name = RC_MAP_IMON_MCE;
 	else
 		rdev->map_name = RC_MAP_IMON_PAD;
diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c
index 035668e..69edffb 100644
--- a/drivers/media/rc/ir-jvc-decoder.c
+++ b/drivers/media/rc/ir-jvc-decoder.c
@@ -47,7 +47,7 @@ static int ir_jvc_decode(struct rc_dev *dev, struct ir_raw_event ev)
 {
 	struct jvc_dec *data = &dev->raw->jvc;
 
-	if (!(dev->raw->enabled_protocols & RC_TYPE_JVC))
+	if (!(dev->raw->enabled_protocols & RC_BIT_JVC))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -174,7 +174,7 @@ out:
 }
 
 static struct ir_raw_handler jvc_handler = {
-	.protocols	= RC_TYPE_JVC,
+	.protocols	= RC_BIT_JVC,
 	.decode		= ir_jvc_decode,
 };
 
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 870c930..9945e5e 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -35,7 +35,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	struct lirc_codec *lirc = &dev->raw->lirc;
 	int sample;
 
-	if (!(dev->raw->enabled_protocols & RC_TYPE_LIRC))
+	if (!(dev->raw->enabled_protocols & RC_BIT_LIRC))
 		return 0;
 
 	if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf)
@@ -408,7 +408,7 @@ static int ir_lirc_unregister(struct rc_dev *dev)
 }
 
 static struct ir_raw_handler lirc_handler = {
-	.protocols	= RC_TYPE_LIRC,
+	.protocols	= RC_BIT_LIRC,
 	.decode		= ir_lirc_decode,
 	.raw_register	= ir_lirc_register,
 	.raw_unregister	= ir_lirc_unregister,
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index 3784ebf..33fafa4 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -216,7 +216,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u32 scancode;
 	unsigned long delay;
 
-	if (!(dev->raw->enabled_protocols & RC_TYPE_MCE_KBD))
+	if (!(dev->raw->enabled_protocols & RC_BIT_MCE_KBD))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -422,7 +422,7 @@ static int ir_mce_kbd_unregister(struct rc_dev *dev)
 }
 
 static struct ir_raw_handler mce_kbd_handler = {
-	.protocols	= RC_TYPE_MCE_KBD,
+	.protocols	= RC_BIT_MCE_KBD,
 	.decode		= ir_mce_kbd_decode,
 	.raw_register	= ir_mce_kbd_register,
 	.raw_unregister	= ir_mce_kbd_unregister,
diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
index 2ca509e..a47ee36 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -52,7 +52,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u8 address, not_address, command, not_command;
 	bool send_32bits = false;
 
-	if (!(dev->raw->enabled_protocols & RC_TYPE_NEC))
+	if (!(dev->raw->enabled_protocols & RC_BIT_NEC))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -201,7 +201,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
 }
 
 static struct ir_raw_handler nec_handler = {
-	.protocols	= RC_TYPE_NEC,
+	.protocols	= RC_BIT_NEC,
 	.decode		= ir_nec_decode,
 };
 
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index 9ab663a..5b4d1dd 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -52,8 +52,8 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u8 toggle;
 	u32 scancode;
 
-        if (!(dev->raw->enabled_protocols & RC_TYPE_RC5))
-                return 0;
+	if (!(dev->raw->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X)))
+		return 0;
 
 	if (!is_timing_event(ev)) {
 		if (ev.reset)
@@ -128,6 +128,10 @@ again:
 		if (data->wanted_bits == RC5X_NBITS) {
 			/* RC5X */
 			u8 xdata, command, system;
+			if (!(dev->raw->enabled_protocols & RC_BIT_RC5X)) {
+				data->state = STATE_INACTIVE;
+				return 0;
+			}
 			xdata    = (data->bits & 0x0003F) >> 0;
 			command  = (data->bits & 0x00FC0) >> 6;
 			system   = (data->bits & 0x1F000) >> 12;
@@ -141,6 +145,10 @@ again:
 		} else {
 			/* RC5 */
 			u8 command, system;
+			if (!(dev->raw->enabled_protocols & RC_BIT_RC5)) {
+				data->state = STATE_INACTIVE;
+				return 0;
+			}
 			command  = (data->bits & 0x0003F) >> 0;
 			system   = (data->bits & 0x007C0) >> 6;
 			toggle   = (data->bits & 0x00800) ? 1 : 0;
@@ -164,7 +172,7 @@ out:
 }
 
 static struct ir_raw_handler rc5_handler = {
-	.protocols	= RC_TYPE_RC5,
+	.protocols	= RC_BIT_RC5 | RC_BIT_RC5X,
 	.decode		= ir_rc5_decode,
 };
 
diff --git a/drivers/media/rc/ir-rc5-sz-decoder.c b/drivers/media/rc/ir-rc5-sz-decoder.c
index ec8d4a2..fd807a8 100644
--- a/drivers/media/rc/ir-rc5-sz-decoder.c
+++ b/drivers/media/rc/ir-rc5-sz-decoder.c
@@ -48,8 +48,8 @@ static int ir_rc5_sz_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u8 toggle, command, system;
 	u32 scancode;
 
-        if (!(dev->raw->enabled_protocols & RC_TYPE_RC5_SZ))
-                return 0;
+	if (!(dev->raw->enabled_protocols & RC_BIT_RC5_SZ))
+		return 0;
 
 	if (!is_timing_event(ev)) {
 		if (ev.reset)
@@ -128,7 +128,7 @@ out:
 }
 
 static struct ir_raw_handler rc5_sz_handler = {
-	.protocols	= RC_TYPE_RC5_SZ,
+	.protocols	= RC_BIT_RC5_SZ,
 	.decode		= ir_rc5_sz_decode,
 };
 
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index 4cfdd7f..e19072f 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -89,7 +89,9 @@ static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u32 scancode;
 	u8 toggle;
 
-	if (!(dev->raw->enabled_protocols & RC_TYPE_RC6))
+	if (!(dev->raw->enabled_protocols &
+	      (RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 |
+	       RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE)))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -271,7 +273,9 @@ out:
 }
 
 static struct ir_raw_handler rc6_handler = {
-	.protocols	= RC_TYPE_RC6,
+	.protocols	= RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 |
+			  RC_BIT_RC6_6A_24 | RC_BIT_RC6_6A_32 |
+			  RC_BIT_RC6_MCE,
 	.decode		= ir_rc6_decode,
 };
 
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index 546199e..9e76c7b 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -28,7 +28,6 @@
 
 #include <plat/dmtimer.h>
 #include <plat/clock.h>
-#include <plat/omap-pm.h>
 
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
@@ -480,18 +479,7 @@ struct platform_driver lirc_rx51_platform_driver = {
 		.owner	= THIS_MODULE,
 	},
 };
-
-static int __init lirc_rx51_init(void)
-{
-	return platform_driver_register(&lirc_rx51_platform_driver);
-}
-module_init(lirc_rx51_init);
-
-static void __exit lirc_rx51_exit(void)
-{
-	platform_driver_unregister(&lirc_rx51_platform_driver);
-}
-module_exit(lirc_rx51_exit);
+module_platform_driver(lirc_rx51_platform_driver);
 
 MODULE_DESCRIPTION("LIRC TX driver for Nokia RX51");
 MODULE_AUTHOR("Nokia Corporation");
diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c
index 7e54ec5..7e69a3b 100644
--- a/drivers/media/rc/ir-sanyo-decoder.c
+++ b/drivers/media/rc/ir-sanyo-decoder.c
@@ -58,7 +58,7 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u32 scancode;
 	u8 address, command, not_command;
 
-	if (!(dev->raw->enabled_protocols & RC_TYPE_SANYO))
+	if (!(dev->raw->enabled_protocols & RC_BIT_SANYO))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -179,7 +179,7 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
 }
 
 static struct ir_raw_handler sanyo_handler = {
-	.protocols	= RC_TYPE_SANYO,
+	.protocols	= RC_BIT_SANYO,
 	.decode		= ir_sanyo_decode,
 };
 
diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c
index dab98b3..fb91434 100644
--- a/drivers/media/rc/ir-sony-decoder.c
+++ b/drivers/media/rc/ir-sony-decoder.c
@@ -45,7 +45,8 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u32 scancode;
 	u8 device, subdevice, function;
 
-	if (!(dev->raw->enabled_protocols & RC_TYPE_SONY))
+	if (!(dev->raw->enabled_protocols &
+	      (RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20)))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -123,16 +124,28 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
 
 		switch (data->count) {
 		case 12:
+			if (!(dev->raw->enabled_protocols & RC_BIT_SONY12)) {
+				data->state = STATE_INACTIVE;
+				return 0;
+			}
 			device    = bitrev8((data->bits <<  3) & 0xF8);
 			subdevice = 0;
 			function  = bitrev8((data->bits >>  4) & 0xFE);
 			break;
 		case 15:
+			if (!(dev->raw->enabled_protocols & RC_BIT_SONY15)) {
+				data->state = STATE_INACTIVE;
+				return 0;
+			}
 			device    = bitrev8((data->bits >>  0) & 0xFF);
 			subdevice = 0;
 			function  = bitrev8((data->bits >>  7) & 0xFE);
 			break;
 		case 20:
+			if (!(dev->raw->enabled_protocols & RC_BIT_SONY20)) {
+				data->state = STATE_INACTIVE;
+				return 0;
+			}
 			device    = bitrev8((data->bits >>  5) & 0xF8);
 			subdevice = bitrev8((data->bits >>  0) & 0xFF);
 			function  = bitrev8((data->bits >> 12) & 0xFE);
@@ -157,7 +170,7 @@ out:
 }
 
 static struct ir_raw_handler sony_handler = {
-	.protocols	= RC_TYPE_SONY,
+	.protocols	= RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20,
 	.decode		= ir_sony_decode,
 };
 
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index 24c77a4..5e5a7f2 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
@@ -1563,7 +1563,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
 	/* set up ir-core props */
 	rdev->priv = itdev;
 	rdev->driver_type = RC_DRIVER_IR_RAW;
-	rdev->allowed_protos = RC_TYPE_ALL;
+	rdev->allowed_protos = RC_BIT_ALL;
 	rdev->open = ite_open;
 	rdev->close = ite_close;
 	rdev->s_idle = ite_s_idle;
@@ -1708,12 +1708,12 @@ static struct pnp_driver ite_driver = {
 	.shutdown	= ite_shutdown,
 };
 
-int ite_init(void)
+static int ite_init(void)
 {
 	return pnp_register_driver(&ite_driver);
 }
 
-void ite_exit(void)
+static void ite_exit(void)
 {
 	pnp_unregister_driver(&ite_driver);
 }
diff --git a/drivers/media/rc/keymaps/rc-imon-mce.c b/drivers/media/rc/keymaps/rc-imon-mce.c
index 124c722..f0da960 100644
--- a/drivers/media/rc/keymaps/rc-imon-mce.c
+++ b/drivers/media/rc/keymaps/rc-imon-mce.c
@@ -121,7 +121,7 @@ static struct rc_map_list imon_mce_map = {
 		.scan    = imon_mce,
 		.size    = ARRAY_SIZE(imon_mce),
 		/* its RC6, but w/a hardware decoder */
-		.rc_type = RC_TYPE_RC6,
+		.rc_type = RC_TYPE_RC6_MCE,
 		.name    = RC_MAP_IMON_MCE,
 	}
 };
diff --git a/drivers/media/rc/keymaps/rc-rc6-mce.c b/drivers/media/rc/keymaps/rc-rc6-mce.c
index 753e43e..ef4006f 100644
--- a/drivers/media/rc/keymaps/rc-rc6-mce.c
+++ b/drivers/media/rc/keymaps/rc-rc6-mce.c
@@ -97,7 +97,7 @@ static struct rc_map_list rc6_mce_map = {
 	.map = {
 		.scan    = rc6_mce,
 		.size    = ARRAY_SIZE(rc6_mce),
-		.rc_type = RC_TYPE_RC6,
+		.rc_type = RC_TYPE_RC6_MCE,
 		.name    = RC_MAP_RC6_MCE,
 	}
 };
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 850547f..b2146cd 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -1205,7 +1205,7 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
 	rc->dev.parent = dev;
 	rc->priv = ir;
 	rc->driver_type = RC_DRIVER_IR_RAW;
-	rc->allowed_protos = RC_TYPE_ALL;
+	rc->allowed_protos = RC_BIT_ALL;
 	rc->timeout = MS_TO_NS(100);
 	if (!ir->flags.no_tx) {
 		rc->s_tx_mask = mceusb_set_tx_mask;
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 2ea913a..e4ea89a 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -472,6 +472,7 @@ static void nvt_enable_wake(struct nvt_dev *nvt)
 	nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN);
 }
 
+#if 0 /* Currently unused */
 /* rx carrier detect only works in learning mode, must be called w/nvt_lock */
 static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt)
 {
@@ -504,7 +505,7 @@ static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt)
 
 	return carrier;
 }
-
+#endif
 /*
  * set carrier frequency
  *
@@ -620,7 +621,6 @@ static void nvt_dump_rx_buf(struct nvt_dev *nvt)
 static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
 {
 	DEFINE_IR_RAW_EVENT(rawir);
-	u32 carrier;
 	u8 sample;
 	int i;
 
@@ -629,9 +629,6 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
 	if (debug)
 		nvt_dump_rx_buf(nvt);
 
-	if (nvt->carrier_detect_enabled)
-		carrier = nvt_rx_carrier_detect(nvt);
-
 	nvt_dbg_verbose("Processing buffer of len %d", nvt->pkts);
 
 	init_ir_raw_event(&rawir);
@@ -1045,7 +1042,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
 	/* Set up the rc device */
 	rdev->priv = nvt;
 	rdev->driver_type = RC_DRIVER_IR_RAW;
-	rdev->allowed_protos = RC_TYPE_ALL;
+	rdev->allowed_protos = RC_BIT_ALL;
 	rdev->open = nvt_open;
 	rdev->close = nvt_close;
 	rdev->tx_ir = nvt_tx_ir;
@@ -1220,12 +1217,12 @@ static struct pnp_driver nvt_driver = {
 	.shutdown	= nvt_shutdown,
 };
 
-int nvt_init(void)
+static int nvt_init(void)
 {
 	return pnp_register_driver(&nvt_driver);
 }
 
-void nvt_exit(void)
+static void nvt_exit(void)
 {
 	pnp_unregister_driver(&nvt_driver);
 }
diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h
index 0d5e087..7c3674f 100644
--- a/drivers/media/rc/nuvoton-cir.h
+++ b/drivers/media/rc/nuvoton-cir.h
@@ -103,7 +103,6 @@ struct nvt_dev {
 
 	/* rx settings */
 	bool learning_enabled;
-	bool carrier_detect_enabled;
 
 	/* track cir wake state */
 	u8 wake_state;
diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c
index f9be681..53d0282 100644
--- a/drivers/media/rc/rc-loopback.c
+++ b/drivers/media/rc/rc-loopback.c
@@ -195,7 +195,7 @@ static int __init loop_init(void)
 	rc->map_name		= RC_MAP_EMPTY;
 	rc->priv		= &loopdev;
 	rc->driver_type		= RC_DRIVER_IR_RAW;
-	rc->allowed_protos	= RC_TYPE_ALL;
+	rc->allowed_protos	= RC_BIT_ALL;
 	rc->timeout		= 100 * 1000 * 1000; /* 100 ms */
 	rc->min_timeout		= 1;
 	rc->max_timeout		= UINT_MAX;
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index cabc19c..601d1ac1 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -725,25 +725,36 @@ static struct class ir_input_class = {
 	.devnode	= ir_devnode,
 };
 
+/*
+ * These are the protocol textual descriptions that are
+ * used by the sysfs protocols file. Note that the order
+ * of the entries is relevant.
+ */
 static struct {
 	u64	type;
 	char	*name;
 } proto_names[] = {
-	{ RC_TYPE_UNKNOWN,	"unknown"	},
-	{ RC_TYPE_RC5,		"rc-5"		},
-	{ RC_TYPE_NEC,		"nec"		},
-	{ RC_TYPE_RC6,		"rc-6"		},
-	{ RC_TYPE_JVC,		"jvc"		},
-	{ RC_TYPE_SONY,		"sony"		},
-	{ RC_TYPE_RC5_SZ,	"rc-5-sz"	},
-	{ RC_TYPE_SANYO,	"sanyo"		},
-	{ RC_TYPE_MCE_KBD,	"mce_kbd"	},
-	{ RC_TYPE_LIRC,		"lirc"		},
-	{ RC_TYPE_OTHER,	"other"		},
+	{ RC_BIT_NONE,		"none"		},
+	{ RC_BIT_OTHER,		"other"		},
+	{ RC_BIT_UNKNOWN,	"unknown"	},
+	{ RC_BIT_RC5 |
+	  RC_BIT_RC5X,		"rc-5"		},
+	{ RC_BIT_NEC,		"nec"		},
+	{ RC_BIT_RC6_0 |
+	  RC_BIT_RC6_6A_20 |
+	  RC_BIT_RC6_6A_24 |
+	  RC_BIT_RC6_6A_32 |
+	  RC_BIT_RC6_MCE,	"rc-6"		},
+	{ RC_BIT_JVC,		"jvc"		},
+	{ RC_BIT_SONY12 |
+	  RC_BIT_SONY15 |
+	  RC_BIT_SONY20,	"sony"		},
+	{ RC_BIT_RC5_SZ,	"rc-5-sz"	},
+	{ RC_BIT_SANYO,		"sanyo"		},
+	{ RC_BIT_MCE_KBD,	"mce_kbd"	},
+	{ RC_BIT_LIRC,		"lirc"		},
 };
 
-#define PROTO_NONE	"none"
-
 /**
  * show_protocols() - shows the current IR protocol(s)
  * @device:	the device descriptor
@@ -790,6 +801,9 @@ static ssize_t show_protocols(struct device *device,
 			tmp += sprintf(tmp, "[%s] ", proto_names[i].name);
 		else if (allowed & proto_names[i].type)
 			tmp += sprintf(tmp, "%s ", proto_names[i].name);
+
+		if (allowed & proto_names[i].type)
+			allowed &= ~proto_names[i].type;
 	}
 
 	if (tmp != buf)
@@ -867,26 +881,20 @@ static ssize_t store_protocols(struct device *device,
 			disable = false;
 		}
 
-		if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) {
-			tmp += sizeof(PROTO_NONE);
-			mask = 0;
-			count++;
-		} else {
-			for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
-				if (!strcasecmp(tmp, proto_names[i].name)) {
-					tmp += strlen(proto_names[i].name);
-					mask = proto_names[i].type;
-					break;
-				}
-			}
-			if (i == ARRAY_SIZE(proto_names)) {
-				IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
-				ret = -EINVAL;
-				goto out;
+		for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
+			if (!strcasecmp(tmp, proto_names[i].name)) {
+				mask = proto_names[i].type;
+				break;
 			}
-			count++;
 		}
 
+		if (i == ARRAY_SIZE(proto_names)) {
+			IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
+			return -EINVAL;
+		}
+
+		count++;
+
 		if (enable)
 			type |= mask;
 		else if (disable)
@@ -902,7 +910,7 @@ static ssize_t store_protocols(struct device *device,
 	}
 
 	if (dev->change_protocol) {
-		rc = dev->change_protocol(dev, type);
+		rc = dev->change_protocol(dev, &type);
 		if (rc < 0) {
 			IR_dprintk(1, "Error setting protocols to 0x%llx\n",
 				   (long long)type);
@@ -1117,7 +1125,8 @@ int rc_register_device(struct rc_dev *dev)
 	}
 
 	if (dev->change_protocol) {
-		rc = dev->change_protocol(dev, rc_map->rc_type);
+		u64 rc_type = (1 << rc_map->rc_type);
+		rc = dev->change_protocol(dev, &rc_type);
 		if (rc < 0)
 			goto out_raw;
 	}
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index 9f5a17b..a8887ab 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -1082,7 +1082,7 @@ static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3)
 	rc->dev.parent = dev;
 	rc->priv = rr3;
 	rc->driver_type = RC_DRIVER_IR_RAW;
-	rc->allowed_protos = RC_TYPE_ALL;
+	rc->allowed_protos = RC_BIT_ALL;
 	rc->timeout = US_TO_NS(2750);
 	rc->tx_ir = redrat3_transmit_ir;
 	rc->s_tx_carrier = redrat3_set_tx_carrier;
diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
index d6f4bfe..c720f12 100644
--- a/drivers/media/rc/streamzap.c
+++ b/drivers/media/rc/streamzap.c
@@ -322,7 +322,7 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz)
 	rdev->dev.parent = dev;
 	rdev->priv = sz;
 	rdev->driver_type = RC_DRIVER_IR_RAW;
-	rdev->allowed_protos = RC_TYPE_ALL;
+	rdev->allowed_protos = RC_BIT_ALL;
 	rdev->driver_name = DRIVER_NAME;
 	rdev->map_name = RC_MAP_STREAMZAP;
 
diff --git a/drivers/media/rc/ttusbir.c b/drivers/media/rc/ttusbir.c
index fef0523..f0921b5 100644
--- a/drivers/media/rc/ttusbir.c
+++ b/drivers/media/rc/ttusbir.c
@@ -316,7 +316,7 @@ static int __devinit ttusbir_probe(struct usb_interface *intf,
 	usb_to_input_id(tt->udev, &rc->input_id);
 	rc->dev.parent = &intf->dev;
 	rc->driver_type = RC_DRIVER_IR_RAW;
-	rc->allowed_protos = RC_TYPE_ALL;
+	rc->allowed_protos = RC_BIT_ALL;
 	rc->priv = tt;
 	rc->driver_name = DRIVER_NAME;
 	rc->map_name = RC_MAP_TT_1500;
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index 7c9b5f3..7f3c476 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -7,6 +7,7 @@
  *  with minor modifications.
  *
  *  Original Author: David Härdeman <david@hardeman.nu>
+ *     Copyright (C) 2012 Sean Young <sean@mess.org>
  *     Copyright (C) 2009 - 2011 David Härdeman <david@hardeman.nu>
  *
  *  Dedicated to my daughter Matilda, without whose loving attention this
@@ -22,9 +23,7 @@
  *    o IR Receive
  *    o IR Transmit
  *    o Wake-On-CIR functionality
- *
- *  To do:
- *    o Learning
+ *    o Carrier detection
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -149,6 +148,12 @@
 #define WBCIR_REGSEL_MASK	0x20
 /* Starting address of selected register in WBCIR_REG_WCEIR_INDEX */
 #define WBCIR_REG_ADDR0		0x00
+/* Enable carrier counter */
+#define WBCIR_CNTR_EN		0x01
+/* Reset carrier counter */
+#define WBCIR_CNTR_R		0x02
+/* Invert TX */
+#define WBCIR_IRTX_INV		0x04
 
 /* Valid banks for the SP3 UART */
 enum wbcir_bank {
@@ -184,7 +189,7 @@ enum wbcir_txstate {
 };
 
 /* Misc */
-#define WBCIR_NAME	"winbond-cir"
+#define WBCIR_NAME	"Winbond CIR"
 #define WBCIR_ID_FAMILY          0xF1 /* Family ID for the WPCD376I	*/
 #define	WBCIR_ID_CHIP            0x04 /* Chip ID for the WPCD376I	*/
 #define INVALID_SCANCODE   0x7FFFFFFF /* Invalid with all protos	*/
@@ -207,7 +212,8 @@ struct wbcir_data {
 	/* RX state */
 	enum wbcir_rxstate rxstate;
 	struct led_trigger *rxtrigger;
-	struct ir_raw_event rxev;
+	int carrier_report_enabled;
+	u32 pulse_duration;
 
 	/* TX state */
 	enum wbcir_txstate txstate;
@@ -330,6 +336,30 @@ wbcir_to_rc6cells(u8 val)
  *****************************************************************************/
 
 static void
+wbcir_carrier_report(struct wbcir_data *data)
+{
+	unsigned counter = inb(data->ebase + WBCIR_REG_ECEIR_CNT_LO) |
+			inb(data->ebase + WBCIR_REG_ECEIR_CNT_HI) << 8;
+
+	if (counter > 0 && counter < 0xffff) {
+		DEFINE_IR_RAW_EVENT(ev);
+
+		ev.carrier_report = 1;
+		ev.carrier = DIV_ROUND_CLOSEST(counter * 1000000u,
+						data->pulse_duration);
+
+		ir_raw_event_store(data->dev, &ev);
+	}
+
+	/* reset and restart the counter */
+	data->pulse_duration = 0;
+	wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL, WBCIR_CNTR_R,
+						WBCIR_CNTR_EN | WBCIR_CNTR_R);
+	wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL, WBCIR_CNTR_EN,
+						WBCIR_CNTR_EN | WBCIR_CNTR_R);
+}
+
+static void
 wbcir_idle_rx(struct rc_dev *dev, bool idle)
 {
 	struct wbcir_data *data = dev->priv;
@@ -339,9 +369,16 @@ wbcir_idle_rx(struct rc_dev *dev, bool idle)
 		led_trigger_event(data->rxtrigger, LED_FULL);
 	}
 
-	if (idle && data->rxstate != WBCIR_RXSTATE_INACTIVE)
+	if (idle && data->rxstate != WBCIR_RXSTATE_INACTIVE) {
+		data->rxstate = WBCIR_RXSTATE_INACTIVE;
+		led_trigger_event(data->rxtrigger, LED_OFF);
+
+		if (data->carrier_report_enabled)
+			wbcir_carrier_report(data);
+
 		/* Tell hardware to go idle by setting RXINACTIVE */
 		outb(WBCIR_RX_DISABLE, data->sbase + WBCIR_REG_SP3_ASCR);
+	}
 }
 
 static void
@@ -349,21 +386,22 @@ wbcir_irq_rx(struct wbcir_data *data, struct pnp_dev *device)
 {
 	u8 irdata;
 	DEFINE_IR_RAW_EVENT(rawir);
+	unsigned duration;
 
 	/* Since RXHDLEV is set, at least 8 bytes are in the FIFO */
 	while (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_AVAIL) {
 		irdata = inb(data->sbase + WBCIR_REG_SP3_RXDATA);
 		if (data->rxstate == WBCIR_RXSTATE_ERROR)
 			continue;
+
+		duration = ((irdata & 0x7F) + 1) * 2;
 		rawir.pulse = irdata & 0x80 ? false : true;
-		rawir.duration = US_TO_NS(((irdata & 0x7F) + 1) * 10);
-		ir_raw_event_store_with_filter(data->dev, &rawir);
-	}
+		rawir.duration = US_TO_NS(duration);
 
-	/* Check if we should go idle */
-	if (data->dev->idle) {
-		led_trigger_event(data->rxtrigger, LED_OFF);
-		data->rxstate = WBCIR_RXSTATE_INACTIVE;
+		if (rawir.pulse)
+			data->pulse_duration += duration;
+
+		ir_raw_event_store_with_filter(data->dev, &rawir);
 	}
 
 	ir_raw_event_handle(data->dev);
@@ -492,6 +530,33 @@ wbcir_irq_handler(int irqno, void *cookie)
  *****************************************************************************/
 
 static int
+wbcir_set_carrier_report(struct rc_dev *dev, int enable)
+{
+	struct wbcir_data *data = dev->priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&data->spinlock, flags);
+
+	if (data->carrier_report_enabled == enable) {
+		spin_unlock_irqrestore(&data->spinlock, flags);
+		return 0;
+	}
+
+	data->pulse_duration = 0;
+	wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL, WBCIR_CNTR_R,
+						WBCIR_CNTR_EN | WBCIR_CNTR_R);
+
+	if (enable && data->dev->idle)
+		wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL,
+				WBCIR_CNTR_EN, WBCIR_CNTR_EN | WBCIR_CNTR_R);
+
+	data->carrier_report_enabled = enable;
+	spin_unlock_irqrestore(&data->spinlock, flags);
+
+	return 0;
+}
+
+static int
 wbcir_txcarrier(struct rc_dev *dev, u32 carrier)
 {
 	struct wbcir_data *data = dev->priv;
@@ -837,7 +902,7 @@ wbcir_init_hw(struct wbcir_data *data)
 
 	/* Set IRTX_INV */
 	if (invert)
-		outb(0x04, data->ebase + WBCIR_REG_ECEIR_CCTL);
+		outb(WBCIR_IRTX_INV, data->ebase + WBCIR_REG_ECEIR_CCTL);
 	else
 		outb(0x00, data->ebase + WBCIR_REG_ECEIR_CCTL);
 
@@ -866,8 +931,8 @@ wbcir_init_hw(struct wbcir_data *data)
 	/* prescaler 1.0, tx/rx fifo lvl 16 */
 	outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2);
 
-	/* Set baud divisor to sample every 10 us */
-	outb(0x0F, data->sbase + WBCIR_REG_SP3_BGDL);
+	/* Set baud divisor to sample every 2 ns */
+	outb(0x03, data->sbase + WBCIR_REG_SP3_BGDL);
 	outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH);
 
 	/* Set CEIR mode */
@@ -876,9 +941,12 @@ wbcir_init_hw(struct wbcir_data *data)
 	inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */
 	inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */
 
-	/* Disable RX demod, enable run-length enc/dec, set freq span */
+	/*
+	 * Disable RX demod, enable run-length enc/dec, set freq span and
+	 * enable over-sampling
+	 */
 	wbcir_select_bank(data, WBCIR_BANK_7);
-	outb(0x90, data->sbase + WBCIR_REG_SP3_RCCFG);
+	outb(0xd0, data->sbase + WBCIR_REG_SP3_RCCFG);
 
 	/* Disable timer */
 	wbcir_select_bank(data, WBCIR_BANK_4);
@@ -915,9 +983,8 @@ wbcir_init_hw(struct wbcir_data *data)
 
 	/* Clear RX state */
 	data->rxstate = WBCIR_RXSTATE_INACTIVE;
-	data->rxev.duration = 0;
 	ir_raw_event_reset(data->dev);
-	ir_raw_event_handle(data->dev);
+	ir_raw_event_set_idle(data->dev, true);
 
 	/* Clear TX state */
 	if (data->txstate == WBCIR_TXSTATE_ACTIVE) {
@@ -1007,7 +1074,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
 	}
 
 	data->dev->driver_type = RC_DRIVER_IR_RAW;
-	data->dev->driver_name = WBCIR_NAME;
+	data->dev->driver_name = DRVNAME;
 	data->dev->input_name = WBCIR_NAME;
 	data->dev->input_phys = "wbcir/cir0";
 	data->dev->input_id.bustype = BUS_HOST;
@@ -1016,13 +1083,15 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
 	data->dev->input_id.version = WBCIR_ID_CHIP;
 	data->dev->map_name = RC_MAP_RC6_MCE;
 	data->dev->s_idle = wbcir_idle_rx;
+	data->dev->s_carrier_report = wbcir_set_carrier_report;
 	data->dev->s_tx_mask = wbcir_txmask;
 	data->dev->s_tx_carrier = wbcir_txcarrier;
 	data->dev->tx_ir = wbcir_tx;
 	data->dev->priv = data;
 	data->dev->dev.parent = &device->dev;
 	data->dev->timeout = MS_TO_NS(100);
-	data->dev->allowed_protos = RC_TYPE_ALL;
+	data->dev->rx_resolution = US_TO_NS(2);
+	data->dev->allowed_protos = RC_BIT_ALL;
 
 	if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) {
 		dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
diff --git a/drivers/media/tuners/max2165.c b/drivers/media/tuners/max2165.c
index ba84936..95ed46f 100644
--- a/drivers/media/tuners/max2165.c
+++ b/drivers/media/tuners/max2165.c
@@ -161,7 +161,7 @@ static int max2165_set_bandwidth(struct max2165_priv *priv, u32 bw)
 	return 0;
 }
 
-int fixpt_div32(u32 dividend, u32 divisor, u32 *quotient, u32 *fraction)
+static int fixpt_div32(u32 dividend, u32 divisor, u32 *quotient, u32 *fraction)
 {
 	u32 remainder;
 	u32 q, f = 0;
diff --git a/drivers/media/tuners/tua9001.c b/drivers/media/tuners/tua9001.c
index 3896684..83a6240 100644
--- a/drivers/media/tuners/tua9001.c
+++ b/drivers/media/tuners/tua9001.c
@@ -136,7 +136,7 @@ static int tua9001_set_params(struct dvb_frontend *fe)
 {
 	struct tua9001_priv *priv = fe->tuner_priv;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret, i;
+	int ret = 0, i;
 	u16 val;
 	u32 frequency;
 	struct reg_val data[2];
diff --git a/drivers/media/tuners/xc4000.c b/drivers/media/tuners/xc4000.c
index 4937712..5c0fd78 100644
--- a/drivers/media/tuners/xc4000.c
+++ b/drivers/media/tuners/xc4000.c
@@ -934,7 +934,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
 	int			   rc = 0, is_retry = 0;
 	u16			   hwmodel;
 	v4l2_std_id		   std0;
-	u8			   hw_major, hw_minor, fw_major, fw_minor;
+	u8			   hw_major = 0, hw_minor = 0, fw_major = 0, fw_minor = 0;
 
 	dprintk(1, "%s called\n", __func__);
 
diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c
index 448361c..0cb7c28 100644
--- a/drivers/media/usb/au0828/au0828-cards.c
+++ b/drivers/media/usb/au0828/au0828-cards.c
@@ -25,7 +25,7 @@
 #include "media/tuner.h"
 #include "media/v4l2-common.h"
 
-void hvr950q_cs5340_audio(void *priv, int enable)
+static void hvr950q_cs5340_audio(void *priv, int enable)
 {
 	/* Because the HVR-950q shares an i2s bus between the cs5340 and the
 	   au8522, we need to hold cs5340 in reset when using the au8522 */
diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c
index b328f65..9a6f156 100644
--- a/drivers/media/usb/au0828/au0828-dvb.c
+++ b/drivers/media/usb/au0828/au0828-dvb.c
@@ -272,7 +272,6 @@ static void au0828_restart_dvb_streaming(struct work_struct *work)
 	struct au0828_dev *dev = container_of(work, struct au0828_dev,
 					      restart_streaming);
 	struct au0828_dvb *dvb = &dev->dvb;
-	int ret;
 
 	if (dev->urb_streaming == 0)
 		return;
@@ -282,7 +281,7 @@ static void au0828_restart_dvb_streaming(struct work_struct *work)
 	mutex_lock(&dvb->lock);
 
 	/* Stop transport */
-	ret = stop_urb_transfer(dev);
+	stop_urb_transfer(dev);
 	au0828_write(dev, 0x608, 0x00);
 	au0828_write(dev, 0x609, 0x00);
 	au0828_write(dev, 0x60a, 0x00);
@@ -293,7 +292,7 @@ static void au0828_restart_dvb_streaming(struct work_struct *work)
 	au0828_write(dev, 0x609, 0x72);
 	au0828_write(dev, 0x60a, 0x71);
 	au0828_write(dev, 0x60b, 0x01);
-	ret = start_urb_transfer(dev);
+	start_urb_transfer(dev);
 
 	mutex_unlock(&dvb->lock);
 }
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 8705855..45387aa 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -158,7 +158,7 @@ static void au0828_irq_callback(struct urb *urb)
 /*
  * Stop and Deallocate URBs
  */
-void au0828_uninit_isoc(struct au0828_dev *dev)
+static void au0828_uninit_isoc(struct au0828_dev *dev)
 {
 	struct urb *urb;
 	int i;
@@ -197,9 +197,9 @@ void au0828_uninit_isoc(struct au0828_dev *dev)
 /*
  * Allocate URBs and start IRQ
  */
-int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
-		     int num_bufs, int max_pkt_size,
-		     int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb))
+static int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
+			    int num_bufs, int max_pkt_size,
+			    int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb))
 {
 	struct au0828_dmaqueue *dma_q = &dev->vidq;
 	int i;
@@ -783,7 +783,7 @@ static int au0828_i2s_init(struct au0828_dev *dev)
  * Auvitek au0828 analog stream enable
  * Please set interface0 to AS5 before enable the stream
  */
-int au0828_analog_stream_enable(struct au0828_dev *d)
+static int au0828_analog_stream_enable(struct au0828_dev *d)
 {
 	dprintk(1, "au0828_analog_stream_enable called\n");
 	au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
@@ -810,7 +810,7 @@ int au0828_analog_stream_disable(struct au0828_dev *d)
 	return 0;
 }
 
-void au0828_analog_stream_reset(struct au0828_dev *dev)
+static void au0828_analog_stream_reset(struct au0828_dev *dev)
 {
 	dprintk(1, "au0828_analog_stream_reset called\n");
 	au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0);
@@ -913,7 +913,7 @@ static int get_ressource(struct au0828_fh *fh)
 /* This function ensures that video frames continue to be delivered even if
    the ITU-656 input isn't receiving any data (thereby preventing applications
    such as tvtime from hanging) */
-void au0828_vid_buffer_timeout(unsigned long data)
+static void au0828_vid_buffer_timeout(unsigned long data)
 {
 	struct au0828_dev *dev = (struct au0828_dev *) data;
 	struct au0828_dmaqueue *dma_q = &dev->vidq;
@@ -937,7 +937,7 @@ void au0828_vid_buffer_timeout(unsigned long data)
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
 
-void au0828_vbi_buffer_timeout(unsigned long data)
+static void au0828_vbi_buffer_timeout(unsigned long data)
 {
 	struct au0828_dev *dev = (struct au0828_dev *) data;
 	struct au0828_dmaqueue *dma_q = &dev->vbiq;
diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c
index 447148e..7222079 100644
--- a/drivers/media/usb/cx231xx/cx231xx-avcore.c
+++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c
@@ -1068,12 +1068,12 @@ int cx231xx_unmute_audio(struct cx231xx *dev)
 }
 EXPORT_SYMBOL_GPL(cx231xx_unmute_audio);
 
-int stopAudioFirmware(struct cx231xx *dev)
+static int stopAudioFirmware(struct cx231xx *dev)
 {
 	return vid_blk_write_byte(dev, DL_CTL_CONTROL, 0x03);
 }
 
-int restartAudioFirmware(struct cx231xx *dev)
+static int restartAudioFirmware(struct cx231xx *dev)
 {
 	return vid_blk_write_byte(dev, DL_CTL_CONTROL, 0x13);
 }
@@ -2631,11 +2631,6 @@ int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type)
 			rc = cx231xx_stop_stream(dev, ep_mask);
 	}
 
-	if (dev->mode == CX231XX_ANALOG_MODE)
-		;/* do any in Analog mode */
-	else
-		;/* do any in digital mode */
-
 	return rc;
 }
 EXPORT_SYMBOL_GPL(cx231xx_capture_start);
diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c
index b84ebc5..bbed1e4 100644
--- a/drivers/media/usb/cx231xx/cx231xx-cards.c
+++ b/drivers/media/usb/cx231xx/cx231xx-cards.c
@@ -686,7 +686,7 @@ int cx231xx_tuner_callback(void *ptr, int component, int command, int arg)
 }
 EXPORT_SYMBOL_GPL(cx231xx_tuner_callback);
 
-void cx231xx_reset_out(struct cx231xx *dev)
+static void cx231xx_reset_out(struct cx231xx *dev)
 {
 	cx231xx_set_gpio_value(dev, CX23417_RESET, 1);
 	msleep(200);
@@ -694,11 +694,13 @@ void cx231xx_reset_out(struct cx231xx *dev)
 	msleep(200);
 	cx231xx_set_gpio_value(dev, CX23417_RESET, 1);
 }
-void cx231xx_enable_OSC(struct cx231xx *dev)
+
+static void cx231xx_enable_OSC(struct cx231xx *dev)
 {
 	cx231xx_set_gpio_value(dev, CX23417_OSC_EN, 1);
 }
-void cx231xx_sleep_s5h1432(struct cx231xx *dev)
+
+static void cx231xx_sleep_s5h1432(struct cx231xx *dev)
 {
 	cx231xx_set_gpio_value(dev, SLEEP_S5H1432, 0);
 }
diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c b/drivers/media/usb/cx231xx/cx231xx-i2c.c
index 781feed..96a5a09 100644
--- a/drivers/media/usb/cx231xx/cx231xx-i2c.c
+++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c
@@ -72,8 +72,8 @@ static inline bool is_tuner(struct cx231xx *dev, struct cx231xx_i2c *bus,
 /*
  * cx231xx_i2c_send_bytes()
  */
-int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap,
-			   const struct i2c_msg *msg)
+static int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap,
+				  const struct i2c_msg *msg)
 {
 	struct cx231xx_i2c *bus = i2c_adap->algo_data;
 	struct cx231xx *dev = bus->dev;
diff --git a/drivers/media/usb/cx231xx/cx231xx-input.c b/drivers/media/usb/cx231xx/cx231xx-input.c
index 96176e9..0f7b424 100644
--- a/drivers/media/usb/cx231xx/cx231xx-input.c
+++ b/drivers/media/usb/cx231xx/cx231xx-input.c
@@ -99,7 +99,7 @@ int cx231xx_ir_init(struct cx231xx *dev)
 	/* The i2c micro-controller only outputs the cmd part of NEC protocol */
 	dev->init_data.rc_dev->scanmask = 0xff;
 	dev->init_data.rc_dev->driver_name = "cx231xx";
-	dev->init_data.type = RC_TYPE_NEC;
+	dev->init_data.type = RC_BIT_NEC;
 	info.addr = 0x30;
 
 	/* Load and bind ir-kbd-i2c */
diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c b/drivers/media/usb/dvb-usb-v2/af9015.c
index 3d7526e..943d934 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -1306,7 +1306,7 @@ static int af9015_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 	if (!rc->map_name)
 		rc->map_name = RC_MAP_EMPTY;
 
-	rc->allowed_protos = RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_NEC;
 	rc->query = af9015_rc_query;
 	rc->interval = 500;
 
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
index ea27eaf..61ae7f9 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -1023,10 +1023,10 @@ static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 		switch (tmp) {
 		case 0: /* NEC */
 		default:
-			rc->allowed_protos = RC_TYPE_NEC;
+			rc->allowed_protos = RC_BIT_NEC;
 			break;
 		case 1: /* RC6 */
-			rc->allowed_protos = RC_TYPE_RC6;
+			rc->allowed_protos = RC_BIT_RC6_MCE;
 			break;
 		}
 
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c
index ec540140..d05c5b5 100644
--- a/drivers/media/usb/dvb-usb-v2/anysee.c
+++ b/drivers/media/usb/dvb-usb-v2/anysee.c
@@ -1048,7 +1048,7 @@ static int anysee_rc_query(struct dvb_usb_device *d)
 
 static int anysee_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 {
-	rc->allowed_protos = RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_NEC;
 	rc->query          = anysee_rc_query;
 	rc->interval       = 250;  /* windows driver uses 500ms */
 
@@ -1170,7 +1170,7 @@ static int anysee_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot,
 	struct dvb_usb_device *d = ci->data;
 	struct anysee_state *state = d_to_priv(d);
 	int ret;
-	u8 tmp;
+	u8 tmp = 0;
 
 	ret = anysee_rd_reg_mask(d, REG_IOC, &tmp, 0x40);
 	if (ret)
diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c
index 54f1221..d75dbf2 100644
--- a/drivers/media/usb/dvb-usb-v2/az6007.c
+++ b/drivers/media/usb/dvb-usb-v2/az6007.c
@@ -826,7 +826,7 @@ static int az6007_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 {
 	pr_debug("Getting az6007 Remote Control properties\n");
 
-	rc->allowed_protos = RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_NEC;
 	rc->query          = az6007_rc_query;
 	rc->interval       = 400;
 
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
index bae16a1..059291b 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
@@ -137,7 +137,7 @@ struct dvb_usb_driver_info {
 struct dvb_usb_rc {
 	const char *map_name;
 	u64 allowed_protos;
-	int (*change_protocol)(struct rc_dev *dev, u64 rc_type);
+	int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
 	int (*query) (struct dvb_usb_device *d);
 	unsigned int interval;
 	const enum rc_driver_type driver_type;
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
index 9859d2a..671b4fa 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -224,7 +224,7 @@ static void dvb_usb_data_complete_raw(struct usb_data_stream *stream, u8 *buf,
 	dvb_dmx_swfilter_raw(&adap->demux, buf, len);
 }
 
-int dvb_usbv2_adapter_stream_init(struct dvb_usb_adapter *adap)
+static int dvb_usbv2_adapter_stream_init(struct dvb_usb_adapter *adap)
 {
 	dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__,
 			adap->id);
@@ -236,7 +236,7 @@ int dvb_usbv2_adapter_stream_init(struct dvb_usb_adapter *adap)
 	return usb_urb_initv2(&adap->stream, &adap->props->stream);
 }
 
-int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap)
+static int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap)
 {
 	dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__,
 			adap->id);
@@ -283,14 +283,13 @@ static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed,
 
 	/* activate the pid on the device pid filter */
 	if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER &&
-			adap->pid_filtering &&
-			adap->props->pid_filter)
+			adap->pid_filtering && adap->props->pid_filter) {
 		ret = adap->props->pid_filter(adap, dvbdmxfeed->index,
 				dvbdmxfeed->pid, (count == 1) ? 1 : 0);
-			if (ret < 0)
-				dev_err(&d->udev->dev, "%s: pid_filter() " \
-						"failed=%d\n", KBUILD_MODNAME,
-						ret);
+		if (ret < 0)
+			dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n",
+					KBUILD_MODNAME, ret);
+	}
 
 	/* start feeding if it is first pid */
 	if (adap->feed_count == 1 && count == 1) {
@@ -369,7 +368,7 @@ static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 	return dvb_usb_ctrl_feed(dvbdmxfeed, -1);
 }
 
-int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap)
+static int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap)
 {
 	int ret;
 	struct dvb_usb_device *d = adap_to_d(adap);
@@ -441,7 +440,7 @@ err_dvb_register_adapter:
 	return ret;
 }
 
-int dvb_usbv2_adapter_dvb_exit(struct dvb_usb_adapter *adap)
+static int dvb_usbv2_adapter_dvb_exit(struct dvb_usb_adapter *adap)
 {
 	dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__,
 			adap->id);
@@ -457,7 +456,7 @@ int dvb_usbv2_adapter_dvb_exit(struct dvb_usb_adapter *adap)
 	return 0;
 }
 
-int dvb_usbv2_device_power_ctrl(struct dvb_usb_device *d, int onoff)
+static int dvb_usbv2_device_power_ctrl(struct dvb_usb_device *d, int onoff)
 {
 	int ret;
 
@@ -554,7 +553,7 @@ err:
 	return ret;
 }
 
-int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap)
+static int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap)
 {
 	int ret, i, count_registered = 0;
 	struct dvb_usb_device *d = adap_to_d(adap);
@@ -623,7 +622,7 @@ err:
 	return ret;
 }
 
-int dvb_usbv2_adapter_frontend_exit(struct dvb_usb_adapter *adap)
+static int dvb_usbv2_adapter_frontend_exit(struct dvb_usb_adapter *adap)
 {
 	int i;
 	dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__,
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c
index 0431bee..5716662 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c
@@ -32,9 +32,7 @@ int dvb_usbv2_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
 		return -EINVAL;
 	}
 
-	ret = mutex_lock_interruptible(&d->usb_mutex);
-	if (ret < 0)
-		return ret;
+	mutex_lock(&d->usb_mutex);
 
 	dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, wlen, wbuf);
 
diff --git a/drivers/media/usb/dvb-usb-v2/it913x.c b/drivers/media/usb/dvb-usb-v2/it913x.c
index 695f910..4720428 100644
--- a/drivers/media/usb/dvb-usb-v2/it913x.c
+++ b/drivers/media/usb/dvb-usb-v2/it913x.c
@@ -659,13 +659,19 @@ static int it913x_frontend_attach(struct dvb_usb_adapter *adap)
 		it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_SW_RST, 0x1);
 		it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x0f);
 		it913x_wr_reg(d, DEV_0, EP0_TX_NAK, 0x1b);
-		it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x2f);
+		if (st->proprietary_ir == false) /* Enable endpoint 3 */
+			it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x3f);
+		else
+			it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x2f);
 		it913x_wr_reg(d, DEV_0, EP4_TX_LEN_LSB,
 					ep_size & 0xff);
 		it913x_wr_reg(d, DEV_0, EP4_TX_LEN_MSB, ep_size >> 8);
 		ret = it913x_wr_reg(d, DEV_0, EP4_MAX_PKT, pkt_size);
 	} else if (adap->id == 1 && adap->fe[0]) {
-		it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x6f);
+		if (st->proprietary_ir == false)
+			it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x7f);
+		else
+			it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x6f);
 		it913x_wr_reg(d, DEV_0, EP5_TX_LEN_LSB,
 					ep_size & 0xff);
 		it913x_wr_reg(d, DEV_0, EP5_TX_LEN_MSB, ep_size >> 8);
@@ -698,7 +704,7 @@ static int it913x_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 		return 0;
 	}
 
-	rc->allowed_protos = RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_NEC;
 	rc->query = it913x_rc_query;
 	rc->interval = 250;
 
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c
index c41d9d9..6427ac3 100644
--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
+++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
@@ -799,7 +799,7 @@ static const char fw_c_rs2000[] = LME2510_C_RS2000;
 static const char fw_lg[] = LME2510_LG;
 static const char fw_s0194[] = LME2510_S0194;
 
-const char *lme_firmware_switch(struct dvb_usb_device *d, int cold)
+static const char *lme_firmware_switch(struct dvb_usb_device *d, int cold)
 {
 	struct lme2510_state *st = d->priv;
 	struct usb_device *udev = d->udev;
@@ -1253,7 +1253,7 @@ static int lme2510_get_stream_config(struct dvb_frontend *fe, u8 *ts_type,
 static int lme2510_get_rc_config(struct dvb_usb_device *d,
 	struct dvb_usb_rc *rc)
 {
-	rc->allowed_protos = RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_NEC;
 	return 0;
 }
 
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index adabba8..223f0e7 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -1197,7 +1197,7 @@ static int rtl2831u_get_rc_config(struct dvb_usb_device *d,
 		struct dvb_usb_rc *rc)
 {
 	rc->map_name = RC_MAP_EMPTY;
-	rc->allowed_protos = RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_NEC;
 	rc->query = rtl2831u_rc_query;
 	rc->interval = 400;
 
@@ -1269,7 +1269,7 @@ static int rtl2832u_get_rc_config(struct dvb_usb_device *d,
 		struct dvb_usb_rc *rc)
 {
 	rc->map_name = RC_MAP_EMPTY;
-	rc->allowed_protos = RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_NEC;
 	rc->query = rtl2832u_rc_query;
 	rc->interval = 400;
 
@@ -1346,6 +1346,10 @@ static const struct usb_device_id rtl28xxu_id_table[] = {
 		&rtl2832u_props, "DigitalNow Quad DVB-T Receiver", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d3,
 		&rtl2832u_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) },
+	{ DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1102,
+		&rtl2832u_props, "Dexatek DK mini DVB-T Dongle", NULL) },
+	{ DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d7,
+		&rtl2832u_props, "TerraTec Cinergy T Stick+", NULL) },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table);
diff --git a/drivers/media/usb/dvb-usb-v2/usb_urb.c b/drivers/media/usb/dvb-usb-v2/usb_urb.c
index 5989b65..7346f85 100644
--- a/drivers/media/usb/dvb-usb-v2/usb_urb.c
+++ b/drivers/media/usb/dvb-usb-v2/usb_urb.c
@@ -112,7 +112,7 @@ int usb_urb_submitv2(struct usb_data_stream *stream,
 	return 0;
 }
 
-int usb_urb_free_urbs(struct usb_data_stream *stream)
+static int usb_urb_free_urbs(struct usb_data_stream *stream)
 {
 	int i;
 
@@ -205,7 +205,7 @@ static int usb_urb_alloc_isoc_urbs(struct usb_data_stream *stream)
 	return 0;
 }
 
-int usb_free_stream_buffers(struct usb_data_stream *stream)
+static int usb_free_stream_buffers(struct usb_data_stream *stream)
 {
 	if (stream->state & USB_STATE_URB_BUF) {
 		while (stream->buf_num) {
@@ -223,8 +223,8 @@ int usb_free_stream_buffers(struct usb_data_stream *stream)
 	return 0;
 }
 
-int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num,
-		unsigned long size)
+static int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num,
+				    unsigned long size)
 {
 	stream->buf_num = 0;
 	stream->buf_size = size;
diff --git a/drivers/media/usb/dvb-usb/az6027.c b/drivers/media/usb/dvb-usb/az6027.c
index 5e45ae6..91e0119 100644
--- a/drivers/media/usb/dvb-usb/az6027.c
+++ b/drivers/media/usb/dvb-usb/az6027.c
@@ -298,7 +298,8 @@ struct stb6100_config az6027_stb6100_config = {
 
 
 /* check for mutex FIXME */
-int az6027_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+static int az6027_usb_in_op(struct dvb_usb_device *d, u8 req,
+			    u16 value, u16 index, u8 *b, int blen)
 {
 	int ret = -1;
 	if (mutex_lock_interruptible(&d->usb_mutex))
@@ -1051,10 +1052,10 @@ static struct i2c_algorithm az6027_i2c_algo = {
 	.functionality = az6027_i2c_func,
 };
 
-int az6027_identify_state(struct usb_device *udev,
-			  struct dvb_usb_device_properties *props,
-			  struct dvb_usb_device_description **desc,
-			  int *cold)
+static int az6027_identify_state(struct usb_device *udev,
+				 struct dvb_usb_device_properties *props,
+				 struct dvb_usb_device_description **desc,
+				 int *cold)
 {
 	u8 *b;
 	s16 ret;
diff --git a/drivers/media/usb/dvb-usb/dib0700.h b/drivers/media/usb/dvb-usb/dib0700.h
index 7de125c..637b612 100644
--- a/drivers/media/usb/dvb-usb/dib0700.h
+++ b/drivers/media/usb/dvb-usb/dib0700.h
@@ -64,7 +64,7 @@ extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
 extern struct i2c_algorithm dib0700_i2c_algo;
 extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
 			struct dvb_usb_device_description **desc, int *cold);
-extern int dib0700_change_protocol(struct rc_dev *dev, u64 rc_type);
+extern int dib0700_change_protocol(struct rc_dev *dev, u64 *rc_type);
 extern int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz);
 
 extern int dib0700_device_count;
diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c
index ef87229..19b5ed2 100644
--- a/drivers/media/usb/dvb-usb/dib0700_core.c
+++ b/drivers/media/usb/dvb-usb/dib0700_core.c
@@ -605,7 +605,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 	return ret;
 }
 
-int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
+int dib0700_change_protocol(struct rc_dev *rc, u64 *rc_type)
 {
 	struct dvb_usb_device *d = rc->priv;
 	struct dib0700_state *st = d->priv;
@@ -621,17 +621,19 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
 	st->buf[2] = 0;
 
 	/* Set the IR mode */
-	if (rc_type == RC_TYPE_RC5)
+	if (*rc_type & RC_BIT_RC5) {
 		new_proto = 1;
-	else if (rc_type == RC_TYPE_NEC)
+		*rc_type = RC_BIT_RC5;
+	} else if (*rc_type & RC_BIT_NEC) {
 		new_proto = 0;
-	else if (rc_type == RC_TYPE_RC6) {
+		*rc_type = RC_BIT_NEC;
+	} else if (*rc_type & RC_BIT_RC6_MCE) {
 		if (st->fw_version < 0x10200) {
 			ret = -EINVAL;
 			goto out;
 		}
-
 		new_proto = 2;
+		*rc_type = RC_BIT_RC6_MCE;
 	} else {
 		ret = -EINVAL;
 		goto out;
@@ -645,7 +647,7 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
 		goto out;
 	}
 
-	d->props.rc.core.protocol = rc_type;
+	d->props.rc.core.protocol = *rc_type;
 
 out:
 	mutex_unlock(&d->usb_mutex);
@@ -707,7 +709,7 @@ static void dib0700_rc_urb_completion(struct urb *purb)
 		 purb->actual_length);
 
 	switch (d->props.rc.core.protocol) {
-	case RC_TYPE_NEC:
+	case RC_BIT_NEC:
 		toggle = 0;
 
 		/* NEC protocol sends repeat code as 0 0 0 FF */
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c
index 510001d..1179842 100644
--- a/drivers/media/usb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
@@ -518,7 +518,7 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
 
 	d->last_event = 0;
 	switch (d->props.rc.core.protocol) {
-	case RC_TYPE_NEC:
+	case RC_BIT_NEC:
 		/* NEC protocol sends repeat code as 0 0 0 FF */
 		if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
 		    (key[3] == 0xff))
@@ -3658,9 +3658,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_interval      = DEFAULT_RC_INTERVAL,
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3698,9 +3698,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_interval      = DEFAULT_RC_INTERVAL,
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3763,9 +3763,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_interval      = DEFAULT_RC_INTERVAL,
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3808,9 +3808,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3890,9 +3890,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3936,9 +3936,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3987,9 +3987,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4055,9 +4055,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4106,9 +4106,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_NEC_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4177,9 +4177,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4215,9 +4215,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4295,9 +4295,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4341,9 +4341,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_NEC_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4394,9 +4394,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4433,9 +4433,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4472,9 +4472,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4511,9 +4511,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4550,9 +4550,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4589,9 +4589,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4644,9 +4644,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4681,9 +4681,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4721,9 +4721,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4761,9 +4761,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4802,9 +4802,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	},
diff --git a/drivers/media/usb/dvb-usb/dvb-usb.h b/drivers/media/usb/dvb-usb/dvb-usb.h
index aab0f99..ce4c4e3 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb.h
+++ b/drivers/media/usb/dvb-usb/dvb-usb.h
@@ -202,7 +202,7 @@ struct dvb_rc {
 	u64 protocol;
 	u64 allowed_protos;
 	enum rc_driver_type driver_type;
-	int (*change_protocol)(struct rc_dev *dev, u64 rc_type);
+	int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
 	char *module_name;
 	int (*rc_query) (struct dvb_usb_device *d);
 	int rc_interval;
diff --git a/drivers/media/usb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c
index 02e8785..d1ddfa1 100644
--- a/drivers/media/usb/dvb-usb/pctv452e.c
+++ b/drivers/media/usb/dvb-usb/pctv452e.c
@@ -927,7 +927,7 @@ static struct dvb_usb_device_properties pctv452e_properties = {
 
 	.rc.core = {
 		.rc_codes	= RC_MAP_DIB0700_RC5_TABLE,
-		.allowed_protos	= RC_TYPE_UNKNOWN,
+		.allowed_protos	= RC_BIT_UNKNOWN,
 		.rc_query	= pctv452e_rc_query,
 		.rc_interval	= 100,
 	},
@@ -980,7 +980,7 @@ static struct dvb_usb_device_properties tt_connect_s2_3600_properties = {
 
 	.rc.core = {
 		.rc_codes	= RC_MAP_TT_1500,
-		.allowed_protos	= RC_TYPE_UNKNOWN,
+		.allowed_protos	= RC_BIT_UNKNOWN,
 		.rc_query	= pctv452e_rc_query,
 		.rc_interval	= 100,
 	},
diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c
index 7a8c8c1..40832a1 100644
--- a/drivers/media/usb/dvb-usb/technisat-usb2.c
+++ b/drivers/media/usb/dvb-usb/technisat-usb2.c
@@ -732,7 +732,7 @@ static struct dvb_usb_device_properties technisat_usb2_devices = {
 		.rc_codes    = RC_MAP_TECHNISAT_USB2,
 		.module_name = "technisat-usb2",
 		.rc_query    = technisat_usb2_rc_query,
-		.allowed_protos = RC_TYPE_ALL,
+		.allowed_protos = RC_BIT_ALL,
 		.driver_type    = RC_DRIVER_IR_RAW,
 	}
 };
diff --git a/drivers/media/usb/dvb-usb/ttusb2.c b/drivers/media/usb/dvb-usb/ttusb2.c
index 6a50cde..bcdac22 100644
--- a/drivers/media/usb/dvb-usb/ttusb2.c
+++ b/drivers/media/usb/dvb-usb/ttusb2.c
@@ -741,7 +741,7 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
 		.rc_interval      = 150, /* Less than IR_KEYPRESS_TIMEOUT */
 		.rc_codes         = RC_MAP_TT_1500,
 		.rc_query         = tt3650_rc_query,
-		.allowed_protos   = RC_TYPE_UNKNOWN,
+		.allowed_protos   = RC_BIT_UNKNOWN,
 	},
 
 	.num_adapters = 1,
diff --git a/drivers/media/usb/dvb-usb/vp702x.c b/drivers/media/usb/dvb-usb/vp702x.c
index 07c673a..22cf9f9 100644
--- a/drivers/media/usb/dvb-usb/vp702x.c
+++ b/drivers/media/usb/dvb-usb/vp702x.c
@@ -56,7 +56,7 @@ static int vp702x_usb_in_op_unlocked(struct dvb_usb_device *d, u8 req,
 }
 
 int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value,
-			    u16 index, u8 *b, int blen)
+		     u16 index, u8 *b, int blen)
 {
 	int ret;
 
@@ -67,8 +67,8 @@ int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value,
 	return ret;
 }
 
-int vp702x_usb_out_op_unlocked(struct dvb_usb_device *d, u8 req, u16 value,
-				      u16 index, u8 *b, int blen)
+static int vp702x_usb_out_op_unlocked(struct dvb_usb_device *d, u8 req,
+				      u16 value, u16 index, u8 *b, int blen)
 {
 	int ret;
 	deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index);
@@ -86,7 +86,7 @@ int vp702x_usb_out_op_unlocked(struct dvb_usb_device *d, u8 req, u16 value,
 		return 0;
 }
 
-int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
 			     u16 index, u8 *b, int blen)
 {
 	int ret;
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index 16a84f9..619bffb 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -1979,6 +1979,15 @@ struct em28xx_board em28xx_boards[] = {
 				EM28XX_I2C_CLK_WAIT_ENABLE |
 				EM28XX_I2C_FREQ_400_KHZ,
 	},
+	[EM2884_BOARD_TERRATEC_HTC_USB_XS] = {
+		.name         = "Terratec Cinergy HTC USB XS",
+		.has_dvb      = 1,
+		.ir_codes     = RC_MAP_NEC_TERRATEC_CINERGY_XS,
+		.tuner_type   = TUNER_ABSENT,
+		.i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
+				EM28XX_I2C_CLK_WAIT_ENABLE |
+				EM28XX_I2C_FREQ_400_KHZ,
+	},
 };
 const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
 
@@ -2057,9 +2066,9 @@ struct usb_device_id em28xx_id_table[] = {
 	{ USB_DEVICE(0x0ccd, 0x0043),
 			.driver_info = EM2870_BOARD_TERRATEC_XS },
 	{ USB_DEVICE(0x0ccd, 0x008e),	/* Cinergy HTC USB XS Rev. 1 */
-			.driver_info = EM2884_BOARD_TERRATEC_H5 },
+			.driver_info = EM2884_BOARD_TERRATEC_HTC_USB_XS },
 	{ USB_DEVICE(0x0ccd, 0x00ac),	/* Cinergy HTC USB XS Rev. 2 */
-			.driver_info = EM2884_BOARD_TERRATEC_H5 },
+			.driver_info = EM2884_BOARD_TERRATEC_HTC_USB_XS },
 	{ USB_DEVICE(0x0ccd, 0x10a2),	/* H5 Rev. 1 */
 			.driver_info = EM2884_BOARD_TERRATEC_H5 },
 	{ USB_DEVICE(0x0ccd, 0x10ad),	/* H5 Rev. 2 */
@@ -3297,7 +3306,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
 
 	dev->num_alt = interface->num_altsetting;
 
-	if ((card[nr] >= 0) && (card[nr] < em28xx_bcount))
+	if ((unsigned)card[nr] < em28xx_bcount)
 		dev->model = card[nr];
 
 	/* save our data pointer in this interface device */
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index 13ae821..63f2e70 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -331,7 +331,7 @@ static struct drxk_config hauppauge_930c_drxk = {
 	.load_firmware_sync = true,
 };
 
-struct drxk_config terratec_htc_stick_drxk = {
+static struct drxk_config terratec_htc_stick_drxk = {
 	.adr = 0x29,
 	.single_master = 1,
 	.no_i2c_bridge = 1,
@@ -520,7 +520,10 @@ static void terratec_htc_stick_init(struct em28xx *dev)
 		{ -1,                   -1,     -1,     -1},
 	};
 
-	/* Init the analog decoder? */
+	/*
+	 * Init the analog decoder (not yet supported), but
+	 * it's probably still a good idea.
+	 */
 	struct {
 		unsigned char r[4];
 		int len;
@@ -547,6 +550,64 @@ static void terratec_htc_stick_init(struct em28xx *dev)
 	em28xx_gpio_set(dev, terratec_htc_stick_end);
 };
 
+static void terratec_htc_usb_xs_init(struct em28xx *dev)
+{
+	int i;
+
+	struct em28xx_reg_seq terratec_htc_usb_xs_init[] = {
+		{EM28XX_R08_GPIO,	0xff,	0xff,	10},
+		{EM2874_R80_GPIO,	0xb2,	0xff,	100},
+		{EM2874_R80_GPIO,	0xb2,	0xff,	50},
+		{EM2874_R80_GPIO,	0xb6,	0xff,	100},
+		{ -1,                   -1,     -1,     -1},
+	};
+	struct em28xx_reg_seq terratec_htc_usb_xs_end[] = {
+		{EM2874_R80_GPIO,	0xa6,	0xff,	100},
+		{EM2874_R80_GPIO,	0xa6,	0xff,	50},
+		{EM2874_R80_GPIO,	0xe6,	0xff,	100},
+		{ -1,                   -1,     -1,     -1},
+	};
+
+	/*
+	 * Init the analog decoder (not yet supported), but
+	 * it's probably still a good idea.
+	 */
+	struct {
+		unsigned char r[4];
+		int len;
+	} regs[] = {
+		{{ 0x06, 0x02, 0x00, 0x31 }, 4},
+		{{ 0x01, 0x02 }, 2},
+		{{ 0x01, 0x02, 0x00, 0xc6 }, 4},
+		{{ 0x01, 0x00 }, 2},
+		{{ 0x01, 0x00, 0xff, 0xaf }, 4},
+		{{ 0x01, 0x00, 0x03, 0xa0 }, 4},
+		{{ 0x01, 0x00 }, 2},
+		{{ 0x01, 0x00, 0x73, 0xaf }, 4},
+		{{ 0x04, 0x00 }, 2},
+		{{ 0x00, 0x04 }, 2},
+		{{ 0x00, 0x04, 0x00, 0x0a }, 4},
+		{{ 0x04, 0x14 }, 2},
+		{{ 0x04, 0x14, 0x00, 0x00 }, 4},
+	};
+
+	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
+
+	em28xx_gpio_set(dev, terratec_htc_usb_xs_init);
+
+	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
+	msleep(10);
+	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
+	msleep(10);
+
+	dev->i2c_client.addr = 0x82 >> 1;
+
+	for (i = 0; i < ARRAY_SIZE(regs); i++)
+		i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
+
+	em28xx_gpio_set(dev, terratec_htc_usb_xs_end);
+};
+
 static void pctv_520e_init(struct em28xx *dev)
 {
 	/*
@@ -1155,6 +1216,25 @@ static int em28xx_dvb_init(struct em28xx *dev)
 			goto out_free;
 		}
 		break;
+	case EM2884_BOARD_TERRATEC_HTC_USB_XS:
+		terratec_htc_usb_xs_init(dev);
+
+		/* attach demodulator */
+		dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk,
+					&dev->i2c_adap);
+		if (!dvb->fe[0]) {
+			result = -EINVAL;
+			goto out_free;
+		}
+
+		/* Attach the demodulator. */
+		if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
+				&dev->i2c_adap,
+				&em28xx_cxd2820r_tda18271_config)) {
+			result = -EINVAL;
+			goto out_free;
+		}
+		break;
 	default:
 		em28xx_errdev("/2: The frontend of your DVB/ATSC card"
 				" isn't supported yet\n");
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
index 97d36b4..660bf80 100644
--- a/drivers/media/usb/em28xx/em28xx-input.c
+++ b/drivers/media/usb/em28xx/em28xx-input.c
@@ -345,7 +345,7 @@ static void em28xx_ir_stop(struct rc_dev *rc)
 	cancel_delayed_work_sync(&ir->work);
 }
 
-static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
+static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type)
 {
 	int rc = 0;
 	struct em28xx_IR *ir = rc_dev->priv;
@@ -354,14 +354,16 @@ static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
 
 	/* Adjust xclk based o IR table for RC5/NEC tables */
 
-	if (rc_type == RC_TYPE_RC5) {
+	if (*rc_type & RC_BIT_RC5) {
 		dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE;
 		ir->full_code = 1;
-	} else if (rc_type == RC_TYPE_NEC) {
+		*rc_type = RC_BIT_RC5;
+	} else if (*rc_type & RC_BIT_NEC) {
 		dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE;
 		ir_config = EM2874_IR_NEC;
 		ir->full_code = 1;
-	} else if (rc_type != RC_TYPE_UNKNOWN)
+		*rc_type = RC_BIT_NEC;
+	} else if (*rc_type != RC_BIT_UNKNOWN)
 		rc = -EINVAL;
 
 	em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk,
@@ -524,6 +526,7 @@ static int em28xx_ir_init(struct em28xx *dev)
 	struct em28xx_IR *ir;
 	struct rc_dev *rc;
 	int err = -ENOMEM;
+	u64 rc_type;
 
 	if (dev->board.ir_codes == NULL) {
 		/* No remote control support */
@@ -546,14 +549,15 @@ static int em28xx_ir_init(struct em28xx *dev)
 	 * em2874 supports more protocols. For now, let's just announce
 	 * the two protocols that were already tested
 	 */
-	rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
 	rc->priv = ir;
 	rc->change_protocol = em28xx_ir_change_protocol;
 	rc->open = em28xx_ir_start;
 	rc->close = em28xx_ir_stop;
 
 	/* By default, keep protocol field untouched */
-	err = em28xx_ir_change_protocol(rc, RC_TYPE_UNKNOWN);
+	rc_type = RC_BIT_UNKNOWN;
+	err = em28xx_ir_change_protocol(rc, &rc_type);
 	if (err)
 		goto err_out_free;
 
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index 8757523..86e90d8 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -128,6 +128,7 @@
 #define EM2874_BOARD_MAXMEDIA_UB425_TC            84
 #define EM2884_BOARD_PCTV_510E                    85
 #define EM2884_BOARD_PCTV_520E                    86
+#define EM2884_BOARD_TERRATEC_HTC_USB_XS	  87
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
index a2b9341..e0a431b 100644
--- a/drivers/media/usb/gspca/gspca.c
+++ b/drivers/media/usb/gspca/gspca.c
@@ -1586,8 +1586,7 @@ static int vidioc_querybuf(struct file *file, void *priv,
 	struct gspca_dev *gspca_dev = video_drvdata(file);
 	struct gspca_frame *frame;
 
-	if (v4l2_buf->index < 0
-	    || v4l2_buf->index >= gspca_dev->nframes)
+	if (v4l2_buf->index >= gspca_dev->nframes)
 		return -EINVAL;
 
 	frame = &gspca_dev->frame[v4l2_buf->index];
diff --git a/drivers/media/usb/gspca/gspca.h b/drivers/media/usb/gspca/gspca.h
index e3eab82..352317d 100644
--- a/drivers/media/usb/gspca/gspca.h
+++ b/drivers/media/usb/gspca/gspca.h
@@ -32,7 +32,7 @@ do {								\
 #define D_USBO 0x00
 #define D_V4L2 0x0100
 #else
-#define PDEBUG(level, fmt, ...)
+#define PDEBUG(level, fmt, ...) do {} while(0)
 #endif
 
 #define GSPCA_MAX_FRAMES 16	/* maximum number of video frame buffers */
diff --git a/drivers/media/usb/gspca/jeilinj.c b/drivers/media/usb/gspca/jeilinj.c
index b897aa8..1ba29fe 100644
--- a/drivers/media/usb/gspca/jeilinj.c
+++ b/drivers/media/usb/gspca/jeilinj.c
@@ -114,7 +114,7 @@ static void jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command)
 }
 
 /* Responses are one byte only */
-static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char response)
+static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char *response)
 {
 	int retval;
 
@@ -123,7 +123,7 @@ static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char response)
 	retval = usb_bulk_msg(gspca_dev->dev,
 	usb_rcvbulkpipe(gspca_dev->dev, 0x84),
 				gspca_dev->usb_buf, 1, NULL, 500);
-	response = gspca_dev->usb_buf[0];
+	*response = gspca_dev->usb_buf[0];
 	if (retval < 0) {
 		pr_err("read command [%02x] error %d\n",
 		       gspca_dev->usb_buf[0], retval);
@@ -260,7 +260,7 @@ static int jlj_start(struct gspca_dev *gspca_dev)
 		if (start_commands[i].delay)
 			msleep(start_commands[i].delay);
 		if (start_commands[i].ack_wanted)
-			jlj_read1(gspca_dev, response);
+			jlj_read1(gspca_dev, &response);
 	}
 	setcamquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
 	msleep(2);
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c
index cc8ec3f..c8e1572 100644
--- a/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c
+++ b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c
@@ -74,6 +74,12 @@ static
 			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2548")
 		}
 	}, {
+		.ident = "Fujitsu-Siemens Amilo Pi 2530",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 2530")
+		}
+	}, {
 		.ident = "MSI GX700",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
diff --git a/drivers/media/usb/gspca/pac7302.c b/drivers/media/usb/gspca/pac7302.c
index 2d5c6d83..4f5869a 100644
--- a/drivers/media/usb/gspca/pac7302.c
+++ b/drivers/media/usb/gspca/pac7302.c
@@ -29,14 +29,13 @@
  * Register page 0:
  *
  * Address	Description
- * 0x02		Red balance control
- * 0x03		Green balance control
- * 0x04 	Blue balance control
- *		     Valus are inverted (0=max, 255=min).
+ * 0x01		Red balance control
+ * 0x02		Green balance control
+ * 0x03		Blue balance control
  *		     The Windows driver uses a quadratic approach to map
  *		     the settable values (0-200) on register values:
- *		     min=0x80, default=0x40, max=0x20
- * 0x0f-0x20	Colors, saturation and exposure control
+ *		     min=0x20, default=0x40, max=0x80
+ * 0x0f-0x20	Color and saturation control
  * 0xa2-0xab	Brightness, contrast and gamma control
  * 0xb6		Sharpness control (bits 0-4)
  *
@@ -78,12 +77,12 @@
  *
  * Page | Register   | Function
  * -----+------------+---------------------------------------------------
+ *  0   | 0x01       | setredbalance()
+ *  0   | 0x03       | setbluebalance()
  *  0   | 0x0f..0x20 | setcolors()
  *  0   | 0xa2..0xab | setbrightcont()
  *  0   | 0xb6       | setsharpness()
- *  0   | 0xc5       | setredbalance()
  *  0   | 0xc6       | setwhitebalance()
- *  0   | 0xc7       | setbluebalance()
  *  0   | 0xdc       | setbrightcont(), setcolors()
  *  3   | 0x02       | setexposure()
  *  3   | 0x10, 0x12 | setgain()
@@ -99,10 +98,13 @@
 /* Include pac common sof detection functions */
 #include "pac_common.h"
 
-#define PAC7302_GAIN_DEFAULT      15
-#define PAC7302_GAIN_KNEE         42
-#define PAC7302_EXPOSURE_DEFAULT  66 /* 33 ms / 30 fps */
-#define PAC7302_EXPOSURE_KNEE    133 /* 66 ms / 15 fps */
+#define PAC7302_RGB_BALANCE_MIN		  0
+#define PAC7302_RGB_BALANCE_MAX		200
+#define PAC7302_RGB_BALANCE_DEFAULT	100
+#define PAC7302_GAIN_DEFAULT		 15
+#define PAC7302_GAIN_KNEE		 42
+#define PAC7302_EXPOSURE_DEFAULT	 66 /* 33 ms / 30 fps */
+#define PAC7302_EXPOSURE_KNEE		133 /* 66 ms / 15 fps */
 
 MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
 		"Thomas Kaiser thomas@kaiser-linux.li");
@@ -439,12 +441,31 @@ static void setwhitebalance(struct gspca_dev *gspca_dev)
 	reg_w(gspca_dev, 0xdc, 0x01);
 }
 
+static u8 rgbbalance_ctrl_to_reg_value(s32 rgb_ctrl_val)
+{
+	const unsigned int k = 1000;	/* precision factor */
+	unsigned int norm;
+
+	/* Normed value [0...k] */
+	norm = k * (rgb_ctrl_val - PAC7302_RGB_BALANCE_MIN)
+		    / (PAC7302_RGB_BALANCE_MAX - PAC7302_RGB_BALANCE_MIN);
+	/* Qudratic apporach improves control at small (register) values: */
+	return 64 * norm * norm / (k*k)  +  32 * norm / k  +  32;
+	/* Y = 64*X*X + 32*X + 32
+	 * => register values 0x20-0x80; Windows driver uses these limits */
+
+	/* NOTE: for full value range (0x00-0xff) use
+	 *         Y = 254*X*X + X
+	 *         => 254 * norm * norm / (k*k)  +  1 * norm / k	*/
+}
+
 static void setredbalance(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	reg_w(gspca_dev, 0xff, 0x00);		/* page 0 */
-	reg_w(gspca_dev, 0xc5, sd->red_balance->val);
+	reg_w(gspca_dev, 0xff, 0x00);			/* page 0 */
+	reg_w(gspca_dev, 0x01,
+	      rgbbalance_ctrl_to_reg_value(sd->red_balance->val));
 
 	reg_w(gspca_dev, 0xdc, 0x01);
 }
@@ -454,7 +475,8 @@ static void setbluebalance(struct gspca_dev *gspca_dev)
 	struct sd *sd = (struct sd *) gspca_dev;
 
 	reg_w(gspca_dev, 0xff, 0x00);			/* page 0 */
-	reg_w(gspca_dev, 0xc7, sd->blue_balance->val);
+	reg_w(gspca_dev, 0x03,
+	      rgbbalance_ctrl_to_reg_value(sd->blue_balance->val));
 
 	reg_w(gspca_dev, 0xdc, 0x01);
 }
@@ -643,9 +665,15 @@ static int sd_init_controls(struct gspca_dev *gspca_dev)
 					V4L2_CID_WHITE_BALANCE_TEMPERATURE,
 					0, 255, 1, 55);
 	sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-					V4L2_CID_RED_BALANCE, 0, 3, 1, 1);
+					V4L2_CID_RED_BALANCE,
+					PAC7302_RGB_BALANCE_MIN,
+					PAC7302_RGB_BALANCE_MAX,
+					1, PAC7302_RGB_BALANCE_DEFAULT);
 	sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-					V4L2_CID_BLUE_BALANCE, 0, 3, 1, 1);
+					V4L2_CID_BLUE_BALANCE,
+					PAC7302_RGB_BALANCE_MIN,
+					PAC7302_RGB_BALANCE_MAX,
+					1, PAC7302_RGB_BALANCE_DEFAULT);
 
 	gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 					V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c
index fd1f8d2..70511d5 100644
--- a/drivers/media/usb/gspca/sonixb.c
+++ b/drivers/media/usb/gspca/sonixb.c
@@ -1449,6 +1449,7 @@ static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
 	{USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
 #endif
+	{USB_DEVICE(0x0c45, 0x6027), SB(OV7630, 101)}, /* Genius Eye 310 */
 	{USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
 	{USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
 	{USB_DEVICE(0x0c45, 0x602a), SB(HV7131D, 102)},
diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c
index 304f43e..84dc26f 100644
--- a/drivers/media/usb/hdpvr/hdpvr-core.c
+++ b/drivers/media/usb/hdpvr/hdpvr-core.c
@@ -401,12 +401,14 @@ static int hdpvr_probe(struct usb_interface *interface,
 	client = hdpvr_register_ir_rx_i2c(dev);
 	if (!client) {
 		v4l2_err(&dev->v4l2_dev, "i2c IR RX device register failed\n");
+		retval = -ENODEV;
 		goto reg_fail;
 	}
 
 	client = hdpvr_register_ir_tx_i2c(dev);
 	if (!client) {
 		v4l2_err(&dev->v4l2_dev, "i2c IR TX device register failed\n");
+		retval = -ENODEV;
 		goto reg_fail;
 	}
 #endif
diff --git a/drivers/media/usb/hdpvr/hdpvr-i2c.c b/drivers/media/usb/hdpvr/hdpvr-i2c.c
index 82e819f..031cf02 100644
--- a/drivers/media/usb/hdpvr/hdpvr-i2c.c
+++ b/drivers/media/usb/hdpvr/hdpvr-i2c.c
@@ -55,7 +55,7 @@ struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev)
 	/* Our default information for ir-kbd-i2c.c to use */
 	init_data->ir_codes = RC_MAP_HAUPPAUGE;
 	init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-	init_data->type = RC_TYPE_RC5;
+	init_data->type = RC_BIT_RC5;
 	init_data->name = "HD-PVR";
 	init_data->polling_interval = 405; /* ms, duplicated from Windows */
 	hdpvr_ir_rx_i2c_board_info.platform_data = init_data;
diff --git a/drivers/media/usb/pvrusb2/Kconfig b/drivers/media/usb/pvrusb2/Kconfig
index 32b11c1..60a2604 100644
--- a/drivers/media/usb/pvrusb2/Kconfig
+++ b/drivers/media/usb/pvrusb2/Kconfig
@@ -17,9 +17,9 @@ config VIDEO_PVRUSB2
 	  module will be called pvrusb2
 
 config VIDEO_PVRUSB2_SYSFS
-	bool "pvrusb2 sysfs support (EXPERIMENTAL)"
+	bool "pvrusb2 sysfs support"
 	default y
-	depends on VIDEO_PVRUSB2 && SYSFS && EXPERIMENTAL
+	depends on VIDEO_PVRUSB2 && SYSFS
 	---help---
 	  This option enables the operation of a sysfs based
 	  interface for query and control of the pvrusb2 driver.
@@ -33,9 +33,9 @@ config VIDEO_PVRUSB2_SYSFS
 	  Note: This feature is experimental and subject to change.
 
 config VIDEO_PVRUSB2_DVB
-	bool "pvrusb2 ATSC/DVB support (EXPERIMENTAL)"
+	bool "pvrusb2 ATSC/DVB support"
 	default y
-	depends on VIDEO_PVRUSB2 && DVB_CORE && EXPERIMENTAL
+	depends on VIDEO_PVRUSB2 && DVB_CORE
 	select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_S5H1409 if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
index fb828ba..299751a 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
@@ -3563,9 +3563,9 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw,
 				     enum pvr2_v4l_type index,int v)
 {
 	switch (index) {
-	case pvr2_v4l_type_video: hdw->v4l_minor_number_video = v;
-	case pvr2_v4l_type_vbi: hdw->v4l_minor_number_vbi = v;
-	case pvr2_v4l_type_radio: hdw->v4l_minor_number_radio = v;
+	case pvr2_v4l_type_video: hdw->v4l_minor_number_video = v;break;
+	case pvr2_v4l_type_vbi: hdw->v4l_minor_number_vbi = v;break;
+	case pvr2_v4l_type_radio: hdw->v4l_minor_number_radio = v;break;
 	default: break;
 	}
 }
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c
index 885ce11..9ab596c 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c
@@ -581,7 +581,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
 	case PVR2_IR_SCHEME_29XXX: /* Original 29xxx device */
 		init_data->ir_codes              = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
-		init_data->type                  = RC_TYPE_RC5;
+		init_data->type                  = RC_BIT_RC5;
 		init_data->name                  = hdw->hdw_desc->description;
 		init_data->polling_interval      = 100; /* ms From ir-kbd-i2c */
 		/* IR Receiver */
@@ -596,7 +596,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
 	case PVR2_IR_SCHEME_24XXX_MCE: /* 24xxx MCE device */
 		init_data->ir_codes              = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-		init_data->type                  = RC_TYPE_RC5;
+		init_data->type                  = RC_BIT_RC5;
 		init_data->name                  = hdw->hdw_desc->description;
 		/* IR Receiver */
 		info.addr          = 0x71;
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
index db249ca..6930676 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
@@ -196,7 +196,7 @@ static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
 	return ret;
 }
 
-int pvr2_s_std(struct file *file, void *priv, v4l2_std_id *std)
+static int pvr2_s_std(struct file *file, void *priv, v4l2_std_id *std)
 {
 	struct pvr2_v4l2_fh *fh = file->private_data;
 	struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
@@ -365,7 +365,7 @@ static int pvr2_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
 			vt->audmode);
 }
 
-int pvr2_s_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
+static int pvr2_s_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
 {
 	struct pvr2_v4l2_fh *fh = file->private_data;
 	struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
diff --git a/drivers/media/usb/pwc/pwc-ctrl.c b/drivers/media/usb/pwc/pwc-ctrl.c
index 1f506fd..3a16185 100644
--- a/drivers/media/usb/pwc/pwc-ctrl.c
+++ b/drivers/media/usb/pwc/pwc-ctrl.c
@@ -179,6 +179,8 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt,
 		return -EINVAL;
 	if (frames < 4)
 		frames = 4;
+	else if (size > PSZ_QCIF && frames > 15)
+		frames = 15;
 	else if (frames > 25)
 		frames = 25;
 	frames = frames2frames[frames];
diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c
index 42e36ba..5210239 100644
--- a/drivers/media/usb/pwc/pwc-if.c
+++ b/drivers/media/usb/pwc/pwc-if.c
@@ -155,7 +155,7 @@ static struct video_device pwc_template = {
 /***************************************************************************/
 /* Private functions */
 
-struct pwc_frame_buf *pwc_get_next_fill_buf(struct pwc_device *pdev)
+static struct pwc_frame_buf *pwc_get_next_fill_buf(struct pwc_device *pdev)
 {
 	unsigned long flags = 0;
 	struct pwc_frame_buf *buf = NULL;
@@ -1000,7 +1000,11 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
 	pdev->vb_queue.buf_struct_size = sizeof(struct pwc_frame_buf);
 	pdev->vb_queue.ops = &pwc_vb_queue_ops;
 	pdev->vb_queue.mem_ops = &vb2_vmalloc_memops;
-	vb2_queue_init(&pdev->vb_queue);
+	rc = vb2_queue_init(&pdev->vb_queue);
+	if (rc < 0) {
+		PWC_ERROR("Oops, could not initialize vb2 queue.\n");
+		goto err_free_mem;
+	}
 
 	/* Init video_device structure */
 	memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index 2191f6d..8ebec0d 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -1651,7 +1651,7 @@ static int vidioc_enum_frameintervals(struct file *file, void *priv,
 	int is_ntsc = 0;
 #define NUM_FRAME_ENUMS 4
 	int frm_dec[NUM_FRAME_ENUMS] = {1, 2, 3, 5};
-	if (fe->index < 0 || fe->index >= NUM_FRAME_ENUMS)
+	if (fe->index >= NUM_FRAME_ENUMS)
 		return -EINVAL;
 	switch (fe->width) {
 	case 640:
diff --git a/drivers/media/usb/siano/Kconfig b/drivers/media/usb/siano/Kconfig
index 3c76e62..5afbd9a 100644
--- a/drivers/media/usb/siano/Kconfig
+++ b/drivers/media/usb/siano/Kconfig
@@ -4,7 +4,8 @@
 
 config SMS_USB_DRV
 	tristate "Siano SMS1xxx based MDTV receiver"
-	depends on DVB_CORE && RC_CORE && HAS_DMA
+	depends on DVB_CORE && HAS_DMA
+	select MEDIA_COMMON_OPTIONS
 	---help---
 	  Choose if you would like to have Siano's support for USB interface
 
diff --git a/drivers/media/usb/sn9c102/sn9c102_core.c b/drivers/media/usb/sn9c102/sn9c102_core.c
index 5bfc8e2..7360586 100644
--- a/drivers/media/usb/sn9c102/sn9c102_core.c
+++ b/drivers/media/usb/sn9c102/sn9c102_core.c
@@ -2481,11 +2481,13 @@ sn9c102_vidioc_enum_framesizes(struct sn9c102_device* cam, void __user * arg)
 		if (frmsize.pixel_format != V4L2_PIX_FMT_SN9C10X &&
 		    frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
 			return -EINVAL;
+		break;
 	case BRIDGE_SN9C105:
 	case BRIDGE_SN9C120:
 		if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG &&
 		    frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
 			return -EINVAL;
+		break;
 	}
 
 	frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE;
diff --git a/drivers/media/usb/stk1160/stk1160-i2c.c b/drivers/media/usb/stk1160/stk1160-i2c.c
index 176ac93..850cf28 100644
--- a/drivers/media/usb/stk1160/stk1160-i2c.c
+++ b/drivers/media/usb/stk1160/stk1160-i2c.c
@@ -116,7 +116,7 @@ static int stk1160_i2c_read_reg(struct stk1160 *dev, u8 addr,
 	if (rc < 0)
 		return rc;
 
-	stk1160_read_reg(dev, STK1160_SBUSR_RD, value);
+	rc = stk1160_read_reg(dev, STK1160_SBUSR_RD, value);
 	if (rc < 0)
 		return rc;
 
diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c
index 8bdfb02..fa3671d 100644
--- a/drivers/media/usb/stk1160/stk1160-video.c
+++ b/drivers/media/usb/stk1160/stk1160-video.c
@@ -475,7 +475,11 @@ int stk1160_alloc_isoc(struct stk1160 *dev)
 		if (!dev->isoc_ctl.transfer_buffer[i]) {
 			stk1160_err("cannot alloc %d bytes for tx[%d] buffer\n",
 				sb_size, i);
-			goto free_i_bufs;
+
+			/* Not enough transfer buffers, so just give up */
+			if (i < STK1160_MIN_BUFS)
+				goto free_i_bufs;
+			goto nomore_tx_bufs;
 		}
 		memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
 
@@ -506,13 +510,28 @@ int stk1160_alloc_isoc(struct stk1160 *dev)
 		}
 	}
 
-	stk1160_dbg("urbs allocated\n");
+	stk1160_dbg("%d urbs allocated\n", num_bufs);
 
 	/* At last we can say we have some buffers */
 	dev->isoc_ctl.num_bufs = num_bufs;
 
 	return 0;
 
+nomore_tx_bufs:
+	/*
+	 * Failed to allocate desired buffer count. However, we may have
+	 * enough to work fine, so we just free the extra urb,
+	 * store the allocated count and keep going, fingers crossed!
+	 */
+	usb_free_urb(dev->isoc_ctl.urb[i]);
+	dev->isoc_ctl.urb[i] = NULL;
+
+	stk1160_warn("%d urbs allocated. Trying to continue...\n", i - 1);
+
+	dev->isoc_ctl.num_bufs = i - 1;
+
+	return 0;
+
 free_i_bufs:
 	/* Save the allocated buffers so far, so we can properly free them */
 	dev->isoc_ctl.num_bufs = i+1;
diff --git a/drivers/media/usb/stk1160/stk1160.h b/drivers/media/usb/stk1160/stk1160.h
index 68c8707..05b05b1 100644
--- a/drivers/media/usb/stk1160/stk1160.h
+++ b/drivers/media/usb/stk1160/stk1160.h
@@ -30,11 +30,12 @@
 #define STK1160_VERSION		"0.9.5"
 #define STK1160_VERSION_NUM	0x000905
 
-/* TODO: Decide on number of packets for each buffer */
+/* Decide on number of packets for each buffer */
 #define STK1160_NUM_PACKETS 64
 
 /* Number of buffers for isoc transfers */
-#define STK1160_NUM_BUFS 16 /* TODO */
+#define STK1160_NUM_BUFS 16
+#define STK1160_MIN_BUFS 1
 
 /* TODO: This endpoint address should be retrieved */
 #define STK1160_EP_VIDEO 0x82
diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c
index 86a0fc5..5d3c032 100644
--- a/drivers/media/usb/stkwebcam/stk-webcam.c
+++ b/drivers/media/usb/stkwebcam/stk-webcam.c
@@ -54,10 +54,6 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jaime Velasco Juan <jsagarribay@gmail.com> and Nicolas VIVIEN");
 MODULE_DESCRIPTION("Syntek DC1125 webcam driver");
 
-
-/* bool for webcam LED management */
-int first_init = 1;
-
 /* Some cameras have audio interfaces, we aren't interested in those */
 static struct usb_device_id stkwebcam_table[] = {
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x174f, 0xa311, 0xff, 0xff, 0xff) },
@@ -554,6 +550,7 @@ static void stk_free_buffers(struct stk_camera *dev)
 
 static int v4l_stk_open(struct file *fp)
 {
+	static int first_init = 1; /* webcam LED management */
 	struct stk_camera *dev;
 	struct video_device *vdev;
 
diff --git a/drivers/media/usb/tlg2300/pd-dvb.c b/drivers/media/usb/tlg2300/pd-dvb.c
index 30fcb11..ca4994a 100644
--- a/drivers/media/usb/tlg2300/pd-dvb.c
+++ b/drivers/media/usb/tlg2300/pd-dvb.c
@@ -1,6 +1,7 @@
 #include "pd-common.h"
 #include <linux/kernel.h>
 #include <linux/usb.h>
+#include <linux/time.h>
 #include <linux/dvb/dmx.h>
 #include <linux/delay.h>
 #include <linux/gfp.h>
diff --git a/drivers/media/usb/tlg2300/pd-video.c b/drivers/media/usb/tlg2300/pd-video.c
index 1f448ac..3082bfa 100644
--- a/drivers/media/usb/tlg2300/pd-video.c
+++ b/drivers/media/usb/tlg2300/pd-video.c
@@ -888,7 +888,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *in)
 {
 	struct front_face *front = fh;
 
-	if (in->index < 0 || in->index >= POSEIDON_INPUTS)
+	if (in->index >= POSEIDON_INPUTS)
 		return -EINVAL;
 	strcpy(in->name, pd_inputs[in->index].name);
 	in->type  = V4L2_INPUT_TYPE_TUNER;
@@ -923,7 +923,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
 	struct poseidon *pd = front->pd;
 	s32 ret, cmd_status;
 
-	if (i < 0 || i >= POSEIDON_INPUTS)
+	if (i >= POSEIDON_INPUTS)
 		return -EINVAL;
 	ret = send_set_req(pd, SGNL_SRC_SEL,
 			pd_inputs[i].tlg_src, &cmd_status);
diff --git a/drivers/media/usb/tm6000/tm6000-input.c b/drivers/media/usb/tm6000/tm6000-input.c
index dffbd4b..8a6bbf1 100644
--- a/drivers/media/usb/tm6000/tm6000-input.c
+++ b/drivers/media/usb/tm6000/tm6000-input.c
@@ -109,12 +109,12 @@ static int tm6000_ir_config(struct tm6000_IR *ir)
 	 */
 
 	switch (ir->rc_type) {
-	case RC_TYPE_NEC:
+	case RC_BIT_NEC:
 		leader = 900;	/* ms */
 		pulse  = 700;	/* ms - the actual value would be 562 */
 		break;
 	default:
-	case RC_TYPE_RC5:
+	case RC_BIT_RC5:
 		leader = 900;	/* ms - from the NEC decoding */
 		pulse  = 1780;	/* ms - The actual value would be 1776 */
 		break;
@@ -122,12 +122,12 @@ static int tm6000_ir_config(struct tm6000_IR *ir)
 
 	pulse = ir_clock_mhz * pulse;
 	leader = ir_clock_mhz * leader;
-	if (ir->rc_type == RC_TYPE_NEC)
+	if (ir->rc_type == RC_BIT_NEC)
 		leader = leader | 0x8000;
 
 	dprintk(2, "%s: %s, %d MHz, leader = 0x%04x, pulse = 0x%06x \n",
 		__func__,
-		(ir->rc_type == RC_TYPE_NEC) ? "NEC" : "RC-5",
+		(ir->rc_type == RC_BIT_NEC) ? "NEC" : "RC-5",
 		ir_clock_mhz, leader, pulse);
 
 	/* Remote WAKEUP = enable, normal mode, from IR decoder output */
@@ -297,7 +297,7 @@ static void tm6000_ir_stop(struct rc_dev *rc)
 	cancel_delayed_work_sync(&ir->work);
 }
 
-static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
+static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 *rc_type)
 {
 	struct tm6000_IR *ir = rc->priv;
 
@@ -306,10 +306,10 @@ static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
 
 	dprintk(2, "%s\n",__func__);
 
-	if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC))
+	if ((rc->rc_map.scan) && (*rc_type == RC_BIT_NEC))
 		ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff);
 
-	ir->rc_type = rc_type;
+	ir->rc_type = *rc_type;
 
 	tm6000_ir_config(ir);
 	/* TODO */
@@ -398,6 +398,7 @@ int tm6000_ir_init(struct tm6000_core *dev)
 	struct tm6000_IR *ir;
 	struct rc_dev *rc;
 	int err = -ENOMEM;
+	u64 rc_type;
 
 	if (!enable_ir)
 		return -ENODEV;
@@ -421,7 +422,7 @@ int tm6000_ir_init(struct tm6000_core *dev)
 	ir->rc = rc;
 
 	/* input setup */
-	rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
 	/* Neded, in order to support NEC remotes with 24 or 32 bits */
 	rc->scanmask = 0xffff;
 	rc->priv = ir;
@@ -444,7 +445,8 @@ int tm6000_ir_init(struct tm6000_core *dev)
 	usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
 	strlcat(ir->phys, "/input0", sizeof(ir->phys));
 
-	tm6000_ir_change_protocol(rc, RC_TYPE_UNKNOWN);
+	rc_type = RC_BIT_UNKNOWN;
+	tm6000_ir_change_protocol(rc, &rc_type);
 
 	rc->input_name = ir->name;
 	rc->input_phys = ir->phys;
diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c
index 4342cd4..f656fd7 100644
--- a/drivers/media/usb/tm6000/tm6000-video.c
+++ b/drivers/media/usb/tm6000/tm6000-video.c
@@ -1802,6 +1802,7 @@ int tm6000_v4l2_register(struct tm6000_core *dev)
 		if (!dev->radio_dev) {
 			printk(KERN_INFO "%s: can't register radio device\n",
 			       dev->name);
+			ret = -ENXIO;
 			return ret; /* FIXME release resource */
 		}
 
diff --git a/drivers/media/usb/usbvision/usbvision.h b/drivers/media/usb/usbvision/usbvision.h
index 43cf61f..8a25876 100644
--- a/drivers/media/usb/usbvision/usbvision.h
+++ b/drivers/media/usb/usbvision/usbvision.h
@@ -167,7 +167,7 @@ enum {
 
 /* This macro restricts an int variable to an inclusive range */
 #define RESTRICT_TO_RANGE(v, mi, ma) \
-	{ if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
+	{ if (((int)v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
 
 /*
  * We use macros to do YUV -> RGB conversion because this is
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index 18a91fa..778addc 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -128,7 +128,7 @@ int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
 	int ret;
 
 	queue->queue.type = type;
-	queue->queue.io_modes = VB2_MMAP | VB2_USERPTR;
+	queue->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
 	queue->queue.drv_priv = queue;
 	queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
 	queue->queue.ops = &uvc_queue_qops;
diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c
index 9afab35..39edd44 100644
--- a/drivers/media/usb/zr364xx/zr364xx.c
+++ b/drivers/media/usb/zr364xx/zr364xx.c
@@ -1007,8 +1007,7 @@ static void read_pipe_completion(struct urb *purb)
 		return;
 	}
 
-	if (purb->actual_length < 0 ||
-	    purb->actual_length > pipe_info->transfer_size) {
+	if (purb->actual_length > pipe_info->transfer_size) {
 		dev_err(&cam->udev->dev, "wrong number of bytes\n");
 		return;
 	}
diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
index 0c54e19..65875c3 100644
--- a/drivers/media/v4l2-core/Kconfig
+++ b/drivers/media/v4l2-core/Kconfig
@@ -59,6 +59,7 @@ config VIDEOBUF_DVB
 
 # Used by drivers that need Videobuf2 modules
 config VIDEOBUF2_CORE
+	select DMA_SHARED_BUFFER
 	tristate
 
 config VIDEOBUF2_MEMOPS
@@ -68,11 +69,13 @@ config VIDEOBUF2_DMA_CONTIG
 	tristate
 	select VIDEOBUF2_CORE
 	select VIDEOBUF2_MEMOPS
+	select DMA_SHARED_BUFFER
 
 config VIDEOBUF2_VMALLOC
 	tristate
 	select VIDEOBUF2_CORE
 	select VIDEOBUF2_MEMOPS
+	select DMA_SHARED_BUFFER
 
 config VIDEOBUF2_DMA_SG
 	tristate
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index f995dd3..380ddd8 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -837,7 +837,7 @@ bool v4l2_detect_gtf(unsigned frame_height,
 		struct v4l2_dv_timings *fmt)
 {
 	int pix_clk;
-	int  v_fp, v_bp, h_fp, h_bp, hsync;
+	int  v_fp, v_bp, h_fp, hsync;
 	int frame_width, image_height, image_width;
 	bool default_gtf;
 	int h_blank;
@@ -885,7 +885,6 @@ bool v4l2_detect_gtf(unsigned frame_height,
 	hsync = hsync - hsync % GTF_CELL_GRAN;
 
 	h_fp = h_blank / 2 - hsync;
-	h_bp = h_blank / 2;
 
 	fmt->bt.polarities = polarities;
 	fmt->bt.width = image_width;
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 83ffb64..7157af3 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -297,6 +297,7 @@ struct v4l2_plane32 {
 	union {
 		__u32		mem_offset;
 		compat_long_t	userptr;
+		__s32		fd;
 	} m;
 	__u32			data_offset;
 	__u32			reserved[11];
@@ -318,6 +319,7 @@ struct v4l2_buffer32 {
 		__u32           offset;
 		compat_long_t   userptr;
 		compat_caddr_t  planes;
+		__s32		fd;
 	} m;
 	__u32			length;
 	__u32			reserved2;
@@ -341,6 +343,9 @@ static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
 		up_pln = compat_ptr(p);
 		if (put_user((unsigned long)up_pln, &up->m.userptr))
 			return -EFAULT;
+	} else if (memory == V4L2_MEMORY_DMABUF) {
+		if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(int)))
+			return -EFAULT;
 	} else {
 		if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
 					sizeof(__u32)))
@@ -364,6 +369,11 @@ static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
 		if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
 					sizeof(__u32)))
 			return -EFAULT;
+	/* For DMABUF, driver might've set up the fd, so copy it back. */
+	if (memory == V4L2_MEMORY_DMABUF)
+		if (copy_in_user(&up32->m.fd, &up->m.fd,
+					sizeof(int)))
+			return -EFAULT;
 
 	return 0;
 }
@@ -446,6 +456,10 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
 			if (get_user(kp->m.offset, &up->m.offset))
 				return -EFAULT;
 			break;
+		case V4L2_MEMORY_DMABUF:
+			if (get_user(kp->m.fd, &up->m.fd))
+				return -EFAULT;
+			break;
 		}
 	}
 
@@ -510,6 +524,10 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
 			if (put_user(kp->m.offset, &up->m.offset))
 				return -EFAULT;
 			break;
+		case V4L2_MEMORY_DMABUF:
+			if (put_user(kp->m.fd, &up->m.fd))
+				return -EFAULT;
+			break;
 		}
 	}
 
@@ -1000,6 +1018,7 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
 	case VIDIOC_S_FBUF32:
 	case VIDIOC_OVERLAY32:
 	case VIDIOC_QBUF32:
+	case VIDIOC_EXPBUF:
 	case VIDIOC_DQBUF32:
 	case VIDIOC_STREAMON32:
 	case VIDIOC_STREAMOFF32:
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index a2df842..98dcad9 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -571,6 +571,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
 	SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
 	SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
 	SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);
+	SET_VALID_IOCTL(ops, VIDIOC_EXPBUF, vidioc_expbuf);
 	SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf);
 	SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
 	SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
diff --git a/drivers/media/v4l2-core/v4l2-event.c b/drivers/media/v4l2-core/v4l2-event.c
index 18a040b..c720092 100644
--- a/drivers/media/v4l2-core/v4l2-event.c
+++ b/drivers/media/v4l2-core/v4l2-event.c
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2009--2010 Nokia Corporation.
  *
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/v4l2-core/v4l2-fh.c b/drivers/media/v4l2-core/v4l2-fh.c
index 9e3fc04..e57c002 100644
--- a/drivers/media/v4l2-core/v4l2-fh.c
+++ b/drivers/media/v4l2-core/v4l2-fh.c
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2009--2010 Nokia Corporation.
  *
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 8f388ff..aa6e7c7 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -155,6 +155,7 @@ static const char *v4l2_memory_names[] = {
 	[V4L2_MEMORY_MMAP]    = "mmap",
 	[V4L2_MEMORY_USERPTR] = "userptr",
 	[V4L2_MEMORY_OVERLAY] = "overlay",
+	[V4L2_MEMORY_DMABUF] = "dmabuf",
 };
 
 #define prt_names(a, arr) (((unsigned)(a)) < ARRAY_SIZE(arr) ? arr[a] : "unknown")
@@ -453,6 +454,15 @@ static void v4l_print_buffer(const void *arg, bool write_only)
 			tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
 }
 
+static void v4l_print_exportbuffer(const void *arg, bool write_only)
+{
+	const struct v4l2_exportbuffer *p = arg;
+
+	pr_cont("fd=%d, type=%s, index=%u, plane=%u, flags=0x%08x\n",
+		p->fd, prt_names(p->type, v4l2_type_names),
+		p->index, p->plane, p->flags);
+}
+
 static void v4l_print_create_buffers(const void *arg, bool write_only)
 {
 	const struct v4l2_create_buffers *p = arg;
@@ -1960,6 +1970,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
 	IOCTL_INFO_STD(VIDIOC_S_FBUF, vidioc_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO),
 	IOCTL_INFO_FNC(VIDIOC_OVERLAY, v4l_overlay, v4l_print_u32, INFO_FL_PRIO),
 	IOCTL_INFO_FNC(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, INFO_FL_QUEUE),
+	IOCTL_INFO_STD(VIDIOC_EXPBUF, vidioc_expbuf, v4l_print_exportbuffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_exportbuffer, flags)),
 	IOCTL_INFO_FNC(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, INFO_FL_QUEUE),
 	IOCTL_INFO_FNC(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
 	IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index 3ac8358..438ea45 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -369,6 +369,19 @@ int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf);
 
 /**
+ * v4l2_m2m_expbuf() - export a source or destination buffer, depending on
+ * the type
+ */
+int v4l2_m2m_expbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+		  struct v4l2_exportbuffer *eb)
+{
+	struct vb2_queue *vq;
+
+	vq = v4l2_m2m_get_vq(m2m_ctx, eb->type);
+	return vb2_expbuf(vq, eb);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_expbuf);
+/**
  * v4l2_m2m_streamon() - turn on streaming for a video queue
  */
 int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
@@ -510,12 +523,10 @@ struct v4l2_m2m_dev *v4l2_m2m_init(struct v4l2_m2m_ops *m2m_ops)
 {
 	struct v4l2_m2m_dev *m2m_dev;
 
-	if (!m2m_ops)
+	if (!m2m_ops || WARN_ON(!m2m_ops->device_run) ||
+			WARN_ON(!m2m_ops->job_abort))
 		return ERR_PTR(-EINVAL);
 
-	BUG_ON(!m2m_ops->device_run);
-	BUG_ON(!m2m_ops->job_abort);
-
 	m2m_dev = kzalloc(sizeof *m2m_dev, GFP_KERNEL);
 	if (!m2m_dev)
 		return ERR_PTR(-ENOMEM);
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index dced41c..996c248 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -412,20 +412,20 @@ static int
 v4l2_subdev_link_validate_get_format(struct media_pad *pad,
 				     struct v4l2_subdev_format *fmt)
 {
-	switch (media_entity_type(pad->entity)) {
-	case MEDIA_ENT_T_V4L2_SUBDEV:
+	if (media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) {
+		struct v4l2_subdev *sd =
+			media_entity_to_v4l2_subdev(pad->entity);
+
 		fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
 		fmt->pad = pad->index;
-		return v4l2_subdev_call(media_entity_to_v4l2_subdev(
-						pad->entity),
-					pad, get_fmt, NULL, fmt);
-	default:
-		WARN(1, "Driver bug! Wrong media entity type %d, entity %s\n",
-		     media_entity_type(pad->entity), pad->entity->name);
-		/* Fall through */
-	case MEDIA_ENT_T_DEVNODE_V4L:
-		return -EINVAL;
+		return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt);
 	}
+
+	WARN(pad->entity->type != MEDIA_ENT_T_DEVNODE_V4L,
+	     "Driver bug! Wrong media entity type 0x%08x, entity %s\n",
+	     pad->entity->type, pad->entity->name);
+
+	return -EINVAL;
 }
 
 int v4l2_subdev_link_validate(struct media_link *link)
diff --git a/drivers/media/v4l2-core/videobuf-core.c b/drivers/media/v4l2-core/videobuf-core.c
index bf7a326..5449e8a 100644
--- a/drivers/media/v4l2-core/videobuf-core.c
+++ b/drivers/media/v4l2-core/videobuf-core.c
@@ -335,6 +335,9 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b,
 	case V4L2_MEMORY_OVERLAY:
 		b->m.offset  = vb->boff;
 		break;
+	case V4L2_MEMORY_DMABUF:
+		/* DMABUF is not handled in videobuf framework */
+		break;
 	}
 
 	b->flags    = 0;
@@ -405,6 +408,7 @@ int __videobuf_mmap_setup(struct videobuf_queue *q,
 			break;
 		case V4L2_MEMORY_USERPTR:
 		case V4L2_MEMORY_OVERLAY:
+		case V4L2_MEMORY_DMABUF:
 			/* nothing */
 			break;
 		}
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 432df11..9f81be2 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -109,6 +109,36 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb)
 }
 
 /**
+ * __vb2_plane_dmabuf_put() - release memory associated with
+ * a DMABUF shared plane
+ */
+static void __vb2_plane_dmabuf_put(struct vb2_queue *q, struct vb2_plane *p)
+{
+	if (!p->mem_priv)
+		return;
+
+	if (p->dbuf_mapped)
+		call_memop(q, unmap_dmabuf, p->mem_priv);
+
+	call_memop(q, detach_dmabuf, p->mem_priv);
+	dma_buf_put(p->dbuf);
+	memset(p, 0, sizeof(*p));
+}
+
+/**
+ * __vb2_buf_dmabuf_put() - release memory associated with
+ * a DMABUF shared buffer
+ */
+static void __vb2_buf_dmabuf_put(struct vb2_buffer *vb)
+{
+	struct vb2_queue *q = vb->vb2_queue;
+	unsigned int plane;
+
+	for (plane = 0; plane < vb->num_planes; ++plane)
+		__vb2_plane_dmabuf_put(q, &vb->planes[plane]);
+}
+
+/**
  * __setup_offsets() - setup unique offsets ("cookies") for every plane in
  * every buffer on the queue
  */
@@ -230,6 +260,8 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
 		/* Free MMAP buffers or release USERPTR buffers */
 		if (q->memory == V4L2_MEMORY_MMAP)
 			__vb2_buf_mem_free(vb);
+		else if (q->memory == V4L2_MEMORY_DMABUF)
+			__vb2_buf_dmabuf_put(vb);
 		else
 			__vb2_buf_userptr_put(vb);
 	}
@@ -362,6 +394,8 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 			b->m.offset = vb->v4l2_planes[0].m.mem_offset;
 		else if (q->memory == V4L2_MEMORY_USERPTR)
 			b->m.userptr = vb->v4l2_planes[0].m.userptr;
+		else if (q->memory == V4L2_MEMORY_DMABUF)
+			b->m.fd = vb->v4l2_planes[0].m.fd;
 	}
 
 	/*
@@ -454,13 +488,28 @@ static int __verify_mmap_ops(struct vb2_queue *q)
 }
 
 /**
+ * __verify_dmabuf_ops() - verify that all memory operations required for
+ * DMABUF queue type have been provided
+ */
+static int __verify_dmabuf_ops(struct vb2_queue *q)
+{
+	if (!(q->io_modes & VB2_DMABUF) || !q->mem_ops->attach_dmabuf ||
+	    !q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
+	    !q->mem_ops->unmap_dmabuf)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
  * __verify_memory_type() - Check whether the memory type and buffer type
  * passed to a buffer operation are compatible with the queue.
  */
 static int __verify_memory_type(struct vb2_queue *q,
 		enum v4l2_memory memory, enum v4l2_buf_type type)
 {
-	if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR) {
+	if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
+	    memory != V4L2_MEMORY_DMABUF) {
 		dprintk(1, "reqbufs: unsupported memory type\n");
 		return -EINVAL;
 	}
@@ -484,6 +533,11 @@ static int __verify_memory_type(struct vb2_queue *q,
 		return -EINVAL;
 	}
 
+	if (memory == V4L2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
+		dprintk(1, "reqbufs: DMABUF for current setup unsupported\n");
+		return -EINVAL;
+	}
+
 	/*
 	 * Place the busy tests at the end: -EBUSY can be ignored when
 	 * create_bufs is called with count == 0, but count == 0 should still
@@ -790,6 +844,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
 {
 	struct vb2_queue *q = vb->vb2_queue;
 	unsigned long flags;
+	unsigned int plane;
 
 	if (vb->state != VB2_BUF_STATE_ACTIVE)
 		return;
@@ -800,6 +855,10 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
 	dprintk(4, "Done processing on buffer %d, state: %d\n",
 			vb->v4l2_buf.index, vb->state);
 
+	/* sync buffers */
+	for (plane = 0; plane < vb->num_planes; ++plane)
+		call_memop(q, finish, vb->planes[plane].mem_priv);
+
 	/* Add the buffer to the done buffers list */
 	spin_lock_irqsave(&q->done_lock, flags);
 	vb->state = state;
@@ -845,6 +904,16 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
 					b->m.planes[plane].length;
 			}
 		}
+		if (b->memory == V4L2_MEMORY_DMABUF) {
+			for (plane = 0; plane < vb->num_planes; ++plane) {
+				v4l2_planes[plane].m.fd =
+					b->m.planes[plane].m.fd;
+				v4l2_planes[plane].length =
+					b->m.planes[plane].length;
+				v4l2_planes[plane].data_offset =
+					b->m.planes[plane].data_offset;
+			}
+		}
 	} else {
 		/*
 		 * Single-planar buffers do not use planes array,
@@ -859,6 +928,13 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
 			v4l2_planes[0].m.userptr = b->m.userptr;
 			v4l2_planes[0].length = b->length;
 		}
+
+		if (b->memory == V4L2_MEMORY_DMABUF) {
+			v4l2_planes[0].m.fd = b->m.fd;
+			v4l2_planes[0].length = b->length;
+			v4l2_planes[0].data_offset = 0;
+		}
+
 	}
 
 	vb->v4l2_buf.field = b->field;
@@ -959,14 +1035,121 @@ static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 }
 
 /**
+ * __qbuf_dmabuf() - handle qbuf of a DMABUF buffer
+ */
+static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+{
+	struct v4l2_plane planes[VIDEO_MAX_PLANES];
+	struct vb2_queue *q = vb->vb2_queue;
+	void *mem_priv;
+	unsigned int plane;
+	int ret;
+	int write = !V4L2_TYPE_IS_OUTPUT(q->type);
+
+	/* Verify and copy relevant information provided by the userspace */
+	__fill_vb2_buffer(vb, b, planes);
+
+	for (plane = 0; plane < vb->num_planes; ++plane) {
+		struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
+
+		if (IS_ERR_OR_NULL(dbuf)) {
+			dprintk(1, "qbuf: invalid dmabuf fd for plane %d\n",
+				plane);
+			ret = -EINVAL;
+			goto err;
+		}
+
+		/* use DMABUF size if length is not provided */
+		if (planes[plane].length == 0)
+			planes[plane].length = dbuf->size;
+
+		if (planes[plane].length < planes[plane].data_offset +
+		    q->plane_sizes[plane]) {
+			ret = -EINVAL;
+			goto err;
+		}
+
+		/* Skip the plane if already verified */
+		if (dbuf == vb->planes[plane].dbuf &&
+		    vb->v4l2_planes[plane].length == planes[plane].length) {
+			dma_buf_put(dbuf);
+			continue;
+		}
+
+		dprintk(1, "qbuf: buffer for plane %d changed\n", plane);
+
+		/* Release previously acquired memory if present */
+		__vb2_plane_dmabuf_put(q, &vb->planes[plane]);
+		memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane));
+
+		/* Acquire each plane's memory */
+		mem_priv = call_memop(q, attach_dmabuf, q->alloc_ctx[plane],
+			dbuf, planes[plane].length, write);
+		if (IS_ERR(mem_priv)) {
+			dprintk(1, "qbuf: failed to attach dmabuf\n");
+			ret = PTR_ERR(mem_priv);
+			dma_buf_put(dbuf);
+			goto err;
+		}
+
+		vb->planes[plane].dbuf = dbuf;
+		vb->planes[plane].mem_priv = mem_priv;
+	}
+
+	/* TODO: This pins the buffer(s) with  dma_buf_map_attachment()).. but
+	 * really we want to do this just before the DMA, not while queueing
+	 * the buffer(s)..
+	 */
+	for (plane = 0; plane < vb->num_planes; ++plane) {
+		ret = call_memop(q, map_dmabuf, vb->planes[plane].mem_priv);
+		if (ret) {
+			dprintk(1, "qbuf: failed to map dmabuf for plane %d\n",
+				plane);
+			goto err;
+		}
+		vb->planes[plane].dbuf_mapped = 1;
+	}
+
+	/*
+	 * Call driver-specific initialization on the newly acquired buffer,
+	 * if provided.
+	 */
+	ret = call_qop(q, buf_init, vb);
+	if (ret) {
+		dprintk(1, "qbuf: buffer initialization failed\n");
+		goto err;
+	}
+
+	/*
+	 * Now that everything is in order, copy relevant information
+	 * provided by userspace.
+	 */
+	for (plane = 0; plane < vb->num_planes; ++plane)
+		vb->v4l2_planes[plane] = planes[plane];
+
+	return 0;
+err:
+	/* In case of errors, release planes that were already acquired */
+	__vb2_buf_dmabuf_put(vb);
+
+	return ret;
+}
+
+/**
  * __enqueue_in_driver() - enqueue a vb2_buffer in driver for processing
  */
 static void __enqueue_in_driver(struct vb2_buffer *vb)
 {
 	struct vb2_queue *q = vb->vb2_queue;
+	unsigned int plane;
 
 	vb->state = VB2_BUF_STATE_ACTIVE;
 	atomic_inc(&q->queued_count);
+
+	/* sync buffers */
+	for (plane = 0; plane < vb->num_planes; ++plane)
+		call_memop(q, prepare, vb->planes[plane].mem_priv);
+
 	q->ops->buf_queue(vb);
 }
 
@@ -982,6 +1165,9 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 	case V4L2_MEMORY_USERPTR:
 		ret = __qbuf_userptr(vb, b);
 		break;
+	case V4L2_MEMORY_DMABUF:
+		ret = __qbuf_dmabuf(vb, b);
+		break;
 	default:
 		WARN(1, "Invalid queue type\n");
 		ret = -EINVAL;
@@ -1303,6 +1489,30 @@ int vb2_wait_for_all_buffers(struct vb2_queue *q)
 EXPORT_SYMBOL_GPL(vb2_wait_for_all_buffers);
 
 /**
+ * __vb2_dqbuf() - bring back the buffer to the DEQUEUED state
+ */
+static void __vb2_dqbuf(struct vb2_buffer *vb)
+{
+	struct vb2_queue *q = vb->vb2_queue;
+	unsigned int i;
+
+	/* nothing to do if the buffer is already dequeued */
+	if (vb->state == VB2_BUF_STATE_DEQUEUED)
+		return;
+
+	vb->state = VB2_BUF_STATE_DEQUEUED;
+
+	/* unmap DMABUF buffer */
+	if (q->memory == V4L2_MEMORY_DMABUF)
+		for (i = 0; i < vb->num_planes; ++i) {
+			if (!vb->planes[i].dbuf_mapped)
+				continue;
+			call_memop(q, unmap_dmabuf, vb->planes[i].mem_priv);
+			vb->planes[i].dbuf_mapped = 0;
+		}
+}
+
+/**
  * vb2_dqbuf() - Dequeue a buffer to the userspace
  * @q:		videobuf2 queue
  * @b:		buffer structure passed from userspace to vidioc_dqbuf handler
@@ -1363,11 +1573,12 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
 	__fill_v4l2_buffer(vb, b);
 	/* Remove from videobuf queue */
 	list_del(&vb->queued_entry);
+	/* go back to dequeued state */
+	__vb2_dqbuf(vb);
 
 	dprintk(1, "dqbuf of buffer %d, with state %d\n",
 			vb->v4l2_buf.index, vb->state);
 
-	vb->state = VB2_BUF_STATE_DEQUEUED;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(vb2_dqbuf);
@@ -1406,7 +1617,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 	 * Reinitialize all buffers for next use.
 	 */
 	for (i = 0; i < q->num_buffers; ++i)
-		q->bufs[i]->state = VB2_BUF_STATE_DEQUEUED;
+		__vb2_dqbuf(q->bufs[i]);
 }
 
 /**
@@ -1540,6 +1751,79 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
 }
 
 /**
+ * vb2_expbuf() - Export a buffer as a file descriptor
+ * @q:		videobuf2 queue
+ * @eb:		export buffer structure passed from userspace to vidioc_expbuf
+ *		handler in driver
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_expbuf handler in driver.
+ */
+int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
+{
+	struct vb2_buffer *vb = NULL;
+	struct vb2_plane *vb_plane;
+	int ret;
+	struct dma_buf *dbuf;
+
+	if (q->memory != V4L2_MEMORY_MMAP) {
+		dprintk(1, "Queue is not currently set up for mmap\n");
+		return -EINVAL;
+	}
+
+	if (!q->mem_ops->get_dmabuf) {
+		dprintk(1, "Queue does not support DMA buffer exporting\n");
+		return -EINVAL;
+	}
+
+	if (eb->flags & ~O_CLOEXEC) {
+		dprintk(1, "Queue does support only O_CLOEXEC flag\n");
+		return -EINVAL;
+	}
+
+	if (eb->type != q->type) {
+		dprintk(1, "qbuf: invalid buffer type\n");
+		return -EINVAL;
+	}
+
+	if (eb->index >= q->num_buffers) {
+		dprintk(1, "buffer index out of range\n");
+		return -EINVAL;
+	}
+
+	vb = q->bufs[eb->index];
+
+	if (eb->plane >= vb->num_planes) {
+		dprintk(1, "buffer plane out of range\n");
+		return -EINVAL;
+	}
+
+	vb_plane = &vb->planes[eb->plane];
+
+	dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv);
+	if (IS_ERR_OR_NULL(dbuf)) {
+		dprintk(1, "Failed to export buffer %d, plane %d\n",
+			eb->index, eb->plane);
+		return -EINVAL;
+	}
+
+	ret = dma_buf_fd(dbuf, eb->flags);
+	if (ret < 0) {
+		dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
+			eb->index, eb->plane, ret);
+		dma_buf_put(dbuf);
+		return ret;
+	}
+
+	dprintk(3, "buffer %d, plane %d exported as %d descriptor\n",
+		eb->index, eb->plane, ret);
+	eb->fd = ret;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_expbuf);
+
+/**
  * vb2_mmap() - map video buffers into application address space
  * @q:		videobuf2 queue
  * @vma:	vma passed to the mmap file operation handler in the driver
@@ -2245,6 +2529,16 @@ int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
 }
 EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
 
+int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	if (vb2_queue_is_busy(vdev, file))
+		return -EBUSY;
+	return vb2_expbuf(vdev->queue, p);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
+
 /* v4l2_file_operations helpers */
 
 int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 4b71326..5729450 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -10,7 +10,10 @@
  * the Free Software Foundation.
  */
 
+#include <linux/dma-buf.h>
 #include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 
@@ -23,40 +26,158 @@ struct vb2_dc_conf {
 };
 
 struct vb2_dc_buf {
-	struct vb2_dc_conf		*conf;
+	struct device			*dev;
 	void				*vaddr;
-	dma_addr_t			dma_addr;
 	unsigned long			size;
-	struct vm_area_struct		*vma;
-	atomic_t			refcount;
+	dma_addr_t			dma_addr;
+	enum dma_data_direction		dma_dir;
+	struct sg_table			*dma_sgt;
+
+	/* MMAP related */
 	struct vb2_vmarea_handler	handler;
+	atomic_t			refcount;
+	struct sg_table			*sgt_base;
+
+	/* USERPTR related */
+	struct vm_area_struct		*vma;
+
+	/* DMABUF related */
+	struct dma_buf_attachment	*db_attach;
 };
 
-static void vb2_dma_contig_put(void *buf_priv);
+/*********************************************/
+/*        scatterlist table functions        */
+/*********************************************/
+
+
+static void vb2_dc_sgt_foreach_page(struct sg_table *sgt,
+	void (*cb)(struct page *pg))
+{
+	struct scatterlist *s;
+	unsigned int i;
+
+	for_each_sg(sgt->sgl, s, sgt->orig_nents, i) {
+		struct page *page = sg_page(s);
+		unsigned int n_pages = PAGE_ALIGN(s->offset + s->length)
+			>> PAGE_SHIFT;
+		unsigned int j;
+
+		for (j = 0; j < n_pages; ++j, ++page)
+			cb(page);
+	}
+}
+
+static unsigned long vb2_dc_get_contiguous_size(struct sg_table *sgt)
+{
+	struct scatterlist *s;
+	dma_addr_t expected = sg_dma_address(sgt->sgl);
+	unsigned int i;
+	unsigned long size = 0;
+
+	for_each_sg(sgt->sgl, s, sgt->nents, i) {
+		if (sg_dma_address(s) != expected)
+			break;
+		expected = sg_dma_address(s) + sg_dma_len(s);
+		size += sg_dma_len(s);
+	}
+	return size;
+}
+
+/*********************************************/
+/*         callbacks for all buffers         */
+/*********************************************/
+
+static void *vb2_dc_cookie(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+
+	return &buf->dma_addr;
+}
+
+static void *vb2_dc_vaddr(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+
+	return buf->vaddr;
+}
+
+static unsigned int vb2_dc_num_users(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+
+	return atomic_read(&buf->refcount);
+}
+
+static void vb2_dc_prepare(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+	struct sg_table *sgt = buf->dma_sgt;
+
+	/* DMABUF exporter will flush the cache for us */
+	if (!sgt || buf->db_attach)
+		return;
+
+	dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+}
+
+static void vb2_dc_finish(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+	struct sg_table *sgt = buf->dma_sgt;
+
+	/* DMABUF exporter will flush the cache for us */
+	if (!sgt || buf->db_attach)
+		return;
+
+	dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+}
+
+/*********************************************/
+/*        callbacks for MMAP buffers         */
+/*********************************************/
+
+static void vb2_dc_put(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+
+	if (!atomic_dec_and_test(&buf->refcount))
+		return;
+
+	if (buf->sgt_base) {
+		sg_free_table(buf->sgt_base);
+		kfree(buf->sgt_base);
+	}
+	dma_free_coherent(buf->dev, buf->size, buf->vaddr, buf->dma_addr);
+	put_device(buf->dev);
+	kfree(buf);
+}
 
-static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
+static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
 {
 	struct vb2_dc_conf *conf = alloc_ctx;
+	struct device *dev = conf->dev;
 	struct vb2_dc_buf *buf;
 
 	buf = kzalloc(sizeof *buf, GFP_KERNEL);
 	if (!buf)
 		return ERR_PTR(-ENOMEM);
 
-	buf->vaddr = dma_alloc_coherent(conf->dev, size, &buf->dma_addr,
-					GFP_KERNEL);
+	/* align image size to PAGE_SIZE */
+	size = PAGE_ALIGN(size);
+
+	buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, GFP_KERNEL);
 	if (!buf->vaddr) {
-		dev_err(conf->dev, "dma_alloc_coherent of size %ld failed\n",
-			size);
+		dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
 		kfree(buf);
 		return ERR_PTR(-ENOMEM);
 	}
 
-	buf->conf = conf;
+	/* Prevent the device from being released while the buffer is used */
+	buf->dev = get_device(dev);
 	buf->size = size;
 
 	buf->handler.refcount = &buf->refcount;
-	buf->handler.put = vb2_dma_contig_put;
+	buf->handler.put = vb2_dc_put;
 	buf->handler.arg = buf;
 
 	atomic_inc(&buf->refcount);
@@ -64,100 +185,575 @@ static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
 	return buf;
 }
 
-static void vb2_dma_contig_put(void *buf_priv)
+static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
 {
 	struct vb2_dc_buf *buf = buf_priv;
+	int ret;
 
-	if (atomic_dec_and_test(&buf->refcount)) {
-		dma_free_coherent(buf->conf->dev, buf->size, buf->vaddr,
-				  buf->dma_addr);
-		kfree(buf);
+	if (!buf) {
+		printk(KERN_ERR "No buffer to map\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * dma_mmap_* uses vm_pgoff as in-buffer offset, but we want to
+	 * map whole buffer
+	 */
+	vma->vm_pgoff = 0;
+
+	ret = dma_mmap_coherent(buf->dev, vma, buf->vaddr,
+		buf->dma_addr, buf->size);
+
+	if (ret) {
+		pr_err("Remapping memory failed, error: %d\n", ret);
+		return ret;
 	}
+
+	vma->vm_flags		|= VM_DONTEXPAND | VM_DONTDUMP;
+	vma->vm_private_data	= &buf->handler;
+	vma->vm_ops		= &vb2_common_vm_ops;
+
+	vma->vm_ops->open(vma);
+
+	pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n",
+		__func__, (unsigned long)buf->dma_addr, vma->vm_start,
+		buf->size);
+
+	return 0;
 }
 
-static void *vb2_dma_contig_cookie(void *buf_priv)
+/*********************************************/
+/*         DMABUF ops for exporters          */
+/*********************************************/
+
+#ifdef HAVE_GENERIC_DMA_COHERENT
+
+struct vb2_dc_attachment {
+	struct sg_table sgt;
+	enum dma_data_direction dir;
+};
+
+static int vb2_dc_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
+	struct dma_buf_attachment *dbuf_attach)
 {
-	struct vb2_dc_buf *buf = buf_priv;
+	struct vb2_dc_attachment *attach;
+	unsigned int i;
+	struct scatterlist *rd, *wr;
+	struct sg_table *sgt;
+	struct vb2_dc_buf *buf = dbuf->priv;
+	int ret;
 
-	return &buf->dma_addr;
+	attach = kzalloc(sizeof(*attach), GFP_KERNEL);
+	if (!attach)
+		return -ENOMEM;
+
+	sgt = &attach->sgt;
+	/* Copy the buf->base_sgt scatter list to the attachment, as we can't
+	 * map the same scatter list to multiple attachments at the same time.
+	 */
+	ret = sg_alloc_table(sgt, buf->sgt_base->orig_nents, GFP_KERNEL);
+	if (ret) {
+		kfree(attach);
+		return -ENOMEM;
+	}
+
+	rd = buf->sgt_base->sgl;
+	wr = sgt->sgl;
+	for (i = 0; i < sgt->orig_nents; ++i) {
+		sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
+		rd = sg_next(rd);
+		wr = sg_next(wr);
+	}
+
+	attach->dir = DMA_NONE;
+	dbuf_attach->priv = attach;
+
+	return 0;
 }
 
-static void *vb2_dma_contig_vaddr(void *buf_priv)
+static void vb2_dc_dmabuf_ops_detach(struct dma_buf *dbuf,
+	struct dma_buf_attachment *db_attach)
 {
-	struct vb2_dc_buf *buf = buf_priv;
-	if (!buf)
-		return NULL;
+	struct vb2_dc_attachment *attach = db_attach->priv;
+	struct sg_table *sgt;
+
+	if (!attach)
+		return;
+
+	sgt = &attach->sgt;
+
+	/* release the scatterlist cache */
+	if (attach->dir != DMA_NONE)
+		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
+			attach->dir);
+	sg_free_table(sgt);
+	kfree(attach);
+	db_attach->priv = NULL;
+}
+
+static struct sg_table *vb2_dc_dmabuf_ops_map(
+	struct dma_buf_attachment *db_attach, enum dma_data_direction dir)
+{
+	struct vb2_dc_attachment *attach = db_attach->priv;
+	/* stealing dmabuf mutex to serialize map/unmap operations */
+	struct mutex *lock = &db_attach->dmabuf->lock;
+	struct sg_table *sgt;
+	int ret;
+
+	mutex_lock(lock);
+
+	sgt = &attach->sgt;
+	/* return previously mapped sg table */
+	if (attach->dir == dir) {
+		mutex_unlock(lock);
+		return sgt;
+	}
+
+	/* release any previous cache */
+	if (attach->dir != DMA_NONE) {
+		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
+			attach->dir);
+		attach->dir = DMA_NONE;
+	}
+
+	/* mapping to the client with new direction */
+	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dir);
+	if (ret <= 0) {
+		pr_err("failed to map scatterlist\n");
+		mutex_unlock(lock);
+		return ERR_PTR(-EIO);
+	}
+
+	attach->dir = dir;
+
+	mutex_unlock(lock);
+
+	return sgt;
+}
+
+static void vb2_dc_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
+	struct sg_table *sgt, enum dma_data_direction dir)
+{
+	/* nothing to be done here */
+}
+
+static void vb2_dc_dmabuf_ops_release(struct dma_buf *dbuf)
+{
+	/* drop reference obtained in vb2_dc_get_dmabuf */
+	vb2_dc_put(dbuf->priv);
+}
+
+static void *vb2_dc_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
+{
+	struct vb2_dc_buf *buf = dbuf->priv;
+
+	return buf->vaddr + pgnum * PAGE_SIZE;
+}
+
+static void *vb2_dc_dmabuf_ops_vmap(struct dma_buf *dbuf)
+{
+	struct vb2_dc_buf *buf = dbuf->priv;
 
 	return buf->vaddr;
 }
 
-static unsigned int vb2_dma_contig_num_users(void *buf_priv)
+static int vb2_dc_dmabuf_ops_mmap(struct dma_buf *dbuf,
+	struct vm_area_struct *vma)
 {
-	struct vb2_dc_buf *buf = buf_priv;
+	return vb2_dc_mmap(dbuf->priv, vma);
+}
 
-	return atomic_read(&buf->refcount);
+static struct dma_buf_ops vb2_dc_dmabuf_ops = {
+	.attach = vb2_dc_dmabuf_ops_attach,
+	.detach = vb2_dc_dmabuf_ops_detach,
+	.map_dma_buf = vb2_dc_dmabuf_ops_map,
+	.unmap_dma_buf = vb2_dc_dmabuf_ops_unmap,
+	.kmap = vb2_dc_dmabuf_ops_kmap,
+	.kmap_atomic = vb2_dc_dmabuf_ops_kmap,
+	.vmap = vb2_dc_dmabuf_ops_vmap,
+	.mmap = vb2_dc_dmabuf_ops_mmap,
+	.release = vb2_dc_dmabuf_ops_release,
+};
+
+static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
+{
+	int ret;
+	struct sg_table *sgt;
+
+	sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+	if (!sgt) {
+		dev_err(buf->dev, "failed to alloc sg table\n");
+		return NULL;
+	}
+
+	ret = dma_get_sgtable(buf->dev, sgt, buf->vaddr, buf->dma_addr,
+		buf->size);
+	if (ret < 0) {
+		dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
+		kfree(sgt);
+		return NULL;
+	}
+
+	return sgt;
 }
 
-static int vb2_dma_contig_mmap(void *buf_priv, struct vm_area_struct *vma)
+static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv)
 {
 	struct vb2_dc_buf *buf = buf_priv;
+	struct dma_buf *dbuf;
 
-	if (!buf) {
-		printk(KERN_ERR "No buffer to map\n");
-		return -EINVAL;
+	if (!buf->sgt_base)
+		buf->sgt_base = vb2_dc_get_base_sgt(buf);
+
+	if (WARN_ON(!buf->sgt_base))
+		return NULL;
+
+	dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, 0);
+	if (IS_ERR(dbuf))
+		return NULL;
+
+	/* dmabuf keeps reference to vb2 buffer */
+	atomic_inc(&buf->refcount);
+
+	return dbuf;
+}
+
+#endif
+
+/*********************************************/
+/*       callbacks for USERPTR buffers       */
+/*********************************************/
+
+static inline int vma_is_io(struct vm_area_struct *vma)
+{
+	return !!(vma->vm_flags & (VM_IO | VM_PFNMAP));
+}
+
+static int vb2_dc_get_user_pages(unsigned long start, struct page **pages,
+	int n_pages, struct vm_area_struct *vma, int write)
+{
+	if (vma_is_io(vma)) {
+		unsigned int i;
+
+		for (i = 0; i < n_pages; ++i, start += PAGE_SIZE) {
+			unsigned long pfn;
+			int ret = follow_pfn(vma, start, &pfn);
+
+			if (ret) {
+				pr_err("no page for address %lu\n", start);
+				return ret;
+			}
+			pages[i] = pfn_to_page(pfn);
+		}
+	} else {
+		int n;
+
+		n = get_user_pages(current, current->mm, start & PAGE_MASK,
+			n_pages, write, 1, pages, NULL);
+		/* negative error means that no page was pinned */
+		n = max(n, 0);
+		if (n != n_pages) {
+			pr_err("got only %d of %d user pages\n", n, n_pages);
+			while (n)
+				put_page(pages[--n]);
+			return -EFAULT;
+		}
 	}
 
-	return vb2_mmap_pfn_range(vma, buf->dma_addr, buf->size,
-				  &vb2_common_vm_ops, &buf->handler);
+	return 0;
 }
 
-static void *vb2_dma_contig_get_userptr(void *alloc_ctx, unsigned long vaddr,
-					unsigned long size, int write)
+static void vb2_dc_put_dirty_page(struct page *page)
 {
+	set_page_dirty_lock(page);
+	put_page(page);
+}
+
+static void vb2_dc_put_userptr(void *buf_priv)
+{
+	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);
+
+	sg_free_table(sgt);
+	kfree(sgt);
+	vb2_put_vma(buf->vma);
+	kfree(buf);
+}
+
+static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
+	unsigned long size, int write)
+{
+	struct vb2_dc_conf *conf = alloc_ctx;
 	struct vb2_dc_buf *buf;
+	unsigned long start;
+	unsigned long end;
+	unsigned long offset;
+	struct page **pages;
+	int n_pages;
+	int ret = 0;
 	struct vm_area_struct *vma;
-	dma_addr_t dma_addr = 0;
-	int ret;
+	struct sg_table *sgt;
+	unsigned long contig_size;
+	unsigned long dma_align = dma_get_cache_alignment();
+
+	/* Only cache aligned DMA transfers are reliable */
+	if (!IS_ALIGNED(vaddr | size, dma_align)) {
+		pr_debug("user data must be aligned to %lu bytes\n", dma_align);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!size) {
+		pr_debug("size is zero\n");
+		return ERR_PTR(-EINVAL);
+	}
 
 	buf = kzalloc(sizeof *buf, GFP_KERNEL);
 	if (!buf)
 		return ERR_PTR(-ENOMEM);
 
-	ret = vb2_get_contig_userptr(vaddr, size, &vma, &dma_addr);
+	buf->dev = conf->dev;
+	buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+	start = vaddr & PAGE_MASK;
+	offset = vaddr & ~PAGE_MASK;
+	end = PAGE_ALIGN(vaddr + size);
+	n_pages = (end - start) >> PAGE_SHIFT;
+
+	pages = kmalloc(n_pages * sizeof(pages[0]), GFP_KERNEL);
+	if (!pages) {
+		ret = -ENOMEM;
+		pr_err("failed to allocate pages table\n");
+		goto fail_buf;
+	}
+
+	/* current->mm->mmap_sem is taken by videobuf2 core */
+	vma = find_vma(current->mm, vaddr);
+	if (!vma) {
+		pr_err("no vma for address %lu\n", vaddr);
+		ret = -EFAULT;
+		goto fail_pages;
+	}
+
+	if (vma->vm_end < vaddr + size) {
+		pr_err("vma at %lu is too small for %lu bytes\n", vaddr, size);
+		ret = -EFAULT;
+		goto fail_pages;
+	}
+
+	buf->vma = vb2_get_vma(vma);
+	if (!buf->vma) {
+		pr_err("failed to copy vma\n");
+		ret = -ENOMEM;
+		goto fail_pages;
+	}
+
+	/* extract page list from userspace mapping */
+	ret = vb2_dc_get_user_pages(start, pages, n_pages, vma, write);
 	if (ret) {
-		printk(KERN_ERR "Failed acquiring VMA for vaddr 0x%08lx\n",
-				vaddr);
-		kfree(buf);
-		return ERR_PTR(ret);
+		pr_err("failed to get user pages\n");
+		goto fail_vma;
+	}
+
+	sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
+	if (!sgt) {
+		pr_err("failed to allocate sg table\n");
+		ret = -ENOMEM;
+		goto fail_get_user_pages;
+	}
+
+	ret = sg_alloc_table_from_pages(sgt, pages, n_pages,
+		offset, size, GFP_KERNEL);
+	if (ret) {
+		pr_err("failed to initialize sg table\n");
+		goto fail_sgt;
+	}
+
+	/* pages are no longer needed */
+	kfree(pages);
+	pages = NULL;
+
+	sgt->nents = dma_map_sg(buf->dev, sgt->sgl, sgt->orig_nents,
+		buf->dma_dir);
+	if (sgt->nents <= 0) {
+		pr_err("failed to map scatterlist\n");
+		ret = -EIO;
+		goto fail_sgt_init;
 	}
 
+	contig_size = vb2_dc_get_contiguous_size(sgt);
+	if (contig_size < size) {
+		pr_err("contiguous mapping is too small %lu/%lu\n",
+			contig_size, size);
+		ret = -EFAULT;
+		goto fail_map_sg;
+	}
+
+	buf->dma_addr = sg_dma_address(sgt->sgl);
 	buf->size = size;
-	buf->dma_addr = dma_addr;
-	buf->vma = vma;
+	buf->dma_sgt = sgt;
 
 	return buf;
+
+fail_map_sg:
+	dma_unmap_sg(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
+
+fail_sgt_init:
+	if (!vma_is_io(buf->vma))
+		vb2_dc_sgt_foreach_page(sgt, put_page);
+	sg_free_table(sgt);
+
+fail_sgt:
+	kfree(sgt);
+
+fail_get_user_pages:
+	if (pages && !vma_is_io(buf->vma))
+		while (n_pages)
+			put_page(pages[--n_pages]);
+
+fail_vma:
+	vb2_put_vma(buf->vma);
+
+fail_pages:
+	kfree(pages); /* kfree is NULL-proof */
+
+fail_buf:
+	kfree(buf);
+
+	return ERR_PTR(ret);
 }
 
-static void vb2_dma_contig_put_userptr(void *mem_priv)
+/*********************************************/
+/*       callbacks for DMABUF buffers        */
+/*********************************************/
+
+static int vb2_dc_map_dmabuf(void *mem_priv)
 {
 	struct vb2_dc_buf *buf = mem_priv;
+	struct sg_table *sgt;
+	unsigned long contig_size;
 
-	if (!buf)
+	if (WARN_ON(!buf->db_attach)) {
+		pr_err("trying to pin a non attached buffer\n");
+		return -EINVAL;
+	}
+
+	if (WARN_ON(buf->dma_sgt)) {
+		pr_err("dmabuf buffer is already pinned\n");
+		return 0;
+	}
+
+	/* get the associated scatterlist for this buffer */
+	sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir);
+	if (IS_ERR_OR_NULL(sgt)) {
+		pr_err("Error getting dmabuf scatterlist\n");
+		return -EINVAL;
+	}
+
+	/* checking if dmabuf is big enough to store contiguous chunk */
+	contig_size = vb2_dc_get_contiguous_size(sgt);
+	if (contig_size < buf->size) {
+		pr_err("contiguous chunk is too small %lu/%lu b\n",
+			contig_size, buf->size);
+		dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);
+		return -EFAULT;
+	}
+
+	buf->dma_addr = sg_dma_address(sgt->sgl);
+	buf->dma_sgt = sgt;
+
+	return 0;
+}
+
+static void vb2_dc_unmap_dmabuf(void *mem_priv)
+{
+	struct vb2_dc_buf *buf = mem_priv;
+	struct sg_table *sgt = buf->dma_sgt;
+
+	if (WARN_ON(!buf->db_attach)) {
+		pr_err("trying to unpin a not attached buffer\n");
 		return;
+	}
 
-	vb2_put_vma(buf->vma);
+	if (WARN_ON(!sgt)) {
+		pr_err("dmabuf buffer is already unpinned\n");
+		return;
+	}
+
+	dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);
+
+	buf->dma_addr = 0;
+	buf->dma_sgt = NULL;
+}
+
+static void vb2_dc_detach_dmabuf(void *mem_priv)
+{
+	struct vb2_dc_buf *buf = mem_priv;
+
+	/* if vb2 works correctly you should never detach mapped buffer */
+	if (WARN_ON(buf->dma_addr))
+		vb2_dc_unmap_dmabuf(buf);
+
+	/* detach this attachment */
+	dma_buf_detach(buf->db_attach->dmabuf, buf->db_attach);
 	kfree(buf);
 }
 
+static void *vb2_dc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
+	unsigned long size, int write)
+{
+	struct vb2_dc_conf *conf = alloc_ctx;
+	struct vb2_dc_buf *buf;
+	struct dma_buf_attachment *dba;
+
+	if (dbuf->size < size)
+		return ERR_PTR(-EFAULT);
+
+	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	buf->dev = conf->dev;
+	/* create attachment for the dmabuf with the user device */
+	dba = dma_buf_attach(dbuf, buf->dev);
+	if (IS_ERR(dba)) {
+		pr_err("failed to attach dmabuf\n");
+		kfree(buf);
+		return dba;
+	}
+
+	buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	buf->size = size;
+	buf->db_attach = dba;
+
+	return buf;
+}
+
+/*********************************************/
+/*       DMA CONTIG exported functions       */
+/*********************************************/
+
 const struct vb2_mem_ops vb2_dma_contig_memops = {
-	.alloc		= vb2_dma_contig_alloc,
-	.put		= vb2_dma_contig_put,
-	.cookie		= vb2_dma_contig_cookie,
-	.vaddr		= vb2_dma_contig_vaddr,
-	.mmap		= vb2_dma_contig_mmap,
-	.get_userptr	= vb2_dma_contig_get_userptr,
-	.put_userptr	= vb2_dma_contig_put_userptr,
-	.num_users	= vb2_dma_contig_num_users,
+	.alloc		= vb2_dc_alloc,
+	.put		= vb2_dc_put,
+#ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT
+	.get_dmabuf	= vb2_dc_get_dmabuf,
+#endif
+	.cookie		= vb2_dc_cookie,
+	.vaddr		= vb2_dc_vaddr,
+	.mmap		= vb2_dc_mmap,
+	.get_userptr	= vb2_dc_get_userptr,
+	.put_userptr	= vb2_dc_put_userptr,
+	.prepare	= vb2_dc_prepare,
+	.finish		= vb2_dc_finish,
+	.map_dmabuf	= vb2_dc_map_dmabuf,
+	.unmap_dmabuf	= vb2_dc_unmap_dmabuf,
+	.attach_dmabuf	= vb2_dc_attach_dmabuf,
+	.detach_dmabuf	= vb2_dc_detach_dmabuf,
+	.num_users	= vb2_dc_num_users,
 };
 EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
 
diff --git a/drivers/media/v4l2-core/videobuf2-memops.c b/drivers/media/v4l2-core/videobuf2-memops.c
index 051ea35..81c1ad8 100644
--- a/drivers/media/v4l2-core/videobuf2-memops.c
+++ b/drivers/media/v4l2-core/videobuf2-memops.c
@@ -137,46 +137,6 @@ int vb2_get_contig_userptr(unsigned long vaddr, unsigned long size,
 EXPORT_SYMBOL_GPL(vb2_get_contig_userptr);
 
 /**
- * vb2_mmap_pfn_range() - map physical pages to userspace
- * @vma:	virtual memory region for the mapping
- * @paddr:	starting physical address of the memory to be mapped
- * @size:	size of the memory to be mapped
- * @vm_ops:	vm operations to be assigned to the created area
- * @priv:	private data to be associated with the area
- *
- * Returns 0 on success.
- */
-int vb2_mmap_pfn_range(struct vm_area_struct *vma, unsigned long paddr,
-				unsigned long size,
-				const struct vm_operations_struct *vm_ops,
-				void *priv)
-{
-	int ret;
-
-	size = min_t(unsigned long, vma->vm_end - vma->vm_start, size);
-
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-	ret = remap_pfn_range(vma, vma->vm_start, paddr >> PAGE_SHIFT,
-				size, vma->vm_page_prot);
-	if (ret) {
-		printk(KERN_ERR "Remapping memory failed, error: %d\n", ret);
-		return ret;
-	}
-
-	vma->vm_flags		|= VM_DONTEXPAND | VM_DONTDUMP;
-	vma->vm_private_data	= priv;
-	vma->vm_ops		= vm_ops;
-
-	vma->vm_ops->open(vma);
-
-	pr_debug("%s: mapped paddr 0x%08lx at 0x%08lx, size %ld\n",
-			__func__, paddr, vma->vm_start, size);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(vb2_mmap_pfn_range);
-
-/**
  * vb2_common_vm_open() - increase refcount of the vma
  * @vma:	virtual memory region for the mapping
  *
diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index 94efa04..a47fd4f 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -30,6 +30,7 @@ struct vb2_vmalloc_buf {
 	unsigned int			n_pages;
 	atomic_t			refcount;
 	struct vb2_vmarea_handler	handler;
+	struct dma_buf			*dbuf;
 };
 
 static void vb2_vmalloc_put(void *buf_priv);
@@ -207,11 +208,66 @@ static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma)
 	return 0;
 }
 
+/*********************************************/
+/*       callbacks for DMABUF buffers        */
+/*********************************************/
+
+static int vb2_vmalloc_map_dmabuf(void *mem_priv)
+{
+	struct vb2_vmalloc_buf *buf = mem_priv;
+
+	buf->vaddr = dma_buf_vmap(buf->dbuf);
+
+	return buf->vaddr ? 0 : -EFAULT;
+}
+
+static void vb2_vmalloc_unmap_dmabuf(void *mem_priv)
+{
+	struct vb2_vmalloc_buf *buf = mem_priv;
+
+	dma_buf_vunmap(buf->dbuf, buf->vaddr);
+	buf->vaddr = NULL;
+}
+
+static void vb2_vmalloc_detach_dmabuf(void *mem_priv)
+{
+	struct vb2_vmalloc_buf *buf = mem_priv;
+
+	if (buf->vaddr)
+		dma_buf_vunmap(buf->dbuf, buf->vaddr);
+
+	kfree(buf);
+}
+
+static void *vb2_vmalloc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
+	unsigned long size, int write)
+{
+	struct vb2_vmalloc_buf *buf;
+
+	if (dbuf->size < size)
+		return ERR_PTR(-EFAULT);
+
+	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	buf->dbuf = dbuf;
+	buf->write = write;
+	buf->size = size;
+
+	return buf;
+}
+
+
 const struct vb2_mem_ops vb2_vmalloc_memops = {
 	.alloc		= vb2_vmalloc_alloc,
 	.put		= vb2_vmalloc_put,
 	.get_userptr	= vb2_vmalloc_get_userptr,
 	.put_userptr	= vb2_vmalloc_put_userptr,
+	.map_dmabuf	= vb2_vmalloc_map_dmabuf,
+	.unmap_dmabuf	= vb2_vmalloc_unmap_dmabuf,
+	.attach_dmabuf	= vb2_vmalloc_attach_dmabuf,
+	.detach_dmabuf	= vb2_vmalloc_detach_dmabuf,
 	.vaddr		= vb2_vmalloc_vaddr,
 	.mmap		= vb2_vmalloc_mmap,
 	.num_users	= vb2_vmalloc_num_users,
diff --git a/drivers/memstick/host/Kconfig b/drivers/memstick/host/Kconfig
index cc0997a..4f7a17f 100644
--- a/drivers/memstick/host/Kconfig
+++ b/drivers/memstick/host/Kconfig
@@ -42,3 +42,13 @@ config MEMSTICK_R592
 
 	  To compile this driver as a module, choose M here: the module will
 	  be called r592.
+
+config MEMSTICK_REALTEK_PCI
+	tristate "Realtek PCI-E Memstick Card Interface Driver"
+	depends on MFD_RTSX_PCI
+	help
+	  Say Y here to include driver code to support Memstick card interface
+	  of Realtek PCI-E card reader
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called rtsx_pci_ms.
diff --git a/drivers/memstick/host/Makefile b/drivers/memstick/host/Makefile
index 31ba8d3..af3459d 100644
--- a/drivers/memstick/host/Makefile
+++ b/drivers/memstick/host/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_MEMSTICK_TIFM_MS)		+= tifm_ms.o
 obj-$(CONFIG_MEMSTICK_JMICRON_38X)	+= jmb38x_ms.o
 obj-$(CONFIG_MEMSTICK_R592)		+= r592.o
+obj-$(CONFIG_MEMSTICK_REALTEK_PCI)	+= rtsx_pci_ms.o
diff --git a/drivers/memstick/host/rtsx_pci_ms.c b/drivers/memstick/host/rtsx_pci_ms.c
new file mode 100644
index 0000000..f5ddb82
--- /dev/null
+++ b/drivers/memstick/host/rtsx_pci_ms.c
@@ -0,0 +1,641 @@
+/* Realtek PCI-Express Memstick Card Interface driver
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/module.h>
+#include <linux/highmem.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/memstick.h>
+#include <linux/mfd/rtsx_pci.h>
+#include <asm/unaligned.h>
+
+struct realtek_pci_ms {
+	struct platform_device	*pdev;
+	struct rtsx_pcr		*pcr;
+	struct memstick_host	*msh;
+	struct memstick_request	*req;
+
+	struct mutex		host_mutex;
+	struct work_struct	handle_req;
+
+	u8			ssc_depth;
+	unsigned int		clock;
+	unsigned char           ifmode;
+	bool			eject;
+};
+
+static inline struct device *ms_dev(struct realtek_pci_ms *host)
+{
+	return &(host->pdev->dev);
+}
+
+static inline void ms_clear_error(struct realtek_pci_ms *host)
+{
+	rtsx_pci_write_register(host->pcr, CARD_STOP,
+			MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR);
+}
+
+#ifdef DEBUG
+
+static void ms_print_debug_regs(struct realtek_pci_ms *host)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	u16 i;
+	u8 *ptr;
+
+	/* Print MS host internal registers */
+	rtsx_pci_init_cmd(pcr);
+	for (i = 0xFD40; i <= 0xFD44; i++)
+		rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
+	for (i = 0xFD52; i <= 0xFD69; i++)
+		rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
+	rtsx_pci_send_cmd(pcr, 100);
+
+	ptr = rtsx_pci_get_cmd_data(pcr);
+	for (i = 0xFD40; i <= 0xFD44; i++)
+		dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
+	for (i = 0xFD52; i <= 0xFD69; i++)
+		dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
+}
+
+#else
+
+#define ms_print_debug_regs(host)
+
+#endif
+
+static int ms_power_on(struct realtek_pci_ms *host)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	int err;
+
+	rtsx_pci_init_cmd(pcr);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, MS_MOD_SEL);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE,
+			CARD_SHARE_MASK, CARD_SHARE_48_MS);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN,
+			MS_CLK_EN, MS_CLK_EN);
+	err = rtsx_pci_send_cmd(pcr, 100);
+	if (err < 0)
+		return err;
+
+	err = rtsx_pci_card_pull_ctl_enable(pcr, RTSX_MS_CARD);
+	if (err < 0)
+		return err;
+
+	err = rtsx_pci_card_power_on(pcr, RTSX_MS_CARD);
+	if (err < 0)
+		return err;
+
+	/* Wait ms power stable */
+	msleep(150);
+
+	err = rtsx_pci_write_register(pcr, CARD_OE,
+			MS_OUTPUT_EN, MS_OUTPUT_EN);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int ms_power_off(struct realtek_pci_ms *host)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	int err;
+
+	rtsx_pci_init_cmd(pcr);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, 0);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0);
+
+	err = rtsx_pci_send_cmd(pcr, 100);
+	if (err < 0)
+		return err;
+
+	err = rtsx_pci_card_power_off(pcr, RTSX_MS_CARD);
+	if (err < 0)
+		return err;
+
+	return rtsx_pci_card_pull_ctl_disable(pcr, RTSX_MS_CARD);
+}
+
+static int ms_transfer_data(struct realtek_pci_ms *host, unsigned char data_dir,
+		u8 tpc, u8 cfg, struct scatterlist *sg)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	int err;
+	unsigned int length = sg->length;
+	u16 sec_cnt = (u16)(length / 512);
+	u8 val, trans_mode, dma_dir;
+
+	dev_dbg(ms_dev(host), "%s: tpc = 0x%02x, data_dir = %s, length = %d\n",
+			__func__, tpc, (data_dir == READ) ? "READ" : "WRITE",
+			length);
+
+	if (data_dir == READ) {
+		dma_dir = DMA_DIR_FROM_CARD;
+		trans_mode = MS_TM_AUTO_READ;
+	} else {
+		dma_dir = DMA_DIR_TO_CARD;
+		trans_mode = MS_TM_AUTO_WRITE;
+	}
+
+	rtsx_pci_init_cmd(pcr);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_H,
+			0xFF, (u8)(sec_cnt >> 8));
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_L,
+			0xFF, (u8)sec_cnt);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0,
+			DMA_DONE_INT, DMA_DONE_INT);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(length >> 24));
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(length >> 16));
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(length >> 8));
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)length);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL,
+			0x03 | DMA_PACK_SIZE_MASK, dma_dir | DMA_EN | DMA_512);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+			0x01, RING_BUFFER);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
+			0xFF, MS_TRANSFER_START | trans_mode);
+	rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
+			MS_TRANSFER_END, MS_TRANSFER_END);
+
+	rtsx_pci_send_cmd_no_wait(pcr);
+
+	err = rtsx_pci_transfer_data(pcr, sg, 1, data_dir == READ, 10000);
+	if (err < 0) {
+		ms_clear_error(host);
+		return err;
+	}
+
+	rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
+	if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT))
+		return -EIO;
+
+	return 0;
+}
+
+static int ms_write_bytes(struct realtek_pci_ms *host, u8 tpc,
+		u8 cfg, u8 cnt, u8 *data, u8 *int_reg)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	int err, i;
+
+	dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc);
+
+	if (!data)
+		return -EINVAL;
+
+	rtsx_pci_init_cmd(pcr);
+
+	for (i = 0; i < cnt; i++)
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+				PPBUF_BASE2 + i, 0xFF, data[i]);
+	if (cnt % 2)
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+				PPBUF_BASE2 + i, 0xFF, 0xFF);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+			0x01, PINGPONG_BUFFER);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
+			0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES);
+	rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
+			MS_TRANSFER_END, MS_TRANSFER_END);
+	if (int_reg)
+		rtsx_pci_add_cmd(pcr, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
+
+	err = rtsx_pci_send_cmd(pcr, 5000);
+	if (err < 0) {
+		u8 val;
+
+		rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
+		dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val);
+
+		if (int_reg)
+			*int_reg = val & 0x0F;
+
+		ms_print_debug_regs(host);
+
+		ms_clear_error(host);
+
+		if (!(tpc & 0x08)) {
+			if (val & MS_CRC16_ERR)
+				return -EIO;
+		} else {
+			if (!(val & 0x80)) {
+				if (val & (MS_INT_ERR | MS_INT_CMDNK))
+					return -EIO;
+			}
+		}
+
+		return -ETIMEDOUT;
+	}
+
+	if (int_reg) {
+		u8 *ptr = rtsx_pci_get_cmd_data(pcr) + 1;
+		*int_reg = *ptr & 0x0F;
+	}
+
+	return 0;
+}
+
+static int ms_read_bytes(struct realtek_pci_ms *host, u8 tpc,
+		u8 cfg, u8 cnt, u8 *data, u8 *int_reg)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	int err, i;
+	u8 *ptr;
+
+	dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc);
+
+	if (!data)
+		return -EINVAL;
+
+	rtsx_pci_init_cmd(pcr);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+			0x01, PINGPONG_BUFFER);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
+			0xFF, MS_TRANSFER_START | MS_TM_READ_BYTES);
+	rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
+			MS_TRANSFER_END, MS_TRANSFER_END);
+	for (i = 0; i < cnt - 1; i++)
+		rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
+	if (cnt % 2)
+		rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + cnt, 0, 0);
+	else
+		rtsx_pci_add_cmd(pcr, READ_REG_CMD,
+				PPBUF_BASE2 + cnt - 1, 0, 0);
+	if (int_reg)
+		rtsx_pci_add_cmd(pcr, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
+
+	err = rtsx_pci_send_cmd(pcr, 5000);
+	if (err < 0) {
+		u8 val;
+
+		rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
+		dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val);
+
+		if (int_reg)
+			*int_reg = val & 0x0F;
+
+		ms_print_debug_regs(host);
+
+		ms_clear_error(host);
+
+		if (!(tpc & 0x08)) {
+			if (val & MS_CRC16_ERR)
+				return -EIO;
+		} else {
+			if (!(val & 0x80)) {
+				if (val & (MS_INT_ERR | MS_INT_CMDNK))
+					return -EIO;
+			}
+		}
+
+		return -ETIMEDOUT;
+	}
+
+	ptr = rtsx_pci_get_cmd_data(pcr) + 1;
+	for (i = 0; i < cnt; i++)
+		data[i] = *ptr++;
+
+	if (int_reg)
+		*int_reg = *ptr & 0x0F;
+
+	return 0;
+}
+
+static int rtsx_pci_ms_issue_cmd(struct realtek_pci_ms *host)
+{
+	struct memstick_request *req = host->req;
+	int err = 0;
+	u8 cfg = 0, int_reg;
+
+	dev_dbg(ms_dev(host), "%s\n", __func__);
+
+	if (req->need_card_int) {
+		if (host->ifmode != MEMSTICK_SERIAL)
+			cfg = WAIT_INT;
+	}
+
+	if (req->long_data) {
+		err = ms_transfer_data(host, req->data_dir,
+				req->tpc, cfg, &(req->sg));
+	} else {
+		if (req->data_dir == READ) {
+			err = ms_read_bytes(host, req->tpc, cfg,
+					req->data_len, req->data, &int_reg);
+		} else {
+			err = ms_write_bytes(host, req->tpc, cfg,
+					req->data_len, req->data, &int_reg);
+		}
+	}
+	if (err < 0)
+		return err;
+
+	if (req->need_card_int && (host->ifmode == MEMSTICK_SERIAL)) {
+		err = ms_read_bytes(host, MS_TPC_GET_INT,
+				NO_WAIT_INT, 1, &int_reg, NULL);
+		if (err < 0)
+			return err;
+	}
+
+	if (req->need_card_int) {
+		dev_dbg(ms_dev(host), "int_reg: 0x%02x\n", int_reg);
+
+		if (int_reg & MS_INT_CMDNK)
+			req->int_reg |= MEMSTICK_INT_CMDNAK;
+		if (int_reg & MS_INT_BREQ)
+			req->int_reg |= MEMSTICK_INT_BREQ;
+		if (int_reg & MS_INT_ERR)
+			req->int_reg |= MEMSTICK_INT_ERR;
+		if (int_reg & MS_INT_CED)
+			req->int_reg |= MEMSTICK_INT_CED;
+	}
+
+	return 0;
+}
+
+static void rtsx_pci_ms_handle_req(struct work_struct *work)
+{
+	struct realtek_pci_ms *host = container_of(work,
+			struct realtek_pci_ms, handle_req);
+	struct rtsx_pcr *pcr = host->pcr;
+	struct memstick_host *msh = host->msh;
+	int rc;
+
+	mutex_lock(&pcr->pcr_mutex);
+
+	rtsx_pci_start_run(pcr);
+
+	rtsx_pci_switch_clock(host->pcr, host->clock, host->ssc_depth,
+			false, true, false);
+	rtsx_pci_write_register(pcr, CARD_SELECT, 0x07, MS_MOD_SEL);
+	rtsx_pci_write_register(pcr, CARD_SHARE_MODE,
+			CARD_SHARE_MASK, CARD_SHARE_48_MS);
+
+	if (!host->req) {
+		do {
+			rc = memstick_next_req(msh, &host->req);
+			dev_dbg(ms_dev(host), "next req %d\n", rc);
+
+			if (!rc)
+				host->req->error = rtsx_pci_ms_issue_cmd(host);
+		} while (!rc);
+	}
+
+	mutex_unlock(&pcr->pcr_mutex);
+}
+
+static void rtsx_pci_ms_request(struct memstick_host *msh)
+{
+	struct realtek_pci_ms *host = memstick_priv(msh);
+
+	dev_dbg(ms_dev(host), "--> %s\n", __func__);
+
+	schedule_work(&host->handle_req);
+}
+
+static int rtsx_pci_ms_set_param(struct memstick_host *msh,
+		enum memstick_param param, int value)
+{
+	struct realtek_pci_ms *host = memstick_priv(msh);
+	struct rtsx_pcr *pcr = host->pcr;
+	unsigned int clock = 0;
+	u8 ssc_depth = 0;
+	int err;
+
+	dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n",
+			__func__, param, value);
+
+	switch (param) {
+	case MEMSTICK_POWER:
+		if (value == MEMSTICK_POWER_ON)
+			err = ms_power_on(host);
+		else if (value == MEMSTICK_POWER_OFF)
+			err = ms_power_off(host);
+		else
+			return -EINVAL;
+		break;
+
+	case MEMSTICK_INTERFACE:
+		if (value == MEMSTICK_SERIAL) {
+			clock = 19000000;
+			ssc_depth = RTSX_SSC_DEPTH_500K;
+
+			err = rtsx_pci_write_register(pcr, MS_CFG,
+					0x18, MS_BUS_WIDTH_1);
+			if (err < 0)
+				return err;
+		} else if (value == MEMSTICK_PAR4) {
+			clock = 39000000;
+			ssc_depth = RTSX_SSC_DEPTH_1M;
+
+			err = rtsx_pci_write_register(pcr, MS_CFG,
+					0x58, MS_BUS_WIDTH_4 | PUSH_TIME_ODD);
+			if (err < 0)
+				return err;
+		} else {
+			return -EINVAL;
+		}
+
+		err = rtsx_pci_switch_clock(pcr, clock,
+				ssc_depth, false, true, false);
+		if (err < 0)
+			return err;
+
+		host->ssc_depth = ssc_depth;
+		host->clock = clock;
+		host->ifmode = value;
+		break;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int rtsx_pci_ms_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct realtek_pci_ms *host = platform_get_drvdata(pdev);
+	struct memstick_host *msh = host->msh;
+
+	dev_dbg(ms_dev(host), "--> %s\n", __func__);
+
+	memstick_suspend_host(msh);
+	return 0;
+}
+
+static int rtsx_pci_ms_resume(struct platform_device *pdev)
+{
+	struct realtek_pci_ms *host = platform_get_drvdata(pdev);
+	struct memstick_host *msh = host->msh;
+
+	dev_dbg(ms_dev(host), "--> %s\n", __func__);
+
+	memstick_resume_host(msh);
+	return 0;
+}
+
+#else /* CONFIG_PM */
+
+#define rtsx_pci_ms_suspend NULL
+#define rtsx_pci_ms_resume NULL
+
+#endif /* CONFIG_PM */
+
+static void rtsx_pci_ms_card_event(struct platform_device *pdev)
+{
+	struct realtek_pci_ms *host = platform_get_drvdata(pdev);
+
+	memstick_detect_change(host->msh);
+}
+
+static int rtsx_pci_ms_drv_probe(struct platform_device *pdev)
+{
+	struct memstick_host *msh;
+	struct realtek_pci_ms *host;
+	struct rtsx_pcr *pcr;
+	struct pcr_handle *handle = pdev->dev.platform_data;
+	int rc;
+
+	if (!handle)
+		return -ENXIO;
+
+	pcr = handle->pcr;
+	if (!pcr)
+		return -ENXIO;
+
+	dev_dbg(&(pdev->dev),
+			": Realtek PCI-E Memstick controller found\n");
+
+	msh = memstick_alloc_host(sizeof(*host), &pdev->dev);
+	if (!msh)
+		return -ENOMEM;
+
+	host = memstick_priv(msh);
+	host->pcr = pcr;
+	host->msh = msh;
+	host->pdev = pdev;
+	platform_set_drvdata(pdev, host);
+	pcr->slots[RTSX_MS_CARD].p_dev = pdev;
+	pcr->slots[RTSX_MS_CARD].card_event = rtsx_pci_ms_card_event;
+
+	mutex_init(&host->host_mutex);
+
+	INIT_WORK(&host->handle_req, rtsx_pci_ms_handle_req);
+	msh->request = rtsx_pci_ms_request;
+	msh->set_param = rtsx_pci_ms_set_param;
+	msh->caps = MEMSTICK_CAP_PAR4;
+
+	rc = memstick_add_host(msh);
+	if (rc) {
+		memstick_free_host(msh);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int rtsx_pci_ms_drv_remove(struct platform_device *pdev)
+{
+	struct realtek_pci_ms *host = platform_get_drvdata(pdev);
+	struct rtsx_pcr *pcr;
+	struct memstick_host *msh;
+	int rc;
+
+	if (!host)
+		return 0;
+
+	pcr = host->pcr;
+	pcr->slots[RTSX_MS_CARD].p_dev = NULL;
+	pcr->slots[RTSX_MS_CARD].card_event = NULL;
+	msh = host->msh;
+	host->eject = true;
+
+	mutex_lock(&host->host_mutex);
+	if (host->req) {
+		dev_dbg(&(pdev->dev),
+			"%s: Controller removed during transfer\n",
+			dev_name(&msh->dev));
+
+		rtsx_pci_complete_unfinished_transfer(pcr);
+
+		host->req->error = -ENOMEDIUM;
+		do {
+			rc = memstick_next_req(msh, &host->req);
+			if (!rc)
+				host->req->error = -ENOMEDIUM;
+		} while (!rc);
+	}
+	mutex_unlock(&host->host_mutex);
+
+	memstick_remove_host(msh);
+	memstick_free_host(msh);
+
+	platform_set_drvdata(pdev, NULL);
+
+	dev_dbg(&(pdev->dev),
+		": Realtek PCI-E Memstick controller has been removed\n");
+
+	return 0;
+}
+
+static struct platform_device_id rtsx_pci_ms_ids[] = {
+	{
+		.name = DRV_NAME_RTSX_PCI_MS,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, rtsx_pci_ms_ids);
+
+static struct platform_driver rtsx_pci_ms_driver = {
+	.probe		= rtsx_pci_ms_drv_probe,
+	.remove		= rtsx_pci_ms_drv_remove,
+	.id_table       = rtsx_pci_ms_ids,
+	.suspend	= rtsx_pci_ms_suspend,
+	.resume		= rtsx_pci_ms_resume,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= DRV_NAME_RTSX_PCI_MS,
+	},
+};
+module_platform_driver(rtsx_pci_ms_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Wei WANG <wei_wang@realsil.com.cn>");
+MODULE_DESCRIPTION("Realtek PCI-E Memstick Card Host Driver");
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 0c3ced7..164afa7 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -792,6 +792,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 			 * than an unsolicited DID_ABORT.
 			 */
 			sc->result = DID_RESET << 16;
+			break;
 
 		case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:		/* 0x004C */
 			if (ioc->bus_type == FC)
diff --git a/drivers/message/i2o/README.ioctl b/drivers/message/i2o/README.ioctl
index 5fb195af4..4a7d2eb 100644
--- a/drivers/message/i2o/README.ioctl
+++ b/drivers/message/i2o/README.ioctl
@@ -138,7 +138,7 @@ VI. Setting Parameters
 
    The return value is the size in bytes of the data written into
    ops->resbuf if no errors occur.  If an error occurs, -1 is returned 
-   and errno is set appropriatly:
+   and errno is set appropriately:
 
       EFAULT      Invalid user space pointer was passed
       ENXIO       Invalid IOP number
@@ -222,7 +222,7 @@ VIII. Downloading Software
    RETURNS
 
    This function returns 0 no errors occur. If an error occurs, -1 
-   is returned and errno is set appropriatly:
+   is returned and errno is set appropriately:
 
       EFAULT      Invalid user space pointer was passed
       ENXIO       Invalid IOP number
@@ -264,7 +264,7 @@ IX. Uploading Software
    RETURNS
 
    This function returns 0 if no errors occur.  If an error occurs, -1
-   is returned and errno is set appropriatly:
+   is returned and errno is set appropriately:
 
       EFAULT      Invalid user space pointer was passed
       ENXIO       Invalid IOP number
@@ -301,7 +301,7 @@ X. Removing Software
    RETURNS
 
    This function returns 0 if no errors occur.  If an error occurs, -1
-   is returned and errno is set appropriatly:
+   is returned and errno is set appropriately:
 
       EFAULT      Invalid user space pointer was passed
       ENXIO       Invalid IOP number
@@ -325,7 +325,7 @@ X. Validating Configuration
    RETURNS
 
    This function returns 0 if no erro occur.  If an error occurs, -1 is
-   returned and errno is set appropriatly:
+   returned and errno is set appropriately:
 
       ETIMEDOUT   Timeout waiting for reply message
       ENXIO       Invalid IOP number
@@ -360,7 +360,7 @@ XI. Configuration Dialog
    RETURNS
 
    This function returns 0 if no error occur. If an error occurs, -1
-   is returned and errno is set appropriatly:
+   is returned and errno is set appropriately:
 
       EFAULT      Invalid user space pointer was passed
       ENXIO       Invalid IOP number
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index 4796bbf..49e86ae 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -609,7 +609,7 @@ static int i2o_block_release(struct gendisk *disk, fmode_t mode)
 	u8 operation;
 
 	/*
-	 * This is to deail with the case of an application
+	 * This is to deal with the case of an application
 	 * opening a device and then the device disappears while
 	 * it's in use, and then the application tries to release
 	 * it.  ex: Unmounting a deleted RAID volume at reboot.
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 9a49c24..5451bef 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -189,7 +189,7 @@ static int i2o_cfg_parms(unsigned long arg, unsigned int type)
 		return -ENXIO;
 
 	/*
-	 * Stop users being able to try and allocate arbitary amounts
+	 * Stop users being able to try and allocate arbitrary amounts
 	 * of DMA space. 64K is way more than sufficient for this.
 	 */
 	if (kcmd.oplen > 65536)
diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index ce229ea..391e23e 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -248,7 +248,7 @@ static const struct regmap_irq pm800_irqs[] = {
 	},
 };
 
-static int __devinit device_gpadc_init(struct pm80x_chip *chip,
+static int device_gpadc_init(struct pm80x_chip *chip,
 				       struct pm80x_platform_data *pdata)
 {
 	struct pm80x_subchip *subchip = chip->subchip;
@@ -315,7 +315,7 @@ out:
 	return ret;
 }
 
-static int __devinit device_irq_init_800(struct pm80x_chip *chip)
+static int device_irq_init_800(struct pm80x_chip *chip)
 {
 	struct regmap *map = chip->regmap;
 	unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
@@ -415,7 +415,7 @@ static void pm800_pages_exit(struct pm80x_chip *chip)
 	}
 }
 
-static int __devinit device_800_init(struct pm80x_chip *chip,
+static int device_800_init(struct pm80x_chip *chip,
 				     struct pm80x_platform_data *pdata)
 {
 	int ret, pmic_id;
@@ -499,7 +499,7 @@ out:
 	return ret;
 }
 
-static int __devinit pm800_probe(struct i2c_client *client,
+static int pm800_probe(struct i2c_client *client,
 				 const struct i2c_device_id *id)
 {
 	int ret = 0;
@@ -554,7 +554,7 @@ out_init:
 	return ret;
 }
 
-static int __devexit pm800_remove(struct i2c_client *client)
+static int pm800_remove(struct i2c_client *client)
 {
 	struct pm80x_chip *chip = i2c_get_clientdata(client);
 
@@ -576,7 +576,7 @@ static struct i2c_driver pm800_driver = {
 		.pm = &pm80x_pm_ops,
 		},
 	.probe = pm800_probe,
-	.remove = __devexit_p(pm800_remove),
+	.remove = pm800_remove,
 	.id_table = pm80x_id_table,
 };
 
diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
index c20a311..e671230 100644
--- a/drivers/mfd/88pm805.c
+++ b/drivers/mfd/88pm805.c
@@ -135,7 +135,7 @@ static struct regmap_irq pm805_irqs[] = {
 	},
 };
 
-static int __devinit device_irq_init_805(struct pm80x_chip *chip)
+static int device_irq_init_805(struct pm80x_chip *chip)
 {
 	struct regmap *map = chip->regmap;
 	unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
@@ -189,7 +189,7 @@ static struct regmap_irq_chip pm805_irq_chip = {
 	.ack_base = PM805_INT_STATUS1,
 };
 
-static int __devinit device_805_init(struct pm80x_chip *chip)
+static int device_805_init(struct pm80x_chip *chip)
 {
 	int ret = 0;
 	unsigned int val;
@@ -232,7 +232,7 @@ out_irq_init:
 	return ret;
 }
 
-static int __devinit pm805_probe(struct i2c_client *client,
+static int pm805_probe(struct i2c_client *client,
 				 const struct i2c_device_id *id)
 {
 	int ret = 0;
@@ -262,7 +262,7 @@ out_init:
 	return ret;
 }
 
-static int __devexit pm805_remove(struct i2c_client *client)
+static int pm805_remove(struct i2c_client *client)
 {
 	struct pm80x_chip *chip = i2c_get_clientdata(client);
 
@@ -281,7 +281,7 @@ static struct i2c_driver pm805_driver = {
 		.pm = &pm80x_pm_ops,
 		},
 	.probe = pm805_probe,
-	.remove = __devexit_p(pm805_remove),
+	.remove = pm805_remove,
 	.id_table = pm80x_id_table,
 };
 
diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c
index cd0bf52..1adb355 100644
--- a/drivers/mfd/88pm80x.c
+++ b/drivers/mfd/88pm80x.c
@@ -31,7 +31,7 @@ const struct regmap_config pm80x_regmap_config = {
 };
 EXPORT_SYMBOL_GPL(pm80x_regmap_config);
 
-int __devinit pm80x_init(struct i2c_client *client,
+int pm80x_init(struct i2c_client *client,
 				 const struct i2c_device_id *id)
 {
 	struct pm80x_chip *chip;
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index 8fa86ed..893fc1b 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -28,111 +28,111 @@
 
 #define INT_STATUS_NUM			3
 
-static struct resource bk0_resources[] __devinitdata = {
+static struct resource bk0_resources[] = {
 	{2, 2, "duty cycle", IORESOURCE_REG, },
 	{3, 3, "always on",  IORESOURCE_REG, },
 	{3, 3, "current",    IORESOURCE_REG, },
 };
-static struct resource bk1_resources[] __devinitdata = {
+static struct resource bk1_resources[] = {
 	{4, 4, "duty cycle", IORESOURCE_REG, },
 	{5, 5, "always on",  IORESOURCE_REG, },
 	{5, 5, "current",    IORESOURCE_REG, },
 };
-static struct resource bk2_resources[] __devinitdata = {
+static struct resource bk2_resources[] = {
 	{6, 6, "duty cycle", IORESOURCE_REG, },
 	{7, 7, "always on",  IORESOURCE_REG, },
 	{5, 5, "current",    IORESOURCE_REG, },
 };
 
-static struct resource led0_resources[] __devinitdata = {
+static struct resource led0_resources[] = {
 	/* RGB1 Red LED */
 	{0xd, 0xd, "control", IORESOURCE_REG, },
 	{0xc, 0xc, "blink",   IORESOURCE_REG, },
 };
-static struct resource led1_resources[] __devinitdata = {
+static struct resource led1_resources[] = {
 	/* RGB1 Green LED */
 	{0xe, 0xe, "control", IORESOURCE_REG, },
 	{0xc, 0xc, "blink",   IORESOURCE_REG, },
 };
-static struct resource led2_resources[] __devinitdata = {
+static struct resource led2_resources[] = {
 	/* RGB1 Blue LED */
 	{0xf, 0xf, "control", IORESOURCE_REG, },
 	{0xc, 0xc, "blink",   IORESOURCE_REG, },
 };
-static struct resource led3_resources[] __devinitdata = {
+static struct resource led3_resources[] = {
 	/* RGB2 Red LED */
 	{0x9, 0x9, "control", IORESOURCE_REG, },
 	{0x8, 0x8, "blink",   IORESOURCE_REG, },
 };
-static struct resource led4_resources[] __devinitdata = {
+static struct resource led4_resources[] = {
 	/* RGB2 Green LED */
 	{0xa, 0xa, "control", IORESOURCE_REG, },
 	{0x8, 0x8, "blink",   IORESOURCE_REG, },
 };
-static struct resource led5_resources[] __devinitdata = {
+static struct resource led5_resources[] = {
 	/* RGB2 Blue LED */
 	{0xb, 0xb, "control", IORESOURCE_REG, },
 	{0x8, 0x8, "blink",   IORESOURCE_REG, },
 };
 
-static struct resource buck1_resources[] __devinitdata = {
+static struct resource buck1_resources[] = {
 	{0x24, 0x24, "buck set", IORESOURCE_REG, },
 };
-static struct resource buck2_resources[] __devinitdata = {
+static struct resource buck2_resources[] = {
 	{0x25, 0x25, "buck set", IORESOURCE_REG, },
 };
-static struct resource buck3_resources[] __devinitdata = {
+static struct resource buck3_resources[] = {
 	{0x26, 0x26, "buck set", IORESOURCE_REG, },
 };
-static struct resource ldo1_resources[] __devinitdata = {
+static struct resource ldo1_resources[] = {
 	{0x10, 0x10, "ldo set", IORESOURCE_REG, },
 };
-static struct resource ldo2_resources[] __devinitdata = {
+static struct resource ldo2_resources[] = {
 	{0x11, 0x11, "ldo set", IORESOURCE_REG, },
 };
-static struct resource ldo3_resources[] __devinitdata = {
+static struct resource ldo3_resources[] = {
 	{0x12, 0x12, "ldo set", IORESOURCE_REG, },
 };
-static struct resource ldo4_resources[] __devinitdata = {
+static struct resource ldo4_resources[] = {
 	{0x13, 0x13, "ldo set", IORESOURCE_REG, },
 };
-static struct resource ldo5_resources[] __devinitdata = {
+static struct resource ldo5_resources[] = {
 	{0x14, 0x14, "ldo set", IORESOURCE_REG, },
 };
-static struct resource ldo6_resources[] __devinitdata = {
+static struct resource ldo6_resources[] = {
 	{0x15, 0x15, "ldo set", IORESOURCE_REG, },
 };
-static struct resource ldo7_resources[] __devinitdata = {
+static struct resource ldo7_resources[] = {
 	{0x16, 0x16, "ldo set", IORESOURCE_REG, },
 };
-static struct resource ldo8_resources[] __devinitdata = {
+static struct resource ldo8_resources[] = {
 	{0x17, 0x17, "ldo set", IORESOURCE_REG, },
 };
-static struct resource ldo9_resources[] __devinitdata = {
+static struct resource ldo9_resources[] = {
 	{0x18, 0x18, "ldo set", IORESOURCE_REG, },
 };
-static struct resource ldo10_resources[] __devinitdata = {
+static struct resource ldo10_resources[] = {
 	{0x19, 0x19, "ldo set", IORESOURCE_REG, },
 };
-static struct resource ldo12_resources[] __devinitdata = {
+static struct resource ldo12_resources[] = {
 	{0x1a, 0x1a, "ldo set", IORESOURCE_REG, },
 };
-static struct resource ldo_vibrator_resources[] __devinitdata = {
+static struct resource ldo_vibrator_resources[] = {
 	{0x28, 0x28, "ldo set", IORESOURCE_REG, },
 };
-static struct resource ldo14_resources[] __devinitdata = {
+static struct resource ldo14_resources[] = {
 	{0x1b, 0x1b, "ldo set", IORESOURCE_REG, },
 };
 
-static struct resource touch_resources[] __devinitdata = {
+static struct resource touch_resources[] = {
 	{PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,},
 };
 
-static struct resource onkey_resources[] __devinitdata = {
+static struct resource onkey_resources[] = {
 	{PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,},
 };
 
-static struct resource codec_resources[] __devinitdata = {
+static struct resource codec_resources[] = {
 	/* Headset microphone insertion or removal */
 	{PM8607_IRQ_MICIN,   PM8607_IRQ_MICIN,   "micin",   IORESOURCE_IRQ,},
 	/* Hook-switch press or release */
@@ -143,12 +143,12 @@ static struct resource codec_resources[] __devinitdata = {
 	{PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,},
 };
 
-static struct resource battery_resources[] __devinitdata = {
+static struct resource battery_resources[] = {
 	{PM8607_IRQ_CC,  PM8607_IRQ_CC,  "columb counter", IORESOURCE_IRQ,},
 	{PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery",        IORESOURCE_IRQ,},
 };
 
-static struct resource charger_resources[] __devinitdata = {
+static struct resource charger_resources[] = {
 	{PM8607_IRQ_CHG,  PM8607_IRQ_CHG,  "charger detect",  IORESOURCE_IRQ,},
 	{PM8607_IRQ_CHG_DONE,  PM8607_IRQ_CHG_DONE,  "charging done",       IORESOURCE_IRQ,},
 	{PM8607_IRQ_CHG_FAIL,  PM8607_IRQ_CHG_FAIL,  "charging timeout",    IORESOURCE_IRQ,},
@@ -158,11 +158,11 @@ static struct resource charger_resources[] __devinitdata = {
 	{PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage",    IORESOURCE_IRQ,},
 };
 
-static struct resource rtc_resources[] __devinitdata = {
+static struct resource rtc_resources[] = {
 	{PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,},
 };
 
-static struct mfd_cell bk_devs[] __devinitdata = {
+static struct mfd_cell bk_devs[] = {
 	{
 		.name = "88pm860x-backlight",
 		.id = 0,
@@ -181,7 +181,7 @@ static struct mfd_cell bk_devs[] __devinitdata = {
 	},
 };
 
-static struct mfd_cell led_devs[] __devinitdata = {
+static struct mfd_cell led_devs[] = {
 	{
 		.name = "88pm860x-led",
 		.id = 0,
@@ -215,7 +215,7 @@ static struct mfd_cell led_devs[] __devinitdata = {
 	},
 };
 
-static struct mfd_cell reg_devs[] __devinitdata = {
+static struct mfd_cell reg_devs[] = {
 	{
 		.name = "88pm860x-regulator",
 		.id = 0,
@@ -565,7 +565,7 @@ static struct irq_domain_ops pm860x_irq_domain_ops = {
 	.xlate	= irq_domain_xlate_onetwocell,
 };
 
-static int __devinit device_irq_init(struct pm860x_chip *chip,
+static int device_irq_init(struct pm860x_chip *chip,
 				     struct pm860x_platform_data *pdata)
 {
 	struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
@@ -730,7 +730,7 @@ out:
 }
 EXPORT_SYMBOL(pm8606_osc_disable);
 
-static void __devinit device_osc_init(struct i2c_client *i2c)
+static void device_osc_init(struct i2c_client *i2c)
 {
 	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
 
@@ -745,7 +745,7 @@ static void __devinit device_osc_init(struct i2c_client *i2c)
 	chip->osc_status = PM8606_REF_GP_OSC_OFF;
 }
 
-static void __devinit device_bk_init(struct pm860x_chip *chip,
+static void device_bk_init(struct pm860x_chip *chip,
 				     struct pm860x_platform_data *pdata)
 {
 	int ret, i;
@@ -765,7 +765,7 @@ static void __devinit device_bk_init(struct pm860x_chip *chip,
 		dev_err(chip->dev, "Failed to add backlight subdev\n");
 }
 
-static void __devinit device_led_init(struct pm860x_chip *chip,
+static void device_led_init(struct pm860x_chip *chip,
 				      struct pm860x_platform_data *pdata)
 {
 	int ret, i;
@@ -787,7 +787,7 @@ static void __devinit device_led_init(struct pm860x_chip *chip,
 	}
 }
 
-static void __devinit device_regulator_init(struct pm860x_chip *chip,
+static void device_regulator_init(struct pm860x_chip *chip,
 					    struct pm860x_platform_data *pdata)
 {
 	int ret;
@@ -866,7 +866,7 @@ static void __devinit device_regulator_init(struct pm860x_chip *chip,
 	}
 }
 
-static void __devinit device_rtc_init(struct pm860x_chip *chip,
+static void device_rtc_init(struct pm860x_chip *chip,
 				      struct pm860x_platform_data *pdata)
 {
 	int ret;
@@ -885,7 +885,7 @@ static void __devinit device_rtc_init(struct pm860x_chip *chip,
 		dev_err(chip->dev, "Failed to add rtc subdev\n");
 }
 
-static void __devinit device_touch_init(struct pm860x_chip *chip,
+static void device_touch_init(struct pm860x_chip *chip,
 					struct pm860x_platform_data *pdata)
 {
 	int ret;
@@ -904,7 +904,7 @@ static void __devinit device_touch_init(struct pm860x_chip *chip,
 		dev_err(chip->dev, "Failed to add touch subdev\n");
 }
 
-static void __devinit device_power_init(struct pm860x_chip *chip,
+static void device_power_init(struct pm860x_chip *chip,
 					struct pm860x_platform_data *pdata)
 {
 	int ret;
@@ -951,7 +951,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip,
 	}
 }
 
-static void __devinit device_onkey_init(struct pm860x_chip *chip,
+static void device_onkey_init(struct pm860x_chip *chip,
 					struct pm860x_platform_data *pdata)
 {
 	int ret;
@@ -965,7 +965,7 @@ static void __devinit device_onkey_init(struct pm860x_chip *chip,
 		dev_err(chip->dev, "Failed to add onkey subdev\n");
 }
 
-static void __devinit device_codec_init(struct pm860x_chip *chip,
+static void device_codec_init(struct pm860x_chip *chip,
 					struct pm860x_platform_data *pdata)
 {
 	int ret;
@@ -979,7 +979,7 @@ static void __devinit device_codec_init(struct pm860x_chip *chip,
 		dev_err(chip->dev, "Failed to add codec subdev\n");
 }
 
-static void __devinit device_8607_init(struct pm860x_chip *chip,
+static void device_8607_init(struct pm860x_chip *chip,
 				       struct i2c_client *i2c,
 				       struct pm860x_platform_data *pdata)
 {
@@ -1040,7 +1040,7 @@ out:
 	return;
 }
 
-static void __devinit device_8606_init(struct pm860x_chip *chip,
+static void device_8606_init(struct pm860x_chip *chip,
 				       struct i2c_client *i2c,
 				       struct pm860x_platform_data *pdata)
 {
@@ -1049,7 +1049,7 @@ static void __devinit device_8606_init(struct pm860x_chip *chip,
 	device_led_init(chip, pdata);
 }
 
-static int __devinit pm860x_device_init(struct pm860x_chip *chip,
+static int pm860x_device_init(struct pm860x_chip *chip,
 					struct pm860x_platform_data *pdata)
 {
 	chip->core_irq = 0;
@@ -1077,7 +1077,7 @@ static int __devinit pm860x_device_init(struct pm860x_chip *chip,
 	return 0;
 }
 
-static void __devexit pm860x_device_exit(struct pm860x_chip *chip)
+static void pm860x_device_exit(struct pm860x_chip *chip)
 {
 	device_irq_exit(chip);
 	mfd_remove_devices(chip->dev);
@@ -1109,7 +1109,7 @@ static struct regmap_config pm860x_regmap_config = {
 	.val_bits = 8,
 };
 
-static int __devinit pm860x_dt_init(struct device_node *np,
+static int pm860x_dt_init(struct device_node *np,
 				    struct device *dev,
 				    struct pm860x_platform_data *pdata)
 {
@@ -1127,7 +1127,7 @@ static int __devinit pm860x_dt_init(struct device_node *np,
 	return 0;
 }
 
-static int __devinit pm860x_probe(struct i2c_client *client,
+static int pm860x_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
 	struct pm860x_platform_data *pdata = client->dev.platform_data;
@@ -1200,7 +1200,7 @@ err:
 	return ret;
 }
 
-static int __devexit pm860x_remove(struct i2c_client *client)
+static int pm860x_remove(struct i2c_client *client)
 {
 	struct pm860x_chip *chip = i2c_get_clientdata(client);
 
@@ -1258,7 +1258,7 @@ static struct i2c_driver pm860x_driver = {
 		.of_match_table	= of_match_ptr(pm860x_dt_ids),
 	},
 	.probe		= pm860x_probe,
-	.remove		= __devexit_p(pm860x_remove),
+	.remove		= pm860x_remove,
 	.id_table	= pm860x_id_table,
 };
 
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index acab3ef..09d43a9 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -63,6 +63,16 @@ config MFD_SM501_GPIO
 	 lines on the SM501. The platform data is used to supply the
 	 base number for the first GPIO line to register.
 
+config MFD_RTSX_PCI
+	tristate "Support for Realtek PCI-E card reader"
+	depends on PCI
+	select MFD_CORE
+	help
+	  This supports for Realtek PCI-Express card reader including rts5209,
+	  rts5229, rtl8411, etc. Realtek card reader supports access to many
+	  types of memory cards, such as Memory Stick, Memory Stick Pro,
+	  Secure Digital and MultiMediaCard.
+
 config MFD_ASIC3
 	bool "Support for Compaq ASIC3"
 	depends on GENERIC_HARDIRQS && GPIOLIB && ARM
@@ -94,6 +104,17 @@ config MFD_TI_SSP
 	  To compile this driver as a module, choose M here: the
 	  module will be called ti-ssp.
 
+config MFD_TI_AM335X_TSCADC
+	tristate "TI ADC / Touch Screen chip support"
+	select MFD_CORE
+	select REGMAP
+	select REGMAP_MMIO
+	help
+	  If you say yes here you get support for Texas Instruments series
+	  of Touch Screen /ADC chips.
+	  To compile this driver as a module, choose M here: the
+	  module will be called ti_am335x_tscadc.
+
 config HTC_EGPIO
 	bool "HTC EGPIO support"
 	depends on GENERIC_HARDIRQS && GPIOLIB && ARM
@@ -201,7 +222,6 @@ config MFD_TPS6586X
 	depends on I2C=y && GENERIC_HARDIRQS
 	select MFD_CORE
 	select REGMAP_I2C
-	depends on REGULATOR
 	help
 	  If you say yes here you get support for the TPS6586X series of
 	  Power Management chips.
@@ -244,6 +264,20 @@ config MFD_TPS65912_SPI
 	  If you say yes here you get support for the TPS65912 series of
 	  PM chips with SPI interface.
 
+config MFD_TPS80031
+	bool "TI TPS80031/TPS80032 Power Management chips"
+	depends on I2C=y && GENERIC_HARDIRQS
+	select MFD_CORE
+	select REGMAP_I2C
+	select IRQ_DOMAIN
+	help
+	  If you say yes here you get support for the Texas Instruments
+	  TPS80031/ TPS80032 Fully Integrated Power Management with Power
+	  Path and Battery Charger. The device provides five configurable
+	  step-down converters, 11 general purpose LDOs, USB OTG Module,
+	  ADC, RTC, 2 PWM, System Voltage Regulator/Battery Charger with
+	  Power Path from USB, 32K clock generator.
+
 config MENELAUS
 	bool "Texas Instruments TWL92330/Menelaus PM chip"
 	depends on I2C=y && ARCH_OMAP2
@@ -300,10 +334,10 @@ config MFD_TWL4030_AUDIO
 
 config TWL6040_CORE
 	bool "Support for TWL6040 audio codec"
-	depends on I2C=y && GENERIC_HARDIRQS
+	depends on I2C=y
 	select MFD_CORE
 	select REGMAP_I2C
-	select IRQ_DOMAIN
+	select REGMAP_IRQ
 	default n
 	help
 	  Say yes here if you want support for Texas Instruments TWL6040 audio
@@ -981,6 +1015,7 @@ config MFD_TPS65090
 	depends on I2C=y && GENERIC_HARDIRQS
 	select MFD_CORE
 	select REGMAP_I2C
+	select REGMAP_IRQ
 	help
 	  If you say yes here you get support for the TPS65090 series of
 	  Power Management chips.
@@ -1025,6 +1060,7 @@ config MFD_STA2X11
 	bool "STA2X11 multi function device support"
 	depends on STA2X11
 	select MFD_CORE
+	select REGMAP_MMIO
 
 config MFD_SYSCON
 	bool "System Controller Register R/W Based on Regmap"
@@ -1044,6 +1080,38 @@ config MFD_PALMAS
 	  If you say yes here you get support for the Palmas
 	  series of PMIC chips from Texas Instruments.
 
+config MFD_VIPERBOARD
+        tristate "Support for Nano River Technologies Viperboard"
+	select MFD_CORE
+	depends on USB
+	default n
+	help
+	  Say yes here if you want support for Nano River Technologies
+	  Viperboard.
+	  There are mfd cell drivers available for i2c master, adc and
+	  both gpios found on the board. The spi part does not yet
+	  have a driver.
+	  You need to select the mfd cell drivers separately.
+	  The drivers do not support all features the board exposes.
+
+config MFD_RETU
+	tristate "Support for Retu multi-function device"
+	select MFD_CORE
+	depends on I2C
+	select REGMAP_IRQ
+	help
+	  Retu is a multi-function device found on Nokia Internet Tablets
+	  (770, N800 and N810).
+
+config MFD_AS3711
+	bool "Support for AS3711"
+	select MFD_CORE
+	select REGMAP_I2C
+	select REGMAP_IRQ
+	depends on I2C=y
+	help
+	  Support for the AS3711 PMIC from AMS
+
 endmenu
 endif
 
@@ -1070,3 +1138,9 @@ config MCP_UCB1200_TS
 	depends on MCP_UCB1200 && INPUT
 
 endmenu
+
+config VEXPRESS_CONFIG
+	bool
+	help
+	  Platform configuration infrastructure for the ARM Ltd.
+	  Versatile Express.
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index d8ccb63..baab62e 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -9,6 +9,9 @@ obj-$(CONFIG_MFD_88PM805)	+= 88pm805.o 88pm80x.o
 obj-$(CONFIG_MFD_SM501)		+= sm501.o
 obj-$(CONFIG_MFD_ASIC3)		+= asic3.o tmio_core.o
 
+rtsx_pci-objs			:= rtsx_pcr.o rts5209.o rts5229.o rtl8411.o
+obj-$(CONFIG_MFD_RTSX_PCI)	+= rtsx_pci.o
+
 obj-$(CONFIG_HTC_EGPIO)		+= htc-egpio.o
 obj-$(CONFIG_HTC_PASIC3)	+= htc-pasic3.o
 obj-$(CONFIG_HTC_I2CPLD)	+= htc-i2cpld.o
@@ -16,6 +19,7 @@ obj-$(CONFIG_HTC_I2CPLD)	+= htc-i2cpld.o
 obj-$(CONFIG_MFD_DAVINCI_VOICECODEC)	+= davinci_voicecodec.o
 obj-$(CONFIG_MFD_DM355EVM_MSP)	+= dm355evm_msp.o
 obj-$(CONFIG_MFD_TI_SSP)	+= ti-ssp.o
+obj-$(CONFIG_MFD_TI_AM335X_TSCADC)	+= ti_am335x_tscadc.o
 
 obj-$(CONFIG_MFD_STA2X11)	+= sta2x11-mfd.o
 obj-$(CONFIG_MFD_STMPE)		+= stmpe.o
@@ -52,18 +56,19 @@ obj-$(CONFIG_TPS6105X)		+= tps6105x.o
 obj-$(CONFIG_TPS65010)		+= tps65010.o
 obj-$(CONFIG_TPS6507X)		+= tps6507x.o
 obj-$(CONFIG_MFD_TPS65217)	+= tps65217.o
-obj-$(CONFIG_MFD_TPS65910)	+= tps65910.o tps65910-irq.o
+obj-$(CONFIG_MFD_TPS65910)	+= tps65910.o
 tps65912-objs                   := tps65912-core.o tps65912-irq.o
 obj-$(CONFIG_MFD_TPS65912)	+= tps65912.o
 obj-$(CONFIG_MFD_TPS65912_I2C)	+= tps65912-i2c.o
 obj-$(CONFIG_MFD_TPS65912_SPI)  += tps65912-spi.o
+obj-$(CONFIG_MFD_TPS80031)	+= tps80031.o
 obj-$(CONFIG_MENELAUS)		+= menelaus.o
 
 obj-$(CONFIG_TWL4030_CORE)	+= twl-core.o twl4030-irq.o twl6030-irq.o
 obj-$(CONFIG_TWL4030_MADC)      += twl4030-madc.o
 obj-$(CONFIG_TWL4030_POWER)    += twl4030-power.o
 obj-$(CONFIG_MFD_TWL4030_AUDIO)	+= twl4030-audio.o
-obj-$(CONFIG_TWL6040_CORE)	+= twl6040-core.o twl6040-irq.o
+obj-$(CONFIG_TWL6040_CORE)	+= twl6040.o
 
 obj-$(CONFIG_MFD_MC13XXX)	+= mc13xxx-core.o
 obj-$(CONFIG_MFD_MC13XXX_SPI)	+= mc13xxx-spi.o
@@ -86,6 +91,7 @@ obj-$(CONFIG_UCB1400_CORE)	+= ucb1400_core.o
 
 obj-$(CONFIG_PMIC_DA903X)	+= da903x.o
 
+obj-$(CONFIG_PMIC_DA9052)	+= da9052-irq.o
 obj-$(CONFIG_PMIC_DA9052)	+= da9052-core.o
 obj-$(CONFIG_MFD_DA9052_SPI)	+= da9052-spi.o
 obj-$(CONFIG_MFD_DA9052_I2C)	+= da9052-i2c.o
@@ -134,7 +140,11 @@ obj-$(CONFIG_MFD_TPS65090)	+= tps65090.o
 obj-$(CONFIG_MFD_AAT2870_CORE)	+= aat2870-core.o
 obj-$(CONFIG_MFD_INTEL_MSIC)	+= intel_msic.o
 obj-$(CONFIG_MFD_PALMAS)	+= palmas.o
+obj-$(CONFIG_MFD_VIPERBOARD)    += viperboard.o
 obj-$(CONFIG_MFD_RC5T583)	+= rc5t583.o rc5t583-irq.o
 obj-$(CONFIG_MFD_SEC_CORE)	+= sec-core.o sec-irq.o
 obj-$(CONFIG_MFD_SYSCON)	+= syscon.o
 obj-$(CONFIG_MFD_LM3533)	+= lm3533-core.o lm3533-ctrlbank.o
+obj-$(CONFIG_MFD_RETU)		+= retu-mfd.o
+obj-$(CONFIG_MFD_AS3711)	+= as3711.o
+obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-config.o vexpress-sysreg.o
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index 2b3dde5..2ec7725 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -661,8 +661,7 @@ struct ab3100_init_setting {
 	u8 setting;
 };
 
-static const struct ab3100_init_setting __devinitconst
-ab3100_init_settings[] = {
+static const struct ab3100_init_setting ab3100_init_settings[] = {
 	{
 		.abreg = AB3100_MCA,
 		.setting = 0x01
@@ -708,7 +707,7 @@ ab3100_init_settings[] = {
 	},
 };
 
-static int __devinit ab3100_setup(struct ab3100 *ab3100)
+static int ab3100_setup(struct ab3100 *ab3100)
 {
 	int err = 0;
 	int i;
@@ -803,7 +802,7 @@ struct ab_family_id {
 	char	*name;
 };
 
-static const struct ab_family_id ids[] __devinitconst = {
+static const struct ab_family_id ids[] = {
 	/* AB3100 */
 	{
 		.id = 0xc0,
@@ -857,7 +856,7 @@ static const struct ab_family_id ids[] __devinitconst = {
 	},
 };
 
-static int __devinit ab3100_probe(struct i2c_client *client,
+static int ab3100_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
 	struct ab3100 *ab3100;
@@ -962,7 +961,7 @@ static int __devinit ab3100_probe(struct i2c_client *client,
 	return err;
 }
 
-static int __devexit ab3100_remove(struct i2c_client *client)
+static int ab3100_remove(struct i2c_client *client)
 {
 	struct ab3100 *ab3100 = i2c_get_clientdata(client);
 
@@ -986,7 +985,7 @@ static struct i2c_driver ab3100_driver = {
 	},
 	.id_table	= ab3100_id,
 	.probe		= ab3100_probe,
-	.remove		= __devexit_p(ab3100_remove),
+	.remove		= ab3100_remove,
 };
 
 static int __init ab3100_i2c_init(void)
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index 1667c77..80ce4a6 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -565,15 +565,10 @@ static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
 	else
 		num_irqs = AB8500_NR_IRQS;
 
-	if (ab8500->irq_base) {
-		ab8500->domain = irq_domain_add_legacy(
-			NULL, num_irqs, ab8500->irq_base,
-			0, &ab8500_irq_ops, ab8500);
-	}
-	else {
-		ab8500->domain = irq_domain_add_linear(
-			np, num_irqs, &ab8500_irq_ops, ab8500);
-	}
+	/* If ->irq_base is zero this will give a linear mapping */
+	ab8500->domain = irq_domain_add_simple(NULL,
+			num_irqs, ab8500->irq_base,
+			&ab8500_irq_ops, ab8500);
 
 	if (!ab8500->domain) {
 		dev_err(ab8500->dev, "Failed to create irqdomain\n");
@@ -591,39 +586,7 @@ int ab8500_suspend(struct ab8500 *ab8500)
 		return 0;
 }
 
-/* AB8500 GPIO Resources */
-static struct resource __devinitdata ab8500_gpio_resources[] = {
-	{
-		.name	= "GPIO_INT6",
-		.start	= AB8500_INT_GPIO6R,
-		.end	= AB8500_INT_GPIO41F,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-/* AB9540 GPIO Resources */
-static struct resource __devinitdata ab9540_gpio_resources[] = {
-	{
-		.name	= "GPIO_INT6",
-		.start	= AB8500_INT_GPIO6R,
-		.end	= AB8500_INT_GPIO41F,
-		.flags	= IORESOURCE_IRQ,
-	},
-	{
-		.name	= "GPIO_INT14",
-		.start	= AB9540_INT_GPIO50R,
-		.end	= AB9540_INT_GPIO54R,
-		.flags	= IORESOURCE_IRQ,
-	},
-	{
-		.name	= "GPIO_INT15",
-		.start	= AB9540_INT_GPIO50F,
-		.end	= AB9540_INT_GPIO54F,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static struct resource __devinitdata ab8500_gpadc_resources[] = {
+static struct resource ab8500_gpadc_resources[] = {
 	{
 		.name	= "HW_CONV_END",
 		.start	= AB8500_INT_GP_HW_ADC_CONV_END,
@@ -638,7 +601,7 @@ static struct resource __devinitdata ab8500_gpadc_resources[] = {
 	},
 };
 
-static struct resource __devinitdata ab8500_rtc_resources[] = {
+static struct resource ab8500_rtc_resources[] = {
 	{
 		.name	= "60S",
 		.start	= AB8500_INT_RTC_60S,
@@ -653,7 +616,7 @@ static struct resource __devinitdata ab8500_rtc_resources[] = {
 	},
 };
 
-static struct resource __devinitdata ab8500_poweronkey_db_resources[] = {
+static struct resource ab8500_poweronkey_db_resources[] = {
 	{
 		.name	= "ONKEY_DBF",
 		.start	= AB8500_INT_PON_KEY1DB_F,
@@ -668,7 +631,7 @@ static struct resource __devinitdata ab8500_poweronkey_db_resources[] = {
 	},
 };
 
-static struct resource __devinitdata ab8500_av_acc_detect_resources[] = {
+static struct resource ab8500_av_acc_detect_resources[] = {
 	{
 	       .name = "ACC_DETECT_1DB_F",
 	       .start = AB8500_INT_ACC_DETECT_1DB_F,
@@ -707,7 +670,7 @@ static struct resource __devinitdata ab8500_av_acc_detect_resources[] = {
 	},
 };
 
-static struct resource __devinitdata ab8500_charger_resources[] = {
+static struct resource ab8500_charger_resources[] = {
 	{
 		.name = "MAIN_CH_UNPLUG_DET",
 		.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
@@ -788,7 +751,7 @@ static struct resource __devinitdata ab8500_charger_resources[] = {
 	},
 };
 
-static struct resource __devinitdata ab8500_btemp_resources[] = {
+static struct resource ab8500_btemp_resources[] = {
 	{
 		.name = "BAT_CTRL_INDB",
 		.start = AB8500_INT_BAT_CTRL_INDB,
@@ -821,7 +784,7 @@ static struct resource __devinitdata ab8500_btemp_resources[] = {
 	},
 };
 
-static struct resource __devinitdata ab8500_fg_resources[] = {
+static struct resource ab8500_fg_resources[] = {
 	{
 		.name = "NCONV_ACCU",
 		.start = AB8500_INT_CCN_CONV_ACC,
@@ -860,10 +823,10 @@ static struct resource __devinitdata ab8500_fg_resources[] = {
 	},
 };
 
-static struct resource __devinitdata ab8500_chargalg_resources[] = {};
+static struct resource ab8500_chargalg_resources[] = {};
 
 #ifdef CONFIG_DEBUG_FS
-static struct resource __devinitdata ab8500_debug_resources[] = {
+static struct resource ab8500_debug_resources[] = {
 	{
 		.name	= "IRQ_FIRST",
 		.start	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
@@ -879,7 +842,7 @@ static struct resource __devinitdata ab8500_debug_resources[] = {
 };
 #endif
 
-static struct resource __devinitdata ab8500_usb_resources[] = {
+static struct resource ab8500_usb_resources[] = {
 	{
 		.name = "ID_WAKEUP_R",
 		.start = AB8500_INT_ID_WAKEUP_R,
@@ -924,7 +887,7 @@ static struct resource __devinitdata ab8500_usb_resources[] = {
 	},
 };
 
-static struct resource __devinitdata ab8505_iddet_resources[] = {
+static struct resource ab8505_iddet_resources[] = {
 	{
 		.name  = "KeyDeglitch",
 		.start = AB8505_INT_KEYDEGLITCH,
@@ -957,7 +920,7 @@ static struct resource __devinitdata ab8505_iddet_resources[] = {
 	},
 };
 
-static struct resource __devinitdata ab8500_temp_resources[] = {
+static struct resource ab8500_temp_resources[] = {
 	{
 		.name  = "AB8500_TEMP_WARM",
 		.start = AB8500_INT_TEMP_WARM,
@@ -966,7 +929,7 @@ static struct resource __devinitdata ab8500_temp_resources[] = {
 	},
 };
 
-static struct mfd_cell __devinitdata abx500_common_devs[] = {
+static struct mfd_cell abx500_common_devs[] = {
 #ifdef CONFIG_DEBUG_FS
 	{
 		.name = "ab8500-debug",
@@ -984,6 +947,10 @@ static struct mfd_cell __devinitdata abx500_common_devs[] = {
 		.of_compatible = "stericsson,ab8500-regulator",
 	},
 	{
+		.name = "abx500-clk",
+		.of_compatible = "stericsson,abx500-clk",
+	},
+	{
 		.name = "ab8500-gpadc",
 		.of_compatible = "stericsson,ab8500-gpadc",
 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
@@ -1038,35 +1005,53 @@ static struct mfd_cell __devinitdata abx500_common_devs[] = {
 	},
 };
 
-static struct mfd_cell __devinitdata ab8500_bm_devs[] = {
+static struct mfd_cell ab8500_bm_devs[] = {
 	{
 		.name = "ab8500-charger",
+		.of_compatible = "stericsson,ab8500-charger",
 		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
 		.resources = ab8500_charger_resources,
+#ifndef CONFIG_OF
+		.platform_data = &ab8500_bm_data,
+		.pdata_size = sizeof(ab8500_bm_data),
+#endif
 	},
 	{
 		.name = "ab8500-btemp",
+		.of_compatible = "stericsson,ab8500-btemp",
 		.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
 		.resources = ab8500_btemp_resources,
+#ifndef CONFIG_OF
+		.platform_data = &ab8500_bm_data,
+		.pdata_size = sizeof(ab8500_bm_data),
+#endif
 	},
 	{
 		.name = "ab8500-fg",
+		.of_compatible = "stericsson,ab8500-fg",
 		.num_resources = ARRAY_SIZE(ab8500_fg_resources),
 		.resources = ab8500_fg_resources,
+#ifndef CONFIG_OF
+		.platform_data = &ab8500_bm_data,
+		.pdata_size = sizeof(ab8500_bm_data),
+#endif
 	},
 	{
 		.name = "ab8500-chargalg",
+		.of_compatible = "stericsson,ab8500-chargalg",
 		.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
 		.resources = ab8500_chargalg_resources,
+#ifndef CONFIG_OF
+		.platform_data = &ab8500_bm_data,
+		.pdata_size = sizeof(ab8500_bm_data),
+#endif
 	},
 };
 
-static struct mfd_cell __devinitdata ab8500_devs[] = {
+static struct mfd_cell ab8500_devs[] = {
 	{
 		.name = "ab8500-gpio",
 		.of_compatible = "stericsson,ab8500-gpio",
-		.num_resources = ARRAY_SIZE(ab8500_gpio_resources),
-		.resources = ab8500_gpio_resources,
 	},
 	{
 		.name = "ab8500-usb",
@@ -1080,11 +1065,9 @@ static struct mfd_cell __devinitdata ab8500_devs[] = {
 	},
 };
 
-static struct mfd_cell __devinitdata ab9540_devs[] = {
+static struct mfd_cell ab9540_devs[] = {
 	{
 		.name = "ab8500-gpio",
-		.num_resources = ARRAY_SIZE(ab9540_gpio_resources),
-		.resources = ab9540_gpio_resources,
 	},
 	{
 		.name = "ab9540-usb",
@@ -1097,7 +1080,7 @@ static struct mfd_cell __devinitdata ab9540_devs[] = {
 };
 
 /* Device list common to ab9540 and ab8505 */
-static struct mfd_cell __devinitdata ab9540_ab8505_devs[] = {
+static struct mfd_cell ab9540_ab8505_devs[] = {
 	{
 		.name = "ab-iddet",
 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
@@ -1248,7 +1231,7 @@ static struct attribute_group ab9540_attr_group = {
 	.attrs	= ab9540_sysfs_entries,
 };
 
-static int __devinit ab8500_probe(struct platform_device *pdev)
+static int ab8500_probe(struct platform_device *pdev)
 {
 	static char *switch_off_status[] = {
 		"Swoff bit programming",
@@ -1269,7 +1252,7 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
 	int i;
 	u8 value;
 
-	ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL);
+	ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
 	if (!ab8500)
 		return -ENOMEM;
 
@@ -1279,10 +1262,8 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
 	ab8500->dev = &pdev->dev;
 
 	resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!resource) {
-		ret = -ENODEV;
-		goto out_free_ab8500;
-	}
+	if (!resource)
+		return -ENODEV;
 
 	ab8500->irq = resource->start;
 
@@ -1305,7 +1286,7 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
 		ret = get_register_interruptible(ab8500, AB8500_MISC,
 			AB8500_IC_NAME_REG, &value);
 		if (ret < 0)
-			goto out_free_ab8500;
+			return ret;
 
 		ab8500->version = value;
 	}
@@ -1313,7 +1294,7 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
 	ret = get_register_interruptible(ab8500, AB8500_MISC,
 		AB8500_REV_REG, &value);
 	if (ret < 0)
-		goto out_free_ab8500;
+		return ret;
 
 	ab8500->chip_id = value;
 
@@ -1330,14 +1311,13 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
 		ab8500->mask_size = AB8500_NUM_IRQ_REGS;
 		ab8500->irq_reg_offset = ab8500_irq_regoffset;
 	}
-	ab8500->mask = kzalloc(ab8500->mask_size, GFP_KERNEL);
+	ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
 	if (!ab8500->mask)
 		return -ENOMEM;
-	ab8500->oldmask = kzalloc(ab8500->mask_size, GFP_KERNEL);
-	if (!ab8500->oldmask) {
-		ret = -ENOMEM;
-		goto out_freemask;
-	}
+	ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
+	if (!ab8500->oldmask)
+		return -ENOMEM;
+
 	/*
 	 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
 	 * 0x01 Swoff bit programming
@@ -1391,37 +1371,37 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
 
 	ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
 	if (ret)
-		goto out_freeoldmask;
+		return ret;
 
 	for (i = 0; i < ab8500->mask_size; i++)
 		ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
 
 	ret = ab8500_irq_init(ab8500, np);
 	if (ret)
-		goto out_freeoldmask;
+		return ret;
 
 	/*  Activate this feature only in ab9540 */
 	/*  till tests are done on ab8500 1p2 or later*/
 	if (is_ab9540(ab8500)) {
-		ret = request_threaded_irq(ab8500->irq, NULL,
-					ab8500_hierarchical_irq,
-					IRQF_ONESHOT | IRQF_NO_SUSPEND,
-					"ab8500", ab8500);
+		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
+						ab8500_hierarchical_irq,
+						IRQF_ONESHOT | IRQF_NO_SUSPEND,
+						"ab8500", ab8500);
 	}
 	else {
-		ret = request_threaded_irq(ab8500->irq, NULL,
-					ab8500_irq,
-					IRQF_ONESHOT | IRQF_NO_SUSPEND,
-					"ab8500", ab8500);
+		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
+						ab8500_irq,
+						IRQF_ONESHOT | IRQF_NO_SUSPEND,
+						"ab8500", ab8500);
 		if (ret)
-			goto out_freeoldmask;
+			return ret;
 	}
 
 	ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
 			ARRAY_SIZE(abx500_common_devs), NULL,
 			ab8500->irq_base, ab8500->domain);
 	if (ret)
-		goto out_freeirq;
+		return ret;
 
 	if (is_ab9540(ab8500))
 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
@@ -1432,14 +1412,14 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
 				ARRAY_SIZE(ab8500_devs), NULL,
 				ab8500->irq_base, ab8500->domain);
 	if (ret)
-		goto out_freeirq;
+		return ret;
 
 	if (is_ab9540(ab8500) || is_ab8505(ab8500))
 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs,
 				ARRAY_SIZE(ab9540_ab8505_devs), NULL,
 				ab8500->irq_base, ab8500->domain);
 	if (ret)
-		goto out_freeirq;
+		return ret;
 
 	if (!no_bm) {
 		/* Add battery management devices */
@@ -1460,20 +1440,9 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
 		dev_err(ab8500->dev, "error creating sysfs entries\n");
 
 	return ret;
-
-out_freeirq:
-	free_irq(ab8500->irq, ab8500);
-out_freeoldmask:
-	kfree(ab8500->oldmask);
-out_freemask:
-	kfree(ab8500->mask);
-out_free_ab8500:
-	kfree(ab8500);
-
-	return ret;
 }
 
-static int __devexit ab8500_remove(struct platform_device *pdev)
+static int ab8500_remove(struct platform_device *pdev)
 {
 	struct ab8500 *ab8500 = platform_get_drvdata(pdev);
 
@@ -1506,7 +1475,7 @@ static struct platform_driver ab8500_core_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe	= ab8500_probe,
-	.remove	= __devexit_p(ab8500_remove),
+	.remove	= ab8500_remove,
 	.id_table = ab8500_id,
 };
 
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
index c4cb806..5a8e707 100644
--- a/drivers/mfd/ab8500-debugfs.c
+++ b/drivers/mfd/ab8500-debugfs.c
@@ -552,7 +552,7 @@ static struct dentry *ab8500_bank_file;
 static struct dentry *ab8500_address_file;
 static struct dentry *ab8500_val_file;
 
-static int __devinit ab8500_debug_probe(struct platform_device *plf)
+static int ab8500_debug_probe(struct platform_device *plf)
 {
 	debug_bank = AB8500_MISC;
 	debug_address = AB8500_REV_REG & 0x00FF;
@@ -597,7 +597,7 @@ exit_no_debugfs:
 	return -ENOMEM;
 }
 
-static int __devexit ab8500_debug_remove(struct platform_device *plf)
+static int ab8500_debug_remove(struct platform_device *plf)
 {
 	debugfs_remove(ab8500_val_file);
 	debugfs_remove(ab8500_address_file);
@@ -614,7 +614,7 @@ static struct platform_driver ab8500_debug_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe  = ab8500_debug_probe,
-	.remove = __devexit_p(ab8500_debug_remove)
+	.remove = ab8500_debug_remove
 };
 
 static int __init ab8500_debug_init(void)
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c
index 29d72a2..3fb1f40d 100644
--- a/drivers/mfd/ab8500-gpadc.c
+++ b/drivers/mfd/ab8500-gpadc.c
@@ -571,7 +571,7 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
 		gpadc->cal_data[ADC_INPUT_VBAT].offset);
 }
 
-static int __devinit ab8500_gpadc_probe(struct platform_device *pdev)
+static int ab8500_gpadc_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 	struct ab8500_gpadc *gpadc;
@@ -634,7 +634,7 @@ fail:
 	return ret;
 }
 
-static int __devexit ab8500_gpadc_remove(struct platform_device *pdev)
+static int ab8500_gpadc_remove(struct platform_device *pdev)
 {
 	struct ab8500_gpadc *gpadc = platform_get_drvdata(pdev);
 
@@ -651,7 +651,7 @@ static int __devexit ab8500_gpadc_remove(struct platform_device *pdev)
 
 static struct platform_driver ab8500_gpadc_driver = {
 	.probe = ab8500_gpadc_probe,
-	.remove = __devexit_p(ab8500_gpadc_remove),
+	.remove = ab8500_gpadc_remove,
 	.driver = {
 		.name = "ab8500-gpadc",
 		.owner = THIS_MODULE,
diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
index c28d4eb..8a33b2c 100644
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -49,13 +49,13 @@ int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value)
 		(u8)(reg & 0xFF), mask, value);
 }
 
-static int __devinit ab8500_sysctrl_probe(struct platform_device *pdev)
+static int ab8500_sysctrl_probe(struct platform_device *pdev)
 {
 	sysctrl_dev = &pdev->dev;
 	return 0;
 }
 
-static int __devexit ab8500_sysctrl_remove(struct platform_device *pdev)
+static int ab8500_sysctrl_remove(struct platform_device *pdev)
 {
 	sysctrl_dev = NULL;
 	return 0;
@@ -67,7 +67,7 @@ static struct platform_driver ab8500_sysctrl_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ab8500_sysctrl_probe,
-	.remove = __devexit_p(ab8500_sysctrl_remove),
+	.remove = ab8500_sysctrl_remove,
 };
 
 static int __init ab8500_sysctrl_init(void)
diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c
index ea8b947..210dd03 100644
--- a/drivers/mfd/adp5520.c
+++ b/drivers/mfd/adp5520.c
@@ -203,7 +203,7 @@ static int adp5520_remove_subdevs(struct adp5520_chip *chip)
 	return device_for_each_child(chip->dev, NULL, __remove_subdev);
 }
 
-static int __devinit adp5520_probe(struct i2c_client *client,
+static int adp5520_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	struct adp5520_platform_data *pdata = client->dev.platform_data;
@@ -307,7 +307,7 @@ out_free_chip:
 	return ret;
 }
 
-static int __devexit adp5520_remove(struct i2c_client *client)
+static int adp5520_remove(struct i2c_client *client)
 {
 	struct adp5520_chip *chip = dev_get_drvdata(&client->dev);
 
@@ -356,7 +356,7 @@ static struct i2c_driver adp5520_driver = {
 		.pm	= &adp5520_pm,
 	},
 	.probe		= adp5520_probe,
-	.remove		= __devexit_p(adp5520_remove),
+	.remove		= adp5520_remove,
 	.id_table 	= adp5520_id,
 };
 
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 1b48f20..c784f46 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -98,9 +98,9 @@ static irqreturn_t arizona_underclocked(int irq, void *data)
 
 	if (val & ARIZONA_AIF3_UNDERCLOCKED_STS)
 		dev_err(arizona->dev, "AIF3 underclocked\n");
-	if (val & ARIZONA_AIF3_UNDERCLOCKED_STS)
-		dev_err(arizona->dev, "AIF3 underclocked\n");
 	if (val & ARIZONA_AIF2_UNDERCLOCKED_STS)
+		dev_err(arizona->dev, "AIF2 underclocked\n");
+	if (val & ARIZONA_AIF1_UNDERCLOCKED_STS)
 		dev_err(arizona->dev, "AIF1 underclocked\n");
 	if (val & ARIZONA_ISRC2_UNDERCLOCKED_STS)
 		dev_err(arizona->dev, "ISRC2 underclocked\n");
@@ -272,6 +272,7 @@ static struct mfd_cell early_devs[] = {
 static struct mfd_cell wm5102_devs[] = {
 	{ .name = "arizona-extcon" },
 	{ .name = "arizona-gpio" },
+	{ .name = "arizona-haptics" },
 	{ .name = "arizona-micsupp" },
 	{ .name = "arizona-pwm" },
 	{ .name = "wm5102-codec" },
@@ -280,12 +281,13 @@ static struct mfd_cell wm5102_devs[] = {
 static struct mfd_cell wm5110_devs[] = {
 	{ .name = "arizona-extcon" },
 	{ .name = "arizona-gpio" },
+	{ .name = "arizona-haptics" },
 	{ .name = "arizona-micsupp" },
 	{ .name = "arizona-pwm" },
 	{ .name = "wm5110-codec" },
 };
 
-int __devinit arizona_dev_init(struct arizona *arizona)
+int arizona_dev_init(struct arizona *arizona)
 {
 	struct device *dev = arizona->dev;
 	const char *type_name;
@@ -415,11 +417,19 @@ int __devinit arizona_dev_init(struct arizona *arizona)
 
 	/* If we have a /RESET GPIO we'll already be reset */
 	if (!arizona->pdata.reset) {
+		regcache_mark_dirty(arizona->regmap);
+
 		ret = regmap_write(arizona->regmap, ARIZONA_SOFTWARE_RESET, 0);
 		if (ret != 0) {
 			dev_err(dev, "Failed to reset device: %d\n", ret);
 			goto err_reset;
 		}
+
+		ret = regcache_sync(arizona->regmap);
+		if (ret != 0) {
+			dev_err(dev, "Failed to sync device: %d\n", ret);
+			goto err_reset;
+		}
 	}
 
 	ret = arizona_wait_for_boot(arizona);
@@ -520,7 +530,7 @@ int __devinit arizona_dev_init(struct arizona *arizona)
 		break;
 	case WM5110:
 		ret = mfd_add_devices(arizona->dev, -1, wm5110_devs,
-				      ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);
+				      ARRAY_SIZE(wm5110_devs), NULL, 0, NULL);
 		break;
 	}
 
@@ -553,7 +563,7 @@ err_early:
 }
 EXPORT_SYMBOL_GPL(arizona_dev_init);
 
-int __devexit arizona_dev_exit(struct arizona *arizona)
+int arizona_dev_exit(struct arizona *arizona)
 {
 	mfd_remove_devices(arizona->dev);
 	arizona_free_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, arizona);
diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c
index 570c4b4..44a1bb9 100644
--- a/drivers/mfd/arizona-i2c.c
+++ b/drivers/mfd/arizona-i2c.c
@@ -22,7 +22,7 @@
 
 #include "arizona.h"
 
-static __devinit int arizona_i2c_probe(struct i2c_client *i2c,
+static int arizona_i2c_probe(struct i2c_client *i2c,
 					  const struct i2c_device_id *id)
 {
 	struct arizona *arizona;
@@ -65,7 +65,7 @@ static __devinit int arizona_i2c_probe(struct i2c_client *i2c,
 	return arizona_dev_init(arizona);
 }
 
-static int __devexit arizona_i2c_remove(struct i2c_client *i2c)
+static int arizona_i2c_remove(struct i2c_client *i2c)
 {
 	struct arizona *arizona = dev_get_drvdata(&i2c->dev);
 	arizona_dev_exit(arizona);
@@ -86,7 +86,7 @@ static struct i2c_driver arizona_i2c_driver = {
 		.pm	= &arizona_pm_ops,
 	},
 	.probe		= arizona_i2c_probe,
-	.remove		= __devexit_p(arizona_i2c_remove),
+	.remove		= arizona_i2c_remove,
 	.id_table	= arizona_i2c_id,
 };
 
diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c
index ef0f2d0..b1b0091 100644
--- a/drivers/mfd/arizona-irq.c
+++ b/drivers/mfd/arizona-irq.c
@@ -178,6 +178,7 @@ int arizona_irq_init(struct arizona *arizona)
 
 		switch (arizona->rev) {
 		case 0:
+		case 1:
 			ctrlif_error = false;
 			break;
 		default:
diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
index df2e5a8..1b9fdd6 100644
--- a/drivers/mfd/arizona-spi.c
+++ b/drivers/mfd/arizona-spi.c
@@ -22,7 +22,7 @@
 
 #include "arizona.h"
 
-static int __devinit arizona_spi_probe(struct spi_device *spi)
+static int arizona_spi_probe(struct spi_device *spi)
 {
 	const struct spi_device_id *id = spi_get_device_id(spi);
 	struct arizona *arizona;
@@ -65,7 +65,7 @@ static int __devinit arizona_spi_probe(struct spi_device *spi)
 	return arizona_dev_init(arizona);
 }
 
-static int __devexit arizona_spi_remove(struct spi_device *spi)
+static int arizona_spi_remove(struct spi_device *spi)
 {
 	struct arizona *arizona = dev_get_drvdata(&spi->dev);
 	arizona_dev_exit(arizona);
@@ -86,7 +86,7 @@ static struct spi_driver arizona_spi_driver = {
 		.pm	= &arizona_pm_ops,
 	},
 	.probe		= arizona_spi_probe,
-	.remove		= __devexit_p(arizona_spi_remove),
+	.remove		= arizona_spi_remove,
 	.id_table	= arizona_spi_ids,
 };
 
diff --git a/drivers/mfd/as3711.c b/drivers/mfd/as3711.c
new file mode 100644
index 0000000..e994c96
--- /dev/null
+++ b/drivers/mfd/as3711.c
@@ -0,0 +1,217 @@
+/*
+ * AS3711 PMIC MFC driver
+ *
+ * Copyright (C) 2012 Renesas Electronics Corporation
+ * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License as
+ * published by the Free Software Foundation
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mfd/as3711.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+enum {
+	AS3711_REGULATOR,
+	AS3711_BACKLIGHT,
+};
+
+/*
+ * Ok to have it static: it is only used during probing and multiple I2C devices
+ * cannot be probed simultaneously. Just make sure to avoid stale data.
+ */
+static struct mfd_cell as3711_subdevs[] = {
+	[AS3711_REGULATOR] = {.name = "as3711-regulator",},
+	[AS3711_BACKLIGHT] = {.name = "as3711-backlight",},
+};
+
+static bool as3711_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case AS3711_GPIO_SIGNAL_IN:
+	case AS3711_INTERRUPT_STATUS_1:
+	case AS3711_INTERRUPT_STATUS_2:
+	case AS3711_INTERRUPT_STATUS_3:
+	case AS3711_CHARGER_STATUS_1:
+	case AS3711_CHARGER_STATUS_2:
+	case AS3711_REG_STATUS:
+		return true;
+	}
+	return false;
+}
+
+static bool as3711_precious_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case AS3711_INTERRUPT_STATUS_1:
+	case AS3711_INTERRUPT_STATUS_2:
+	case AS3711_INTERRUPT_STATUS_3:
+		return true;
+	}
+	return false;
+}
+
+static bool as3711_readable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case AS3711_SD_1_VOLTAGE:
+	case AS3711_SD_2_VOLTAGE:
+	case AS3711_SD_3_VOLTAGE:
+	case AS3711_SD_4_VOLTAGE:
+	case AS3711_LDO_1_VOLTAGE:
+	case AS3711_LDO_2_VOLTAGE:
+	case AS3711_LDO_3_VOLTAGE:
+	case AS3711_LDO_4_VOLTAGE:
+	case AS3711_LDO_5_VOLTAGE:
+	case AS3711_LDO_6_VOLTAGE:
+	case AS3711_LDO_7_VOLTAGE:
+	case AS3711_LDO_8_VOLTAGE:
+	case AS3711_SD_CONTROL:
+	case AS3711_GPIO_SIGNAL_OUT:
+	case AS3711_GPIO_SIGNAL_IN:
+	case AS3711_SD_CONTROL_1:
+	case AS3711_SD_CONTROL_2:
+	case AS3711_CURR_CONTROL:
+	case AS3711_CURR1_VALUE:
+	case AS3711_CURR2_VALUE:
+	case AS3711_CURR3_VALUE:
+	case AS3711_STEPUP_CONTROL_1:
+	case AS3711_STEPUP_CONTROL_2:
+	case AS3711_STEPUP_CONTROL_4:
+	case AS3711_STEPUP_CONTROL_5:
+	case AS3711_REG_STATUS:
+	case AS3711_INTERRUPT_STATUS_1:
+	case AS3711_INTERRUPT_STATUS_2:
+	case AS3711_INTERRUPT_STATUS_3:
+	case AS3711_CHARGER_STATUS_1:
+	case AS3711_CHARGER_STATUS_2:
+	case AS3711_ASIC_ID_1:
+	case AS3711_ASIC_ID_2:
+		return true;
+	}
+	return false;
+}
+
+static const struct regmap_config as3711_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.volatile_reg = as3711_volatile_reg,
+	.readable_reg = as3711_readable_reg,
+	.precious_reg = as3711_precious_reg,
+	.max_register = AS3711_MAX_REGS,
+	.num_reg_defaults_raw = AS3711_MAX_REGS,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static int as3711_i2c_probe(struct i2c_client *client,
+			    const struct i2c_device_id *id)
+{
+	struct as3711 *as3711;
+	struct as3711_platform_data *pdata = client->dev.platform_data;
+	unsigned int id1, id2;
+	int ret;
+
+	if (!pdata)
+		dev_dbg(&client->dev, "Platform data not found\n");
+
+	as3711 = devm_kzalloc(&client->dev, sizeof(struct as3711), GFP_KERNEL);
+	if (!as3711) {
+		dev_err(&client->dev, "Memory allocation failed\n");
+		return -ENOMEM;
+	}
+
+	as3711->dev = &client->dev;
+	i2c_set_clientdata(client, as3711);
+
+	if (client->irq)
+		dev_notice(&client->dev, "IRQ not supported yet\n");
+
+	as3711->regmap = devm_regmap_init_i2c(client, &as3711_regmap_config);
+	if (IS_ERR(as3711->regmap)) {
+		ret = PTR_ERR(as3711->regmap);
+		dev_err(&client->dev, "regmap initialization failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = regmap_read(as3711->regmap, AS3711_ASIC_ID_1, &id1);
+	if (!ret)
+		ret = regmap_read(as3711->regmap, AS3711_ASIC_ID_2, &id2);
+	if (ret < 0) {
+		dev_err(&client->dev, "regmap_read() failed: %d\n", ret);
+		return ret;
+	}
+	if (id1 != 0x8b)
+		return -ENODEV;
+	dev_info(as3711->dev, "AS3711 detected: %x:%x\n", id1, id2);
+
+	/* We can reuse as3711_subdevs[], it will be copied in mfd_add_devices() */
+	if (pdata) {
+		as3711_subdevs[AS3711_REGULATOR].platform_data = &pdata->regulator;
+		as3711_subdevs[AS3711_REGULATOR].pdata_size = sizeof(pdata->regulator);
+		as3711_subdevs[AS3711_BACKLIGHT].platform_data = &pdata->backlight;
+		as3711_subdevs[AS3711_BACKLIGHT].pdata_size = sizeof(pdata->backlight);
+	} else {
+		as3711_subdevs[AS3711_REGULATOR].platform_data = NULL;
+		as3711_subdevs[AS3711_REGULATOR].pdata_size = 0;
+		as3711_subdevs[AS3711_BACKLIGHT].platform_data = NULL;
+		as3711_subdevs[AS3711_BACKLIGHT].pdata_size = 0;
+	}
+
+	ret = mfd_add_devices(as3711->dev, -1, as3711_subdevs,
+			      ARRAY_SIZE(as3711_subdevs), NULL, 0, NULL);
+	if (ret < 0)
+		dev_err(&client->dev, "add mfd devices failed: %d\n", ret);
+
+	return ret;
+}
+
+static int as3711_i2c_remove(struct i2c_client *client)
+{
+	struct as3711 *as3711 = i2c_get_clientdata(client);
+
+	mfd_remove_devices(as3711->dev);
+	return 0;
+}
+
+static const struct i2c_device_id as3711_i2c_id[] = {
+	{.name = "as3711", .driver_data = 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, as3711_i2c_id);
+
+static struct i2c_driver as3711_i2c_driver = {
+	.driver = {
+		   .name = "as3711",
+		   .owner = THIS_MODULE,
+		   },
+	.probe = as3711_i2c_probe,
+	.remove = as3711_i2c_remove,
+	.id_table = as3711_i2c_id,
+};
+
+static int __init as3711_i2c_init(void)
+{
+	return i2c_add_driver(&as3711_i2c_driver);
+}
+/* Initialise early */
+subsys_initcall(as3711_i2c_init);
+
+static void __exit as3711_i2c_exit(void)
+{
+	i2c_del_driver(&as3711_i2c_driver);
+}
+module_exit(as3711_i2c_exit);
+
+MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
+MODULE_DESCRIPTION("AS3711 PMIC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index 62f0883..1b15986 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -1039,7 +1039,7 @@ static int __init asic3_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit asic3_remove(struct platform_device *pdev)
+static int asic3_remove(struct platform_device *pdev)
 {
 	int ret;
 	struct asic3 *asic = platform_get_drvdata(pdev);
@@ -1071,7 +1071,7 @@ static struct platform_driver asic3_device_driver = {
 	.driver		= {
 		.name	= "asic3",
 	},
-	.remove		= __devexit_p(asic3_remove),
+	.remove		= asic3_remove,
 	.shutdown	= asic3_shutdown,
 };
 
diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c
index 2b28213..2e4752a 100644
--- a/drivers/mfd/cs5535-mfd.c
+++ b/drivers/mfd/cs5535-mfd.c
@@ -71,9 +71,9 @@ static int cs5535_mfd_res_disable(struct platform_device *pdev)
 	return 0;
 }
 
-static __devinitdata struct resource cs5535_mfd_resources[NR_BARS];
+static struct resource cs5535_mfd_resources[NR_BARS];
 
-static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
+static struct mfd_cell cs5535_mfd_cells[] = {
 	{
 		.id = SMB_BAR,
 		.name = "cs5535-smb",
@@ -113,7 +113,7 @@ static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
 };
 
 #ifdef CONFIG_OLPC
-static void __devinit cs5535_clone_olpc_cells(void)
+static void cs5535_clone_olpc_cells(void)
 {
 	const char *acpi_clones[] = { "olpc-xo1-pm-acpi", "olpc-xo1-sci-acpi" };
 
@@ -126,7 +126,7 @@ static void __devinit cs5535_clone_olpc_cells(void)
 static void cs5535_clone_olpc_cells(void) { }
 #endif
 
-static int __devinit cs5535_mfd_probe(struct pci_dev *pdev,
+static int cs5535_mfd_probe(struct pci_dev *pdev,
 		const struct pci_device_id *id)
 {
 	int err, i;
@@ -166,7 +166,7 @@ err_disable:
 	return err;
 }
 
-static void __devexit cs5535_mfd_remove(struct pci_dev *pdev)
+static void cs5535_mfd_remove(struct pci_dev *pdev)
 {
 	mfd_remove_devices(&pdev->dev);
 	pci_disable_device(pdev);
@@ -183,7 +183,7 @@ static struct pci_driver cs5535_mfd_driver = {
 	.name = DRV_NAME,
 	.id_table = cs5535_mfd_pci_tbl,
 	.probe = cs5535_mfd_probe,
-	.remove = __devexit_p(cs5535_mfd_remove),
+	.remove = cs5535_mfd_remove,
 };
 
 module_pci_driver(cs5535_mfd_driver);
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
index 1924b85..05176cd 100644
--- a/drivers/mfd/da903x.c
+++ b/drivers/mfd/da903x.c
@@ -246,7 +246,7 @@ int da903x_query_status(struct device *dev, unsigned int sbits)
 }
 EXPORT_SYMBOL(da903x_query_status);
 
-static int __devinit da9030_init_chip(struct da903x_chip *chip)
+static int da9030_init_chip(struct da903x_chip *chip)
 {
 	uint8_t chip_id;
 	int err;
@@ -459,7 +459,7 @@ static int da903x_remove_subdevs(struct da903x_chip *chip)
 	return device_for_each_child(chip->dev, NULL, __remove_subdev);
 }
 
-static int __devinit da903x_add_subdevs(struct da903x_chip *chip,
+static int da903x_add_subdevs(struct da903x_chip *chip,
 					struct da903x_platform_data *pdata)
 {
 	struct da903x_subdev_info *subdev;
@@ -491,7 +491,7 @@ failed:
 	return ret;
 }
 
-static int __devinit da903x_probe(struct i2c_client *client,
+static int da903x_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
 	struct da903x_platform_data *pdata = client->dev.platform_data;
@@ -544,7 +544,7 @@ out_free_chip:
 	return ret;
 }
 
-static int __devexit da903x_remove(struct i2c_client *client)
+static int da903x_remove(struct i2c_client *client)
 {
 	struct da903x_chip *chip = i2c_get_clientdata(client);
 
@@ -560,7 +560,7 @@ static struct i2c_driver da903x_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= da903x_probe,
-	.remove		= __devexit_p(da903x_remove),
+	.remove		= da903x_remove,
 	.id_table	= da903x_id_table,
 };
 
diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c
index a0a62b2..a3c9613 100644
--- a/drivers/mfd/da9052-core.c
+++ b/drivers/mfd/da9052-core.c
@@ -15,7 +15,6 @@
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/mfd/core.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -24,16 +23,6 @@
 #include <linux/mfd/da9052/pdata.h>
 #include <linux/mfd/da9052/reg.h>
 
-#define DA9052_NUM_IRQ_REGS		4
-#define DA9052_IRQ_MASK_POS_1		0x01
-#define DA9052_IRQ_MASK_POS_2		0x02
-#define DA9052_IRQ_MASK_POS_3		0x04
-#define DA9052_IRQ_MASK_POS_4		0x08
-#define DA9052_IRQ_MASK_POS_5		0x10
-#define DA9052_IRQ_MASK_POS_6		0x20
-#define DA9052_IRQ_MASK_POS_7		0x40
-#define DA9052_IRQ_MASK_POS_8		0x80
-
 static bool da9052_reg_readable(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
@@ -425,15 +414,6 @@ err:
 }
 EXPORT_SYMBOL_GPL(da9052_adc_manual_read);
 
-static irqreturn_t da9052_auxadc_irq(int irq, void *irq_data)
-{
-	struct da9052 *da9052 = irq_data;
-
-	complete(&da9052->done);
-
-	return IRQ_HANDLED;
-}
-
 int da9052_adc_read_temp(struct da9052 *da9052)
 {
 	int tbat;
@@ -447,75 +427,7 @@ int da9052_adc_read_temp(struct da9052 *da9052)
 }
 EXPORT_SYMBOL_GPL(da9052_adc_read_temp);
 
-static struct resource da9052_rtc_resource = {
-	.name = "ALM",
-	.start = DA9052_IRQ_ALARM,
-	.end   = DA9052_IRQ_ALARM,
-	.flags = IORESOURCE_IRQ,
-};
-
-static struct resource da9052_onkey_resource = {
-	.name = "ONKEY",
-	.start = DA9052_IRQ_NONKEY,
-	.end   = DA9052_IRQ_NONKEY,
-	.flags = IORESOURCE_IRQ,
-};
-
-static struct resource da9052_bat_resources[] = {
-	{
-		.name = "BATT TEMP",
-		.start = DA9052_IRQ_TBAT,
-		.end   = DA9052_IRQ_TBAT,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "DCIN DET",
-		.start = DA9052_IRQ_DCIN,
-		.end   = DA9052_IRQ_DCIN,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "DCIN REM",
-		.start = DA9052_IRQ_DCINREM,
-		.end   = DA9052_IRQ_DCINREM,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "VBUS DET",
-		.start = DA9052_IRQ_VBUS,
-		.end   = DA9052_IRQ_VBUS,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "VBUS REM",
-		.start = DA9052_IRQ_VBUSREM,
-		.end   = DA9052_IRQ_VBUSREM,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "CHG END",
-		.start = DA9052_IRQ_CHGEND,
-		.end   = DA9052_IRQ_CHGEND,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource da9052_tsi_resources[] = {
-	{
-		.name = "PENDWN",
-		.start = DA9052_IRQ_PENDOWN,
-		.end   = DA9052_IRQ_PENDOWN,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "TSIRDY",
-		.start = DA9052_IRQ_TSIREADY,
-		.end   = DA9052_IRQ_TSIREADY,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct mfd_cell __devinitdata da9052_subdev_info[] = {
+static struct mfd_cell da9052_subdev_info[] = {
 	{
 		.name = "da9052-regulator",
 		.id = 1,
@@ -574,13 +486,9 @@ static struct mfd_cell __devinitdata da9052_subdev_info[] = {
 	},
 	{
 		.name = "da9052-onkey",
-		.resources = &da9052_onkey_resource,
-		.num_resources = 1,
 	},
 	{
 		.name = "da9052-rtc",
-		.resources = &da9052_rtc_resource,
-		.num_resources = 1,
 	},
 	{
 		.name = "da9052-gpio",
@@ -602,160 +510,15 @@ static struct mfd_cell __devinitdata da9052_subdev_info[] = {
 	},
 	{
 		.name = "da9052-tsi",
-		.resources = da9052_tsi_resources,
-		.num_resources = ARRAY_SIZE(da9052_tsi_resources),
 	},
 	{
 		.name = "da9052-bat",
-		.resources = da9052_bat_resources,
-		.num_resources = ARRAY_SIZE(da9052_bat_resources),
 	},
 	{
 		.name = "da9052-watchdog",
 	},
 };
 
-static struct regmap_irq da9052_irqs[] = {
-	[DA9052_IRQ_DCIN] = {
-		.reg_offset = 0,
-		.mask = DA9052_IRQ_MASK_POS_1,
-	},
-	[DA9052_IRQ_VBUS] = {
-		.reg_offset = 0,
-		.mask = DA9052_IRQ_MASK_POS_2,
-	},
-	[DA9052_IRQ_DCINREM] = {
-		.reg_offset = 0,
-		.mask = DA9052_IRQ_MASK_POS_3,
-	},
-	[DA9052_IRQ_VBUSREM] = {
-		.reg_offset = 0,
-		.mask = DA9052_IRQ_MASK_POS_4,
-	},
-	[DA9052_IRQ_VDDLOW] = {
-		.reg_offset = 0,
-		.mask = DA9052_IRQ_MASK_POS_5,
-	},
-	[DA9052_IRQ_ALARM] = {
-		.reg_offset = 0,
-		.mask = DA9052_IRQ_MASK_POS_6,
-	},
-	[DA9052_IRQ_SEQRDY] = {
-		.reg_offset = 0,
-		.mask = DA9052_IRQ_MASK_POS_7,
-	},
-	[DA9052_IRQ_COMP1V2] = {
-		.reg_offset = 0,
-		.mask = DA9052_IRQ_MASK_POS_8,
-	},
-	[DA9052_IRQ_NONKEY] = {
-		.reg_offset = 1,
-		.mask = DA9052_IRQ_MASK_POS_1,
-	},
-	[DA9052_IRQ_IDFLOAT] = {
-		.reg_offset = 1,
-		.mask = DA9052_IRQ_MASK_POS_2,
-	},
-	[DA9052_IRQ_IDGND] = {
-		.reg_offset = 1,
-		.mask = DA9052_IRQ_MASK_POS_3,
-	},
-	[DA9052_IRQ_CHGEND] = {
-		.reg_offset = 1,
-		.mask = DA9052_IRQ_MASK_POS_4,
-	},
-	[DA9052_IRQ_TBAT] = {
-		.reg_offset = 1,
-		.mask = DA9052_IRQ_MASK_POS_5,
-	},
-	[DA9052_IRQ_ADC_EOM] = {
-		.reg_offset = 1,
-		.mask = DA9052_IRQ_MASK_POS_6,
-	},
-	[DA9052_IRQ_PENDOWN] = {
-		.reg_offset = 1,
-		.mask = DA9052_IRQ_MASK_POS_7,
-	},
-	[DA9052_IRQ_TSIREADY] = {
-		.reg_offset = 1,
-		.mask = DA9052_IRQ_MASK_POS_8,
-	},
-	[DA9052_IRQ_GPI0] = {
-		.reg_offset = 2,
-		.mask = DA9052_IRQ_MASK_POS_1,
-	},
-	[DA9052_IRQ_GPI1] = {
-		.reg_offset = 2,
-		.mask = DA9052_IRQ_MASK_POS_2,
-	},
-	[DA9052_IRQ_GPI2] = {
-		.reg_offset = 2,
-		.mask = DA9052_IRQ_MASK_POS_3,
-	},
-	[DA9052_IRQ_GPI3] = {
-		.reg_offset = 2,
-		.mask = DA9052_IRQ_MASK_POS_4,
-	},
-	[DA9052_IRQ_GPI4] = {
-		.reg_offset = 2,
-		.mask = DA9052_IRQ_MASK_POS_5,
-	},
-	[DA9052_IRQ_GPI5] = {
-		.reg_offset = 2,
-		.mask = DA9052_IRQ_MASK_POS_6,
-	},
-	[DA9052_IRQ_GPI6] = {
-		.reg_offset = 2,
-		.mask = DA9052_IRQ_MASK_POS_7,
-	},
-	[DA9052_IRQ_GPI7] = {
-		.reg_offset = 2,
-		.mask = DA9052_IRQ_MASK_POS_8,
-	},
-	[DA9052_IRQ_GPI8] = {
-		.reg_offset = 3,
-		.mask = DA9052_IRQ_MASK_POS_1,
-	},
-	[DA9052_IRQ_GPI9] = {
-		.reg_offset = 3,
-		.mask = DA9052_IRQ_MASK_POS_2,
-	},
-	[DA9052_IRQ_GPI10] = {
-		.reg_offset = 3,
-		.mask = DA9052_IRQ_MASK_POS_3,
-	},
-	[DA9052_IRQ_GPI11] = {
-		.reg_offset = 3,
-		.mask = DA9052_IRQ_MASK_POS_4,
-	},
-	[DA9052_IRQ_GPI12] = {
-		.reg_offset = 3,
-		.mask = DA9052_IRQ_MASK_POS_5,
-	},
-	[DA9052_IRQ_GPI13] = {
-		.reg_offset = 3,
-		.mask = DA9052_IRQ_MASK_POS_6,
-	},
-	[DA9052_IRQ_GPI14] = {
-		.reg_offset = 3,
-		.mask = DA9052_IRQ_MASK_POS_7,
-	},
-	[DA9052_IRQ_GPI15] = {
-		.reg_offset = 3,
-		.mask = DA9052_IRQ_MASK_POS_8,
-	},
-};
-
-static struct regmap_irq_chip da9052_regmap_irq_chip = {
-	.name = "da9052_irq",
-	.status_base = DA9052_EVENT_A_REG,
-	.mask_base = DA9052_IRQ_MASK_A_REG,
-	.ack_base = DA9052_EVENT_A_REG,
-	.num_regs = DA9052_NUM_IRQ_REGS,
-	.irqs = da9052_irqs,
-	.num_irqs = ARRAY_SIZE(da9052_irqs),
-};
-
 struct regmap_config da9052_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
@@ -769,7 +532,7 @@ struct regmap_config da9052_regmap_config = {
 };
 EXPORT_SYMBOL_GPL(da9052_regmap_config);
 
-int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
+int da9052_device_init(struct da9052 *da9052, u8 chip_id)
 {
 	struct da9052_pdata *pdata = da9052->dev->platform_data;
 	int ret;
@@ -782,45 +545,31 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
 
 	da9052->chip_id = chip_id;
 
-	if (!pdata || !pdata->irq_base)
-		da9052->irq_base = -1;
-	else
-		da9052->irq_base = pdata->irq_base;
-
-	ret = regmap_add_irq_chip(da9052->regmap, da9052->chip_irq,
-				  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-				  da9052->irq_base, &da9052_regmap_irq_chip,
-				  &da9052->irq_data);
-	if (ret < 0)
-		goto regmap_err;
-
-	da9052->irq_base = regmap_irq_chip_get_base(da9052->irq_data);
-
-	ret = request_threaded_irq(DA9052_IRQ_ADC_EOM, NULL, da9052_auxadc_irq,
-				   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-				   "adc irq", da9052);
-	if (ret != 0)
-		dev_err(da9052->dev, "DA9052 ADC IRQ failed ret=%d\n", ret);
+	ret = da9052_irq_init(da9052);
+	if (ret != 0) {
+		dev_err(da9052->dev, "da9052_irq_init failed: %d\n", ret);
+		return ret;
+	}
 
 	ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info,
 			      ARRAY_SIZE(da9052_subdev_info), NULL, 0, NULL);
-	if (ret)
+	if (ret) {
+		dev_err(da9052->dev, "mfd_add_devices failed: %d\n", ret);
 		goto err;
+	}
 
 	return 0;
 
 err:
-	free_irq(DA9052_IRQ_ADC_EOM, da9052);
-	mfd_remove_devices(da9052->dev);
-regmap_err:
+	da9052_irq_exit(da9052);
+
 	return ret;
 }
 
 void da9052_device_exit(struct da9052 *da9052)
 {
-	free_irq(DA9052_IRQ_ADC_EOM, da9052);
-	regmap_del_irq_chip(da9052->chip_irq, da9052->irq_data);
 	mfd_remove_devices(da9052->dev);
+	da9052_irq_exit(da9052);
 }
 
 MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c
index 352c58b..ac74a4d 100644
--- a/drivers/mfd/da9052-i2c.c
+++ b/drivers/mfd/da9052-i2c.c
@@ -64,7 +64,7 @@ static const struct of_device_id dialog_dt_ids[] = {
 };
 #endif
 
-static int __devinit da9052_i2c_probe(struct i2c_client *client,
+static int da9052_i2c_probe(struct i2c_client *client,
 				       const struct i2c_device_id *id)
 {
 	struct da9052 *da9052;
@@ -121,7 +121,7 @@ static int __devinit da9052_i2c_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int __devexit da9052_i2c_remove(struct i2c_client *client)
+static int da9052_i2c_remove(struct i2c_client *client)
 {
 	struct da9052 *da9052 = i2c_get_clientdata(client);
 
@@ -131,7 +131,7 @@ static int __devexit da9052_i2c_remove(struct i2c_client *client)
 
 static struct i2c_driver da9052_i2c_driver = {
 	.probe = da9052_i2c_probe,
-	.remove = __devexit_p(da9052_i2c_remove),
+	.remove = da9052_i2c_remove,
 	.id_table = da9052_i2c_id,
 	.driver = {
 		.name = "da9052",
diff --git a/drivers/mfd/da9052-irq.c b/drivers/mfd/da9052-irq.c
new file mode 100644
index 0000000..57ae784
--- /dev/null
+++ b/drivers/mfd/da9052-irq.c
@@ -0,0 +1,288 @@
+/*
+ * DA9052 interrupt support
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ * Based on arizona-irq.c, which is:
+ *
+ * Copyright 2012 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 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#include <linux/mfd/da9052/da9052.h>
+#include <linux/mfd/da9052/reg.h>
+
+#define DA9052_NUM_IRQ_REGS		4
+#define DA9052_IRQ_MASK_POS_1		0x01
+#define DA9052_IRQ_MASK_POS_2		0x02
+#define DA9052_IRQ_MASK_POS_3		0x04
+#define DA9052_IRQ_MASK_POS_4		0x08
+#define DA9052_IRQ_MASK_POS_5		0x10
+#define DA9052_IRQ_MASK_POS_6		0x20
+#define DA9052_IRQ_MASK_POS_7		0x40
+#define DA9052_IRQ_MASK_POS_8		0x80
+
+static struct regmap_irq da9052_irqs[] = {
+	[DA9052_IRQ_DCIN] = {
+		.reg_offset = 0,
+		.mask = DA9052_IRQ_MASK_POS_1,
+	},
+	[DA9052_IRQ_VBUS] = {
+		.reg_offset = 0,
+		.mask = DA9052_IRQ_MASK_POS_2,
+	},
+	[DA9052_IRQ_DCINREM] = {
+		.reg_offset = 0,
+		.mask = DA9052_IRQ_MASK_POS_3,
+	},
+	[DA9052_IRQ_VBUSREM] = {
+		.reg_offset = 0,
+		.mask = DA9052_IRQ_MASK_POS_4,
+	},
+	[DA9052_IRQ_VDDLOW] = {
+		.reg_offset = 0,
+		.mask = DA9052_IRQ_MASK_POS_5,
+	},
+	[DA9052_IRQ_ALARM] = {
+		.reg_offset = 0,
+		.mask = DA9052_IRQ_MASK_POS_6,
+	},
+	[DA9052_IRQ_SEQRDY] = {
+		.reg_offset = 0,
+		.mask = DA9052_IRQ_MASK_POS_7,
+	},
+	[DA9052_IRQ_COMP1V2] = {
+		.reg_offset = 0,
+		.mask = DA9052_IRQ_MASK_POS_8,
+	},
+	[DA9052_IRQ_NONKEY] = {
+		.reg_offset = 1,
+		.mask = DA9052_IRQ_MASK_POS_1,
+	},
+	[DA9052_IRQ_IDFLOAT] = {
+		.reg_offset = 1,
+		.mask = DA9052_IRQ_MASK_POS_2,
+	},
+	[DA9052_IRQ_IDGND] = {
+		.reg_offset = 1,
+		.mask = DA9052_IRQ_MASK_POS_3,
+	},
+	[DA9052_IRQ_CHGEND] = {
+		.reg_offset = 1,
+		.mask = DA9052_IRQ_MASK_POS_4,
+	},
+	[DA9052_IRQ_TBAT] = {
+		.reg_offset = 1,
+		.mask = DA9052_IRQ_MASK_POS_5,
+	},
+	[DA9052_IRQ_ADC_EOM] = {
+		.reg_offset = 1,
+		.mask = DA9052_IRQ_MASK_POS_6,
+	},
+	[DA9052_IRQ_PENDOWN] = {
+		.reg_offset = 1,
+		.mask = DA9052_IRQ_MASK_POS_7,
+	},
+	[DA9052_IRQ_TSIREADY] = {
+		.reg_offset = 1,
+		.mask = DA9052_IRQ_MASK_POS_8,
+	},
+	[DA9052_IRQ_GPI0] = {
+		.reg_offset = 2,
+		.mask = DA9052_IRQ_MASK_POS_1,
+	},
+	[DA9052_IRQ_GPI1] = {
+		.reg_offset = 2,
+		.mask = DA9052_IRQ_MASK_POS_2,
+	},
+	[DA9052_IRQ_GPI2] = {
+		.reg_offset = 2,
+		.mask = DA9052_IRQ_MASK_POS_3,
+	},
+	[DA9052_IRQ_GPI3] = {
+		.reg_offset = 2,
+		.mask = DA9052_IRQ_MASK_POS_4,
+	},
+	[DA9052_IRQ_GPI4] = {
+		.reg_offset = 2,
+		.mask = DA9052_IRQ_MASK_POS_5,
+	},
+	[DA9052_IRQ_GPI5] = {
+		.reg_offset = 2,
+		.mask = DA9052_IRQ_MASK_POS_6,
+	},
+	[DA9052_IRQ_GPI6] = {
+		.reg_offset = 2,
+		.mask = DA9052_IRQ_MASK_POS_7,
+	},
+	[DA9052_IRQ_GPI7] = {
+		.reg_offset = 2,
+		.mask = DA9052_IRQ_MASK_POS_8,
+	},
+	[DA9052_IRQ_GPI8] = {
+		.reg_offset = 3,
+		.mask = DA9052_IRQ_MASK_POS_1,
+	},
+	[DA9052_IRQ_GPI9] = {
+		.reg_offset = 3,
+		.mask = DA9052_IRQ_MASK_POS_2,
+	},
+	[DA9052_IRQ_GPI10] = {
+		.reg_offset = 3,
+		.mask = DA9052_IRQ_MASK_POS_3,
+	},
+	[DA9052_IRQ_GPI11] = {
+		.reg_offset = 3,
+		.mask = DA9052_IRQ_MASK_POS_4,
+	},
+	[DA9052_IRQ_GPI12] = {
+		.reg_offset = 3,
+		.mask = DA9052_IRQ_MASK_POS_5,
+	},
+	[DA9052_IRQ_GPI13] = {
+		.reg_offset = 3,
+		.mask = DA9052_IRQ_MASK_POS_6,
+	},
+	[DA9052_IRQ_GPI14] = {
+		.reg_offset = 3,
+		.mask = DA9052_IRQ_MASK_POS_7,
+	},
+	[DA9052_IRQ_GPI15] = {
+		.reg_offset = 3,
+		.mask = DA9052_IRQ_MASK_POS_8,
+	},
+};
+
+static struct regmap_irq_chip da9052_regmap_irq_chip = {
+	.name = "da9052_irq",
+	.status_base = DA9052_EVENT_A_REG,
+	.mask_base = DA9052_IRQ_MASK_A_REG,
+	.ack_base = DA9052_EVENT_A_REG,
+	.num_regs = DA9052_NUM_IRQ_REGS,
+	.irqs = da9052_irqs,
+	.num_irqs = ARRAY_SIZE(da9052_irqs),
+};
+
+static int da9052_map_irq(struct da9052 *da9052, int irq)
+{
+	return regmap_irq_get_virq(da9052->irq_data, irq);
+}
+
+int da9052_enable_irq(struct da9052 *da9052, int irq)
+{
+	irq = da9052_map_irq(da9052, irq);
+	if (irq < 0)
+		return irq;
+
+	enable_irq(irq);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(da9052_enable_irq);
+
+int da9052_disable_irq(struct da9052 *da9052, int irq)
+{
+	irq = da9052_map_irq(da9052, irq);
+	if (irq < 0)
+		return irq;
+
+	disable_irq(irq);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(da9052_disable_irq);
+
+int da9052_disable_irq_nosync(struct da9052 *da9052, int irq)
+{
+	irq = da9052_map_irq(da9052, irq);
+	if (irq < 0)
+		return irq;
+
+	disable_irq_nosync(irq);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(da9052_disable_irq_nosync);
+
+int da9052_request_irq(struct da9052 *da9052, int irq, char *name,
+			   irq_handler_t handler, void *data)
+{
+	irq = da9052_map_irq(da9052, irq);
+	if (irq < 0)
+		return irq;
+
+	return request_threaded_irq(irq, NULL, handler,
+				     IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+				     name, data);
+}
+EXPORT_SYMBOL_GPL(da9052_request_irq);
+
+void da9052_free_irq(struct da9052 *da9052, int irq, void *data)
+{
+	irq = da9052_map_irq(da9052, irq);
+	if (irq < 0)
+		return;
+
+	free_irq(irq, data);
+}
+EXPORT_SYMBOL_GPL(da9052_free_irq);
+
+static irqreturn_t da9052_auxadc_irq(int irq, void *irq_data)
+{
+	struct da9052 *da9052 = irq_data;
+
+	complete(&da9052->done);
+
+	return IRQ_HANDLED;
+}
+
+int da9052_irq_init(struct da9052 *da9052)
+{
+	int ret;
+
+	ret = regmap_add_irq_chip(da9052->regmap, da9052->chip_irq,
+				  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+				  -1, &da9052_regmap_irq_chip,
+				  &da9052->irq_data);
+	if (ret < 0) {
+		dev_err(da9052->dev, "regmap_add_irq_chip failed: %d\n", ret);
+		goto regmap_err;
+	}
+
+	ret = da9052_request_irq(da9052, DA9052_IRQ_ADC_EOM, "adc-irq",
+			    da9052_auxadc_irq, da9052);
+
+	if (ret != 0) {
+		dev_err(da9052->dev, "DA9052_IRQ_ADC_EOM failed: %d\n", ret);
+		goto request_irq_err;
+	}
+
+	return 0;
+
+request_irq_err:
+	regmap_del_irq_chip(da9052->chip_irq, da9052->irq_data);
+regmap_err:
+	return ret;
+
+}
+
+int da9052_irq_exit(struct da9052 *da9052)
+{
+	da9052_free_irq(da9052, DA9052_IRQ_ADC_EOM , da9052);
+	regmap_del_irq_chip(da9052->chip_irq, da9052->irq_data);
+
+	return 0;
+}
diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c
index dbeadc5..61d63b9 100644
--- a/drivers/mfd/da9052-spi.c
+++ b/drivers/mfd/da9052-spi.c
@@ -21,7 +21,7 @@
 
 #include <linux/mfd/da9052/da9052.h>
 
-static int __devinit da9052_spi_probe(struct spi_device *spi)
+static int da9052_spi_probe(struct spi_device *spi)
 {
 	int ret;
 	const struct spi_device_id *id = spi_get_device_id(spi);
@@ -58,7 +58,7 @@ static int __devinit da9052_spi_probe(struct spi_device *spi)
 	return 0;
 }
 
-static int __devexit da9052_spi_remove(struct spi_device *spi)
+static int da9052_spi_remove(struct spi_device *spi)
 {
 	struct da9052 *da9052 = dev_get_drvdata(&spi->dev);
 
@@ -76,7 +76,7 @@ static struct spi_device_id da9052_spi_id[] = {
 
 static struct spi_driver da9052_spi_driver = {
 	.probe = da9052_spi_probe,
-	.remove = __devexit_p(da9052_spi_remove),
+	.remove = da9052_spi_remove,
 	.id_table = da9052_spi_id,
 	.driver = {
 		.name = "da9052",
diff --git a/drivers/mfd/da9055-core.c b/drivers/mfd/da9055-core.c
index ff6c77f3..f56a1a9 100644
--- a/drivers/mfd/da9055-core.c
+++ b/drivers/mfd/da9055-core.c
@@ -377,7 +377,7 @@ static struct regmap_irq_chip da9055_regmap_irq_chip = {
 	.num_irqs = ARRAY_SIZE(da9055_irqs),
 };
 
-int __devinit da9055_device_init(struct da9055 *da9055)
+int da9055_device_init(struct da9055 *da9055)
 {
 	struct da9055_pdata *pdata = da9055->dev->platform_data;
 	int ret;
@@ -412,7 +412,7 @@ err:
 	return ret;
 }
 
-void __devexit da9055_device_exit(struct da9055 *da9055)
+void da9055_device_exit(struct da9055 *da9055)
 {
 	regmap_del_irq_chip(da9055->chip_irq, da9055->irq_data);
 	mfd_remove_devices(da9055->dev);
diff --git a/drivers/mfd/da9055-i2c.c b/drivers/mfd/da9055-i2c.c
index 88f6dca..607387f 100644
--- a/drivers/mfd/da9055-i2c.c
+++ b/drivers/mfd/da9055-i2c.c
@@ -18,7 +18,7 @@
 
 #include <linux/mfd/da9055/core.h>
 
-static int __devinit da9055_i2c_probe(struct i2c_client *i2c,
+static int da9055_i2c_probe(struct i2c_client *i2c,
 				      const struct i2c_device_id *id)
 {
 	struct da9055 *da9055;
@@ -44,7 +44,7 @@ static int __devinit da9055_i2c_probe(struct i2c_client *i2c,
 	return da9055_device_init(da9055);
 }
 
-static int __devexit da9055_i2c_remove(struct i2c_client *i2c)
+static int da9055_i2c_remove(struct i2c_client *i2c)
 {
 	struct da9055 *da9055 = i2c_get_clientdata(i2c);
 
@@ -60,7 +60,7 @@ static struct i2c_device_id da9055_i2c_id[] = {
 
 static struct i2c_driver da9055_i2c_driver = {
 	.probe = da9055_i2c_probe,
-	.remove = __devexit_p(da9055_i2c_remove),
+	.remove = da9055_i2c_remove,
 	.id_table = da9055_i2c_id,
 	.driver = {
 		.name = "da9055",
diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c
index 45e83a6..c0bcc87 100644
--- a/drivers/mfd/davinci_voicecodec.c
+++ b/drivers/mfd/davinci_voicecodec.c
@@ -151,7 +151,7 @@ fail1:
 	return ret;
 }
 
-static int __devexit davinci_vc_remove(struct platform_device *pdev)
+static int davinci_vc_remove(struct platform_device *pdev)
 {
 	struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
 
@@ -174,7 +174,7 @@ static struct platform_driver davinci_vc_driver = {
 		.name = "davinci_voicecodec",
 		.owner = THIS_MODULE,
 	},
-	.remove	= __devexit_p(davinci_vc_remove),
+	.remove	= davinci_vc_remove,
 };
 
 static int __init davinci_vc_init(void)
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 00b8b0f..dc8826d 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -31,6 +31,7 @@
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/regulator/db8500-prcmu.h>
 #include <linux/regulator/machine.h>
+#include <linux/cpufreq.h>
 #include <asm/hardware/gic.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
@@ -420,9 +421,6 @@ static struct {
 
 static atomic_t ac_wake_req_state = ATOMIC_INIT(0);
 
-/* Functions definition */
-static void compute_armss_rate(void);
-
 /* Spinlocks */
 static DEFINE_SPINLOCK(prcmu_lock);
 static DEFINE_SPINLOCK(clkout_lock);
@@ -1019,7 +1017,6 @@ int db8500_prcmu_set_arm_opp(u8 opp)
 		(mb1_transfer.ack.arm_opp != opp))
 		r = -EIO;
 
-	compute_armss_rate();
 	mutex_unlock(&mb1_transfer.lock);
 
 	return r;
@@ -1169,12 +1166,12 @@ int db8500_prcmu_get_ape_opp(void)
 }
 
 /**
- * prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage
+ * db8500_prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage
  * @enable: true to request the higher voltage, false to drop a request.
  *
  * Calls to this function to enable and disable requests must be balanced.
  */
-int prcmu_request_ape_opp_100_voltage(bool enable)
+int db8500_prcmu_request_ape_opp_100_voltage(bool enable)
 {
 	int r = 0;
 	u8 header;
@@ -1669,13 +1666,8 @@ static unsigned long clock_rate(u8 clock)
 	else
 		return 0;
 }
-static unsigned long latest_armss_rate;
-static unsigned long armss_rate(void)
-{
-	return latest_armss_rate;
-}
 
-static void compute_armss_rate(void)
+static unsigned long armss_rate(void)
 {
 	u32 r;
 	unsigned long rate;
@@ -1700,7 +1692,7 @@ static void compute_armss_rate(void)
 		rate = pll_rate(PRCM_PLLARM_FREQ, ROOT_CLOCK_RATE, PLL_DIV);
 	}
 
-	latest_armss_rate = rate;
+	return rate;
 }
 
 static unsigned long dsiclk_rate(u8 n)
@@ -1820,6 +1812,35 @@ static long round_clock_rate(u8 clock, unsigned long rate)
 	return rounded_rate;
 }
 
+/* CPU FREQ table, may be changed due to if MAX_OPP is supported. */
+static struct cpufreq_frequency_table db8500_cpufreq_table[] = {
+	{ .frequency = 200000, .index = ARM_EXTCLK,},
+	{ .frequency = 400000, .index = ARM_50_OPP,},
+	{ .frequency = 800000, .index = ARM_100_OPP,},
+	{ .frequency = CPUFREQ_TABLE_END,}, /* To be used for MAX_OPP. */
+	{ .frequency = CPUFREQ_TABLE_END,},
+};
+
+static long round_armss_rate(unsigned long rate)
+{
+	long freq = 0;
+	int i = 0;
+
+	/* cpufreq table frequencies is in KHz. */
+	rate = rate / 1000;
+
+	/* Find the corresponding arm opp from the cpufreq table. */
+	while (db8500_cpufreq_table[i].frequency != CPUFREQ_TABLE_END) {
+		freq = db8500_cpufreq_table[i].frequency;
+		if (freq == rate)
+			break;
+		i++;
+	}
+
+	/* Return the last valid value, even if a match was not found. */
+	return freq * 1000;
+}
+
 #define MIN_PLL_VCO_RATE 600000000ULL
 #define MAX_PLL_VCO_RATE 1680640000ULL
 
@@ -1891,6 +1912,8 @@ long prcmu_round_clock_rate(u8 clock, unsigned long rate)
 {
 	if (clock < PRCMU_NUM_REG_CLOCKS)
 		return round_clock_rate(clock, rate);
+	else if (clock == PRCMU_ARMSS)
+		return round_armss_rate(rate);
 	else if (clock == PRCMU_PLLDSI)
 		return round_plldsi_rate(rate);
 	else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
@@ -1950,6 +1973,27 @@ static void set_clock_rate(u8 clock, unsigned long rate)
 	spin_unlock_irqrestore(&clk_mgt_lock, flags);
 }
 
+static int set_armss_rate(unsigned long rate)
+{
+	int i = 0;
+
+	/* cpufreq table frequencies is in KHz. */
+	rate = rate / 1000;
+
+	/* Find the corresponding arm opp from the cpufreq table. */
+	while (db8500_cpufreq_table[i].frequency != CPUFREQ_TABLE_END) {
+		if (db8500_cpufreq_table[i].frequency == rate)
+			break;
+		i++;
+	}
+
+	if (db8500_cpufreq_table[i].frequency != rate)
+		return -EINVAL;
+
+	/* Set the new arm opp. */
+	return db8500_prcmu_set_arm_opp(db8500_cpufreq_table[i].index);
+}
+
 static int set_plldsi_rate(unsigned long rate)
 {
 	unsigned long src_rate;
@@ -2030,6 +2074,8 @@ int prcmu_set_clock_rate(u8 clock, unsigned long rate)
 {
 	if (clock < PRCMU_NUM_REG_CLOCKS)
 		set_clock_rate(clock, rate);
+	else if (clock == PRCMU_ARMSS)
+		return set_armss_rate(rate);
 	else if (clock == PRCMU_PLLDSI)
 		return set_plldsi_rate(rate);
 	else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
@@ -2697,9 +2743,15 @@ static struct irq_domain_ops db8500_irq_ops = {
 
 static int db8500_irq_init(struct device_node *np)
 {
-	db8500_irq_domain = irq_domain_add_legacy(
-		np, NUM_PRCMU_WAKEUPS, IRQ_PRCMU_BASE,
-		0, &db8500_irq_ops, NULL);
+	int irq_base = -1;
+
+	/* In the device tree case, just take some IRQs */
+	if (!np)
+		irq_base = IRQ_PRCMU_BASE;
+
+	db8500_irq_domain = irq_domain_add_simple(
+		np, NUM_PRCMU_WAKEUPS, irq_base,
+		&db8500_irq_ops, NULL);
 
 	if (!db8500_irq_domain) {
 		pr_err("Failed to create irqdomain\n");
@@ -2711,7 +2763,7 @@ static int db8500_irq_init(struct device_node *np)
 
 void __init db8500_prcmu_early_init(void)
 {
-	if (cpu_is_u8500v2()) {
+	if (cpu_is_u8500v2() || cpu_is_u9540()) {
 		void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K);
 
 		if (tcpm_base != NULL) {
@@ -2729,7 +2781,11 @@ void __init db8500_prcmu_early_init(void)
 			iounmap(tcpm_base);
 		}
 
-		tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE);
+		if (cpu_is_u9540())
+			tcdm_base = ioremap_nocache(U8500_PRCMU_TCDM_BASE,
+						SZ_4K + SZ_8K) + SZ_8K;
+		else
+			tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE);
 	} else {
 		pr_err("prcmu: Unsupported chip version\n");
 		BUG();
@@ -2754,8 +2810,6 @@ void __init db8500_prcmu_early_init(void)
 	init_completion(&mb5_transfer.work);
 
 	INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
-
-	compute_armss_rate();
 }
 
 static void __init init_prcm_registers(void)
@@ -3020,6 +3074,8 @@ static struct mfd_cell db8500_prcmu_devs[] = {
 	{
 		.name = "cpufreq-u8500",
 		.of_compatible = "stericsson,cpufreq-u8500",
+		.platform_data = &db8500_cpufreq_table,
+		.pdata_size = sizeof(db8500_cpufreq_table),
 	},
 	{
 		.name = "ab8500-core",
@@ -3030,11 +3086,19 @@ static struct mfd_cell db8500_prcmu_devs[] = {
 	},
 };
 
+static void db8500_prcmu_update_cpufreq(void)
+{
+	if (prcmu_has_arm_maxopp()) {
+		db8500_cpufreq_table[3].frequency = 1000000;
+		db8500_cpufreq_table[3].index = ARM_MAX_OPP;
+	}
+}
+
 /**
  * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic
  *
  */
-static int __devinit db8500_prcmu_probe(struct platform_device *pdev)
+static int db8500_prcmu_probe(struct platform_device *pdev)
 {
 	struct ab8500_platform_data *ab8500_platdata = pdev->dev.platform_data;
 	struct device_node *np = pdev->dev.of_node;
@@ -3074,6 +3138,8 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev)
 	if (cpu_is_u8500v20_or_later())
 		prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
 
+	db8500_prcmu_update_cpufreq();
+
 	err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs,
 			      ARRAY_SIZE(db8500_prcmu_devs), NULL, 0, NULL);
 	if (err) {
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
index db662e2..b7a61f0 100644
--- a/drivers/mfd/ezx-pcap.c
+++ b/drivers/mfd/ezx-pcap.c
@@ -371,7 +371,7 @@ static int pcap_remove_subdev(struct device *dev, void *unused)
 	return 0;
 }
 
-static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
+static int pcap_add_subdev(struct pcap_chip *pcap,
 						struct pcap_subdev *subdev)
 {
 	struct platform_device *pdev;
@@ -391,7 +391,7 @@ static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
 	return ret;
 }
 
-static int __devexit ezx_pcap_remove(struct spi_device *spi)
+static int ezx_pcap_remove(struct spi_device *spi)
 {
 	struct pcap_chip *pcap = dev_get_drvdata(&spi->dev);
 	struct pcap_platform_data *pdata = spi->dev.platform_data;
@@ -420,7 +420,7 @@ static int __devexit ezx_pcap_remove(struct spi_device *spi)
 	return 0;
 }
 
-static int __devinit ezx_pcap_probe(struct spi_device *spi)
+static int ezx_pcap_probe(struct spi_device *spi)
 {
 	struct pcap_platform_data *pdata = spi->dev.platform_data;
 	struct pcap_chip *pcap;
@@ -525,7 +525,7 @@ ret:
 
 static struct spi_driver ezxpcap_driver = {
 	.probe	= ezx_pcap_probe,
-	.remove = __devexit_p(ezx_pcap_remove),
+	.remove = ezx_pcap_remove,
 	.driver = {
 		.name	= "ezx-pcap",
 		.owner	= THIS_MODULE,
diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c
index d55065c..324187c 100644
--- a/drivers/mfd/htc-i2cpld.c
+++ b/drivers/mfd/htc-i2cpld.c
@@ -327,7 +327,7 @@ static void htcpld_chip_reset(struct i2c_client *client)
 		client, (chip_data->cache_out = chip_data->reset));
 }
 
-static int __devinit htcpld_setup_chip_irq(
+static int htcpld_setup_chip_irq(
 		struct platform_device *pdev,
 		int chip_index)
 {
@@ -361,7 +361,7 @@ static int __devinit htcpld_setup_chip_irq(
 	return ret;
 }
 
-static int __devinit htcpld_register_chip_i2c(
+static int htcpld_register_chip_i2c(
 		struct platform_device *pdev,
 		int chip_index)
 {
@@ -419,7 +419,7 @@ static int __devinit htcpld_register_chip_i2c(
 	return 0;
 }
 
-static void __devinit htcpld_unregister_chip_i2c(
+static void htcpld_unregister_chip_i2c(
 		struct platform_device *pdev,
 		int chip_index)
 {
@@ -434,7 +434,7 @@ static void __devinit htcpld_unregister_chip_i2c(
 		i2c_unregister_device(chip->client);
 }
 
-static int __devinit htcpld_register_chip_gpio(
+static int htcpld_register_chip_gpio(
 		struct platform_device *pdev,
 		int chip_index)
 {
@@ -501,7 +501,7 @@ static int __devinit htcpld_register_chip_gpio(
 	return 0;
 }
 
-static int __devinit htcpld_setup_chips(struct platform_device *pdev)
+static int htcpld_setup_chips(struct platform_device *pdev)
 {
 	struct htcpld_data *htcpld;
 	struct device *dev = &pdev->dev;
@@ -563,7 +563,7 @@ static int __devinit htcpld_setup_chips(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devinit htcpld_core_probe(struct platform_device *pdev)
+static int htcpld_core_probe(struct platform_device *pdev)
 {
 	struct htcpld_data *htcpld;
 	struct device *dev = &pdev->dev;
diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c
index 266bdc5..ab8d0b2 100644
--- a/drivers/mfd/intel_msic.c
+++ b/drivers/mfd/intel_msic.c
@@ -306,7 +306,7 @@ int intel_msic_irq_read(struct intel_msic *msic, unsigned short reg, u8 *val)
 }
 EXPORT_SYMBOL_GPL(intel_msic_irq_read);
 
-static int __devinit intel_msic_init_devices(struct intel_msic *msic)
+static int intel_msic_init_devices(struct intel_msic *msic)
 {
 	struct platform_device *pdev = msic->pdev;
 	struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
@@ -364,7 +364,7 @@ fail:
 	return ret;
 }
 
-static void __devexit intel_msic_remove_devices(struct intel_msic *msic)
+static void intel_msic_remove_devices(struct intel_msic *msic)
 {
 	struct platform_device *pdev = msic->pdev;
 	struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
@@ -375,7 +375,7 @@ static void __devexit intel_msic_remove_devices(struct intel_msic *msic)
 		gpio_free(pdata->ocd->gpio);
 }
 
-static int __devinit intel_msic_probe(struct platform_device *pdev)
+static int intel_msic_probe(struct platform_device *pdev)
 {
 	struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
 	struct intel_msic *msic;
@@ -445,7 +445,7 @@ static int __devinit intel_msic_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit intel_msic_remove(struct platform_device *pdev)
+static int intel_msic_remove(struct platform_device *pdev)
 {
 	struct intel_msic *msic = platform_get_drvdata(pdev);
 
@@ -457,7 +457,7 @@ static int __devexit intel_msic_remove(struct platform_device *pdev)
 
 static struct platform_driver intel_msic_driver = {
 	.probe		= intel_msic_probe,
-	.remove		= __devexit_p(intel_msic_remove),
+	.remove		= intel_msic_remove,
 	.driver		= {
 		.name	= "intel_msic",
 		.owner	= THIS_MODULE,
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c
index 965c480..45ece11 100644
--- a/drivers/mfd/janz-cmodio.c
+++ b/drivers/mfd/janz-cmodio.c
@@ -63,7 +63,7 @@ struct cmodio_device {
  * Subdevices using the mfd-core API
  */
 
-static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv,
+static int cmodio_setup_subdevice(struct cmodio_device *priv,
 					    char *name, unsigned int devno,
 					    unsigned int modno)
 {
@@ -120,7 +120,7 @@ static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv,
 }
 
 /* Probe each submodule using kernel parameters */
-static int __devinit cmodio_probe_submodules(struct cmodio_device *priv)
+static int cmodio_probe_submodules(struct cmodio_device *priv)
 {
 	struct pci_dev *pdev = priv->pdev;
 	unsigned int num_probed = 0;
@@ -177,7 +177,7 @@ static const struct attribute_group cmodio_sysfs_attr_group = {
  * PCI Driver
  */
 
-static int __devinit cmodio_pci_probe(struct pci_dev *dev,
+static int cmodio_pci_probe(struct pci_dev *dev,
 				      const struct pci_device_id *id)
 {
 	struct cmodio_device *priv;
@@ -254,7 +254,7 @@ out_return:
 	return ret;
 }
 
-static void __devexit cmodio_pci_remove(struct pci_dev *dev)
+static void cmodio_pci_remove(struct pci_dev *dev)
 {
 	struct cmodio_device *priv = pci_get_drvdata(dev);
 
@@ -280,7 +280,7 @@ static struct pci_driver cmodio_pci_driver = {
 	.name     = DRV_NAME,
 	.id_table = cmodio_pci_ids,
 	.probe    = cmodio_pci_probe,
-	.remove   = __devexit_p(cmodio_pci_remove),
+	.remove   = cmodio_pci_remove,
 };
 
 module_pci_driver(cmodio_pci_driver);
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c
index c6b6d7d..e80587f 100644
--- a/drivers/mfd/jz4740-adc.c
+++ b/drivers/mfd/jz4740-adc.c
@@ -202,7 +202,7 @@ static struct mfd_cell jz4740_adc_cells[] = {
 	},
 };
 
-static int __devinit jz4740_adc_probe(struct platform_device *pdev)
+static int jz4740_adc_probe(struct platform_device *pdev)
 {
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
@@ -211,7 +211,7 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev)
 	int ret;
 	int irq_base;
 
-	adc = kmalloc(sizeof(*adc), GFP_KERNEL);
+	adc = devm_kzalloc(&pdev->dev, sizeof(*adc), GFP_KERNEL);
 	if (!adc) {
 		dev_err(&pdev->dev, "Failed to allocate driver structure\n");
 		return -ENOMEM;
@@ -221,30 +221,27 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev)
 	if (adc->irq < 0) {
 		ret = adc->irq;
 		dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
-		goto err_free;
+		return ret;
 	}
 
 	irq_base = platform_get_irq(pdev, 1);
 	if (irq_base < 0) {
-		ret = irq_base;
-		dev_err(&pdev->dev, "Failed to get irq base: %d\n", ret);
-		goto err_free;
+		dev_err(&pdev->dev, "Failed to get irq base: %d\n", irq_base);
+		return irq_base;
 	}
 
 	mem_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem_base) {
-		ret = -ENOENT;
 		dev_err(&pdev->dev, "Failed to get platform mmio resource\n");
-		goto err_free;
+		return -ENOENT;
 	}
 
 	/* Only request the shared registers for the MFD driver */
 	adc->mem = request_mem_region(mem_base->start, JZ_REG_ADC_STATUS,
 					pdev->name);
 	if (!adc->mem) {
-		ret = -EBUSY;
 		dev_err(&pdev->dev, "Failed to request mmio memory region\n");
-		goto err_free;
+		return -EBUSY;
 	}
 
 	adc->base = ioremap_nocache(adc->mem->start, resource_size(adc->mem));
@@ -301,13 +298,10 @@ err_iounmap:
 	iounmap(adc->base);
 err_release_mem_region:
 	release_mem_region(adc->mem->start, resource_size(adc->mem));
-err_free:
-	kfree(adc);
-
 	return ret;
 }
 
-static int __devexit jz4740_adc_remove(struct platform_device *pdev)
+static int jz4740_adc_remove(struct platform_device *pdev)
 {
 	struct jz4740_adc *adc = platform_get_drvdata(pdev);
 
@@ -325,14 +319,12 @@ static int __devexit jz4740_adc_remove(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, NULL);
 
-	kfree(adc);
-
 	return 0;
 }
 
 static struct platform_driver jz4740_adc_driver = {
 	.probe	= jz4740_adc_probe,
-	.remove = __devexit_p(jz4740_adc_remove),
+	.remove = jz4740_adc_remove,
 	.driver = {
 		.name = "jz4740-adc",
 		.owner = THIS_MODULE,
diff --git a/drivers/mfd/lm3533-core.c b/drivers/mfd/lm3533-core.c
index 24212f4..ceebf2c 100644
--- a/drivers/mfd/lm3533-core.c
+++ b/drivers/mfd/lm3533-core.c
@@ -382,7 +382,7 @@ static struct attribute_group lm3533_attribute_group = {
 	.attrs		= lm3533_attributes
 };
 
-static int __devinit lm3533_device_als_init(struct lm3533 *lm3533)
+static int lm3533_device_als_init(struct lm3533 *lm3533)
 {
 	struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
 	int ret;
@@ -405,7 +405,7 @@ static int __devinit lm3533_device_als_init(struct lm3533 *lm3533)
 	return 0;
 }
 
-static int __devinit lm3533_device_bl_init(struct lm3533 *lm3533)
+static int lm3533_device_bl_init(struct lm3533 *lm3533)
 {
 	struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
 	int i;
@@ -434,7 +434,7 @@ static int __devinit lm3533_device_bl_init(struct lm3533 *lm3533)
 	return 0;
 }
 
-static int __devinit lm3533_device_led_init(struct lm3533 *lm3533)
+static int lm3533_device_led_init(struct lm3533 *lm3533)
 {
 	struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
 	int i;
@@ -463,7 +463,7 @@ static int __devinit lm3533_device_led_init(struct lm3533 *lm3533)
 	return 0;
 }
 
-static int __devinit lm3533_device_setup(struct lm3533 *lm3533,
+static int lm3533_device_setup(struct lm3533 *lm3533,
 					struct lm3533_platform_data *pdata)
 {
 	int ret;
@@ -479,7 +479,7 @@ static int __devinit lm3533_device_setup(struct lm3533 *lm3533,
 	return 0;
 }
 
-static int __devinit lm3533_device_init(struct lm3533 *lm3533)
+static int lm3533_device_init(struct lm3533 *lm3533)
 {
 	struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
 	int ret;
@@ -534,7 +534,7 @@ err_disable:
 	return ret;
 }
 
-static void __devexit lm3533_device_exit(struct lm3533 *lm3533)
+static void lm3533_device_exit(struct lm3533 *lm3533)
 {
 	dev_dbg(lm3533->dev, "%s\n", __func__);
 
@@ -596,7 +596,7 @@ static struct regmap_config regmap_config = {
 	.precious_reg	= lm3533_precious_register,
 };
 
-static int __devinit lm3533_i2c_probe(struct i2c_client *i2c,
+static int lm3533_i2c_probe(struct i2c_client *i2c,
 					const struct i2c_device_id *id)
 {
 	struct lm3533 *lm3533;
@@ -624,7 +624,7 @@ static int __devinit lm3533_i2c_probe(struct i2c_client *i2c,
 	return 0;
 }
 
-static int __devexit lm3533_i2c_remove(struct i2c_client *i2c)
+static int lm3533_i2c_remove(struct i2c_client *i2c)
 {
 	struct lm3533 *lm3533 = i2c_get_clientdata(i2c);
 
@@ -648,7 +648,7 @@ static struct i2c_driver lm3533_i2c_driver = {
 	},
 	.id_table	= lm3533_i2c_ids,
 	.probe		= lm3533_i2c_probe,
-	.remove		= __devexit_p(lm3533_i2c_remove),
+	.remove		= lm3533_i2c_remove,
 };
 
 static int __init lm3533_i2c_init(void)
diff --git a/drivers/mfd/lp8788.c b/drivers/mfd/lp8788.c
index 3e94a69..c3d3c9b 100644
--- a/drivers/mfd/lp8788.c
+++ b/drivers/mfd/lp8788.c
@@ -203,7 +203,7 @@ static int lp8788_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 			       ARRAY_SIZE(lp8788_devs), NULL, 0, NULL);
 }
 
-static int __devexit lp8788_remove(struct i2c_client *cl)
+static int lp8788_remove(struct i2c_client *cl)
 {
 	struct lp8788 *lp = i2c_get_clientdata(cl);
 
@@ -224,7 +224,7 @@ static struct i2c_driver lp8788_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = lp8788_probe,
-	.remove = __devexit_p(lp8788_remove),
+	.remove = lp8788_remove,
 	.id_table = lp8788_ids,
 };
 
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index a22544f..d9d9303 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -196,7 +196,7 @@ enum lpc_chipsets {
 	LPC_LPT_LP,	/* Lynx Point-LP */
 };
 
-struct lpc_ich_info lpc_chipset_info[] __devinitdata = {
+struct lpc_ich_info lpc_chipset_info[] = {
 	[LPC_ICH] = {
 		.name = "ICH",
 		.iTCO_version = 1,
@@ -672,7 +672,7 @@ static void lpc_ich_restore_config_space(struct pci_dev *dev)
 	}
 }
 
-static void __devinit lpc_ich_enable_acpi_space(struct pci_dev *dev)
+static void lpc_ich_enable_acpi_space(struct pci_dev *dev)
 {
 	u8 reg_save;
 
@@ -681,7 +681,7 @@ static void __devinit lpc_ich_enable_acpi_space(struct pci_dev *dev)
 	lpc_ich_acpi_save = reg_save;
 }
 
-static void __devinit lpc_ich_enable_gpio_space(struct pci_dev *dev)
+static void lpc_ich_enable_gpio_space(struct pci_dev *dev)
 {
 	u8 reg_save;
 
@@ -690,7 +690,7 @@ static void __devinit lpc_ich_enable_gpio_space(struct pci_dev *dev)
 	lpc_ich_gpio_save = reg_save;
 }
 
-static void __devinit lpc_ich_finalize_cell(struct mfd_cell *cell,
+static void lpc_ich_finalize_cell(struct mfd_cell *cell,
 					const struct pci_device_id *id)
 {
 	cell->platform_data = &lpc_chipset_info[id->driver_data];
@@ -702,7 +702,7 @@ static void __devinit lpc_ich_finalize_cell(struct mfd_cell *cell,
  * GPIO groups and it's enough to have access to one of these to instantiate
  * the device.
  */
-static int __devinit lpc_ich_check_conflict_gpio(struct resource *res)
+static int lpc_ich_check_conflict_gpio(struct resource *res)
 {
 	int ret;
 	u8 use_gpio = 0;
@@ -721,7 +721,7 @@ static int __devinit lpc_ich_check_conflict_gpio(struct resource *res)
 	return use_gpio ? use_gpio : ret;
 }
 
-static int __devinit lpc_ich_init_gpio(struct pci_dev *dev,
+static int lpc_ich_init_gpio(struct pci_dev *dev,
 				const struct pci_device_id *id)
 {
 	u32 base_addr_cfg;
@@ -734,7 +734,7 @@ static int __devinit lpc_ich_init_gpio(struct pci_dev *dev,
 	pci_read_config_dword(dev, ACPIBASE, &base_addr_cfg);
 	base_addr = base_addr_cfg & 0x0000ff80;
 	if (!base_addr) {
-		dev_err(&dev->dev, "I/O space for ACPI uninitialized\n");
+		dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n");
 		lpc_ich_cells[LPC_GPIO].num_resources--;
 		goto gpe0_done;
 	}
@@ -760,7 +760,7 @@ gpe0_done:
 	pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg);
 	base_addr = base_addr_cfg & 0x0000ff80;
 	if (!base_addr) {
-		dev_err(&dev->dev, "I/O space for GPIO uninitialized\n");
+		dev_notice(&dev->dev, "I/O space for GPIO uninitialized\n");
 		ret = -ENODEV;
 		goto gpio_done;
 	}
@@ -798,7 +798,7 @@ gpio_done:
 	return ret;
 }
 
-static int __devinit lpc_ich_init_wdt(struct pci_dev *dev,
+static int lpc_ich_init_wdt(struct pci_dev *dev,
 				const struct pci_device_id *id)
 {
 	u32 base_addr_cfg;
@@ -810,7 +810,7 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev,
 	pci_read_config_dword(dev, ACPIBASE, &base_addr_cfg);
 	base_addr = base_addr_cfg & 0x0000ff80;
 	if (!base_addr) {
-		dev_err(&dev->dev, "I/O space for ACPI uninitialized\n");
+		dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n");
 		ret = -ENODEV;
 		goto wdt_done;
 	}
@@ -830,12 +830,15 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev,
 	 * we have to read RCBA from PCI Config space 0xf0 and use
 	 * it as base. GCS = RCBA + ICH6_GCS(0x3410).
 	 */
-	if (lpc_chipset_info[id->driver_data].iTCO_version == 2) {
+	if (lpc_chipset_info[id->driver_data].iTCO_version == 1) {
+		/* Don't register iomem for TCO ver 1 */
+		lpc_ich_cells[LPC_WDT].num_resources--;
+	} else {
 		pci_read_config_dword(dev, RCBABASE, &base_addr_cfg);
 		base_addr = base_addr_cfg & 0xffffc000;
 		if (!(base_addr_cfg & 1)) {
-			pr_err("RCBA is disabled by hardware/BIOS, "
-					"device disabled\n");
+			dev_notice(&dev->dev, "RCBA is disabled by "
+					"hardware/BIOS, device disabled\n");
 			ret = -ENODEV;
 			goto wdt_done;
 		}
@@ -852,7 +855,7 @@ wdt_done:
 	return ret;
 }
 
-static int __devinit lpc_ich_probe(struct pci_dev *dev,
+static int lpc_ich_probe(struct pci_dev *dev,
 				const struct pci_device_id *id)
 {
 	int ret;
@@ -871,6 +874,7 @@ static int __devinit lpc_ich_probe(struct pci_dev *dev,
 	 * successfully.
 	 */
 	if (!cell_added) {
+		dev_warn(&dev->dev, "No MFD cells added\n");
 		lpc_ich_restore_config_space(dev);
 		return -ENODEV;
 	}
@@ -878,7 +882,7 @@ static int __devinit lpc_ich_probe(struct pci_dev *dev,
 	return 0;
 }
 
-static void __devexit lpc_ich_remove(struct pci_dev *dev)
+static void lpc_ich_remove(struct pci_dev *dev)
 {
 	mfd_remove_devices(&dev->dev);
 	lpc_ich_restore_config_space(dev);
@@ -888,7 +892,7 @@ static struct pci_driver lpc_ich_driver = {
 	.name		= "lpc_ich",
 	.id_table	= lpc_ich_ids,
 	.probe		= lpc_ich_probe,
-	.remove		= __devexit_p(lpc_ich_remove),
+	.remove		= lpc_ich_remove,
 };
 
 static int __init lpc_ich_init(void)
diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c
index f6b9c5c..5624fcb 100644
--- a/drivers/mfd/lpc_sch.c
+++ b/drivers/mfd/lpc_sch.c
@@ -83,7 +83,7 @@ static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = {
 };
 MODULE_DEVICE_TABLE(pci, lpc_sch_ids);
 
-static int __devinit lpc_sch_probe(struct pci_dev *dev,
+static int lpc_sch_probe(struct pci_dev *dev,
 				const struct pci_device_id *id)
 {
 	unsigned int base_addr_cfg;
@@ -164,7 +164,7 @@ out_dev:
 	return ret;
 }
 
-static void __devexit lpc_sch_remove(struct pci_dev *dev)
+static void lpc_sch_remove(struct pci_dev *dev)
 {
 	mfd_remove_devices(&dev->dev);
 }
@@ -173,7 +173,7 @@ static struct pci_driver lpc_sch_driver = {
 	.name		= "lpc_sch",
 	.id_table	= lpc_sch_ids,
 	.probe		= lpc_sch_probe,
-	.remove		= __devexit_p(lpc_sch_remove),
+	.remove		= lpc_sch_remove,
 };
 
 module_pci_driver(lpc_sch_driver);
diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
index d9e24c8..f6878f8 100644
--- a/drivers/mfd/max77686.c
+++ b/drivers/mfd/max77686.c
@@ -45,7 +45,7 @@ static struct regmap_config max77686_regmap_config = {
 };
 
 #ifdef CONFIG_OF
-static struct of_device_id __devinitdata max77686_pmic_dt_match[] = {
+static struct of_device_id max77686_pmic_dt_match[] = {
 	{.compatible = "maxim,max77686",        .data = 0},
 	{},
 };
diff --git a/drivers/mfd/max8907.c b/drivers/mfd/max8907.c
index 17f2593..e9b1c93 100644
--- a/drivers/mfd/max8907.c
+++ b/drivers/mfd/max8907.c
@@ -183,7 +183,7 @@ static void max8907_power_off(void)
 			MAX8907_MASK_POWER_OFF, MAX8907_MASK_POWER_OFF);
 }
 
-static __devinit int max8907_i2c_probe(struct i2c_client *i2c,
+static int max8907_i2c_probe(struct i2c_client *i2c,
 				       const struct i2c_device_id *id)
 {
 	struct max8907 *max8907;
@@ -288,7 +288,7 @@ err_alloc_drvdata:
 	return ret;
 }
 
-static __devexit int max8907_i2c_remove(struct i2c_client *i2c)
+static int max8907_i2c_remove(struct i2c_client *i2c)
 {
 	struct max8907 *max8907 = i2c_get_clientdata(i2c);
 
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
index 9f54c04..e32466e 100644
--- a/drivers/mfd/max8925-core.c
+++ b/drivers/mfd/max8925-core.c
@@ -19,12 +19,12 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/max8925.h>
 
-static struct resource bk_resources[] __devinitdata = {
+static struct resource bk_resources[] = {
 	{ 0x84, 0x84, "mode control", IORESOURCE_REG, },
 	{ 0x85, 0x85, "control",      IORESOURCE_REG, },
 };
 
-static struct mfd_cell bk_devs[] __devinitdata = {
+static struct mfd_cell bk_devs[] = {
 	{
 		.name		= "max8925-backlight",
 		.num_resources	= ARRAY_SIZE(bk_resources),
@@ -110,99 +110,99 @@ static struct mfd_cell onkey_devs[] = {
 	},
 };
 
-static struct resource sd1_resources[] __devinitdata = {
+static struct resource sd1_resources[] = {
 	{0x06, 0x06, "sdv", IORESOURCE_REG, },
 };
 
-static struct resource sd2_resources[] __devinitdata = {
+static struct resource sd2_resources[] = {
 	{0x09, 0x09, "sdv", IORESOURCE_REG, },
 };
 
-static struct resource sd3_resources[] __devinitdata = {
+static struct resource sd3_resources[] = {
 	{0x0c, 0x0c, "sdv", IORESOURCE_REG, },
 };
 
-static struct resource ldo1_resources[] __devinitdata = {
+static struct resource ldo1_resources[] = {
 	{0x1a, 0x1a, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo2_resources[] __devinitdata = {
+static struct resource ldo2_resources[] = {
 	{0x1e, 0x1e, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo3_resources[] __devinitdata = {
+static struct resource ldo3_resources[] = {
 	{0x22, 0x22, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo4_resources[] __devinitdata = {
+static struct resource ldo4_resources[] = {
 	{0x26, 0x26, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo5_resources[] __devinitdata = {
+static struct resource ldo5_resources[] = {
 	{0x2a, 0x2a, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo6_resources[] __devinitdata = {
+static struct resource ldo6_resources[] = {
 	{0x2e, 0x2e, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo7_resources[] __devinitdata = {
+static struct resource ldo7_resources[] = {
 	{0x32, 0x32, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo8_resources[] __devinitdata = {
+static struct resource ldo8_resources[] = {
 	{0x36, 0x36, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo9_resources[] __devinitdata = {
+static struct resource ldo9_resources[] = {
 	{0x3a, 0x3a, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo10_resources[] __devinitdata = {
+static struct resource ldo10_resources[] = {
 	{0x3e, 0x3e, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo11_resources[] __devinitdata = {
+static struct resource ldo11_resources[] = {
 	{0x42, 0x42, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo12_resources[] __devinitdata = {
+static struct resource ldo12_resources[] = {
 	{0x46, 0x46, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo13_resources[] __devinitdata = {
+static struct resource ldo13_resources[] = {
 	{0x4a, 0x4a, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo14_resources[] __devinitdata = {
+static struct resource ldo14_resources[] = {
 	{0x4e, 0x4e, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo15_resources[] __devinitdata = {
+static struct resource ldo15_resources[] = {
 	{0x52, 0x52, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo16_resources[] __devinitdata = {
+static struct resource ldo16_resources[] = {
 	{0x12, 0x12, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo17_resources[] __devinitdata = {
+static struct resource ldo17_resources[] = {
 	{0x16, 0x16, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo18_resources[] __devinitdata = {
+static struct resource ldo18_resources[] = {
 	{0x74, 0x74, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo19_resources[] __devinitdata = {
+static struct resource ldo19_resources[] = {
 	{0x5e, 0x5e, "ldov", IORESOURCE_REG, },
 };
 
-static struct resource ldo20_resources[] __devinitdata = {
+static struct resource ldo20_resources[] = {
 	{0x9e, 0x9e, "ldov", IORESOURCE_REG, },
 };
 
-static struct mfd_cell reg_devs[] __devinitdata = {
+static struct mfd_cell reg_devs[] = {
 	{
 		.name = "max8925-regulator",
 		.id = 0,
@@ -714,7 +714,7 @@ tsc_irq:
 	return 0;
 }
 
-static void __devinit init_regulator(struct max8925_chip *chip,
+static void init_regulator(struct max8925_chip *chip,
 				     struct max8925_platform_data *pdata)
 {
 	int ret;
@@ -821,7 +821,7 @@ static void __devinit init_regulator(struct max8925_chip *chip,
 	}
 }
 
-int __devinit max8925_device_init(struct max8925_chip *chip,
+int max8925_device_init(struct max8925_chip *chip,
 				  struct max8925_platform_data *pdata)
 {
 	int ret;
@@ -901,7 +901,7 @@ out:
 	return ret;
 }
 
-void __devexit max8925_device_exit(struct max8925_chip *chip)
+void max8925_device_exit(struct max8925_chip *chip)
 {
 	if (chip->core_irq)
 		free_irq(chip->core_irq, chip);
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
index d9e4b36..00b5b45 100644
--- a/drivers/mfd/max8925-i2c.c
+++ b/drivers/mfd/max8925-i2c.c
@@ -135,7 +135,7 @@ static const struct i2c_device_id max8925_id_table[] = {
 };
 MODULE_DEVICE_TABLE(i2c, max8925_id_table);
 
-static int __devinit max8925_probe(struct i2c_client *client,
+static int max8925_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
 	struct max8925_platform_data *pdata = client->dev.platform_data;
@@ -168,7 +168,7 @@ static int __devinit max8925_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int __devexit max8925_remove(struct i2c_client *client)
+static int max8925_remove(struct i2c_client *client)
 {
 	struct max8925_chip *chip = i2c_get_clientdata(client);
 
@@ -210,7 +210,7 @@ static struct i2c_driver max8925_driver = {
 		.pm     = &max8925_pm_ops,
 	},
 	.probe		= max8925_probe,
-	.remove		= __devexit_p(max8925_remove),
+	.remove		= max8925_remove,
 	.id_table	= max8925_id_table,
 };
 
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index f1235170..abd5c80 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -21,8 +21,10 @@
  * This driver is based on max8998.c
  */
 
+#include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/of_irq.h>
 #include <linux/interrupt.h>
 #include <linux/pm_runtime.h>
 #include <linux/module.h>
@@ -47,6 +49,13 @@ static struct mfd_cell max8997_devs[] = {
 	{ .name = "max8997-led", .id = 2 },
 };
 
+#ifdef CONFIG_OF
+static struct of_device_id __devinitdata max8997_pmic_dt_match[] = {
+	{ .compatible = "maxim,max8997-pmic", .data = TYPE_MAX8997 },
+	{},
+};
+#endif
+
 int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
 {
 	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
@@ -123,6 +132,58 @@ int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
 }
 EXPORT_SYMBOL_GPL(max8997_update_reg);
 
+#ifdef CONFIG_OF
+/*
+ * Only the common platform data elements for max8997 are parsed here from the
+ * device tree. Other sub-modules of max8997 such as pmic, rtc and others have
+ * to parse their own platform data elements from device tree.
+ *
+ * The max8997 platform data structure is instantiated here and the drivers for
+ * the sub-modules need not instantiate another instance while parsing their
+ * platform data.
+ */
+static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
+					struct device *dev)
+{
+	struct max8997_platform_data *pd;
+
+	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+	if (!pd) {
+		dev_err(dev, "could not allocate memory for pdata\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pd->ono = irq_of_parse_and_map(dev->of_node, 1);
+
+	/*
+	 * ToDo: the 'wakeup' member in the platform data is more of a linux
+	 * specfic information. Hence, there is no binding for that yet and
+	 * not parsed here.
+	 */
+
+	return pd;
+}
+#else
+static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
+					struct device *dev)
+{
+	return 0;
+}
+#endif
+
+static inline int max8997_i2c_get_driver_data(struct i2c_client *i2c,
+						const struct i2c_device_id *id)
+{
+#ifdef CONFIG_OF
+	if (i2c->dev.of_node) {
+		const struct of_device_id *match;
+		match = of_match_node(max8997_pmic_dt_match, i2c->dev.of_node);
+		return (int)match->data;
+	}
+#endif
+	return (int)id->driver_data;
+}
+
 static int max8997_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
@@ -137,12 +198,21 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
 	i2c_set_clientdata(i2c, max8997);
 	max8997->dev = &i2c->dev;
 	max8997->i2c = i2c;
-	max8997->type = id->driver_data;
+	max8997->type = max8997_i2c_get_driver_data(i2c, id);
 	max8997->irq = i2c->irq;
 
+	if (max8997->dev->of_node) {
+		pdata = max8997_i2c_parse_dt_pdata(max8997->dev);
+		if (IS_ERR(pdata)) {
+			ret = PTR_ERR(pdata);
+			goto err;
+		}
+	}
+
 	if (!pdata)
 		goto err;
 
+	max8997->pdata = pdata;
 	max8997->ono = pdata->ono;
 
 	mutex_init(&max8997->iolock);
@@ -434,6 +504,7 @@ static struct i2c_driver max8997_i2c_driver = {
 		   .name = "max8997",
 		   .owner = THIS_MODULE,
 		   .pm = &max8997_pm,
+		   .of_match_table = of_match_ptr(max8997_pmic_dt_match),
 	},
 	.probe = max8997_i2c_probe,
 	.remove = max8997_i2c_remove,
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index 1aba023..2a9b100 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -119,6 +119,11 @@
 #define MC13XXX_REVISION_FAB		(0x03 << 11)
 #define MC13XXX_REVISION_ICIDCODE	(0x3f << 13)
 
+#define MC34708_REVISION_REVMETAL	(0x07 <<  0)
+#define MC34708_REVISION_REVFULL	(0x07 <<  3)
+#define MC34708_REVISION_FIN		(0x07 <<  6)
+#define MC34708_REVISION_FAB		(0x07 <<  9)
+
 #define MC13XXX_ADC1		44
 #define MC13XXX_ADC1_ADEN		(1 << 0)
 #define MC13XXX_ADC1_RAND		(1 << 1)
@@ -410,62 +415,52 @@ static irqreturn_t mc13xxx_irq_thread(int irq, void *data)
 	return IRQ_RETVAL(handled);
 }
 
-static const char *mc13xxx_chipname[] = {
-	[MC13XXX_ID_MC13783] = "mc13783",
-	[MC13XXX_ID_MC13892] = "mc13892",
-};
-
 #define maskval(reg, mask)	(((reg) & (mask)) >> __ffs(mask))
-static int mc13xxx_identify(struct mc13xxx *mc13xxx)
+static void mc13xxx_print_revision(struct mc13xxx *mc13xxx, u32 revision)
 {
-	u32 icid;
-	u32 revision;
-	int ret;
-
-	/*
-	 * Get the generation ID from register 46, as apparently some older
-	 * IC revisions only have this info at this location. Newer ICs seem to
-	 * have both.
-	 */
-	ret = mc13xxx_reg_read(mc13xxx, 46, &icid);
-	if (ret)
-		return ret;
+	dev_info(mc13xxx->dev, "%s: rev: %d.%d, "
+			"fin: %d, fab: %d, icid: %d/%d\n",
+			mc13xxx->variant->name,
+			maskval(revision, MC13XXX_REVISION_REVFULL),
+			maskval(revision, MC13XXX_REVISION_REVMETAL),
+			maskval(revision, MC13XXX_REVISION_FIN),
+			maskval(revision, MC13XXX_REVISION_FAB),
+			maskval(revision, MC13XXX_REVISION_ICID),
+			maskval(revision, MC13XXX_REVISION_ICIDCODE));
+}
 
-	icid = (icid >> 6) & 0x7;
+static void mc34708_print_revision(struct mc13xxx *mc13xxx, u32 revision)
+{
+	dev_info(mc13xxx->dev, "%s: rev %d.%d, fin: %d, fab: %d\n",
+			mc13xxx->variant->name,
+			maskval(revision, MC34708_REVISION_REVFULL),
+			maskval(revision, MC34708_REVISION_REVMETAL),
+			maskval(revision, MC34708_REVISION_FIN),
+			maskval(revision, MC34708_REVISION_FAB));
+}
 
-	switch (icid) {
-	case 2:
-		mc13xxx->ictype = MC13XXX_ID_MC13783;
-		break;
-	case 7:
-		mc13xxx->ictype = MC13XXX_ID_MC13892;
-		break;
-	default:
-		mc13xxx->ictype = MC13XXX_ID_INVALID;
-		break;
-	}
+/* These are only exported for mc13xxx-i2c and mc13xxx-spi */
+struct mc13xxx_variant mc13xxx_variant_mc13783 = {
+	.name = "mc13783",
+	.print_revision = mc13xxx_print_revision,
+};
+EXPORT_SYMBOL_GPL(mc13xxx_variant_mc13783);
 
-	if (mc13xxx->ictype == MC13XXX_ID_MC13783 ||
-			mc13xxx->ictype == MC13XXX_ID_MC13892) {
-		ret = mc13xxx_reg_read(mc13xxx, MC13XXX_REVISION, &revision);
-
-		dev_info(mc13xxx->dev, "%s: rev: %d.%d, "
-				"fin: %d, fab: %d, icid: %d/%d\n",
-				mc13xxx_chipname[mc13xxx->ictype],
-				maskval(revision, MC13XXX_REVISION_REVFULL),
-				maskval(revision, MC13XXX_REVISION_REVMETAL),
-				maskval(revision, MC13XXX_REVISION_FIN),
-				maskval(revision, MC13XXX_REVISION_FAB),
-				maskval(revision, MC13XXX_REVISION_ICID),
-				maskval(revision, MC13XXX_REVISION_ICIDCODE));
-	}
+struct mc13xxx_variant mc13xxx_variant_mc13892 = {
+	.name = "mc13892",
+	.print_revision = mc13xxx_print_revision,
+};
+EXPORT_SYMBOL_GPL(mc13xxx_variant_mc13892);
 
-	return (mc13xxx->ictype == MC13XXX_ID_INVALID) ? -ENODEV : 0;
-}
+struct mc13xxx_variant mc13xxx_variant_mc34708 = {
+	.name = "mc34708",
+	.print_revision = mc34708_print_revision,
+};
+EXPORT_SYMBOL_GPL(mc13xxx_variant_mc34708);
 
 static const char *mc13xxx_get_chipname(struct mc13xxx *mc13xxx)
 {
-	return mc13xxx_chipname[mc13xxx->ictype];
+	return mc13xxx->variant->name;
 }
 
 int mc13xxx_get_flags(struct mc13xxx *mc13xxx)
@@ -653,13 +648,16 @@ int mc13xxx_common_init(struct mc13xxx *mc13xxx,
 		struct mc13xxx_platform_data *pdata, int irq)
 {
 	int ret;
+	u32 revision;
 
 	mc13xxx_lock(mc13xxx);
 
-	ret = mc13xxx_identify(mc13xxx);
+	ret = mc13xxx_reg_read(mc13xxx, MC13XXX_REVISION, &revision);
 	if (ret)
 		goto err_revision;
 
+	mc13xxx->variant->print_revision(mc13xxx, revision);
+
 	/* mask all irqs */
 	ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK0, 0x00ffffff);
 	if (ret)
diff --git a/drivers/mfd/mc13xxx-i2c.c b/drivers/mfd/mc13xxx-i2c.c
index 9d18dde..f745e27 100644
--- a/drivers/mfd/mc13xxx-i2c.c
+++ b/drivers/mfd/mc13xxx-i2c.c
@@ -24,7 +24,10 @@
 static const struct i2c_device_id mc13xxx_i2c_device_id[] = {
 	{
 		.name = "mc13892",
-		.driver_data = MC13XXX_ID_MC13892,
+		.driver_data = (kernel_ulong_t)&mc13xxx_variant_mc13892,
+	}, {
+		.name = "mc34708",
+		.driver_data = (kernel_ulong_t)&mc13xxx_variant_mc34708,
 	}, {
 		/* sentinel */
 	}
@@ -34,7 +37,10 @@ MODULE_DEVICE_TABLE(i2c, mc13xxx_i2c_device_id);
 static const struct of_device_id mc13xxx_dt_ids[] = {
 	{
 		.compatible = "fsl,mc13892",
-		.data = (void *) &mc13xxx_i2c_device_id[0],
+		.data = &mc13xxx_variant_mc13892,
+	}, {
+		.compatible = "fsl,mc34708",
+		.data = &mc13xxx_variant_mc34708,
 	}, {
 		/* sentinel */
 	}
@@ -76,16 +82,20 @@ static int mc13xxx_i2c_probe(struct i2c_client *client,
 		return ret;
 	}
 
-	ret = mc13xxx_common_init(mc13xxx, pdata, client->irq);
+	if (client->dev.of_node) {
+		const struct of_device_id *of_id =
+			of_match_device(mc13xxx_dt_ids, &client->dev);
+		mc13xxx->variant = of_id->data;
+	} else {
+		mc13xxx->variant = (void *)id->driver_data;
+	}
 
-	if (ret == 0 && (id->driver_data != mc13xxx->ictype))
-		dev_warn(mc13xxx->dev,
-				"device id doesn't match auto detection!\n");
+	ret = mc13xxx_common_init(mc13xxx, pdata, client->irq);
 
 	return ret;
 }
 
-static int __devexit mc13xxx_i2c_remove(struct i2c_client *client)
+static int mc13xxx_i2c_remove(struct i2c_client *client)
 {
 	struct mc13xxx *mc13xxx = dev_get_drvdata(&client->dev);
 
@@ -102,7 +112,7 @@ static struct i2c_driver mc13xxx_i2c_driver = {
 		.of_match_table = mc13xxx_dt_ids,
 	},
 	.probe = mc13xxx_i2c_probe,
-	.remove = __devexit_p(mc13xxx_i2c_remove),
+	.remove = mc13xxx_i2c_remove,
 };
 
 static int __init mc13xxx_i2c_init(void)
diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c
index 0bdb43a..3032bae 100644
--- a/drivers/mfd/mc13xxx-spi.c
+++ b/drivers/mfd/mc13xxx-spi.c
@@ -28,10 +28,13 @@
 static const struct spi_device_id mc13xxx_device_id[] = {
 	{
 		.name = "mc13783",
-		.driver_data = MC13XXX_ID_MC13783,
+		.driver_data = (kernel_ulong_t)&mc13xxx_variant_mc13783,
 	}, {
 		.name = "mc13892",
-		.driver_data = MC13XXX_ID_MC13892,
+		.driver_data = (kernel_ulong_t)&mc13xxx_variant_mc13892,
+	}, {
+		.name = "mc34708",
+		.driver_data = (kernel_ulong_t)&mc13xxx_variant_mc34708,
 	}, {
 		/* sentinel */
 	}
@@ -39,8 +42,9 @@ static const struct spi_device_id mc13xxx_device_id[] = {
 MODULE_DEVICE_TABLE(spi, mc13xxx_device_id);
 
 static const struct of_device_id mc13xxx_dt_ids[] = {
-	{ .compatible = "fsl,mc13783", .data = (void *) MC13XXX_ID_MC13783, },
-	{ .compatible = "fsl,mc13892", .data = (void *) MC13XXX_ID_MC13892, },
+	{ .compatible = "fsl,mc13783", .data = &mc13xxx_variant_mc13783, },
+	{ .compatible = "fsl,mc13892", .data = &mc13xxx_variant_mc13892, },
+	{ .compatible = "fsl,mc34708", .data = &mc13xxx_variant_mc34708, },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, mc13xxx_dt_ids);
@@ -144,22 +148,21 @@ static int mc13xxx_spi_probe(struct spi_device *spi)
 		return ret;
 	}
 
-	ret = mc13xxx_common_init(mc13xxx, pdata, spi->irq);
+	if (spi->dev.of_node) {
+		const struct of_device_id *of_id =
+			of_match_device(mc13xxx_dt_ids, &spi->dev);
 
-	if (ret) {
-		dev_set_drvdata(&spi->dev, NULL);
+		mc13xxx->variant = of_id->data;
 	} else {
-		const struct spi_device_id *devid =
-			spi_get_device_id(spi);
-		if (!devid || devid->driver_data != mc13xxx->ictype)
-			dev_warn(mc13xxx->dev,
-				"device id doesn't match auto detection!\n");
+		const struct spi_device_id *id_entry = spi_get_device_id(spi);
+
+		mc13xxx->variant = (void *)id_entry->driver_data;
 	}
 
-	return ret;
+	return mc13xxx_common_init(mc13xxx, pdata, spi->irq);
 }
 
-static int __devexit mc13xxx_spi_remove(struct spi_device *spi)
+static int mc13xxx_spi_remove(struct spi_device *spi)
 {
 	struct mc13xxx *mc13xxx = dev_get_drvdata(&spi->dev);
 
@@ -176,7 +179,7 @@ static struct spi_driver mc13xxx_spi_driver = {
 		.of_match_table = mc13xxx_dt_ids,
 	},
 	.probe = mc13xxx_spi_probe,
-	.remove = __devexit_p(mc13xxx_spi_remove),
+	.remove = mc13xxx_spi_remove,
 };
 
 static int __init mc13xxx_init(void)
diff --git a/drivers/mfd/mc13xxx.h b/drivers/mfd/mc13xxx.h
index bbba06f..460ec5c 100644
--- a/drivers/mfd/mc13xxx.h
+++ b/drivers/mfd/mc13xxx.h
@@ -13,19 +13,25 @@
 #include <linux/regmap.h>
 #include <linux/mfd/mc13xxx.h>
 
-enum mc13xxx_id {
-	MC13XXX_ID_MC13783,
-	MC13XXX_ID_MC13892,
-	MC13XXX_ID_INVALID,
+#define MC13XXX_NUMREGS 0x3f
+
+struct mc13xxx;
+
+struct mc13xxx_variant {
+	const char *name;
+	void (*print_revision)(struct mc13xxx *mc13xxx, u32 revision);
 };
 
-#define MC13XXX_NUMREGS 0x3f
+extern struct mc13xxx_variant
+		mc13xxx_variant_mc13783,
+		mc13xxx_variant_mc13892,
+		mc13xxx_variant_mc34708;
 
 struct mc13xxx {
 	struct regmap *regmap;
 
 	struct device *dev;
-	enum mc13xxx_id ictype;
+	const struct mc13xxx_variant *variant;
 
 	struct mutex lock;
 	int irq;
diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c
index 55d5899..998ce8c 100644
--- a/drivers/mfd/menelaus.c
+++ b/drivers/mfd/menelaus.c
@@ -41,11 +41,11 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 #include <linux/slab.h>
+#include <linux/mfd/menelaus.h>
 
 #include <asm/mach/irq.h>
 
 #include <asm/gpio.h>
-#include <plat/menelaus.h>
 
 #define DRIVER_NAME			"menelaus"
 
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index f8b7771..7604f4e 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -21,6 +21,10 @@
 #include <linux/irqdomain.h>
 #include <linux/of.h>
 
+static struct device_type mfd_dev_type = {
+	.name	= "mfd_device",
+};
+
 int mfd_cell_enable(struct platform_device *pdev)
 {
 	const struct mfd_cell *cell = mfd_get_cell(pdev);
@@ -91,6 +95,7 @@ static int mfd_add_device(struct device *parent, int id,
 		goto fail_device;
 
 	pdev->dev.parent = parent;
+	pdev->dev.type = &mfd_dev_type;
 
 	if (parent->of_node && cell->of_compatible) {
 		for_each_child_of_node(parent->of_node, np) {
@@ -204,10 +209,16 @@ EXPORT_SYMBOL(mfd_add_devices);
 
 static int mfd_remove_devices_fn(struct device *dev, void *c)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	const struct mfd_cell *cell = mfd_get_cell(pdev);
+	struct platform_device *pdev;
+	const struct mfd_cell *cell;
 	atomic_t **usage_count = c;
 
+	if (dev->type != &mfd_dev_type)
+		return 0;
+
+	pdev = to_platform_device(dev);
+	cell = mfd_get_cell(pdev);
+
 	/* find the base address of usage_count pointers (for freeing) */
 	if (!*usage_count || (cell->usage_count < *usage_count))
 		*usage_count = cell->usage_count;
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 23cec57..770a0d0 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -26,9 +26,12 @@
 #include <linux/spinlock.h>
 #include <linux/gpio.h>
 #include <plat/cpu.h>
-#include <plat/usb.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/usb-omap.h>
 #include <linux/pm_runtime.h>
 
+#include "omap-usb.h"
+
 #define USBHS_DRIVER_NAME	"usbhs_omap"
 #define OMAP_EHCI_DEVICE	"ehci-omap"
 #define OMAP_OHCI_DEVICE	"ohci-omap3"
@@ -464,7 +467,7 @@ static void omap_usbhs_deinit(struct device *dev)
  *
  * Allocates basic resources for this USB host controller.
  */
-static int __devinit usbhs_omap_probe(struct platform_device *pdev)
+static int usbhs_omap_probe(struct platform_device *pdev)
 {
 	struct device			*dev =  &pdev->dev;
 	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
@@ -652,7 +655,7 @@ end_probe:
  *
  * Reverses the effect of usbhs_omap_probe().
  */
-static int __devexit usbhs_omap_remove(struct platform_device *pdev)
+static int usbhs_omap_remove(struct platform_device *pdev)
 {
 	struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
 
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index 4b7757b..eb86915 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -25,8 +25,8 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/err.h>
-#include <plat/usb.h>
 #include <linux/pm_runtime.h>
+#include <linux/platform_data/usb-omap.h>
 
 #define USBTLL_DRIVER_NAME	"usbhs_tll"
 
@@ -200,7 +200,7 @@ static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode)
  *
  * Allocates basic resources for this USB host controller.
  */
-static int __devinit usbtll_omap_probe(struct platform_device *pdev)
+static int usbtll_omap_probe(struct platform_device *pdev)
 {
 	struct device				*dev =  &pdev->dev;
 	struct usbtll_omap_platform_data	*pdata = dev->platform_data;
@@ -348,7 +348,7 @@ end:
  *
  * Reverses the effect of usbtll_omap_probe().
  */
-static int __devexit usbtll_omap_remove(struct platform_device *pdev)
+static int usbtll_omap_remove(struct platform_device *pdev)
 {
 	struct usbtll_omap *tll = platform_get_drvdata(pdev);
 
@@ -424,7 +424,7 @@ static struct platform_driver usbtll_omap_driver = {
 		.pm		= &usbtllomap_dev_pm_ops,
 	},
 	.probe		= usbtll_omap_probe,
-	.remove		= __devexit_p(usbtll_omap_remove),
+	.remove		= usbtll_omap_remove,
 };
 
 int omap_tll_enable(void)
diff --git a/drivers/mfd/omap-usb.h b/drivers/mfd/omap-usb.h
new file mode 100644
index 0000000..972aa96
--- /dev/null
+++ b/drivers/mfd/omap-usb.h
@@ -0,0 +1,2 @@
+extern int omap_tll_enable(void);
+extern int omap_tll_disable(void);
diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c
index 4f8d6e6..6ffd7a2 100644
--- a/drivers/mfd/palmas.c
+++ b/drivers/mfd/palmas.c
@@ -247,7 +247,7 @@ static struct regmap_irq_chip palmas_irq_chip = {
 			PALMAS_INT1_MASK),
 };
 
-static void __devinit palmas_dt_to_pdata(struct device_node *node,
+static void palmas_dt_to_pdata(struct device_node *node,
 		struct palmas_platform_data *pdata)
 {
 	int ret;
@@ -275,7 +275,7 @@ static void __devinit palmas_dt_to_pdata(struct device_node *node,
 					PALMAS_POWER_CTRL_ENABLE2_MASK;
 }
 
-static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
+static int palmas_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
 	struct palmas *palmas;
@@ -492,7 +492,7 @@ static const struct i2c_device_id palmas_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, palmas_i2c_id);
 
-static struct of_device_id __devinitdata of_palmas_match_tbl[] = {
+static struct of_device_id of_palmas_match_tbl[] = {
 	{ .compatible = "ti,palmas", },
 	{ /* end */ }
 };
diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c
index 3927c17..18b53cb 100644
--- a/drivers/mfd/pcf50633-adc.c
+++ b/drivers/mfd/pcf50633-adc.c
@@ -199,7 +199,7 @@ static void pcf50633_adc_irq(int irq, void *data)
 	kfree(req);
 }
 
-static int __devinit pcf50633_adc_probe(struct platform_device *pdev)
+static int pcf50633_adc_probe(struct platform_device *pdev)
 {
 	struct pcf50633_adc *adc;
 
@@ -218,7 +218,7 @@ static int __devinit pcf50633_adc_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit pcf50633_adc_remove(struct platform_device *pdev)
+static int pcf50633_adc_remove(struct platform_device *pdev)
 {
 	struct pcf50633_adc *adc = platform_get_drvdata(pdev);
 	int i, head;
@@ -246,7 +246,7 @@ static struct platform_driver pcf50633_adc_driver = {
 		.name = "pcf50633-adc",
 	},
 	.probe = pcf50633_adc_probe,
-	.remove = __devexit_p(pcf50633_adc_remove),
+	.remove = pcf50633_adc_remove,
 };
 
 module_platform_driver(pcf50633_adc_driver);
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 45ce1fb..64803f1 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -191,7 +191,7 @@ static struct regmap_config pcf50633_regmap_config = {
 	.val_bits = 8,
 };
 
-static int __devinit pcf50633_probe(struct i2c_client *client,
+static int pcf50633_probe(struct i2c_client *client,
 				const struct i2c_device_id *ids)
 {
 	struct pcf50633 *pcf;
@@ -275,7 +275,7 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int __devexit pcf50633_remove(struct i2c_client *client)
+static int pcf50633_remove(struct i2c_client *client)
 {
 	struct pcf50633 *pcf = i2c_get_clientdata(client);
 	int i;
@@ -308,7 +308,7 @@ static struct i2c_driver pcf50633_driver = {
 	},
 	.id_table = pcf50633_id_table,
 	.probe = pcf50633_probe,
-	.remove = __devexit_p(pcf50633_remove),
+	.remove = pcf50633_remove,
 };
 
 static int __init pcf50633_init(void)
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index e873b157..d4b297c 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -80,7 +80,7 @@ static struct pm8xxx_drvdata pm8921_drvdata = {
 	.pmic_read_irq_stat	= pm8921_read_irq_stat,
 };
 
-static int __devinit pm8921_add_subdevices(const struct pm8921_platform_data
+static int pm8921_add_subdevices(const struct pm8921_platform_data
 					   *pdata,
 					   struct pm8921 *pmic,
 					   u32 rev)
@@ -104,7 +104,7 @@ static int __devinit pm8921_add_subdevices(const struct pm8921_platform_data
 	return ret;
 }
 
-static int __devinit pm8921_probe(struct platform_device *pdev)
+static int pm8921_probe(struct platform_device *pdev)
 {
 	const struct pm8921_platform_data *pdata = pdev->dev.platform_data;
 	struct pm8921 *pmic;
@@ -165,7 +165,7 @@ err_read_rev:
 	return rc;
 }
 
-static int __devexit pm8921_remove(struct platform_device *pdev)
+static int pm8921_remove(struct platform_device *pdev)
 {
 	struct pm8xxx_drvdata *drvdata;
 	struct pm8921 *pmic = NULL;
@@ -187,7 +187,7 @@ static int __devexit pm8921_remove(struct platform_device *pdev)
 
 static struct platform_driver pm8921_driver = {
 	.probe		= pm8921_probe,
-	.remove		= __devexit_p(pm8921_remove),
+	.remove		= pm8921_remove,
 	.driver		= {
 		.name	= "pm8921-core",
 		.owner	= THIS_MODULE,
diff --git a/drivers/mfd/pm8xxx-irq.c b/drivers/mfd/pm8xxx-irq.c
index d452dd0..1360e20 100644
--- a/drivers/mfd/pm8xxx-irq.c
+++ b/drivers/mfd/pm8xxx-irq.c
@@ -309,7 +309,7 @@ bail_out:
 }
 EXPORT_SYMBOL_GPL(pm8xxx_get_irq_stat);
 
-struct pm_irq_chip *  __devinit pm8xxx_irq_init(struct device *dev,
+struct pm_irq_chip *  pm8xxx_irq_init(struct device *dev,
 				const struct pm8xxx_irq_platform_data *pdata)
 {
 	struct pm_irq_chip  *chip;
@@ -363,7 +363,7 @@ struct pm_irq_chip *  __devinit pm8xxx_irq_init(struct device *dev,
 	return chip;
 }
 
-int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip)
+int pm8xxx_irq_exit(struct pm_irq_chip *chip)
 {
 	irq_set_chained_handler(chip->devirq, NULL);
 	kfree(chip);
diff --git a/drivers/mfd/rc5t583-irq.c b/drivers/mfd/rc5t583-irq.c
index fe00cdd..b41db59 100644
--- a/drivers/mfd/rc5t583-irq.c
+++ b/drivers/mfd/rc5t583-irq.c
@@ -345,7 +345,7 @@ int rc5t583_irq_init(struct rc5t583 *rc5t583, int irq, int irq_base)
 	mutex_init(&rc5t583->irq_lock);
 
 	/* Initailize all int register to 0 */
-	for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; i++)  {
+	for (i = 0; i < RC5T583_MAX_INTERRUPT_EN_REGS; i++)  {
 		ret = rc5t583_write(rc5t583->dev, irq_en_add[i],
 				rc5t583->irq_en_reg[i]);
 		if (ret < 0)
diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c
index f1a024e..14bdacc 100644
--- a/drivers/mfd/rc5t583.c
+++ b/drivers/mfd/rc5t583.c
@@ -246,7 +246,7 @@ static const struct regmap_config rc5t583_regmap_config = {
 	.cache_type = REGCACHE_RBTREE,
 };
 
-static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c,
+static int rc5t583_i2c_probe(struct i2c_client *i2c,
 			      const struct i2c_device_id *id)
 {
 	struct rc5t583 *rc5t583;
@@ -303,7 +303,7 @@ err_add_devs:
 	return ret;
 }
 
-static int  __devexit rc5t583_i2c_remove(struct i2c_client *i2c)
+static int  rc5t583_i2c_remove(struct i2c_client *i2c)
 {
 	struct rc5t583 *rc5t583 = i2c_get_clientdata(i2c);
 
@@ -325,7 +325,7 @@ static struct i2c_driver rc5t583_i2c_driver = {
 		   .owner = THIS_MODULE,
 		   },
 	.probe = rc5t583_i2c_probe,
-	.remove = __devexit_p(rc5t583_i2c_remove),
+	.remove = rc5t583_i2c_remove,
 	.id_table = rc5t583_i2c_id,
 };
 
diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c
index fbabc3cb..21b7bef 100644
--- a/drivers/mfd/rdc321x-southbridge.c
+++ b/drivers/mfd/rdc321x-southbridge.c
@@ -72,7 +72,7 @@ static struct mfd_cell rdc321x_sb_cells[] = {
 	},
 };
 
-static int __devinit rdc321x_sb_probe(struct pci_dev *pdev,
+static int rdc321x_sb_probe(struct pci_dev *pdev,
 					const struct pci_device_id *ent)
 {
 	int err;
@@ -91,7 +91,7 @@ static int __devinit rdc321x_sb_probe(struct pci_dev *pdev,
 			       NULL, 0, NULL);
 }
 
-static void __devexit rdc321x_sb_remove(struct pci_dev *pdev)
+static void rdc321x_sb_remove(struct pci_dev *pdev)
 {
 	mfd_remove_devices(&pdev->dev);
 }
@@ -106,7 +106,7 @@ static struct pci_driver rdc321x_sb_driver = {
 	.name		= "RDC321x Southbridge",
 	.id_table	= rdc321x_sb_table,
 	.probe		= rdc321x_sb_probe,
-	.remove		= __devexit_p(rdc321x_sb_remove),
+	.remove		= rdc321x_sb_remove,
 };
 
 module_pci_driver(rdc321x_sb_driver);
diff --git a/drivers/mfd/retu-mfd.c b/drivers/mfd/retu-mfd.c
new file mode 100644
index 0000000..7ff4a37
--- /dev/null
+++ b/drivers/mfd/retu-mfd.c
@@ -0,0 +1,264 @@
+/*
+ * Retu MFD driver
+ *
+ * Copyright (C) 2004, 2005 Nokia Corporation
+ *
+ * Based on code written by Juha Yrjölä, David Weinehall and Mikko Ylinen.
+ * Rewritten by Aaro Koskinen.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/retu.h>
+#include <linux/interrupt.h>
+#include <linux/moduleparam.h>
+
+/* Registers */
+#define RETU_REG_ASICR		0x00		/* ASIC ID and revision */
+#define RETU_REG_ASICR_VILMA	(1 << 7)	/* Bit indicating Vilma */
+#define RETU_REG_IDR		0x01		/* Interrupt ID */
+#define RETU_REG_IMR		0x02		/* Interrupt mask */
+
+/* Interrupt sources */
+#define RETU_INT_PWR		0		/* Power button */
+
+struct retu_dev {
+	struct regmap			*regmap;
+	struct device			*dev;
+	struct mutex			mutex;
+	struct regmap_irq_chip_data	*irq_data;
+};
+
+static struct resource retu_pwrbutton_res[] = {
+	{
+		.name	= "retu-pwrbutton",
+		.start	= RETU_INT_PWR,
+		.end	= RETU_INT_PWR,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct mfd_cell retu_devs[] = {
+	{
+		.name		= "retu-wdt"
+	},
+	{
+		.name		= "retu-pwrbutton",
+		.resources	= retu_pwrbutton_res,
+		.num_resources	= ARRAY_SIZE(retu_pwrbutton_res),
+	}
+};
+
+static struct regmap_irq retu_irqs[] = {
+	[RETU_INT_PWR] = {
+		.mask = 1 << RETU_INT_PWR,
+	}
+};
+
+static struct regmap_irq_chip retu_irq_chip = {
+	.name		= "RETU",
+	.irqs		= retu_irqs,
+	.num_irqs	= ARRAY_SIZE(retu_irqs),
+	.num_regs	= 1,
+	.status_base	= RETU_REG_IDR,
+	.mask_base	= RETU_REG_IMR,
+	.ack_base	= RETU_REG_IDR,
+};
+
+/* Retu device registered for the power off. */
+static struct retu_dev *retu_pm_power_off;
+
+int retu_read(struct retu_dev *rdev, u8 reg)
+{
+	int ret;
+	int value;
+
+	mutex_lock(&rdev->mutex);
+	ret = regmap_read(rdev->regmap, reg, &value);
+	mutex_unlock(&rdev->mutex);
+
+	return ret ? ret : value;
+}
+EXPORT_SYMBOL_GPL(retu_read);
+
+int retu_write(struct retu_dev *rdev, u8 reg, u16 data)
+{
+	int ret;
+
+	mutex_lock(&rdev->mutex);
+	ret = regmap_write(rdev->regmap, reg, data);
+	mutex_unlock(&rdev->mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(retu_write);
+
+static void retu_power_off(void)
+{
+	struct retu_dev *rdev = retu_pm_power_off;
+	int reg;
+
+	mutex_lock(&retu_pm_power_off->mutex);
+
+	/* Ignore power button state */
+	regmap_read(rdev->regmap, RETU_REG_CC1, &reg);
+	regmap_write(rdev->regmap, RETU_REG_CC1, reg | 2);
+
+	/* Expire watchdog immediately */
+	regmap_write(rdev->regmap, RETU_REG_WATCHDOG, 0);
+
+	/* Wait for poweroff */
+	for (;;)
+		cpu_relax();
+
+	mutex_unlock(&retu_pm_power_off->mutex);
+}
+
+static int retu_regmap_read(void *context, const void *reg, size_t reg_size,
+			    void *val, size_t val_size)
+{
+	int ret;
+	struct device *dev = context;
+	struct i2c_client *i2c = to_i2c_client(dev);
+
+	BUG_ON(reg_size != 1 || val_size != 2);
+
+	ret = i2c_smbus_read_word_data(i2c, *(u8 const *)reg);
+	if (ret < 0)
+		return ret;
+
+	*(u16 *)val = ret;
+	return 0;
+}
+
+static int retu_regmap_write(void *context, const void *data, size_t count)
+{
+	u8 reg;
+	u16 val;
+	struct device *dev = context;
+	struct i2c_client *i2c = to_i2c_client(dev);
+
+	BUG_ON(count != sizeof(reg) + sizeof(val));
+	memcpy(&reg, data, sizeof(reg));
+	memcpy(&val, data + sizeof(reg), sizeof(val));
+	return i2c_smbus_write_word_data(i2c, reg, val);
+}
+
+static struct regmap_bus retu_bus = {
+	.read = retu_regmap_read,
+	.write = retu_regmap_write,
+	.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+static struct regmap_config retu_config = {
+	.reg_bits = 8,
+	.val_bits = 16,
+};
+
+static int __devinit retu_probe(struct i2c_client *i2c,
+				const struct i2c_device_id *id)
+{
+	struct retu_dev *rdev;
+	int ret;
+
+	rdev = devm_kzalloc(&i2c->dev, sizeof(*rdev), GFP_KERNEL);
+	if (rdev == NULL)
+		return -ENOMEM;
+
+	i2c_set_clientdata(i2c, rdev);
+	rdev->dev = &i2c->dev;
+	mutex_init(&rdev->mutex);
+	rdev->regmap = devm_regmap_init(&i2c->dev, &retu_bus, &i2c->dev,
+					&retu_config);
+	if (IS_ERR(rdev->regmap))
+		return PTR_ERR(rdev->regmap);
+
+	ret = retu_read(rdev, RETU_REG_ASICR);
+	if (ret < 0) {
+		dev_err(rdev->dev, "could not read Retu revision: %d\n", ret);
+		return ret;
+	}
+
+	dev_info(rdev->dev, "Retu%s v%d.%d found\n",
+		 (ret & RETU_REG_ASICR_VILMA) ? " & Vilma" : "",
+		 (ret >> 4) & 0x7, ret & 0xf);
+
+	/* Mask all RETU interrupts. */
+	ret = retu_write(rdev, RETU_REG_IMR, 0xffff);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_add_irq_chip(rdev->regmap, i2c->irq, IRQF_ONESHOT, -1,
+				  &retu_irq_chip, &rdev->irq_data);
+	if (ret < 0)
+		return ret;
+
+	ret = mfd_add_devices(rdev->dev, -1, retu_devs, ARRAY_SIZE(retu_devs),
+			      NULL, regmap_irq_chip_get_base(rdev->irq_data),
+			      NULL);
+	if (ret < 0) {
+		regmap_del_irq_chip(i2c->irq, rdev->irq_data);
+		return ret;
+	}
+
+	if (!pm_power_off) {
+		retu_pm_power_off = rdev;
+		pm_power_off	  = retu_power_off;
+	}
+
+	return 0;
+}
+
+static int __devexit retu_remove(struct i2c_client *i2c)
+{
+	struct retu_dev *rdev = i2c_get_clientdata(i2c);
+
+	if (retu_pm_power_off == rdev) {
+		pm_power_off	  = NULL;
+		retu_pm_power_off = NULL;
+	}
+	mfd_remove_devices(rdev->dev);
+	regmap_del_irq_chip(i2c->irq, rdev->irq_data);
+
+	return 0;
+}
+
+static const struct i2c_device_id retu_id[] = {
+	{ "retu-mfd", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, retu_id);
+
+static struct i2c_driver retu_driver = {
+	.driver		= {
+		.name = "retu-mfd",
+		.owner = THIS_MODULE,
+	},
+	.probe		= retu_probe,
+	.remove		= retu_remove,
+	.id_table	= retu_id,
+};
+module_i2c_driver(retu_driver);
+
+MODULE_DESCRIPTION("Retu MFD driver");
+MODULE_AUTHOR("Juha Yrjölä");
+MODULE_AUTHOR("David Weinehall");
+MODULE_AUTHOR("Mikko Ylinen");
+MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c
new file mode 100644
index 0000000..89f046c
--- /dev/null
+++ b/drivers/mfd/rtl8411.c
@@ -0,0 +1,251 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/mfd/rtsx_pci.h>
+
+#include "rtsx_pcr.h"
+
+static u8 rtl8411_get_ic_version(struct rtsx_pcr *pcr)
+{
+	u8 val;
+
+	rtsx_pci_read_register(pcr, SYS_VER, &val);
+	return val & 0x0F;
+}
+
+static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr)
+{
+	return rtsx_pci_write_register(pcr, CD_PAD_CTL,
+			CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
+}
+
+static int rtl8411_turn_on_led(struct rtsx_pcr *pcr)
+{
+	return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00);
+}
+
+static int rtl8411_turn_off_led(struct rtsx_pcr *pcr)
+{
+	return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01);
+}
+
+static int rtl8411_enable_auto_blink(struct rtsx_pcr *pcr)
+{
+	return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D);
+}
+
+static int rtl8411_disable_auto_blink(struct rtsx_pcr *pcr)
+{
+	return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00);
+}
+
+static int rtl8411_card_power_on(struct rtsx_pcr *pcr, int card)
+{
+	int err;
+
+	rtsx_pci_init_cmd(pcr);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+			BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_CTL,
+			BPP_LDO_POWB, BPP_LDO_SUSPEND);
+	err = rtsx_pci_send_cmd(pcr, 100);
+	if (err < 0)
+		return err;
+
+	/* To avoid too large in-rush current */
+	udelay(150);
+
+	err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+			BPP_POWER_MASK, BPP_POWER_10_PERCENT_ON);
+	if (err < 0)
+		return err;
+
+	udelay(150);
+
+	err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+			BPP_POWER_MASK, BPP_POWER_15_PERCENT_ON);
+	if (err < 0)
+		return err;
+
+	udelay(150);
+
+	err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+			BPP_POWER_MASK, BPP_POWER_ON);
+	if (err < 0)
+		return err;
+
+	return rtsx_pci_write_register(pcr, LDO_CTL, BPP_LDO_POWB, BPP_LDO_ON);
+}
+
+static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card)
+{
+	int err;
+
+	err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+			BPP_POWER_MASK, BPP_POWER_OFF);
+	if (err < 0)
+		return err;
+
+	return rtsx_pci_write_register(pcr, LDO_CTL,
+			BPP_LDO_POWB, BPP_LDO_SUSPEND);
+}
+
+static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr)
+{
+	unsigned int card_exist;
+
+	card_exist = rtsx_pci_readl(pcr, RTSX_BIPR);
+	card_exist &= CARD_EXIST;
+	if (!card_exist) {
+		/* Enable card CD */
+		rtsx_pci_write_register(pcr, CD_PAD_CTL,
+				CD_DISABLE_MASK, CD_ENABLE);
+		/* Enable card interrupt */
+		rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x00);
+		return 0;
+	}
+
+	if (hweight32(card_exist) > 1) {
+		rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+				BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON);
+		msleep(100);
+
+		card_exist = rtsx_pci_readl(pcr, RTSX_BIPR);
+		if (card_exist & MS_EXIST)
+			card_exist = MS_EXIST;
+		else if (card_exist & SD_EXIST)
+			card_exist = SD_EXIST;
+		else
+			card_exist = 0;
+
+		rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+				BPP_POWER_MASK, BPP_POWER_OFF);
+
+		dev_dbg(&(pcr->pci->dev),
+				"After CD deglitch, card_exist = 0x%x\n",
+				card_exist);
+	}
+
+	if (card_exist & MS_EXIST) {
+		/* Disable SD interrupt */
+		rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x40);
+		rtsx_pci_write_register(pcr, CD_PAD_CTL,
+				CD_DISABLE_MASK, MS_CD_EN_ONLY);
+	} else if (card_exist & SD_EXIST) {
+		/* Disable MS interrupt */
+		rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x80);
+		rtsx_pci_write_register(pcr, CD_PAD_CTL,
+				CD_DISABLE_MASK, SD_CD_EN_ONLY);
+	}
+
+	return card_exist;
+}
+
+static const struct pcr_ops rtl8411_pcr_ops = {
+	.extra_init_hw = rtl8411_extra_init_hw,
+	.optimize_phy = NULL,
+	.turn_on_led = rtl8411_turn_on_led,
+	.turn_off_led = rtl8411_turn_off_led,
+	.enable_auto_blink = rtl8411_enable_auto_blink,
+	.disable_auto_blink = rtl8411_disable_auto_blink,
+	.card_power_on = rtl8411_card_power_on,
+	.card_power_off = rtl8411_card_power_off,
+	.cd_deglitch = rtl8411_cd_deglitch,
+};
+
+/* SD Pull Control Enable:
+ *     SD_DAT[3:0] ==> pull up
+ *     SD_CD       ==> pull up
+ *     SD_WP       ==> pull up
+ *     SD_CMD      ==> pull up
+ *     SD_CLK      ==> pull down
+ */
+static const u32 rtl8411_sd_pull_ctl_enable_tbl[] = {
+	RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
+	RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+	RTSX_REG_PAIR(CARD_PULL_CTL3, 0xA9),
+	RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
+	RTSX_REG_PAIR(CARD_PULL_CTL5, 0x09),
+	RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
+	0,
+};
+
+/* SD Pull Control Disable:
+ *     SD_DAT[3:0] ==> pull down
+ *     SD_CD       ==> pull up
+ *     SD_WP       ==> pull down
+ *     SD_CMD      ==> pull down
+ *     SD_CLK      ==> pull down
+ */
+static const u32 rtl8411_sd_pull_ctl_disable_tbl[] = {
+	RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
+	RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+	RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
+	RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
+	RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
+	RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
+	0,
+};
+
+/* MS Pull Control Enable:
+ *     MS CD       ==> pull up
+ *     others      ==> pull down
+ */
+static const u32 rtl8411_ms_pull_ctl_enable_tbl[] = {
+	RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
+	RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+	RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
+	RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05),
+	RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
+	RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
+	0,
+};
+
+/* MS Pull Control Disable:
+ *     MS CD       ==> pull up
+ *     others      ==> pull down
+ */
+static const u32 rtl8411_ms_pull_ctl_disable_tbl[] = {
+	RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
+	RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+	RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
+	RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
+	RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
+	RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
+	0,
+};
+
+void rtl8411_init_params(struct rtsx_pcr *pcr)
+{
+	pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
+	pcr->num_slots = 2;
+	pcr->ops = &rtl8411_pcr_ops;
+
+	pcr->ic_version = rtl8411_get_ic_version(pcr);
+	pcr->sd_pull_ctl_enable_tbl = rtl8411_sd_pull_ctl_enable_tbl;
+	pcr->sd_pull_ctl_disable_tbl = rtl8411_sd_pull_ctl_disable_tbl;
+	pcr->ms_pull_ctl_enable_tbl = rtl8411_ms_pull_ctl_enable_tbl;
+	pcr->ms_pull_ctl_disable_tbl = rtl8411_ms_pull_ctl_disable_tbl;
+}
diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c
new file mode 100644
index 0000000..283a4f1
--- /dev/null
+++ b/drivers/mfd/rts5209.c
@@ -0,0 +1,223 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/mfd/rtsx_pci.h>
+
+#include "rtsx_pcr.h"
+
+static u8 rts5209_get_ic_version(struct rtsx_pcr *pcr)
+{
+	u8 val;
+
+	val = rtsx_pci_readb(pcr, 0x1C);
+	return val & 0x0F;
+}
+
+static void rts5209_init_vendor_cfg(struct rtsx_pcr *pcr)
+{
+	u32 val;
+
+	rtsx_pci_read_config_dword(pcr, 0x724, &val);
+	dev_dbg(&(pcr->pci->dev), "Cfg 0x724: 0x%x\n", val);
+
+	if (!(val & 0x80)) {
+		if (val & 0x08)
+			pcr->ms_pmos = false;
+		else
+			pcr->ms_pmos = true;
+	}
+}
+
+static int rts5209_extra_init_hw(struct rtsx_pcr *pcr)
+{
+	rtsx_pci_init_cmd(pcr);
+
+	/* Turn off LED */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO, 0xFF, 0x03);
+	/* Configure GPIO as output */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO_DIR, 0xFF, 0x03);
+
+	return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rts5209_optimize_phy(struct rtsx_pcr *pcr)
+{
+	return rtsx_pci_write_phy_register(pcr, 0x00, 0xB966);
+}
+
+static int rts5209_turn_on_led(struct rtsx_pcr *pcr)
+{
+	return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00);
+}
+
+static int rts5209_turn_off_led(struct rtsx_pcr *pcr)
+{
+	return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01);
+}
+
+static int rts5209_enable_auto_blink(struct rtsx_pcr *pcr)
+{
+	return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D);
+}
+
+static int rts5209_disable_auto_blink(struct rtsx_pcr *pcr)
+{
+	return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00);
+}
+
+static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card)
+{
+	int err;
+	u8 pwr_mask, partial_pwr_on, pwr_on;
+
+	pwr_mask = SD_POWER_MASK;
+	partial_pwr_on = SD_PARTIAL_POWER_ON;
+	pwr_on = SD_POWER_ON;
+
+	if (pcr->ms_pmos && (card == RTSX_MS_CARD)) {
+		pwr_mask = MS_POWER_MASK;
+		partial_pwr_on = MS_PARTIAL_POWER_ON;
+		pwr_on = MS_POWER_ON;
+	}
+
+	rtsx_pci_init_cmd(pcr);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+			pwr_mask, partial_pwr_on);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+			LDO3318_PWR_MASK, 0x04);
+	err = rtsx_pci_send_cmd(pcr, 100);
+	if (err < 0)
+		return err;
+
+	/* To avoid too large in-rush current */
+	udelay(150);
+
+	rtsx_pci_init_cmd(pcr);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask, pwr_on);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+			LDO3318_PWR_MASK, 0x00);
+	err = rtsx_pci_send_cmd(pcr, 100);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)
+{
+	u8 pwr_mask, pwr_off;
+
+	pwr_mask = SD_POWER_MASK;
+	pwr_off = SD_POWER_OFF;
+
+	if (pcr->ms_pmos && (card == RTSX_MS_CARD)) {
+		pwr_mask = MS_POWER_MASK;
+		pwr_off = MS_POWER_OFF;
+	}
+
+	rtsx_pci_init_cmd(pcr);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+			pwr_mask | PMOS_STRG_MASK, pwr_off | PMOS_STRG_400mA);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+			LDO3318_PWR_MASK, 0X06);
+	return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static const struct pcr_ops rts5209_pcr_ops = {
+	.extra_init_hw = rts5209_extra_init_hw,
+	.optimize_phy = rts5209_optimize_phy,
+	.turn_on_led = rts5209_turn_on_led,
+	.turn_off_led = rts5209_turn_off_led,
+	.enable_auto_blink = rts5209_enable_auto_blink,
+	.disable_auto_blink = rts5209_disable_auto_blink,
+	.card_power_on = rts5209_card_power_on,
+	.card_power_off = rts5209_card_power_off,
+	.cd_deglitch = NULL,
+};
+
+/* SD Pull Control Enable:
+ *     SD_DAT[3:0] ==> pull up
+ *     SD_CD       ==> pull up
+ *     SD_WP       ==> pull up
+ *     SD_CMD      ==> pull up
+ *     SD_CLK      ==> pull down
+ */
+static const u32 rts5209_sd_pull_ctl_enable_tbl[] = {
+	RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
+	RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+	RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
+	0,
+};
+
+/* SD Pull Control Disable:
+ *     SD_DAT[3:0] ==> pull down
+ *     SD_CD       ==> pull up
+ *     SD_WP       ==> pull down
+ *     SD_CMD      ==> pull down
+ *     SD_CLK      ==> pull down
+ */
+static const u32 rts5209_sd_pull_ctl_disable_tbl[] = {
+	RTSX_REG_PAIR(CARD_PULL_CTL1, 0x55),
+	RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+	RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
+	0,
+};
+
+/* MS Pull Control Enable:
+ *     MS CD       ==> pull up
+ *     others      ==> pull down
+ */
+static const u32 rts5209_ms_pull_ctl_enable_tbl[] = {
+	RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
+	RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
+	RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
+	0,
+};
+
+/* MS Pull Control Disable:
+ *     MS CD       ==> pull up
+ *     others      ==> pull down
+ */
+static const u32 rts5209_ms_pull_ctl_disable_tbl[] = {
+	RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
+	RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
+	RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
+	0,
+};
+
+void rts5209_init_params(struct rtsx_pcr *pcr)
+{
+	pcr->extra_caps = EXTRA_CAPS_SD_SDR50 |
+		EXTRA_CAPS_SD_SDR104 | EXTRA_CAPS_MMC_8BIT;
+	pcr->num_slots = 2;
+	pcr->ops = &rts5209_pcr_ops;
+
+	rts5209_init_vendor_cfg(pcr);
+
+	pcr->ic_version = rts5209_get_ic_version(pcr);
+	pcr->sd_pull_ctl_enable_tbl = rts5209_sd_pull_ctl_enable_tbl;
+	pcr->sd_pull_ctl_disable_tbl = rts5209_sd_pull_ctl_disable_tbl;
+	pcr->ms_pull_ctl_enable_tbl = rts5209_ms_pull_ctl_enable_tbl;
+	pcr->ms_pull_ctl_disable_tbl = rts5209_ms_pull_ctl_disable_tbl;
+}
diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c
new file mode 100644
index 0000000..b9dbab2
--- /dev/null
+++ b/drivers/mfd/rts5229.c
@@ -0,0 +1,205 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/mfd/rtsx_pci.h>
+
+#include "rtsx_pcr.h"
+
+static u8 rts5229_get_ic_version(struct rtsx_pcr *pcr)
+{
+	u8 val;
+
+	rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
+	return val & 0x0F;
+}
+
+static int rts5229_extra_init_hw(struct rtsx_pcr *pcr)
+{
+	rtsx_pci_init_cmd(pcr);
+
+	/* Configure GPIO as output */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
+	/* Switch LDO3318 source from DV33 to card_3v3 */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
+	/* LED shine disabled, set initial shine cycle period */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
+
+	return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rts5229_optimize_phy(struct rtsx_pcr *pcr)
+{
+	/* Optimize RX sensitivity */
+	return rtsx_pci_write_phy_register(pcr, 0x00, 0xBA42);
+}
+
+static int rts5229_turn_on_led(struct rtsx_pcr *pcr)
+{
+	return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);
+}
+
+static int rts5229_turn_off_led(struct rtsx_pcr *pcr)
+{
+	return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);
+}
+
+static int rts5229_enable_auto_blink(struct rtsx_pcr *pcr)
+{
+	return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);
+}
+
+static int rts5229_disable_auto_blink(struct rtsx_pcr *pcr)
+{
+	return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);
+}
+
+static int rts5229_card_power_on(struct rtsx_pcr *pcr, int card)
+{
+	int err;
+
+	rtsx_pci_init_cmd(pcr);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+			SD_POWER_MASK, SD_PARTIAL_POWER_ON);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+			LDO3318_PWR_MASK, 0x02);
+	err = rtsx_pci_send_cmd(pcr, 100);
+	if (err < 0)
+		return err;
+
+	/* To avoid too large in-rush current */
+	udelay(150);
+
+	rtsx_pci_init_cmd(pcr);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+			SD_POWER_MASK, SD_POWER_ON);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+			LDO3318_PWR_MASK, 0x06);
+	err = rtsx_pci_send_cmd(pcr, 100);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card)
+{
+	rtsx_pci_init_cmd(pcr);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+			SD_POWER_MASK | PMOS_STRG_MASK,
+			SD_POWER_OFF | PMOS_STRG_400mA);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+			LDO3318_PWR_MASK, 0X00);
+	return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static const struct pcr_ops rts5229_pcr_ops = {
+	.extra_init_hw = rts5229_extra_init_hw,
+	.optimize_phy = rts5229_optimize_phy,
+	.turn_on_led = rts5229_turn_on_led,
+	.turn_off_led = rts5229_turn_off_led,
+	.enable_auto_blink = rts5229_enable_auto_blink,
+	.disable_auto_blink = rts5229_disable_auto_blink,
+	.card_power_on = rts5229_card_power_on,
+	.card_power_off = rts5229_card_power_off,
+	.cd_deglitch = NULL,
+};
+
+/* SD Pull Control Enable:
+ *     SD_DAT[3:0] ==> pull up
+ *     SD_CD       ==> pull up
+ *     SD_WP       ==> pull up
+ *     SD_CMD      ==> pull up
+ *     SD_CLK      ==> pull down
+ */
+static const u32 rts5229_sd_pull_ctl_enable_tbl1[] = {
+	RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+	RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
+	0,
+};
+
+/* For RTS5229 version C */
+static const u32 rts5229_sd_pull_ctl_enable_tbl2[] = {
+	RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+	RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD9),
+	0,
+};
+
+/* SD Pull Control Disable:
+ *     SD_DAT[3:0] ==> pull down
+ *     SD_CD       ==> pull up
+ *     SD_WP       ==> pull down
+ *     SD_CMD      ==> pull down
+ *     SD_CLK      ==> pull down
+ */
+static const u32 rts5229_sd_pull_ctl_disable_tbl1[] = {
+	RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+	RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
+	0,
+};
+
+/* For RTS5229 version C */
+static const u32 rts5229_sd_pull_ctl_disable_tbl2[] = {
+	RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+	RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE5),
+	0,
+};
+
+/* MS Pull Control Enable:
+ *     MS CD       ==> pull up
+ *     others      ==> pull down
+ */
+static const u32 rts5229_ms_pull_ctl_enable_tbl[] = {
+	RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
+	RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
+	0,
+};
+
+/* MS Pull Control Disable:
+ *     MS CD       ==> pull up
+ *     others      ==> pull down
+ */
+static const u32 rts5229_ms_pull_ctl_disable_tbl[] = {
+	RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
+	RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
+	0,
+};
+
+void rts5229_init_params(struct rtsx_pcr *pcr)
+{
+	pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
+	pcr->num_slots = 2;
+	pcr->ops = &rts5229_pcr_ops;
+
+	pcr->ic_version = rts5229_get_ic_version(pcr);
+	if (pcr->ic_version == IC_VER_C) {
+		pcr->sd_pull_ctl_enable_tbl = rts5229_sd_pull_ctl_enable_tbl2;
+		pcr->sd_pull_ctl_disable_tbl = rts5229_sd_pull_ctl_disable_tbl2;
+	} else {
+		pcr->sd_pull_ctl_enable_tbl = rts5229_sd_pull_ctl_enable_tbl1;
+		pcr->sd_pull_ctl_disable_tbl = rts5229_sd_pull_ctl_disable_tbl1;
+	}
+	pcr->ms_pull_ctl_enable_tbl = rts5229_ms_pull_ctl_enable_tbl;
+	pcr->ms_pull_ctl_disable_tbl = rts5229_ms_pull_ctl_disable_tbl;
+}
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
new file mode 100644
index 0000000..3a44efa
--- /dev/null
+++ b/drivers/mfd/rtsx_pcr.c
@@ -0,0 +1,1252 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/highmem.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/idr.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/rtsx_pci.h>
+#include <asm/unaligned.h>
+
+#include "rtsx_pcr.h"
+
+static bool msi_en = true;
+module_param(msi_en, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(msi_en, "Enable MSI");
+
+static DEFINE_IDR(rtsx_pci_idr);
+static DEFINE_SPINLOCK(rtsx_pci_lock);
+
+static struct mfd_cell rtsx_pcr_cells[] = {
+	[RTSX_SD_CARD] = {
+		.name = DRV_NAME_RTSX_PCI_SDMMC,
+	},
+	[RTSX_MS_CARD] = {
+		.name = DRV_NAME_RTSX_PCI_MS,
+	},
+};
+
+static DEFINE_PCI_DEVICE_TABLE(rtsx_pci_ids) = {
+	{ PCI_DEVICE(0x10EC, 0x5209), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+	{ PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+	{ PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, rtsx_pci_ids);
+
+void rtsx_pci_start_run(struct rtsx_pcr *pcr)
+{
+	/* If pci device removed, don't queue idle work any more */
+	if (pcr->remove_pci)
+		return;
+
+	if (pcr->state != PDEV_STAT_RUN) {
+		pcr->state = PDEV_STAT_RUN;
+		if (pcr->ops->enable_auto_blink)
+			pcr->ops->enable_auto_blink(pcr);
+	}
+
+	mod_delayed_work(system_wq, &pcr->idle_work, msecs_to_jiffies(200));
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_start_run);
+
+int rtsx_pci_write_register(struct rtsx_pcr *pcr, u16 addr, u8 mask, u8 data)
+{
+	int i;
+	u32 val = HAIMR_WRITE_START;
+
+	val |= (u32)(addr & 0x3FFF) << 16;
+	val |= (u32)mask << 8;
+	val |= (u32)data;
+
+	rtsx_pci_writel(pcr, RTSX_HAIMR, val);
+
+	for (i = 0; i < MAX_RW_REG_CNT; i++) {
+		val = rtsx_pci_readl(pcr, RTSX_HAIMR);
+		if ((val & HAIMR_TRANS_END) == 0) {
+			if (data != (u8)val)
+				return -EIO;
+			return 0;
+		}
+	}
+
+	return -ETIMEDOUT;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_write_register);
+
+int rtsx_pci_read_register(struct rtsx_pcr *pcr, u16 addr, u8 *data)
+{
+	u32 val = HAIMR_READ_START;
+	int i;
+
+	val |= (u32)(addr & 0x3FFF) << 16;
+	rtsx_pci_writel(pcr, RTSX_HAIMR, val);
+
+	for (i = 0; i < MAX_RW_REG_CNT; i++) {
+		val = rtsx_pci_readl(pcr, RTSX_HAIMR);
+		if ((val & HAIMR_TRANS_END) == 0)
+			break;
+	}
+
+	if (i >= MAX_RW_REG_CNT)
+		return -ETIMEDOUT;
+
+	if (data)
+		*data = (u8)(val & 0xFF);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_read_register);
+
+int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val)
+{
+	int err, i, finished = 0;
+	u8 tmp;
+
+	rtsx_pci_init_cmd(pcr);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYDATA0, 0xFF, (u8)val);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYDATA1, 0xFF, (u8)(val >> 8));
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYADDR, 0xFF, addr);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYRWCTL, 0xFF, 0x81);
+
+	err = rtsx_pci_send_cmd(pcr, 100);
+	if (err < 0)
+		return err;
+
+	for (i = 0; i < 100000; i++) {
+		err = rtsx_pci_read_register(pcr, PHYRWCTL, &tmp);
+		if (err < 0)
+			return err;
+
+		if (!(tmp & 0x80)) {
+			finished = 1;
+			break;
+		}
+	}
+
+	if (!finished)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_write_phy_register);
+
+int rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val)
+{
+	int err, i, finished = 0;
+	u16 data;
+	u8 *ptr, tmp;
+
+	rtsx_pci_init_cmd(pcr);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYADDR, 0xFF, addr);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYRWCTL, 0xFF, 0x80);
+
+	err = rtsx_pci_send_cmd(pcr, 100);
+	if (err < 0)
+		return err;
+
+	for (i = 0; i < 100000; i++) {
+		err = rtsx_pci_read_register(pcr, PHYRWCTL, &tmp);
+		if (err < 0)
+			return err;
+
+		if (!(tmp & 0x80)) {
+			finished = 1;
+			break;
+		}
+	}
+
+	if (!finished)
+		return -ETIMEDOUT;
+
+	rtsx_pci_init_cmd(pcr);
+
+	rtsx_pci_add_cmd(pcr, READ_REG_CMD, PHYDATA0, 0, 0);
+	rtsx_pci_add_cmd(pcr, READ_REG_CMD, PHYDATA1, 0, 0);
+
+	err = rtsx_pci_send_cmd(pcr, 100);
+	if (err < 0)
+		return err;
+
+	ptr = rtsx_pci_get_cmd_data(pcr);
+	data = ((u16)ptr[1] << 8) | ptr[0];
+
+	if (val)
+		*val = data;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_read_phy_register);
+
+void rtsx_pci_stop_cmd(struct rtsx_pcr *pcr)
+{
+	rtsx_pci_writel(pcr, RTSX_HCBCTLR, STOP_CMD);
+	rtsx_pci_writel(pcr, RTSX_HDBCTLR, STOP_DMA);
+
+	rtsx_pci_write_register(pcr, DMACTL, 0x80, 0x80);
+	rtsx_pci_write_register(pcr, RBCTL, 0x80, 0x80);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_stop_cmd);
+
+void rtsx_pci_add_cmd(struct rtsx_pcr *pcr,
+		u8 cmd_type, u16 reg_addr, u8 mask, u8 data)
+{
+	unsigned long flags;
+	u32 val = 0;
+	u32 *ptr = (u32 *)(pcr->host_cmds_ptr);
+
+	val |= (u32)(cmd_type & 0x03) << 30;
+	val |= (u32)(reg_addr & 0x3FFF) << 16;
+	val |= (u32)mask << 8;
+	val |= (u32)data;
+
+	spin_lock_irqsave(&pcr->lock, flags);
+	ptr += pcr->ci;
+	if (pcr->ci < (HOST_CMDS_BUF_LEN / 4)) {
+		put_unaligned_le32(val, ptr);
+		ptr++;
+		pcr->ci++;
+	}
+	spin_unlock_irqrestore(&pcr->lock, flags);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_add_cmd);
+
+void rtsx_pci_send_cmd_no_wait(struct rtsx_pcr *pcr)
+{
+	u32 val = 1 << 31;
+
+	rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
+
+	val |= (u32)(pcr->ci * 4) & 0x00FFFFFF;
+	/* Hardware Auto Response */
+	val |= 0x40000000;
+	rtsx_pci_writel(pcr, RTSX_HCBCTLR, val);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_send_cmd_no_wait);
+
+int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout)
+{
+	struct completion trans_done;
+	u32 val = 1 << 31;
+	long timeleft;
+	unsigned long flags;
+	int err = 0;
+
+	spin_lock_irqsave(&pcr->lock, flags);
+
+	/* set up data structures for the wakeup system */
+	pcr->done = &trans_done;
+	pcr->trans_result = TRANS_NOT_READY;
+	init_completion(&trans_done);
+
+	rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
+
+	val |= (u32)(pcr->ci * 4) & 0x00FFFFFF;
+	/* Hardware Auto Response */
+	val |= 0x40000000;
+	rtsx_pci_writel(pcr, RTSX_HCBCTLR, val);
+
+	spin_unlock_irqrestore(&pcr->lock, flags);
+
+	/* Wait for TRANS_OK_INT */
+	timeleft = wait_for_completion_interruptible_timeout(
+			&trans_done, msecs_to_jiffies(timeout));
+	if (timeleft <= 0) {
+		dev_dbg(&(pcr->pci->dev), "Timeout (%s %d)\n",
+				__func__, __LINE__);
+		err = -ETIMEDOUT;
+		goto finish_send_cmd;
+	}
+
+	spin_lock_irqsave(&pcr->lock, flags);
+	if (pcr->trans_result == TRANS_RESULT_FAIL)
+		err = -EINVAL;
+	else if (pcr->trans_result == TRANS_RESULT_OK)
+		err = 0;
+	else if (pcr->trans_result == TRANS_NO_DEVICE)
+		err = -ENODEV;
+	spin_unlock_irqrestore(&pcr->lock, flags);
+
+finish_send_cmd:
+	spin_lock_irqsave(&pcr->lock, flags);
+	pcr->done = NULL;
+	spin_unlock_irqrestore(&pcr->lock, flags);
+
+	if ((err < 0) && (err != -ENODEV))
+		rtsx_pci_stop_cmd(pcr);
+
+	if (pcr->finish_me)
+		complete(pcr->finish_me);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_send_cmd);
+
+static void rtsx_pci_add_sg_tbl(struct rtsx_pcr *pcr,
+		dma_addr_t addr, unsigned int len, int end)
+{
+	u64 *ptr = (u64 *)(pcr->host_sg_tbl_ptr) + pcr->sgi;
+	u64 val;
+	u8 option = SG_VALID | SG_TRANS_DATA;
+
+	dev_dbg(&(pcr->pci->dev), "DMA addr: 0x%x, Len: 0x%x\n",
+			(unsigned int)addr, len);
+
+	if (end)
+		option |= SG_END;
+	val = ((u64)addr << 32) | ((u64)len << 12) | option;
+
+	put_unaligned_le64(val, ptr);
+	ptr++;
+	pcr->sgi++;
+}
+
+int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+		int num_sg, bool read, int timeout)
+{
+	struct completion trans_done;
+	u8 dir;
+	int err = 0, i, count;
+	long timeleft;
+	unsigned long flags;
+	struct scatterlist *sg;
+	enum dma_data_direction dma_dir;
+	u32 val;
+	dma_addr_t addr;
+	unsigned int len;
+
+	dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg);
+
+	/* don't transfer data during abort processing */
+	if (pcr->remove_pci)
+		return -EINVAL;
+
+	if ((sglist == NULL) || (num_sg <= 0))
+		return -EINVAL;
+
+	if (read) {
+		dir = DEVICE_TO_HOST;
+		dma_dir = DMA_FROM_DEVICE;
+	} else {
+		dir = HOST_TO_DEVICE;
+		dma_dir = DMA_TO_DEVICE;
+	}
+
+	count = dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
+	if (count < 1) {
+		dev_err(&(pcr->pci->dev), "scatterlist map failed\n");
+		return -EINVAL;
+	}
+	dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count);
+
+	val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE;
+	pcr->sgi = 0;
+	for_each_sg(sglist, sg, count, i) {
+		addr = sg_dma_address(sg);
+		len = sg_dma_len(sg);
+		rtsx_pci_add_sg_tbl(pcr, addr, len, i == count - 1);
+	}
+
+	spin_lock_irqsave(&pcr->lock, flags);
+
+	pcr->done = &trans_done;
+	pcr->trans_result = TRANS_NOT_READY;
+	init_completion(&trans_done);
+	rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr);
+	rtsx_pci_writel(pcr, RTSX_HDBCTLR, val);
+
+	spin_unlock_irqrestore(&pcr->lock, flags);
+
+	timeleft = wait_for_completion_interruptible_timeout(
+			&trans_done, msecs_to_jiffies(timeout));
+	if (timeleft <= 0) {
+		dev_dbg(&(pcr->pci->dev), "Timeout (%s %d)\n",
+				__func__, __LINE__);
+		err = -ETIMEDOUT;
+		goto out;
+	}
+
+	spin_lock_irqsave(&pcr->lock, flags);
+
+	if (pcr->trans_result == TRANS_RESULT_FAIL)
+		err = -EINVAL;
+	else if (pcr->trans_result == TRANS_NO_DEVICE)
+		err = -ENODEV;
+
+	spin_unlock_irqrestore(&pcr->lock, flags);
+
+out:
+	spin_lock_irqsave(&pcr->lock, flags);
+	pcr->done = NULL;
+	spin_unlock_irqrestore(&pcr->lock, flags);
+
+	dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
+
+	if ((err < 0) && (err != -ENODEV))
+		rtsx_pci_stop_cmd(pcr);
+
+	if (pcr->finish_me)
+		complete(pcr->finish_me);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
+
+int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
+{
+	int err;
+	int i, j;
+	u16 reg;
+	u8 *ptr;
+
+	if (buf_len > 512)
+		buf_len = 512;
+
+	ptr = buf;
+	reg = PPBUF_BASE2;
+	for (i = 0; i < buf_len / 256; i++) {
+		rtsx_pci_init_cmd(pcr);
+
+		for (j = 0; j < 256; j++)
+			rtsx_pci_add_cmd(pcr, READ_REG_CMD, reg++, 0, 0);
+
+		err = rtsx_pci_send_cmd(pcr, 250);
+		if (err < 0)
+			return err;
+
+		memcpy(ptr, rtsx_pci_get_cmd_data(pcr), 256);
+		ptr += 256;
+	}
+
+	if (buf_len % 256) {
+		rtsx_pci_init_cmd(pcr);
+
+		for (j = 0; j < buf_len % 256; j++)
+			rtsx_pci_add_cmd(pcr, READ_REG_CMD, reg++, 0, 0);
+
+		err = rtsx_pci_send_cmd(pcr, 250);
+		if (err < 0)
+			return err;
+	}
+
+	memcpy(ptr, rtsx_pci_get_cmd_data(pcr), buf_len % 256);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_read_ppbuf);
+
+int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
+{
+	int err;
+	int i, j;
+	u16 reg;
+	u8 *ptr;
+
+	if (buf_len > 512)
+		buf_len = 512;
+
+	ptr = buf;
+	reg = PPBUF_BASE2;
+	for (i = 0; i < buf_len / 256; i++) {
+		rtsx_pci_init_cmd(pcr);
+
+		for (j = 0; j < 256; j++) {
+			rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+					reg++, 0xFF, *ptr);
+			ptr++;
+		}
+
+		err = rtsx_pci_send_cmd(pcr, 250);
+		if (err < 0)
+			return err;
+	}
+
+	if (buf_len % 256) {
+		rtsx_pci_init_cmd(pcr);
+
+		for (j = 0; j < buf_len % 256; j++) {
+			rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+					reg++, 0xFF, *ptr);
+			ptr++;
+		}
+
+		err = rtsx_pci_send_cmd(pcr, 250);
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_write_ppbuf);
+
+static int rtsx_pci_set_pull_ctl(struct rtsx_pcr *pcr, const u32 *tbl)
+{
+	int err;
+
+	rtsx_pci_init_cmd(pcr);
+
+	while (*tbl & 0xFFFF0000) {
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+				(u16)(*tbl >> 16), 0xFF, (u8)(*tbl));
+		tbl++;
+	}
+
+	err = rtsx_pci_send_cmd(pcr, 100);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card)
+{
+	const u32 *tbl;
+
+	if (card == RTSX_SD_CARD)
+		tbl = pcr->sd_pull_ctl_enable_tbl;
+	else if (card == RTSX_MS_CARD)
+		tbl = pcr->ms_pull_ctl_enable_tbl;
+	else
+		return -EINVAL;
+
+	return rtsx_pci_set_pull_ctl(pcr, tbl);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_card_pull_ctl_enable);
+
+int rtsx_pci_card_pull_ctl_disable(struct rtsx_pcr *pcr, int card)
+{
+	const u32 *tbl;
+
+	if (card == RTSX_SD_CARD)
+		tbl = pcr->sd_pull_ctl_disable_tbl;
+	else if (card == RTSX_MS_CARD)
+		tbl = pcr->ms_pull_ctl_disable_tbl;
+	else
+		return -EINVAL;
+
+
+	return rtsx_pci_set_pull_ctl(pcr, tbl);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_card_pull_ctl_disable);
+
+static void rtsx_pci_enable_bus_int(struct rtsx_pcr *pcr)
+{
+	pcr->bier = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN | SD_INT_EN;
+
+	if (pcr->num_slots > 1)
+		pcr->bier |= MS_INT_EN;
+
+	/* Enable Bus Interrupt */
+	rtsx_pci_writel(pcr, RTSX_BIER, pcr->bier);
+
+	dev_dbg(&(pcr->pci->dev), "RTSX_BIER: 0x%08x\n", pcr->bier);
+}
+
+static inline u8 double_ssc_depth(u8 depth)
+{
+	return ((depth > 1) ? (depth - 1) : depth);
+}
+
+static u8 revise_ssc_depth(u8 ssc_depth, u8 div)
+{
+	if (div > CLK_DIV_1) {
+		if (ssc_depth > (div - 1))
+			ssc_depth -= (div - 1);
+		else
+			ssc_depth = SSC_DEPTH_4M;
+	}
+
+	return ssc_depth;
+}
+
+int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
+		u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk)
+{
+	int err, clk;
+	u8 N, min_N, max_N, clk_divider;
+	u8 mcu_cnt, div, max_div;
+	u8 depth[] = {
+		[RTSX_SSC_DEPTH_4M] = SSC_DEPTH_4M,
+		[RTSX_SSC_DEPTH_2M] = SSC_DEPTH_2M,
+		[RTSX_SSC_DEPTH_1M] = SSC_DEPTH_1M,
+		[RTSX_SSC_DEPTH_500K] = SSC_DEPTH_500K,
+		[RTSX_SSC_DEPTH_250K] = SSC_DEPTH_250K,
+	};
+
+	if (initial_mode) {
+		/* We use 250k(around) here, in initial stage */
+		clk_divider = SD_CLK_DIVIDE_128;
+		card_clock = 30000000;
+	} else {
+		clk_divider = SD_CLK_DIVIDE_0;
+	}
+	err = rtsx_pci_write_register(pcr, SD_CFG1,
+			SD_CLK_DIVIDE_MASK, clk_divider);
+	if (err < 0)
+		return err;
+
+	card_clock /= 1000000;
+	dev_dbg(&(pcr->pci->dev), "Switch card clock to %dMHz\n", card_clock);
+
+	min_N = 80;
+	max_N = 208;
+	max_div = CLK_DIV_8;
+
+	clk = card_clock;
+	if (!initial_mode && double_clk)
+		clk = card_clock * 2;
+	dev_dbg(&(pcr->pci->dev),
+			"Internal SSC clock: %dMHz (cur_clock = %d)\n",
+			clk, pcr->cur_clock);
+
+	if (clk == pcr->cur_clock)
+		return 0;
+
+	N = (u8)(clk - 2);
+	if ((clk <= 2) || (N > max_N))
+		return -EINVAL;
+
+	mcu_cnt = (u8)(125/clk + 3);
+	if (mcu_cnt > 15)
+		mcu_cnt = 15;
+
+	/* Make sure that the SSC clock div_n is equal or greater than min_N */
+	div = CLK_DIV_1;
+	while ((N < min_N) && (div < max_div)) {
+		N = (N + 2) * 2 - 2;
+		div++;
+	}
+	dev_dbg(&(pcr->pci->dev), "N = %d, div = %d\n", N, div);
+
+	ssc_depth = depth[ssc_depth];
+	if (double_clk)
+		ssc_depth = double_ssc_depth(ssc_depth);
+
+	ssc_depth = revise_ssc_depth(ssc_depth, div);
+	dev_dbg(&(pcr->pci->dev), "ssc_depth = %d\n", ssc_depth);
+
+	rtsx_pci_init_cmd(pcr);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
+			CLK_LOW_FREQ, CLK_LOW_FREQ);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_DIV,
+			0xFF, (div << 4) | mcu_cnt);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2,
+			SSC_DEPTH_MASK, ssc_depth);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, N);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB);
+	if (vpclk) {
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+				PHASE_NOT_RESET, 0);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+				PHASE_NOT_RESET, PHASE_NOT_RESET);
+	}
+
+	err = rtsx_pci_send_cmd(pcr, 2000);
+	if (err < 0)
+		return err;
+
+	/* Wait SSC clock stable */
+	udelay(10);
+	err = rtsx_pci_write_register(pcr, CLK_CTL, CLK_LOW_FREQ, 0);
+	if (err < 0)
+		return err;
+
+	pcr->cur_clock = clk;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_switch_clock);
+
+int rtsx_pci_card_power_on(struct rtsx_pcr *pcr, int card)
+{
+	if (pcr->ops->card_power_on)
+		return pcr->ops->card_power_on(pcr, card);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_card_power_on);
+
+int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card)
+{
+	if (pcr->ops->card_power_off)
+		return pcr->ops->card_power_off(pcr, card);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off);
+
+unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr)
+{
+	unsigned int val;
+
+	val = rtsx_pci_readl(pcr, RTSX_BIPR);
+	if (pcr->ops->cd_deglitch)
+		val = pcr->ops->cd_deglitch(pcr);
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_card_exist);
+
+void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr)
+{
+	struct completion finish;
+
+	pcr->finish_me = &finish;
+	init_completion(&finish);
+
+	if (pcr->done)
+		complete(pcr->done);
+
+	if (!pcr->remove_pci)
+		rtsx_pci_stop_cmd(pcr);
+
+	wait_for_completion_interruptible_timeout(&finish,
+			msecs_to_jiffies(2));
+	pcr->finish_me = NULL;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_complete_unfinished_transfer);
+
+static void rtsx_pci_card_detect(struct work_struct *work)
+{
+	struct delayed_work *dwork;
+	struct rtsx_pcr *pcr;
+	unsigned long flags;
+	unsigned int card_detect = 0;
+	u32 irq_status;
+
+	dwork = to_delayed_work(work);
+	pcr = container_of(dwork, struct rtsx_pcr, carddet_work);
+
+	dev_dbg(&(pcr->pci->dev), "--> %s\n", __func__);
+
+	spin_lock_irqsave(&pcr->lock, flags);
+
+	irq_status = rtsx_pci_readl(pcr, RTSX_BIPR);
+	dev_dbg(&(pcr->pci->dev), "irq_status: 0x%08x\n", irq_status);
+
+	if (pcr->card_inserted || pcr->card_removed) {
+		dev_dbg(&(pcr->pci->dev),
+				"card_inserted: 0x%x, card_removed: 0x%x\n",
+				pcr->card_inserted, pcr->card_removed);
+
+		if (pcr->ops->cd_deglitch)
+			pcr->card_inserted = pcr->ops->cd_deglitch(pcr);
+
+		card_detect = pcr->card_inserted | pcr->card_removed;
+		pcr->card_inserted = 0;
+		pcr->card_removed = 0;
+	}
+
+	spin_unlock_irqrestore(&pcr->lock, flags);
+
+	if (card_detect & SD_EXIST)
+		pcr->slots[RTSX_SD_CARD].card_event(
+				pcr->slots[RTSX_SD_CARD].p_dev);
+	if (card_detect & MS_EXIST)
+		pcr->slots[RTSX_MS_CARD].card_event(
+				pcr->slots[RTSX_MS_CARD].p_dev);
+}
+
+static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
+{
+	struct rtsx_pcr *pcr = dev_id;
+	u32 int_reg;
+
+	if (!pcr)
+		return IRQ_NONE;
+
+	spin_lock(&pcr->lock);
+
+	int_reg = rtsx_pci_readl(pcr, RTSX_BIPR);
+	/* Clear interrupt flag */
+	rtsx_pci_writel(pcr, RTSX_BIPR, int_reg);
+	if ((int_reg & pcr->bier) == 0) {
+		spin_unlock(&pcr->lock);
+		return IRQ_NONE;
+	}
+	if (int_reg == 0xFFFFFFFF) {
+		spin_unlock(&pcr->lock);
+		return IRQ_HANDLED;
+	}
+
+	int_reg &= (pcr->bier | 0x7FFFFF);
+
+	if (int_reg & SD_INT) {
+		if (int_reg & SD_EXIST) {
+			pcr->card_inserted |= SD_EXIST;
+		} else {
+			pcr->card_removed |= SD_EXIST;
+			pcr->card_inserted &= ~SD_EXIST;
+		}
+	}
+
+	if (int_reg & MS_INT) {
+		if (int_reg & MS_EXIST) {
+			pcr->card_inserted |= MS_EXIST;
+		} else {
+			pcr->card_removed |= MS_EXIST;
+			pcr->card_inserted &= ~MS_EXIST;
+		}
+	}
+
+	if (pcr->card_inserted || pcr->card_removed)
+		schedule_delayed_work(&pcr->carddet_work,
+				msecs_to_jiffies(200));
+
+	if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) {
+		if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) {
+			pcr->trans_result = TRANS_RESULT_FAIL;
+			if (pcr->done)
+				complete(pcr->done);
+		} else if (int_reg & TRANS_OK_INT) {
+			pcr->trans_result = TRANS_RESULT_OK;
+			if (pcr->done)
+				complete(pcr->done);
+		}
+	}
+
+	spin_unlock(&pcr->lock);
+	return IRQ_HANDLED;
+}
+
+static int rtsx_pci_acquire_irq(struct rtsx_pcr *pcr)
+{
+	dev_info(&(pcr->pci->dev), "%s: pcr->msi_en = %d, pci->irq = %d\n",
+			__func__, pcr->msi_en, pcr->pci->irq);
+
+	if (request_irq(pcr->pci->irq, rtsx_pci_isr,
+			pcr->msi_en ? 0 : IRQF_SHARED,
+			DRV_NAME_RTSX_PCI, pcr)) {
+		dev_err(&(pcr->pci->dev),
+			"rtsx_sdmmc: unable to grab IRQ %d, disabling device\n",
+			pcr->pci->irq);
+		return -1;
+	}
+
+	pcr->irq = pcr->pci->irq;
+	pci_intx(pcr->pci, !pcr->msi_en);
+
+	return 0;
+}
+
+static void rtsx_pci_idle_work(struct work_struct *work)
+{
+	struct delayed_work *dwork = to_delayed_work(work);
+	struct rtsx_pcr *pcr = container_of(dwork, struct rtsx_pcr, idle_work);
+
+	dev_dbg(&(pcr->pci->dev), "--> %s\n", __func__);
+
+	mutex_lock(&pcr->pcr_mutex);
+
+	pcr->state = PDEV_STAT_IDLE;
+
+	if (pcr->ops->disable_auto_blink)
+		pcr->ops->disable_auto_blink(pcr);
+	if (pcr->ops->turn_off_led)
+		pcr->ops->turn_off_led(pcr);
+
+	mutex_unlock(&pcr->pcr_mutex);
+}
+
+static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
+{
+	int err;
+
+	rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
+
+	rtsx_pci_enable_bus_int(pcr);
+
+	/* Power on SSC */
+	err = rtsx_pci_write_register(pcr, FPDCTL, SSC_POWER_DOWN, 0);
+	if (err < 0)
+		return err;
+
+	/* Wait SSC power stable */
+	udelay(200);
+
+	if (pcr->ops->optimize_phy) {
+		err = pcr->ops->optimize_phy(pcr);
+		if (err < 0)
+			return err;
+	}
+
+	rtsx_pci_init_cmd(pcr);
+
+	/* Set mcu_cnt to 7 to ensure data can be sampled properly */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_DIV, 0x07, 0x07);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, HOST_SLEEP_STATE, 0x03, 0x00);
+	/* Disable card clock */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, 0x1E, 0);
+	/* Reset ASPM state to default value */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
+	/* Reset delink mode */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CHANGE_LINK_STATE, 0x0A, 0);
+	/* Card driving select */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
+			0x07, DRIVER_TYPE_D);
+	/* Enable SSC Clock */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1,
+			0xFF, SSC_8X_EN | SSC_SEL_4M);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2, 0xFF, 0x12);
+	/* Disable cd_pwr_save */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CHANGE_LINK_STATE, 0x16, 0x10);
+	/* Clear Link Ready Interrupt */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0,
+			LINK_RDY_INT, LINK_RDY_INT);
+	/* Enlarge the estimation window of PERST# glitch
+	 * to reduce the chance of invalid card interrupt
+	 */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PERST_GLITCH_WIDTH, 0xFF, 0x80);
+	/* Update RC oscillator to 400k
+	 * bit[0] F_HIGH: for RC oscillator, Rst_value is 1'b1
+	 *                1: 2M  0: 400k
+	 */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RCCTL, 0x01, 0x00);
+	/* Set interrupt write clear
+	 * bit 1: U_elbi_if_rd_clr_en
+	 *	1: Enable ELBI interrupt[31:22] & [7:0] flag read clear
+	 *	0: ELBI interrupt flag[31:22] & [7:0] only can be write clear
+	 */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, NFTS_TX_CTRL, 0x02, 0);
+	/* Force CLKREQ# PIN to drive 0 to request clock */
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x08, 0x08);
+
+	err = rtsx_pci_send_cmd(pcr, 100);
+	if (err < 0)
+		return err;
+
+	/* Enable clk_request_n to enable clock power management */
+	rtsx_pci_write_config_byte(pcr, 0x81, 1);
+	/* Enter L1 when host tx idle */
+	rtsx_pci_write_config_byte(pcr, 0x70F, 0x5B);
+
+	if (pcr->ops->extra_init_hw) {
+		err = pcr->ops->extra_init_hw(pcr);
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
+{
+	int err;
+
+	spin_lock_init(&pcr->lock);
+	mutex_init(&pcr->pcr_mutex);
+
+	switch (PCI_PID(pcr)) {
+	default:
+	case 0x5209:
+		rts5209_init_params(pcr);
+		break;
+
+	case 0x5229:
+		rts5229_init_params(pcr);
+		break;
+
+	case 0x5289:
+		rtl8411_init_params(pcr);
+		break;
+	}
+
+	dev_dbg(&(pcr->pci->dev), "PID: 0x%04x, IC version: 0x%02x\n",
+			PCI_PID(pcr), pcr->ic_version);
+
+	pcr->slots = kcalloc(pcr->num_slots, sizeof(struct rtsx_slot),
+			GFP_KERNEL);
+	if (!pcr->slots)
+		return -ENOMEM;
+
+	pcr->state = PDEV_STAT_IDLE;
+	err = rtsx_pci_init_hw(pcr);
+	if (err < 0) {
+		kfree(pcr->slots);
+		return err;
+	}
+
+	return 0;
+}
+
+static int __devinit rtsx_pci_probe(struct pci_dev *pcidev,
+				    const struct pci_device_id *id)
+{
+	struct rtsx_pcr *pcr;
+	struct pcr_handle *handle;
+	u32 base, len;
+	int ret, i;
+
+	dev_dbg(&(pcidev->dev),
+		": Realtek PCI-E Card Reader found at %s [%04x:%04x] (rev %x)\n",
+		pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device,
+		(int)pcidev->revision);
+
+	ret = pci_enable_device(pcidev);
+	if (ret)
+		return ret;
+
+	ret = pci_request_regions(pcidev, DRV_NAME_RTSX_PCI);
+	if (ret)
+		goto disable;
+
+	pcr = kzalloc(sizeof(*pcr), GFP_KERNEL);
+	if (!pcr) {
+		ret = -ENOMEM;
+		goto release_pci;
+	}
+
+	handle = kzalloc(sizeof(*handle), GFP_KERNEL);
+	if (!handle) {
+		ret = -ENOMEM;
+		goto free_pcr;
+	}
+	handle->pcr = pcr;
+
+	if (!idr_pre_get(&rtsx_pci_idr, GFP_KERNEL)) {
+		ret = -ENOMEM;
+		goto free_handle;
+	}
+
+	spin_lock(&rtsx_pci_lock);
+	ret = idr_get_new(&rtsx_pci_idr, pcr, &pcr->id);
+	spin_unlock(&rtsx_pci_lock);
+	if (ret)
+		goto free_handle;
+
+	pcr->pci = pcidev;
+	dev_set_drvdata(&pcidev->dev, handle);
+
+	len = pci_resource_len(pcidev, 0);
+	base = pci_resource_start(pcidev, 0);
+	pcr->remap_addr = ioremap_nocache(base, len);
+	if (!pcr->remap_addr) {
+		ret = -ENOMEM;
+		goto free_host;
+	}
+
+	pcr->rtsx_resv_buf = dma_alloc_coherent(&(pcidev->dev),
+			RTSX_RESV_BUF_LEN, &(pcr->rtsx_resv_buf_addr),
+			GFP_KERNEL);
+	if (pcr->rtsx_resv_buf == NULL) {
+		ret = -ENXIO;
+		goto unmap;
+	}
+	pcr->host_cmds_ptr = pcr->rtsx_resv_buf;
+	pcr->host_cmds_addr = pcr->rtsx_resv_buf_addr;
+	pcr->host_sg_tbl_ptr = pcr->rtsx_resv_buf + HOST_CMDS_BUF_LEN;
+	pcr->host_sg_tbl_addr = pcr->rtsx_resv_buf_addr + HOST_CMDS_BUF_LEN;
+
+	pcr->card_inserted = 0;
+	pcr->card_removed = 0;
+	INIT_DELAYED_WORK(&pcr->carddet_work, rtsx_pci_card_detect);
+	INIT_DELAYED_WORK(&pcr->idle_work, rtsx_pci_idle_work);
+
+	pcr->msi_en = msi_en;
+	if (pcr->msi_en) {
+		ret = pci_enable_msi(pcidev);
+		if (ret < 0)
+			pcr->msi_en = false;
+	}
+
+	ret = rtsx_pci_acquire_irq(pcr);
+	if (ret < 0)
+		goto free_dma;
+
+	pci_set_master(pcidev);
+	synchronize_irq(pcr->irq);
+
+	ret = rtsx_pci_init_chip(pcr);
+	if (ret < 0)
+		goto disable_irq;
+
+	for (i = 0; i < ARRAY_SIZE(rtsx_pcr_cells); i++) {
+		rtsx_pcr_cells[i].platform_data = handle;
+		rtsx_pcr_cells[i].pdata_size = sizeof(*handle);
+	}
+	ret = mfd_add_devices(&pcidev->dev, pcr->id, rtsx_pcr_cells,
+			ARRAY_SIZE(rtsx_pcr_cells), NULL, 0, NULL);
+	if (ret < 0)
+		goto disable_irq;
+
+	schedule_delayed_work(&pcr->idle_work, msecs_to_jiffies(200));
+
+	return 0;
+
+disable_irq:
+	free_irq(pcr->irq, (void *)pcr);
+free_dma:
+	dma_free_coherent(&(pcr->pci->dev), RTSX_RESV_BUF_LEN,
+			pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr);
+unmap:
+	iounmap(pcr->remap_addr);
+free_host:
+	dev_set_drvdata(&pcidev->dev, NULL);
+free_handle:
+	kfree(handle);
+free_pcr:
+	kfree(pcr);
+release_pci:
+	pci_release_regions(pcidev);
+disable:
+	pci_disable_device(pcidev);
+
+	return ret;
+}
+
+static void __devexit rtsx_pci_remove(struct pci_dev *pcidev)
+{
+	struct pcr_handle *handle = pci_get_drvdata(pcidev);
+	struct rtsx_pcr *pcr = handle->pcr;
+
+	pcr->remove_pci = true;
+
+	cancel_delayed_work(&pcr->carddet_work);
+	cancel_delayed_work(&pcr->idle_work);
+
+	mfd_remove_devices(&pcidev->dev);
+
+	dma_free_coherent(&(pcr->pci->dev), RTSX_RESV_BUF_LEN,
+			pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr);
+	free_irq(pcr->irq, (void *)pcr);
+	if (pcr->msi_en)
+		pci_disable_msi(pcr->pci);
+	iounmap(pcr->remap_addr);
+
+	dev_set_drvdata(&pcidev->dev, NULL);
+	pci_release_regions(pcidev);
+	pci_disable_device(pcidev);
+
+	spin_lock(&rtsx_pci_lock);
+	idr_remove(&rtsx_pci_idr, pcr->id);
+	spin_unlock(&rtsx_pci_lock);
+
+	kfree(pcr->slots);
+	kfree(pcr);
+	kfree(handle);
+
+	dev_dbg(&(pcidev->dev),
+		": Realtek PCI-E Card Reader at %s [%04x:%04x] has been removed\n",
+		pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device);
+}
+
+#ifdef CONFIG_PM
+
+static int rtsx_pci_suspend(struct pci_dev *pcidev, pm_message_t state)
+{
+	struct pcr_handle *handle;
+	struct rtsx_pcr *pcr;
+	int ret = 0;
+
+	dev_dbg(&(pcidev->dev), "--> %s\n", __func__);
+
+	handle = pci_get_drvdata(pcidev);
+	pcr = handle->pcr;
+
+	cancel_delayed_work(&pcr->carddet_work);
+	cancel_delayed_work(&pcr->idle_work);
+
+	mutex_lock(&pcr->pcr_mutex);
+
+	if (pcr->ops->turn_off_led)
+		pcr->ops->turn_off_led(pcr);
+
+	rtsx_pci_writel(pcr, RTSX_BIER, 0);
+	pcr->bier = 0;
+
+	rtsx_pci_write_register(pcr, PETXCFG, 0x08, 0x08);
+	rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, 0x02);
+
+	pci_save_state(pcidev);
+	pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0);
+	pci_disable_device(pcidev);
+	pci_set_power_state(pcidev, pci_choose_state(pcidev, state));
+
+	mutex_unlock(&pcr->pcr_mutex);
+	return ret;
+}
+
+static int rtsx_pci_resume(struct pci_dev *pcidev)
+{
+	struct pcr_handle *handle;
+	struct rtsx_pcr *pcr;
+	int ret = 0;
+
+	dev_dbg(&(pcidev->dev), "--> %s\n", __func__);
+
+	handle = pci_get_drvdata(pcidev);
+	pcr = handle->pcr;
+
+	mutex_lock(&pcr->pcr_mutex);
+
+	pci_set_power_state(pcidev, PCI_D0);
+	pci_restore_state(pcidev);
+	ret = pci_enable_device(pcidev);
+	if (ret)
+		goto out;
+	pci_set_master(pcidev);
+
+	ret = rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, 0x00);
+	if (ret)
+		goto out;
+
+	ret = rtsx_pci_init_hw(pcr);
+	if (ret)
+		goto out;
+
+	schedule_delayed_work(&pcr->idle_work, msecs_to_jiffies(200));
+
+out:
+	mutex_unlock(&pcr->pcr_mutex);
+	return ret;
+}
+
+#else /* CONFIG_PM */
+
+#define rtsx_pci_suspend NULL
+#define rtsx_pci_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct pci_driver rtsx_pci_driver = {
+	.name = DRV_NAME_RTSX_PCI,
+	.id_table = rtsx_pci_ids,
+	.probe = rtsx_pci_probe,
+	.remove = __devexit_p(rtsx_pci_remove),
+	.suspend = rtsx_pci_suspend,
+	.resume = rtsx_pci_resume,
+};
+module_pci_driver(rtsx_pci_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Wei WANG <wei_wang@realsil.com.cn>");
+MODULE_DESCRIPTION("Realtek PCI-E Card Reader Driver");
diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h
new file mode 100644
index 0000000..12462c1
--- /dev/null
+++ b/drivers/mfd/rtsx_pcr.h
@@ -0,0 +1,32 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __RTSX_PCR_H
+#define __RTSX_PCR_H
+
+#include <linux/mfd/rtsx_pci.h>
+
+void rts5209_init_params(struct rtsx_pcr *pcr);
+void rts5229_init_params(struct rtsx_pcr *pcr);
+void rtl8411_init_params(struct rtsx_pcr *pcr);
+
+#endif
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index c901fa5..0dd84e9 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -24,67 +24,67 @@
 
 static struct regmap_irq s2mps11_irqs[] = {
 	[S2MPS11_IRQ_PWRONF] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S2MPS11_IRQ_PWRONF_MASK,
 	},
 	[S2MPS11_IRQ_PWRONR] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S2MPS11_IRQ_PWRONR_MASK,
 	},
 	[S2MPS11_IRQ_JIGONBF] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S2MPS11_IRQ_JIGONBF_MASK,
 	},
 	[S2MPS11_IRQ_JIGONBR] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S2MPS11_IRQ_JIGONBR_MASK,
 	},
 	[S2MPS11_IRQ_ACOKBF] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S2MPS11_IRQ_ACOKBF_MASK,
 	},
 	[S2MPS11_IRQ_ACOKBR] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S2MPS11_IRQ_ACOKBR_MASK,
 	},
 	[S2MPS11_IRQ_PWRON1S] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S2MPS11_IRQ_PWRON1S_MASK,
 	},
 	[S2MPS11_IRQ_MRB] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S2MPS11_IRQ_MRB_MASK,
 	},
 	[S2MPS11_IRQ_RTC60S] = {
-		.reg_offset = 2,
+		.reg_offset = 1,
 		.mask = S2MPS11_IRQ_RTC60S_MASK,
 	},
 	[S2MPS11_IRQ_RTCA1] = {
-		.reg_offset = 2,
+		.reg_offset = 1,
 		.mask = S2MPS11_IRQ_RTCA1_MASK,
 	},
 	[S2MPS11_IRQ_RTCA2] = {
-		.reg_offset = 2,
+		.reg_offset = 1,
 		.mask = S2MPS11_IRQ_RTCA2_MASK,
 	},
 	[S2MPS11_IRQ_SMPL] = {
-		.reg_offset = 2,
+		.reg_offset = 1,
 		.mask = S2MPS11_IRQ_SMPL_MASK,
 	},
 	[S2MPS11_IRQ_RTC1S] = {
-		.reg_offset = 2,
+		.reg_offset = 1,
 		.mask = S2MPS11_IRQ_RTC1S_MASK,
 	},
 	[S2MPS11_IRQ_WTSR] = {
-		.reg_offset = 2,
+		.reg_offset = 1,
 		.mask = S2MPS11_IRQ_WTSR_MASK,
 	},
 	[S2MPS11_IRQ_INT120C] = {
-		.reg_offset = 3,
+		.reg_offset = 2,
 		.mask = S2MPS11_IRQ_INT120C_MASK,
 	},
 	[S2MPS11_IRQ_INT140C] = {
-		.reg_offset = 3,
+		.reg_offset = 2,
 		.mask = S2MPS11_IRQ_INT140C_MASK,
 	},
 };
@@ -92,146 +92,146 @@ static struct regmap_irq s2mps11_irqs[] = {
 
 static struct regmap_irq s5m8767_irqs[] = {
 	[S5M8767_IRQ_PWRR] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S5M8767_IRQ_PWRR_MASK,
 	},
 	[S5M8767_IRQ_PWRF] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S5M8767_IRQ_PWRF_MASK,
 	},
 	[S5M8767_IRQ_PWR1S] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S5M8767_IRQ_PWR1S_MASK,
 	},
 	[S5M8767_IRQ_JIGR] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S5M8767_IRQ_JIGR_MASK,
 	},
 	[S5M8767_IRQ_JIGF] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S5M8767_IRQ_JIGF_MASK,
 	},
 	[S5M8767_IRQ_LOWBAT2] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S5M8767_IRQ_LOWBAT2_MASK,
 	},
 	[S5M8767_IRQ_LOWBAT1] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S5M8767_IRQ_LOWBAT1_MASK,
 	},
 	[S5M8767_IRQ_MRB] = {
-		.reg_offset = 2,
+		.reg_offset = 1,
 		.mask = S5M8767_IRQ_MRB_MASK,
 	},
 	[S5M8767_IRQ_DVSOK2] = {
-		.reg_offset = 2,
+		.reg_offset = 1,
 		.mask = S5M8767_IRQ_DVSOK2_MASK,
 	},
 	[S5M8767_IRQ_DVSOK3] = {
-		.reg_offset = 2,
+		.reg_offset = 1,
 		.mask = S5M8767_IRQ_DVSOK3_MASK,
 	},
 	[S5M8767_IRQ_DVSOK4] = {
-		.reg_offset = 2,
+		.reg_offset = 1,
 		.mask = S5M8767_IRQ_DVSOK4_MASK,
 	},
 	[S5M8767_IRQ_RTC60S] = {
-		.reg_offset = 3,
+		.reg_offset = 2,
 		.mask = S5M8767_IRQ_RTC60S_MASK,
 	},
 	[S5M8767_IRQ_RTCA1] = {
-		.reg_offset = 3,
+		.reg_offset = 2,
 		.mask = S5M8767_IRQ_RTCA1_MASK,
 	},
 	[S5M8767_IRQ_RTCA2] = {
-		.reg_offset = 3,
+		.reg_offset = 2,
 		.mask = S5M8767_IRQ_RTCA2_MASK,
 	},
 	[S5M8767_IRQ_SMPL] = {
-		.reg_offset = 3,
+		.reg_offset = 2,
 		.mask = S5M8767_IRQ_SMPL_MASK,
 	},
 	[S5M8767_IRQ_RTC1S] = {
-		.reg_offset = 3,
+		.reg_offset = 2,
 		.mask = S5M8767_IRQ_RTC1S_MASK,
 	},
 	[S5M8767_IRQ_WTSR] = {
-		.reg_offset = 3,
+		.reg_offset = 2,
 		.mask = S5M8767_IRQ_WTSR_MASK,
 	},
 };
 
 static struct regmap_irq s5m8763_irqs[] = {
 	[S5M8763_IRQ_DCINF] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S5M8763_IRQ_DCINF_MASK,
 	},
 	[S5M8763_IRQ_DCINR] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S5M8763_IRQ_DCINR_MASK,
 	},
 	[S5M8763_IRQ_JIGF] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S5M8763_IRQ_JIGF_MASK,
 	},
 	[S5M8763_IRQ_JIGR] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S5M8763_IRQ_JIGR_MASK,
 	},
 	[S5M8763_IRQ_PWRONF] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S5M8763_IRQ_PWRONF_MASK,
 	},
 	[S5M8763_IRQ_PWRONR] = {
-		.reg_offset = 1,
+		.reg_offset = 0,
 		.mask = S5M8763_IRQ_PWRONR_MASK,
 	},
 	[S5M8763_IRQ_WTSREVNT] = {
-		.reg_offset = 2,
+		.reg_offset = 1,
 		.mask = S5M8763_IRQ_WTSREVNT_MASK,
 	},
 	[S5M8763_IRQ_SMPLEVNT] = {
-		.reg_offset = 2,
+		.reg_offset = 1,
 		.mask = S5M8763_IRQ_SMPLEVNT_MASK,
 	},
 	[S5M8763_IRQ_ALARM1] = {
-		.reg_offset = 2,
+		.reg_offset = 1,
 		.mask = S5M8763_IRQ_ALARM1_MASK,
 	},
 	[S5M8763_IRQ_ALARM0] = {
-		.reg_offset = 2,
+		.reg_offset = 1,
 		.mask = S5M8763_IRQ_ALARM0_MASK,
 	},
 	[S5M8763_IRQ_ONKEY1S] = {
-		.reg_offset = 3,
+		.reg_offset = 2,
 		.mask = S5M8763_IRQ_ONKEY1S_MASK,
 	},
 	[S5M8763_IRQ_TOPOFFR] = {
-		.reg_offset = 3,
+		.reg_offset = 2,
 		.mask = S5M8763_IRQ_TOPOFFR_MASK,
 	},
 	[S5M8763_IRQ_DCINOVPR] = {
-		.reg_offset = 3,
+		.reg_offset = 2,
 		.mask = S5M8763_IRQ_DCINOVPR_MASK,
 	},
 	[S5M8763_IRQ_CHGRSTF] = {
-		.reg_offset = 3,
+		.reg_offset = 2,
 		.mask = S5M8763_IRQ_CHGRSTF_MASK,
 	},
 	[S5M8763_IRQ_DONER] = {
-		.reg_offset = 3,
+		.reg_offset = 2,
 		.mask = S5M8763_IRQ_DONER_MASK,
 	},
 	[S5M8763_IRQ_CHGFAULT] = {
-		.reg_offset = 3,
+		.reg_offset = 2,
 		.mask = S5M8763_IRQ_CHGFAULT_MASK,
 	},
 	[S5M8763_IRQ_LOBAT1] = {
-		.reg_offset = 4,
+		.reg_offset = 3,
 		.mask = S5M8763_IRQ_LOBAT1_MASK,
 	},
 	[S5M8763_IRQ_LOBAT2] = {
-		.reg_offset = 4,
+		.reg_offset = 3,
 		.mask = S5M8763_IRQ_LOBAT2_MASK,
 	},
 };
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index d927dd4..9816c23 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1014,7 +1014,7 @@ static struct gpio_chip gpio_chip_template = {
 	.get			= sm501_gpio_get,
 };
 
-static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm,
+static int sm501_gpio_register_chip(struct sm501_devdata *sm,
 					      struct sm501_gpio *gpio,
 					      struct sm501_gpio_chip *chip)
 {
@@ -1042,7 +1042,7 @@ static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm,
 	return gpiochip_add(gchip);
 }
 
-static int __devinit sm501_register_gpio(struct sm501_devdata *sm)
+static int sm501_register_gpio(struct sm501_devdata *sm)
 {
 	struct sm501_gpio *gpio = &sm->gpio;
 	resource_size_t iobase = sm->io_res->start + SM501_GPIO;
@@ -1313,7 +1313,7 @@ static unsigned int sm501_mem_local[] = {
  * Common init code for an SM501
 */
 
-static int __devinit sm501_init_dev(struct sm501_devdata *sm)
+static int sm501_init_dev(struct sm501_devdata *sm)
 {
 	struct sm501_initdata *idata;
 	struct sm501_platdata *pdata;
@@ -1389,7 +1389,7 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
 	return 0;
 }
 
-static int __devinit sm501_plat_probe(struct platform_device *dev)
+static int sm501_plat_probe(struct platform_device *dev)
 {
 	struct sm501_devdata *sm;
 	int ret;
@@ -1578,7 +1578,7 @@ static struct sm501_platdata sm501_pci_platdata = {
 	.gpio_base	= -1,
 };
 
-static int __devinit sm501_pci_probe(struct pci_dev *dev,
+static int sm501_pci_probe(struct pci_dev *dev,
 				     const struct pci_device_id *id)
 {
 	struct sm501_devdata *sm;
@@ -1685,7 +1685,7 @@ static void sm501_dev_remove(struct sm501_devdata *sm)
 	sm501_gpio_remove(sm);
 }
 
-static void __devexit sm501_pci_remove(struct pci_dev *dev)
+static void sm501_pci_remove(struct pci_dev *dev)
 {
 	struct sm501_devdata *sm = pci_get_drvdata(dev);
 
@@ -1723,12 +1723,12 @@ static struct pci_driver sm501_pci_driver = {
 	.name		= "sm501",
 	.id_table	= sm501_pci_tbl,
 	.probe		= sm501_pci_probe,
-	.remove		= __devexit_p(sm501_pci_remove),
+	.remove		= sm501_pci_remove,
 };
 
 MODULE_ALIAS("platform:sm501");
 
-static struct of_device_id __devinitdata of_sm501_match_tbl[] = {
+static struct of_device_id of_sm501_match_tbl[] = {
 	{ .compatible = "smi,sm501", },
 	{ /* end */ }
 };
diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c
index d35da68..012a521 100644
--- a/drivers/mfd/sta2x11-mfd.c
+++ b/drivers/mfd/sta2x11-mfd.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2009-2011 Wind River Systems, Inc.
- * Copyright (c) 2011 ST Microelectronics (Alessandro Rubini)
+ * Copyright (c) 2011 ST Microelectronics (Alessandro Rubini, Davide Ciminaghi)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -27,21 +27,28 @@
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
-#include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/sta2x11-mfd.h>
+#include <linux/regmap.h>
 
 #include <asm/sta2x11.h>
 
+static inline int __reg_within_range(unsigned int r,
+				     unsigned int start,
+				     unsigned int end)
+{
+	return ((r >= start) && (r <= end));
+}
+
 /* This describes STA2X11 MFD chip for us, we may have several */
 struct sta2x11_mfd {
 	struct sta2x11_instance *instance;
-	spinlock_t lock;
+	struct regmap *regmap[sta2x11_n_mfd_plat_devs];
+	spinlock_t lock[sta2x11_n_mfd_plat_devs];
 	struct list_head list;
-	void __iomem *sctl_regs;
-	void __iomem *apbreg_regs;
+	void __iomem *regs[sta2x11_n_mfd_plat_devs];
 };
 
 static LIST_HEAD(sta2x11_mfd_list);
@@ -69,8 +76,9 @@ static struct sta2x11_mfd *sta2x11_mfd_find(struct pci_dev *pdev)
 	return NULL;
 }
 
-static int __devinit sta2x11_mfd_add(struct pci_dev *pdev, gfp_t flags)
+static int sta2x11_mfd_add(struct pci_dev *pdev, gfp_t flags)
 {
+	int i;
 	struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev);
 	struct sta2x11_instance *instance;
 
@@ -83,13 +91,14 @@ static int __devinit sta2x11_mfd_add(struct pci_dev *pdev, gfp_t flags)
 	if (!mfd)
 		return -ENOMEM;
 	INIT_LIST_HEAD(&mfd->list);
-	spin_lock_init(&mfd->lock);
+	for (i = 0; i < ARRAY_SIZE(mfd->lock); i++)
+		spin_lock_init(&mfd->lock[i]);
 	mfd->instance = instance;
 	list_add(&mfd->list, &sta2x11_mfd_list);
 	return 0;
 }
 
-static int __devexit mfd_remove(struct pci_dev *pdev)
+static int mfd_remove(struct pci_dev *pdev)
 {
 	struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev);
 
@@ -100,161 +109,274 @@ static int __devexit mfd_remove(struct pci_dev *pdev)
 	return 0;
 }
 
-/* These two functions are exported and are not expected to fail */
-u32 sta2x11_sctl_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val)
+/* This function is exported and is not expected to fail */
+u32 __sta2x11_mfd_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val,
+		       enum sta2x11_mfd_plat_dev index)
 {
 	struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev);
 	u32 r;
 	unsigned long flags;
+	void __iomem *regs = mfd->regs[index];
 
 	if (!mfd) {
 		dev_warn(&pdev->dev, ": can't access sctl regs\n");
 		return 0;
 	}
-	if (!mfd->sctl_regs) {
+	if (!regs) {
 		dev_warn(&pdev->dev, ": system ctl not initialized\n");
 		return 0;
 	}
-	spin_lock_irqsave(&mfd->lock, flags);
-	r = readl(mfd->sctl_regs + reg);
+	spin_lock_irqsave(&mfd->lock[index], flags);
+	r = readl(regs + reg);
 	r &= ~mask;
 	r |= val;
 	if (mask)
-		writel(r, mfd->sctl_regs + reg);
-	spin_unlock_irqrestore(&mfd->lock, flags);
+		writel(r, regs + reg);
+	spin_unlock_irqrestore(&mfd->lock[index], flags);
 	return r;
 }
-EXPORT_SYMBOL(sta2x11_sctl_mask);
+EXPORT_SYMBOL(__sta2x11_mfd_mask);
 
-u32 sta2x11_apbreg_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val)
+int sta2x11_mfd_get_regs_data(struct platform_device *dev,
+			      enum sta2x11_mfd_plat_dev index,
+			      void __iomem **regs,
+			      spinlock_t **lock)
 {
-	struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev);
-	u32 r;
-	unsigned long flags;
+	struct pci_dev *pdev = *(struct pci_dev **)(dev->dev.platform_data);
+	struct sta2x11_mfd *mfd;
 
-	if (!mfd) {
-		dev_warn(&pdev->dev, ": can't access apb regs\n");
-		return 0;
-	}
-	if (!mfd->apbreg_regs) {
-		dev_warn(&pdev->dev, ": apb bridge not initialized\n");
-		return 0;
-	}
-	spin_lock_irqsave(&mfd->lock, flags);
-	r = readl(mfd->apbreg_regs + reg);
-	r &= ~mask;
-	r |= val;
-	if (mask)
-		writel(r, mfd->apbreg_regs + reg);
-	spin_unlock_irqrestore(&mfd->lock, flags);
-	return r;
+	if (!pdev)
+		return -ENODEV;
+	mfd = sta2x11_mfd_find(pdev);
+	if (!mfd)
+		return -ENODEV;
+	if (index >= sta2x11_n_mfd_plat_devs)
+		return -ENODEV;
+	*regs = mfd->regs[index];
+	*lock = &mfd->lock[index];
+	pr_debug("%s %d *regs = %p\n", __func__, __LINE__, *regs);
+	return *regs ? 0 : -ENODEV;
 }
-EXPORT_SYMBOL(sta2x11_apbreg_mask);
-
-/* Two debugfs files, for our registers (FIXME: one instance only) */
-#define REG(regname) {.name = #regname, .offset = SCTL_ ## regname}
-static struct debugfs_reg32 sta2x11_sctl_regs[] = {
-	REG(SCCTL), REG(ARMCFG), REG(SCPLLCTL), REG(SCPLLFCTRL),
-	REG(SCRESFRACT), REG(SCRESCTRL1), REG(SCRESXTRL2), REG(SCPEREN0),
-	REG(SCPEREN1), REG(SCPEREN2), REG(SCGRST), REG(SCPCIPMCR1),
-	REG(SCPCIPMCR2), REG(SCPCIPMSR1), REG(SCPCIPMSR2), REG(SCPCIPMSR3),
-	REG(SCINTREN), REG(SCRISR), REG(SCCLKSTAT0), REG(SCCLKSTAT1),
-	REG(SCCLKSTAT2), REG(SCRSTSTA),
-};
-#undef REG
+EXPORT_SYMBOL(sta2x11_mfd_get_regs_data);
 
-static struct debugfs_regset32 sctl_regset = {
-	.regs = sta2x11_sctl_regs,
-	.nregs = ARRAY_SIZE(sta2x11_sctl_regs),
-};
+/*
+ * Special sta2x11-mfd regmap lock/unlock functions
+ */
+
+static void sta2x11_regmap_lock(void *__lock)
+{
+	spinlock_t *lock = __lock;
+	spin_lock(lock);
+}
 
-#define REG(regname) {.name = #regname, .offset = regname}
-static struct debugfs_reg32 sta2x11_apbreg_regs[] = {
-	REG(APBREG_BSR), REG(APBREG_PAER), REG(APBREG_PWAC), REG(APBREG_PRAC),
-	REG(APBREG_PCG), REG(APBREG_PUR), REG(APBREG_EMU_PCG),
+static void sta2x11_regmap_unlock(void *__lock)
+{
+	spinlock_t *lock = __lock;
+	spin_unlock(lock);
+}
+
+/* OTP (one time programmable registers do not require locking */
+static void sta2x11_regmap_nolock(void *__lock)
+{
+}
+
+static const char *sta2x11_mfd_names[sta2x11_n_mfd_plat_devs] = {
+	[sta2x11_sctl] = STA2X11_MFD_SCTL_NAME,
+	[sta2x11_apbreg] = STA2X11_MFD_APBREG_NAME,
+	[sta2x11_apb_soc_regs] = STA2X11_MFD_APB_SOC_REGS_NAME,
+	[sta2x11_scr] = STA2X11_MFD_SCR_NAME,
 };
-#undef REG
 
-static struct debugfs_regset32 apbreg_regset = {
-	.regs = sta2x11_apbreg_regs,
-	.nregs = ARRAY_SIZE(sta2x11_apbreg_regs),
+static bool sta2x11_sctl_writeable_reg(struct device *dev, unsigned int reg)
+{
+	return !__reg_within_range(reg, SCTL_SCPCIECSBRST, SCTL_SCRSTSTA);
+}
+
+static struct regmap_config sta2x11_sctl_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.lock = sta2x11_regmap_lock,
+	.unlock = sta2x11_regmap_unlock,
+	.max_register = SCTL_SCRSTSTA,
+	.writeable_reg = sta2x11_sctl_writeable_reg,
 };
 
-static struct dentry *sta2x11_sctl_debugfs;
-static struct dentry *sta2x11_apbreg_debugfs;
+static bool sta2x11_scr_readable_reg(struct device *dev, unsigned int reg)
+{
+	return (reg == STA2X11_SECR_CR) ||
+		__reg_within_range(reg, STA2X11_SECR_FVR0, STA2X11_SECR_FVR1);
+}
 
-/* Probe for the two platform devices */
-static int sta2x11_sctl_probe(struct platform_device *dev)
+static bool sta2x11_scr_writeable_reg(struct device *dev, unsigned int reg)
 {
-	struct pci_dev **pdev;
-	struct sta2x11_mfd *mfd;
-	struct resource *res;
+	return false;
+}
 
-	pdev = dev->dev.platform_data;
-	mfd = sta2x11_mfd_find(*pdev);
-	if (!mfd)
-		return -ENODEV;
+static struct regmap_config sta2x11_scr_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.lock = sta2x11_regmap_nolock,
+	.unlock = sta2x11_regmap_nolock,
+	.max_register = STA2X11_SECR_FVR1,
+	.readable_reg = sta2x11_scr_readable_reg,
+	.writeable_reg = sta2x11_scr_writeable_reg,
+};
 
-	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENOMEM;
+static bool sta2x11_apbreg_readable_reg(struct device *dev, unsigned int reg)
+{
+	/* Two blocks (CAN and MLB, SARAC) 0x100 bytes apart */
+	if (reg >= APBREG_BSR_SARAC)
+		reg -= APBREG_BSR_SARAC;
+	switch (reg) {
+	case APBREG_BSR:
+	case APBREG_PAER:
+	case APBREG_PWAC:
+	case APBREG_PRAC:
+	case APBREG_PCG:
+	case APBREG_PUR:
+	case APBREG_EMU_PCG:
+		return true;
+	default:
+		return false;
+	}
+}
 
-	if (!request_mem_region(res->start, resource_size(res),
-				"sta2x11-sctl"))
-		return -EBUSY;
+static bool sta2x11_apbreg_writeable_reg(struct device *dev, unsigned int reg)
+{
+	if (reg >= APBREG_BSR_SARAC)
+		reg -= APBREG_BSR_SARAC;
+	if (!sta2x11_apbreg_readable_reg(dev, reg))
+		return false;
+	return reg != APBREG_PAER;
+}
 
-	mfd->sctl_regs = ioremap(res->start, resource_size(res));
-	if (!mfd->sctl_regs) {
-		release_mem_region(res->start, resource_size(res));
-		return -ENOMEM;
+static struct regmap_config sta2x11_apbreg_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.lock = sta2x11_regmap_lock,
+	.unlock = sta2x11_regmap_unlock,
+	.max_register = APBREG_EMU_PCG_SARAC,
+	.readable_reg = sta2x11_apbreg_readable_reg,
+	.writeable_reg = sta2x11_apbreg_writeable_reg,
+};
+
+static bool sta2x11_apb_soc_regs_readable_reg(struct device *dev,
+					      unsigned int reg)
+{
+	return reg <= PCIE_SoC_INT_ROUTER_STATUS3_REG ||
+		__reg_within_range(reg, DMA_IP_CTRL_REG, SPARE3_RESERVED) ||
+		__reg_within_range(reg, MASTER_LOCK_REG,
+				   SYSTEM_CONFIG_STATUS_REG) ||
+		reg == MSP_CLK_CTRL_REG ||
+		__reg_within_range(reg, COMPENSATION_REG1, TEST_CTL_REG);
+}
+
+static bool sta2x11_apb_soc_regs_writeable_reg(struct device *dev,
+					       unsigned int reg)
+{
+	if (!sta2x11_apb_soc_regs_readable_reg(dev, reg))
+		return false;
+	switch (reg) {
+	case PCIE_COMMON_CLOCK_CONFIG_0_4_0:
+	case SYSTEM_CONFIG_STATUS_REG:
+	case COMPENSATION_REG1:
+	case PCIE_SoC_INT_ROUTER_STATUS0_REG...PCIE_SoC_INT_ROUTER_STATUS3_REG:
+	case PCIE_PM_STATUS_0_PORT_0_4...PCIE_PM_STATUS_7_0_EP4:
+		return false;
+	default:
+		return true;
 	}
-	sctl_regset.base = mfd->sctl_regs;
-	sta2x11_sctl_debugfs = debugfs_create_regset32("sta2x11-sctl",
-						  S_IFREG | S_IRUGO,
-						  NULL, &sctl_regset);
-	return 0;
 }
 
-static int sta2x11_apbreg_probe(struct platform_device *dev)
+static struct regmap_config sta2x11_apb_soc_regs_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.lock = sta2x11_regmap_lock,
+	.unlock = sta2x11_regmap_unlock,
+	.max_register = TEST_CTL_REG,
+	.readable_reg = sta2x11_apb_soc_regs_readable_reg,
+	.writeable_reg = sta2x11_apb_soc_regs_writeable_reg,
+};
+
+static struct regmap_config *
+sta2x11_mfd_regmap_configs[sta2x11_n_mfd_plat_devs] = {
+	[sta2x11_sctl] = &sta2x11_sctl_regmap_config,
+	[sta2x11_apbreg] = &sta2x11_apbreg_regmap_config,
+	[sta2x11_apb_soc_regs] = &sta2x11_apb_soc_regs_regmap_config,
+	[sta2x11_scr] = &sta2x11_scr_regmap_config,
+};
+
+/* Probe for the four platform devices */
+
+static int sta2x11_mfd_platform_probe(struct platform_device *dev,
+				      enum sta2x11_mfd_plat_dev index)
 {
 	struct pci_dev **pdev;
 	struct sta2x11_mfd *mfd;
 	struct resource *res;
+	const char *name = sta2x11_mfd_names[index];
+	struct regmap_config *regmap_config = sta2x11_mfd_regmap_configs[index];
 
 	pdev = dev->dev.platform_data;
-	dev_dbg(&dev->dev, "%s: pdata is %p\n", __func__, pdev);
-	dev_dbg(&dev->dev, "%s: *pdata is %p\n", __func__, *pdev);
-
 	mfd = sta2x11_mfd_find(*pdev);
 	if (!mfd)
 		return -ENODEV;
+	if (!regmap_config)
+		return -ENODEV;
 
 	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
 	if (!res)
 		return -ENOMEM;
 
-	if (!request_mem_region(res->start, resource_size(res),
-				"sta2x11-apbreg"))
+	if (!request_mem_region(res->start, resource_size(res), name))
 		return -EBUSY;
 
-	mfd->apbreg_regs = ioremap(res->start, resource_size(res));
-	if (!mfd->apbreg_regs) {
+	mfd->regs[index] = ioremap(res->start, resource_size(res));
+	if (!mfd->regs[index]) {
 		release_mem_region(res->start, resource_size(res));
 		return -ENOMEM;
 	}
-	dev_dbg(&dev->dev, "%s: regbase %p\n", __func__, mfd->apbreg_regs);
+	regmap_config->lock_arg = &mfd->lock;
+	/*
+	   No caching, registers could be reached both via regmap and via
+	   void __iomem *
+	*/
+	regmap_config->cache_type = REGCACHE_NONE;
+	mfd->regmap[index] = devm_regmap_init_mmio(&dev->dev, mfd->regs[index],
+						   regmap_config);
+	WARN_ON(!mfd->regmap[index]);
 
-	apbreg_regset.base = mfd->apbreg_regs;
-	sta2x11_apbreg_debugfs = debugfs_create_regset32("sta2x11-apbreg",
-						  S_IFREG | S_IRUGO,
-						  NULL, &apbreg_regset);
 	return 0;
 }
 
-/* The two platform drivers */
+static int sta2x11_sctl_probe(struct platform_device *dev)
+{
+	return sta2x11_mfd_platform_probe(dev, sta2x11_sctl);
+}
+
+static int sta2x11_apbreg_probe(struct platform_device *dev)
+{
+	return sta2x11_mfd_platform_probe(dev, sta2x11_apbreg);
+}
+
+static int sta2x11_apb_soc_regs_probe(struct platform_device *dev)
+{
+	return sta2x11_mfd_platform_probe(dev, sta2x11_apb_soc_regs);
+}
+
+static int sta2x11_scr_probe(struct platform_device *dev)
+{
+	return sta2x11_mfd_platform_probe(dev, sta2x11_scr);
+}
+
+/* The three platform drivers */
 static struct platform_driver sta2x11_sctl_platform_driver = {
 	.driver = {
-		.name	= "sta2x11-sctl",
+		.name	= STA2X11_MFD_SCTL_NAME,
 		.owner	= THIS_MODULE,
 	},
 	.probe		= sta2x11_sctl_probe,
@@ -268,7 +390,7 @@ static int __init sta2x11_sctl_init(void)
 
 static struct platform_driver sta2x11_platform_driver = {
 	.driver = {
-		.name	= "sta2x11-apbreg",
+		.name	= STA2X11_MFD_APBREG_NAME,
 		.owner	= THIS_MODULE,
 	},
 	.probe		= sta2x11_apbreg_probe,
@@ -280,13 +402,44 @@ static int __init sta2x11_apbreg_init(void)
 	return platform_driver_register(&sta2x11_platform_driver);
 }
 
+static struct platform_driver sta2x11_apb_soc_regs_platform_driver = {
+	.driver = {
+		.name	= STA2X11_MFD_APB_SOC_REGS_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sta2x11_apb_soc_regs_probe,
+};
+
+static int __init sta2x11_apb_soc_regs_init(void)
+{
+	pr_info("%s\n", __func__);
+	return platform_driver_register(&sta2x11_apb_soc_regs_platform_driver);
+}
+
+static struct platform_driver sta2x11_scr_platform_driver = {
+	.driver = {
+		.name = STA2X11_MFD_SCR_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = sta2x11_scr_probe,
+};
+
+static int __init sta2x11_scr_init(void)
+{
+	pr_info("%s\n", __func__);
+	return platform_driver_register(&sta2x11_scr_platform_driver);
+}
+
+
 /*
- * What follows is the PCI device that hosts the above two pdevs.
+ * What follows are the PCI devices that host the above pdevs.
  * Each logic block is 4kB and they are all consecutive: we use this info.
  */
 
-/* Bar 0 */
-enum bar0_cells {
+/* Mfd 0 device */
+
+/* Mfd 0, Bar 0 */
+enum mfd0_bar0_cells {
 	STA2X11_GPIO_0 = 0,
 	STA2X11_GPIO_1,
 	STA2X11_GPIO_2,
@@ -295,8 +448,8 @@ enum bar0_cells {
 	STA2X11_SCR,
 	STA2X11_TIME,
 };
-/* Bar 1 */
-enum bar1_cells {
+/* Mfd 0 , Bar 1 */
+enum mfd0_bar1_cells {
 	STA2X11_APBREG = 0,
 };
 #define CELL_4K(_name, _cell) { \
@@ -305,42 +458,73 @@ enum bar1_cells {
 		.flags = IORESOURCE_MEM, \
 		}
 
-static const __devinitconst struct resource gpio_resources[] = {
+static const struct resource gpio_resources[] = {
 	{
-		.name = "sta2x11_gpio", /* 4 consecutive cells, 1 driver */
+		/* 4 consecutive cells, 1 driver */
+		.name = STA2X11_MFD_GPIO_NAME,
 		.start = 0,
 		.end = (4 * 4096) - 1,
 		.flags = IORESOURCE_MEM,
 	}
 };
-static const __devinitconst struct resource sctl_resources[] = {
-	CELL_4K("sta2x11-sctl", STA2X11_SCTL),
+static const struct resource sctl_resources[] = {
+	CELL_4K(STA2X11_MFD_SCTL_NAME, STA2X11_SCTL),
 };
-static const __devinitconst struct resource scr_resources[] = {
-	CELL_4K("sta2x11-scr", STA2X11_SCR),
+static const struct resource scr_resources[] = {
+	CELL_4K(STA2X11_MFD_SCR_NAME, STA2X11_SCR),
 };
-static const __devinitconst struct resource time_resources[] = {
-	CELL_4K("sta2x11-time", STA2X11_TIME),
+static const struct resource time_resources[] = {
+	CELL_4K(STA2X11_MFD_TIME_NAME, STA2X11_TIME),
 };
 
-static const __devinitconst struct resource apbreg_resources[] = {
-	CELL_4K("sta2x11-apbreg", STA2X11_APBREG),
+static const struct resource apbreg_resources[] = {
+	CELL_4K(STA2X11_MFD_APBREG_NAME, STA2X11_APBREG),
 };
 
 #define DEV(_name, _r) \
 	{ .name = _name, .num_resources = ARRAY_SIZE(_r), .resources = _r, }
 
-static __devinitdata struct mfd_cell sta2x11_mfd_bar0[] = {
-	DEV("sta2x11-gpio", gpio_resources), /* offset 0: we add pdata later */
-	DEV("sta2x11-sctl", sctl_resources),
-	DEV("sta2x11-scr", scr_resources),
-	DEV("sta2x11-time", time_resources),
+static struct mfd_cell sta2x11_mfd0_bar0[] = {
+	/* offset 0: we add pdata later */
+	DEV(STA2X11_MFD_GPIO_NAME, gpio_resources),
+	DEV(STA2X11_MFD_SCTL_NAME, sctl_resources),
+	DEV(STA2X11_MFD_SCR_NAME,  scr_resources),
+	DEV(STA2X11_MFD_TIME_NAME, time_resources),
 };
 
-static __devinitdata struct mfd_cell sta2x11_mfd_bar1[] = {
-	DEV("sta2x11-apbreg", apbreg_resources),
+static struct mfd_cell sta2x11_mfd0_bar1[] = {
+	DEV(STA2X11_MFD_APBREG_NAME, apbreg_resources),
 };
 
+/* Mfd 1 devices */
+
+/* Mfd 1, Bar 0 */
+enum mfd1_bar0_cells {
+	STA2X11_VIC = 0,
+};
+
+/* Mfd 1, Bar 1 */
+enum mfd1_bar1_cells {
+	STA2X11_APB_SOC_REGS = 0,
+};
+
+static const struct resource vic_resources[] = {
+	CELL_4K(STA2X11_MFD_VIC_NAME, STA2X11_VIC),
+};
+
+static const struct resource apb_soc_regs_resources[] = {
+	CELL_4K(STA2X11_MFD_APB_SOC_REGS_NAME, STA2X11_APB_SOC_REGS),
+};
+
+static struct mfd_cell sta2x11_mfd1_bar0[] = {
+	DEV(STA2X11_MFD_VIC_NAME, vic_resources),
+};
+
+static struct mfd_cell sta2x11_mfd1_bar1[] = {
+	DEV(STA2X11_MFD_APB_SOC_REGS_NAME, apb_soc_regs_resources),
+};
+
+
 static int sta2x11_mfd_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	pci_save_state(pdev);
@@ -363,11 +547,63 @@ static int sta2x11_mfd_resume(struct pci_dev *pdev)
 	return 0;
 }
 
-static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev,
+struct sta2x11_mfd_bar_setup_data {
+	struct mfd_cell *cells;
+	int ncells;
+};
+
+struct sta2x11_mfd_setup_data {
+	struct sta2x11_mfd_bar_setup_data bars[2];
+};
+
+#define STA2X11_MFD0 0
+#define STA2X11_MFD1 1
+
+static struct sta2x11_mfd_setup_data mfd_setup_data[] = {
+	/* Mfd 0: gpio, sctl, scr, timers / apbregs */
+	[STA2X11_MFD0] = {
+		.bars = {
+			[0] = {
+				.cells = sta2x11_mfd0_bar0,
+				.ncells = ARRAY_SIZE(sta2x11_mfd0_bar0),
+			},
+			[1] = {
+				.cells = sta2x11_mfd0_bar1,
+				.ncells = ARRAY_SIZE(sta2x11_mfd0_bar1),
+			},
+		},
+	},
+	/* Mfd 1: vic / apb-soc-regs */
+	[STA2X11_MFD1] = {
+		.bars = {
+			[0] = {
+				.cells = sta2x11_mfd1_bar0,
+				.ncells = ARRAY_SIZE(sta2x11_mfd1_bar0),
+			},
+			[1] = {
+				.cells = sta2x11_mfd1_bar1,
+				.ncells = ARRAY_SIZE(sta2x11_mfd1_bar1),
+			},
+		},
+	},
+};
+
+static void sta2x11_mfd_setup(struct pci_dev *pdev,
+					struct sta2x11_mfd_setup_data *sd)
+{
+	int i, j;
+	for (i = 0; i < ARRAY_SIZE(sd->bars); i++)
+		for (j = 0; j < sd->bars[i].ncells; j++) {
+			sd->bars[i].cells[j].pdata_size = sizeof(pdev);
+			sd->bars[i].cells[j].platform_data = &pdev;
+		}
+}
+
+static int sta2x11_mfd_probe(struct pci_dev *pdev,
 				       const struct pci_device_id *pci_id)
 {
 	int err, i;
-	struct sta2x11_gpio_pdata *gpio_data;
+	struct sta2x11_mfd_setup_data *setup_data;
 
 	dev_info(&pdev->dev, "%s\n", __func__);
 
@@ -381,46 +617,29 @@ static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev,
 	if (err)
 		dev_info(&pdev->dev, "Enable msi failed\n");
 
-	/* Read gpio config data as pci device's platform data */
-	gpio_data = dev_get_platdata(&pdev->dev);
-	if (!gpio_data)
-		dev_warn(&pdev->dev, "no gpio configuration\n");
-
-	dev_dbg(&pdev->dev, "%s, gpio_data = %p (%p)\n", __func__,
-		gpio_data, &gpio_data);
-	dev_dbg(&pdev->dev, "%s, pdev = %p (%p)\n", __func__,
-		pdev, &pdev);
+	setup_data = pci_id->device == PCI_DEVICE_ID_STMICRO_GPIO ?
+		&mfd_setup_data[STA2X11_MFD0] :
+		&mfd_setup_data[STA2X11_MFD1];
 
 	/* platform data is the pci device for all of them */
-	for (i = 0; i < ARRAY_SIZE(sta2x11_mfd_bar0); i++) {
-		sta2x11_mfd_bar0[i].pdata_size = sizeof(pdev);
-		sta2x11_mfd_bar0[i].platform_data = &pdev;
-	}
-	sta2x11_mfd_bar1[0].pdata_size = sizeof(pdev);
-	sta2x11_mfd_bar1[0].platform_data = &pdev;
+	sta2x11_mfd_setup(pdev, setup_data);
 
 	/* Record this pdev before mfd_add_devices: their probe looks for it */
-	sta2x11_mfd_add(pdev, GFP_ATOMIC);
-
-
-	err = mfd_add_devices(&pdev->dev, -1,
-			      sta2x11_mfd_bar0,
-			      ARRAY_SIZE(sta2x11_mfd_bar0),
-			      &pdev->resource[0],
-			      0, NULL);
-	if (err) {
-		dev_err(&pdev->dev, "mfd_add_devices[0] failed: %d\n", err);
-		goto err_disable;
-	}
-
-	err = mfd_add_devices(&pdev->dev, -1,
-			      sta2x11_mfd_bar1,
-			      ARRAY_SIZE(sta2x11_mfd_bar1),
-			      &pdev->resource[1],
-			      0, NULL);
-	if (err) {
-		dev_err(&pdev->dev, "mfd_add_devices[1] failed: %d\n", err);
-		goto err_disable;
+	if (!sta2x11_mfd_find(pdev))
+		sta2x11_mfd_add(pdev, GFP_ATOMIC);
+
+	/* Just 2 bars for all mfd's at present */
+	for (i = 0; i < 2; i++) {
+		err = mfd_add_devices(&pdev->dev, -1,
+				      setup_data->bars[i].cells,
+				      setup_data->bars[i].ncells,
+				      &pdev->resource[i],
+				      0, NULL);
+		if (err) {
+			dev_err(&pdev->dev,
+				"mfd_add_devices[%d] failed: %d\n", i, err);
+			goto err_disable;
+		}
 	}
 
 	return 0;
@@ -434,6 +653,7 @@ err_disable:
 
 static DEFINE_PCI_DEVICE_TABLE(sta2x11_mfd_tbl) = {
 	{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_GPIO)},
+	{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_VIC)},
 	{0,},
 };
 
@@ -459,6 +679,8 @@ static int __init sta2x11_mfd_init(void)
  */
 subsys_initcall(sta2x11_apbreg_init);
 subsys_initcall(sta2x11_sctl_init);
+subsys_initcall(sta2x11_apb_soc_regs_init);
+subsys_initcall(sta2x11_scr_init);
 rootfs_initcall(sta2x11_mfd_init);
 
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
index 947a06a..fd5fcb6 100644
--- a/drivers/mfd/stmpe-i2c.c
+++ b/drivers/mfd/stmpe-i2c.c
@@ -52,7 +52,7 @@ static struct stmpe_client_info i2c_ci = {
 	.write_block = i2c_block_write,
 };
 
-static int __devinit
+static int
 stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
 {
 	i2c_ci.data = (void *)id;
@@ -63,7 +63,7 @@ stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
 	return stmpe_probe(&i2c_ci, id->driver_data);
 }
 
-static int __devexit stmpe_i2c_remove(struct i2c_client *i2c)
+static int stmpe_i2c_remove(struct i2c_client *i2c)
 {
 	struct stmpe *stmpe = dev_get_drvdata(&i2c->dev);
 
@@ -82,13 +82,15 @@ static const struct i2c_device_id stmpe_i2c_id[] = {
 MODULE_DEVICE_TABLE(i2c, stmpe_id);
 
 static struct i2c_driver stmpe_i2c_driver = {
-	.driver.name	= "stmpe-i2c",
-	.driver.owner	= THIS_MODULE,
+	.driver = {
+		.name = "stmpe-i2c",
+		.owner = THIS_MODULE,
 #ifdef CONFIG_PM
-	.driver.pm	= &stmpe_dev_pm_ops,
+		.pm = &stmpe_dev_pm_ops,
 #endif
+	},
 	.probe		= stmpe_i2c_probe,
-	.remove		= __devexit_p(stmpe_i2c_remove),
+	.remove		= stmpe_i2c_remove,
 	.id_table	= stmpe_i2c_id,
 };
 
diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c
index 9edfe86..973659f 100644
--- a/drivers/mfd/stmpe-spi.c
+++ b/drivers/mfd/stmpe-spi.c
@@ -82,7 +82,7 @@ static struct stmpe_client_info spi_ci = {
 	.init = spi_init,
 };
 
-static int __devinit
+static int
 stmpe_spi_probe(struct spi_device *spi)
 {
 	const struct spi_device_id *id = spi_get_device_id(spi);
@@ -101,7 +101,7 @@ stmpe_spi_probe(struct spi_device *spi)
 	return stmpe_probe(&spi_ci, id->driver_data);
 }
 
-static int __devexit stmpe_spi_remove(struct spi_device *spi)
+static int stmpe_spi_remove(struct spi_device *spi)
 {
 	struct stmpe *stmpe = dev_get_drvdata(&spi->dev);
 
@@ -128,7 +128,7 @@ static struct spi_driver stmpe_spi_driver = {
 #endif
 	},
 	.probe		= stmpe_spi_probe,
-	.remove		= __devexit_p(stmpe_spi_remove),
+	.remove		= stmpe_spi_remove,
 	.id_table	= stmpe_spi_id,
 };
 
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index c94f521..d595c12 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -12,6 +12,8 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
 #include <linux/mfd/core.h>
@@ -310,20 +312,17 @@ static struct mfd_cell stmpe_gpio_cell_noirq = {
 static struct resource stmpe_keypad_resources[] = {
 	{
 		.name	= "KEYPAD",
-		.start	= 0,
-		.end	= 0,
 		.flags	= IORESOURCE_IRQ,
 	},
 	{
 		.name	= "KEYPAD_OVER",
-		.start	= 1,
-		.end	= 1,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
 
 static struct mfd_cell stmpe_keypad_cell = {
 	.name		= "stmpe-keypad",
+	.of_compatible  = "st,stmpe-keypad",
 	.resources	= stmpe_keypad_resources,
 	.num_resources	= ARRAY_SIZE(stmpe_keypad_resources),
 };
@@ -397,20 +396,17 @@ static struct stmpe_variant_info stmpe801_noirq = {
 static struct resource stmpe_ts_resources[] = {
 	{
 		.name	= "TOUCH_DET",
-		.start	= 0,
-		.end	= 0,
 		.flags	= IORESOURCE_IRQ,
 	},
 	{
 		.name	= "FIFO_TH",
-		.start	= 1,
-		.end	= 1,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
 
 static struct mfd_cell stmpe_ts_cell = {
 	.name		= "stmpe-ts",
+	.of_compatible	= "st,stmpe-ts",
 	.resources	= stmpe_ts_resources,
 	.num_resources	= ARRAY_SIZE(stmpe_ts_resources),
 };
@@ -526,12 +522,12 @@ static const u8 stmpe1601_regs[] = {
 static struct stmpe_variant_block stmpe1601_blocks[] = {
 	{
 		.cell	= &stmpe_gpio_cell,
-		.irq	= STMPE24XX_IRQ_GPIOC,
+		.irq	= STMPE1601_IRQ_GPIOC,
 		.block	= STMPE_BLOCK_GPIO,
 	},
 	{
 		.cell	= &stmpe_keypad_cell,
-		.irq	= STMPE24XX_IRQ_KEYPAD,
+		.irq	= STMPE1601_IRQ_KEYPAD,
 		.block	= STMPE_BLOCK_KEYPAD,
 	},
 };
@@ -765,7 +761,9 @@ static irqreturn_t stmpe_irq(int irq, void *data)
 	int i;
 
 	if (variant->id_val == STMPE801_ID) {
-		handle_nested_irq(stmpe->irq_base);
+		int base = irq_create_mapping(stmpe->domain, 0);
+
+		handle_nested_irq(base);
 		return IRQ_HANDLED;
 	}
 
@@ -786,8 +784,9 @@ static irqreturn_t stmpe_irq(int irq, void *data)
 		while (status) {
 			int bit = __ffs(status);
 			int line = bank * 8 + bit;
+			int nestedirq = irq_create_mapping(stmpe->domain, line);
 
-			handle_nested_irq(stmpe->irq_base + line);
+			handle_nested_irq(nestedirq);
 			status &= ~(1 << bit);
 		}
 
@@ -828,7 +827,7 @@ static void stmpe_irq_sync_unlock(struct irq_data *data)
 static void stmpe_irq_mask(struct irq_data *data)
 {
 	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
-	int offset = data->irq - stmpe->irq_base;
+	int offset = data->hwirq;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
 
@@ -838,7 +837,7 @@ static void stmpe_irq_mask(struct irq_data *data)
 static void stmpe_irq_unmask(struct irq_data *data)
 {
 	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
-	int offset = data->irq - stmpe->irq_base;
+	int offset = data->hwirq;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
 
@@ -853,43 +852,59 @@ static struct irq_chip stmpe_irq_chip = {
 	.irq_unmask		= stmpe_irq_unmask,
 };
 
-static int __devinit stmpe_irq_init(struct stmpe *stmpe)
+static int stmpe_irq_map(struct irq_domain *d, unsigned int virq,
+                                irq_hw_number_t hwirq)
 {
+	struct stmpe *stmpe = d->host_data;
 	struct irq_chip *chip = NULL;
-	int num_irqs = stmpe->variant->num_irqs;
-	int base = stmpe->irq_base;
-	int irq;
 
 	if (stmpe->variant->id_val != STMPE801_ID)
 		chip = &stmpe_irq_chip;
 
-	for (irq = base; irq < base + num_irqs; irq++) {
-		irq_set_chip_data(irq, stmpe);
-		irq_set_chip_and_handler(irq, chip, handle_edge_irq);
-		irq_set_nested_thread(irq, 1);
+	irq_set_chip_data(virq, stmpe);
+	irq_set_chip_and_handler(virq, chip, handle_edge_irq);
+	irq_set_nested_thread(virq, 1);
 #ifdef CONFIG_ARM
-		set_irq_flags(irq, IRQF_VALID);
+	set_irq_flags(virq, IRQF_VALID);
 #else
-		irq_set_noprobe(irq);
+	irq_set_noprobe(virq);
 #endif
-	}
 
 	return 0;
 }
 
-static void stmpe_irq_remove(struct stmpe *stmpe)
+static void stmpe_irq_unmap(struct irq_domain *d, unsigned int virq)
 {
-	int num_irqs = stmpe->variant->num_irqs;
-	int base = stmpe->irq_base;
-	int irq;
-
-	for (irq = base; irq < base + num_irqs; irq++) {
 #ifdef CONFIG_ARM
-		set_irq_flags(irq, 0);
+		set_irq_flags(virq, 0);
 #endif
-		irq_set_chip_and_handler(irq, NULL, NULL);
-		irq_set_chip_data(irq, NULL);
+		irq_set_chip_and_handler(virq, NULL, NULL);
+		irq_set_chip_data(virq, NULL);
+}
+
+static struct irq_domain_ops stmpe_irq_ops = {
+        .map    = stmpe_irq_map,
+        .unmap  = stmpe_irq_unmap,
+        .xlate  = irq_domain_xlate_twocell,
+};
+
+static int __devinit stmpe_irq_init(struct stmpe *stmpe,
+				struct device_node *np)
+{
+	int base = 0;
+	int num_irqs = stmpe->variant->num_irqs;
+
+	if (!np)
+		base = stmpe->irq_base;
+
+	stmpe->domain = irq_domain_add_simple(np, num_irqs, base,
+					      &stmpe_irq_ops, stmpe);
+	if (!stmpe->domain) {
+		dev_err(stmpe->dev, "Failed to create irqdomain\n");
+		return -ENOSYS;
 	}
+
+	return 0;
 }
 
 static int __devinit stmpe_chip_init(struct stmpe *stmpe)
@@ -959,10 +974,10 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe)
 }
 
 static int __devinit stmpe_add_device(struct stmpe *stmpe,
-				      struct mfd_cell *cell, int irq)
+				      struct mfd_cell *cell)
 {
 	return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
-			       NULL, stmpe->irq_base + irq, NULL);
+			       NULL, stmpe->irq_base, stmpe->domain);
 }
 
 static int __devinit stmpe_devices_init(struct stmpe *stmpe)
@@ -970,7 +985,7 @@ static int __devinit stmpe_devices_init(struct stmpe *stmpe)
 	struct stmpe_variant_info *variant = stmpe->variant;
 	unsigned int platform_blocks = stmpe->pdata->blocks;
 	int ret = -EINVAL;
-	int i;
+	int i, j;
 
 	for (i = 0; i < variant->num_blocks; i++) {
 		struct stmpe_variant_block *block = &variant->blocks[i];
@@ -978,8 +993,17 @@ static int __devinit stmpe_devices_init(struct stmpe *stmpe)
 		if (!(platform_blocks & block->block))
 			continue;
 
+		for (j = 0; j < block->cell->num_resources; j++) {
+			struct resource *res =
+				(struct resource *) &block->cell->resources[j];
+
+			/* Dynamically fill in a variant's IRQ. */
+			if (res->flags & IORESOURCE_IRQ)
+				res->start = res->end = block->irq + j;
+		}
+
 		platform_blocks &= ~block->block;
-		ret = stmpe_add_device(stmpe, block->cell, block->irq);
+		ret = stmpe_add_device(stmpe, block->cell);
 		if (ret)
 			return ret;
 	}
@@ -992,17 +1016,52 @@ static int __devinit stmpe_devices_init(struct stmpe *stmpe)
 	return ret;
 }
 
+void __devinit stmpe_of_probe(struct stmpe_platform_data *pdata,
+			struct device_node *np)
+{
+	struct device_node *child;
+
+	of_property_read_u32(np, "st,autosleep-timeout",
+			&pdata->autosleep_timeout);
+
+	pdata->autosleep = (pdata->autosleep_timeout) ? true : false;
+
+	for_each_child_of_node(np, child) {
+		if (!strcmp(child->name, "stmpe_gpio")) {
+			pdata->blocks |= STMPE_BLOCK_GPIO;
+		}
+		if (!strcmp(child->name, "stmpe_keypad")) {
+			pdata->blocks |= STMPE_BLOCK_KEYPAD;
+		}
+		if (!strcmp(child->name, "stmpe_touchscreen")) {
+			pdata->blocks |= STMPE_BLOCK_TOUCHSCREEN;
+		}
+		if (!strcmp(child->name, "stmpe_adc")) {
+			pdata->blocks |= STMPE_BLOCK_ADC;
+		}
+	}
+}
+
 /* Called from client specific probe routines */
 int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
 {
 	struct stmpe_platform_data *pdata = dev_get_platdata(ci->dev);
+	struct device_node *np = ci->dev->of_node;
 	struct stmpe *stmpe;
 	int ret;
 
-	if (!pdata)
-		return -EINVAL;
+	if (!pdata) {
+		if (!np)
+			return -EINVAL;
+
+		pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL);
+		if (!pdata)
+			return -ENOMEM;
+
+		stmpe_of_probe(pdata, np);
+	}
 
-	stmpe = kzalloc(sizeof(struct stmpe), GFP_KERNEL);
+	stmpe = devm_kzalloc(ci->dev, sizeof(struct stmpe), GFP_KERNEL);
 	if (!stmpe)
 		return -ENOMEM;
 
@@ -1024,11 +1083,12 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
 		ci->init(stmpe);
 
 	if (pdata->irq_over_gpio) {
-		ret = gpio_request_one(pdata->irq_gpio, GPIOF_DIR_IN, "stmpe");
+		ret = devm_gpio_request_one(ci->dev, pdata->irq_gpio,
+				GPIOF_DIR_IN, "stmpe");
 		if (ret) {
 			dev_err(stmpe->dev, "failed to request IRQ GPIO: %d\n",
 					ret);
-			goto out_free;
+			return ret;
 		}
 
 		stmpe->irq = gpio_to_irq(pdata->irq_gpio);
@@ -1045,51 +1105,37 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
 			dev_err(stmpe->dev,
 				"%s does not support no-irq mode!\n",
 				stmpe->variant->name);
-			ret = -ENODEV;
-			goto free_gpio;
+			return -ENODEV;
 		}
 		stmpe->variant = stmpe_noirq_variant_info[stmpe->partnum];
 	}
 
 	ret = stmpe_chip_init(stmpe);
 	if (ret)
-		goto free_gpio;
+		return ret;
 
 	if (stmpe->irq >= 0) {
-		ret = stmpe_irq_init(stmpe);
+		ret = stmpe_irq_init(stmpe, np);
 		if (ret)
-			goto free_gpio;
+			return ret;
 
-		ret = request_threaded_irq(stmpe->irq, NULL, stmpe_irq,
-				pdata->irq_trigger | IRQF_ONESHOT,
+		ret = devm_request_threaded_irq(ci->dev, stmpe->irq, NULL,
+				stmpe_irq, pdata->irq_trigger | IRQF_ONESHOT,
 				"stmpe", stmpe);
 		if (ret) {
 			dev_err(stmpe->dev, "failed to request IRQ: %d\n",
 					ret);
-			goto out_removeirq;
+			return ret;
 		}
 	}
 
 	ret = stmpe_devices_init(stmpe);
-	if (ret) {
-		dev_err(stmpe->dev, "failed to add children\n");
-		goto out_removedevs;
-	}
-
-	return 0;
+	if (!ret)
+		return 0;
 
-out_removedevs:
+	dev_err(stmpe->dev, "failed to add children\n");
 	mfd_remove_devices(stmpe->dev);
-	if (stmpe->irq >= 0)
-		free_irq(stmpe->irq, stmpe);
-out_removeirq:
-	if (stmpe->irq >= 0)
-		stmpe_irq_remove(stmpe);
-free_gpio:
-	if (pdata->irq_over_gpio)
-		gpio_free(pdata->irq_gpio);
-out_free:
-	kfree(stmpe);
+
 	return ret;
 }
 
@@ -1097,16 +1143,6 @@ int stmpe_remove(struct stmpe *stmpe)
 {
 	mfd_remove_devices(stmpe->dev);
 
-	if (stmpe->irq >= 0) {
-		free_irq(stmpe->irq, stmpe);
-		stmpe_irq_remove(stmpe);
-	}
-
-	if (stmpe->pdata->irq_over_gpio)
-		gpio_free(stmpe->pdata->irq_gpio);
-
-	kfree(stmpe);
-
 	return 0;
 }
 
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 65fe609..3f10591 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -97,7 +97,7 @@ static struct regmap_config syscon_regmap_config = {
 	.reg_stride = 4,
 };
 
-static int __devinit syscon_probe(struct platform_device *pdev)
+static int syscon_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
@@ -138,7 +138,7 @@ static int __devinit syscon_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit syscon_remove(struct platform_device *pdev)
+static int syscon_remove(struct platform_device *pdev)
 {
 	struct syscon *syscon;
 
@@ -156,7 +156,7 @@ static struct platform_driver syscon_driver = {
 		.of_match_table = of_syscon_match,
 	},
 	.probe		= syscon_probe,
-	.remove		= __devexit_p(syscon_remove),
+	.remove		= syscon_remove,
 };
 
 static int __init syscon_init(void)
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
index 8f4c853..a06d66b 100644
--- a/drivers/mfd/tc3589x.c
+++ b/drivers/mfd/tc3589x.c
@@ -282,7 +282,7 @@ static int tc3589x_chip_init(struct tc3589x *tc3589x)
 	return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1);
 }
 
-static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)
+static int tc3589x_device_init(struct tc3589x *tc3589x)
 {
 	int ret = 0;
 	unsigned int blocks = tc3589x->pdata->block;
@@ -329,7 +329,7 @@ static int tc3589x_of_probe(struct device_node *np,
 	return 0;
 }
 
-static int __devinit tc3589x_probe(struct i2c_client *i2c,
+static int tc3589x_probe(struct i2c_client *i2c,
 				   const struct i2c_device_id *id)
 {
 	struct tc3589x_platform_data *pdata = i2c->dev.platform_data;
@@ -402,7 +402,7 @@ out_free:
 	return ret;
 }
 
-static int __devexit tc3589x_remove(struct i2c_client *client)
+static int tc3589x_remove(struct i2c_client *client)
 {
 	struct tc3589x *tc3589x = i2c_get_clientdata(client);
 
@@ -458,7 +458,7 @@ static struct i2c_driver tc3589x_driver = {
 	.driver.owner	= THIS_MODULE,
 	.driver.pm	= &tc3589x_dev_pm_ops,
 	.probe		= tc3589x_probe,
-	.remove		= __devexit_p(tc3589x_remove),
+	.remove		= tc3589x_remove,
 	.id_table	= tc3589x_id,
 };
 
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
index 413c891..366f7b9 100644
--- a/drivers/mfd/tc6387xb.c
+++ b/drivers/mfd/tc6387xb.c
@@ -138,7 +138,7 @@ static struct mfd_cell tc6387xb_cells[] = {
 	},
 };
 
-static int __devinit tc6387xb_probe(struct platform_device *dev)
+static int tc6387xb_probe(struct platform_device *dev)
 {
 	struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
 	struct resource *iomem, *rscr;
@@ -208,7 +208,7 @@ err_no_irq:
 	return ret;
 }
 
-static int __devexit tc6387xb_remove(struct platform_device *dev)
+static int tc6387xb_remove(struct platform_device *dev)
 {
 	struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
 
@@ -229,7 +229,7 @@ static struct platform_driver tc6387xb_platform_driver = {
 		.name		= "tc6387xb",
 	},
 	.probe		= tc6387xb_probe,
-	.remove		= __devexit_p(tc6387xb_remove),
+	.remove		= tc6387xb_remove,
 	.suspend        = tc6387xb_suspend,
 	.resume         = tc6387xb_resume,
 };
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index dcab026..15e1463 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -137,7 +137,7 @@ static int tc6393xb_nand_enable(struct platform_device *nand)
 	return 0;
 }
 
-static struct resource __devinitdata tc6393xb_nand_resources[] = {
+static struct resource tc6393xb_nand_resources[] = {
 	{
 		.start	= 0x1000,
 		.end	= 0x1007,
@@ -196,7 +196,7 @@ static const struct resource tc6393xb_ohci_resources[] = {
 	},
 };
 
-static struct resource __devinitdata tc6393xb_fb_resources[] = {
+static struct resource tc6393xb_fb_resources[] = {
 	{
 		.start	= 0x5000,
 		.end	= 0x51ff,
@@ -382,7 +382,7 @@ static struct tmio_mmc_data tc6393xb_mmc_data = {
 	.set_clk_div = tc6393xb_mmc_clk_div,
 };
 
-static struct mfd_cell __devinitdata tc6393xb_cells[] = {
+static struct mfd_cell tc6393xb_cells[] = {
 	[TC6393XB_CELL_NAND] = {
 		.name = "tmio-nand",
 		.enable = tc6393xb_nand_enable,
@@ -602,7 +602,7 @@ static void tc6393xb_detach_irq(struct platform_device *dev)
 
 /*--------------------------------------------------------------------------*/
 
-static int __devinit tc6393xb_probe(struct platform_device *dev)
+static int tc6393xb_probe(struct platform_device *dev)
 {
 	struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
 	struct tc6393xb *tc6393xb;
@@ -731,7 +731,7 @@ err_kzalloc:
 	return ret;
 }
 
-static int __devexit tc6393xb_remove(struct platform_device *dev)
+static int tc6393xb_remove(struct platform_device *dev)
 {
 	struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
 	struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
@@ -831,7 +831,7 @@ static int tc6393xb_resume(struct platform_device *dev)
 
 static struct platform_driver tc6393xb_driver = {
 	.probe = tc6393xb_probe,
-	.remove = __devexit_p(tc6393xb_remove),
+	.remove = tc6393xb_remove,
 	.suspend = tc6393xb_suspend,
 	.resume = tc6393xb_resume,
 
diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c
index 7c3675a..09a14ce 100644
--- a/drivers/mfd/ti-ssp.c
+++ b/drivers/mfd/ti-ssp.c
@@ -315,7 +315,7 @@ static irqreturn_t ti_ssp_interrupt(int irq, void *dev_data)
 	return IRQ_HANDLED;
 }
 
-static int __devinit ti_ssp_probe(struct platform_device *pdev)
+static int ti_ssp_probe(struct platform_device *pdev)
 {
 	static struct ti_ssp *ssp;
 	const struct ti_ssp_data *pdata = pdev->dev.platform_data;
@@ -433,7 +433,7 @@ error_res:
 	return error;
 }
 
-static int __devexit ti_ssp_remove(struct platform_device *pdev)
+static int ti_ssp_remove(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct ti_ssp *ssp = dev_get_drvdata(dev);
@@ -451,7 +451,7 @@ static int __devexit ti_ssp_remove(struct platform_device *pdev)
 
 static struct platform_driver ti_ssp_driver = {
 	.probe		= ti_ssp_probe,
-	.remove		= __devexit_p(ti_ssp_remove),
+	.remove		= ti_ssp_remove,
 	.driver		= {
 		.name	= "ti-ssp",
 		.owner	= THIS_MODULE,
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
new file mode 100644
index 0000000..8ca3bf0
--- /dev/null
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -0,0 +1,274 @@
+/*
+ * TI Touch Screen / ADC MFD driver
+ *
+ * Copyright (C) 2012 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.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/mfd/core.h>
+#include <linux/pm_runtime.h>
+
+#include <linux/mfd/ti_am335x_tscadc.h>
+#include <linux/input/ti_am335x_tsc.h>
+#include <linux/platform_data/ti_am335x_adc.h>
+
+static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg)
+{
+	unsigned int val;
+
+	regmap_read(tsadc->regmap_tscadc, reg, &val);
+	return val;
+}
+
+static void tscadc_writel(struct ti_tscadc_dev *tsadc, unsigned int reg,
+					unsigned int val)
+{
+	regmap_write(tsadc->regmap_tscadc, reg, val);
+}
+
+static const struct regmap_config tscadc_regmap_config = {
+	.name = "ti_tscadc",
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+};
+
+static void tscadc_idle_config(struct ti_tscadc_dev *config)
+{
+	unsigned int idleconfig;
+
+	idleconfig = STEPCONFIG_YNN | STEPCONFIG_INM_ADCREFM |
+			STEPCONFIG_INP_ADCREFM | STEPCONFIG_YPN;
+
+	tscadc_writel(config, REG_IDLECONFIG, idleconfig);
+}
+
+static	int __devinit ti_tscadc_probe(struct platform_device *pdev)
+{
+	struct ti_tscadc_dev	*tscadc;
+	struct resource		*res;
+	struct clk		*clk;
+	struct mfd_tscadc_board	*pdata = pdev->dev.platform_data;
+	struct mfd_cell		*cell;
+	int			err, ctrl;
+	int			clk_value, clock_rate;
+	int			tsc_wires, adc_channels = 0, total_channels;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "Could not find platform data\n");
+		return -EINVAL;
+	}
+
+	if (pdata->adc_init)
+		adc_channels = pdata->adc_init->adc_channels;
+
+	tsc_wires = pdata->tsc_init->wires;
+	total_channels = tsc_wires + adc_channels;
+
+	if (total_channels > 8) {
+		dev_err(&pdev->dev, "Number of i/p channels more than 8\n");
+		return -EINVAL;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "no memory resource defined.\n");
+		return -EINVAL;
+	}
+
+	/* Allocate memory for device */
+	tscadc = devm_kzalloc(&pdev->dev,
+			sizeof(struct ti_tscadc_dev), GFP_KERNEL);
+	if (!tscadc) {
+		dev_err(&pdev->dev, "failed to allocate memory.\n");
+		return -ENOMEM;
+	}
+	tscadc->dev = &pdev->dev;
+
+	err = platform_get_irq(pdev, 0);
+	if (err < 0) {
+		dev_err(&pdev->dev, "no irq ID is specified.\n");
+		goto ret;
+	} else
+		tscadc->irq = err;
+
+	res = devm_request_mem_region(&pdev->dev,
+			res->start, resource_size(res), pdev->name);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to reserve registers.\n");
+		return -EBUSY;
+	}
+
+	tscadc->tscadc_base = devm_ioremap(&pdev->dev,
+			res->start, resource_size(res));
+	if (!tscadc->tscadc_base) {
+		dev_err(&pdev->dev, "failed to map registers.\n");
+		return -ENOMEM;
+	}
+
+	tscadc->regmap_tscadc = devm_regmap_init_mmio(&pdev->dev,
+			tscadc->tscadc_base, &tscadc_regmap_config);
+	if (IS_ERR(tscadc->regmap_tscadc)) {
+		dev_err(&pdev->dev, "regmap init failed\n");
+		err = PTR_ERR(tscadc->regmap_tscadc);
+		goto ret;
+	}
+
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_sync(&pdev->dev);
+
+	/*
+	 * The TSC_ADC_Subsystem has 2 clock domains
+	 * OCP_CLK and ADC_CLK.
+	 * The ADC clock is expected to run at target of 3MHz,
+	 * and expected to capture 12-bit data at a rate of 200 KSPS.
+	 * The TSC_ADC_SS controller design assumes the OCP clock is
+	 * at least 6x faster than the ADC clock.
+	 */
+	clk = clk_get(&pdev->dev, "adc_tsc_fck");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "failed to get TSC fck\n");
+		err = PTR_ERR(clk);
+		goto err_disable_clk;
+	}
+	clock_rate = clk_get_rate(clk);
+	clk_put(clk);
+	clk_value = clock_rate / ADC_CLK;
+	if (clk_value < MAX_CLK_DIV) {
+		dev_err(&pdev->dev, "clock input less than min clock requirement\n");
+		err = -EINVAL;
+		goto err_disable_clk;
+	}
+	/* TSCADC_CLKDIV needs to be configured to the value minus 1 */
+	clk_value = clk_value - 1;
+	tscadc_writel(tscadc, REG_CLKDIV, clk_value);
+
+	/* Set the control register bits */
+	ctrl = CNTRLREG_STEPCONFIGWRT |
+			CNTRLREG_TSCENB |
+			CNTRLREG_STEPID |
+			CNTRLREG_4WIRE;
+	tscadc_writel(tscadc, REG_CTRL, ctrl);
+
+	/* Set register bits for Idle Config Mode */
+	tscadc_idle_config(tscadc);
+
+	/* Enable the TSC module enable bit */
+	ctrl = tscadc_readl(tscadc, REG_CTRL);
+	ctrl |= CNTRLREG_TSCSSENB;
+	tscadc_writel(tscadc, REG_CTRL, ctrl);
+
+	/* TSC Cell */
+	cell = &tscadc->cells[TSC_CELL];
+	cell->name = "tsc";
+	cell->platform_data = tscadc;
+	cell->pdata_size = sizeof(*tscadc);
+
+	/* ADC Cell */
+	cell = &tscadc->cells[ADC_CELL];
+	cell->name = "tiadc";
+	cell->platform_data = tscadc;
+	cell->pdata_size = sizeof(*tscadc);
+
+	err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
+			TSCADC_CELLS, NULL, 0, NULL);
+	if (err < 0)
+		goto err_disable_clk;
+
+	device_init_wakeup(&pdev->dev, true);
+	platform_set_drvdata(pdev, tscadc);
+
+	return 0;
+
+err_disable_clk:
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+ret:
+	return err;
+}
+
+static int __devexit ti_tscadc_remove(struct platform_device *pdev)
+{
+	struct ti_tscadc_dev	*tscadc = platform_get_drvdata(pdev);
+
+	tscadc_writel(tscadc, REG_SE, 0x00);
+
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
+	mfd_remove_devices(tscadc->dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int tscadc_suspend(struct device *dev)
+{
+	struct ti_tscadc_dev	*tscadc_dev = dev_get_drvdata(dev);
+
+	tscadc_writel(tscadc_dev, REG_SE, 0x00);
+	pm_runtime_put_sync(dev);
+
+	return 0;
+}
+
+static int tscadc_resume(struct device *dev)
+{
+	struct ti_tscadc_dev	*tscadc_dev = dev_get_drvdata(dev);
+	unsigned int restore, ctrl;
+
+	pm_runtime_get_sync(dev);
+
+	/* context restore */
+	ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_TSCENB |
+			CNTRLREG_STEPID | CNTRLREG_4WIRE;
+	tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
+	tscadc_idle_config(tscadc_dev);
+	tscadc_writel(tscadc_dev, REG_SE, STPENB_STEPENB);
+	restore = tscadc_readl(tscadc_dev, REG_CTRL);
+	tscadc_writel(tscadc_dev, REG_CTRL,
+			(restore | CNTRLREG_TSCSSENB));
+
+	return 0;
+}
+
+static const struct dev_pm_ops tscadc_pm_ops = {
+	.suspend = tscadc_suspend,
+	.resume = tscadc_resume,
+};
+#define TSCADC_PM_OPS (&tscadc_pm_ops)
+#else
+#define TSCADC_PM_OPS NULL
+#endif
+
+static struct platform_driver ti_tscadc_driver = {
+	.driver = {
+		.name   = "ti_tscadc",
+		.owner	= THIS_MODULE,
+		.pm	= TSCADC_PM_OPS,
+	},
+	.probe	= ti_tscadc_probe,
+	.remove	= __devexit_p(ti_tscadc_remove),
+
+};
+
+module_platform_driver(ti_tscadc_driver);
+
+MODULE_DESCRIPTION("TI touchscreen / ADC MFD controller driver");
+MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
index cccc626..59e0ee2 100644
--- a/drivers/mfd/timberdale.c
+++ b/drivers/mfd/timberdale.c
@@ -75,13 +75,13 @@ static struct i2c_board_info timberdale_i2c_board_info[] = {
 	},
 };
 
-static __devinitdata struct xiic_i2c_platform_data
+static struct xiic_i2c_platform_data
 timberdale_xiic_platform_data = {
 	.devices = timberdale_i2c_board_info,
 	.num_devices = ARRAY_SIZE(timberdale_i2c_board_info)
 };
 
-static __devinitdata struct ocores_i2c_platform_data
+static struct ocores_i2c_platform_data
 timberdale_ocores_platform_data = {
 	.reg_shift = 2,
 	.clock_khz = 62500,
@@ -89,7 +89,7 @@ timberdale_ocores_platform_data = {
 	.num_devices = ARRAY_SIZE(timberdale_i2c_board_info)
 };
 
-static const __devinitconst struct resource timberdale_xiic_resources[] = {
+static const struct resource timberdale_xiic_resources[] = {
 	{
 		.start	= XIICOFFSET,
 		.end	= XIICEND,
@@ -102,7 +102,7 @@ static const __devinitconst struct resource timberdale_xiic_resources[] = {
 	},
 };
 
-static const __devinitconst struct resource timberdale_ocores_resources[] = {
+static const struct resource timberdale_ocores_resources[] = {
 	{
 		.start	= OCORESOFFSET,
 		.end	= OCORESEND,
@@ -143,7 +143,7 @@ static struct spi_board_info timberdale_spi_8bit_board_info[] = {
 	},
 };
 
-static __devinitdata struct xspi_platform_data timberdale_xspi_platform_data = {
+static struct xspi_platform_data timberdale_xspi_platform_data = {
 	.num_chipselect = 3,
 	.little_endian = true,
 	/* bits per word and devices will be filled in runtime depending
@@ -151,7 +151,7 @@ static __devinitdata struct xspi_platform_data timberdale_xspi_platform_data = {
 	 */
 };
 
-static const __devinitconst struct resource timberdale_spi_resources[] = {
+static const struct resource timberdale_spi_resources[] = {
 	{
 		.start 	= SPIOFFSET,
 		.end	= SPIEND,
@@ -164,13 +164,13 @@ static const __devinitconst struct resource timberdale_spi_resources[] = {
 	},
 };
 
-static __devinitdata struct ks8842_platform_data
+static struct ks8842_platform_data
 	timberdale_ks8842_platform_data = {
 	.rx_dma_channel = DMA_ETH_RX,
 	.tx_dma_channel = DMA_ETH_TX
 };
 
-static const __devinitconst struct resource timberdale_eth_resources[] = {
+static const struct resource timberdale_eth_resources[] = {
 	{
 		.start	= ETHOFFSET,
 		.end	= ETHEND,
@@ -183,14 +183,14 @@ static const __devinitconst struct resource timberdale_eth_resources[] = {
 	},
 };
 
-static __devinitdata struct timbgpio_platform_data
+static struct timbgpio_platform_data
 	timberdale_gpio_platform_data = {
 	.gpio_base = 0,
 	.nr_pins = GPIO_NR_PINS,
 	.irq_base = 200,
 };
 
-static const __devinitconst struct resource timberdale_gpio_resources[] = {
+static const struct resource timberdale_gpio_resources[] = {
 	{
 		.start	= GPIOOFFSET,
 		.end	= GPIOEND,
@@ -203,7 +203,7 @@ static const __devinitconst struct resource timberdale_gpio_resources[] = {
 	},
 };
 
-static const __devinitconst struct resource timberdale_mlogicore_resources[] = {
+static const struct resource timberdale_mlogicore_resources[] = {
 	{
 		.start	= MLCOREOFFSET,
 		.end	= MLCOREEND,
@@ -221,7 +221,7 @@ static const __devinitconst struct resource timberdale_mlogicore_resources[] = {
 	},
 };
 
-static const __devinitconst struct resource timberdale_uart_resources[] = {
+static const struct resource timberdale_uart_resources[] = {
 	{
 		.start	= UARTOFFSET,
 		.end	= UARTEND,
@@ -234,7 +234,7 @@ static const __devinitconst struct resource timberdale_uart_resources[] = {
 	},
 };
 
-static const __devinitconst struct resource timberdale_uartlite_resources[] = {
+static const struct resource timberdale_uartlite_resources[] = {
 	{
 		.start	= UARTLITEOFFSET,
 		.end	= UARTLITEEND,
@@ -247,13 +247,13 @@ static const __devinitconst struct resource timberdale_uartlite_resources[] = {
 	},
 };
 
-static __devinitdata struct i2c_board_info timberdale_adv7180_i2c_board_info = {
+static struct i2c_board_info timberdale_adv7180_i2c_board_info = {
 	/* Requires jumper JP9 to be off */
 	I2C_BOARD_INFO("adv7180", 0x42 >> 1),
 	.irq = IRQ_TIMBERDALE_ADV7180
 };
 
-static __devinitdata struct timb_video_platform_data
+static struct timb_video_platform_data
 	timberdale_video_platform_data = {
 	.dma_channel = DMA_VIDEO_RX,
 	.i2c_adapter = 0,
@@ -262,7 +262,7 @@ static __devinitdata struct timb_video_platform_data
 	}
 };
 
-static const __devinitconst struct resource
+static const struct resource
 timberdale_radio_resources[] = {
 	{
 		.start	= RDSOFFSET,
@@ -276,22 +276,22 @@ timberdale_radio_resources[] = {
 	},
 };
 
-static __devinitdata struct i2c_board_info timberdale_tef6868_i2c_board_info = {
+static struct i2c_board_info timberdale_tef6868_i2c_board_info = {
 	I2C_BOARD_INFO("tef6862", 0x60)
 };
 
-static __devinitdata struct i2c_board_info timberdale_saa7706_i2c_board_info = {
+static struct i2c_board_info timberdale_saa7706_i2c_board_info = {
 	I2C_BOARD_INFO("saa7706h", 0x1C)
 };
 
-static __devinitdata struct timb_radio_platform_data
+static struct timb_radio_platform_data
 	timberdale_radio_platform_data = {
 	.i2c_adapter = 0,
 	.tuner = &timberdale_tef6868_i2c_board_info,
 	.dsp = &timberdale_saa7706_i2c_board_info
 };
 
-static const __devinitconst struct resource timberdale_video_resources[] = {
+static const struct resource timberdale_video_resources[] = {
 	{
 		.start	= LOGIWOFFSET,
 		.end	= LOGIWEND,
@@ -303,7 +303,7 @@ static const __devinitconst struct resource timberdale_video_resources[] = {
 	*/
 };
 
-static __devinitdata struct timb_dma_platform_data timb_dma_platform_data = {
+static struct timb_dma_platform_data timb_dma_platform_data = {
 	.nr_channels = 10,
 	.channels = {
 		{
@@ -362,7 +362,7 @@ static __devinitdata struct timb_dma_platform_data timb_dma_platform_data = {
 	}
 };
 
-static const __devinitconst struct resource timberdale_dma_resources[] = {
+static const struct resource timberdale_dma_resources[] = {
 	{
 		.start	= DMAOFFSET,
 		.end	= DMAEND,
@@ -375,7 +375,7 @@ static const __devinitconst struct resource timberdale_dma_resources[] = {
 	},
 };
 
-static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
+static struct mfd_cell timberdale_cells_bar0_cfg0[] = {
 	{
 		.name = "timb-dma",
 		.num_resources = ARRAY_SIZE(timberdale_dma_resources),
@@ -432,7 +432,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
 	},
 };
 
-static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
+static struct mfd_cell timberdale_cells_bar0_cfg1[] = {
 	{
 		.name = "timb-dma",
 		.num_resources = ARRAY_SIZE(timberdale_dma_resources),
@@ -499,7 +499,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
 	},
 };
 
-static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
+static struct mfd_cell timberdale_cells_bar0_cfg2[] = {
 	{
 		.name = "timb-dma",
 		.num_resources = ARRAY_SIZE(timberdale_dma_resources),
@@ -549,7 +549,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
 	},
 };
 
-static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
+static struct mfd_cell timberdale_cells_bar0_cfg3[] = {
 	{
 		.name = "timb-dma",
 		.num_resources = ARRAY_SIZE(timberdale_dma_resources),
@@ -606,7 +606,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
 	},
 };
 
-static const __devinitconst struct resource timberdale_sdhc_resources[] = {
+static const struct resource timberdale_sdhc_resources[] = {
 	/* located in bar 1 and bar 2 */
 	{
 		.start	= SDHC0OFFSET,
@@ -620,7 +620,7 @@ static const __devinitconst struct resource timberdale_sdhc_resources[] = {
 	},
 };
 
-static __devinitdata struct mfd_cell timberdale_cells_bar1[] = {
+static struct mfd_cell timberdale_cells_bar1[] = {
 	{
 		.name = "sdhci",
 		.num_resources = ARRAY_SIZE(timberdale_sdhc_resources),
@@ -628,7 +628,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar1[] = {
 	},
 };
 
-static __devinitdata struct mfd_cell timberdale_cells_bar2[] = {
+static struct mfd_cell timberdale_cells_bar2[] = {
 	{
 		.name = "sdhci",
 		.num_resources = ARRAY_SIZE(timberdale_sdhc_resources),
@@ -650,7 +650,7 @@ static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
 
 /*--------------------------------------------------------------------------*/
 
-static int __devinit timb_probe(struct pci_dev *dev,
+static int timb_probe(struct pci_dev *dev,
 	const struct pci_device_id *id)
 {
 	struct timberdale_device *priv;
@@ -840,7 +840,7 @@ err_enable:
 	return -ENODEV;
 }
 
-static void __devexit timb_remove(struct pci_dev *dev)
+static void timb_remove(struct pci_dev *dev)
 {
 	struct timberdale_device *priv = pci_get_drvdata(dev);
 
@@ -867,7 +867,7 @@ static struct pci_driver timberdale_pci_driver = {
 	.name = DRIVER_NAME,
 	.id_table = timberdale_pci_tbl,
 	.probe = timb_probe,
-	.remove = __devexit_p(timb_remove),
+	.remove = timb_remove,
 };
 
 static int __init timberdale_init(void)
diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c
index 14051bd..1d302f5 100644
--- a/drivers/mfd/tps6105x.c
+++ b/drivers/mfd/tps6105x.c
@@ -86,7 +86,7 @@ fail:
 }
 EXPORT_SYMBOL(tps6105x_mask_and_set);
 
-static int __devinit tps6105x_startup(struct tps6105x *tps6105x)
+static int tps6105x_startup(struct tps6105x *tps6105x)
 {
 	int ret;
 	u8 regval;
@@ -133,7 +133,7 @@ static struct mfd_cell tps6105x_cells[] = {
 	},
 };
 
-static int __devinit tps6105x_probe(struct i2c_client *client,
+static int tps6105x_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct tps6105x			*tps6105x;
@@ -199,7 +199,7 @@ fail:
 	return ret;
 }
 
-static int __devexit tps6105x_remove(struct i2c_client *client)
+static int tps6105x_remove(struct i2c_client *client)
 {
 	struct tps6105x *tps6105x = i2c_get_clientdata(client);
 
@@ -226,7 +226,7 @@ static struct i2c_driver tps6105x_driver = {
 		.name	= "tps6105x",
 	},
 	.probe		= tps6105x_probe,
-	.remove		= __devexit_p(tps6105x_remove),
+	.remove		= tps6105x_remove,
 	.id_table	= tps6105x_id,
 };
 
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
index 074ae32..8d12a8e 100644
--- a/drivers/mfd/tps65090.c
+++ b/drivers/mfd/tps65090.c
@@ -25,7 +25,6 @@
 #include <linux/i2c.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps65090.h>
-#include <linux/regmap.h>
 #include <linux/err.h>
 
 #define NUM_INT_REG 2
@@ -39,204 +38,102 @@
 #define TPS65090_INT_MSK	0x2
 #define TPS65090_INT_MSK2	0x3
 
-struct tps65090_irq_data {
-	u8		mask_reg;
-	u8		mask_pos;
-};
-
-#define TPS65090_IRQ(_reg, _mask_pos)		\
-	{					\
-		.mask_reg	= (_reg),	\
-		.mask_pos	= (_mask_pos),	\
-	}
-
-static const struct tps65090_irq_data tps65090_irqs[] = {
-	[0]		= TPS65090_IRQ(0, 0),
-	[1]		= TPS65090_IRQ(0, 1),
-	[2]		= TPS65090_IRQ(0, 2),
-	[3]		= TPS65090_IRQ(0, 3),
-	[4]		= TPS65090_IRQ(0, 4),
-	[5]		= TPS65090_IRQ(0, 5),
-	[6]		= TPS65090_IRQ(0, 6),
-	[7]		= TPS65090_IRQ(0, 7),
-	[8]		= TPS65090_IRQ(1, 0),
-	[9]		= TPS65090_IRQ(1, 1),
-	[10]		= TPS65090_IRQ(1, 2),
-	[11]		= TPS65090_IRQ(1, 3),
-	[12]		= TPS65090_IRQ(1, 4),
-	[13]		= TPS65090_IRQ(1, 5),
-	[14]		= TPS65090_IRQ(1, 6),
-	[15]		= TPS65090_IRQ(1, 7),
-};
+#define TPS65090_INT1_MASK_VAC_STATUS_CHANGE		1
+#define TPS65090_INT1_MASK_VSYS_STATUS_CHANGE		2
+#define TPS65090_INT1_MASK_BAT_STATUS_CHANGE		3
+#define TPS65090_INT1_MASK_CHARGING_STATUS_CHANGE	4
+#define TPS65090_INT1_MASK_CHARGING_COMPLETE		5
+#define TPS65090_INT1_MASK_OVERLOAD_DCDC1		6
+#define TPS65090_INT1_MASK_OVERLOAD_DCDC2		7
+#define TPS65090_INT2_MASK_OVERLOAD_DCDC3		0
+#define TPS65090_INT2_MASK_OVERLOAD_FET1		1
+#define TPS65090_INT2_MASK_OVERLOAD_FET2		2
+#define TPS65090_INT2_MASK_OVERLOAD_FET3		3
+#define TPS65090_INT2_MASK_OVERLOAD_FET4		4
+#define TPS65090_INT2_MASK_OVERLOAD_FET5		5
+#define TPS65090_INT2_MASK_OVERLOAD_FET6		6
+#define TPS65090_INT2_MASK_OVERLOAD_FET7		7
 
 static struct mfd_cell tps65090s[] = {
 	{
 		.name = "tps65090-pmic",
 	},
 	{
-		.name = "tps65090-regulator",
+		.name = "tps65090-charger",
 	},
 };
 
-int tps65090_write(struct device *dev, int reg, uint8_t val)
-{
-	struct tps65090 *tps = dev_get_drvdata(dev);
-	return regmap_write(tps->rmap, reg, val);
-}
-EXPORT_SYMBOL_GPL(tps65090_write);
-
-int tps65090_read(struct device *dev, int reg, uint8_t *val)
-{
-	struct tps65090 *tps = dev_get_drvdata(dev);
-	unsigned int temp_val;
-	int ret;
-	ret = regmap_read(tps->rmap, reg, &temp_val);
-	if (!ret)
-		*val = temp_val;
-	return ret;
-}
-EXPORT_SYMBOL_GPL(tps65090_read);
-
-int tps65090_set_bits(struct device *dev, int reg, uint8_t bit_num)
-{
-	struct tps65090 *tps = dev_get_drvdata(dev);
-	return regmap_update_bits(tps->rmap, reg, BIT(bit_num), ~0u);
-}
-EXPORT_SYMBOL_GPL(tps65090_set_bits);
-
-int tps65090_clr_bits(struct device *dev, int reg, uint8_t bit_num)
-{
-	struct tps65090 *tps = dev_get_drvdata(dev);
-	return regmap_update_bits(tps->rmap, reg, BIT(bit_num), 0u);
-}
-EXPORT_SYMBOL_GPL(tps65090_clr_bits);
-
-static void tps65090_irq_lock(struct irq_data *data)
-{
-	struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data);
-
-	mutex_lock(&tps65090->irq_lock);
-}
-
-static void tps65090_irq_mask(struct irq_data *irq_data)
-{
-	struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data);
-	unsigned int __irq = irq_data->hwirq;
-	const struct tps65090_irq_data *data = &tps65090_irqs[__irq];
-
-	tps65090_set_bits(tps65090->dev, (TPS65090_INT_MSK + data->mask_reg),
-		data->mask_pos);
-}
-
-static void tps65090_irq_unmask(struct irq_data *irq_data)
-{
-	struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data);
-	unsigned int __irq = irq_data->irq - tps65090->irq_base;
-	const struct tps65090_irq_data *data = &tps65090_irqs[__irq];
-
-	tps65090_clr_bits(tps65090->dev, (TPS65090_INT_MSK + data->mask_reg),
-		data->mask_pos);
-}
-
-static void tps65090_irq_sync_unlock(struct irq_data *data)
-{
-	struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data);
-
-	mutex_unlock(&tps65090->irq_lock);
-}
-
-static irqreturn_t tps65090_irq(int irq, void *data)
-{
-	struct tps65090 *tps65090 = data;
-	int ret = 0;
-	u8 status, mask;
-	unsigned long int acks = 0;
-	int i;
-
-	for (i = 0; i < NUM_INT_REG; i++) {
-		ret = tps65090_read(tps65090->dev, TPS65090_INT_MSK + i, &mask);
-		if (ret < 0) {
-			dev_err(tps65090->dev,
-				"failed to read mask reg [addr:%d]\n",
-				TPS65090_INT_MSK + i);
-			return IRQ_NONE;
-		}
-		ret = tps65090_read(tps65090->dev, TPS65090_INT_STS + i,
-			&status);
-		if (ret < 0) {
-			dev_err(tps65090->dev,
-				"failed to read status reg [addr:%d]\n",
-				 TPS65090_INT_STS + i);
-			return IRQ_NONE;
-		}
-		if (status) {
-			/* Ack only those interrupts which are not masked */
-			status &= (~mask);
-			ret = tps65090_write(tps65090->dev,
-					TPS65090_INT_STS + i, status);
-			if (ret < 0) {
-				dev_err(tps65090->dev,
-					"failed to write interrupt status\n");
-				return IRQ_NONE;
-			}
-			acks |= (status << (i * 8));
-		}
-	}
-
-	for_each_set_bit(i, &acks, ARRAY_SIZE(tps65090_irqs))
-		handle_nested_irq(tps65090->irq_base + i);
-	return acks ? IRQ_HANDLED : IRQ_NONE;
-}
-
-static int __devinit tps65090_irq_init(struct tps65090 *tps65090, int irq,
-	int irq_base)
-{
-	int i, ret;
-
-	if (!irq_base) {
-		dev_err(tps65090->dev, "IRQ base not set\n");
-		return -EINVAL;
-	}
-
-	mutex_init(&tps65090->irq_lock);
-
-	for (i = 0; i < NUM_INT_REG; i++)
-		tps65090_write(tps65090->dev, TPS65090_INT_MSK + i, 0xFF);
-
-	for (i = 0; i < NUM_INT_REG; i++)
-		tps65090_write(tps65090->dev, TPS65090_INT_STS + i, 0xff);
-
-	tps65090->irq_base = irq_base;
-	tps65090->irq_chip.name = "tps65090";
-	tps65090->irq_chip.irq_mask = tps65090_irq_mask;
-	tps65090->irq_chip.irq_unmask = tps65090_irq_unmask;
-	tps65090->irq_chip.irq_bus_lock = tps65090_irq_lock;
-	tps65090->irq_chip.irq_bus_sync_unlock = tps65090_irq_sync_unlock;
-
-	for (i = 0; i < ARRAY_SIZE(tps65090_irqs); i++) {
-		int __irq = i + tps65090->irq_base;
-		irq_set_chip_data(__irq, tps65090);
-		irq_set_chip_and_handler(__irq, &tps65090->irq_chip,
-					 handle_simple_irq);
-		irq_set_nested_thread(__irq, 1);
-#ifdef CONFIG_ARM
-		set_irq_flags(__irq, IRQF_VALID);
-#endif
-	}
-
-	ret = request_threaded_irq(irq, NULL, tps65090_irq, IRQF_ONESHOT,
-				"tps65090", tps65090);
-	if (!ret) {
-		device_init_wakeup(tps65090->dev, 1);
-		enable_irq_wake(irq);
-	}
+static const struct regmap_irq tps65090_irqs[] = {
+	/* INT1 IRQs*/
+	[TPS65090_IRQ_VAC_STATUS_CHANGE] = {
+			.mask = TPS65090_INT1_MASK_VAC_STATUS_CHANGE,
+	},
+	[TPS65090_IRQ_VSYS_STATUS_CHANGE] = {
+			.mask = TPS65090_INT1_MASK_VSYS_STATUS_CHANGE,
+	},
+	[TPS65090_IRQ_BAT_STATUS_CHANGE] = {
+			.mask = TPS65090_INT1_MASK_BAT_STATUS_CHANGE,
+	},
+	[TPS65090_IRQ_CHARGING_STATUS_CHANGE] = {
+			.mask = TPS65090_INT1_MASK_CHARGING_STATUS_CHANGE,
+	},
+	[TPS65090_IRQ_CHARGING_COMPLETE] = {
+			.mask = TPS65090_INT1_MASK_CHARGING_COMPLETE,
+	},
+	[TPS65090_IRQ_OVERLOAD_DCDC1] = {
+			.mask = TPS65090_INT1_MASK_OVERLOAD_DCDC1,
+	},
+	[TPS65090_IRQ_OVERLOAD_DCDC2] = {
+			.mask = TPS65090_INT1_MASK_OVERLOAD_DCDC2,
+	},
+	/* INT2 IRQs*/
+	[TPS65090_IRQ_OVERLOAD_DCDC3] = {
+			.reg_offset = 1,
+			.mask = TPS65090_INT2_MASK_OVERLOAD_DCDC3,
+	},
+	[TPS65090_IRQ_OVERLOAD_FET1] = {
+			.reg_offset = 1,
+			.mask = TPS65090_INT2_MASK_OVERLOAD_FET1,
+	},
+	[TPS65090_IRQ_OVERLOAD_FET2] = {
+			.reg_offset = 1,
+			.mask = TPS65090_INT2_MASK_OVERLOAD_FET2,
+	},
+	[TPS65090_IRQ_OVERLOAD_FET3] = {
+			.reg_offset = 1,
+			.mask = TPS65090_INT2_MASK_OVERLOAD_FET3,
+	},
+	[TPS65090_IRQ_OVERLOAD_FET4] = {
+			.reg_offset = 1,
+			.mask = TPS65090_INT2_MASK_OVERLOAD_FET4,
+	},
+	[TPS65090_IRQ_OVERLOAD_FET5] = {
+			.reg_offset = 1,
+			.mask = TPS65090_INT2_MASK_OVERLOAD_FET5,
+	},
+	[TPS65090_IRQ_OVERLOAD_FET6] = {
+			.reg_offset = 1,
+			.mask = TPS65090_INT2_MASK_OVERLOAD_FET6,
+	},
+	[TPS65090_IRQ_OVERLOAD_FET7] = {
+			.reg_offset = 1,
+			.mask = TPS65090_INT2_MASK_OVERLOAD_FET7,
+	},
+};
 
-	return ret;
-}
+static struct regmap_irq_chip tps65090_irq_chip = {
+	.name = "tps65090",
+	.irqs = tps65090_irqs,
+	.num_irqs = ARRAY_SIZE(tps65090_irqs),
+	.num_regs = NUM_INT_REG,
+	.status_base = TPS65090_INT_STS,
+	.mask_base = TPS65090_INT_MSK,
+	.mask_invert = true,
+};
 
 static bool is_volatile_reg(struct device *dev, unsigned int reg)
 {
-	if (reg == TPS65090_INT_STS)
+	if ((reg == TPS65090_INT_STS) || (reg == TPS65090_INT_STS2))
 		return true;
 	else
 		return false;
@@ -251,7 +148,7 @@ static const struct regmap_config tps65090_regmap_config = {
 	.volatile_reg = is_volatile_reg,
 };
 
-static int __devinit tps65090_i2c_probe(struct i2c_client *client,
+static int tps65090_i2c_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	struct tps65090_platform_data *pdata = client->dev.platform_data;
@@ -263,36 +160,36 @@ static int __devinit tps65090_i2c_probe(struct i2c_client *client,
 		return -EINVAL;
 	}
 
-	tps65090 = devm_kzalloc(&client->dev, sizeof(struct tps65090),
-		GFP_KERNEL);
-	if (tps65090 == NULL)
+	tps65090 = devm_kzalloc(&client->dev, sizeof(*tps65090), GFP_KERNEL);
+	if (!tps65090) {
+		dev_err(&client->dev, "mem alloc for tps65090 failed\n");
 		return -ENOMEM;
+	}
 
-	tps65090->client = client;
 	tps65090->dev = &client->dev;
 	i2c_set_clientdata(client, tps65090);
 
-	mutex_init(&tps65090->lock);
-
-	if (client->irq) {
-		ret = tps65090_irq_init(tps65090, client->irq, pdata->irq_base);
-		if (ret) {
-			dev_err(&client->dev, "IRQ init failed with err: %d\n",
-				ret);
-			goto err_exit;
-		}
-	}
-
-	tps65090->rmap = devm_regmap_init_i2c(tps65090->client,
-					      &tps65090_regmap_config);
+	tps65090->rmap = devm_regmap_init_i2c(client, &tps65090_regmap_config);
 	if (IS_ERR(tps65090->rmap)) {
 		ret = PTR_ERR(tps65090->rmap);
 		dev_err(&client->dev, "regmap_init failed with err: %d\n", ret);
-		goto err_irq_exit;
+		return ret;
+	}
+
+	if (client->irq) {
+		ret = regmap_add_irq_chip(tps65090->rmap, client->irq,
+			IRQF_ONESHOT | IRQF_TRIGGER_LOW, pdata->irq_base,
+			&tps65090_irq_chip, &tps65090->irq_data);
+			if (ret) {
+				dev_err(&client->dev,
+					"IRQ init failed with err: %d\n", ret);
+			return ret;
+		}
 	}
 
 	ret = mfd_add_devices(tps65090->dev, -1, tps65090s,
-			      ARRAY_SIZE(tps65090s), NULL, 0, NULL);
+		ARRAY_SIZE(tps65090s), NULL,
+		regmap_irq_chip_get_base(tps65090->irq_data), NULL);
 	if (ret) {
 		dev_err(&client->dev, "add mfd devices failed with err: %d\n",
 			ret);
@@ -303,18 +200,17 @@ static int __devinit tps65090_i2c_probe(struct i2c_client *client,
 
 err_irq_exit:
 	if (client->irq)
-		free_irq(client->irq, tps65090);
-err_exit:
+		regmap_del_irq_chip(client->irq, tps65090->irq_data);
 	return ret;
 }
 
-static int __devexit tps65090_i2c_remove(struct i2c_client *client)
+static int tps65090_i2c_remove(struct i2c_client *client)
 {
 	struct tps65090 *tps65090 = i2c_get_clientdata(client);
 
 	mfd_remove_devices(tps65090->dev);
 	if (client->irq)
-		free_irq(client->irq, tps65090);
+		regmap_del_irq_chip(client->irq, tps65090->irq_data);
 
 	return 0;
 }
@@ -354,7 +250,7 @@ static struct i2c_driver tps65090_driver = {
 		.pm	= &tps65090_pm_ops,
 	},
 	.probe		= tps65090_i2c_probe,
-	.remove		= __devexit_p(tps65090_i2c_remove),
+	.remove		= tps65090_i2c_remove,
 	.id_table	= tps65090_id_table,
 };
 
diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c
index 3fb32e6..b8f4864 100644
--- a/drivers/mfd/tps65217.c
+++ b/drivers/mfd/tps65217.c
@@ -153,13 +153,14 @@ static const struct of_device_id tps65217_of_match[] = {
 	{ /* sentinel */ },
 };
 
-static int __devinit tps65217_probe(struct i2c_client *client,
+static int tps65217_probe(struct i2c_client *client,
 				const struct i2c_device_id *ids)
 {
 	struct tps65217 *tps;
 	unsigned int version;
 	unsigned int chip_id = ids->driver_data;
 	const struct of_device_id *match;
+	bool status_off = false;
 	int ret;
 
 	if (client->dev.of_node) {
@@ -170,6 +171,8 @@ static int __devinit tps65217_probe(struct i2c_client *client,
 			return -EINVAL;
 		}
 		chip_id = (unsigned int)match->data;
+		status_off = of_property_read_bool(client->dev.of_node,
+					"ti,pmic-shutdown-controller");
 	}
 
 	if (!chip_id) {
@@ -207,6 +210,15 @@ static int __devinit tps65217_probe(struct i2c_client *client,
 		return ret;
 	}
 
+	/* Set the PMIC to shutdown on PWR_EN toggle */
+	if (status_off) {
+		ret = tps65217_set_bits(tps, TPS65217_REG_STATUS,
+				TPS65217_STATUS_OFF, TPS65217_STATUS_OFF,
+				TPS65217_PROTECT_NONE);
+		if (ret)
+			dev_warn(tps->dev, "unable to set the status OFF\n");
+	}
+
 	dev_info(tps->dev, "TPS65217 ID %#x version 1.%d\n",
 			(version & TPS65217_CHIPID_CHIP_MASK) >> 4,
 			version & TPS65217_CHIPID_REV_MASK);
@@ -214,7 +226,7 @@ static int __devinit tps65217_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int __devexit tps65217_remove(struct i2c_client *client)
+static int tps65217_remove(struct i2c_client *client)
 {
 	struct tps65217 *tps = i2c_get_clientdata(client);
 
@@ -237,7 +249,7 @@ static struct i2c_driver tps65217_driver = {
 	},
 	.id_table	= tps65217_id_table,
 	.probe		= tps65217_probe,
-	.remove		= __devexit_p(tps65217_remove),
+	.remove		= tps65217_remove,
 };
 
 static int __init tps65217_init(void)
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 4674643..721b918 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -17,15 +17,15 @@
 
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
+#include <linux/platform_device.h>
 #include <linux/regmap.h>
-#include <linux/regulator/of_regulator.h>
-#include <linux/regulator/machine.h>
 
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps6586x.h>
@@ -94,12 +94,25 @@ static const struct tps6586x_irq_data tps6586x_irqs[] = {
 	[TPS6586X_INT_RTC_ALM2] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 1),
 };
 
+static struct resource tps6586x_rtc_resources[] = {
+	{
+		.start  = TPS6586X_INT_RTC_ALM1,
+		.end	= TPS6586X_INT_RTC_ALM1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
 static struct mfd_cell tps6586x_cell[] = {
 	{
 		.name = "tps6586x-gpio",
 	},
 	{
+		.name = "tps6586x-pmic",
+	},
+	{
 		.name = "tps6586x-rtc",
+		.num_resources = ARRAY_SIZE(tps6586x_rtc_resources),
+		.resources = &tps6586x_rtc_resources[0],
 	},
 	{
 		.name = "tps6586x-onkey",
@@ -116,6 +129,7 @@ struct tps6586x {
 	int			irq_base;
 	u32			irq_en;
 	u8			mask_reg[5];
+	struct irq_domain	*irq_domain;
 };
 
 static inline struct tps6586x *dev_to_tps6586x(struct device *dev)
@@ -184,6 +198,14 @@ int tps6586x_update(struct device *dev, int reg, uint8_t val, uint8_t mask)
 }
 EXPORT_SYMBOL_GPL(tps6586x_update);
 
+int tps6586x_irq_get_virq(struct device *dev, int irq)
+{
+	struct tps6586x *tps6586x = dev_to_tps6586x(dev);
+
+	return irq_create_mapping(tps6586x->irq_domain, irq);
+}
+EXPORT_SYMBOL_GPL(tps6586x_irq_get_virq);
+
 static int __remove_subdev(struct device *dev, void *unused)
 {
 	platform_device_unregister(to_platform_device(dev));
@@ -205,7 +227,7 @@ static void tps6586x_irq_lock(struct irq_data *data)
 static void tps6586x_irq_enable(struct irq_data *irq_data)
 {
 	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data);
-	unsigned int __irq = irq_data->irq - tps6586x->irq_base;
+	unsigned int __irq = irq_data->hwirq;
 	const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq];
 
 	tps6586x->mask_reg[data->mask_reg] &= ~data->mask_mask;
@@ -216,7 +238,7 @@ static void tps6586x_irq_disable(struct irq_data *irq_data)
 {
 	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data);
 
-	unsigned int __irq = irq_data->irq - tps6586x->irq_base;
+	unsigned int __irq = irq_data->hwirq;
 	const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq];
 
 	tps6586x->mask_reg[data->mask_reg] |= data->mask_mask;
@@ -239,6 +261,39 @@ static void tps6586x_irq_sync_unlock(struct irq_data *data)
 	mutex_unlock(&tps6586x->irq_lock);
 }
 
+static struct irq_chip tps6586x_irq_chip = {
+	.name = "tps6586x",
+	.irq_bus_lock = tps6586x_irq_lock,
+	.irq_bus_sync_unlock = tps6586x_irq_sync_unlock,
+	.irq_disable = tps6586x_irq_disable,
+	.irq_enable = tps6586x_irq_enable,
+};
+
+static int tps6586x_irq_map(struct irq_domain *h, unsigned int virq,
+				irq_hw_number_t hw)
+{
+	struct tps6586x *tps6586x = h->host_data;
+
+	irq_set_chip_data(virq, tps6586x);
+	irq_set_chip_and_handler(virq, &tps6586x_irq_chip, handle_simple_irq);
+	irq_set_nested_thread(virq, 1);
+
+	/* ARM needs us to explicitly flag the IRQ as valid
+	 * and will set them noprobe when we do so. */
+#ifdef CONFIG_ARM
+	set_irq_flags(virq, IRQF_VALID);
+#else
+	irq_set_noprobe(virq);
+#endif
+
+	return 0;
+}
+
+static struct irq_domain_ops tps6586x_domain_ops = {
+	.map    = tps6586x_irq_map,
+	.xlate  = irq_domain_xlate_twocell,
+};
+
 static irqreturn_t tps6586x_irq(int irq, void *data)
 {
 	struct tps6586x *tps6586x = data;
@@ -259,7 +314,8 @@ static irqreturn_t tps6586x_irq(int irq, void *data)
 		int i = __ffs(acks);
 
 		if (tps6586x->irq_en & (1 << i))
-			handle_nested_irq(tps6586x->irq_base + i);
+			handle_nested_irq(
+				irq_find_mapping(tps6586x->irq_domain, i));
 
 		acks &= ~(1 << i);
 	}
@@ -267,16 +323,13 @@ static irqreturn_t tps6586x_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
+static int tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
 				       int irq_base)
 {
 	int i, ret;
 	u8 tmp[4];
-
-	if (!irq_base) {
-		dev_warn(tps6586x->dev, "No interrupt support on IRQ base\n");
-		return -EINVAL;
-	}
+	int new_irq_base;
+	int irq_num = ARRAY_SIZE(tps6586x_irqs);
 
 	mutex_init(&tps6586x->irq_lock);
 	for (i = 0; i < 5; i++) {
@@ -286,25 +339,24 @@ static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
 
 	tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1, sizeof(tmp), tmp);
 
-	tps6586x->irq_base = irq_base;
-
-	tps6586x->irq_chip.name = "tps6586x";
-	tps6586x->irq_chip.irq_enable = tps6586x_irq_enable;
-	tps6586x->irq_chip.irq_disable = tps6586x_irq_disable;
-	tps6586x->irq_chip.irq_bus_lock = tps6586x_irq_lock;
-	tps6586x->irq_chip.irq_bus_sync_unlock = tps6586x_irq_sync_unlock;
-
-	for (i = 0; i < ARRAY_SIZE(tps6586x_irqs); i++) {
-		int __irq = i + tps6586x->irq_base;
-		irq_set_chip_data(__irq, tps6586x);
-		irq_set_chip_and_handler(__irq, &tps6586x->irq_chip,
-					 handle_simple_irq);
-		irq_set_nested_thread(__irq, 1);
-#ifdef CONFIG_ARM
-		set_irq_flags(__irq, IRQF_VALID);
-#endif
+	if  (irq_base > 0) {
+		new_irq_base = irq_alloc_descs(irq_base, 0, irq_num, -1);
+		if (new_irq_base < 0) {
+			dev_err(tps6586x->dev,
+				"Failed to alloc IRQs: %d\n", new_irq_base);
+			return new_irq_base;
+		}
+	} else {
+		new_irq_base = 0;
 	}
 
+	tps6586x->irq_domain = irq_domain_add_simple(tps6586x->dev->of_node,
+				irq_num, new_irq_base, &tps6586x_domain_ops,
+				tps6586x);
+	if (!tps6586x->irq_domain) {
+		dev_err(tps6586x->dev, "Failed to create IRQ domain\n");
+		return -ENOMEM;
+	}
 	ret = request_threaded_irq(irq, NULL, tps6586x_irq, IRQF_ONESHOT,
 				   "tps6586x", tps6586x);
 
@@ -316,7 +368,7 @@ static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
 	return ret;
 }
 
-static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x,
+static int tps6586x_add_subdevs(struct tps6586x *tps6586x,
 					  struct tps6586x_platform_data *pdata)
 {
 	struct tps6586x_subdev_info *subdev;
@@ -350,80 +402,19 @@ failed:
 }
 
 #ifdef CONFIG_OF
-static struct of_regulator_match tps6586x_matches[] = {
-	{ .name = "sys",     .driver_data = (void *)TPS6586X_ID_SYS     },
-	{ .name = "sm0",     .driver_data = (void *)TPS6586X_ID_SM_0    },
-	{ .name = "sm1",     .driver_data = (void *)TPS6586X_ID_SM_1    },
-	{ .name = "sm2",     .driver_data = (void *)TPS6586X_ID_SM_2    },
-	{ .name = "ldo0",    .driver_data = (void *)TPS6586X_ID_LDO_0   },
-	{ .name = "ldo1",    .driver_data = (void *)TPS6586X_ID_LDO_1   },
-	{ .name = "ldo2",    .driver_data = (void *)TPS6586X_ID_LDO_2   },
-	{ .name = "ldo3",    .driver_data = (void *)TPS6586X_ID_LDO_3   },
-	{ .name = "ldo4",    .driver_data = (void *)TPS6586X_ID_LDO_4   },
-	{ .name = "ldo5",    .driver_data = (void *)TPS6586X_ID_LDO_5   },
-	{ .name = "ldo6",    .driver_data = (void *)TPS6586X_ID_LDO_6   },
-	{ .name = "ldo7",    .driver_data = (void *)TPS6586X_ID_LDO_7   },
-	{ .name = "ldo8",    .driver_data = (void *)TPS6586X_ID_LDO_8   },
-	{ .name = "ldo9",    .driver_data = (void *)TPS6586X_ID_LDO_9   },
-	{ .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC },
-};
-
 static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client)
 {
-	const unsigned int num = ARRAY_SIZE(tps6586x_matches);
 	struct device_node *np = client->dev.of_node;
 	struct tps6586x_platform_data *pdata;
-	struct tps6586x_subdev_info *devs;
-	struct device_node *regs;
-	const char *sys_rail_name = NULL;
-	unsigned int count;
-	unsigned int i, j;
-	int err;
-
-	regs = of_find_node_by_name(np, "regulators");
-	if (!regs)
-		return NULL;
-
-	err = of_regulator_match(&client->dev, regs, tps6586x_matches, num);
-	if (err < 0) {
-		of_node_put(regs);
-		return NULL;
-	}
-
-	of_node_put(regs);
-	count = err;
-
-	devs = devm_kzalloc(&client->dev, count * sizeof(*devs), GFP_KERNEL);
-	if (!devs)
-		return NULL;
-
-	for (i = 0, j = 0; i < num && j < count; i++) {
-		struct regulator_init_data *reg_idata;
-
-		if (!tps6586x_matches[i].init_data)
-			continue;
-
-		reg_idata  = tps6586x_matches[i].init_data;
-		devs[j].name = "tps6586x-regulator";
-		devs[j].platform_data = tps6586x_matches[i].init_data;
-		devs[j].id = (int)tps6586x_matches[i].driver_data;
-		if (devs[j].id == TPS6586X_ID_SYS)
-			sys_rail_name = reg_idata->constraints.name;
-
-		if ((devs[j].id == TPS6586X_ID_LDO_5) ||
-			(devs[j].id == TPS6586X_ID_LDO_RTC))
-			reg_idata->supply_regulator = sys_rail_name;
-
-		devs[j].of_node = tps6586x_matches[i].of_node;
-		j++;
-	}
 
 	pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
-	if (!pdata)
+	if (!pdata) {
+		dev_err(&client->dev, "Memory allocation failed\n");
 		return NULL;
+	}
 
-	pdata->num_subdevs = count;
-	pdata->subdevs = devs;
+	pdata->num_subdevs = 0;
+	pdata->subdevs = NULL;
 	pdata->gpio_base = -1;
 	pdata->irq_base = -1;
 	pdata->pm_off = of_property_read_bool(np, "ti,system-power-controller");
@@ -468,7 +459,7 @@ static void tps6586x_power_off(void)
 	tps6586x_set_bits(tps6586x_dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT);
 }
 
-static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
+static int tps6586x_i2c_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	struct tps6586x_platform_data *pdata = client->dev.platform_data;
@@ -521,7 +512,7 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
 
 	ret = mfd_add_devices(tps6586x->dev, -1,
 			      tps6586x_cell, ARRAY_SIZE(tps6586x_cell),
-			      NULL, 0, NULL);
+			      NULL, 0, tps6586x->irq_domain);
 	if (ret < 0) {
 		dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret);
 		goto err_mfd_add;
@@ -548,7 +539,7 @@ err_mfd_add:
 	return ret;
 }
 
-static int __devexit tps6586x_i2c_remove(struct i2c_client *client)
+static int tps6586x_i2c_remove(struct i2c_client *client)
 {
 	struct tps6586x *tps6586x = i2c_get_clientdata(client);
 
@@ -572,7 +563,7 @@ static struct i2c_driver tps6586x_driver = {
 		.of_match_table = of_match_ptr(tps6586x_of_match),
 	},
 	.probe		= tps6586x_i2c_probe,
-	.remove		= __devexit_p(tps6586x_i2c_remove),
+	.remove		= tps6586x_i2c_remove,
 	.id_table	= tps6586x_id_table,
 };
 
diff --git a/drivers/mfd/tps65910-irq.c b/drivers/mfd/tps65910-irq.c
deleted file mode 100644
index 09aab3e4..0000000
--- a/drivers/mfd/tps65910-irq.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * tps65910-irq.c  --  TI TPS6591x
- *
- * Copyright 2010 Texas Instruments Inc.
- *
- * Author: Graeme Gregory <gg@slimlogic.co.uk>
- * Author: Jorge Eduardo Candelaria <jedu@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.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/bug.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/gpio.h>
-#include <linux/mfd/tps65910.h>
-
-/*
- * This is a threaded IRQ handler so can access I2C/SPI.  Since all
- * interrupts are clear on read the IRQ line will be reasserted and
- * the physical IRQ will be handled again if another interrupt is
- * asserted while we run - in the normal course of events this is a
- * rare occurrence so we save I2C/SPI reads.  We're also assuming that
- * it's rare to get lots of interrupts firing simultaneously so try to
- * minimise I/O.
- */
-static irqreturn_t tps65910_irq(int irq, void *irq_data)
-{
-	struct tps65910 *tps65910 = irq_data;
-	unsigned int reg;
-	u32 irq_sts;
-	u32 irq_mask;
-	int i;
-
-	tps65910_reg_read(tps65910, TPS65910_INT_STS, &reg);
-	irq_sts = reg;
-	tps65910_reg_read(tps65910, TPS65910_INT_STS2, &reg);
-	irq_sts |= reg << 8;
-	switch (tps65910_chip_id(tps65910)) {
-	case TPS65911:
-		tps65910_reg_read(tps65910, TPS65910_INT_STS3, &reg);
-		irq_sts |= reg << 16;
-	}
-
-	tps65910_reg_read(tps65910, TPS65910_INT_MSK, &reg);
-	irq_mask = reg;
-	tps65910_reg_read(tps65910, TPS65910_INT_MSK2, &reg);
-	irq_mask |= reg << 8;
-	switch (tps65910_chip_id(tps65910)) {
-	case TPS65911:
-		tps65910_reg_read(tps65910, TPS65910_INT_MSK3, &reg);
-		irq_mask |= reg << 16;
-	}
-
-	irq_sts &= ~irq_mask;
-
-	if (!irq_sts)
-		return IRQ_NONE;
-
-	for (i = 0; i < tps65910->irq_num; i++) {
-
-		if (!(irq_sts & (1 << i)))
-			continue;
-
-		handle_nested_irq(irq_find_mapping(tps65910->domain, i));
-	}
-
-	/* Write the STS register back to clear IRQs we handled */
-	reg = irq_sts & 0xFF;
-	irq_sts >>= 8;
-	tps65910_reg_write(tps65910, TPS65910_INT_STS, reg);
-	reg = irq_sts & 0xFF;
-	tps65910_reg_write(tps65910, TPS65910_INT_STS2, reg);
-	switch (tps65910_chip_id(tps65910)) {
-	case TPS65911:
-		reg = irq_sts >> 8;
-		tps65910_reg_write(tps65910, TPS65910_INT_STS3, reg);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static void tps65910_irq_lock(struct irq_data *data)
-{
-	struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
-
-	mutex_lock(&tps65910->irq_lock);
-}
-
-static void tps65910_irq_sync_unlock(struct irq_data *data)
-{
-	struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
-	u32 reg_mask;
-	unsigned int reg;
-
-	tps65910_reg_read(tps65910, TPS65910_INT_MSK, &reg);
-	reg_mask = reg;
-	tps65910_reg_read(tps65910, TPS65910_INT_MSK2, &reg);
-	reg_mask |= reg << 8;
-	switch (tps65910_chip_id(tps65910)) {
-	case TPS65911:
-		tps65910_reg_read(tps65910, TPS65910_INT_MSK3, &reg);
-		reg_mask |= reg << 16;
-	}
-
-	if (tps65910->irq_mask != reg_mask) {
-		reg = tps65910->irq_mask & 0xFF;
-		tps65910_reg_write(tps65910, TPS65910_INT_MSK, reg);
-		reg = tps65910->irq_mask >> 8 & 0xFF;
-		tps65910_reg_write(tps65910, TPS65910_INT_MSK2, reg);
-		switch (tps65910_chip_id(tps65910)) {
-		case TPS65911:
-			reg = tps65910->irq_mask >> 16;
-			tps65910_reg_write(tps65910, TPS65910_INT_MSK3, reg);
-		}
-	}
-	mutex_unlock(&tps65910->irq_lock);
-}
-
-static void tps65910_irq_enable(struct irq_data *data)
-{
-	struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
-
-	tps65910->irq_mask &= ~(1 << data->hwirq);
-}
-
-static void tps65910_irq_disable(struct irq_data *data)
-{
-	struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
-
-	tps65910->irq_mask |= (1 << data->hwirq);
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int tps65910_irq_set_wake(struct irq_data *data, unsigned int enable)
-{
-	struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
-	return irq_set_irq_wake(tps65910->chip_irq, enable);
-}
-#else
-#define tps65910_irq_set_wake NULL
-#endif
-
-static struct irq_chip tps65910_irq_chip = {
-	.name = "tps65910",
-	.irq_bus_lock = tps65910_irq_lock,
-	.irq_bus_sync_unlock = tps65910_irq_sync_unlock,
-	.irq_disable = tps65910_irq_disable,
-	.irq_enable = tps65910_irq_enable,
-	.irq_set_wake = tps65910_irq_set_wake,
-};
-
-static int tps65910_irq_map(struct irq_domain *h, unsigned int virq,
-				irq_hw_number_t hw)
-{
-	struct tps65910 *tps65910 = h->host_data;
-
-	irq_set_chip_data(virq, tps65910);
-	irq_set_chip_and_handler(virq, &tps65910_irq_chip, handle_edge_irq);
-	irq_set_nested_thread(virq, 1);
-
-	/* ARM needs us to explicitly flag the IRQ as valid
-	 * and will set them noprobe when we do so. */
-#ifdef CONFIG_ARM
-	set_irq_flags(virq, IRQF_VALID);
-#else
-	irq_set_noprobe(virq);
-#endif
-
-	return 0;
-}
-
-static struct irq_domain_ops tps65910_domain_ops = {
-	.map	= tps65910_irq_map,
-	.xlate	= irq_domain_xlate_twocell,
-};
-
-int tps65910_irq_init(struct tps65910 *tps65910, int irq,
-		    struct tps65910_platform_data *pdata)
-{
-	int ret;
-	int flags = IRQF_ONESHOT;
-
-	if (!irq) {
-		dev_warn(tps65910->dev, "No interrupt support, no core IRQ\n");
-		return -EINVAL;
-	}
-
-	if (!pdata) {
-		dev_warn(tps65910->dev, "No interrupt support, no pdata\n");
-		return -EINVAL;
-	}
-
-	switch (tps65910_chip_id(tps65910)) {
-	case TPS65910:
-		tps65910->irq_num = TPS65910_NUM_IRQ;
-		break;
-	case TPS65911:
-		tps65910->irq_num = TPS65911_NUM_IRQ;
-		break;
-	}
-
-	if (pdata->irq_base > 0) {
-		pdata->irq_base = irq_alloc_descs(pdata->irq_base, 0,
-					tps65910->irq_num, -1);
-		if (pdata->irq_base < 0) {
-			dev_warn(tps65910->dev, "Failed to alloc IRQs: %d\n",
-					pdata->irq_base);
-			return pdata->irq_base;
-		}
-	}
-
-	tps65910->irq_mask = 0xFFFFFF;
-
-	mutex_init(&tps65910->irq_lock);
-	tps65910->chip_irq = irq;
-	tps65910->irq_base = pdata->irq_base;
-
-	if (pdata->irq_base > 0)
-		tps65910->domain = irq_domain_add_legacy(tps65910->dev->of_node,
-					tps65910->irq_num,
-					pdata->irq_base,
-					0,
-					&tps65910_domain_ops, tps65910);
-	else
-		tps65910->domain = irq_domain_add_linear(tps65910->dev->of_node,
-					tps65910->irq_num,
-					&tps65910_domain_ops, tps65910);
-
-	if (!tps65910->domain) {
-		dev_err(tps65910->dev, "Failed to create IRQ domain\n");
-		return -ENOMEM;
-	}
-
-	ret = request_threaded_irq(irq, NULL, tps65910_irq, flags,
-				   "tps65910", tps65910);
-
-	irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
-
-	if (ret != 0)
-		dev_err(tps65910->dev, "Failed to request IRQ: %d\n", ret);
-
-	return ret;
-}
-
-int tps65910_irq_exit(struct tps65910 *tps65910)
-{
-	if (tps65910->chip_irq)
-		free_irq(tps65910->chip_irq, tps65910);
-	return 0;
-}
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index 0d79ce2..3e9c657 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -19,6 +19,9 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/mfd/core.h>
 #include <linux/regmap.h>
 #include <linux/mfd/tps65910.h>
@@ -50,6 +53,219 @@ static struct mfd_cell tps65910s[] = {
 };
 
 
+static const struct regmap_irq tps65911_irqs[] = {
+	/* INT_STS */
+	[TPS65911_IRQ_PWRHOLD_F] = {
+		.mask = INT_MSK_PWRHOLD_F_IT_MSK_MASK,
+		.reg_offset = 0,
+	},
+	[TPS65911_IRQ_VBAT_VMHI] = {
+		.mask = INT_MSK_VMBHI_IT_MSK_MASK,
+		.reg_offset = 0,
+	},
+	[TPS65911_IRQ_PWRON] = {
+		.mask = INT_MSK_PWRON_IT_MSK_MASK,
+		.reg_offset = 0,
+	},
+	[TPS65911_IRQ_PWRON_LP] = {
+		.mask = INT_MSK_PWRON_LP_IT_MSK_MASK,
+		.reg_offset = 0,
+	},
+	[TPS65911_IRQ_PWRHOLD_R] = {
+		.mask = INT_MSK_PWRHOLD_R_IT_MSK_MASK,
+		.reg_offset = 0,
+	},
+	[TPS65911_IRQ_HOTDIE] = {
+		.mask = INT_MSK_HOTDIE_IT_MSK_MASK,
+		.reg_offset = 0,
+	},
+	[TPS65911_IRQ_RTC_ALARM] = {
+		.mask = INT_MSK_RTC_ALARM_IT_MSK_MASK,
+		.reg_offset = 0,
+	},
+	[TPS65911_IRQ_RTC_PERIOD] = {
+		.mask = INT_MSK_RTC_PERIOD_IT_MSK_MASK,
+		.reg_offset = 0,
+	},
+
+	/* INT_STS2 */
+	[TPS65911_IRQ_GPIO0_R] = {
+		.mask = INT_MSK2_GPIO0_R_IT_MSK_MASK,
+		.reg_offset = 1,
+	},
+	[TPS65911_IRQ_GPIO0_F] = {
+		.mask = INT_MSK2_GPIO0_F_IT_MSK_MASK,
+		.reg_offset = 1,
+	},
+	[TPS65911_IRQ_GPIO1_R] = {
+		.mask = INT_MSK2_GPIO1_R_IT_MSK_MASK,
+		.reg_offset = 1,
+	},
+	[TPS65911_IRQ_GPIO1_F] = {
+		.mask = INT_MSK2_GPIO1_F_IT_MSK_MASK,
+		.reg_offset = 1,
+	},
+	[TPS65911_IRQ_GPIO2_R] = {
+		.mask = INT_MSK2_GPIO2_R_IT_MSK_MASK,
+		.reg_offset = 1,
+	},
+	[TPS65911_IRQ_GPIO2_F] = {
+		.mask = INT_MSK2_GPIO2_F_IT_MSK_MASK,
+		.reg_offset = 1,
+	},
+	[TPS65911_IRQ_GPIO3_R] = {
+		.mask = INT_MSK2_GPIO3_R_IT_MSK_MASK,
+		.reg_offset = 1,
+	},
+	[TPS65911_IRQ_GPIO3_F] = {
+		.mask = INT_MSK2_GPIO3_F_IT_MSK_MASK,
+		.reg_offset = 1,
+	},
+
+	/* INT_STS2 */
+	[TPS65911_IRQ_GPIO4_R] = {
+		.mask = INT_MSK3_GPIO4_R_IT_MSK_MASK,
+		.reg_offset = 2,
+	},
+	[TPS65911_IRQ_GPIO4_F] = {
+		.mask = INT_MSK3_GPIO4_F_IT_MSK_MASK,
+		.reg_offset = 2,
+	},
+	[TPS65911_IRQ_GPIO5_R] = {
+		.mask = INT_MSK3_GPIO5_R_IT_MSK_MASK,
+		.reg_offset = 2,
+	},
+	[TPS65911_IRQ_GPIO5_F] = {
+		.mask = INT_MSK3_GPIO5_F_IT_MSK_MASK,
+		.reg_offset = 2,
+	},
+	[TPS65911_IRQ_WTCHDG] = {
+		.mask = INT_MSK3_WTCHDG_IT_MSK_MASK,
+		.reg_offset = 2,
+	},
+	[TPS65911_IRQ_VMBCH2_H] = {
+		.mask = INT_MSK3_VMBCH2_H_IT_MSK_MASK,
+		.reg_offset = 2,
+	},
+	[TPS65911_IRQ_VMBCH2_L] = {
+		.mask = INT_MSK3_VMBCH2_L_IT_MSK_MASK,
+		.reg_offset = 2,
+	},
+	[TPS65911_IRQ_PWRDN] = {
+		.mask = INT_MSK3_PWRDN_IT_MSK_MASK,
+		.reg_offset = 2,
+	},
+};
+
+static const struct regmap_irq tps65910_irqs[] = {
+	/* INT_STS */
+	[TPS65910_IRQ_VBAT_VMBDCH] = {
+		.mask = TPS65910_INT_MSK_VMBDCH_IT_MSK_MASK,
+		.reg_offset = 0,
+	},
+	[TPS65910_IRQ_VBAT_VMHI] = {
+		.mask = TPS65910_INT_MSK_VMBHI_IT_MSK_MASK,
+		.reg_offset = 0,
+	},
+	[TPS65910_IRQ_PWRON] = {
+		.mask = TPS65910_INT_MSK_PWRON_IT_MSK_MASK,
+		.reg_offset = 0,
+	},
+	[TPS65910_IRQ_PWRON_LP] = {
+		.mask = TPS65910_INT_MSK_PWRON_LP_IT_MSK_MASK,
+		.reg_offset = 0,
+	},
+	[TPS65910_IRQ_PWRHOLD] = {
+		.mask = TPS65910_INT_MSK_PWRHOLD_IT_MSK_MASK,
+		.reg_offset = 0,
+	},
+	[TPS65910_IRQ_HOTDIE] = {
+		.mask = TPS65910_INT_MSK_HOTDIE_IT_MSK_MASK,
+		.reg_offset = 0,
+	},
+	[TPS65910_IRQ_RTC_ALARM] = {
+		.mask = TPS65910_INT_MSK_RTC_ALARM_IT_MSK_MASK,
+		.reg_offset = 0,
+	},
+	[TPS65910_IRQ_RTC_PERIOD] = {
+		.mask = TPS65910_INT_MSK_RTC_PERIOD_IT_MSK_MASK,
+		.reg_offset = 0,
+	},
+
+	/* INT_STS2 */
+	[TPS65910_IRQ_GPIO_R] = {
+		.mask = TPS65910_INT_MSK2_GPIO0_F_IT_MSK_MASK,
+		.reg_offset = 1,
+	},
+	[TPS65910_IRQ_GPIO_F] = {
+		.mask = TPS65910_INT_MSK2_GPIO0_R_IT_MSK_MASK,
+		.reg_offset = 1,
+	},
+};
+
+static struct regmap_irq_chip tps65911_irq_chip = {
+	.name = "tps65910",
+	.irqs = tps65911_irqs,
+	.num_irqs = ARRAY_SIZE(tps65911_irqs),
+	.num_regs = 3,
+	.irq_reg_stride = 2,
+	.status_base = TPS65910_INT_STS,
+	.mask_base = TPS65910_INT_MSK,
+	.ack_base = TPS65910_INT_MSK,
+};
+
+static struct regmap_irq_chip tps65910_irq_chip = {
+	.name = "tps65910",
+	.irqs = tps65910_irqs,
+	.num_irqs = ARRAY_SIZE(tps65910_irqs),
+	.num_regs = 2,
+	.irq_reg_stride = 2,
+	.status_base = TPS65910_INT_STS,
+	.mask_base = TPS65910_INT_MSK,
+	.ack_base = TPS65910_INT_MSK,
+};
+
+static int tps65910_irq_init(struct tps65910 *tps65910, int irq,
+		    struct tps65910_platform_data *pdata)
+{
+	int ret = 0;
+	static struct regmap_irq_chip *tps6591x_irqs_chip;
+
+	if (!irq) {
+		dev_warn(tps65910->dev, "No interrupt support, no core IRQ\n");
+		return -EINVAL;
+	}
+
+	if (!pdata) {
+		dev_warn(tps65910->dev, "No interrupt support, no pdata\n");
+		return -EINVAL;
+	}
+
+	switch (tps65910_chip_id(tps65910)) {
+	case TPS65910:
+		tps6591x_irqs_chip = &tps65910_irq_chip;
+		break;
+	case TPS65911:
+		tps6591x_irqs_chip = &tps65911_irq_chip;
+		break;
+	}
+
+	tps65910->chip_irq = irq;
+	ret = regmap_add_irq_chip(tps65910->regmap, tps65910->chip_irq,
+		IRQF_ONESHOT, pdata->irq_base,
+		tps6591x_irqs_chip, &tps65910->irq_data);
+	if (ret < 0)
+		dev_warn(tps65910->dev, "Failed to add irq_chip %d\n", ret);
+	return ret;
+}
+
+static int tps65910_irq_exit(struct tps65910 *tps65910)
+{
+	if (tps65910->chip_irq > 0)
+		regmap_del_irq_chip(tps65910->chip_irq, tps65910->irq_data);
+	return 0;
+}
+
 static bool is_volatile_reg(struct device *dev, unsigned int reg)
 {
 	struct tps65910 *tps65910 = dev_get_drvdata(dev);
@@ -78,7 +294,7 @@ static const struct regmap_config tps65910_regmap_config = {
 	.cache_type = REGCACHE_RBTREE,
 };
 
-static int __devinit tps65910_ck32k_init(struct tps65910 *tps65910,
+static int tps65910_ck32k_init(struct tps65910 *tps65910,
 					struct tps65910_board *pmic_pdata)
 {
 	int ret;
@@ -96,7 +312,7 @@ static int __devinit tps65910_ck32k_init(struct tps65910 *tps65910,
 	return 0;
 }
 
-static int __devinit tps65910_sleepinit(struct tps65910 *tps65910,
+static int tps65910_sleepinit(struct tps65910 *tps65910,
 		struct tps65910_board *pmic_pdata)
 {
 	struct device *dev = NULL;
@@ -237,7 +453,7 @@ static void tps65910_power_off(void)
 			DEVCTRL_DEV_ON_MASK);
 }
 
-static __devinit int tps65910_i2c_probe(struct i2c_client *i2c,
+static int tps65910_i2c_probe(struct i2c_client *i2c,
 					const struct i2c_device_id *id)
 {
 	struct tps65910 *tps65910;
@@ -279,14 +495,6 @@ static __devinit int tps65910_i2c_probe(struct i2c_client *i2c,
 		return ret;
 	}
 
-	ret = mfd_add_devices(tps65910->dev, -1,
-			      tps65910s, ARRAY_SIZE(tps65910s),
-			      NULL, 0, NULL);
-	if (ret < 0) {
-		dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret);
-		return ret;
-	}
-
 	init_data->irq = pmic_plat_data->irq;
 	init_data->irq_base = pmic_plat_data->irq_base;
 
@@ -299,10 +507,19 @@ static __devinit int tps65910_i2c_probe(struct i2c_client *i2c,
 		pm_power_off = tps65910_power_off;
 	}
 
+	ret = mfd_add_devices(tps65910->dev, -1,
+			      tps65910s, ARRAY_SIZE(tps65910s),
+			      NULL, 0,
+			      regmap_irq_get_domain(tps65910->irq_data));
+	if (ret < 0) {
+		dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret);
+		return ret;
+	}
+
 	return ret;
 }
 
-static __devexit int tps65910_i2c_remove(struct i2c_client *i2c)
+static int tps65910_i2c_remove(struct i2c_client *i2c)
 {
 	struct tps65910 *tps65910 = i2c_get_clientdata(i2c);
 
@@ -327,7 +544,7 @@ static struct i2c_driver tps65910_i2c_driver = {
 		   .of_match_table = of_match_ptr(tps65910_of_match),
 	},
 	.probe = tps65910_i2c_probe,
-	.remove = __devexit_p(tps65910_i2c_remove),
+	.remove = tps65910_i2c_remove,
 	.id_table = tps65910_i2c_id,
 };
 
diff --git a/drivers/mfd/tps65911-comparator.c b/drivers/mfd/tps65911-comparator.c
index 0b6e361..c0816eb 100644
--- a/drivers/mfd/tps65911-comparator.c
+++ b/drivers/mfd/tps65911-comparator.c
@@ -122,7 +122,7 @@ static ssize_t comp_threshold_show(struct device *dev,
 static DEVICE_ATTR(comp1_threshold, S_IRUGO, comp_threshold_show, NULL);
 static DEVICE_ATTR(comp2_threshold, S_IRUGO, comp_threshold_show, NULL);
 
-static __devinit int tps65911_comparator_probe(struct platform_device *pdev)
+static int tps65911_comparator_probe(struct platform_device *pdev)
 {
 	struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
 	struct tps65910_board *pdata = dev_get_platdata(tps65910->dev);
@@ -152,7 +152,7 @@ static __devinit int tps65911_comparator_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static __devexit int tps65911_comparator_remove(struct platform_device *pdev)
+static int tps65911_comparator_remove(struct platform_device *pdev)
 {
 	struct tps65910 *tps65910;
 
@@ -169,7 +169,7 @@ static struct platform_driver tps65911_comparator_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = tps65911_comparator_probe,
-	.remove = __devexit_p(tps65911_comparator_remove),
+	.remove = tps65911_comparator_remove,
 };
 
 static int __init tps65911_comparator_init(void)
diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c
index 27d3302..b45f460 100644
--- a/drivers/mfd/tps65912-spi.c
+++ b/drivers/mfd/tps65912-spi.c
@@ -81,7 +81,7 @@ static int tps65912_spi_read(struct tps65912 *tps65912, u8 addr,
 	return ret;
 }
 
-static int __devinit tps65912_spi_probe(struct spi_device *spi)
+static int tps65912_spi_probe(struct spi_device *spi)
 {
 	struct tps65912 *tps65912;
 
@@ -99,7 +99,7 @@ static int __devinit tps65912_spi_probe(struct spi_device *spi)
 	return tps65912_device_init(tps65912);
 }
 
-static int __devexit tps65912_spi_remove(struct spi_device *spi)
+static int tps65912_spi_remove(struct spi_device *spi)
 {
 	struct tps65912 *tps65912 = spi_get_drvdata(spi);
 
@@ -114,7 +114,7 @@ static struct spi_driver tps65912_spi_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe	= tps65912_spi_probe,
-	.remove = __devexit_p(tps65912_spi_remove),
+	.remove = tps65912_spi_remove,
 };
 
 static int __init tps65912_spi_init(void)
diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c
new file mode 100644
index 0000000..f64005e
--- /dev/null
+++ b/drivers/mfd/tps80031.c
@@ -0,0 +1,573 @@
+/*
+ * tps80031.c -- TI TPS80031/TPS80032 mfd core driver.
+ *
+ * MFD core driver for TI TPS80031/TPS80032 Fully Integrated
+ * Power Management with Power Path and Battery Charger
+ *
+ * Copyright (c) 2012, 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/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps80031.h>
+#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+static struct resource tps80031_rtc_resources[] = {
+	{
+		.start = TPS80031_INT_RTC_ALARM,
+		.end = TPS80031_INT_RTC_ALARM,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+/* TPS80031 sub mfd devices */
+static struct mfd_cell tps80031_cell[] = {
+	{
+		.name = "tps80031-pmic",
+	},
+	{
+		.name = "tps80031-clock",
+	},
+	{
+		.name = "tps80031-rtc",
+		.num_resources = ARRAY_SIZE(tps80031_rtc_resources),
+		.resources = tps80031_rtc_resources,
+	},
+	{
+		.name = "tps80031-gpadc",
+	},
+	{
+		.name = "tps80031-fuel-gauge",
+	},
+	{
+		.name = "tps80031-charger",
+	},
+};
+
+static int tps80031_slave_address[TPS80031_NUM_SLAVES] = {
+	TPS80031_I2C_ID0_ADDR,
+	TPS80031_I2C_ID1_ADDR,
+	TPS80031_I2C_ID2_ADDR,
+	TPS80031_I2C_ID3_ADDR,
+};
+
+struct tps80031_pupd_data {
+	u8	reg;
+	u8	pullup_bit;
+	u8	pulldown_bit;
+};
+
+#define TPS80031_IRQ(_reg, _mask)			\
+	{							\
+		.reg_offset = (TPS80031_INT_MSK_LINE_##_reg) -	\
+				TPS80031_INT_MSK_LINE_A,	\
+		.mask = BIT(_mask),				\
+	}
+
+static const struct regmap_irq tps80031_main_irqs[] = {
+	[TPS80031_INT_PWRON]		= TPS80031_IRQ(A, 0),
+	[TPS80031_INT_RPWRON]		= TPS80031_IRQ(A, 1),
+	[TPS80031_INT_SYS_VLOW]		= TPS80031_IRQ(A, 2),
+	[TPS80031_INT_RTC_ALARM]	= TPS80031_IRQ(A, 3),
+	[TPS80031_INT_RTC_PERIOD]	= TPS80031_IRQ(A, 4),
+	[TPS80031_INT_HOT_DIE]		= TPS80031_IRQ(A, 5),
+	[TPS80031_INT_VXX_SHORT]	= TPS80031_IRQ(A, 6),
+	[TPS80031_INT_SPDURATION]	= TPS80031_IRQ(A, 7),
+	[TPS80031_INT_WATCHDOG]		= TPS80031_IRQ(B, 0),
+	[TPS80031_INT_BAT]		= TPS80031_IRQ(B, 1),
+	[TPS80031_INT_SIM]		= TPS80031_IRQ(B, 2),
+	[TPS80031_INT_MMC]		= TPS80031_IRQ(B, 3),
+	[TPS80031_INT_RES]		= TPS80031_IRQ(B, 4),
+	[TPS80031_INT_GPADC_RT]		= TPS80031_IRQ(B, 5),
+	[TPS80031_INT_GPADC_SW2_EOC]	= TPS80031_IRQ(B, 6),
+	[TPS80031_INT_CC_AUTOCAL]	= TPS80031_IRQ(B, 7),
+	[TPS80031_INT_ID_WKUP]		= TPS80031_IRQ(C, 0),
+	[TPS80031_INT_VBUSS_WKUP]	= TPS80031_IRQ(C, 1),
+	[TPS80031_INT_ID]		= TPS80031_IRQ(C, 2),
+	[TPS80031_INT_VBUS]		= TPS80031_IRQ(C, 3),
+	[TPS80031_INT_CHRG_CTRL]	= TPS80031_IRQ(C, 4),
+	[TPS80031_INT_EXT_CHRG]		= TPS80031_IRQ(C, 5),
+	[TPS80031_INT_INT_CHRG]		= TPS80031_IRQ(C, 6),
+	[TPS80031_INT_RES2]		= TPS80031_IRQ(C, 7),
+};
+
+static struct regmap_irq_chip tps80031_irq_chip = {
+	.name = "tps80031",
+	.irqs = tps80031_main_irqs,
+	.num_irqs = ARRAY_SIZE(tps80031_main_irqs),
+	.num_regs = 3,
+	.status_base = TPS80031_INT_STS_A,
+	.mask_base = TPS80031_INT_MSK_LINE_A,
+};
+
+#define PUPD_DATA(_reg, _pulldown_bit, _pullup_bit)	\
+	{						\
+		.reg = TPS80031_CFG_INPUT_PUPD##_reg,	\
+		.pulldown_bit = _pulldown_bit,		\
+		.pullup_bit = _pullup_bit,		\
+	}
+
+static const struct tps80031_pupd_data tps80031_pupds[] = {
+	[TPS80031_PREQ1]		= PUPD_DATA(1, BIT(0),	BIT(1)),
+	[TPS80031_PREQ2A]		= PUPD_DATA(1, BIT(2),	BIT(3)),
+	[TPS80031_PREQ2B]		= PUPD_DATA(1, BIT(4),	BIT(5)),
+	[TPS80031_PREQ2C]		= PUPD_DATA(1, BIT(6),	BIT(7)),
+	[TPS80031_PREQ3]		= PUPD_DATA(2, BIT(0),	BIT(1)),
+	[TPS80031_NRES_WARM]		= PUPD_DATA(2, 0,	BIT(2)),
+	[TPS80031_PWM_FORCE]		= PUPD_DATA(2, BIT(5),	0),
+	[TPS80031_CHRG_EXT_CHRG_STATZ]	= PUPD_DATA(2, 0,	BIT(6)),
+	[TPS80031_SIM]			= PUPD_DATA(3, BIT(0),	BIT(1)),
+	[TPS80031_MMC]			= PUPD_DATA(3, BIT(2),	BIT(3)),
+	[TPS80031_GPADC_START]		= PUPD_DATA(3, BIT(4),	0),
+	[TPS80031_DVSI2C_SCL]		= PUPD_DATA(4, 0,	BIT(0)),
+	[TPS80031_DVSI2C_SDA]		= PUPD_DATA(4, 0,	BIT(1)),
+	[TPS80031_CTLI2C_SCL]		= PUPD_DATA(4, 0,	BIT(2)),
+	[TPS80031_CTLI2C_SDA]		= PUPD_DATA(4, 0,	BIT(3)),
+};
+static struct tps80031 *tps80031_power_off_dev;
+
+int tps80031_ext_power_req_config(struct device *dev,
+		unsigned long ext_ctrl_flag, int preq_bit,
+		int state_reg_add, int trans_reg_add)
+{
+	u8 res_ass_reg = 0;
+	int preq_mask_bit = 0;
+	int ret;
+
+	if (!(ext_ctrl_flag & TPS80031_EXT_PWR_REQ))
+		return 0;
+
+	if (ext_ctrl_flag & TPS80031_PWR_REQ_INPUT_PREQ1) {
+		res_ass_reg = TPS80031_PREQ1_RES_ASS_A + (preq_bit >> 3);
+		preq_mask_bit = 5;
+	} else if (ext_ctrl_flag & TPS80031_PWR_REQ_INPUT_PREQ2) {
+		res_ass_reg = TPS80031_PREQ2_RES_ASS_A + (preq_bit >> 3);
+		preq_mask_bit = 6;
+	} else if (ext_ctrl_flag & TPS80031_PWR_REQ_INPUT_PREQ3) {
+		res_ass_reg = TPS80031_PREQ3_RES_ASS_A + (preq_bit >> 3);
+		preq_mask_bit = 7;
+	}
+
+	/* Configure REQ_ASS registers */
+	ret = tps80031_set_bits(dev, TPS80031_SLAVE_ID1, res_ass_reg,
+					BIT(preq_bit & 0x7));
+	if (ret < 0) {
+		dev_err(dev, "reg 0x%02x setbit failed, err = %d\n",
+				res_ass_reg, ret);
+		return ret;
+	}
+
+	/* Unmask the PREQ */
+	ret = tps80031_clr_bits(dev, TPS80031_SLAVE_ID1,
+			TPS80031_PHOENIX_MSK_TRANSITION, BIT(preq_mask_bit));
+	if (ret < 0) {
+		dev_err(dev, "reg 0x%02x clrbit failed, err = %d\n",
+			TPS80031_PHOENIX_MSK_TRANSITION, ret);
+		return ret;
+	}
+
+	/* Switch regulator control to resource now */
+	if (ext_ctrl_flag & (TPS80031_PWR_REQ_INPUT_PREQ2 |
+					TPS80031_PWR_REQ_INPUT_PREQ3)) {
+		ret = tps80031_update(dev, TPS80031_SLAVE_ID1, state_reg_add,
+						0x0, TPS80031_STATE_MASK);
+		if (ret < 0)
+			dev_err(dev, "reg 0x%02x update failed, err = %d\n",
+				state_reg_add, ret);
+	} else {
+		ret = tps80031_update(dev, TPS80031_SLAVE_ID1, trans_reg_add,
+				TPS80031_TRANS_SLEEP_OFF,
+				TPS80031_TRANS_SLEEP_MASK);
+		if (ret < 0)
+			dev_err(dev, "reg 0x%02x update failed, err = %d\n",
+				trans_reg_add, ret);
+	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tps80031_ext_power_req_config);
+
+static void tps80031_power_off(void)
+{
+	dev_info(tps80031_power_off_dev->dev, "switching off PMU\n");
+	tps80031_write(tps80031_power_off_dev->dev, TPS80031_SLAVE_ID1,
+				TPS80031_PHOENIX_DEV_ON, TPS80031_DEVOFF);
+}
+
+static void tps80031_pupd_init(struct tps80031 *tps80031,
+			       struct tps80031_platform_data *pdata)
+{
+	struct tps80031_pupd_init_data *pupd_init_data = pdata->pupd_init_data;
+	int data_size = pdata->pupd_init_data_size;
+	int i;
+
+	for (i = 0; i < data_size; ++i) {
+		struct tps80031_pupd_init_data *pupd_init = &pupd_init_data[i];
+		const struct tps80031_pupd_data *pupd =
+			&tps80031_pupds[pupd_init->input_pin];
+		u8 update_value = 0;
+		u8 update_mask = pupd->pulldown_bit | pupd->pullup_bit;
+
+		if (pupd_init->setting == TPS80031_PUPD_PULLDOWN)
+			update_value = pupd->pulldown_bit;
+		else if (pupd_init->setting == TPS80031_PUPD_PULLUP)
+			update_value = pupd->pullup_bit;
+
+		tps80031_update(tps80031->dev, TPS80031_SLAVE_ID1, pupd->reg,
+				update_value, update_mask);
+	}
+}
+
+static int tps80031_init_ext_control(struct tps80031 *tps80031,
+			struct tps80031_platform_data *pdata)
+{
+	struct device *dev = tps80031->dev;
+	int ret;
+	int i;
+
+	/* Clear all external control for this rail */
+	for (i = 0; i < 9; ++i) {
+		ret = tps80031_write(dev, TPS80031_SLAVE_ID1,
+				TPS80031_PREQ1_RES_ASS_A + i, 0);
+		if (ret < 0) {
+			dev_err(dev, "reg 0x%02x write failed, err = %d\n",
+				TPS80031_PREQ1_RES_ASS_A + i, ret);
+			return ret;
+		}
+	}
+
+	/* Mask the PREQ */
+	ret = tps80031_set_bits(dev, TPS80031_SLAVE_ID1,
+			TPS80031_PHOENIX_MSK_TRANSITION, 0x7 << 5);
+	if (ret < 0) {
+		dev_err(dev, "reg 0x%02x set_bits failed, err = %d\n",
+			TPS80031_PHOENIX_MSK_TRANSITION, ret);
+		return ret;
+	}
+	return ret;
+}
+
+static int __devinit tps80031_irq_init(struct tps80031 *tps80031, int irq,
+				int irq_base)
+{
+	struct device *dev = tps80031->dev;
+	int i, ret;
+
+	/*
+	 * The MASK register used for updating status register when
+	 * interrupt occurs and LINE register used to pass the status
+	 * to actual interrupt line.  As per datasheet:
+	 * When INT_MSK_LINE [i] is set to 1, the associated interrupt
+	 * number i is INT line masked, which means that no interrupt is
+	 * generated on the INT line.
+	 * When INT_MSK_LINE [i] is set to 0, the associated interrupt
+	 * number i is  line enabled: An interrupt is generated on the
+	 * INT line.
+	 * In any case, the INT_STS [i] status bit may or may not be updated,
+	 * only linked to the INT_MSK_STS [i] configuration register bit.
+	 *
+	 * When INT_MSK_STS [i] is set to 1, the associated interrupt number
+	 * i is status masked, which means that no interrupt is stored in
+	 * the INT_STS[i] status bit. Note that no interrupt number i is
+	 * generated on the INT line, even if the INT_MSK_LINE [i] register
+	 * bit is set to 0.
+	 * When INT_MSK_STS [i] is set to 0, the associated interrupt number i
+	 * is status enabled: An interrupt status is updated in the INT_STS [i]
+	 * register. The interrupt may or may not be generated on the INT line,
+	 * depending on the INT_MSK_LINE [i] configuration register bit.
+	 */
+	for (i = 0; i < 3; i++)
+		tps80031_write(dev, TPS80031_SLAVE_ID2,
+				TPS80031_INT_MSK_STS_A + i, 0x00);
+
+	ret = regmap_add_irq_chip(tps80031->regmap[TPS80031_SLAVE_ID2], irq,
+			IRQF_ONESHOT, irq_base,
+			&tps80031_irq_chip, &tps80031->irq_data);
+	if (ret < 0) {
+		dev_err(dev, "add irq failed, err = %d\n", ret);
+		return ret;
+	}
+	return ret;
+}
+
+static bool rd_wr_reg_id0(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TPS80031_SMPS1_CFG_FORCE ... TPS80031_SMPS2_CFG_VOLTAGE:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool rd_wr_reg_id1(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TPS80031_SECONDS_REG ... TPS80031_RTC_RESET_STATUS_REG:
+	case TPS80031_VALIDITY0 ... TPS80031_VALIDITY7:
+	case TPS80031_PHOENIX_START_CONDITION ... TPS80031_KEY_PRESS_DUR_CFG:
+	case TPS80031_SMPS4_CFG_TRANS ... TPS80031_SMPS3_CFG_VOLTAGE:
+	case TPS80031_BROADCAST_ADDR_ALL ... TPS80031_BROADCAST_ADDR_CLK_RST:
+	case TPS80031_VANA_CFG_TRANS ... TPS80031_LDO7_CFG_VOLTAGE:
+	case TPS80031_REGEN1_CFG_TRANS ... TPS80031_TMP_CFG_STATE:
+	case TPS80031_PREQ1_RES_ASS_A ... TPS80031_PREQ3_RES_ASS_C:
+	case TPS80031_SMPS_OFFSET ... TPS80031_BATDEBOUNCING:
+	case TPS80031_CFG_INPUT_PUPD1 ... TPS80031_CFG_SMPS_PD:
+	case TPS80031_BACKUP_REG:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool is_volatile_reg_id1(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TPS80031_SMPS4_CFG_TRANS ... TPS80031_SMPS3_CFG_VOLTAGE:
+	case TPS80031_VANA_CFG_TRANS ... TPS80031_LDO7_CFG_VOLTAGE:
+	case TPS80031_REGEN1_CFG_TRANS ... TPS80031_TMP_CFG_STATE:
+	case TPS80031_PREQ1_RES_ASS_A ... TPS80031_PREQ3_RES_ASS_C:
+	case TPS80031_SMPS_OFFSET ... TPS80031_BATDEBOUNCING:
+	case TPS80031_CFG_INPUT_PUPD1 ... TPS80031_CFG_SMPS_PD:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool rd_wr_reg_id2(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TPS80031_USB_VENDOR_ID_LSB ... TPS80031_USB_OTG_REVISION:
+	case TPS80031_GPADC_CTRL ... TPS80031_CTRL_P1:
+	case TPS80031_RTCH0_LSB ... TPS80031_GPCH0_MSB:
+	case TPS80031_TOGGLE1 ... TPS80031_VIBMODE:
+	case TPS80031_PWM1ON ... TPS80031_PWM2OFF:
+	case TPS80031_FG_REG_00 ... TPS80031_FG_REG_11:
+	case TPS80031_INT_STS_A ... TPS80031_INT_MSK_STS_C:
+	case TPS80031_CONTROLLER_CTRL2 ... TPS80031_LED_PWM_CTRL2:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool rd_wr_reg_id3(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TPS80031_GPADC_TRIM0 ... TPS80031_GPADC_TRIM18:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_config tps80031_regmap_configs[] = {
+	{
+		.reg_bits = 8,
+		.val_bits = 8,
+		.writeable_reg = rd_wr_reg_id0,
+		.readable_reg = rd_wr_reg_id0,
+		.max_register = TPS80031_MAX_REGISTER,
+	},
+	{
+		.reg_bits = 8,
+		.val_bits = 8,
+		.writeable_reg = rd_wr_reg_id1,
+		.readable_reg = rd_wr_reg_id1,
+		.volatile_reg = is_volatile_reg_id1,
+		.max_register = TPS80031_MAX_REGISTER,
+	},
+	{
+		.reg_bits = 8,
+		.val_bits = 8,
+		.writeable_reg = rd_wr_reg_id2,
+		.readable_reg = rd_wr_reg_id2,
+		.max_register = TPS80031_MAX_REGISTER,
+	},
+	{
+		.reg_bits = 8,
+		.val_bits = 8,
+		.writeable_reg = rd_wr_reg_id3,
+		.readable_reg = rd_wr_reg_id3,
+		.max_register = TPS80031_MAX_REGISTER,
+	},
+};
+
+static int __devinit tps80031_probe(struct i2c_client *client,
+					const struct i2c_device_id *id)
+{
+	struct tps80031_platform_data *pdata = client->dev.platform_data;
+	struct tps80031 *tps80031;
+	int ret;
+	uint8_t es_version;
+	uint8_t ep_ver;
+	int i;
+
+	if (!pdata) {
+		dev_err(&client->dev, "tps80031 requires platform data\n");
+		return -EINVAL;
+	}
+
+	tps80031 = devm_kzalloc(&client->dev, sizeof(*tps80031), GFP_KERNEL);
+	if (!tps80031) {
+		dev_err(&client->dev, "Malloc failed for tps80031\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < TPS80031_NUM_SLAVES; i++) {
+		if (tps80031_slave_address[i] == client->addr)
+			tps80031->clients[i] = client;
+		else
+			tps80031->clients[i] = i2c_new_dummy(client->adapter,
+						tps80031_slave_address[i]);
+		if (!tps80031->clients[i]) {
+			dev_err(&client->dev, "can't attach client %d\n", i);
+			ret = -ENOMEM;
+			goto fail_client_reg;
+		}
+
+		i2c_set_clientdata(tps80031->clients[i], tps80031);
+		tps80031->regmap[i] = devm_regmap_init_i2c(tps80031->clients[i],
+					&tps80031_regmap_configs[i]);
+		if (IS_ERR(tps80031->regmap[i])) {
+			ret = PTR_ERR(tps80031->regmap[i]);
+			dev_err(&client->dev,
+				"regmap %d init failed, err %d\n", i, ret);
+			goto fail_client_reg;
+		}
+	}
+
+	ret = tps80031_read(&client->dev, TPS80031_SLAVE_ID3,
+			TPS80031_JTAGVERNUM, &es_version);
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"Silicon version number read failed: %d\n", ret);
+		goto fail_client_reg;
+	}
+
+	ret = tps80031_read(&client->dev, TPS80031_SLAVE_ID3,
+			TPS80031_EPROM_REV, &ep_ver);
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"Silicon eeprom version read failed: %d\n", ret);
+		goto fail_client_reg;
+	}
+
+	dev_info(&client->dev, "ES version 0x%02x and EPROM version 0x%02x\n",
+					es_version, ep_ver);
+	tps80031->es_version = es_version;
+	tps80031->dev = &client->dev;
+	i2c_set_clientdata(client, tps80031);
+	tps80031->chip_info = id->driver_data;
+
+	ret = tps80031_irq_init(tps80031, client->irq, pdata->irq_base);
+	if (ret) {
+		dev_err(&client->dev, "IRQ init failed: %d\n", ret);
+		goto fail_client_reg;
+	}
+
+	tps80031_pupd_init(tps80031, pdata);
+
+	tps80031_init_ext_control(tps80031, pdata);
+
+	ret = mfd_add_devices(tps80031->dev, -1,
+			tps80031_cell, ARRAY_SIZE(tps80031_cell),
+			NULL, 0,
+			regmap_irq_get_domain(tps80031->irq_data));
+	if (ret < 0) {
+		dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret);
+		goto fail_mfd_add;
+	}
+
+	if (pdata->use_power_off && !pm_power_off) {
+		tps80031_power_off_dev = tps80031;
+		pm_power_off = tps80031_power_off;
+	}
+	return 0;
+
+fail_mfd_add:
+	regmap_del_irq_chip(client->irq, tps80031->irq_data);
+
+fail_client_reg:
+	for (i = 0; i < TPS80031_NUM_SLAVES; i++) {
+		if (tps80031->clients[i]  && (tps80031->clients[i] != client))
+			i2c_unregister_device(tps80031->clients[i]);
+	}
+	return ret;
+}
+
+static int __devexit tps80031_remove(struct i2c_client *client)
+{
+	struct tps80031 *tps80031 = i2c_get_clientdata(client);
+	int i;
+
+	if (tps80031_power_off_dev == tps80031) {
+		tps80031_power_off_dev = NULL;
+		pm_power_off = NULL;
+	}
+
+	mfd_remove_devices(tps80031->dev);
+
+	regmap_del_irq_chip(client->irq, tps80031->irq_data);
+
+	for (i = 0; i < TPS80031_NUM_SLAVES; i++) {
+		if (tps80031->clients[i] != client)
+			i2c_unregister_device(tps80031->clients[i]);
+	}
+	return 0;
+}
+
+static const struct i2c_device_id tps80031_id_table[] = {
+	{ "tps80031", TPS80031 },
+	{ "tps80032", TPS80032 },
+};
+MODULE_DEVICE_TABLE(i2c, tps80031_id_table);
+
+static struct i2c_driver tps80031_driver = {
+	.driver	= {
+		.name	= "tps80031",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= tps80031_probe,
+	.remove		= __devexit_p(tps80031_remove),
+	.id_table	= tps80031_id_table,
+};
+
+static int __init tps80031_init(void)
+{
+	return i2c_add_driver(&tps80031_driver);
+}
+subsys_initcall(tps80031_init);
+
+static void __exit tps80031_exit(void)
+{
+	i2c_del_driver(&tps80031_driver);
+}
+module_exit(tps80031_exit);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("TPS80031 core driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 4ae6423..4f3baad 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -32,6 +32,7 @@
 #include <linux/mutex.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/device.h>
@@ -65,9 +66,6 @@
 
 /* Triton Core internal information (BEGIN) */
 
-/* Last - for index max*/
-#define TWL4030_MODULE_LAST		TWL4030_MODULE_SECURED_REG
-
 #define TWL_NUM_SLAVES		4
 
 #define SUB_CHIP_ID0 0
@@ -171,13 +169,7 @@ EXPORT_SYMBOL(twl_rev);
 /* Structure for each TWL4030/TWL6030 Slave */
 struct twl_client {
 	struct i2c_client *client;
-	u8 address;
-
-	/* max numb of i2c_msg required is for read =2 */
-	struct i2c_msg xfer_msg[2];
-
-	/* To lock access to xfer_msg */
-	struct mutex xfer_lock;
+	struct regmap *regmap;
 };
 
 static struct twl_client twl_modules[TWL_NUM_SLAVES];
@@ -189,7 +181,7 @@ struct twl_mapping {
 };
 static struct twl_mapping *twl_map;
 
-static struct twl_mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
+static struct twl_mapping twl4030_map[] = {
 	/*
 	 * NOTE:  don't change this table without updating the
 	 * <linux/i2c/twl.h> defines for TWL4030_MODULE_*
@@ -197,34 +189,62 @@ static struct twl_mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
 	 */
 
 	{ 0, TWL4030_BASEADD_USB },
-
 	{ 1, TWL4030_BASEADD_AUDIO_VOICE },
 	{ 1, TWL4030_BASEADD_GPIO },
 	{ 1, TWL4030_BASEADD_INTBR },
 	{ 1, TWL4030_BASEADD_PIH },
-	{ 1, TWL4030_BASEADD_TEST },
 
+	{ 1, TWL4030_BASEADD_TEST },
 	{ 2, TWL4030_BASEADD_KEYPAD },
 	{ 2, TWL4030_BASEADD_MADC },
 	{ 2, TWL4030_BASEADD_INTERRUPTS },
 	{ 2, TWL4030_BASEADD_LED },
+
 	{ 2, TWL4030_BASEADD_MAIN_CHARGE },
 	{ 2, TWL4030_BASEADD_PRECHARGE },
 	{ 2, TWL4030_BASEADD_PWM0 },
 	{ 2, TWL4030_BASEADD_PWM1 },
 	{ 2, TWL4030_BASEADD_PWMA },
+
 	{ 2, TWL4030_BASEADD_PWMB },
 	{ 2, TWL5031_BASEADD_ACCESSORY },
 	{ 2, TWL5031_BASEADD_INTERRUPTS },
-
 	{ 3, TWL4030_BASEADD_BACKUP },
 	{ 3, TWL4030_BASEADD_INT },
+
 	{ 3, TWL4030_BASEADD_PM_MASTER },
 	{ 3, TWL4030_BASEADD_PM_RECEIVER },
 	{ 3, TWL4030_BASEADD_RTC },
 	{ 3, TWL4030_BASEADD_SECURED_REG },
 };
 
+static struct regmap_config twl4030_regmap_config[4] = {
+	{
+		/* Address 0x48 */
+		.reg_bits = 8,
+		.val_bits = 8,
+		.max_register = 0xff,
+	},
+	{
+		/* Address 0x49 */
+		.reg_bits = 8,
+		.val_bits = 8,
+		.max_register = 0xff,
+	},
+	{
+		/* Address 0x4a */
+		.reg_bits = 8,
+		.val_bits = 8,
+		.max_register = 0xff,
+	},
+	{
+		/* Address 0x4b */
+		.reg_bits = 8,
+		.val_bits = 8,
+		.max_register = 0xff,
+	},
+};
+
 static struct twl_mapping twl6030_map[] = {
 	/*
 	 * NOTE:  don't change this table without updating the
@@ -254,14 +274,35 @@ static struct twl_mapping twl6030_map[] = {
 	{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
 	{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
 	{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
+
 	{ SUB_CHIP_ID0, TWL6030_BASEADD_PM_MASTER },
 	{ SUB_CHIP_ID0, TWL6030_BASEADD_PM_SLAVE_MISC },
-
 	{ SUB_CHIP_ID0, TWL6030_BASEADD_RTC },
 	{ SUB_CHIP_ID0, TWL6030_BASEADD_MEM },
 	{ SUB_CHIP_ID1, TWL6025_BASEADD_CHARGER },
 };
 
+static struct regmap_config twl6030_regmap_config[3] = {
+	{
+		/* Address 0x48 */
+		.reg_bits = 8,
+		.val_bits = 8,
+		.max_register = 0xff,
+	},
+	{
+		/* Address 0x49 */
+		.reg_bits = 8,
+		.val_bits = 8,
+		.max_register = 0xff,
+	},
+	{
+		/* Address 0x4a */
+		.reg_bits = 8,
+		.val_bits = 8,
+		.max_register = 0xff,
+	},
+};
+
 /*----------------------------------------------------------------------*/
 
 /* Exported Functions */
@@ -283,9 +324,8 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
 	int ret;
 	int sid;
 	struct twl_client *twl;
-	struct i2c_msg *msg;
 
-	if (unlikely(mod_no > TWL_MODULE_LAST)) {
+	if (unlikely(mod_no >= TWL_MODULE_LAST)) {
 		pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
 		return -EPERM;
 	}
@@ -301,32 +341,14 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
 	}
 	twl = &twl_modules[sid];
 
-	mutex_lock(&twl->xfer_lock);
-	/*
-	 * [MSG1]: fill the register address data
-	 * fill the data Tx buffer
-	 */
-	msg = &twl->xfer_msg[0];
-	msg->addr = twl->address;
-	msg->len = num_bytes + 1;
-	msg->flags = 0;
-	msg->buf = value;
-	/* over write the first byte of buffer with the register address */
-	*value = twl_map[mod_no].base + reg;
-	ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 1);
-	mutex_unlock(&twl->xfer_lock);
-
-	/* i2c_transfer returns number of messages transferred */
-	if (ret != 1) {
-		pr_err("%s: i2c_write failed to transfer all messages\n",
-			DRIVER_NAME);
-		if (ret < 0)
-			return ret;
-		else
-			return -EIO;
-	} else {
-		return 0;
-	}
+	ret = regmap_bulk_write(twl->regmap, twl_map[mod_no].base + reg,
+				value, num_bytes);
+
+	if (ret)
+		pr_err("%s: Write failed (mod %d, reg 0x%02x count %d)\n",
+		       DRIVER_NAME, mod_no, reg, num_bytes);
+
+	return ret;
 }
 EXPORT_SYMBOL(twl_i2c_write);
 
@@ -342,12 +364,10 @@ EXPORT_SYMBOL(twl_i2c_write);
 int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
 {
 	int ret;
-	u8 val;
 	int sid;
 	struct twl_client *twl;
-	struct i2c_msg *msg;
 
-	if (unlikely(mod_no > TWL_MODULE_LAST)) {
+	if (unlikely(mod_no >= TWL_MODULE_LAST)) {
 		pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
 		return -EPERM;
 	}
@@ -363,34 +383,14 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
 	}
 	twl = &twl_modules[sid];
 
-	mutex_lock(&twl->xfer_lock);
-	/* [MSG1] fill the register address data */
-	msg = &twl->xfer_msg[0];
-	msg->addr = twl->address;
-	msg->len = 1;
-	msg->flags = 0;	/* Read the register value */
-	val = twl_map[mod_no].base + reg;
-	msg->buf = &val;
-	/* [MSG2] fill the data rx buffer */
-	msg = &twl->xfer_msg[1];
-	msg->addr = twl->address;
-	msg->flags = I2C_M_RD;	/* Read the register value */
-	msg->len = num_bytes;	/* only n bytes */
-	msg->buf = value;
-	ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 2);
-	mutex_unlock(&twl->xfer_lock);
-
-	/* i2c_transfer returns number of messages transferred */
-	if (ret != 2) {
-		pr_err("%s: i2c_read failed to transfer all messages\n",
-			DRIVER_NAME);
-		if (ret < 0)
-			return ret;
-		else
-			return -EIO;
-	} else {
-		return 0;
-	}
+	ret = regmap_bulk_read(twl->regmap, twl_map[mod_no].base + reg,
+			       value, num_bytes);
+
+	if (ret)
+		pr_err("%s: Read failed (mod %d, reg 0x%02x count %d)\n",
+		       DRIVER_NAME, mod_no, reg, num_bytes);
+
+	return ret;
 }
 EXPORT_SYMBOL(twl_i2c_read);
 
@@ -404,12 +404,7 @@ EXPORT_SYMBOL(twl_i2c_read);
  */
 int twl_i2c_write_u8(u8 mod_no, u8 value, u8 reg)
 {
-
-	/* 2 bytes offset 1 contains the data offset 0 is used by i2c_write */
-	u8 temp_buffer[2] = { 0 };
-	/* offset 1 contains the data */
-	temp_buffer[1] = value;
-	return twl_i2c_write(mod_no, temp_buffer, reg, 1);
+	return twl_i2c_write(mod_no, &value, reg, 1);
 }
 EXPORT_SYMBOL(twl_i2c_write_u8);
 
@@ -646,8 +641,9 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 			return PTR_ERR(child);
 	}
 
-	if (IS_ENABLED(CONFIG_TWL4030_MADC) && pdata->madc) {
-		child = add_child(2, "twl4030_madc",
+	if (IS_ENABLED(CONFIG_TWL4030_MADC) && pdata->madc &&
+	    twl_class_is_4030()) {
+		child = add_child(SUB_CHIP_ID2, "twl4030_madc",
 				pdata->madc, sizeof(*pdata->madc),
 				true, irq_base + MADC_INTR_OFFSET, 0);
 		if (IS_ERR(child))
@@ -663,15 +659,21 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 		 * HW security concerns, and "least privilege".
 		 */
 		sub_chip_id = twl_map[TWL_MODULE_RTC].sid;
-		child = add_child(sub_chip_id, "twl_rtc",
-				NULL, 0,
+		child = add_child(sub_chip_id, "twl_rtc", NULL, 0,
 				true, irq_base + RTC_INTR_OFFSET, 0);
 		if (IS_ERR(child))
 			return PTR_ERR(child);
 	}
 
-	if (IS_ENABLED(CONFIG_PWM_TWL6030) && twl_class_is_6030()) {
-		child = add_child(TWL6030_MODULE_ID1, "twl6030-pwm", NULL, 0,
+	if (IS_ENABLED(CONFIG_PWM_TWL)) {
+		child = add_child(SUB_CHIP_ID1, "twl-pwm", NULL, 0,
+				  false, 0, 0);
+		if (IS_ERR(child))
+			return PTR_ERR(child);
+	}
+
+	if (IS_ENABLED(CONFIG_PWM_TWL_LED)) {
+		child = add_child(SUB_CHIP_ID1, "twl-pwmled", NULL, 0,
 				  false, 0, 0);
 		if (IS_ERR(child))
 			return PTR_ERR(child);
@@ -723,9 +725,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 
 		}
 
-		child = add_child(0, "twl4030_usb",
-				pdata->usb, sizeof(*pdata->usb),
-				true,
+		child = add_child(SUB_CHIP_ID0, "twl4030_usb",
+				pdata->usb, sizeof(*pdata->usb), true,
 				/* irq0 = USB_PRES, irq1 = USB */
 				irq_base + USB_PRES_INTR_OFFSET,
 				irq_base + USB_INTR_OFFSET);
@@ -773,9 +774,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 
 		pdata->usb->features = features;
 
-		child = add_child(0, "twl6030_usb",
-			pdata->usb, sizeof(*pdata->usb),
-			true,
+		child = add_child(SUB_CHIP_ID0, "twl6030_usb",
+			pdata->usb, sizeof(*pdata->usb), true,
 			/* irq1 = VBUS_PRES, irq0 = USB ID */
 			irq_base + USBOTG_INTR_OFFSET,
 			irq_base + USB_PRES_INTR_OFFSET);
@@ -799,22 +799,22 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 	}
 
 	if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) {
-		child = add_child(0, "twl4030_wdt", NULL, 0, false, 0, 0);
+		child = add_child(SUB_CHIP_ID3, "twl4030_wdt", NULL, 0,
+				  false, 0, 0);
 		if (IS_ERR(child))
 			return PTR_ERR(child);
 	}
 
 	if (IS_ENABLED(CONFIG_INPUT_TWL4030_PWRBUTTON) && twl_class_is_4030()) {
-		child = add_child(1, "twl4030_pwrbutton",
-				NULL, 0, true, irq_base + 8 + 0, 0);
+		child = add_child(SUB_CHIP_ID3, "twl4030_pwrbutton", NULL, 0,
+				  true, irq_base + 8 + 0, 0);
 		if (IS_ERR(child))
 			return PTR_ERR(child);
 	}
 
 	if (IS_ENABLED(CONFIG_MFD_TWL4030_AUDIO) && pdata->audio &&
 	    twl_class_is_4030()) {
-		sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
-		child = add_child(sub_chip_id, "twl4030-audio",
+		child = add_child(SUB_CHIP_ID1, "twl4030-audio",
 				pdata->audio, sizeof(*pdata->audio),
 				false, 0, 0);
 		if (IS_ERR(child))
@@ -1054,7 +1054,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 
 	if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci &&
 			!(features & (TPS_SUBSET | TWL5031))) {
-		child = add_child(3, "twl4030_bci",
+		child = add_child(SUB_CHIP_ID3, "twl4030_bci",
 				pdata->bci, sizeof(*pdata->bci), false,
 				/* irq0 = CHG_PRES, irq1 = BCI */
 				irq_base + BCI_PRES_INTR_OFFSET,
@@ -1077,8 +1077,8 @@ static inline int __init protect_pm_master(void)
 {
 	int e = 0;
 
-	e = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0,
-			TWL4030_PM_MASTER_PROTECT_KEY);
+	e = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
+			     TWL4030_PM_MASTER_PROTECT_KEY);
 	return e;
 }
 
@@ -1086,12 +1086,10 @@ static inline int __init unprotect_pm_master(void)
 {
 	int e = 0;
 
-	e |= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
-			TWL4030_PM_MASTER_KEY_CFG1,
-			TWL4030_PM_MASTER_PROTECT_KEY);
-	e |= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
-			TWL4030_PM_MASTER_KEY_CFG2,
-			TWL4030_PM_MASTER_PROTECT_KEY);
+	e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
+			      TWL4030_PM_MASTER_PROTECT_KEY);
+	e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
+			      TWL4030_PM_MASTER_PROTECT_KEY);
 
 	return e;
 }
@@ -1170,12 +1168,13 @@ static int twl_remove(struct i2c_client *client)
 }
 
 /* NOTE: This driver only handles a single twl4030/tps659x0 chip */
-static int __devinit
+static int
 twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct twl4030_platform_data	*pdata = client->dev.platform_data;
 	struct device_node		*node = client->dev.of_node;
 	struct platform_device		*pdev;
+	struct regmap_config		*twl_regmap_config;
 	int				irq_base = 0;
 	int				status;
 	unsigned			i, num_slaves;
@@ -1229,22 +1228,23 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	if ((id->driver_data) & TWL6030_CLASS) {
 		twl_id = TWL6030_CLASS_ID;
 		twl_map = &twl6030_map[0];
+		twl_regmap_config = twl6030_regmap_config;
 		num_slaves = TWL_NUM_SLAVES - 1;
 	} else {
 		twl_id = TWL4030_CLASS_ID;
 		twl_map = &twl4030_map[0];
+		twl_regmap_config = twl4030_regmap_config;
 		num_slaves = TWL_NUM_SLAVES;
 	}
 
 	for (i = 0; i < num_slaves; i++) {
 		struct twl_client *twl = &twl_modules[i];
 
-		twl->address = client->addr + i;
 		if (i == 0) {
 			twl->client = client;
 		} else {
 			twl->client = i2c_new_dummy(client->adapter,
-					twl->address);
+						    client->addr + i);
 			if (!twl->client) {
 				dev_err(&client->dev,
 					"can't attach client %d\n", i);
@@ -1252,7 +1252,16 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 				goto fail;
 			}
 		}
-		mutex_init(&twl->xfer_lock);
+
+		twl->regmap = devm_regmap_init_i2c(twl->client,
+						   &twl_regmap_config[i]);
+		if (IS_ERR(twl->regmap)) {
+			status = PTR_ERR(twl->regmap);
+			dev_err(&client->dev,
+				"Failed to allocate regmap %d, err: %d\n", i,
+				status);
+			goto fail;
+		}
 	}
 
 	inuse = true;
diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c
index 5c11acf..e16edca 100644
--- a/drivers/mfd/twl4030-audio.c
+++ b/drivers/mfd/twl4030-audio.c
@@ -184,7 +184,7 @@ static bool twl4030_audio_has_vibra(struct twl4030_audio_data *pdata,
 	return false;
 }
 
-static int __devinit twl4030_audio_probe(struct platform_device *pdev)
+static int twl4030_audio_probe(struct platform_device *pdev)
 {
 	struct twl4030_audio *audio;
 	struct twl4030_audio_data *pdata = pdev->dev.platform_data;
@@ -269,7 +269,7 @@ static int __devinit twl4030_audio_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit twl4030_audio_remove(struct platform_device *pdev)
+static int twl4030_audio_remove(struct platform_device *pdev)
 {
 	mfd_remove_devices(&pdev->dev);
 	platform_set_drvdata(pdev, NULL);
@@ -291,7 +291,7 @@ static struct platform_driver twl4030_audio_driver = {
 		.of_match_table = twl4030_audio_of_match,
 	},
 	.probe		= twl4030_audio_probe,
-	.remove		= __devexit_p(twl4030_audio_remove),
+	.remove		= twl4030_audio_remove,
 };
 
 module_platform_driver(twl4030_audio_driver);
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index ad733d7..a5f9888 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -295,8 +295,8 @@ static irqreturn_t handle_twl4030_pih(int irq, void *devid)
 	irqreturn_t	ret;
 	u8		pih_isr;
 
-	ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
-			REG_PIH_ISR_P1);
+	ret = twl_i2c_read_u8(TWL_MODULE_PIH, &pih_isr,
+			      REG_PIH_ISR_P1);
 	if (ret) {
 		pr_warning("twl4030: I2C error %d reading PIH ISR\n", ret);
 		return IRQ_NONE;
@@ -501,7 +501,7 @@ static void twl4030_sih_bus_sync_unlock(struct irq_data *data)
 		} imr;
 
 		/* byte[0] gets overwritten as we write ... */
-		imr.word = cpu_to_le32(agent->imr << 8);
+		imr.word = cpu_to_le32(agent->imr);
 		agent->imr_change_pending = false;
 
 		/* write the whole mask ... simpler than subsetting it */
@@ -526,7 +526,7 @@ static void twl4030_sih_bus_sync_unlock(struct irq_data *data)
 		 * any processor on the other IRQ line, EDR registers are
 		 * shared.
 		 */
-		status = twl_i2c_read(sih->module, bytes + 1,
+		status = twl_i2c_read(sih->module, bytes,
 				sih->edr_offset, sih->bytes_edr);
 		if (status) {
 			pr_err("twl4030: %s, %s --> %d\n", __func__,
@@ -538,7 +538,7 @@ static void twl4030_sih_bus_sync_unlock(struct irq_data *data)
 		while (edge_change) {
 			int		i = fls(edge_change) - 1;
 			struct irq_data	*idata;
-			int		byte = 1 + (i >> 2);
+			int		byte = i >> 2;
 			int		off = (i & 0x3) * 2;
 			unsigned int	type;
 
@@ -672,7 +672,8 @@ int twl4030_sih_setup(struct device *dev, int module, int irq_base)
 	irq = sih_mod + twl4030_irq_base;
 	irq_set_handler_data(irq, agent);
 	agent->irq_name = kasprintf(GFP_KERNEL, "twl4030_%s", sih->name);
-	status = request_threaded_irq(irq, NULL, handle_twl4030_sih, 0,
+	status = request_threaded_irq(irq, NULL, handle_twl4030_sih,
+				      IRQF_EARLY_RESUME,
 				      agent->irq_name ?: sih->name, NULL);
 
 	dev_info(dev, "%s (irq %d) chaining IRQs %d..%d\n", sih->name,
diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
index 456ecb5..88ff9dc 100644
--- a/drivers/mfd/twl4030-madc.c
+++ b/drivers/mfd/twl4030-madc.c
@@ -173,7 +173,7 @@ static int twl4030battery_temperature(int raw_volt)
 
 	volt = (raw_volt * TEMP_STEP_SIZE) / TEMP_PSR_R;
 	/* Getting and calculating the supply current in micro ampers */
-	ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
+	ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
 		REG_BCICTL2);
 	if (ret < 0)
 		return ret;
@@ -196,7 +196,7 @@ static int twl4030battery_current(int raw_volt)
 	int ret;
 	u8 val;
 
-	ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
+	ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
 		TWL4030_BCI_BCICTL1);
 	if (ret)
 		return ret;
@@ -635,7 +635,7 @@ static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
 	int ret;
 	u8 regval;
 
-	ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
+	ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
 			      &regval, TWL4030_BCI_BCICTL1);
 	if (ret) {
 		dev_err(madc->dev, "unable to read BCICTL1 reg 0x%X",
@@ -646,7 +646,7 @@ static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
 		regval |= chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
 	else
 		regval &= chan ? ~TWL4030_BCI_ITHEN : ~TWL4030_BCI_TYPEN;
-	ret = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
+	ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
 			       regval, TWL4030_BCI_BCICTL1);
 	if (ret) {
 		dev_err(madc->dev, "unable to write BCICTL1 reg 0x%X\n",
@@ -668,7 +668,7 @@ static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
 	u8 regval;
 	int ret;
 
-	ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
+	ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
 			      &regval, TWL4030_MADC_CTRL1);
 	if (ret) {
 		dev_err(madc->dev, "unable to read madc ctrl1 reg 0x%X\n",
@@ -692,7 +692,7 @@ static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
 /*
  * Initialize MADC and request for threaded irq
  */
-static int __devinit twl4030_madc_probe(struct platform_device *pdev)
+static int twl4030_madc_probe(struct platform_device *pdev)
 {
 	struct twl4030_madc_data *madc;
 	struct twl4030_madc_platform_data *pdata = pdev->dev.platform_data;
@@ -725,7 +725,7 @@ static int __devinit twl4030_madc_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto err_current_generator;
 
-	ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
+	ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
 			      &regval, TWL4030_BCI_BCICTL1);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to read reg BCI CTL1 0x%X\n",
@@ -733,7 +733,7 @@ static int __devinit twl4030_madc_probe(struct platform_device *pdev)
 		goto err_i2c;
 	}
 	regval |= TWL4030_BCI_MESBAT;
-	ret = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
+	ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
 			       regval, TWL4030_BCI_BCICTL1);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to write reg BCI Ctl1 0x%X\n",
@@ -785,7 +785,7 @@ err_power:
 	return ret;
 }
 
-static int __devexit twl4030_madc_remove(struct platform_device *pdev)
+static int twl4030_madc_remove(struct platform_device *pdev)
 {
 	struct twl4030_madc_data *madc = platform_get_drvdata(pdev);
 
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
index 79ca33d..4dae241 100644
--- a/drivers/mfd/twl4030-power.c
+++ b/drivers/mfd/twl4030-power.c
@@ -124,21 +124,19 @@ static u8 res_config_addrs[] = {
 	[RES_MAIN_REF]	= 0x94,
 };
 
-static int __devinit twl4030_write_script_byte(u8 address, u8 byte)
+static int twl4030_write_script_byte(u8 address, u8 byte)
 {
 	int err;
 
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address,
-				R_MEMORY_ADDRESS);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_MEMORY_ADDRESS);
 	if (err)
 		goto out;
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, byte,
-				R_MEMORY_DATA);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, byte, R_MEMORY_DATA);
 out:
 	return err;
 }
 
-static int __devinit twl4030_write_script_ins(u8 address, u16 pmb_message,
+static int twl4030_write_script_ins(u8 address, u16 pmb_message,
 					   u8 delay, u8 next)
 {
 	int err;
@@ -158,7 +156,7 @@ out:
 	return err;
 }
 
-static int __devinit twl4030_write_script(u8 address, struct twl4030_ins *script,
+static int twl4030_write_script(u8 address, struct twl4030_ins *script,
 				       int len)
 {
 	int err;
@@ -183,74 +181,66 @@ static int __devinit twl4030_write_script(u8 address, struct twl4030_ins *script
 	return err;
 }
 
-static int __devinit twl4030_config_wakeup3_sequence(u8 address)
+static int twl4030_config_wakeup3_sequence(u8 address)
 {
 	int err;
 	u8 data;
 
 	/* Set SLEEP to ACTIVE SEQ address for P3 */
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address,
-				R_SEQ_ADD_S2A3);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_S2A3);
 	if (err)
 		goto out;
 
 	/* P3 LVL_WAKEUP should be on LEVEL */
-	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data,
-				R_P3_SW_EVENTS);
+	err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P3_SW_EVENTS);
 	if (err)
 		goto out;
 	data |= LVL_WAKEUP;
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data,
-				R_P3_SW_EVENTS);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P3_SW_EVENTS);
 out:
 	if (err)
 		pr_err("TWL4030 wakeup sequence for P3 config error\n");
 	return err;
 }
 
-static int __devinit twl4030_config_wakeup12_sequence(u8 address)
+static int twl4030_config_wakeup12_sequence(u8 address)
 {
 	int err = 0;
 	u8 data;
 
 	/* Set SLEEP to ACTIVE SEQ address for P1 and P2 */
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address,
-				R_SEQ_ADD_S2A12);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_S2A12);
 	if (err)
 		goto out;
 
 	/* P1/P2 LVL_WAKEUP should be on LEVEL */
-	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data,
-				R_P1_SW_EVENTS);
+	err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P1_SW_EVENTS);
 	if (err)
 		goto out;
 
 	data |= LVL_WAKEUP;
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data,
-				R_P1_SW_EVENTS);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P1_SW_EVENTS);
 	if (err)
 		goto out;
 
-	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data,
-				R_P2_SW_EVENTS);
+	err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P2_SW_EVENTS);
 	if (err)
 		goto out;
 
 	data |= LVL_WAKEUP;
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data,
-				R_P2_SW_EVENTS);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P2_SW_EVENTS);
 	if (err)
 		goto out;
 
 	if (machine_is_omap_3430sdp() || machine_is_omap_ldp()) {
 		/* Disabling AC charger effect on sleep-active transitions */
-		err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data,
-					R_CFG_P1_TRANSITION);
+		err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data,
+				      R_CFG_P1_TRANSITION);
 		if (err)
 			goto out;
 		data &= ~(1<<1);
-		err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data ,
-					R_CFG_P1_TRANSITION);
+		err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data,
+				       R_CFG_P1_TRANSITION);
 		if (err)
 			goto out;
 	}
@@ -262,13 +252,12 @@ out:
 	return err;
 }
 
-static int __devinit twl4030_config_sleep_sequence(u8 address)
+static int twl4030_config_sleep_sequence(u8 address)
 {
 	int err;
 
 	/* Set ACTIVE to SLEEP SEQ address in T2 memory*/
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address,
-				R_SEQ_ADD_A2S);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_A2S);
 
 	if (err)
 		pr_err("TWL4030 sleep sequence config error\n");
@@ -276,55 +265,48 @@ static int __devinit twl4030_config_sleep_sequence(u8 address)
 	return err;
 }
 
-static int __devinit twl4030_config_warmreset_sequence(u8 address)
+static int twl4030_config_warmreset_sequence(u8 address)
 {
 	int err;
 	u8 rd_data;
 
 	/* Set WARM RESET SEQ address for P1 */
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address,
-				R_SEQ_ADD_WARM);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_WARM);
 	if (err)
 		goto out;
 
 	/* P1/P2/P3 enable WARMRESET */
-	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data,
-				R_P1_SW_EVENTS);
+	err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P1_SW_EVENTS);
 	if (err)
 		goto out;
 
 	rd_data |= ENABLE_WARMRESET;
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data,
-				R_P1_SW_EVENTS);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P1_SW_EVENTS);
 	if (err)
 		goto out;
 
-	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data,
-				R_P2_SW_EVENTS);
+	err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P2_SW_EVENTS);
 	if (err)
 		goto out;
 
 	rd_data |= ENABLE_WARMRESET;
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data,
-				R_P2_SW_EVENTS);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P2_SW_EVENTS);
 	if (err)
 		goto out;
 
-	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data,
-				R_P3_SW_EVENTS);
+	err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P3_SW_EVENTS);
 	if (err)
 		goto out;
 
 	rd_data |= ENABLE_WARMRESET;
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data,
-				R_P3_SW_EVENTS);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P3_SW_EVENTS);
 out:
 	if (err)
 		pr_err("TWL4030 warmreset seq config error\n");
 	return err;
 }
 
-static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfig)
+static int twl4030_configure_resource(struct twl4030_resconfig *rconfig)
 {
 	int rconfig_addr;
 	int err;
@@ -341,7 +323,7 @@ static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfi
 	rconfig_addr = res_config_addrs[rconfig->resource];
 
 	/* Set resource group */
-	err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp,
+	err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &grp,
 			      rconfig_addr + DEV_GRP_OFFSET);
 	if (err) {
 		pr_err("TWL4030 Resource %d group could not be read\n",
@@ -352,7 +334,7 @@ static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfi
 	if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) {
 		grp &= ~DEV_GRP_MASK;
 		grp |= rconfig->devgroup << DEV_GRP_SHIFT;
-		err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+		err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER,
 				       grp, rconfig_addr + DEV_GRP_OFFSET);
 		if (err < 0) {
 			pr_err("TWL4030 failed to program devgroup\n");
@@ -361,7 +343,7 @@ static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfi
 	}
 
 	/* Set resource types */
-	err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type,
+	err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &type,
 				rconfig_addr + TYPE_OFFSET);
 	if (err < 0) {
 		pr_err("TWL4030 Resource %d type could not be read\n",
@@ -379,7 +361,7 @@ static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfi
 		type |= rconfig->type2 << TYPE2_SHIFT;
 	}
 
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+	err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER,
 				type, rconfig_addr + TYPE_OFFSET);
 	if (err < 0) {
 		pr_err("TWL4030 failed to program resource type\n");
@@ -387,7 +369,7 @@ static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfi
 	}
 
 	/* Set remap states */
-	err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &remap,
+	err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &remap,
 			      rconfig_addr + REMAP_OFFSET);
 	if (err < 0) {
 		pr_err("TWL4030 Resource %d remap could not be read\n",
@@ -405,7 +387,7 @@ static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfi
 		remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT;
 	}
 
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+	err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER,
 			       remap,
 			       rconfig_addr + REMAP_OFFSET);
 	if (err < 0) {
@@ -416,7 +398,7 @@ static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfi
 	return 0;
 }
 
-static int __devinit load_twl4030_script(struct twl4030_script *tscript,
+static int load_twl4030_script(struct twl4030_script *tscript,
 	       u8 address)
 {
 	int err;
@@ -463,49 +445,47 @@ int twl4030_remove_script(u8 flags)
 {
 	int err = 0;
 
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
-			TWL4030_PM_MASTER_KEY_CFG1,
-			TWL4030_PM_MASTER_PROTECT_KEY);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
+			       TWL4030_PM_MASTER_PROTECT_KEY);
 	if (err) {
 		pr_err("twl4030: unable to unlock PROTECT_KEY\n");
 		return err;
 	}
 
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
-			TWL4030_PM_MASTER_KEY_CFG2,
-			TWL4030_PM_MASTER_PROTECT_KEY);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
+			       TWL4030_PM_MASTER_PROTECT_KEY);
 	if (err) {
 		pr_err("twl4030: unable to unlock PROTECT_KEY\n");
 		return err;
 	}
 
 	if (flags & TWL4030_WRST_SCRIPT) {
-		err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
-				R_SEQ_ADD_WARM);
+		err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
+				       R_SEQ_ADD_WARM);
 		if (err)
 			return err;
 	}
 	if (flags & TWL4030_WAKEUP12_SCRIPT) {
-		err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
-				R_SEQ_ADD_S2A12);
+		err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
+				       R_SEQ_ADD_S2A12);
 		if (err)
 			return err;
 	}
 	if (flags & TWL4030_WAKEUP3_SCRIPT) {
-		err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
-				R_SEQ_ADD_S2A3);
+		err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
+				       R_SEQ_ADD_S2A3);
 		if (err)
 			return err;
 	}
 	if (flags & TWL4030_SLEEP_SCRIPT) {
-		err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
-				R_SEQ_ADD_A2S);
+		err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
+				       R_SEQ_ADD_A2S);
 		if (err)
 			return err;
 	}
 
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0,
-			TWL4030_PM_MASTER_PROTECT_KEY);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
+			       TWL4030_PM_MASTER_PROTECT_KEY);
 	if (err)
 		pr_err("TWL4030 Unable to relock registers\n");
 
@@ -521,28 +501,26 @@ void twl4030_power_off(void)
 {
 	int err;
 
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, PWR_DEVOFF,
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, PWR_DEVOFF,
 			       TWL4030_PM_MASTER_P1_SW_EVENTS);
 	if (err)
 		pr_err("TWL4030 Unable to power off\n");
 }
 
-void __devinit twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
+void twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
 {
 	int err = 0;
 	int i;
 	struct twl4030_resconfig *resconfig;
 	u8 val, address = twl4030_start_script_address;
 
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
-			TWL4030_PM_MASTER_KEY_CFG1,
-			TWL4030_PM_MASTER_PROTECT_KEY);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
+			       TWL4030_PM_MASTER_PROTECT_KEY);
 	if (err)
 		goto unlock;
 
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
-			TWL4030_PM_MASTER_KEY_CFG2,
-			TWL4030_PM_MASTER_PROTECT_KEY);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
+			       TWL4030_PM_MASTER_PROTECT_KEY);
 	if (err)
 		goto unlock;
 
@@ -567,14 +545,14 @@ void __devinit twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
 	/* Board has to be wired properly to use this feature */
 	if (twl4030_scripts->use_poweroff && !pm_power_off) {
 		/* Default for SEQ_OFFSYNC is set, lets ensure this */
-		err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val,
+		err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val,
 				      TWL4030_PM_MASTER_CFG_P123_TRANSITION);
 		if (err) {
 			pr_warning("TWL4030 Unable to read registers\n");
 
 		} else if (!(val & SEQ_OFFSYNC)) {
 			val |= SEQ_OFFSYNC;
-			err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val,
+			err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val,
 					TWL4030_PM_MASTER_CFG_P123_TRANSITION);
 			if (err) {
 				pr_err("TWL4030 Unable to setup SEQ_OFFSYNC\n");
@@ -586,8 +564,8 @@ void __devinit twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
 	}
 
 relock:
-	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0,
-			TWL4030_PM_MASTER_PROTECT_KEY);
+	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
+			       TWL4030_PM_MASTER_PROTECT_KEY);
 	if (err)
 		pr_err("TWL4030 Unable to relock registers\n");
 	return;
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index b76902f..277a8db 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -355,7 +355,7 @@ int twl6030_init_irq(struct device *dev, int irq_num)
 	static struct irq_chip  twl6030_irq_chip;
 	int			status = 0;
 	int			i;
-	u8			mask[4];
+	u8			mask[3];
 
 	nr_irqs = TWL6030_NR_IRQS;
 
@@ -370,9 +370,9 @@ int twl6030_init_irq(struct device *dev, int irq_num)
 
 	irq_end = irq_base + nr_irqs;
 
+	mask[0] = 0xFF;
 	mask[1] = 0xFF;
 	mask[2] = 0xFF;
-	mask[3] = 0xFF;
 
 	/* mask all int lines */
 	twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_LINE_A, 3);
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c
deleted file mode 100644
index 3f2a1cf..0000000
--- a/drivers/mfd/twl6040-core.c
+++ /dev/null
@@ -1,718 +0,0 @@
-/*
- * MFD driver for TWL6040 audio device
- *
- * Authors:	Misael Lopez Cruz <misael.lopez@ti.com>
- *		Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
- *		Peter Ujfalusi <peter.ujfalusi@ti.com>
- *
- * Copyright:	(C) 2011 Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <linux/of_gpio.h>
-#include <linux/of_platform.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/regmap.h>
-#include <linux/err.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/twl6040.h>
-#include <linux/regulator/consumer.h>
-
-#define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1)
-#define TWL6040_NUM_SUPPLIES	(2)
-
-static bool twl6040_has_vibra(struct twl6040_platform_data *pdata,
-			      struct device_node *node)
-{
-	if (pdata && pdata->vibra)
-		return true;
-
-#ifdef CONFIG_OF
-	if (of_find_node_by_name(node, "vibra"))
-		return true;
-#endif
-
-	return false;
-}
-
-int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
-{
-	int ret;
-	unsigned int val;
-
-	/* Vibra control registers from cache */
-	if (unlikely(reg == TWL6040_REG_VIBCTLL ||
-		     reg == TWL6040_REG_VIBCTLR)) {
-		val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)];
-	} else {
-		ret = regmap_read(twl6040->regmap, reg, &val);
-		if (ret < 0)
-			return ret;
-	}
-
-	return val;
-}
-EXPORT_SYMBOL(twl6040_reg_read);
-
-int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val)
-{
-	int ret;
-
-	ret = regmap_write(twl6040->regmap, reg, val);
-	/* Cache the vibra control registers */
-	if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR)
-		twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val;
-
-	return ret;
-}
-EXPORT_SYMBOL(twl6040_reg_write);
-
-int twl6040_set_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
-{
-	return regmap_update_bits(twl6040->regmap, reg, mask, mask);
-}
-EXPORT_SYMBOL(twl6040_set_bits);
-
-int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
-{
-	return regmap_update_bits(twl6040->regmap, reg, mask, 0);
-}
-EXPORT_SYMBOL(twl6040_clear_bits);
-
-/* twl6040 codec manual power-up sequence */
-static int twl6040_power_up(struct twl6040 *twl6040)
-{
-	u8 ldoctl, ncpctl, lppllctl;
-	int ret;
-
-	/* enable high-side LDO, reference system and internal oscillator */
-	ldoctl = TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA;
-	ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
-	if (ret)
-		return ret;
-	usleep_range(10000, 10500);
-
-	/* enable negative charge pump */
-	ncpctl = TWL6040_NCPENA;
-	ret = twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
-	if (ret)
-		goto ncp_err;
-	usleep_range(1000, 1500);
-
-	/* enable low-side LDO */
-	ldoctl |= TWL6040_LSLDOENA;
-	ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
-	if (ret)
-		goto lsldo_err;
-	usleep_range(1000, 1500);
-
-	/* enable low-power PLL */
-	lppllctl = TWL6040_LPLLENA;
-	ret = twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
-	if (ret)
-		goto lppll_err;
-	usleep_range(5000, 5500);
-
-	/* disable internal oscillator */
-	ldoctl &= ~TWL6040_OSCENA;
-	ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
-	if (ret)
-		goto osc_err;
-
-	return 0;
-
-osc_err:
-	lppllctl &= ~TWL6040_LPLLENA;
-	twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
-lppll_err:
-	ldoctl &= ~TWL6040_LSLDOENA;
-	twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
-lsldo_err:
-	ncpctl &= ~TWL6040_NCPENA;
-	twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
-ncp_err:
-	ldoctl &= ~(TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA);
-	twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
-
-	return ret;
-}
-
-/* twl6040 manual power-down sequence */
-static void twl6040_power_down(struct twl6040 *twl6040)
-{
-	u8 ncpctl, ldoctl, lppllctl;
-
-	ncpctl = twl6040_reg_read(twl6040, TWL6040_REG_NCPCTL);
-	ldoctl = twl6040_reg_read(twl6040, TWL6040_REG_LDOCTL);
-	lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
-
-	/* enable internal oscillator */
-	ldoctl |= TWL6040_OSCENA;
-	twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
-	usleep_range(1000, 1500);
-
-	/* disable low-power PLL */
-	lppllctl &= ~TWL6040_LPLLENA;
-	twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
-
-	/* disable low-side LDO */
-	ldoctl &= ~TWL6040_LSLDOENA;
-	twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
-
-	/* disable negative charge pump */
-	ncpctl &= ~TWL6040_NCPENA;
-	twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
-
-	/* disable high-side LDO, reference system and internal oscillator */
-	ldoctl &= ~(TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA);
-	twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
-}
-
-static irqreturn_t twl6040_naudint_handler(int irq, void *data)
-{
-	struct twl6040 *twl6040 = data;
-	u8 intid, status;
-
-	intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
-
-	if (intid & TWL6040_READYINT)
-		complete(&twl6040->ready);
-
-	if (intid & TWL6040_THINT) {
-		status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS);
-		if (status & TWL6040_TSHUTDET) {
-			dev_warn(twl6040->dev,
-				 "Thermal shutdown, powering-off");
-			twl6040_power(twl6040, 0);
-		} else {
-			dev_warn(twl6040->dev,
-				 "Leaving thermal shutdown, powering-on");
-			twl6040_power(twl6040, 1);
-		}
-	}
-
-	return IRQ_HANDLED;
-}
-
-static int twl6040_power_up_completion(struct twl6040 *twl6040,
-				       int naudint)
-{
-	int time_left;
-	u8 intid;
-
-	time_left = wait_for_completion_timeout(&twl6040->ready,
-						msecs_to_jiffies(144));
-	if (!time_left) {
-		intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
-		if (!(intid & TWL6040_READYINT)) {
-			dev_err(twl6040->dev,
-				"timeout waiting for READYINT\n");
-			return -ETIMEDOUT;
-		}
-	}
-
-	return 0;
-}
-
-int twl6040_power(struct twl6040 *twl6040, int on)
-{
-	int audpwron = twl6040->audpwron;
-	int naudint = twl6040->irq;
-	int ret = 0;
-
-	mutex_lock(&twl6040->mutex);
-
-	if (on) {
-		/* already powered-up */
-		if (twl6040->power_count++)
-			goto out;
-
-		if (gpio_is_valid(audpwron)) {
-			/* use AUDPWRON line */
-			gpio_set_value(audpwron, 1);
-			/* wait for power-up completion */
-			ret = twl6040_power_up_completion(twl6040, naudint);
-			if (ret) {
-				dev_err(twl6040->dev,
-					"automatic power-down failed\n");
-				twl6040->power_count = 0;
-				goto out;
-			}
-		} else {
-			/* use manual power-up sequence */
-			ret = twl6040_power_up(twl6040);
-			if (ret) {
-				dev_err(twl6040->dev,
-					"manual power-up failed\n");
-				twl6040->power_count = 0;
-				goto out;
-			}
-		}
-		/* Default PLL configuration after power up */
-		twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
-		twl6040->sysclk = 19200000;
-		twl6040->mclk = 32768;
-	} else {
-		/* already powered-down */
-		if (!twl6040->power_count) {
-			dev_err(twl6040->dev,
-				"device is already powered-off\n");
-			ret = -EPERM;
-			goto out;
-		}
-
-		if (--twl6040->power_count)
-			goto out;
-
-		if (gpio_is_valid(audpwron)) {
-			/* use AUDPWRON line */
-			gpio_set_value(audpwron, 0);
-
-			/* power-down sequence latency */
-			usleep_range(500, 700);
-		} else {
-			/* use manual power-down sequence */
-			twl6040_power_down(twl6040);
-		}
-		twl6040->sysclk = 0;
-		twl6040->mclk = 0;
-	}
-
-out:
-	mutex_unlock(&twl6040->mutex);
-	return ret;
-}
-EXPORT_SYMBOL(twl6040_power);
-
-int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
-		    unsigned int freq_in, unsigned int freq_out)
-{
-	u8 hppllctl, lppllctl;
-	int ret = 0;
-
-	mutex_lock(&twl6040->mutex);
-
-	hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);
-	lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
-
-	/* Force full reconfiguration when switching between PLL */
-	if (pll_id != twl6040->pll) {
-		twl6040->sysclk = 0;
-		twl6040->mclk = 0;
-	}
-
-	switch (pll_id) {
-	case TWL6040_SYSCLK_SEL_LPPLL:
-		/* low-power PLL divider */
-		/* Change the sysclk configuration only if it has been canged */
-		if (twl6040->sysclk != freq_out) {
-			switch (freq_out) {
-			case 17640000:
-				lppllctl |= TWL6040_LPLLFIN;
-				break;
-			case 19200000:
-				lppllctl &= ~TWL6040_LPLLFIN;
-				break;
-			default:
-				dev_err(twl6040->dev,
-					"freq_out %d not supported\n",
-					freq_out);
-				ret = -EINVAL;
-				goto pll_out;
-			}
-			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
-					  lppllctl);
-		}
-
-		/* The PLL in use has not been change, we can exit */
-		if (twl6040->pll == pll_id)
-			break;
-
-		switch (freq_in) {
-		case 32768:
-			lppllctl |= TWL6040_LPLLENA;
-			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
-					  lppllctl);
-			mdelay(5);
-			lppllctl &= ~TWL6040_HPLLSEL;
-			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
-					  lppllctl);
-			hppllctl &= ~TWL6040_HPLLENA;
-			twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
-					  hppllctl);
-			break;
-		default:
-			dev_err(twl6040->dev,
-				"freq_in %d not supported\n", freq_in);
-			ret = -EINVAL;
-			goto pll_out;
-		}
-		break;
-	case TWL6040_SYSCLK_SEL_HPPLL:
-		/* high-performance PLL can provide only 19.2 MHz */
-		if (freq_out != 19200000) {
-			dev_err(twl6040->dev,
-				"freq_out %d not supported\n", freq_out);
-			ret = -EINVAL;
-			goto pll_out;
-		}
-
-		if (twl6040->mclk != freq_in) {
-			hppllctl &= ~TWL6040_MCLK_MSK;
-
-			switch (freq_in) {
-			case 12000000:
-				/* PLL enabled, active mode */
-				hppllctl |= TWL6040_MCLK_12000KHZ |
-					    TWL6040_HPLLENA;
-				break;
-			case 19200000:
-				/*
-				* PLL disabled
-				* (enable PLL if MCLK jitter quality
-				*  doesn't meet specification)
-				*/
-				hppllctl |= TWL6040_MCLK_19200KHZ;
-				break;
-			case 26000000:
-				/* PLL enabled, active mode */
-				hppllctl |= TWL6040_MCLK_26000KHZ |
-					    TWL6040_HPLLENA;
-				break;
-			case 38400000:
-				/* PLL enabled, active mode */
-				hppllctl |= TWL6040_MCLK_38400KHZ |
-					    TWL6040_HPLLENA;
-				break;
-			default:
-				dev_err(twl6040->dev,
-					"freq_in %d not supported\n", freq_in);
-				ret = -EINVAL;
-				goto pll_out;
-			}
-
-			/*
-			 * enable clock slicer to ensure input waveform is
-			 * square
-			 */
-			hppllctl |= TWL6040_HPLLSQRENA;
-
-			twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
-					  hppllctl);
-			usleep_range(500, 700);
-			lppllctl |= TWL6040_HPLLSEL;
-			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
-					  lppllctl);
-			lppllctl &= ~TWL6040_LPLLENA;
-			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
-					  lppllctl);
-		}
-		break;
-	default:
-		dev_err(twl6040->dev, "unknown pll id %d\n", pll_id);
-		ret = -EINVAL;
-		goto pll_out;
-	}
-
-	twl6040->sysclk = freq_out;
-	twl6040->mclk = freq_in;
-	twl6040->pll = pll_id;
-
-pll_out:
-	mutex_unlock(&twl6040->mutex);
-	return ret;
-}
-EXPORT_SYMBOL(twl6040_set_pll);
-
-int twl6040_get_pll(struct twl6040 *twl6040)
-{
-	if (twl6040->power_count)
-		return twl6040->pll;
-	else
-		return -ENODEV;
-}
-EXPORT_SYMBOL(twl6040_get_pll);
-
-unsigned int twl6040_get_sysclk(struct twl6040 *twl6040)
-{
-	return twl6040->sysclk;
-}
-EXPORT_SYMBOL(twl6040_get_sysclk);
-
-/* Get the combined status of the vibra control register */
-int twl6040_get_vibralr_status(struct twl6040 *twl6040)
-{
-	u8 status;
-
-	status = twl6040->vibra_ctrl_cache[0] | twl6040->vibra_ctrl_cache[1];
-	status &= (TWL6040_VIBENA | TWL6040_VIBSEL);
-
-	return status;
-}
-EXPORT_SYMBOL(twl6040_get_vibralr_status);
-
-static struct resource twl6040_vibra_rsrc[] = {
-	{
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource twl6040_codec_rsrc[] = {
-	{
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static bool twl6040_readable_reg(struct device *dev, unsigned int reg)
-{
-	/* Register 0 is not readable */
-	if (!reg)
-		return false;
-	return true;
-}
-
-static struct regmap_config twl6040_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-	.max_register = TWL6040_REG_STATUS, /* 0x2e */
-
-	.readable_reg = twl6040_readable_reg,
-};
-
-static int __devinit twl6040_probe(struct i2c_client *client,
-				     const struct i2c_device_id *id)
-{
-	struct twl6040_platform_data *pdata = client->dev.platform_data;
-	struct device_node *node = client->dev.of_node;
-	struct twl6040 *twl6040;
-	struct mfd_cell *cell = NULL;
-	int irq, ret, children = 0;
-
-	if (!pdata && !node) {
-		dev_err(&client->dev, "Platform data is missing\n");
-		return -EINVAL;
-	}
-
-	/* In order to operate correctly we need valid interrupt config */
-	if (!client->irq) {
-		dev_err(&client->dev, "Invalid IRQ configuration\n");
-		return -EINVAL;
-	}
-
-	twl6040 = devm_kzalloc(&client->dev, sizeof(struct twl6040),
-			       GFP_KERNEL);
-	if (!twl6040) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	twl6040->regmap = devm_regmap_init_i2c(client, &twl6040_regmap_config);
-	if (IS_ERR(twl6040->regmap)) {
-		ret = PTR_ERR(twl6040->regmap);
-		goto err;
-	}
-
-	i2c_set_clientdata(client, twl6040);
-
-	twl6040->supplies[0].supply = "vio";
-	twl6040->supplies[1].supply = "v2v1";
-	ret = regulator_bulk_get(&client->dev, TWL6040_NUM_SUPPLIES,
-				 twl6040->supplies);
-	if (ret != 0) {
-		dev_err(&client->dev, "Failed to get supplies: %d\n", ret);
-		goto regulator_get_err;
-	}
-
-	ret = regulator_bulk_enable(TWL6040_NUM_SUPPLIES, twl6040->supplies);
-	if (ret != 0) {
-		dev_err(&client->dev, "Failed to enable supplies: %d\n", ret);
-		goto power_err;
-	}
-
-	twl6040->dev = &client->dev;
-	twl6040->irq = client->irq;
-
-	mutex_init(&twl6040->mutex);
-	init_completion(&twl6040->ready);
-
-	twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
-
-	/* ERRATA: Automatic power-up is not possible in ES1.0 */
-	if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0) {
-		if (pdata)
-			twl6040->audpwron = pdata->audpwron_gpio;
-		else
-			twl6040->audpwron = of_get_named_gpio(node,
-						"ti,audpwron-gpio", 0);
-	} else
-		twl6040->audpwron = -EINVAL;
-
-	if (gpio_is_valid(twl6040->audpwron)) {
-		ret = gpio_request_one(twl6040->audpwron, GPIOF_OUT_INIT_LOW,
-				       "audpwron");
-		if (ret)
-			goto gpio_err;
-	}
-
-	/* codec interrupt */
-	ret = twl6040_irq_init(twl6040);
-	if (ret)
-		goto irq_init_err;
-
-	ret = request_threaded_irq(twl6040->irq_base + TWL6040_IRQ_READY,
-				   NULL, twl6040_naudint_handler, IRQF_ONESHOT,
-				   "twl6040_irq_ready", twl6040);
-	if (ret) {
-		dev_err(twl6040->dev, "READY IRQ request failed: %d\n",
-			ret);
-		goto irq_err;
-	}
-
-	/* dual-access registers controlled by I2C only */
-	twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL);
-
-	/*
-	 * The main functionality of twl6040 to provide audio on OMAP4+ systems.
-	 * We can add the ASoC codec child whenever this driver has been loaded.
-	 * The ASoC codec can work without pdata, pass the platform_data only if
-	 * it has been provided.
-	 */
-	irq = twl6040->irq_base + TWL6040_IRQ_PLUG;
-	cell = &twl6040->cells[children];
-	cell->name = "twl6040-codec";
-	twl6040_codec_rsrc[0].start = irq;
-	twl6040_codec_rsrc[0].end = irq;
-	cell->resources = twl6040_codec_rsrc;
-	cell->num_resources = ARRAY_SIZE(twl6040_codec_rsrc);
-	if (pdata && pdata->codec) {
-		cell->platform_data = pdata->codec;
-		cell->pdata_size = sizeof(*pdata->codec);
-	}
-	children++;
-
-	if (twl6040_has_vibra(pdata, node)) {
-		irq = twl6040->irq_base + TWL6040_IRQ_VIB;
-
-		cell = &twl6040->cells[children];
-		cell->name = "twl6040-vibra";
-		twl6040_vibra_rsrc[0].start = irq;
-		twl6040_vibra_rsrc[0].end = irq;
-		cell->resources = twl6040_vibra_rsrc;
-		cell->num_resources = ARRAY_SIZE(twl6040_vibra_rsrc);
-
-		if (pdata && pdata->vibra) {
-			cell->platform_data = pdata->vibra;
-			cell->pdata_size = sizeof(*pdata->vibra);
-		}
-		children++;
-	}
-
-	/*
-	 * Enable the GPO driver in the following cases:
-	 * DT booted kernel or legacy boot with valid gpo platform_data
-	 */
-	if (!pdata || (pdata && pdata->gpo)) {
-		cell = &twl6040->cells[children];
-		cell->name = "twl6040-gpo";
-
-		if (pdata) {
-			cell->platform_data = pdata->gpo;
-			cell->pdata_size = sizeof(*pdata->gpo);
-		}
-		children++;
-	}
-
-	ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children,
-			      NULL, 0, NULL);
-	if (ret)
-		goto mfd_err;
-
-	return 0;
-
-mfd_err:
-	free_irq(twl6040->irq_base + TWL6040_IRQ_READY, twl6040);
-irq_err:
-	twl6040_irq_exit(twl6040);
-irq_init_err:
-	if (gpio_is_valid(twl6040->audpwron))
-		gpio_free(twl6040->audpwron);
-gpio_err:
-	regulator_bulk_disable(TWL6040_NUM_SUPPLIES, twl6040->supplies);
-power_err:
-	regulator_bulk_free(TWL6040_NUM_SUPPLIES, twl6040->supplies);
-regulator_get_err:
-	i2c_set_clientdata(client, NULL);
-err:
-	return ret;
-}
-
-static int __devexit twl6040_remove(struct i2c_client *client)
-{
-	struct twl6040 *twl6040 = i2c_get_clientdata(client);
-
-	if (twl6040->power_count)
-		twl6040_power(twl6040, 0);
-
-	if (gpio_is_valid(twl6040->audpwron))
-		gpio_free(twl6040->audpwron);
-
-	free_irq(twl6040->irq_base + TWL6040_IRQ_READY, twl6040);
-	twl6040_irq_exit(twl6040);
-
-	mfd_remove_devices(&client->dev);
-	i2c_set_clientdata(client, NULL);
-
-	regulator_bulk_disable(TWL6040_NUM_SUPPLIES, twl6040->supplies);
-	regulator_bulk_free(TWL6040_NUM_SUPPLIES, twl6040->supplies);
-
-	return 0;
-}
-
-static const struct i2c_device_id twl6040_i2c_id[] = {
-	{ "twl6040", 0, },
-	{ "twl6041", 0, },
-	{ },
-};
-MODULE_DEVICE_TABLE(i2c, twl6040_i2c_id);
-
-static struct i2c_driver twl6040_driver = {
-	.driver = {
-		.name = "twl6040",
-		.owner = THIS_MODULE,
-	},
-	.probe		= twl6040_probe,
-	.remove		= __devexit_p(twl6040_remove),
-	.id_table	= twl6040_i2c_id,
-};
-
-module_i2c_driver(twl6040_driver);
-
-MODULE_DESCRIPTION("TWL6040 MFD");
-MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
-MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:twl6040");
diff --git a/drivers/mfd/twl6040-irq.c b/drivers/mfd/twl6040-irq.c
deleted file mode 100644
index 4b42543..0000000
--- a/drivers/mfd/twl6040-irq.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Interrupt controller support for TWL6040
- *
- * Author:     Misael Lopez Cruz <misael.lopez@ti.com>
- *
- * Copyright:   (C) 2011 Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/irq.h>
-#include <linux/of.h>
-#include <linux/irqdomain.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/twl6040.h>
-
-struct twl6040_irq_data {
-	int mask;
-	int status;
-};
-
-static struct twl6040_irq_data twl6040_irqs[] = {
-	{
-		.mask = TWL6040_THMSK,
-		.status = TWL6040_THINT,
-	},
-	{
-		.mask = TWL6040_PLUGMSK,
-		.status = TWL6040_PLUGINT | TWL6040_UNPLUGINT,
-	},
-	{
-		.mask = TWL6040_HOOKMSK,
-		.status = TWL6040_HOOKINT,
-	},
-	{
-		.mask = TWL6040_HFMSK,
-		.status = TWL6040_HFINT,
-	},
-	{
-		.mask = TWL6040_VIBMSK,
-		.status = TWL6040_VIBINT,
-	},
-	{
-		.mask = TWL6040_READYMSK,
-		.status = TWL6040_READYINT,
-	},
-};
-
-static inline
-struct twl6040_irq_data *irq_to_twl6040_irq(struct twl6040 *twl6040,
-					    int irq)
-{
-	return &twl6040_irqs[irq - twl6040->irq_base];
-}
-
-static void twl6040_irq_lock(struct irq_data *data)
-{
-	struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
-
-	mutex_lock(&twl6040->irq_mutex);
-}
-
-static void twl6040_irq_sync_unlock(struct irq_data *data)
-{
-	struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
-
-	/* write back to hardware any change in irq mask */
-	if (twl6040->irq_masks_cur != twl6040->irq_masks_cache) {
-		twl6040->irq_masks_cache = twl6040->irq_masks_cur;
-		twl6040_reg_write(twl6040, TWL6040_REG_INTMR,
-				  twl6040->irq_masks_cur);
-	}
-
-	mutex_unlock(&twl6040->irq_mutex);
-}
-
-static void twl6040_irq_enable(struct irq_data *data)
-{
-	struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
-	struct twl6040_irq_data *irq_data = irq_to_twl6040_irq(twl6040,
-							       data->irq);
-
-	twl6040->irq_masks_cur &= ~irq_data->mask;
-}
-
-static void twl6040_irq_disable(struct irq_data *data)
-{
-	struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
-	struct twl6040_irq_data *irq_data = irq_to_twl6040_irq(twl6040,
-							       data->irq);
-
-	twl6040->irq_masks_cur |= irq_data->mask;
-}
-
-static struct irq_chip twl6040_irq_chip = {
-	.name			= "twl6040",
-	.irq_bus_lock		= twl6040_irq_lock,
-	.irq_bus_sync_unlock	= twl6040_irq_sync_unlock,
-	.irq_enable		= twl6040_irq_enable,
-	.irq_disable		= twl6040_irq_disable,
-};
-
-static irqreturn_t twl6040_irq_thread(int irq, void *data)
-{
-	struct twl6040 *twl6040 = data;
-	u8 intid;
-	int i;
-
-	intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
-
-	/* apply masking and report (backwards to handle READYINT first) */
-	for (i = ARRAY_SIZE(twl6040_irqs) - 1; i >= 0; i--) {
-		if (twl6040->irq_masks_cur & twl6040_irqs[i].mask)
-			intid &= ~twl6040_irqs[i].status;
-		if (intid & twl6040_irqs[i].status)
-			handle_nested_irq(twl6040->irq_base + i);
-	}
-
-	/* ack unmasked irqs */
-	twl6040_reg_write(twl6040, TWL6040_REG_INTID, intid);
-
-	return IRQ_HANDLED;
-}
-
-int twl6040_irq_init(struct twl6040 *twl6040)
-{
-	struct device_node *node = twl6040->dev->of_node;
-	int i, nr_irqs, irq_base, ret;
-	u8 val;
-
-	mutex_init(&twl6040->irq_mutex);
-
-	/* mask the individual interrupt sources */
-	twl6040->irq_masks_cur = TWL6040_ALLINT_MSK;
-	twl6040->irq_masks_cache = TWL6040_ALLINT_MSK;
-	twl6040_reg_write(twl6040, TWL6040_REG_INTMR, TWL6040_ALLINT_MSK);
-
-	nr_irqs = ARRAY_SIZE(twl6040_irqs);
-
-	irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);
-	if (IS_ERR_VALUE(irq_base)) {
-		dev_err(twl6040->dev, "Fail to allocate IRQ descs\n");
-		return irq_base;
-	}
-	twl6040->irq_base = irq_base;
-
-	irq_domain_add_legacy(node, ARRAY_SIZE(twl6040_irqs), irq_base, 0,
-			      &irq_domain_simple_ops, NULL);
-
-	/* Register them with genirq */
-	for (i = irq_base; i < irq_base + nr_irqs; i++) {
-		irq_set_chip_data(i, twl6040);
-		irq_set_chip_and_handler(i, &twl6040_irq_chip,
-					 handle_level_irq);
-		irq_set_nested_thread(i, 1);
-
-		/* ARM needs us to explicitly flag the IRQ as valid
-		 * and will set them noprobe when we do so. */
-#ifdef CONFIG_ARM
-		set_irq_flags(i, IRQF_VALID);
-#else
-		irq_set_noprobe(i);
-#endif
-	}
-
-	ret = request_threaded_irq(twl6040->irq, NULL, twl6040_irq_thread,
-				   IRQF_ONESHOT, "twl6040", twl6040);
-	if (ret) {
-		dev_err(twl6040->dev, "failed to request IRQ %d: %d\n",
-			twl6040->irq, ret);
-		return ret;
-	}
-
-	/* reset interrupts */
-	val = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
-
-	/* interrupts cleared on write */
-	twl6040_clear_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_INTCLRMODE);
-
-	return 0;
-}
-EXPORT_SYMBOL(twl6040_irq_init);
-
-void twl6040_irq_exit(struct twl6040 *twl6040)
-{
-	free_irq(twl6040->irq, twl6040);
-}
-EXPORT_SYMBOL(twl6040_irq_exit);
diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c
new file mode 100644
index 0000000..583be76
--- /dev/null
+++ b/drivers/mfd/twl6040.c
@@ -0,0 +1,748 @@
+/*
+ * MFD driver for TWL6040 audio device
+ *
+ * Authors:	Misael Lopez Cruz <misael.lopez@ti.com>
+ *		Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
+ *		Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * Copyright:	(C) 2011 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/twl6040.h>
+#include <linux/regulator/consumer.h>
+
+#define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1)
+#define TWL6040_NUM_SUPPLIES	(2)
+
+static bool twl6040_has_vibra(struct twl6040_platform_data *pdata,
+			      struct device_node *node)
+{
+	if (pdata && pdata->vibra)
+		return true;
+
+#ifdef CONFIG_OF
+	if (of_find_node_by_name(node, "vibra"))
+		return true;
+#endif
+
+	return false;
+}
+
+int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
+{
+	int ret;
+	unsigned int val;
+
+	/* Vibra control registers from cache */
+	if (unlikely(reg == TWL6040_REG_VIBCTLL ||
+		     reg == TWL6040_REG_VIBCTLR)) {
+		val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)];
+	} else {
+		ret = regmap_read(twl6040->regmap, reg, &val);
+		if (ret < 0)
+			return ret;
+	}
+
+	return val;
+}
+EXPORT_SYMBOL(twl6040_reg_read);
+
+int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val)
+{
+	int ret;
+
+	ret = regmap_write(twl6040->regmap, reg, val);
+	/* Cache the vibra control registers */
+	if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR)
+		twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val;
+
+	return ret;
+}
+EXPORT_SYMBOL(twl6040_reg_write);
+
+int twl6040_set_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
+{
+	return regmap_update_bits(twl6040->regmap, reg, mask, mask);
+}
+EXPORT_SYMBOL(twl6040_set_bits);
+
+int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
+{
+	return regmap_update_bits(twl6040->regmap, reg, mask, 0);
+}
+EXPORT_SYMBOL(twl6040_clear_bits);
+
+/* twl6040 codec manual power-up sequence */
+static int twl6040_power_up_manual(struct twl6040 *twl6040)
+{
+	u8 ldoctl, ncpctl, lppllctl;
+	int ret;
+
+	/* enable high-side LDO, reference system and internal oscillator */
+	ldoctl = TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA;
+	ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+	if (ret)
+		return ret;
+	usleep_range(10000, 10500);
+
+	/* enable negative charge pump */
+	ncpctl = TWL6040_NCPENA;
+	ret = twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
+	if (ret)
+		goto ncp_err;
+	usleep_range(1000, 1500);
+
+	/* enable low-side LDO */
+	ldoctl |= TWL6040_LSLDOENA;
+	ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+	if (ret)
+		goto lsldo_err;
+	usleep_range(1000, 1500);
+
+	/* enable low-power PLL */
+	lppllctl = TWL6040_LPLLENA;
+	ret = twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+	if (ret)
+		goto lppll_err;
+	usleep_range(5000, 5500);
+
+	/* disable internal oscillator */
+	ldoctl &= ~TWL6040_OSCENA;
+	ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+	if (ret)
+		goto osc_err;
+
+	return 0;
+
+osc_err:
+	lppllctl &= ~TWL6040_LPLLENA;
+	twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+lppll_err:
+	ldoctl &= ~TWL6040_LSLDOENA;
+	twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+lsldo_err:
+	ncpctl &= ~TWL6040_NCPENA;
+	twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
+ncp_err:
+	ldoctl &= ~(TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA);
+	twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+
+	dev_err(twl6040->dev, "manual power-up failed\n");
+	return ret;
+}
+
+/* twl6040 manual power-down sequence */
+static void twl6040_power_down_manual(struct twl6040 *twl6040)
+{
+	u8 ncpctl, ldoctl, lppllctl;
+
+	ncpctl = twl6040_reg_read(twl6040, TWL6040_REG_NCPCTL);
+	ldoctl = twl6040_reg_read(twl6040, TWL6040_REG_LDOCTL);
+	lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
+
+	/* enable internal oscillator */
+	ldoctl |= TWL6040_OSCENA;
+	twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+	usleep_range(1000, 1500);
+
+	/* disable low-power PLL */
+	lppllctl &= ~TWL6040_LPLLENA;
+	twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
+
+	/* disable low-side LDO */
+	ldoctl &= ~TWL6040_LSLDOENA;
+	twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+
+	/* disable negative charge pump */
+	ncpctl &= ~TWL6040_NCPENA;
+	twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
+
+	/* disable high-side LDO, reference system and internal oscillator */
+	ldoctl &= ~(TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA);
+	twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
+}
+
+static irqreturn_t twl6040_readyint_handler(int irq, void *data)
+{
+	struct twl6040 *twl6040 = data;
+
+	complete(&twl6040->ready);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t twl6040_thint_handler(int irq, void *data)
+{
+	struct twl6040 *twl6040 = data;
+	u8 status;
+
+	status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS);
+	if (status & TWL6040_TSHUTDET) {
+		dev_warn(twl6040->dev, "Thermal shutdown, powering-off");
+		twl6040_power(twl6040, 0);
+	} else {
+		dev_warn(twl6040->dev, "Leaving thermal shutdown, powering-on");
+		twl6040_power(twl6040, 1);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int twl6040_power_up_automatic(struct twl6040 *twl6040)
+{
+	int time_left;
+
+	gpio_set_value(twl6040->audpwron, 1);
+
+	time_left = wait_for_completion_timeout(&twl6040->ready,
+						msecs_to_jiffies(144));
+	if (!time_left) {
+		u8 intid;
+
+		dev_warn(twl6040->dev, "timeout waiting for READYINT\n");
+		intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
+		if (!(intid & TWL6040_READYINT)) {
+			dev_err(twl6040->dev, "automatic power-up failed\n");
+			gpio_set_value(twl6040->audpwron, 0);
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+int twl6040_power(struct twl6040 *twl6040, int on)
+{
+	int ret = 0;
+
+	mutex_lock(&twl6040->mutex);
+
+	if (on) {
+		/* already powered-up */
+		if (twl6040->power_count++)
+			goto out;
+
+		if (gpio_is_valid(twl6040->audpwron)) {
+			/* use automatic power-up sequence */
+			ret = twl6040_power_up_automatic(twl6040);
+			if (ret) {
+				twl6040->power_count = 0;
+				goto out;
+			}
+		} else {
+			/* use manual power-up sequence */
+			ret = twl6040_power_up_manual(twl6040);
+			if (ret) {
+				twl6040->power_count = 0;
+				goto out;
+			}
+		}
+		/* Default PLL configuration after power up */
+		twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
+		twl6040->sysclk = 19200000;
+		twl6040->mclk = 32768;
+	} else {
+		/* already powered-down */
+		if (!twl6040->power_count) {
+			dev_err(twl6040->dev,
+				"device is already powered-off\n");
+			ret = -EPERM;
+			goto out;
+		}
+
+		if (--twl6040->power_count)
+			goto out;
+
+		if (gpio_is_valid(twl6040->audpwron)) {
+			/* use AUDPWRON line */
+			gpio_set_value(twl6040->audpwron, 0);
+
+			/* power-down sequence latency */
+			usleep_range(500, 700);
+		} else {
+			/* use manual power-down sequence */
+			twl6040_power_down_manual(twl6040);
+		}
+		twl6040->sysclk = 0;
+		twl6040->mclk = 0;
+	}
+
+out:
+	mutex_unlock(&twl6040->mutex);
+	return ret;
+}
+EXPORT_SYMBOL(twl6040_power);
+
+int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
+		    unsigned int freq_in, unsigned int freq_out)
+{
+	u8 hppllctl, lppllctl;
+	int ret = 0;
+
+	mutex_lock(&twl6040->mutex);
+
+	hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);
+	lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
+
+	/* Force full reconfiguration when switching between PLL */
+	if (pll_id != twl6040->pll) {
+		twl6040->sysclk = 0;
+		twl6040->mclk = 0;
+	}
+
+	switch (pll_id) {
+	case TWL6040_SYSCLK_SEL_LPPLL:
+		/* low-power PLL divider */
+		/* Change the sysclk configuration only if it has been canged */
+		if (twl6040->sysclk != freq_out) {
+			switch (freq_out) {
+			case 17640000:
+				lppllctl |= TWL6040_LPLLFIN;
+				break;
+			case 19200000:
+				lppllctl &= ~TWL6040_LPLLFIN;
+				break;
+			default:
+				dev_err(twl6040->dev,
+					"freq_out %d not supported\n",
+					freq_out);
+				ret = -EINVAL;
+				goto pll_out;
+			}
+			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+					  lppllctl);
+		}
+
+		/* The PLL in use has not been change, we can exit */
+		if (twl6040->pll == pll_id)
+			break;
+
+		switch (freq_in) {
+		case 32768:
+			lppllctl |= TWL6040_LPLLENA;
+			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+					  lppllctl);
+			mdelay(5);
+			lppllctl &= ~TWL6040_HPLLSEL;
+			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+					  lppllctl);
+			hppllctl &= ~TWL6040_HPLLENA;
+			twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
+					  hppllctl);
+			break;
+		default:
+			dev_err(twl6040->dev,
+				"freq_in %d not supported\n", freq_in);
+			ret = -EINVAL;
+			goto pll_out;
+		}
+		break;
+	case TWL6040_SYSCLK_SEL_HPPLL:
+		/* high-performance PLL can provide only 19.2 MHz */
+		if (freq_out != 19200000) {
+			dev_err(twl6040->dev,
+				"freq_out %d not supported\n", freq_out);
+			ret = -EINVAL;
+			goto pll_out;
+		}
+
+		if (twl6040->mclk != freq_in) {
+			hppllctl &= ~TWL6040_MCLK_MSK;
+
+			switch (freq_in) {
+			case 12000000:
+				/* PLL enabled, active mode */
+				hppllctl |= TWL6040_MCLK_12000KHZ |
+					    TWL6040_HPLLENA;
+				break;
+			case 19200000:
+				/*
+				* PLL disabled
+				* (enable PLL if MCLK jitter quality
+				*  doesn't meet specification)
+				*/
+				hppllctl |= TWL6040_MCLK_19200KHZ;
+				break;
+			case 26000000:
+				/* PLL enabled, active mode */
+				hppllctl |= TWL6040_MCLK_26000KHZ |
+					    TWL6040_HPLLENA;
+				break;
+			case 38400000:
+				/* PLL enabled, active mode */
+				hppllctl |= TWL6040_MCLK_38400KHZ |
+					    TWL6040_HPLLENA;
+				break;
+			default:
+				dev_err(twl6040->dev,
+					"freq_in %d not supported\n", freq_in);
+				ret = -EINVAL;
+				goto pll_out;
+			}
+
+			/*
+			 * enable clock slicer to ensure input waveform is
+			 * square
+			 */
+			hppllctl |= TWL6040_HPLLSQRENA;
+
+			twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
+					  hppllctl);
+			usleep_range(500, 700);
+			lppllctl |= TWL6040_HPLLSEL;
+			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+					  lppllctl);
+			lppllctl &= ~TWL6040_LPLLENA;
+			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
+					  lppllctl);
+		}
+		break;
+	default:
+		dev_err(twl6040->dev, "unknown pll id %d\n", pll_id);
+		ret = -EINVAL;
+		goto pll_out;
+	}
+
+	twl6040->sysclk = freq_out;
+	twl6040->mclk = freq_in;
+	twl6040->pll = pll_id;
+
+pll_out:
+	mutex_unlock(&twl6040->mutex);
+	return ret;
+}
+EXPORT_SYMBOL(twl6040_set_pll);
+
+int twl6040_get_pll(struct twl6040 *twl6040)
+{
+	if (twl6040->power_count)
+		return twl6040->pll;
+	else
+		return -ENODEV;
+}
+EXPORT_SYMBOL(twl6040_get_pll);
+
+unsigned int twl6040_get_sysclk(struct twl6040 *twl6040)
+{
+	return twl6040->sysclk;
+}
+EXPORT_SYMBOL(twl6040_get_sysclk);
+
+/* Get the combined status of the vibra control register */
+int twl6040_get_vibralr_status(struct twl6040 *twl6040)
+{
+	u8 status;
+
+	status = twl6040->vibra_ctrl_cache[0] | twl6040->vibra_ctrl_cache[1];
+	status &= (TWL6040_VIBENA | TWL6040_VIBSEL);
+
+	return status;
+}
+EXPORT_SYMBOL(twl6040_get_vibralr_status);
+
+static struct resource twl6040_vibra_rsrc[] = {
+	{
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource twl6040_codec_rsrc[] = {
+	{
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static bool twl6040_readable_reg(struct device *dev, unsigned int reg)
+{
+	/* Register 0 is not readable */
+	if (!reg)
+		return false;
+	return true;
+}
+
+static struct regmap_config twl6040_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = TWL6040_REG_STATUS, /* 0x2e */
+
+	.readable_reg = twl6040_readable_reg,
+};
+
+static const struct regmap_irq twl6040_irqs[] = {
+	{ .reg_offset = 0, .mask = TWL6040_THINT, },
+	{ .reg_offset = 0, .mask = TWL6040_PLUGINT | TWL6040_UNPLUGINT, },
+	{ .reg_offset = 0, .mask = TWL6040_HOOKINT, },
+	{ .reg_offset = 0, .mask = TWL6040_HFINT, },
+	{ .reg_offset = 0, .mask = TWL6040_VIBINT, },
+	{ .reg_offset = 0, .mask = TWL6040_READYINT, },
+};
+
+static struct regmap_irq_chip twl6040_irq_chip = {
+	.name = "twl6040",
+	.irqs = twl6040_irqs,
+	.num_irqs = ARRAY_SIZE(twl6040_irqs),
+
+	.num_regs = 1,
+	.status_base = TWL6040_REG_INTID,
+	.mask_base = TWL6040_REG_INTMR,
+};
+
+static int __devinit twl6040_probe(struct i2c_client *client,
+				     const struct i2c_device_id *id)
+{
+	struct twl6040_platform_data *pdata = client->dev.platform_data;
+	struct device_node *node = client->dev.of_node;
+	struct twl6040 *twl6040;
+	struct mfd_cell *cell = NULL;
+	int irq, ret, children = 0;
+
+	if (!pdata && !node) {
+		dev_err(&client->dev, "Platform data is missing\n");
+		return -EINVAL;
+	}
+
+	/* In order to operate correctly we need valid interrupt config */
+	if (!client->irq) {
+		dev_err(&client->dev, "Invalid IRQ configuration\n");
+		return -EINVAL;
+	}
+
+	twl6040 = devm_kzalloc(&client->dev, sizeof(struct twl6040),
+			       GFP_KERNEL);
+	if (!twl6040) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	twl6040->regmap = devm_regmap_init_i2c(client, &twl6040_regmap_config);
+	if (IS_ERR(twl6040->regmap)) {
+		ret = PTR_ERR(twl6040->regmap);
+		goto err;
+	}
+
+	i2c_set_clientdata(client, twl6040);
+
+	twl6040->supplies[0].supply = "vio";
+	twl6040->supplies[1].supply = "v2v1";
+	ret = regulator_bulk_get(&client->dev, TWL6040_NUM_SUPPLIES,
+				 twl6040->supplies);
+	if (ret != 0) {
+		dev_err(&client->dev, "Failed to get supplies: %d\n", ret);
+		goto regulator_get_err;
+	}
+
+	ret = regulator_bulk_enable(TWL6040_NUM_SUPPLIES, twl6040->supplies);
+	if (ret != 0) {
+		dev_err(&client->dev, "Failed to enable supplies: %d\n", ret);
+		goto power_err;
+	}
+
+	twl6040->dev = &client->dev;
+	twl6040->irq = client->irq;
+
+	mutex_init(&twl6040->mutex);
+	init_completion(&twl6040->ready);
+
+	twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
+
+	/* ERRATA: Automatic power-up is not possible in ES1.0 */
+	if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0) {
+		if (pdata)
+			twl6040->audpwron = pdata->audpwron_gpio;
+		else
+			twl6040->audpwron = of_get_named_gpio(node,
+						"ti,audpwron-gpio", 0);
+	} else
+		twl6040->audpwron = -EINVAL;
+
+	if (gpio_is_valid(twl6040->audpwron)) {
+		ret = gpio_request_one(twl6040->audpwron, GPIOF_OUT_INIT_LOW,
+				       "audpwron");
+		if (ret)
+			goto gpio_err;
+	}
+
+	ret = regmap_add_irq_chip(twl6040->regmap, twl6040->irq,
+			IRQF_ONESHOT, 0, &twl6040_irq_chip,
+			&twl6040->irq_data);
+	if (ret < 0)
+		goto irq_init_err;
+
+	twl6040->irq_ready = regmap_irq_get_virq(twl6040->irq_data,
+					       TWL6040_IRQ_READY);
+	twl6040->irq_th = regmap_irq_get_virq(twl6040->irq_data,
+					       TWL6040_IRQ_TH);
+
+	ret = request_threaded_irq(twl6040->irq_ready, NULL,
+				   twl6040_readyint_handler, IRQF_ONESHOT,
+				   "twl6040_irq_ready", twl6040);
+	if (ret) {
+		dev_err(twl6040->dev, "READY IRQ request failed: %d\n", ret);
+		goto readyirq_err;
+	}
+
+	ret = request_threaded_irq(twl6040->irq_th, NULL,
+				   twl6040_thint_handler, IRQF_ONESHOT,
+				   "twl6040_irq_th", twl6040);
+	if (ret) {
+		dev_err(twl6040->dev, "Thermal IRQ request failed: %d\n", ret);
+		goto thirq_err;
+	}
+
+	/* dual-access registers controlled by I2C only */
+	twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL);
+
+	/*
+	 * The main functionality of twl6040 to provide audio on OMAP4+ systems.
+	 * We can add the ASoC codec child whenever this driver has been loaded.
+	 * The ASoC codec can work without pdata, pass the platform_data only if
+	 * it has been provided.
+	 */
+	irq = regmap_irq_get_virq(twl6040->irq_data, TWL6040_IRQ_PLUG);
+	cell = &twl6040->cells[children];
+	cell->name = "twl6040-codec";
+	twl6040_codec_rsrc[0].start = irq;
+	twl6040_codec_rsrc[0].end = irq;
+	cell->resources = twl6040_codec_rsrc;
+	cell->num_resources = ARRAY_SIZE(twl6040_codec_rsrc);
+	if (pdata && pdata->codec) {
+		cell->platform_data = pdata->codec;
+		cell->pdata_size = sizeof(*pdata->codec);
+	}
+	children++;
+
+	if (twl6040_has_vibra(pdata, node)) {
+		irq = regmap_irq_get_virq(twl6040->irq_data, TWL6040_IRQ_VIB);
+
+		cell = &twl6040->cells[children];
+		cell->name = "twl6040-vibra";
+		twl6040_vibra_rsrc[0].start = irq;
+		twl6040_vibra_rsrc[0].end = irq;
+		cell->resources = twl6040_vibra_rsrc;
+		cell->num_resources = ARRAY_SIZE(twl6040_vibra_rsrc);
+
+		if (pdata && pdata->vibra) {
+			cell->platform_data = pdata->vibra;
+			cell->pdata_size = sizeof(*pdata->vibra);
+		}
+		children++;
+	}
+
+	/*
+	 * Enable the GPO driver in the following cases:
+	 * DT booted kernel or legacy boot with valid gpo platform_data
+	 */
+	if (!pdata || (pdata && pdata->gpo)) {
+		cell = &twl6040->cells[children];
+		cell->name = "twl6040-gpo";
+
+		if (pdata) {
+			cell->platform_data = pdata->gpo;
+			cell->pdata_size = sizeof(*pdata->gpo);
+		}
+		children++;
+	}
+
+	ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children,
+			      NULL, 0, NULL);
+	if (ret)
+		goto mfd_err;
+
+	return 0;
+
+mfd_err:
+	free_irq(twl6040->irq_th, twl6040);
+thirq_err:
+	free_irq(twl6040->irq_ready, twl6040);
+readyirq_err:
+	regmap_del_irq_chip(twl6040->irq, twl6040->irq_data);
+irq_init_err:
+	if (gpio_is_valid(twl6040->audpwron))
+		gpio_free(twl6040->audpwron);
+gpio_err:
+	regulator_bulk_disable(TWL6040_NUM_SUPPLIES, twl6040->supplies);
+power_err:
+	regulator_bulk_free(TWL6040_NUM_SUPPLIES, twl6040->supplies);
+regulator_get_err:
+	i2c_set_clientdata(client, NULL);
+err:
+	return ret;
+}
+
+static int __devexit twl6040_remove(struct i2c_client *client)
+{
+	struct twl6040 *twl6040 = i2c_get_clientdata(client);
+
+	if (twl6040->power_count)
+		twl6040_power(twl6040, 0);
+
+	if (gpio_is_valid(twl6040->audpwron))
+		gpio_free(twl6040->audpwron);
+
+	free_irq(twl6040->irq_ready, twl6040);
+	free_irq(twl6040->irq_th, twl6040);
+	regmap_del_irq_chip(twl6040->irq, twl6040->irq_data);
+
+	mfd_remove_devices(&client->dev);
+	i2c_set_clientdata(client, NULL);
+
+	regulator_bulk_disable(TWL6040_NUM_SUPPLIES, twl6040->supplies);
+	regulator_bulk_free(TWL6040_NUM_SUPPLIES, twl6040->supplies);
+
+	return 0;
+}
+
+static const struct i2c_device_id twl6040_i2c_id[] = {
+	{ "twl6040", 0, },
+	{ "twl6041", 0, },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, twl6040_i2c_id);
+
+static struct i2c_driver twl6040_driver = {
+	.driver = {
+		.name = "twl6040",
+		.owner = THIS_MODULE,
+	},
+	.probe		= twl6040_probe,
+	.remove		= __devexit_p(twl6040_remove),
+	.id_table	= twl6040_i2c_id,
+};
+
+module_i2c_driver(twl6040_driver);
+
+MODULE_DESCRIPTION("TWL6040 MFD");
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
+MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:twl6040");
diff --git a/drivers/mfd/vexpress-config.c b/drivers/mfd/vexpress-config.c
new file mode 100644
index 0000000..fae15d8
--- /dev/null
+++ b/drivers/mfd/vexpress-config.c
@@ -0,0 +1,277 @@
+/*
+ * This program is free software; you can 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#define pr_fmt(fmt) "vexpress-config: " fmt
+
+#include <linux/bitops.h>
+#include <linux/completion.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/vexpress.h>
+
+
+#define VEXPRESS_CONFIG_MAX_BRIDGES 2
+
+struct vexpress_config_bridge {
+	struct device_node *node;
+	struct vexpress_config_bridge_info *info;
+	struct list_head transactions;
+	spinlock_t transactions_lock;
+} vexpress_config_bridges[VEXPRESS_CONFIG_MAX_BRIDGES];
+
+static DECLARE_BITMAP(vexpress_config_bridges_map,
+		ARRAY_SIZE(vexpress_config_bridges));
+static DEFINE_MUTEX(vexpress_config_bridges_mutex);
+
+struct vexpress_config_bridge *vexpress_config_bridge_register(
+		struct device_node *node,
+		struct vexpress_config_bridge_info *info)
+{
+	struct vexpress_config_bridge *bridge;
+	int i;
+
+	pr_debug("Registering bridge '%s'\n", info->name);
+
+	mutex_lock(&vexpress_config_bridges_mutex);
+	i = find_first_zero_bit(vexpress_config_bridges_map,
+			ARRAY_SIZE(vexpress_config_bridges));
+	if (i >= ARRAY_SIZE(vexpress_config_bridges)) {
+		pr_err("Can't register more bridges!\n");
+		mutex_unlock(&vexpress_config_bridges_mutex);
+		return NULL;
+	}
+	__set_bit(i, vexpress_config_bridges_map);
+	bridge = &vexpress_config_bridges[i];
+
+	bridge->node = node;
+	bridge->info = info;
+	INIT_LIST_HEAD(&bridge->transactions);
+	spin_lock_init(&bridge->transactions_lock);
+
+	mutex_unlock(&vexpress_config_bridges_mutex);
+
+	return bridge;
+}
+
+void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge)
+{
+	struct vexpress_config_bridge __bridge = *bridge;
+	int i;
+
+	mutex_lock(&vexpress_config_bridges_mutex);
+	for (i = 0; i < ARRAY_SIZE(vexpress_config_bridges); i++)
+		if (&vexpress_config_bridges[i] == bridge)
+			__clear_bit(i, vexpress_config_bridges_map);
+	mutex_unlock(&vexpress_config_bridges_mutex);
+
+	WARN_ON(!list_empty(&__bridge.transactions));
+	while (!list_empty(&__bridge.transactions))
+		cpu_relax();
+}
+
+
+struct vexpress_config_func {
+	struct vexpress_config_bridge *bridge;
+	void *func;
+};
+
+struct vexpress_config_func *__vexpress_config_func_get(struct device *dev,
+		struct device_node *node)
+{
+	struct device_node *bridge_node;
+	struct vexpress_config_func *func;
+	int i;
+
+	if (WARN_ON(dev && node && dev->of_node != node))
+		return NULL;
+	if (dev && !node)
+		node = dev->of_node;
+
+	func = kzalloc(sizeof(*func), GFP_KERNEL);
+	if (!func)
+		return NULL;
+
+	bridge_node = of_node_get(node);
+	while (bridge_node) {
+		const __be32 *prop = of_get_property(bridge_node,
+				"arm,vexpress,config-bridge", NULL);
+
+		if (prop) {
+			bridge_node = of_find_node_by_phandle(
+					be32_to_cpup(prop));
+			break;
+		}
+
+		bridge_node = of_get_next_parent(bridge_node);
+	}
+
+	mutex_lock(&vexpress_config_bridges_mutex);
+	for (i = 0; i < ARRAY_SIZE(vexpress_config_bridges); i++) {
+		struct vexpress_config_bridge *bridge =
+				&vexpress_config_bridges[i];
+
+		if (test_bit(i, vexpress_config_bridges_map) &&
+				bridge->node == bridge_node) {
+			func->bridge = bridge;
+			func->func = bridge->info->func_get(dev, node);
+			break;
+		}
+	}
+	mutex_unlock(&vexpress_config_bridges_mutex);
+
+	if (!func->func) {
+		of_node_put(node);
+		kfree(func);
+		return NULL;
+	}
+
+	return func;
+}
+
+void vexpress_config_func_put(struct vexpress_config_func *func)
+{
+	func->bridge->info->func_put(func->func);
+	of_node_put(func->bridge->node);
+	kfree(func);
+}
+
+
+struct vexpress_config_trans {
+	struct vexpress_config_func *func;
+	int offset;
+	bool write;
+	u32 *data;
+	int status;
+	struct completion completion;
+	struct list_head list;
+};
+
+static void vexpress_config_dump_trans(const char *what,
+		struct vexpress_config_trans *trans)
+{
+	pr_debug("%s %s trans %p func 0x%p offset %d data 0x%x status %d\n",
+			what, trans->write ? "write" : "read", trans,
+			trans->func->func, trans->offset,
+			trans->data ? *trans->data : 0, trans->status);
+}
+
+static int vexpress_config_schedule(struct vexpress_config_trans *trans)
+{
+	int status;
+	struct vexpress_config_bridge *bridge = trans->func->bridge;
+	unsigned long flags;
+
+	init_completion(&trans->completion);
+	trans->status = -EFAULT;
+
+	spin_lock_irqsave(&bridge->transactions_lock, flags);
+
+	vexpress_config_dump_trans("Executing", trans);
+
+	if (list_empty(&bridge->transactions))
+		status = bridge->info->func_exec(trans->func->func,
+				trans->offset, trans->write, trans->data);
+	else
+		status = VEXPRESS_CONFIG_STATUS_WAIT;
+
+	switch (status) {
+	case VEXPRESS_CONFIG_STATUS_DONE:
+		vexpress_config_dump_trans("Finished", trans);
+		trans->status = status;
+		break;
+	case VEXPRESS_CONFIG_STATUS_WAIT:
+		list_add_tail(&trans->list, &bridge->transactions);
+		break;
+	}
+
+	spin_unlock_irqrestore(&bridge->transactions_lock, flags);
+
+	return status;
+}
+
+void vexpress_config_complete(struct vexpress_config_bridge *bridge,
+		int status)
+{
+	struct vexpress_config_trans *trans;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bridge->transactions_lock, flags);
+
+	trans = list_first_entry(&bridge->transactions,
+			struct vexpress_config_trans, list);
+	vexpress_config_dump_trans("Completed", trans);
+
+	trans->status = status;
+	list_del(&trans->list);
+
+	if (!list_empty(&bridge->transactions)) {
+		vexpress_config_dump_trans("Pending", trans);
+
+		bridge->info->func_exec(trans->func->func, trans->offset,
+				trans->write, trans->data);
+	}
+	spin_unlock_irqrestore(&bridge->transactions_lock, flags);
+
+	complete(&trans->completion);
+}
+
+int vexpress_config_wait(struct vexpress_config_trans *trans)
+{
+	wait_for_completion(&trans->completion);
+
+	return trans->status;
+}
+
+
+int vexpress_config_read(struct vexpress_config_func *func, int offset,
+		u32 *data)
+{
+	struct vexpress_config_trans trans = {
+		.func = func,
+		.offset = offset,
+		.write = false,
+		.data = data,
+		.status = 0,
+	};
+	int status = vexpress_config_schedule(&trans);
+
+	if (status == VEXPRESS_CONFIG_STATUS_WAIT)
+		status = vexpress_config_wait(&trans);
+
+	return status;
+}
+EXPORT_SYMBOL(vexpress_config_read);
+
+int vexpress_config_write(struct vexpress_config_func *func, int offset,
+		u32 data)
+{
+	struct vexpress_config_trans trans = {
+		.func = func,
+		.offset = offset,
+		.write = true,
+		.data = &data,
+		.status = 0,
+	};
+	int status = vexpress_config_schedule(&trans);
+
+	if (status == VEXPRESS_CONFIG_STATUS_WAIT)
+		status = vexpress_config_wait(&trans);
+
+	return status;
+}
+EXPORT_SYMBOL(vexpress_config_write);
diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c
new file mode 100644
index 0000000..059d6b1
--- /dev/null
+++ b/drivers/mfd/vexpress-sysreg.c
@@ -0,0 +1,552 @@
+/*
+ * This program is free software; you can 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/leds.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/timer.h>
+#include <linux/vexpress.h>
+
+#define SYS_ID			0x000
+#define SYS_SW			0x004
+#define SYS_LED			0x008
+#define SYS_100HZ		0x024
+#define SYS_FLAGS		0x030
+#define SYS_FLAGSSET		0x030
+#define SYS_FLAGSCLR		0x034
+#define SYS_NVFLAGS		0x038
+#define SYS_NVFLAGSSET		0x038
+#define SYS_NVFLAGSCLR		0x03c
+#define SYS_MCI			0x048
+#define SYS_FLASH		0x04c
+#define SYS_CFGSW		0x058
+#define SYS_24MHZ		0x05c
+#define SYS_MISC		0x060
+#define SYS_DMA			0x064
+#define SYS_PROCID0		0x084
+#define SYS_PROCID1		0x088
+#define SYS_CFGDATA		0x0a0
+#define SYS_CFGCTRL		0x0a4
+#define SYS_CFGSTAT		0x0a8
+
+#define SYS_HBI_MASK		0xfff
+#define SYS_ID_HBI_SHIFT	16
+#define SYS_PROCIDx_HBI_SHIFT	0
+
+#define SYS_MCI_CARDIN		(1 << 0)
+#define SYS_MCI_WPROT		(1 << 1)
+
+#define SYS_FLASH_WPn		(1 << 0)
+
+#define SYS_MISC_MASTERSITE	(1 << 14)
+
+#define SYS_CFGCTRL_START	(1 << 31)
+#define SYS_CFGCTRL_WRITE	(1 << 30)
+#define SYS_CFGCTRL_DCC(n)	(((n) & 0xf) << 26)
+#define SYS_CFGCTRL_FUNC(n)	(((n) & 0x3f) << 20)
+#define SYS_CFGCTRL_SITE(n)	(((n) & 0x3) << 16)
+#define SYS_CFGCTRL_POSITION(n)	(((n) & 0xf) << 12)
+#define SYS_CFGCTRL_DEVICE(n)	(((n) & 0xfff) << 0)
+
+#define SYS_CFGSTAT_ERR		(1 << 1)
+#define SYS_CFGSTAT_COMPLETE	(1 << 0)
+
+
+static void __iomem *vexpress_sysreg_base;
+static struct device *vexpress_sysreg_dev;
+static int vexpress_master_site;
+
+
+void vexpress_flags_set(u32 data)
+{
+	writel(~0, vexpress_sysreg_base + SYS_FLAGSCLR);
+	writel(data, vexpress_sysreg_base + SYS_FLAGSSET);
+}
+
+u32 vexpress_get_procid(int site)
+{
+	if (site == VEXPRESS_SITE_MASTER)
+		site = vexpress_master_site;
+
+	return readl(vexpress_sysreg_base + (site == VEXPRESS_SITE_DB1 ?
+			SYS_PROCID0 : SYS_PROCID1));
+}
+
+u32 vexpress_get_hbi(int site)
+{
+	u32 id;
+
+	switch (site) {
+	case VEXPRESS_SITE_MB:
+		id = readl(vexpress_sysreg_base + SYS_ID);
+		return (id >> SYS_ID_HBI_SHIFT) & SYS_HBI_MASK;
+	case VEXPRESS_SITE_MASTER:
+	case VEXPRESS_SITE_DB1:
+	case VEXPRESS_SITE_DB2:
+		id = vexpress_get_procid(site);
+		return (id >> SYS_PROCIDx_HBI_SHIFT) & SYS_HBI_MASK;
+	}
+
+	return ~0;
+}
+
+void __iomem *vexpress_get_24mhz_clock_base(void)
+{
+	return vexpress_sysreg_base + SYS_24MHZ;
+}
+
+
+static void vexpress_sysreg_find_prop(struct device_node *node,
+		const char *name, u32 *val)
+{
+	of_node_get(node);
+	while (node) {
+		if (of_property_read_u32(node, name, val) == 0) {
+			of_node_put(node);
+			return;
+		}
+		node = of_get_next_parent(node);
+	}
+}
+
+unsigned __vexpress_get_site(struct device *dev, struct device_node *node)
+{
+	u32 site = 0;
+
+	WARN_ON(dev && node && dev->of_node != node);
+	if (dev && !node)
+		node = dev->of_node;
+
+	if (node) {
+		vexpress_sysreg_find_prop(node, "arm,vexpress,site", &site);
+	} else if (dev && dev->bus == &platform_bus_type) {
+		struct platform_device *pdev = to_platform_device(dev);
+
+		if (pdev->num_resources == 1 &&
+				pdev->resource[0].flags == IORESOURCE_BUS)
+			site = pdev->resource[0].start;
+	} else if (dev && strncmp(dev_name(dev), "ct:", 3) == 0) {
+		site = VEXPRESS_SITE_MASTER;
+	}
+
+	if (site == VEXPRESS_SITE_MASTER)
+		site = vexpress_master_site;
+
+	return site;
+}
+
+
+struct vexpress_sysreg_config_func {
+	u32 template;
+	u32 device;
+};
+
+static struct vexpress_config_bridge *vexpress_sysreg_config_bridge;
+static struct timer_list vexpress_sysreg_config_timer;
+static u32 *vexpress_sysreg_config_data;
+static int vexpress_sysreg_config_tries;
+
+static void *vexpress_sysreg_config_func_get(struct device *dev,
+		struct device_node *node)
+{
+	struct vexpress_sysreg_config_func *config_func;
+	u32 site;
+	u32 position = 0;
+	u32 dcc = 0;
+	u32 func_device[2];
+	int err = -EFAULT;
+
+	if (node) {
+		of_node_get(node);
+		vexpress_sysreg_find_prop(node, "arm,vexpress,site", &site);
+		vexpress_sysreg_find_prop(node, "arm,vexpress,position",
+				&position);
+		vexpress_sysreg_find_prop(node, "arm,vexpress,dcc", &dcc);
+		err = of_property_read_u32_array(node,
+				"arm,vexpress-sysreg,func", func_device,
+				ARRAY_SIZE(func_device));
+		of_node_put(node);
+	} else if (dev && dev->bus == &platform_bus_type) {
+		struct platform_device *pdev = to_platform_device(dev);
+
+		if (pdev->num_resources == 1 &&
+				pdev->resource[0].flags == IORESOURCE_BUS) {
+			site = pdev->resource[0].start;
+			func_device[0] = pdev->resource[0].end;
+			func_device[1] = pdev->id;
+			err = 0;
+		}
+	}
+	if (err)
+		return NULL;
+
+	config_func = kzalloc(sizeof(*config_func), GFP_KERNEL);
+	if (!config_func)
+		return NULL;
+
+	config_func->template = SYS_CFGCTRL_DCC(dcc);
+	config_func->template |= SYS_CFGCTRL_FUNC(func_device[0]);
+	config_func->template |= SYS_CFGCTRL_SITE(site == VEXPRESS_SITE_MASTER ?
+			vexpress_master_site : site);
+	config_func->template |= SYS_CFGCTRL_POSITION(position);
+	config_func->device |= func_device[1];
+
+	dev_dbg(vexpress_sysreg_dev, "func 0x%p = 0x%x, %d\n", config_func,
+			config_func->template, config_func->device);
+
+	return config_func;
+}
+
+static void vexpress_sysreg_config_func_put(void *func)
+{
+	kfree(func);
+}
+
+static int vexpress_sysreg_config_func_exec(void *func, int offset,
+		bool write, u32 *data)
+{
+	int status;
+	struct vexpress_sysreg_config_func *config_func = func;
+	u32 command;
+
+	if (WARN_ON(!vexpress_sysreg_base))
+		return -ENOENT;
+
+	command = readl(vexpress_sysreg_base + SYS_CFGCTRL);
+	if (WARN_ON(command & SYS_CFGCTRL_START))
+		return -EBUSY;
+
+	command = SYS_CFGCTRL_START;
+	command |= write ? SYS_CFGCTRL_WRITE : 0;
+	command |= config_func->template;
+	command |= SYS_CFGCTRL_DEVICE(config_func->device + offset);
+
+	/* Use a canary for reads */
+	if (!write)
+		*data = 0xdeadbeef;
+
+	dev_dbg(vexpress_sysreg_dev, "command %x, data %x\n",
+			command, *data);
+	writel(*data, vexpress_sysreg_base + SYS_CFGDATA);
+	writel(0, vexpress_sysreg_base + SYS_CFGSTAT);
+	writel(command, vexpress_sysreg_base + SYS_CFGCTRL);
+	mb();
+
+	if (vexpress_sysreg_dev) {
+		/* Schedule completion check */
+		if (!write)
+			vexpress_sysreg_config_data = data;
+		vexpress_sysreg_config_tries = 100;
+		mod_timer(&vexpress_sysreg_config_timer,
+				jiffies + usecs_to_jiffies(100));
+		status = VEXPRESS_CONFIG_STATUS_WAIT;
+	} else {
+		/* Early execution, no timer available, have to spin */
+		u32 cfgstat;
+
+		do {
+			cpu_relax();
+			cfgstat = readl(vexpress_sysreg_base + SYS_CFGSTAT);
+		} while (!cfgstat);
+
+		if (!write && (cfgstat & SYS_CFGSTAT_COMPLETE))
+			*data = readl(vexpress_sysreg_base + SYS_CFGDATA);
+		status = VEXPRESS_CONFIG_STATUS_DONE;
+
+		if (cfgstat & SYS_CFGSTAT_ERR)
+			status = -EINVAL;
+	}
+
+	return status;
+}
+
+struct vexpress_config_bridge_info vexpress_sysreg_config_bridge_info = {
+	.name = "vexpress-sysreg",
+	.func_get = vexpress_sysreg_config_func_get,
+	.func_put = vexpress_sysreg_config_func_put,
+	.func_exec = vexpress_sysreg_config_func_exec,
+};
+
+static void vexpress_sysreg_config_complete(unsigned long data)
+{
+	int status = VEXPRESS_CONFIG_STATUS_DONE;
+	u32 cfgstat = readl(vexpress_sysreg_base + SYS_CFGSTAT);
+
+	if (cfgstat & SYS_CFGSTAT_ERR)
+		status = -EINVAL;
+	if (!vexpress_sysreg_config_tries--)
+		status = -ETIMEDOUT;
+
+	if (status < 0) {
+		dev_err(vexpress_sysreg_dev, "error %d\n", status);
+	} else if (!(cfgstat & SYS_CFGSTAT_COMPLETE)) {
+		mod_timer(&vexpress_sysreg_config_timer,
+				jiffies + usecs_to_jiffies(50));
+		return;
+	}
+
+	if (vexpress_sysreg_config_data) {
+		*vexpress_sysreg_config_data = readl(vexpress_sysreg_base +
+				SYS_CFGDATA);
+		dev_dbg(vexpress_sysreg_dev, "read data %x\n",
+				*vexpress_sysreg_config_data);
+		vexpress_sysreg_config_data = NULL;
+	}
+
+	vexpress_config_complete(vexpress_sysreg_config_bridge, status);
+}
+
+
+void __init vexpress_sysreg_early_init(void __iomem *base)
+{
+	struct device_node *node = of_find_compatible_node(NULL, NULL,
+			"arm,vexpress-sysreg");
+
+	if (node)
+		base = of_iomap(node, 0);
+
+	if (WARN_ON(!base))
+		return;
+
+	vexpress_sysreg_base = base;
+
+	if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE)
+		vexpress_master_site = VEXPRESS_SITE_DB2;
+	else
+		vexpress_master_site = VEXPRESS_SITE_DB1;
+
+	vexpress_sysreg_config_bridge = vexpress_config_bridge_register(
+			node, &vexpress_sysreg_config_bridge_info);
+	WARN_ON(!vexpress_sysreg_config_bridge);
+}
+
+void __init vexpress_sysreg_of_early_init(void)
+{
+	vexpress_sysreg_early_init(NULL);
+}
+
+
+static struct vexpress_sysreg_gpio {
+	unsigned long reg;
+	u32 value;
+} vexpress_sysreg_gpios[] = {
+	[VEXPRESS_GPIO_MMC_CARDIN] = {
+		.reg = SYS_MCI,
+		.value = SYS_MCI_CARDIN,
+	},
+	[VEXPRESS_GPIO_MMC_WPROT] = {
+		.reg = SYS_MCI,
+		.value = SYS_MCI_WPROT,
+	},
+	[VEXPRESS_GPIO_FLASH_WPn] = {
+		.reg = SYS_FLASH,
+		.value = SYS_FLASH_WPn,
+	},
+};
+
+static int vexpress_sysreg_gpio_direction_input(struct gpio_chip *chip,
+				       unsigned offset)
+{
+	return 0;
+}
+
+static int vexpress_sysreg_gpio_direction_output(struct gpio_chip *chip,
+						unsigned offset, int value)
+{
+	return 0;
+}
+
+static int vexpress_sysreg_gpio_get(struct gpio_chip *chip,
+				       unsigned offset)
+{
+	struct vexpress_sysreg_gpio *gpio = &vexpress_sysreg_gpios[offset];
+	u32 reg_value = readl(vexpress_sysreg_base + gpio->reg);
+
+	return !!(reg_value & gpio->value);
+}
+
+static void vexpress_sysreg_gpio_set(struct gpio_chip *chip,
+				       unsigned offset, int value)
+{
+	struct vexpress_sysreg_gpio *gpio = &vexpress_sysreg_gpios[offset];
+	u32 reg_value = readl(vexpress_sysreg_base + gpio->reg);
+
+	if (value)
+		reg_value |= gpio->value;
+	else
+		reg_value &= ~gpio->value;
+
+	writel(reg_value, vexpress_sysreg_base + gpio->reg);
+}
+
+static struct gpio_chip vexpress_sysreg_gpio_chip = {
+	.label = "vexpress-sysreg",
+	.direction_input = vexpress_sysreg_gpio_direction_input,
+	.direction_output = vexpress_sysreg_gpio_direction_output,
+	.get = vexpress_sysreg_gpio_get,
+	.set = vexpress_sysreg_gpio_set,
+	.ngpio = ARRAY_SIZE(vexpress_sysreg_gpios),
+	.base = 0,
+};
+
+
+static ssize_t vexpress_sysreg_sys_id_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "0x%08x\n", readl(vexpress_sysreg_base + SYS_ID));
+}
+
+DEVICE_ATTR(sys_id, S_IRUGO, vexpress_sysreg_sys_id_show, NULL);
+
+static int __devinit vexpress_sysreg_probe(struct platform_device *pdev)
+{
+	int err;
+	struct resource *res = platform_get_resource(pdev,
+			IORESOURCE_MEM, 0);
+
+	if (!devm_request_mem_region(&pdev->dev, res->start,
+			resource_size(res), pdev->name)) {
+		dev_err(&pdev->dev, "Failed to request memory region!\n");
+		return -EBUSY;
+	}
+
+	if (!vexpress_sysreg_base)
+		vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start,
+				resource_size(res));
+
+	if (!vexpress_sysreg_base) {
+		dev_err(&pdev->dev, "Failed to obtain base address!\n");
+		return -EFAULT;
+	}
+
+	setup_timer(&vexpress_sysreg_config_timer,
+			vexpress_sysreg_config_complete, 0);
+
+	vexpress_sysreg_gpio_chip.dev = &pdev->dev;
+	err = gpiochip_add(&vexpress_sysreg_gpio_chip);
+	if (err) {
+		vexpress_config_bridge_unregister(
+				vexpress_sysreg_config_bridge);
+		dev_err(&pdev->dev, "Failed to register GPIO chip! (%d)\n",
+				err);
+		return err;
+	}
+
+	vexpress_sysreg_dev = &pdev->dev;
+
+	device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id);
+
+	return 0;
+}
+
+static const struct of_device_id vexpress_sysreg_match[] = {
+	{ .compatible = "arm,vexpress-sysreg", },
+	{},
+};
+
+static struct platform_driver vexpress_sysreg_driver = {
+	.driver = {
+		.name = "vexpress-sysreg",
+		.of_match_table = vexpress_sysreg_match,
+	},
+	.probe = vexpress_sysreg_probe,
+};
+
+static int __init vexpress_sysreg_init(void)
+{
+	return platform_driver_register(&vexpress_sysreg_driver);
+}
+core_initcall(vexpress_sysreg_init);
+
+
+#if defined(CONFIG_LEDS_CLASS)
+
+struct vexpress_sysreg_led {
+	u32 mask;
+	struct led_classdev cdev;
+} vexpress_sysreg_leds[] = {
+	{ .mask = 1 << 0, .cdev.name = "v2m:green:user1",
+			.cdev.default_trigger = "heartbeat", },
+	{ .mask = 1 << 1, .cdev.name = "v2m:green:user2",
+			.cdev.default_trigger = "mmc0", },
+	{ .mask = 1 << 2, .cdev.name = "v2m:green:user3",
+			.cdev.default_trigger = "cpu0", },
+	{ .mask = 1 << 3, .cdev.name = "v2m:green:user4",
+			.cdev.default_trigger = "cpu1", },
+	{ .mask = 1 << 4, .cdev.name = "v2m:green:user5",
+			.cdev.default_trigger = "cpu2", },
+	{ .mask = 1 << 5, .cdev.name = "v2m:green:user6",
+			.cdev.default_trigger = "cpu3", },
+	{ .mask = 1 << 6, .cdev.name = "v2m:green:user7",
+			.cdev.default_trigger = "cpu4", },
+	{ .mask = 1 << 7, .cdev.name = "v2m:green:user8",
+			.cdev.default_trigger = "cpu5", },
+};
+
+static DEFINE_SPINLOCK(vexpress_sysreg_leds_lock);
+
+static void vexpress_sysreg_led_brightness_set(struct led_classdev *cdev,
+		enum led_brightness brightness)
+{
+	struct vexpress_sysreg_led *led = container_of(cdev,
+			struct vexpress_sysreg_led, cdev);
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&vexpress_sysreg_leds_lock, flags);
+
+	val = readl(vexpress_sysreg_base + SYS_LED);
+	if (brightness == LED_OFF)
+		val &= ~led->mask;
+	else
+		val |= led->mask;
+	writel(val, vexpress_sysreg_base + SYS_LED);
+
+	spin_unlock_irqrestore(&vexpress_sysreg_leds_lock, flags);
+}
+
+static int __init vexpress_sysreg_init_leds(void)
+{
+	struct vexpress_sysreg_led *led;
+	int i;
+
+	/* Clear all user LEDs */
+	writel(0, vexpress_sysreg_base + SYS_LED);
+
+	for (i = 0, led = vexpress_sysreg_leds;
+			i < ARRAY_SIZE(vexpress_sysreg_leds); i++, led++) {
+		int err;
+
+		led->cdev.brightness_set = vexpress_sysreg_led_brightness_set;
+		err = led_classdev_register(vexpress_sysreg_dev, &led->cdev);
+		if (err) {
+			dev_err(vexpress_sysreg_dev,
+					"Failed to register LED %d! (%d)\n",
+					i, err);
+			while (led--, i--)
+				led_classdev_unregister(&led->cdev);
+			return err;
+		}
+	}
+
+	return 0;
+}
+device_initcall(vexpress_sysreg_init_leds);
+
+#endif
diff --git a/drivers/mfd/viperboard.c b/drivers/mfd/viperboard.c
new file mode 100644
index 0000000..af2a670
--- /dev/null
+++ b/drivers/mfd/viperboard.c
@@ -0,0 +1,137 @@
+/*
+ *  Nano River Technologies viperboard driver
+ *
+ *  This is the core driver for the viperboard. There are cell drivers
+ *  available for I2C, ADC and both GPIOs. SPI is not yet supported.
+ *  The drivers do not support all features the board exposes. See user
+ *  manual of the viperboard.
+ *
+ *  (C) 2012 by Lemonage GmbH
+ *  Author: Lars Poeschel <poeschel@lemonage.de>
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+
+#include <linux/mfd/core.h>
+#include <linux/mfd/viperboard.h>
+
+#include <linux/usb.h>
+
+
+static const struct usb_device_id vprbrd_table[] = {
+	{ USB_DEVICE(0x2058, 0x1005) },   /* Nano River Technologies */
+	{ }                               /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, vprbrd_table);
+
+static struct mfd_cell vprbrd_devs[] = {
+	{
+		.name = "viperboard-gpio",
+	},
+	{
+		.name = "viperboard-i2c",
+	},
+	{
+		.name = "viperboard-adc",
+	},
+};
+
+static int vprbrd_probe(struct usb_interface *interface,
+			      const struct usb_device_id *id)
+{
+	struct vprbrd *vb;
+
+	u16 version = 0;
+	int pipe, ret;
+
+	/* allocate memory for our device state and initialize it */
+	vb = kzalloc(sizeof(*vb), GFP_KERNEL);
+	if (vb == NULL) {
+		dev_err(&interface->dev, "Out of memory\n");
+		return -ENOMEM;
+	}
+
+	mutex_init(&vb->lock);
+
+	vb->usb_dev = usb_get_dev(interface_to_usbdev(interface));
+
+	/* save our data pointer in this interface device */
+	usb_set_intfdata(interface, vb);
+	dev_set_drvdata(&vb->pdev.dev, vb);
+
+	/* get version information, major first, minor then */
+	pipe = usb_rcvctrlpipe(vb->usb_dev, 0);
+	ret = usb_control_msg(vb->usb_dev, pipe, VPRBRD_USB_REQUEST_MAJOR,
+		VPRBRD_USB_TYPE_IN, 0x0000, 0x0000, vb->buf, 1,
+		VPRBRD_USB_TIMEOUT_MS);
+	if (ret == 1)
+		version = vb->buf[0];
+
+	ret = usb_control_msg(vb->usb_dev, pipe, VPRBRD_USB_REQUEST_MINOR,
+		VPRBRD_USB_TYPE_IN, 0x0000, 0x0000, vb->buf, 1,
+		VPRBRD_USB_TIMEOUT_MS);
+	if (ret == 1) {
+		version <<= 8;
+		version = version | vb->buf[0];
+	}
+
+	dev_info(&interface->dev,
+		 "version %x.%02x found at bus %03d address %03d\n",
+		 version >> 8, version & 0xff,
+		 vb->usb_dev->bus->busnum, vb->usb_dev->devnum);
+
+	ret = mfd_add_devices(&interface->dev, -1, vprbrd_devs,
+				ARRAY_SIZE(vprbrd_devs), NULL, 0, NULL);
+	if (ret != 0) {
+		dev_err(&interface->dev, "Failed to add mfd devices to core.");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	if (vb) {
+		usb_put_dev(vb->usb_dev);
+		kfree(vb);
+	}
+
+	return ret;
+}
+
+static void vprbrd_disconnect(struct usb_interface *interface)
+{
+	struct vprbrd *vb = usb_get_intfdata(interface);
+
+	mfd_remove_devices(&interface->dev);
+	usb_set_intfdata(interface, NULL);
+	usb_put_dev(vb->usb_dev);
+	kfree(vb);
+
+	dev_dbg(&interface->dev, "disconnected\n");
+}
+
+static struct usb_driver vprbrd_driver = {
+	.name		= "viperboard",
+	.probe		= vprbrd_probe,
+	.disconnect	= vprbrd_disconnect,
+	.id_table	= vprbrd_table,
+};
+
+module_usb_driver(vprbrd_driver);
+
+MODULE_DESCRIPTION("Nano River Technologies viperboard mfd core driver");
+MODULE_AUTHOR("Lars Poeschel <poeschel@lemonage.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/vx855.c b/drivers/mfd/vx855.c
index b9a636d..757ecc6 100644
--- a/drivers/mfd/vx855.c
+++ b/drivers/mfd/vx855.c
@@ -72,7 +72,7 @@ static struct mfd_cell vx855_cells[] = {
 	},
 };
 
-static __devinit int vx855_probe(struct pci_dev *pdev,
+static int vx855_probe(struct pci_dev *pdev,
 				 const struct pci_device_id *id)
 {
 	int ret;
@@ -112,7 +112,7 @@ out:
 	return ret;
 }
 
-static void __devexit vx855_remove(struct pci_dev *pdev)
+static void vx855_remove(struct pci_dev *pdev)
 {
 	mfd_remove_devices(&pdev->dev);
 	pci_disable_device(pdev);
@@ -128,7 +128,7 @@ static struct pci_driver vx855_pci_driver = {
 	.name		= "vx855",
 	.id_table	= vx855_pci_tbl,
 	.probe		= vx855_probe,
-	.remove		= __devexit_p(vx855_remove),
+	.remove		= vx855_remove,
 };
 
 module_pci_driver(vx855_pci_driver);
diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c
index 86e0e43..edbe6c1 100644
--- a/drivers/mfd/wl1273-core.c
+++ b/drivers/mfd/wl1273-core.c
@@ -182,7 +182,7 @@ static int wl1273_core_remove(struct i2c_client *client)
 	return 0;
 }
 
-static int __devinit wl1273_core_probe(struct i2c_client *client,
+static int wl1273_core_probe(struct i2c_client *client,
 				       const struct i2c_device_id *id)
 {
 	struct wl1273_fm_platform_data *pdata = client->dev.platform_data;
@@ -262,7 +262,7 @@ static struct i2c_driver wl1273_core_driver = {
 	},
 	.probe = wl1273_core_probe,
 	.id_table = wl1273_driver_id_table,
-	.remove = __devexit_p(wl1273_core_remove),
+	.remove = wl1273_core_remove,
 };
 
 static int __init wl1273_core_init(void)
diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c
index 01b9255..8bd0504 100644
--- a/drivers/mfd/wm5102-tables.c
+++ b/drivers/mfd/wm5102-tables.c
@@ -43,6 +43,7 @@ static const struct reg_default wm5102_reva_patch[] = {
 	{ 0x479, 0x0A30 },
 	{ 0x47B, 0x0810 },
 	{ 0x47D, 0x0510 },
+	{ 0x4D1, 0x017F },
 	{ 0x500, 0x000D },
 	{ 0x507, 0x1820 },
 	{ 0x508, 0x1820 },
@@ -52,524 +53,6 @@ static const struct reg_default wm5102_reva_patch[] = {
 	{ 0x580, 0x000D },
 	{ 0x587, 0x1820 },
 	{ 0x588, 0x1820 },
-	{ 0x101, 0x8140 },
-	{ 0x3000, 0x2225 },
-	{ 0x3001, 0x3a03 },
-	{ 0x3002, 0x0225 },
-	{ 0x3003, 0x0801 },
-	{ 0x3004, 0x6249 },
-	{ 0x3005, 0x0c04 },
-	{ 0x3006, 0x0225 },
-	{ 0x3007, 0x5901 },
-	{ 0x3008, 0xe249 },
-	{ 0x3009, 0x030d },
-	{ 0x300a, 0x0249 },
-	{ 0x300b, 0x2c01 },
-	{ 0x300c, 0xe249 },
-	{ 0x300d, 0x4342 },
-	{ 0x300e, 0xe249 },
-	{ 0x300f, 0x73c0 },
-	{ 0x3010, 0x4249 },
-	{ 0x3011, 0x0c00 },
-	{ 0x3012, 0x0225 },
-	{ 0x3013, 0x1f01 },
-	{ 0x3014, 0x0225 },
-	{ 0x3015, 0x1e01 },
-	{ 0x3016, 0x0225 },
-	{ 0x3017, 0xfa00 },
-	{ 0x3018, 0x0000 },
-	{ 0x3019, 0xf000 },
-	{ 0x301a, 0x0000 },
-	{ 0x301b, 0xf000 },
-	{ 0x301c, 0x0000 },
-	{ 0x301d, 0xf000 },
-	{ 0x301e, 0x0000 },
-	{ 0x301f, 0xf000 },
-	{ 0x3020, 0x0000 },
-	{ 0x3021, 0xf000 },
-	{ 0x3022, 0x0000 },
-	{ 0x3023, 0xf000 },
-	{ 0x3024, 0x0000 },
-	{ 0x3025, 0xf000 },
-	{ 0x3026, 0x0000 },
-	{ 0x3027, 0xf000 },
-	{ 0x3028, 0x0000 },
-	{ 0x3029, 0xf000 },
-	{ 0x302a, 0x0000 },
-	{ 0x302b, 0xf000 },
-	{ 0x302c, 0x0000 },
-	{ 0x302d, 0xf000 },
-	{ 0x302e, 0x0000 },
-	{ 0x302f, 0xf000 },
-	{ 0x3030, 0x0225 },
-	{ 0x3031, 0x1a01 },
-	{ 0x3032, 0x0225 },
-	{ 0x3033, 0x1e00 },
-	{ 0x3034, 0x0225 },
-	{ 0x3035, 0x1f00 },
-	{ 0x3036, 0x6225 },
-	{ 0x3037, 0xf800 },
-	{ 0x3038, 0x0000 },
-	{ 0x3039, 0xf000 },
-	{ 0x303a, 0x0000 },
-	{ 0x303b, 0xf000 },
-	{ 0x303c, 0x0000 },
-	{ 0x303d, 0xf000 },
-	{ 0x303e, 0x0000 },
-	{ 0x303f, 0xf000 },
-	{ 0x3040, 0x2226 },
-	{ 0x3041, 0x3a03 },
-	{ 0x3042, 0x0226 },
-	{ 0x3043, 0x0801 },
-	{ 0x3044, 0x6249 },
-	{ 0x3045, 0x0c06 },
-	{ 0x3046, 0x0226 },
-	{ 0x3047, 0x5901 },
-	{ 0x3048, 0xe249 },
-	{ 0x3049, 0x030d },
-	{ 0x304a, 0x0249 },
-	{ 0x304b, 0x2c01 },
-	{ 0x304c, 0xe249 },
-	{ 0x304d, 0x4342 },
-	{ 0x304e, 0xe249 },
-	{ 0x304f, 0x73c0 },
-	{ 0x3050, 0x4249 },
-	{ 0x3051, 0x0c00 },
-	{ 0x3052, 0x0226 },
-	{ 0x3053, 0x1f01 },
-	{ 0x3054, 0x0226 },
-	{ 0x3055, 0x1e01 },
-	{ 0x3056, 0x0226 },
-	{ 0x3057, 0xfa00 },
-	{ 0x3058, 0x0000 },
-	{ 0x3059, 0xf000 },
-	{ 0x305a, 0x0000 },
-	{ 0x305b, 0xf000 },
-	{ 0x305c, 0x0000 },
-	{ 0x305d, 0xf000 },
-	{ 0x305e, 0x0000 },
-	{ 0x305f, 0xf000 },
-	{ 0x3060, 0x0000 },
-	{ 0x3061, 0xf000 },
-	{ 0x3062, 0x0000 },
-	{ 0x3063, 0xf000 },
-	{ 0x3064, 0x0000 },
-	{ 0x3065, 0xf000 },
-	{ 0x3066, 0x0000 },
-	{ 0x3067, 0xf000 },
-	{ 0x3068, 0x0000 },
-	{ 0x3069, 0xf000 },
-	{ 0x306a, 0x0000 },
-	{ 0x306b, 0xf000 },
-	{ 0x306c, 0x0000 },
-	{ 0x306d, 0xf000 },
-	{ 0x306e, 0x0000 },
-	{ 0x306f, 0xf000 },
-	{ 0x3070, 0x0226 },
-	{ 0x3071, 0x1a01 },
-	{ 0x3072, 0x0226 },
-	{ 0x3073, 0x1e00 },
-	{ 0x3074, 0x0226 },
-	{ 0x3075, 0x1f00 },
-	{ 0x3076, 0x6226 },
-	{ 0x3077, 0xf800 },
-	{ 0x3078, 0x0000 },
-	{ 0x3079, 0xf000 },
-	{ 0x307a, 0x0000 },
-	{ 0x307b, 0xf000 },
-	{ 0x307c, 0x0000 },
-	{ 0x307d, 0xf000 },
-	{ 0x307e, 0x0000 },
-	{ 0x307f, 0xf000 },
-	{ 0x3080, 0x2227 },
-	{ 0x3081, 0x3a03 },
-	{ 0x3082, 0x0227 },
-	{ 0x3083, 0x0801 },
-	{ 0x3084, 0x6255 },
-	{ 0x3085, 0x0c04 },
-	{ 0x3086, 0x0227 },
-	{ 0x3087, 0x5901 },
-	{ 0x3088, 0xe255 },
-	{ 0x3089, 0x030d },
-	{ 0x308a, 0x0255 },
-	{ 0x308b, 0x2c01 },
-	{ 0x308c, 0xe255 },
-	{ 0x308d, 0x4342 },
-	{ 0x308e, 0xe255 },
-	{ 0x308f, 0x73c0 },
-	{ 0x3090, 0x4255 },
-	{ 0x3091, 0x0c00 },
-	{ 0x3092, 0x0227 },
-	{ 0x3093, 0x1f01 },
-	{ 0x3094, 0x0227 },
-	{ 0x3095, 0x1e01 },
-	{ 0x3096, 0x0227 },
-	{ 0x3097, 0xfa00 },
-	{ 0x3098, 0x0000 },
-	{ 0x3099, 0xf000 },
-	{ 0x309a, 0x0000 },
-	{ 0x309b, 0xf000 },
-	{ 0x309c, 0x0000 },
-	{ 0x309d, 0xf000 },
-	{ 0x309e, 0x0000 },
-	{ 0x309f, 0xf000 },
-	{ 0x30a0, 0x0000 },
-	{ 0x30a1, 0xf000 },
-	{ 0x30a2, 0x0000 },
-	{ 0x30a3, 0xf000 },
-	{ 0x30a4, 0x0000 },
-	{ 0x30a5, 0xf000 },
-	{ 0x30a6, 0x0000 },
-	{ 0x30a7, 0xf000 },
-	{ 0x30a8, 0x0000 },
-	{ 0x30a9, 0xf000 },
-	{ 0x30aa, 0x0000 },
-	{ 0x30ab, 0xf000 },
-	{ 0x30ac, 0x0000 },
-	{ 0x30ad, 0xf000 },
-	{ 0x30ae, 0x0000 },
-	{ 0x30af, 0xf000 },
-	{ 0x30b0, 0x0227 },
-	{ 0x30b1, 0x1a01 },
-	{ 0x30b2, 0x0227 },
-	{ 0x30b3, 0x1e00 },
-	{ 0x30b4, 0x0227 },
-	{ 0x30b5, 0x1f00 },
-	{ 0x30b6, 0x6227 },
-	{ 0x30b7, 0xf800 },
-	{ 0x30b8, 0x0000 },
-	{ 0x30b9, 0xf000 },
-	{ 0x30ba, 0x0000 },
-	{ 0x30bb, 0xf000 },
-	{ 0x30bc, 0x0000 },
-	{ 0x30bd, 0xf000 },
-	{ 0x30be, 0x0000 },
-	{ 0x30bf, 0xf000 },
-	{ 0x30c0, 0x2228 },
-	{ 0x30c1, 0x3a03 },
-	{ 0x30c2, 0x0228 },
-	{ 0x30c3, 0x0801 },
-	{ 0x30c4, 0x6255 },
-	{ 0x30c5, 0x0c06 },
-	{ 0x30c6, 0x0228 },
-	{ 0x30c7, 0x5901 },
-	{ 0x30c8, 0xe255 },
-	{ 0x30c9, 0x030d },
-	{ 0x30ca, 0x0255 },
-	{ 0x30cb, 0x2c01 },
-	{ 0x30cc, 0xe255 },
-	{ 0x30cd, 0x4342 },
-	{ 0x30ce, 0xe255 },
-	{ 0x30cf, 0x73c0 },
-	{ 0x30d0, 0x4255 },
-	{ 0x30d1, 0x0c00 },
-	{ 0x30d2, 0x0228 },
-	{ 0x30d3, 0x1f01 },
-	{ 0x30d4, 0x0228 },
-	{ 0x30d5, 0x1e01 },
-	{ 0x30d6, 0x0228 },
-	{ 0x30d7, 0xfa00 },
-	{ 0x30d8, 0x0000 },
-	{ 0x30d9, 0xf000 },
-	{ 0x30da, 0x0000 },
-	{ 0x30db, 0xf000 },
-	{ 0x30dc, 0x0000 },
-	{ 0x30dd, 0xf000 },
-	{ 0x30de, 0x0000 },
-	{ 0x30df, 0xf000 },
-	{ 0x30e0, 0x0000 },
-	{ 0x30e1, 0xf000 },
-	{ 0x30e2, 0x0000 },
-	{ 0x30e3, 0xf000 },
-	{ 0x30e4, 0x0000 },
-	{ 0x30e5, 0xf000 },
-	{ 0x30e6, 0x0000 },
-	{ 0x30e7, 0xf000 },
-	{ 0x30e8, 0x0000 },
-	{ 0x30e9, 0xf000 },
-	{ 0x30ea, 0x0000 },
-	{ 0x30eb, 0xf000 },
-	{ 0x30ec, 0x0000 },
-	{ 0x30ed, 0xf000 },
-	{ 0x30ee, 0x0000 },
-	{ 0x30ef, 0xf000 },
-	{ 0x30f0, 0x0228 },
-	{ 0x30f1, 0x1a01 },
-	{ 0x30f2, 0x0228 },
-	{ 0x30f3, 0x1e00 },
-	{ 0x30f4, 0x0228 },
-	{ 0x30f5, 0x1f00 },
-	{ 0x30f6, 0x6228 },
-	{ 0x30f7, 0xf800 },
-	{ 0x30f8, 0x0000 },
-	{ 0x30f9, 0xf000 },
-	{ 0x30fa, 0x0000 },
-	{ 0x30fb, 0xf000 },
-	{ 0x30fc, 0x0000 },
-	{ 0x30fd, 0xf000 },
-	{ 0x30fe, 0x0000 },
-	{ 0x30ff, 0xf000 },
-	{ 0x3100, 0x222b },
-	{ 0x3101, 0x3a03 },
-	{ 0x3102, 0x222b },
-	{ 0x3103, 0x5803 },
-	{ 0x3104, 0xe26f },
-	{ 0x3105, 0x030d },
-	{ 0x3106, 0x626f },
-	{ 0x3107, 0x2c01 },
-	{ 0x3108, 0xe26f },
-	{ 0x3109, 0x4342 },
-	{ 0x310a, 0xe26f },
-	{ 0x310b, 0x73c0 },
-	{ 0x310c, 0x026f },
-	{ 0x310d, 0x0c00 },
-	{ 0x310e, 0x022b },
-	{ 0x310f, 0x1f01 },
-	{ 0x3110, 0x022b },
-	{ 0x3111, 0x1e01 },
-	{ 0x3112, 0x022b },
-	{ 0x3113, 0xfa00 },
-	{ 0x3114, 0x0000 },
-	{ 0x3115, 0xf000 },
-	{ 0x3116, 0x0000 },
-	{ 0x3117, 0xf000 },
-	{ 0x3118, 0x0000 },
-	{ 0x3119, 0xf000 },
-	{ 0x311a, 0x0000 },
-	{ 0x311b, 0xf000 },
-	{ 0x311c, 0x0000 },
-	{ 0x311d, 0xf000 },
-	{ 0x311e, 0x0000 },
-	{ 0x311f, 0xf000 },
-	{ 0x3120, 0x022b },
-	{ 0x3121, 0x0a01 },
-	{ 0x3122, 0x022b },
-	{ 0x3123, 0x1e00 },
-	{ 0x3124, 0x022b },
-	{ 0x3125, 0x1f00 },
-	{ 0x3126, 0x622b },
-	{ 0x3127, 0xf800 },
-	{ 0x3128, 0x0000 },
-	{ 0x3129, 0xf000 },
-	{ 0x312a, 0x0000 },
-	{ 0x312b, 0xf000 },
-	{ 0x312c, 0x0000 },
-	{ 0x312d, 0xf000 },
-	{ 0x312e, 0x0000 },
-	{ 0x312f, 0xf000 },
-	{ 0x3130, 0x0000 },
-	{ 0x3131, 0xf000 },
-	{ 0x3132, 0x0000 },
-	{ 0x3133, 0xf000 },
-	{ 0x3134, 0x0000 },
-	{ 0x3135, 0xf000 },
-	{ 0x3136, 0x0000 },
-	{ 0x3137, 0xf000 },
-	{ 0x3138, 0x0000 },
-	{ 0x3139, 0xf000 },
-	{ 0x313a, 0x0000 },
-	{ 0x313b, 0xf000 },
-	{ 0x313c, 0x0000 },
-	{ 0x313d, 0xf000 },
-	{ 0x313e, 0x0000 },
-	{ 0x313f, 0xf000 },
-	{ 0x3140, 0x0000 },
-	{ 0x3141, 0xf000 },
-	{ 0x3142, 0x0000 },
-	{ 0x3143, 0xf000 },
-	{ 0x3144, 0x0000 },
-	{ 0x3145, 0xf000 },
-	{ 0x3146, 0x0000 },
-	{ 0x3147, 0xf000 },
-	{ 0x3148, 0x0000 },
-	{ 0x3149, 0xf000 },
-	{ 0x314a, 0x0000 },
-	{ 0x314b, 0xf000 },
-	{ 0x314c, 0x0000 },
-	{ 0x314d, 0xf000 },
-	{ 0x314e, 0x0000 },
-	{ 0x314f, 0xf000 },
-	{ 0x3150, 0x0000 },
-	{ 0x3151, 0xf000 },
-	{ 0x3152, 0x0000 },
-	{ 0x3153, 0xf000 },
-	{ 0x3154, 0x0000 },
-	{ 0x3155, 0xf000 },
-	{ 0x3156, 0x0000 },
-	{ 0x3157, 0xf000 },
-	{ 0x3158, 0x0000 },
-	{ 0x3159, 0xf000 },
-	{ 0x315a, 0x0000 },
-	{ 0x315b, 0xf000 },
-	{ 0x315c, 0x0000 },
-	{ 0x315d, 0xf000 },
-	{ 0x315e, 0x0000 },
-	{ 0x315f, 0xf000 },
-	{ 0x3160, 0x0000 },
-	{ 0x3161, 0xf000 },
-	{ 0x3162, 0x0000 },
-	{ 0x3163, 0xf000 },
-	{ 0x3164, 0x0000 },
-	{ 0x3165, 0xf000 },
-	{ 0x3166, 0x0000 },
-	{ 0x3167, 0xf000 },
-	{ 0x3168, 0x0000 },
-	{ 0x3169, 0xf000 },
-	{ 0x316a, 0x0000 },
-	{ 0x316b, 0xf000 },
-	{ 0x316c, 0x0000 },
-	{ 0x316d, 0xf000 },
-	{ 0x316e, 0x0000 },
-	{ 0x316f, 0xf000 },
-	{ 0x3170, 0x0000 },
-	{ 0x3171, 0xf000 },
-	{ 0x3172, 0x0000 },
-	{ 0x3173, 0xf000 },
-	{ 0x3174, 0x0000 },
-	{ 0x3175, 0xf000 },
-	{ 0x3176, 0x0000 },
-	{ 0x3177, 0xf000 },
-	{ 0x3178, 0x0000 },
-	{ 0x3179, 0xf000 },
-	{ 0x317a, 0x0000 },
-	{ 0x317b, 0xf000 },
-	{ 0x317c, 0x0000 },
-	{ 0x317d, 0xf000 },
-	{ 0x317e, 0x0000 },
-	{ 0x317f, 0xf000 },
-	{ 0x3180, 0x2001 },
-	{ 0x3181, 0xf101 },
-	{ 0x3182, 0x0000 },
-	{ 0x3183, 0xf000 },
-	{ 0x3184, 0x0000 },
-	{ 0x3185, 0xf000 },
-	{ 0x3186, 0x0000 },
-	{ 0x3187, 0xf000 },
-	{ 0x3188, 0x0000 },
-	{ 0x3189, 0xf000 },
-	{ 0x318a, 0x0000 },
-	{ 0x318b, 0xf000 },
-	{ 0x318c, 0x0000 },
-	{ 0x318d, 0xf000 },
-	{ 0x318e, 0x0000 },
-	{ 0x318f, 0xf000 },
-	{ 0x3190, 0x0000 },
-	{ 0x3191, 0xf000 },
-	{ 0x3192, 0x0000 },
-	{ 0x3193, 0xf000 },
-	{ 0x3194, 0x0000 },
-	{ 0x3195, 0xf000 },
-	{ 0x3196, 0x0000 },
-	{ 0x3197, 0xf000 },
-	{ 0x3198, 0x0000 },
-	{ 0x3199, 0xf000 },
-	{ 0x319a, 0x0000 },
-	{ 0x319b, 0xf000 },
-	{ 0x319c, 0x0000 },
-	{ 0x319d, 0xf000 },
-	{ 0x319e, 0x0000 },
-	{ 0x319f, 0xf000 },
-	{ 0x31a0, 0x0000 },
-	{ 0x31a1, 0xf000 },
-	{ 0x31a2, 0x0000 },
-	{ 0x31a3, 0xf000 },
-	{ 0x31a4, 0x0000 },
-	{ 0x31a5, 0xf000 },
-	{ 0x31a6, 0x0000 },
-	{ 0x31a7, 0xf000 },
-	{ 0x31a8, 0x0000 },
-	{ 0x31a9, 0xf000 },
-	{ 0x31aa, 0x0000 },
-	{ 0x31ab, 0xf000 },
-	{ 0x31ac, 0x0000 },
-	{ 0x31ad, 0xf000 },
-	{ 0x31ae, 0x0000 },
-	{ 0x31af, 0xf000 },
-	{ 0x31b0, 0x0000 },
-	{ 0x31b1, 0xf000 },
-	{ 0x31b2, 0x0000 },
-	{ 0x31b3, 0xf000 },
-	{ 0x31b4, 0x0000 },
-	{ 0x31b5, 0xf000 },
-	{ 0x31b6, 0x0000 },
-	{ 0x31b7, 0xf000 },
-	{ 0x31b8, 0x0000 },
-	{ 0x31b9, 0xf000 },
-	{ 0x31ba, 0x0000 },
-	{ 0x31bb, 0xf000 },
-	{ 0x31bc, 0x0000 },
-	{ 0x31bd, 0xf000 },
-	{ 0x31be, 0x0000 },
-	{ 0x31bf, 0xf000 },
-	{ 0x31c0, 0x0000 },
-	{ 0x31c1, 0xf000 },
-	{ 0x31c2, 0x0000 },
-	{ 0x31c3, 0xf000 },
-	{ 0x31c4, 0x0000 },
-	{ 0x31c5, 0xf000 },
-	{ 0x31c6, 0x0000 },
-	{ 0x31c7, 0xf000 },
-	{ 0x31c8, 0x0000 },
-	{ 0x31c9, 0xf000 },
-	{ 0x31ca, 0x0000 },
-	{ 0x31cb, 0xf000 },
-	{ 0x31cc, 0x0000 },
-	{ 0x31cd, 0xf000 },
-	{ 0x31ce, 0x0000 },
-	{ 0x31cf, 0xf000 },
-	{ 0x31d0, 0x0000 },
-	{ 0x31d1, 0xf000 },
-	{ 0x31d2, 0x0000 },
-	{ 0x31d3, 0xf000 },
-	{ 0x31d4, 0x0000 },
-	{ 0x31d5, 0xf000 },
-	{ 0x31d6, 0x0000 },
-	{ 0x31d7, 0xf000 },
-	{ 0x31d8, 0x0000 },
-	{ 0x31d9, 0xf000 },
-	{ 0x31da, 0x0000 },
-	{ 0x31db, 0xf000 },
-	{ 0x31dc, 0x0000 },
-	{ 0x31dd, 0xf000 },
-	{ 0x31de, 0x0000 },
-	{ 0x31df, 0xf000 },
-	{ 0x31e0, 0x0000 },
-	{ 0x31e1, 0xf000 },
-	{ 0x31e2, 0x0000 },
-	{ 0x31e3, 0xf000 },
-	{ 0x31e4, 0x0000 },
-	{ 0x31e5, 0xf000 },
-	{ 0x31e6, 0x0000 },
-	{ 0x31e7, 0xf000 },
-	{ 0x31e8, 0x0000 },
-	{ 0x31e9, 0xf000 },
-	{ 0x31ea, 0x0000 },
-	{ 0x31eb, 0xf000 },
-	{ 0x31ec, 0x0000 },
-	{ 0x31ed, 0xf000 },
-	{ 0x31ee, 0x0000 },
-	{ 0x31ef, 0xf000 },
-	{ 0x31f0, 0x0000 },
-	{ 0x31f1, 0xf000 },
-	{ 0x31f2, 0x0000 },
-	{ 0x31f3, 0xf000 },
-	{ 0x31f4, 0x0000 },
-	{ 0x31f5, 0xf000 },
-	{ 0x31f6, 0x0000 },
-	{ 0x31f7, 0xf000 },
-	{ 0x31f8, 0x0000 },
-	{ 0x31f9, 0xf000 },
-	{ 0x31fa, 0x0000 },
-	{ 0x31fb, 0xf000 },
-	{ 0x31fc, 0x0000 },
-	{ 0x31fd, 0xf000 },
-	{ 0x31fe, 0x0000 },
-	{ 0x31ff, 0xf000 },
-	{ 0x024d, 0xff50 },
-	{ 0x0252, 0xff50 },
-	{ 0x0259, 0x0112 },
-	{ 0x025e, 0x0112 },
-	{ 0x101, 0x0304 },
 	{ 0x80, 0x0000 },
 };
 
@@ -775,6 +258,7 @@ static const struct reg_default wm5102_reg_default[] = {
 	{ 0x00000154, 0x0000 },   /* R340   - Rate Estimator 3 */ 
 	{ 0x00000155, 0x0000 },   /* R341   - Rate Estimator 4 */ 
 	{ 0x00000156, 0x0000 },   /* R342   - Rate Estimator 5 */ 
+	{ 0x00000161, 0x0000 },   /* R353   - Dynamic Frequency Scaling 1 */ 
 	{ 0x00000171, 0x0000 },   /* R369   - FLL1 Control 1 */ 
 	{ 0x00000172, 0x0008 },   /* R370   - FLL1 Control 2 */ 
 	{ 0x00000173, 0x0018 },   /* R371   - FLL1 Control 3 */ 
@@ -1564,6 +1048,7 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_RATE_ESTIMATOR_3:
 	case ARIZONA_RATE_ESTIMATOR_4:
 	case ARIZONA_RATE_ESTIMATOR_5:
+	case ARIZONA_DYNAMIC_FREQUENCY_SCALING_1:
 	case ARIZONA_FLL1_CONTROL_1:
 	case ARIZONA_FLL1_CONTROL_2:
 	case ARIZONA_FLL1_CONTROL_3:
@@ -1571,6 +1056,7 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_FLL1_CONTROL_5:
 	case ARIZONA_FLL1_CONTROL_6:
 	case ARIZONA_FLL1_LOOP_FILTER_TEST_1:
+	case ARIZONA_FLL1_NCO_TEST_0:
 	case ARIZONA_FLL1_SYNCHRONISER_1:
 	case ARIZONA_FLL1_SYNCHRONISER_2:
 	case ARIZONA_FLL1_SYNCHRONISER_3:
@@ -1586,6 +1072,7 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_FLL2_CONTROL_5:
 	case ARIZONA_FLL2_CONTROL_6:
 	case ARIZONA_FLL2_LOOP_FILTER_TEST_1:
+	case ARIZONA_FLL2_NCO_TEST_0:
 	case ARIZONA_FLL2_SYNCHRONISER_1:
 	case ARIZONA_FLL2_SYNCHRONISER_2:
 	case ARIZONA_FLL2_SYNCHRONISER_3:
@@ -1596,6 +1083,7 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
 	case ARIZONA_FLL2_GPIO_CLOCK:
 	case ARIZONA_MIC_CHARGE_PUMP_1:
 	case ARIZONA_LDO1_CONTROL_1:
+	case ARIZONA_LDO1_CONTROL_2:
 	case ARIZONA_LDO2_CONTROL_1:
 	case ARIZONA_MIC_BIAS_CTRL_1:
 	case ARIZONA_MIC_BIAS_CTRL_2:
@@ -2331,11 +1819,16 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg)
 	case ARIZONA_SOFTWARE_RESET:
 	case ARIZONA_DEVICE_REVISION:
 	case ARIZONA_OUTPUT_STATUS_1:
+	case ARIZONA_RAW_OUTPUT_STATUS_1:
+	case ARIZONA_SLIMBUS_RX_PORT_STATUS:
+	case ARIZONA_SLIMBUS_TX_PORT_STATUS:
 	case ARIZONA_SAMPLE_RATE_1_STATUS:
 	case ARIZONA_SAMPLE_RATE_2_STATUS:
 	case ARIZONA_SAMPLE_RATE_3_STATUS:
 	case ARIZONA_HAPTICS_STATUS:
 	case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS:
+	case ARIZONA_FLL1_NCO_TEST_0:
+	case ARIZONA_FLL2_NCO_TEST_0:
 	case ARIZONA_FX_CTRL2:
 	case ARIZONA_INTERRUPT_STATUS_1:
 	case ARIZONA_INTERRUPT_STATUS_2:
@@ -2369,12 +1862,14 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg)
 	}
 }
 
+#define WM5102_MAX_REGISTER 0x1a8fff
+
 const struct regmap_config wm5102_spi_regmap = {
 	.reg_bits = 32,
 	.pad_bits = 16,
 	.val_bits = 16,
 
-	.max_register = ARIZONA_DSP1_STATUS_2,
+	.max_register = WM5102_MAX_REGISTER,
 	.readable_reg = wm5102_readable_register,
 	.volatile_reg = wm5102_volatile_register,
 
@@ -2388,7 +1883,7 @@ const struct regmap_config wm5102_i2c_regmap = {
 	.reg_bits = 32,
 	.val_bits = 16,
 
-	.max_register = ARIZONA_DSP1_STATUS_2,
+	.max_register = WM5102_MAX_REGISTER,
 	.readable_reg = wm5102_readable_register,
 	.volatile_reg = wm5102_volatile_register,
 
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
index 4bceee9..4e70e15 100644
--- a/drivers/mfd/wm831x-spi.c
+++ b/drivers/mfd/wm831x-spi.c
@@ -21,7 +21,7 @@
 
 #include <linux/mfd/wm831x/core.h>
 
-static int __devinit wm831x_spi_probe(struct spi_device *spi)
+static int wm831x_spi_probe(struct spi_device *spi)
 {
 	const struct spi_device_id *id = spi_get_device_id(spi);
 	struct wm831x *wm831x;
@@ -51,7 +51,7 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi)
 	return wm831x_device_init(wm831x, type, spi->irq);
 }
 
-static int __devexit wm831x_spi_remove(struct spi_device *spi)
+static int wm831x_spi_remove(struct spi_device *spi)
 {
 	struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
 
@@ -99,7 +99,7 @@ static struct spi_driver wm831x_spi_driver = {
 	},
 	.id_table	= wm831x_spi_ids,
 	.probe		= wm831x_spi_probe,
-	.remove		= __devexit_p(wm831x_spi_remove),
+	.remove		= wm831x_spi_remove,
 	.shutdown	= wm831x_spi_shutdown,
 };
 
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index 8fefc96..45dd547 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -374,21 +374,21 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
 }
 #endif
 
-static const __devinitconst struct reg_default wm8994_revc_patch[] = {
+static const struct reg_default wm8994_revc_patch[] = {
 	{ 0x102, 0x3 },
 	{ 0x56, 0x3 },
 	{ 0x817, 0x0 },
 	{ 0x102, 0x0 },
 };
 
-static const __devinitconst struct reg_default wm8958_reva_patch[] = {
+static const struct reg_default wm8958_reva_patch[] = {
 	{ 0x102, 0x3 },
 	{ 0xcb, 0x81 },
 	{ 0x817, 0x0 },
 	{ 0x102, 0x0 },
 };
 
-static const __devinitconst struct reg_default wm1811_reva_patch[] = {
+static const struct reg_default wm1811_reva_patch[] = {
 	{ 0x102, 0x3 },
 	{ 0x56, 0xc07 },
 	{ 0x5d, 0x7e },
@@ -399,15 +399,21 @@ static const __devinitconst struct reg_default wm1811_reva_patch[] = {
 /*
  * Instantiate the generic non-control parts of the device.
  */
-static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq)
+static int wm8994_device_init(struct wm8994 *wm8994, int irq)
 {
-	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+	struct wm8994_pdata *pdata;
 	struct regmap_config *regmap_config;
 	const struct reg_default *regmap_patch = NULL;
 	const char *devname;
 	int ret, i, patch_regs;
 	int pulls = 0;
 
+	if (dev_get_platdata(wm8994->dev)) {
+		pdata = dev_get_platdata(wm8994->dev);
+		wm8994->pdata = *pdata;
+	}
+	pdata = &wm8994->pdata;
+
 	dev_set_drvdata(wm8994->dev, wm8994);
 
 	/* Add the on-chip regulators first for bootstrapping */
@@ -557,6 +563,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq)
 		case 1:
 		case 2:
 		case 3:
+		case 4:
 			regmap_patch = wm1811_reva_patch;
 			patch_regs = ARRAY_SIZE(wm1811_reva_patch);
 			break;
@@ -604,24 +611,21 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq)
 		}
 	}
 
-	if (pdata) {
-		wm8994->irq_base = pdata->irq_base;
-		wm8994->gpio_base = pdata->gpio_base;
-
-		/* GPIO configuration is only applied if it's non-zero */
-		for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
-			if (pdata->gpio_defaults[i]) {
-				wm8994_set_bits(wm8994, WM8994_GPIO_1 + i,
-						0xffff,
-						pdata->gpio_defaults[i]);
-			}
+	wm8994->irq_base = pdata->irq_base;
+	wm8994->gpio_base = pdata->gpio_base;
+
+	/* GPIO configuration is only applied if it's non-zero */
+	for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
+		if (pdata->gpio_defaults[i]) {
+			wm8994_set_bits(wm8994, WM8994_GPIO_1 + i,
+					0xffff, pdata->gpio_defaults[i]);
 		}
+	}
 
-		wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven;
+	wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven;
 
-		if (pdata->spkmode_pu)
-			pulls |= WM8994_SPKMODE_PU;
-	}
+	if (pdata->spkmode_pu)
+		pulls |= WM8994_SPKMODE_PU;
 
 	/* Disable unneeded pulls */
 	wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
@@ -671,7 +675,7 @@ err:
 	return ret;
 }
 
-static __devexit void wm8994_device_exit(struct wm8994 *wm8994)
+static void wm8994_device_exit(struct wm8994 *wm8994)
 {
 	pm_runtime_disable(wm8994->dev);
 	mfd_remove_devices(wm8994->dev);
@@ -689,7 +693,7 @@ static const struct of_device_id wm8994_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, wm8994_of_match);
 
-static __devinit int wm8994_i2c_probe(struct i2c_client *i2c,
+static int wm8994_i2c_probe(struct i2c_client *i2c,
 				      const struct i2c_device_id *id)
 {
 	struct wm8994 *wm8994;
@@ -715,7 +719,7 @@ static __devinit int wm8994_i2c_probe(struct i2c_client *i2c,
 	return wm8994_device_init(wm8994, i2c->irq);
 }
 
-static __devexit int wm8994_i2c_remove(struct i2c_client *i2c)
+static int wm8994_i2c_remove(struct i2c_client *i2c)
 {
 	struct wm8994 *wm8994 = i2c_get_clientdata(i2c);
 
@@ -744,7 +748,7 @@ static struct i2c_driver wm8994_i2c_driver = {
 		.of_match_table = wm8994_of_match,
 	},
 	.probe = wm8994_i2c_probe,
-	.remove = __devexit_p(wm8994_i2c_remove),
+	.remove = wm8994_i2c_remove,
 	.id_table = wm8994_i2c_id,
 };
 
diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c
index 8208262..705b881 100644
--- a/drivers/misc/ad525x_dpot-i2c.c
+++ b/drivers/misc/ad525x_dpot-i2c.c
@@ -51,7 +51,7 @@ static const struct ad_dpot_bus_ops bops = {
 	.write_r8d16	= write_r8d16,
 };
 
-static int __devinit ad_dpot_i2c_probe(struct i2c_client *client,
+static int ad_dpot_i2c_probe(struct i2c_client *client,
 				      const struct i2c_device_id *id)
 {
 	struct ad_dpot_bus_data bdata = {
@@ -68,7 +68,7 @@ static int __devinit ad_dpot_i2c_probe(struct i2c_client *client,
 	return ad_dpot_probe(&client->dev, &bdata, id->driver_data, id->name);
 }
 
-static int __devexit ad_dpot_i2c_remove(struct i2c_client *client)
+static int ad_dpot_i2c_remove(struct i2c_client *client)
 {
 	return ad_dpot_remove(&client->dev);
 }
@@ -109,7 +109,7 @@ static struct i2c_driver ad_dpot_i2c_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= ad_dpot_i2c_probe,
-	.remove		= __devexit_p(ad_dpot_i2c_remove),
+	.remove		= ad_dpot_i2c_remove,
 	.id_table	= ad_dpot_id,
 };
 
diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c
index f623175..9da04ed 100644
--- a/drivers/misc/ad525x_dpot-spi.c
+++ b/drivers/misc/ad525x_dpot-spi.c
@@ -75,7 +75,7 @@ static const struct ad_dpot_bus_ops bops = {
 	.write_r8d8	= write16,
 	.write_r8d16	= write24,
 };
-static int __devinit ad_dpot_spi_probe(struct spi_device *spi)
+static int ad_dpot_spi_probe(struct spi_device *spi)
 {
 	struct ad_dpot_bus_data bdata = {
 		.client = spi,
@@ -87,7 +87,7 @@ static int __devinit ad_dpot_spi_probe(struct spi_device *spi)
 			     spi_get_device_id(spi)->name);
 }
 
-static int __devexit ad_dpot_spi_remove(struct spi_device *spi)
+static int ad_dpot_spi_remove(struct spi_device *spi)
 {
 	return ad_dpot_remove(&spi->dev);
 }
@@ -131,7 +131,7 @@ static struct spi_driver ad_dpot_spi_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= ad_dpot_spi_probe,
-	.remove		= __devexit_p(ad_dpot_spi_remove),
+	.remove		= ad_dpot_spi_remove,
 	.id_table	= ad_dpot_spi_id,
 };
 
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c
index 6938f1b..8f99e8e 100644
--- a/drivers/misc/ad525x_dpot.c
+++ b/drivers/misc/ad525x_dpot.c
@@ -641,7 +641,7 @@ static const struct attribute_group ad525x_group_commands = {
 	.attrs = ad525x_attributes_commands,
 };
 
-__devinit int ad_dpot_add_files(struct device *dev,
+int ad_dpot_add_files(struct device *dev,
 		unsigned features, unsigned rdac)
 {
 	int err = sysfs_create_file(&dev->kobj,
@@ -685,7 +685,7 @@ inline void ad_dpot_remove_files(struct device *dev,
 	}
 }
 
-int __devinit ad_dpot_probe(struct device *dev,
+int ad_dpot_probe(struct device *dev,
 		struct ad_dpot_bus_data *bdata, unsigned long devid,
 			    const char *name)
 {
diff --git a/drivers/misc/apds9802als.c b/drivers/misc/apds9802als.c
index 0314773..d648b08 100644
--- a/drivers/misc/apds9802als.c
+++ b/drivers/misc/apds9802als.c
@@ -68,7 +68,7 @@ static int als_wait_for_data_ready(struct device *dev)
 		ret = i2c_smbus_read_byte_data(client, 0x86);
 	} while (!(ret & 0x80) && retry--);
 
-	if (!retry) {
+	if (retry < 0) {
 		dev_warn(dev, "timeout waiting for data ready\n");
 		return -ETIMEDOUT;
 	}
@@ -254,7 +254,7 @@ als_error1:
 	return res;
 }
 
-static int __devexit apds9802als_remove(struct i2c_client *client)
+static int apds9802als_remove(struct i2c_client *client)
 {
 	struct als_data *data = i2c_get_clientdata(client);
 
@@ -326,7 +326,7 @@ static struct i2c_driver apds9802als_driver = {
 		.pm = APDS9802ALS_PM_OPS,
 	},
 	.probe = apds9802als_probe,
-	.remove = __devexit_p(apds9802als_remove),
+	.remove = apds9802als_remove,
 	.suspend = apds9802als_suspend,
 	.resume = apds9802als_resume,
 	.id_table = apds9802als_id,
diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c
index ee74244..0e67f82 100644
--- a/drivers/misc/apds990x.c
+++ b/drivers/misc/apds990x.c
@@ -1047,7 +1047,7 @@ static struct attribute_group apds990x_attribute_group[] = {
 	{.attrs = sysfs_attrs_ctrl },
 };
 
-static int __devinit apds990x_probe(struct i2c_client *client,
+static int apds990x_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
 	struct apds990x_chip *chip;
@@ -1181,7 +1181,7 @@ fail1:
 	return err;
 }
 
-static int __devexit apds990x_remove(struct i2c_client *client)
+static int apds990x_remove(struct i2c_client *client)
 {
 	struct apds990x_chip *chip = i2c_get_clientdata(client);
 
@@ -1275,7 +1275,7 @@ static struct i2c_driver apds990x_driver = {
 		.pm	= &apds990x_pm_ops,
 	},
 	.probe	  = apds990x_probe,
-	.remove	  = __devexit_p(apds990x_remove),
+	.remove	  = apds990x_remove,
 	.id_table = apds990x_id,
 };
 
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 5bb1877..158da5a 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -18,6 +18,8 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 
+#include <linux/of.h>
+
 /* Serialize access to ssc_list and user count */
 static DEFINE_SPINLOCK(user_lock);
 static LIST_HEAD(ssc_list);
@@ -29,7 +31,13 @@ struct ssc_device *ssc_request(unsigned int ssc_num)
 
 	spin_lock(&user_lock);
 	list_for_each_entry(ssc, &ssc_list, list) {
-		if (ssc->pdev->id == ssc_num) {
+		if (ssc->pdev->dev.of_node) {
+			if (of_alias_get_id(ssc->pdev->dev.of_node, "ssc")
+				== ssc_num) {
+				ssc_valid = 1;
+				break;
+			}
+		} else if (ssc->pdev->id == ssc_num) {
 			ssc_valid = 1;
 			break;
 		}
@@ -68,39 +76,93 @@ void ssc_free(struct ssc_device *ssc)
 }
 EXPORT_SYMBOL(ssc_free);
 
-static int __init ssc_probe(struct platform_device *pdev)
+static struct atmel_ssc_platform_data at91rm9200_config = {
+	.use_dma = 0,
+};
+
+static struct atmel_ssc_platform_data at91sam9g45_config = {
+	.use_dma = 1,
+};
+
+static const struct platform_device_id atmel_ssc_devtypes[] = {
+	{
+		.name = "at91rm9200_ssc",
+		.driver_data = (unsigned long) &at91rm9200_config,
+	}, {
+		.name = "at91sam9g45_ssc",
+		.driver_data = (unsigned long) &at91sam9g45_config,
+	}, {
+		/* sentinel */
+	}
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id atmel_ssc_dt_ids[] = {
+	{
+		.compatible = "atmel,at91rm9200-ssc",
+		.data = &at91rm9200_config,
+	}, {
+		.compatible = "atmel,at91sam9g45-ssc",
+		.data = &at91sam9g45_config,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(of, atmel_ssc_dt_ids);
+#endif
+
+static inline const struct atmel_ssc_platform_data * __init
+	atmel_ssc_get_driver_data(struct platform_device *pdev)
+{
+	if (pdev->dev.of_node) {
+		const struct of_device_id *match;
+		match = of_match_node(atmel_ssc_dt_ids, pdev->dev.of_node);
+		if (match == NULL)
+			return NULL;
+		return match->data;
+	}
+
+	return (struct atmel_ssc_platform_data *)
+		platform_get_device_id(pdev)->driver_data;
+}
+
+static int ssc_probe(struct platform_device *pdev)
 {
-	int retval = 0;
 	struct resource *regs;
 	struct ssc_device *ssc;
+	const struct atmel_ssc_platform_data *plat_dat;
 
-	ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL);
+	ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
 	if (!ssc) {
 		dev_dbg(&pdev->dev, "out of memory\n");
-		retval = -ENOMEM;
-		goto out;
+		return -ENOMEM;
 	}
 
+	ssc->pdev = pdev;
+
+	plat_dat = atmel_ssc_get_driver_data(pdev);
+	if (!plat_dat)
+		return -ENODEV;
+	ssc->pdata = (struct atmel_ssc_platform_data *)plat_dat;
+
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!regs) {
 		dev_dbg(&pdev->dev, "no mmio resource defined\n");
-		retval = -ENXIO;
-		goto out_free;
+		return -ENXIO;
 	}
 
-	ssc->clk = clk_get(&pdev->dev, "pclk");
-	if (IS_ERR(ssc->clk)) {
-		dev_dbg(&pdev->dev, "no pclk clock defined\n");
-		retval = -ENXIO;
-		goto out_free;
-	}
-
-	ssc->pdev = pdev;
-	ssc->regs = ioremap(regs->start, resource_size(regs));
+	ssc->regs = devm_request_and_ioremap(&pdev->dev, regs);
 	if (!ssc->regs) {
 		dev_dbg(&pdev->dev, "ioremap failed\n");
-		retval = -EINVAL;
-		goto out_clk;
+		return -EINVAL;
+	}
+
+	ssc->phybase = regs->start;
+
+	ssc->clk = devm_clk_get(&pdev->dev, "pclk");
+	if (IS_ERR(ssc->clk)) {
+		dev_dbg(&pdev->dev, "no pclk clock defined\n");
+		return -ENXIO;
 	}
 
 	/* disable all interrupts */
@@ -112,8 +174,7 @@ static int __init ssc_probe(struct platform_device *pdev)
 	ssc->irq = platform_get_irq(pdev, 0);
 	if (!ssc->irq) {
 		dev_dbg(&pdev->dev, "could not get irq\n");
-		retval = -ENXIO;
-		goto out_unmap;
+		return -ENXIO;
 	}
 
 	spin_lock(&user_lock);
@@ -125,51 +186,31 @@ static int __init ssc_probe(struct platform_device *pdev)
 	dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n",
 			ssc->regs, ssc->irq);
 
-	goto out;
-
-out_unmap:
-	iounmap(ssc->regs);
-out_clk:
-	clk_put(ssc->clk);
-out_free:
-	kfree(ssc);
-out:
-	return retval;
+	return 0;
 }
 
-static int __devexit ssc_remove(struct platform_device *pdev)
+static int ssc_remove(struct platform_device *pdev)
 {
 	struct ssc_device *ssc = platform_get_drvdata(pdev);
 
 	spin_lock(&user_lock);
-	iounmap(ssc->regs);
-	clk_put(ssc->clk);
 	list_del(&ssc->list);
-	kfree(ssc);
 	spin_unlock(&user_lock);
 
 	return 0;
 }
 
 static struct platform_driver ssc_driver = {
-	.remove		= __devexit_p(ssc_remove),
 	.driver		= {
 		.name		= "ssc",
 		.owner		= THIS_MODULE,
+		.of_match_table	= of_match_ptr(atmel_ssc_dt_ids),
 	},
+	.id_table	= atmel_ssc_devtypes,
+	.probe		= ssc_probe,
+	.remove		= ssc_remove,
 };
-
-static int __init ssc_init(void)
-{
-	return platform_driver_probe(&ssc_driver, ssc_probe);
-}
-module_init(ssc_init);
-
-static void __exit ssc_exit(void)
-{
-	platform_driver_unregister(&ssc_driver);
-}
-module_exit(ssc_exit);
+module_platform_driver(ssc_driver);
 
 MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
 MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91");
diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c
index 3d56ae7..2ed8fc3 100644
--- a/drivers/misc/bh1770glc.c
+++ b/drivers/misc/bh1770glc.c
@@ -1162,7 +1162,7 @@ static struct attribute_group bh1770_attribute_group = {
 	.attrs = sysfs_attrs
 };
 
-static int __devinit bh1770_probe(struct i2c_client *client,
+static int bh1770_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
 	struct bh1770_chip *chip;
@@ -1285,7 +1285,7 @@ fail1:
 	return err;
 }
 
-static int __devexit bh1770_remove(struct i2c_client *client)
+static int bh1770_remove(struct i2c_client *client)
 {
 	struct bh1770_chip *chip = i2c_get_clientdata(client);
 
@@ -1395,7 +1395,7 @@ static struct i2c_driver bh1770_driver = {
 		.pm	= &bh1770_pm_ops,
 	},
 	.probe	  = bh1770_probe,
-	.remove	  = __devexit_p(bh1770_remove),
+	.remove	  = bh1770_remove,
 	.id_table = bh1770_id,
 };
 
diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c
index f1f9877..cf03d0a 100644
--- a/drivers/misc/bh1780gli.c
+++ b/drivers/misc/bh1780gli.c
@@ -144,7 +144,7 @@ static const struct attribute_group bh1780_attr_group = {
 	.attrs = bh1780_attributes,
 };
 
-static int __devinit bh1780_probe(struct i2c_client *client,
+static int bh1780_probe(struct i2c_client *client,
 						const struct i2c_device_id *id)
 {
 	int ret;
@@ -185,7 +185,7 @@ err_op_failed:
 	return ret;
 }
 
-static int __devexit bh1780_remove(struct i2c_client *client)
+static int bh1780_remove(struct i2c_client *client)
 {
 	struct bh1780_data *ddata;
 
@@ -248,7 +248,7 @@ static const struct i2c_device_id bh1780_id[] = {
 
 static struct i2c_driver bh1780_driver = {
 	.probe		= bh1780_probe,
-	.remove		= __devexit_p(bh1780_remove),
+	.remove		= bh1780_remove,
 	.id_table	= bh1780_id,
 	.driver = {
 		.name = "bh1780",
diff --git a/drivers/misc/bmp085-i2c.c b/drivers/misc/bmp085-i2c.c
index a4f33c9..3abfcec 100644
--- a/drivers/misc/bmp085-i2c.c
+++ b/drivers/misc/bmp085-i2c.c
@@ -36,7 +36,7 @@ static int bmp085_i2c_detect(struct i2c_client *client,
 	return bmp085_detect(&client->dev);
 }
 
-static int __devinit bmp085_i2c_probe(struct i2c_client *client,
+static int bmp085_i2c_probe(struct i2c_client *client,
 				      const struct i2c_device_id *id)
 {
 	int err;
@@ -71,7 +71,7 @@ static struct i2c_driver bmp085_i2c_driver = {
 	},
 	.id_table	= bmp085_id,
 	.probe		= bmp085_i2c_probe,
-	.remove		= __devexit_p(bmp085_i2c_remove),
+	.remove		= bmp085_i2c_remove,
 
 	.detect		= bmp085_i2c_detect,
 	.address_list	= normal_i2c
diff --git a/drivers/misc/bmp085-spi.c b/drivers/misc/bmp085-spi.c
index 5e982af..d6a5265 100644
--- a/drivers/misc/bmp085-spi.c
+++ b/drivers/misc/bmp085-spi.c
@@ -22,7 +22,7 @@
 #include <linux/err.h>
 #include "bmp085.h"
 
-static int __devinit bmp085_spi_probe(struct spi_device *client)
+static int bmp085_spi_probe(struct spi_device *client)
 {
 	int err;
 	struct regmap *regmap;
@@ -70,7 +70,7 @@ static struct spi_driver bmp085_spi_driver = {
 	},
 	.id_table	= bmp085_id,
 	.probe		= bmp085_spi_probe,
-	.remove		= __devexit_p(bmp085_spi_remove)
+	.remove		= bmp085_spi_remove
 };
 
 module_spi_driver(bmp085_spi_driver);
diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c
index 62e4182..849e2fe 100644
--- a/drivers/misc/bmp085.c
+++ b/drivers/misc/bmp085.c
@@ -420,7 +420,7 @@ struct regmap_config bmp085_regmap_config = {
 };
 EXPORT_SYMBOL_GPL(bmp085_regmap_config);
 
-__devinit int bmp085_probe(struct device *dev, struct regmap *regmap)
+int bmp085_probe(struct device *dev, struct regmap *regmap)
 {
 	struct bmp085_data *data;
 	int err = 0;
diff --git a/drivers/misc/cb710/core.c b/drivers/misc/cb710/core.c
index 9d5eed7..2e50f81 100644
--- a/drivers/misc/cb710/core.c
+++ b/drivers/misc/cb710/core.c
@@ -30,7 +30,7 @@ void cb710_pci_update_config_reg(struct pci_dev *pdev,
 EXPORT_SYMBOL_GPL(cb710_pci_update_config_reg);
 
 /* Some magic writes based on Windows driver init code */
-static int __devinit cb710_pci_configure(struct pci_dev *pdev)
+static int cb710_pci_configure(struct pci_dev *pdev)
 {
 	unsigned int devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
 	struct pci_dev *pdev0;
@@ -96,7 +96,7 @@ static void cb710_release_slot(struct device *dev)
 #endif
 }
 
-static int __devinit cb710_register_slot(struct cb710_chip *chip,
+static int cb710_register_slot(struct cb710_chip *chip,
 	unsigned slot_mask, unsigned io_offset, const char *name)
 {
 	int nr = chip->slots;
@@ -201,7 +201,7 @@ static int cb710_resume(struct pci_dev *pdev)
 
 #endif /* CONFIG_PM */
 
-static int __devinit cb710_probe(struct pci_dev *pdev,
+static int cb710_probe(struct pci_dev *pdev,
 	const struct pci_device_id *ent)
 {
 	struct cb710_chip *chip;
@@ -305,7 +305,7 @@ unreg_mmc:
 	return err;
 }
 
-static void __devexit cb710_remove_one(struct pci_dev *pdev)
+static void cb710_remove_one(struct pci_dev *pdev)
 {
 	struct cb710_chip *chip = pci_get_drvdata(pdev);
 	unsigned long flags;
@@ -332,7 +332,7 @@ static struct pci_driver cb710_driver = {
 	.name = KBUILD_MODNAME,
 	.id_table = cb710_pci_tbl,
 	.probe = cb710_probe,
-	.remove = __devexit_p(cb710_remove_one),
+	.remove = cb710_remove_one,
 #ifdef CONFIG_PM
 	.suspend = cb710_suspend,
 	.resume = cb710_resume,
diff --git a/drivers/misc/cs5535-mfgpt.c b/drivers/misc/cs5535-mfgpt.c
index f505a40..9858f36 100644
--- a/drivers/misc/cs5535-mfgpt.c
+++ b/drivers/misc/cs5535-mfgpt.c
@@ -246,7 +246,7 @@ EXPORT_SYMBOL_GPL(cs5535_mfgpt_write);
  * Jordan tells me that he and Mitch once played w/ it, but it's unclear
  * what the results of that were (and they experienced some instability).
  */
-static void __devinit reset_all_timers(void)
+static void reset_all_timers(void)
 {
 	uint32_t val, dummy;
 
@@ -262,7 +262,7 @@ static void __devinit reset_all_timers(void)
  * In other cases (such as with VSAless OpenFirmware), the system firmware
  * leaves timers available for us to use.
  */
-static int __devinit scan_timers(struct cs5535_mfgpt_chip *mfgpt)
+static int scan_timers(struct cs5535_mfgpt_chip *mfgpt)
 {
 	struct cs5535_mfgpt_timer timer = { .chip = mfgpt };
 	unsigned long flags;
@@ -289,7 +289,7 @@ static int __devinit scan_timers(struct cs5535_mfgpt_chip *mfgpt)
 	return timers;
 }
 
-static int __devinit cs5535_mfgpt_probe(struct platform_device *pdev)
+static int cs5535_mfgpt_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	int err = -EIO, t;
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index ab1ad41..2baeec5 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -656,7 +656,7 @@ err_out:
 	return err;
 }
 
-static int __devexit at24_remove(struct i2c_client *client)
+static int at24_remove(struct i2c_client *client)
 {
 	struct at24_data *at24;
 	int i;
@@ -680,7 +680,7 @@ static struct i2c_driver at24_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = at24_probe,
-	.remove = __devexit_p(at24_remove),
+	.remove = at24_remove,
 	.id_table = at24_ids,
 };
 
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 4ed93dd..b08cf8a 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -459,7 +459,7 @@ fail:
 	return err;
 }
 
-static int __devexit at25_remove(struct spi_device *spi)
+static int at25_remove(struct spi_device *spi)
 {
 	struct at25_data	*at25;
 
@@ -477,7 +477,7 @@ static struct spi_driver at25_driver = {
 		.owner		= THIS_MODULE,
 	},
 	.probe		= at25_probe,
-	.remove		= __devexit_p(at25_remove),
+	.remove		= at25_remove,
 };
 
 module_spi_driver(at25_driver);
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
index ce3fe36..a6b5d5e 100644
--- a/drivers/misc/eeprom/eeprom_93xx46.c
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -309,7 +309,7 @@ static ssize_t eeprom_93xx46_store_erase(struct device *dev,
 }
 static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase);
 
-static int __devinit eeprom_93xx46_probe(struct spi_device *spi)
+static int eeprom_93xx46_probe(struct spi_device *spi)
 {
 	struct eeprom_93xx46_platform_data *pd;
 	struct eeprom_93xx46_dev *edev;
@@ -370,7 +370,7 @@ fail:
 	return err;
 }
 
-static int __devexit eeprom_93xx46_remove(struct spi_device *spi)
+static int eeprom_93xx46_remove(struct spi_device *spi)
 {
 	struct eeprom_93xx46_dev *edev = dev_get_drvdata(&spi->dev);
 
@@ -389,7 +389,7 @@ static struct spi_driver eeprom_93xx46_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= eeprom_93xx46_probe,
-	.remove		= __devexit_p(eeprom_93xx46_remove),
+	.remove		= eeprom_93xx46_remove,
 };
 
 module_spi_driver(eeprom_93xx46_driver);
diff --git a/drivers/misc/fsa9480.c b/drivers/misc/fsa9480.c
index ac96c3a..e8cbb1c 100644
--- a/drivers/misc/fsa9480.c
+++ b/drivers/misc/fsa9480.c
@@ -407,7 +407,7 @@ static int fsa9480_irq_init(struct fsa9480_usbsw *usbsw)
 	return 0;
 }
 
-static int __devinit fsa9480_probe(struct i2c_client *client,
+static int fsa9480_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@@ -462,7 +462,7 @@ fail1:
 	return ret;
 }
 
-static int __devexit fsa9480_remove(struct i2c_client *client)
+static int fsa9480_remove(struct i2c_client *client)
 {
 	struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client);
 	if (client->irq)
@@ -533,7 +533,7 @@ static struct i2c_driver fsa9480_i2c_driver = {
 		.name = "fsa9480",
 	},
 	.probe = fsa9480_probe,
-	.remove = __devexit_p(fsa9480_remove),
+	.remove = fsa9480_remove,
 	.resume = fsa9480_resume,
 	.suspend = fsa9480_suspend,
 	.id_table = fsa9480_id,
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
index 12ccdf9..621c7a3 100644
--- a/drivers/misc/hpilo.c
+++ b/drivers/misc/hpilo.c
@@ -30,7 +30,7 @@
 
 static struct class *ilo_class;
 static unsigned int ilo_major;
-static unsigned int max_ccb = MIN_CCB;
+static unsigned int max_ccb = 16;
 static char ilo_hwdev[MAX_ILO_DEV];
 
 static inline int get_entry_id(int entry)
@@ -686,7 +686,7 @@ static void ilo_unmap_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
 	pci_iounmap(pdev, hw->mmio_vaddr);
 }
 
-static int __devinit ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
+static int ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
 {
 	int error = -ENOMEM;
 
@@ -725,6 +725,9 @@ static void ilo_remove(struct pci_dev *pdev)
 	int i, minor;
 	struct ilo_hwinfo *ilo_hw = pci_get_drvdata(pdev);
 
+	if (!ilo_hw)
+		return;
+
 	clear_device(ilo_hw);
 
 	minor = MINOR(ilo_hw->cdev.dev);
@@ -748,12 +751,16 @@ static void ilo_remove(struct pci_dev *pdev)
 	ilo_hwdev[(minor / max_ccb)] = 0;
 }
 
-static int __devinit ilo_probe(struct pci_dev *pdev,
+static int ilo_probe(struct pci_dev *pdev,
 			       const struct pci_device_id *ent)
 {
-	int devnum, minor, start, error;
+	int devnum, minor, start, error = 0;
 	struct ilo_hwinfo *ilo_hw;
 
+	/* Ignore subsystem_device = 0x1979 (set by BIOS)  */
+	if (pdev->subsystem_device == 0x1979)
+		goto out;
+
 	if (max_ccb > MAX_CCB)
 		max_ccb = MAX_CCB;
 	else if (max_ccb < MIN_CCB)
@@ -852,7 +859,7 @@ static struct pci_driver ilo_driver = {
 	.name 	  = ILO_NAME,
 	.id_table = ilo_devices,
 	.probe 	  = ilo_probe,
-	.remove   = __devexit_p(ilo_remove),
+	.remove   = ilo_remove,
 };
 
 static int __init ilo_init(void)
@@ -892,14 +899,14 @@ static void __exit ilo_exit(void)
 	class_destroy(ilo_class);
 }
 
-MODULE_VERSION("1.3");
+MODULE_VERSION("1.4");
 MODULE_ALIAS(ILO_NAME);
 MODULE_DESCRIPTION(ILO_NAME);
 MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>");
 MODULE_LICENSE("GPL v2");
 
 module_param(max_ccb, uint, 0444);
-MODULE_PARM_DESC(max_ccb, "Maximum number of HP iLO channels to attach (8)");
+MODULE_PARM_DESC(max_ccb, "Maximum number of HP iLO channels to attach (16)");
 
 module_init(ilo_init);
 module_exit(ilo_exit);
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
index 168d800..0346d87 100644
--- a/drivers/misc/ibmasm/module.c
+++ b/drivers/misc/ibmasm/module.c
@@ -62,7 +62,7 @@ module_param(ibmasm_debug, int , S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(ibmasm_debug, " Set debug mode on or off");
 
 
-static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	int result;
 	struct service_processor *sp;
@@ -163,7 +163,7 @@ error_resources:
 	return result;
 }
 
-static void __devexit ibmasm_remove_one(struct pci_dev *pdev)
+static void ibmasm_remove_one(struct pci_dev *pdev)
 {
 	struct service_processor *sp = (struct service_processor *)pci_get_drvdata(pdev);
 
@@ -198,7 +198,7 @@ static struct pci_driver ibmasm_driver = {
 	.name		= DRIVER_NAME,
 	.id_table	= ibmasm_pci_table,
 	.probe		= ibmasm_init_one,
-	.remove		= __devexit_p(ibmasm_remove_one),
+	.remove		= ibmasm_remove_one,
 };
 
 static void __exit ibmasm_exit (void)
diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c
index 6a77106..06f6ad2 100644
--- a/drivers/misc/ioc4.c
+++ b/drivers/misc/ioc4.c
@@ -139,7 +139,7 @@ ioc4_unregister_submodule(struct ioc4_submodule *is)
  * even though the following code utilizes external interrupt registers
  * to perform the speed calculation.
  */
-static void __devinit
+static void
 ioc4_clock_calibrate(struct ioc4_driver_data *idd)
 {
 	union ioc4_int_out int_out;
@@ -231,7 +231,7 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd)
  * on the same PCI bus at slot number 3 to differentiate IO9 from IO10.
  * If neither is present, it's a PCI-RT.
  */
-static unsigned int __devinit
+static unsigned int
 ioc4_variant(struct ioc4_driver_data *idd)
 {
 	struct pci_dev *pdev = NULL;
@@ -279,7 +279,7 @@ ioc4_load_modules(struct work_struct *work)
 static DECLARE_WORK(ioc4_load_modules_work, ioc4_load_modules);
 
 /* Adds a new instance of an IOC4 card */
-static int __devinit
+static int
 ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
 {
 	struct ioc4_driver_data *idd;
@@ -415,7 +415,7 @@ out:
 }
 
 /* Removes a particular instance of an IOC4 card. */
-static void __devexit
+static void
 ioc4_remove(struct pci_dev *pdev)
 {
 	struct ioc4_submodule *is;
@@ -466,7 +466,7 @@ static struct pci_driver ioc4_driver = {
 	.name = "IOC4",
 	.id_table = ioc4_id_table,
 	.probe = ioc4_probe,
-	.remove = __devexit_p(ioc4_remove),
+	.remove = ioc4_remove,
 };
 
 MODULE_DEVICE_TABLE(pci, ioc4_id_table);
diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c
index eb5de2e..29b306c 100644
--- a/drivers/misc/isl29003.c
+++ b/drivers/misc/isl29003.c
@@ -365,7 +365,7 @@ static int isl29003_init_client(struct i2c_client *client)
  * I2C layer
  */
 
-static int __devinit isl29003_probe(struct i2c_client *client,
+static int isl29003_probe(struct i2c_client *client,
 				    const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@@ -401,7 +401,7 @@ exit_kfree:
 	return err;
 }
 
-static int __devexit isl29003_remove(struct i2c_client *client)
+static int isl29003_remove(struct i2c_client *client)
 {
 	sysfs_remove_group(&client->dev.kobj, &isl29003_attr_group);
 	isl29003_set_power_state(client, 0);
@@ -451,7 +451,7 @@ static struct i2c_driver isl29003_driver = {
 	.suspend = isl29003_suspend,
 	.resume	= isl29003_resume,
 	.probe	= isl29003_probe,
-	.remove	= __devexit_p(isl29003_remove),
+	.remove	= isl29003_remove,
 	.id_table = isl29003_id,
 };
 
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
index 60ec868..7c97550 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
@@ -114,7 +114,7 @@ static struct of_device_id lis3lv02d_i2c_dt_ids[] = {
 MODULE_DEVICE_TABLE(of, lis3lv02d_i2c_dt_ids);
 #endif
 
-static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
+static int lis3lv02d_i2c_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	int ret = 0;
@@ -191,7 +191,7 @@ fail:
 	return ret;
 }
 
-static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
+static int lis3lv02d_i2c_remove(struct i2c_client *client)
 {
 	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
 	struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
@@ -280,7 +280,7 @@ static struct i2c_driver lis3lv02d_i2c_driver = {
 		.of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids),
 	},
 	.probe	= lis3lv02d_i2c_probe,
-	.remove	= __devexit_p(lis3lv02d_i2c_remove),
+	.remove	= lis3lv02d_i2c_remove,
 	.id_table = lis3lv02d_id,
 };
 
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
index ccb6475..9aa2bd2 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d_spi.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
@@ -69,7 +69,7 @@ static struct of_device_id lis302dl_spi_dt_ids[] = {
 MODULE_DEVICE_TABLE(of, lis302dl_spi_dt_ids);
 #endif
 
-static int __devinit lis302dl_spi_probe(struct spi_device *spi)
+static int lis302dl_spi_probe(struct spi_device *spi)
 {
 	int ret;
 
@@ -100,7 +100,7 @@ static int __devinit lis302dl_spi_probe(struct spi_device *spi)
 	return lis3lv02d_init_device(&lis3_dev);
 }
 
-static int __devexit lis302dl_spi_remove(struct spi_device *spi)
+static int lis302dl_spi_remove(struct spi_device *spi)
 {
 	struct lis3lv02d *lis3 = spi_get_drvdata(spi);
 	lis3lv02d_joystick_disable(lis3);
@@ -144,7 +144,7 @@ static struct spi_driver lis302dl_spi_driver = {
 		.of_match_table = of_match_ptr(lis302dl_spi_dt_ids),
 	},
 	.probe	= lis302dl_spi_probe,
-	.remove	= __devexit_p(lis302dl_spi_remove),
+	.remove	= lis302dl_spi_remove,
 };
 
 module_spi_driver(lis302dl_spi_driver);
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index 57168db..0017842 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -8,4 +8,5 @@ mei-objs += interrupt.o
 mei-objs += interface.o
 mei-objs += iorw.o
 mei-objs += main.o
+mei-objs += amthif.o
 mei-objs += wd.o
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
new file mode 100644
index 0000000..18794ae
--- /dev/null
+++ b/drivers/misc/mei/amthif.c
@@ -0,0 +1,722 @@
+/*
+ *
+ * Intel Management Engine Interface (Intel MEI) Linux driver
+ * Copyright (c) 2003-2012, 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/aio.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/cdev.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/uuid.h>
+#include <linux/jiffies.h>
+#include <linux/uaccess.h>
+
+
+#include "mei_dev.h"
+#include "hw.h"
+#include <linux/mei.h>
+#include "interface.h"
+
+const uuid_le mei_amthi_guid  = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
+						0xa8, 0x46, 0xe0, 0xff, 0x65,
+						0x81, 0x4c);
+
+/**
+ * mei_amthif_reset_params - initializes mei device iamthif
+ *
+ * @dev: the device structure
+ */
+void mei_amthif_reset_params(struct mei_device *dev)
+{
+	/* reset iamthif parameters. */
+	dev->iamthif_current_cb = NULL;
+	dev->iamthif_msg_buf_size = 0;
+	dev->iamthif_msg_buf_index = 0;
+	dev->iamthif_canceled = false;
+	dev->iamthif_ioctl = false;
+	dev->iamthif_state = MEI_IAMTHIF_IDLE;
+	dev->iamthif_timer = 0;
+}
+
+/**
+ * mei_amthif_host_init_ - mei initialization amthif client.
+ *
+ * @dev: the device structure
+ *
+ */
+void mei_amthif_host_init(struct mei_device *dev)
+{
+	int i;
+	unsigned char *msg_buf;
+
+	mei_cl_init(&dev->iamthif_cl, dev);
+	dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
+
+	/* find ME amthi client */
+	i = mei_me_cl_link(dev, &dev->iamthif_cl,
+			    &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID);
+	if (i < 0) {
+		dev_info(&dev->pdev->dev, "failed to find iamthif client.\n");
+		return;
+	}
+
+	/* Assign iamthif_mtu to the value received from ME  */
+
+	dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length;
+	dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n",
+			dev->me_clients[i].props.max_msg_length);
+
+	kfree(dev->iamthif_msg_buf);
+	dev->iamthif_msg_buf = NULL;
+
+	/* allocate storage for ME message buffer */
+	msg_buf = kcalloc(dev->iamthif_mtu,
+			sizeof(unsigned char), GFP_KERNEL);
+	if (!msg_buf) {
+		dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n");
+		return;
+	}
+
+	dev->iamthif_msg_buf = msg_buf;
+
+	if (mei_connect(dev, &dev->iamthif_cl)) {
+		dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n");
+		dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
+		dev->iamthif_cl.host_client_id = 0;
+	} else {
+		dev->iamthif_cl.timer_count = MEI_CONNECT_TIMEOUT;
+	}
+}
+
+/**
+ * mei_amthif_find_read_list_entry - finds a amthilist entry for current file
+ *
+ * @dev: the device structure
+ * @file: pointer to file object
+ *
+ * returns   returned a list entry on success, NULL on failure.
+ */
+struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
+						struct file *file)
+{
+	struct mei_cl_cb *pos = NULL;
+	struct mei_cl_cb *next = NULL;
+
+	list_for_each_entry_safe(pos, next,
+				&dev->amthif_rd_complete_list.list, list) {
+		if (pos->cl && pos->cl == &dev->iamthif_cl &&
+			pos->file_object == file)
+			return pos;
+	}
+	return NULL;
+}
+
+
+/**
+ * mei_amthif_read - read data from AMTHIF client
+ *
+ * @dev: the device structure
+ * @if_num:  minor number
+ * @file: pointer to file object
+ * @*ubuf: pointer to user data in user space
+ * @length: data length to read
+ * @offset: data read offset
+ *
+ * Locking: called under "dev->device_lock" lock
+ *
+ * returns
+ *  returned data length on success,
+ *  zero if no data to read,
+ *  negative on failure.
+ */
+int mei_amthif_read(struct mei_device *dev, struct file *file,
+	       char __user *ubuf, size_t length, loff_t *offset)
+{
+	int rets;
+	int wait_ret;
+	struct mei_cl_cb *cb = NULL;
+	struct mei_cl *cl = file->private_data;
+	unsigned long timeout;
+	int i;
+
+	/* Only Posible if we are in timeout */
+	if (!cl || cl != &dev->iamthif_cl) {
+		dev_dbg(&dev->pdev->dev, "bad file ext.\n");
+		return -ETIMEDOUT;
+	}
+
+	i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
+
+	if (i < 0) {
+		dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
+		return -ENODEV;
+	}
+	dev_dbg(&dev->pdev->dev, "checking amthi data\n");
+	cb = mei_amthif_find_read_list_entry(dev, file);
+
+	/* Check for if we can block or not*/
+	if (cb == NULL && file->f_flags & O_NONBLOCK)
+		return -EAGAIN;
+
+
+	dev_dbg(&dev->pdev->dev, "waiting for amthi data\n");
+	while (cb == NULL) {
+		/* unlock the Mutex */
+		mutex_unlock(&dev->device_lock);
+
+		wait_ret = wait_event_interruptible(dev->iamthif_cl.wait,
+			(cb = mei_amthif_find_read_list_entry(dev, file)));
+
+		if (wait_ret)
+			return -ERESTARTSYS;
+
+		dev_dbg(&dev->pdev->dev, "woke up from sleep\n");
+
+		/* Locking again the Mutex */
+		mutex_lock(&dev->device_lock);
+	}
+
+
+	dev_dbg(&dev->pdev->dev, "Got amthi data\n");
+	dev->iamthif_timer = 0;
+
+	if (cb) {
+		timeout = cb->read_time +
+			mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
+		dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n",
+				timeout);
+
+		if  (time_after(jiffies, timeout)) {
+			dev_dbg(&dev->pdev->dev, "amthi Time out\n");
+			/* 15 sec for the message has expired */
+			list_del(&cb->list);
+			rets = -ETIMEDOUT;
+			goto free;
+		}
+	}
+	/* if the whole message will fit remove it from the list */
+	if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset))
+		list_del(&cb->list);
+	else if (cb->buf_idx > 0 && cb->buf_idx <= *offset) {
+		/* end of the message has been reached */
+		list_del(&cb->list);
+		rets = 0;
+		goto free;
+	}
+		/* else means that not full buffer will be read and do not
+		 * remove message from deletion list
+		 */
+
+	dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n",
+	    cb->response_buffer.size);
+	dev_dbg(&dev->pdev->dev, "amthi cb->buf_idx - %lu\n", cb->buf_idx);
+
+	/* length is being turncated to PAGE_SIZE, however,
+	 * the buf_idx may point beyond */
+	length = min_t(size_t, length, (cb->buf_idx - *offset));
+
+	if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length))
+		rets = -EFAULT;
+	else {
+		rets = length;
+		if ((*offset + length) < cb->buf_idx) {
+			*offset += length;
+			goto out;
+		}
+	}
+free:
+	dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n");
+	*offset = 0;
+	mei_io_cb_free(cb);
+out:
+	return rets;
+}
+
+/**
+ * mei_amthif_send_cmd - send amthif command to the ME
+ *
+ * @dev: the device structure
+ * @cb: mei call back struct
+ *
+ * returns 0 on success, <0 on failure.
+ *
+ */
+static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
+{
+	struct mei_msg_hdr mei_hdr;
+	int ret;
+
+	if (!dev || !cb)
+		return -ENODEV;
+
+	dev_dbg(&dev->pdev->dev, "write data to amthi client.\n");
+
+	dev->iamthif_state = MEI_IAMTHIF_WRITING;
+	dev->iamthif_current_cb = cb;
+	dev->iamthif_file_object = cb->file_object;
+	dev->iamthif_canceled = false;
+	dev->iamthif_ioctl = true;
+	dev->iamthif_msg_buf_size = cb->request_buffer.size;
+	memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
+	       cb->request_buffer.size);
+
+	ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl);
+	if (ret < 0)
+		return ret;
+
+	if (ret && dev->mei_host_buffer_is_empty) {
+		ret = 0;
+		dev->mei_host_buffer_is_empty = false;
+		if (cb->request_buffer.size > mei_hbuf_max_data(dev)) {
+			mei_hdr.length = mei_hbuf_max_data(dev);
+			mei_hdr.msg_complete = 0;
+		} else {
+			mei_hdr.length = cb->request_buffer.size;
+			mei_hdr.msg_complete = 1;
+		}
+
+		mei_hdr.host_addr = dev->iamthif_cl.host_client_id;
+		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),
+					mei_hdr.length))
+			return -ENODEV;
+
+		if (mei_hdr.msg_complete) {
+			if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl))
+				return -ENODEV;
+			dev->iamthif_flow_control_pending = true;
+			dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
+			dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n");
+			dev->iamthif_current_cb = cb;
+			dev->iamthif_file_object = cb->file_object;
+			list_add_tail(&cb->list, &dev->write_waiting_list.list);
+		} else {
+			dev_dbg(&dev->pdev->dev, "message does not complete, so add amthi cb to write list.\n");
+			list_add_tail(&cb->list, &dev->write_list.list);
+		}
+	} else {
+		if (!(dev->mei_host_buffer_is_empty))
+			dev_dbg(&dev->pdev->dev, "host buffer is not empty");
+
+		dev_dbg(&dev->pdev->dev, "No flow control credentials, so add iamthif cb to write list.\n");
+		list_add_tail(&cb->list, &dev->write_list.list);
+	}
+	return 0;
+}
+
+/**
+ * mei_amthif_write - write amthif data to amthif client
+ *
+ * @dev: the device structure
+ * @cb: mei call back struct
+ *
+ * returns 0 on success, <0 on failure.
+ *
+ */
+int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
+{
+	int ret;
+
+	if (!dev || !cb)
+		return -ENODEV;
+
+	ret = mei_io_cb_alloc_resp_buf(cb, dev->iamthif_mtu);
+	if (ret)
+		return ret;
+
+	cb->fop_type = MEI_FOP_IOCTL;
+
+	if (!list_empty(&dev->amthif_cmd_list.list) ||
+	    dev->iamthif_state != MEI_IAMTHIF_IDLE) {
+		dev_dbg(&dev->pdev->dev,
+			"amthif state = %d\n", dev->iamthif_state);
+		dev_dbg(&dev->pdev->dev, "AMTHIF: add cb to the wait list\n");
+		list_add_tail(&cb->list, &dev->amthif_cmd_list.list);
+		return 0;
+	}
+	return mei_amthif_send_cmd(dev, cb);
+}
+/**
+ * mei_amthif_run_next_cmd
+ *
+ * @dev: the device structure
+ *
+ * returns 0 on success, <0 on failure.
+ */
+void mei_amthif_run_next_cmd(struct mei_device *dev)
+{
+	struct mei_cl_cb *pos = NULL;
+	struct mei_cl_cb *next = NULL;
+	int status;
+
+	if (!dev)
+		return;
+
+	dev->iamthif_msg_buf_size = 0;
+	dev->iamthif_msg_buf_index = 0;
+	dev->iamthif_canceled = false;
+	dev->iamthif_ioctl = true;
+	dev->iamthif_state = MEI_IAMTHIF_IDLE;
+	dev->iamthif_timer = 0;
+	dev->iamthif_file_object = NULL;
+
+	dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n");
+
+	list_for_each_entry_safe(pos, next, &dev->amthif_cmd_list.list, list) {
+		list_del(&pos->list);
+
+		if (pos->cl && pos->cl == &dev->iamthif_cl) {
+			status = mei_amthif_send_cmd(dev, pos);
+			if (status) {
+				dev_dbg(&dev->pdev->dev,
+					"amthi write failed status = %d\n",
+						status);
+				return;
+			}
+			break;
+		}
+	}
+}
+
+
+unsigned int mei_amthif_poll(struct mei_device *dev,
+		struct file *file, poll_table *wait)
+{
+	unsigned int mask = 0;
+	mutex_unlock(&dev->device_lock);
+	poll_wait(file, &dev->iamthif_cl.wait, wait);
+	mutex_lock(&dev->device_lock);
+	if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
+		dev->iamthif_file_object == file) {
+		mask |= (POLLIN | POLLRDNORM);
+		dev_dbg(&dev->pdev->dev, "run next amthi cb\n");
+		mei_amthif_run_next_cmd(dev);
+	}
+	return mask;
+}
+
+
+
+/**
+ * mei_amthif_irq_process_completed - processes completed iamthif operation.
+ *
+ * @dev: the device structure.
+ * @slots: free slots.
+ * @cb_pos: callback block.
+ * @cl: private data of the file object.
+ * @cmpl_list: complete list.
+ *
+ * returns 0, OK; otherwise, error.
+ */
+int mei_amthif_irq_write_complete(struct mei_device *dev, s32 *slots,
+			struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list)
+{
+	struct mei_msg_hdr *mei_hdr;
+	struct mei_cl *cl = cb->cl;
+	size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index;
+	size_t msg_slots = mei_data2slots(len);
+
+	mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
+	mei_hdr->host_addr = cl->host_client_id;
+	mei_hdr->me_addr = cl->me_client_id;
+	mei_hdr->reserved = 0;
+
+	if (*slots >= msg_slots) {
+		mei_hdr->length = len;
+		mei_hdr->msg_complete = 1;
+	/* Split the message only if we can write the whole host buffer */
+	} else if (*slots == dev->hbuf_depth) {
+		msg_slots = *slots;
+		len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
+		mei_hdr->length = len;
+		mei_hdr->msg_complete = 0;
+	} else {
+		/* wait for next time the host buffer is empty */
+		return 0;
+	}
+
+	dev_dbg(&dev->pdev->dev, "msg: len = %d complete = %d\n",
+			mei_hdr->length, mei_hdr->msg_complete);
+
+	*slots -=  msg_slots;
+	if (mei_write_message(dev, mei_hdr,
+		dev->iamthif_msg_buf + dev->iamthif_msg_buf_index,
+		mei_hdr->length)) {
+			dev->iamthif_state = MEI_IAMTHIF_IDLE;
+			cl->status = -ENODEV;
+			list_del(&cb->list);
+			return -ENODEV;
+	}
+
+	if (mei_flow_ctrl_reduce(dev, cl))
+		return -ENODEV;
+
+	dev->iamthif_msg_buf_index += mei_hdr->length;
+	cl->status = 0;
+
+	if (mei_hdr->msg_complete) {
+		dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
+		dev->iamthif_flow_control_pending = true;
+
+		/* save iamthif cb sent to amthi client */
+		cb->buf_idx = dev->iamthif_msg_buf_index;
+		dev->iamthif_current_cb = cb;
+
+		list_move_tail(&cb->list, &dev->write_waiting_list.list);
+	}
+
+
+	return 0;
+}
+
+/**
+ * mei_amthif_irq_read_message - read routine after ISR to
+ *			handle the read amthi message
+ *
+ * @complete_list: An instance of our list structure
+ * @dev: the device structure
+ * @mei_hdr: header of amthi message
+ *
+ * returns 0 on success, <0 on failure.
+ */
+int mei_amthif_irq_read_message(struct mei_cl_cb *complete_list,
+		struct mei_device *dev, struct mei_msg_hdr *mei_hdr)
+{
+	struct mei_cl_cb *cb;
+	unsigned char *buffer;
+
+	BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id);
+	BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING);
+
+	buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
+	BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length);
+
+	mei_read_slots(dev, buffer, mei_hdr->length);
+
+	dev->iamthif_msg_buf_index += mei_hdr->length;
+
+	if (!mei_hdr->msg_complete)
+		return 0;
+
+	dev_dbg(&dev->pdev->dev,
+			"amthi_message_buffer_index =%d\n",
+			mei_hdr->length);
+
+	dev_dbg(&dev->pdev->dev, "completed amthi read.\n ");
+	if (!dev->iamthif_current_cb)
+		return -ENODEV;
+
+	cb = dev->iamthif_current_cb;
+	dev->iamthif_current_cb = NULL;
+
+	if (!cb->cl)
+		return -ENODEV;
+
+	dev->iamthif_stall_timer = 0;
+	cb->buf_idx = dev->iamthif_msg_buf_index;
+	cb->read_time = jiffies;
+	if (dev->iamthif_ioctl && cb->cl == &dev->iamthif_cl) {
+		/* found the iamthif cb */
+		dev_dbg(&dev->pdev->dev, "complete the amthi read cb.\n ");
+		dev_dbg(&dev->pdev->dev, "add the amthi read cb to complete.\n ");
+		list_add_tail(&cb->list, &complete_list->list);
+	}
+	return 0;
+}
+
+/**
+ * mei_amthif_irq_read - prepares to read amthif data.
+ *
+ * @dev: the device structure.
+ * @slots: free slots.
+ *
+ * returns 0, OK; otherwise, error.
+ */
+int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
+{
+
+	if (((*slots) * sizeof(u32)) < (sizeof(struct mei_msg_hdr)
+			+ sizeof(struct hbm_flow_control))) {
+		return -EMSGSIZE;
+	}
+	*slots -= mei_data2slots(sizeof(struct hbm_flow_control));
+	if (mei_send_flow_control(dev, &dev->iamthif_cl)) {
+		dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
+		return -EIO;
+	}
+
+	dev_dbg(&dev->pdev->dev, "iamthif flow control success\n");
+	dev->iamthif_state = MEI_IAMTHIF_READING;
+	dev->iamthif_flow_control_pending = false;
+	dev->iamthif_msg_buf_index = 0;
+	dev->iamthif_msg_buf_size = 0;
+	dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
+	dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
+	return 0;
+}
+
+/**
+ * mei_amthif_complete - complete amthif callback.
+ *
+ * @dev: the device structure.
+ * @cb_pos: callback block.
+ */
+void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
+{
+	if (dev->iamthif_canceled != 1) {
+		dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
+		dev->iamthif_stall_timer = 0;
+		memcpy(cb->response_buffer.data,
+				dev->iamthif_msg_buf,
+				dev->iamthif_msg_buf_index);
+		list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list);
+		dev_dbg(&dev->pdev->dev, "amthi read completed\n");
+		dev->iamthif_timer = jiffies;
+		dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
+				dev->iamthif_timer);
+	} else {
+		mei_amthif_run_next_cmd(dev);
+	}
+
+	dev_dbg(&dev->pdev->dev, "completing amthi call back.\n");
+	wake_up_interruptible(&dev->iamthif_cl.wait);
+}
+
+/**
+ * mei_clear_list - removes all callbacks associated with file
+ *		from mei_cb_list
+ *
+ * @dev: device structure.
+ * @file: file structure
+ * @mei_cb_list: callbacks list
+ *
+ * mei_clear_list is called to clear resources associated with file
+ * when application calls close function or Ctrl-C was pressed
+ *
+ * returns true if callback removed from the list, false otherwise
+ */
+static bool mei_clear_list(struct mei_device *dev,
+		const struct file *file, struct list_head *mei_cb_list)
+{
+	struct mei_cl_cb *cb_pos = NULL;
+	struct mei_cl_cb *cb_next = NULL;
+	bool removed = false;
+
+	/* list all list member */
+	list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, list) {
+		/* check if list member associated with a file */
+		if (file == cb_pos->file_object) {
+			/* remove member from the list */
+			list_del(&cb_pos->list);
+			/* check if cb equal to current iamthif cb */
+			if (dev->iamthif_current_cb == cb_pos) {
+				dev->iamthif_current_cb = NULL;
+				/* send flow control to iamthif client */
+				mei_send_flow_control(dev, &dev->iamthif_cl);
+			}
+			/* free all allocated buffers */
+			mei_io_cb_free(cb_pos);
+			cb_pos = NULL;
+			removed = true;
+		}
+	}
+	return removed;
+}
+
+/**
+ * mei_clear_lists - removes all callbacks associated with file
+ *
+ * @dev: device structure
+ * @file: file structure
+ *
+ * mei_clear_lists is called to clear resources associated with file
+ * when application calls close function or Ctrl-C was pressed
+ *
+ * returns true if callback removed from the list, false otherwise
+ */
+static bool mei_clear_lists(struct mei_device *dev, struct file *file)
+{
+	bool removed = false;
+
+	/* remove callbacks associated with a file */
+	mei_clear_list(dev, file, &dev->amthif_cmd_list.list);
+	if (mei_clear_list(dev, file, &dev->amthif_rd_complete_list.list))
+		removed = true;
+
+	mei_clear_list(dev, file, &dev->ctrl_rd_list.list);
+
+	if (mei_clear_list(dev, file, &dev->ctrl_wr_list.list))
+		removed = true;
+
+	if (mei_clear_list(dev, file, &dev->write_waiting_list.list))
+		removed = true;
+
+	if (mei_clear_list(dev, file, &dev->write_list.list))
+		removed = true;
+
+	/* check if iamthif_current_cb not NULL */
+	if (dev->iamthif_current_cb && !removed) {
+		/* check file and iamthif current cb association */
+		if (dev->iamthif_current_cb->file_object == file) {
+			/* remove cb */
+			mei_io_cb_free(dev->iamthif_current_cb);
+			dev->iamthif_current_cb = NULL;
+			removed = true;
+		}
+	}
+	return removed;
+}
+
+/**
+* mei_amthif_release - the release function
+*
+*  @inode: pointer to inode structure
+*  @file: pointer to file structure
+*
+*  returns 0 on success, <0 on error
+*/
+int mei_amthif_release(struct mei_device *dev, struct file *file)
+{
+	if (dev->open_handle_count > 0)
+		dev->open_handle_count--;
+
+	if (dev->iamthif_file_object == file &&
+	    dev->iamthif_state != MEI_IAMTHIF_IDLE) {
+
+		dev_dbg(&dev->pdev->dev, "amthi canceled iamthif state %d\n",
+		    dev->iamthif_state);
+		dev->iamthif_canceled = true;
+		if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
+			dev_dbg(&dev->pdev->dev, "run next amthi iamthif cb\n");
+			mei_amthif_run_next_cmd(dev);
+		}
+	}
+
+	if (mei_clear_lists(dev, file))
+		dev->iamthif_state = MEI_IAMTHIF_IDLE;
+
+	return 0;
+}
diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h
index 9700532..be8ca6b 100644
--- a/drivers/misc/mei/hw.h
+++ b/drivers/misc/mei/hw.h
@@ -20,16 +20,16 @@
 #include <linux/uuid.h>
 
 /*
- * Timeouts
+ * Timeouts in Seconds
  */
-#define MEI_INTEROP_TIMEOUT    (HZ * 7)
-#define MEI_CONNECT_TIMEOUT		3	/* at least 2 seconds */
+#define MEI_INTEROP_TIMEOUT         7  /* Timeout on ready message */
+#define MEI_CONNECT_TIMEOUT         3  /* HPS: at least 2 seconds */
 
-#define CONNECT_TIMEOUT        15	/* HPS definition */
-#define INIT_CLIENTS_TIMEOUT   15	/* HPS definition */
+#define MEI_CL_CONNECT_TIMEOUT     15  /* HPS: Client Connect Timeout */
+#define MEI_CLIENTS_INIT_TIMEOUT   15  /* HPS: Clients Enumeration Timeout */
 
-#define IAMTHIF_STALL_TIMER		12	/* seconds */
-#define IAMTHIF_READ_TIMER		10000	/* ms */
+#define MEI_IAMTHIF_STALL_TIMER    12  /* HPS */
+#define MEI_IAMTHIF_READ_TIMER     10  /* HPS */
 
 /*
  * Internal Clients Number
@@ -293,6 +293,14 @@ struct hbm_props_response {
 	struct mei_client_properties client_properties;
 } __packed;
 
+/**
+ * struct hbm_client_connect_request - connect/disconnect request
+ *
+ * @hbm_cmd - bus message command header
+ * @me_addr - address of the client in ME
+ * @host_addr - address of the client in the driver
+ * @reserved
+ */
 struct hbm_client_connect_request {
 	u8 hbm_cmd;
 	u8 me_addr;
@@ -300,6 +308,14 @@ struct hbm_client_connect_request {
 	u8 reserved;
 } __packed;
 
+/**
+ * struct hbm_client_connect_response - connect/disconnect response
+ *
+ * @hbm_cmd - bus message command header
+ * @me_addr - address of the client in ME
+ * @host_addr - address of the client in the driver
+ * @status - status of the request
+ */
 struct hbm_client_connect_response {
 	u8 hbm_cmd;
 	u8 me_addr;
@@ -307,12 +323,6 @@ struct hbm_client_connect_response {
 	u8 status;
 } __packed;
 
-struct hbm_client_disconnect_request {
-	u8 hbm_cmd;
-	u8 me_addr;
-	u8 host_addr;
-	u8 reserved[1];
-} __packed;
 
 #define MEI_FC_MESSAGE_RESERVED_LENGTH           5
 
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 98f1430..a54cd55 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -43,21 +43,6 @@ const char *mei_dev_state_str(int state)
 }
 
 
-const uuid_le mei_amthi_guid  = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
-						0xa8, 0x46, 0xe0, 0xff, 0x65,
-						0x81, 0x4c);
-
-/**
- * mei_io_list_init - Sets up a queue list.
- *
- * @list: An instance io list structure
- * @dev: the device structure
- */
-void mei_io_list_init(struct mei_io_list *list)
-{
-	/* initialize our queue list */
-	INIT_LIST_HEAD(&list->mei_cb.cb_list);
-}
 
 /**
  * mei_io_list_flush - removes list entry belonging to cl.
@@ -65,17 +50,15 @@ void mei_io_list_init(struct mei_io_list *list)
  * @list:  An instance of our list structure
  * @cl: private data of the file object
  */
-void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl)
+void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
 {
 	struct mei_cl_cb *pos;
 	struct mei_cl_cb *next;
 
-	list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) {
-		if (pos->file_private) {
-			struct mei_cl *cl_tmp;
-			cl_tmp = (struct mei_cl *)pos->file_private;
-			if (mei_cl_cmp_id(cl, cl_tmp))
-				list_del(&pos->cb_list);
+	list_for_each_entry_safe(pos, next, &list->list, list) {
+		if (pos->cl) {
+			if (mei_cl_cmp_id(cl, pos->cl))
+				list_del(&pos->list);
 		}
 	}
 }
@@ -96,31 +79,14 @@ int mei_cl_flush_queues(struct mei_cl *cl)
 	mei_io_list_flush(&cl->dev->write_waiting_list, cl);
 	mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
 	mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
-	mei_io_list_flush(&cl->dev->amthi_cmd_list, cl);
-	mei_io_list_flush(&cl->dev->amthi_read_complete_list, cl);
+	mei_io_list_flush(&cl->dev->amthif_cmd_list, cl);
+	mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl);
 	return 0;
 }
 
 
 
 /**
- * mei_reset_iamthif_params - initializes mei device iamthif
- *
- * @dev: the device structure
- */
-static void mei_reset_iamthif_params(struct mei_device *dev)
-{
-	/* reset iamthif parameters. */
-	dev->iamthif_current_cb = NULL;
-	dev->iamthif_msg_buf_size = 0;
-	dev->iamthif_msg_buf_index = 0;
-	dev->iamthif_canceled = false;
-	dev->iamthif_ioctl = false;
-	dev->iamthif_state = MEI_IAMTHIF_IDLE;
-	dev->iamthif_timer = 0;
-}
-
-/**
  * init_mei_device - allocates and initializes the mei device structure
  *
  * @pdev: The pci device structure
@@ -144,16 +110,14 @@ struct mei_device *mei_device_init(struct pci_dev *pdev)
 	init_waitqueue_head(&dev->wait_stop_wd);
 	dev->dev_state = MEI_DEV_INITIALIZING;
 	dev->iamthif_state = MEI_IAMTHIF_IDLE;
-	dev->wd_interface_reg = false;
-
 
 	mei_io_list_init(&dev->read_list);
 	mei_io_list_init(&dev->write_list);
 	mei_io_list_init(&dev->write_waiting_list);
 	mei_io_list_init(&dev->ctrl_wr_list);
 	mei_io_list_init(&dev->ctrl_rd_list);
-	mei_io_list_init(&dev->amthi_cmd_list);
-	mei_io_list_init(&dev->amthi_read_complete_list);
+	mei_io_list_init(&dev->amthif_cmd_list);
+	mei_io_list_init(&dev->amthif_rd_complete_list);
 	dev->pdev = pdev;
 	return dev;
 }
@@ -196,7 +160,8 @@ int mei_hw_init(struct mei_device *dev)
 	if (!dev->recvd_msg) {
 		mutex_unlock(&dev->device_lock);
 		err = wait_event_interruptible_timeout(dev->wait_recvd_msg,
-			dev->recvd_msg, MEI_INTEROP_TIMEOUT);
+			dev->recvd_msg,
+			mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT));
 		mutex_lock(&dev->device_lock);
 	}
 
@@ -317,15 +282,13 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
 			cl_pos->timer_count = 0;
 		}
 		/* remove entry if already in list */
-		dev_dbg(&dev->pdev->dev, "list del iamthif and wd file list.\n");
-		mei_remove_client_from_file_list(dev,
-				dev->wd_cl.host_client_id);
+		dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n");
+		mei_me_cl_unlink(dev, &dev->wd_cl);
 
-		mei_remove_client_from_file_list(dev,
-				dev->iamthif_cl.host_client_id);
+		mei_me_cl_unlink(dev, &dev->iamthif_cl);
 
-		mei_reset_iamthif_params(dev);
-		dev->extra_write_index = 0;
+		mei_amthif_reset_params(dev);
+		memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg));
 	}
 
 	dev->me_clients_num = 0;
@@ -351,10 +314,9 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
 		}
 	}
 	/* remove all waiting requests */
-	list_for_each_entry_safe(cb_pos, cb_next,
-			&dev->write_list.mei_cb.cb_list, cb_list) {
-		list_del(&cb_pos->cb_list);
-		mei_free_cb_private(cb_pos);
+	list_for_each_entry_safe(cb_pos, cb_next, &dev->write_list.list, list) {
+		list_del(&cb_pos->list);
+		mei_io_cb_free(cb_pos);
 	}
 }
 
@@ -370,31 +332,26 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
 void mei_host_start_message(struct mei_device *dev)
 {
 	struct mei_msg_hdr *mei_hdr;
-	struct hbm_host_version_request *host_start_req;
+	struct hbm_host_version_request *start_req;
+	const size_t len = sizeof(struct hbm_host_version_request);
+
+	mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
 
 	/* host start message */
-	mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
-	mei_hdr->host_addr = 0;
-	mei_hdr->me_addr = 0;
-	mei_hdr->length = sizeof(struct hbm_host_version_request);
-	mei_hdr->msg_complete = 1;
-	mei_hdr->reserved = 0;
-
-	host_start_req =
-	    (struct hbm_host_version_request *) &dev->wr_msg_buf[1];
-	memset(host_start_req, 0, sizeof(struct hbm_host_version_request));
-	host_start_req->hbm_cmd = HOST_START_REQ_CMD;
-	host_start_req->host_version.major_version = HBM_MAJOR_VERSION;
-	host_start_req->host_version.minor_version = HBM_MINOR_VERSION;
+	start_req = (struct hbm_host_version_request *)&dev->wr_msg_buf[1];
+	memset(start_req, 0, len);
+	start_req->hbm_cmd = HOST_START_REQ_CMD;
+	start_req->host_version.major_version = HBM_MAJOR_VERSION;
+	start_req->host_version.minor_version = HBM_MINOR_VERSION;
+
 	dev->recvd_msg = false;
-	if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req,
-				       mei_hdr->length)) {
+	if (mei_write_message(dev, mei_hdr, (unsigned char *)start_req, len)) {
 		dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n");
 		dev->dev_state = MEI_DEV_RESETING;
 		mei_reset(dev, 1);
 	}
 	dev->init_clients_state = MEI_START_MESSAGE;
-	dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
+	dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
 	return ;
 }
 
@@ -408,26 +365,22 @@ void mei_host_start_message(struct mei_device *dev)
 void mei_host_enum_clients_message(struct mei_device *dev)
 {
 	struct mei_msg_hdr *mei_hdr;
-	struct hbm_host_enum_request *host_enum_req;
-	mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
+	struct hbm_host_enum_request *enum_req;
+	const size_t len = sizeof(struct hbm_host_enum_request);
 	/* enumerate clients */
-	mei_hdr->host_addr = 0;
-	mei_hdr->me_addr = 0;
-	mei_hdr->length = sizeof(struct hbm_host_enum_request);
-	mei_hdr->msg_complete = 1;
-	mei_hdr->reserved = 0;
-
-	host_enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1];
-	memset(host_enum_req, 0, sizeof(struct hbm_host_enum_request));
-	host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
-	if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req,
-				mei_hdr->length)) {
+	mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
+
+	enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1];
+	memset(enum_req, 0, sizeof(struct hbm_host_enum_request));
+	enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
+
+	if (mei_write_message(dev, mei_hdr, (unsigned char *)enum_req, len)) {
 		dev->dev_state = MEI_DEV_RESETING;
 		dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
 		mei_reset(dev, 1);
 	}
 	dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE;
-	dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
+	dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
 	return;
 }
 
@@ -470,56 +423,87 @@ void mei_allocate_me_clients_storage(struct mei_device *dev)
 	dev->me_clients = clients;
 	return ;
 }
-/**
- * host_client_properties - reads properties for client
- *
- * @dev: the device structure
- *
- * returns:
- * 	< 0 - Error.
- *  = 0 - no more clients.
- *  = 1 - still have clients to send properties request.
- */
-int mei_host_client_properties(struct mei_device *dev)
+
+void mei_host_client_init(struct work_struct *work)
 {
-	struct mei_msg_hdr *mei_header;
-	struct hbm_props_request *host_cli_req;
-	int b;
-	u8 client_num = dev->me_client_presentation_num;
-
-	b = dev->me_client_index;
-	b = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, b);
-	if (b < MEI_CLIENTS_MAX) {
-		dev->me_clients[client_num].client_id = b;
-		dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
-		mei_header = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
-		mei_header->host_addr = 0;
-		mei_header->me_addr = 0;
-		mei_header->length = sizeof(struct hbm_props_request);
-		mei_header->msg_complete = 1;
-		mei_header->reserved = 0;
-
-		host_cli_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
-
-		memset(host_cli_req, 0, sizeof(struct hbm_props_request));
-
-		host_cli_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
-		host_cli_req->address = b;
-
-		if (mei_write_message(dev, mei_header,
-				(unsigned char *)host_cli_req,
-				mei_header->length)) {
-			dev->dev_state = MEI_DEV_RESETING;
-			dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
-			mei_reset(dev, 1);
-			return -EIO;
-		}
+	struct mei_device *dev = container_of(work,
+					      struct mei_device, init_work);
+	struct mei_client_properties *client_props;
+	int i;
+
+	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;
+
+		if (!uuid_le_cmp(client_props->protocol_name, mei_amthi_guid))
+			mei_amthif_host_init(dev);
+		else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid))
+			mei_wd_host_init(dev);
+	}
+
+	dev->dev_state = MEI_DEV_ENABLED;
 
-		dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
-		dev->me_client_index = b;
-		return 1;
+	mutex_unlock(&dev->device_lock);
+}
+
+int mei_host_client_enumerate(struct mei_device *dev)
+{
+
+	struct mei_msg_hdr *mei_hdr;
+	struct hbm_props_request *prop_req;
+	const size_t len = sizeof(struct hbm_props_request);
+	unsigned long next_client_index;
+	u8 client_num;
+
+
+	client_num = dev->me_client_presentation_num;
+
+	next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX,
+					  dev->me_client_index);
+
+	/* We got all client properties */
+	if (next_client_index == MEI_CLIENTS_MAX) {
+		schedule_work(&dev->init_work);
+
+		return 0;
 	}
 
+	dev->me_clients[client_num].client_id = next_client_index;
+	dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
+
+	mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
+	prop_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
+
+	memset(prop_req, 0, sizeof(struct hbm_props_request));
+
+
+	prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
+	prop_req->address = next_client_index;
+
+	if (mei_write_message(dev, mei_hdr, (unsigned char *) prop_req,
+			      mei_hdr->length)) {
+		dev->dev_state = MEI_DEV_RESETING;
+		dev_err(&dev->pdev->dev, "Properties request command failed\n");
+		mei_reset(dev, 1);
+
+		return -EIO;
+	}
+
+	dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
+	dev->me_client_index = next_client_index;
+
 	return 0;
 }
 
@@ -557,17 +541,20 @@ int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid)
 
 
 /**
- * mei_me_cl_update_filext - searches for ME client guid
- *                       sets client_id in mei_file_private if found
+ * mei_me_cl_link - create link between host and me clinet and add
+ *   me_cl to the list
+ *
  * @dev: the device structure
- * @cl: private file structure to set client_id in
- * @cuuid: searched uuid of ME client
- * @client_id: id of host client to be set in file private structure
+ * @cl: link between me and host client assocated with opened file descriptor
+ * @cuuid: uuid of ME client
+ * @client_id: id of the host client
  *
- * returns ME client index
+ * returns ME client index if ME client
+ *	-EINVAL on incorrect values
+ *	-ENONET if client not found
  */
-int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl,
-				const uuid_le *cuuid, u8 host_cl_id)
+int mei_me_cl_link(struct mei_device *dev, struct mei_cl *cl,
+			const uuid_le *cuuid, u8 host_cl_id)
 {
 	int i;
 
@@ -587,54 +574,22 @@ int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl,
 
 	return -ENOENT;
 }
-
 /**
- * host_init_iamthif - mei initialization iamthif client.
+ * mei_me_cl_unlink - remove me_cl from the list
  *
  * @dev: the device structure
- *
+ * @host_client_id: host client id to be removed
  */
-void mei_host_init_iamthif(struct mei_device *dev)
+void mei_me_cl_unlink(struct mei_device *dev, struct mei_cl *cl)
 {
-	int i;
-	unsigned char *msg_buf;
-
-	mei_cl_init(&dev->iamthif_cl, dev);
-	dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
-
-	/* find ME amthi client */
-	i = mei_me_cl_update_filext(dev, &dev->iamthif_cl,
-			    &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID);
-	if (i < 0) {
-		dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n");
-		return;
-	}
-
-	/* Assign iamthif_mtu to the value received from ME  */
-
-	dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length;
-	dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n",
-			dev->me_clients[i].props.max_msg_length);
-
-	kfree(dev->iamthif_msg_buf);
-	dev->iamthif_msg_buf = NULL;
-
-	/* allocate storage for ME message buffer */
-	msg_buf = kcalloc(dev->iamthif_mtu,
-			sizeof(unsigned char), GFP_KERNEL);
-	if (!msg_buf) {
-		dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n");
-		return;
-	}
-
-	dev->iamthif_msg_buf = msg_buf;
-
-	if (mei_connect(dev, &dev->iamthif_cl)) {
-		dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n");
-		dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
-		dev->iamthif_cl.host_client_id = 0;
-	} else {
-		dev->iamthif_cl.timer_count = CONNECT_TIMEOUT;
+	struct mei_cl *pos, *next;
+	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;
+		}
 	}
 }
 
@@ -671,9 +626,8 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev)
  */
 int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
 {
-	int rets, err;
-	long timeout = 15;	/* 15 seconds */
 	struct mei_cl_cb *cb;
+	int rets, err;
 
 	if (!dev || !cl)
 		return -ENODEV;
@@ -681,13 +635,11 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
 	if (cl->state != MEI_FILE_DISCONNECTING)
 		return 0;
 
-	cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+	cb = mei_io_cb_init(cl, NULL);
 	if (!cb)
 		return -ENOMEM;
 
-	INIT_LIST_HEAD(&cb->cb_list);
-	cb->file_private = cl;
-	cb->major_file_operations = MEI_CLOSE;
+	cb->fop_type = MEI_FOP_CLOSE;
 	if (dev->mei_host_buffer_is_empty) {
 		dev->mei_host_buffer_is_empty = false;
 		if (mei_disconnect(dev, cl)) {
@@ -696,17 +648,17 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
 			goto free;
 		}
 		mdelay(10); /* Wait for hardware disconnection ready */
-		list_add_tail(&cb->cb_list, &dev->ctrl_rd_list.mei_cb.cb_list);
+		list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
 	} else {
 		dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
-		list_add_tail(&cb->cb_list,
-				&dev->ctrl_wr_list.mei_cb.cb_list);
+		list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
+
 	}
 	mutex_unlock(&dev->device_lock);
 
 	err = wait_event_timeout(dev->wait_recvd_msg,
-		 (MEI_FILE_DISCONNECTED == cl->state),
-		 timeout * HZ);
+			MEI_FILE_DISCONNECTED == cl->state,
+			mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
 
 	mutex_lock(&dev->device_lock);
 	if (MEI_FILE_DISCONNECTED == cl->state) {
@@ -728,29 +680,7 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
 	mei_io_list_flush(&dev->ctrl_rd_list, cl);
 	mei_io_list_flush(&dev->ctrl_wr_list, cl);
 free:
-	mei_free_cb_private(cb);
+	mei_io_cb_free(cb);
 	return rets;
 }
 
-/**
- * mei_remove_client_from_file_list -
- *	removes file private data from device file list
- *
- * @dev: the device structure
- * @host_client_id: host client id to be removed
- */
-void mei_remove_client_from_file_list(struct mei_device *dev,
-				       u8 host_client_id)
-{
-	struct mei_cl *cl_pos = NULL;
-	struct mei_cl *cl_next = NULL;
-	list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
-		if (host_client_id == cl_pos->host_client_id) {
-			dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n",
-					cl_pos->host_client_id,
-					cl_pos->me_client_id);
-			list_del_init(&cl_pos->link);
-			break;
-		}
-	}
-}
diff --git a/drivers/misc/mei/interface.c b/drivers/misc/mei/interface.c
index 509c395..8de8547 100644
--- a/drivers/misc/mei/interface.c
+++ b/drivers/misc/mei/interface.c
@@ -292,28 +292,23 @@ int mei_flow_ctrl_reduce(struct mei_device *dev, struct mei_cl *cl)
 int mei_send_flow_control(struct mei_device *dev, struct mei_cl *cl)
 {
 	struct mei_msg_hdr *mei_hdr;
-	struct hbm_flow_control *mei_flow_control;
-
-	mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
-	mei_hdr->host_addr = 0;
-	mei_hdr->me_addr = 0;
-	mei_hdr->length = sizeof(struct hbm_flow_control);
-	mei_hdr->msg_complete = 1;
-	mei_hdr->reserved = 0;
-
-	mei_flow_control = (struct hbm_flow_control *) &dev->wr_msg_buf[1];
-	memset(mei_flow_control, 0, sizeof(*mei_flow_control));
-	mei_flow_control->host_addr = cl->host_client_id;
-	mei_flow_control->me_addr = cl->me_client_id;
-	mei_flow_control->hbm_cmd = MEI_FLOW_CONTROL_CMD;
-	memset(mei_flow_control->reserved, 0,
-			sizeof(mei_flow_control->reserved));
+	struct hbm_flow_control *flow_ctrl;
+	const size_t len = sizeof(struct hbm_flow_control);
+
+	mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
+
+	flow_ctrl = (struct hbm_flow_control *)&dev->wr_msg_buf[1];
+	memset(flow_ctrl, 0, len);
+	flow_ctrl->hbm_cmd = MEI_FLOW_CONTROL_CMD;
+	flow_ctrl->host_addr = cl->host_client_id;
+	flow_ctrl->me_addr = cl->me_client_id;
+	/* FIXME: reserved !? */
+	memset(flow_ctrl->reserved, 0, sizeof(flow_ctrl->reserved));
 	dev_dbg(&dev->pdev->dev, "sending flow control host client = %d, ME client = %d\n",
 		cl->host_client_id, cl->me_client_id);
 
 	return mei_write_message(dev, mei_hdr,
-				(unsigned char *) mei_flow_control,
-				sizeof(struct hbm_flow_control));
+			(unsigned char *) flow_ctrl, len);
 }
 
 /**
@@ -352,26 +347,19 @@ int mei_other_client_is_connecting(struct mei_device *dev,
 int mei_disconnect(struct mei_device *dev, struct mei_cl *cl)
 {
 	struct mei_msg_hdr *mei_hdr;
-	struct hbm_client_disconnect_request *mei_cli_disconnect;
-
-	mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
-	mei_hdr->host_addr = 0;
-	mei_hdr->me_addr = 0;
-	mei_hdr->length = sizeof(struct hbm_client_disconnect_request);
-	mei_hdr->msg_complete = 1;
-	mei_hdr->reserved = 0;
-
-	mei_cli_disconnect =
-	    (struct hbm_client_disconnect_request *) &dev->wr_msg_buf[1];
-	memset(mei_cli_disconnect, 0, sizeof(*mei_cli_disconnect));
-	mei_cli_disconnect->host_addr = cl->host_client_id;
-	mei_cli_disconnect->me_addr = cl->me_client_id;
-	mei_cli_disconnect->hbm_cmd = CLIENT_DISCONNECT_REQ_CMD;
-	mei_cli_disconnect->reserved[0] = 0;
+	struct hbm_client_connect_request *req;
+	const size_t len = sizeof(struct hbm_client_connect_request);
 
-	return mei_write_message(dev, mei_hdr,
-				(unsigned char *) mei_cli_disconnect,
-				sizeof(struct hbm_client_disconnect_request));
+	mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
+
+	req = (struct hbm_client_connect_request *)&dev->wr_msg_buf[1];
+	memset(req, 0, len);
+	req->hbm_cmd = CLIENT_DISCONNECT_REQ_CMD;
+	req->host_addr = cl->host_client_id;
+	req->me_addr = cl->me_client_id;
+	req->reserved = 0;
+
+	return mei_write_message(dev, mei_hdr, (unsigned char *)req, len);
 }
 
 /**
@@ -385,23 +373,16 @@ int mei_disconnect(struct mei_device *dev, struct mei_cl *cl)
 int mei_connect(struct mei_device *dev, struct mei_cl *cl)
 {
 	struct mei_msg_hdr *mei_hdr;
-	struct hbm_client_connect_request *mei_cli_connect;
-
-	mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
-	mei_hdr->host_addr = 0;
-	mei_hdr->me_addr = 0;
-	mei_hdr->length = sizeof(struct hbm_client_connect_request);
-	mei_hdr->msg_complete = 1;
-	mei_hdr->reserved = 0;
-
-	mei_cli_connect =
-	    (struct hbm_client_connect_request *) &dev->wr_msg_buf[1];
-	mei_cli_connect->host_addr = cl->host_client_id;
-	mei_cli_connect->me_addr = cl->me_client_id;
-	mei_cli_connect->hbm_cmd = CLIENT_CONNECT_REQ_CMD;
-	mei_cli_connect->reserved = 0;
+	struct hbm_client_connect_request *req;
+	const size_t len = sizeof(struct hbm_client_connect_request);
 
-	return mei_write_message(dev, mei_hdr,
-				(unsigned char *) mei_cli_connect,
-				sizeof(struct hbm_client_connect_request));
+	mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
+
+	req = (struct hbm_client_connect_request *) &dev->wr_msg_buf[1];
+	req->hbm_cmd = CLIENT_CONNECT_REQ_CMD;
+	req->host_addr = cl->host_client_id;
+	req->me_addr = cl->me_client_id;
+	req->reserved = 0;
+
+	return mei_write_message(dev, mei_hdr, (unsigned char *) req, len);
 }
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 3533edd..04fa213 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -57,14 +57,14 @@ irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id)
  */
 static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
 {
-	if (cb_pos->major_file_operations == MEI_WRITE) {
-		mei_free_cb_private(cb_pos);
+	if (cb_pos->fop_type == MEI_FOP_WRITE) {
+		mei_io_cb_free(cb_pos);
 		cb_pos = NULL;
 		cl->writing_state = MEI_WRITE_COMPLETE;
 		if (waitqueue_active(&cl->tx_wait))
 			wake_up_interruptible(&cl->tx_wait);
 
-	} else if (cb_pos->major_file_operations == MEI_READ &&
+	} else if (cb_pos->fop_type == MEI_FOP_READ &&
 			MEI_READING == cl->reading_state) {
 		cl->reading_state = MEI_READ_COMPLETE;
 		if (waitqueue_active(&cl->rx_wait))
@@ -74,94 +74,6 @@ static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
 }
 
 /**
- * _mei_cmpl_iamthif - processes completed iamthif operation.
- *
- * @dev: the device structure.
- * @cb_pos: callback block.
- */
-static void _mei_cmpl_iamthif(struct mei_device *dev, struct mei_cl_cb *cb_pos)
-{
-	if (dev->iamthif_canceled != 1) {
-		dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
-		dev->iamthif_stall_timer = 0;
-		memcpy(cb_pos->response_buffer.data,
-				dev->iamthif_msg_buf,
-				dev->iamthif_msg_buf_index);
-		list_add_tail(&cb_pos->cb_list,
-				&dev->amthi_read_complete_list.mei_cb.cb_list);
-		dev_dbg(&dev->pdev->dev, "amthi read completed.\n");
-		dev->iamthif_timer = jiffies;
-		dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
-				dev->iamthif_timer);
-	} else {
-		mei_run_next_iamthif_cmd(dev);
-	}
-
-	dev_dbg(&dev->pdev->dev, "completing amthi call back.\n");
-	wake_up_interruptible(&dev->iamthif_cl.wait);
-}
-
-
-/**
- * mei_irq_thread_read_amthi_message - bottom half read routine after ISR to
- * handle the read amthi message data processing.
- *
- * @complete_list: An instance of our list structure
- * @dev: the device structure
- * @mei_hdr: header of amthi message
- *
- * returns 0 on success, <0 on failure.
- */
-static int mei_irq_thread_read_amthi_message(struct mei_io_list *complete_list,
-		struct mei_device *dev,
-		struct mei_msg_hdr *mei_hdr)
-{
-	struct mei_cl *cl;
-	struct mei_cl_cb *cb;
-	unsigned char *buffer;
-
-	BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id);
-	BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING);
-
-	buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
-	BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length);
-
-	mei_read_slots(dev, buffer, mei_hdr->length);
-
-	dev->iamthif_msg_buf_index += mei_hdr->length;
-
-	if (!mei_hdr->msg_complete)
-		return 0;
-
-	dev_dbg(&dev->pdev->dev,
-			"amthi_message_buffer_index =%d\n",
-			mei_hdr->length);
-
-	dev_dbg(&dev->pdev->dev, "completed amthi read.\n ");
-	if (!dev->iamthif_current_cb)
-		return -ENODEV;
-
-	cb = dev->iamthif_current_cb;
-	dev->iamthif_current_cb = NULL;
-
-	cl = (struct mei_cl *)cb->file_private;
-	if (!cl)
-		return -ENODEV;
-
-	dev->iamthif_stall_timer = 0;
-	cb->information =	dev->iamthif_msg_buf_index;
-	cb->read_time = jiffies;
-	if (dev->iamthif_ioctl && cl == &dev->iamthif_cl) {
-		/* found the iamthif cb */
-		dev_dbg(&dev->pdev->dev, "complete the amthi read cb.\n ");
-		dev_dbg(&dev->pdev->dev, "add the amthi read cb to complete.\n ");
-		list_add_tail(&cb->cb_list,
-						&complete_list->mei_cb.cb_list);
-	}
-	return 0;
-}
-
-/**
  * _mei_irq_thread_state_ok - checks if mei header matches file private data
  *
  * @cl: private data of the file object
@@ -188,7 +100,7 @@ static int _mei_irq_thread_state_ok(struct mei_cl *cl,
  *
  * returns 0 on success, <0 on failure.
  */
-static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list,
+static int mei_irq_thread_read_client_message(struct mei_cl_cb *complete_list,
 		struct mei_device *dev,
 		struct mei_msg_hdr *mei_hdr)
 {
@@ -197,36 +109,36 @@ static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list,
 	unsigned char *buffer = NULL;
 
 	dev_dbg(&dev->pdev->dev, "start client msg\n");
-	if (list_empty(&dev->read_list.mei_cb.cb_list))
+	if (list_empty(&dev->read_list.list))
 		goto quit;
 
-	list_for_each_entry_safe(cb_pos, cb_next,
-			&dev->read_list.mei_cb.cb_list, cb_list) {
-		cl = (struct mei_cl *)cb_pos->file_private;
+	list_for_each_entry_safe(cb_pos, cb_next, &dev->read_list.list, list) {
+		cl = cb_pos->cl;
 		if (cl && _mei_irq_thread_state_ok(cl, mei_hdr)) {
 			cl->reading_state = MEI_READING;
-			buffer = cb_pos->response_buffer.data + cb_pos->information;
+			buffer = cb_pos->response_buffer.data + cb_pos->buf_idx;
 
 			if (cb_pos->response_buffer.size <
-					mei_hdr->length + cb_pos->information) {
+					mei_hdr->length + cb_pos->buf_idx) {
 				dev_dbg(&dev->pdev->dev, "message overflow.\n");
-				list_del(&cb_pos->cb_list);
+				list_del(&cb_pos->list);
 				return -ENOMEM;
 			}
 			if (buffer)
 				mei_read_slots(dev, buffer, mei_hdr->length);
 
-			cb_pos->information += mei_hdr->length;
+			cb_pos->buf_idx += mei_hdr->length;
 			if (mei_hdr->msg_complete) {
 				cl->status = 0;
-				list_del(&cb_pos->cb_list);
+				list_del(&cb_pos->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,
-					cb_pos->information);
-				list_add_tail(&cb_pos->cb_list,
-					&complete_list->mei_cb.cb_list);
+					cb_pos->buf_idx);
+
+				list_add_tail(&cb_pos->list,
+						&complete_list->list);
 			}
 
 			break;
@@ -246,37 +158,6 @@ quit:
 }
 
 /**
- * _mei_irq_thread_iamthif_read - prepares to read iamthif data.
- *
- * @dev: the device structure.
- * @slots: free slots.
- *
- * returns 0, OK; otherwise, error.
- */
-static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
-{
-
-	if (((*slots) * sizeof(u32)) < (sizeof(struct mei_msg_hdr)
-			+ sizeof(struct hbm_flow_control))) {
-		return -EMSGSIZE;
-	}
-	*slots -= mei_data2slots(sizeof(struct hbm_flow_control));
-	if (mei_send_flow_control(dev, &dev->iamthif_cl)) {
-		dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
-		return -EIO;
-	}
-
-	dev_dbg(&dev->pdev->dev, "iamthif flow control success\n");
-	dev->iamthif_state = MEI_IAMTHIF_READING;
-	dev->iamthif_flow_control_pending = false;
-	dev->iamthif_msg_buf_index = 0;
-	dev->iamthif_msg_buf_size = 0;
-	dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER;
-	dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
-	return 0;
-}
-
-/**
  * _mei_irq_thread_close - processes close related operation.
  *
  * @dev: the device structure.
@@ -290,26 +171,24 @@ static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
 static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
 				struct mei_cl_cb *cb_pos,
 				struct mei_cl *cl,
-				struct mei_io_list *cmpl_list)
+				struct mei_cl_cb *cmpl_list)
 {
 	if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
-			sizeof(struct hbm_client_disconnect_request)))
+			sizeof(struct hbm_client_connect_request)))
 		return -EBADMSG;
 
-	*slots -= mei_data2slots(sizeof(struct hbm_client_disconnect_request));
+	*slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
 
 	if (mei_disconnect(dev, cl)) {
 		cl->status = 0;
-		cb_pos->information = 0;
-		list_move_tail(&cb_pos->cb_list,
-				&cmpl_list->mei_cb.cb_list);
+		cb_pos->buf_idx = 0;
+		list_move_tail(&cb_pos->list, &cmpl_list->list);
 		return -EMSGSIZE;
 	} else {
 		cl->state = MEI_FILE_DISCONNECTING;
 		cl->status = 0;
-		cb_pos->information = 0;
-		list_move_tail(&cb_pos->cb_list,
-				&dev->ctrl_rd_list.mei_cb.cb_list);
+		cb_pos->buf_idx = 0;
+		list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
 		cl->timer_count = MEI_CONNECT_TIMEOUT;
 	}
 
@@ -356,7 +235,7 @@ static void mei_client_connect_response(struct mei_device *dev,
 {
 
 	struct mei_cl *cl;
-	struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
+	struct mei_cl_cb *pos = NULL, *next = NULL;
 
 	dev_dbg(&dev->pdev->dev,
 			"connect_response:\n"
@@ -373,8 +252,6 @@ static void mei_client_connect_response(struct mei_device *dev,
 		dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n");
 		mei_watchdog_register(dev);
 
-		/* next step in the state maching */
-		mei_host_init_iamthif(dev);
 		return;
 	}
 
@@ -382,17 +259,16 @@ static void mei_client_connect_response(struct mei_device *dev,
 		dev->iamthif_state = MEI_IAMTHIF_IDLE;
 		return;
 	}
-	list_for_each_entry_safe(cb_pos, cb_next,
-				&dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
+	list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) {
 
-		cl = (struct mei_cl *)cb_pos->file_private;
+		cl = pos->cl;
 		if (!cl) {
-			list_del(&cb_pos->cb_list);
+			list_del(&pos->list);
 			return;
 		}
-		if (MEI_IOCTL == cb_pos->major_file_operations) {
+		if (pos->fop_type == MEI_FOP_IOCTL) {
 			if (is_treat_specially_client(cl, rs)) {
-				list_del(&cb_pos->cb_list);
+				list_del(&pos->list);
 				cl->status = 0;
 				cl->timer_count = 0;
 				break;
@@ -411,7 +287,7 @@ static void mei_client_disconnect_response(struct mei_device *dev,
 					struct hbm_client_connect_response *rs)
 {
 	struct mei_cl *cl;
-	struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
+	struct mei_cl_cb *pos = NULL, *next = NULL;
 
 	dev_dbg(&dev->pdev->dev,
 			"disconnect_response:\n"
@@ -422,12 +298,11 @@ static void mei_client_disconnect_response(struct mei_device *dev,
 			rs->host_addr,
 			rs->status);
 
-	list_for_each_entry_safe(cb_pos, cb_next,
-			&dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
-		cl = (struct mei_cl *)cb_pos->file_private;
+	list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) {
+		cl = pos->cl;
 
 		if (!cl) {
-			list_del(&cb_pos->cb_list);
+			list_del(&pos->list);
 			return;
 		}
 
@@ -435,7 +310,7 @@ static void mei_client_disconnect_response(struct mei_device *dev,
 		if (cl->host_client_id == rs->host_addr &&
 		    cl->me_client_id == rs->me_addr) {
 
-			list_del(&cb_pos->cb_list);
+			list_del(&pos->list);
 			if (!rs->status)
 				cl->state = MEI_FILE_DISCONNECTED;
 
@@ -537,10 +412,10 @@ static void mei_client_flow_control_response(struct mei_device *dev,
  * returns !=0, same; 0,not.
  */
 static int same_disconn_addr(struct mei_cl *cl,
-			     struct hbm_client_disconnect_request *disconn)
+			     struct hbm_client_connect_request *req)
 {
-	return (cl->host_client_id == disconn->host_addr &&
-		cl->me_client_id == disconn->me_addr);
+	return (cl->host_client_id == req->host_addr &&
+		cl->me_client_id == req->me_addr);
 }
 
 /**
@@ -550,49 +425,38 @@ static int same_disconn_addr(struct mei_cl *cl,
  * @disconnect_req: disconnect request bus message.
  */
 static void mei_client_disconnect_request(struct mei_device *dev,
-		struct hbm_client_disconnect_request *disconnect_req)
+		struct hbm_client_connect_request *disconnect_req)
 {
-	struct mei_msg_hdr *mei_hdr;
 	struct hbm_client_connect_response *disconnect_res;
-	struct mei_cl *cl_pos = NULL;
-	struct mei_cl *cl_next = NULL;
+	struct mei_cl *pos, *next;
+	const size_t len = sizeof(struct hbm_client_connect_response);
 
-	list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
-		if (same_disconn_addr(cl_pos, disconnect_req)) {
+	list_for_each_entry_safe(pos, next, &dev->file_list, link) {
+		if (same_disconn_addr(pos, disconnect_req)) {
 			dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n",
 					disconnect_req->host_addr,
 					disconnect_req->me_addr);
-			cl_pos->state = MEI_FILE_DISCONNECTED;
-			cl_pos->timer_count = 0;
-			if (cl_pos == &dev->wd_cl)
+			pos->state = MEI_FILE_DISCONNECTED;
+			pos->timer_count = 0;
+			if (pos == &dev->wd_cl)
 				dev->wd_pending = false;
-			else if (cl_pos == &dev->iamthif_cl)
+			else if (pos == &dev->iamthif_cl)
 				dev->iamthif_timer = 0;
 
 			/* prepare disconnect response */
-			mei_hdr =
-				(struct mei_msg_hdr *) &dev->ext_msg_buf[0];
-			mei_hdr->host_addr = 0;
-			mei_hdr->me_addr = 0;
-			mei_hdr->length =
-				sizeof(struct hbm_client_connect_response);
-			mei_hdr->msg_complete = 1;
-			mei_hdr->reserved = 0;
-
+			(void)mei_hbm_hdr((u32 *)&dev->wr_ext_msg.hdr, len);
 			disconnect_res =
 				(struct hbm_client_connect_response *)
-				&dev->ext_msg_buf[1];
-			disconnect_res->host_addr = cl_pos->host_client_id;
-			disconnect_res->me_addr = cl_pos->me_client_id;
+				&dev->wr_ext_msg.data;
 			disconnect_res->hbm_cmd = CLIENT_DISCONNECT_RES_CMD;
+			disconnect_res->host_addr = pos->host_client_id;
+			disconnect_res->me_addr = pos->me_client_id;
 			disconnect_res->status = 0;
-			dev->extra_write_index = 2;
 			break;
 		}
 	}
 }
 
-
 /**
  * mei_irq_thread_read_bus_message - bottom half read routine after ISR to
  * handle the read bus message cmd processing.
@@ -604,16 +468,15 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
 		struct mei_msg_hdr *mei_hdr)
 {
 	struct mei_bus_message *mei_msg;
+	struct mei_me_client *me_client;
 	struct hbm_host_version_response *version_res;
 	struct hbm_client_connect_response *connect_res;
 	struct hbm_client_connect_response *disconnect_res;
+	struct hbm_client_connect_request *disconnect_req;
 	struct hbm_flow_control *flow_control;
 	struct hbm_props_response *props_res;
 	struct hbm_host_enum_response *enum_res;
-	struct hbm_client_disconnect_request *disconnect_req;
-	struct hbm_host_stop_request *host_stop_req;
-	int res;
-
+	struct hbm_host_stop_request *stop_req;
 
 	/* read the message to our buffer */
 	BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf));
@@ -637,26 +500,20 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
 				return;
 			}
 		} else {
+			u32 *buf = dev->wr_msg_buf;
+			const size_t len = sizeof(struct hbm_host_stop_request);
+
 			dev->version = version_res->me_max_version;
+
 			/* send stop message */
-			mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
-			mei_hdr->host_addr = 0;
-			mei_hdr->me_addr = 0;
-			mei_hdr->length = sizeof(struct hbm_host_stop_request);
-			mei_hdr->msg_complete = 1;
-			mei_hdr->reserved = 0;
-
-			host_stop_req = (struct hbm_host_stop_request *)
-							&dev->wr_msg_buf[1];
-
-			memset(host_stop_req,
-					0,
-					sizeof(struct hbm_host_stop_request));
-			host_stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
-			host_stop_req->reason = DRIVER_STOP_REQUEST;
+			mei_hdr = mei_hbm_hdr(&buf[0], len);
+			stop_req = (struct hbm_host_stop_request *)&buf[1];
+			memset(stop_req, 0, len);
+			stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
+			stop_req->reason = DRIVER_STOP_REQUEST;
+
 			mei_write_message(dev, mei_hdr,
-					   (unsigned char *) (host_stop_req),
-					   mei_hdr->length);
+					(unsigned char *)stop_req, len);
 			dev_dbg(&dev->pdev->dev, "version mismatch.\n");
 			return;
 		}
@@ -666,16 +523,14 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
 		break;
 
 	case CLIENT_CONNECT_RES_CMD:
-		connect_res =
-			(struct hbm_client_connect_response *) mei_msg;
+		connect_res = (struct hbm_client_connect_response *) mei_msg;
 		mei_client_connect_response(dev, connect_res);
 		dev_dbg(&dev->pdev->dev, "client connect response message received.\n");
 		wake_up(&dev->wait_recvd_msg);
 		break;
 
 	case CLIENT_DISCONNECT_RES_CMD:
-		disconnect_res =
-			(struct hbm_client_connect_response *) mei_msg;
+		disconnect_res = (struct hbm_client_connect_response *) mei_msg;
 		mei_client_disconnect_response(dev, disconnect_res);
 		dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n");
 		wake_up(&dev->wait_recvd_msg);
@@ -689,64 +544,37 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
 
 	case HOST_CLIENT_PROPERTIES_RES_CMD:
 		props_res = (struct hbm_props_response *)mei_msg;
+		me_client = &dev->me_clients[dev->me_client_presentation_num];
+
 		if (props_res->status || !dev->me_clients) {
 			dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n");
 			mei_reset(dev, 1);
 			return;
 		}
-		if (dev->me_clients[dev->me_client_presentation_num]
-					.client_id == props_res->address) {
 
-			dev->me_clients[dev->me_client_presentation_num].props
-						= props_res->client_properties;
+		if (me_client->client_id != props_res->address) {
+			dev_err(&dev->pdev->dev,
+				"Host client properties reply mismatch\n");
+			mei_reset(dev, 1);
 
-			if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
-			    dev->init_clients_state ==
-					MEI_CLIENT_PROPERTIES_MESSAGE) {
-				dev->me_client_index++;
-				dev->me_client_presentation_num++;
-
-				/** Send Client Properties request **/
-				res = mei_host_client_properties(dev);
-				if (res < 0) {
-					dev_dbg(&dev->pdev->dev, "mei_host_client_properties() failed");
-					return;
-				} else if (!res) {
-					/*
-					 * No more clients to send to.
-					 * Clear Map for indicating now ME clients
-					 * with associated host client
-					 */
-					bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
-					dev->open_handle_count = 0;
-
-					/*
-					 * Reserving the first three client IDs
-					 * Client Id 0 - Reserved for MEI Bus Message communications
-					 * Client Id 1 - Reserved for Watchdog
-					 * Client ID 2 - Reserved for AMTHI
-					 */
-					bitmap_set(dev->host_clients_map, 0, 3);
-					dev->dev_state = MEI_DEV_ENABLED;
-
-					/* if wd initialization fails, initialization the AMTHI client,
-					 * otherwise the AMTHI client will be initialized after the WD client connect response
-					 * will be received
-					 */
-					if (mei_wd_host_init(dev))
-						mei_host_init_iamthif(dev);
-				}
+			return;
+		}
 
-			} else {
-				dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message");
-				mei_reset(dev, 1);
-				return;
-			}
-		} else {
-			dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message for wrong client ID\n");
+		if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
+		    dev->init_clients_state != MEI_CLIENT_PROPERTIES_MESSAGE) {
+			dev_err(&dev->pdev->dev,
+				"Unexpected client properties reply\n");
 			mei_reset(dev, 1);
+
 			return;
 		}
+
+		me_client->props = props_res->client_properties;
+		dev->me_client_index++;
+		dev->me_client_presentation_num++;
+
+		mei_host_client_enumerate(dev);
+
 		break;
 
 	case HOST_ENUM_RES_CMD:
@@ -760,7 +588,8 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
 				mei_allocate_me_clients_storage(dev);
 				dev->init_clients_state =
 					MEI_CLIENT_PROPERTIES_MESSAGE;
-				mei_host_client_properties(dev);
+
+				mei_host_client_enumerate(dev);
 		} else {
 			dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n");
 			mei_reset(dev, 1);
@@ -776,29 +605,23 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
 
 	case CLIENT_DISCONNECT_REQ_CMD:
 		/* search for client */
-		disconnect_req =
-			(struct hbm_client_disconnect_request *) mei_msg;
+		disconnect_req = (struct hbm_client_connect_request *)mei_msg;
 		mei_client_disconnect_request(dev, disconnect_req);
 		break;
 
 	case ME_STOP_REQ_CMD:
-		/* prepare stop request */
-		mei_hdr = (struct mei_msg_hdr *) &dev->ext_msg_buf[0];
-		mei_hdr->host_addr = 0;
-		mei_hdr->me_addr = 0;
-		mei_hdr->length = sizeof(struct hbm_host_stop_request);
-		mei_hdr->msg_complete = 1;
-		mei_hdr->reserved = 0;
-		host_stop_req =
-			(struct hbm_host_stop_request *) &dev->ext_msg_buf[1];
-		memset(host_stop_req, 0, sizeof(struct hbm_host_stop_request));
-		host_stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
-		host_stop_req->reason = DRIVER_STOP_REQUEST;
-		host_stop_req->reserved[0] = 0;
-		host_stop_req->reserved[1] = 0;
-		dev->extra_write_index = 2;
-		break;
+	{
+		/* prepare stop request: sent in next interrupt event */
+
+		const size_t len = sizeof(struct hbm_host_stop_request);
 
+		mei_hdr = mei_hbm_hdr((u32 *)&dev->wr_ext_msg.hdr, len);
+		stop_req = (struct hbm_host_stop_request *)&dev->wr_ext_msg.data;
+		memset(stop_req, 0, len);
+		stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
+		stop_req->reason = DRIVER_STOP_REQUEST;
+		break;
+	}
 	default:
 		BUG();
 		break;
@@ -821,12 +644,12 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
 static int _mei_irq_thread_read(struct mei_device *dev,	s32 *slots,
 			struct mei_cl_cb *cb_pos,
 			struct mei_cl *cl,
-			struct mei_io_list *cmpl_list)
+			struct mei_cl_cb *cmpl_list)
 {
 	if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
 			sizeof(struct hbm_flow_control))) {
 		/* return the cancel routine */
-		list_del(&cb_pos->cb_list);
+		list_del(&cb_pos->list);
 		return -EBADMSG;
 	}
 
@@ -834,11 +657,11 @@ static int _mei_irq_thread_read(struct mei_device *dev,	s32 *slots,
 
 	if (mei_send_flow_control(dev, cl)) {
 		cl->status = -ENODEV;
-		cb_pos->information = 0;
-		list_move_tail(&cb_pos->cb_list, &cmpl_list->mei_cb.cb_list);
+		cb_pos->buf_idx = 0;
+		list_move_tail(&cb_pos->list, &cmpl_list->list);
 		return -ENODEV;
 	}
-	list_move_tail(&cb_pos->cb_list, &dev->read_list.mei_cb.cb_list);
+	list_move_tail(&cb_pos->list, &dev->read_list.list);
 
 	return 0;
 }
@@ -858,12 +681,12 @@ static int _mei_irq_thread_read(struct mei_device *dev,	s32 *slots,
 static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
 			struct mei_cl_cb *cb_pos,
 			struct mei_cl *cl,
-			struct mei_io_list *cmpl_list)
+			struct mei_cl_cb *cmpl_list)
 {
 	if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
 			sizeof(struct hbm_client_connect_request))) {
 		/* return the cancel routine */
-		list_del(&cb_pos->cb_list);
+		list_del(&cb_pos->list);
 		return -EBADMSG;
 	}
 
@@ -871,188 +694,73 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
 	 *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
 	if (mei_connect(dev, cl)) {
 		cl->status = -ENODEV;
-		cb_pos->information = 0;
-		list_del(&cb_pos->cb_list);
+		cb_pos->buf_idx = 0;
+		list_del(&cb_pos->list);
 		return -ENODEV;
 	} else {
-		list_move_tail(&cb_pos->cb_list,
-			&dev->ctrl_rd_list.mei_cb.cb_list);
+		list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
 		cl->timer_count = MEI_CONNECT_TIMEOUT;
 	}
 	return 0;
 }
 
 /**
- * _mei_irq_thread_cmpl - processes completed and no-iamthif operation.
+ * mei_irq_thread_write_complete - write messages to device.
  *
  * @dev: the device structure.
  * @slots: free slots.
- * @cb_pos: callback block.
- * @cl: private data of the file object.
+ * @cb: callback block.
  * @cmpl_list: complete list.
  *
  * returns 0, OK; otherwise, error.
  */
-static int _mei_irq_thread_cmpl(struct mei_device *dev,	s32 *slots,
-			struct mei_cl_cb *cb_pos,
-			struct mei_cl *cl,
-			struct mei_io_list *cmpl_list)
+static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots,
+			struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list)
 {
 	struct mei_msg_hdr *mei_hdr;
+	struct mei_cl *cl = cb->cl;
+	size_t len = cb->request_buffer.size - cb->buf_idx;
+	size_t msg_slots = mei_data2slots(len);
+
+	mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
+	mei_hdr->host_addr = cl->host_client_id;
+	mei_hdr->me_addr = cl->me_client_id;
+	mei_hdr->reserved = 0;
 
-	if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
-			(cb_pos->request_buffer.size -
-			cb_pos->information))) {
-		mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
-		mei_hdr->host_addr = cl->host_client_id;
-		mei_hdr->me_addr = cl->me_client_id;
-		mei_hdr->length = cb_pos->request_buffer.size -
-					cb_pos->information;
+	if (*slots >= msg_slots) {
+		mei_hdr->length = len;
 		mei_hdr->msg_complete = 1;
-		mei_hdr->reserved = 0;
-		dev_dbg(&dev->pdev->dev, "cb_pos->request_buffer.size =%d"
-			"mei_hdr->msg_complete = %d\n",
-				cb_pos->request_buffer.size,
-				mei_hdr->msg_complete);
-		dev_dbg(&dev->pdev->dev, "cb_pos->information  =%lu\n",
-				cb_pos->information);
-		dev_dbg(&dev->pdev->dev, "mei_hdr->length  =%d\n",
-				mei_hdr->length);
-		*slots -= mei_data2slots(mei_hdr->length);
-		if (mei_write_message(dev, mei_hdr,
-				(unsigned char *)
-				(cb_pos->request_buffer.data +
-				cb_pos->information),
-				mei_hdr->length)) {
-			cl->status = -ENODEV;
-			list_move_tail(&cb_pos->cb_list,
-				&cmpl_list->mei_cb.cb_list);
-			return -ENODEV;
-		} else {
-			if (mei_flow_ctrl_reduce(dev, cl))
-				return -ENODEV;
-			cl->status = 0;
-			cb_pos->information += mei_hdr->length;
-			list_move_tail(&cb_pos->cb_list,
-				&dev->write_waiting_list.mei_cb.cb_list);
-		}
+	/* Split the message only if we can write the whole host buffer */
 	} else if (*slots == dev->hbuf_depth) {
-		/* buffer is still empty */
-		mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
-		mei_hdr->host_addr = cl->host_client_id;
-		mei_hdr->me_addr = cl->me_client_id;
-		mei_hdr->length =
-			(*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
+		msg_slots = *slots;
+		len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
+		mei_hdr->length = len;
 		mei_hdr->msg_complete = 0;
-		mei_hdr->reserved = 0;
-		*slots -= mei_data2slots(mei_hdr->length);
-		if (mei_write_message(dev, mei_hdr,
-					(unsigned char *)
-					(cb_pos->request_buffer.data +
-					cb_pos->information),
-					mei_hdr->length)) {
-			cl->status = -ENODEV;
-			list_move_tail(&cb_pos->cb_list,
-				&cmpl_list->mei_cb.cb_list);
-			return -ENODEV;
-		} else {
-			cb_pos->information += mei_hdr->length;
-			dev_dbg(&dev->pdev->dev,
-					"cb_pos->request_buffer.size =%d"
-					" mei_hdr->msg_complete = %d\n",
-					cb_pos->request_buffer.size,
-					mei_hdr->msg_complete);
-			dev_dbg(&dev->pdev->dev, "cb_pos->information  =%lu\n",
-					cb_pos->information);
-			dev_dbg(&dev->pdev->dev, "mei_hdr->length  =%d\n",
-					mei_hdr->length);
-		}
-		return -EMSGSIZE;
 	} else {
-		return -EBADMSG;
+		/* wait for next time the host buffer is empty */
+		return 0;
 	}
 
-	return 0;
-}
-
-/**
- * _mei_irq_thread_cmpl_iamthif - processes completed iamthif operation.
- *
- * @dev: the device structure.
- * @slots: free slots.
- * @cb_pos: callback block.
- * @cl: private data of the file object.
- * @cmpl_list: complete list.
- *
- * returns 0, OK; otherwise, error.
- */
-static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
-			struct mei_cl_cb *cb_pos,
-			struct mei_cl *cl,
-			struct mei_io_list *cmpl_list)
-{
-	struct mei_msg_hdr *mei_hdr;
-
-	if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
-			dev->iamthif_msg_buf_size -
-			dev->iamthif_msg_buf_index)) {
-		mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
-		mei_hdr->host_addr = cl->host_client_id;
-		mei_hdr->me_addr = cl->me_client_id;
-		mei_hdr->length = dev->iamthif_msg_buf_size -
-			dev->iamthif_msg_buf_index;
-		mei_hdr->msg_complete = 1;
-		mei_hdr->reserved = 0;
-
-		*slots -= mei_data2slots(mei_hdr->length);
-
-		if (mei_write_message(dev, mei_hdr,
-					(dev->iamthif_msg_buf +
-					dev->iamthif_msg_buf_index),
-					mei_hdr->length)) {
-			dev->iamthif_state = MEI_IAMTHIF_IDLE;
-			cl->status = -ENODEV;
-			list_del(&cb_pos->cb_list);
-			return -ENODEV;
-		} else {
-			if (mei_flow_ctrl_reduce(dev, cl))
-				return -ENODEV;
-			dev->iamthif_msg_buf_index += mei_hdr->length;
-			cb_pos->information = dev->iamthif_msg_buf_index;
-			cl->status = 0;
-			dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
-			dev->iamthif_flow_control_pending = true;
-			/* save iamthif cb sent to amthi client */
-			dev->iamthif_current_cb = cb_pos;
-			list_move_tail(&cb_pos->cb_list,
-				&dev->write_waiting_list.mei_cb.cb_list);
+	dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n",
+			cb->request_buffer.size, cb->buf_idx);
+	dev_dbg(&dev->pdev->dev, "msg: len = %d complete = %d\n",
+			mei_hdr->length, mei_hdr->msg_complete);
 
-		}
-	} else if (*slots == dev->hbuf_depth) {
-		/* buffer is still empty */
-		mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
-		mei_hdr->host_addr = cl->host_client_id;
-		mei_hdr->me_addr = cl->me_client_id;
-		mei_hdr->length =
-			(*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
-		mei_hdr->msg_complete = 0;
-		mei_hdr->reserved = 0;
+	*slots -=  msg_slots;
+	if (mei_write_message(dev, mei_hdr,
+		cb->request_buffer.data + cb->buf_idx, len)) {
+		cl->status = -ENODEV;
+		list_move_tail(&cb->list, &cmpl_list->list);
+		return -ENODEV;
+	}
 
-		*slots -= mei_data2slots(mei_hdr->length);
+	if (mei_flow_ctrl_reduce(dev, cl))
+		return -ENODEV;
 
-		if (mei_write_message(dev, mei_hdr,
-					(dev->iamthif_msg_buf +
-					dev->iamthif_msg_buf_index),
-					mei_hdr->length)) {
-			cl->status = -ENODEV;
-			list_del(&cb_pos->cb_list);
-		} else {
-			dev->iamthif_msg_buf_index += mei_hdr->length;
-		}
-		return -EMSGSIZE;
-	} else {
-		return -EBADMSG;
-	}
+	cl->status = 0;
+	cb->buf_idx += mei_hdr->length;
+	if (mei_hdr->msg_complete)
+		list_move_tail(&cb->list, &dev->write_waiting_list.list);
 
 	return 0;
 }
@@ -1067,7 +775,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
  *
  * returns 0 on success, <0 on failure.
  */
-static int mei_irq_thread_read_handler(struct mei_io_list *cmpl_list,
+static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list,
 		struct mei_device *dev,
 		s32 *slots)
 {
@@ -1130,8 +838,8 @@ static int mei_irq_thread_read_handler(struct mei_io_list *cmpl_list,
 		dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n");
 		dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
 				mei_hdr->length);
-		ret = mei_irq_thread_read_amthi_message(cmpl_list,
-							dev, mei_hdr);
+
+		ret = mei_amthif_irq_read_message(cmpl_list, dev, mei_hdr);
 		if (ret)
 			goto end;
 
@@ -1164,53 +872,51 @@ end:
  * mei_irq_thread_write_handler - bottom half write routine after
  * ISR to handle the write processing.
  *
- * @cmpl_list: An instance of our list structure
  * @dev: the device structure
- * @slots: slots to write.
+ * @cmpl_list: An instance of our list structure
  *
  * returns 0 on success, <0 on failure.
  */
-static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
-		struct mei_device *dev,
-		s32 *slots)
+static int mei_irq_thread_write_handler(struct mei_device *dev,
+				struct mei_cl_cb *cmpl_list)
 {
 
 	struct mei_cl *cl;
 	struct mei_cl_cb *pos = NULL, *next = NULL;
-	struct mei_io_list *list;
+	struct mei_cl_cb *list;
+	s32 slots;
 	int ret;
 
 	if (!mei_hbuf_is_empty(dev)) {
 		dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
 		return 0;
 	}
-	*slots = mei_hbuf_empty_slots(dev);
-	if (*slots <= 0)
+	slots = mei_hbuf_empty_slots(dev);
+	if (slots <= 0)
 		return -EMSGSIZE;
 
 	/* complete all waiting for write CB */
 	dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
 
 	list = &dev->write_waiting_list;
-	list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) {
-		cl = (struct mei_cl *)pos->file_private;
+	list_for_each_entry_safe(pos, next, &list->list, list) {
+		cl = pos->cl;
 		if (cl == NULL)
 			continue;
 
 		cl->status = 0;
-		list_del(&pos->cb_list);
+		list_del(&pos->list);
 		if (MEI_WRITING == cl->writing_state &&
-		   (pos->major_file_operations == MEI_WRITE) &&
-		   (cl != &dev->iamthif_cl)) {
+		    pos->fop_type == MEI_FOP_WRITE &&
+		    cl != &dev->iamthif_cl) {
 			dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n");
 			cl->writing_state = MEI_WRITE_COMPLETE;
-			list_add_tail(&pos->cb_list,
-				      &cmpl_list->mei_cb.cb_list);
+			list_add_tail(&pos->list, &cmpl_list->list);
 		}
 		if (cl == &dev->iamthif_cl) {
 			dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
 			if (dev->iamthif_flow_control_pending) {
-				ret = _mei_irq_thread_iamthif_read(dev, slots);
+				ret = mei_amthif_irq_read(dev, &slots);
 				if (ret)
 					return ret;
 			}
@@ -1222,15 +928,11 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
 		wake_up_interruptible(&dev->wait_stop_wd);
 	}
 
-	if (dev->extra_write_index) {
-		dev_dbg(&dev->pdev->dev, "extra_write_index =%d.\n",
-				dev->extra_write_index);
-		mei_write_message(dev,
-				(struct mei_msg_hdr *) &dev->ext_msg_buf[0],
-				(unsigned char *) &dev->ext_msg_buf[1],
-				(dev->extra_write_index - 1) * sizeof(u32));
-		*slots -= dev->extra_write_index;
-		dev->extra_write_index = 0;
+	if (dev->wr_ext_msg.hdr.length) {
+		mei_write_message(dev, &dev->wr_ext_msg.hdr,
+			dev->wr_ext_msg.data, dev->wr_ext_msg.hdr.length);
+		slots -= mei_data2slots(dev->wr_ext_msg.hdr.length);
+		dev->wr_ext_msg.hdr.length = 0;
 	}
 	if (dev->dev_state == MEI_DEV_ENABLED) {
 		if (dev->wd_pending &&
@@ -1243,41 +945,43 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
 			dev->wd_pending = false;
 
 			if (dev->wd_state == MEI_WD_RUNNING)
-				*slots -= mei_data2slots(MEI_WD_START_MSG_SIZE);
+				slots -= mei_data2slots(MEI_WD_START_MSG_SIZE);
 			else
-				*slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE);
+				slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE);
 		}
 	}
 
 	/* complete control write list CB */
 	dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
-	list_for_each_entry_safe(pos, next,
-				&dev->ctrl_wr_list.mei_cb.cb_list, cb_list) {
-		cl = (struct mei_cl *) pos->file_private;
+	list_for_each_entry_safe(pos, next, &dev->ctrl_wr_list.list, list) {
+		cl = pos->cl;
 		if (!cl) {
-			list_del(&pos->cb_list);
+			list_del(&pos->list);
 			return -ENODEV;
 		}
-		switch (pos->major_file_operations) {
-		case MEI_CLOSE:
+		switch (pos->fop_type) {
+		case MEI_FOP_CLOSE:
 			/* send disconnect message */
-			ret = _mei_irq_thread_close(dev, slots, pos, cl, cmpl_list);
+			ret = _mei_irq_thread_close(dev, &slots, pos,
+						cl, cmpl_list);
 			if (ret)
 				return ret;
 
 			break;
-		case MEI_READ:
+		case MEI_FOP_READ:
 			/* send flow control message */
-			ret = _mei_irq_thread_read(dev, slots, pos, cl, cmpl_list);
+			ret = _mei_irq_thread_read(dev, &slots, pos,
+						cl, cmpl_list);
 			if (ret)
 				return ret;
 
 			break;
-		case MEI_IOCTL:
+		case MEI_FOP_IOCTL:
 			/* connect message */
 			if (mei_other_client_is_connecting(dev, cl))
 				continue;
-			ret = _mei_irq_thread_ioctl(dev, slots, pos, cl, cmpl_list);
+			ret = _mei_irq_thread_ioctl(dev, &slots, pos,
+						cl, cmpl_list);
 			if (ret)
 				return ret;
 
@@ -1290,40 +994,26 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
 	}
 	/* complete  write list CB */
 	dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
-	list_for_each_entry_safe(pos, next,
-				&dev->write_list.mei_cb.cb_list, cb_list) {
-		cl = (struct mei_cl *)pos->file_private;
+	list_for_each_entry_safe(pos, next, &dev->write_list.list, list) {
+		cl = pos->cl;
 		if (cl == NULL)
 			continue;
-
-		if (cl != &dev->iamthif_cl) {
-			if (mei_flow_ctrl_creds(dev, cl) <= 0) {
-				dev_dbg(&dev->pdev->dev,
-					"No flow control credentials for client %d, not sending.\n",
-					cl->host_client_id);
-				continue;
-			}
-			ret = _mei_irq_thread_cmpl(dev, slots, pos,
-						cl, cmpl_list);
-			if (ret)
-				return ret;
-
-		} else if (cl == &dev->iamthif_cl) {
-			/* IAMTHIF IOCTL */
-			dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n");
-			if (mei_flow_ctrl_creds(dev, cl) <= 0) {
-				dev_dbg(&dev->pdev->dev,
-					"No flow control credentials for amthi client %d.\n",
-					cl->host_client_id);
-				continue;
-			}
-			ret = _mei_irq_thread_cmpl_iamthif(dev, slots, pos,
-						cl, cmpl_list);
-			if (ret)
-				return ret;
-
+		if (mei_flow_ctrl_creds(dev, 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(dev, &slots,
+							pos, cmpl_list);
+		else
+			ret = mei_irq_thread_write_complete(dev, &slots, pos,
+						cmpl_list);
+		if (ret)
+			return ret;
+
 	}
 	return 0;
 }
@@ -1342,7 +1032,6 @@ void mei_timer(struct work_struct *work)
 	unsigned long timeout;
 	struct mei_cl *cl_pos = NULL;
 	struct mei_cl *cl_next = NULL;
-	struct list_head *amthi_complete_list = NULL;
 	struct mei_cl_cb  *cb_pos = NULL;
 	struct mei_cl_cb  *cb_next = NULL;
 
@@ -1385,19 +1074,18 @@ void mei_timer(struct work_struct *work)
 			dev->iamthif_state = MEI_IAMTHIF_IDLE;
 			dev->iamthif_timer = 0;
 
-			if (dev->iamthif_current_cb)
-				mei_free_cb_private(dev->iamthif_current_cb);
+			mei_io_cb_free(dev->iamthif_current_cb);
+			dev->iamthif_current_cb = NULL;
 
 			dev->iamthif_file_object = NULL;
-			dev->iamthif_current_cb = NULL;
-			mei_run_next_iamthif_cmd(dev);
+			mei_amthif_run_next_cmd(dev);
 		}
 	}
 
 	if (dev->iamthif_timer) {
 
 		timeout = dev->iamthif_timer +
-				msecs_to_jiffies(IAMTHIF_READ_TIMER);
+			mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
 
 		dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
 				dev->iamthif_timer);
@@ -1411,25 +1099,22 @@ void mei_timer(struct work_struct *work)
 
 			dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n");
 
-			amthi_complete_list = &dev->amthi_read_complete_list.
-					mei_cb.cb_list;
-
-			list_for_each_entry_safe(cb_pos, cb_next, amthi_complete_list, cb_list) {
+			list_for_each_entry_safe(cb_pos, cb_next,
+				&dev->amthif_rd_complete_list.list, list) {
 
 				cl_pos = cb_pos->file_object->private_data;
 
 				/* Finding the AMTHI entry. */
 				if (cl_pos == &dev->iamthif_cl)
-					list_del(&cb_pos->cb_list);
+					list_del(&cb_pos->list);
 			}
-			if (dev->iamthif_current_cb)
-				mei_free_cb_private(dev->iamthif_current_cb);
+			mei_io_cb_free(dev->iamthif_current_cb);
+			dev->iamthif_current_cb = NULL;
 
 			dev->iamthif_file_object->private_data = NULL;
 			dev->iamthif_file_object = NULL;
-			dev->iamthif_current_cb = NULL;
 			dev->iamthif_timer = 0;
-			mei_run_next_iamthif_cmd(dev);
+			mei_amthif_run_next_cmd(dev);
 
 		}
 	}
@@ -1451,7 +1136,7 @@ out:
 irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
 {
 	struct mei_device *dev = (struct mei_device *) dev_id;
-	struct mei_io_list complete_list;
+	struct mei_cl_cb complete_list;
 	struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
 	struct mei_cl *cl;
 	s32 slots;
@@ -1504,17 +1189,17 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
 	}
 	/* check slots available for reading */
 	slots = mei_count_full_read_slots(dev);
-	dev_dbg(&dev->pdev->dev, "slots =%08x  extra_write_index =%08x.\n",
-		slots, dev->extra_write_index);
-	while (slots > 0 && !dev->extra_write_index) {
-		dev_dbg(&dev->pdev->dev, "slots =%08x  extra_write_index =%08x.\n",
-				slots, dev->extra_write_index);
+	while (slots > 0) {
+		/* we have urgent data to send so break the read */
+		if (dev->wr_ext_msg.hdr.length)
+			break;
+		dev_dbg(&dev->pdev->dev, "slots =%08x\n", slots);
 		dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n");
 		rets = mei_irq_thread_read_handler(&complete_list, dev, &slots);
 		if (rets)
 			goto end;
 	}
-	rets = mei_irq_thread_write_handler(&complete_list, dev, &slots);
+	rets = mei_irq_thread_write_handler(dev, &complete_list);
 end:
 	dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
 	dev->host_hw_state = mei_hcsr_read(dev);
@@ -1531,21 +1216,20 @@ end:
 		wake_up_interruptible(&dev->wait_recvd_msg);
 		bus_message_received = false;
 	}
-	if (list_empty(&complete_list.mei_cb.cb_list))
+	if (list_empty(&complete_list.list))
 		return IRQ_HANDLED;
 
 
-	list_for_each_entry_safe(cb_pos, cb_next,
-			&complete_list.mei_cb.cb_list, cb_list) {
-		cl = (struct mei_cl *)cb_pos->file_private;
-		list_del(&cb_pos->cb_list);
+	list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) {
+		cl = cb_pos->cl;
+		list_del(&cb_pos->list);
 		if (cl) {
 			if (cl != &dev->iamthif_cl) {
 				dev_dbg(&dev->pdev->dev, "completing call back.\n");
 				_mei_cmpl(cl, cb_pos);
 				cb_pos = NULL;
 			} else if (cl == &dev->iamthif_cl) {
-				_mei_cmpl_iamthif(dev, cb_pos);
+				mei_amthif_complete(dev, cb_pos);
 			}
 		}
 	}
diff --git a/drivers/misc/mei/iorw.c b/drivers/misc/mei/iorw.c
index fcba98e..eb93a1b 100644
--- a/drivers/misc/mei/iorw.c
+++ b/drivers/misc/mei/iorw.c
@@ -39,6 +39,95 @@
 #include "interface.h"
 
 /**
+ * mei_io_cb_free - free mei_cb_private related memory
+ *
+ * @cb: mei callback struct
+ */
+void mei_io_cb_free(struct mei_cl_cb *cb)
+{
+	if (cb == NULL)
+		return;
+
+	kfree(cb->request_buffer.data);
+	kfree(cb->response_buffer.data);
+	kfree(cb);
+}
+/**
+ * mei_io_cb_init - allocate and initialize io callback
+ *
+ * @cl - mei client
+ * @file: pointer to file structure
+ *
+ * returns mei_cl_cb pointer or NULL;
+ */
+struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
+{
+	struct mei_cl_cb *cb;
+
+	cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+	if (!cb)
+		return NULL;
+
+	mei_io_list_init(cb);
+
+	cb->file_object = fp;
+	cb->cl = cl;
+	cb->buf_idx = 0;
+	return cb;
+}
+
+
+/**
+ * mei_io_cb_alloc_req_buf - allocate request buffer
+ *
+ * @cb -  io callback structure
+ * @size: size of the buffer
+ *
+ * returns 0 on success
+ *         -EINVAL if cb is NULL
+ *         -ENOMEM if allocation failed
+ */
+int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length)
+{
+	if (!cb)
+		return -EINVAL;
+
+	if (length == 0)
+		return 0;
+
+	cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
+	if (!cb->request_buffer.data)
+		return -ENOMEM;
+	cb->request_buffer.size = length;
+	return 0;
+}
+/**
+ * mei_io_cb_alloc_req_buf - allocate respose buffer
+ *
+ * @cb -  io callback structure
+ * @size: size of the buffer
+ *
+ * returns 0 on success
+ *         -EINVAL if cb is NULL
+ *         -ENOMEM if allocation failed
+ */
+int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
+{
+	if (!cb)
+		return -EINVAL;
+
+	if (length == 0)
+		return 0;
+
+	cb->response_buffer.data = kmalloc(length, GFP_KERNEL);
+	if (!cb->response_buffer.data)
+		return -ENOMEM;
+	cb->response_buffer.size = length;
+	return 0;
+}
+
+
+/**
  * mei_me_cl_by_id return index to me_clients for client_id
  *
  * @dev: the device structure
@@ -82,9 +171,7 @@ int mei_ioctl_connect_client(struct file *file,
 	struct mei_cl_cb *cb;
 	struct mei_client *client;
 	struct mei_cl *cl;
-	struct mei_cl *cl_pos = NULL;
-	struct mei_cl *cl_next = NULL;
-	long timeout = CONNECT_TIMEOUT;
+	long timeout = mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT);
 	int i;
 	int err;
 	int rets;
@@ -97,16 +184,14 @@ int mei_ioctl_connect_client(struct file *file,
 
 	dev_dbg(&dev->pdev->dev, "mei_ioctl_connect_client() Entry\n");
 
-
 	/* buffered ioctl cb */
-	cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+	cb = mei_io_cb_init(cl, file);
 	if (!cb) {
 		rets = -ENOMEM;
 		goto end;
 	}
-	INIT_LIST_HEAD(&cb->cb_list);
 
-	cb->major_file_operations = MEI_IOCTL;
+	cb->fop_type = MEI_FOP_IOCTL;
 
 	if (dev->dev_state != MEI_DEV_ENABLED) {
 		rets = -ENODEV;
@@ -142,21 +227,9 @@ int mei_ioctl_connect_client(struct file *file,
 			goto end;
 		}
 		clear_bit(cl->host_client_id, dev->host_clients_map);
-		list_for_each_entry_safe(cl_pos, cl_next,
-					 &dev->file_list, link) {
-			if (mei_cl_cmp_id(cl, cl_pos)) {
-				dev_dbg(&dev->pdev->dev,
-					"remove file private data node host"
-				    " client = %d, ME client = %d.\n",
-				    cl_pos->host_client_id,
-				    cl_pos->me_client_id);
-				list_del(&cl_pos->link);
-			}
+		mei_me_cl_unlink(dev, cl);
 
-		}
-		dev_dbg(&dev->pdev->dev, "free file private data memory.\n");
 		kfree(cl);
-
 		cl = NULL;
 		file->private_data = &dev->iamthif_cl;
 
@@ -192,25 +265,19 @@ int mei_ioctl_connect_client(struct file *file,
 		} else {
 			dev_dbg(&dev->pdev->dev, "Sending connect message - succeeded\n");
 			cl->timer_count = MEI_CONNECT_TIMEOUT;
-			cb->file_private = cl;
-			list_add_tail(&cb->cb_list,
-				      &dev->ctrl_rd_list.mei_cb.
-				      cb_list);
+			list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
 		}
 
 
 	} else {
 		dev_dbg(&dev->pdev->dev, "Queuing the connect request due to device busy\n");
-		cb->file_private = cl;
 		dev_dbg(&dev->pdev->dev, "add connect cb to control write list.\n");
-		list_add_tail(&cb->cb_list,
-			      &dev->ctrl_wr_list.mei_cb.cb_list);
+		list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
 	}
 	mutex_unlock(&dev->device_lock);
 	err = wait_event_timeout(dev->wait_recvd_msg,
 			(MEI_FILE_CONNECTED == cl->state ||
-			 MEI_FILE_DISCONNECTED == cl->state),
-			timeout * HZ);
+			 MEI_FILE_DISCONNECTED == cl->state), timeout);
 
 	mutex_lock(&dev->device_lock);
 	if (MEI_FILE_CONNECTED == cl->state) {
@@ -234,153 +301,7 @@ int mei_ioctl_connect_client(struct file *file,
 	rets = 0;
 end:
 	dev_dbg(&dev->pdev->dev, "free connect cb memory.");
-	kfree(cb);
-	return rets;
-}
-
-/**
- * find_amthi_read_list_entry - finds a amthilist entry for current file
- *
- * @dev: the device structure
- * @file: pointer to file object
- *
- * returns   returned a list entry on success, NULL on failure.
- */
-struct mei_cl_cb *find_amthi_read_list_entry(
-		struct mei_device *dev,
-		struct file *file)
-{
-	struct mei_cl *cl_temp;
-	struct mei_cl_cb *pos = NULL;
-	struct mei_cl_cb *next = NULL;
-
-	list_for_each_entry_safe(pos, next,
-	    &dev->amthi_read_complete_list.mei_cb.cb_list, cb_list) {
-		cl_temp = (struct mei_cl *)pos->file_private;
-		if (cl_temp && cl_temp == &dev->iamthif_cl &&
-			pos->file_object == file)
-			return pos;
-	}
-	return NULL;
-}
-
-/**
- * amthi_read - read data from AMTHI client
- *
- * @dev: the device structure
- * @if_num:  minor number
- * @file: pointer to file object
- * @*ubuf: pointer to user data in user space
- * @length: data length to read
- * @offset: data read offset
- *
- * Locking: called under "dev->device_lock" lock
- *
- * returns
- *  returned data length on success,
- *  zero if no data to read,
- *  negative on failure.
- */
-int amthi_read(struct mei_device *dev, struct file *file,
-	       char __user *ubuf, size_t length, loff_t *offset)
-{
-	int rets;
-	int wait_ret;
-	struct mei_cl_cb *cb = NULL;
-	struct mei_cl *cl = file->private_data;
-	unsigned long timeout;
-	int i;
-
-	/* Only Posible if we are in timeout */
-	if (!cl || cl != &dev->iamthif_cl) {
-		dev_dbg(&dev->pdev->dev, "bad file ext.\n");
-		return -ETIMEDOUT;
-	}
-
-	i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
-
-	if (i < 0) {
-		dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
-		return -ENODEV;
-	}
-	dev_dbg(&dev->pdev->dev, "checking amthi data\n");
-	cb = find_amthi_read_list_entry(dev, file);
-
-	/* Check for if we can block or not*/
-	if (cb == NULL && file->f_flags & O_NONBLOCK)
-		return -EAGAIN;
-
-
-	dev_dbg(&dev->pdev->dev, "waiting for amthi data\n");
-	while (cb == NULL) {
-		/* unlock the Mutex */
-		mutex_unlock(&dev->device_lock);
-
-		wait_ret = wait_event_interruptible(dev->iamthif_cl.wait,
-			(cb = find_amthi_read_list_entry(dev, file)));
-
-		if (wait_ret)
-			return -ERESTARTSYS;
-
-		dev_dbg(&dev->pdev->dev, "woke up from sleep\n");
-
-		/* Locking again the Mutex */
-		mutex_lock(&dev->device_lock);
-	}
-
-
-	dev_dbg(&dev->pdev->dev, "Got amthi data\n");
-	dev->iamthif_timer = 0;
-
-	if (cb) {
-		timeout = cb->read_time + msecs_to_jiffies(IAMTHIF_READ_TIMER);
-		dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n",
-				timeout);
-
-		if  (time_after(jiffies, timeout)) {
-			dev_dbg(&dev->pdev->dev, "amthi Time out\n");
-			/* 15 sec for the message has expired */
-			list_del(&cb->cb_list);
-			rets = -ETIMEDOUT;
-			goto free;
-		}
-	}
-	/* if the whole message will fit remove it from the list */
-	if (cb->information >= *offset && length >= (cb->information - *offset))
-		list_del(&cb->cb_list);
-	else if (cb->information > 0 && cb->information <= *offset) {
-		/* end of the message has been reached */
-		list_del(&cb->cb_list);
-		rets = 0;
-		goto free;
-	}
-		/* else means that not full buffer will be read and do not
-		 * remove message from deletion list
-		 */
-
-	dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n",
-	    cb->response_buffer.size);
-	dev_dbg(&dev->pdev->dev, "amthi cb->information - %lu\n",
-	    cb->information);
-
-	/* length is being turncated to PAGE_SIZE, however,
-	 * the information may be longer */
-	length = min_t(size_t, length, (cb->information - *offset));
-
-	if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length))
-		rets = -EFAULT;
-	else {
-		rets = length;
-		if ((*offset + length) < cb->information) {
-			*offset += length;
-			goto out;
-		}
-	}
-free:
-	dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n");
-	*offset = 0;
-	mei_free_cb_private(cb);
-out:
+	mei_io_cb_free(cb);
 	return rets;
 }
 
@@ -396,7 +317,7 @@ out:
 int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
 {
 	struct mei_cl_cb *cb;
-	int rets = 0;
+	int rets;
 	int i;
 
 	if (cl->state != MEI_FILE_CONNECTED)
@@ -405,187 +326,41 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
 	if (dev->dev_state != MEI_DEV_ENABLED)
 		return -ENODEV;
 
-	dev_dbg(&dev->pdev->dev, "check if read is pending.\n");
 	if (cl->read_pending || cl->read_cb) {
 		dev_dbg(&dev->pdev->dev, "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);
+		return  -ENODEV;
+	}
 
-	cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+	cb = mei_io_cb_init(cl, NULL);
 	if (!cb)
 		return -ENOMEM;
 
-	dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n",
-		cl->host_client_id, cl->me_client_id);
-	i = mei_me_cl_by_id(dev, cl->me_client_id);
-	if (i < 0) {
-		rets = -ENODEV;
-		goto unlock;
-	}
+	rets = mei_io_cb_alloc_resp_buf(cb,
+			dev->me_clients[i].props.max_msg_length);
+	if (rets)
+		goto err;
 
-	cb->response_buffer.size = dev->me_clients[i].props.max_msg_length;
-	cb->response_buffer.data =
-			kmalloc(cb->response_buffer.size, GFP_KERNEL);
-	if (!cb->response_buffer.data) {
-		rets = -ENOMEM;
-		goto unlock;
-	}
-	dev_dbg(&dev->pdev->dev, "allocation call back data success.\n");
-	cb->major_file_operations = MEI_READ;
-	/* make sure information is zero before we start */
-	cb->information = 0;
-	cb->file_private = (void *) cl;
+	cb->fop_type = MEI_FOP_READ;
 	cl->read_cb = cb;
 	if (dev->mei_host_buffer_is_empty) {
 		dev->mei_host_buffer_is_empty = false;
 		if (mei_send_flow_control(dev, cl)) {
 			rets = -ENODEV;
-			goto unlock;
+			goto err;
 		}
-		list_add_tail(&cb->cb_list, &dev->read_list.mei_cb.cb_list);
+		list_add_tail(&cb->list, &dev->read_list.list);
 	} else {
-		list_add_tail(&cb->cb_list, &dev->ctrl_wr_list.mei_cb.cb_list);
+		list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
 	}
 	return rets;
-unlock:
-	mei_free_cb_private(cb);
+err:
+	mei_io_cb_free(cb);
 	return rets;
 }
 
-/**
- * amthi_write - write iamthif data to amthi client
- *
- * @dev: the device structure
- * @cb: mei call back struct
- *
- * returns 0 on success, <0 on failure.
- */
-int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
-{
-	struct mei_msg_hdr mei_hdr;
-	int ret;
-
-	if (!dev || !cb)
-		return -ENODEV;
-
-	dev_dbg(&dev->pdev->dev, "write data to amthi client.\n");
-
-	dev->iamthif_state = MEI_IAMTHIF_WRITING;
-	dev->iamthif_current_cb = cb;
-	dev->iamthif_file_object = cb->file_object;
-	dev->iamthif_canceled = false;
-	dev->iamthif_ioctl = true;
-	dev->iamthif_msg_buf_size = cb->request_buffer.size;
-	memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
-	       cb->request_buffer.size);
-
-	ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl);
-	if (ret < 0)
-		return ret;
-
-	if (ret && dev->mei_host_buffer_is_empty) {
-		ret = 0;
-		dev->mei_host_buffer_is_empty = false;
-		if (cb->request_buffer.size > mei_hbuf_max_data(dev)) {
-			mei_hdr.length = mei_hbuf_max_data(dev);
-			mei_hdr.msg_complete = 0;
-		} else {
-			mei_hdr.length = cb->request_buffer.size;
-			mei_hdr.msg_complete = 1;
-		}
-
-		mei_hdr.host_addr = dev->iamthif_cl.host_client_id;
-		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),
-					mei_hdr.length))
-			return -ENODEV;
-
-		if (mei_hdr.msg_complete) {
-			if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl))
-				return -ENODEV;
-			dev->iamthif_flow_control_pending = true;
-			dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
-			dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n");
-			dev->iamthif_current_cb = cb;
-			dev->iamthif_file_object = cb->file_object;
-			list_add_tail(&cb->cb_list,
-				      &dev->write_waiting_list.mei_cb.cb_list);
-		} else {
-			dev_dbg(&dev->pdev->dev, "message does not complete, "
-					"so add amthi cb to write list.\n");
-			list_add_tail(&cb->cb_list,
-				      &dev->write_list.mei_cb.cb_list);
-		}
-	} else {
-		if (!(dev->mei_host_buffer_is_empty))
-			dev_dbg(&dev->pdev->dev, "host buffer is not empty");
-
-		dev_dbg(&dev->pdev->dev, "No flow control credentials, "
-				"so add iamthif cb to write list.\n");
-		list_add_tail(&cb->cb_list, &dev->write_list.mei_cb.cb_list);
-	}
-	return 0;
-}
-
-/**
- * iamthif_ioctl_send_msg - send cmd data to amthi client
- *
- * @dev: the device structure
- *
- * returns 0 on success, <0 on failure.
- */
-void mei_run_next_iamthif_cmd(struct mei_device *dev)
-{
-	struct mei_cl *cl_tmp;
-	struct mei_cl_cb *pos = NULL;
-	struct mei_cl_cb *next = NULL;
-	int status;
-
-	if (!dev)
-		return;
-
-	dev->iamthif_msg_buf_size = 0;
-	dev->iamthif_msg_buf_index = 0;
-	dev->iamthif_canceled = false;
-	dev->iamthif_ioctl = true;
-	dev->iamthif_state = MEI_IAMTHIF_IDLE;
-	dev->iamthif_timer = 0;
-	dev->iamthif_file_object = NULL;
-
-	dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n");
-
-	list_for_each_entry_safe(pos, next,
-			&dev->amthi_cmd_list.mei_cb.cb_list, cb_list) {
-		list_del(&pos->cb_list);
-		cl_tmp = (struct mei_cl *)pos->file_private;
-
-		if (cl_tmp && cl_tmp == &dev->iamthif_cl) {
-			status = amthi_write(dev, pos);
-			if (status) {
-				dev_dbg(&dev->pdev->dev,
-					"amthi write failed status = %d\n",
-						status);
-				return;
-			}
-			break;
-		}
-	}
-}
-
-/**
- * mei_free_cb_private - free mei_cb_private related memory
- *
- * @cb: mei callback struct
- */
-void mei_free_cb_private(struct mei_cl_cb *cb)
-{
-	if (cb == NULL)
-		return;
-
-	kfree(cb->request_buffer.data);
-	kfree(cb->response_buffer.data);
-	kfree(cb);
-}
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index e8b0858..43fb52f 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -90,93 +90,6 @@ static DEFINE_MUTEX(mei_mutex);
 
 
 /**
- * mei_clear_list - removes all callbacks associated with file
- *		from mei_cb_list
- *
- * @dev: device structure.
- * @file: file structure
- * @mei_cb_list: callbacks list
- *
- * mei_clear_list is called to clear resources associated with file
- * when application calls close function or Ctrl-C was pressed
- *
- * returns true if callback removed from the list, false otherwise
- */
-static bool mei_clear_list(struct mei_device *dev,
-		struct file *file, struct list_head *mei_cb_list)
-{
-	struct mei_cl_cb *cb_pos = NULL;
-	struct mei_cl_cb *cb_next = NULL;
-	struct file *file_temp;
-	bool removed = false;
-
-	/* list all list member */
-	list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, cb_list) {
-		file_temp = (struct file *)cb_pos->file_object;
-		/* check if list member associated with a file */
-		if (file_temp == file) {
-			/* remove member from the list */
-			list_del(&cb_pos->cb_list);
-			/* check if cb equal to current iamthif cb */
-			if (dev->iamthif_current_cb == cb_pos) {
-				dev->iamthif_current_cb = NULL;
-				/* send flow control to iamthif client */
-				mei_send_flow_control(dev, &dev->iamthif_cl);
-			}
-			/* free all allocated buffers */
-			mei_free_cb_private(cb_pos);
-			cb_pos = NULL;
-			removed = true;
-		}
-	}
-	return removed;
-}
-
-/**
- * mei_clear_lists - removes all callbacks associated with file
- *
- * @dev: device structure
- * @file: file structure
- *
- * mei_clear_lists is called to clear resources associated with file
- * when application calls close function or Ctrl-C was pressed
- *
- * returns true if callback removed from the list, false otherwise
- */
-static bool mei_clear_lists(struct mei_device *dev, struct file *file)
-{
-	bool removed = false;
-
-	/* remove callbacks associated with a file */
-	mei_clear_list(dev, file, &dev->amthi_cmd_list.mei_cb.cb_list);
-	if (mei_clear_list(dev, file,
-			    &dev->amthi_read_complete_list.mei_cb.cb_list))
-		removed = true;
-
-	mei_clear_list(dev, file, &dev->ctrl_rd_list.mei_cb.cb_list);
-
-	if (mei_clear_list(dev, file, &dev->ctrl_wr_list.mei_cb.cb_list))
-		removed = true;
-
-	if (mei_clear_list(dev, file, &dev->write_waiting_list.mei_cb.cb_list))
-		removed = true;
-
-	if (mei_clear_list(dev, file, &dev->write_list.mei_cb.cb_list))
-		removed = true;
-
-	/* check if iamthif_current_cb not NULL */
-	if (dev->iamthif_current_cb && !removed) {
-		/* check file and iamthif current cb association */
-		if (dev->iamthif_current_cb->file_object == file) {
-			/* remove cb */
-			mei_free_cb_private(dev->iamthif_current_cb);
-			dev->iamthif_current_cb = NULL;
-			removed = true;
-		}
-	}
-	return removed;
-}
-/**
  * find_read_list_entry - find read list entry
  *
  * @dev: device structure
@@ -192,14 +105,9 @@ static struct mei_cl_cb *find_read_list_entry(
 	struct mei_cl_cb *next = NULL;
 
 	dev_dbg(&dev->pdev->dev, "remove read_list CB\n");
-	list_for_each_entry_safe(pos, next,
-			&dev->read_list.mei_cb.cb_list, cb_list) {
-		struct mei_cl *cl_temp;
-		cl_temp = (struct mei_cl *)pos->file_private;
-
-		if (mei_cl_cmp_id(cl, cl_temp))
+	list_for_each_entry_safe(pos, next, &dev->read_list.list, list)
+		if (mei_cl_cmp_id(cl, pos->cl))
 			return pos;
-	}
 	return NULL;
 }
 
@@ -297,67 +205,51 @@ static int mei_release(struct inode *inode, struct file *file)
 	dev = cl->dev;
 
 	mutex_lock(&dev->device_lock);
-	if (cl != &dev->iamthif_cl) {
-		if (cl->state == MEI_FILE_CONNECTED) {
-			cl->state = MEI_FILE_DISCONNECTING;
-			dev_dbg(&dev->pdev->dev,
-				"disconnecting client host client = %d, "
-			    "ME client = %d\n",
-			    cl->host_client_id,
-			    cl->me_client_id);
-			rets = mei_disconnect_host_client(dev, cl);
-		}
-		mei_cl_flush_queues(cl);
-		dev_dbg(&dev->pdev->dev, "remove client host client = %d, ME client = %d\n",
+	if (cl == &dev->iamthif_cl) {
+		rets = mei_amthif_release(dev, file);
+		goto out;
+	}
+	if (cl->state == MEI_FILE_CONNECTED) {
+		cl->state = MEI_FILE_DISCONNECTING;
+		dev_dbg(&dev->pdev->dev,
+			"disconnecting client host client = %d, "
+		    "ME client = %d\n",
 		    cl->host_client_id,
 		    cl->me_client_id);
+		rets = mei_disconnect_host_client(dev, cl);
+	}
+	mei_cl_flush_queues(cl);
+	dev_dbg(&dev->pdev->dev, "remove client host client = %d, ME client = %d\n",
+	    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_me_cl_unlink(dev, cl);
 
-		if (dev->open_handle_count > 0) {
-			clear_bit(cl->host_client_id, dev->host_clients_map);
-			dev->open_handle_count--;
-		}
-		mei_remove_client_from_file_list(dev, cl->host_client_id);
-
-		/* free read cb */
-		cb = NULL;
-		if (cl->read_cb) {
-			cb = find_read_list_entry(dev, cl);
-			/* Remove entry from read list */
-			if (cb)
-				list_del(&cb->cb_list);
-
-			cb = cl->read_cb;
-			cl->read_cb = NULL;
-		}
-
-		file->private_data = NULL;
-
-		if (cb) {
-			mei_free_cb_private(cb);
-			cb = NULL;
-		}
+	/* free read cb */
+	cb = NULL;
+	if (cl->read_cb) {
+		cb = find_read_list_entry(dev, cl);
+		/* Remove entry from read list */
+		if (cb)
+			list_del(&cb->list);
 
-		kfree(cl);
-	} else {
-		if (dev->open_handle_count > 0)
-			dev->open_handle_count--;
-
-		if (dev->iamthif_file_object == file &&
-		    dev->iamthif_state != MEI_IAMTHIF_IDLE) {
-
-			dev_dbg(&dev->pdev->dev, "amthi canceled iamthif state %d\n",
-			    dev->iamthif_state);
-			dev->iamthif_canceled = true;
-			if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
-				dev_dbg(&dev->pdev->dev, "run next amthi iamthif cb\n");
-				mei_run_next_iamthif_cmd(dev);
-			}
-		}
+		cb = cl->read_cb;
+		cl->read_cb = NULL;
+	}
 
-		if (mei_clear_lists(dev, file))
-			dev->iamthif_state = MEI_IAMTHIF_IDLE;
+	file->private_data = NULL;
 
+	if (cb) {
+		mei_io_cb_free(cb);
+		cb = NULL;
 	}
+
+	kfree(cl);
+out:
 	mutex_unlock(&dev->device_lock);
 	return rets;
 }
@@ -411,20 +303,19 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 	}
 
 	if (cl == &dev->iamthif_cl) {
-		rets = amthi_read(dev, file, ubuf, length, offset);
+		rets = mei_amthif_read(dev, file, ubuf, length, offset);
 		goto out;
 	}
 
-	if (cl->read_cb && cl->read_cb->information > *offset) {
+	if (cl->read_cb && cl->read_cb->buf_idx > *offset) {
 		cb = cl->read_cb;
 		goto copy_buffer;
-	} else if (cl->read_cb && cl->read_cb->information > 0 &&
-		   cl->read_cb->information <= *offset) {
+	} else if (cl->read_cb && cl->read_cb->buf_idx > 0 &&
+		   cl->read_cb->buf_idx <= *offset) {
 		cb = cl->read_cb;
 		rets = 0;
 		goto free;
-	} else if ((!cl->read_cb || !cl->read_cb->information) &&
-		    *offset > 0) {
+	} else if ((!cl->read_cb || !cl->read_cb->buf_idx) && *offset > 0) {
 		/*Offset needs to be cleaned for contiguous reads*/
 		*offset = 0;
 		rets = 0;
@@ -481,16 +372,15 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 copy_buffer:
 	dev_dbg(&dev->pdev->dev, "cb->response_buffer size - %d\n",
 	    cb->response_buffer.size);
-	dev_dbg(&dev->pdev->dev, "cb->information - %lu\n",
-	    cb->information);
-	if (length == 0 || ubuf == NULL || *offset > cb->information) {
+	dev_dbg(&dev->pdev->dev, "cb->buf_idx - %lu\n", cb->buf_idx);
+	if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) {
 		rets = -EMSGSIZE;
 		goto free;
 	}
 
-	/* length is being truncated to PAGE_SIZE, however, */
-	/* information size may be longer */
-	length = min_t(size_t, length, (cb->information - *offset));
+	/* length is being truncated to PAGE_SIZE,
+	 * however buf_idx may point beyond that */
+	length = min_t(size_t, length, cb->buf_idx - *offset);
 
 	if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
 		rets = -EFAULT;
@@ -499,15 +389,15 @@ copy_buffer:
 
 	rets = length;
 	*offset += length;
-	if ((unsigned long)*offset < cb->information)
+	if ((unsigned long)*offset < cb->buf_idx)
 		goto out;
 
 free:
 	cb_pos = find_read_list_entry(dev, cl);
 	/* Remove entry from read list */
 	if (cb_pos)
-		list_del(&cb_pos->cb_list);
-	mei_free_cb_private(cb);
+		list_del(&cb_pos->list);
+	mei_io_cb_free(cb);
 	cl->reading_state = MEI_IDLE;
 	cl->read_cb = NULL;
 	cl->read_pending = 0;
@@ -516,7 +406,6 @@ out:
 	mutex_unlock(&dev->device_lock);
 	return rets;
 }
-
 /**
  * mei_write - the write function.
  *
@@ -546,23 +435,39 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 	mutex_lock(&dev->device_lock);
 
 	if (dev->dev_state != MEI_DEV_ENABLED) {
-		mutex_unlock(&dev->device_lock);
-		return -ENODEV;
+		rets = -ENODEV;
+		goto err;
 	}
 
+	i = mei_me_cl_by_id(dev, cl->me_client_id);
+	if (i < 0) {
+		rets = -ENODEV;
+		goto err;
+	}
+	if (length > dev->me_clients[i].props.max_msg_length || length <= 0) {
+		rets = -EMSGSIZE;
+		goto err;
+	}
+
+	if (cl->state != MEI_FILE_CONNECTED) {
+		rets = -ENODEV;
+		dev_err(&dev->pdev->dev, "host client = %d,  is not connected to ME client = %d",
+			cl->host_client_id, cl->me_client_id);
+		goto err;
+	}
 	if (cl == &dev->iamthif_cl) {
-		write_cb = find_amthi_read_list_entry(dev, file);
+		write_cb = mei_amthif_find_read_list_entry(dev, file);
 
 		if (write_cb) {
 			timeout = write_cb->read_time +
-					msecs_to_jiffies(IAMTHIF_READ_TIMER);
+				mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
 
 			if (time_after(jiffies, timeout) ||
-				 cl->reading_state == MEI_READ_COMPLETE) {
-					*offset = 0;
-					list_del(&write_cb->cb_list);
-					mei_free_cb_private(write_cb);
-					write_cb = NULL;
+			    cl->reading_state == MEI_READ_COMPLETE) {
+				*offset = 0;
+				list_del(&write_cb->list);
+				mei_io_cb_free(write_cb);
+				write_cb = NULL;
 			}
 		}
 	}
@@ -572,8 +477,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 		*offset = 0;
 		write_cb = find_read_list_entry(dev, cl);
 		if (write_cb) {
-			list_del(&write_cb->cb_list);
-			mei_free_cb_private(write_cb);
+			list_del(&write_cb->list);
+			mei_io_cb_free(write_cb);
 			write_cb = NULL;
 			cl->reading_state = MEI_IDLE;
 			cl->read_cb = NULL;
@@ -583,24 +488,21 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 		*offset = 0;
 
 
-	write_cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+	write_cb = mei_io_cb_init(cl, file);
 	if (!write_cb) {
-		mutex_unlock(&dev->device_lock);
-		return -ENOMEM;
+		dev_err(&dev->pdev->dev, "write cb allocation failed\n");
+		rets = -ENOMEM;
+		goto err;
 	}
+	rets = mei_io_cb_alloc_req_buf(write_cb, length);
+	if (rets)
+		goto err;
 
-	write_cb->file_object = file;
-	write_cb->file_private = cl;
-	write_cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
-	rets = -ENOMEM;
-	if (!write_cb->request_buffer.data)
-		goto unlock_dev;
-
-	dev_dbg(&dev->pdev->dev, "length =%d\n", (int) length);
+	dev_dbg(&dev->pdev->dev, "cb request size = %zd\n", length);
 
-	rets = -EFAULT;
-	if (copy_from_user(write_cb->request_buffer.data, ubuf, length))
-		goto unlock_dev;
+	rets = copy_from_user(write_cb->request_buffer.data, ubuf, length);
+	if (rets)
+		goto err;
 
 	cl->sm_state = 0;
 	if (length == 4 &&
@@ -612,139 +514,71 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 				 write_cb->request_buffer.data, 4) == 0)))
 		cl->sm_state |= MEI_WD_STATE_INDEPENDENCE_MSG_SENT;
 
-	INIT_LIST_HEAD(&write_cb->cb_list);
 	if (cl == &dev->iamthif_cl) {
-		write_cb->response_buffer.data =
-		    kmalloc(dev->iamthif_mtu, GFP_KERNEL);
-		if (!write_cb->response_buffer.data) {
-			rets = -ENOMEM;
-			goto unlock_dev;
-		}
-		if (dev->dev_state != MEI_DEV_ENABLED) {
-			rets = -ENODEV;
-			goto unlock_dev;
-		}
-		i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
-		if (i < 0) {
-			rets = -ENODEV;
-			goto unlock_dev;
-		}
-		if (length > dev->me_clients[i].props.max_msg_length ||
-			   length <= 0) {
-			rets = -EMSGSIZE;
-			goto unlock_dev;
-		}
+		rets = mei_amthif_write(dev, write_cb);
 
-		write_cb->response_buffer.size = dev->iamthif_mtu;
-		write_cb->major_file_operations = MEI_IOCTL;
-		write_cb->information = 0;
-		write_cb->request_buffer.size = length;
-		if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
-			rets = -ENODEV;
-			goto unlock_dev;
-		}
-
-		if (!list_empty(&dev->amthi_cmd_list.mei_cb.cb_list) ||
-				dev->iamthif_state != MEI_IAMTHIF_IDLE) {
-			dev_dbg(&dev->pdev->dev, "amthi_state = %d\n",
-					(int) dev->iamthif_state);
-			dev_dbg(&dev->pdev->dev, "add amthi cb to amthi cmd waiting list\n");
-			list_add_tail(&write_cb->cb_list,
-					&dev->amthi_cmd_list.mei_cb.cb_list);
-			rets = length;
-		} else {
-			dev_dbg(&dev->pdev->dev, "call amthi write\n");
-			rets = amthi_write(dev, write_cb);
-
-			if (rets) {
-				dev_dbg(&dev->pdev->dev, "amthi write failed with status = %d\n",
-				    rets);
-				goto unlock_dev;
-			}
-			rets = length;
+		if (rets) {
+			dev_err(&dev->pdev->dev,
+				"amthi write failed with status = %d\n", rets);
+			goto err;
 		}
 		mutex_unlock(&dev->device_lock);
-		return rets;
+		return length;
 	}
 
-	write_cb->major_file_operations = MEI_WRITE;
-	/* make sure information is zero before we start */
-
-	write_cb->information = 0;
-	write_cb->request_buffer.size = length;
+	write_cb->fop_type = MEI_FOP_WRITE;
 
 	dev_dbg(&dev->pdev->dev, "host client = %d, ME client = %d\n",
 	    cl->host_client_id, cl->me_client_id);
-	if (cl->state != MEI_FILE_CONNECTED) {
-		rets = -ENODEV;
-		dev_dbg(&dev->pdev->dev, "host client = %d,  is not connected to ME client = %d",
-		    cl->host_client_id,
-		    cl->me_client_id);
-		goto unlock_dev;
-	}
-	i = mei_me_cl_by_id(dev, cl->me_client_id);
-	if (i < 0) {
-		rets = -ENODEV;
-		goto unlock_dev;
-	}
-	if (length > dev->me_clients[i].props.max_msg_length || length <= 0) {
-		rets = -EINVAL;
-		goto unlock_dev;
-	}
-	write_cb->file_private = cl;
-
 	rets = mei_flow_ctrl_creds(dev, cl);
 	if (rets < 0)
-		goto unlock_dev;
+		goto err;
 
-	if (rets && dev->mei_host_buffer_is_empty) {
-		rets = 0;
-		dev->mei_host_buffer_is_empty = false;
-		if (length >  mei_hbuf_max_data(dev)) {
-			mei_hdr.length = mei_hbuf_max_data(dev);
-			mei_hdr.msg_complete = 0;
-		} else {
-			mei_hdr.length = length;
-			mei_hdr.msg_complete = 1;
-		}
-		mei_hdr.host_addr = cl->host_client_id;
-		mei_hdr.me_addr = cl->me_client_id;
-		mei_hdr.reserved = 0;
-		dev_dbg(&dev->pdev->dev, "call mei_write_message header=%08x.\n",
-		    *((u32 *) &mei_hdr));
-		if (mei_write_message(dev, &mei_hdr,
-			(unsigned char *) (write_cb->request_buffer.data),
-			mei_hdr.length)) {
-			rets = -ENODEV;
-			goto unlock_dev;
-		}
+	if (rets == 0 || dev->mei_host_buffer_is_empty == false) {
+		write_cb->buf_idx = 0;
+		mei_hdr.msg_complete = 0;
 		cl->writing_state = MEI_WRITING;
-		write_cb->information = mei_hdr.length;
-		if (mei_hdr.msg_complete) {
-			if (mei_flow_ctrl_reduce(dev, cl)) {
-				rets = -ENODEV;
-				goto unlock_dev;
-			}
-			list_add_tail(&write_cb->cb_list,
-				      &dev->write_waiting_list.mei_cb.cb_list);
-		} else {
-			list_add_tail(&write_cb->cb_list,
-				      &dev->write_list.mei_cb.cb_list);
-		}
+		goto out;
+	}
 
+	dev->mei_host_buffer_is_empty = false;
+	if (length >  mei_hbuf_max_data(dev)) {
+		mei_hdr.length = mei_hbuf_max_data(dev);
+		mei_hdr.msg_complete = 0;
 	} else {
+		mei_hdr.length = length;
+		mei_hdr.msg_complete = 1;
+	}
+	mei_hdr.host_addr = cl->host_client_id;
+	mei_hdr.me_addr = cl->me_client_id;
+	mei_hdr.reserved = 0;
+	dev_dbg(&dev->pdev->dev, "call mei_write_message header=%08x.\n",
+	    *((u32 *) &mei_hdr));
+	if (mei_write_message(dev, &mei_hdr,
+		write_cb->request_buffer.data, mei_hdr.length)) {
+		rets = -ENODEV;
+		goto err;
+	}
+	cl->writing_state = MEI_WRITING;
+	write_cb->buf_idx = mei_hdr.length;
 
-		write_cb->information = 0;
-		cl->writing_state = MEI_WRITING;
-		list_add_tail(&write_cb->cb_list,
-			      &dev->write_list.mei_cb.cb_list);
+out:
+	if (mei_hdr.msg_complete) {
+		if (mei_flow_ctrl_reduce(dev, cl)) {
+			rets = -ENODEV;
+			goto err;
+		}
+		list_add_tail(&write_cb->list, &dev->write_waiting_list.list);
+	} else {
+		list_add_tail(&write_cb->list, &dev->write_list.list);
 	}
+
 	mutex_unlock(&dev->device_lock);
 	return length;
 
-unlock_dev:
+err:
 	mutex_unlock(&dev->device_lock);
-	mei_free_cb_private(write_cb);
+	mei_io_cb_free(write_cb);
 	return rets;
 }
 
@@ -860,15 +694,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
 
 
 	if (cl == &dev->iamthif_cl) {
-		mutex_unlock(&dev->device_lock);
-		poll_wait(file, &dev->iamthif_cl.wait, wait);
-		mutex_lock(&dev->device_lock);
-		if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
-			dev->iamthif_file_object == file) {
-			mask |= (POLLIN | POLLRDNORM);
-			dev_dbg(&dev->pdev->dev, "run next amthi cb\n");
-			mei_run_next_iamthif_cmd(dev);
-		}
+		mask = mei_amthif_poll(dev, file, wait);
 		goto out;
 	}
 
@@ -917,7 +743,7 @@ static struct miscdevice  mei_misc_device = {
  *
  * returns true if ME Interface is valid, false otherwise
  */
-static bool __devinit mei_quirk_probe(struct pci_dev *pdev,
+static bool mei_quirk_probe(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
 {
 	u32 reg;
@@ -939,7 +765,7 @@ static bool __devinit mei_quirk_probe(struct pci_dev *pdev,
  *
  * returns 0 on success, <0 on failure.
  */
-static int __devinit mei_probe(struct pci_dev *pdev,
+static int mei_probe(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
 {
 	struct mei_device *dev;
@@ -1003,6 +829,8 @@ static int __devinit mei_probe(struct pci_dev *pdev,
 		goto disable_msi;
 	}
 	INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
+	INIT_WORK(&dev->init_work, mei_host_client_init);
+
 	if (mei_hw_init(dev)) {
 		dev_err(&pdev->dev, "init hw failure.\n");
 		err = -ENODEV;
@@ -1054,7 +882,7 @@ end:
  * mei_remove is called by the PCI subsystem to alert the driver
  * that it should release a PCI device.
  */
-static void __devexit mei_remove(struct pci_dev *pdev)
+static void mei_remove(struct pci_dev *pdev)
 {
 	struct mei_device *dev;
 
@@ -1087,8 +915,8 @@ static void __devexit mei_remove(struct pci_dev *pdev)
 
 	/* remove entry if already in list */
 	dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n");
-	mei_remove_client_from_file_list(dev, dev->wd_cl.host_client_id);
-	mei_remove_client_from_file_list(dev, dev->iamthif_cl.host_client_id);
+	mei_me_cl_unlink(dev, &dev->wd_cl);
+	mei_me_cl_unlink(dev, &dev->iamthif_cl);
 
 	dev->iamthif_current_cb = NULL;
 	dev->me_clients_num = 0;
@@ -1195,8 +1023,8 @@ static struct pci_driver mei_driver = {
 	.name = KBUILD_MODNAME,
 	.id_table = mei_pci_tbl,
 	.probe = mei_probe,
-	.remove = __devexit_p(mei_remove),
-	.shutdown = __devexit_p(mei_remove),
+	.remove = mei_remove,
+	.shutdown = mei_remove,
 	.driver.pm = MEI_PM_OPS,
 };
 
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index adb35fb..25da045 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -19,6 +19,7 @@
 
 #include <linux/types.h>
 #include <linux/watchdog.h>
+#include <linux/poll.h>
 #include <linux/mei.h>
 #include "hw.h"
 
@@ -125,13 +126,20 @@ enum mei_wd_states {
 	MEI_WD_STOPPING,
 };
 
-/* MEI CB */
-enum mei_cb_major_types {
-	MEI_READ = 0,
-	MEI_WRITE,
-	MEI_IOCTL,
-	MEI_OPEN,
-	MEI_CLOSE
+/**
+ * enum mei_cb_file_ops  - file operation associated with the callback
+ * @MEI_FOP_READ   - read
+ * @MEI_FOP_WRITE  - write
+ * @MEI_FOP_IOCTL  - ioctl
+ * @MEI_FOP_OPEN   - open
+ * @MEI_FOP_CLOSE  - close
+ */
+enum mei_cb_file_ops {
+	MEI_FOP_READ = 0,
+	MEI_FOP_WRITE,
+	MEI_FOP_IOCTL,
+	MEI_FOP_OPEN,
+	MEI_FOP_CLOSE
 };
 
 /*
@@ -143,13 +151,21 @@ struct mei_message_data {
 };
 
 
+struct mei_cl;
+
+/**
+ * struct mei_cl_cb - file operation callback structure
+ *
+ * @cl - file client who is running this operation
+ * @fop_type - file operation type
+ */
 struct mei_cl_cb {
-	struct list_head cb_list;
-	enum mei_cb_major_types major_file_operations;
-	void *file_private;
+	struct list_head list;
+	struct mei_cl *cl;
+	enum mei_cb_file_ops fop_type;
 	struct mei_message_data request_buffer;
 	struct mei_message_data response_buffer;
-	unsigned long information;
+	unsigned long buf_idx;
 	unsigned long read_time;
 	struct file *file_object;
 };
@@ -175,29 +191,23 @@ struct mei_cl {
 	struct mei_cl_cb *read_cb;
 };
 
-struct mei_io_list {
-	struct mei_cl_cb mei_cb;
-};
-
 /**
- * struct mei_deive -  MEI private device struct
+ * struct mei_device -  MEI private device struct
  * @hbuf_depth - depth of host(write) buffer
+ * @wr_ext_msg - buffer for hbm control responses (set in read cycle)
  */
 struct mei_device {
 	struct pci_dev *pdev;	/* pointer to pci device struct */
 	/*
 	 * lists of queues
 	 */
-	 /* array of pointers to aio lists */
-	struct mei_io_list read_list;		/* driver read queue */
-	struct mei_io_list write_list;		/* driver write queue */
-	struct mei_io_list write_waiting_list;	/* write waiting queue */
-	struct mei_io_list ctrl_wr_list;	/* managed write IOCTL list */
-	struct mei_io_list ctrl_rd_list;	/* managed read IOCTL list */
-	struct mei_io_list amthi_cmd_list;	/* amthi list for cmd waiting */
-
-	/* driver managed amthi list for reading completed amthi cmd data */
-	struct mei_io_list amthi_read_complete_list;
+	/* array of pointers to aio lists */
+	struct mei_cl_cb read_list;		/* driver read queue */
+	struct mei_cl_cb write_list;		/* driver write queue */
+	struct mei_cl_cb write_waiting_list;	/* write waiting queue */
+	struct mei_cl_cb ctrl_wr_list;		/* managed write IOCTL list */
+	struct mei_cl_cb ctrl_rd_list;		/* managed read IOCTL list */
+
 	/*
 	 * list of files
 	 */
@@ -235,11 +245,13 @@ struct mei_device {
 	u16 init_clients_timer;
 	bool need_reset;
 
-	u32 extra_write_index;
 	unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE];	/* control messages */
-	u32 wr_msg_buf[128];	/* used for control messages */
-	u32 ext_msg_buf[8];	/* for control responses */
 	u32 rd_msg_hdr;
+	u32 wr_msg_buf[128];	/* used for control messages */
+	struct {
+		struct mei_msg_hdr hdr;
+		unsigned char data[4];	/* All HBM messages are 4 bytes */
+	} wr_ext_msg;		/* for control responses */
 
 	struct hbm_version version;
 
@@ -253,12 +265,15 @@ struct mei_device {
 
 	struct mei_cl wd_cl;
 	enum mei_wd_states wd_state;
-	bool wd_interface_reg;
 	bool wd_pending;
 	u16 wd_timeout;
 	unsigned char wd_data[MEI_WD_START_MSG_SIZE];
 
 
+	/* amthif list for cmd waiting */
+	struct mei_cl_cb amthif_cmd_list;
+	/* driver managed amthif list for reading completed amthif cmd data */
+	struct mei_cl_cb amthif_rd_complete_list;
 	struct file *iamthif_file_object;
 	struct mei_cl iamthif_cl;
 	struct mei_cl_cb *iamthif_current_cb;
@@ -272,8 +287,15 @@ struct mei_device {
 	bool iamthif_flow_control_pending;
 	bool iamthif_ioctl;
 	bool iamthif_canceled;
+
+	struct work_struct init_work;
 };
 
+static inline unsigned long mei_secs_to_jiffies(unsigned long sec)
+{
+	return msecs_to_jiffies(sec * MSEC_PER_SEC);
+}
+
 
 /*
  * mei init function prototypes
@@ -284,21 +306,34 @@ int mei_hw_init(struct mei_device *dev);
 int mei_task_initialize_clients(void *data);
 int mei_initialize_clients(struct mei_device *dev);
 int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl);
-void mei_remove_client_from_file_list(struct mei_device *dev, u8 host_client_id);
-void mei_host_init_iamthif(struct mei_device *dev);
 void mei_allocate_me_clients_storage(struct mei_device *dev);
 
 
-int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl,
+int mei_me_cl_link(struct mei_device *dev, struct mei_cl *cl,
 			const uuid_le *cguid, u8 host_client_id);
+void mei_me_cl_unlink(struct mei_device *dev, struct mei_cl *cl);
 int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid);
 int mei_me_cl_by_id(struct mei_device *dev, u8 client_id);
 
 /*
- * MEI IO List Functions
+ * MEI IO Functions
+ */
+struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp);
+void mei_io_cb_free(struct mei_cl_cb *priv_cb);
+int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length);
+int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length);
+
+
+/**
+ * mei_io_list_init - Sets up a queue list.
+ *
+ * @list: An instance cl callback structure
  */
-void mei_io_list_init(struct mei_io_list *list);
-void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl);
+static inline void mei_io_list_init(struct mei_cl_cb *list)
+{
+	INIT_LIST_HEAD(&list->list);
+}
+void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl);
 
 /*
  * MEI ME Client Functions
@@ -330,7 +365,8 @@ static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
  */
 void mei_host_start_message(struct mei_device *dev);
 void mei_host_enum_clients_message(struct mei_device *dev);
-int mei_host_client_properties(struct mei_device *dev);
+int mei_host_client_enumerate(struct mei_device *dev);
+void mei_host_client_init(struct work_struct *work);
 
 /*
  *  MEI interrupt functions prototype
@@ -347,18 +383,40 @@ int mei_ioctl_connect_client(struct file *file,
 
 int mei_start_read(struct mei_device *dev, struct mei_cl *cl);
 
-int amthi_write(struct mei_device *dev, struct mei_cl_cb *priv_cb);
 
-int amthi_read(struct mei_device *dev, struct file *file,
-	      char __user *ubuf, size_t length, loff_t *offset);
+/*
+ * AMTHIF - AMT Host Interface Functions
+ */
+void mei_amthif_reset_params(struct mei_device *dev);
+
+void mei_amthif_host_init(struct mei_device *dev);
+
+int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *priv_cb);
 
-struct mei_cl_cb *find_amthi_read_list_entry(struct mei_device *dev,
+int mei_amthif_read(struct mei_device *dev, struct file *file,
+		char __user *ubuf, size_t length, loff_t *offset);
+
+unsigned int mei_amthif_poll(struct mei_device *dev,
+		struct file *file, poll_table *wait);
+
+int mei_amthif_release(struct mei_device *dev, struct file *file);
+
+struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
 						struct file *file);
 
-void mei_run_next_iamthif_cmd(struct mei_device *dev);
+void mei_amthif_run_next_cmd(struct mei_device *dev);
+
 
-void mei_free_cb_private(struct mei_cl_cb *priv_cb);
+int mei_amthif_read_message(struct mei_cl_cb *complete_list,
+		struct mei_device *dev, struct mei_msg_hdr *mei_hdr);
 
+int mei_amthif_irq_write_complete(struct mei_device *dev, s32 *slots,
+			struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list);
+
+void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb);
+int mei_amthif_irq_read_message(struct mei_cl_cb *complete_list,
+		struct mei_device *dev, struct mei_msg_hdr *mei_hdr);
+int mei_amthif_irq_read(struct mei_device *dev, s32 *slots);
 
 /*
  * Register Access Function
@@ -437,4 +495,15 @@ void mei_csr_clear_his(struct mei_device *dev);
 void mei_enable_interrupts(struct mei_device *dev);
 void mei_disable_interrupts(struct mei_device *dev);
 
+static inline struct mei_msg_hdr *mei_hbm_hdr(u32 *buf, size_t length)
+{
+	struct mei_msg_hdr *hdr = (struct mei_msg_hdr *)buf;
+	hdr->host_addr = 0;
+	hdr->me_addr = 0;
+	hdr->length = length;
+	hdr->msg_complete = 1;
+	hdr->reserved = 0;
+	return hdr;
+}
+
 #endif
diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c
index d96c537..636409f 100644
--- a/drivers/misc/mei/wd.c
+++ b/drivers/misc/mei/wd.c
@@ -62,6 +62,7 @@ static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
  */
 int mei_wd_host_init(struct mei_device *dev)
 {
+	int id;
 	mei_cl_init(&dev->wd_cl, dev);
 
 	/* look for WD client and connect to it */
@@ -69,12 +70,11 @@ int mei_wd_host_init(struct mei_device *dev)
 	dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT;
 	dev->wd_state = MEI_WD_IDLE;
 
-	/* find ME WD client */
-	mei_me_cl_update_filext(dev, &dev->wd_cl,
+	/* Connect WD ME client to the host client */
+	id = mei_me_cl_link(dev, &dev->wd_cl,
 				&mei_wd_guid, MEI_WD_HOST_CLIENT_ID);
 
-	dev_dbg(&dev->pdev->dev, "wd: check client\n");
-	if (MEI_FILE_CONNECTING != dev->wd_cl.state) {
+	if (id < 0) {
 		dev_info(&dev->pdev->dev, "wd: failed to find the client\n");
 		return -ENOENT;
 	}
@@ -85,7 +85,7 @@ int mei_wd_host_init(struct mei_device *dev)
 		dev->wd_cl.host_client_id = 0;
 		return -EIO;
 	}
-	dev->wd_cl.timer_count = CONNECT_TIMEOUT;
+	dev->wd_cl.timer_count = MEI_CONNECT_TIMEOUT;
 
 	return 0;
 }
@@ -360,23 +360,20 @@ void mei_watchdog_register(struct mei_device *dev)
 	if (watchdog_register_device(&amt_wd_dev)) {
 		dev_err(&dev->pdev->dev,
 			"wd: unable to register watchdog device.\n");
-		dev->wd_interface_reg = false;
 		return;
 	}
 
 	dev_dbg(&dev->pdev->dev,
 		"wd: successfully register watchdog interface.\n");
-	dev->wd_interface_reg = true;
 	watchdog_set_drvdata(&amt_wd_dev, dev);
 }
 
 void mei_watchdog_unregister(struct mei_device *dev)
 {
-	if (!dev->wd_interface_reg)
+	if (test_bit(WDOG_UNREGISTERED, &amt_wd_dev.status))
 		return;
 
 	watchdog_set_drvdata(&amt_wd_dev, NULL);
 	watchdog_unregister_device(&amt_wd_dev);
-	dev->wd_interface_reg = false;
 }
 
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
index c9f20da..931e635 100644
--- a/drivers/misc/pch_phub.c
+++ b/drivers/misc/pch_phub.c
@@ -666,7 +666,7 @@ static struct bin_attribute pch_bin_attr = {
 	.write = pch_phub_bin_write,
 };
 
-static int __devinit pch_phub_probe(struct pci_dev *pdev,
+static int pch_phub_probe(struct pci_dev *pdev,
 				    const struct pci_device_id *id)
 {
 	int retval;
@@ -819,7 +819,7 @@ err_pci_enable_dev:
 	return ret;
 }
 
-static void __devexit pch_phub_remove(struct pci_dev *pdev)
+static void pch_phub_remove(struct pci_dev *pdev)
 {
 	struct pch_phub_reg *chip = pci_get_drvdata(pdev);
 
@@ -888,7 +888,7 @@ static struct pci_driver pch_phub_driver = {
 	.name = "pch_phub",
 	.id_table = pch_phub_pcidev_id,
 	.probe = pch_phub_probe,
-	.remove = __devexit_p(pch_phub_remove),
+	.remove = pch_phub_remove,
 	.suspend = pch_phub_suspend,
 	.resume = pch_phub_resume
 };
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index 21b28fc..68b7c77 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -324,7 +324,7 @@ static irqreturn_t phantom_isr(int irq, void *data)
  * Init and deinit driver
  */
 
-static unsigned int __devinit phantom_get_free(void)
+static unsigned int phantom_get_free(void)
 {
 	unsigned int i;
 
@@ -335,7 +335,7 @@ static unsigned int __devinit phantom_get_free(void)
 	return i;
 }
 
-static int __devinit phantom_probe(struct pci_dev *pdev,
+static int phantom_probe(struct pci_dev *pdev,
 	const struct pci_device_id *pci_id)
 {
 	struct phantom_device *pht;
@@ -435,7 +435,7 @@ err:
 	return retval;
 }
 
-static void __devexit phantom_remove(struct pci_dev *pdev)
+static void phantom_remove(struct pci_dev *pdev)
 {
 	struct phantom_device *pht = pci_get_drvdata(pdev);
 	unsigned int minor = MINOR(pht->cdev.dev);
@@ -487,7 +487,7 @@ static int phantom_resume(struct pci_dev *pdev)
 #define phantom_resume	NULL
 #endif
 
-static struct pci_device_id phantom_pci_tbl[] __devinitdata = {
+static struct pci_device_id phantom_pci_tbl[] = {
 	{ .vendor = PCI_VENDOR_ID_PLX, .device = PCI_DEVICE_ID_PLX_9050,
 	  .subvendor = PCI_VENDOR_ID_PLX, .subdevice = PCI_DEVICE_ID_PLX_9050,
 	  .class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 },
@@ -499,7 +499,7 @@ static struct pci_driver phantom_pci_driver = {
 	.name = "phantom",
 	.id_table = phantom_pci_tbl,
 	.probe = phantom_probe,
-	.remove = __devexit_p(phantom_remove),
+	.remove = phantom_remove,
 	.suspend = phantom_suspend,
 	.resume = phantom_resume
 };
diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c
index 4999b34..f84ff0c 100644
--- a/drivers/misc/pti.c
+++ b/drivers/misc/pti.c
@@ -76,7 +76,7 @@ struct pti_dev {
  */
 static DEFINE_MUTEX(alloclock);
 
-static const struct pci_device_id pci_ids[] __devinitconst = {
+static const struct pci_device_id pci_ids[] = {
 		{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x82B)},
 		{0}
 };
@@ -796,7 +796,7 @@ static const struct tty_port_operations tty_port_ops = {
  *	0 for success
  *	otherwise, error
  */
-static int __devinit pti_pci_probe(struct pci_dev *pdev,
+static int pti_pci_probe(struct pci_dev *pdev,
 		const struct pci_device_id *ent)
 {
 	unsigned int a;
@@ -879,14 +879,17 @@ err:
  *		   PCI bus.
  * @pdev: variable containing pci info of PTI.
  */
-static void __devexit pti_pci_remove(struct pci_dev *pdev)
+static void pti_pci_remove(struct pci_dev *pdev)
 {
 	struct pti_dev *drv_data = pci_get_drvdata(pdev);
+	unsigned int a;
 
 	unregister_console(&pti_console);
 
-	tty_unregister_device(pti_tty_driver, 0);
-	tty_unregister_device(pti_tty_driver, 1);
+	for (a = 0; a < PTITTY_MINOR_NUM; a++) {
+		tty_unregister_device(pti_tty_driver, a);
+		tty_port_destroy(&drv_data->port[a]);
+	}
 
 	iounmap(drv_data->pti_ioaddr);
 	pci_set_drvdata(pdev, NULL);
@@ -901,7 +904,7 @@ static struct pci_driver pti_pci_driver = {
 	.name		= PCINAME,
 	.id_table	= pci_ids,
 	.probe		= pti_pci_probe,
-	.remove		= __devexit_p(pti_pci_remove),
+	.remove		= pti_pci_remove,
 };
 
 /**
diff --git a/drivers/misc/spear13xx_pcie_gadget.c b/drivers/misc/spear13xx_pcie_gadget.c
index 123ed98..7deb25d 100644
--- a/drivers/misc/spear13xx_pcie_gadget.c
+++ b/drivers/misc/spear13xx_pcie_gadget.c
@@ -711,7 +711,7 @@ static void spear13xx_pcie_device_init(struct spear_pcie_gadget_config *config)
 	spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1);
 }
 
-static int __devinit spear_pcie_gadget_probe(struct platform_device *pdev)
+static int spear_pcie_gadget_probe(struct platform_device *pdev)
 {
 	struct resource *res0, *res1;
 	unsigned int status = 0;
@@ -853,7 +853,7 @@ err_rel_res0:
 	return status;
 }
 
-static int __devexit spear_pcie_gadget_remove(struct platform_device *pdev)
+static int spear_pcie_gadget_remove(struct platform_device *pdev)
 {
 	struct resource *res0, *res1;
 	static struct pcie_gadget_target *target;
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
index 46937b1..b90a224 100644
--- a/drivers/misc/ti-st/st_core.c
+++ b/drivers/misc/ti-st/st_core.c
@@ -511,7 +511,6 @@ long st_register(struct st_proto_s *new_proto)
 	unsigned long flags = 0;
 
 	st_kim_ref(&st_gdata, 0);
-	pr_info("%s(%d) ", __func__, new_proto->chnl_id);
 	if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL
 	    || new_proto->reg_complete_cb == NULL) {
 		pr_err("gdata/new_proto/recv or reg_complete_cb not ready");
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 04a8199..9ff942a 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -705,9 +705,9 @@ static const struct file_operations list_debugfs_fops = {
 static struct dentry *kim_debugfs_dir;
 static int kim_probe(struct platform_device *pdev)
 {
-	long status;
 	struct kim_data_s	*kim_gdata;
 	struct ti_st_plat_data	*pdata = pdev->dev.platform_data;
+	int err;
 
 	if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) {
 		/* multiple devices could exist */
@@ -724,10 +724,11 @@ static int kim_probe(struct platform_device *pdev)
 	}
 	dev_set_drvdata(&pdev->dev, kim_gdata);
 
-	status = st_core_init(&kim_gdata->core_data);
-	if (status != 0) {
+	err = st_core_init(&kim_gdata->core_data);
+	if (err != 0) {
 		pr_err(" ST core init failed");
-		return -EIO;
+		err = -EIO;
+		goto err_core_init;
 	}
 	/* refer to itself */
 	kim_gdata->core_data->kim_data = kim_gdata;
@@ -738,10 +739,10 @@ static int kim_probe(struct platform_device *pdev)
 	init_completion(&kim_gdata->kim_rcvd);
 	init_completion(&kim_gdata->ldisc_installed);
 
-	status = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp);
-	if (status) {
+	err = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp);
+	if (err) {
 		pr_err("failed to create sysfs entries");
-		return status;
+		goto err_sysfs_group;
 	}
 
 	/* copying platform data */
@@ -753,8 +754,8 @@ static int kim_probe(struct platform_device *pdev)
 	kim_debugfs_dir = debugfs_create_dir("ti-st", NULL);
 	if (IS_ERR(kim_debugfs_dir)) {
 		pr_err(" debugfs entries creation failed ");
-		kim_debugfs_dir = NULL;
-		return -EIO;
+		err = -EIO;
+		goto err_debugfs_dir;
 	}
 
 	debugfs_create_file("version", S_IRUGO, kim_debugfs_dir,
@@ -763,6 +764,17 @@ static int kim_probe(struct platform_device *pdev)
 				kim_gdata, &list_debugfs_fops);
 	pr_info(" debugfs entries created ");
 	return 0;
+
+err_debugfs_dir:
+	sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
+
+err_sysfs_group:
+	st_core_exit(kim_gdata->core_data);
+
+err_core_init:
+	kfree(kim_gdata);
+
+	return err;
 }
 
 static int kim_remove(struct platform_device *pdev)
diff --git a/drivers/misc/ti_dac7512.c b/drivers/misc/ti_dac7512.c
index 5acbba1..1d86407 100644
--- a/drivers/misc/ti_dac7512.c
+++ b/drivers/misc/ti_dac7512.c
@@ -54,7 +54,7 @@ static const struct attribute_group dac7512_attr_group = {
 	.attrs = dac7512_attributes,
 };
 
-static int __devinit dac7512_probe(struct spi_device *spi)
+static int dac7512_probe(struct spi_device *spi)
 {
 	int ret;
 
@@ -67,7 +67,7 @@ static int __devinit dac7512_probe(struct spi_device *spi)
 	return sysfs_create_group(&spi->dev.kobj, &dac7512_attr_group);
 }
 
-static int __devexit dac7512_remove(struct spi_device *spi)
+static int dac7512_remove(struct spi_device *spi)
 {
 	sysfs_remove_group(&spi->dev.kobj, &dac7512_attr_group);
 	return 0;
@@ -79,7 +79,7 @@ static struct spi_driver dac7512_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe	= dac7512_probe,
-	.remove	= __devexit_p(dac7512_remove),
+	.remove	= dac7512_remove,
 };
 
 module_spi_driver(dac7512_driver);
diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c
index 0beb298..1e7bc0e 100644
--- a/drivers/misc/tsl2550.c
+++ b/drivers/misc/tsl2550.c
@@ -347,7 +347,7 @@ static int tsl2550_init_client(struct i2c_client *client)
  */
 
 static struct i2c_driver tsl2550_driver;
-static int __devinit tsl2550_probe(struct i2c_client *client,
+static int tsl2550_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@@ -405,7 +405,7 @@ exit:
 	return err;
 }
 
-static int __devexit tsl2550_remove(struct i2c_client *client)
+static int tsl2550_remove(struct i2c_client *client)
 {
 	sysfs_remove_group(&client->dev.kobj, &tsl2550_attr_group);
 
@@ -450,7 +450,7 @@ static struct i2c_driver tsl2550_driver = {
 	.suspend = tsl2550_suspend,
 	.resume	= tsl2550_resume,
 	.probe	= tsl2550_probe,
-	.remove	= __devexit_p(tsl2550_remove),
+	.remove	= tsl2550_remove,
 	.id_table = tsl2550_id,
 };
 
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 172a768..21056b9 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -57,6 +57,7 @@ MODULE_ALIAS("mmc:block");
 #define INAND_CMD38_ARG_SECERASE 0x80
 #define INAND_CMD38_ARG_SECTRIM1 0x81
 #define INAND_CMD38_ARG_SECTRIM2 0x88
+#define MMC_BLK_TIMEOUT_MS  (10 * 60 * 1000)        /* 10 minute timeout */
 
 static DEFINE_MUTEX(block_mutex);
 
@@ -126,6 +127,10 @@ enum mmc_blk_status {
 module_param(perdev_minors, int, 0444);
 MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
 
+static inline int mmc_blk_part_switch(struct mmc_card *card,
+				      struct mmc_blk_data *md);
+static int get_card_status(struct mmc_card *card, u32 *status, int retries);
+
 static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
 {
 	struct mmc_blk_data *md;
@@ -357,6 +362,38 @@ out:
 	return ERR_PTR(err);
 }
 
+static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
+				       u32 retries_max)
+{
+	int err;
+	u32 retry_count = 0;
+
+	if (!status || !retries_max)
+		return -EINVAL;
+
+	do {
+		err = get_card_status(card, status, 5);
+		if (err)
+			break;
+
+		if (!R1_STATUS(*status) &&
+				(R1_CURRENT_STATE(*status) != R1_STATE_PRG))
+			break; /* RPMB programming operation complete */
+
+		/*
+		 * Rechedule to give the MMC device a chance to continue
+		 * processing the previous command without being polled too
+		 * frequently.
+		 */
+		usleep_range(1000, 5000);
+	} while (++retry_count < retries_max);
+
+	if (retry_count == retries_max)
+		err = -EPERM;
+
+	return err;
+}
+
 static int mmc_blk_ioctl_cmd(struct block_device *bdev,
 	struct mmc_ioc_cmd __user *ic_ptr)
 {
@@ -368,6 +405,8 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
 	struct mmc_request mrq = {NULL};
 	struct scatterlist sg;
 	int err;
+	int is_rpmb = false;
+	u32 status = 0;
 
 	/*
 	 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
@@ -387,6 +426,9 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
 		goto cmd_err;
 	}
 
+	if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
+		is_rpmb = true;
+
 	card = md->queue.card;
 	if (IS_ERR(card)) {
 		err = PTR_ERR(card);
@@ -437,12 +479,23 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
 
 	mmc_claim_host(card->host);
 
+	err = mmc_blk_part_switch(card, md);
+	if (err)
+		goto cmd_rel_host;
+
 	if (idata->ic.is_acmd) {
 		err = mmc_app_cmd(card->host, card);
 		if (err)
 			goto cmd_rel_host;
 	}
 
+	if (is_rpmb) {
+		err = mmc_set_blockcount(card, data.blocks,
+			idata->ic.write_flag & (1 << 31));
+		if (err)
+			goto cmd_rel_host;
+	}
+
 	mmc_wait_for_req(card->host, &mrq);
 
 	if (cmd.error) {
@@ -478,6 +531,18 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
 		}
 	}
 
+	if (is_rpmb) {
+		/*
+		 * Ensure RPMB command has completed by polling CMD13
+		 * "Send Status".
+		 */
+		err = ioctl_rpmb_card_status_poll(card, &status, 5);
+		if (err)
+			dev_err(mmc_dev(card->host),
+					"%s: Card Status=0x%08X, error %d\n",
+					__func__, status, err);
+	}
+
 cmd_rel_host:
 	mmc_release_host(card->host);
 
@@ -1034,6 +1099,9 @@ static int mmc_blk_err_check(struct mmc_card *card,
 	 */
 	if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
 		u32 status;
+		unsigned long timeout;
+
+		timeout = jiffies + msecs_to_jiffies(MMC_BLK_TIMEOUT_MS);
 		do {
 			int err = get_card_status(card, &status, 5);
 			if (err) {
@@ -1041,6 +1109,17 @@ static int mmc_blk_err_check(struct mmc_card *card,
 				       req->rq_disk->disk_name, err);
 				return MMC_BLK_CMD_ERR;
 			}
+
+			/* Timeout if the device never becomes ready for data
+			 * and never leaves the program state.
+			 */
+			if (time_after(jiffies, timeout)) {
+				pr_err("%s: Card stuck in programming state!"\
+					" %s %s\n", mmc_hostname(card->host),
+					req->rq_disk->disk_name, __func__);
+
+				return MMC_BLK_CMD_ERR;
+			}
 			/*
 			 * Some cards mishandle the status bits,
 			 * so make sure to check both the busy
@@ -1504,6 +1583,8 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
 	md->disk->queue = md->queue.queue;
 	md->disk->driverfs_dev = parent;
 	set_disk_ro(md->disk, md->read_only || default_ro);
+	if (area_type & MMC_BLK_DATA_AREA_RPMB)
+		md->disk->flags |= GENHD_FL_NO_PART_SCAN;
 
 	/*
 	 * As discussed on lkml, GENHD_FL_REMOVABLE should:
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index e360a97..fadf52e 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -68,6 +68,16 @@ static int mmc_queue_thread(void *d)
 		if (req || mq->mqrq_prev->req) {
 			set_current_state(TASK_RUNNING);
 			mq->issue_fn(mq, req);
+
+			/*
+			 * Current request becomes previous request
+			 * and vice versa.
+			 */
+			mq->mqrq_prev->brq.mrq.data = NULL;
+			mq->mqrq_prev->req = NULL;
+			tmp = mq->mqrq_prev;
+			mq->mqrq_prev = mq->mqrq_cur;
+			mq->mqrq_cur = tmp;
 		} else {
 			if (kthread_should_stop()) {
 				set_current_state(TASK_RUNNING);
@@ -77,13 +87,6 @@ static int mmc_queue_thread(void *d)
 			schedule();
 			down(&mq->thread_sem);
 		}
-
-		/* Current request becomes previous request and vice versa. */
-		mq->mqrq_prev->brq.mrq.data = NULL;
-		mq->mqrq_prev->req = NULL;
-		tmp = mq->mqrq_prev;
-		mq->mqrq_prev = mq->mqrq_cur;
-		mq->mqrq_cur = tmp;
 	} while (1);
 	up(&mq->thread_sem);
 
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index d2339ea..bd57a11 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -66,8 +66,6 @@ struct uart_icount {
 
 struct sdio_uart_port {
 	struct tty_port		port;
-	struct kref		kref;
-	struct tty_struct	*tty;
 	unsigned int		index;
 	struct sdio_func	*func;
 	struct mutex		func_lock;
@@ -93,7 +91,6 @@ static int sdio_uart_add_port(struct sdio_uart_port *port)
 {
 	int index, ret = -EBUSY;
 
-	kref_init(&port->kref);
 	mutex_init(&port->func_lock);
 	spin_lock_init(&port->write_lock);
 	if (kfifo_alloc(&port->xmit_fifo, FIFO_SIZE, GFP_KERNEL))
@@ -123,23 +120,15 @@ static struct sdio_uart_port *sdio_uart_port_get(unsigned index)
 	spin_lock(&sdio_uart_table_lock);
 	port = sdio_uart_table[index];
 	if (port)
-		kref_get(&port->kref);
+		tty_port_get(&port->port);
 	spin_unlock(&sdio_uart_table_lock);
 
 	return port;
 }
 
-static void sdio_uart_port_destroy(struct kref *kref)
-{
-	struct sdio_uart_port *port =
-		container_of(kref, struct sdio_uart_port, kref);
-	kfifo_free(&port->xmit_fifo);
-	kfree(port);
-}
-
 static void sdio_uart_port_put(struct sdio_uart_port *port)
 {
-	kref_put(&port->kref, sdio_uart_port_destroy);
+	tty_port_put(&port->port);
 }
 
 static void sdio_uart_port_remove(struct sdio_uart_port *port)
@@ -737,6 +726,14 @@ static void sdio_uart_shutdown(struct tty_port *tport)
 	sdio_uart_release_func(port);
 }
 
+static void sdio_uart_port_destroy(struct tty_port *tport)
+{
+	struct sdio_uart_port *port =
+		container_of(tport, struct sdio_uart_port, port);
+	kfifo_free(&port->xmit_fifo);
+	kfree(port);
+}
+
 /**
  *	sdio_uart_install	-	install method
  *	@driver: the driver in use (sdio_uart in our case)
@@ -1045,6 +1042,7 @@ static const struct tty_port_operations sdio_uart_port_ops = {
 	.carrier_raised = uart_carrier_raised,
 	.shutdown = sdio_uart_shutdown,
 	.activate = sdio_uart_activate,
+	.destruct = sdio_uart_port_destroy,
 };
 
 static const struct tty_operations sdio_uart_ops = {
diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
index ef10387..269d072 100644
--- a/drivers/mmc/core/Kconfig
+++ b/drivers/mmc/core/Kconfig
@@ -18,8 +18,7 @@ config MMC_UNSAFE_RESUME
 	  module parameter "removable=0" or "removable=1".
 
 config MMC_CLKGATE
-	bool "MMC host clock gating (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	bool "MMC host clock gating"
 	help
 	  This will attempt to aggressively gate the clock to the MMC card.
 	  This is done to save power due to gating off the logic and bus
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 06c42cf..aaed768 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -42,6 +42,9 @@
 #include "sd_ops.h"
 #include "sdio_ops.h"
 
+/* If the device is not responding */
+#define MMC_CORE_TIMEOUT_MS	(10 * 60 * 1000) /* 10 minute timeout */
+
 /*
  * Background operations can take a long time, depending on the housekeeping
  * operations the card has to perform.
@@ -1631,6 +1634,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
 {
 	struct mmc_command cmd = {0};
 	unsigned int qty = 0;
+	unsigned long timeout;
 	int err;
 
 	/*
@@ -1708,6 +1712,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
 	if (mmc_host_is_spi(card->host))
 		goto out;
 
+	timeout = jiffies + msecs_to_jiffies(MMC_CORE_TIMEOUT_MS);
 	do {
 		memset(&cmd, 0, sizeof(struct mmc_command));
 		cmd.opcode = MMC_SEND_STATUS;
@@ -1721,8 +1726,19 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
 			err = -EIO;
 			goto out;
 		}
+
+		/* Timeout if the device never becomes ready for data and
+		 * never leaves the program state.
+		 */
+		if (time_after(jiffies, timeout)) {
+			pr_err("%s: Card stuck in programming state! %s\n",
+				mmc_hostname(card->host), __func__);
+			err =  -EIO;
+			goto out;
+		}
+
 	} while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
-		 R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG);
+		 (R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG));
 out:
 	return err;
 }
@@ -1942,6 +1958,20 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
 }
 EXPORT_SYMBOL(mmc_set_blocklen);
 
+int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount,
+			bool is_rel_write)
+{
+	struct mmc_command cmd = {0};
+
+	cmd.opcode = MMC_SET_BLOCK_COUNT;
+	cmd.arg = blockcount & 0x0000FFFF;
+	if (is_rel_write)
+		cmd.arg |= 1 << 31;
+	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
+	return mmc_wait_for_cmd(card->host, &cmd, 5);
+}
+EXPORT_SYMBOL(mmc_set_blockcount);
+
 static void mmc_hw_reset_for_init(struct mmc_host *host)
 {
 	if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index d96c643..35c2f85 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -144,6 +144,22 @@ static int mmc_ios_show(struct seq_file *s, void *data)
 	}
 	seq_printf(s, "timing spec:\t%u (%s)\n", ios->timing, str);
 
+	switch (ios->signal_voltage) {
+	case MMC_SIGNAL_VOLTAGE_330:
+		str = "3.30 V";
+		break;
+	case MMC_SIGNAL_VOLTAGE_180:
+		str = "1.80 V";
+		break;
+	case MMC_SIGNAL_VOLTAGE_120:
+		str = "1.20 V";
+		break;
+	default:
+		str = "invalid";
+		break;
+	}
+	seq_printf(s, "signal voltage:\t%u (%s)\n", ios->chip_select, str);
+
 	return 0;
 }
 
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 7cc4638..f605d6e 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -239,7 +239,7 @@ static void mmc_select_card_type(struct mmc_card *card)
 {
 	struct mmc_host *host = card->host;
 	u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
-	unsigned int caps = host->caps, caps2 = host->caps2;
+	u32 caps = host->caps, caps2 = host->caps2;
 	unsigned int hs_max_dtr = 0;
 
 	if (card_type & EXT_CSD_CARD_TYPE_26)
@@ -491,6 +491,17 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
 
 		card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM];
 		card->ext_csd.rst_n_function = ext_csd[EXT_CSD_RST_N_FUNCTION];
+
+		/*
+		 * RPMB regions are defined in multiples of 128K.
+		 */
+		card->ext_csd.raw_rpmb_size_mult = ext_csd[EXT_CSD_RPMB_MULT];
+		if (ext_csd[EXT_CSD_RPMB_MULT]) {
+			mmc_part_add(card, ext_csd[EXT_CSD_RPMB_MULT] << 17,
+				EXT_CSD_PART_CONFIG_ACC_RPMB,
+				"rpmb", 0, false,
+				MMC_BLK_DATA_AREA_RPMB);
+		}
 	}
 
 	card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT];
@@ -615,6 +626,8 @@ MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
 MMC_DEV_ATTR(enhanced_area_offset, "%llu\n",
 		card->ext_csd.enhanced_area_offset);
 MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size);
+MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult);
+MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors);
 
 static struct attribute *mmc_std_attrs[] = {
 	&dev_attr_cid.attr,
@@ -630,6 +643,8 @@ static struct attribute *mmc_std_attrs[] = {
 	&dev_attr_serial.attr,
 	&dev_attr_enhanced_area_offset.attr,
 	&dev_attr_enhanced_area_size.attr,
+	&dev_attr_raw_rpmb_size_mult.attr,
+	&dev_attr_rel_sectors.attr,
 	NULL,
 };
 
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index a0e1720..6d8f701 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -21,6 +21,8 @@
 #include "core.h"
 #include "mmc_ops.h"
 
+#define MMC_OPS_TIMEOUT_MS	(10 * 60 * 1000) /* 10 minute timeout */
+
 static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
 {
 	int err;
@@ -409,6 +411,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 {
 	int err;
 	struct mmc_command cmd = {0};
+	unsigned long timeout;
 	u32 status;
 
 	BUG_ON(!card);
@@ -437,6 +440,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 		return 0;
 
 	/* Must check status to be sure of no errors */
+	timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS);
 	do {
 		err = mmc_send_status(card, &status);
 		if (err)
@@ -445,6 +449,13 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 			break;
 		if (mmc_host_is_spi(card->host))
 			break;
+
+		/* Timeout if the device never leaves the program state. */
+		if (time_after(jiffies, timeout)) {
+			pr_err("%s: Card stuck in programming state! %s\n",
+				mmc_hostname(card->host), __func__);
+			return -ETIMEDOUT;
+		}
 	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
 
 	if (mmc_host_is_spi(card->host)) {
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index 8f6f5ac..78cb4d5 100644
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -188,8 +188,7 @@ EXPORT_SYMBOL_GPL(sdio_set_block_size);
  */
 static inline unsigned int sdio_max_byte_size(struct sdio_func *func)
 {
-	unsigned mval =	min(func->card->host->max_seg_size,
-			    func->card->host->max_blk_size);
+	unsigned mval =	func->card->host->max_blk_size;
 
 	if (mmc_blksz_for_byte_mode(func->card))
 		mval = min(mval, func->cur_blksize);
@@ -311,11 +310,8 @@ static int sdio_io_rw_ext_helper(struct sdio_func *func, int write,
 	/* Do the bulk of the transfer using block mode (if supported). */
 	if (func->card->cccr.multi_block && (size > sdio_max_byte_size(func))) {
 		/* Blocks per command is limited by host count, host transfer
-		 * size (we only use a single sg entry) and the maximum for
-		 * IO_RW_EXTENDED of 511 blocks. */
-		max_blocks = min(func->card->host->max_blk_count,
-			func->card->host->max_seg_size / func->cur_blksize);
-		max_blocks = min(max_blocks, 511u);
+		 * size and the maximum for IO_RW_EXTENDED of 511 blocks. */
+		max_blocks = min(func->card->host->max_blk_count, 511u);
 
 		while (remainder >= func->cur_blksize) {
 			unsigned blocks;
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
index d29e206..62508b4 100644
--- a/drivers/mmc/core/sdio_ops.c
+++ b/drivers/mmc/core/sdio_ops.c
@@ -124,7 +124,10 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
 	struct mmc_request mrq = {NULL};
 	struct mmc_command cmd = {0};
 	struct mmc_data data = {0};
-	struct scatterlist sg;
+	struct scatterlist sg, *sg_ptr;
+	struct sg_table sgtable;
+	unsigned int nents, left_size, i;
+	unsigned int seg_size = card->host->max_seg_size;
 
 	BUG_ON(!card);
 	BUG_ON(fn > 7);
@@ -152,15 +155,36 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
 	/* Code in host drivers/fwk assumes that "blocks" always is >=1 */
 	data.blocks = blocks ? blocks : 1;
 	data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
-	data.sg = &sg;
-	data.sg_len = 1;
 
-	sg_init_one(&sg, buf, data.blksz * data.blocks);
+	left_size = data.blksz * data.blocks;
+	nents = (left_size - 1) / seg_size + 1;
+	if (nents > 1) {
+		if (sg_alloc_table(&sgtable, nents, GFP_KERNEL))
+			return -ENOMEM;
+
+		data.sg = sgtable.sgl;
+		data.sg_len = nents;
+
+		for_each_sg(data.sg, sg_ptr, data.sg_len, i) {
+			sg_set_page(sg_ptr, virt_to_page(buf + (i * seg_size)),
+					min(seg_size, left_size),
+					offset_in_page(buf + (i * seg_size)));
+			left_size = left_size - seg_size;
+		}
+	} else {
+		data.sg = &sg;
+		data.sg_len = 1;
+
+		sg_init_one(&sg, buf, left_size);
+	}
 
 	mmc_set_data_timeout(&data, card);
 
 	mmc_wait_for_req(card->host, &mrq);
 
+	if (nents > 1)
+		sg_free_table(&sgtable);
+
 	if (cmd.error)
 		return cmd.error;
 	if (data.error)
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 9bf10e7..84f4f77 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -69,7 +69,7 @@ config MMC_SDHCI_PCI
 	  If unsure, say N.
 
 config MMC_RICOH_MMC
-	bool "Ricoh MMC Controller Disabler  (EXPERIMENTAL)"
+	bool "Ricoh MMC Controller Disabler"
 	depends on MMC_SDHCI_PCI
 	help
 	  This adds a pci quirk to disable Ricoh MMC Controller. This
@@ -81,6 +81,18 @@ config MMC_RICOH_MMC
 
 	  If unsure, say Y.
 
+config MMC_SDHCI_ACPI
+	tristate "SDHCI support for ACPI enumerated SDHCI controllers"
+	depends on MMC_SDHCI && ACPI
+	help
+	  This selects support for ACPI enumerated SDHCI controllers,
+	  identified by ACPI Compatibility ID PNP0D40 or specific
+	  ACPI Hardware IDs.
+
+	  If you have a controller with this interface, say Y or M here.
+
+	  If unsure, say N.
+
 config MMC_SDHCI_PLTFM
 	tristate "SDHCI platform and OF driver helper"
 	depends on MMC_SDHCI
@@ -174,9 +186,6 @@ config MMC_SDHCI_S3C
 	  often referrered to as the HSMMC block in some of the Samsung S3C
 	  range of SoC.
 
-	  Note, due to the problems with DMA, the DMA support is only
-	  available with CONFIG_EXPERIMENTAL is selected.
-
 	  If you have a controller with this interface, say Y or M here.
 
 	  If unsure, say N.
@@ -221,7 +230,7 @@ config MMC_SDHCI_SPEAR
 
 config MMC_SDHCI_S3C_DMA
 	bool "DMA support on S3C SDHCI"
-	depends on MMC_SDHCI_S3C && EXPERIMENTAL
+	depends on MMC_SDHCI_S3C
 	help
 	  Enable DMA support on the Samsung S3C SDHCI glue. The DMA
 	  has proved to be problematic if the controller encounters
@@ -270,26 +279,8 @@ config MMC_AU1X
 
 	  If unsure, say N.
 
-choice
-	prompt "Atmel SD/MMC Driver"
-	depends on AVR32 || ARCH_AT91
-	default MMC_ATMELMCI if AVR32
-	help
-	  Choose which driver to use for the Atmel MCI Silicon
-
-config MMC_AT91
-	tristate "AT91 SD/MMC Card Interface support (DEPRECATED)"
-	depends on ARCH_AT91
-	help
-	  This selects the AT91 MCI controller. This driver will
-	  be removed soon (for more information have a look to
-	  Documentation/feature-removal-schedule.txt). Please use
-	  MMC_ATMEL_MCI.
-
-	  If unsure, say N.
-
 config MMC_ATMELMCI
-	tristate "Atmel Multimedia Card Interface support"
+	tristate "Atmel SD/MMC Driver (Multimedia Card Interface)"
 	depends on AVR32 || ARCH_AT91
 	help
 	  This selects the Atmel Multimedia Card Interface driver. If
@@ -298,8 +289,6 @@ config MMC_ATMELMCI
 
 	  If unsure, say N.
 
-endchoice
-
 config MMC_ATMELMCI_DMA
 	bool "Atmel MCI DMA support"
 	depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE
@@ -338,8 +327,8 @@ config MMC_MXS
 	  If unsure, say N.
 
 config MMC_TIFM_SD
-	tristate "TI Flash Media MMC/SD Interface support  (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && PCI
+	tristate "TI Flash Media MMC/SD Interface support"
+	depends on PCI
 	select TIFM_CORE
 	help
 	  Say Y here if you want to be able to access MMC/SD cards with
@@ -418,8 +407,7 @@ config MMC_S3C_PIO
 	  the S3C MCI driver.
 
 config MMC_S3C_DMA
-	bool "Use DMA transfers only (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	bool "Use DMA transfers only"
 	help
 	  Use DMA to transfer data between memory and the hardare.
 
@@ -428,7 +416,7 @@ config MMC_S3C_DMA
 	  option is useful.
 
 config MMC_S3C_PIODMA
-	bool "Support for both PIO and DMA (EXPERIMENTAL)"
+	bool "Support for both PIO and DMA"
 	help
 	  Compile both the PIO and DMA transfer routines into the
 	  driver and let the platform select at run-time which one
@@ -439,8 +427,8 @@ config MMC_S3C_PIODMA
 endchoice
 
 config MMC_SDRICOH_CS
-	tristate "MMC/SD driver for Ricoh Bay1Controllers (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && PCI && PCMCIA
+	tristate "MMC/SD driver for Ricoh Bay1Controllers"
+	depends on PCI && PCMCIA
 	help
 	  Say Y here if your Notebook reports a Ricoh Bay1Controller PCMCIA
 	  card whenever you insert a MMC or SD card into the card slot.
@@ -621,3 +609,22 @@ config MMC_USHC
 
 	  Note: These controllers only support SDIO cards and do not
 	  support MMC or SD memory cards.
+
+config MMC_WMT
+	tristate "Wondermedia SD/MMC Host Controller support"
+	depends on ARCH_VT8500
+	default y
+	help
+	  This selects support for the SD/MMC Host Controller on
+	  Wondermedia WM8505/WM8650 based SoCs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called wmt-sdmmc.
+
+
+config MMC_REALTEK_PCI
+	tristate "Realtek PCI-E SD/MMC Card Interface Driver"
+	depends on MFD_RTSX_PCI
+	help
+	  Say Y here to include driver code to support SD/MMC card interface
+	  of Realtek PCI-E card reader
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 17ad0a7..e4e218c 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_MMC_MXS)		+= mxs-mmc.o
 obj-$(CONFIG_MMC_SDHCI)		+= sdhci.o
 obj-$(CONFIG_MMC_SDHCI_PCI)	+= sdhci-pci.o
 obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI))	+= sdhci-pci-data.o
+obj-$(CONFIG_MMC_SDHCI_ACPI)	+= sdhci-acpi.o
 obj-$(CONFIG_MMC_SDHCI_PXAV3)	+= sdhci-pxav3.o
 obj-$(CONFIG_MMC_SDHCI_PXAV2)	+= sdhci-pxav2.o
 obj-$(CONFIG_MMC_SDHCI_S3C)	+= sdhci-s3c.o
@@ -17,7 +18,6 @@ obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
 obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o
 obj-$(CONFIG_MMC_OMAP)		+= omap.o
 obj-$(CONFIG_MMC_OMAP_HS)	+= omap_hsmmc.o
-obj-$(CONFIG_MMC_AT91)		+= at91_mci.o
 obj-$(CONFIG_MMC_ATMELMCI)	+= atmel-mci.o
 obj-$(CONFIG_MMC_TIFM_SD)	+= tifm_sd.o
 obj-$(CONFIG_MMC_MSM)		+= msm_sdcc.o
@@ -45,6 +45,11 @@ obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
 obj-$(CONFIG_MMC_VUB300)	+= vub300.o
 obj-$(CONFIG_MMC_USHC)		+= ushc.o
+obj-$(CONFIG_MMC_WMT)		+= wmt-sdmmc.o
+
+obj-$(CONFIG_MMC_REALTEK_PCI)	+= rtsx_pci_sdmmc.o
+
+obj-$(CONFIG_MMC_REALTEK_PCI)	+= rtsx_pci_sdmmc.o
 
 obj-$(CONFIG_MMC_SDHCI_PLTFM)		+= sdhci-pltfm.o
 obj-$(CONFIG_MMC_SDHCI_CNS3XXX)		+= sdhci-cns3xxx.o
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
deleted file mode 100644
index 74bed0f..0000000
--- a/drivers/mmc/host/at91_mci.c
+++ /dev/null
@@ -1,1219 +0,0 @@
-/*
- *  linux/drivers/mmc/host/at91_mci.c - ATMEL AT91 MCI Driver
- *
- *  Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
- *
- *  Copyright (C) 2006 Malcolm Noyes
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/*
-   This is the AT91 MCI driver that has been tested with both MMC cards
-   and SD-cards.  Boards that support write protect are now supported.
-   The CCAT91SBC001 board does not support SD cards.
-
-   The three entry points are at91_mci_request, at91_mci_set_ios
-   and at91_mci_get_ro.
-
-   SET IOS
-     This configures the device to put it into the correct mode and clock speed
-     required.
-
-   MCI REQUEST
-     MCI request processes the commands sent in the mmc_request structure. This
-     can consist of a processing command and a stop command in the case of
-     multiple block transfers.
-
-     There are three main types of request, commands, reads and writes.
-
-     Commands are straight forward. The command is submitted to the controller and
-     the request function returns. When the controller generates an interrupt to indicate
-     the command is finished, the response to the command are read and the mmc_request_done
-     function called to end the request.
-
-     Reads and writes work in a similar manner to normal commands but involve the PDC (DMA)
-     controller to manage the transfers.
-
-     A read is done from the controller directly to the scatterlist passed in from the request.
-     Due to a bug in the AT91RM9200 controller, when a read is completed, all the words are byte
-     swapped in the scatterlist buffers.  AT91SAM926x are not affected by this bug.
-
-     The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY
-
-     A write is slightly different in that the bytes to write are read from the scatterlist
-     into a dma memory buffer (this is in case the source buffer should be read only). The
-     entire write buffer is then done from this single dma memory buffer.
-
-     The sequence of write interrupts is: ENDTX, TXBUFE, NOTBUSY, CMDRDY
-
-   GET RO
-     Gets the status of the write protect pin, if available.
-*/
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk.h>
-#include <linux/atmel_pdc.h>
-#include <linux/gfp.h>
-#include <linux/highmem.h>
-
-#include <linux/mmc/host.h>
-#include <linux/mmc/sdio.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/gpio.h>
-
-#include <mach/board.h>
-#include <mach/cpu.h>
-
-#include "at91_mci.h"
-
-#define DRIVER_NAME "at91_mci"
-
-static inline int at91mci_is_mci1rev2xx(void)
-{
-	return (   cpu_is_at91sam9260()
-		|| cpu_is_at91sam9263()
-		|| cpu_is_at91sam9rl()
-		|| cpu_is_at91sam9g10()
-		|| cpu_is_at91sam9g20()
-		);
-}
-
-#define FL_SENT_COMMAND	(1 << 0)
-#define FL_SENT_STOP	(1 << 1)
-
-#define AT91_MCI_ERRORS	(AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE	\
-		| AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE		\
-		| AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)
-
-#define at91_mci_read(host, reg)	__raw_readl((host)->baseaddr + (reg))
-#define at91_mci_write(host, reg, val)	__raw_writel((val), (host)->baseaddr + (reg))
-
-#define MCI_BLKSIZE 		512
-#define MCI_MAXBLKSIZE 		4095
-#define MCI_BLKATONCE 		256
-#define MCI_BUFSIZE 		(MCI_BLKSIZE * MCI_BLKATONCE)
-
-/*
- * Low level type for this driver
- */
-struct at91mci_host
-{
-	struct mmc_host *mmc;
-	struct mmc_command *cmd;
-	struct mmc_request *request;
-
-	void __iomem *baseaddr;
-	int irq;
-
-	struct at91_mmc_data *board;
-	int present;
-
-	struct clk *mci_clk;
-
-	/*
-	 * Flag indicating when the command has been sent. This is used to
-	 * work out whether or not to send the stop
-	 */
-	unsigned int flags;
-	/* flag for current bus settings */
-	u32 bus_mode;
-
-	/* DMA buffer used for transmitting */
-	unsigned int* buffer;
-	dma_addr_t physical_address;
-	unsigned int total_length;
-
-	/* Latest in the scatterlist that has been enabled for transfer, but not freed */
-	int in_use_index;
-
-	/* Latest in the scatterlist that has been enabled for transfer */
-	int transfer_index;
-
-	/* Timer for timeouts */
-	struct timer_list timer;
-};
-
-/*
- * Reset the controller and restore most of the state
- */
-static void at91_reset_host(struct at91mci_host *host)
-{
-	unsigned long flags;
-	u32 mr;
-	u32 sdcr;
-	u32 dtor;
-	u32 imr;
-
-	local_irq_save(flags);
-	imr = at91_mci_read(host, AT91_MCI_IMR);
-
-	at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
-
-	/* save current state */
-	mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
-	sdcr = at91_mci_read(host, AT91_MCI_SDCR);
-	dtor = at91_mci_read(host, AT91_MCI_DTOR);
-
-	/* reset the controller */
-	at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
-
-	/* restore state */
-	at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
-	at91_mci_write(host, AT91_MCI_MR, mr);
-	at91_mci_write(host, AT91_MCI_SDCR, sdcr);
-	at91_mci_write(host, AT91_MCI_DTOR, dtor);
-	at91_mci_write(host, AT91_MCI_IER, imr);
-
-	/* make sure sdio interrupts will fire */
-	at91_mci_read(host, AT91_MCI_SR);
-
-	local_irq_restore(flags);
-}
-
-static void at91_timeout_timer(unsigned long data)
-{
-	struct at91mci_host *host;
-
-	host = (struct at91mci_host *)data;
-
-	if (host->request) {
-		dev_err(host->mmc->parent, "Timeout waiting end of packet\n");
-
-		if (host->cmd && host->cmd->data) {
-			host->cmd->data->error = -ETIMEDOUT;
-		} else {
-			if (host->cmd)
-				host->cmd->error = -ETIMEDOUT;
-			else
-				host->request->cmd->error = -ETIMEDOUT;
-		}
-
-		at91_reset_host(host);
-		mmc_request_done(host->mmc, host->request);
-	}
-}
-
-/*
- * Copy from sg to a dma block - used for transfers
- */
-static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
-{
-	unsigned int len, i, size;
-	unsigned *dmabuf = host->buffer;
-
-	size = data->blksz * data->blocks;
-	len = data->sg_len;
-
-	/* MCI1 rev2xx Data Write Operation and number of bytes erratum */
-	if (at91mci_is_mci1rev2xx())
-		if (host->total_length == 12)
-			memset(dmabuf, 0, 12);
-
-	/*
-	 * Just loop through all entries. Size might not
-	 * be the entire list though so make sure that
-	 * we do not transfer too much.
-	 */
-	for (i = 0; i < len; i++) {
-		struct scatterlist *sg;
-		int amount;
-		unsigned int *sgbuffer;
-
-		sg = &data->sg[i];
-
-		sgbuffer = kmap_atomic(sg_page(sg)) + sg->offset;
-		amount = min(size, sg->length);
-		size -= amount;
-
-		if (cpu_is_at91rm9200()) {	/* AT91RM9200 errata */
-			int index;
-
-			for (index = 0; index < (amount / 4); index++)
-				*dmabuf++ = swab32(sgbuffer[index]);
-		} else {
-			char *tmpv = (char *)dmabuf;
-			memcpy(tmpv, sgbuffer, amount);
-			tmpv += amount;
-			dmabuf = (unsigned *)tmpv;
-		}
-
-		kunmap_atomic(sgbuffer);
-
-		if (size == 0)
-			break;
-	}
-
-	/*
-	 * Check that we didn't get a request to transfer
-	 * more data than can fit into the SG list.
-	 */
-	BUG_ON(size != 0);
-}
-
-/*
- * Handle after a dma read
- */
-static void at91_mci_post_dma_read(struct at91mci_host *host)
-{
-	struct mmc_command *cmd;
-	struct mmc_data *data;
-	unsigned int len, i, size;
-	unsigned *dmabuf = host->buffer;
-
-	pr_debug("post dma read\n");
-
-	cmd = host->cmd;
-	if (!cmd) {
-		pr_debug("no command\n");
-		return;
-	}
-
-	data = cmd->data;
-	if (!data) {
-		pr_debug("no data\n");
-		return;
-	}
-
-	size = data->blksz * data->blocks;
-	len = data->sg_len;
-
-	at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
-	at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
-
-	for (i = 0; i < len; i++) {
-		struct scatterlist *sg;
-		int amount;
-		unsigned int *sgbuffer;
-
-		sg = &data->sg[i];
-
-		sgbuffer = kmap_atomic(sg_page(sg)) + sg->offset;
-		amount = min(size, sg->length);
-		size -= amount;
-
-		if (cpu_is_at91rm9200()) {	/* AT91RM9200 errata */
-			int index;
-			for (index = 0; index < (amount / 4); index++)
-				sgbuffer[index] = swab32(*dmabuf++);
-		} else {
-			char *tmpv = (char *)dmabuf;
-			memcpy(sgbuffer, tmpv, amount);
-			tmpv += amount;
-			dmabuf = (unsigned *)tmpv;
-		}
-
-		flush_kernel_dcache_page(sg_page(sg));
-		kunmap_atomic(sgbuffer);
-		data->bytes_xfered += amount;
-		if (size == 0)
-			break;
-	}
-
-	pr_debug("post dma read done\n");
-}
-
-/*
- * Handle transmitted data
- */
-static void at91_mci_handle_transmitted(struct at91mci_host *host)
-{
-	struct mmc_command *cmd;
-	struct mmc_data *data;
-
-	pr_debug("Handling the transmit\n");
-
-	/* Disable the transfer */
-	at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
-
-	/* Now wait for cmd ready */
-	at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
-
-	cmd = host->cmd;
-	if (!cmd) return;
-
-	data = cmd->data;
-	if (!data) return;
-
-	if (cmd->data->blocks > 1) {
-		pr_debug("multiple write : wait for BLKE...\n");
-		at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
-	} else
-		at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
-}
-
-/*
- * Update bytes transfered count during a write operation
- */
-static void at91_mci_update_bytes_xfered(struct at91mci_host *host)
-{
-	struct mmc_data *data;
-
-	/* always deal with the effective request (and not the current cmd) */
-
-	if (host->request->cmd && host->request->cmd->error != 0)
-		return;
-
-	if (host->request->data) {
-		data = host->request->data;
-		if (data->flags & MMC_DATA_WRITE) {
-			/* card is in IDLE mode now */
-			pr_debug("-> bytes_xfered %d, total_length = %d\n",
-				data->bytes_xfered, host->total_length);
-			data->bytes_xfered = data->blksz * data->blocks;
-		}
-	}
-}
-
-
-/*Handle after command sent ready*/
-static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
-{
-	if (!host->cmd)
-		return 1;
-	else if (!host->cmd->data) {
-		if (host->flags & FL_SENT_STOP) {
-			/*After multi block write, we must wait for NOTBUSY*/
-			at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
-		} else return 1;
-	} else if (host->cmd->data->flags & MMC_DATA_WRITE) {
-		/*After sendding multi-block-write command, start DMA transfer*/
-		at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE | AT91_MCI_BLKE);
-		at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
-	}
-
-	/* command not completed, have to wait */
-	return 0;
-}
-
-
-/*
- * Enable the controller
- */
-static void at91_mci_enable(struct at91mci_host *host)
-{
-	unsigned int mr;
-
-	at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
-	at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
-	at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
-	mr = AT91_MCI_PDCMODE | 0x34a;
-
-	if (at91mci_is_mci1rev2xx())
-		mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
-
-	at91_mci_write(host, AT91_MCI_MR, mr);
-
-	/* use Slot A or B (only one at same time) */
-	at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
-}
-
-/*
- * Disable the controller
- */
-static void at91_mci_disable(struct at91mci_host *host)
-{
-	at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
-}
-
-/*
- * Send a command
- */
-static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
-{
-	unsigned int cmdr, mr;
-	unsigned int block_length;
-	struct mmc_data *data = cmd->data;
-
-	unsigned int blocks;
-	unsigned int ier = 0;
-
-	host->cmd = cmd;
-
-	/* Needed for leaving busy state before CMD1 */
-	if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
-		pr_debug("Clearing timeout\n");
-		at91_mci_write(host, AT91_MCI_ARGR, 0);
-		at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
-		while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
-			/* spin */
-			pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
-		}
-	}
-
-	cmdr = cmd->opcode;
-
-	if (mmc_resp_type(cmd) == MMC_RSP_NONE)
-		cmdr |= AT91_MCI_RSPTYP_NONE;
-	else {
-		/* if a response is expected then allow maximum response latancy */
-		cmdr |= AT91_MCI_MAXLAT;
-		/* set 136 bit response for R2, 48 bit response otherwise */
-		if (mmc_resp_type(cmd) == MMC_RSP_R2)
-			cmdr |= AT91_MCI_RSPTYP_136;
-		else
-			cmdr |= AT91_MCI_RSPTYP_48;
-	}
-
-	if (data) {
-
-		if (cpu_is_at91rm9200() || cpu_is_at91sam9261()) {
-			if (data->blksz & 0x3) {
-				pr_debug("Unsupported block size\n");
-				cmd->error = -EINVAL;
-				mmc_request_done(host->mmc, host->request);
-				return;
-			}
-			if (data->flags & MMC_DATA_STREAM) {
-				pr_debug("Stream commands not supported\n");
-				cmd->error = -EINVAL;
-				mmc_request_done(host->mmc, host->request);
-				return;
-			}
-		}
-
-		block_length = data->blksz;
-		blocks = data->blocks;
-
-		/* always set data start - also set direction flag for read */
-		if (data->flags & MMC_DATA_READ)
-			cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
-		else if (data->flags & MMC_DATA_WRITE)
-			cmdr |= AT91_MCI_TRCMD_START;
-
-		if (cmd->opcode == SD_IO_RW_EXTENDED) {
-			cmdr |= AT91_MCI_TRTYP_SDIO_BLOCK;
-		} else {
-			if (data->flags & MMC_DATA_STREAM)
-				cmdr |= AT91_MCI_TRTYP_STREAM;
-			if (data->blocks > 1)
-				cmdr |= AT91_MCI_TRTYP_MULTIPLE;
-		}
-	}
-	else {
-		block_length = 0;
-		blocks = 0;
-	}
-
-	if (host->flags & FL_SENT_STOP)
-		cmdr |= AT91_MCI_TRCMD_STOP;
-
-	if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
-		cmdr |= AT91_MCI_OPDCMD;
-
-	/*
-	 * Set the arguments and send the command
-	 */
-	pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
-		cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
-
-	if (!data) {
-		at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
-		at91_mci_write(host, ATMEL_PDC_RPR, 0);
-		at91_mci_write(host, ATMEL_PDC_RCR, 0);
-		at91_mci_write(host, ATMEL_PDC_RNPR, 0);
-		at91_mci_write(host, ATMEL_PDC_RNCR, 0);
-		at91_mci_write(host, ATMEL_PDC_TPR, 0);
-		at91_mci_write(host, ATMEL_PDC_TCR, 0);
-		at91_mci_write(host, ATMEL_PDC_TNPR, 0);
-		at91_mci_write(host, ATMEL_PDC_TNCR, 0);
-		ier = AT91_MCI_CMDRDY;
-	} else {
-		/* zero block length and PDC mode */
-		mr = at91_mci_read(host, AT91_MCI_MR) & 0x5fff;
-		mr |= (data->blksz & 0x3) ? AT91_MCI_PDCFBYTE : 0;
-		mr |= (block_length << 16);
-		mr |= AT91_MCI_PDCMODE;
-		at91_mci_write(host, AT91_MCI_MR, mr);
-
-		if (!(cpu_is_at91rm9200() || cpu_is_at91sam9261()))
-			at91_mci_write(host, AT91_MCI_BLKR,
-				AT91_MCI_BLKR_BCNT(blocks) |
-				AT91_MCI_BLKR_BLKLEN(block_length));
-
-		/*
-		 * Disable the PDC controller
-		 */
-		at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
-
-		if (cmdr & AT91_MCI_TRCMD_START) {
-			data->bytes_xfered = 0;
-			host->transfer_index = 0;
-			host->in_use_index = 0;
-			if (cmdr & AT91_MCI_TRDIR) {
-				/*
-				 * Handle a read
-				 */
-				host->total_length = 0;
-
-				at91_mci_write(host, ATMEL_PDC_RPR, host->physical_address);
-				at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ?
-					(blocks * block_length) : (blocks * block_length) / 4);
-				at91_mci_write(host, ATMEL_PDC_RNPR, 0);
-				at91_mci_write(host, ATMEL_PDC_RNCR, 0);
-
-				ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
-			}
-			else {
-				/*
-				 * Handle a write
-				 */
-				host->total_length = block_length * blocks;
-				/*
-				 * MCI1 rev2xx Data Write Operation and
-				 * number of bytes erratum
-				 */
-				if (at91mci_is_mci1rev2xx())
-					if (host->total_length < 12)
-						host->total_length = 12;
-
-				at91_mci_sg_to_dma(host, data);
-
-				pr_debug("Transmitting %d bytes\n", host->total_length);
-
-				at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
-				at91_mci_write(host, ATMEL_PDC_TCR, (data->blksz & 0x3) ?
-						host->total_length : host->total_length / 4);
-
-				ier = AT91_MCI_CMDRDY;
-			}
-		}
-	}
-
-	/*
-	 * Send the command and then enable the PDC - not the other way round as
-	 * the data sheet says
-	 */
-
-	at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
-	at91_mci_write(host, AT91_MCI_CMDR, cmdr);
-
-	if (cmdr & AT91_MCI_TRCMD_START) {
-		if (cmdr & AT91_MCI_TRDIR)
-			at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
-	}
-
-	/* Enable selected interrupts */
-	at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
-}
-
-/*
- * Process the next step in the request
- */
-static void at91_mci_process_next(struct at91mci_host *host)
-{
-	if (!(host->flags & FL_SENT_COMMAND)) {
-		host->flags |= FL_SENT_COMMAND;
-		at91_mci_send_command(host, host->request->cmd);
-	}
-	else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
-		host->flags |= FL_SENT_STOP;
-		at91_mci_send_command(host, host->request->stop);
-	} else {
-		del_timer(&host->timer);
-		/* the at91rm9200 mci controller hangs after some transfers,
-		 * and the workaround is to reset it after each transfer.
-		 */
-		if (cpu_is_at91rm9200())
-			at91_reset_host(host);
-		mmc_request_done(host->mmc, host->request);
-	}
-}
-
-/*
- * Handle a command that has been completed
- */
-static void at91_mci_completed_command(struct at91mci_host *host, unsigned int status)
-{
-	struct mmc_command *cmd = host->cmd;
-	struct mmc_data *data = cmd->data;
-
-	at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
-
-	cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
-	cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
-	cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
-	cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
-
-	pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n",
-		 status, at91_mci_read(host, AT91_MCI_SR),
-		 cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
-
-	if (status & AT91_MCI_ERRORS) {
-		if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
-			cmd->error = 0;
-		}
-		else {
-			if (status & (AT91_MCI_DTOE | AT91_MCI_DCRCE)) {
-				if (data) {
-					if (status & AT91_MCI_DTOE)
-						data->error = -ETIMEDOUT;
-					else if (status & AT91_MCI_DCRCE)
-						data->error = -EILSEQ;
-				}
-			} else {
-				if (status & AT91_MCI_RTOE)
-					cmd->error = -ETIMEDOUT;
-				else if (status & AT91_MCI_RCRCE)
-					cmd->error = -EILSEQ;
-				else
-					cmd->error = -EIO;
-			}
-
-			pr_debug("Error detected and set to %d/%d (cmd = %d, retries = %d)\n",
-				cmd->error, data ? data->error : 0,
-				 cmd->opcode, cmd->retries);
-		}
-	}
-	else
-		cmd->error = 0;
-
-	at91_mci_process_next(host);
-}
-
-/*
- * Handle an MMC request
- */
-static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
-{
-	struct at91mci_host *host = mmc_priv(mmc);
-	host->request = mrq;
-	host->flags = 0;
-
-	/* more than 1s timeout needed with slow SD cards */
-	mod_timer(&host->timer, jiffies +  msecs_to_jiffies(2000));
-
-	at91_mci_process_next(host);
-}
-
-/*
- * Set the IOS
- */
-static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
-	int clkdiv;
-	struct at91mci_host *host = mmc_priv(mmc);
-	unsigned long at91_master_clock = clk_get_rate(host->mci_clk);
-
-	host->bus_mode = ios->bus_mode;
-
-	if (ios->clock == 0) {
-		/* Disable the MCI controller */
-		at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS);
-		clkdiv = 0;
-	}
-	else {
-		/* Enable the MCI controller */
-		at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
-
-		if ((at91_master_clock % (ios->clock * 2)) == 0)
-			clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
-		else
-			clkdiv = (at91_master_clock / ios->clock) / 2;
-
-		pr_debug("clkdiv = %d. mcck = %ld\n", clkdiv,
-			at91_master_clock / (2 * (clkdiv + 1)));
-	}
-	if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
-		pr_debug("MMC: Setting controller bus width to 4\n");
-		at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
-	}
-	else {
-		pr_debug("MMC: Setting controller bus width to 1\n");
-		at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
-	}
-
-	/* Set the clock divider */
-	at91_mci_write(host, AT91_MCI_MR, (at91_mci_read(host, AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
-
-	/* maybe switch power to the card */
-	if (gpio_is_valid(host->board->vcc_pin)) {
-		switch (ios->power_mode) {
-			case MMC_POWER_OFF:
-				gpio_set_value(host->board->vcc_pin, 0);
-				break;
-			case MMC_POWER_UP:
-				gpio_set_value(host->board->vcc_pin, 1);
-				break;
-			case MMC_POWER_ON:
-				break;
-			default:
-				WARN_ON(1);
-		}
-	}
-}
-
-/*
- * Handle an interrupt
- */
-static irqreturn_t at91_mci_irq(int irq, void *devid)
-{
-	struct at91mci_host *host = devid;
-	int completed = 0;
-	unsigned int int_status, int_mask;
-
-	int_status = at91_mci_read(host, AT91_MCI_SR);
-	int_mask = at91_mci_read(host, AT91_MCI_IMR);
-
-	pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask,
-		int_status & int_mask);
-
-	int_status = int_status & int_mask;
-
-	if (int_status & AT91_MCI_ERRORS) {
-		completed = 1;
-
-		if (int_status & AT91_MCI_UNRE)
-			pr_debug("MMC: Underrun error\n");
-		if (int_status & AT91_MCI_OVRE)
-			pr_debug("MMC: Overrun error\n");
-		if (int_status & AT91_MCI_DTOE)
-			pr_debug("MMC: Data timeout\n");
-		if (int_status & AT91_MCI_DCRCE)
-			pr_debug("MMC: CRC error in data\n");
-		if (int_status & AT91_MCI_RTOE)
-			pr_debug("MMC: Response timeout\n");
-		if (int_status & AT91_MCI_RENDE)
-			pr_debug("MMC: Response end bit error\n");
-		if (int_status & AT91_MCI_RCRCE)
-			pr_debug("MMC: Response CRC error\n");
-		if (int_status & AT91_MCI_RDIRE)
-			pr_debug("MMC: Response direction error\n");
-		if (int_status & AT91_MCI_RINDE)
-			pr_debug("MMC: Response index error\n");
-	} else {
-		/* Only continue processing if no errors */
-
-		if (int_status & AT91_MCI_TXBUFE) {
-			pr_debug("TX buffer empty\n");
-			at91_mci_handle_transmitted(host);
-		}
-
-		if (int_status & AT91_MCI_ENDRX) {
-			pr_debug("ENDRX\n");
-			at91_mci_post_dma_read(host);
-		}
-
-		if (int_status & AT91_MCI_RXBUFF) {
-			pr_debug("RX buffer full\n");
-			at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
-			at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
-			completed = 1;
-		}
-
-		if (int_status & AT91_MCI_ENDTX)
-			pr_debug("Transmit has ended\n");
-
-		if (int_status & AT91_MCI_NOTBUSY) {
-			pr_debug("Card is ready\n");
-			at91_mci_update_bytes_xfered(host);
-			completed = 1;
-		}
-
-		if (int_status & AT91_MCI_DTIP)
-			pr_debug("Data transfer in progress\n");
-
-		if (int_status & AT91_MCI_BLKE) {
-			pr_debug("Block transfer has ended\n");
-			if (host->request->data && host->request->data->blocks > 1) {
-				/* multi block write : complete multi write
-				 * command and send stop */
-				completed = 1;
-			} else {
-				at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
-			}
-		}
-
-		if (int_status & AT91_MCI_SDIOIRQA)
-			mmc_signal_sdio_irq(host->mmc);
-
-		if (int_status & AT91_MCI_SDIOIRQB)
-			mmc_signal_sdio_irq(host->mmc);
-
-		if (int_status & AT91_MCI_TXRDY)
-			pr_debug("Ready to transmit\n");
-
-		if (int_status & AT91_MCI_RXRDY)
-			pr_debug("Ready to receive\n");
-
-		if (int_status & AT91_MCI_CMDRDY) {
-			pr_debug("Command ready\n");
-			completed = at91_mci_handle_cmdrdy(host);
-		}
-	}
-
-	if (completed) {
-		pr_debug("Completed command\n");
-		at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
-		at91_mci_completed_command(host, int_status);
-	} else
-		at91_mci_write(host, AT91_MCI_IDR, int_status & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
-{
-	struct at91mci_host *host = _host;
-	int present;
-
-	/* entering this ISR means that we have configured det_pin:
-	 * we can use its value in board structure */
-	present = !gpio_get_value(host->board->det_pin);
-
-	/*
-	 * we expect this irq on both insert and remove,
-	 * and use a short delay to debounce.
-	 */
-	if (present != host->present) {
-		host->present = present;
-		pr_debug("%s: card %s\n", mmc_hostname(host->mmc),
-			present ? "insert" : "remove");
-		if (!present) {
-			pr_debug("****** Resetting SD-card bus width ******\n");
-			at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
-		}
-		/* 0.5s needed because of early card detect switch firing */
-		mmc_detect_change(host->mmc, msecs_to_jiffies(500));
-	}
-	return IRQ_HANDLED;
-}
-
-static int at91_mci_get_ro(struct mmc_host *mmc)
-{
-	struct at91mci_host *host = mmc_priv(mmc);
-
-	if (gpio_is_valid(host->board->wp_pin))
-		return !!gpio_get_value(host->board->wp_pin);
-	/*
-	 * Board doesn't support read only detection; let the mmc core
-	 * decide what to do.
-	 */
-	return -ENOSYS;
-}
-
-static void at91_mci_enable_sdio_irq(struct mmc_host *mmc, int enable)
-{
-	struct at91mci_host *host = mmc_priv(mmc);
-
-	pr_debug("%s: sdio_irq %c : %s\n", mmc_hostname(host->mmc),
-		host->board->slot_b ? 'B':'A', enable ? "enable" : "disable");
-	at91_mci_write(host, enable ? AT91_MCI_IER : AT91_MCI_IDR,
-		host->board->slot_b ? AT91_MCI_SDIOIRQB : AT91_MCI_SDIOIRQA);
-
-}
-
-static const struct mmc_host_ops at91_mci_ops = {
-	.request	= at91_mci_request,
-	.set_ios	= at91_mci_set_ios,
-	.get_ro		= at91_mci_get_ro,
-	.enable_sdio_irq = at91_mci_enable_sdio_irq,
-};
-
-/*
- * Probe for the device
- */
-static int __init at91_mci_probe(struct platform_device *pdev)
-{
-	struct mmc_host *mmc;
-	struct at91mci_host *host;
-	struct resource *res;
-	int ret;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENXIO;
-
-	if (!request_mem_region(res->start, resource_size(res), DRIVER_NAME))
-		return -EBUSY;
-
-	mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
-	if (!mmc) {
-		ret = -ENOMEM;
-		dev_dbg(&pdev->dev, "couldn't allocate mmc host\n");
-		goto fail6;
-	}
-
-	mmc->ops = &at91_mci_ops;
-	mmc->f_min = 375000;
-	mmc->f_max = 25000000;
-	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-	mmc->caps = 0;
-
-	mmc->max_blk_size  = MCI_MAXBLKSIZE;
-	mmc->max_blk_count = MCI_BLKATONCE;
-	mmc->max_req_size  = MCI_BUFSIZE;
-	mmc->max_segs      = MCI_BLKATONCE;
-	mmc->max_seg_size  = MCI_BUFSIZE;
-
-	host = mmc_priv(mmc);
-	host->mmc = mmc;
-	host->bus_mode = 0;
-	host->board = pdev->dev.platform_data;
-	if (host->board->wire4) {
-		if (at91mci_is_mci1rev2xx())
-			mmc->caps |= MMC_CAP_4_BIT_DATA;
-		else
-			dev_warn(&pdev->dev, "4 wire bus mode not supported"
-				" - using 1 wire\n");
-	}
-
-	host->buffer = dma_alloc_coherent(&pdev->dev, MCI_BUFSIZE,
-					&host->physical_address, GFP_KERNEL);
-	if (!host->buffer) {
-		ret = -ENOMEM;
-		dev_err(&pdev->dev, "Can't allocate transmit buffer\n");
-		goto fail5;
-	}
-
-	/* Add SDIO capability when available */
-	if (at91mci_is_mci1rev2xx()) {
-		/* at91mci MCI1 rev2xx sdio interrupt erratum */
-		if (host->board->wire4 || !host->board->slot_b)
-			mmc->caps |= MMC_CAP_SDIO_IRQ;
-	}
-
-	/*
-	 * Reserve GPIOs ... board init code makes sure these pins are set
-	 * up as GPIOs with the right direction (input, except for vcc)
-	 */
-	if (gpio_is_valid(host->board->det_pin)) {
-		ret = gpio_request(host->board->det_pin, "mmc_detect");
-		if (ret < 0) {
-			dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
-			goto fail4b;
-		}
-	}
-	if (gpio_is_valid(host->board->wp_pin)) {
-		ret = gpio_request(host->board->wp_pin, "mmc_wp");
-		if (ret < 0) {
-			dev_dbg(&pdev->dev, "couldn't claim wp sense pin\n");
-			goto fail4;
-		}
-	}
-	if (gpio_is_valid(host->board->vcc_pin)) {
-		ret = gpio_request(host->board->vcc_pin, "mmc_vcc");
-		if (ret < 0) {
-			dev_dbg(&pdev->dev, "couldn't claim vcc switch pin\n");
-			goto fail3;
-		}
-	}
-
-	/*
-	 * Get Clock
-	 */
-	host->mci_clk = clk_get(&pdev->dev, "mci_clk");
-	if (IS_ERR(host->mci_clk)) {
-		ret = -ENODEV;
-		dev_dbg(&pdev->dev, "no mci_clk?\n");
-		goto fail2;
-	}
-
-	/*
-	 * Map I/O region
-	 */
-	host->baseaddr = ioremap(res->start, resource_size(res));
-	if (!host->baseaddr) {
-		ret = -ENOMEM;
-		goto fail1;
-	}
-
-	/*
-	 * Reset hardware
-	 */
-	clk_enable(host->mci_clk);		/* Enable the peripheral clock */
-	at91_mci_disable(host);
-	at91_mci_enable(host);
-
-	/*
-	 * Allocate the MCI interrupt
-	 */
-	host->irq = platform_get_irq(pdev, 0);
-	ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED,
-			mmc_hostname(mmc), host);
-	if (ret) {
-		dev_dbg(&pdev->dev, "request MCI interrupt failed\n");
-		goto fail0;
-	}
-
-	setup_timer(&host->timer, at91_timeout_timer, (unsigned long)host);
-
-	platform_set_drvdata(pdev, mmc);
-
-	/*
-	 * Add host to MMC layer
-	 */
-	if (gpio_is_valid(host->board->det_pin)) {
-		host->present = !gpio_get_value(host->board->det_pin);
-	}
-	else
-		host->present = -1;
-
-	mmc_add_host(mmc);
-
-	/*
-	 * monitor card insertion/removal if we can
-	 */
-	if (gpio_is_valid(host->board->det_pin)) {
-		ret = request_irq(gpio_to_irq(host->board->det_pin),
-				at91_mmc_det_irq, 0, mmc_hostname(mmc), host);
-		if (ret)
-			dev_warn(&pdev->dev, "request MMC detect irq failed\n");
-		else
-			device_init_wakeup(&pdev->dev, 1);
-	}
-
-	pr_debug("Added MCI driver\n");
-
-	return 0;
-
-fail0:
-	clk_disable(host->mci_clk);
-	iounmap(host->baseaddr);
-fail1:
-	clk_put(host->mci_clk);
-fail2:
-	if (gpio_is_valid(host->board->vcc_pin))
-		gpio_free(host->board->vcc_pin);
-fail3:
-	if (gpio_is_valid(host->board->wp_pin))
-		gpio_free(host->board->wp_pin);
-fail4:
-	if (gpio_is_valid(host->board->det_pin))
-		gpio_free(host->board->det_pin);
-fail4b:
-	if (host->buffer)
-		dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
-				host->buffer, host->physical_address);
-fail5:
-	mmc_free_host(mmc);
-fail6:
-	release_mem_region(res->start, resource_size(res));
-	dev_err(&pdev->dev, "probe failed, err %d\n", ret);
-	return ret;
-}
-
-/*
- * Remove a device
- */
-static int __exit at91_mci_remove(struct platform_device *pdev)
-{
-	struct mmc_host *mmc = platform_get_drvdata(pdev);
-	struct at91mci_host *host;
-	struct resource *res;
-
-	if (!mmc)
-		return -1;
-
-	host = mmc_priv(mmc);
-
-	if (host->buffer)
-		dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
-				host->buffer, host->physical_address);
-
-	if (gpio_is_valid(host->board->det_pin)) {
-		if (device_can_wakeup(&pdev->dev))
-			free_irq(gpio_to_irq(host->board->det_pin), host);
-		device_init_wakeup(&pdev->dev, 0);
-		gpio_free(host->board->det_pin);
-	}
-
-	at91_mci_disable(host);
-	del_timer_sync(&host->timer);
-	mmc_remove_host(mmc);
-	free_irq(host->irq, host);
-
-	clk_disable(host->mci_clk);			/* Disable the peripheral clock */
-	clk_put(host->mci_clk);
-
-	if (gpio_is_valid(host->board->vcc_pin))
-		gpio_free(host->board->vcc_pin);
-	if (gpio_is_valid(host->board->wp_pin))
-		gpio_free(host->board->wp_pin);
-
-	iounmap(host->baseaddr);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-
-	mmc_free_host(mmc);
-	platform_set_drvdata(pdev, NULL);
-	pr_debug("MCI Removed\n");
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct mmc_host *mmc = platform_get_drvdata(pdev);
-	struct at91mci_host *host = mmc_priv(mmc);
-	int ret = 0;
-
-	if (gpio_is_valid(host->board->det_pin) && device_may_wakeup(&pdev->dev))
-		enable_irq_wake(host->board->det_pin);
-
-	if (mmc)
-		ret = mmc_suspend_host(mmc);
-
-	return ret;
-}
-
-static int at91_mci_resume(struct platform_device *pdev)
-{
-	struct mmc_host *mmc = platform_get_drvdata(pdev);
-	struct at91mci_host *host = mmc_priv(mmc);
-	int ret = 0;
-
-	if (gpio_is_valid(host->board->det_pin) && device_may_wakeup(&pdev->dev))
-		disable_irq_wake(host->board->det_pin);
-
-	if (mmc)
-		ret = mmc_resume_host(mmc);
-
-	return ret;
-}
-#else
-#define at91_mci_suspend	NULL
-#define at91_mci_resume		NULL
-#endif
-
-static struct platform_driver at91_mci_driver = {
-	.remove		= __exit_p(at91_mci_remove),
-	.suspend	= at91_mci_suspend,
-	.resume		= at91_mci_resume,
-	.driver		= {
-		.name	= DRIVER_NAME,
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init at91_mci_init(void)
-{
-	return platform_driver_probe(&at91_mci_driver, at91_mci_probe);
-}
-
-static void __exit at91_mci_exit(void)
-{
-	platform_driver_unregister(&at91_mci_driver);
-}
-
-module_init(at91_mci_init);
-module_exit(at91_mci_exit);
-
-MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
-MODULE_AUTHOR("Nick Randell");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:at91_mci");
diff --git a/drivers/mmc/host/at91_mci.h b/drivers/mmc/host/at91_mci.h
deleted file mode 100644
index eec3a6b..0000000
--- a/drivers/mmc/host/at91_mci.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * drivers/mmc/host/at91_mci.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * MultiMedia Card Interface (MCI) registers.
- * Based on AT91RM9200 datasheet revision F.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91_MCI_H
-#define AT91_MCI_H
-
-#define AT91_MCI_CR		0x00		/* Control Register */
-#define		AT91_MCI_MCIEN		(1 <<  0)	/* Multi-Media Interface Enable */
-#define		AT91_MCI_MCIDIS		(1 <<  1)	/* Multi-Media Interface Disable */
-#define		AT91_MCI_PWSEN		(1 <<  2)	/* Power Save Mode Enable */
-#define		AT91_MCI_PWSDIS		(1 <<  3)	/* Power Save Mode Disable */
-#define		AT91_MCI_SWRST		(1 <<  7)	/* Software Reset */
-
-#define AT91_MCI_MR		0x04		/* Mode Register */
-#define		AT91_MCI_CLKDIV		(0xff  <<  0)	/* Clock Divider */
-#define		AT91_MCI_PWSDIV		(7     <<  8)	/* Power Saving Divider */
-#define		AT91_MCI_RDPROOF	(1     << 11)	/* Read Proof Enable [SAM926[03] only] */
-#define		AT91_MCI_WRPROOF	(1     << 12)	/* Write Proof Enable [SAM926[03] only] */
-#define		AT91_MCI_PDCFBYTE	(1     << 13)	/* PDC Force Byte Transfer [SAM926[03] only] */
-#define		AT91_MCI_PDCPADV	(1     << 14)	/* PDC Padding Value */
-#define		AT91_MCI_PDCMODE	(1     << 15)	/* PDC-orientated Mode */
-#define		AT91_MCI_BLKLEN		(0xfff << 18)	/* Data Block Length */
-
-#define AT91_MCI_DTOR		0x08		/* Data Timeout Register */
-#define		AT91_MCI_DTOCYC		(0xf << 0)	/* Data Timeout Cycle Number */
-#define		AT91_MCI_DTOMUL		(7   << 4)	/* Data Timeout Multiplier */
-#define		AT91_MCI_DTOMUL_1		(0 <<  4)
-#define		AT91_MCI_DTOMUL_16		(1 <<  4)
-#define		AT91_MCI_DTOMUL_128		(2 <<  4)
-#define		AT91_MCI_DTOMUL_256		(3 <<  4)
-#define		AT91_MCI_DTOMUL_1K		(4 <<  4)
-#define		AT91_MCI_DTOMUL_4K		(5 <<  4)
-#define		AT91_MCI_DTOMUL_64K		(6 <<  4)
-#define		AT91_MCI_DTOMUL_1M		(7 <<  4)
-
-#define AT91_MCI_SDCR		0x0c		/* SD Card Register */
-#define		AT91_MCI_SDCSEL		(3 << 0)	/* SD Card Selector */
-#define		AT91_MCI_SDCBUS		(1 << 7)	/* 1-bit or 4-bit bus */
-
-#define AT91_MCI_ARGR		0x10		/* Argument Register */
-
-#define AT91_MCI_CMDR		0x14		/* Command Register */
-#define		AT91_MCI_CMDNB		(0x3f << 0)	/* Command Number */
-#define		AT91_MCI_RSPTYP		(3    << 6)	/* Response Type */
-#define			AT91_MCI_RSPTYP_NONE	(0 <<  6)
-#define			AT91_MCI_RSPTYP_48	(1 <<  6)
-#define			AT91_MCI_RSPTYP_136	(2 <<  6)
-#define		AT91_MCI_SPCMD		(7    << 8)	/* Special Command */
-#define			AT91_MCI_SPCMD_NONE	(0 <<  8)
-#define			AT91_MCI_SPCMD_INIT	(1 <<  8)
-#define			AT91_MCI_SPCMD_SYNC	(2 <<  8)
-#define			AT91_MCI_SPCMD_ICMD	(4 <<  8)
-#define			AT91_MCI_SPCMD_IRESP	(5 <<  8)
-#define		AT91_MCI_OPDCMD		(1 << 11)	/* Open Drain Command */
-#define		AT91_MCI_MAXLAT		(1 << 12)	/* Max Latency for Command to Response */
-#define		AT91_MCI_TRCMD		(3 << 16)	/* Transfer Command */
-#define			AT91_MCI_TRCMD_NONE	(0 << 16)
-#define			AT91_MCI_TRCMD_START	(1 << 16)
-#define			AT91_MCI_TRCMD_STOP	(2 << 16)
-#define		AT91_MCI_TRDIR		(1 << 18)	/* Transfer Direction */
-#define		AT91_MCI_TRTYP		(3 << 19)	/* Transfer Type */
-#define			AT91_MCI_TRTYP_BLOCK	(0 << 19)
-#define			AT91_MCI_TRTYP_MULTIPLE	(1 << 19)
-#define			AT91_MCI_TRTYP_STREAM	(2 << 19)
-#define			AT91_MCI_TRTYP_SDIO_BYTE	(4 << 19)
-#define			AT91_MCI_TRTYP_SDIO_BLOCK	(5 << 19)
-
-#define AT91_MCI_BLKR		0x18		/* Block Register */
-#define		AT91_MCI_BLKR_BCNT(n)	((0xffff & (n)) << 0)	/* Block count */
-#define		AT91_MCI_BLKR_BLKLEN(n)	((0xffff & (n)) << 16)	/* Block length */
-
-#define AT91_MCI_RSPR(n)	(0x20 + ((n) * 4))	/* Response Registers 0-3 */
-#define AT91_MCR_RDR		0x30		/* Receive Data Register */
-#define AT91_MCR_TDR		0x34		/* Transmit Data Register */
-
-#define AT91_MCI_SR		0x40		/* Status Register */
-#define		AT91_MCI_CMDRDY		(1 <<  0)	/* Command Ready */
-#define		AT91_MCI_RXRDY		(1 <<  1)	/* Receiver Ready */
-#define		AT91_MCI_TXRDY		(1 <<  2)	/* Transmit Ready */
-#define		AT91_MCI_BLKE		(1 <<  3)	/* Data Block Ended */
-#define		AT91_MCI_DTIP		(1 <<  4)	/* Data Transfer in Progress */
-#define		AT91_MCI_NOTBUSY	(1 <<  5)	/* Data Not Busy */
-#define		AT91_MCI_ENDRX		(1 <<  6)	/* End of RX Buffer */
-#define		AT91_MCI_ENDTX		(1 <<  7)	/* End fo TX Buffer */
-#define		AT91_MCI_SDIOIRQA	(1 <<  8)	/* SDIO Interrupt for Slot A */
-#define		AT91_MCI_SDIOIRQB	(1 <<  9)	/* SDIO Interrupt for Slot B */
-#define		AT91_MCI_RXBUFF		(1 << 14)	/* RX Buffer Full */
-#define		AT91_MCI_TXBUFE		(1 << 15)	/* TX Buffer Empty */
-#define		AT91_MCI_RINDE		(1 << 16)	/* Response Index Error */
-#define		AT91_MCI_RDIRE		(1 << 17)	/* Response Direction Error */
-#define		AT91_MCI_RCRCE		(1 << 18)	/* Response CRC Error */
-#define		AT91_MCI_RENDE		(1 << 19)	/* Response End Bit Error */
-#define		AT91_MCI_RTOE		(1 << 20)	/* Response Time-out Error */
-#define		AT91_MCI_DCRCE		(1 << 21)	/* Data CRC Error */
-#define		AT91_MCI_DTOE		(1 << 22)	/* Data Time-out Error */
-#define		AT91_MCI_OVRE		(1 << 30)	/* Overrun */
-#define		AT91_MCI_UNRE		(1 << 31)	/* Underrun */
-
-#define AT91_MCI_IER		0x44		/* Interrupt Enable Register */
-#define AT91_MCI_IDR		0x48		/* Interrupt Disable Register */
-#define AT91_MCI_IMR		0x4c		/* Interrupt Mask Register */
-
-#endif
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index ddf096e..722af1d 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/types.h>
+#include <linux/platform_data/atmel.h>
 
 #include <linux/mmc/host.h>
 #include <linux/mmc/sdio.h>
@@ -40,7 +41,6 @@
 #include <asm/unaligned.h>
 
 #include <mach/cpu.h>
-#include <mach/board.h>
 
 #include "atmel-mci-regs.h"
 
@@ -511,7 +511,7 @@ static const struct of_device_id atmci_dt_ids[] = {
 
 MODULE_DEVICE_TABLE(of, atmci_dt_ids);
 
-static struct mci_platform_data __devinit*
+static struct mci_platform_data*
 atmci_of_init(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index dbd0c8a..127a8fa 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -943,7 +943,7 @@ static const struct mmc_host_ops au1xmmc_ops = {
 	.enable_sdio_irq = au1xmmc_enable_sdio_irq,
 };
 
-static int __devinit au1xmmc_probe(struct platform_device *pdev)
+static int au1xmmc_probe(struct platform_device *pdev)
 {
 	struct mmc_host *mmc;
 	struct au1xmmc_host *host;
@@ -1114,7 +1114,7 @@ out0:
 	return ret;
 }
 
-static int __devexit au1xmmc_remove(struct platform_device *pdev)
+static int au1xmmc_remove(struct platform_device *pdev)
 {
 	struct au1xmmc_host *host = platform_get_drvdata(pdev);
 
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c
index b9b463e..fb4348c 100644
--- a/drivers/mmc/host/bfin_sdh.c
+++ b/drivers/mmc/host/bfin_sdh.c
@@ -522,7 +522,7 @@ static void sdh_reset(void)
 	SSYNC();
 }
 
-static int __devinit sdh_probe(struct platform_device *pdev)
+static int sdh_probe(struct platform_device *pdev)
 {
 	struct mmc_host *mmc;
 	struct sdh_host *host;
@@ -617,7 +617,7 @@ out1:
 	return ret;
 }
 
-static int __devexit sdh_remove(struct platform_device *pdev)
+static int sdh_remove(struct platform_device *pdev)
 {
 	struct mmc_host *mmc = platform_get_drvdata(pdev);
 
@@ -680,7 +680,7 @@ static int sdh_resume(struct platform_device *dev)
 
 static struct platform_driver sdh_driver = {
 	.probe   = sdh_probe,
-	.remove  = __devexit_p(sdh_remove),
+	.remove  = sdh_remove,
 	.suspend = sdh_suspend,
 	.resume  = sdh_resume,
 	.driver  = {
diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c
index 83693fd..777ca20 100644
--- a/drivers/mmc/host/cb710-mmc.c
+++ b/drivers/mmc/host/cb710-mmc.c
@@ -690,7 +690,7 @@ static int cb710_mmc_resume(struct platform_device *pdev)
 
 #endif /* CONFIG_PM */
 
-static int __devinit cb710_mmc_init(struct platform_device *pdev)
+static int cb710_mmc_init(struct platform_device *pdev)
 {
 	struct cb710_slot *slot = cb710_pdev_to_slot(pdev);
 	struct cb710_chip *chip = cb710_slot_to_chip(slot);
@@ -746,7 +746,7 @@ err_free_mmc:
 	return err;
 }
 
-static int __devexit cb710_mmc_exit(struct platform_device *pdev)
+static int cb710_mmc_exit(struct platform_device *pdev)
 {
 	struct cb710_slot *slot = cb710_pdev_to_slot(pdev);
 	struct mmc_host *mmc = cb710_slot_to_mmc(slot);
@@ -773,7 +773,7 @@ static int __devexit cb710_mmc_exit(struct platform_device *pdev)
 static struct platform_driver cb710_mmc_driver = {
 	.driver.name = "cb710-mmc",
 	.probe = cb710_mmc_init,
-	.remove = __devexit_p(cb710_mmc_exit),
+	.remove = cb710_mmc_exit,
 #ifdef CONFIG_PM
 	.suspend = cb710_mmc_suspend,
 	.resume = cb710_mmc_resume,
diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c
index edb37e9..8ee0f74 100644
--- a/drivers/mmc/host/dw_mmc-pci.c
+++ b/drivers/mmc/host/dw_mmc-pci.c
@@ -37,7 +37,7 @@ static struct dw_mci_board pci_board_data = {
 	.fifo_depth			= 32,
 };
 
-static int __devinit dw_mci_pci_probe(struct pci_dev *pdev,
+static int dw_mci_pci_probe(struct pci_dev *pdev,
 				  const struct pci_device_id *entries)
 {
 	struct dw_mci *host;
@@ -85,7 +85,7 @@ err_disable_dev:
 	return ret;
 }
 
-static void __devexit dw_mci_pci_remove(struct pci_dev *pdev)
+static void dw_mci_pci_remove(struct pci_dev *pdev)
 {
 	struct dw_mci *host = pci_get_drvdata(pdev);
 
@@ -134,7 +134,7 @@ static struct pci_driver dw_mci_pci_driver = {
 	.name		= "dw_mmc_pci",
 	.id_table	= dw_mci_pci_id,
 	.probe		= dw_mci_pci_probe,
-	.remove		= dw_mci_pci_remove,
+	.remove		= __devexit_p(dw_mci_pci_remove),
 	.driver		=	{
 		.pm =   &dw_mci_pci_pmops
 	},
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index 917936b..222036c 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -62,12 +62,12 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
 }
 EXPORT_SYMBOL_GPL(dw_mci_pltfm_register);
 
-static int __devinit dw_mci_pltfm_probe(struct platform_device *pdev)
+static int dw_mci_pltfm_probe(struct platform_device *pdev)
 {
 	return dw_mci_pltfm_register(pdev, NULL);
 }
 
-static int __devexit dw_mci_pltfm_remove(struct platform_device *pdev)
+static int dw_mci_pltfm_remove(struct platform_device *pdev)
 {
 	struct dw_mci *host = platform_get_drvdata(pdev);
 
@@ -119,7 +119,8 @@ static const struct of_device_id dw_mci_pltfm_match[] = {
 MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
 
 static struct platform_driver dw_mci_pltfm_driver = {
-	.remove		= __exit_p(dw_mci_pltfm_remove),
+	.probe		= dw_mci_pltfm_probe,
+	.remove		= __devexit_p(dw_mci_pltfm_remove),
 	.driver		= {
 		.name		= "dw_mmc",
 		.of_match_table	= of_match_ptr(dw_mci_pltfm_match),
@@ -127,18 +128,7 @@ static struct platform_driver dw_mci_pltfm_driver = {
 	},
 };
 
-static int __init dw_mci_init(void)
-{
-	return platform_driver_probe(&dw_mci_pltfm_driver, dw_mci_pltfm_probe);
-}
-
-static void __exit dw_mci_exit(void)
-{
-	platform_driver_unregister(&dw_mci_pltfm_driver);
-}
-
-module_init(dw_mci_init);
-module_exit(dw_mci_exit);
+module_platform_driver(dw_mci_pltfm_driver);
 
 MODULE_DESCRIPTION("DW Multimedia Card Interface driver");
 MODULE_AUTHOR("NXP Semiconductor VietNam");
diff --git a/drivers/mmc/host/dw_mmc-pltfm.h b/drivers/mmc/host/dw_mmc-pltfm.h
index 2ac37b8..68e7fd2 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.h
+++ b/drivers/mmc/host/dw_mmc-pltfm.h
@@ -14,7 +14,7 @@
 
 extern int dw_mci_pltfm_register(struct platform_device *pdev,
 				const struct dw_mci_drv_data *drv_data);
-extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev);
+extern int dw_mci_pltfm_remove(struct platform_device *pdev);
 extern const struct dev_pm_ops dw_mci_pltfm_pmops;
 
 #endif /* _DW_MMC_PLTFM_H_ */
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index c0667c8..7342029 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -232,7 +232,7 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
 {
 	struct mmc_data	*data;
 	struct dw_mci_slot *slot = mmc_priv(mmc);
-	struct dw_mci_drv_data *drv_data = slot->host->drv_data;
+	const struct dw_mci_drv_data *drv_data = slot->host->drv_data;
 	u32 cmdr;
 	cmd->error = -EINPROGRESS;
 
@@ -617,13 +617,13 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg)
 		cmd, arg, cmd_status);
 }
 
-static void dw_mci_setup_bus(struct dw_mci_slot *slot)
+static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
 {
 	struct dw_mci *host = slot->host;
 	u32 div;
 	u32 clk_en_a;
 
-	if (slot->clock != host->current_speed) {
+	if (slot->clock != host->current_speed || force_clkinit) {
 		div = host->bus_hz / slot->clock;
 		if (host->bus_hz % slot->clock && host->bus_hz > slot->clock)
 			/*
@@ -684,7 +684,7 @@ static void __dw_mci_start_request(struct dw_mci *host,
 		host->pdata->select_slot(slot->id);
 
 	/* Slot specific timing and width adjustment */
-	dw_mci_setup_bus(slot);
+	dw_mci_setup_bus(slot, false);
 
 	host->cur_slot = slot;
 	host->mrq = mrq;
@@ -773,7 +773,7 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct dw_mci_slot *slot = mmc_priv(mmc);
-	struct dw_mci_drv_data *drv_data = slot->host->drv_data;
+	const struct dw_mci_drv_data *drv_data = slot->host->drv_data;
 	u32 regs;
 
 	/* set default 1 bit mode */
@@ -1817,7 +1817,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 {
 	struct mmc_host *mmc;
 	struct dw_mci_slot *slot;
-	struct dw_mci_drv_data *drv_data = host->drv_data;
+	const struct dw_mci_drv_data *drv_data = host->drv_data;
 	int ctrl_id, ret;
 	u8 bus_width;
 
@@ -1850,6 +1850,9 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 	if (host->pdata->caps)
 		mmc->caps = host->pdata->caps;
 
+	if (host->pdata->pm_caps)
+		mmc->pm_caps = host->pdata->pm_caps;
+
 	if (host->dev->of_node) {
 		ctrl_id = of_alias_get_id(host->dev->of_node, "mshc");
 		if (ctrl_id < 0)
@@ -2038,7 +2041,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 	struct dw_mci_board *pdata;
 	struct device *dev = host->dev;
 	struct device_node *np = dev->of_node;
-	struct dw_mci_drv_data *drv_data = host->drv_data;
+	const struct dw_mci_drv_data *drv_data = host->drv_data;
 	int idx, ret;
 
 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
@@ -2072,6 +2075,12 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 			return ERR_PTR(ret);
 	}
 
+	if (of_find_property(np, "keep-power-in-suspend", NULL))
+		pdata->pm_caps |= MMC_PM_KEEP_POWER;
+
+	if (of_find_property(np, "enable-sdio-wakeup", NULL))
+		pdata->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
+
 	return pdata;
 }
 
@@ -2084,7 +2093,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 
 int dw_mci_probe(struct dw_mci *host)
 {
-	struct dw_mci_drv_data *drv_data = host->drv_data;
+	const struct dw_mci_drv_data *drv_data = host->drv_data;
 	int width, i, ret = 0;
 	u32 fifo_size;
 	int init_slots = 0;
@@ -2411,6 +2420,11 @@ int dw_mci_resume(struct dw_mci *host)
 		struct dw_mci_slot *slot = host->slot[i];
 		if (!slot)
 			continue;
+		if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) {
+			dw_mci_set_ios(slot->mmc, &slot->mmc->ios);
+			dw_mci_setup_bus(slot, true);
+		}
+
 		ret = mmc_resume_host(host->slot[i]->mmc);
 		if (ret < 0)
 			return ret;
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index c8852a8..2391c6b 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -702,7 +702,7 @@ static const struct jz_gpio_bulk_request jz4740_mmc_pins[] = {
 	JZ_GPIO_BULK_PIN(MSC_DATA3),
 };
 
-static int __devinit jz4740_mmc_request_gpio(struct device *dev, int gpio,
+static int jz4740_mmc_request_gpio(struct device *dev, int gpio,
 	const char *name, bool output, int value)
 {
 	int ret;
@@ -724,7 +724,7 @@ static int __devinit jz4740_mmc_request_gpio(struct device *dev, int gpio,
 	return 0;
 }
 
-static int __devinit jz4740_mmc_request_gpios(struct platform_device *pdev)
+static int jz4740_mmc_request_gpios(struct platform_device *pdev)
 {
 	int ret;
 	struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data;
@@ -759,7 +759,7 @@ err:
 	return ret;
 }
 
-static int __devinit jz4740_mmc_request_cd_irq(struct platform_device *pdev,
+static int jz4740_mmc_request_cd_irq(struct platform_device *pdev,
 	struct jz4740_mmc_host *host)
 {
 	struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data;
@@ -802,7 +802,7 @@ static inline size_t jz4740_mmc_num_pins(struct jz4740_mmc_host *host)
 	return num_pins;
 }
 
-static int __devinit jz4740_mmc_probe(struct platform_device* pdev)
+static int jz4740_mmc_probe(struct platform_device* pdev)
 {
 	int ret;
 	struct mmc_host *mmc;
@@ -938,7 +938,7 @@ err_free_host:
 	return ret;
 }
 
-static int __devexit jz4740_mmc_remove(struct platform_device *pdev)
+static int jz4740_mmc_remove(struct platform_device *pdev)
 {
 	struct jz4740_mmc_host *host = platform_get_drvdata(pdev);
 
@@ -1004,7 +1004,7 @@ const struct dev_pm_ops jz4740_mmc_pm_ops = {
 
 static struct platform_driver jz4740_mmc_driver = {
 	.probe = jz4740_mmc_probe,
-	.remove = __devexit_p(jz4740_mmc_remove),
+	.remove = jz4740_mmc_remove,
 	.driver = {
 		.name = "jz4740-mmc",
 		.owner = THIS_MODULE,
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index a600eab..74145d1 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1485,7 +1485,7 @@ nomem:
 }
 
 
-static int __devexit mmc_spi_remove(struct spi_device *spi)
+static int mmc_spi_remove(struct spi_device *spi)
 {
 	struct mmc_host		*mmc = dev_get_drvdata(&spi->dev);
 	struct mmc_spi_host	*host;
@@ -1517,7 +1517,7 @@ static int __devexit mmc_spi_remove(struct spi_device *spi)
 	return 0;
 }
 
-static struct of_device_id mmc_spi_of_match_table[] __devinitdata = {
+static struct of_device_id mmc_spi_of_match_table[] = {
 	{ .compatible = "mmc-spi-slot", },
 	{},
 };
@@ -1529,7 +1529,7 @@ static struct spi_driver mmc_spi_driver = {
 		.of_match_table = mmc_spi_of_match_table,
 	},
 	.probe =	mmc_spi_probe,
-	.remove =	__devexit_p(mmc_spi_remove),
+	.remove =	mmc_spi_remove,
 };
 
 module_spi_driver(mmc_spi_driver);
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index edc3e9b..aa04b42 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -33,6 +33,7 @@
 #include <linux/amba/mmci.h>
 #include <linux/pm_runtime.h>
 #include <linux/types.h>
+#include <linux/pinctrl/consumer.h>
 
 #include <asm/div64.h>
 #include <asm/io.h>
@@ -261,7 +262,7 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
  * no custom DMA interfaces are supported.
  */
 #ifdef CONFIG_DMA_ENGINE
-static void __devinit mmci_dma_setup(struct mmci_host *host)
+static void mmci_dma_setup(struct mmci_host *host)
 {
 	struct mmci_platform_data *plat = host->plat;
 	const char *rxname, *txname;
@@ -337,7 +338,7 @@ static void __devinit mmci_dma_setup(struct mmci_host *host)
 }
 
 /*
- * This is used in __devinit or __devexit so inline it
+ * This is used in or so inline it
  * so it can be discarded.
  */
 static inline void mmci_dma_release(struct mmci_host *host)
@@ -654,9 +655,31 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
 
 	/* The ST Micro variants has a special bit to enable SDIO */
 	if (variant->sdio && host->mmc->card)
-		if (mmc_card_sdio(host->mmc->card))
+		if (mmc_card_sdio(host->mmc->card)) {
+			/*
+			 * The ST Micro variants has a special bit
+			 * to enable SDIO.
+			 */
+			u32 clk;
+
 			datactrl |= MCI_ST_DPSM_SDIOEN;
 
+			/*
+			 * The ST Micro variant for SDIO small write transfers
+			 * needs to have clock H/W flow control disabled,
+			 * otherwise the transfer will not start. The threshold
+			 * depends on the rate of MCLK.
+			 */
+			if (data->flags & MMC_DATA_WRITE &&
+			    (host->size < 8 ||
+			     (host->size <= 8 && host->mclk > 50000000)))
+				clk = host->clk_reg & ~variant->clkreg_enable;
+			else
+				clk = host->clk_reg | variant->clkreg_enable;
+
+			mmci_write_clkreg(host, clk);
+		}
+
 	/*
 	 * Attempt to use DMA operation mode, if this
 	 * should fail, fall back to PIO mode
@@ -877,22 +900,6 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem
 		count = min(remain, maxcnt);
 
 		/*
-		 * The ST Micro variant for SDIO transfer sizes
-		 * less then 8 bytes should have clock H/W flow
-		 * control disabled.
-		 */
-		if (variant->sdio &&
-		    mmc_card_sdio(host->mmc->card)) {
-			u32 clk;
-			if (count < 8)
-				clk = host->clk_reg & ~variant->clkreg_enable;
-			else
-				clk = host->clk_reg | variant->clkreg_enable;
-
-			mmci_write_clkreg(host, clk);
-		}
-
-		/*
 		 * SDIO especially may want to send something that is
 		 * not divisible by 4 (as opposed to card sectors
 		 * etc), and the FIFO only accept full 32-bit writes.
@@ -1255,7 +1262,7 @@ static void mmci_dt_populate_generic_pdata(struct device_node *np,
 }
 #endif
 
-static int __devinit mmci_probe(struct amba_device *dev,
+static int mmci_probe(struct amba_device *dev,
 	const struct amba_id *id)
 {
 	struct mmci_platform_data *plat = dev->dev.platform_data;
@@ -1360,6 +1367,23 @@ static int __devinit mmci_probe(struct amba_device *dev,
 		mmc->f_max = min(host->mclk, fmax);
 	dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max);
 
+	host->pinctrl = devm_pinctrl_get(&dev->dev);
+	if (IS_ERR(host->pinctrl)) {
+		ret = PTR_ERR(host->pinctrl);
+		goto clk_disable;
+	}
+
+	host->pins_default = pinctrl_lookup_state(host->pinctrl,
+			PINCTRL_STATE_DEFAULT);
+
+	/* enable pins to be muxed in and configured */
+	if (!IS_ERR(host->pins_default)) {
+		ret = pinctrl_select_state(host->pinctrl, host->pins_default);
+		if (ret)
+			dev_warn(&dev->dev, "could not set default pins\n");
+	} else
+		dev_warn(&dev->dev, "could not get default pinstate\n");
+
 #ifdef CONFIG_REGULATOR
 	/* If we're using the regulator framework, try to fetch a regulator */
 	host->vcc = regulator_get(&dev->dev, "vmmc");
@@ -1522,7 +1546,7 @@ static int __devinit mmci_probe(struct amba_device *dev,
 	return ret;
 }
 
-static int __devexit mmci_remove(struct amba_device *dev)
+static int mmci_remove(struct amba_device *dev)
 {
 	struct mmc_host *mmc = amba_get_drvdata(dev);
 
@@ -1669,7 +1693,7 @@ static struct amba_driver mmci_driver = {
 		.pm	= &mmci_dev_pm_ops,
 	},
 	.probe		= mmci_probe,
-	.remove		= __devexit_p(mmci_remove),
+	.remove		= mmci_remove,
 	.id_table	= mmci_ids,
 };
 
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index d437ccf..d34d8c0 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -195,6 +195,10 @@ struct mmci_host {
 	unsigned int		size;
 	struct regulator	*vcc;
 
+	/* pinctrl handles */
+	struct pinctrl		*pinctrl;
+	struct pinctrl_state	*pins_default;
+
 #ifdef CONFIG_DMA_ENGINE
 	/* DMA stuff */
 	struct dma_chan		*dma_current;
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index 6290b7f..a72936e 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -41,7 +41,6 @@
 #include <linux/platform_data/mmc-mxcmmc.h>
 
 #include <linux/platform_data/dma-imx.h>
-#include <mach/hardware.h>
 
 #define DRIVER_NAME "mxc-mmc"
 #define MXCMCI_TIMEOUT_MS 10000
@@ -113,6 +112,11 @@
 #define INT_WRITE_OP_DONE_EN		(1 << 1)
 #define INT_READ_OP_EN			(1 << 0)
 
+enum mxcmci_type {
+	IMX21_MMC,
+	IMX31_MMC,
+};
+
 struct mxcmci_host {
 	struct mmc_host		*mmc;
 	struct resource		*res;
@@ -153,7 +157,26 @@ struct mxcmci_host {
 	struct imx_dma_data	dma_data;
 
 	struct timer_list	watchdog;
+	enum mxcmci_type	devtype;
+};
+
+static struct platform_device_id mxcmci_devtype[] = {
+	{
+		.name = "imx21-mmc",
+		.driver_data = IMX21_MMC,
+	}, {
+		.name = "imx31-mmc",
+		.driver_data = IMX31_MMC,
+	}, {
+		/* sentinel */
+	}
 };
+MODULE_DEVICE_TABLE(platform, mxcmci_devtype);
+
+static inline int is_imx31_mmc(struct mxcmci_host *host)
+{
+	return host->devtype == IMX31_MMC;
+}
 
 static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
 
@@ -240,7 +263,7 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
 		return 0;
 
 	for_each_sg(data->sg, sg, data->sg_len, i) {
-		if (sg->offset & 3 || sg->length & 3) {
+		if (sg->offset & 3 || sg->length & 3 || sg->length < 512) {
 			host->do_dma = 0;
 			return 0;
 		}
@@ -843,6 +866,8 @@ static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
 
 static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card)
 {
+	struct mxcmci_host *mxcmci = mmc_priv(host);
+
 	/*
 	 * MX3 SoCs have a silicon bug which corrupts CRC calculation of
 	 * multi-block transfers when connected SDIO peripheral doesn't
@@ -850,7 +875,7 @@ static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card)
 	 * One way to prevent this is to only allow 1-bit transfers.
 	 */
 
-	if (cpu_is_mx3() && card->type == MMC_TYPE_SDIO)
+	if (is_imx31_mmc(mxcmci) && card->type == MMC_TYPE_SDIO)
 		host->caps &= ~MMC_CAP_4_BIT_DATA;
 	else
 		host->caps |= MMC_CAP_4_BIT_DATA;
@@ -948,6 +973,7 @@ static int mxcmci_probe(struct platform_device *pdev)
 
 	host->mmc = mmc;
 	host->pdata = pdev->dev.platform_data;
+	host->devtype = pdev->id_entry->driver_data;
 	spin_lock_init(&host->lock);
 
 	mxcmci_init_ocr(host);
@@ -1120,6 +1146,7 @@ static const struct dev_pm_ops mxcmci_pm_ops = {
 static struct platform_driver mxcmci_driver = {
 	.probe		= mxcmci_probe,
 	.remove		= mxcmci_remove,
+	.id_table	= mxcmci_devtype,
 	.driver		= {
 		.name		= DRIVER_NAME,
 		.owner		= THIS_MODULE,
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index 80d1e6d..206fe49 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -43,7 +43,6 @@
 #include <linux/module.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/stmp_device.h>
-#include <linux/mmc/mxs-mmc.h>
 #include <linux/spi/mxs-spi.h>
 
 #define DRIVER_NAME	"mxs-mmc"
@@ -593,13 +592,13 @@ static int mxs_mmc_probe(struct platform_device *pdev)
 	struct mxs_mmc_host *host;
 	struct mmc_host *mmc;
 	struct resource *iores, *dmares;
-	struct mxs_mmc_platform_data *pdata;
 	struct pinctrl *pinctrl;
 	int ret = 0, irq_err, irq_dma;
 	dma_cap_mask_t mask;
 	struct regulator *reg_vmmc;
 	enum of_gpio_flags flags;
 	struct mxs_ssp *ssp;
+	u32 bus_width = 0;
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -682,25 +681,15 @@ static int mxs_mmc_probe(struct platform_device *pdev)
 	mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED |
 		    MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL;
 
-	pdata =	mmc_dev(host->mmc)->platform_data;
-	if (!pdata) {
-		u32 bus_width = 0;
-		of_property_read_u32(np, "bus-width", &bus_width);
-		if (bus_width == 4)
-			mmc->caps |= MMC_CAP_4_BIT_DATA;
-		else if (bus_width == 8)
-			mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
-		host->wp_gpio = of_get_named_gpio_flags(np, "wp-gpios", 0,
-							&flags);
-		if (flags & OF_GPIO_ACTIVE_LOW)
-			host->wp_inverted = 1;
-	} else {
-		if (pdata->flags & SLOTF_8_BIT_CAPABLE)
-			mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
-		if (pdata->flags & SLOTF_4_BIT_CAPABLE)
-			mmc->caps |= MMC_CAP_4_BIT_DATA;
-		host->wp_gpio = pdata->wp_gpio;
-	}
+	of_property_read_u32(np, "bus-width", &bus_width);
+	if (bus_width == 4)
+		mmc->caps |= MMC_CAP_4_BIT_DATA;
+	else if (bus_width == 8)
+		mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
+	host->wp_gpio = of_get_named_gpio_flags(np, "wp-gpios", 0, &flags);
+
+	if (flags & OF_GPIO_ACTIVE_LOW)
+		host->wp_inverted = 1;
 
 	mmc->f_min = 400000;
 	mmc->f_max = 288000000;
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 48ad361..4254975 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -28,9 +28,8 @@
 #include <linux/clk.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
+#include <linux/platform_data/mmc-omap.h>
 
-#include <plat/mmc.h>
-#include <plat/dma.h>
 
 #define	OMAP_MMC_REG_CMD	0x00
 #define	OMAP_MMC_REG_ARGL	0x01
@@ -72,6 +71,13 @@
 #define	OMAP_MMC_STAT_CARD_BUSY		(1 <<  2)
 #define	OMAP_MMC_STAT_END_OF_CMD	(1 <<  0)
 
+#define mmc_omap7xx()	(host->features & MMC_OMAP7XX)
+#define mmc_omap15xx()	(host->features & MMC_OMAP15XX)
+#define mmc_omap16xx()	(host->features & MMC_OMAP16XX)
+#define MMC_OMAP1_MASK	(MMC_OMAP7XX | MMC_OMAP15XX | MMC_OMAP16XX)
+#define mmc_omap1()	(host->features & MMC_OMAP1_MASK)
+#define mmc_omap2()	(!mmc_omap1())
+
 #define OMAP_MMC_REG(host, reg)		(OMAP_MMC_REG_##reg << (host)->reg_shift)
 #define OMAP_MMC_READ(host, reg)	__raw_readw((host)->virt_base + OMAP_MMC_REG(host, reg))
 #define OMAP_MMC_WRITE(host, reg, val)	__raw_writew((val), (host)->virt_base + OMAP_MMC_REG(host, reg))
@@ -84,6 +90,16 @@
 #define OMAP_MMC_CMDTYPE_AC	2
 #define OMAP_MMC_CMDTYPE_ADTC	3
 
+#define OMAP_DMA_MMC_TX		21
+#define OMAP_DMA_MMC_RX		22
+#define OMAP_DMA_MMC2_TX	54
+#define OMAP_DMA_MMC2_RX	55
+
+#define OMAP24XX_DMA_MMC2_TX	47
+#define OMAP24XX_DMA_MMC2_RX	48
+#define OMAP24XX_DMA_MMC1_TX	61
+#define OMAP24XX_DMA_MMC1_RX	62
+
 
 #define DRIVER_NAME "mmci-omap"
 
@@ -147,6 +163,7 @@ struct mmc_omap_host {
 	u32			buffer_bytes_left;
 	u32			total_bytes_left;
 
+	unsigned		features;
 	unsigned		use_dma:1;
 	unsigned		brs_received:1, dma_done:1;
 	unsigned		dma_in_use:1;
@@ -988,7 +1005,7 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
 		 * blocksize is at least that large. Blocksize is
 		 * usually 512 bytes; but not for some SD reads.
 		 */
-		burst = cpu_is_omap15xx() ? 32 : 64;
+		burst = mmc_omap15xx() ? 32 : 64;
 		if (burst > data->blksz)
 			burst = data->blksz;
 
@@ -1104,8 +1121,7 @@ static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_on,
 	if (slot->pdata->set_power != NULL)
 		slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on,
 					vdd);
-
-	if (cpu_is_omap24xx()) {
+	if (mmc_omap2()) {
 		u16 w;
 
 		if (power_on) {
@@ -1214,7 +1230,7 @@ static const struct mmc_host_ops mmc_omap_ops = {
 	.set_ios	= mmc_omap_set_ios,
 };
 
-static int __devinit mmc_omap_new_slot(struct mmc_omap_host *host, int id)
+static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
 {
 	struct mmc_omap_slot *slot = NULL;
 	struct mmc_host *mmc;
@@ -1239,7 +1255,7 @@ static int __devinit mmc_omap_new_slot(struct mmc_omap_host *host, int id)
 	mmc->ops = &mmc_omap_ops;
 	mmc->f_min = 400000;
 
-	if (cpu_class_is_omap2())
+	if (mmc_omap2())
 		mmc->f_max = 48000000;
 	else
 		mmc->f_max = 24000000;
@@ -1309,7 +1325,7 @@ static void mmc_omap_remove_slot(struct mmc_omap_slot *slot)
 	mmc_free_host(mmc);
 }
 
-static int __devinit mmc_omap_probe(struct platform_device *pdev)
+static int mmc_omap_probe(struct platform_device *pdev)
 {
 	struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
 	struct mmc_omap_host *host = NULL;
@@ -1359,6 +1375,7 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
 	init_waitqueue_head(&host->slot_wq);
 
 	host->pdata = pdata;
+	host->features = host->pdata->slots[0].features;
 	host->dev = &pdev->dev;
 	platform_set_drvdata(pdev, host);
 
@@ -1391,7 +1408,7 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
 	host->dma_tx_burst = -1;
 	host->dma_rx_burst = -1;
 
-	if (cpu_is_omap24xx())
+	if (mmc_omap2())
 		sig = host->id == 0 ? OMAP24XX_DMA_MMC1_TX : OMAP24XX_DMA_MMC2_TX;
 	else
 		sig = host->id == 0 ? OMAP_DMA_MMC_TX : OMAP_DMA_MMC2_TX;
@@ -1407,7 +1424,7 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
 		dev_warn(host->dev, "unable to obtain TX DMA engine channel %u\n",
 			sig);
 #endif
-	if (cpu_is_omap24xx())
+	if (mmc_omap2())
 		sig = host->id == 0 ? OMAP24XX_DMA_MMC1_RX : OMAP24XX_DMA_MMC2_RX;
 	else
 		sig = host->id == 0 ? OMAP_DMA_MMC_RX : OMAP_DMA_MMC2_RX;
@@ -1435,7 +1452,7 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
 	}
 
 	host->nr_slots = pdata->nr_slots;
-	host->reg_shift = (cpu_is_omap7xx() ? 1 : 2);
+	host->reg_shift = (mmc_omap7xx() ? 1 : 2);
 
 	host->mmc_omap_wq = alloc_workqueue("mmc_omap", 0, 0);
 	if (!host->mmc_omap_wq)
@@ -1478,7 +1495,7 @@ err_free_mem_region:
 	return ret;
 }
 
-static int __devexit mmc_omap_remove(struct platform_device *pdev)
+static int mmc_omap_remove(struct platform_device *pdev)
 {
 	struct mmc_omap_host *host = platform_get_drvdata(pdev);
 	int i;
@@ -1566,7 +1583,7 @@ static int mmc_omap_resume(struct platform_device *pdev)
 
 static struct platform_driver mmc_omap_driver = {
 	.probe		= mmc_omap_probe,
-	.remove		= __devexit_p(mmc_omap_remove),
+	.remove		= mmc_omap_remove,
 	.suspend	= mmc_omap_suspend,
 	.resume		= mmc_omap_resume,
 	.driver		= {
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index fedd258..bc58078 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -37,10 +37,9 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/pm_runtime.h>
-#include <mach/hardware.h>
-#include <plat/mmc.h>
-#include <plat/cpu.h>
+#include <linux/platform_data/mmc-omap.h>
 
 /* OMAP HSMMC Host Controller Registers */
 #define OMAP_HSMMC_SYSSTATUS	0x0014
@@ -62,6 +61,7 @@
 
 #define VS18			(1 << 26)
 #define VS30			(1 << 25)
+#define HSS			(1 << 21)
 #define SDVS18			(0x5 << 9)
 #define SDVS30			(0x6 << 9)
 #define SDVS33			(0x7 << 9)
@@ -78,28 +78,17 @@
 #define CLKD_SHIFT		6
 #define DTO_MASK		0x000F0000
 #define DTO_SHIFT		16
-#define INT_EN_MASK		0x307F0033
-#define BWR_ENABLE		(1 << 4)
-#define BRR_ENABLE		(1 << 5)
-#define DTO_ENABLE		(1 << 20)
 #define INIT_STREAM		(1 << 1)
 #define DP_SELECT		(1 << 21)
 #define DDIR			(1 << 4)
-#define DMA_EN			0x1
+#define DMAE			0x1
 #define MSBS			(1 << 5)
 #define BCE			(1 << 1)
 #define FOUR_BIT		(1 << 1)
+#define HSPE			(1 << 2)
 #define DDR			(1 << 19)
 #define DW8			(1 << 5)
-#define CC			0x1
-#define TC			0x02
 #define OD			0x1
-#define ERR			(1 << 15)
-#define CMD_TIMEOUT		(1 << 16)
-#define DATA_TIMEOUT		(1 << 20)
-#define CMD_CRC			(1 << 17)
-#define DATA_CRC		(1 << 21)
-#define CARD_ERR		(1 << 28)
 #define STAT_CLEAR		0xFFFFFFFF
 #define INIT_STREAM_CMD		0x00000000
 #define DUAL_VOLT_OCR_BIT	7
@@ -108,6 +97,26 @@
 #define SOFTRESET		(1 << 1)
 #define RESETDONE		(1 << 0)
 
+/* Interrupt masks for IE and ISE register */
+#define CC_EN			(1 << 0)
+#define TC_EN			(1 << 1)
+#define BWR_EN			(1 << 4)
+#define BRR_EN			(1 << 5)
+#define ERR_EN			(1 << 15)
+#define CTO_EN			(1 << 16)
+#define CCRC_EN			(1 << 17)
+#define CEB_EN			(1 << 18)
+#define CIE_EN			(1 << 19)
+#define DTO_EN			(1 << 20)
+#define DCRC_EN			(1 << 21)
+#define DEB_EN			(1 << 22)
+#define CERR_EN			(1 << 28)
+#define BADA_EN			(1 << 29)
+
+#define INT_EN_MASK		(BADA_EN | CERR_EN | DEB_EN | DCRC_EN |\
+		DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \
+		BRR_EN | BWR_EN | TC_EN | CC_EN)
+
 #define MMC_AUTOSUSPEND_DELAY	100
 #define MMC_TIMEOUT_MS		20
 #define OMAP_MMC_MIN_CLOCK	400000
@@ -302,7 +311,7 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
 
 	reg = regulator_get(host->dev, "vmmc");
 	if (IS_ERR(reg)) {
-		dev_dbg(host->dev, "vmmc regulator missing\n");
+		dev_err(host->dev, "vmmc regulator missing\n");
 		return PTR_ERR(reg);
 	} else {
 		mmc_slot(host).set_power = omap_hsmmc_set_power;
@@ -455,13 +464,13 @@ static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host,
 	unsigned int irq_mask;
 
 	if (host->use_dma)
-		irq_mask = INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE);
+		irq_mask = INT_EN_MASK & ~(BRR_EN | BWR_EN);
 	else
 		irq_mask = INT_EN_MASK;
 
 	/* Disable timeout for erases */
 	if (cmd->opcode == MMC_ERASE)
-		irq_mask &= ~DTO_ENABLE;
+		irq_mask &= ~DTO_EN;
 
 	OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
 	OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
@@ -494,6 +503,7 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
 	struct mmc_ios *ios = &host->mmc->ios;
 	unsigned long regval;
 	unsigned long timeout;
+	unsigned long clkdiv;
 
 	dev_vdbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock);
 
@@ -501,7 +511,8 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
 
 	regval = OMAP_HSMMC_READ(host->base, SYSCTL);
 	regval = regval & ~(CLKD_MASK | DTO_MASK);
-	regval = regval | (calc_divisor(host, ios) << 6) | (DTO << 16);
+	clkdiv = calc_divisor(host, ios);
+	regval = regval | (clkdiv << 6) | (DTO << 16);
 	OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
 	OMAP_HSMMC_WRITE(host->base, SYSCTL,
 		OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
@@ -512,6 +523,27 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
 		&& time_before(jiffies, timeout))
 		cpu_relax();
 
+	/*
+	 * Enable High-Speed Support
+	 * Pre-Requisites
+	 *	- Controller should support High-Speed-Enable Bit
+	 *	- Controller should not be using DDR Mode
+	 *	- Controller should advertise that it supports High Speed
+	 *	  in capabilities register
+	 *	- MMC/SD clock coming out of controller > 25MHz
+	 */
+	if ((mmc_slot(host).features & HSMMC_HAS_HSPE_SUPPORT) &&
+	    (ios->timing != MMC_TIMING_UHS_DDR50) &&
+	    ((OMAP_HSMMC_READ(host->base, CAPA) & HSS) == HSS)) {
+		regval = OMAP_HSMMC_READ(host->base, HCTL);
+		if (clkdiv && (clk_get_rate(host->fclk)/clkdiv) > 25000000)
+			regval |= HSPE;
+		else
+			regval &= ~HSPE;
+
+		OMAP_HSMMC_WRITE(host->base, HCTL, regval);
+	}
+
 	omap_hsmmc_start_clock(host);
 }
 
@@ -676,8 +708,8 @@ static void send_init_stream(struct omap_hsmmc_host *host)
 	OMAP_HSMMC_WRITE(host->base, CMD, INIT_STREAM_CMD);
 
 	timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
-	while ((reg != CC) && time_before(jiffies, timeout))
-		reg = OMAP_HSMMC_READ(host->base, STAT) & CC;
+	while ((reg != CC_EN) && time_before(jiffies, timeout))
+		reg = OMAP_HSMMC_READ(host->base, STAT) & CC_EN;
 
 	OMAP_HSMMC_WRITE(host->base, CON,
 		OMAP_HSMMC_READ(host->base, CON) & ~INIT_STREAM);
@@ -768,7 +800,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
 	}
 
 	if (host->use_dma)
-		cmdreg |= DMA_EN;
+		cmdreg |= DMAE;
 
 	host->req_in_progress = 1;
 
@@ -968,16 +1000,20 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,
 			__func__);
 }
 
-static void hsmmc_command_incomplete(struct omap_hsmmc_host *host, int err)
+static void hsmmc_command_incomplete(struct omap_hsmmc_host *host,
+					int err, int end_cmd)
 {
-	omap_hsmmc_reset_controller_fsm(host, SRC);
-	host->cmd->error = err;
+	if (end_cmd) {
+		omap_hsmmc_reset_controller_fsm(host, SRC);
+		if (host->cmd)
+			host->cmd->error = err;
+	}
 
 	if (host->data) {
 		omap_hsmmc_reset_controller_fsm(host, SRD);
 		omap_hsmmc_dma_cleanup(host, err);
-	}
-
+	} else if (host->mrq && host->mrq->cmd)
+		host->mrq->cmd->error = err;
 }
 
 static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
@@ -988,23 +1024,25 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
 	data = host->data;
 	dev_vdbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
 
-	if (status & ERR) {
+	if (status & ERR_EN) {
 		omap_hsmmc_dbg_report_irq(host, status);
-		if (status & (CMD_TIMEOUT | DATA_TIMEOUT))
-			hsmmc_command_incomplete(host, -ETIMEDOUT);
-		else if (status & (CMD_CRC | DATA_CRC))
-			hsmmc_command_incomplete(host, -EILSEQ);
 
-		end_cmd = 1;
+		if (status & (CTO_EN | CCRC_EN))
+			end_cmd = 1;
+		if (status & (CTO_EN | DTO_EN))
+			hsmmc_command_incomplete(host, -ETIMEDOUT, end_cmd);
+		else if (status & (CCRC_EN | DCRC_EN))
+			hsmmc_command_incomplete(host, -EILSEQ, end_cmd);
+
 		if (host->data || host->response_busy) {
-			end_trans = 1;
+			end_trans = !end_cmd;
 			host->response_busy = 0;
 		}
 	}
 
-	if (end_cmd || ((status & CC) && host->cmd))
+	if (end_cmd || ((status & CC_EN) && host->cmd))
 		omap_hsmmc_cmd_done(host, host->cmd);
-	if ((end_trans || (status & TC)) && host->mrq)
+	if ((end_trans || (status & TC_EN)) && host->mrq)
 		omap_hsmmc_xfer_done(host, data);
 }
 
@@ -1101,7 +1139,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd)
 
 	return 0;
 err:
-	dev_dbg(mmc_dev(host->mmc), "Unable to switch operating voltage\n");
+	dev_err(mmc_dev(host->mmc), "Unable to switch operating voltage\n");
 	return ret;
 }
 
@@ -1360,7 +1398,7 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req)
 	if (host->use_dma) {
 		ret = omap_hsmmc_start_dma_transfer(host, req);
 		if (ret != 0) {
-			dev_dbg(mmc_dev(host->mmc), "MMC start dma failure\n");
+			dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
 			return ret;
 		}
 	}
@@ -1678,7 +1716,7 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
 {
 	struct omap_mmc_platform_data *pdata;
 	struct device_node *np = dev->of_node;
-	u32 bus_width;
+	u32 bus_width, max_freq;
 
 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
@@ -1705,6 +1743,12 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
 	if (of_find_property(np, "ti,needs-special-reset", NULL))
 		pdata->slots[0].features |= HSMMC_HAS_UPDATED_RESET;
 
+	if (!of_property_read_u32(np, "max-frequency", &max_freq))
+		pdata->max_freq = max_freq;
+
+	if (of_find_property(np, "ti,needs-special-hs-handling", NULL))
+		pdata->slots[0].features |= HSMMC_HAS_HSPE_SUPPORT;
+
 	return pdata;
 }
 #else
@@ -1715,7 +1759,7 @@ static inline struct omap_mmc_platform_data
 }
 #endif
 
-static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
+static int omap_hsmmc_probe(struct platform_device *pdev)
 {
 	struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
 	struct mmc_host *mmc;
@@ -1725,6 +1769,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
 	const struct of_device_id *match;
 	dma_cap_mask_t mask;
 	unsigned tx_req, rx_req;
+	struct pinctrl *pinctrl;
 
 	match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev);
 	if (match) {
@@ -1821,7 +1866,6 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
 	 * MMC can still work without debounce clock.
 	 */
 	if (IS_ERR(host->dbclk)) {
-		dev_warn(mmc_dev(host->mmc), "Failed to get debounce clk\n");
 		host->dbclk = NULL;
 	} else if (clk_prepare_enable(host->dbclk) != 0) {
 		dev_warn(mmc_dev(host->mmc), "Failed to enable debounce clk\n");
@@ -1889,13 +1933,13 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
 	ret = request_irq(host->irq, omap_hsmmc_irq, 0,
 			mmc_hostname(mmc), host);
 	if (ret) {
-		dev_dbg(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
+		dev_err(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
 		goto err_irq;
 	}
 
 	if (pdata->init != NULL) {
 		if (pdata->init(&pdev->dev) != 0) {
-			dev_dbg(mmc_dev(host->mmc),
+			dev_err(mmc_dev(host->mmc),
 				"Unable to configure MMC IRQs\n");
 			goto err_irq_cd_init;
 		}
@@ -1918,7 +1962,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
 					   IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 					   mmc_hostname(mmc), host);
 		if (ret) {
-			dev_dbg(mmc_dev(host->mmc),
+			dev_err(mmc_dev(host->mmc),
 				"Unable to grab MMC CD IRQ\n");
 			goto err_irq_cd;
 		}
@@ -1928,6 +1972,11 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
 
 	omap_hsmmc_disable_irq(host);
 
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev,
+			"pins are not configured from the driver\n");
+
 	omap_hsmmc_protect_card(host);
 
 	mmc_add_host(mmc);
@@ -1986,7 +2035,7 @@ err:
 	return ret;
 }
 
-static int __devexit omap_hsmmc_remove(struct platform_device *pdev)
+static int omap_hsmmc_remove(struct platform_device *pdev)
 {
 	struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -2027,6 +2076,25 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
+static int omap_hsmmc_prepare(struct device *dev)
+{
+	struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+
+	if (host->pdata->suspend)
+		return host->pdata->suspend(dev, host->slot_id);
+
+	return 0;
+}
+
+static void omap_hsmmc_complete(struct device *dev)
+{
+	struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+
+	if (host->pdata->resume)
+		host->pdata->resume(dev, host->slot_id);
+
+}
+
 static int omap_hsmmc_suspend(struct device *dev)
 {
 	int ret = 0;
@@ -2040,23 +2108,10 @@ static int omap_hsmmc_suspend(struct device *dev)
 
 	pm_runtime_get_sync(host->dev);
 	host->suspended = 1;
-	if (host->pdata->suspend) {
-		ret = host->pdata->suspend(dev, host->slot_id);
-		if (ret) {
-			dev_dbg(dev, "Unable to handle MMC board"
-					" level suspend\n");
-			host->suspended = 0;
-			return ret;
-		}
-	}
 	ret = mmc_suspend_host(host->mmc);
 
 	if (ret) {
 		host->suspended = 0;
-		if (host->pdata->resume) {
-			if (host->pdata->resume(dev, host->slot_id))
-				dev_dbg(dev, "Unmask interrupt failed\n");
-		}
 		goto err;
 	}
 
@@ -2093,12 +2148,6 @@ static int omap_hsmmc_resume(struct device *dev)
 	if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER))
 		omap_hsmmc_conf_bus_power(host);
 
-	if (host->pdata->resume) {
-		ret = host->pdata->resume(dev, host->slot_id);
-		if (ret)
-			dev_dbg(dev, "Unmask interrupt failed\n");
-	}
-
 	omap_hsmmc_protect_card(host);
 
 	/* Notify the core to resume the host */
@@ -2114,8 +2163,10 @@ static int omap_hsmmc_resume(struct device *dev)
 }
 
 #else
+#define omap_hsmmc_prepare	NULL
+#define omap_hsmmc_complete	NULL
 #define omap_hsmmc_suspend	NULL
-#define omap_hsmmc_resume		NULL
+#define omap_hsmmc_resume	NULL
 #endif
 
 static int omap_hsmmc_runtime_suspend(struct device *dev)
@@ -2143,13 +2194,15 @@ static int omap_hsmmc_runtime_resume(struct device *dev)
 static struct dev_pm_ops omap_hsmmc_dev_pm_ops = {
 	.suspend	= omap_hsmmc_suspend,
 	.resume		= omap_hsmmc_resume,
+	.prepare	= omap_hsmmc_prepare,
+	.complete	= omap_hsmmc_complete,
 	.runtime_suspend = omap_hsmmc_runtime_suspend,
 	.runtime_resume = omap_hsmmc_runtime_resume,
 };
 
 static struct platform_driver omap_hsmmc_driver = {
 	.probe		= omap_hsmmc_probe,
-	.remove		= __devexit_p(omap_hsmmc_remove),
+	.remove		= omap_hsmmc_remove,
 	.driver		= {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 3f9d6d5..2b2f65a 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -584,7 +584,7 @@ static const struct of_device_id pxa_mmc_dt_ids[] = {
 
 MODULE_DEVICE_TABLE(of, pxa_mmc_dt_ids);
 
-static int __devinit pxamci_of_init(struct platform_device *pdev)
+static int pxamci_of_init(struct platform_device *pdev)
 {
         struct device_node *np = pdev->dev.of_node;
         struct pxamci_platform_data *pdata;
@@ -614,7 +614,7 @@ static int __devinit pxamci_of_init(struct platform_device *pdev)
         return 0;
 }
 #else
-static int __devinit pxamci_of_init(struct platform_device *pdev)
+static int pxamci_of_init(struct platform_device *pdev)
 {
         return 0;
 }
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
new file mode 100644
index 0000000..571915d
--- /dev/null
+++ b/drivers/mmc/host/rtsx_pci_sdmmc.c
@@ -0,0 +1,1348 @@
+/* Realtek PCI-Express SD/MMC Card Interface driver
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+#include <linux/mmc/card.h>
+#include <linux/mfd/rtsx_pci.h>
+#include <asm/unaligned.h>
+
+/* SD Tuning Data Structure
+ * Record continuous timing phase path
+ */
+struct timing_phase_path {
+	int start;
+	int end;
+	int mid;
+	int len;
+};
+
+struct realtek_pci_sdmmc {
+	struct platform_device	*pdev;
+	struct rtsx_pcr		*pcr;
+	struct mmc_host		*mmc;
+	struct mmc_request	*mrq;
+
+	struct mutex		host_mutex;
+
+	u8			ssc_depth;
+	unsigned int		clock;
+	bool			vpclk;
+	bool			double_clk;
+	bool			eject;
+	bool			initial_mode;
+	bool			ddr_mode;
+};
+
+static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host)
+{
+	return &(host->pdev->dev);
+}
+
+static inline void sd_clear_error(struct realtek_pci_sdmmc *host)
+{
+	rtsx_pci_write_register(host->pcr, CARD_STOP,
+			SD_STOP | SD_CLR_ERR, SD_STOP | SD_CLR_ERR);
+}
+
+#ifdef DEBUG
+static void sd_print_debug_regs(struct realtek_pci_sdmmc *host)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	u16 i;
+	u8 *ptr;
+
+	/* Print SD host internal registers */
+	rtsx_pci_init_cmd(pcr);
+	for (i = 0xFDA0; i <= 0xFDAE; i++)
+		rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
+	for (i = 0xFD52; i <= 0xFD69; i++)
+		rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
+	rtsx_pci_send_cmd(pcr, 100);
+
+	ptr = rtsx_pci_get_cmd_data(pcr);
+	for (i = 0xFDA0; i <= 0xFDAE; i++)
+		dev_dbg(sdmmc_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
+	for (i = 0xFD52; i <= 0xFD69; i++)
+		dev_dbg(sdmmc_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
+}
+#else
+#define sd_print_debug_regs(host)
+#endif /* DEBUG */
+
+static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt,
+		u8 *buf, int buf_len, int timeout)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	int err, i;
+	u8 trans_mode;
+
+	dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD%d\n", __func__, cmd[0] - 0x40);
+
+	if (!buf)
+		buf_len = 0;
+
+	if ((cmd[0] & 0x3F) == MMC_SEND_TUNING_BLOCK)
+		trans_mode = SD_TM_AUTO_TUNING;
+	else
+		trans_mode = SD_TM_NORMAL_READ;
+
+	rtsx_pci_init_cmd(pcr);
+
+	for (i = 0; i < 5; i++)
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD0 + i, 0xFF, cmd[i]);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H,
+			0xFF, (u8)(byte_cnt >> 8));
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF,
+			SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
+			SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6);
+	if (trans_mode != SD_TM_AUTO_TUNING)
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+				CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER,
+			0xFF, trans_mode | SD_TRANSFER_START);
+	rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER,
+			SD_TRANSFER_END, SD_TRANSFER_END);
+
+	err = rtsx_pci_send_cmd(pcr, timeout);
+	if (err < 0) {
+		sd_print_debug_regs(host);
+		dev_dbg(sdmmc_dev(host),
+			"rtsx_pci_send_cmd fail (err = %d)\n", err);
+		return err;
+	}
+
+	if (buf && buf_len) {
+		err = rtsx_pci_read_ppbuf(pcr, buf, buf_len);
+		if (err < 0) {
+			dev_dbg(sdmmc_dev(host),
+				"rtsx_pci_read_ppbuf fail (err = %d)\n", err);
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+static int sd_write_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt,
+		u8 *buf, int buf_len, int timeout)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	int err, i;
+	u8 trans_mode;
+
+	if (!buf)
+		buf_len = 0;
+
+	if (buf && buf_len) {
+		err = rtsx_pci_write_ppbuf(pcr, buf, buf_len);
+		if (err < 0) {
+			dev_dbg(sdmmc_dev(host),
+				"rtsx_pci_write_ppbuf fail (err = %d)\n", err);
+			return err;
+		}
+	}
+
+	trans_mode = cmd ? SD_TM_AUTO_WRITE_2 : SD_TM_AUTO_WRITE_3;
+	rtsx_pci_init_cmd(pcr);
+
+	if (cmd) {
+		dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d\n", __func__,
+				cmd[0] - 0x40);
+
+		for (i = 0; i < 5; i++)
+			rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+					SD_CMD0 + i, 0xFF, cmd[i]);
+	}
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H,
+			0xFF, (u8)(byte_cnt >> 8));
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF,
+		SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
+		SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
+			trans_mode | SD_TRANSFER_START);
+	rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER,
+			SD_TRANSFER_END, SD_TRANSFER_END);
+
+	err = rtsx_pci_send_cmd(pcr, timeout);
+	if (err < 0) {
+		sd_print_debug_regs(host);
+		dev_dbg(sdmmc_dev(host),
+			"rtsx_pci_send_cmd fail (err = %d)\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
+		struct mmc_command *cmd)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	u8 cmd_idx = (u8)cmd->opcode;
+	u32 arg = cmd->arg;
+	int err = 0;
+	int timeout = 100;
+	int i;
+	u8 *ptr;
+	int stat_idx = 0;
+	u8 rsp_type;
+	int rsp_len = 5;
+
+	dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n",
+			__func__, cmd_idx, arg);
+
+	/* Response type:
+	 * R0
+	 * R1, R5, R6, R7
+	 * R1b
+	 * R2
+	 * R3, R4
+	 */
+	switch (mmc_resp_type(cmd)) {
+	case MMC_RSP_NONE:
+		rsp_type = SD_RSP_TYPE_R0;
+		rsp_len = 0;
+		break;
+	case MMC_RSP_R1:
+		rsp_type = SD_RSP_TYPE_R1;
+		break;
+	case MMC_RSP_R1B:
+		rsp_type = SD_RSP_TYPE_R1b;
+		break;
+	case MMC_RSP_R2:
+		rsp_type = SD_RSP_TYPE_R2;
+		rsp_len = 16;
+		break;
+	case MMC_RSP_R3:
+		rsp_type = SD_RSP_TYPE_R3;
+		break;
+	default:
+		dev_dbg(sdmmc_dev(host), "cmd->flag is not valid\n");
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (rsp_type == SD_RSP_TYPE_R1b)
+		timeout = 3000;
+
+	if (cmd->opcode == SD_SWITCH_VOLTAGE) {
+		err = rtsx_pci_write_register(pcr, SD_BUS_STAT,
+				0xFF, SD_CLK_TOGGLE_EN);
+		if (err < 0)
+			goto out;
+	}
+
+	rtsx_pci_init_cmd(pcr);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD0, 0xFF, 0x40 | cmd_idx);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD1, 0xFF, (u8)(arg >> 24));
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD2, 0xFF, (u8)(arg >> 16));
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD3, 0xFF, (u8)(arg >> 8));
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8)arg);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+			0x01, PINGPONG_BUFFER);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER,
+			0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
+	rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER,
+		     SD_TRANSFER_END | SD_STAT_IDLE,
+		     SD_TRANSFER_END | SD_STAT_IDLE);
+
+	if (rsp_type == SD_RSP_TYPE_R2) {
+		/* Read data from ping-pong buffer */
+		for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++)
+			rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0);
+		stat_idx = 16;
+	} else if (rsp_type != SD_RSP_TYPE_R0) {
+		/* Read data from SD_CMDx registers */
+		for (i = SD_CMD0; i <= SD_CMD4; i++)
+			rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0);
+		stat_idx = 5;
+	}
+
+	rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0);
+
+	err = rtsx_pci_send_cmd(pcr, timeout);
+	if (err < 0) {
+		sd_print_debug_regs(host);
+		sd_clear_error(host);
+		dev_dbg(sdmmc_dev(host),
+			"rtsx_pci_send_cmd error (err = %d)\n", err);
+		goto out;
+	}
+
+	if (rsp_type == SD_RSP_TYPE_R0) {
+		err = 0;
+		goto out;
+	}
+
+	/* Eliminate returned value of CHECK_REG_CMD */
+	ptr = rtsx_pci_get_cmd_data(pcr) + 1;
+
+	/* Check (Start,Transmission) bit of Response */
+	if ((ptr[0] & 0xC0) != 0) {
+		err = -EILSEQ;
+		dev_dbg(sdmmc_dev(host), "Invalid response bit\n");
+		goto out;
+	}
+
+	/* Check CRC7 */
+	if (!(rsp_type & SD_NO_CHECK_CRC7)) {
+		if (ptr[stat_idx] & SD_CRC7_ERR) {
+			err = -EILSEQ;
+			dev_dbg(sdmmc_dev(host), "CRC7 error\n");
+			goto out;
+		}
+	}
+
+	if (rsp_type == SD_RSP_TYPE_R2) {
+		for (i = 0; i < 4; i++) {
+			cmd->resp[i] = get_unaligned_be32(ptr + 1 + i * 4);
+			dev_dbg(sdmmc_dev(host), "cmd->resp[%d] = 0x%08x\n",
+					i, cmd->resp[i]);
+		}
+	} else {
+		cmd->resp[0] = get_unaligned_be32(ptr + 1);
+		dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n",
+				cmd->resp[0]);
+	}
+
+out:
+	cmd->error = err;
+}
+
+static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	struct mmc_host *mmc = host->mmc;
+	struct mmc_card *card = mmc->card;
+	struct mmc_data *data = mrq->data;
+	int uhs = mmc_sd_card_uhs(card);
+	int read = (data->flags & MMC_DATA_READ) ? 1 : 0;
+	u8 cfg2, trans_mode;
+	int err;
+	size_t data_len = data->blksz * data->blocks;
+
+	if (read) {
+		cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
+			SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0;
+		trans_mode = SD_TM_AUTO_READ_3;
+	} else {
+		cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 |
+			SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0;
+		trans_mode = SD_TM_AUTO_WRITE_3;
+	}
+
+	if (!uhs)
+		cfg2 |= SD_NO_CHECK_WAIT_CRC_TO;
+
+	rtsx_pci_init_cmd(pcr);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L,
+			0xFF, (u8)data->blocks);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H,
+			0xFF, (u8)(data->blocks >> 8));
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0,
+			DMA_DONE_INT, DMA_DONE_INT);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3,
+			0xFF, (u8)(data_len >> 24));
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2,
+			0xFF, (u8)(data_len >> 16));
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1,
+			0xFF, (u8)(data_len >> 8));
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)data_len);
+	if (read) {
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL,
+				0x03 | DMA_PACK_SIZE_MASK,
+				DMA_DIR_FROM_CARD | DMA_EN | DMA_512);
+	} else {
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL,
+				0x03 | DMA_PACK_SIZE_MASK,
+				DMA_DIR_TO_CARD | DMA_EN | DMA_512);
+	}
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+			0x01, RING_BUFFER);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, cfg2);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
+			trans_mode | SD_TRANSFER_START);
+	rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER,
+			SD_TRANSFER_END, SD_TRANSFER_END);
+
+	rtsx_pci_send_cmd_no_wait(pcr);
+
+	err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000);
+	if (err < 0) {
+		sd_clear_error(host);
+		return err;
+	}
+
+	return 0;
+}
+
+static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host)
+{
+	rtsx_pci_write_register(host->pcr, SD_CFG1,
+			SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_128);
+}
+
+static inline void sd_disable_initial_mode(struct realtek_pci_sdmmc *host)
+{
+	rtsx_pci_write_register(host->pcr, SD_CFG1,
+			SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0);
+}
+
+static void sd_normal_rw(struct realtek_pci_sdmmc *host,
+		struct mmc_request *mrq)
+{
+	struct mmc_command *cmd = mrq->cmd;
+	struct mmc_data *data = mrq->data;
+	u8 _cmd[5], *buf;
+
+	_cmd[0] = 0x40 | (u8)cmd->opcode;
+	put_unaligned_be32(cmd->arg, (u32 *)(&_cmd[1]));
+
+	buf = kzalloc(data->blksz, GFP_NOIO);
+	if (!buf) {
+		cmd->error = -ENOMEM;
+		return;
+	}
+
+	if (data->flags & MMC_DATA_READ) {
+		if (host->initial_mode)
+			sd_disable_initial_mode(host);
+
+		cmd->error = sd_read_data(host, _cmd, (u16)data->blksz, buf,
+				data->blksz, 200);
+
+		if (host->initial_mode)
+			sd_enable_initial_mode(host);
+
+		sg_copy_from_buffer(data->sg, data->sg_len, buf, data->blksz);
+	} else {
+		sg_copy_to_buffer(data->sg, data->sg_len, buf, data->blksz);
+
+		cmd->error = sd_write_data(host, _cmd, (u16)data->blksz, buf,
+				data->blksz, 200);
+	}
+
+	kfree(buf);
+}
+
+static int sd_change_phase(struct realtek_pci_sdmmc *host, u8 sample_point)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	int err;
+
+	dev_dbg(sdmmc_dev(host), "%s: sample_point = %d\n",
+			__func__, sample_point);
+
+	rtsx_pci_init_cmd(pcr);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CHANGE_CLK, CHANGE_CLK);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPRX_CTL, 0x1F, sample_point);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+			PHASE_NOT_RESET, PHASE_NOT_RESET);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CHANGE_CLK, 0);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0);
+
+	err = rtsx_pci_send_cmd(pcr, 100);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static u8 sd_search_final_phase(struct realtek_pci_sdmmc *host, u32 phase_map)
+{
+	struct timing_phase_path path[MAX_PHASE + 1];
+	int i, j, cont_path_cnt;
+	int new_block, max_len, final_path_idx;
+	u8 final_phase = 0xFF;
+
+	/* Parse phase_map, take it as a bit-ring */
+	cont_path_cnt = 0;
+	new_block = 1;
+	j = 0;
+	for (i = 0; i < MAX_PHASE + 1; i++) {
+		if (phase_map & (1 << i)) {
+			if (new_block) {
+				new_block = 0;
+				j = cont_path_cnt++;
+				path[j].start = i;
+				path[j].end = i;
+			} else {
+				path[j].end = i;
+			}
+		} else {
+			new_block = 1;
+			if (cont_path_cnt) {
+				/* Calculate path length and middle point */
+				int idx = cont_path_cnt - 1;
+				path[idx].len =
+					path[idx].end - path[idx].start + 1;
+				path[idx].mid =
+					path[idx].start + path[idx].len / 2;
+			}
+		}
+	}
+
+	if (cont_path_cnt == 0) {
+		dev_dbg(sdmmc_dev(host), "No continuous phase path\n");
+		goto finish;
+	} else {
+		/* Calculate last continuous path length and middle point */
+		int idx = cont_path_cnt - 1;
+		path[idx].len = path[idx].end - path[idx].start + 1;
+		path[idx].mid = path[idx].start + path[idx].len / 2;
+	}
+
+	/* Connect the first and last continuous paths if they are adjacent */
+	if (!path[0].start && (path[cont_path_cnt - 1].end == MAX_PHASE)) {
+		/* Using negative index */
+		path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1;
+		path[0].len += path[cont_path_cnt - 1].len;
+		path[0].mid = path[0].start + path[0].len / 2;
+		/* Convert negative middle point index to positive one */
+		if (path[0].mid < 0)
+			path[0].mid += MAX_PHASE + 1;
+		cont_path_cnt--;
+	}
+
+	/* Choose the longest continuous phase path */
+	max_len = 0;
+	final_phase = 0;
+	final_path_idx = 0;
+	for (i = 0; i < cont_path_cnt; i++) {
+		if (path[i].len > max_len) {
+			max_len = path[i].len;
+			final_phase = (u8)path[i].mid;
+			final_path_idx = i;
+		}
+
+		dev_dbg(sdmmc_dev(host), "path[%d].start = %d\n",
+				i, path[i].start);
+		dev_dbg(sdmmc_dev(host), "path[%d].end = %d\n",
+				i, path[i].end);
+		dev_dbg(sdmmc_dev(host), "path[%d].len = %d\n",
+				i, path[i].len);
+		dev_dbg(sdmmc_dev(host), "path[%d].mid = %d\n",
+				i, path[i].mid);
+	}
+
+finish:
+	dev_dbg(sdmmc_dev(host), "Final chosen phase: %d\n", final_phase);
+	return final_phase;
+}
+
+static void sd_wait_data_idle(struct realtek_pci_sdmmc *host)
+{
+	int err, i;
+	u8 val = 0;
+
+	for (i = 0; i < 100; i++) {
+		err = rtsx_pci_read_register(host->pcr, SD_DATA_STATE, &val);
+		if (val & SD_DATA_IDLE)
+			return;
+
+		udelay(100);
+	}
+}
+
+static int sd_tuning_rx_cmd(struct realtek_pci_sdmmc *host,
+		u8 opcode, u8 sample_point)
+{
+	int err;
+	u8 cmd[5] = {0};
+
+	err = sd_change_phase(host, sample_point);
+	if (err < 0)
+		return err;
+
+	cmd[0] = 0x40 | opcode;
+	err = sd_read_data(host, cmd, 0x40, NULL, 0, 100);
+	if (err < 0) {
+		/* Wait till SD DATA IDLE */
+		sd_wait_data_idle(host);
+		sd_clear_error(host);
+		return err;
+	}
+
+	return 0;
+}
+
+static int sd_tuning_phase(struct realtek_pci_sdmmc *host,
+		u8 opcode, u32 *phase_map)
+{
+	int err, i;
+	u32 raw_phase_map = 0;
+
+	for (i = MAX_PHASE; i >= 0; i--) {
+		err = sd_tuning_rx_cmd(host, opcode, (u8)i);
+		if (err == 0)
+			raw_phase_map |= 1 << i;
+	}
+
+	if (phase_map)
+		*phase_map = raw_phase_map;
+
+	return 0;
+}
+
+static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode)
+{
+	int err, i;
+	u32 raw_phase_map[RX_TUNING_CNT] = {0}, phase_map;
+	u8 final_phase;
+
+	for (i = 0; i < RX_TUNING_CNT; i++) {
+		err = sd_tuning_phase(host, opcode, &(raw_phase_map[i]));
+		if (err < 0)
+			return err;
+
+		if (raw_phase_map[i] == 0)
+			break;
+	}
+
+	phase_map = 0xFFFFFFFF;
+	for (i = 0; i < RX_TUNING_CNT; i++) {
+		dev_dbg(sdmmc_dev(host), "RX raw_phase_map[%d] = 0x%08x\n",
+				i, raw_phase_map[i]);
+		phase_map &= raw_phase_map[i];
+	}
+	dev_dbg(sdmmc_dev(host), "RX phase_map = 0x%08x\n", phase_map);
+
+	if (phase_map) {
+		final_phase = sd_search_final_phase(host, phase_map);
+		if (final_phase == 0xFF)
+			return -EINVAL;
+
+		err = sd_change_phase(host, final_phase);
+		if (err < 0)
+			return err;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+	struct rtsx_pcr *pcr = host->pcr;
+	struct mmc_command *cmd = mrq->cmd;
+	struct mmc_data *data = mrq->data;
+	unsigned int data_size = 0;
+
+	if (host->eject) {
+		cmd->error = -ENOMEDIUM;
+		goto finish;
+	}
+
+	mutex_lock(&pcr->pcr_mutex);
+
+	rtsx_pci_start_run(pcr);
+
+	rtsx_pci_switch_clock(pcr, host->clock, host->ssc_depth,
+			host->initial_mode, host->double_clk, host->vpclk);
+	rtsx_pci_write_register(pcr, CARD_SELECT, 0x07, SD_MOD_SEL);
+	rtsx_pci_write_register(pcr, CARD_SHARE_MODE,
+			CARD_SHARE_MASK, CARD_SHARE_48_SD);
+
+	mutex_lock(&host->host_mutex);
+	host->mrq = mrq;
+	mutex_unlock(&host->host_mutex);
+
+	if (mrq->data)
+		data_size = data->blocks * data->blksz;
+
+	if (!data_size || mmc_op_multi(cmd->opcode) ||
+			(cmd->opcode == MMC_READ_SINGLE_BLOCK) ||
+			(cmd->opcode == MMC_WRITE_BLOCK)) {
+		sd_send_cmd_get_rsp(host, cmd);
+
+		if (!cmd->error && data_size) {
+			sd_rw_multi(host, mrq);
+
+			if (mmc_op_multi(cmd->opcode) && mrq->stop)
+				sd_send_cmd_get_rsp(host, mrq->stop);
+		}
+	} else {
+		sd_normal_rw(host, mrq);
+	}
+
+	if (mrq->data) {
+		if (cmd->error || data->error)
+			data->bytes_xfered = 0;
+		else
+			data->bytes_xfered = data->blocks * data->blksz;
+	}
+
+	mutex_unlock(&pcr->pcr_mutex);
+
+finish:
+	if (cmd->error)
+		dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error);
+
+	mutex_lock(&host->host_mutex);
+	host->mrq = NULL;
+	mutex_unlock(&host->host_mutex);
+
+	mmc_request_done(mmc, mrq);
+}
+
+static int sd_set_bus_width(struct realtek_pci_sdmmc *host,
+		unsigned char bus_width)
+{
+	int err = 0;
+	u8 width[] = {
+		[MMC_BUS_WIDTH_1] = SD_BUS_WIDTH_1BIT,
+		[MMC_BUS_WIDTH_4] = SD_BUS_WIDTH_4BIT,
+		[MMC_BUS_WIDTH_8] = SD_BUS_WIDTH_8BIT,
+	};
+
+	if (bus_width <= MMC_BUS_WIDTH_8)
+		err = rtsx_pci_write_register(host->pcr, SD_CFG1,
+				0x03, width[bus_width]);
+
+	return err;
+}
+
+static int sd_power_on(struct realtek_pci_sdmmc *host)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	int err;
+
+	rtsx_pci_init_cmd(pcr);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE,
+			CARD_SHARE_MASK, CARD_SHARE_48_SD);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN,
+			SD_CLK_EN, SD_CLK_EN);
+	err = rtsx_pci_send_cmd(pcr, 100);
+	if (err < 0)
+		return err;
+
+	err = rtsx_pci_card_pull_ctl_enable(pcr, RTSX_SD_CARD);
+	if (err < 0)
+		return err;
+
+	err = rtsx_pci_card_power_on(pcr, RTSX_SD_CARD);
+	if (err < 0)
+		return err;
+
+	err = rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int sd_power_off(struct realtek_pci_sdmmc *host)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	int err;
+
+	rtsx_pci_init_cmd(pcr);
+
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0);
+	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE, SD_OUTPUT_EN, 0);
+
+	err = rtsx_pci_send_cmd(pcr, 100);
+	if (err < 0)
+		return err;
+
+	err = rtsx_pci_card_power_off(pcr, RTSX_SD_CARD);
+	if (err < 0)
+		return err;
+
+	return rtsx_pci_card_pull_ctl_disable(pcr, RTSX_SD_CARD);
+}
+
+static int sd_set_power_mode(struct realtek_pci_sdmmc *host,
+		unsigned char power_mode)
+{
+	int err;
+
+	if (power_mode == MMC_POWER_OFF)
+		err = sd_power_off(host);
+	else
+		err = sd_power_on(host);
+
+	return err;
+}
+
+static int sd_set_timing(struct realtek_pci_sdmmc *host,
+		unsigned char timing, bool *ddr_mode)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	int err = 0;
+
+	*ddr_mode = false;
+
+	rtsx_pci_init_cmd(pcr);
+
+	switch (timing) {
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_UHS_SDR50:
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1,
+				0x0C | SD_ASYNC_FIFO_NOT_RST,
+				SD_30_MODE | SD_ASYNC_FIFO_NOT_RST);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
+				CLK_LOW_FREQ, CLK_LOW_FREQ);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF,
+				CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0);
+		break;
+
+	case MMC_TIMING_UHS_DDR50:
+		*ddr_mode = true;
+
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1,
+				0x0C | SD_ASYNC_FIFO_NOT_RST,
+				SD_DDR_MODE | SD_ASYNC_FIFO_NOT_RST);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
+				CLK_LOW_FREQ, CLK_LOW_FREQ);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF,
+				CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_PUSH_POINT_CTL,
+				DDR_VAR_TX_CMD_DAT, DDR_VAR_TX_CMD_DAT);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL,
+				DDR_VAR_RX_DAT | DDR_VAR_RX_CMD,
+				DDR_VAR_RX_DAT | DDR_VAR_RX_CMD);
+		break;
+
+	case MMC_TIMING_MMC_HS:
+	case MMC_TIMING_SD_HS:
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1,
+				0x0C, SD_20_MODE);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
+				CLK_LOW_FREQ, CLK_LOW_FREQ);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF,
+				CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_PUSH_POINT_CTL,
+				SD20_TX_SEL_MASK, SD20_TX_14_AHEAD);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL,
+				SD20_RX_SEL_MASK, SD20_RX_14_DELAY);
+		break;
+
+	default:
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+				SD_CFG1, 0x0C, SD_20_MODE);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
+				CLK_LOW_FREQ, CLK_LOW_FREQ);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF,
+				CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+				SD_PUSH_POINT_CTL, 0xFF, 0);
+		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL,
+				SD20_RX_SEL_MASK, SD20_RX_POS_EDGE);
+		break;
+	}
+
+	err = rtsx_pci_send_cmd(pcr, 100);
+
+	return err;
+}
+
+static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+	struct rtsx_pcr *pcr = host->pcr;
+
+	if (host->eject)
+		return;
+
+	mutex_lock(&pcr->pcr_mutex);
+
+	rtsx_pci_start_run(pcr);
+
+	sd_set_bus_width(host, ios->bus_width);
+	sd_set_power_mode(host, ios->power_mode);
+	sd_set_timing(host, ios->timing, &host->ddr_mode);
+
+	host->vpclk = false;
+	host->double_clk = true;
+
+	switch (ios->timing) {
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_UHS_SDR50:
+		host->ssc_depth = RTSX_SSC_DEPTH_2M;
+		host->vpclk = true;
+		host->double_clk = false;
+		break;
+	case MMC_TIMING_UHS_DDR50:
+	case MMC_TIMING_UHS_SDR25:
+		host->ssc_depth = RTSX_SSC_DEPTH_1M;
+		break;
+	default:
+		host->ssc_depth = RTSX_SSC_DEPTH_500K;
+		break;
+	}
+
+	host->initial_mode = (ios->clock <= 1000000) ? true : false;
+
+	host->clock = ios->clock;
+	rtsx_pci_switch_clock(pcr, ios->clock, host->ssc_depth,
+			host->initial_mode, host->double_clk, host->vpclk);
+
+	mutex_unlock(&pcr->pcr_mutex);
+}
+
+static int sdmmc_get_ro(struct mmc_host *mmc)
+{
+	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+	struct rtsx_pcr *pcr = host->pcr;
+	int ro = 0;
+	u32 val;
+
+	if (host->eject)
+		return -ENOMEDIUM;
+
+	mutex_lock(&pcr->pcr_mutex);
+
+	rtsx_pci_start_run(pcr);
+
+	/* Check SD mechanical write-protect switch */
+	val = rtsx_pci_readl(pcr, RTSX_BIPR);
+	dev_dbg(sdmmc_dev(host), "%s: RTSX_BIPR = 0x%08x\n", __func__, val);
+	if (val & SD_WRITE_PROTECT)
+		ro = 1;
+
+	mutex_unlock(&pcr->pcr_mutex);
+
+	return ro;
+}
+
+static int sdmmc_get_cd(struct mmc_host *mmc)
+{
+	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+	struct rtsx_pcr *pcr = host->pcr;
+	int cd = 0;
+	u32 val;
+
+	if (host->eject)
+		return -ENOMEDIUM;
+
+	mutex_lock(&pcr->pcr_mutex);
+
+	rtsx_pci_start_run(pcr);
+
+	/* Check SD card detect */
+	val = rtsx_pci_card_exist(pcr);
+	dev_dbg(sdmmc_dev(host), "%s: RTSX_BIPR = 0x%08x\n", __func__, val);
+	if (val & SD_EXIST)
+		cd = 1;
+
+	mutex_unlock(&pcr->pcr_mutex);
+
+	return cd;
+}
+
+static int sd_wait_voltage_stable_1(struct realtek_pci_sdmmc *host)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	int err;
+	u8 stat;
+
+	/* Reference to Signal Voltage Switch Sequence in SD spec.
+	 * Wait for a period of time so that the card can drive SD_CMD and
+	 * SD_DAT[3:0] to low after sending back CMD11 response.
+	 */
+	mdelay(1);
+
+	/* SD_CMD, SD_DAT[3:0] should be driven to low by card;
+	 * If either one of SD_CMD,SD_DAT[3:0] is not low,
+	 * abort the voltage switch sequence;
+	 */
+	err = rtsx_pci_read_register(pcr, SD_BUS_STAT, &stat);
+	if (err < 0)
+		return err;
+
+	if (stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
+				SD_DAT1_STATUS | SD_DAT0_STATUS))
+		return -EINVAL;
+
+	/* Stop toggle SD clock */
+	err = rtsx_pci_write_register(pcr, SD_BUS_STAT,
+			0xFF, SD_CLK_FORCE_STOP);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int sd_wait_voltage_stable_2(struct realtek_pci_sdmmc *host)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	int err;
+	u8 stat, mask, val;
+
+	/* Wait 1.8V output of voltage regulator in card stable */
+	msleep(50);
+
+	/* Toggle SD clock again */
+	err = rtsx_pci_write_register(pcr, SD_BUS_STAT, 0xFF, SD_CLK_TOGGLE_EN);
+	if (err < 0)
+		return err;
+
+	/* Wait for a period of time so that the card can drive
+	 * SD_DAT[3:0] to high at 1.8V
+	 */
+	msleep(20);
+
+	/* SD_CMD, SD_DAT[3:0] should be pulled high by host */
+	err = rtsx_pci_read_register(pcr, SD_BUS_STAT, &stat);
+	if (err < 0)
+		return err;
+
+	mask = SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
+		SD_DAT1_STATUS | SD_DAT0_STATUS;
+	val = SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
+		SD_DAT1_STATUS | SD_DAT0_STATUS;
+	if ((stat & mask) != val) {
+		dev_dbg(sdmmc_dev(host),
+			"%s: SD_BUS_STAT = 0x%x\n", __func__, stat);
+		rtsx_pci_write_register(pcr, SD_BUS_STAT,
+				SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
+		rtsx_pci_write_register(pcr, CARD_CLK_EN, 0xFF, 0);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int sd_change_bank_voltage(struct realtek_pci_sdmmc *host, u8 voltage)
+{
+	struct rtsx_pcr *pcr = host->pcr;
+	int err;
+
+	if (voltage == SD_IO_3V3) {
+		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
+		if (err < 0)
+			return err;
+	} else if (voltage == SD_IO_1V8) {
+		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
+		if (err < 0)
+			return err;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+	struct rtsx_pcr *pcr = host->pcr;
+	int err = 0;
+	u8 voltage;
+
+	dev_dbg(sdmmc_dev(host), "%s: signal_voltage = %d\n",
+			__func__, ios->signal_voltage);
+
+	if (host->eject)
+		return -ENOMEDIUM;
+
+	mutex_lock(&pcr->pcr_mutex);
+
+	rtsx_pci_start_run(pcr);
+
+	if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330)
+		voltage = SD_IO_3V3;
+	else
+		voltage = SD_IO_1V8;
+
+	if (voltage == SD_IO_1V8) {
+		err = rtsx_pci_write_register(pcr,
+				SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B);
+		if (err < 0)
+			goto out;
+
+		err = sd_wait_voltage_stable_1(host);
+		if (err < 0)
+			goto out;
+	}
+
+	err = sd_change_bank_voltage(host, voltage);
+	if (err < 0)
+		goto out;
+
+	if (voltage == SD_IO_1V8) {
+		err = sd_wait_voltage_stable_2(host);
+		if (err < 0)
+			goto out;
+	}
+
+	/* Stop toggle SD clock in idle */
+	err = rtsx_pci_write_register(pcr, SD_BUS_STAT,
+			SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
+
+out:
+	mutex_unlock(&pcr->pcr_mutex);
+
+	return err;
+}
+
+static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+	struct rtsx_pcr *pcr = host->pcr;
+	int err = 0;
+
+	if (host->eject)
+		return -ENOMEDIUM;
+
+	mutex_lock(&pcr->pcr_mutex);
+
+	rtsx_pci_start_run(pcr);
+
+	if (!host->ddr_mode)
+		err = sd_tuning_rx(host, MMC_SEND_TUNING_BLOCK);
+
+	mutex_unlock(&pcr->pcr_mutex);
+
+	return err;
+}
+
+static const struct mmc_host_ops realtek_pci_sdmmc_ops = {
+	.request = sdmmc_request,
+	.set_ios = sdmmc_set_ios,
+	.get_ro = sdmmc_get_ro,
+	.get_cd = sdmmc_get_cd,
+	.start_signal_voltage_switch = sdmmc_switch_voltage,
+	.execute_tuning = sdmmc_execute_tuning,
+};
+
+#ifdef CONFIG_PM
+static int rtsx_pci_sdmmc_suspend(struct platform_device *pdev,
+		pm_message_t state)
+{
+	struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
+	struct mmc_host *mmc = host->mmc;
+	int err;
+
+	dev_dbg(sdmmc_dev(host), "--> %s\n", __func__);
+
+	err = mmc_suspend_host(mmc);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int rtsx_pci_sdmmc_resume(struct platform_device *pdev)
+{
+	struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
+	struct mmc_host *mmc = host->mmc;
+
+	dev_dbg(sdmmc_dev(host), "--> %s\n", __func__);
+
+	return mmc_resume_host(mmc);
+}
+#else /* CONFIG_PM */
+#define rtsx_pci_sdmmc_suspend NULL
+#define rtsx_pci_sdmmc_resume NULL
+#endif /* CONFIG_PM */
+
+static void init_extra_caps(struct realtek_pci_sdmmc *host)
+{
+	struct mmc_host *mmc = host->mmc;
+	struct rtsx_pcr *pcr = host->pcr;
+
+	dev_dbg(sdmmc_dev(host), "pcr->extra_caps = 0x%x\n", pcr->extra_caps);
+
+	if (pcr->extra_caps & EXTRA_CAPS_SD_SDR50)
+		mmc->caps |= MMC_CAP_UHS_SDR50;
+	if (pcr->extra_caps & EXTRA_CAPS_SD_SDR104)
+		mmc->caps |= MMC_CAP_UHS_SDR104;
+	if (pcr->extra_caps & EXTRA_CAPS_SD_DDR50)
+		mmc->caps |= MMC_CAP_UHS_DDR50;
+	if (pcr->extra_caps & EXTRA_CAPS_MMC_HSDDR)
+		mmc->caps |= MMC_CAP_1_8V_DDR;
+	if (pcr->extra_caps & EXTRA_CAPS_MMC_8BIT)
+		mmc->caps |= MMC_CAP_8_BIT_DATA;
+}
+
+static void realtek_init_host(struct realtek_pci_sdmmc *host)
+{
+	struct mmc_host *mmc = host->mmc;
+
+	mmc->f_min = 250000;
+	mmc->f_max = 208000000;
+	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED |
+		MMC_CAP_MMC_HIGHSPEED | MMC_CAP_BUS_WIDTH_TEST |
+		MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25;
+	mmc->max_current_330 = 400;
+	mmc->max_current_180 = 800;
+	mmc->ops = &realtek_pci_sdmmc_ops;
+
+	init_extra_caps(host);
+
+	mmc->max_segs = 256;
+	mmc->max_seg_size = 65536;
+	mmc->max_blk_size = 512;
+	mmc->max_blk_count = 65535;
+	mmc->max_req_size = 524288;
+}
+
+static void rtsx_pci_sdmmc_card_event(struct platform_device *pdev)
+{
+	struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
+
+	mmc_detect_change(host->mmc, 0);
+}
+
+static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
+{
+	struct mmc_host *mmc;
+	struct realtek_pci_sdmmc *host;
+	struct rtsx_pcr *pcr;
+	struct pcr_handle *handle = pdev->dev.platform_data;
+
+	if (!handle)
+		return -ENXIO;
+
+	pcr = handle->pcr;
+	if (!pcr)
+		return -ENXIO;
+
+	dev_dbg(&(pdev->dev), ": Realtek PCI-E SDMMC controller found\n");
+
+	mmc = mmc_alloc_host(sizeof(*host), &pdev->dev);
+	if (!mmc)
+		return -ENOMEM;
+
+	host = mmc_priv(mmc);
+	host->pcr = pcr;
+	host->mmc = mmc;
+	host->pdev = pdev;
+	platform_set_drvdata(pdev, host);
+	pcr->slots[RTSX_SD_CARD].p_dev = pdev;
+	pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event;
+
+	mutex_init(&host->host_mutex);
+
+	realtek_init_host(host);
+
+	mmc_add_host(mmc);
+
+	return 0;
+}
+
+static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
+{
+	struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
+	struct rtsx_pcr *pcr;
+	struct mmc_host *mmc;
+
+	if (!host)
+		return 0;
+
+	pcr = host->pcr;
+	pcr->slots[RTSX_SD_CARD].p_dev = NULL;
+	pcr->slots[RTSX_SD_CARD].card_event = NULL;
+	mmc = host->mmc;
+	host->eject = true;
+
+	mutex_lock(&host->host_mutex);
+	if (host->mrq) {
+		dev_dbg(&(pdev->dev),
+			"%s: Controller removed during transfer\n",
+			mmc_hostname(mmc));
+
+		rtsx_pci_complete_unfinished_transfer(pcr);
+
+		host->mrq->cmd->error = -ENOMEDIUM;
+		if (host->mrq->stop)
+			host->mrq->stop->error = -ENOMEDIUM;
+		mmc_request_done(mmc, host->mrq);
+	}
+	mutex_unlock(&host->host_mutex);
+
+	mmc_remove_host(mmc);
+	mmc_free_host(mmc);
+
+	platform_set_drvdata(pdev, NULL);
+
+	dev_dbg(&(pdev->dev),
+		": Realtek PCI-E SDMMC controller has been removed\n");
+
+	return 0;
+}
+
+static struct platform_device_id rtsx_pci_sdmmc_ids[] = {
+	{
+		.name = DRV_NAME_RTSX_PCI_SDMMC,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, rtsx_pci_sdmmc_ids);
+
+static struct platform_driver rtsx_pci_sdmmc_driver = {
+	.probe		= rtsx_pci_sdmmc_drv_probe,
+	.remove		= rtsx_pci_sdmmc_drv_remove,
+	.id_table       = rtsx_pci_sdmmc_ids,
+	.suspend	= rtsx_pci_sdmmc_suspend,
+	.resume		= rtsx_pci_sdmmc_resume,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= DRV_NAME_RTSX_PCI_SDMMC,
+	},
+};
+module_platform_driver(rtsx_pci_sdmmc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Wei WANG <wei_wang@realsil.com.cn>");
+MODULE_DESCRIPTION("Realtek PCI-E SD/MMC Card Host Driver");
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 4638dda..63fb265 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -1540,7 +1540,7 @@ static inline void s3cmci_debugfs_remove(struct s3cmci_host *host) { }
 
 #endif /* CONFIG_DEBUG_FS */
 
-static int __devinit s3cmci_probe(struct platform_device *pdev)
+static int s3cmci_probe(struct platform_device *pdev)
 {
 	struct s3cmci_host *host;
 	struct mmc_host	*mmc;
@@ -1819,7 +1819,7 @@ static void s3cmci_shutdown(struct platform_device *pdev)
 	clk_disable(host->clk);
 }
 
-static int __devexit s3cmci_remove(struct platform_device *pdev)
+static int s3cmci_remove(struct platform_device *pdev)
 {
 	struct mmc_host		*mmc  = platform_get_drvdata(pdev);
 	struct s3cmci_host	*host = mmc_priv(mmc);
@@ -1906,7 +1906,7 @@ static struct platform_driver s3cmci_driver = {
 	},
 	.id_table	= s3cmci_driver_ids,
 	.probe		= s3cmci_probe,
-	.remove		= __devexit_p(s3cmci_remove),
+	.remove		= s3cmci_remove,
 	.shutdown	= s3cmci_shutdown,
 };
 
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
new file mode 100644
index 0000000..6ac3617
--- /dev/null
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -0,0 +1,304 @@
+/*
+ * Secure Digital Host Controller Interface ACPI driver.
+ *
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/compiler.h>
+#include <linux/stddef.h>
+#include <linux/bitops.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/acpi.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/pm.h>
+#include <linux/mmc/sdhci.h>
+
+#include "sdhci.h"
+
+enum {
+	SDHCI_ACPI_SD_CD	= BIT(0),
+	SDHCI_ACPI_RUNTIME_PM	= BIT(1),
+};
+
+struct sdhci_acpi_chip {
+	const struct	sdhci_ops *ops;
+	unsigned int	quirks;
+	unsigned int	quirks2;
+	unsigned long	caps;
+	unsigned int	caps2;
+	mmc_pm_flag_t	pm_caps;
+};
+
+struct sdhci_acpi_slot {
+	const struct	sdhci_acpi_chip *chip;
+	unsigned int	quirks;
+	unsigned int	quirks2;
+	unsigned long	caps;
+	unsigned int	caps2;
+	mmc_pm_flag_t	pm_caps;
+	unsigned int	flags;
+};
+
+struct sdhci_acpi_host {
+	struct sdhci_host		*host;
+	const struct sdhci_acpi_slot	*slot;
+	struct platform_device		*pdev;
+	bool				use_runtime_pm;
+};
+
+static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag)
+{
+	return c->slot && (c->slot->flags & flag);
+}
+
+static int sdhci_acpi_enable_dma(struct sdhci_host *host)
+{
+	return 0;
+}
+
+static const struct sdhci_ops sdhci_acpi_ops_dflt = {
+	.enable_dma = sdhci_acpi_enable_dma,
+};
+
+static const struct acpi_device_id sdhci_acpi_ids[] = {
+	{ "PNP0D40" },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids);
+
+static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(const char *hid)
+{
+	const struct acpi_device_id *id;
+
+	for (id = sdhci_acpi_ids; id->id[0]; id++)
+		if (!strcmp(id->id, hid))
+			return (const struct sdhci_acpi_slot *)id->driver_data;
+	return NULL;
+}
+
+static int __devinit sdhci_acpi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	acpi_handle handle = ACPI_HANDLE(dev);
+	struct acpi_device *device;
+	struct sdhci_acpi_host *c;
+	struct sdhci_host *host;
+	struct resource *iomem;
+	resource_size_t len;
+	const char *hid;
+	int err;
+
+	if (acpi_bus_get_device(handle, &device))
+		return -ENODEV;
+
+	if (acpi_bus_get_status(device) || !device->status.present)
+		return -ENODEV;
+
+	hid = acpi_device_hid(device);
+
+	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!iomem)
+		return -ENOMEM;
+
+	len = resource_size(iomem);
+	if (len < 0x100)
+		dev_err(dev, "Invalid iomem size!\n");
+
+	if (!devm_request_mem_region(dev, iomem->start, len, dev_name(dev)))
+		return -ENOMEM;
+
+	host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host));
+	if (IS_ERR(host))
+		return PTR_ERR(host);
+
+	c = sdhci_priv(host);
+	c->host = host;
+	c->slot = sdhci_acpi_get_slot(hid);
+	c->pdev = pdev;
+	c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM);
+
+	platform_set_drvdata(pdev, c);
+
+	host->hw_name	= "ACPI";
+	host->ops	= &sdhci_acpi_ops_dflt;
+	host->irq	= platform_get_irq(pdev, 0);
+
+	host->ioaddr = devm_ioremap_nocache(dev, iomem->start,
+					    resource_size(iomem));
+	if (host->ioaddr == NULL) {
+		err = -ENOMEM;
+		goto err_free;
+	}
+
+	if (!dev->dma_mask) {
+		u64 dma_mask;
+
+		if (sdhci_readl(host, SDHCI_CAPABILITIES) & SDHCI_CAN_64BIT) {
+			/* 64-bit DMA is not supported at present */
+			dma_mask = DMA_BIT_MASK(32);
+		} else {
+			dma_mask = DMA_BIT_MASK(32);
+		}
+
+		dev->dma_mask = &dev->coherent_dma_mask;
+		dev->coherent_dma_mask = dma_mask;
+	}
+
+	if (c->slot) {
+		if (c->slot->chip) {
+			host->ops            = c->slot->chip->ops;
+			host->quirks        |= c->slot->chip->quirks;
+			host->quirks2       |= c->slot->chip->quirks2;
+			host->mmc->caps     |= c->slot->chip->caps;
+			host->mmc->caps2    |= c->slot->chip->caps2;
+			host->mmc->pm_caps  |= c->slot->chip->pm_caps;
+		}
+		host->quirks        |= c->slot->quirks;
+		host->quirks2       |= c->slot->quirks2;
+		host->mmc->caps     |= c->slot->caps;
+		host->mmc->caps2    |= c->slot->caps2;
+		host->mmc->pm_caps  |= c->slot->pm_caps;
+	}
+
+	err = sdhci_add_host(host);
+	if (err)
+		goto err_free;
+
+	if (c->use_runtime_pm) {
+		pm_suspend_ignore_children(dev, 1);
+		pm_runtime_set_autosuspend_delay(dev, 50);
+		pm_runtime_use_autosuspend(dev);
+		pm_runtime_enable(dev);
+	}
+
+	return 0;
+
+err_free:
+	platform_set_drvdata(pdev, NULL);
+	sdhci_free_host(c->host);
+	return err;
+}
+
+static int __devexit sdhci_acpi_remove(struct platform_device *pdev)
+{
+	struct sdhci_acpi_host *c = platform_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;
+	int dead;
+
+	if (c->use_runtime_pm) {
+		pm_runtime_get_sync(dev);
+		pm_runtime_disable(dev);
+		pm_runtime_put_noidle(dev);
+	}
+
+	dead = (sdhci_readl(c->host, SDHCI_INT_STATUS) == ~0);
+	sdhci_remove_host(c->host, dead);
+	platform_set_drvdata(pdev, NULL);
+	sdhci_free_host(c->host);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int sdhci_acpi_suspend(struct device *dev)
+{
+	struct sdhci_acpi_host *c = dev_get_drvdata(dev);
+
+	return sdhci_suspend_host(c->host);
+}
+
+static int sdhci_acpi_resume(struct device *dev)
+{
+	struct sdhci_acpi_host *c = dev_get_drvdata(dev);
+
+	return sdhci_resume_host(c->host);
+}
+
+#else
+
+#define sdhci_acpi_suspend	NULL
+#define sdhci_acpi_resume	NULL
+
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+
+static int sdhci_acpi_runtime_suspend(struct device *dev)
+{
+	struct sdhci_acpi_host *c = dev_get_drvdata(dev);
+
+	return sdhci_runtime_suspend_host(c->host);
+}
+
+static int sdhci_acpi_runtime_resume(struct device *dev)
+{
+	struct sdhci_acpi_host *c = dev_get_drvdata(dev);
+
+	return sdhci_runtime_resume_host(c->host);
+}
+
+static int sdhci_acpi_runtime_idle(struct device *dev)
+{
+	return 0;
+}
+
+#else
+
+#define sdhci_acpi_runtime_suspend	NULL
+#define sdhci_acpi_runtime_resume	NULL
+#define sdhci_acpi_runtime_idle		NULL
+
+#endif
+
+static const struct dev_pm_ops sdhci_acpi_pm_ops = {
+	.suspend		= sdhci_acpi_suspend,
+	.resume			= sdhci_acpi_resume,
+	.runtime_suspend	= sdhci_acpi_runtime_suspend,
+	.runtime_resume		= sdhci_acpi_runtime_resume,
+	.runtime_idle		= sdhci_acpi_runtime_idle,
+};
+
+static struct platform_driver sdhci_acpi_driver = {
+	.driver = {
+		.name			= "sdhci-acpi",
+		.owner			= THIS_MODULE,
+		.acpi_match_table	= sdhci_acpi_ids,
+		.pm			= &sdhci_acpi_pm_ops,
+	},
+	.probe	= sdhci_acpi_probe,
+	.remove	= __devexit_p(sdhci_acpi_remove),
+};
+
+module_platform_driver(sdhci_acpi_driver);
+
+MODULE_DESCRIPTION("Secure Digital Host Controller Interface ACPI driver");
+MODULE_AUTHOR("Adrian Hunter");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c
index 28a8708..30bfdc4 100644
--- a/drivers/mmc/host/sdhci-cns3xxx.c
+++ b/drivers/mmc/host/sdhci-cns3xxx.c
@@ -95,12 +95,12 @@ static struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
 		  SDHCI_QUIRK_NONSTANDARD_CLOCK,
 };
 
-static int __devinit sdhci_cns3xxx_probe(struct platform_device *pdev)
+static int sdhci_cns3xxx_probe(struct platform_device *pdev)
 {
 	return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata);
 }
 
-static int __devexit sdhci_cns3xxx_remove(struct platform_device *pdev)
+static int sdhci_cns3xxx_remove(struct platform_device *pdev)
 {
 	return sdhci_pltfm_unregister(pdev);
 }
@@ -112,7 +112,7 @@ static struct platform_driver sdhci_cns3xxx_driver = {
 		.pm	= SDHCI_PLTFM_PMOPS,
 	},
 	.probe		= sdhci_cns3xxx_probe,
-	.remove		= __devexit_p(sdhci_cns3xxx_remove),
+	.remove		= sdhci_cns3xxx_remove,
 };
 
 module_platform_driver(sdhci_cns3xxx_driver);
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c
index 8fd50a2..6511213 100644
--- a/drivers/mmc/host/sdhci-dove.c
+++ b/drivers/mmc/host/sdhci-dove.c
@@ -22,7 +22,6 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/clk.h>
-#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/mmc/host.h>
 #include <linux/of.h>
@@ -78,7 +77,7 @@ static struct sdhci_pltfm_data sdhci_dove_pdata = {
 		  SDHCI_QUIRK_NO_HISPD_BIT,
 };
 
-static int __devinit sdhci_dove_probe(struct platform_device *pdev)
+static int sdhci_dove_probe(struct platform_device *pdev)
 {
 	struct sdhci_host *host;
 	struct sdhci_pltfm_host *pltfm_host;
@@ -114,7 +113,7 @@ sdhci_dove_register_fail:
 	return ret;
 }
 
-static int __devexit sdhci_dove_remove(struct platform_device *pdev)
+static int sdhci_dove_remove(struct platform_device *pdev)
 {
 	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -129,7 +128,7 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = {
+static const struct of_device_id sdhci_dove_of_match_table[] = {
 	{ .compatible = "marvell,dove-sdhci", },
 	{}
 };
@@ -143,7 +142,7 @@ static struct platform_driver sdhci_dove_driver = {
 		.of_match_table = of_match_ptr(sdhci_dove_of_match_table),
 	},
 	.probe		= sdhci_dove_probe,
-	.remove		= __devexit_p(sdhci_dove_remove),
+	.remove		= sdhci_dove_remove,
 };
 
 module_platform_driver(sdhci_dove_driver);
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index effc2ac..8d54fd7 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -403,7 +403,7 @@ static irqreturn_t cd_irq(int irq, void *data)
 };
 
 #ifdef CONFIG_OF
-static int __devinit
+static int
 sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
 			 struct esdhc_platform_data *boarddata)
 {
@@ -440,7 +440,7 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
 }
 #endif
 
-static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
+static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id =
 			of_match_device(imx_esdhc_dt_ids, &pdev->dev);
@@ -599,7 +599,7 @@ err_imx_data:
 	return err;
 }
 
-static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
+static int sdhci_esdhc_imx_remove(struct platform_device *pdev)
 {
 	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -637,7 +637,7 @@ static struct platform_driver sdhci_esdhc_imx_driver = {
 	},
 	.id_table	= imx_esdhc_devtype,
 	.probe		= sdhci_esdhc_imx_probe,
-	.remove		= __devexit_p(sdhci_esdhc_imx_remove),
+	.remove		= sdhci_esdhc_imx_remove,
 };
 
 module_platform_driver(sdhci_esdhc_imx_driver);
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 63d219f..e751beb 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -177,6 +177,9 @@ static void esdhc_of_platform_init(struct sdhci_host *host)
 	vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
 	if (vvn == VENDOR_V_22)
 		host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
+
+	if (vvn > VENDOR_V_22)
+		host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
 }
 
 static struct sdhci_ops sdhci_esdhc_ops = {
@@ -208,12 +211,12 @@ static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
 	.ops = &sdhci_esdhc_ops,
 };
 
-static int __devinit sdhci_esdhc_probe(struct platform_device *pdev)
+static int sdhci_esdhc_probe(struct platform_device *pdev)
 {
 	return sdhci_pltfm_register(pdev, &sdhci_esdhc_pdata);
 }
 
-static int __devexit sdhci_esdhc_remove(struct platform_device *pdev)
+static int sdhci_esdhc_remove(struct platform_device *pdev)
 {
 	return sdhci_pltfm_unregister(pdev);
 }
@@ -234,7 +237,7 @@ static struct platform_driver sdhci_esdhc_driver = {
 		.pm = SDHCI_PLTFM_PMOPS,
 	},
 	.probe = sdhci_esdhc_probe,
-	.remove = __devexit_p(sdhci_esdhc_remove),
+	.remove = sdhci_esdhc_remove,
 };
 
 module_platform_driver(sdhci_esdhc_driver);
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
index 0ce088a..c3d3715 100644
--- a/drivers/mmc/host/sdhci-of-hlwd.c
+++ b/drivers/mmc/host/sdhci-of-hlwd.c
@@ -66,12 +66,12 @@ static struct sdhci_pltfm_data sdhci_hlwd_pdata = {
 	.ops = &sdhci_hlwd_ops,
 };
 
-static int __devinit sdhci_hlwd_probe(struct platform_device *pdev)
+static int sdhci_hlwd_probe(struct platform_device *pdev)
 {
 	return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata);
 }
 
-static int __devexit sdhci_hlwd_remove(struct platform_device *pdev)
+static int sdhci_hlwd_remove(struct platform_device *pdev)
 {
 	return sdhci_pltfm_unregister(pdev);
 }
@@ -90,7 +90,7 @@ static struct platform_driver sdhci_hlwd_driver = {
 		.pm = SDHCI_PLTFM_PMOPS,
 	},
 	.probe = sdhci_hlwd_probe,
-	.remove = __devexit_p(sdhci_hlwd_remove),
+	.remove = sdhci_hlwd_remove,
 };
 
 module_platform_driver(sdhci_hlwd_driver);
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 04936f3..d01aa61 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -653,7 +653,7 @@ static const struct sdhci_pci_fixes sdhci_via = {
 	.probe		= via_probe,
 };
 
-static const struct pci_device_id pci_ids[] __devinitconst = {
+static const struct pci_device_id pci_ids[] = {
 	{
 		.vendor		= PCI_VENDOR_ID_RICOH,
 		.device		= PCI_DEVICE_ID_RICOH_R5C822,
@@ -1183,7 +1183,7 @@ static const struct dev_pm_ops sdhci_pci_pm_ops = {
  *                                                                           *
 \*****************************************************************************/
 
-static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
+static struct sdhci_pci_slot *sdhci_pci_probe_slot(
 	struct pci_dev *pdev, struct sdhci_pci_chip *chip, int first_bar,
 	int slotno)
 {
@@ -1338,7 +1338,7 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
 	sdhci_free_host(slot->host);
 }
 
-static void __devinit sdhci_pci_runtime_pm_allow(struct device *dev)
+static void sdhci_pci_runtime_pm_allow(struct device *dev)
 {
 	pm_runtime_put_noidle(dev);
 	pm_runtime_allow(dev);
@@ -1347,13 +1347,13 @@ static void __devinit sdhci_pci_runtime_pm_allow(struct device *dev)
 	pm_suspend_ignore_children(dev, 1);
 }
 
-static void __devexit sdhci_pci_runtime_pm_forbid(struct device *dev)
+static void sdhci_pci_runtime_pm_forbid(struct device *dev)
 {
 	pm_runtime_forbid(dev);
 	pm_runtime_get_noresume(dev);
 }
 
-static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
+static int sdhci_pci_probe(struct pci_dev *pdev,
 				     const struct pci_device_id *ent)
 {
 	struct sdhci_pci_chip *chip;
@@ -1445,7 +1445,7 @@ err:
 	return ret;
 }
 
-static void __devexit sdhci_pci_remove(struct pci_dev *pdev)
+static void sdhci_pci_remove(struct pci_dev *pdev)
 {
 	int i;
 	struct sdhci_pci_chip *chip;
@@ -1470,7 +1470,7 @@ static struct pci_driver sdhci_driver = {
 	.name =		"sdhci-pci",
 	.id_table =	pci_ids,
 	.probe =	sdhci_pci_probe,
-	.remove =	__devexit_p(sdhci_pci_remove),
+	.remove =	sdhci_pci_remove,
 	.driver =	{
 		.pm =   &sdhci_pci_pm_ops
 	},
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index 2716445..c6c3b12 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -89,6 +89,12 @@ void sdhci_get_of_property(struct platform_device *pdev)
 		clk = of_get_property(np, "clock-frequency", &size);
 		if (clk && size == sizeof(*clk) && *clk)
 			pltfm_host->clock = be32_to_cpup(clk);
+
+		if (of_find_property(np, "keep-power-in-suspend", NULL))
+			host->mmc->pm_caps |= MMC_PM_KEEP_POWER;
+
+		if (of_find_property(np, "enable-sdio-wakeup", NULL))
+			host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
 	}
 }
 #else
diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
index 8e63a9c..ac854aa 100644
--- a/drivers/mmc/host/sdhci-pxav2.c
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -166,7 +166,7 @@ static inline struct sdhci_pxa_platdata *pxav2_get_mmc_pdata(struct device *dev)
 }
 #endif
 
-static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
+static int sdhci_pxav2_probe(struct platform_device *pdev)
 {
 	struct sdhci_pltfm_host *pltfm_host;
 	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
@@ -247,7 +247,7 @@ err_clk_get:
 	return ret;
 }
 
-static int __devexit sdhci_pxav2_remove(struct platform_device *pdev)
+static int sdhci_pxav2_remove(struct platform_device *pdev)
 {
 	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -275,7 +275,7 @@ static struct platform_driver sdhci_pxav2_driver = {
 		.pm	= SDHCI_PLTFM_PMOPS,
 	},
 	.probe		= sdhci_pxav2_probe,
-	.remove		= __devexit_p(sdhci_pxav2_remove),
+	.remove		= sdhci_pxav2_remove,
 };
 
 module_platform_driver(sdhci_pxav2_driver);
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
index e918a2b..fad0966 100644
--- a/drivers/mmc/host/sdhci-pxav3.c
+++ b/drivers/mmc/host/sdhci-pxav3.c
@@ -163,10 +163,18 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 	return 0;
 }
 
+static u32 pxav3_get_max_clock(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+	return clk_get_rate(pltfm_host->clk);
+}
+
 static struct sdhci_ops pxav3_sdhci_ops = {
 	.platform_reset_exit = pxav3_set_private_registers,
 	.set_uhs_signaling = pxav3_set_uhs_signaling,
 	.platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
+	.get_max_clock = pxav3_get_max_clock,
 };
 
 #ifdef CONFIG_OF
@@ -214,7 +222,7 @@ static inline struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
 }
 #endif
 
-static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
+static int sdhci_pxav3_probe(struct platform_device *pdev)
 {
 	struct sdhci_pltfm_host *pltfm_host;
 	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
@@ -249,7 +257,8 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
 
 	host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
 		| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
-		| SDHCI_QUIRK_32BIT_ADMA_SIZE;
+		| SDHCI_QUIRK_32BIT_ADMA_SIZE
+		| SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
 
 	/* enable 1/8V DDR capable */
 	host->mmc->caps |= MMC_CAP_1_8V_DDR;
@@ -271,6 +280,8 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
 
 		if (pdata->quirks)
 			host->quirks |= pdata->quirks;
+		if (pdata->quirks2)
+			host->quirks2 |= pdata->quirks2;
 		if (pdata->host_caps)
 			host->mmc->caps |= pdata->host_caps;
 		if (pdata->host_caps2)
@@ -313,7 +324,7 @@ err_clk_get:
 	return ret;
 }
 
-static int __devexit sdhci_pxav3_remove(struct platform_device *pdev)
+static int sdhci_pxav3_remove(struct platform_device *pdev)
 {
 	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -346,7 +357,7 @@ static struct platform_driver sdhci_pxav3_driver = {
 		.pm	= SDHCI_PLTFM_PMOPS,
 	},
 	.probe		= sdhci_pxav3_probe,
-	.remove		= __devexit_p(sdhci_pxav3_remove),
+	.remove		= sdhci_pxav3_remove,
 };
 
 module_platform_driver(sdhci_pxav3_driver);
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index a54dd5d..7ea3aea 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -24,6 +24,7 @@
 #include <linux/of_gpio.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
 
 #include <linux/mmc/host.h>
 
@@ -57,6 +58,7 @@ struct sdhci_s3c {
 	int			ext_cd_irq;
 	int			ext_cd_gpio;
 	int			*gpios;
+	struct pinctrl          *pctrl;
 
 	struct clk		*clk_io;
 	struct clk		*clk_bus[MAX_BUS_CLK];
@@ -373,18 +375,25 @@ static struct sdhci_ops sdhci_s3c_ops = {
 static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
 {
 	struct sdhci_host *host = platform_get_drvdata(dev);
+	struct sdhci_s3c *sc = sdhci_priv(host);
 	unsigned long flags;
 
 	if (host) {
 		spin_lock_irqsave(&host->lock, flags);
 		if (state) {
 			dev_dbg(&dev->dev, "card inserted.\n");
+#ifdef CONFIG_PM_RUNTIME
+			clk_prepare_enable(sc->clk_io);
+#endif
 			host->flags &= ~SDHCI_DEVICE_DEAD;
 			host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
 		} else {
 			dev_dbg(&dev->dev, "card removed.\n");
 			host->flags |= SDHCI_DEVICE_DEAD;
 			host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+#ifdef CONFIG_PM_RUNTIME
+			clk_disable_unprepare(sc->clk_io);
+#endif
 		}
 		tasklet_schedule(&host->card_tasklet);
 		spin_unlock_irqrestore(&host->lock, flags);
@@ -406,7 +415,7 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
 	struct s3c_sdhci_platdata *pdata = sc->pdata;
 	struct device *dev = &sc->pdev->dev;
 
-	if (gpio_request(pdata->ext_cd_gpio, "SDHCI EXT CD") == 0) {
+	if (devm_gpio_request(dev, pdata->ext_cd_gpio, "SDHCI EXT CD") == 0) {
 		sc->ext_cd_gpio = pdata->ext_cd_gpio;
 		sc->ext_cd_irq = gpio_to_irq(pdata->ext_cd_gpio);
 		if (sc->ext_cd_irq &&
@@ -430,7 +439,7 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
 }
 
 #ifdef CONFIG_OF
-static int __devinit sdhci_s3c_parse_dt(struct device *dev,
+static int sdhci_s3c_parse_dt(struct device *dev,
 		struct sdhci_host *host, struct s3c_sdhci_platdata *pdata)
 {
 	struct device_node *node = dev->of_node;
@@ -449,12 +458,12 @@ static int __devinit sdhci_s3c_parse_dt(struct device *dev,
 		return -ENOMEM;
 
 	/* get the card detection method */
-	if (of_get_property(node, "broken-cd", 0)) {
+	if (of_get_property(node, "broken-cd", NULL)) {
 		pdata->cd_type = S3C_SDHCI_CD_NONE;
 		goto setup_bus;
 	}
 
-	if (of_get_property(node, "non-removable", 0)) {
+	if (of_get_property(node, "non-removable", NULL)) {
 		pdata->cd_type = S3C_SDHCI_CD_PERMANENT;
 		goto setup_bus;
 	}
@@ -477,8 +486,9 @@ static int __devinit sdhci_s3c_parse_dt(struct device *dev,
 		return -EINVAL;
 	}
 
-	dev_info(dev, "assuming no card detect line available\n");
-	pdata->cd_type = S3C_SDHCI_CD_NONE;
+	/* assuming internal card detect that will be configured by pinctrl */
+	pdata->cd_type = S3C_SDHCI_CD_INTERNAL;
+	goto setup_bus;
 
  found_cd:
 	if (pdata->cd_type == S3C_SDHCI_CD_GPIO) {
@@ -487,7 +497,7 @@ static int __devinit sdhci_s3c_parse_dt(struct device *dev,
 		if (of_get_property(node, "cd-inverted", NULL))
 			pdata->ext_cd_gpio_invert = 1;
 	} else if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		ret = gpio_request(gpio, "sdhci-cd");
+		ret = devm_gpio_request(dev, gpio, "sdhci-cd");
 		if (ret) {
 			dev_err(dev, "card detect gpio request failed\n");
 			return -EINVAL;
@@ -496,36 +506,31 @@ static int __devinit sdhci_s3c_parse_dt(struct device *dev,
 	}
 
  setup_bus:
+	if (!IS_ERR(ourhost->pctrl))
+		return 0;
+
 	/* get the gpios for command, clock and data lines */
 	for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) {
 		gpio = of_get_gpio(node, cnt);
 		if (!gpio_is_valid(gpio)) {
 			dev_err(dev, "invalid gpio[%d]\n", cnt);
-			goto err_free_dt_cd_gpio;
+			return -EINVAL;
 		}
 		ourhost->gpios[cnt] = gpio;
 	}
 
 	for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) {
-		ret = gpio_request(ourhost->gpios[cnt], "sdhci-gpio");
+		ret = devm_gpio_request(dev, ourhost->gpios[cnt], "sdhci-gpio");
 		if (ret) {
 			dev_err(dev, "gpio[%d] request failed\n", cnt);
-			goto err_free_dt_gpios;
+			return -EINVAL;
 		}
 	}
 
 	return 0;
-
- err_free_dt_gpios:
-	while (--cnt >= 0)
-		gpio_free(ourhost->gpios[cnt]);
- err_free_dt_cd_gpio:
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL)
-		gpio_free(ourhost->ext_cd_gpio);
-	return -EINVAL;
 }
 #else
-static int __devinit sdhci_s3c_parse_dt(struct device *dev,
+static int sdhci_s3c_parse_dt(struct device *dev,
 		struct sdhci_host *host, struct s3c_sdhci_platdata *pdata)
 {
 	return -EINVAL;
@@ -548,7 +553,7 @@ static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data(
 			platform_get_device_id(pdev)->driver_data;
 }
 
-static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
+static int sdhci_s3c_probe(struct platform_device *pdev)
 {
 	struct s3c_sdhci_platdata *pdata;
 	struct sdhci_s3c_drv_data *drv_data;
@@ -579,13 +584,15 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata) {
 		ret = -ENOMEM;
-		goto err_pdata;
+		goto err_pdata_io_clk;
 	}
 
+	sc->pctrl = devm_pinctrl_get_select_default(&pdev->dev);
+
 	if (pdev->dev.of_node) {
 		ret = sdhci_s3c_parse_dt(&pdev->dev, host, pdata);
 		if (ret)
-			goto err_pdata;
+			goto err_pdata_io_clk;
 	} else {
 		memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));
 		sc->ext_cd_gpio = -1; /* invalid gpio number */
@@ -603,7 +610,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
 	if (IS_ERR(sc->clk_io)) {
 		dev_err(dev, "failed to get io clock\n");
 		ret = PTR_ERR(sc->clk_io);
-		goto err_io_clk;
+		goto err_pdata_io_clk;
 	}
 
 	/* enable the local io clock and keep it running for the moment. */
@@ -766,19 +773,13 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
 	clk_disable_unprepare(sc->clk_io);
 	clk_put(sc->clk_io);
 
- err_io_clk:
-	for (ptr = 0; ptr < NUM_GPIOS(sc->pdata->max_width); ptr++)
-		gpio_free(sc->gpios[ptr]);
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL)
-		gpio_free(sc->ext_cd_gpio);
-
- err_pdata:
+ err_pdata_io_clk:
 	sdhci_free_host(host);
 
 	return ret;
 }
 
-static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
+static int sdhci_s3c_remove(struct platform_device *pdev)
 {
 	struct sdhci_host *host =  platform_get_drvdata(pdev);
 	struct sdhci_s3c *sc = sdhci_priv(host);
@@ -791,9 +792,6 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
 	if (sc->ext_cd_irq)
 		free_irq(sc->ext_cd_irq, sc);
 
-	if (gpio_is_valid(sc->ext_cd_gpio))
-		gpio_free(sc->ext_cd_gpio);
-
 #ifdef CONFIG_PM_RUNTIME
 	if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
 		clk_prepare_enable(sc->clk_io);
@@ -814,11 +812,6 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
 	clk_disable_unprepare(sc->clk_io);
 	clk_put(sc->clk_io);
 
-	if (pdev->dev.of_node) {
-		for (ptr = 0; ptr < NUM_GPIOS(sc->pdata->max_width); ptr++)
-			gpio_free(sc->gpios[ptr]);
-	}
-
 	sdhci_free_host(host);
 	platform_set_drvdata(pdev, NULL);
 
@@ -916,7 +909,7 @@ MODULE_DEVICE_TABLE(of, sdhci_s3c_dt_match);
 
 static struct platform_driver sdhci_s3c_driver = {
 	.probe		= sdhci_s3c_probe,
-	.remove		= __devexit_p(sdhci_s3c_remove),
+	.remove		= sdhci_s3c_remove,
 	.id_table	= sdhci_s3c_driver_ids,
 	.driver		= {
 		.owner	= THIS_MODULE,
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c
index 6be89c0..c6ece0b 100644
--- a/drivers/mmc/host/sdhci-spear.c
+++ b/drivers/mmc/host/sdhci-spear.c
@@ -71,8 +71,7 @@ static irqreturn_t sdhci_gpio_irq(int irq, void *dev_id)
 }
 
 #ifdef CONFIG_OF
-static struct sdhci_plat_data * __devinit
-sdhci_probe_config_dt(struct platform_device *pdev)
+static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct sdhci_plat_data *pdata = NULL;
@@ -96,14 +95,13 @@ sdhci_probe_config_dt(struct platform_device *pdev)
 	return pdata;
 }
 #else
-static struct sdhci_plat_data * __devinit
-sdhci_probe_config_dt(struct platform_device *pdev)
+static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev)
 {
 	return ERR_PTR(-ENOSYS);
 }
 #endif
 
-static int __devinit sdhci_probe(struct platform_device *pdev)
+static int sdhci_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct sdhci_host *host;
@@ -146,6 +144,11 @@ static int __devinit sdhci_probe(struct platform_device *pdev)
 		goto put_clk;
 	}
 
+	ret = clk_set_rate(sdhci->clk, 50000000);
+	if (ret)
+		dev_dbg(&pdev->dev, "Error setting desired clk, clk=%lu\n",
+				clk_get_rate(sdhci->clk));
+
 	if (np) {
 		sdhci->data = sdhci_probe_config_dt(pdev);
 		if (IS_ERR(sdhci->data)) {
@@ -268,7 +271,7 @@ err:
 	return ret;
 }
 
-static int __devexit sdhci_remove(struct platform_device *pdev)
+static int sdhci_remove(struct platform_device *pdev)
 {
 	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev);
@@ -297,7 +300,7 @@ static int sdhci_suspend(struct device *dev)
 
 	ret = sdhci_suspend_host(host);
 	if (!ret)
-		clk_disable_unprepare(sdhci->clk);
+		clk_disable(sdhci->clk);
 
 	return ret;
 }
@@ -308,7 +311,7 @@ static int sdhci_resume(struct device *dev)
 	struct spear_sdhci *sdhci = dev_get_platdata(dev);
 	int ret;
 
-	ret = clk_prepare_enable(sdhci->clk);
+	ret = clk_enable(sdhci->clk);
 	if (ret) {
 		dev_dbg(dev, "Resume: Error enabling clock\n");
 		return ret;
@@ -336,7 +339,7 @@ static struct platform_driver sdhci_driver = {
 		.of_match_table = of_match_ptr(sdhci_spear_id_table),
 	},
 	.probe		= sdhci_probe,
-	.remove		= __devexit_p(sdhci_remove),
+	.remove		= sdhci_remove,
 };
 
 module_platform_driver(sdhci_driver);
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index f9eb916..3695b2e 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -206,7 +206,7 @@ static struct sdhci_tegra_soc_data soc_data_tegra30 = {
 };
 #endif
 
-static const struct of_device_id sdhci_tegra_dt_match[] __devinitdata = {
+static const struct of_device_id sdhci_tegra_dt_match[] = {
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
 	{ .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 },
 #endif
@@ -217,7 +217,7 @@ static const struct of_device_id sdhci_tegra_dt_match[] __devinitdata = {
 };
 MODULE_DEVICE_TABLE(of, sdhci_dt_ids);
 
-static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata(
+static struct tegra_sdhci_platform_data *sdhci_tegra_dt_parse_pdata(
 						struct platform_device *pdev)
 {
 	struct tegra_sdhci_platform_data *plat;
@@ -244,7 +244,7 @@ static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata(
 	return plat;
 }
 
-static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
+static int sdhci_tegra_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *match;
 	const struct sdhci_tegra_soc_data *soc_data;
@@ -370,7 +370,7 @@ err_no_plat:
 	return rc;
 }
 
-static int __devexit sdhci_tegra_remove(struct platform_device *pdev)
+static int sdhci_tegra_remove(struct platform_device *pdev)
 {
 	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -407,7 +407,7 @@ static struct platform_driver sdhci_tegra_driver = {
 		.pm	= SDHCI_PLTFM_PMOPS,
 	},
 	.probe		= sdhci_tegra_probe,
-	.remove		= __devexit_p(sdhci_tegra_remove),
+	.remove		= sdhci_tegra_remove,
 };
 
 module_platform_driver(sdhci_tegra_driver);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index c7851c0..63b84eb 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1618,7 +1618,7 @@ static int sdhci_do_3_3v_signal_voltage_switch(struct sdhci_host *host,
 	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
 	if (host->vqmmc) {
-		ret = regulator_set_voltage(host->vqmmc, 3300000, 3300000);
+		ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000);
 		if (ret) {
 			pr_warning("%s: Switching to 3.3V signalling voltage "
 				   " failed\n", mmc_hostname(host->mmc));
@@ -1662,7 +1662,7 @@ static int sdhci_do_1_8v_signal_voltage_switch(struct sdhci_host *host,
 		 */
 		if (host->vqmmc)
 			ret = regulator_set_voltage(host->vqmmc,
-				1800000, 1800000);
+				1700000, 1950000);
 		else
 			ret = 0;
 
@@ -2858,12 +2858,14 @@ int sdhci_add_host(struct sdhci_host *host)
 				mmc_hostname(mmc));
 			host->vqmmc = NULL;
 		}
-	}
-	else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000))
+	} else {
 		regulator_enable(host->vqmmc);
-	else
-		caps[1] &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
-		       SDHCI_SUPPORT_DDR50);
+		if (!regulator_is_supported_voltage(host->vqmmc, 1700000,
+			1950000))
+			caps[1] &= ~(SDHCI_SUPPORT_SDR104 |
+					SDHCI_SUPPORT_SDR50 |
+					SDHCI_SUPPORT_DDR50);
+	}
 
 	/* Any UHS-I mode in caps implies SDR12 and SDR25 support. */
 	if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
@@ -2919,21 +2921,18 @@ int sdhci_add_host(struct sdhci_host *host)
 				mmc_hostname(mmc));
 			host->vmmc = NULL;
 		}
-	} else
-		regulator_enable(host->vmmc);
+	}
 
 #ifdef CONFIG_REGULATOR
-	if (host->vmmc) {
-		ret = regulator_is_supported_voltage(host->vmmc, 3300000,
-			3300000);
+	if (host->vmmc && regulator_count_voltages(host->vmmc) > 1) {
+		ret = regulator_is_supported_voltage(host->vmmc, 2700000,
+			3600000);
 		if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_330)))
 			caps[0] &= ~SDHCI_CAN_VDD_330;
-		ret = regulator_is_supported_voltage(host->vmmc, 3000000,
-			3000000);
 		if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_300)))
 			caps[0] &= ~SDHCI_CAN_VDD_300;
-		ret = regulator_is_supported_voltage(host->vmmc, 1800000,
-			1800000);
+		ret = regulator_is_supported_voltage(host->vmmc, 1700000,
+			1950000);
 		if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_180)))
 			caps[0] &= ~SDHCI_CAN_VDD_180;
 	}
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index d25bc97..9b8efac 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -1302,7 +1302,7 @@ static void sh_mmcif_init_ocr(struct sh_mmcif_host *host)
 		dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
 }
 
-static int __devinit sh_mmcif_probe(struct platform_device *pdev)
+static int sh_mmcif_probe(struct platform_device *pdev)
 {
 	int ret = 0, irq[2];
 	struct mmc_host *mmc;
@@ -1430,7 +1430,7 @@ ealloch:
 	return ret;
 }
 
-static int __devexit sh_mmcif_remove(struct platform_device *pdev)
+static int sh_mmcif_remove(struct platform_device *pdev)
 {
 	struct sh_mmcif_host *host = platform_get_drvdata(pdev);
 	struct sh_mmcif_plat_data *pd = pdev->dev.platform_data;
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 0bdc146..9125684 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -117,7 +117,7 @@ static const struct sh_mobile_sdhi_ops sdhi_ops = {
 	.cd_wakeup = sh_mobile_sdhi_cd_wakeup,
 };
 
-static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
+static int sh_mobile_sdhi_probe(struct platform_device *pdev)
 {
 	struct sh_mobile_sdhi *priv;
 	struct tmio_mmc_data *mmc_data;
@@ -330,7 +330,7 @@ static struct platform_driver sh_mobile_sdhi_driver = {
 		.of_match_table = sh_mobile_sdhi_of_match,
 	},
 	.probe		= sh_mobile_sdhi_probe,
-	.remove		= __devexit_p(sh_mobile_sdhi_remove),
+	.remove		= sh_mobile_sdhi_remove,
 };
 
 module_platform_driver(sh_mobile_sdhi_driver);
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index 113ce6c..139212e 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -57,7 +57,7 @@ static int tmio_mmc_resume(struct platform_device *dev)
 #define tmio_mmc_resume NULL
 #endif
 
-static int __devinit tmio_mmc_probe(struct platform_device *pdev)
+static int tmio_mmc_probe(struct platform_device *pdev)
 {
 	const struct mfd_cell *cell = mfd_get_cell(pdev);
 	struct tmio_mmc_data *pdata;
@@ -107,7 +107,7 @@ out:
 	return ret;
 }
 
-static int __devexit tmio_mmc_remove(struct platform_device *pdev)
+static int tmio_mmc_remove(struct platform_device *pdev)
 {
 	const struct mfd_cell *cell = mfd_get_cell(pdev);
 	struct mmc_host *mmc = platform_get_drvdata(pdev);
@@ -133,7 +133,7 @@ static struct platform_driver tmio_mmc_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = tmio_mmc_probe,
-	.remove = __devexit_p(tmio_mmc_remove),
+	.remove = tmio_mmc_remove,
 	.suspend = tmio_mmc_suspend,
 	.resume = tmio_mmc_resume,
 };
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 0d8a9bb..50bf495 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -918,7 +918,7 @@ static void tmio_mmc_init_ocr(struct tmio_mmc_host *host)
 		dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
 }
 
-int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
+int tmio_mmc_host_probe(struct tmio_mmc_host **host,
 				  struct platform_device *pdev,
 				  struct tmio_mmc_data *pdata)
 {
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
index f18bece..4f84586 100644
--- a/drivers/mmc/host/via-sdmmc.c
+++ b/drivers/mmc/host/via-sdmmc.c
@@ -1082,7 +1082,7 @@ static void via_init_mmc_host(struct via_crdr_mmc_host *host)
 	msleep(1);
 }
 
-static int __devinit via_sd_probe(struct pci_dev *pcidev,
+static int via_sd_probe(struct pci_dev *pcidev,
 				    const struct pci_device_id *id)
 {
 	struct mmc_host *mmc;
@@ -1176,7 +1176,7 @@ disable:
 	return ret;
 }
 
-static void __devexit via_sd_remove(struct pci_dev *pcidev)
+static void via_sd_remove(struct pci_dev *pcidev)
 {
 	struct via_crdr_mmc_host *sdhost = pci_get_drvdata(pcidev);
 	unsigned long flags;
@@ -1332,7 +1332,7 @@ static struct pci_driver via_sd_driver = {
 	.name = DRV_NAME,
 	.id_table = via_ids,
 	.probe = via_sd_probe,
-	.remove = __devexit_p(via_sd_remove),
+	.remove = via_sd_remove,
 	.suspend = via_sd_suspend,
 	.resume = via_sd_resume,
 };
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
index 64acd9c..e954b77 100644
--- a/drivers/mmc/host/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -1196,7 +1196,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id)
  * Allocate/free MMC structure.
  */
 
-static int __devinit wbsd_alloc_mmc(struct device *dev)
+static int wbsd_alloc_mmc(struct device *dev)
 {
 	struct mmc_host *mmc;
 	struct wbsd_host *host;
@@ -1288,7 +1288,7 @@ static void wbsd_free_mmc(struct device *dev)
  * Scan for known chip id:s
  */
 
-static int __devinit wbsd_scan(struct wbsd_host *host)
+static int wbsd_scan(struct wbsd_host *host)
 {
 	int i, j, k;
 	int id;
@@ -1344,7 +1344,7 @@ static int __devinit wbsd_scan(struct wbsd_host *host)
  * Allocate/free io port ranges
  */
 
-static int __devinit wbsd_request_region(struct wbsd_host *host, int base)
+static int wbsd_request_region(struct wbsd_host *host, int base)
 {
 	if (base & 0x7)
 		return -EINVAL;
@@ -1374,7 +1374,7 @@ static void wbsd_release_regions(struct wbsd_host *host)
  * Allocate/free DMA port and buffer
  */
 
-static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma)
+static void wbsd_request_dma(struct wbsd_host *host, int dma)
 {
 	if (dma < 0)
 		return;
@@ -1452,7 +1452,7 @@ static void wbsd_release_dma(struct wbsd_host *host)
  * Allocate/free IRQ.
  */
 
-static int __devinit wbsd_request_irq(struct wbsd_host *host, int irq)
+static int wbsd_request_irq(struct wbsd_host *host, int irq)
 {
 	int ret;
 
@@ -1502,7 +1502,7 @@ static void  wbsd_release_irq(struct wbsd_host *host)
  * Allocate all resources for the host.
  */
 
-static int __devinit wbsd_request_resources(struct wbsd_host *host,
+static int wbsd_request_resources(struct wbsd_host *host,
 	int base, int irq, int dma)
 {
 	int ret;
@@ -1644,7 +1644,7 @@ static void wbsd_chip_poweroff(struct wbsd_host *host)
  *                                                                           *
 \*****************************************************************************/
 
-static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma,
+static int wbsd_init(struct device *dev, int base, int irq, int dma,
 	int pnp)
 {
 	struct wbsd_host *host = NULL;
@@ -1735,7 +1735,7 @@ static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma,
 	return 0;
 }
 
-static void __devexit wbsd_shutdown(struct device *dev, int pnp)
+static void wbsd_shutdown(struct device *dev, int pnp)
 {
 	struct mmc_host *mmc = dev_get_drvdata(dev);
 	struct wbsd_host *host;
@@ -1762,13 +1762,13 @@ static void __devexit wbsd_shutdown(struct device *dev, int pnp)
  * Non-PnP
  */
 
-static int __devinit wbsd_probe(struct platform_device *dev)
+static int wbsd_probe(struct platform_device *dev)
 {
 	/* Use the module parameters for resources */
 	return wbsd_init(&dev->dev, param_io, param_irq, param_dma, 0);
 }
 
-static int __devexit wbsd_remove(struct platform_device *dev)
+static int wbsd_remove(struct platform_device *dev)
 {
 	wbsd_shutdown(&dev->dev, 0);
 
@@ -1781,7 +1781,7 @@ static int __devexit wbsd_remove(struct platform_device *dev)
 
 #ifdef CONFIG_PNP
 
-static int __devinit
+static int
 wbsd_pnp_probe(struct pnp_dev *pnpdev, const struct pnp_device_id *dev_id)
 {
 	int io, irq, dma;
@@ -1801,7 +1801,7 @@ wbsd_pnp_probe(struct pnp_dev *pnpdev, const struct pnp_device_id *dev_id)
 	return wbsd_init(&pnpdev->dev, io, irq, dma, 1);
 }
 
-static void __devexit wbsd_pnp_remove(struct pnp_dev *dev)
+static void wbsd_pnp_remove(struct pnp_dev *dev)
 {
 	wbsd_shutdown(&dev->dev, 1);
 }
@@ -1941,7 +1941,7 @@ static struct platform_device *wbsd_device;
 
 static struct platform_driver wbsd_driver = {
 	.probe		= wbsd_probe,
-	.remove		= __devexit_p(wbsd_remove),
+	.remove		= wbsd_remove,
 
 	.suspend	= wbsd_platform_suspend,
 	.resume		= wbsd_platform_resume,
@@ -1957,7 +1957,7 @@ static struct pnp_driver wbsd_pnp_driver = {
 	.name		= DRIVER_NAME,
 	.id_table	= pnp_dev_table,
 	.probe		= wbsd_pnp_probe,
-	.remove		= __devexit_p(wbsd_pnp_remove),
+	.remove		= wbsd_pnp_remove,
 
 	.suspend	= wbsd_pnp_suspend,
 	.resume		= wbsd_pnp_resume,
diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c
new file mode 100644
index 0000000..5ba4605
--- /dev/null
+++ b/drivers/mmc/host/wmt-sdmmc.c
@@ -0,0 +1,1029 @@
+/*
+ *  WM8505/WM8650 SD/MMC Host Controller
+ *
+ *  Copyright (C) 2010 Tony Prisk
+ *  Copyright (C) 2008 WonderMedia Technologies, 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/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_device.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+
+#include <asm/byteorder.h>
+
+
+#define DRIVER_NAME "wmt-sdhc"
+
+
+/* MMC/SD controller registers */
+#define SDMMC_CTLR			0x00
+#define SDMMC_CMD			0x01
+#define SDMMC_RSPTYPE			0x02
+#define SDMMC_ARG			0x04
+#define SDMMC_BUSMODE			0x08
+#define SDMMC_BLKLEN			0x0C
+#define SDMMC_BLKCNT			0x0E
+#define SDMMC_RSP			0x10
+#define SDMMC_CBCR			0x20
+#define SDMMC_INTMASK0			0x24
+#define SDMMC_INTMASK1			0x25
+#define SDMMC_STS0			0x28
+#define SDMMC_STS1			0x29
+#define SDMMC_STS2			0x2A
+#define SDMMC_STS3			0x2B
+#define SDMMC_RSPTIMEOUT		0x2C
+#define SDMMC_CLK			0x30	/* VT8500 only */
+#define SDMMC_EXTCTRL			0x34
+#define SDMMC_SBLKLEN			0x38
+#define SDMMC_DMATIMEOUT		0x3C
+
+
+/* SDMMC_CTLR bit fields */
+#define CTLR_CMD_START			0x01
+#define CTLR_CMD_WRITE			0x04
+#define CTLR_FIFO_RESET			0x08
+
+/* SDMMC_BUSMODE bit fields */
+#define BM_SPI_MODE			0x01
+#define BM_FOURBIT_MODE			0x02
+#define BM_EIGHTBIT_MODE		0x04
+#define BM_SD_OFF			0x10
+#define BM_SPI_CS			0x20
+#define BM_SD_POWER			0x40
+#define BM_SOFT_RESET			0x80
+#define BM_ONEBIT_MASK			0xFD
+
+/* SDMMC_BLKLEN bit fields */
+#define BLKL_CRCERR_ABORT		0x0800
+#define BLKL_CD_POL_HIGH		0x1000
+#define BLKL_GPI_CD			0x2000
+#define BLKL_DATA3_CD			0x4000
+#define BLKL_INT_ENABLE			0x8000
+
+/* SDMMC_INTMASK0 bit fields */
+#define INT0_MBLK_TRAN_DONE_INT_EN	0x10
+#define INT0_BLK_TRAN_DONE_INT_EN	0x20
+#define INT0_CD_INT_EN			0x40
+#define INT0_DI_INT_EN			0x80
+
+/* SDMMC_INTMASK1 bit fields */
+#define INT1_CMD_RES_TRAN_DONE_INT_EN	0x02
+#define INT1_CMD_RES_TOUT_INT_EN	0x04
+#define INT1_MBLK_AUTO_STOP_INT_EN	0x08
+#define INT1_DATA_TOUT_INT_EN		0x10
+#define INT1_RESCRC_ERR_INT_EN		0x20
+#define INT1_RCRC_ERR_INT_EN		0x40
+#define INT1_WCRC_ERR_INT_EN		0x80
+
+/* SDMMC_STS0 bit fields */
+#define STS0_WRITE_PROTECT		0x02
+#define STS0_CD_DATA3			0x04
+#define STS0_CD_GPI			0x08
+#define STS0_MBLK_DONE			0x10
+#define STS0_BLK_DONE			0x20
+#define STS0_CARD_DETECT		0x40
+#define STS0_DEVICE_INS			0x80
+
+/* SDMMC_STS1 bit fields */
+#define STS1_SDIO_INT			0x01
+#define STS1_CMDRSP_DONE		0x02
+#define STS1_RSP_TIMEOUT		0x04
+#define STS1_AUTOSTOP_DONE		0x08
+#define STS1_DATA_TIMEOUT		0x10
+#define STS1_RSP_CRC_ERR		0x20
+#define STS1_RCRC_ERR			0x40
+#define STS1_WCRC_ERR			0x80
+
+/* SDMMC_STS2 bit fields */
+#define STS2_CMD_RES_BUSY		0x10
+#define STS2_DATARSP_BUSY		0x20
+#define STS2_DIS_FORCECLK		0x80
+
+
+/* MMC/SD DMA Controller Registers */
+#define SDDMA_GCR			0x100
+#define SDDMA_IER			0x104
+#define SDDMA_ISR			0x108
+#define SDDMA_DESPR			0x10C
+#define SDDMA_RBR			0x110
+#define SDDMA_DAR			0x114
+#define SDDMA_BAR			0x118
+#define SDDMA_CPR			0x11C
+#define SDDMA_CCR			0x120
+
+
+/* SDDMA_GCR bit fields */
+#define DMA_GCR_DMA_EN			0x00000001
+#define DMA_GCR_SOFT_RESET		0x00000100
+
+/* SDDMA_IER bit fields */
+#define DMA_IER_INT_EN			0x00000001
+
+/* SDDMA_ISR bit fields */
+#define DMA_ISR_INT_STS			0x00000001
+
+/* SDDMA_RBR bit fields */
+#define DMA_RBR_FORMAT			0x40000000
+#define DMA_RBR_END			0x80000000
+
+/* SDDMA_CCR bit fields */
+#define DMA_CCR_RUN			0x00000080
+#define DMA_CCR_IF_TO_PERIPHERAL	0x00000000
+#define DMA_CCR_PERIPHERAL_TO_IF	0x00400000
+
+/* SDDMA_CCR event status */
+#define DMA_CCR_EVT_NO_STATUS		0x00000000
+#define DMA_CCR_EVT_UNDERRUN		0x00000001
+#define DMA_CCR_EVT_OVERRUN		0x00000002
+#define DMA_CCR_EVT_DESP_READ		0x00000003
+#define DMA_CCR_EVT_DATA_RW		0x00000004
+#define DMA_CCR_EVT_EARLY_END		0x00000005
+#define DMA_CCR_EVT_SUCCESS		0x0000000F
+
+#define PDMA_READ			0x00
+#define PDMA_WRITE			0x01
+
+#define WMT_SD_POWER_OFF		0
+#define WMT_SD_POWER_ON			1
+
+struct wmt_dma_descriptor {
+	u32 flags;
+	u32 data_buffer_addr;
+	u32 branch_addr;
+	u32 reserved1;
+};
+
+struct wmt_mci_caps {
+	unsigned int	f_min;
+	unsigned int	f_max;
+	u32		ocr_avail;
+	u32		caps;
+	u32		max_seg_size;
+	u32		max_segs;
+	u32		max_blk_size;
+};
+
+struct wmt_mci_priv {
+	struct mmc_host *mmc;
+	void __iomem *sdmmc_base;
+
+	int irq_regular;
+	int irq_dma;
+
+	void *dma_desc_buffer;
+	dma_addr_t dma_desc_device_addr;
+
+	struct completion cmdcomp;
+	struct completion datacomp;
+
+	struct completion *comp_cmd;
+	struct completion *comp_dma;
+
+	struct mmc_request *req;
+	struct mmc_command *cmd;
+
+	struct clk *clk_sdmmc;
+	struct device *dev;
+
+	u8 power_inverted;
+	u8 cd_inverted;
+};
+
+static void wmt_set_sd_power(struct wmt_mci_priv *priv, int enable)
+{
+	u32 reg_tmp;
+	if (enable) {
+		if (priv->power_inverted) {
+			reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+			writeb(reg_tmp | BM_SD_OFF,
+			       priv->sdmmc_base + SDMMC_BUSMODE);
+		} else {
+			reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+			writeb(reg_tmp & (~BM_SD_OFF),
+			       priv->sdmmc_base + SDMMC_BUSMODE);
+		}
+	} else {
+		if (priv->power_inverted) {
+			reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+			writeb(reg_tmp & (~BM_SD_OFF),
+			       priv->sdmmc_base + SDMMC_BUSMODE);
+		} else {
+			reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+			writeb(reg_tmp | BM_SD_OFF,
+			       priv->sdmmc_base + SDMMC_BUSMODE);
+		}
+	}
+}
+
+static void wmt_mci_read_response(struct mmc_host *mmc)
+{
+	struct wmt_mci_priv *priv;
+	int idx1, idx2;
+	u8 tmp_resp;
+	u32 response;
+
+	priv = mmc_priv(mmc);
+
+	for (idx1 = 0; idx1 < 4; idx1++) {
+		response = 0;
+		for (idx2 = 0; idx2 < 4; idx2++) {
+			if ((idx1 == 3) && (idx2 == 3))
+				tmp_resp = readb(priv->sdmmc_base + SDMMC_RSP);
+			else
+				tmp_resp = readb(priv->sdmmc_base + SDMMC_RSP +
+						 (idx1*4) + idx2 + 1);
+			response |= (tmp_resp << (idx2 * 8));
+		}
+		priv->cmd->resp[idx1] = cpu_to_be32(response);
+	}
+}
+
+static void wmt_mci_start_command(struct wmt_mci_priv *priv)
+{
+	u32 reg_tmp;
+
+	reg_tmp = readb(priv->sdmmc_base + SDMMC_CTLR);
+	writeb(reg_tmp | CTLR_CMD_START, priv->sdmmc_base + SDMMC_CTLR);
+}
+
+static int wmt_mci_send_command(struct mmc_host *mmc, u8 command, u8 cmdtype,
+				u32 arg, u8 rsptype)
+{
+	struct wmt_mci_priv *priv;
+	u32 reg_tmp;
+
+	priv = mmc_priv(mmc);
+
+	/* write command, arg, resptype registers */
+	writeb(command, priv->sdmmc_base + SDMMC_CMD);
+	writel(arg, priv->sdmmc_base + SDMMC_ARG);
+	writeb(rsptype, priv->sdmmc_base + SDMMC_RSPTYPE);
+
+	/* reset response FIFO */
+	reg_tmp = readb(priv->sdmmc_base + SDMMC_CTLR);
+	writeb(reg_tmp | CTLR_FIFO_RESET, priv->sdmmc_base + SDMMC_CTLR);
+
+	/* ensure clock enabled - VT3465 */
+	wmt_set_sd_power(priv, WMT_SD_POWER_ON);
+
+	/* clear status bits */
+	writeb(0xFF, priv->sdmmc_base + SDMMC_STS0);
+	writeb(0xFF, priv->sdmmc_base + SDMMC_STS1);
+	writeb(0xFF, priv->sdmmc_base + SDMMC_STS2);
+	writeb(0xFF, priv->sdmmc_base + SDMMC_STS3);
+
+	/* set command type */
+	reg_tmp = readb(priv->sdmmc_base + SDMMC_CTLR);
+	writeb((reg_tmp & 0x0F) | (cmdtype << 4),
+	       priv->sdmmc_base + SDMMC_CTLR);
+
+	return 0;
+}
+
+static void wmt_mci_disable_dma(struct wmt_mci_priv *priv)
+{
+	writel(DMA_ISR_INT_STS, priv->sdmmc_base + SDDMA_ISR);
+	writel(0, priv->sdmmc_base + SDDMA_IER);
+}
+
+static void wmt_complete_data_request(struct wmt_mci_priv *priv)
+{
+	struct mmc_request *req;
+	req = priv->req;
+
+	req->data->bytes_xfered = req->data->blksz * req->data->blocks;
+
+	/* unmap the DMA pages used for write data */
+	if (req->data->flags & MMC_DATA_WRITE)
+		dma_unmap_sg(mmc_dev(priv->mmc), req->data->sg,
+			     req->data->sg_len, DMA_TO_DEVICE);
+	else
+		dma_unmap_sg(mmc_dev(priv->mmc), req->data->sg,
+			     req->data->sg_len, DMA_FROM_DEVICE);
+
+	/* Check if the DMA ISR returned a data error */
+	if ((req->cmd->error) || (req->data->error))
+		mmc_request_done(priv->mmc, req);
+	else {
+		wmt_mci_read_response(priv->mmc);
+		if (!req->data->stop) {
+			/* single-block read/write requests end here */
+			mmc_request_done(priv->mmc, req);
+		} else {
+			/*
+			 * we change the priv->cmd variable so the response is
+			 * stored in the stop struct rather than the original
+			 * calling command struct
+			 */
+			priv->comp_cmd = &priv->cmdcomp;
+			init_completion(priv->comp_cmd);
+			priv->cmd = req->data->stop;
+			wmt_mci_send_command(priv->mmc, req->data->stop->opcode,
+					     7, req->data->stop->arg, 9);
+			wmt_mci_start_command(priv);
+		}
+	}
+}
+
+static irqreturn_t wmt_mci_dma_isr(int irq_num, void *data)
+{
+	struct mmc_host *mmc;
+	struct wmt_mci_priv *priv;
+
+	int status;
+
+	priv = (struct wmt_mci_priv *)data;
+	mmc = priv->mmc;
+
+	status = readl(priv->sdmmc_base + SDDMA_CCR) & 0x0F;
+
+	if (status != DMA_CCR_EVT_SUCCESS) {
+		dev_err(priv->dev, "DMA Error: Status = %d\n", status);
+		priv->req->data->error = -ETIMEDOUT;
+		complete(priv->comp_dma);
+		return IRQ_HANDLED;
+	}
+
+	priv->req->data->error = 0;
+
+	wmt_mci_disable_dma(priv);
+
+	complete(priv->comp_dma);
+
+	if (priv->comp_cmd) {
+		if (completion_done(priv->comp_cmd)) {
+			/*
+			 * if the command (regular) interrupt has already
+			 * completed, finish off the request otherwise we wait
+			 * for the command interrupt and finish from there.
+			 */
+			wmt_complete_data_request(priv);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t wmt_mci_regular_isr(int irq_num, void *data)
+{
+	struct wmt_mci_priv *priv;
+	u32 status0;
+	u32 status1;
+	u32 status2;
+	u32 reg_tmp;
+	int cmd_done;
+
+	priv = (struct wmt_mci_priv *)data;
+	cmd_done = 0;
+	status0 = readb(priv->sdmmc_base + SDMMC_STS0);
+	status1 = readb(priv->sdmmc_base + SDMMC_STS1);
+	status2 = readb(priv->sdmmc_base + SDMMC_STS2);
+
+	/* Check for card insertion */
+	reg_tmp = readb(priv->sdmmc_base + SDMMC_INTMASK0);
+	if ((reg_tmp & INT0_DI_INT_EN) && (status0 & STS0_DEVICE_INS)) {
+		mmc_detect_change(priv->mmc, 0);
+		if (priv->cmd)
+			priv->cmd->error = -ETIMEDOUT;
+		if (priv->comp_cmd)
+			complete(priv->comp_cmd);
+		if (priv->comp_dma) {
+			wmt_mci_disable_dma(priv);
+			complete(priv->comp_dma);
+		}
+		writeb(STS0_DEVICE_INS, priv->sdmmc_base + SDMMC_STS0);
+		return IRQ_HANDLED;
+	}
+
+	if ((!priv->req->data) ||
+	    ((priv->req->data->stop) && (priv->cmd == priv->req->data->stop))) {
+		/* handle non-data & stop_transmission requests */
+		if (status1 & STS1_CMDRSP_DONE) {
+			priv->cmd->error = 0;
+			cmd_done = 1;
+		} else if ((status1 & STS1_RSP_TIMEOUT) ||
+			   (status1 & STS1_DATA_TIMEOUT)) {
+			priv->cmd->error = -ETIMEDOUT;
+			cmd_done = 1;
+		}
+
+		if (cmd_done) {
+			priv->comp_cmd = NULL;
+
+			if (!priv->cmd->error)
+				wmt_mci_read_response(priv->mmc);
+
+			priv->cmd = NULL;
+
+			mmc_request_done(priv->mmc, priv->req);
+		}
+	} else {
+		/* handle data requests */
+		if (status1 & STS1_CMDRSP_DONE) {
+			if (priv->cmd)
+				priv->cmd->error = 0;
+			if (priv->comp_cmd)
+				complete(priv->comp_cmd);
+		}
+
+		if ((status1 & STS1_RSP_TIMEOUT) ||
+		    (status1 & STS1_DATA_TIMEOUT)) {
+			if (priv->cmd)
+				priv->cmd->error = -ETIMEDOUT;
+			if (priv->comp_cmd)
+				complete(priv->comp_cmd);
+			if (priv->comp_dma) {
+				wmt_mci_disable_dma(priv);
+				complete(priv->comp_dma);
+			}
+		}
+
+		if (priv->comp_dma) {
+			/*
+			 * If the dma interrupt has already completed, finish
+			 * off the request; otherwise we wait for the DMA
+			 * interrupt and finish from there.
+			 */
+			if (completion_done(priv->comp_dma))
+				wmt_complete_data_request(priv);
+		}
+	}
+
+	writeb(status0, priv->sdmmc_base + SDMMC_STS0);
+	writeb(status1, priv->sdmmc_base + SDMMC_STS1);
+	writeb(status2, priv->sdmmc_base + SDMMC_STS2);
+
+	return IRQ_HANDLED;
+}
+
+static void wmt_reset_hardware(struct mmc_host *mmc)
+{
+	struct wmt_mci_priv *priv;
+	u32 reg_tmp;
+
+	priv = mmc_priv(mmc);
+
+	/* reset controller */
+	reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+	writeb(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base + SDMMC_BUSMODE);
+
+	/* reset response FIFO */
+	reg_tmp = readb(priv->sdmmc_base + SDMMC_CTLR);
+	writeb(reg_tmp | CTLR_FIFO_RESET, priv->sdmmc_base + SDMMC_CTLR);
+
+	/* enable GPI pin to detect card */
+	writew(BLKL_INT_ENABLE | BLKL_GPI_CD, priv->sdmmc_base + SDMMC_BLKLEN);
+
+	/* clear interrupt status */
+	writeb(0xFF, priv->sdmmc_base + SDMMC_STS0);
+	writeb(0xFF, priv->sdmmc_base + SDMMC_STS1);
+
+	/* setup interrupts */
+	writeb(INT0_CD_INT_EN | INT0_DI_INT_EN, priv->sdmmc_base +
+	       SDMMC_INTMASK0);
+	writeb(INT1_DATA_TOUT_INT_EN | INT1_CMD_RES_TRAN_DONE_INT_EN |
+	       INT1_CMD_RES_TOUT_INT_EN, priv->sdmmc_base + SDMMC_INTMASK1);
+
+	/* set the DMA timeout */
+	writew(8191, priv->sdmmc_base + SDMMC_DMATIMEOUT);
+
+	/* auto clock freezing enable */
+	reg_tmp = readb(priv->sdmmc_base + SDMMC_STS2);
+	writeb(reg_tmp | STS2_DIS_FORCECLK, priv->sdmmc_base + SDMMC_STS2);
+
+	/* set a default clock speed of 400Khz */
+	clk_set_rate(priv->clk_sdmmc, 400000);
+}
+
+static int wmt_dma_init(struct mmc_host *mmc)
+{
+	struct wmt_mci_priv *priv;
+
+	priv = mmc_priv(mmc);
+
+	writel(DMA_GCR_SOFT_RESET, priv->sdmmc_base + SDDMA_GCR);
+	writel(DMA_GCR_DMA_EN, priv->sdmmc_base + SDDMA_GCR);
+	if ((readl(priv->sdmmc_base + SDDMA_GCR) & DMA_GCR_DMA_EN) != 0)
+		return 0;
+	else
+		return 1;
+}
+
+static void wmt_dma_init_descriptor(struct wmt_dma_descriptor *desc,
+		u16 req_count, u32 buffer_addr, u32 branch_addr, int end)
+{
+	desc->flags = 0x40000000 | req_count;
+	if (end)
+		desc->flags |= 0x80000000;
+	desc->data_buffer_addr = buffer_addr;
+	desc->branch_addr = branch_addr;
+}
+
+static void wmt_dma_config(struct mmc_host *mmc, u32 descaddr, u8 dir)
+{
+	struct wmt_mci_priv *priv;
+	u32 reg_tmp;
+
+	priv = mmc_priv(mmc);
+
+	/* Enable DMA Interrupts */
+	writel(DMA_IER_INT_EN, priv->sdmmc_base + SDDMA_IER);
+
+	/* Write DMA Descriptor Pointer Register */
+	writel(descaddr, priv->sdmmc_base + SDDMA_DESPR);
+
+	writel(0x00, priv->sdmmc_base + SDDMA_CCR);
+
+	if (dir == PDMA_WRITE) {
+		reg_tmp = readl(priv->sdmmc_base + SDDMA_CCR);
+		writel(reg_tmp & DMA_CCR_IF_TO_PERIPHERAL, priv->sdmmc_base +
+		       SDDMA_CCR);
+	} else {
+		reg_tmp = readl(priv->sdmmc_base + SDDMA_CCR);
+		writel(reg_tmp | DMA_CCR_PERIPHERAL_TO_IF, priv->sdmmc_base +
+		       SDDMA_CCR);
+	}
+}
+
+static void wmt_dma_start(struct wmt_mci_priv *priv)
+{
+	u32 reg_tmp;
+
+	reg_tmp = readl(priv->sdmmc_base + SDDMA_CCR);
+	writel(reg_tmp | DMA_CCR_RUN, priv->sdmmc_base + SDDMA_CCR);
+}
+
+static void wmt_mci_request(struct mmc_host *mmc, struct mmc_request *req)
+{
+	struct wmt_mci_priv *priv;
+	struct wmt_dma_descriptor *desc;
+	u8 command;
+	u8 cmdtype;
+	u32 arg;
+	u8 rsptype;
+	u32 reg_tmp;
+
+	struct scatterlist *sg;
+	int i;
+	int sg_cnt;
+	int offset;
+	u32 dma_address;
+	int desc_cnt;
+
+	priv = mmc_priv(mmc);
+	priv->req = req;
+
+	/*
+	 * Use the cmd variable to pass a pointer to the resp[] structure
+	 * This is required on multi-block requests to pass the pointer to the
+	 * stop command
+	 */
+	priv->cmd = req->cmd;
+
+	command = req->cmd->opcode;
+	arg = req->cmd->arg;
+	rsptype = mmc_resp_type(req->cmd);
+	cmdtype = 0;
+
+	/* rsptype=7 only valid for SPI commands - should be =2 for SD */
+	if (rsptype == 7)
+		rsptype = 2;
+	/* rsptype=21 is R1B, convert for controller */
+	if (rsptype == 21)
+		rsptype = 9;
+
+	if (!req->data) {
+		wmt_mci_send_command(mmc, command, cmdtype, arg, rsptype);
+		wmt_mci_start_command(priv);
+		/* completion is now handled in the regular_isr() */
+	}
+	if (req->data) {
+		priv->comp_cmd = &priv->cmdcomp;
+		init_completion(priv->comp_cmd);
+
+		wmt_dma_init(mmc);
+
+		/* set controller data length */
+		reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN);
+		writew((reg_tmp & 0xF800) | (req->data->blksz - 1),
+		       priv->sdmmc_base + SDMMC_BLKLEN);
+
+		/* set controller block count */
+		writew(req->data->blocks, priv->sdmmc_base + SDMMC_BLKCNT);
+
+		desc = (struct wmt_dma_descriptor *)priv->dma_desc_buffer;
+
+		if (req->data->flags & MMC_DATA_WRITE) {
+			sg_cnt = dma_map_sg(mmc_dev(mmc), req->data->sg,
+					    req->data->sg_len, DMA_TO_DEVICE);
+			cmdtype = 1;
+			if (req->data->blocks > 1)
+				cmdtype = 3;
+		} else {
+			sg_cnt = dma_map_sg(mmc_dev(mmc), req->data->sg,
+					    req->data->sg_len, DMA_FROM_DEVICE);
+			cmdtype = 2;
+			if (req->data->blocks > 1)
+				cmdtype = 4;
+		}
+
+		dma_address = priv->dma_desc_device_addr + 16;
+		desc_cnt = 0;
+
+		for_each_sg(req->data->sg, sg, sg_cnt, i) {
+			offset = 0;
+			while (offset < sg_dma_len(sg)) {
+				wmt_dma_init_descriptor(desc, req->data->blksz,
+						sg_dma_address(sg)+offset,
+						dma_address, 0);
+				desc++;
+				desc_cnt++;
+				offset += req->data->blksz;
+				dma_address += 16;
+				if (desc_cnt == req->data->blocks)
+					break;
+			}
+		}
+		desc--;
+		desc->flags |= 0x80000000;
+
+		if (req->data->flags & MMC_DATA_WRITE)
+			wmt_dma_config(mmc, priv->dma_desc_device_addr,
+				       PDMA_WRITE);
+		else
+			wmt_dma_config(mmc, priv->dma_desc_device_addr,
+				       PDMA_READ);
+
+		wmt_mci_send_command(mmc, command, cmdtype, arg, rsptype);
+
+		priv->comp_dma = &priv->datacomp;
+		init_completion(priv->comp_dma);
+
+		wmt_dma_start(priv);
+		wmt_mci_start_command(priv);
+	}
+}
+
+static void wmt_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct wmt_mci_priv *priv;
+	u32 reg_tmp;
+
+	priv = mmc_priv(mmc);
+
+	if (ios->power_mode == MMC_POWER_UP) {
+		wmt_reset_hardware(mmc);
+
+		wmt_set_sd_power(priv, WMT_SD_POWER_ON);
+	}
+	if (ios->power_mode == MMC_POWER_OFF)
+		wmt_set_sd_power(priv, WMT_SD_POWER_OFF);
+
+	if (ios->clock != 0)
+		clk_set_rate(priv->clk_sdmmc, ios->clock);
+
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_8:
+		reg_tmp = readb(priv->sdmmc_base + SDMMC_EXTCTRL);
+		writeb(reg_tmp | 0x04, priv->sdmmc_base + SDMMC_EXTCTRL);
+		break;
+	case MMC_BUS_WIDTH_4:
+		reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+		writeb(reg_tmp | BM_FOURBIT_MODE, priv->sdmmc_base +
+		       SDMMC_BUSMODE);
+
+		reg_tmp = readb(priv->sdmmc_base + SDMMC_EXTCTRL);
+		writeb(reg_tmp & 0xFB, priv->sdmmc_base + SDMMC_EXTCTRL);
+		break;
+	case MMC_BUS_WIDTH_1:
+		reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+		writeb(reg_tmp & BM_ONEBIT_MASK, priv->sdmmc_base +
+		       SDMMC_BUSMODE);
+
+		reg_tmp = readb(priv->sdmmc_base + SDMMC_EXTCTRL);
+		writeb(reg_tmp & 0xFB, priv->sdmmc_base + SDMMC_EXTCTRL);
+		break;
+	}
+}
+
+static int wmt_mci_get_ro(struct mmc_host *mmc)
+{
+	struct wmt_mci_priv *priv = mmc_priv(mmc);
+
+	return !(readb(priv->sdmmc_base + SDMMC_STS0) & STS0_WRITE_PROTECT);
+}
+
+static int wmt_mci_get_cd(struct mmc_host *mmc)
+{
+	struct wmt_mci_priv *priv = mmc_priv(mmc);
+	u32 cd = (readb(priv->sdmmc_base + SDMMC_STS0) & STS0_CD_GPI) >> 3;
+
+	return !(cd ^ priv->cd_inverted);
+}
+
+static struct mmc_host_ops wmt_mci_ops = {
+	.request = wmt_mci_request,
+	.set_ios = wmt_mci_set_ios,
+	.get_ro = wmt_mci_get_ro,
+	.get_cd = wmt_mci_get_cd,
+};
+
+/* Controller capabilities */
+static struct wmt_mci_caps wm8505_caps = {
+	.f_min = 390425,
+	.f_max = 50000000,
+	.ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34,
+	.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED |
+		MMC_CAP_SD_HIGHSPEED,
+	.max_seg_size = 65024,
+	.max_segs = 128,
+	.max_blk_size = 2048,
+};
+
+static struct of_device_id wmt_mci_dt_ids[] = {
+	{ .compatible = "wm,wm8505-sdhc", .data = &wm8505_caps },
+	{ /* Sentinel */ },
+};
+
+static int __devinit wmt_mci_probe(struct platform_device *pdev)
+{
+	struct mmc_host *mmc;
+	struct wmt_mci_priv *priv;
+	struct device_node *np = pdev->dev.of_node;
+	const struct of_device_id *of_id =
+		of_match_device(wmt_mci_dt_ids, &pdev->dev);
+	const struct wmt_mci_caps *wmt_caps = of_id->data;
+	int ret;
+	int regular_irq, dma_irq;
+
+	if (!of_id || !of_id->data) {
+		dev_err(&pdev->dev, "Controller capabilities data missing\n");
+		return -EFAULT;
+	}
+
+	if (!np) {
+		dev_err(&pdev->dev, "Missing SDMMC description in devicetree\n");
+		return -EFAULT;
+	}
+
+	regular_irq = irq_of_parse_and_map(np, 0);
+	dma_irq = irq_of_parse_and_map(np, 1);
+
+	if (!regular_irq || !dma_irq) {
+		dev_err(&pdev->dev, "Getting IRQs failed!\n");
+		ret = -ENXIO;
+		goto fail1;
+	}
+
+	mmc = mmc_alloc_host(sizeof(struct wmt_mci_priv), &pdev->dev);
+	if (!mmc) {
+		dev_err(&pdev->dev, "Failed to allocate mmc_host\n");
+		ret = -ENOMEM;
+		goto fail1;
+	}
+
+	mmc->ops = &wmt_mci_ops;
+	mmc->f_min = wmt_caps->f_min;
+	mmc->f_max = wmt_caps->f_max;
+	mmc->ocr_avail = wmt_caps->ocr_avail;
+	mmc->caps = wmt_caps->caps;
+
+	mmc->max_seg_size = wmt_caps->max_seg_size;
+	mmc->max_segs = wmt_caps->max_segs;
+	mmc->max_blk_size = wmt_caps->max_blk_size;
+
+	mmc->max_req_size = (16*512*mmc->max_segs);
+	mmc->max_blk_count = mmc->max_req_size / 512;
+
+	priv = mmc_priv(mmc);
+	priv->mmc = mmc;
+	priv->dev = &pdev->dev;
+
+	priv->power_inverted = 0;
+	priv->cd_inverted = 0;
+
+	if (of_get_property(np, "sdon-inverted", NULL))
+		priv->power_inverted = 1;
+	if (of_get_property(np, "cd-inverted", NULL))
+		priv->cd_inverted = 1;
+
+	priv->sdmmc_base = of_iomap(np, 0);
+	if (!priv->sdmmc_base) {
+		dev_err(&pdev->dev, "Failed to map IO space\n");
+		ret = -ENOMEM;
+		goto fail2;
+	}
+
+	priv->irq_regular = regular_irq;
+	priv->irq_dma = dma_irq;
+
+	ret = request_irq(regular_irq, wmt_mci_regular_isr, 0, "sdmmc", priv);
+	if (ret) {
+		dev_err(&pdev->dev, "Register regular IRQ fail\n");
+		goto fail3;
+	}
+
+	ret = request_irq(dma_irq, wmt_mci_dma_isr, 32, "sdmmc", priv);
+	if (ret) {
+		dev_err(&pdev->dev, "Register DMA IRQ fail\n");
+		goto fail4;
+	}
+
+	/* alloc some DMA buffers for descriptors/transfers */
+	priv->dma_desc_buffer = dma_alloc_coherent(&pdev->dev,
+						   mmc->max_blk_count * 16,
+						   &priv->dma_desc_device_addr,
+						   208);
+	if (!priv->dma_desc_buffer) {
+		dev_err(&pdev->dev, "DMA alloc fail\n");
+		ret = -EPERM;
+		goto fail5;
+	}
+
+	platform_set_drvdata(pdev, mmc);
+
+	priv->clk_sdmmc = of_clk_get(np, 0);
+	if (IS_ERR(priv->clk_sdmmc)) {
+		dev_err(&pdev->dev, "Error getting clock\n");
+		ret = PTR_ERR(priv->clk_sdmmc);
+		goto fail5;
+	}
+
+	clk_prepare_enable(priv->clk_sdmmc);
+
+	/* configure the controller to a known 'ready' state */
+	wmt_reset_hardware(mmc);
+
+	mmc_add_host(mmc);
+
+	dev_info(&pdev->dev, "WMT SDHC Controller initialized\n");
+
+	return 0;
+fail5:
+	free_irq(dma_irq, priv);
+fail4:
+	free_irq(regular_irq, priv);
+fail3:
+	iounmap(priv->sdmmc_base);
+fail2:
+	mmc_free_host(mmc);
+fail1:
+	return ret;
+}
+
+static int __devexit wmt_mci_remove(struct platform_device *pdev)
+{
+	struct mmc_host *mmc;
+	struct wmt_mci_priv *priv;
+	struct resource *res;
+	u32 reg_tmp;
+
+	mmc = platform_get_drvdata(pdev);
+	priv = mmc_priv(mmc);
+
+	/* reset SD controller */
+	reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+	writel(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base + SDMMC_BUSMODE);
+	reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN);
+	writew(reg_tmp & ~(0xA000), priv->sdmmc_base + SDMMC_BLKLEN);
+	writeb(0xFF, priv->sdmmc_base + SDMMC_STS0);
+	writeb(0xFF, priv->sdmmc_base + SDMMC_STS1);
+
+	/* release the dma buffers */
+	dma_free_coherent(&pdev->dev, priv->mmc->max_blk_count * 16,
+			  priv->dma_desc_buffer, priv->dma_desc_device_addr);
+
+	mmc_remove_host(mmc);
+
+	free_irq(priv->irq_regular, priv);
+	free_irq(priv->irq_dma, priv);
+
+	iounmap(priv->sdmmc_base);
+
+	clk_disable_unprepare(priv->clk_sdmmc);
+	clk_put(priv->clk_sdmmc);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, res->end - res->start + 1);
+
+	mmc_free_host(mmc);
+
+	platform_set_drvdata(pdev, NULL);
+
+	dev_info(&pdev->dev, "WMT MCI device removed\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int wmt_mci_suspend(struct device *dev)
+{
+	u32 reg_tmp;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+	struct wmt_mci_priv *priv;
+	int ret;
+
+	if (!mmc)
+		return 0;
+
+	priv = mmc_priv(mmc);
+	ret = mmc_suspend_host(mmc);
+
+	if (!ret) {
+		reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+		writeb(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base +
+		       SDMMC_BUSMODE);
+
+		reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN);
+		writew(reg_tmp & 0x5FFF, priv->sdmmc_base + SDMMC_BLKLEN);
+
+		writeb(0xFF, priv->sdmmc_base + SDMMC_STS0);
+		writeb(0xFF, priv->sdmmc_base + SDMMC_STS1);
+
+		clk_disable(priv->clk_sdmmc);
+	}
+	return ret;
+}
+
+static int wmt_mci_resume(struct device *dev)
+{
+	u32 reg_tmp;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+	struct wmt_mci_priv *priv;
+	int ret = 0;
+
+	if (mmc) {
+		priv = mmc_priv(mmc);
+		clk_enable(priv->clk_sdmmc);
+
+		reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+		writeb(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base +
+		       SDMMC_BUSMODE);
+
+		reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN);
+		writew(reg_tmp | (BLKL_GPI_CD | BLKL_INT_ENABLE),
+		       priv->sdmmc_base + SDMMC_BLKLEN);
+
+		reg_tmp = readb(priv->sdmmc_base + SDMMC_INTMASK0);
+		writeb(reg_tmp | INT0_DI_INT_EN, priv->sdmmc_base +
+		       SDMMC_INTMASK0);
+
+		ret = mmc_resume_host(mmc);
+	}
+
+	return ret;
+}
+
+static const struct dev_pm_ops wmt_mci_pm = {
+	.suspend        = wmt_mci_suspend,
+	.resume         = wmt_mci_resume,
+};
+
+#define wmt_mci_pm_ops (&wmt_mci_pm)
+
+#else	/* !CONFIG_PM */
+
+#define wmt_mci_pm_ops NULL
+
+#endif
+
+static struct platform_driver wmt_mci_driver = {
+	.probe = wmt_mci_probe,
+	.remove = __exit_p(wmt_mci_remove),
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.pm = wmt_mci_pm_ops,
+		.of_match_table = wmt_mci_dt_ids,
+	},
+};
+
+module_platform_driver(wmt_mci_driver);
+
+MODULE_DESCRIPTION("Wondermedia MMC/SD Driver");
+MODULE_AUTHOR("Tony Prisk");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, wmt_mci_dt_ids);
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 73fcbbe..03f2eb5 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -291,7 +291,7 @@ config SSFDC
 
 config SM_FTL
 	tristate "SmartMedia/xD new translation layer"
-	depends on EXPERIMENTAL && BLOCK
+	depends on BLOCK
 	select MTD_BLKDEVS
 	select MTD_NAND_ECC
 	help
diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c
index 9453931..7c057a0 100644
--- a/drivers/mtd/ar7part.c
+++ b/drivers/mtd/ar7part.c
@@ -26,19 +26,16 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/bootmem.h>
-#include <linux/magic.h>
 #include <linux/module.h>
 
+#include <uapi/linux/magic.h>
+
 #define AR7_PARTS	4
 #define ROOT_OFFSET	0xe0000
 
 #define LOADER_MAGIC1	le32_to_cpu(0xfeedfa42)
 #define LOADER_MAGIC2	le32_to_cpu(0xfeed1281)
 
-#ifndef SQUASHFS_MAGIC
-#define SQUASHFS_MAGIC	0x73717368
-#endif
-
 struct ar7_bin_rec {
 	unsigned int checksum;
 	unsigned int length;
diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c
index 63d2a64..6eeb84c 100644
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -37,8 +37,7 @@
 
 #define BCM63XX_EXTENDED_SIZE	0xBFC00000	/* Extended flash address */
 
-#define BCM63XX_MIN_CFE_SIZE	0x10000		/* always at least 64KiB */
-#define BCM63XX_MIN_NVRAM_SIZE	0x10000		/* always at least 64KiB */
+#define BCM63XX_CFE_BLOCK_SIZE	0x10000		/* always at least 64KiB */
 
 #define BCM63XX_CFE_MAGIC_OFFSET 0x4e0
 
@@ -79,7 +78,7 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
 	unsigned int rootfsaddr, kerneladdr, spareaddr;
 	unsigned int rootfslen, kernellen, sparelen, totallen;
 	unsigned int cfelen, nvramlen;
-	int namelen = 0;
+	unsigned int cfe_erasesize;
 	int i;
 	u32 computed_crc;
 	bool rootfs_first = false;
@@ -87,8 +86,11 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
 	if (bcm63xx_detect_cfe(master))
 		return -EINVAL;
 
-	cfelen = max_t(uint32_t, master->erasesize, BCM63XX_MIN_CFE_SIZE);
-	nvramlen = max_t(uint32_t, master->erasesize, BCM63XX_MIN_NVRAM_SIZE);
+	cfe_erasesize = max_t(uint32_t, master->erasesize,
+			      BCM63XX_CFE_BLOCK_SIZE);
+
+	cfelen = cfe_erasesize;
+	nvramlen = cfe_erasesize;
 
 	/* Allocate memory for buffer */
 	buf = vmalloc(sizeof(struct bcm_tag));
@@ -121,7 +123,6 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
 		kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE;
 		rootfsaddr = rootfsaddr - BCM63XX_EXTENDED_SIZE;
 		spareaddr = roundup(totallen, master->erasesize) + cfelen;
-		sparelen = master->size - spareaddr - nvramlen;
 
 		if (rootfsaddr < kerneladdr) {
 			/* default Broadcom layout */
@@ -139,19 +140,15 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
 		rootfslen = 0;
 		rootfsaddr = 0;
 		spareaddr = cfelen;
-		sparelen = master->size - cfelen - nvramlen;
 	}
+	sparelen = master->size - spareaddr - nvramlen;
 
 	/* Determine number of partitions */
-	namelen = 8;
-	if (rootfslen > 0) {
+	if (rootfslen > 0)
 		nrparts++;
-		namelen += 6;
-	}
-	if (kernellen > 0) {
+
+	if (kernellen > 0)
 		nrparts++;
-		namelen += 6;
-	}
 
 	/* Ask kernel for more memory */
 	parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL);
@@ -193,17 +190,16 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
 	parts[curpart].name = "nvram";
 	parts[curpart].offset = master->size - nvramlen;
 	parts[curpart].size = nvramlen;
+	curpart++;
 
 	/* Global partition "linux" to make easy firmware upgrade */
-	curpart++;
 	parts[curpart].name = "linux";
 	parts[curpart].offset = cfelen;
 	parts[curpart].size = master->size - cfelen - nvramlen;
 
 	for (i = 0; i < nrparts; i++)
-		pr_info("Partition %d is %s offset %lx and length %lx\n", i,
-			parts[i].name, (long unsigned int)(parts[i].offset),
-			(long unsigned int)(parts[i].size));
+		pr_info("Partition %d is %s offset %llx and length %llx\n", i,
+			parts[i].name, parts[i].offset,	parts[i].size);
 
 	pr_info("Spare partition is offset %x and length %x\n",	spareaddr,
 		sparelen);
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index e469b01..c219e3d 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -225,7 +225,7 @@ config MTD_ABSENT
 
 config MTD_XIP
 	bool "XIP aware MTD support"
-	depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL && ARCH_MTD_XIP
+	depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && ARCH_MTD_XIP
 	default y if XIP_KERNEL
 	help
 	  This allows MTD support to work with flash memory which is also
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
index aed1b8a..c533f27 100644
--- a/drivers/mtd/cmdlinepart.c
+++ b/drivers/mtd/cmdlinepart.c
@@ -56,8 +56,8 @@
 
 
 /* special size referring to all the remaining space in a partition */
-#define SIZE_REMAINING UINT_MAX
-#define OFFSET_CONTINUOUS UINT_MAX
+#define SIZE_REMAINING ULLONG_MAX
+#define OFFSET_CONTINUOUS ULLONG_MAX
 
 struct cmdline_mtd_partition {
 	struct cmdline_mtd_partition *next;
@@ -89,7 +89,7 @@ static struct mtd_partition * newpart(char *s,
 				      int extra_mem_size)
 {
 	struct mtd_partition *parts;
-	unsigned long size, offset = OFFSET_CONTINUOUS;
+	unsigned long long size, offset = OFFSET_CONTINUOUS;
 	char *name;
 	int name_len;
 	unsigned char *extra_mem;
@@ -104,7 +104,8 @@ static struct mtd_partition * newpart(char *s,
 	} else {
 		size = memparse(s, &s);
 		if (size < PAGE_SIZE) {
-			printk(KERN_ERR ERRP "partition size too small (%lx)\n", size);
+			printk(KERN_ERR ERRP "partition size too small (%llx)\n",
+			       size);
 			return ERR_PTR(-EINVAL);
 		}
 	}
@@ -296,7 +297,7 @@ static int parse_cmdline_partitions(struct mtd_info *master,
 				    struct mtd_partition **pparts,
 				    struct mtd_part_parser_data *data)
 {
-	unsigned long offset;
+	unsigned long long offset;
 	int i, err;
 	struct cmdline_mtd_partition *part;
 	const char *mtd_id = master->name;
@@ -308,48 +309,52 @@ static int parse_cmdline_partitions(struct mtd_info *master,
 			return err;
 	}
 
+	/*
+	 * Search for the partition definition matching master->name.
+	 * If master->name is not set, stop at first partition definition.
+	 */
 	for (part = partitions; part; part = part->next) {
-		if ((!mtd_id) || (!strcmp(part->mtd_id, mtd_id))) {
-			for (i = 0, offset = 0; i < part->num_parts; i++) {
-				if (part->parts[i].offset == OFFSET_CONTINUOUS)
-					part->parts[i].offset = offset;
-				else
-					offset = part->parts[i].offset;
-
-				if (part->parts[i].size == SIZE_REMAINING)
-					part->parts[i].size = master->size - offset;
-
-				if (part->parts[i].size == 0) {
-					printk(KERN_WARNING ERRP
-					       "%s: skipping zero sized partition\n",
-					       part->mtd_id);
-					part->num_parts--;
-					memmove(&part->parts[i],
-						&part->parts[i + 1],
-						sizeof(*part->parts) * (part->num_parts - i));
-					continue;
-				}
-
-				if (offset + part->parts[i].size > master->size) {
-					printk(KERN_WARNING ERRP
-					       "%s: partitioning exceeds flash size, truncating\n",
-					       part->mtd_id);
-					part->parts[i].size = master->size - offset;
-				}
-				offset += part->parts[i].size;
-			}
-
-			*pparts = kmemdup(part->parts,
-					sizeof(*part->parts) * part->num_parts,
-					GFP_KERNEL);
-			if (!*pparts)
-				return -ENOMEM;
-
-			return part->num_parts;
+		if ((!mtd_id) || (!strcmp(part->mtd_id, mtd_id)))
+			break;
+	}
+
+	if (!part)
+		return 0;
+
+	for (i = 0, offset = 0; i < part->num_parts; i++) {
+		if (part->parts[i].offset == OFFSET_CONTINUOUS)
+			part->parts[i].offset = offset;
+		else
+			offset = part->parts[i].offset;
+
+		if (part->parts[i].size == SIZE_REMAINING)
+			part->parts[i].size = master->size - offset;
+
+		if (part->parts[i].size == 0) {
+			printk(KERN_WARNING ERRP
+			       "%s: skipping zero sized partition\n",
+			       part->mtd_id);
+			part->num_parts--;
+			memmove(&part->parts[i], &part->parts[i + 1],
+				sizeof(*part->parts) * (part->num_parts - i));
+			continue;
 		}
+
+		if (offset + part->parts[i].size > master->size) {
+			printk(KERN_WARNING ERRP
+			       "%s: partitioning exceeds flash size, truncating\n",
+			       part->mtd_id);
+			part->parts[i].size = master->size - offset;
+		}
+		offset += part->parts[i].size;
 	}
 
-	return 0;
+	*pparts = kmemdup(part->parts, sizeof(*part->parts) * part->num_parts,
+			  GFP_KERNEL);
+	if (!*pparts)
+		return -ENOMEM;
+
+	return part->num_parts;
 }
 
 
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 27f80cd..c187342 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -52,7 +52,7 @@ config MTD_MS02NV
 
 config MTD_DATAFLASH
 	tristate "Support for AT45xxx DataFlash"
-	depends on SPI_MASTER && EXPERIMENTAL
+	depends on SPI_MASTER
 	help
 	  This enables access to AT45xxx DataFlash chips, using SPI.
 	  Sometimes DataFlash chips are packaged inside MMC-format
@@ -81,7 +81,7 @@ config MTD_DATAFLASH_OTP
 
 config MTD_M25P80
 	tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)"
-	depends on SPI_MASTER && EXPERIMENTAL
+	depends on SPI_MASTER
 	help
 	  This enables access to most modern SPI flash chips, used for
 	  program and data storage.   Series supported include Atmel AT26DF,
diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c
index 2dc5a6f..4714584 100644
--- a/drivers/mtd/devices/bcm47xxsflash.c
+++ b/drivers/mtd/devices/bcm47xxsflash.c
@@ -66,7 +66,7 @@ out:
 	return err;
 }
 
-static int __devexit bcm47xxsflash_remove(struct platform_device *pdev)
+static int bcm47xxsflash_remove(struct platform_device *pdev)
 {
 	struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev);
 
@@ -77,7 +77,7 @@ static int __devexit bcm47xxsflash_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver bcma_sflash_driver = {
-	.remove = __devexit_p(bcm47xxsflash_remove),
+	.remove = bcm47xxsflash_remove,
 	.driver = {
 		.name = "bcma_sflash",
 		.owner = THIS_MODULE,
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 681e2ee..8debac9 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -433,7 +433,7 @@ static int __init block2mtd_init(void)
 }
 
 
-static void __devexit block2mtd_exit(void)
+static void block2mtd_exit(void)
 {
 	struct list_head *pos, *next;
 
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c
index 706b847..88b3fd3 100644
--- a/drivers/mtd/devices/docprobe.c
+++ b/drivers/mtd/devices/docprobe.c
@@ -70,8 +70,6 @@ static unsigned long __initdata doc_locations[] = {
 	0xe0000, 0xe2000, 0xe4000, 0xe6000,
 	0xe8000, 0xea000, 0xec000, 0xee000,
 #endif /*  CONFIG_MTD_DOCPROBE_HIGH */
-#else
-#warning Unknown architecture for DiskOnChip. No default probe locations defined
 #endif
 	0xffffffff };
 
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 03838ba..4eeeb2d 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -73,14 +73,6 @@
 #define	MAX_READY_WAIT_JIFFIES	(40 * HZ)	/* M25P16 specs 40s max chip erase */
 #define	MAX_CMD_SIZE		5
 
-#ifdef CONFIG_M25PXX_USE_FAST_READ
-#define OPCODE_READ 	OPCODE_FAST_READ
-#define FAST_READ_DUMMY_BYTE 1
-#else
-#define OPCODE_READ 	OPCODE_NORM_READ
-#define FAST_READ_DUMMY_BYTE 0
-#endif
-
 #define JEDEC_MFR(_jedec_id)	((_jedec_id) >> 16)
 
 /****************************************************************************/
@@ -93,6 +85,7 @@ struct m25p {
 	u16			addr_width;
 	u8			erase_opcode;
 	u8			*command;
+	bool			fast_read;
 };
 
 static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
@@ -168,6 +161,7 @@ static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable)
 {
 	switch (JEDEC_MFR(jedec_id)) {
 	case CFI_MFR_MACRONIX:
+	case 0xEF /* winbond */:
 		flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B;
 		return spi_write(flash->spi, flash->command, 1);
 	default:
@@ -342,6 +336,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
 	struct m25p *flash = mtd_to_m25p(mtd);
 	struct spi_transfer t[2];
 	struct spi_message m;
+	uint8_t opcode;
 
 	pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
 			__func__, (u32)from, len);
@@ -354,7 +349,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
 	 * Should add 1 byte DUMMY_BYTE.
 	 */
 	t[0].tx_buf = flash->command;
-	t[0].len = m25p_cmdsz(flash) + FAST_READ_DUMMY_BYTE;
+	t[0].len = m25p_cmdsz(flash) + (flash->fast_read ? 1 : 0);
 	spi_message_add_tail(&t[0], &m);
 
 	t[1].rx_buf = buf;
@@ -376,12 +371,14 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
 	 */
 
 	/* Set up the write data buffer. */
-	flash->command[0] = OPCODE_READ;
+	opcode = flash->fast_read ? OPCODE_FAST_READ : OPCODE_NORM_READ;
+	flash->command[0] = opcode;
 	m25p_addr2cmd(flash, from, flash->command);
 
 	spi_sync(flash->spi, &m);
 
-	*retlen = m.actual_length - m25p_cmdsz(flash) - FAST_READ_DUMMY_BYTE;
+	*retlen = m.actual_length - m25p_cmdsz(flash) -
+			(flash->fast_read ? 1 : 0);
 
 	mutex_unlock(&flash->lock);
 
@@ -664,7 +661,8 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
 
 	/* Micron */
-	{ "n25q128",  INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
+	{ "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024, 256, 0) },
+	{ "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
 	{ "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
 
 	/* Spansion -- single (large) sector size only, at least
@@ -745,6 +743,8 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
 	{ "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
 	{ "w25q80", INFO(0xef5014, 0, 64 * 1024,  16, SECT_4K) },
+	{ "w25q80bl", INFO(0xef4014, 0, 64 * 1024,  16, SECT_4K) },
+	{ "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) },
 
 	/* Catalyst / On Semiconductor -- non-JEDEC */
 	{ "cat25c11", CAT25_INFO(  16, 8, 16, 1) },
@@ -756,7 +756,7 @@ static const struct spi_device_id m25p_ids[] = {
 };
 MODULE_DEVICE_TABLE(spi, m25p_ids);
 
-static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
+static const struct spi_device_id *jedec_probe(struct spi_device *spi)
 {
 	int			tmp;
 	u8			code = OPCODE_RDID;
@@ -801,7 +801,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
  * matches what the READ command supports, at least until this driver
  * understands FAST_READ (for clocks over 25 MHz).
  */
-static int __devinit m25p_probe(struct spi_device *spi)
+static int m25p_probe(struct spi_device *spi)
 {
 	const struct spi_device_id	*id = spi_get_device_id(spi);
 	struct flash_platform_data	*data;
@@ -809,9 +809,10 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	struct flash_info		*info;
 	unsigned			i;
 	struct mtd_part_parser_data	ppdata;
+	struct device_node __maybe_unused *np = spi->dev.of_node;
 
 #ifdef CONFIG_MTD_OF_PARTS
-	if (!of_device_is_available(spi->dev.of_node))
+	if (!of_device_is_available(np))
 		return -ENODEV;
 #endif
 
@@ -863,7 +864,8 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	flash = kzalloc(sizeof *flash, GFP_KERNEL);
 	if (!flash)
 		return -ENOMEM;
-	flash->command = kmalloc(MAX_CMD_SIZE + FAST_READ_DUMMY_BYTE, GFP_KERNEL);
+	flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : 0),
+					GFP_KERNEL);
 	if (!flash->command) {
 		kfree(flash);
 		return -ENOMEM;
@@ -920,6 +922,16 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	flash->page_size = info->page_size;
 	flash->mtd.writebufsize = flash->page_size;
 
+	flash->fast_read = false;
+#ifdef CONFIG_OF
+	if (np && of_property_read_bool(np, "m25p,fast-read"))
+		flash->fast_read = true;
+#endif
+
+#ifdef CONFIG_M25PXX_USE_FAST_READ
+	flash->fast_read = true;
+#endif
+
 	if (info->addr_width)
 		flash->addr_width = info->addr_width;
 	else {
@@ -961,7 +973,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
 }
 
 
-static int __devexit m25p_remove(struct spi_device *spi)
+static int m25p_remove(struct spi_device *spi)
 {
 	struct m25p	*flash = dev_get_drvdata(&spi->dev);
 	int		status;
@@ -983,7 +995,7 @@ static struct spi_driver m25p80_driver = {
 	},
 	.id_table	= m25p_ids,
 	.probe	= m25p_probe,
-	.remove	= __devexit_p(m25p_remove),
+	.remove	= m25p_remove,
 
 	/* REVISIT: many of these chips have deep power-down modes, which
 	 * should clearly be entered on suspend() to minimize power use.
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 928fb0e..ea7ea7b 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -618,7 +618,7 @@ static char *otp_setup(struct mtd_info *device, char revision)
 /*
  * Register DataFlash device with MTD subsystem.
  */
-static int __devinit
+static int
 add_dataflash_otp(struct spi_device *spi, char *name,
 		int nr_pages, int pagesize, int pageoffset, char revision)
 {
@@ -679,7 +679,7 @@ add_dataflash_otp(struct spi_device *spi, char *name,
 	return err;
 }
 
-static inline int __devinit
+static inline int
 add_dataflash(struct spi_device *spi, char *name,
 		int nr_pages, int pagesize, int pageoffset)
 {
@@ -705,7 +705,7 @@ struct flash_info {
 #define IS_POW2PS	0x0001		/* uses 2^N byte pages */
 };
 
-static struct flash_info __devinitdata dataflash_data [] = {
+static struct flash_info dataflash_data[] = {
 
 	/*
 	 * NOTE:  chips with SUP_POW2PS (rev D and up) need two entries,
@@ -740,7 +740,7 @@ static struct flash_info __devinitdata dataflash_data [] = {
 	{ "at45db642d",  0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS},
 };
 
-static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
+static struct flash_info *jedec_probe(struct spi_device *spi)
 {
 	int			tmp;
 	uint8_t			code = OP_READ_ID;
@@ -823,7 +823,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
  *   AT45DB0642  64Mbit  (8M)    xx111xxx (0x3c)   8192   1056     11
  *   AT45DB1282  128Mbit (16M)   xx0100xx (0x10)  16384   1056     11
  */
-static int __devinit dataflash_probe(struct spi_device *spi)
+static int dataflash_probe(struct spi_device *spi)
 {
 	int status;
 	struct flash_info	*info;
@@ -897,7 +897,7 @@ static int __devinit dataflash_probe(struct spi_device *spi)
 	return status;
 }
 
-static int __devexit dataflash_remove(struct spi_device *spi)
+static int dataflash_remove(struct spi_device *spi)
 {
 	struct dataflash	*flash = dev_get_drvdata(&spi->dev);
 	int			status;
@@ -920,7 +920,7 @@ static struct spi_driver dataflash_driver = {
 	},
 
 	.probe		= dataflash_probe,
-	.remove		= __devexit_p(dataflash_remove),
+	.remove		= dataflash_remove,
 
 	/* FIXME:  investigate suspend and resume... */
 };
diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c
index dcc3c95..2d2c2a5 100644
--- a/drivers/mtd/devices/spear_smi.c
+++ b/drivers/mtd/devices/spear_smi.c
@@ -756,7 +756,7 @@ err_probe:
 
 
 #ifdef CONFIG_OF
-static int __devinit spear_smi_probe_config_dt(struct platform_device *pdev,
+static int spear_smi_probe_config_dt(struct platform_device *pdev,
 					       struct device_node *np)
 {
 	struct spear_smi_plat_data *pdata = dev_get_platdata(&pdev->dev);
@@ -799,7 +799,7 @@ static int __devinit spear_smi_probe_config_dt(struct platform_device *pdev,
 	return 0;
 }
 #else
-static int __devinit spear_smi_probe_config_dt(struct platform_device *pdev,
+static int spear_smi_probe_config_dt(struct platform_device *pdev,
 					       struct device_node *np)
 {
 	return -ENOSYS;
@@ -901,7 +901,7 @@ static int spear_smi_setup_banks(struct platform_device *pdev,
  * and do proper init for any found one.
  * Returns 0 on success, non zero otherwise
  */
-static int __devinit spear_smi_probe(struct platform_device *pdev)
+static int spear_smi_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct spear_smi_plat_data *pdata = NULL;
@@ -1016,7 +1016,7 @@ err:
  *
  * free all allocations and delete the partitions.
  */
-static int __devexit spear_smi_remove(struct platform_device *pdev)
+static int spear_smi_remove(struct platform_device *pdev)
 {
 	struct spear_smi *dev;
 	struct spear_snor_flash *flash;
@@ -1092,20 +1092,9 @@ static struct platform_driver spear_smi_driver = {
 #endif
 	},
 	.probe = spear_smi_probe,
-	.remove = __devexit_p(spear_smi_remove),
+	.remove = spear_smi_remove,
 };
-
-static int spear_smi_init(void)
-{
-	return platform_driver_register(&spear_smi_driver);
-}
-module_init(spear_smi_init);
-
-static void spear_smi_exit(void)
-{
-	platform_driver_unregister(&spear_smi_driver);
-}
-module_exit(spear_smi_exit);
+module_platform_driver(spear_smi_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ashish Priyadarshi, Shiraz Hashim <shiraz.hashim@st.com>");
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
index ab8a2f4..8091b01 100644
--- a/drivers/mtd/devices/sst25l.c
+++ b/drivers/mtd/devices/sst25l.c
@@ -64,7 +64,7 @@ struct flash_info {
 
 #define to_sst25l_flash(x) container_of(x, struct sst25l_flash, mtd)
 
-static struct flash_info __devinitdata sst25l_flash_info[] = {
+static struct flash_info sst25l_flash_info[] = {
 	{"sst25lf020a", 0xbf43, 256, 1024, 4096},
 	{"sst25lf040a",	0xbf44,	256, 2048, 4096},
 };
@@ -313,7 +313,7 @@ out:
 	return ret;
 }
 
-static struct flash_info *__devinit sst25l_match_device(struct spi_device *spi)
+static struct flash_info *sst25l_match_device(struct spi_device *spi)
 {
 	struct flash_info *flash_info = NULL;
 	struct spi_message m;
@@ -353,7 +353,7 @@ static struct flash_info *__devinit sst25l_match_device(struct spi_device *spi)
 	return flash_info;
 }
 
-static int __devinit sst25l_probe(struct spi_device *spi)
+static int sst25l_probe(struct spi_device *spi)
 {
 	struct flash_info *flash_info;
 	struct sst25l_flash *flash;
@@ -411,7 +411,7 @@ static int __devinit sst25l_probe(struct spi_device *spi)
 	return 0;
 }
 
-static int __devexit sst25l_remove(struct spi_device *spi)
+static int sst25l_remove(struct spi_device *spi)
 {
 	struct sst25l_flash *flash = dev_get_drvdata(&spi->dev);
 	int ret;
@@ -428,7 +428,7 @@ static struct spi_driver sst25l_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= sst25l_probe,
-	.remove		= __devexit_p(sst25l_remove),
+	.remove		= sst25l_remove,
 };
 
 module_spi_driver(sst25l_driver);
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 2e47c2e..62ba82c 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -324,13 +324,6 @@ config MTD_SOLUTIONENGINE
 	  This enables access to the flash chips on the Hitachi SolutionEngine and
 	  similar boards. Say 'Y' if you are building a kernel for such a board.
 
-config MTD_CDB89712
-	tristate "Cirrus CDB89712 evaluation board mappings"
-	depends on MTD_CFI && ARCH_CDB89712
-	help
-	  This enables access to the flash or ROM chips on the CDB89712 board.
-	  If you have such a board, say 'Y'.
-
 config MTD_SA1100
 	tristate "CFI Flash device mapped on StrongARM SA11x0"
 	depends on MTD_CFI && ARCH_SA1100
@@ -365,13 +358,6 @@ config MTD_IXP2000
 	  IXP2000 based board and would like to use the flash chips on it,
 	  say 'Y'.
 
-config MTD_FORTUNET
-	tristate "CFI Flash device mapped on the FortuNet board"
-	depends on MTD_CFI && SA1100_FORTUNET
-	help
-	  This enables access to the Flash on the FortuNet board.  If you
-	  have such a board, say 'Y'.
-
 config MTD_AUTCPU12
 	bool "NV-RAM mapping AUTCPU12 board"
 	depends on ARCH_AUTCPU12
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index deb43e9..4ded287 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -7,7 +7,6 @@ obj-$(CONFIG_MTD)		+= map_funcs.o
 endif
 
 # Chip mappings
-obj-$(CONFIG_MTD_CDB89712)	+= cdb89712.o
 obj-$(CONFIG_MTD_CFI_FLAGADM)	+= cfi_flagadm.o
 obj-$(CONFIG_MTD_DC21285)	+= dc21285.o
 obj-$(CONFIG_MTD_DILNETPC)	+= dilnetpc.o
@@ -40,7 +39,6 @@ obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
 obj-$(CONFIG_MTD_PCI)		+= pci.o
 obj-$(CONFIG_MTD_AUTCPU12)	+= autcpu12-nvram.o
 obj-$(CONFIG_MTD_IMPA7)		+= impa7.o
-obj-$(CONFIG_MTD_FORTUNET)	+= fortunet.o
 obj-$(CONFIG_MTD_UCLINUX)	+= uclinux.o
 obj-$(CONFIG_MTD_NETtel)	+= nettel.o
 obj-$(CONFIG_MTD_SCB2_FLASH)	+= scb2_flash.o
diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c
index e2875d6..f7207b0 100644
--- a/drivers/mtd/maps/amd76xrom.c
+++ b/drivers/mtd/maps/amd76xrom.c
@@ -100,8 +100,8 @@ static void amd76xrom_cleanup(struct amd76xrom_window *window)
 }
 
 
-static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
-	const struct pci_device_id *ent)
+static int amd76xrom_init_one(struct pci_dev *pdev,
+			      const struct pci_device_id *ent)
 {
 	static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
 	u8 byte;
@@ -289,7 +289,7 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
 }
 
 
-static void __devexit amd76xrom_remove_one (struct pci_dev *pdev)
+static void amd76xrom_remove_one(struct pci_dev *pdev)
 {
 	struct amd76xrom_window *window = &amd76xrom_window;
 
@@ -347,4 +347,3 @@ module_exit(cleanup_amd76xrom);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>");
 MODULE_DESCRIPTION("MTD map driver for BIOS chips on the AMD76X southbridge");
-
diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-nvram.c
index 76fb594..a2dc2ae 100644
--- a/drivers/mtd/maps/autcpu12-nvram.c
+++ b/drivers/mtd/maps/autcpu12-nvram.c
@@ -33,7 +33,7 @@ struct autcpu12_nvram_priv {
 	struct map_info map;
 };
 
-static int __devinit autcpu12_nvram_probe(struct platform_device *pdev)
+static int autcpu12_nvram_probe(struct platform_device *pdev)
 {
 	map_word tmp, save0, save1;
 	struct resource *res;
@@ -105,7 +105,7 @@ static int __devinit autcpu12_nvram_probe(struct platform_device *pdev)
 	return -ENOMEM;
 }
 
-static int __devexit autcpu12_nvram_remove(struct platform_device *pdev)
+static int autcpu12_nvram_remove(struct platform_device *pdev)
 {
 	struct autcpu12_nvram_priv *priv = platform_get_drvdata(pdev);
 
@@ -121,7 +121,7 @@ static struct platform_driver autcpu12_nvram_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= autcpu12_nvram_probe,
-	.remove		= __devexit_p(autcpu12_nvram_remove),
+	.remove		= autcpu12_nvram_remove,
 };
 module_platform_driver(autcpu12_nvram_driver);
 
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
index ef5cde8..f833edf 100644
--- a/drivers/mtd/maps/bfin-async-flash.c
+++ b/drivers/mtd/maps/bfin-async-flash.c
@@ -30,7 +30,8 @@
 #include <linux/io.h>
 #include <asm/unaligned.h>
 
-#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); })
+#define pr_devinit(fmt, args...) \
+		({ static const char __fmt[] = fmt; printk(__fmt, ## args); })
 
 #define DRIVER_NAME "bfin-async-flash"
 
@@ -123,7 +124,7 @@ static void bfin_flash_copy_to(struct map_info *map, unsigned long to, const voi
 
 static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
 
-static int __devinit bfin_flash_probe(struct platform_device *pdev)
+static int bfin_flash_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct physmap_flash_data *pdata = pdev->dev.platform_data;
@@ -172,7 +173,7 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit bfin_flash_remove(struct platform_device *pdev)
+static int bfin_flash_remove(struct platform_device *pdev)
 {
 	struct async_state *state = platform_get_drvdata(pdev);
 	gpio_free(state->enet_flash_pin);
@@ -184,7 +185,7 @@ static int __devexit bfin_flash_remove(struct platform_device *pdev)
 
 static struct platform_driver bfin_flash_driver = {
 	.probe		= bfin_flash_probe,
-	.remove		= __devexit_p(bfin_flash_remove),
+	.remove		= bfin_flash_remove,
 	.driver		= {
 		.name	= DRIVER_NAME,
 	},
diff --git a/drivers/mtd/maps/cdb89712.c b/drivers/mtd/maps/cdb89712.c
deleted file mode 100644
index c29cbf8..0000000
--- a/drivers/mtd/maps/cdb89712.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Flash on Cirrus CDB89712
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-/* dynamic ioremap() areas */
-#define FLASH_START      0x00000000
-#define FLASH_SIZE       0x800000
-#define FLASH_WIDTH      4
-
-#define SRAM_START       0x60000000
-#define SRAM_SIZE        0xc000
-#define SRAM_WIDTH       4
-
-#define BOOTROM_START    0x70000000
-#define BOOTROM_SIZE     0x80
-#define BOOTROM_WIDTH    4
-
-
-static struct mtd_info *flash_mtd;
-
-struct map_info cdb89712_flash_map = {
-	.name = "flash",
-	.size = FLASH_SIZE,
-	.bankwidth = FLASH_WIDTH,
-	.phys = FLASH_START,
-};
-
-struct resource cdb89712_flash_resource = {
-	.name =   "Flash",
-	.start =  FLASH_START,
-	.end =    FLASH_START + FLASH_SIZE - 1,
-	.flags =  IORESOURCE_IO | IORESOURCE_BUSY,
-};
-
-static int __init init_cdb89712_flash (void)
-{
-	int err;
-
-	if (request_resource (&ioport_resource, &cdb89712_flash_resource)) {
-		printk(KERN_NOTICE "Failed to reserve Cdb89712 FLASH space\n");
-		err = -EBUSY;
-		goto out;
-	}
-
-	cdb89712_flash_map.virt = ioremap(FLASH_START, FLASH_SIZE);
-	if (!cdb89712_flash_map.virt) {
-		printk(KERN_NOTICE "Failed to ioremap Cdb89712 FLASH space\n");
-		err = -EIO;
-		goto out_resource;
-	}
-	simple_map_init(&cdb89712_flash_map);
-	flash_mtd = do_map_probe("cfi_probe", &cdb89712_flash_map);
-	if (!flash_mtd) {
-		flash_mtd = do_map_probe("map_rom", &cdb89712_flash_map);
-		if (flash_mtd)
-			flash_mtd->erasesize = 0x10000;
-	}
-	if (!flash_mtd) {
-		printk("FLASH probe failed\n");
-		err = -ENXIO;
-		goto out_ioremap;
-	}
-
-	flash_mtd->owner = THIS_MODULE;
-
-	if (mtd_device_register(flash_mtd, NULL, 0)) {
-		printk("FLASH device addition failed\n");
-		err = -ENOMEM;
-		goto out_probe;
-	}
-
-	return 0;
-
-out_probe:
-	map_destroy(flash_mtd);
-	flash_mtd = 0;
-out_ioremap:
-	iounmap((void *)cdb89712_flash_map.virt);
-out_resource:
-	release_resource (&cdb89712_flash_resource);
-out:
-	return err;
-}
-
-
-
-
-
-static struct mtd_info *sram_mtd;
-
-struct map_info cdb89712_sram_map = {
-	.name = "SRAM",
-	.size = SRAM_SIZE,
-	.bankwidth = SRAM_WIDTH,
-	.phys = SRAM_START,
-};
-
-struct resource cdb89712_sram_resource = {
-	.name =   "SRAM",
-	.start =  SRAM_START,
-	.end =    SRAM_START + SRAM_SIZE - 1,
-	.flags =  IORESOURCE_IO | IORESOURCE_BUSY,
-};
-
-static int __init init_cdb89712_sram (void)
-{
-	int err;
-
-	if (request_resource (&ioport_resource, &cdb89712_sram_resource)) {
-		printk(KERN_NOTICE "Failed to reserve Cdb89712 SRAM space\n");
-		err = -EBUSY;
-		goto out;
-	}
-
-	cdb89712_sram_map.virt = ioremap(SRAM_START, SRAM_SIZE);
-	if (!cdb89712_sram_map.virt) {
-		printk(KERN_NOTICE "Failed to ioremap Cdb89712 SRAM space\n");
-		err = -EIO;
-		goto out_resource;
-	}
-	simple_map_init(&cdb89712_sram_map);
-	sram_mtd = do_map_probe("map_ram", &cdb89712_sram_map);
-	if (!sram_mtd) {
-		printk("SRAM probe failed\n");
-		err = -ENXIO;
-		goto out_ioremap;
-	}
-
-	sram_mtd->owner = THIS_MODULE;
-	sram_mtd->erasesize = 16;
-
-	if (mtd_device_register(sram_mtd, NULL, 0)) {
-		printk("SRAM device addition failed\n");
-		err = -ENOMEM;
-		goto out_probe;
-	}
-
-	return 0;
-
-out_probe:
-	map_destroy(sram_mtd);
-	sram_mtd = 0;
-out_ioremap:
-	iounmap((void *)cdb89712_sram_map.virt);
-out_resource:
-	release_resource (&cdb89712_sram_resource);
-out:
-	return err;
-}
-
-
-
-
-
-
-
-static struct mtd_info *bootrom_mtd;
-
-struct map_info cdb89712_bootrom_map = {
-	.name = "BootROM",
-	.size = BOOTROM_SIZE,
-	.bankwidth = BOOTROM_WIDTH,
-	.phys = BOOTROM_START,
-};
-
-struct resource cdb89712_bootrom_resource = {
-	.name =   "BootROM",
-	.start =  BOOTROM_START,
-	.end =    BOOTROM_START + BOOTROM_SIZE - 1,
-	.flags =  IORESOURCE_IO | IORESOURCE_BUSY,
-};
-
-static int __init init_cdb89712_bootrom (void)
-{
-	int err;
-
-	if (request_resource (&ioport_resource, &cdb89712_bootrom_resource)) {
-		printk(KERN_NOTICE "Failed to reserve Cdb89712 BOOTROM space\n");
-		err = -EBUSY;
-		goto out;
-	}
-
-	cdb89712_bootrom_map.virt = ioremap(BOOTROM_START, BOOTROM_SIZE);
-	if (!cdb89712_bootrom_map.virt) {
-		printk(KERN_NOTICE "Failed to ioremap Cdb89712 BootROM space\n");
-		err = -EIO;
-		goto out_resource;
-	}
-	simple_map_init(&cdb89712_bootrom_map);
-	bootrom_mtd = do_map_probe("map_rom", &cdb89712_bootrom_map);
-	if (!bootrom_mtd) {
-		printk("BootROM probe failed\n");
-		err = -ENXIO;
-		goto out_ioremap;
-	}
-
-	bootrom_mtd->owner = THIS_MODULE;
-	bootrom_mtd->erasesize = 0x10000;
-
-	if (mtd_device_register(bootrom_mtd, NULL, 0)) {
-		printk("BootROM device addition failed\n");
-		err = -ENOMEM;
-		goto out_probe;
-	}
-
-	return 0;
-
-out_probe:
-	map_destroy(bootrom_mtd);
-	bootrom_mtd = 0;
-out_ioremap:
-	iounmap((void *)cdb89712_bootrom_map.virt);
-out_resource:
-	release_resource (&cdb89712_bootrom_resource);
-out:
-	return err;
-}
-
-
-
-
-
-static int __init init_cdb89712_maps(void)
-{
-
-       	printk(KERN_INFO "Cirrus CDB89712 MTD mappings:\n  Flash 0x%x at 0x%x\n  SRAM 0x%x at 0x%x\n  BootROM 0x%x at 0x%x\n",
-	       FLASH_SIZE, FLASH_START, SRAM_SIZE, SRAM_START, BOOTROM_SIZE, BOOTROM_START);
-
-	init_cdb89712_flash();
-	init_cdb89712_sram();
-	init_cdb89712_bootrom();
-
-	return 0;
-}
-
-
-static void __exit cleanup_cdb89712_maps(void)
-{
-	if (sram_mtd) {
-		mtd_device_unregister(sram_mtd);
-		map_destroy(sram_mtd);
-		iounmap((void *)cdb89712_sram_map.virt);
-		release_resource (&cdb89712_sram_resource);
-	}
-
-	if (flash_mtd) {
-		mtd_device_unregister(flash_mtd);
-		map_destroy(flash_mtd);
-		iounmap((void *)cdb89712_flash_map.virt);
-		release_resource (&cdb89712_flash_resource);
-	}
-
-	if (bootrom_mtd) {
-		mtd_device_unregister(bootrom_mtd);
-		map_destroy(bootrom_mtd);
-		iounmap((void *)cdb89712_bootrom_map.virt);
-		release_resource (&cdb89712_bootrom_resource);
-	}
-}
-
-module_init(init_cdb89712_maps);
-module_exit(cleanup_cdb89712_maps);
-
-MODULE_AUTHOR("Ray L");
-MODULE_DESCRIPTION("ARM CDB89712 map driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
index 3d0e762..586a1c7 100644
--- a/drivers/mtd/maps/ck804xrom.c
+++ b/drivers/mtd/maps/ck804xrom.c
@@ -112,8 +112,8 @@ static void ck804xrom_cleanup(struct ck804xrom_window *window)
 }
 
 
-static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
-					 const struct pci_device_id *ent)
+static int ck804xrom_init_one(struct pci_dev *pdev,
+			      const struct pci_device_id *ent)
 {
 	static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
 	u8 byte;
@@ -320,7 +320,7 @@ static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
 }
 
 
-static void __devexit ck804xrom_remove_one (struct pci_dev *pdev)
+static void ck804xrom_remove_one(struct pci_dev *pdev)
 {
 	struct ck804xrom_window *window = &ck804xrom_window;
 
diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c
index 08322b1..ff8681a 100644
--- a/drivers/mtd/maps/esb2rom.c
+++ b/drivers/mtd/maps/esb2rom.c
@@ -144,7 +144,7 @@ static void esb2rom_cleanup(struct esb2rom_window *window)
 	pci_dev_put(window->pdev);
 }
 
-static int __devinit esb2rom_init_one(struct pci_dev *pdev,
+static int esb2rom_init_one(struct pci_dev *pdev,
 				      const struct pci_device_id *ent)
 {
 	static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
@@ -378,13 +378,13 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev,
 	return 0;
 }
 
-static void __devexit esb2rom_remove_one (struct pci_dev *pdev)
+static void esb2rom_remove_one(struct pci_dev *pdev)
 {
 	struct esb2rom_window *window = &esb2rom_window;
 	esb2rom_cleanup(window);
 }
 
-static struct pci_device_id esb2rom_pci_tbl[] __devinitdata = {
+static struct pci_device_id esb2rom_pci_tbl[] = {
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
 	  PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
diff --git a/drivers/mtd/maps/fortunet.c b/drivers/mtd/maps/fortunet.c
deleted file mode 100644
index 956e2e4..0000000
--- a/drivers/mtd/maps/fortunet.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/* fortunet.c memory map
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/string.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/io.h>
-
-#define MAX_NUM_REGIONS		4
-#define MAX_NUM_PARTITIONS	8
-
-#define DEF_WINDOW_ADDR_PHY	0x00000000
-#define DEF_WINDOW_SIZE		0x00800000		// 8 Mega Bytes
-
-#define MTD_FORTUNET_PK		"MTD FortuNet: "
-
-#define MAX_NAME_SIZE		128
-
-struct map_region
-{
-	int			window_addr_physical;
-	int			altbankwidth;
-	struct map_info		map_info;
-	struct mtd_info		*mymtd;
-	struct mtd_partition	parts[MAX_NUM_PARTITIONS];
-	char			map_name[MAX_NAME_SIZE];
-	char			parts_name[MAX_NUM_PARTITIONS][MAX_NAME_SIZE];
-};
-
-static struct map_region	map_regions[MAX_NUM_REGIONS];
-static int			map_regions_set[MAX_NUM_REGIONS] = {0,0,0,0};
-static int			map_regions_parts[MAX_NUM_REGIONS] = {0,0,0,0};
-
-
-
-struct map_info default_map = {
-	.size = DEF_WINDOW_SIZE,
-	.bankwidth = 4,
-};
-
-static char * __init get_string_option(char *dest,int dest_size,char *sor)
-{
-	if(!dest_size)
-		return sor;
-	dest_size--;
-	while(*sor)
-	{
-		if(*sor==',')
-		{
-			sor++;
-			break;
-		}
-		else if(*sor=='\"')
-		{
-			sor++;
-			while(*sor)
-			{
-				if(*sor=='\"')
-				{
-					sor++;
-					break;
-				}
-				*dest = *sor;
-				dest++;
-				sor++;
-				dest_size--;
-				if(!dest_size)
-				{
-					*dest = 0;
-					return sor;
-				}
-			}
-		}
-		else
-		{
-			*dest = *sor;
-			dest++;
-			sor++;
-			dest_size--;
-			if(!dest_size)
-			{
-				*dest = 0;
-				return sor;
-			}
-		}
-	}
-	*dest = 0;
-	return sor;
-}
-
-static int __init MTD_New_Region(char *line)
-{
-	char	string[MAX_NAME_SIZE];
-	int	params[6];
-	get_options (get_string_option(string,sizeof(string),line),6,params);
-	if(params[0]<1)
-	{
-		printk(MTD_FORTUNET_PK "Bad parameters for MTD Region "
-			" name,region-number[,base,size,bankwidth,altbankwidth]\n");
-		return 1;
-	}
-	if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS))
-	{
-		printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n",
-			params[1],MAX_NUM_REGIONS-1);
-		return 1;
-	}
-	memset(&map_regions[params[1]],0,sizeof(map_regions[params[1]]));
-	memcpy(&map_regions[params[1]].map_info,
-		&default_map,sizeof(map_regions[params[1]].map_info));
-        map_regions_set[params[1]] = 1;
-        map_regions[params[1]].window_addr_physical = DEF_WINDOW_ADDR_PHY;
-        map_regions[params[1]].altbankwidth = 2;
-        map_regions[params[1]].mymtd = NULL;
-	map_regions[params[1]].map_info.name = map_regions[params[1]].map_name;
-	strcpy(map_regions[params[1]].map_info.name,string);
-	if(params[0]>1)
-	{
-		map_regions[params[1]].window_addr_physical = params[2];
-	}
-	if(params[0]>2)
-	{
-		map_regions[params[1]].map_info.size = params[3];
-	}
-	if(params[0]>3)
-	{
-		map_regions[params[1]].map_info.bankwidth = params[4];
-	}
-	if(params[0]>4)
-	{
-		map_regions[params[1]].altbankwidth = params[5];
-	}
-	return 1;
-}
-
-static int __init MTD_New_Partition(char *line)
-{
-	char	string[MAX_NAME_SIZE];
-	int	params[4];
-	get_options (get_string_option(string,sizeof(string),line),4,params);
-	if(params[0]<3)
-	{
-		printk(MTD_FORTUNET_PK "Bad parameters for MTD Partition "
-			" name,region-number,size,offset\n");
-		return 1;
-	}
-	if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS))
-	{
-		printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n",
-			params[1],MAX_NUM_REGIONS-1);
-		return 1;
-	}
-	if(map_regions_parts[params[1]]>=MAX_NUM_PARTITIONS)
-	{
-		printk(MTD_FORTUNET_PK "Out of space for partition in this region\n");
-		return 1;
-	}
-	map_regions[params[1]].parts[map_regions_parts[params[1]]].name =
-		map_regions[params[1]].	parts_name[map_regions_parts[params[1]]];
-	strcpy(map_regions[params[1]].parts[map_regions_parts[params[1]]].name,string);
-	map_regions[params[1]].parts[map_regions_parts[params[1]]].size =
-		params[2];
-	map_regions[params[1]].parts[map_regions_parts[params[1]]].offset =
-		params[3];
-	map_regions[params[1]].parts[map_regions_parts[params[1]]].mask_flags = 0;
-	map_regions_parts[params[1]]++;
-	return 1;
-}
-
-__setup("MTD_Region=", MTD_New_Region);
-__setup("MTD_Partition=", MTD_New_Partition);
-
-/* Backwards-spelling-compatibility */
-__setup("MTD_Partion=", MTD_New_Partition);
-
-static int __init init_fortunet(void)
-{
-	int	ix,iy;
-	for(iy=ix=0;ix<MAX_NUM_REGIONS;ix++)
-	{
-		if(map_regions_parts[ix]&&(!map_regions_set[ix]))
-		{
-			printk(MTD_FORTUNET_PK "Region %d is not setup (Setting to default)\n",
-				ix);
-			memset(&map_regions[ix],0,sizeof(map_regions[ix]));
-			memcpy(&map_regions[ix].map_info,&default_map,
-				sizeof(map_regions[ix].map_info));
-			map_regions_set[ix] = 1;
-			map_regions[ix].window_addr_physical = DEF_WINDOW_ADDR_PHY;
-			map_regions[ix].altbankwidth = 2;
-			map_regions[ix].mymtd = NULL;
-			map_regions[ix].map_info.name = map_regions[ix].map_name;
-			strcpy(map_regions[ix].map_info.name,"FORTUNET");
-		}
-		if(map_regions_set[ix])
-		{
-			iy++;
-			printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash device at physically "
-				" address %x size %x\n",
-				map_regions[ix].map_info.name,
-				map_regions[ix].window_addr_physical,
-				map_regions[ix].map_info.size);
-
-			map_regions[ix].map_info.phys =	map_regions[ix].window_addr_physical,
-
-			map_regions[ix].map_info.virt =
-				ioremap_nocache(
-				map_regions[ix].window_addr_physical,
-				map_regions[ix].map_info.size);
-			if(!map_regions[ix].map_info.virt)
-			{
-				int j = 0;
-				printk(MTD_FORTUNET_PK "%s flash failed to ioremap!\n",
-					map_regions[ix].map_info.name);
-				for (j = 0 ; j < ix; j++)
-					iounmap(map_regions[j].map_info.virt);
-				return -ENXIO;
-			}
-			simple_map_init(&map_regions[ix].map_info);
-
-			printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash is virtually at: %x\n",
-				map_regions[ix].map_info.name,
-				map_regions[ix].map_info.virt);
-			map_regions[ix].mymtd = do_map_probe("cfi_probe",
-				&map_regions[ix].map_info);
-			if((!map_regions[ix].mymtd)&&(
-				map_regions[ix].altbankwidth!=map_regions[ix].map_info.bankwidth))
-			{
-				printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternate bankwidth "
-					"for %s flash.\n",
-					map_regions[ix].map_info.name);
-				map_regions[ix].map_info.bankwidth =
-					map_regions[ix].altbankwidth;
-				map_regions[ix].mymtd = do_map_probe("cfi_probe",
-					&map_regions[ix].map_info);
-			}
-			map_regions[ix].mymtd->owner = THIS_MODULE;
-			mtd_device_register(map_regions[ix].mymtd,
-					    map_regions[ix].parts,
-					    map_regions_parts[ix]);
-		}
-	}
-	if(iy)
-		return 0;
-	return -ENXIO;
-}
-
-static void __exit cleanup_fortunet(void)
-{
-	int	ix;
-	for(ix=0;ix<MAX_NUM_REGIONS;ix++)
-	{
-		if(map_regions_set[ix])
-		{
-			if( map_regions[ix].mymtd )
-			{
-				mtd_device_unregister(map_regions[ix].mymtd);
-				map_destroy( map_regions[ix].mymtd );
-			}
-			iounmap((void *)map_regions[ix].map_info.virt);
-		}
-	}
-}
-
-module_init(init_fortunet);
-module_exit(cleanup_fortunet);
-
-MODULE_AUTHOR("FortuNet, Inc.");
-MODULE_DESCRIPTION("MTD map driver for FortuNet boards");
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
index e4de96b..7b643de 100644
--- a/drivers/mtd/maps/gpio-addr-flash.c
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -26,7 +26,8 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 
-#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); })
+#define pr_devinit(fmt, args...) \
+	({ static const char __fmt[] = fmt; printk(__fmt, ## args); })
 
 #define DRIVER_NAME "gpio-addr-flash"
 #define PFX DRIVER_NAME ": "
@@ -142,7 +143,8 @@ static void gf_write(struct map_info *map, map_word d1, unsigned long ofs)
  *
  * See gf_copy_from() caveat.
  */
-static void gf_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
+static void gf_copy_to(struct map_info *map, unsigned long to,
+		       const void *from, ssize_t len)
 {
 	struct async_state *state = gf_map_info_to_state(map);
 
@@ -185,7 +187,7 @@ static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
  *	...
  * };
  */
-static int __devinit gpio_flash_probe(struct platform_device *pdev)
+static int gpio_flash_probe(struct platform_device *pdev)
 {
 	size_t i, arr_size;
 	struct physmap_flash_data *pdata;
@@ -258,7 +260,7 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit gpio_flash_remove(struct platform_device *pdev)
+static int gpio_flash_remove(struct platform_device *pdev)
 {
 	struct async_state *state = platform_get_drvdata(pdev);
 	size_t i = 0;
@@ -273,7 +275,7 @@ static int __devexit gpio_flash_remove(struct platform_device *pdev)
 
 static struct platform_driver gpio_flash_driver = {
 	.probe		= gpio_flash_probe,
-	.remove		= __devexit_p(gpio_flash_remove),
+	.remove		= gpio_flash_remove,
 	.driver		= {
 		.name	= DRIVER_NAME,
 	},
diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c
index 6689dcb..c7478e1 100644
--- a/drivers/mtd/maps/ichxrom.c
+++ b/drivers/mtd/maps/ichxrom.c
@@ -84,8 +84,8 @@ static void ichxrom_cleanup(struct ichxrom_window *window)
 }
 
 
-static int __devinit ichxrom_init_one (struct pci_dev *pdev,
-	const struct pci_device_id *ent)
+static int ichxrom_init_one(struct pci_dev *pdev,
+			    const struct pci_device_id *ent)
 {
 	static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
 	struct ichxrom_window *window = &ichxrom_window;
@@ -315,13 +315,13 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev,
 }
 
 
-static void __devexit ichxrom_remove_one (struct pci_dev *pdev)
+static void ichxrom_remove_one(struct pci_dev *pdev)
 {
 	struct ichxrom_window *window = &ichxrom_window;
 	ichxrom_cleanup(window);
 }
 
-static struct pci_device_id ichxrom_pci_tbl[] __devinitdata = {
+static struct pci_device_id ichxrom_pci_tbl[] = {
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
 	  PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c
index 93f0317..3ee2ad1 100644
--- a/drivers/mtd/maps/intel_vr_nor.c
+++ b/drivers/mtd/maps/intel_vr_nor.c
@@ -63,24 +63,24 @@ struct vr_nor_mtd {
 #define TIMING_BYTE_EN		(1 <<  0)	/* 8-bit vs 16-bit bus */
 #define TIMING_MASK		0x3FFF0000
 
-static void __devexit vr_nor_destroy_partitions(struct vr_nor_mtd *p)
+static void vr_nor_destroy_partitions(struct vr_nor_mtd *p)
 {
 	mtd_device_unregister(p->info);
 }
 
-static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p)
+static int vr_nor_init_partitions(struct vr_nor_mtd *p)
 {
 	/* register the flash bank */
 	/* partition the flash bank */
 	return mtd_device_parse_register(p->info, NULL, NULL, NULL, 0);
 }
 
-static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p)
+static void vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p)
 {
 	map_destroy(p->info);
 }
 
-static int __devinit vr_nor_mtd_setup(struct vr_nor_mtd *p)
+static int vr_nor_mtd_setup(struct vr_nor_mtd *p)
 {
 	static const char *probe_types[] =
 	    { "cfi_probe", "jedec_probe", NULL };
@@ -96,7 +96,7 @@ static int __devinit vr_nor_mtd_setup(struct vr_nor_mtd *p)
 	return 0;
 }
 
-static void __devexit vr_nor_destroy_maps(struct vr_nor_mtd *p)
+static void vr_nor_destroy_maps(struct vr_nor_mtd *p)
 {
 	unsigned int exp_timing_cs0;
 
@@ -116,7 +116,7 @@ static void __devexit vr_nor_destroy_maps(struct vr_nor_mtd *p)
  * Initialize the map_info structure and map the flash.
  * Returns 0 on success, nonzero otherwise.
  */
-static int __devinit vr_nor_init_maps(struct vr_nor_mtd *p)
+static int vr_nor_init_maps(struct vr_nor_mtd *p)
 {
 	unsigned long csr_phys, csr_len;
 	unsigned long win_phys, win_len;
@@ -176,7 +176,7 @@ static struct pci_device_id vr_nor_pci_ids[] = {
 	{0,}
 };
 
-static void __devexit vr_nor_pci_remove(struct pci_dev *dev)
+static void vr_nor_pci_remove(struct pci_dev *dev)
 {
 	struct vr_nor_mtd *p = pci_get_drvdata(dev);
 
@@ -189,7 +189,7 @@ static void __devexit vr_nor_pci_remove(struct pci_dev *dev)
 	pci_disable_device(dev);
 }
 
-static int __devinit
+static int
 vr_nor_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	struct vr_nor_mtd *p = NULL;
@@ -256,7 +256,7 @@ vr_nor_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 static struct pci_driver vr_nor_pci_driver = {
 	.name = DRV_NAME,
 	.probe = vr_nor_pci_probe,
-	.remove = __devexit_p(vr_nor_pci_remove),
+	.remove = vr_nor_pci_remove,
 	.id_table = vr_nor_pci_ids,
 };
 
diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
index c03456f..3c3c791 100644
--- a/drivers/mtd/maps/lantiq-flash.c
+++ b/drivers/mtd/maps/lantiq-flash.c
@@ -45,7 +45,7 @@ struct ltq_mtd {
 };
 
 static const char ltq_map_name[] = "ltq_nor";
-static const char *ltq_probe_types[] __devinitconst = {
+static const char *ltq_probe_types[] = {
 					"cmdlinepart", "ofpart", NULL };
 
 static map_word
@@ -109,7 +109,7 @@ ltq_copy_to(struct map_info *map, unsigned long to,
 	spin_unlock_irqrestore(&ebu_lock, flags);
 }
 
-static int __devinit
+static int
 ltq_mtd_probe(struct platform_device *pdev)
 {
 	struct mtd_part_parser_data ppdata;
@@ -185,7 +185,7 @@ err_out:
 	return err;
 }
 
-static int __devexit
+static int
 ltq_mtd_remove(struct platform_device *pdev)
 {
 	struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev);
@@ -209,7 +209,7 @@ MODULE_DEVICE_TABLE(of, ltq_mtd_match);
 
 static struct platform_driver ltq_mtd_driver = {
 	.probe = ltq_mtd_probe,
-	.remove = __devexit_p(ltq_mtd_remove),
+	.remove = ltq_mtd_remove,
 	.driver = {
 		.name = "ltq-nor",
 		.owner = THIS_MODULE,
diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c
index 3c7ad17..ab0fead 100644
--- a/drivers/mtd/maps/latch-addr-flash.c
+++ b/drivers/mtd/maps/latch-addr-flash.c
@@ -125,7 +125,7 @@ static int latch_addr_flash_remove(struct platform_device *dev)
 	return 0;
 }
 
-static int __devinit latch_addr_flash_probe(struct platform_device *dev)
+static int latch_addr_flash_probe(struct platform_device *dev)
 {
 	struct latch_addr_flash_data *latch_addr_data;
 	struct latch_addr_flash_info *info;
@@ -218,7 +218,7 @@ done:
 
 static struct platform_driver latch_addr_flash_driver = {
 	.probe		= latch_addr_flash_probe,
-	.remove		= __devexit_p(latch_addr_flash_remove),
+	.remove		= latch_addr_flash_remove,
 	.driver		= {
 		.name	= DRIVER_NAME,
 	},
diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c
index 1c30c1a..ed82914 100644
--- a/drivers/mtd/maps/pci.c
+++ b/drivers/mtd/maps/pci.c
@@ -253,7 +253,7 @@ static struct pci_device_id mtd_pci_ids[] = {
  * Generic code follows.
  */
 
-static int __devinit
+static int
 mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	struct mtd_pci_info *info = (struct mtd_pci_info *)id->driver_data;
@@ -308,7 +308,7 @@ out:
 	return err;
 }
 
-static void __devexit
+static void
 mtd_pci_remove(struct pci_dev *dev)
 {
 	struct mtd_info *mtd = pci_get_drvdata(dev);
@@ -326,7 +326,7 @@ mtd_pci_remove(struct pci_dev *dev)
 static struct pci_driver mtd_pci_driver = {
 	.name =		"MTD PCI",
 	.probe =	mtd_pci_probe,
-	.remove =	__devexit_p(mtd_pci_remove),
+	.remove =	mtd_pci_remove,
 	.id_table =	mtd_pci_ids,
 };
 
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 6f19aca..cde8bf9 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -77,7 +77,7 @@ static int of_flash_remove(struct platform_device *dev)
 /* Helper function to handle probing of the obsolete "direct-mapped"
  * compatible binding, which has an extra "probe-type" property
  * describing the type of flash probe necessary. */
-static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
+static struct mtd_info *obsolete_probe(struct platform_device *dev,
 						  struct map_info *map)
 {
 	struct device_node *dp = dev->dev.of_node;
@@ -116,7 +116,7 @@ static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
    information. */
 static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
 					"ofpart", "ofoldpart", NULL };
-static const char ** __devinit of_get_probes(struct device_node *dp)
+static const char **of_get_probes(struct device_node *dp)
 {
 	const char *cp;
 	int cplen;
@@ -145,14 +145,14 @@ static const char ** __devinit of_get_probes(struct device_node *dp)
 	return res;
 }
 
-static void __devinit of_free_probes(const char **probes)
+static void of_free_probes(const char **probes)
 {
 	if (probes != part_probe_types_def)
 		kfree(probes);
 }
 
 static struct of_device_id of_flash_match[];
-static int __devinit of_flash_probe(struct platform_device *dev)
+static int of_flash_probe(struct platform_device *dev)
 {
 	const char **part_probe_types;
 	const struct of_device_id *match;
@@ -170,6 +170,7 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	resource_size_t res_size;
 	struct mtd_part_parser_data ppdata;
 	bool map_indirect;
+	const char *mtd_name;
 
 	match = of_match_device(of_flash_match, &dev->dev);
 	if (!match)
@@ -178,6 +179,8 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 
 	reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);
 
+	of_property_read_string(dp, "linux,mtd-name", &mtd_name);
+
 	/*
 	 * Get number of "reg" tuples. Scan for MTD devices on area's
 	 * described by each "reg" region. This makes it possible (including
@@ -234,7 +237,7 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 			goto err_out;
 		}
 
-		info->list[i].map.name = dev_name(&dev->dev);
+		info->list[i].map.name = mtd_name ?: dev_name(&dev->dev);
 		info->list[i].map.phys = res.start;
 		info->list[i].map.size = res_size;
 		info->list[i].map.bankwidth = be32_to_cpup(width);
diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c
index 65bd1cd..afea93b 100644
--- a/drivers/mtd/maps/pismo.c
+++ b/drivers/mtd/maps/pismo.c
@@ -58,7 +58,7 @@ static void pismo_set_vpp(struct platform_device *pdev, int on)
 	pismo->vpp(pismo->vpp_data, on);
 }
 
-static unsigned int __devinit pismo_width_to_bytes(unsigned int width)
+static unsigned int pismo_width_to_bytes(unsigned int width)
 {
 	width &= 15;
 	if (width > 2)
@@ -66,7 +66,7 @@ static unsigned int __devinit pismo_width_to_bytes(unsigned int width)
 	return 1 << width;
 }
 
-static int __devinit pismo_eeprom_read(struct i2c_client *client, void *buf,
+static int pismo_eeprom_read(struct i2c_client *client, void *buf,
 	u8 addr, size_t size)
 {
 	int ret;
@@ -88,7 +88,7 @@ static int __devinit pismo_eeprom_read(struct i2c_client *client, void *buf,
 	return ret == ARRAY_SIZE(msg) ? size : -EIO;
 }
 
-static int __devinit pismo_add_device(struct pismo_data *pismo, int i,
+static int pismo_add_device(struct pismo_data *pismo, int i,
 	struct pismo_mem *region, const char *name, void *pdata, size_t psize)
 {
 	struct platform_device *dev;
@@ -129,7 +129,7 @@ static int __devinit pismo_add_device(struct pismo_data *pismo, int i,
 	return ret;
 }
 
-static int __devinit pismo_add_nor(struct pismo_data *pismo, int i,
+static int pismo_add_nor(struct pismo_data *pismo, int i,
 	struct pismo_mem *region)
 {
 	struct physmap_flash_data data = {
@@ -143,7 +143,7 @@ static int __devinit pismo_add_nor(struct pismo_data *pismo, int i,
 		&data, sizeof(data));
 }
 
-static int __devinit pismo_add_sram(struct pismo_data *pismo, int i,
+static int pismo_add_sram(struct pismo_data *pismo, int i,
 	struct pismo_mem *region)
 {
 	struct platdata_mtd_ram data = {
@@ -154,7 +154,7 @@ static int __devinit pismo_add_sram(struct pismo_data *pismo, int i,
 		&data, sizeof(data));
 }
 
-static void __devinit pismo_add_one(struct pismo_data *pismo, int i,
+static void pismo_add_one(struct pismo_data *pismo, int i,
 	const struct pismo_cs_block *cs, phys_addr_t base)
 {
 	struct device *dev = &pismo->client->dev;
@@ -197,7 +197,7 @@ static void __devinit pismo_add_one(struct pismo_data *pismo, int i,
 	}
 }
 
-static int __devexit pismo_remove(struct i2c_client *client)
+static int pismo_remove(struct i2c_client *client)
 {
 	struct pismo_data *pismo = i2c_get_clientdata(client);
 	int i;
@@ -210,7 +210,7 @@ static int __devexit pismo_remove(struct i2c_client *client)
 	return 0;
 }
 
-static int __devinit pismo_probe(struct i2c_client *client,
+static int pismo_probe(struct i2c_client *client,
 				 const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@@ -267,7 +267,7 @@ static struct i2c_driver pismo_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= pismo_probe,
-	.remove		= __devexit_p(pismo_remove),
+	.remove		= pismo_remove,
 	.id_table	= pismo_id,
 };
 
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 891558d..2de66b0 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -219,7 +219,7 @@ static int platram_probe(struct platform_device *pdev)
 
 	platram_setrw(info, PLATRAM_RW);
 
-	/* check to see if there are any available partitions, or wether
+	/* check to see if there are any available partitions, or whether
 	 * to add this device whole */
 
 	err = mtd_device_parse_register(info->mtd, pdata->probes, NULL,
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index 81884c2..43e3dbb 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -49,7 +49,7 @@ struct pxa2xx_flash_info {
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 
-static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
+static int pxa2xx_flash_probe(struct platform_device *pdev)
 {
 	struct flash_platform_data *flash = pdev->dev.platform_data;
 	struct pxa2xx_flash_info *info;
@@ -105,7 +105,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
+static int pxa2xx_flash_remove(struct platform_device *dev)
 {
 	struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
 
@@ -139,7 +139,7 @@ static struct platform_driver pxa2xx_flash_driver = {
 		.owner		= THIS_MODULE,
 	},
 	.probe		= pxa2xx_flash_probe,
-	.remove		= __devexit_p(pxa2xx_flash_remove),
+	.remove		= pxa2xx_flash_remove,
 	.shutdown	= pxa2xx_flash_shutdown,
 };
 
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index a675bdb..f694417 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -149,8 +149,8 @@ static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *pla
 		plat->exit();
 }
 
-static struct sa_info *__devinit
-sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat)
+static struct sa_info *sa1100_setup_mtd(struct platform_device *pdev,
+					struct flash_platform_data *plat)
 {
 	struct sa_info *info;
 	int nr, size, i, ret = 0;
@@ -246,7 +246,7 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat)
 
 static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
 
-static int __devinit sa1100_mtd_probe(struct platform_device *pdev)
+static int sa1100_mtd_probe(struct platform_device *pdev)
 {
 	struct flash_platform_data *plat = pdev->dev.platform_data;
 	struct sa_info *info;
diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c
index 9dcbc68..71796137 100644
--- a/drivers/mtd/maps/scb2_flash.c
+++ b/drivers/mtd/maps/scb2_flash.c
@@ -69,7 +69,7 @@ static struct map_info scb2_map = {
 };
 static int region_fail;
 
-static int __devinit
+static int
 scb2_fixup_mtd(struct mtd_info *mtd)
 {
 	int i;
@@ -133,7 +133,7 @@ scb2_fixup_mtd(struct mtd_info *mtd)
 /* CSB5's 'Function Control Register' has bits for decoding @ >= 0xffc00000 */
 #define CSB5_FCR	0x41
 #define CSB5_FCR_DECODE_ALL 0x0e
-static int __devinit
+static int
 scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent)
 {
 	u8 reg;
@@ -197,7 +197,7 @@ scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent)
 	return 0;
 }
 
-static void __devexit
+static void
 scb2_flash_remove(struct pci_dev *dev)
 {
 	if (!scb2_mtd)
@@ -231,7 +231,7 @@ static struct pci_driver scb2_flash_driver = {
 	.name =     "Intel SCB2 BIOS Flash",
 	.id_table = scb2_flash_pci_ids,
 	.probe =    scb2_flash_probe,
-	.remove =   __devexit_p(scb2_flash_remove),
+	.remove =   scb2_flash_remove,
 };
 
 module_pci_driver(scb2_flash_driver);
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
index 175e537..d467f3b 100644
--- a/drivers/mtd/maps/sun_uflash.c
+++ b/drivers/mtd/maps/sun_uflash.c
@@ -108,7 +108,7 @@ int uflash_devinit(struct platform_device *op, struct device_node *dp)
 	return 0;
 }
 
-static int __devinit uflash_probe(struct platform_device *op)
+static int uflash_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 
@@ -121,7 +121,7 @@ static int __devinit uflash_probe(struct platform_device *op)
 	return uflash_devinit(op, dp);
 }
 
-static int __devexit uflash_remove(struct platform_device *op)
+static int uflash_remove(struct platform_device *op)
 {
 	struct uflash_dev *up = dev_get_drvdata(&op->dev);
 
@@ -155,7 +155,7 @@ static struct platform_driver uflash_driver = {
 		.of_match_table = uflash_match,
 	},
 	.probe		= uflash_probe,
-	.remove		= __devexit_p(uflash_remove),
+	.remove		= uflash_remove,
 };
 
 module_platform_driver(uflash_driver);
diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c
index 2e2b094..6b223cf 100644
--- a/drivers/mtd/maps/vmu-flash.c
+++ b/drivers/mtd/maps/vmu-flash.c
@@ -596,7 +596,7 @@ fail_name:
 }
 
 /* Handles very basic info about the flash, queries for details */
-static int __devinit vmu_connect(struct maple_device *mdev)
+static int vmu_connect(struct maple_device *mdev)
 {
 	unsigned long test_flash_data, basic_flash_data;
 	int c, error;
@@ -690,7 +690,7 @@ fail_nomem:
 	return error;
 }
 
-static void __devexit vmu_disconnect(struct maple_device *mdev)
+static void vmu_disconnect(struct maple_device *mdev)
 {
 	struct memcard *card;
 	struct mdev_part *mpart;
@@ -772,7 +772,7 @@ static void vmu_file_error(struct maple_device *mdev, void *recvbuf)
 }
 
 
-static int __devinit probe_maple_vmu(struct device *dev)
+static int probe_maple_vmu(struct device *dev)
 {
 	int error;
 	struct maple_device *mdev = to_maple_dev(dev);
@@ -789,7 +789,7 @@ static int __devinit probe_maple_vmu(struct device *dev)
 	return 0;
 }
 
-static int __devexit remove_maple_vmu(struct device *dev)
+static int remove_maple_vmu(struct device *dev)
 {
 	struct maple_device *mdev = to_maple_dev(dev);
 
@@ -802,7 +802,7 @@ static struct maple_driver vmu_flash_driver = {
 	.drv = {
 		.name =		"Dreamcast_visual_memory",
 		.probe =	probe_maple_vmu,
-		.remove = 	__devexit_p(remove_maple_vmu),
+		.remove =	remove_maple_vmu,
 	},
 };
 
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index f1f0671..5ad39bb 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -32,7 +32,6 @@
 #include <linux/hdreg.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
-#include <linux/kthread.h>
 #include <asm/uaccess.h>
 
 #include "mtdcore.h"
@@ -121,16 +120,14 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
 
 int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev)
 {
-	if (kthread_should_stop())
-		return 1;
-
 	return dev->bg_stop;
 }
 EXPORT_SYMBOL_GPL(mtd_blktrans_cease_background);
 
-static int mtd_blktrans_thread(void *arg)
+static void mtd_blktrans_work(struct work_struct *work)
 {
-	struct mtd_blktrans_dev *dev = arg;
+	struct mtd_blktrans_dev *dev =
+		container_of(work, struct mtd_blktrans_dev, work);
 	struct mtd_blktrans_ops *tr = dev->tr;
 	struct request_queue *rq = dev->rq;
 	struct request *req = NULL;
@@ -138,7 +135,7 @@ static int mtd_blktrans_thread(void *arg)
 
 	spin_lock_irq(rq->queue_lock);
 
-	while (!kthread_should_stop()) {
+	while (1) {
 		int res;
 
 		dev->bg_stop = false;
@@ -156,15 +153,7 @@ static int mtd_blktrans_thread(void *arg)
 				background_done = !dev->bg_stop;
 				continue;
 			}
-			set_current_state(TASK_INTERRUPTIBLE);
-
-			if (kthread_should_stop())
-				set_current_state(TASK_RUNNING);
-
-			spin_unlock_irq(rq->queue_lock);
-			schedule();
-			spin_lock_irq(rq->queue_lock);
-			continue;
+			break;
 		}
 
 		spin_unlock_irq(rq->queue_lock);
@@ -185,8 +174,6 @@ static int mtd_blktrans_thread(void *arg)
 		__blk_end_request_all(req, -EIO);
 
 	spin_unlock_irq(rq->queue_lock);
-
-	return 0;
 }
 
 static void mtd_blktrans_request(struct request_queue *rq)
@@ -199,10 +186,8 @@ static void mtd_blktrans_request(struct request_queue *rq)
 	if (!dev)
 		while ((req = blk_fetch_request(rq)) != NULL)
 			__blk_end_request_all(req, -ENODEV);
-	else {
-		dev->bg_stop = true;
-		wake_up_process(dev->thread);
-	}
+	else
+		queue_work(dev->wq, &dev->work);
 }
 
 static int blktrans_open(struct block_device *bdev, fmode_t mode)
@@ -325,7 +310,7 @@ unlock:
 	return ret;
 }
 
-static const struct block_device_operations mtd_blktrans_ops = {
+static const struct block_device_operations mtd_block_ops = {
 	.owner		= THIS_MODULE,
 	.open		= blktrans_open,
 	.release	= blktrans_release,
@@ -401,7 +386,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
 	gd->private_data = new;
 	gd->major = tr->major;
 	gd->first_minor = (new->devnum) << tr->part_bits;
-	gd->fops = &mtd_blktrans_ops;
+	gd->fops = &mtd_block_ops;
 
 	if (tr->part_bits)
 		if (new->devnum < 26)
@@ -437,14 +422,13 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
 
 	gd->queue = new->rq;
 
-	/* Create processing thread */
-	/* TODO: workqueue ? */
-	new->thread = kthread_run(mtd_blktrans_thread, new,
-			"%s%d", tr->name, new->mtd->index);
-	if (IS_ERR(new->thread)) {
-		ret = PTR_ERR(new->thread);
+	/* Create processing workqueue */
+	new->wq = alloc_workqueue("%s%d", 0, 0,
+				  tr->name, new->mtd->index);
+	if (!new->wq)
 		goto error4;
-	}
+	INIT_WORK(&new->work, mtd_blktrans_work);
+
 	gd->driverfs_dev = &new->mtd->dev;
 
 	if (new->readonly)
@@ -484,9 +468,8 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
 	/* Stop new requests to arrive */
 	del_gendisk(old->disk);
 
-
-	/* Stop the thread */
-	kthread_stop(old->thread);
+	/* Stop workqueue. This will perform any pending request. */
+	destroy_workqueue(old->wq);
 
 	/* Kill current requests */
 	spin_lock_irqsave(&old->queue_lock, flags);
diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c
index f5b3f91..97bb8f6 100644
--- a/drivers/mtd/mtdoops.c
+++ b/drivers/mtd/mtdoops.c
@@ -271,7 +271,7 @@ static void find_next_position(struct mtdoops_context *cxt)
 
 		if (count[0] == 0xffffffff && count[1] == 0xffffffff)
 			mark_page_unused(cxt, page);
-		if (count[0] == 0xffffffff)
+		if (count[0] == 0xffffffff || count[1] != MTDOOPS_KERNMSG_MAGIC)
 			continue;
 		if (maxcount == 0xffffffff) {
 			maxcount = count[0];
@@ -289,14 +289,13 @@ static void find_next_position(struct mtdoops_context *cxt)
 		}
 	}
 	if (maxcount == 0xffffffff) {
-		cxt->nextpage = 0;
-		cxt->nextcount = 1;
-		schedule_work(&cxt->work_erase);
-		return;
+		cxt->nextpage = cxt->oops_pages - 1;
+		cxt->nextcount = 0;
+	}
+	else {
+		cxt->nextpage = maxpos;
+		cxt->nextcount = maxcount;
 	}
-
-	cxt->nextpage = maxpos;
-	cxt->nextcount = maxcount;
 
 	mtdoops_inc_counter(cxt);
 }
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 4883139..5e83023 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -49,24 +49,31 @@ config MTD_NAND_MUSEUM_IDS
 	  NAND chips (page size 256 byte, erase size 4-8KiB). The IDs
 	  of these chips were reused by later, larger chips.
 
-config MTD_NAND_AUTCPU12
-	tristate "SmartMediaCard on autronix autcpu12 board"
-	depends on ARCH_AUTCPU12
-	help
-	  This enables the driver for the autronix autcpu12 board to
-	  access the SmartMediaCard.
-
 config MTD_NAND_DENALI
-       depends on PCI
+        tristate "Support Denali NAND controller"
+        help
+	  Enable support for the Denali NAND controller.  This should be
+	  combined with either the PCI or platform drivers to provide device
+	  registration.
+
+config MTD_NAND_DENALI_PCI
         tristate "Support Denali NAND controller on Intel Moorestown"
+	depends on PCI && MTD_NAND_DENALI
         help
           Enable the driver for NAND flash on Intel Moorestown, using the
           Denali NAND controller core.
- 
+
+config MTD_NAND_DENALI_DT
+	tristate "Support Denali NAND controller as a DT device"
+	depends on HAVE_CLK && MTD_NAND_DENALI
+	help
+	  Enable the driver for NAND flash on platforms using a Denali NAND
+	  controller as a DT device.
+
 config MTD_NAND_DENALI_SCRATCH_REG_ADDR
         hex "Denali NAND size scratch register address"
         default "0xFF108018"
-        depends on MTD_NAND_DENALI
+        depends on MTD_NAND_DENALI_PCI
         help
           Some platforms place the NAND chip size in a scratch register
           because (some versions of) the driver aren't able to automatically
@@ -86,12 +93,6 @@ config MTD_NAND_GPIO
 	help
 	  This enables a GPIO based NAND flash driver.
 
-config MTD_NAND_SPIA
-	tristate "NAND Flash device on SPIA board"
-	depends on ARCH_P720T
-	help
-	  If you had to ask, you don't have one. Say 'N'.
-
 config MTD_NAND_AMS_DELTA
 	tristate "NAND Flash device on Amstrad E3"
 	depends on MACH_AMS_DELTA
@@ -259,8 +260,7 @@ config MTD_NAND_S3C2410_CLKSTOP
 	  approximately 5mA of power when there is nothing happening.
 
 config MTD_NAND_DISKONCHIP
-	tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation)"
 	depends on HAS_IOMEM
 	select REED_SOLOMON
 	select REED_SOLOMON_DEC16
@@ -330,8 +330,8 @@ config MTD_NAND_DISKONCHIP_BBTWRITE
 	  parameter "inftl_bbt_write=1".
 
 config MTD_NAND_DOCG4
-	tristate "Support for DiskOnChip G4 (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && HAS_IOMEM
+	tristate "Support for DiskOnChip G4"
+	depends on HAS_IOMEM
 	select BCH
 	select BITREVERSE
 	help
@@ -446,6 +446,15 @@ config MTD_NAND_GPMI_NAND
 	 block, such as SD card. So pay attention to it when you enable
 	 the GPMI.
 
+config MTD_NAND_BCM47XXNFLASH
+	tristate "R/O support for NAND flash on BCMA bus"
+	depends on BCMA_NFLASH
+	help
+	  BCMA bus can have various flash memories attached, they are
+	  registered by bcma as platform devices. This enables driver for
+	  NAND flash memories. For now only read mode for BCM4706 is
+	  implemented.
+
 config MTD_NAND_PLATFORM
 	tristate "Support for generic platform NAND driver"
 	depends on HAS_IOMEM
@@ -512,12 +521,6 @@ config MTD_NAND_MXC
 	  This enables the driver for the NAND flash controller on the
 	  MXC processors.
 
-config MTD_NAND_NOMADIK
-	tristate "ST Nomadik 8815 NAND support"
-	depends on ARCH_NOMADIK
-	help
-	  Driver for the NAND flash controller on the Nomadik, with ECC.
-
 config MTD_NAND_SH_FLCTL
 	tristate "Support for NAND on Renesas SuperH FLCTL"
 	depends on SUPERH || ARCH_SHMOBILE
@@ -559,7 +562,7 @@ config MTD_NAND_JZ4740
 
 config MTD_NAND_FSMC
 	tristate "Support for NAND on ST Micros FSMC"
-	depends on PLAT_SPEAR || PLAT_NOMADIK || MACH_U300
+	depends on PLAT_SPEAR || ARCH_NOMADIK || ARCH_U8500 || MACH_U300
 	help
 	  Enables support for NAND Flash chips on the ST Microelectronics
 	  Flexible Static Memory Controller (FSMC)
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 2cbd091..d76d912 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -9,10 +9,10 @@ obj-$(CONFIG_MTD_NAND_IDS)		+= nand_ids.o
 obj-$(CONFIG_MTD_SM_COMMON) 		+= sm_common.o
 
 obj-$(CONFIG_MTD_NAND_CAFE)		+= cafe_nand.o
-obj-$(CONFIG_MTD_NAND_SPIA)		+= spia.o
 obj-$(CONFIG_MTD_NAND_AMS_DELTA)	+= ams-delta.o
-obj-$(CONFIG_MTD_NAND_AUTCPU12)		+= autcpu12.o
 obj-$(CONFIG_MTD_NAND_DENALI)		+= denali.o
+obj-$(CONFIG_MTD_NAND_DENALI_PCI)	+= denali_pci.o
+obj-$(CONFIG_MTD_NAND_DENALI_DT)	+= denali_dt.o
 obj-$(CONFIG_MTD_NAND_AU1550)		+= au1550nd.o
 obj-$(CONFIG_MTD_NAND_BF5XX)		+= bf5xx_nand.o
 obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB)	+= ppchameleonevb.o
@@ -47,11 +47,11 @@ obj-$(CONFIG_MTD_NAND_MXC)		+= mxc_nand.o
 obj-$(CONFIG_MTD_NAND_SOCRATES)		+= socrates_nand.o
 obj-$(CONFIG_MTD_NAND_TXX9NDFMC)	+= txx9ndfmc.o
 obj-$(CONFIG_MTD_NAND_NUC900)		+= nuc900_nand.o
-obj-$(CONFIG_MTD_NAND_NOMADIK)		+= nomadik_nand.o
 obj-$(CONFIG_MTD_NAND_MPC5121_NFC)	+= mpc5121_nfc.o
 obj-$(CONFIG_MTD_NAND_RICOH)		+= r852.o
 obj-$(CONFIG_MTD_NAND_JZ4740)		+= jz4740_nand.o
 obj-$(CONFIG_MTD_NAND_GPMI_NAND)	+= gpmi-nand/
 obj-$(CONFIG_MTD_NAND_XWAY)		+= xway_nand.o
+obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH)	+= bcm47xxnflash/
 
 nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index 9e7723a..f1d71cd 100644
--- a/drivers/mtd/nand/ams-delta.c
+++ b/drivers/mtd/nand/ams-delta.c
@@ -173,7 +173,7 @@ static const struct gpio _mandatory_gpio[] = {
 /*
  * Main initialization routine
  */
-static int __devinit ams_delta_init(struct platform_device *pdev)
+static int ams_delta_init(struct platform_device *pdev)
 {
 	struct nand_chip *this;
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -270,7 +270,7 @@ out_free:
 /*
  * Clean up routine
  */
-static int __devexit ams_delta_cleanup(struct platform_device *pdev)
+static int ams_delta_cleanup(struct platform_device *pdev)
 {
 	void __iomem *io_base = platform_get_drvdata(pdev);
 
@@ -289,7 +289,7 @@ static int __devexit ams_delta_cleanup(struct platform_device *pdev)
 
 static struct platform_driver ams_delta_nand_driver = {
 	.probe		= ams_delta_init,
-	.remove		= __devexit_p(ams_delta_cleanup),
+	.remove		= ams_delta_cleanup,
 	.driver		= {
 		.name	= "ams-delta-nand",
 		.owner	= THIS_MODULE,
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 9144557..aa3cb85 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -41,6 +41,7 @@
 #include <linux/gpio.h>
 #include <linux/io.h>
 #include <linux/platform_data/atmel.h>
+#include <linux/pinctrl/consumer.h>
 
 #include <mach/cpu.h>
 
@@ -330,13 +331,13 @@ static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
  *               12-bits                20-bytes                 21-bytes
  *               24-bits                39-bytes                 42-bytes
  */
-static int __devinit pmecc_get_ecc_bytes(int cap, int sector_size)
+static int pmecc_get_ecc_bytes(int cap, int sector_size)
 {
 	int m = 12 + sector_size / 512;
 	return (m * cap + 7) / 8;
 }
 
-static void __devinit pmecc_config_ecc_layout(struct nand_ecclayout *layout,
+static void pmecc_config_ecc_layout(struct nand_ecclayout *layout,
 	int oobsize, int ecc_len)
 {
 	int i;
@@ -352,7 +353,7 @@ static void __devinit pmecc_config_ecc_layout(struct nand_ecclayout *layout,
 		oobsize - ecc_len - layout->oobfree[0].offset;
 }
 
-static void __devinit __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host)
+static void __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host)
 {
 	int table_size;
 
@@ -374,7 +375,7 @@ static void pmecc_data_free(struct atmel_nand_host *host)
 	kfree(host->pmecc_delta);
 }
 
-static int __devinit pmecc_data_alloc(struct atmel_nand_host *host)
+static int pmecc_data_alloc(struct atmel_nand_host *host)
 {
 	const int cap = host->pmecc_corr_cap;
 
@@ -1205,7 +1206,7 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
 }
 
 #if defined(CONFIG_OF)
-static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
+static int atmel_of_init_port(struct atmel_nand_host *host,
 					 struct device_node *np)
 {
 	u32 val, table_offset;
@@ -1292,7 +1293,7 @@ static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
 	return 0;
 }
 #else
-static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
+static int atmel_of_init_port(struct atmel_nand_host *host,
 					 struct device_node *np)
 {
 	return -EINVAL;
@@ -1370,6 +1371,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 	struct resource *mem;
 	struct mtd_part_parser_data ppdata = {};
 	int res;
+	struct pinctrl *pinctrl;
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem) {
@@ -1414,6 +1416,13 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 	nand_chip->IO_ADDR_W = host->io_base;
 	nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
 
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl)) {
+		dev_err(host->dev, "Failed to request pinctrl\n");
+		res = PTR_ERR(pinctrl);
+		goto err_ecc_ioremap;
+	}
+
 	if (gpio_is_valid(host->board.rdy_pin)) {
 		res = gpio_request(host->board.rdy_pin, "nand_rdy");
 		if (res < 0) {
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index 5c47b20..217459d 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -382,7 +382,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
 	while(!this->dev_ready(mtd));
 }
 
-static int __devinit find_nand_cs(unsigned long nand_base)
+static int find_nand_cs(unsigned long nand_base)
 {
 	void __iomem *base =
 			(void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR);
@@ -403,7 +403,7 @@ static int __devinit find_nand_cs(unsigned long nand_base)
 	return -ENODEV;
 }
 
-static int __devinit au1550nd_probe(struct platform_device *pdev)
+static int au1550nd_probe(struct platform_device *pdev)
 {
 	struct au1550nd_platdata *pd;
 	struct au1550nd_ctx *ctx;
@@ -491,7 +491,7 @@ out1:
 	return ret;
 }
 
-static int __devexit au1550nd_remove(struct platform_device *pdev)
+static int au1550nd_remove(struct platform_device *pdev)
 {
 	struct au1550nd_ctx *ctx = platform_get_drvdata(pdev);
 	struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -509,7 +509,7 @@ static struct platform_driver au1550nd_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= au1550nd_probe,
-	.remove		= __devexit_p(au1550nd_remove),
+	.remove		= au1550nd_remove,
 };
 
 module_platform_driver(au1550nd_driver);
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c
deleted file mode 100644
index 04769a4..0000000
--- a/drivers/mtd/nand/autcpu12.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- *  drivers/mtd/autcpu12.c
- *
- *  Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
- *
- *  Derived from drivers/mtd/spia.c
- *	 Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.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.
- *
- *  Overview:
- *   This is a device driver for the NAND flash device found on the
- *   autronix autcpu12 board, which is a SmartMediaCard. It supports
- *   16MiB, 32MiB and 64MiB cards.
- *
- *
- *	02-12-2002 TG	Cleanup of module params
- *
- *	02-20-2002 TG	adjusted for different rd/wr address support
- *			added support for read device ready/busy line
- *			added page_cache
- *
- *	10-06-2002 TG	128K card support added
- */
-
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include <asm/sizes.h>
-#include <mach/autcpu12.h>
-
-/*
- * MTD structure for AUTCPU12 board
- */
-static struct mtd_info *autcpu12_mtd = NULL;
-static void __iomem *autcpu12_fio_base;
-
-/*
- * Define partitions for flash devices
- */
-static struct mtd_partition partition_info16k[] = {
-	{ .name		= "AUTCPU12 flash partition 1",
-	  .offset	= 0,
-	  .size		= 8 * SZ_1M },
-	{ .name		= "AUTCPU12 flash partition 2",
-	  .offset	= 8 * SZ_1M,
-	  .size		= 8 * SZ_1M },
-};
-
-static struct mtd_partition partition_info32k[] = {
-	{ .name		= "AUTCPU12 flash partition 1",
-	  .offset	= 0,
-	  .size		= 8 * SZ_1M },
-	{ .name		= "AUTCPU12 flash partition 2",
-	  .offset	= 8 * SZ_1M,
-	  .size		= 24 * SZ_1M },
-};
-
-static struct mtd_partition partition_info64k[] = {
-	{ .name		= "AUTCPU12 flash partition 1",
-	  .offset	= 0,
-	  .size		= 16 * SZ_1M },
-	{ .name		= "AUTCPU12 flash partition 2",
-	  .offset	= 16 * SZ_1M,
-	  .size		= 48 * SZ_1M },
-};
-
-static struct mtd_partition partition_info128k[] = {
-	{ .name		= "AUTCPU12 flash partition 1",
-	  .offset	= 0,
-	  .size		= 16 * SZ_1M },
-	{ .name		= "AUTCPU12 flash partition 2",
-	  .offset	= 16 * SZ_1M,
-	  .size		= 112 * SZ_1M },
-};
-
-#define NUM_PARTITIONS16K 2
-#define NUM_PARTITIONS32K 2
-#define NUM_PARTITIONS64K 2
-#define NUM_PARTITIONS128K 2
-/*
- *	hardware specific access to control-lines
- *
- *	ALE bit 4 autcpu12_pedr
- *	CLE bit 5 autcpu12_pedr
- *	NCE bit 0 fio_ctrl
- *
- */
-static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd,
-			       unsigned int ctrl)
-{
-	struct nand_chip *chip = mtd->priv;
-
-	if (ctrl & NAND_CTRL_CHANGE) {
-		void __iomem *addr;
-		unsigned char bits;
-
-		bits = clps_readb(AUTCPU12_SMC_PORT_OFFSET) & ~0x30;
-		bits |= (ctrl & NAND_CLE) << 4;
-		bits |= (ctrl & NAND_ALE) << 2;
-		clps_writeb(bits, AUTCPU12_SMC_PORT_OFFSET);
-
-		addr = autcpu12_fio_base + AUTCPU12_SMC_SELECT_OFFSET;
-		writeb((readb(addr) & ~0x1) | (ctrl & NAND_NCE), addr);
-	}
-
-	if (cmd != NAND_CMD_NONE)
-		writeb(cmd, chip->IO_ADDR_W);
-}
-
-/*
- *	read device ready pin
- */
-int autcpu12_device_ready(struct mtd_info *mtd)
-{
-	return clps_readb(AUTCPU12_SMC_PORT_OFFSET) & AUTCPU12_SMC_RDY;
-}
-
-/*
- * Main initialization routine
- */
-static int __init autcpu12_init(void)
-{
-	struct nand_chip *this;
-	int err = 0;
-
-	/* Allocate memory for MTD device structure and private data */
-	autcpu12_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip),
-			       GFP_KERNEL);
-	if (!autcpu12_mtd) {
-		printk("Unable to allocate AUTCPU12 NAND MTD device structure.\n");
-		err = -ENOMEM;
-		goto out;
-	}
-
-	/* map physical address */
-	autcpu12_fio_base = ioremap(AUTCPU12_PHYS_SMC, SZ_1K);
-	if (!autcpu12_fio_base) {
-		printk("Ioremap autcpu12 SmartMedia Card failed\n");
-		err = -EIO;
-		goto out_mtd;
-	}
-
-	/* Get pointer to private data */
-	this = (struct nand_chip *)(&autcpu12_mtd[1]);
-
-	/* Initialize structures */
-	memset(autcpu12_mtd, 0, sizeof(struct mtd_info));
-	memset(this, 0, sizeof(struct nand_chip));
-
-	/* Link the private data with the MTD structure */
-	autcpu12_mtd->priv = this;
-	autcpu12_mtd->owner = THIS_MODULE;
-
-	/* Set address of NAND IO lines */
-	this->IO_ADDR_R = autcpu12_fio_base;
-	this->IO_ADDR_W = autcpu12_fio_base;
-	this->cmd_ctrl = autcpu12_hwcontrol;
-	this->dev_ready = autcpu12_device_ready;
-	/* 20 us command delay time */
-	this->chip_delay = 20;
-	this->ecc.mode = NAND_ECC_SOFT;
-
-	/* Enable the following for a flash based bad block table */
-	/*
-	   this->bbt_options = NAND_BBT_USE_FLASH;
-	 */
-	this->bbt_options = NAND_BBT_USE_FLASH;
-
-	/* Scan to find existence of the device */
-	if (nand_scan(autcpu12_mtd, 1)) {
-		err = -ENXIO;
-		goto out_ior;
-	}
-
-	/* Register the partitions */
-	switch (autcpu12_mtd->size) {
-		case SZ_16M:
-			mtd_device_register(autcpu12_mtd, partition_info16k,
-					    NUM_PARTITIONS16K);
-			break;
-		case SZ_32M:
-			mtd_device_register(autcpu12_mtd, partition_info32k,
-					    NUM_PARTITIONS32K);
-			break;
-		case SZ_64M:
-			mtd_device_register(autcpu12_mtd, partition_info64k,
-					    NUM_PARTITIONS64K);
-			break;
-		case SZ_128M:
-			mtd_device_register(autcpu12_mtd, partition_info128k,
-					    NUM_PARTITIONS128K);
-			break;
-		default:
-			printk("Unsupported SmartMedia device\n");
-			err = -ENXIO;
-			goto out_ior;
-	}
-	goto out;
-
- out_ior:
-	iounmap(autcpu12_fio_base);
- out_mtd:
-	kfree(autcpu12_mtd);
- out:
-	return err;
-}
-
-module_init(autcpu12_init);
-
-/*
- * Clean up routine
- */
-static void __exit autcpu12_cleanup(void)
-{
-	/* Release resources, unregister device */
-	nand_release(autcpu12_mtd);
-
-	/* unmap physical address */
-	iounmap(autcpu12_fio_base);
-
-	/* Free the MTD device structure */
-	kfree(autcpu12_mtd);
-}
-
-module_exit(autcpu12_cleanup);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
-MODULE_DESCRIPTION("Glue layer for SmartMediaCard on autronix autcpu12");
diff --git a/drivers/mtd/nand/bcm47xxnflash/Makefile b/drivers/mtd/nand/bcm47xxnflash/Makefile
new file mode 100644
index 0000000..f05b119
--- /dev/null
+++ b/drivers/mtd/nand/bcm47xxnflash/Makefile
@@ -0,0 +1,4 @@
+bcm47xxnflash-y				+= main.o
+bcm47xxnflash-y				+= ops_bcm4706.o
+
+obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH)	+= bcm47xxnflash.o
diff --git a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
new file mode 100644
index 0000000..0bdb2ce
--- /dev/null
+++ b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
@@ -0,0 +1,22 @@
+#ifndef __BCM47XXNFLASH_H
+#define __BCM47XXNFLASH_H
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+
+struct bcm47xxnflash {
+	struct bcma_drv_cc *cc;
+
+	struct nand_chip nand_chip;
+	struct mtd_info mtd;
+
+	unsigned curr_command;
+	int curr_page_addr;
+	int curr_column;
+
+	u8 id_data[8];
+};
+
+int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n);
+
+#endif /* BCM47XXNFLASH */
diff --git a/drivers/mtd/nand/bcm47xxnflash/main.c b/drivers/mtd/nand/bcm47xxnflash/main.c
new file mode 100644
index 0000000..2b8b05b
--- /dev/null
+++ b/drivers/mtd/nand/bcm47xxnflash/main.c
@@ -0,0 +1,108 @@
+/*
+ * BCM47XX NAND flash driver
+ *
+ * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/bcma/bcma.h>
+
+#include "bcm47xxnflash.h"
+
+MODULE_DESCRIPTION("NAND flash driver for BCMA bus");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Rafał Miłecki");
+
+static const char *probes[] = { "bcm47xxpart", NULL };
+
+static int bcm47xxnflash_probe(struct platform_device *pdev)
+{
+	struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev);
+	struct bcm47xxnflash *b47n;
+	int err = 0;
+
+	b47n = kzalloc(sizeof(*b47n), GFP_KERNEL);
+	if (!b47n) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	b47n->nand_chip.priv = b47n;
+	b47n->mtd.owner = THIS_MODULE;
+	b47n->mtd.priv = &b47n->nand_chip; /* Required */
+	b47n->cc = container_of(nflash, struct bcma_drv_cc, nflash);
+
+	if (b47n->cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
+		err = bcm47xxnflash_ops_bcm4706_init(b47n);
+	} else {
+		pr_err("Device not supported\n");
+		err = -ENOTSUPP;
+	}
+	if (err) {
+		pr_err("Initialization failed: %d\n", err);
+		goto err_init;
+	}
+
+	err = mtd_device_parse_register(&b47n->mtd, probes, NULL, NULL, 0);
+	if (err) {
+		pr_err("Failed to register MTD device: %d\n", err);
+		goto err_dev_reg;
+	}
+
+	return 0;
+
+err_dev_reg:
+err_init:
+	kfree(b47n);
+out:
+	return err;
+}
+
+static int __devexit bcm47xxnflash_remove(struct platform_device *pdev)
+{
+	struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev);
+
+	if (nflash->mtd)
+		mtd_device_unregister(nflash->mtd);
+
+	return 0;
+}
+
+static struct platform_driver bcm47xxnflash_driver = {
+	.remove = __devexit_p(bcm47xxnflash_remove),
+	.driver = {
+		.name = "bcma_nflash",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init bcm47xxnflash_init(void)
+{
+	int err;
+
+	/*
+	 * Platform device "bcma_nflash" exists on SoCs and is registered very
+	 * early, it won't be added during runtime (use platform_driver_probe).
+	 */
+	err = platform_driver_probe(&bcm47xxnflash_driver, bcm47xxnflash_probe);
+	if (err)
+		pr_err("Failed to register serial flash driver: %d\n", err);
+
+	return err;
+}
+
+static void __exit bcm47xxnflash_exit(void)
+{
+	platform_driver_unregister(&bcm47xxnflash_driver);
+}
+
+module_init(bcm47xxnflash_init);
+module_exit(bcm47xxnflash_exit);
diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
new file mode 100644
index 0000000..e42e182
--- /dev/null
+++ b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
@@ -0,0 +1,316 @@
+/*
+ * BCM47XX NAND flash driver
+ *
+ * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/bcma/bcma.h>
+
+#include "bcm47xxnflash.h"
+
+/* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has
+ * shown 164 retries as maxiumum. */
+#define NFLASH_READY_RETRIES		1000
+
+#define NFLASH_SECTOR_SIZE		512
+
+/**************************************************
+ * Various helpers
+ **************************************************/
+
+static inline u8 bcm47xxnflash_ops_bcm4706_ns_to_cycle(u16 ns, u16 clock)
+{
+	return ((ns * 1000 * clock) / 1000000) + 1;
+}
+
+static int bcm47xxnflash_ops_bcm4706_ctl_cmd(struct bcma_drv_cc *cc, u32 code)
+{
+	int i = 0;
+
+	bcma_cc_write32(cc, BCMA_CC_NFLASH_CTL, 0x80000000 | code);
+	for (i = 0; i < NFLASH_READY_RETRIES; i++) {
+		if (!(bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & 0x80000000)) {
+			i = 0;
+			break;
+		}
+	}
+	if (i) {
+		pr_err("NFLASH control command not ready!\n");
+		return -EBUSY;
+	}
+	return 0;
+}
+
+static int bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc *cc)
+{
+	int i;
+
+	for (i = 0; i < NFLASH_READY_RETRIES; i++) {
+		if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & 0x04000000) {
+			if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) &
+			    BCMA_CC_NFLASH_CTL_ERR) {
+				pr_err("Error on polling\n");
+				return -EBUSY;
+			} else {
+				return 0;
+			}
+		}
+	}
+
+	pr_err("Polling timeout!\n");
+	return -EBUSY;
+}
+
+/**************************************************
+ * R/W
+ **************************************************/
+
+static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
+					   int len)
+{
+	struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
+	struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
+
+	u32 ctlcode;
+	u32 *dest = (u32 *)buf;
+	int i;
+	int toread;
+
+	BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask);
+	/* Don't validate column using nand_chip->page_shift, it may be bigger
+	 * when accessing OOB */
+
+	while (len) {
+		/* We can read maximum of 0x200 bytes at once */
+		toread = min(len, 0x200);
+
+		/* Set page and column */
+		bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_COL_ADDR,
+				b47n->curr_column);
+		bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_ROW_ADDR,
+				b47n->curr_page_addr);
+
+		/* Prepare to read */
+		ctlcode = 0x40000000 | 0x00080000 | 0x00040000 | 0x00020000 |
+			  0x00010000;
+		ctlcode |= NAND_CMD_READSTART << 8;
+		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode))
+			return;
+		if (bcm47xxnflash_ops_bcm4706_poll(b47n->cc))
+			return;
+
+		/* Eventually read some data :) */
+		for (i = 0; i < toread; i += 4, dest++) {
+			ctlcode = 0x40000000 | 0x30000000 | 0x00100000;
+			if (i == toread - 4) /* Last read goes without that */
+				ctlcode &= ~0x40000000;
+			if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
+							      ctlcode))
+				return;
+			*dest = bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA);
+		}
+
+		b47n->curr_column += toread;
+		len -= toread;
+	}
+}
+
+/**************************************************
+ * NAND chip ops
+ **************************************************/
+
+/* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */
+static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd,
+						  int chip)
+{
+	return;
+}
+
+/*
+ * Default nand_command and nand_command_lp don't match BCM4706 hardware layout.
+ * For example, reading chip id is performed in a non-standard way.
+ * Setting column and page is also handled differently, we use a special
+ * registers of ChipCommon core. Hacking cmd_ctrl to understand and convert
+ * standard commands would be much more complicated.
+ */
+static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
+					      unsigned command, int column,
+					      int page_addr)
+{
+	struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
+	struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
+	u32 ctlcode;
+	int i;
+
+	if (column != -1)
+		b47n->curr_column = column;
+	if (page_addr != -1)
+		b47n->curr_page_addr = page_addr;
+
+	switch (command) {
+	case NAND_CMD_RESET:
+		pr_warn("Chip reset not implemented yet\n");
+		break;
+	case NAND_CMD_READID:
+		ctlcode = 0x40000000 | 0x01000000 | 0x00080000 | 0x00010000;
+		ctlcode |= NAND_CMD_READID;
+		if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode)) {
+			pr_err("READID error\n");
+			break;
+		}
+
+		/*
+		 * Reading is specific, last one has to go without 0x40000000
+		 * bit. We don't know how many reads NAND subsystem is going
+		 * to perform, so cache everything.
+		 */
+		for (i = 0; i < ARRAY_SIZE(b47n->id_data); i++) {
+			ctlcode = 0x40000000 | 0x00100000;
+			if (i == ARRAY_SIZE(b47n->id_data) - 1)
+				ctlcode &= ~0x40000000;
+			if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
+							      ctlcode)) {
+				pr_err("READID error\n");
+				break;
+			}
+			b47n->id_data[i] =
+				bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA)
+				& 0xFF;
+		}
+
+		break;
+	case NAND_CMD_READ0:
+		break;
+	case NAND_CMD_READOOB:
+		if (page_addr != -1)
+			b47n->curr_column += mtd->writesize;
+		break;
+	default:
+		pr_err("Command 0x%X unsupported\n", command);
+		break;
+	}
+	b47n->curr_command = command;
+}
+
+static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
+{
+	struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
+	struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
+	u32 tmp = 0;
+
+	switch (b47n->curr_command) {
+	case NAND_CMD_READID:
+		if (b47n->curr_column >= ARRAY_SIZE(b47n->id_data)) {
+			pr_err("Requested invalid id_data: %d\n",
+			       b47n->curr_column);
+			return 0;
+		}
+		return b47n->id_data[b47n->curr_column++];
+	case NAND_CMD_READOOB:
+		bcm47xxnflash_ops_bcm4706_read(mtd, (u8 *)&tmp, 4);
+		return tmp & 0xFF;
+	}
+
+	pr_err("Invalid command for byte read: 0x%X\n", b47n->curr_command);
+	return 0;
+}
+
+static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd,
+					       uint8_t *buf, int len)
+{
+	struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
+	struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
+
+	switch (b47n->curr_command) {
+	case NAND_CMD_READ0:
+	case NAND_CMD_READOOB:
+		bcm47xxnflash_ops_bcm4706_read(mtd, buf, len);
+		return;
+	}
+
+	pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command);
+}
+
+/**************************************************
+ * Init
+ **************************************************/
+
+int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
+{
+	int err;
+	u32 freq;
+	u16 clock;
+	u8 w0, w1, w2, w3, w4;
+
+	unsigned long chipsize; /* MiB */
+	u8 tbits, col_bits, col_size, row_bits, row_bsize;
+	u32 val;
+
+	b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;
+	b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
+	b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
+	b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf;
+	b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH;
+	b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */
+
+	/* Enable NAND flash access */
+	bcma_cc_set32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
+		      BCMA_CC_4706_FLASHSCFG_NF1);
+
+	/* Configure wait counters */
+	if (b47n->cc->status & BCMA_CC_CHIPST_4706_PKG_OPTION) {
+		freq = 100000000;
+	} else {
+		freq = bcma_chipco_pll_read(b47n->cc, 4);
+		freq = (freq * 0xFFF) >> 3;
+		freq = (freq * 25000000) >> 3;
+	}
+	clock = freq / 1000000;
+	w0 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(15, clock);
+	w1 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(20, clock);
+	w2 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
+	w3 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
+	w4 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(100, clock);
+	bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_WAITCNT0,
+			(w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0));
+
+	/* Scan NAND */
+	err = nand_scan(&b47n->mtd, 1);
+	if (err) {
+		pr_err("Could not scan NAND flash: %d\n", err);
+		goto exit;
+	}
+
+	/* Configure FLASH */
+	chipsize = b47n->nand_chip.chipsize >> 20;
+	tbits = ffs(chipsize); /* find first bit set */
+	if (!tbits || tbits != fls(chipsize)) {
+		pr_err("Invalid flash size: 0x%lX\n", chipsize);
+		err = -ENOTSUPP;
+		goto exit;
+	}
+	tbits += 19; /* Broadcom increases *index* by 20, we increase *pos* */
+
+	col_bits = b47n->nand_chip.page_shift + 1;
+	col_size = (col_bits + 7) / 8;
+
+	row_bits = tbits - col_bits + 1;
+	row_bsize = (row_bits + 7) / 8;
+
+	val = ((row_bsize - 1) << 6) | ((col_size - 1) << 4) | 2;
+	bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_CONF, val);
+
+exit:
+	if (err)
+		bcma_cc_mask32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
+			       ~BCMA_CC_4706_FLASHSCFG_NF1);
+	return err;
+}
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
index ab0caa7..4271e94 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/bf5xx_nand.c
@@ -658,7 +658,7 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info)
 /*
  * Device management interface
  */
-static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info)
+static int bf5xx_nand_add_partition(struct bf5xx_nand_info *info)
 {
 	struct mtd_info *mtd = &info->mtd;
 	struct mtd_partition *parts = info->platform->partitions;
@@ -667,7 +667,7 @@ static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info)
 	return mtd_device_register(mtd, parts, nr);
 }
 
-static int __devexit bf5xx_nand_remove(struct platform_device *pdev)
+static int bf5xx_nand_remove(struct platform_device *pdev)
 {
 	struct bf5xx_nand_info *info = to_nand_info(pdev);
 
@@ -725,7 +725,7 @@ static int bf5xx_nand_scan(struct mtd_info *mtd)
  * it can allocate all necessary resources then calls the
  * nand layer to look for devices
  */
-static int __devinit bf5xx_nand_probe(struct platform_device *pdev)
+static int bf5xx_nand_probe(struct platform_device *pdev)
 {
 	struct bf5xx_nand_platform *plat = to_nand_plat(pdev);
 	struct bf5xx_nand_info *info = NULL;
@@ -865,7 +865,7 @@ static int bf5xx_nand_resume(struct platform_device *dev)
 /* driver device registration */
 static struct platform_driver bf5xx_nand_driver = {
 	.probe		= bf5xx_nand_probe,
-	.remove		= __devexit_p(bf5xx_nand_remove),
+	.remove		= bf5xx_nand_remove,
 	.suspend	= bf5xx_nand_suspend,
 	.resume		= bf5xx_nand_resume,
 	.driver		= {
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index 2bb7170..010d612 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -585,7 +585,7 @@ static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
 }
 
 /* F_2[X]/(X**6+X+1)  */
-static unsigned short __devinit gf64_mul(u8 a, u8 b)
+static unsigned short gf64_mul(u8 a, u8 b)
 {
 	u8 c;
 	unsigned int i;
@@ -604,7 +604,7 @@ static unsigned short __devinit gf64_mul(u8 a, u8 b)
 }
 
 /* F_64[X]/(X**2+X+A**-1) with A the generator of F_64[X]  */
-static u16 __devinit gf4096_mul(u16 a, u16 b)
+static u16 gf4096_mul(u16 a, u16 b)
 {
 	u8 ah, al, bh, bl, ch, cl;
 
@@ -619,14 +619,14 @@ static u16 __devinit gf4096_mul(u16 a, u16 b)
 	return (ch << 6) ^ cl;
 }
 
-static int __devinit cafe_mul(int x)
+static int cafe_mul(int x)
 {
 	if (x == 0)
 		return 1;
 	return gf4096_mul(x, 0xe01);
 }
 
-static int __devinit cafe_nand_probe(struct pci_dev *pdev,
+static int cafe_nand_probe(struct pci_dev *pdev,
 				     const struct pci_device_id *ent)
 {
 	struct mtd_info *mtd;
@@ -821,7 +821,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
 	return err;
 }
 
-static void __devexit cafe_nand_remove(struct pci_dev *pdev)
+static void cafe_nand_remove(struct pci_dev *pdev)
 {
 	struct mtd_info *mtd = pci_get_drvdata(pdev);
 	struct cafe_priv *cafe = mtd->priv;
@@ -887,7 +887,7 @@ static struct pci_driver cafe_nand_pci_driver = {
 	.name = "CAFÉ NAND",
 	.id_table = cafe_nand_tbl,
 	.probe = cafe_nand_probe,
-	.remove = __devexit_p(cafe_nand_remove),
+	.remove = cafe_nand_remove,
 	.resume = cafe_nand_resume,
 };
 
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index adb6c3e..2cdeab8 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -237,6 +237,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
 	this->ecc.hwctl  = cs_enable_hwecc;
 	this->ecc.calculate = cs_calculate_ecc;
 	this->ecc.correct  = nand_correct_data;
+	this->ecc.strength = 1;
 
 	/* Enable the following for a flash based bad block table */
 	this->bbt_options = NAND_BBT_USE_FLASH;
@@ -247,8 +248,6 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
 		goto out_ior;
 	}
 
-	this->ecc.strength = 1;
-
 	new_mtd->name = kasprintf(GFP_KERNEL, "cs553x_nand_cs%d", cs);
 
 	cs553x_mtd[cs] = new_mtd;
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index 945047a..3502606 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -821,9 +821,16 @@ syndrome_done:
 	if (ret < 0)
 		goto err_scan;
 
-	ret = mtd_device_parse_register(&info->mtd, NULL, NULL, pdata->parts,
-					pdata->nr_parts);
-
+	if (pdata->parts)
+		ret = mtd_device_parse_register(&info->mtd, NULL, NULL,
+					pdata->parts, pdata->nr_parts);
+	else {
+		struct mtd_part_parser_data	ppdata;
+
+		ppdata.of_node = pdev->dev.of_node;
+		ret = mtd_device_parse_register(&info->mtd, NULL, &ppdata,
+						NULL, 0);
+	}
 	if (ret < 0)
 		goto err_scan;
 
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index e706a23..0c8bb6b 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -16,14 +16,12 @@
  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  *
  */
-
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/wait.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
 #include <linux/mtd/mtd.h>
 #include <linux/module.h>
 
@@ -89,13 +87,6 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting."
  * format the bank into the proper bits for the controller */
 #define BANK(x) ((x) << 24)
 
-/* List of platforms this NAND controller has be integrated into */
-static const struct pci_device_id denali_pci_ids[] = {
-	{ PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 },
-	{ PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST },
-	{ /* end: all zeroes */ }
-};
-
 /* forward declarations */
 static void clear_interrupts(struct denali_nand_info *denali);
 static uint32_t wait_for_irq(struct denali_nand_info *denali,
@@ -699,7 +690,7 @@ static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask)
 
 	if (comp_res == 0) {
 		/* timeout */
-		printk(KERN_ERR "timeout occurred, status = 0x%x, mask = 0x%x\n",
+		pr_err("timeout occurred, status = 0x%x, mask = 0x%x\n",
 				intr_status, irq_mask);
 
 		intr_status = 0;
@@ -1305,8 +1296,7 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
 		/* TODO: Read OOB data */
 		break;
 	default:
-		printk(KERN_ERR ": unsupported command"
-				" received 0x%x\n", cmd);
+		pr_err(": unsupported command received 0x%x\n", cmd);
 		break;
 	}
 }
@@ -1425,107 +1415,48 @@ void denali_drv_init(struct denali_nand_info *denali)
 	denali->irq_status = 0;
 }
 
-/* driver entry point */
-static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+int denali_init(struct denali_nand_info *denali)
 {
-	int ret = -ENODEV;
-	resource_size_t csr_base, mem_base;
-	unsigned long csr_len, mem_len;
-	struct denali_nand_info *denali;
-
-	denali = kzalloc(sizeof(*denali), GFP_KERNEL);
-	if (!denali)
-		return -ENOMEM;
+	int ret;
 
-	ret = pci_enable_device(dev);
-	if (ret) {
-		printk(KERN_ERR "Spectra: pci_enable_device failed.\n");
-		goto failed_alloc_memery;
-	}
-
-	if (id->driver_data == INTEL_CE4100) {
+	if (denali->platform == INTEL_CE4100) {
 		/* Due to a silicon limitation, we can only support
 		 * ONFI timing mode 1 and below.
 		 */
 		if (onfi_timing_mode < -1 || onfi_timing_mode > 1) {
-			printk(KERN_ERR "Intel CE4100 only supports"
-					" ONFI timing mode 1 or below\n");
-			ret = -EINVAL;
-			goto failed_enable_dev;
-		}
-		denali->platform = INTEL_CE4100;
-		mem_base = pci_resource_start(dev, 0);
-		mem_len = pci_resource_len(dev, 1);
-		csr_base = pci_resource_start(dev, 1);
-		csr_len = pci_resource_len(dev, 1);
-	} else {
-		denali->platform = INTEL_MRST;
-		csr_base = pci_resource_start(dev, 0);
-		csr_len = pci_resource_len(dev, 0);
-		mem_base = pci_resource_start(dev, 1);
-		mem_len = pci_resource_len(dev, 1);
-		if (!mem_len) {
-			mem_base = csr_base + csr_len;
-			mem_len = csr_len;
+			pr_err("Intel CE4100 only supports ONFI timing mode 1 or below\n");
+			return -EINVAL;
 		}
 	}
 
 	/* Is 32-bit DMA supported? */
-	ret = dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
+	ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32));
 	if (ret) {
-		printk(KERN_ERR "Spectra: no usable DMA configuration\n");
-		goto failed_enable_dev;
+		pr_err("Spectra: no usable DMA configuration\n");
+		return ret;
 	}
-	denali->buf.dma_buf = dma_map_single(&dev->dev, denali->buf.buf,
+	denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf,
 					     DENALI_BUF_SIZE,
 					     DMA_BIDIRECTIONAL);
 
-	if (dma_mapping_error(&dev->dev, denali->buf.dma_buf)) {
-		dev_err(&dev->dev, "Spectra: failed to map DMA buffer\n");
-		goto failed_enable_dev;
-	}
-
-	pci_set_master(dev);
-	denali->dev = &dev->dev;
-	denali->mtd.dev.parent = &dev->dev;
-
-	ret = pci_request_regions(dev, DENALI_NAND_NAME);
-	if (ret) {
-		printk(KERN_ERR "Spectra: Unable to request memory regions\n");
-		goto failed_dma_map;
-	}
-
-	denali->flash_reg = ioremap_nocache(csr_base, csr_len);
-	if (!denali->flash_reg) {
-		printk(KERN_ERR "Spectra: Unable to remap memory region\n");
-		ret = -ENOMEM;
-		goto failed_req_regions;
-	}
-
-	denali->flash_mem = ioremap_nocache(mem_base, mem_len);
-	if (!denali->flash_mem) {
-		printk(KERN_ERR "Spectra: ioremap_nocache failed!");
-		ret = -ENOMEM;
-		goto failed_remap_reg;
+	if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) {
+		dev_err(denali->dev, "Spectra: failed to map DMA buffer\n");
+		return -EIO;
 	}
-
+	denali->mtd.dev.parent = denali->dev;
 	denali_hw_init(denali);
 	denali_drv_init(denali);
 
 	/* denali_isr register is done after all the hardware
 	 * initilization is finished*/
-	if (request_irq(dev->irq, denali_isr, IRQF_SHARED,
+	if (request_irq(denali->irq, denali_isr, IRQF_SHARED,
 			DENALI_NAND_NAME, denali)) {
-		printk(KERN_ERR "Spectra: Unable to allocate IRQ\n");
-		ret = -ENODEV;
-		goto failed_remap_mem;
+		pr_err("Spectra: Unable to allocate IRQ\n");
+		return -ENODEV;
 	}
 
 	/* now that our ISR is registered, we can enable interrupts */
 	denali_set_intr_modes(denali, true);
-
-	pci_set_drvdata(dev, denali);
-
 	denali->mtd.name = "denali-nand";
 	denali->mtd.owner = THIS_MODULE;
 	denali->mtd.priv = &denali->nand;
@@ -1549,8 +1480,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	 */
 	if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) {
 		ret = -ENODEV;
-		printk(KERN_ERR "Spectra: device size not supported by this "
-			"version of MTD.");
+		pr_err("Spectra: device size not supported by this version of MTD.");
 		goto failed_req_irq;
 	}
 
@@ -1602,8 +1532,8 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	} else if (denali->mtd.oobsize < (denali->bbtskipbytes +
 			ECC_8BITS * (denali->mtd.writesize /
 			ECC_SECTOR_SIZE))) {
-		printk(KERN_ERR "Your NAND chip OOB is not large enough to"
-				" contain 8bit ECC correction codes");
+		pr_err("Your NAND chip OOB is not large enough to \
+				contain 8bit ECC correction codes");
 		goto failed_req_irq;
 	} else {
 		denali->nand.ecc.strength = 8;
@@ -1655,56 +1585,24 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
 	ret = mtd_device_register(&denali->mtd, NULL, 0);
 	if (ret) {
-		dev_err(&dev->dev, "Spectra: Failed to register MTD: %d\n",
+		dev_err(denali->dev, "Spectra: Failed to register MTD: %d\n",
 				ret);
 		goto failed_req_irq;
 	}
 	return 0;
 
 failed_req_irq:
-	denali_irq_cleanup(dev->irq, denali);
-failed_remap_mem:
-	iounmap(denali->flash_mem);
-failed_remap_reg:
-	iounmap(denali->flash_reg);
-failed_req_regions:
-	pci_release_regions(dev);
-failed_dma_map:
-	dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
-			 DMA_BIDIRECTIONAL);
-failed_enable_dev:
-	pci_disable_device(dev);
-failed_alloc_memery:
-	kfree(denali);
+	denali_irq_cleanup(denali->irq, denali);
+
 	return ret;
 }
+EXPORT_SYMBOL(denali_init);
 
 /* driver exit point */
-static void denali_pci_remove(struct pci_dev *dev)
+void denali_remove(struct denali_nand_info *denali)
 {
-	struct denali_nand_info *denali = pci_get_drvdata(dev);
-
-	nand_release(&denali->mtd);
-
-	denali_irq_cleanup(dev->irq, denali);
-
-	iounmap(denali->flash_reg);
-	iounmap(denali->flash_mem);
-	pci_release_regions(dev);
-	pci_disable_device(dev);
-	dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
-			 DMA_BIDIRECTIONAL);
-	pci_set_drvdata(dev, NULL);
-	kfree(denali);
+	denali_irq_cleanup(denali->irq, denali);
+	dma_unmap_single(denali->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
+			DMA_BIDIRECTIONAL);
 }
-
-MODULE_DEVICE_TABLE(pci, denali_pci_ids);
-
-static struct pci_driver denali_pci_driver = {
-	.name = DENALI_NAND_NAME,
-	.id_table = denali_pci_ids,
-	.probe = denali_pci_probe,
-	.remove = denali_pci_remove,
-};
-
-module_pci_driver(denali_pci_driver);
+EXPORT_SYMBOL(denali_remove);
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index fabb9d5..cec5712 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -466,6 +466,7 @@ struct nand_buf {
 
 #define INTEL_CE4100	1
 #define INTEL_MRST	2
+#define DT		3
 
 struct denali_nand_info {
 	struct mtd_info mtd;
@@ -487,6 +488,7 @@ struct denali_nand_info {
 	uint32_t irq_status;
 	int irq_debug_array[32];
 	int idx;
+	int irq;
 
 	uint32_t devnum;	/* represent how many nands connected */
 	uint32_t fwblks; /* represent how many blocks FW used */
@@ -496,4 +498,7 @@ struct denali_nand_info {
 	uint32_t max_banks;
 };
 
+extern int denali_init(struct denali_nand_info *denali);
+extern void denali_remove(struct denali_nand_info *denali);
+
 #endif /*_LLD_NAND_*/
diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c
new file mode 100644
index 0000000..546f8cb
--- /dev/null
+++ b/drivers/mtd/nand/denali_dt.c
@@ -0,0 +1,167 @@
+/*
+ * NAND Flash Controller Device Driver for DT
+ *
+ * Copyright © 2011, Picochip.
+ *
+ * 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.
+ */
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+
+#include "denali.h"
+
+struct denali_dt {
+	struct denali_nand_info	denali;
+	struct clk		*clk;
+};
+
+static void __iomem *request_and_map(struct device *dev,
+				     const struct resource *res)
+{
+	void __iomem *ptr;
+
+	if (!devm_request_mem_region(dev, res->start, resource_size(res),
+				     "denali-dt")) {
+		dev_err(dev, "unable to request %s\n", res->name);
+		return NULL;
+	}
+
+	ptr = devm_ioremap_nocache(dev, res->start, resource_size(res));
+	if (!res)
+		dev_err(dev, "ioremap_nocache of %s failed!", res->name);
+
+	return ptr;
+}
+
+static const struct of_device_id denali_nand_dt_ids[] = {
+		{ .compatible = "denali,denali-nand-dt" },
+		{ /* sentinel */ }
+	};
+
+MODULE_DEVICE_TABLE(of, denali_nand_dt_ids);
+
+static u64 denali_dma_mask;
+
+static int denali_dt_probe(struct platform_device *ofdev)
+{
+	struct resource *denali_reg, *nand_data;
+	struct denali_dt *dt;
+	struct denali_nand_info *denali;
+	int ret;
+	const struct of_device_id *of_id;
+
+	of_id = of_match_device(denali_nand_dt_ids, &ofdev->dev);
+	if (of_id) {
+		ofdev->id_entry = of_id->data;
+	} else {
+		pr_err("Failed to find the right device id.\n");
+		return -ENOMEM;
+	}
+
+	dt = devm_kzalloc(&ofdev->dev, sizeof(*dt), GFP_KERNEL);
+	if (!dt)
+		return -ENOMEM;
+	denali = &dt->denali;
+
+	denali_reg = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "denali_reg");
+	nand_data = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "nand_data");
+	if (!denali_reg || !nand_data) {
+		dev_err(&ofdev->dev, "resources not completely defined\n");
+		return -EINVAL;
+	}
+
+	denali->platform = DT;
+	denali->dev = &ofdev->dev;
+	denali->irq = platform_get_irq(ofdev, 0);
+	if (denali->irq < 0) {
+		dev_err(&ofdev->dev, "no irq defined\n");
+		return -ENXIO;
+	}
+
+	denali->flash_reg = request_and_map(&ofdev->dev, denali_reg);
+	if (!denali->flash_reg)
+		return -ENOMEM;
+
+	denali->flash_mem = request_and_map(&ofdev->dev, nand_data);
+	if (!denali->flash_mem)
+		return -ENOMEM;
+
+	if (!of_property_read_u32(ofdev->dev.of_node,
+		"dma-mask", (u32 *)&denali_dma_mask)) {
+		denali->dev->dma_mask = &denali_dma_mask;
+	} else {
+		denali->dev->dma_mask = NULL;
+	}
+
+	dt->clk = clk_get(&ofdev->dev, NULL);
+	if (IS_ERR(dt->clk)) {
+		dev_err(&ofdev->dev, "no clk available\n");
+		return PTR_ERR(dt->clk);
+	}
+	clk_prepare_enable(dt->clk);
+
+	ret = denali_init(denali);
+	if (ret)
+		goto out_disable_clk;
+
+	platform_set_drvdata(ofdev, dt);
+	return 0;
+
+out_disable_clk:
+	clk_disable_unprepare(dt->clk);
+	clk_put(dt->clk);
+
+	return ret;
+}
+
+static int denali_dt_remove(struct platform_device *ofdev)
+{
+	struct denali_dt *dt = platform_get_drvdata(ofdev);
+
+	denali_remove(&dt->denali);
+	clk_disable(dt->clk);
+	clk_put(dt->clk);
+
+	return 0;
+}
+
+static struct platform_driver denali_dt_driver = {
+	.probe		= denali_dt_probe,
+	.remove		= denali_dt_remove,
+	.driver		= {
+		.name	= "denali-nand-dt",
+		.owner	= THIS_MODULE,
+		.of_match_table	= of_match_ptr(denali_nand_dt_ids),
+	},
+};
+
+static int __init denali_init_dt(void)
+{
+	return platform_driver_register(&denali_dt_driver);
+}
+module_init(denali_init_dt);
+
+static void __exit denali_exit_dt(void)
+{
+	platform_driver_unregister(&denali_dt_driver);
+}
+module_exit(denali_exit_dt);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jamie Iles");
+MODULE_DESCRIPTION("DT driver for Denali NAND controller");
diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c
new file mode 100644
index 0000000..e3e4662
--- /dev/null
+++ b/drivers/mtd/nand/denali_pci.c
@@ -0,0 +1,144 @@
+/*
+ * NAND Flash Controller Device Driver
+ * Copyright © 2009-2010, Intel Corporation and its suppliers.
+ *
+ * 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.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include "denali.h"
+
+#define DENALI_NAND_NAME    "denali-nand-pci"
+
+/* List of platforms this NAND controller has be integrated into */
+static DEFINE_PCI_DEVICE_TABLE(denali_pci_ids) = {
+	{ PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 },
+	{ PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST },
+	{ /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE(pci, denali_pci_ids);
+
+static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	int ret = -ENODEV;
+	resource_size_t csr_base, mem_base;
+	unsigned long csr_len, mem_len;
+	struct denali_nand_info *denali;
+
+	denali = kzalloc(sizeof(*denali), GFP_KERNEL);
+	if (!denali)
+		return -ENOMEM;
+
+	ret = pci_enable_device(dev);
+	if (ret) {
+		pr_err("Spectra: pci_enable_device failed.\n");
+		goto failed_alloc_memery;
+	}
+
+	if (id->driver_data == INTEL_CE4100) {
+		denali->platform = INTEL_CE4100;
+		mem_base = pci_resource_start(dev, 0);
+		mem_len = pci_resource_len(dev, 1);
+		csr_base = pci_resource_start(dev, 1);
+		csr_len = pci_resource_len(dev, 1);
+	} else {
+		denali->platform = INTEL_MRST;
+		csr_base = pci_resource_start(dev, 0);
+		csr_len = pci_resource_len(dev, 0);
+		mem_base = pci_resource_start(dev, 1);
+		mem_len = pci_resource_len(dev, 1);
+		if (!mem_len) {
+			mem_base = csr_base + csr_len;
+			mem_len = csr_len;
+		}
+	}
+
+	pci_set_master(dev);
+	denali->dev = &dev->dev;
+	denali->irq = dev->irq;
+
+	ret = pci_request_regions(dev, DENALI_NAND_NAME);
+	if (ret) {
+		pr_err("Spectra: Unable to request memory regions\n");
+		goto failed_enable_dev;
+	}
+
+	denali->flash_reg = ioremap_nocache(csr_base, csr_len);
+	if (!denali->flash_reg) {
+		pr_err("Spectra: Unable to remap memory region\n");
+		ret = -ENOMEM;
+		goto failed_req_regions;
+	}
+
+	denali->flash_mem = ioremap_nocache(mem_base, mem_len);
+	if (!denali->flash_mem) {
+		pr_err("Spectra: ioremap_nocache failed!");
+		ret = -ENOMEM;
+		goto failed_remap_reg;
+	}
+
+	ret = denali_init(denali);
+	if (ret)
+		goto failed_remap_mem;
+
+	pci_set_drvdata(dev, denali);
+
+	return 0;
+
+failed_remap_mem:
+	iounmap(denali->flash_mem);
+failed_remap_reg:
+	iounmap(denali->flash_reg);
+failed_req_regions:
+	pci_release_regions(dev);
+failed_enable_dev:
+	pci_disable_device(dev);
+failed_alloc_memery:
+	kfree(denali);
+
+	return ret;
+}
+
+/* driver exit point */
+static void denali_pci_remove(struct pci_dev *dev)
+{
+	struct denali_nand_info *denali = pci_get_drvdata(dev);
+
+	denali_remove(denali);
+	iounmap(denali->flash_reg);
+	iounmap(denali->flash_mem);
+	pci_release_regions(dev);
+	pci_disable_device(dev);
+	pci_set_drvdata(dev, NULL);
+	kfree(denali);
+}
+
+static struct pci_driver denali_pci_driver = {
+	.name = DENALI_NAND_NAME,
+	.id_table = denali_pci_ids,
+	.probe = denali_pci_probe,
+	.remove = denali_pci_remove,
+};
+
+static int denali_init_pci(void)
+{
+	pr_info("Spectra MTD driver built on %s @ %s\n", __DATE__, __TIME__);
+	return pci_register_driver(&denali_pci_driver);
+}
+module_init(denali_init_pci);
+
+static void denali_exit_pci(void)
+{
+	pci_unregister_driver(&denali_pci_driver);
+}
+module_exit(denali_exit_pci);
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 256eb30..81fa578 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -53,8 +53,6 @@ static unsigned long __initdata doc_locations[] = {
 	0xe0000, 0xe2000, 0xe4000, 0xe6000,
 	0xe8000, 0xea000, 0xec000, 0xee000,
 #endif /*  CONFIG_MTD_DOCPROBE_HIGH */
-#else
-#warning Unknown architecture for DiskOnChip. No default probe locations defined
 #endif
 	0xffffffff };
 
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index cc1480a..2065720 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -109,20 +109,6 @@ static struct nand_ecclayout fsl_elbc_oob_lp_eccm1 = {
 };
 
 /*
- * fsl_elbc_oob_lp_eccm* specify that LP NAND's OOB free area starts at offset
- * 1, so we have to adjust bad block pattern. This pattern should be used for
- * x8 chips only. So far hardware does not support x16 chips anyway.
- */
-static u8 scan_ff_pattern[] = { 0xff, };
-
-static struct nand_bbt_descr largepage_memorybased = {
-	.options = 0,
-	.offs = 0,
-	.len = 1,
-	.pattern = scan_ff_pattern,
-};
-
-/*
  * ELBC may use HW ECC, so that OOB offsets, that NAND core uses for bbt,
  * interfere with ECC positions, that's why we implement our own descriptors.
  * OOB {11, 5}, works for both SP and LP chips, with ECCM = 1 and ECCM = 0.
@@ -699,7 +685,6 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
 			chip->ecc.layout = (priv->fmr & FMR_ECCM) ?
 			                   &fsl_elbc_oob_lp_eccm1 :
 			                   &fsl_elbc_oob_lp_eccm0;
-			chip->badblock_pattern = &largepage_memorybased;
 		}
 	} else {
 		dev_err(priv->dev,
@@ -814,7 +799,7 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
 
 static DEFINE_MUTEX(fsl_elbc_nand_mutex);
 
-static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
+static int fsl_elbc_nand_probe(struct platform_device *pdev)
 {
 	struct fsl_lbc_regs __iomem *lbc;
 	struct fsl_elbc_mtd *priv;
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index 3551a99..ad62226 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -389,7 +389,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 			timing = IFC_FIR_OP_RBCD;
 
 		out_be32(&ifc->ifc_nand.nand_fir0,
-				(IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) |
+				(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
 				(IFC_FIR_OP_UA  << IFC_NAND_FIR0_OP1_SHIFT) |
 				(timing << IFC_NAND_FIR0_OP2_SHIFT));
 		out_be32(&ifc->ifc_nand.nand_fcr0,
@@ -754,7 +754,7 @@ static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv)
 
 	/* READID */
 	out_be32(&ifc->ifc_nand.nand_fir0,
-			(IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) |
+			(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
 			(IFC_FIR_OP_UA  << IFC_NAND_FIR0_OP1_SHIFT) |
 			(IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
 	out_be32(&ifc->ifc_nand.nand_fcr0,
@@ -922,7 +922,7 @@ static int match_bank(struct fsl_ifc_regs __iomem *ifc, int bank,
 
 static DEFINE_MUTEX(fsl_ifc_nand_mutex);
 
-static int __devinit fsl_ifc_nand_probe(struct platform_device *dev)
+static int fsl_ifc_nand_probe(struct platform_device *dev)
 {
 	struct fsl_ifc_regs __iomem *ifc;
 	struct fsl_ifc_mtd *priv;
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 45df542..5a8f5c4 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -152,7 +152,7 @@ static void fun_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 		fun_wait_rnb(fun);
 }
 
-static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
+static int fun_chip_init(struct fsl_upm_nand *fun,
 				   const struct device_node *upm_np,
 				   const struct resource *io_res)
 {
@@ -201,7 +201,7 @@ err:
 	return ret;
 }
 
-static int __devinit fun_probe(struct platform_device *ofdev)
+static int fun_probe(struct platform_device *ofdev)
 {
 	struct fsl_upm_nand *fun;
 	struct resource io_res;
@@ -318,7 +318,7 @@ err1:
 	return ret;
 }
 
-static int __devexit fun_remove(struct platform_device *ofdev)
+static int fun_remove(struct platform_device *ofdev)
 {
 	struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev);
 	int i;
@@ -350,7 +350,7 @@ static struct platform_driver of_fun_driver = {
 		.of_match_table = of_fun_match,
 	},
 	.probe		= fun_probe,
-	.remove		= __devexit_p(fun_remove),
+	.remove		= fun_remove,
 };
 
 module_platform_driver(of_fun_driver);
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 38d2624..1d74464 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -361,7 +361,7 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 	struct nand_chip *this = mtd->priv;
 	struct fsmc_nand_data *host = container_of(mtd,
 					struct fsmc_nand_data, mtd);
-	void *__iomem *regs = host->regs_va;
+	void __iomem *regs = host->regs_va;
 	unsigned int bank = host->bank;
 
 	if (ctrl & NAND_CTRL_CHANGE) {
@@ -383,13 +383,13 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 			pc |= FSMC_ENABLE;
 		else
 			pc &= ~FSMC_ENABLE;
-		writel(pc, FSMC_NAND_REG(regs, bank, PC));
+		writel_relaxed(pc, FSMC_NAND_REG(regs, bank, PC));
 	}
 
 	mb();
 
 	if (cmd != NAND_CMD_NONE)
-		writeb(cmd, this->IO_ADDR_W);
+		writeb_relaxed(cmd, this->IO_ADDR_W);
 }
 
 /*
@@ -426,14 +426,18 @@ static void fsmc_nand_setup(void __iomem *regs, uint32_t bank,
 	tset = (tims->tset & FSMC_TSET_MASK) << FSMC_TSET_SHIFT;
 
 	if (busw)
-		writel(value | FSMC_DEVWID_16, FSMC_NAND_REG(regs, bank, PC));
+		writel_relaxed(value | FSMC_DEVWID_16,
+				FSMC_NAND_REG(regs, bank, PC));
 	else
-		writel(value | FSMC_DEVWID_8, FSMC_NAND_REG(regs, bank, PC));
+		writel_relaxed(value | FSMC_DEVWID_8,
+				FSMC_NAND_REG(regs, bank, PC));
 
-	writel(readl(FSMC_NAND_REG(regs, bank, PC)) | tclr | tar,
+	writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | tclr | tar,
 			FSMC_NAND_REG(regs, bank, PC));
-	writel(thiz | thold | twait | tset, FSMC_NAND_REG(regs, bank, COMM));
-	writel(thiz | thold | twait | tset, FSMC_NAND_REG(regs, bank, ATTRIB));
+	writel_relaxed(thiz | thold | twait | tset,
+			FSMC_NAND_REG(regs, bank, COMM));
+	writel_relaxed(thiz | thold | twait | tset,
+			FSMC_NAND_REG(regs, bank, ATTRIB));
 }
 
 /*
@@ -446,11 +450,11 @@ static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
 	void __iomem *regs = host->regs_va;
 	uint32_t bank = host->bank;
 
-	writel(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCPLEN_256,
+	writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCPLEN_256,
 			FSMC_NAND_REG(regs, bank, PC));
-	writel(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCEN,
+	writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCEN,
 			FSMC_NAND_REG(regs, bank, PC));
-	writel(readl(FSMC_NAND_REG(regs, bank, PC)) | FSMC_ECCEN,
+	writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | FSMC_ECCEN,
 			FSMC_NAND_REG(regs, bank, PC));
 }
 
@@ -470,7 +474,7 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
 	unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT;
 
 	do {
-		if (readl(FSMC_NAND_REG(regs, bank, STS)) & FSMC_CODE_RDY)
+		if (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) & FSMC_CODE_RDY)
 			break;
 		else
 			cond_resched();
@@ -481,25 +485,25 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
 		return -ETIMEDOUT;
 	}
 
-	ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC1));
+	ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
 	ecc[0] = (uint8_t) (ecc_tmp >> 0);
 	ecc[1] = (uint8_t) (ecc_tmp >> 8);
 	ecc[2] = (uint8_t) (ecc_tmp >> 16);
 	ecc[3] = (uint8_t) (ecc_tmp >> 24);
 
-	ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC2));
+	ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2));
 	ecc[4] = (uint8_t) (ecc_tmp >> 0);
 	ecc[5] = (uint8_t) (ecc_tmp >> 8);
 	ecc[6] = (uint8_t) (ecc_tmp >> 16);
 	ecc[7] = (uint8_t) (ecc_tmp >> 24);
 
-	ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC3));
+	ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3));
 	ecc[8] = (uint8_t) (ecc_tmp >> 0);
 	ecc[9] = (uint8_t) (ecc_tmp >> 8);
 	ecc[10] = (uint8_t) (ecc_tmp >> 16);
 	ecc[11] = (uint8_t) (ecc_tmp >> 24);
 
-	ecc_tmp = readl(FSMC_NAND_REG(regs, bank, STS));
+	ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, STS));
 	ecc[12] = (uint8_t) (ecc_tmp >> 16);
 
 	return 0;
@@ -519,7 +523,7 @@ static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data,
 	uint32_t bank = host->bank;
 	uint32_t ecc_tmp;
 
-	ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC1));
+	ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
 	ecc[0] = (uint8_t) (ecc_tmp >> 0);
 	ecc[1] = (uint8_t) (ecc_tmp >> 8);
 	ecc[2] = (uint8_t) (ecc_tmp >> 16);
@@ -601,7 +605,7 @@ static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len,
 	dma_async_issue_pending(chan);
 
 	ret =
-	wait_for_completion_interruptible_timeout(&host->dma_access_complete,
+	wait_for_completion_timeout(&host->dma_access_complete,
 				msecs_to_jiffies(3000));
 	if (ret <= 0) {
 		chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
@@ -628,10 +632,10 @@ static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 		uint32_t *p = (uint32_t *)buf;
 		len = len >> 2;
 		for (i = 0; i < len; i++)
-			writel(p[i], chip->IO_ADDR_W);
+			writel_relaxed(p[i], chip->IO_ADDR_W);
 	} else {
 		for (i = 0; i < len; i++)
-			writeb(buf[i], chip->IO_ADDR_W);
+			writeb_relaxed(buf[i], chip->IO_ADDR_W);
 	}
 }
 
@@ -651,10 +655,10 @@ static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 		uint32_t *p = (uint32_t *)buf;
 		len = len >> 2;
 		for (i = 0; i < len; i++)
-			p[i] = readl(chip->IO_ADDR_R);
+			p[i] = readl_relaxed(chip->IO_ADDR_R);
 	} else {
 		for (i = 0; i < len; i++)
-			buf[i] = readb(chip->IO_ADDR_R);
+			buf[i] = readb_relaxed(chip->IO_ADDR_R);
 	}
 }
 
@@ -783,7 +787,7 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
 	uint32_t num_err, i;
 	uint32_t ecc1, ecc2, ecc3, ecc4;
 
-	num_err = (readl(FSMC_NAND_REG(regs, bank, STS)) >> 10) & 0xF;
+	num_err = (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) >> 10) & 0xF;
 
 	/* no bit flipping */
 	if (likely(num_err == 0))
@@ -826,10 +830,10 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
 	 * uint64_t array and error offset indexes are populated in err_idx
 	 * array
 	 */
-	ecc1 = readl(FSMC_NAND_REG(regs, bank, ECC1));
-	ecc2 = readl(FSMC_NAND_REG(regs, bank, ECC2));
-	ecc3 = readl(FSMC_NAND_REG(regs, bank, ECC3));
-	ecc4 = readl(FSMC_NAND_REG(regs, bank, STS));
+	ecc1 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
+	ecc2 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2));
+	ecc3 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3));
+	ecc4 = readl_relaxed(FSMC_NAND_REG(regs, bank, STS));
 
 	err_idx[0] = (ecc1 >> 0) & 0x1FFF;
 	err_idx[1] = (ecc1 >> 13) & 0x1FFF;
@@ -860,7 +864,7 @@ static bool filter(struct dma_chan *chan, void *slave)
 }
 
 #ifdef CONFIG_OF
-static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev,
+static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
 					       struct device_node *np)
 {
 	struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
@@ -876,15 +880,13 @@ static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev,
 			return -EINVAL;
 		}
 	}
-	of_property_read_u32(np, "st,ale-off", &pdata->ale_off);
-	of_property_read_u32(np, "st,cle-off", &pdata->cle_off);
 	if (of_get_property(np, "nand-skip-bbtscan", NULL))
 		pdata->options = NAND_SKIP_BBTSCAN;
 
 	return 0;
 }
 #else
-static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev,
+static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
 					       struct device_node *np)
 {
 	return -ENOSYS;
@@ -935,41 +937,28 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	if (!res)
 		return -EINVAL;
 
-	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
-				pdev->name)) {
-		dev_err(&pdev->dev, "Failed to get memory data resourse\n");
-		return -ENOENT;
-	}
-
-	host->data_pa = (dma_addr_t)res->start;
-	host->data_va = devm_ioremap(&pdev->dev, res->start,
-			resource_size(res));
+	host->data_va = devm_request_and_ioremap(&pdev->dev, res);
 	if (!host->data_va) {
 		dev_err(&pdev->dev, "data ioremap failed\n");
 		return -ENOMEM;
 	}
+	host->data_pa = (dma_addr_t)res->start;
 
-	if (!devm_request_mem_region(&pdev->dev, res->start + pdata->ale_off,
-			resource_size(res), pdev->name)) {
-		dev_err(&pdev->dev, "Failed to get memory ale resourse\n");
-		return -ENOENT;
-	}
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_addr");
+	if (!res)
+		return -EINVAL;
 
-	host->addr_va = devm_ioremap(&pdev->dev, res->start + pdata->ale_off,
-			resource_size(res));
+	host->addr_va = devm_request_and_ioremap(&pdev->dev, res);
 	if (!host->addr_va) {
 		dev_err(&pdev->dev, "ale ioremap failed\n");
 		return -ENOMEM;
 	}
 
-	if (!devm_request_mem_region(&pdev->dev, res->start + pdata->cle_off,
-			resource_size(res), pdev->name)) {
-		dev_err(&pdev->dev, "Failed to get memory cle resourse\n");
-		return -ENOENT;
-	}
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_cmd");
+	if (!res)
+		return -EINVAL;
 
-	host->cmd_va = devm_ioremap(&pdev->dev, res->start + pdata->cle_off,
-			resource_size(res));
+	host->cmd_va = devm_request_and_ioremap(&pdev->dev, res);
 	if (!host->cmd_va) {
 		dev_err(&pdev->dev, "ale ioremap failed\n");
 		return -ENOMEM;
@@ -979,14 +968,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	if (!res)
 		return -EINVAL;
 
-	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
-			pdev->name)) {
-		dev_err(&pdev->dev, "Failed to get memory regs resourse\n");
-		return -ENOENT;
-	}
-
-	host->regs_va = devm_ioremap(&pdev->dev, res->start,
-			resource_size(res));
+	host->regs_va = devm_request_and_ioremap(&pdev->dev, res);
 	if (!host->regs_va) {
 		dev_err(&pdev->dev, "regs ioremap failed\n");
 		return -ENOMEM;
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c
index bc73bc5..7aec569 100644
--- a/drivers/mtd/nand/gpio.c
+++ b/drivers/mtd/nand/gpio.c
@@ -134,7 +134,11 @@ static void gpio_nand_readbuf16(struct mtd_info *mtd, u_char *buf, int len)
 static int gpio_nand_devready(struct mtd_info *mtd)
 {
 	struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd);
-	return gpio_get_value(gpiomtd->plat.gpio_rdy);
+
+	if (gpio_is_valid(gpiomtd->plat.gpio_rdy))
+		return gpio_get_value(gpiomtd->plat.gpio_rdy);
+
+	return 1;
 }
 
 #ifdef CONFIG_OF
@@ -227,7 +231,7 @@ gpio_nand_get_io_sync(struct platform_device *pdev)
 	return platform_get_resource(pdev, IORESOURCE_MEM, 1);
 }
 
-static int __devexit gpio_nand_remove(struct platform_device *dev)
+static int gpio_nand_remove(struct platform_device *dev)
 {
 	struct gpiomtd *gpiomtd = platform_get_drvdata(dev);
 	struct resource *res;
@@ -252,7 +256,8 @@ static int __devexit gpio_nand_remove(struct platform_device *dev)
 	gpio_free(gpiomtd->plat.gpio_nce);
 	if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
 		gpio_free(gpiomtd->plat.gpio_nwp);
-	gpio_free(gpiomtd->plat.gpio_rdy);
+	if (gpio_is_valid(gpiomtd->plat.gpio_rdy))
+		gpio_free(gpiomtd->plat.gpio_rdy);
 
 	kfree(gpiomtd);
 
@@ -277,7 +282,7 @@ static void __iomem *request_and_remap(struct resource *res, size_t size,
 	return ptr;
 }
 
-static int __devinit gpio_nand_probe(struct platform_device *dev)
+static int gpio_nand_probe(struct platform_device *dev)
 {
 	struct gpiomtd *gpiomtd;
 	struct nand_chip *this;
@@ -336,10 +341,12 @@ static int __devinit gpio_nand_probe(struct platform_device *dev)
 	if (ret)
 		goto err_cle;
 	gpio_direction_output(gpiomtd->plat.gpio_cle, 0);
-	ret = gpio_request(gpiomtd->plat.gpio_rdy, "NAND RDY");
-	if (ret)
-		goto err_rdy;
-	gpio_direction_input(gpiomtd->plat.gpio_rdy);
+	if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) {
+		ret = gpio_request(gpiomtd->plat.gpio_rdy, "NAND RDY");
+		if (ret)
+			goto err_rdy;
+		gpio_direction_input(gpiomtd->plat.gpio_rdy);
+	}
 
 
 	this->IO_ADDR_W  = this->IO_ADDR_R;
@@ -386,7 +393,8 @@ static int __devinit gpio_nand_probe(struct platform_device *dev)
 err_wp:
 	if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
 		gpio_set_value(gpiomtd->plat.gpio_nwp, 0);
-	gpio_free(gpiomtd->plat.gpio_rdy);
+	if (gpio_is_valid(gpiomtd->plat.gpio_rdy))
+		gpio_free(gpiomtd->plat.gpio_rdy);
 err_rdy:
 	gpio_free(gpiomtd->plat.gpio_cle);
 err_cle:
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
index 3502acc..1585c5b 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
@@ -18,7 +18,6 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
-#include <linux/mtd/gpmi-nand.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
 
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index d79696b..5cd141f 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -25,7 +25,6 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
-#include <linux/mtd/gpmi-nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/of.h>
@@ -33,6 +32,12 @@
 #include <linux/of_mtd.h>
 #include "gpmi-nand.h"
 
+/* Resource names for the GPMI NAND driver. */
+#define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME  "gpmi-nand"
+#define GPMI_NAND_BCH_REGS_ADDR_RES_NAME   "bch"
+#define GPMI_NAND_BCH_INTERRUPT_RES_NAME   "bch"
+#define GPMI_NAND_DMA_INTERRUPT_RES_NAME   "gpmi-dma"
+
 /* add our owner bbt descriptor */
 static uint8_t scan_ff_pattern[] = { 0xff };
 static struct nand_bbt_descr gpmi_bbt_descr = {
@@ -222,7 +227,7 @@ void prepare_data_dma(struct gpmi_nand_data *this, enum dma_data_direction dr)
 
 		ret = dma_map_sg(this->dev, sgl, 1, dr);
 		if (ret == 0)
-			pr_err("map failed.\n");
+			pr_err("DMA mapping failed.\n");
 
 		this->direct_dma_map_ok = false;
 	}
@@ -314,7 +319,7 @@ int start_dma_with_bch_irq(struct gpmi_nand_data *this,
 	return 0;
 }
 
-static int __devinit
+static int
 acquire_register_block(struct gpmi_nand_data *this, const char *res_name)
 {
 	struct platform_device *pdev = this->pdev;
@@ -355,7 +360,7 @@ static void release_register_block(struct gpmi_nand_data *this)
 	res->bch_regs = NULL;
 }
 
-static int __devinit
+static int
 acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h)
 {
 	struct platform_device *pdev = this->pdev;
@@ -422,7 +427,7 @@ static void release_dma_channels(struct gpmi_nand_data *this)
 		}
 }
 
-static int __devinit acquire_dma_channels(struct gpmi_nand_data *this)
+static int acquire_dma_channels(struct gpmi_nand_data *this)
 {
 	struct platform_device *pdev = this->pdev;
 	struct resource *r_dma;
@@ -456,7 +461,7 @@ static int __devinit acquire_dma_channels(struct gpmi_nand_data *this)
 
 	dma_chan = dma_request_channel(mask, gpmi_dma_filter, this);
 	if (!dma_chan) {
-		pr_err("dma_request_channel failed.\n");
+		pr_err("Failed to request DMA channel.\n");
 		goto acquire_err;
 	}
 
@@ -487,7 +492,7 @@ static char *extra_clks_for_mx6q[GPMI_CLK_MAX] = {
 	"gpmi_apb", "gpmi_bch", "gpmi_bch_apb", "per1_bch",
 };
 
-static int __devinit gpmi_get_clks(struct gpmi_nand_data *this)
+static int gpmi_get_clks(struct gpmi_nand_data *this)
 {
 	struct resources *r = &this->resources;
 	char **extra_clks = NULL;
@@ -533,7 +538,7 @@ err_clock:
 	return -ENOMEM;
 }
 
-static int __devinit acquire_resources(struct gpmi_nand_data *this)
+static int acquire_resources(struct gpmi_nand_data *this)
 {
 	struct pinctrl *pinctrl;
 	int ret;
@@ -583,7 +588,7 @@ static void release_resources(struct gpmi_nand_data *this)
 	release_dma_channels(this);
 }
 
-static int __devinit init_hardware(struct gpmi_nand_data *this)
+static int init_hardware(struct gpmi_nand_data *this)
 {
 	int ret;
 
@@ -625,7 +630,8 @@ static int read_page_prepare(struct gpmi_nand_data *this,
 						length, DMA_FROM_DEVICE);
 		if (dma_mapping_error(dev, dest_phys)) {
 			if (alt_size < length) {
-				pr_err("Alternate buffer is too small\n");
+				pr_err("%s, Alternate buffer is too small\n",
+					__func__);
 				return -ENOMEM;
 			}
 			goto map_failed;
@@ -675,7 +681,8 @@ static int send_page_prepare(struct gpmi_nand_data *this,
 						DMA_TO_DEVICE);
 		if (dma_mapping_error(dev, source_phys)) {
 			if (alt_size < length) {
-				pr_err("Alternate buffer is too small\n");
+				pr_err("%s, Alternate buffer is too small\n",
+					__func__);
 				return -ENOMEM;
 			}
 			goto map_failed;
@@ -763,7 +770,7 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
 
 error_alloc:
 	gpmi_free_dma_buffer(this);
-	pr_err("allocate DMA buffer ret!!\n");
+	pr_err("Error allocating DMA buffers!\n");
 	return -ENOMEM;
 }
 
@@ -1474,7 +1481,7 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this)
 	/* Set up the NFC geometry which is used by BCH. */
 	ret = bch_set_geometry(this);
 	if (ret) {
-		pr_err("set geometry ret : %d\n", ret);
+		pr_err("Error setting BCH geometry : %d\n", ret);
 		return ret;
 	}
 
@@ -1535,7 +1542,7 @@ static void gpmi_nfc_exit(struct gpmi_nand_data *this)
 	gpmi_free_dma_buffer(this);
 }
 
-static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this)
+static int gpmi_nfc_init(struct gpmi_nand_data *this)
 {
 	struct mtd_info  *mtd = &this->mtd;
 	struct nand_chip *chip = &this->nand;
@@ -1618,7 +1625,7 @@ static const struct of_device_id gpmi_nand_id_table[] = {
 };
 MODULE_DEVICE_TABLE(of, gpmi_nand_id_table);
 
-static int __devinit gpmi_nand_probe(struct platform_device *pdev)
+static int gpmi_nand_probe(struct platform_device *pdev)
 {
 	struct gpmi_nand_data *this;
 	const struct of_device_id *of_id;
@@ -1668,7 +1675,7 @@ exit_acquire_resources:
 	return ret;
 }
 
-static int __devexit gpmi_nand_remove(struct platform_device *pdev)
+static int gpmi_nand_remove(struct platform_device *pdev)
 {
 	struct gpmi_nand_data *this = platform_get_drvdata(pdev);
 
@@ -1685,7 +1692,7 @@ static struct platform_driver gpmi_nand_driver = {
 		.of_match_table = gpmi_nand_id_table,
 	},
 	.probe   = gpmi_nand_probe,
-	.remove  = __devexit_p(gpmi_nand_remove),
+	.remove  = gpmi_nand_remove,
 	.id_table = gpmi_ids,
 };
 module_platform_driver(gpmi_nand_driver);
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
index 7ac25c1..3d93a5e 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
@@ -130,7 +130,6 @@ struct gpmi_nand_data {
 	/* System Interface */
 	struct device		*dev;
 	struct platform_device	*pdev;
-	struct gpmi_nand_platform_data	*pdata;
 
 	/* Resources */
 	struct resources	resources;
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
index 100b677..8d415f0 100644
--- a/drivers/mtd/nand/jz4740_nand.c
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -316,13 +316,17 @@ err:
 	return ret;
 }
 
-static inline void jz_nand_iounmap_resource(struct resource *res, void __iomem *base)
+static inline void jz_nand_iounmap_resource(struct resource *res,
+					    void __iomem *base)
 {
 	iounmap(base);
 	release_mem_region(res->start, resource_size(res));
 }
 
-static int __devinit jz_nand_detect_bank(struct platform_device *pdev, struct jz_nand *nand, unsigned char bank, size_t chipnr, uint8_t *nand_maf_id, uint8_t *nand_dev_id) {
+static int jz_nand_detect_bank(struct platform_device *pdev,
+			       struct jz_nand *nand, unsigned char bank,
+			       size_t chipnr, uint8_t *nand_maf_id,
+			       uint8_t *nand_dev_id) {
 	int ret;
 	int gpio;
 	char gpio_name[9];
@@ -400,7 +404,7 @@ notfound_gpio:
 	return ret;
 }
 
-static int __devinit jz_nand_probe(struct platform_device *pdev)
+static int jz_nand_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct jz_nand *nand;
@@ -541,7 +545,7 @@ err_free:
 	return ret;
 }
 
-static int __devexit jz_nand_remove(struct platform_device *pdev)
+static int jz_nand_remove(struct platform_device *pdev)
 {
 	struct jz_nand *nand = platform_get_drvdata(pdev);
 	struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
@@ -573,7 +577,7 @@ static int __devexit jz_nand_remove(struct platform_device *pdev)
 
 static struct platform_driver jz_nand_driver = {
 	.probe = jz_nand_probe,
-	.remove = __devexit_p(jz_nand_remove),
+	.remove = jz_nand_remove,
 	.driver = {
 		.name = "jz4740-nand",
 		.owner = THIS_MODULE,
diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c
index c29b7ac..f182bef 100644
--- a/drivers/mtd/nand/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/lpc32xx_mlc.c
@@ -655,7 +655,7 @@ static struct lpc32xx_nand_cfg_mlc *lpc32xx_parse_dt(struct device *dev)
 /*
  * Probe for NAND controller
  */
-static int __devinit lpc32xx_nand_probe(struct platform_device *pdev)
+static int lpc32xx_nand_probe(struct platform_device *pdev)
 {
 	struct lpc32xx_nand_host *host;
 	struct mtd_info *mtd;
@@ -845,7 +845,7 @@ err_exit1:
 /*
  * Remove NAND device
  */
-static int __devexit lpc32xx_nand_remove(struct platform_device *pdev)
+static int lpc32xx_nand_remove(struct platform_device *pdev)
 {
 	struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
 	struct mtd_info *mtd = &host->mtd;
@@ -907,7 +907,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_nand_match);
 
 static struct platform_driver lpc32xx_nand_driver = {
 	.probe		= lpc32xx_nand_probe,
-	.remove		= __devexit_p(lpc32xx_nand_remove),
+	.remove		= lpc32xx_nand_remove,
 	.resume		= lpc32xx_nand_resume,
 	.suspend	= lpc32xx_nand_suspend,
 	.driver		= {
diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c
index 32409c4..030b78c 100644
--- a/drivers/mtd/nand/lpc32xx_slc.c
+++ b/drivers/mtd/nand/lpc32xx_slc.c
@@ -755,7 +755,7 @@ static struct lpc32xx_nand_cfg_slc *lpc32xx_parse_dt(struct device *dev)
 /*
  * Probe for NAND controller
  */
-static int __devinit lpc32xx_nand_probe(struct platform_device *pdev)
+static int lpc32xx_nand_probe(struct platform_device *pdev)
 {
 	struct lpc32xx_nand_host *host;
 	struct mtd_info *mtd;
@@ -949,7 +949,7 @@ err_exit1:
 /*
  * Remove NAND device.
  */
-static int __devexit lpc32xx_nand_remove(struct platform_device *pdev)
+static int lpc32xx_nand_remove(struct platform_device *pdev)
 {
 	uint32_t tmp;
 	struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
@@ -1021,7 +1021,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_nand_match);
 
 static struct platform_driver lpc32xx_nand_driver = {
 	.probe		= lpc32xx_nand_probe,
-	.remove		= __devexit_p(lpc32xx_nand_remove),
+	.remove		= lpc32xx_nand_remove,
 	.resume		= lpc32xx_nand_resume,
 	.suspend	= lpc32xx_nand_suspend,
 	.driver		= {
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index f776c85..3c9cdcb 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -626,7 +626,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 		iounmap(prv->csreg);
 }
 
-static int __devinit mpc5121_nfc_probe(struct platform_device *op)
+static int mpc5121_nfc_probe(struct platform_device *op)
 {
 	struct device_node *rootnode, *dn = op->dev.of_node;
 	struct device *dev = &op->dev;
@@ -827,7 +827,7 @@ error:
 	return retval;
 }
 
-static int __devexit mpc5121_nfc_remove(struct platform_device *op)
+static int mpc5121_nfc_remove(struct platform_device *op)
 {
 	struct device *dev = &op->dev;
 	struct mtd_info *mtd = dev_get_drvdata(dev);
@@ -841,14 +841,14 @@ static int __devexit mpc5121_nfc_remove(struct platform_device *op)
 	return 0;
 }
 
-static struct of_device_id mpc5121_nfc_match[] __devinitdata = {
+static struct of_device_id mpc5121_nfc_match[] = {
 	{ .compatible = "fsl,mpc5121-nfc", },
 	{},
 };
 
 static struct platform_driver mpc5121_nfc_driver = {
 	.probe		= mpc5121_nfc_probe,
-	.remove		= __devexit_p(mpc5121_nfc_remove),
+	.remove		= mpc5121_nfc_remove,
 	.driver		= {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 72e31d8..d316324 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -37,15 +37,9 @@
 
 #include <asm/mach/flash.h>
 #include <linux/platform_data/mtd-mxc_nand.h>
-#include <mach/hardware.h>
 
 #define DRIVER_NAME "mxc_nand"
 
-#define nfc_is_v21()		(cpu_is_mx25() || cpu_is_mx35())
-#define nfc_is_v1()		(cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
-#define nfc_is_v3_2a()		cpu_is_mx51()
-#define nfc_is_v3_2b()		cpu_is_mx53()
-
 /* Addresses for NFC registers */
 #define NFC_V1_V2_BUF_SIZE		(host->regs + 0x00)
 #define NFC_V1_V2_BUF_ADDR		(host->regs + 0x04)
@@ -1283,6 +1277,53 @@ static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
 	.ppb_shift = 8,
 };
 
+static inline int is_imx21_nfc(struct mxc_nand_host *host)
+{
+	return host->devtype_data == &imx21_nand_devtype_data;
+}
+
+static inline int is_imx27_nfc(struct mxc_nand_host *host)
+{
+	return host->devtype_data == &imx27_nand_devtype_data;
+}
+
+static inline int is_imx25_nfc(struct mxc_nand_host *host)
+{
+	return host->devtype_data == &imx25_nand_devtype_data;
+}
+
+static inline int is_imx51_nfc(struct mxc_nand_host *host)
+{
+	return host->devtype_data == &imx51_nand_devtype_data;
+}
+
+static inline int is_imx53_nfc(struct mxc_nand_host *host)
+{
+	return host->devtype_data == &imx53_nand_devtype_data;
+}
+
+static struct platform_device_id mxcnd_devtype[] = {
+	{
+		.name = "imx21-nand",
+		.driver_data = (kernel_ulong_t) &imx21_nand_devtype_data,
+	}, {
+		.name = "imx27-nand",
+		.driver_data = (kernel_ulong_t) &imx27_nand_devtype_data,
+	}, {
+		.name = "imx25-nand",
+		.driver_data = (kernel_ulong_t) &imx25_nand_devtype_data,
+	}, {
+		.name = "imx51-nand",
+		.driver_data = (kernel_ulong_t) &imx51_nand_devtype_data,
+	}, {
+		.name = "imx53-nand",
+		.driver_data = (kernel_ulong_t) &imx53_nand_devtype_data,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, mxcnd_devtype);
+
 #ifdef CONFIG_OF_MTD
 static const struct of_device_id mxcnd_dt_ids[] = {
 	{
@@ -1337,33 +1378,7 @@ static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
 }
 #endif
 
-static int __init mxcnd_probe_pdata(struct mxc_nand_host *host)
-{
-	struct mxc_nand_platform_data *pdata = host->dev->platform_data;
-
-	if (!pdata)
-		return -ENODEV;
-
-	host->pdata = *pdata;
-
-	if (nfc_is_v1()) {
-		if (cpu_is_mx21())
-			host->devtype_data = &imx21_nand_devtype_data;
-		else
-			host->devtype_data = &imx27_nand_devtype_data;
-	} else if (nfc_is_v21()) {
-		host->devtype_data = &imx25_nand_devtype_data;
-	} else if (nfc_is_v3_2a()) {
-		host->devtype_data = &imx51_nand_devtype_data;
-	} else if (nfc_is_v3_2b()) {
-		host->devtype_data = &imx53_nand_devtype_data;
-	} else
-		BUG();
-
-	return 0;
-}
-
-static int __devinit mxcnd_probe(struct platform_device *pdev)
+static int mxcnd_probe(struct platform_device *pdev)
 {
 	struct nand_chip *this;
 	struct mtd_info *mtd;
@@ -1404,8 +1419,16 @@ static int __devinit mxcnd_probe(struct platform_device *pdev)
 		return PTR_ERR(host->clk);
 
 	err = mxcnd_probe_dt(host);
-	if (err > 0)
-		err = mxcnd_probe_pdata(host);
+	if (err > 0) {
+		struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
+		if (pdata) {
+			host->pdata = *pdata;
+			host->devtype_data = (struct mxc_nand_devtype_data *)
+						pdev->id_entry->driver_data;
+		} else {
+			err = -ENODEV;
+		}
+	}
 	if (err < 0)
 		return err;
 
@@ -1494,7 +1517,7 @@ static int __devinit mxcnd_probe(struct platform_device *pdev)
 	}
 
 	/* first scan to find the device and get the page size */
-	if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) {
+	if (nand_scan_ident(mtd, is_imx25_nfc(host) ? 4 : 1, NULL)) {
 		err = -ENXIO;
 		goto escan;
 	}
@@ -1508,7 +1531,7 @@ static int __devinit mxcnd_probe(struct platform_device *pdev)
 		this->ecc.layout = host->devtype_data->ecclayout_4k;
 
 	if (this->ecc.mode == NAND_ECC_HW) {
-		if (nfc_is_v1())
+		if (is_imx21_nfc(host) || is_imx27_nfc(host))
 			this->ecc.strength = 1;
 		else
 			this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
@@ -1538,7 +1561,7 @@ escan:
 	return err;
 }
 
-static int __devexit mxcnd_remove(struct platform_device *pdev)
+static int mxcnd_remove(struct platform_device *pdev)
 {
 	struct mxc_nand_host *host = platform_get_drvdata(pdev);
 
@@ -1555,8 +1578,9 @@ static struct platform_driver mxcnd_driver = {
 		   .owner = THIS_MODULE,
 		   .of_match_table = of_match_ptr(mxcnd_dt_ids),
 	},
+	.id_table = mxcnd_devtype,
 	.probe = mxcnd_probe,
-	.remove = __devexit_p(mxcnd_remove),
+	.remove = mxcnd_remove,
 };
 module_platform_driver(mxcnd_driver);
 
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 1a03b7f..6eef7fb 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -160,7 +160,7 @@ static uint8_t nand_read_byte(struct mtd_info *mtd)
 }
 
 /**
- * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
+ * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip
  * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip
  * @mtd: MTD device structure
  *
@@ -865,6 +865,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
 	led_trigger_event(nand_led_trigger, LED_OFF);
 
 	status = (int)chip->read_byte(mtd);
+	/* This can happen if in case of timeout or buggy dev_ready */
+	WARN_ON(!(status & NAND_STATUS_READY));
 	return status;
 }
 
@@ -899,7 +901,7 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
 	/* Call wait ready function */
 	status = chip->waitfunc(mtd, chip);
 	/* See if device thinks it succeeded */
-	if (status & 0x01) {
+	if (status & NAND_STATUS_FAIL) {
 		pr_debug("%s: error status = 0x%08x\n",
 					__func__, status);
 		ret = -EIO;
@@ -1004,7 +1006,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 	/* Call wait ready function */
 	status = chip->waitfunc(mtd, chip);
 	/* See if device thinks it succeeded */
-	if (status & 0x01) {
+	if (status & NAND_STATUS_FAIL) {
 		pr_debug("%s: error status = 0x%08x\n",
 					__func__, status);
 		ret = -EIO;
@@ -3327,6 +3329,8 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 		return PTR_ERR(type);
 	}
 
+	chip->select_chip(mtd, -1);
+
 	/* Check for a chip array */
 	for (i = 1; i < maxchips; i++) {
 		chip->select_chip(mtd, i);
@@ -3336,8 +3340,11 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 		chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
 		/* Read manufacturer and device IDs */
 		if (nand_maf_id != chip->read_byte(mtd) ||
-		    nand_dev_id != chip->read_byte(mtd))
+		    nand_dev_id != chip->read_byte(mtd)) {
+			chip->select_chip(mtd, -1);
 			break;
+		}
+		chip->select_chip(mtd, -1);
 	}
 	if (i > 1)
 		pr_info("%d NAND chips detected\n", i);
@@ -3596,9 +3603,6 @@ int nand_scan_tail(struct mtd_info *mtd)
 	/* Initialize state */
 	chip->state = FL_READY;
 
-	/* De-select the device */
-	chip->select_chip(mtd, -1);
-
 	/* Invalidate the pagebuffer reference */
 	chip->pagebuf = -1;
 
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index a932c48..c3c13e6 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -1397,10 +1397,7 @@ int do_read_error(struct nandsim *ns, int num)
 	unsigned int page_no = ns->regs.row;
 
 	if (read_error(page_no)) {
-		int i;
-		memset(ns->buf.byte, 0xFF, num);
-		for (i = 0; i < num; ++i)
-			ns->buf.byte[i] = random32();
+		prandom_bytes(ns->buf.byte, num);
 		NS_WARN("simulating read error in page %u\n", page_no);
 		return 1;
 	}
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 5fd3f01..8e148f1 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -197,7 +197,7 @@ err:
 	return ret;
 }
 
-static int __devinit ndfc_probe(struct platform_device *ofdev)
+static int ndfc_probe(struct platform_device *ofdev)
 {
 	struct ndfc_controller *ndfc;
 	const __be32 *reg;
@@ -256,7 +256,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev)
 	return 0;
 }
 
-static int __devexit ndfc_remove(struct platform_device *ofdev)
+static int ndfc_remove(struct platform_device *ofdev)
 {
 	struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev);
 
@@ -279,7 +279,7 @@ static struct platform_driver ndfc_driver = {
 		.of_match_table = ndfc_match,
 	},
 	.probe = ndfc_probe,
-	.remove = __devexit_p(ndfc_remove),
+	.remove = ndfc_remove,
 };
 
 module_platform_driver(ndfc_driver);
diff --git a/drivers/mtd/nand/nomadik_nand.c b/drivers/mtd/nand/nomadik_nand.c
deleted file mode 100644
index 9ee0c4e..0000000
--- a/drivers/mtd/nand/nomadik_nand.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- *  drivers/mtd/nand/nomadik_nand.c
- *
- *  Overview:
- *  	Driver for on-board NAND flash on Nomadik Platforms
- *
- * Copyright © 2007 STMicroelectronics Pvt. Ltd.
- * Author: Sachin Verma <sachin.verma@st.com>
- *
- * Copyright © 2009 Alessandro Rubini
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/partitions.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/platform_data/mtd-nomadik-nand.h>
-#include <mach/fsmc.h>
-
-#include <mtd/mtd-abi.h>
-
-struct nomadik_nand_host {
-	struct mtd_info		mtd;
-	struct nand_chip	nand;
-	void __iomem *data_va;
-	void __iomem *cmd_va;
-	void __iomem *addr_va;
-	struct nand_bbt_descr *bbt_desc;
-};
-
-static struct nand_ecclayout nomadik_ecc_layout = {
-	.eccbytes = 3 * 4,
-	.eccpos = { /* each subpage has 16 bytes: pos 2,3,4 hosts ECC */
-		0x02, 0x03, 0x04,
-		0x12, 0x13, 0x14,
-		0x22, 0x23, 0x24,
-		0x32, 0x33, 0x34},
-	/* let's keep bytes 5,6,7 for us, just in case we change ECC algo */
-	.oobfree = { {0x08, 0x08}, {0x18, 0x08}, {0x28, 0x08}, {0x38, 0x08} },
-};
-
-static void nomadik_ecc_control(struct mtd_info *mtd, int mode)
-{
-	/* No need to enable hw ecc, it's on by default */
-}
-
-static void nomadik_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
-	struct nand_chip *nand = mtd->priv;
-	struct nomadik_nand_host *host = nand->priv;
-
-	if (cmd == NAND_CMD_NONE)
-		return;
-
-	if (ctrl & NAND_CLE)
-		writeb(cmd, host->cmd_va);
-	else
-		writeb(cmd, host->addr_va);
-}
-
-static int nomadik_nand_probe(struct platform_device *pdev)
-{
-	struct nomadik_nand_platform_data *pdata = pdev->dev.platform_data;
-	struct nomadik_nand_host *host;
-	struct mtd_info *mtd;
-	struct nand_chip *nand;
-	struct resource *res;
-	int ret = 0;
-
-	/* Allocate memory for the device structure (and zero it) */
-	host = kzalloc(sizeof(struct nomadik_nand_host), GFP_KERNEL);
-	if (!host) {
-		dev_err(&pdev->dev, "Failed to allocate device structure.\n");
-		return -ENOMEM;
-	}
-
-	/* Call the client's init function, if any */
-	if (pdata->init)
-		ret = pdata->init();
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Init function failed\n");
-		goto err;
-	}
-
-	/* ioremap three regions */
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_addr");
-	if (!res) {
-		ret = -EIO;
-		goto err_unmap;
-	}
-	host->addr_va = ioremap(res->start, resource_size(res));
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data");
-	if (!res) {
-		ret = -EIO;
-		goto err_unmap;
-	}
-	host->data_va = ioremap(res->start, resource_size(res));
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_cmd");
-	if (!res) {
-		ret = -EIO;
-		goto err_unmap;
-	}
-	host->cmd_va = ioremap(res->start, resource_size(res));
-
-	if (!host->addr_va || !host->data_va || !host->cmd_va) {
-		ret = -ENOMEM;
-		goto err_unmap;
-	}
-
-	/* Link all private pointers */
-	mtd = &host->mtd;
-	nand = &host->nand;
-	mtd->priv = nand;
-	nand->priv = host;
-
-	host->mtd.owner = THIS_MODULE;
-	nand->IO_ADDR_R = host->data_va;
-	nand->IO_ADDR_W = host->data_va;
-	nand->cmd_ctrl = nomadik_cmd_ctrl;
-
-	/*
-	 * This stanza declares ECC_HW but uses soft routines. It's because
-	 * HW claims to make the calculation but not the correction. However,
-	 * I haven't managed to get the desired data out of it until now.
-	 */
-	nand->ecc.mode = NAND_ECC_SOFT;
-	nand->ecc.layout = &nomadik_ecc_layout;
-	nand->ecc.hwctl = nomadik_ecc_control;
-	nand->ecc.size = 512;
-	nand->ecc.bytes = 3;
-
-	nand->options = pdata->options;
-
-	/*
-	 * Scan to find existence of the device
-	 */
-	if (nand_scan(&host->mtd, 1)) {
-		ret = -ENXIO;
-		goto err_unmap;
-	}
-
-	mtd_device_register(&host->mtd, pdata->parts, pdata->nparts);
-
-	platform_set_drvdata(pdev, host);
-	return 0;
-
- err_unmap:
-	if (host->cmd_va)
-		iounmap(host->cmd_va);
-	if (host->data_va)
-		iounmap(host->data_va);
-	if (host->addr_va)
-		iounmap(host->addr_va);
- err:
-	kfree(host);
-	return ret;
-}
-
-/*
- * Clean up routine
- */
-static int nomadik_nand_remove(struct platform_device *pdev)
-{
-	struct nomadik_nand_host *host = platform_get_drvdata(pdev);
-	struct nomadik_nand_platform_data *pdata = pdev->dev.platform_data;
-
-	if (pdata->exit)
-		pdata->exit();
-
-	if (host) {
-		nand_release(&host->mtd);
-		iounmap(host->cmd_va);
-		iounmap(host->data_va);
-		iounmap(host->addr_va);
-		kfree(host);
-	}
-	return 0;
-}
-
-static int nomadik_nand_suspend(struct device *dev)
-{
-	struct nomadik_nand_host *host = dev_get_drvdata(dev);
-	int ret = 0;
-	if (host)
-		ret = mtd_suspend(&host->mtd);
-	return ret;
-}
-
-static int nomadik_nand_resume(struct device *dev)
-{
-	struct nomadik_nand_host *host = dev_get_drvdata(dev);
-	if (host)
-		mtd_resume(&host->mtd);
-	return 0;
-}
-
-static const struct dev_pm_ops nomadik_nand_pm_ops = {
-	.suspend = nomadik_nand_suspend,
-	.resume = nomadik_nand_resume,
-};
-
-static struct platform_driver nomadik_nand_driver = {
-	.probe = nomadik_nand_probe,
-	.remove = nomadik_nand_remove,
-	.driver = {
-		.owner = THIS_MODULE,
-		.name = "nomadik_nand",
-		.pm = &nomadik_nand_pm_ops,
-	},
-};
-
-module_platform_driver(nomadik_nand_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("ST Microelectronics (sachin.verma@st.com)");
-MODULE_DESCRIPTION("NAND driver for Nomadik Platform");
diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c
index 94dc46b..a619119 100644
--- a/drivers/mtd/nand/nuc900_nand.c
+++ b/drivers/mtd/nand/nuc900_nand.c
@@ -246,7 +246,7 @@ static void nuc900_nand_enable(struct nuc900_nand *nand)
 	spin_unlock(&nand->lock);
 }
 
-static int __devinit nuc900_nand_probe(struct platform_device *pdev)
+static int nuc900_nand_probe(struct platform_device *pdev)
 {
 	struct nuc900_nand *nuc900_nand;
 	struct nand_chip *chip;
@@ -317,7 +317,7 @@ fail1:	kfree(nuc900_nand);
 	return retval;
 }
 
-static int __devexit nuc900_nand_remove(struct platform_device *pdev)
+static int nuc900_nand_remove(struct platform_device *pdev)
 {
 	struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -340,7 +340,7 @@ static int __devexit nuc900_nand_remove(struct platform_device *pdev)
 
 static struct platform_driver nuc900_nand_driver = {
 	.probe		= nuc900_nand_probe,
-	.remove		= __devexit_p(nuc900_nand_remove),
+	.remove		= nuc900_nand_remove,
 	.driver		= {
 		.name	= "nuc900-fmi",
 		.owner	= THIS_MODULE,
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 5b31386..359293e 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -27,8 +27,7 @@
 #include <linux/bch.h>
 #endif
 
-#include <plat/dma.h>
-#include <plat/gpmc.h>
+#include <plat-omap/dma-omap.h>
 #include <linux/platform_data/mtd-nand-omap2.h>
 
 #define	DRIVER_NAME	"omap2-nand"
@@ -106,10 +105,18 @@
 #define	CS_MASK				0x7
 #define	ENABLE_PREFETCH			(0x1 << 7)
 #define	DMA_MPU_MODE_SHIFT		2
+#define	ECCSIZE0_SHIFT			12
 #define	ECCSIZE1_SHIFT			22
 #define	ECC1RESULTSIZE			0x1
 #define	ECCCLEAR			0x100
 #define	ECC1				0x1
+#define	PREFETCH_FIFOTHRESHOLD_MAX	0x40
+#define	PREFETCH_FIFOTHRESHOLD(val)	((val) << 8)
+#define	PREFETCH_STATUS_COUNT(val)	(val & 0x00003fff)
+#define	PREFETCH_STATUS_FIFO_CNT(val)	((val >> 24) & 0x7F)
+#define	STATUS_BUFF_EMPTY		0x00000001
+
+#define OMAP24XX_DMA_GPMC		4
 
 /* oob info generated runtime depending on ecc algorithm and layout selected */
 static struct nand_ecclayout omap_oobinfo;
@@ -269,7 +276,7 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
 		/* wait until buffer is available for write */
 		do {
 			status = readl(info->reg.gpmc_status) &
-					GPMC_STATUS_BUFF_EMPTY;
+					STATUS_BUFF_EMPTY;
 		} while (!status);
 	}
 }
@@ -307,7 +314,7 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
 		/* wait until buffer is available for write */
 		do {
 			status = readl(info->reg.gpmc_status) &
-					GPMC_STATUS_BUFF_EMPTY;
+					STATUS_BUFF_EMPTY;
 		} while (!status);
 	}
 }
@@ -348,7 +355,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
 	} else {
 		do {
 			r_count = readl(info->reg.gpmc_prefetch_status);
-			r_count = GPMC_PREFETCH_STATUS_FIFO_CNT(r_count);
+			r_count = PREFETCH_STATUS_FIFO_CNT(r_count);
 			r_count = r_count >> 2;
 			ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
 			p += r_count;
@@ -395,7 +402,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 	} else {
 		while (len) {
 			w_count = readl(info->reg.gpmc_prefetch_status);
-			w_count = GPMC_PREFETCH_STATUS_FIFO_CNT(w_count);
+			w_count = PREFETCH_STATUS_FIFO_CNT(w_count);
 			w_count = w_count >> 1;
 			for (i = 0; (i < w_count) && len; i++, len -= 2)
 				iowrite16(*p++, info->nand.IO_ADDR_W);
@@ -407,7 +414,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 		do {
 			cpu_relax();
 			val = readl(info->reg.gpmc_prefetch_status);
-			val = GPMC_PREFETCH_STATUS_COUNT(val);
+			val = PREFETCH_STATUS_COUNT(val);
 		} while (val && (tim++ < limit));
 
 		/* disable and stop the PFPW engine */
@@ -493,7 +500,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 	do {
 		cpu_relax();
 		val = readl(info->reg.gpmc_prefetch_status);
-		val = GPMC_PREFETCH_STATUS_COUNT(val);
+		val = PREFETCH_STATUS_COUNT(val);
 	} while (val && (tim++ < limit));
 
 	/* disable and stop the PFPW engine */
@@ -556,7 +563,7 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 	u32 bytes;
 
 	bytes = readl(info->reg.gpmc_prefetch_status);
-	bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(bytes);
+	bytes = PREFETCH_STATUS_FIFO_CNT(bytes);
 	bytes = bytes  & 0xFFFC; /* io in multiple of 4 bytes */
 	if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
 		if (this_irq == info->gpmc_irq_count)
@@ -682,7 +689,7 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 	limit = (loops_per_jiffy *  msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
 	do {
 		val = readl(info->reg.gpmc_prefetch_status);
-		val = GPMC_PREFETCH_STATUS_COUNT(val);
+		val = PREFETCH_STATUS_COUNT(val);
 		cpu_relax();
 	} while (val && (tim++ < limit));
 
@@ -996,7 +1003,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
 		cond_resched();
 	}
 
-	status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA);
+	status = readb(info->reg.gpmc_nand_data);
 	return status;
 }
 
@@ -1029,19 +1036,45 @@ static int omap_dev_ready(struct mtd_info *mtd)
 static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode)
 {
 	int nerrors;
-	unsigned int dev_width;
+	unsigned int dev_width, nsectors;
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 						   mtd);
 	struct nand_chip *chip = mtd->priv;
+	u32 val;
 
 	nerrors = (info->nand.ecc.bytes == 13) ? 8 : 4;
 	dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
+	nsectors = 1;
 	/*
 	 * Program GPMC to perform correction on one 512-byte sector at a time.
 	 * Using 4 sectors at a time (i.e. ecc.size = 2048) is also possible and
 	 * gives a slight (5%) performance gain (but requires additional code).
 	 */
-	(void)gpmc_enable_hwecc_bch(info->gpmc_cs, mode, dev_width, 1, nerrors);
+
+	writel(ECC1, info->reg.gpmc_ecc_control);
+
+	/*
+	 * When using BCH, sector size is hardcoded to 512 bytes.
+	 * Here we are using wrapping mode 6 both for reading and writing, with:
+	 *  size0 = 0  (no additional protected byte in spare area)
+	 *  size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
+	 */
+	val = (32 << ECCSIZE1_SHIFT) | (0 << ECCSIZE0_SHIFT);
+	writel(val, info->reg.gpmc_ecc_size_config);
+
+	/* BCH configuration */
+	val = ((1                        << 16) | /* enable BCH */
+	       (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */
+	       (0x06                     <<  8) | /* wrap mode = 6 */
+	       (dev_width                <<  7) | /* bus width */
+	       (((nsectors-1) & 0x7)     <<  4) | /* number of sectors */
+	       (info->gpmc_cs            <<  1) | /* ECC CS */
+	       (0x1));                            /* enable ECC */
+
+	writel(val, info->reg.gpmc_ecc_config);
+
+	/* clear ecc and enable bits */
+	writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control);
 }
 
 /**
@@ -1055,7 +1088,32 @@ static int omap3_calculate_ecc_bch4(struct mtd_info *mtd, const u_char *dat,
 {
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 						   mtd);
-	return gpmc_calculate_ecc_bch4(info->gpmc_cs, dat, ecc_code);
+	unsigned long nsectors, val1, val2;
+	int i;
+
+	nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
+
+	for (i = 0; i < nsectors; i++) {
+
+		/* Read hw-computed remainder */
+		val1 = readl(info->reg.gpmc_bch_result0[i]);
+		val2 = readl(info->reg.gpmc_bch_result1[i]);
+
+		/*
+		 * Add constant polynomial to remainder, in order to get an ecc
+		 * sequence of 0xFFs for a buffer filled with 0xFFs; and
+		 * left-justify the resulting polynomial.
+		 */
+		*ecc_code++ = 0x28 ^ ((val2 >> 12) & 0xFF);
+		*ecc_code++ = 0x13 ^ ((val2 >>  4) & 0xFF);
+		*ecc_code++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF));
+		*ecc_code++ = 0x39 ^ ((val1 >> 20) & 0xFF);
+		*ecc_code++ = 0x96 ^ ((val1 >> 12) & 0xFF);
+		*ecc_code++ = 0xac ^ ((val1 >> 4) & 0xFF);
+		*ecc_code++ = 0x7f ^ ((val1 & 0xF) << 4);
+	}
+
+	return 0;
 }
 
 /**
@@ -1069,7 +1127,39 @@ static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat,
 {
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 						   mtd);
-	return gpmc_calculate_ecc_bch8(info->gpmc_cs, dat, ecc_code);
+	unsigned long nsectors, val1, val2, val3, val4;
+	int i;
+
+	nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
+
+	for (i = 0; i < nsectors; i++) {
+
+		/* Read hw-computed remainder */
+		val1 = readl(info->reg.gpmc_bch_result0[i]);
+		val2 = readl(info->reg.gpmc_bch_result1[i]);
+		val3 = readl(info->reg.gpmc_bch_result2[i]);
+		val4 = readl(info->reg.gpmc_bch_result3[i]);
+
+		/*
+		 * Add constant polynomial to remainder, in order to get an ecc
+		 * sequence of 0xFFs for a buffer filled with 0xFFs.
+		 */
+		*ecc_code++ = 0xef ^ (val4 & 0xFF);
+		*ecc_code++ = 0x51 ^ ((val3 >> 24) & 0xFF);
+		*ecc_code++ = 0x2e ^ ((val3 >> 16) & 0xFF);
+		*ecc_code++ = 0x09 ^ ((val3 >> 8) & 0xFF);
+		*ecc_code++ = 0xed ^ (val3 & 0xFF);
+		*ecc_code++ = 0x93 ^ ((val2 >> 24) & 0xFF);
+		*ecc_code++ = 0x9a ^ ((val2 >> 16) & 0xFF);
+		*ecc_code++ = 0xc2 ^ ((val2 >> 8) & 0xFF);
+		*ecc_code++ = 0x97 ^ (val2 & 0xFF);
+		*ecc_code++ = 0x79 ^ ((val1 >> 24) & 0xFF);
+		*ecc_code++ = 0xe5 ^ ((val1 >> 16) & 0xFF);
+		*ecc_code++ = 0x24 ^ ((val1 >> 8) & 0xFF);
+		*ecc_code++ = 0xb5 ^ (val1 & 0xFF);
+	}
+
+	return 0;
 }
 
 /**
@@ -1125,7 +1215,7 @@ static void omap3_free_bch(struct mtd_info *mtd)
  */
 static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
 {
-	int ret, max_errors;
+	int max_errors;
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 						   mtd);
 #ifdef CONFIG_MTD_NAND_OMAP_BCH8
@@ -1142,11 +1232,6 @@ static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
 		goto fail;
 	}
 
-	/* initialize GPMC BCH engine */
-	ret = gpmc_init_hwecc_bch(info->gpmc_cs, 1, max_errors);
-	if (ret)
-		goto fail;
-
 	/* software bch library is only used to detect and locate errors */
 	info->bch = init_bch(13, max_errors, 0x201b /* hw polynomial */);
 	if (!info->bch)
@@ -1239,7 +1324,7 @@ static void omap3_free_bch(struct mtd_info *mtd)
 }
 #endif /* CONFIG_MTD_NAND_OMAP_BCH */
 
-static int __devinit omap_nand_probe(struct platform_device *pdev)
+static int omap_nand_probe(struct platform_device *pdev)
 {
 	struct omap_nand_info		*info;
 	struct omap_nand_platform_data	*pdata;
@@ -1513,7 +1598,7 @@ static int omap_nand_remove(struct platform_device *pdev)
 	/* Release NAND device, its internal structures and partitions */
 	nand_release(&info->mtd);
 	iounmap(info->nand.IO_ADDR_R);
-	release_mem_region(info->phys_base, NAND_IO_SIZE);
+	release_mem_region(info->phys_base, info->mem_size);
 	kfree(info);
 	return 0;
 }
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index aefaf8c..cd72b92 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -194,7 +194,7 @@ no_res:
 	return ret;
 }
 
-static int __devexit orion_nand_remove(struct platform_device *pdev)
+static int orion_nand_remove(struct platform_device *pdev)
 {
 	struct mtd_info *mtd = platform_get_drvdata(pdev);
 	struct nand_chip *nc = mtd->priv;
@@ -223,7 +223,7 @@ static struct of_device_id orion_nand_of_match_table[] = {
 #endif
 
 static struct platform_driver orion_nand_driver = {
-	.remove		= __devexit_p(orion_nand_remove),
+	.remove		= orion_nand_remove,
 	.driver		= {
 		.name	= "orion_nand",
 		.owner	= THIS_MODULE,
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c
index 1440e51..5a67082 100644
--- a/drivers/mtd/nand/pasemi_nand.c
+++ b/drivers/mtd/nand/pasemi_nand.c
@@ -89,7 +89,7 @@ int pasemi_device_ready(struct mtd_info *mtd)
 	return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR);
 }
 
-static int __devinit pasemi_nand_probe(struct platform_device *ofdev)
+static int pasemi_nand_probe(struct platform_device *ofdev)
 {
 	struct pci_dev *pdev;
 	struct device_node *np = ofdev->dev.of_node;
@@ -184,7 +184,7 @@ static int __devinit pasemi_nand_probe(struct platform_device *ofdev)
 	return err;
 }
 
-static int __devexit pasemi_nand_remove(struct platform_device *ofdev)
+static int pasemi_nand_remove(struct platform_device *ofdev)
 {
 	struct nand_chip *chip;
 
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
index a47ee68..c004566 100644
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/plat_nand.c
@@ -28,7 +28,7 @@ static const char *part_probe_types[] = { "cmdlinepart", NULL };
 /*
  * Probe for the NAND device.
  */
-static int __devinit plat_nand_probe(struct platform_device *pdev)
+static int plat_nand_probe(struct platform_device *pdev)
 {
 	struct platform_nand_data *pdata = pdev->dev.platform_data;
 	struct mtd_part_parser_data ppdata;
@@ -134,7 +134,7 @@ out_free:
 /*
  * Remove a NAND device.
  */
-static int __devexit plat_nand_remove(struct platform_device *pdev)
+static int plat_nand_remove(struct platform_device *pdev)
 {
 	struct plat_nand_data *data = platform_get_drvdata(pdev);
 	struct platform_nand_data *pdata = pdev->dev.platform_data;
@@ -160,7 +160,7 @@ MODULE_DEVICE_TABLE(of, plat_nand_match);
 
 static struct platform_driver plat_nand_driver = {
 	.probe	= plat_nand_probe,
-	.remove	= __devexit_p(plat_nand_remove),
+	.remove	= plat_nand_remove,
 	.driver	= {
 		.name		= "gen_nand",
 		.owner		= THIS_MODULE,
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 295e4be..df954b4 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -730,11 +730,14 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
 				      struct s3c2410_nand_mtd *mtd,
 				      struct s3c2410_nand_set *set)
 {
-	if (set)
+	if (set) {
 		mtd->mtd.name = set->name;
 
-	return mtd_device_parse_register(&mtd->mtd, NULL, NULL,
+		return mtd_device_parse_register(&mtd->mtd, NULL, NULL,
 					 set->partitions, set->nr_partitions);
+	}
+
+	return -ENODEV;
 }
 
 /**
@@ -879,7 +882,7 @@ static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
 	if (chip->ecc.mode != NAND_ECC_HW)
 		return;
 
-		/* change the behaviour depending on wether we are using
+		/* change the behaviour depending on whether we are using
 		 * the large or small page nand device */
 
 	if (chip->page_shift > 10) {
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index 4fbfe96..57b3971 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -23,11 +23,18 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/completion.h>
 #include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_mtd.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/sh_dma.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 
@@ -106,6 +113,84 @@ static void wait_completion(struct sh_flctl *flctl)
 	writeb(0x0, FLTRCR(flctl));
 }
 
+static void flctl_dma_complete(void *param)
+{
+	struct sh_flctl *flctl = param;
+
+	complete(&flctl->dma_complete);
+}
+
+static void flctl_release_dma(struct sh_flctl *flctl)
+{
+	if (flctl->chan_fifo0_rx) {
+		dma_release_channel(flctl->chan_fifo0_rx);
+		flctl->chan_fifo0_rx = NULL;
+	}
+	if (flctl->chan_fifo0_tx) {
+		dma_release_channel(flctl->chan_fifo0_tx);
+		flctl->chan_fifo0_tx = NULL;
+	}
+}
+
+static void flctl_setup_dma(struct sh_flctl *flctl)
+{
+	dma_cap_mask_t mask;
+	struct dma_slave_config cfg;
+	struct platform_device *pdev = flctl->pdev;
+	struct sh_flctl_platform_data *pdata = pdev->dev.platform_data;
+	int ret;
+
+	if (!pdata)
+		return;
+
+	if (pdata->slave_id_fifo0_tx <= 0 || pdata->slave_id_fifo0_rx <= 0)
+		return;
+
+	/* We can only either use DMA for both Tx and Rx or not use it at all */
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	flctl->chan_fifo0_tx = dma_request_channel(mask, shdma_chan_filter,
+					    (void *)pdata->slave_id_fifo0_tx);
+	dev_dbg(&pdev->dev, "%s: TX: got channel %p\n", __func__,
+		flctl->chan_fifo0_tx);
+
+	if (!flctl->chan_fifo0_tx)
+		return;
+
+	memset(&cfg, 0, sizeof(cfg));
+	cfg.slave_id = pdata->slave_id_fifo0_tx;
+	cfg.direction = DMA_MEM_TO_DEV;
+	cfg.dst_addr = (dma_addr_t)FLDTFIFO(flctl);
+	cfg.src_addr = 0;
+	ret = dmaengine_slave_config(flctl->chan_fifo0_tx, &cfg);
+	if (ret < 0)
+		goto err;
+
+	flctl->chan_fifo0_rx = dma_request_channel(mask, shdma_chan_filter,
+					    (void *)pdata->slave_id_fifo0_rx);
+	dev_dbg(&pdev->dev, "%s: RX: got channel %p\n", __func__,
+		flctl->chan_fifo0_rx);
+
+	if (!flctl->chan_fifo0_rx)
+		goto err;
+
+	cfg.slave_id = pdata->slave_id_fifo0_rx;
+	cfg.direction = DMA_DEV_TO_MEM;
+	cfg.dst_addr = 0;
+	cfg.src_addr = (dma_addr_t)FLDTFIFO(flctl);
+	ret = dmaengine_slave_config(flctl->chan_fifo0_rx, &cfg);
+	if (ret < 0)
+		goto err;
+
+	init_completion(&flctl->dma_complete);
+
+	return;
+
+err:
+	flctl_release_dma(flctl);
+}
+
 static void set_addr(struct mtd_info *mtd, int column, int page_addr)
 {
 	struct sh_flctl *flctl = mtd_to_flctl(mtd);
@@ -225,7 +310,7 @@ static enum flctl_ecc_res_t wait_recfifo_ready
 
 		for (i = 0; i < 3; i++) {
 			uint8_t org;
-			int index;
+			unsigned int index;
 
 			data = readl(ecc_reg[i]);
 
@@ -261,6 +346,70 @@ static void wait_wecfifo_ready(struct sh_flctl *flctl)
 	timeout_error(flctl, __func__);
 }
 
+static int flctl_dma_fifo0_transfer(struct sh_flctl *flctl, unsigned long *buf,
+					int len, enum dma_data_direction dir)
+{
+	struct dma_async_tx_descriptor *desc = NULL;
+	struct dma_chan *chan;
+	enum dma_transfer_direction tr_dir;
+	dma_addr_t dma_addr;
+	dma_cookie_t cookie = -EINVAL;
+	uint32_t reg;
+	int ret;
+
+	if (dir == DMA_FROM_DEVICE) {
+		chan = flctl->chan_fifo0_rx;
+		tr_dir = DMA_DEV_TO_MEM;
+	} else {
+		chan = flctl->chan_fifo0_tx;
+		tr_dir = DMA_MEM_TO_DEV;
+	}
+
+	dma_addr = dma_map_single(chan->device->dev, buf, len, dir);
+
+	if (dma_addr)
+		desc = dmaengine_prep_slave_single(chan, dma_addr, len,
+			tr_dir, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+	if (desc) {
+		reg = readl(FLINTDMACR(flctl));
+		reg |= DREQ0EN;
+		writel(reg, FLINTDMACR(flctl));
+
+		desc->callback = flctl_dma_complete;
+		desc->callback_param = flctl;
+		cookie = dmaengine_submit(desc);
+
+		dma_async_issue_pending(chan);
+	} else {
+		/* DMA failed, fall back to PIO */
+		flctl_release_dma(flctl);
+		dev_warn(&flctl->pdev->dev,
+			 "DMA failed, falling back to PIO\n");
+		ret = -EIO;
+		goto out;
+	}
+
+	ret =
+	wait_for_completion_timeout(&flctl->dma_complete,
+				msecs_to_jiffies(3000));
+
+	if (ret <= 0) {
+		chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
+		dev_err(&flctl->pdev->dev, "wait_for_completion_timeout\n");
+	}
+
+out:
+	reg = readl(FLINTDMACR(flctl));
+	reg &= ~DREQ0EN;
+	writel(reg, FLINTDMACR(flctl));
+
+	dma_unmap_single(chan->device->dev, dma_addr, len, dir);
+
+	/* ret > 0 is success */
+	return ret;
+}
+
 static void read_datareg(struct sh_flctl *flctl, int offset)
 {
 	unsigned long data;
@@ -279,11 +428,20 @@ static void read_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
 
 	len_4align = (rlen + 3) / 4;
 
+	/* initiate DMA transfer */
+	if (flctl->chan_fifo0_rx && rlen >= 32 &&
+		flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_DEV_TO_MEM) > 0)
+			goto convert;	/* DMA success */
+
+	/* do polling transfer */
 	for (i = 0; i < len_4align; i++) {
 		wait_rfifo_ready(flctl);
 		buf[i] = readl(FLDTFIFO(flctl));
-		buf[i] = be32_to_cpu(buf[i]);
 	}
+
+convert:
+	for (i = 0; i < len_4align; i++)
+		buf[i] = be32_to_cpu(buf[i]);
 }
 
 static enum flctl_ecc_res_t read_ecfiforeg
@@ -305,28 +463,39 @@ static enum flctl_ecc_res_t read_ecfiforeg
 	return res;
 }
 
-static void write_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
+static void write_fiforeg(struct sh_flctl *flctl, int rlen,
+						unsigned int offset)
 {
 	int i, len_4align;
-	unsigned long *data = (unsigned long *)&flctl->done_buff[offset];
-	void *fifo_addr = (void *)FLDTFIFO(flctl);
+	unsigned long *buf = (unsigned long *)&flctl->done_buff[offset];
 
 	len_4align = (rlen + 3) / 4;
 	for (i = 0; i < len_4align; i++) {
 		wait_wfifo_ready(flctl);
-		writel(cpu_to_be32(data[i]), fifo_addr);
+		writel(cpu_to_be32(buf[i]), FLDTFIFO(flctl));
 	}
 }
 
-static void write_ec_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
+static void write_ec_fiforeg(struct sh_flctl *flctl, int rlen,
+						unsigned int offset)
 {
 	int i, len_4align;
-	unsigned long *data = (unsigned long *)&flctl->done_buff[offset];
+	unsigned long *buf = (unsigned long *)&flctl->done_buff[offset];
 
 	len_4align = (rlen + 3) / 4;
+
+	for (i = 0; i < len_4align; i++)
+		buf[i] = cpu_to_be32(buf[i]);
+
+	/* initiate DMA transfer */
+	if (flctl->chan_fifo0_tx && rlen >= 32 &&
+		flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_MEM_TO_DEV) > 0)
+			return;	/* DMA success */
+
+	/* do polling transfer */
 	for (i = 0; i < len_4align; i++) {
 		wait_wecfifo_ready(flctl);
-		writel(cpu_to_be32(data[i]), FLECFIFO(flctl));
+		writel(buf[i], FLECFIFO(flctl));
 	}
 }
 
@@ -727,7 +896,9 @@ static void flctl_select_chip(struct mtd_info *mtd, int chipnr)
 
 		if (!flctl->qos_request) {
 			ret = dev_pm_qos_add_request(&flctl->pdev->dev,
-							&flctl->pm_qos, 100);
+							&flctl->pm_qos,
+							DEV_PM_QOS_LATENCY,
+							100);
 			if (ret < 0)
 				dev_err(&flctl->pdev->dev,
 					"PM QoS request failed: %d\n", ret);
@@ -748,41 +919,35 @@ static void flctl_select_chip(struct mtd_info *mtd, int chipnr)
 static void flctl_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
 	struct sh_flctl *flctl = mtd_to_flctl(mtd);
-	int index = flctl->index;
 
-	memcpy(&flctl->done_buff[index], buf, len);
+	memcpy(&flctl->done_buff[flctl->index], buf, len);
 	flctl->index += len;
 }
 
 static uint8_t flctl_read_byte(struct mtd_info *mtd)
 {
 	struct sh_flctl *flctl = mtd_to_flctl(mtd);
-	int index = flctl->index;
 	uint8_t data;
 
-	data = flctl->done_buff[index];
+	data = flctl->done_buff[flctl->index];
 	flctl->index++;
 	return data;
 }
 
 static uint16_t flctl_read_word(struct mtd_info *mtd)
 {
-       struct sh_flctl *flctl = mtd_to_flctl(mtd);
-       int index = flctl->index;
-       uint16_t data;
-       uint16_t *buf = (uint16_t *)&flctl->done_buff[index];
+	struct sh_flctl *flctl = mtd_to_flctl(mtd);
+	uint16_t *buf = (uint16_t *)&flctl->done_buff[flctl->index];
 
-       data = *buf;
-       flctl->index += 2;
-       return data;
+	flctl->index += 2;
+	return *buf;
 }
 
 static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
 	struct sh_flctl *flctl = mtd_to_flctl(mtd);
-	int index = flctl->index;
 
-	memcpy(buf, &flctl->done_buff[index], len);
+	memcpy(buf, &flctl->done_buff[flctl->index], len);
 	flctl->index += len;
 }
 
@@ -856,7 +1021,74 @@ static irqreturn_t flctl_handle_flste(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit flctl_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+struct flctl_soc_config {
+	unsigned long flcmncr_val;
+	unsigned has_hwecc:1;
+	unsigned use_holden:1;
+};
+
+static struct flctl_soc_config flctl_sh7372_config = {
+	.flcmncr_val = CLK_16B_12L_4H | TYPESEL_SET | SHBUSSEL,
+	.has_hwecc = 1,
+	.use_holden = 1,
+};
+
+static const struct of_device_id of_flctl_match[] = {
+	{ .compatible = "renesas,shmobile-flctl-sh7372",
+				.data = &flctl_sh7372_config },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_flctl_match);
+
+static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
+{
+	const struct of_device_id *match;
+	struct flctl_soc_config *config;
+	struct sh_flctl_platform_data *pdata;
+	struct device_node *dn = dev->of_node;
+	int ret;
+
+	match = of_match_device(of_flctl_match, dev);
+	if (match)
+		config = (struct flctl_soc_config *)match->data;
+	else {
+		dev_err(dev, "%s: no OF configuration attached\n", __func__);
+		return NULL;
+	}
+
+	pdata = devm_kzalloc(dev, sizeof(struct sh_flctl_platform_data),
+								GFP_KERNEL);
+	if (!pdata) {
+		dev_err(dev, "%s: failed to allocate config data\n", __func__);
+		return NULL;
+	}
+
+	/* set SoC specific options */
+	pdata->flcmncr_val = config->flcmncr_val;
+	pdata->has_hwecc = config->has_hwecc;
+	pdata->use_holden = config->use_holden;
+
+	/* parse user defined options */
+	ret = of_get_nand_bus_width(dn);
+	if (ret == 16)
+		pdata->flcmncr_val |= SEL_16BIT;
+	else if (ret != 8) {
+		dev_err(dev, "%s: invalid bus width\n", __func__);
+		return NULL;
+	}
+
+	return pdata;
+}
+#else /* CONFIG_OF */
+#define of_flctl_match NULL
+static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
+{
+	return NULL;
+}
+#endif /* CONFIG_OF */
+
+static int flctl_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	struct sh_flctl *flctl;
@@ -865,12 +1097,7 @@ static int __devinit flctl_probe(struct platform_device *pdev)
 	struct sh_flctl_platform_data *pdata;
 	int ret = -ENXIO;
 	int irq;
-
-	pdata = pdev->dev.platform_data;
-	if (pdata == NULL) {
-		dev_err(&pdev->dev, "no platform data defined\n");
-		return -EINVAL;
-	}
+	struct mtd_part_parser_data ppdata = {};
 
 	flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL);
 	if (!flctl) {
@@ -902,6 +1129,17 @@ static int __devinit flctl_probe(struct platform_device *pdev)
 		goto err_flste;
 	}
 
+	if (pdev->dev.of_node)
+		pdata = flctl_parse_dt(&pdev->dev);
+	else
+		pdata = pdev->dev.platform_data;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "no setup data defined\n");
+		ret = -EINVAL;
+		goto err_pdata;
+	}
+
 	platform_set_drvdata(pdev, flctl);
 	flctl_mtd = &flctl->mtd;
 	nand = &flctl->chip;
@@ -930,6 +1168,8 @@ static int __devinit flctl_probe(struct platform_device *pdev)
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_resume(&pdev->dev);
 
+	flctl_setup_dma(flctl);
+
 	ret = nand_scan_ident(flctl_mtd, 1, NULL);
 	if (ret)
 		goto err_chip;
@@ -942,12 +1182,16 @@ static int __devinit flctl_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_chip;
 
-	mtd_device_register(flctl_mtd, pdata->parts, pdata->nr_parts);
+	ppdata.of_node = pdev->dev.of_node;
+	ret = mtd_device_parse_register(flctl_mtd, NULL, &ppdata, pdata->parts,
+			pdata->nr_parts);
 
 	return 0;
 
 err_chip:
+	flctl_release_dma(flctl);
 	pm_runtime_disable(&pdev->dev);
+err_pdata:
 	free_irq(irq, flctl);
 err_flste:
 	iounmap(flctl->reg);
@@ -956,10 +1200,11 @@ err_iomap:
 	return ret;
 }
 
-static int __devexit flctl_remove(struct platform_device *pdev)
+static int flctl_remove(struct platform_device *pdev)
 {
 	struct sh_flctl *flctl = platform_get_drvdata(pdev);
 
+	flctl_release_dma(flctl);
 	nand_release(&flctl->mtd);
 	pm_runtime_disable(&pdev->dev);
 	free_irq(platform_get_irq(pdev, 0), flctl);
@@ -974,6 +1219,7 @@ static struct platform_driver flctl_driver = {
 	.driver = {
 		.name	= "sh_flctl",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_flctl_match,
 	},
 };
 
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 3421e37..127bc42 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -106,7 +106,7 @@ static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat,
 /*
  * Main initialization routine
  */
-static int __devinit sharpsl_nand_probe(struct platform_device *pdev)
+static int sharpsl_nand_probe(struct platform_device *pdev)
 {
 	struct nand_chip *this;
 	struct resource *r;
@@ -205,7 +205,7 @@ err_get_res:
 /*
  * Clean up routine
  */
-static int __devexit sharpsl_nand_remove(struct platform_device *pdev)
+static int sharpsl_nand_remove(struct platform_device *pdev)
 {
 	struct sharpsl_nand *sharpsl = platform_get_drvdata(pdev);
 
@@ -228,7 +228,7 @@ static struct platform_driver sharpsl_nand_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= sharpsl_nand_probe,
-	.remove		= __devexit_p(sharpsl_nand_remove),
+	.remove		= sharpsl_nand_remove,
 };
 
 module_platform_driver(sharpsl_nand_driver);
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index f3f28fa..09dde7d 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -140,7 +140,7 @@ static int socrates_nand_device_ready(struct mtd_info *mtd)
 /*
  * Probe for the NAND device.
  */
-static int __devinit socrates_nand_probe(struct platform_device *ofdev)
+static int socrates_nand_probe(struct platform_device *ofdev)
 {
 	struct socrates_nand_host *host;
 	struct mtd_info *mtd;
@@ -220,7 +220,7 @@ out:
 /*
  * Remove a NAND device.
  */
-static int __devexit socrates_nand_remove(struct platform_device *ofdev)
+static int socrates_nand_remove(struct platform_device *ofdev)
 {
 	struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev);
 	struct mtd_info *mtd = &host->mtd;
@@ -251,7 +251,7 @@ static struct platform_driver socrates_nand_driver = {
 		.of_match_table = socrates_nand_match,
 	},
 	.probe		= socrates_nand_probe,
-	.remove		= __devexit_p(socrates_nand_remove),
+	.remove		= socrates_nand_remove,
 };
 
 module_platform_driver(socrates_nand_driver);
diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c
deleted file mode 100644
index bef76cd..0000000
--- a/drivers/mtd/nand/spia.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- *  drivers/mtd/nand/spia.c
- *
- *  Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
- *
- *
- *	10-29-2001 TG	change to support hardwarespecific access
- *			to controllines	(due to change in nand.c)
- *			page_cache added
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  Overview:
- *   This is a device driver for the NAND flash device found on the
- *   SPIA board which utilizes the Toshiba TC58V64AFT part. This is
- *   a 64Mibit (8MiB x 8 bits) NAND flash device.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-
-/*
- * MTD structure for SPIA board
- */
-static struct mtd_info *spia_mtd = NULL;
-
-/*
- * Values specific to the SPIA board (used with EP7212 processor)
- */
-#define SPIA_IO_BASE	0xd0000000	/* Start of EP7212 IO address space */
-#define SPIA_FIO_BASE	0xf0000000	/* Address where flash is mapped */
-#define SPIA_PEDR	0x0080	/*
-				 * IO offset to Port E data register
-				 * where the CLE, ALE and NCE pins
-				 * are wired to.
-				 */
-#define SPIA_PEDDR	0x00c0	/*
-				 * IO offset to Port E data direction
-				 * register so we can control the IO
-				 * lines.
-				 */
-
-/*
- * Module stuff
- */
-
-static int spia_io_base = SPIA_IO_BASE;
-static int spia_fio_base = SPIA_FIO_BASE;
-static int spia_pedr = SPIA_PEDR;
-static int spia_peddr = SPIA_PEDDR;
-
-module_param(spia_io_base, int, 0);
-module_param(spia_fio_base, int, 0);
-module_param(spia_pedr, int, 0);
-module_param(spia_peddr, int, 0);
-
-/*
- * Define partitions for flash device
- */
-static const struct mtd_partition partition_info[] = {
-	{
-	 .name = "SPIA flash partition 1",
-	 .offset = 0,
-	 .size = 2 * 1024 * 1024},
-	{
-	 .name = "SPIA flash partition 2",
-	 .offset = 2 * 1024 * 1024,
-	 .size = 6 * 1024 * 1024}
-};
-
-#define NUM_PARTITIONS 2
-
-/*
- *	hardware specific access to control-lines
- *
- *	ctrl:
- *	NAND_CNE: bit 0 -> bit 2
- *	NAND_CLE: bit 1 -> bit 0
- *	NAND_ALE: bit 2 -> bit 1
- */
-static void spia_hwcontrol(struct mtd_info *mtd, int cmd)
-{
-	struct nand_chip *chip = mtd->priv;
-
-	if (ctrl & NAND_CTRL_CHANGE) {
-		void __iomem *addr = spia_io_base + spia_pedr;
-		unsigned char bits;
-
-		bits = (ctrl & NAND_CNE) << 2;
-		bits |= (ctrl & NAND_CLE | NAND_ALE) >> 1;
-		writeb((readb(addr) & ~0x7) | bits, addr);
-	}
-
-	if (cmd != NAND_CMD_NONE)
-		writeb(cmd, chip->IO_ADDR_W);
-}
-
-/*
- * Main initialization routine
- */
-static int __init spia_init(void)
-{
-	struct nand_chip *this;
-
-	/* Allocate memory for MTD device structure and private data */
-	spia_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
-	if (!spia_mtd) {
-		printk("Unable to allocate SPIA NAND MTD device structure.\n");
-		return -ENOMEM;
-	}
-
-	/* Get pointer to private data */
-	this = (struct nand_chip *)(&spia_mtd[1]);
-
-	/* Initialize structures */
-	memset(spia_mtd, 0, sizeof(struct mtd_info));
-	memset(this, 0, sizeof(struct nand_chip));
-
-	/* Link the private data with the MTD structure */
-	spia_mtd->priv = this;
-	spia_mtd->owner = THIS_MODULE;
-
-	/*
-	 * Set GPIO Port E control register so that the pins are configured
-	 * to be outputs for controlling the NAND flash.
-	 */
-	(*(volatile unsigned char *)(spia_io_base + spia_peddr)) = 0x07;
-
-	/* Set address of NAND IO lines */
-	this->IO_ADDR_R = (void __iomem *)spia_fio_base;
-	this->IO_ADDR_W = (void __iomem *)spia_fio_base;
-	/* Set address of hardware control function */
-	this->cmd_ctrl = spia_hwcontrol;
-	/* 15 us command delay time */
-	this->chip_delay = 15;
-
-	/* Scan to find existence of the device */
-	if (nand_scan(spia_mtd, 1)) {
-		kfree(spia_mtd);
-		return -ENXIO;
-	}
-
-	/* Register the partitions */
-	mtd_device_register(spia_mtd, partition_info, NUM_PARTITIONS);
-
-	/* Return happy */
-	return 0;
-}
-
-module_init(spia_init);
-
-/*
- * Clean up routine
- */
-static void __exit spia_cleanup(void)
-{
-	/* Release resources, unregister device */
-	nand_release(spia_mtd);
-
-	/* Free the MTD device structure */
-	kfree(spia_mtd);
-}
-
-module_exit(spia_cleanup);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com");
-MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on SPIA board");
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index d9127e2..dbd3aa5 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -71,7 +71,10 @@ static int parse_ofpart_partitions(struct mtd_info *master,
 		(*pparts)[i].name = (char *)partname;
 
 		if (of_get_property(pp, "read-only", &len))
-			(*pparts)[i].mask_flags = MTD_WRITEABLE;
+			(*pparts)[i].mask_flags |= MTD_WRITEABLE;
+
+		if (of_get_property(pp, "lock", &len))
+			(*pparts)[i].mask_flags |= MTD_POWERUP_LOCK;
 
 		i++;
 	}
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index 1c4f97c..9f11562 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -35,7 +35,7 @@ struct onenand_info {
 	struct onenand_chip	onenand;
 };
 
-static int __devinit generic_onenand_probe(struct platform_device *pdev)
+static int generic_onenand_probe(struct platform_device *pdev)
 {
 	struct onenand_info *info;
 	struct onenand_platform_data *pdata = pdev->dev.platform_data;
@@ -88,7 +88,7 @@ out_free_info:
 	return err;
 }
 
-static int __devexit generic_onenand_remove(struct platform_device *pdev)
+static int generic_onenand_remove(struct platform_device *pdev)
 {
 	struct onenand_info *info = platform_get_drvdata(pdev);
 	struct resource *res = pdev->resource;
@@ -112,7 +112,7 @@ static struct platform_driver generic_onenand_driver = {
 		.owner		= THIS_MODULE,
 	},
 	.probe		= generic_onenand_probe,
-	.remove		= __devexit_p(generic_onenand_remove),
+	.remove		= generic_onenand_remove,
 };
 
 module_platform_driver(generic_onenand_driver);
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 1961be9..5ca4dcd 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -38,12 +38,10 @@
 #include <linux/regulator/consumer.h>
 
 #include <asm/mach/flash.h>
-#include <plat/gpmc.h>
 #include <linux/platform_data/mtd-onenand-omap2.h>
 #include <asm/gpio.h>
 
-#include <plat/dma.h>
-#include <plat/cpu.h>
+#include <plat-omap/dma-omap.h>
 
 #define DRIVER_NAME "omap2-onenand"
 
@@ -63,6 +61,7 @@ struct omap2_onenand {
 	int freq;
 	int (*setup)(void __iomem *base, int *freq_ptr);
 	struct regulator *regulator;
+	u8 flags;
 };
 
 static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
@@ -155,7 +154,7 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state)
 		if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) {
 			syscfg |= ONENAND_SYS_CFG1_IOBE;
 			write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
-			if (cpu_is_omap34xx())
+			if (c->flags & ONENAND_IN_OMAP34XX)
 				/* Add a delay to let GPIO settle */
 				syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
 		}
@@ -446,13 +445,19 @@ out_copy:
 
 #else
 
-int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
-				 unsigned char *buffer, int offset,
-				 size_t count);
+static int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
+					unsigned char *buffer, int offset,
+					size_t count)
+{
+	return -ENOSYS;
+}
 
-int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
-				  const unsigned char *buffer,
-				  int offset, size_t count);
+static int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
+					 const unsigned char *buffer,
+					 int offset, size_t count)
+{
+	return -ENOSYS;
+}
 
 #endif
 
@@ -550,13 +555,19 @@ static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
 
 #else
 
-int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
-				 unsigned char *buffer, int offset,
-				 size_t count);
+static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
+					unsigned char *buffer, int offset,
+					size_t count)
+{
+	return -ENOSYS;
+}
 
-int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
-				  const unsigned char *buffer,
-				  int offset, size_t count);
+static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
+					 const unsigned char *buffer,
+					 int offset, size_t count)
+{
+	return -ENOSYS;
+}
 
 #endif
 
@@ -619,7 +630,7 @@ static int omap2_onenand_disable(struct mtd_info *mtd)
 	return ret;
 }
 
-static int __devinit omap2_onenand_probe(struct platform_device *pdev)
+static int omap2_onenand_probe(struct platform_device *pdev)
 {
 	struct omap_onenand_platform_data *pdata;
 	struct omap2_onenand *c;
@@ -639,6 +650,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 
 	init_completion(&c->irq_done);
 	init_completion(&c->dma_done);
+	c->flags = pdata->flags;
 	c->gpmc_cs = pdata->cs;
 	c->gpio_irq = pdata->gpio_irq;
 	c->dma_channel = pdata->dma_channel;
@@ -729,7 +741,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 	this = &c->onenand;
 	if (c->dma_channel >= 0) {
 		this->wait = omap2_onenand_wait;
-		if (cpu_is_omap34xx()) {
+		if (c->flags & ONENAND_IN_OMAP34XX) {
 			this->read_bufferram = omap3_onenand_read_bufferram;
 			this->write_bufferram = omap3_onenand_write_bufferram;
 		} else {
@@ -787,7 +799,7 @@ err_kfree:
 	return r;
 }
 
-static int __devexit omap2_onenand_remove(struct platform_device *pdev)
+static int omap2_onenand_remove(struct platform_device *pdev)
 {
 	struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
 
@@ -803,7 +815,6 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
 	}
 	iounmap(c->onenand.base);
 	release_mem_region(c->phys_base, c->mem_size);
-	gpmc_cs_free(c->gpmc_cs);
 	kfree(c);
 
 	return 0;
@@ -811,7 +822,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
 
 static struct platform_driver omap2_onenand_driver = {
 	.probe		= omap2_onenand_probe,
-	.remove		= __devexit_p(omap2_onenand_remove),
+	.remove		= omap2_onenand_remove,
 	.shutdown	= omap2_onenand_shutdown,
 	.driver		= {
 		.name	= DRIVER_NAME,
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index 8e4b3f2..33f2a8f 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -1053,7 +1053,7 @@ onenand_fail:
 	return err;
 }
 
-static int __devexit s3c_onenand_remove(struct platform_device *pdev)
+static int s3c_onenand_remove(struct platform_device *pdev)
 {
 	struct mtd_info *mtd = platform_get_drvdata(pdev);
 
@@ -1130,7 +1130,7 @@ static struct platform_driver s3c_onenand_driver = {
 	},
 	.id_table	= s3c_onenand_driver_ids,
 	.probe          = s3c_onenand_probe,
-	.remove         = __devexit_p(s3c_onenand_remove),
+	.remove         = s3c_onenand_remove,
 };
 
 module_platform_driver(s3c_onenand_driver);
diff --git a/drivers/mtd/tests/mtd_nandbiterrs.c b/drivers/mtd/tests/mtd_nandbiterrs.c
index cc8d62c..207bf9a 100644
--- a/drivers/mtd/tests/mtd_nandbiterrs.c
+++ b/drivers/mtd/tests/mtd_nandbiterrs.c
@@ -39,6 +39,9 @@
  * this program; see the file COPYING. If not, write to the Free Software
  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -47,8 +50,6 @@
 #include <linux/mtd/nand.h>
 #include <linux/slab.h>
 
-#define msg(FMT, VA...) pr_info("mtd_nandbiterrs: "FMT, ##VA)
-
 static int dev;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -103,7 +104,7 @@ static int erase_block(void)
 	struct erase_info ei;
 	loff_t addr = eraseblock * mtd->erasesize;
 
-	msg("erase_block\n");
+	pr_info("erase_block\n");
 
 	memset(&ei, 0, sizeof(struct erase_info));
 	ei.mtd  = mtd;
@@ -112,7 +113,7 @@ static int erase_block(void)
 
 	err = mtd_erase(mtd, &ei);
 	if (err || ei.state == MTD_ERASE_FAILED) {
-		msg("error %d while erasing\n", err);
+		pr_err("error %d while erasing\n", err);
 		if (!err)
 			err = -EIO;
 		return err;
@@ -128,11 +129,11 @@ static int write_page(int log)
 	size_t written;
 
 	if (log)
-		msg("write_page\n");
+		pr_info("write_page\n");
 
 	err = mtd_write(mtd, offset, mtd->writesize, &written, wbuffer);
 	if (err || written != mtd->writesize) {
-		msg("error: write failed at %#llx\n", (long long)offset);
+		pr_err("error: write failed at %#llx\n", (long long)offset);
 		if (!err)
 			err = -EIO;
 	}
@@ -147,7 +148,7 @@ static int rewrite_page(int log)
 	struct mtd_oob_ops ops;
 
 	if (log)
-		msg("rewrite page\n");
+		pr_info("rewrite page\n");
 
 	ops.mode      = MTD_OPS_RAW; /* No ECC */
 	ops.len       = mtd->writesize;
@@ -160,7 +161,7 @@ static int rewrite_page(int log)
 
 	err = mtd_write_oob(mtd, offset, &ops);
 	if (err || ops.retlen != mtd->writesize) {
-		msg("error: write_oob failed (%d)\n", err);
+		pr_err("error: write_oob failed (%d)\n", err);
 		if (!err)
 			err = -EIO;
 	}
@@ -177,7 +178,7 @@ static int read_page(int log)
 	struct mtd_ecc_stats oldstats;
 
 	if (log)
-		msg("read_page\n");
+		pr_info("read_page\n");
 
 	/* Saving last mtd stats */
 	memcpy(&oldstats, &mtd->ecc_stats, sizeof(oldstats));
@@ -187,7 +188,7 @@ static int read_page(int log)
 		err = mtd->ecc_stats.corrected - oldstats.corrected;
 
 	if (err < 0 || read != mtd->writesize) {
-		msg("error: read failed at %#llx\n", (long long)offset);
+		pr_err("error: read failed at %#llx\n", (long long)offset);
 		if (err >= 0)
 			err = -EIO;
 	}
@@ -201,11 +202,11 @@ static int verify_page(int log)
 	unsigned i, errs = 0;
 
 	if (log)
-		msg("verify_page\n");
+		pr_info("verify_page\n");
 
 	for (i = 0; i < mtd->writesize; i++) {
 		if (rbuffer[i] != hash(i+seed)) {
-			msg("Error: page offset %u, expected %02x, got %02x\n",
+			pr_err("Error: page offset %u, expected %02x, got %02x\n",
 				i, hash(i+seed), rbuffer[i]);
 			errs++;
 		}
@@ -230,13 +231,13 @@ static int insert_biterror(unsigned byte)
 		for (bit = 7; bit >= 0; bit--) {
 			if (CBIT(wbuffer[byte], bit)) {
 				BCLR(wbuffer[byte], bit);
-				msg("Inserted biterror @ %u/%u\n", byte, bit);
+				pr_info("Inserted biterror @ %u/%u\n", byte, bit);
 				return 0;
 			}
 		}
 		byte++;
 	}
-	msg("biterror: Failed to find a '1' bit\n");
+	pr_err("biterror: Failed to find a '1' bit\n");
 	return -EIO;
 }
 
@@ -248,7 +249,7 @@ static int incremental_errors_test(void)
 	unsigned i;
 	unsigned errs_per_subpage = 0;
 
-	msg("incremental biterrors test\n");
+	pr_info("incremental biterrors test\n");
 
 	for (i = 0; i < mtd->writesize; i++)
 		wbuffer[i] = hash(i+seed);
@@ -265,9 +266,9 @@ static int incremental_errors_test(void)
 
 		err = read_page(1);
 		if (err > 0)
-			msg("Read reported %d corrected bit errors\n", err);
+			pr_info("Read reported %d corrected bit errors\n", err);
 		if (err < 0) {
-			msg("After %d biterrors per subpage, read reported error %d\n",
+			pr_err("After %d biterrors per subpage, read reported error %d\n",
 				errs_per_subpage, err);
 			err = 0;
 			goto exit;
@@ -275,11 +276,11 @@ static int incremental_errors_test(void)
 
 		err = verify_page(1);
 		if (err) {
-			msg("ECC failure, read data is incorrect despite read success\n");
+			pr_err("ECC failure, read data is incorrect despite read success\n");
 			goto exit;
 		}
 
-		msg("Successfully corrected %d bit errors per subpage\n",
+		pr_info("Successfully corrected %d bit errors per subpage\n",
 			errs_per_subpage);
 
 		for (i = 0; i < subcount; i++) {
@@ -311,7 +312,7 @@ static int overwrite_test(void)
 
 	memset(bitstats, 0, sizeof(bitstats));
 
-	msg("overwrite biterrors test\n");
+	pr_info("overwrite biterrors test\n");
 
 	for (i = 0; i < mtd->writesize; i++)
 		wbuffer[i] = hash(i+seed);
@@ -329,18 +330,18 @@ static int overwrite_test(void)
 		err = read_page(0);
 		if (err >= 0) {
 			if (err >= MAXBITS) {
-				msg("Implausible number of bit errors corrected\n");
+				pr_info("Implausible number of bit errors corrected\n");
 				err = -EIO;
 				break;
 			}
 			bitstats[err]++;
 			if (err > max_corrected) {
 				max_corrected = err;
-				msg("Read reported %d corrected bit errors\n",
+				pr_info("Read reported %d corrected bit errors\n",
 					err);
 			}
 		} else { /* err < 0 */
-			msg("Read reported error %d\n", err);
+			pr_info("Read reported error %d\n", err);
 			err = 0;
 			break;
 		}
@@ -348,7 +349,7 @@ static int overwrite_test(void)
 		err = verify_page(0);
 		if (err) {
 			bitstats[max_corrected] = opno;
-			msg("ECC failure, read data is incorrect despite read success\n");
+			pr_info("ECC failure, read data is incorrect despite read success\n");
 			break;
 		}
 
@@ -357,9 +358,9 @@ static int overwrite_test(void)
 
 	/* At this point bitstats[0] contains the number of ops with no bit
 	 * errors, bitstats[1] the number of ops with 1 bit error, etc. */
-	msg("Bit error histogram (%d operations total):\n", opno);
+	pr_info("Bit error histogram (%d operations total):\n", opno);
 	for (i = 0; i < max_corrected; i++)
-		msg("Page reads with %3d corrected bit errors: %d\n",
+		pr_info("Page reads with %3d corrected bit errors: %d\n",
 			i, bitstats[i]);
 
 exit:
@@ -370,36 +371,36 @@ static int __init mtd_nandbiterrs_init(void)
 {
 	int err = 0;
 
-	msg("\n");
-	msg("==================================================\n");
-	msg("MTD device: %d\n", dev);
+	printk("\n");
+	printk(KERN_INFO "==================================================\n");
+	pr_info("MTD device: %d\n", dev);
 
 	mtd = get_mtd_device(NULL, dev);
 	if (IS_ERR(mtd)) {
 		err = PTR_ERR(mtd);
-		msg("error: cannot get MTD device\n");
+		pr_err("error: cannot get MTD device\n");
 		goto exit_mtddev;
 	}
 
 	if (mtd->type != MTD_NANDFLASH) {
-		msg("this test requires NAND flash\n");
+		pr_info("this test requires NAND flash\n");
 		err = -ENODEV;
 		goto exit_nand;
 	}
 
-	msg("MTD device size %llu, eraseblock=%u, page=%u, oob=%u\n",
+	pr_info("MTD device size %llu, eraseblock=%u, page=%u, oob=%u\n",
 		(unsigned long long)mtd->size, mtd->erasesize,
 		mtd->writesize, mtd->oobsize);
 
 	subsize  = mtd->writesize >> mtd->subpage_sft;
 	subcount = mtd->writesize / subsize;
 
-	msg("Device uses %d subpages of %d bytes\n", subcount, subsize);
+	pr_info("Device uses %d subpages of %d bytes\n", subcount, subsize);
 
 	offset     = page_offset * mtd->writesize;
 	eraseblock = mtd_div_by_eb(offset, mtd);
 
-	msg("Using page=%u, offset=%llu, eraseblock=%u\n",
+	pr_info("Using page=%u, offset=%llu, eraseblock=%u\n",
 		page_offset, offset, eraseblock);
 
 	wbuffer = kmalloc(mtd->writesize, GFP_KERNEL);
@@ -432,8 +433,8 @@ static int __init mtd_nandbiterrs_init(void)
 		goto exit_error;
 
 	err = -EIO;
-	msg("finished successfully.\n");
-	msg("==================================================\n");
+	pr_info("finished successfully.\n");
+	printk(KERN_INFO "==================================================\n");
 
 exit_error:
 	kfree(rbuffer);
diff --git a/drivers/mtd/tests/mtd_nandecctest.c b/drivers/mtd/tests/mtd_nandecctest.c
index b437fa4..db2f22e 100644
--- a/drivers/mtd/tests/mtd_nandecctest.c
+++ b/drivers/mtd/tests/mtd_nandecctest.c
@@ -1,3 +1,5 @@
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/list.h>
@@ -254,7 +256,7 @@ static int nand_ecc_test_run(const size_t size)
 		goto error;
 	}
 
-	get_random_bytes(correct_data, size);
+	prandom_bytes(correct_data, size);
 	__nand_calculate_ecc(correct_data, size, correct_ecc);
 
 	for (i = 0; i < ARRAY_SIZE(nand_ecc_test); i++) {
@@ -264,13 +266,13 @@ static int nand_ecc_test_run(const size_t size)
 						correct_data, size);
 
 		if (err) {
-			pr_err("mtd_nandecctest: not ok - %s-%zd\n",
+			pr_err("not ok - %s-%zd\n",
 				nand_ecc_test[i].name, size);
 			dump_data_ecc(error_data, error_ecc,
 				correct_data, correct_ecc, size);
 			break;
 		}
-		pr_info("mtd_nandecctest: ok - %s-%zd\n",
+		pr_info("ok - %s-%zd\n",
 			nand_ecc_test[i].name, size);
 	}
 error:
diff --git a/drivers/mtd/tests/mtd_oobtest.c b/drivers/mtd/tests/mtd_oobtest.c
index ed9b628..3e24b37 100644
--- a/drivers/mtd/tests/mtd_oobtest.c
+++ b/drivers/mtd/tests/mtd_oobtest.c
@@ -19,6 +19,8 @@
  * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <asm/div64.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -27,8 +29,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
-
-#define PRINT_PREF KERN_INFO "mtd_oobtest: "
+#include <linux/random.h>
 
 static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
@@ -46,26 +47,7 @@ static int use_offset;
 static int use_len;
 static int use_len_max;
 static int vary_offset;
-static unsigned long next = 1;
-
-static inline unsigned int simple_rand(void)
-{
-	next = next * 1103515245 + 12345;
-	return (unsigned int)((next / 65536) % 32768);
-}
-
-static inline void simple_srand(unsigned long seed)
-{
-	next = seed;
-}
-
-static void set_random_data(unsigned char *buf, size_t len)
-{
-	size_t i;
-
-	for (i = 0; i < len; ++i)
-		buf[i] = simple_rand();
-}
+static struct rnd_state rnd_state;
 
 static int erase_eraseblock(int ebnum)
 {
@@ -80,13 +62,12 @@ static int erase_eraseblock(int ebnum)
 
 	err = mtd_erase(mtd, &ei);
 	if (err) {
-		printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+		pr_err("error %d while erasing EB %d\n", err, ebnum);
 		return err;
 	}
 
 	if (ei.state == MTD_ERASE_FAILED) {
-		printk(PRINT_PREF "some erase error occurred at EB %d\n",
-		       ebnum);
+		pr_err("some erase error occurred at EB %d\n", ebnum);
 		return -EIO;
 	}
 
@@ -98,7 +79,7 @@ static int erase_whole_device(void)
 	int err;
 	unsigned int i;
 
-	printk(PRINT_PREF "erasing whole device\n");
+	pr_info("erasing whole device\n");
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
 			continue;
@@ -107,7 +88,7 @@ static int erase_whole_device(void)
 			return err;
 		cond_resched();
 	}
-	printk(PRINT_PREF "erased %u eraseblocks\n", i);
+	pr_info("erased %u eraseblocks\n", i);
 	return 0;
 }
 
@@ -130,7 +111,7 @@ static int write_eraseblock(int ebnum)
 	loff_t addr = ebnum * mtd->erasesize;
 
 	for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
-		set_random_data(writebuf, use_len);
+		prandom_bytes_state(&rnd_state, writebuf, use_len);
 		ops.mode      = MTD_OPS_AUTO_OOB;
 		ops.len       = 0;
 		ops.retlen    = 0;
@@ -141,9 +122,9 @@ static int write_eraseblock(int ebnum)
 		ops.oobbuf    = writebuf;
 		err = mtd_write_oob(mtd, addr, &ops);
 		if (err || ops.oobretlen != use_len) {
-			printk(PRINT_PREF "error: writeoob failed at %#llx\n",
+			pr_err("error: writeoob failed at %#llx\n",
 			       (long long)addr);
-			printk(PRINT_PREF "error: use_len %d, use_offset %d\n",
+			pr_err("error: use_len %d, use_offset %d\n",
 			       use_len, use_offset);
 			errcnt += 1;
 			return err ? err : -1;
@@ -160,7 +141,7 @@ static int write_whole_device(void)
 	int err;
 	unsigned int i;
 
-	printk(PRINT_PREF "writing OOBs of whole device\n");
+	pr_info("writing OOBs of whole device\n");
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
 			continue;
@@ -168,10 +149,10 @@ static int write_whole_device(void)
 		if (err)
 			return err;
 		if (i % 256 == 0)
-			printk(PRINT_PREF "written up to eraseblock %u\n", i);
+			pr_info("written up to eraseblock %u\n", i);
 		cond_resched();
 	}
-	printk(PRINT_PREF "written %u eraseblocks\n", i);
+	pr_info("written %u eraseblocks\n", i);
 	return 0;
 }
 
@@ -183,7 +164,7 @@ static int verify_eraseblock(int ebnum)
 	loff_t addr = ebnum * mtd->erasesize;
 
 	for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
-		set_random_data(writebuf, use_len);
+		prandom_bytes_state(&rnd_state, writebuf, use_len);
 		ops.mode      = MTD_OPS_AUTO_OOB;
 		ops.len       = 0;
 		ops.retlen    = 0;
@@ -194,17 +175,17 @@ static int verify_eraseblock(int ebnum)
 		ops.oobbuf    = readbuf;
 		err = mtd_read_oob(mtd, addr, &ops);
 		if (err || ops.oobretlen != use_len) {
-			printk(PRINT_PREF "error: readoob failed at %#llx\n",
+			pr_err("error: readoob failed at %#llx\n",
 			       (long long)addr);
 			errcnt += 1;
 			return err ? err : -1;
 		}
 		if (memcmp(readbuf, writebuf, use_len)) {
-			printk(PRINT_PREF "error: verify failed at %#llx\n",
+			pr_err("error: verify failed at %#llx\n",
 			       (long long)addr);
 			errcnt += 1;
 			if (errcnt > 1000) {
-				printk(PRINT_PREF "error: too many errors\n");
+				pr_err("error: too many errors\n");
 				return -1;
 			}
 		}
@@ -221,29 +202,28 @@ static int verify_eraseblock(int ebnum)
 			ops.oobbuf    = readbuf;
 			err = mtd_read_oob(mtd, addr, &ops);
 			if (err || ops.oobretlen != mtd->ecclayout->oobavail) {
-				printk(PRINT_PREF "error: readoob failed at "
-				       "%#llx\n", (long long)addr);
+				pr_err("error: readoob failed at %#llx\n",
+						(long long)addr);
 				errcnt += 1;
 				return err ? err : -1;
 			}
 			if (memcmp(readbuf + use_offset, writebuf, use_len)) {
-				printk(PRINT_PREF "error: verify failed at "
-				       "%#llx\n", (long long)addr);
+				pr_err("error: verify failed at %#llx\n",
+						(long long)addr);
 				errcnt += 1;
 				if (errcnt > 1000) {
-					printk(PRINT_PREF "error: too many "
-					       "errors\n");
+					pr_err("error: too many errors\n");
 					return -1;
 				}
 			}
 			for (k = 0; k < use_offset; ++k)
 				if (readbuf[k] != 0xff) {
-					printk(PRINT_PREF "error: verify 0xff "
+					pr_err("error: verify 0xff "
 					       "failed at %#llx\n",
 					       (long long)addr);
 					errcnt += 1;
 					if (errcnt > 1000) {
-						printk(PRINT_PREF "error: too "
+						pr_err("error: too "
 						       "many errors\n");
 						return -1;
 					}
@@ -251,12 +231,12 @@ static int verify_eraseblock(int ebnum)
 			for (k = use_offset + use_len;
 			     k < mtd->ecclayout->oobavail; ++k)
 				if (readbuf[k] != 0xff) {
-					printk(PRINT_PREF "error: verify 0xff "
+					pr_err("error: verify 0xff "
 					       "failed at %#llx\n",
 					       (long long)addr);
 					errcnt += 1;
 					if (errcnt > 1000) {
-						printk(PRINT_PREF "error: too "
+						pr_err("error: too "
 						       "many errors\n");
 						return -1;
 					}
@@ -275,7 +255,7 @@ static int verify_eraseblock_in_one_go(int ebnum)
 	loff_t addr = ebnum * mtd->erasesize;
 	size_t len = mtd->ecclayout->oobavail * pgcnt;
 
-	set_random_data(writebuf, len);
+	prandom_bytes_state(&rnd_state, writebuf, len);
 	ops.mode      = MTD_OPS_AUTO_OOB;
 	ops.len       = 0;
 	ops.retlen    = 0;
@@ -286,17 +266,17 @@ static int verify_eraseblock_in_one_go(int ebnum)
 	ops.oobbuf    = readbuf;
 	err = mtd_read_oob(mtd, addr, &ops);
 	if (err || ops.oobretlen != len) {
-		printk(PRINT_PREF "error: readoob failed at %#llx\n",
+		pr_err("error: readoob failed at %#llx\n",
 		       (long long)addr);
 		errcnt += 1;
 		return err ? err : -1;
 	}
 	if (memcmp(readbuf, writebuf, len)) {
-		printk(PRINT_PREF "error: verify failed at %#llx\n",
+		pr_err("error: verify failed at %#llx\n",
 		       (long long)addr);
 		errcnt += 1;
 		if (errcnt > 1000) {
-			printk(PRINT_PREF "error: too many errors\n");
+			pr_err("error: too many errors\n");
 			return -1;
 		}
 	}
@@ -309,7 +289,7 @@ static int verify_all_eraseblocks(void)
 	int err;
 	unsigned int i;
 
-	printk(PRINT_PREF "verifying all eraseblocks\n");
+	pr_info("verifying all eraseblocks\n");
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
 			continue;
@@ -317,10 +297,10 @@ static int verify_all_eraseblocks(void)
 		if (err)
 			return err;
 		if (i % 256 == 0)
-			printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+			pr_info("verified up to eraseblock %u\n", i);
 		cond_resched();
 	}
-	printk(PRINT_PREF "verified %u eraseblocks\n", i);
+	pr_info("verified %u eraseblocks\n", i);
 	return 0;
 }
 
@@ -331,7 +311,7 @@ static int is_block_bad(int ebnum)
 
 	ret = mtd_block_isbad(mtd, addr);
 	if (ret)
-		printk(PRINT_PREF "block %d is bad\n", ebnum);
+		pr_info("block %d is bad\n", ebnum);
 	return ret;
 }
 
@@ -341,18 +321,18 @@ static int scan_for_bad_eraseblocks(void)
 
 	bbt = kmalloc(ebcnt, GFP_KERNEL);
 	if (!bbt) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		return -ENOMEM;
 	}
 
-	printk(PRINT_PREF "scanning for bad eraseblocks\n");
+	pr_info("scanning for bad eraseblocks\n");
 	for (i = 0; i < ebcnt; ++i) {
 		bbt[i] = is_block_bad(i) ? 1 : 0;
 		if (bbt[i])
 			bad += 1;
 		cond_resched();
 	}
-	printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+	pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
 	return 0;
 }
 
@@ -368,22 +348,22 @@ static int __init mtd_oobtest_init(void)
 	printk(KERN_INFO "=================================================\n");
 
 	if (dev < 0) {
-		printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
-		printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+		pr_info("Please specify a valid mtd-device via module parameter\n");
+		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
 		return -EINVAL;
 	}
 
-	printk(PRINT_PREF "MTD device: %d\n", dev);
+	pr_info("MTD device: %d\n", dev);
 
 	mtd = get_mtd_device(NULL, dev);
 	if (IS_ERR(mtd)) {
 		err = PTR_ERR(mtd);
-		printk(PRINT_PREF "error: cannot get MTD device\n");
+		pr_err("error: cannot get MTD device\n");
 		return err;
 	}
 
 	if (mtd->type != MTD_NANDFLASH) {
-		printk(PRINT_PREF "this test requires NAND flash\n");
+		pr_info("this test requires NAND flash\n");
 		goto out;
 	}
 
@@ -392,7 +372,7 @@ static int __init mtd_oobtest_init(void)
 	ebcnt = tmp;
 	pgcnt = mtd->erasesize / mtd->writesize;
 
-	printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+	pr_info("MTD device size %llu, eraseblock size %u, "
 	       "page size %u, count of eraseblocks %u, pages per "
 	       "eraseblock %u, OOB size %u\n",
 	       (unsigned long long)mtd->size, mtd->erasesize,
@@ -401,12 +381,12 @@ static int __init mtd_oobtest_init(void)
 	err = -ENOMEM;
 	readbuf = kmalloc(mtd->erasesize, GFP_KERNEL);
 	if (!readbuf) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		goto out;
 	}
 	writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
 	if (!writebuf) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		goto out;
 	}
 
@@ -420,18 +400,18 @@ static int __init mtd_oobtest_init(void)
 	vary_offset = 0;
 
 	/* First test: write all OOB, read it back and verify */
-	printk(PRINT_PREF "test 1 of 5\n");
+	pr_info("test 1 of 5\n");
 
 	err = erase_whole_device();
 	if (err)
 		goto out;
 
-	simple_srand(1);
+	prandom_seed_state(&rnd_state, 1);
 	err = write_whole_device();
 	if (err)
 		goto out;
 
-	simple_srand(1);
+	prandom_seed_state(&rnd_state, 1);
 	err = verify_all_eraseblocks();
 	if (err)
 		goto out;
@@ -440,20 +420,20 @@ static int __init mtd_oobtest_init(void)
 	 * Second test: write all OOB, a block at a time, read it back and
 	 * verify.
 	 */
-	printk(PRINT_PREF "test 2 of 5\n");
+	pr_info("test 2 of 5\n");
 
 	err = erase_whole_device();
 	if (err)
 		goto out;
 
-	simple_srand(3);
+	prandom_seed_state(&rnd_state, 3);
 	err = write_whole_device();
 	if (err)
 		goto out;
 
 	/* Check all eraseblocks */
-	simple_srand(3);
-	printk(PRINT_PREF "verifying all eraseblocks\n");
+	prandom_seed_state(&rnd_state, 3);
+	pr_info("verifying all eraseblocks\n");
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
 			continue;
@@ -461,16 +441,16 @@ static int __init mtd_oobtest_init(void)
 		if (err)
 			goto out;
 		if (i % 256 == 0)
-			printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+			pr_info("verified up to eraseblock %u\n", i);
 		cond_resched();
 	}
-	printk(PRINT_PREF "verified %u eraseblocks\n", i);
+	pr_info("verified %u eraseblocks\n", i);
 
 	/*
 	 * Third test: write OOB at varying offsets and lengths, read it back
 	 * and verify.
 	 */
-	printk(PRINT_PREF "test 3 of 5\n");
+	pr_info("test 3 of 5\n");
 
 	err = erase_whole_device();
 	if (err)
@@ -481,7 +461,7 @@ static int __init mtd_oobtest_init(void)
 	use_len = mtd->ecclayout->oobavail;
 	use_len_max = mtd->ecclayout->oobavail;
 	vary_offset = 1;
-	simple_srand(5);
+	prandom_seed_state(&rnd_state, 5);
 
 	err = write_whole_device();
 	if (err)
@@ -492,7 +472,7 @@ static int __init mtd_oobtest_init(void)
 	use_len = mtd->ecclayout->oobavail;
 	use_len_max = mtd->ecclayout->oobavail;
 	vary_offset = 1;
-	simple_srand(5);
+	prandom_seed_state(&rnd_state, 5);
 	err = verify_all_eraseblocks();
 	if (err)
 		goto out;
@@ -503,7 +483,7 @@ static int __init mtd_oobtest_init(void)
 	vary_offset = 0;
 
 	/* Fourth test: try to write off end of device */
-	printk(PRINT_PREF "test 4 of 5\n");
+	pr_info("test 4 of 5\n");
 
 	err = erase_whole_device();
 	if (err)
@@ -522,14 +502,14 @@ static int __init mtd_oobtest_init(void)
 	ops.ooboffs   = mtd->ecclayout->oobavail;
 	ops.datbuf    = NULL;
 	ops.oobbuf    = writebuf;
-	printk(PRINT_PREF "attempting to start write past end of OOB\n");
-	printk(PRINT_PREF "an error is expected...\n");
+	pr_info("attempting to start write past end of OOB\n");
+	pr_info("an error is expected...\n");
 	err = mtd_write_oob(mtd, addr0, &ops);
 	if (err) {
-		printk(PRINT_PREF "error occurred as expected\n");
+		pr_info("error occurred as expected\n");
 		err = 0;
 	} else {
-		printk(PRINT_PREF "error: can write past end of OOB\n");
+		pr_err("error: can write past end of OOB\n");
 		errcnt += 1;
 	}
 
@@ -542,19 +522,19 @@ static int __init mtd_oobtest_init(void)
 	ops.ooboffs   = mtd->ecclayout->oobavail;
 	ops.datbuf    = NULL;
 	ops.oobbuf    = readbuf;
-	printk(PRINT_PREF "attempting to start read past end of OOB\n");
-	printk(PRINT_PREF "an error is expected...\n");
+	pr_info("attempting to start read past end of OOB\n");
+	pr_info("an error is expected...\n");
 	err = mtd_read_oob(mtd, addr0, &ops);
 	if (err) {
-		printk(PRINT_PREF "error occurred as expected\n");
+		pr_info("error occurred as expected\n");
 		err = 0;
 	} else {
-		printk(PRINT_PREF "error: can read past end of OOB\n");
+		pr_err("error: can read past end of OOB\n");
 		errcnt += 1;
 	}
 
 	if (bbt[ebcnt - 1])
-		printk(PRINT_PREF "skipping end of device tests because last "
+		pr_info("skipping end of device tests because last "
 		       "block is bad\n");
 	else {
 		/* Attempt to write off end of device */
@@ -566,14 +546,14 @@ static int __init mtd_oobtest_init(void)
 		ops.ooboffs   = 0;
 		ops.datbuf    = NULL;
 		ops.oobbuf    = writebuf;
-		printk(PRINT_PREF "attempting to write past end of device\n");
-		printk(PRINT_PREF "an error is expected...\n");
+		pr_info("attempting to write past end of device\n");
+		pr_info("an error is expected...\n");
 		err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
 		if (err) {
-			printk(PRINT_PREF "error occurred as expected\n");
+			pr_info("error occurred as expected\n");
 			err = 0;
 		} else {
-			printk(PRINT_PREF "error: wrote past end of device\n");
+			pr_err("error: wrote past end of device\n");
 			errcnt += 1;
 		}
 
@@ -586,14 +566,14 @@ static int __init mtd_oobtest_init(void)
 		ops.ooboffs   = 0;
 		ops.datbuf    = NULL;
 		ops.oobbuf    = readbuf;
-		printk(PRINT_PREF "attempting to read past end of device\n");
-		printk(PRINT_PREF "an error is expected...\n");
+		pr_info("attempting to read past end of device\n");
+		pr_info("an error is expected...\n");
 		err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
 		if (err) {
-			printk(PRINT_PREF "error occurred as expected\n");
+			pr_info("error occurred as expected\n");
 			err = 0;
 		} else {
-			printk(PRINT_PREF "error: read past end of device\n");
+			pr_err("error: read past end of device\n");
 			errcnt += 1;
 		}
 
@@ -610,14 +590,14 @@ static int __init mtd_oobtest_init(void)
 		ops.ooboffs   = 1;
 		ops.datbuf    = NULL;
 		ops.oobbuf    = writebuf;
-		printk(PRINT_PREF "attempting to write past end of device\n");
-		printk(PRINT_PREF "an error is expected...\n");
+		pr_info("attempting to write past end of device\n");
+		pr_info("an error is expected...\n");
 		err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops);
 		if (err) {
-			printk(PRINT_PREF "error occurred as expected\n");
+			pr_info("error occurred as expected\n");
 			err = 0;
 		} else {
-			printk(PRINT_PREF "error: wrote past end of device\n");
+			pr_err("error: wrote past end of device\n");
 			errcnt += 1;
 		}
 
@@ -630,20 +610,20 @@ static int __init mtd_oobtest_init(void)
 		ops.ooboffs   = 1;
 		ops.datbuf    = NULL;
 		ops.oobbuf    = readbuf;
-		printk(PRINT_PREF "attempting to read past end of device\n");
-		printk(PRINT_PREF "an error is expected...\n");
+		pr_info("attempting to read past end of device\n");
+		pr_info("an error is expected...\n");
 		err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops);
 		if (err) {
-			printk(PRINT_PREF "error occurred as expected\n");
+			pr_info("error occurred as expected\n");
 			err = 0;
 		} else {
-			printk(PRINT_PREF "error: read past end of device\n");
+			pr_err("error: read past end of device\n");
 			errcnt += 1;
 		}
 	}
 
 	/* Fifth test: write / read across block boundaries */
-	printk(PRINT_PREF "test 5 of 5\n");
+	pr_info("test 5 of 5\n");
 
 	/* Erase all eraseblocks */
 	err = erase_whole_device();
@@ -651,8 +631,8 @@ static int __init mtd_oobtest_init(void)
 		goto out;
 
 	/* Write all eraseblocks */
-	simple_srand(11);
-	printk(PRINT_PREF "writing OOBs of whole device\n");
+	prandom_seed_state(&rnd_state, 11);
+	pr_info("writing OOBs of whole device\n");
 	for (i = 0; i < ebcnt - 1; ++i) {
 		int cnt = 2;
 		int pg;
@@ -661,7 +641,7 @@ static int __init mtd_oobtest_init(void)
 			continue;
 		addr = (i + 1) * mtd->erasesize - mtd->writesize;
 		for (pg = 0; pg < cnt; ++pg) {
-			set_random_data(writebuf, sz);
+			prandom_bytes_state(&rnd_state, writebuf, sz);
 			ops.mode      = MTD_OPS_AUTO_OOB;
 			ops.len       = 0;
 			ops.retlen    = 0;
@@ -674,21 +654,21 @@ static int __init mtd_oobtest_init(void)
 			if (err)
 				goto out;
 			if (i % 256 == 0)
-				printk(PRINT_PREF "written up to eraseblock "
-				       "%u\n", i);
+				pr_info("written up to eraseblock %u\n", i);
 			cond_resched();
 			addr += mtd->writesize;
 		}
 	}
-	printk(PRINT_PREF "written %u eraseblocks\n", i);
+	pr_info("written %u eraseblocks\n", i);
 
 	/* Check all eraseblocks */
-	simple_srand(11);
-	printk(PRINT_PREF "verifying all eraseblocks\n");
+	prandom_seed_state(&rnd_state, 11);
+	pr_info("verifying all eraseblocks\n");
 	for (i = 0; i < ebcnt - 1; ++i) {
 		if (bbt[i] || bbt[i + 1])
 			continue;
-		set_random_data(writebuf, mtd->ecclayout->oobavail * 2);
+		prandom_bytes_state(&rnd_state, writebuf,
+					mtd->ecclayout->oobavail * 2);
 		addr = (i + 1) * mtd->erasesize - mtd->writesize;
 		ops.mode      = MTD_OPS_AUTO_OOB;
 		ops.len       = 0;
@@ -702,28 +682,28 @@ static int __init mtd_oobtest_init(void)
 		if (err)
 			goto out;
 		if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) {
-			printk(PRINT_PREF "error: verify failed at %#llx\n",
+			pr_err("error: verify failed at %#llx\n",
 			       (long long)addr);
 			errcnt += 1;
 			if (errcnt > 1000) {
-				printk(PRINT_PREF "error: too many errors\n");
+				pr_err("error: too many errors\n");
 				goto out;
 			}
 		}
 		if (i % 256 == 0)
-			printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+			pr_info("verified up to eraseblock %u\n", i);
 		cond_resched();
 	}
-	printk(PRINT_PREF "verified %u eraseblocks\n", i);
+	pr_info("verified %u eraseblocks\n", i);
 
-	printk(PRINT_PREF "finished with %d errors\n", errcnt);
+	pr_info("finished with %d errors\n", errcnt);
 out:
 	kfree(bbt);
 	kfree(writebuf);
 	kfree(readbuf);
 	put_mtd_device(mtd);
 	if (err)
-		printk(PRINT_PREF "error %d occurred\n", err);
+		pr_info("error %d occurred\n", err);
 	printk(KERN_INFO "=================================================\n");
 	return err;
 }
diff --git a/drivers/mtd/tests/mtd_pagetest.c b/drivers/mtd/tests/mtd_pagetest.c
index 252ddb0..0c1140b 100644
--- a/drivers/mtd/tests/mtd_pagetest.c
+++ b/drivers/mtd/tests/mtd_pagetest.c
@@ -19,6 +19,8 @@
  * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <asm/div64.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -27,8 +29,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
-
-#define PRINT_PREF KERN_INFO "mtd_pagetest: "
+#include <linux/random.h>
 
 static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
@@ -45,26 +46,7 @@ static int bufsize;
 static int ebcnt;
 static int pgcnt;
 static int errcnt;
-static unsigned long next = 1;
-
-static inline unsigned int simple_rand(void)
-{
-	next = next * 1103515245 + 12345;
-	return (unsigned int)((next / 65536) % 32768);
-}
-
-static inline void simple_srand(unsigned long seed)
-{
-	next = seed;
-}
-
-static void set_random_data(unsigned char *buf, size_t len)
-{
-	size_t i;
-
-	for (i = 0; i < len; ++i)
-		buf[i] = simple_rand();
-}
+static struct rnd_state rnd_state;
 
 static int erase_eraseblock(int ebnum)
 {
@@ -79,12 +61,12 @@ static int erase_eraseblock(int ebnum)
 
 	err = mtd_erase(mtd, &ei);
 	if (err) {
-		printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+		pr_err("error %d while erasing EB %d\n", err, ebnum);
 		return err;
 	}
 
 	if (ei.state == MTD_ERASE_FAILED) {
-		printk(PRINT_PREF "some erase error occurred at EB %d\n",
+		pr_err("some erase error occurred at EB %d\n",
 		       ebnum);
 		return -EIO;
 	}
@@ -98,11 +80,11 @@ static int write_eraseblock(int ebnum)
 	size_t written;
 	loff_t addr = ebnum * mtd->erasesize;
 
-	set_random_data(writebuf, mtd->erasesize);
+	prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
 	cond_resched();
 	err = mtd_write(mtd, addr, mtd->erasesize, &written, writebuf);
 	if (err || written != mtd->erasesize)
-		printk(PRINT_PREF "error: write failed at %#llx\n",
+		pr_err("error: write failed at %#llx\n",
 		       (long long)addr);
 
 	return err;
@@ -124,14 +106,14 @@ static int verify_eraseblock(int ebnum)
 	for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
 		addrn -= mtd->erasesize;
 
-	set_random_data(writebuf, mtd->erasesize);
+	prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
 	for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) {
 		/* Do a read to set the internal dataRAMs to different data */
 		err = mtd_read(mtd, addr0, bufsize, &read, twopages);
 		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != bufsize) {
-			printk(PRINT_PREF "error: read failed at %#llx\n",
+			pr_err("error: read failed at %#llx\n",
 			       (long long)addr0);
 			return err;
 		}
@@ -139,7 +121,7 @@ static int verify_eraseblock(int ebnum)
 		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != bufsize) {
-			printk(PRINT_PREF "error: read failed at %#llx\n",
+			pr_err("error: read failed at %#llx\n",
 			       (long long)(addrn - bufsize));
 			return err;
 		}
@@ -148,25 +130,26 @@ static int verify_eraseblock(int ebnum)
 		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != bufsize) {
-			printk(PRINT_PREF "error: read failed at %#llx\n",
+			pr_err("error: read failed at %#llx\n",
 			       (long long)addr);
 			break;
 		}
 		if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) {
-			printk(PRINT_PREF "error: verify failed at %#llx\n",
+			pr_err("error: verify failed at %#llx\n",
 			       (long long)addr);
 			errcnt += 1;
 		}
 	}
 	/* Check boundary between eraseblocks */
 	if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) {
-		unsigned long oldnext = next;
+		struct rnd_state old_state = rnd_state;
+
 		/* Do a read to set the internal dataRAMs to different data */
 		err = mtd_read(mtd, addr0, bufsize, &read, twopages);
 		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != bufsize) {
-			printk(PRINT_PREF "error: read failed at %#llx\n",
+			pr_err("error: read failed at %#llx\n",
 			       (long long)addr0);
 			return err;
 		}
@@ -174,7 +157,7 @@ static int verify_eraseblock(int ebnum)
 		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != bufsize) {
-			printk(PRINT_PREF "error: read failed at %#llx\n",
+			pr_err("error: read failed at %#llx\n",
 			       (long long)(addrn - bufsize));
 			return err;
 		}
@@ -183,18 +166,18 @@ static int verify_eraseblock(int ebnum)
 		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != bufsize) {
-			printk(PRINT_PREF "error: read failed at %#llx\n",
+			pr_err("error: read failed at %#llx\n",
 			       (long long)addr);
 			return err;
 		}
 		memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize);
-		set_random_data(boundary + pgsize, pgsize);
+		prandom_bytes_state(&rnd_state, boundary + pgsize, pgsize);
 		if (memcmp(twopages, boundary, bufsize)) {
-			printk(PRINT_PREF "error: verify failed at %#llx\n",
+			pr_err("error: verify failed at %#llx\n",
 			       (long long)addr);
 			errcnt += 1;
 		}
-		next = oldnext;
+		rnd_state = old_state;
 	}
 	return err;
 }
@@ -206,10 +189,10 @@ static int crosstest(void)
 	loff_t addr, addr0, addrn;
 	unsigned char *pp1, *pp2, *pp3, *pp4;
 
-	printk(PRINT_PREF "crosstest\n");
+	pr_info("crosstest\n");
 	pp1 = kmalloc(pgsize * 4, GFP_KERNEL);
 	if (!pp1) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		return -ENOMEM;
 	}
 	pp2 = pp1 + pgsize;
@@ -231,7 +214,7 @@ static int crosstest(void)
 	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != pgsize) {
-		printk(PRINT_PREF "error: read failed at %#llx\n",
+		pr_err("error: read failed at %#llx\n",
 		       (long long)addr);
 		kfree(pp1);
 		return err;
@@ -243,7 +226,7 @@ static int crosstest(void)
 	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != pgsize) {
-		printk(PRINT_PREF "error: read failed at %#llx\n",
+		pr_err("error: read failed at %#llx\n",
 		       (long long)addr);
 		kfree(pp1);
 		return err;
@@ -251,12 +234,12 @@ static int crosstest(void)
 
 	/* Read first page to pp2 */
 	addr = addr0;
-	printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
+	pr_info("reading page at %#llx\n", (long long)addr);
 	err = mtd_read(mtd, addr, pgsize, &read, pp2);
 	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != pgsize) {
-		printk(PRINT_PREF "error: read failed at %#llx\n",
+		pr_err("error: read failed at %#llx\n",
 		       (long long)addr);
 		kfree(pp1);
 		return err;
@@ -264,12 +247,12 @@ static int crosstest(void)
 
 	/* Read last page to pp3 */
 	addr = addrn - pgsize;
-	printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
+	pr_info("reading page at %#llx\n", (long long)addr);
 	err = mtd_read(mtd, addr, pgsize, &read, pp3);
 	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != pgsize) {
-		printk(PRINT_PREF "error: read failed at %#llx\n",
+		pr_err("error: read failed at %#llx\n",
 		       (long long)addr);
 		kfree(pp1);
 		return err;
@@ -277,25 +260,25 @@ static int crosstest(void)
 
 	/* Read first page again to pp4 */
 	addr = addr0;
-	printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
+	pr_info("reading page at %#llx\n", (long long)addr);
 	err = mtd_read(mtd, addr, pgsize, &read, pp4);
 	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != pgsize) {
-		printk(PRINT_PREF "error: read failed at %#llx\n",
+		pr_err("error: read failed at %#llx\n",
 		       (long long)addr);
 		kfree(pp1);
 		return err;
 	}
 
 	/* pp2 and pp4 should be the same */
-	printk(PRINT_PREF "verifying pages read at %#llx match\n",
+	pr_info("verifying pages read at %#llx match\n",
 	       (long long)addr0);
 	if (memcmp(pp2, pp4, pgsize)) {
-		printk(PRINT_PREF "verify failed!\n");
+		pr_err("verify failed!\n");
 		errcnt += 1;
 	} else if (!err)
-		printk(PRINT_PREF "crosstest ok\n");
+		pr_info("crosstest ok\n");
 	kfree(pp1);
 	return err;
 }
@@ -307,7 +290,7 @@ static int erasecrosstest(void)
 	loff_t addr0;
 	char *readbuf = twopages;
 
-	printk(PRINT_PREF "erasecrosstest\n");
+	pr_info("erasecrosstest\n");
 
 	ebnum = 0;
 	addr0 = 0;
@@ -320,79 +303,79 @@ static int erasecrosstest(void)
 	while (ebnum2 && bbt[ebnum2])
 		ebnum2 -= 1;
 
-	printk(PRINT_PREF "erasing block %d\n", ebnum);
+	pr_info("erasing block %d\n", ebnum);
 	err = erase_eraseblock(ebnum);
 	if (err)
 		return err;
 
-	printk(PRINT_PREF "writing 1st page of block %d\n", ebnum);
-	set_random_data(writebuf, pgsize);
+	pr_info("writing 1st page of block %d\n", ebnum);
+	prandom_bytes_state(&rnd_state, writebuf, pgsize);
 	strcpy(writebuf, "There is no data like this!");
 	err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
 	if (err || written != pgsize) {
-		printk(PRINT_PREF "error: write failed at %#llx\n",
+		pr_info("error: write failed at %#llx\n",
 		       (long long)addr0);
 		return err ? err : -1;
 	}
 
-	printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
+	pr_info("reading 1st page of block %d\n", ebnum);
 	memset(readbuf, 0, pgsize);
 	err = mtd_read(mtd, addr0, pgsize, &read, readbuf);
 	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != pgsize) {
-		printk(PRINT_PREF "error: read failed at %#llx\n",
+		pr_err("error: read failed at %#llx\n",
 		       (long long)addr0);
 		return err ? err : -1;
 	}
 
-	printk(PRINT_PREF "verifying 1st page of block %d\n", ebnum);
+	pr_info("verifying 1st page of block %d\n", ebnum);
 	if (memcmp(writebuf, readbuf, pgsize)) {
-		printk(PRINT_PREF "verify failed!\n");
+		pr_err("verify failed!\n");
 		errcnt += 1;
 		return -1;
 	}
 
-	printk(PRINT_PREF "erasing block %d\n", ebnum);
+	pr_info("erasing block %d\n", ebnum);
 	err = erase_eraseblock(ebnum);
 	if (err)
 		return err;
 
-	printk(PRINT_PREF "writing 1st page of block %d\n", ebnum);
-	set_random_data(writebuf, pgsize);
+	pr_info("writing 1st page of block %d\n", ebnum);
+	prandom_bytes_state(&rnd_state, writebuf, pgsize);
 	strcpy(writebuf, "There is no data like this!");
 	err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
 	if (err || written != pgsize) {
-		printk(PRINT_PREF "error: write failed at %#llx\n",
+		pr_err("error: write failed at %#llx\n",
 		       (long long)addr0);
 		return err ? err : -1;
 	}
 
-	printk(PRINT_PREF "erasing block %d\n", ebnum2);
+	pr_info("erasing block %d\n", ebnum2);
 	err = erase_eraseblock(ebnum2);
 	if (err)
 		return err;
 
-	printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
+	pr_info("reading 1st page of block %d\n", ebnum);
 	memset(readbuf, 0, pgsize);
 	err = mtd_read(mtd, addr0, pgsize, &read, readbuf);
 	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != pgsize) {
-		printk(PRINT_PREF "error: read failed at %#llx\n",
+		pr_err("error: read failed at %#llx\n",
 		       (long long)addr0);
 		return err ? err : -1;
 	}
 
-	printk(PRINT_PREF "verifying 1st page of block %d\n", ebnum);
+	pr_info("verifying 1st page of block %d\n", ebnum);
 	if (memcmp(writebuf, readbuf, pgsize)) {
-		printk(PRINT_PREF "verify failed!\n");
+		pr_err("verify failed!\n");
 		errcnt += 1;
 		return -1;
 	}
 
 	if (!err)
-		printk(PRINT_PREF "erasecrosstest ok\n");
+		pr_info("erasecrosstest ok\n");
 	return err;
 }
 
@@ -402,7 +385,7 @@ static int erasetest(void)
 	int err = 0, i, ebnum, ok = 1;
 	loff_t addr0;
 
-	printk(PRINT_PREF "erasetest\n");
+	pr_info("erasetest\n");
 
 	ebnum = 0;
 	addr0 = 0;
@@ -411,40 +394,40 @@ static int erasetest(void)
 		ebnum += 1;
 	}
 
-	printk(PRINT_PREF "erasing block %d\n", ebnum);
+	pr_info("erasing block %d\n", ebnum);
 	err = erase_eraseblock(ebnum);
 	if (err)
 		return err;
 
-	printk(PRINT_PREF "writing 1st page of block %d\n", ebnum);
-	set_random_data(writebuf, pgsize);
+	pr_info("writing 1st page of block %d\n", ebnum);
+	prandom_bytes_state(&rnd_state, writebuf, pgsize);
 	err = mtd_write(mtd, addr0, pgsize, &written, writebuf);
 	if (err || written != pgsize) {
-		printk(PRINT_PREF "error: write failed at %#llx\n",
+		pr_err("error: write failed at %#llx\n",
 		       (long long)addr0);
 		return err ? err : -1;
 	}
 
-	printk(PRINT_PREF "erasing block %d\n", ebnum);
+	pr_info("erasing block %d\n", ebnum);
 	err = erase_eraseblock(ebnum);
 	if (err)
 		return err;
 
-	printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
+	pr_info("reading 1st page of block %d\n", ebnum);
 	err = mtd_read(mtd, addr0, pgsize, &read, twopages);
 	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != pgsize) {
-		printk(PRINT_PREF "error: read failed at %#llx\n",
+		pr_err("error: read failed at %#llx\n",
 		       (long long)addr0);
 		return err ? err : -1;
 	}
 
-	printk(PRINT_PREF "verifying 1st page of block %d is all 0xff\n",
+	pr_info("verifying 1st page of block %d is all 0xff\n",
 	       ebnum);
 	for (i = 0; i < pgsize; ++i)
 		if (twopages[i] != 0xff) {
-			printk(PRINT_PREF "verifying all 0xff failed at %d\n",
+			pr_err("verifying all 0xff failed at %d\n",
 			       i);
 			errcnt += 1;
 			ok = 0;
@@ -452,7 +435,7 @@ static int erasetest(void)
 		}
 
 	if (ok && !err)
-		printk(PRINT_PREF "erasetest ok\n");
+		pr_info("erasetest ok\n");
 
 	return err;
 }
@@ -464,7 +447,7 @@ static int is_block_bad(int ebnum)
 
 	ret = mtd_block_isbad(mtd, addr);
 	if (ret)
-		printk(PRINT_PREF "block %d is bad\n", ebnum);
+		pr_info("block %d is bad\n", ebnum);
 	return ret;
 }
 
@@ -474,18 +457,18 @@ static int scan_for_bad_eraseblocks(void)
 
 	bbt = kzalloc(ebcnt, GFP_KERNEL);
 	if (!bbt) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		return -ENOMEM;
 	}
 
-	printk(PRINT_PREF "scanning for bad eraseblocks\n");
+	pr_info("scanning for bad eraseblocks\n");
 	for (i = 0; i < ebcnt; ++i) {
 		bbt[i] = is_block_bad(i) ? 1 : 0;
 		if (bbt[i])
 			bad += 1;
 		cond_resched();
 	}
-	printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+	pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
 	return 0;
 }
 
@@ -499,22 +482,22 @@ static int __init mtd_pagetest_init(void)
 	printk(KERN_INFO "=================================================\n");
 
 	if (dev < 0) {
-		printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
-		printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+		pr_info("Please specify a valid mtd-device via module parameter\n");
+		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
 		return -EINVAL;
 	}
 
-	printk(PRINT_PREF "MTD device: %d\n", dev);
+	pr_info("MTD device: %d\n", dev);
 
 	mtd = get_mtd_device(NULL, dev);
 	if (IS_ERR(mtd)) {
 		err = PTR_ERR(mtd);
-		printk(PRINT_PREF "error: cannot get MTD device\n");
+		pr_err("error: cannot get MTD device\n");
 		return err;
 	}
 
 	if (mtd->type != MTD_NANDFLASH) {
-		printk(PRINT_PREF "this test requires NAND flash\n");
+		pr_info("this test requires NAND flash\n");
 		goto out;
 	}
 
@@ -524,7 +507,7 @@ static int __init mtd_pagetest_init(void)
 	pgcnt = mtd->erasesize / mtd->writesize;
 	pgsize = mtd->writesize;
 
-	printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+	pr_info("MTD device size %llu, eraseblock size %u, "
 	       "page size %u, count of eraseblocks %u, pages per "
 	       "eraseblock %u, OOB size %u\n",
 	       (unsigned long long)mtd->size, mtd->erasesize,
@@ -534,17 +517,17 @@ static int __init mtd_pagetest_init(void)
 	bufsize = pgsize * 2;
 	writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
 	if (!writebuf) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		goto out;
 	}
 	twopages = kmalloc(bufsize, GFP_KERNEL);
 	if (!twopages) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		goto out;
 	}
 	boundary = kmalloc(bufsize, GFP_KERNEL);
 	if (!boundary) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		goto out;
 	}
 
@@ -553,7 +536,7 @@ static int __init mtd_pagetest_init(void)
 		goto out;
 
 	/* Erase all eraseblocks */
-	printk(PRINT_PREF "erasing whole device\n");
+	pr_info("erasing whole device\n");
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
 			continue;
@@ -562,11 +545,11 @@ static int __init mtd_pagetest_init(void)
 			goto out;
 		cond_resched();
 	}
-	printk(PRINT_PREF "erased %u eraseblocks\n", i);
+	pr_info("erased %u eraseblocks\n", i);
 
 	/* Write all eraseblocks */
-	simple_srand(1);
-	printk(PRINT_PREF "writing whole device\n");
+	prandom_seed_state(&rnd_state, 1);
+	pr_info("writing whole device\n");
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
 			continue;
@@ -574,14 +557,14 @@ static int __init mtd_pagetest_init(void)
 		if (err)
 			goto out;
 		if (i % 256 == 0)
-			printk(PRINT_PREF "written up to eraseblock %u\n", i);
+			pr_info("written up to eraseblock %u\n", i);
 		cond_resched();
 	}
-	printk(PRINT_PREF "written %u eraseblocks\n", i);
+	pr_info("written %u eraseblocks\n", i);
 
 	/* Check all eraseblocks */
-	simple_srand(1);
-	printk(PRINT_PREF "verifying all eraseblocks\n");
+	prandom_seed_state(&rnd_state, 1);
+	pr_info("verifying all eraseblocks\n");
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
 			continue;
@@ -589,10 +572,10 @@ static int __init mtd_pagetest_init(void)
 		if (err)
 			goto out;
 		if (i % 256 == 0)
-			printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+			pr_info("verified up to eraseblock %u\n", i);
 		cond_resched();
 	}
-	printk(PRINT_PREF "verified %u eraseblocks\n", i);
+	pr_info("verified %u eraseblocks\n", i);
 
 	err = crosstest();
 	if (err)
@@ -606,7 +589,7 @@ static int __init mtd_pagetest_init(void)
 	if (err)
 		goto out;
 
-	printk(PRINT_PREF "finished with %d errors\n", errcnt);
+	pr_info("finished with %d errors\n", errcnt);
 out:
 
 	kfree(bbt);
@@ -615,7 +598,7 @@ out:
 	kfree(writebuf);
 	put_mtd_device(mtd);
 	if (err)
-		printk(PRINT_PREF "error %d occurred\n", err);
+		pr_info("error %d occurred\n", err);
 	printk(KERN_INFO "=================================================\n");
 	return err;
 }
diff --git a/drivers/mtd/tests/mtd_readtest.c b/drivers/mtd/tests/mtd_readtest.c
index 121aba1..31f505c 100644
--- a/drivers/mtd/tests/mtd_readtest.c
+++ b/drivers/mtd/tests/mtd_readtest.c
@@ -19,6 +19,8 @@
  * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -27,8 +29,6 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 
-#define PRINT_PREF KERN_INFO "mtd_readtest: "
-
 static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -56,7 +56,7 @@ static int read_eraseblock_by_page(int ebnum)
 		if (ret == -EUCLEAN)
 			ret = 0;
 		if (ret || read != pgsize) {
-			printk(PRINT_PREF "error: read failed at %#llx\n",
+			pr_err("error: read failed at %#llx\n",
 			       (long long)addr);
 			if (!err)
 				err = ret;
@@ -77,7 +77,7 @@ static int read_eraseblock_by_page(int ebnum)
 			ret = mtd_read_oob(mtd, addr, &ops);
 			if ((ret && !mtd_is_bitflip(ret)) ||
 					ops.oobretlen != mtd->oobsize) {
-				printk(PRINT_PREF "error: read oob failed at "
+				pr_err("error: read oob failed at "
 						  "%#llx\n", (long long)addr);
 				if (!err)
 					err = ret;
@@ -99,7 +99,7 @@ static void dump_eraseblock(int ebnum)
 	char line[128];
 	int pg, oob;
 
-	printk(PRINT_PREF "dumping eraseblock %d\n", ebnum);
+	pr_info("dumping eraseblock %d\n", ebnum);
 	n = mtd->erasesize;
 	for (i = 0; i < n;) {
 		char *p = line;
@@ -112,7 +112,7 @@ static void dump_eraseblock(int ebnum)
 	}
 	if (!mtd->oobsize)
 		return;
-	printk(PRINT_PREF "dumping oob from eraseblock %d\n", ebnum);
+	pr_info("dumping oob from eraseblock %d\n", ebnum);
 	n = mtd->oobsize;
 	for (pg = 0, i = 0; pg < pgcnt; pg++)
 		for (oob = 0; oob < n;) {
@@ -134,7 +134,7 @@ static int is_block_bad(int ebnum)
 
 	ret = mtd_block_isbad(mtd, addr);
 	if (ret)
-		printk(PRINT_PREF "block %d is bad\n", ebnum);
+		pr_info("block %d is bad\n", ebnum);
 	return ret;
 }
 
@@ -144,21 +144,21 @@ static int scan_for_bad_eraseblocks(void)
 
 	bbt = kzalloc(ebcnt, GFP_KERNEL);
 	if (!bbt) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		return -ENOMEM;
 	}
 
 	if (!mtd_can_have_bb(mtd))
 		return 0;
 
-	printk(PRINT_PREF "scanning for bad eraseblocks\n");
+	pr_info("scanning for bad eraseblocks\n");
 	for (i = 0; i < ebcnt; ++i) {
 		bbt[i] = is_block_bad(i) ? 1 : 0;
 		if (bbt[i])
 			bad += 1;
 		cond_resched();
 	}
-	printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+	pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
 	return 0;
 }
 
@@ -171,21 +171,21 @@ static int __init mtd_readtest_init(void)
 	printk(KERN_INFO "=================================================\n");
 
 	if (dev < 0) {
-		printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
+		pr_info("Please specify a valid mtd-device via module parameter\n");
 		return -EINVAL;
 	}
 
-	printk(PRINT_PREF "MTD device: %d\n", dev);
+	pr_info("MTD device: %d\n", dev);
 
 	mtd = get_mtd_device(NULL, dev);
 	if (IS_ERR(mtd)) {
 		err = PTR_ERR(mtd);
-		printk(PRINT_PREF "error: Cannot get MTD device\n");
+		pr_err("error: Cannot get MTD device\n");
 		return err;
 	}
 
 	if (mtd->writesize == 1) {
-		printk(PRINT_PREF "not NAND flash, assume page size is 512 "
+		pr_info("not NAND flash, assume page size is 512 "
 		       "bytes.\n");
 		pgsize = 512;
 	} else
@@ -196,7 +196,7 @@ static int __init mtd_readtest_init(void)
 	ebcnt = tmp;
 	pgcnt = mtd->erasesize / pgsize;
 
-	printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+	pr_info("MTD device size %llu, eraseblock size %u, "
 	       "page size %u, count of eraseblocks %u, pages per "
 	       "eraseblock %u, OOB size %u\n",
 	       (unsigned long long)mtd->size, mtd->erasesize,
@@ -205,12 +205,12 @@ static int __init mtd_readtest_init(void)
 	err = -ENOMEM;
 	iobuf = kmalloc(mtd->erasesize, GFP_KERNEL);
 	if (!iobuf) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		goto out;
 	}
 	iobuf1 = kmalloc(mtd->erasesize, GFP_KERNEL);
 	if (!iobuf1) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		goto out;
 	}
 
@@ -219,7 +219,7 @@ static int __init mtd_readtest_init(void)
 		goto out;
 
 	/* Read all eraseblocks 1 page at a time */
-	printk(PRINT_PREF "testing page read\n");
+	pr_info("testing page read\n");
 	for (i = 0; i < ebcnt; ++i) {
 		int ret;
 
@@ -235,9 +235,9 @@ static int __init mtd_readtest_init(void)
 	}
 
 	if (err)
-		printk(PRINT_PREF "finished with errors\n");
+		pr_info("finished with errors\n");
 	else
-		printk(PRINT_PREF "finished\n");
+		pr_info("finished\n");
 
 out:
 
@@ -246,7 +246,7 @@ out:
 	kfree(bbt);
 	put_mtd_device(mtd);
 	if (err)
-		printk(PRINT_PREF "error %d occurred\n", err);
+		pr_info("error %d occurred\n", err);
 	printk(KERN_INFO "=================================================\n");
 	return err;
 }
diff --git a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/mtd_speedtest.c
index 42b0f74..a6ce9c1 100644
--- a/drivers/mtd/tests/mtd_speedtest.c
+++ b/drivers/mtd/tests/mtd_speedtest.c
@@ -19,6 +19,8 @@
  * Author: Adrian Hunter <adrian.hunter@nokia.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -28,8 +30,6 @@
 #include <linux/sched.h>
 #include <linux/random.h>
 
-#define PRINT_PREF KERN_INFO "mtd_speedtest: "
-
 static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -49,13 +49,6 @@ static int pgcnt;
 static int goodebcnt;
 static struct timeval start, finish;
 
-static void set_random_data(unsigned char *buf, size_t len)
-{
-	size_t i;
-
-	for (i = 0; i < len; ++i)
-		buf[i] = random32();
-}
 
 static int erase_eraseblock(int ebnum)
 {
@@ -70,12 +63,12 @@ static int erase_eraseblock(int ebnum)
 
 	err = mtd_erase(mtd, &ei);
 	if (err) {
-		printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+		pr_err("error %d while erasing EB %d\n", err, ebnum);
 		return err;
 	}
 
 	if (ei.state == MTD_ERASE_FAILED) {
-		printk(PRINT_PREF "some erase error occurred at EB %d\n",
+		pr_err("some erase error occurred at EB %d\n",
 		       ebnum);
 		return -EIO;
 	}
@@ -96,13 +89,13 @@ static int multiblock_erase(int ebnum, int blocks)
 
 	err = mtd_erase(mtd, &ei);
 	if (err) {
-		printk(PRINT_PREF "error %d while erasing EB %d, blocks %d\n",
+		pr_err("error %d while erasing EB %d, blocks %d\n",
 		       err, ebnum, blocks);
 		return err;
 	}
 
 	if (ei.state == MTD_ERASE_FAILED) {
-		printk(PRINT_PREF "some erase error occurred at EB %d,"
+		pr_err("some erase error occurred at EB %d,"
 		       "blocks %d\n", ebnum, blocks);
 		return -EIO;
 	}
@@ -134,7 +127,7 @@ static int write_eraseblock(int ebnum)
 
 	err = mtd_write(mtd, addr, mtd->erasesize, &written, iobuf);
 	if (err || written != mtd->erasesize) {
-		printk(PRINT_PREF "error: write failed at %#llx\n", addr);
+		pr_err("error: write failed at %#llx\n", addr);
 		if (!err)
 			err = -EINVAL;
 	}
@@ -152,7 +145,7 @@ static int write_eraseblock_by_page(int ebnum)
 	for (i = 0; i < pgcnt; i++) {
 		err = mtd_write(mtd, addr, pgsize, &written, buf);
 		if (err || written != pgsize) {
-			printk(PRINT_PREF "error: write failed at %#llx\n",
+			pr_err("error: write failed at %#llx\n",
 			       addr);
 			if (!err)
 				err = -EINVAL;
@@ -175,7 +168,7 @@ static int write_eraseblock_by_2pages(int ebnum)
 	for (i = 0; i < n; i++) {
 		err = mtd_write(mtd, addr, sz, &written, buf);
 		if (err || written != sz) {
-			printk(PRINT_PREF "error: write failed at %#llx\n",
+			pr_err("error: write failed at %#llx\n",
 			       addr);
 			if (!err)
 				err = -EINVAL;
@@ -187,7 +180,7 @@ static int write_eraseblock_by_2pages(int ebnum)
 	if (pgcnt % 2) {
 		err = mtd_write(mtd, addr, pgsize, &written, buf);
 		if (err || written != pgsize) {
-			printk(PRINT_PREF "error: write failed at %#llx\n",
+			pr_err("error: write failed at %#llx\n",
 			       addr);
 			if (!err)
 				err = -EINVAL;
@@ -208,7 +201,7 @@ static int read_eraseblock(int ebnum)
 	if (mtd_is_bitflip(err))
 		err = 0;
 	if (err || read != mtd->erasesize) {
-		printk(PRINT_PREF "error: read failed at %#llx\n", addr);
+		pr_err("error: read failed at %#llx\n", addr);
 		if (!err)
 			err = -EINVAL;
 	}
@@ -229,7 +222,7 @@ static int read_eraseblock_by_page(int ebnum)
 		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != pgsize) {
-			printk(PRINT_PREF "error: read failed at %#llx\n",
+			pr_err("error: read failed at %#llx\n",
 			       addr);
 			if (!err)
 				err = -EINVAL;
@@ -255,7 +248,7 @@ static int read_eraseblock_by_2pages(int ebnum)
 		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != sz) {
-			printk(PRINT_PREF "error: read failed at %#llx\n",
+			pr_err("error: read failed at %#llx\n",
 			       addr);
 			if (!err)
 				err = -EINVAL;
@@ -270,7 +263,7 @@ static int read_eraseblock_by_2pages(int ebnum)
 		if (mtd_is_bitflip(err))
 			err = 0;
 		if (err || read != pgsize) {
-			printk(PRINT_PREF "error: read failed at %#llx\n",
+			pr_err("error: read failed at %#llx\n",
 			       addr);
 			if (!err)
 				err = -EINVAL;
@@ -287,7 +280,7 @@ static int is_block_bad(int ebnum)
 
 	ret = mtd_block_isbad(mtd, addr);
 	if (ret)
-		printk(PRINT_PREF "block %d is bad\n", ebnum);
+		pr_info("block %d is bad\n", ebnum);
 	return ret;
 }
 
@@ -321,21 +314,21 @@ static int scan_for_bad_eraseblocks(void)
 
 	bbt = kzalloc(ebcnt, GFP_KERNEL);
 	if (!bbt) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		return -ENOMEM;
 	}
 
 	if (!mtd_can_have_bb(mtd))
 		goto out;
 
-	printk(PRINT_PREF "scanning for bad eraseblocks\n");
+	pr_info("scanning for bad eraseblocks\n");
 	for (i = 0; i < ebcnt; ++i) {
 		bbt[i] = is_block_bad(i) ? 1 : 0;
 		if (bbt[i])
 			bad += 1;
 		cond_resched();
 	}
-	printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+	pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
 out:
 	goodebcnt = ebcnt - bad;
 	return 0;
@@ -351,25 +344,25 @@ static int __init mtd_speedtest_init(void)
 	printk(KERN_INFO "=================================================\n");
 
 	if (dev < 0) {
-		printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
-		printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+		pr_info("Please specify a valid mtd-device via module parameter\n");
+		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
 		return -EINVAL;
 	}
 
 	if (count)
-		printk(PRINT_PREF "MTD device: %d    count: %d\n", dev, count);
+		pr_info("MTD device: %d    count: %d\n", dev, count);
 	else
-		printk(PRINT_PREF "MTD device: %d\n", dev);
+		pr_info("MTD device: %d\n", dev);
 
 	mtd = get_mtd_device(NULL, dev);
 	if (IS_ERR(mtd)) {
 		err = PTR_ERR(mtd);
-		printk(PRINT_PREF "error: cannot get MTD device\n");
+		pr_err("error: cannot get MTD device\n");
 		return err;
 	}
 
 	if (mtd->writesize == 1) {
-		printk(PRINT_PREF "not NAND flash, assume page size is 512 "
+		pr_info("not NAND flash, assume page size is 512 "
 		       "bytes.\n");
 		pgsize = 512;
 	} else
@@ -380,7 +373,7 @@ static int __init mtd_speedtest_init(void)
 	ebcnt = tmp;
 	pgcnt = mtd->erasesize / pgsize;
 
-	printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+	pr_info("MTD device size %llu, eraseblock size %u, "
 	       "page size %u, count of eraseblocks %u, pages per "
 	       "eraseblock %u, OOB size %u\n",
 	       (unsigned long long)mtd->size, mtd->erasesize,
@@ -392,11 +385,11 @@ static int __init mtd_speedtest_init(void)
 	err = -ENOMEM;
 	iobuf = kmalloc(mtd->erasesize, GFP_KERNEL);
 	if (!iobuf) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		goto out;
 	}
 
-	set_random_data(iobuf, mtd->erasesize);
+	prandom_bytes(iobuf, mtd->erasesize);
 
 	err = scan_for_bad_eraseblocks();
 	if (err)
@@ -407,7 +400,7 @@ static int __init mtd_speedtest_init(void)
 		goto out;
 
 	/* Write all eraseblocks, 1 eraseblock at a time */
-	printk(PRINT_PREF "testing eraseblock write speed\n");
+	pr_info("testing eraseblock write speed\n");
 	start_timing();
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
@@ -419,10 +412,10 @@ static int __init mtd_speedtest_init(void)
 	}
 	stop_timing();
 	speed = calc_speed();
-	printk(PRINT_PREF "eraseblock write speed is %ld KiB/s\n", speed);
+	pr_info("eraseblock write speed is %ld KiB/s\n", speed);
 
 	/* Read all eraseblocks, 1 eraseblock at a time */
-	printk(PRINT_PREF "testing eraseblock read speed\n");
+	pr_info("testing eraseblock read speed\n");
 	start_timing();
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
@@ -434,14 +427,14 @@ static int __init mtd_speedtest_init(void)
 	}
 	stop_timing();
 	speed = calc_speed();
-	printk(PRINT_PREF "eraseblock read speed is %ld KiB/s\n", speed);
+	pr_info("eraseblock read speed is %ld KiB/s\n", speed);
 
 	err = erase_whole_device();
 	if (err)
 		goto out;
 
 	/* Write all eraseblocks, 1 page at a time */
-	printk(PRINT_PREF "testing page write speed\n");
+	pr_info("testing page write speed\n");
 	start_timing();
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
@@ -453,10 +446,10 @@ static int __init mtd_speedtest_init(void)
 	}
 	stop_timing();
 	speed = calc_speed();
-	printk(PRINT_PREF "page write speed is %ld KiB/s\n", speed);
+	pr_info("page write speed is %ld KiB/s\n", speed);
 
 	/* Read all eraseblocks, 1 page at a time */
-	printk(PRINT_PREF "testing page read speed\n");
+	pr_info("testing page read speed\n");
 	start_timing();
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
@@ -468,14 +461,14 @@ static int __init mtd_speedtest_init(void)
 	}
 	stop_timing();
 	speed = calc_speed();
-	printk(PRINT_PREF "page read speed is %ld KiB/s\n", speed);
+	pr_info("page read speed is %ld KiB/s\n", speed);
 
 	err = erase_whole_device();
 	if (err)
 		goto out;
 
 	/* Write all eraseblocks, 2 pages at a time */
-	printk(PRINT_PREF "testing 2 page write speed\n");
+	pr_info("testing 2 page write speed\n");
 	start_timing();
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
@@ -487,10 +480,10 @@ static int __init mtd_speedtest_init(void)
 	}
 	stop_timing();
 	speed = calc_speed();
-	printk(PRINT_PREF "2 page write speed is %ld KiB/s\n", speed);
+	pr_info("2 page write speed is %ld KiB/s\n", speed);
 
 	/* Read all eraseblocks, 2 pages at a time */
-	printk(PRINT_PREF "testing 2 page read speed\n");
+	pr_info("testing 2 page read speed\n");
 	start_timing();
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
@@ -502,10 +495,10 @@ static int __init mtd_speedtest_init(void)
 	}
 	stop_timing();
 	speed = calc_speed();
-	printk(PRINT_PREF "2 page read speed is %ld KiB/s\n", speed);
+	pr_info("2 page read speed is %ld KiB/s\n", speed);
 
 	/* Erase all eraseblocks */
-	printk(PRINT_PREF "Testing erase speed\n");
+	pr_info("Testing erase speed\n");
 	start_timing();
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
@@ -517,12 +510,12 @@ static int __init mtd_speedtest_init(void)
 	}
 	stop_timing();
 	speed = calc_speed();
-	printk(PRINT_PREF "erase speed is %ld KiB/s\n", speed);
+	pr_info("erase speed is %ld KiB/s\n", speed);
 
 	/* Multi-block erase all eraseblocks */
 	for (k = 1; k < 7; k++) {
 		blocks = 1 << k;
-		printk(PRINT_PREF "Testing %dx multi-block erase speed\n",
+		pr_info("Testing %dx multi-block erase speed\n",
 		       blocks);
 		start_timing();
 		for (i = 0; i < ebcnt; ) {
@@ -541,16 +534,16 @@ static int __init mtd_speedtest_init(void)
 		}
 		stop_timing();
 		speed = calc_speed();
-		printk(PRINT_PREF "%dx multi-block erase speed is %ld KiB/s\n",
+		pr_info("%dx multi-block erase speed is %ld KiB/s\n",
 		       blocks, speed);
 	}
-	printk(PRINT_PREF "finished\n");
+	pr_info("finished\n");
 out:
 	kfree(iobuf);
 	kfree(bbt);
 	put_mtd_device(mtd);
 	if (err)
-		printk(PRINT_PREF "error %d occurred\n", err);
+		pr_info("error %d occurred\n", err);
 	printk(KERN_INFO "=================================================\n");
 	return err;
 }
diff --git a/drivers/mtd/tests/mtd_stresstest.c b/drivers/mtd/tests/mtd_stresstest.c
index cb268ce..2d7e6cf 100644
--- a/drivers/mtd/tests/mtd_stresstest.c
+++ b/drivers/mtd/tests/mtd_stresstest.c
@@ -19,6 +19,8 @@
  * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -29,8 +31,6 @@
 #include <linux/vmalloc.h>
 #include <linux/random.h>
 
-#define PRINT_PREF KERN_INFO "mtd_stresstest: "
-
 static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
@@ -94,12 +94,12 @@ static int erase_eraseblock(int ebnum)
 
 	err = mtd_erase(mtd, &ei);
 	if (unlikely(err)) {
-		printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+		pr_err("error %d while erasing EB %d\n", err, ebnum);
 		return err;
 	}
 
 	if (unlikely(ei.state == MTD_ERASE_FAILED)) {
-		printk(PRINT_PREF "some erase error occurred at EB %d\n",
+		pr_err("some erase error occurred at EB %d\n",
 		       ebnum);
 		return -EIO;
 	}
@@ -114,7 +114,7 @@ static int is_block_bad(int ebnum)
 
 	ret = mtd_block_isbad(mtd, addr);
 	if (ret)
-		printk(PRINT_PREF "block %d is bad\n", ebnum);
+		pr_info("block %d is bad\n", ebnum);
 	return ret;
 }
 
@@ -137,7 +137,7 @@ static int do_read(void)
 	if (mtd_is_bitflip(err))
 		err = 0;
 	if (unlikely(err || read != len)) {
-		printk(PRINT_PREF "error: read failed at 0x%llx\n",
+		pr_err("error: read failed at 0x%llx\n",
 		       (long long)addr);
 		if (!err)
 			err = -EINVAL;
@@ -174,7 +174,7 @@ static int do_write(void)
 	addr = eb * mtd->erasesize + offs;
 	err = mtd_write(mtd, addr, len, &written, writebuf);
 	if (unlikely(err || written != len)) {
-		printk(PRINT_PREF "error: write failed at 0x%llx\n",
+		pr_err("error: write failed at 0x%llx\n",
 		       (long long)addr);
 		if (!err)
 			err = -EINVAL;
@@ -203,21 +203,21 @@ static int scan_for_bad_eraseblocks(void)
 
 	bbt = kzalloc(ebcnt, GFP_KERNEL);
 	if (!bbt) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		return -ENOMEM;
 	}
 
 	if (!mtd_can_have_bb(mtd))
 		return 0;
 
-	printk(PRINT_PREF "scanning for bad eraseblocks\n");
+	pr_info("scanning for bad eraseblocks\n");
 	for (i = 0; i < ebcnt; ++i) {
 		bbt[i] = is_block_bad(i) ? 1 : 0;
 		if (bbt[i])
 			bad += 1;
 		cond_resched();
 	}
-	printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+	pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
 	return 0;
 }
 
@@ -231,22 +231,22 @@ static int __init mtd_stresstest_init(void)
 	printk(KERN_INFO "=================================================\n");
 
 	if (dev < 0) {
-		printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
-		printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+		pr_info("Please specify a valid mtd-device via module parameter\n");
+		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
 		return -EINVAL;
 	}
 
-	printk(PRINT_PREF "MTD device: %d\n", dev);
+	pr_info("MTD device: %d\n", dev);
 
 	mtd = get_mtd_device(NULL, dev);
 	if (IS_ERR(mtd)) {
 		err = PTR_ERR(mtd);
-		printk(PRINT_PREF "error: cannot get MTD device\n");
+		pr_err("error: cannot get MTD device\n");
 		return err;
 	}
 
 	if (mtd->writesize == 1) {
-		printk(PRINT_PREF "not NAND flash, assume page size is 512 "
+		pr_info("not NAND flash, assume page size is 512 "
 		       "bytes.\n");
 		pgsize = 512;
 	} else
@@ -257,14 +257,14 @@ static int __init mtd_stresstest_init(void)
 	ebcnt = tmp;
 	pgcnt = mtd->erasesize / pgsize;
 
-	printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+	pr_info("MTD device size %llu, eraseblock size %u, "
 	       "page size %u, count of eraseblocks %u, pages per "
 	       "eraseblock %u, OOB size %u\n",
 	       (unsigned long long)mtd->size, mtd->erasesize,
 	       pgsize, ebcnt, pgcnt, mtd->oobsize);
 
 	if (ebcnt < 2) {
-		printk(PRINT_PREF "error: need at least 2 eraseblocks\n");
+		pr_err("error: need at least 2 eraseblocks\n");
 		err = -ENOSPC;
 		goto out_put_mtd;
 	}
@@ -277,29 +277,28 @@ static int __init mtd_stresstest_init(void)
 	writebuf = vmalloc(bufsize);
 	offsets = kmalloc(ebcnt * sizeof(int), GFP_KERNEL);
 	if (!readbuf || !writebuf || !offsets) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		goto out;
 	}
 	for (i = 0; i < ebcnt; i++)
 		offsets[i] = mtd->erasesize;
-	for (i = 0; i < bufsize; i++)
-		writebuf[i] = random32();
+	prandom_bytes(writebuf, bufsize);
 
 	err = scan_for_bad_eraseblocks();
 	if (err)
 		goto out;
 
 	/* Do operations */
-	printk(PRINT_PREF "doing operations\n");
+	pr_info("doing operations\n");
 	for (op = 0; op < count; op++) {
 		if ((op & 1023) == 0)
-			printk(PRINT_PREF "%d operations done\n", op);
+			pr_info("%d operations done\n", op);
 		err = do_operation();
 		if (err)
 			goto out;
 		cond_resched();
 	}
-	printk(PRINT_PREF "finished, %d operations done\n", op);
+	pr_info("finished, %d operations done\n", op);
 
 out:
 	kfree(offsets);
@@ -309,7 +308,7 @@ out:
 out_put_mtd:
 	put_mtd_device(mtd);
 	if (err)
-		printk(PRINT_PREF "error %d occurred\n", err);
+		pr_info("error %d occurred\n", err);
 	printk(KERN_INFO "=================================================\n");
 	return err;
 }
diff --git a/drivers/mtd/tests/mtd_subpagetest.c b/drivers/mtd/tests/mtd_subpagetest.c
index 9667bf5..aade56f 100644
--- a/drivers/mtd/tests/mtd_subpagetest.c
+++ b/drivers/mtd/tests/mtd_subpagetest.c
@@ -19,6 +19,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -26,8 +28,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
-
-#define PRINT_PREF KERN_INFO "mtd_subpagetest: "
+#include <linux/random.h>
 
 static int dev = -EINVAL;
 module_param(dev, int, S_IRUGO);
@@ -43,26 +44,7 @@ static int bufsize;
 static int ebcnt;
 static int pgcnt;
 static int errcnt;
-static unsigned long next = 1;
-
-static inline unsigned int simple_rand(void)
-{
-	next = next * 1103515245 + 12345;
-	return (unsigned int)((next / 65536) % 32768);
-}
-
-static inline void simple_srand(unsigned long seed)
-{
-	next = seed;
-}
-
-static void set_random_data(unsigned char *buf, size_t len)
-{
-	size_t i;
-
-	for (i = 0; i < len; ++i)
-		buf[i] = simple_rand();
-}
+static struct rnd_state rnd_state;
 
 static inline void clear_data(unsigned char *buf, size_t len)
 {
@@ -82,12 +64,12 @@ static int erase_eraseblock(int ebnum)
 
 	err = mtd_erase(mtd, &ei);
 	if (err) {
-		printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+		pr_err("error %d while erasing EB %d\n", err, ebnum);
 		return err;
 	}
 
 	if (ei.state == MTD_ERASE_FAILED) {
-		printk(PRINT_PREF "some erase error occurred at EB %d\n",
+		pr_err("some erase error occurred at EB %d\n",
 		       ebnum);
 		return -EIO;
 	}
@@ -100,7 +82,7 @@ static int erase_whole_device(void)
 	int err;
 	unsigned int i;
 
-	printk(PRINT_PREF "erasing whole device\n");
+	pr_info("erasing whole device\n");
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
 			continue;
@@ -109,7 +91,7 @@ static int erase_whole_device(void)
 			return err;
 		cond_resched();
 	}
-	printk(PRINT_PREF "erased %u eraseblocks\n", i);
+	pr_info("erased %u eraseblocks\n", i);
 	return 0;
 }
 
@@ -119,28 +101,28 @@ static int write_eraseblock(int ebnum)
 	int err = 0;
 	loff_t addr = ebnum * mtd->erasesize;
 
-	set_random_data(writebuf, subpgsize);
+	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
 	err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
 	if (unlikely(err || written != subpgsize)) {
-		printk(PRINT_PREF "error: write failed at %#llx\n",
+		pr_err("error: write failed at %#llx\n",
 		       (long long)addr);
 		if (written != subpgsize) {
-			printk(PRINT_PREF "  write size: %#x\n", subpgsize);
-			printk(PRINT_PREF "  written: %#zx\n", written);
+			pr_err("  write size: %#x\n", subpgsize);
+			pr_err("  written: %#zx\n", written);
 		}
 		return err ? err : -1;
 	}
 
 	addr += subpgsize;
 
-	set_random_data(writebuf, subpgsize);
+	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
 	err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
 	if (unlikely(err || written != subpgsize)) {
-		printk(PRINT_PREF "error: write failed at %#llx\n",
+		pr_err("error: write failed at %#llx\n",
 		       (long long)addr);
 		if (written != subpgsize) {
-			printk(PRINT_PREF "  write size: %#x\n", subpgsize);
-			printk(PRINT_PREF "  written: %#zx\n", written);
+			pr_err("  write size: %#x\n", subpgsize);
+			pr_err("  written: %#zx\n", written);
 		}
 		return err ? err : -1;
 	}
@@ -157,15 +139,15 @@ static int write_eraseblock2(int ebnum)
 	for (k = 1; k < 33; ++k) {
 		if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
 			break;
-		set_random_data(writebuf, subpgsize * k);
+		prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);
 		err = mtd_write(mtd, addr, subpgsize * k, &written, writebuf);
 		if (unlikely(err || written != subpgsize * k)) {
-			printk(PRINT_PREF "error: write failed at %#llx\n",
+			pr_err("error: write failed at %#llx\n",
 			       (long long)addr);
 			if (written != subpgsize) {
-				printk(PRINT_PREF "  write size: %#x\n",
+				pr_err("  write size: %#x\n",
 				       subpgsize * k);
-				printk(PRINT_PREF "  written: %#08zx\n",
+				pr_err("  written: %#08zx\n",
 				       written);
 			}
 			return err ? err : -1;
@@ -193,55 +175,55 @@ static int verify_eraseblock(int ebnum)
 	int err = 0;
 	loff_t addr = ebnum * mtd->erasesize;
 
-	set_random_data(writebuf, subpgsize);
+	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
 	clear_data(readbuf, subpgsize);
 	err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
 	if (unlikely(err || read != subpgsize)) {
 		if (mtd_is_bitflip(err) && read == subpgsize) {
-			printk(PRINT_PREF "ECC correction at %#llx\n",
+			pr_info("ECC correction at %#llx\n",
 			       (long long)addr);
 			err = 0;
 		} else {
-			printk(PRINT_PREF "error: read failed at %#llx\n",
+			pr_err("error: read failed at %#llx\n",
 			       (long long)addr);
 			return err ? err : -1;
 		}
 	}
 	if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
-		printk(PRINT_PREF "error: verify failed at %#llx\n",
+		pr_err("error: verify failed at %#llx\n",
 		       (long long)addr);
-		printk(PRINT_PREF "------------- written----------------\n");
+		pr_info("------------- written----------------\n");
 		print_subpage(writebuf);
-		printk(PRINT_PREF "------------- read ------------------\n");
+		pr_info("------------- read ------------------\n");
 		print_subpage(readbuf);
-		printk(PRINT_PREF "-------------------------------------\n");
+		pr_info("-------------------------------------\n");
 		errcnt += 1;
 	}
 
 	addr += subpgsize;
 
-	set_random_data(writebuf, subpgsize);
+	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
 	clear_data(readbuf, subpgsize);
 	err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
 	if (unlikely(err || read != subpgsize)) {
 		if (mtd_is_bitflip(err) && read == subpgsize) {
-			printk(PRINT_PREF "ECC correction at %#llx\n",
+			pr_info("ECC correction at %#llx\n",
 			       (long long)addr);
 			err = 0;
 		} else {
-			printk(PRINT_PREF "error: read failed at %#llx\n",
+			pr_err("error: read failed at %#llx\n",
 			       (long long)addr);
 			return err ? err : -1;
 		}
 	}
 	if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
-		printk(PRINT_PREF "error: verify failed at %#llx\n",
+		pr_info("error: verify failed at %#llx\n",
 		       (long long)addr);
-		printk(PRINT_PREF "------------- written----------------\n");
+		pr_info("------------- written----------------\n");
 		print_subpage(writebuf);
-		printk(PRINT_PREF "------------- read ------------------\n");
+		pr_info("------------- read ------------------\n");
 		print_subpage(readbuf);
-		printk(PRINT_PREF "-------------------------------------\n");
+		pr_info("-------------------------------------\n");
 		errcnt += 1;
 	}
 
@@ -257,22 +239,22 @@ static int verify_eraseblock2(int ebnum)
 	for (k = 1; k < 33; ++k) {
 		if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
 			break;
-		set_random_data(writebuf, subpgsize * k);
+		prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);
 		clear_data(readbuf, subpgsize * k);
 		err = mtd_read(mtd, addr, subpgsize * k, &read, readbuf);
 		if (unlikely(err || read != subpgsize * k)) {
 			if (mtd_is_bitflip(err) && read == subpgsize * k) {
-				printk(PRINT_PREF "ECC correction at %#llx\n",
+				pr_info("ECC correction at %#llx\n",
 				       (long long)addr);
 				err = 0;
 			} else {
-				printk(PRINT_PREF "error: read failed at "
+				pr_err("error: read failed at "
 				       "%#llx\n", (long long)addr);
 				return err ? err : -1;
 			}
 		}
 		if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) {
-			printk(PRINT_PREF "error: verify failed at %#llx\n",
+			pr_err("error: verify failed at %#llx\n",
 			       (long long)addr);
 			errcnt += 1;
 		}
@@ -295,17 +277,17 @@ static int verify_eraseblock_ff(int ebnum)
 		err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
 		if (unlikely(err || read != subpgsize)) {
 			if (mtd_is_bitflip(err) && read == subpgsize) {
-				printk(PRINT_PREF "ECC correction at %#llx\n",
+				pr_info("ECC correction at %#llx\n",
 				       (long long)addr);
 				err = 0;
 			} else {
-				printk(PRINT_PREF "error: read failed at "
+				pr_err("error: read failed at "
 				       "%#llx\n", (long long)addr);
 				return err ? err : -1;
 			}
 		}
 		if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
-			printk(PRINT_PREF "error: verify 0xff failed at "
+			pr_err("error: verify 0xff failed at "
 			       "%#llx\n", (long long)addr);
 			errcnt += 1;
 		}
@@ -320,7 +302,7 @@ static int verify_all_eraseblocks_ff(void)
 	int err;
 	unsigned int i;
 
-	printk(PRINT_PREF "verifying all eraseblocks for 0xff\n");
+	pr_info("verifying all eraseblocks for 0xff\n");
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
 			continue;
@@ -328,10 +310,10 @@ static int verify_all_eraseblocks_ff(void)
 		if (err)
 			return err;
 		if (i % 256 == 0)
-			printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+			pr_info("verified up to eraseblock %u\n", i);
 		cond_resched();
 	}
-	printk(PRINT_PREF "verified %u eraseblocks\n", i);
+	pr_info("verified %u eraseblocks\n", i);
 	return 0;
 }
 
@@ -342,7 +324,7 @@ static int is_block_bad(int ebnum)
 
 	ret = mtd_block_isbad(mtd, addr);
 	if (ret)
-		printk(PRINT_PREF "block %d is bad\n", ebnum);
+		pr_info("block %d is bad\n", ebnum);
 	return ret;
 }
 
@@ -352,18 +334,18 @@ static int scan_for_bad_eraseblocks(void)
 
 	bbt = kzalloc(ebcnt, GFP_KERNEL);
 	if (!bbt) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		return -ENOMEM;
 	}
 
-	printk(PRINT_PREF "scanning for bad eraseblocks\n");
+	pr_info("scanning for bad eraseblocks\n");
 	for (i = 0; i < ebcnt; ++i) {
 		bbt[i] = is_block_bad(i) ? 1 : 0;
 		if (bbt[i])
 			bad += 1;
 		cond_resched();
 	}
-	printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+	pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
 	return 0;
 }
 
@@ -377,22 +359,22 @@ static int __init mtd_subpagetest_init(void)
 	printk(KERN_INFO "=================================================\n");
 
 	if (dev < 0) {
-		printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
-		printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+		pr_info("Please specify a valid mtd-device via module parameter\n");
+		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
 		return -EINVAL;
 	}
 
-	printk(PRINT_PREF "MTD device: %d\n", dev);
+	pr_info("MTD device: %d\n", dev);
 
 	mtd = get_mtd_device(NULL, dev);
 	if (IS_ERR(mtd)) {
 		err = PTR_ERR(mtd);
-		printk(PRINT_PREF "error: cannot get MTD device\n");
+		pr_err("error: cannot get MTD device\n");
 		return err;
 	}
 
 	if (mtd->type != MTD_NANDFLASH) {
-		printk(PRINT_PREF "this test requires NAND flash\n");
+		pr_info("this test requires NAND flash\n");
 		goto out;
 	}
 
@@ -402,7 +384,7 @@ static int __init mtd_subpagetest_init(void)
 	ebcnt = tmp;
 	pgcnt = mtd->erasesize / mtd->writesize;
 
-	printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+	pr_info("MTD device size %llu, eraseblock size %u, "
 	       "page size %u, subpage size %u, count of eraseblocks %u, "
 	       "pages per eraseblock %u, OOB size %u\n",
 	       (unsigned long long)mtd->size, mtd->erasesize,
@@ -412,12 +394,12 @@ static int __init mtd_subpagetest_init(void)
 	bufsize = subpgsize * 32;
 	writebuf = kmalloc(bufsize, GFP_KERNEL);
 	if (!writebuf) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_info("error: cannot allocate memory\n");
 		goto out;
 	}
 	readbuf = kmalloc(bufsize, GFP_KERNEL);
 	if (!readbuf) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_info("error: cannot allocate memory\n");
 		goto out;
 	}
 
@@ -429,8 +411,8 @@ static int __init mtd_subpagetest_init(void)
 	if (err)
 		goto out;
 
-	printk(PRINT_PREF "writing whole device\n");
-	simple_srand(1);
+	pr_info("writing whole device\n");
+	prandom_seed_state(&rnd_state, 1);
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
 			continue;
@@ -438,13 +420,13 @@ static int __init mtd_subpagetest_init(void)
 		if (unlikely(err))
 			goto out;
 		if (i % 256 == 0)
-			printk(PRINT_PREF "written up to eraseblock %u\n", i);
+			pr_info("written up to eraseblock %u\n", i);
 		cond_resched();
 	}
-	printk(PRINT_PREF "written %u eraseblocks\n", i);
+	pr_info("written %u eraseblocks\n", i);
 
-	simple_srand(1);
-	printk(PRINT_PREF "verifying all eraseblocks\n");
+	prandom_seed_state(&rnd_state, 1);
+	pr_info("verifying all eraseblocks\n");
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
 			continue;
@@ -452,10 +434,10 @@ static int __init mtd_subpagetest_init(void)
 		if (unlikely(err))
 			goto out;
 		if (i % 256 == 0)
-			printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+			pr_info("verified up to eraseblock %u\n", i);
 		cond_resched();
 	}
-	printk(PRINT_PREF "verified %u eraseblocks\n", i);
+	pr_info("verified %u eraseblocks\n", i);
 
 	err = erase_whole_device();
 	if (err)
@@ -466,8 +448,8 @@ static int __init mtd_subpagetest_init(void)
 		goto out;
 
 	/* Write all eraseblocks */
-	simple_srand(3);
-	printk(PRINT_PREF "writing whole device\n");
+	prandom_seed_state(&rnd_state, 3);
+	pr_info("writing whole device\n");
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
 			continue;
@@ -475,14 +457,14 @@ static int __init mtd_subpagetest_init(void)
 		if (unlikely(err))
 			goto out;
 		if (i % 256 == 0)
-			printk(PRINT_PREF "written up to eraseblock %u\n", i);
+			pr_info("written up to eraseblock %u\n", i);
 		cond_resched();
 	}
-	printk(PRINT_PREF "written %u eraseblocks\n", i);
+	pr_info("written %u eraseblocks\n", i);
 
 	/* Check all eraseblocks */
-	simple_srand(3);
-	printk(PRINT_PREF "verifying all eraseblocks\n");
+	prandom_seed_state(&rnd_state, 3);
+	pr_info("verifying all eraseblocks\n");
 	for (i = 0; i < ebcnt; ++i) {
 		if (bbt[i])
 			continue;
@@ -490,10 +472,10 @@ static int __init mtd_subpagetest_init(void)
 		if (unlikely(err))
 			goto out;
 		if (i % 256 == 0)
-			printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+			pr_info("verified up to eraseblock %u\n", i);
 		cond_resched();
 	}
-	printk(PRINT_PREF "verified %u eraseblocks\n", i);
+	pr_info("verified %u eraseblocks\n", i);
 
 	err = erase_whole_device();
 	if (err)
@@ -503,7 +485,7 @@ static int __init mtd_subpagetest_init(void)
 	if (err)
 		goto out;
 
-	printk(PRINT_PREF "finished with %d errors\n", errcnt);
+	pr_info("finished with %d errors\n", errcnt);
 
 out:
 	kfree(bbt);
@@ -511,7 +493,7 @@ out:
 	kfree(writebuf);
 	put_mtd_device(mtd);
 	if (err)
-		printk(PRINT_PREF "error %d occurred\n", err);
+		pr_info("error %d occurred\n", err);
 	printk(KERN_INFO "=================================================\n");
 	return err;
 }
diff --git a/drivers/mtd/tests/mtd_torturetest.c b/drivers/mtd/tests/mtd_torturetest.c
index b65861b..c4cde1e 100644
--- a/drivers/mtd/tests/mtd_torturetest.c
+++ b/drivers/mtd/tests/mtd_torturetest.c
@@ -23,6 +23,8 @@
  * damage caused by this program.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -31,7 +33,6 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 
-#define PRINT_PREF KERN_INFO "mtd_torturetest: "
 #define RETRIES 3
 
 static int eb = 8;
@@ -107,12 +108,12 @@ static inline int erase_eraseblock(int ebnum)
 
 	err = mtd_erase(mtd, &ei);
 	if (err) {
-		printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+		pr_err("error %d while erasing EB %d\n", err, ebnum);
 		return err;
 	}
 
 	if (ei.state == MTD_ERASE_FAILED) {
-		printk(PRINT_PREF "some erase error occurred at EB %d\n",
+		pr_err("some erase error occurred at EB %d\n",
 		       ebnum);
 		return -EIO;
 	}
@@ -139,40 +140,40 @@ static inline int check_eraseblock(int ebnum, unsigned char *buf)
 retry:
 	err = mtd_read(mtd, addr, len, &read, check_buf);
 	if (mtd_is_bitflip(err))
-		printk(PRINT_PREF "single bit flip occurred at EB %d "
+		pr_err("single bit flip occurred at EB %d "
 		       "MTD reported that it was fixed.\n", ebnum);
 	else if (err) {
-		printk(PRINT_PREF "error %d while reading EB %d, "
+		pr_err("error %d while reading EB %d, "
 		       "read %zd\n", err, ebnum, read);
 		return err;
 	}
 
 	if (read != len) {
-		printk(PRINT_PREF "failed to read %zd bytes from EB %d, "
+		pr_err("failed to read %zd bytes from EB %d, "
 		       "read only %zd, but no error reported\n",
 		       len, ebnum, read);
 		return -EIO;
 	}
 
 	if (memcmp(buf, check_buf, len)) {
-		printk(PRINT_PREF "read wrong data from EB %d\n", ebnum);
+		pr_err("read wrong data from EB %d\n", ebnum);
 		report_corrupt(check_buf, buf);
 
 		if (retries++ < RETRIES) {
 			/* Try read again */
 			yield();
-			printk(PRINT_PREF "re-try reading data from EB %d\n",
+			pr_info("re-try reading data from EB %d\n",
 			       ebnum);
 			goto retry;
 		} else {
-			printk(PRINT_PREF "retried %d times, still errors, "
+			pr_info("retried %d times, still errors, "
 			       "give-up\n", RETRIES);
 			return -EINVAL;
 		}
 	}
 
 	if (retries != 0)
-		printk(PRINT_PREF "only attempt number %d was OK (!!!)\n",
+		pr_info("only attempt number %d was OK (!!!)\n",
 		       retries);
 
 	return 0;
@@ -191,12 +192,12 @@ static inline int write_pattern(int ebnum, void *buf)
 	}
 	err = mtd_write(mtd, addr, len, &written, buf);
 	if (err) {
-		printk(PRINT_PREF "error %d while writing EB %d, written %zd"
+		pr_err("error %d while writing EB %d, written %zd"
 		      " bytes\n", err, ebnum, written);
 		return err;
 	}
 	if (written != len) {
-		printk(PRINT_PREF "written only %zd bytes of %zd, but no error"
+		pr_info("written only %zd bytes of %zd, but no error"
 		       " reported\n", written, len);
 		return -EIO;
 	}
@@ -211,64 +212,64 @@ static int __init tort_init(void)
 
 	printk(KERN_INFO "\n");
 	printk(KERN_INFO "=================================================\n");
-	printk(PRINT_PREF "Warning: this program is trying to wear out your "
+	pr_info("Warning: this program is trying to wear out your "
 	       "flash, stop it if this is not wanted.\n");
 
 	if (dev < 0) {
-		printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n");
-		printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n");
+		pr_info("Please specify a valid mtd-device via module parameter\n");
+		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
 		return -EINVAL;
 	}
 
-	printk(PRINT_PREF "MTD device: %d\n", dev);
-	printk(PRINT_PREF "torture %d eraseblocks (%d-%d) of mtd%d\n",
+	pr_info("MTD device: %d\n", dev);
+	pr_info("torture %d eraseblocks (%d-%d) of mtd%d\n",
 	       ebcnt, eb, eb + ebcnt - 1, dev);
 	if (pgcnt)
-		printk(PRINT_PREF "torturing just %d pages per eraseblock\n",
+		pr_info("torturing just %d pages per eraseblock\n",
 			pgcnt);
-	printk(PRINT_PREF "write verify %s\n", check ? "enabled" : "disabled");
+	pr_info("write verify %s\n", check ? "enabled" : "disabled");
 
 	mtd = get_mtd_device(NULL, dev);
 	if (IS_ERR(mtd)) {
 		err = PTR_ERR(mtd);
-		printk(PRINT_PREF "error: cannot get MTD device\n");
+		pr_err("error: cannot get MTD device\n");
 		return err;
 	}
 
 	if (mtd->writesize == 1) {
-		printk(PRINT_PREF "not NAND flash, assume page size is 512 "
+		pr_info("not NAND flash, assume page size is 512 "
 		       "bytes.\n");
 		pgsize = 512;
 	} else
 		pgsize = mtd->writesize;
 
 	if (pgcnt && (pgcnt > mtd->erasesize / pgsize || pgcnt < 0)) {
-		printk(PRINT_PREF "error: invalid pgcnt value %d\n", pgcnt);
+		pr_err("error: invalid pgcnt value %d\n", pgcnt);
 		goto out_mtd;
 	}
 
 	err = -ENOMEM;
 	patt_5A5 = kmalloc(mtd->erasesize, GFP_KERNEL);
 	if (!patt_5A5) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		goto out_mtd;
 	}
 
 	patt_A5A = kmalloc(mtd->erasesize, GFP_KERNEL);
 	if (!patt_A5A) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		goto out_patt_5A5;
 	}
 
 	patt_FF = kmalloc(mtd->erasesize, GFP_KERNEL);
 	if (!patt_FF) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		goto out_patt_A5A;
 	}
 
 	check_buf = kmalloc(mtd->erasesize, GFP_KERNEL);
 	if (!check_buf) {
-		printk(PRINT_PREF "error: cannot allocate memory\n");
+		pr_err("error: cannot allocate memory\n");
 		goto out_patt_FF;
 	}
 
@@ -295,13 +296,13 @@ static int __init tort_init(void)
 			err = mtd_block_isbad(mtd, (loff_t)i * mtd->erasesize);
 
 			if (err < 0) {
-				printk(PRINT_PREF "block_isbad() returned %d "
+				pr_info("block_isbad() returned %d "
 				       "for EB %d\n", err, i);
 				goto out;
 			}
 
 			if (err) {
-				printk("EB %d is bad. Skip it.\n", i);
+				pr_err("EB %d is bad. Skip it.\n", i);
 				bad_ebs[i - eb] = 1;
 			}
 		}
@@ -329,7 +330,7 @@ static int __init tort_init(void)
 					continue;
 				err = check_eraseblock(i, patt_FF);
 				if (err) {
-					printk(PRINT_PREF "verify failed"
+					pr_info("verify failed"
 					       " for 0xFF... pattern\n");
 					goto out;
 				}
@@ -362,7 +363,7 @@ static int __init tort_init(void)
 					patt = patt_A5A;
 				err = check_eraseblock(i, patt);
 				if (err) {
-					printk(PRINT_PREF "verify failed for %s"
+					pr_info("verify failed for %s"
 					       " pattern\n",
 					       ((eb + erase_cycles) & 1) ?
 					       "0x55AA55..." : "0xAA55AA...");
@@ -380,7 +381,7 @@ static int __init tort_init(void)
 			stop_timing();
 			ms = (finish.tv_sec - start.tv_sec) * 1000 +
 			     (finish.tv_usec - start.tv_usec) / 1000;
-			printk(PRINT_PREF "%08u erase cycles done, took %lu "
+			pr_info("%08u erase cycles done, took %lu "
 			       "milliseconds (%lu seconds)\n",
 			       erase_cycles, ms, ms / 1000);
 			start_timing();
@@ -391,7 +392,7 @@ static int __init tort_init(void)
 	}
 out:
 
-	printk(PRINT_PREF "finished after %u erase cycles\n",
+	pr_info("finished after %u erase cycles\n",
 	       erase_cycles);
 	kfree(check_buf);
 out_patt_FF:
@@ -403,7 +404,7 @@ out_patt_5A5:
 out_mtd:
 	put_mtd_device(mtd);
 	if (err)
-		printk(PRINT_PREF "error %d occurred during torturing\n", err);
+		pr_info("error %d occurred during torturing\n", err);
 	printk(KERN_INFO "=================================================\n");
 	return err;
 }
@@ -441,9 +442,9 @@ static void report_corrupt(unsigned char *read, unsigned char *written)
 			       &bits) >= 0)
 			pages++;
 
-	printk(PRINT_PREF "verify fails on %d pages, %d bytes/%d bits\n",
+	pr_info("verify fails on %d pages, %d bytes/%d bits\n",
 	       pages, bytes, bits);
-	printk(PRINT_PREF "The following is a list of all differences between"
+	pr_info("The following is a list of all differences between"
 	       " what was read from flash and what was expected\n");
 
 	for (i = 0; i < check_len; i += pgsize) {
@@ -457,7 +458,7 @@ static void report_corrupt(unsigned char *read, unsigned char *written)
 		printk("-------------------------------------------------------"
 		       "----------------------------------\n");
 
-		printk(PRINT_PREF "Page %zd has %d bytes/%d bits failing verify,"
+		pr_info("Page %zd has %d bytes/%d bits failing verify,"
 		       " starting at offset 0x%x\n",
 		       (mtd->erasesize - check_len + i) / pgsize,
 		       bytes, bits, first);
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 1a5f53c..0648c69 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -814,10 +814,8 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
 	if (max_sqnum > ai->max_sqnum)
 		ai->max_sqnum = max_sqnum;
 
-	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
-		list_del(&tmp_aeb->u.list);
-		list_add_tail(&tmp_aeb->u.list, &ai->free);
-	}
+	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list)
+		list_move_tail(&tmp_aeb->u.list, &ai->free);
 
 	/*
 	 * If fastmap is leaking PEBs (must not happen), raise a
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 6a70184..2334190 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -123,8 +123,7 @@ config IFB
 source "drivers/net/team/Kconfig"
 
 config MACVLAN
-	tristate "MAC-VLAN support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	tristate "MAC-VLAN support"
 	---help---
 	  This allows one to create virtual interfaces that map packets to
 	  or from specific MAC addresses to a particular interface.
@@ -138,7 +137,7 @@ config MACVLAN
 	  will be called macvlan.
 
 config MACVTAP
-	tristate "MAC-VLAN based tap driver (EXPERIMENTAL)"
+	tristate "MAC-VLAN based tap driver"
 	depends on MACVLAN
 	help
 	  This adds a specialized tap character device driver that is based
@@ -234,8 +233,8 @@ config VETH
 	  versa.
 
 config VIRTIO_NET
-	tristate "Virtio network driver (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && VIRTIO
+	tristate "Virtio network driver"
+	depends on VIRTIO
 	---help---
 	  This is the virtual network driver for virtio.  It can be used with
 	  lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 5f5b69f..c8bff3e 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1838,7 +1838,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 		 * anyway (it holds no special properties of the bond device),
 		 * so we can change it without calling change_active_interface()
 		 */
-		if (!bond->curr_active_slave)
+		if (!bond->curr_active_slave && new_slave->link == BOND_LINK_UP)
 			bond->curr_active_slave = new_slave;
 
 		break;
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index f8af2fc..486b1cb 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -244,7 +244,7 @@ struct bonding {
 	struct   delayed_work ad_work;
 	struct   delayed_work mcast_work;
 #ifdef CONFIG_DEBUG_FS
-	/* debugging suport via debugfs */
+	/* debugging support via debugfs */
 	struct	 dentry *debug_dir;
 #endif /* CONFIG_DEBUG_FS */
 };
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index bb709fd..b56bd9e 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -110,6 +110,15 @@ config PCH_CAN
 	  is an IOH for x86 embedded processor (Intel Atom E6xx series).
 	  This driver can access CAN bus.
 
+config CAN_GRCAN
+	tristate "Aeroflex Gaisler GRCAN and GRHCAN CAN devices"
+	depends on CAN_DEV && OF
+	---help---
+	  Say Y here if you want to use Aeroflex Gaisler GRCAN or GRHCAN.
+	  Note that the driver supports little endian, even though little
+	  endian syntheses of the cores would need some modifications on
+	  the hardware level to work.
+
 source "drivers/net/can/mscan/Kconfig"
 
 source "drivers/net/can/sja1000/Kconfig"
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 938be37..7de5986 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -22,5 +22,6 @@ obj-$(CONFIG_CAN_BFIN)		+= bfin_can.o
 obj-$(CONFIG_CAN_JANZ_ICAN3)	+= janz-ican3.o
 obj-$(CONFIG_CAN_FLEXCAN)	+= flexcan.o
 obj-$(CONFIG_PCH_CAN)		+= pch_can.o
+obj-$(CONFIG_CAN_GRCAN)		+= grcan.o
 
 ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index fcff73a..7978882 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -33,12 +33,11 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/types.h>
+#include <linux/platform_data/atmel.h>
 
 #include <linux/can/dev.h>
 #include <linux/can/error.h>
 
-#include <mach/board.h>
-
 #define AT91_MB_MASK(i)		((1 << (i)) - 1)
 
 /* Common registers */
@@ -1372,6 +1371,7 @@ static const struct platform_device_id at91_can_id_table[] = {
 		/* sentinel */
 	}
 };
+MODULE_DEVICE_TABLE(platform, at91_can_id_table);
 
 static struct platform_driver at91_can_driver = {
 	.probe = at91_can_probe,
diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
index f2d6d25..a3f8de9 100644
--- a/drivers/net/can/bfin_can.c
+++ b/drivers/net/can/bfin_can.c
@@ -691,3 +691,4 @@ module_platform_driver(bfin_can_driver);
 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Blackfin on-chip CAN netdevice driver");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index e5180df..5233b8f 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -233,6 +233,12 @@ static inline void c_can_pm_runtime_put_sync(const struct c_can_priv *priv)
 		pm_runtime_put_sync(priv->device);
 }
 
+static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable)
+{
+	if (priv->raminit)
+		priv->raminit(priv, enable);
+}
+
 static inline int get_tx_next_msg_obj(const struct c_can_priv *priv)
 {
 	return (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) +
@@ -1090,6 +1096,7 @@ static int c_can_open(struct net_device *dev)
 	struct c_can_priv *priv = netdev_priv(dev);
 
 	c_can_pm_runtime_get_sync(priv);
+	c_can_reset_ram(priv, true);
 
 	/* open the can device */
 	err = open_candev(dev);
@@ -1118,6 +1125,7 @@ static int c_can_open(struct net_device *dev)
 exit_irq_fail:
 	close_candev(dev);
 exit_open_fail:
+	c_can_reset_ram(priv, false);
 	c_can_pm_runtime_put_sync(priv);
 	return err;
 }
@@ -1131,6 +1139,8 @@ static int c_can_close(struct net_device *dev)
 	c_can_stop(dev);
 	free_irq(dev->irq, dev);
 	close_candev(dev);
+
+	c_can_reset_ram(priv, false);
 	c_can_pm_runtime_put_sync(priv);
 
 	return 0;
@@ -1188,6 +1198,7 @@ int c_can_power_down(struct net_device *dev)
 
 	c_can_stop(dev);
 
+	c_can_reset_ram(priv, false);
 	c_can_pm_runtime_put_sync(priv);
 
 	return 0;
@@ -1206,6 +1217,7 @@ int c_can_power_up(struct net_device *dev)
 	WARN_ON(priv->type != BOSCH_D_CAN);
 
 	c_can_pm_runtime_get_sync(priv);
+	c_can_reset_ram(priv, true);
 
 	/* Clear PDR and INIT bits */
 	val = priv->read_reg(priv, C_CAN_CTRL_EX_REG);
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index e5ed41d..d2e1c21 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -169,6 +169,9 @@ struct c_can_priv {
 	void *priv;		/* for board-specific data */
 	u16 irqstatus;
 	enum c_can_dev_id type;
+	u32 __iomem *raminit_ctrlreg;
+	unsigned int instance;
+	void (*raminit) (const struct c_can_priv *priv, bool enable);
 };
 
 struct net_device *alloc_c_can_dev(void);
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index ee14161..0044fd8 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -38,6 +38,8 @@
 
 #include "c_can.h"
 
+#define CAN_RAMINIT_START_MASK(i)	(1 << (i))
+
 /*
  * 16-bit c_can registers can be arranged differently in the memory
  * architecture of different implementations. For example: 16-bit
@@ -68,6 +70,18 @@ static void c_can_plat_write_reg_aligned_to_32bit(struct c_can_priv *priv,
 	writew(val, priv->base + 2 * priv->regs[index]);
 }
 
+static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable)
+{
+	u32 val;
+
+	val = readl(priv->raminit_ctrlreg);
+	if (enable)
+		val |= CAN_RAMINIT_START_MASK(priv->instance);
+	else
+		val &= ~CAN_RAMINIT_START_MASK(priv->instance);
+	writel(val, priv->raminit_ctrlreg);
+}
+
 static struct platform_device_id c_can_id_table[] = {
 	[BOSCH_C_CAN_PLATFORM] = {
 		.name = KBUILD_MODNAME,
@@ -83,12 +97,14 @@ static struct platform_device_id c_can_id_table[] = {
 	}, {
 	}
 };
+MODULE_DEVICE_TABLE(platform, c_can_id_table);
 
 static const struct of_device_id c_can_of_table[] = {
 	{ .compatible = "bosch,c_can", .data = &c_can_id_table[BOSCH_C_CAN] },
 	{ .compatible = "bosch,d_can", .data = &c_can_id_table[BOSCH_D_CAN] },
 	{ /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, c_can_of_table);
 
 static int __devinit c_can_plat_probe(struct platform_device *pdev)
 {
@@ -99,7 +115,7 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
 	const struct of_device_id *match;
 	const struct platform_device_id *id;
 	struct pinctrl *pinctrl;
-	struct resource *mem;
+	struct resource *mem, *res;
 	int irq;
 	struct clk *clk;
 
@@ -178,6 +194,18 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
 		priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
 		priv->read_reg = c_can_plat_read_reg_aligned_to_16bit;
 		priv->write_reg = c_can_plat_write_reg_aligned_to_16bit;
+
+		if (pdev->dev.of_node)
+			priv->instance = of_alias_get_id(pdev->dev.of_node, "d_can");
+		else
+			priv->instance = pdev->id;
+
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+		priv->raminit_ctrlreg =	devm_request_and_ioremap(&pdev->dev, res);
+		if (!priv->raminit_ctrlreg || priv->instance < 0)
+			dev_info(&pdev->dev, "control memory is not used for raminit\n");
+		else
+			priv->raminit = c_can_hw_raminit;
 		break;
 	default:
 		ret = -EINVAL;
diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c
index 688371c..3da6cbb 100644
--- a/drivers/net/can/cc770/cc770_platform.c
+++ b/drivers/net/can/cc770/cc770_platform.c
@@ -60,6 +60,7 @@
 MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
 MODULE_DESCRIPTION("Socket-CAN driver for CC770 on the platform bus");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
 
 #define CC770_PLATFORM_CAN_CLOCK  16000000
 
@@ -258,6 +259,7 @@ static struct of_device_id __devinitdata cc770_platform_table[] = {
 	{.compatible = "intc,82527"},  /* AN82527 from Intel CP */
 	{},
 };
+MODULE_DEVICE_TABLE(of, cc770_platform_table);
 
 static struct platform_driver cc770_platform_driver = {
 	.driver = {
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index a412bf6..9a17965 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -979,11 +979,13 @@ static const struct of_device_id flexcan_of_match[] = {
 	{ .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
 	{ /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, flexcan_of_match);
 
 static const struct platform_device_id flexcan_id_table[] = {
 	{ .name = "flexcan", .driver_data = (kernel_ulong_t)&fsl_p1010_devtype_data, },
 	{ /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(platform, flexcan_id_table);
 
 static int __devinit flexcan_probe(struct platform_device *pdev)
 {
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
new file mode 100644
index 0000000..391f484
--- /dev/null
+++ b/drivers/net/can/grcan.c
@@ -0,0 +1,1756 @@
+/*
+ * Socket CAN driver for Aeroflex Gaisler GRCAN and GRHCAN.
+ *
+ * 2012 (c) Aeroflex Gaisler AB
+ *
+ * This driver supports GRCAN and GRHCAN CAN controllers available in the GRLIB
+ * VHDL IP core library.
+ *
+ * Full documentation of the GRCAN core can be found here:
+ * http://www.gaisler.com/products/grlib/grip.pdf
+ *
+ * See "Documentation/devicetree/bindings/net/can/grcan.txt" for information on
+ * open firmware properties.
+ *
+ * See "Documentation/ABI/testing/sysfs-class-net-grcan" for information on the
+ * sysfs interface.
+ *
+ * See "Documentation/kernel-parameters.txt" for information on the module
+ * parameters.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Contributors: Andreas Larsson <andreas@gaisler.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#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>
+
+#define DRV_NAME	"grcan"
+
+#define GRCAN_NAPI_WEIGHT	32
+
+#define GRCAN_RESERVE_SIZE(slot1, slot2) (((slot2) - (slot1)) / 4 - 1)
+
+struct grcan_registers {
+	u32 conf;	/* 0x00 */
+	u32 stat;	/* 0x04 */
+	u32 ctrl;	/* 0x08 */
+	u32 __reserved1[GRCAN_RESERVE_SIZE(0x08, 0x18)];
+	u32 smask;	/* 0x18 - CanMASK */
+	u32 scode;	/* 0x1c - CanCODE */
+	u32 __reserved2[GRCAN_RESERVE_SIZE(0x1c, 0x100)];
+	u32 pimsr;	/* 0x100 */
+	u32 pimr;	/* 0x104 */
+	u32 pisr;	/* 0x108 */
+	u32 pir;	/* 0x10C */
+	u32 imr;	/* 0x110 */
+	u32 picr;	/* 0x114 */
+	u32 __reserved3[GRCAN_RESERVE_SIZE(0x114, 0x200)];
+	u32 txctrl;	/* 0x200 */
+	u32 txaddr;	/* 0x204 */
+	u32 txsize;	/* 0x208 */
+	u32 txwr;	/* 0x20C */
+	u32 txrd;	/* 0x210 */
+	u32 txirq;	/* 0x214 */
+	u32 __reserved4[GRCAN_RESERVE_SIZE(0x214, 0x300)];
+	u32 rxctrl;	/* 0x300 */
+	u32 rxaddr;	/* 0x304 */
+	u32 rxsize;	/* 0x308 */
+	u32 rxwr;	/* 0x30C */
+	u32 rxrd;	/* 0x310 */
+	u32 rxirq;	/* 0x314 */
+	u32 rxmask;	/* 0x318 */
+	u32 rxcode;	/* 0x31C */
+};
+
+#define GRCAN_CONF_ABORT	0x00000001
+#define GRCAN_CONF_ENABLE0	0x00000002
+#define GRCAN_CONF_ENABLE1	0x00000004
+#define GRCAN_CONF_SELECT	0x00000008
+#define GRCAN_CONF_SILENT	0x00000010
+#define GRCAN_CONF_SAM		0x00000020 /* Available in some hardware */
+#define GRCAN_CONF_BPR		0x00000300 /* Note: not BRP */
+#define GRCAN_CONF_RSJ		0x00007000
+#define GRCAN_CONF_PS1		0x00f00000
+#define GRCAN_CONF_PS2		0x000f0000
+#define GRCAN_CONF_SCALER	0xff000000
+#define GRCAN_CONF_OPERATION						\
+	(GRCAN_CONF_ABORT | GRCAN_CONF_ENABLE0 | GRCAN_CONF_ENABLE1	\
+	 | GRCAN_CONF_SELECT | GRCAN_CONF_SILENT | GRCAN_CONF_SAM)
+#define GRCAN_CONF_TIMING						\
+	(GRCAN_CONF_BPR | GRCAN_CONF_RSJ | GRCAN_CONF_PS1		\
+	 | GRCAN_CONF_PS2 | GRCAN_CONF_SCALER)
+
+#define GRCAN_CONF_RSJ_MIN	1
+#define GRCAN_CONF_RSJ_MAX	4
+#define GRCAN_CONF_PS1_MIN	1
+#define GRCAN_CONF_PS1_MAX	15
+#define GRCAN_CONF_PS2_MIN	2
+#define GRCAN_CONF_PS2_MAX	8
+#define GRCAN_CONF_SCALER_MIN	0
+#define GRCAN_CONF_SCALER_MAX	255
+#define GRCAN_CONF_SCALER_INC	1
+
+#define GRCAN_CONF_BPR_BIT	8
+#define GRCAN_CONF_RSJ_BIT	12
+#define GRCAN_CONF_PS1_BIT	20
+#define GRCAN_CONF_PS2_BIT	16
+#define GRCAN_CONF_SCALER_BIT	24
+
+#define GRCAN_STAT_PASS		0x000001
+#define GRCAN_STAT_OFF		0x000002
+#define GRCAN_STAT_OR		0x000004
+#define GRCAN_STAT_AHBERR	0x000008
+#define GRCAN_STAT_ACTIVE	0x000010
+#define GRCAN_STAT_RXERRCNT	0x00ff00
+#define GRCAN_STAT_TXERRCNT	0xff0000
+
+#define GRCAN_STAT_ERRCTR_RELATED	(GRCAN_STAT_PASS | GRCAN_STAT_OFF)
+
+#define GRCAN_STAT_RXERRCNT_BIT	8
+#define GRCAN_STAT_TXERRCNT_BIT	16
+
+#define GRCAN_STAT_ERRCNT_WARNING_LIMIT	96
+#define GRCAN_STAT_ERRCNT_PASSIVE_LIMIT	127
+
+#define GRCAN_CTRL_RESET	0x2
+#define GRCAN_CTRL_ENABLE	0x1
+
+#define GRCAN_TXCTRL_ENABLE	0x1
+#define GRCAN_TXCTRL_ONGOING	0x2
+#define GRCAN_TXCTRL_SINGLE	0x4
+
+#define GRCAN_RXCTRL_ENABLE	0x1
+#define GRCAN_RXCTRL_ONGOING	0x2
+
+/* Relative offset of IRQ sources to AMBA Plug&Play */
+#define GRCAN_IRQIX_IRQ		0
+#define GRCAN_IRQIX_TXSYNC	1
+#define GRCAN_IRQIX_RXSYNC	2
+
+#define GRCAN_IRQ_PASS		0x00001
+#define GRCAN_IRQ_OFF		0x00002
+#define GRCAN_IRQ_OR		0x00004
+#define GRCAN_IRQ_RXAHBERR	0x00008
+#define GRCAN_IRQ_TXAHBERR	0x00010
+#define GRCAN_IRQ_RXIRQ		0x00020
+#define GRCAN_IRQ_TXIRQ		0x00040
+#define GRCAN_IRQ_RXFULL	0x00080
+#define GRCAN_IRQ_TXEMPTY	0x00100
+#define GRCAN_IRQ_RX		0x00200
+#define GRCAN_IRQ_TX		0x00400
+#define GRCAN_IRQ_RXSYNC	0x00800
+#define GRCAN_IRQ_TXSYNC	0x01000
+#define GRCAN_IRQ_RXERRCTR	0x02000
+#define GRCAN_IRQ_TXERRCTR	0x04000
+#define GRCAN_IRQ_RXMISS	0x08000
+#define GRCAN_IRQ_TXLOSS	0x10000
+
+#define GRCAN_IRQ_NONE	0
+#define GRCAN_IRQ_ALL							\
+	(GRCAN_IRQ_PASS | GRCAN_IRQ_OFF | GRCAN_IRQ_OR			\
+	 | GRCAN_IRQ_RXAHBERR | GRCAN_IRQ_TXAHBERR			\
+	 | GRCAN_IRQ_RXIRQ | GRCAN_IRQ_TXIRQ				\
+	 | GRCAN_IRQ_RXFULL | GRCAN_IRQ_TXEMPTY				\
+	 | GRCAN_IRQ_RX | GRCAN_IRQ_TX | GRCAN_IRQ_RXSYNC		\
+	 | GRCAN_IRQ_TXSYNC | GRCAN_IRQ_RXERRCTR			\
+	 | GRCAN_IRQ_TXERRCTR | GRCAN_IRQ_RXMISS			\
+	 | GRCAN_IRQ_TXLOSS)
+
+#define GRCAN_IRQ_ERRCTR_RELATED (GRCAN_IRQ_RXERRCTR | GRCAN_IRQ_TXERRCTR \
+				  | GRCAN_IRQ_PASS | GRCAN_IRQ_OFF)
+#define GRCAN_IRQ_ERRORS (GRCAN_IRQ_ERRCTR_RELATED | GRCAN_IRQ_OR	\
+			  | GRCAN_IRQ_TXAHBERR | GRCAN_IRQ_RXAHBERR	\
+			  | GRCAN_IRQ_TXLOSS)
+#define GRCAN_IRQ_DEFAULT (GRCAN_IRQ_RX | GRCAN_IRQ_TX | GRCAN_IRQ_ERRORS)
+
+#define GRCAN_MSG_SIZE		16
+
+#define GRCAN_MSG_IDE		0x80000000
+#define GRCAN_MSG_RTR		0x40000000
+#define GRCAN_MSG_BID		0x1ffc0000
+#define GRCAN_MSG_EID		0x1fffffff
+#define GRCAN_MSG_IDE_BIT	31
+#define GRCAN_MSG_RTR_BIT	30
+#define GRCAN_MSG_BID_BIT	18
+#define GRCAN_MSG_EID_BIT	0
+
+#define GRCAN_MSG_DLC		0xf0000000
+#define GRCAN_MSG_TXERRC	0x00ff0000
+#define GRCAN_MSG_RXERRC	0x0000ff00
+#define GRCAN_MSG_DLC_BIT	28
+#define GRCAN_MSG_TXERRC_BIT	16
+#define GRCAN_MSG_RXERRC_BIT	8
+#define GRCAN_MSG_AHBERR	0x00000008
+#define GRCAN_MSG_OR		0x00000004
+#define GRCAN_MSG_OFF		0x00000002
+#define GRCAN_MSG_PASS		0x00000001
+
+#define GRCAN_MSG_DATA_SLOT_INDEX(i) (2 + (i) / 4)
+#define GRCAN_MSG_DATA_SHIFT(i) ((3 - (i) % 4) * 8)
+
+#define GRCAN_BUFFER_ALIGNMENT		1024
+#define GRCAN_DEFAULT_BUFFER_SIZE	1024
+#define GRCAN_VALID_TR_SIZE_MASK	0x001fffc0
+
+#define GRCAN_INVALID_BUFFER_SIZE(s)			\
+	((s) == 0 || ((s) & ~GRCAN_VALID_TR_SIZE_MASK))
+
+#if GRCAN_INVALID_BUFFER_SIZE(GRCAN_DEFAULT_BUFFER_SIZE)
+#error "Invalid default buffer size"
+#endif
+
+struct grcan_dma_buffer {
+	size_t size;
+	void *buf;
+	dma_addr_t handle;
+};
+
+struct grcan_dma {
+	size_t base_size;
+	void *base_buf;
+	dma_addr_t base_handle;
+	struct grcan_dma_buffer tx;
+	struct grcan_dma_buffer rx;
+};
+
+/* GRCAN configuration parameters */
+struct grcan_device_config {
+	unsigned short enable0;
+	unsigned short enable1;
+	unsigned short select;
+	unsigned int txsize;
+	unsigned int rxsize;
+};
+
+#define GRCAN_DEFAULT_DEVICE_CONFIG {				\
+		.enable0	= 0,				\
+		.enable1	= 0,				\
+		.select		= 0,				\
+		.txsize		= GRCAN_DEFAULT_BUFFER_SIZE,	\
+		.rxsize		= GRCAN_DEFAULT_BUFFER_SIZE,	\
+		}
+
+#define GRCAN_TXBUG_SAFE_GRLIB_VERSION	0x4100
+#define GRLIB_VERSION_MASK		0xffff
+
+/* GRCAN private data structure */
+struct grcan_priv {
+	struct can_priv can;	/* must be the first member */
+	struct net_device *dev;
+	struct napi_struct napi;
+
+	struct grcan_registers __iomem *regs;	/* ioremap'ed registers */
+	struct grcan_device_config config;
+	struct grcan_dma dma;
+
+	struct sk_buff **echo_skb;	/* We allocate this on our own */
+	u8 *txdlc;			/* Length of queued frames */
+
+	/* The echo skb pointer, pointing into echo_skb and indicating which
+	 * frames can be echoed back. See the "Notes on the tx cyclic buffer
+	 * handling"-comment for grcan_start_xmit for more details.
+	 */
+	u32 eskbp;
+
+	/* Lock for controlling changes to the netif tx queue state, accesses to
+	 * the echo_skb pointer eskbp and for making sure that a running reset
+	 * and/or a close of the interface is done without interference from
+	 * other parts of the code.
+	 *
+	 * The echo_skb pointer, eskbp, should only be accessed under this lock
+	 * as it can be changed in several places and together with decisions on
+	 * whether to wake up the tx queue.
+	 *
+	 * The tx queue must never be woken up if there is a running reset or
+	 * close in progress.
+	 *
+	 * A running reset (see below on need_txbug_workaround) should never be
+	 * done if the interface is closing down and several running resets
+	 * should never be scheduled simultaneously.
+	 */
+	spinlock_t lock;
+
+	/* Whether a workaround is needed due to a bug in older hardware. In
+	 * this case, the driver both tries to prevent the bug from being
+	 * triggered and recovers, if the bug nevertheless happens, by doing a
+	 * running reset. A running reset, resets the device and continues from
+	 * where it were without being noticeable from outside the driver (apart
+	 * from slight delays).
+	 */
+	bool need_txbug_workaround;
+
+	/* To trigger initization of running reset and to trigger running reset
+	 * respectively in the case of a hanged device due to a txbug.
+	 */
+	struct timer_list hang_timer;
+	struct timer_list rr_timer;
+
+	/* To avoid waking up the netif queue and restarting timers
+	 * when a reset is scheduled or when closing of the device is
+	 * undergoing
+	 */
+	bool resetting;
+	bool closing;
+};
+
+/* Wait time for a short wait for ongoing to clear */
+#define GRCAN_SHORTWAIT_USECS	10
+
+/* Limit on the number of transmitted bits of an eff frame according to the CAN
+ * specification: 1 bit start of frame, 32 bits arbitration field, 6 bits
+ * control field, 8 bytes data field, 16 bits crc field, 2 bits ACK field and 7
+ * bits end of frame
+ */
+#define GRCAN_EFF_FRAME_MAX_BITS	(1+32+6+8*8+16+2+7)
+
+#if defined(__BIG_ENDIAN)
+static inline u32 grcan_read_reg(u32 __iomem *reg)
+{
+	return ioread32be(reg);
+}
+
+static inline void grcan_write_reg(u32 __iomem *reg, u32 val)
+{
+	iowrite32be(val, reg);
+}
+#else
+static inline u32 grcan_read_reg(u32 __iomem *reg)
+{
+	return ioread32(reg);
+}
+
+static inline void grcan_write_reg(u32 __iomem *reg, u32 val)
+{
+	iowrite32(val, reg);
+}
+#endif
+
+static inline void grcan_clear_bits(u32 __iomem *reg, u32 mask)
+{
+	grcan_write_reg(reg, grcan_read_reg(reg) & ~mask);
+}
+
+static inline void grcan_set_bits(u32 __iomem *reg, u32 mask)
+{
+	grcan_write_reg(reg, grcan_read_reg(reg) | mask);
+}
+
+static inline u32 grcan_read_bits(u32 __iomem *reg, u32 mask)
+{
+	return grcan_read_reg(reg) & mask;
+}
+
+static inline void grcan_write_bits(u32 __iomem *reg, u32 value, u32 mask)
+{
+	u32 old = grcan_read_reg(reg);
+
+	grcan_write_reg(reg, (old & ~mask) | (value & mask));
+}
+
+/* a and b should both be in [0,size] and a == b == size should not hold */
+static inline u32 grcan_ring_add(u32 a, u32 b, u32 size)
+{
+	u32 sum = a + b;
+
+	if (sum < size)
+		return sum;
+	else
+		return sum - size;
+}
+
+/* a and b should both be in [0,size) */
+static inline u32 grcan_ring_sub(u32 a, u32 b, u32 size)
+{
+	return grcan_ring_add(a, size - b, size);
+}
+
+/* Available slots for new transmissions */
+static inline u32 grcan_txspace(size_t txsize, u32 txwr, u32 eskbp)
+{
+	u32 slots = txsize / GRCAN_MSG_SIZE - 1;
+	u32 used = grcan_ring_sub(txwr, eskbp, txsize) / GRCAN_MSG_SIZE;
+
+	return slots - used;
+}
+
+/* Configuration parameters that can be set via module parameters */
+static struct grcan_device_config grcan_module_config =
+	GRCAN_DEFAULT_DEVICE_CONFIG;
+
+static const struct can_bittiming_const grcan_bittiming_const = {
+	.name		= DRV_NAME,
+	.tseg1_min	= GRCAN_CONF_PS1_MIN + 1,
+	.tseg1_max	= GRCAN_CONF_PS1_MAX + 1,
+	.tseg2_min	= GRCAN_CONF_PS2_MIN,
+	.tseg2_max	= GRCAN_CONF_PS2_MAX,
+	.sjw_max	= GRCAN_CONF_RSJ_MAX,
+	.brp_min	= GRCAN_CONF_SCALER_MIN + 1,
+	.brp_max	= GRCAN_CONF_SCALER_MAX + 1,
+	.brp_inc	= GRCAN_CONF_SCALER_INC,
+};
+
+static int grcan_set_bittiming(struct net_device *dev)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_registers __iomem *regs = priv->regs;
+	struct can_bittiming *bt = &priv->can.bittiming;
+	u32 timing = 0;
+	int bpr, rsj, ps1, ps2, scaler;
+
+	/* Should never happen - function will not be called when
+	 * device is up
+	 */
+	if (grcan_read_bits(&regs->ctrl, GRCAN_CTRL_ENABLE))
+		return -EBUSY;
+
+	bpr = 0; /* Note bpr and brp are different concepts */
+	rsj = bt->sjw;
+	ps1 = (bt->prop_seg + bt->phase_seg1) - 1; /* tseg1 - 1 */
+	ps2 = bt->phase_seg2;
+	scaler = (bt->brp - 1);
+	netdev_dbg(dev, "Request for BPR=%d, RSJ=%d, PS1=%d, PS2=%d, SCALER=%d",
+		   bpr, rsj, ps1, ps2, scaler);
+	if (!(ps1 > ps2)) {
+		netdev_err(dev, "PS1 > PS2 must hold: PS1=%d, PS2=%d\n",
+			   ps1, ps2);
+		return -EINVAL;
+	}
+	if (!(ps2 >= rsj)) {
+		netdev_err(dev, "PS2 >= RSJ must hold: PS2=%d, RSJ=%d\n",
+			   ps2, rsj);
+		return -EINVAL;
+	}
+
+	timing |= (bpr << GRCAN_CONF_BPR_BIT) & GRCAN_CONF_BPR;
+	timing |= (rsj << GRCAN_CONF_RSJ_BIT) & GRCAN_CONF_RSJ;
+	timing |= (ps1 << GRCAN_CONF_PS1_BIT) & GRCAN_CONF_PS1;
+	timing |= (ps2 << GRCAN_CONF_PS2_BIT) & GRCAN_CONF_PS2;
+	timing |= (scaler << GRCAN_CONF_SCALER_BIT) & GRCAN_CONF_SCALER;
+	netdev_info(dev, "setting timing=0x%x\n", timing);
+	grcan_write_bits(&regs->conf, timing, GRCAN_CONF_TIMING);
+
+	return 0;
+}
+
+static int grcan_get_berr_counter(const struct net_device *dev,
+				  struct can_berr_counter *bec)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_registers __iomem *regs = priv->regs;
+	u32 status = grcan_read_reg(&regs->stat);
+
+	bec->txerr = (status & GRCAN_STAT_TXERRCNT) >> GRCAN_STAT_TXERRCNT_BIT;
+	bec->rxerr = (status & GRCAN_STAT_RXERRCNT) >> GRCAN_STAT_RXERRCNT_BIT;
+	return 0;
+}
+
+static int grcan_poll(struct napi_struct *napi, int budget);
+
+/* Reset device, but keep configuration information */
+static void grcan_reset(struct net_device *dev)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_registers __iomem *regs = priv->regs;
+	u32 config = grcan_read_reg(&regs->conf);
+
+	grcan_set_bits(&regs->ctrl, GRCAN_CTRL_RESET);
+	grcan_write_reg(&regs->conf, config);
+
+	priv->eskbp = grcan_read_reg(&regs->txrd);
+	priv->can.state = CAN_STATE_STOPPED;
+
+	/* Turn off hardware filtering - regs->rxcode set to 0 by reset */
+	grcan_write_reg(&regs->rxmask, 0);
+}
+
+/* stop device without changing any configurations */
+static void grcan_stop_hardware(struct net_device *dev)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_registers __iomem *regs = priv->regs;
+
+	grcan_write_reg(&regs->imr, GRCAN_IRQ_NONE);
+	grcan_clear_bits(&regs->txctrl, GRCAN_TXCTRL_ENABLE);
+	grcan_clear_bits(&regs->rxctrl, GRCAN_RXCTRL_ENABLE);
+	grcan_clear_bits(&regs->ctrl, GRCAN_CTRL_ENABLE);
+}
+
+/* Let priv->eskbp catch up to regs->txrd and echo back the skbs if echo
+ * is true and free them otherwise.
+ *
+ * If budget is >= 0, stop after handling at most budget skbs. Otherwise,
+ * continue until priv->eskbp catches up to regs->txrd.
+ *
+ * priv->lock *must* be held when calling this function
+ */
+static int catch_up_echo_skb(struct net_device *dev, int budget, bool echo)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_registers __iomem *regs = priv->regs;
+	struct grcan_dma *dma = &priv->dma;
+	struct net_device_stats *stats = &dev->stats;
+	int i, work_done;
+
+	/* Updates to priv->eskbp and wake-ups of the queue needs to
+	 * be atomic towards the reads of priv->eskbp and shut-downs
+	 * of the queue in grcan_start_xmit.
+	 */
+	u32 txrd = grcan_read_reg(&regs->txrd);
+
+	for (work_done = 0; work_done < budget || budget < 0; work_done++) {
+		if (priv->eskbp == txrd)
+			break;
+		i = priv->eskbp / GRCAN_MSG_SIZE;
+		if (echo) {
+			/* Normal echo of messages */
+			stats->tx_packets++;
+			stats->tx_bytes += priv->txdlc[i];
+			priv->txdlc[i] = 0;
+			can_get_echo_skb(dev, i);
+		} else {
+			/* For cleanup of untransmitted messages */
+			can_free_echo_skb(dev, i);
+		}
+
+		priv->eskbp = grcan_ring_add(priv->eskbp, GRCAN_MSG_SIZE,
+					     dma->tx.size);
+		txrd = grcan_read_reg(&regs->txrd);
+	}
+	return work_done;
+}
+
+static void grcan_lost_one_shot_frame(struct net_device *dev)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_registers __iomem *regs = priv->regs;
+	struct grcan_dma *dma = &priv->dma;
+	u32 txrd;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	catch_up_echo_skb(dev, -1, true);
+
+	if (unlikely(grcan_read_bits(&regs->txctrl, GRCAN_TXCTRL_ENABLE))) {
+		/* Should never happen */
+		netdev_err(dev, "TXCTRL enabled at TXLOSS in one shot mode\n");
+	} else {
+		/* By the time an GRCAN_IRQ_TXLOSS is generated in
+		 * one-shot mode there is no problem in writing
+		 * to TXRD even in versions of the hardware in
+		 * which GRCAN_TXCTRL_ONGOING is not cleared properly
+		 * in one-shot mode.
+		 */
+
+		/* Skip message and discard echo-skb */
+		txrd = grcan_read_reg(&regs->txrd);
+		txrd = grcan_ring_add(txrd, GRCAN_MSG_SIZE, dma->tx.size);
+		grcan_write_reg(&regs->txrd, txrd);
+		catch_up_echo_skb(dev, -1, false);
+
+		if (!priv->resetting && !priv->closing &&
+		    !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) {
+			netif_wake_queue(dev);
+			grcan_set_bits(&regs->txctrl, GRCAN_TXCTRL_ENABLE);
+		}
+	}
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void grcan_err(struct net_device *dev, u32 sources, u32 status)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_registers __iomem *regs = priv->regs;
+	struct grcan_dma *dma = &priv->dma;
+	struct net_device_stats *stats = &dev->stats;
+	struct can_frame cf;
+
+	/* Zero potential error_frame */
+	memset(&cf, 0, sizeof(cf));
+
+	/* Message lost interrupt. This might be due to arbitration error, but
+	 * is also triggered when there is no one else on the can bus or when
+	 * there is a problem with the hardware interface or the bus itself. As
+	 * arbitration errors can not be singled out, no error frames are
+	 * generated reporting this event as an arbitration error.
+	 */
+	if (sources & GRCAN_IRQ_TXLOSS) {
+		/* Take care of failed one-shot transmit */
+		if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
+			grcan_lost_one_shot_frame(dev);
+
+		/* Stop printing as soon as error passive or bus off is in
+		 * effect to limit the amount of txloss debug printouts.
+		 */
+		if (!(status & GRCAN_STAT_ERRCTR_RELATED)) {
+			netdev_dbg(dev, "tx message lost\n");
+			stats->tx_errors++;
+		}
+	}
+
+	/* Conditions dealing with the error counters. There is no interrupt for
+	 * error warning, but there are interrupts for increases of the error
+	 * counters.
+	 */
+	if ((sources & GRCAN_IRQ_ERRCTR_RELATED) ||
+	    (status & GRCAN_STAT_ERRCTR_RELATED)) {
+		enum can_state state = priv->can.state;
+		enum can_state oldstate = state;
+		u32 txerr = (status & GRCAN_STAT_TXERRCNT)
+			>> GRCAN_STAT_TXERRCNT_BIT;
+		u32 rxerr = (status & GRCAN_STAT_RXERRCNT)
+			>> GRCAN_STAT_RXERRCNT_BIT;
+
+		/* Figure out current state */
+		if (status & GRCAN_STAT_OFF) {
+			state = CAN_STATE_BUS_OFF;
+		} else if (status & GRCAN_STAT_PASS) {
+			state = CAN_STATE_ERROR_PASSIVE;
+		} else if (txerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT ||
+			   rxerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT) {
+			state = CAN_STATE_ERROR_WARNING;
+		} else {
+			state = CAN_STATE_ERROR_ACTIVE;
+		}
+
+		/* Handle and report state changes */
+		if (state != oldstate) {
+			switch (state) {
+			case CAN_STATE_BUS_OFF:
+				netdev_dbg(dev, "bus-off\n");
+				netif_carrier_off(dev);
+				priv->can.can_stats.bus_off++;
+
+				/* Prevent the hardware from recovering from bus
+				 * off on its own if restart is disabled.
+				 */
+				if (!priv->can.restart_ms)
+					grcan_stop_hardware(dev);
+
+				cf.can_id |= CAN_ERR_BUSOFF;
+				break;
+
+			case CAN_STATE_ERROR_PASSIVE:
+				netdev_dbg(dev, "Error passive condition\n");
+				priv->can.can_stats.error_passive++;
+
+				cf.can_id |= CAN_ERR_CRTL;
+				if (txerr >= GRCAN_STAT_ERRCNT_PASSIVE_LIMIT)
+					cf.data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
+				if (rxerr >= GRCAN_STAT_ERRCNT_PASSIVE_LIMIT)
+					cf.data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
+				break;
+
+			case CAN_STATE_ERROR_WARNING:
+				netdev_dbg(dev, "Error warning condition\n");
+				priv->can.can_stats.error_warning++;
+
+				cf.can_id |= CAN_ERR_CRTL;
+				if (txerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT)
+					cf.data[1] |= CAN_ERR_CRTL_TX_WARNING;
+				if (rxerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT)
+					cf.data[1] |= CAN_ERR_CRTL_RX_WARNING;
+				break;
+
+			case CAN_STATE_ERROR_ACTIVE:
+				netdev_dbg(dev, "Error active condition\n");
+				cf.can_id |= CAN_ERR_CRTL;
+				break;
+
+			default:
+				/* There are no others at this point */
+				break;
+			}
+			cf.data[6] = txerr;
+			cf.data[7] = rxerr;
+			priv->can.state = state;
+		}
+
+		/* Report automatic restarts */
+		if (priv->can.restart_ms && oldstate == CAN_STATE_BUS_OFF) {
+			unsigned long flags;
+
+			cf.can_id |= CAN_ERR_RESTARTED;
+			netdev_dbg(dev, "restarted\n");
+			priv->can.can_stats.restarts++;
+			netif_carrier_on(dev);
+
+			spin_lock_irqsave(&priv->lock, flags);
+
+			if (!priv->resetting && !priv->closing) {
+				u32 txwr = grcan_read_reg(&regs->txwr);
+
+				if (grcan_txspace(dma->tx.size, txwr,
+						  priv->eskbp))
+					netif_wake_queue(dev);
+			}
+
+			spin_unlock_irqrestore(&priv->lock, flags);
+		}
+	}
+
+	/* Data overrun interrupt */
+	if ((sources & GRCAN_IRQ_OR) || (status & GRCAN_STAT_OR)) {
+		netdev_dbg(dev, "got data overrun interrupt\n");
+		stats->rx_over_errors++;
+		stats->rx_errors++;
+
+		cf.can_id |= CAN_ERR_CRTL;
+		cf.data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
+	}
+
+	/* AHB bus error interrupts (not CAN bus errors) - shut down the
+	 * device.
+	 */
+	if (sources & (GRCAN_IRQ_TXAHBERR | GRCAN_IRQ_RXAHBERR) ||
+	    (status & GRCAN_STAT_AHBERR)) {
+		char *txrx = "";
+		unsigned long flags;
+
+		if (sources & GRCAN_IRQ_TXAHBERR) {
+			txrx = "on tx ";
+			stats->tx_errors++;
+		} else if (sources & GRCAN_IRQ_RXAHBERR) {
+			txrx = "on rx ";
+			stats->rx_errors++;
+		}
+		netdev_err(dev, "Fatal AHB buss error %s- halting device\n",
+			   txrx);
+
+		spin_lock_irqsave(&priv->lock, flags);
+
+		/* Prevent anything to be enabled again and halt device */
+		priv->closing = true;
+		netif_stop_queue(dev);
+		grcan_stop_hardware(dev);
+		priv->can.state = CAN_STATE_STOPPED;
+
+		spin_unlock_irqrestore(&priv->lock, flags);
+	}
+
+	/* Pass on error frame if something to report,
+	 * i.e. id contains some information
+	 */
+	if (cf.can_id) {
+		struct can_frame *skb_cf;
+		struct sk_buff *skb = alloc_can_err_skb(dev, &skb_cf);
+
+		if (skb == NULL) {
+			netdev_dbg(dev, "could not allocate error frame\n");
+			return;
+		}
+		skb_cf->can_id |= cf.can_id;
+		memcpy(skb_cf->data, cf.data, sizeof(cf.data));
+
+		netif_rx(skb);
+	}
+}
+
+static irqreturn_t grcan_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_registers __iomem *regs = priv->regs;
+	u32 sources, status;
+
+	/* Find out the source */
+	sources = grcan_read_reg(&regs->pimsr);
+	if (!sources)
+		return IRQ_NONE;
+	grcan_write_reg(&regs->picr, sources);
+	status = grcan_read_reg(&regs->stat);
+
+	/* If we got TX progress, the device has not hanged,
+	 * so disable the hang timer
+	 */
+	if (priv->need_txbug_workaround &&
+	    (sources & (GRCAN_IRQ_TX | GRCAN_IRQ_TXLOSS))) {
+		del_timer(&priv->hang_timer);
+	}
+
+	/* Frame(s) received or transmitted */
+	if (sources & (GRCAN_IRQ_TX | GRCAN_IRQ_RX)) {
+		/* Disable tx/rx interrupts and schedule poll(). No need for
+		 * locking as interference from a running reset at worst leads
+		 * to an extra interrupt.
+		 */
+		grcan_clear_bits(&regs->imr, GRCAN_IRQ_TX | GRCAN_IRQ_RX);
+		napi_schedule(&priv->napi);
+	}
+
+	/* (Potential) error conditions to take care of */
+	if (sources & GRCAN_IRQ_ERRORS)
+		grcan_err(dev, sources, status);
+
+	return IRQ_HANDLED;
+}
+
+/* Reset device and restart operations from where they were.
+ *
+ * This assumes that RXCTRL & RXCTRL is properly disabled and that RX
+ * is not ONGOING (TX might be stuck in ONGOING due to a harwrware bug
+ * for single shot)
+ */
+static void grcan_running_reset(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_registers __iomem *regs = priv->regs;
+	unsigned long flags;
+
+	/* This temporarily messes with eskbp, so we need to lock
+	 * priv->lock
+	 */
+	spin_lock_irqsave(&priv->lock, flags);
+
+	priv->resetting = false;
+	del_timer(&priv->hang_timer);
+	del_timer(&priv->rr_timer);
+
+	if (!priv->closing) {
+		/* Save and reset - config register preserved by grcan_reset */
+		u32 imr = grcan_read_reg(&regs->imr);
+
+		u32 txaddr = grcan_read_reg(&regs->txaddr);
+		u32 txsize = grcan_read_reg(&regs->txsize);
+		u32 txwr = grcan_read_reg(&regs->txwr);
+		u32 txrd = grcan_read_reg(&regs->txrd);
+		u32 eskbp = priv->eskbp;
+
+		u32 rxaddr = grcan_read_reg(&regs->rxaddr);
+		u32 rxsize = grcan_read_reg(&regs->rxsize);
+		u32 rxwr = grcan_read_reg(&regs->rxwr);
+		u32 rxrd = grcan_read_reg(&regs->rxrd);
+
+		grcan_reset(dev);
+
+		/* Restore */
+		grcan_write_reg(&regs->txaddr, txaddr);
+		grcan_write_reg(&regs->txsize, txsize);
+		grcan_write_reg(&regs->txwr, txwr);
+		grcan_write_reg(&regs->txrd, txrd);
+		priv->eskbp = eskbp;
+
+		grcan_write_reg(&regs->rxaddr, rxaddr);
+		grcan_write_reg(&regs->rxsize, rxsize);
+		grcan_write_reg(&regs->rxwr, rxwr);
+		grcan_write_reg(&regs->rxrd, rxrd);
+
+		/* Turn on device again */
+		grcan_write_reg(&regs->imr, imr);
+		priv->can.state = CAN_STATE_ERROR_ACTIVE;
+		grcan_write_reg(&regs->txctrl, GRCAN_TXCTRL_ENABLE
+				| (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT
+				   ? GRCAN_TXCTRL_SINGLE : 0));
+		grcan_write_reg(&regs->rxctrl, GRCAN_RXCTRL_ENABLE);
+		grcan_write_reg(&regs->ctrl, GRCAN_CTRL_ENABLE);
+
+		/* Start queue if there is size and listen-onle mode is not
+		 * enabled
+		 */
+		if (grcan_txspace(priv->dma.tx.size, txwr, priv->eskbp) &&
+		    !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
+			netif_wake_queue(dev);
+	}
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	netdev_err(dev, "Device reset and restored\n");
+}
+
+/* Waiting time in usecs corresponding to the transmission of three maximum
+ * sized can frames in the given bitrate (in bits/sec). Waiting for this amount
+ * of time makes sure that the can controller have time to finish sending or
+ * receiving a frame with a good margin.
+ *
+ * usecs/sec * number of frames * bits/frame / bits/sec
+ */
+static inline u32 grcan_ongoing_wait_usecs(__u32 bitrate)
+{
+	return 1000000 * 3 * GRCAN_EFF_FRAME_MAX_BITS / bitrate;
+}
+
+/* Set timer so that it will not fire until after a period in which the can
+ * controller have a good margin to finish transmitting a frame unless it has
+ * hanged
+ */
+static inline void grcan_reset_timer(struct timer_list *timer, __u32 bitrate)
+{
+	u32 wait_jiffies = usecs_to_jiffies(grcan_ongoing_wait_usecs(bitrate));
+
+	mod_timer(timer, jiffies + wait_jiffies);
+}
+
+/* Disable channels and schedule a running reset */
+static void grcan_initiate_running_reset(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_registers __iomem *regs = priv->regs;
+	unsigned long flags;
+
+	netdev_err(dev, "Device seems hanged - reset scheduled\n");
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* The main body of this function must never be executed again
+	 * until after an execution of grcan_running_reset
+	 */
+	if (!priv->resetting && !priv->closing) {
+		priv->resetting = true;
+		netif_stop_queue(dev);
+		grcan_clear_bits(&regs->txctrl, GRCAN_TXCTRL_ENABLE);
+		grcan_clear_bits(&regs->rxctrl, GRCAN_RXCTRL_ENABLE);
+		grcan_reset_timer(&priv->rr_timer, priv->can.bittiming.bitrate);
+	}
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void grcan_free_dma_buffers(struct net_device *dev)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_dma *dma = &priv->dma;
+
+	dma_free_coherent(&dev->dev, dma->base_size, dma->base_buf,
+			  dma->base_handle);
+	memset(dma, 0, sizeof(*dma));
+}
+
+static int grcan_allocate_dma_buffers(struct net_device *dev,
+				      size_t tsize, size_t rsize)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_dma *dma = &priv->dma;
+	struct grcan_dma_buffer *large = rsize > tsize ? &dma->rx : &dma->tx;
+	struct grcan_dma_buffer *small = rsize > tsize ? &dma->tx : &dma->rx;
+	size_t shift;
+
+	/* Need a whole number of GRCAN_BUFFER_ALIGNMENT for the large,
+	 * i.e. first buffer
+	 */
+	size_t maxs = max(tsize, rsize);
+	size_t lsize = ALIGN(maxs, GRCAN_BUFFER_ALIGNMENT);
+
+	/* Put the small buffer after that */
+	size_t ssize = min(tsize, rsize);
+
+	/* Extra GRCAN_BUFFER_ALIGNMENT to allow for alignment */
+	dma->base_size = lsize + ssize + GRCAN_BUFFER_ALIGNMENT;
+	dma->base_buf = dma_alloc_coherent(&dev->dev,
+					   dma->base_size,
+					   &dma->base_handle,
+					   GFP_KERNEL);
+
+	if (!dma->base_buf)
+		return -ENOMEM;
+
+	dma->tx.size = tsize;
+	dma->rx.size = rsize;
+
+	large->handle = ALIGN(dma->base_handle, GRCAN_BUFFER_ALIGNMENT);
+	small->handle = large->handle + lsize;
+	shift = large->handle - dma->base_handle;
+
+	large->buf = dma->base_buf + shift;
+	small->buf = large->buf + lsize;
+
+	return 0;
+}
+
+/* priv->lock *must* be held when calling this function */
+static int grcan_start(struct net_device *dev)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_registers __iomem *regs = priv->regs;
+	u32 confop, txctrl;
+
+	grcan_reset(dev);
+
+	grcan_write_reg(&regs->txaddr, priv->dma.tx.handle);
+	grcan_write_reg(&regs->txsize, priv->dma.tx.size);
+	/* regs->txwr, regs->txrd and priv->eskbp already set to 0 by reset */
+
+	grcan_write_reg(&regs->rxaddr, priv->dma.rx.handle);
+	grcan_write_reg(&regs->rxsize, priv->dma.rx.size);
+	/* regs->rxwr and regs->rxrd already set to 0 by reset */
+
+	/* Enable interrupts */
+	grcan_read_reg(&regs->pir);
+	grcan_write_reg(&regs->imr, GRCAN_IRQ_DEFAULT);
+
+	/* Enable interfaces, channels and device */
+	confop = GRCAN_CONF_ABORT
+		| (priv->config.enable0 ? GRCAN_CONF_ENABLE0 : 0)
+		| (priv->config.enable1 ? GRCAN_CONF_ENABLE1 : 0)
+		| (priv->config.select ? GRCAN_CONF_SELECT : 0)
+		| (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY ?
+		   GRCAN_CONF_SILENT : 0)
+		| (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES ?
+		   GRCAN_CONF_SAM : 0);
+	grcan_write_bits(&regs->conf, confop, GRCAN_CONF_OPERATION);
+	txctrl = GRCAN_TXCTRL_ENABLE
+		| (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT
+		   ? GRCAN_TXCTRL_SINGLE : 0);
+	grcan_write_reg(&regs->txctrl, txctrl);
+	grcan_write_reg(&regs->rxctrl, GRCAN_RXCTRL_ENABLE);
+	grcan_write_reg(&regs->ctrl, GRCAN_CTRL_ENABLE);
+
+	priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+	return 0;
+}
+
+static int grcan_set_mode(struct net_device *dev, enum can_mode mode)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	unsigned long flags;
+	int err = 0;
+
+	if (mode == CAN_MODE_START) {
+		/* This might be called to restart the device to recover from
+		 * bus off errors
+		 */
+		spin_lock_irqsave(&priv->lock, flags);
+		if (priv->closing || priv->resetting) {
+			err = -EBUSY;
+		} else {
+			netdev_info(dev, "Restarting device\n");
+			grcan_start(dev);
+			if (!(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
+				netif_wake_queue(dev);
+		}
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return err;
+	}
+	return -EOPNOTSUPP;
+}
+
+static int grcan_open(struct net_device *dev)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_dma *dma = &priv->dma;
+	unsigned long flags;
+	int err;
+
+	/* Allocate memory */
+	err = grcan_allocate_dma_buffers(dev, priv->config.txsize,
+					 priv->config.rxsize);
+	if (err) {
+		netdev_err(dev, "could not allocate DMA buffers\n");
+		return err;
+	}
+
+	priv->echo_skb = kzalloc(dma->tx.size * sizeof(*priv->echo_skb),
+				 GFP_KERNEL);
+	if (!priv->echo_skb) {
+		err = -ENOMEM;
+		goto exit_free_dma_buffers;
+	}
+	priv->can.echo_skb_max = dma->tx.size;
+	priv->can.echo_skb = priv->echo_skb;
+
+	priv->txdlc = kzalloc(dma->tx.size * sizeof(*priv->txdlc), GFP_KERNEL);
+	if (!priv->txdlc) {
+		err = -ENOMEM;
+		goto exit_free_echo_skb;
+	}
+
+	/* Get can device up */
+	err = open_candev(dev);
+	if (err)
+		goto exit_free_txdlc;
+
+	err = request_irq(dev->irq, grcan_interrupt, IRQF_SHARED,
+			  dev->name, dev);
+	if (err)
+		goto exit_close_candev;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	napi_enable(&priv->napi);
+	grcan_start(dev);
+	if (!(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
+		netif_start_queue(dev);
+	priv->resetting = false;
+	priv->closing = false;
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+
+exit_close_candev:
+	close_candev(dev);
+exit_free_txdlc:
+	kfree(priv->txdlc);
+exit_free_echo_skb:
+	kfree(priv->echo_skb);
+exit_free_dma_buffers:
+	grcan_free_dma_buffers(dev);
+	return err;
+}
+
+static int grcan_close(struct net_device *dev)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	unsigned long flags;
+
+	napi_disable(&priv->napi);
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	priv->closing = true;
+	if (priv->need_txbug_workaround) {
+		del_timer_sync(&priv->hang_timer);
+		del_timer_sync(&priv->rr_timer);
+	}
+	netif_stop_queue(dev);
+	grcan_stop_hardware(dev);
+	priv->can.state = CAN_STATE_STOPPED;
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	free_irq(dev->irq, dev);
+	close_candev(dev);
+
+	grcan_free_dma_buffers(dev);
+	priv->can.echo_skb_max = 0;
+	priv->can.echo_skb = NULL;
+	kfree(priv->echo_skb);
+	kfree(priv->txdlc);
+
+	return 0;
+}
+
+static int grcan_transmit_catch_up(struct net_device *dev, int budget)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	unsigned long flags;
+	int work_done;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	work_done = catch_up_echo_skb(dev, budget, true);
+	if (work_done) {
+		if (!priv->resetting && !priv->closing &&
+		    !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
+			netif_wake_queue(dev);
+
+		/* With napi we don't get TX interrupts for a while,
+		 * so prevent a running reset while catching up
+		 */
+		if (priv->need_txbug_workaround)
+			del_timer(&priv->hang_timer);
+	}
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return work_done;
+}
+
+static int grcan_receive(struct net_device *dev, int budget)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_registers __iomem *regs = priv->regs;
+	struct grcan_dma *dma = &priv->dma;
+	struct net_device_stats *stats = &dev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	u32 wr, rd, startrd;
+	u32 *slot;
+	u32 i, rtr, eff, j, shift;
+	int work_done = 0;
+
+	rd = grcan_read_reg(&regs->rxrd);
+	startrd = rd;
+	for (work_done = 0; work_done < budget; work_done++) {
+		/* Check for packet to receive */
+		wr = grcan_read_reg(&regs->rxwr);
+		if (rd == wr)
+			break;
+
+		/* Take care of packet */
+		skb = alloc_can_skb(dev, &cf);
+		if (skb == NULL) {
+			netdev_err(dev,
+				   "dropping frame: skb allocation failed\n");
+			stats->rx_dropped++;
+			continue;
+		}
+
+		slot = dma->rx.buf + rd;
+		eff = slot[0] & GRCAN_MSG_IDE;
+		rtr = slot[0] & GRCAN_MSG_RTR;
+		if (eff) {
+			cf->can_id = ((slot[0] & GRCAN_MSG_EID)
+				      >> GRCAN_MSG_EID_BIT);
+			cf->can_id |= CAN_EFF_FLAG;
+		} else {
+			cf->can_id = ((slot[0] & GRCAN_MSG_BID)
+				      >> GRCAN_MSG_BID_BIT);
+		}
+		cf->can_dlc = get_can_dlc((slot[1] & GRCAN_MSG_DLC)
+					  >> GRCAN_MSG_DLC_BIT);
+		if (rtr) {
+			cf->can_id |= CAN_RTR_FLAG;
+		} else {
+			for (i = 0; i < cf->can_dlc; i++) {
+				j = GRCAN_MSG_DATA_SLOT_INDEX(i);
+				shift = GRCAN_MSG_DATA_SHIFT(i);
+				cf->data[i] = (u8)(slot[j] >> shift);
+			}
+		}
+		netif_receive_skb(skb);
+
+		/* Update statistics and read pointer */
+		stats->rx_packets++;
+		stats->rx_bytes += cf->can_dlc;
+		rd = grcan_ring_add(rd, GRCAN_MSG_SIZE, dma->rx.size);
+	}
+
+	/* Make sure everything is read before allowing hardware to
+	 * use the memory
+	 */
+	mb();
+
+	/* Update read pointer - no need to check for ongoing */
+	if (likely(rd != startrd))
+		grcan_write_reg(&regs->rxrd, rd);
+
+	return work_done;
+}
+
+static int grcan_poll(struct napi_struct *napi, int budget)
+{
+	struct grcan_priv *priv = container_of(napi, struct grcan_priv, napi);
+	struct net_device *dev = priv->dev;
+	struct grcan_registers __iomem *regs = priv->regs;
+	unsigned long flags;
+	int tx_work_done, rx_work_done;
+	int rx_budget = budget / 2;
+	int tx_budget = budget - rx_budget;
+
+	/* Half of the budget for receiveing messages */
+	rx_work_done = grcan_receive(dev, rx_budget);
+
+	/* Half of the budget for transmitting messages as that can trigger echo
+	 * frames being received
+	 */
+	tx_work_done = grcan_transmit_catch_up(dev, tx_budget);
+
+	if (rx_work_done < rx_budget && tx_work_done < tx_budget) {
+		napi_complete(napi);
+
+		/* Guarantee no interference with a running reset that otherwise
+		 * could turn off interrupts.
+		 */
+		spin_lock_irqsave(&priv->lock, flags);
+
+		/* Enable tx and rx interrupts again. No need to check
+		 * priv->closing as napi_disable in grcan_close is waiting for
+		 * scheduled napi calls to finish.
+		 */
+		grcan_set_bits(&regs->imr, GRCAN_IRQ_TX | GRCAN_IRQ_RX);
+
+		spin_unlock_irqrestore(&priv->lock, flags);
+	}
+
+	return rx_work_done + tx_work_done;
+}
+
+/* Work tx bug by waiting while for the risky situation to clear. If that fails,
+ * drop a frame in one-shot mode or indicate a busy device otherwise.
+ *
+ * Returns 0 on successful wait. Otherwise it sets *netdev_tx_status to the
+ * value that should be returned by grcan_start_xmit when aborting the xmit.
+ */
+static int grcan_txbug_workaround(struct net_device *dev, struct sk_buff *skb,
+				  u32 txwr, u32 oneshotmode,
+				  netdev_tx_t *netdev_tx_status)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_registers __iomem *regs = priv->regs;
+	struct grcan_dma *dma = &priv->dma;
+	int i;
+	unsigned long flags;
+
+	/* Wait a while for ongoing to be cleared or read pointer to catch up to
+	 * write pointer. The latter is needed due to a bug in older versions of
+	 * GRCAN in which ONGOING is not cleared properly one-shot mode when a
+	 * transmission fails.
+	 */
+	for (i = 0; i < GRCAN_SHORTWAIT_USECS; i++) {
+		udelay(1);
+		if (!grcan_read_bits(&regs->txctrl, GRCAN_TXCTRL_ONGOING) ||
+		    grcan_read_reg(&regs->txrd) == txwr) {
+			return 0;
+		}
+	}
+
+	/* Clean up, in case the situation was not resolved */
+	spin_lock_irqsave(&priv->lock, flags);
+	if (!priv->resetting && !priv->closing) {
+		/* Queue might have been stopped earlier in grcan_start_xmit */
+		if (grcan_txspace(dma->tx.size, txwr, priv->eskbp))
+			netif_wake_queue(dev);
+		/* Set a timer to resolve a hanged tx controller */
+		if (!timer_pending(&priv->hang_timer))
+			grcan_reset_timer(&priv->hang_timer,
+					  priv->can.bittiming.bitrate);
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (oneshotmode) {
+		/* In one-shot mode we should never end up here because
+		 * then the interrupt handler increases txrd on TXLOSS,
+		 * but it is consistent with one-shot mode to drop the
+		 * frame in this case.
+		 */
+		kfree_skb(skb);
+		*netdev_tx_status = NETDEV_TX_OK;
+	} else {
+		/* In normal mode the socket-can transmission queue get
+		 * to keep the frame so that it can be retransmitted
+		 * later
+		 */
+		*netdev_tx_status = NETDEV_TX_BUSY;
+	}
+	return -EBUSY;
+}
+
+/* Notes on the tx cyclic buffer handling:
+ *
+ * regs->txwr	- the next slot for the driver to put data to be sent
+ * regs->txrd	- the next slot for the device to read data
+ * priv->eskbp	- the next slot for the driver to call can_put_echo_skb for
+ *
+ * grcan_start_xmit can enter more messages as long as regs->txwr does
+ * not reach priv->eskbp (within 1 message gap)
+ *
+ * The device sends messages until regs->txrd reaches regs->txwr
+ *
+ * The interrupt calls handler calls can_put_echo_skb until
+ * priv->eskbp reaches regs->txrd
+ */
+static netdev_tx_t grcan_start_xmit(struct sk_buff *skb,
+				    struct net_device *dev)
+{
+	struct grcan_priv *priv = netdev_priv(dev);
+	struct grcan_registers __iomem *regs = priv->regs;
+	struct grcan_dma *dma = &priv->dma;
+	struct can_frame *cf = (struct can_frame *)skb->data;
+	u32 id, txwr, txrd, space, txctrl;
+	int slotindex;
+	u32 *slot;
+	u32 i, rtr, eff, dlc, tmp, err;
+	int j, shift;
+	unsigned long flags;
+	u32 oneshotmode = priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT;
+
+	if (can_dropped_invalid_skb(dev, skb))
+		return NETDEV_TX_OK;
+
+	/* Trying to transmit in silent mode will generate error interrupts, but
+	 * this should never happen - the queue should not have been started.
+	 */
+	if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+		return NETDEV_TX_BUSY;
+
+	/* Reads of priv->eskbp and shut-downs of the queue needs to
+	 * be atomic towards the updates to priv->eskbp and wake-ups
+	 * of the queue in the interrupt handler.
+	 */
+	spin_lock_irqsave(&priv->lock, flags);
+
+	txwr = grcan_read_reg(&regs->txwr);
+	space = grcan_txspace(dma->tx.size, txwr, priv->eskbp);
+
+	slotindex = txwr / GRCAN_MSG_SIZE;
+	slot = dma->tx.buf + txwr;
+
+	if (unlikely(space == 1))
+		netif_stop_queue(dev);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+	/* End of critical section*/
+
+	/* This should never happen. If circular buffer is full, the
+	 * netif_stop_queue should have been stopped already.
+	 */
+	if (unlikely(!space)) {
+		netdev_err(dev, "No buffer space, but queue is non-stopped.\n");
+		return NETDEV_TX_BUSY;
+	}
+
+	/* Convert and write CAN message to DMA buffer */
+	eff = cf->can_id & CAN_EFF_FLAG;
+	rtr = cf->can_id & CAN_RTR_FLAG;
+	id = cf->can_id & (eff ? CAN_EFF_MASK : CAN_SFF_MASK);
+	dlc = cf->can_dlc;
+	if (eff)
+		tmp = (id << GRCAN_MSG_EID_BIT) & GRCAN_MSG_EID;
+	else
+		tmp = (id << GRCAN_MSG_BID_BIT) & GRCAN_MSG_BID;
+	slot[0] = (eff ? GRCAN_MSG_IDE : 0) | (rtr ? GRCAN_MSG_RTR : 0) | tmp;
+
+	slot[1] = ((dlc << GRCAN_MSG_DLC_BIT) & GRCAN_MSG_DLC);
+	slot[2] = 0;
+	slot[3] = 0;
+	for (i = 0; i < dlc; i++) {
+		j = GRCAN_MSG_DATA_SLOT_INDEX(i);
+		shift = GRCAN_MSG_DATA_SHIFT(i);
+		slot[j] |= cf->data[i] << shift;
+	}
+
+	/* Checking that channel has not been disabled. These cases
+	 * should never happen
+	 */
+	txctrl = grcan_read_reg(&regs->txctrl);
+	if (!(txctrl & GRCAN_TXCTRL_ENABLE))
+		netdev_err(dev, "tx channel spuriously disabled\n");
+
+	if (oneshotmode && !(txctrl & GRCAN_TXCTRL_SINGLE))
+		netdev_err(dev, "one-shot mode spuriously disabled\n");
+
+	/* Bug workaround for old version of grcan where updating txwr
+	 * in the same clock cycle as the controller updates txrd to
+	 * the current txwr could hang the can controller
+	 */
+	if (priv->need_txbug_workaround) {
+		txrd = grcan_read_reg(&regs->txrd);
+		if (unlikely(grcan_ring_sub(txwr, txrd, dma->tx.size) == 1)) {
+			netdev_tx_t txstatus;
+
+			err = grcan_txbug_workaround(dev, skb, txwr,
+						     oneshotmode, &txstatus);
+			if (err)
+				return txstatus;
+		}
+	}
+
+	/* Prepare skb for echoing. This must be after the bug workaround above
+	 * as ownership of the skb is passed on by calling can_put_echo_skb.
+	 * Returning NETDEV_TX_BUSY or accessing skb or cf after a call to
+	 * can_put_echo_skb would be an error unless other measures are
+	 * taken.
+	 */
+	priv->txdlc[slotindex] = cf->can_dlc; /* Store dlc for statistics */
+	can_put_echo_skb(skb, dev, slotindex);
+
+	/* Make sure everything is written before allowing hardware to
+	 * read from the memory
+	 */
+	wmb();
+
+	/* Update write pointer to start transmission */
+	grcan_write_reg(&regs->txwr,
+			grcan_ring_add(txwr, GRCAN_MSG_SIZE, dma->tx.size));
+
+	return NETDEV_TX_OK;
+}
+
+/* ========== Setting up sysfs interface and module parameters ========== */
+
+#define GRCAN_NOT_BOOL(unsigned_val) ((unsigned_val) > 1)
+
+#define GRCAN_MODULE_PARAM(name, mtype, valcheckf, desc)		\
+	static void grcan_sanitize_##name(struct platform_device *pd)	\
+	{								\
+		struct grcan_device_config grcan_default_config		\
+			= GRCAN_DEFAULT_DEVICE_CONFIG;			\
+		if (valcheckf(grcan_module_config.name)) {		\
+			dev_err(&pd->dev,				\
+				"Invalid module parameter value for "	\
+				#name " - setting default\n");		\
+			grcan_module_config.name =			\
+				grcan_default_config.name;		\
+		}							\
+	}								\
+	module_param_named(name, grcan_module_config.name,		\
+			   mtype, S_IRUGO);				\
+	MODULE_PARM_DESC(name, desc)
+
+#define GRCAN_CONFIG_ATTR(name, desc)					\
+	static ssize_t grcan_store_##name(struct device *sdev,		\
+					  struct device_attribute *att,	\
+					  const char *buf,		\
+					  size_t count)			\
+	{								\
+		struct net_device *dev = to_net_dev(sdev);		\
+		struct grcan_priv *priv = netdev_priv(dev);		\
+		u8 val;							\
+		int ret;						\
+		if (dev->flags & IFF_UP)				\
+			return -EBUSY;					\
+		ret = kstrtou8(buf, 0, &val);				\
+		if (ret < 0 || val > 1)					\
+			return -EINVAL;					\
+		priv->config.name = val;				\
+		return count;						\
+	}								\
+	static ssize_t grcan_show_##name(struct device *sdev,		\
+					 struct device_attribute *att,	\
+					 char *buf)			\
+	{								\
+		struct net_device *dev = to_net_dev(sdev);		\
+		struct grcan_priv *priv = netdev_priv(dev);		\
+		return sprintf(buf, "%d\n", priv->config.name);		\
+	}								\
+	static DEVICE_ATTR(name, S_IRUGO | S_IWUSR,			\
+			   grcan_show_##name,				\
+			   grcan_store_##name);				\
+	GRCAN_MODULE_PARAM(name, ushort, GRCAN_NOT_BOOL, desc)
+
+/* The following configuration options are made available both via module
+ * parameters and writable sysfs files. See the chapter about GRCAN in the
+ * documentation for the GRLIB VHDL library for further details.
+ */
+GRCAN_CONFIG_ATTR(enable0,
+		  "Configuration of physical interface 0. Determines\n"	\
+		  "the \"Enable 0\" bit of the configuration register.\n" \
+		  "Format: 0 | 1\nDefault: 0\n");
+
+GRCAN_CONFIG_ATTR(enable1,
+		  "Configuration of physical interface 1. Determines\n"	\
+		  "the \"Enable 1\" bit of the configuration register.\n" \
+		  "Format: 0 | 1\nDefault: 0\n");
+
+GRCAN_CONFIG_ATTR(select,
+		  "Select which physical interface to use.\n"	\
+		  "Format: 0 | 1\nDefault: 0\n");
+
+/* The tx and rx buffer size configuration options are only available via module
+ * parameters.
+ */
+GRCAN_MODULE_PARAM(txsize, uint, GRCAN_INVALID_BUFFER_SIZE,
+		   "Sets the size of the tx buffer.\n"			\
+		   "Format: <unsigned int> where (txsize & ~0x1fffc0) == 0\n" \
+		   "Default: 1024\n");
+GRCAN_MODULE_PARAM(rxsize, uint, GRCAN_INVALID_BUFFER_SIZE,
+		   "Sets the size of the rx buffer.\n"			\
+		   "Format: <unsigned int> where (size & ~0x1fffc0) == 0\n" \
+		   "Default: 1024\n");
+
+/* Function that makes sure that configuration done using
+ * module parameters are set to valid values
+ */
+static void grcan_sanitize_module_config(struct platform_device *ofdev)
+{
+	grcan_sanitize_enable0(ofdev);
+	grcan_sanitize_enable1(ofdev);
+	grcan_sanitize_select(ofdev);
+	grcan_sanitize_txsize(ofdev);
+	grcan_sanitize_rxsize(ofdev);
+}
+
+static const struct attribute *const sysfs_grcan_attrs[] = {
+	/* Config attrs */
+	&dev_attr_enable0.attr,
+	&dev_attr_enable1.attr,
+	&dev_attr_select.attr,
+	NULL,
+};
+
+static const struct attribute_group sysfs_grcan_group = {
+	.name	= "grcan",
+	.attrs	= (struct attribute **)sysfs_grcan_attrs,
+};
+
+/* ========== Setting up the driver ========== */
+
+static const struct net_device_ops grcan_netdev_ops = {
+	.ndo_open	= grcan_open,
+	.ndo_stop	= grcan_close,
+	.ndo_start_xmit	= grcan_start_xmit,
+};
+
+static int grcan_setup_netdev(struct platform_device *ofdev,
+			      void __iomem *base,
+			      int irq, u32 ambafreq, bool txbug)
+{
+	struct net_device *dev;
+	struct grcan_priv *priv;
+	struct grcan_registers __iomem *regs;
+	int err;
+
+	dev = alloc_candev(sizeof(struct grcan_priv), 0);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->irq = irq;
+	dev->flags |= IFF_ECHO;
+	dev->netdev_ops = &grcan_netdev_ops;
+	dev->sysfs_groups[0] = &sysfs_grcan_group;
+
+	priv = netdev_priv(dev);
+	memcpy(&priv->config, &grcan_module_config,
+	       sizeof(struct grcan_device_config));
+	priv->dev = dev;
+	priv->regs = base;
+	priv->can.bittiming_const = &grcan_bittiming_const;
+	priv->can.do_set_bittiming = grcan_set_bittiming;
+	priv->can.do_set_mode = grcan_set_mode;
+	priv->can.do_get_berr_counter = grcan_get_berr_counter;
+	priv->can.clock.freq = ambafreq;
+	priv->can.ctrlmode_supported =
+		CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_ONE_SHOT;
+	priv->need_txbug_workaround = txbug;
+
+	/* Discover if triple sampling is supported by hardware */
+	regs = priv->regs;
+	grcan_set_bits(&regs->ctrl, GRCAN_CTRL_RESET);
+	grcan_set_bits(&regs->conf, GRCAN_CONF_SAM);
+	if (grcan_read_bits(&regs->conf, GRCAN_CONF_SAM)) {
+		priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
+		dev_dbg(&ofdev->dev, "Hardware supports triple-sampling\n");
+	}
+
+	spin_lock_init(&priv->lock);
+
+	if (priv->need_txbug_workaround) {
+		init_timer(&priv->rr_timer);
+		priv->rr_timer.function = grcan_running_reset;
+		priv->rr_timer.data = (unsigned long)dev;
+
+		init_timer(&priv->hang_timer);
+		priv->hang_timer.function = grcan_initiate_running_reset;
+		priv->hang_timer.data = (unsigned long)dev;
+	}
+
+	netif_napi_add(dev, &priv->napi, grcan_poll, GRCAN_NAPI_WEIGHT);
+
+	SET_NETDEV_DEV(dev, &ofdev->dev);
+	dev_info(&ofdev->dev, "regs=0x%p, irq=%d, clock=%d\n",
+		 priv->regs, dev->irq, priv->can.clock.freq);
+
+	err = register_candev(dev);
+	if (err)
+		goto exit_free_candev;
+
+	dev_set_drvdata(&ofdev->dev, dev);
+
+	/* Reset device to allow bit-timing to be set. No need to call
+	 * grcan_reset at this stage. That is done in grcan_open.
+	 */
+	grcan_write_reg(&regs->ctrl, GRCAN_CTRL_RESET);
+
+	return 0;
+exit_free_candev:
+	free_candev(dev);
+	return err;
+}
+
+static int __devinit grcan_probe(struct platform_device *ofdev)
+{
+	struct device_node *np = ofdev->dev.of_node;
+	struct resource *res;
+	u32 sysid, ambafreq;
+	int irq, err;
+	void __iomem *base;
+	bool txbug = true;
+
+	/* Compare GRLIB version number with the first that does not
+	 * have the tx bug (see start_xmit)
+	 */
+	err = of_property_read_u32(np, "systemid", &sysid);
+	if (!err && ((sysid & GRLIB_VERSION_MASK)
+		     >= GRCAN_TXBUG_SAFE_GRLIB_VERSION))
+		txbug = false;
+
+	err = of_property_read_u32(np, "freq", &ambafreq);
+	if (err) {
+		dev_err(&ofdev->dev, "unable to fetch \"freq\" property\n");
+		goto exit_error;
+	}
+
+	res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
+	base = devm_request_and_ioremap(&ofdev->dev, res);
+	if (!base) {
+		dev_err(&ofdev->dev, "couldn't map IO resource\n");
+		err = -EADDRNOTAVAIL;
+		goto exit_error;
+	}
+
+	irq = irq_of_parse_and_map(np, GRCAN_IRQIX_IRQ);
+	if (!irq) {
+		dev_err(&ofdev->dev, "no irq found\n");
+		err = -ENODEV;
+		goto exit_error;
+	}
+
+	grcan_sanitize_module_config(ofdev);
+
+	err = grcan_setup_netdev(ofdev, base, irq, ambafreq, txbug);
+	if (err)
+		goto exit_dispose_irq;
+
+	return 0;
+
+exit_dispose_irq:
+	irq_dispose_mapping(irq);
+exit_error:
+	dev_err(&ofdev->dev,
+		"%s socket CAN driver initialization failed with error %d\n",
+		DRV_NAME, err);
+	return err;
+}
+
+static int __devexit grcan_remove(struct platform_device *ofdev)
+{
+	struct net_device *dev = dev_get_drvdata(&ofdev->dev);
+	struct grcan_priv *priv = netdev_priv(dev);
+
+	unregister_candev(dev); /* Will in turn call grcan_close */
+
+	irq_dispose_mapping(dev->irq);
+	dev_set_drvdata(&ofdev->dev, NULL);
+	netif_napi_del(&priv->napi);
+	free_candev(dev);
+
+	return 0;
+}
+
+static struct of_device_id grcan_match[] __devinitconst = {
+	{.name = "GAISLER_GRCAN"},
+	{.name = "01_03d"},
+	{.name = "GAISLER_GRHCAN"},
+	{.name = "01_034"},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, grcan_match);
+
+static struct platform_driver grcan_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = grcan_match,
+	},
+	.probe = grcan_probe,
+	.remove = __devexit_p(grcan_remove),
+};
+
+module_platform_driver(grcan_driver);
+
+MODULE_AUTHOR("Aeroflex Gaisler AB.");
+MODULE_DESCRIPTION("Socket CAN driver for Aeroflex Gaisler GRCAN");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
index 7edadee..c0bfb0a 100644
--- a/drivers/net/can/janz-ican3.c
+++ b/drivers/net/can/janz-ican3.c
@@ -1692,7 +1692,7 @@ static int ican3_get_berr_counter(const struct net_device *ndev,
 		return ret;
 
 	ret = wait_for_completion_timeout(&mod->buserror_comp, HZ);
-	if (ret <= 0) {
+	if (ret == 0) {
 		dev_info(mod->dev, "%s timed out\n", __func__);
 		return -ETIMEDOUT;
 	}
@@ -1718,7 +1718,7 @@ static ssize_t ican3_sysfs_show_term(struct device *dev,
 		return ret;
 
 	ret = wait_for_completion_timeout(&mod->termination_comp, HZ);
-	if (ret <= 0) {
+	if (ret == 0) {
 		dev_info(mod->dev, "%s timed out\n", __func__);
 		return -ETIMEDOUT;
 	}
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 799c354..514d020 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -396,6 +396,7 @@ static const struct of_device_id __devinitconst mpc5xxx_can_table[] = {
 	{ .compatible = "fsl,mpc5121-mscan", .data = &mpc5121_can_data, },
 	{},
 };
+MODULE_DEVICE_TABLE(of, mpc5xxx_can_table);
 
 static struct platform_driver mpc5xxx_can_driver = {
 	.driver = {
diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig
index 03df9a8..92f73c7 100644
--- a/drivers/net/can/sja1000/Kconfig
+++ b/drivers/net/can/sja1000/Kconfig
@@ -21,7 +21,7 @@ config CAN_SJA1000_PLATFORM
 
 config CAN_SJA1000_OF_PLATFORM
 	tristate "Generic OF Platform Bus based SJA1000 driver"
-	depends on PPC_OF
+	depends on OF
 	---help---
 	  This driver adds support for the SJA1000 chips connected to
 	  the OpenFirmware "platform bus" found on embedded systems with
@@ -93,6 +93,7 @@ config CAN_PLX_PCI
 	   - Marathon CAN-bus-PCI card (http://www.marathon.ru/)
 	   - TEWS TECHNOLOGIES TPMC810 card (http://www.tews.com/)
 	   - IXXAT Automation PC-I 04/PCI card (http://www.ixxat.com/)
+	   - Connect Tech Inc. CANpro/104-Plus Opto (CRG001) card (http://www.connecttech.com)
 
 config CAN_TSCAN1
 	tristate "TS-CAN1 PC104 boards"
diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c
index 8bc9598..dc04407 100644
--- a/drivers/net/can/sja1000/plx_pci.c
+++ b/drivers/net/can/sja1000/plx_pci.c
@@ -44,6 +44,7 @@ MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, "
 			"esd CAN-PCI/CPCI/PCI104/200, "
 			"esd CAN-PCI/PMC/266, "
 			"esd CAN-PCIe/2000, "
+			"Connect Tech Inc. CANpro/104-Plus Opto (CRG001), "
 			"IXXAT PC-I 04/PCI")
 MODULE_LICENSE("GPL v2");
 
@@ -131,6 +132,9 @@ struct plx_pci_card {
 #define TEWS_PCI_VENDOR_ID		0x1498
 #define TEWS_PCI_DEVICE_ID_TMPC810	0x032A
 
+#define CTI_PCI_VENDOR_ID		0x12c4
+#define CTI_PCI_DEVICE_ID_CRG001	0x0900
+
 static void plx_pci_reset_common(struct pci_dev *pdev);
 static void plx_pci_reset_marathon(struct pci_dev *pdev);
 static void plx9056_pci_reset_common(struct pci_dev *pdev);
@@ -222,6 +226,14 @@ static struct plx_pci_card_info plx_pci_card_info_tews __devinitdata = {
 	/* based on PLX9030 */
 };
 
+static struct plx_pci_card_info plx_pci_card_info_cti __devinitdata = {
+	"Connect Tech Inc. CANpro/104-Plus Opto (CRG001)", 2,
+	PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
+	{0, 0x00, 0x00}, { {2, 0x000, 0x80}, {2, 0x100, 0x80} },
+	&plx_pci_reset_common
+	/* based on PLX9030 */
+};
+
 static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = {
 	{
 		/* Adlink PCI-7841/cPCI-7841 */
@@ -300,6 +312,13 @@ static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = {
 		0, 0,
 		(kernel_ulong_t)&plx_pci_card_info_tews
 	},
+	{
+		/* Connect Tech Inc. CANpro/104-Plus Opto (CRG001) card */
+		PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
+		CTI_PCI_VENDOR_ID, CTI_PCI_DEVICE_ID_CRG001,
+		0, 0,
+		(kernel_ulong_t)&plx_pci_card_info_cti
+	},
 	{ 0,}
 };
 MODULE_DEVICE_TABLE(pci, plx_pci_tbl);
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
index f2683eb..e45258d 100644
--- a/drivers/net/can/sja1000/sja1000_of_platform.c
+++ b/drivers/net/can/sja1000/sja1000_of_platform.c
@@ -42,6 +42,8 @@
 #include <linux/can/dev.h>
 
 #include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <asm/prom.h>
 
 #include "sja1000.h"
@@ -59,13 +61,13 @@ MODULE_LICENSE("GPL v2");
 
 static u8 sja1000_ofp_read_reg(const struct sja1000_priv *priv, int reg)
 {
-	return in_8(priv->reg_base + reg);
+	return ioread8(priv->reg_base + reg);
 }
 
 static void sja1000_ofp_write_reg(const struct sja1000_priv *priv,
 				  int reg, u8 val)
 {
-	out_8(priv->reg_base + reg, val);
+	iowrite8(val, priv->reg_base + reg);
 }
 
 static int __devexit sja1000_ofp_remove(struct platform_device *ofdev)
diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c
index 662c5f7..21619bb 100644
--- a/drivers/net/can/sja1000/sja1000_platform.c
+++ b/drivers/net/can/sja1000/sja1000_platform.c
@@ -34,6 +34,7 @@
 
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
 MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the platform bus");
+MODULE_ALIAS("platform:" DRV_NAME);
 MODULE_LICENSE("GPL v2");
 
 static u8 sp_read_reg8(const struct sja1000_priv *priv, int reg)
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index 9ded21e..1267b36 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -1055,3 +1055,4 @@ module_platform_driver(ti_hecc_driver);
 MODULE_AUTHOR("Anant Gole <anantgole@ti.com>");
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION(DRV_DESC);
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig
index 0a68768..a4e4bee 100644
--- a/drivers/net/can/usb/Kconfig
+++ b/drivers/net/can/usb/Kconfig
@@ -13,6 +13,35 @@ config CAN_ESD_USB2
           This driver supports the CAN-USB/2 interface
           from esd electronic system design gmbh (http://www.esd.eu).
 
+config CAN_KVASER_USB
+	tristate "Kvaser CAN/USB interface"
+	---help---
+	  This driver adds support for Kvaser CAN/USB devices like Kvaser
+	  Leaf Light.
+
+	  The driver gives support for the following devices:
+	    - Kvaser Leaf Light
+	    - Kvaser Leaf Professional HS
+	    - Kvaser Leaf SemiPro HS
+	    - Kvaser Leaf Professional LS
+	    - Kvaser Leaf Professional SWC
+	    - Kvaser Leaf Professional LIN
+	    - Kvaser Leaf SemiPro LS
+	    - Kvaser Leaf SemiPro SWC
+	    - Kvaser Memorator II HS/HS
+	    - Kvaser USBcan Professional HS/HS
+	    - Kvaser Leaf Light GI
+	    - Kvaser Leaf Professional HS (OBD-II connector)
+	    - Kvaser Memorator Professional HS/LS
+	    - Kvaser Leaf Light "China"
+	    - Kvaser BlackBird SemiPro
+	    - Kvaser USBcan R
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called kvaser_usb.
+
 config CAN_PEAK_USB
 	tristate "PEAK PCAN-USB/USB Pro interfaces"
 	---help---
diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile
index da6d1d3..80a2ee4 100644
--- a/drivers/net/can/usb/Makefile
+++ b/drivers/net/can/usb/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o
 obj-$(CONFIG_CAN_ESD_USB2) += esd_usb2.o
+obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o
 obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/
 
 ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c
index bd36e55..124e0dd 100644
--- a/drivers/net/can/usb/esd_usb2.c
+++ b/drivers/net/can/usb/esd_usb2.c
@@ -1,7 +1,7 @@
 /*
- * CAN driver for esd CAN-USB/2
+ * CAN driver for esd CAN-USB/2 and CAN-USB/Micro
  *
- * Copyright (C) 2010 Matthias Fuchs <matthias.fuchs@esd.eu>, esd gmbh
+ * Copyright (C) 2010-2012 Matthias Fuchs <matthias.fuchs@esd.eu>, esd gmbh
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published
@@ -28,14 +28,16 @@
 #include <linux/can/error.h>
 
 MODULE_AUTHOR("Matthias Fuchs <matthias.fuchs@esd.eu>");
-MODULE_DESCRIPTION("CAN driver for esd CAN-USB/2 interfaces");
+MODULE_DESCRIPTION("CAN driver for esd CAN-USB/2 and CAN-USB/Micro interfaces");
 MODULE_LICENSE("GPL v2");
 
 /* Define these values to match your devices */
 #define USB_ESDGMBH_VENDOR_ID	0x0ab4
 #define USB_CANUSB2_PRODUCT_ID	0x0010
+#define USB_CANUSBM_PRODUCT_ID	0x0011
 
 #define ESD_USB2_CAN_CLOCK	60000000
+#define ESD_USBM_CAN_CLOCK	36000000
 #define ESD_USB2_MAX_NETS	2
 
 /* USB2 commands */
@@ -69,6 +71,7 @@ MODULE_LICENSE("GPL v2");
 #define ESD_USB2_TSEG2_SHIFT	20
 #define ESD_USB2_SJW_MAX	4
 #define ESD_USB2_SJW_SHIFT	14
+#define ESD_USBM_SJW_SHIFT	24
 #define ESD_USB2_BRP_MIN	1
 #define ESD_USB2_BRP_MAX	1024
 #define ESD_USB2_BRP_INC	1
@@ -183,6 +186,7 @@ struct __attribute__ ((packed)) esd_usb2_msg {
 
 static struct usb_device_id esd_usb2_table[] = {
 	{USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSB2_PRODUCT_ID)},
+	{USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSBM_PRODUCT_ID)},
 	{}
 };
 MODULE_DEVICE_TABLE(usb, esd_usb2_table);
@@ -889,11 +893,22 @@ static int esd_usb2_set_bittiming(struct net_device *netdev)
 	struct can_bittiming *bt = &priv->can.bittiming;
 	struct esd_usb2_msg msg;
 	u32 canbtr;
+	int sjw_shift;
 
 	canbtr = ESD_USB2_UBR;
+	if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+		canbtr |= ESD_USB2_LOM;
+
 	canbtr |= (bt->brp - 1) & (ESD_USB2_BRP_MAX - 1);
+
+	if (le16_to_cpu(priv->usb2->udev->descriptor.idProduct) ==
+	    USB_CANUSBM_PRODUCT_ID)
+		sjw_shift = ESD_USBM_SJW_SHIFT;
+	else
+		sjw_shift = ESD_USB2_SJW_SHIFT;
+
 	canbtr |= ((bt->sjw - 1) & (ESD_USB2_SJW_MAX - 1))
-		<< ESD_USB2_SJW_SHIFT;
+		<< sjw_shift;
 	canbtr |= ((bt->prop_seg + bt->phase_seg1 - 1)
 		   & (ESD_USB2_TSEG1_MAX - 1))
 		<< ESD_USB2_TSEG1_SHIFT;
@@ -971,12 +986,20 @@ static int esd_usb2_probe_one_net(struct usb_interface *intf, int index)
 	priv->index = index;
 
 	priv->can.state = CAN_STATE_STOPPED;
-	priv->can.clock.freq = ESD_USB2_CAN_CLOCK;
+	priv->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY;
+
+	if (le16_to_cpu(dev->udev->descriptor.idProduct) ==
+	    USB_CANUSBM_PRODUCT_ID)
+		priv->can.clock.freq = ESD_USBM_CAN_CLOCK;
+	else {
+		priv->can.clock.freq = ESD_USB2_CAN_CLOCK;
+		priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
+	}
+
 	priv->can.bittiming_const = &esd_usb2_bittiming_const;
 	priv->can.do_set_bittiming = esd_usb2_set_bittiming;
 	priv->can.do_set_mode = esd_usb2_set_mode;
 	priv->can.do_get_berr_counter = esd_usb2_get_berr_counter;
-	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
 
 	netdev->flags |= IFF_ECHO; /* we support local echo */
 
diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c
new file mode 100644
index 0000000..5b58a4d
--- /dev/null
+++ b/drivers/net/can/usb/kvaser_usb.c
@@ -0,0 +1,1627 @@
+/*
+ * This program is free software; 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.
+ *
+ * Parts of this driver are based on the following:
+ *  - Kvaser linux leaf driver (version 4.78)
+ *  - CAN driver for esd CAN-USB/2
+ *
+ * Copyright (C) 2002-2006 KVASER AB, Sweden. All rights reserved.
+ * Copyright (C) 2010 Matthias Fuchs <matthias.fuchs@esd.eu>, esd gmbh
+ * Copyright (C) 2012 Olivier Sobrie <olivier@sobrie.be>
+ */
+
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/usb.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+
+#define MAX_TX_URBS			16
+#define MAX_RX_URBS			4
+#define START_TIMEOUT			1000 /* msecs */
+#define STOP_TIMEOUT			1000 /* msecs */
+#define USB_SEND_TIMEOUT		1000 /* msecs */
+#define USB_RECV_TIMEOUT		1000 /* msecs */
+#define RX_BUFFER_SIZE			3072
+#define CAN_USB_CLOCK			8000000
+#define MAX_NET_DEVICES			3
+
+/* Kvaser USB devices */
+#define KVASER_VENDOR_ID		0x0bfd
+#define USB_LEAF_DEVEL_PRODUCT_ID	10
+#define USB_LEAF_LITE_PRODUCT_ID	11
+#define USB_LEAF_PRO_PRODUCT_ID		12
+#define USB_LEAF_SPRO_PRODUCT_ID	14
+#define USB_LEAF_PRO_LS_PRODUCT_ID	15
+#define USB_LEAF_PRO_SWC_PRODUCT_ID	16
+#define USB_LEAF_PRO_LIN_PRODUCT_ID	17
+#define USB_LEAF_SPRO_LS_PRODUCT_ID	18
+#define USB_LEAF_SPRO_SWC_PRODUCT_ID	19
+#define USB_MEMO2_DEVEL_PRODUCT_ID	22
+#define USB_MEMO2_HSHS_PRODUCT_ID	23
+#define USB_UPRO_HSHS_PRODUCT_ID	24
+#define USB_LEAF_LITE_GI_PRODUCT_ID	25
+#define USB_LEAF_PRO_OBDII_PRODUCT_ID	26
+#define USB_MEMO2_HSLS_PRODUCT_ID	27
+#define USB_LEAF_LITE_CH_PRODUCT_ID	28
+#define USB_BLACKBIRD_SPRO_PRODUCT_ID	29
+#define USB_OEM_MERCURY_PRODUCT_ID	34
+#define USB_OEM_LEAF_PRODUCT_ID		35
+#define USB_CAN_R_PRODUCT_ID		39
+
+/* USB devices features */
+#define KVASER_HAS_SILENT_MODE		BIT(0)
+#define KVASER_HAS_TXRX_ERRORS		BIT(1)
+
+/* Message header size */
+#define MSG_HEADER_LEN			2
+
+/* Can message flags */
+#define MSG_FLAG_ERROR_FRAME		BIT(0)
+#define MSG_FLAG_OVERRUN		BIT(1)
+#define MSG_FLAG_NERR			BIT(2)
+#define MSG_FLAG_WAKEUP			BIT(3)
+#define MSG_FLAG_REMOTE_FRAME		BIT(4)
+#define MSG_FLAG_RESERVED		BIT(5)
+#define MSG_FLAG_TX_ACK			BIT(6)
+#define MSG_FLAG_TX_REQUEST		BIT(7)
+
+/* Can states */
+#define M16C_STATE_BUS_RESET		BIT(0)
+#define M16C_STATE_BUS_ERROR		BIT(4)
+#define M16C_STATE_BUS_PASSIVE		BIT(5)
+#define M16C_STATE_BUS_OFF		BIT(6)
+
+/* Can msg ids */
+#define CMD_RX_STD_MESSAGE		12
+#define CMD_TX_STD_MESSAGE		13
+#define CMD_RX_EXT_MESSAGE		14
+#define CMD_TX_EXT_MESSAGE		15
+#define CMD_SET_BUS_PARAMS		16
+#define CMD_GET_BUS_PARAMS		17
+#define CMD_GET_BUS_PARAMS_REPLY	18
+#define CMD_GET_CHIP_STATE		19
+#define CMD_CHIP_STATE_EVENT		20
+#define CMD_SET_CTRL_MODE		21
+#define CMD_GET_CTRL_MODE		22
+#define CMD_GET_CTRL_MODE_REPLY		23
+#define CMD_RESET_CHIP			24
+#define CMD_RESET_CARD			25
+#define CMD_START_CHIP			26
+#define CMD_START_CHIP_REPLY		27
+#define CMD_STOP_CHIP			28
+#define CMD_STOP_CHIP_REPLY		29
+#define CMD_GET_CARD_INFO2		32
+#define CMD_GET_CARD_INFO		34
+#define CMD_GET_CARD_INFO_REPLY		35
+#define CMD_GET_SOFTWARE_INFO		38
+#define CMD_GET_SOFTWARE_INFO_REPLY	39
+#define CMD_ERROR_EVENT			45
+#define CMD_FLUSH_QUEUE			48
+#define CMD_RESET_ERROR_COUNTER		49
+#define CMD_TX_ACKNOWLEDGE		50
+#define CMD_CAN_ERROR_EVENT		51
+#define CMD_USB_THROTTLE		77
+#define CMD_LOG_MESSAGE			106
+
+/* error factors */
+#define M16C_EF_ACKE			BIT(0)
+#define M16C_EF_CRCE			BIT(1)
+#define M16C_EF_FORME			BIT(2)
+#define M16C_EF_STFE			BIT(3)
+#define M16C_EF_BITE0			BIT(4)
+#define M16C_EF_BITE1			BIT(5)
+#define M16C_EF_RCVE			BIT(6)
+#define M16C_EF_TRE			BIT(7)
+
+/* bittiming parameters */
+#define KVASER_USB_TSEG1_MIN		1
+#define KVASER_USB_TSEG1_MAX		16
+#define KVASER_USB_TSEG2_MIN		1
+#define KVASER_USB_TSEG2_MAX		8
+#define KVASER_USB_SJW_MAX		4
+#define KVASER_USB_BRP_MIN		1
+#define KVASER_USB_BRP_MAX		64
+#define KVASER_USB_BRP_INC		1
+
+/* ctrl modes */
+#define KVASER_CTRL_MODE_NORMAL		1
+#define KVASER_CTRL_MODE_SILENT		2
+#define KVASER_CTRL_MODE_SELFRECEPTION	3
+#define KVASER_CTRL_MODE_OFF		4
+
+struct kvaser_msg_simple {
+	u8 tid;
+	u8 channel;
+} __packed;
+
+struct kvaser_msg_cardinfo {
+	u8 tid;
+	u8 nchannels;
+	__le32 serial_number;
+	__le32 padding;
+	__le32 clock_resolution;
+	__le32 mfgdate;
+	u8 ean[8];
+	u8 hw_revision;
+	u8 usb_hs_mode;
+	__le16 padding2;
+} __packed;
+
+struct kvaser_msg_cardinfo2 {
+	u8 tid;
+	u8 channel;
+	u8 pcb_id[24];
+	__le32 oem_unlock_code;
+} __packed;
+
+struct kvaser_msg_softinfo {
+	u8 tid;
+	u8 channel;
+	__le32 sw_options;
+	__le32 fw_version;
+	__le16 max_outstanding_tx;
+	__le16 padding[9];
+} __packed;
+
+struct kvaser_msg_busparams {
+	u8 tid;
+	u8 channel;
+	__le32 bitrate;
+	u8 tseg1;
+	u8 tseg2;
+	u8 sjw;
+	u8 no_samp;
+} __packed;
+
+struct kvaser_msg_tx_can {
+	u8 channel;
+	u8 tid;
+	u8 msg[14];
+	u8 padding;
+	u8 flags;
+} __packed;
+
+struct kvaser_msg_rx_can {
+	u8 channel;
+	u8 flag;
+	__le16 time[3];
+	u8 msg[14];
+} __packed;
+
+struct kvaser_msg_chip_state_event {
+	u8 tid;
+	u8 channel;
+	__le16 time[3];
+	u8 tx_errors_count;
+	u8 rx_errors_count;
+	u8 status;
+	u8 padding[3];
+} __packed;
+
+struct kvaser_msg_tx_acknowledge {
+	u8 channel;
+	u8 tid;
+	__le16 time[3];
+	u8 flags;
+	u8 time_offset;
+} __packed;
+
+struct kvaser_msg_error_event {
+	u8 tid;
+	u8 flags;
+	__le16 time[3];
+	u8 channel;
+	u8 padding;
+	u8 tx_errors_count;
+	u8 rx_errors_count;
+	u8 status;
+	u8 error_factor;
+} __packed;
+
+struct kvaser_msg_ctrl_mode {
+	u8 tid;
+	u8 channel;
+	u8 ctrl_mode;
+	u8 padding[3];
+} __packed;
+
+struct kvaser_msg_flush_queue {
+	u8 tid;
+	u8 channel;
+	u8 flags;
+	u8 padding[3];
+} __packed;
+
+struct kvaser_msg_log_message {
+	u8 channel;
+	u8 flags;
+	__le16 time[3];
+	u8 dlc;
+	u8 time_offset;
+	__le32 id;
+	u8 data[8];
+} __packed;
+
+struct kvaser_msg {
+	u8 len;
+	u8 id;
+	union	{
+		struct kvaser_msg_simple simple;
+		struct kvaser_msg_cardinfo cardinfo;
+		struct kvaser_msg_cardinfo2 cardinfo2;
+		struct kvaser_msg_softinfo softinfo;
+		struct kvaser_msg_busparams busparams;
+		struct kvaser_msg_tx_can tx_can;
+		struct kvaser_msg_rx_can rx_can;
+		struct kvaser_msg_chip_state_event chip_state_event;
+		struct kvaser_msg_tx_acknowledge tx_acknowledge;
+		struct kvaser_msg_error_event error_event;
+		struct kvaser_msg_ctrl_mode ctrl_mode;
+		struct kvaser_msg_flush_queue flush_queue;
+		struct kvaser_msg_log_message log_message;
+	} u;
+} __packed;
+
+struct kvaser_usb_tx_urb_context {
+	struct kvaser_usb_net_priv *priv;
+	u32 echo_index;
+	int dlc;
+};
+
+struct kvaser_usb {
+	struct usb_device *udev;
+	struct kvaser_usb_net_priv *nets[MAX_NET_DEVICES];
+
+	struct usb_endpoint_descriptor *bulk_in, *bulk_out;
+	struct usb_anchor rx_submitted;
+
+	u32 fw_version;
+	unsigned int nchannels;
+
+	bool rxinitdone;
+	void *rxbuf[MAX_RX_URBS];
+	dma_addr_t rxbuf_dma[MAX_RX_URBS];
+};
+
+struct kvaser_usb_net_priv {
+	struct can_priv can;
+
+	atomic_t active_tx_urbs;
+	struct usb_anchor tx_submitted;
+	struct kvaser_usb_tx_urb_context tx_contexts[MAX_TX_URBS];
+
+	struct completion start_comp, stop_comp;
+
+	struct kvaser_usb *dev;
+	struct net_device *netdev;
+	int channel;
+
+	struct can_berr_counter bec;
+};
+
+static const struct usb_device_id kvaser_usb_table[] = {
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_DEVEL_PRODUCT_ID) },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_PRODUCT_ID) },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS |
+			       KVASER_HAS_SILENT_MODE },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS |
+			       KVASER_HAS_SILENT_MODE },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LS_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS |
+			       KVASER_HAS_SILENT_MODE },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_SWC_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS |
+			       KVASER_HAS_SILENT_MODE },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LIN_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS |
+			       KVASER_HAS_SILENT_MODE },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_LS_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS |
+			       KVASER_HAS_SILENT_MODE },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_SWC_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS |
+			       KVASER_HAS_SILENT_MODE },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_DEVEL_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS |
+			       KVASER_HAS_SILENT_MODE },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSHS_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS |
+			       KVASER_HAS_SILENT_MODE },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_UPRO_HSHS_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_GI_PRODUCT_ID) },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_OBDII_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS |
+			       KVASER_HAS_SILENT_MODE },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSLS_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_CH_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_SPRO_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_MERCURY_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_LEAF_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_CAN_R_PRODUCT_ID),
+		.driver_info = KVASER_HAS_TXRX_ERRORS },
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, kvaser_usb_table);
+
+static inline int kvaser_usb_send_msg(const struct kvaser_usb *dev,
+				      struct kvaser_msg *msg)
+{
+	int actual_len;
+
+	return usb_bulk_msg(dev->udev,
+			    usb_sndbulkpipe(dev->udev,
+					dev->bulk_out->bEndpointAddress),
+			    msg, msg->len, &actual_len,
+			    USB_SEND_TIMEOUT);
+}
+
+static int kvaser_usb_wait_msg(const struct kvaser_usb *dev, u8 id,
+			       struct kvaser_msg *msg)
+{
+	struct kvaser_msg *tmp;
+	void *buf;
+	int actual_len;
+	int err;
+	int pos = 0;
+
+	buf = kzalloc(RX_BUFFER_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	err = usb_bulk_msg(dev->udev,
+			   usb_rcvbulkpipe(dev->udev,
+					   dev->bulk_in->bEndpointAddress),
+			   buf, RX_BUFFER_SIZE, &actual_len,
+			   USB_RECV_TIMEOUT);
+	if (err < 0)
+		goto end;
+
+	while (pos <= actual_len - MSG_HEADER_LEN) {
+		tmp = buf + pos;
+
+		if (!tmp->len)
+			break;
+
+		if (pos + tmp->len > actual_len) {
+			dev_err(dev->udev->dev.parent, "Format error\n");
+			break;
+		}
+
+		if (tmp->id == id) {
+			memcpy(msg, tmp, tmp->len);
+			goto end;
+		}
+
+		pos += tmp->len;
+	}
+
+	err = -EINVAL;
+
+end:
+	kfree(buf);
+
+	return err;
+}
+
+static int kvaser_usb_send_simple_msg(const struct kvaser_usb *dev,
+				      u8 msg_id, int channel)
+{
+	struct kvaser_msg *msg;
+	int rc;
+
+	msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	msg->id = msg_id;
+	msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_simple);
+	msg->u.simple.channel = channel;
+	msg->u.simple.tid = 0xff;
+
+	rc = kvaser_usb_send_msg(dev, msg);
+
+	kfree(msg);
+	return rc;
+}
+
+static int kvaser_usb_get_software_info(struct kvaser_usb *dev)
+{
+	struct kvaser_msg msg;
+	int err;
+
+	err = kvaser_usb_send_simple_msg(dev, CMD_GET_SOFTWARE_INFO, 0);
+	if (err)
+		return err;
+
+	err = kvaser_usb_wait_msg(dev, CMD_GET_SOFTWARE_INFO_REPLY, &msg);
+	if (err)
+		return err;
+
+	dev->fw_version = le32_to_cpu(msg.u.softinfo.fw_version);
+
+	return 0;
+}
+
+static int kvaser_usb_get_card_info(struct kvaser_usb *dev)
+{
+	struct kvaser_msg msg;
+	int err;
+
+	err = kvaser_usb_send_simple_msg(dev, CMD_GET_CARD_INFO, 0);
+	if (err)
+		return err;
+
+	err = kvaser_usb_wait_msg(dev, CMD_GET_CARD_INFO_REPLY, &msg);
+	if (err)
+		return err;
+
+	dev->nchannels = msg.u.cardinfo.nchannels;
+
+	return 0;
+}
+
+static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev,
+				      const struct kvaser_msg *msg)
+{
+	struct net_device_stats *stats;
+	struct kvaser_usb_tx_urb_context *context;
+	struct kvaser_usb_net_priv *priv;
+	struct sk_buff *skb;
+	struct can_frame *cf;
+	u8 channel = msg->u.tx_acknowledge.channel;
+	u8 tid = msg->u.tx_acknowledge.tid;
+
+	if (channel >= dev->nchannels) {
+		dev_err(dev->udev->dev.parent,
+			"Invalid channel number (%d)\n", channel);
+		return;
+	}
+
+	priv = dev->nets[channel];
+
+	if (!netif_device_present(priv->netdev))
+		return;
+
+	stats = &priv->netdev->stats;
+
+	context = &priv->tx_contexts[tid % MAX_TX_URBS];
+
+	/* Sometimes the state change doesn't come after a bus-off event */
+	if (priv->can.restart_ms &&
+	    (priv->can.state >= CAN_STATE_BUS_OFF)) {
+		skb = alloc_can_err_skb(priv->netdev, &cf);
+		if (skb) {
+			cf->can_id |= CAN_ERR_RESTARTED;
+			netif_rx(skb);
+
+			stats->rx_packets++;
+			stats->rx_bytes += cf->can_dlc;
+		} else {
+			netdev_err(priv->netdev,
+				   "No memory left for err_skb\n");
+		}
+
+		priv->can.can_stats.restarts++;
+		netif_carrier_on(priv->netdev);
+
+		priv->can.state = CAN_STATE_ERROR_ACTIVE;
+	}
+
+	stats->tx_packets++;
+	stats->tx_bytes += context->dlc;
+	can_get_echo_skb(priv->netdev, context->echo_index);
+
+	context->echo_index = MAX_TX_URBS;
+	atomic_dec(&priv->active_tx_urbs);
+
+	netif_wake_queue(priv->netdev);
+}
+
+static void kvaser_usb_simple_msg_callback(struct urb *urb)
+{
+	struct net_device *netdev = urb->context;
+
+	kfree(urb->transfer_buffer);
+
+	if (urb->status)
+		netdev_warn(netdev, "urb status received: %d\n",
+			    urb->status);
+}
+
+static int kvaser_usb_simple_msg_async(struct kvaser_usb_net_priv *priv,
+				       u8 msg_id)
+{
+	struct kvaser_usb *dev = priv->dev;
+	struct net_device *netdev = priv->netdev;
+	struct kvaser_msg *msg;
+	struct urb *urb;
+	void *buf;
+	int err;
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		netdev_err(netdev, "No memory left for URBs\n");
+		return -ENOMEM;
+	}
+
+	buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC);
+	if (!buf) {
+		netdev_err(netdev, "No memory left for USB buffer\n");
+		usb_free_urb(urb);
+		return -ENOMEM;
+	}
+
+	msg = (struct kvaser_msg *)buf;
+	msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_simple);
+	msg->id = msg_id;
+	msg->u.simple.channel = priv->channel;
+
+	usb_fill_bulk_urb(urb, dev->udev,
+			  usb_sndbulkpipe(dev->udev,
+					  dev->bulk_out->bEndpointAddress),
+			  buf, msg->len,
+			  kvaser_usb_simple_msg_callback, priv);
+	usb_anchor_urb(urb, &priv->tx_submitted);
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err) {
+		netdev_err(netdev, "Error transmitting URB\n");
+		usb_unanchor_urb(urb);
+		usb_free_urb(urb);
+		kfree(buf);
+		return err;
+	}
+
+	usb_free_urb(urb);
+
+	return 0;
+}
+
+static void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv)
+{
+	int i;
+
+	usb_kill_anchored_urbs(&priv->tx_submitted);
+	atomic_set(&priv->active_tx_urbs, 0);
+
+	for (i = 0; i < MAX_TX_URBS; i++)
+		priv->tx_contexts[i].echo_index = MAX_TX_URBS;
+}
+
+static void kvaser_usb_rx_error(const struct kvaser_usb *dev,
+				const struct kvaser_msg *msg)
+{
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	struct net_device_stats *stats;
+	struct kvaser_usb_net_priv *priv;
+	unsigned int new_state;
+	u8 channel, status, txerr, rxerr, error_factor;
+
+	switch (msg->id) {
+	case CMD_CAN_ERROR_EVENT:
+		channel = msg->u.error_event.channel;
+		status =  msg->u.error_event.status;
+		txerr = msg->u.error_event.tx_errors_count;
+		rxerr = msg->u.error_event.rx_errors_count;
+		error_factor = msg->u.error_event.error_factor;
+		break;
+	case CMD_LOG_MESSAGE:
+		channel = msg->u.log_message.channel;
+		status = msg->u.log_message.data[0];
+		txerr = msg->u.log_message.data[2];
+		rxerr = msg->u.log_message.data[3];
+		error_factor = msg->u.log_message.data[1];
+		break;
+	case CMD_CHIP_STATE_EVENT:
+		channel = msg->u.chip_state_event.channel;
+		status =  msg->u.chip_state_event.status;
+		txerr = msg->u.chip_state_event.tx_errors_count;
+		rxerr = msg->u.chip_state_event.rx_errors_count;
+		error_factor = 0;
+		break;
+	default:
+		dev_err(dev->udev->dev.parent, "Invalid msg id (%d)\n",
+			msg->id);
+		return;
+	}
+
+	if (channel >= dev->nchannels) {
+		dev_err(dev->udev->dev.parent,
+			"Invalid channel number (%d)\n", channel);
+		return;
+	}
+
+	priv = dev->nets[channel];
+	stats = &priv->netdev->stats;
+
+	if (status & M16C_STATE_BUS_RESET) {
+		kvaser_usb_unlink_tx_urbs(priv);
+		return;
+	}
+
+	skb = alloc_can_err_skb(priv->netdev, &cf);
+	if (!skb) {
+		stats->rx_dropped++;
+		return;
+	}
+
+	new_state = priv->can.state;
+
+	netdev_dbg(priv->netdev, "Error status: 0x%02x\n", status);
+
+	if (status & M16C_STATE_BUS_OFF) {
+		cf->can_id |= CAN_ERR_BUSOFF;
+
+		priv->can.can_stats.bus_off++;
+		if (!priv->can.restart_ms)
+			kvaser_usb_simple_msg_async(priv, CMD_STOP_CHIP);
+
+		netif_carrier_off(priv->netdev);
+
+		new_state = CAN_STATE_BUS_OFF;
+	} else if (status & M16C_STATE_BUS_PASSIVE) {
+		if (priv->can.state != CAN_STATE_ERROR_PASSIVE) {
+			cf->can_id |= CAN_ERR_CRTL;
+
+			if (txerr || rxerr)
+				cf->data[1] = (txerr > rxerr)
+						? CAN_ERR_CRTL_TX_PASSIVE
+						: CAN_ERR_CRTL_RX_PASSIVE;
+			else
+				cf->data[1] = CAN_ERR_CRTL_TX_PASSIVE |
+					      CAN_ERR_CRTL_RX_PASSIVE;
+
+			priv->can.can_stats.error_passive++;
+		}
+
+		new_state = CAN_STATE_ERROR_PASSIVE;
+	}
+
+	if (status == M16C_STATE_BUS_ERROR) {
+		if ((priv->can.state < CAN_STATE_ERROR_WARNING) &&
+		    ((txerr >= 96) || (rxerr >= 96))) {
+			cf->can_id |= CAN_ERR_CRTL;
+			cf->data[1] = (txerr > rxerr)
+					? CAN_ERR_CRTL_TX_WARNING
+					: CAN_ERR_CRTL_RX_WARNING;
+
+			priv->can.can_stats.error_warning++;
+			new_state = CAN_STATE_ERROR_WARNING;
+		} else if (priv->can.state > CAN_STATE_ERROR_ACTIVE) {
+			cf->can_id |= CAN_ERR_PROT;
+			cf->data[2] = CAN_ERR_PROT_ACTIVE;
+
+			new_state = CAN_STATE_ERROR_ACTIVE;
+		}
+	}
+
+	if (!status) {
+		cf->can_id |= CAN_ERR_PROT;
+		cf->data[2] = CAN_ERR_PROT_ACTIVE;
+
+		new_state = CAN_STATE_ERROR_ACTIVE;
+	}
+
+	if (priv->can.restart_ms &&
+	    (priv->can.state >= CAN_STATE_BUS_OFF) &&
+	    (new_state < CAN_STATE_BUS_OFF)) {
+		cf->can_id |= CAN_ERR_RESTARTED;
+		netif_carrier_on(priv->netdev);
+
+		priv->can.can_stats.restarts++;
+	}
+
+	if (error_factor) {
+		priv->can.can_stats.bus_error++;
+		stats->rx_errors++;
+
+		cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
+
+		if (error_factor & M16C_EF_ACKE)
+			cf->data[3] |= (CAN_ERR_PROT_LOC_ACK);
+		if (error_factor & M16C_EF_CRCE)
+			cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ |
+					CAN_ERR_PROT_LOC_CRC_DEL);
+		if (error_factor & M16C_EF_FORME)
+			cf->data[2] |= CAN_ERR_PROT_FORM;
+		if (error_factor & M16C_EF_STFE)
+			cf->data[2] |= CAN_ERR_PROT_STUFF;
+		if (error_factor & M16C_EF_BITE0)
+			cf->data[2] |= CAN_ERR_PROT_BIT0;
+		if (error_factor & M16C_EF_BITE1)
+			cf->data[2] |= CAN_ERR_PROT_BIT1;
+		if (error_factor & M16C_EF_TRE)
+			cf->data[2] |= CAN_ERR_PROT_TX;
+	}
+
+	cf->data[6] = txerr;
+	cf->data[7] = rxerr;
+
+	priv->bec.txerr = txerr;
+	priv->bec.rxerr = rxerr;
+
+	priv->can.state = new_state;
+
+	netif_rx(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+}
+
+static void kvaser_usb_rx_can_err(const struct kvaser_usb_net_priv *priv,
+				  const struct kvaser_msg *msg)
+{
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	struct net_device_stats *stats = &priv->netdev->stats;
+
+	if (msg->u.rx_can.flag & (MSG_FLAG_ERROR_FRAME |
+					 MSG_FLAG_NERR)) {
+		netdev_err(priv->netdev, "Unknow error (flags: 0x%02x)\n",
+			   msg->u.rx_can.flag);
+
+		stats->rx_errors++;
+		return;
+	}
+
+	if (msg->u.rx_can.flag & MSG_FLAG_OVERRUN) {
+		skb = alloc_can_err_skb(priv->netdev, &cf);
+		if (!skb) {
+			stats->rx_dropped++;
+			return;
+		}
+
+		cf->can_id |= CAN_ERR_CRTL;
+		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+
+		stats->rx_over_errors++;
+		stats->rx_errors++;
+
+		netif_rx(skb);
+
+		stats->rx_packets++;
+		stats->rx_bytes += cf->can_dlc;
+	}
+}
+
+static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev,
+				  const struct kvaser_msg *msg)
+{
+	struct kvaser_usb_net_priv *priv;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	struct net_device_stats *stats;
+	u8 channel = msg->u.rx_can.channel;
+
+	if (channel >= dev->nchannels) {
+		dev_err(dev->udev->dev.parent,
+			"Invalid channel number (%d)\n", channel);
+		return;
+	}
+
+	priv = dev->nets[channel];
+	stats = &priv->netdev->stats;
+
+	if (msg->u.rx_can.flag & (MSG_FLAG_ERROR_FRAME | MSG_FLAG_NERR |
+				  MSG_FLAG_OVERRUN)) {
+		kvaser_usb_rx_can_err(priv, msg);
+		return;
+	} else if (msg->u.rx_can.flag & ~MSG_FLAG_REMOTE_FRAME) {
+		netdev_warn(priv->netdev,
+			    "Unhandled frame (flags: 0x%02x)",
+			    msg->u.rx_can.flag);
+		return;
+	}
+
+	skb = alloc_can_skb(priv->netdev, &cf);
+	if (!skb) {
+		stats->tx_dropped++;
+		return;
+	}
+
+	cf->can_id = ((msg->u.rx_can.msg[0] & 0x1f) << 6) |
+		     (msg->u.rx_can.msg[1] & 0x3f);
+	cf->can_dlc = get_can_dlc(msg->u.rx_can.msg[5]);
+
+	if (msg->id == CMD_RX_EXT_MESSAGE) {
+		cf->can_id <<= 18;
+		cf->can_id |= ((msg->u.rx_can.msg[2] & 0x0f) << 14) |
+			      ((msg->u.rx_can.msg[3] & 0xff) << 6) |
+			      (msg->u.rx_can.msg[4] & 0x3f);
+		cf->can_id |= CAN_EFF_FLAG;
+	}
+
+	if (msg->u.rx_can.flag & MSG_FLAG_REMOTE_FRAME)
+		cf->can_id |= CAN_RTR_FLAG;
+	else
+		memcpy(cf->data, &msg->u.rx_can.msg[6], cf->can_dlc);
+
+	netif_rx(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+}
+
+static void kvaser_usb_start_chip_reply(const struct kvaser_usb *dev,
+					const struct kvaser_msg *msg)
+{
+	struct kvaser_usb_net_priv *priv;
+	u8 channel = msg->u.simple.channel;
+
+	if (channel >= dev->nchannels) {
+		dev_err(dev->udev->dev.parent,
+			"Invalid channel number (%d)\n", channel);
+		return;
+	}
+
+	priv = dev->nets[channel];
+
+	if (completion_done(&priv->start_comp) &&
+	    netif_queue_stopped(priv->netdev)) {
+		netif_wake_queue(priv->netdev);
+	} else {
+		netif_start_queue(priv->netdev);
+		complete(&priv->start_comp);
+	}
+}
+
+static void kvaser_usb_stop_chip_reply(const struct kvaser_usb *dev,
+				       const struct kvaser_msg *msg)
+{
+	struct kvaser_usb_net_priv *priv;
+	u8 channel = msg->u.simple.channel;
+
+	if (channel >= dev->nchannels) {
+		dev_err(dev->udev->dev.parent,
+			"Invalid channel number (%d)\n", channel);
+		return;
+	}
+
+	priv = dev->nets[channel];
+
+	complete(&priv->stop_comp);
+}
+
+static void kvaser_usb_handle_message(const struct kvaser_usb *dev,
+				      const struct kvaser_msg *msg)
+{
+	switch (msg->id) {
+	case CMD_START_CHIP_REPLY:
+		kvaser_usb_start_chip_reply(dev, msg);
+		break;
+
+	case CMD_STOP_CHIP_REPLY:
+		kvaser_usb_stop_chip_reply(dev, msg);
+		break;
+
+	case CMD_RX_STD_MESSAGE:
+	case CMD_RX_EXT_MESSAGE:
+		kvaser_usb_rx_can_msg(dev, msg);
+		break;
+
+	case CMD_CHIP_STATE_EVENT:
+	case CMD_CAN_ERROR_EVENT:
+		kvaser_usb_rx_error(dev, msg);
+		break;
+
+	case CMD_LOG_MESSAGE:
+		if (msg->u.log_message.flags & MSG_FLAG_ERROR_FRAME)
+			kvaser_usb_rx_error(dev, msg);
+		break;
+
+	case CMD_TX_ACKNOWLEDGE:
+		kvaser_usb_tx_acknowledge(dev, msg);
+		break;
+
+	default:
+		dev_warn(dev->udev->dev.parent,
+			 "Unhandled message (%d)\n", msg->id);
+		break;
+	}
+}
+
+static void kvaser_usb_read_bulk_callback(struct urb *urb)
+{
+	struct kvaser_usb *dev = urb->context;
+	struct kvaser_msg *msg;
+	int pos = 0;
+	int err, i;
+
+	switch (urb->status) {
+	case 0:
+		break;
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+	default:
+		dev_info(dev->udev->dev.parent, "Rx URB aborted (%d)\n",
+			 urb->status);
+		goto resubmit_urb;
+	}
+
+	while (pos <= urb->actual_length - MSG_HEADER_LEN) {
+		msg = urb->transfer_buffer + pos;
+
+		if (!msg->len)
+			break;
+
+		if (pos + msg->len > urb->actual_length) {
+			dev_err(dev->udev->dev.parent, "Format error\n");
+			break;
+		}
+
+		kvaser_usb_handle_message(dev, msg);
+
+		pos += msg->len;
+	}
+
+resubmit_urb:
+	usb_fill_bulk_urb(urb, dev->udev,
+			  usb_rcvbulkpipe(dev->udev,
+					  dev->bulk_in->bEndpointAddress),
+			  urb->transfer_buffer, RX_BUFFER_SIZE,
+			  kvaser_usb_read_bulk_callback, dev);
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err == -ENODEV) {
+		for (i = 0; i < dev->nchannels; i++) {
+			if (!dev->nets[i])
+				continue;
+
+			netif_device_detach(dev->nets[i]->netdev);
+		}
+	} else if (err) {
+		dev_err(dev->udev->dev.parent,
+			"Failed resubmitting read bulk urb: %d\n", err);
+	}
+
+	return;
+}
+
+static int kvaser_usb_setup_rx_urbs(struct kvaser_usb *dev)
+{
+	int i, err = 0;
+
+	if (dev->rxinitdone)
+		return 0;
+
+	for (i = 0; i < MAX_RX_URBS; i++) {
+		struct urb *urb = NULL;
+		u8 *buf = NULL;
+		dma_addr_t buf_dma;
+
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb) {
+			dev_warn(dev->udev->dev.parent,
+				 "No memory left for URBs\n");
+			err = -ENOMEM;
+			break;
+		}
+
+		buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE,
+					 GFP_KERNEL, &buf_dma);
+		if (!buf) {
+			dev_warn(dev->udev->dev.parent,
+				 "No memory left for USB buffer\n");
+			usb_free_urb(urb);
+			err = -ENOMEM;
+			break;
+		}
+
+		usb_fill_bulk_urb(urb, dev->udev,
+				  usb_rcvbulkpipe(dev->udev,
+					  dev->bulk_in->bEndpointAddress),
+				  buf, RX_BUFFER_SIZE,
+				  kvaser_usb_read_bulk_callback,
+				  dev);
+		urb->transfer_dma = buf_dma;
+		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+		usb_anchor_urb(urb, &dev->rx_submitted);
+
+		err = usb_submit_urb(urb, GFP_KERNEL);
+		if (err) {
+			usb_unanchor_urb(urb);
+			usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
+					  buf_dma);
+			usb_free_urb(urb);
+			break;
+		}
+
+		dev->rxbuf[i] = buf;
+		dev->rxbuf_dma[i] = buf_dma;
+
+		usb_free_urb(urb);
+	}
+
+	if (i == 0) {
+		dev_warn(dev->udev->dev.parent,
+			 "Cannot setup read URBs, error %d\n", err);
+		return err;
+	} else if (i < MAX_RX_URBS) {
+		dev_warn(dev->udev->dev.parent,
+			 "RX performances may be slow\n");
+	}
+
+	dev->rxinitdone = true;
+
+	return 0;
+}
+
+static int kvaser_usb_set_opt_mode(const struct kvaser_usb_net_priv *priv)
+{
+	struct kvaser_msg *msg;
+	int rc;
+
+	msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	msg->id = CMD_SET_CTRL_MODE;
+	msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_ctrl_mode);
+	msg->u.ctrl_mode.tid = 0xff;
+	msg->u.ctrl_mode.channel = priv->channel;
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+		msg->u.ctrl_mode.ctrl_mode = KVASER_CTRL_MODE_SILENT;
+	else
+		msg->u.ctrl_mode.ctrl_mode = KVASER_CTRL_MODE_NORMAL;
+
+	rc = kvaser_usb_send_msg(priv->dev, msg);
+
+	kfree(msg);
+	return rc;
+}
+
+static int kvaser_usb_start_chip(struct kvaser_usb_net_priv *priv)
+{
+	int err;
+
+	init_completion(&priv->start_comp);
+
+	err = kvaser_usb_send_simple_msg(priv->dev, CMD_START_CHIP,
+					 priv->channel);
+	if (err)
+		return err;
+
+	if (!wait_for_completion_timeout(&priv->start_comp,
+					 msecs_to_jiffies(START_TIMEOUT)))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int kvaser_usb_open(struct net_device *netdev)
+{
+	struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+	struct kvaser_usb *dev = priv->dev;
+	int err;
+
+	err = open_candev(netdev);
+	if (err)
+		return err;
+
+	err = kvaser_usb_setup_rx_urbs(dev);
+	if (err)
+		goto error;
+
+	err = kvaser_usb_set_opt_mode(priv);
+	if (err)
+		goto error;
+
+	err = kvaser_usb_start_chip(priv);
+	if (err) {
+		netdev_warn(netdev, "Cannot start device, error %d\n", err);
+		goto error;
+	}
+
+	priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+	return 0;
+
+error:
+	close_candev(netdev);
+	return err;
+}
+
+static void kvaser_usb_unlink_all_urbs(struct kvaser_usb *dev)
+{
+	int i;
+
+	usb_kill_anchored_urbs(&dev->rx_submitted);
+
+	for (i = 0; i < MAX_RX_URBS; i++)
+		usb_free_coherent(dev->udev, RX_BUFFER_SIZE,
+				  dev->rxbuf[i],
+				  dev->rxbuf_dma[i]);
+
+	for (i = 0; i < MAX_NET_DEVICES; i++) {
+		struct kvaser_usb_net_priv *priv = dev->nets[i];
+
+		if (priv)
+			kvaser_usb_unlink_tx_urbs(priv);
+	}
+}
+
+static int kvaser_usb_stop_chip(struct kvaser_usb_net_priv *priv)
+{
+	int err;
+
+	init_completion(&priv->stop_comp);
+
+	err = kvaser_usb_send_simple_msg(priv->dev, CMD_STOP_CHIP,
+					 priv->channel);
+	if (err)
+		return err;
+
+	if (!wait_for_completion_timeout(&priv->stop_comp,
+					 msecs_to_jiffies(STOP_TIMEOUT)))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int kvaser_usb_flush_queue(struct kvaser_usb_net_priv *priv)
+{
+	struct kvaser_msg *msg;
+	int rc;
+
+	msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	msg->id = CMD_FLUSH_QUEUE;
+	msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_flush_queue);
+	msg->u.flush_queue.channel = priv->channel;
+	msg->u.flush_queue.flags = 0x00;
+
+	rc = kvaser_usb_send_msg(priv->dev, msg);
+
+	kfree(msg);
+	return rc;
+}
+
+static int kvaser_usb_close(struct net_device *netdev)
+{
+	struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+	struct kvaser_usb *dev = priv->dev;
+	int err;
+
+	netif_stop_queue(netdev);
+
+	err = kvaser_usb_flush_queue(priv);
+	if (err)
+		netdev_warn(netdev, "Cannot flush queue, error %d\n", err);
+
+	if (kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel))
+		netdev_warn(netdev, "Cannot reset card, error %d\n", err);
+
+	err = kvaser_usb_stop_chip(priv);
+	if (err)
+		netdev_warn(netdev, "Cannot stop device, error %d\n", err);
+
+	priv->can.state = CAN_STATE_STOPPED;
+	close_candev(priv->netdev);
+
+	return 0;
+}
+
+static void kvaser_usb_write_bulk_callback(struct urb *urb)
+{
+	struct kvaser_usb_tx_urb_context *context = urb->context;
+	struct kvaser_usb_net_priv *priv;
+	struct net_device *netdev;
+
+	if (WARN_ON(!context))
+		return;
+
+	priv = context->priv;
+	netdev = priv->netdev;
+
+	kfree(urb->transfer_buffer);
+
+	if (!netif_device_present(netdev))
+		return;
+
+	if (urb->status)
+		netdev_info(netdev, "Tx URB aborted (%d)\n", urb->status);
+}
+
+static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
+					 struct net_device *netdev)
+{
+	struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+	struct kvaser_usb *dev = priv->dev;
+	struct net_device_stats *stats = &netdev->stats;
+	struct can_frame *cf = (struct can_frame *)skb->data;
+	struct kvaser_usb_tx_urb_context *context = NULL;
+	struct urb *urb;
+	void *buf;
+	struct kvaser_msg *msg;
+	int i, err;
+	int ret = NETDEV_TX_OK;
+
+	if (can_dropped_invalid_skb(netdev, skb))
+		return NETDEV_TX_OK;
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		netdev_err(netdev, "No memory left for URBs\n");
+		stats->tx_dropped++;
+		goto nourbmem;
+	}
+
+	buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC);
+	if (!buf) {
+		netdev_err(netdev, "No memory left for USB buffer\n");
+		stats->tx_dropped++;
+		goto nobufmem;
+	}
+
+	msg = buf;
+	msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_tx_can);
+	msg->u.tx_can.flags = 0;
+	msg->u.tx_can.channel = priv->channel;
+
+	if (cf->can_id & CAN_EFF_FLAG) {
+		msg->id = CMD_TX_EXT_MESSAGE;
+		msg->u.tx_can.msg[0] = (cf->can_id >> 24) & 0x1f;
+		msg->u.tx_can.msg[1] = (cf->can_id >> 18) & 0x3f;
+		msg->u.tx_can.msg[2] = (cf->can_id >> 14) & 0x0f;
+		msg->u.tx_can.msg[3] = (cf->can_id >> 6) & 0xff;
+		msg->u.tx_can.msg[4] = cf->can_id & 0x3f;
+	} else {
+		msg->id = CMD_TX_STD_MESSAGE;
+		msg->u.tx_can.msg[0] = (cf->can_id >> 6) & 0x1f;
+		msg->u.tx_can.msg[1] = cf->can_id & 0x3f;
+	}
+
+	msg->u.tx_can.msg[5] = cf->can_dlc;
+	memcpy(&msg->u.tx_can.msg[6], cf->data, cf->can_dlc);
+
+	if (cf->can_id & CAN_RTR_FLAG)
+		msg->u.tx_can.flags |= MSG_FLAG_REMOTE_FRAME;
+
+	for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++) {
+		if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) {
+			context = &priv->tx_contexts[i];
+			break;
+		}
+	}
+
+	if (!context) {
+		netdev_warn(netdev, "cannot find free context\n");
+		ret =  NETDEV_TX_BUSY;
+		goto releasebuf;
+	}
+
+	context->priv = priv;
+	context->echo_index = i;
+	context->dlc = cf->can_dlc;
+
+	msg->u.tx_can.tid = context->echo_index;
+
+	usb_fill_bulk_urb(urb, dev->udev,
+			  usb_sndbulkpipe(dev->udev,
+					  dev->bulk_out->bEndpointAddress),
+			  buf, msg->len,
+			  kvaser_usb_write_bulk_callback, context);
+	usb_anchor_urb(urb, &priv->tx_submitted);
+
+	can_put_echo_skb(skb, netdev, context->echo_index);
+
+	atomic_inc(&priv->active_tx_urbs);
+
+	if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS)
+		netif_stop_queue(netdev);
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (unlikely(err)) {
+		can_free_echo_skb(netdev, context->echo_index);
+
+		skb = NULL; /* set to NULL to avoid double free in
+			     * dev_kfree_skb(skb) */
+
+		atomic_dec(&priv->active_tx_urbs);
+		usb_unanchor_urb(urb);
+
+		stats->tx_dropped++;
+
+		if (err == -ENODEV)
+			netif_device_detach(netdev);
+		else
+			netdev_warn(netdev, "Failed tx_urb %d\n", err);
+
+		goto releasebuf;
+	}
+
+	usb_free_urb(urb);
+
+	return NETDEV_TX_OK;
+
+releasebuf:
+	kfree(buf);
+nobufmem:
+	usb_free_urb(urb);
+nourbmem:
+	dev_kfree_skb(skb);
+	return ret;
+}
+
+static const struct net_device_ops kvaser_usb_netdev_ops = {
+	.ndo_open = kvaser_usb_open,
+	.ndo_stop = kvaser_usb_close,
+	.ndo_start_xmit = kvaser_usb_start_xmit,
+};
+
+static const struct can_bittiming_const kvaser_usb_bittiming_const = {
+	.name = "kvaser_usb",
+	.tseg1_min = KVASER_USB_TSEG1_MIN,
+	.tseg1_max = KVASER_USB_TSEG1_MAX,
+	.tseg2_min = KVASER_USB_TSEG2_MIN,
+	.tseg2_max = KVASER_USB_TSEG2_MAX,
+	.sjw_max = KVASER_USB_SJW_MAX,
+	.brp_min = KVASER_USB_BRP_MIN,
+	.brp_max = KVASER_USB_BRP_MAX,
+	.brp_inc = KVASER_USB_BRP_INC,
+};
+
+static int kvaser_usb_set_bittiming(struct net_device *netdev)
+{
+	struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+	struct can_bittiming *bt = &priv->can.bittiming;
+	struct kvaser_usb *dev = priv->dev;
+	struct kvaser_msg *msg;
+	int rc;
+
+	msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	msg->id = CMD_SET_BUS_PARAMS;
+	msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_busparams);
+	msg->u.busparams.channel = priv->channel;
+	msg->u.busparams.tid = 0xff;
+	msg->u.busparams.bitrate = cpu_to_le32(bt->bitrate);
+	msg->u.busparams.sjw = bt->sjw;
+	msg->u.busparams.tseg1 = bt->prop_seg + bt->phase_seg1;
+	msg->u.busparams.tseg2 = bt->phase_seg2;
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+		msg->u.busparams.no_samp = 3;
+	else
+		msg->u.busparams.no_samp = 1;
+
+	rc = kvaser_usb_send_msg(dev, msg);
+
+	kfree(msg);
+	return rc;
+}
+
+static int kvaser_usb_set_mode(struct net_device *netdev,
+			       enum can_mode mode)
+{
+	struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+	int err;
+
+	switch (mode) {
+	case CAN_MODE_START:
+		err = kvaser_usb_simple_msg_async(priv, CMD_START_CHIP);
+		if (err)
+			return err;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int kvaser_usb_get_berr_counter(const struct net_device *netdev,
+				       struct can_berr_counter *bec)
+{
+	struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+
+	*bec = priv->bec;
+
+	return 0;
+}
+
+static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev)
+{
+	int i;
+
+	for (i = 0; i < dev->nchannels; i++) {
+		if (!dev->nets[i])
+			continue;
+
+		unregister_netdev(dev->nets[i]->netdev);
+	}
+
+	kvaser_usb_unlink_all_urbs(dev);
+
+	for (i = 0; i < dev->nchannels; i++) {
+		if (!dev->nets[i])
+			continue;
+
+		free_candev(dev->nets[i]->netdev);
+	}
+}
+
+static int kvaser_usb_init_one(struct usb_interface *intf,
+			       const struct usb_device_id *id, int channel)
+{
+	struct kvaser_usb *dev = usb_get_intfdata(intf);
+	struct net_device *netdev;
+	struct kvaser_usb_net_priv *priv;
+	int i, err;
+
+	netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS);
+	if (!netdev) {
+		dev_err(&intf->dev, "Cannot alloc candev\n");
+		return -ENOMEM;
+	}
+
+	priv = netdev_priv(netdev);
+
+	init_completion(&priv->start_comp);
+	init_completion(&priv->stop_comp);
+
+	init_usb_anchor(&priv->tx_submitted);
+	atomic_set(&priv->active_tx_urbs, 0);
+
+	for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++)
+		priv->tx_contexts[i].echo_index = MAX_TX_URBS;
+
+	priv->dev = dev;
+	priv->netdev = netdev;
+	priv->channel = channel;
+
+	priv->can.state = CAN_STATE_STOPPED;
+	priv->can.clock.freq = CAN_USB_CLOCK;
+	priv->can.bittiming_const = &kvaser_usb_bittiming_const;
+	priv->can.do_set_bittiming = kvaser_usb_set_bittiming;
+	priv->can.do_set_mode = kvaser_usb_set_mode;
+	if (id->driver_info & KVASER_HAS_TXRX_ERRORS)
+		priv->can.do_get_berr_counter = kvaser_usb_get_berr_counter;
+	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
+	if (id->driver_info & KVASER_HAS_SILENT_MODE)
+		priv->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
+
+	netdev->flags |= IFF_ECHO;
+
+	netdev->netdev_ops = &kvaser_usb_netdev_ops;
+
+	SET_NETDEV_DEV(netdev, &intf->dev);
+
+	dev->nets[channel] = priv;
+
+	err = register_candev(netdev);
+	if (err) {
+		dev_err(&intf->dev, "Failed to register can device\n");
+		free_candev(netdev);
+		dev->nets[channel] = NULL;
+		return err;
+	}
+
+	netdev_dbg(netdev, "device registered\n");
+
+	return 0;
+}
+
+static void 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;
+	int i;
+
+	iface_desc = &intf->altsetting[0];
+
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+		endpoint = &iface_desc->endpoint[i].desc;
+
+		if (usb_endpoint_is_bulk_in(endpoint))
+			*in = endpoint;
+
+		if (usb_endpoint_is_bulk_out(endpoint))
+			*out = endpoint;
+	}
+}
+
+static int kvaser_usb_probe(struct usb_interface *intf,
+			    const struct usb_device_id *id)
+{
+	struct kvaser_usb *dev;
+	int err = -ENOMEM;
+	int i;
+
+	dev = devm_kzalloc(&intf->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	kvaser_usb_get_endpoints(intf, &dev->bulk_in, &dev->bulk_out);
+	if (!dev->bulk_in || !dev->bulk_out) {
+		dev_err(&intf->dev, "Cannot get usb endpoint(s)");
+		return err;
+	}
+
+	dev->udev = interface_to_usbdev(intf);
+
+	init_usb_anchor(&dev->rx_submitted);
+
+	usb_set_intfdata(intf, dev);
+
+	for (i = 0; i < MAX_NET_DEVICES; i++)
+		kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, i);
+
+	err = kvaser_usb_get_software_info(dev);
+	if (err) {
+		dev_err(&intf->dev,
+			"Cannot get software infos, error %d\n", err);
+		return err;
+	}
+
+	err = kvaser_usb_get_card_info(dev);
+	if (err) {
+		dev_err(&intf->dev,
+			"Cannot get card infos, error %d\n", err);
+		return err;
+	}
+
+	dev_dbg(&intf->dev, "Firmware version: %d.%d.%d\n",
+		((dev->fw_version >> 24) & 0xff),
+		((dev->fw_version >> 16) & 0xff),
+		(dev->fw_version & 0xffff));
+
+	for (i = 0; i < dev->nchannels; i++) {
+		err = kvaser_usb_init_one(intf, id, i);
+		if (err) {
+			kvaser_usb_remove_interfaces(dev);
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+static void kvaser_usb_disconnect(struct usb_interface *intf)
+{
+	struct kvaser_usb *dev = usb_get_intfdata(intf);
+
+	usb_set_intfdata(intf, NULL);
+
+	if (!dev)
+		return;
+
+	kvaser_usb_remove_interfaces(dev);
+}
+
+static struct usb_driver kvaser_usb_driver = {
+	.name = "kvaser_usb",
+	.probe = kvaser_usb_probe,
+	.disconnect = kvaser_usb_disconnect,
+	.id_table = kvaser_usb_table,
+};
+
+module_usb_driver(kvaser_usb_driver);
+
+MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>");
+MODULE_DESCRIPTION("CAN driver for Kvaser CAN/USB devices");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c
index 86f26a1..25723d8 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb.c
@@ -519,8 +519,10 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n,
 	mc->pdev->dev.can.state = new_state;
 
 	if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) {
+		struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb);
+
 		peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv);
-		skb->tstamp = timeval_to_ktime(tv);
+		hwts->hwtstamp = timeval_to_ktime(tv);
 	}
 
 	netif_rx(skb);
@@ -605,6 +607,7 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
 	struct sk_buff *skb;
 	struct can_frame *cf;
 	struct timeval tv;
+	struct skb_shared_hwtstamps *hwts;
 
 	skb = alloc_can_skb(mc->netdev, &cf);
 	if (!skb)
@@ -652,7 +655,8 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
 
 	/* convert timestamp into kernel time */
 	peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv);
-	skb->tstamp = timeval_to_ktime(tv);
+	hwts = skb_hwtstamps(skb);
+	hwts->hwtstamp = timeval_to_ktime(tv);
 
 	/* push the skb */
 	netif_rx(skb);
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
index e1626d9..30d79bf 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
@@ -532,6 +532,7 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if,
 	struct can_frame *can_frame;
 	struct sk_buff *skb;
 	struct timeval tv;
+	struct skb_shared_hwtstamps *hwts;
 
 	skb = alloc_can_skb(netdev, &can_frame);
 	if (!skb)
@@ -549,7 +550,8 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if,
 		memcpy(can_frame->data, rx->data, can_frame->can_dlc);
 
 	peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(rx->ts32), &tv);
-	skb->tstamp = timeval_to_ktime(tv);
+	hwts = skb_hwtstamps(skb);
+	hwts->hwtstamp = timeval_to_ktime(tv);
 
 	netif_rx(skb);
 	netdev->stats.rx_packets++;
@@ -570,6 +572,7 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if,
 	u8 err_mask = 0;
 	struct sk_buff *skb;
 	struct timeval tv;
+	struct skb_shared_hwtstamps *hwts;
 
 	/* nothing should be sent while in BUS_OFF state */
 	if (dev->can.state == CAN_STATE_BUS_OFF)
@@ -664,7 +667,8 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if,
 	dev->can.state = new_state;
 
 	peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(er->ts32), &tv);
-	skb->tstamp = timeval_to_ktime(tv);
+	hwts = skb_hwtstamps(skb);
+	hwts->hwtstamp = timeval_to_ktime(tv);
 	netif_rx(skb);
 	netdev->stats.rx_packets++;
 	netdev->stats.rx_bytes += can_frame->can_dlc;
diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index dd151d5..b8fe808 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -1,5 +1,5 @@
 menu "Distributed Switch Architecture drivers"
-	depends on NET_DSA
+	depends on HAVE_NET_DSA
 
 config NET_DSA_MV88E6XXX
 	tristate
@@ -7,6 +7,7 @@ config NET_DSA_MV88E6XXX
 
 config NET_DSA_MV88E6060
 	tristate "Marvell 88E6060 ethernet switch chip support"
+	select NET_DSA
 	select NET_DSA_TAG_TRAILER
 	---help---
 	  This enables support for the Marvell 88E6060 ethernet switch
@@ -18,6 +19,7 @@ config NET_DSA_MV88E6XXX_NEED_PPU
 
 config NET_DSA_MV88E6131
 	tristate "Marvell 88E6085/6095/6095F/6131 ethernet switch chip support"
+	select NET_DSA
 	select NET_DSA_MV88E6XXX
 	select NET_DSA_MV88E6XXX_NEED_PPU
 	select NET_DSA_TAG_DSA
@@ -27,6 +29,7 @@ config NET_DSA_MV88E6131
 
 config NET_DSA_MV88E6123_61_65
 	tristate "Marvell 88E6123/6161/6165 ethernet switch chip support"
+	select NET_DSA
 	select NET_DSA_MV88E6XXX
 	select NET_DSA_TAG_EDSA
 	---help---
diff --git a/drivers/net/ethernet/8390/Kconfig b/drivers/net/ethernet/8390/Kconfig
index e1219e0..8e15bd4 100644
--- a/drivers/net/ethernet/8390/Kconfig
+++ b/drivers/net/ethernet/8390/Kconfig
@@ -5,10 +5,7 @@
 config NET_VENDOR_8390
 	bool "National Semi-conductor 8390 devices"
 	default y
-	depends on NET_VENDOR_NATSEMI && (AMIGA_PCMCIA || PCI || SUPERH || \
-		   ISA || MCA || EISA || MAC || M32R || MACH_TX49XX || \
-		   MCA_LEGACY || H8300 || ARM || MIPS || ZORRO || PCMCIA || \
-		   EXPERIMENTAL)
+	depends on NET_VENDOR_NATSEMI
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y
 	  and read the Ethernet-HOWTO, available from
@@ -34,8 +31,8 @@ config EL2
 	  will be called 3c503.
 
 config AC3200
-	tristate "Ansel Communications EISA 3200 support (EXPERIMENTAL)"
-	depends on PCI && (ISA || EISA) && EXPERIMENTAL
+	tristate "Ansel Communications EISA 3200 support"
+	depends on PCI && (ISA || EISA)
 	select CRC32
 	---help---
 	  If you have a network (Ethernet) card of this type, say Y and read
@@ -87,8 +84,8 @@ config E2100
 	  will be called e2100.
 
 config ES3210
-	tristate "Racal-Interlan EISA ES3210 support (EXPERIMENTAL)"
-	depends on PCI && EISA && EXPERIMENTAL
+	tristate "Racal-Interlan EISA ES3210 support"
+	depends on PCI && EISA
 	select CRC32
 	---help---
 	  If you have a network (Ethernet) card of this type, say Y and read
@@ -141,8 +138,8 @@ config ARM_ETHERH
 	  should say Y to this option if you wish to use it with Linux.
 
 config LNE390
-	tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)"
-	depends on PCI && EISA && EXPERIMENTAL
+	tristate "Mylex EISA LNE390A/B support"
+	depends on PCI && EISA
 	select CRC32
 	---help---
 	  If you have a network (Ethernet) card of this type, say Y and read
@@ -227,8 +224,8 @@ config APNE
 	  will be called apne.
 
 config NE3210
-	tristate "Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)"
-	depends on PCI && EISA && EXPERIMENTAL
+	tristate "Novell/Eagle/Microdyne NE3210 EISA support"
+	depends on PCI && EISA
 	select CRC32
 	---help---
 	  If you have a network (Ethernet) card of this type, say Y and read
diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c
index 203ff9d..846381c 100644
--- a/drivers/net/ethernet/8390/ax88796.c
+++ b/drivers/net/ethernet/8390/ax88796.c
@@ -109,7 +109,7 @@ static inline struct ax_device *to_ax_dev(struct net_device *dev)
 /*
  * ax_initial_check
  *
- * do an initial probe for the card to check wether it exists
+ * do an initial probe for the card to check whether it exists
  * and is functional
  */
 static int ax_initial_check(struct net_device *dev)
diff --git a/drivers/net/ethernet/8390/etherh.c b/drivers/net/ethernet/8390/etherh.c
index 8322c54..6414e84 100644
--- a/drivers/net/ethernet/8390/etherh.c
+++ b/drivers/net/ethernet/8390/etherh.c
@@ -463,12 +463,6 @@ etherh_open(struct net_device *dev)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
 
-	if (!is_valid_ether_addr(dev->dev_addr)) {
-		printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
-			dev->name);
-		return -EINVAL;
-	}
-
 	if (request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev))
 		return -EAGAIN;
 
diff --git a/drivers/net/ethernet/adi/Kconfig b/drivers/net/ethernet/adi/Kconfig
index 49a30d3..e49c0ef 100644
--- a/drivers/net/ethernet/adi/Kconfig
+++ b/drivers/net/ethernet/adi/Kconfig
@@ -61,7 +61,7 @@ config BFIN_RX_DESC_NUM
 
 config BFIN_MAC_USE_HWSTAMP
 	bool "Use IEEE 1588 hwstamp"
-	depends on BFIN_MAC && BF518
+	select PTP_1588_CLOCK
 	default y
 	---help---
 	  To support the IEEE 1588 Precision Time Protocol (PTP), select y here
diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c
index f816426..f1c458d 100644
--- a/drivers/net/ethernet/adi/bfin_mac.c
+++ b/drivers/net/ethernet/adi/bfin_mac.c
@@ -548,14 +548,17 @@ static int bfin_mac_ethtool_setwol(struct net_device *dev,
 	return 0;
 }
 
+#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP
 static int bfin_mac_ethtool_get_ts_info(struct net_device *dev,
 	struct ethtool_ts_info *info)
 {
+	struct bfin_mac_local *lp = netdev_priv(dev);
+
 	info->so_timestamping =
 		SOF_TIMESTAMPING_TX_HARDWARE |
 		SOF_TIMESTAMPING_RX_HARDWARE |
-		SOF_TIMESTAMPING_SYS_HARDWARE;
-	info->phc_index = -1;
+		SOF_TIMESTAMPING_RAW_HARDWARE;
+	info->phc_index = lp->phc_index;
 	info->tx_types =
 		(1 << HWTSTAMP_TX_OFF) |
 		(1 << HWTSTAMP_TX_ON);
@@ -566,6 +569,7 @@ static int bfin_mac_ethtool_get_ts_info(struct net_device *dev,
 		(1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT);
 	return 0;
 }
+#endif
 
 static const struct ethtool_ops bfin_mac_ethtool_ops = {
 	.get_settings = bfin_mac_ethtool_getsettings,
@@ -574,7 +578,9 @@ static const struct ethtool_ops bfin_mac_ethtool_ops = {
 	.get_drvinfo = bfin_mac_ethtool_getdrvinfo,
 	.get_wol = bfin_mac_ethtool_getwol,
 	.set_wol = bfin_mac_ethtool_setwol,
+#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP
 	.get_ts_info = bfin_mac_ethtool_get_ts_info,
+#endif
 };
 
 /**************************************************************************/
@@ -649,6 +655,20 @@ static int bfin_mac_set_mac_address(struct net_device *dev, void *p)
 #ifdef CONFIG_BFIN_MAC_USE_HWSTAMP
 #define bfin_mac_hwtstamp_is_none(cfg) ((cfg) == HWTSTAMP_FILTER_NONE)
 
+static u32 bfin_select_phc_clock(u32 input_clk, unsigned int *shift_result)
+{
+	u32 ipn = 1000000000UL / input_clk;
+	u32 ppn = 1;
+	unsigned int shift = 0;
+
+	while (ppn <= ipn) {
+		ppn <<= 1;
+		shift++;
+	}
+	*shift_result = shift;
+	return 1000000000UL / ppn;
+}
+
 static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
 		struct ifreq *ifr, int cmd)
 {
@@ -798,19 +818,7 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
 		bfin_read_EMAC_PTP_TXSNAPLO();
 		bfin_read_EMAC_PTP_TXSNAPHI();
 
-		/*
-		 * Set registers so that rollover occurs soon to test this.
-		 */
-		bfin_write_EMAC_PTP_TIMELO(0x00000000);
-		bfin_write_EMAC_PTP_TIMEHI(0xFF800000);
-
 		SSYNC();
-
-		lp->compare.last_update = 0;
-		timecounter_init(&lp->clock,
-				&lp->cycles,
-				ktime_to_ns(ktime_get_real()));
-		timecompare_update(&lp->compare, 0);
 	}
 
 	lp->stamp_cfg = config;
@@ -818,15 +826,6 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
 		-EFAULT : 0;
 }
 
-static void bfin_dump_hwtamp(char *s, ktime_t *hw, ktime_t *ts, struct timecompare *cmp)
-{
-	ktime_t sys = ktime_get_real();
-
-	pr_debug("%s %s hardware:%d,%d transform system:%d,%d system:%d,%d, cmp:%lld, %lld\n",
-			__func__, s, hw->tv.sec, hw->tv.nsec, ts->tv.sec, ts->tv.nsec, sys.tv.sec,
-			sys.tv.nsec, cmp->offset, cmp->skew);
-}
-
 static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
 {
 	struct bfin_mac_local *lp = netdev_priv(netdev);
@@ -857,15 +856,9 @@ static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
 			regval = bfin_read_EMAC_PTP_TXSNAPLO();
 			regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32;
 			memset(&shhwtstamps, 0, sizeof(shhwtstamps));
-			ns = timecounter_cyc2time(&lp->clock,
-					regval);
-			timecompare_update(&lp->compare, ns);
+			ns = regval << lp->shift;
 			shhwtstamps.hwtstamp = ns_to_ktime(ns);
-			shhwtstamps.syststamp =
-				timecompare_transform(&lp->compare, ns);
 			skb_tstamp_tx(skb, &shhwtstamps);
-
-			bfin_dump_hwtamp("TX", &shhwtstamps.hwtstamp, &shhwtstamps.syststamp, &lp->compare);
 		}
 	}
 }
@@ -888,55 +881,184 @@ static void bfin_rx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
 
 	regval = bfin_read_EMAC_PTP_RXSNAPLO();
 	regval |= (u64)bfin_read_EMAC_PTP_RXSNAPHI() << 32;
-	ns = timecounter_cyc2time(&lp->clock, regval);
-	timecompare_update(&lp->compare, ns);
+	ns = regval << lp->shift;
 	memset(shhwtstamps, 0, sizeof(*shhwtstamps));
 	shhwtstamps->hwtstamp = ns_to_ktime(ns);
-	shhwtstamps->syststamp = timecompare_transform(&lp->compare, ns);
+}
+
+static void bfin_mac_hwtstamp_init(struct net_device *netdev)
+{
+	struct bfin_mac_local *lp = netdev_priv(netdev);
+	u64 addend, ppb;
+	u32 input_clk, phc_clk;
+
+	/* Initialize hardware timer */
+	input_clk = get_sclk();
+	phc_clk = bfin_select_phc_clock(input_clk, &lp->shift);
+	addend = phc_clk * (1ULL << 32);
+	do_div(addend, input_clk);
+	bfin_write_EMAC_PTP_ADDEND((u32)addend);
+
+	lp->addend = addend;
+	ppb = 1000000000ULL * input_clk;
+	do_div(ppb, phc_clk);
+	lp->max_ppb = ppb - 1000000000ULL - 1ULL;
 
-	bfin_dump_hwtamp("RX", &shhwtstamps->hwtstamp, &shhwtstamps->syststamp, &lp->compare);
+	/* Initialize hwstamp config */
+	lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE;
+	lp->stamp_cfg.tx_type = HWTSTAMP_TX_OFF;
 }
 
-/*
- * bfin_read_clock - read raw cycle counter (to be used by time counter)
- */
-static cycle_t bfin_read_clock(const struct cyclecounter *tc)
+static u64 bfin_ptp_time_read(struct bfin_mac_local *lp)
 {
-	u64 stamp;
+	u64 ns;
+	u32 lo, hi;
+
+	lo = bfin_read_EMAC_PTP_TIMELO();
+	hi = bfin_read_EMAC_PTP_TIMEHI();
 
-	stamp =  bfin_read_EMAC_PTP_TIMELO();
-	stamp |= (u64)bfin_read_EMAC_PTP_TIMEHI() << 32ULL;
+	ns = ((u64) hi) << 32;
+	ns |= lo;
+	ns <<= lp->shift;
 
-	return stamp;
+	return ns;
 }
 
-#define PTP_CLK 25000000
+static void bfin_ptp_time_write(struct bfin_mac_local *lp, u64 ns)
+{
+	u32 hi, lo;
 
-static void bfin_mac_hwtstamp_init(struct net_device *netdev)
+	ns >>= lp->shift;
+	hi = ns >> 32;
+	lo = ns & 0xffffffff;
+
+	bfin_write_EMAC_PTP_TIMELO(lo);
+	bfin_write_EMAC_PTP_TIMEHI(hi);
+}
+
+/* PTP Hardware Clock operations */
+
+static int bfin_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+	u64 adj;
+	u32 diff, addend;
+	int neg_adj = 0;
+	struct bfin_mac_local *lp =
+		container_of(ptp, struct bfin_mac_local, caps);
+
+	if (ppb < 0) {
+		neg_adj = 1;
+		ppb = -ppb;
+	}
+	addend = lp->addend;
+	adj = addend;
+	adj *= ppb;
+	diff = div_u64(adj, 1000000000ULL);
+
+	addend = neg_adj ? addend - diff : addend + diff;
+
+	bfin_write_EMAC_PTP_ADDEND(addend);
+
+	return 0;
+}
+
+static int bfin_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	s64 now;
+	unsigned long flags;
+	struct bfin_mac_local *lp =
+		container_of(ptp, struct bfin_mac_local, caps);
+
+	spin_lock_irqsave(&lp->phc_lock, flags);
+
+	now = bfin_ptp_time_read(lp);
+	now += delta;
+	bfin_ptp_time_write(lp, now);
+
+	spin_unlock_irqrestore(&lp->phc_lock, flags);
+
+	return 0;
+}
+
+static int bfin_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+	u64 ns;
+	u32 remainder;
+	unsigned long flags;
+	struct bfin_mac_local *lp =
+		container_of(ptp, struct bfin_mac_local, caps);
+
+	spin_lock_irqsave(&lp->phc_lock, flags);
+
+	ns = bfin_ptp_time_read(lp);
+
+	spin_unlock_irqrestore(&lp->phc_lock, flags);
+
+	ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
+	ts->tv_nsec = remainder;
+	return 0;
+}
+
+static int bfin_ptp_settime(struct ptp_clock_info *ptp,
+			   const struct timespec *ts)
+{
+	u64 ns;
+	unsigned long flags;
+	struct bfin_mac_local *lp =
+		container_of(ptp, struct bfin_mac_local, caps);
+
+	ns = ts->tv_sec * 1000000000ULL;
+	ns += ts->tv_nsec;
+
+	spin_lock_irqsave(&lp->phc_lock, flags);
+
+	bfin_ptp_time_write(lp, ns);
+
+	spin_unlock_irqrestore(&lp->phc_lock, flags);
+
+	return 0;
+}
+
+static int bfin_ptp_enable(struct ptp_clock_info *ptp,
+			  struct ptp_clock_request *rq, int on)
+{
+	return -EOPNOTSUPP;
+}
+
+static struct ptp_clock_info bfin_ptp_caps = {
+	.owner		= THIS_MODULE,
+	.name		= "BF518 clock",
+	.max_adj	= 0,
+	.n_alarm	= 0,
+	.n_ext_ts	= 0,
+	.n_per_out	= 0,
+	.pps		= 0,
+	.adjfreq	= bfin_ptp_adjfreq,
+	.adjtime	= bfin_ptp_adjtime,
+	.gettime	= bfin_ptp_gettime,
+	.settime	= bfin_ptp_settime,
+	.enable		= bfin_ptp_enable,
+};
+
+static int bfin_phc_init(struct net_device *netdev, struct device *dev)
 {
 	struct bfin_mac_local *lp = netdev_priv(netdev);
-	u64 append;
 
-	/* Initialize hardware timer */
-	append = PTP_CLK * (1ULL << 32);
-	do_div(append, get_sclk());
-	bfin_write_EMAC_PTP_ADDEND((u32)append);
-
-	memset(&lp->cycles, 0, sizeof(lp->cycles));
-	lp->cycles.read = bfin_read_clock;
-	lp->cycles.mask = CLOCKSOURCE_MASK(64);
-	lp->cycles.mult = 1000000000 / PTP_CLK;
-	lp->cycles.shift = 0;
-
-	/* Synchronize our NIC clock against system wall clock */
-	memset(&lp->compare, 0, sizeof(lp->compare));
-	lp->compare.source = &lp->clock;
-	lp->compare.target = ktime_get_real;
-	lp->compare.num_samples = 10;
+	lp->caps = bfin_ptp_caps;
+	lp->caps.max_adj = lp->max_ppb;
+	lp->clock = ptp_clock_register(&lp->caps, dev);
+	if (IS_ERR(lp->clock))
+		return PTR_ERR(lp->clock);
 
-	/* Initialize hwstamp config */
-	lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE;
-	lp->stamp_cfg.tx_type = HWTSTAMP_TX_OFF;
+	lp->phc_index = ptp_clock_index(lp->clock);
+	spin_lock_init(&lp->phc_lock);
+
+	return 0;
+}
+
+static void bfin_phc_release(struct bfin_mac_local *lp)
+{
+	ptp_clock_unregister(lp->clock);
 }
 
 #else
@@ -945,6 +1067,8 @@ static void bfin_mac_hwtstamp_init(struct net_device *netdev)
 # define bfin_mac_hwtstamp_ioctl(dev, ifr, cmd) (-EOPNOTSUPP)
 # define bfin_rx_hwtstamp(dev, skb)
 # define bfin_tx_hwtstamp(dev, skb)
+# define bfin_phc_init(netdev, dev) 0
+# define bfin_phc_release(lp)
 #endif
 
 static inline void _tx_reclaim_skb(void)
@@ -1579,12 +1703,17 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
 	}
 
 	bfin_mac_hwtstamp_init(ndev);
+	if (bfin_phc_init(ndev, &pdev->dev)) {
+		dev_err(&pdev->dev, "Cannot register PHC device!\n");
+		goto out_err_phc;
+	}
 
 	/* now, print out the card info, in a short format.. */
 	netdev_info(ndev, "%s, Version %s\n", DRV_DESC, DRV_VERSION);
 
 	return 0;
 
+out_err_phc:
 out_err_reg_ndev:
 	free_irq(IRQ_MAC_RX, ndev);
 out_err_request_irq:
@@ -1603,6 +1732,8 @@ static int __devexit bfin_mac_remove(struct platform_device *pdev)
 	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct bfin_mac_local *lp = netdev_priv(ndev);
 
+	bfin_phc_release(lp);
+
 	platform_set_drvdata(pdev, NULL);
 
 	lp->mii_bus->priv = NULL;
diff --git a/drivers/net/ethernet/adi/bfin_mac.h b/drivers/net/ethernet/adi/bfin_mac.h
index 960905c..7a07ee0 100644
--- a/drivers/net/ethernet/adi/bfin_mac.h
+++ b/drivers/net/ethernet/adi/bfin_mac.h
@@ -11,8 +11,7 @@
 #define _BFIN_MAC_H_
 
 #include <linux/net_tstamp.h>
-#include <linux/clocksource.h>
-#include <linux/timecompare.h>
+#include <linux/ptp_clock_kernel.h>
 #include <linux/timer.h>
 #include <linux/etherdevice.h>
 #include <linux/bfin_mac.h>
@@ -94,10 +93,14 @@ struct bfin_mac_local {
 	struct mii_bus *mii_bus;
 
 #if defined(CONFIG_BFIN_MAC_USE_HWSTAMP)
-	struct cyclecounter cycles;
-	struct timecounter clock;
-	struct timecompare compare;
+	u32 addend;
+	unsigned int shift;
+	s32 max_ppb;
 	struct hwtstamp_config stamp_cfg;
+	struct ptp_clock_info caps;
+	struct ptp_clock *clock;
+	int phc_index;
+	spinlock_t phc_lock; /* protects time lo/hi registers */
 #endif
 };
 
diff --git a/drivers/net/ethernet/atheros/Kconfig b/drivers/net/ethernet/atheros/Kconfig
index 1ed886d..36d6abd 100644
--- a/drivers/net/ethernet/atheros/Kconfig
+++ b/drivers/net/ethernet/atheros/Kconfig
@@ -44,8 +44,8 @@ config ATL1
 	  will be called atl1.
 
 config ATL1E
-	tristate "Atheros L1E Gigabit Ethernet support (EXPERIMENTAL)"
-	depends on PCI && EXPERIMENTAL
+	tristate "Atheros L1E Gigabit Ethernet support"
+	depends on PCI
 	select CRC32
 	select NET_CORE
 	select MII
@@ -56,8 +56,8 @@ config ATL1E
 	  will be called atl1e.
 
 config ATL1C
-	tristate "Atheros L1C Gigabit Ethernet support (EXPERIMENTAL)"
-	depends on PCI && EXPERIMENTAL
+	tristate "Atheros L1C Gigabit Ethernet support"
+	depends on PCI
 	select CRC32
 	select NET_CORE
 	select MII
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 72897c4..641d884 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -34,25 +34,16 @@
 
 #include "bnx2x_hsi.h"
 
-#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
-#define BCM_CNIC 1
 #include "../cnic_if.h"
-#endif
 
-#ifdef BCM_CNIC
-#define BNX2X_MIN_MSIX_VEC_CNT 3
-#define BNX2X_MSIX_VEC_FP_START 2
-#else
-#define BNX2X_MIN_MSIX_VEC_CNT 2
-#define BNX2X_MSIX_VEC_FP_START 1
-#endif
+
+#define BNX2X_MIN_MSIX_VEC_CNT(bp)		((bp)->min_msix_vec_cnt)
 
 #include <linux/mdio.h>
 
 #include "bnx2x_reg.h"
 #include "bnx2x_fw_defs.h"
 #include "bnx2x_mfw_req.h"
-#include "bnx2x_hsi.h"
 #include "bnx2x_link.h"
 #include "bnx2x_sp.h"
 #include "bnx2x_dcb.h"
@@ -256,15 +247,10 @@ enum {
 	/* FCoE L2 */
 #define	BNX2X_FCOE_ETH_CID(bp)		(BNX2X_CNIC_START_ETH_CID(bp) + 1)
 
-/** Additional rings budgeting */
-#ifdef BCM_CNIC
-#define CNIC_PRESENT			1
-#define FCOE_PRESENT			1
-#else
-#define CNIC_PRESENT			0
-#define FCOE_PRESENT			0
-#endif /* BCM_CNIC */
-#define NON_ETH_CONTEXT_USE	(FCOE_PRESENT)
+#define CNIC_SUPPORT(bp)		((bp)->cnic_support)
+#define CNIC_ENABLED(bp)		((bp)->cnic_enabled)
+#define CNIC_LOADED(bp)			((bp)->cnic_loaded)
+#define FCOE_INIT(bp)			((bp)->fcoe_init)
 
 #define AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR \
 	AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR
@@ -297,9 +283,7 @@ enum {
 	OOO_TXQ_IDX_OFFSET,
 };
 #define MAX_ETH_TXQ_IDX(bp)	(BNX2X_NUM_NON_CNIC_QUEUES(bp) * (bp)->max_cos)
-#ifdef BCM_CNIC
 #define FCOE_TXQ_IDX(bp)	(MAX_ETH_TXQ_IDX(bp) + FCOE_TXQ_IDX_OFFSET)
-#endif
 
 /* fast path */
 /*
@@ -585,15 +569,9 @@ struct bnx2x_fastpath {
 						->var)
 
 
-#define IS_ETH_FP(fp)			(fp->index < \
-					 BNX2X_NUM_ETH_QUEUES(fp->bp))
-#ifdef BCM_CNIC
-#define IS_FCOE_FP(fp)			(fp->index == FCOE_IDX(fp->bp))
-#define IS_FCOE_IDX(idx)		((idx) == FCOE_IDX(bp))
-#else
-#define IS_FCOE_FP(fp)		false
-#define IS_FCOE_IDX(idx)	false
-#endif
+#define IS_ETH_FP(fp)		((fp)->index < BNX2X_NUM_ETH_QUEUES((fp)->bp))
+#define IS_FCOE_FP(fp)		((fp)->index == FCOE_IDX((fp)->bp))
+#define IS_FCOE_IDX(idx)	((idx) == FCOE_IDX(bp))
 
 
 /* MC hsi */
@@ -886,6 +864,18 @@ struct bnx2x_common {
 					 (CHIP_REV(bp) == CHIP_REV_Bx))
 #define CHIP_IS_E3A0(bp)		(CHIP_IS_E3(bp) && \
 					 (CHIP_REV(bp) == CHIP_REV_Ax))
+/* This define is used in two main places:
+ * 1. In the early stages of nic_load, to know if to configrue Parser / Searcher
+ * to nic-only mode or to offload mode. Offload mode is configured if either the
+ * chip is E1x (where MIC_MODE register is not applicable), or if cnic already
+ * registered for this port (which means that the user wants storage services).
+ * 2. During cnic-related load, to know if offload mode is already configured in
+ * the HW or needs to be configrued.
+ * Since the transition from nic-mode to offload-mode in HW causes traffic
+ * coruption, nic-mode is configured only in ports on which storage services
+ * where never requested.
+ */
+#define CONFIGURE_NIC_MODE(bp)		(!CHIP_IS_E1x(bp) && !CNIC_ENABLED(bp))
 
 	int			flash_size;
 #define BNX2X_NVRAM_1MB_SIZE			0x20000	/* 1M bit in bytes */
@@ -946,7 +936,6 @@ struct bnx2x_port {
 
 	/* used to synchronize phy accesses */
 	struct mutex		phy_mutex;
-	int			need_hw_lock;
 
 	u32			port_stx;
 
@@ -1003,18 +992,15 @@ union cdu_context {
 #define CDU_ILT_PAGE_SZ		(8192 << CDU_ILT_PAGE_SZ_HW) /* 32K */
 #define ILT_PAGE_CIDS		(CDU_ILT_PAGE_SZ / sizeof(union cdu_context))
 
-#ifdef BCM_CNIC
 #define CNIC_ISCSI_CID_MAX	256
 #define CNIC_FCOE_CID_MAX	2048
 #define CNIC_CID_MAX		(CNIC_ISCSI_CID_MAX + CNIC_FCOE_CID_MAX)
 #define CNIC_ILT_LINES		DIV_ROUND_UP(CNIC_CID_MAX, ILT_PAGE_CIDS)
-#endif
 
 #define QM_ILT_PAGE_SZ_HW	0
 #define QM_ILT_PAGE_SZ		(4096 << QM_ILT_PAGE_SZ_HW) /* 4K */
 #define QM_CID_ROUND		1024
 
-#ifdef BCM_CNIC
 /* TM (timers) host DB constants */
 #define TM_ILT_PAGE_SZ_HW	0
 #define TM_ILT_PAGE_SZ		(4096 << TM_ILT_PAGE_SZ_HW) /* 4K */
@@ -1032,8 +1018,6 @@ union cdu_context {
 #define SRC_T2_SZ		SRC_ILT_SZ
 #define SRC_ILT_LINES		DIV_ROUND_UP(SRC_ILT_SZ, SRC_ILT_PAGE_SZ)
 
-#endif
-
 #define MAX_DMAE_C		8
 
 /* DMA memory not used in fastpath */
@@ -1227,7 +1211,6 @@ struct bnx2x {
 	struct bnx2x_sp_objs	*sp_objs;
 	struct bnx2x_fp_stats	*fp_stats;
 	struct bnx2x_fp_txdata	*bnx2x_txq;
-	int			bnx2x_txq_size;
 	void __iomem		*regview;
 	void __iomem		*doorbells;
 	u16			db_size;
@@ -1350,6 +1333,15 @@ struct bnx2x {
 #define NO_ISCSI_OOO(bp)	((bp)->flags & NO_ISCSI_OOO_FLAG)
 #define NO_FCOE(bp)		((bp)->flags & NO_FCOE_FLAG)
 
+	u8			cnic_support;
+	bool			cnic_enabled;
+	bool			cnic_loaded;
+
+	/* Flag that indicates that we can start looking for FCoE L2 queue
+	 * completions in the default status block.
+	 */
+	bool			fcoe_init;
+
 	int			pm_cap;
 	int			mrrs;
 
@@ -1420,6 +1412,8 @@ struct bnx2x {
 #define BNX2X_MAX_COS			3
 #define BNX2X_MAX_TX_COS		2
 	int			num_queues;
+	uint			num_ethernet_queues;
+	uint			num_cnic_queues;
 	int			num_napi_queues;
 	int			disable_tpa;
 
@@ -1433,6 +1427,7 @@ struct bnx2x {
 	u8			igu_dsb_id;
 	u8			igu_base_sb;
 	u8			igu_sb_cnt;
+	u8			min_msix_vec_cnt;
 
 	dma_addr_t		def_status_blk_mapping;
 
@@ -1478,16 +1473,16 @@ struct bnx2x {
  * Maximum supported number of RSS queues: number of IGU SBs minus one that goes
  * to CNIC.
  */
-#define BNX2X_MAX_RSS_COUNT(bp)	((bp)->igu_sb_cnt - CNIC_PRESENT)
+#define BNX2X_MAX_RSS_COUNT(bp)	((bp)->igu_sb_cnt - CNIC_SUPPORT(bp))
 
 /*
  * Maximum CID count that might be required by the bnx2x:
  * Max RSS * Max_Tx_Multi_Cos + FCoE + iSCSI
  */
 #define BNX2X_L2_CID_COUNT(bp)	(BNX2X_NUM_ETH_QUEUES(bp) * BNX2X_MULTI_TX_COS \
-				+ NON_ETH_CONTEXT_USE + CNIC_PRESENT)
+				+ 2 * CNIC_SUPPORT(bp))
 #define BNX2X_L2_MAX_CID(bp)	(BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS \
-				+ NON_ETH_CONTEXT_USE + CNIC_PRESENT)
+				+ 2 * CNIC_SUPPORT(bp))
 #define L2_ILT_LINES(bp)	(DIV_ROUND_UP(BNX2X_L2_CID_COUNT(bp),\
 					ILT_PAGE_CIDS))
 
@@ -1495,9 +1490,6 @@ struct bnx2x {
 
 	int			dropless_fc;
 
-#ifdef BCM_CNIC
-	u32			cnic_flags;
-#define BNX2X_CNIC_FLAG_MAC_SET		1
 	void			*t2;
 	dma_addr_t		t2_mapping;
 	struct cnic_ops	__rcu	*cnic_ops;
@@ -1518,7 +1510,6 @@ struct bnx2x {
 
 	/* Start index of the "special" (CNIC related) L2 cleints */
 	u8				cnic_base_cl_id;
-#endif
 
 	int			dmae_ready;
 	/* used to synchronize dmae accesses */
@@ -1647,9 +1638,9 @@ struct bnx2x {
 /* Tx queues may be less or equal to Rx queues */
 extern int num_queues;
 #define BNX2X_NUM_QUEUES(bp)	(bp->num_queues)
-#define BNX2X_NUM_ETH_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - NON_ETH_CONTEXT_USE)
+#define BNX2X_NUM_ETH_QUEUES(bp) ((bp)->num_ethernet_queues)
 #define BNX2X_NUM_NON_CNIC_QUEUES(bp)	(BNX2X_NUM_QUEUES(bp) - \
-					 NON_ETH_CONTEXT_USE)
+					 (bp)->num_cnic_queues)
 #define BNX2X_NUM_RX_QUEUES(bp)	BNX2X_NUM_QUEUES(bp)
 
 #define is_multi(bp)		(BNX2X_NUM_QUEUES(bp) > 1)
@@ -1689,6 +1680,13 @@ struct bnx2x_func_init_params {
 	u16		spq_prod;	/* valid iff FUNC_FLG_SPQ */
 };
 
+#define for_each_cnic_queue(bp, var) \
+	for ((var) = BNX2X_NUM_ETH_QUEUES(bp); (var) < BNX2X_NUM_QUEUES(bp); \
+	     (var)++) \
+		if (skip_queue(bp, var))	\
+			continue;		\
+		else
+
 #define for_each_eth_queue(bp, var) \
 	for ((var) = 0; (var) < BNX2X_NUM_ETH_QUEUES(bp); (var)++)
 
@@ -1702,6 +1700,22 @@ struct bnx2x_func_init_params {
 		else
 
 /* Skip forwarding FP */
+#define for_each_valid_rx_queue(bp, var)			\
+	for ((var) = 0;						\
+	     (var) < (CNIC_LOADED(bp) ? BNX2X_NUM_QUEUES(bp) :	\
+		      BNX2X_NUM_ETH_QUEUES(bp));		\
+	     (var)++)						\
+		if (skip_rx_queue(bp, var))			\
+			continue;				\
+		else
+
+#define for_each_rx_queue_cnic(bp, var) \
+	for ((var) = BNX2X_NUM_ETH_QUEUES(bp); (var) < BNX2X_NUM_QUEUES(bp); \
+	     (var)++) \
+		if (skip_rx_queue(bp, var))	\
+			continue;		\
+		else
+
 #define for_each_rx_queue(bp, var) \
 	for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
 		if (skip_rx_queue(bp, var))	\
@@ -1709,6 +1723,22 @@ struct bnx2x_func_init_params {
 		else
 
 /* Skip OOO FP */
+#define for_each_valid_tx_queue(bp, var)			\
+	for ((var) = 0;						\
+	     (var) < (CNIC_LOADED(bp) ? BNX2X_NUM_QUEUES(bp) :	\
+		      BNX2X_NUM_ETH_QUEUES(bp));		\
+	     (var)++)						\
+		if (skip_tx_queue(bp, var))			\
+			continue;				\
+		else
+
+#define for_each_tx_queue_cnic(bp, var) \
+	for ((var) = BNX2X_NUM_ETH_QUEUES(bp); (var) < BNX2X_NUM_QUEUES(bp); \
+	     (var)++) \
+		if (skip_tx_queue(bp, var))	\
+			continue;		\
+		else
+
 #define for_each_tx_queue(bp, var) \
 	for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
 		if (skip_tx_queue(bp, var))	\
@@ -2179,7 +2209,6 @@ void bnx2x_notify_link_changed(struct bnx2x *bp);
 #define BNX2X_MF_SD_PROTOCOL(bp) \
 	((bp)->mf_config[BP_VN(bp)] & FUNC_MF_CFG_PROTOCOL_MASK)
 
-#ifdef BCM_CNIC
 #define BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp) \
 	(BNX2X_MF_SD_PROTOCOL(bp) == FUNC_MF_CFG_PROTOCOL_ISCSI)
 
@@ -2196,9 +2225,12 @@ void bnx2x_notify_link_changed(struct bnx2x *bp);
 #define IS_MF_STORAGE_SD(bp) (IS_MF_SD(bp) && \
 				(BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp) || \
 				 BNX2X_IS_MF_SD_PROTOCOL_FCOE(bp)))
-#else
-#define IS_MF_FCOE_AFEX(bp)	false
-#endif
 
+enum {
+	SWITCH_UPDATE,
+	AFEX_UPDATE,
+};
+
+#define NUM_MACS	8
 
 #endif /* bnx2x.h */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 4833b6a..4cb4566 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -948,14 +948,12 @@ void bnx2x_acquire_phy_lock(struct bnx2x *bp)
 {
 	mutex_lock(&bp->port.phy_mutex);
 
-	if (bp->port.need_hw_lock)
-		bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_MDIO);
+	bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_MDIO);
 }
 
 void bnx2x_release_phy_lock(struct bnx2x *bp)
 {
-	if (bp->port.need_hw_lock)
-		bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_MDIO);
+	bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_MDIO);
 
 	mutex_unlock(&bp->port.phy_mutex);
 }
@@ -1152,6 +1150,25 @@ static void bnx2x_free_tpa_pool(struct bnx2x *bp,
 	}
 }
 
+void bnx2x_init_rx_rings_cnic(struct bnx2x *bp)
+{
+	int j;
+
+	for_each_rx_queue_cnic(bp, j) {
+		struct bnx2x_fastpath *fp = &bp->fp[j];
+
+		fp->rx_bd_cons = 0;
+
+		/* Activate BD ring */
+		/* Warning!
+		 * this will generate an interrupt (to the TSTORM)
+		 * must only be done after chip is initialized
+		 */
+		bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod,
+				     fp->rx_sge_prod);
+	}
+}
+
 void bnx2x_init_rx_rings(struct bnx2x *bp)
 {
 	int func = BP_FUNC(bp);
@@ -1159,7 +1176,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
 	int i, j;
 
 	/* Allocate TPA resources */
-	for_each_rx_queue(bp, j) {
+	for_each_eth_queue(bp, j) {
 		struct bnx2x_fastpath *fp = &bp->fp[j];
 
 		DP(NETIF_MSG_IFUP,
@@ -1217,7 +1234,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
 		}
 	}
 
-	for_each_rx_queue(bp, j) {
+	for_each_eth_queue(bp, j) {
 		struct bnx2x_fastpath *fp = &bp->fp[j];
 
 		fp->rx_bd_cons = 0;
@@ -1244,29 +1261,45 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
 	}
 }
 
-static void bnx2x_free_tx_skbs(struct bnx2x *bp)
+static void bnx2x_free_tx_skbs_queue(struct bnx2x_fastpath *fp)
 {
-	int i;
 	u8 cos;
+	struct bnx2x *bp = fp->bp;
 
-	for_each_tx_queue(bp, i) {
-		struct bnx2x_fastpath *fp = &bp->fp[i];
-		for_each_cos_in_tx_queue(fp, cos) {
-			struct bnx2x_fp_txdata *txdata = fp->txdata_ptr[cos];
-			unsigned pkts_compl = 0, bytes_compl = 0;
+	for_each_cos_in_tx_queue(fp, cos) {
+		struct bnx2x_fp_txdata *txdata = fp->txdata_ptr[cos];
+		unsigned pkts_compl = 0, bytes_compl = 0;
 
-			u16 sw_prod = txdata->tx_pkt_prod;
-			u16 sw_cons = txdata->tx_pkt_cons;
+		u16 sw_prod = txdata->tx_pkt_prod;
+		u16 sw_cons = txdata->tx_pkt_cons;
 
-			while (sw_cons != sw_prod) {
-				bnx2x_free_tx_pkt(bp, txdata, TX_BD(sw_cons),
-				    &pkts_compl, &bytes_compl);
-				sw_cons++;
-			}
-			netdev_tx_reset_queue(
-				netdev_get_tx_queue(bp->dev,
-						    txdata->txq_index));
+		while (sw_cons != sw_prod) {
+			bnx2x_free_tx_pkt(bp, txdata, TX_BD(sw_cons),
+					  &pkts_compl, &bytes_compl);
+			sw_cons++;
 		}
+
+		netdev_tx_reset_queue(
+			netdev_get_tx_queue(bp->dev,
+					    txdata->txq_index));
+	}
+}
+
+static void bnx2x_free_tx_skbs_cnic(struct bnx2x *bp)
+{
+	int i;
+
+	for_each_tx_queue_cnic(bp, i) {
+		bnx2x_free_tx_skbs_queue(&bp->fp[i]);
+	}
+}
+
+static void bnx2x_free_tx_skbs(struct bnx2x *bp)
+{
+	int i;
+
+	for_each_eth_queue(bp, i) {
+		bnx2x_free_tx_skbs_queue(&bp->fp[i]);
 	}
 }
 
@@ -1294,11 +1327,20 @@ static void bnx2x_free_rx_bds(struct bnx2x_fastpath *fp)
 	}
 }
 
+static void bnx2x_free_rx_skbs_cnic(struct bnx2x *bp)
+{
+	int j;
+
+	for_each_rx_queue_cnic(bp, j) {
+		bnx2x_free_rx_bds(&bp->fp[j]);
+	}
+}
+
 static void bnx2x_free_rx_skbs(struct bnx2x *bp)
 {
 	int j;
 
-	for_each_rx_queue(bp, j) {
+	for_each_eth_queue(bp, j) {
 		struct bnx2x_fastpath *fp = &bp->fp[j];
 
 		bnx2x_free_rx_bds(fp);
@@ -1308,6 +1350,12 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
 	}
 }
 
+void bnx2x_free_skbs_cnic(struct bnx2x *bp)
+{
+	bnx2x_free_tx_skbs_cnic(bp);
+	bnx2x_free_rx_skbs_cnic(bp);
+}
+
 void bnx2x_free_skbs(struct bnx2x *bp)
 {
 	bnx2x_free_tx_skbs(bp);
@@ -1347,11 +1395,12 @@ static void bnx2x_free_msix_irqs(struct bnx2x *bp, int nvecs)
 	DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n",
 	   bp->msix_table[offset].vector);
 	offset++;
-#ifdef BCM_CNIC
-	if (nvecs == offset)
-		return;
-	offset++;
-#endif
+
+	if (CNIC_SUPPORT(bp)) {
+		if (nvecs == offset)
+			return;
+		offset++;
+	}
 
 	for_each_eth_queue(bp, i) {
 		if (nvecs == offset)
@@ -1368,7 +1417,7 @@ void bnx2x_free_irq(struct bnx2x *bp)
 	if (bp->flags & USING_MSIX_FLAG &&
 	    !(bp->flags & USING_SINGLE_MSIX_FLAG))
 		bnx2x_free_msix_irqs(bp, BNX2X_NUM_ETH_QUEUES(bp) +
-				     CNIC_PRESENT + 1);
+				     CNIC_SUPPORT(bp) + 1);
 	else
 		free_irq(bp->dev->irq, bp->dev);
 }
@@ -1382,12 +1431,14 @@ int bnx2x_enable_msix(struct bnx2x *bp)
 	   bp->msix_table[0].entry);
 	msix_vec++;
 
-#ifdef BCM_CNIC
-	bp->msix_table[msix_vec].entry = msix_vec;
-	BNX2X_DEV_INFO("msix_table[%d].entry = %d (CNIC)\n",
-	   bp->msix_table[msix_vec].entry, bp->msix_table[msix_vec].entry);
-	msix_vec++;
-#endif
+	/* Cnic requires an msix vector for itself */
+	if (CNIC_SUPPORT(bp)) {
+		bp->msix_table[msix_vec].entry = msix_vec;
+		BNX2X_DEV_INFO("msix_table[%d].entry = %d (CNIC)\n",
+			       msix_vec, bp->msix_table[msix_vec].entry);
+		msix_vec++;
+	}
+
 	/* We need separate vectors for ETH queues only (not FCoE) */
 	for_each_eth_queue(bp, i) {
 		bp->msix_table[msix_vec].entry = msix_vec;
@@ -1396,7 +1447,7 @@ int bnx2x_enable_msix(struct bnx2x *bp)
 		msix_vec++;
 	}
 
-	req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_PRESENT + 1;
+	req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_SUPPORT(bp) + 1;
 
 	rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], req_cnt);
 
@@ -1404,7 +1455,7 @@ int bnx2x_enable_msix(struct bnx2x *bp)
 	 * reconfigure number of tx/rx queues according to available
 	 * MSI-X vectors
 	 */
-	if (rc >= BNX2X_MIN_MSIX_VEC_CNT) {
+	if (rc >= BNX2X_MIN_MSIX_VEC_CNT(bp)) {
 		/* how less vectors we will have? */
 		int diff = req_cnt - rc;
 
@@ -1419,7 +1470,8 @@ int bnx2x_enable_msix(struct bnx2x *bp)
 		/*
 		 * decrease number of queues by number of unallocated entries
 		 */
-		bp->num_queues -= diff;
+		bp->num_ethernet_queues -= diff;
+		bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
 
 		BNX2X_DEV_INFO("New queue configuration set: %d\n",
 			       bp->num_queues);
@@ -1435,6 +1487,9 @@ int bnx2x_enable_msix(struct bnx2x *bp)
 		BNX2X_DEV_INFO("Using single MSI-X vector\n");
 		bp->flags |= USING_SINGLE_MSIX_FLAG;
 
+		BNX2X_DEV_INFO("set number of queues to 1\n");
+		bp->num_ethernet_queues = 1;
+		bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
 	} else if (rc < 0) {
 		BNX2X_DEV_INFO("MSI-X is not attainable  rc %d\n", rc);
 		goto no_msix;
@@ -1464,9 +1519,9 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
 		return -EBUSY;
 	}
 
-#ifdef BCM_CNIC
-	offset++;
-#endif
+	if (CNIC_SUPPORT(bp))
+		offset++;
+
 	for_each_eth_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
 		snprintf(fp->name, sizeof(fp->name), "%s-fp-%d",
@@ -1485,7 +1540,7 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
 	}
 
 	i = BNX2X_NUM_ETH_QUEUES(bp);
-	offset = 1 + CNIC_PRESENT;
+	offset = 1 + CNIC_SUPPORT(bp);
 	netdev_info(bp->dev, "using MSI-X  IRQs: sp %d  fp[%d] %d ... fp[%d] %d\n",
 	       bp->msix_table[0].vector,
 	       0, bp->msix_table[offset].vector,
@@ -1556,19 +1611,35 @@ static int bnx2x_setup_irqs(struct bnx2x *bp)
 	return 0;
 }
 
+static void bnx2x_napi_enable_cnic(struct bnx2x *bp)
+{
+	int i;
+
+	for_each_rx_queue_cnic(bp, i)
+		napi_enable(&bnx2x_fp(bp, i, napi));
+}
+
 static void bnx2x_napi_enable(struct bnx2x *bp)
 {
 	int i;
 
-	for_each_rx_queue(bp, i)
+	for_each_eth_queue(bp, i)
 		napi_enable(&bnx2x_fp(bp, i, napi));
 }
 
+static void bnx2x_napi_disable_cnic(struct bnx2x *bp)
+{
+	int i;
+
+	for_each_rx_queue_cnic(bp, i)
+		napi_disable(&bnx2x_fp(bp, i, napi));
+}
+
 static void bnx2x_napi_disable(struct bnx2x *bp)
 {
 	int i;
 
-	for_each_rx_queue(bp, i)
+	for_each_eth_queue(bp, i)
 		napi_disable(&bnx2x_fp(bp, i, napi));
 }
 
@@ -1576,6 +1647,8 @@ void bnx2x_netif_start(struct bnx2x *bp)
 {
 	if (netif_running(bp->dev)) {
 		bnx2x_napi_enable(bp);
+		if (CNIC_LOADED(bp))
+			bnx2x_napi_enable_cnic(bp);
 		bnx2x_int_enable(bp);
 		if (bp->state == BNX2X_STATE_OPEN)
 			netif_tx_wake_all_queues(bp->dev);
@@ -1586,14 +1659,15 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
 {
 	bnx2x_int_disable_sync(bp, disable_hw);
 	bnx2x_napi_disable(bp);
+	if (CNIC_LOADED(bp))
+		bnx2x_napi_disable_cnic(bp);
 }
 
 u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
 {
 	struct bnx2x *bp = netdev_priv(dev);
 
-#ifdef BCM_CNIC
-	if (!NO_FCOE(bp)) {
+	if (CNIC_LOADED(bp) && !NO_FCOE(bp)) {
 		struct ethhdr *hdr = (struct ethhdr *)skb->data;
 		u16 ether_type = ntohs(hdr->h_proto);
 
@@ -1609,7 +1683,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
 		if ((ether_type == ETH_P_FCOE) || (ether_type == ETH_P_FIP))
 			return bnx2x_fcoe_tx(bp, txq_index);
 	}
-#endif
+
 	/* select a non-FCoE queue */
 	return __skb_tx_hash(dev, skb, BNX2X_NUM_ETH_QUEUES(bp));
 }
@@ -1618,15 +1692,15 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
 void bnx2x_set_num_queues(struct bnx2x *bp)
 {
 	/* RSS queues */
-	bp->num_queues = bnx2x_calc_num_queues(bp);
+	bp->num_ethernet_queues = bnx2x_calc_num_queues(bp);
 
-#ifdef BCM_CNIC
 	/* override in STORAGE SD modes */
 	if (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))
-		bp->num_queues = 1;
-#endif
+		bp->num_ethernet_queues = 1;
+
 	/* Add special queues */
-	bp->num_queues += NON_ETH_CONTEXT_USE;
+	bp->num_cnic_queues = CNIC_SUPPORT(bp); /* For FCOE */
+	bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
 
 	BNX2X_DEV_INFO("set number of queues to %d\n", bp->num_queues);
 }
@@ -1653,20 +1727,18 @@ void bnx2x_set_num_queues(struct bnx2x *bp)
  * bnx2x_setup_tc() takes care of the proper TC mappings so that __skb_tx_hash()
  * will return a proper Tx index if TC is enabled (netdev->num_tc > 0).
  */
-static int bnx2x_set_real_num_queues(struct bnx2x *bp)
+static int bnx2x_set_real_num_queues(struct bnx2x *bp, int include_cnic)
 {
 	int rc, tx, rx;
 
 	tx = BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos;
-	rx = BNX2X_NUM_QUEUES(bp) - NON_ETH_CONTEXT_USE;
+	rx = BNX2X_NUM_ETH_QUEUES(bp);
 
 /* account for fcoe queue */
-#ifdef BCM_CNIC
-	if (!NO_FCOE(bp)) {
-		rx += FCOE_PRESENT;
-		tx += FCOE_PRESENT;
+	if (include_cnic && !NO_FCOE(bp)) {
+		rx++;
+		tx++;
 	}
-#endif
 
 	rc = netif_set_real_num_tx_queues(bp->dev, tx);
 	if (rc) {
@@ -1741,7 +1813,6 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
 			bool config_hash)
 {
 	struct bnx2x_config_rss_params params = {NULL};
-	int i;
 
 	/* Although RSS is meaningless when there is a single HW queue we
 	 * still need it enabled in order to have HW Rx hash generated.
@@ -1773,9 +1844,7 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
 
 	if (config_hash) {
 		/* RSS keys */
-		for (i = 0; i < sizeof(params.rss_key) / 4; i++)
-			params.rss_key[i] = random32();
-
+		prandom_bytes(params.rss_key, sizeof(params.rss_key));
 		__set_bit(BNX2X_RSS_SET_SRCH, &params.rss_flags);
 	}
 
@@ -1859,14 +1928,26 @@ static void bnx2x_squeeze_objects(struct bnx2x *bp)
 		(bp)->state = BNX2X_STATE_ERROR; \
 		goto label; \
 	} while (0)
-#else
+
+#define LOAD_ERROR_EXIT_CNIC(bp, label) \
+	do { \
+		bp->cnic_loaded = false; \
+		goto label; \
+	} while (0)
+#else /*BNX2X_STOP_ON_ERROR*/
 #define LOAD_ERROR_EXIT(bp, label) \
 	do { \
 		(bp)->state = BNX2X_STATE_ERROR; \
 		(bp)->panic = 1; \
 		return -EBUSY; \
 	} while (0)
-#endif
+#define LOAD_ERROR_EXIT_CNIC(bp, label) \
+	do { \
+		bp->cnic_loaded = false; \
+		(bp)->panic = 1; \
+		return -EBUSY; \
+	} while (0)
+#endif /*BNX2X_STOP_ON_ERROR*/
 
 bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err)
 {
@@ -1959,10 +2040,8 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index)
 		fp->max_cos = 1;
 
 	/* Init txdata pointers */
-#ifdef BCM_CNIC
 	if (IS_FCOE_FP(fp))
 		fp->txdata_ptr[0] = &bp->bnx2x_txq[FCOE_TXQ_IDX(bp)];
-#endif
 	if (IS_ETH_FP(fp))
 		for_each_cos_in_tx_queue(fp, cos)
 			fp->txdata_ptr[cos] = &bp->bnx2x_txq[cos *
@@ -1980,11 +2059,95 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index)
 	else if (bp->flags & GRO_ENABLE_FLAG)
 		fp->mode = TPA_MODE_GRO;
 
-#ifdef BCM_CNIC
 	/* We don't want TPA on an FCoE L2 ring */
 	if (IS_FCOE_FP(fp))
 		fp->disable_tpa = 1;
-#endif
+}
+
+int bnx2x_load_cnic(struct bnx2x *bp)
+{
+	int i, rc, port = BP_PORT(bp);
+
+	DP(NETIF_MSG_IFUP, "Starting CNIC-related load\n");
+
+	mutex_init(&bp->cnic_mutex);
+
+	rc = bnx2x_alloc_mem_cnic(bp);
+	if (rc) {
+		BNX2X_ERR("Unable to allocate bp memory for cnic\n");
+		LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic0);
+	}
+
+	rc = bnx2x_alloc_fp_mem_cnic(bp);
+	if (rc) {
+		BNX2X_ERR("Unable to allocate memory for cnic fps\n");
+		LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic0);
+	}
+
+	/* Update the number of queues with the cnic queues */
+	rc = bnx2x_set_real_num_queues(bp, 1);
+	if (rc) {
+		BNX2X_ERR("Unable to set real_num_queues including cnic\n");
+		LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic0);
+	}
+
+	/* Add all CNIC NAPI objects */
+	bnx2x_add_all_napi_cnic(bp);
+	DP(NETIF_MSG_IFUP, "cnic napi added\n");
+	bnx2x_napi_enable_cnic(bp);
+
+	rc = bnx2x_init_hw_func_cnic(bp);
+	if (rc)
+		LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic1);
+
+	bnx2x_nic_init_cnic(bp);
+
+	/* Enable Timer scan */
+	REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 1);
+
+	for_each_cnic_queue(bp, i) {
+		rc = bnx2x_setup_queue(bp, &bp->fp[i], 0);
+		if (rc) {
+			BNX2X_ERR("Queue setup failed\n");
+			LOAD_ERROR_EXIT(bp, load_error_cnic2);
+		}
+	}
+
+	/* Initialize Rx filter. */
+	netif_addr_lock_bh(bp->dev);
+	bnx2x_set_rx_mode(bp->dev);
+	netif_addr_unlock_bh(bp->dev);
+
+	/* re-read iscsi info */
+	bnx2x_get_iscsi_info(bp);
+	bnx2x_setup_cnic_irq_info(bp);
+	bnx2x_setup_cnic_info(bp);
+	bp->cnic_loaded = true;
+	if (bp->state == BNX2X_STATE_OPEN)
+		bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD);
+
+
+	DP(NETIF_MSG_IFUP, "Ending successfully CNIC-related load\n");
+
+	return 0;
+
+#ifndef BNX2X_STOP_ON_ERROR
+load_error_cnic2:
+	/* Disable Timer scan */
+	REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
+
+load_error_cnic1:
+	bnx2x_napi_disable_cnic(bp);
+	/* Update the number of queues without the cnic queues */
+	rc = bnx2x_set_real_num_queues(bp, 0);
+	if (rc)
+		BNX2X_ERR("Unable to set real_num_queues not including cnic\n");
+load_error_cnic0:
+	BNX2X_ERR("CNIC-related load failed\n");
+	bnx2x_free_fp_mem_cnic(bp);
+	bnx2x_free_mem_cnic(bp);
+	return rc;
+#endif /* ! BNX2X_STOP_ON_ERROR */
 }
 
 
@@ -1995,6 +2158,10 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 	u32 load_code;
 	int i, rc;
 
+	DP(NETIF_MSG_IFUP, "Starting NIC load\n");
+	DP(NETIF_MSG_IFUP,
+	   "CNIC is %s\n", CNIC_ENABLED(bp) ? "enabled" : "disabled");
+
 #ifdef BNX2X_STOP_ON_ERROR
 	if (unlikely(bp->panic)) {
 		BNX2X_ERR("Can't load NIC when there is panic\n");
@@ -2022,9 +2189,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 	DP(NETIF_MSG_IFUP, "num queues: %d", bp->num_queues);
 	for_each_queue(bp, i)
 		bnx2x_bz_fp(bp, i);
-	memset(bp->bnx2x_txq, 0, bp->bnx2x_txq_size *
-	       sizeof(struct bnx2x_fp_txdata));
+	memset(bp->bnx2x_txq, 0, (BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS +
+				  bp->num_cnic_queues) *
+				  sizeof(struct bnx2x_fp_txdata));
 
+	bp->fcoe_init = false;
 
 	/* Set the receive queues buffer size */
 	bnx2x_set_rx_buf_size(bp);
@@ -2034,9 +2203,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 
 	/* As long as bnx2x_alloc_mem() may possibly update
 	 * bp->num_queues, bnx2x_set_real_num_queues() should always
-	 * come after it.
+	 * come after it. At this stage cnic queues are not counted.
 	 */
-	rc = bnx2x_set_real_num_queues(bp);
+	rc = bnx2x_set_real_num_queues(bp, 0);
 	if (rc) {
 		BNX2X_ERR("Unable to set real_num_queues\n");
 		LOAD_ERROR_EXIT(bp, load_error0);
@@ -2050,6 +2219,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 
 	/* Add all NAPI objects */
 	bnx2x_add_all_napi(bp);
+	DP(NETIF_MSG_IFUP, "napi added\n");
 	bnx2x_napi_enable(bp);
 
 	/* set pf load just before approaching the MCP */
@@ -2073,7 +2243,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 			 DRV_PULSE_SEQ_MASK);
 		BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
 
-		load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0);
+		load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ,
+					     DRV_MSG_CODE_LOAD_REQ_WITH_LFA);
 		if (!load_code) {
 			BNX2X_ERR("MCP response failure, aborting\n");
 			rc = -EBUSY;
@@ -2191,23 +2362,18 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 		LOAD_ERROR_EXIT(bp, load_error3);
 	}
 
-#ifdef BCM_CNIC
-	/* Enable Timer scan */
-	REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 1);
-#endif
-
-	for_each_nondefault_queue(bp, i) {
+	for_each_nondefault_eth_queue(bp, i) {
 		rc = bnx2x_setup_queue(bp, &bp->fp[i], 0);
 		if (rc) {
 			BNX2X_ERR("Queue setup failed\n");
-			LOAD_ERROR_EXIT(bp, load_error4);
+			LOAD_ERROR_EXIT(bp, load_error3);
 		}
 	}
 
 	rc = bnx2x_init_rss_pf(bp);
 	if (rc) {
 		BNX2X_ERR("PF RSS init failed\n");
-		LOAD_ERROR_EXIT(bp, load_error4);
+		LOAD_ERROR_EXIT(bp, load_error3);
 	}
 
 	/* Now when Clients are configured we are ready to work */
@@ -2217,7 +2383,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 	rc = bnx2x_set_eth_mac(bp, true);
 	if (rc) {
 		BNX2X_ERR("Setting Ethernet MAC failed\n");
-		LOAD_ERROR_EXIT(bp, load_error4);
+		LOAD_ERROR_EXIT(bp, load_error3);
 	}
 
 	if (bp->pending_max) {
@@ -2264,14 +2430,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 	/* start the timer */
 	mod_timer(&bp->timer, jiffies + bp->current_interval);
 
-#ifdef BCM_CNIC
-	/* re-read iscsi info */
-	bnx2x_get_iscsi_info(bp);
-	bnx2x_setup_cnic_irq_info(bp);
-	bnx2x_setup_cnic_info(bp);
-	if (bp->state == BNX2X_STATE_OPEN)
-		bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD);
-#endif
+	if (CNIC_ENABLED(bp))
+		bnx2x_load_cnic(bp);
 
 	/* mark driver is loaded in shmem2 */
 	if (SHMEM2_HAS(bp, drv_capabilities_flag)) {
@@ -2293,14 +2453,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 	if (bp->port.pmf && (bp->state != BNX2X_STATE_DIAG))
 		bnx2x_dcbx_init(bp, false);
 
+	DP(NETIF_MSG_IFUP, "Ending successfully NIC load\n");
+
 	return 0;
 
 #ifndef BNX2X_STOP_ON_ERROR
-load_error4:
-#ifdef BCM_CNIC
-	/* Disable Timer scan */
-	REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
-#endif
 load_error3:
 	bnx2x_int_disable_sync(bp, 1);
 
@@ -2338,6 +2495,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
 	int i;
 	bool global = false;
 
+	DP(NETIF_MSG_IFUP, "Starting NIC unload\n");
+
 	/* mark driver is unloaded in shmem2 */
 	if (SHMEM2_HAS(bp, drv_capabilities_flag)) {
 		u32 val;
@@ -2373,14 +2532,13 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
 	bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
 	smp_mb();
 
+	if (CNIC_LOADED(bp))
+		bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
+
 	/* Stop Tx */
 	bnx2x_tx_disable(bp);
 	netdev_reset_tc(bp->dev);
 
-#ifdef BCM_CNIC
-	bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
-#endif
-
 	bp->rx_mode = BNX2X_RX_MODE_NONE;
 
 	del_timer_sync(&bp->timer);
@@ -2414,7 +2572,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
 		bnx2x_netif_stop(bp, 1);
 		/* Delete all NAPI objects */
 		bnx2x_del_all_napi(bp);
-
+		if (CNIC_LOADED(bp))
+			bnx2x_del_all_napi_cnic(bp);
 		/* Release IRQs */
 		bnx2x_free_irq(bp);
 
@@ -2435,12 +2594,19 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
 
 	/* Free SKBs, SGEs, TPA pool and driver internals */
 	bnx2x_free_skbs(bp);
+	if (CNIC_LOADED(bp))
+		bnx2x_free_skbs_cnic(bp);
 	for_each_rx_queue(bp, i)
 		bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
 
+	if (CNIC_LOADED(bp)) {
+		bnx2x_free_fp_mem_cnic(bp);
+		bnx2x_free_mem_cnic(bp);
+	}
 	bnx2x_free_mem(bp);
 
 	bp->state = BNX2X_STATE_CLOSED;
+	bp->cnic_loaded = false;
 
 	/* Check if there are pending parity attentions. If there are - set
 	 * RECOVERY_IN_PROGRESS.
@@ -2460,6 +2626,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
 	if (!bnx2x_clear_pf_load(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp)))
 		bnx2x_disable_close_the_gate(bp);
 
+	DP(NETIF_MSG_IFUP, "Ending NIC unload\n");
+
 	return 0;
 }
 
@@ -2550,7 +2718,7 @@ int bnx2x_poll(struct napi_struct *napi, int budget)
 
 		/* Fall out from the NAPI loop if needed */
 		if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
-#ifdef BCM_CNIC
+
 			/* No need to update SB for FCoE L2 ring as long as
 			 * it's connected to the default SB and the SB
 			 * has been updated when NAPI was scheduled.
@@ -2559,8 +2727,6 @@ int bnx2x_poll(struct napi_struct *napi, int budget)
 				napi_complete(napi);
 				break;
 			}
-#endif
-
 			bnx2x_update_fpsb_idx(fp);
 			/* bnx2x_has_rx_work() reads the status block,
 			 * thus we need to ensure that status block indices
@@ -2940,7 +3106,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	txq_index = skb_get_queue_mapping(skb);
 	txq = netdev_get_tx_queue(dev, txq_index);
 
-	BUG_ON(txq_index >= MAX_ETH_TXQ_IDX(bp) + FCOE_PRESENT);
+	BUG_ON(txq_index >= MAX_ETH_TXQ_IDX(bp) + (CNIC_LOADED(bp) ? 1 : 0));
 
 	txdata = &bp->bnx2x_txq[txq_index];
 
@@ -3339,13 +3505,11 @@ int bnx2x_change_mac_addr(struct net_device *dev, void *p)
 		return -EINVAL;
 	}
 
-#ifdef BCM_CNIC
 	if ((IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp)) &&
 	    !is_zero_ether_addr(addr->sa_data)) {
 		BNX2X_ERR("Can't configure non-zero address on iSCSI or FCoE functions in MF-SD mode\n");
 		return -EINVAL;
 	}
-#endif
 
 	if (netif_running(dev))  {
 		rc = bnx2x_set_eth_mac(bp, false);
@@ -3369,13 +3533,11 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
 	u8 cos;
 
 	/* Common */
-#ifdef BCM_CNIC
+
 	if (IS_FCOE_IDX(fp_index)) {
 		memset(sb, 0, sizeof(union host_hc_status_block));
 		fp->status_blk_mapping = 0;
-
 	} else {
-#endif
 		/* status blocks */
 		if (!CHIP_IS_E1x(bp))
 			BNX2X_PCI_FREE(sb->e2_sb,
@@ -3387,9 +3549,8 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
 				       bnx2x_fp(bp, fp_index,
 						status_blk_mapping),
 				       sizeof(struct host_hc_status_block_e1x));
-#ifdef BCM_CNIC
 	}
-#endif
+
 	/* Rx */
 	if (!skip_rx_queue(bp, fp_index)) {
 		bnx2x_free_rx_bds(fp);
@@ -3431,10 +3592,17 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
 	/* end of fastpath */
 }
 
+void bnx2x_free_fp_mem_cnic(struct bnx2x *bp)
+{
+	int i;
+	for_each_cnic_queue(bp, i)
+		bnx2x_free_fp_mem_at(bp, i);
+}
+
 void bnx2x_free_fp_mem(struct bnx2x *bp)
 {
 	int i;
-	for_each_queue(bp, i)
+	for_each_eth_queue(bp, i)
 		bnx2x_free_fp_mem_at(bp, i);
 }
 
@@ -3519,14 +3687,11 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
 	u8 cos;
 	int rx_ring_size = 0;
 
-#ifdef BCM_CNIC
 	if (!bp->rx_ring_size &&
 	    (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))) {
 		rx_ring_size = MIN_RX_SIZE_NONTPA;
 		bp->rx_ring_size = rx_ring_size;
-	} else
-#endif
-	if (!bp->rx_ring_size) {
+	} else if (!bp->rx_ring_size) {
 		rx_ring_size = MAX_RX_AVAIL/BNX2X_NUM_RX_QUEUES(bp);
 
 		if (CHIP_IS_E3(bp)) {
@@ -3550,9 +3715,8 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
 
 	/* Common */
 	sb = &bnx2x_fp(bp, index, status_blk);
-#ifdef BCM_CNIC
+
 	if (!IS_FCOE_IDX(index)) {
-#endif
 		/* status blocks */
 		if (!CHIP_IS_E1x(bp))
 			BNX2X_PCI_ALLOC(sb->e2_sb,
@@ -3562,9 +3726,7 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
 			BNX2X_PCI_ALLOC(sb->e1x_sb,
 				&bnx2x_fp(bp, index, status_blk_mapping),
 			    sizeof(struct host_hc_status_block_e1x));
-#ifdef BCM_CNIC
 	}
-#endif
 
 	/* FCoE Queue uses Default SB and doesn't ACK the SB, thus no need to
 	 * set shortcuts for it.
@@ -3641,31 +3803,31 @@ alloc_mem_err:
 	return 0;
 }
 
+int bnx2x_alloc_fp_mem_cnic(struct bnx2x *bp)
+{
+	if (!NO_FCOE(bp))
+		/* FCoE */
+		if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX(bp)))
+			/* we will fail load process instead of mark
+			 * NO_FCOE_FLAG
+			 */
+			return -ENOMEM;
+
+	return 0;
+}
+
 int bnx2x_alloc_fp_mem(struct bnx2x *bp)
 {
 	int i;
 
-	/**
-	 * 1. Allocate FP for leading - fatal if error
-	 * 2. {CNIC} Allocate FCoE FP - fatal if error
-	 * 3. {CNIC} Allocate OOO + FWD - disable OOO if error
-	 * 4. Allocate RSS - fix number of queues if error
+	/* 1. Allocate FP for leading - fatal if error
+	 * 2. Allocate RSS - fix number of queues if error
 	 */
 
 	/* leading */
 	if (bnx2x_alloc_fp_mem_at(bp, 0))
 		return -ENOMEM;
 
-#ifdef BCM_CNIC
-	if (!NO_FCOE(bp))
-		/* FCoE */
-		if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX(bp)))
-			/* we will fail load process instead of mark
-			 * NO_FCOE_FLAG
-			 */
-			return -ENOMEM;
-#endif
-
 	/* RSS */
 	for_each_nondefault_eth_queue(bp, i)
 		if (bnx2x_alloc_fp_mem_at(bp, i))
@@ -3676,17 +3838,17 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp)
 		int delta = BNX2X_NUM_ETH_QUEUES(bp) - i;
 
 		WARN_ON(delta < 0);
-#ifdef BCM_CNIC
-		/**
-		 * move non eth FPs next to last eth FP
-		 * must be done in that order
-		 * FCOE_IDX < FWD_IDX < OOO_IDX
-		 */
+		if (CNIC_SUPPORT(bp))
+			/* move non eth FPs next to last eth FP
+			 * must be done in that order
+			 * FCOE_IDX < FWD_IDX < OOO_IDX
+			 */
 
-		/* move FCoE fp even NO_FCOE_FLAG is on */
-		bnx2x_move_fp(bp, FCOE_IDX(bp), FCOE_IDX(bp) - delta);
-#endif
-		bp->num_queues -= delta;
+			/* move FCoE fp even NO_FCOE_FLAG is on */
+			bnx2x_move_fp(bp, FCOE_IDX(bp), FCOE_IDX(bp) - delta);
+		bp->num_ethernet_queues -= delta;
+		bp->num_queues = bp->num_ethernet_queues +
+				 bp->num_cnic_queues;
 		BNX2X_ERR("Adjusted num of queues from %d to %d\n",
 			  bp->num_queues + delta, bp->num_queues);
 	}
@@ -3711,7 +3873,7 @@ int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
 	struct msix_entry *tbl;
 	struct bnx2x_ilt *ilt;
 	int msix_table_size = 0;
-	int fp_array_size;
+	int fp_array_size, txq_array_size;
 	int i;
 
 	/*
@@ -3721,7 +3883,7 @@ int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
 	msix_table_size = bp->igu_sb_cnt + 1;
 
 	/* fp array: RSS plus CNIC related L2 queues */
-	fp_array_size = BNX2X_MAX_RSS_COUNT(bp) + NON_ETH_CONTEXT_USE;
+	fp_array_size = BNX2X_MAX_RSS_COUNT(bp) + CNIC_SUPPORT(bp);
 	BNX2X_DEV_INFO("fp_array_size %d", fp_array_size);
 
 	fp = kcalloc(fp_array_size, sizeof(*fp), GFP_KERNEL);
@@ -3750,12 +3912,12 @@ int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
 		goto alloc_err;
 
 	/* Allocate memory for the transmission queues array */
-	bp->bnx2x_txq_size = BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS;
-#ifdef BCM_CNIC
-	bp->bnx2x_txq_size++;
-#endif
-	bp->bnx2x_txq = kcalloc(bp->bnx2x_txq_size,
-				sizeof(struct bnx2x_fp_txdata), GFP_KERNEL);
+	txq_array_size =
+		BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS + CNIC_SUPPORT(bp);
+	BNX2X_DEV_INFO("txq_array_size %d", txq_array_size);
+
+	bp->bnx2x_txq = kcalloc(txq_array_size, sizeof(struct bnx2x_fp_txdata),
+				GFP_KERNEL);
 	if (!bp->bnx2x_txq)
 		goto alloc_err;
 
@@ -3838,7 +4000,7 @@ int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
 	return LINK_CONFIG_IDX(sel_phy_idx);
 }
 
-#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
+#ifdef NETDEV_FCOE_WWNN
 int bnx2x_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type)
 {
 	struct bnx2x *bp = netdev_priv(dev);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index 9c5ea6c..ad28074 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -238,7 +238,6 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance);
  * @dev_instance:	private instance
  */
 irqreturn_t bnx2x_interrupt(int irq, void *dev_instance);
-#ifdef BCM_CNIC
 
 /**
  * bnx2x_cnic_notify - send command to cnic driver
@@ -262,8 +261,6 @@ void bnx2x_setup_cnic_irq_info(struct bnx2x *bp);
  */
 void bnx2x_setup_cnic_info(struct bnx2x *bp);
 
-#endif
-
 /**
  * bnx2x_int_enable - enable HW interrupts.
  *
@@ -283,7 +280,7 @@ void bnx2x_int_enable(struct bnx2x *bp);
 void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw);
 
 /**
- * bnx2x_nic_init - init driver internals.
+ * bnx2x_nic_init_cnic - init driver internals for cnic.
  *
  * @bp:		driver handle
  * @load_code:	COMMON, PORT or FUNCTION
@@ -293,9 +290,26 @@ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw);
  *  - status blocks
  *  - etc.
  */
-void bnx2x_nic_init(struct bnx2x *bp, u32 load_code);
+void bnx2x_nic_init_cnic(struct bnx2x *bp);
 
 /**
+ * bnx2x_nic_init - init driver internals.
+ *
+ * @bp:		driver handle
+ *
+ * Initializes:
+ *  - rings
+ *  - status blocks
+ *  - etc.
+ */
+void bnx2x_nic_init(struct bnx2x *bp, u32 load_code);
+/**
+ * bnx2x_alloc_mem_cnic - allocate driver's memory for cnic.
+ *
+ * @bp:		driver handle
+ */
+int bnx2x_alloc_mem_cnic(struct bnx2x *bp);
+/**
  * bnx2x_alloc_mem - allocate driver's memory.
  *
  * @bp:		driver handle
@@ -303,6 +317,12 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code);
 int bnx2x_alloc_mem(struct bnx2x *bp);
 
 /**
+ * bnx2x_free_mem_cnic - release driver's memory for cnic.
+ *
+ * @bp:		driver handle
+ */
+void bnx2x_free_mem_cnic(struct bnx2x *bp);
+/**
  * bnx2x_free_mem - release driver's memory.
  *
  * @bp:		driver handle
@@ -407,6 +427,7 @@ bool bnx2x_reset_is_done(struct bnx2x *bp, int engine);
 void bnx2x_set_reset_in_progress(struct bnx2x *bp);
 void bnx2x_set_reset_global(struct bnx2x *bp);
 void bnx2x_disable_close_the_gate(struct bnx2x *bp);
+int bnx2x_init_hw_func_cnic(struct bnx2x *bp);
 
 /**
  * bnx2x_sp_event - handle ramrods completion.
@@ -424,6 +445,14 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe);
 void bnx2x_ilt_set_info(struct bnx2x *bp);
 
 /**
+ * bnx2x_ilt_set_cnic_info - prepare ILT configurations for SRC
+ * and TM.
+ *
+ * @bp:		driver handle
+ */
+void bnx2x_ilt_set_info_cnic(struct bnx2x *bp);
+
+/**
  * bnx2x_dcbx_init - initialize dcbx protocol.
  *
  * @bp:		driver handle
@@ -491,12 +520,17 @@ int bnx2x_resume(struct pci_dev *pdev);
 /* Release IRQ vectors */
 void bnx2x_free_irq(struct bnx2x *bp);
 
+void bnx2x_free_fp_mem_cnic(struct bnx2x *bp);
 void bnx2x_free_fp_mem(struct bnx2x *bp);
+int bnx2x_alloc_fp_mem_cnic(struct bnx2x *bp);
 int bnx2x_alloc_fp_mem(struct bnx2x *bp);
 void bnx2x_init_rx_rings(struct bnx2x *bp);
+void bnx2x_init_rx_rings_cnic(struct bnx2x *bp);
+void bnx2x_free_skbs_cnic(struct bnx2x *bp);
 void bnx2x_free_skbs(struct bnx2x *bp);
 void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw);
 void bnx2x_netif_start(struct bnx2x *bp);
+int bnx2x_load_cnic(struct bnx2x *bp);
 
 /**
  * bnx2x_enable_msix - set msix configuration.
@@ -547,7 +581,7 @@ void bnx2x_free_mem_bp(struct bnx2x *bp);
  */
 int bnx2x_change_mtu(struct net_device *dev, int new_mtu);
 
-#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
+#ifdef NETDEV_FCOE_WWNN
 /**
  * bnx2x_fcoe_get_wwn - return the requested WWN value for this port
  *
@@ -793,23 +827,39 @@ static inline void bnx2x_free_rx_sge(struct bnx2x *bp,
 	sge->addr_lo = 0;
 }
 
-static inline void bnx2x_add_all_napi(struct bnx2x *bp)
+static inline void bnx2x_add_all_napi_cnic(struct bnx2x *bp)
 {
 	int i;
 
-	bp->num_napi_queues = bp->num_queues;
+	/* Add NAPI objects */
+	for_each_rx_queue_cnic(bp, i)
+		netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
+			       bnx2x_poll, BNX2X_NAPI_WEIGHT);
+}
+
+static inline void bnx2x_add_all_napi(struct bnx2x *bp)
+{
+	int i;
 
 	/* Add NAPI objects */
-	for_each_rx_queue(bp, i)
+	for_each_eth_queue(bp, i)
 		netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
 			       bnx2x_poll, BNX2X_NAPI_WEIGHT);
 }
 
+static inline void bnx2x_del_all_napi_cnic(struct bnx2x *bp)
+{
+	int i;
+
+	for_each_rx_queue_cnic(bp, i)
+		netif_napi_del(&bnx2x_fp(bp, i, napi));
+}
+
 static inline void bnx2x_del_all_napi(struct bnx2x *bp)
 {
 	int i;
 
-	for_each_rx_queue(bp, i)
+	for_each_eth_queue(bp, i)
 		netif_napi_del(&bnx2x_fp(bp, i, napi));
 }
 
@@ -979,11 +1029,9 @@ static inline u8 bnx2x_stats_id(struct bnx2x_fastpath *fp)
 {
 	struct bnx2x *bp = fp->bp;
 	if (!CHIP_IS_E1x(bp)) {
-#ifdef BCM_CNIC
 		/* there are special statistics counters for FCoE 136..140 */
 		if (IS_FCOE_FP(fp))
 			return bp->cnic_base_cl_id + (bp->pf_num >> 1);
-#endif
 		return fp->cl_id;
 	}
 	return fp->cl_id + BP_PORT(bp) * FP_SB_MAX_E1x;
@@ -1102,7 +1150,6 @@ static inline void bnx2x_init_txdata(struct bnx2x *bp,
 	   txdata->cid, txdata->txq_index);
 }
 
-#ifdef BCM_CNIC
 static inline u8 bnx2x_cnic_eth_cl_id(struct bnx2x *bp, u8 cl_idx)
 {
 	return bp->cnic_base_cl_id + cl_idx +
@@ -1162,7 +1209,6 @@ static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
 	   fp->index, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id,
 	   fp->igu_sb_id);
 }
-#endif
 
 static inline int bnx2x_clean_tx_queue(struct bnx2x *bp,
 				       struct bnx2x_fp_txdata *txdata)
@@ -1280,7 +1326,7 @@ static inline bool bnx2x_mtu_allows_gro(int mtu)
 	 */
 	return mtu <= SGE_PAGE_SIZE && (U_ETH_SGL_SIZE * fpp) <= MAX_SKB_FRAGS;
 }
-#ifdef BCM_CNIC
+
 /**
  * bnx2x_get_iscsi_info - update iSCSI params according to licensing info.
  *
@@ -1288,7 +1334,6 @@ static inline bool bnx2x_mtu_allows_gro(int mtu)
  *
  */
 void bnx2x_get_iscsi_info(struct bnx2x *bp);
-#endif
 
 /**
  * bnx2x_link_sync_notify - send notification to other functions.
@@ -1340,13 +1385,11 @@ static inline void bnx2x_update_drv_flags(struct bnx2x *bp, u32 flags, u32 set)
 
 static inline bool bnx2x_is_valid_ether_addr(struct bnx2x *bp, u8 *addr)
 {
-	if (is_valid_ether_addr(addr))
+	if (is_valid_ether_addr(addr) ||
+	    (is_zero_ether_addr(addr) &&
+	     (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))))
 		return true;
-#ifdef BCM_CNIC
-	if (is_zero_ether_addr(addr) &&
-	    (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp)))
-		return true;
-#endif
+
 	return false;
 }
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
index 2245c38..cba4a16 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
@@ -1908,10 +1908,10 @@ static void bnx2x_dcbnl_get_perm_hw_addr(struct net_device *netdev,
 	/* first the HW mac address */
 	memcpy(perm_addr, netdev->dev_addr, netdev->addr_len);
 
-#ifdef BCM_CNIC
-	/* second SAN address */
-	memcpy(perm_addr+netdev->addr_len, bp->fip_mac, netdev->addr_len);
-#endif
+	if (CNIC_LOADED(bp))
+		/* second SAN address */
+		memcpy(perm_addr+netdev->addr_len, bp->fip_mac,
+		       netdev->addr_len);
 }
 
 static void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device *netdev, int prio,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index 6e5bdd1..e05f981 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -2660,20 +2660,25 @@ static int bnx2x_set_phys_id(struct net_device *dev,
 		return 1;	/* cycle on/off once per second */
 
 	case ETHTOOL_ID_ON:
+		bnx2x_acquire_phy_lock(bp);
 		bnx2x_set_led(&bp->link_params, &bp->link_vars,
 			      LED_MODE_ON, SPEED_1000);
+		bnx2x_release_phy_lock(bp);
 		break;
 
 	case ETHTOOL_ID_OFF:
+		bnx2x_acquire_phy_lock(bp);
 		bnx2x_set_led(&bp->link_params, &bp->link_vars,
 			      LED_MODE_FRONT_PANEL_OFF, 0);
-
+		bnx2x_release_phy_lock(bp);
 		break;
 
 	case ETHTOOL_ID_INACTIVE:
+		bnx2x_acquire_phy_lock(bp);
 		bnx2x_set_led(&bp->link_params, &bp->link_vars,
 			      LED_MODE_OPER,
 			      bp->link_vars.line_speed);
+		bnx2x_release_phy_lock(bp);
 	}
 
 	return 0;
@@ -2901,7 +2906,9 @@ static void bnx2x_get_channels(struct net_device *dev,
 static void bnx2x_change_num_queues(struct bnx2x *bp, int num_rss)
 {
 	bnx2x_disable_msi(bp);
-	BNX2X_NUM_QUEUES(bp) = num_rss + NON_ETH_CONTEXT_USE;
+	bp->num_ethernet_queues = num_rss;
+	bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
+	BNX2X_DEV_INFO("set number of queues to %d\n", bp->num_queues);
 	bnx2x_set_int_mode(bp);
 }
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
index 1870492..1504e0a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
@@ -695,6 +695,7 @@ struct port_hw_cfg {		    /* port 0: 0x12c  port 1: 0x2bc */
 		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54618SE    0x00000e00
 		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8722       0x00000f00
 		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54616      0x00001000
+		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84834      0x00001100
 		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE       0x0000fd00
 		#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN      0x0000ff00
 
@@ -751,6 +752,7 @@ struct port_hw_cfg {		    /* port 0: 0x12c  port 1: 0x2bc */
 		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE     0x00000e00
 		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722        0x00000f00
 		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616       0x00001000
+		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834       0x00001100
 		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT_WC      0x0000fc00
 		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE        0x0000fd00
 		#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN       0x0000ff00
@@ -1246,6 +1248,7 @@ struct drv_func_mb {
 	#define DRV_MSG_CODE_VRFY_AFEX_SUPPORTED        0xa2000000
 	#define REQ_BC_VER_4_VRFY_AFEX_SUPPORTED        0x00070002
 	#define REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED   0x00070014
+	#define REQ_BC_VER_4_MT_SUPPORTED               0x00070201
 	#define REQ_BC_VER_4_PFC_STATS_SUPPORTED        0x00070201
 	#define REQ_BC_VER_4_FCOE_FEATURES              0x00070209
 
@@ -2159,6 +2162,16 @@ struct shmem2_region {
 	#define SHMEM_EEE_TIME_OUTPUT_BIT	   0x80000000
 
 	u32 sizeof_port_stats;
+
+	/* Link Flap Avoidance */
+	u32 lfa_host_addr[PORT_MAX];
+	u32 reserved1;
+
+	u32 reserved2;				/* Offset 0x148 */
+	u32 reserved3;				/* Offset 0x14C */
+	u32 reserved4;				/* Offset 0x150 */
+	u32 link_attr_sync[PORT_MAX];		/* Offset 0x154 */
+	#define LINK_ATTR_SYNC_KR2_ENABLE	(1<<0)
 };
 
 
@@ -4845,9 +4858,17 @@ struct vif_list_event_data {
 	__le32 reserved2;
 };
 
-/*
- * union for all event ring message types
- */
+/* function update event data */
+struct function_update_event_data {
+	u8 echo;
+	u8 reserved;
+	__le16 reserved0;
+	__le32 reserved1;
+	__le32 reserved2;
+};
+
+
+/* union for all event ring message types */
 union event_data {
 	struct vf_pf_event_data vf_pf_event;
 	struct eth_event_data eth_event;
@@ -4855,6 +4876,7 @@ union event_data {
 	struct vf_flr_event_data vf_flr_event;
 	struct malicious_vf_event_data malicious_vf_event;
 	struct vif_list_event_data vif_list_event;
+	struct function_update_event_data function_update_event;
 };
 
 
@@ -4984,8 +5006,10 @@ struct function_update_data {
 	u8 allowed_priorities;
 	u8 network_cos_mode;
 	u8 lb_mode_en;
-	u8 reserved0;
-	__le32 reserved1;
+	u8 tx_switch_suspend_change_flg;
+	u8 tx_switch_suspend;
+	u8 echo;
+	__le16 reserved1;
 };
 
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h
index fe66d90..d755acf 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h
@@ -648,15 +648,25 @@ static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num,
 	return rc;
 }
 
+static int bnx2x_ilt_mem_op_cnic(struct bnx2x *bp, u8 memop)
+{
+	int rc = 0;
+
+	if (CONFIGURE_NIC_MODE(bp))
+		rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop);
+	if (!rc)
+		rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_TM, memop);
+
+	return rc;
+}
+
 static int bnx2x_ilt_mem_op(struct bnx2x *bp, u8 memop)
 {
 	int rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_CDU, memop);
 	if (!rc)
 		rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_QM, memop);
-	if (!rc)
+	if (!rc && CNIC_SUPPORT(bp) && !CONFIGURE_NIC_MODE(bp))
 		rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop);
-	if (!rc)
-		rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_TM, memop);
 
 	return rc;
 }
@@ -781,12 +791,19 @@ static void bnx2x_ilt_client_id_init_op(struct bnx2x *bp,
 	bnx2x_ilt_client_init_op(bp, ilt_cli, initop);
 }
 
+static void bnx2x_ilt_init_op_cnic(struct bnx2x *bp, u8 initop)
+{
+	if (CONFIGURE_NIC_MODE(bp))
+		bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop);
+	bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_TM, initop);
+}
+
 static void bnx2x_ilt_init_op(struct bnx2x *bp, u8 initop)
 {
 	bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_CDU, initop);
 	bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_QM, initop);
-	bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop);
-	bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_TM, initop);
+	if (CNIC_SUPPORT(bp) && !CONFIGURE_NIC_MODE(bp))
+		bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop);
 }
 
 static void bnx2x_ilt_init_client_psz(struct bnx2x *bp, int cli_num,
@@ -890,7 +907,6 @@ static void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count,
 /****************************************************************************
 * SRC initializations
 ****************************************************************************/
-#ifdef BCM_CNIC
 /* called during init func stage */
 static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
 			      dma_addr_t t2_mapping, int src_cid_count)
@@ -915,5 +931,4 @@ static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
 		    U64_HI((u64)t2_mapping +
 			   (src_cid_count-1) * sizeof(struct src_ent)));
 }
-#endif
 #endif /* BNX2X_INIT_OPS_H */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index f6cfdc6..3e7d824 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -121,6 +121,7 @@
 #define	GP_STATUS_10G_XFI   MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI
 #define	GP_STATUS_20G_DXGXS MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS
 #define	GP_STATUS_10G_SFI   MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI
+#define	GP_STATUS_20G_KR2 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_KR2
 #define LINK_10THD		LINK_STATUS_SPEED_AND_DUPLEX_10THD
 #define LINK_10TFD		LINK_STATUS_SPEED_AND_DUPLEX_10TFD
 #define LINK_100TXHD		LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
@@ -1440,30 +1441,47 @@ void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
 /******************************************************************/
 /*			MAC/PBF section				  */
 /******************************************************************/
-static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id, u8 port)
+static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id,
+			       u32 emac_base)
 {
-	u32 mode, emac_base;
+	u32 new_mode, cur_mode;
+	u32 clc_cnt;
 	/* Set clause 45 mode, slow down the MDIO clock to 2.5MHz
 	 * (a value of 49==0x31) and make sure that the AUTO poll is off
 	 */
+	cur_mode = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
 
-	if (CHIP_IS_E2(bp))
-		emac_base = GRCBASE_EMAC0;
-	else
-		emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-	mode = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
-	mode &= ~(EMAC_MDIO_MODE_AUTO_POLL |
-		  EMAC_MDIO_MODE_CLOCK_CNT);
 	if (USES_WARPCORE(bp))
-		mode |= (74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
+		clc_cnt = 74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT;
 	else
-		mode |= (49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
+		clc_cnt = 49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT;
 
-	mode |= (EMAC_MDIO_MODE_CLAUSE_45);
-	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE, mode);
+	if (((cur_mode & EMAC_MDIO_MODE_CLOCK_CNT) == clc_cnt) &&
+	    (cur_mode & (EMAC_MDIO_MODE_CLAUSE_45)))
+		return;
 
+	new_mode = cur_mode &
+		~(EMAC_MDIO_MODE_AUTO_POLL | EMAC_MDIO_MODE_CLOCK_CNT);
+	new_mode |= clc_cnt;
+	new_mode |= (EMAC_MDIO_MODE_CLAUSE_45);
+
+	DP(NETIF_MSG_LINK, "Changing emac_mode from 0x%x to 0x%x\n",
+	   cur_mode, new_mode);
+	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE, new_mode);
 	udelay(40);
 }
+
+static void bnx2x_set_mdio_emac_per_phy(struct bnx2x *bp,
+					struct link_params *params)
+{
+	u8 phy_index;
+	/* Set mdio clock per phy */
+	for (phy_index = INT_PHY; phy_index < params->num_phys;
+	      phy_index++)
+		bnx2x_set_mdio_clk(bp, params->chip_id,
+				   params->phy[phy_index].mdio_ctrl);
+}
+
 static u8 bnx2x_is_4_port_mode(struct bnx2x *bp)
 {
 	u32 port4mode_ovwr_val;
@@ -1508,7 +1526,8 @@ static void bnx2x_emac_init(struct link_params *params,
 		}
 		timeout--;
 	} while (val & EMAC_MODE_RESET);
-	bnx2x_set_mdio_clk(bp, params->chip_id, port);
+
+	bnx2x_set_mdio_emac_per_phy(bp, params);
 	/* Set mac address */
 	val = ((params->mac_addr[0] << 8) |
 		params->mac_addr[1]);
@@ -1664,7 +1683,10 @@ static void bnx2x_xmac_init(struct link_params *params, u32 max_speed)
 	 * ports of the path
 	 */
 
-	if ((CHIP_NUM(bp) == CHIP_NUM_57840_4_10) &&
+	if (((CHIP_NUM(bp) == CHIP_NUM_57840_4_10) ||
+	     (CHIP_NUM(bp) == CHIP_NUM_57840_2_20) ||
+	     (CHIP_NUM(bp) == CHIP_NUM_57840_OBSOLETE)) &&
+	    is_port4mode &&
 	    (REG_RD(bp, MISC_REG_RESET_REG_2) &
 	     MISC_REGISTERS_RESET_REG_2_XMAC)) {
 		DP(NETIF_MSG_LINK,
@@ -1760,6 +1782,18 @@ static int bnx2x_xmac_enable(struct link_params *params,
 	 */
 	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 0);
 
+	/* When XMAC is in XLGMII mode, disable sending idles for fault
+	 * detection.
+	 */
+	if (!(params->phy[INT_PHY].flags & FLAGS_TX_ERROR_CHECK)) {
+		REG_WR(bp, xmac_base + XMAC_REG_RX_LSS_CTRL,
+		       (XMAC_RX_LSS_CTRL_REG_LOCAL_FAULT_DISABLE |
+			XMAC_RX_LSS_CTRL_REG_REMOTE_FAULT_DISABLE));
+		REG_WR(bp, xmac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, 0);
+		REG_WR(bp, xmac_base + XMAC_REG_CLEAR_RX_LSS_STATUS,
+		       XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS |
+		       XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS);
+	}
 	/* Set Max packet size */
 	REG_WR(bp, xmac_base + XMAC_REG_RX_MAX_SIZE, 0x2710);
 
@@ -1780,6 +1814,12 @@ static int bnx2x_xmac_enable(struct link_params *params,
 	/* Enable TX and RX */
 	val = XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN;
 
+	/* Set MAC in XLGMII mode for dual-mode */
+	if ((vars->line_speed == SPEED_20000) &&
+	    (params->phy[INT_PHY].supported &
+	     SUPPORTED_20000baseKR2_Full))
+		val |= XMAC_CTRL_REG_XLGMII_ALIGN_ENB;
+
 	/* Check loopback mode */
 	if (lb)
 		val |= XMAC_CTRL_REG_LINE_LOCAL_LPBK;
@@ -2096,6 +2136,16 @@ static void bnx2x_update_mng(struct link_params *params, u32 link_status)
 			port_mb[params->port].link_status), link_status);
 }
 
+static void bnx2x_update_link_attr(struct link_params *params, u32 link_attr)
+{
+	struct bnx2x *bp = params->bp;
+
+	if (SHMEM2_HAS(bp, link_attr_sync))
+		REG_WR(bp, params->shmem2_base +
+		       offsetof(struct shmem2_region,
+				link_attr_sync[params->port]), link_attr);
+}
+
 static void bnx2x_update_pfc_nig(struct link_params *params,
 		struct link_vars *vars,
 		struct bnx2x_nig_brb_pfc_port_params *nig_params)
@@ -2126,7 +2176,7 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
 		if (CHIP_IS_E3(bp))
 			ppp_enable = 0;
 		else
-		ppp_enable = 1;
+			ppp_enable = 1;
 		xcm_mask &= ~(port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
 				     NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
 		xcm_out_en = 0;
@@ -2247,7 +2297,6 @@ int bnx2x_update_pfc(struct link_params *params,
 	return bnx2x_status;
 }
 
-
 static int bnx2x_bmac1_enable(struct link_params *params,
 			      struct link_vars *vars,
 			      u8 is_lb)
@@ -2651,6 +2700,13 @@ static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
 	u32 val;
 	u16 i;
 	int rc = 0;
+	u32 chip_id;
+	if (phy->flags & FLAGS_MDC_MDIO_WA_G) {
+		chip_id = (REG_RD(bp, MISC_REG_CHIP_NUM) << 16) |
+			  ((REG_RD(bp, MISC_REG_CHIP_REV) & 0xf) << 12);
+		bnx2x_set_mdio_clk(bp, chip_id, phy->mdio_ctrl);
+	}
+
 	if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
 		bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
 			      EMAC_MDIO_STATUS_10MB);
@@ -2719,6 +2775,13 @@ static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
 	u32 tmp;
 	u8 i;
 	int rc = 0;
+	u32 chip_id;
+	if (phy->flags & FLAGS_MDC_MDIO_WA_G) {
+		chip_id = (REG_RD(bp, MISC_REG_CHIP_NUM) << 16) |
+			  ((REG_RD(bp, MISC_REG_CHIP_REV) & 0xf) << 12);
+		bnx2x_set_mdio_clk(bp, chip_id, phy->mdio_ctrl);
+	}
+
 	if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
 		bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
 			      EMAC_MDIO_STATUS_10MB);
@@ -3147,6 +3210,15 @@ static void bnx2x_cl45_read_or_write(struct bnx2x *bp, struct bnx2x_phy *phy,
 	bnx2x_cl45_write(bp, phy, devad, reg, val | or_val);
 }
 
+static void bnx2x_cl45_read_and_write(struct bnx2x *bp,
+				      struct bnx2x_phy *phy,
+				      u8 devad, u16 reg, u16 and_val)
+{
+	u16 val;
+	bnx2x_cl45_read(bp, phy, devad, reg, &val);
+	bnx2x_cl45_write(bp, phy, devad, reg, val & and_val);
+}
+
 int bnx2x_phy_read(struct link_params *params, u8 phy_addr,
 		   u8 devad, u16 reg, u16 *ret_val)
 {
@@ -3551,6 +3623,44 @@ static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
  * init configuration, and set/clear SGMII flag. Internal
  * phy init is done purely in phy_init stage.
  */
+static void bnx2x_warpcore_enable_AN_KR2(struct bnx2x_phy *phy,
+					 struct link_params *params,
+					 struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u16 i;
+	static struct bnx2x_reg_set reg_set[] = {
+		/* Step 1 - Program the TX/RX alignment markers */
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0xa157},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xcbe2},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0x7537},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0xa157},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xcbe2},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0x7537},
+		/* Step 2 - Configure the NP registers */
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000a},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6400},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0620},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0157},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x6464},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x3150},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x3150},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0157},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0620}
+	};
+	DP(NETIF_MSG_LINK, "Enabling 20G-KR2\n");
+
+	bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+				 MDIO_WC_REG_CL49_USERB0_CTRL, (3<<6));
+
+	for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++)
+		bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
+				 reg_set[i].val);
+
+	/* Start KR2 work-around timer which handles BCM8073 link-parner */
+	vars->link_attr_sync |= LINK_ATTR_SYNC_KR2_ENABLE;
+	bnx2x_update_link_attr(params, vars->link_attr_sync);
+}
 
 static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
 					       struct link_params *params)
@@ -3564,6 +3674,21 @@ static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
 				 MDIO_WC_REG_DIGITAL4_MISC5, 0xc000);
 }
 
+static void bnx2x_warpcore_restart_AN_KR(struct bnx2x_phy *phy,
+					 struct link_params *params)
+{
+	/* Restart autoneg on the leading lane only */
+	struct bnx2x *bp = params->bp;
+	u16 lane = bnx2x_get_warpcore_lane(phy, params);
+	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+			  MDIO_AER_BLOCK_AER_REG, lane);
+	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200);
+
+	/* Restore AER */
+	bnx2x_set_aer_mmd(params, phy);
+}
+
 static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 					struct link_params *params,
 					struct link_vars *vars) {
@@ -3576,7 +3701,9 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 		{MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415},
 		{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190},
 		/* Disable Autoneg: re-enable it after adv is done. */
-		{MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0}
+		{MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0},
+		{MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_KR_CONTROL, 0x2},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP, 0},
 	};
 	DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n");
 	/* Set to default registers that may be overriden by 10G force */
@@ -3585,11 +3712,11 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 				 reg_set[i].val);
 
 	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-		MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl);
-	cl72_ctrl &= 0xf8ff;
+			MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl);
+	cl72_ctrl &= 0x08ff;
 	cl72_ctrl |= 0x3800;
 	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-		MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl);
+			 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl);
 
 	/* Check adding advertisement for 1G KX */
 	if (((vars->line_speed == SPEED_AUTO_NEG) &&
@@ -3624,6 +3751,16 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 		     ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
 		      (0x06 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
 		      (0x09 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
+	/* Configure the next lane if dual mode */
+	if (phy->flags & FLAGS_WC_DUAL_MODE)
+		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+				 MDIO_WC_REG_TX0_TX_DRIVER + 0x10*(lane+1),
+				 ((0x02 <<
+				 MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+				  (0x06 <<
+				   MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
+				  (0x09 <<
+				MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
 	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
 			 MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL,
 			 0x03f0);
@@ -3670,10 +3807,26 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
 			MDIO_WC_REG_DIGITAL3_UP1, 0x1f);
 
-	/* Enable Autoneg */
-	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
-			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200);
+	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+	     (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) ||
+	    (phy->req_line_speed == SPEED_20000)) {
+
+		CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+				  MDIO_AER_BLOCK_AER_REG, lane);
+
+		bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+					 MDIO_WC_REG_RX1_PCI_CTRL + (0x10*lane),
+					 (1<<11));
+
+		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+				 MDIO_WC_REG_XGXS_X2_CONTROL3, 0x7);
+		bnx2x_set_aer_mmd(params, phy);
+
+		bnx2x_warpcore_enable_AN_KR2(phy, params, vars);
+	}
 
+	/* Enable Autoneg: only on the main lane */
+	bnx2x_warpcore_restart_AN_KR(phy, params);
 }
 
 static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
@@ -3692,9 +3845,7 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
 		{MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1},
 		{MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa},
 		/* Leave cl72 training enable, needed for KR */
-		{MDIO_PMA_DEVAD,
-		MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150,
-		0x2}
+		{MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_KR_CONTROL, 0x2}
 	};
 
 	for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++)
@@ -3764,27 +3915,21 @@ static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy,
 	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0);
 
 	/* Disable 100FX Enable and Auto-Detect */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_FX100_CTRL1, &val);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_FX100_CTRL1, (val & 0xFFFA));
+	bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+				  MDIO_WC_REG_FX100_CTRL1, 0xFFFA);
 
 	/* Disable 100FX Idle detect */
 	bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
 				 MDIO_WC_REG_FX100_CTRL3, 0x0080);
 
 	/* Set Block address to Remote PHY & Clear forced_speed[5] */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_DIGITAL4_MISC3, &val);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_DIGITAL4_MISC3, (val & 0xFF7F));
+	bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+				  MDIO_WC_REG_DIGITAL4_MISC3, 0xFF7F);
 
 	/* Turn off auto-detect & fiber mode */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &val);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
-			 (val & 0xFFEE));
+	bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+				  MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
+				  0xFFEE);
 
 	/* Set filter_force_link, disable_false_link and parallel_detect */
 	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
@@ -3846,22 +3991,65 @@ static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy,
 			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x100);
 
 	/* Release tx_fifo_reset */
+	bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+				  MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3,
+				  0xFFFE);
+	/* Release rxSeqStart */
+	bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+				  MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, 0x7FFF);
+}
+
+static void bnx2x_warpcore_set_20G_force_KR2(struct bnx2x_phy *phy,
+					     struct link_params *params)
+{
+	u16 val;
+	struct bnx2x *bp = params->bp;
+	/* Set global registers, so set AER lane to 0 */
+	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+			  MDIO_AER_BLOCK_AER_REG, 0);
+
+	/* Disable sequencer */
+	bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+				  MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, ~(1<<13));
+
+	bnx2x_set_aer_mmd(params, phy);
+
+	bnx2x_cl45_read_and_write(bp, phy, MDIO_PMA_DEVAD,
+				  MDIO_WC_REG_PMD_KR_CONTROL, ~(1<<1));
+	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+			 MDIO_AN_REG_CTRL, 0);
+	/* Turn off CL73 */
 	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, &val);
+			MDIO_WC_REG_CL73_USERB0_CTRL, &val);
+	val &= ~(1<<5);
+	val |= (1<<6);
 	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, val & 0xFFFE);
+			 MDIO_WC_REG_CL73_USERB0_CTRL, val);
+
+	/* Set 20G KR2 force speed */
+	bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+				 MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x1f);
+
+	bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+				 MDIO_WC_REG_DIGITAL4_MISC3, (1<<7));
 
-	/* Release rxSeqStart */
 	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, &val);
+			MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &val);
+	val &= ~(3<<14);
+	val |= (1<<15);
 	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, (val & 0x7FFF));
-}
+			 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, val);
+	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+			 MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP, 0x835A);
 
-static void bnx2x_warpcore_set_20G_KR2(struct bnx2x *bp,
-				       struct bnx2x_phy *phy)
-{
-	DP(NETIF_MSG_LINK, "KR2 still not supported !!!\n");
+	/* Enable sequencer (over lane 0) */
+	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+			  MDIO_AER_BLOCK_AER_REG, 0);
+
+	bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+				 MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, (1<<13));
+
+	bnx2x_set_aer_mmd(params, phy);
 }
 
 static void bnx2x_warpcore_set_20G_DXGXS(struct bnx2x *bp,
@@ -3931,20 +4119,16 @@ static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
 	u16 val16, digctrl_kx1, digctrl_kx2;
 
 	/* Clear XFI clock comp in non-10G single lane mode. */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_RX66_CONTROL, &val16);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_RX66_CONTROL, val16 & ~(3<<13));
+	bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+				  MDIO_WC_REG_RX66_CONTROL, ~(3<<13));
 
 	bnx2x_warpcore_set_lpi_passthrough(phy, params);
 
 	if (always_autoneg || phy->req_line_speed == SPEED_AUTO_NEG) {
 		/* SGMII Autoneg */
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
-		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-				 MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
-				 val16 | 0x1000);
+		bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+					 MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
+					 0x1000);
 		DP(NETIF_MSG_LINK, "set SGMII AUTONEG\n");
 	} else {
 		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
@@ -4086,7 +4270,7 @@ static int bnx2x_get_mod_abs_int_cfg(struct bnx2x *bp,
 		if ((cfg_pin < PIN_CFG_GPIO0_P0) ||
 		    (cfg_pin > PIN_CFG_GPIO3_P1)) {
 			DP(NETIF_MSG_LINK,
-			   "ERROR: Invalid cfg pin %x for module detect indication\n",
+			   "No cfg pin %x for module detect indication\n",
 			   cfg_pin);
 			return -EINVAL;
 		}
@@ -4097,7 +4281,7 @@ static int bnx2x_get_mod_abs_int_cfg(struct bnx2x *bp,
 		*gpio_num = MISC_REGISTERS_GPIO_3;
 		*gpio_port = port;
 	}
-	DP(NETIF_MSG_LINK, "MOD_ABS int GPIO%d_P%d\n", *gpio_num, *gpio_port);
+
 	return 0;
 }
 
@@ -4120,7 +4304,7 @@ static int bnx2x_is_sfp_module_plugged(struct bnx2x_phy *phy,
 		return 0;
 }
 static int bnx2x_warpcore_get_sigdet(struct bnx2x_phy *phy,
-					struct link_params *params)
+				     struct link_params *params)
 {
 	u16 gp2_status_reg0, lane;
 	struct bnx2x *bp = params->bp;
@@ -4134,8 +4318,8 @@ static int bnx2x_warpcore_get_sigdet(struct bnx2x_phy *phy,
 }
 
 static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
-				       struct link_params *params,
-				       struct link_vars *vars)
+					  struct link_params *params,
+					  struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	u32 serdes_net_if;
@@ -4163,7 +4347,7 @@ static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
 		case PORT_HW_CFG_NET_SERDES_IF_KR:
 			/* Do we get link yet? */
 			bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, 0x81d1,
-								&gp_status1);
+					&gp_status1);
 			lnkup = (gp_status1 >> (8+lane)) & 0x1;/* 1G */
 				/*10G KR*/
 			lnkup_kr = (gp_status1 >> (12+lane)) & 0x1;
@@ -4215,6 +4399,27 @@ static void bnx2x_warpcore_config_sfi(struct bnx2x_phy *phy,
 	}
 }
 
+static void bnx2x_sfp_e3_set_transmitter(struct link_params *params,
+					 struct bnx2x_phy *phy,
+					 u8 tx_en)
+{
+	struct bnx2x *bp = params->bp;
+	u32 cfg_pin;
+	u8 port = params->port;
+
+	cfg_pin = REG_RD(bp, params->shmem_base +
+			 offsetof(struct shmem_region,
+				  dev_info.port_hw_config[port].e3_sfp_ctrl)) &
+		PORT_HW_CFG_E3_TX_LASER_MASK;
+	/* Set the !tx_en since this pin is DISABLE_TX_LASER */
+	DP(NETIF_MSG_LINK, "Setting WC TX to %d\n", tx_en);
+
+	/* For 20G, the expected pin to be used is 3 pins after the current */
+	bnx2x_set_cfg_pin(bp, cfg_pin, tx_en ^ 1);
+	if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)
+		bnx2x_set_cfg_pin(bp, cfg_pin + 3, tx_en ^ 1);
+}
+
 static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
 				       struct link_params *params,
 				       struct link_vars *vars)
@@ -4275,9 +4480,14 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
 			break;
 
 		case PORT_HW_CFG_NET_SERDES_IF_SFI:
-			/* Issue Module detection */
+			/* Issue Module detection if module is plugged, or
+			 * enabled transmitter to avoid current leakage in case
+			 * no module is connected
+			 */
 			if (bnx2x_is_sfp_module_plugged(phy, params))
 				bnx2x_sfp_module_detection(phy, params);
+			else
+				bnx2x_sfp_e3_set_transmitter(params, phy, 1);
 
 			bnx2x_warpcore_config_sfi(phy, params);
 			break;
@@ -4293,16 +4503,14 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
 
 			bnx2x_sfp_module_detection(phy, params);
 			break;
-
 		case PORT_HW_CFG_NET_SERDES_IF_KR2:
-			if (vars->line_speed != SPEED_20000) {
-				DP(NETIF_MSG_LINK, "Speed not supported yet\n");
-				return;
+			if (!params->loopback_mode) {
+				bnx2x_warpcore_enable_AN_KR(phy, params, vars);
+			} else {
+				DP(NETIF_MSG_LINK, "Setting KR 20G-Force\n");
+				bnx2x_warpcore_set_20G_force_KR2(phy, params);
 			}
-			DP(NETIF_MSG_LINK, "Setting 20G KR2\n");
-			bnx2x_warpcore_set_20G_KR2(bp, phy);
 			break;
-
 		default:
 			DP(NETIF_MSG_LINK,
 			   "Unsupported Serdes Net Interface 0x%x\n",
@@ -4316,68 +4524,35 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
 	DP(NETIF_MSG_LINK, "Exit config init\n");
 }
 
-static void bnx2x_sfp_e3_set_transmitter(struct link_params *params,
-					 struct bnx2x_phy *phy,
-					 u8 tx_en)
-{
-	struct bnx2x *bp = params->bp;
-	u32 cfg_pin;
-	u8 port = params->port;
-
-	cfg_pin = REG_RD(bp, params->shmem_base +
-				offsetof(struct shmem_region,
-				dev_info.port_hw_config[port].e3_sfp_ctrl)) &
-				PORT_HW_CFG_TX_LASER_MASK;
-	/* Set the !tx_en since this pin is DISABLE_TX_LASER */
-	DP(NETIF_MSG_LINK, "Setting WC TX to %d\n", tx_en);
-	/* For 20G, the expected pin to be used is 3 pins after the current */
-
-	bnx2x_set_cfg_pin(bp, cfg_pin, tx_en ^ 1);
-	if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)
-		bnx2x_set_cfg_pin(bp, cfg_pin + 3, tx_en ^ 1);
-}
-
 static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
 				      struct link_params *params)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val16, lane;
 	bnx2x_sfp_e3_set_transmitter(params, phy, 0);
-	bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
+	bnx2x_set_mdio_emac_per_phy(bp, params);
 	bnx2x_set_aer_mmd(params, phy);
 	/* Global register */
 	bnx2x_warpcore_reset_lane(bp, phy, 1);
 
 	/* Clear loopback settings (if any) */
 	/* 10G & 20G */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 &
-			 0xBFFF);
+	bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+				  MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0xBFFF);
 
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_IEEE0BLK_MIICNTL, &val16);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_IEEE0BLK_MIICNTL, val16 & 0xfffe);
+	bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+				  MDIO_WC_REG_IEEE0BLK_MIICNTL, 0xfffe);
 
 	/* Update those 1-copy registers */
 	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
 			  MDIO_AER_BLOCK_AER_REG, 0);
 	/* Enable 1G MDIO (1-copy) */
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
-			&val16);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
-			 val16 & ~0x10);
-
-	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-			MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
-	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-			 MDIO_WC_REG_XGXSBLK1_LANECTRL2,
-			 val16 & 0xff00);
+	bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+				  MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
+				  ~0x10);
 
+	bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+				  MDIO_WC_REG_XGXSBLK1_LANECTRL2, 0xff00);
 	lane = bnx2x_get_warpcore_lane(phy, params);
 	/* Disable CL36 PCS Tx */
 	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
@@ -4413,8 +4588,9 @@ static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
 	DP(NETIF_MSG_LINK, "Setting Warpcore loopback type %x, speed %d\n",
 		       params->loopback_mode, phy->req_line_speed);
 
-	if (phy->req_line_speed < SPEED_10000) {
-		/* 10/100/1000 */
+	if (phy->req_line_speed < SPEED_10000 ||
+	    phy->supported & SUPPORTED_20000baseKR2_Full) {
+		/* 10/100/1000/20G-KR2 */
 
 		/* Update those 1-copy registers */
 		CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
@@ -4427,18 +4603,20 @@ static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
 		lane = bnx2x_get_warpcore_lane(phy, params);
 		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
 				MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
+		val16 |= (1<<lane);
+		if (phy->flags & FLAGS_WC_DUAL_MODE)
+			val16 |= (2<<lane);
 		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_XGXSBLK1_LANECTRL2,
-				val16 | (1<<lane));
+				 MDIO_WC_REG_XGXSBLK1_LANECTRL2,
+				 val16);
 
 		/* Switch back to 4-copy registers */
 		bnx2x_set_aer_mmd(params, phy);
 	} else {
-		/* 10G & 20G */
+		/* 10G / 20G-DXGXS */
 		bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
 					 MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
 					 0x4000);
-
 		bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
 					 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1);
 	}
@@ -4603,6 +4781,10 @@ void bnx2x_link_status_update(struct link_params *params,
 		params->feature_config_flags &=
 					~FEATURE_CONFIG_PFC_ENABLED;
 
+	if (SHMEM2_HAS(bp, link_attr_sync))
+		vars->link_attr_sync = SHMEM2_RD(bp,
+						 link_attr_sync[params->port]);
+
 	DP(NETIF_MSG_LINK, "link_status 0x%x  phy_link_up %x int_mask 0x%x\n",
 		 vars->link_status, vars->phy_link_up, vars->aeu_int_mask);
 	DP(NETIF_MSG_LINK, "line_speed %x  duplex %x  flow_ctrl 0x%x\n",
@@ -5332,6 +5514,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
 			vars->link_status |= LINK_10GTFD;
 			break;
 		case GP_STATUS_20G_DXGXS:
+		case GP_STATUS_20G_KR2:
 			vars->line_speed = SPEED_20000;
 			vars->link_status |= LINK_20GTFD;
 			break;
@@ -5439,7 +5622,15 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
 	int rc = 0;
 	lane = bnx2x_get_warpcore_lane(phy, params);
 	/* Read gp_status */
-	if (phy->req_line_speed > SPEED_10000) {
+	if ((params->loopback_mode) &&
+	    (phy->flags & FLAGS_WC_DUAL_MODE)) {
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_DIGITAL5_LINK_STATUS, &link_up);
+		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+				MDIO_WC_REG_DIGITAL5_LINK_STATUS, &link_up);
+		link_up &= 0x1;
+	} else if ((phy->req_line_speed > SPEED_10000) &&
+		(phy->supported & SUPPORTED_20000baseMLD2_Full)) {
 		u16 temp_link_up;
 		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
 				1, &temp_link_up);
@@ -5452,12 +5643,22 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
 			bnx2x_ext_phy_resolve_fc(phy, params, vars);
 	} else {
 		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_GP2_STATUS_GP_2_1, &gp_status1);
+				MDIO_WC_REG_GP2_STATUS_GP_2_1,
+				&gp_status1);
 		DP(NETIF_MSG_LINK, "0x81d1 = 0x%x\n", gp_status1);
-		/* Check for either KR or generic link up. */
-		gp_status1 = ((gp_status1 >> 8) & 0xf) |
-			((gp_status1 >> 12) & 0xf);
-		link_up = gp_status1 & (1 << lane);
+		/* Check for either KR, 1G, or AN up. */
+		link_up = ((gp_status1 >> 8) |
+			   (gp_status1 >> 12) |
+			   (gp_status1)) &
+			(1 << lane);
+		if (phy->supported & SUPPORTED_20000baseKR2_Full) {
+			u16 an_link;
+			bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+					MDIO_AN_REG_STATUS, &an_link);
+			bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+					MDIO_AN_REG_STATUS, &an_link);
+			link_up |= (an_link & (1<<2));
+		}
 		if (link_up && SINGLE_MEDIA_DIRECT(params)) {
 			u16 pd, gp_status4;
 			if (phy->req_line_speed == SPEED_AUTO_NEG) {
@@ -5522,7 +5723,7 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
 	if ((lane & 1) == 0)
 		gp_speed <<= 8;
 	gp_speed &= 0x3f00;
-
+	link_up = !!link_up;
 
 	rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, gp_speed,
 					 duplex);
@@ -6683,7 +6884,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 		} else if (prev_line_speed != vars->line_speed) {
 			REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4,
 			       0);
-			 usleep_range(1000, 2000);
+			usleep_range(1000, 2000);
 		}
 	}
 
@@ -6753,7 +6954,7 @@ void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port)
 {
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
 		       MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
-	 usleep_range(1000, 2000);
+	usleep_range(1000, 2000);
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
 		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
 }
@@ -6894,7 +7095,7 @@ static int bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
 				MDIO_PMA_DEVAD,
 				MDIO_PMA_REG_M8051_MSGOUT_REG, &fw_msgout);
 
-		 usleep_range(1000, 2000);
+		usleep_range(1000, 2000);
 	} while (fw_ver1 == 0 || fw_ver1 == 0x4321 ||
 			((fw_msgout & 0xff) != 0x03 && (phy->type ==
 			PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)));
@@ -7604,13 +7805,12 @@ static int bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
 		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
 			return 0;
-		 usleep_range(1000, 2000);
+		usleep_range(1000, 2000);
 	}
 	return -EINVAL;
 }
 
 static void bnx2x_warpcore_power_module(struct link_params *params,
-					struct bnx2x_phy *phy,
 					u8 power)
 {
 	u32 pin_cfg;
@@ -7652,10 +7852,10 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 	addr32 = addr & (~0x3);
 	do {
 		if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) {
-			bnx2x_warpcore_power_module(params, phy, 0);
+			bnx2x_warpcore_power_module(params, 0);
 			/* Note that 100us are not enough here */
 			usleep_range(1000, 2000);
-			bnx2x_warpcore_power_module(params, phy, 1);
+			bnx2x_warpcore_power_module(params, 1);
 		}
 		rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt,
 				    data_array);
@@ -7715,7 +7915,7 @@ static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 	/* Wait appropriate time for two-wire command to finish before
 	 * polling the status register
 	 */
-	 usleep_range(1000, 2000);
+	usleep_range(1000, 2000);
 
 	/* Wait up to 500us for command complete status */
 	for (i = 0; i < 100; i++) {
@@ -7751,7 +7951,7 @@ static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
 		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
 			return 0;
-		 usleep_range(1000, 2000);
+		usleep_range(1000, 2000);
 	}
 
 	return -EINVAL;
@@ -7786,9 +7986,8 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
 {
 	struct bnx2x *bp = params->bp;
 	u32 sync_offset = 0, phy_idx, media_types;
-	u8 val[2], check_limiting_mode = 0;
+	u8 gport, val[2], check_limiting_mode = 0;
 	*edc_mode = EDC_MODE_LIMITING;
-
 	phy->media_type = ETH_PHY_UNSPECIFIED;
 	/* First check for copper cable */
 	if (bnx2x_read_sfp_module_eeprom(phy,
@@ -7843,8 +8042,15 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
 			       SFP_EEPROM_COMP_CODE_LR_MASK |
 			       SFP_EEPROM_COMP_CODE_LRM_MASK)) == 0) {
 			DP(NETIF_MSG_LINK, "1G Optic module detected\n");
+			gport = params->port;
 			phy->media_type = ETH_PHY_SFP_1G_FIBER;
 			phy->req_line_speed = SPEED_1000;
+			if (!CHIP_IS_E1x(bp))
+				gport = BP_PATH(bp) + (params->port << 1);
+			netdev_err(bp->dev, "Warning: Link speed was forced to 1000Mbps."
+			      " Current SFP module in port %d is not"
+			      " compliant with 10G Ethernet\n",
+			 gport);
 		} else {
 			int idx, cfg_idx = 0;
 			DP(NETIF_MSG_LINK, "10G Optic module detected\n");
@@ -8241,7 +8447,7 @@ static void bnx2x_warpcore_hw_reset(struct bnx2x_phy *phy,
 				    struct link_params *params)
 {
 	struct bnx2x *bp = params->bp;
-	bnx2x_warpcore_power_module(params, phy, 0);
+	bnx2x_warpcore_power_module(params, 0);
 	/* Put Warpcore in low power mode */
 	REG_WR(bp, MISC_REG_WC0_RESET, 0x0c0e);
 
@@ -8264,7 +8470,7 @@ static void bnx2x_power_sfp_module(struct link_params *params,
 		bnx2x_8727_power_module(params->bp, phy, power);
 		break;
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-		bnx2x_warpcore_power_module(params, phy, power);
+		bnx2x_warpcore_power_module(params, power);
 		break;
 	default:
 		break;
@@ -8337,7 +8543,8 @@ int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
 	u32 val = REG_RD(bp, params->shmem_base +
 			     offsetof(struct shmem_region, dev_info.
 				     port_feature_config[params->port].config));
-
+	/* Enabled transmitter by default */
+	bnx2x_sfp_set_transmitter(params, phy, 1);
 	DP(NETIF_MSG_LINK, "SFP+ module plugged in/out detected on port %d\n",
 		 params->port);
 	/* Power up module */
@@ -8370,14 +8577,12 @@ int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
 	 */
 	bnx2x_set_limiting_mode(params, phy, edc_mode);
 
-	/* Enable transmit for this module if the module is approved, or
-	 * if unapproved modules should also enable the Tx laser
+	/* Disable transmit for this module if the module is not approved, and
+	 * laser needs to be disabled.
 	 */
-	if (rc == 0 ||
-	    (val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
-	    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-		bnx2x_sfp_set_transmitter(params, phy, 1);
-	else
+	if ((rc) &&
+	    ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
+	     PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER))
 		bnx2x_sfp_set_transmitter(params, phy, 0);
 
 	return rc;
@@ -8389,11 +8594,13 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
 	struct bnx2x_phy *phy;
 	u32 gpio_val;
 	u8 gpio_num, gpio_port;
-	if (CHIP_IS_E3(bp))
+	if (CHIP_IS_E3(bp)) {
 		phy = &params->phy[INT_PHY];
-	else
+		/* Always enable TX laser,will be disabled in case of fault */
+		bnx2x_sfp_set_transmitter(params, phy, 1);
+	} else {
 		phy = &params->phy[EXT_PHY1];
-
+	}
 	if (bnx2x_get_mod_abs_int_cfg(bp, params->chip_id, params->shmem_base,
 				      params->port, &gpio_num, &gpio_port) ==
 	    -EINVAL) {
@@ -8409,7 +8616,7 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
 
 	/* Call the handling function in case module is detected */
 	if (gpio_val == 0) {
-		bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
+		bnx2x_set_mdio_emac_per_phy(bp, params);
 		bnx2x_set_aer_mmd(params, phy);
 
 		bnx2x_power_sfp_module(params, phy, 1);
@@ -8438,10 +8645,6 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
 			DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
 		}
 	} else {
-		u32 val = REG_RD(bp, params->shmem_base +
-				 offsetof(struct shmem_region, dev_info.
-					  port_feature_config[params->port].
-					  config));
 		bnx2x_set_gpio_int(bp, gpio_num,
 				   MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
 				   gpio_port);
@@ -8449,10 +8652,6 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
 		 * Disable transmit for this module
 		 */
 		phy->media_type = ETH_PHY_NOT_PRESENT;
-		if (((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
-		     PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) ||
-		    CHIP_IS_E3(bp))
-			bnx2x_sfp_set_transmitter(params, phy, 0);
 	}
 }
 
@@ -9192,6 +9391,7 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
 			bnx2x_cl45_read(bp, phy,
 				MDIO_PMA_DEVAD,
 				MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
+			bnx2x_8727_power_module(params->bp, phy, 0);
 			return 0;
 		}
 	} /* Over current check */
@@ -9296,20 +9496,28 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
 					    struct bnx2x *bp,
 					    u8 port)
 {
-	u16 val, fw_ver1, fw_ver2, cnt;
+	u16 val, fw_ver2, cnt, i;
+	static struct bnx2x_reg_set reg_set[] = {
+		{MDIO_PMA_DEVAD, 0xA819, 0x0014},
+		{MDIO_PMA_DEVAD, 0xA81A, 0xc200},
+		{MDIO_PMA_DEVAD, 0xA81B, 0x0000},
+		{MDIO_PMA_DEVAD, 0xA81C, 0x0300},
+		{MDIO_PMA_DEVAD, 0xA817, 0x0009}
+	};
+	u16 fw_ver1;
 
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+	if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+	    (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
 		bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, 0x400f, &fw_ver1);
 		bnx2x_save_spirom_version(bp, port, fw_ver1 & 0xfff,
 				phy->ver_addr);
 	} else {
 		/* For 32-bit registers in 848xx, access via MDIO2ARM i/f. */
 		/* (1) set reg 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
-		bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014);
-		bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
-		bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000);
-		bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300);
-		bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009);
+		for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set);
+		      i++)
+			bnx2x_cl45_write(bp, phy, reg_set[i].devad,
+					 reg_set[i].reg, reg_set[i].val);
 
 		for (cnt = 0; cnt < 100; cnt++) {
 			bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
@@ -9357,8 +9565,16 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
 static void bnx2x_848xx_set_led(struct bnx2x *bp,
 				struct bnx2x_phy *phy)
 {
-	u16 val, offset;
-
+	u16 val, offset, i;
+	static struct bnx2x_reg_set reg_set[] = {
+		{MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x0080},
+		{MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED2_MASK, 0x0018},
+		{MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_MASK, 0x0006},
+		{MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_BLINK, 0x0000},
+		{MDIO_PMA_DEVAD, MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH,
+			MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ},
+		{MDIO_AN_DEVAD, 0xFFFB, 0xFFFD}
+	};
 	/* PHYC_CTL_LED_CTL */
 	bnx2x_cl45_read(bp, phy,
 			MDIO_PMA_DEVAD,
@@ -9370,49 +9586,20 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp,
 			 MDIO_PMA_DEVAD,
 			 MDIO_PMA_REG_8481_LINK_SIGNAL, val);
 
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LED1_MASK,
-			 0x80);
-
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LED2_MASK,
-			 0x18);
-
-	/* Select activity source by Tx and Rx, as suggested by PHY AE */
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LED3_MASK,
-			 0x0006);
-
-	/* Select the closest activity blink rate to that in 10/100/1000 */
-	bnx2x_cl45_write(bp, phy,
-			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_8481_LED3_BLINK,
-			0);
-
-	/* Configure the blink rate to ~15.9 Hz */
-	bnx2x_cl45_write(bp, phy,
-			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH,
-			MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ);
+	for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++)
+		bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
+				 reg_set[i].val);
 
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+	if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+	    (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834))
 		offset = MDIO_PMA_REG_84833_CTL_LED_CTL_1;
 	else
 		offset = MDIO_PMA_REG_84823_CTL_LED_CTL_1;
 
-	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, offset, &val);
-	val |= MDIO_PMA_REG_84823_LED3_STRETCH_EN; /* stretch_en for LED3*/
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD, offset, val);
-
-	/* 'Interrupt Mask' */
-	bnx2x_cl45_write(bp, phy,
-			 MDIO_AN_DEVAD,
-			 0xFFFB, 0xFFFD);
+	/* stretch_en for LED3*/
+	bnx2x_cl45_read_or_write(bp, phy,
+				 MDIO_PMA_DEVAD, offset,
+				 MDIO_PMA_REG_84823_LED3_STRETCH_EN);
 }
 
 static void bnx2x_848xx_specific_func(struct bnx2x_phy *phy,
@@ -9422,7 +9609,8 @@ static void bnx2x_848xx_specific_func(struct bnx2x_phy *phy,
 	struct bnx2x *bp = params->bp;
 	switch (action) {
 	case PHY_INIT:
-		if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+		if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
+		    (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
 			/* Save spirom version */
 			bnx2x_save_848xx_spirom_version(phy, bp, params->port);
 		}
@@ -9443,7 +9631,7 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
 				       struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
-	u16 autoneg_val, an_1000_val, an_10_100_val, an_10g_val;
+	u16 autoneg_val, an_1000_val, an_10_100_val;
 
 	bnx2x_848xx_specific_func(phy, params, PHY_INIT);
 	bnx2x_cl45_write(bp, phy,
@@ -9542,11 +9730,12 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
 	if (phy->req_duplex == DUPLEX_FULL)
 		autoneg_val |= (1<<8);
 
-	/* Always write this if this is not 84833.
-	 * For 84833, write it only when it's a forced speed.
+	/* Always write this if this is not 84833/4.
+	 * For 84833/4, write it only when it's a forced speed.
 	 */
-	if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
-		((autoneg_val & (1<<12)) == 0))
+	if (((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
+	     (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) ||
+	    ((autoneg_val & (1<<12)) == 0))
 		bnx2x_cl45_write(bp, phy,
 			 MDIO_AN_DEVAD,
 			 MDIO_AN_REG_8481_LEGACY_MII_CTRL, autoneg_val);
@@ -9558,14 +9747,11 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
 			DP(NETIF_MSG_LINK, "Advertising 10G\n");
 			/* Restart autoneg for 10G*/
 
-			bnx2x_cl45_read(bp, phy,
-					MDIO_AN_DEVAD,
-					MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
-					&an_10g_val);
-			bnx2x_cl45_write(bp, phy,
-					 MDIO_AN_DEVAD,
-					 MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
-					 an_10g_val | 0x1000);
+			bnx2x_cl45_read_or_write(
+				bp, phy,
+				MDIO_AN_DEVAD,
+				MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
+				0x1000);
 			bnx2x_cl45_write(bp, phy,
 					 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
 					 0x3200);
@@ -9598,9 +9784,8 @@ static int bnx2x_8481_config_init(struct bnx2x_phy *phy,
 #define PHY84833_CMDHDLR_WAIT 300
 #define PHY84833_CMDHDLR_MAX_ARGS 5
 static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
-				   struct link_params *params,
-		   u16 fw_cmd,
-		   u16 cmd_args[], int argc)
+				struct link_params *params, u16 fw_cmd,
+				u16 cmd_args[], int argc)
 {
 	int idx;
 	u16 val;
@@ -9614,7 +9799,7 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
 				MDIO_84833_CMD_HDLR_STATUS, &val);
 		if (val == PHY84833_STATUS_CMD_OPEN_FOR_CMDS)
 			break;
-		 usleep_range(1000, 2000);
+		usleep_range(1000, 2000);
 	}
 	if (idx >= PHY84833_CMDHDLR_WAIT) {
 		DP(NETIF_MSG_LINK, "FW cmd: FW not ready.\n");
@@ -9635,7 +9820,7 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
 		if ((val == PHY84833_STATUS_CMD_COMPLETE_PASS) ||
 			(val == PHY84833_STATUS_CMD_COMPLETE_ERROR))
 			break;
-		 usleep_range(1000, 2000);
+		usleep_range(1000, 2000);
 	}
 	if ((idx >= PHY84833_CMDHDLR_WAIT) ||
 		(val == PHY84833_STATUS_CMD_COMPLETE_ERROR)) {
@@ -9654,7 +9839,6 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
 	return 0;
 }
 
-
 static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy,
 				   struct link_params *params,
 				   struct link_vars *vars)
@@ -9802,11 +9986,11 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 	struct bnx2x *bp = params->bp;
 	u8 port, initialize = 1;
 	u16 val;
-	u32 actual_phy_selection, cms_enable;
+	u32 actual_phy_selection;
 	u16 cmd_args[PHY84833_CMDHDLR_MAX_ARGS];
 	int rc = 0;
 
-	 usleep_range(1000, 2000);
+	usleep_range(1000, 2000);
 
 	if (!(CHIP_IS_E1x(bp)))
 		port = BP_PATH(bp);
@@ -9828,7 +10012,8 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 
 	/* Wait for GPHY to come out of reset */
 	msleep(50);
-	if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+	if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
+	    (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
 		/* BCM84823 requires that XGXS links up first @ 10G for normal
 		 * behavior.
 		 */
@@ -9884,7 +10069,8 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 	DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
 		   params->multi_phy_config, val);
 
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+	if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+	    (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
 		bnx2x_84833_pair_swap_cfg(phy, params, vars);
 
 		/* Keep AutogrEEEn disabled. */
@@ -9904,7 +10090,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 		bnx2x_save_848xx_spirom_version(phy, bp, params->port);
 	/* 84833 PHY has a better feature and doesn't need to support this. */
 	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
-		cms_enable = REG_RD(bp, params->shmem_base +
+		u32 cms_enable = REG_RD(bp, params->shmem_base +
 			offsetof(struct shmem_region,
 			dev_info.port_hw_config[params->port].default_cfg)) &
 			PORT_HW_CFG_ENABLE_CMS_MASK;
@@ -9933,7 +10119,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 			return rc;
 		}
 
-		if ((params->req_duplex[actual_phy_selection] == DUPLEX_FULL) &&
+		if ((phy->req_duplex == DUPLEX_FULL) &&
 		    (params->eee_mode & EEE_MODE_ADV_LPI) &&
 		    (bnx2x_eee_calc_timer(params) ||
 		     !(params->eee_mode & EEE_MODE_ENABLE_LPI)))
@@ -9948,15 +10134,13 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 		vars->eee_status &= ~SHMEM_EEE_SUPPORTED_MASK;
 	}
 
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+	if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+	    (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
 		/* Bring PHY out of super isolate mode as the final step. */
-		bnx2x_cl45_read(bp, phy,
-				MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
-		val &= ~MDIO_84833_SUPER_ISOLATE;
-		bnx2x_cl45_write(bp, phy,
-				MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
+		bnx2x_cl45_read_and_write(bp, phy,
+					  MDIO_CTL_DEVAD,
+					  MDIO_84833_TOP_CFG_XGPHY_STRAP1,
+					  (u16)~MDIO_84833_SUPER_ISOLATE);
 	}
 	return rc;
 }
@@ -10090,7 +10274,6 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
 	return link_up;
 }
 
-
 static int bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
 {
 	int status = 0;
@@ -10962,7 +11145,7 @@ static void bnx2x_7101_set_link_led(struct bnx2x_phy *phy,
 /*			STATIC PHY DECLARATION			  */
 /******************************************************************/
 
-static struct bnx2x_phy phy_null = {
+static const struct bnx2x_phy phy_null = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN,
 	.addr		= 0,
 	.def_md_devad	= 0,
@@ -10988,7 +11171,7 @@ static struct bnx2x_phy phy_null = {
 	.phy_specific_func = (phy_specific_func_t)NULL
 };
 
-static struct bnx2x_phy phy_serdes = {
+static const struct bnx2x_phy phy_serdes = {
 	.type		= PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT,
 	.addr		= 0xff,
 	.def_md_devad	= 0,
@@ -11023,7 +11206,7 @@ static struct bnx2x_phy phy_serdes = {
 	.phy_specific_func = (phy_specific_func_t)NULL
 };
 
-static struct bnx2x_phy phy_xgxs = {
+static const struct bnx2x_phy phy_xgxs = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
 	.addr		= 0xff,
 	.def_md_devad	= 0,
@@ -11058,12 +11241,11 @@ static struct bnx2x_phy phy_xgxs = {
 	.set_link_led	= (set_link_led_t)NULL,
 	.phy_specific_func = (phy_specific_func_t)bnx2x_xgxs_specific_func
 };
-static struct bnx2x_phy phy_warpcore = {
+static const struct bnx2x_phy phy_warpcore = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
 	.addr		= 0xff,
 	.def_md_devad	= 0,
-	.flags		= (FLAGS_HW_LOCK_REQUIRED |
-			   FLAGS_TX_ERROR_CHECK),
+	.flags		= FLAGS_TX_ERROR_CHECK,
 	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.mdio_ctrl	= 0,
@@ -11097,7 +11279,7 @@ static struct bnx2x_phy phy_warpcore = {
 };
 
 
-static struct bnx2x_phy phy_7101 = {
+static const struct bnx2x_phy phy_7101 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
 	.addr		= 0xff,
 	.def_md_devad	= 0,
@@ -11126,11 +11308,11 @@ static struct bnx2x_phy phy_7101 = {
 	.set_link_led	= (set_link_led_t)bnx2x_7101_set_link_led,
 	.phy_specific_func = (phy_specific_func_t)NULL
 };
-static struct bnx2x_phy phy_8073 = {
+static const struct bnx2x_phy phy_8073 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
 	.addr		= 0xff,
 	.def_md_devad	= 0,
-	.flags		= FLAGS_HW_LOCK_REQUIRED,
+	.flags		= 0,
 	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.mdio_ctrl	= 0,
@@ -11157,7 +11339,7 @@ static struct bnx2x_phy phy_8073 = {
 	.set_link_led	= (set_link_led_t)NULL,
 	.phy_specific_func = (phy_specific_func_t)bnx2x_8073_specific_func
 };
-static struct bnx2x_phy phy_8705 = {
+static const struct bnx2x_phy phy_8705 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705,
 	.addr		= 0xff,
 	.def_md_devad	= 0,
@@ -11185,7 +11367,7 @@ static struct bnx2x_phy phy_8705 = {
 	.set_link_led	= (set_link_led_t)NULL,
 	.phy_specific_func = (phy_specific_func_t)NULL
 };
-static struct bnx2x_phy phy_8706 = {
+static const struct bnx2x_phy phy_8706 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
 	.addr		= 0xff,
 	.def_md_devad	= 0,
@@ -11215,12 +11397,11 @@ static struct bnx2x_phy phy_8706 = {
 	.phy_specific_func = (phy_specific_func_t)NULL
 };
 
-static struct bnx2x_phy phy_8726 = {
+static const struct bnx2x_phy phy_8726 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
 	.addr		= 0xff,
 	.def_md_devad	= 0,
-	.flags		= (FLAGS_HW_LOCK_REQUIRED |
-			   FLAGS_INIT_XGXS_FIRST |
+	.flags		= (FLAGS_INIT_XGXS_FIRST |
 			   FLAGS_TX_ERROR_CHECK),
 	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
 	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
@@ -11248,7 +11429,7 @@ static struct bnx2x_phy phy_8726 = {
 	.phy_specific_func = (phy_specific_func_t)NULL
 };
 
-static struct bnx2x_phy phy_8727 = {
+static const struct bnx2x_phy phy_8727 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
 	.addr		= 0xff,
 	.def_md_devad	= 0,
@@ -11278,7 +11459,7 @@ static struct bnx2x_phy phy_8727 = {
 	.set_link_led	= (set_link_led_t)bnx2x_8727_set_link_led,
 	.phy_specific_func = (phy_specific_func_t)bnx2x_8727_specific_func
 };
-static struct bnx2x_phy phy_8481 = {
+static const struct bnx2x_phy phy_8481 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
 	.addr		= 0xff,
 	.def_md_devad	= 0,
@@ -11314,7 +11495,7 @@ static struct bnx2x_phy phy_8481 = {
 	.phy_specific_func = (phy_specific_func_t)NULL
 };
 
-static struct bnx2x_phy phy_84823 = {
+static const struct bnx2x_phy phy_84823 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
 	.addr		= 0xff,
 	.def_md_devad	= 0,
@@ -11351,7 +11532,7 @@ static struct bnx2x_phy phy_84823 = {
 	.phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func
 };
 
-static struct bnx2x_phy phy_84833 = {
+static const struct bnx2x_phy phy_84833 = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833,
 	.addr		= 0xff,
 	.def_md_devad	= 0,
@@ -11386,7 +11567,41 @@ static struct bnx2x_phy phy_84833 = {
 	.phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func
 };
 
-static struct bnx2x_phy phy_54618se = {
+static const struct bnx2x_phy phy_84834 = {
+	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834,
+	.addr		= 0xff,
+	.def_md_devad	= 0,
+	.flags		= FLAGS_FAN_FAILURE_DET_REQ |
+			    FLAGS_REARM_LATCH_SIGNAL,
+	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.mdio_ctrl	= 0,
+	.supported	= (SUPPORTED_100baseT_Half |
+			   SUPPORTED_100baseT_Full |
+			   SUPPORTED_1000baseT_Full |
+			   SUPPORTED_10000baseT_Full |
+			   SUPPORTED_TP |
+			   SUPPORTED_Autoneg |
+			   SUPPORTED_Pause |
+			   SUPPORTED_Asym_Pause),
+	.media_type	= ETH_PHY_BASE_T,
+	.ver_addr	= 0,
+	.req_flow_ctrl	= 0,
+	.req_line_speed	= 0,
+	.speed_cap_mask	= 0,
+	.req_duplex	= 0,
+	.rsrv		= 0,
+	.config_init	= (config_init_t)bnx2x_848x3_config_init,
+	.read_status	= (read_status_t)bnx2x_848xx_read_status,
+	.link_reset	= (link_reset_t)bnx2x_848x3_link_reset,
+	.config_loopback = (config_loopback_t)NULL,
+	.format_fw_ver	= (format_fw_ver_t)bnx2x_848xx_format_ver,
+	.hw_reset	= (hw_reset_t)bnx2x_84833_hw_reset_phy,
+	.set_link_led	= (set_link_led_t)bnx2x_848xx_set_link_led,
+	.phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func
+};
+
+static const struct bnx2x_phy phy_54618se = {
 	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE,
 	.addr		= 0xff,
 	.def_md_devad	= 0,
@@ -11564,9 +11779,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
 			phy->media_type = ETH_PHY_KR;
 			phy->flags |= FLAGS_WC_DUAL_MODE;
 			phy->supported &= (SUPPORTED_20000baseKR2_Full |
+					   SUPPORTED_Autoneg |
 					   SUPPORTED_FIBRE |
 					   SUPPORTED_Pause |
 					   SUPPORTED_Asym_Pause);
+			phy->flags &= ~FLAGS_TX_ERROR_CHECK;
 			break;
 		default:
 			DP(NETIF_MSG_LINK, "Unknown WC interface type 0x%x\n",
@@ -11665,6 +11882,9 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
 		*phy = phy_84833;
 		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834:
+		*phy = phy_84834;
+		break;
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616:
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE:
 		*phy = phy_54618se;
@@ -11721,9 +11941,10 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
 	}
 	phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port);
 
-	if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
+	if (((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+	     (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) &&
 	    (phy->ver_addr)) {
-		/* Remove 100Mb link supported for BCM84833 when phy fw
+		/* Remove 100Mb link supported for BCM84833/4 when phy fw
 		 * version lower than or equal to 1.39
 		 */
 		u32 raw_ver = REG_RD(bp, phy->ver_addr);
@@ -11733,12 +11954,6 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
 					    SUPPORTED_100baseT_Full);
 	}
 
-	/* In case mdc/mdio_access of the external phy is different than the
-	 * mdc/mdio access of the XGXS, a HW lock must be taken in each access
-	 * to prevent one port interfere with another port's CL45 operations.
-	 */
-	if (mdc_mdio_access != SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH)
-		phy->flags |= FLAGS_HW_LOCK_REQUIRED;
 	DP(NETIF_MSG_LINK, "phy_type 0x%x port %d found in index %d\n",
 		   phy_type, port, phy_index);
 	DP(NETIF_MSG_LINK, "             addr=0x%x, mdio_ctl=0x%x\n",
@@ -11863,7 +12078,6 @@ u32 bnx2x_phy_selection(struct link_params *params)
 	return return_cfg;
 }
 
-
 int bnx2x_phy_probe(struct link_params *params)
 {
 	u8 phy_index, actual_phy_idx;
@@ -11907,6 +12121,10 @@ int bnx2x_phy_probe(struct link_params *params)
 		    FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET)
 			phy->flags &= ~FLAGS_TX_ERROR_CHECK;
 
+		if (!(params->feature_config_flags &
+		      FEATURE_CONFIG_MT_SUPPORT))
+			phy->flags |= FLAGS_MDC_MDIO_WA_G;
+
 		sync_offset = params->shmem_base +
 			offsetof(struct shmem_region,
 			dev_info.port_hw_config[params->port].media_type);
@@ -11934,8 +12152,8 @@ int bnx2x_phy_probe(struct link_params *params)
 	return 0;
 }
 
-void bnx2x_init_bmac_loopback(struct link_params *params,
-			      struct link_vars *vars)
+static void bnx2x_init_bmac_loopback(struct link_params *params,
+				     struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 		vars->link_up = 1;
@@ -11954,8 +12172,8 @@ void bnx2x_init_bmac_loopback(struct link_params *params,
 		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 }
 
-void bnx2x_init_emac_loopback(struct link_params *params,
-			      struct link_vars *vars)
+static void bnx2x_init_emac_loopback(struct link_params *params,
+				     struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 		vars->link_up = 1;
@@ -11973,8 +12191,8 @@ void bnx2x_init_emac_loopback(struct link_params *params,
 		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 }
 
-void bnx2x_init_xmac_loopback(struct link_params *params,
-			      struct link_vars *vars)
+static void bnx2x_init_xmac_loopback(struct link_params *params,
+				     struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	vars->link_up = 1;
@@ -11999,8 +12217,8 @@ void bnx2x_init_xmac_loopback(struct link_params *params,
 	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 }
 
-void bnx2x_init_umac_loopback(struct link_params *params,
-			      struct link_vars *vars)
+static void bnx2x_init_umac_loopback(struct link_params *params,
+				     struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	vars->link_up = 1;
@@ -12014,17 +12232,21 @@ void bnx2x_init_umac_loopback(struct link_params *params,
 	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 }
 
-void bnx2x_init_xgxs_loopback(struct link_params *params,
-			      struct link_vars *vars)
+static void bnx2x_init_xgxs_loopback(struct link_params *params,
+				     struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
-		vars->link_up = 1;
-		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-		vars->duplex = DUPLEX_FULL;
+	struct bnx2x_phy *int_phy = &params->phy[INT_PHY];
+	vars->link_up = 1;
+	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+	vars->duplex = DUPLEX_FULL;
 	if (params->req_line_speed[0] == SPEED_1000)
-			vars->line_speed = SPEED_1000;
+		vars->line_speed = SPEED_1000;
+	else if ((params->req_line_speed[0] == SPEED_20000) ||
+		 (int_phy->flags & FLAGS_WC_DUAL_MODE))
+		vars->line_speed = SPEED_20000;
 	else
-			vars->line_speed = SPEED_10000;
+		vars->line_speed = SPEED_10000;
 
 	if (!USES_WARPCORE(bp))
 		bnx2x_xgxs_deassert(params);
@@ -12044,34 +12266,30 @@ void bnx2x_init_xgxs_loopback(struct link_params *params,
 			bnx2x_bmac_enable(params, vars, 0, 1);
 	}
 
-		if (params->loopback_mode == LOOPBACK_XGXS) {
-			/* set 10G XGXS loopback */
-			params->phy[INT_PHY].config_loopback(
-				&params->phy[INT_PHY],
-				params);
-
-		} else {
-			/* set external phy loopback */
-			u8 phy_index;
-			for (phy_index = EXT_PHY1;
-			      phy_index < params->num_phys; phy_index++) {
-				if (params->phy[phy_index].config_loopback)
-					params->phy[phy_index].config_loopback(
-						&params->phy[phy_index],
-						params);
-			}
-		}
-		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+	if (params->loopback_mode == LOOPBACK_XGXS) {
+		/* Set 10G XGXS loopback */
+		int_phy->config_loopback(int_phy, params);
+	} else {
+		/* Set external phy loopback */
+		u8 phy_index;
+		for (phy_index = EXT_PHY1;
+		      phy_index < params->num_phys; phy_index++)
+			if (params->phy[phy_index].config_loopback)
+				params->phy[phy_index].config_loopback(
+					&params->phy[phy_index],
+					params);
+	}
+	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 
 	bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed);
 }
 
-static void bnx2x_set_rx_filter(struct link_params *params, u8 en)
+void bnx2x_set_rx_filter(struct link_params *params, u8 en)
 {
 	struct bnx2x *bp = params->bp;
 	u8 val = en * 0x1F;
 
-	/* Open the gate between the NIG to the BRB */
+	/* Open / close the gate between the NIG and the BRB */
 	if (!CHIP_IS_E1x(bp))
 		val |= en * 0x20;
 	REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK + params->port*4, val);
@@ -12345,7 +12563,7 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
 	 * Hold it as vars low
 	 */
 	 /* Clear link led */
-	bnx2x_set_mdio_clk(bp, params->chip_id, port);
+	bnx2x_set_mdio_emac_per_phy(bp, params);
 	bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
 
 	if (reset_ext_phy) {
@@ -12696,7 +12914,7 @@ static int bnx2x_8727_common_init_phy(struct bnx2x *bp,
 	/* Initiate PHY reset*/
 	bnx2x_set_gpio(bp, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_LOW,
 		       port);
-	 usleep_range(1000, 2000);
+	usleep_range(1000, 2000);
 	bnx2x_set_gpio(bp, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_HIGH,
 		       port);
 
@@ -12784,7 +13002,8 @@ static int bnx2x_84833_common_init_phy(struct bnx2x *bp,
 }
 
 static int bnx2x_84833_pre_init_phy(struct bnx2x *bp,
-					       struct bnx2x_phy *phy)
+				    struct bnx2x_phy *phy,
+				    u8 port)
 {
 	u16 val, cnt;
 	/* Wait for FW completing its initialization. */
@@ -12794,7 +13013,7 @@ static int bnx2x_84833_pre_init_phy(struct bnx2x *bp,
 				MDIO_PMA_REG_CTRL, &val);
 		if (!(val & (1<<15)))
 			break;
-		 usleep_range(1000, 2000);
+		usleep_range(1000, 2000);
 	}
 	if (cnt >= 1500) {
 		DP(NETIF_MSG_LINK, "84833 reset timeout\n");
@@ -12811,26 +13030,28 @@ static int bnx2x_84833_pre_init_phy(struct bnx2x *bp,
 			 MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
 
 	/* Save spirom version */
-	bnx2x_save_848xx_spirom_version(phy, bp, PORT_0);
+	bnx2x_save_848xx_spirom_version(phy, bp, port);
 	return 0;
 }
 
 int bnx2x_pre_init_phy(struct bnx2x *bp,
 				  u32 shmem_base,
 				  u32 shmem2_base,
-				  u32 chip_id)
+				  u32 chip_id,
+				  u8 port)
 {
 	int rc = 0;
 	struct bnx2x_phy phy;
-	bnx2x_set_mdio_clk(bp, chip_id, PORT_0);
 	if (bnx2x_populate_phy(bp, EXT_PHY1, shmem_base, shmem2_base,
-			       PORT_0, &phy)) {
+			       port, &phy) != 0) {
 		DP(NETIF_MSG_LINK, "populate_phy failed\n");
 		return -EINVAL;
 	}
+	bnx2x_set_mdio_clk(bp, chip_id, phy.mdio_ctrl);
 	switch (phy.type) {
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
-		rc = bnx2x_84833_pre_init_phy(bp, &phy);
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834:
+		rc = bnx2x_84833_pre_init_phy(bp, &phy, port);
 		break;
 	default:
 		break;
@@ -12867,6 +13088,7 @@ static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
 						phy_index, chip_id);
 		break;
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834:
 		/* GPIO3's are linked, and so both need to be toggled
 		 * to obtain required 2us pulse.
 		 */
@@ -12898,8 +13120,9 @@ int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
 	u32 phy_ver, val;
 	u8 phy_index = 0;
 	u32 ext_phy_type, ext_phy_config;
-	bnx2x_set_mdio_clk(bp, chip_id, PORT_0);
-	bnx2x_set_mdio_clk(bp, chip_id, PORT_1);
+
+	bnx2x_set_mdio_clk(bp, chip_id, GRCBASE_EMAC0);
+	bnx2x_set_mdio_clk(bp, chip_id, GRCBASE_EMAC1);
 	DP(NETIF_MSG_LINK, "Begin common phy init\n");
 	if (CHIP_IS_E3(bp)) {
 		/* Enable EPIO */
@@ -12960,6 +13183,7 @@ static void bnx2x_check_over_curr(struct link_params *params,
 					    " error.\n",
 			 params->port);
 			vars->phy_flags |= PHY_OVER_CURRENT_FLAG;
+			bnx2x_warpcore_power_module(params, 0);
 		}
 	} else
 		vars->phy_flags &= ~PHY_OVER_CURRENT_FLAG;
@@ -13139,6 +13363,108 @@ static void bnx2x_sfp_tx_fault_detection(struct bnx2x_phy *phy,
 		}
 	}
 }
+static void bnx2x_disable_kr2(struct link_params *params,
+			      struct link_vars *vars,
+			      struct bnx2x_phy *phy)
+{
+	struct bnx2x *bp = params->bp;
+	int i;
+	static struct bnx2x_reg_set reg_set[] = {
+		/* Step 1 - Program the TX/RX alignment markers */
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0x7690},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xe647},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0xc4f0},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0x7690},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xe647},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0xc4f0},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000c},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6000},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0000},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0002},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x0000},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x0af7},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x0af7},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0002},
+		{MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0000}
+	};
+	DP(NETIF_MSG_LINK, "Disabling 20G-KR2\n");
+
+	for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++)
+		bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
+				 reg_set[i].val);
+	vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
+	bnx2x_update_link_attr(params, vars->link_attr_sync);
+
+	/* Restart AN on leading lane */
+	bnx2x_warpcore_restart_AN_KR(phy, params);
+}
+
+static void bnx2x_kr2_recovery(struct link_params *params,
+			       struct link_vars *vars,
+			       struct bnx2x_phy *phy)
+{
+	struct bnx2x *bp = params->bp;
+	DP(NETIF_MSG_LINK, "KR2 recovery\n");
+	bnx2x_warpcore_enable_AN_KR2(phy, params, vars);
+	bnx2x_warpcore_restart_AN_KR(phy, params);
+}
+
+static void bnx2x_check_kr2_wa(struct link_params *params,
+			       struct link_vars *vars,
+			       struct bnx2x_phy *phy)
+{
+	struct bnx2x *bp = params->bp;
+	u16 base_page, next_page, not_kr2_device, lane;
+	int sigdet = bnx2x_warpcore_get_sigdet(phy, params);
+
+	if (!sigdet) {
+		if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE))
+			bnx2x_kr2_recovery(params, vars, phy);
+		return;
+	}
+
+	lane = bnx2x_get_warpcore_lane(phy, params);
+	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+			  MDIO_AER_BLOCK_AER_REG, lane);
+	bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+			MDIO_AN_REG_LP_AUTO_NEG, &base_page);
+	bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+			MDIO_AN_REG_LP_AUTO_NEG2, &next_page);
+	bnx2x_set_aer_mmd(params, phy);
+
+	/* CL73 has not begun yet */
+	if (base_page == 0) {
+		if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE))
+			bnx2x_kr2_recovery(params, vars, phy);
+		return;
+	}
+
+	/* In case NP bit is not set in the BasePage, or it is set,
+	 * but only KX is advertised, declare this link partner as non-KR2
+	 * device.
+	 */
+	not_kr2_device = (((base_page & 0x8000) == 0) ||
+			  (((base_page & 0x8000) &&
+			    ((next_page & 0xe0) == 0x2))));
+
+	/* In case KR2 is already disabled, check if we need to re-enable it */
+	if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
+		if (!not_kr2_device) {
+			DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page,
+				       next_page);
+			bnx2x_kr2_recovery(params, vars, phy);
+		}
+		return;
+	}
+	/* KR2 is enabled, but not KR2 device */
+	if (not_kr2_device) {
+		/* Disable KR2 on both lanes */
+		DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page, next_page);
+		bnx2x_disable_kr2(params, vars, phy);
+		return;
+	}
+}
+
 void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
 {
 	u16 phy_idx;
@@ -13156,6 +13482,9 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
 	if (CHIP_IS_E3(bp)) {
 		struct bnx2x_phy *phy = &params->phy[INT_PHY];
 		bnx2x_set_aer_mmd(params, phy);
+		if ((phy->supported & SUPPORTED_20000baseKR2_Full) &&
+		    (phy->speed_cap_mask & SPEED_20000))
+			bnx2x_check_kr2_wa(params, vars, phy);
 		bnx2x_check_over_curr(params, vars);
 		if (vars->rx_tx_asic_rst)
 			bnx2x_warpcore_config_runtime(phy, params, vars);
@@ -13176,27 +13505,7 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
 				bnx2x_update_mng(params, vars->link_status);
 			}
 		}
-
-	}
-
-}
-
-u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base)
-{
-	u8 phy_index;
-	struct bnx2x_phy phy;
-	for (phy_index = INT_PHY; phy_index < MAX_PHYS;
-	      phy_index++) {
-		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
-				       0, &phy) != 0) {
-			DP(NETIF_MSG_LINK, "populate phy failed\n");
-			return 0;
-		}
-
-		if (phy.flags & FLAGS_HW_LOCK_REQUIRED)
-			return 1;
 	}
-	return 0;
 }
 
 u8 bnx2x_fan_failure_det_req(struct bnx2x *bp,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
index 9165b89..181c5ce 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
@@ -139,8 +139,6 @@ struct bnx2x_phy {
 	u8 addr;
 	u8 def_md_devad;
 	u16 flags;
-	/* Require HW lock */
-#define FLAGS_HW_LOCK_REQUIRED		(1<<0)
 	/* No Over-Current detection */
 #define FLAGS_NOC			(1<<1)
 	/* Fan failure detection required */
@@ -156,6 +154,7 @@ struct bnx2x_phy {
 #define FLAGS_MDC_MDIO_WA_B0		(1<<10)
 #define FLAGS_TX_ERROR_CHECK		(1<<12)
 #define FLAGS_EEE			(1<<13)
+#define FLAGS_MDC_MDIO_WA_G		(1<<15)
 
 	/* preemphasis values for the rx side */
 	u16 rx_preemphasis[4];
@@ -267,6 +266,8 @@ struct link_params {
 #define FEATURE_CONFIG_AUTOGREEEN_ENABLED			(1<<9)
 #define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED		(1<<10)
 #define FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET		(1<<11)
+#define FEATURE_CONFIG_MT_SUPPORT			(1<<13)
+
 	/* Will be populated during common init */
 	struct bnx2x_phy phy[MAX_PHYS];
 
@@ -347,6 +348,8 @@ struct link_vars {
 	u8 rx_tx_asic_rst;
 	u8 turn_to_run_wc_rt;
 	u16 rsrv2;
+	/* The same definitions as the shmem2 parameter */
+	u32 link_attr_sync;
 };
 
 /***********************************************************/
@@ -418,10 +421,6 @@ int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 
 void bnx2x_hw_reset_phy(struct link_params *params);
 
-/* Checks if HW lock is required for this phy/board type */
-u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base,
-			  u32 shmem2_base);
-
 /* Check swap bit and adjust PHY order */
 u32 bnx2x_phy_selection(struct link_params *params);
 
@@ -432,7 +431,8 @@ int bnx2x_phy_probe(struct link_params *params);
 u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base,
 			     u32 shmem2_base, u8 port);
 
-
+/* Open / close the gate between the NIG and the BRB */
+void bnx2x_set_rx_filter(struct link_params *params, u8 en);
 
 /* DCBX structs */
 
@@ -459,9 +459,6 @@ struct bnx2x_nig_brb_pfc_port_params {
 	u32 rx_cos_priority_mask[DCBX_MAX_NUM_COS];
 	u32 llfc_high_priority_classes;
 	u32 llfc_low_priority_classes;
-	/* BRB */
-	u32 cos0_pauseable;
-	u32 cos1_pauseable;
 };
 
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 01611b3..b4659c4 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -791,10 +791,9 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 
 		/* host sb data */
 
-#ifdef BCM_CNIC
 		if (IS_FCOE_FP(fp))
 			continue;
-#endif
+
 		BNX2X_ERR("     run indexes (");
 		for (j = 0; j < HC_SB_MAX_SM; j++)
 			pr_cont("0x%x%s",
@@ -859,7 +858,7 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 #ifdef BNX2X_STOP_ON_ERROR
 	/* Rings */
 	/* Rx */
-	for_each_rx_queue(bp, i) {
+	for_each_valid_rx_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
 
 		start = RX_BD(le16_to_cpu(*fp->rx_cons_sb) - 10);
@@ -893,7 +892,7 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 	}
 
 	/* Tx */
-	for_each_tx_queue(bp, i) {
+	for_each_valid_tx_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
 		for_each_cos_in_tx_queue(fp, cos) {
 			struct bnx2x_fp_txdata *txdata = fp->txdata_ptr[cos];
@@ -1483,7 +1482,7 @@ static void bnx2x_igu_int_disable(struct bnx2x *bp)
 		BNX2X_ERR("BUG! proper val not read from IGU!\n");
 }
 
-void bnx2x_int_disable(struct bnx2x *bp)
+static void bnx2x_int_disable(struct bnx2x *bp)
 {
 	if (bp->common.int_block == INT_BLOCK_HC)
 		bnx2x_hc_int_disable(bp);
@@ -1504,9 +1503,8 @@ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
 	if (msix) {
 		synchronize_irq(bp->msix_table[0].vector);
 		offset = 1;
-#ifdef BCM_CNIC
-		offset++;
-#endif
+		if (CNIC_SUPPORT(bp))
+			offset++;
 		for_each_eth_queue(bp, i)
 			synchronize_irq(bp->msix_table[offset++].vector);
 	} else
@@ -1588,9 +1586,8 @@ static bool bnx2x_trylock_leader_lock(struct bnx2x *bp)
 	return bnx2x_trylock_hw_lock(bp, bnx2x_get_leader_lock_resource(bp));
 }
 
-#ifdef BCM_CNIC
 static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid, u8 err);
-#endif
+
 
 void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe)
 {
@@ -1720,7 +1717,7 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
 	for_each_eth_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
 
-		mask = 0x2 << (fp->index + CNIC_PRESENT);
+		mask = 0x2 << (fp->index + CNIC_SUPPORT(bp));
 		if (status & mask) {
 			/* Handle Rx or Tx according to SB id */
 			prefetch(fp->rx_cons_sb);
@@ -1732,22 +1729,23 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
 		}
 	}
 
-#ifdef BCM_CNIC
-	mask = 0x2;
-	if (status & (mask | 0x1)) {
-		struct cnic_ops *c_ops = NULL;
+	if (CNIC_SUPPORT(bp)) {
+		mask = 0x2;
+		if (status & (mask | 0x1)) {
+			struct cnic_ops *c_ops = NULL;
 
-		if (likely(bp->state == BNX2X_STATE_OPEN)) {
-			rcu_read_lock();
-			c_ops = rcu_dereference(bp->cnic_ops);
-			if (c_ops)
-				c_ops->cnic_handler(bp->cnic_data, NULL);
-			rcu_read_unlock();
-		}
+			if (likely(bp->state == BNX2X_STATE_OPEN)) {
+				rcu_read_lock();
+				c_ops = rcu_dereference(bp->cnic_ops);
+				if (c_ops)
+					c_ops->cnic_handler(bp->cnic_data,
+							    NULL);
+				rcu_read_unlock();
+			}
 
-		status &= ~mask;
+			status &= ~mask;
+		}
 	}
-#endif
 
 	if (unlikely(status & 0x1)) {
 		queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
@@ -3075,11 +3073,13 @@ static void bnx2x_drv_info_ether_stat(struct bnx2x *bp)
 
 static void bnx2x_drv_info_fcoe_stat(struct bnx2x *bp)
 {
-#ifdef BCM_CNIC
 	struct bnx2x_dcbx_app_params *app = &bp->dcbx_port_params.app;
 	struct fcoe_stats_info *fcoe_stat =
 		&bp->slowpath->drv_info_to_mcp.fcoe_stat;
 
+	if (!CNIC_LOADED(bp))
+		return;
+
 	memcpy(fcoe_stat->mac_local + MAC_LEADING_ZERO_CNT,
 	       bp->fip_mac, ETH_ALEN);
 
@@ -3162,16 +3162,17 @@ static void bnx2x_drv_info_fcoe_stat(struct bnx2x *bp)
 
 	/* ask L5 driver to add data to the struct */
 	bnx2x_cnic_notify(bp, CNIC_CTL_FCOE_STATS_GET_CMD);
-#endif
 }
 
 static void bnx2x_drv_info_iscsi_stat(struct bnx2x *bp)
 {
-#ifdef BCM_CNIC
 	struct bnx2x_dcbx_app_params *app = &bp->dcbx_port_params.app;
 	struct iscsi_stats_info *iscsi_stat =
 		&bp->slowpath->drv_info_to_mcp.iscsi_stat;
 
+	if (!CNIC_LOADED(bp))
+		return;
+
 	memcpy(iscsi_stat->mac_local + MAC_LEADING_ZERO_CNT,
 	       bp->cnic_eth_dev.iscsi_mac, ETH_ALEN);
 
@@ -3180,7 +3181,6 @@ static void bnx2x_drv_info_iscsi_stat(struct bnx2x *bp)
 
 	/* ask L5 driver to add data to the struct */
 	bnx2x_cnic_notify(bp, CNIC_CTL_ISCSI_STATS_GET_CMD);
-#endif
 }
 
 /* called due to MCP event (on pmf):
@@ -4572,7 +4572,6 @@ static void bnx2x_update_eq_prod(struct bnx2x *bp, u16 prod)
 	mmiowb(); /* keep prod updates ordered */
 }
 
-#ifdef BCM_CNIC
 static int  bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid,
 				      union event_ring_elem *elem)
 {
@@ -4594,7 +4593,6 @@ static int  bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid,
 	bnx2x_cnic_cfc_comp(bp, cid, err);
 	return 0;
 }
-#endif
 
 static void bnx2x_handle_mcast_eqe(struct bnx2x *bp)
 {
@@ -4635,11 +4633,9 @@ static void bnx2x_handle_classification_eqe(struct bnx2x *bp,
 	switch (elem->message.data.eth_event.echo >> BNX2X_SWCID_SHIFT) {
 	case BNX2X_FILTER_MAC_PENDING:
 		DP(BNX2X_MSG_SP, "Got SETUP_MAC completions\n");
-#ifdef BCM_CNIC
-		if (cid == BNX2X_ISCSI_ETH_CID(bp))
+		if (CNIC_LOADED(bp) && (cid == BNX2X_ISCSI_ETH_CID(bp)))
 			vlan_mac_obj = &bp->iscsi_l2_mac_obj;
 		else
-#endif
 			vlan_mac_obj = &bp->sp_objs[cid].mac_obj;
 
 		break;
@@ -4665,9 +4661,7 @@ static void bnx2x_handle_classification_eqe(struct bnx2x *bp,
 
 }
 
-#ifdef BCM_CNIC
 static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start);
-#endif
 
 static void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp)
 {
@@ -4678,14 +4672,12 @@ static void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp)
 	/* Send rx_mode command again if was requested */
 	if (test_and_clear_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state))
 		bnx2x_set_storm_rx_mode(bp);
-#ifdef BCM_CNIC
 	else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED,
 				    &bp->sp_state))
 		bnx2x_set_iscsi_eth_rx_mode(bp, true);
 	else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED,
 				    &bp->sp_state))
 		bnx2x_set_iscsi_eth_rx_mode(bp, false);
-#endif
 
 	netif_addr_unlock_bh(bp->dev);
 }
@@ -4747,7 +4739,6 @@ static void bnx2x_after_function_update(struct bnx2x *bp)
 				  q);
 	}
 
-#ifdef BCM_CNIC
 	if (!NO_FCOE(bp)) {
 		fp = &bp->fp[FCOE_IDX(bp)];
 		queue_params.q_obj = &bnx2x_sp_obj(bp, fp).q_obj;
@@ -4770,22 +4761,16 @@ static void bnx2x_after_function_update(struct bnx2x *bp)
 		bnx2x_link_report(bp);
 		bnx2x_fw_command(bp, DRV_MSG_CODE_AFEX_VIFSET_ACK, 0);
 	}
-#else
-	/* If no FCoE ring - ACK MCP now */
-	bnx2x_link_report(bp);
-	bnx2x_fw_command(bp, DRV_MSG_CODE_AFEX_VIFSET_ACK, 0);
-#endif /* BCM_CNIC */
 }
 
 static struct bnx2x_queue_sp_obj *bnx2x_cid_to_q_obj(
 	struct bnx2x *bp, u32 cid)
 {
 	DP(BNX2X_MSG_SP, "retrieving fp from cid %d\n", cid);
-#ifdef BCM_CNIC
-	if (cid == BNX2X_FCOE_ETH_CID(bp))
+
+	if (CNIC_LOADED(bp) && (cid == BNX2X_FCOE_ETH_CID(bp)))
 		return &bnx2x_fcoe_sp_obj(bp, q_obj);
 	else
-#endif
 		return &bp->sp_objs[CID_TO_FP(cid, bp)].q_obj;
 }
 
@@ -4793,6 +4778,7 @@ static void bnx2x_eq_int(struct bnx2x *bp)
 {
 	u16 hw_cons, sw_cons, sw_prod;
 	union event_ring_elem *elem;
+	u8 echo;
 	u32 cid;
 	u8 opcode;
 	int spqe_cnt = 0;
@@ -4847,10 +4833,11 @@ static void bnx2x_eq_int(struct bnx2x *bp)
 			 */
 			DP(BNX2X_MSG_SP,
 			   "got delete ramrod for MULTI[%d]\n", cid);
-#ifdef BCM_CNIC
-			if (!bnx2x_cnic_handle_cfc_del(bp, cid, elem))
+
+			if (CNIC_LOADED(bp) &&
+			    !bnx2x_cnic_handle_cfc_del(bp, cid, elem))
 				goto next_spqe;
-#endif
+
 			q_obj = bnx2x_cid_to_q_obj(bp, cid);
 
 			if (q_obj->complete_cmd(bp, q_obj, BNX2X_Q_CMD_CFC_DEL))
@@ -4875,21 +4862,34 @@ static void bnx2x_eq_int(struct bnx2x *bp)
 				break;
 			bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_RELEASED);
 			goto next_spqe;
+
 		case EVENT_RING_OPCODE_FUNCTION_UPDATE:
-			DP(BNX2X_MSG_SP | BNX2X_MSG_MCP,
-			   "AFEX: ramrod completed FUNCTION_UPDATE\n");
-			f_obj->complete_cmd(bp, f_obj, BNX2X_F_CMD_AFEX_UPDATE);
+			echo = elem->message.data.function_update_event.echo;
+			if (echo == SWITCH_UPDATE) {
+				DP(BNX2X_MSG_SP | NETIF_MSG_IFUP,
+				   "got FUNC_SWITCH_UPDATE ramrod\n");
+				if (f_obj->complete_cmd(
+					bp, f_obj, BNX2X_F_CMD_SWITCH_UPDATE))
+					break;
 
-			/* We will perform the Queues update from sp_rtnl task
-			 * as all Queue SP operations should run under
-			 * rtnl_lock.
-			 */
-			smp_mb__before_clear_bit();
-			set_bit(BNX2X_SP_RTNL_AFEX_F_UPDATE,
-				&bp->sp_rtnl_state);
-			smp_mb__after_clear_bit();
+			} else {
+				DP(BNX2X_MSG_SP | BNX2X_MSG_MCP,
+				   "AFEX: ramrod completed FUNCTION_UPDATE\n");
+				f_obj->complete_cmd(bp, f_obj,
+						    BNX2X_F_CMD_AFEX_UPDATE);
+
+				/* We will perform the Queues update from
+				 * sp_rtnl task as all Queue SP operations
+				 * should run under rtnl_lock.
+				 */
+				smp_mb__before_clear_bit();
+				set_bit(BNX2X_SP_RTNL_AFEX_F_UPDATE,
+					&bp->sp_rtnl_state);
+				smp_mb__after_clear_bit();
+
+				schedule_delayed_work(&bp->sp_rtnl_task, 0);
+			}
 
-			schedule_delayed_work(&bp->sp_rtnl_task, 0);
 			goto next_spqe;
 
 		case EVENT_RING_OPCODE_AFEX_VIF_LISTS:
@@ -4999,11 +4999,10 @@ static void bnx2x_sp_task(struct work_struct *work)
 
 	/* SP events: STAT_QUERY and others */
 	if (status & BNX2X_DEF_SB_IDX) {
-#ifdef BCM_CNIC
 		struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
 
-		if ((!NO_FCOE(bp)) &&
-			(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
+		if (FCOE_INIT(bp) &&
+		    (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
 			/*
 			 * Prevent local bottom-halves from running as
 			 * we are going to change the local NAPI list.
@@ -5012,7 +5011,7 @@ static void bnx2x_sp_task(struct work_struct *work)
 			napi_schedule(&bnx2x_fcoe(bp, napi));
 			local_bh_enable();
 		}
-#endif
+
 		/* Handle EQ completions */
 		bnx2x_eq_int(bp);
 
@@ -5050,8 +5049,7 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
 		return IRQ_HANDLED;
 #endif
 
-#ifdef BCM_CNIC
-	{
+	if (CNIC_LOADED(bp)) {
 		struct cnic_ops *c_ops;
 
 		rcu_read_lock();
@@ -5060,7 +5058,7 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
 			c_ops->cnic_handler(bp->cnic_data, NULL);
 		rcu_read_unlock();
 	}
-#endif
+
 	queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
 
 	return IRQ_HANDLED;
@@ -5498,12 +5496,10 @@ void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
 	unsigned long rx_mode_flags = 0, ramrod_flags = 0;
 	unsigned long rx_accept_flags = 0, tx_accept_flags = 0;
 
-#ifdef BCM_CNIC
 	if (!NO_FCOE(bp))
 
 		/* Configure rx_mode of FCoE Queue */
 		__set_bit(BNX2X_RX_MODE_FCOE_ETH, &rx_mode_flags);
-#endif
 
 	switch (bp->rx_mode) {
 	case BNX2X_RX_MODE_NONE:
@@ -5624,12 +5620,12 @@ static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
 
 static inline u8 bnx2x_fp_igu_sb_id(struct bnx2x_fastpath *fp)
 {
-	return fp->bp->igu_base_sb + fp->index + CNIC_PRESENT;
+	return fp->bp->igu_base_sb + fp->index + CNIC_SUPPORT(fp->bp);
 }
 
 static inline u8 bnx2x_fp_fw_sb_id(struct bnx2x_fastpath *fp)
 {
-	return fp->bp->base_fw_ndsb + fp->index + CNIC_PRESENT;
+	return fp->bp->base_fw_ndsb + fp->index + CNIC_SUPPORT(fp->bp);
 }
 
 static u8 bnx2x_fp_cl_id(struct bnx2x_fastpath *fp)
@@ -5720,23 +5716,25 @@ static void bnx2x_init_tx_ring_one(struct bnx2x_fp_txdata *txdata)
 	txdata->tx_pkt = 0;
 }
 
+static void bnx2x_init_tx_rings_cnic(struct bnx2x *bp)
+{
+	int i;
+
+	for_each_tx_queue_cnic(bp, i)
+		bnx2x_init_tx_ring_one(bp->fp[i].txdata_ptr[0]);
+}
 static void bnx2x_init_tx_rings(struct bnx2x *bp)
 {
 	int i;
 	u8 cos;
 
-	for_each_tx_queue(bp, i)
+	for_each_eth_queue(bp, i)
 		for_each_cos_in_tx_queue(&bp->fp[i], cos)
 			bnx2x_init_tx_ring_one(bp->fp[i].txdata_ptr[cos]);
 }
 
-void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
+void bnx2x_nic_init_cnic(struct bnx2x *bp)
 {
-	int i;
-
-	for_each_eth_queue(bp, i)
-		bnx2x_init_eth_fp(bp, i);
-#ifdef BCM_CNIC
 	if (!NO_FCOE(bp))
 		bnx2x_init_fcoe_fp(bp);
 
@@ -5744,8 +5742,22 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
 		      BNX2X_VF_ID_INVALID, false,
 		      bnx2x_cnic_fw_sb_id(bp), bnx2x_cnic_igu_sb_id(bp));
 
-#endif
+	/* ensure status block indices were read */
+	rmb();
+	bnx2x_init_rx_rings_cnic(bp);
+	bnx2x_init_tx_rings_cnic(bp);
+
+	/* flush all */
+	mb();
+	mmiowb();
+}
+
+void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
+{
+	int i;
 
+	for_each_eth_queue(bp, i)
+		bnx2x_init_eth_fp(bp, i);
 	/* Initialize MOD_ABS interrupts */
 	bnx2x_init_mod_abs_int(bp, &bp->link_vars, bp->common.chip_id,
 			       bp->common.shmem_base, bp->common.shmem2_base,
@@ -6031,10 +6043,9 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
 	msleep(50);
 	bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON);
 	bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON);
-#ifndef BCM_CNIC
-	/* set NIC mode */
-	REG_WR(bp, PRS_REG_NIC_MODE, 1);
-#endif
+	if (!CNIC_SUPPORT(bp))
+		/* set NIC mode */
+		REG_WR(bp, PRS_REG_NIC_MODE, 1);
 
 	/* Enable inputs of parser neighbor blocks */
 	REG_WR(bp, TSDM_REG_ENABLE_IN1, 0x7fffffff);
@@ -6256,6 +6267,10 @@ void bnx2x_pf_disable(struct bnx2x *bp)
 static void bnx2x__common_init_phy(struct bnx2x *bp)
 {
 	u32 shmem_base[2], shmem2_base[2];
+	/* Avoid common init in case MFW supports LFA */
+	if (SHMEM2_RD(bp, size) >
+	    (u32)offsetof(struct shmem2_region, lfa_host_addr[BP_PORT(bp)]))
+		return;
 	shmem_base[0] =  bp->common.shmem_base;
 	shmem2_base[0] = bp->common.shmem2_base;
 	if (!CHIP_IS_E1x(bp)) {
@@ -6522,9 +6537,8 @@ static int bnx2x_init_hw_common(struct bnx2x *bp)
 	REG_WR(bp, QM_REG_SOFT_RESET, 1);
 	REG_WR(bp, QM_REG_SOFT_RESET, 0);
 
-#ifdef BCM_CNIC
-	bnx2x_init_block(bp, BLOCK_TM, PHASE_COMMON);
-#endif
+	if (CNIC_SUPPORT(bp))
+		bnx2x_init_block(bp, BLOCK_TM, PHASE_COMMON);
 
 	bnx2x_init_block(bp, BLOCK_DORQ, PHASE_COMMON);
 	REG_WR(bp, DORQ_REG_DPM_CID_OFST, BNX2X_DB_SHIFT);
@@ -6611,18 +6625,18 @@ static int bnx2x_init_hw_common(struct bnx2x *bp)
 
 	bnx2x_init_block(bp, BLOCK_SRC, PHASE_COMMON);
 
-#ifdef BCM_CNIC
-	REG_WR(bp, SRC_REG_KEYSEARCH_0, 0x63285672);
-	REG_WR(bp, SRC_REG_KEYSEARCH_1, 0x24b8f2cc);
-	REG_WR(bp, SRC_REG_KEYSEARCH_2, 0x223aef9b);
-	REG_WR(bp, SRC_REG_KEYSEARCH_3, 0x26001e3a);
-	REG_WR(bp, SRC_REG_KEYSEARCH_4, 0x7ae91116);
-	REG_WR(bp, SRC_REG_KEYSEARCH_5, 0x5ce5230b);
-	REG_WR(bp, SRC_REG_KEYSEARCH_6, 0x298d8adf);
-	REG_WR(bp, SRC_REG_KEYSEARCH_7, 0x6eb0ff09);
-	REG_WR(bp, SRC_REG_KEYSEARCH_8, 0x1830f82f);
-	REG_WR(bp, SRC_REG_KEYSEARCH_9, 0x01e46be7);
-#endif
+	if (CNIC_SUPPORT(bp)) {
+		REG_WR(bp, SRC_REG_KEYSEARCH_0, 0x63285672);
+		REG_WR(bp, SRC_REG_KEYSEARCH_1, 0x24b8f2cc);
+		REG_WR(bp, SRC_REG_KEYSEARCH_2, 0x223aef9b);
+		REG_WR(bp, SRC_REG_KEYSEARCH_3, 0x26001e3a);
+		REG_WR(bp, SRC_REG_KEYSEARCH_4, 0x7ae91116);
+		REG_WR(bp, SRC_REG_KEYSEARCH_5, 0x5ce5230b);
+		REG_WR(bp, SRC_REG_KEYSEARCH_6, 0x298d8adf);
+		REG_WR(bp, SRC_REG_KEYSEARCH_7, 0x6eb0ff09);
+		REG_WR(bp, SRC_REG_KEYSEARCH_8, 0x1830f82f);
+		REG_WR(bp, SRC_REG_KEYSEARCH_9, 0x01e46be7);
+	}
 	REG_WR(bp, SRC_REG_SOFT_RST, 0);
 
 	if (sizeof(union cdu_context) != 1024)
@@ -6786,11 +6800,11 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
 	/* QM cid (connection) count */
 	bnx2x_qm_init_cid_count(bp, bp->qm_cid_count, INITOP_SET);
 
-#ifdef BCM_CNIC
-	bnx2x_init_block(bp, BLOCK_TM, init_phase);
-	REG_WR(bp, TM_REG_LIN0_SCAN_TIME + port*4, 20);
-	REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + port*4, 31);
-#endif
+	if (CNIC_SUPPORT(bp)) {
+		bnx2x_init_block(bp, BLOCK_TM, init_phase);
+		REG_WR(bp, TM_REG_LIN0_SCAN_TIME + port*4, 20);
+		REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + port*4, 31);
+	}
 
 	bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
 
@@ -6877,9 +6891,9 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
 		REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0);
 	}
 
-#ifdef BCM_CNIC
-	bnx2x_init_block(bp, BLOCK_SRC, init_phase);
-#endif
+	if (CNIC_SUPPORT(bp))
+		bnx2x_init_block(bp, BLOCK_SRC, init_phase);
+
 	bnx2x_init_block(bp, BLOCK_CDU, init_phase);
 	bnx2x_init_block(bp, BLOCK_CFC, init_phase);
 
@@ -7040,6 +7054,130 @@ static void bnx2x_clear_func_ilt(struct bnx2x *bp, u32 func)
 		bnx2x_ilt_wr(bp, i, 0);
 }
 
+
+static void bnx2x_init_searcher(struct bnx2x *bp)
+{
+	int port = BP_PORT(bp);
+	bnx2x_src_init_t2(bp, bp->t2, bp->t2_mapping, SRC_CONN_NUM);
+	/* T1 hash bits value determines the T1 number of entries */
+	REG_WR(bp, SRC_REG_NUMBER_HASH_BITS0 + port*4, SRC_HASH_BITS);
+}
+
+static inline int bnx2x_func_switch_update(struct bnx2x *bp, int suspend)
+{
+	int rc;
+	struct bnx2x_func_state_params func_params = {NULL};
+	struct bnx2x_func_switch_update_params *switch_update_params =
+		&func_params.params.switch_update;
+
+	/* Prepare parameters for function state transitions */
+	__set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+	__set_bit(RAMROD_RETRY, &func_params.ramrod_flags);
+
+	func_params.f_obj = &bp->func_obj;
+	func_params.cmd = BNX2X_F_CMD_SWITCH_UPDATE;
+
+	/* Function parameters */
+	switch_update_params->suspend = suspend;
+
+	rc = bnx2x_func_state_change(bp, &func_params);
+
+	return rc;
+}
+
+static int bnx2x_reset_nic_mode(struct bnx2x *bp)
+{
+	int rc, i, port = BP_PORT(bp);
+	int vlan_en = 0, mac_en[NUM_MACS];
+
+
+	/* Close input from network */
+	if (bp->mf_mode == SINGLE_FUNCTION) {
+		bnx2x_set_rx_filter(&bp->link_params, 0);
+	} else {
+		vlan_en = REG_RD(bp, port ? NIG_REG_LLH1_FUNC_EN :
+				   NIG_REG_LLH0_FUNC_EN);
+		REG_WR(bp, port ? NIG_REG_LLH1_FUNC_EN :
+			  NIG_REG_LLH0_FUNC_EN, 0);
+		for (i = 0; i < NUM_MACS; i++) {
+			mac_en[i] = REG_RD(bp, port ?
+					     (NIG_REG_LLH1_FUNC_MEM_ENABLE +
+					      4 * i) :
+					     (NIG_REG_LLH0_FUNC_MEM_ENABLE +
+					      4 * i));
+			REG_WR(bp, port ? (NIG_REG_LLH1_FUNC_MEM_ENABLE +
+					      4 * i) :
+				  (NIG_REG_LLH0_FUNC_MEM_ENABLE + 4 * i), 0);
+		}
+	}
+
+	/* Close BMC to host */
+	REG_WR(bp, port ? NIG_REG_P0_TX_MNG_HOST_ENABLE :
+	       NIG_REG_P1_TX_MNG_HOST_ENABLE, 0);
+
+	/* Suspend Tx switching to the PF. Completion of this ramrod
+	 * further guarantees that all the packets of that PF / child
+	 * VFs in BRB were processed by the Parser, so it is safe to
+	 * change the NIC_MODE register.
+	 */
+	rc = bnx2x_func_switch_update(bp, 1);
+	if (rc) {
+		BNX2X_ERR("Can't suspend tx-switching!\n");
+		return rc;
+	}
+
+	/* Change NIC_MODE register */
+	REG_WR(bp, PRS_REG_NIC_MODE, 0);
+
+	/* Open input from network */
+	if (bp->mf_mode == SINGLE_FUNCTION) {
+		bnx2x_set_rx_filter(&bp->link_params, 1);
+	} else {
+		REG_WR(bp, port ? NIG_REG_LLH1_FUNC_EN :
+			  NIG_REG_LLH0_FUNC_EN, vlan_en);
+		for (i = 0; i < NUM_MACS; i++) {
+			REG_WR(bp, port ? (NIG_REG_LLH1_FUNC_MEM_ENABLE +
+					      4 * i) :
+				  (NIG_REG_LLH0_FUNC_MEM_ENABLE + 4 * i),
+				  mac_en[i]);
+		}
+	}
+
+	/* Enable BMC to host */
+	REG_WR(bp, port ? NIG_REG_P0_TX_MNG_HOST_ENABLE :
+	       NIG_REG_P1_TX_MNG_HOST_ENABLE, 1);
+
+	/* Resume Tx switching to the PF */
+	rc = bnx2x_func_switch_update(bp, 0);
+	if (rc) {
+		BNX2X_ERR("Can't resume tx-switching!\n");
+		return rc;
+	}
+
+	DP(NETIF_MSG_IFUP, "NIC MODE disabled\n");
+	return 0;
+}
+
+int bnx2x_init_hw_func_cnic(struct bnx2x *bp)
+{
+	int rc;
+
+	bnx2x_ilt_init_op_cnic(bp, INITOP_SET);
+
+	if (CONFIGURE_NIC_MODE(bp)) {
+		/* Configrue searcher as part of function hw init */
+		bnx2x_init_searcher(bp);
+
+		/* Reset NIC mode */
+		rc = bnx2x_reset_nic_mode(bp);
+		if (rc)
+			BNX2X_ERR("Can't change NIC mode!\n");
+		return rc;
+	}
+
+	return 0;
+}
+
 static int bnx2x_init_hw_func(struct bnx2x *bp)
 {
 	int port = BP_PORT(bp);
@@ -7082,17 +7220,16 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
 	}
 	bnx2x_ilt_init_op(bp, INITOP_SET);
 
-#ifdef BCM_CNIC
-	bnx2x_src_init_t2(bp, bp->t2, bp->t2_mapping, SRC_CONN_NUM);
-
-	/* T1 hash bits value determines the T1 number of entries */
-	REG_WR(bp, SRC_REG_NUMBER_HASH_BITS0 + port*4, SRC_HASH_BITS);
-#endif
+	if (!CONFIGURE_NIC_MODE(bp)) {
+		bnx2x_init_searcher(bp);
+		REG_WR(bp, PRS_REG_NIC_MODE, 0);
+		DP(NETIF_MSG_IFUP, "NIC MODE disabled\n");
+	} else {
+		/* Set NIC mode */
+		REG_WR(bp, PRS_REG_NIC_MODE, 1);
+		DP(NETIF_MSG_IFUP, "NIC MODE configrued\n");
 
-#ifndef BCM_CNIC
-	/* set NIC mode */
-	REG_WR(bp, PRS_REG_NIC_MODE, 1);
-#endif  /* BCM_CNIC */
+	}
 
 	if (!CHIP_IS_E1x(bp)) {
 		u32 pf_conf = IGU_PF_CONF_FUNC_EN;
@@ -7343,6 +7480,20 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
 }
 
 
+void bnx2x_free_mem_cnic(struct bnx2x *bp)
+{
+	bnx2x_ilt_mem_op_cnic(bp, ILT_MEMOP_FREE);
+
+	if (!CHIP_IS_E1x(bp))
+		BNX2X_PCI_FREE(bp->cnic_sb.e2_sb, bp->cnic_sb_mapping,
+			       sizeof(struct host_hc_status_block_e2));
+	else
+		BNX2X_PCI_FREE(bp->cnic_sb.e1x_sb, bp->cnic_sb_mapping,
+			       sizeof(struct host_hc_status_block_e1x));
+
+	BNX2X_PCI_FREE(bp->t2, bp->t2_mapping, SRC_T2_SZ);
+}
+
 void bnx2x_free_mem(struct bnx2x *bp)
 {
 	int i;
@@ -7367,17 +7518,6 @@ void bnx2x_free_mem(struct bnx2x *bp)
 
 	BNX2X_FREE(bp->ilt->lines);
 
-#ifdef BCM_CNIC
-	if (!CHIP_IS_E1x(bp))
-		BNX2X_PCI_FREE(bp->cnic_sb.e2_sb, bp->cnic_sb_mapping,
-			       sizeof(struct host_hc_status_block_e2));
-	else
-		BNX2X_PCI_FREE(bp->cnic_sb.e1x_sb, bp->cnic_sb_mapping,
-			       sizeof(struct host_hc_status_block_e1x));
-
-	BNX2X_PCI_FREE(bp->t2, bp->t2_mapping, SRC_T2_SZ);
-#endif
-
 	BNX2X_PCI_FREE(bp->spq, bp->spq_mapping, BCM_PAGE_SIZE);
 
 	BNX2X_PCI_FREE(bp->eq_ring, bp->eq_mapping,
@@ -7445,24 +7585,44 @@ alloc_mem_err:
 	return -ENOMEM;
 }
 
-
-int bnx2x_alloc_mem(struct bnx2x *bp)
+int bnx2x_alloc_mem_cnic(struct bnx2x *bp)
 {
-	int i, allocated, context_size;
-
-#ifdef BCM_CNIC
 	if (!CHIP_IS_E1x(bp))
 		/* size = the status block + ramrod buffers */
 		BNX2X_PCI_ALLOC(bp->cnic_sb.e2_sb, &bp->cnic_sb_mapping,
 				sizeof(struct host_hc_status_block_e2));
 	else
-		BNX2X_PCI_ALLOC(bp->cnic_sb.e1x_sb, &bp->cnic_sb_mapping,
-				sizeof(struct host_hc_status_block_e1x));
+		BNX2X_PCI_ALLOC(bp->cnic_sb.e1x_sb,
+				&bp->cnic_sb_mapping,
+				sizeof(struct
+				       host_hc_status_block_e1x));
 
-	/* allocate searcher T2 table */
-	BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ);
-#endif
+	if (CONFIGURE_NIC_MODE(bp))
+		/* allocate searcher T2 table, as it wan't allocated before */
+		BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ);
+
+	/* write address to which L5 should insert its values */
+	bp->cnic_eth_dev.addr_drv_info_to_mcp =
+		&bp->slowpath->drv_info_to_mcp;
 
+	if (bnx2x_ilt_mem_op_cnic(bp, ILT_MEMOP_ALLOC))
+		goto alloc_mem_err;
+
+	return 0;
+
+alloc_mem_err:
+	bnx2x_free_mem_cnic(bp);
+	BNX2X_ERR("Can't allocate memory\n");
+	return -ENOMEM;
+}
+
+int bnx2x_alloc_mem(struct bnx2x *bp)
+{
+	int i, allocated, context_size;
+
+	if (!CONFIGURE_NIC_MODE(bp))
+		/* allocate searcher T2 table */
+		BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ);
 
 	BNX2X_PCI_ALLOC(bp->def_status_blk, &bp->def_status_blk_mapping,
 			sizeof(struct host_sp_status_block));
@@ -7470,11 +7630,6 @@ int bnx2x_alloc_mem(struct bnx2x *bp)
 	BNX2X_PCI_ALLOC(bp->slowpath, &bp->slowpath_mapping,
 			sizeof(struct bnx2x_slowpath));
 
-#ifdef BCM_CNIC
-	/* write address to which L5 should insert its values */
-	bp->cnic_eth_dev.addr_drv_info_to_mcp = &bp->slowpath->drv_info_to_mcp;
-#endif
-
 	/* Allocated memory for FW statistics  */
 	if (bnx2x_alloc_fw_stats_mem(bp))
 		goto alloc_mem_err;
@@ -7596,14 +7751,12 @@ int bnx2x_set_eth_mac(struct bnx2x *bp, bool set)
 {
 	unsigned long ramrod_flags = 0;
 
-#ifdef BCM_CNIC
 	if (is_zero_ether_addr(bp->dev->dev_addr) &&
 	    (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))) {
 		DP(NETIF_MSG_IFUP | NETIF_MSG_IFDOWN,
 		   "Ignoring Zero MAC for STORAGE SD mode\n");
 		return 0;
 	}
-#endif
 
 	DP(NETIF_MSG_IFUP, "Adding Eth MAC\n");
 
@@ -7632,7 +7785,8 @@ void bnx2x_set_int_mode(struct bnx2x *bp)
 		bnx2x_enable_msi(bp);
 		/* falling through... */
 	case INT_MODE_INTx:
-		bp->num_queues = 1 + NON_ETH_CONTEXT_USE;
+		bp->num_ethernet_queues = 1;
+		bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
 		BNX2X_DEV_INFO("set number of queues to 1\n");
 		break;
 	default:
@@ -7644,9 +7798,10 @@ void bnx2x_set_int_mode(struct bnx2x *bp)
 		    bp->flags & USING_SINGLE_MSIX_FLAG) {
 			/* failed to enable multiple MSI-X */
 			BNX2X_DEV_INFO("Failed to enable multiple MSI-X (%d), set number of queues to %d\n",
-				       bp->num_queues, 1 + NON_ETH_CONTEXT_USE);
+				       bp->num_queues,
+				       1 + bp->num_cnic_queues);
 
-			bp->num_queues = 1 + NON_ETH_CONTEXT_USE;
+			bp->num_queues = 1 + bp->num_cnic_queues;
 
 			/* Try to enable MSI */
 			if (!(bp->flags & USING_SINGLE_MSIX_FLAG) &&
@@ -7679,9 +7834,9 @@ void bnx2x_ilt_set_info(struct bnx2x *bp)
 	ilt_client->flags = ILT_CLIENT_SKIP_MEM;
 	ilt_client->start = line;
 	line += bnx2x_cid_ilt_lines(bp);
-#ifdef BCM_CNIC
-	line += CNIC_ILT_LINES;
-#endif
+
+	if (CNIC_SUPPORT(bp))
+		line += CNIC_ILT_LINES;
 	ilt_client->end = line - 1;
 
 	DP(NETIF_MSG_IFUP, "ilt client[CDU]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n",
@@ -7714,49 +7869,43 @@ void bnx2x_ilt_set_info(struct bnx2x *bp)
 		   ilog2(ilt_client->page_size >> 12));
 
 	}
-	/* SRC */
-	ilt_client = &ilt->clients[ILT_CLIENT_SRC];
-#ifdef BCM_CNIC
-	ilt_client->client_num = ILT_CLIENT_SRC;
-	ilt_client->page_size = SRC_ILT_PAGE_SZ;
-	ilt_client->flags = 0;
-	ilt_client->start = line;
-	line += SRC_ILT_LINES;
-	ilt_client->end = line - 1;
 
-	DP(NETIF_MSG_IFUP,
-	   "ilt client[SRC]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n",
-	   ilt_client->start,
-	   ilt_client->end,
-	   ilt_client->page_size,
-	   ilt_client->flags,
-	   ilog2(ilt_client->page_size >> 12));
+	if (CNIC_SUPPORT(bp)) {
+		/* SRC */
+		ilt_client = &ilt->clients[ILT_CLIENT_SRC];
+		ilt_client->client_num = ILT_CLIENT_SRC;
+		ilt_client->page_size = SRC_ILT_PAGE_SZ;
+		ilt_client->flags = 0;
+		ilt_client->start = line;
+		line += SRC_ILT_LINES;
+		ilt_client->end = line - 1;
 
-#else
-	ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM);
-#endif
+		DP(NETIF_MSG_IFUP,
+		   "ilt client[SRC]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n",
+		   ilt_client->start,
+		   ilt_client->end,
+		   ilt_client->page_size,
+		   ilt_client->flags,
+		   ilog2(ilt_client->page_size >> 12));
 
-	/* TM */
-	ilt_client = &ilt->clients[ILT_CLIENT_TM];
-#ifdef BCM_CNIC
-	ilt_client->client_num = ILT_CLIENT_TM;
-	ilt_client->page_size = TM_ILT_PAGE_SZ;
-	ilt_client->flags = 0;
-	ilt_client->start = line;
-	line += TM_ILT_LINES;
-	ilt_client->end = line - 1;
+		/* TM */
+		ilt_client = &ilt->clients[ILT_CLIENT_TM];
+		ilt_client->client_num = ILT_CLIENT_TM;
+		ilt_client->page_size = TM_ILT_PAGE_SZ;
+		ilt_client->flags = 0;
+		ilt_client->start = line;
+		line += TM_ILT_LINES;
+		ilt_client->end = line - 1;
 
-	DP(NETIF_MSG_IFUP,
-	   "ilt client[TM]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n",
-	   ilt_client->start,
-	   ilt_client->end,
-	   ilt_client->page_size,
-	   ilt_client->flags,
-	   ilog2(ilt_client->page_size >> 12));
+		DP(NETIF_MSG_IFUP,
+		   "ilt client[TM]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n",
+		   ilt_client->start,
+		   ilt_client->end,
+		   ilt_client->page_size,
+		   ilt_client->flags,
+		   ilog2(ilt_client->page_size >> 12));
+	}
 
-#else
-	ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM);
-#endif
 	BUG_ON(line > ILT_MAX_LINES);
 }
 
@@ -7823,7 +7972,7 @@ static void bnx2x_pf_q_prep_init(struct bnx2x *bp,
 	}
 }
 
-int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+static int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 			struct bnx2x_queue_state_params *q_params,
 			struct bnx2x_queue_setup_tx_only_params *tx_only_params,
 			int tx_index, bool leading)
@@ -7924,6 +8073,9 @@ int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 	/* Set the command */
 	q_params.cmd = BNX2X_Q_CMD_SETUP;
 
+	if (IS_FCOE_FP(fp))
+		bp->fcoe_init = true;
+
 	/* Change the state to SETUP */
 	rc = bnx2x_queue_state_change(bp, &q_params);
 	if (rc) {
@@ -8037,12 +8189,12 @@ static void bnx2x_reset_func(struct bnx2x *bp)
 			   SB_DISABLED);
 	}
 
-#ifdef BCM_CNIC
-	/* CNIC SB */
-	REG_WR8(bp, BAR_CSTRORM_INTMEM +
-		CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(bnx2x_cnic_fw_sb_id(bp)),
-		SB_DISABLED);
-#endif
+	if (CNIC_LOADED(bp))
+		/* CNIC SB */
+		REG_WR8(bp, BAR_CSTRORM_INTMEM +
+			CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET
+			(bnx2x_cnic_fw_sb_id(bp)), SB_DISABLED);
+
 	/* SP SB */
 	REG_WR8(bp, BAR_CSTRORM_INTMEM +
 		   CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(func),
@@ -8061,19 +8213,19 @@ static void bnx2x_reset_func(struct bnx2x *bp)
 		REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, 0);
 	}
 
-#ifdef BCM_CNIC
-	/* Disable Timer scan */
-	REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
-	/*
-	 * Wait for at least 10ms and up to 2 second for the timers scan to
-	 * complete
-	 */
-	for (i = 0; i < 200; i++) {
-		msleep(10);
-		if (!REG_RD(bp, TM_REG_LIN0_SCAN_ON + port*4))
-			break;
+	if (CNIC_LOADED(bp)) {
+		/* Disable Timer scan */
+		REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
+		/*
+		 * Wait for at least 10ms and up to 2 second for the timers
+		 * scan to complete
+		 */
+		for (i = 0; i < 200; i++) {
+			msleep(10);
+			if (!REG_RD(bp, TM_REG_LIN0_SCAN_ON + port*4))
+				break;
+		}
 	}
-#endif
 	/* Clear ILT */
 	bnx2x_clear_func_ilt(bp, func);
 
@@ -8409,13 +8561,24 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode, bool keep_link)
 	/* Close multi and leading connections
 	 * Completions for ramrods are collected in a synchronous way
 	 */
-	for_each_queue(bp, i)
+	for_each_eth_queue(bp, i)
 		if (bnx2x_stop_queue(bp, i))
 #ifdef BNX2X_STOP_ON_ERROR
 			return;
 #else
 			goto unload_error;
 #endif
+
+	if (CNIC_LOADED(bp)) {
+		for_each_cnic_queue(bp, i)
+			if (bnx2x_stop_queue(bp, i))
+#ifdef BNX2X_STOP_ON_ERROR
+				return;
+#else
+				goto unload_error;
+#endif
+	}
+
 	/* If SP settings didn't get completed so far - something
 	 * very wrong has happen.
 	 */
@@ -8437,6 +8600,8 @@ unload_error:
 	bnx2x_netif_stop(bp, 1);
 	/* Delete all NAPI objects */
 	bnx2x_del_all_napi(bp);
+	if (CNIC_LOADED(bp))
+		bnx2x_del_all_napi_cnic(bp);
 
 	/* Release IRQs */
 	bnx2x_free_irq(bp);
@@ -8850,7 +9015,7 @@ static int bnx2x_process_kill(struct bnx2x *bp, bool global)
 	return 0;
 }
 
-int bnx2x_leader_reset(struct bnx2x *bp)
+static int bnx2x_leader_reset(struct bnx2x *bp)
 {
 	int rc = 0;
 	bool global = bnx2x_reset_is_global(bp);
@@ -9701,6 +9866,14 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
 
 	bp->link_params.shmem_base = bp->common.shmem_base;
 	bp->link_params.shmem2_base = bp->common.shmem2_base;
+	if (SHMEM2_RD(bp, size) >
+	    (u32)offsetof(struct shmem2_region, lfa_host_addr[BP_PORT(bp)]))
+		bp->link_params.lfa_base =
+		REG_RD(bp, bp->common.shmem2_base +
+		       (u32)offsetof(struct shmem2_region,
+				     lfa_host_addr[BP_PORT(bp)]));
+	else
+		bp->link_params.lfa_base = 0;
 	BNX2X_DEV_INFO("shmem offset 0x%x  shmem2 offset 0x%x\n",
 		       bp->common.shmem_base, bp->common.shmem2_base);
 
@@ -9748,6 +9921,11 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
 	bp->link_params.feature_config_flags |=
 		(val >= REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED) ?
 		FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED : 0;
+
+	bp->link_params.feature_config_flags |=
+		(val >= REQ_BC_VER_4_MT_SUPPORTED) ?
+		FEATURE_CONFIG_MT_SUPPORT : 0;
+
 	bp->flags |= (val >= REQ_BC_VER_4_PFC_STATS_SUPPORTED) ?
 			BC_SUPPORTS_PFC_STATS : 0;
 
@@ -10199,17 +10377,6 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
 		bp->mdio.prtad =
 			XGXS_EXT_PHY_ADDR(ext_phy_config);
 
-	/*
-	 * Check if hw lock is required to access MDC/MDIO bus to the PHY(s)
-	 * In MF mode, it is set to cover self test cases
-	 */
-	if (IS_MF(bp))
-		bp->port.need_hw_lock = 1;
-	else
-		bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
-							bp->common.shmem_base,
-							bp->common.shmem2_base);
-
 	/* Configure link feature according to nvram value */
 	eee_mode = (((SHMEM_RD(bp, dev_info.
 		      port_feature_config[port].eee_power_mode)) &
@@ -10227,12 +10394,15 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
 void bnx2x_get_iscsi_info(struct bnx2x *bp)
 {
 	u32 no_flags = NO_ISCSI_FLAG;
-#ifdef BCM_CNIC
 	int port = BP_PORT(bp);
-
 	u32 max_iscsi_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
 				drv_lic_key[port].max_iscsi_conn);
 
+	if (!CNIC_SUPPORT(bp)) {
+		bp->flags |= no_flags;
+		return;
+	}
+
 	/* Get the number of maximum allowed iSCSI connections */
 	bp->cnic_eth_dev.max_iscsi_conn =
 		(max_iscsi_conn & BNX2X_MAX_ISCSI_INIT_CONN_MASK) >>
@@ -10247,12 +10417,9 @@ void bnx2x_get_iscsi_info(struct bnx2x *bp)
 	 */
 	if (!bp->cnic_eth_dev.max_iscsi_conn)
 		bp->flags |= no_flags;
-#else
-	bp->flags |= no_flags;
-#endif
+
 }
 
-#ifdef BCM_CNIC
 static void __devinit bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func)
 {
 	/* Port info */
@@ -10267,16 +10434,18 @@ static void __devinit bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func)
 	bp->cnic_eth_dev.fcoe_wwn_node_name_lo =
 		MF_CFG_RD(bp, func_ext_config[func].fcoe_wwn_node_name_lower);
 }
-#endif
 static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp)
 {
-#ifdef BCM_CNIC
 	int port = BP_PORT(bp);
 	int func = BP_ABS_FUNC(bp);
-
 	u32 max_fcoe_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
 				drv_lic_key[port].max_fcoe_conn);
 
+	if (!CNIC_SUPPORT(bp)) {
+		bp->flags |= NO_FCOE_FLAG;
+		return;
+	}
+
 	/* Get the number of maximum allowed FCoE connections */
 	bp->cnic_eth_dev.max_fcoe_conn =
 		(max_fcoe_conn & BNX2X_MAX_FCOE_INIT_CONN_MASK) >>
@@ -10322,9 +10491,6 @@ static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp)
 	 */
 	if (!bp->cnic_eth_dev.max_fcoe_conn)
 		bp->flags |= NO_FCOE_FLAG;
-#else
-	bp->flags |= NO_FCOE_FLAG;
-#endif
 }
 
 static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp)
@@ -10338,132 +10504,133 @@ static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp)
 	bnx2x_get_fcoe_info(bp);
 }
 
-static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
+static void __devinit bnx2x_get_cnic_mac_hwinfo(struct bnx2x *bp)
 {
 	u32 val, val2;
 	int func = BP_ABS_FUNC(bp);
 	int port = BP_PORT(bp);
-#ifdef BCM_CNIC
 	u8 *iscsi_mac = bp->cnic_eth_dev.iscsi_mac;
 	u8 *fip_mac = bp->fip_mac;
-#endif
-
-	/* Zero primary MAC configuration */
-	memset(bp->dev->dev_addr, 0, ETH_ALEN);
 
-	if (BP_NOMCP(bp)) {
-		BNX2X_ERROR("warning: random MAC workaround active\n");
-		eth_hw_addr_random(bp->dev);
-	} else if (IS_MF(bp)) {
-		val2 = MF_CFG_RD(bp, func_mf_config[func].mac_upper);
-		val = MF_CFG_RD(bp, func_mf_config[func].mac_lower);
-		if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) &&
-		    (val != FUNC_MF_CFG_LOWERMAC_DEFAULT))
-			bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
-
-#ifdef BCM_CNIC
-		/*
-		 * iSCSI and FCoE NPAR MACs: if there is no either iSCSI or
+	if (IS_MF(bp)) {
+		/* iSCSI and FCoE NPAR MACs: if there is no either iSCSI or
 		 * FCoE MAC then the appropriate feature should be disabled.
-		 *
-		 * In non SD mode features configuration comes from
-		 * struct func_ext_config.
+		 * In non SD mode features configuration comes from struct
+		 * func_ext_config.
 		 */
-		if (!IS_MF_SD(bp)) {
+		if (!IS_MF_SD(bp) && !CHIP_IS_E1x(bp)) {
 			u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg);
 			if (cfg & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD) {
 				val2 = MF_CFG_RD(bp, func_ext_config[func].
-						     iscsi_mac_addr_upper);
+						 iscsi_mac_addr_upper);
 				val = MF_CFG_RD(bp, func_ext_config[func].
-						    iscsi_mac_addr_lower);
+						iscsi_mac_addr_lower);
 				bnx2x_set_mac_buf(iscsi_mac, val, val2);
-				BNX2X_DEV_INFO("Read iSCSI MAC: %pM\n",
-					       iscsi_mac);
-			} else
+				BNX2X_DEV_INFO
+					("Read iSCSI MAC: %pM\n", iscsi_mac);
+			} else {
 				bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
+			}
 
 			if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD) {
 				val2 = MF_CFG_RD(bp, func_ext_config[func].
-						     fcoe_mac_addr_upper);
+						 fcoe_mac_addr_upper);
 				val = MF_CFG_RD(bp, func_ext_config[func].
-						    fcoe_mac_addr_lower);
+						fcoe_mac_addr_lower);
 				bnx2x_set_mac_buf(fip_mac, val, val2);
-				BNX2X_DEV_INFO("Read FCoE L2 MAC: %pM\n",
-					       fip_mac);
-
-			} else
+				BNX2X_DEV_INFO
+					("Read FCoE L2 MAC: %pM\n", fip_mac);
+			} else {
 				bp->flags |= NO_FCOE_FLAG;
+			}
 
 			bp->mf_ext_config = cfg;
 
 		} else { /* SD MODE */
-			if (IS_MF_STORAGE_SD(bp)) {
-				if (BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp)) {
-					/* use primary mac as iscsi mac */
-					memcpy(iscsi_mac, bp->dev->dev_addr,
-					       ETH_ALEN);
-
-					BNX2X_DEV_INFO("SD ISCSI MODE\n");
-					BNX2X_DEV_INFO("Read iSCSI MAC: %pM\n",
-						       iscsi_mac);
-				} else { /* FCoE */
-					memcpy(fip_mac, bp->dev->dev_addr,
-					       ETH_ALEN);
-					BNX2X_DEV_INFO("SD FCoE MODE\n");
-					BNX2X_DEV_INFO("Read FIP MAC: %pM\n",
-						       fip_mac);
-				}
-				/* Zero primary MAC configuration */
-				memset(bp->dev->dev_addr, 0, ETH_ALEN);
+			if (BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp)) {
+				/* use primary mac as iscsi mac */
+				memcpy(iscsi_mac, bp->dev->dev_addr, ETH_ALEN);
+
+				BNX2X_DEV_INFO("SD ISCSI MODE\n");
+				BNX2X_DEV_INFO
+					("Read iSCSI MAC: %pM\n", iscsi_mac);
+			} else if (BNX2X_IS_MF_SD_PROTOCOL_FCOE(bp)) {
+				/* use primary mac as fip mac */
+				memcpy(fip_mac, bp->dev->dev_addr, ETH_ALEN);
+				BNX2X_DEV_INFO("SD FCoE MODE\n");
+				BNX2X_DEV_INFO
+					("Read FIP MAC: %pM\n", fip_mac);
 			}
 		}
 
+		if (IS_MF_STORAGE_SD(bp))
+			/* Zero primary MAC configuration */
+			memset(bp->dev->dev_addr, 0, ETH_ALEN);
+
 		if (IS_MF_FCOE_AFEX(bp))
 			/* use FIP MAC as primary MAC */
 			memcpy(bp->dev->dev_addr, fip_mac, ETH_ALEN);
 
-#endif
 	} else {
-		/* in SF read MACs from port configuration */
-		val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
-		val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
-		bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
-
-#ifdef BCM_CNIC
 		val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].
-				    iscsi_mac_upper);
+				iscsi_mac_upper);
 		val = SHMEM_RD(bp, dev_info.port_hw_config[port].
-				   iscsi_mac_lower);
+			       iscsi_mac_lower);
 		bnx2x_set_mac_buf(iscsi_mac, val, val2);
 
 		val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].
-				    fcoe_fip_mac_upper);
+				fcoe_fip_mac_upper);
 		val = SHMEM_RD(bp, dev_info.port_hw_config[port].
-				   fcoe_fip_mac_lower);
+			       fcoe_fip_mac_lower);
 		bnx2x_set_mac_buf(fip_mac, val, val2);
-#endif
 	}
 
-	memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN);
-	memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
-
-#ifdef BCM_CNIC
-	/* Disable iSCSI if MAC configuration is
-	 * invalid.
-	 */
+	/* Disable iSCSI OOO if MAC configuration is invalid. */
 	if (!is_valid_ether_addr(iscsi_mac)) {
-		bp->flags |= NO_ISCSI_FLAG;
+		bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
 		memset(iscsi_mac, 0, ETH_ALEN);
 	}
 
-	/* Disable FCoE if MAC configuration is
-	 * invalid.
-	 */
+	/* Disable FCoE if MAC configuration is invalid. */
 	if (!is_valid_ether_addr(fip_mac)) {
 		bp->flags |= NO_FCOE_FLAG;
 		memset(bp->fip_mac, 0, ETH_ALEN);
 	}
-#endif
+}
+
+static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
+{
+	u32 val, val2;
+	int func = BP_ABS_FUNC(bp);
+	int port = BP_PORT(bp);
+
+	/* Zero primary MAC configuration */
+	memset(bp->dev->dev_addr, 0, ETH_ALEN);
+
+	if (BP_NOMCP(bp)) {
+		BNX2X_ERROR("warning: random MAC workaround active\n");
+		eth_hw_addr_random(bp->dev);
+	} else if (IS_MF(bp)) {
+		val2 = MF_CFG_RD(bp, func_mf_config[func].mac_upper);
+		val = MF_CFG_RD(bp, func_mf_config[func].mac_lower);
+		if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) &&
+		    (val != FUNC_MF_CFG_LOWERMAC_DEFAULT))
+			bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
+
+		if (CNIC_SUPPORT(bp))
+			bnx2x_get_cnic_mac_hwinfo(bp);
+	} else {
+		/* in SF read MACs from port configuration */
+		val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
+		val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
+		bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
+
+		if (CNIC_SUPPORT(bp))
+			bnx2x_get_cnic_mac_hwinfo(bp);
+	}
+
+	memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN);
+	memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
 
 	if (!bnx2x_is_valid_ether_addr(bp, bp->dev->dev_addr))
 		dev_err(&bp->pdev->dev,
@@ -10840,9 +11007,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
 	mutex_init(&bp->port.phy_mutex);
 	mutex_init(&bp->fw_mb_mutex);
 	spin_lock_init(&bp->stats_lock);
-#ifdef BCM_CNIC
-	mutex_init(&bp->cnic_mutex);
-#endif
+
 
 	INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
 	INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task);
@@ -10880,10 +11045,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
 		dev_err(&bp->pdev->dev, "MCP disabled, must load devices in order!\n");
 
 	bp->disable_tpa = disable_tpa;
-
-#ifdef BCM_CNIC
 	bp->disable_tpa |= IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp);
-#endif
 
 	/* Set TPA flags */
 	if (bp->disable_tpa) {
@@ -10917,12 +11079,10 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
 	bnx2x_dcbx_set_state(bp, true, BNX2X_DCBX_ENABLED_ON_NEG_ON);
 	bnx2x_dcbx_init_params(bp);
 
-#ifdef BCM_CNIC
 	if (CHIP_IS_E1x(bp))
 		bp->cnic_base_cl_id = FP_SB_MAX_E1x;
 	else
 		bp->cnic_base_cl_id = FP_SB_MAX_E2;
-#endif
 
 	/* multiple tx priority */
 	if (CHIP_IS_E1x(bp))
@@ -10932,6 +11092,16 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
 	if (CHIP_IS_E3B0(bp))
 		bp->max_cos = BNX2X_MULTI_TX_COS_E3B0;
 
+	/* We need at least one default status block for slow-path events,
+	 * second status block for the L2 queue, and a third status block for
+	 * CNIC if supproted.
+	 */
+	if (CNIC_SUPPORT(bp))
+		bp->min_msix_vec_cnt = 3;
+	else
+		bp->min_msix_vec_cnt = 2;
+	BNX2X_DEV_INFO("bp->min_msix_vec_cnt %d", bp->min_msix_vec_cnt);
+
 	return rc;
 }
 
@@ -11168,11 +11338,9 @@ void bnx2x_set_rx_mode(struct net_device *dev)
 	}
 
 	bp->rx_mode = rx_mode;
-#ifdef BCM_CNIC
 	/* handle ISCSI SD mode */
 	if (IS_MF_ISCSI_SD(bp))
 		bp->rx_mode = BNX2X_RX_MODE_NONE;
-#endif
 
 	/* Schedule the rx_mode command */
 	if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state)) {
@@ -11284,7 +11452,7 @@ static const struct net_device_ops bnx2x_netdev_ops = {
 #endif
 	.ndo_setup_tc		= bnx2x_setup_tc,
 
-#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
+#ifdef NETDEV_FCOE_WWNN
 	.ndo_fcoe_get_wwn	= bnx2x_fcoe_get_wwn,
 #endif
 };
@@ -11750,9 +11918,8 @@ static int bnx2x_set_qm_cid_count(struct bnx2x *bp)
 {
 	int cid_count = BNX2X_L2_MAX_CID(bp);
 
-#ifdef BCM_CNIC
-	cid_count += CNIC_CID_MAX;
-#endif
+	if (CNIC_SUPPORT(bp))
+		cid_count += CNIC_CID_MAX;
 	return roundup(cid_count, QM_CID_ROUND);
 }
 
@@ -11762,7 +11929,8 @@ static int bnx2x_set_qm_cid_count(struct bnx2x *bp)
  * @dev:	pci device
  *
  */
-static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev)
+static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev,
+				     int cnic_cnt)
 {
 	int pos;
 	u16 control;
@@ -11774,7 +11942,7 @@ static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev)
 	 * one fast path queue: one FP queue + SB for CNIC
 	 */
 	if (!pos)
-		return 1 + CNIC_PRESENT;
+		return 1 + cnic_cnt;
 
 	/*
 	 * The value in the PCI configuration space is the index of the last
@@ -11794,6 +11962,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 	int pcie_width, pcie_speed;
 	int rc, max_non_def_sbs;
 	int rx_count, tx_count, rss_count, doorbell_size;
+	int cnic_cnt;
 	/*
 	 * An estimated maximum supported CoS number according to the chip
 	 * version.
@@ -11837,21 +12006,22 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 		return -ENODEV;
 	}
 
-	max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev);
+	cnic_cnt = 1;
+	max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev, cnic_cnt);
 
 	WARN_ON(!max_non_def_sbs);
 
 	/* Maximum number of RSS queues: one IGU SB goes to CNIC */
-	rss_count = max_non_def_sbs - CNIC_PRESENT;
+	rss_count = max_non_def_sbs - cnic_cnt;
 
 	/* Maximum number of netdev Rx queues: RSS + FCoE L2 */
-	rx_count = rss_count + FCOE_PRESENT;
+	rx_count = rss_count + cnic_cnt;
 
 	/*
 	 * Maximum number of netdev Tx queues:
 	 * Maximum TSS queues * Maximum supported number of CoS  + FCoE L2
 	 */
-	tx_count = rss_count * max_cos_est + FCOE_PRESENT;
+	tx_count = rss_count * max_cos_est + cnic_cnt;
 
 	/* dev zeroed in init_etherdev */
 	dev = alloc_etherdev_mqs(sizeof(*bp), tx_count, rx_count);
@@ -11862,6 +12032,8 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 
 	bp->igu_sb_cnt = max_non_def_sbs;
 	bp->msg_enable = debug;
+	bp->cnic_support = cnic_cnt;
+
 	pci_set_drvdata(pdev, dev);
 
 	rc = bnx2x_init_dev(pdev, dev, ent->driver_data);
@@ -11870,6 +12042,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 		return rc;
 	}
 
+	BNX2X_DEV_INFO("Cnic support is %s\n", CNIC_SUPPORT(bp) ? "on" : "off");
 	BNX2X_DEV_INFO("max_non_def_sbs %d\n", max_non_def_sbs);
 
 	BNX2X_DEV_INFO("Allocated netdev with %d tx and %d rx queues\n",
@@ -11902,10 +12075,10 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 	/* calc qm_cid_count */
 	bp->qm_cid_count = bnx2x_set_qm_cid_count(bp);
 
-#ifdef BCM_CNIC
-	/* disable FCOE L2 queue for E1x */
+	/* disable FCOE L2 queue for E1x*/
 	if (CHIP_IS_E1x(bp))
 		bp->flags |= NO_FCOE_FLAG;
+
 	/* disable FCOE for 57840 device, until FW supports it */
 	switch (ent->driver_data) {
 	case BCM57840_O:
@@ -11915,8 +12088,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 	case BCM57840_MF:
 		bp->flags |= NO_FCOE_FLAG;
 	}
-#endif
-
 
 	/* Set bp->num_queues for MSI-X mode*/
 	bnx2x_set_num_queues(bp);
@@ -11932,14 +12103,13 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 		goto init_one_exit;
 	}
 
-#ifdef BCM_CNIC
+
 	if (!NO_FCOE(bp)) {
 		/* Add storage MAC address */
 		rtnl_lock();
 		dev_addr_add(bp->dev, bp->fip_mac, NETDEV_HW_ADDR_T_SAN);
 		rtnl_unlock();
 	}
-#endif
 
 	bnx2x_get_pcie_width_speed(bp, &pcie_width, &pcie_speed);
 
@@ -11984,14 +12154,12 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
 	}
 	bp = netdev_priv(dev);
 
-#ifdef BCM_CNIC
 	/* Delete storage MAC address */
 	if (!NO_FCOE(bp)) {
 		rtnl_lock();
 		dev_addr_del(bp->dev, bp->fip_mac, NETDEV_HW_ADDR_T_SAN);
 		rtnl_unlock();
 	}
-#endif
 
 #ifdef BCM_DCBNL
 	/* Delete app tlvs from dcbnl */
@@ -12039,15 +12207,17 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
 
 	bp->rx_mode = BNX2X_RX_MODE_NONE;
 
-#ifdef BCM_CNIC
-	bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
-#endif
+	if (CNIC_LOADED(bp))
+		bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
+
 	/* Stop Tx */
 	bnx2x_tx_disable(bp);
 
 	bnx2x_netif_stop(bp, 0);
 	/* Delete all NAPI objects */
 	bnx2x_del_all_napi(bp);
+	if (CNIC_LOADED(bp))
+		bnx2x_del_all_napi_cnic(bp);
 
 	del_timer_sync(&bp->timer);
 
@@ -12238,7 +12408,6 @@ void bnx2x_notify_link_changed(struct bnx2x *bp)
 module_init(bnx2x_init);
 module_exit(bnx2x_cleanup);
 
-#ifdef BCM_CNIC
 /**
  * bnx2x_set_iscsi_eth_mac_addr - set iSCSI MAC(s).
  *
@@ -12691,12 +12860,31 @@ static int bnx2x_register_cnic(struct net_device *dev, struct cnic_ops *ops,
 {
 	struct bnx2x *bp = netdev_priv(dev);
 	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+	int rc;
+
+	DP(NETIF_MSG_IFUP, "Register_cnic called\n");
 
 	if (ops == NULL) {
 		BNX2X_ERR("NULL ops received\n");
 		return -EINVAL;
 	}
 
+	if (!CNIC_SUPPORT(bp)) {
+		BNX2X_ERR("Can't register CNIC when not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (!CNIC_LOADED(bp)) {
+		rc = bnx2x_load_cnic(bp);
+		if (rc) {
+			BNX2X_ERR("CNIC-related load failed\n");
+			return rc;
+		}
+
+	}
+
+	bp->cnic_enabled = true;
+
 	bp->cnic_kwq = kzalloc(PAGE_SIZE, GFP_KERNEL);
 	if (!bp->cnic_kwq)
 		return -ENOMEM;
@@ -12788,5 +12976,4 @@ struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
 }
 EXPORT_SYMBOL(bnx2x_cnic_probe);
 
-#endif /* BCM_CNIC */
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
index 1b1999d..f8d432a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
@@ -2107,6 +2107,7 @@
 #define NIG_REG_LLH1_ERROR_MASK 				 0x10090
 /* [RW 8] event id for llh1 */
 #define NIG_REG_LLH1_EVENT_ID					 0x10088
+#define NIG_REG_LLH1_FUNC_EN					 0x16104
 #define NIG_REG_LLH1_FUNC_MEM					 0x161c0
 #define NIG_REG_LLH1_FUNC_MEM_ENABLE				 0x16160
 #define NIG_REG_LLH1_FUNC_MEM_SIZE				 16
@@ -2302,6 +2303,15 @@
  * set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
  * accommodate the 9 input clients to ETS arbiter. */
 #define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB			 0x18684
+/* [RW 1] MCP-to-host path enable. Set this bit to enable the routing of MCP
+ * packets to BRB LB interface to forward the packet to the host. All
+ * packets from MCP are forwarded to the network when this bit is cleared -
+ * regardless of the configured destination in tx_mng_destination register.
+ * When MCP-to-host paths for both ports 0 and 1 are disabled - the arbiter
+ * for BRB LB interface is bypassed and PBF LB traffic is always selected to
+ * send to BRB LB.
+ */
+#define NIG_REG_P0_TX_MNG_HOST_ENABLE				 0x182f4
 #define NIG_REG_P1_HWPFC_ENABLE					 0x181d0
 #define NIG_REG_P1_MAC_IN_EN					 0x185c0
 /* [RW 1] Output enable for TX MAC interface */
@@ -2418,6 +2428,12 @@
 #define NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB			 0x186e4
 /* [R 1] TX FIFO for transmitting data to MAC is empty. */
 #define NIG_REG_P1_TX_MACFIFO_EMPTY				 0x18594
+/* [RW 1] MCP-to-host path enable. Set this bit to enable the routing of MCP
+ * packets to BRB LB interface to forward the packet to the host. All
+ * packets from MCP are forwarded to the network when this bit is cleared -
+ * regardless of the configured destination in tx_mng_destination register.
+ */
+#define NIG_REG_P1_TX_MNG_HOST_ENABLE				 0x182f8
 /* [R 1] FIFO empty status of the MCP TX FIFO used for storing MCP packets
    forwarded to the host. */
 #define NIG_REG_P1_TX_MNG_HOST_FIFO_EMPTY			 0x182b8
@@ -5482,6 +5498,7 @@
 #define XMAC_CTRL_REG_RX_EN					 (0x1<<1)
 #define XMAC_CTRL_REG_SOFT_RESET				 (0x1<<6)
 #define XMAC_CTRL_REG_TX_EN					 (0x1<<0)
+#define XMAC_CTRL_REG_XLGMII_ALIGN_ENB				 (0x1<<7)
 #define XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN				 (0x1<<18)
 #define XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN				 (0x1<<17)
 #define XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON			 (0x1<<1)
@@ -5502,11 +5519,14 @@
 #define XMAC_REG_PAUSE_CTRL					 0x68
 #define XMAC_REG_PFC_CTRL					 0x70
 #define XMAC_REG_PFC_CTRL_HI					 0x74
+#define XMAC_REG_RX_LSS_CTRL					 0x50
 #define XMAC_REG_RX_LSS_STATUS					 0x58
 /* [RW 14] Maximum packet size in receive direction; exclusive of preamble &
  * CRC in strip mode */
 #define XMAC_REG_RX_MAX_SIZE					 0x40
 #define XMAC_REG_TX_CTRL					 0x20
+#define XMAC_RX_LSS_CTRL_REG_LOCAL_FAULT_DISABLE		 (0x1<<0)
+#define XMAC_RX_LSS_CTRL_REG_REMOTE_FAULT_DISABLE		 (0x1<<1)
 /* [RW 16] Indirect access to the XX table of the XX protection mechanism.
    The fields are:[4:0] - tail pointer; 9:5] - Link List size; 14:10] -
    header pointer. */
@@ -6672,6 +6692,7 @@
 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI	0x1B00
 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS	0x1E00
 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI	0x1F00
+#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_KR2	0x3900
 
 
 #define MDIO_REG_BANK_10G_PARALLEL_DETECT		0x8130
@@ -7046,7 +7067,8 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT2	0x12
 #define MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_ABILITY	0x4000
 #define MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_REQ		0x8000
-#define MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150  0x96
+#define MDIO_WC_REG_PCS_STATUS2				0x0021
+#define MDIO_WC_REG_PMD_KR_CONTROL			0x0096
 #define MDIO_WC_REG_XGXSBLK0_XGXSCONTROL		0x8000
 #define MDIO_WC_REG_XGXSBLK0_MISCCONTROL1		0x800e
 #define MDIO_WC_REG_XGXSBLK1_DESKEW			0x8010
@@ -7078,6 +7100,7 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_PAR_DET_10G_STATUS			0x8130
 #define MDIO_WC_REG_PAR_DET_10G_CTRL			0x8131
 #define MDIO_WC_REG_XGXS_X2_CONTROL2			0x8141
+#define MDIO_WC_REG_XGXS_X2_CONTROL3			0x8142
 #define MDIO_WC_REG_XGXS_RX_LN_SWAP1			0x816B
 #define MDIO_WC_REG_XGXS_TX_LN_SWAP1			0x8169
 #define MDIO_WC_REG_GP2_STATUS_GP_2_0			0x81d0
@@ -7112,6 +7135,7 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET		0x0a
 #define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_MASK		0x7c00
 #define MDIO_WC_REG_TX_FIR_TAP_ENABLE		0x8000
+#define MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP		0x82e2
 #define MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL	0x82e3
 #define MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL	0x82e6
 #define MDIO_WC_REG_CL72_USERB0_CL72_BR_DEF_CTRL	0x82e7
@@ -7129,9 +7153,16 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_DIGITAL4_MISC5			0x833e
 #define MDIO_WC_REG_DIGITAL5_MISC6			0x8345
 #define MDIO_WC_REG_DIGITAL5_MISC7			0x8349
+#define MDIO_WC_REG_DIGITAL5_LINK_STATUS		0x834d
 #define MDIO_WC_REG_DIGITAL5_ACTUAL_SPEED		0x834e
 #define MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL		0x8350
 #define MDIO_WC_REG_CL49_USERB0_CTRL			0x8368
+#define MDIO_WC_REG_CL73_USERB0_CTRL			0x8370
+#define MDIO_WC_REG_CL73_USERB0_USTAT			0x8371
+#define MDIO_WC_REG_CL73_BAM_CTRL1			0x8372
+#define MDIO_WC_REG_CL73_BAM_CTRL2			0x8373
+#define MDIO_WC_REG_CL73_BAM_CTRL3			0x8374
+#define MDIO_WC_REG_CL73_BAM_CODE_FIELD			0x837b
 #define MDIO_WC_REG_EEE_COMBO_CONTROL0			0x8390
 #define MDIO_WC_REG_TX66_CONTROL			0x83b0
 #define MDIO_WC_REG_RX66_CONTROL			0x83c0
@@ -7145,7 +7176,17 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_RX66_SCW3_MASK			0x83c9
 #define MDIO_WC_REG_FX100_CTRL1				0x8400
 #define MDIO_WC_REG_FX100_CTRL3				0x8402
-
+#define MDIO_WC_REG_CL82_USERB1_TX_CTRL5		0x8436
+#define MDIO_WC_REG_CL82_USERB1_TX_CTRL6		0x8437
+#define MDIO_WC_REG_CL82_USERB1_TX_CTRL7		0x8438
+#define MDIO_WC_REG_CL82_USERB1_TX_CTRL9		0x8439
+#define MDIO_WC_REG_CL82_USERB1_RX_CTRL10		0x843a
+#define MDIO_WC_REG_CL82_USERB1_RX_CTRL11		0x843b
+#define MDIO_WC_REG_ETA_CL73_OUI1			0x8453
+#define MDIO_WC_REG_ETA_CL73_OUI2			0x8454
+#define MDIO_WC_REG_ETA_CL73_OUI3			0x8455
+#define MDIO_WC_REG_ETA_CL73_LD_BAM_CODE		0x8456
+#define MDIO_WC_REG_ETA_CL73_LD_UD_CODE			0x8457
 #define MDIO_WC_REG_MICROBLK_CMD			0xffc2
 #define MDIO_WC_REG_MICROBLK_DL_STATUS			0xffc5
 #define MDIO_WC_REG_MICROBLK_CMD3			0xffcc
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index 614981c..09b625e 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
@@ -4318,7 +4318,7 @@ static int bnx2x_queue_comp_cmd(struct bnx2x *bp,
 
 	if (o->next_tx_only >= o->max_cos)
 		/* >= becuase tx only must always be smaller than cos since the
-		 * primary connection suports COS 0
+		 * primary connection supports COS 0
 		 */
 		BNX2X_ERR("illegal value for next tx_only: %d. max cos was %d",
 			   o->next_tx_only, o->max_cos);
@@ -5350,12 +5350,24 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp,
 		else if ((cmd == BNX2X_F_CMD_AFEX_VIFLISTS) &&
 			 (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
 			next_state = BNX2X_F_STATE_STARTED;
+
+		/* Switch_update ramrod can be sent in either started or
+		 * tx_stopped state, and it doesn't change the state.
+		 */
+		else if ((cmd == BNX2X_F_CMD_SWITCH_UPDATE) &&
+			 (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
+			next_state = BNX2X_F_STATE_STARTED;
+
 		else if (cmd == BNX2X_F_CMD_TX_STOP)
 			next_state = BNX2X_F_STATE_TX_STOPPED;
 
 		break;
 	case BNX2X_F_STATE_TX_STOPPED:
-		if (cmd == BNX2X_F_CMD_TX_START)
+		if ((cmd == BNX2X_F_CMD_SWITCH_UPDATE) &&
+		    (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
+			next_state = BNX2X_F_STATE_TX_STOPPED;
+
+		else if (cmd == BNX2X_F_CMD_TX_START)
 			next_state = BNX2X_F_STATE_STARTED;
 
 		break;
@@ -5637,6 +5649,28 @@ static inline int bnx2x_func_send_start(struct bnx2x *bp,
 			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
 }
 
+static inline int bnx2x_func_send_switch_update(struct bnx2x *bp,
+					struct bnx2x_func_state_params *params)
+{
+	struct bnx2x_func_sp_obj *o = params->f_obj;
+	struct function_update_data *rdata =
+		(struct function_update_data *)o->rdata;
+	dma_addr_t data_mapping = o->rdata_mapping;
+	struct bnx2x_func_switch_update_params *switch_update_params =
+		&params->params.switch_update;
+
+	memset(rdata, 0, sizeof(*rdata));
+
+	/* Fill the ramrod data with provided parameters */
+	rdata->tx_switch_suspend_change_flg = 1;
+	rdata->tx_switch_suspend = switch_update_params->suspend;
+	rdata->echo = SWITCH_UPDATE;
+
+	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0,
+			     U64_HI(data_mapping),
+			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
+}
+
 static inline int bnx2x_func_send_afex_update(struct bnx2x *bp,
 					 struct bnx2x_func_state_params *params)
 {
@@ -5657,6 +5691,7 @@ static inline int bnx2x_func_send_afex_update(struct bnx2x *bp,
 		cpu_to_le16(afex_update_params->afex_default_vlan);
 	rdata->allowed_priorities_change_flg = 1;
 	rdata->allowed_priorities = afex_update_params->allowed_priorities;
+	rdata->echo = AFEX_UPDATE;
 
 	/*  No need for an explicit memory barrier here as long we would
 	 *  need to ensure the ordering of writing to the SPQ element
@@ -5773,6 +5808,8 @@ static int bnx2x_func_send_cmd(struct bnx2x *bp,
 		return bnx2x_func_send_tx_stop(bp, params);
 	case BNX2X_F_CMD_TX_START:
 		return bnx2x_func_send_tx_start(bp, params);
+	case BNX2X_F_CMD_SWITCH_UPDATE:
+		return bnx2x_func_send_switch_update(bp, params);
 	default:
 		BNX2X_ERR("Unknown command: %d\n", params->cmd);
 		return -EINVAL;
@@ -5818,16 +5855,30 @@ int bnx2x_func_state_change(struct bnx2x *bp,
 			    struct bnx2x_func_state_params *params)
 {
 	struct bnx2x_func_sp_obj *o = params->f_obj;
-	int rc;
+	int rc, cnt = 300;
 	enum bnx2x_func_cmd cmd = params->cmd;
 	unsigned long *pending = &o->pending;
 
 	mutex_lock(&o->one_pending_mutex);
 
 	/* Check that the requested transition is legal */
-	if (o->check_transition(bp, o, params)) {
+	rc = o->check_transition(bp, o, params);
+	if ((rc == -EBUSY) &&
+	    (test_bit(RAMROD_RETRY, &params->ramrod_flags))) {
+		while ((rc == -EBUSY) && (--cnt > 0)) {
+			mutex_unlock(&o->one_pending_mutex);
+			msleep(10);
+			mutex_lock(&o->one_pending_mutex);
+			rc = o->check_transition(bp, o, params);
+		}
+		if (rc == -EBUSY) {
+			mutex_unlock(&o->one_pending_mutex);
+			BNX2X_ERR("timeout waiting for previous ramrod completion\n");
+			return rc;
+		}
+	} else if (rc) {
 		mutex_unlock(&o->one_pending_mutex);
-		return -EINVAL;
+		return rc;
 	}
 
 	/* Set "pending" bit */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
index acf2fe4..adbd91b 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
@@ -40,6 +40,12 @@ enum {
 	 * pending commands list.
 	 */
 	RAMROD_CONT,
+	/* If there is another pending ramrod, wait until it finishes and
+	 * re-try to submit this one. This flag can be set only in sleepable
+	 * context, and should not be set from the context that completes the
+	 * ramrods as deadlock will occur.
+	 */
+	RAMROD_RETRY,
 };
 
 typedef enum {
@@ -1061,6 +1067,7 @@ enum bnx2x_func_cmd {
 	BNX2X_F_CMD_AFEX_VIFLISTS,
 	BNX2X_F_CMD_TX_STOP,
 	BNX2X_F_CMD_TX_START,
+	BNX2X_F_CMD_SWITCH_UPDATE,
 	BNX2X_F_CMD_MAX,
 };
 
@@ -1103,6 +1110,10 @@ struct bnx2x_func_start_params {
 	u8 network_cos_mode;
 };
 
+struct bnx2x_func_switch_update_params {
+	u8 suspend;
+};
+
 struct bnx2x_func_afex_update_params {
 	u16 vif_id;
 	u16 afex_default_vlan;
@@ -1136,6 +1147,7 @@ struct bnx2x_func_state_params {
 		struct bnx2x_func_hw_init_params hw_init;
 		struct bnx2x_func_hw_reset_params hw_reset;
 		struct bnx2x_func_start_params start;
+		struct bnx2x_func_switch_update_params switch_update;
 		struct bnx2x_func_afex_update_params afex_update;
 		struct bnx2x_func_afex_viflists_params afex_viflists;
 		struct bnx2x_func_tx_start_params tx_start;
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index a8800ac..5cc976d 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -90,10 +90,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 
 #define DRV_MODULE_NAME		"tg3"
 #define TG3_MAJ_NUM			3
-#define TG3_MIN_NUM			125
+#define TG3_MIN_NUM			127
 #define DRV_MODULE_VERSION	\
 	__stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE	"September 26, 2012"
+#define DRV_MODULE_RELDATE	"November 14, 2012"
 
 #define RESET_KIND_SHUTDOWN	0
 #define RESET_KIND_INIT		1
@@ -226,6 +226,9 @@ static int tg3_debug = -1;	/* -1 == use TG3_DEF_MSG_ENABLE as value */
 module_param(tg3_debug, int, 0);
 MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value");
 
+#define TG3_DRV_DATA_FLAG_10_100_ONLY	0x0001
+#define TG3_DRV_DATA_FLAG_5705_10_100	0x0002
+
 static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)},
@@ -245,20 +248,28 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901),
+	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY |
+			TG3_DRV_DATA_FLAG_5705_10_100},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2),
+	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY |
+			TG3_DRV_DATA_FLAG_5705_10_100},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F),
+	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY |
+			TG3_DRV_DATA_FLAG_5705_10_100},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5722)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F),
+	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F),
+	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755)},
@@ -266,8 +277,13 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5756)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)},
+	{PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5787M,
+			PCI_VENDOR_ID_LENOVO,
+			TG3PCI_SUBDEVICE_ID_LENOVO_5787M),
+	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F),
+	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715)},
@@ -286,18 +302,28 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761SE)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_G)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_F)},
+	{PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780,
+			PCI_VENDOR_ID_AI, TG3PCI_SUBDEVICE_ID_ACER_57780_A),
+	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
+	{PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780,
+			PCI_VENDOR_ID_AI, TG3PCI_SUBDEVICE_ID_ACER_57780_B),
+	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57760)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790),
+	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57788)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717_C)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5718)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57781)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57785)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57761)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57765)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791)},
-	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791),
+	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795),
+	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57762)},
@@ -398,19 +424,27 @@ static const struct {
 };
 
 #define TG3_NUM_STATS	ARRAY_SIZE(ethtool_stats_keys)
+#define TG3_NVRAM_TEST		0
+#define TG3_LINK_TEST		1
+#define TG3_REGISTER_TEST	2
+#define TG3_MEMORY_TEST		3
+#define TG3_MAC_LOOPB_TEST	4
+#define TG3_PHY_LOOPB_TEST	5
+#define TG3_EXT_LOOPB_TEST	6
+#define TG3_INTERRUPT_TEST	7
 
 
 static const struct {
 	const char string[ETH_GSTRING_LEN];
 } ethtool_test_keys[] = {
-	{ "nvram test        (online) " },
-	{ "link test         (online) " },
-	{ "register test     (offline)" },
-	{ "memory test       (offline)" },
-	{ "mac loopback test (offline)" },
-	{ "phy loopback test (offline)" },
-	{ "ext loopback test (offline)" },
-	{ "interrupt test    (offline)" },
+	[TG3_NVRAM_TEST]	= { "nvram test        (online) " },
+	[TG3_LINK_TEST]		= { "link test         (online) " },
+	[TG3_REGISTER_TEST]	= { "register test     (offline)" },
+	[TG3_MEMORY_TEST]	= { "memory test       (offline)" },
+	[TG3_MAC_LOOPB_TEST]	= { "mac loopback test (offline)" },
+	[TG3_PHY_LOOPB_TEST]	= { "phy loopback test (offline)" },
+	[TG3_EXT_LOOPB_TEST]	= { "ext loopback test (offline)" },
+	[TG3_INTERRUPT_TEST]	= { "interrupt test    (offline)" },
 };
 
 #define TG3_NUM_TEST	ARRAY_SIZE(ethtool_test_keys)
@@ -2447,6 +2481,18 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
 	return err;
 }
 
+static void tg3_carrier_on(struct tg3 *tp)
+{
+	netif_carrier_on(tp->dev);
+	tp->link_up = true;
+}
+
+static void tg3_carrier_off(struct tg3 *tp)
+{
+	netif_carrier_off(tp->dev);
+	tp->link_up = false;
+}
+
 /* This will reset the tigon3 PHY if there is no valid
  * link unless the FORCE argument is non-zero.
  */
@@ -2465,8 +2511,8 @@ static int tg3_phy_reset(struct tg3 *tp)
 	if (err != 0)
 		return -EBUSY;
 
-	if (netif_running(tp->dev) && netif_carrier_ok(tp->dev)) {
-		netif_carrier_off(tp->dev);
+	if (netif_running(tp->dev) && tp->link_up) {
+		tg3_carrier_off(tp);
 		tg3_link_report(tp);
 	}
 
@@ -4160,6 +4206,24 @@ static bool tg3_phy_copper_fetch_rmtadv(struct tg3 *tp, u32 *rmtadv)
 	return true;
 }
 
+static bool tg3_test_and_report_link_chg(struct tg3 *tp, int curr_link_up)
+{
+	if (curr_link_up != tp->link_up) {
+		if (curr_link_up) {
+			tg3_carrier_on(tp);
+		} else {
+			tg3_carrier_off(tp);
+			if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
+				tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
+		}
+
+		tg3_link_report(tp);
+		return true;
+	}
+
+	return false;
+}
+
 static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 {
 	int current_link_up;
@@ -4192,7 +4256,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
 	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
 	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
-	    netif_carrier_ok(tp->dev)) {
+	    tp->link_up) {
 		tg3_readphy(tp, MII_BMSR, &bmsr);
 		if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
 		    !(bmsr & BMSR_LSTATUS))
@@ -4434,13 +4498,7 @@ relink:
 						 PCI_EXP_LNKCTL_CLKREQ_EN);
 	}
 
-	if (current_link_up != netif_carrier_ok(tp->dev)) {
-		if (current_link_up)
-			netif_carrier_on(tp->dev);
-		else
-			netif_carrier_off(tp->dev);
-		tg3_link_report(tp);
-	}
+	tg3_test_and_report_link_chg(tp, current_link_up);
 
 	return 0;
 }
@@ -5080,7 +5138,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
 	orig_active_duplex = tp->link_config.active_duplex;
 
 	if (!tg3_flag(tp, HW_AUTONEG) &&
-	    netif_carrier_ok(tp->dev) &&
+	    tp->link_up &&
 	    tg3_flag(tp, INIT_COMPLETE)) {
 		mac_status = tr32(MAC_STATUS);
 		mac_status &= (MAC_STATUS_PCS_SYNCED |
@@ -5158,13 +5216,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
 				    LED_CTRL_TRAFFIC_OVERRIDE));
 	}
 
-	if (current_link_up != netif_carrier_ok(tp->dev)) {
-		if (current_link_up)
-			netif_carrier_on(tp->dev);
-		else
-			netif_carrier_off(tp->dev);
-		tg3_link_report(tp);
-	} else {
+	if (!tg3_test_and_report_link_chg(tp, current_link_up)) {
 		u32 now_pause_cfg = tp->link_config.active_flowctrl;
 		if (orig_pause_cfg != now_pause_cfg ||
 		    orig_active_speed != tp->link_config.active_speed ||
@@ -5257,7 +5309,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
 			new_bmcr |= BMCR_SPEED1000;
 
 			/* Force a linkdown */
-			if (netif_carrier_ok(tp->dev)) {
+			if (tp->link_up) {
 				u32 adv;
 
 				err |= tg3_readphy(tp, MII_ADVERTISE, &adv);
@@ -5269,7 +5321,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
 							   BMCR_ANRESTART |
 							   BMCR_ANENABLE);
 				udelay(10);
-				netif_carrier_off(tp->dev);
+				tg3_carrier_off(tp);
 			}
 			tg3_writephy(tp, MII_BMCR, new_bmcr);
 			bmcr = new_bmcr;
@@ -5335,15 +5387,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
 	tp->link_config.active_speed = current_speed;
 	tp->link_config.active_duplex = current_duplex;
 
-	if (current_link_up != netif_carrier_ok(tp->dev)) {
-		if (current_link_up)
-			netif_carrier_on(tp->dev);
-		else {
-			netif_carrier_off(tp->dev);
-			tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
-		}
-		tg3_link_report(tp);
-	}
+	tg3_test_and_report_link_chg(tp, current_link_up);
 	return err;
 }
 
@@ -5355,7 +5399,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp)
 		return;
 	}
 
-	if (!netif_carrier_ok(tp->dev) &&
+	if (!tp->link_up &&
 	    (tp->link_config.autoneg == AUTONEG_ENABLE)) {
 		u32 bmcr;
 
@@ -5385,7 +5429,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp)
 				tp->phy_flags |= TG3_PHYFLG_PARALLEL_DETECT;
 			}
 		}
-	} else if (netif_carrier_ok(tp->dev) &&
+	} else if (tp->link_up &&
 		   (tp->link_config.autoneg == AUTONEG_ENABLE) &&
 		   (tp->phy_flags & TG3_PHYFLG_PARALLEL_DETECT)) {
 		u32 phy2;
@@ -5451,7 +5495,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
 		     (32 << TX_LENGTHS_SLOT_TIME_SHIFT));
 
 	if (!tg3_flag(tp, 5705_PLUS)) {
-		if (netif_carrier_ok(tp->dev)) {
+		if (tp->link_up) {
 			tw32(HOSTCC_STAT_COAL_TICKS,
 			     tp->coal.stats_block_coalesce_usecs);
 		} else {
@@ -5461,7 +5505,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
 
 	if (tg3_flag(tp, ASPM_WORKAROUND)) {
 		val = tr32(PCIE_PWR_MGMT_THRESH);
-		if (!netif_carrier_ok(tp->dev))
+		if (!tp->link_up)
 			val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK) |
 			      tp->pwrmgmt_thresh;
 		else
@@ -6477,6 +6521,7 @@ static inline void tg3_netif_stop(struct tg3 *tp)
 {
 	tp->dev->trans_start = jiffies;	/* prevent tx timeout */
 	tg3_napi_disable(tp);
+	netif_carrier_off(tp->dev);
 	netif_tx_disable(tp->dev);
 }
 
@@ -6488,6 +6533,9 @@ static inline void tg3_netif_start(struct tg3 *tp)
 	 */
 	netif_tx_wake_all_queues(tp->dev);
 
+	if (tp->link_up)
+		netif_carrier_on(tp->dev);
+
 	tg3_napi_enable(tp);
 	tp->napi[0].hw_status->status |= SD_STATUS_UPDATED;
 	tg3_enable_ints(tp);
@@ -8386,7 +8434,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
 		tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq);
 		tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq);
 
-		if (!netif_carrier_ok(tp->dev))
+		if (!tp->link_up)
 			val = 0;
 
 		tw32(HOSTCC_STAT_COAL_TICKS, val);
@@ -8662,14 +8710,14 @@ static void tg3_rss_check_indir_tbl(struct tg3 *tp)
 	if (!tg3_flag(tp, SUPPORT_MSIX))
 		return;
 
-	if (tp->irq_cnt <= 2) {
+	if (tp->rxq_cnt == 1) {
 		memset(&tp->rss_ind_tbl[0], 0, sizeof(tp->rss_ind_tbl));
 		return;
 	}
 
 	/* Validate table against current IRQ count */
 	for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) {
-		if (tp->rss_ind_tbl[i] >= tp->irq_cnt - 1)
+		if (tp->rss_ind_tbl[i] >= tp->rxq_cnt)
 			break;
 	}
 
@@ -9679,7 +9727,7 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp)
 {
 	struct tg3_hw_stats *sp = tp->hw_stats;
 
-	if (!netif_carrier_ok(tp->dev))
+	if (!tp->link_up)
 		return;
 
 	TG3_STAT_ADD32(&sp->tx_octets, MAC_TX_STATS_OCTETS);
@@ -9823,11 +9871,11 @@ static void tg3_timer(unsigned long __opaque)
 			u32 mac_stat = tr32(MAC_STATUS);
 			int need_setup = 0;
 
-			if (netif_carrier_ok(tp->dev) &&
+			if (tp->link_up &&
 			    (mac_stat & MAC_STATUS_LNKSTATE_CHANGED)) {
 				need_setup = 1;
 			}
-			if (!netif_carrier_ok(tp->dev) &&
+			if (!tp->link_up &&
 			    (mac_stat & (MAC_STATUS_PCS_SYNCED |
 					 MAC_STATUS_SIGNAL_DET))) {
 				need_setup = 1;
@@ -10429,10 +10477,8 @@ static void tg3_stop(struct tg3 *tp)
 {
 	int i;
 
-	tg3_napi_disable(tp);
 	tg3_reset_task_cancel(tp);
-
-	netif_tx_disable(tp->dev);
+	tg3_netif_stop(tp);
 
 	tg3_timer_stop(tp);
 
@@ -10481,7 +10527,7 @@ static int tg3_open(struct net_device *dev)
 		}
 	}
 
-	netif_carrier_off(tp->dev);
+	tg3_carrier_off(tp);
 
 	err = tg3_power_up(tp);
 	if (err)
@@ -10514,7 +10560,7 @@ static int tg3_close(struct net_device *dev)
 
 	tg3_power_down(tp);
 
-	netif_carrier_off(tp->dev);
+	tg3_carrier_off(tp);
 
 	return 0;
 }
@@ -10888,7 +10934,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 			cmd->advertising |= ADVERTISED_Asym_Pause;
 		}
 	}
-	if (netif_running(dev) && netif_carrier_ok(dev)) {
+	if (netif_running(dev) && tp->link_up) {
 		ethtool_cmd_speed_set(cmd, tp->link_config.active_speed);
 		cmd->duplex = tp->link_config.active_duplex;
 		cmd->lp_advertising = tp->link_config.rmt_adv;
@@ -11406,7 +11452,7 @@ static int tg3_set_channels(struct net_device *dev,
 
 	tg3_stop(tp);
 
-	netif_carrier_off(dev);
+	tg3_carrier_off(tp);
 
 	tg3_start(tp, true, false);
 
@@ -11755,7 +11801,7 @@ static int tg3_test_link(struct tg3 *tp)
 		max = TG3_COPPER_TIMEOUT_SEC;
 
 	for (i = 0; i < max; i++) {
-		if (netif_carrier_ok(tp->dev))
+		if (tp->link_up)
 			return 0;
 
 		if (msleep_interruptible(1000))
@@ -12326,19 +12372,19 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
 	tp->phy_flags &= ~TG3_PHYFLG_EEE_CAP;
 
 	if (!netif_running(tp->dev)) {
-		data[0] = TG3_LOOPBACK_FAILED;
-		data[1] = TG3_LOOPBACK_FAILED;
+		data[TG3_MAC_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
+		data[TG3_PHY_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
 		if (do_extlpbk)
-			data[2] = TG3_LOOPBACK_FAILED;
+			data[TG3_EXT_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
 		goto done;
 	}
 
 	err = tg3_reset_hw(tp, 1);
 	if (err) {
-		data[0] = TG3_LOOPBACK_FAILED;
-		data[1] = TG3_LOOPBACK_FAILED;
+		data[TG3_MAC_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
+		data[TG3_PHY_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
 		if (do_extlpbk)
-			data[2] = TG3_LOOPBACK_FAILED;
+			data[TG3_EXT_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
 		goto done;
 	}
 
@@ -12361,11 +12407,11 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
 		tg3_mac_loopback(tp, true);
 
 		if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
-			data[0] |= TG3_STD_LOOPBACK_FAILED;
+			data[TG3_MAC_LOOPB_TEST] |= TG3_STD_LOOPBACK_FAILED;
 
 		if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
 		    tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false))
-			data[0] |= TG3_JMB_LOOPBACK_FAILED;
+			data[TG3_MAC_LOOPB_TEST] |= TG3_JMB_LOOPBACK_FAILED;
 
 		tg3_mac_loopback(tp, false);
 	}
@@ -12384,13 +12430,13 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
 		}
 
 		if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
-			data[1] |= TG3_STD_LOOPBACK_FAILED;
+			data[TG3_PHY_LOOPB_TEST] |= TG3_STD_LOOPBACK_FAILED;
 		if (tg3_flag(tp, TSO_CAPABLE) &&
 		    tg3_run_loopback(tp, ETH_FRAME_LEN, true))
-			data[1] |= TG3_TSO_LOOPBACK_FAILED;
+			data[TG3_PHY_LOOPB_TEST] |= TG3_TSO_LOOPBACK_FAILED;
 		if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
 		    tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false))
-			data[1] |= TG3_JMB_LOOPBACK_FAILED;
+			data[TG3_PHY_LOOPB_TEST] |= TG3_JMB_LOOPBACK_FAILED;
 
 		if (do_extlpbk) {
 			tg3_phy_lpbk_set(tp, 0, true);
@@ -12402,13 +12448,16 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
 			mdelay(40);
 
 			if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
-				data[2] |= TG3_STD_LOOPBACK_FAILED;
+				data[TG3_EXT_LOOPB_TEST] |=
+							TG3_STD_LOOPBACK_FAILED;
 			if (tg3_flag(tp, TSO_CAPABLE) &&
 			    tg3_run_loopback(tp, ETH_FRAME_LEN, true))
-				data[2] |= TG3_TSO_LOOPBACK_FAILED;
+				data[TG3_EXT_LOOPB_TEST] |=
+							TG3_TSO_LOOPBACK_FAILED;
 			if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
 			    tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false))
-				data[2] |= TG3_JMB_LOOPBACK_FAILED;
+				data[TG3_EXT_LOOPB_TEST] |=
+							TG3_JMB_LOOPBACK_FAILED;
 		}
 
 		/* Re-enable gphy autopowerdown. */
@@ -12416,7 +12465,8 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
 			tg3_phy_toggle_apd(tp, true);
 	}
 
-	err = (data[0] | data[1] | data[2]) ? -EIO : 0;
+	err = (data[TG3_MAC_LOOPB_TEST] | data[TG3_PHY_LOOPB_TEST] |
+	       data[TG3_EXT_LOOPB_TEST]) ? -EIO : 0;
 
 done:
 	tp->phy_flags |= eee_cap;
@@ -12441,11 +12491,11 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
 
 	if (tg3_test_nvram(tp) != 0) {
 		etest->flags |= ETH_TEST_FL_FAILED;
-		data[0] = 1;
+		data[TG3_NVRAM_TEST] = 1;
 	}
 	if (!doextlpbk && tg3_test_link(tp)) {
 		etest->flags |= ETH_TEST_FL_FAILED;
-		data[1] = 1;
+		data[TG3_LINK_TEST] = 1;
 	}
 	if (etest->flags & ETH_TEST_FL_OFFLINE) {
 		int err, err2 = 0, irq_sync = 0;
@@ -12471,25 +12521,25 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
 
 		if (tg3_test_registers(tp) != 0) {
 			etest->flags |= ETH_TEST_FL_FAILED;
-			data[2] = 1;
+			data[TG3_REGISTER_TEST] = 1;
 		}
 
 		if (tg3_test_memory(tp) != 0) {
 			etest->flags |= ETH_TEST_FL_FAILED;
-			data[3] = 1;
+			data[TG3_MEMORY_TEST] = 1;
 		}
 
 		if (doextlpbk)
 			etest->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
 
-		if (tg3_test_loopback(tp, &data[4], doextlpbk))
+		if (tg3_test_loopback(tp, data, doextlpbk))
 			etest->flags |= ETH_TEST_FL_FAILED;
 
 		tg3_full_unlock(tp);
 
 		if (tg3_test_interrupt(tp) != 0) {
 			etest->flags |= ETH_TEST_FL_FAILED;
-			data[7] = 1;
+			data[TG3_INTERRUPT_TEST] = 1;
 		}
 
 		tg3_full_lock(tp, 0);
@@ -14026,7 +14076,8 @@ out_not_found:
 
 out_no_vpd:
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
-		if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717)
+		if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
+		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717_C)
 			strcpy(tp->board_part_number, "BCM5717");
 		else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718)
 			strcpy(tp->board_part_number, "BCM5718");
@@ -14397,6 +14448,7 @@ static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
 		tg3_flag_set(tp, CPMU_PRESENT);
 
 		if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
+		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717_C ||
 		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
 		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 ||
 		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720)
@@ -14424,6 +14476,9 @@ static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW)
 		tp->pci_chip_rev_id = CHIPREV_ID_5752_A0;
 
+	if (tp->pci_chip_rev_id == CHIPREV_ID_5717_C0)
+		tp->pci_chip_rev_id = CHIPREV_ID_5720_A0;
+
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
@@ -14462,7 +14517,30 @@ static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
 		tg3_flag_set(tp, 5705_PLUS);
 }
 
-static int __devinit tg3_get_invariants(struct tg3 *tp)
+static bool tg3_10_100_only_device(struct tg3 *tp,
+				   const struct pci_device_id *ent)
+{
+	u32 grc_misc_cfg = tr32(GRC_MISC_CFG) & GRC_MISC_CFG_BOARD_ID_MASK;
+
+	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
+	    (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
+	    (tp->phy_flags & TG3_PHYFLG_IS_FET))
+		return true;
+
+	if (ent->driver_data & TG3_DRV_DATA_FLAG_10_100_ONLY) {
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+			if (ent->driver_data & TG3_DRV_DATA_FLAG_5705_10_100)
+				return true;
+		} else {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static int __devinit tg3_get_invariants(struct tg3 *tp,
+					const struct pci_device_id *ent)
 {
 	u32 misc_ctrl_reg;
 	u32 pci_state_reg, grc_misc_cfg;
@@ -15141,22 +15219,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	else
 		tp->mac_mode = 0;
 
-	/* these are limited to 10/100 only */
-	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
-	     (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
-	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
-	     tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
-	     (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901 ||
-	      tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 ||
-	      tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) ||
-	    (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
-	     (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F ||
-	      tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F ||
-	      tp->pdev->device == PCI_DEVICE_ID_TIGON3_5787F)) ||
-	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790 ||
-	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 ||
-	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795 ||
-	    (tp->phy_flags & TG3_PHYFLG_IS_FET))
+	if (tg3_10_100_only_device(tp, ent))
 		tp->phy_flags |= TG3_PHYFLG_10_100_ONLY;
 
 	err = tg3_phy_probe(tp);
@@ -16013,6 +16076,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S ||
 	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761SE ||
 	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
+	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717_C ||
 	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
 	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 ||
 	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720) {
@@ -16034,7 +16098,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 	dev->netdev_ops = &tg3_netdev_ops;
 	dev->irq = pdev->irq;
 
-	err = tg3_get_invariants(tp);
+	err = tg3_get_invariants(tp, ent);
 	if (err) {
 		dev_err(&pdev->dev,
 			"Problem fetching invariants of chip, aborting\n");
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index d9308c32..4534804 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -44,12 +44,14 @@
 #define  TG3PCI_DEVICE_TIGON3_5761S	 0x1688
 #define  TG3PCI_DEVICE_TIGON3_5761SE	 0x1689
 #define  TG3PCI_DEVICE_TIGON3_57780	 0x1692
+#define  TG3PCI_DEVICE_TIGON3_5787M	 0x1693
 #define  TG3PCI_DEVICE_TIGON3_57760	 0x1690
 #define  TG3PCI_DEVICE_TIGON3_57790	 0x1694
 #define  TG3PCI_DEVICE_TIGON3_57788	 0x1691
 #define  TG3PCI_DEVICE_TIGON3_5785_G	 0x1699 /* GPHY */
 #define  TG3PCI_DEVICE_TIGON3_5785_F	 0x16a0 /* 10/100 only */
 #define  TG3PCI_DEVICE_TIGON3_5717	 0x1655
+#define  TG3PCI_DEVICE_TIGON3_5717_C	 0x1665
 #define  TG3PCI_DEVICE_TIGON3_5718	 0x1656
 #define  TG3PCI_DEVICE_TIGON3_57781	 0x16b1
 #define  TG3PCI_DEVICE_TIGON3_57785	 0x16b5
@@ -95,6 +97,10 @@
 #define TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780_2	0x0099
 #define TG3PCI_SUBVENDOR_ID_IBM			PCI_VENDOR_ID_IBM
 #define TG3PCI_SUBDEVICE_ID_IBM_5703SAX2	0x0281
+#define TG3PCI_SUBDEVICE_ID_ACER_57780_A	0x0601
+#define TG3PCI_SUBDEVICE_ID_ACER_57780_B	0x0612
+#define TG3PCI_SUBDEVICE_ID_LENOVO_5787M	0x3056
+
 /* 0x30 --> 0x64 unused */
 #define TG3PCI_MSI_DATA			0x00000064
 /* 0x66 --> 0x68 unused */
@@ -149,6 +155,7 @@
 #define  CHIPREV_ID_57780_A0		 0x57780000
 #define  CHIPREV_ID_57780_A1		 0x57780001
 #define  CHIPREV_ID_5717_A0		 0x05717000
+#define  CHIPREV_ID_5717_C0		 0x05717200
 #define  CHIPREV_ID_57765_A0		 0x57785000
 #define  CHIPREV_ID_5719_A0		 0x05719000
 #define  CHIPREV_ID_5720_A0		 0x05720000
@@ -3262,6 +3269,7 @@ struct tg3 {
 #if IS_ENABLED(CONFIG_HWMON)
 	struct device			*hwmon_dev;
 #endif
+	bool				link_up;
 };
 
 #endif /* !(_T3_H) */
diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig
index db93191..ceb0de0 100644
--- a/drivers/net/ethernet/cadence/Kconfig
+++ b/drivers/net/ethernet/cadence/Kconfig
@@ -2,13 +2,10 @@
 # Atmel device configuration
 #
 
-config HAVE_NET_MACB
-	bool
-
 config NET_CADENCE
 	bool "Cadence devices"
+	depends on HAS_IOMEM
 	default y
-	depends on HAVE_NET_MACB || (ARM && ARCH_AT91RM9200)
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y.
 	  Make sure you know the name of your card. Read the Ethernet-HOWTO,
@@ -25,16 +22,14 @@ if NET_CADENCE
 
 config ARM_AT91_ETHER
 	tristate "AT91RM9200 Ethernet support"
-	depends on ARM && ARCH_AT91RM9200
 	select NET_CORE
-	select MII
+	select MACB
 	---help---
 	  If you wish to compile a kernel for the AT91RM9200 and enable
 	  ethernet support, then you should always answer Y to this.
 
 config MACB
 	tristate "Cadence MACB/GEM support"
-	depends on HAVE_NET_MACB
 	select PHYLIB
 	---help---
 	  The Cadence MACB ethernet interface is found on many Atmel AT32 and
diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c
index 4e980a7..716cc01 100644
--- a/drivers/net/ethernet/cadence/at91_ether.c
+++ b/drivers/net/ethernet/cadence/at91_ether.c
@@ -6,11 +6,6 @@
  * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
  * Initial version by Rick Bronson 01/11/2003
  *
- * Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker
- *   (Polaroid Corporation)
- *
- * Realtek RTL8201(B)L PHY support by Roman Avramenko <roman@imsystems.ru>
- *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version
@@ -20,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/mii.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
@@ -31,956 +25,248 @@
 #include <linux/clk.h>
 #include <linux/gfp.h>
 #include <linux/phy.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_net.h>
+#include <linux/pinctrl/consumer.h>
 
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/mach-types.h>
-
-#include <mach/at91rm9200_emac.h>
-#include <asm/gpio.h>
-#include <mach/board.h>
-
-#include "at91_ether.h"
-
-#define DRV_NAME	"at91_ether"
-#define DRV_VERSION	"1.0"
-
-#define LINK_POLL_INTERVAL	(HZ)
-
-/* ..................................................................... */
-
-/*
- * Read from a EMAC register.
- */
-static inline unsigned long at91_emac_read(struct at91_private *lp, unsigned int reg)
-{
-	return __raw_readl(lp->emac_base + reg);
-}
-
-/*
- * Write to a EMAC register.
- */
-static inline void at91_emac_write(struct at91_private *lp, unsigned int reg, unsigned long value)
-{
-	__raw_writel(value, lp->emac_base + reg);
-}
-
-/* ........................... PHY INTERFACE ........................... */
-
-/*
- * Enable the MDIO bit in MAC control register
- * When not called from an interrupt-handler, access to the PHY must be
- *  protected by a spinlock.
- */
-static void enable_mdi(struct at91_private *lp)
-{
-	unsigned long ctl;
-
-	ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-	at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_MPE);	/* enable management port */
-}
-
-/*
- * Disable the MDIO bit in the MAC control register
- */
-static void disable_mdi(struct at91_private *lp)
-{
-	unsigned long ctl;
-
-	ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-	at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE);	/* disable management port */
-}
-
-/*
- * Wait until the PHY operation is complete.
- */
-static inline void at91_phy_wait(struct at91_private *lp)
-{
-	unsigned long timeout = jiffies + 2;
-
-	while (!(at91_emac_read(lp, AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) {
-		if (time_after(jiffies, timeout)) {
-			printk("at91_ether: MIO timeout\n");
-			break;
-		}
-		cpu_relax();
-	}
-}
-
-/*
- * Write value to the a PHY register
- * Note: MDI interface is assumed to already have been enabled.
- */
-static void write_phy(struct at91_private *lp, unsigned char phy_addr, unsigned char address, unsigned int value)
-{
-	at91_emac_write(lp, AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W
-		| ((phy_addr & 0x1f) << 23) | (address << 18) | (value & AT91_EMAC_DATA));
-
-	/* Wait until IDLE bit in Network Status register is cleared */
-	at91_phy_wait(lp);
-}
-
-/*
- * Read value stored in a PHY register.
- * Note: MDI interface is assumed to already have been enabled.
- */
-static void read_phy(struct at91_private *lp, unsigned char phy_addr, unsigned char address, unsigned int *value)
-{
-	at91_emac_write(lp, AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R
-		| ((phy_addr & 0x1f) << 23) | (address << 18));
-
-	/* Wait until IDLE bit in Network Status register is cleared */
-	at91_phy_wait(lp);
-
-	*value = at91_emac_read(lp, AT91_EMAC_MAN) & AT91_EMAC_DATA;
-}
-
-/* ........................... PHY MANAGEMENT .......................... */
-
-/*
- * Access the PHY to determine the current link speed and mode, and update the
- * MAC accordingly.
- * If no link or auto-negotiation is busy, then no changes are made.
- */
-static void update_linkspeed(struct net_device *dev, int silent)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned int bmsr, bmcr, lpa, mac_cfg;
-	unsigned int speed, duplex;
-
-	if (!mii_link_ok(&lp->mii)) {		/* no link */
-		netif_carrier_off(dev);
-		if (!silent)
-			printk(KERN_INFO "%s: Link down.\n", dev->name);
-		return;
-	}
-
-	/* Link up, or auto-negotiation still in progress */
-	read_phy(lp, lp->phy_address, MII_BMSR, &bmsr);
-	read_phy(lp, lp->phy_address, MII_BMCR, &bmcr);
-	if (bmcr & BMCR_ANENABLE) {				/* AutoNegotiation is enabled */
-		if (!(bmsr & BMSR_ANEGCOMPLETE))
-			return;			/* Do nothing - another interrupt generated when negotiation complete */
-
-		read_phy(lp, lp->phy_address, MII_LPA, &lpa);
-		if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100;
-		else speed = SPEED_10;
-		if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL;
-		else duplex = DUPLEX_HALF;
-	} else {
-		speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
-		duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
-	}
-
-	/* Update the MAC */
-	mac_cfg = at91_emac_read(lp, AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD);
-	if (speed == SPEED_100) {
-		if (duplex == DUPLEX_FULL)		/* 100 Full Duplex */
-			mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD;
-		else					/* 100 Half Duplex */
-			mac_cfg |= AT91_EMAC_SPD;
-	} else {
-		if (duplex == DUPLEX_FULL)		/* 10 Full Duplex */
-			mac_cfg |= AT91_EMAC_FD;
-		else {}					/* 10 Half Duplex */
-	}
-	at91_emac_write(lp, AT91_EMAC_CFG, mac_cfg);
-
-	if (!silent)
-		printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
-	netif_carrier_on(dev);
-}
-
-/*
- * Handle interrupts from the PHY
- */
-static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = (struct net_device *) dev_id;
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned int phy;
-
-	/*
-	 * This hander is triggered on both edges, but the PHY chips expect
-	 * level-triggering.  We therefore have to check if the PHY actually has
-	 * an IRQ pending.
-	 */
-	enable_mdi(lp);
-	if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
-		read_phy(lp, lp->phy_address, MII_DSINTR_REG, &phy);	/* ack interrupt in Davicom PHY */
-		if (!(phy & (1 << 0)))
-			goto done;
-	}
-	else if (lp->phy_type == MII_LXT971A_ID) {
-		read_phy(lp, lp->phy_address, MII_ISINTS_REG, &phy);	/* ack interrupt in Intel PHY */
-		if (!(phy & (1 << 2)))
-			goto done;
-	}
-	else if (lp->phy_type == MII_BCM5221_ID) {
-		read_phy(lp, lp->phy_address, MII_BCMINTR_REG, &phy);	/* ack interrupt in Broadcom PHY */
-		if (!(phy & (1 << 0)))
-			goto done;
-	}
-	else if (lp->phy_type == MII_KS8721_ID) {
-		read_phy(lp, lp->phy_address, MII_TPISTATUS, &phy);		/* ack interrupt in Micrel PHY */
-		if (!(phy & ((1 << 2) | 1)))
-			goto done;
-	}
-	else if (lp->phy_type == MII_T78Q21x3_ID) {					/* ack interrupt in Teridian PHY */
-		read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &phy);
-		if (!(phy & ((1 << 2) | 1)))
-			goto done;
-	}
-	else if (lp->phy_type == MII_DP83848_ID) {
-		read_phy(lp, lp->phy_address, MII_DPPHYSTS_REG, &phy);	/* ack interrupt in DP83848 PHY */
-		if (!(phy & (1 << 7)))
-			goto done;
-	}
-
-	update_linkspeed(dev, 0);
-
-done:
-	disable_mdi(lp);
-
-	return IRQ_HANDLED;
-}
-
-/*
- * Initialize and enable the PHY interrupt for link-state changes
- */
-static void enable_phyirq(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned int dsintr, irq_number;
-	int status;
-
-	if (!gpio_is_valid(lp->board_data.phy_irq_pin)) {
-		/*
-		 * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L),
-		 * or board does not have it connected.
-		 */
-		mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
-		return;
-	}
-
-	irq_number = gpio_to_irq(lp->board_data.phy_irq_pin);
-	status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev);
-	if (status) {
-		printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status);
-		return;
-	}
-
-	spin_lock_irq(&lp->lock);
-	enable_mdi(lp);
-
-	if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {	/* for Davicom PHY */
-		read_phy(lp, lp->phy_address, MII_DSINTR_REG, &dsintr);
-		dsintr = dsintr & ~0xf00;		/* clear bits 8..11 */
-		write_phy(lp, lp->phy_address, MII_DSINTR_REG, dsintr);
-	}
-	else if (lp->phy_type == MII_LXT971A_ID) {	/* for Intel PHY */
-		read_phy(lp, lp->phy_address, MII_ISINTE_REG, &dsintr);
-		dsintr = dsintr | 0xf2;			/* set bits 1, 4..7 */
-		write_phy(lp, lp->phy_address, MII_ISINTE_REG, dsintr);
-	}
-	else if (lp->phy_type == MII_BCM5221_ID) {	/* for Broadcom PHY */
-		dsintr = (1 << 15) | ( 1 << 14);
-		write_phy(lp, lp->phy_address, MII_BCMINTR_REG, dsintr);
-	}
-	else if (lp->phy_type == MII_KS8721_ID) {	/* for Micrel PHY */
-		dsintr = (1 << 10) | ( 1 << 8);
-		write_phy(lp, lp->phy_address, MII_TPISTATUS, dsintr);
-	}
-	else if (lp->phy_type == MII_T78Q21x3_ID) {	/* for Teridian PHY */
-		read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &dsintr);
-		dsintr = dsintr | 0x500;		/* set bits 8, 10 */
-		write_phy(lp, lp->phy_address, MII_T78Q21INT_REG, dsintr);
-	}
-	else if (lp->phy_type == MII_DP83848_ID) {	/* National Semiconductor DP83848 PHY */
-		read_phy(lp, lp->phy_address, MII_DPMISR_REG, &dsintr);
-		dsintr = dsintr | 0x3c;			/* set bits 2..5 */
-		write_phy(lp, lp->phy_address, MII_DPMISR_REG, dsintr);
-		read_phy(lp, lp->phy_address, MII_DPMICR_REG, &dsintr);
-		dsintr = dsintr | 0x3;			/* set bits 0,1 */
-		write_phy(lp, lp->phy_address, MII_DPMICR_REG, dsintr);
-	}
-
-	disable_mdi(lp);
-	spin_unlock_irq(&lp->lock);
-}
-
-/*
- * Disable the PHY interrupt
- */
-static void disable_phyirq(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned int dsintr;
-	unsigned int irq_number;
-
-	if (!gpio_is_valid(lp->board_data.phy_irq_pin)) {
-		del_timer_sync(&lp->check_timer);
-		return;
-	}
-
-	spin_lock_irq(&lp->lock);
-	enable_mdi(lp);
-
-	if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {	/* for Davicom PHY */
-		read_phy(lp, lp->phy_address, MII_DSINTR_REG, &dsintr);
-		dsintr = dsintr | 0xf00;			/* set bits 8..11 */
-		write_phy(lp, lp->phy_address, MII_DSINTR_REG, dsintr);
-	}
-	else if (lp->phy_type == MII_LXT971A_ID) {	/* for Intel PHY */
-		read_phy(lp, lp->phy_address, MII_ISINTE_REG, &dsintr);
-		dsintr = dsintr & ~0xf2;			/* clear bits 1, 4..7 */
-		write_phy(lp, lp->phy_address, MII_ISINTE_REG, dsintr);
-	}
-	else if (lp->phy_type == MII_BCM5221_ID) {	/* for Broadcom PHY */
-		read_phy(lp, lp->phy_address, MII_BCMINTR_REG, &dsintr);
-		dsintr = ~(1 << 14);
-		write_phy(lp, lp->phy_address, MII_BCMINTR_REG, dsintr);
-	}
-	else if (lp->phy_type == MII_KS8721_ID) {	/* for Micrel PHY */
-		read_phy(lp, lp->phy_address, MII_TPISTATUS, &dsintr);
-		dsintr = ~((1 << 10) | (1 << 8));
-		write_phy(lp, lp->phy_address, MII_TPISTATUS, dsintr);
-	}
-	else if (lp->phy_type == MII_T78Q21x3_ID) {	/* for Teridian PHY */
-		read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &dsintr);
-		dsintr = dsintr & ~0x500;			/* clear bits 8, 10 */
-		write_phy(lp, lp->phy_address, MII_T78Q21INT_REG, dsintr);
-	}
-	else if (lp->phy_type == MII_DP83848_ID) {	/* National Semiconductor DP83848 PHY */
-		read_phy(lp, lp->phy_address, MII_DPMICR_REG, &dsintr);
-		dsintr = dsintr & ~0x3;				/* clear bits 0, 1 */
-		write_phy(lp, lp->phy_address, MII_DPMICR_REG, dsintr);
-		read_phy(lp, lp->phy_address, MII_DPMISR_REG, &dsintr);
-		dsintr = dsintr & ~0x3c;			/* clear bits 2..5 */
-		write_phy(lp, lp->phy_address, MII_DPMISR_REG, dsintr);
-	}
-
-	disable_mdi(lp);
-	spin_unlock_irq(&lp->lock);
-
-	irq_number = gpio_to_irq(lp->board_data.phy_irq_pin);
-	free_irq(irq_number, dev);			/* Free interrupt handler */
-}
-
-/*
- * Perform a software reset of the PHY.
- */
-#if 0
-static void reset_phy(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned int bmcr;
-
-	spin_lock_irq(&lp->lock);
-	enable_mdi(lp);
-
-	/* Perform PHY reset */
-	write_phy(lp, lp->phy_address, MII_BMCR, BMCR_RESET);
-
-	/* Wait until PHY reset is complete */
-	do {
-		read_phy(lp, lp->phy_address, MII_BMCR, &bmcr);
-	} while (!(bmcr & BMCR_RESET));
-
-	disable_mdi(lp);
-	spin_unlock_irq(&lp->lock);
-}
-#endif
-
-static void at91ether_check_link(unsigned long dev_id)
-{
-	struct net_device *dev = (struct net_device *) dev_id;
-	struct at91_private *lp = netdev_priv(dev);
-
-	enable_mdi(lp);
-	update_linkspeed(dev, 1);
-	disable_mdi(lp);
-
-	mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
-}
-
-/*
- * Perform any PHY-specific initialization.
- */
-static void __init initialize_phy(struct at91_private *lp)
-{
-	unsigned int val;
-
-	spin_lock_irq(&lp->lock);
-	enable_mdi(lp);
-
-	if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
-		read_phy(lp, lp->phy_address, MII_DSCR_REG, &val);
-		if ((val & (1 << 10)) == 0)			/* DSCR bit 10 is 0 -- fiber mode */
-			lp->phy_media = PORT_FIBRE;
-	} else if (machine_is_csb337()) {
-		/* mix link activity status into LED2 link state */
-		write_phy(lp, lp->phy_address, MII_LEDCTRL_REG, 0x0d22);
-	} else if (machine_is_ecbat91())
-		write_phy(lp, lp->phy_address, MII_LEDCTRL_REG, 0x156A);
-
-	disable_mdi(lp);
-	spin_unlock_irq(&lp->lock);
-}
-
-/* ......................... ADDRESS MANAGEMENT ........................ */
-
-/*
- * NOTE: Your bootloader must always set the MAC address correctly before
- * booting into Linux.
- *
- * - It must always set the MAC address after reset, even if it doesn't
- *   happen to access the Ethernet while it's booting.  Some versions of
- *   U-Boot on the AT91RM9200-DK do not do this.
- *
- * - Likewise it must store the addresses in the correct byte order.
- *   MicroMonitor (uMon) on the CSB337 does this incorrectly (and
- *   continues to do so, for bug-compatibility).
- */
-
-static short __init unpack_mac_address(struct net_device *dev, unsigned int hi, unsigned int lo)
-{
-	char addr[6];
-
-	if (machine_is_csb337()) {
-		addr[5] = (lo & 0xff);			/* The CSB337 bootloader stores the MAC the wrong-way around */
-		addr[4] = (lo & 0xff00) >> 8;
-		addr[3] = (lo & 0xff0000) >> 16;
-		addr[2] = (lo & 0xff000000) >> 24;
-		addr[1] = (hi & 0xff);
-		addr[0] = (hi & 0xff00) >> 8;
-	}
-	else {
-		addr[0] = (lo & 0xff);
-		addr[1] = (lo & 0xff00) >> 8;
-		addr[2] = (lo & 0xff0000) >> 16;
-		addr[3] = (lo & 0xff000000) >> 24;
-		addr[4] = (hi & 0xff);
-		addr[5] = (hi & 0xff00) >> 8;
-	}
-
-	if (is_valid_ether_addr(addr)) {
-		memcpy(dev->dev_addr, &addr, 6);
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * Set the ethernet MAC address in dev->dev_addr
- */
-static void __init get_mac_address(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-
-	/* Check Specific-Address 1 */
-	if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA1H), at91_emac_read(lp, AT91_EMAC_SA1L)))
-		return;
-	/* Check Specific-Address 2 */
-	if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA2H), at91_emac_read(lp, AT91_EMAC_SA2L)))
-		return;
-	/* Check Specific-Address 3 */
-	if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA3H), at91_emac_read(lp, AT91_EMAC_SA3L)))
-		return;
-	/* Check Specific-Address 4 */
-	if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA4H), at91_emac_read(lp, AT91_EMAC_SA4L)))
-		return;
-
-	printk(KERN_ERR "at91_ether: Your bootloader did not configure a MAC address.\n");
-}
-
-/*
- * Program the hardware MAC address from dev->dev_addr.
- */
-static void update_mac_address(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-
-	at91_emac_write(lp, AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]));
-	at91_emac_write(lp, AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4]));
-
-	at91_emac_write(lp, AT91_EMAC_SA2L, 0);
-	at91_emac_write(lp, AT91_EMAC_SA2H, 0);
-}
-
-/*
- * Store the new hardware address in dev->dev_addr, and update the MAC.
- */
-static int set_mac_address(struct net_device *dev, void* addr)
-{
-	struct sockaddr *address = addr;
-
-	if (!is_valid_ether_addr(address->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
-	update_mac_address(dev);
-
-	printk("%s: Setting MAC address to %pM\n", dev->name,
-	       dev->dev_addr);
+#include "macb.h"
 
-	return 0;
-}
-
-static int inline hash_bit_value(int bitnr, __u8 *addr)
-{
-	if (addr[bitnr / 8] & (1 << (bitnr % 8)))
-		return 1;
-	return 0;
-}
+/* 1518 rounded up */
+#define MAX_RBUFF_SZ	0x600
+/* max number of receive buffers */
+#define MAX_RX_DESCR	9
 
-/*
- * The hash address register is 64 bits long and takes up two locations in the memory map.
- * The least significant bits are stored in EMAC_HSL and the most significant
- * bits in EMAC_HSH.
- *
- * The unicast hash enable and the multicast hash enable bits in the network configuration
- *  register enable the reception of hash matched frames. The destination address is
- *  reduced to a 6 bit index into the 64 bit hash register using the following hash function.
- * The hash function is an exclusive or of every sixth bit of the destination address.
- *   hash_index[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47]
- *   hash_index[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46]
- *   hash_index[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45]
- *   hash_index[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44]
- *   hash_index[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43]
- *   hash_index[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42]
- * da[0] represents the least significant bit of the first byte received, that is, the multicast/
- *  unicast indicator, and da[47] represents the most significant bit of the last byte
- *  received.
- * If the hash index points to a bit that is set in the hash register then the frame will be
- *  matched according to whether the frame is multicast or unicast.
- * A multicast match will be signalled if the multicast hash enable bit is set, da[0] is 1 and
- *  the hash index points to a bit set in the hash register.
- * A unicast match will be signalled if the unicast hash enable bit is set, da[0] is 0 and the
- *  hash index points to a bit set in the hash register.
- * To receive all multicast frames, the hash register should be set with all ones and the
- *  multicast hash enable bit should be set in the network configuration register.
- */
-
-/*
- * Return the hash index value for the specified address.
- */
-static int hash_get_index(__u8 *addr)
-{
-	int i, j, bitval;
-	int hash_index = 0;
-
-	for (j = 0; j < 6; j++) {
-		for (i = 0, bitval = 0; i < 8; i++)
-			bitval ^= hash_bit_value(i*6 + j, addr);
-
-		hash_index |= (bitval << j);
-	}
-
-	return hash_index;
-}
-
-/*
- * Add multicast addresses to the internal multicast-hash table.
- */
-static void at91ether_sethashtable(struct net_device *dev)
+/* Initialize and start the Receiver and Transmit subsystems */
+static int at91ether_start(struct net_device *dev)
 {
-	struct at91_private *lp = netdev_priv(dev);
-	struct netdev_hw_addr *ha;
-	unsigned long mc_filter[2];
-	unsigned int bitnr;
-
-	mc_filter[0] = mc_filter[1] = 0;
-
-	netdev_for_each_mc_addr(ha, dev) {
-		bitnr = hash_get_index(ha->addr);
-		mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
-	}
-
-	at91_emac_write(lp, AT91_EMAC_HSL, mc_filter[0]);
-	at91_emac_write(lp, AT91_EMAC_HSH, mc_filter[1]);
-}
+	struct macb *lp = netdev_priv(dev);
+	dma_addr_t addr;
+	u32 ctl;
+	int i;
 
-/*
- * Enable/Disable promiscuous and multicast modes.
- */
-static void at91ether_set_multicast_list(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned long cfg;
-
-	cfg = at91_emac_read(lp, AT91_EMAC_CFG);
-
-	if (dev->flags & IFF_PROMISC)			/* Enable promiscuous mode */
-		cfg |= AT91_EMAC_CAF;
-	else if (dev->flags & (~IFF_PROMISC))		/* Disable promiscuous mode */
-		cfg &= ~AT91_EMAC_CAF;
-
-	if (dev->flags & IFF_ALLMULTI) {		/* Enable all multicast mode */
-		at91_emac_write(lp, AT91_EMAC_HSH, -1);
-		at91_emac_write(lp, AT91_EMAC_HSL, -1);
-		cfg |= AT91_EMAC_MTI;
-	} else if (!netdev_mc_empty(dev)) { /* Enable specific multicasts */
-		at91ether_sethashtable(dev);
-		cfg |= AT91_EMAC_MTI;
-	} else if (dev->flags & (~IFF_ALLMULTI)) {	/* Disable all multicast mode */
-		at91_emac_write(lp, AT91_EMAC_HSH, 0);
-		at91_emac_write(lp, AT91_EMAC_HSL, 0);
-		cfg &= ~AT91_EMAC_MTI;
+	lp->rx_ring = dma_alloc_coherent(&lp->pdev->dev,
+					MAX_RX_DESCR * sizeof(struct macb_dma_desc),
+					&lp->rx_ring_dma, GFP_KERNEL);
+	if (!lp->rx_ring) {
+		netdev_err(dev, "unable to alloc rx ring DMA buffer\n");
+		return -ENOMEM;
 	}
 
-	at91_emac_write(lp, AT91_EMAC_CFG, cfg);
-}
-
-/* ......................... ETHTOOL SUPPORT ........................... */
-
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned int value;
-
-	read_phy(lp, phy_id, location, &value);
-	return value;
-}
-
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
-{
-	struct at91_private *lp = netdev_priv(dev);
-
-	write_phy(lp, phy_id, location, value);
-}
-
-static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	int ret;
-
-	spin_lock_irq(&lp->lock);
-	enable_mdi(lp);
+	lp->rx_buffers = dma_alloc_coherent(&lp->pdev->dev,
+					MAX_RX_DESCR * MAX_RBUFF_SZ,
+					&lp->rx_buffers_dma, GFP_KERNEL);
+	if (!lp->rx_buffers) {
+		netdev_err(dev, "unable to alloc rx data DMA buffer\n");
 
-	ret = mii_ethtool_gset(&lp->mii, cmd);
-
-	disable_mdi(lp);
-	spin_unlock_irq(&lp->lock);
-
-	if (lp->phy_media == PORT_FIBRE) {		/* override media type since mii.c doesn't know */
-		cmd->supported = SUPPORTED_FIBRE;
-		cmd->port = PORT_FIBRE;
+		dma_free_coherent(&lp->pdev->dev,
+					MAX_RX_DESCR * sizeof(struct macb_dma_desc),
+					lp->rx_ring, lp->rx_ring_dma);
+		lp->rx_ring = NULL;
+		return -ENOMEM;
 	}
 
-	return ret;
-}
-
-static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	int ret;
-
-	spin_lock_irq(&lp->lock);
-	enable_mdi(lp);
-
-	ret = mii_ethtool_sset(&lp->mii, cmd);
-
-	disable_mdi(lp);
-	spin_unlock_irq(&lp->lock);
-
-	return ret;
-}
-
-static int at91ether_nwayreset(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	int ret;
-
-	spin_lock_irq(&lp->lock);
-	enable_mdi(lp);
-
-	ret = mii_nway_restart(&lp->mii);
-
-	disable_mdi(lp);
-	spin_unlock_irq(&lp->lock);
-
-	return ret;
-}
-
-static void at91ether_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-	strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info));
-}
-
-static const struct ethtool_ops at91ether_ethtool_ops = {
-	.get_settings	= at91ether_get_settings,
-	.set_settings	= at91ether_set_settings,
-	.get_drvinfo	= at91ether_get_drvinfo,
-	.nway_reset	= at91ether_nwayreset,
-	.get_link	= ethtool_op_get_link,
-};
-
-static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	int res;
-
-	if (!netif_running(dev))
-		return -EINVAL;
-
-	spin_lock_irq(&lp->lock);
-	enable_mdi(lp);
-	res = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL);
-	disable_mdi(lp);
-	spin_unlock_irq(&lp->lock);
-
-	return res;
-}
-
-/* ................................ MAC ................................ */
-
-/*
- * Initialize and start the Receiver and Transmit subsystems
- */
-static void at91ether_start(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	struct recv_desc_bufs *dlist, *dlist_phys;
-	int i;
-	unsigned long ctl;
-
-	dlist = lp->dlist;
-	dlist_phys = lp->dlist_phys;
-
+	addr = lp->rx_buffers_dma;
 	for (i = 0; i < MAX_RX_DESCR; i++) {
-		dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0];
-		dlist->descriptors[i].size = 0;
+		lp->rx_ring[i].addr = addr;
+		lp->rx_ring[i].ctrl = 0;
+		addr += MAX_RBUFF_SZ;
 	}
 
 	/* Set the Wrap bit on the last descriptor */
-	dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP;
+	lp->rx_ring[MAX_RX_DESCR - 1].addr |= MACB_BIT(RX_WRAP);
 
 	/* Reset buffer index */
-	lp->rxBuffIndex = 0;
+	lp->rx_tail = 0;
 
 	/* Program address of descriptor list in Rx Buffer Queue register */
-	at91_emac_write(lp, AT91_EMAC_RBQP, (unsigned long) dlist_phys);
+	macb_writel(lp, RBQP, lp->rx_ring_dma);
 
 	/* Enable Receive and Transmit */
-	ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-	at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE);
+	ctl = macb_readl(lp, NCR);
+	macb_writel(lp, NCR, ctl | MACB_BIT(RE) | MACB_BIT(TE));
+
+	return 0;
 }
 
-/*
- * Open the ethernet interface
- */
+/* Open the ethernet interface */
 static int at91ether_open(struct net_device *dev)
 {
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned long ctl;
-
-	if (!is_valid_ether_addr(dev->dev_addr))
-		return -EADDRNOTAVAIL;
-
-	clk_enable(lp->ether_clk);		/* Re-enable Peripheral clock */
+	struct macb *lp = netdev_priv(dev);
+	u32 ctl;
+	int ret;
 
 	/* Clear internal statistics */
-	ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-	at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_CSR);
+	ctl = macb_readl(lp, NCR);
+	macb_writel(lp, NCR, ctl | MACB_BIT(CLRSTAT));
 
-	/* Update the MAC address (incase user has changed it) */
-	update_mac_address(dev);
+	macb_set_hwaddr(lp);
 
-	/* Enable PHY interrupt */
-	enable_phyirq(dev);
+	ret = at91ether_start(dev);
+	if (ret)
+		return ret;
 
 	/* Enable MAC interrupts */
-	at91_emac_write(lp, AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA
-				| AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
-				| AT91_EMAC_ROVR | AT91_EMAC_ABT);
-
-	/* Determine current link speed */
-	spin_lock_irq(&lp->lock);
-	enable_mdi(lp);
-	update_linkspeed(dev, 0);
-	disable_mdi(lp);
-	spin_unlock_irq(&lp->lock);
-
-	at91ether_start(dev);
+	macb_writel(lp, IER, MACB_BIT(RCOMP)	|
+			     MACB_BIT(RXUBR)	|
+			     MACB_BIT(ISR_TUND)	|
+			     MACB_BIT(ISR_RLE)	|
+			     MACB_BIT(TCOMP)	|
+			     MACB_BIT(ISR_ROVR)	|
+			     MACB_BIT(HRESP));
+
+	/* schedule a link state check */
+	phy_start(lp->phy_dev);
+
 	netif_start_queue(dev);
+
 	return 0;
 }
 
-/*
- * Close the interface
- */
+/* Close the interface */
 static int at91ether_close(struct net_device *dev)
 {
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned long ctl;
+	struct macb *lp = netdev_priv(dev);
+	u32 ctl;
 
 	/* Disable Receiver and Transmitter */
-	ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-	at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE));
-
-	/* Disable PHY interrupt */
-	disable_phyirq(dev);
+	ctl = macb_readl(lp, NCR);
+	macb_writel(lp, NCR, ctl & ~(MACB_BIT(TE) | MACB_BIT(RE)));
 
 	/* Disable MAC interrupts */
-	at91_emac_write(lp, AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA
-				| AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
-				| AT91_EMAC_ROVR | AT91_EMAC_ABT);
+	macb_writel(lp, IDR, MACB_BIT(RCOMP)	|
+			     MACB_BIT(RXUBR)	|
+			     MACB_BIT(ISR_TUND)	|
+			     MACB_BIT(ISR_RLE)	|
+			     MACB_BIT(TCOMP)	|
+			     MACB_BIT(ISR_ROVR) |
+			     MACB_BIT(HRESP));
 
 	netif_stop_queue(dev);
 
-	clk_disable(lp->ether_clk);		/* Disable Peripheral clock */
+	dma_free_coherent(&lp->pdev->dev,
+				MAX_RX_DESCR * sizeof(struct macb_dma_desc),
+				lp->rx_ring, lp->rx_ring_dma);
+	lp->rx_ring = NULL;
+
+	dma_free_coherent(&lp->pdev->dev,
+				MAX_RX_DESCR * MAX_RBUFF_SZ,
+				lp->rx_buffers, lp->rx_buffers_dma);
+	lp->rx_buffers = NULL;
 
 	return 0;
 }
 
-/*
- * Transmit packet.
- */
+/* Transmit packet */
 static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct at91_private *lp = netdev_priv(dev);
+	struct macb *lp = netdev_priv(dev);
 
-	if (at91_emac_read(lp, AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) {
+	if (macb_readl(lp, TSR) & MACB_BIT(RM9200_BNQ)) {
 		netif_stop_queue(dev);
 
 		/* Store packet information (to free when Tx completed) */
 		lp->skb = skb;
 		lp->skb_length = skb->len;
-		lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE);
-		dev->stats.tx_bytes += skb->len;
+		lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len,
+							DMA_TO_DEVICE);
 
 		/* Set address of the data in the Transmit Address register */
-		at91_emac_write(lp, AT91_EMAC_TAR, lp->skb_physaddr);
+		macb_writel(lp, TAR, lp->skb_physaddr);
 		/* Set length of the packet in the Transmit Control register */
-		at91_emac_write(lp, AT91_EMAC_TCR, skb->len);
+		macb_writel(lp, TCR, skb->len);
 
 	} else {
-		printk(KERN_ERR "at91_ether.c: at91ether_start_xmit() called, but device is busy!\n");
-		return NETDEV_TX_BUSY;	/* if we return anything but zero, dev.c:1055 calls kfree_skb(skb)
-				on this skb, he also reports -ENETDOWN and printk's, so either
-				we free and return(0) or don't free and return 1 */
+		netdev_err(dev, "%s called, but device is busy!\n", __func__);
+		return NETDEV_TX_BUSY;
 	}
 
 	return NETDEV_TX_OK;
 }
 
-/*
- * Update the current statistics from the internal statistics registers.
- */
-static struct net_device_stats *at91ether_stats(struct net_device *dev)
-{
-	struct at91_private *lp = netdev_priv(dev);
-	int ale, lenerr, seqe, lcol, ecol;
-
-	if (netif_running(dev)) {
-		dev->stats.rx_packets += at91_emac_read(lp, AT91_EMAC_OK);	/* Good frames received */
-		ale = at91_emac_read(lp, AT91_EMAC_ALE);
-		dev->stats.rx_frame_errors += ale;				/* Alignment errors */
-		lenerr = at91_emac_read(lp, AT91_EMAC_ELR) + at91_emac_read(lp, AT91_EMAC_USF);
-		dev->stats.rx_length_errors += lenerr;				/* Excessive Length or Undersize Frame error */
-		seqe = at91_emac_read(lp, AT91_EMAC_SEQE);
-		dev->stats.rx_crc_errors += seqe;				/* CRC error */
-		dev->stats.rx_fifo_errors += at91_emac_read(lp, AT91_EMAC_DRFC);/* Receive buffer not available */
-		dev->stats.rx_errors += (ale + lenerr + seqe
-			+ at91_emac_read(lp, AT91_EMAC_CDE) + at91_emac_read(lp, AT91_EMAC_RJB));
-
-		dev->stats.tx_packets += at91_emac_read(lp, AT91_EMAC_FRA);	/* Frames successfully transmitted */
-		dev->stats.tx_fifo_errors += at91_emac_read(lp, AT91_EMAC_TUE);	/* Transmit FIFO underruns */
-		dev->stats.tx_carrier_errors += at91_emac_read(lp, AT91_EMAC_CSE);	/* Carrier Sense errors */
-		dev->stats.tx_heartbeat_errors += at91_emac_read(lp, AT91_EMAC_SQEE);/* Heartbeat error */
-
-		lcol = at91_emac_read(lp, AT91_EMAC_LCOL);
-		ecol = at91_emac_read(lp, AT91_EMAC_ECOL);
-		dev->stats.tx_window_errors += lcol;			/* Late collisions */
-		dev->stats.tx_aborted_errors += ecol;			/* 16 collisions */
-
-		dev->stats.collisions += (at91_emac_read(lp, AT91_EMAC_SCOL) + at91_emac_read(lp, AT91_EMAC_MCOL) + lcol + ecol);
-	}
-	return &dev->stats;
-}
-
-/*
- * Extract received frame from buffer descriptors and sent to upper layers.
+/* Extract received frame from buffer descriptors and sent to upper layers.
  * (Called from interrupt context)
  */
 static void at91ether_rx(struct net_device *dev)
 {
-	struct at91_private *lp = netdev_priv(dev);
-	struct recv_desc_bufs *dlist;
+	struct macb *lp = netdev_priv(dev);
 	unsigned char *p_recv;
 	struct sk_buff *skb;
 	unsigned int pktlen;
 
-	dlist = lp->dlist;
-	while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) {
-		p_recv = dlist->recv_buf[lp->rxBuffIndex];
-		pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff;	/* Length of frame including FCS */
+	while (lp->rx_ring[lp->rx_tail].addr & MACB_BIT(RX_USED)) {
+		p_recv = lp->rx_buffers + lp->rx_tail * MAX_RBUFF_SZ;
+		pktlen = MACB_BF(RX_FRMLEN, lp->rx_ring[lp->rx_tail].ctrl);
 		skb = netdev_alloc_skb(dev, pktlen + 2);
-		if (skb != NULL) {
+		if (skb) {
 			skb_reserve(skb, 2);
 			memcpy(skb_put(skb, pktlen), p_recv, pktlen);
 
 			skb->protocol = eth_type_trans(skb, dev);
-			dev->stats.rx_bytes += pktlen;
+			lp->stats.rx_packets++;
+			lp->stats.rx_bytes += pktlen;
 			netif_rx(skb);
+		} else {
+			lp->stats.rx_dropped++;
+			netdev_notice(dev, "Memory squeeze, dropping packet.\n");
 		}
-		else {
-			dev->stats.rx_dropped += 1;
-			printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
-		}
 
-		if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST)
-			dev->stats.multicast++;
+		if (lp->rx_ring[lp->rx_tail].ctrl & MACB_BIT(RX_MHASH_MATCH))
+			lp->stats.multicast++;
+
+		/* reset ownership bit */
+		lp->rx_ring[lp->rx_tail].addr &= ~MACB_BIT(RX_USED);
 
-		dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE;	/* reset ownership bit */
-		if (lp->rxBuffIndex == MAX_RX_DESCR-1)				/* wrap after last buffer */
-			lp->rxBuffIndex = 0;
+		/* wrap after last buffer */
+		if (lp->rx_tail == MAX_RX_DESCR - 1)
+			lp->rx_tail = 0;
 		else
-			lp->rxBuffIndex++;
+			lp->rx_tail++;
 	}
 }
 
-/*
- * MAC interrupt handler
- */
+/* MAC interrupt handler */
 static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
 {
-	struct net_device *dev = (struct net_device *) dev_id;
-	struct at91_private *lp = netdev_priv(dev);
-	unsigned long intstatus, ctl;
+	struct net_device *dev = dev_id;
+	struct macb *lp = netdev_priv(dev);
+	u32 intstatus, ctl;
 
 	/* MAC Interrupt Status register indicates what interrupts are pending.
-	   It is automatically cleared once read. */
-	intstatus = at91_emac_read(lp, AT91_EMAC_ISR);
+	 * It is automatically cleared once read.
+	 */
+	intstatus = macb_readl(lp, ISR);
 
-	if (intstatus & AT91_EMAC_RCOM)		/* Receive complete */
+	/* Receive complete */
+	if (intstatus & MACB_BIT(RCOMP))
 		at91ether_rx(dev);
 
-	if (intstatus & AT91_EMAC_TCOM) {	/* Transmit complete */
-		/* The TCOM bit is set even if the transmission failed. */
-		if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY))
-			dev->stats.tx_errors += 1;
+	/* Transmit complete */
+	if (intstatus & MACB_BIT(TCOMP)) {
+		/* The TCOM bit is set even if the transmission failed */
+		if (intstatus & (MACB_BIT(ISR_TUND) | MACB_BIT(ISR_RLE)))
+			lp->stats.tx_errors++;
 
 		if (lp->skb) {
 			dev_kfree_skb_irq(lp->skb);
 			lp->skb = NULL;
 			dma_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, DMA_TO_DEVICE);
+			lp->stats.tx_packets++;
+			lp->stats.tx_bytes += lp->skb_length;
 		}
 		netif_wake_queue(dev);
 	}
 
-	/* Work-around for Errata #11 */
-	if (intstatus & AT91_EMAC_RBNA) {
-		ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-		at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE);
-		at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_RE);
+	/* Work-around for EMAC Errata section 41.3.1 */
+	if (intstatus & MACB_BIT(RXUBR)) {
+		ctl = macb_readl(lp, NCR);
+		macb_writel(lp, NCR, ctl & ~MACB_BIT(RE));
+		macb_writel(lp, NCR, ctl | MACB_BIT(RE));
 	}
 
-	if (intstatus & AT91_EMAC_ROVR)
-		printk("%s: ROVR error\n", dev->name);
+	if (intstatus & MACB_BIT(ISR_ROVR))
+		netdev_err(dev, "ROVR error\n");
 
 	return IRQ_HANDLED;
 }
@@ -1000,10 +286,10 @@ static const struct net_device_ops at91ether_netdev_ops = {
 	.ndo_open		= at91ether_open,
 	.ndo_stop		= at91ether_close,
 	.ndo_start_xmit		= at91ether_start_xmit,
-	.ndo_get_stats		= at91ether_stats,
-	.ndo_set_rx_mode	= at91ether_set_multicast_list,
-	.ndo_set_mac_address	= set_mac_address,
-	.ndo_do_ioctl		= at91ether_ioctl,
+	.ndo_get_stats		= macb_get_stats,
+	.ndo_set_rx_mode	= macb_set_rx_mode,
+	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_do_ioctl		= macb_ioctl,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1011,197 +297,160 @@ static const struct net_device_ops at91ether_netdev_ops = {
 #endif
 };
 
-/*
- * Detect the PHY type, and its address.
- */
-static int __init at91ether_phy_detect(struct at91_private *lp)
+#if defined(CONFIG_OF)
+static const struct of_device_id at91ether_dt_ids[] = {
+	{ .compatible = "cdns,at91rm9200-emac" },
+	{ .compatible = "cdns,emac" },
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, at91ether_dt_ids);
+
+static int at91ether_get_phy_mode_dt(struct platform_device *pdev)
 {
-	unsigned int phyid1, phyid2;
-	unsigned long phy_id;
-	unsigned short phy_address = 0;
-
-	while (phy_address < PHY_MAX_ADDR) {
-		/* Read the PHY ID registers */
-		enable_mdi(lp);
-		read_phy(lp, phy_address, MII_PHYSID1, &phyid1);
-		read_phy(lp, phy_address, MII_PHYSID2, &phyid2);
-		disable_mdi(lp);
-
-		phy_id = (phyid1 << 16) | (phyid2 & 0xfff0);
-		switch (phy_id) {
-			case MII_DM9161_ID:		/* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */
-			case MII_DM9161A_ID:		/* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */
-			case MII_LXT971A_ID:		/* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */
-			case MII_RTL8201_ID:		/* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */
-			case MII_BCM5221_ID:		/* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */
-			case MII_DP83847_ID:		/* National Semiconductor DP83847:  */
-			case MII_DP83848_ID:		/* National Semiconductor DP83848:  */
-			case MII_AC101L_ID:		/* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
-			case MII_KS8721_ID:		/* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
-			case MII_T78Q21x3_ID:		/* Teridian 78Q21x3: PHY_ID1 = 0x0E, PHY_ID2 = 7237 */
-			case MII_LAN83C185_ID:		/* SMSC LAN83C185: PHY_ID1 = 0x0007, PHY_ID2 = 0xC0A1 */
-				/* store detected values */
-				lp->phy_type = phy_id;		/* Type of PHY connected */
-				lp->phy_address = phy_address;	/* MDI address of PHY */
-				return 1;
-		}
+	struct device_node *np = pdev->dev.of_node;
 
-		phy_address++;
-	}
+	if (np)
+		return of_get_phy_mode(np);
 
-	return 0;		/* not detected */
+	return -ENODEV;
 }
 
+static int at91ether_get_hwaddr_dt(struct macb *bp)
+{
+	struct device_node *np = bp->pdev->dev.of_node;
 
-/*
- * Detect MAC & PHY and perform ethernet interface initialization
- */
+	if (np) {
+		const char *mac = of_get_mac_address(np);
+		if (mac) {
+			memcpy(bp->dev->dev_addr, mac, ETH_ALEN);
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+#else
+static int at91ether_get_phy_mode_dt(struct platform_device *pdev)
+{
+	return -ENODEV;
+}
+static int at91ether_get_hwaddr_dt(struct macb *bp)
+{
+	return -ENODEV;
+}
+#endif
+
+/* Detect MAC & PHY and perform ethernet interface initialization */
 static int __init at91ether_probe(struct platform_device *pdev)
 {
 	struct macb_platform_data *board_data = pdev->dev.platform_data;
 	struct resource *regs;
 	struct net_device *dev;
-	struct at91_private *lp;
+	struct phy_device *phydev;
+	struct pinctrl *pinctrl;
+	struct macb *lp;
 	int res;
+	u32 reg;
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!regs)
 		return -ENOENT;
 
-	dev = alloc_etherdev(sizeof(struct at91_private));
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl)) {
+		res = PTR_ERR(pinctrl);
+		if (res == -EPROBE_DEFER)
+			return res;
+
+		dev_warn(&pdev->dev, "No pinctrl provided\n");
+	}
+
+	dev = alloc_etherdev(sizeof(struct macb));
 	if (!dev)
 		return -ENOMEM;
 
 	lp = netdev_priv(dev);
-	lp->board_data = *board_data;
+	lp->pdev = pdev;
+	lp->dev = dev;
 	spin_lock_init(&lp->lock);
 
-	dev->base_addr = regs->start;		/* physical base address */
-	lp->emac_base = ioremap(regs->start, regs->end - regs->start + 1);
-	if (!lp->emac_base) {
+	/* physical base address */
+	dev->base_addr = regs->start;
+	lp->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
+	if (!lp->regs) {
 		res = -ENOMEM;
 		goto err_free_dev;
 	}
 
 	/* Clock */
-	lp->ether_clk = clk_get(&pdev->dev, "ether_clk");
-	if (IS_ERR(lp->ether_clk)) {
-		res = PTR_ERR(lp->ether_clk);
-		goto err_ioumap;
+	lp->pclk = devm_clk_get(&pdev->dev, "ether_clk");
+	if (IS_ERR(lp->pclk)) {
+		res = PTR_ERR(lp->pclk);
+		goto err_free_dev;
 	}
-	clk_enable(lp->ether_clk);
+	clk_enable(lp->pclk);
 
 	/* Install the interrupt handler */
 	dev->irq = platform_get_irq(pdev, 0);
-	if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev)) {
-		res = -EBUSY;
+	res = devm_request_irq(&pdev->dev, dev->irq, at91ether_interrupt, 0, dev->name, dev);
+	if (res)
 		goto err_disable_clock;
-	}
-
-	/* Allocate memory for DMA Receive descriptors */
-	lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL);
-	if (lp->dlist == NULL) {
-		res = -ENOMEM;
-		goto err_free_irq;
-	}
 
 	ether_setup(dev);
 	dev->netdev_ops = &at91ether_netdev_ops;
-	dev->ethtool_ops = &at91ether_ethtool_ops;
+	dev->ethtool_ops = &macb_ethtool_ops;
 	platform_set_drvdata(pdev, dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	get_mac_address(dev);		/* Get ethernet address and store it in dev->dev_addr */
-	update_mac_address(dev);	/* Program ethernet address into MAC */
-
-	at91_emac_write(lp, AT91_EMAC_CTL, 0);
+	res = at91ether_get_hwaddr_dt(lp);
+	if (res < 0)
+		macb_get_hwaddr(lp);
 
-	if (board_data->is_rmii)
-		at91_emac_write(lp, AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII);
-	else
-		at91_emac_write(lp, AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG);
-
-	/* Detect PHY */
-	if (!at91ether_phy_detect(lp)) {
-		printk(KERN_ERR "at91_ether: Could not detect ethernet PHY\n");
-		res = -ENODEV;
-		goto err_free_dmamem;
+	res = at91ether_get_phy_mode_dt(pdev);
+	if (res < 0) {
+		if (board_data && board_data->is_rmii)
+			lp->phy_interface = PHY_INTERFACE_MODE_RMII;
+		else
+			lp->phy_interface = PHY_INTERFACE_MODE_MII;
+	} else {
+		lp->phy_interface = res;
 	}
 
-	initialize_phy(lp);
+	macb_writel(lp, NCR, 0);
+
+	reg = MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG);
+	if (lp->phy_interface == PHY_INTERFACE_MODE_RMII)
+		reg |= MACB_BIT(RM9200_RMII);
 
-	lp->mii.dev = dev;		/* Support for ethtool */
-	lp->mii.mdio_read = mdio_read;
-	lp->mii.mdio_write = mdio_write;
-	lp->mii.phy_id = lp->phy_address;
-	lp->mii.phy_id_mask = 0x1f;
-	lp->mii.reg_num_mask = 0x1f;
+	macb_writel(lp, NCFGR, reg);
 
 	/* Register the network interface */
 	res = register_netdev(dev);
 	if (res)
-		goto err_free_dmamem;
-
-	/* Determine current link speed */
-	spin_lock_irq(&lp->lock);
-	enable_mdi(lp);
-	update_linkspeed(dev, 0);
-	disable_mdi(lp);
-	spin_unlock_irq(&lp->lock);
-	netif_carrier_off(dev);		/* will be enabled in open() */
-
-	/* If board has no PHY IRQ, use a timer to poll the PHY */
-	if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
-		gpio_request(board_data->phy_irq_pin, "ethernet_phy");
-	} else {
-		/* If board has no PHY IRQ, use a timer to poll the PHY */
-		init_timer(&lp->check_timer);
-		lp->check_timer.data = (unsigned long)dev;
-		lp->check_timer.function = at91ether_check_link;
-	}
+		goto err_disable_clock;
+
+	if (macb_mii_init(lp) != 0)
+		goto err_out_unregister_netdev;
+
+	/* will be enabled in open() */
+	netif_carrier_off(dev);
+
+	phydev = lp->phy_dev;
+	netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+				phydev->drv->name, dev_name(&phydev->dev),
+				phydev->irq);
 
 	/* Display ethernet banner */
-	printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%pM)\n",
-	       dev->name, (uint) dev->base_addr, dev->irq,
-	       at91_emac_read(lp, AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-",
-	       at91_emac_read(lp, AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex",
-	       dev->dev_addr);
-	if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
-		printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
-	else if (lp->phy_type == MII_LXT971A_ID)
-		printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
-	else if (lp->phy_type == MII_RTL8201_ID)
-		printk(KERN_INFO "%s: Realtek RTL8201(B)L PHY\n", dev->name);
-	else if (lp->phy_type == MII_BCM5221_ID)
-		printk(KERN_INFO "%s: Broadcom BCM5221 PHY\n", dev->name);
-	else if (lp->phy_type == MII_DP83847_ID)
-		printk(KERN_INFO "%s: National Semiconductor DP83847 PHY\n", dev->name);
-	else if (lp->phy_type == MII_DP83848_ID)
-		printk(KERN_INFO "%s: National Semiconductor DP83848 PHY\n", dev->name);
-	else if (lp->phy_type == MII_AC101L_ID)
-		printk(KERN_INFO "%s: Altima AC101L PHY\n", dev->name);
-	else if (lp->phy_type == MII_KS8721_ID)
-		printk(KERN_INFO "%s: Micrel KS8721 PHY\n", dev->name);
-	else if (lp->phy_type == MII_T78Q21x3_ID)
-		printk(KERN_INFO "%s: Teridian 78Q21x3 PHY\n", dev->name);
-	else if (lp->phy_type == MII_LAN83C185_ID)
-		printk(KERN_INFO "%s: SMSC LAN83C185 PHY\n", dev->name);
-
-	clk_disable(lp->ether_clk);					/* Disable Peripheral clock */
+	netdev_info(dev, "AT91 ethernet at 0x%08lx int=%d (%pM)\n",
+				dev->base_addr, dev->irq, dev->dev_addr);
 
 	return 0;
 
-
-err_free_dmamem:
-	platform_set_drvdata(pdev, NULL);
-	dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
-err_free_irq:
-	free_irq(dev->irq, dev);
+err_out_unregister_netdev:
+	unregister_netdev(dev);
 err_disable_clock:
-	clk_disable(lp->ether_clk);
-	clk_put(lp->ether_clk);
-err_ioumap:
-	iounmap(lp->emac_base);
+	clk_disable(lp->pclk);
 err_free_dev:
 	free_netdev(dev);
 	return res;
@@ -1210,38 +459,33 @@ err_free_dev:
 static int __devexit at91ether_remove(struct platform_device *pdev)
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
-	struct at91_private *lp = netdev_priv(dev);
+	struct macb *lp = netdev_priv(dev);
 
-	if (gpio_is_valid(lp->board_data.phy_irq_pin))
-		gpio_free(lp->board_data.phy_irq_pin);
+	if (lp->phy_dev)
+		phy_disconnect(lp->phy_dev);
 
+	mdiobus_unregister(lp->mii_bus);
+	kfree(lp->mii_bus->irq);
+	mdiobus_free(lp->mii_bus);
 	unregister_netdev(dev);
-	free_irq(dev->irq, dev);
-	dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
-	clk_put(lp->ether_clk);
-
-	platform_set_drvdata(pdev, NULL);
+	clk_disable(lp->pclk);
 	free_netdev(dev);
+	platform_set_drvdata(pdev, NULL);
+
 	return 0;
 }
 
 #ifdef CONFIG_PM
-
 static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
 {
 	struct net_device *net_dev = platform_get_drvdata(pdev);
-	struct at91_private *lp = netdev_priv(net_dev);
+	struct macb *lp = netdev_priv(net_dev);
 
 	if (netif_running(net_dev)) {
-		if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
-			int phy_irq = gpio_to_irq(lp->board_data.phy_irq_pin);
-			disable_irq(phy_irq);
-		}
-
 		netif_stop_queue(net_dev);
 		netif_device_detach(net_dev);
 
-		clk_disable(lp->ether_clk);
+		clk_disable(lp->pclk);
 	}
 	return 0;
 }
@@ -1249,22 +493,16 @@ static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
 static int at91ether_resume(struct platform_device *pdev)
 {
 	struct net_device *net_dev = platform_get_drvdata(pdev);
-	struct at91_private *lp = netdev_priv(net_dev);
+	struct macb *lp = netdev_priv(net_dev);
 
 	if (netif_running(net_dev)) {
-		clk_enable(lp->ether_clk);
+		clk_enable(lp->pclk);
 
 		netif_device_attach(net_dev);
 		netif_start_queue(net_dev);
-
-		if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
-			int phy_irq = gpio_to_irq(lp->board_data.phy_irq_pin);
-			enable_irq(phy_irq);
-		}
 	}
 	return 0;
 }
-
 #else
 #define at91ether_suspend	NULL
 #define at91ether_resume	NULL
@@ -1275,8 +513,9 @@ static struct platform_driver at91ether_driver = {
 	.suspend	= at91ether_suspend,
 	.resume		= at91ether_resume,
 	.driver		= {
-		.name	= DRV_NAME,
+		.name	= "at91_ether",
 		.owner	= THIS_MODULE,
+		.of_match_table	= of_match_ptr(at91ether_dt_ids),
 	},
 };
 
@@ -1296,4 +535,4 @@ module_exit(at91ether_exit)
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
 MODULE_AUTHOR("Andrew Victor");
-MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_ALIAS("platform:at91_ether");
diff --git a/drivers/net/ethernet/cadence/at91_ether.h b/drivers/net/ethernet/cadence/at91_ether.h
deleted file mode 100644
index 0ef6328..0000000
--- a/drivers/net/ethernet/cadence/at91_ether.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Ethernet driver for the Atmel AT91RM9200 (Thunder)
- *
- *  Copyright (C) SAN People (Pty) Ltd
- *
- * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
- * Initial version by Rick Bronson.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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 AT91_ETHERNET
-#define AT91_ETHERNET
-
-
-/* Davicom 9161 PHY */
-#define MII_DM9161_ID		0x0181b880
-#define MII_DM9161A_ID		0x0181b8a0
-#define MII_DSCR_REG		16
-#define MII_DSCSR_REG		17
-#define MII_DSINTR_REG		21
-
-/* Intel LXT971A PHY */
-#define MII_LXT971A_ID		0x001378E0
-#define MII_ISINTE_REG		18
-#define MII_ISINTS_REG		19
-#define MII_LEDCTRL_REG		20
-
-/* Realtek RTL8201 PHY */
-#define MII_RTL8201_ID		0x00008200
-
-/* Broadcom BCM5221 PHY */
-#define MII_BCM5221_ID		0x004061e0
-#define MII_BCMINTR_REG		26
-
-/* National Semiconductor DP83847 */
-#define MII_DP83847_ID		0x20005c30
-
-/* National Semiconductor DP83848 */
-#define MII_DP83848_ID		0x20005c90
-#define MII_DPPHYSTS_REG	16
-#define MII_DPMICR_REG		17
-#define MII_DPMISR_REG		18
-
-/* Altima AC101L PHY */
-#define MII_AC101L_ID		0x00225520
-
-/* Micrel KS8721 PHY */
-#define MII_KS8721_ID		0x00221610
-
-/* Teridian 78Q2123/78Q2133 */
-#define MII_T78Q21x3_ID		0x000e7230
-#define MII_T78Q21INT_REG	17
-
-/* SMSC LAN83C185 */
-#define MII_LAN83C185_ID	0x0007C0A0
-
-/* ........................................................................ */
-
-#define MAX_RBUFF_SZ	0x600		/* 1518 rounded up */
-#define MAX_RX_DESCR	9		/* max number of receive buffers */
-
-#define EMAC_DESC_DONE	0x00000001	/* bit for if DMA is done */
-#define EMAC_DESC_WRAP	0x00000002	/* bit for wrap */
-
-#define EMAC_BROADCAST	0x80000000	/* broadcast address */
-#define EMAC_MULTICAST	0x40000000	/* multicast address */
-#define EMAC_UNICAST	0x20000000	/* unicast address */
-
-struct rbf_t
-{
-	unsigned int addr;
-	unsigned long size;
-};
-
-struct recv_desc_bufs
-{
-	struct rbf_t descriptors[MAX_RX_DESCR];		/* must be on sizeof (rbf_t) boundary */
-	char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ];	/* must be on long boundary */
-};
-
-struct at91_private
-{
-	struct mii_if_info mii;			/* ethtool support */
-	struct macb_platform_data board_data;	/* board-specific
-						 * configuration (shared with
-						 * macb for common data */
-	void __iomem *emac_base;		/* base register address */
-	struct clk *ether_clk;			/* clock */
-
-	/* PHY */
-	unsigned long phy_type;			/* type of PHY (PHY_ID) */
-	spinlock_t lock;			/* lock for MDI interface */
-	short phy_media;			/* media interface type */
-	unsigned short phy_address;		/* 5-bit MDI address of PHY (0..31) */
-	struct timer_list check_timer;		/* Poll link status */
-
-	/* Transmit */
-	struct sk_buff *skb;			/* holds skb until xmit interrupt completes */
-	dma_addr_t skb_physaddr;		/* phys addr from pci_map_single */
-	int skb_length;				/* saved skb length for pci_unmap_single */
-
-	/* Receive */
-	int rxBuffIndex;			/* index into receive descriptor list */
-	struct recv_desc_bufs *dlist;		/* descriptor list address */
-	struct recv_desc_bufs *dlist_phys;	/* descriptor list physical address */
-};
-
-#endif
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index 033064b..6a59bce 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -14,8 +14,10 @@
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/circ_buf.h>
 #include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -26,37 +28,74 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_net.h>
+#include <linux/pinctrl/consumer.h>
 
 #include "macb.h"
 
 #define RX_BUFFER_SIZE		128
-#define RX_RING_SIZE		512
-#define RX_RING_BYTES		(sizeof(struct dma_desc) * RX_RING_SIZE)
+#define RX_RING_SIZE		512 /* must be power of 2 */
+#define RX_RING_BYTES		(sizeof(struct macb_dma_desc) * RX_RING_SIZE)
 
-/* Make the IP header word-aligned (the ethernet header is 14 bytes) */
-#define RX_OFFSET		2
+#define TX_RING_SIZE		128 /* must be power of 2 */
+#define TX_RING_BYTES		(sizeof(struct macb_dma_desc) * TX_RING_SIZE)
 
-#define TX_RING_SIZE		128
-#define DEF_TX_RING_PENDING	(TX_RING_SIZE - 1)
-#define TX_RING_BYTES		(sizeof(struct dma_desc) * TX_RING_SIZE)
+/* level of occupied TX descriptors under which we wake up TX process */
+#define MACB_TX_WAKEUP_THRESH	(3 * TX_RING_SIZE / 4)
 
-#define TX_RING_GAP(bp)						\
-	(TX_RING_SIZE - (bp)->tx_pending)
-#define TX_BUFFS_AVAIL(bp)					\
-	(((bp)->tx_tail <= (bp)->tx_head) ?			\
-	 (bp)->tx_tail + (bp)->tx_pending - (bp)->tx_head :	\
-	 (bp)->tx_tail - (bp)->tx_head - TX_RING_GAP(bp))
-#define NEXT_TX(n)		(((n) + 1) & (TX_RING_SIZE - 1))
+#define MACB_RX_INT_FLAGS	(MACB_BIT(RCOMP) | MACB_BIT(RXUBR)	\
+				 | MACB_BIT(ISR_ROVR))
+#define MACB_TX_ERR_FLAGS	(MACB_BIT(ISR_TUND)			\
+					| MACB_BIT(ISR_RLE)		\
+					| MACB_BIT(TXERR))
+#define MACB_TX_INT_FLAGS	(MACB_TX_ERR_FLAGS | MACB_BIT(TCOMP))
 
-#define NEXT_RX(n)		(((n) + 1) & (RX_RING_SIZE - 1))
+/*
+ * Graceful stop timeouts in us. We should allow up to
+ * 1 frame time (10 Mbits/s, full-duplex, ignoring collisions)
+ */
+#define MACB_HALT_TIMEOUT	1230
 
-/* minimum number of free TX descriptors before waking up TX process */
-#define MACB_TX_WAKEUP_THRESH	(TX_RING_SIZE / 4)
+/* Ring buffer accessors */
+static unsigned int macb_tx_ring_wrap(unsigned int index)
+{
+	return index & (TX_RING_SIZE - 1);
+}
 
-#define MACB_RX_INT_FLAGS	(MACB_BIT(RCOMP) | MACB_BIT(RXUBR)	\
-				 | MACB_BIT(ISR_ROVR))
+static struct macb_dma_desc *macb_tx_desc(struct macb *bp, unsigned int index)
+{
+	return &bp->tx_ring[macb_tx_ring_wrap(index)];
+}
 
-static void __macb_set_hwaddr(struct macb *bp)
+static struct macb_tx_skb *macb_tx_skb(struct macb *bp, unsigned int index)
+{
+	return &bp->tx_skb[macb_tx_ring_wrap(index)];
+}
+
+static dma_addr_t macb_tx_dma(struct macb *bp, unsigned int index)
+{
+	dma_addr_t offset;
+
+	offset = macb_tx_ring_wrap(index) * sizeof(struct macb_dma_desc);
+
+	return bp->tx_ring_dma + offset;
+}
+
+static unsigned int macb_rx_ring_wrap(unsigned int index)
+{
+	return index & (RX_RING_SIZE - 1);
+}
+
+static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index)
+{
+	return &bp->rx_ring[macb_rx_ring_wrap(index)];
+}
+
+static void *macb_rx_buffer(struct macb *bp, unsigned int index)
+{
+	return bp->rx_buffers + RX_BUFFER_SIZE * macb_rx_ring_wrap(index);
+}
+
+void macb_set_hwaddr(struct macb *bp)
 {
 	u32 bottom;
 	u16 top;
@@ -65,31 +104,58 @@ static void __macb_set_hwaddr(struct macb *bp)
 	macb_or_gem_writel(bp, SA1B, bottom);
 	top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4)));
 	macb_or_gem_writel(bp, SA1T, top);
+
+	/* Clear unused address register sets */
+	macb_or_gem_writel(bp, SA2B, 0);
+	macb_or_gem_writel(bp, SA2T, 0);
+	macb_or_gem_writel(bp, SA3B, 0);
+	macb_or_gem_writel(bp, SA3T, 0);
+	macb_or_gem_writel(bp, SA4B, 0);
+	macb_or_gem_writel(bp, SA4T, 0);
 }
+EXPORT_SYMBOL_GPL(macb_set_hwaddr);
 
-static void __init macb_get_hwaddr(struct macb *bp)
+void macb_get_hwaddr(struct macb *bp)
 {
+	struct macb_platform_data *pdata;
 	u32 bottom;
 	u16 top;
 	u8 addr[6];
+	int i;
 
-	bottom = macb_or_gem_readl(bp, SA1B);
-	top = macb_or_gem_readl(bp, SA1T);
+	pdata = bp->pdev->dev.platform_data;
 
-	addr[0] = bottom & 0xff;
-	addr[1] = (bottom >> 8) & 0xff;
-	addr[2] = (bottom >> 16) & 0xff;
-	addr[3] = (bottom >> 24) & 0xff;
-	addr[4] = top & 0xff;
-	addr[5] = (top >> 8) & 0xff;
+	/* Check all 4 address register for vaild address */
+	for (i = 0; i < 4; i++) {
+		bottom = macb_or_gem_readl(bp, SA1B + i * 8);
+		top = macb_or_gem_readl(bp, SA1T + i * 8);
+
+		if (pdata && pdata->rev_eth_addr) {
+			addr[5] = bottom & 0xff;
+			addr[4] = (bottom >> 8) & 0xff;
+			addr[3] = (bottom >> 16) & 0xff;
+			addr[2] = (bottom >> 24) & 0xff;
+			addr[1] = top & 0xff;
+			addr[0] = (top & 0xff00) >> 8;
+		} else {
+			addr[0] = bottom & 0xff;
+			addr[1] = (bottom >> 8) & 0xff;
+			addr[2] = (bottom >> 16) & 0xff;
+			addr[3] = (bottom >> 24) & 0xff;
+			addr[4] = top & 0xff;
+			addr[5] = (top >> 8) & 0xff;
+		}
 
-	if (is_valid_ether_addr(addr)) {
-		memcpy(bp->dev->dev_addr, addr, sizeof(addr));
-	} else {
-		netdev_info(bp->dev, "invalid hw address, using random\n");
-		eth_hw_addr_random(bp->dev);
+		if (is_valid_ether_addr(addr)) {
+			memcpy(bp->dev->dev_addr, addr, sizeof(addr));
+			return;
+		}
 	}
+
+	netdev_info(bp->dev, "invalid hw address, using random\n");
+	eth_hw_addr_random(bp->dev);
 }
+EXPORT_SYMBOL_GPL(macb_get_hwaddr);
 
 static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
 {
@@ -152,13 +218,17 @@ static void macb_handle_link_change(struct net_device *dev)
 
 			reg = macb_readl(bp, NCFGR);
 			reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
+			if (macb_is_gem(bp))
+				reg &= ~GEM_BIT(GBE);
 
 			if (phydev->duplex)
 				reg |= MACB_BIT(FD);
 			if (phydev->speed == SPEED_100)
 				reg |= MACB_BIT(SPD);
+			if (phydev->speed == SPEED_1000)
+				reg |= GEM_BIT(GBE);
 
-			macb_writel(bp, NCFGR, reg);
+			macb_or_gem_writel(bp, NCFGR, reg);
 
 			bp->speed = phydev->speed;
 			bp->duplex = phydev->duplex;
@@ -196,7 +266,9 @@ static void macb_handle_link_change(struct net_device *dev)
 static int macb_mii_probe(struct net_device *dev)
 {
 	struct macb *bp = netdev_priv(dev);
+	struct macb_platform_data *pdata;
 	struct phy_device *phydev;
+	int phy_irq;
 	int ret;
 
 	phydev = phy_find_first(bp->mii_bus);
@@ -205,7 +277,14 @@ static int macb_mii_probe(struct net_device *dev)
 		return -1;
 	}
 
-	/* TODO : add pin_irq */
+	pdata = dev_get_platdata(&bp->pdev->dev);
+	if (pdata && gpio_is_valid(pdata->phy_irq_pin)) {
+		ret = devm_gpio_request(&bp->pdev->dev, pdata->phy_irq_pin, "phy int");
+		if (!ret) {
+			phy_irq = gpio_to_irq(pdata->phy_irq_pin);
+			phydev->irq = (phy_irq < 0) ? PHY_POLL : phy_irq;
+		}
+	}
 
 	/* attach the mac to the phy */
 	ret = phy_connect_direct(dev, phydev, &macb_handle_link_change, 0,
@@ -216,7 +295,10 @@ static int macb_mii_probe(struct net_device *dev)
 	}
 
 	/* mask with MAC supported features */
-	phydev->supported &= PHY_BASIC_FEATURES;
+	if (macb_is_gem(bp))
+		phydev->supported &= PHY_GBIT_FEATURES;
+	else
+		phydev->supported &= PHY_BASIC_FEATURES;
 
 	phydev->advertising = phydev->supported;
 
@@ -228,7 +310,7 @@ static int macb_mii_probe(struct net_device *dev)
 	return 0;
 }
 
-static int macb_mii_init(struct macb *bp)
+int macb_mii_init(struct macb *bp)
 {
 	struct macb_platform_data *pdata;
 	int err = -ENXIO, i;
@@ -284,6 +366,7 @@ err_out_free_mdiobus:
 err_out:
 	return err;
 }
+EXPORT_SYMBOL_GPL(macb_mii_init);
 
 static void macb_update_stats(struct macb *bp)
 {
@@ -297,93 +380,148 @@ static void macb_update_stats(struct macb *bp)
 		*p += __raw_readl(reg);
 }
 
-static void macb_tx(struct macb *bp)
+static int macb_halt_tx(struct macb *bp)
 {
-	unsigned int tail;
-	unsigned int head;
-	u32 status;
+	unsigned long	halt_time, timeout;
+	u32		status;
 
-	status = macb_readl(bp, TSR);
-	macb_writel(bp, TSR, status);
+	macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(THALT));
 
-	netdev_dbg(bp->dev, "macb_tx status = %02lx\n", (unsigned long)status);
+	timeout = jiffies + usecs_to_jiffies(MACB_HALT_TIMEOUT);
+	do {
+		halt_time = jiffies;
+		status = macb_readl(bp, TSR);
+		if (!(status & MACB_BIT(TGO)))
+			return 0;
 
-	if (status & (MACB_BIT(UND) | MACB_BIT(TSR_RLE))) {
-		int i;
-		netdev_err(bp->dev, "TX %s, resetting buffers\n",
-			   status & MACB_BIT(UND) ?
-			   "underrun" : "retry limit exceeded");
+		usleep_range(10, 250);
+	} while (time_before(halt_time, timeout));
 
-		/* Transfer ongoing, disable transmitter, to avoid confusion */
-		if (status & MACB_BIT(TGO))
-			macb_writel(bp, NCR, macb_readl(bp, NCR) & ~MACB_BIT(TE));
+	return -ETIMEDOUT;
+}
 
-		head = bp->tx_head;
+static void macb_tx_error_task(struct work_struct *work)
+{
+	struct macb	*bp = container_of(work, struct macb, tx_error_task);
+	struct macb_tx_skb	*tx_skb;
+	struct sk_buff		*skb;
+	unsigned int		tail;
 
-		/*Mark all the buffer as used to avoid sending a lost buffer*/
-		for (i = 0; i < TX_RING_SIZE; i++)
-			bp->tx_ring[i].ctrl = MACB_BIT(TX_USED);
+	netdev_vdbg(bp->dev, "macb_tx_error_task: t = %u, h = %u\n",
+		    bp->tx_tail, bp->tx_head);
 
-		/* Add wrap bit */
-		bp->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
+	/* Make sure nobody is trying to queue up new packets */
+	netif_stop_queue(bp->dev);
 
-		/* free transmit buffer in upper layer*/
-		for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) {
-			struct ring_info *rp = &bp->tx_skb[tail];
-			struct sk_buff *skb = rp->skb;
+	/*
+	 * Stop transmission now
+	 * (in case we have just queued new packets)
+	 */
+	if (macb_halt_tx(bp))
+		/* Just complain for now, reinitializing TX path can be good */
+		netdev_err(bp->dev, "BUG: halt tx timed out\n");
 
-			BUG_ON(skb == NULL);
+	/* No need for the lock here as nobody will interrupt us anymore */
 
-			rmb();
+	/*
+	 * Treat frames in TX queue including the ones that caused the error.
+	 * Free transmit buffers in upper layer.
+	 */
+	for (tail = bp->tx_tail; tail != bp->tx_head; tail++) {
+		struct macb_dma_desc	*desc;
+		u32			ctrl;
+
+		desc = macb_tx_desc(bp, tail);
+		ctrl = desc->ctrl;
+		tx_skb = macb_tx_skb(bp, tail);
+		skb = tx_skb->skb;
+
+		if (ctrl & MACB_BIT(TX_USED)) {
+			netdev_vdbg(bp->dev, "txerr skb %u (data %p) TX complete\n",
+				    macb_tx_ring_wrap(tail), skb->data);
+			bp->stats.tx_packets++;
+			bp->stats.tx_bytes += skb->len;
+		} else {
+			/*
+			 * "Buffers exhausted mid-frame" errors may only happen
+			 * if the driver is buggy, so complain loudly about those.
+			 * Statistics are updated by hardware.
+			 */
+			if (ctrl & MACB_BIT(TX_BUF_EXHAUSTED))
+				netdev_err(bp->dev,
+					   "BUG: TX buffers exhausted mid-frame\n");
 
-			dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len,
-							 DMA_TO_DEVICE);
-			rp->skb = NULL;
-			dev_kfree_skb_irq(skb);
+			desc->ctrl = ctrl | MACB_BIT(TX_USED);
 		}
 
-		bp->tx_head = bp->tx_tail = 0;
-
-		/* Enable the transmitter again */
-		if (status & MACB_BIT(TGO))
-			macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TE));
+		dma_unmap_single(&bp->pdev->dev, tx_skb->mapping, skb->len,
+				 DMA_TO_DEVICE);
+		tx_skb->skb = NULL;
+		dev_kfree_skb(skb);
 	}
 
-	if (!(status & MACB_BIT(COMP)))
-		/*
-		 * This may happen when a buffer becomes complete
-		 * between reading the ISR and scanning the
-		 * descriptors.  Nothing to worry about.
-		 */
-		return;
+	/* Make descriptor updates visible to hardware */
+	wmb();
+
+	/* Reinitialize the TX desc queue */
+	macb_writel(bp, TBQP, bp->tx_ring_dma);
+	/* Make TX ring reflect state of hardware */
+	bp->tx_head = bp->tx_tail = 0;
+
+	/* Now we are ready to start transmission again */
+	netif_wake_queue(bp->dev);
+
+	/* Housework before enabling TX IRQ */
+	macb_writel(bp, TSR, macb_readl(bp, TSR));
+	macb_writel(bp, IER, MACB_TX_INT_FLAGS);
+}
+
+static void macb_tx_interrupt(struct macb *bp)
+{
+	unsigned int tail;
+	unsigned int head;
+	u32 status;
+
+	status = macb_readl(bp, TSR);
+	macb_writel(bp, TSR, status);
+
+	netdev_vdbg(bp->dev, "macb_tx_interrupt status = 0x%03lx\n",
+		(unsigned long)status);
 
 	head = bp->tx_head;
-	for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) {
-		struct ring_info *rp = &bp->tx_skb[tail];
-		struct sk_buff *skb = rp->skb;
-		u32 bufstat;
+	for (tail = bp->tx_tail; tail != head; tail++) {
+		struct macb_tx_skb	*tx_skb;
+		struct sk_buff		*skb;
+		struct macb_dma_desc	*desc;
+		u32			ctrl;
 
-		BUG_ON(skb == NULL);
+		desc = macb_tx_desc(bp, tail);
 
+		/* Make hw descriptor updates visible to CPU */
 		rmb();
-		bufstat = bp->tx_ring[tail].ctrl;
 
-		if (!(bufstat & MACB_BIT(TX_USED)))
+		ctrl = desc->ctrl;
+
+		if (!(ctrl & MACB_BIT(TX_USED)))
 			break;
 
-		netdev_dbg(bp->dev, "skb %u (data %p) TX complete\n",
-			   tail, skb->data);
-		dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len,
+		tx_skb = macb_tx_skb(bp, tail);
+		skb = tx_skb->skb;
+
+		netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
+			macb_tx_ring_wrap(tail), skb->data);
+		dma_unmap_single(&bp->pdev->dev, tx_skb->mapping, skb->len,
 				 DMA_TO_DEVICE);
 		bp->stats.tx_packets++;
 		bp->stats.tx_bytes += skb->len;
-		rp->skb = NULL;
+		tx_skb->skb = NULL;
 		dev_kfree_skb_irq(skb);
 	}
 
 	bp->tx_tail = tail;
-	if (netif_queue_stopped(bp->dev) &&
-	    TX_BUFFS_AVAIL(bp) > MACB_TX_WAKEUP_THRESH)
+	if (netif_queue_stopped(bp->dev)
+			&& CIRC_CNT(bp->tx_head, bp->tx_tail,
+				    TX_RING_SIZE) <= MACB_TX_WAKEUP_THRESH)
 		netif_wake_queue(bp->dev);
 }
 
@@ -392,31 +530,48 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
 {
 	unsigned int len;
 	unsigned int frag;
-	unsigned int offset = 0;
+	unsigned int offset;
 	struct sk_buff *skb;
+	struct macb_dma_desc *desc;
 
-	len = MACB_BFEXT(RX_FRMLEN, bp->rx_ring[last_frag].ctrl);
+	desc = macb_rx_desc(bp, last_frag);
+	len = MACB_BFEXT(RX_FRMLEN, desc->ctrl);
 
-	netdev_dbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
-		   first_frag, last_frag, len);
+	netdev_vdbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
+		macb_rx_ring_wrap(first_frag),
+		macb_rx_ring_wrap(last_frag), len);
 
-	skb = netdev_alloc_skb(bp->dev, len + RX_OFFSET);
+	/*
+	 * The ethernet header starts NET_IP_ALIGN bytes into the
+	 * first buffer. Since the header is 14 bytes, this makes the
+	 * payload word-aligned.
+	 *
+	 * Instead of calling skb_reserve(NET_IP_ALIGN), we just copy
+	 * the two padding bytes into the skb so that we avoid hitting
+	 * the slowpath in memcpy(), and pull them off afterwards.
+	 */
+	skb = netdev_alloc_skb(bp->dev, len + NET_IP_ALIGN);
 	if (!skb) {
 		bp->stats.rx_dropped++;
-		for (frag = first_frag; ; frag = NEXT_RX(frag)) {
-			bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
+		for (frag = first_frag; ; frag++) {
+			desc = macb_rx_desc(bp, frag);
+			desc->addr &= ~MACB_BIT(RX_USED);
 			if (frag == last_frag)
 				break;
 		}
+
+		/* Make descriptor updates visible to hardware */
 		wmb();
+
 		return 1;
 	}
 
-	skb_reserve(skb, RX_OFFSET);
+	offset = 0;
+	len += NET_IP_ALIGN;
 	skb_checksum_none_assert(skb);
 	skb_put(skb, len);
 
-	for (frag = first_frag; ; frag = NEXT_RX(frag)) {
+	for (frag = first_frag; ; frag++) {
 		unsigned int frag_len = RX_BUFFER_SIZE;
 
 		if (offset + frag_len > len) {
@@ -424,22 +579,24 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
 			frag_len = len - offset;
 		}
 		skb_copy_to_linear_data_offset(skb, offset,
-					       (bp->rx_buffers +
-					        (RX_BUFFER_SIZE * frag)),
-					       frag_len);
+				macb_rx_buffer(bp, frag), frag_len);
 		offset += RX_BUFFER_SIZE;
-		bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
-		wmb();
+		desc = macb_rx_desc(bp, frag);
+		desc->addr &= ~MACB_BIT(RX_USED);
 
 		if (frag == last_frag)
 			break;
 	}
 
+	/* Make descriptor updates visible to hardware */
+	wmb();
+
+	__skb_pull(skb, NET_IP_ALIGN);
 	skb->protocol = eth_type_trans(skb, bp->dev);
 
 	bp->stats.rx_packets++;
-	bp->stats.rx_bytes += len;
-	netdev_dbg(bp->dev, "received skb of length %u, csum: %08x\n",
+	bp->stats.rx_bytes += skb->len;
+	netdev_vdbg(bp->dev, "received skb of length %u, csum: %08x\n",
 		   skb->len, skb->csum);
 	netif_receive_skb(skb);
 
@@ -452,8 +609,12 @@ static void discard_partial_frame(struct macb *bp, unsigned int begin,
 {
 	unsigned int frag;
 
-	for (frag = begin; frag != end; frag = NEXT_RX(frag))
-		bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
+	for (frag = begin; frag != end; frag++) {
+		struct macb_dma_desc *desc = macb_rx_desc(bp, frag);
+		desc->addr &= ~MACB_BIT(RX_USED);
+	}
+
+	/* Make descriptor updates visible to hardware */
 	wmb();
 
 	/*
@@ -466,15 +627,18 @@ static void discard_partial_frame(struct macb *bp, unsigned int begin,
 static int macb_rx(struct macb *bp, int budget)
 {
 	int received = 0;
-	unsigned int tail = bp->rx_tail;
+	unsigned int tail;
 	int first_frag = -1;
 
-	for (; budget > 0; tail = NEXT_RX(tail)) {
+	for (tail = bp->rx_tail; budget > 0; tail++) {
+		struct macb_dma_desc *desc = macb_rx_desc(bp, tail);
 		u32 addr, ctrl;
 
+		/* Make hw descriptor updates visible to CPU */
 		rmb();
-		addr = bp->rx_ring[tail].addr;
-		ctrl = bp->rx_ring[tail].ctrl;
+
+		addr = desc->addr;
+		ctrl = desc->ctrl;
 
 		if (!(addr & MACB_BIT(RX_USED)))
 			break;
@@ -517,7 +681,7 @@ static int macb_poll(struct napi_struct *napi, int budget)
 
 	work_done = 0;
 
-	netdev_dbg(bp->dev, "poll: status = %08lx, budget = %d\n",
+	netdev_vdbg(bp->dev, "poll: status = %08lx, budget = %d\n",
 		   (unsigned long)status, budget);
 
 	work_done = macb_rx(bp, budget);
@@ -552,10 +716,12 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
 	while (status) {
 		/* close possible race with dev_close */
 		if (unlikely(!netif_running(dev))) {
-			macb_writel(bp, IDR, ~0UL);
+			macb_writel(bp, IDR, -1);
 			break;
 		}
 
+		netdev_vdbg(bp->dev, "isr = 0x%08lx\n", (unsigned long)status);
+
 		if (status & MACB_RX_INT_FLAGS) {
 			/*
 			 * There's no point taking any more interrupts
@@ -567,14 +733,19 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
 			macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
 
 			if (napi_schedule_prep(&bp->napi)) {
-				netdev_dbg(bp->dev, "scheduling RX softirq\n");
+				netdev_vdbg(bp->dev, "scheduling RX softirq\n");
 				__napi_schedule(&bp->napi);
 			}
 		}
 
-		if (status & (MACB_BIT(TCOMP) | MACB_BIT(ISR_TUND) |
-			    MACB_BIT(ISR_RLE)))
-			macb_tx(bp);
+		if (unlikely(status & (MACB_TX_ERR_FLAGS))) {
+			macb_writel(bp, IDR, MACB_TX_INT_FLAGS);
+			schedule_work(&bp->tx_error_task);
+			break;
+		}
+
+		if (status & MACB_BIT(TCOMP))
+			macb_tx_interrupt(bp);
 
 		/*
 		 * Link change detection isn't possible with RMII, so we'll
@@ -626,11 +797,13 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct macb *bp = netdev_priv(dev);
 	dma_addr_t mapping;
 	unsigned int len, entry;
+	struct macb_dma_desc *desc;
+	struct macb_tx_skb *tx_skb;
 	u32 ctrl;
 	unsigned long flags;
 
-#ifdef DEBUG
-	netdev_dbg(bp->dev,
+#if defined(DEBUG) && defined(VERBOSE_DEBUG)
+	netdev_vdbg(bp->dev,
 		   "start_xmit: len %u head %p data %p tail %p end %p\n",
 		   skb->len, skb->head, skb->data,
 		   skb_tail_pointer(skb), skb_end_pointer(skb));
@@ -642,7 +815,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	spin_lock_irqsave(&bp->lock, flags);
 
 	/* This is a hard error, log it. */
-	if (TX_BUFFS_AVAIL(bp) < 1) {
+	if (CIRC_SPACE(bp->tx_head, bp->tx_tail, TX_RING_SIZE) < 1) {
 		netif_stop_queue(dev);
 		spin_unlock_irqrestore(&bp->lock, flags);
 		netdev_err(bp->dev, "BUG! Tx Ring full when queue awake!\n");
@@ -651,13 +824,16 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		return NETDEV_TX_BUSY;
 	}
 
-	entry = bp->tx_head;
-	netdev_dbg(bp->dev, "Allocated ring entry %u\n", entry);
+	entry = macb_tx_ring_wrap(bp->tx_head);
+	bp->tx_head++;
+	netdev_vdbg(bp->dev, "Allocated ring entry %u\n", entry);
 	mapping = dma_map_single(&bp->pdev->dev, skb->data,
 				 len, DMA_TO_DEVICE);
-	bp->tx_skb[entry].skb = skb;
-	bp->tx_skb[entry].mapping = mapping;
-	netdev_dbg(bp->dev, "Mapped skb data %p to DMA addr %08lx\n",
+
+	tx_skb = &bp->tx_skb[entry];
+	tx_skb->skb = skb;
+	tx_skb->mapping = mapping;
+	netdev_vdbg(bp->dev, "Mapped skb data %p to DMA addr %08lx\n",
 		   skb->data, (unsigned long)mapping);
 
 	ctrl = MACB_BF(TX_FRMLEN, len);
@@ -665,18 +841,18 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (entry == (TX_RING_SIZE - 1))
 		ctrl |= MACB_BIT(TX_WRAP);
 
-	bp->tx_ring[entry].addr = mapping;
-	bp->tx_ring[entry].ctrl = ctrl;
-	wmb();
+	desc = &bp->tx_ring[entry];
+	desc->addr = mapping;
+	desc->ctrl = ctrl;
 
-	entry = NEXT_TX(entry);
-	bp->tx_head = entry;
+	/* Make newly initialized descriptor visible to hardware */
+	wmb();
 
 	skb_tx_timestamp(skb);
 
 	macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
 
-	if (TX_BUFFS_AVAIL(bp) < 1)
+	if (CIRC_SPACE(bp->tx_head, bp->tx_tail, TX_RING_SIZE) < 1)
 		netif_stop_queue(dev);
 
 	spin_unlock_irqrestore(&bp->lock, flags);
@@ -712,7 +888,7 @@ static int macb_alloc_consistent(struct macb *bp)
 {
 	int size;
 
-	size = TX_RING_SIZE * sizeof(struct ring_info);
+	size = TX_RING_SIZE * sizeof(struct macb_tx_skb);
 	bp->tx_skb = kmalloc(size, GFP_KERNEL);
 	if (!bp->tx_skb)
 		goto out_err;
@@ -775,9 +951,6 @@ static void macb_init_rings(struct macb *bp)
 
 static void macb_reset_hw(struct macb *bp)
 {
-	/* Make sure we have the write buffer for ourselves */
-	wmb();
-
 	/*
 	 * Disable RX and TX (XXX: Should we halt the transmission
 	 * more gracefully?)
@@ -788,11 +961,11 @@ static void macb_reset_hw(struct macb *bp)
 	macb_writel(bp, NCR, MACB_BIT(CLRSTAT));
 
 	/* Clear all status flags */
-	macb_writel(bp, TSR, ~0UL);
-	macb_writel(bp, RSR, ~0UL);
+	macb_writel(bp, TSR, -1);
+	macb_writel(bp, RSR, -1);
 
 	/* Disable all interrupts */
-	macb_writel(bp, IDR, ~0UL);
+	macb_writel(bp, IDR, -1);
 	macb_readl(bp, ISR);
 }
 
@@ -860,8 +1033,12 @@ static u32 macb_dbw(struct macb *bp)
 }
 
 /*
- * Configure the receive DMA engine to use the correct receive buffer size.
- * This is a configurable parameter for GEM.
+ * Configure the receive DMA engine
+ * - use the correct receive buffer size
+ * - set the possibility to use INCR16 bursts
+ *   (if not supported by FIFO, it will fallback to default)
+ * - set both rx/tx packet buffers to full memory size
+ * These are configurable parameters for GEM.
  */
 static void macb_configure_dma(struct macb *bp)
 {
@@ -870,6 +1047,8 @@ static void macb_configure_dma(struct macb *bp)
 	if (macb_is_gem(bp)) {
 		dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);
 		dmacfg |= GEM_BF(RXBS, RX_BUFFER_SIZE / 64);
+		dmacfg |= GEM_BF(FBLDO, 16);
+		dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
 		gem_writel(bp, DMACFG, dmacfg);
 	}
 }
@@ -879,9 +1058,10 @@ static void macb_init_hw(struct macb *bp)
 	u32 config;
 
 	macb_reset_hw(bp);
-	__macb_set_hwaddr(bp);
+	macb_set_hwaddr(bp);
 
 	config = macb_mdc_clk_div(bp);
+	config |= MACB_BF(RBOF, NET_IP_ALIGN);	/* Make eth data aligned */
 	config |= MACB_BIT(PAE);		/* PAuse Enable */
 	config |= MACB_BIT(DRFCS);		/* Discard Rx FCS */
 	config |= MACB_BIT(BIG);		/* Receive oversized frames */
@@ -891,6 +1071,8 @@ static void macb_init_hw(struct macb *bp)
 		config |= MACB_BIT(NBC);	/* No BroadCast */
 	config |= macb_dbw(bp);
 	macb_writel(bp, NCFGR, config);
+	bp->speed = SPEED_10;
+	bp->duplex = DUPLEX_HALF;
 
 	macb_configure_dma(bp);
 
@@ -902,13 +1084,8 @@ static void macb_init_hw(struct macb *bp)
 	macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE));
 
 	/* Enable interrupts */
-	macb_writel(bp, IER, (MACB_BIT(RCOMP)
-			      | MACB_BIT(RXUBR)
-			      | MACB_BIT(ISR_TUND)
-			      | MACB_BIT(ISR_RLE)
-			      | MACB_BIT(TXERR)
-			      | MACB_BIT(TCOMP)
-			      | MACB_BIT(ISR_ROVR)
+	macb_writel(bp, IER, (MACB_RX_INT_FLAGS
+			      | MACB_TX_INT_FLAGS
 			      | MACB_BIT(HRESP)));
 
 }
@@ -996,7 +1173,7 @@ static void macb_sethashtable(struct net_device *dev)
 /*
  * Enable/Disable promiscuous and multicast modes.
  */
-static void macb_set_rx_mode(struct net_device *dev)
+void macb_set_rx_mode(struct net_device *dev)
 {
 	unsigned long cfg;
 	struct macb *bp = netdev_priv(dev);
@@ -1028,6 +1205,7 @@ static void macb_set_rx_mode(struct net_device *dev)
 
 	macb_writel(bp, NCFGR, cfg);
 }
+EXPORT_SYMBOL_GPL(macb_set_rx_mode);
 
 static int macb_open(struct net_device *dev)
 {
@@ -1043,9 +1221,6 @@ static int macb_open(struct net_device *dev)
 	if (!bp->phy_dev)
 		return -EAGAIN;
 
-	if (!is_valid_ether_addr(dev->dev_addr))
-		return -EADDRNOTAVAIL;
-
 	err = macb_alloc_consistent(bp);
 	if (err) {
 		netdev_err(dev, "Unable to allocate DMA memory (error %d)\n",
@@ -1135,7 +1310,7 @@ static struct net_device_stats *gem_get_stats(struct macb *bp)
 	return nstat;
 }
 
-static struct net_device_stats *macb_get_stats(struct net_device *dev)
+struct net_device_stats *macb_get_stats(struct net_device *dev)
 {
 	struct macb *bp = netdev_priv(dev);
 	struct net_device_stats *nstat = &bp->stats;
@@ -1181,6 +1356,7 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev)
 
 	return nstat;
 }
+EXPORT_SYMBOL_GPL(macb_get_stats);
 
 static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
@@ -1204,25 +1380,55 @@ static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 	return phy_ethtool_sset(phydev, cmd);
 }
 
-static void macb_get_drvinfo(struct net_device *dev,
-			     struct ethtool_drvinfo *info)
+static int macb_get_regs_len(struct net_device *netdev)
+{
+	return MACB_GREGS_NBR * sizeof(u32);
+}
+
+static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+			  void *p)
 {
 	struct macb *bp = netdev_priv(dev);
+	unsigned int tail, head;
+	u32 *regs_buff = p;
+
+	regs->version = (macb_readl(bp, MID) & ((1 << MACB_REV_SIZE) - 1))
+			| MACB_GREGS_VERSION;
+
+	tail = macb_tx_ring_wrap(bp->tx_tail);
+	head = macb_tx_ring_wrap(bp->tx_head);
+
+	regs_buff[0]  = macb_readl(bp, NCR);
+	regs_buff[1]  = macb_or_gem_readl(bp, NCFGR);
+	regs_buff[2]  = macb_readl(bp, NSR);
+	regs_buff[3]  = macb_readl(bp, TSR);
+	regs_buff[4]  = macb_readl(bp, RBQP);
+	regs_buff[5]  = macb_readl(bp, TBQP);
+	regs_buff[6]  = macb_readl(bp, RSR);
+	regs_buff[7]  = macb_readl(bp, IMR);
 
-	strcpy(info->driver, bp->pdev->dev.driver->name);
-	strcpy(info->version, "$Revision: 1.14 $");
-	strcpy(info->bus_info, dev_name(&bp->pdev->dev));
+	regs_buff[8]  = tail;
+	regs_buff[9]  = head;
+	regs_buff[10] = macb_tx_dma(bp, tail);
+	regs_buff[11] = macb_tx_dma(bp, head);
+
+	if (macb_is_gem(bp)) {
+		regs_buff[12] = gem_readl(bp, USRIO);
+		regs_buff[13] = gem_readl(bp, DMACFG);
+	}
 }
 
-static const struct ethtool_ops macb_ethtool_ops = {
+const struct ethtool_ops macb_ethtool_ops = {
 	.get_settings		= macb_get_settings,
 	.set_settings		= macb_set_settings,
-	.get_drvinfo		= macb_get_drvinfo,
+	.get_regs_len		= macb_get_regs_len,
+	.get_regs		= macb_get_regs,
 	.get_link		= ethtool_op_get_link,
 	.get_ts_info		= ethtool_op_get_ts_info,
 };
+EXPORT_SYMBOL_GPL(macb_ethtool_ops);
 
-static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct macb *bp = netdev_priv(dev);
 	struct phy_device *phydev = bp->phy_dev;
@@ -1235,6 +1441,7 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
 	return phy_mii_ioctl(phydev, rq, cmd);
 }
+EXPORT_SYMBOL_GPL(macb_ioctl);
 
 static const struct net_device_ops macb_netdev_ops = {
 	.ndo_open		= macb_open,
@@ -1306,6 +1513,7 @@ static int __init macb_probe(struct platform_device *pdev)
 	struct phy_device *phydev;
 	u32 config;
 	int err = -ENXIO;
+	struct pinctrl *pinctrl;
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!regs) {
@@ -1313,6 +1521,15 @@ static int __init macb_probe(struct platform_device *pdev)
 		goto err_out;
 	}
 
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl)) {
+		err = PTR_ERR(pinctrl);
+		if (err == -EPROBE_DEFER)
+			goto err_out;
+
+		dev_warn(&pdev->dev, "No pinctrl provided\n");
+	}
+
 	err = -ENOMEM;
 	dev = alloc_etherdev(sizeof(*bp));
 	if (!dev)
@@ -1328,6 +1545,7 @@ static int __init macb_probe(struct platform_device *pdev)
 	bp->dev = dev;
 
 	spin_lock_init(&bp->lock);
+	INIT_WORK(&bp->tx_error_task, macb_tx_error_task);
 
 	bp->pclk = clk_get(&pdev->dev, "pclk");
 	if (IS_ERR(bp->pclk)) {
@@ -1384,7 +1602,9 @@ static int __init macb_probe(struct platform_device *pdev)
 		bp->phy_interface = err;
 	}
 
-	if (bp->phy_interface == PHY_INTERFACE_MODE_RMII)
+	if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII)
+		macb_or_gem_writel(bp, USRIO, GEM_BIT(RGMII));
+	else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII)
 #if defined(CONFIG_ARCH_AT91)
 		macb_or_gem_writel(bp, USRIO, (MACB_BIT(RMII) |
 					       MACB_BIT(CLKEN)));
@@ -1398,8 +1618,6 @@ static int __init macb_probe(struct platform_device *pdev)
 		macb_or_gem_writel(bp, USRIO, MACB_BIT(MII));
 #endif
 
-	bp->tx_pending = DEF_TX_RING_PENDING;
-
 	err = register_netdev(dev);
 	if (err) {
 		dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 335e288..570908b 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -10,10 +10,15 @@
 #ifndef _MACB_H
 #define _MACB_H
 
+#define MACB_GREGS_NBR 16
+#define MACB_GREGS_VERSION 1
+
 /* MACB register offsets */
 #define MACB_NCR				0x0000
 #define MACB_NCFGR				0x0004
 #define MACB_NSR				0x0008
+#define MACB_TAR				0x000c /* AT91RM9200 only */
+#define MACB_TCR				0x0010 /* AT91RM9200 only */
 #define MACB_TSR				0x0014
 #define MACB_RBQP				0x0018
 #define MACB_TBQP				0x001c
@@ -69,6 +74,12 @@
 #define GEM_HRT					0x0084
 #define GEM_SA1B				0x0088
 #define GEM_SA1T				0x008C
+#define GEM_SA2B				0x0090
+#define GEM_SA2T				0x0094
+#define GEM_SA3B				0x0098
+#define GEM_SA3T				0x009C
+#define GEM_SA4B				0x00A0
+#define GEM_SA4T				0x00A4
 #define GEM_OTX					0x0100
 #define GEM_DCFG1				0x0280
 #define GEM_DCFG2				0x0284
@@ -133,6 +144,8 @@
 #define MACB_RTY_SIZE				1
 #define MACB_PAE_OFFSET				13
 #define MACB_PAE_SIZE				1
+#define MACB_RM9200_RMII_OFFSET			13 /* AT91RM9200 only */
+#define MACB_RM9200_RMII_SIZE			1  /* AT91RM9200 only */
 #define MACB_RBOF_OFFSET			14
 #define MACB_RBOF_SIZE				2
 #define MACB_RLCE_OFFSET			16
@@ -145,6 +158,8 @@
 #define MACB_IRXFCS_SIZE			1
 
 /* GEM specific NCFGR bitfields. */
+#define GEM_GBE_OFFSET				10
+#define GEM_GBE_SIZE				1
 #define GEM_CLK_OFFSET				18
 #define GEM_CLK_SIZE				3
 #define GEM_DBW_OFFSET				21
@@ -156,8 +171,19 @@
 #define GEM_DBW128				2
 
 /* Bitfields in DMACFG. */
+#define GEM_FBLDO_OFFSET			0
+#define GEM_FBLDO_SIZE				5
+#define GEM_RXBMS_OFFSET			8
+#define GEM_RXBMS_SIZE				2
+#define GEM_TXPBMS_OFFSET			10
+#define GEM_TXPBMS_SIZE				1
+#define GEM_TXCOEN_OFFSET			11
+#define GEM_TXCOEN_SIZE				1
 #define GEM_RXBS_OFFSET				16
 #define GEM_RXBS_SIZE				8
+#define GEM_DDRP_OFFSET				24
+#define GEM_DDRP_SIZE				1
+
 
 /* Bitfields in NSR */
 #define MACB_NSR_LINK_OFFSET			0
@@ -178,6 +204,8 @@
 #define MACB_TGO_SIZE				1
 #define MACB_BEX_OFFSET				4
 #define MACB_BEX_SIZE				1
+#define MACB_RM9200_BNQ_OFFSET			4 /* AT91RM9200 only */
+#define MACB_RM9200_BNQ_SIZE			1 /* AT91RM9200 only */
 #define MACB_COMP_OFFSET			5
 #define MACB_COMP_SIZE				1
 #define MACB_UND_OFFSET				6
@@ -246,6 +274,8 @@
 /* Bitfields in USRIO (AT91) */
 #define MACB_RMII_OFFSET			0
 #define MACB_RMII_SIZE				1
+#define GEM_RGMII_OFFSET			0	/* GEM gigabit mode */
+#define GEM_RGMII_SIZE				1
 #define MACB_CLKEN_OFFSET			1
 #define MACB_CLKEN_SIZE				1
 
@@ -352,7 +382,12 @@
 		__v; \
 	})
 
-struct dma_desc {
+/**
+ * struct macb_dma_desc - Hardware DMA descriptor
+ * @addr: DMA address of data buffer
+ * @ctrl: Control and status bits
+ */
+struct macb_dma_desc {
 	u32	addr;
 	u32	ctrl;
 };
@@ -417,7 +452,12 @@ struct dma_desc {
 #define MACB_TX_USED_OFFSET			31
 #define MACB_TX_USED_SIZE			1
 
-struct ring_info {
+/**
+ * struct macb_tx_skb - data about an skb which is being transmitted
+ * @skb: skb currently being transmitted
+ * @mapping: DMA address of the skb's data buffer
+ */
+struct macb_tx_skb {
 	struct sk_buff		*skb;
 	dma_addr_t		mapping;
 };
@@ -502,12 +542,12 @@ struct macb {
 	void __iomem		*regs;
 
 	unsigned int		rx_tail;
-	struct dma_desc		*rx_ring;
+	struct macb_dma_desc	*rx_ring;
 	void			*rx_buffers;
 
 	unsigned int		tx_head, tx_tail;
-	struct dma_desc		*tx_ring;
-	struct ring_info	*tx_skb;
+	struct macb_dma_desc	*tx_ring;
+	struct macb_tx_skb	*tx_skb;
 
 	spinlock_t		lock;
 	struct platform_device	*pdev;
@@ -515,6 +555,7 @@ struct macb {
 	struct clk		*hclk;
 	struct net_device	*dev;
 	struct napi_struct	napi;
+	struct work_struct	tx_error_task;
 	struct net_device_stats	stats;
 	union {
 		struct macb_stats	macb;
@@ -525,8 +566,6 @@ struct macb {
 	dma_addr_t		tx_ring_dma;
 	dma_addr_t		rx_buffers_dma;
 
-	unsigned int		rx_pending, tx_pending;
-
 	struct mii_bus		*mii_bus;
 	struct phy_device	*phy_dev;
 	unsigned int 		link;
@@ -534,8 +573,22 @@ struct macb {
 	unsigned int 		duplex;
 
 	phy_interface_t		phy_interface;
+
+	/* AT91RM9200 transmit */
+	struct sk_buff *skb;			/* holds skb until xmit interrupt completes */
+	dma_addr_t skb_physaddr;		/* phys addr from pci_map_single */
+	int skb_length;				/* saved skb length for pci_unmap_single */
 };
 
+extern const struct ethtool_ops macb_ethtool_ops;
+
+int macb_mii_init(struct macb *bp);
+int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+struct net_device_stats *macb_get_stats(struct net_device *dev);
+void macb_set_rx_mode(struct net_device *dev);
+void macb_set_hwaddr(struct macb *bp);
+void macb_get_hwaddr(struct macb *bp);
+
 static inline bool macb_is_gem(struct macb *bp)
 {
 	return MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2;
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 16814b3..b407043 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -191,6 +191,7 @@
 #define DMA_CONTROL_ST		0x00002000	/* Start/Stop Transmission */
 #define DMA_CONTROL_SR		0x00000002	/* Start/Stop Receive */
 #define DMA_CONTROL_DFF		0x01000000	/* Disable flush of rx frames */
+#define DMA_CONTROL_OSF		0x00000004	/* Operate on 2nd tx frame */
 
 /* DMA Normal interrupt */
 #define DMA_INTR_ENA_NIE	0x00010000	/* Normal Summary */
@@ -210,7 +211,7 @@
 #define DMA_INTR_ENA_TIE	0x00000001	/* Transmit Interrupt */
 
 #define DMA_INTR_NORMAL		(DMA_INTR_ENA_NIE | DMA_INTR_ENA_RIE | \
-				 DMA_INTR_ENA_TUE)
+				 DMA_INTR_ENA_TUE | DMA_INTR_ENA_TIE)
 
 #define DMA_INTR_ABNORMAL	(DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \
 				 DMA_INTR_ENA_RWE | DMA_INTR_ENA_RSE | \
@@ -373,6 +374,7 @@ struct xgmac_priv {
 	struct sk_buff **tx_skbuff;
 	unsigned int tx_head;
 	unsigned int tx_tail;
+	int tx_irq_cnt;
 
 	void __iomem *base;
 	unsigned int dma_buf_sz;
@@ -663,6 +665,7 @@ static void xgmac_rx_refill(struct xgmac_priv *priv)
 {
 	struct xgmac_dma_desc *p;
 	dma_addr_t paddr;
+	int bufsz = priv->dev->mtu + ETH_HLEN + ETH_FCS_LEN;
 
 	while (dma_ring_space(priv->rx_head, priv->rx_tail, DMA_RX_RING_SZ) > 1) {
 		int entry = priv->rx_head;
@@ -671,13 +674,13 @@ static void xgmac_rx_refill(struct xgmac_priv *priv)
 		p = priv->dma_rx + entry;
 
 		if (priv->rx_skbuff[entry] == NULL) {
-			skb = netdev_alloc_skb(priv->dev, priv->dma_buf_sz);
+			skb = netdev_alloc_skb_ip_align(priv->dev, bufsz);
 			if (unlikely(skb == NULL))
 				break;
 
 			priv->rx_skbuff[entry] = skb;
 			paddr = dma_map_single(priv->device, skb->data,
-					       priv->dma_buf_sz, DMA_FROM_DEVICE);
+					       bufsz, DMA_FROM_DEVICE);
 			desc_set_buf_addr(p, paddr, priv->dma_buf_sz);
 		}
 
@@ -701,10 +704,10 @@ static int xgmac_dma_desc_rings_init(struct net_device *dev)
 	unsigned int bfsize;
 
 	/* Set the Buffer size according to the MTU;
-	 * indeed, in case of jumbo we need to bump-up the buffer sizes.
+	 * The total buffer size including any IP offset must be a multiple
+	 * of 8 bytes.
 	 */
-	bfsize = ALIGN(dev->mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN + 64,
-		       64);
+	bfsize = ALIGN(dev->mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN, 8);
 
 	netdev_dbg(priv->dev, "mtu [%d] bfsize [%d]\n", dev->mtu, bfsize);
 
@@ -845,9 +848,6 @@ static void xgmac_free_dma_desc_rings(struct xgmac_priv *priv)
 static void xgmac_tx_complete(struct xgmac_priv *priv)
 {
 	int i;
-	void __iomem *ioaddr = priv->base;
-
-	writel(DMA_STATUS_TU | DMA_STATUS_NIS, ioaddr + XGMAC_DMA_STATUS);
 
 	while (dma_ring_cnt(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ)) {
 		unsigned int entry = priv->tx_tail;
@@ -888,7 +888,7 @@ static void xgmac_tx_complete(struct xgmac_priv *priv)
 	}
 
 	if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) >
-	    TX_THRESH)
+	    MAX_SKB_FRAGS)
 		netif_wake_queue(priv->dev);
 }
 
@@ -965,8 +965,7 @@ static int xgmac_hw_init(struct net_device *dev)
 		ctrl |= XGMAC_CONTROL_IPC;
 	writel(ctrl, ioaddr + XGMAC_CONTROL);
 
-	value = DMA_CONTROL_DFF;
-	writel(value, ioaddr + XGMAC_DMA_CONTROL);
+	writel(DMA_CONTROL_OSF, ioaddr + XGMAC_DMA_CONTROL);
 
 	/* Set the HW DMA mode and the COE */
 	writel(XGMAC_OMR_TSF | XGMAC_OMR_RFD | XGMAC_OMR_RFA |
@@ -1060,19 +1059,15 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct xgmac_priv *priv = netdev_priv(dev);
 	unsigned int entry;
 	int i;
+	u32 irq_flag;
 	int nfrags = skb_shinfo(skb)->nr_frags;
 	struct xgmac_dma_desc *desc, *first;
 	unsigned int desc_flags;
 	unsigned int len;
 	dma_addr_t paddr;
 
-	if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) <
-	    (nfrags + 1)) {
-		writel(DMA_INTR_DEFAULT_MASK | DMA_INTR_ENA_TIE,
-			priv->base + XGMAC_DMA_INTR_ENA);
-		netif_stop_queue(dev);
-		return NETDEV_TX_BUSY;
-	}
+	priv->tx_irq_cnt = (priv->tx_irq_cnt + 1) & (DMA_TX_RING_SZ/4 - 1);
+	irq_flag = priv->tx_irq_cnt ? 0 : TXDESC_INTERRUPT;
 
 	desc_flags = (skb->ip_summed == CHECKSUM_PARTIAL) ?
 		TXDESC_CSUM_ALL : 0;
@@ -1113,9 +1108,9 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
 	/* Interrupt on completition only for the latest segment */
 	if (desc != first)
 		desc_set_tx_owner(desc, desc_flags |
-			TXDESC_LAST_SEG | TXDESC_INTERRUPT);
+			TXDESC_LAST_SEG | irq_flag);
 	else
-		desc_flags |= TXDESC_LAST_SEG | TXDESC_INTERRUPT;
+		desc_flags |= TXDESC_LAST_SEG | irq_flag;
 
 	/* Set owner on first desc last to avoid race condition */
 	wmb();
@@ -1124,6 +1119,9 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
 	priv->tx_head = dma_ring_incr(entry, DMA_TX_RING_SZ);
 
 	writel(1, priv->base + XGMAC_DMA_TX_POLL);
+	if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) <
+	    MAX_SKB_FRAGS)
+		netif_stop_queue(dev);
 
 	return NETDEV_TX_OK;
 }
@@ -1139,9 +1137,6 @@ static int xgmac_rx(struct xgmac_priv *priv, int limit)
 		struct sk_buff *skb;
 		int frame_len;
 
-		writel(DMA_STATUS_RI | DMA_STATUS_NIS,
-		       priv->base + XGMAC_DMA_STATUS);
-
 		entry = priv->rx_tail;
 		p = priv->dma_rx + entry;
 		if (desc_get_owner(p))
@@ -1180,8 +1175,6 @@ static int xgmac_rx(struct xgmac_priv *priv, int limit)
 
 	xgmac_rx_refill(priv);
 
-	writel(1, priv->base + XGMAC_DMA_RX_POLL);
-
 	return count;
 }
 
@@ -1205,7 +1198,7 @@ static int xgmac_poll(struct napi_struct *napi, int budget)
 
 	if (work_done < budget) {
 		napi_complete(napi);
-		writel(DMA_INTR_DEFAULT_MASK, priv->base + XGMAC_DMA_INTR_ENA);
+		__raw_writel(DMA_INTR_DEFAULT_MASK, priv->base + XGMAC_DMA_INTR_ENA);
 	}
 	return work_done;
 }
@@ -1350,7 +1343,7 @@ static irqreturn_t xgmac_pmt_interrupt(int irq, void *dev_id)
 	struct xgmac_priv *priv = netdev_priv(dev);
 	void __iomem *ioaddr = priv->base;
 
-	intr_status = readl(ioaddr + XGMAC_INT_STAT);
+	intr_status = __raw_readl(ioaddr + XGMAC_INT_STAT);
 	if (intr_status & XGMAC_INT_STAT_PMT) {
 		netdev_dbg(priv->dev, "received Magic frame\n");
 		/* clear the PMT bits 5 and 6 by reading the PMT */
@@ -1368,9 +1361,9 @@ static irqreturn_t xgmac_interrupt(int irq, void *dev_id)
 	struct xgmac_extra_stats *x = &priv->xstats;
 
 	/* read the status register (CSR5) */
-	intr_status = readl(priv->base + XGMAC_DMA_STATUS);
-	intr_status &= readl(priv->base + XGMAC_DMA_INTR_ENA);
-	writel(intr_status, priv->base + XGMAC_DMA_STATUS);
+	intr_status = __raw_readl(priv->base + XGMAC_DMA_STATUS);
+	intr_status &= __raw_readl(priv->base + XGMAC_DMA_INTR_ENA);
+	__raw_writel(intr_status, priv->base + XGMAC_DMA_STATUS);
 
 	/* It displays the DMA process states (CSR5 register) */
 	/* ABNORMAL interrupts */
@@ -1405,8 +1398,8 @@ static irqreturn_t xgmac_interrupt(int irq, void *dev_id)
 	}
 
 	/* TX/RX NORMAL interrupts */
-	if (intr_status & (DMA_STATUS_RI | DMA_STATUS_TU)) {
-		writel(DMA_INTR_ABNORMAL, priv->base + XGMAC_DMA_INTR_ENA);
+	if (intr_status & (DMA_STATUS_RI | DMA_STATUS_TU | DMA_STATUS_TI)) {
+		__raw_writel(DMA_INTR_ABNORMAL, priv->base + XGMAC_DMA_INTR_ENA);
 		napi_schedule(&priv->napi);
 	}
 
diff --git a/drivers/net/ethernet/chelsio/Kconfig b/drivers/net/ethernet/chelsio/Kconfig
index 2de50f9..a71c0f3 100644
--- a/drivers/net/ethernet/chelsio/Kconfig
+++ b/drivers/net/ethernet/chelsio/Kconfig
@@ -5,7 +5,7 @@
 config NET_VENDOR_CHELSIO
 	bool "Chelsio devices"
 	default y
-	depends on PCI || INET
+	depends on PCI
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y
 	  and read the Ethernet-HOWTO, available from
@@ -48,7 +48,7 @@ config CHELSIO_T1_1G
 
 config CHELSIO_T3
 	tristate "Chelsio Communications T3 10Gb Ethernet support"
-	depends on PCI && INET
+	depends on PCI
 	select FW_LOADER
 	select MDIO
 	---help---
diff --git a/drivers/net/ethernet/chelsio/cxgb3/common.h b/drivers/net/ethernet/chelsio/cxgb3/common.h
index df01b63..8c82248 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/common.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/common.h
@@ -42,10 +42,9 @@
 #include <linux/mdio.h>
 #include "version.h"
 
-#define CH_ERR(adap, fmt, ...)   dev_err(&adap->pdev->dev, fmt, ## __VA_ARGS__)
-#define CH_WARN(adap, fmt, ...)  dev_warn(&adap->pdev->dev, fmt, ## __VA_ARGS__)
-#define CH_ALERT(adap, fmt, ...) \
-	dev_printk(KERN_ALERT, &adap->pdev->dev, fmt, ## __VA_ARGS__)
+#define CH_ERR(adap, fmt, ...)   dev_err(&adap->pdev->dev, fmt, ##__VA_ARGS__)
+#define CH_WARN(adap, fmt, ...)  dev_warn(&adap->pdev->dev, fmt, ##__VA_ARGS__)
+#define CH_ALERT(adap, fmt, ...) dev_alert(&adap->pdev->dev, fmt, ##__VA_ARGS__)
 
 /*
  * More powerful macro that selectively prints messages based on msg_enable.
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 0df1284..17ab96d 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3203,7 +3203,7 @@ static int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c)
 	memset(c, 0, sizeof(*c));
 	c->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
 			       FW_CMD_REQUEST | FW_CMD_READ);
-	c->retval_len16 = htonl(FW_LEN16(*c));
+	c->cfvalid_to_len16 = htonl(FW_LEN16(*c));
 	ret = t4_wr_mbox(adap, adap->fn, c, sizeof(*c), c);
 	if (ret < 0)
 		return ret;
@@ -3397,7 +3397,7 @@ static int adap_init0_config(struct adapter *adapter, int reset)
 		htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
 		      FW_CMD_REQUEST |
 		      FW_CMD_READ);
-	caps_cmd.retval_len16 =
+	caps_cmd.cfvalid_to_len16 =
 		htonl(FW_CAPS_CONFIG_CMD_CFVALID |
 		      FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) |
 		      FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(maddr >> 16) |
@@ -3422,7 +3422,7 @@ static int adap_init0_config(struct adapter *adapter, int reset)
 		htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
 		      FW_CMD_REQUEST |
 		      FW_CMD_WRITE);
-	caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd));
+	caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
 	ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd),
 			 NULL);
 	if (ret < 0)
@@ -3497,7 +3497,7 @@ static int adap_init0_no_config(struct adapter *adapter, int reset)
 	memset(&caps_cmd, 0, sizeof(caps_cmd));
 	caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
 				     FW_CMD_REQUEST | FW_CMD_READ);
-	caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd));
+	caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
 	ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd),
 			 &caps_cmd);
 	if (ret < 0)
@@ -3929,7 +3929,7 @@ static int adap_init0(struct adapter *adap)
 	memset(&caps_cmd, 0, sizeof(caps_cmd));
 	caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
 				     FW_CMD_REQUEST | FW_CMD_READ);
-	caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd));
+	caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
 	ret = t4_wr_mbox(adap, adap->mbox, &caps_cmd, sizeof(caps_cmd),
 			 &caps_cmd);
 	if (ret < 0)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index 3ecc087..fe9a2ea 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -508,7 +508,7 @@ static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q)
 {
 	if (q->pend_cred >= 8) {
 		wmb();
-		t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), DBPRIO |
+		t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), DBPRIO(1) |
 			     QID(q->cntxt_id) | PIDX(q->pend_cred / 8));
 		q->pend_cred &= 7;
 	}
@@ -2082,10 +2082,10 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
 			goto fl_nomem;
 
 		flsz = fl->size / 8 + s->stat_len / sizeof(struct tx_desc);
-		c.iqns_to_fl0congen = htonl(FW_IQ_CMD_FL0PACKEN |
+		c.iqns_to_fl0congen = htonl(FW_IQ_CMD_FL0PACKEN(1) |
 					    FW_IQ_CMD_FL0FETCHRO(1) |
 					    FW_IQ_CMD_FL0DATARO(1) |
-					    FW_IQ_CMD_FL0PADEN);
+					    FW_IQ_CMD_FL0PADEN(1));
 		c.fl0dcaen_to_fl0cidxfthresh = htons(FW_IQ_CMD_FL0FBMIN(2) |
 				FW_IQ_CMD_FL0FBMAX(3));
 		c.fl0size = htons(flsz);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 730ae2c..137e1f8 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -648,12 +648,12 @@ static int sf1_read(struct adapter *adapter, unsigned int byte_cnt, int cont,
 
 	if (!byte_cnt || byte_cnt > 4)
 		return -EINVAL;
-	if (t4_read_reg(adapter, SF_OP) & BUSY)
+	if (t4_read_reg(adapter, SF_OP) & SF_BUSY)
 		return -EBUSY;
 	cont = cont ? SF_CONT : 0;
 	lock = lock ? SF_LOCK : 0;
 	t4_write_reg(adapter, SF_OP, lock | cont | BYTECNT(byte_cnt - 1));
-	ret = t4_wait_op_done(adapter, SF_OP, BUSY, 0, SF_ATTEMPTS, 5);
+	ret = t4_wait_op_done(adapter, SF_OP, SF_BUSY, 0, SF_ATTEMPTS, 5);
 	if (!ret)
 		*valp = t4_read_reg(adapter, SF_DATA);
 	return ret;
@@ -676,14 +676,14 @@ static int sf1_write(struct adapter *adapter, unsigned int byte_cnt, int cont,
 {
 	if (!byte_cnt || byte_cnt > 4)
 		return -EINVAL;
-	if (t4_read_reg(adapter, SF_OP) & BUSY)
+	if (t4_read_reg(adapter, SF_OP) & SF_BUSY)
 		return -EBUSY;
 	cont = cont ? SF_CONT : 0;
 	lock = lock ? SF_LOCK : 0;
 	t4_write_reg(adapter, SF_DATA, val);
 	t4_write_reg(adapter, SF_OP, lock |
 		     cont | BYTECNT(byte_cnt - 1) | OP_WR);
-	return t4_wait_op_done(adapter, SF_OP, BUSY, 0, SF_ATTEMPTS, 5);
+	return t4_wait_op_done(adapter, SF_OP, SF_BUSY, 0, SF_ATTEMPTS, 5);
 }
 
 /**
@@ -2252,14 +2252,14 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
 		t4_write_reg(adap, EPIO_REG(DATA0), mask0);
 		t4_write_reg(adap, EPIO_REG(OP), ADDRESS(i) | EPIOWR);
 		t4_read_reg(adap, EPIO_REG(OP));                /* flush */
-		if (t4_read_reg(adap, EPIO_REG(OP)) & BUSY)
+		if (t4_read_reg(adap, EPIO_REG(OP)) & SF_BUSY)
 			return -ETIMEDOUT;
 
 		/* write CRC */
 		t4_write_reg(adap, EPIO_REG(DATA0), crc);
 		t4_write_reg(adap, EPIO_REG(OP), ADDRESS(i + 32) | EPIOWR);
 		t4_read_reg(adap, EPIO_REG(OP));                /* flush */
-		if (t4_read_reg(adap, EPIO_REG(OP)) & BUSY)
+		if (t4_read_reg(adap, EPIO_REG(OP)) & SF_BUSY)
 			return -ETIMEDOUT;
 	}
 #undef EPIO_REG
@@ -2405,7 +2405,7 @@ int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox,
 retry:
 	memset(&c, 0, sizeof(c));
 	INIT_CMD(c, HELLO, WRITE);
-	c.err_to_mbasyncnot = htonl(
+	c.err_to_clearinit = htonl(
 		FW_HELLO_CMD_MASTERDIS(master == MASTER_CANT) |
 		FW_HELLO_CMD_MASTERFORCE(master == MASTER_MUST) |
 		FW_HELLO_CMD_MBMASTER(master == MASTER_MUST ? mbox :
@@ -2426,7 +2426,7 @@ retry:
 		return ret;
 	}
 
-	v = ntohl(c.err_to_mbasyncnot);
+	v = ntohl(c.err_to_clearinit);
 	master_mbox = FW_HELLO_CMD_MBMASTER_GET(v);
 	if (state) {
 		if (v & FW_HELLO_CMD_ERR)
@@ -2774,7 +2774,7 @@ int t4_fw_config_file(struct adapter *adap, unsigned int mbox,
 		htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
 		      FW_CMD_REQUEST |
 		      FW_CMD_READ);
-	caps_cmd.retval_len16 =
+	caps_cmd.cfvalid_to_len16 =
 		htonl(FW_CAPS_CONFIG_CMD_CFVALID |
 		      FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) |
 		      FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(maddr >> 16) |
@@ -2797,7 +2797,7 @@ int t4_fw_config_file(struct adapter *adap, unsigned int mbox,
 		htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
 		      FW_CMD_REQUEST |
 		      FW_CMD_WRITE);
-	caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd));
+	caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
 	return t4_wr_mbox(adap, mbox, &caps_cmd, sizeof(caps_cmd), NULL);
 }
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
index eb71b82..b760808 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
@@ -658,6 +658,7 @@ struct ulptx_sgl {
 	__be32 cmd_nsge;
 #define ULPTX_CMD(x) ((x) << 24)
 #define ULPTX_NSGE(x) ((x) << 0)
+#define ULPTX_MORE (1U << 23)
 	__be32 len0;
 	__be64 addr0;
 	struct ulptx_sge_pair sge[0];
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index a1a8b57..75393f5 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -67,7 +67,7 @@
 #define  QID_MASK    0xffff8000U
 #define  QID_SHIFT   15
 #define  QID(x)      ((x) << QID_SHIFT)
-#define  DBPRIO      0x00004000U
+#define  DBPRIO(x)   ((x) << 14)
 #define  PIDX_MASK   0x00003fffU
 #define  PIDX_SHIFT  0
 #define  PIDX(x)     ((x) << PIDX_SHIFT)
@@ -193,6 +193,12 @@
 #define SGE_FL_BUFFER_SIZE1 0x1048
 #define SGE_FL_BUFFER_SIZE2 0x104c
 #define SGE_FL_BUFFER_SIZE3 0x1050
+#define SGE_FL_BUFFER_SIZE4 0x1054
+#define SGE_FL_BUFFER_SIZE5 0x1058
+#define SGE_FL_BUFFER_SIZE6 0x105c
+#define SGE_FL_BUFFER_SIZE7 0x1060
+#define SGE_FL_BUFFER_SIZE8 0x1064
+
 #define SGE_INGRESS_RX_THRESHOLD 0x10a0
 #define  THRESHOLD_0_MASK   0x3f000000U
 #define  THRESHOLD_0_SHIFT  24
@@ -217,6 +223,17 @@
 #define  EGRTHRESHOLD(x)     ((x) << EGRTHRESHOLDshift)
 #define  EGRTHRESHOLD_GET(x) (((x) & EGRTHRESHOLD_MASK) >> EGRTHRESHOLDshift)
 
+#define SGE_DBFIFO_STATUS 0x10a4
+#define  HP_INT_THRESH_SHIFT 28
+#define  HP_INT_THRESH_MASK  0xfU
+#define  HP_INT_THRESH(x)    ((x) << HP_INT_THRESH_SHIFT)
+#define  LP_INT_THRESH_SHIFT 12
+#define  LP_INT_THRESH_MASK  0xfU
+#define  LP_INT_THRESH(x)    ((x) << LP_INT_THRESH_SHIFT)
+
+#define SGE_DOORBELL_CONTROL 0x10a8
+#define  ENABLE_DROP        (1 << 13)
+
 #define SGE_TIMER_VALUE_0_AND_1 0x10b8
 #define  TIMERVALUE0_MASK   0xffff0000U
 #define  TIMERVALUE0_SHIFT  16
@@ -277,6 +294,10 @@
 #define A_SGE_CTXT_CMD 0x11fc
 #define A_SGE_DBQ_CTXT_BADDR 0x1084
 
+#define PCIE_PF_CFG 0x40
+#define  AIVEC(x)	((x) << 4)
+#define  AIVEC_MASK	0x3ffU
+
 #define PCIE_PF_CLI 0x44
 #define PCIE_INT_CAUSE 0x3004
 #define  UNXSPLCPLERR  0x20000000U
@@ -322,6 +343,13 @@
 #define PCIE_MEM_ACCESS_OFFSET 0x306c
 
 #define PCIE_FW 0x30b8
+#define  PCIE_FW_ERR		0x80000000U
+#define  PCIE_FW_INIT		0x40000000U
+#define  PCIE_FW_HALT		0x20000000U
+#define  PCIE_FW_MASTER_VLD	0x00008000U
+#define  PCIE_FW_MASTER(x)	((x) << 12)
+#define  PCIE_FW_MASTER_MASK	0x7
+#define  PCIE_FW_MASTER_GET(x)	(((x) >> 12) & PCIE_FW_MASTER_MASK)
 
 #define PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS 0x5908
 #define  RNPP 0x80000000U
@@ -432,6 +460,9 @@
 #define  MBOWNER(x)     ((x) << MBOWNER_SHIFT)
 #define  MBOWNER_GET(x) (((x) & MBOWNER_MASK) >> MBOWNER_SHIFT)
 
+#define CIM_PF_HOST_INT_ENABLE 0x288
+#define  MBMSGRDYINTEN(x) ((x) << 19)
+
 #define CIM_PF_HOST_INT_CAUSE 0x28c
 #define  MBMSGRDYINT 0x00080000U
 
@@ -922,7 +953,7 @@
 
 #define SF_DATA 0x193f8
 #define SF_OP 0x193fc
-#define  BUSY          0x80000000U
+#define  SF_BUSY       0x80000000U
 #define  SF_LOCK       0x00000010U
 #define  SF_CONT       0x00000008U
 #define  BYTECNT_MASK  0x00000006U
@@ -981,6 +1012,7 @@
 #define  I2CM       0x00000002U
 #define  CIM        0x00000001U
 
+#define PL_INT_ENABLE 0x19410
 #define PL_INT_MAP0 0x19414
 #define PL_RST 0x19428
 #define  PIORST     0x00000002U
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index a636463..0abc864 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
@@ -68,6 +68,7 @@ struct fw_wr_hdr {
 };
 
 #define FW_WR_OP(x)	 ((x) << 24)
+#define FW_WR_OP_GET(x)	 (((x) >> 24) & 0xff)
 #define FW_WR_ATOMIC(x)	 ((x) << 23)
 #define FW_WR_FLUSH(x)   ((x) << 22)
 #define FW_WR_COMPL(x)   ((x) << 21)
@@ -222,6 +223,7 @@ struct fw_cmd_hdr {
 #define FW_CMD_OP(x)		((x) << 24)
 #define FW_CMD_OP_GET(x)        (((x) >> 24) & 0xff)
 #define FW_CMD_REQUEST          (1U << 23)
+#define FW_CMD_REQUEST_GET(x)   (((x) >> 23) & 0x1)
 #define FW_CMD_READ		(1U << 22)
 #define FW_CMD_WRITE		(1U << 21)
 #define FW_CMD_EXEC		(1U << 20)
@@ -229,6 +231,7 @@ struct fw_cmd_hdr {
 #define FW_CMD_RETVAL(x)	((x) << 8)
 #define FW_CMD_RETVAL_GET(x)	(((x) >> 8) & 0xff)
 #define FW_CMD_LEN16(x)         ((x) << 0)
+#define FW_LEN16(fw_struct)	FW_CMD_LEN16(sizeof(fw_struct) / 16)
 
 enum fw_ldst_addrspc {
 	FW_LDST_ADDRSPC_FIRMWARE  = 0x0001,
@@ -241,7 +244,8 @@ enum fw_ldst_addrspc {
 	FW_LDST_ADDRSPC_TP_MIB    = 0x0012,
 	FW_LDST_ADDRSPC_MDIO      = 0x0018,
 	FW_LDST_ADDRSPC_MPS       = 0x0020,
-	FW_LDST_ADDRSPC_FUNC      = 0x0028
+	FW_LDST_ADDRSPC_FUNC      = 0x0028,
+	FW_LDST_ADDRSPC_FUNC_PCIE = 0x0029,
 };
 
 enum fw_ldst_mps_fid {
@@ -303,6 +307,16 @@ struct fw_ldst_cmd {
 			__be64 data0;
 			__be64 data1;
 		} func;
+		struct fw_ldst_pcie {
+			u8 ctrl_to_fn;
+			u8 bnum;
+			u8 r;
+			u8 ext_r;
+			u8 select_naccess;
+			u8 pcie_fn;
+			__be16 nset_pkd;
+			__be32 data[12];
+		} pcie;
 	} u;
 };
 
@@ -312,6 +326,9 @@ struct fw_ldst_cmd {
 #define FW_LDST_CMD_FID(x)	((x) << 15)
 #define FW_LDST_CMD_CTL(x)	((x) << 0)
 #define FW_LDST_CMD_RPLCPF(x)	((x) << 0)
+#define FW_LDST_CMD_LC		(1U << 4)
+#define FW_LDST_CMD_NACCESS(x)	((x) << 0)
+#define FW_LDST_CMD_FN(x)	((x) << 0)
 
 struct fw_reset_cmd {
 	__be32 op_to_write;
@@ -333,7 +350,7 @@ enum fw_hellow_cmd {
 struct fw_hello_cmd {
 	__be32 op_to_write;
 	__be32 retval_len16;
-	__be32 err_to_mbasyncnot;
+	__be32 err_to_clearinit;
 #define FW_HELLO_CMD_ERR	    (1U << 31)
 #define FW_HELLO_CMD_INIT	    (1U << 30)
 #define FW_HELLO_CMD_MASTERDIS(x)   ((x) << 29)
@@ -343,6 +360,7 @@ struct fw_hello_cmd {
 #define FW_HELLO_CMD_MBMASTER(x)     ((x) << FW_HELLO_CMD_MBMASTER_SHIFT)
 #define FW_HELLO_CMD_MBMASTER_GET(x) \
 	(((x) >> FW_HELLO_CMD_MBMASTER_SHIFT) & FW_HELLO_CMD_MBMASTER_MASK)
+#define FW_HELLO_CMD_MBASYNCNOTINT(x)	((x) << 23)
 #define FW_HELLO_CMD_MBASYNCNOT(x)  ((x) << 20)
 #define FW_HELLO_CMD_STAGE(x)       ((x) << 17)
 #define FW_HELLO_CMD_CLEARINIT      (1U << 16)
@@ -428,6 +446,7 @@ enum fw_caps_config_iscsi {
 enum fw_caps_config_fcoe {
 	FW_CAPS_CONFIG_FCOE_INITIATOR	= 0x00000001,
 	FW_CAPS_CONFIG_FCOE_TARGET	= 0x00000002,
+	FW_CAPS_CONFIG_FCOE_CTRL_OFLD	= 0x00000004,
 };
 
 enum fw_memtype_cf {
@@ -440,7 +459,7 @@ enum fw_memtype_cf {
 
 struct fw_caps_config_cmd {
 	__be32 op_to_write;
-	__be32 retval_len16;
+	__be32 cfvalid_to_len16;
 	__be32 r2;
 	__be32 hwmbitmap;
 	__be16 nbmcaps;
@@ -701,8 +720,8 @@ struct fw_iq_cmd {
 #define FW_IQ_CMD_FL0FETCHRO(x) ((x) << 6)
 #define FW_IQ_CMD_FL0HOSTFCMODE(x) ((x) << 4)
 #define FW_IQ_CMD_FL0CPRIO(x) ((x) << 3)
-#define FW_IQ_CMD_FL0PADEN (1U << 2)
-#define FW_IQ_CMD_FL0PACKEN (1U << 1)
+#define FW_IQ_CMD_FL0PADEN(x) ((x) << 2)
+#define FW_IQ_CMD_FL0PACKEN(x) ((x) << 1)
 #define FW_IQ_CMD_FL0CONGEN (1U << 0)
 
 #define FW_IQ_CMD_FL0DCAEN(x) ((x) << 15)
@@ -1190,6 +1209,14 @@ enum fw_port_dcb_cfg_rc {
 	FW_PORT_DCB_CFG_ERROR	= 0x1
 };
 
+enum fw_port_dcb_type {
+	FW_PORT_DCB_TYPE_PGID		= 0x00,
+	FW_PORT_DCB_TYPE_PGRATE		= 0x01,
+	FW_PORT_DCB_TYPE_PRIORATE	= 0x02,
+	FW_PORT_DCB_TYPE_PFC		= 0x03,
+	FW_PORT_DCB_TYPE_APP_ID		= 0x04,
+};
+
 struct fw_port_cmd {
 	__be32 op_to_portid;
 	__be32 action_to_len16;
@@ -1257,6 +1284,7 @@ struct fw_port_cmd {
 #define FW_PORT_CMD_TXIPG(x) ((x) << 19)
 
 #define FW_PORT_CMD_LSTATUS (1U << 31)
+#define FW_PORT_CMD_LSTATUS_GET(x) (((x) >> 31) & 0x1)
 #define FW_PORT_CMD_LSPEED(x) ((x) << 24)
 #define FW_PORT_CMD_LSPEED_GET(x) (((x) >> 24) & 0x3f)
 #define FW_PORT_CMD_TXPAUSE (1U << 23)
@@ -1305,6 +1333,9 @@ enum fw_port_module_type {
 	FW_PORT_MOD_TYPE_TWINAX_PASSIVE,
 	FW_PORT_MOD_TYPE_TWINAX_ACTIVE,
 	FW_PORT_MOD_TYPE_LRM,
+	FW_PORT_MOD_TYPE_ERROR		= FW_PORT_CMD_MODTYPE_MASK - 3,
+	FW_PORT_MOD_TYPE_UNKNOWN	= FW_PORT_CMD_MODTYPE_MASK - 2,
+	FW_PORT_MOD_TYPE_NOTSUPPORTED	= FW_PORT_CMD_MODTYPE_MASK - 1,
 
 	FW_PORT_MOD_TYPE_NONE = FW_PORT_CMD_MODTYPE_MASK
 };
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
index f16745f..92170d5 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
@@ -536,7 +536,7 @@ static inline void ring_fl_db(struct adapter *adapter, struct sge_fl *fl)
 	if (fl->pend_cred >= FL_PER_EQ_UNIT) {
 		wmb();
 		t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL,
-			     DBPRIO |
+			     DBPRIO(1) |
 			     QID(fl->cntxt_id) |
 			     PIDX(fl->pend_cred / FL_PER_EQ_UNIT));
 		fl->pend_cred %= FL_PER_EQ_UNIT;
@@ -952,7 +952,7 @@ static inline void ring_tx_db(struct adapter *adapter, struct sge_txq *tq,
 	 * Warn if we write doorbells with the wrong priority and write
 	 * descriptors before telling HW.
 	 */
-	WARN_ON((QID(tq->cntxt_id) | PIDX(n)) & DBPRIO);
+	WARN_ON((QID(tq->cntxt_id) | PIDX(n)) & DBPRIO(1));
 	wmb();
 	t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL,
 		     QID(tq->cntxt_id) | PIDX(n));
@@ -2126,8 +2126,8 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq,
 		cmd.iqns_to_fl0congen =
 			cpu_to_be32(
 				FW_IQ_CMD_FL0HOSTFCMODE(SGE_HOSTFCMODE_NONE) |
-				FW_IQ_CMD_FL0PACKEN |
-				FW_IQ_CMD_FL0PADEN);
+				FW_IQ_CMD_FL0PACKEN(1) |
+				FW_IQ_CMD_FL0PADEN(1));
 		cmd.fl0dcaen_to_fl0cidxfthresh =
 			cpu_to_be16(
 				FW_IQ_CMD_FL0FBMIN(SGE_FETCHBURSTMIN_64B) |
diff --git a/drivers/net/ethernet/cisco/Kconfig b/drivers/net/ethernet/cisco/Kconfig
index 94606f7..1c7b884 100644
--- a/drivers/net/ethernet/cisco/Kconfig
+++ b/drivers/net/ethernet/cisco/Kconfig
@@ -5,7 +5,7 @@
 config NET_VENDOR_CISCO
 	bool "Cisco devices"
 	default y
-	depends on PCI && INET
+	depends on PCI
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y
 	  and read the Ethernet-HOWTO, available from
diff --git a/drivers/net/ethernet/cisco/enic/Kconfig b/drivers/net/ethernet/cisco/enic/Kconfig
index 9cc706a..b63f8d8 100644
--- a/drivers/net/ethernet/cisco/enic/Kconfig
+++ b/drivers/net/ethernet/cisco/enic/Kconfig
@@ -4,6 +4,6 @@
 
 config ENIC
 	tristate "Cisco VIC Ethernet NIC Support"
-	depends on PCI && INET
+	depends on PCI
 	---help---
 	  This enables the support for the Cisco VIC Ethernet card.
diff --git a/drivers/net/ethernet/dec/ewrk3.c b/drivers/net/ethernet/dec/ewrk3.c
index 17ae8c6..9f992b9 100644
--- a/drivers/net/ethernet/dec/ewrk3.c
+++ b/drivers/net/ethernet/dec/ewrk3.c
@@ -1910,9 +1910,8 @@ static struct net_device *ewrk3_devs[MAX_NUM_EWRK3S];
 static int ndevs;
 static int io[MAX_NUM_EWRK3S+1] = { 0x300, 0, };
 
-/* '21' below should really be 'MAX_NUM_EWRK3S' */
 module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
+module_param_array(irq, byte, NULL, 0);
 MODULE_PARM_DESC(io, "EtherWORKS 3 I/O base address(es)");
 MODULE_PARM_DESC(irq, "EtherWORKS 3 IRQ number(s)");
 
diff --git a/drivers/net/ethernet/dec/tulip/Kconfig b/drivers/net/ethernet/dec/tulip/Kconfig
index 1203be0..0c37fb2 100644
--- a/drivers/net/ethernet/dec/tulip/Kconfig
+++ b/drivers/net/ethernet/dec/tulip/Kconfig
@@ -57,8 +57,8 @@ config TULIP
 	  be called tulip.
 
 config TULIP_MWI
-	bool "New bus configuration (EXPERIMENTAL)"
-	depends on TULIP && EXPERIMENTAL
+	bool "New bus configuration"
+	depends on TULIP
 	---help---
 	  This configures your Tulip card specifically for the card and
 	  system cache line size type you are using.
diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c
index a059f0c..2fb01bf 100644
--- a/drivers/net/ethernet/dlink/dl2k.c
+++ b/drivers/net/ethernet/dlink/dl2k.c
@@ -1758,21 +1758,7 @@ static struct pci_driver rio_driver = {
 	.remove		= __devexit_p(rio_remove1),
 };
 
-static int __init
-rio_init (void)
-{
-	return pci_register_driver(&rio_driver);
-}
-
-static void __exit
-rio_exit (void)
-{
-	pci_unregister_driver (&rio_driver);
-}
-
-module_init (rio_init);
-module_exit (rio_exit);
-
+module_pci_driver(rio_driver);
 /*
 
 Compile command:
diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c
index 290b26f..feb5095 100644
--- a/drivers/net/ethernet/dnet.c
+++ b/drivers/net/ethernet/dnet.c
@@ -664,9 +664,6 @@ static int dnet_open(struct net_device *dev)
 	if (!bp->phy_dev)
 		return -EAGAIN;
 
-	if (!is_valid_ether_addr(dev->dev_addr))
-		return -EADDRNOTAVAIL;
-
 	napi_enable(&bp->napi);
 	dnet_init_hw(bp);
 
diff --git a/drivers/net/ethernet/emulex/Kconfig b/drivers/net/ethernet/emulex/Kconfig
index 7a28a64..1b8d638 100644
--- a/drivers/net/ethernet/emulex/Kconfig
+++ b/drivers/net/ethernet/emulex/Kconfig
@@ -5,7 +5,7 @@
 config NET_VENDOR_EMULEX
 	bool "Emulex devices"
 	default y
-	depends on PCI && INET
+	depends on PCI
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y
 	  and read the Ethernet-HOWTO, available from
diff --git a/drivers/net/ethernet/emulex/benet/Kconfig b/drivers/net/ethernet/emulex/benet/Kconfig
index 804db04..231129d 100644
--- a/drivers/net/ethernet/emulex/benet/Kconfig
+++ b/drivers/net/ethernet/emulex/benet/Kconfig
@@ -1,6 +1,6 @@
 config BE2NET
 	tristate "ServerEngines' 10Gbps NIC - BladeEngine"
-	depends on PCI && INET
+	depends on PCI
 	---help---
 	  This driver implements the NIC functionality for ServerEngines'
 	  10Gbps network adapter - BladeEngine.
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index cf4c05b..abf26c7 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -34,7 +34,7 @@
 #include "be_hw.h"
 #include "be_roce.h"
 
-#define DRV_VER			"4.4.31.0u"
+#define DRV_VER			"4.4.161.0u"
 #define DRV_NAME		"be2net"
 #define BE_NAME			"ServerEngines BladeEngine2 10Gbps NIC"
 #define BE3_NAME		"ServerEngines BladeEngine3 10Gbps NIC"
@@ -53,6 +53,7 @@
 #define OC_DEVICE_ID3		0xe220	/* Device id for Lancer cards */
 #define OC_DEVICE_ID4           0xe228   /* Device id for VF in Lancer */
 #define OC_DEVICE_ID5		0x720	/* Device Id for Skyhawk cards */
+#define OC_DEVICE_ID6		0x728   /* Device id for VF in SkyHawk */
 #define OC_SUBSYS_DEVICE_ID1	0xE602
 #define OC_SUBSYS_DEVICE_ID2	0xE642
 #define OC_SUBSYS_DEVICE_ID3	0xE612
@@ -71,6 +72,7 @@ static inline char *nic_name(struct pci_dev *pdev)
 	case BE_DEVICE_ID2:
 		return BE3_NAME;
 	case OC_DEVICE_ID5:
+	case OC_DEVICE_ID6:
 		return OC_NAME_SH;
 	default:
 		return BE_NAME;
@@ -346,7 +348,6 @@ struct be_adapter {
 	struct pci_dev *pdev;
 	struct net_device *netdev;
 
-	u8 __iomem *csr;
 	u8 __iomem *db;		/* Door Bell */
 
 	struct mutex mbox_lock; /* For serializing mbox cmds to BE card */
@@ -374,11 +375,8 @@ struct be_adapter {
 	struct be_rx_obj rx_obj[MAX_RX_QS];
 	u32 big_page_size;	/* Compounded page size shared by rx wrbs */
 
-	u8 eq_next_idx;
 	struct be_drv_stats drv_stats;
-
 	u16 vlans_added;
-	u16 max_vlans;	/* Number of vlans supported */
 	u8 vlan_tag[VLAN_N_VID];
 	u8 vlan_prio_bmap;	/* Available Priority BitMap */
 	u16 recommended_prio;	/* Recommended Priority */
@@ -391,6 +389,7 @@ struct be_adapter {
 
 	struct delayed_work func_recovery_work;
 	u32 flags;
+	u32 cmd_privileges;
 	/* Ethtool knobs and info */
 	char fw_ver[FW_VER_LEN];
 	int if_handle;		/* Used to configure filtering */
@@ -408,10 +407,8 @@ struct be_adapter {
 	u32 rx_fc;		/* Rx flow control */
 	u32 tx_fc;		/* Tx flow control */
 	bool stats_cmd_sent;
-	u8 generation;		/* BladeEngine ASIC generation */
 	u32 if_type;
 	struct {
-		u8 __iomem *base;	/* Door Bell */
 		u32 size;
 		u32 total_size;
 		u64 io_addr;
@@ -434,10 +431,18 @@ struct be_adapter {
 	struct phy_info phy;
 	u8 wol_cap;
 	bool wol;
-	u32 max_pmac_cnt;	/* Max secondary UC MACs programmable */
 	u32 uc_macs;		/* Count of secondary UC MAC programmed */
 	u32 msg_enable;
 	int be_get_temp_freq;
+	u16 max_mcast_mac;
+	u16 max_tx_queues;
+	u16 max_rss_queues;
+	u16 max_rx_queues;
+	u16 max_pmac_cnt;
+	u16 max_vlans;
+	u16 max_event_queues;
+	u32 if_cap_flags;
+	u8 pf_number;
 };
 
 #define be_physfn(adapter)		(!adapter->virtfn)
@@ -448,21 +453,25 @@ struct be_adapter {
 	for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs;	\
 		i++, vf_cfg++)
 
-/* BladeEngine Generation numbers */
-#define BE_GEN2 2
-#define BE_GEN3 3
-
 #define ON				1
 #define OFF				0
-#define lancer_chip(adapter)	((adapter->pdev->device == OC_DEVICE_ID3) || \
-				 (adapter->pdev->device == OC_DEVICE_ID4))
 
-#define skyhawk_chip(adapter)	(adapter->pdev->device == OC_DEVICE_ID5)
+#define lancer_chip(adapter)	(adapter->pdev->device == OC_DEVICE_ID3 || \
+				 adapter->pdev->device == OC_DEVICE_ID4)
+
+#define skyhawk_chip(adapter)	(adapter->pdev->device == OC_DEVICE_ID5 || \
+				 adapter->pdev->device == OC_DEVICE_ID6)
+
+#define BE3_chip(adapter)	(adapter->pdev->device == BE_DEVICE_ID2 || \
+				 adapter->pdev->device == OC_DEVICE_ID2)
 
+#define BE2_chip(adapter)	(adapter->pdev->device == BE_DEVICE_ID1 || \
+				 adapter->pdev->device == OC_DEVICE_ID1)
 
-#define be_roce_supported(adapter) ((adapter->if_type == SLI_INTF_TYPE_3 || \
-				adapter->sli_family == SKYHAWK_SLI_FAMILY) && \
-				(adapter->function_mode & RDMA_ENABLED))
+#define BEx_chip(adapter)	(BE3_chip(adapter) || BE2_chip(adapter))
+
+#define be_roce_supported(adapter)	(skyhawk_chip(adapter) && \
+					(adapter->function_mode & RDMA_ENABLED))
 
 extern const struct ethtool_ops be_ethtool_ops;
 
@@ -637,12 +646,6 @@ static inline bool be_is_wol_excluded(struct be_adapter *adapter)
 	}
 }
 
-static inline bool be_type_2_3(struct be_adapter *adapter)
-{
-	return (adapter->if_type == SLI_INTF_TYPE_2 ||
-		adapter->if_type == SLI_INTF_TYPE_3) ? true : false;
-}
-
 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 af60bb2..f2875aa 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -19,6 +19,55 @@
 #include "be.h"
 #include "be_cmds.h"
 
+static struct be_cmd_priv_map cmd_priv_map[] = {
+	{
+		OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
+		CMD_SUBSYSTEM_ETH,
+		BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
+		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+	},
+	{
+		OPCODE_COMMON_GET_FLOW_CONTROL,
+		CMD_SUBSYSTEM_COMMON,
+		BE_PRIV_LNKQUERY | BE_PRIV_VHADM |
+		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+	},
+	{
+		OPCODE_COMMON_SET_FLOW_CONTROL,
+		CMD_SUBSYSTEM_COMMON,
+		BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
+		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+	},
+	{
+		OPCODE_ETH_GET_PPORT_STATS,
+		CMD_SUBSYSTEM_ETH,
+		BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
+		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+	},
+	{
+		OPCODE_COMMON_GET_PHY_DETAILS,
+		CMD_SUBSYSTEM_COMMON,
+		BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
+		BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+	}
+};
+
+static bool be_cmd_allowed(struct be_adapter *adapter, u8 opcode,
+			   u8 subsystem)
+{
+	int i;
+	int num_entries = sizeof(cmd_priv_map)/sizeof(struct be_cmd_priv_map);
+	u32 cmd_privileges = adapter->cmd_privileges;
+
+	for (i = 0; i < num_entries; i++)
+		if (opcode == cmd_priv_map[i].opcode &&
+		    subsystem == cmd_priv_map[i].subsystem)
+			if (!(cmd_privileges & cmd_priv_map[i].priv_mask))
+				return false;
+
+	return true;
+}
+
 static inline void *embedded_payload(struct be_mcc_wrb *wrb)
 {
 	return wrb->payload.embedded_payload;
@@ -419,14 +468,13 @@ static int be_mbox_notify_wait(struct be_adapter *adapter)
 static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage)
 {
 	u32 sem;
+	u32 reg = skyhawk_chip(adapter) ? SLIPORT_SEMAPHORE_OFFSET_SH :
+					  SLIPORT_SEMAPHORE_OFFSET_BE;
 
-	if (lancer_chip(adapter))
-		sem  = ioread32(adapter->db + MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET);
-	else
-		sem  = ioread32(adapter->csr + MPU_EP_SEMAPHORE_OFFSET);
+	pci_read_config_dword(adapter->pdev, reg, &sem);
+	*stage = sem & POST_STAGE_MASK;
 
-	*stage = sem & EP_SEMAPHORE_POST_STAGE_MASK;
-	if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) & EP_SEMAPHORE_POST_ERR_MASK)
+	if ((sem >> POST_ERR_SHIFT) & POST_ERR_MASK)
 		return -1;
 	else
 		return 0;
@@ -452,10 +500,33 @@ int lancer_wait_ready(struct be_adapter *adapter)
 	return status;
 }
 
+static bool lancer_provisioning_error(struct be_adapter *adapter)
+{
+	u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0;
+	sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
+	if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
+		sliport_err1 = ioread32(adapter->db +
+					SLIPORT_ERROR1_OFFSET);
+		sliport_err2 = ioread32(adapter->db +
+					SLIPORT_ERROR2_OFFSET);
+
+		if (sliport_err1 == SLIPORT_ERROR_NO_RESOURCE1 &&
+		    sliport_err2 == SLIPORT_ERROR_NO_RESOURCE2)
+			return true;
+	}
+	return false;
+}
+
 int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
 {
 	int status;
 	u32 sliport_status, err, reset_needed;
+	bool resource_error;
+
+	resource_error = lancer_provisioning_error(adapter);
+	if (resource_error)
+		return -1;
+
 	status = lancer_wait_ready(adapter);
 	if (!status) {
 		sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
@@ -477,6 +548,14 @@ int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
 			status = -1;
 		}
 	}
+	/* Stop error recovery if error is not recoverable.
+	 * No resource error is temporary errors and will go away
+	 * when PF provisions resources.
+	 */
+	resource_error = lancer_provisioning_error(adapter);
+	if (status == -1 && !resource_error)
+		adapter->eeh_error = true;
+
 	return status;
 }
 
@@ -601,6 +680,9 @@ static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter)
 	struct be_queue_info *mccq = &adapter->mcc_obj.q;
 	struct be_mcc_wrb *wrb;
 
+	if (!mccq->created)
+		return NULL;
+
 	if (atomic_read(&mccq->used) >= mccq->len) {
 		dev_err(&adapter->pdev->dev, "Out of MCCQ wrbs\n");
 		return NULL;
@@ -1155,8 +1237,7 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
 	req->id = cpu_to_le16(q->id);
 
 	status = be_mbox_notify_wait(adapter);
-	if (!status)
-		q->created = false;
+	q->created = false;
 
 	mutex_unlock(&adapter->mbox_lock);
 	return status;
@@ -1183,8 +1264,7 @@ int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q)
 	req->id = cpu_to_le16(q->id);
 
 	status = be_mcc_notify_wait(adapter);
-	if (!status)
-		q->created = false;
+	q->created = false;
 
 err:
 	spin_unlock_bh(&adapter->mcc_lock);
@@ -1281,7 +1361,8 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
 	be_wrb_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH,
 		OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb, nonemb_cmd);
 
-	if (adapter->generation == BE_GEN3)
+	/* version 1 of the cmd is not supported only by BE2 */
+	if (!BE2_chip(adapter))
 		hdr->version = 1;
 
 	be_mcc_notify(adapter);
@@ -1301,6 +1382,10 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
 	struct lancer_cmd_req_pport_stats *req;
 	int status = 0;
 
+	if (!be_cmd_allowed(adapter, OPCODE_ETH_GET_PPORT_STATS,
+			    CMD_SUBSYSTEM_ETH))
+		return -EPERM;
+
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
@@ -1367,7 +1452,8 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed,
 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL);
 
-	if (adapter->generation == BE_GEN3 || lancer_chip(adapter))
+	/* version 1 of the cmd is not supported only by BE2 */
+	if (!BE2_chip(adapter))
 		req->hdr.version = 1;
 
 	req->hdr.domain = dom;
@@ -1658,9 +1744,9 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
 		/* Reset mcast promisc mode if already set by setting mask
 		 * and not setting flags field
 		 */
-		if (!lancer_chip(adapter) || be_physfn(adapter))
-			req->if_flags_mask |=
-				cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS);
+		req->if_flags_mask |=
+			cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS &
+				    adapter->if_cap_flags);
 
 		req->mcast_num = cpu_to_le32(netdev_mc_count(adapter->netdev));
 		netdev_for_each_mc_addr(ha, adapter->netdev)
@@ -1680,6 +1766,10 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
 	struct be_cmd_req_set_flow_control *req;
 	int status;
 
+	if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_FLOW_CONTROL,
+			    CMD_SUBSYSTEM_COMMON))
+		return -EPERM;
+
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
@@ -1709,6 +1799,10 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
 	struct be_cmd_req_get_flow_control *req;
 	int status;
 
+	if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_FLOW_CONTROL,
+			    CMD_SUBSYSTEM_COMMON))
+		return -EPERM;
+
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
@@ -2067,7 +2161,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
 			 int offset)
 {
 	struct be_mcc_wrb *wrb;
-	struct be_cmd_write_flashrom *req;
+	struct be_cmd_read_flash_crc *req;
 	int status;
 
 	spin_lock_bh(&adapter->mcc_lock);
@@ -2080,7 +2174,8 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
 	req = embedded_payload(wrb);
 
 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-		OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4, wrb, NULL);
+			       OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
+			       wrb, NULL);
 
 	req->params.op_type = cpu_to_le32(OPTYPE_REDBOOT);
 	req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
@@ -2089,7 +2184,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
 
 	status = be_mcc_notify_wait(adapter);
 	if (!status)
-		memcpy(flashed_crc, req->params.data_buf, 4);
+		memcpy(flashed_crc, req->crc, 4);
 
 err:
 	spin_unlock_bh(&adapter->mcc_lock);
@@ -2275,6 +2370,10 @@ int be_cmd_get_phy_info(struct be_adapter *adapter)
 	struct be_dma_mem cmd;
 	int status;
 
+	if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_PHY_DETAILS,
+			    CMD_SUBSYSTEM_COMMON))
+		return -EPERM;
+
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
@@ -2434,6 +2533,42 @@ err:
 	return status;
 }
 
+/* Get privilege(s) for a function */
+int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege,
+			     u32 domain)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_get_fn_privileges *req;
+	int status;
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+
+	req = embedded_payload(wrb);
+
+	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+			       OPCODE_COMMON_GET_FN_PRIVILEGES, sizeof(*req),
+			       wrb, NULL);
+
+	req->hdr.domain = domain;
+
+	status = be_mcc_notify_wait(adapter);
+	if (!status) {
+		struct be_cmd_resp_get_fn_privileges *resp =
+						embedded_payload(wrb);
+		*privilege = le32_to_cpu(resp->privilege_mask);
+	}
+
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+
 /* Uses synchronous MCCQ */
 int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
 			     bool *pmac_id_active, u32 *pmac_id, u8 domain)
@@ -2651,6 +2786,10 @@ int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
 	int payload_len = sizeof(*req);
 	struct be_dma_mem cmd;
 
+	if (!be_cmd_allowed(adapter, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
+			    CMD_SUBSYSTEM_ETH))
+		return -EPERM;
+
 	memset(&cmd, 0, sizeof(struct be_dma_mem));
 	cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1);
 	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
@@ -2792,6 +2931,240 @@ err:
 	return status;
 }
 
+static struct be_nic_resource_desc *be_get_nic_desc(u8 *buf, u32 desc_count,
+						    u32 max_buf_size)
+{
+	struct be_nic_resource_desc *desc = (struct be_nic_resource_desc *)buf;
+	int i;
+
+	for (i = 0; i < desc_count; i++) {
+		desc->desc_len = RESOURCE_DESC_SIZE;
+		if (((void *)desc + desc->desc_len) >
+		    (void *)(buf + max_buf_size)) {
+			desc = NULL;
+			break;
+		}
+
+		if (desc->desc_type == NIC_RESOURCE_DESC_TYPE_ID)
+			break;
+
+		desc = (void *)desc + desc->desc_len;
+	}
+
+	if (!desc || i == MAX_RESOURCE_DESC)
+		return NULL;
+
+	return desc;
+}
+
+/* Uses Mbox */
+int be_cmd_get_func_config(struct be_adapter *adapter)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_get_func_config *req;
+	int status;
+	struct be_dma_mem cmd;
+
+	memset(&cmd, 0, sizeof(struct be_dma_mem));
+	cmd.size = sizeof(struct be_cmd_resp_get_func_config);
+	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
+				      &cmd.dma);
+	if (!cmd.va) {
+		dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
+		return -ENOMEM;
+	}
+	if (mutex_lock_interruptible(&adapter->mbox_lock))
+		return -1;
+
+	wrb = wrb_from_mbox(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+
+	req = cmd.va;
+
+	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+			       OPCODE_COMMON_GET_FUNC_CONFIG,
+			       cmd.size, wrb, &cmd);
+
+	status = be_mbox_notify_wait(adapter);
+	if (!status) {
+		struct be_cmd_resp_get_func_config *resp = cmd.va;
+		u32 desc_count = le32_to_cpu(resp->desc_count);
+		struct be_nic_resource_desc *desc;
+
+		desc = be_get_nic_desc(resp->func_param, desc_count,
+				       sizeof(resp->func_param));
+		if (!desc) {
+			status = -EINVAL;
+			goto err;
+		}
+
+		adapter->pf_number = desc->pf_num;
+		adapter->max_pmac_cnt = le16_to_cpu(desc->unicast_mac_count);
+		adapter->max_vlans = le16_to_cpu(desc->vlan_count);
+		adapter->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count);
+		adapter->max_tx_queues = le16_to_cpu(desc->txq_count);
+		adapter->max_rss_queues = le16_to_cpu(desc->rssq_count);
+		adapter->max_rx_queues = le16_to_cpu(desc->rq_count);
+
+		adapter->max_event_queues = le16_to_cpu(desc->eq_count);
+		adapter->if_cap_flags = le32_to_cpu(desc->cap_flags);
+	}
+err:
+	mutex_unlock(&adapter->mbox_lock);
+	pci_free_consistent(adapter->pdev, cmd.size,
+			    cmd.va, cmd.dma);
+	return status;
+}
+
+ /* Uses sync mcc */
+int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags,
+			      u8 domain)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_get_profile_config *req;
+	int status;
+	struct be_dma_mem cmd;
+
+	memset(&cmd, 0, sizeof(struct be_dma_mem));
+	cmd.size = sizeof(struct be_cmd_resp_get_profile_config);
+	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
+				      &cmd.dma);
+	if (!cmd.va) {
+		dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
+		return -ENOMEM;
+	}
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+
+	req = cmd.va;
+
+	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+			       OPCODE_COMMON_GET_PROFILE_CONFIG,
+			       cmd.size, wrb, &cmd);
+
+	req->type = ACTIVE_PROFILE_TYPE;
+	req->hdr.domain = domain;
+
+	status = be_mcc_notify_wait(adapter);
+	if (!status) {
+		struct be_cmd_resp_get_profile_config *resp = cmd.va;
+		u32 desc_count = le32_to_cpu(resp->desc_count);
+		struct be_nic_resource_desc *desc;
+
+		desc = be_get_nic_desc(resp->func_param, desc_count,
+				       sizeof(resp->func_param));
+
+		if (!desc) {
+			status = -EINVAL;
+			goto err;
+		}
+		*cap_flags = le32_to_cpu(desc->cap_flags);
+	}
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	pci_free_consistent(adapter->pdev, cmd.size,
+			    cmd.va, cmd.dma);
+	return status;
+}
+
+/* Uses sync mcc */
+int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps,
+			      u8 domain)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_set_profile_config *req;
+	int status;
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+
+	req = embedded_payload(wrb);
+
+	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+			       OPCODE_COMMON_SET_PROFILE_CONFIG, sizeof(*req),
+			       wrb, NULL);
+
+	req->hdr.domain = domain;
+	req->desc_count = cpu_to_le32(1);
+
+	req->nic_desc.desc_type = NIC_RESOURCE_DESC_TYPE_ID;
+	req->nic_desc.desc_len = RESOURCE_DESC_SIZE;
+	req->nic_desc.flags = (1 << QUN) | (1 << IMM) | (1 << NOSV);
+	req->nic_desc.pf_num = adapter->pf_number;
+	req->nic_desc.vf_num = domain;
+
+	/* Mark fields invalid */
+	req->nic_desc.unicast_mac_count = 0xFFFF;
+	req->nic_desc.mcc_count = 0xFFFF;
+	req->nic_desc.vlan_count = 0xFFFF;
+	req->nic_desc.mcast_mac_count = 0xFFFF;
+	req->nic_desc.txq_count = 0xFFFF;
+	req->nic_desc.rq_count = 0xFFFF;
+	req->nic_desc.rssq_count = 0xFFFF;
+	req->nic_desc.lro_count = 0xFFFF;
+	req->nic_desc.cq_count = 0xFFFF;
+	req->nic_desc.toe_conn_count = 0xFFFF;
+	req->nic_desc.eq_count = 0xFFFF;
+	req->nic_desc.link_param = 0xFF;
+	req->nic_desc.bw_min = 0xFFFFFFFF;
+	req->nic_desc.acpi_params = 0xFF;
+	req->nic_desc.wol_param = 0x0F;
+
+	/* Change BW */
+	req->nic_desc.bw_min = cpu_to_le32(bps);
+	req->nic_desc.bw_max = cpu_to_le32(bps);
+	status = be_mcc_notify_wait(adapter);
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+
+/* Uses sync mcc */
+int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_enable_disable_vf *req;
+	int status;
+
+	if (!lancer_chip(adapter))
+		return 0;
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+
+	req = embedded_payload(wrb);
+
+	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+			       OPCODE_COMMON_ENABLE_DISABLE_VF, sizeof(*req),
+			       wrb, NULL);
+
+	req->hdr.domain = domain;
+	req->enable = 1;
+	status = be_mcc_notify_wait(adapter);
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+
 int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
 			int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
 {
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 0936e21..d6552e1 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -196,9 +196,14 @@ struct be_mcc_mailbox {
 #define OPCODE_COMMON_GET_MAC_LIST			147
 #define OPCODE_COMMON_SET_MAC_LIST			148
 #define OPCODE_COMMON_GET_HSW_CONFIG			152
+#define OPCODE_COMMON_GET_FUNC_CONFIG			160
+#define OPCODE_COMMON_GET_PROFILE_CONFIG		164
+#define OPCODE_COMMON_SET_PROFILE_CONFIG		165
 #define OPCODE_COMMON_SET_HSW_CONFIG			153
+#define OPCODE_COMMON_GET_FN_PRIVILEGES			170
 #define OPCODE_COMMON_READ_OBJECT			171
 #define OPCODE_COMMON_WRITE_OBJECT			172
+#define OPCODE_COMMON_ENABLE_DISABLE_VF			196
 
 #define OPCODE_ETH_RSS_CONFIG				1
 #define OPCODE_ETH_ACPI_CONFIG				2
@@ -1151,14 +1156,22 @@ struct flashrom_params {
 	u32 op_type;
 	u32 data_buf_size;
 	u32 offset;
-	u8 data_buf[4];
 };
 
 struct be_cmd_write_flashrom {
 	struct be_cmd_req_hdr hdr;
 	struct flashrom_params params;
-};
+	u8 data_buf[32768];
+	u8 rsvd[4];
+} __packed;
 
+/* cmd to read flash crc */
+struct be_cmd_read_flash_crc {
+	struct be_cmd_req_hdr hdr;
+	struct flashrom_params params;
+	u8 crc[4];
+	u8 rsvd[4];
+};
 /**************** Lancer Firmware Flash ************/
 struct amap_lancer_write_obj_context {
 	u8 write_length[24];
@@ -1429,6 +1442,41 @@ struct be_cmd_resp_set_func_cap {
 	u8 rsvd[212];
 };
 
+/*********************** Function Privileges ***********************/
+enum {
+	BE_PRIV_DEFAULT = 0x1,
+	BE_PRIV_LNKQUERY = 0x2,
+	BE_PRIV_LNKSTATS = 0x4,
+	BE_PRIV_LNKMGMT = 0x8,
+	BE_PRIV_LNKDIAG = 0x10,
+	BE_PRIV_UTILQUERY = 0x20,
+	BE_PRIV_FILTMGMT = 0x40,
+	BE_PRIV_IFACEMGMT = 0x80,
+	BE_PRIV_VHADM = 0x100,
+	BE_PRIV_DEVCFG = 0x200,
+	BE_PRIV_DEVSEC = 0x400
+};
+#define MAX_PRIVILEGES		(BE_PRIV_VHADM | BE_PRIV_DEVCFG | \
+				 BE_PRIV_DEVSEC)
+#define MIN_PRIVILEGES		BE_PRIV_DEFAULT
+
+struct be_cmd_priv_map {
+	u8 opcode;
+	u8 subsystem;
+	u32 priv_mask;
+};
+
+struct be_cmd_req_get_fn_privileges {
+	struct be_cmd_req_hdr hdr;
+	u32 rsvd;
+};
+
+struct be_cmd_resp_get_fn_privileges {
+	struct be_cmd_resp_hdr hdr;
+	u32 privilege_mask;
+};
+
+
 /******************** GET/SET_MACLIST  **************************/
 #define BE_MAX_MAC			64
 struct be_cmd_req_get_mac_list {
@@ -1608,33 +1656,6 @@ struct be_cmd_resp_get_stats_v1 {
 	struct be_hw_stats_v1 hw_stats;
 };
 
-static inline void *hw_stats_from_cmd(struct be_adapter *adapter)
-{
-	if (adapter->generation == BE_GEN3) {
-		struct be_cmd_resp_get_stats_v1 *cmd = adapter->stats_cmd.va;
-
-		return &cmd->hw_stats;
-	} else {
-		struct be_cmd_resp_get_stats_v0 *cmd = adapter->stats_cmd.va;
-
-		return &cmd->hw_stats;
-	}
-}
-
-static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter)
-{
-	if (adapter->generation == BE_GEN3) {
-		struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
-
-		return &hw_stats->erx;
-	} else {
-		struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
-
-		return &hw_stats->erx;
-	}
-}
-
-
 /************** get fat capabilites *******************/
 #define MAX_MODULES 27
 #define MAX_MODES 4
@@ -1684,6 +1705,96 @@ struct be_cmd_req_set_ext_fat_caps {
 	struct be_fat_conf_params set_params;
 };
 
+#define RESOURCE_DESC_SIZE			72
+#define NIC_RESOURCE_DESC_TYPE_ID		0x41
+#define MAX_RESOURCE_DESC			4
+
+/* QOS unit number */
+#define QUN					4
+/* Immediate */
+#define IMM					6
+/* No save */
+#define NOSV					7
+
+struct be_nic_resource_desc {
+	u8 desc_type;
+	u8 desc_len;
+	u8 rsvd1;
+	u8 flags;
+	u8 vf_num;
+	u8 rsvd2;
+	u8 pf_num;
+	u8 rsvd3;
+	u16 unicast_mac_count;
+	u8 rsvd4[6];
+	u16 mcc_count;
+	u16 vlan_count;
+	u16 mcast_mac_count;
+	u16 txq_count;
+	u16 rq_count;
+	u16 rssq_count;
+	u16 lro_count;
+	u16 cq_count;
+	u16 toe_conn_count;
+	u16 eq_count;
+	u32 rsvd5;
+	u32 cap_flags;
+	u8 link_param;
+	u8 rsvd6[3];
+	u32 bw_min;
+	u32 bw_max;
+	u8 acpi_params;
+	u8 wol_param;
+	u16 rsvd7;
+	u32 rsvd8[3];
+};
+
+struct be_cmd_req_get_func_config {
+	struct be_cmd_req_hdr hdr;
+};
+
+struct be_cmd_resp_get_func_config {
+	struct be_cmd_req_hdr hdr;
+	u32 desc_count;
+	u8 func_param[MAX_RESOURCE_DESC * RESOURCE_DESC_SIZE];
+};
+
+#define ACTIVE_PROFILE_TYPE			0x2
+struct be_cmd_req_get_profile_config {
+	struct be_cmd_req_hdr hdr;
+	u8 rsvd;
+	u8 type;
+	u16 rsvd1;
+};
+
+struct be_cmd_resp_get_profile_config {
+	struct be_cmd_req_hdr hdr;
+	u32 desc_count;
+	u8 func_param[MAX_RESOURCE_DESC * RESOURCE_DESC_SIZE];
+};
+
+struct be_cmd_req_set_profile_config {
+	struct be_cmd_req_hdr hdr;
+	u32 rsvd;
+	u32 desc_count;
+	struct be_nic_resource_desc nic_desc;
+};
+
+struct be_cmd_resp_set_profile_config {
+	struct be_cmd_req_hdr hdr;
+};
+
+struct be_cmd_enable_disable_vf {
+	struct be_cmd_req_hdr hdr;
+	u8 enable;
+	u8 rsvd[3];
+};
+
+static inline bool check_privilege(struct be_adapter *adapter, u32 flags)
+{
+	return flags & adapter->cmd_privileges ? true : false;
+}
+
 extern int be_pci_fnum_get(struct be_adapter *adapter);
 extern int be_fw_wait_ready(struct be_adapter *adapter);
 extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
@@ -1780,6 +1891,8 @@ extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter);
 extern int be_cmd_req_native_mode(struct be_adapter *adapter);
 extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size);
 extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf);
+extern int be_cmd_get_fn_privileges(struct be_adapter *adapter,
+				    u32 *privilege, u32 domain);
 extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
 				    bool *pmac_id_active, u32 *pmac_id,
 				    u8 domain);
@@ -1798,4 +1911,10 @@ extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
 extern int lancer_wait_ready(struct be_adapter *adapter);
 extern int lancer_test_and_set_rdy_state(struct be_adapter *adapter);
 extern int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name);
+extern int be_cmd_get_func_config(struct be_adapter *adapter);
+extern int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags,
+				     u8 domain);
 
+extern int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps,
+				     u8 domain);
+extern int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain);
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index 8e6fb0b..00454a1 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -261,6 +261,9 @@ be_get_reg_len(struct net_device *netdev)
 	struct be_adapter *adapter = netdev_priv(netdev);
 	u32 log_size = 0;
 
+	if (!check_privilege(adapter, MAX_PRIVILEGES))
+		return 0;
+
 	if (be_physfn(adapter)) {
 		if (lancer_chip(adapter))
 			log_size = lancer_cmd_get_file_len(adapter,
@@ -525,6 +528,10 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 	u8 link_status;
 	u16 link_speed = 0;
 	int status;
+	u32 auto_speeds;
+	u32 fixed_speeds;
+	u32 dac_cable_len;
+	u16 interface_type;
 
 	if (adapter->phy.link_speed < 0) {
 		status = be_cmd_link_status_query(adapter, &link_speed,
@@ -534,39 +541,46 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 		ethtool_cmd_speed_set(ecmd, link_speed);
 
 		status = be_cmd_get_phy_info(adapter);
-		if (status)
-			return status;
-
-		ecmd->supported =
-			convert_to_et_setting(adapter->phy.interface_type,
-					adapter->phy.auto_speeds_supported |
-					adapter->phy.fixed_speeds_supported);
-		ecmd->advertising =
-			convert_to_et_setting(adapter->phy.interface_type,
-					adapter->phy.auto_speeds_supported);
-
-		ecmd->port = be_get_port_type(adapter->phy.interface_type,
-					      adapter->phy.dac_cable_len);
-
-		if (adapter->phy.auto_speeds_supported) {
-			ecmd->supported |= SUPPORTED_Autoneg;
-			ecmd->autoneg = AUTONEG_ENABLE;
-			ecmd->advertising |= ADVERTISED_Autoneg;
-		}
+		if (!status) {
+			interface_type = adapter->phy.interface_type;
+			auto_speeds = adapter->phy.auto_speeds_supported;
+			fixed_speeds = adapter->phy.fixed_speeds_supported;
+			dac_cable_len = adapter->phy.dac_cable_len;
+
+			ecmd->supported =
+				convert_to_et_setting(interface_type,
+						      auto_speeds |
+						      fixed_speeds);
+			ecmd->advertising =
+				convert_to_et_setting(interface_type,
+						      auto_speeds);
+
+			ecmd->port = be_get_port_type(interface_type,
+						      dac_cable_len);
+
+			if (adapter->phy.auto_speeds_supported) {
+				ecmd->supported |= SUPPORTED_Autoneg;
+				ecmd->autoneg = AUTONEG_ENABLE;
+				ecmd->advertising |= ADVERTISED_Autoneg;
+			}
 
-		if (be_pause_supported(adapter)) {
 			ecmd->supported |= SUPPORTED_Pause;
-			ecmd->advertising |= ADVERTISED_Pause;
-		}
-
-		switch (adapter->phy.interface_type) {
-		case PHY_TYPE_KR_10GB:
-		case PHY_TYPE_KX4_10GB:
-			ecmd->transceiver = XCVR_INTERNAL;
-			break;
-		default:
-			ecmd->transceiver = XCVR_EXTERNAL;
-			break;
+			if (be_pause_supported(adapter))
+				ecmd->advertising |= ADVERTISED_Pause;
+
+			switch (adapter->phy.interface_type) {
+			case PHY_TYPE_KR_10GB:
+			case PHY_TYPE_KX4_10GB:
+				ecmd->transceiver = XCVR_INTERNAL;
+				break;
+			default:
+				ecmd->transceiver = XCVR_EXTERNAL;
+				break;
+			}
+		} else {
+			ecmd->port = PORT_OTHER;
+			ecmd->autoneg = AUTONEG_DISABLE;
+			ecmd->transceiver = XCVR_DUMMY1;
 		}
 
 		/* Save for future use */
@@ -787,6 +801,10 @@ static int
 be_get_eeprom_len(struct net_device *netdev)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
+
+	if (!check_privilege(adapter, MAX_PRIVILEGES))
+		return 0;
+
 	if (lancer_chip(adapter)) {
 		if (be_physfn(adapter))
 			return lancer_cmd_get_file_len(adapter,
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h
index b755f70..541d453 100644
--- a/drivers/net/ethernet/emulex/benet/be_hw.h
+++ b/drivers/net/ethernet/emulex/benet/be_hw.h
@@ -31,12 +31,12 @@
 
 #define MPU_EP_CONTROL 		0
 
-/********** MPU semphore ******************/
-#define MPU_EP_SEMAPHORE_OFFSET		0xac
-#define MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET	0x400
-#define EP_SEMAPHORE_POST_STAGE_MASK		0x0000FFFF
-#define EP_SEMAPHORE_POST_ERR_MASK		0x1
-#define EP_SEMAPHORE_POST_ERR_SHIFT		31
+/********** MPU semphore: used for SH & BE  *************/
+#define SLIPORT_SEMAPHORE_OFFSET_BE		0x7c
+#define SLIPORT_SEMAPHORE_OFFSET_SH		0x94
+#define POST_STAGE_MASK				0x0000FFFF
+#define POST_ERR_MASK				0x1
+#define POST_ERR_SHIFT				31
 
 /* MPU semphore POST stage values */
 #define POST_STAGE_AWAITING_HOST_RDY 	0x1 /* FW awaiting goahead from host */
@@ -59,6 +59,9 @@
 #define PHYSDEV_CONTROL_FW_RESET_MASK	0x00000002
 #define PHYSDEV_CONTROL_INP_MASK	0x40000000
 
+#define SLIPORT_ERROR_NO_RESOURCE1	0x2
+#define SLIPORT_ERROR_NO_RESOURCE2	0x9
+
 /********* Memory BAR register ************/
 #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 	0xfc
 /* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt
@@ -102,11 +105,6 @@
 #define SLI_INTF_TYPE_2		2
 #define SLI_INTF_TYPE_3		3
 
-/* SLI family */
-#define BE_SLI_FAMILY		0x0
-#define LANCER_A0_SLI_FAMILY	0xA
-#define SKYHAWK_SLI_FAMILY      0x2
-
 /********* ISR0 Register offset **********/
 #define CEV_ISR0_OFFSET 			0xC18
 #define CEV_ISR_SIZE				4
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index d1b6cc5..0661e93 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -44,6 +44,7 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
 	{ PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID3)},
 	{ PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID4)},
 	{ PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID5)},
+	{ PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID6)},
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, be_dev_ids);
@@ -237,23 +238,46 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
 	int status = 0;
 	u8 current_mac[ETH_ALEN];
 	u32 pmac_id = adapter->pmac_id[0];
+	bool active_mac = true;
 
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 
-	status = be_cmd_mac_addr_query(adapter, current_mac, false,
-				       adapter->if_handle, 0);
+	/* For BE VF, MAC address is already activated by PF.
+	 * Hence only operation left is updating netdev->devaddr.
+	 * Update it if user is passing the same MAC which was used
+	 * during configuring VF MAC from PF(Hypervisor).
+	 */
+	if (!lancer_chip(adapter) && !be_physfn(adapter)) {
+		status = be_cmd_mac_addr_query(adapter, current_mac,
+					       false, adapter->if_handle, 0);
+		if (!status && !memcmp(current_mac, addr->sa_data, ETH_ALEN))
+			goto done;
+		else
+			goto err;
+	}
+
+	if (!memcmp(addr->sa_data, netdev->dev_addr, ETH_ALEN))
+		goto done;
+
+	/* For Lancer check if any MAC is active.
+	 * If active, get its mac id.
+	 */
+	if (lancer_chip(adapter) && !be_physfn(adapter))
+		be_cmd_get_mac_from_list(adapter, current_mac, &active_mac,
+					 &pmac_id, 0);
+
+	status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
+				 adapter->if_handle,
+				 &adapter->pmac_id[0], 0);
+
 	if (status)
 		goto err;
 
-	if (memcmp(addr->sa_data, current_mac, ETH_ALEN)) {
-		status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
-				adapter->if_handle, &adapter->pmac_id[0], 0);
-		if (status)
-			goto err;
-
-		be_cmd_pmac_del(adapter, adapter->if_handle, pmac_id, 0);
-	}
+	if (active_mac)
+		be_cmd_pmac_del(adapter, adapter->if_handle,
+				pmac_id, 0);
+done:
 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
 	return 0;
 err:
@@ -261,7 +285,35 @@ err:
 	return status;
 }
 
-static void populate_be2_stats(struct be_adapter *adapter)
+/* BE2 supports only v0 cmd */
+static void *hw_stats_from_cmd(struct be_adapter *adapter)
+{
+	if (BE2_chip(adapter)) {
+		struct be_cmd_resp_get_stats_v0 *cmd = adapter->stats_cmd.va;
+
+		return &cmd->hw_stats;
+	} else  {
+		struct be_cmd_resp_get_stats_v1 *cmd = adapter->stats_cmd.va;
+
+		return &cmd->hw_stats;
+	}
+}
+
+/* BE2 supports only v0 cmd */
+static void *be_erx_stats_from_cmd(struct be_adapter *adapter)
+{
+	if (BE2_chip(adapter)) {
+		struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
+
+		return &hw_stats->erx;
+	} else {
+		struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
+
+		return &hw_stats->erx;
+	}
+}
+
+static void populate_be_v0_stats(struct be_adapter *adapter)
 {
 	struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
 	struct be_pmem_stats *pmem_sts = &hw_stats->pmem;
@@ -310,7 +362,7 @@ static void populate_be2_stats(struct be_adapter *adapter)
 	adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops;
 }
 
-static void populate_be3_stats(struct be_adapter *adapter)
+static void populate_be_v1_stats(struct be_adapter *adapter)
 {
 	struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
 	struct be_pmem_stats *pmem_sts = &hw_stats->pmem;
@@ -412,28 +464,25 @@ void be_parse_stats(struct be_adapter *adapter)
 	struct be_rx_obj *rxo;
 	int i;
 
-	if (adapter->generation == BE_GEN3) {
-		if (lancer_chip(adapter))
-			populate_lancer_stats(adapter);
-		 else
-			populate_be3_stats(adapter);
+	if (lancer_chip(adapter)) {
+		populate_lancer_stats(adapter);
 	} else {
-		populate_be2_stats(adapter);
-	}
-
-	if (lancer_chip(adapter))
-		goto done;
+		if (BE2_chip(adapter))
+			populate_be_v0_stats(adapter);
+		else
+			/* for BE3 and Skyhawk */
+			populate_be_v1_stats(adapter);
 
-	/* as erx_v1 is longer than v0, ok to use v1 defn for v0 access */
-	for_all_rx_queues(adapter, rxo, i) {
-		/* below erx HW counter can actually wrap around after
-		 * 65535. Driver accumulates a 32-bit value
-		 */
-		accumulate_16bit_val(&rx_stats(rxo)->rx_drops_no_frags,
-				(u16)erx->rx_drops_no_fragments[rxo->q.id]);
+		/* as erx_v1 is longer than v0, ok to use v1 for v0 access */
+		for_all_rx_queues(adapter, rxo, i) {
+			/* below erx HW counter can actually wrap around after
+			 * 65535. Driver accumulates a 32-bit value
+			 */
+			accumulate_16bit_val(&rx_stats(rxo)->rx_drops_no_frags,
+					     (u16)erx->rx_drops_no_fragments \
+					     [rxo->q.id]);
+		}
 	}
-done:
-	return;
 }
 
 static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev,
@@ -597,16 +646,6 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr,
 			hdr, skb_shinfo(skb)->gso_size);
 		if (skb_is_gso_v6(skb) && !lancer_chip(adapter))
 			AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso6, hdr, 1);
-		if (lancer_chip(adapter) && adapter->sli_family  ==
-							LANCER_A0_SLI_FAMILY) {
-			AMAP_SET_BITS(struct amap_eth_hdr_wrb, ipcs, hdr, 1);
-			if (is_tcp_pkt(skb))
-				AMAP_SET_BITS(struct amap_eth_hdr_wrb,
-								tcpcs, hdr, 1);
-			else if (is_udp_pkt(skb))
-				AMAP_SET_BITS(struct amap_eth_hdr_wrb,
-								udpcs, hdr, 1);
-		}
 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		if (is_tcp_pkt(skb))
 			AMAP_SET_BITS(struct amap_eth_hdr_wrb, tcpcs, hdr, 1);
@@ -856,11 +895,15 @@ static int be_vlan_add_vid(struct net_device *netdev, u16 vid)
 	struct be_adapter *adapter = netdev_priv(netdev);
 	int status = 0;
 
-	if (!be_physfn(adapter)) {
+	if (!lancer_chip(adapter) && !be_physfn(adapter)) {
 		status = -EINVAL;
 		goto ret;
 	}
 
+	/* Packets with VID 0 are always received by Lancer by default */
+	if (lancer_chip(adapter) && vid == 0)
+		goto ret;
+
 	adapter->vlan_tag[vid] = 1;
 	if (adapter->vlans_added <= (adapter->max_vlans + 1))
 		status = be_vid_config(adapter);
@@ -878,11 +921,15 @@ static int be_vlan_rem_vid(struct net_device *netdev, u16 vid)
 	struct be_adapter *adapter = netdev_priv(netdev);
 	int status = 0;
 
-	if (!be_physfn(adapter)) {
+	if (!lancer_chip(adapter) && !be_physfn(adapter)) {
 		status = -EINVAL;
 		goto ret;
 	}
 
+	/* Packets with VID 0 are always received by Lancer by default */
+	if (lancer_chip(adapter) && vid == 0)
+		goto ret;
+
 	adapter->vlan_tag[vid] = 0;
 	if (adapter->vlans_added <= adapter->max_vlans)
 		status = be_vid_config(adapter);
@@ -917,7 +964,7 @@ static void be_set_rx_mode(struct net_device *netdev)
 
 	/* Enable multicast promisc if num configured exceeds what we support */
 	if (netdev->flags & IFF_ALLMULTI ||
-			netdev_mc_count(netdev) > BE_MAX_MC) {
+	    netdev_mc_count(netdev) > adapter->max_mcast_mac) {
 		be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON);
 		goto done;
 	}
@@ -962,6 +1009,9 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
 	struct be_adapter *adapter = netdev_priv(netdev);
 	struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
 	int status;
+	bool active_mac = false;
+	u32 pmac_id;
+	u8 old_mac[ETH_ALEN];
 
 	if (!sriov_enabled(adapter))
 		return -EPERM;
@@ -970,6 +1020,12 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
 		return -EINVAL;
 
 	if (lancer_chip(adapter)) {
+		status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac,
+						  &pmac_id, vf + 1);
+		if (!status && active_mac)
+			be_cmd_pmac_del(adapter, vf_cfg->if_handle,
+					pmac_id, vf + 1);
+
 		status = be_cmd_set_mac_list(adapter,  mac, 1, vf + 1);
 	} else {
 		status = be_cmd_pmac_del(adapter, vf_cfg->if_handle,
@@ -1062,7 +1118,10 @@ static int be_set_vf_tx_rate(struct net_device *netdev,
 		return -EINVAL;
 	}
 
-	status = be_cmd_set_qos(adapter, rate / 10, vf + 1);
+	if (lancer_chip(adapter))
+		status = be_cmd_set_profile_config(adapter, rate / 10, vf + 1);
+	else
+		status = be_cmd_set_qos(adapter, rate / 10, vf + 1);
 
 	if (status)
 		dev_err(&adapter->pdev->dev,
@@ -1616,24 +1675,6 @@ static inline int events_get(struct be_eq_obj *eqo)
 	return num;
 }
 
-static int event_handle(struct be_eq_obj *eqo)
-{
-	bool rearm = false;
-	int num = events_get(eqo);
-
-	/* Deal with any spurious interrupts that come without events */
-	if (!num)
-		rearm = true;
-
-	if (num || msix_enabled(eqo->adapter))
-		be_eq_notify(eqo->adapter, eqo->q.id, rearm, true, num);
-
-	if (num)
-		napi_schedule(&eqo->napi);
-
-	return num;
-}
-
 /* Leaves the EQ is disarmed state */
 static void be_eq_clean(struct be_eq_obj *eqo)
 {
@@ -1837,12 +1878,13 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)
 
 static int be_num_txqs_want(struct be_adapter *adapter)
 {
-	if (sriov_want(adapter) || be_is_mc(adapter) ||
-	    lancer_chip(adapter) || !be_physfn(adapter) ||
-	    adapter->generation == BE_GEN2)
+	if ((!lancer_chip(adapter) && sriov_want(adapter)) ||
+	    be_is_mc(adapter) ||
+	    (!lancer_chip(adapter) && !be_physfn(adapter)) ||
+	    BE2_chip(adapter))
 		return 1;
 	else
-		return MAX_TX_QS;
+		return adapter->max_tx_queues;
 }
 
 static int be_tx_cqs_create(struct be_adapter *adapter)
@@ -1954,22 +1996,31 @@ static int be_rx_cqs_create(struct be_adapter *adapter)
 
 static irqreturn_t be_intx(int irq, void *dev)
 {
-	struct be_adapter *adapter = dev;
-	int num_evts;
+	struct be_eq_obj *eqo = dev;
+	struct be_adapter *adapter = eqo->adapter;
+	int num_evts = 0;
 
-	/* With INTx only one EQ is used */
-	num_evts = event_handle(&adapter->eq_obj[0]);
-	if (num_evts)
-		return IRQ_HANDLED;
-	else
-		return IRQ_NONE;
+	/* On Lancer, clear-intr bit of the EQ DB does not work.
+	 * INTx is de-asserted only on notifying num evts.
+	 */
+	if (lancer_chip(adapter))
+		num_evts = events_get(eqo);
+
+	/* The EQ-notify may not de-assert INTx rightaway, causing
+	 * the ISR to be invoked again. So, return HANDLED even when
+	 * num_evts is zero.
+	 */
+	be_eq_notify(adapter, eqo->q.id, false, true, num_evts);
+	napi_schedule(&eqo->napi);
+	return IRQ_HANDLED;
 }
 
 static irqreturn_t be_msix(int irq, void *dev)
 {
 	struct be_eq_obj *eqo = dev;
 
-	event_handle(eqo);
+	be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0);
+	napi_schedule(&eqo->napi);
 	return IRQ_HANDLED;
 }
 
@@ -2065,9 +2116,11 @@ int be_poll(struct napi_struct *napi, int budget)
 {
 	struct be_eq_obj *eqo = container_of(napi, struct be_eq_obj, napi);
 	struct be_adapter *adapter = eqo->adapter;
-	int max_work = 0, work, i;
+	int max_work = 0, work, i, num_evts;
 	bool tx_done;
 
+	num_evts = events_get(eqo);
+
 	/* Process all TXQs serviced by this EQ */
 	for (i = eqo->idx; i < adapter->num_tx_qs; i += adapter->num_evt_qs) {
 		tx_done = be_process_tx(adapter, &adapter->tx_obj[i],
@@ -2090,10 +2143,10 @@ int be_poll(struct napi_struct *napi, int budget)
 
 	if (max_work < budget) {
 		napi_complete(napi);
-		be_eq_notify(adapter, eqo->q.id, true, false, 0);
+		be_eq_notify(adapter, eqo->q.id, true, false, num_evts);
 	} else {
 		/* As we'll continue in polling mode, count and clear events */
-		be_eq_notify(adapter, eqo->q.id, false, false, events_get(eqo));
+		be_eq_notify(adapter, eqo->q.id, false, false, num_evts);
 	}
 	return max_work;
 }
@@ -2177,9 +2230,11 @@ static void be_msix_disable(struct be_adapter *adapter)
 static uint be_num_rss_want(struct be_adapter *adapter)
 {
 	u32 num = 0;
+
 	if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
-	     !sriov_want(adapter) && be_physfn(adapter)) {
-		num = (adapter->be3_native) ? BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
+	    (lancer_chip(adapter) ||
+	     (!sriov_want(adapter) && be_physfn(adapter)))) {
+		num = adapter->max_rss_queues;
 		num = min_t(u32, num, (u32)netif_get_num_default_rss_queues());
 	}
 	return num;
@@ -2277,10 +2332,10 @@ static int be_irq_register(struct be_adapter *adapter)
 			return status;
 	}
 
-	/* INTx */
+	/* INTx: only the first EQ is used */
 	netdev->irq = adapter->pdev->irq;
 	status = request_irq(netdev->irq, be_intx, IRQF_SHARED, netdev->name,
-			adapter);
+			     &adapter->eq_obj[0]);
 	if (status) {
 		dev_err(&adapter->pdev->dev,
 			"INTx request IRQ failed - err %d\n", status);
@@ -2302,7 +2357,7 @@ static void be_irq_unregister(struct be_adapter *adapter)
 
 	/* INTx */
 	if (!msix_enabled(adapter)) {
-		free_irq(netdev->irq, adapter);
+		free_irq(netdev->irq, &adapter->eq_obj[0]);
 		goto done;
 	}
 
@@ -2579,10 +2634,30 @@ static int be_clear(struct be_adapter *adapter)
 	be_tx_queues_destroy(adapter);
 	be_evt_queues_destroy(adapter);
 
+	kfree(adapter->pmac_id);
+	adapter->pmac_id = NULL;
+
 	be_msix_disable(adapter);
 	return 0;
 }
 
+static void be_get_vf_if_cap_flags(struct be_adapter *adapter,
+				   u32 *cap_flags, u8 domain)
+{
+	bool profile_present = false;
+	int status;
+
+	if (lancer_chip(adapter)) {
+		status = be_cmd_get_profile_config(adapter, cap_flags, domain);
+		if (!status)
+			profile_present = true;
+	}
+
+	if (!profile_present)
+		*cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
+			     BE_IF_FLAGS_MULTICAST;
+}
+
 static int be_vf_setup_init(struct be_adapter *adapter)
 {
 	struct be_vf_cfg *vf_cfg;
@@ -2634,9 +2709,13 @@ static int be_vf_setup(struct be_adapter *adapter)
 	if (status)
 		goto err;
 
-	cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
-				BE_IF_FLAGS_MULTICAST;
 	for_all_vfs(adapter, vf_cfg, vf) {
+		be_get_vf_if_cap_flags(adapter, &cap_flags, vf + 1);
+
+		en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED |
+					BE_IF_FLAGS_BROADCAST |
+					BE_IF_FLAGS_MULTICAST);
+
 		status = be_cmd_if_create(adapter, cap_flags, en_flags,
 					  &vf_cfg->if_handle, vf + 1);
 		if (status)
@@ -2661,6 +2740,8 @@ static int be_vf_setup(struct be_adapter *adapter)
 		if (status)
 			goto err;
 		vf_cfg->def_vid = def_vlan;
+
+		be_cmd_enable_vf(adapter, vf + 1);
 	}
 	return 0;
 err:
@@ -2674,7 +2755,10 @@ static void be_setup_init(struct be_adapter *adapter)
 	adapter->if_handle = -1;
 	adapter->be3_native = false;
 	adapter->promiscuous = false;
-	adapter->eq_next_idx = 0;
+	if (be_physfn(adapter))
+		adapter->cmd_privileges = MAX_PRIVILEGES;
+	else
+		adapter->cmd_privileges = MIN_PRIVILEGES;
 }
 
 static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle,
@@ -2712,12 +2796,93 @@ static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle,
 	return status;
 }
 
+static void be_get_resources(struct be_adapter *adapter)
+{
+	int status;
+	bool profile_present = false;
+
+	if (lancer_chip(adapter)) {
+		status = be_cmd_get_func_config(adapter);
+
+		if (!status)
+			profile_present = true;
+	}
+
+	if (profile_present) {
+		/* Sanity fixes for Lancer */
+		adapter->max_pmac_cnt = min_t(u16, adapter->max_pmac_cnt,
+					      BE_UC_PMAC_COUNT);
+		adapter->max_vlans = min_t(u16, adapter->max_vlans,
+					   BE_NUM_VLANS_SUPPORTED);
+		adapter->max_mcast_mac = min_t(u16, adapter->max_mcast_mac,
+					       BE_MAX_MC);
+		adapter->max_tx_queues = min_t(u16, adapter->max_tx_queues,
+					       MAX_TX_QS);
+		adapter->max_rss_queues = min_t(u16, adapter->max_rss_queues,
+						BE3_MAX_RSS_QS);
+		adapter->max_event_queues = min_t(u16,
+						  adapter->max_event_queues,
+						  BE3_MAX_RSS_QS);
+
+		if (adapter->max_rss_queues &&
+		    adapter->max_rss_queues == adapter->max_rx_queues)
+			adapter->max_rss_queues -= 1;
+
+		if (adapter->max_event_queues < adapter->max_rss_queues)
+			adapter->max_rss_queues = adapter->max_event_queues;
+
+	} else {
+		if (be_physfn(adapter))
+			adapter->max_pmac_cnt = BE_UC_PMAC_COUNT;
+		else
+			adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT;
+
+		if (adapter->function_mode & FLEX10_MODE)
+			adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
+		else
+			adapter->max_vlans = BE_NUM_VLANS_SUPPORTED;
+
+		adapter->max_mcast_mac = BE_MAX_MC;
+		adapter->max_tx_queues = MAX_TX_QS;
+		adapter->max_rss_queues = (adapter->be3_native) ?
+					   BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
+		adapter->max_event_queues = BE3_MAX_RSS_QS;
+
+		adapter->if_cap_flags = BE_IF_FLAGS_UNTAGGED |
+					BE_IF_FLAGS_BROADCAST |
+					BE_IF_FLAGS_MULTICAST |
+					BE_IF_FLAGS_PASS_L3L4_ERRORS |
+					BE_IF_FLAGS_MCAST_PROMISCUOUS |
+					BE_IF_FLAGS_VLAN_PROMISCUOUS |
+					BE_IF_FLAGS_PROMISCUOUS;
+
+		if (adapter->function_caps & BE_FUNCTION_CAPS_RSS)
+			adapter->if_cap_flags |= BE_IF_FLAGS_RSS;
+	}
+}
+
 /* Routine to query per function resource limits */
 static int be_get_config(struct be_adapter *adapter)
 {
-	int pos;
+	int pos, status;
 	u16 dev_num_vfs;
 
+	status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
+				     &adapter->function_mode,
+				     &adapter->function_caps);
+	if (status)
+		goto err;
+
+	be_get_resources(adapter);
+
+	/* primary mac needs 1 pmac entry */
+	adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1,
+				   sizeof(u32), GFP_KERNEL);
+	if (!adapter->pmac_id) {
+		status = -ENOMEM;
+		goto err;
+	}
+
 	pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV);
 	if (pos) {
 		pci_read_config_word(adapter->pdev, pos + PCI_SRIOV_TOTAL_VF,
@@ -2726,13 +2891,14 @@ static int be_get_config(struct be_adapter *adapter)
 			dev_num_vfs = min_t(u16, dev_num_vfs, MAX_VFS);
 		adapter->dev_num_vfs = dev_num_vfs;
 	}
-	return 0;
+err:
+	return status;
 }
 
 static int be_setup(struct be_adapter *adapter)
 {
 	struct device *dev = &adapter->pdev->dev;
-	u32 cap_flags, en_flags;
+	u32 en_flags;
 	u32 tx_fc, rx_fc;
 	int status;
 	u8 mac[ETH_ALEN];
@@ -2740,9 +2906,12 @@ static int be_setup(struct be_adapter *adapter)
 
 	be_setup_init(adapter);
 
-	be_get_config(adapter);
+	if (!lancer_chip(adapter))
+		be_cmd_req_native_mode(adapter);
 
-	be_cmd_req_native_mode(adapter);
+	status = be_get_config(adapter);
+	if (status)
+		goto err;
 
 	be_msix_enable(adapter);
 
@@ -2762,24 +2931,22 @@ static int be_setup(struct be_adapter *adapter)
 	if (status)
 		goto err;
 
+	be_cmd_get_fn_privileges(adapter, &adapter->cmd_privileges, 0);
+	/* In UMC mode FW does not return right privileges.
+	 * Override with correct privilege equivalent to PF.
+	 */
+	if (be_is_mc(adapter))
+		adapter->cmd_privileges = MAX_PRIVILEGES;
+
 	en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
 			BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS;
-	cap_flags = en_flags | BE_IF_FLAGS_MCAST_PROMISCUOUS |
-			BE_IF_FLAGS_VLAN_PROMISCUOUS | BE_IF_FLAGS_PROMISCUOUS;
 
-	if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) {
-		cap_flags |= BE_IF_FLAGS_RSS;
+	if (adapter->function_caps & BE_FUNCTION_CAPS_RSS)
 		en_flags |= BE_IF_FLAGS_RSS;
-	}
 
-	if (lancer_chip(adapter) && !be_physfn(adapter)) {
-		en_flags = BE_IF_FLAGS_UNTAGGED |
-			    BE_IF_FLAGS_BROADCAST |
-			    BE_IF_FLAGS_MULTICAST;
-		cap_flags = en_flags;
-	}
+	en_flags = en_flags & adapter->if_cap_flags;
 
-	status = be_cmd_if_create(adapter, cap_flags, en_flags,
+	status = be_cmd_if_create(adapter, adapter->if_cap_flags, en_flags,
 				  &adapter->if_handle, 0);
 	if (status != 0)
 		goto err;
@@ -2827,8 +2994,8 @@ static int be_setup(struct be_adapter *adapter)
 			dev_warn(dev, "device doesn't support SRIOV\n");
 	}
 
-	be_cmd_get_phy_info(adapter);
-	if (be_pause_supported(adapter))
+	status = be_cmd_get_phy_info(adapter);
+	if (!status && be_pause_supported(adapter))
 		adapter->phy.fc_autoneg = 1;
 
 	schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
@@ -2846,8 +3013,10 @@ static void be_netpoll(struct net_device *netdev)
 	struct be_eq_obj *eqo;
 	int i;
 
-	for_all_evt_queues(adapter, eqo, i)
-		event_handle(eqo);
+	for_all_evt_queues(adapter, eqo, i) {
+		be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0);
+		napi_schedule(&eqo->napi);
+	}
 
 	return;
 }
@@ -2895,7 +3064,7 @@ static bool is_comp_in_ufi(struct be_adapter *adapter,
 	int i = 0, img_type = 0;
 	struct flash_section_info_g2 *fsec_g2 = NULL;
 
-	if (adapter->generation != BE_GEN3)
+	if (BE2_chip(adapter))
 		fsec_g2 = (struct flash_section_info_g2 *)fsec;
 
 	for (i = 0; i < MAX_FLASH_COMP; i++) {
@@ -2928,7 +3097,49 @@ struct flash_section_info *get_fsec_info(struct be_adapter *adapter,
 	return NULL;
 }
 
-static int be_flash_data(struct be_adapter *adapter,
+static int be_flash(struct be_adapter *adapter, const u8 *img,
+		struct be_dma_mem *flash_cmd, int optype, int img_size)
+{
+	u32 total_bytes = 0, flash_op, num_bytes = 0;
+	int status = 0;
+	struct be_cmd_write_flashrom *req = flash_cmd->va;
+
+	total_bytes = img_size;
+	while (total_bytes) {
+		num_bytes = min_t(u32, 32*1024, total_bytes);
+
+		total_bytes -= num_bytes;
+
+		if (!total_bytes) {
+			if (optype == OPTYPE_PHY_FW)
+				flash_op = FLASHROM_OPER_PHY_FLASH;
+			else
+				flash_op = FLASHROM_OPER_FLASH;
+		} else {
+			if (optype == OPTYPE_PHY_FW)
+				flash_op = FLASHROM_OPER_PHY_SAVE;
+			else
+				flash_op = FLASHROM_OPER_SAVE;
+		}
+
+		memcpy(req->data_buf, img, num_bytes);
+		img += num_bytes;
+		status = be_cmd_write_flashrom(adapter, flash_cmd, optype,
+						flash_op, num_bytes);
+		if (status) {
+			if (status == ILLEGAL_IOCTL_REQ &&
+			    optype == OPTYPE_PHY_FW)
+				break;
+			dev_err(&adapter->pdev->dev,
+				"cmd to write to flash rom failed.\n");
+			return status;
+		}
+	}
+	return 0;
+}
+
+/* For BE2 and BE3 */
+static int be_flash_BEx(struct be_adapter *adapter,
 			 const struct firmware *fw,
 			 struct be_dma_mem *flash_cmd,
 			 int num_of_images)
@@ -2936,12 +3147,9 @@ static int be_flash_data(struct be_adapter *adapter,
 {
 	int status = 0, i, filehdr_size = 0;
 	int img_hdrs_size = (num_of_images * sizeof(struct image_hdr));
-	u32 total_bytes = 0, flash_op;
-	int num_bytes;
 	const u8 *p = fw->data;
-	struct be_cmd_write_flashrom *req = flash_cmd->va;
 	const struct flash_comp *pflashcomp;
-	int num_comp, hdr_size;
+	int num_comp, redboot;
 	struct flash_section_info *fsec = NULL;
 
 	struct flash_comp gen3_flash_types[] = {
@@ -2986,7 +3194,7 @@ static int be_flash_data(struct be_adapter *adapter,
 			 FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_FCoE}
 	};
 
-	if (adapter->generation == BE_GEN3) {
+	if (BE3_chip(adapter)) {
 		pflashcomp = gen3_flash_types;
 		filehdr_size = sizeof(struct flash_file_hdr_g3);
 		num_comp = ARRAY_SIZE(gen3_flash_types);
@@ -2995,6 +3203,7 @@ static int be_flash_data(struct be_adapter *adapter,
 		filehdr_size = sizeof(struct flash_file_hdr_g2);
 		num_comp = ARRAY_SIZE(gen2_flash_types);
 	}
+
 	/* Get flash section info*/
 	fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
 	if (!fsec) {
@@ -3010,70 +3219,105 @@ static int be_flash_data(struct be_adapter *adapter,
 		    memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0)
 			continue;
 
-		if (pflashcomp[i].optype == OPTYPE_PHY_FW) {
-			if (!phy_flashing_required(adapter))
+		if (pflashcomp[i].optype == OPTYPE_PHY_FW  &&
+		    !phy_flashing_required(adapter))
 				continue;
-		}
-
-		hdr_size = filehdr_size +
-			   (num_of_images * sizeof(struct image_hdr));
 
-		if ((pflashcomp[i].optype == OPTYPE_REDBOOT) &&
-		    (!be_flash_redboot(adapter, fw->data, pflashcomp[i].offset,
-				       pflashcomp[i].size, hdr_size)))
-			continue;
+		if (pflashcomp[i].optype == OPTYPE_REDBOOT) {
+			redboot = be_flash_redboot(adapter, fw->data,
+				pflashcomp[i].offset, pflashcomp[i].size,
+				filehdr_size + img_hdrs_size);
+			if (!redboot)
+				continue;
+		}
 
-		/* Flash the component */
 		p = fw->data;
 		p += filehdr_size + pflashcomp[i].offset + img_hdrs_size;
 		if (p + pflashcomp[i].size > fw->data + fw->size)
 			return -1;
-		total_bytes = pflashcomp[i].size;
-		while (total_bytes) {
-			if (total_bytes > 32*1024)
-				num_bytes = 32*1024;
-			else
-				num_bytes = total_bytes;
-			total_bytes -= num_bytes;
-			if (!total_bytes) {
-				if (pflashcomp[i].optype == OPTYPE_PHY_FW)
-					flash_op = FLASHROM_OPER_PHY_FLASH;
-				else
-					flash_op = FLASHROM_OPER_FLASH;
-			} else {
-				if (pflashcomp[i].optype == OPTYPE_PHY_FW)
-					flash_op = FLASHROM_OPER_PHY_SAVE;
-				else
-					flash_op = FLASHROM_OPER_SAVE;
-			}
-			memcpy(req->params.data_buf, p, num_bytes);
-			p += num_bytes;
-			status = be_cmd_write_flashrom(adapter, flash_cmd,
-				pflashcomp[i].optype, flash_op, num_bytes);
-			if (status) {
-				if ((status == ILLEGAL_IOCTL_REQ) &&
-					(pflashcomp[i].optype ==
-						OPTYPE_PHY_FW))
-					break;
-				dev_err(&adapter->pdev->dev,
-					"cmd to write to flash rom failed.\n");
-				return -1;
-			}
+
+		status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype,
+					pflashcomp[i].size);
+		if (status) {
+			dev_err(&adapter->pdev->dev,
+				"Flashing section type %d failed.\n",
+				pflashcomp[i].img_type);
+			return status;
 		}
 	}
 	return 0;
 }
 
-static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr)
+static int be_flash_skyhawk(struct be_adapter *adapter,
+		const struct firmware *fw,
+		struct be_dma_mem *flash_cmd, int num_of_images)
 {
-	if (fhdr == NULL)
-		return 0;
-	if (fhdr->build[0] == '3')
-		return BE_GEN3;
-	else if (fhdr->build[0] == '2')
-		return BE_GEN2;
-	else
-		return 0;
+	int status = 0, i, filehdr_size = 0;
+	int img_offset, img_size, img_optype, redboot;
+	int img_hdrs_size = num_of_images * sizeof(struct image_hdr);
+	const u8 *p = fw->data;
+	struct flash_section_info *fsec = NULL;
+
+	filehdr_size = sizeof(struct flash_file_hdr_g3);
+	fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
+	if (!fsec) {
+		dev_err(&adapter->pdev->dev,
+			"Invalid Cookie. UFI corrupted ?\n");
+		return -1;
+	}
+
+	for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
+		img_offset = le32_to_cpu(fsec->fsec_entry[i].offset);
+		img_size   = le32_to_cpu(fsec->fsec_entry[i].pad_size);
+
+		switch (le32_to_cpu(fsec->fsec_entry[i].type)) {
+		case IMAGE_FIRMWARE_iSCSI:
+			img_optype = OPTYPE_ISCSI_ACTIVE;
+			break;
+		case IMAGE_BOOT_CODE:
+			img_optype = OPTYPE_REDBOOT;
+			break;
+		case IMAGE_OPTION_ROM_ISCSI:
+			img_optype = OPTYPE_BIOS;
+			break;
+		case IMAGE_OPTION_ROM_PXE:
+			img_optype = OPTYPE_PXE_BIOS;
+			break;
+		case IMAGE_OPTION_ROM_FCoE:
+			img_optype = OPTYPE_FCOE_BIOS;
+			break;
+		case IMAGE_FIRMWARE_BACKUP_iSCSI:
+			img_optype = OPTYPE_ISCSI_BACKUP;
+			break;
+		case IMAGE_NCSI:
+			img_optype = OPTYPE_NCSI_FW;
+			break;
+		default:
+			continue;
+		}
+
+		if (img_optype == OPTYPE_REDBOOT) {
+			redboot = be_flash_redboot(adapter, fw->data,
+					img_offset, img_size,
+					filehdr_size + img_hdrs_size);
+			if (!redboot)
+				continue;
+		}
+
+		p = fw->data;
+		p += filehdr_size + img_offset + img_hdrs_size;
+		if (p + img_size > fw->data + fw->size)
+			return -1;
+
+		status = be_flash(adapter, p, flash_cmd, img_optype, img_size);
+		if (status) {
+			dev_err(&adapter->pdev->dev,
+				"Flashing section type %d failed.\n",
+				fsec->fsec_entry[i].type);
+			return status;
+		}
+	}
+	return 0;
 }
 
 static int lancer_wait_idle(struct be_adapter *adapter)
@@ -3207,6 +3451,28 @@ lancer_fw_exit:
 	return status;
 }
 
+#define UFI_TYPE2		2
+#define UFI_TYPE3		3
+#define UFI_TYPE4		4
+static int be_get_ufi_type(struct be_adapter *adapter,
+			   struct flash_file_hdr_g2 *fhdr)
+{
+	if (fhdr == NULL)
+		goto be_get_ufi_exit;
+
+	if (skyhawk_chip(adapter) && fhdr->build[0] == '4')
+		return UFI_TYPE4;
+	else if (BE3_chip(adapter) && fhdr->build[0] == '3')
+		return UFI_TYPE3;
+	else if (BE2_chip(adapter) && fhdr->build[0] == '2')
+		return UFI_TYPE2;
+
+be_get_ufi_exit:
+	dev_err(&adapter->pdev->dev,
+		"UFI and Interface are not compatible for flashing\n");
+	return -1;
+}
+
 static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
 {
 	struct flash_file_hdr_g2 *fhdr;
@@ -3214,12 +3480,9 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
 	struct image_hdr *img_hdr_ptr = NULL;
 	struct be_dma_mem flash_cmd;
 	const u8 *p;
-	int status = 0, i = 0, num_imgs = 0;
-
-	p = fw->data;
-	fhdr = (struct flash_file_hdr_g2 *) p;
+	int status = 0, i = 0, num_imgs = 0, ufi_type = 0;
 
-	flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024;
+	flash_cmd.size = sizeof(struct be_cmd_write_flashrom);
 	flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size,
 					  &flash_cmd.dma, GFP_KERNEL);
 	if (!flash_cmd.va) {
@@ -3229,27 +3492,32 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
 		goto be_fw_exit;
 	}
 
-	if ((adapter->generation == BE_GEN3) &&
-			(get_ufigen_type(fhdr) == BE_GEN3)) {
-		fhdr3 = (struct flash_file_hdr_g3 *) fw->data;
-		num_imgs = le32_to_cpu(fhdr3->num_imgs);
-		for (i = 0; i < num_imgs; i++) {
-			img_hdr_ptr = (struct image_hdr *) (fw->data +
-					(sizeof(struct flash_file_hdr_g3) +
-					 i * sizeof(struct image_hdr)));
-			if (le32_to_cpu(img_hdr_ptr->imageid) == 1)
-				status = be_flash_data(adapter, fw, &flash_cmd,
-							num_imgs);
+	p = fw->data;
+	fhdr = (struct flash_file_hdr_g2 *)p;
+
+	ufi_type = be_get_ufi_type(adapter, fhdr);
+
+	fhdr3 = (struct flash_file_hdr_g3 *)fw->data;
+	num_imgs = le32_to_cpu(fhdr3->num_imgs);
+	for (i = 0; i < num_imgs; i++) {
+		img_hdr_ptr = (struct image_hdr *)(fw->data +
+				(sizeof(struct flash_file_hdr_g3) +
+				 i * sizeof(struct image_hdr)));
+		if (le32_to_cpu(img_hdr_ptr->imageid) == 1) {
+			if (ufi_type == UFI_TYPE4)
+				status = be_flash_skyhawk(adapter, fw,
+							&flash_cmd, num_imgs);
+			else if (ufi_type == UFI_TYPE3)
+				status = be_flash_BEx(adapter, fw, &flash_cmd,
+						      num_imgs);
 		}
-	} else if ((adapter->generation == BE_GEN2) &&
-			(get_ufigen_type(fhdr) == BE_GEN2)) {
-		status = be_flash_data(adapter, fw, &flash_cmd, 0);
-	} else {
-		dev_err(&adapter->pdev->dev,
-			"UFI and Interface are not compatible for flashing\n");
-		status = -1;
 	}
 
+	if (ufi_type == UFI_TYPE2)
+		status = be_flash_BEx(adapter, fw, &flash_cmd, 0);
+	else if (ufi_type == -1)
+		status = -1;
+
 	dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va,
 			  flash_cmd.dma);
 	if (status) {
@@ -3344,80 +3612,47 @@ static void be_netdev_init(struct net_device *netdev)
 
 static void be_unmap_pci_bars(struct be_adapter *adapter)
 {
-	if (adapter->csr)
-		iounmap(adapter->csr);
 	if (adapter->db)
-		iounmap(adapter->db);
-	if (adapter->roce_db.base)
-		pci_iounmap(adapter->pdev, adapter->roce_db.base);
+		pci_iounmap(adapter->pdev, adapter->db);
 }
 
-static int lancer_roce_map_pci_bars(struct be_adapter *adapter)
+static int db_bar(struct be_adapter *adapter)
 {
-	struct pci_dev *pdev = adapter->pdev;
-	u8 __iomem *addr;
-
-	addr = pci_iomap(pdev, 2, 0);
-	if (addr == NULL)
-		return -ENOMEM;
+	if (lancer_chip(adapter) || !be_physfn(adapter))
+		return 0;
+	else
+		return 4;
+}
 
-	adapter->roce_db.base = addr;
-	adapter->roce_db.io_addr = pci_resource_start(pdev, 2);
-	adapter->roce_db.size = 8192;
-	adapter->roce_db.total_size = pci_resource_len(pdev, 2);
+static int be_roce_map_pci_bars(struct be_adapter *adapter)
+{
+	if (skyhawk_chip(adapter)) {
+		adapter->roce_db.size = 4096;
+		adapter->roce_db.io_addr = pci_resource_start(adapter->pdev,
+							      db_bar(adapter));
+		adapter->roce_db.total_size = pci_resource_len(adapter->pdev,
+							       db_bar(adapter));
+	}
 	return 0;
 }
 
 static int be_map_pci_bars(struct be_adapter *adapter)
 {
 	u8 __iomem *addr;
-	int db_reg;
+	u32 sli_intf;
 
-	if (lancer_chip(adapter)) {
-		if (be_type_2_3(adapter)) {
-			addr = ioremap_nocache(
-					pci_resource_start(adapter->pdev, 0),
-					pci_resource_len(adapter->pdev, 0));
-			if (addr == NULL)
-				return -ENOMEM;
-			adapter->db = addr;
-		}
-		if (adapter->if_type == SLI_INTF_TYPE_3) {
-			if (lancer_roce_map_pci_bars(adapter))
-				goto pci_map_err;
-		}
-		return 0;
-	}
-
-	if (be_physfn(adapter)) {
-		addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2),
-				pci_resource_len(adapter->pdev, 2));
-		if (addr == NULL)
-			return -ENOMEM;
-		adapter->csr = addr;
-	}
+	pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+	adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
+				SLI_INTF_IF_TYPE_SHIFT;
 
-	if (adapter->generation == BE_GEN2) {
-		db_reg = 4;
-	} else {
-		if (be_physfn(adapter))
-			db_reg = 4;
-		else
-			db_reg = 0;
-	}
-	addr = ioremap_nocache(pci_resource_start(adapter->pdev, db_reg),
-				pci_resource_len(adapter->pdev, db_reg));
+	addr = pci_iomap(adapter->pdev, db_bar(adapter), 0);
 	if (addr == NULL)
 		goto pci_map_err;
 	adapter->db = addr;
-	if (adapter->sli_family == SKYHAWK_SLI_FAMILY) {
-		adapter->roce_db.size = 4096;
-		adapter->roce_db.io_addr =
-				pci_resource_start(adapter->pdev, db_reg);
-		adapter->roce_db.total_size =
-				pci_resource_len(adapter->pdev, db_reg);
-	}
+
+	be_roce_map_pci_bars(adapter);
 	return 0;
+
 pci_map_err:
 	be_unmap_pci_bars(adapter);
 	return -ENOMEM;
@@ -3437,7 +3672,6 @@ static void be_ctrl_cleanup(struct be_adapter *adapter)
 	if (mem->va)
 		dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
 				  mem->dma);
-	kfree(adapter->pmac_id);
 }
 
 static int be_ctrl_init(struct be_adapter *adapter)
@@ -3445,8 +3679,14 @@ static int be_ctrl_init(struct be_adapter *adapter)
 	struct be_dma_mem *mbox_mem_alloc = &adapter->mbox_mem_alloced;
 	struct be_dma_mem *mbox_mem_align = &adapter->mbox_mem;
 	struct be_dma_mem *rx_filter = &adapter->rx_filter;
+	u32 sli_intf;
 	int status;
 
+	pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+	adapter->sli_family = (sli_intf & SLI_INTF_FAMILY_MASK) >>
+				 SLI_INTF_FAMILY_SHIFT;
+	adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0;
+
 	status = be_map_pci_bars(adapter);
 	if (status)
 		goto done;
@@ -3473,13 +3713,6 @@ static int be_ctrl_init(struct be_adapter *adapter)
 		goto free_mbox;
 	}
 	memset(rx_filter->va, 0, rx_filter->size);
-
-	/* primary mac needs 1 pmac entry */
-	adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1,
-				   sizeof(*adapter->pmac_id), GFP_KERNEL);
-	if (!adapter->pmac_id)
-		return -ENOMEM;
-
 	mutex_init(&adapter->mbox_lock);
 	spin_lock_init(&adapter->mcc_lock);
 	spin_lock_init(&adapter->mcc_cq_lock);
@@ -3512,14 +3745,14 @@ static int be_stats_init(struct be_adapter *adapter)
 {
 	struct be_dma_mem *cmd = &adapter->stats_cmd;
 
-	if (adapter->generation == BE_GEN2) {
+	if (lancer_chip(adapter))
+		cmd->size = sizeof(struct lancer_cmd_req_pport_stats);
+	else if (BE2_chip(adapter))
 		cmd->size = sizeof(struct be_cmd_req_get_stats_v0);
-	} else {
-		if (lancer_chip(adapter))
-			cmd->size = sizeof(struct lancer_cmd_req_pport_stats);
-		else
-			cmd->size = sizeof(struct be_cmd_req_get_stats_v1);
-	}
+	else
+		/* BE3 and Skyhawk */
+		cmd->size = sizeof(struct be_cmd_req_get_stats_v1);
+
 	cmd->va = dma_alloc_coherent(&adapter->pdev->dev, cmd->size, &cmd->dma,
 				     GFP_KERNEL);
 	if (cmd->va == NULL)
@@ -3573,6 +3806,9 @@ u32 be_get_fw_log_level(struct be_adapter *adapter)
 	u32 level = 0;
 	int j;
 
+	if (lancer_chip(adapter))
+		return 0;
+
 	memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
 	extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
 	extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size,
@@ -3598,26 +3834,12 @@ u32 be_get_fw_log_level(struct be_adapter *adapter)
 err:
 	return level;
 }
+
 static int be_get_initial_config(struct be_adapter *adapter)
 {
 	int status;
 	u32 level;
 
-	status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
-			&adapter->function_mode, &adapter->function_caps);
-	if (status)
-		return status;
-
-	if (adapter->function_mode & FLEX10_MODE)
-		adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
-	else
-		adapter->max_vlans = BE_NUM_VLANS_SUPPORTED;
-
-	if (be_physfn(adapter))
-		adapter->max_pmac_cnt = BE_UC_PMAC_COUNT;
-	else
-		adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT;
-
 	status = be_cmd_get_cntl_attributes(adapter);
 	if (status)
 		return status;
@@ -3642,55 +3864,6 @@ static int be_get_initial_config(struct be_adapter *adapter)
 	return 0;
 }
 
-static int be_dev_type_check(struct be_adapter *adapter)
-{
-	struct pci_dev *pdev = adapter->pdev;
-	u32 sli_intf = 0, if_type;
-
-	switch (pdev->device) {
-	case BE_DEVICE_ID1:
-	case OC_DEVICE_ID1:
-		adapter->generation = BE_GEN2;
-		break;
-	case BE_DEVICE_ID2:
-	case OC_DEVICE_ID2:
-		adapter->generation = BE_GEN3;
-		break;
-	case OC_DEVICE_ID3:
-	case OC_DEVICE_ID4:
-		pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
-		adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
-						SLI_INTF_IF_TYPE_SHIFT;
-		if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
-						SLI_INTF_IF_TYPE_SHIFT;
-		if (((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) ||
-			!be_type_2_3(adapter)) {
-			dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
-			return -EINVAL;
-		}
-		adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >>
-					 SLI_INTF_FAMILY_SHIFT);
-		adapter->generation = BE_GEN3;
-		break;
-	case OC_DEVICE_ID5:
-		pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
-		if ((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) {
-			dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
-			return -EINVAL;
-		}
-		adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >>
-					 SLI_INTF_FAMILY_SHIFT);
-		adapter->generation = BE_GEN3;
-		break;
-	default:
-		adapter->generation = 0;
-	}
-
-	pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
-	adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0;
-	return 0;
-}
-
 static int lancer_recover_func(struct be_adapter *adapter)
 {
 	int status;
@@ -3721,8 +3894,9 @@ static int lancer_recover_func(struct be_adapter *adapter)
 		"Adapter SLIPORT recovery succeeded\n");
 	return 0;
 err:
-	dev_err(&adapter->pdev->dev,
-		"Adapter SLIPORT recovery failed\n");
+	if (adapter->eeh_error)
+		dev_err(&adapter->pdev->dev,
+			"Adapter SLIPORT recovery failed\n");
 
 	return status;
 }
@@ -3845,11 +4019,6 @@ static int __devinit be_probe(struct pci_dev *pdev,
 	adapter = netdev_priv(netdev);
 	adapter->pdev = pdev;
 	pci_set_drvdata(pdev, adapter);
-
-	status = be_dev_type_check(adapter);
-	if (status)
-		goto free_netdev;
-
 	adapter->netdev = netdev;
 	SET_NETDEV_DEV(netdev, &pdev->dev);
 
@@ -4023,9 +4192,6 @@ static void be_shutdown(struct pci_dev *pdev)
 
 	netif_device_detach(adapter->netdev);
 
-	if (adapter->wol)
-		be_setup_wol(adapter, true);
-
 	be_cmd_reset_function(adapter);
 
 	pci_disable_device(pdev);
@@ -4061,9 +4227,13 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev,
 
 	/* The error could cause the FW to trigger a flash debug dump.
 	 * Resetting the card while flash dump is in progress
-	 * can cause it not to recover; wait for it to finish
+	 * can cause it not to recover; wait for it to finish.
+	 * Wait only for first function as it is needed only once per
+	 * adapter.
 	 */
-	ssleep(30);
+	if (pdev->devfn == 0)
+		ssleep(30);
+
 	return PCI_ERS_RESULT_NEED_RESET;
 }
 
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.c b/drivers/net/ethernet/emulex/benet/be_roce.c
index deecc44..55d32aa 100644
--- a/drivers/net/ethernet/emulex/benet/be_roce.c
+++ b/drivers/net/ethernet/emulex/benet/be_roce.c
@@ -47,10 +47,7 @@ static void _be_roce_dev_add(struct be_adapter *adapter)
 		dev_info.dpp_unmapped_len = 0;
 	}
 	dev_info.pdev = adapter->pdev;
-	if (adapter->sli_family == SKYHAWK_SLI_FAMILY)
-		dev_info.db = adapter->db;
-	else
-		dev_info.db = adapter->roce_db.base;
+	dev_info.db = adapter->db;
 	dev_info.unmapped_db = adapter->roce_db.io_addr;
 	dev_info.db_page_size = adapter->roce_db.size;
 	dev_info.db_total_size = adapter->roce_db.total_size;
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig
index feff516..5ba6e1c 100644
--- a/drivers/net/ethernet/freescale/Kconfig
+++ b/drivers/net/ethernet/freescale/Kconfig
@@ -92,4 +92,13 @@ config GIANFAR
 	  This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx,
 	  and MPC86xx family of chips, and the FEC on the 8540.
 
+config FEC_PTP
+	bool "PTP Hardware Clock (PHC)"
+	depends on FEC && ARCH_MXC
+	select PTP_1588_CLOCK
+	default y if SOC_IMX6Q
+	--help---
+	  Say Y here if you want to use PTP Hardware Clock (PHC) in the
+	  driver.  Only the basic clock operations have been implemented.
+
 endif # NET_VENDOR_FREESCALE
diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile
index 3d1839a..d4d19b3 100644
--- a/drivers/net/ethernet/freescale/Makefile
+++ b/drivers/net/ethernet/freescale/Makefile
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_FEC) += fec.o
+obj-$(CONFIG_FEC_PTP) += fec_ptp.o
 obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
 ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
 	obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index fffd205..2665162 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -140,21 +140,6 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
 #endif
 #endif /* CONFIG_M5272 */
 
-/* The number of Tx and Rx buffers.  These are allocated from the page
- * pool.  The code may assume these are power of two, so it it best
- * to keep them that size.
- * We don't need to allocate pages for the transmitter.  We just use
- * the skbuffer directly.
- */
-#define FEC_ENET_RX_PAGES	8
-#define FEC_ENET_RX_FRSIZE	2048
-#define FEC_ENET_RX_FRPPG	(PAGE_SIZE / FEC_ENET_RX_FRSIZE)
-#define RX_RING_SIZE		(FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
-#define FEC_ENET_TX_FRSIZE	2048
-#define FEC_ENET_TX_FRPPG	(PAGE_SIZE / FEC_ENET_TX_FRSIZE)
-#define TX_RING_SIZE		16	/* Must be power of two */
-#define TX_RING_MOD_MASK	15	/*   for this to work */
-
 #if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE)
 #error "FEC: descriptor ring size constants too large"
 #endif
@@ -179,9 +164,6 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
 #define PKT_MINBUF_SIZE		64
 #define PKT_MAXBLR_SIZE		1520
 
-/* This device has up to three irqs on some platforms */
-#define FEC_IRQ_NUM		3
-
 /*
  * The 5270/5271/5280/5282/532x RX control register also contains maximum frame
  * size bits. Other FEC hardware does not, so we need to take that into
@@ -194,61 +176,6 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
 #define	OPT_FRAME_SIZE	0
 #endif
 
-/* The FEC buffer descriptors track the ring buffers.  The rx_bd_base and
- * tx_bd_base always point to the base of the buffer descriptors.  The
- * cur_rx and cur_tx point to the currently available buffer.
- * The dirty_tx tracks the current buffer that is being sent by the
- * controller.  The cur_tx and dirty_tx are equal under both completely
- * empty and completely full conditions.  The empty/ready indicator in
- * the buffer descriptor determines the actual condition.
- */
-struct fec_enet_private {
-	/* Hardware registers of the FEC device */
-	void __iomem *hwp;
-
-	struct net_device *netdev;
-
-	struct clk *clk_ipg;
-	struct clk *clk_ahb;
-
-	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
-	unsigned char *tx_bounce[TX_RING_SIZE];
-	struct	sk_buff* tx_skbuff[TX_RING_SIZE];
-	struct	sk_buff* rx_skbuff[RX_RING_SIZE];
-	ushort	skb_cur;
-	ushort	skb_dirty;
-
-	/* CPM dual port RAM relative addresses */
-	dma_addr_t	bd_dma;
-	/* Address of Rx and Tx buffers */
-	struct bufdesc	*rx_bd_base;
-	struct bufdesc	*tx_bd_base;
-	/* The next free ring entry */
-	struct bufdesc	*cur_rx, *cur_tx;
-	/* The ring entries to be free()ed */
-	struct bufdesc	*dirty_tx;
-
-	uint	tx_full;
-	/* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
-	spinlock_t hw_lock;
-
-	struct	platform_device *pdev;
-
-	int	opened;
-	int	dev_id;
-
-	/* Phylib and MDIO interface */
-	struct	mii_bus *mii_bus;
-	struct	phy_device *phy_dev;
-	int	mii_timeout;
-	uint	phy_speed;
-	phy_interface_t	phy_interface;
-	int	link;
-	int	full_duplex;
-	struct	completion mdio_done;
-	int	irq[FEC_IRQ_NUM];
-};
-
 /* FEC MII MMFR bits definition */
 #define FEC_MMFR_ST		(1 << 30)
 #define FEC_MMFR_OP_READ	(2 << 28)
@@ -353,6 +280,17 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 			| BD_ENET_TX_LAST | BD_ENET_TX_TC);
 	bdp->cbd_sc = status;
 
+#ifdef CONFIG_FEC_PTP
+	bdp->cbd_bdu = 0;
+	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
+			fep->hwts_tx_en)) {
+			bdp->cbd_esc = (BD_ENET_TX_TS | BD_ENET_TX_INT);
+			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+	} else {
+
+		bdp->cbd_esc = BD_ENET_TX_INT;
+	}
+#endif
 	/* Trigger transmission start */
 	writel(0, fep->hwp + FEC_X_DES_ACTIVE);
 
@@ -510,10 +448,17 @@ fec_restart(struct net_device *ndev, int duplex)
 		writel(1 << 8, fep->hwp + FEC_X_WMRK);
 	}
 
+#ifdef CONFIG_FEC_PTP
+	ecntl |= (1 << 4);
+#endif
+
 	/* And last, enable the transmit and receive processing */
 	writel(ecntl, fep->hwp + FEC_ECNTRL);
 	writel(0, fep->hwp + FEC_R_DES_ACTIVE);
 
+#ifdef CONFIG_FEC_PTP
+	fec_ptp_start_cyclecounter(ndev);
+#endif
 	/* Enable interrupts we wish to service */
 	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
 }
@@ -599,6 +544,19 @@ fec_enet_tx(struct net_device *ndev)
 			ndev->stats.tx_packets++;
 		}
 
+#ifdef CONFIG_FEC_PTP
+		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
+			struct skb_shared_hwtstamps shhwtstamps;
+			unsigned long flags;
+
+			memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+			spin_lock_irqsave(&fep->tmreg_lock, flags);
+			shhwtstamps.hwtstamp = ns_to_ktime(
+				timecounter_cyc2time(&fep->tc, bdp->ts));
+			spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+			skb_tstamp_tx(skb, &shhwtstamps);
+		}
+#endif
 		if (status & BD_ENET_TX_READY)
 			printk("HEY! Enet xmit interrupt and TX_READY.\n");
 
@@ -725,6 +683,21 @@ fec_enet_rx(struct net_device *ndev)
 			skb_put(skb, pkt_len - 4);	/* Make room */
 			skb_copy_to_linear_data(skb, data, pkt_len - 4);
 			skb->protocol = eth_type_trans(skb, ndev);
+#ifdef CONFIG_FEC_PTP
+			/* Get receive timestamp from the skb */
+			if (fep->hwts_rx_en) {
+				struct skb_shared_hwtstamps *shhwtstamps =
+							    skb_hwtstamps(skb);
+				unsigned long flags;
+
+				memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+
+				spin_lock_irqsave(&fep->tmreg_lock, flags);
+				shhwtstamps->hwtstamp = ns_to_ktime(
+				    timecounter_cyc2time(&fep->tc, bdp->ts));
+				spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+			}
+#endif
 			if (!skb_defer_rx_timestamp(skb))
 				netif_rx(skb);
 		}
@@ -739,6 +712,12 @@ rx_processing_done:
 		status |= BD_ENET_RX_EMPTY;
 		bdp->cbd_sc = status;
 
+#ifdef CONFIG_FEC_PTP
+		bdp->cbd_esc = BD_ENET_RX_INT;
+		bdp->cbd_prot = 0;
+		bdp->cbd_bdu = 0;
+#endif
+
 		/* Update BD pointer to next entry */
 		if (status & BD_ENET_RX_WRAP)
 			bdp = fep->rx_bd_base;
@@ -1178,6 +1157,10 @@ static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
 	if (!phydev)
 		return -ENODEV;
 
+#ifdef CONFIG_FEC_PTP
+	if (cmd == SIOCSHWTSTAMP)
+		return fec_ptp_ioctl(ndev, rq, cmd);
+#endif
 	return phy_mii_ioctl(phydev, rq, cmd);
 }
 
@@ -1224,6 +1207,9 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
 		bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,
 				FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
 		bdp->cbd_sc = BD_ENET_RX_EMPTY;
+#ifdef CONFIG_FEC_PTP
+		bdp->cbd_esc = BD_ENET_RX_INT;
+#endif
 		bdp++;
 	}
 
@@ -1237,6 +1223,10 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
 
 		bdp->cbd_sc = 0;
 		bdp->cbd_bufaddr = 0;
+
+#ifdef CONFIG_FEC_PTP
+		bdp->cbd_esc = BD_ENET_RX_INT;
+#endif
 		bdp++;
 	}
 
@@ -1638,9 +1628,19 @@ fec_probe(struct platform_device *pdev)
 		goto failed_clk;
 	}
 
+#ifdef CONFIG_FEC_PTP
+	fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
+	if (IS_ERR(fep->clk_ptp)) {
+		ret = PTR_ERR(fep->clk_ptp);
+		goto failed_clk;
+	}
+#endif
+
 	clk_prepare_enable(fep->clk_ahb);
 	clk_prepare_enable(fep->clk_ipg);
-
+#ifdef CONFIG_FEC_PTP
+	clk_prepare_enable(fep->clk_ptp);
+#endif
 	reg_phy = devm_regulator_get(&pdev->dev, "phy");
 	if (!IS_ERR(reg_phy)) {
 		ret = regulator_enable(reg_phy);
@@ -1668,6 +1668,10 @@ fec_probe(struct platform_device *pdev)
 	if (ret)
 		goto failed_register;
 
+#ifdef CONFIG_FEC_PTP
+	fec_ptp_init(ndev, pdev);
+#endif
+
 	return 0;
 
 failed_register:
@@ -1677,6 +1681,9 @@ failed_init:
 failed_regulator:
 	clk_disable_unprepare(fep->clk_ahb);
 	clk_disable_unprepare(fep->clk_ipg);
+#ifdef CONFIG_FEC_PTP
+	clk_disable_unprepare(fep->clk_ptp);
+#endif
 failed_pin:
 failed_clk:
 	for (i = 0; i < FEC_IRQ_NUM; i++) {
@@ -1709,6 +1716,12 @@ fec_drv_remove(struct platform_device *pdev)
 		if (irq > 0)
 			free_irq(irq, ndev);
 	}
+#ifdef CONFIG_FEC_PTP
+	del_timer_sync(&fep->time_keep);
+	clk_disable_unprepare(fep->clk_ptp);
+	if (fep->ptp_clock)
+		ptp_clock_unregister(fep->ptp_clock);
+#endif
 	clk_disable_unprepare(fep->clk_ahb);
 	clk_disable_unprepare(fep->clk_ipg);
 	iounmap(fep->hwp);
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 8408c62..c5a3bc1 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -13,6 +13,12 @@
 #define	FEC_H
 /****************************************************************************/
 
+#ifdef CONFIG_FEC_PTP
+#include <linux/clocksource.h>
+#include <linux/net_tstamp.h>
+#include <linux/ptp_clock_kernel.h>
+#endif
+
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
     defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
     defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
@@ -88,6 +94,13 @@ struct bufdesc {
 	unsigned short cbd_datlen;	/* Data length */
 	unsigned short cbd_sc;	/* Control and status info */
 	unsigned long cbd_bufaddr;	/* Buffer address */
+#ifdef CONFIG_FEC_PTP
+	unsigned long cbd_esc;
+	unsigned long cbd_prot;
+	unsigned long cbd_bdu;
+	unsigned long ts;
+	unsigned short res0[4];
+#endif
 };
 #else
 struct bufdesc {
@@ -147,6 +160,112 @@ struct bufdesc {
 #define BD_ENET_TX_CSL          ((ushort)0x0001)
 #define BD_ENET_TX_STATS        ((ushort)0x03ff)        /* All status bits */
 
+/*enhanced buffer desciptor control/status used by Ethernet transmit*/
+#define BD_ENET_TX_INT          0x40000000
+#define BD_ENET_TX_TS           0x20000000
+
+
+/* This device has up to three irqs on some platforms */
+#define FEC_IRQ_NUM		3
+
+/* The number of Tx and Rx buffers.  These are allocated from the page
+ * pool.  The code may assume these are power of two, so it it best
+ * to keep them that size.
+ * We don't need to allocate pages for the transmitter.  We just use
+ * the skbuffer directly.
+ */
+
+#define FEC_ENET_RX_PAGES	8
+#define FEC_ENET_RX_FRSIZE	2048
+#define FEC_ENET_RX_FRPPG	(PAGE_SIZE / FEC_ENET_RX_FRSIZE)
+#define RX_RING_SIZE		(FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
+#define FEC_ENET_TX_FRSIZE	2048
+#define FEC_ENET_TX_FRPPG	(PAGE_SIZE / FEC_ENET_TX_FRSIZE)
+#define TX_RING_SIZE		16	/* Must be power of two */
+#define TX_RING_MOD_MASK	15	/*   for this to work */
+
+#define BD_ENET_RX_INT          0x00800000
+#define BD_ENET_RX_PTP          ((ushort)0x0400)
+
+/* The FEC buffer descriptors track the ring buffers.  The rx_bd_base and
+ * tx_bd_base always point to the base of the buffer descriptors.  The
+ * cur_rx and cur_tx point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller.  The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions.  The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct fec_enet_private {
+	/* Hardware registers of the FEC device */
+	void __iomem *hwp;
+
+	struct net_device *netdev;
+
+	struct clk *clk_ipg;
+	struct clk *clk_ahb;
+#ifdef CONFIG_FEC_PTP
+	struct clk *clk_ptp;
+#endif
+
+	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
+	unsigned char *tx_bounce[TX_RING_SIZE];
+	struct	sk_buff *tx_skbuff[TX_RING_SIZE];
+	struct	sk_buff *rx_skbuff[RX_RING_SIZE];
+	ushort	skb_cur;
+	ushort	skb_dirty;
+
+	/* CPM dual port RAM relative addresses */
+	dma_addr_t	bd_dma;
+	/* Address of Rx and Tx buffers */
+	struct bufdesc	*rx_bd_base;
+	struct bufdesc	*tx_bd_base;
+	/* The next free ring entry */
+	struct bufdesc	*cur_rx, *cur_tx;
+	/* The ring entries to be free()ed */
+	struct bufdesc	*dirty_tx;
+
+	uint	tx_full;
+	/* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
+	spinlock_t hw_lock;
+
+	struct	platform_device *pdev;
+
+	int	opened;
+	int	dev_id;
+
+	/* Phylib and MDIO interface */
+	struct	mii_bus *mii_bus;
+	struct	phy_device *phy_dev;
+	int	mii_timeout;
+	uint	phy_speed;
+	phy_interface_t	phy_interface;
+	int	link;
+	int	full_duplex;
+	struct	completion mdio_done;
+	int	irq[FEC_IRQ_NUM];
+
+#ifdef CONFIG_FEC_PTP
+	struct ptp_clock *ptp_clock;
+	struct ptp_clock_info ptp_caps;
+	unsigned long last_overflow_check;
+	spinlock_t tmreg_lock;
+	struct cyclecounter cc;
+	struct timecounter tc;
+	int rx_hwtstamp_filter;
+	u32 base_incval;
+	u32 cycle_speed;
+	int hwts_rx_en;
+	int hwts_tx_en;
+	struct timer_list time_keep;
+#endif
+
+};
+
+#ifdef CONFIG_FEC_PTP
+void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev);
+void fec_ptp_start_cyclecounter(struct net_device *ndev);
+int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd);
+#endif
 
 /****************************************************************************/
 #endif /* FEC_H */
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
new file mode 100644
index 0000000..c40526c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -0,0 +1,383 @@
+/*
+ * Fast Ethernet Controller (ENET) PTP driver for MX6x.
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/phy.h>
+#include <linux/fec.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_net.h>
+
+#include "fec.h"
+
+/* FEC 1588 register bits */
+#define FEC_T_CTRL_SLAVE                0x00002000
+#define FEC_T_CTRL_CAPTURE              0x00000800
+#define FEC_T_CTRL_RESTART              0x00000200
+#define FEC_T_CTRL_PERIOD_RST           0x00000030
+#define FEC_T_CTRL_PERIOD_EN		0x00000010
+#define FEC_T_CTRL_ENABLE               0x00000001
+
+#define FEC_T_INC_MASK                  0x0000007f
+#define FEC_T_INC_OFFSET                0
+#define FEC_T_INC_CORR_MASK             0x00007f00
+#define FEC_T_INC_CORR_OFFSET           8
+
+#define FEC_ATIME_CTRL		0x400
+#define FEC_ATIME		0x404
+#define FEC_ATIME_EVT_OFFSET	0x408
+#define FEC_ATIME_EVT_PERIOD	0x40c
+#define FEC_ATIME_CORR		0x410
+#define FEC_ATIME_INC		0x414
+#define FEC_TS_TIMESTAMP	0x418
+
+#define FEC_CC_MULT	(1 << 31)
+/**
+ * fec_ptp_read - read raw cycle counter (to be used by time counter)
+ * @cc: the cyclecounter structure
+ *
+ * this function reads the cyclecounter registers and is called by the
+ * cyclecounter structure used to construct a ns counter from the
+ * arbitrary fixed point registers
+ */
+static cycle_t fec_ptp_read(const struct cyclecounter *cc)
+{
+	struct fec_enet_private *fep =
+		container_of(cc, struct fec_enet_private, cc);
+	u32 tempval;
+
+	tempval = readl(fep->hwp + FEC_ATIME_CTRL);
+	tempval |= FEC_T_CTRL_CAPTURE;
+	writel(tempval, fep->hwp + FEC_ATIME_CTRL);
+
+	return readl(fep->hwp + FEC_ATIME);
+}
+
+/**
+ * fec_ptp_start_cyclecounter - create the cycle counter from hw
+ * @ndev: network device
+ *
+ * this function initializes the timecounter and cyclecounter
+ * structures for use in generated a ns counter from the arbitrary
+ * fixed point cycles registers in the hardware.
+ */
+void fec_ptp_start_cyclecounter(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	unsigned long flags;
+	int inc;
+
+	inc = 1000000000 / clk_get_rate(fep->clk_ptp);
+
+	/* grab the ptp lock */
+	spin_lock_irqsave(&fep->tmreg_lock, flags);
+
+	/* 1ns counter */
+	writel(inc << FEC_T_INC_OFFSET, fep->hwp + FEC_ATIME_INC);
+
+	/* use free running count */
+	writel(0, fep->hwp + FEC_ATIME_EVT_PERIOD);
+
+	writel(FEC_T_CTRL_ENABLE, fep->hwp + FEC_ATIME_CTRL);
+
+	memset(&fep->cc, 0, sizeof(fep->cc));
+	fep->cc.read = fec_ptp_read;
+	fep->cc.mask = CLOCKSOURCE_MASK(32);
+	fep->cc.shift = 31;
+	fep->cc.mult = FEC_CC_MULT;
+
+	/* reset the ns time counter */
+	timecounter_init(&fep->tc, &fep->cc, ktime_to_ns(ktime_get_real()));
+
+	spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+}
+
+/**
+ * fec_ptp_adjfreq - adjust ptp cycle frequency
+ * @ptp: the ptp clock structure
+ * @ppb: parts per billion adjustment from base
+ *
+ * Adjust the frequency of the ptp cycle counter by the
+ * indicated ppb from the base frequency.
+ *
+ * Because ENET hardware frequency adjust is complex,
+ * using software method to do that.
+ */
+static int fec_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+	u64 diff;
+	unsigned long flags;
+	int neg_adj = 0;
+	u32 mult = FEC_CC_MULT;
+
+	struct fec_enet_private *fep =
+	    container_of(ptp, struct fec_enet_private, ptp_caps);
+
+	if (ppb < 0) {
+		ppb = -ppb;
+		neg_adj = 1;
+	}
+
+	diff = mult;
+	diff *= ppb;
+	diff = div_u64(diff, 1000000000ULL);
+
+	spin_lock_irqsave(&fep->tmreg_lock, flags);
+	/*
+	 * dummy read to set cycle_last in tc to now.
+	 * So use adjusted mult to calculate when next call
+	 * timercounter_read.
+	 */
+	timecounter_read(&fep->tc);
+
+	fep->cc.mult = neg_adj ? mult - diff : mult + diff;
+
+	spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+
+	return 0;
+}
+
+/**
+ * fec_ptp_adjtime
+ * @ptp: the ptp clock structure
+ * @delta: offset to adjust the cycle counter by
+ *
+ * adjust the timer by resetting the timecounter structure.
+ */
+static int fec_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	struct fec_enet_private *fep =
+	    container_of(ptp, struct fec_enet_private, ptp_caps);
+	unsigned long flags;
+	u64 now;
+
+	spin_lock_irqsave(&fep->tmreg_lock, flags);
+
+	now = timecounter_read(&fep->tc);
+	now += delta;
+
+	/* reset the timecounter */
+	timecounter_init(&fep->tc, &fep->cc, now);
+
+	spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+
+	return 0;
+}
+
+/**
+ * fec_ptp_gettime
+ * @ptp: the ptp clock structure
+ * @ts: timespec structure to hold the current time value
+ *
+ * read the timecounter and return the correct value on ns,
+ * after converting it into a struct timespec.
+ */
+static int fec_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+	struct fec_enet_private *adapter =
+	    container_of(ptp, struct fec_enet_private, ptp_caps);
+	u64 ns;
+	u32 remainder;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->tmreg_lock, flags);
+	ns = timecounter_read(&adapter->tc);
+	spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+
+	ts->tv_sec = div_u64_rem(ns, 1000000000ULL, &remainder);
+	ts->tv_nsec = remainder;
+
+	return 0;
+}
+
+/**
+ * fec_ptp_settime
+ * @ptp: the ptp clock structure
+ * @ts: the timespec containing the new time for the cycle counter
+ *
+ * reset the timecounter to use a new base value instead of the kernel
+ * wall timer value.
+ */
+static int fec_ptp_settime(struct ptp_clock_info *ptp,
+			   const struct timespec *ts)
+{
+	struct fec_enet_private *fep =
+	    container_of(ptp, struct fec_enet_private, ptp_caps);
+
+	u64 ns;
+	unsigned long flags;
+
+	ns = ts->tv_sec * 1000000000ULL;
+	ns += ts->tv_nsec;
+
+	spin_lock_irqsave(&fep->tmreg_lock, flags);
+	timecounter_init(&fep->tc, &fep->cc, ns);
+	spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+	return 0;
+}
+
+/**
+ * fec_ptp_enable
+ * @ptp: the ptp clock structure
+ * @rq: the requested feature to change
+ * @on: whether to enable or disable the feature
+ *
+ */
+static int fec_ptp_enable(struct ptp_clock_info *ptp,
+			  struct ptp_clock_request *rq, int on)
+{
+	return -EOPNOTSUPP;
+}
+
+/**
+ * fec_ptp_hwtstamp_ioctl - control hardware time stamping
+ * @ndev: pointer to net_device
+ * @ifreq: ioctl data
+ * @cmd: particular ioctl requested
+ */
+int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+
+	struct hwtstamp_config config;
+
+	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+		return -EFAULT;
+
+	/* reserved for future extensions */
+	if (config.flags)
+		return -EINVAL;
+
+	switch (config.tx_type) {
+	case HWTSTAMP_TX_OFF:
+		fep->hwts_tx_en = 0;
+		break;
+	case HWTSTAMP_TX_ON:
+		fep->hwts_tx_en = 1;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	switch (config.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		if (fep->hwts_rx_en)
+			fep->hwts_rx_en = 0;
+		config.rx_filter = HWTSTAMP_FILTER_NONE;
+		break;
+
+	default:
+		/*
+		 * register RXMTRL must be set in order to do V1 packets,
+		 * therefore it is not possible to time stamp both V1 Sync and
+		 * Delay_Req messages and hardware does not support
+		 * timestamping all packets => return error
+		 */
+		fep->hwts_rx_en = 1;
+		config.rx_filter = HWTSTAMP_FILTER_ALL;
+		break;
+	}
+
+	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
+	    -EFAULT : 0;
+}
+
+/**
+ * fec_time_keep - call timecounter_read every second to avoid timer overrun
+ *                 because ENET just support 32bit counter, will timeout in 4s
+ */
+static void fec_time_keep(unsigned long _data)
+{
+	struct fec_enet_private *fep = (struct fec_enet_private *)_data;
+	u64 ns;
+	unsigned long flags;
+
+	spin_lock_irqsave(&fep->tmreg_lock, flags);
+	ns = timecounter_read(&fep->tc);
+	spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+
+	mod_timer(&fep->time_keep, jiffies + HZ);
+}
+
+/**
+ * fec_ptp_init
+ * @ndev: The FEC network adapter
+ *
+ * This function performs the required steps for enabling ptp
+ * support. If ptp support has already been loaded it simply calls the
+ * cyclecounter init routine and exits.
+ */
+
+void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+
+	fep->ptp_caps.owner = THIS_MODULE;
+	snprintf(fep->ptp_caps.name, 16, "fec ptp");
+
+	fep->ptp_caps.max_adj = 250000000;
+	fep->ptp_caps.n_alarm = 0;
+	fep->ptp_caps.n_ext_ts = 0;
+	fep->ptp_caps.n_per_out = 0;
+	fep->ptp_caps.pps = 0;
+	fep->ptp_caps.adjfreq = fec_ptp_adjfreq;
+	fep->ptp_caps.adjtime = fec_ptp_adjtime;
+	fep->ptp_caps.gettime = fec_ptp_gettime;
+	fep->ptp_caps.settime = fec_ptp_settime;
+	fep->ptp_caps.enable = fec_ptp_enable;
+
+	spin_lock_init(&fep->tmreg_lock);
+
+	fec_ptp_start_cyclecounter(ndev);
+
+	init_timer(&fep->time_keep);
+	fep->time_keep.data = (unsigned long)fep;
+	fep->time_keep.function = fec_time_keep;
+	fep->time_keep.expires = jiffies + HZ;
+	add_timer(&fep->time_keep);
+
+	fep->ptp_clock = ptp_clock_register(&fep->ptp_caps, &pdev->dev);
+	if (IS_ERR(fep->ptp_clock)) {
+		fep->ptp_clock = NULL;
+		pr_err("ptp_clock_register failed\n");
+	} else {
+		pr_info("registered PHC device on %s\n", ndev->name);
+	}
+}
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 19ac096..bffb2ed 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -210,7 +210,7 @@ static int gfar_init_bds(struct net_device *ndev)
 				skb = gfar_new_skb(ndev);
 				if (!skb) {
 					netdev_err(ndev, "Can't allocate RX buffers\n");
-					goto err_rxalloc_fail;
+					return -ENOMEM;
 				}
 				rx_queue->rx_skbuff[j] = skb;
 
@@ -223,10 +223,6 @@ static int gfar_init_bds(struct net_device *ndev)
 	}
 
 	return 0;
-
-err_rxalloc_fail:
-	free_skb_resources(priv);
-	return -ENOMEM;
 }
 
 static int gfar_alloc_skb_resources(struct net_device *ndev)
@@ -1359,7 +1355,11 @@ static int gfar_restore(struct device *dev)
 		return 0;
 	}
 
-	gfar_init_bds(ndev);
+	if (gfar_init_bds(ndev)) {
+		free_skb_resources(priv);
+		return -ENOMEM;
+	}
+
 	init_registers(ndev);
 	gfar_set_mac_address(ndev);
 	gfar_init_mac(ndev);
@@ -1712,6 +1712,7 @@ static void free_skb_tx_queue(struct gfar_priv_tx_q *tx_queue)
 		tx_queue->tx_skbuff[i] = NULL;
 	}
 	kfree(tx_queue->tx_skbuff);
+	tx_queue->tx_skbuff = NULL;
 }
 
 static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue)
@@ -1735,6 +1736,7 @@ static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue)
 		rxbdp++;
 	}
 	kfree(rx_queue->rx_skbuff);
+	rx_queue->rx_skbuff = NULL;
 }
 
 /* If there are any tx skbs or rx skbs still around, free them.
diff --git a/drivers/net/ethernet/i825xx/Kconfig b/drivers/net/ethernet/i825xx/Kconfig
index 959faf7..dedfa3a 100644
--- a/drivers/net/ethernet/i825xx/Kconfig
+++ b/drivers/net/ethernet/i825xx/Kconfig
@@ -5,9 +5,7 @@
 config NET_VENDOR_I825XX
 	bool "Intel (82586/82593/82596) devices"
 	default y
-	depends on NET_VENDOR_INTEL && (ISA || ISA_DMA_API || ARM || \
-		   ARCH_ACORN || MCA || MCA_LEGACY || SNI_RM || SUN3 || \
-		   GSC || BVME6000 || MVME16x || EXPERIMENTAL)
+	depends on NET_VENDOR_INTEL
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y
 	  and read the Ethernet-HOWTO, available from
@@ -33,8 +31,8 @@ config ELPLUS
 	  will be called 3c505.
 
 config EL16
-	tristate "3c507 \"EtherLink 16\" support (EXPERIMENTAL)"
-	depends on ISA && EXPERIMENTAL
+	tristate "3c507 \"EtherLink 16\" support"
+	depends on ISA
 	---help---
 	  If you have a network (Ethernet) card of this type, say Y and read
 	  the Ethernet-HOWTO, available from
@@ -149,8 +147,8 @@ config SUN3_82586
 	  VME boards.
 
 config ZNET
-	tristate "Zenith Z-Note support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && ISA_DMA_API && X86
+	tristate "Zenith Z-Note support"
+	depends on ISA_DMA_API && X86
 	---help---
 	  The Zenith Z-Note notebook computer has a built-in network
 	  (Ethernet) card, and this is the Linux driver for it. Note that the
diff --git a/drivers/net/ethernet/i825xx/ether1.c b/drivers/net/ethernet/i825xx/ether1.c
index 067db3f..7b9609d 100644
--- a/drivers/net/ethernet/i825xx/ether1.c
+++ b/drivers/net/ethernet/i825xx/ether1.c
@@ -638,12 +638,6 @@ ether1_txalloc (struct net_device *dev, int size)
 static int
 ether1_open (struct net_device *dev)
 {
-	if (!is_valid_ether_addr(dev->dev_addr)) {
-		printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
-			dev->name);
-		return -EINVAL;
-	}
-
 	if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev))
 		return -EAGAIN;
 
diff --git a/drivers/net/ethernet/ibm/Kconfig b/drivers/net/ethernet/ibm/Kconfig
index b9773d2..6529d31 100644
--- a/drivers/net/ethernet/ibm/Kconfig
+++ b/drivers/net/ethernet/ibm/Kconfig
@@ -6,7 +6,7 @@ config NET_VENDOR_IBM
 	bool "IBM devices"
 	default y
 	depends on MCA || PPC_PSERIES || PPC_PSERIES || PPC_DCR || \
-		   (IBMEBUS && INET && SPARSEMEM)
+		   (IBMEBUS && SPARSEMEM)
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y
 	  and read the Ethernet-HOWTO, available from
@@ -33,8 +33,7 @@ source "drivers/net/ethernet/ibm/emac/Kconfig"
 
 config EHEA
 	tristate "eHEA Ethernet support"
-	depends on IBMEBUS && INET && SPARSEMEM
-	select INET_LRO
+	depends on IBMEBUS && SPARSEMEM
 	---help---
 	  This driver supports the IBM pSeries eHEA ethernet adapter.
 
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c
index f4d2da0..09faf33 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -3028,7 +3028,7 @@ static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
 	ehea_set_ethtool_ops(dev);
 
 	dev->hw_features = NETIF_F_SG | NETIF_F_TSO
-		      | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_LRO;
+		      | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX;
 	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
 		      | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX
 		      | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_phyp.h b/drivers/net/ethernet/ibm/ehea/ehea_phyp.h
index 8364815..99b6c2a 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_phyp.h
+++ b/drivers/net/ethernet/ibm/ehea/ehea_phyp.h
@@ -39,26 +39,6 @@
  * hcp_*  - structures, variables and functions releated to Hypervisor Calls
  */
 
-static inline u32 get_longbusy_msecs(int long_busy_ret_code)
-{
-	switch (long_busy_ret_code) {
-	case H_LONG_BUSY_ORDER_1_MSEC:
-		return 1;
-	case H_LONG_BUSY_ORDER_10_MSEC:
-		return 10;
-	case H_LONG_BUSY_ORDER_100_MSEC:
-		return 100;
-	case H_LONG_BUSY_ORDER_1_SEC:
-		return 1000;
-	case H_LONG_BUSY_ORDER_10_SEC:
-		return 10000;
-	case H_LONG_BUSY_ORDER_100_SEC:
-		return 100000;
-	default:
-		return 1;
-	}
-}
-
 /* Number of pages which can be registered at once by H_REGISTER_HEA_RPAGES */
 #define EHEA_MAX_RPAGE 512
 
diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c
index 479e43e..84c6b6c 100644
--- a/drivers/net/ethernet/ibm/emac/mal.c
+++ b/drivers/net/ethernet/ibm/emac/mal.c
@@ -738,13 +738,11 @@ static int __devexit mal_remove(struct platform_device *ofdev)
 	/* Synchronize with scheduled polling */
 	napi_disable(&mal->napi);
 
-	if (!list_empty(&mal->list)) {
+	if (!list_empty(&mal->list))
 		/* This is *very* bad */
-		printk(KERN_EMERG
+		WARN(1, KERN_EMERG
 		       "mal%d: commac list is not empty on remove!\n",
 		       mal->index);
-		WARN_ON(1);
-	}
 
 	dev_set_drvdata(&ofdev->dev, NULL);
 
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 0cafe4f..6c78633 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -5,11 +5,6 @@
 config NET_VENDOR_INTEL
 	bool "Intel devices"
 	default y
-	depends on PCI || PCI_MSI || ISA || ISA_DMA_API || ARM || \
-		   ARCH_ACORN || MCA || MCA_LEGACY || SNI_RM || SUN3 || \
-		   GSC || BVME6000 || MVME16x || \
-		   (ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR) || \
-		   EXPERIMENTAL
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y
 	  and read the Ethernet-HOWTO, available from
@@ -93,6 +88,7 @@ config E1000E
 config IGB
 	tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
 	depends on PCI
+	select PTP_1588_CLOCK
 	---help---
 	  This driver supports Intel(R) 82575/82576 gigabit ethernet family of
 	  adapters.  For more information on how to identify your adapter, go
@@ -120,19 +116,6 @@ config IGB_DCA
 	  driver.  DCA is a method for warming the CPU cache before data
 	  is used, with the intent of lessening the impact of cache misses.
 
-config IGB_PTP
-	bool "PTP Hardware Clock (PHC)"
-	default n
-	depends on IGB && EXPERIMENTAL
-	select PPS
-	select PTP_1588_CLOCK
-	---help---
-	  Say Y here if you want to use PTP Hardware Clock (PHC) in the
-	  driver.  Only the basic clock operations have been implemented.
-
-	  Every timestamp and clock read operations must consult the
-	  overflow counter to form a correct time value.
-
 config IGBVF
 	tristate "Intel(R) 82576 Virtual Function Ethernet support"
 	depends on PCI
@@ -178,8 +161,9 @@ config IXGB
 
 config IXGBE
 	tristate "Intel(R) 10GbE PCI Express adapters support"
-	depends on PCI && INET
+	depends on PCI
 	select MDIO
+	select PTP_1588_CLOCK
 	---help---
 	  This driver supports Intel(R) 10GbE PCI Express family of
 	  adapters.  For more information on how to identify your adapter, go
@@ -222,19 +206,6 @@ config IXGBE_DCB
 
 	  If unsure, say N.
 
-config IXGBE_PTP
-	bool "PTP Clock Support"
-	default n
-	depends on IXGBE && EXPERIMENTAL
-	select PPS
-	select PTP_1588_CLOCK
-	---help---
-	  Say Y here if you want support for 1588 Timestamping with a
-	  PHC device, using the PTP 1588 Clock support. This is
-	  required to enable timestamping support for the device.
-
-	  If unsure, say N.
-
 config IXGBEVF
 	tristate "Intel(R) 82599 Virtual Function Ethernet support"
 	depends on PCI_MSI
diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
index 9089d00..14e3051 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
@@ -1671,7 +1671,7 @@ static void e1000_get_wol(struct net_device *netdev,
 	/* apply any specific unsupported masks here */
 	switch (hw->device_id) {
 	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
-		/* KSP3 does not suppport UCAST wake-ups */
+		/* KSP3 does not support UCAST wake-ups */
 		wol->supported &= ~WAKE_UCAST;
 
 		if (adapter->wol & E1000_WUFC_EX)
diff --git a/drivers/net/ethernet/intel/e1000/e1000_hw.c b/drivers/net/ethernet/intel/e1000/e1000_hw.c
index 3d68395..8fedd24 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_hw.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_hw.c
@@ -107,6 +107,7 @@ u16 e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = {
 };
 
 static DEFINE_SPINLOCK(e1000_eeprom_lock);
+static DEFINE_SPINLOCK(e1000_phy_lock);
 
 /**
  * e1000_set_phy_type - Set the phy type member in the hw struct.
@@ -2830,19 +2831,25 @@ static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw)
 s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data)
 {
 	u32 ret_val;
+	unsigned long flags;
 
 	e_dbg("e1000_read_phy_reg");
 
+	spin_lock_irqsave(&e1000_phy_lock, flags);
+
 	if ((hw->phy_type == e1000_phy_igp) &&
 	    (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
 		ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
 						 (u16) reg_addr);
-		if (ret_val)
+		if (ret_val) {
+			spin_unlock_irqrestore(&e1000_phy_lock, flags);
 			return ret_val;
+		}
 	}
 
 	ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
 					phy_data);
+	spin_unlock_irqrestore(&e1000_phy_lock, flags);
 
 	return ret_val;
 }
@@ -2965,19 +2972,25 @@ static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
 s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data)
 {
 	u32 ret_val;
+	unsigned long flags;
 
 	e_dbg("e1000_write_phy_reg");
 
+	spin_lock_irqsave(&e1000_phy_lock, flags);
+
 	if ((hw->phy_type == e1000_phy_igp) &&
 	    (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
 		ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
 						 (u16) reg_addr);
-		if (ret_val)
+		if (ret_val) {
+			spin_unlock_irqrestore(&e1000_phy_lock, flags);
 			return ret_val;
+		}
 	}
 
 	ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
 					 phy_data);
+	spin_unlock_irqrestore(&e1000_phy_lock, flags);
 
 	return ret_val;
 }
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index f444eb0..dadb13b 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -5067,6 +5067,17 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
 		return NETDEV_TX_OK;
 	}
 
+	/*
+	 * The minimum packet size with TCTL.PSP set is 17 bytes so
+	 * pad skb in order to meet this minimum size requirement
+	 */
+	if (unlikely(skb->len < 17)) {
+		if (skb_pad(skb, 17 - skb->len))
+			return NETDEV_TX_OK;
+		skb->len = 17;
+		skb_set_tail_pointer(skb, 17);
+	}
+
 	mss = skb_shinfo(skb)->gso_size;
 	if (mss) {
 		u8 hdr_len;
diff --git a/drivers/net/ethernet/intel/igb/Makefile b/drivers/net/ethernet/intel/igb/Makefile
index 97c197f..624476c 100644
--- a/drivers/net/ethernet/intel/igb/Makefile
+++ b/drivers/net/ethernet/intel/igb/Makefile
@@ -34,6 +34,4 @@ obj-$(CONFIG_IGB) += igb.o
 
 igb-objs := igb_main.o igb_ethtool.o e1000_82575.o \
 	    e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o \
-	    e1000_i210.o
-
-igb-$(CONFIG_IGB_PTP) += igb_ptp.o
+	    e1000_i210.o igb_ptp.o
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index ca4641e..8c12dbd 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -319,6 +319,7 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
 		nvm->ops.acquire = igb_acquire_nvm_i210;
 		nvm->ops.release = igb_release_nvm_i210;
 		nvm->ops.read    = igb_read_nvm_srrd_i210;
+		nvm->ops.write   = igb_write_nvm_srwr_i210;
 		nvm->ops.valid_led_default = igb_valid_led_default_i210;
 		break;
 	case e1000_i211:
@@ -1277,12 +1278,20 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
 {
 	u32 ctrl;
 	s32  ret_val;
+	u32 phpm_reg;
 
 	ctrl = rd32(E1000_CTRL);
 	ctrl |= E1000_CTRL_SLU;
 	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
 	wr32(E1000_CTRL, ctrl);
 
+	/* Clear Go Link Disconnect bit */
+	if (hw->mac.type >= e1000_82580) {
+		phpm_reg = rd32(E1000_82580_PHY_POWER_MGMT);
+		phpm_reg &= ~E1000_82580_PM_GO_LINKD;
+		wr32(E1000_82580_PHY_POWER_MGMT, phpm_reg);
+	}
+
 	ret_val = igb_setup_serdes_link_82575(hw);
 	if (ret_val)
 		goto out;
@@ -2233,19 +2242,16 @@ s32 igb_set_eee_i350(struct e1000_hw *hw)
 
 	/* enable or disable per user setting */
 	if (!(hw->dev_spec._82575.eee_disable)) {
-		ipcnfg |= (E1000_IPCNFG_EEE_1G_AN |
-			E1000_IPCNFG_EEE_100M_AN);
-		eeer |= (E1000_EEER_TX_LPI_EN |
-			E1000_EEER_RX_LPI_EN |
+		u32 eee_su = rd32(E1000_EEE_SU);
+
+		ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN);
+		eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
 			E1000_EEER_LPI_FC);
 
-		/* keep the LPI clock running before EEE is enabled */
-		if (hw->mac.type == e1000_i210 || hw->mac.type == e1000_i211) {
-			u32 eee_su;
-			eee_su = rd32(E1000_EEE_SU);
-			eee_su &= ~E1000_EEE_SU_LPI_CLK_STP;
-			wr32(E1000_EEE_SU, eee_su);
-		}
+		/* This bit should not be set in normal operation. */
+		if (eee_su & E1000_EEE_SU_LPI_CLK_STP)
+			hw_dbg("LPI Clock Stop Bit should not be set!\n");
+
 
 	} else {
 		ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN |
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.h b/drivers/net/ethernet/intel/igb/e1000_82575.h
index e85c453..44b76b3 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.h
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.h
@@ -172,10 +172,13 @@ struct e1000_adv_tx_context_desc {
 #define E1000_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */
 #define E1000_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header enable */
 #define E1000_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload enable */
+#define E1000_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* DCA Rx rd Desc Relax Order */
 
 #define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
 #define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */
+#define E1000_DCA_TXCTRL_DESC_RRO_EN (1 << 9) /* Tx rd Desc Relax Order */
 #define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */
+#define E1000_DCA_TXCTRL_DATA_RRO_EN (1 << 13) /* Tx rd data Relax Order */
 
 /* Additional DCA related definitions, note change in position of CPUID */
 #define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
index de4b41e..198d148 100644
--- a/drivers/net/ethernet/intel/igb/e1000_defines.h
+++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
@@ -636,6 +636,7 @@
 /* NVM Word Offsets */
 #define NVM_COMPAT                 0x0003
 #define NVM_ID_LED_SETTINGS        0x0004 /* SERDES output amplitude */
+#define NVM_VERSION                0x0005
 #define NVM_INIT_CONTROL2_REG      0x000F
 #define NVM_INIT_CONTROL3_PORT_B   0x0014
 #define NVM_INIT_CONTROL3_PORT_A   0x0024
@@ -653,6 +654,19 @@
 #define NVM_LED_1_CFG              0x001C
 #define NVM_LED_0_2_CFG            0x001F
 
+/* NVM version defines */
+#define NVM_ETRACK_WORD            0x0042
+#define NVM_COMB_VER_OFF           0x0083
+#define NVM_COMB_VER_PTR           0x003d
+#define NVM_MAJOR_MASK             0xF000
+#define NVM_MINOR_MASK             0x0FF0
+#define NVM_BUILD_MASK             0x000F
+#define NVM_COMB_VER_MASK          0x00FF
+#define NVM_MAJOR_SHIFT                12
+#define NVM_MINOR_SHIFT                 4
+#define NVM_COMB_VER_SHFT               8
+#define NVM_VER_INVALID            0xFFFF
+#define NVM_ETRACK_SHIFT               16
 
 #define E1000_NVM_CFG_DONE_PORT_0  0x040000 /* MNG config cycle done */
 #define E1000_NVM_CFG_DONE_PORT_1  0x080000 /* ...for second port */
@@ -860,6 +874,7 @@
 #define E1000_EEER_FRC_AN            0x10000000  /* Enable EEE in loopback */
 #define E1000_EEER_LPI_FC            0x00040000  /* EEE Enable on FC */
 #define E1000_EEE_SU_LPI_CLK_STP     0X00800000  /* EEE LPI Clock Stop */
+#define E1000_EEER_EEE_NEG           0x20000000  /* EEE capability nego */
 
 /* SerDes Control */
 #define E1000_GEN_CTL_READY             0x80000000
diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.c b/drivers/net/ethernet/intel/igb/e1000_i210.c
index 77a5f93..4147429 100644
--- a/drivers/net/ethernet/intel/igb/e1000_i210.c
+++ b/drivers/net/ethernet/intel/igb/e1000_i210.c
@@ -423,6 +423,100 @@ s32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data)
 }
 
 /**
+ *  igb_read_invm_version - Reads iNVM version and image type
+ *  @hw: pointer to the HW structure
+ *  @invm_ver: version structure for the version read
+ *
+ *  Reads iNVM version and image type.
+ **/
+s32 igb_read_invm_version(struct e1000_hw *hw,
+			  struct e1000_fw_version *invm_ver) {
+	u32 *record = NULL;
+	u32 *next_record = NULL;
+	u32 i = 0;
+	u32 invm_dword = 0;
+	u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE /
+					     E1000_INVM_RECORD_SIZE_IN_BYTES);
+	u32 buffer[E1000_INVM_SIZE];
+	s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
+	u16 version = 0;
+
+	/* Read iNVM memory */
+	for (i = 0; i < E1000_INVM_SIZE; i++) {
+		invm_dword = rd32(E1000_INVM_DATA_REG(i));
+		buffer[i] = invm_dword;
+	}
+
+	/* Read version number */
+	for (i = 1; i < invm_blocks; i++) {
+		record = &buffer[invm_blocks - i];
+		next_record = &buffer[invm_blocks - i + 1];
+
+		/* Check if we have first version location used */
+		if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) {
+			version = 0;
+			status = E1000_SUCCESS;
+			break;
+		}
+		/* Check if we have second version location used */
+		else if ((i == 1) &&
+			 ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) {
+			version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
+			status = E1000_SUCCESS;
+			break;
+		}
+		/* Check if we have odd version location
+		 * used and it is the last one used
+		 */
+		else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) &&
+			 ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) &&
+			 (i != 1))) {
+			version = (*next_record & E1000_INVM_VER_FIELD_TWO)
+				  >> 13;
+			status = E1000_SUCCESS;
+			break;
+		}
+		/* Check if we have even version location
+		 * used and it is the last one used
+		 */
+		else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) &&
+			 ((*record & 0x3) == 0)) {
+			version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
+			status = E1000_SUCCESS;
+			break;
+		}
+	}
+
+	if (status == E1000_SUCCESS) {
+		invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK)
+					>> E1000_INVM_MAJOR_SHIFT;
+		invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK;
+	}
+	/* Read Image Type */
+	for (i = 1; i < invm_blocks; i++) {
+		record = &buffer[invm_blocks - i];
+		next_record = &buffer[invm_blocks - i + 1];
+
+		/* Check if we have image type in first location used */
+		if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) {
+			invm_ver->invm_img_type = 0;
+			status = E1000_SUCCESS;
+			break;
+		}
+		/* Check if we have image type in first location used */
+		else if ((((*record & 0x3) == 0) &&
+			 ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) ||
+			 ((((*record & 0x3) != 0) && (i != 1)))) {
+			invm_ver->invm_img_type =
+				(*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23;
+			status = E1000_SUCCESS;
+			break;
+		}
+	}
+	return status;
+}
+
+/**
  *  igb_validate_nvm_checksum_i210 - Validate EEPROM checksum
  *  @hw: pointer to the HW structure
  *
diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.h b/drivers/net/ethernet/intel/igb/e1000_i210.h
index 5dc2bd3..974d235 100644
--- a/drivers/net/ethernet/intel/igb/e1000_i210.h
+++ b/drivers/net/ethernet/intel/igb/e1000_i210.h
@@ -43,6 +43,8 @@ extern void igb_release_nvm_i210(struct e1000_hw *hw);
 extern s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
 extern s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
 			       u16 *data);
+extern s32 igb_read_invm_version(struct e1000_hw *hw,
+				 struct e1000_fw_version *invm_ver);
 
 #define E1000_STM_OPCODE		0xDB00
 #define E1000_EEPROM_FLASH_SIZE_WORD	0x11
@@ -65,6 +67,15 @@ enum E1000_INVM_STRUCTURE_TYPE {
 
 #define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS	8
 #define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS	1
+#define E1000_INVM_ULT_BYTES_SIZE			8
+#define E1000_INVM_RECORD_SIZE_IN_BYTES			4
+#define E1000_INVM_VER_FIELD_ONE			0x1FF8
+#define E1000_INVM_VER_FIELD_TWO			0x7FE000
+#define E1000_INVM_IMGTYPE_FIELD			0x1F800000
+
+#define E1000_INVM_MAJOR_MASK		0x3F0
+#define E1000_INVM_MINOR_MASK		0xF
+#define E1000_INVM_MAJOR_SHIFT		4
 
 #define ID_LED_DEFAULT_I210		((ID_LED_OFF1_ON2  << 8) | \
 					 (ID_LED_OFF1_OFF2 <<  4) | \
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c
index 819c145..7acddfe 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mac.c
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.c
@@ -1391,6 +1391,10 @@ s32 igb_validate_mdi_setting(struct e1000_hw *hw)
 {
 	s32 ret_val = 0;
 
+	/* All MDI settings are supported on 82580 and newer. */
+	if (hw->mac.type >= e1000_82580)
+		goto out;
+
 	if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) {
 		hw_dbg("Invalid MDI setting detected\n");
 		hw->phy.mdix = 1;
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.h b/drivers/net/ethernet/intel/igb/e1000_mac.h
index cbddc4e..e2b2c4b 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mac.h
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.h
@@ -33,6 +33,7 @@
 #include "e1000_phy.h"
 #include "e1000_nvm.h"
 #include "e1000_defines.h"
+#include "e1000_i210.h"
 
 /*
  * Functions that should not be called directly from drivers but can be used
diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.c b/drivers/net/ethernet/intel/igb/e1000_nvm.c
index aa5fcdf..7db3f80 100644
--- a/drivers/net/ethernet/intel/igb/e1000_nvm.c
+++ b/drivers/net/ethernet/intel/igb/e1000_nvm.c
@@ -710,3 +710,74 @@ s32 igb_update_nvm_checksum(struct e1000_hw *hw)
 out:
 	return ret_val;
 }
+
+/**
+ *  igb_get_fw_version - Get firmware version information
+ *  @hw: pointer to the HW structure
+ *  @fw_vers: pointer to output structure
+ *
+ *  unsupported MAC types will return all 0 version structure
+ **/
+void igb_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers)
+{
+	u16 eeprom_verh, eeprom_verl, comb_verh, comb_verl, comb_offset;
+	u16 fw_version;
+
+	memset(fw_vers, 0, sizeof(struct e1000_fw_version));
+
+	switch (hw->mac.type) {
+	case e1000_i211:
+		igb_read_invm_version(hw, fw_vers);
+		return;
+	case e1000_82575:
+	case e1000_82576:
+	case e1000_82580:
+	case e1000_i350:
+	case e1000_i210:
+		break;
+	default:
+		return;
+	}
+	/* basic eeprom version numbers */
+	hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version);
+	fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK) >> NVM_MAJOR_SHIFT;
+	fw_vers->eep_minor = (fw_version & NVM_MINOR_MASK);
+
+	/* etrack id */
+	hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verl);
+	hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh);
+	fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT) | eeprom_verl;
+
+	switch (hw->mac.type) {
+	case e1000_i210:
+	case e1000_i350:
+		/* find combo image version */
+		hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset);
+		if ((comb_offset != 0x0) && (comb_offset != NVM_VER_INVALID)) {
+
+			hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset
+					 + 1), 1, &comb_verh);
+			hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset),
+					 1, &comb_verl);
+
+			/* get Option Rom version if it exists and is valid */
+			if ((comb_verh && comb_verl) &&
+			    ((comb_verh != NVM_VER_INVALID) &&
+			     (comb_verl != NVM_VER_INVALID))) {
+
+				fw_vers->or_valid = true;
+				fw_vers->or_major =
+					comb_verl >> NVM_COMB_VER_SHFT;
+				fw_vers->or_build =
+					((comb_verl << NVM_COMB_VER_SHFT)
+					| (comb_verh >> NVM_COMB_VER_SHFT));
+				fw_vers->or_patch =
+					comb_verh & NVM_COMB_VER_MASK;
+			}
+		}
+		break;
+	default:
+		break;
+	}
+	return;
+}
diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.h b/drivers/net/ethernet/intel/igb/e1000_nvm.h
index 825b022..7012d45 100644
--- a/drivers/net/ethernet/intel/igb/e1000_nvm.h
+++ b/drivers/net/ethernet/intel/igb/e1000_nvm.h
@@ -40,4 +40,20 @@ s32  igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
 s32  igb_validate_nvm_checksum(struct e1000_hw *hw);
 s32  igb_update_nvm_checksum(struct e1000_hw *hw);
 
+struct e1000_fw_version {
+	u32 etrack_id;
+	u16 eep_major;
+	u16 eep_minor;
+
+	u8 invm_major;
+	u8 invm_minor;
+	u8 invm_img_type;
+
+	bool or_valid;
+	u16 or_major;
+	u16 or_build;
+	u16 or_patch;
+};
+void igb_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers);
+
 #endif
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c
index 3404bc7..fe76004 100644
--- a/drivers/net/ethernet/intel/igb/e1000_phy.c
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.c
@@ -1207,20 +1207,25 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw)
 	u16 phy_data;
 	bool link;
 
-	/*
-	 * Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
-	 * forced whenever speed and duplex are forced.
-	 */
-	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-	if (ret_val)
-		goto out;
+	/* I210 and I211 devices support Auto-Crossover in forced operation. */
+	if (phy->type != e1000_phy_i210) {
+		/*
+		 * Clear Auto-Crossover to force MDI manually.  M88E1000
+		 * requires MDI forced whenever speed and duplex are forced.
+		 */
+		ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL,
+					    &phy_data);
+		if (ret_val)
+			goto out;
 
-	phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
-	ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
-	if (ret_val)
-		goto out;
+		phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+		ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
+					     phy_data);
+		if (ret_val)
+			goto out;
 
-	hw_dbg("M88E1000 PSCR: %X\n", phy_data);
+		hw_dbg("M88E1000 PSCR: %X\n", phy_data);
+	}
 
 	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
 	if (ret_val)
@@ -1710,6 +1715,26 @@ s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw)
 
 	switch (hw->phy.id) {
 	case I210_I_PHY_ID:
+		/* Get cable length from PHY Cable Diagnostics Control Reg */
+		ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
+					    (I347AT4_PCDL + phy->addr),
+					    &phy_data);
+		if (ret_val)
+			return ret_val;
+
+		/* Check if the unit of cable length is meters or cm */
+		ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
+					    I347AT4_PCDC, &phy_data2);
+		if (ret_val)
+			return ret_val;
+
+		is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
+
+		/* Populate the phy structure with cable length in meters */
+		phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
+		phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
+		phy->cable_length = phy_data / (is_cm ? 100 : 1);
+		break;
 	case I347AT4_E_PHY_ID:
 		/* Remember the original page select and set it to 7 */
 		ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.h b/drivers/net/ethernet/intel/igb/e1000_phy.h
index 6ac3299..ed282f8 100644
--- a/drivers/net/ethernet/intel/igb/e1000_phy.h
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.h
@@ -124,6 +124,7 @@ s32  igb_check_polarity_m88(struct e1000_hw *hw);
 #define E1000_82580_PM_SPD		0x0001 /* Smart Power Down */
 #define E1000_82580_PM_D0_LPLU		0x0002 /* For D0a states */
 #define E1000_82580_PM_D3_LPLU		0x0004 /* For all other states */
+#define E1000_82580_PM_GO_LINKD		0x0020 /* Go Link Disconnect */
 
 /* Enable flexible speed on link-up */
 #define IGP02E1000_PM_D0_LPLU             0x0002 /* For D0a states */
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 8aad230..c15a481 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -34,11 +34,9 @@
 #include "e1000_mac.h"
 #include "e1000_82575.h"
 
-#ifdef CONFIG_IGB_PTP
 #include <linux/clocksource.h>
 #include <linux/net_tstamp.h>
 #include <linux/ptp_clock_kernel.h>
-#endif /* CONFIG_IGB_PTP */
 #include <linux/bitops.h>
 #include <linux/if_vlan.h>
 
@@ -132,9 +130,10 @@ struct vf_data_storage {
 #define MAXIMUM_ETHERNET_VLAN_SIZE 1522
 
 /* Supported Rx Buffer Sizes */
-#define IGB_RXBUFFER_256   256
-#define IGB_RXBUFFER_16384 16384
-#define IGB_RX_HDR_LEN     IGB_RXBUFFER_256
+#define IGB_RXBUFFER_256	256
+#define IGB_RXBUFFER_2048	2048
+#define IGB_RX_HDR_LEN		IGB_RXBUFFER_256
+#define IGB_RX_BUFSZ		IGB_RXBUFFER_2048
 
 /* How many Tx Descriptors do we need to call netif_wake_queue ? */
 #define IGB_TX_QUEUE_WAKE	16
@@ -151,11 +150,18 @@ struct vf_data_storage {
 
 #define IGB_MNG_VLAN_NONE -1
 
-#define IGB_TX_FLAGS_CSUM		0x00000001
-#define IGB_TX_FLAGS_VLAN		0x00000002
-#define IGB_TX_FLAGS_TSO		0x00000004
-#define IGB_TX_FLAGS_IPV4		0x00000008
-#define IGB_TX_FLAGS_TSTAMP		0x00000010
+enum igb_tx_flags {
+	/* cmd_type flags */
+	IGB_TX_FLAGS_VLAN	= 0x01,
+	IGB_TX_FLAGS_TSO	= 0x02,
+	IGB_TX_FLAGS_TSTAMP	= 0x04,
+
+	/* olinfo flags */
+	IGB_TX_FLAGS_IPV4	= 0x10,
+	IGB_TX_FLAGS_CSUM	= 0x20,
+};
+
+/* VLAN info */
 #define IGB_TX_FLAGS_VLAN_MASK		0xffff0000
 #define IGB_TX_FLAGS_VLAN_SHIFT	16
 
@@ -174,11 +180,9 @@ struct igb_tx_buffer {
 };
 
 struct igb_rx_buffer {
-	struct sk_buff *skb;
 	dma_addr_t dma;
 	struct page *page;
-	dma_addr_t page_dma;
-	u32 page_offset;
+	unsigned int page_offset;
 };
 
 struct igb_tx_queue_stats {
@@ -205,22 +209,6 @@ struct igb_ring_container {
 	u8 itr;				/* current ITR setting for ring */
 };
 
-struct igb_q_vector {
-	struct igb_adapter *adapter;	/* backlink */
-	int cpu;			/* CPU for DCA */
-	u32 eims_value;			/* EIMS mask value */
-
-	struct igb_ring_container rx, tx;
-
-	struct napi_struct napi;
-
-	u16 itr_val;
-	u8 set_itr;
-	void __iomem *itr_register;
-
-	char name[IFNAMSIZ + 9];
-};
-
 struct igb_ring {
 	struct igb_q_vector *q_vector;	/* backlink to q_vector */
 	struct net_device *netdev;	/* back pointer to net_device */
@@ -232,15 +220,17 @@ struct igb_ring {
 	void *desc;			/* descriptor ring memory */
 	unsigned long flags;		/* ring specific flags */
 	void __iomem *tail;		/* pointer to ring tail register */
+	dma_addr_t dma;			/* phys address of the ring */
+	unsigned int  size;		/* length of desc. ring in bytes */
 
 	u16 count;			/* number of desc. in the ring */
 	u8 queue_index;			/* logical index of the ring*/
 	u8 reg_idx;			/* physical index of the ring */
-	u32 size;			/* length of desc. ring in bytes */
 
 	/* everything past this point are written often */
-	u16 next_to_clean ____cacheline_aligned_in_smp;
+	u16 next_to_clean;
 	u16 next_to_use;
+	u16 next_to_alloc;
 
 	union {
 		/* TX */
@@ -251,12 +241,30 @@ struct igb_ring {
 		};
 		/* RX */
 		struct {
+			struct sk_buff *skb;
 			struct igb_rx_queue_stats rx_stats;
 			struct u64_stats_sync rx_syncp;
 		};
 	};
-	/* Items past this point are only used during ring alloc / free */
-	dma_addr_t dma;                /* phys address of the ring */
+} ____cacheline_internodealigned_in_smp;
+
+struct igb_q_vector {
+	struct igb_adapter *adapter;	/* backlink */
+	int cpu;			/* CPU for DCA */
+	u32 eims_value;			/* EIMS mask value */
+
+	u16 itr_val;
+	u8 set_itr;
+	void __iomem *itr_register;
+
+	struct igb_ring_container rx, tx;
+
+	struct napi_struct napi;
+	struct rcu_head rcu;	/* to avoid race with update stats on free */
+	char name[IFNAMSIZ + 9];
+
+	/* for dynamic allocation of rings associated with this q_vector */
+	struct igb_ring ring[0] ____cacheline_internodealigned_in_smp;
 };
 
 enum e1000_ring_flags_t {
@@ -362,8 +370,6 @@ struct igb_adapter {
 	u32 eims_other;
 
 	/* to not mess up cache alignment, always add to the bottom */
-	u32 eeprom_wol;
-
 	u16 tx_ring_count;
 	u16 rx_ring_count;
 	unsigned int vfs_allocated_count;
@@ -373,7 +379,6 @@ struct igb_adapter {
 	u32 wvbr;
 	u32 *shadow_vfta;
 
-#ifdef CONFIG_IGB_PTP
 	struct ptp_clock *ptp_clock;
 	struct ptp_clock_info ptp_caps;
 	struct delayed_work ptp_overflow_work;
@@ -382,17 +387,19 @@ struct igb_adapter {
 	spinlock_t tmreg_lock;
 	struct cyclecounter cc;
 	struct timecounter tc;
-#endif /* CONFIG_IGB_PTP */
 
 	char fw_version[32];
 };
 
-#define IGB_FLAG_HAS_MSI           (1 << 0)
-#define IGB_FLAG_DCA_ENABLED       (1 << 1)
-#define IGB_FLAG_QUAD_PORT_A       (1 << 2)
-#define IGB_FLAG_QUEUE_PAIRS       (1 << 3)
-#define IGB_FLAG_DMAC              (1 << 4)
-#define IGB_FLAG_PTP               (1 << 5)
+#define IGB_FLAG_HAS_MSI		(1 << 0)
+#define IGB_FLAG_DCA_ENABLED		(1 << 1)
+#define IGB_FLAG_QUAD_PORT_A		(1 << 2)
+#define IGB_FLAG_QUEUE_PAIRS		(1 << 3)
+#define IGB_FLAG_DMAC			(1 << 4)
+#define IGB_FLAG_PTP			(1 << 5)
+#define IGB_FLAG_RSS_FIELD_IPV4_UDP	(1 << 6)
+#define IGB_FLAG_RSS_FIELD_IPV6_UDP	(1 << 7)
+#define IGB_FLAG_WOL_SUPPORTED		(1 << 8)
 
 /* DMA Coalescing defines */
 #define IGB_MIN_TXPBSIZE           20408
@@ -436,18 +443,27 @@ extern bool igb_has_link(struct igb_adapter *adapter);
 extern void igb_set_ethtool_ops(struct net_device *);
 extern void igb_power_up_link(struct igb_adapter *);
 extern void igb_set_fw_version(struct igb_adapter *);
-#ifdef CONFIG_IGB_PTP
 extern void igb_ptp_init(struct igb_adapter *adapter);
 extern void igb_ptp_stop(struct igb_adapter *adapter);
 extern void igb_ptp_reset(struct igb_adapter *adapter);
 extern void igb_ptp_tx_work(struct work_struct *work);
 extern void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter);
-extern void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
-				union e1000_adv_rx_desc *rx_desc,
+extern void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
+				struct sk_buff *skb);
+extern void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector,
+				unsigned char *va,
 				struct sk_buff *skb);
+static inline void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
+				       union e1000_adv_rx_desc *rx_desc,
+				       struct sk_buff *skb)
+{
+	if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TS) &&
+	    !igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP))
+		igb_ptp_rx_rgtstamp(q_vector, skb);
+}
+
 extern int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
 				  struct ifreq *ifr, int cmd);
-#endif /* CONFIG_IGB_PTP */
 
 static inline s32 igb_reset_phy(struct e1000_hw *hw)
 {
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 2ea0128..e2288b5 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -37,6 +37,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
+#include <linux/highmem.h>
 
 #include "igb.h"
 
@@ -1685,16 +1686,24 @@ static void igb_create_lbtest_frame(struct sk_buff *skb,
 	memset(&skb->data[frame_size + 12], 0xAF, 1);
 }
 
-static int igb_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
+static int igb_check_lbtest_frame(struct igb_rx_buffer *rx_buffer,
+				  unsigned int frame_size)
 {
-	frame_size /= 2;
-	if (*(skb->data + 3) == 0xFF) {
-		if ((*(skb->data + frame_size + 10) == 0xBE) &&
-		   (*(skb->data + frame_size + 12) == 0xAF)) {
-			return 0;
-		}
-	}
-	return 13;
+	unsigned char *data;
+	bool match = true;
+
+	frame_size >>= 1;
+
+	data = kmap(rx_buffer->page);
+
+	if (data[3] != 0xFF ||
+	    data[frame_size + 10] != 0xBE ||
+	    data[frame_size + 12] != 0xAF)
+		match = false;
+
+	kunmap(rx_buffer->page);
+
+	return match;
 }
 
 static int igb_clean_test_rings(struct igb_ring *rx_ring,
@@ -1704,9 +1713,7 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring,
 	union e1000_adv_rx_desc *rx_desc;
 	struct igb_rx_buffer *rx_buffer_info;
 	struct igb_tx_buffer *tx_buffer_info;
-	struct netdev_queue *txq;
 	u16 rx_ntc, tx_ntc, count = 0;
-	unsigned int total_bytes = 0, total_packets = 0;
 
 	/* initialize next to clean and descriptor values */
 	rx_ntc = rx_ring->next_to_clean;
@@ -1717,21 +1724,24 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring,
 		/* check rx buffer */
 		rx_buffer_info = &rx_ring->rx_buffer_info[rx_ntc];
 
-		/* unmap rx buffer, will be remapped by alloc_rx_buffers */
-		dma_unmap_single(rx_ring->dev,
-				 rx_buffer_info->dma,
-				 IGB_RX_HDR_LEN,
-				 DMA_FROM_DEVICE);
-		rx_buffer_info->dma = 0;
+		/* sync Rx buffer for CPU read */
+		dma_sync_single_for_cpu(rx_ring->dev,
+					rx_buffer_info->dma,
+					IGB_RX_BUFSZ,
+					DMA_FROM_DEVICE);
 
 		/* verify contents of skb */
-		if (!igb_check_lbtest_frame(rx_buffer_info->skb, size))
+		if (igb_check_lbtest_frame(rx_buffer_info, size))
 			count++;
 
+		/* sync Rx buffer for device write */
+		dma_sync_single_for_device(rx_ring->dev,
+					   rx_buffer_info->dma,
+					   IGB_RX_BUFSZ,
+					   DMA_FROM_DEVICE);
+
 		/* unmap buffer on tx side */
 		tx_buffer_info = &tx_ring->tx_buffer_info[tx_ntc];
-		total_bytes += tx_buffer_info->bytecount;
-		total_packets += tx_buffer_info->gso_segs;
 		igb_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
 
 		/* increment rx/tx next to clean counters */
@@ -1746,8 +1756,7 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring,
 		rx_desc = IGB_RX_DESC(rx_ring, rx_ntc);
 	}
 
-	txq = netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
-	netdev_tx_completed_queue(txq, total_packets, total_bytes);
+	netdev_tx_reset_queue(txring_txq(tx_ring));
 
 	/* re-map buffers to ring, store next to clean values */
 	igb_alloc_rx_buffers(rx_ring, count);
@@ -1957,54 +1966,6 @@ static void igb_diag_test(struct net_device *netdev,
 	msleep_interruptible(4 * 1000);
 }
 
-static int igb_wol_exclusion(struct igb_adapter *adapter,
-			     struct ethtool_wolinfo *wol)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	int retval = 1; /* fail by default */
-
-	switch (hw->device_id) {
-	case E1000_DEV_ID_82575GB_QUAD_COPPER:
-		/* WoL not supported */
-		wol->supported = 0;
-		break;
-	case E1000_DEV_ID_82575EB_FIBER_SERDES:
-	case E1000_DEV_ID_82576_FIBER:
-	case E1000_DEV_ID_82576_SERDES:
-		/* Wake events not supported on port B */
-		if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1) {
-			wol->supported = 0;
-			break;
-		}
-		/* return success for non excluded adapter ports */
-		retval = 0;
-		break;
-	case E1000_DEV_ID_82576_QUAD_COPPER:
-	case E1000_DEV_ID_82576_QUAD_COPPER_ET2:
-		/* quad port adapters only support WoL on port A */
-		if (!(adapter->flags & IGB_FLAG_QUAD_PORT_A)) {
-			wol->supported = 0;
-			break;
-		}
-		/* return success for non excluded adapter ports */
-		retval = 0;
-		break;
-	default:
-		/* dual port cards only support WoL on port A from now on
-		 * unless it was enabled in the eeprom for port B
-		 * so exclude FUNC_1 ports from having WoL enabled */
-		if ((rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) &&
-		    !adapter->eeprom_wol) {
-			wol->supported = 0;
-			break;
-		}
-
-		retval = 0;
-	}
-
-	return retval;
-}
-
 static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
@@ -2014,10 +1975,7 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 	                 WAKE_PHY;
 	wol->wolopts = 0;
 
-	/* this function will set ->supported = 0 and return 1 if wol is not
-	 * supported by this hardware */
-	if (igb_wol_exclusion(adapter, wol) ||
-	    !device_can_wakeup(&adapter->pdev->dev))
+	if (!(adapter->flags & IGB_FLAG_WOL_SUPPORTED))
 		return;
 
 	/* apply any specific unsupported masks here */
@@ -2045,8 +2003,7 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 	if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE))
 		return -EOPNOTSUPP;
 
-	if (igb_wol_exclusion(adapter, wol) ||
-	    !device_can_wakeup(&adapter->pdev->dev))
+	if (!(adapter->flags & IGB_FLAG_WOL_SUPPORTED))
 		return wol->wolopts ? -EOPNOTSUPP : 0;
 
 	/* these settings will always override what we currently have */
@@ -2301,7 +2258,6 @@ static int igb_get_ts_info(struct net_device *dev,
 	struct igb_adapter *adapter = netdev_priv(dev);
 
 	switch (adapter->hw.mac.type) {
-#ifdef CONFIG_IGB_PTP
 	case e1000_82576:
 	case e1000_82580:
 	case e1000_i350:
@@ -2337,12 +2293,288 @@ static int igb_get_ts_info(struct net_device *dev,
 				(1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
 
 		return 0;
-#endif /* CONFIG_IGB_PTP */
 	default:
 		return -EOPNOTSUPP;
 	}
 }
 
+static int igb_get_rss_hash_opts(struct igb_adapter *adapter,
+				 struct ethtool_rxnfc *cmd)
+{
+	cmd->data = 0;
+
+	/* Report default options for RSS on igb */
+	switch (cmd->flow_type) {
+	case TCP_V4_FLOW:
+		cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+	case UDP_V4_FLOW:
+		if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV4_UDP)
+			cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+	case SCTP_V4_FLOW:
+	case AH_ESP_V4_FLOW:
+	case AH_V4_FLOW:
+	case ESP_V4_FLOW:
+	case IPV4_FLOW:
+		cmd->data |= RXH_IP_SRC | RXH_IP_DST;
+		break;
+	case TCP_V6_FLOW:
+		cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+	case UDP_V6_FLOW:
+		if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV6_UDP)
+			cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+	case SCTP_V6_FLOW:
+	case AH_ESP_V6_FLOW:
+	case AH_V6_FLOW:
+	case ESP_V6_FLOW:
+	case IPV6_FLOW:
+		cmd->data |= RXH_IP_SRC | RXH_IP_DST;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int igb_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+			   u32 *rule_locs)
+{
+	struct igb_adapter *adapter = netdev_priv(dev);
+	int ret = -EOPNOTSUPP;
+
+	switch (cmd->cmd) {
+	case ETHTOOL_GRXRINGS:
+		cmd->data = adapter->num_rx_queues;
+		ret = 0;
+		break;
+	case ETHTOOL_GRXFH:
+		ret = igb_get_rss_hash_opts(adapter, cmd);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+#define UDP_RSS_FLAGS (IGB_FLAG_RSS_FIELD_IPV4_UDP | \
+		       IGB_FLAG_RSS_FIELD_IPV6_UDP)
+static int igb_set_rss_hash_opt(struct igb_adapter *adapter,
+				struct ethtool_rxnfc *nfc)
+{
+	u32 flags = adapter->flags;
+
+	/* RSS does not support anything other than hashing
+	 * to queues on src and dst IPs and ports
+	 */
+	if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
+			  RXH_L4_B_0_1 | RXH_L4_B_2_3))
+		return -EINVAL;
+
+	switch (nfc->flow_type) {
+	case TCP_V4_FLOW:
+	case TCP_V6_FLOW:
+		if (!(nfc->data & RXH_IP_SRC) ||
+		    !(nfc->data & RXH_IP_DST) ||
+		    !(nfc->data & RXH_L4_B_0_1) ||
+		    !(nfc->data & RXH_L4_B_2_3))
+			return -EINVAL;
+		break;
+	case UDP_V4_FLOW:
+		if (!(nfc->data & RXH_IP_SRC) ||
+		    !(nfc->data & RXH_IP_DST))
+			return -EINVAL;
+		switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
+		case 0:
+			flags &= ~IGB_FLAG_RSS_FIELD_IPV4_UDP;
+			break;
+		case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+			flags |= IGB_FLAG_RSS_FIELD_IPV4_UDP;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case UDP_V6_FLOW:
+		if (!(nfc->data & RXH_IP_SRC) ||
+		    !(nfc->data & RXH_IP_DST))
+			return -EINVAL;
+		switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
+		case 0:
+			flags &= ~IGB_FLAG_RSS_FIELD_IPV6_UDP;
+			break;
+		case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+			flags |= IGB_FLAG_RSS_FIELD_IPV6_UDP;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case AH_ESP_V4_FLOW:
+	case AH_V4_FLOW:
+	case ESP_V4_FLOW:
+	case SCTP_V4_FLOW:
+	case AH_ESP_V6_FLOW:
+	case AH_V6_FLOW:
+	case ESP_V6_FLOW:
+	case SCTP_V6_FLOW:
+		if (!(nfc->data & RXH_IP_SRC) ||
+		    !(nfc->data & RXH_IP_DST) ||
+		    (nfc->data & RXH_L4_B_0_1) ||
+		    (nfc->data & RXH_L4_B_2_3))
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* if we changed something we need to update flags */
+	if (flags != adapter->flags) {
+		struct e1000_hw *hw = &adapter->hw;
+		u32 mrqc = rd32(E1000_MRQC);
+
+		if ((flags & UDP_RSS_FLAGS) &&
+		    !(adapter->flags & UDP_RSS_FLAGS))
+			dev_err(&adapter->pdev->dev,
+				"enabling UDP RSS: fragmented packets may arrive out of order to the stack above\n");
+
+		adapter->flags = flags;
+
+		/* Perform hash on these packet types */
+		mrqc |= E1000_MRQC_RSS_FIELD_IPV4 |
+			E1000_MRQC_RSS_FIELD_IPV4_TCP |
+			E1000_MRQC_RSS_FIELD_IPV6 |
+			E1000_MRQC_RSS_FIELD_IPV6_TCP;
+
+		mrqc &= ~(E1000_MRQC_RSS_FIELD_IPV4_UDP |
+			  E1000_MRQC_RSS_FIELD_IPV6_UDP);
+
+		if (flags & IGB_FLAG_RSS_FIELD_IPV4_UDP)
+			mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP;
+
+		if (flags & IGB_FLAG_RSS_FIELD_IPV6_UDP)
+			mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP;
+
+		wr32(E1000_MRQC, mrqc);
+	}
+
+	return 0;
+}
+
+static int igb_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
+{
+	struct igb_adapter *adapter = netdev_priv(dev);
+	int ret = -EOPNOTSUPP;
+
+	switch (cmd->cmd) {
+	case ETHTOOL_SRXFH:
+		ret = igb_set_rss_hash_opt(adapter, cmd);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
+{
+	struct igb_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
+	u32 ipcnfg, eeer;
+
+	if ((hw->mac.type < e1000_i350) ||
+	    (hw->phy.media_type != e1000_media_type_copper))
+		return -EOPNOTSUPP;
+
+	edata->supported = (SUPPORTED_1000baseT_Full |
+			    SUPPORTED_100baseT_Full);
+
+	ipcnfg = rd32(E1000_IPCNFG);
+	eeer = rd32(E1000_EEER);
+
+	/* EEE status on negotiated link */
+	if (ipcnfg & E1000_IPCNFG_EEE_1G_AN)
+		edata->advertised = ADVERTISED_1000baseT_Full;
+
+	if (ipcnfg & E1000_IPCNFG_EEE_100M_AN)
+		edata->advertised |= ADVERTISED_100baseT_Full;
+
+	if (eeer & E1000_EEER_EEE_NEG)
+		edata->eee_active = true;
+
+	edata->eee_enabled = !hw->dev_spec._82575.eee_disable;
+
+	if (eeer & E1000_EEER_TX_LPI_EN)
+		edata->tx_lpi_enabled = true;
+
+	/* Report correct negotiated EEE status for devices that
+	 * wrongly report EEE at half-duplex
+	 */
+	if (adapter->link_duplex == HALF_DUPLEX) {
+		edata->eee_enabled = false;
+		edata->eee_active = false;
+		edata->tx_lpi_enabled = false;
+		edata->advertised &= ~edata->advertised;
+	}
+
+	return 0;
+}
+
+static int igb_set_eee(struct net_device *netdev,
+		       struct ethtool_eee *edata)
+{
+	struct igb_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
+	struct ethtool_eee eee_curr;
+	s32 ret_val;
+
+	if ((hw->mac.type < e1000_i350) ||
+	    (hw->phy.media_type != e1000_media_type_copper))
+		return -EOPNOTSUPP;
+
+	ret_val = igb_get_eee(netdev, &eee_curr);
+	if (ret_val)
+		return ret_val;
+
+	if (eee_curr.eee_enabled) {
+		if (eee_curr.tx_lpi_enabled != edata->tx_lpi_enabled) {
+			dev_err(&adapter->pdev->dev,
+				"Setting EEE tx-lpi is not supported\n");
+			return -EINVAL;
+		}
+
+		/* Tx LPI timer is not implemented currently */
+		if (edata->tx_lpi_timer) {
+			dev_err(&adapter->pdev->dev,
+				"Setting EEE Tx LPI timer is not supported\n");
+			return -EINVAL;
+		}
+
+		if (eee_curr.advertised != edata->advertised) {
+			dev_err(&adapter->pdev->dev,
+				"Setting EEE Advertisement is not supported\n");
+			return -EINVAL;
+		}
+
+	} else if (!edata->eee_enabled) {
+		dev_err(&adapter->pdev->dev,
+			"Setting EEE options are not supported with EEE disabled\n");
+			return -EINVAL;
+		}
+
+	if (hw->dev_spec._82575.eee_disable != !edata->eee_enabled) {
+		hw->dev_spec._82575.eee_disable = !edata->eee_enabled;
+		igb_set_eee_i350(hw);
+
+		/* reset link */
+		if (!netif_running(netdev))
+			igb_reset(adapter);
+	}
+
+	return 0;
+}
+
 static int igb_ethtool_begin(struct net_device *netdev)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
@@ -2383,6 +2615,10 @@ static const struct ethtool_ops igb_ethtool_ops = {
 	.get_coalesce           = igb_get_coalesce,
 	.set_coalesce           = igb_set_coalesce,
 	.get_ts_info            = igb_get_ts_info,
+	.get_rxnfc		= igb_get_rxnfc,
+	.set_rxnfc		= igb_set_rxnfc,
+	.get_eee		= igb_get_eee,
+	.set_eee		= igb_set_eee,
 	.begin			= igb_ethtool_begin,
 	.complete		= igb_ethtool_complete,
 };
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index e1ceb37..b85b15a 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -61,7 +61,7 @@
 
 #define MAJ 4
 #define MIN 0
-#define BUILD 1
+#define BUILD 17
 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
 __stringify(BUILD) "-k"
 char igb_driver_name[] = "igb";
@@ -534,31 +534,27 @@ rx_ring_summary:
 
 			if (staterr & E1000_RXD_STAT_DD) {
 				/* Descriptor Done */
-				pr_info("%s[0x%03X]     %016llX %016llX -------"
-					"--------- %p%s\n", "RWB", i,
+				pr_info("%s[0x%03X]     %016llX %016llX ---------------- %s\n",
+					"RWB", i,
 					le64_to_cpu(u0->a),
 					le64_to_cpu(u0->b),
-					buffer_info->skb, next_desc);
+					next_desc);
 			} else {
-				pr_info("%s[0x%03X]     %016llX %016llX %016llX"
-					" %p%s\n", "R  ", i,
+				pr_info("%s[0x%03X]     %016llX %016llX %016llX %s\n",
+					"R  ", i,
 					le64_to_cpu(u0->a),
 					le64_to_cpu(u0->b),
 					(u64)buffer_info->dma,
-					buffer_info->skb, next_desc);
+					next_desc);
 
 				if (netif_msg_pktdata(adapter) &&
-				    buffer_info->dma && buffer_info->skb) {
-					print_hex_dump(KERN_INFO, "",
-						  DUMP_PREFIX_ADDRESS,
-						  16, 1, buffer_info->skb->data,
-						  IGB_RX_HDR_LEN, true);
+				    buffer_info->dma && buffer_info->page) {
 					print_hex_dump(KERN_INFO, "",
 					  DUMP_PREFIX_ADDRESS,
 					  16, 1,
 					  page_address(buffer_info->page) +
 						      buffer_info->page_offset,
-					  PAGE_SIZE/2, true);
+					  IGB_RX_BUFSZ, true);
 				}
 			}
 		}
@@ -656,80 +652,6 @@ static void igb_cache_ring_register(struct igb_adapter *adapter)
 	}
 }
 
-static void igb_free_queues(struct igb_adapter *adapter)
-{
-	int i;
-
-	for (i = 0; i < adapter->num_tx_queues; i++) {
-		kfree(adapter->tx_ring[i]);
-		adapter->tx_ring[i] = NULL;
-	}
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		kfree(adapter->rx_ring[i]);
-		adapter->rx_ring[i] = NULL;
-	}
-	adapter->num_rx_queues = 0;
-	adapter->num_tx_queues = 0;
-}
-
-/**
- * igb_alloc_queues - Allocate memory for all rings
- * @adapter: board private structure to initialize
- *
- * We allocate one ring per queue at run-time since we don't know the
- * number of queues at compile-time.
- **/
-static int igb_alloc_queues(struct igb_adapter *adapter)
-{
-	struct igb_ring *ring;
-	int i;
-
-	for (i = 0; i < adapter->num_tx_queues; i++) {
-		ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL);
-		if (!ring)
-			goto err;
-		ring->count = adapter->tx_ring_count;
-		ring->queue_index = i;
-		ring->dev = &adapter->pdev->dev;
-		ring->netdev = adapter->netdev;
-		/* For 82575, context index must be unique per ring. */
-		if (adapter->hw.mac.type == e1000_82575)
-			set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags);
-		adapter->tx_ring[i] = ring;
-	}
-
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL);
-		if (!ring)
-			goto err;
-		ring->count = adapter->rx_ring_count;
-		ring->queue_index = i;
-		ring->dev = &adapter->pdev->dev;
-		ring->netdev = adapter->netdev;
-		/* set flag indicating ring supports SCTP checksum offload */
-		if (adapter->hw.mac.type >= e1000_82576)
-			set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags);
-
-		/*
-		 * On i350, i210, and i211, loopback VLAN packets
-		 * have the tag byte-swapped.
-		 * */
-		if (adapter->hw.mac.type >= e1000_i350)
-			set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags);
-
-		adapter->rx_ring[i] = ring;
-	}
-
-	igb_cache_ring_register(adapter);
-
-	return 0;
-
-err:
-	igb_free_queues(adapter);
-
-	return -ENOMEM;
-}
-
 /**
  *  igb_write_ivar - configure ivar for given MSI-X vector
  *  @hw: pointer to the HW structure
@@ -960,6 +882,35 @@ static void igb_reset_interrupt_capability(struct igb_adapter *adapter)
 }
 
 /**
+ * igb_free_q_vector - Free memory allocated for specific interrupt vector
+ * @adapter: board private structure to initialize
+ * @v_idx: Index of vector to be freed
+ *
+ * This function frees the memory allocated to the q_vector.  In addition if
+ * NAPI is enabled it will delete any references to the NAPI struct prior
+ * to freeing the q_vector.
+ **/
+static void igb_free_q_vector(struct igb_adapter *adapter, int v_idx)
+{
+	struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
+
+	if (q_vector->tx.ring)
+		adapter->tx_ring[q_vector->tx.ring->queue_index] = NULL;
+
+	if (q_vector->rx.ring)
+		adapter->tx_ring[q_vector->rx.ring->queue_index] = NULL;
+
+	adapter->q_vector[v_idx] = NULL;
+	netif_napi_del(&q_vector->napi);
+
+	/*
+	 * ixgbe_get_stats64() might access the rings on this vector,
+	 * we must wait a grace period before freeing it.
+	 */
+	kfree_rcu(q_vector, rcu);
+}
+
+/**
  * igb_free_q_vectors - Free memory allocated for interrupt vectors
  * @adapter: board private structure to initialize
  *
@@ -969,17 +920,14 @@ static void igb_reset_interrupt_capability(struct igb_adapter *adapter)
  **/
 static void igb_free_q_vectors(struct igb_adapter *adapter)
 {
-	int v_idx;
+	int v_idx = adapter->num_q_vectors;
 
-	for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) {
-		struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
-		adapter->q_vector[v_idx] = NULL;
-		if (!q_vector)
-			continue;
-		netif_napi_del(&q_vector->napi);
-		kfree(q_vector);
-	}
+	adapter->num_tx_queues = 0;
+	adapter->num_rx_queues = 0;
 	adapter->num_q_vectors = 0;
+
+	while (v_idx--)
+		igb_free_q_vector(adapter, v_idx);
 }
 
 /**
@@ -990,7 +938,6 @@ static void igb_free_q_vectors(struct igb_adapter *adapter)
  */
 static void igb_clear_interrupt_scheme(struct igb_adapter *adapter)
 {
-	igb_free_queues(adapter);
 	igb_free_q_vectors(adapter);
 	igb_reset_interrupt_capability(adapter);
 }
@@ -1001,7 +948,7 @@ static void igb_clear_interrupt_scheme(struct igb_adapter *adapter)
  * Attempt to configure interrupts using the best available
  * capabilities of the hardware and kernel.
  **/
-static int igb_set_interrupt_capability(struct igb_adapter *adapter)
+static void igb_set_interrupt_capability(struct igb_adapter *adapter)
 {
 	int err;
 	int numvecs, i;
@@ -1038,7 +985,7 @@ static int igb_set_interrupt_capability(struct igb_adapter *adapter)
 			      adapter->msix_entries,
 			      numvecs);
 	if (err == 0)
-		goto out;
+		return;
 
 	igb_reset_interrupt_capability(adapter);
 
@@ -1068,105 +1015,183 @@ msi_only:
 	adapter->num_q_vectors = 1;
 	if (!pci_enable_msi(adapter->pdev))
 		adapter->flags |= IGB_FLAG_HAS_MSI;
-out:
-	/* Notify the stack of the (possibly) reduced queue counts. */
-	rtnl_lock();
-	netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
-	err = netif_set_real_num_rx_queues(adapter->netdev,
-		adapter->num_rx_queues);
-	rtnl_unlock();
-	return err;
+}
+
+static void igb_add_ring(struct igb_ring *ring,
+			 struct igb_ring_container *head)
+{
+	head->ring = ring;
+	head->count++;
 }
 
 /**
- * igb_alloc_q_vectors - Allocate memory for interrupt vectors
+ * igb_alloc_q_vector - Allocate memory for a single interrupt vector
  * @adapter: board private structure to initialize
+ * @v_count: q_vectors allocated on adapter, used for ring interleaving
+ * @v_idx: index of vector in adapter struct
+ * @txr_count: total number of Tx rings to allocate
+ * @txr_idx: index of first Tx ring to allocate
+ * @rxr_count: total number of Rx rings to allocate
+ * @rxr_idx: index of first Rx ring to allocate
  *
- * We allocate one q_vector per queue interrupt.  If allocation fails we
- * return -ENOMEM.
+ * We allocate one q_vector.  If allocation fails we return -ENOMEM.
  **/
-static int igb_alloc_q_vectors(struct igb_adapter *adapter)
+static int igb_alloc_q_vector(struct igb_adapter *adapter,
+			      int v_count, int v_idx,
+			      int txr_count, int txr_idx,
+			      int rxr_count, int rxr_idx)
 {
 	struct igb_q_vector *q_vector;
-	struct e1000_hw *hw = &adapter->hw;
-	int v_idx;
+	struct igb_ring *ring;
+	int ring_count, size;
 
-	for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) {
-		q_vector = kzalloc(sizeof(struct igb_q_vector),
-				   GFP_KERNEL);
-		if (!q_vector)
-			goto err_out;
-		q_vector->adapter = adapter;
-		q_vector->itr_register = hw->hw_addr + E1000_EITR(0);
-		q_vector->itr_val = IGB_START_ITR;
-		netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll, 64);
-		adapter->q_vector[v_idx] = q_vector;
+	/* igb only supports 1 Tx and/or 1 Rx queue per vector */
+	if (txr_count > 1 || rxr_count > 1)
+		return -ENOMEM;
+
+	ring_count = txr_count + rxr_count;
+	size = sizeof(struct igb_q_vector) +
+	       (sizeof(struct igb_ring) * ring_count);
+
+	/* allocate q_vector and rings */
+	q_vector = kzalloc(size, GFP_KERNEL);
+	if (!q_vector)
+		return -ENOMEM;
+
+	/* initialize NAPI */
+	netif_napi_add(adapter->netdev, &q_vector->napi,
+		       igb_poll, 64);
+
+	/* tie q_vector and adapter together */
+	adapter->q_vector[v_idx] = q_vector;
+	q_vector->adapter = adapter;
+
+	/* initialize work limits */
+	q_vector->tx.work_limit = adapter->tx_work_limit;
+
+	/* initialize ITR configuration */
+	q_vector->itr_register = adapter->hw.hw_addr + E1000_EITR(0);
+	q_vector->itr_val = IGB_START_ITR;
+
+	/* initialize pointer to rings */
+	ring = q_vector->ring;
+
+	if (txr_count) {
+		/* assign generic ring traits */
+		ring->dev = &adapter->pdev->dev;
+		ring->netdev = adapter->netdev;
+
+		/* configure backlink on ring */
+		ring->q_vector = q_vector;
+
+		/* update q_vector Tx values */
+		igb_add_ring(ring, &q_vector->tx);
+
+		/* For 82575, context index must be unique per ring. */
+		if (adapter->hw.mac.type == e1000_82575)
+			set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags);
+
+		/* apply Tx specific ring traits */
+		ring->count = adapter->tx_ring_count;
+		ring->queue_index = txr_idx;
+
+		/* assign ring to adapter */
+		adapter->tx_ring[txr_idx] = ring;
+
+		/* push pointer to next ring */
+		ring++;
 	}
 
-	return 0;
+	if (rxr_count) {
+		/* assign generic ring traits */
+		ring->dev = &adapter->pdev->dev;
+		ring->netdev = adapter->netdev;
 
-err_out:
-	igb_free_q_vectors(adapter);
-	return -ENOMEM;
-}
+		/* configure backlink on ring */
+		ring->q_vector = q_vector;
 
-static void igb_map_rx_ring_to_vector(struct igb_adapter *adapter,
-                                      int ring_idx, int v_idx)
-{
-	struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
+		/* update q_vector Rx values */
+		igb_add_ring(ring, &q_vector->rx);
 
-	q_vector->rx.ring = adapter->rx_ring[ring_idx];
-	q_vector->rx.ring->q_vector = q_vector;
-	q_vector->rx.count++;
-	q_vector->itr_val = adapter->rx_itr_setting;
-	if (q_vector->itr_val && q_vector->itr_val <= 3)
-		q_vector->itr_val = IGB_START_ITR;
-}
+		/* set flag indicating ring supports SCTP checksum offload */
+		if (adapter->hw.mac.type >= e1000_82576)
+			set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags);
 
-static void igb_map_tx_ring_to_vector(struct igb_adapter *adapter,
-                                      int ring_idx, int v_idx)
-{
-	struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
+		/*
+		 * On i350, i210, and i211, loopback VLAN packets
+		 * have the tag byte-swapped.
+		 * */
+		if (adapter->hw.mac.type >= e1000_i350)
+			set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags);
 
-	q_vector->tx.ring = adapter->tx_ring[ring_idx];
-	q_vector->tx.ring->q_vector = q_vector;
-	q_vector->tx.count++;
-	q_vector->itr_val = adapter->tx_itr_setting;
-	q_vector->tx.work_limit = adapter->tx_work_limit;
-	if (q_vector->itr_val && q_vector->itr_val <= 3)
-		q_vector->itr_val = IGB_START_ITR;
+		/* apply Rx specific ring traits */
+		ring->count = adapter->rx_ring_count;
+		ring->queue_index = rxr_idx;
+
+		/* assign ring to adapter */
+		adapter->rx_ring[rxr_idx] = ring;
+	}
+
+	return 0;
 }
 
+
 /**
- * igb_map_ring_to_vector - maps allocated queues to vectors
+ * igb_alloc_q_vectors - Allocate memory for interrupt vectors
+ * @adapter: board private structure to initialize
  *
- * This function maps the recently allocated queues to vectors.
+ * We allocate one q_vector per queue interrupt.  If allocation fails we
+ * return -ENOMEM.
  **/
-static int igb_map_ring_to_vector(struct igb_adapter *adapter)
+static int igb_alloc_q_vectors(struct igb_adapter *adapter)
 {
-	int i;
-	int v_idx = 0;
+	int q_vectors = adapter->num_q_vectors;
+	int rxr_remaining = adapter->num_rx_queues;
+	int txr_remaining = adapter->num_tx_queues;
+	int rxr_idx = 0, txr_idx = 0, v_idx = 0;
+	int err;
 
-	if ((adapter->num_q_vectors < adapter->num_rx_queues) ||
-	    (adapter->num_q_vectors < adapter->num_tx_queues))
-		return -ENOMEM;
+	if (q_vectors >= (rxr_remaining + txr_remaining)) {
+		for (; rxr_remaining; v_idx++) {
+			err = igb_alloc_q_vector(adapter, q_vectors, v_idx,
+						 0, 0, 1, rxr_idx);
 
-	if (adapter->num_q_vectors >=
-	    (adapter->num_rx_queues + adapter->num_tx_queues)) {
-		for (i = 0; i < adapter->num_rx_queues; i++)
-			igb_map_rx_ring_to_vector(adapter, i, v_idx++);
-		for (i = 0; i < adapter->num_tx_queues; i++)
-			igb_map_tx_ring_to_vector(adapter, i, v_idx++);
-	} else {
-		for (i = 0; i < adapter->num_rx_queues; i++) {
-			if (i < adapter->num_tx_queues)
-				igb_map_tx_ring_to_vector(adapter, i, v_idx);
-			igb_map_rx_ring_to_vector(adapter, i, v_idx++);
+			if (err)
+				goto err_out;
+
+			/* update counts and index */
+			rxr_remaining--;
+			rxr_idx++;
 		}
-		for (; i < adapter->num_tx_queues; i++)
-			igb_map_tx_ring_to_vector(adapter, i, v_idx++);
 	}
+
+	for (; v_idx < q_vectors; v_idx++) {
+		int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx);
+		int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx);
+		err = igb_alloc_q_vector(adapter, q_vectors, v_idx,
+					 tqpv, txr_idx, rqpv, rxr_idx);
+
+		if (err)
+			goto err_out;
+
+		/* update counts and index */
+		rxr_remaining -= rqpv;
+		txr_remaining -= tqpv;
+		rxr_idx++;
+		txr_idx++;
+	}
+
 	return 0;
+
+err_out:
+	adapter->num_tx_queues = 0;
+	adapter->num_rx_queues = 0;
+	adapter->num_q_vectors = 0;
+
+	while (v_idx--)
+		igb_free_q_vector(adapter, v_idx);
+
+	return -ENOMEM;
 }
 
 /**
@@ -1179,9 +1204,7 @@ static int igb_init_interrupt_scheme(struct igb_adapter *adapter)
 	struct pci_dev *pdev = adapter->pdev;
 	int err;
 
-	err = igb_set_interrupt_capability(adapter);
-	if (err)
-		return err;
+	igb_set_interrupt_capability(adapter);
 
 	err = igb_alloc_q_vectors(adapter);
 	if (err) {
@@ -1189,24 +1212,10 @@ static int igb_init_interrupt_scheme(struct igb_adapter *adapter)
 		goto err_alloc_q_vectors;
 	}
 
-	err = igb_alloc_queues(adapter);
-	if (err) {
-		dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
-		goto err_alloc_queues;
-	}
-
-	err = igb_map_ring_to_vector(adapter);
-	if (err) {
-		dev_err(&pdev->dev, "Invalid q_vector to ring mapping\n");
-		goto err_map_queues;
-	}
-
+	igb_cache_ring_register(adapter);
 
 	return 0;
-err_map_queues:
-	igb_free_queues(adapter);
-err_alloc_queues:
-	igb_free_q_vectors(adapter);
+
 err_alloc_q_vectors:
 	igb_reset_interrupt_capability(adapter);
 	return err;
@@ -1229,11 +1238,11 @@ static int igb_request_irq(struct igb_adapter *adapter)
 		if (!err)
 			goto request_done;
 		/* fall back to MSI */
+		igb_free_all_tx_resources(adapter);
+		igb_free_all_rx_resources(adapter);
 		igb_clear_interrupt_scheme(adapter);
 		if (!pci_enable_msi(pdev))
 			adapter->flags |= IGB_FLAG_HAS_MSI;
-		igb_free_all_tx_resources(adapter);
-		igb_free_all_rx_resources(adapter);
 		adapter->num_tx_queues = 1;
 		adapter->num_rx_queues = 1;
 		adapter->num_q_vectors = 1;
@@ -1243,13 +1252,6 @@ static int igb_request_irq(struct igb_adapter *adapter)
 			        "Unable to allocate memory for vectors\n");
 			goto request_done;
 		}
-		err = igb_alloc_queues(adapter);
-		if (err) {
-			dev_err(&pdev->dev,
-			        "Unable to allocate memory for queues\n");
-			igb_free_q_vectors(adapter);
-			goto request_done;
-		}
 		igb_setup_all_tx_resources(adapter);
 		igb_setup_all_rx_resources(adapter);
 	}
@@ -1587,8 +1589,7 @@ void igb_reset(struct igb_adapter *adapter)
 	struct e1000_hw *hw = &adapter->hw;
 	struct e1000_mac_info *mac = &hw->mac;
 	struct e1000_fc_info *fc = &hw->fc;
-	u32 pba = 0, tx_space, min_tx_space, min_rx_space;
-	u16 hwm;
+	u32 pba = 0, tx_space, min_tx_space, min_rx_space, hwm;
 
 	/* Repartition Pba for greater than 9k mtu
 	 * To take effect CTRL.RST is required.
@@ -1663,7 +1664,7 @@ void igb_reset(struct igb_adapter *adapter)
 	hwm = min(((pba << 10) * 9 / 10),
 			((pba << 10) - 2 * adapter->max_frame_size));
 
-	fc->high_water = hwm & 0xFFF0;	/* 16-byte granularity */
+	fc->high_water = hwm & 0xFFFFFFF0;	/* 16-byte granularity */
 	fc->low_water = fc->high_water - 16;
 	fc->pause_time = 0xFFFF;
 	fc->send_xon = 1;
@@ -1706,10 +1707,8 @@ void igb_reset(struct igb_adapter *adapter)
 	/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
 	wr32(E1000_VET, ETHERNET_IEEE_VLAN_TYPE);
 
-#ifdef CONFIG_IGB_PTP
 	/* Re-enable PTP, where applicable. */
 	igb_ptp_reset(adapter);
-#endif /* CONFIG_IGB_PTP */
 
 	igb_get_phy_info(hw);
 }
@@ -1783,58 +1782,34 @@ static const struct net_device_ops igb_netdev_ops = {
 void igb_set_fw_version(struct igb_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
-	u16 eeprom_verh, eeprom_verl, comb_verh, comb_verl, comb_offset;
-	u16 major, build, patch, fw_version;
-	u32 etrack_id;
-
-	hw->nvm.ops.read(hw, 5, 1, &fw_version);
-	if (adapter->hw.mac.type != e1000_i211) {
-		hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verh);
-		hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verl);
-		etrack_id = (eeprom_verh << IGB_ETRACK_SHIFT) | eeprom_verl;
-
-		/* combo image version needs to be found */
-		hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset);
-		if ((comb_offset != 0x0) &&
-		    (comb_offset != IGB_NVM_VER_INVALID)) {
-			hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset
-					 + 1), 1, &comb_verh);
-			hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset),
-					 1, &comb_verl);
-
-			/* Only display Option Rom if it exists and is valid */
-			if ((comb_verh && comb_verl) &&
-			    ((comb_verh != IGB_NVM_VER_INVALID) &&
-			     (comb_verl != IGB_NVM_VER_INVALID))) {
-				major = comb_verl >> IGB_COMB_VER_SHFT;
-				build = (comb_verl << IGB_COMB_VER_SHFT) |
-					(comb_verh >> IGB_COMB_VER_SHFT);
-				patch = comb_verh & IGB_COMB_VER_MASK;
-				snprintf(adapter->fw_version,
-					 sizeof(adapter->fw_version),
-					 "%d.%d%d, 0x%08x, %d.%d.%d",
-					 (fw_version & IGB_MAJOR_MASK) >>
-					 IGB_MAJOR_SHIFT,
-					 (fw_version & IGB_MINOR_MASK) >>
-					 IGB_MINOR_SHIFT,
-					 (fw_version & IGB_BUILD_MASK),
-					 etrack_id, major, build, patch);
-				goto out;
-			}
-		}
-		snprintf(adapter->fw_version, sizeof(adapter->fw_version),
-			 "%d.%d%d, 0x%08x",
-			 (fw_version & IGB_MAJOR_MASK) >> IGB_MAJOR_SHIFT,
-			 (fw_version & IGB_MINOR_MASK) >> IGB_MINOR_SHIFT,
-			 (fw_version & IGB_BUILD_MASK), etrack_id);
-	} else {
+	struct e1000_fw_version fw;
+
+	igb_get_fw_version(hw, &fw);
+
+	switch (hw->mac.type) {
+	case e1000_i211:
 		snprintf(adapter->fw_version, sizeof(adapter->fw_version),
-			 "%d.%d%d",
-			 (fw_version & IGB_MAJOR_MASK) >> IGB_MAJOR_SHIFT,
-			 (fw_version & IGB_MINOR_MASK) >> IGB_MINOR_SHIFT,
-			 (fw_version & IGB_BUILD_MASK));
+			 "%2d.%2d-%d",
+			 fw.invm_major, fw.invm_minor, fw.invm_img_type);
+		break;
+
+	default:
+		/* if option is rom valid, display its version too */
+		if (fw.or_valid) {
+			snprintf(adapter->fw_version,
+				 sizeof(adapter->fw_version),
+				 "%d.%d, 0x%08x, %d.%d.%d",
+				 fw.eep_major, fw.eep_minor, fw.etrack_id,
+				 fw.or_major, fw.or_build, fw.or_patch);
+		/* no option rom */
+		} else {
+			snprintf(adapter->fw_version,
+				 sizeof(adapter->fw_version),
+				 "%d.%d, 0x%08x",
+				 fw.eep_major, fw.eep_minor, fw.etrack_id);
+		}
+		break;
 	}
-out:
 	return;
 }
 
@@ -1861,7 +1836,6 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 	const struct e1000_info *ei = igb_info_tbl[ent->driver_data];
 	unsigned long mmio_start, mmio_len;
 	int err, pci_using_dac;
-	u16 eeprom_apme_mask = IGB_EEPROM_APME;
 	u8 part_str[E1000_PBANUM_LENGTH];
 
 	/* Catch broken hardware that put the wrong VF device ID in
@@ -2069,28 +2043,27 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 
 	igb_validate_mdi_setting(hw);
 
-	/* Initial Wake on LAN setting If APM wake is enabled in the EEPROM,
-	 * enable the ACPI Magic Packet filter
-	 */
-
+	/* By default, support wake on port A */
 	if (hw->bus.func == 0)
-		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
-	else if (hw->mac.type >= e1000_82580)
+		adapter->flags |= IGB_FLAG_WOL_SUPPORTED;
+
+	/* Check the NVM for wake support on non-port A ports */
+	if (hw->mac.type >= e1000_82580)
 		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A +
 		                 NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1,
 		                 &eeprom_data);
 	else if (hw->bus.func == 1)
 		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
 
-	if (eeprom_data & eeprom_apme_mask)
-		adapter->eeprom_wol |= E1000_WUFC_MAG;
+	if (eeprom_data & IGB_EEPROM_APME)
+		adapter->flags |= IGB_FLAG_WOL_SUPPORTED;
 
 	/* now that we have the eeprom settings, apply the special cases where
 	 * the eeprom may be wrong or the board simply won't support wake on
 	 * lan on a particular port */
 	switch (pdev->device) {
 	case E1000_DEV_ID_82575GB_QUAD_COPPER:
-		adapter->eeprom_wol = 0;
+		adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED;
 		break;
 	case E1000_DEV_ID_82575EB_FIBER_SERDES:
 	case E1000_DEV_ID_82576_FIBER:
@@ -2098,24 +2071,38 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 		/* Wake events only supported on port A for dual fiber
 		 * regardless of eeprom setting */
 		if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1)
-			adapter->eeprom_wol = 0;
+			adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED;
 		break;
 	case E1000_DEV_ID_82576_QUAD_COPPER:
 	case E1000_DEV_ID_82576_QUAD_COPPER_ET2:
 		/* if quad port adapter, disable WoL on all but port A */
 		if (global_quad_port_a != 0)
-			adapter->eeprom_wol = 0;
+			adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED;
 		else
 			adapter->flags |= IGB_FLAG_QUAD_PORT_A;
 		/* Reset for multiple quad port adapters */
 		if (++global_quad_port_a == 4)
 			global_quad_port_a = 0;
 		break;
+	default:
+		/* If the device can't wake, don't set software support */
+		if (!device_can_wakeup(&adapter->pdev->dev))
+			adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED;
 	}
 
 	/* initialize the wol settings based on the eeprom settings */
-	adapter->wol = adapter->eeprom_wol;
-	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+	if (adapter->flags & IGB_FLAG_WOL_SUPPORTED)
+		adapter->wol |= E1000_WUFC_MAG;
+
+	/* Some vendors want WoL disabled by default, but still supported */
+	if ((hw->mac.type == e1000_i350) &&
+	    (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)) {
+		adapter->flags |= IGB_FLAG_WOL_SUPPORTED;
+		adapter->wol = 0;
+	}
+
+	device_set_wakeup_enable(&adapter->pdev->dev,
+				 adapter->flags & IGB_FLAG_WOL_SUPPORTED);
 
 	/* reset the hardware with the new settings */
 	igb_reset(adapter);
@@ -2141,10 +2128,8 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 
 #endif
 
-#ifdef CONFIG_IGB_PTP
 	/* do hw tstamp init after resetting */
 	igb_ptp_init(adapter);
-#endif /* CONFIG_IGB_PTP */
 
 	dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n");
 	/* print bus type/speed/width info */
@@ -2219,9 +2204,7 @@ static void __devexit igb_remove(struct pci_dev *pdev)
 	struct e1000_hw *hw = &adapter->hw;
 
 	pm_runtime_get_noresume(&pdev->dev);
-#ifdef CONFIG_IGB_PTP
 	igb_ptp_stop(adapter);
-#endif /* CONFIG_IGB_PTP */
 
 	/*
 	 * The watchdog timer may be rescheduled, so explicitly
@@ -2531,6 +2514,17 @@ static int __igb_open(struct net_device *netdev, bool resuming)
 	if (err)
 		goto err_req_irq;
 
+	/* Notify the stack of the actual queue counts. */
+	err = netif_set_real_num_tx_queues(adapter->netdev,
+					   adapter->num_tx_queues);
+	if (err)
+		goto err_set_queues;
+
+	err = netif_set_real_num_rx_queues(adapter->netdev,
+					   adapter->num_rx_queues);
+	if (err)
+		goto err_set_queues;
+
 	/* From here on the code is the same as igb_up() */
 	clear_bit(__IGB_DOWN, &adapter->state);
 
@@ -2560,6 +2554,8 @@ static int __igb_open(struct net_device *netdev, bool resuming)
 
 	return 0;
 
+err_set_queues:
+	igb_free_irq(adapter);
 err_req_irq:
 	igb_release_hw_control(adapter);
 	igb_power_down_link(adapter);
@@ -2637,10 +2633,8 @@ int igb_setup_tx_resources(struct igb_ring *tx_ring)
 	tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
 	tx_ring->size = ALIGN(tx_ring->size, 4096);
 
-	tx_ring->desc = dma_alloc_coherent(dev,
-					   tx_ring->size,
-					   &tx_ring->dma,
-					   GFP_KERNEL);
+	tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size,
+					   &tx_ring->dma, GFP_KERNEL);
 	if (!tx_ring->desc)
 		goto err;
 
@@ -2777,18 +2771,16 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
 	if (!rx_ring->rx_buffer_info)
 		goto err;
 
-
 	/* Round up to nearest 4K */
 	rx_ring->size = rx_ring->count * sizeof(union e1000_adv_rx_desc);
 	rx_ring->size = ALIGN(rx_ring->size, 4096);
 
-	rx_ring->desc = dma_alloc_coherent(dev,
-					   rx_ring->size,
-					   &rx_ring->dma,
-					   GFP_KERNEL);
+	rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size,
+					   &rx_ring->dma, GFP_KERNEL);
 	if (!rx_ring->desc)
 		goto err;
 
+	rx_ring->next_to_alloc = 0;
 	rx_ring->next_to_clean = 0;
 	rx_ring->next_to_use = 0;
 
@@ -2893,18 +2885,21 @@ static void igb_setup_mrqc(struct igb_adapter *adapter)
 
 	/* Don't need to set TUOFL or IPOFL, they default to 1 */
 	wr32(E1000_RXCSUM, rxcsum);
-	/*
-	 * Generate RSS hash based on TCP port numbers and/or
-	 * IPv4/v6 src and dst addresses since UDP cannot be
-	 * hashed reliably due to IP fragmentation
-	 */
 
+	/* Generate RSS hash based on packet types, TCP/UDP
+	 * port numbers and/or IPv4/v6 src and dst addresses
+	 */
 	mrqc = E1000_MRQC_RSS_FIELD_IPV4 |
 	       E1000_MRQC_RSS_FIELD_IPV4_TCP |
 	       E1000_MRQC_RSS_FIELD_IPV6 |
 	       E1000_MRQC_RSS_FIELD_IPV6_TCP |
 	       E1000_MRQC_RSS_FIELD_IPV6_TCP_EX;
 
+	if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV4_UDP)
+		mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP;
+	if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV6_UDP)
+		mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP;
+
 	/* If VMDq is enabled then we set the appropriate mode for that, else
 	 * we default to RSS so that an RSS hash is calculated per packet even
 	 * if we are only using one queue */
@@ -3106,16 +3101,10 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
 
 	/* set descriptor configuration */
 	srrctl = IGB_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
-#if (PAGE_SIZE / 2) > IGB_RXBUFFER_16384
-	srrctl |= IGB_RXBUFFER_16384 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
-#else
-	srrctl |= (PAGE_SIZE / 2) >> E1000_SRRCTL_BSIZEPKT_SHIFT;
-#endif
-	srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
-#ifdef CONFIG_IGB_PTP
+	srrctl |= IGB_RX_BUFSZ >> E1000_SRRCTL_BSIZEPKT_SHIFT;
+	srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
 	if (hw->mac.type >= e1000_82580)
 		srrctl |= E1000_SRRCTL_TIMESTAMP;
-#endif /* CONFIG_IGB_PTP */
 	/* Only set Drop Enable if we are supporting multiple queues */
 	if (adapter->vfs_allocated_count || adapter->num_rx_queues > 1)
 		srrctl |= E1000_SRRCTL_DROP_EN;
@@ -3305,36 +3294,27 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
 	unsigned long size;
 	u16 i;
 
+	if (rx_ring->skb)
+		dev_kfree_skb(rx_ring->skb);
+	rx_ring->skb = NULL;
+
 	if (!rx_ring->rx_buffer_info)
 		return;
 
 	/* Free all the Rx ring sk_buffs */
 	for (i = 0; i < rx_ring->count; i++) {
 		struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i];
-		if (buffer_info->dma) {
-			dma_unmap_single(rx_ring->dev,
-			                 buffer_info->dma,
-					 IGB_RX_HDR_LEN,
-					 DMA_FROM_DEVICE);
-			buffer_info->dma = 0;
-		}
 
-		if (buffer_info->skb) {
-			dev_kfree_skb(buffer_info->skb);
-			buffer_info->skb = NULL;
-		}
-		if (buffer_info->page_dma) {
-			dma_unmap_page(rx_ring->dev,
-			               buffer_info->page_dma,
-				       PAGE_SIZE / 2,
-				       DMA_FROM_DEVICE);
-			buffer_info->page_dma = 0;
-		}
-		if (buffer_info->page) {
-			put_page(buffer_info->page);
-			buffer_info->page = NULL;
-			buffer_info->page_offset = 0;
-		}
+		if (!buffer_info->page)
+			continue;
+
+		dma_unmap_page(rx_ring->dev,
+			       buffer_info->dma,
+			       PAGE_SIZE,
+			       DMA_FROM_DEVICE);
+		__free_page(buffer_info->page);
+
+		buffer_info->page = NULL;
 	}
 
 	size = sizeof(struct igb_rx_buffer) * rx_ring->count;
@@ -3343,6 +3323,7 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
 	/* Zero out the descriptor ring */
 	memset(rx_ring->desc, 0, rx_ring->size);
 
+	rx_ring->next_to_alloc = 0;
 	rx_ring->next_to_clean = 0;
 	rx_ring->next_to_use = 0;
 }
@@ -4028,6 +4009,9 @@ static int igb_tso(struct igb_ring *tx_ring,
 	u32 vlan_macip_lens, type_tucmd;
 	u32 mss_l4len_idx, l4len;
 
+	if (skb->ip_summed != CHECKSUM_PARTIAL)
+		return 0;
+
 	if (!skb_is_gso(skb))
 		return 0;
 
@@ -4148,26 +4132,32 @@ static void igb_tx_csum(struct igb_ring *tx_ring, struct igb_tx_buffer *first)
 	igb_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx);
 }
 
-static __le32 igb_tx_cmd_type(u32 tx_flags)
+#define IGB_SET_FLAG(_input, _flag, _result) \
+	((_flag <= _result) ? \
+	 ((u32)(_input & _flag) * (_result / _flag)) : \
+	 ((u32)(_input & _flag) / (_flag / _result)))
+
+static u32 igb_tx_cmd_type(struct sk_buff *skb, u32 tx_flags)
 {
 	/* set type for advanced descriptor with frame checksum insertion */
-	__le32 cmd_type = cpu_to_le32(E1000_ADVTXD_DTYP_DATA |
-				      E1000_ADVTXD_DCMD_IFCS |
-				      E1000_ADVTXD_DCMD_DEXT);
+	u32 cmd_type = E1000_ADVTXD_DTYP_DATA |
+		       E1000_ADVTXD_DCMD_DEXT |
+		       E1000_ADVTXD_DCMD_IFCS;
 
 	/* set HW vlan bit if vlan is present */
-	if (tx_flags & IGB_TX_FLAGS_VLAN)
-		cmd_type |= cpu_to_le32(E1000_ADVTXD_DCMD_VLE);
+	cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_VLAN,
+				 (E1000_ADVTXD_DCMD_VLE));
+
+	/* set segmentation bits for TSO */
+	cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSO,
+				 (E1000_ADVTXD_DCMD_TSE));
 
-#ifdef CONFIG_IGB_PTP
 	/* set timestamp bit if present */
-	if (unlikely(tx_flags & IGB_TX_FLAGS_TSTAMP))
-		cmd_type |= cpu_to_le32(E1000_ADVTXD_MAC_TSTAMP);
-#endif /* CONFIG_IGB_PTP */
+	cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSTAMP,
+				 (E1000_ADVTXD_MAC_TSTAMP));
 
-	/* set segmentation bits for TSO */
-	if (tx_flags & IGB_TX_FLAGS_TSO)
-		cmd_type |= cpu_to_le32(E1000_ADVTXD_DCMD_TSE);
+	/* insert frame checksum */
+	cmd_type ^= IGB_SET_FLAG(skb->no_fcs, 1, E1000_ADVTXD_DCMD_IFCS);
 
 	return cmd_type;
 }
@@ -4178,19 +4168,19 @@ static void igb_tx_olinfo_status(struct igb_ring *tx_ring,
 {
 	u32 olinfo_status = paylen << E1000_ADVTXD_PAYLEN_SHIFT;
 
-	/* 82575 requires a unique index per ring if any offload is enabled */
-	if ((tx_flags & (IGB_TX_FLAGS_CSUM | IGB_TX_FLAGS_VLAN)) &&
-	    test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags))
+	/* 82575 requires a unique index per ring */
+	if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags))
 		olinfo_status |= tx_ring->reg_idx << 4;
 
 	/* insert L4 checksum */
-	if (tx_flags & IGB_TX_FLAGS_CSUM) {
-		olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
+	olinfo_status |= IGB_SET_FLAG(tx_flags,
+				      IGB_TX_FLAGS_CSUM,
+				      (E1000_TXD_POPTS_TXSM << 8));
 
-		/* insert IPv4 checksum */
-		if (tx_flags & IGB_TX_FLAGS_IPV4)
-			olinfo_status |= E1000_TXD_POPTS_IXSM << 8;
-	}
+	/* insert IPv4 checksum */
+	olinfo_status |= IGB_SET_FLAG(tx_flags,
+				      IGB_TX_FLAGS_IPV4,
+				      (E1000_TXD_POPTS_IXSM << 8));
 
 	tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
 }
@@ -4209,33 +4199,37 @@ static void igb_tx_map(struct igb_ring *tx_ring,
 	struct sk_buff *skb = first->skb;
 	struct igb_tx_buffer *tx_buffer;
 	union e1000_adv_tx_desc *tx_desc;
+	struct skb_frag_struct *frag;
 	dma_addr_t dma;
-	struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
-	unsigned int data_len = skb->data_len;
-	unsigned int size = skb_headlen(skb);
-	unsigned int paylen = skb->len - hdr_len;
-	__le32 cmd_type;
+	unsigned int data_len, size;
 	u32 tx_flags = first->tx_flags;
+	u32 cmd_type = igb_tx_cmd_type(skb, tx_flags);
 	u16 i = tx_ring->next_to_use;
 
 	tx_desc = IGB_TX_DESC(tx_ring, i);
 
-	igb_tx_olinfo_status(tx_ring, tx_desc, tx_flags, paylen);
-	cmd_type = igb_tx_cmd_type(tx_flags);
+	igb_tx_olinfo_status(tx_ring, tx_desc, tx_flags, skb->len - hdr_len);
+
+	size = skb_headlen(skb);
+	data_len = skb->data_len;
 
 	dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE);
-	if (dma_mapping_error(tx_ring->dev, dma))
-		goto dma_error;
 
-	/* record length, and DMA address */
-	dma_unmap_len_set(first, len, size);
-	dma_unmap_addr_set(first, dma, dma);
-	tx_desc->read.buffer_addr = cpu_to_le64(dma);
+	tx_buffer = first;
+
+	for (frag = &skb_shinfo(skb)->frags[0];; frag++) {
+		if (dma_mapping_error(tx_ring->dev, dma))
+			goto dma_error;
+
+		/* record length, and DMA address */
+		dma_unmap_len_set(tx_buffer, len, size);
+		dma_unmap_addr_set(tx_buffer, dma, dma);
+
+		tx_desc->read.buffer_addr = cpu_to_le64(dma);
 
-	for (;;) {
 		while (unlikely(size > IGB_MAX_DATA_PER_TXD)) {
 			tx_desc->read.cmd_type_len =
-				cmd_type | cpu_to_le32(IGB_MAX_DATA_PER_TXD);
+				cpu_to_le32(cmd_type ^ IGB_MAX_DATA_PER_TXD);
 
 			i++;
 			tx_desc++;
@@ -4243,18 +4237,18 @@ static void igb_tx_map(struct igb_ring *tx_ring,
 				tx_desc = IGB_TX_DESC(tx_ring, 0);
 				i = 0;
 			}
+			tx_desc->read.olinfo_status = 0;
 
 			dma += IGB_MAX_DATA_PER_TXD;
 			size -= IGB_MAX_DATA_PER_TXD;
 
-			tx_desc->read.olinfo_status = 0;
 			tx_desc->read.buffer_addr = cpu_to_le64(dma);
 		}
 
 		if (likely(!data_len))
 			break;
 
-		tx_desc->read.cmd_type_len = cmd_type | cpu_to_le32(size);
+		tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type ^ size);
 
 		i++;
 		tx_desc++;
@@ -4262,32 +4256,22 @@ static void igb_tx_map(struct igb_ring *tx_ring,
 			tx_desc = IGB_TX_DESC(tx_ring, 0);
 			i = 0;
 		}
+		tx_desc->read.olinfo_status = 0;
 
 		size = skb_frag_size(frag);
 		data_len -= size;
 
 		dma = skb_frag_dma_map(tx_ring->dev, frag, 0,
-				   size, DMA_TO_DEVICE);
-		if (dma_mapping_error(tx_ring->dev, dma))
-			goto dma_error;
+				       size, DMA_TO_DEVICE);
 
 		tx_buffer = &tx_ring->tx_buffer_info[i];
-		dma_unmap_len_set(tx_buffer, len, size);
-		dma_unmap_addr_set(tx_buffer, dma, dma);
-
-		tx_desc->read.olinfo_status = 0;
-		tx_desc->read.buffer_addr = cpu_to_le64(dma);
-
-		frag++;
 	}
 
-	netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
-
 	/* write last descriptor with RS and EOP bits */
-	cmd_type |= cpu_to_le32(size) | cpu_to_le32(IGB_TXD_DCMD);
-	if (unlikely(skb->no_fcs))
-		cmd_type &= ~(cpu_to_le32(E1000_ADVTXD_DCMD_IFCS));
-	tx_desc->read.cmd_type_len = cmd_type;
+	cmd_type |= size | IGB_TXD_DCMD;
+	tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type);
+
+	netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
 
 	/* set the timestamp */
 	first->time_stamp = jiffies;
@@ -4372,9 +4356,7 @@ static inline int igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size)
 netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
 				struct igb_ring *tx_ring)
 {
-#ifdef CONFIG_IGB_PTP
 	struct igb_adapter *adapter = netdev_priv(tx_ring->netdev);
-#endif /* CONFIG_IGB_PTP */
 	struct igb_tx_buffer *first;
 	int tso;
 	u32 tx_flags = 0;
@@ -4397,7 +4379,6 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
 	first->bytecount = skb->len;
 	first->gso_segs = 1;
 
-#ifdef CONFIG_IGB_PTP
 	if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
 		     !(adapter->ptp_tx_skb))) {
 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
@@ -4407,7 +4388,6 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
 		if (adapter->hw.mac.type == e1000_82576)
 			schedule_work(&adapter->ptp_tx_work);
 	}
-#endif /* CONFIG_IGB_PTP */
 
 	if (vlan_tx_tag_present(skb)) {
 		tx_flags |= IGB_TX_FLAGS_VLAN;
@@ -4467,10 +4447,11 @@ static netdev_tx_t igb_xmit_frame(struct sk_buff *skb,
 	 * The minimum packet size with TCTL.PSP set is 17 so pad the skb
 	 * in order to meet this minimum size requirement.
 	 */
-	if (skb->len < 17) {
-		if (skb_padto(skb, 17))
+	if (unlikely(skb->len < 17)) {
+		if (skb_pad(skb, 17 - skb->len))
 			return NETDEV_TX_OK;
 		skb->len = 17;
+		skb_set_tail_pointer(skb, 17);
 	}
 
 	return igb_xmit_frame_ring(skb, igb_tx_queue_mapping(adapter, skb));
@@ -4800,7 +4781,6 @@ static irqreturn_t igb_msix_other(int irq, void *data)
 			mod_timer(&adapter->watchdog_timer, jiffies + 1);
 	}
 
-#ifdef CONFIG_IGB_PTP
 	if (icr & E1000_ICR_TS) {
 		u32 tsicr = rd32(E1000_TSICR);
 
@@ -4811,7 +4791,6 @@ static irqreturn_t igb_msix_other(int irq, void *data)
 			schedule_work(&adapter->ptp_tx_work);
 		}
 	}
-#endif /* CONFIG_IGB_PTP */
 
 	wr32(E1000_EIMS, adapter->eims_other);
 
@@ -4851,45 +4830,63 @@ static irqreturn_t igb_msix_ring(int irq, void *data)
 }
 
 #ifdef CONFIG_IGB_DCA
+static void igb_update_tx_dca(struct igb_adapter *adapter,
+			      struct igb_ring *tx_ring,
+			      int cpu)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 txctrl = dca3_get_tag(tx_ring->dev, cpu);
+
+	if (hw->mac.type != e1000_82575)
+		txctrl <<= E1000_DCA_TXCTRL_CPUID_SHIFT;
+
+	/*
+	 * We can enable relaxed ordering for reads, but not writes when
+	 * DCA is enabled.  This is due to a known issue in some chipsets
+	 * which will cause the DCA tag to be cleared.
+	 */
+	txctrl |= E1000_DCA_TXCTRL_DESC_RRO_EN |
+		  E1000_DCA_TXCTRL_DATA_RRO_EN |
+		  E1000_DCA_TXCTRL_DESC_DCA_EN;
+
+	wr32(E1000_DCA_TXCTRL(tx_ring->reg_idx), txctrl);
+}
+
+static void igb_update_rx_dca(struct igb_adapter *adapter,
+			      struct igb_ring *rx_ring,
+			      int cpu)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 rxctrl = dca3_get_tag(&adapter->pdev->dev, cpu);
+
+	if (hw->mac.type != e1000_82575)
+		rxctrl <<= E1000_DCA_RXCTRL_CPUID_SHIFT;
+
+	/*
+	 * We can enable relaxed ordering for reads, but not writes when
+	 * DCA is enabled.  This is due to a known issue in some chipsets
+	 * which will cause the DCA tag to be cleared.
+	 */
+	rxctrl |= E1000_DCA_RXCTRL_DESC_RRO_EN |
+		  E1000_DCA_RXCTRL_DESC_DCA_EN;
+
+	wr32(E1000_DCA_RXCTRL(rx_ring->reg_idx), rxctrl);
+}
+
 static void igb_update_dca(struct igb_q_vector *q_vector)
 {
 	struct igb_adapter *adapter = q_vector->adapter;
-	struct e1000_hw *hw = &adapter->hw;
 	int cpu = get_cpu();
 
 	if (q_vector->cpu == cpu)
 		goto out_no_update;
 
-	if (q_vector->tx.ring) {
-		int q = q_vector->tx.ring->reg_idx;
-		u32 dca_txctrl = rd32(E1000_DCA_TXCTRL(q));
-		if (hw->mac.type == e1000_82575) {
-			dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK;
-			dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
-		} else {
-			dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK_82576;
-			dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) <<
-			              E1000_DCA_TXCTRL_CPUID_SHIFT;
-		}
-		dca_txctrl |= E1000_DCA_TXCTRL_DESC_DCA_EN;
-		wr32(E1000_DCA_TXCTRL(q), dca_txctrl);
-	}
-	if (q_vector->rx.ring) {
-		int q = q_vector->rx.ring->reg_idx;
-		u32 dca_rxctrl = rd32(E1000_DCA_RXCTRL(q));
-		if (hw->mac.type == e1000_82575) {
-			dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK;
-			dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
-		} else {
-			dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK_82576;
-			dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) <<
-			              E1000_DCA_RXCTRL_CPUID_SHIFT;
-		}
-		dca_rxctrl |= E1000_DCA_RXCTRL_DESC_DCA_EN;
-		dca_rxctrl |= E1000_DCA_RXCTRL_HEAD_DCA_EN;
-		dca_rxctrl |= E1000_DCA_RXCTRL_DATA_DCA_EN;
-		wr32(E1000_DCA_RXCTRL(q), dca_rxctrl);
-	}
+	if (q_vector->tx.ring)
+		igb_update_tx_dca(adapter, q_vector->tx.ring, cpu);
+
+	if (q_vector->rx.ring)
+		igb_update_rx_dca(adapter, q_vector->rx.ring, cpu);
+
 	q_vector->cpu = cpu;
 out_no_update:
 	put_cpu();
@@ -5545,7 +5542,6 @@ static irqreturn_t igb_intr_msi(int irq, void *data)
 			mod_timer(&adapter->watchdog_timer, jiffies + 1);
 	}
 
-#ifdef CONFIG_IGB_PTP
 	if (icr & E1000_ICR_TS) {
 		u32 tsicr = rd32(E1000_TSICR);
 
@@ -5556,7 +5552,6 @@ static irqreturn_t igb_intr_msi(int irq, void *data)
 			schedule_work(&adapter->ptp_tx_work);
 		}
 	}
-#endif /* CONFIG_IGB_PTP */
 
 	napi_schedule(&q_vector->napi);
 
@@ -5599,7 +5594,6 @@ static irqreturn_t igb_intr(int irq, void *data)
 			mod_timer(&adapter->watchdog_timer, jiffies + 1);
 	}
 
-#ifdef CONFIG_IGB_PTP
 	if (icr & E1000_ICR_TS) {
 		u32 tsicr = rd32(E1000_TSICR);
 
@@ -5610,7 +5604,6 @@ static irqreturn_t igb_intr(int irq, void *data)
 			schedule_work(&adapter->ptp_tx_work);
 		}
 	}
-#endif /* CONFIG_IGB_PTP */
 
 	napi_schedule(&q_vector->napi);
 
@@ -5840,6 +5833,181 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
 	return !!budget;
 }
 
+/**
+ * igb_reuse_rx_page - page flip buffer and store it back on the ring
+ * @rx_ring: rx descriptor ring to store buffers on
+ * @old_buff: donor buffer to have page reused
+ *
+ * Synchronizes page for reuse by the adapter
+ **/
+static void igb_reuse_rx_page(struct igb_ring *rx_ring,
+			      struct igb_rx_buffer *old_buff)
+{
+	struct igb_rx_buffer *new_buff;
+	u16 nta = rx_ring->next_to_alloc;
+
+	new_buff = &rx_ring->rx_buffer_info[nta];
+
+	/* update, and store next to alloc */
+	nta++;
+	rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0;
+
+	/* transfer page from old buffer to new buffer */
+	memcpy(new_buff, old_buff, sizeof(struct igb_rx_buffer));
+
+	/* sync the buffer for use by the device */
+	dma_sync_single_range_for_device(rx_ring->dev, old_buff->dma,
+					 old_buff->page_offset,
+					 IGB_RX_BUFSZ,
+					 DMA_FROM_DEVICE);
+}
+
+/**
+ * igb_add_rx_frag - Add contents of Rx buffer to sk_buff
+ * @rx_ring: rx descriptor ring to transact packets on
+ * @rx_buffer: buffer containing page to add
+ * @rx_desc: descriptor containing length of buffer written by hardware
+ * @skb: sk_buff to place the data into
+ *
+ * This function will add the data contained in rx_buffer->page to the skb.
+ * This is done either through a direct copy if the data in the buffer is
+ * less than the skb header size, otherwise it will just attach the page as
+ * a frag to the skb.
+ *
+ * The function will then update the page offset if necessary and return
+ * true if the buffer can be reused by the adapter.
+ **/
+static bool igb_add_rx_frag(struct igb_ring *rx_ring,
+			    struct igb_rx_buffer *rx_buffer,
+			    union e1000_adv_rx_desc *rx_desc,
+			    struct sk_buff *skb)
+{
+	struct page *page = rx_buffer->page;
+	unsigned int size = le16_to_cpu(rx_desc->wb.upper.length);
+
+	if ((size <= IGB_RX_HDR_LEN) && !skb_is_nonlinear(skb)) {
+		unsigned char *va = page_address(page) + rx_buffer->page_offset;
+
+		if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
+			igb_ptp_rx_pktstamp(rx_ring->q_vector, va, skb);
+			va += IGB_TS_HDR_LEN;
+			size -= IGB_TS_HDR_LEN;
+		}
+
+		memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long)));
+
+		/* we can reuse buffer as-is, just make sure it is local */
+		if (likely(page_to_nid(page) == numa_node_id()))
+			return true;
+
+		/* this page cannot be reused so discard it */
+		put_page(page);
+		return false;
+	}
+
+	skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
+			rx_buffer->page_offset, size, IGB_RX_BUFSZ);
+
+	/* avoid re-using remote pages */
+	if (unlikely(page_to_nid(page) != numa_node_id()))
+		return false;
+
+#if (PAGE_SIZE < 8192)
+	/* if we are only owner of page we can reuse it */
+	if (unlikely(page_count(page) != 1))
+		return false;
+
+	/* flip page offset to other buffer */
+	rx_buffer->page_offset ^= IGB_RX_BUFSZ;
+
+	/*
+	 * since we are the only owner of the page and we need to
+	 * increment it, just set the value to 2 in order to avoid
+	 * an unnecessary locked operation
+	 */
+	atomic_set(&page->_count, 2);
+#else
+	/* move offset up to the next cache line */
+	rx_buffer->page_offset += SKB_DATA_ALIGN(size);
+
+	if (rx_buffer->page_offset > (PAGE_SIZE - IGB_RX_BUFSZ))
+		return false;
+
+	/* bump ref count on page before it is given to the stack */
+	get_page(page);
+#endif
+
+	return true;
+}
+
+static struct sk_buff *igb_fetch_rx_buffer(struct igb_ring *rx_ring,
+					   union e1000_adv_rx_desc *rx_desc,
+					   struct sk_buff *skb)
+{
+	struct igb_rx_buffer *rx_buffer;
+	struct page *page;
+
+	rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean];
+
+	/*
+	 * This memory barrier is needed to keep us from reading
+	 * any other fields out of the rx_desc until we know the
+	 * RXD_STAT_DD bit is set
+	 */
+	rmb();
+
+	page = rx_buffer->page;
+	prefetchw(page);
+
+	if (likely(!skb)) {
+		void *page_addr = page_address(page) +
+				  rx_buffer->page_offset;
+
+		/* prefetch first cache line of first page */
+		prefetch(page_addr);
+#if L1_CACHE_BYTES < 128
+		prefetch(page_addr + L1_CACHE_BYTES);
+#endif
+
+		/* allocate a skb to store the frags */
+		skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
+						IGB_RX_HDR_LEN);
+		if (unlikely(!skb)) {
+			rx_ring->rx_stats.alloc_failed++;
+			return NULL;
+		}
+
+		/*
+		 * we will be copying header into skb->data in
+		 * pskb_may_pull so it is in our interest to prefetch
+		 * it now to avoid a possible cache miss
+		 */
+		prefetchw(skb->data);
+	}
+
+	/* we are reusing so sync this buffer for CPU use */
+	dma_sync_single_range_for_cpu(rx_ring->dev,
+				      rx_buffer->dma,
+				      rx_buffer->page_offset,
+				      IGB_RX_BUFSZ,
+				      DMA_FROM_DEVICE);
+
+	/* pull page into skb */
+	if (igb_add_rx_frag(rx_ring, rx_buffer, rx_desc, skb)) {
+		/* hand second half of page back to the ring */
+		igb_reuse_rx_page(rx_ring, rx_buffer);
+	} else {
+		/* we are not reusing the buffer so unmap it */
+		dma_unmap_page(rx_ring->dev, rx_buffer->dma,
+			       PAGE_SIZE, DMA_FROM_DEVICE);
+	}
+
+	/* clear contents of rx_buffer */
+	rx_buffer->page = NULL;
+
+	return skb;
+}
+
 static inline void igb_rx_checksum(struct igb_ring *ring,
 				   union e1000_adv_rx_desc *rx_desc,
 				   struct sk_buff *skb)
@@ -5889,224 +6057,389 @@ static inline void igb_rx_hash(struct igb_ring *ring,
 		skb->rxhash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
 }
 
-static void igb_rx_vlan(struct igb_ring *ring,
-			union e1000_adv_rx_desc *rx_desc,
-			struct sk_buff *skb)
+/**
+ * igb_is_non_eop - process handling of non-EOP buffers
+ * @rx_ring: Rx ring being processed
+ * @rx_desc: Rx descriptor for current buffer
+ * @skb: current socket buffer containing buffer in progress
+ *
+ * This function updates next to clean.  If the buffer is an EOP buffer
+ * this function exits returning false, otherwise it will place the
+ * sk_buff in the next buffer to be chained and return true indicating
+ * that this is in fact a non-EOP buffer.
+ **/
+static bool igb_is_non_eop(struct igb_ring *rx_ring,
+			   union e1000_adv_rx_desc *rx_desc)
 {
-	if (igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) {
-		u16 vid;
-		if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) &&
-		    test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags))
-			vid = be16_to_cpu(rx_desc->wb.upper.vlan);
-		else
-			vid = le16_to_cpu(rx_desc->wb.upper.vlan);
+	u32 ntc = rx_ring->next_to_clean + 1;
 
-		__vlan_hwaccel_put_tag(skb, vid);
-	}
+	/* fetch, update, and store next to clean */
+	ntc = (ntc < rx_ring->count) ? ntc : 0;
+	rx_ring->next_to_clean = ntc;
+
+	prefetch(IGB_RX_DESC(rx_ring, ntc));
+
+	if (likely(igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP)))
+		return false;
+
+	return true;
 }
 
-static inline u16 igb_get_hlen(union e1000_adv_rx_desc *rx_desc)
-{
-	/* HW will not DMA in data larger than the given buffer, even if it
-	 * parses the (NFS, of course) header to be larger.  In that case, it
-	 * fills the header buffer and spills the rest into the page.
+/**
+ * igb_get_headlen - determine size of header for LRO/GRO
+ * @data: pointer to the start of the headers
+ * @max_len: total length of section to find headers in
+ *
+ * This function is meant to determine the length of headers that will
+ * be recognized by hardware for LRO, and GRO offloads.  The main
+ * motivation of doing this is to only perform one pull for IPv4 TCP
+ * packets so that we can do basic things like calculating the gso_size
+ * based on the average data per packet.
+ **/
+static unsigned int igb_get_headlen(unsigned char *data,
+				    unsigned int max_len)
+{
+	union {
+		unsigned char *network;
+		/* l2 headers */
+		struct ethhdr *eth;
+		struct vlan_hdr *vlan;
+		/* l3 headers */
+		struct iphdr *ipv4;
+		struct ipv6hdr *ipv6;
+	} hdr;
+	__be16 protocol;
+	u8 nexthdr = 0;	/* default to not TCP */
+	u8 hlen;
+
+	/* this should never happen, but better safe than sorry */
+	if (max_len < ETH_HLEN)
+		return max_len;
+
+	/* initialize network frame pointer */
+	hdr.network = data;
+
+	/* set first protocol and move network header forward */
+	protocol = hdr.eth->h_proto;
+	hdr.network += ETH_HLEN;
+
+	/* handle any vlan tag if present */
+	if (protocol == __constant_htons(ETH_P_8021Q)) {
+		if ((hdr.network - data) > (max_len - VLAN_HLEN))
+			return max_len;
+
+		protocol = hdr.vlan->h_vlan_encapsulated_proto;
+		hdr.network += VLAN_HLEN;
+	}
+
+	/* handle L3 protocols */
+	if (protocol == __constant_htons(ETH_P_IP)) {
+		if ((hdr.network - data) > (max_len - sizeof(struct iphdr)))
+			return max_len;
+
+		/* access ihl as a u8 to avoid unaligned access on ia64 */
+		hlen = (hdr.network[0] & 0x0F) << 2;
+
+		/* verify hlen meets minimum size requirements */
+		if (hlen < sizeof(struct iphdr))
+			return hdr.network - data;
+
+		/* record next protocol if header is present */
+		if (!hdr.ipv4->frag_off)
+			nexthdr = hdr.ipv4->protocol;
+	} else if (protocol == __constant_htons(ETH_P_IPV6)) {
+		if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr)))
+			return max_len;
+
+		/* record next protocol */
+		nexthdr = hdr.ipv6->nexthdr;
+		hlen = sizeof(struct ipv6hdr);
+	} else {
+		return hdr.network - data;
+	}
+
+	/* relocate pointer to start of L4 header */
+	hdr.network += hlen;
+
+	/* finally sort out TCP */
+	if (nexthdr == IPPROTO_TCP) {
+		if ((hdr.network - data) > (max_len - sizeof(struct tcphdr)))
+			return max_len;
+
+		/* access doff as a u8 to avoid unaligned access on ia64 */
+		hlen = (hdr.network[12] & 0xF0) >> 2;
+
+		/* verify hlen meets minimum size requirements */
+		if (hlen < sizeof(struct tcphdr))
+			return hdr.network - data;
+
+		hdr.network += hlen;
+	} else if (nexthdr == IPPROTO_UDP) {
+		if ((hdr.network - data) > (max_len - sizeof(struct udphdr)))
+			return max_len;
+
+		hdr.network += sizeof(struct udphdr);
+	}
+
+	/*
+	 * If everything has gone correctly hdr.network should be the
+	 * data section of the packet and will be the end of the header.
+	 * If not then it probably represents the end of the last recognized
+	 * header.
 	 */
-	u16 hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) &
-	           E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT;
-	if (hlen > IGB_RX_HDR_LEN)
-		hlen = IGB_RX_HDR_LEN;
-	return hlen;
+	if ((hdr.network - data) < max_len)
+		return hdr.network - data;
+	else
+		return max_len;
 }
 
-static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget)
+/**
+ * igb_pull_tail - igb specific version of skb_pull_tail
+ * @rx_ring: rx descriptor ring packet is being transacted on
+ * @rx_desc: pointer to the EOP Rx descriptor
+ * @skb: pointer to current skb being adjusted
+ *
+ * This function is an igb specific version of __pskb_pull_tail.  The
+ * main difference between this version and the original function is that
+ * this function can make several assumptions about the state of things
+ * that allow for significant optimizations versus the standard function.
+ * As a result we can do things like drop a frag and maintain an accurate
+ * truesize for the skb.
+ */
+static void igb_pull_tail(struct igb_ring *rx_ring,
+			  union e1000_adv_rx_desc *rx_desc,
+			  struct sk_buff *skb)
 {
-	struct igb_ring *rx_ring = q_vector->rx.ring;
-	union e1000_adv_rx_desc *rx_desc;
-	const int current_node = numa_node_id();
-	unsigned int total_bytes = 0, total_packets = 0;
-	u16 cleaned_count = igb_desc_unused(rx_ring);
-	u16 i = rx_ring->next_to_clean;
+	struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
+	unsigned char *va;
+	unsigned int pull_len;
 
-	rx_desc = IGB_RX_DESC(rx_ring, i);
+	/*
+	 * it is valid to use page_address instead of kmap since we are
+	 * working with pages allocated out of the lomem pool per
+	 * alloc_page(GFP_ATOMIC)
+	 */
+	va = skb_frag_address(frag);
 
-	while (igb_test_staterr(rx_desc, E1000_RXD_STAT_DD)) {
-		struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i];
-		struct sk_buff *skb = buffer_info->skb;
-		union e1000_adv_rx_desc *next_rxd;
+	if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
+		/* retrieve timestamp from buffer */
+		igb_ptp_rx_pktstamp(rx_ring->q_vector, va, skb);
 
-		buffer_info->skb = NULL;
-		prefetch(skb->data);
+		/* update pointers to remove timestamp header */
+		skb_frag_size_sub(frag, IGB_TS_HDR_LEN);
+		frag->page_offset += IGB_TS_HDR_LEN;
+		skb->data_len -= IGB_TS_HDR_LEN;
+		skb->len -= IGB_TS_HDR_LEN;
 
-		i++;
-		if (i == rx_ring->count)
-			i = 0;
+		/* move va to start of packet data */
+		va += IGB_TS_HDR_LEN;
+	}
 
-		next_rxd = IGB_RX_DESC(rx_ring, i);
-		prefetch(next_rxd);
+	/*
+	 * we need the header to contain the greater of either ETH_HLEN or
+	 * 60 bytes if the skb->len is less than 60 for skb_pad.
+	 */
+	pull_len = igb_get_headlen(va, IGB_RX_HDR_LEN);
 
-		/*
-		 * This memory barrier is needed to keep us from reading
-		 * any other fields out of the rx_desc until we know the
-		 * RXD_STAT_DD bit is set
-		 */
-		rmb();
+	/* align pull length to size of long to optimize memcpy performance */
+	skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long)));
 
-		if (!skb_is_nonlinear(skb)) {
-			__skb_put(skb, igb_get_hlen(rx_desc));
-			dma_unmap_single(rx_ring->dev, buffer_info->dma,
-					 IGB_RX_HDR_LEN,
-					 DMA_FROM_DEVICE);
-			buffer_info->dma = 0;
+	/* update all of the pointers */
+	skb_frag_size_sub(frag, pull_len);
+	frag->page_offset += pull_len;
+	skb->data_len -= pull_len;
+	skb->tail += pull_len;
+}
+
+/**
+ * igb_cleanup_headers - Correct corrupted or empty headers
+ * @rx_ring: rx descriptor ring packet is being transacted on
+ * @rx_desc: pointer to the EOP Rx descriptor
+ * @skb: pointer to current skb being fixed
+ *
+ * Address the case where we are pulling data in on pages only
+ * and as such no data is present in the skb header.
+ *
+ * In addition if skb is not at least 60 bytes we need to pad it so that
+ * it is large enough to qualify as a valid Ethernet frame.
+ *
+ * Returns true if an error was encountered and skb was freed.
+ **/
+static bool igb_cleanup_headers(struct igb_ring *rx_ring,
+				union e1000_adv_rx_desc *rx_desc,
+				struct sk_buff *skb)
+{
+
+	if (unlikely((igb_test_staterr(rx_desc,
+				       E1000_RXDEXT_ERR_FRAME_ERR_MASK)))) {
+		struct net_device *netdev = rx_ring->netdev;
+		if (!(netdev->features & NETIF_F_RXALL)) {
+			dev_kfree_skb_any(skb);
+			return true;
 		}
+	}
+
+	/* place header in linear portion of buffer */
+	if (skb_is_nonlinear(skb))
+		igb_pull_tail(rx_ring, rx_desc, skb);
 
-		if (rx_desc->wb.upper.length) {
-			u16 length = le16_to_cpu(rx_desc->wb.upper.length);
+	/* if skb_pad returns an error the skb was freed */
+	if (unlikely(skb->len < 60)) {
+		int pad_len = 60 - skb->len;
 
-			skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
-						buffer_info->page,
-						buffer_info->page_offset,
-						length);
+		if (skb_pad(skb, pad_len))
+			return true;
+		__skb_put(skb, pad_len);
+	}
 
-			skb->len += length;
-			skb->data_len += length;
-			skb->truesize += PAGE_SIZE / 2;
+	return false;
+}
 
-			if ((page_count(buffer_info->page) != 1) ||
-			    (page_to_nid(buffer_info->page) != current_node))
-				buffer_info->page = NULL;
-			else
-				get_page(buffer_info->page);
+/**
+ * igb_process_skb_fields - Populate skb header fields from Rx descriptor
+ * @rx_ring: rx descriptor ring packet is being transacted on
+ * @rx_desc: pointer to the EOP Rx descriptor
+ * @skb: pointer to current skb being populated
+ *
+ * This function checks the ring, descriptor, and packet information in
+ * order to populate the hash, checksum, VLAN, timestamp, protocol, and
+ * other fields within the skb.
+ **/
+static void igb_process_skb_fields(struct igb_ring *rx_ring,
+				   union e1000_adv_rx_desc *rx_desc,
+				   struct sk_buff *skb)
+{
+	struct net_device *dev = rx_ring->netdev;
 
-			dma_unmap_page(rx_ring->dev, buffer_info->page_dma,
-				       PAGE_SIZE / 2, DMA_FROM_DEVICE);
-			buffer_info->page_dma = 0;
-		}
+	igb_rx_hash(rx_ring, rx_desc, skb);
 
-		if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP)) {
-			struct igb_rx_buffer *next_buffer;
-			next_buffer = &rx_ring->rx_buffer_info[i];
-			buffer_info->skb = next_buffer->skb;
-			buffer_info->dma = next_buffer->dma;
-			next_buffer->skb = skb;
-			next_buffer->dma = 0;
-			goto next_desc;
-		}
+	igb_rx_checksum(rx_ring, rx_desc, skb);
 
-		if (unlikely((igb_test_staterr(rx_desc,
-					       E1000_RXDEXT_ERR_FRAME_ERR_MASK))
-			     && !(rx_ring->netdev->features & NETIF_F_RXALL))) {
-			dev_kfree_skb_any(skb);
-			goto next_desc;
-		}
+	igb_ptp_rx_hwtstamp(rx_ring->q_vector, rx_desc, skb);
 
-#ifdef CONFIG_IGB_PTP
-		igb_ptp_rx_hwtstamp(q_vector, rx_desc, skb);
-#endif /* CONFIG_IGB_PTP */
-		igb_rx_hash(rx_ring, rx_desc, skb);
-		igb_rx_checksum(rx_ring, rx_desc, skb);
-		igb_rx_vlan(rx_ring, rx_desc, skb);
+	if ((dev->features & NETIF_F_HW_VLAN_RX) &&
+	    igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) {
+		u16 vid;
+		if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) &&
+		    test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &rx_ring->flags))
+			vid = be16_to_cpu(rx_desc->wb.upper.vlan);
+		else
+			vid = le16_to_cpu(rx_desc->wb.upper.vlan);
 
-		total_bytes += skb->len;
-		total_packets++;
+		__vlan_hwaccel_put_tag(skb, vid);
+	}
 
-		skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+	skb_record_rx_queue(skb, rx_ring->queue_index);
 
-		napi_gro_receive(&q_vector->napi, skb);
+	skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+}
 
-		budget--;
-next_desc:
-		if (!budget)
-			break;
+static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
+{
+	struct igb_ring *rx_ring = q_vector->rx.ring;
+	struct sk_buff *skb = rx_ring->skb;
+	unsigned int total_bytes = 0, total_packets = 0;
+	u16 cleaned_count = igb_desc_unused(rx_ring);
+
+	do {
+		union e1000_adv_rx_desc *rx_desc;
 
-		cleaned_count++;
 		/* return some buffers to hardware, one at a time is too slow */
 		if (cleaned_count >= IGB_RX_BUFFER_WRITE) {
 			igb_alloc_rx_buffers(rx_ring, cleaned_count);
 			cleaned_count = 0;
 		}
 
-		/* use prefetched values */
-		rx_desc = next_rxd;
-	}
+		rx_desc = IGB_RX_DESC(rx_ring, rx_ring->next_to_clean);
 
-	rx_ring->next_to_clean = i;
-	u64_stats_update_begin(&rx_ring->rx_syncp);
-	rx_ring->rx_stats.packets += total_packets;
-	rx_ring->rx_stats.bytes += total_bytes;
-	u64_stats_update_end(&rx_ring->rx_syncp);
-	q_vector->rx.total_packets += total_packets;
-	q_vector->rx.total_bytes += total_bytes;
+		if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_DD))
+			break;
 
-	if (cleaned_count)
-		igb_alloc_rx_buffers(rx_ring, cleaned_count);
+		/* retrieve a buffer from the ring */
+		skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb);
 
-	return !!budget;
-}
+		/* exit if we failed to retrieve a buffer */
+		if (!skb)
+			break;
 
-static bool igb_alloc_mapped_skb(struct igb_ring *rx_ring,
-				 struct igb_rx_buffer *bi)
-{
-	struct sk_buff *skb = bi->skb;
-	dma_addr_t dma = bi->dma;
+		cleaned_count++;
 
-	if (dma)
-		return true;
+		/* fetch next buffer in frame if non-eop */
+		if (igb_is_non_eop(rx_ring, rx_desc))
+			continue;
 
-	if (likely(!skb)) {
-		skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
-						IGB_RX_HDR_LEN);
-		bi->skb = skb;
-		if (!skb) {
-			rx_ring->rx_stats.alloc_failed++;
-			return false;
+		/* verify the packet layout is correct */
+		if (igb_cleanup_headers(rx_ring, rx_desc, skb)) {
+			skb = NULL;
+			continue;
 		}
 
-		/* initialize skb for ring */
-		skb_record_rx_queue(skb, rx_ring->queue_index);
-	}
+		/* probably a little skewed due to removing CRC */
+		total_bytes += skb->len;
 
-	dma = dma_map_single(rx_ring->dev, skb->data,
-			     IGB_RX_HDR_LEN, DMA_FROM_DEVICE);
+		/* populate checksum, timestamp, VLAN, and protocol */
+		igb_process_skb_fields(rx_ring, rx_desc, skb);
 
-	if (dma_mapping_error(rx_ring->dev, dma)) {
-		rx_ring->rx_stats.alloc_failed++;
-		return false;
-	}
+		napi_gro_receive(&q_vector->napi, skb);
 
-	bi->dma = dma;
-	return true;
+		/* reset skb pointer */
+		skb = NULL;
+
+		/* update budget accounting */
+		total_packets++;
+	} while (likely(total_packets < budget));
+
+	/* place incomplete frames back on ring for completion */
+	rx_ring->skb = skb;
+
+	u64_stats_update_begin(&rx_ring->rx_syncp);
+	rx_ring->rx_stats.packets += total_packets;
+	rx_ring->rx_stats.bytes += total_bytes;
+	u64_stats_update_end(&rx_ring->rx_syncp);
+	q_vector->rx.total_packets += total_packets;
+	q_vector->rx.total_bytes += total_bytes;
+
+	if (cleaned_count)
+		igb_alloc_rx_buffers(rx_ring, cleaned_count);
+
+	return (total_packets < budget);
 }
 
 static bool igb_alloc_mapped_page(struct igb_ring *rx_ring,
 				  struct igb_rx_buffer *bi)
 {
 	struct page *page = bi->page;
-	dma_addr_t page_dma = bi->page_dma;
-	unsigned int page_offset = bi->page_offset ^ (PAGE_SIZE / 2);
+	dma_addr_t dma;
 
-	if (page_dma)
+	/* since we are recycling buffers we should seldom need to alloc */
+	if (likely(page))
 		return true;
 
-	if (!page) {
-		page = __skb_alloc_page(GFP_ATOMIC, bi->skb);
-		bi->page = page;
-		if (unlikely(!page)) {
-			rx_ring->rx_stats.alloc_failed++;
-			return false;
-		}
+	/* alloc new page for storage */
+	page = __skb_alloc_page(GFP_ATOMIC | __GFP_COLD, NULL);
+	if (unlikely(!page)) {
+		rx_ring->rx_stats.alloc_failed++;
+		return false;
 	}
 
-	page_dma = dma_map_page(rx_ring->dev, page,
-				page_offset, PAGE_SIZE / 2,
-				DMA_FROM_DEVICE);
+	/* map page for use */
+	dma = dma_map_page(rx_ring->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE);
+
+	/*
+	 * if mapping failed free memory back to system since
+	 * there isn't much point in holding memory we can't use
+	 */
+	if (dma_mapping_error(rx_ring->dev, dma)) {
+		__free_page(page);
 
-	if (dma_mapping_error(rx_ring->dev, page_dma)) {
 		rx_ring->rx_stats.alloc_failed++;
 		return false;
 	}
 
-	bi->page_dma = page_dma;
-	bi->page_offset = page_offset;
+	bi->dma = dma;
+	bi->page = page;
+	bi->page_offset = 0;
+
 	return true;
 }
 
@@ -6120,22 +6453,23 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)
 	struct igb_rx_buffer *bi;
 	u16 i = rx_ring->next_to_use;
 
+	/* nothing to do */
+	if (!cleaned_count)
+		return;
+
 	rx_desc = IGB_RX_DESC(rx_ring, i);
 	bi = &rx_ring->rx_buffer_info[i];
 	i -= rx_ring->count;
 
-	while (cleaned_count--) {
-		if (!igb_alloc_mapped_skb(rx_ring, bi))
-			break;
-
-		/* Refresh the desc even if buffer_addrs didn't change
-		 * because each write-back erases this info. */
-		rx_desc->read.hdr_addr = cpu_to_le64(bi->dma);
-
+	do {
 		if (!igb_alloc_mapped_page(rx_ring, bi))
 			break;
 
-		rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma);
+		/*
+		 * Refresh the desc even if buffer_addrs didn't change
+		 * because each write-back erases this info.
+		 */
+		rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
 
 		rx_desc++;
 		bi++;
@@ -6148,17 +6482,25 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)
 
 		/* clear the hdr_addr for the next_to_use descriptor */
 		rx_desc->read.hdr_addr = 0;
-	}
+
+		cleaned_count--;
+	} while (cleaned_count);
 
 	i += rx_ring->count;
 
 	if (rx_ring->next_to_use != i) {
+		/* record the next descriptor to use */
 		rx_ring->next_to_use = i;
 
-		/* Force memory writes to complete before letting h/w
+		/* update next to alloc since we have filled the ring */
+		rx_ring->next_to_alloc = i;
+
+		/*
+		 * Force memory writes to complete before letting h/w
 		 * know there are new descriptors to fetch.  (Only
 		 * applicable for weak-ordered memory model archs,
-		 * such as IA-64). */
+		 * such as IA-64).
+		 */
 		wmb();
 		writel(i, rx_ring->tail);
 	}
@@ -6207,10 +6549,8 @@ static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 	case SIOCGMIIREG:
 	case SIOCSMIIREG:
 		return igb_mii_ioctl(netdev, ifr, cmd);
-#ifdef CONFIG_IGB_PTP
 	case SIOCSHWTSTAMP:
 		return igb_ptp_hwtstamp_ioctl(netdev, ifr, cmd);
-#endif /* CONFIG_IGB_PTP */
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -6492,7 +6832,9 @@ static int igb_resume(struct device *dev)
 	wr32(E1000_WUS, ~0);
 
 	if (netdev->flags & IFF_UP) {
+		rtnl_lock();
 		err = __igb_open(netdev, true);
+		rtnl_unlock();
 		if (err)
 			return err;
 	}
diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c
index ee21445..ab34297 100644
--- a/drivers/net/ethernet/intel/igb/igb_ptp.c
+++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
@@ -441,18 +441,46 @@ void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)
 	adapter->ptp_tx_skb = NULL;
 }
 
-void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
-			 union e1000_adv_rx_desc *rx_desc,
+/**
+ * igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp
+ * @q_vector: Pointer to interrupt specific structure
+ * @va: Pointer to address containing Rx buffer
+ * @skb: Buffer containing timestamp and packet
+ *
+ * This function is meant to retrieve a timestamp from the first buffer of an
+ * incoming frame.  The value is stored in little endian format starting on
+ * byte 8.
+ */
+void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector,
+			 unsigned char *va,
+			 struct sk_buff *skb)
+{
+	__le64 *regval = (__le64 *)va;
+
+	/*
+	 * The timestamp is recorded in little endian format.
+	 * DWORD: 0        1        2        3
+	 * Field: Reserved Reserved SYSTIML  SYSTIMH
+	 */
+	igb_ptp_systim_to_hwtstamp(q_vector->adapter, skb_hwtstamps(skb),
+				   le64_to_cpu(regval[1]));
+}
+
+/**
+ * igb_ptp_rx_rgtstamp - retrieve Rx timestamp stored in register
+ * @q_vector: Pointer to interrupt specific structure
+ * @skb: Buffer containing timestamp and packet
+ *
+ * This function is meant to retrieve a timestamp from the internal registers
+ * of the adapter and store it in the skb.
+ */
+void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
 			 struct sk_buff *skb)
 {
 	struct igb_adapter *adapter = q_vector->adapter;
 	struct e1000_hw *hw = &adapter->hw;
 	u64 regval;
 
-	if (!igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP |
-				       E1000_RXDADV_STAT_TS))
-		return;
-
 	/*
 	 * If this bit is set, then the RX registers contain the time stamp. No
 	 * other packet will be time stamped until we read these registers, so
@@ -464,18 +492,11 @@ void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
 	 * If nothing went wrong, then it should have a shared tx_flags that we
 	 * can turn into a skb_shared_hwtstamps.
 	 */
-	if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
-		u32 *stamp = (u32 *)skb->data;
-		regval = le32_to_cpu(*(stamp + 2));
-		regval |= (u64)le32_to_cpu(*(stamp + 3)) << 32;
-		skb_pull(skb, IGB_TS_HDR_LEN);
-	} else {
-		if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
-			return;
+	if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
+		return;
 
-		regval = rd32(E1000_RXSTMPL);
-		regval |= (u64)rd32(E1000_RXSTMPH) << 32;
-	}
+	regval = rd32(E1000_RXSTMPL);
+	regval |= (u64)rd32(E1000_RXSTMPH) << 32;
 
 	igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
 }
@@ -532,18 +553,6 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
 	case HWTSTAMP_FILTER_NONE:
 		tsync_rx_ctl = 0;
 		break;
-	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
-	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
-	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
-	case HWTSTAMP_FILTER_ALL:
-		/*
-		 * register TSYNCRXCFG must be set, therefore it is not
-		 * possible to time stamp both Sync and Delay_Req messages
-		 * => fall back to time stamping all packets
-		 */
-		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL;
-		config.rx_filter = HWTSTAMP_FILTER_ALL;
-		break;
 	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
 		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1;
 		tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE;
@@ -554,31 +563,33 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
 		tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE;
 		is_l4 = true;
 		break;
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
 	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
 	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
-		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
-		tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE;
-		is_l2 = true;
-		is_l4 = true;
-		config.rx_filter = HWTSTAMP_FILTER_SOME;
-		break;
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
 	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
 	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
-		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
-		tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE;
-		is_l2 = true;
-		is_l4 = true;
-		config.rx_filter = HWTSTAMP_FILTER_SOME;
-		break;
-	case HWTSTAMP_FILTER_PTP_V2_EVENT:
-	case HWTSTAMP_FILTER_PTP_V2_SYNC:
-	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
 		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2;
 		config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
 		is_l2 = true;
 		is_l4 = true;
 		break;
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_ALL:
+		/* 82576 cannot timestamp all packets, which it needs to do to
+		 * support both V1 Sync and Delay_Req messages
+		 */
+		if (hw->mac.type != e1000_82576) {
+			tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL;
+			config.rx_filter = HWTSTAMP_FILTER_ALL;
+			break;
+		}
+		/* fall through */
 	default:
+		config.rx_filter = HWTSTAMP_FILTER_NONE;
 		return -ERANGE;
 	}
 
@@ -596,6 +607,9 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
 	if ((hw->mac.type >= e1000_82580) && tsync_rx_ctl) {
 		tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED;
 		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL;
+		config.rx_filter = HWTSTAMP_FILTER_ALL;
+		is_l2 = true;
+		is_l4 = true;
 
 		if ((hw->mac.type == e1000_i210) ||
 		    (hw->mac.type == e1000_i211)) {
diff --git a/drivers/net/ethernet/intel/igbvf/defines.h b/drivers/net/ethernet/intel/igbvf/defines.h
index 3e18045..d9fa999 100644
--- a/drivers/net/ethernet/intel/igbvf/defines.h
+++ b/drivers/net/ethernet/intel/igbvf/defines.h
@@ -46,6 +46,7 @@
 #define E1000_RXD_ERR_SE        0x02    /* Symbol Error */
 #define E1000_RXD_SPC_VLAN_MASK 0x0FFF  /* VLAN ID is in lower 12 bits */
 
+#define E1000_RXDEXT_STATERR_LB    0x00040000
 #define E1000_RXDEXT_STATERR_CE    0x01000000
 #define E1000_RXDEXT_STATERR_SE    0x02000000
 #define E1000_RXDEXT_STATERR_SEQ   0x04000000
diff --git a/drivers/net/ethernet/intel/igbvf/igbvf.h b/drivers/net/ethernet/intel/igbvf/igbvf.h
index a895e2f..fdca7b6 100644
--- a/drivers/net/ethernet/intel/igbvf/igbvf.h
+++ b/drivers/net/ethernet/intel/igbvf/igbvf.h
@@ -295,7 +295,7 @@ struct igbvf_info {
 
 /* hardware capability, feature, and workaround flags */
 #define IGBVF_FLAG_RX_CSUM_DISABLED             (1 << 0)
-
+#define IGBVF_FLAG_RX_LB_VLAN_BSWAP		(1 << 1)
 #define IGBVF_RX_DESC_ADV(R, i)     \
 	(&((((R).desc))[i].rx_desc))
 #define IGBVF_TX_DESC_ADV(R, i)     \
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 0ac11f5..3d92ad8 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -47,7 +47,7 @@
 
 #include "igbvf.h"
 
-#define DRV_VERSION "2.0.1-k"
+#define DRV_VERSION "2.0.2-k"
 char igbvf_driver_name[] = "igbvf";
 const char igbvf_driver_version[] = DRV_VERSION;
 static const char igbvf_driver_string[] =
@@ -107,12 +107,19 @@ static void igbvf_receive_skb(struct igbvf_adapter *adapter,
                               struct sk_buff *skb,
                               u32 status, u16 vlan)
 {
+	u16 vid;
+
 	if (status & E1000_RXD_STAT_VP) {
-		u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
+		if ((adapter->flags & IGBVF_FLAG_RX_LB_VLAN_BSWAP) &&
+		    (status & E1000_RXDEXT_STATERR_LB))
+			vid = be16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
+		else
+			vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
 		if (test_bit(vid, adapter->active_vlans))
 			__vlan_hwaccel_put_tag(skb, vid);
 	}
-	netif_receive_skb(skb);
+
+	napi_gro_receive(&adapter->rx_ring->napi, skb);
 }
 
 static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter,
@@ -184,6 +191,13 @@ static void igbvf_alloc_rx_buffers(struct igbvf_ring *rx_ring,
 				             buffer_info->page_offset,
 				             PAGE_SIZE / 2,
 					     DMA_FROM_DEVICE);
+			if (dma_mapping_error(&pdev->dev,
+					      buffer_info->page_dma)) {
+				__free_page(buffer_info->page);
+				buffer_info->page = NULL;
+				dev_err(&pdev->dev, "RX DMA map failed\n");
+				break;
+			}
 		}
 
 		if (!buffer_info->skb) {
@@ -197,6 +211,12 @@ static void igbvf_alloc_rx_buffers(struct igbvf_ring *rx_ring,
 			buffer_info->dma = dma_map_single(&pdev->dev, skb->data,
 			                                  bufsz,
 							  DMA_FROM_DEVICE);
+			if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
+				dev_kfree_skb(buffer_info->skb);
+				buffer_info->skb = NULL;
+				dev_err(&pdev->dev, "RX DMA map failed\n");
+				goto no_buffers;
+			}
 		}
 		/* Refresh the desc even if buffer_addrs didn't change because
 		 * each write-back erases this info. */
@@ -2754,6 +2774,10 @@ static int __devinit igbvf_probe(struct pci_dev *pdev,
 	/* reset the hardware with the new settings */
 	igbvf_reset(adapter);
 
+	/* set hardware-specific flags */
+	if (adapter->hw.mac.type == e1000_vfadapt_i350)
+		adapter->flags |= IGBVF_FLAG_RX_LB_VLAN_BSWAP;
+
 	strcpy(netdev->name, "eth%d");
 	err = register_netdev(netdev);
 	if (err)
diff --git a/drivers/net/ethernet/intel/ixgbe/Makefile b/drivers/net/ethernet/intel/ixgbe/Makefile
index 89f40e5..f3a632b 100644
--- a/drivers/net/ethernet/intel/ixgbe/Makefile
+++ b/drivers/net/ethernet/intel/ixgbe/Makefile
@@ -34,11 +34,10 @@ obj-$(CONFIG_IXGBE) += ixgbe.o
 
 ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o ixgbe_debugfs.o\
               ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \
-              ixgbe_mbx.o ixgbe_x540.o ixgbe_lib.o
+              ixgbe_mbx.o ixgbe_x540.o ixgbe_lib.o ixgbe_ptp.o
 
 ixgbe-$(CONFIG_IXGBE_DCB) +=  ixgbe_dcb.o ixgbe_dcb_82598.o \
                               ixgbe_dcb_82599.o ixgbe_dcb_nl.o
 
-ixgbe-$(CONFIG_IXGBE_PTP) += ixgbe_ptp.o
 ixgbe-$(CONFIG_IXGBE_HWMON) += ixgbe_sysfs.o
 ixgbe-$(CONFIG_FCOE:m=y) += ixgbe_fcoe.o
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 30efc9f..8e78676 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -36,11 +36,9 @@
 #include <linux/aer.h>
 #include <linux/if_vlan.h>
 
-#ifdef CONFIG_IXGBE_PTP
 #include <linux/clocksource.h>
 #include <linux/net_tstamp.h>
 #include <linux/ptp_clock_kernel.h>
-#endif /* CONFIG_IXGBE_PTP */
 
 #include "ixgbe_type.h"
 #include "ixgbe_common.h"
@@ -135,6 +133,7 @@ struct vf_data_storage {
 	u16 tx_rate;
 	u16 vlan_count;
 	u8 spoofchk_enabled;
+	unsigned int vf_api;
 };
 
 struct vf_macvlans {
@@ -482,8 +481,9 @@ struct ixgbe_adapter {
 #define IXGBE_FLAG2_FDIR_REQUIRES_REINIT        (u32)(1 << 7)
 #define IXGBE_FLAG2_RSS_FIELD_IPV4_UDP		(u32)(1 << 8)
 #define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP		(u32)(1 << 9)
-#define IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED	(u32)(1 << 10)
+#define IXGBE_FLAG2_PTP_ENABLED			(u32)(1 << 10)
 #define IXGBE_FLAG2_PTP_PPS_ENABLED		(u32)(1 << 11)
+#define IXGBE_FLAG2_BRIDGE_MODE_VEB		(u32)(1 << 12)
 
 	/* Tx fast path data */
 	int num_tx_queues;
@@ -571,7 +571,6 @@ struct ixgbe_adapter {
 	u32 interrupt_event;
 	u32 led_reg;
 
-#ifdef CONFIG_IXGBE_PTP
 	struct ptp_clock *ptp_clock;
 	struct ptp_clock_info ptp_caps;
 	unsigned long last_overflow_check;
@@ -580,8 +579,6 @@ struct ixgbe_adapter {
 	struct timecounter tc;
 	int rx_hwtstamp_filter;
 	u32 base_incval;
-	u32 cycle_speed;
-#endif /* CONFIG_IXGBE_PTP */
 
 	/* SR-IOV */
 	DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS);
@@ -600,6 +597,8 @@ struct ixgbe_adapter {
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *ixgbe_dbg_adapter;
 #endif /*CONFIG_DEBUG_FS*/
+
+	u8 default_up;
 };
 
 struct ixgbe_fdir_filter {
@@ -691,6 +690,7 @@ extern s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
 						 u16 soft_id);
 extern void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
 						 union ixgbe_atr_input *mask);
+extern bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
 extern void ixgbe_set_rx_mode(struct net_device *netdev);
 #ifdef CONFIG_IXGBE_DCB
 extern void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter);
@@ -739,7 +739,6 @@ static inline struct netdev_queue *txring_txq(const struct ixgbe_ring *ring)
 	return netdev_get_tx_queue(ring->netdev, ring->queue_index);
 }
 
-#ifdef CONFIG_IXGBE_PTP
 extern void ixgbe_ptp_init(struct ixgbe_adapter *adapter);
 extern void ixgbe_ptp_stop(struct ixgbe_adapter *adapter);
 extern void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter);
@@ -751,7 +750,7 @@ extern void ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector,
 extern int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
 				    struct ifreq *ifr, int cmd);
 extern void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter);
+extern void ixgbe_ptp_reset(struct ixgbe_adapter *adapter);
 extern void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr);
-#endif /* CONFIG_IXGBE_PTP */
 
 #endif /* _IXGBE_H_ */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
index 1077cb2..e75f5a4 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
@@ -62,7 +62,6 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
                                          bool autoneg,
                                          bool autoneg_wait_to_complete);
 static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
-static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
 
 static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
 {
@@ -99,9 +98,8 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
 static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
 {
 	s32 ret_val = 0;
-	u32 reg_anlp1 = 0;
-	u32 i = 0;
 	u16 list_offset, data_offset, data_value;
+	bool got_lock = false;
 
 	if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
 		ixgbe_init_mac_link_ops_82599(hw);
@@ -137,28 +135,36 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
 		usleep_range(hw->eeprom.semaphore_delay * 1000,
 			     hw->eeprom.semaphore_delay * 2000);
 
-		/* Now restart DSP by setting Restart_AN and clearing LMS */
-		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, ((IXGBE_READ_REG(hw,
-		                IXGBE_AUTOC) & ~IXGBE_AUTOC_LMS_MASK) |
-		                IXGBE_AUTOC_AN_RESTART));
-
-		/* Wait for AN to leave state 0 */
-		for (i = 0; i < 10; i++) {
-			usleep_range(4000, 8000);
-			reg_anlp1 = IXGBE_READ_REG(hw, IXGBE_ANLP1);
-			if (reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK)
-				break;
+		/* Need SW/FW semaphore around AUTOC writes if LESM on,
+		 * likewise reset_pipeline requires lock as it also writes
+		 * AUTOC.
+		 */
+		if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+			ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+							IXGBE_GSSR_MAC_CSR_SM);
+			if (ret_val)
+				goto setup_sfp_out;
+
+			got_lock = true;
+		}
+
+		/* Restart DSP and set SFI mode */
+		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (IXGBE_READ_REG(hw,
+				IXGBE_AUTOC) | IXGBE_AUTOC_LMS_10G_SERIAL));
+
+		ret_val = ixgbe_reset_pipeline_82599(hw);
+
+		if (got_lock) {
+			hw->mac.ops.release_swfw_sync(hw,
+						      IXGBE_GSSR_MAC_CSR_SM);
+			got_lock = false;
 		}
-		if (!(reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK)) {
-			hw_dbg(hw, "sfp module setup not complete\n");
+
+		if (ret_val) {
+			hw_dbg(hw, " sfp module setup not complete\n");
 			ret_val = IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
 			goto setup_sfp_out;
 		}
-
-		/* Restart DSP by setting Restart_AN and return to SFI mode */
-		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (IXGBE_READ_REG(hw,
-		                IXGBE_AUTOC) | IXGBE_AUTOC_LMS_10G_SERIAL |
-		                IXGBE_AUTOC_AN_RESTART));
 	}
 
 setup_sfp_out:
@@ -394,14 +400,26 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
 	u32 links_reg;
 	u32 i;
 	s32 status = 0;
+	bool got_lock = false;
+
+	if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+		status = hw->mac.ops.acquire_swfw_sync(hw,
+						IXGBE_GSSR_MAC_CSR_SM);
+		if (status)
+			goto out;
+
+		got_lock = true;
+	}
 
 	/* Restart link */
-	autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
-	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
-	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+	ixgbe_reset_pipeline_82599(hw);
+
+	if (got_lock)
+		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
 
 	/* Only poll for autoneg to complete if specified to do so */
 	if (autoneg_wait_to_complete) {
+		autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
 		if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
 		     IXGBE_AUTOC_LMS_KX4_KX_KR ||
 		    (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
@@ -425,6 +443,7 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
 	/* Add delay to filter out noises during initial link setup */
 	msleep(50);
 
+out:
 	return status;
 }
 
@@ -779,6 +798,7 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
 	u32 links_reg;
 	u32 i;
 	ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
+	bool got_lock = false;
 
 	/* Check to see if speed passed in is supported. */
 	status = hw->mac.ops.get_link_capabilities(hw, &link_capabilities,
@@ -836,9 +856,26 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
 	}
 
 	if (autoc != start_autoc) {
+		/* Need SW/FW semaphore around AUTOC writes if LESM is on,
+		 * likewise reset_pipeline requires us to hold this lock as
+		 * it also writes to AUTOC.
+		 */
+		if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+			status = hw->mac.ops.acquire_swfw_sync(hw,
+							IXGBE_GSSR_MAC_CSR_SM);
+			if (status != 0)
+				goto out;
+
+			got_lock = true;
+		}
+
 		/* Restart link */
-		autoc |= IXGBE_AUTOC_AN_RESTART;
 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
+		ixgbe_reset_pipeline_82599(hw);
+
+		if (got_lock)
+			hw->mac.ops.release_swfw_sync(hw,
+						      IXGBE_GSSR_MAC_CSR_SM);
 
 		/* Only poll for autoneg to complete if specified to do so */
 		if (autoneg_wait_to_complete) {
@@ -994,9 +1031,28 @@ mac_reset_top:
 		hw->mac.orig_autoc2 = autoc2;
 		hw->mac.orig_link_settings_stored = true;
 	} else {
-		if (autoc != hw->mac.orig_autoc)
-			IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (hw->mac.orig_autoc |
-			                IXGBE_AUTOC_AN_RESTART));
+		if (autoc != hw->mac.orig_autoc) {
+			/* Need SW/FW semaphore around AUTOC writes if LESM is
+			 * on, likewise reset_pipeline requires us to hold
+			 * this lock as it also writes to AUTOC.
+			 */
+			bool got_lock = false;
+			if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+				status = hw->mac.ops.acquire_swfw_sync(hw,
+							IXGBE_GSSR_MAC_CSR_SM);
+				if (status)
+					goto reset_hw_out;
+
+				got_lock = true;
+			}
+
+			IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc);
+			ixgbe_reset_pipeline_82599(hw);
+
+			if (got_lock)
+				hw->mac.ops.release_swfw_sync(hw,
+							IXGBE_GSSR_MAC_CSR_SM);
+		}
 
 		if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
 		    (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) {
@@ -1983,7 +2039,7 @@ fw_version_out:
  *  Returns true if the LESM FW module is present and enabled. Otherwise
  *  returns false. Smart Speed must be disabled if LESM FW module is enabled.
  **/
-static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
+bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
 {
 	bool lesm_enabled = false;
 	u16 fw_offset, fw_lesm_param_offset, fw_lesm_state;
@@ -2080,6 +2136,50 @@ static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw,
 	return ret_val;
 }
 
+/**
+ * ixgbe_reset_pipeline_82599 - perform pipeline reset
+ *
+ * @hw: pointer to hardware structure
+ *
+ * Reset pipeline by asserting Restart_AN together with LMS change to ensure
+ * full pipeline reset.  Note - We must hold the SW/FW semaphore before writing
+ * to AUTOC, so this function assumes the semaphore is held.
+ **/
+s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
+{
+	s32 i, autoc_reg, ret_val;
+	s32 anlp1_reg = 0;
+
+	autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
+
+	/* Write AUTOC register with toggled LMS[2] bit and Restart_AN */
+	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg ^ IXGBE_AUTOC_LMS_1G_AN);
+
+	/* Wait for AN to leave state 0 */
+	for (i = 0; i < 10; i++) {
+		usleep_range(4000, 8000);
+		anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
+		if (anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)
+			break;
+	}
+
+	if (!(anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)) {
+		hw_dbg(hw, "auto negotiation not completed\n");
+		ret_val = IXGBE_ERR_RESET_FAILED;
+		goto reset_pipeline_out;
+	}
+
+	ret_val = 0;
+
+reset_pipeline_out:
+	/* Write AUTOC register with original LMS field and Restart_AN */
+	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return ret_val;
+}
+
 static struct ixgbe_mac_operations mac_ops_82599 = {
 	.init_hw                = &ixgbe_init_hw_generic,
 	.reset_hw               = &ixgbe_reset_hw_82599,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index dbf37e4..5af1eeb 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -65,13 +65,12 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
  *  function check the device id to see if the associated phy supports
  *  autoneg flow control.
  **/
-static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
+s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
 {
 
 	switch (hw->device_id) {
 	case IXGBE_DEV_ID_X540T:
 	case IXGBE_DEV_ID_X540T1:
-		return 0;
 	case IXGBE_DEV_ID_82599_T3_LOM:
 		return 0;
 	default:
@@ -90,6 +89,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
 	s32 ret_val = 0;
 	u32 reg = 0, reg_bp = 0;
 	u16 reg_cu = 0;
+	bool got_lock = false;
 
 	/*
 	 * Validate the requested mode.  Strict IEEE mode does not allow
@@ -210,8 +210,29 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
 	 *
 	 */
 	if (hw->phy.media_type == ixgbe_media_type_backplane) {
-		reg_bp |= IXGBE_AUTOC_AN_RESTART;
+		/* Need the SW/FW semaphore around AUTOC writes if 82599 and
+		 * LESM is on, likewise reset_pipeline requries the lock as
+		 * it also writes AUTOC.
+		 */
+		if ((hw->mac.type == ixgbe_mac_82599EB) &&
+		    ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+			ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+							IXGBE_GSSR_MAC_CSR_SM);
+			if (ret_val)
+				goto out;
+
+			got_lock = true;
+		}
+
 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
+
+		if (hw->mac.type == ixgbe_mac_82599EB)
+			ixgbe_reset_pipeline_82599(hw);
+
+		if (got_lock)
+			hw->mac.ops.release_swfw_sync(hw,
+						      IXGBE_GSSR_MAC_CSR_SM);
+
 	} else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
 		    (ixgbe_device_supports_autoneg_fc(hw) == 0)) {
 		hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
@@ -1778,8 +1799,7 @@ s32 ixgbe_validate_mac_addr(u8 *mac_addr)
 	else if (IXGBE_IS_BROADCAST(mac_addr))
 		status = IXGBE_ERR_INVALID_MAC_ADDR;
 	/* Reject the zero address */
-	else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 &&
-	         mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0)
+	else if (is_zero_ether_addr(mac_addr))
 		status = IXGBE_ERR_INVALID_MAC_ADDR;
 
 	return status;
@@ -2617,6 +2637,7 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
 	bool link_up = false;
 	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+	s32 ret_val = 0;
 
 	/*
 	 * Link must be up to auto-blink the LEDs;
@@ -2625,10 +2646,28 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
 	hw->mac.ops.check_link(hw, &speed, &link_up, false);
 
 	if (!link_up) {
+		/* Need the SW/FW semaphore around AUTOC writes if 82599 and
+		 * LESM is on.
+		 */
+		bool got_lock = false;
+
+		if ((hw->mac.type == ixgbe_mac_82599EB) &&
+		    ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+			ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+							IXGBE_GSSR_MAC_CSR_SM);
+			if (ret_val)
+				goto out;
+
+			got_lock = true;
+		}
 		autoc_reg |= IXGBE_AUTOC_AN_RESTART;
 		autoc_reg |= IXGBE_AUTOC_FLU;
 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
 		IXGBE_WRITE_FLUSH(hw);
+
+		if (got_lock)
+			hw->mac.ops.release_swfw_sync(hw,
+						      IXGBE_GSSR_MAC_CSR_SM);
 		usleep_range(10000, 20000);
 	}
 
@@ -2637,7 +2676,8 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
 	IXGBE_WRITE_FLUSH(hw);
 
-	return 0;
+out:
+	return ret_val;
 }
 
 /**
@@ -2649,18 +2689,40 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
 {
 	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+	s32 ret_val = 0;
+	bool got_lock = false;
+
+	/* Need the SW/FW semaphore around AUTOC writes if 82599 and
+	 * LESM is on.
+	 */
+	if ((hw->mac.type == ixgbe_mac_82599EB) &&
+	    ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+						IXGBE_GSSR_MAC_CSR_SM);
+		if (ret_val)
+			goto out;
+
+		got_lock = true;
+	}
 
 	autoc_reg &= ~IXGBE_AUTOC_FLU;
 	autoc_reg |= IXGBE_AUTOC_AN_RESTART;
 	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
 
+	if (hw->mac.type == ixgbe_mac_82599EB)
+		ixgbe_reset_pipeline_82599(hw);
+
+	if (got_lock)
+		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+
 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
 	led_reg &= ~IXGBE_LED_BLINK(index);
 	led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
 	IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
 	IXGBE_WRITE_FLUSH(hw);
 
-	return 0;
+out:
+	return ret_val;
 }
 
 /**
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
index d813d11..1b65b6c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
@@ -78,6 +78,7 @@ s32 ixgbe_disable_rx_buff_generic(struct ixgbe_hw *hw);
 s32 ixgbe_enable_rx_buff_generic(struct ixgbe_hw *hw);
 s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval);
 s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw);
+s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw);
 void ixgbe_fc_autoneg(struct ixgbe_hw *hw);
 
 s32 ixgbe_validate_mac_addr(u8 *mac_addr);
@@ -107,6 +108,7 @@ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw);
 
 void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb,
 			     u32 headroom, int strategy);
+s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
 
 #define IXGBE_I2C_THERMAL_SENSOR_ADDR	0xF8
 #define IXGBE_EMC_INTERNAL_DATA		0x00
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c
index 8d3a218..efaf9a7 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c
@@ -37,20 +37,6 @@ static struct dentry *ixgbe_dbg_root;
 static char ixgbe_dbg_reg_ops_buf[256] = "";
 
 /**
- * ixgbe_dbg_reg_ops_open - prep the debugfs pokee data item when opened
- * @inode: inode that was opened
- * @filp:  file info
- *
- * Stash the adapter pointer hiding in the inode into the file pointer where
- * we can find it later in the read and write calls
- **/
-static int ixgbe_dbg_reg_ops_open(struct inode *inode, struct file *filp)
-{
-	filp->private_data = inode->i_private;
-	return 0;
-}
-
-/**
  * ixgbe_dbg_reg_ops_read - read for reg_ops datum
  * @filp: the opened file
  * @buffer: where to write the data for the user to read
@@ -142,7 +128,7 @@ static ssize_t ixgbe_dbg_reg_ops_write(struct file *filp,
 
 static const struct file_operations ixgbe_dbg_reg_ops_fops = {
 	.owner = THIS_MODULE,
-	.open =  ixgbe_dbg_reg_ops_open,
+	.open = simple_open,
 	.read =  ixgbe_dbg_reg_ops_read,
 	.write = ixgbe_dbg_reg_ops_write,
 };
@@ -150,20 +136,6 @@ static const struct file_operations ixgbe_dbg_reg_ops_fops = {
 static char ixgbe_dbg_netdev_ops_buf[256] = "";
 
 /**
- * ixgbe_dbg_netdev_ops_open - prep the debugfs netdev_ops data item
- * @inode: inode that was opened
- * @filp: file info
- *
- * Stash the adapter pointer hiding in the inode into the file pointer
- * where we can find it later in the read and write calls
- **/
-static int ixgbe_dbg_netdev_ops_open(struct inode *inode, struct file *filp)
-{
-	filp->private_data = inode->i_private;
-	return 0;
-}
-
-/**
  * ixgbe_dbg_netdev_ops_read - read for netdev_ops datum
  * @filp: the opened file
  * @buffer: where to write the data for the user to read
@@ -238,7 +210,7 @@ static ssize_t ixgbe_dbg_netdev_ops_write(struct file *filp,
 
 static const struct file_operations ixgbe_dbg_netdev_ops_fops = {
 	.owner = THIS_MODULE,
-	.open = ixgbe_dbg_netdev_ops_open,
+	.open = simple_open,
 	.read = ixgbe_dbg_netdev_ops_read,
 	.write = ixgbe_dbg_netdev_ops_write,
 };
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index 116f0e9..3268584 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -383,6 +383,11 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
 	    (adapter->flags & IXGBE_FLAG_DCB_ENABLED))
 		return -EINVAL;
 
+	/* some devices do not support autoneg of link flow control */
+	if ((pause->autoneg == AUTONEG_ENABLE) &&
+	    (ixgbe_device_supports_autoneg_fc(hw) != 0))
+		return -EINVAL;
+
 	fc.disable_fc_autoneg = (pause->autoneg != AUTONEG_ENABLE);
 
 	if ((pause->rx_pause && pause->tx_pause) || pause->autoneg)
@@ -887,24 +892,23 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
                                struct ethtool_ringparam *ring)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	struct ixgbe_ring *temp_tx_ring, *temp_rx_ring;
+	struct ixgbe_ring *temp_ring;
 	int i, err = 0;
 	u32 new_rx_count, new_tx_count;
-	bool need_update = false;
 
 	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
 		return -EINVAL;
 
-	new_rx_count = max_t(u32, ring->rx_pending, IXGBE_MIN_RXD);
-	new_rx_count = min_t(u32, new_rx_count, IXGBE_MAX_RXD);
-	new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE);
-
-	new_tx_count = max_t(u32, ring->tx_pending, IXGBE_MIN_TXD);
-	new_tx_count = min_t(u32, new_tx_count, IXGBE_MAX_TXD);
+	new_tx_count = clamp_t(u32, ring->tx_pending,
+			       IXGBE_MIN_TXD, IXGBE_MAX_TXD);
 	new_tx_count = ALIGN(new_tx_count, IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE);
 
-	if ((new_tx_count == adapter->tx_ring[0]->count) &&
-	    (new_rx_count == adapter->rx_ring[0]->count)) {
+	new_rx_count = clamp_t(u32, ring->rx_pending,
+			       IXGBE_MIN_RXD, IXGBE_MAX_RXD);
+	new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE);
+
+	if ((new_tx_count == adapter->tx_ring_count) &&
+	    (new_rx_count == adapter->rx_ring_count)) {
 		/* nothing to do */
 		return 0;
 	}
@@ -922,81 +926,80 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
 		goto clear_reset;
 	}
 
-	temp_tx_ring = vmalloc(adapter->num_tx_queues * sizeof(struct ixgbe_ring));
-	if (!temp_tx_ring) {
+	/* allocate temporary buffer to store rings in */
+	i = max_t(int, adapter->num_tx_queues, adapter->num_rx_queues);
+	temp_ring = vmalloc(i * sizeof(struct ixgbe_ring));
+
+	if (!temp_ring) {
 		err = -ENOMEM;
 		goto clear_reset;
 	}
 
+	ixgbe_down(adapter);
+
+	/*
+	 * Setup new Tx resources and free the old Tx resources in that order.
+	 * We can then assign the new resources to the rings via a memcpy.
+	 * The advantage to this approach is that we are guaranteed to still
+	 * have resources even in the case of an allocation failure.
+	 */
 	if (new_tx_count != adapter->tx_ring_count) {
 		for (i = 0; i < adapter->num_tx_queues; i++) {
-			memcpy(&temp_tx_ring[i], adapter->tx_ring[i],
+			memcpy(&temp_ring[i], adapter->tx_ring[i],
 			       sizeof(struct ixgbe_ring));
-			temp_tx_ring[i].count = new_tx_count;
-			err = ixgbe_setup_tx_resources(&temp_tx_ring[i]);
+
+			temp_ring[i].count = new_tx_count;
+			err = ixgbe_setup_tx_resources(&temp_ring[i]);
 			if (err) {
 				while (i) {
 					i--;
-					ixgbe_free_tx_resources(&temp_tx_ring[i]);
+					ixgbe_free_tx_resources(&temp_ring[i]);
 				}
-				goto clear_reset;
+				goto err_setup;
 			}
 		}
-		need_update = true;
-	}
 
-	temp_rx_ring = vmalloc(adapter->num_rx_queues * sizeof(struct ixgbe_ring));
-	if (!temp_rx_ring) {
-		err = -ENOMEM;
-		goto err_setup;
+		for (i = 0; i < adapter->num_tx_queues; i++) {
+			ixgbe_free_tx_resources(adapter->tx_ring[i]);
+
+			memcpy(adapter->tx_ring[i], &temp_ring[i],
+			       sizeof(struct ixgbe_ring));
+		}
+
+		adapter->tx_ring_count = new_tx_count;
 	}
 
+	/* Repeat the process for the Rx rings if needed */
 	if (new_rx_count != adapter->rx_ring_count) {
 		for (i = 0; i < adapter->num_rx_queues; i++) {
-			memcpy(&temp_rx_ring[i], adapter->rx_ring[i],
+			memcpy(&temp_ring[i], adapter->rx_ring[i],
 			       sizeof(struct ixgbe_ring));
-			temp_rx_ring[i].count = new_rx_count;
-			err = ixgbe_setup_rx_resources(&temp_rx_ring[i]);
+
+			temp_ring[i].count = new_rx_count;
+			err = ixgbe_setup_rx_resources(&temp_ring[i]);
 			if (err) {
 				while (i) {
 					i--;
-					ixgbe_free_rx_resources(&temp_rx_ring[i]);
+					ixgbe_free_rx_resources(&temp_ring[i]);
 				}
 				goto err_setup;
 			}
+
 		}
-		need_update = true;
-	}
 
-	/* if rings need to be updated, here's the place to do it in one shot */
-	if (need_update) {
-		ixgbe_down(adapter);
+		for (i = 0; i < adapter->num_rx_queues; i++) {
+			ixgbe_free_rx_resources(adapter->rx_ring[i]);
 
-		/* tx */
-		if (new_tx_count != adapter->tx_ring_count) {
-			for (i = 0; i < adapter->num_tx_queues; i++) {
-				ixgbe_free_tx_resources(adapter->tx_ring[i]);
-				memcpy(adapter->tx_ring[i], &temp_tx_ring[i],
-				       sizeof(struct ixgbe_ring));
-			}
-			adapter->tx_ring_count = new_tx_count;
+			memcpy(adapter->rx_ring[i], &temp_ring[i],
+			       sizeof(struct ixgbe_ring));
 		}
 
-		/* rx */
-		if (new_rx_count != adapter->rx_ring_count) {
-			for (i = 0; i < adapter->num_rx_queues; i++) {
-				ixgbe_free_rx_resources(adapter->rx_ring[i]);
-				memcpy(adapter->rx_ring[i], &temp_rx_ring[i],
-				       sizeof(struct ixgbe_ring));
-			}
-			adapter->rx_ring_count = new_rx_count;
-		}
-		ixgbe_up(adapter);
+		adapter->rx_ring_count = new_rx_count;
 	}
 
-	vfree(temp_rx_ring);
 err_setup:
-	vfree(temp_tx_ring);
+	ixgbe_up(adapter);
+	vfree(temp_ring);
 clear_reset:
 	clear_bit(__IXGBE_RESETTING, &adapter->state);
 	return err;
@@ -2669,7 +2672,6 @@ static int ixgbe_get_ts_info(struct net_device *dev,
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
 
 	switch (adapter->hw.mac.type) {
-#ifdef CONFIG_IXGBE_PTP
 	case ixgbe_mac_X540:
 	case ixgbe_mac_82599EB:
 		info->so_timestamping =
@@ -2695,7 +2697,6 @@ static int ixgbe_get_ts_info(struct net_device *dev,
 			(1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
 			(1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
 		break;
-#endif /* CONFIG_IXGBE_PTP */
 	default:
 		return ethtool_op_get_ts_info(dev, info);
 		break;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
index ae73ef1..252850d 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
@@ -800,6 +800,10 @@ int ixgbe_fcoe_enable(struct net_device *netdev)
 		return -EINVAL;
 
 	e_info(drv, "Enabling FCoE offload features.\n");
+
+	if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
+		e_warn(probe, "Enabling FCoE on PF will disable legacy VFs\n");
+
 	if (netif_running(netdev))
 		netdev->netdev_ops->ndo_stop(netdev);
 
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
index 17ecbce..8c74f73 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -802,10 +802,13 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
 	/* setup affinity mask and node */
 	if (cpu != -1)
 		cpumask_set_cpu(cpu, &q_vector->affinity_mask);
-	else
-		cpumask_copy(&q_vector->affinity_mask, cpu_online_mask);
 	q_vector->numa_node = node;
 
+#ifdef CONFIG_IXGBE_DCA
+	/* initialize CPU for DCA */
+	q_vector->cpu = -1;
+
+#endif
 	/* initialize NAPI */
 	netif_napi_add(adapter->netdev, &q_vector->napi,
 		       ixgbe_poll, 64);
@@ -821,6 +824,21 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
 	/* initialize pointer to rings */
 	ring = q_vector->ring;
 
+	/* intialize ITR */
+	if (txr_count && !rxr_count) {
+		/* tx only vector */
+		if (adapter->tx_itr_setting == 1)
+			q_vector->itr = IXGBE_10K_ITR;
+		else
+			q_vector->itr = adapter->tx_itr_setting;
+	} else {
+		/* rx or rx/tx vector */
+		if (adapter->rx_itr_setting == 1)
+			q_vector->itr = IXGBE_20K_ITR;
+		else
+			q_vector->itr = adapter->rx_itr_setting;
+	}
+
 	while (txr_count) {
 		/* assign generic ring traits */
 		ring->dev = &adapter->pdev->dev;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index fa3d552..484bbed 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -44,6 +44,7 @@
 #include <linux/ethtool.h>
 #include <linux/if.h>
 #include <linux/if_vlan.h>
+#include <linux/if_bridge.h>
 #include <linux/prefetch.h>
 #include <scsi/fc/fc_fcoe.h>
 
@@ -62,11 +63,7 @@ char ixgbe_default_device_descr[] =
 static char ixgbe_default_device_descr[] =
 			      "Intel(R) 10 Gigabit Network Connection";
 #endif
-#define MAJ 3
-#define MIN 9
-#define BUILD 15
-#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
-	__stringify(BUILD) "-k"
+#define DRV_VERSION "3.11.33-k"
 const char ixgbe_driver_version[] = DRV_VERSION;
 static const char ixgbe_copyright[] =
 				"Copyright (c) 1999-2012 Intel Corporation.";
@@ -335,11 +332,13 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
 		goto exit;
 
 	dev_info(&adapter->pdev->dev, "TX Rings Summary\n");
-	pr_info("Queue [NTU] [NTC] [bi(ntc)->dma  ] leng ntw timestamp\n");
+	pr_info(" %s     %s              %s        %s\n",
+		"Queue [NTU] [NTC] [bi(ntc)->dma  ]",
+		"leng", "ntw", "timestamp");
 	for (n = 0; n < adapter->num_tx_queues; n++) {
 		tx_ring = adapter->tx_ring[n];
 		tx_buffer = &tx_ring->tx_buffer_info[tx_ring->next_to_clean];
-		pr_info(" %5d %5X %5X %016llX %04X %p %016llX\n",
+		pr_info(" %5d %5X %5X %016llX %08X %p %016llX\n",
 			   n, tx_ring->next_to_use, tx_ring->next_to_clean,
 			   (u64)dma_unmap_addr(tx_buffer, dma),
 			   dma_unmap_len(tx_buffer, len),
@@ -355,13 +354,37 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
 
 	/* Transmit Descriptor Formats
 	 *
-	 * Advanced Transmit Descriptor
+	 * 82598 Advanced Transmit Descriptor
 	 *   +--------------------------------------------------------------+
 	 * 0 |         Buffer Address [63:0]                                |
 	 *   +--------------------------------------------------------------+
-	 * 8 |  PAYLEN  | PORTS  | IDX | STA | DCMD  |DTYP |  RSV |  DTALEN |
+	 * 8 |  PAYLEN  | POPTS  | IDX | STA | DCMD  |DTYP |  RSV |  DTALEN |
 	 *   +--------------------------------------------------------------+
 	 *   63       46 45    40 39 36 35 32 31   24 23 20 19              0
+	 *
+	 * 82598 Advanced Transmit Descriptor (Write-Back Format)
+	 *   +--------------------------------------------------------------+
+	 * 0 |                          RSV [63:0]                          |
+	 *   +--------------------------------------------------------------+
+	 * 8 |            RSV           |  STA  |          NXTSEQ           |
+	 *   +--------------------------------------------------------------+
+	 *   63                       36 35   32 31                         0
+	 *
+	 * 82599+ Advanced Transmit Descriptor
+	 *   +--------------------------------------------------------------+
+	 * 0 |         Buffer Address [63:0]                                |
+	 *   +--------------------------------------------------------------+
+	 * 8 |PAYLEN  |POPTS|CC|IDX  |STA  |DCMD  |DTYP |MAC  |RSV  |DTALEN |
+	 *   +--------------------------------------------------------------+
+	 *   63     46 45 40 39 38 36 35 32 31  24 23 20 19 18 17 16 15     0
+	 *
+	 * 82599+ Advanced Transmit Descriptor (Write-Back Format)
+	 *   +--------------------------------------------------------------+
+	 * 0 |                          RSV [63:0]                          |
+	 *   +--------------------------------------------------------------+
+	 * 8 |            RSV           |  STA  |           RSV             |
+	 *   +--------------------------------------------------------------+
+	 *   63                       36 35   32 31                         0
 	 */
 
 	for (n = 0; n < adapter->num_tx_queues; n++) {
@@ -369,40 +392,43 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
 		pr_info("------------------------------------\n");
 		pr_info("TX QUEUE INDEX = %d\n", tx_ring->queue_index);
 		pr_info("------------------------------------\n");
-		pr_info("T [desc]     [address 63:0  ] "
-			"[PlPOIdStDDt Ln] [bi->dma       ] "
-			"leng  ntw timestamp        bi->skb\n");
+		pr_info("%s%s    %s              %s        %s          %s\n",
+			"T [desc]     [address 63:0  ] ",
+			"[PlPOIdStDDt Ln] [bi->dma       ] ",
+			"leng", "ntw", "timestamp", "bi->skb");
 
 		for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
 			tx_desc = IXGBE_TX_DESC(tx_ring, i);
 			tx_buffer = &tx_ring->tx_buffer_info[i];
 			u0 = (struct my_u0 *)tx_desc;
-			pr_info("T [0x%03X]    %016llX %016llX %016llX"
-				" %04X  %p %016llX %p", i,
-				le64_to_cpu(u0->a),
-				le64_to_cpu(u0->b),
-				(u64)dma_unmap_addr(tx_buffer, dma),
-				dma_unmap_len(tx_buffer, len),
-				tx_buffer->next_to_watch,
-				(u64)tx_buffer->time_stamp,
-				tx_buffer->skb);
-			if (i == tx_ring->next_to_use &&
-				i == tx_ring->next_to_clean)
-				pr_cont(" NTC/U\n");
-			else if (i == tx_ring->next_to_use)
-				pr_cont(" NTU\n");
-			else if (i == tx_ring->next_to_clean)
-				pr_cont(" NTC\n");
-			else
-				pr_cont("\n");
-
-			if (netif_msg_pktdata(adapter) &&
-			    tx_buffer->skb)
-				print_hex_dump(KERN_INFO, "",
-					DUMP_PREFIX_ADDRESS, 16, 1,
-					tx_buffer->skb->data,
+			if (dma_unmap_len(tx_buffer, len) > 0) {
+				pr_info("T [0x%03X]    %016llX %016llX %016llX %08X %p %016llX %p",
+					i,
+					le64_to_cpu(u0->a),
+					le64_to_cpu(u0->b),
+					(u64)dma_unmap_addr(tx_buffer, dma),
 					dma_unmap_len(tx_buffer, len),
-					true);
+					tx_buffer->next_to_watch,
+					(u64)tx_buffer->time_stamp,
+					tx_buffer->skb);
+				if (i == tx_ring->next_to_use &&
+					i == tx_ring->next_to_clean)
+					pr_cont(" NTC/U\n");
+				else if (i == tx_ring->next_to_use)
+					pr_cont(" NTU\n");
+				else if (i == tx_ring->next_to_clean)
+					pr_cont(" NTC\n");
+				else
+					pr_cont("\n");
+
+				if (netif_msg_pktdata(adapter) &&
+				    tx_buffer->skb)
+					print_hex_dump(KERN_INFO, "",
+						DUMP_PREFIX_ADDRESS, 16, 1,
+						tx_buffer->skb->data,
+						dma_unmap_len(tx_buffer, len),
+						true);
+			}
 		}
 	}
 
@@ -422,7 +448,9 @@ rx_ring_summary:
 
 	dev_info(&adapter->pdev->dev, "RX Rings Dump\n");
 
-	/* Advanced Receive Descriptor (Read) Format
+	/* Receive Descriptor Formats
+	 *
+	 * 82598 Advanced Receive Descriptor (Read) Format
 	 *    63                                           1        0
 	 *    +-----------------------------------------------------+
 	 *  0 |       Packet Buffer Address [63:1]           |A0/NSE|
@@ -431,27 +459,52 @@ rx_ring_summary:
 	 *    +-----------------------------------------------------+
 	 *
 	 *
-	 * Advanced Receive Descriptor (Write-Back) Format
+	 * 82598 Advanced Receive Descriptor (Write-Back) Format
 	 *
 	 *   63       48 47    32 31  30      21 20 16 15   4 3     0
 	 *   +------------------------------------------------------+
-	 * 0 | Packet     IP     |SPH| HDR_LEN   | RSV|Packet|  RSS |
-	 *   | Checksum   Ident  |   |           |    | Type | Type |
+	 * 0 |       RSS Hash /  |SPH| HDR_LEN  | RSV |Packet|  RSS |
+	 *   | Packet   | IP     |   |          |     | Type | Type |
+	 *   | Checksum | Ident  |   |          |     |      |      |
 	 *   +------------------------------------------------------+
 	 * 8 | VLAN Tag | Length | Extended Error | Extended Status |
 	 *   +------------------------------------------------------+
 	 *   63       48 47    32 31            20 19               0
+	 *
+	 * 82599+ Advanced Receive Descriptor (Read) Format
+	 *    63                                           1        0
+	 *    +-----------------------------------------------------+
+	 *  0 |       Packet Buffer Address [63:1]           |A0/NSE|
+	 *    +----------------------------------------------+------+
+	 *  8 |       Header Buffer Address [63:1]           |  DD  |
+	 *    +-----------------------------------------------------+
+	 *
+	 *
+	 * 82599+ Advanced Receive Descriptor (Write-Back) Format
+	 *
+	 *   63       48 47    32 31  30      21 20 17 16   4 3     0
+	 *   +------------------------------------------------------+
+	 * 0 |RSS / Frag Checksum|SPH| HDR_LEN  |RSC- |Packet|  RSS |
+	 *   |/ RTT / PCoE_PARAM |   |          | CNT | Type | Type |
+	 *   |/ Flow Dir Flt ID  |   |          |     |      |      |
+	 *   +------------------------------------------------------+
+	 * 8 | VLAN Tag | Length |Extended Error| Xtnd Status/NEXTP |
+	 *   +------------------------------------------------------+
+	 *   63       48 47    32 31          20 19                 0
 	 */
+
 	for (n = 0; n < adapter->num_rx_queues; n++) {
 		rx_ring = adapter->rx_ring[n];
 		pr_info("------------------------------------\n");
 		pr_info("RX QUEUE INDEX = %d\n", rx_ring->queue_index);
 		pr_info("------------------------------------\n");
-		pr_info("R  [desc]      [ PktBuf     A0] "
-			"[  HeadBuf   DD] [bi->dma       ] [bi->skb] "
+		pr_info("%s%s%s",
+			"R  [desc]      [ PktBuf     A0] ",
+			"[  HeadBuf   DD] [bi->dma       ] [bi->skb       ] ",
 			"<-- Adv Rx Read format\n");
-		pr_info("RWB[desc]      [PcsmIpSHl PtRs] "
-			"[vl er S cks ln] ---------------- [bi->skb] "
+		pr_info("%s%s%s",
+			"RWB[desc]      [PcsmIpSHl PtRs] ",
+			"[vl er S cks ln] ---------------- [bi->skb       ] ",
 			"<-- Adv Rx Write-Back format\n");
 
 		for (i = 0; i < rx_ring->count; i++) {
@@ -646,6 +699,7 @@ static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct ixgbe_hw_stats *hwstats = &adapter->stats;
 	u32 xoff[8] = {0};
+	u8 tc;
 	int i;
 	bool pfc_en = adapter->dcb_cfg.pfc_mode_enable;
 
@@ -659,21 +713,26 @@ static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
 
 	/* update stats for each tc, only valid with PFC enabled */
 	for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) {
+		u32 pxoffrxc;
+
 		switch (hw->mac.type) {
 		case ixgbe_mac_82598EB:
-			xoff[i] = IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
+			pxoffrxc = IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
 			break;
 		default:
-			xoff[i] = IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
+			pxoffrxc = IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
 		}
-		hwstats->pxoffrxc[i] += xoff[i];
+		hwstats->pxoffrxc[i] += pxoffrxc;
+		/* Get the TC for given UP */
+		tc = netdev_get_prio_tc_map(adapter->netdev, i);
+		xoff[tc] += pxoffrxc;
 	}
 
 	/* disarm tx queues that have received xoff frames */
 	for (i = 0; i < adapter->num_tx_queues; i++) {
 		struct ixgbe_ring *tx_ring = adapter->tx_ring[i];
-		u8 tc = tx_ring->dcb_tc;
 
+		tc = tx_ring->dcb_tc;
 		if (xoff[tc])
 			clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state);
 	}
@@ -791,10 +850,8 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
 		total_bytes += tx_buffer->bytecount;
 		total_packets += tx_buffer->gso_segs;
 
-#ifdef CONFIG_IXGBE_PTP
 		if (unlikely(tx_buffer->tx_flags & IXGBE_TX_FLAGS_TSTAMP))
 			ixgbe_ptp_tx_hwtstamp(q_vector, tx_buffer->skb);
-#endif
 
 		/* free the skb */
 		dev_kfree_skb_any(tx_buffer->skb);
@@ -967,7 +1024,6 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
 	 * which will cause the DCA tag to be cleared.
 	 */
 	rxctrl |= IXGBE_DCA_RXCTRL_DESC_RRO_EN |
-		  IXGBE_DCA_RXCTRL_DATA_DCA_EN |
 		  IXGBE_DCA_RXCTRL_DESC_DCA_EN;
 
 	IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(reg_idx), rxctrl);
@@ -1244,6 +1300,7 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
 		struct vlan_hdr *vlan;
 		/* l3 headers */
 		struct iphdr *ipv4;
+		struct ipv6hdr *ipv6;
 	} hdr;
 	__be16 protocol;
 	u8 nexthdr = 0;	/* default to not TCP */
@@ -1284,6 +1341,13 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
 		/* record next protocol */
 		nexthdr = hdr.ipv4->protocol;
 		hdr.network += hlen;
+	} else if (protocol == __constant_htons(ETH_P_IPV6)) {
+		if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr)))
+			return max_len;
+
+		/* record next protocol */
+		nexthdr = hdr.ipv6->nexthdr;
+		hdr.network += sizeof(struct ipv6hdr);
 #ifdef IXGBE_FCOE
 	} else if (protocol == __constant_htons(ETH_P_FCOE)) {
 		if ((hdr.network - data) > (max_len - FCOE_HEADER_LEN))
@@ -1294,7 +1358,7 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
 		return hdr.network - data;
 	}
 
-	/* finally sort out TCP */
+	/* finally sort out TCP/UDP */
 	if (nexthdr == IPPROTO_TCP) {
 		if ((hdr.network - data) > (max_len - sizeof(struct tcphdr)))
 			return max_len;
@@ -1307,6 +1371,11 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
 			return hdr.network - data;
 
 		hdr.network += hlen;
+	} else if (nexthdr == IPPROTO_UDP) {
+		if ((hdr.network - data) > (max_len - sizeof(struct udphdr)))
+			return max_len;
+
+		hdr.network += sizeof(struct udphdr);
 	}
 
 	/*
@@ -1369,9 +1438,7 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring,
 
 	ixgbe_rx_checksum(rx_ring, rx_desc, skb);
 
-#ifdef CONFIG_IXGBE_PTP
 	ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, rx_desc, skb);
-#endif
 
 	if ((dev->features & NETIF_F_HW_VLAN_RX) &&
 	    ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) {
@@ -1781,7 +1848,7 @@ dma_sync:
  **/
 static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
 			       struct ixgbe_ring *rx_ring,
-			       int budget)
+			       const int budget)
 {
 	unsigned int total_rx_bytes = 0, total_rx_packets = 0;
 #ifdef IXGBE_FCOE
@@ -1832,7 +1899,6 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
 
 		/* probably a little skewed due to removing CRC */
 		total_rx_bytes += skb->len;
-		total_rx_packets++;
 
 		/* populate checksum, timestamp, VLAN, and protocol */
 		ixgbe_process_skb_fields(rx_ring, rx_desc, skb);
@@ -1865,8 +1931,8 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
 		ixgbe_rx_skb(q_vector, skb);
 
 		/* update budget accounting */
-		budget--;
-	} while (likely(budget));
+		total_rx_packets++;
+	} while (likely(total_rx_packets < budget));
 
 	u64_stats_update_begin(&rx_ring->syncp);
 	rx_ring->stats.packets += total_rx_packets;
@@ -1878,7 +1944,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
 	if (cleaned_count)
 		ixgbe_alloc_rx_buffers(rx_ring, cleaned_count);
 
-	return !!budget;
+	return (total_rx_packets < budget);
 }
 
 /**
@@ -1914,20 +1980,6 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
 		ixgbe_for_each_ring(ring, q_vector->tx)
 			ixgbe_set_ivar(adapter, 1, ring->reg_idx, v_idx);
 
-		if (q_vector->tx.ring && !q_vector->rx.ring) {
-			/* tx only vector */
-			if (adapter->tx_itr_setting == 1)
-				q_vector->itr = IXGBE_10K_ITR;
-			else
-				q_vector->itr = adapter->tx_itr_setting;
-		} else {
-			/* rx or rx/tx vector */
-			if (adapter->rx_itr_setting == 1)
-				q_vector->itr = IXGBE_20K_ITR;
-			else
-				q_vector->itr = adapter->rx_itr_setting;
-		}
-
 		ixgbe_write_eitr(q_vector);
 	}
 
@@ -2324,10 +2376,8 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
 		break;
 	}
 
-#ifdef CONFIG_IXGBE_PTP
 	if (adapter->hw.mac.type == ixgbe_mac_X540)
 		mask |= IXGBE_EIMS_TIMESYNC;
-#endif
 
 	if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) &&
 	    !(adapter->flags2 & IXGBE_FLAG2_FDIR_REQUIRES_REINIT))
@@ -2393,10 +2443,8 @@ static irqreturn_t ixgbe_msix_other(int irq, void *data)
 
 	ixgbe_check_fan_failure(adapter, eicr);
 
-#ifdef CONFIG_IXGBE_PTP
 	if (unlikely(eicr & IXGBE_EICR_TIMESYNC))
 		ixgbe_ptp_check_pps_event(adapter, eicr);
-#endif
 
 	/* re-enable the original interrupt state, no lsc, no queues */
 	if (!test_bit(__IXGBE_DOWN, &adapter->state))
@@ -2588,10 +2636,8 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
 	}
 
 	ixgbe_check_fan_failure(adapter, eicr);
-#ifdef CONFIG_IXGBE_PTP
 	if (unlikely(eicr & IXGBE_EICR_TIMESYNC))
 		ixgbe_ptp_check_pps_event(adapter, eicr);
-#endif
 
 	/* would disable interrupts here but EIAM disabled it */
 	napi_schedule(&q_vector->napi);
@@ -2699,12 +2745,6 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_q_vector *q_vector = adapter->q_vector[0];
 
-	/* rx/tx vector */
-	if (adapter->rx_itr_setting == 1)
-		q_vector->itr = IXGBE_20K_ITR;
-	else
-		q_vector->itr = adapter->rx_itr_setting;
-
 	ixgbe_write_eitr(q_vector);
 
 	ixgbe_set_ivar(adapter, 0, 0, 0);
@@ -3132,14 +3172,6 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
 	ixgbe_configure_srrctl(adapter, ring);
 	ixgbe_configure_rscctl(adapter, ring);
 
-	/* If operating in IOV mode set RLPML for X540 */
-	if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) &&
-	    hw->mac.type == ixgbe_mac_X540) {
-		rxdctl &= ~IXGBE_RXDCTL_RLPMLMASK;
-		rxdctl |= ((ring->netdev->mtu + ETH_HLEN +
-			    ETH_FCS_LEN + VLAN_HLEN) | IXGBE_RXDCTL_RLPML_EN);
-	}
-
 	if (hw->mac.type == ixgbe_mac_82598EB) {
 		/*
 		 * enable cache line friendly hardware writes:
@@ -3211,7 +3243,8 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
 	IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset ^ 1), reg_offset - 1);
 	IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), (~0) << vf_shift);
 	IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset ^ 1), reg_offset - 1);
-	IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
+	if (adapter->flags2 & IXGBE_FLAG2_BRIDGE_MODE_VEB)
+		IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
 
 	/* Map PF MAC address in RAR Entry 0 to first pool following VFs */
 	hw->mac.ops.set_vmdq(hw, 0, VMDQ_P(0));
@@ -3234,8 +3267,6 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
 
 	IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext);
 
-	/* enable Tx loopback for VF/PF communication */
-	IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
 
 	/* Enable MAC Anti-Spoofing */
 	hw->mac.ops.set_mac_anti_spoofing(hw, (adapter->num_vfs != 0),
@@ -3263,6 +3294,11 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter)
 		max_frame = IXGBE_FCOE_JUMBO_FRAME_SIZE;
 
 #endif /* IXGBE_FCOE */
+
+	/* adjust max frame to be at least the size of a standard frame */
+	if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN))
+		max_frame = (ETH_FRAME_LEN + ETH_FCS_LEN);
+
 	mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
 	if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) {
 		mhadd &= ~IXGBE_MHADD_MFS_MASK;
@@ -3271,9 +3307,6 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter)
 		IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
 	}
 
-	/* MHADD will allow an extra 4 bytes past for vlan tagged frames */
-	max_frame += VLAN_HLEN;
-
 	hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
 	/* set jumbo enable since MHADD.MFS is keeping size locked at max_frame */
 	hlreg0 |= IXGBE_HLREG0_JUMBOEN;
@@ -4072,11 +4105,8 @@ static void ixgbe_up_complete(struct ixgbe_adapter *adapter)
 	else
 		ixgbe_configure_msi_and_legacy(adapter);
 
-	/* enable the optics for both mult-speed fiber and 82599 SFP+ fiber */
-	if (hw->mac.ops.enable_tx_laser &&
-	    ((hw->phy.multispeed_fiber) ||
-	     ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
-	      (hw->mac.type == ixgbe_mac_82599EB))))
+	/* enable the optics for 82599 SFP+ fiber */
+	if (hw->mac.ops.enable_tx_laser)
 		hw->mac.ops.enable_tx_laser(hw);
 
 	clear_bit(__IXGBE_DOWN, &adapter->state);
@@ -4192,6 +4222,9 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
 	/* update SAN MAC vmdq pool selection */
 	if (hw->mac.san_mac_rar_index)
 		hw->mac.ops.set_vmdq_san_mac(hw, VMDQ_P(0));
+
+	if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED)
+		ixgbe_ptp_reset(adapter);
 }
 
 /**
@@ -4393,11 +4426,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
 	if (!pci_channel_offline(adapter->pdev))
 		ixgbe_reset(adapter);
 
-	/* power down the optics for multispeed fiber and 82599 SFP+ fiber */
-	if (hw->mac.ops.disable_tx_laser &&
-	    ((hw->phy.multispeed_fiber) ||
-	     ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
-	      (hw->mac.type == ixgbe_mac_82599EB))))
+	/* power down the optics for 82599 SFP+ fiber */
+	if (hw->mac.ops.disable_tx_laser)
 		hw->mac.ops.disable_tx_laser(hw);
 
 	ixgbe_clean_all_tx_rings(adapter);
@@ -4533,7 +4563,8 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
 	ixgbe_pbthresh_setup(adapter);
 	hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE;
 	hw->fc.send_xon = true;
-	hw->fc.disable_fc_autoneg = false;
+	hw->fc.disable_fc_autoneg =
+		(ixgbe_device_supports_autoneg_fc(hw) == 0) ? false : true;
 
 #ifdef CONFIG_PCI_IOV
 	/* assign number of SR-IOV VFs */
@@ -4828,14 +4859,14 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
 		return -EINVAL;
 
 	/*
-	 * For 82599EB we cannot allow PF to change MTU greater than 1500
-	 * in SR-IOV mode as it may cause buffer overruns in guest VFs that
-	 * don't allocate and chain buffers correctly.
+	 * For 82599EB we cannot allow legacy VFs to enable their receive
+	 * paths when MTU greater than 1500 is configured.  So display a
+	 * warning that legacy VFs will be disabled.
 	 */
 	if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) &&
 	    (adapter->hw.mac.type == ixgbe_mac_82599EB) &&
 	    (max_frame > MAXIMUM_ETHERNET_VLAN_SIZE))
-			return -EINVAL;
+		e_warn(probe, "Setting MTU > 1500 will disable legacy VFs\n");
 
 	e_info(probe, "changing MTU from %d to %d\n", netdev->mtu, new_mtu);
 
@@ -4901,6 +4932,8 @@ static int ixgbe_open(struct net_device *netdev)
 	if (err)
 		goto err_set_queues;
 
+	ixgbe_ptp_init(adapter);
+
 	ixgbe_up_complete(adapter);
 
 	return 0;
@@ -4932,6 +4965,8 @@ static int ixgbe_close(struct net_device *netdev)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
+	ixgbe_ptp_stop(adapter);
+
 	ixgbe_down(adapter);
 	ixgbe_free_irq(adapter);
 
@@ -5022,14 +5057,8 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
 	if (wufc) {
 		ixgbe_set_rx_mode(netdev);
 
-		/*
-		 * enable the optics for both mult-speed fiber and
-		 * 82599 SFP+ fiber as we can WoL.
-		 */
-		if (hw->mac.ops.enable_tx_laser &&
-		    (hw->phy.multispeed_fiber ||
-		    (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber &&
-		     hw->mac.type == ixgbe_mac_82599EB)))
+		/* enable the optics for 82599 SFP+ fiber as we can WoL */
+		if (hw->mac.ops.enable_tx_laser)
 			hw->mac.ops.enable_tx_laser(hw);
 
 		/* turn on all-multi mode if wake on multicast is enabled */
@@ -5442,6 +5471,23 @@ static void ixgbe_watchdog_update_link(struct ixgbe_adapter *adapter)
 	adapter->link_speed = link_speed;
 }
 
+static void ixgbe_update_default_up(struct ixgbe_adapter *adapter)
+{
+#ifdef CONFIG_IXGBE_DCB
+	struct net_device *netdev = adapter->netdev;
+	struct dcb_app app = {
+			      .selector = IEEE_8021QAZ_APP_SEL_ETHERTYPE,
+			      .protocol = 0,
+			     };
+	u8 up = 0;
+
+	if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)
+		up = dcb_ieee_getapp_mask(netdev, &app);
+
+	adapter->default_up = (up > 1) ? (ffs(up) - 1) : 0;
+#endif
+}
+
 /**
  * ixgbe_watchdog_link_is_up - update netif_carrier status and
  *                             print link up message
@@ -5482,9 +5528,8 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
 		break;
 	}
 
-#ifdef CONFIG_IXGBE_PTP
-	ixgbe_ptp_start_cyclecounter(adapter);
-#endif
+	if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED)
+		ixgbe_ptp_start_cyclecounter(adapter);
 
 	e_info(drv, "NIC Link is Up %s, Flow Control: %s\n",
 	       (link_speed == IXGBE_LINK_SPEED_10GB_FULL ?
@@ -5501,6 +5546,9 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
 	netif_carrier_on(netdev);
 	ixgbe_check_vf_rate_limit(adapter);
 
+	/* update the default user priority for VFs */
+	ixgbe_update_default_up(adapter);
+
 	/* ping all the active vfs to let them know link has changed */
 	ixgbe_ping_all_vfs(adapter);
 }
@@ -5526,9 +5574,8 @@ static void ixgbe_watchdog_link_is_down(struct ixgbe_adapter *adapter)
 	if (ixgbe_is_sfp(hw) && hw->mac.type == ixgbe_mac_82598EB)
 		adapter->flags2 |= IXGBE_FLAG2_SEARCH_FOR_SFP;
 
-#ifdef CONFIG_IXGBE_PTP
-	ixgbe_ptp_start_cyclecounter(adapter);
-#endif
+	if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED)
+		ixgbe_ptp_start_cyclecounter(adapter);
 
 	e_info(drv, "NIC Link is Down\n");
 	netif_carrier_off(netdev);
@@ -5833,9 +5880,7 @@ static void ixgbe_service_task(struct work_struct *work)
 	ixgbe_watchdog_subtask(adapter);
 	ixgbe_fdir_reinit_subtask(adapter);
 	ixgbe_check_hang_subtask(adapter);
-#ifdef CONFIG_IXGBE_PTP
 	ixgbe_ptp_overflow_check(adapter);
-#endif
 
 	ixgbe_service_event_complete(adapter);
 }
@@ -5988,10 +6033,8 @@ static __le32 ixgbe_tx_cmd_type(u32 tx_flags)
 	if (tx_flags & IXGBE_TX_FLAGS_HW_VLAN)
 		cmd_type |= cpu_to_le32(IXGBE_ADVTXD_DCMD_VLE);
 
-#ifdef CONFIG_IXGBE_PTP
 	if (tx_flags & IXGBE_TX_FLAGS_TSTAMP)
 		cmd_type |= cpu_to_le32(IXGBE_ADVTXD_MAC_TSTAMP);
-#endif
 
 	/* set segmentation enable bits for TSO/FSO */
 #ifdef IXGBE_FCOE
@@ -6393,12 +6436,10 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
 
 	skb_tx_timestamp(skb);
 
-#ifdef CONFIG_IXGBE_PTP
 	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 		tx_flags |= IXGBE_TX_FLAGS_TSTAMP;
 	}
-#endif
 
 #ifdef CONFIG_PCI_IOV
 	/*
@@ -6485,6 +6526,7 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
 		if (skb_pad(skb, 17 - skb->len))
 			return NETDEV_TX_OK;
 		skb->len = 17;
+		skb_set_tail_pointer(skb, 17);
 	}
 
 	tx_ring = adapter->tx_ring[skb->queue_mapping];
@@ -6547,10 +6589,8 @@ static int ixgbe_ioctl(struct net_device *netdev, struct ifreq *req, int cmd)
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
 	switch (cmd) {
-#ifdef CONFIG_IXGBE_PTP
 	case SIOCSHWTSTAMP:
 		return ixgbe_ptp_hwtstamp_ioctl(adapter, req, cmd);
-#endif
 	default:
 		return mdio_mii_ioctl(&adapter->hw.phy.mdio, if_mii(req), cmd);
 	}
@@ -6910,13 +6950,16 @@ static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 	if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
 		return -EOPNOTSUPP;
 
-	if (ndm->ndm_state & NUD_PERMANENT) {
+	/* Hardware does not support aging addresses so if a
+	 * ndm_state is given only allow permanent addresses
+	 */
+	if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) {
 		pr_info("%s: FDB only supports static addresses\n",
 			ixgbe_driver_name);
 		return -EINVAL;
 	}
 
-	if (is_unicast_ether_addr(addr)) {
+	if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) {
 		u32 rar_uc_entries = IXGBE_MAX_PF_MACVLANS;
 
 		if (netdev_uc_count(dev) < rar_uc_entries)
@@ -6974,6 +7017,61 @@ static int ixgbe_ndo_fdb_dump(struct sk_buff *skb,
 	return idx;
 }
 
+static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
+				    struct nlmsghdr *nlh)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	struct nlattr *attr, *br_spec;
+	int rem;
+
+	if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
+		return -EOPNOTSUPP;
+
+	br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
+
+	nla_for_each_nested(attr, br_spec, rem) {
+		__u16 mode;
+		u32 reg = 0;
+
+		if (nla_type(attr) != IFLA_BRIDGE_MODE)
+			continue;
+
+		mode = nla_get_u16(attr);
+		if (mode == BRIDGE_MODE_VEPA) {
+			reg = 0;
+			adapter->flags2 &= ~IXGBE_FLAG2_BRIDGE_MODE_VEB;
+		} else if (mode == BRIDGE_MODE_VEB) {
+			reg = IXGBE_PFDTXGSWC_VT_LBEN;
+			adapter->flags2 |= IXGBE_FLAG2_BRIDGE_MODE_VEB;
+		} else
+			return -EINVAL;
+
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_PFDTXGSWC, reg);
+
+		e_info(drv, "enabling bridge mode: %s\n",
+			mode == BRIDGE_MODE_VEPA ? "VEPA" : "VEB");
+	}
+
+	return 0;
+}
+
+static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+				    struct net_device *dev)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	u16 mode;
+
+	if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
+		return 0;
+
+	if (adapter->flags2 & IXGBE_FLAG2_BRIDGE_MODE_VEB)
+		mode = BRIDGE_MODE_VEB;
+	else
+		mode = BRIDGE_MODE_VEPA;
+
+	return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode);
+}
+
 static const struct net_device_ops ixgbe_netdev_ops = {
 	.ndo_open		= ixgbe_open,
 	.ndo_stop		= ixgbe_close,
@@ -7013,6 +7111,8 @@ static const struct net_device_ops ixgbe_netdev_ops = {
 	.ndo_fdb_add		= ixgbe_ndo_fdb_add,
 	.ndo_fdb_del		= ixgbe_ndo_fdb_del,
 	.ndo_fdb_dump		= ixgbe_ndo_fdb_dump,
+	.ndo_bridge_setlink	= ixgbe_ndo_bridge_setlink,
+	.ndo_bridge_getlink	= ixgbe_ndo_bridge_getlink,
 };
 
 /**
@@ -7042,6 +7142,7 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
 				break;
 		case IXGBE_SUBDEV_ID_82599_SFP:
 		case IXGBE_SUBDEV_ID_82599_RNDC:
+		case IXGBE_SUBDEV_ID_82599_ECNA_DP:
 			is_wol_supported = 1;
 			break;
 		}
@@ -7364,10 +7465,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 
 	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
 
-#ifdef CONFIG_IXGBE_PTP
-	ixgbe_ptp_init(adapter);
-#endif /* CONFIG_IXGBE_PTP*/
-
 	/* save off EEPROM version number */
 	hw->eeprom.ops.read(hw, 0x2e, &adapter->eeprom_verh);
 	hw->eeprom.ops.read(hw, 0x2d, &adapter->eeprom_verl);
@@ -7420,11 +7517,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 	if (err)
 		goto err_register;
 
-	/* power down the optics for multispeed fiber and 82599 SFP+ fiber */
-	if (hw->mac.ops.disable_tx_laser &&
-	    ((hw->phy.multispeed_fiber) ||
-	     ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
-	      (hw->mac.type == ixgbe_mac_82599EB))))
+	/* power down the optics for 82599 SFP+ fiber */
+	if (hw->mac.ops.disable_tx_laser)
 		hw->mac.ops.disable_tx_laser(hw);
 
 	/* carrier off reporting is important to ethtool even BEFORE open */
@@ -7505,9 +7599,6 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
 	set_bit(__IXGBE_DOWN, &adapter->state);
 	cancel_work_sync(&adapter->service_task);
 
-#ifdef CONFIG_IXGBE_PTP
-	ixgbe_ptp_stop(adapter);
-#endif
 
 #ifdef CONFIG_IXGBE_DCA
 	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
index 310bdd9..42dd65e 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
@@ -62,12 +62,39 @@
 /* bits 23:16 are used for exra info for certain messages */
 #define IXGBE_VT_MSGINFO_MASK     (0xFF << IXGBE_VT_MSGINFO_SHIFT)
 
+/* definitions to support mailbox API version negotiation */
+
+/*
+ * Each element denotes a version of the API; existing numbers may not
+ * change; any additions must go at the end
+ */
+enum ixgbe_pfvf_api_rev {
+	ixgbe_mbox_api_10,	/* API version 1.0, linux/freebsd VF driver */
+	ixgbe_mbox_api_20,	/* API version 2.0, solaris Phase1 VF driver */
+	ixgbe_mbox_api_11,	/* API version 1.1, linux/freebsd VF driver */
+	/* This value should always be last */
+	ixgbe_mbox_api_unknown,	/* indicates that API version is not known */
+};
+
+/* mailbox API, legacy requests */
 #define IXGBE_VF_RESET            0x01 /* VF requests reset */
 #define IXGBE_VF_SET_MAC_ADDR     0x02 /* VF requests PF to set MAC addr */
 #define IXGBE_VF_SET_MULTICAST    0x03 /* VF requests PF to set MC addr */
 #define IXGBE_VF_SET_VLAN         0x04 /* VF requests PF to set VLAN */
-#define IXGBE_VF_SET_LPE          0x05 /* VF requests PF to set VMOLR.LPE */
-#define IXGBE_VF_SET_MACVLAN      0x06 /* VF requests PF for unicast filter */
+
+/* mailbox API, version 1.0 VF requests */
+#define IXGBE_VF_SET_LPE	0x05 /* VF requests PF to set VMOLR.LPE */
+#define IXGBE_VF_SET_MACVLAN	0x06 /* VF requests PF for unicast filter */
+#define IXGBE_VF_API_NEGOTIATE	0x08 /* negotiate API version */
+
+/* mailbox API, version 1.1 VF requests */
+#define IXGBE_VF_GET_QUEUES	0x09 /* get queue configuration */
+
+/* GET_QUEUES return data indices within the mailbox */
+#define IXGBE_VF_TX_QUEUES	1	/* number of Tx queues supported */
+#define IXGBE_VF_RX_QUEUES	2	/* number of Rx queues supported */
+#define IXGBE_VF_TRANS_VLAN	3	/* Indication of port vlan */
+#define IXGBE_VF_DEF_QUEUE	4	/* Default queue offset */
 
 /* length of permanent address message returned from PF */
 #define IXGBE_VF_PERMADDR_MSG_LEN 4
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
index d929131..1a751c9 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
@@ -387,6 +387,15 @@ void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr)
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct ptp_clock_event event;
 
+	event.type = PTP_CLOCK_PPS;
+
+	/* this check is necessary in case the interrupt was enabled via some
+	 * alternative means (ex. debug_fs). Better to check here than
+	 * everywhere that calls this function.
+	 */
+	if (!adapter->ptp_clock)
+		return;
+
 	switch (hw->mac.type) {
 	case ixgbe_mac_X540:
 		ptp_clock_event(adapter->ptp_clock, &event);
@@ -411,7 +420,7 @@ void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter)
 	unsigned long elapsed_jiffies = adapter->last_overflow_check - jiffies;
 	struct timespec ts;
 
-	if ((adapter->flags2 & IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED) &&
+	if ((adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED) &&
 	    (elapsed_jiffies >= IXGBE_OVERFLOW_PERIOD)) {
 		ixgbe_ptp_gettime(&adapter->ptp_caps, &ts);
 		adapter->last_overflow_check = jiffies;
@@ -554,12 +563,14 @@ void ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector,
 	adapter = q_vector->adapter;
 	hw = &adapter->hw;
 
+	if (likely(!ixgbe_ptp_match(skb, adapter->rx_hwtstamp_filter)))
+		return;
+
 	tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL);
 
 	/* Check if we have a valid timestamp and make sure the skb should
 	 * have been timestamped */
-	if (likely(!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID) ||
-		   !ixgbe_ptp_match(skb, adapter->rx_hwtstamp_filter)))
+	if (!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID))
 		return;
 
 	/*
@@ -622,8 +633,7 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
 	struct hwtstamp_config config;
 	u32 tsync_tx_ctl = IXGBE_TSYNCTXCTL_ENABLED;
 	u32 tsync_rx_ctl = IXGBE_TSYNCRXCTL_ENABLED;
-	u32 tsync_rx_mtrl = 0;
-	bool is_l4 = false;
+	u32 tsync_rx_mtrl = PTP_EV_PORT << 16;
 	bool is_l2 = false;
 	u32 regval;
 
@@ -646,16 +656,15 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
 	switch (config.rx_filter) {
 	case HWTSTAMP_FILTER_NONE:
 		tsync_rx_ctl = 0;
+		tsync_rx_mtrl = 0;
 		break;
 	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
 		tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
 		tsync_rx_mtrl = IXGBE_RXMTRL_V1_SYNC_MSG;
-		is_l4 = true;
 		break;
 	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
 		tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
 		tsync_rx_mtrl = IXGBE_RXMTRL_V1_DELAY_REQ_MSG;
-		is_l4 = true;
 		break;
 	case HWTSTAMP_FILTER_PTP_V2_EVENT:
 	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
@@ -668,7 +677,6 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
 	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
 		tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_EVENT_V2;
 		is_l2 = true;
-		is_l4 = true;
 		config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
 		break;
 	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
@@ -693,42 +701,15 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
 	/* Store filter value for later use */
 	adapter->rx_hwtstamp_filter = config.rx_filter;
 
-	/* define ethertype filter for timestamped packets */
+	/* define ethertype filter for timestamping L2 packets */
 	if (is_l2)
-		IXGBE_WRITE_REG(hw, IXGBE_ETQF(3),
+		IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_1588),
 				(IXGBE_ETQF_FILTER_EN | /* enable filter */
 				 IXGBE_ETQF_1588 | /* enable timestamping */
 				 ETH_P_1588));     /* 1588 eth protocol type */
 	else
-		IXGBE_WRITE_REG(hw, IXGBE_ETQF(3), 0);
-
-#define PTP_PORT 319
-	/* L4 Queue Filter[3]: filter by destination port and protocol */
-	if (is_l4) {
-		u32 ftqf = (IXGBE_FTQF_PROTOCOL_UDP /* UDP */
-			    | IXGBE_FTQF_POOL_MASK_EN /* Pool not compared */
-			    | IXGBE_FTQF_QUEUE_ENABLE);
-
-		ftqf |= ((IXGBE_FTQF_PROTOCOL_COMP_MASK /* protocol check */
-			  & IXGBE_FTQF_DEST_PORT_MASK /* dest check */
-			  & IXGBE_FTQF_SOURCE_PORT_MASK) /* source check */
-			 << IXGBE_FTQF_5TUPLE_MASK_SHIFT);
+		IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_1588), 0);
 
-		IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(3),
-				(3 << IXGBE_IMIR_RX_QUEUE_SHIFT_82599 |
-				 IXGBE_IMIR_SIZE_BP_82599));
-
-		/* enable port check */
-		IXGBE_WRITE_REG(hw, IXGBE_SDPQF(3),
-				(htons(PTP_PORT) |
-				 htons(PTP_PORT) << 16));
-
-		IXGBE_WRITE_REG(hw, IXGBE_FTQF(3), ftqf);
-
-		tsync_rx_mtrl |= PTP_PORT << 16;
-	} else {
-		IXGBE_WRITE_REG(hw, IXGBE_FTQF(3), 0);
-	}
 
 	/* enable/disable TX */
 	regval = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL);
@@ -759,58 +740,20 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
  * ixgbe_ptp_start_cyclecounter - create the cycle counter from hw
  * @adapter: pointer to the adapter structure
  *
- * this function initializes the timecounter and cyclecounter
- * structures for use in generated a ns counter from the arbitrary
- * fixed point cycles registers in the hardware.
- *
- * A change in link speed impacts the frequency of the DMA clock on
- * the device, which is used to generate the cycle counter
- * registers. Therefor this function is called whenever the link speed
- * changes.
- *
- * This function also turns on the SDP pin for clock out feature (X540
- * only), because this is where the shift is first calculated.
+ * This function should be called to set the proper values for the TIMINCA
+ * register and tell the cyclecounter structure what the tick rate of SYSTIME
+ * is. It does not directly modify SYSTIME registers or the timecounter
+ * structure. It should be called whenever a new TIMINCA value is necessary,
+ * such as during initialization or when the link speed changes.
  */
 void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 incval = 0;
-	u32 timinca = 0;
 	u32 shift = 0;
-	u32 cycle_speed;
 	unsigned long flags;
 
 	/**
-	 * Determine what speed we need to set the cyclecounter
-	 * for. It should be different for 100Mb, 1Gb, and 10Gb. Treat
-	 * unknown speeds as 10Gb. (Hence why we can't just copy the
-	 * link_speed.
-	 */
-	switch (adapter->link_speed) {
-	case IXGBE_LINK_SPEED_100_FULL:
-	case IXGBE_LINK_SPEED_1GB_FULL:
-	case IXGBE_LINK_SPEED_10GB_FULL:
-		cycle_speed = adapter->link_speed;
-		break;
-	default:
-		/* cycle speed should be 10Gb when there is no link */
-		cycle_speed = IXGBE_LINK_SPEED_10GB_FULL;
-		break;
-	}
-
-	/*
-	 * grab the current TIMINCA value from the register so that it can be
-	 * double checked. If the register value has been cleared, it must be
-	 * reset to the correct value for generating a cyclecounter. If
-	 * TIMINCA is zero, the SYSTIME registers do not increment at all.
-	 */
-	timinca = IXGBE_READ_REG(hw, IXGBE_TIMINCA);
-
-	/* Bail if the cycle speed didn't change and TIMINCA is non-zero */
-	if (adapter->cycle_speed == cycle_speed && timinca)
-		return;
-
-	/**
 	 * Scale the NIC cycle counter by a large factor so that
 	 * relatively small corrections to the frequency can be added
 	 * or subtracted. The drawbacks of a large factor include
@@ -819,8 +762,12 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
 	 * to nanoseconds using only a multiplier and a right-shift,
 	 * and (c) the value must fit within the timinca register space
 	 * => math based on internal DMA clock rate and available bits
+	 *
+	 * Note that when there is no link, internal DMA clock is same as when
+	 * link speed is 10Gb. Set the registers correctly even when link is
+	 * down to preserve the clock setting
 	 */
-	switch (cycle_speed) {
+	switch (adapter->link_speed) {
 	case IXGBE_LINK_SPEED_100_FULL:
 		incval = IXGBE_INCVAL_100;
 		shift = IXGBE_INCVAL_SHIFT_100;
@@ -830,6 +777,7 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
 		shift = IXGBE_INCVAL_SHIFT_1GB;
 		break;
 	case IXGBE_LINK_SPEED_10GB_FULL:
+	default:
 		incval = IXGBE_INCVAL_10GB;
 		shift = IXGBE_INCVAL_SHIFT_10GB;
 		break;
@@ -857,18 +805,11 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
 		return;
 	}
 
-	/* reset the system time registers */
-	IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000);
-	IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000);
-	IXGBE_WRITE_FLUSH(hw);
-
-	/* store the new cycle speed */
-	adapter->cycle_speed = cycle_speed;
-
+	/* update the base incval used to calculate frequency adjustment */
 	ACCESS_ONCE(adapter->base_incval) = incval;
 	smp_mb();
 
-	/* grab the ptp lock */
+	/* need lock to prevent incorrect read while modifying cyclecounter */
 	spin_lock_irqsave(&adapter->tmreg_lock, flags);
 
 	memset(&adapter->cc, 0, sizeof(adapter->cc));
@@ -877,6 +818,31 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
 	adapter->cc.shift = shift;
 	adapter->cc.mult = 1;
 
+	spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+}
+
+/**
+ * ixgbe_ptp_reset
+ * @adapter: the ixgbe private board structure
+ *
+ * When the MAC resets, all timesync features are reset. This function should be
+ * called to re-enable the PTP clock structure. It will re-init the timecounter
+ * structure based on the kernel time as well as setup the cycle counter data.
+ */
+void ixgbe_ptp_reset(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	unsigned long flags;
+
+	/* set SYSTIME registers to 0 just in case */
+	IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000);
+	IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000);
+	IXGBE_WRITE_FLUSH(hw);
+
+	ixgbe_ptp_start_cyclecounter(adapter);
+
+	spin_lock_irqsave(&adapter->tmreg_lock, flags);
+
 	/* reset the ns time counter */
 	timecounter_init(&adapter->tc, &adapter->cc,
 			 ktime_to_ns(ktime_get_real()));
@@ -904,7 +870,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
 
 	switch (adapter->hw.mac.type) {
 	case ixgbe_mac_X540:
-		snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
+		snprintf(adapter->ptp_caps.name, 16, "%s", netdev->name);
 		adapter->ptp_caps.owner = THIS_MODULE;
 		adapter->ptp_caps.max_adj = 250000000;
 		adapter->ptp_caps.n_alarm = 0;
@@ -918,7 +884,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
 		adapter->ptp_caps.enable = ixgbe_ptp_enable;
 		break;
 	case ixgbe_mac_82599EB:
-		snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
+		snprintf(adapter->ptp_caps.name, 16, "%s", netdev->name);
 		adapter->ptp_caps.owner = THIS_MODULE;
 		adapter->ptp_caps.max_adj = 250000000;
 		adapter->ptp_caps.n_alarm = 0;
@@ -942,11 +908,6 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
 
 	spin_lock_init(&adapter->tmreg_lock);
 
-	ixgbe_ptp_start_cyclecounter(adapter);
-
-	/* (Re)start the overflow check */
-	adapter->flags2 |= IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED;
-
 	adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps,
 						&adapter->pdev->dev);
 	if (IS_ERR(adapter->ptp_clock)) {
@@ -955,6 +916,11 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
 	} else
 		e_dev_info("registered PHC device on %s\n", netdev->name);
 
+	ixgbe_ptp_reset(adapter);
+
+	/* set the flag that PTP has been enabled */
+	adapter->flags2 |= IXGBE_FLAG2_PTP_ENABLED;
+
 	return;
 }
 
@@ -967,7 +933,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
 void ixgbe_ptp_stop(struct ixgbe_adapter *adapter)
 {
 	/* stop the overflow check task */
-	adapter->flags2 &= ~(IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED |
+	adapter->flags2 &= ~(IXGBE_FLAG2_PTP_ENABLED |
 			     IXGBE_FLAG2_PTP_PPS_ENABLED);
 
 	ixgbe_ptp_setup_sdp(adapter);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index dce48bf..85cddac 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -117,6 +117,10 @@ void ixgbe_enable_sriov(struct ixgbe_adapter *adapter,
 		}
 	}
 
+	/* Initialize default switching mode VEB */
+	IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
+	adapter->flags2 |= IXGBE_FLAG2_BRIDGE_MODE_VEB;
+
 	/* If call to enable VFs succeeded then allocate memory
 	 * for per VF control structures.
 	 */
@@ -150,16 +154,6 @@ void ixgbe_enable_sriov(struct ixgbe_adapter *adapter,
 		adapter->flags2 &= ~(IXGBE_FLAG2_RSC_CAPABLE |
 				     IXGBE_FLAG2_RSC_ENABLED);
 
-#ifdef IXGBE_FCOE
-		/*
-		 * When SR-IOV is enabled 82599 cannot support jumbo frames
-		 * so we must disable FCoE because we cannot support FCoE MTU.
-		 */
-		if (adapter->hw.mac.type == ixgbe_mac_82599EB)
-			adapter->flags &= ~(IXGBE_FLAG_FCOE_ENABLED |
-					    IXGBE_FLAG_FCOE_CAPABLE);
-#endif
-
 		/* enable spoof checking for all VFs */
 		for (i = 0; i < adapter->num_vfs; i++)
 			adapter->vfinfo[i].spoofchk_enabled = true;
@@ -265,8 +259,11 @@ void ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
 }
 
 static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
-				   int entries, u16 *hash_list, u32 vf)
+				   u32 *msgbuf, u32 vf)
 {
+	int entries = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK)
+		       >> IXGBE_VT_MSGINFO_SHIFT;
+	u16 *hash_list = (u16 *)&msgbuf[1];
 	struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];
 	struct ixgbe_hw *hw = &adapter->hw;
 	int i;
@@ -353,31 +350,89 @@ static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid,
 	return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add);
 }
 
-static void ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf)
+static s32 ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	int new_mtu = msgbuf[1];
+	int max_frame = msgbuf[1];
 	u32 max_frs;
-	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
 
-	/* Only X540 supports jumbo frames in IOV mode */
-	if (adapter->hw.mac.type != ixgbe_mac_X540)
-		return;
+	/*
+	 * For 82599EB we have to keep all PFs and VFs operating with
+	 * the same max_frame value in order to avoid sending an oversize
+	 * frame to a VF.  In order to guarantee this is handled correctly
+	 * for all cases we have several special exceptions to take into
+	 * account before we can enable the VF for receive
+	 */
+	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+		struct net_device *dev = adapter->netdev;
+		int pf_max_frame = dev->mtu + ETH_HLEN;
+		u32 reg_offset, vf_shift, vfre;
+		s32 err = 0;
+
+#ifdef CONFIG_FCOE
+		if (dev->features & NETIF_F_FCOE_MTU)
+			pf_max_frame = max_t(int, pf_max_frame,
+					     IXGBE_FCOE_JUMBO_FRAME_SIZE);
+
+#endif /* CONFIG_FCOE */
+		switch (adapter->vfinfo[vf].vf_api) {
+		case ixgbe_mbox_api_11:
+			/*
+			 * Version 1.1 supports jumbo frames on VFs if PF has
+			 * jumbo frames enabled which means legacy VFs are
+			 * disabled
+			 */
+			if (pf_max_frame > ETH_FRAME_LEN)
+				break;
+		default:
+			/*
+			 * If the PF or VF are running w/ jumbo frames enabled
+			 * we need to shut down the VF Rx path as we cannot
+			 * support jumbo frames on legacy VFs
+			 */
+			if ((pf_max_frame > ETH_FRAME_LEN) ||
+			    (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)))
+				err = -EINVAL;
+			break;
+		}
+
+		/* determine VF receive enable location */
+		vf_shift = vf % 32;
+		reg_offset = vf / 32;
+
+		/* enable or disable receive depending on error */
+		vfre = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset));
+		if (err)
+			vfre &= ~(1 << vf_shift);
+		else
+			vfre |= 1 << vf_shift;
+		IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), vfre);
+
+		if (err) {
+			e_err(drv, "VF max_frame %d out of range\n", max_frame);
+			return err;
+		}
+	}
 
 	/* MTU < 68 is an error and causes problems on some kernels */
-	if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE)) {
-		e_err(drv, "VF mtu %d out of range\n", new_mtu);
-		return;
+	if (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE) {
+		e_err(drv, "VF max_frame %d out of range\n", max_frame);
+		return -EINVAL;
 	}
 
-	max_frs = (IXGBE_READ_REG(hw, IXGBE_MAXFRS) &
-		   IXGBE_MHADD_MFS_MASK) >> IXGBE_MHADD_MFS_SHIFT;
-	if (max_frs < new_mtu) {
-		max_frs = new_mtu << IXGBE_MHADD_MFS_SHIFT;
+	/* pull current max frame size from hardware */
+	max_frs = IXGBE_READ_REG(hw, IXGBE_MAXFRS);
+	max_frs &= IXGBE_MHADD_MFS_MASK;
+	max_frs >>= IXGBE_MHADD_MFS_SHIFT;
+
+	if (max_frs < max_frame) {
+		max_frs = max_frame << IXGBE_MHADD_MFS_SHIFT;
 		IXGBE_WRITE_REG(hw, IXGBE_MAXFRS, max_frs);
 	}
 
-	e_info(hw, "VF requests change max MTU to %d\n", new_mtu);
+	e_info(hw, "VF requests change max MTU to %d\n", max_frame);
+
+	return 0;
 }
 
 static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
@@ -392,35 +447,47 @@ static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
 	IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr);
 }
 
-static void ixgbe_set_vmvir(struct ixgbe_adapter *adapter, u32 vid, u32 vf)
+static void ixgbe_set_vmvir(struct ixgbe_adapter *adapter,
+			    u16 vid, u16 qos, u32 vf)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
+	u32 vmvir = vid | (qos << VLAN_PRIO_SHIFT) | IXGBE_VMVIR_VLANA_DEFAULT;
 
-	if (vid)
-		IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf),
-				(vid | IXGBE_VMVIR_VLANA_DEFAULT));
-	else
-		IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), vmvir);
 }
 
+static void ixgbe_clear_vmvir(struct ixgbe_adapter *adapter, u32 vf)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+
+	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0);
+}
 static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
+	struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];
 	int rar_entry = hw->mac.num_rar_entries - (vf + 1);
+	u8 num_tcs = netdev_get_num_tc(adapter->netdev);
+
+	/* add PF assigned VLAN or VLAN 0 */
+	ixgbe_set_vf_vlan(adapter, true, vfinfo->pf_vlan, vf);
 
 	/* reset offloads to defaults */
-	if (adapter->vfinfo[vf].pf_vlan) {
-		ixgbe_set_vf_vlan(adapter, true,
-				  adapter->vfinfo[vf].pf_vlan, vf);
-		ixgbe_set_vmvir(adapter,
-				(adapter->vfinfo[vf].pf_vlan |
-				 (adapter->vfinfo[vf].pf_qos <<
-				  VLAN_PRIO_SHIFT)), vf);
-		ixgbe_set_vmolr(hw, vf, false);
+	ixgbe_set_vmolr(hw, vf, !vfinfo->pf_vlan);
+
+	/* set outgoing tags for VFs */
+	if (!vfinfo->pf_vlan && !vfinfo->pf_qos && !num_tcs) {
+		ixgbe_clear_vmvir(adapter, vf);
 	} else {
-		ixgbe_set_vf_vlan(adapter, true, 0, vf);
-		ixgbe_set_vmvir(adapter, 0, vf);
-		ixgbe_set_vmolr(hw, vf, true);
+		if (vfinfo->pf_qos || !num_tcs)
+			ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
+					vfinfo->pf_qos, vf);
+		else
+			ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
+					adapter->default_up, vf);
+
+		if (vfinfo->spoofchk_enabled)
+			hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
 	}
 
 	/* reset multicast table array for vf */
@@ -430,6 +497,9 @@ static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
 	ixgbe_set_rx_mode(adapter->netdev);
 
 	hw->mac.ops.clear_rar(hw, rar_entry);
+
+	/* reset VF api back to unknown */
+	adapter->vfinfo[vf].vf_api = ixgbe_mbox_api_10;
 }
 
 static int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter,
@@ -521,30 +591,221 @@ int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask)
 	return 0;
 }
 
-static inline void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
+static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32 reg;
+	unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses;
+	u32 reg, msgbuf[4];
 	u32 reg_offset, vf_shift;
+	u8 *addr = (u8 *)(&msgbuf[1]);
+
+	e_info(probe, "VF Reset msg received from vf %d\n", vf);
+
+	/* reset the filters for the device */
+	ixgbe_vf_reset_event(adapter, vf);
+
+	/* set vf mac address */
+	ixgbe_set_vf_mac(adapter, vf, vf_mac);
 
 	vf_shift = vf % 32;
 	reg_offset = vf / 32;
 
-	/* enable transmit and receive for vf */
+	/* enable transmit for vf */
 	reg = IXGBE_READ_REG(hw, IXGBE_VFTE(reg_offset));
-	reg |= (reg | (1 << vf_shift));
+	reg |= 1 << vf_shift;
 	IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), reg);
 
+	/* enable receive for vf */
 	reg = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset));
-	reg |= (reg | (1 << vf_shift));
+	reg |= 1 << vf_shift;
+	/*
+	 * The 82599 cannot support a mix of jumbo and non-jumbo PF/VFs.
+	 * For more info take a look at ixgbe_set_vf_lpe
+	 */
+	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+		struct net_device *dev = adapter->netdev;
+		int pf_max_frame = dev->mtu + ETH_HLEN;
+
+#ifdef CONFIG_FCOE
+		if (dev->features & NETIF_F_FCOE_MTU)
+			pf_max_frame = max_t(int, pf_max_frame,
+					     IXGBE_FCOE_JUMBO_FRAME_SIZE);
+
+#endif /* CONFIG_FCOE */
+		if (pf_max_frame > ETH_FRAME_LEN)
+			reg &= ~(1 << vf_shift);
+	}
 	IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), reg);
 
+	/* enable VF mailbox for further messages */
+	adapter->vfinfo[vf].clear_to_send = true;
+
 	/* Enable counting of spoofed packets in the SSVPC register */
 	reg = IXGBE_READ_REG(hw, IXGBE_VMECM(reg_offset));
 	reg |= (1 << vf_shift);
 	IXGBE_WRITE_REG(hw, IXGBE_VMECM(reg_offset), reg);
 
-	ixgbe_vf_reset_event(adapter, vf);
+	/* reply to reset with ack and vf mac address */
+	msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK;
+	memcpy(addr, vf_mac, ETH_ALEN);
+
+	/*
+	 * Piggyback the multicast filter type so VF can compute the
+	 * correct vectors
+	 */
+	msgbuf[3] = hw->mac.mc_filter_type;
+	ixgbe_write_mbx(hw, msgbuf, IXGBE_VF_PERMADDR_MSG_LEN, vf);
+
+	return 0;
+}
+
+static int ixgbe_set_vf_mac_addr(struct ixgbe_adapter *adapter,
+				 u32 *msgbuf, u32 vf)
+{
+	u8 *new_mac = ((u8 *)(&msgbuf[1]));
+
+	if (!is_valid_ether_addr(new_mac)) {
+		e_warn(drv, "VF %d attempted to set invalid mac\n", vf);
+		return -1;
+	}
+
+	if (adapter->vfinfo[vf].pf_set_mac &&
+	    memcmp(adapter->vfinfo[vf].vf_mac_addresses, new_mac,
+		   ETH_ALEN)) {
+		e_warn(drv,
+		       "VF %d attempted to override administratively set MAC address\n"
+		       "Reload the VF driver to resume operations\n",
+		       vf);
+		return -1;
+	}
+
+	return ixgbe_set_vf_mac(adapter, vf, new_mac) < 0;
+}
+
+static int ixgbe_set_vf_vlan_msg(struct ixgbe_adapter *adapter,
+				 u32 *msgbuf, u32 vf)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	int add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT;
+	int vid = (msgbuf[1] & IXGBE_VLVF_VLANID_MASK);
+	int err;
+	u8 tcs = netdev_get_num_tc(adapter->netdev);
+
+	if (adapter->vfinfo[vf].pf_vlan || tcs) {
+		e_warn(drv,
+		       "VF %d attempted to override administratively set VLAN configuration\n"
+		       "Reload the VF driver to resume operations\n",
+		       vf);
+		return -1;
+	}
+
+	if (add)
+		adapter->vfinfo[vf].vlan_count++;
+	else if (adapter->vfinfo[vf].vlan_count)
+		adapter->vfinfo[vf].vlan_count--;
+
+	err = ixgbe_set_vf_vlan(adapter, add, vid, vf);
+	if (!err && adapter->vfinfo[vf].spoofchk_enabled)
+		hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
+
+	return err;
+}
+
+static int ixgbe_set_vf_macvlan_msg(struct ixgbe_adapter *adapter,
+				    u32 *msgbuf, u32 vf)
+{
+	u8 *new_mac = ((u8 *)(&msgbuf[1]));
+	int index = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >>
+		    IXGBE_VT_MSGINFO_SHIFT;
+	int err;
+
+	if (adapter->vfinfo[vf].pf_set_mac && index > 0) {
+		e_warn(drv,
+		       "VF %d requested MACVLAN filter but is administratively denied\n",
+		       vf);
+		return -1;
+	}
+
+	/* An non-zero index indicates the VF is setting a filter */
+	if (index) {
+		if (!is_valid_ether_addr(new_mac)) {
+			e_warn(drv, "VF %d attempted to set invalid mac\n", vf);
+			return -1;
+		}
+
+		/*
+		 * If the VF is allowed to set MAC filters then turn off
+		 * anti-spoofing to avoid false positives.
+		 */
+		if (adapter->vfinfo[vf].spoofchk_enabled)
+			ixgbe_ndo_set_vf_spoofchk(adapter->netdev, vf, false);
+	}
+
+	err = ixgbe_set_vf_macvlan(adapter, vf, index, new_mac);
+	if (err == -ENOSPC)
+		e_warn(drv,
+		       "VF %d has requested a MACVLAN filter but there is no space for it\n",
+		       vf);
+
+	return err < 0;
+}
+
+static int ixgbe_negotiate_vf_api(struct ixgbe_adapter *adapter,
+				  u32 *msgbuf, u32 vf)
+{
+	int api = msgbuf[1];
+
+	switch (api) {
+	case ixgbe_mbox_api_10:
+	case ixgbe_mbox_api_11:
+		adapter->vfinfo[vf].vf_api = api;
+		return 0;
+	default:
+		break;
+	}
+
+	e_info(drv, "VF %d requested invalid api version %u\n", vf, api);
+
+	return -1;
+}
+
+static int ixgbe_get_vf_queues(struct ixgbe_adapter *adapter,
+			       u32 *msgbuf, u32 vf)
+{
+	struct net_device *dev = adapter->netdev;
+	struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ];
+	unsigned int default_tc = 0;
+	u8 num_tcs = netdev_get_num_tc(dev);
+
+	/* verify the PF is supporting the correct APIs */
+	switch (adapter->vfinfo[vf].vf_api) {
+	case ixgbe_mbox_api_20:
+	case ixgbe_mbox_api_11:
+		break;
+	default:
+		return -1;
+	}
+
+	/* only allow 1 Tx queue for bandwidth limiting */
+	msgbuf[IXGBE_VF_TX_QUEUES] = __ALIGN_MASK(1, ~vmdq->mask);
+	msgbuf[IXGBE_VF_RX_QUEUES] = __ALIGN_MASK(1, ~vmdq->mask);
+
+	/* if TCs > 1 determine which TC belongs to default user priority */
+	if (num_tcs > 1)
+		default_tc = netdev_get_prio_tc_map(dev, adapter->default_up);
+
+	/* notify VF of need for VLAN tag stripping, and correct queue */
+	if (num_tcs)
+		msgbuf[IXGBE_VF_TRANS_VLAN] = num_tcs;
+	else if (adapter->vfinfo[vf].pf_vlan || adapter->vfinfo[vf].pf_qos)
+		msgbuf[IXGBE_VF_TRANS_VLAN] = 1;
+	else
+		msgbuf[IXGBE_VF_TRANS_VLAN] = 0;
+
+	/* notify VF of default queue */
+	msgbuf[IXGBE_VF_DEF_QUEUE] = default_tc;
+
+	return 0;
 }
 
 static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
@@ -553,10 +814,6 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
 	u32 msgbuf[IXGBE_VFMAILBOX_SIZE];
 	struct ixgbe_hw *hw = &adapter->hw;
 	s32 retval;
-	int entries;
-	u16 *hash_list;
-	int add, vid, index;
-	u8 *new_mac;
 
 	retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf);
 
@@ -572,39 +829,13 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
 	/* flush the ack before we write any messages back */
 	IXGBE_WRITE_FLUSH(hw);
 
+	if (msgbuf[0] == IXGBE_VF_RESET)
+		return ixgbe_vf_reset_msg(adapter, vf);
+
 	/*
 	 * until the vf completes a virtual function reset it should not be
 	 * allowed to start any configuration.
 	 */
-
-	if (msgbuf[0] == IXGBE_VF_RESET) {
-		unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses;
-		new_mac = (u8 *)(&msgbuf[1]);
-		e_info(probe, "VF Reset msg received from vf %d\n", vf);
-		adapter->vfinfo[vf].clear_to_send = false;
-		ixgbe_vf_reset_msg(adapter, vf);
-		adapter->vfinfo[vf].clear_to_send = true;
-
-		if (is_valid_ether_addr(new_mac) &&
-		    !adapter->vfinfo[vf].pf_set_mac)
-			ixgbe_set_vf_mac(adapter, vf, vf_mac);
-		else
-			ixgbe_set_vf_mac(adapter,
-				 vf, adapter->vfinfo[vf].vf_mac_addresses);
-
-		/* reply to reset with ack and vf mac address */
-		msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK;
-		memcpy(new_mac, vf_mac, ETH_ALEN);
-		/*
-		 * Piggyback the multicast filter type so VF can compute the
-		 * correct vectors
-		 */
-		msgbuf[3] = hw->mac.mc_filter_type;
-		ixgbe_write_mbx(hw, msgbuf, IXGBE_VF_PERMADDR_MSG_LEN, vf);
-
-		return retval;
-	}
-
 	if (!adapter->vfinfo[vf].clear_to_send) {
 		msgbuf[0] |= IXGBE_VT_MSGTYPE_NACK;
 		ixgbe_write_mbx(hw, msgbuf, 1, vf);
@@ -613,70 +844,25 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
 
 	switch ((msgbuf[0] & 0xFFFF)) {
 	case IXGBE_VF_SET_MAC_ADDR:
-		new_mac = ((u8 *)(&msgbuf[1]));
-		if (is_valid_ether_addr(new_mac) &&
-		    !adapter->vfinfo[vf].pf_set_mac) {
-			ixgbe_set_vf_mac(adapter, vf, new_mac);
-		} else if (memcmp(adapter->vfinfo[vf].vf_mac_addresses,
-				  new_mac, ETH_ALEN)) {
-			e_warn(drv, "VF %d attempted to override "
-			       "administratively set MAC address\nReload "
-			       "the VF driver to resume operations\n", vf);
-			retval = -1;
-		}
+		retval = ixgbe_set_vf_mac_addr(adapter, msgbuf, vf);
 		break;
 	case IXGBE_VF_SET_MULTICAST:
-		entries = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK)
-		          >> IXGBE_VT_MSGINFO_SHIFT;
-		hash_list = (u16 *)&msgbuf[1];
-		retval = ixgbe_set_vf_multicasts(adapter, entries,
-		                                 hash_list, vf);
-		break;
-	case IXGBE_VF_SET_LPE:
-		ixgbe_set_vf_lpe(adapter, msgbuf);
+		retval = ixgbe_set_vf_multicasts(adapter, msgbuf, vf);
 		break;
 	case IXGBE_VF_SET_VLAN:
-		add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK)
-		      >> IXGBE_VT_MSGINFO_SHIFT;
-		vid = (msgbuf[1] & IXGBE_VLVF_VLANID_MASK);
-		if (adapter->vfinfo[vf].pf_vlan) {
-			e_warn(drv, "VF %d attempted to override "
-			       "administratively set VLAN configuration\n"
-			       "Reload the VF driver to resume operations\n",
-			       vf);
-			retval = -1;
-		} else {
-			if (add)
-				adapter->vfinfo[vf].vlan_count++;
-			else if (adapter->vfinfo[vf].vlan_count)
-				adapter->vfinfo[vf].vlan_count--;
-			retval = ixgbe_set_vf_vlan(adapter, add, vid, vf);
-			if (!retval && adapter->vfinfo[vf].spoofchk_enabled)
-				hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
-		}
+		retval = ixgbe_set_vf_vlan_msg(adapter, msgbuf, vf);
+		break;
+	case IXGBE_VF_SET_LPE:
+		retval = ixgbe_set_vf_lpe(adapter, msgbuf, vf);
 		break;
 	case IXGBE_VF_SET_MACVLAN:
-		index = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >>
-			IXGBE_VT_MSGINFO_SHIFT;
-		if (adapter->vfinfo[vf].pf_set_mac && index > 0) {
-			e_warn(drv, "VF %d requested MACVLAN filter but is "
-				    "administratively denied\n", vf);
-			retval = -1;
-			break;
-		}
-		/*
-		 * If the VF is allowed to set MAC filters then turn off
-		 * anti-spoofing to avoid false positives.  An index
-		 * greater than 0 will indicate the VF is setting a
-		 * macvlan MAC filter.
-		 */
-		if (index > 0 && adapter->vfinfo[vf].spoofchk_enabled)
-			ixgbe_ndo_set_vf_spoofchk(adapter->netdev, vf, false);
-		retval = ixgbe_set_vf_macvlan(adapter, vf, index,
-					      (unsigned char *)(&msgbuf[1]));
-		if (retval == -ENOSPC)
-			e_warn(drv, "VF %d has requested a MACVLAN filter "
-				    "but there is no space for it\n", vf);
+		retval = ixgbe_set_vf_macvlan_msg(adapter, msgbuf, vf);
+		break;
+	case IXGBE_VF_API_NEGOTIATE:
+		retval = ixgbe_negotiate_vf_api(adapter, msgbuf, vf);
+		break;
+	case IXGBE_VF_GET_QUEUES:
+		retval = ixgbe_get_vf_queues(adapter, msgbuf, vf);
 		break;
 	default:
 		e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]);
@@ -692,7 +878,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
 
 	msgbuf[0] |= IXGBE_VT_MSGTYPE_CTS;
 
-	ixgbe_write_mbx(hw, msgbuf, 1, vf);
+	ixgbe_write_mbx(hw, msgbuf, mbx_size, vf);
 
 	return retval;
 }
@@ -783,7 +969,7 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
 		err = ixgbe_set_vf_vlan(adapter, true, vlan, vf);
 		if (err)
 			goto out;
-		ixgbe_set_vmvir(adapter, vlan | (qos << VLAN_PRIO_SHIFT), vf);
+		ixgbe_set_vmvir(adapter, vlan, qos, vf);
 		ixgbe_set_vmolr(hw, vf, false);
 		if (adapter->vfinfo[vf].spoofchk_enabled)
 			hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
@@ -803,7 +989,7 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
 	} else {
 		err = ixgbe_set_vf_vlan(adapter, false,
 					adapter->vfinfo[vf].pf_vlan, vf);
-		ixgbe_set_vmvir(adapter, vlan, vf);
+		ixgbe_clear_vmvir(adapter, vf);
 		ixgbe_set_vmolr(hw, vf, true);
 		hw->mac.ops.set_vlan_anti_spoofing(hw, false, vf);
 		if (adapter->vfinfo[vf].vlan_count)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 0722f33..21915e2 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -56,6 +56,7 @@
 #define IXGBE_SUBDEV_ID_82599_SFP        0x11A9
 #define IXGBE_SUBDEV_ID_82599_RNDC       0x1F72
 #define IXGBE_SUBDEV_ID_82599_560FLR     0x17D0
+#define IXGBE_SUBDEV_ID_82599_ECNA_DP    0x0470
 #define IXGBE_DEV_ID_82599_SFP_EM        0x1507
 #define IXGBE_DEV_ID_82599_SFP_SF2       0x154D
 #define IXGBE_DEV_ID_82599EN_SFP         0x1557
diff --git a/drivers/net/ethernet/intel/ixgbevf/defines.h b/drivers/net/ethernet/intel/ixgbevf/defines.h
index da17ccf..3147795 100644
--- a/drivers/net/ethernet/intel/ixgbevf/defines.h
+++ b/drivers/net/ethernet/intel/ixgbevf/defines.h
@@ -33,8 +33,11 @@
 #define IXGBE_DEV_ID_X540_VF            0x1515
 
 #define IXGBE_VF_IRQ_CLEAR_MASK         7
-#define IXGBE_VF_MAX_TX_QUEUES          1
-#define IXGBE_VF_MAX_RX_QUEUES          1
+#define IXGBE_VF_MAX_TX_QUEUES          8
+#define IXGBE_VF_MAX_RX_QUEUES          8
+
+/* DCB define */
+#define IXGBE_VF_MAX_TRAFFIC_CLASS	8
 
 /* Link speed */
 typedef u32 ixgbe_link_speed;
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index 4a9c9c2..fc0af9a 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -58,7 +58,6 @@ struct ixgbevf_ring {
 	struct ixgbevf_ring *next;
 	struct net_device *netdev;
 	struct device *dev;
-	struct ixgbevf_adapter *adapter;  /* backlink */
 	void *desc;			/* descriptor ring memory */
 	dma_addr_t dma;			/* phys. address of descriptor ring */
 	unsigned int size;		/* length in bytes */
@@ -75,6 +74,8 @@ struct ixgbevf_ring {
 	u64			total_bytes;
 	u64			total_packets;
 	struct u64_stats_sync	syncp;
+	u64 hw_csum_rx_error;
+	u64 hw_csum_rx_good;
 
 	u16 head;
 	u16 tail;
@@ -89,8 +90,8 @@ struct ixgbevf_ring {
 /* How many Rx Buffers do we bundle into one write to the hardware ? */
 #define IXGBEVF_RX_BUFFER_WRITE	16	/* Must be power of 2 */
 
-#define MAX_RX_QUEUES 1
-#define MAX_TX_QUEUES 1
+#define MAX_RX_QUEUES IXGBE_VF_MAX_RX_QUEUES
+#define MAX_TX_QUEUES IXGBE_VF_MAX_TX_QUEUES
 
 #define IXGBEVF_DEFAULT_TXD   1024
 #define IXGBEVF_DEFAULT_RXD   512
@@ -101,10 +102,10 @@ struct ixgbevf_ring {
 
 /* Supported Rx Buffer Sizes */
 #define IXGBEVF_RXBUFFER_256   256    /* Used for packet split */
-#define IXGBEVF_RXBUFFER_3K    3072
-#define IXGBEVF_RXBUFFER_7K    7168
-#define IXGBEVF_RXBUFFER_15K   15360
-#define IXGBEVF_MAX_RXBUFFER   16384  /* largest size for single descriptor */
+#define IXGBEVF_RXBUFFER_2K    2048
+#define IXGBEVF_RXBUFFER_4K    4096
+#define IXGBEVF_RXBUFFER_8K    8192
+#define IXGBEVF_RXBUFFER_10K   10240
 
 #define IXGBEVF_RX_HDR_SIZE IXGBEVF_RXBUFFER_256
 
@@ -229,6 +230,7 @@ struct ixgbevf_adapter {
 	 */
 	u32 flags;
 #define IXGBE_FLAG_IN_WATCHDOG_TASK             (u32)(1)
+#define IXGBE_FLAG_IN_NETPOLL                   (u32)(1 << 1)
 
 	/* OS defined structs */
 	struct net_device *netdev;
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index de1ad50..f267c00 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -58,7 +58,7 @@ const char ixgbevf_driver_name[] = "ixgbevf";
 static const char ixgbevf_driver_string[] =
 	"Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver";
 
-#define DRV_VERSION "2.6.0-k"
+#define DRV_VERSION "2.7.12-k"
 const char ixgbevf_driver_version[] = DRV_VERSION;
 static char ixgbevf_copyright[] =
 	"Copyright (c) 2009 - 2012 Intel Corporation.";
@@ -99,6 +99,7 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 
 /* forward decls */
 static void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector);
+static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter);
 
 static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw,
 					   struct ixgbevf_ring *rx_ring,
@@ -120,7 +121,6 @@ static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw,
  * @direction: 0 for Rx, 1 for Tx, -1 for other causes
  * @queue: queue to map the corresponding interrupt to
  * @msix_vector: the vector to map to the corresponding queue
- *
  */
 static void ixgbevf_set_ivar(struct ixgbevf_adapter *adapter, s8 direction,
 			     u8 queue, u8 msix_vector)
@@ -287,17 +287,19 @@ static void ixgbevf_receive_skb(struct ixgbevf_q_vector *q_vector,
 	if (is_vlan && test_bit(tag & VLAN_VID_MASK, adapter->active_vlans))
 		__vlan_hwaccel_put_tag(skb, tag);
 
-	napi_gro_receive(&q_vector->napi, skb);
+	if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
+		napi_gro_receive(&q_vector->napi, skb);
+	else
+		netif_rx(skb);
 }
 
 /**
  * ixgbevf_rx_checksum - indicate in skb if hw indicated a good cksum
- * @adapter: address of board private structure
+ * @ring: pointer to Rx descriptor ring structure
  * @status_err: hardware indication of status of receive
  * @skb: skb currently being received and modified
  **/
-static inline void ixgbevf_rx_checksum(struct ixgbevf_adapter *adapter,
-				       struct ixgbevf_ring *ring,
+static inline void ixgbevf_rx_checksum(struct ixgbevf_ring *ring,
 				       u32 status_err, struct sk_buff *skb)
 {
 	skb_checksum_none_assert(skb);
@@ -309,7 +311,7 @@ static inline void ixgbevf_rx_checksum(struct ixgbevf_adapter *adapter,
 	/* if IP and error */
 	if ((status_err & IXGBE_RXD_STAT_IPCS) &&
 	    (status_err & IXGBE_RXDADV_ERR_IPE)) {
-		adapter->hw_csum_rx_error++;
+		ring->hw_csum_rx_error++;
 		return;
 	}
 
@@ -317,13 +319,13 @@ static inline void ixgbevf_rx_checksum(struct ixgbevf_adapter *adapter,
 		return;
 
 	if (status_err & IXGBE_RXDADV_ERR_TCPE) {
-		adapter->hw_csum_rx_error++;
+		ring->hw_csum_rx_error++;
 		return;
 	}
 
 	/* It must be a TCP or UDP packet with a valid checksum */
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
-	adapter->hw_csum_rx_good++;
+	ring->hw_csum_rx_good++;
 }
 
 /**
@@ -337,15 +339,16 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter,
 	struct pci_dev *pdev = adapter->pdev;
 	union ixgbe_adv_rx_desc *rx_desc;
 	struct ixgbevf_rx_buffer *bi;
-	struct sk_buff *skb;
 	unsigned int i = rx_ring->next_to_use;
 
 	bi = &rx_ring->rx_buffer_info[i];
 
 	while (cleaned_count--) {
 		rx_desc = IXGBEVF_RX_DESC(rx_ring, i);
-		skb = bi->skb;
-		if (!skb) {
+
+		if (!bi->skb) {
+			struct sk_buff *skb;
+
 			skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
 							rx_ring->rx_buf_len);
 			if (!skb) {
@@ -353,11 +356,16 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter,
 				goto no_buffers;
 			}
 			bi->skb = skb;
-		}
-		if (!bi->dma) {
+
 			bi->dma = dma_map_single(&pdev->dev, skb->data,
 						 rx_ring->rx_buf_len,
 						 DMA_FROM_DEVICE);
+			if (dma_mapping_error(&pdev->dev, bi->dma)) {
+				dev_kfree_skb(skb);
+				bi->skb = NULL;
+				dev_err(&pdev->dev, "RX DMA map failed\n");
+				break;
+			}
 		}
 		rx_desc->read.pkt_addr = cpu_to_le64(bi->dma);
 
@@ -370,7 +378,6 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter,
 no_buffers:
 	if (rx_ring->next_to_use != i) {
 		rx_ring->next_to_use = i;
-
 		ixgbevf_release_rx_desc(&adapter->hw, rx_ring, i);
 	}
 }
@@ -454,7 +461,7 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
 			goto next_desc;
 		}
 
-		ixgbevf_rx_checksum(adapter, rx_ring, staterr, skb);
+		ixgbevf_rx_checksum(rx_ring, staterr, skb);
 
 		/* probably a little skewed due to removing CRC */
 		total_rx_bytes += skb->len;
@@ -471,6 +478,16 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
 		}
 		skb->protocol = eth_type_trans(skb, rx_ring->netdev);
 
+		/* Workaround hardware that can't do proper VEPA multicast
+		 * source pruning.
+		 */
+		if ((skb->pkt_type & (PACKET_BROADCAST | PACKET_MULTICAST)) &&
+		    !(compare_ether_addr(adapter->netdev->dev_addr,
+					eth_hdr(skb)->h_source))) {
+			dev_kfree_skb_irq(skb);
+			goto next_desc;
+		}
+
 		ixgbevf_receive_skb(q_vector, skb, staterr, rx_desc);
 
 next_desc:
@@ -533,9 +550,11 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget)
 	else
 		per_ring_budget = budget;
 
+	adapter->flags |= IXGBE_FLAG_IN_NETPOLL;
 	ixgbevf_for_each_ring(ring, q_vector->rx)
 		clean_complete &= ixgbevf_clean_rx_irq(q_vector, ring,
 						       per_ring_budget);
+	adapter->flags &= ~IXGBE_FLAG_IN_NETPOLL;
 
 	/* If all work not completed, return budget and keep polling */
 	if (!clean_complete)
@@ -743,7 +762,6 @@ static irqreturn_t ixgbevf_msix_other(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-
 /**
  * ixgbevf_msix_clean_rings - single unshared vector rx clean (all queues)
  * @irq: unused
@@ -1065,20 +1083,20 @@ static void ixgbevf_set_rx_buffer_len(struct ixgbevf_adapter *adapter)
 	max_frame += VLAN_HLEN;
 
 	/*
-	 * Make best use of allocation by using all but 1K of a
-	 * power of 2 allocation that will be used for skb->head.
+	 * Allocate buffer sizes that fit well into 32K and
+	 * take into account max frame size of 9.5K
 	 */
 	if ((hw->mac.type == ixgbe_mac_X540_vf) &&
 	    (max_frame <= MAXIMUM_ETHERNET_VLAN_SIZE))
 		rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE;
-	else if (max_frame <= IXGBEVF_RXBUFFER_3K)
-		rx_buf_len = IXGBEVF_RXBUFFER_3K;
-	else if (max_frame <= IXGBEVF_RXBUFFER_7K)
-		rx_buf_len = IXGBEVF_RXBUFFER_7K;
-	else if (max_frame <= IXGBEVF_RXBUFFER_15K)
-		rx_buf_len = IXGBEVF_RXBUFFER_15K;
+	else if (max_frame <= IXGBEVF_RXBUFFER_2K)
+		rx_buf_len = IXGBEVF_RXBUFFER_2K;
+	else if (max_frame <= IXGBEVF_RXBUFFER_4K)
+		rx_buf_len = IXGBEVF_RXBUFFER_4K;
+	else if (max_frame <= IXGBEVF_RXBUFFER_8K)
+		rx_buf_len = IXGBEVF_RXBUFFER_8K;
 	else
-		rx_buf_len = IXGBEVF_MAX_RXBUFFER;
+		rx_buf_len = IXGBEVF_RXBUFFER_10K;
 
 	for (i = 0; i < adapter->num_rx_queues; i++)
 		adapter->rx_ring[i].rx_buf_len = rx_buf_len;
@@ -1128,15 +1146,12 @@ static int ixgbevf_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
 	struct ixgbe_hw *hw = &adapter->hw;
 	int err;
 
-	if (!hw->mac.ops.set_vfta)
-		return -EOPNOTSUPP;
-
-	spin_lock(&adapter->mbx_lock);
+	spin_lock_bh(&adapter->mbx_lock);
 
 	/* add VID to filter table */
 	err = hw->mac.ops.set_vfta(hw, vid, 0, true);
 
-	spin_unlock(&adapter->mbx_lock);
+	spin_unlock_bh(&adapter->mbx_lock);
 
 	/* translate error return types so error makes sense */
 	if (err == IXGBE_ERR_MBX)
@@ -1156,13 +1171,12 @@ static int ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 	struct ixgbe_hw *hw = &adapter->hw;
 	int err = -EOPNOTSUPP;
 
-	spin_lock(&adapter->mbx_lock);
+	spin_lock_bh(&adapter->mbx_lock);
 
 	/* remove VID from filter table */
-	if (hw->mac.ops.set_vfta)
-		err = hw->mac.ops.set_vfta(hw, vid, 0, false);
+	err = hw->mac.ops.set_vfta(hw, vid, 0, false);
 
-	spin_unlock(&adapter->mbx_lock);
+	spin_unlock_bh(&adapter->mbx_lock);
 
 	clear_bit(vid, adapter->active_vlans);
 
@@ -1206,27 +1220,27 @@ static int ixgbevf_write_uc_addr_list(struct net_device *netdev)
 }
 
 /**
- * ixgbevf_set_rx_mode - Multicast set
+ * ixgbevf_set_rx_mode - Multicast and unicast set
  * @netdev: network interface device structure
  *
  * The set_rx_method entry point is called whenever the multicast address
- * list or the network interface flags are updated.  This routine is
- * responsible for configuring the hardware for proper multicast mode.
+ * list, unicast address list or the network interface flags are updated.
+ * This routine is responsible for configuring the hardware for proper
+ * multicast mode and configuring requested unicast filters.
  **/
 static void ixgbevf_set_rx_mode(struct net_device *netdev)
 {
 	struct ixgbevf_adapter *adapter = netdev_priv(netdev);
 	struct ixgbe_hw *hw = &adapter->hw;
 
-	spin_lock(&adapter->mbx_lock);
+	spin_lock_bh(&adapter->mbx_lock);
 
 	/* reprogram multicast list */
-	if (hw->mac.ops.update_mc_addr_list)
-		hw->mac.ops.update_mc_addr_list(hw, netdev);
+	hw->mac.ops.update_mc_addr_list(hw, netdev);
 
 	ixgbevf_write_uc_addr_list(netdev);
 
-	spin_unlock(&adapter->mbx_lock);
+	spin_unlock_bh(&adapter->mbx_lock);
 }
 
 static void ixgbevf_napi_enable_all(struct ixgbevf_adapter *adapter)
@@ -1290,8 +1304,8 @@ static inline void ixgbevf_rx_desc_queue_enable(struct ixgbevf_adapter *adapter,
 		       "not set within the polling period\n", rxr);
 	}
 
-	ixgbevf_release_rx_desc(&adapter->hw, &adapter->rx_ring[rxr],
-				(adapter->rx_ring[rxr].count - 1));
+	ixgbevf_release_rx_desc(hw, &adapter->rx_ring[rxr],
+				adapter->rx_ring[rxr].count - 1);
 }
 
 static void ixgbevf_save_reset_stats(struct ixgbevf_adapter *adapter)
@@ -1335,11 +1349,12 @@ static void ixgbevf_init_last_counter_stats(struct ixgbevf_adapter *adapter)
 static void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	int api[] = { ixgbe_mbox_api_10,
+	int api[] = { ixgbe_mbox_api_11,
+		      ixgbe_mbox_api_10,
 		      ixgbe_mbox_api_unknown };
 	int err = 0, idx = 0;
 
-	spin_lock(&adapter->mbx_lock);
+	spin_lock_bh(&adapter->mbx_lock);
 
 	while (api[idx] != ixgbe_mbox_api_unknown) {
 		err = ixgbevf_negotiate_api_version(hw, api[idx]);
@@ -1348,7 +1363,7 @@ static void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter)
 		idx++;
 	}
 
-	spin_unlock(&adapter->mbx_lock);
+	spin_unlock_bh(&adapter->mbx_lock);
 }
 
 static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
@@ -1389,16 +1404,14 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
 
 	ixgbevf_configure_msix(adapter);
 
-	spin_lock(&adapter->mbx_lock);
+	spin_lock_bh(&adapter->mbx_lock);
 
-	if (hw->mac.ops.set_rar) {
-		if (is_valid_ether_addr(hw->mac.addr))
-			hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0);
-		else
-			hw->mac.ops.set_rar(hw, 0, hw->mac.perm_addr, 0);
-	}
+	if (is_valid_ether_addr(hw->mac.addr))
+		hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0);
+	else
+		hw->mac.ops.set_rar(hw, 0, hw->mac.perm_addr, 0);
 
-	spin_unlock(&adapter->mbx_lock);
+	spin_unlock_bh(&adapter->mbx_lock);
 
 	clear_bit(__IXGBEVF_DOWN, &adapter->state);
 	ixgbevf_napi_enable_all(adapter);
@@ -1413,12 +1426,87 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
 	mod_timer(&adapter->watchdog_timer, jiffies);
 }
 
+static int ixgbevf_reset_queues(struct ixgbevf_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	struct ixgbevf_ring *rx_ring;
+	unsigned int def_q = 0;
+	unsigned int num_tcs = 0;
+	unsigned int num_rx_queues = 1;
+	int err, i;
+
+	spin_lock_bh(&adapter->mbx_lock);
+
+	/* fetch queue configuration from the PF */
+	err = ixgbevf_get_queues(hw, &num_tcs, &def_q);
+
+	spin_unlock_bh(&adapter->mbx_lock);
+
+	if (err)
+		return err;
+
+	if (num_tcs > 1) {
+		/* update default Tx ring register index */
+		adapter->tx_ring[0].reg_idx = def_q;
+
+		/* we need as many queues as traffic classes */
+		num_rx_queues = num_tcs;
+	}
+
+	/* nothing to do if we have the correct number of queues */
+	if (adapter->num_rx_queues == num_rx_queues)
+		return 0;
+
+	/* allocate new rings */
+	rx_ring = kcalloc(num_rx_queues,
+			  sizeof(struct ixgbevf_ring), GFP_KERNEL);
+	if (!rx_ring)
+		return -ENOMEM;
+
+	/* setup ring fields */
+	for (i = 0; i < num_rx_queues; i++) {
+		rx_ring[i].count = adapter->rx_ring_count;
+		rx_ring[i].queue_index = i;
+		rx_ring[i].reg_idx = i;
+		rx_ring[i].dev = &adapter->pdev->dev;
+		rx_ring[i].netdev = adapter->netdev;
+
+		/* allocate resources on the ring */
+		err = ixgbevf_setup_rx_resources(adapter, &rx_ring[i]);
+		if (err) {
+			while (i) {
+				i--;
+				ixgbevf_free_rx_resources(adapter, &rx_ring[i]);
+			}
+			kfree(rx_ring);
+			return err;
+		}
+	}
+
+	/* free the existing rings and queues */
+	ixgbevf_free_all_rx_resources(adapter);
+	adapter->num_rx_queues = 0;
+	kfree(adapter->rx_ring);
+
+	/* move new rings into position on the adapter struct */
+	adapter->rx_ring = rx_ring;
+	adapter->num_rx_queues = num_rx_queues;
+
+	/* reset ring to vector mapping */
+	ixgbevf_reset_q_vectors(adapter);
+	ixgbevf_map_rings_to_vectors(adapter);
+
+	return 0;
+}
+
 void ixgbevf_up(struct ixgbevf_adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 
 	ixgbevf_negotiate_api(adapter);
 
+	ixgbevf_reset_queues(adapter);
+
 	ixgbevf_configure(adapter);
 
 	ixgbevf_up_complete(adapter);
@@ -1497,7 +1585,6 @@ static void ixgbevf_clean_tx_ring(struct ixgbevf_adapter *adapter,
 		return;
 
 	/* Free all the Tx ring sk_buffs */
-
 	for (i = 0; i < tx_ring->count; i++) {
 		tx_buffer_info = &tx_ring->tx_buffer_info[i];
 		ixgbevf_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
@@ -1593,13 +1680,6 @@ void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter)
 	while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state))
 		msleep(1);
 
-	/*
-	 * Check if PF is up before re-init.  If not then skip until
-	 * later when the PF is up and ready to service requests from
-	 * the VF via mailbox.  If the VF is up and running then the
-	 * watchdog task will continue to schedule reset tasks until
-	 * the PF is up and running.
-	 */
 	ixgbevf_down(adapter);
 	ixgbevf_up(adapter);
 
@@ -1611,15 +1691,11 @@ void ixgbevf_reset(struct ixgbevf_adapter *adapter)
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 
-	spin_lock(&adapter->mbx_lock);
-
 	if (hw->mac.ops.reset_hw(hw))
 		hw_dbg(hw, "PF still resetting\n");
 	else
 		hw->mac.ops.init_hw(hw);
 
-	spin_unlock(&adapter->mbx_lock);
-
 	if (is_valid_ether_addr(adapter->hw.mac.addr)) {
 		memcpy(netdev->dev_addr, adapter->hw.mac.addr,
 		       netdev->addr_len);
@@ -1628,10 +1704,11 @@ void ixgbevf_reset(struct ixgbevf_adapter *adapter)
 	}
 }
 
-static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter,
-					 int vectors)
+static int ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter,
+					int vectors)
 {
-	int err, vector_threshold;
+	int err = 0;
+	int vector_threshold;
 
 	/* We'll want at least 2 (vector_threshold):
 	 * 1) TxQ[0] + RxQ[0] handler
@@ -1647,21 +1724,18 @@ static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter,
 	while (vectors >= vector_threshold) {
 		err = pci_enable_msix(adapter->pdev, adapter->msix_entries,
 				      vectors);
-		if (!err) /* Success in acquiring all requested vectors. */
+		if (!err || err < 0) /* Success or a nasty failure. */
 			break;
-		else if (err < 0)
-			vectors = 0; /* Nasty failure, quit now */
 		else /* err == number of vectors we should try again with */
 			vectors = err;
 	}
 
-	if (vectors < vector_threshold) {
-		/* Can't allocate enough MSI-X interrupts?  Oh well.
-		 * This just means we'll go with either a single MSI
-		 * vector or fall back to legacy interrupts.
-		 */
-		hw_dbg(&adapter->hw,
-		       "Unable to allocate MSI-X interrupts\n");
+	if (vectors < vector_threshold)
+		err = -ENOMEM;
+
+	if (err) {
+		dev_err(&adapter->pdev->dev,
+			"Unable to allocate MSI-X interrupts\n");
 		kfree(adapter->msix_entries);
 		adapter->msix_entries = NULL;
 	} else {
@@ -1672,6 +1746,8 @@ static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter,
 		 */
 		adapter->num_msix_vectors = vectors;
 	}
+
+	return err;
 }
 
 /**
@@ -1717,6 +1793,7 @@ static int ixgbevf_alloc_queues(struct ixgbevf_adapter *adapter)
 	for (i = 0; i < adapter->num_tx_queues; i++) {
 		adapter->tx_ring[i].count = adapter->tx_ring_count;
 		adapter->tx_ring[i].queue_index = i;
+		/* reg_idx may be remapped later by DCB config */
 		adapter->tx_ring[i].reg_idx = i;
 		adapter->tx_ring[i].dev = &adapter->pdev->dev;
 		adapter->tx_ring[i].netdev = adapter->netdev;
@@ -1774,7 +1851,9 @@ static int ixgbevf_set_interrupt_capability(struct ixgbevf_adapter *adapter)
 	for (vector = 0; vector < v_budget; vector++)
 		adapter->msix_entries[vector].entry = vector;
 
-	ixgbevf_acquire_msix_vectors(adapter, v_budget);
+	err = ixgbevf_acquire_msix_vectors(adapter, v_budget);
+	if (err)
+		goto out;
 
 	err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues);
 	if (err)
@@ -1834,18 +1913,13 @@ err_out:
  **/
 static void ixgbevf_free_q_vectors(struct ixgbevf_adapter *adapter)
 {
-	int q_idx, num_q_vectors;
-	int napi_vectors;
-
-	num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
-	napi_vectors = adapter->num_rx_queues;
+	int q_idx, num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
 
 	for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
 		struct ixgbevf_q_vector *q_vector = adapter->q_vector[q_idx];
 
 		adapter->q_vector[q_idx] = NULL;
-		if (q_idx < napi_vectors)
-			netif_napi_del(&q_vector->napi);
+		netif_napi_del(&q_vector->napi);
 		kfree(q_vector);
 	}
 }
@@ -1950,8 +2024,11 @@ static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
 	hw->subsystem_device_id = pdev->subsystem_device;
 
 	hw->mbx.ops.init_params(hw);
-	hw->mac.max_tx_queues = MAX_TX_QUEUES;
-	hw->mac.max_rx_queues = MAX_RX_QUEUES;
+
+	/* assume legacy case in which PF would only give VF 2 queues */
+	hw->mac.max_tx_queues = 2;
+	hw->mac.max_rx_queues = 2;
+
 	err = hw->mac.ops.reset_hw(hw);
 	if (err) {
 		dev_info(&pdev->dev,
@@ -1966,7 +2043,7 @@ static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
 			goto out;
 		}
 		memcpy(adapter->netdev->dev_addr, adapter->hw.mac.addr,
-			adapter->netdev->addr_len);
+		       adapter->netdev->addr_len);
 	}
 
 	/* lock to protect mailbox accesses */
@@ -2016,6 +2093,7 @@ out:
 void ixgbevf_update_stats(struct ixgbevf_adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
+	int i;
 
 	UPDATE_VF_COUNTER_32bit(IXGBE_VFGPRC, adapter->stats.last_vfgprc,
 				adapter->stats.vfgprc);
@@ -2029,6 +2107,15 @@ void ixgbevf_update_stats(struct ixgbevf_adapter *adapter)
 				adapter->stats.vfgotc);
 	UPDATE_VF_COUNTER_32bit(IXGBE_VFMPRC, adapter->stats.last_vfmprc,
 				adapter->stats.vfmprc);
+
+	for (i = 0;  i  < adapter->num_rx_queues;  i++) {
+		adapter->hw_csum_rx_error +=
+			adapter->rx_ring[i].hw_csum_rx_error;
+		adapter->hw_csum_rx_good +=
+			adapter->rx_ring[i].hw_csum_rx_good;
+		adapter->rx_ring[i].hw_csum_rx_error = 0;
+		adapter->rx_ring[i].hw_csum_rx_good = 0;
+	}
 }
 
 /**
@@ -2103,6 +2190,7 @@ static void ixgbevf_watchdog_task(struct work_struct *work)
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 link_speed = adapter->link_speed;
 	bool link_up = adapter->link_up;
+	s32 need_reset;
 
 	adapter->flags |= IXGBE_FLAG_IN_WATCHDOG_TASK;
 
@@ -2110,29 +2198,19 @@ static void ixgbevf_watchdog_task(struct work_struct *work)
 	 * Always check the link on the watchdog because we have
 	 * no LSC interrupt
 	 */
-	if (hw->mac.ops.check_link) {
-		s32 need_reset;
-
-		spin_lock(&adapter->mbx_lock);
+	spin_lock_bh(&adapter->mbx_lock);
 
-		need_reset = hw->mac.ops.check_link(hw, &link_speed,
-						    &link_up, false);
+	need_reset = hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
 
-		spin_unlock(&adapter->mbx_lock);
+	spin_unlock_bh(&adapter->mbx_lock);
 
-		if (need_reset) {
-			adapter->link_up = link_up;
-			adapter->link_speed = link_speed;
-			netif_carrier_off(netdev);
-			netif_tx_stop_all_queues(netdev);
-			schedule_work(&adapter->reset_task);
-			goto pf_has_reset;
-		}
-	} else {
-		/* always assume link is up, if no check link
-		 * function */
-		link_speed = IXGBE_LINK_SPEED_10GB_FULL;
-		link_up = true;
+	if (need_reset) {
+		adapter->link_up = link_up;
+		adapter->link_speed = link_speed;
+		netif_carrier_off(netdev);
+		netif_tx_stop_all_queues(netdev);
+		schedule_work(&adapter->reset_task);
+		goto pf_has_reset;
 	}
 	adapter->link_up = link_up;
 	adapter->link_speed = link_speed;
@@ -2377,6 +2455,63 @@ static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter)
 						  &adapter->rx_ring[i]);
 }
 
+static int ixgbevf_setup_queues(struct ixgbevf_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	struct ixgbevf_ring *rx_ring;
+	unsigned int def_q = 0;
+	unsigned int num_tcs = 0;
+	unsigned int num_rx_queues = 1;
+	int err, i;
+
+	spin_lock_bh(&adapter->mbx_lock);
+
+	/* fetch queue configuration from the PF */
+	err = ixgbevf_get_queues(hw, &num_tcs, &def_q);
+
+	spin_unlock_bh(&adapter->mbx_lock);
+
+	if (err)
+		return err;
+
+	if (num_tcs > 1) {
+		/* update default Tx ring register index */
+		adapter->tx_ring[0].reg_idx = def_q;
+
+		/* we need as many queues as traffic classes */
+		num_rx_queues = num_tcs;
+	}
+
+	/* nothing to do if we have the correct number of queues */
+	if (adapter->num_rx_queues == num_rx_queues)
+		return 0;
+
+	/* allocate new rings */
+	rx_ring = kcalloc(num_rx_queues,
+			  sizeof(struct ixgbevf_ring), GFP_KERNEL);
+	if (!rx_ring)
+		return -ENOMEM;
+
+	/* setup ring fields */
+	for (i = 0; i < num_rx_queues; i++) {
+		rx_ring[i].count = adapter->rx_ring_count;
+		rx_ring[i].queue_index = i;
+		rx_ring[i].reg_idx = i;
+		rx_ring[i].dev = &adapter->pdev->dev;
+		rx_ring[i].netdev = adapter->netdev;
+	}
+
+	/* free the existing ring and queues */
+	adapter->num_rx_queues = 0;
+	kfree(adapter->rx_ring);
+
+	/* move new rings into position on the adapter struct */
+	adapter->rx_ring = rx_ring;
+	adapter->num_rx_queues = num_rx_queues;
+
+	return 0;
+}
+
 /**
  * ixgbevf_open - Called when a network interface is made active
  * @netdev: network interface device structure
@@ -2413,6 +2548,11 @@ static int ixgbevf_open(struct net_device *netdev)
 
 	ixgbevf_negotiate_api(adapter);
 
+	/* setup queue reg_idx and Rx queue count */
+	err = ixgbevf_setup_queues(adapter);
+	if (err)
+		goto err_setup_queues;
+
 	/* allocate transmit descriptors */
 	err = ixgbevf_setup_all_tx_resources(adapter);
 	if (err)
@@ -2451,6 +2591,7 @@ err_setup_rx:
 	ixgbevf_free_all_rx_resources(adapter);
 err_setup_tx:
 	ixgbevf_free_all_tx_resources(adapter);
+err_setup_queues:
 	ixgbevf_reset(adapter);
 
 err_setup_reset:
@@ -2562,9 +2703,6 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring,
 static bool ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring,
 			    struct sk_buff *skb, u32 tx_flags)
 {
-
-
-
 	u32 vlan_macip_lens = 0;
 	u32 mss_l4len_idx = 0;
 	u32 type_tucmd = 0;
@@ -2678,10 +2816,10 @@ static int ixgbevf_tx_map(struct ixgbevf_ring *tx_ring,
 			tx_buffer_info->dma =
 				skb_frag_dma_map(tx_ring->dev, frag,
 						 offset, size, DMA_TO_DEVICE);
-			tx_buffer_info->mapped_as_page = true;
 			if (dma_mapping_error(tx_ring->dev,
 					      tx_buffer_info->dma))
 				goto dma_error;
+			tx_buffer_info->mapped_as_page = true;
 			tx_buffer_info->next_to_watch = i;
 
 			len -= size;
@@ -2754,7 +2892,6 @@ static void ixgbevf_tx_queue(struct ixgbevf_ring *tx_ring, int tx_flags,
 		olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT);
 		if (tx_flags & IXGBE_TX_FLAGS_IPV4)
 			olinfo_status |= IXGBE_ADVTXD_POPTS_IXSM;
-
 	}
 
 	/*
@@ -2823,6 +2960,11 @@ static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 #if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD
 	unsigned short f;
 #endif
+	u8 *dst_mac = skb_header_pointer(skb, 0, 0, NULL);
+	if (!dst_mac || is_link_local_ether_addr(dst_mac)) {
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
 
 	tx_ring = &adapter->tx_ring[r_idx];
 
@@ -2902,12 +3044,11 @@ static int ixgbevf_set_mac(struct net_device *netdev, void *p)
 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
 	memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len);
 
-	spin_lock(&adapter->mbx_lock);
+	spin_lock_bh(&adapter->mbx_lock);
 
-	if (hw->mac.ops.set_rar)
-		hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0);
+	hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0);
 
-	spin_unlock(&adapter->mbx_lock);
+	spin_unlock_bh(&adapter->mbx_lock);
 
 	return 0;
 }
@@ -2925,8 +3066,15 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)
 	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
 	int max_possible_frame = MAXIMUM_ETHERNET_VLAN_SIZE;
 
-	if (adapter->hw.mac.type == ixgbe_mac_X540_vf)
+	switch (adapter->hw.api_version) {
+	case ixgbe_mbox_api_11:
 		max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
+		break;
+	default:
+		if (adapter->hw.mac.type == ixgbe_mac_X540_vf)
+			max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
+		break;
+	}
 
 	/* MTU < 68 is an error and causes problems on some kernels */
 	if ((new_mtu < 68) || (max_frame > max_possible_frame))
@@ -3223,10 +3371,6 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
 	if (err)
 		goto err_sw_init;
 
-	/* pick up the PCI bus settings for reporting later */
-	if (hw->mac.ops.get_bus_info)
-		hw->mac.ops.get_bus_info(hw);
-
 	strcpy(netdev->name, "eth%d");
 
 	err = register_netdev(netdev);
diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.h b/drivers/net/ethernet/intel/ixgbevf/mbx.h
index 946ce86..0bc3005 100644
--- a/drivers/net/ethernet/intel/ixgbevf/mbx.h
+++ b/drivers/net/ethernet/intel/ixgbevf/mbx.h
@@ -85,6 +85,7 @@
 enum ixgbe_pfvf_api_rev {
 	ixgbe_mbox_api_10,	/* API version 1.0, linux/freebsd VF driver */
 	ixgbe_mbox_api_20,	/* API version 2.0, solaris Phase1 VF driver */
+	ixgbe_mbox_api_11,	/* API version 1.1, linux/freebsd VF driver */
 	/* This value should always be last */
 	ixgbe_mbox_api_unknown,	/* indicates that API version is not known */
 };
@@ -100,6 +101,15 @@ enum ixgbe_pfvf_api_rev {
 #define IXGBE_VF_SET_MACVLAN	0x06 /* VF requests PF for unicast filter */
 #define IXGBE_VF_API_NEGOTIATE	0x08 /* negotiate API version */
 
+/* mailbox API, version 1.1 VF requests */
+#define IXGBE_VF_GET_QUEUE	0x09 /* get queue configuration */
+
+/* GET_QUEUES return data indices within the mailbox */
+#define IXGBE_VF_TX_QUEUES	1	/* number of Tx queues supported */
+#define IXGBE_VF_RX_QUEUES	2	/* number of Rx queues supported */
+#define IXGBE_VF_TRANS_VLAN	3	/* Indication of port vlan */
+#define IXGBE_VF_DEF_QUEUE	4	/* Default queue offset */
+
 /* length of permanent address message returned from PF */
 #define IXGBE_VF_PERMADDR_MSG_LEN 4
 /* word in permanent address message with the current multicast type */
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
index 0c7447e..0c94557 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.c
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
@@ -331,6 +331,9 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,
 	netdev_for_each_mc_addr(ha, netdev) {
 		if (i == cnt)
 			break;
+		if (is_link_local_ether_addr(ha->addr))
+			continue;
+
 		vector_list[i++] = ixgbevf_mta_vector(hw, ha->addr);
 	}
 
@@ -513,6 +516,64 @@ int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api)
 	return err;
 }
 
+int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
+		       unsigned int *default_tc)
+{
+	int err;
+	u32 msg[5];
+
+	/* do nothing if API doesn't support ixgbevf_get_queues */
+	switch (hw->api_version) {
+	case ixgbe_mbox_api_11:
+		break;
+	default:
+		return 0;
+	}
+
+	/* Fetch queue configuration from the PF */
+	msg[0] = IXGBE_VF_GET_QUEUE;
+	msg[1] = msg[2] = msg[3] = msg[4] = 0;
+	err = hw->mbx.ops.write_posted(hw, msg, 5);
+
+	if (!err)
+		err = hw->mbx.ops.read_posted(hw, msg, 5);
+
+	if (!err) {
+		msg[0] &= ~IXGBE_VT_MSGTYPE_CTS;
+
+		/*
+		 * if we we didn't get an ACK there must have been
+		 * some sort of mailbox error so we should treat it
+		 * as such
+		 */
+		if (msg[0] != (IXGBE_VF_GET_QUEUE | IXGBE_VT_MSGTYPE_ACK))
+			return IXGBE_ERR_MBX;
+
+		/* record and validate values from message */
+		hw->mac.max_tx_queues = msg[IXGBE_VF_TX_QUEUES];
+		if (hw->mac.max_tx_queues == 0 ||
+		    hw->mac.max_tx_queues > IXGBE_VF_MAX_TX_QUEUES)
+			hw->mac.max_tx_queues = IXGBE_VF_MAX_TX_QUEUES;
+
+		hw->mac.max_rx_queues = msg[IXGBE_VF_RX_QUEUES];
+		if (hw->mac.max_rx_queues == 0 ||
+		    hw->mac.max_rx_queues > IXGBE_VF_MAX_RX_QUEUES)
+			hw->mac.max_rx_queues = IXGBE_VF_MAX_RX_QUEUES;
+
+		*num_tcs = msg[IXGBE_VF_TRANS_VLAN];
+		/* in case of unknown state assume we cannot tag frames */
+		if (*num_tcs > hw->mac.max_rx_queues)
+			*num_tcs = 1;
+
+		*default_tc = msg[IXGBE_VF_DEF_QUEUE];
+		/* default to queue 0 on out-of-bounds queue number */
+		if (*default_tc >= hw->mac.max_tx_queues)
+			*default_tc = 0;
+	}
+
+	return err;
+}
+
 static const struct ixgbe_mac_operations ixgbevf_mac_ops = {
 	.init_hw             = ixgbevf_init_hw_vf,
 	.reset_hw            = ixgbevf_reset_hw_vf,
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.h b/drivers/net/ethernet/intel/ixgbevf/vf.h
index 47f11a5..7b1f502 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.h
@@ -174,5 +174,7 @@ struct ixgbevf_info {
 
 void ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size);
 int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api);
+int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
+		       unsigned int *default_tc);
 #endif /* __IXGBE_VF_H__ */
 
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index 5948972..10d678d 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -1131,7 +1131,7 @@ static int pxa168_eth_open(struct net_device *dev)
 	err = request_irq(dev->irq, pxa168_eth_int_handler,
 			  IRQF_DISABLED, dev->name, dev);
 	if (err) {
-		dev_printk(KERN_ERR, &dev->dev, "can't assign irq\n");
+		dev_err(&dev->dev, "can't assign irq\n");
 		return -EAGAIN;
 	}
 	pep->rx_resource_err = 0;
@@ -1201,9 +1201,8 @@ static int pxa168_eth_change_mtu(struct net_device *dev, int mtu)
 	 */
 	pxa168_eth_stop(dev);
 	if (pxa168_eth_open(dev)) {
-		dev_printk(KERN_ERR, &dev->dev,
-			   "fatal error on re-opening device after "
-			   "MTU change\n");
+		dev_err(&dev->dev,
+			"fatal error on re-opening device after MTU change\n");
 	}
 
 	return 0;
diff --git a/drivers/net/ethernet/mellanox/Kconfig b/drivers/net/ethernet/mellanox/Kconfig
index d8099a7..bcdbc14 100644
--- a/drivers/net/ethernet/mellanox/Kconfig
+++ b/drivers/net/ethernet/mellanox/Kconfig
@@ -5,7 +5,7 @@
 config NET_VENDOR_MELLANOX
 	bool "Mellanox devices"
 	default y
-	depends on PCI && INET
+	depends on PCI
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y
 	  and read the Ethernet-HOWTO, available from
diff --git a/drivers/net/ethernet/mellanox/mlx4/Kconfig b/drivers/net/ethernet/mellanox/mlx4/Kconfig
index 5f027f9..eb520ab 100644
--- a/drivers/net/ethernet/mellanox/mlx4/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlx4/Kconfig
@@ -4,9 +4,8 @@
 
 config MLX4_EN
 	tristate "Mellanox Technologies 10Gbit Ethernet support"
-	depends on PCI && INET
+	depends on PCI
 	select MLX4_CORE
-	select INET_LRO
 	---help---
 	  This driver supports Mellanox Technologies ConnectX Ethernet
 	  devices.
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 3d1899f..e791e70 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -1755,7 +1755,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
 			spin_lock_init(&s_state->lock);
 		}
 
-		memset(&priv->mfunc.master.cmd_eqe, 0, sizeof(struct mlx4_eqe));
+		memset(&priv->mfunc.master.cmd_eqe, 0, dev->caps.eqe_size);
 		priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD;
 		INIT_WORK(&priv->mfunc.master.comm_work,
 			  mlx4_master_comm_channel);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
index aa9c2f6..b8d0854 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
@@ -51,7 +51,7 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv,
 	int err;
 
 	cq->size = entries;
-	cq->buf_size = cq->size * sizeof(struct mlx4_cqe);
+	cq->buf_size = cq->size * mdev->dev->caps.cqe_size;
 
 	cq->ring = ring;
 	cq->is_tx = mode;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c b/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
index 5d367958..b799ab12 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
@@ -237,7 +237,7 @@ static int mlx4_en_dcbnl_ieee_setmaxrate(struct net_device *dev,
 	if (err)
 		return err;
 
-	memcpy(priv->maxrate, tmp, sizeof(*priv->maxrate));
+	memcpy(priv->maxrate, tmp, sizeof(priv->maxrate));
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index edd9cb8..0163326 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -870,7 +870,7 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
 	/* If we haven't received a specific coalescing setting
 	 * (module param), we set the moderation parameters as follows:
 	 * - moder_cnt is set to the number of mtu sized packets to
-	 *   satisfy our coelsing target.
+	 *   satisfy our coalescing target.
 	 * - moder_time is set to a fixed value.
 	 */
 	priv->rx_frames = MLX4_EN_RX_COAL_TARGET;
@@ -1600,6 +1600,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 		goto out;
 	}
 	priv->rx_ring_num = prof->rx_ring_num;
+	priv->cqe_factor = (mdev->dev->caps.cqe_size == 64) ? 1 : 0;
 	priv->mac_index = -1;
 	priv->msg_enable = MLX4_EN_MSG_LEVEL;
 	spin_lock_init(&priv->stats_lock);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 5aba5ec..fed26d8 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -566,6 +566,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 	struct ethhdr *ethh;
 	dma_addr_t dma;
 	u64 s_mac;
+	int factor = priv->cqe_factor;
 
 	if (!priv->port_up)
 		return 0;
@@ -574,7 +575,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 	 * descriptor offset can be deduced from the CQE index instead of
 	 * reading 'cqe->index' */
 	index = cq->mcq.cons_index & ring->size_mask;
-	cqe = &cq->buf[index];
+	cqe = &cq->buf[(index << factor) + factor];
 
 	/* Process all completed CQEs */
 	while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK,
@@ -630,7 +631,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 			if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
 			    (cqe->checksum == cpu_to_be16(0xffff))) {
 				ring->csum_ok++;
-				/* This packet is eligible for LRO if it is:
+				/* This packet is eligible for GRO if it is:
 				 * - DIX Ethernet (type interpretation)
 				 * - TCP/IP (v4)
 				 * - without IP options
@@ -667,7 +668,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 					goto next;
 				}
 
-				/* LRO not possible, complete processing here */
+				/* GRO not possible, complete processing here */
 				ip_summed = CHECKSUM_UNNECESSARY;
 			} else {
 				ip_summed = CHECKSUM_NONE;
@@ -709,12 +710,9 @@ next:
 
 		++cq->mcq.cons_index;
 		index = (cq->mcq.cons_index) & ring->size_mask;
-		cqe = &cq->buf[index];
-		if (++polled == budget) {
-			/* We are here because we reached the NAPI budget -
-			 * flush only pending LRO sessions */
+		cqe = &cq->buf[(index << factor) + factor];
+		if (++polled == budget)
 			goto out;
-		}
 	}
 
 out:
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index b35094c..25c157a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -315,12 +315,13 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
 	struct mlx4_cqe *buf = cq->buf;
 	u32 packets = 0;
 	u32 bytes = 0;
+	int factor = priv->cqe_factor;
 
 	if (!priv->port_up)
 		return;
 
 	index = cons_index & size_mask;
-	cqe = &buf[index];
+	cqe = &buf[(index << factor) + factor];
 	ring_index = ring->cons & size_mask;
 
 	/* Process all completed CQEs */
@@ -349,7 +350,7 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
 
 		++cons_index;
 		index = cons_index & size_mask;
-		cqe = &buf[index];
+		cqe = &buf[(index << factor) + factor];
 	}
 
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index b84a88b..b941f96 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -101,15 +101,21 @@ static void eq_set_ci(struct mlx4_eq *eq, int req_not)
 	mb();
 }
 
-static struct mlx4_eqe *get_eqe(struct mlx4_eq *eq, u32 entry)
+static struct mlx4_eqe *get_eqe(struct mlx4_eq *eq, u32 entry, u8 eqe_factor)
 {
-	unsigned long off = (entry & (eq->nent - 1)) * MLX4_EQ_ENTRY_SIZE;
-	return eq->page_list[off / PAGE_SIZE].buf + off % PAGE_SIZE;
+	/* (entry & (eq->nent - 1)) gives us a cyclic array */
+	unsigned long offset = (entry & (eq->nent - 1)) * (MLX4_EQ_ENTRY_SIZE << eqe_factor);
+	/* CX3 is capable of extending the EQE from 32 to 64 bytes.
+	 * When this feature is enabled, the first (in the lower addresses)
+	 * 32 bytes in the 64 byte EQE are reserved and the next 32 bytes
+	 * contain the legacy EQE information.
+	 */
+	return eq->page_list[offset / PAGE_SIZE].buf + (offset + (eqe_factor ? MLX4_EQ_ENTRY_SIZE : 0)) % PAGE_SIZE;
 }
 
-static struct mlx4_eqe *next_eqe_sw(struct mlx4_eq *eq)
+static struct mlx4_eqe *next_eqe_sw(struct mlx4_eq *eq, u8 eqe_factor)
 {
-	struct mlx4_eqe *eqe = get_eqe(eq, eq->cons_index);
+	struct mlx4_eqe *eqe = get_eqe(eq, eq->cons_index, eqe_factor);
 	return !!(eqe->owner & 0x80) ^ !!(eq->cons_index & eq->nent) ? NULL : eqe;
 }
 
@@ -177,7 +183,7 @@ static void slave_event(struct mlx4_dev *dev, u8 slave, struct mlx4_eqe *eqe)
 		return;
 	}
 
-	memcpy(s_eqe, eqe, sizeof(struct mlx4_eqe) - 1);
+	memcpy(s_eqe, eqe, dev->caps.eqe_size - 1);
 	s_eqe->slave_id = slave;
 	/* ensure all information is written before setting the ownersip bit */
 	wmb();
@@ -441,7 +447,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
 	int i;
 	enum slave_port_gen_event gen_event;
 
-	while ((eqe = next_eqe_sw(eq))) {
+	while ((eqe = next_eqe_sw(eq, dev->caps.eqe_factor))) {
 		/*
 		 * Make sure we read EQ entry contents after we've
 		 * checked the ownership bit.
@@ -864,7 +870,8 @@ static int mlx4_create_eq(struct mlx4_dev *dev, int nent,
 
 	eq->dev   = dev;
 	eq->nent  = roundup_pow_of_two(max(nent, 2));
-	npages = PAGE_ALIGN(eq->nent * MLX4_EQ_ENTRY_SIZE) / PAGE_SIZE;
+	/* CX3 is capable of extending the CQE/EQE from 32 to 64 bytes */
+	npages = PAGE_ALIGN(eq->nent * (MLX4_EQ_ENTRY_SIZE << dev->caps.eqe_factor)) / PAGE_SIZE;
 
 	eq->page_list = kmalloc(npages * sizeof *eq->page_list,
 				GFP_KERNEL);
@@ -966,8 +973,9 @@ static void mlx4_free_eq(struct mlx4_dev *dev,
 	struct mlx4_priv *priv = mlx4_priv(dev);
 	struct mlx4_cmd_mailbox *mailbox;
 	int err;
-	int npages = PAGE_ALIGN(MLX4_EQ_ENTRY_SIZE * eq->nent) / PAGE_SIZE;
 	int i;
+	/* CX3 is capable of extending the CQE/EQE from 32 to 64 bytes */
+	int npages = PAGE_ALIGN((MLX4_EQ_ENTRY_SIZE << dev->caps.eqe_factor) * eq->nent) / PAGE_SIZE;
 
 	mailbox = mlx4_alloc_cmd_mailbox(dev);
 	if (IS_ERR(mailbox))
@@ -1267,7 +1275,7 @@ int mlx4_test_interrupts(struct mlx4_dev *dev)
 		/* Temporary use polling for command completions */
 		mlx4_cmd_use_polling(dev);
 
-		/* Map the new eq to handle all asyncronous events */
+		/* Map the new eq to handle all asynchronous events */
 		err = mlx4_MAP_EQ(dev, get_async_ev_mask(dev), 0,
 				  priv->eq_table.eq[i].eqn);
 		if (err) {
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index 4f30b99..9a9de51 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -110,6 +110,8 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u64 flags)
 		[42] = "Multicast VEP steering support",
 		[48] = "Counters support",
 		[59] = "Port management change event support",
+		[61] = "64 byte EQE support",
+		[62] = "64 byte CQE support",
 	};
 	int i;
 
@@ -235,7 +237,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
 		field = dev->caps.num_ports;
 		MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_NUM_PORTS_OFFSET);
 
-		size = 0; /* no PF behaviour is set for now */
+		size = dev->caps.function_caps; /* set PF behaviours */
 		MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_PF_BHVR_OFFSET);
 
 		field = 0; /* protected FMR support not available as yet */
@@ -1237,6 +1239,24 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS)
 		*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 4);
 
+	/* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */
+	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_EQE) {
+		*(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 29);
+		dev->caps.eqe_size   = 64;
+		dev->caps.eqe_factor = 1;
+	} else {
+		dev->caps.eqe_size   = 32;
+		dev->caps.eqe_factor = 0;
+	}
+
+	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_CQE) {
+		*(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 30);
+		dev->caps.cqe_size   = 64;
+		dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_64B_CQE;
+	} else {
+		dev->caps.cqe_size   = 32;
+	}
+
 	/* QPC/EEC/CQC/EQC/RDMARC attributes */
 
 	MLX4_PUT(inbox, param->qpc_base,      INIT_HCA_QPC_BASE_OFFSET);
@@ -1319,6 +1339,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 	struct mlx4_cmd_mailbox *mailbox;
 	__be32 *outbox;
 	int err;
+	u8 byte_field;
 
 #define QUERY_HCA_GLOBAL_CAPS_OFFSET	0x04
 
@@ -1370,6 +1391,13 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 			 INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
 	}
 
+	/* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */
+	MLX4_GET(byte_field, outbox, INIT_HCA_EQE_CQE_OFFSETS);
+	if (byte_field & 0x20) /* 64-bytes eqe enabled */
+		param->dev_cap_enabled |= MLX4_DEV_CAP_64B_EQE_ENABLED;
+	if (byte_field & 0x40) /* 64-bytes cqe enabled */
+		param->dev_cap_enabled |= MLX4_DEV_CAP_64B_CQE_ENABLED;
+
 	/* TPT attributes */
 
 	MLX4_GET(param->dmpt_base,  outbox, INIT_HCA_DMPT_BASE_OFFSET);
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h
index 85abe9c..2c2e7ad 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.h
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.h
@@ -172,6 +172,7 @@ struct mlx4_init_hca_param {
 	u8  log_uar_sz;
 	u8  uar_page_sz; /* log pg sz in 4k chunks */
 	u8  fs_hash_enable_bits;
+	u64 dev_cap_enabled;
 };
 
 struct mlx4_init_ib_param {
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 2aa80af..4337f68 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -95,8 +95,14 @@ MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num"
 					 " Not in use with device managed"
 					 " flow steering");
 
+static bool enable_64b_cqe_eqe;
+module_param(enable_64b_cqe_eqe, bool, 0444);
+MODULE_PARM_DESC(enable_64b_cqe_eqe,
+		 "Enable 64 byte CQEs/EQEs when the the FW supports this");
+
 #define HCA_GLOBAL_CAP_MASK            0
-#define PF_CONTEXT_BEHAVIOUR_MASK      0
+
+#define PF_CONTEXT_BEHAVIOUR_MASK	MLX4_FUNC_CAP_64B_EQE_CQE
 
 static char mlx4_version[] __devinitdata =
 	DRV_NAME ": Mellanox ConnectX core driver v"
@@ -386,6 +392,21 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 		dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_EXCH];
 
 	dev->caps.sqp_demux = (mlx4_is_master(dev)) ? MLX4_MAX_NUM_SLAVES : 0;
+
+	if (!enable_64b_cqe_eqe) {
+		if (dev_cap->flags &
+		    (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) {
+			mlx4_warn(dev, "64B EQEs/CQEs supported by the device but not enabled\n");
+			dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_64B_CQE;
+			dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_64B_EQE;
+		}
+	}
+
+	if ((dev_cap->flags &
+	    (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) &&
+	    mlx4_is_master(dev))
+		dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE;
+
 	return 0;
 }
 /*The function checks if there are live vf, return the num of them*/
@@ -599,6 +620,21 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
 		goto err_mem;
 	}
 
+	if (hca_param.dev_cap_enabled & MLX4_DEV_CAP_64B_EQE_ENABLED) {
+		dev->caps.eqe_size   = 64;
+		dev->caps.eqe_factor = 1;
+	} else {
+		dev->caps.eqe_size   = 32;
+		dev->caps.eqe_factor = 0;
+	}
+
+	if (hca_param.dev_cap_enabled & MLX4_DEV_CAP_64B_CQE_ENABLED) {
+		dev->caps.cqe_size   = 64;
+		dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_64B_CQE;
+	} else {
+		dev->caps.cqe_size   = 32;
+	}
+
 	return 0;
 
 err_mem:
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 9d27e42..074bc53 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -95,8 +95,6 @@
 #define MLX4_EN_ALLOC_SIZE	PAGE_ALIGN(16384)
 #define MLX4_EN_ALLOC_ORDER	get_order(MLX4_EN_ALLOC_SIZE)
 
-#define MLX4_EN_MAX_LRO_DESCRIPTORS	32
-
 /* Receive fragment sizes; we use at most 4 fragments (for 9600 byte MTU
  * and 4K allocations) */
 enum {
@@ -126,7 +124,7 @@ enum {
 #define MLX4_EN_RX_COAL_TIME	0x10
 
 #define MLX4_EN_TX_COAL_PKTS	16
-#define MLX4_EN_TX_COAL_TIME	0x80
+#define MLX4_EN_TX_COAL_TIME	0x10
 
 #define MLX4_EN_RX_RATE_LOW		400000
 #define MLX4_EN_RX_COAL_TIME_LOW	0
@@ -290,21 +288,6 @@ struct mlx4_en_rx_ring {
 	unsigned long csum_none;
 };
 
-
-static inline int mlx4_en_can_lro(__be16 status)
-{
-	return (status & cpu_to_be16(MLX4_CQE_STATUS_IPV4	|
-				     MLX4_CQE_STATUS_IPV4F	|
-				     MLX4_CQE_STATUS_IPV6	|
-				     MLX4_CQE_STATUS_IPV4OPT	|
-				     MLX4_CQE_STATUS_TCP	|
-				     MLX4_CQE_STATUS_UDP	|
-				     MLX4_CQE_STATUS_IPOK)) ==
-		cpu_to_be16(MLX4_CQE_STATUS_IPV4 |
-			    MLX4_CQE_STATUS_IPOK |
-			    MLX4_CQE_STATUS_TCP);
-}
-
 struct mlx4_en_cq {
 	struct mlx4_cq          mcq;
 	struct mlx4_hwq_resources wqres;
@@ -487,6 +470,7 @@ struct mlx4_en_priv {
 	int mac_index;
 	unsigned max_mtu;
 	int base_qpn;
+	int cqe_factor;
 
 	struct mlx4_en_rss_map rss_map;
 	__be32 ctrl_flags;
diff --git a/drivers/net/ethernet/micrel/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c
index dccae1d..e62c312 100644
--- a/drivers/net/ethernet/micrel/ks8695net.c
+++ b/drivers/net/ethernet/micrel/ks8695net.c
@@ -1249,9 +1249,6 @@ ks8695_open(struct net_device *ndev)
 	struct ks8695_priv *ksp = netdev_priv(ndev);
 	int ret;
 
-	if (!is_valid_ether_addr(ndev->dev_addr))
-		return -EADDRNOTAVAIL;
-
 	ks8695_reset(ksp);
 
 	ks8695_update_mac(ksp);
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index 69e0197..f672425 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -6769,7 +6769,7 @@ static int stp;
 /*
  * This enables fast aging in the KSZ8842 switch.  Not sure what situation
  * needs that.  However, fast aging is used to flush the dynamic MAC table when
- * STP suport is enabled.
+ * STP support is enabled.
  */
 static int fast_aging;
 
@@ -7243,18 +7243,7 @@ static struct pci_driver pci_device_driver = {
 	.remove		= pcidev_exit
 };
 
-static int __init ksz884x_init_module(void)
-{
-	return pci_register_driver(&pci_device_driver);
-}
-
-static void __exit ksz884x_cleanup_module(void)
-{
-	pci_unregister_driver(&pci_device_driver);
-}
-
-module_init(ksz884x_init_module);
-module_exit(ksz884x_cleanup_module);
+module_pci_driver(pci_device_driver);
 
 MODULE_DESCRIPTION("KSZ8841/2 PCI network driver");
 MODULE_AUTHOR("Tristram Ha <Tristram.Ha@micrel.com>");
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp_gen_header.h b/drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp_gen_header.h
index 7ec4b86..75ec5e7 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp_gen_header.h
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp_gen_header.h
@@ -27,7 +27,7 @@ struct mcp_gen_header {
 	 *
 	 * Fields below this comment are extensions added in later versions
 	 * of this struct, drivers should compare the header_length against
-	 * offsetof(field) to check wether a given MCP implements them.
+	 * offsetof(field) to check whether a given MCP implements them.
 	 *
 	 * Never remove any field.  Keep everything naturally align.
 	 */
diff --git a/drivers/net/ethernet/natsemi/Kconfig b/drivers/net/ethernet/natsemi/Kconfig
index f157334..a100860 100644
--- a/drivers/net/ethernet/natsemi/Kconfig
+++ b/drivers/net/ethernet/natsemi/Kconfig
@@ -5,9 +5,6 @@
 config NET_VENDOR_NATSEMI
 	bool "National Semi-conductor devices"
 	default y
-	depends on AMIGA_PCMCIA || ARM || EISA || EXPERIMENTAL || H8300 || \
-		   ISA || M32R || MAC || MACH_JAZZ || MACH_TX49XX || MIPS || \
-		   PCI || PCMCIA || SUPERH || XTENSA_PLATFORM_XT2000 || ZORRO
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y
 	  and read the Ethernet-HOWTO, available from
diff --git a/drivers/net/ethernet/neterion/Kconfig b/drivers/net/ethernet/neterion/Kconfig
index ff26b54..87abb4f 100644
--- a/drivers/net/ethernet/neterion/Kconfig
+++ b/drivers/net/ethernet/neterion/Kconfig
@@ -32,7 +32,7 @@ config S2IO
 
 config VXGE
 	tristate "Exar X3100 Series 10GbE PCIe Server Adapter"
-	depends on PCI && INET
+	depends on PCI
 	---help---
 	  This driver supports Exar Corp's X3100 Series 10 GbE PCIe
 	  I/O Virtualized Server Adapter.
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index de50547..c98decb 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -8239,7 +8239,8 @@ static int __init s2io_starter(void)
 
 /**
  * s2io_closer - Cleanup routine for the driver
- * Description: This function is the cleanup routine for the driver. It unregist * ers the driver.
+ * Description: This function is the cleanup routine for the driver. It
+ * unregisters the driver.
  */
 
 static __exit void s2io_closer(void)
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
index af8b414..db6e101 100644
--- a/drivers/net/ethernet/nxp/lpc_eth.c
+++ b/drivers/net/ethernet/nxp/lpc_eth.c
@@ -1219,9 +1219,6 @@ static int lpc_eth_open(struct net_device *ndev)
 	if (netif_msg_ifup(pldat))
 		dev_dbg(&pldat->pdev->dev, "enabling %s\n", ndev->name);
 
-	if (!is_valid_ether_addr(ndev->dev_addr))
-		return -EADDRNOTAVAIL;
-
 	__lpc_eth_clock_enable(pldat, true);
 
 	/* Reset and initialize */
@@ -1301,6 +1298,7 @@ static const struct net_device_ops lpc_netdev_ops = {
 	.ndo_set_rx_mode	= lpc_eth_set_multicast_list,
 	.ndo_do_ioctl		= lpc_eth_ioctl,
 	.ndo_set_mac_address	= lpc_set_mac_address,
+	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 };
 
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
index 5296cc8..34d05bf 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
@@ -7,6 +7,7 @@ config PCH_GBE
 	depends on PCI
 	select NET_CORE
 	select MII
+	select PTP_1588_CLOCK_PCH
 	---help---
 	  This is a gigabit ethernet driver for EG20T PCH.
 	  EG20T PCH is the platform controller hub that is used in Intel's
@@ -20,19 +21,3 @@ config PCH_GBE
 	  purpose use.
 	  ML7223/ML7831 is companion chip for Intel Atom E6xx series.
 	  ML7223/ML7831 is completely compatible for Intel EG20T PCH.
-
-if PCH_GBE
-
-config PCH_PTP
-	bool "PCH PTP clock support"
-	default n
-	depends on EXPERIMENTAL
-	select PPS
-	select PTP_1588_CLOCK
-	select PTP_1588_CLOCK_PCH
-	---help---
-	  Say Y here if you want to use Precision Time Protocol (PTP) in the
-	  driver. PTP is a method to precisely synchronize distributed clocks
-	  over Ethernet networks.
-
-endif # PCH_GBE
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
index b07311e..7fb7e17 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
@@ -649,7 +649,6 @@ extern void pch_gbe_free_tx_resources(struct pch_gbe_adapter *adapter,
 extern void pch_gbe_free_rx_resources(struct pch_gbe_adapter *adapter,
 				       struct pch_gbe_rx_ring *rx_ring);
 extern void pch_gbe_update_stats(struct pch_gbe_adapter *adapter);
-#ifdef CONFIG_PCH_PTP
 extern u32 pch_ch_control_read(struct pci_dev *pdev);
 extern void pch_ch_control_write(struct pci_dev *pdev, u32 val);
 extern u32 pch_ch_event_read(struct pci_dev *pdev);
@@ -659,7 +658,6 @@ extern u32 pch_src_uuid_hi_read(struct pci_dev *pdev);
 extern u64 pch_rx_snap_read(struct pci_dev *pdev);
 extern u64 pch_tx_snap_read(struct pci_dev *pdev);
 extern int pch_set_station_address(u8 *addr, struct pci_dev *pdev);
-#endif
 
 /* pch_gbe_param.c */
 extern void pch_gbe_check_options(struct pch_gbe_adapter *adapter);
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 4c4fe5b..39ab4d0 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -21,10 +21,8 @@
 #include "pch_gbe.h"
 #include "pch_gbe_api.h"
 #include <linux/module.h>
-#ifdef CONFIG_PCH_PTP
 #include <linux/net_tstamp.h>
 #include <linux/ptp_classify.h>
-#endif
 
 #define DRV_VERSION     "1.01"
 const char pch_driver_version[] = DRV_VERSION;
@@ -98,7 +96,6 @@ const char pch_driver_version[] = DRV_VERSION;
 
 #define PCH_GBE_INT_DISABLE_ALL		0
 
-#ifdef CONFIG_PCH_PTP
 /* Macros for ieee1588 */
 /* 0x40 Time Synchronization Channel Control Register Bits */
 #define MASTER_MODE   (1<<0)
@@ -113,7 +110,6 @@ const char pch_driver_version[] = DRV_VERSION;
 
 #define PTP_L4_MULTICAST_SA "01:00:5e:00:01:81"
 #define PTP_L2_MULTICAST_SA "01:1b:19:00:00:00"
-#endif
 
 static unsigned int copybreak __read_mostly = PCH_GBE_COPYBREAK_DEFAULT;
 
@@ -122,7 +118,6 @@ static void pch_gbe_mdio_write(struct net_device *netdev, int addr, int reg,
 			       int data);
 static void pch_gbe_set_multi(struct net_device *netdev);
 
-#ifdef CONFIG_PCH_PTP
 static struct sock_filter ptp_filter[] = {
 	PTP_FILTER
 };
@@ -291,7 +286,6 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 
 	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
 }
-#endif
 
 inline void pch_gbe_mac_load_mac_addr(struct pch_gbe_hw *hw)
 {
@@ -1244,9 +1238,7 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter,
 		  (int)sizeof(struct pch_gbe_tx_desc) * ring_num,
 		  &hw->reg->TX_DSC_SW_P);
 
-#ifdef CONFIG_PCH_PTP
 	pch_tx_timestamp(adapter, skb);
-#endif
 
 	dev_kfree_skb_any(skb);
 }
@@ -1730,9 +1722,7 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter,
 			/* Write meta date of skb */
 			skb_put(skb, length);
 
-#ifdef CONFIG_PCH_PTP
 			pch_rx_timestamp(adapter, skb);
-#endif
 
 			skb->protocol = eth_type_trans(skb, netdev);
 			if (tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK)
@@ -2334,10 +2324,8 @@ static int pch_gbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 
 	pr_debug("cmd : 0x%04x\n", cmd);
 
-#ifdef CONFIG_PCH_PTP
 	if (cmd == SIOCSHWTSTAMP)
 		return hwtstamp_ioctl(netdev, ifr, cmd);
-#endif
 
 	return generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
 }
@@ -2623,14 +2611,12 @@ static int pch_gbe_probe(struct pci_dev *pdev,
 		goto err_free_netdev;
 	}
 
-#ifdef CONFIG_PCH_PTP
 	adapter->ptp_pdev = pci_get_bus_and_slot(adapter->pdev->bus->number,
 					       PCI_DEVFN(12, 4));
 	if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) {
 		pr_err("Bad ptp filter\n");
 		return -EINVAL;
 	}
-#endif
 
 	netdev->netdev_ops = &pch_gbe_netdev_ops;
 	netdev->watchdog_timeo = PCH_GBE_WATCHDOG_PERIOD;
diff --git a/drivers/net/ethernet/packetengines/Kconfig b/drivers/net/ethernet/packetengines/Kconfig
index 8f29feb..cbbeca3 100644
--- a/drivers/net/ethernet/packetengines/Kconfig
+++ b/drivers/net/ethernet/packetengines/Kconfig
@@ -32,8 +32,8 @@ config HAMACHI
 	  called hamachi.
 
 config YELLOWFIN
-	tristate "Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)"
-	depends on PCI && EXPERIMENTAL
+	tristate "Packet Engines Yellowfin Gigabit-NIC support"
+	depends on PCI
 	select CRC32
 	---help---
 	  Say Y here if you have a Packet Engines G-NIC PCI Gigabit Ethernet
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
index 10468e7..4ca2c19 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
@@ -218,7 +218,7 @@ skip:
 			check_sfp_module = netif_running(dev) &&
 				adapter->has_link_events;
 		} else {
-			ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg);
+			ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
 			ecmd->advertising |=
 				(ADVERTISED_TP | ADVERTISED_Autoneg);
 			ecmd->port = PORT_TP;
@@ -381,7 +381,7 @@ static u32 netxen_nic_test_link(struct net_device *dev)
 
 static int
 netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
-		      u8 * bytes)
+		      u8 *bytes)
 {
 	struct netxen_adapter *adapter = netdev_priv(dev);
 	int offset;
@@ -488,6 +488,8 @@ netxen_nic_get_pauseparam(struct net_device *dev,
 	__u32 val;
 	int port = adapter->physical_port;
 
+	pause->autoneg = 0;
+
 	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 		if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))
 			return;
@@ -496,19 +498,19 @@ netxen_nic_get_pauseparam(struct net_device *dev,
 		pause->rx_pause = netxen_gb_get_rx_flowctl(val);
 		val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
 		switch (port) {
-			case 0:
-				pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
-				break;
-			case 1:
-				pause->tx_pause = !(netxen_gb_get_gb1_mask(val));
-				break;
-			case 2:
-				pause->tx_pause = !(netxen_gb_get_gb2_mask(val));
-				break;
-			case 3:
-			default:
-				pause->tx_pause = !(netxen_gb_get_gb3_mask(val));
-				break;
+		case 0:
+			pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
+			break;
+		case 1:
+			pause->tx_pause = !(netxen_gb_get_gb1_mask(val));
+			break;
+		case 2:
+			pause->tx_pause = !(netxen_gb_get_gb2_mask(val));
+			break;
+		case 3:
+		default:
+			pause->tx_pause = !(netxen_gb_get_gb3_mask(val));
+			break;
 		}
 	} else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 		if ((port < 0) || (port >= NETXEN_NIU_MAX_XG_PORTS))
@@ -532,6 +534,11 @@ netxen_nic_set_pauseparam(struct net_device *dev,
 	struct netxen_adapter *adapter = netdev_priv(dev);
 	__u32 val;
 	int port = adapter->physical_port;
+
+	/* not supported */
+	if (pause->autoneg)
+		return -EINVAL;
+
 	/* read mode */
 	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 		if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))
@@ -549,31 +556,31 @@ netxen_nic_set_pauseparam(struct net_device *dev,
 		/* set autoneg */
 		val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
 		switch (port) {
-			case 0:
-				if (pause->tx_pause)
-					netxen_gb_unset_gb0_mask(val);
-				else
-					netxen_gb_set_gb0_mask(val);
-				break;
-			case 1:
-				if (pause->tx_pause)
-					netxen_gb_unset_gb1_mask(val);
-				else
-					netxen_gb_set_gb1_mask(val);
-				break;
-			case 2:
-				if (pause->tx_pause)
-					netxen_gb_unset_gb2_mask(val);
-				else
-					netxen_gb_set_gb2_mask(val);
-				break;
-			case 3:
-			default:
-				if (pause->tx_pause)
-					netxen_gb_unset_gb3_mask(val);
-				else
-					netxen_gb_set_gb3_mask(val);
-				break;
+		case 0:
+			if (pause->tx_pause)
+				netxen_gb_unset_gb0_mask(val);
+			else
+				netxen_gb_set_gb0_mask(val);
+			break;
+		case 1:
+			if (pause->tx_pause)
+				netxen_gb_unset_gb1_mask(val);
+			else
+				netxen_gb_set_gb1_mask(val);
+			break;
+		case 2:
+			if (pause->tx_pause)
+				netxen_gb_unset_gb2_mask(val);
+			else
+				netxen_gb_set_gb2_mask(val);
+			break;
+		case 3:
+		default:
+			if (pause->tx_pause)
+				netxen_gb_unset_gb3_mask(val);
+			else
+				netxen_gb_set_gb3_mask(val);
+			break;
 		}
 		NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);
 	} else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
@@ -636,7 +643,7 @@ static int netxen_get_sset_count(struct net_device *dev, int sset)
 
 static void
 netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
-		     u64 * data)
+		     u64 *data)
 {
 	memset(data, 0, sizeof(uint64_t) * NETXEN_NIC_TEST_LEN);
 	if ((data[0] = netxen_nic_reg_test(dev)))
@@ -647,7 +654,7 @@ netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
 }
 
 static void
-netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
+netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
 {
 	int index;
 
@@ -668,7 +675,7 @@ netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
 
 static void
 netxen_nic_get_ethtool_stats(struct net_device *dev,
-			     struct ethtool_stats *stats, u64 * data)
+			     struct ethtool_stats *stats, u64 *data)
 {
 	struct netxen_adapter *adapter = netdev_priv(dev);
 	int index;
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
index 6407d0d..12d1f24 100644
--- a/drivers/net/ethernet/qlogic/qla3xxx.c
+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -1920,7 +1920,6 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
 {
 	struct ql_tx_buf_cb *tx_cb;
 	int i;
-	int retval = 0;
 
 	if (mac_rsp->flags & OB_MAC_IOCB_RSP_S) {
 		netdev_warn(qdev->ndev,
@@ -1935,7 +1934,6 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
 			   "Frame too short to be legal, frame not sent\n");
 
 		qdev->ndev->stats.tx_errors++;
-		retval = -EIO;
 		goto frame_not_sent;
 	}
 
@@ -1944,7 +1942,6 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
 			   mac_rsp->transaction_id);
 
 		qdev->ndev->stats.tx_errors++;
-		retval = -EIO;
 		goto invalid_seg_count;
 	}
 
@@ -3958,15 +3955,4 @@ static struct pci_driver ql3xxx_driver = {
 	.remove = __devexit_p(ql3xxx_remove),
 };
 
-static int __init ql3xxx_init_module(void)
-{
-	return pci_register_driver(&ql3xxx_driver);
-}
-
-static void __exit ql3xxx_exit(void)
-{
-	pci_unregister_driver(&ql3xxx_driver);
-}
-
-module_init(ql3xxx_init_module);
-module_exit(ql3xxx_exit);
+module_pci_driver(ql3xxx_driver);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile
index ddba83e..c4b8ced 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/Makefile
+++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile
@@ -5,4 +5,5 @@
 obj-$(CONFIG_QLCNIC) := qlcnic.o
 
 qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \
-	qlcnic_ethtool.o qlcnic_ctx.o
+	qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \
+	qlcnic_sysfs.o qlcnic_minidump.o
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index eaa1db9..082eecb 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -89,16 +89,6 @@
 #define QLCNIC_CT_DEFAULT_RX_BUF_LEN	2048
 #define QLCNIC_LRO_BUFFER_EXTRA		2048
 
-/* Opcodes to be used with the commands */
-#define TX_ETHER_PKT	0x01
-#define TX_TCP_PKT	0x02
-#define TX_UDP_PKT	0x03
-#define TX_IP_PKT	0x04
-#define TX_TCP_LSO	0x05
-#define TX_TCP_LSO6	0x06
-#define TX_TCPV6_PKT	0x0b
-#define TX_UDPV6_PKT	0x0c
-
 /* Tx defines */
 #define QLCNIC_MAX_FRAGS_PER_TX	14
 #define MAX_TSO_HEADER_DESC	2
@@ -147,28 +137,6 @@
  * Added fileds of tcpHdrSize and ipHdrSize, The driver needs to do it only when
  * we are doing LSO (above the 1500 size packet) only.
  */
-
-#define FLAGS_VLAN_TAGGED	0x10
-#define FLAGS_VLAN_OOB		0x40
-
-#define qlcnic_set_tx_vlan_tci(cmd_desc, v)	\
-	(cmd_desc)->vlan_TCI = cpu_to_le16(v);
-#define qlcnic_set_cmd_desc_port(cmd_desc, var)	\
-	((cmd_desc)->port_ctxid |= ((var) & 0x0F))
-#define qlcnic_set_cmd_desc_ctxid(cmd_desc, var)	\
-	((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
-
-#define qlcnic_set_tx_port(_desc, _port) \
-	((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0))
-
-#define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \
-	((_desc)->flags_opcode |= \
-	cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7)))
-
-#define qlcnic_set_tx_frags_len(_desc, _frags, _len) \
-	((_desc)->nfrags__length = \
-	cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8)))
-
 struct cmd_desc_type0 {
 	u8 tcp_hdr_offset;	/* For LSO only */
 	u8 ip_hdr_offset;	/* For LSO only */
@@ -203,65 +171,6 @@ struct rcv_desc {
 	__le64 addr_buffer;
 } __packed;
 
-/* opcode field in status_desc */
-#define QLCNIC_SYN_OFFLOAD	0x03
-#define QLCNIC_RXPKT_DESC  	0x04
-#define QLCNIC_OLD_RXPKT_DESC	0x3f
-#define QLCNIC_RESPONSE_DESC	0x05
-#define QLCNIC_LRO_DESC  	0x12
-
-/* for status field in status_desc */
-#define STATUS_CKSUM_LOOP	0
-#define STATUS_CKSUM_OK		2
-
-/* owner bits of status_desc */
-#define STATUS_OWNER_HOST	(0x1ULL << 56)
-#define STATUS_OWNER_PHANTOM	(0x2ULL << 56)
-
-/* Status descriptor:
-   0-3 port, 4-7 status, 8-11 type, 12-27 total_length
-   28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
-   53-55 desc_cnt, 56-57 owner, 58-63 opcode
- */
-#define qlcnic_get_sts_port(sts_data)	\
-	((sts_data) & 0x0F)
-#define qlcnic_get_sts_status(sts_data)	\
-	(((sts_data) >> 4) & 0x0F)
-#define qlcnic_get_sts_type(sts_data)	\
-	(((sts_data) >> 8) & 0x0F)
-#define qlcnic_get_sts_totallength(sts_data)	\
-	(((sts_data) >> 12) & 0xFFFF)
-#define qlcnic_get_sts_refhandle(sts_data)	\
-	(((sts_data) >> 28) & 0xFFFF)
-#define qlcnic_get_sts_prot(sts_data)	\
-	(((sts_data) >> 44) & 0x0F)
-#define qlcnic_get_sts_pkt_offset(sts_data)	\
-	(((sts_data) >> 48) & 0x1F)
-#define qlcnic_get_sts_desc_cnt(sts_data)	\
-	(((sts_data) >> 53) & 0x7)
-#define qlcnic_get_sts_opcode(sts_data)	\
-	(((sts_data) >> 58) & 0x03F)
-
-#define qlcnic_get_lro_sts_refhandle(sts_data) 	\
-	((sts_data) & 0x0FFFF)
-#define qlcnic_get_lro_sts_length(sts_data)	\
-	(((sts_data) >> 16) & 0x0FFFF)
-#define qlcnic_get_lro_sts_l2_hdr_offset(sts_data)	\
-	(((sts_data) >> 32) & 0x0FF)
-#define qlcnic_get_lro_sts_l4_hdr_offset(sts_data)	\
-	(((sts_data) >> 40) & 0x0FF)
-#define qlcnic_get_lro_sts_timestamp(sts_data)	\
-	(((sts_data) >> 48) & 0x1)
-#define qlcnic_get_lro_sts_type(sts_data)	\
-	(((sts_data) >> 49) & 0x7)
-#define qlcnic_get_lro_sts_push_flag(sts_data)		\
-	(((sts_data) >> 52) & 0x1)
-#define qlcnic_get_lro_sts_seq_number(sts_data)		\
-	((sts_data) & 0x0FFFFFFFF)
-#define qlcnic_get_lro_sts_mss(sts_data1)		\
-	((sts_data1 >> 32) & 0x0FFFF)
-
-
 struct status_desc {
 	__le64 status_desc_data[2];
 } __attribute__ ((aligned(16)));
@@ -280,16 +189,16 @@ struct status_desc {
 #define QLCNIC_UNI_FIRMWARE_IDX_OFF 	29
 
 struct uni_table_desc{
-	u32	findex;
-	u32	num_entries;
-	u32	entry_size;
-	u32	reserved[5];
+	__le32	findex;
+	__le32	num_entries;
+	__le32	entry_size;
+	__le32	reserved[5];
 };
 
 struct uni_data_desc{
-	u32	findex;
-	u32	size;
-	u32	reserved[5];
+	__le32	findex;
+	__le32	size;
+	__le32	reserved[5];
 };
 
 /* Flash Defines and Structures */
@@ -416,19 +325,19 @@ struct qlcnic_nic_intr_coalesce {
 };
 
 struct qlcnic_dump_template_hdr {
-	__le32	type;
-	__le32	offset;
-	__le32	size;
-	__le32	cap_mask;
-	__le32	num_entries;
-	__le32	version;
-	__le32	timestamp;
-	__le32	checksum;
-	__le32	drv_cap_mask;
-	__le32	sys_info[3];
-	__le32	saved_state[16];
-	__le32	cap_sizes[8];
-	__le32	rsvd[0];
+	u32	type;
+	u32	offset;
+	u32	size;
+	u32	cap_mask;
+	u32	num_entries;
+	u32	version;
+	u32	timestamp;
+	u32	checksum;
+	u32	drv_cap_mask;
+	u32	sys_info[3];
+	u32	saved_state[16];
+	u32	cap_sizes[8];
+	u32	rsvd[0];
 };
 
 struct qlcnic_fw_dump {
@@ -1065,16 +974,16 @@ struct qlcnic_adapter {
 
 	spinlock_t tx_clean_lock;
 	spinlock_t mac_learn_lock;
-	__le32 file_prd_off;	/*File fw product offset*/
+	u32 file_prd_off;	/*File fw product offset*/
 	u32 fw_version;
 	const struct firmware *fw;
 };
 
-struct qlcnic_info {
+struct qlcnic_info_le {
 	__le16	pci_func;
-	__le16	op_mode; /* 1 = Priv, 2 = NP, 3 = NP passthru */
+	__le16	op_mode;	/* 1 = Priv, 2 = NP, 3 = NP passthru */
 	__le16	phys_port;
-	__le16	switch_mode; /* 0 = disabled, 1 = int, 2 = ext */
+	__le16	switch_mode;	/* 0 = disabled, 1 = int, 2 = ext */
 
 	__le32	capabilities;
 	u8	max_mac_filters;
@@ -1088,13 +997,28 @@ struct qlcnic_info {
 	u8	reserved2[104];
 } __packed;
 
-struct qlcnic_pci_info {
-	__le16	id; /* pci function id */
-	__le16	active; /* 1 = Enabled */
-	__le16	type; /* 1 = NIC, 2 = FCoE, 3 = iSCSI */
-	__le16	default_port; /* default port number */
+struct qlcnic_info {
+	u16	pci_func;
+	u16	op_mode;
+	u16	phys_port;
+	u16	switch_mode;
+	u32	capabilities;
+	u8	max_mac_filters;
+	u8	reserved1;
+	u16	max_mtu;
+	u16	max_tx_ques;
+	u16	max_rx_ques;
+	u16	min_tx_bw;
+	u16	max_tx_bw;
+};
 
-	__le16	tx_min_bw; /* Multiple of 100mbpc */
+struct qlcnic_pci_info_le {
+	__le16	id;		/* pci function id */
+	__le16	active;		/* 1 = Enabled */
+	__le16	type;		/* 1 = NIC, 2 = FCoE, 3 = iSCSI */
+	__le16	default_port;	/* default port number */
+
+	__le16	tx_min_bw;	/* Multiple of 100mbpc */
 	__le16	tx_max_bw;
 	__le16	reserved1[2];
 
@@ -1102,6 +1026,16 @@ struct qlcnic_pci_info {
 	u8	reserved2[106];
 } __packed;
 
+struct qlcnic_pci_info {
+	u16	id;
+	u16	active;
+	u16	type;
+	u16	default_port;
+	u16	tx_min_bw;
+	u16	tx_max_bw;
+	u8	mac[ETH_ALEN];
+};
+
 struct qlcnic_npar_info {
 	u16	pvid;
 	u16	min_bw;
@@ -1208,7 +1142,7 @@ do {	\
 			(VAL1) += (VAL2); \
 } while (0)
 
-struct qlcnic_mac_statistics{
+struct qlcnic_mac_statistics_le {
 	__le64	mac_tx_frames;
 	__le64	mac_tx_bytes;
 	__le64	mac_tx_mcast_pkts;
@@ -1248,7 +1182,45 @@ struct qlcnic_mac_statistics{
 	__le64	mac_align_error;
 } __packed;
 
-struct __qlcnic_esw_statistics {
+struct qlcnic_mac_statistics {
+	u64	mac_tx_frames;
+	u64	mac_tx_bytes;
+	u64	mac_tx_mcast_pkts;
+	u64	mac_tx_bcast_pkts;
+	u64	mac_tx_pause_cnt;
+	u64	mac_tx_ctrl_pkt;
+	u64	mac_tx_lt_64b_pkts;
+	u64	mac_tx_lt_127b_pkts;
+	u64	mac_tx_lt_255b_pkts;
+	u64	mac_tx_lt_511b_pkts;
+	u64	mac_tx_lt_1023b_pkts;
+	u64	mac_tx_lt_1518b_pkts;
+	u64	mac_tx_gt_1518b_pkts;
+	u64	rsvd1[3];
+	u64	mac_rx_frames;
+	u64	mac_rx_bytes;
+	u64	mac_rx_mcast_pkts;
+	u64	mac_rx_bcast_pkts;
+	u64	mac_rx_pause_cnt;
+	u64	mac_rx_ctrl_pkt;
+	u64	mac_rx_lt_64b_pkts;
+	u64	mac_rx_lt_127b_pkts;
+	u64	mac_rx_lt_255b_pkts;
+	u64	mac_rx_lt_511b_pkts;
+	u64	mac_rx_lt_1023b_pkts;
+	u64	mac_rx_lt_1518b_pkts;
+	u64	mac_rx_gt_1518b_pkts;
+	u64	rsvd2[3];
+	u64	mac_rx_length_error;
+	u64	mac_rx_length_small;
+	u64	mac_rx_length_large;
+	u64	mac_rx_jabber;
+	u64	mac_rx_dropped;
+	u64	mac_rx_crc_error;
+	u64	mac_align_error;
+};
+
+struct qlcnic_esw_stats_le {
 	__le16 context_id;
 	__le16 version;
 	__le16 size;
@@ -1263,147 +1235,27 @@ struct __qlcnic_esw_statistics {
 	__le64 rsvd[3];
 } __packed;
 
+struct __qlcnic_esw_statistics {
+	u16	context_id;
+	u16	version;
+	u16	size;
+	u16	unused;
+	u64	unicast_frames;
+	u64	multicast_frames;
+	u64	broadcast_frames;
+	u64	dropped_frames;
+	u64	errors;
+	u64	local_frames;
+	u64	numbytes;
+	u64	rsvd[3];
+};
+
 struct qlcnic_esw_statistics {
 	struct __qlcnic_esw_statistics rx;
 	struct __qlcnic_esw_statistics tx;
 };
 
-struct qlcnic_common_entry_hdr {
-	__le32	type;
-	__le32	offset;
-	__le32	cap_size;
-	u8	mask;
-	u8	rsvd[2];
-	u8	flags;
-} __packed;
-
-struct __crb {
-	__le32	addr;
-	u8	stride;
-	u8	rsvd1[3];
-	__le32	data_size;
-	__le32	no_ops;
-	__le32	rsvd2[4];
-} __packed;
-
-struct __ctrl {
-	__le32	addr;
-	u8	stride;
-	u8	index_a;
-	__le16	timeout;
-	__le32	data_size;
-	__le32	no_ops;
-	u8	opcode;
-	u8	index_v;
-	u8	shl_val;
-	u8	shr_val;
-	__le32	val1;
-	__le32	val2;
-	__le32	val3;
-} __packed;
-
-struct __cache {
-	__le32	addr;
-	__le16	stride;
-	__le16	init_tag_val;
-	__le32	size;
-	__le32	no_ops;
-	__le32	ctrl_addr;
-	__le32	ctrl_val;
-	__le32	read_addr;
-	u8	read_addr_stride;
-	u8	read_addr_num;
-	u8	rsvd1[2];
-} __packed;
-
-struct __ocm {
-	u8	rsvd[8];
-	__le32	size;
-	__le32	no_ops;
-	u8	rsvd1[8];
-	__le32	read_addr;
-	__le32	read_addr_stride;
-} __packed;
-
-struct __mem {
-	u8	rsvd[24];
-	__le32	addr;
-	__le32	size;
-} __packed;
-
-struct __mux {
-	__le32	addr;
-	u8	rsvd[4];
-	__le32	size;
-	__le32	no_ops;
-	__le32	val;
-	__le32	val_stride;
-	__le32	read_addr;
-	u8	rsvd2[4];
-} __packed;
-
-struct __queue {
-	__le32	sel_addr;
-	__le16	stride;
-	u8	rsvd[2];
-	__le32	size;
-	__le32	no_ops;
-	u8	rsvd2[8];
-	__le32	read_addr;
-	u8	read_addr_stride;
-	u8	read_addr_cnt;
-	u8	rsvd3[2];
-} __packed;
-
-struct qlcnic_dump_entry {
-	struct qlcnic_common_entry_hdr hdr;
-	union {
-		struct __crb	crb;
-		struct __cache	cache;
-		struct __ocm	ocm;
-		struct __mem	mem;
-		struct __mux	mux;
-		struct __queue	que;
-		struct __ctrl	ctrl;
-	} region;
-} __packed;
-
-enum op_codes {
-	QLCNIC_DUMP_NOP		= 0,
-	QLCNIC_DUMP_READ_CRB	= 1,
-	QLCNIC_DUMP_READ_MUX	= 2,
-	QLCNIC_DUMP_QUEUE	= 3,
-	QLCNIC_DUMP_BRD_CONFIG	= 4,
-	QLCNIC_DUMP_READ_OCM	= 6,
-	QLCNIC_DUMP_PEG_REG	= 7,
-	QLCNIC_DUMP_L1_DTAG	= 8,
-	QLCNIC_DUMP_L1_ITAG	= 9,
-	QLCNIC_DUMP_L1_DATA	= 11,
-	QLCNIC_DUMP_L1_INST	= 12,
-	QLCNIC_DUMP_L2_DTAG	= 21,
-	QLCNIC_DUMP_L2_ITAG	= 22,
-	QLCNIC_DUMP_L2_DATA	= 23,
-	QLCNIC_DUMP_L2_INST	= 24,
-	QLCNIC_DUMP_READ_ROM	= 71,
-	QLCNIC_DUMP_READ_MEM	= 72,
-	QLCNIC_DUMP_READ_CTRL	= 98,
-	QLCNIC_DUMP_TLHDR	= 99,
-	QLCNIC_DUMP_RDEND	= 255
-};
-
-#define QLCNIC_DUMP_WCRB	BIT_0
-#define QLCNIC_DUMP_RWCRB	BIT_1
-#define QLCNIC_DUMP_ANDCRB	BIT_2
-#define QLCNIC_DUMP_ORCRB	BIT_3
-#define QLCNIC_DUMP_POLLCRB	BIT_4
-#define QLCNIC_DUMP_RD_SAVE	BIT_5
-#define QLCNIC_DUMP_WRT_SAVED	BIT_6
-#define QLCNIC_DUMP_MOD_SAVE_ST	BIT_7
-#define QLCNIC_DUMP_SKIP	BIT_7
-
-#define QLCNIC_DUMP_MASK_MIN		3
 #define QLCNIC_DUMP_MASK_DEF		0x1f
-#define QLCNIC_DUMP_MASK_MAX		0xff
 #define QLCNIC_FORCE_FW_DUMP_KEY	0xdeadfeed
 #define QLCNIC_ENABLE_FW_DUMP		0xaddfeed
 #define QLCNIC_DISABLE_FW_DUMP		0xbadfeed
@@ -1411,12 +1263,6 @@ enum op_codes {
 #define QLCNIC_SET_QUIESCENT		0xadd00010
 #define QLCNIC_RESET_QUIESCENT		0xadd00020
 
-struct qlcnic_dump_operations {
-	enum op_codes opcode;
-	u32 (*handler)(struct qlcnic_adapter *,
-			struct qlcnic_dump_entry *, u32 *);
-};
-
 struct _cdrp_cmd {
 	u32 cmd;
 	u32 arg1;
@@ -1474,6 +1320,8 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int);
 #define __QLCNIC_MAX_LED_RATE	0xf
 #define __QLCNIC_MAX_LED_STATE	0x2
 
+#define MAX_CTL_CHECK 1000
+
 int qlcnic_get_board_info(struct qlcnic_adapter *adapter);
 int qlcnic_wol_supported(struct qlcnic_adapter *adapter);
 int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate);
@@ -1530,9 +1378,8 @@ int qlcnic_set_features(struct net_device *netdev, netdev_features_t features);
 int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable);
 int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable);
 int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
-void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
-		struct qlcnic_host_tx_ring *tx_ring);
-void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *);
+void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *);
+void qlcnic_fetch_mac(u32, u32, u8, u8 *);
 void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
 void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter);
 int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode);
@@ -1571,6 +1418,26 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8);
 int qlcnic_get_mac_stats(struct qlcnic_adapter *, struct qlcnic_mac_statistics *);
 extern int qlcnic_config_tso;
 
+int qlcnic_napi_add(struct qlcnic_adapter *, struct net_device *);
+void qlcnic_napi_del(struct qlcnic_adapter *adapter);
+void qlcnic_napi_enable(struct qlcnic_adapter *adapter);
+void qlcnic_napi_disable(struct qlcnic_adapter *adapter);
+int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *, int);
+void qlcnic_free_sds_rings(struct qlcnic_recv_context *);
+void qlcnic_free_tx_rings(struct qlcnic_adapter *);
+int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *);
+
+void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter);
+void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter);
+void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter);
+void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
+int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
+int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
+void qlcnic_set_vlan_config(struct qlcnic_adapter *,
+			    struct qlcnic_esw_func_cfg *);
+void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *,
+				      struct qlcnic_esw_func_cfg *);
+
 /*
  * QLOGIC Board information
  */
@@ -1617,6 +1484,21 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring)
 				tx_ring->producer;
 }
 
+static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring)
+{
+	writel(0, sds_ring->crb_intr_mask);
+}
+
+static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring)
+{
+	struct qlcnic_adapter *adapter = sds_ring->adapter;
+
+	writel(0x1, sds_ring->crb_intr_mask);
+
+	if (!QLCNIC_IS_MSI_FAMILY(adapter))
+		writel(0xfbff, adapter->tgt_mask_reg);
+}
+
 extern const struct ethtool_ops qlcnic_ethtool_ops;
 extern const struct ethtool_ops qlcnic_ethtool_failed_ops;
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index 2a179d0..bd31104 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -103,7 +103,7 @@ qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd)
 
 }
 
-static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u16 temp_size)
+static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u32 temp_size)
 {
 	uint64_t sum = 0;
 	int count = temp_size / sizeof(uint32_t);
@@ -117,9 +117,9 @@ static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u16 temp_size)
 int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
 {
 	int err, i;
-	u16 temp_size;
 	void *tmp_addr;
-	u32 version, csum, *template, *tmp_buf;
+	u32 temp_size, version, csum, *template;
+	__le32 *tmp_buf;
 	struct qlcnic_cmd_args cmd;
 	struct qlcnic_hardware_context *ahw;
 	struct qlcnic_dump_template_hdr *tmpl_hdr, *tmp_tmpl;
@@ -163,13 +163,6 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
 		goto error;
 	}
 	tmp_tmpl = tmp_addr;
-	csum = qlcnic_temp_checksum((uint32_t *) tmp_addr, temp_size);
-	if (csum) {
-		dev_err(&adapter->pdev->dev,
-			"Template header checksum validation failed\n");
-		err = -EIO;
-		goto error;
-	}
 	ahw->fw_dump.tmpl_hdr = vzalloc(temp_size);
 	if (!ahw->fw_dump.tmpl_hdr) {
 		err = -EIO;
@@ -180,6 +173,14 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
 	for (i = 0; i < temp_size/sizeof(u32); i++)
 		*template++ = __le32_to_cpu(*tmp_buf++);
 
+	csum = qlcnic_temp_checksum((u32 *)ahw->fw_dump.tmpl_hdr, temp_size);
+	if (csum) {
+		dev_err(&adapter->pdev->dev,
+			"Template header checksum validation failed\n");
+		err = -EIO;
+		goto error;
+	}
+
 	tmpl_hdr = ahw->fw_dump.tmpl_hdr;
 	tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF;
 	ahw->fw_dump.enable = 1;
@@ -231,6 +232,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
 	size_t rq_size, rsp_size;
 	u32 cap, reg, val, reg2;
 	int err;
+	u16 temp;
 
 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
 
@@ -267,8 +269,8 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
 	if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
 		cap |= QLCNIC_CAP0_LRO_MSS;
 
-	prq->valid_field_offset = offsetof(struct qlcnic_hostrq_rx_ctx,
-							 msix_handler);
+	temp = offsetof(struct qlcnic_hostrq_rx_ctx, msix_handler);
+	prq->valid_field_offset = cpu_to_le16(temp);
 	prq->txrx_sds_binding = nsds_rings - 1;
 
 	prq->capabilities[0] = cpu_to_le32(cap);
@@ -671,7 +673,7 @@ int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
 	err = cmd.rsp.cmd;
 
 	if (err == QLCNIC_RCODE_SUCCESS)
-		qlcnic_fetch_mac(adapter, cmd.rsp.arg1, cmd.rsp.arg2, 0, mac);
+		qlcnic_fetch_mac(cmd.rsp.arg1, cmd.rsp.arg2, 0, mac);
 	else {
 		dev_err(&adapter->pdev->dev,
 			"Failed to get mac address%d\n", err);
@@ -687,10 +689,10 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
 {
 	int	err;
 	dma_addr_t nic_dma_t;
-	struct qlcnic_info *nic_info;
+	struct qlcnic_info_le *nic_info;
 	void *nic_info_addr;
 	struct qlcnic_cmd_args cmd;
-	size_t	nic_size = sizeof(struct qlcnic_info);
+	size_t	nic_size = sizeof(struct qlcnic_info_le);
 
 	nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
 				&nic_dma_t, GFP_KERNEL);
@@ -745,8 +747,8 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
 	dma_addr_t nic_dma_t;
 	void *nic_info_addr;
 	struct qlcnic_cmd_args cmd;
-	struct qlcnic_info *nic_info;
-	size_t nic_size = sizeof(struct qlcnic_info);
+	struct qlcnic_info_le *nic_info;
+	size_t nic_size = sizeof(struct qlcnic_info_le);
 
 	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
 		return err;
@@ -796,9 +798,9 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
 	int err = 0, i;
 	struct qlcnic_cmd_args cmd;
 	dma_addr_t pci_info_dma_t;
-	struct qlcnic_pci_info *npar;
+	struct qlcnic_pci_info_le *npar;
 	void *pci_info_addr;
-	size_t npar_size = sizeof(struct qlcnic_pci_info);
+	size_t npar_size = sizeof(struct qlcnic_pci_info_le);
 	size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC;
 
 	pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size,
@@ -877,8 +879,8 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
 int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
 		const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
 
-	size_t stats_size = sizeof(struct __qlcnic_esw_statistics);
-	struct __qlcnic_esw_statistics *stats;
+	size_t stats_size = sizeof(struct qlcnic_esw_stats_le);
+	struct qlcnic_esw_stats_le *stats;
 	dma_addr_t stats_dma_t;
 	void *stats_addr;
 	u32 arg1;
@@ -939,9 +941,9 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
 int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
 		struct qlcnic_mac_statistics *mac_stats)
 {
-	struct qlcnic_mac_statistics *stats;
+	struct qlcnic_mac_statistics_le *stats;
 	struct qlcnic_cmd_args cmd;
-	size_t stats_size = sizeof(struct qlcnic_mac_statistics);
+	size_t stats_size = sizeof(struct qlcnic_mac_statistics_le);
 	dma_addr_t stats_dma_t;
 	void *stats_addr;
 	int err;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index 9e9e78a..4a9425b 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -1247,7 +1247,8 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
 			void *buffer)
 {
 	int i, copy_sz;
-	u32 *hdr_ptr, *data;
+	u32 *hdr_ptr;
+	__le32 *data;
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
index 28a6b28..bd5030e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
@@ -792,22 +792,6 @@ static const u32 MIU_TEST_READ_DATA[] = {
 #define QLCNIC_FLASH_SEM2_ULK	0x0013C014
 #define QLCNIC_FLASH_LOCK_ID	0x001B2100
 
-#define QLCNIC_RD_DUMP_REG(addr, bar0, data) do {			\
-	writel((addr & 0xFFFF0000), (void *) (bar0 +			\
-		QLCNIC_FW_DUMP_REG1));					\
-	readl((void *) (bar0 + QLCNIC_FW_DUMP_REG1));			\
-	*data = readl((void *) (bar0 + QLCNIC_FW_DUMP_REG2 +		\
-		LSW(addr)));						\
-} while (0)
-
-#define QLCNIC_WR_DUMP_REG(addr, bar0, data) do {			\
-	writel((addr & 0xFFFF0000), (void *) (bar0 +			\
-		QLCNIC_FW_DUMP_REG1));					\
-	readl((void *) (bar0 + QLCNIC_FW_DUMP_REG1));			\
-	writel(data, (void *) (bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr)));\
-	readl((void *) (bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr)));	\
-} while (0)
-
 /* PCI function operational mode */
 enum {
 	QLCNIC_MGMT_FUNC	= 0,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 2a0c9dc..ff879cd 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -350,7 +350,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
 
 	tx_ring->producer = producer;
 
-	qlcnic_update_cmd_producer(adapter, tx_ring);
+	qlcnic_update_cmd_producer(tx_ring);
 
 	__netif_tx_unlock_bh(tx_ring->txq);
 
@@ -540,7 +540,7 @@ void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter)
 	}
 }
 
-int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag)
+static int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag)
 {
 	struct qlcnic_nic_req req;
 	int rv;
@@ -1061,8 +1061,6 @@ qlcnic_pci_camqm_write_2M(struct qlcnic_adapter *adapter, u64 off, u64 data)
 	mutex_unlock(&adapter->ahw->mem_lock);
 }
 
-#define MAX_CTL_CHECK   1000
-
 int
 qlcnic_pci_mem_write_2M(struct qlcnic_adapter *adapter,
 		u64 off, u64 data)
@@ -1320,469 +1318,3 @@ int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
 
 	return rv;
 }
-
-/* FW dump related functions */
-static u32
-qlcnic_dump_crb(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
-		u32 *buffer)
-{
-	int i;
-	u32 addr, data;
-	struct __crb *crb = &entry->region.crb;
-	void __iomem *base = adapter->ahw->pci_base0;
-
-	addr = crb->addr;
-
-	for (i = 0; i < crb->no_ops; i++) {
-		QLCNIC_RD_DUMP_REG(addr, base, &data);
-		*buffer++ = cpu_to_le32(addr);
-		*buffer++ = cpu_to_le32(data);
-		addr += crb->stride;
-	}
-	return crb->no_ops * 2 * sizeof(u32);
-}
-
-static u32
-qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,
-	struct qlcnic_dump_entry *entry, u32 *buffer)
-{
-	int i, k, timeout = 0;
-	void __iomem *base = adapter->ahw->pci_base0;
-	u32 addr, data;
-	u8 opcode, no_ops;
-	struct __ctrl *ctr = &entry->region.ctrl;
-	struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr;
-
-	addr = ctr->addr;
-	no_ops = ctr->no_ops;
-
-	for (i = 0; i < no_ops; i++) {
-		k = 0;
-		opcode = 0;
-		for (k = 0; k < 8; k++) {
-			if (!(ctr->opcode & (1 << k)))
-				continue;
-			switch (1 << k) {
-			case QLCNIC_DUMP_WCRB:
-				QLCNIC_WR_DUMP_REG(addr, base, ctr->val1);
-				break;
-			case QLCNIC_DUMP_RWCRB:
-				QLCNIC_RD_DUMP_REG(addr, base, &data);
-				QLCNIC_WR_DUMP_REG(addr, base, data);
-				break;
-			case QLCNIC_DUMP_ANDCRB:
-				QLCNIC_RD_DUMP_REG(addr, base, &data);
-				QLCNIC_WR_DUMP_REG(addr, base,
-					(data & ctr->val2));
-				break;
-			case QLCNIC_DUMP_ORCRB:
-				QLCNIC_RD_DUMP_REG(addr, base, &data);
-				QLCNIC_WR_DUMP_REG(addr, base,
-					(data | ctr->val3));
-				break;
-			case QLCNIC_DUMP_POLLCRB:
-				while (timeout <= ctr->timeout) {
-					QLCNIC_RD_DUMP_REG(addr, base, &data);
-					if ((data & ctr->val2) == ctr->val1)
-						break;
-					msleep(1);
-					timeout++;
-				}
-				if (timeout > ctr->timeout) {
-					dev_info(&adapter->pdev->dev,
-					"Timed out, aborting poll CRB\n");
-					return -EINVAL;
-				}
-				break;
-			case QLCNIC_DUMP_RD_SAVE:
-				if (ctr->index_a)
-					addr = t_hdr->saved_state[ctr->index_a];
-				QLCNIC_RD_DUMP_REG(addr, base, &data);
-				t_hdr->saved_state[ctr->index_v] = data;
-				break;
-			case QLCNIC_DUMP_WRT_SAVED:
-				if (ctr->index_v)
-					data = t_hdr->saved_state[ctr->index_v];
-				else
-					data = ctr->val1;
-				if (ctr->index_a)
-					addr = t_hdr->saved_state[ctr->index_a];
-				QLCNIC_WR_DUMP_REG(addr, base, data);
-				break;
-			case QLCNIC_DUMP_MOD_SAVE_ST:
-				data = t_hdr->saved_state[ctr->index_v];
-				data <<= ctr->shl_val;
-				data >>= ctr->shr_val;
-				if (ctr->val2)
-					data &= ctr->val2;
-				data |= ctr->val3;
-				data += ctr->val1;
-				t_hdr->saved_state[ctr->index_v] = data;
-				break;
-			default:
-				dev_info(&adapter->pdev->dev,
-					"Unknown opcode\n");
-				break;
-			}
-		}
-		addr += ctr->stride;
-	}
-	return 0;
-}
-
-static u32
-qlcnic_dump_mux(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
-	u32 *buffer)
-{
-	int loop;
-	u32 val, data = 0;
-	struct __mux *mux = &entry->region.mux;
-	void __iomem *base = adapter->ahw->pci_base0;
-
-	val = mux->val;
-	for (loop = 0; loop < mux->no_ops; loop++) {
-		QLCNIC_WR_DUMP_REG(mux->addr, base, val);
-		QLCNIC_RD_DUMP_REG(mux->read_addr, base, &data);
-		*buffer++ = cpu_to_le32(val);
-		*buffer++ = cpu_to_le32(data);
-		val += mux->val_stride;
-	}
-	return 2 * mux->no_ops * sizeof(u32);
-}
-
-static u32
-qlcnic_dump_que(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
-	u32 *buffer)
-{
-	int i, loop;
-	u32 cnt, addr, data, que_id = 0;
-	void __iomem *base = adapter->ahw->pci_base0;
-	struct __queue *que = &entry->region.que;
-
-	addr = que->read_addr;
-	cnt = que->read_addr_cnt;
-
-	for (loop = 0; loop < que->no_ops; loop++) {
-		QLCNIC_WR_DUMP_REG(que->sel_addr, base, que_id);
-		addr = que->read_addr;
-		for (i = 0; i < cnt; i++) {
-			QLCNIC_RD_DUMP_REG(addr, base, &data);
-			*buffer++ = cpu_to_le32(data);
-			addr += que->read_addr_stride;
-		}
-		que_id += que->stride;
-	}
-	return que->no_ops * cnt * sizeof(u32);
-}
-
-static u32
-qlcnic_dump_ocm(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
-	u32 *buffer)
-{
-	int i;
-	u32 data;
-	void __iomem *addr;
-	struct __ocm *ocm = &entry->region.ocm;
-
-	addr = adapter->ahw->pci_base0 + ocm->read_addr;
-	for (i = 0; i < ocm->no_ops; i++) {
-		data = readl(addr);
-		*buffer++ = cpu_to_le32(data);
-		addr += ocm->read_addr_stride;
-	}
-	return ocm->no_ops * sizeof(u32);
-}
-
-static u32
-qlcnic_read_rom(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
-	u32 *buffer)
-{
-	int i, count = 0;
-	u32 fl_addr, size, val, lck_val, addr;
-	struct __mem *rom = &entry->region.mem;
-	void __iomem *base = adapter->ahw->pci_base0;
-
-	fl_addr = rom->addr;
-	size = rom->size/4;
-lock_try:
-	lck_val = readl(base + QLCNIC_FLASH_SEM2_LK);
-	if (!lck_val && count < MAX_CTL_CHECK) {
-		msleep(10);
-		count++;
-		goto lock_try;
-	}
-	writel(adapter->ahw->pci_func, (base + QLCNIC_FLASH_LOCK_ID));
-	for (i = 0; i < size; i++) {
-		addr = fl_addr & 0xFFFF0000;
-		QLCNIC_WR_DUMP_REG(FLASH_ROM_WINDOW, base, addr);
-		addr = LSW(fl_addr) + FLASH_ROM_DATA;
-		QLCNIC_RD_DUMP_REG(addr, base, &val);
-		fl_addr += 4;
-		*buffer++ = cpu_to_le32(val);
-	}
-	readl(base + QLCNIC_FLASH_SEM2_ULK);
-	return rom->size;
-}
-
-static u32
-qlcnic_dump_l1_cache(struct qlcnic_adapter *adapter,
-	struct qlcnic_dump_entry *entry, u32 *buffer)
-{
-	int i;
-	u32 cnt, val, data, addr;
-	void __iomem *base = adapter->ahw->pci_base0;
-	struct __cache *l1 = &entry->region.cache;
-
-	val = l1->init_tag_val;
-
-	for (i = 0; i < l1->no_ops; i++) {
-		QLCNIC_WR_DUMP_REG(l1->addr, base, val);
-		QLCNIC_WR_DUMP_REG(l1->ctrl_addr, base, LSW(l1->ctrl_val));
-		addr = l1->read_addr;
-		cnt = l1->read_addr_num;
-		while (cnt) {
-			QLCNIC_RD_DUMP_REG(addr, base, &data);
-			*buffer++ = cpu_to_le32(data);
-			addr += l1->read_addr_stride;
-			cnt--;
-		}
-		val += l1->stride;
-	}
-	return l1->no_ops * l1->read_addr_num * sizeof(u32);
-}
-
-static u32
-qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter,
-	struct qlcnic_dump_entry *entry, u32 *buffer)
-{
-	int i;
-	u32 cnt, val, data, addr;
-	u8 poll_mask, poll_to, time_out = 0;
-	void __iomem *base = adapter->ahw->pci_base0;
-	struct __cache *l2 = &entry->region.cache;
-
-	val = l2->init_tag_val;
-	poll_mask = LSB(MSW(l2->ctrl_val));
-	poll_to = MSB(MSW(l2->ctrl_val));
-
-	for (i = 0; i < l2->no_ops; i++) {
-		QLCNIC_WR_DUMP_REG(l2->addr, base, val);
-		if (LSW(l2->ctrl_val))
-			QLCNIC_WR_DUMP_REG(l2->ctrl_addr, base,
-				LSW(l2->ctrl_val));
-		if (!poll_mask)
-			goto skip_poll;
-		do {
-			QLCNIC_RD_DUMP_REG(l2->ctrl_addr, base, &data);
-			if (!(data & poll_mask))
-				break;
-			msleep(1);
-			time_out++;
-		} while (time_out <= poll_to);
-
-		if (time_out > poll_to) {
-			dev_err(&adapter->pdev->dev,
-				"Timeout exceeded in %s, aborting dump\n",
-				__func__);
-			return -EINVAL;
-		}
-skip_poll:
-		addr = l2->read_addr;
-		cnt = l2->read_addr_num;
-		while (cnt) {
-			QLCNIC_RD_DUMP_REG(addr, base, &data);
-			*buffer++ = cpu_to_le32(data);
-			addr += l2->read_addr_stride;
-			cnt--;
-		}
-		val += l2->stride;
-	}
-	return l2->no_ops * l2->read_addr_num * sizeof(u32);
-}
-
-static u32
-qlcnic_read_memory(struct qlcnic_adapter *adapter,
-	struct qlcnic_dump_entry *entry, u32 *buffer)
-{
-	u32 addr, data, test, ret = 0;
-	int i, reg_read;
-	struct __mem *mem = &entry->region.mem;
-	void __iomem *base = adapter->ahw->pci_base0;
-
-	reg_read = mem->size;
-	addr = mem->addr;
-	/* check for data size of multiple of 16 and 16 byte alignment */
-	if ((addr & 0xf) || (reg_read%16)) {
-		dev_info(&adapter->pdev->dev,
-			"Unaligned memory addr:0x%x size:0x%x\n",
-			addr, reg_read);
-		return -EINVAL;
-	}
-
-	mutex_lock(&adapter->ahw->mem_lock);
-
-	while (reg_read != 0) {
-		QLCNIC_WR_DUMP_REG(MIU_TEST_ADDR_LO, base, addr);
-		QLCNIC_WR_DUMP_REG(MIU_TEST_ADDR_HI, base, 0);
-		QLCNIC_WR_DUMP_REG(MIU_TEST_CTR, base,
-			TA_CTL_ENABLE | TA_CTL_START);
-
-		for (i = 0; i < MAX_CTL_CHECK; i++) {
-			QLCNIC_RD_DUMP_REG(MIU_TEST_CTR, base, &test);
-			if (!(test & TA_CTL_BUSY))
-				break;
-		}
-		if (i == MAX_CTL_CHECK) {
-			if (printk_ratelimit()) {
-				dev_err(&adapter->pdev->dev,
-					"failed to read through agent\n");
-				ret = -EINVAL;
-				goto out;
-			}
-		}
-		for (i = 0; i < 4; i++) {
-			QLCNIC_RD_DUMP_REG(MIU_TEST_READ_DATA[i], base, &data);
-			*buffer++ = cpu_to_le32(data);
-		}
-		addr += 16;
-		reg_read -= 16;
-		ret += 16;
-	}
-out:
-	mutex_unlock(&adapter->ahw->mem_lock);
-	return mem->size;
-}
-
-static u32
-qlcnic_dump_nop(struct qlcnic_adapter *adapter,
-	struct qlcnic_dump_entry *entry, u32 *buffer)
-{
-	entry->hdr.flags |= QLCNIC_DUMP_SKIP;
-	return 0;
-}
-
-struct qlcnic_dump_operations fw_dump_ops[] = {
-	{ QLCNIC_DUMP_NOP, qlcnic_dump_nop },
-	{ QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb },
-	{ QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux },
-	{ QLCNIC_DUMP_QUEUE, qlcnic_dump_que },
-	{ QLCNIC_DUMP_BRD_CONFIG, qlcnic_read_rom },
-	{ QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm },
-	{ QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl },
-	{ QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache },
-	{ QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache },
-	{ QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache },
-	{ QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache },
-	{ QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache },
-	{ QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache },
-	{ QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache },
-	{ QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache },
-	{ QLCNIC_DUMP_READ_ROM, qlcnic_read_rom },
-	{ QLCNIC_DUMP_READ_MEM, qlcnic_read_memory },
-	{ QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl },
-	{ QLCNIC_DUMP_TLHDR, qlcnic_dump_nop },
-	{ QLCNIC_DUMP_RDEND, qlcnic_dump_nop },
-};
-
-/* Walk the template and collect dump for each entry in the dump template */
-static int
-qlcnic_valid_dump_entry(struct device *dev, struct qlcnic_dump_entry *entry,
-	u32 size)
-{
-	int ret = 1;
-	if (size != entry->hdr.cap_size) {
-		dev_info(dev,
-		"Invalidate dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n",
-		entry->hdr.type, entry->hdr.mask, size, entry->hdr.cap_size);
-		dev_info(dev, "Aborting further dump capture\n");
-		ret = 0;
-	}
-	return ret;
-}
-
-int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
-{
-	u32 *buffer;
-	char mesg[64];
-	char *msg[] = {mesg, NULL};
-	int i, k, ops_cnt, ops_index, dump_size = 0;
-	u32 entry_offset, dump, no_entries, buf_offset = 0;
-	struct qlcnic_dump_entry *entry;
-	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
-	struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr;
-
-	if (fw_dump->clr) {
-		dev_info(&adapter->pdev->dev,
-			"Previous dump not cleared, not capturing dump\n");
-		return -EIO;
-	}
-	/* Calculate the size for dump data area only */
-	for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++)
-		if (i & tmpl_hdr->drv_cap_mask)
-			dump_size += tmpl_hdr->cap_sizes[k];
-	if (!dump_size)
-		return -EIO;
-
-	fw_dump->data = vzalloc(dump_size);
-	if (!fw_dump->data) {
-		dev_info(&adapter->pdev->dev,
-			"Unable to allocate (%d KB) for fw dump\n",
-			dump_size/1024);
-		return -ENOMEM;
-	}
-	buffer = fw_dump->data;
-	fw_dump->size = dump_size;
-	no_entries = tmpl_hdr->num_entries;
-	ops_cnt = ARRAY_SIZE(fw_dump_ops);
-	entry_offset = tmpl_hdr->offset;
-	tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION;
-	tmpl_hdr->sys_info[1] = adapter->fw_version;
-
-	for (i = 0; i < no_entries; i++) {
-		entry = (void *)tmpl_hdr + entry_offset;
-		if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) {
-			entry->hdr.flags |= QLCNIC_DUMP_SKIP;
-			entry_offset += entry->hdr.offset;
-			continue;
-		}
-		/* Find the handler for this entry */
-		ops_index = 0;
-		while (ops_index < ops_cnt) {
-			if (entry->hdr.type == fw_dump_ops[ops_index].opcode)
-				break;
-			ops_index++;
-		}
-		if (ops_index == ops_cnt) {
-			dev_info(&adapter->pdev->dev,
-				"Invalid entry type %d, exiting dump\n",
-				entry->hdr.type);
-			goto error;
-		}
-		/* Collect dump for this entry */
-		dump = fw_dump_ops[ops_index].handler(adapter, entry, buffer);
-		if (dump && !qlcnic_valid_dump_entry(&adapter->pdev->dev, entry,
-			dump))
-			entry->hdr.flags |= QLCNIC_DUMP_SKIP;
-		buf_offset += entry->hdr.cap_size;
-		entry_offset += entry->hdr.offset;
-		buffer = fw_dump->data + buf_offset;
-	}
-	if (dump_size != buf_offset) {
-		dev_info(&adapter->pdev->dev,
-			"Captured(%d) and expected size(%d) do not match\n",
-			buf_offset, dump_size);
-		goto error;
-	} else {
-		fw_dump->clr = 1;
-		snprintf(mesg, sizeof(mesg), "FW_DUMP=%s",
-			adapter->netdev->name);
-		dev_info(&adapter->pdev->dev, "Dump data, %d bytes captured\n",
-			fw_dump->size);
-		/* Send a udev event to notify availability of FW dump */
-		kobject_uevent_env(&adapter->pdev->dev.kobj, KOBJ_CHANGE, msg);
-		return 0;
-	}
-error:
-	vfree(fw_dump->data);
-	return -EINVAL;
-}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
index 0bcda9c..d8610ea 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
@@ -25,10 +25,6 @@ static unsigned int crb_addr_xform[QLCNIC_MAX_CRB_XFORM];
 
 #define QLCNIC_ADDR_ERROR (0xffffffff)
 
-static void
-qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
-		struct qlcnic_host_rds_ring *rds_ring);
-
 static int
 qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter);
 
@@ -778,15 +774,15 @@ qlcnic_has_mn(struct qlcnic_adapter *adapter)
 static
 struct uni_table_desc *qlcnic_get_table_desc(const u8 *unirom, int section)
 {
-	u32 i;
+	u32 i, entries;
 	struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
-	__le32 entries = cpu_to_le32(directory->num_entries);
+	entries = le32_to_cpu(directory->num_entries);
 
 	for (i = 0; i < entries; i++) {
 
-		__le32 offs = cpu_to_le32(directory->findex) +
-				(i * cpu_to_le32(directory->entry_size));
-		__le32 tab_type = cpu_to_le32(*((u32 *)&unirom[offs] + 8));
+		u32 offs = le32_to_cpu(directory->findex) +
+			   i * le32_to_cpu(directory->entry_size);
+		u32 tab_type = le32_to_cpu(*((__le32 *)&unirom[offs] + 8));
 
 		if (tab_type == section)
 			return (struct uni_table_desc *) &unirom[offs];
@@ -802,17 +798,16 @@ qlcnic_validate_header(struct qlcnic_adapter *adapter)
 {
 	const u8 *unirom = adapter->fw->data;
 	struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
-	__le32 fw_file_size = adapter->fw->size;
-	__le32 entries;
-	__le32 entry_size;
-	__le32 tab_size;
+	u32 entries, entry_size, tab_size, fw_file_size;
+
+	fw_file_size = adapter->fw->size;
 
 	if (fw_file_size < FILEHEADER_SIZE)
 		return -EINVAL;
 
-	entries = cpu_to_le32(directory->num_entries);
-	entry_size = cpu_to_le32(directory->entry_size);
-	tab_size = cpu_to_le32(directory->findex) + (entries * entry_size);
+	entries = le32_to_cpu(directory->num_entries);
+	entry_size = le32_to_cpu(directory->entry_size);
+	tab_size = le32_to_cpu(directory->findex) + (entries * entry_size);
 
 	if (fw_file_size < tab_size)
 		return -EINVAL;
@@ -825,29 +820,29 @@ qlcnic_validate_bootld(struct qlcnic_adapter *adapter)
 {
 	struct uni_table_desc *tab_desc;
 	struct uni_data_desc *descr;
+	u32 offs, tab_size, data_size, idx;
 	const u8 *unirom = adapter->fw->data;
-	int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
-				QLCNIC_UNI_BOOTLD_IDX_OFF));
-	__le32 offs;
-	__le32 tab_size;
-	__le32 data_size;
+	__le32 temp;
 
+	temp = *((__le32 *)&unirom[adapter->file_prd_off] +
+		 QLCNIC_UNI_BOOTLD_IDX_OFF);
+	idx = le32_to_cpu(temp);
 	tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_BOOTLD);
 
 	if (!tab_desc)
 		return -EINVAL;
 
-	tab_size = cpu_to_le32(tab_desc->findex) +
-			(cpu_to_le32(tab_desc->entry_size) * (idx + 1));
+	tab_size = le32_to_cpu(tab_desc->findex) +
+		   le32_to_cpu(tab_desc->entry_size) * (idx + 1);
 
 	if (adapter->fw->size < tab_size)
 		return -EINVAL;
 
-	offs = cpu_to_le32(tab_desc->findex) +
-		(cpu_to_le32(tab_desc->entry_size) * (idx));
+	offs = le32_to_cpu(tab_desc->findex) +
+	       le32_to_cpu(tab_desc->entry_size) * idx;
 	descr = (struct uni_data_desc *)&unirom[offs];
 
-	data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size);
+	data_size = le32_to_cpu(descr->findex) + le32_to_cpu(descr->size);
 
 	if (adapter->fw->size < data_size)
 		return -EINVAL;
@@ -861,27 +856,27 @@ qlcnic_validate_fw(struct qlcnic_adapter *adapter)
 	struct uni_table_desc *tab_desc;
 	struct uni_data_desc *descr;
 	const u8 *unirom = adapter->fw->data;
-	int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
-				QLCNIC_UNI_FIRMWARE_IDX_OFF));
-	__le32 offs;
-	__le32 tab_size;
-	__le32 data_size;
+	u32 offs, tab_size, data_size, idx;
+	__le32 temp;
 
+	temp = *((__le32 *)&unirom[adapter->file_prd_off] +
+		 QLCNIC_UNI_FIRMWARE_IDX_OFF);
+	idx = le32_to_cpu(temp);
 	tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_FW);
 
 	if (!tab_desc)
 		return -EINVAL;
 
-	tab_size = cpu_to_le32(tab_desc->findex) +
-			(cpu_to_le32(tab_desc->entry_size) * (idx + 1));
+	tab_size = le32_to_cpu(tab_desc->findex) +
+		   le32_to_cpu(tab_desc->entry_size) * (idx + 1);
 
 	if (adapter->fw->size < tab_size)
 		return -EINVAL;
 
-	offs = cpu_to_le32(tab_desc->findex) +
-		(cpu_to_le32(tab_desc->entry_size) * (idx));
+	offs = le32_to_cpu(tab_desc->findex) +
+	       le32_to_cpu(tab_desc->entry_size) * idx;
 	descr = (struct uni_data_desc *)&unirom[offs];
-	data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size);
+	data_size = le32_to_cpu(descr->findex) + le32_to_cpu(descr->size);
 
 	if (adapter->fw->size < data_size)
 		return -EINVAL;
@@ -895,19 +890,17 @@ qlcnic_validate_product_offs(struct qlcnic_adapter *adapter)
 	struct uni_table_desc *ptab_descr;
 	const u8 *unirom = adapter->fw->data;
 	int mn_present = qlcnic_has_mn(adapter);
-	__le32 entries;
-	__le32 entry_size;
-	__le32 tab_size;
-	u32 i;
+	u32 entries, entry_size, tab_size, i;
+	__le32 temp;
 
 	ptab_descr = qlcnic_get_table_desc(unirom,
 				QLCNIC_UNI_DIR_SECT_PRODUCT_TBL);
 	if (!ptab_descr)
 		return -EINVAL;
 
-	entries = cpu_to_le32(ptab_descr->num_entries);
-	entry_size = cpu_to_le32(ptab_descr->entry_size);
-	tab_size = cpu_to_le32(ptab_descr->findex) + (entries * entry_size);
+	entries = le32_to_cpu(ptab_descr->num_entries);
+	entry_size = le32_to_cpu(ptab_descr->entry_size);
+	tab_size = le32_to_cpu(ptab_descr->findex) + (entries * entry_size);
 
 	if (adapter->fw->size < tab_size)
 		return -EINVAL;
@@ -915,16 +908,16 @@ qlcnic_validate_product_offs(struct qlcnic_adapter *adapter)
 nomn:
 	for (i = 0; i < entries; i++) {
 
-		__le32 flags, file_chiprev, offs;
+		u32 flags, file_chiprev, offs;
 		u8 chiprev = adapter->ahw->revision_id;
 		u32 flagbit;
 
-		offs = cpu_to_le32(ptab_descr->findex) +
-				(i * cpu_to_le32(ptab_descr->entry_size));
-		flags = cpu_to_le32(*((int *)&unirom[offs] +
-						QLCNIC_UNI_FLAGS_OFF));
-		file_chiprev = cpu_to_le32(*((int *)&unirom[offs] +
-						QLCNIC_UNI_CHIP_REV_OFF));
+		offs = le32_to_cpu(ptab_descr->findex) +
+		       i * le32_to_cpu(ptab_descr->entry_size);
+		temp = *((__le32 *)&unirom[offs] + QLCNIC_UNI_FLAGS_OFF);
+		flags = le32_to_cpu(temp);
+		temp = *((__le32 *)&unirom[offs] + QLCNIC_UNI_CHIP_REV_OFF);
+		file_chiprev = le32_to_cpu(temp);
 
 		flagbit = mn_present ? 1 : 2;
 
@@ -976,18 +969,20 @@ struct uni_data_desc *qlcnic_get_data_desc(struct qlcnic_adapter *adapter,
 			u32 section, u32 idx_offset)
 {
 	const u8 *unirom = adapter->fw->data;
-	int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
-								idx_offset));
 	struct uni_table_desc *tab_desc;
-	__le32 offs;
+	u32 offs, idx;
+	__le32 temp;
+
+	temp = *((__le32 *)&unirom[adapter->file_prd_off] + idx_offset);
+	idx = le32_to_cpu(temp);
 
 	tab_desc = qlcnic_get_table_desc(unirom, section);
 
 	if (tab_desc == NULL)
 		return NULL;
 
-	offs = cpu_to_le32(tab_desc->findex) +
-			(cpu_to_le32(tab_desc->entry_size) * idx);
+	offs = le32_to_cpu(tab_desc->findex) +
+	       le32_to_cpu(tab_desc->entry_size) * idx;
 
 	return (struct uni_data_desc *)&unirom[offs];
 }
@@ -996,11 +991,13 @@ static u8 *
 qlcnic_get_bootld_offs(struct qlcnic_adapter *adapter)
 {
 	u32 offs = QLCNIC_BOOTLD_START;
+	struct uni_data_desc *data_desc;
+
+	data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_BOOTLD,
+					 QLCNIC_UNI_BOOTLD_IDX_OFF);
 
 	if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
-		offs = cpu_to_le32((qlcnic_get_data_desc(adapter,
-					QLCNIC_UNI_DIR_SECT_BOOTLD,
-					QLCNIC_UNI_BOOTLD_IDX_OFF))->findex);
+		offs = le32_to_cpu(data_desc->findex);
 
 	return (u8 *)&adapter->fw->data[offs];
 }
@@ -1009,43 +1006,48 @@ static u8 *
 qlcnic_get_fw_offs(struct qlcnic_adapter *adapter)
 {
 	u32 offs = QLCNIC_IMAGE_START;
+	struct uni_data_desc *data_desc;
 
+	data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
+					 QLCNIC_UNI_FIRMWARE_IDX_OFF);
 	if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
-		offs = cpu_to_le32((qlcnic_get_data_desc(adapter,
-					QLCNIC_UNI_DIR_SECT_FW,
-					QLCNIC_UNI_FIRMWARE_IDX_OFF))->findex);
+		offs = le32_to_cpu(data_desc->findex);
 
 	return (u8 *)&adapter->fw->data[offs];
 }
 
-static __le32
-qlcnic_get_fw_size(struct qlcnic_adapter *adapter)
+static u32 qlcnic_get_fw_size(struct qlcnic_adapter *adapter)
 {
+	struct uni_data_desc *data_desc;
+	const u8 *unirom = adapter->fw->data;
+
+	data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
+					 QLCNIC_UNI_FIRMWARE_IDX_OFF);
+
 	if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
-		return cpu_to_le32((qlcnic_get_data_desc(adapter,
-					QLCNIC_UNI_DIR_SECT_FW,
-					QLCNIC_UNI_FIRMWARE_IDX_OFF))->size);
+		return le32_to_cpu(data_desc->size);
 	else
-		return cpu_to_le32(
-			*(u32 *)&adapter->fw->data[QLCNIC_FW_SIZE_OFFSET]);
+		return le32_to_cpu(*(__le32 *)&unirom[QLCNIC_FW_SIZE_OFFSET]);
 }
 
-static __le32
-qlcnic_get_fw_version(struct qlcnic_adapter *adapter)
+static u32 qlcnic_get_fw_version(struct qlcnic_adapter *adapter)
 {
 	struct uni_data_desc *fw_data_desc;
 	const struct firmware *fw = adapter->fw;
-	__le32 major, minor, sub;
+	u32 major, minor, sub;
+	__le32 version_offset;
 	const u8 *ver_str;
 	int i, ret;
 
-	if (adapter->fw_type != QLCNIC_UNIFIED_ROMIMAGE)
-		return cpu_to_le32(*(u32 *)&fw->data[QLCNIC_FW_VERSION_OFFSET]);
+	if (adapter->fw_type != QLCNIC_UNIFIED_ROMIMAGE) {
+		version_offset = *(__le32 *)&fw->data[QLCNIC_FW_VERSION_OFFSET];
+		return le32_to_cpu(version_offset);
+	}
 
 	fw_data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
 			QLCNIC_UNI_FIRMWARE_IDX_OFF);
-	ver_str = fw->data + cpu_to_le32(fw_data_desc->findex) +
-		cpu_to_le32(fw_data_desc->size) - 17;
+	ver_str = fw->data + le32_to_cpu(fw_data_desc->findex) +
+		  le32_to_cpu(fw_data_desc->size) - 17;
 
 	for (i = 0; i < 12; i++) {
 		if (!strncmp(&ver_str[i], "REV=", 4)) {
@@ -1061,18 +1063,20 @@ qlcnic_get_fw_version(struct qlcnic_adapter *adapter)
 	return 0;
 }
 
-static __le32
-qlcnic_get_bios_version(struct qlcnic_adapter *adapter)
+static u32 qlcnic_get_bios_version(struct qlcnic_adapter *adapter)
 {
 	const struct firmware *fw = adapter->fw;
-	__le32 bios_ver, prd_off = adapter->file_prd_off;
+	u32 bios_ver, prd_off = adapter->file_prd_off;
+	u8 *version_offset;
+	__le32 temp;
 
-	if (adapter->fw_type != QLCNIC_UNIFIED_ROMIMAGE)
-		return cpu_to_le32(
-			*(u32 *)&fw->data[QLCNIC_BIOS_VERSION_OFFSET]);
+	if (adapter->fw_type != QLCNIC_UNIFIED_ROMIMAGE) {
+		version_offset = (u8 *)&fw->data[QLCNIC_BIOS_VERSION_OFFSET];
+		return le32_to_cpu(*(__le32 *)version_offset);
+	}
 
-	bios_ver = cpu_to_le32(*((u32 *) (&fw->data[prd_off])
-				+ QLCNIC_UNI_BIOS_VERSION_OFF));
+	temp = *((__le32 *)(&fw->data[prd_off]) + QLCNIC_UNI_BIOS_VERSION_OFF);
+	bios_ver = le32_to_cpu(temp);
 
 	return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24);
 }
@@ -1131,7 +1135,7 @@ static const char *fw_name[] = {
 int
 qlcnic_load_firmware(struct qlcnic_adapter *adapter)
 {
-	u64 *ptr64;
+	__le64 *ptr64;
 	u32 i, flashaddr, size;
 	const struct firmware *fw = adapter->fw;
 	struct pci_dev *pdev = adapter->pdev;
@@ -1140,15 +1144,15 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter)
 			fw_name[adapter->fw_type]);
 
 	if (fw) {
-		__le64 data;
+		u64 data;
 
 		size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8;
 
-		ptr64 = (u64 *)qlcnic_get_bootld_offs(adapter);
+		ptr64 = (__le64 *)qlcnic_get_bootld_offs(adapter);
 		flashaddr = QLCNIC_BOOTLD_START;
 
 		for (i = 0; i < size; i++) {
-			data = cpu_to_le64(ptr64[i]);
+			data = le64_to_cpu(ptr64[i]);
 
 			if (qlcnic_pci_mem_write_2M(adapter, flashaddr, data))
 				return -EIO;
@@ -1156,13 +1160,13 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter)
 			flashaddr += 8;
 		}
 
-		size = (__force u32)qlcnic_get_fw_size(adapter) / 8;
+		size = qlcnic_get_fw_size(adapter) / 8;
 
-		ptr64 = (u64 *)qlcnic_get_fw_offs(adapter);
+		ptr64 = (__le64 *)qlcnic_get_fw_offs(adapter);
 		flashaddr = QLCNIC_IMAGE_START;
 
 		for (i = 0; i < size; i++) {
-			data = cpu_to_le64(ptr64[i]);
+			data = le64_to_cpu(ptr64[i]);
 
 			if (qlcnic_pci_mem_write_2M(adapter,
 						flashaddr, data))
@@ -1171,9 +1175,9 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter)
 			flashaddr += 8;
 		}
 
-		size = (__force u32)qlcnic_get_fw_size(adapter) % 8;
+		size = qlcnic_get_fw_size(adapter) % 8;
 		if (size) {
-			data = cpu_to_le64(ptr64[i]);
+			data = le64_to_cpu(ptr64[i]);
 
 			if (qlcnic_pci_mem_write_2M(adapter,
 						flashaddr, data))
@@ -1225,7 +1229,7 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter)
 static int
 qlcnic_validate_firmware(struct qlcnic_adapter *adapter)
 {
-	__le32 val;
+	u32 val;
 	u32 ver, bios, min_size;
 	struct pci_dev *pdev = adapter->pdev;
 	const struct firmware *fw = adapter->fw;
@@ -1237,8 +1241,8 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter)
 
 		min_size = QLCNIC_UNI_FW_MIN_SIZE;
 	} else {
-		val = cpu_to_le32(*(u32 *)&fw->data[QLCNIC_FW_MAGIC_OFFSET]);
-		if ((__force u32)val != QLCNIC_BDINFO_MAGIC)
+		val = le32_to_cpu(*(__le32 *)&fw->data[QLCNIC_FW_MAGIC_OFFSET]);
+		if (val != QLCNIC_BDINFO_MAGIC)
 			return -EINVAL;
 
 		min_size = QLCNIC_FW_MIN_SIZE;
@@ -1259,7 +1263,7 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter)
 
 	val = qlcnic_get_bios_version(adapter);
 	qlcnic_rom_fast_read(adapter, QLCNIC_BIOS_VERSION_OFFSET, (int *)&bios);
-	if ((__force u32)val != bios) {
+	if (val != bios) {
 		dev_err(&pdev->dev, "%s: firmware bios is incompatible\n",
 				fw_name[fw_type]);
 		return -EINVAL;
@@ -1324,633 +1328,3 @@ qlcnic_release_firmware(struct qlcnic_adapter *adapter)
 	release_firmware(adapter->fw);
 	adapter->fw = NULL;
 }
-
-static void
-qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
-				struct qlcnic_fw_msg *msg)
-{
-	u32 cable_OUI;
-	u16 cable_len;
-	u16 link_speed;
-	u8  link_status, module, duplex, autoneg;
-	u8 lb_status = 0;
-	struct net_device *netdev = adapter->netdev;
-
-	adapter->has_link_events = 1;
-
-	cable_OUI = msg->body[1] & 0xffffffff;
-	cable_len = (msg->body[1] >> 32) & 0xffff;
-	link_speed = (msg->body[1] >> 48) & 0xffff;
-
-	link_status = msg->body[2] & 0xff;
-	duplex = (msg->body[2] >> 16) & 0xff;
-	autoneg = (msg->body[2] >> 24) & 0xff;
-	lb_status = (msg->body[2] >> 32) & 0x3;
-
-	module = (msg->body[2] >> 8) & 0xff;
-	if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE)
-		dev_info(&netdev->dev, "unsupported cable: OUI 0x%x, "
-				"length %d\n", cable_OUI, cable_len);
-	else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN)
-		dev_info(&netdev->dev, "unsupported cable length %d\n",
-				cable_len);
-
-	if (!link_status && (lb_status == QLCNIC_ILB_MODE ||
-	    lb_status == QLCNIC_ELB_MODE))
-		adapter->ahw->loopback_state |= QLCNIC_LINKEVENT;
-
-	qlcnic_advert_link_change(adapter, link_status);
-
-	if (duplex == LINKEVENT_FULL_DUPLEX)
-		adapter->link_duplex = DUPLEX_FULL;
-	else
-		adapter->link_duplex = DUPLEX_HALF;
-
-	adapter->module_type = module;
-	adapter->link_autoneg = autoneg;
-
-	if (link_status) {
-		adapter->link_speed = link_speed;
-	} else {
-		adapter->link_speed = SPEED_UNKNOWN;
-		adapter->link_duplex = DUPLEX_UNKNOWN;
-	}
-}
-
-static void
-qlcnic_handle_fw_message(int desc_cnt, int index,
-		struct qlcnic_host_sds_ring *sds_ring)
-{
-	struct qlcnic_fw_msg msg;
-	struct status_desc *desc;
-	struct qlcnic_adapter *adapter;
-	struct device *dev;
-	int i = 0, opcode, ret;
-
-	while (desc_cnt > 0 && i < 8) {
-		desc = &sds_ring->desc_head[index];
-		msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]);
-		msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]);
-
-		index = get_next_index(index, sds_ring->num_desc);
-		desc_cnt--;
-	}
-
-	adapter = sds_ring->adapter;
-	dev = &adapter->pdev->dev;
-	opcode = qlcnic_get_nic_msg_opcode(msg.body[0]);
-
-	switch (opcode) {
-	case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
-		qlcnic_handle_linkevent(adapter, &msg);
-		break;
-	case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK:
-		ret = (u32)(msg.body[1]);
-		switch (ret) {
-		case 0:
-			adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE;
-			break;
-		case 1:
-			dev_info(dev, "loopback already in progress\n");
-			adapter->diag_cnt = -QLCNIC_TEST_IN_PROGRESS;
-			break;
-		case 2:
-			dev_info(dev, "loopback cable is not connected\n");
-			adapter->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN;
-			break;
-		default:
-			dev_info(dev, "loopback configure request failed,"
-					" ret %x\n", ret);
-			adapter->diag_cnt = -QLCNIC_UNDEFINED_ERROR;
-			break;
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-static int
-qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter,
-		struct qlcnic_host_rds_ring *rds_ring,
-		struct qlcnic_rx_buffer *buffer)
-{
-	struct sk_buff *skb;
-	dma_addr_t dma;
-	struct pci_dev *pdev = adapter->pdev;
-
-	skb = netdev_alloc_skb(adapter->netdev, rds_ring->skb_size);
-	if (!skb) {
-		adapter->stats.skb_alloc_failure++;
-		return -ENOMEM;
-	}
-
-	skb_reserve(skb, NET_IP_ALIGN);
-
-	dma = pci_map_single(pdev, skb->data,
-			rds_ring->dma_size, PCI_DMA_FROMDEVICE);
-
-	if (pci_dma_mapping_error(pdev, dma)) {
-		adapter->stats.rx_dma_map_error++;
-		dev_kfree_skb_any(skb);
-		return -ENOMEM;
-	}
-
-	buffer->skb = skb;
-	buffer->dma = dma;
-
-	return 0;
-}
-
-static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
-		struct qlcnic_host_rds_ring *rds_ring, u16 index, u16 cksum)
-{
-	struct qlcnic_rx_buffer *buffer;
-	struct sk_buff *skb;
-
-	buffer = &rds_ring->rx_buf_arr[index];
-
-	if (unlikely(buffer->skb == NULL)) {
-		WARN_ON(1);
-		return NULL;
-	}
-
-	pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size,
-			PCI_DMA_FROMDEVICE);
-
-	skb = buffer->skb;
-
-	if (likely((adapter->netdev->features & NETIF_F_RXCSUM) &&
-	    (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) {
-		adapter->stats.csummed++;
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	} else {
-		skb_checksum_none_assert(skb);
-	}
-
-	buffer->skb = NULL;
-
-	return skb;
-}
-
-static inline int
-qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb,
-			u16 *vlan_tag)
-{
-	struct ethhdr *eth_hdr;
-
-	if (!__vlan_get_tag(skb, vlan_tag)) {
-		eth_hdr = (struct ethhdr *) skb->data;
-		memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
-		skb_pull(skb, VLAN_HLEN);
-	}
-	if (!adapter->pvid)
-		return 0;
-
-	if (*vlan_tag == adapter->pvid) {
-		/* Outer vlan tag. Packet should follow non-vlan path */
-		*vlan_tag = 0xffff;
-		return 0;
-	}
-	if (adapter->flags & QLCNIC_TAGGING_ENABLED)
-		return 0;
-
-	return -EINVAL;
-}
-
-static struct qlcnic_rx_buffer *
-qlcnic_process_rcv(struct qlcnic_adapter *adapter,
-		struct qlcnic_host_sds_ring *sds_ring,
-		int ring, u64 sts_data0)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-	struct qlcnic_rx_buffer *buffer;
-	struct sk_buff *skb;
-	struct qlcnic_host_rds_ring *rds_ring;
-	int index, length, cksum, pkt_offset;
-	u16 vid = 0xffff;
-
-	if (unlikely(ring >= adapter->max_rds_rings))
-		return NULL;
-
-	rds_ring = &recv_ctx->rds_rings[ring];
-
-	index = qlcnic_get_sts_refhandle(sts_data0);
-	if (unlikely(index >= rds_ring->num_desc))
-		return NULL;
-
-	buffer = &rds_ring->rx_buf_arr[index];
-
-	length = qlcnic_get_sts_totallength(sts_data0);
-	cksum  = qlcnic_get_sts_status(sts_data0);
-	pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
-
-	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
-	if (!skb)
-		return buffer;
-
-	if (length > rds_ring->skb_size)
-		skb_put(skb, rds_ring->skb_size);
-	else
-		skb_put(skb, length);
-
-	if (pkt_offset)
-		skb_pull(skb, pkt_offset);
-
-	if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
-		adapter->stats.rxdropped++;
-		dev_kfree_skb(skb);
-		return buffer;
-	}
-
-	skb->protocol = eth_type_trans(skb, netdev);
-
-	if (vid != 0xffff)
-		__vlan_hwaccel_put_tag(skb, vid);
-
-	napi_gro_receive(&sds_ring->napi, skb);
-
-	adapter->stats.rx_pkts++;
-	adapter->stats.rxbytes += length;
-
-	return buffer;
-}
-
-#define QLC_TCP_HDR_SIZE            20
-#define QLC_TCP_TS_OPTION_SIZE      12
-#define QLC_TCP_TS_HDR_SIZE         (QLC_TCP_HDR_SIZE + QLC_TCP_TS_OPTION_SIZE)
-
-static struct qlcnic_rx_buffer *
-qlcnic_process_lro(struct qlcnic_adapter *adapter,
-		struct qlcnic_host_sds_ring *sds_ring,
-		int ring, u64 sts_data0, u64 sts_data1)
-{
-	struct net_device *netdev = adapter->netdev;
-	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-	struct qlcnic_rx_buffer *buffer;
-	struct sk_buff *skb;
-	struct qlcnic_host_rds_ring *rds_ring;
-	struct iphdr *iph;
-	struct tcphdr *th;
-	bool push, timestamp;
-	int l2_hdr_offset, l4_hdr_offset;
-	int index;
-	u16 lro_length, length, data_offset;
-	u32 seq_number;
-	u16 vid = 0xffff;
-
-	if (unlikely(ring > adapter->max_rds_rings))
-		return NULL;
-
-	rds_ring = &recv_ctx->rds_rings[ring];
-
-	index = qlcnic_get_lro_sts_refhandle(sts_data0);
-	if (unlikely(index > rds_ring->num_desc))
-		return NULL;
-
-	buffer = &rds_ring->rx_buf_arr[index];
-
-	timestamp = qlcnic_get_lro_sts_timestamp(sts_data0);
-	lro_length = qlcnic_get_lro_sts_length(sts_data0);
-	l2_hdr_offset = qlcnic_get_lro_sts_l2_hdr_offset(sts_data0);
-	l4_hdr_offset = qlcnic_get_lro_sts_l4_hdr_offset(sts_data0);
-	push = qlcnic_get_lro_sts_push_flag(sts_data0);
-	seq_number = qlcnic_get_lro_sts_seq_number(sts_data1);
-
-	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
-	if (!skb)
-		return buffer;
-
-	if (timestamp)
-		data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE;
-	else
-		data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE;
-
-	skb_put(skb, lro_length + data_offset);
-
-	skb_pull(skb, l2_hdr_offset);
-
-	if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
-		adapter->stats.rxdropped++;
-		dev_kfree_skb(skb);
-		return buffer;
-	}
-
-	skb->protocol = eth_type_trans(skb, netdev);
-
-	iph = (struct iphdr *)skb->data;
-	th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
-
-	length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
-	iph->tot_len = htons(length);
-	iph->check = 0;
-	iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-	th->psh = push;
-	th->seq = htonl(seq_number);
-
-	length = skb->len;
-
-	if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
-		skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1);
-
-	if (vid != 0xffff)
-		__vlan_hwaccel_put_tag(skb, vid);
-	netif_receive_skb(skb);
-
-	adapter->stats.lro_pkts++;
-	adapter->stats.lrobytes += length;
-
-	return buffer;
-}
-
-int
-qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max)
-{
-	struct qlcnic_adapter *adapter = sds_ring->adapter;
-	struct list_head *cur;
-	struct status_desc *desc;
-	struct qlcnic_rx_buffer *rxbuf;
-	u64 sts_data0, sts_data1;
-
-	int count = 0;
-	int opcode, ring, desc_cnt;
-	u32 consumer = sds_ring->consumer;
-
-	while (count < max) {
-		desc = &sds_ring->desc_head[consumer];
-		sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
-
-		if (!(sts_data0 & STATUS_OWNER_HOST))
-			break;
-
-		desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
-		opcode = qlcnic_get_sts_opcode(sts_data0);
-
-		switch (opcode) {
-		case QLCNIC_RXPKT_DESC:
-		case QLCNIC_OLD_RXPKT_DESC:
-		case QLCNIC_SYN_OFFLOAD:
-			ring = qlcnic_get_sts_type(sts_data0);
-			rxbuf = qlcnic_process_rcv(adapter, sds_ring,
-					ring, sts_data0);
-			break;
-		case QLCNIC_LRO_DESC:
-			ring = qlcnic_get_lro_sts_type(sts_data0);
-			sts_data1 = le64_to_cpu(desc->status_desc_data[1]);
-			rxbuf = qlcnic_process_lro(adapter, sds_ring,
-					ring, sts_data0, sts_data1);
-			break;
-		case QLCNIC_RESPONSE_DESC:
-			qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
-		default:
-			goto skip;
-		}
-
-		WARN_ON(desc_cnt > 1);
-
-		if (likely(rxbuf))
-			list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
-		else
-			adapter->stats.null_rxbuf++;
-
-skip:
-		for (; desc_cnt > 0; desc_cnt--) {
-			desc = &sds_ring->desc_head[consumer];
-			desc->status_desc_data[0] =
-				cpu_to_le64(STATUS_OWNER_PHANTOM);
-			consumer = get_next_index(consumer, sds_ring->num_desc);
-		}
-		count++;
-	}
-
-	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
-		struct qlcnic_host_rds_ring *rds_ring =
-			&adapter->recv_ctx->rds_rings[ring];
-
-		if (!list_empty(&sds_ring->free_list[ring])) {
-			list_for_each(cur, &sds_ring->free_list[ring]) {
-				rxbuf = list_entry(cur,
-						struct qlcnic_rx_buffer, list);
-				qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf);
-			}
-			spin_lock(&rds_ring->lock);
-			list_splice_tail_init(&sds_ring->free_list[ring],
-						&rds_ring->free_list);
-			spin_unlock(&rds_ring->lock);
-		}
-
-		qlcnic_post_rx_buffers_nodb(adapter, rds_ring);
-	}
-
-	if (count) {
-		sds_ring->consumer = consumer;
-		writel(consumer, sds_ring->crb_sts_consumer);
-	}
-
-	return count;
-}
-
-void
-qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
-	struct qlcnic_host_rds_ring *rds_ring)
-{
-	struct rcv_desc *pdesc;
-	struct qlcnic_rx_buffer *buffer;
-	int count = 0;
-	u32 producer;
-	struct list_head *head;
-
-	producer = rds_ring->producer;
-
-	head = &rds_ring->free_list;
-	while (!list_empty(head)) {
-
-		buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
-
-		if (!buffer->skb) {
-			if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
-				break;
-		}
-
-		count++;
-		list_del(&buffer->list);
-
-		/* make a rcv descriptor  */
-		pdesc = &rds_ring->desc_head[producer];
-		pdesc->addr_buffer = cpu_to_le64(buffer->dma);
-		pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
-		pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
-
-		producer = get_next_index(producer, rds_ring->num_desc);
-	}
-
-	if (count) {
-		rds_ring->producer = producer;
-		writel((producer-1) & (rds_ring->num_desc-1),
-				rds_ring->crb_rcv_producer);
-	}
-}
-
-static void
-qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
-		struct qlcnic_host_rds_ring *rds_ring)
-{
-	struct rcv_desc *pdesc;
-	struct qlcnic_rx_buffer *buffer;
-	int  count = 0;
-	uint32_t producer;
-	struct list_head *head;
-
-	if (!spin_trylock(&rds_ring->lock))
-		return;
-
-	producer = rds_ring->producer;
-
-	head = &rds_ring->free_list;
-	while (!list_empty(head)) {
-
-		buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
-
-		if (!buffer->skb) {
-			if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
-				break;
-		}
-
-		count++;
-		list_del(&buffer->list);
-
-		/* make a rcv descriptor  */
-		pdesc = &rds_ring->desc_head[producer];
-		pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
-		pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
-		pdesc->addr_buffer = cpu_to_le64(buffer->dma);
-
-		producer = get_next_index(producer, rds_ring->num_desc);
-	}
-
-	if (count) {
-		rds_ring->producer = producer;
-		writel((producer - 1) & (rds_ring->num_desc - 1),
-				rds_ring->crb_rcv_producer);
-	}
-	spin_unlock(&rds_ring->lock);
-}
-
-static void dump_skb(struct sk_buff *skb, struct qlcnic_adapter *adapter)
-{
-	int i;
-	unsigned char *data = skb->data;
-
-	printk(KERN_INFO "\n");
-	for (i = 0; i < skb->len; i++) {
-		QLCDB(adapter, DRV, "%02x ", data[i]);
-		if ((i & 0x0f) == 8)
-			printk(KERN_INFO "\n");
-	}
-}
-
-void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
-		struct qlcnic_host_sds_ring *sds_ring,
-		int ring, u64 sts_data0)
-{
-	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-	struct sk_buff *skb;
-	struct qlcnic_host_rds_ring *rds_ring;
-	int index, length, cksum, pkt_offset;
-
-	if (unlikely(ring >= adapter->max_rds_rings))
-		return;
-
-	rds_ring = &recv_ctx->rds_rings[ring];
-
-	index = qlcnic_get_sts_refhandle(sts_data0);
-	length = qlcnic_get_sts_totallength(sts_data0);
-	if (unlikely(index >= rds_ring->num_desc))
-		return;
-
-	cksum  = qlcnic_get_sts_status(sts_data0);
-	pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
-
-	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
-	if (!skb)
-		return;
-
-	if (length > rds_ring->skb_size)
-		skb_put(skb, rds_ring->skb_size);
-	else
-		skb_put(skb, length);
-
-	if (pkt_offset)
-		skb_pull(skb, pkt_offset);
-
-	if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
-		adapter->diag_cnt++;
-	else
-		dump_skb(skb, adapter);
-
-	dev_kfree_skb_any(skb);
-	adapter->stats.rx_pkts++;
-	adapter->stats.rxbytes += length;
-
-	return;
-}
-
-void
-qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
-{
-	struct qlcnic_adapter *adapter = sds_ring->adapter;
-	struct status_desc *desc;
-	u64 sts_data0;
-	int ring, opcode, desc_cnt;
-
-	u32 consumer = sds_ring->consumer;
-
-	desc = &sds_ring->desc_head[consumer];
-	sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
-
-	if (!(sts_data0 & STATUS_OWNER_HOST))
-		return;
-
-	desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
-	opcode = qlcnic_get_sts_opcode(sts_data0);
-	switch (opcode) {
-	case QLCNIC_RESPONSE_DESC:
-		qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
-		break;
-	default:
-		ring = qlcnic_get_sts_type(sts_data0);
-		qlcnic_process_rcv_diag(adapter, sds_ring, ring, sts_data0);
-		break;
-	}
-
-	for (; desc_cnt > 0; desc_cnt--) {
-		desc = &sds_ring->desc_head[consumer];
-		desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
-		consumer = get_next_index(consumer, sds_ring->num_desc);
-	}
-
-	sds_ring->consumer = consumer;
-	writel(consumer, sds_ring->crb_sts_consumer);
-}
-
-void
-qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2,
-			u8 alt_mac, u8 *mac)
-{
-	u32 mac_low, mac_high;
-	int i;
-
-	mac_low = off1;
-	mac_high = off2;
-
-	if (alt_mac) {
-		mac_low |= (mac_low >> 16) | (mac_high << 16);
-		mac_high >>= 16;
-	}
-
-	for (i = 0; i < 2; i++)
-		mac[i] = (u8)(mac_high >> ((1 - i) * 8));
-	for (i = 2; i < 6; i++)
-		mac[i] = (u8)(mac_low >> ((5 - i) * 8));
-}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
new file mode 100644
index 0000000..ba352c1
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -0,0 +1,1309 @@
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
+
+#include "qlcnic.h"
+
+#define QLCNIC_MAC_HASH(MAC)\
+	((((MAC) & 0x70000) >> 0x10) | (((MAC) & 0x70000000000ULL) >> 0x25))
+
+#define TX_ETHER_PKT	0x01
+#define TX_TCP_PKT	0x02
+#define TX_UDP_PKT	0x03
+#define TX_IP_PKT	0x04
+#define TX_TCP_LSO	0x05
+#define TX_TCP_LSO6	0x06
+#define TX_TCPV6_PKT	0x0b
+#define TX_UDPV6_PKT	0x0c
+#define FLAGS_VLAN_TAGGED	0x10
+#define FLAGS_VLAN_OOB		0x40
+
+#define qlcnic_set_tx_vlan_tci(cmd_desc, v)	\
+	(cmd_desc)->vlan_TCI = cpu_to_le16(v);
+#define qlcnic_set_cmd_desc_port(cmd_desc, var)	\
+	((cmd_desc)->port_ctxid |= ((var) & 0x0F))
+#define qlcnic_set_cmd_desc_ctxid(cmd_desc, var)	\
+	((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
+
+#define qlcnic_set_tx_port(_desc, _port) \
+	((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0))
+
+#define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \
+	((_desc)->flags_opcode |= \
+	cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7)))
+
+#define qlcnic_set_tx_frags_len(_desc, _frags, _len) \
+	((_desc)->nfrags__length = \
+	cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8)))
+
+/* owner bits of status_desc */
+#define STATUS_OWNER_HOST	(0x1ULL << 56)
+#define STATUS_OWNER_PHANTOM	(0x2ULL << 56)
+
+/* Status descriptor:
+   0-3 port, 4-7 status, 8-11 type, 12-27 total_length
+   28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
+   53-55 desc_cnt, 56-57 owner, 58-63 opcode
+ */
+#define qlcnic_get_sts_port(sts_data)	\
+	((sts_data) & 0x0F)
+#define qlcnic_get_sts_status(sts_data)	\
+	(((sts_data) >> 4) & 0x0F)
+#define qlcnic_get_sts_type(sts_data)	\
+	(((sts_data) >> 8) & 0x0F)
+#define qlcnic_get_sts_totallength(sts_data)	\
+	(((sts_data) >> 12) & 0xFFFF)
+#define qlcnic_get_sts_refhandle(sts_data)	\
+	(((sts_data) >> 28) & 0xFFFF)
+#define qlcnic_get_sts_prot(sts_data)	\
+	(((sts_data) >> 44) & 0x0F)
+#define qlcnic_get_sts_pkt_offset(sts_data)	\
+	(((sts_data) >> 48) & 0x1F)
+#define qlcnic_get_sts_desc_cnt(sts_data)	\
+	(((sts_data) >> 53) & 0x7)
+#define qlcnic_get_sts_opcode(sts_data)	\
+	(((sts_data) >> 58) & 0x03F)
+
+#define qlcnic_get_lro_sts_refhandle(sts_data) 	\
+	((sts_data) & 0x0FFFF)
+#define qlcnic_get_lro_sts_length(sts_data)	\
+	(((sts_data) >> 16) & 0x0FFFF)
+#define qlcnic_get_lro_sts_l2_hdr_offset(sts_data)	\
+	(((sts_data) >> 32) & 0x0FF)
+#define qlcnic_get_lro_sts_l4_hdr_offset(sts_data)	\
+	(((sts_data) >> 40) & 0x0FF)
+#define qlcnic_get_lro_sts_timestamp(sts_data)	\
+	(((sts_data) >> 48) & 0x1)
+#define qlcnic_get_lro_sts_type(sts_data)	\
+	(((sts_data) >> 49) & 0x7)
+#define qlcnic_get_lro_sts_push_flag(sts_data)		\
+	(((sts_data) >> 52) & 0x1)
+#define qlcnic_get_lro_sts_seq_number(sts_data)		\
+	((sts_data) & 0x0FFFFFFFF)
+#define qlcnic_get_lro_sts_mss(sts_data1)		\
+	((sts_data1 >> 32) & 0x0FFFF)
+
+/* opcode field in status_desc */
+#define QLCNIC_SYN_OFFLOAD	0x03
+#define QLCNIC_RXPKT_DESC  	0x04
+#define QLCNIC_OLD_RXPKT_DESC	0x3f
+#define QLCNIC_RESPONSE_DESC	0x05
+#define QLCNIC_LRO_DESC  	0x12
+
+/* for status field in status_desc */
+#define STATUS_CKSUM_LOOP	0
+#define STATUS_CKSUM_OK		2
+
+static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
+				 u64 uaddr, __le16 vlan_id,
+				 struct qlcnic_host_tx_ring *tx_ring)
+{
+	struct cmd_desc_type0 *hwdesc;
+	struct qlcnic_nic_req *req;
+	struct qlcnic_mac_req *mac_req;
+	struct qlcnic_vlan_req *vlan_req;
+	u32 producer;
+	u64 word;
+
+	producer = tx_ring->producer;
+	hwdesc = &tx_ring->desc_head[tx_ring->producer];
+
+	req = (struct qlcnic_nic_req *)hwdesc;
+	memset(req, 0, sizeof(struct qlcnic_nic_req));
+	req->qhdr = cpu_to_le64(QLCNIC_REQUEST << 23);
+
+	word = QLCNIC_MAC_EVENT | ((u64)(adapter->portnum) << 16);
+	req->req_hdr = cpu_to_le64(word);
+
+	mac_req = (struct qlcnic_mac_req *)&(req->words[0]);
+	mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
+	memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN);
+
+	vlan_req = (struct qlcnic_vlan_req *)&req->words[1];
+	vlan_req->vlan_id = vlan_id;
+
+	tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
+	smp_mb();
+}
+
+static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
+			       struct qlcnic_host_tx_ring *tx_ring,
+			       struct cmd_desc_type0 *first_desc,
+			       struct sk_buff *skb)
+{
+	struct ethhdr *phdr = (struct ethhdr *)(skb->data);
+	struct qlcnic_filter *fil, *tmp_fil;
+	struct hlist_node *tmp_hnode, *n;
+	struct hlist_head *head;
+	u64 src_addr = 0;
+	__le16 vlan_id = 0;
+	u8 hindex;
+
+	if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
+		return;
+
+	if (adapter->fhash.fnum >= adapter->fhash.fmax)
+		return;
+
+	/* Only NPAR capable devices support vlan based learning*/
+	if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
+		vlan_id = first_desc->vlan_TCI;
+	memcpy(&src_addr, phdr->h_source, ETH_ALEN);
+	hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1);
+	head = &(adapter->fhash.fhead[hindex]);
+
+	hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
+		if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) &&
+			    tmp_fil->vlan_id == vlan_id) {
+
+			if (jiffies > (QLCNIC_READD_AGE * HZ + tmp_fil->ftime))
+				qlcnic_change_filter(adapter, src_addr, vlan_id,
+						     tx_ring);
+			tmp_fil->ftime = jiffies;
+			return;
+		}
+	}
+
+	fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
+	if (!fil)
+		return;
+
+	qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring);
+
+	fil->ftime = jiffies;
+	fil->vlan_id = vlan_id;
+	memcpy(fil->faddr, &src_addr, ETH_ALEN);
+
+	spin_lock(&adapter->mac_learn_lock);
+
+	hlist_add_head(&(fil->fnode), head);
+	adapter->fhash.fnum++;
+
+	spin_unlock(&adapter->mac_learn_lock);
+}
+
+static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
+			 struct cmd_desc_type0 *first_desc, struct sk_buff *skb)
+{
+	u8 l4proto, opcode = 0, hdr_len = 0;
+	u16 flags = 0, vlan_tci = 0;
+	int copied, offset, copy_len, size;
+	struct cmd_desc_type0 *hwdesc;
+	struct vlan_ethhdr *vh;
+	struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
+	u16 protocol = ntohs(skb->protocol);
+	u32 producer = tx_ring->producer;
+
+	if (protocol == ETH_P_8021Q) {
+		vh = (struct vlan_ethhdr *)skb->data;
+		flags = FLAGS_VLAN_TAGGED;
+		vlan_tci = ntohs(vh->h_vlan_TCI);
+		protocol = ntohs(vh->h_vlan_encapsulated_proto);
+	} else if (vlan_tx_tag_present(skb)) {
+		flags = FLAGS_VLAN_OOB;
+		vlan_tci = vlan_tx_tag_get(skb);
+	}
+	if (unlikely(adapter->pvid)) {
+		if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
+			return -EIO;
+		if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED))
+			goto set_flags;
+
+		flags = FLAGS_VLAN_OOB;
+		vlan_tci = adapter->pvid;
+	}
+set_flags:
+	qlcnic_set_tx_vlan_tci(first_desc, vlan_tci);
+	qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
+
+	if (*(skb->data) & BIT_0) {
+		flags |= BIT_0;
+		memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN);
+	}
+	opcode = TX_ETHER_PKT;
+	if ((adapter->netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
+	    skb_shinfo(skb)->gso_size > 0) {
+		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+		first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
+		first_desc->total_hdr_length = hdr_len;
+		opcode = (protocol == ETH_P_IPV6) ? TX_TCP_LSO6 : TX_TCP_LSO;
+
+		/* For LSO, we need to copy the MAC/IP/TCP headers into
+		* the descriptor ring */
+		copied = 0;
+		offset = 2;
+
+		if (flags & FLAGS_VLAN_OOB) {
+			first_desc->total_hdr_length += VLAN_HLEN;
+			first_desc->tcp_hdr_offset = VLAN_HLEN;
+			first_desc->ip_hdr_offset = VLAN_HLEN;
+
+			/* Only in case of TSO on vlan device */
+			flags |= FLAGS_VLAN_TAGGED;
+
+			/* Create a TSO vlan header template for firmware */
+			hwdesc = &tx_ring->desc_head[producer];
+			tx_ring->cmd_buf_arr[producer].skb = NULL;
+
+			copy_len = min((int)sizeof(struct cmd_desc_type0) -
+				       offset, hdr_len + VLAN_HLEN);
+
+			vh = (struct vlan_ethhdr *)((char *) hwdesc + 2);
+			skb_copy_from_linear_data(skb, vh, 12);
+			vh->h_vlan_proto = htons(ETH_P_8021Q);
+			vh->h_vlan_TCI = htons(vlan_tci);
+
+			skb_copy_from_linear_data_offset(skb, 12,
+							 (char *)vh + 16,
+							 copy_len - 16);
+			copied = copy_len - VLAN_HLEN;
+			offset = 0;
+			producer = get_next_index(producer, tx_ring->num_desc);
+		}
+
+		while (copied < hdr_len) {
+			size = (int)sizeof(struct cmd_desc_type0) - offset;
+			copy_len = min(size, (hdr_len - copied));
+			hwdesc = &tx_ring->desc_head[producer];
+			tx_ring->cmd_buf_arr[producer].skb = NULL;
+			skb_copy_from_linear_data_offset(skb, copied,
+							 (char *)hwdesc +
+							 offset, copy_len);
+			copied += copy_len;
+			offset = 0;
+			producer = get_next_index(producer, tx_ring->num_desc);
+		}
+
+		tx_ring->producer = producer;
+		smp_mb();
+		adapter->stats.lso_frames++;
+
+	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		if (protocol == ETH_P_IP) {
+			l4proto = ip_hdr(skb)->protocol;
+
+			if (l4proto == IPPROTO_TCP)
+				opcode = TX_TCP_PKT;
+			else if (l4proto == IPPROTO_UDP)
+				opcode = TX_UDP_PKT;
+		} else if (protocol == ETH_P_IPV6) {
+			l4proto = ipv6_hdr(skb)->nexthdr;
+
+			if (l4proto == IPPROTO_TCP)
+				opcode = TX_TCPV6_PKT;
+			else if (l4proto == IPPROTO_UDP)
+				opcode = TX_UDPV6_PKT;
+		}
+	}
+	first_desc->tcp_hdr_offset += skb_transport_offset(skb);
+	first_desc->ip_hdr_offset += skb_network_offset(skb);
+	qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
+
+	return 0;
+}
+
+static int qlcnic_map_tx_skb(struct pci_dev *pdev, struct sk_buff *skb,
+			     struct qlcnic_cmd_buffer *pbuf)
+{
+	struct qlcnic_skb_frag *nf;
+	struct skb_frag_struct *frag;
+	int i, nr_frags;
+	dma_addr_t map;
+
+	nr_frags = skb_shinfo(skb)->nr_frags;
+	nf = &pbuf->frag_array[0];
+
+	map = pci_map_single(pdev, skb->data, skb_headlen(skb),
+			     PCI_DMA_TODEVICE);
+	if (pci_dma_mapping_error(pdev, map))
+		goto out_err;
+
+	nf->dma = map;
+	nf->length = skb_headlen(skb);
+
+	for (i = 0; i < nr_frags; i++) {
+		frag = &skb_shinfo(skb)->frags[i];
+		nf = &pbuf->frag_array[i+1];
+		map = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag),
+				       DMA_TO_DEVICE);
+		if (dma_mapping_error(&pdev->dev, map))
+			goto unwind;
+
+		nf->dma = map;
+		nf->length = skb_frag_size(frag);
+	}
+
+	return 0;
+
+unwind:
+	while (--i >= 0) {
+		nf = &pbuf->frag_array[i+1];
+		pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
+	}
+
+	nf = &pbuf->frag_array[0];
+	pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
+
+out_err:
+	return -ENOMEM;
+}
+
+static void qlcnic_unmap_buffers(struct pci_dev *pdev, struct sk_buff *skb,
+				 struct qlcnic_cmd_buffer *pbuf)
+{
+	struct qlcnic_skb_frag *nf = &pbuf->frag_array[0];
+	int i, nr_frags = skb_shinfo(skb)->nr_frags;
+
+	for (i = 0; i < nr_frags; i++) {
+		nf = &pbuf->frag_array[i+1];
+		pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
+	}
+
+	nf = &pbuf->frag_array[0];
+	pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
+	pbuf->skb = NULL;
+}
+
+static inline void qlcnic_clear_cmddesc(u64 *desc)
+{
+	desc[0] = 0ULL;
+	desc[2] = 0ULL;
+	desc[7] = 0ULL;
+}
+
+netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct qlcnic_adapter *adapter = netdev_priv(netdev);
+	struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
+	struct qlcnic_cmd_buffer *pbuf;
+	struct qlcnic_skb_frag *buffrag;
+	struct cmd_desc_type0 *hwdesc, *first_desc;
+	struct pci_dev *pdev;
+	struct ethhdr *phdr;
+	int i, k, frag_count, delta = 0;
+	u32 producer, num_txd;
+
+	num_txd = tx_ring->num_desc;
+
+	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
+		netif_stop_queue(netdev);
+		return NETDEV_TX_BUSY;
+	}
+
+	if (adapter->flags & QLCNIC_MACSPOOF) {
+		phdr = (struct ethhdr *)skb->data;
+		if (!ether_addr_equal(phdr->h_source, adapter->mac_addr))
+			goto drop_packet;
+	}
+
+	frag_count = skb_shinfo(skb)->nr_frags + 1;
+	/* 14 frags supported for normal packet and
+	 * 32 frags supported for TSO packet
+	 */
+	if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) {
+		for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++)
+			delta += skb_frag_size(&skb_shinfo(skb)->frags[i]);
+
+		if (!__pskb_pull_tail(skb, delta))
+			goto drop_packet;
+
+		frag_count = 1 + skb_shinfo(skb)->nr_frags;
+	}
+
+	if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) {
+		netif_stop_queue(netdev);
+		if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
+			netif_start_queue(netdev);
+		} else {
+			adapter->stats.xmit_off++;
+			return NETDEV_TX_BUSY;
+		}
+	}
+
+	producer = tx_ring->producer;
+	pbuf = &tx_ring->cmd_buf_arr[producer];
+	pdev = adapter->pdev;
+	first_desc = &tx_ring->desc_head[producer];
+	hwdesc = &tx_ring->desc_head[producer];
+	qlcnic_clear_cmddesc((u64 *)hwdesc);
+
+	if (qlcnic_map_tx_skb(pdev, skb, pbuf)) {
+		adapter->stats.tx_dma_map_error++;
+		goto drop_packet;
+	}
+
+	pbuf->skb = skb;
+	pbuf->frag_count = frag_count;
+
+	qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len);
+	qlcnic_set_tx_port(first_desc, adapter->portnum);
+
+	for (i = 0; i < frag_count; i++) {
+		k = i % 4;
+
+		if ((k == 0) && (i > 0)) {
+			/* move to next desc.*/
+			producer = get_next_index(producer, num_txd);
+			hwdesc = &tx_ring->desc_head[producer];
+			qlcnic_clear_cmddesc((u64 *)hwdesc);
+			tx_ring->cmd_buf_arr[producer].skb = NULL;
+		}
+
+		buffrag = &pbuf->frag_array[i];
+		hwdesc->buffer_length[k] = cpu_to_le16(buffrag->length);
+		switch (k) {
+		case 0:
+			hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
+			break;
+		case 1:
+			hwdesc->addr_buffer2 = cpu_to_le64(buffrag->dma);
+			break;
+		case 2:
+			hwdesc->addr_buffer3 = cpu_to_le64(buffrag->dma);
+			break;
+		case 3:
+			hwdesc->addr_buffer4 = cpu_to_le64(buffrag->dma);
+			break;
+		}
+	}
+
+	tx_ring->producer = get_next_index(producer, num_txd);
+	smp_mb();
+
+	if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb)))
+		goto unwind_buff;
+
+	if (adapter->mac_learn)
+		qlcnic_send_filter(adapter, tx_ring, first_desc, skb);
+
+	adapter->stats.txbytes += skb->len;
+	adapter->stats.xmitcalled++;
+
+	qlcnic_update_cmd_producer(tx_ring);
+
+	return NETDEV_TX_OK;
+
+unwind_buff:
+	qlcnic_unmap_buffers(pdev, skb, pbuf);
+drop_packet:
+	adapter->stats.txdropped++;
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+}
+
+void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	if (adapter->ahw->linkup && !linkup) {
+		netdev_info(netdev, "NIC Link is down\n");
+		adapter->ahw->linkup = 0;
+		if (netif_running(netdev)) {
+			netif_carrier_off(netdev);
+			netif_stop_queue(netdev);
+		}
+	} else if (!adapter->ahw->linkup && linkup) {
+		netdev_info(netdev, "NIC Link is up\n");
+		adapter->ahw->linkup = 1;
+		if (netif_running(netdev)) {
+			netif_carrier_on(netdev);
+			netif_wake_queue(netdev);
+		}
+	}
+}
+
+static int qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter,
+			       struct qlcnic_host_rds_ring *rds_ring,
+			       struct qlcnic_rx_buffer *buffer)
+{
+	struct sk_buff *skb;
+	dma_addr_t dma;
+	struct pci_dev *pdev = adapter->pdev;
+
+	skb = netdev_alloc_skb(adapter->netdev, rds_ring->skb_size);
+	if (!skb) {
+		adapter->stats.skb_alloc_failure++;
+		return -ENOMEM;
+	}
+
+	skb_reserve(skb, NET_IP_ALIGN);
+	dma = pci_map_single(pdev, skb->data, rds_ring->dma_size,
+			     PCI_DMA_FROMDEVICE);
+
+	if (pci_dma_mapping_error(pdev, dma)) {
+		adapter->stats.rx_dma_map_error++;
+		dev_kfree_skb_any(skb);
+		return -ENOMEM;
+	}
+
+	buffer->skb = skb;
+	buffer->dma = dma;
+
+	return 0;
+}
+
+static void qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
+					 struct qlcnic_host_rds_ring *rds_ring)
+{
+	struct rcv_desc *pdesc;
+	struct qlcnic_rx_buffer *buffer;
+	int  count = 0;
+	uint32_t producer;
+	struct list_head *head;
+
+	if (!spin_trylock(&rds_ring->lock))
+		return;
+
+	producer = rds_ring->producer;
+	head = &rds_ring->free_list;
+
+	while (!list_empty(head)) {
+		buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
+
+		if (!buffer->skb) {
+			if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
+				break;
+		}
+
+		count++;
+		list_del(&buffer->list);
+
+		/* make a rcv descriptor  */
+		pdesc = &rds_ring->desc_head[producer];
+		pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
+		pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
+		pdesc->addr_buffer = cpu_to_le64(buffer->dma);
+		producer = get_next_index(producer, rds_ring->num_desc);
+	}
+
+	if (count) {
+		rds_ring->producer = producer;
+		writel((producer - 1) & (rds_ring->num_desc - 1),
+		       rds_ring->crb_rcv_producer);
+	}
+
+	spin_unlock(&rds_ring->lock);
+}
+
+static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter)
+{
+	u32 sw_consumer, hw_consumer;
+	int i, done, count = 0;
+	struct qlcnic_cmd_buffer *buffer;
+	struct pci_dev *pdev = adapter->pdev;
+	struct net_device *netdev = adapter->netdev;
+	struct qlcnic_skb_frag *frag;
+	struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
+
+	if (!spin_trylock(&adapter->tx_clean_lock))
+		return 1;
+
+	sw_consumer = tx_ring->sw_consumer;
+	hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
+
+	while (sw_consumer != hw_consumer) {
+		buffer = &tx_ring->cmd_buf_arr[sw_consumer];
+		if (buffer->skb) {
+			frag = &buffer->frag_array[0];
+			pci_unmap_single(pdev, frag->dma, frag->length,
+					 PCI_DMA_TODEVICE);
+			frag->dma = 0ULL;
+			for (i = 1; i < buffer->frag_count; i++) {
+				frag++;
+				pci_unmap_page(pdev, frag->dma, frag->length,
+					       PCI_DMA_TODEVICE);
+				frag->dma = 0ULL;
+			}
+
+			adapter->stats.xmitfinished++;
+			dev_kfree_skb_any(buffer->skb);
+			buffer->skb = NULL;
+		}
+
+		sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc);
+		if (++count >= MAX_STATUS_HANDLE)
+			break;
+	}
+
+	if (count && netif_running(netdev)) {
+		tx_ring->sw_consumer = sw_consumer;
+
+		smp_mb();
+
+		if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
+			if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
+				netif_wake_queue(netdev);
+				adapter->stats.xmit_on++;
+			}
+		}
+		adapter->tx_timeo_cnt = 0;
+	}
+	/*
+	 * If everything is freed up to consumer then check if the ring is full
+	 * If the ring is full then check if more needs to be freed and
+	 * schedule the call back again.
+	 *
+	 * This happens when there are 2 CPUs. One could be freeing and the
+	 * other filling it. If the ring is full when we get out of here and
+	 * the card has already interrupted the host then the host can miss the
+	 * interrupt.
+	 *
+	 * There is still a possible race condition and the host could miss an
+	 * interrupt. The card has to take care of this.
+	 */
+	hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
+	done = (sw_consumer == hw_consumer);
+
+	spin_unlock(&adapter->tx_clean_lock);
+
+	return done;
+}
+
+static int qlcnic_poll(struct napi_struct *napi, int budget)
+{
+	struct qlcnic_host_sds_ring *sds_ring;
+	struct qlcnic_adapter *adapter;
+	int tx_complete, work_done;
+
+	sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
+	adapter = sds_ring->adapter;
+
+	tx_complete = qlcnic_process_cmd_ring(adapter);
+	work_done = qlcnic_process_rcv_ring(sds_ring, budget);
+
+	if ((work_done < budget) && tx_complete) {
+		napi_complete(&sds_ring->napi);
+		if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+			qlcnic_enable_int(sds_ring);
+	}
+
+	return work_done;
+}
+
+static int qlcnic_rx_poll(struct napi_struct *napi, int budget)
+{
+	struct qlcnic_host_sds_ring *sds_ring;
+	struct qlcnic_adapter *adapter;
+	int work_done;
+
+	sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
+	adapter = sds_ring->adapter;
+
+	work_done = qlcnic_process_rcv_ring(sds_ring, budget);
+
+	if (work_done < budget) {
+		napi_complete(&sds_ring->napi);
+		if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+			qlcnic_enable_int(sds_ring);
+	}
+
+	return work_done;
+}
+
+static void qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
+				    struct qlcnic_fw_msg *msg)
+{
+	u32 cable_OUI;
+	u16 cable_len, link_speed;
+	u8  link_status, module, duplex, autoneg, lb_status = 0;
+	struct net_device *netdev = adapter->netdev;
+
+	adapter->has_link_events = 1;
+
+	cable_OUI = msg->body[1] & 0xffffffff;
+	cable_len = (msg->body[1] >> 32) & 0xffff;
+	link_speed = (msg->body[1] >> 48) & 0xffff;
+
+	link_status = msg->body[2] & 0xff;
+	duplex = (msg->body[2] >> 16) & 0xff;
+	autoneg = (msg->body[2] >> 24) & 0xff;
+	lb_status = (msg->body[2] >> 32) & 0x3;
+
+	module = (msg->body[2] >> 8) & 0xff;
+	if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE)
+		dev_info(&netdev->dev,
+			 "unsupported cable: OUI 0x%x, length %d\n",
+			 cable_OUI, cable_len);
+	else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN)
+		dev_info(&netdev->dev, "unsupported cable length %d\n",
+			 cable_len);
+
+	if (!link_status && (lb_status == QLCNIC_ILB_MODE ||
+	    lb_status == QLCNIC_ELB_MODE))
+		adapter->ahw->loopback_state |= QLCNIC_LINKEVENT;
+
+	qlcnic_advert_link_change(adapter, link_status);
+
+	if (duplex == LINKEVENT_FULL_DUPLEX)
+		adapter->link_duplex = DUPLEX_FULL;
+	else
+		adapter->link_duplex = DUPLEX_HALF;
+
+	adapter->module_type = module;
+	adapter->link_autoneg = autoneg;
+
+	if (link_status) {
+		adapter->link_speed = link_speed;
+	} else {
+		adapter->link_speed = SPEED_UNKNOWN;
+		adapter->link_duplex = DUPLEX_UNKNOWN;
+	}
+}
+
+static void qlcnic_handle_fw_message(int desc_cnt, int index,
+				     struct qlcnic_host_sds_ring *sds_ring)
+{
+	struct qlcnic_fw_msg msg;
+	struct status_desc *desc;
+	struct qlcnic_adapter *adapter;
+	struct device *dev;
+	int i = 0, opcode, ret;
+
+	while (desc_cnt > 0 && i < 8) {
+		desc = &sds_ring->desc_head[index];
+		msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]);
+		msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]);
+
+		index = get_next_index(index, sds_ring->num_desc);
+		desc_cnt--;
+	}
+
+	adapter = sds_ring->adapter;
+	dev = &adapter->pdev->dev;
+	opcode = qlcnic_get_nic_msg_opcode(msg.body[0]);
+
+	switch (opcode) {
+	case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
+		qlcnic_handle_linkevent(adapter, &msg);
+		break;
+	case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK:
+		ret = (u32)(msg.body[1]);
+		switch (ret) {
+		case 0:
+			adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE;
+			break;
+		case 1:
+			dev_info(dev, "loopback already in progress\n");
+			adapter->diag_cnt = -QLCNIC_TEST_IN_PROGRESS;
+			break;
+		case 2:
+			dev_info(dev, "loopback cable is not connected\n");
+			adapter->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN;
+			break;
+		default:
+			dev_info(dev,
+				 "loopback configure request failed, err %x\n",
+				 ret);
+			adapter->diag_cnt = -QLCNIC_UNDEFINED_ERROR;
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static struct sk_buff *
+qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
+		     struct qlcnic_host_rds_ring *rds_ring, u16 index,
+		     u16 cksum)
+{
+	struct qlcnic_rx_buffer *buffer;
+	struct sk_buff *skb;
+
+	buffer = &rds_ring->rx_buf_arr[index];
+
+	if (unlikely(buffer->skb == NULL)) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size,
+			 PCI_DMA_FROMDEVICE);
+
+	skb = buffer->skb;
+
+	if (likely((adapter->netdev->features & NETIF_F_RXCSUM) &&
+		   (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) {
+		adapter->stats.csummed++;
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+	} else {
+		skb_checksum_none_assert(skb);
+	}
+
+	buffer->skb = NULL;
+
+	return skb;
+}
+
+static inline int qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter,
+					  struct sk_buff *skb, u16 *vlan_tag)
+{
+	struct ethhdr *eth_hdr;
+
+	if (!__vlan_get_tag(skb, vlan_tag)) {
+		eth_hdr = (struct ethhdr *)skb->data;
+		memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
+		skb_pull(skb, VLAN_HLEN);
+	}
+	if (!adapter->pvid)
+		return 0;
+
+	if (*vlan_tag == adapter->pvid) {
+		/* Outer vlan tag. Packet should follow non-vlan path */
+		*vlan_tag = 0xffff;
+		return 0;
+	}
+	if (adapter->flags & QLCNIC_TAGGING_ENABLED)
+		return 0;
+
+	return -EINVAL;
+}
+
+static struct qlcnic_rx_buffer *
+qlcnic_process_rcv(struct qlcnic_adapter *adapter,
+		   struct qlcnic_host_sds_ring *sds_ring, int ring,
+		   u64 sts_data0)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+	struct qlcnic_rx_buffer *buffer;
+	struct sk_buff *skb;
+	struct qlcnic_host_rds_ring *rds_ring;
+	int index, length, cksum, pkt_offset;
+	u16 vid = 0xffff;
+
+	if (unlikely(ring >= adapter->max_rds_rings))
+		return NULL;
+
+	rds_ring = &recv_ctx->rds_rings[ring];
+
+	index = qlcnic_get_sts_refhandle(sts_data0);
+	if (unlikely(index >= rds_ring->num_desc))
+		return NULL;
+
+	buffer = &rds_ring->rx_buf_arr[index];
+	length = qlcnic_get_sts_totallength(sts_data0);
+	cksum  = qlcnic_get_sts_status(sts_data0);
+	pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
+
+	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
+	if (!skb)
+		return buffer;
+
+	if (length > rds_ring->skb_size)
+		skb_put(skb, rds_ring->skb_size);
+	else
+		skb_put(skb, length);
+
+	if (pkt_offset)
+		skb_pull(skb, pkt_offset);
+
+	if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+		adapter->stats.rxdropped++;
+		dev_kfree_skb(skb);
+		return buffer;
+	}
+
+	skb->protocol = eth_type_trans(skb, netdev);
+
+	if (vid != 0xffff)
+		__vlan_hwaccel_put_tag(skb, vid);
+
+	napi_gro_receive(&sds_ring->napi, skb);
+
+	adapter->stats.rx_pkts++;
+	adapter->stats.rxbytes += length;
+
+	return buffer;
+}
+
+#define QLC_TCP_HDR_SIZE            20
+#define QLC_TCP_TS_OPTION_SIZE      12
+#define QLC_TCP_TS_HDR_SIZE         (QLC_TCP_HDR_SIZE + QLC_TCP_TS_OPTION_SIZE)
+
+static struct qlcnic_rx_buffer *
+qlcnic_process_lro(struct qlcnic_adapter *adapter,
+		   int ring, u64 sts_data0, u64 sts_data1)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+	struct qlcnic_rx_buffer *buffer;
+	struct sk_buff *skb;
+	struct qlcnic_host_rds_ring *rds_ring;
+	struct iphdr *iph;
+	struct tcphdr *th;
+	bool push, timestamp;
+	int index, l2_hdr_offset, l4_hdr_offset;
+	u16 lro_length, length, data_offset, vid = 0xffff;
+	u32 seq_number;
+
+	if (unlikely(ring > adapter->max_rds_rings))
+		return NULL;
+
+	rds_ring = &recv_ctx->rds_rings[ring];
+
+	index = qlcnic_get_lro_sts_refhandle(sts_data0);
+	if (unlikely(index > rds_ring->num_desc))
+		return NULL;
+
+	buffer = &rds_ring->rx_buf_arr[index];
+
+	timestamp = qlcnic_get_lro_sts_timestamp(sts_data0);
+	lro_length = qlcnic_get_lro_sts_length(sts_data0);
+	l2_hdr_offset = qlcnic_get_lro_sts_l2_hdr_offset(sts_data0);
+	l4_hdr_offset = qlcnic_get_lro_sts_l4_hdr_offset(sts_data0);
+	push = qlcnic_get_lro_sts_push_flag(sts_data0);
+	seq_number = qlcnic_get_lro_sts_seq_number(sts_data1);
+
+	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
+	if (!skb)
+		return buffer;
+
+	if (timestamp)
+		data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE;
+	else
+		data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE;
+
+	skb_put(skb, lro_length + data_offset);
+	skb_pull(skb, l2_hdr_offset);
+
+	if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+		adapter->stats.rxdropped++;
+		dev_kfree_skb(skb);
+		return buffer;
+	}
+
+	skb->protocol = eth_type_trans(skb, netdev);
+	iph = (struct iphdr *)skb->data;
+	th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
+	length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
+	iph->tot_len = htons(length);
+	iph->check = 0;
+	iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+	th->psh = push;
+	th->seq = htonl(seq_number);
+	length = skb->len;
+
+	if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
+		skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1);
+
+	if (vid != 0xffff)
+		__vlan_hwaccel_put_tag(skb, vid);
+	netif_receive_skb(skb);
+
+	adapter->stats.lro_pkts++;
+	adapter->stats.lrobytes += length;
+
+	return buffer;
+}
+
+int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max)
+{
+	struct qlcnic_host_rds_ring *rds_ring;
+	struct qlcnic_adapter *adapter = sds_ring->adapter;
+	struct list_head *cur;
+	struct status_desc *desc;
+	struct qlcnic_rx_buffer *rxbuf;
+	u64 sts_data0, sts_data1;
+	__le64 owner_phantom = cpu_to_le64(STATUS_OWNER_PHANTOM);
+	int opcode, ring, desc_cnt, count = 0;
+	u32 consumer = sds_ring->consumer;
+
+	while (count < max) {
+		desc = &sds_ring->desc_head[consumer];
+		sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
+
+		if (!(sts_data0 & STATUS_OWNER_HOST))
+			break;
+
+		desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
+		opcode = qlcnic_get_sts_opcode(sts_data0);
+
+		switch (opcode) {
+		case QLCNIC_RXPKT_DESC:
+		case QLCNIC_OLD_RXPKT_DESC:
+		case QLCNIC_SYN_OFFLOAD:
+			ring = qlcnic_get_sts_type(sts_data0);
+			rxbuf = qlcnic_process_rcv(adapter, sds_ring, ring,
+						   sts_data0);
+			break;
+		case QLCNIC_LRO_DESC:
+			ring = qlcnic_get_lro_sts_type(sts_data0);
+			sts_data1 = le64_to_cpu(desc->status_desc_data[1]);
+			rxbuf = qlcnic_process_lro(adapter, ring, sts_data0,
+						   sts_data1);
+			break;
+		case QLCNIC_RESPONSE_DESC:
+			qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
+		default:
+			goto skip;
+		}
+
+		WARN_ON(desc_cnt > 1);
+
+		if (likely(rxbuf))
+			list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
+		else
+			adapter->stats.null_rxbuf++;
+
+skip:
+		for (; desc_cnt > 0; desc_cnt--) {
+			desc = &sds_ring->desc_head[consumer];
+			desc->status_desc_data[0] = owner_phantom;
+			consumer = get_next_index(consumer, sds_ring->num_desc);
+		}
+		count++;
+	}
+
+	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+		rds_ring = &adapter->recv_ctx->rds_rings[ring];
+
+		if (!list_empty(&sds_ring->free_list[ring])) {
+			list_for_each(cur, &sds_ring->free_list[ring]) {
+				rxbuf = list_entry(cur, struct qlcnic_rx_buffer,
+						   list);
+				qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf);
+			}
+			spin_lock(&rds_ring->lock);
+			list_splice_tail_init(&sds_ring->free_list[ring],
+					      &rds_ring->free_list);
+			spin_unlock(&rds_ring->lock);
+		}
+
+		qlcnic_post_rx_buffers_nodb(adapter, rds_ring);
+	}
+
+	if (count) {
+		sds_ring->consumer = consumer;
+		writel(consumer, sds_ring->crb_sts_consumer);
+	}
+
+	return count;
+}
+
+void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
+			    struct qlcnic_host_rds_ring *rds_ring)
+{
+	struct rcv_desc *pdesc;
+	struct qlcnic_rx_buffer *buffer;
+	int count = 0;
+	u32 producer;
+	struct list_head *head;
+
+	producer = rds_ring->producer;
+	head = &rds_ring->free_list;
+
+	while (!list_empty(head)) {
+
+		buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
+
+		if (!buffer->skb) {
+			if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
+				break;
+		}
+
+		count++;
+		list_del(&buffer->list);
+
+		/* make a rcv descriptor  */
+		pdesc = &rds_ring->desc_head[producer];
+		pdesc->addr_buffer = cpu_to_le64(buffer->dma);
+		pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
+		pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
+		producer = get_next_index(producer, rds_ring->num_desc);
+	}
+
+	if (count) {
+		rds_ring->producer = producer;
+		writel((producer-1) & (rds_ring->num_desc-1),
+		       rds_ring->crb_rcv_producer);
+	}
+}
+
+static void dump_skb(struct sk_buff *skb, struct qlcnic_adapter *adapter)
+{
+	int i;
+	unsigned char *data = skb->data;
+
+	pr_info(KERN_INFO "\n");
+	for (i = 0; i < skb->len; i++) {
+		QLCDB(adapter, DRV, "%02x ", data[i]);
+		if ((i & 0x0f) == 8)
+			pr_info(KERN_INFO "\n");
+	}
+}
+
+static void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, int ring,
+				    u64 sts_data0)
+{
+	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+	struct sk_buff *skb;
+	struct qlcnic_host_rds_ring *rds_ring;
+	int index, length, cksum, pkt_offset;
+
+	if (unlikely(ring >= adapter->max_rds_rings))
+		return;
+
+	rds_ring = &recv_ctx->rds_rings[ring];
+
+	index = qlcnic_get_sts_refhandle(sts_data0);
+	length = qlcnic_get_sts_totallength(sts_data0);
+	if (unlikely(index >= rds_ring->num_desc))
+		return;
+
+	cksum  = qlcnic_get_sts_status(sts_data0);
+	pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
+
+	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
+	if (!skb)
+		return;
+
+	if (length > rds_ring->skb_size)
+		skb_put(skb, rds_ring->skb_size);
+	else
+		skb_put(skb, length);
+
+	if (pkt_offset)
+		skb_pull(skb, pkt_offset);
+
+	if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
+		adapter->diag_cnt++;
+	else
+		dump_skb(skb, adapter);
+
+	dev_kfree_skb_any(skb);
+	adapter->stats.rx_pkts++;
+	adapter->stats.rxbytes += length;
+
+	return;
+}
+
+void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
+{
+	struct qlcnic_adapter *adapter = sds_ring->adapter;
+	struct status_desc *desc;
+	u64 sts_data0;
+	int ring, opcode, desc_cnt;
+
+	u32 consumer = sds_ring->consumer;
+
+	desc = &sds_ring->desc_head[consumer];
+	sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
+
+	if (!(sts_data0 & STATUS_OWNER_HOST))
+		return;
+
+	desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
+	opcode = qlcnic_get_sts_opcode(sts_data0);
+	switch (opcode) {
+	case QLCNIC_RESPONSE_DESC:
+		qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
+		break;
+	default:
+		ring = qlcnic_get_sts_type(sts_data0);
+		qlcnic_process_rcv_diag(adapter, ring, sts_data0);
+		break;
+	}
+
+	for (; desc_cnt > 0; desc_cnt--) {
+		desc = &sds_ring->desc_head[consumer];
+		desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
+		consumer = get_next_index(consumer, sds_ring->num_desc);
+	}
+
+	sds_ring->consumer = consumer;
+	writel(consumer, sds_ring->crb_sts_consumer);
+}
+
+void qlcnic_fetch_mac(u32 off1, u32 off2, u8 alt_mac, u8 *mac)
+{
+	u32 mac_low, mac_high;
+	int i;
+
+	mac_low = off1;
+	mac_high = off2;
+
+	if (alt_mac) {
+		mac_low |= (mac_low >> 16) | (mac_high << 16);
+		mac_high >>= 16;
+	}
+
+	for (i = 0; i < 2; i++)
+		mac[i] = (u8)(mac_high >> ((1 - i) * 8));
+	for (i = 2; i < 6; i++)
+		mac[i] = (u8)(mac_low >> ((5 - i) * 8));
+}
+
+int qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev)
+{
+	int ring, max_sds_rings;
+	struct qlcnic_host_sds_ring *sds_ring;
+	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+	if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
+		return -ENOMEM;
+
+	max_sds_rings = adapter->max_sds_rings;
+
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
+
+		if (ring == max_sds_rings - 1)
+			netif_napi_add(netdev, &sds_ring->napi, qlcnic_poll,
+				       QLCNIC_NETDEV_WEIGHT / max_sds_rings);
+		else
+			netif_napi_add(netdev, &sds_ring->napi, qlcnic_rx_poll,
+				       QLCNIC_NETDEV_WEIGHT*2);
+	}
+
+	return 0;
+}
+
+void qlcnic_napi_del(struct qlcnic_adapter *adapter)
+{
+	int ring;
+	struct qlcnic_host_sds_ring *sds_ring;
+	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
+		netif_napi_del(&sds_ring->napi);
+	}
+
+	qlcnic_free_sds_rings(adapter->recv_ctx);
+}
+
+void qlcnic_napi_enable(struct qlcnic_adapter *adapter)
+{
+	int ring;
+	struct qlcnic_host_sds_ring *sds_ring;
+	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+		return;
+
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
+		napi_enable(&sds_ring->napi);
+		qlcnic_enable_int(sds_ring);
+	}
+}
+
+void qlcnic_napi_disable(struct qlcnic_adapter *adapter)
+{
+	int ring;
+	struct qlcnic_host_sds_ring *sds_ring;
+	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+		return;
+
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
+		qlcnic_disable_int(sds_ring);
+		napi_synchronize(&sds_ring->napi);
+		napi_disable(&sds_ring->napi);
+	}
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 24ad17e..1eef0bf 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -66,17 +66,10 @@ static void qlcnic_fw_poll_work(struct work_struct *work);
 static void qlcnic_schedule_work(struct qlcnic_adapter *adapter,
 		work_func_t func, int delay);
 static void qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter);
-static int qlcnic_poll(struct napi_struct *napi, int budget);
-static int qlcnic_rx_poll(struct napi_struct *napi, int budget);
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void qlcnic_poll_controller(struct net_device *netdev);
 #endif
 
-static void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter);
-static void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter);
-static void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter);
-static void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
-
 static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding);
 static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8);
 static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter);
@@ -92,8 +85,6 @@ static int qlcnic_start_firmware(struct qlcnic_adapter *);
 
 static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
 static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
-static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
-static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
 static int qlcnicvf_start_firmware(struct qlcnic_adapter *);
 static void qlcnic_set_netdev_features(struct qlcnic_adapter *,
 				struct qlcnic_esw_func_cfg *);
@@ -115,9 +106,7 @@ static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = {
 MODULE_DEVICE_TABLE(pci, qlcnic_pci_tbl);
 
 
-inline void
-qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
-		struct qlcnic_host_tx_ring *tx_ring)
+inline void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *tx_ring)
 {
 	writel(tx_ring->producer, tx_ring->crb_cmd_producer);
 }
@@ -132,23 +121,7 @@ static const u32 msi_tgt_status[8] = {
 static const
 struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG;
 
-static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring)
-{
-	writel(0, sds_ring->crb_intr_mask);
-}
-
-static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring)
-{
-	struct qlcnic_adapter *adapter = sds_ring->adapter;
-
-	writel(0x1, sds_ring->crb_intr_mask);
-
-	if (!QLCNIC_IS_MSI_FAMILY(adapter))
-		writel(0xfbff, adapter->tgt_mask_reg);
-}
-
-static int
-qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
+int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
 {
 	int size = sizeof(struct qlcnic_host_sds_ring) * count;
 
@@ -157,8 +130,7 @@ qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
 	return recv_ctx->sds_rings == NULL;
 }
 
-static void
-qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
+void qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
 {
 	if (recv_ctx->sds_rings != NULL)
 		kfree(recv_ctx->sds_rings);
@@ -166,80 +138,6 @@ qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
 	recv_ctx->sds_rings = NULL;
 }
 
-static int
-qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev)
-{
-	int ring;
-	struct qlcnic_host_sds_ring *sds_ring;
-	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
-	if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
-		return -ENOMEM;
-
-	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
-		sds_ring = &recv_ctx->sds_rings[ring];
-
-		if (ring == adapter->max_sds_rings - 1)
-			netif_napi_add(netdev, &sds_ring->napi, qlcnic_poll,
-				QLCNIC_NETDEV_WEIGHT/adapter->max_sds_rings);
-		else
-			netif_napi_add(netdev, &sds_ring->napi,
-				qlcnic_rx_poll, QLCNIC_NETDEV_WEIGHT*2);
-	}
-
-	return 0;
-}
-
-static void
-qlcnic_napi_del(struct qlcnic_adapter *adapter)
-{
-	int ring;
-	struct qlcnic_host_sds_ring *sds_ring;
-	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
-	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
-		sds_ring = &recv_ctx->sds_rings[ring];
-		netif_napi_del(&sds_ring->napi);
-	}
-
-	qlcnic_free_sds_rings(adapter->recv_ctx);
-}
-
-static void
-qlcnic_napi_enable(struct qlcnic_adapter *adapter)
-{
-	int ring;
-	struct qlcnic_host_sds_ring *sds_ring;
-	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
-	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
-		return;
-
-	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
-		sds_ring = &recv_ctx->sds_rings[ring];
-		napi_enable(&sds_ring->napi);
-		qlcnic_enable_int(sds_ring);
-	}
-}
-
-static void
-qlcnic_napi_disable(struct qlcnic_adapter *adapter)
-{
-	int ring;
-	struct qlcnic_host_sds_ring *sds_ring;
-	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
-	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
-		return;
-
-	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
-		sds_ring = &recv_ctx->sds_rings[ring];
-		qlcnic_disable_int(sds_ring);
-		napi_synchronize(&sds_ring->napi);
-		napi_disable(&sds_ring->napi);
-	}
-}
-
 static void qlcnic_clear_stats(struct qlcnic_adapter *adapter)
 {
 	memset(&adapter->stats, 0, sizeof(adapter->stats));
@@ -724,9 +622,8 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
 	return err;
 }
 
-static void
-qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
-		struct qlcnic_esw_func_cfg *esw_cfg)
+void qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
+			    struct qlcnic_esw_func_cfg *esw_cfg)
 {
 	if (esw_cfg->discard_tagged)
 		adapter->flags &= ~QLCNIC_TAGGING_ENABLED;
@@ -757,9 +654,8 @@ qlcnic_vlan_rx_del(struct net_device *netdev, u16 vid)
 	return 0;
 }
 
-static void
-qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
-		struct qlcnic_esw_func_cfg *esw_cfg)
+void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
+				      struct qlcnic_esw_func_cfg *esw_cfg)
 {
 	adapter->flags &= ~(QLCNIC_MACSPOOF | QLCNIC_MAC_OVERRIDE_DISABLED |
 				QLCNIC_PROMISC_DISABLED);
@@ -776,8 +672,7 @@ qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
 	qlcnic_set_netdev_features(adapter, esw_cfg);
 }
 
-static int
-qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
+static int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
 {
 	struct qlcnic_esw_func_cfg esw_cfg;
 
@@ -1485,8 +1380,8 @@ qlcnic_reset_context(struct qlcnic_adapter *adapter)
 }
 
 static int
-qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
-		struct net_device *netdev, u8 pci_using_dac)
+qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
+		    int pci_using_dac)
 {
 	int err;
 	struct pci_dev *pdev = adapter->pdev;
@@ -1506,7 +1401,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
 
 	if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO)
 		netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
-	if (pci_using_dac)
+	if (pci_using_dac == 1)
 		netdev->hw_features |= NETIF_F_HIGHDMA;
 
 	netdev->vlan_features = netdev->hw_features;
@@ -1530,7 +1425,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
 	return 0;
 }
 
-static int qlcnic_set_dma_mask(struct pci_dev *pdev, u8 *pci_using_dac)
+static int qlcnic_set_dma_mask(struct pci_dev *pdev, int *pci_using_dac)
 {
 	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
 			!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
@@ -1564,9 +1459,8 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct net_device *netdev = NULL;
 	struct qlcnic_adapter *adapter = NULL;
-	int err;
+	int err, pci_using_dac = -1;
 	uint8_t revision_id;
-	uint8_t pci_using_dac;
 	char brd_name[QLCNIC_MAX_BOARD_NAME_LEN];
 
 	err = pci_enable_device(pdev);
@@ -1927,428 +1821,6 @@ static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter)
 	adapter->fhash.fmax = 0;
 }
 
-static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
-		u64 uaddr, __le16 vlan_id, struct qlcnic_host_tx_ring *tx_ring)
-{
-	struct cmd_desc_type0 *hwdesc;
-	struct qlcnic_nic_req *req;
-	struct qlcnic_mac_req *mac_req;
-	struct qlcnic_vlan_req *vlan_req;
-	u32 producer;
-	u64 word;
-
-	producer = tx_ring->producer;
-	hwdesc = &tx_ring->desc_head[tx_ring->producer];
-
-	req = (struct qlcnic_nic_req *)hwdesc;
-	memset(req, 0, sizeof(struct qlcnic_nic_req));
-	req->qhdr = cpu_to_le64(QLCNIC_REQUEST << 23);
-
-	word = QLCNIC_MAC_EVENT | ((u64)(adapter->portnum) << 16);
-	req->req_hdr = cpu_to_le64(word);
-
-	mac_req = (struct qlcnic_mac_req *)&(req->words[0]);
-	mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
-	memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN);
-
-	vlan_req = (struct qlcnic_vlan_req *)&req->words[1];
-	vlan_req->vlan_id = vlan_id;
-
-	tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
-	smp_mb();
-}
-
-#define QLCNIC_MAC_HASH(MAC)\
-	((((MAC) & 0x70000) >> 0x10) | (((MAC) & 0x70000000000ULL) >> 0x25))
-
-static void
-qlcnic_send_filter(struct qlcnic_adapter *adapter,
-		struct qlcnic_host_tx_ring *tx_ring,
-		struct cmd_desc_type0 *first_desc,
-		struct sk_buff *skb)
-{
-	struct ethhdr *phdr = (struct ethhdr *)(skb->data);
-	struct qlcnic_filter *fil, *tmp_fil;
-	struct hlist_node *tmp_hnode, *n;
-	struct hlist_head *head;
-	u64 src_addr = 0;
-	__le16 vlan_id = 0;
-	u8 hindex;
-
-	if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
-		return;
-
-	if (adapter->fhash.fnum >= adapter->fhash.fmax)
-		return;
-
-	/* Only NPAR capable devices support vlan based learning*/
-	if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
-		vlan_id = first_desc->vlan_TCI;
-	memcpy(&src_addr, phdr->h_source, ETH_ALEN);
-	hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1);
-	head = &(adapter->fhash.fhead[hindex]);
-
-	hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
-		if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) &&
-			    tmp_fil->vlan_id == vlan_id) {
-
-			if (jiffies >
-			    (QLCNIC_READD_AGE * HZ + tmp_fil->ftime))
-				qlcnic_change_filter(adapter, src_addr, vlan_id,
-								tx_ring);
-			tmp_fil->ftime = jiffies;
-			return;
-		}
-	}
-
-	fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
-	if (!fil)
-		return;
-
-	qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring);
-
-	fil->ftime = jiffies;
-	fil->vlan_id = vlan_id;
-	memcpy(fil->faddr, &src_addr, ETH_ALEN);
-	spin_lock(&adapter->mac_learn_lock);
-	hlist_add_head(&(fil->fnode), head);
-	adapter->fhash.fnum++;
-	spin_unlock(&adapter->mac_learn_lock);
-}
-
-static int
-qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
-		struct cmd_desc_type0 *first_desc,
-		struct sk_buff *skb)
-{
-	u8 opcode = 0, hdr_len = 0;
-	u16 flags = 0, vlan_tci = 0;
-	int copied, offset, copy_len;
-	struct cmd_desc_type0 *hwdesc;
-	struct vlan_ethhdr *vh;
-	struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
-	u16 protocol = ntohs(skb->protocol);
-	u32 producer = tx_ring->producer;
-
-	if (protocol == ETH_P_8021Q) {
-		vh = (struct vlan_ethhdr *)skb->data;
-		flags = FLAGS_VLAN_TAGGED;
-		vlan_tci = vh->h_vlan_TCI;
-		protocol = ntohs(vh->h_vlan_encapsulated_proto);
-	} else if (vlan_tx_tag_present(skb)) {
-		flags = FLAGS_VLAN_OOB;
-		vlan_tci = vlan_tx_tag_get(skb);
-	}
-	if (unlikely(adapter->pvid)) {
-		if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
-			return -EIO;
-		if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED))
-			goto set_flags;
-
-		flags = FLAGS_VLAN_OOB;
-		vlan_tci = adapter->pvid;
-	}
-set_flags:
-	qlcnic_set_tx_vlan_tci(first_desc, vlan_tci);
-	qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
-
-	if (*(skb->data) & BIT_0) {
-		flags |= BIT_0;
-		memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN);
-	}
-	opcode = TX_ETHER_PKT;
-	if ((adapter->netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
-			skb_shinfo(skb)->gso_size > 0) {
-
-		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-
-		first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
-		first_desc->total_hdr_length = hdr_len;
-
-		opcode = (protocol == ETH_P_IPV6) ? TX_TCP_LSO6 : TX_TCP_LSO;
-
-		/* For LSO, we need to copy the MAC/IP/TCP headers into
-		* the descriptor ring */
-		copied = 0;
-		offset = 2;
-
-		if (flags & FLAGS_VLAN_OOB) {
-			first_desc->total_hdr_length += VLAN_HLEN;
-			first_desc->tcp_hdr_offset = VLAN_HLEN;
-			first_desc->ip_hdr_offset = VLAN_HLEN;
-			/* Only in case of TSO on vlan device */
-			flags |= FLAGS_VLAN_TAGGED;
-
-			/* Create a TSO vlan header template for firmware */
-
-			hwdesc = &tx_ring->desc_head[producer];
-			tx_ring->cmd_buf_arr[producer].skb = NULL;
-
-			copy_len = min((int)sizeof(struct cmd_desc_type0) -
-				offset, hdr_len + VLAN_HLEN);
-
-			vh = (struct vlan_ethhdr *)((char *) hwdesc + 2);
-			skb_copy_from_linear_data(skb, vh, 12);
-			vh->h_vlan_proto = htons(ETH_P_8021Q);
-			vh->h_vlan_TCI = htons(vlan_tci);
-
-			skb_copy_from_linear_data_offset(skb, 12,
-				(char *)vh + 16, copy_len - 16);
-
-			copied = copy_len - VLAN_HLEN;
-			offset = 0;
-
-			producer = get_next_index(producer, tx_ring->num_desc);
-		}
-
-		while (copied < hdr_len) {
-
-			copy_len = min((int)sizeof(struct cmd_desc_type0) -
-				offset, (hdr_len - copied));
-
-			hwdesc = &tx_ring->desc_head[producer];
-			tx_ring->cmd_buf_arr[producer].skb = NULL;
-
-			skb_copy_from_linear_data_offset(skb, copied,
-				 (char *) hwdesc + offset, copy_len);
-
-			copied += copy_len;
-			offset = 0;
-
-			producer = get_next_index(producer, tx_ring->num_desc);
-		}
-
-		tx_ring->producer = producer;
-		smp_mb();
-		adapter->stats.lso_frames++;
-
-	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		u8 l4proto;
-
-		if (protocol == ETH_P_IP) {
-			l4proto = ip_hdr(skb)->protocol;
-
-			if (l4proto == IPPROTO_TCP)
-				opcode = TX_TCP_PKT;
-			else if (l4proto == IPPROTO_UDP)
-				opcode = TX_UDP_PKT;
-		} else if (protocol == ETH_P_IPV6) {
-			l4proto = ipv6_hdr(skb)->nexthdr;
-
-			if (l4proto == IPPROTO_TCP)
-				opcode = TX_TCPV6_PKT;
-			else if (l4proto == IPPROTO_UDP)
-				opcode = TX_UDPV6_PKT;
-		}
-	}
-	first_desc->tcp_hdr_offset += skb_transport_offset(skb);
-	first_desc->ip_hdr_offset += skb_network_offset(skb);
-	qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
-
-	return 0;
-}
-
-static int
-qlcnic_map_tx_skb(struct pci_dev *pdev,
-		struct sk_buff *skb, struct qlcnic_cmd_buffer *pbuf)
-{
-	struct qlcnic_skb_frag *nf;
-	struct skb_frag_struct *frag;
-	int i, nr_frags;
-	dma_addr_t map;
-
-	nr_frags = skb_shinfo(skb)->nr_frags;
-	nf = &pbuf->frag_array[0];
-
-	map = pci_map_single(pdev, skb->data,
-			skb_headlen(skb), PCI_DMA_TODEVICE);
-	if (pci_dma_mapping_error(pdev, map))
-		goto out_err;
-
-	nf->dma = map;
-	nf->length = skb_headlen(skb);
-
-	for (i = 0; i < nr_frags; i++) {
-		frag = &skb_shinfo(skb)->frags[i];
-		nf = &pbuf->frag_array[i+1];
-
-		map = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag),
-				       DMA_TO_DEVICE);
-		if (dma_mapping_error(&pdev->dev, map))
-			goto unwind;
-
-		nf->dma = map;
-		nf->length = skb_frag_size(frag);
-	}
-
-	return 0;
-
-unwind:
-	while (--i >= 0) {
-		nf = &pbuf->frag_array[i+1];
-		pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
-	}
-
-	nf = &pbuf->frag_array[0];
-	pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
-
-out_err:
-	return -ENOMEM;
-}
-
-static void
-qlcnic_unmap_buffers(struct pci_dev *pdev, struct sk_buff *skb,
-			struct qlcnic_cmd_buffer *pbuf)
-{
-	struct qlcnic_skb_frag *nf = &pbuf->frag_array[0];
-	int nr_frags = skb_shinfo(skb)->nr_frags;
-	int i;
-
-	for (i = 0; i < nr_frags; i++) {
-		nf = &pbuf->frag_array[i+1];
-		pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
-	}
-
-	nf = &pbuf->frag_array[0];
-	pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
-	pbuf->skb = NULL;
-}
-
-static inline void
-qlcnic_clear_cmddesc(u64 *desc)
-{
-	desc[0] = 0ULL;
-	desc[2] = 0ULL;
-	desc[7] = 0ULL;
-}
-
-netdev_tx_t
-qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
-{
-	struct qlcnic_adapter *adapter = netdev_priv(netdev);
-	struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
-	struct qlcnic_cmd_buffer *pbuf;
-	struct qlcnic_skb_frag *buffrag;
-	struct cmd_desc_type0 *hwdesc, *first_desc;
-	struct pci_dev *pdev;
-	struct ethhdr *phdr;
-	int delta = 0;
-	int i, k;
-
-	u32 producer;
-	int frag_count;
-	u32 num_txd = tx_ring->num_desc;
-
-	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
-		netif_stop_queue(netdev);
-		return NETDEV_TX_BUSY;
-	}
-
-	if (adapter->flags & QLCNIC_MACSPOOF) {
-		phdr = (struct ethhdr *)skb->data;
-		if (!ether_addr_equal(phdr->h_source, adapter->mac_addr))
-			goto drop_packet;
-	}
-
-	frag_count = skb_shinfo(skb)->nr_frags + 1;
-	/* 14 frags supported for normal packet and
-	 * 32 frags supported for TSO packet
-	 */
-	if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) {
-
-		for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++)
-			delta += skb_frag_size(&skb_shinfo(skb)->frags[i]);
-
-		if (!__pskb_pull_tail(skb, delta))
-			goto drop_packet;
-
-		frag_count = 1 + skb_shinfo(skb)->nr_frags;
-	}
-
-	if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) {
-		netif_stop_queue(netdev);
-		if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH)
-			netif_start_queue(netdev);
-		else {
-			adapter->stats.xmit_off++;
-			return NETDEV_TX_BUSY;
-		}
-	}
-
-	producer = tx_ring->producer;
-	pbuf = &tx_ring->cmd_buf_arr[producer];
-
-	pdev = adapter->pdev;
-
-	first_desc = hwdesc = &tx_ring->desc_head[producer];
-	qlcnic_clear_cmddesc((u64 *)hwdesc);
-
-	if (qlcnic_map_tx_skb(pdev, skb, pbuf)) {
-		adapter->stats.tx_dma_map_error++;
-		goto drop_packet;
-	}
-
-	pbuf->skb = skb;
-	pbuf->frag_count = frag_count;
-
-	qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len);
-	qlcnic_set_tx_port(first_desc, adapter->portnum);
-
-	for (i = 0; i < frag_count; i++) {
-
-		k = i % 4;
-
-		if ((k == 0) && (i > 0)) {
-			/* move to next desc.*/
-			producer = get_next_index(producer, num_txd);
-			hwdesc = &tx_ring->desc_head[producer];
-			qlcnic_clear_cmddesc((u64 *)hwdesc);
-			tx_ring->cmd_buf_arr[producer].skb = NULL;
-		}
-
-		buffrag = &pbuf->frag_array[i];
-
-		hwdesc->buffer_length[k] = cpu_to_le16(buffrag->length);
-		switch (k) {
-		case 0:
-			hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
-			break;
-		case 1:
-			hwdesc->addr_buffer2 = cpu_to_le64(buffrag->dma);
-			break;
-		case 2:
-			hwdesc->addr_buffer3 = cpu_to_le64(buffrag->dma);
-			break;
-		case 3:
-			hwdesc->addr_buffer4 = cpu_to_le64(buffrag->dma);
-			break;
-		}
-	}
-
-	tx_ring->producer = get_next_index(producer, num_txd);
-	smp_mb();
-
-	if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb)))
-		goto unwind_buff;
-
-	if (adapter->mac_learn)
-		qlcnic_send_filter(adapter, tx_ring, first_desc, skb);
-
-	adapter->stats.txbytes += skb->len;
-	adapter->stats.xmitcalled++;
-
-	qlcnic_update_cmd_producer(adapter, tx_ring);
-
-	return NETDEV_TX_OK;
-
-unwind_buff:
-	qlcnic_unmap_buffers(pdev, skb, pbuf);
-drop_packet:
-	adapter->stats.txdropped++;
-	dev_kfree_skb_any(skb);
-	return NETDEV_TX_OK;
-}
-
 static int qlcnic_check_temp(struct qlcnic_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
@@ -2385,27 +1857,6 @@ static int qlcnic_check_temp(struct qlcnic_adapter *adapter)
 	return rv;
 }
 
-void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
-{
-	struct net_device *netdev = adapter->netdev;
-
-	if (adapter->ahw->linkup && !linkup) {
-		netdev_info(netdev, "NIC Link is down\n");
-		adapter->ahw->linkup = 0;
-		if (netif_running(netdev)) {
-			netif_carrier_off(netdev);
-			netif_stop_queue(netdev);
-		}
-	} else if (!adapter->ahw->linkup && linkup) {
-		netdev_info(netdev, "NIC Link is up\n");
-		adapter->ahw->linkup = 1;
-		if (netif_running(netdev)) {
-			netif_carrier_on(netdev);
-			netif_wake_queue(netdev);
-		}
-	}
-}
-
 static void qlcnic_tx_timeout(struct net_device *netdev)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
@@ -2512,143 +1963,27 @@ static irqreturn_t qlcnic_msix_intr(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter)
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void qlcnic_poll_controller(struct net_device *netdev)
 {
-	u32 sw_consumer, hw_consumer;
-	int count = 0, i;
-	struct qlcnic_cmd_buffer *buffer;
-	struct pci_dev *pdev = adapter->pdev;
-	struct net_device *netdev = adapter->netdev;
-	struct qlcnic_skb_frag *frag;
-	int done;
-	struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
-
-	if (!spin_trylock(&adapter->tx_clean_lock))
-		return 1;
-
-	sw_consumer = tx_ring->sw_consumer;
-	hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
-
-	while (sw_consumer != hw_consumer) {
-		buffer = &tx_ring->cmd_buf_arr[sw_consumer];
-		if (buffer->skb) {
-			frag = &buffer->frag_array[0];
-			pci_unmap_single(pdev, frag->dma, frag->length,
-					 PCI_DMA_TODEVICE);
-			frag->dma = 0ULL;
-			for (i = 1; i < buffer->frag_count; i++) {
-				frag++;
-				pci_unmap_page(pdev, frag->dma, frag->length,
-					       PCI_DMA_TODEVICE);
-				frag->dma = 0ULL;
-			}
-
-			adapter->stats.xmitfinished++;
-			dev_kfree_skb_any(buffer->skb);
-			buffer->skb = NULL;
-		}
-
-		sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc);
-		if (++count >= MAX_STATUS_HANDLE)
-			break;
-	}
-
-	if (count && netif_running(netdev)) {
-		tx_ring->sw_consumer = sw_consumer;
-
-		smp_mb();
+	int ring;
+	struct qlcnic_host_sds_ring *sds_ring;
+	struct qlcnic_adapter *adapter = netdev_priv(netdev);
+	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
 
-		if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
-			if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
-				netif_wake_queue(netdev);
-				adapter->stats.xmit_on++;
-			}
-		}
-		adapter->tx_timeo_cnt = 0;
+	disable_irq(adapter->irq);
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
+		qlcnic_intr(adapter->irq, sds_ring);
 	}
-	/*
-	 * If everything is freed up to consumer then check if the ring is full
-	 * If the ring is full then check if more needs to be freed and
-	 * schedule the call back again.
-	 *
-	 * This happens when there are 2 CPUs. One could be freeing and the
-	 * other filling it. If the ring is full when we get out of here and
-	 * the card has already interrupted the host then the host can miss the
-	 * interrupt.
-	 *
-	 * There is still a possible race condition and the host could miss an
-	 * interrupt. The card has to take care of this.
-	 */
-	hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
-	done = (sw_consumer == hw_consumer);
-	spin_unlock(&adapter->tx_clean_lock);
-
-	return done;
+	enable_irq(adapter->irq);
 }
+#endif
 
-static int qlcnic_poll(struct napi_struct *napi, int budget)
+static void
+qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding)
 {
-	struct qlcnic_host_sds_ring *sds_ring =
-		container_of(napi, struct qlcnic_host_sds_ring, napi);
-
-	struct qlcnic_adapter *adapter = sds_ring->adapter;
-
-	int tx_complete;
-	int work_done;
-
-	tx_complete = qlcnic_process_cmd_ring(adapter);
-
-	work_done = qlcnic_process_rcv_ring(sds_ring, budget);
-
-	if ((work_done < budget) && tx_complete) {
-		napi_complete(&sds_ring->napi);
-		if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
-			qlcnic_enable_int(sds_ring);
-	}
-
-	return work_done;
-}
-
-static int qlcnic_rx_poll(struct napi_struct *napi, int budget)
-{
-	struct qlcnic_host_sds_ring *sds_ring =
-		container_of(napi, struct qlcnic_host_sds_ring, napi);
-
-	struct qlcnic_adapter *adapter = sds_ring->adapter;
-	int work_done;
-
-	work_done = qlcnic_process_rcv_ring(sds_ring, budget);
-
-	if (work_done < budget) {
-		napi_complete(&sds_ring->napi);
-		if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
-			qlcnic_enable_int(sds_ring);
-	}
-
-	return work_done;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void qlcnic_poll_controller(struct net_device *netdev)
-{
-	int ring;
-	struct qlcnic_host_sds_ring *sds_ring;
-	struct qlcnic_adapter *adapter = netdev_priv(netdev);
-	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
-	disable_irq(adapter->irq);
-	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
-		sds_ring = &recv_ctx->sds_rings[ring];
-		qlcnic_intr(adapter->irq, sds_ring);
-	}
-	enable_irq(adapter->irq);
-}
-#endif
-
-static void
-qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding)
-{
-	u32 val;
+	u32 val;
 
 	val = adapter->portnum & 0xf;
 	val |= encoding << 7;
@@ -3395,93 +2730,6 @@ qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
 	return err;
 }
 
-static int
-qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
-{
-	return -EOPNOTSUPP;
-}
-
-static int
-qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
-{
-	return -EOPNOTSUPP;
-}
-
-static ssize_t
-qlcnic_store_bridged_mode(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t len)
-{
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	unsigned long new;
-	int ret = -EINVAL;
-
-	if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG))
-		goto err_out;
-
-	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
-		goto err_out;
-
-	if (strict_strtoul(buf, 2, &new))
-		goto err_out;
-
-	if (!adapter->nic_ops->config_bridged_mode(adapter, !!new))
-		ret = len;
-
-err_out:
-	return ret;
-}
-
-static ssize_t
-qlcnic_show_bridged_mode(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	int bridged_mode = 0;
-
-	if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
-		bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED);
-
-	return sprintf(buf, "%d\n", bridged_mode);
-}
-
-static struct device_attribute dev_attr_bridged_mode = {
-       .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)},
-       .show = qlcnic_show_bridged_mode,
-       .store = qlcnic_store_bridged_mode,
-};
-
-static ssize_t
-qlcnic_store_diag_mode(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t len)
-{
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	unsigned long new;
-
-	if (strict_strtoul(buf, 2, &new))
-		return -EINVAL;
-
-	if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED))
-		adapter->flags ^= QLCNIC_DIAG_ENABLED;
-
-	return len;
-}
-
-static ssize_t
-qlcnic_show_diag_mode(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-
-	return sprintf(buf, "%d\n",
-			!!(adapter->flags & QLCNIC_DIAG_ENABLED));
-}
-
-static struct device_attribute dev_attr_diag_mode = {
-	.attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)},
-	.show = qlcnic_show_diag_mode,
-	.store = qlcnic_store_diag_mode,
-};
-
 int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val)
 {
 	if (!use_msi_x && !use_msi) {
@@ -3532,859 +2780,6 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data)
 	return err;
 }
 
-static int
-qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon, u8 *state,
-			u8 *rate)
-{
-	*rate = LSB(beacon);
-	*state = MSB(beacon);
-
-	QLCDB(adapter, DRV, "rate %x state %x\n", *rate, *state);
-
-	if (!*state) {
-		*rate = __QLCNIC_MAX_LED_RATE;
-		return 0;
-	} else if (*state > __QLCNIC_MAX_LED_STATE)
-		return -EINVAL;
-
-	if ((!*rate) || (*rate > __QLCNIC_MAX_LED_RATE))
-		return -EINVAL;
-
-	return 0;
-}
-
-static ssize_t
-qlcnic_store_beacon(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t len)
-{
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	int max_sds_rings = adapter->max_sds_rings;
-	u16 beacon;
-	u8 b_state, b_rate;
-	int err;
-
-	if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
-		dev_warn(dev, "LED test not supported for non "
-				"privilege function\n");
-		return -EOPNOTSUPP;
-	}
-
-	if (len != sizeof(u16))
-		return QL_STATUS_INVALID_PARAM;
-
-	memcpy(&beacon, buf, sizeof(u16));
-	err = qlcnic_validate_beacon(adapter, beacon, &b_state, &b_rate);
-	if (err)
-		return err;
-
-	if (adapter->ahw->beacon_state == b_state)
-		return len;
-
-	rtnl_lock();
-
-	if (!adapter->ahw->beacon_state)
-		if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
-			rtnl_unlock();
-			return -EBUSY;
-		}
-
-	if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
-		err = -EIO;
-		goto out;
-	}
-
-	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
-		err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST);
-		if (err)
-			goto out;
-		set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
-	}
-
-	err = qlcnic_config_led(adapter, b_state, b_rate);
-
-	if (!err) {
-		err = len;
-		adapter->ahw->beacon_state = b_state;
-	}
-
-	if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
-		qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
-
- out:
-	if (!adapter->ahw->beacon_state)
-		clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
-	rtnl_unlock();
-
-	return err;
-}
-
-static ssize_t
-qlcnic_show_beacon(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-
-	return sprintf(buf, "%d\n", adapter->ahw->beacon_state);
-}
-
-static struct device_attribute dev_attr_beacon = {
-	.attr = {.name = "beacon", .mode = (S_IRUGO | S_IWUSR)},
-	.show = qlcnic_show_beacon,
-	.store = qlcnic_store_beacon,
-};
-
-static int
-qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter,
-		loff_t offset, size_t size)
-{
-	size_t crb_size = 4;
-
-	if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
-		return -EIO;
-
-	if (offset < QLCNIC_PCI_CRBSPACE) {
-		if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM,
-					QLCNIC_PCI_CAMQM_END))
-			crb_size = 8;
-		else
-			return -EINVAL;
-	}
-
-	if ((size != crb_size) || (offset & (crb_size-1)))
-		return  -EINVAL;
-
-	return 0;
-}
-
-static ssize_t
-qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
-		struct bin_attribute *attr,
-		char *buf, loff_t offset, size_t size)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	u32 data;
-	u64 qmdata;
-	int ret;
-
-	ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
-	if (ret != 0)
-		return ret;
-
-	if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
-		qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata);
-		memcpy(buf, &qmdata, size);
-	} else {
-		data = QLCRD32(adapter, offset);
-		memcpy(buf, &data, size);
-	}
-	return size;
-}
-
-static ssize_t
-qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
-		struct bin_attribute *attr,
-		char *buf, loff_t offset, size_t size)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	u32 data;
-	u64 qmdata;
-	int ret;
-
-	ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
-	if (ret != 0)
-		return ret;
-
-	if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
-		memcpy(&qmdata, buf, size);
-		qlcnic_pci_camqm_write_2M(adapter, offset, qmdata);
-	} else {
-		memcpy(&data, buf, size);
-		QLCWR32(adapter, offset, data);
-	}
-	return size;
-}
-
-static int
-qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter,
-		loff_t offset, size_t size)
-{
-	if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
-		return -EIO;
-
-	if ((size != 8) || (offset & 0x7))
-		return  -EIO;
-
-	return 0;
-}
-
-static ssize_t
-qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
-		struct bin_attribute *attr,
-		char *buf, loff_t offset, size_t size)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	u64 data;
-	int ret;
-
-	ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
-	if (ret != 0)
-		return ret;
-
-	if (qlcnic_pci_mem_read_2M(adapter, offset, &data))
-		return -EIO;
-
-	memcpy(buf, &data, size);
-
-	return size;
-}
-
-static ssize_t
-qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
-		struct bin_attribute *attr,
-		char *buf, loff_t offset, size_t size)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	u64 data;
-	int ret;
-
-	ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
-	if (ret != 0)
-		return ret;
-
-	memcpy(&data, buf, size);
-
-	if (qlcnic_pci_mem_write_2M(adapter, offset, data))
-		return -EIO;
-
-	return size;
-}
-
-static struct bin_attribute bin_attr_crb = {
-	.attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)},
-	.size = 0,
-	.read = qlcnic_sysfs_read_crb,
-	.write = qlcnic_sysfs_write_crb,
-};
-
-static struct bin_attribute bin_attr_mem = {
-	.attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)},
-	.size = 0,
-	.read = qlcnic_sysfs_read_mem,
-	.write = qlcnic_sysfs_write_mem,
-};
-
-static int
-validate_pm_config(struct qlcnic_adapter *adapter,
-			struct qlcnic_pm_func_cfg *pm_cfg, int count)
-{
-
-	u8 src_pci_func, s_esw_id, d_esw_id;
-	u8 dest_pci_func;
-	int i;
-
-	for (i = 0; i < count; i++) {
-		src_pci_func = pm_cfg[i].pci_func;
-		dest_pci_func = pm_cfg[i].dest_npar;
-		if (src_pci_func >= QLCNIC_MAX_PCI_FUNC
-				|| dest_pci_func >= QLCNIC_MAX_PCI_FUNC)
-			return QL_STATUS_INVALID_PARAM;
-
-		if (adapter->npars[src_pci_func].type != QLCNIC_TYPE_NIC)
-			return QL_STATUS_INVALID_PARAM;
-
-		if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC)
-			return QL_STATUS_INVALID_PARAM;
-
-		s_esw_id = adapter->npars[src_pci_func].phy_port;
-		d_esw_id = adapter->npars[dest_pci_func].phy_port;
-
-		if (s_esw_id != d_esw_id)
-			return QL_STATUS_INVALID_PARAM;
-
-	}
-	return 0;
-
-}
-
-static ssize_t
-qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj,
-	struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	struct qlcnic_pm_func_cfg *pm_cfg;
-	u32 id, action, pci_func;
-	int count, rem, i, ret;
-
-	count	= size / sizeof(struct qlcnic_pm_func_cfg);
-	rem	= size % sizeof(struct qlcnic_pm_func_cfg);
-	if (rem)
-		return QL_STATUS_INVALID_PARAM;
-
-	pm_cfg = (struct qlcnic_pm_func_cfg *) buf;
-
-	ret = validate_pm_config(adapter, pm_cfg, count);
-	if (ret)
-		return ret;
-	for (i = 0; i < count; i++) {
-		pci_func = pm_cfg[i].pci_func;
-		action = !!pm_cfg[i].action;
-		id = adapter->npars[pci_func].phy_port;
-		ret = qlcnic_config_port_mirroring(adapter, id,
-						action, pci_func);
-		if (ret)
-			return ret;
-	}
-
-	for (i = 0; i < count; i++) {
-		pci_func = pm_cfg[i].pci_func;
-		id = adapter->npars[pci_func].phy_port;
-		adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action;
-		adapter->npars[pci_func].dest_npar = id;
-	}
-	return size;
-}
-
-static ssize_t
-qlcnic_sysfs_read_pm_config(struct file *filp, struct kobject *kobj,
-	struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC];
-	int i;
-
-	if (size != sizeof(pm_cfg))
-		return QL_STATUS_INVALID_PARAM;
-
-	for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
-		if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
-			continue;
-		pm_cfg[i].action = adapter->npars[i].enable_pm;
-		pm_cfg[i].dest_npar = 0;
-		pm_cfg[i].pci_func = i;
-	}
-	memcpy(buf, &pm_cfg, size);
-
-	return size;
-}
-
-static int
-validate_esw_config(struct qlcnic_adapter *adapter,
-	struct qlcnic_esw_func_cfg *esw_cfg, int count)
-{
-	u32 op_mode;
-	u8 pci_func;
-	int i;
-
-	op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE);
-
-	for (i = 0; i < count; i++) {
-		pci_func = esw_cfg[i].pci_func;
-		if (pci_func >= QLCNIC_MAX_PCI_FUNC)
-			return QL_STATUS_INVALID_PARAM;
-
-		if (adapter->op_mode == QLCNIC_MGMT_FUNC)
-			if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
-				return QL_STATUS_INVALID_PARAM;
-
-		switch (esw_cfg[i].op_mode) {
-		case QLCNIC_PORT_DEFAULTS:
-			if (QLC_DEV_GET_DRV(op_mode, pci_func) !=
-						QLCNIC_NON_PRIV_FUNC) {
-				if (esw_cfg[i].mac_anti_spoof != 0)
-					return QL_STATUS_INVALID_PARAM;
-				if (esw_cfg[i].mac_override != 1)
-					return QL_STATUS_INVALID_PARAM;
-				if (esw_cfg[i].promisc_mode != 1)
-					return QL_STATUS_INVALID_PARAM;
-			}
-			break;
-		case QLCNIC_ADD_VLAN:
-			if (!IS_VALID_VLAN(esw_cfg[i].vlan_id))
-				return QL_STATUS_INVALID_PARAM;
-			if (!esw_cfg[i].op_type)
-				return QL_STATUS_INVALID_PARAM;
-			break;
-		case QLCNIC_DEL_VLAN:
-			if (!esw_cfg[i].op_type)
-				return QL_STATUS_INVALID_PARAM;
-			break;
-		default:
-			return QL_STATUS_INVALID_PARAM;
-		}
-	}
-	return 0;
-}
-
-static ssize_t
-qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
-	struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	struct qlcnic_esw_func_cfg *esw_cfg;
-	struct qlcnic_npar_info *npar;
-	int count, rem, i, ret;
-	u8 pci_func, op_mode = 0;
-
-	count	= size / sizeof(struct qlcnic_esw_func_cfg);
-	rem	= size % sizeof(struct qlcnic_esw_func_cfg);
-	if (rem)
-		return QL_STATUS_INVALID_PARAM;
-
-	esw_cfg = (struct qlcnic_esw_func_cfg *) buf;
-	ret = validate_esw_config(adapter, esw_cfg, count);
-	if (ret)
-		return ret;
-
-	for (i = 0; i < count; i++) {
-		if (adapter->op_mode == QLCNIC_MGMT_FUNC)
-			if (qlcnic_config_switch_port(adapter, &esw_cfg[i]))
-				return QL_STATUS_INVALID_PARAM;
-
-		if (adapter->ahw->pci_func != esw_cfg[i].pci_func)
-			continue;
-
-		op_mode = esw_cfg[i].op_mode;
-		qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]);
-		esw_cfg[i].op_mode = op_mode;
-		esw_cfg[i].pci_func = adapter->ahw->pci_func;
-
-		switch (esw_cfg[i].op_mode) {
-		case QLCNIC_PORT_DEFAULTS:
-			qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
-			break;
-		case QLCNIC_ADD_VLAN:
-			qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
-			break;
-		case QLCNIC_DEL_VLAN:
-			esw_cfg[i].vlan_id = 0;
-			qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
-			break;
-		}
-	}
-
-	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
-		goto out;
-
-	for (i = 0; i < count; i++) {
-		pci_func = esw_cfg[i].pci_func;
-		npar = &adapter->npars[pci_func];
-		switch (esw_cfg[i].op_mode) {
-		case QLCNIC_PORT_DEFAULTS:
-			npar->promisc_mode = esw_cfg[i].promisc_mode;
-			npar->mac_override = esw_cfg[i].mac_override;
-			npar->offload_flags = esw_cfg[i].offload_flags;
-			npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof;
-			npar->discard_tagged = esw_cfg[i].discard_tagged;
-			break;
-		case QLCNIC_ADD_VLAN:
-			npar->pvid = esw_cfg[i].vlan_id;
-			break;
-		case QLCNIC_DEL_VLAN:
-			npar->pvid = 0;
-			break;
-		}
-	}
-out:
-	return size;
-}
-
-static ssize_t
-qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj,
-	struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC];
-	u8 i;
-
-	if (size != sizeof(esw_cfg))
-		return QL_STATUS_INVALID_PARAM;
-
-	for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
-		if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
-			continue;
-		esw_cfg[i].pci_func = i;
-		if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]))
-			return QL_STATUS_INVALID_PARAM;
-	}
-	memcpy(buf, &esw_cfg, size);
-
-	return size;
-}
-
-static int
-validate_npar_config(struct qlcnic_adapter *adapter,
-				struct qlcnic_npar_func_cfg *np_cfg, int count)
-{
-	u8 pci_func, i;
-
-	for (i = 0; i < count; i++) {
-		pci_func = np_cfg[i].pci_func;
-		if (pci_func >= QLCNIC_MAX_PCI_FUNC)
-			return QL_STATUS_INVALID_PARAM;
-
-		if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
-			return QL_STATUS_INVALID_PARAM;
-
-		if (!IS_VALID_BW(np_cfg[i].min_bw) ||
-		    !IS_VALID_BW(np_cfg[i].max_bw))
-			return QL_STATUS_INVALID_PARAM;
-	}
-	return 0;
-}
-
-static ssize_t
-qlcnic_sysfs_write_npar_config(struct file *file, struct kobject *kobj,
-	struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	struct qlcnic_info nic_info;
-	struct qlcnic_npar_func_cfg *np_cfg;
-	int i, count, rem, ret;
-	u8 pci_func;
-
-	count	= size / sizeof(struct qlcnic_npar_func_cfg);
-	rem	= size % sizeof(struct qlcnic_npar_func_cfg);
-	if (rem)
-		return QL_STATUS_INVALID_PARAM;
-
-	np_cfg = (struct qlcnic_npar_func_cfg *) buf;
-	ret = validate_npar_config(adapter, np_cfg, count);
-	if (ret)
-		return ret;
-
-	for (i = 0; i < count ; i++) {
-		pci_func = np_cfg[i].pci_func;
-		ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
-		if (ret)
-			return ret;
-		nic_info.pci_func = pci_func;
-		nic_info.min_tx_bw = np_cfg[i].min_bw;
-		nic_info.max_tx_bw = np_cfg[i].max_bw;
-		ret = qlcnic_set_nic_info(adapter, &nic_info);
-		if (ret)
-			return ret;
-		adapter->npars[i].min_bw = nic_info.min_tx_bw;
-		adapter->npars[i].max_bw = nic_info.max_tx_bw;
-	}
-
-	return size;
-
-}
-static ssize_t
-qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj,
-	struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	struct qlcnic_info nic_info;
-	struct qlcnic_npar_func_cfg np_cfg[QLCNIC_MAX_PCI_FUNC];
-	int i, ret;
-
-	if (size != sizeof(np_cfg))
-		return QL_STATUS_INVALID_PARAM;
-
-	for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
-		if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
-			continue;
-		ret = qlcnic_get_nic_info(adapter, &nic_info, i);
-		if (ret)
-			return ret;
-
-		np_cfg[i].pci_func = i;
-		np_cfg[i].op_mode = (u8)nic_info.op_mode;
-		np_cfg[i].port_num = nic_info.phys_port;
-		np_cfg[i].fw_capab = nic_info.capabilities;
-		np_cfg[i].min_bw = nic_info.min_tx_bw ;
-		np_cfg[i].max_bw = nic_info.max_tx_bw;
-		np_cfg[i].max_tx_queues = nic_info.max_tx_ques;
-		np_cfg[i].max_rx_queues = nic_info.max_rx_ques;
-	}
-	memcpy(buf, &np_cfg, size);
-	return size;
-}
-
-static ssize_t
-qlcnic_sysfs_get_port_stats(struct file *file, struct kobject *kobj,
-	struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	struct qlcnic_esw_statistics port_stats;
-	int ret;
-
-	if (size != sizeof(struct qlcnic_esw_statistics))
-		return QL_STATUS_INVALID_PARAM;
-
-	if (offset >= QLCNIC_MAX_PCI_FUNC)
-		return QL_STATUS_INVALID_PARAM;
-
-	memset(&port_stats, 0, size);
-	ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
-								&port_stats.rx);
-	if (ret)
-		return ret;
-
-	ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
-								&port_stats.tx);
-	if (ret)
-		return ret;
-
-	memcpy(buf, &port_stats, size);
-	return size;
-}
-
-static ssize_t
-qlcnic_sysfs_get_esw_stats(struct file *file, struct kobject *kobj,
-	struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	struct qlcnic_esw_statistics esw_stats;
-	int ret;
-
-	if (size != sizeof(struct qlcnic_esw_statistics))
-		return QL_STATUS_INVALID_PARAM;
-
-	if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
-		return QL_STATUS_INVALID_PARAM;
-
-	memset(&esw_stats, 0, size);
-	ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
-								&esw_stats.rx);
-	if (ret)
-		return ret;
-
-	ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
-								&esw_stats.tx);
-	if (ret)
-		return ret;
-
-	memcpy(buf, &esw_stats, size);
-	return size;
-}
-
-static ssize_t
-qlcnic_sysfs_clear_esw_stats(struct file *file, struct kobject *kobj,
-	struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	int ret;
-
-	if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
-		return QL_STATUS_INVALID_PARAM;
-
-	ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
-						QLCNIC_QUERY_RX_COUNTER);
-	if (ret)
-		return ret;
-
-	ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
-						QLCNIC_QUERY_TX_COUNTER);
-	if (ret)
-		return ret;
-
-	return size;
-}
-
-static ssize_t
-qlcnic_sysfs_clear_port_stats(struct file *file, struct kobject *kobj,
-	struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	int ret;
-
-	if (offset >= QLCNIC_MAX_PCI_FUNC)
-		return QL_STATUS_INVALID_PARAM;
-
-	ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
-						QLCNIC_QUERY_RX_COUNTER);
-	if (ret)
-		return ret;
-
-	ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
-						QLCNIC_QUERY_TX_COUNTER);
-	if (ret)
-		return ret;
-
-	return size;
-}
-
-static ssize_t
-qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj,
-	struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-	struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC];
-	struct qlcnic_pci_info *pci_info;
-	int i, ret;
-
-	if (size != sizeof(pci_cfg))
-		return QL_STATUS_INVALID_PARAM;
-
-	pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
-	if (!pci_info)
-		return -ENOMEM;
-
-	ret = qlcnic_get_pci_info(adapter, pci_info);
-	if (ret) {
-		kfree(pci_info);
-		return ret;
-	}
-
-	for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
-		pci_cfg[i].pci_func = pci_info[i].id;
-		pci_cfg[i].func_type = pci_info[i].type;
-		pci_cfg[i].port_num = pci_info[i].default_port;
-		pci_cfg[i].min_bw = pci_info[i].tx_min_bw;
-		pci_cfg[i].max_bw = pci_info[i].tx_max_bw;
-		memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN);
-	}
-	memcpy(buf, &pci_cfg, size);
-	kfree(pci_info);
-	return size;
-}
-static struct bin_attribute bin_attr_npar_config = {
-	.attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)},
-	.size = 0,
-	.read = qlcnic_sysfs_read_npar_config,
-	.write = qlcnic_sysfs_write_npar_config,
-};
-
-static struct bin_attribute bin_attr_pci_config = {
-	.attr = {.name = "pci_config", .mode = (S_IRUGO | S_IWUSR)},
-	.size = 0,
-	.read = qlcnic_sysfs_read_pci_config,
-	.write = NULL,
-};
-
-static struct bin_attribute bin_attr_port_stats = {
-	.attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)},
-	.size = 0,
-	.read = qlcnic_sysfs_get_port_stats,
-	.write = qlcnic_sysfs_clear_port_stats,
-};
-
-static struct bin_attribute bin_attr_esw_stats = {
-	.attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)},
-	.size = 0,
-	.read = qlcnic_sysfs_get_esw_stats,
-	.write = qlcnic_sysfs_clear_esw_stats,
-};
-
-static struct bin_attribute bin_attr_esw_config = {
-	.attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)},
-	.size = 0,
-	.read = qlcnic_sysfs_read_esw_config,
-	.write = qlcnic_sysfs_write_esw_config,
-};
-
-static struct bin_attribute bin_attr_pm_config = {
-	.attr = {.name = "pm_config", .mode = (S_IRUGO | S_IWUSR)},
-	.size = 0,
-	.read = qlcnic_sysfs_read_pm_config,
-	.write = qlcnic_sysfs_write_pm_config,
-};
-
-static void
-qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)
-{
-	struct device *dev = &adapter->pdev->dev;
-
-	if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
-		if (device_create_file(dev, &dev_attr_bridged_mode))
-			dev_warn(dev,
-				"failed to create bridged_mode sysfs entry\n");
-}
-
-static void
-qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter)
-{
-	struct device *dev = &adapter->pdev->dev;
-
-	if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
-		device_remove_file(dev, &dev_attr_bridged_mode);
-}
-
-static void
-qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
-{
-	struct device *dev = &adapter->pdev->dev;
-	u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
-
-	if (device_create_bin_file(dev, &bin_attr_port_stats))
-		dev_info(dev, "failed to create port stats sysfs entry");
-
-	if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
-		return;
-	if (device_create_file(dev, &dev_attr_diag_mode))
-		dev_info(dev, "failed to create diag_mode sysfs entry\n");
-	if (device_create_bin_file(dev, &bin_attr_crb))
-		dev_info(dev, "failed to create crb sysfs entry\n");
-	if (device_create_bin_file(dev, &bin_attr_mem))
-		dev_info(dev, "failed to create mem sysfs entry\n");
-
-	if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
-		return;
-
-	if (device_create_bin_file(dev, &bin_attr_pci_config))
-		dev_info(dev, "failed to create pci config sysfs entry");
-	if (device_create_file(dev, &dev_attr_beacon))
-		dev_info(dev, "failed to create beacon sysfs entry");
-
-	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
-		return;
-	if (device_create_bin_file(dev, &bin_attr_esw_config))
-		dev_info(dev, "failed to create esw config sysfs entry");
-	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
-		return;
-	if (device_create_bin_file(dev, &bin_attr_npar_config))
-		dev_info(dev, "failed to create npar config sysfs entry");
-	if (device_create_bin_file(dev, &bin_attr_pm_config))
-		dev_info(dev, "failed to create pm config sysfs entry");
-	if (device_create_bin_file(dev, &bin_attr_esw_stats))
-		dev_info(dev, "failed to create eswitch stats sysfs entry");
-}
-
-static void
-qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
-{
-	struct device *dev = &adapter->pdev->dev;
-	u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
-
-	device_remove_bin_file(dev, &bin_attr_port_stats);
-
-	if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
-		return;
-	device_remove_file(dev, &dev_attr_diag_mode);
-	device_remove_bin_file(dev, &bin_attr_crb);
-	device_remove_bin_file(dev, &bin_attr_mem);
-	if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
-		return;
-	device_remove_bin_file(dev, &bin_attr_pci_config);
-	device_remove_file(dev, &dev_attr_beacon);
-	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
-		return;
-	device_remove_bin_file(dev, &bin_attr_esw_config);
-	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
-		return;
-	device_remove_bin_file(dev, &bin_attr_npar_config);
-	device_remove_bin_file(dev, &bin_attr_pm_config);
-	device_remove_bin_file(dev, &bin_attr_esw_stats);
-}
-
 #ifdef CONFIG_INET
 
 #define is_qlcnic_netdev(dev) (dev->netdev_ops == &qlcnic_netdev_ops)
@@ -4523,7 +2918,7 @@ static void
 qlcnic_restore_indev_addr(struct net_device *dev, unsigned long event)
 { }
 #endif
-static const struct pci_error_handlers qlcnic_err_handler = {
+static struct pci_error_handlers qlcnic_err_handler = {
 	.error_detected = qlcnic_io_error_detected,
 	.slot_reset = qlcnic_io_slot_reset,
 	.resume = qlcnic_io_resume,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
new file mode 100644
index 0000000..12ff292
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
@@ -0,0 +1,629 @@
+#include "qlcnic.h"
+#include "qlcnic_hdr.h"
+
+#include <net/ip.h>
+
+#define QLCNIC_DUMP_WCRB	BIT_0
+#define QLCNIC_DUMP_RWCRB	BIT_1
+#define QLCNIC_DUMP_ANDCRB	BIT_2
+#define QLCNIC_DUMP_ORCRB	BIT_3
+#define QLCNIC_DUMP_POLLCRB	BIT_4
+#define QLCNIC_DUMP_RD_SAVE	BIT_5
+#define QLCNIC_DUMP_WRT_SAVED	BIT_6
+#define QLCNIC_DUMP_MOD_SAVE_ST	BIT_7
+#define QLCNIC_DUMP_SKIP	BIT_7
+
+#define QLCNIC_DUMP_MASK_MAX	0xff
+
+struct qlcnic_common_entry_hdr {
+	u32     type;
+	u32     offset;
+	u32     cap_size;
+	u8      mask;
+	u8      rsvd[2];
+	u8      flags;
+} __packed;
+
+struct __crb {
+	u32	addr;
+	u8	stride;
+	u8	rsvd1[3];
+	u32	data_size;
+	u32	no_ops;
+	u32	rsvd2[4];
+} __packed;
+
+struct __ctrl {
+	u32	addr;
+	u8	stride;
+	u8	index_a;
+	u16	timeout;
+	u32	data_size;
+	u32	no_ops;
+	u8	opcode;
+	u8	index_v;
+	u8	shl_val;
+	u8	shr_val;
+	u32	val1;
+	u32	val2;
+	u32	val3;
+} __packed;
+
+struct __cache {
+	u32	addr;
+	u16	stride;
+	u16	init_tag_val;
+	u32	size;
+	u32	no_ops;
+	u32	ctrl_addr;
+	u32	ctrl_val;
+	u32	read_addr;
+	u8	read_addr_stride;
+	u8	read_addr_num;
+	u8	rsvd1[2];
+} __packed;
+
+struct __ocm {
+	u8	rsvd[8];
+	u32	size;
+	u32	no_ops;
+	u8	rsvd1[8];
+	u32	read_addr;
+	u32	read_addr_stride;
+} __packed;
+
+struct __mem {
+	u8	rsvd[24];
+	u32	addr;
+	u32	size;
+} __packed;
+
+struct __mux {
+	u32	addr;
+	u8	rsvd[4];
+	u32	size;
+	u32	no_ops;
+	u32	val;
+	u32	val_stride;
+	u32	read_addr;
+	u8	rsvd2[4];
+} __packed;
+
+struct __queue {
+	u32	sel_addr;
+	u16	stride;
+	u8	rsvd[2];
+	u32	size;
+	u32	no_ops;
+	u8	rsvd2[8];
+	u32	read_addr;
+	u8	read_addr_stride;
+	u8	read_addr_cnt;
+	u8	rsvd3[2];
+} __packed;
+
+struct qlcnic_dump_entry {
+	struct qlcnic_common_entry_hdr hdr;
+	union {
+		struct __crb	crb;
+		struct __cache	cache;
+		struct __ocm	ocm;
+		struct __mem	mem;
+		struct __mux	mux;
+		struct __queue	que;
+		struct __ctrl	ctrl;
+	} region;
+} __packed;
+
+enum qlcnic_minidump_opcode {
+	QLCNIC_DUMP_NOP		= 0,
+	QLCNIC_DUMP_READ_CRB	= 1,
+	QLCNIC_DUMP_READ_MUX	= 2,
+	QLCNIC_DUMP_QUEUE	= 3,
+	QLCNIC_DUMP_BRD_CONFIG	= 4,
+	QLCNIC_DUMP_READ_OCM	= 6,
+	QLCNIC_DUMP_PEG_REG	= 7,
+	QLCNIC_DUMP_L1_DTAG	= 8,
+	QLCNIC_DUMP_L1_ITAG	= 9,
+	QLCNIC_DUMP_L1_DATA	= 11,
+	QLCNIC_DUMP_L1_INST	= 12,
+	QLCNIC_DUMP_L2_DTAG	= 21,
+	QLCNIC_DUMP_L2_ITAG	= 22,
+	QLCNIC_DUMP_L2_DATA	= 23,
+	QLCNIC_DUMP_L2_INST	= 24,
+	QLCNIC_DUMP_READ_ROM	= 71,
+	QLCNIC_DUMP_READ_MEM	= 72,
+	QLCNIC_DUMP_READ_CTRL	= 98,
+	QLCNIC_DUMP_TLHDR	= 99,
+	QLCNIC_DUMP_RDEND	= 255
+};
+
+struct qlcnic_dump_operations {
+	enum qlcnic_minidump_opcode opcode;
+	u32 (*handler)(struct qlcnic_adapter *, struct qlcnic_dump_entry *,
+		       __le32 *);
+};
+
+static void qlcnic_read_dump_reg(u32 addr, void __iomem *bar0, u32 *data)
+{
+	u32 dest;
+	void __iomem *window_reg;
+
+	dest = addr & 0xFFFF0000;
+	window_reg = bar0 + QLCNIC_FW_DUMP_REG1;
+	writel(dest, window_reg);
+	readl(window_reg);
+	window_reg = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr);
+	*data = readl(window_reg);
+}
+
+static void qlcnic_write_dump_reg(u32 addr, void __iomem *bar0, u32 data)
+{
+	u32 dest;
+	void __iomem *window_reg;
+
+	dest = addr & 0xFFFF0000;
+	window_reg = bar0 + QLCNIC_FW_DUMP_REG1;
+	writel(dest, window_reg);
+	readl(window_reg);
+	window_reg = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr);
+	writel(data, window_reg);
+	readl(window_reg);
+}
+
+/* FW dump related functions */
+static u32 qlcnic_dump_crb(struct qlcnic_adapter *adapter,
+			   struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+	int i;
+	u32 addr, data;
+	struct __crb *crb = &entry->region.crb;
+	void __iomem *base = adapter->ahw->pci_base0;
+
+	addr = crb->addr;
+
+	for (i = 0; i < crb->no_ops; i++) {
+		qlcnic_read_dump_reg(addr, base, &data);
+		*buffer++ = cpu_to_le32(addr);
+		*buffer++ = cpu_to_le32(data);
+		addr += crb->stride;
+	}
+	return crb->no_ops * 2 * sizeof(u32);
+}
+
+static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,
+			    struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+	int i, k, timeout = 0;
+	void __iomem *base = adapter->ahw->pci_base0;
+	u32 addr, data;
+	u8 opcode, no_ops;
+	struct __ctrl *ctr = &entry->region.ctrl;
+	struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr;
+
+	addr = ctr->addr;
+	no_ops = ctr->no_ops;
+
+	for (i = 0; i < no_ops; i++) {
+		k = 0;
+		opcode = 0;
+		for (k = 0; k < 8; k++) {
+			if (!(ctr->opcode & (1 << k)))
+				continue;
+			switch (1 << k) {
+			case QLCNIC_DUMP_WCRB:
+				qlcnic_write_dump_reg(addr, base, ctr->val1);
+				break;
+			case QLCNIC_DUMP_RWCRB:
+				qlcnic_read_dump_reg(addr, base, &data);
+				qlcnic_write_dump_reg(addr, base, data);
+				break;
+			case QLCNIC_DUMP_ANDCRB:
+				qlcnic_read_dump_reg(addr, base, &data);
+				qlcnic_write_dump_reg(addr, base,
+						      data & ctr->val2);
+				break;
+			case QLCNIC_DUMP_ORCRB:
+				qlcnic_read_dump_reg(addr, base, &data);
+				qlcnic_write_dump_reg(addr, base,
+						      data | ctr->val3);
+				break;
+			case QLCNIC_DUMP_POLLCRB:
+				while (timeout <= ctr->timeout) {
+					qlcnic_read_dump_reg(addr, base, &data);
+					if ((data & ctr->val2) == ctr->val1)
+						break;
+					msleep(1);
+					timeout++;
+				}
+				if (timeout > ctr->timeout) {
+					dev_info(&adapter->pdev->dev,
+					"Timed out, aborting poll CRB\n");
+					return -EINVAL;
+				}
+				break;
+			case QLCNIC_DUMP_RD_SAVE:
+				if (ctr->index_a)
+					addr = t_hdr->saved_state[ctr->index_a];
+				qlcnic_read_dump_reg(addr, base, &data);
+				t_hdr->saved_state[ctr->index_v] = data;
+				break;
+			case QLCNIC_DUMP_WRT_SAVED:
+				if (ctr->index_v)
+					data = t_hdr->saved_state[ctr->index_v];
+				else
+					data = ctr->val1;
+				if (ctr->index_a)
+					addr = t_hdr->saved_state[ctr->index_a];
+				qlcnic_write_dump_reg(addr, base, data);
+				break;
+			case QLCNIC_DUMP_MOD_SAVE_ST:
+				data = t_hdr->saved_state[ctr->index_v];
+				data <<= ctr->shl_val;
+				data >>= ctr->shr_val;
+				if (ctr->val2)
+					data &= ctr->val2;
+				data |= ctr->val3;
+				data += ctr->val1;
+				t_hdr->saved_state[ctr->index_v] = data;
+				break;
+			default:
+				dev_info(&adapter->pdev->dev,
+					 "Unknown opcode\n");
+				break;
+			}
+		}
+		addr += ctr->stride;
+	}
+	return 0;
+}
+
+static u32 qlcnic_dump_mux(struct qlcnic_adapter *adapter,
+			   struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+	int loop;
+	u32 val, data = 0;
+	struct __mux *mux = &entry->region.mux;
+	void __iomem *base = adapter->ahw->pci_base0;
+
+	val = mux->val;
+	for (loop = 0; loop < mux->no_ops; loop++) {
+		qlcnic_write_dump_reg(mux->addr, base, val);
+		qlcnic_read_dump_reg(mux->read_addr, base, &data);
+		*buffer++ = cpu_to_le32(val);
+		*buffer++ = cpu_to_le32(data);
+		val += mux->val_stride;
+	}
+	return 2 * mux->no_ops * sizeof(u32);
+}
+
+static u32 qlcnic_dump_que(struct qlcnic_adapter *adapter,
+			   struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+	int i, loop;
+	u32 cnt, addr, data, que_id = 0;
+	void __iomem *base = adapter->ahw->pci_base0;
+	struct __queue *que = &entry->region.que;
+
+	addr = que->read_addr;
+	cnt = que->read_addr_cnt;
+
+	for (loop = 0; loop < que->no_ops; loop++) {
+		qlcnic_write_dump_reg(que->sel_addr, base, que_id);
+		addr = que->read_addr;
+		for (i = 0; i < cnt; i++) {
+			qlcnic_read_dump_reg(addr, base, &data);
+			*buffer++ = cpu_to_le32(data);
+			addr += que->read_addr_stride;
+		}
+		que_id += que->stride;
+	}
+	return que->no_ops * cnt * sizeof(u32);
+}
+
+static u32 qlcnic_dump_ocm(struct qlcnic_adapter *adapter,
+			   struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+	int i;
+	u32 data;
+	void __iomem *addr;
+	struct __ocm *ocm = &entry->region.ocm;
+
+	addr = adapter->ahw->pci_base0 + ocm->read_addr;
+	for (i = 0; i < ocm->no_ops; i++) {
+		data = readl(addr);
+		*buffer++ = cpu_to_le32(data);
+		addr += ocm->read_addr_stride;
+	}
+	return ocm->no_ops * sizeof(u32);
+}
+
+static u32 qlcnic_read_rom(struct qlcnic_adapter *adapter,
+			   struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+	int i, count = 0;
+	u32 fl_addr, size, val, lck_val, addr;
+	struct __mem *rom = &entry->region.mem;
+	void __iomem *base = adapter->ahw->pci_base0;
+
+	fl_addr = rom->addr;
+	size = rom->size/4;
+lock_try:
+	lck_val = readl(base + QLCNIC_FLASH_SEM2_LK);
+	if (!lck_val && count < MAX_CTL_CHECK) {
+		msleep(10);
+		count++;
+		goto lock_try;
+	}
+	writel(adapter->ahw->pci_func, (base + QLCNIC_FLASH_LOCK_ID));
+	for (i = 0; i < size; i++) {
+		addr = fl_addr & 0xFFFF0000;
+		qlcnic_write_dump_reg(FLASH_ROM_WINDOW, base, addr);
+		addr = LSW(fl_addr) + FLASH_ROM_DATA;
+		qlcnic_read_dump_reg(addr, base, &val);
+		fl_addr += 4;
+		*buffer++ = cpu_to_le32(val);
+	}
+	readl(base + QLCNIC_FLASH_SEM2_ULK);
+	return rom->size;
+}
+
+static u32 qlcnic_dump_l1_cache(struct qlcnic_adapter *adapter,
+				struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+	int i;
+	u32 cnt, val, data, addr;
+	void __iomem *base = adapter->ahw->pci_base0;
+	struct __cache *l1 = &entry->region.cache;
+
+	val = l1->init_tag_val;
+
+	for (i = 0; i < l1->no_ops; i++) {
+		qlcnic_write_dump_reg(l1->addr, base, val);
+		qlcnic_write_dump_reg(l1->ctrl_addr, base, LSW(l1->ctrl_val));
+		addr = l1->read_addr;
+		cnt = l1->read_addr_num;
+		while (cnt) {
+			qlcnic_read_dump_reg(addr, base, &data);
+			*buffer++ = cpu_to_le32(data);
+			addr += l1->read_addr_stride;
+			cnt--;
+		}
+		val += l1->stride;
+	}
+	return l1->no_ops * l1->read_addr_num * sizeof(u32);
+}
+
+static u32 qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter,
+				struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+	int i;
+	u32 cnt, val, data, addr;
+	u8 poll_mask, poll_to, time_out = 0;
+	void __iomem *base = adapter->ahw->pci_base0;
+	struct __cache *l2 = &entry->region.cache;
+
+	val = l2->init_tag_val;
+	poll_mask = LSB(MSW(l2->ctrl_val));
+	poll_to = MSB(MSW(l2->ctrl_val));
+
+	for (i = 0; i < l2->no_ops; i++) {
+		qlcnic_write_dump_reg(l2->addr, base, val);
+		if (LSW(l2->ctrl_val))
+			qlcnic_write_dump_reg(l2->ctrl_addr, base,
+					      LSW(l2->ctrl_val));
+		if (!poll_mask)
+			goto skip_poll;
+		do {
+			qlcnic_read_dump_reg(l2->ctrl_addr, base, &data);
+			if (!(data & poll_mask))
+				break;
+			msleep(1);
+			time_out++;
+		} while (time_out <= poll_to);
+
+		if (time_out > poll_to) {
+			dev_err(&adapter->pdev->dev,
+				"Timeout exceeded in %s, aborting dump\n",
+				__func__);
+			return -EINVAL;
+		}
+skip_poll:
+		addr = l2->read_addr;
+		cnt = l2->read_addr_num;
+		while (cnt) {
+			qlcnic_read_dump_reg(addr, base, &data);
+			*buffer++ = cpu_to_le32(data);
+			addr += l2->read_addr_stride;
+			cnt--;
+		}
+		val += l2->stride;
+	}
+	return l2->no_ops * l2->read_addr_num * sizeof(u32);
+}
+
+static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter,
+			      struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+	u32 addr, data, test, ret = 0;
+	int i, reg_read;
+	struct __mem *mem = &entry->region.mem;
+	void __iomem *base = adapter->ahw->pci_base0;
+
+	reg_read = mem->size;
+	addr = mem->addr;
+	/* check for data size of multiple of 16 and 16 byte alignment */
+	if ((addr & 0xf) || (reg_read%16)) {
+		dev_info(&adapter->pdev->dev,
+			 "Unaligned memory addr:0x%x size:0x%x\n",
+			 addr, reg_read);
+		return -EINVAL;
+	}
+
+	mutex_lock(&adapter->ahw->mem_lock);
+
+	while (reg_read != 0) {
+		qlcnic_write_dump_reg(MIU_TEST_ADDR_LO, base, addr);
+		qlcnic_write_dump_reg(MIU_TEST_ADDR_HI, base, 0);
+		qlcnic_write_dump_reg(MIU_TEST_CTR, base,
+				      TA_CTL_ENABLE | TA_CTL_START);
+
+		for (i = 0; i < MAX_CTL_CHECK; i++) {
+			qlcnic_read_dump_reg(MIU_TEST_CTR, base, &test);
+			if (!(test & TA_CTL_BUSY))
+				break;
+		}
+		if (i == MAX_CTL_CHECK) {
+			if (printk_ratelimit()) {
+				dev_err(&adapter->pdev->dev,
+					"failed to read through agent\n");
+				ret = -EINVAL;
+				goto out;
+			}
+		}
+		for (i = 0; i < 4; i++) {
+			qlcnic_read_dump_reg(MIU_TEST_READ_DATA[i], base,
+					     &data);
+			*buffer++ = cpu_to_le32(data);
+		}
+		addr += 16;
+		reg_read -= 16;
+		ret += 16;
+	}
+out:
+	mutex_unlock(&adapter->ahw->mem_lock);
+	return mem->size;
+}
+
+static u32 qlcnic_dump_nop(struct qlcnic_adapter *adapter,
+			   struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+	entry->hdr.flags |= QLCNIC_DUMP_SKIP;
+	return 0;
+}
+
+static const struct qlcnic_dump_operations fw_dump_ops[] = {
+	{ QLCNIC_DUMP_NOP, qlcnic_dump_nop },
+	{ QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb },
+	{ QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux },
+	{ QLCNIC_DUMP_QUEUE, qlcnic_dump_que },
+	{ QLCNIC_DUMP_BRD_CONFIG, qlcnic_read_rom },
+	{ QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm },
+	{ QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl },
+	{ QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache },
+	{ QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache },
+	{ QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache },
+	{ QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache },
+	{ QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache },
+	{ QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache },
+	{ QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache },
+	{ QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache },
+	{ QLCNIC_DUMP_READ_ROM, qlcnic_read_rom },
+	{ QLCNIC_DUMP_READ_MEM, qlcnic_read_memory },
+	{ QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl },
+	{ QLCNIC_DUMP_TLHDR, qlcnic_dump_nop },
+	{ QLCNIC_DUMP_RDEND, qlcnic_dump_nop },
+};
+
+/* Walk the template and collect dump for each entry in the dump template */
+static int
+qlcnic_valid_dump_entry(struct device *dev, struct qlcnic_dump_entry *entry,
+			u32 size)
+{
+	int ret = 1;
+	if (size != entry->hdr.cap_size) {
+		dev_info(dev,
+			 "Invalid dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n",
+		entry->hdr.type, entry->hdr.mask, size, entry->hdr.cap_size);
+		dev_info(dev, "Aborting further dump capture\n");
+		ret = 0;
+	}
+	return ret;
+}
+
+int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
+{
+	__le32 *buffer;
+	char mesg[64];
+	char *msg[] = {mesg, NULL};
+	int i, k, ops_cnt, ops_index, dump_size = 0;
+	u32 entry_offset, dump, no_entries, buf_offset = 0;
+	struct qlcnic_dump_entry *entry;
+	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
+	struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr;
+
+	if (fw_dump->clr) {
+		dev_info(&adapter->pdev->dev,
+			 "Previous dump not cleared, not capturing dump\n");
+		return -EIO;
+	}
+	/* Calculate the size for dump data area only */
+	for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++)
+		if (i & tmpl_hdr->drv_cap_mask)
+			dump_size += tmpl_hdr->cap_sizes[k];
+	if (!dump_size)
+		return -EIO;
+
+	fw_dump->data = vzalloc(dump_size);
+	if (!fw_dump->data) {
+		dev_info(&adapter->pdev->dev,
+			 "Unable to allocate (%d KB) for fw dump\n",
+			 dump_size / 1024);
+		return -ENOMEM;
+	}
+	buffer = fw_dump->data;
+	fw_dump->size = dump_size;
+	no_entries = tmpl_hdr->num_entries;
+	ops_cnt = ARRAY_SIZE(fw_dump_ops);
+	entry_offset = tmpl_hdr->offset;
+	tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION;
+	tmpl_hdr->sys_info[1] = adapter->fw_version;
+
+	for (i = 0; i < no_entries; i++) {
+		entry = (void *)tmpl_hdr + entry_offset;
+		if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) {
+			entry->hdr.flags |= QLCNIC_DUMP_SKIP;
+			entry_offset += entry->hdr.offset;
+			continue;
+		}
+		/* Find the handler for this entry */
+		ops_index = 0;
+		while (ops_index < ops_cnt) {
+			if (entry->hdr.type == fw_dump_ops[ops_index].opcode)
+				break;
+			ops_index++;
+		}
+		if (ops_index == ops_cnt) {
+			dev_info(&adapter->pdev->dev,
+				 "Invalid entry type %d, exiting dump\n",
+				 entry->hdr.type);
+			goto error;
+		}
+		/* Collect dump for this entry */
+		dump = fw_dump_ops[ops_index].handler(adapter, entry, buffer);
+		if (dump && !qlcnic_valid_dump_entry(&adapter->pdev->dev, entry,
+						     dump))
+			entry->hdr.flags |= QLCNIC_DUMP_SKIP;
+		buf_offset += entry->hdr.cap_size;
+		entry_offset += entry->hdr.offset;
+		buffer = fw_dump->data + buf_offset;
+	}
+	if (dump_size != buf_offset) {
+		dev_info(&adapter->pdev->dev,
+			 "Captured(%d) and expected size(%d) do not match\n",
+			 buf_offset, dump_size);
+		goto error;
+	} else {
+		fw_dump->clr = 1;
+		snprintf(mesg, sizeof(mesg), "FW_DUMP=%s",
+			 adapter->netdev->name);
+		dev_info(&adapter->pdev->dev, "Dump data, %d bytes captured\n",
+			 fw_dump->size);
+		/* Send a udev event to notify availability of FW dump */
+		kobject_uevent_env(&adapter->pdev->dev.kobj, KOBJ_CHANGE, msg);
+		return 0;
+	}
+error:
+	vfree(fw_dump->data);
+	return -EINVAL;
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
new file mode 100644
index 0000000..10a702a
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
@@ -0,0 +1,962 @@
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+
+#include "qlcnic.h"
+
+#include <linux/swab.h>
+#include <linux/dma-mapping.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
+#include <linux/inetdevice.h>
+#include <linux/sysfs.h>
+#include <linux/aer.h>
+#include <linux/log2.h>
+
+#include <linux/sysfs.h>
+
+int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
+{
+	return -EOPNOTSUPP;
+}
+
+int qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
+{
+	return -EOPNOTSUPP;
+}
+
+static ssize_t qlcnic_store_bridged_mode(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t len)
+{
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	unsigned long new;
+	int ret = -EINVAL;
+
+	if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG))
+		goto err_out;
+
+	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
+		goto err_out;
+
+	if (strict_strtoul(buf, 2, &new))
+		goto err_out;
+
+	if (!adapter->nic_ops->config_bridged_mode(adapter, !!new))
+		ret = len;
+
+err_out:
+	return ret;
+}
+
+static ssize_t qlcnic_show_bridged_mode(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	int bridged_mode = 0;
+
+	if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
+		bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED);
+
+	return sprintf(buf, "%d\n", bridged_mode);
+}
+
+static ssize_t qlcnic_store_diag_mode(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t len)
+{
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	unsigned long new;
+
+	if (strict_strtoul(buf, 2, &new))
+		return -EINVAL;
+
+	if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED))
+		adapter->flags ^= QLCNIC_DIAG_ENABLED;
+
+	return len;
+}
+
+static ssize_t qlcnic_show_diag_mode(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n",
+		       !!(adapter->flags & QLCNIC_DIAG_ENABLED));
+}
+
+static int qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon,
+				  u8 *state, u8 *rate)
+{
+	*rate = LSB(beacon);
+	*state = MSB(beacon);
+
+	QLCDB(adapter, DRV, "rate %x state %x\n", *rate, *state);
+
+	if (!*state) {
+		*rate = __QLCNIC_MAX_LED_RATE;
+		return 0;
+	} else if (*state > __QLCNIC_MAX_LED_STATE) {
+		return -EINVAL;
+	}
+
+	if ((!*rate) || (*rate > __QLCNIC_MAX_LED_RATE))
+		return -EINVAL;
+
+	return 0;
+}
+
+static ssize_t qlcnic_store_beacon(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t len)
+{
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	int max_sds_rings = adapter->max_sds_rings;
+	u16 beacon;
+	u8 b_state, b_rate;
+	int err;
+
+	if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
+		dev_warn(dev,
+			 "LED test not supported in non privileged mode\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (len != sizeof(u16))
+		return QL_STATUS_INVALID_PARAM;
+
+	memcpy(&beacon, buf, sizeof(u16));
+	err = qlcnic_validate_beacon(adapter, beacon, &b_state, &b_rate);
+	if (err)
+		return err;
+
+	if (adapter->ahw->beacon_state == b_state)
+		return len;
+
+	rtnl_lock();
+
+	if (!adapter->ahw->beacon_state)
+		if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
+			rtnl_unlock();
+			return -EBUSY;
+		}
+
+	if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
+		err = -EIO;
+		goto out;
+	}
+
+	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
+		err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST);
+		if (err)
+			goto out;
+		set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
+	}
+
+	err = qlcnic_config_led(adapter, b_state, b_rate);
+
+	if (!err) {
+		err = len;
+		adapter->ahw->beacon_state = b_state;
+	}
+
+	if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
+		qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
+
+ out:
+	if (!adapter->ahw->beacon_state)
+		clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
+	rtnl_unlock();
+
+	return err;
+}
+
+static ssize_t qlcnic_show_beacon(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", adapter->ahw->beacon_state);
+}
+
+static int qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter,
+				     loff_t offset, size_t size)
+{
+	size_t crb_size = 4;
+
+	if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
+		return -EIO;
+
+	if (offset < QLCNIC_PCI_CRBSPACE) {
+		if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM,
+				  QLCNIC_PCI_CAMQM_END))
+			crb_size = 8;
+		else
+			return -EINVAL;
+	}
+
+	if ((size != crb_size) || (offset & (crb_size-1)))
+		return  -EINVAL;
+
+	return 0;
+}
+
+static ssize_t qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
+				     struct bin_attribute *attr, char *buf,
+				     loff_t offset, size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	u32 data;
+	u64 qmdata;
+	int ret;
+
+	ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
+	if (ret != 0)
+		return ret;
+
+	if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
+		qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata);
+		memcpy(buf, &qmdata, size);
+	} else {
+		data = QLCRD32(adapter, offset);
+		memcpy(buf, &data, size);
+	}
+	return size;
+}
+
+static ssize_t qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
+				      struct bin_attribute *attr, char *buf,
+				      loff_t offset, size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	u32 data;
+	u64 qmdata;
+	int ret;
+
+	ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
+	if (ret != 0)
+		return ret;
+
+	if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
+		memcpy(&qmdata, buf, size);
+		qlcnic_pci_camqm_write_2M(adapter, offset, qmdata);
+	} else {
+		memcpy(&data, buf, size);
+		QLCWR32(adapter, offset, data);
+	}
+	return size;
+}
+
+static int qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter,
+				     loff_t offset, size_t size)
+{
+	if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
+		return -EIO;
+
+	if ((size != 8) || (offset & 0x7))
+		return  -EIO;
+
+	return 0;
+}
+
+static ssize_t qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
+				     struct bin_attribute *attr, char *buf,
+				     loff_t offset, size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	u64 data;
+	int ret;
+
+	ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
+	if (ret != 0)
+		return ret;
+
+	if (qlcnic_pci_mem_read_2M(adapter, offset, &data))
+		return -EIO;
+
+	memcpy(buf, &data, size);
+
+	return size;
+}
+
+static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
+				      struct bin_attribute *attr, char *buf,
+				      loff_t offset, size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	u64 data;
+	int ret;
+
+	ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
+	if (ret != 0)
+		return ret;
+
+	memcpy(&data, buf, size);
+
+	if (qlcnic_pci_mem_write_2M(adapter, offset, data))
+		return -EIO;
+
+	return size;
+}
+
+static int validate_pm_config(struct qlcnic_adapter *adapter,
+			      struct qlcnic_pm_func_cfg *pm_cfg, int count)
+{
+	u8 src_pci_func, s_esw_id, d_esw_id, dest_pci_func;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		src_pci_func = pm_cfg[i].pci_func;
+		dest_pci_func = pm_cfg[i].dest_npar;
+		if (src_pci_func >= QLCNIC_MAX_PCI_FUNC ||
+		    dest_pci_func >= QLCNIC_MAX_PCI_FUNC)
+			return QL_STATUS_INVALID_PARAM;
+
+		if (adapter->npars[src_pci_func].type != QLCNIC_TYPE_NIC)
+			return QL_STATUS_INVALID_PARAM;
+
+		if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC)
+			return QL_STATUS_INVALID_PARAM;
+
+		s_esw_id = adapter->npars[src_pci_func].phy_port;
+		d_esw_id = adapter->npars[dest_pci_func].phy_port;
+
+		if (s_esw_id != d_esw_id)
+			return QL_STATUS_INVALID_PARAM;
+	}
+	return 0;
+
+}
+
+static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp,
+					    struct kobject *kobj,
+					    struct bin_attribute *attr,
+					    char *buf, loff_t offset,
+					    size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	struct qlcnic_pm_func_cfg *pm_cfg;
+	u32 id, action, pci_func;
+	int count, rem, i, ret;
+
+	count	= size / sizeof(struct qlcnic_pm_func_cfg);
+	rem	= size % sizeof(struct qlcnic_pm_func_cfg);
+	if (rem)
+		return QL_STATUS_INVALID_PARAM;
+
+	pm_cfg = (struct qlcnic_pm_func_cfg *)buf;
+
+	ret = validate_pm_config(adapter, pm_cfg, count);
+	if (ret)
+		return ret;
+	for (i = 0; i < count; i++) {
+		pci_func = pm_cfg[i].pci_func;
+		action = !!pm_cfg[i].action;
+		id = adapter->npars[pci_func].phy_port;
+		ret = qlcnic_config_port_mirroring(adapter, id, action,
+						   pci_func);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < count; i++) {
+		pci_func = pm_cfg[i].pci_func;
+		id = adapter->npars[pci_func].phy_port;
+		adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action;
+		adapter->npars[pci_func].dest_npar = id;
+	}
+	return size;
+}
+
+static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp,
+					   struct kobject *kobj,
+					   struct bin_attribute *attr,
+					   char *buf, loff_t offset,
+					   size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC];
+	int i;
+
+	if (size != sizeof(pm_cfg))
+		return QL_STATUS_INVALID_PARAM;
+
+	for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+		if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
+			continue;
+		pm_cfg[i].action = adapter->npars[i].enable_pm;
+		pm_cfg[i].dest_npar = 0;
+		pm_cfg[i].pci_func = i;
+	}
+	memcpy(buf, &pm_cfg, size);
+
+	return size;
+}
+
+static int validate_esw_config(struct qlcnic_adapter *adapter,
+			       struct qlcnic_esw_func_cfg *esw_cfg, int count)
+{
+	u32 op_mode;
+	u8 pci_func;
+	int i;
+
+	op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE);
+
+	for (i = 0; i < count; i++) {
+		pci_func = esw_cfg[i].pci_func;
+		if (pci_func >= QLCNIC_MAX_PCI_FUNC)
+			return QL_STATUS_INVALID_PARAM;
+
+		if (adapter->op_mode == QLCNIC_MGMT_FUNC) {
+			if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
+				return QL_STATUS_INVALID_PARAM;
+		}
+
+		switch (esw_cfg[i].op_mode) {
+		case QLCNIC_PORT_DEFAULTS:
+			if (QLC_DEV_GET_DRV(op_mode, pci_func) !=
+					    QLCNIC_NON_PRIV_FUNC) {
+				if (esw_cfg[i].mac_anti_spoof != 0)
+					return QL_STATUS_INVALID_PARAM;
+				if (esw_cfg[i].mac_override != 1)
+					return QL_STATUS_INVALID_PARAM;
+				if (esw_cfg[i].promisc_mode != 1)
+					return QL_STATUS_INVALID_PARAM;
+			}
+			break;
+		case QLCNIC_ADD_VLAN:
+			if (!IS_VALID_VLAN(esw_cfg[i].vlan_id))
+				return QL_STATUS_INVALID_PARAM;
+			if (!esw_cfg[i].op_type)
+				return QL_STATUS_INVALID_PARAM;
+			break;
+		case QLCNIC_DEL_VLAN:
+			if (!esw_cfg[i].op_type)
+				return QL_STATUS_INVALID_PARAM;
+			break;
+		default:
+			return QL_STATUS_INVALID_PARAM;
+		}
+	}
+	return 0;
+}
+
+static ssize_t qlcnic_sysfs_write_esw_config(struct file *file,
+					     struct kobject *kobj,
+					     struct bin_attribute *attr,
+					     char *buf, loff_t offset,
+					     size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	struct qlcnic_esw_func_cfg *esw_cfg;
+	struct qlcnic_npar_info *npar;
+	int count, rem, i, ret;
+	u8 pci_func, op_mode = 0;
+
+	count	= size / sizeof(struct qlcnic_esw_func_cfg);
+	rem	= size % sizeof(struct qlcnic_esw_func_cfg);
+	if (rem)
+		return QL_STATUS_INVALID_PARAM;
+
+	esw_cfg = (struct qlcnic_esw_func_cfg *)buf;
+	ret = validate_esw_config(adapter, esw_cfg, count);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < count; i++) {
+		if (adapter->op_mode == QLCNIC_MGMT_FUNC) {
+			if (qlcnic_config_switch_port(adapter, &esw_cfg[i]))
+				return QL_STATUS_INVALID_PARAM;
+		}
+
+		if (adapter->ahw->pci_func != esw_cfg[i].pci_func)
+			continue;
+
+		op_mode = esw_cfg[i].op_mode;
+		qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]);
+		esw_cfg[i].op_mode = op_mode;
+		esw_cfg[i].pci_func = adapter->ahw->pci_func;
+
+		switch (esw_cfg[i].op_mode) {
+		case QLCNIC_PORT_DEFAULTS:
+			qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
+			break;
+		case QLCNIC_ADD_VLAN:
+			qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
+			break;
+		case QLCNIC_DEL_VLAN:
+			esw_cfg[i].vlan_id = 0;
+			qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
+			break;
+		}
+	}
+
+	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+		goto out;
+
+	for (i = 0; i < count; i++) {
+		pci_func = esw_cfg[i].pci_func;
+		npar = &adapter->npars[pci_func];
+		switch (esw_cfg[i].op_mode) {
+		case QLCNIC_PORT_DEFAULTS:
+			npar->promisc_mode = esw_cfg[i].promisc_mode;
+			npar->mac_override = esw_cfg[i].mac_override;
+			npar->offload_flags = esw_cfg[i].offload_flags;
+			npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof;
+			npar->discard_tagged = esw_cfg[i].discard_tagged;
+			break;
+		case QLCNIC_ADD_VLAN:
+			npar->pvid = esw_cfg[i].vlan_id;
+			break;
+		case QLCNIC_DEL_VLAN:
+			npar->pvid = 0;
+			break;
+		}
+	}
+out:
+	return size;
+}
+
+static ssize_t qlcnic_sysfs_read_esw_config(struct file *file,
+					    struct kobject *kobj,
+					    struct bin_attribute *attr,
+					    char *buf, loff_t offset,
+					    size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC];
+	u8 i;
+
+	if (size != sizeof(esw_cfg))
+		return QL_STATUS_INVALID_PARAM;
+
+	for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+		if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
+			continue;
+		esw_cfg[i].pci_func = i;
+		if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]))
+			return QL_STATUS_INVALID_PARAM;
+	}
+	memcpy(buf, &esw_cfg, size);
+
+	return size;
+}
+
+static int validate_npar_config(struct qlcnic_adapter *adapter,
+				struct qlcnic_npar_func_cfg *np_cfg,
+				int count)
+{
+	u8 pci_func, i;
+
+	for (i = 0; i < count; i++) {
+		pci_func = np_cfg[i].pci_func;
+		if (pci_func >= QLCNIC_MAX_PCI_FUNC)
+			return QL_STATUS_INVALID_PARAM;
+
+		if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
+			return QL_STATUS_INVALID_PARAM;
+
+		if (!IS_VALID_BW(np_cfg[i].min_bw) ||
+		    !IS_VALID_BW(np_cfg[i].max_bw))
+			return QL_STATUS_INVALID_PARAM;
+	}
+	return 0;
+}
+
+static ssize_t qlcnic_sysfs_write_npar_config(struct file *file,
+					      struct kobject *kobj,
+					      struct bin_attribute *attr,
+					      char *buf, loff_t offset,
+					      size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	struct qlcnic_info nic_info;
+	struct qlcnic_npar_func_cfg *np_cfg;
+	int i, count, rem, ret;
+	u8 pci_func;
+
+	count	= size / sizeof(struct qlcnic_npar_func_cfg);
+	rem	= size % sizeof(struct qlcnic_npar_func_cfg);
+	if (rem)
+		return QL_STATUS_INVALID_PARAM;
+
+	np_cfg = (struct qlcnic_npar_func_cfg *)buf;
+	ret = validate_npar_config(adapter, np_cfg, count);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < count ; i++) {
+		pci_func = np_cfg[i].pci_func;
+		ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
+		if (ret)
+			return ret;
+		nic_info.pci_func = pci_func;
+		nic_info.min_tx_bw = np_cfg[i].min_bw;
+		nic_info.max_tx_bw = np_cfg[i].max_bw;
+		ret = qlcnic_set_nic_info(adapter, &nic_info);
+		if (ret)
+			return ret;
+		adapter->npars[i].min_bw = nic_info.min_tx_bw;
+		adapter->npars[i].max_bw = nic_info.max_tx_bw;
+	}
+
+	return size;
+
+}
+
+static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
+					     struct kobject *kobj,
+					     struct bin_attribute *attr,
+					     char *buf, loff_t offset,
+					     size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	struct qlcnic_info nic_info;
+	struct qlcnic_npar_func_cfg np_cfg[QLCNIC_MAX_PCI_FUNC];
+	int i, ret;
+
+	if (size != sizeof(np_cfg))
+		return QL_STATUS_INVALID_PARAM;
+
+	for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+		if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
+			continue;
+		ret = qlcnic_get_nic_info(adapter, &nic_info, i);
+		if (ret)
+			return ret;
+
+		np_cfg[i].pci_func = i;
+		np_cfg[i].op_mode = (u8)nic_info.op_mode;
+		np_cfg[i].port_num = nic_info.phys_port;
+		np_cfg[i].fw_capab = nic_info.capabilities;
+		np_cfg[i].min_bw = nic_info.min_tx_bw;
+		np_cfg[i].max_bw = nic_info.max_tx_bw;
+		np_cfg[i].max_tx_queues = nic_info.max_tx_ques;
+		np_cfg[i].max_rx_queues = nic_info.max_rx_ques;
+	}
+	memcpy(buf, &np_cfg, size);
+	return size;
+}
+
+static ssize_t qlcnic_sysfs_get_port_stats(struct file *file,
+					   struct kobject *kobj,
+					   struct bin_attribute *attr,
+					   char *buf, loff_t offset,
+					   size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	struct qlcnic_esw_statistics port_stats;
+	int ret;
+
+	if (size != sizeof(struct qlcnic_esw_statistics))
+		return QL_STATUS_INVALID_PARAM;
+
+	if (offset >= QLCNIC_MAX_PCI_FUNC)
+		return QL_STATUS_INVALID_PARAM;
+
+	memset(&port_stats, 0, size);
+	ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
+				    &port_stats.rx);
+	if (ret)
+		return ret;
+
+	ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
+				    &port_stats.tx);
+	if (ret)
+		return ret;
+
+	memcpy(buf, &port_stats, size);
+	return size;
+}
+
+static ssize_t qlcnic_sysfs_get_esw_stats(struct file *file,
+					  struct kobject *kobj,
+					  struct bin_attribute *attr,
+					  char *buf, loff_t offset,
+					  size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	struct qlcnic_esw_statistics esw_stats;
+	int ret;
+
+	if (size != sizeof(struct qlcnic_esw_statistics))
+		return QL_STATUS_INVALID_PARAM;
+
+	if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
+		return QL_STATUS_INVALID_PARAM;
+
+	memset(&esw_stats, 0, size);
+	ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
+				       &esw_stats.rx);
+	if (ret)
+		return ret;
+
+	ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
+				       &esw_stats.tx);
+	if (ret)
+		return ret;
+
+	memcpy(buf, &esw_stats, size);
+	return size;
+}
+
+static ssize_t qlcnic_sysfs_clear_esw_stats(struct file *file,
+					    struct kobject *kobj,
+					    struct bin_attribute *attr,
+					    char *buf, loff_t offset,
+					    size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	int ret;
+
+	if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
+		return QL_STATUS_INVALID_PARAM;
+
+	ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
+				     QLCNIC_QUERY_RX_COUNTER);
+	if (ret)
+		return ret;
+
+	ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
+				     QLCNIC_QUERY_TX_COUNTER);
+	if (ret)
+		return ret;
+
+	return size;
+}
+
+static ssize_t qlcnic_sysfs_clear_port_stats(struct file *file,
+					     struct kobject *kobj,
+					     struct bin_attribute *attr,
+					     char *buf, loff_t offset,
+					     size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	int ret;
+
+	if (offset >= QLCNIC_MAX_PCI_FUNC)
+		return QL_STATUS_INVALID_PARAM;
+
+	ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
+				     QLCNIC_QUERY_RX_COUNTER);
+	if (ret)
+		return ret;
+
+	ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
+				     QLCNIC_QUERY_TX_COUNTER);
+	if (ret)
+		return ret;
+
+	return size;
+}
+
+static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
+					    struct kobject *kobj,
+					    struct bin_attribute *attr,
+					    char *buf, loff_t offset,
+					    size_t size)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+	struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC];
+	struct qlcnic_pci_info *pci_info;
+	int i, ret;
+
+	if (size != sizeof(pci_cfg))
+		return QL_STATUS_INVALID_PARAM;
+
+	pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
+	if (!pci_info)
+		return -ENOMEM;
+
+	ret = qlcnic_get_pci_info(adapter, pci_info);
+	if (ret) {
+		kfree(pci_info);
+		return ret;
+	}
+
+	for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
+		pci_cfg[i].pci_func = pci_info[i].id;
+		pci_cfg[i].func_type = pci_info[i].type;
+		pci_cfg[i].port_num = pci_info[i].default_port;
+		pci_cfg[i].min_bw = pci_info[i].tx_min_bw;
+		pci_cfg[i].max_bw = pci_info[i].tx_max_bw;
+		memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN);
+	}
+	memcpy(buf, &pci_cfg, size);
+	kfree(pci_info);
+	return size;
+}
+
+static struct device_attribute dev_attr_bridged_mode = {
+       .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)},
+       .show = qlcnic_show_bridged_mode,
+       .store = qlcnic_store_bridged_mode,
+};
+
+static struct device_attribute dev_attr_diag_mode = {
+	.attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)},
+	.show = qlcnic_show_diag_mode,
+	.store = qlcnic_store_diag_mode,
+};
+
+static struct device_attribute dev_attr_beacon = {
+	.attr = {.name = "beacon", .mode = (S_IRUGO | S_IWUSR)},
+	.show = qlcnic_show_beacon,
+	.store = qlcnic_store_beacon,
+};
+
+static struct bin_attribute bin_attr_crb = {
+	.attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)},
+	.size = 0,
+	.read = qlcnic_sysfs_read_crb,
+	.write = qlcnic_sysfs_write_crb,
+};
+
+static struct bin_attribute bin_attr_mem = {
+	.attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)},
+	.size = 0,
+	.read = qlcnic_sysfs_read_mem,
+	.write = qlcnic_sysfs_write_mem,
+};
+
+static struct bin_attribute bin_attr_npar_config = {
+	.attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)},
+	.size = 0,
+	.read = qlcnic_sysfs_read_npar_config,
+	.write = qlcnic_sysfs_write_npar_config,
+};
+
+static struct bin_attribute bin_attr_pci_config = {
+	.attr = {.name = "pci_config", .mode = (S_IRUGO | S_IWUSR)},
+	.size = 0,
+	.read = qlcnic_sysfs_read_pci_config,
+	.write = NULL,
+};
+
+static struct bin_attribute bin_attr_port_stats = {
+	.attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)},
+	.size = 0,
+	.read = qlcnic_sysfs_get_port_stats,
+	.write = qlcnic_sysfs_clear_port_stats,
+};
+
+static struct bin_attribute bin_attr_esw_stats = {
+	.attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)},
+	.size = 0,
+	.read = qlcnic_sysfs_get_esw_stats,
+	.write = qlcnic_sysfs_clear_esw_stats,
+};
+
+static struct bin_attribute bin_attr_esw_config = {
+	.attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)},
+	.size = 0,
+	.read = qlcnic_sysfs_read_esw_config,
+	.write = qlcnic_sysfs_write_esw_config,
+};
+
+static struct bin_attribute bin_attr_pm_config = {
+	.attr = {.name = "pm_config", .mode = (S_IRUGO | S_IWUSR)},
+	.size = 0,
+	.read = qlcnic_sysfs_read_pm_config,
+	.write = qlcnic_sysfs_write_pm_config,
+};
+
+void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)
+{
+	struct device *dev = &adapter->pdev->dev;
+
+	if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
+		if (device_create_file(dev, &dev_attr_bridged_mode))
+			dev_warn(dev,
+				 "failed to create bridged_mode sysfs entry\n");
+}
+
+void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter)
+{
+	struct device *dev = &adapter->pdev->dev;
+
+	if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
+		device_remove_file(dev, &dev_attr_bridged_mode);
+}
+
+void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
+{
+	struct device *dev = &adapter->pdev->dev;
+	u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+
+	if (device_create_bin_file(dev, &bin_attr_port_stats))
+		dev_info(dev, "failed to create port stats sysfs entry");
+
+	if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
+		return;
+	if (device_create_file(dev, &dev_attr_diag_mode))
+		dev_info(dev, "failed to create diag_mode sysfs entry\n");
+	if (device_create_bin_file(dev, &bin_attr_crb))
+		dev_info(dev, "failed to create crb sysfs entry\n");
+	if (device_create_bin_file(dev, &bin_attr_mem))
+		dev_info(dev, "failed to create mem sysfs entry\n");
+
+	if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
+		return;
+
+	if (device_create_bin_file(dev, &bin_attr_pci_config))
+		dev_info(dev, "failed to create pci config sysfs entry");
+	if (device_create_file(dev, &dev_attr_beacon))
+		dev_info(dev, "failed to create beacon sysfs entry");
+
+	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+		return;
+	if (device_create_bin_file(dev, &bin_attr_esw_config))
+		dev_info(dev, "failed to create esw config sysfs entry");
+	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+		return;
+	if (device_create_bin_file(dev, &bin_attr_npar_config))
+		dev_info(dev, "failed to create npar config sysfs entry");
+	if (device_create_bin_file(dev, &bin_attr_pm_config))
+		dev_info(dev, "failed to create pm config sysfs entry");
+	if (device_create_bin_file(dev, &bin_attr_esw_stats))
+		dev_info(dev, "failed to create eswitch stats sysfs entry");
+}
+
+void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
+{
+	struct device *dev = &adapter->pdev->dev;
+	u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+
+	device_remove_bin_file(dev, &bin_attr_port_stats);
+
+	if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
+		return;
+	device_remove_file(dev, &dev_attr_diag_mode);
+	device_remove_bin_file(dev, &bin_attr_crb);
+	device_remove_bin_file(dev, &bin_attr_mem);
+	if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
+		return;
+	device_remove_bin_file(dev, &bin_attr_pci_config);
+	device_remove_file(dev, &dev_attr_beacon);
+	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+		return;
+	device_remove_bin_file(dev, &bin_attr_esw_config);
+	if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+		return;
+	device_remove_bin_file(dev, &bin_attr_npar_config);
+	device_remove_bin_file(dev, &bin_attr_pm_config);
+	device_remove_bin_file(dev, &bin_attr_esw_stats);
+}
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
index 58185b6..10093f0 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
@@ -86,7 +86,7 @@ exit:
 }
 
 /* Read out the SERDES registers */
-static int ql_read_serdes_reg(struct ql_adapter *qdev, u32 reg, u32 * data)
+static int ql_read_serdes_reg(struct ql_adapter *qdev, u32 reg, u32 *data)
 {
 	int status;
 
@@ -364,7 +364,7 @@ exit:
 /* Read the 400 xgmac control/statistics registers
  * skipping unused locations.
  */
-static int ql_get_xgmac_regs(struct ql_adapter *qdev, u32 * buf,
+static int ql_get_xgmac_regs(struct ql_adapter *qdev, u32 *buf,
 					unsigned int other_function)
 {
 	int status = 0;
@@ -405,7 +405,7 @@ static int ql_get_xgmac_regs(struct ql_adapter *qdev, u32 * buf,
 	return status;
 }
 
-static int ql_get_ets_regs(struct ql_adapter *qdev, u32 * buf)
+static int ql_get_ets_regs(struct ql_adapter *qdev, u32 *buf)
 {
 	int status = 0;
 	int i;
@@ -423,7 +423,7 @@ static int ql_get_ets_regs(struct ql_adapter *qdev, u32 * buf)
 	return status;
 }
 
-static void ql_get_intr_states(struct ql_adapter *qdev, u32 * buf)
+static void ql_get_intr_states(struct ql_adapter *qdev, u32 *buf)
 {
 	int i;
 
@@ -434,7 +434,7 @@ static void ql_get_intr_states(struct ql_adapter *qdev, u32 * buf)
 	}
 }
 
-static int ql_get_cam_entries(struct ql_adapter *qdev, u32 * buf)
+static int ql_get_cam_entries(struct ql_adapter *qdev, u32 *buf)
 {
 	int i, status;
 	u32 value[3];
@@ -471,7 +471,7 @@ err:
 	return status;
 }
 
-static int ql_get_routing_entries(struct ql_adapter *qdev, u32 * buf)
+static int ql_get_routing_entries(struct ql_adapter *qdev, u32 *buf)
 {
 	int status;
 	u32 value, i;
@@ -496,7 +496,7 @@ err:
 }
 
 /* Read the MPI Processor shadow registers */
-static int ql_get_mpi_shadow_regs(struct ql_adapter *qdev, u32 * buf)
+static int ql_get_mpi_shadow_regs(struct ql_adapter *qdev, u32 *buf)
 {
 	u32 i;
 	int status;
@@ -515,7 +515,7 @@ end:
 }
 
 /* Read the MPI Processor core registers */
-static int ql_get_mpi_regs(struct ql_adapter *qdev, u32 * buf,
+static int ql_get_mpi_regs(struct ql_adapter *qdev, u32 *buf,
 				u32 offset, u32 count)
 {
 	int i, status = 0;
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index b01f83a..6cb96b4 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -648,6 +648,7 @@ static void cp_tx (struct cp_private *cp)
 {
 	unsigned tx_head = cp->tx_head;
 	unsigned tx_tail = cp->tx_tail;
+	unsigned bytes_compl = 0, pkts_compl = 0;
 
 	while (tx_tail != tx_head) {
 		struct cp_desc *txd = cp->tx_ring + tx_tail;
@@ -666,6 +667,9 @@ static void cp_tx (struct cp_private *cp)
 				 le32_to_cpu(txd->opts1) & 0xffff,
 				 PCI_DMA_TODEVICE);
 
+		bytes_compl += skb->len;
+		pkts_compl++;
+
 		if (status & LastFrag) {
 			if (status & (TxError | TxFIFOUnder)) {
 				netif_dbg(cp, tx_err, cp->dev,
@@ -697,6 +701,7 @@ static void cp_tx (struct cp_private *cp)
 
 	cp->tx_tail = tx_tail;
 
+	netdev_completed_queue(cp->dev, pkts_compl, bytes_compl);
 	if (TX_BUFFS_AVAIL(cp) > (MAX_SKB_FRAGS + 1))
 		netif_wake_queue(cp->dev);
 }
@@ -843,6 +848,8 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 		wmb();
 	}
 	cp->tx_head = entry;
+
+	netdev_sent_queue(dev, skb->len);
 	netif_dbg(cp, tx_queued, cp->dev, "tx queued, slot %d, skblen %d\n",
 		  entry, skb->len);
 	if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1))
@@ -937,6 +944,8 @@ static void cp_stop_hw (struct cp_private *cp)
 
 	cp->rx_tail = 0;
 	cp->tx_head = cp->tx_tail = 0;
+
+	netdev_reset_queue(cp->dev);
 }
 
 static void cp_reset_hw (struct cp_private *cp)
@@ -957,8 +966,38 @@ static void cp_reset_hw (struct cp_private *cp)
 
 static inline void cp_start_hw (struct cp_private *cp)
 {
+	dma_addr_t ring_dma;
+
 	cpw16(CpCmd, cp->cpcmd);
+
+	/*
+	 * These (at least TxRingAddr) need to be configured after the
+	 * corresponding bits in CpCmd are enabled. Datasheet v1.6 §6.33
+	 * (C+ Command Register) recommends that these and more be configured
+	 * *after* the [RT]xEnable bits in CpCmd are set. And on some hardware
+	 * it's been observed that the TxRingAddr is actually reset to garbage
+	 * when C+ mode Tx is enabled in CpCmd.
+	 */
+	cpw32_f(HiTxRingAddr, 0);
+	cpw32_f(HiTxRingAddr + 4, 0);
+
+	ring_dma = cp->ring_dma;
+	cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
+	cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
+
+	ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
+	cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
+	cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
+
+	/*
+	 * Strictly speaking, the datasheet says this should be enabled
+	 * *before* setting the descriptor addresses. But what, then, would
+	 * prevent it from doing DMA to random unconfigured addresses?
+	 * This variant appears to work fine.
+	 */
 	cpw8(Cmd, RxOn | TxOn);
+
+	netdev_reset_queue(cp->dev);
 }
 
 static void cp_enable_irq(struct cp_private *cp)
@@ -969,7 +1008,6 @@ static void cp_enable_irq(struct cp_private *cp)
 static void cp_init_hw (struct cp_private *cp)
 {
 	struct net_device *dev = cp->dev;
-	dma_addr_t ring_dma;
 
 	cp_reset_hw(cp);
 
@@ -992,17 +1030,6 @@ static void cp_init_hw (struct cp_private *cp)
 
 	cpw8(Config5, cpr8(Config5) & PMEStatus);
 
-	cpw32_f(HiTxRingAddr, 0);
-	cpw32_f(HiTxRingAddr + 4, 0);
-
-	ring_dma = cp->ring_dma;
-	cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
-	cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
-
-	ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
-	cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
-	cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
-
 	cpw16(MultiIntr, 0);
 
 	cpw8_f(Cfg9346, Cfg9346_Lock);
@@ -1192,6 +1219,7 @@ static void cp_tx_timeout(struct net_device *dev)
 	cp_clean_rings(cp);
 	rc = cp_init_rings(cp);
 	cp_start_hw(cp);
+	cp_enable_irq(cp);
 
 	netif_wake_queue(dev);
 
diff --git a/drivers/net/ethernet/realtek/Kconfig b/drivers/net/ethernet/realtek/Kconfig
index 5821966..783fa8b 100644
--- a/drivers/net/ethernet/realtek/Kconfig
+++ b/drivers/net/ethernet/realtek/Kconfig
@@ -34,8 +34,8 @@ config ATP
 	  will be called atp.
 
 config 8139CP
-	tristate "RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support (EXPERIMENTAL)"
-	depends on PCI && EXPERIMENTAL
+	tristate "RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support"
+	depends on PCI
 	select CRC32
 	select NET_CORE
 	select MII
diff --git a/drivers/net/ethernet/realtek/atp.c b/drivers/net/ethernet/realtek/atp.c
index e02f04d..9f2d416 100644
--- a/drivers/net/ethernet/realtek/atp.c
+++ b/drivers/net/ethernet/realtek/atp.c
@@ -175,8 +175,7 @@ struct net_local {
     unsigned int tx_unit_busy:1;
     unsigned char re_tx,	/* Number of packet retransmissions. */
 		addr_mode,		/* Current Rx filter e.g. promiscuous, etc. */
-		pac_cnt_in_tx_buf,
-		chip_type;
+		pac_cnt_in_tx_buf;
 };
 
 /* This code, written by wwc@super.org, resets the adapter every
@@ -339,7 +338,6 @@ static int __init atp_probe1(long ioaddr)
 	write_reg_high(ioaddr, CMR1, CMR1h_RESET | CMR1h_MUX);
 
 	lp = netdev_priv(dev);
-	lp->chip_type = RTL8002;
 	lp->addr_mode = CMR2h_Normal;
 	spin_lock_init(&lp->lock);
 
@@ -852,7 +850,7 @@ net_close(struct net_device *dev)
  *	Set or clear the multicast filter for this adapter.
  */
 
-static void set_rx_mode_8002(struct net_device *dev)
+static void set_rx_mode(struct net_device *dev)
 {
 	struct net_local *lp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
@@ -864,58 +862,6 @@ static void set_rx_mode_8002(struct net_device *dev)
 	write_reg_high(ioaddr, CMR2, lp->addr_mode);
 }
 
-static void set_rx_mode_8012(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	unsigned char new_mode, mc_filter[8]; /* Multicast hash filter */
-	int i;
-
-	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
-		new_mode = CMR2h_PROMISC;
-	} else if ((netdev_mc_count(dev) > 1000) ||
-		   (dev->flags & IFF_ALLMULTI)) {
-		/* Too many to filter perfectly -- accept all multicasts. */
-		memset(mc_filter, 0xff, sizeof(mc_filter));
-		new_mode = CMR2h_Normal;
-	} else {
-		struct netdev_hw_addr *ha;
-
-		memset(mc_filter, 0, sizeof(mc_filter));
-		netdev_for_each_mc_addr(ha, dev) {
-			int filterbit = ether_crc_le(ETH_ALEN, ha->addr) & 0x3f;
-			mc_filter[filterbit >> 5] |= 1 << (filterbit & 31);
-		}
-		new_mode = CMR2h_Normal;
-	}
-	lp->addr_mode = new_mode;
-    write_reg(ioaddr, CMR2, CMR2_IRQOUT | 0x04); /* Switch to page 1. */
-    for (i = 0; i < 8; i++)
-		write_reg_byte(ioaddr, i, mc_filter[i]);
-	if (net_debug > 2 || 1) {
-		lp->addr_mode = 1;
-		printk(KERN_DEBUG "%s: Mode %d, setting multicast filter to",
-			   dev->name, lp->addr_mode);
-		for (i = 0; i < 8; i++)
-			printk(" %2.2x", mc_filter[i]);
-		printk(".\n");
-	}
-
-	write_reg_high(ioaddr, CMR2, lp->addr_mode);
-    write_reg(ioaddr, CMR2, CMR2_IRQOUT); /* Switch back to page 0 */
-}
-
-static void set_rx_mode(struct net_device *dev)
-{
-	struct net_local *lp = netdev_priv(dev);
-
-	if (lp->chip_type == RTL8002)
-		return set_rx_mode_8002(dev);
-	else
-		return set_rx_mode_8012(dev);
-}
-
-
 static int __init atp_init_module(void) {
 	if (debug)					/* Emit version even if no cards detected. */
 		printk(KERN_INFO "%s", version);
diff --git a/drivers/net/ethernet/realtek/atp.h b/drivers/net/ethernet/realtek/atp.h
index 0edc642..040b137 100644
--- a/drivers/net/ethernet/realtek/atp.h
+++ b/drivers/net/ethernet/realtek/atp.h
@@ -16,8 +16,6 @@ struct rx_header {
 #define PAR_STATUS	1
 #define PAR_CONTROL 2
 
-enum chip_type { RTL8002, RTL8012 };
-
 #define Ctrl_LNibRead	0x08	/* LP_PSELECP */
 #define Ctrl_HNibRead	0
 #define Ctrl_LNibWrite	0x08	/* LP_PSELECP */
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 927aa33..248f883 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -78,24 +78,18 @@ static const int multicast_filter_limit = 32;
 
 #define MAX_READ_REQUEST_SHIFT	12
 #define TX_DMA_BURST	7	/* Maximum PCI burst, '7' is unlimited */
-#define SafeMtu		0x1c20	/* ... actually life sucks beyond ~7k */
 #define InterFrameGap	0x03	/* 3 means InterFrameGap = the shortest one */
 
 #define R8169_REGS_SIZE		256
 #define R8169_NAPI_WEIGHT	64
 #define NUM_TX_DESC	64	/* Number of Tx descriptor registers */
 #define NUM_RX_DESC	256	/* Number of Rx descriptor registers */
-#define RX_BUF_SIZE	1536	/* Rx Buffer size */
 #define R8169_TX_RING_BYTES	(NUM_TX_DESC * sizeof(struct TxDesc))
 #define R8169_RX_RING_BYTES	(NUM_RX_DESC * sizeof(struct RxDesc))
 
 #define RTL8169_TX_TIMEOUT	(6*HZ)
 #define RTL8169_PHY_TIMEOUT	(10*HZ)
 
-#define RTL_EEPROM_SIG		cpu_to_le32(0x8129)
-#define RTL_EEPROM_SIG_MASK	cpu_to_le32(0xffff)
-#define RTL_EEPROM_SIG_ADDR	0x0000
-
 /* write/read MMIO register */
 #define RTL_W8(reg, val8)	writeb ((val8), ioaddr + (reg))
 #define RTL_W16(reg, val16)	writew ((val16), ioaddr + (reg))
@@ -456,6 +450,7 @@ enum rtl8168_registers {
 #define PWM_EN				(1 << 22)
 #define RXDV_GATED_EN			(1 << 19)
 #define EARLY_TALLY_EN			(1 << 16)
+#define FORCE_CLK			(1 << 15) /* force clock request */
 };
 
 enum rtl_register_content {
@@ -519,6 +514,7 @@ enum rtl_register_content {
 	PMEnable	= (1 << 0),	/* Power Management Enable */
 
 	/* Config2 register p. 25 */
+	ClkReqEn	= (1 << 7),	/* Clock Request Enable */
 	MSIEnable	= (1 << 5),	/* 8169 only. Reserved in the 8168. */
 	PCI_Clock_66MHz = 0x01,
 	PCI_Clock_33MHz = 0x00,
@@ -539,6 +535,7 @@ enum rtl_register_content {
 	Spi_en		= (1 << 3),
 	LanWake		= (1 << 1),	/* LanWake enable/disable */
 	PMEStatus	= (1 << 0),	/* PME status can be reset by PCI RST# */
+	ASPM_en		= (1 << 0),	/* ASPM enable */
 
 	/* TBICSR p.28 */
 	TBIReset	= 0x80000000,
@@ -687,6 +684,7 @@ enum features {
 	RTL_FEATURE_WOL		= (1 << 0),
 	RTL_FEATURE_MSI		= (1 << 1),
 	RTL_FEATURE_GMII	= (1 << 2),
+	RTL_FEATURE_FW_LOADED	= (1 << 3),
 };
 
 struct rtl8169_counters {
@@ -1816,8 +1814,7 @@ static int rtl8169_set_features(struct net_device *dev,
 }
 
 
-static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
-				      struct sk_buff *skb)
+static inline u32 rtl8169_tx_vlan_tag(struct sk_buff *skb)
 {
 	return (vlan_tx_tag_present(skb)) ?
 		TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
@@ -2394,8 +2391,10 @@ static void rtl_apply_firmware(struct rtl8169_private *tp)
 	struct rtl_fw *rtl_fw = tp->rtl_fw;
 
 	/* TODO: release firmware once rtl_phy_write_fw signals failures. */
-	if (!IS_ERR_OR_NULL(rtl_fw))
+	if (!IS_ERR_OR_NULL(rtl_fw)) {
 		rtl_phy_write_fw(tp, rtl_fw);
+		tp->features |= RTL_FEATURE_FW_LOADED;
+	}
 }
 
 static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
@@ -2406,6 +2405,31 @@ static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
 		rtl_apply_firmware(tp);
 }
 
+static void r810x_aldps_disable(struct rtl8169_private *tp)
+{
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_writephy(tp, 0x18, 0x0310);
+	msleep(100);
+}
+
+static void r810x_aldps_enable(struct rtl8169_private *tp)
+{
+	if (!(tp->features & RTL_FEATURE_FW_LOADED))
+		return;
+
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_writephy(tp, 0x18, 0x8310);
+}
+
+static void r8168_aldps_enable_1(struct rtl8169_private *tp)
+{
+	if (!(tp->features & RTL_FEATURE_FW_LOADED))
+		return;
+
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_w1w0_phy(tp, 0x15, 0x1000, 0x0000);
+}
+
 static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
@@ -3178,6 +3202,8 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
 	rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
 	rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
 	rtl_writephy(tp, 0x1f, 0x0000);
+
+	r8168_aldps_enable_1(tp);
 }
 
 static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
@@ -3250,6 +3276,8 @@ static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
 	rtl_writephy(tp, 0x05, 0x8b85);
 	rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
 	rtl_writephy(tp, 0x1f, 0x0000);
+
+	r8168_aldps_enable_1(tp);
 }
 
 static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
@@ -3257,6 +3285,8 @@ static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
 	rtl_apply_firmware(tp);
 
 	rtl8168f_hw_phy_config(tp);
+
+	r8168_aldps_enable_1(tp);
 }
 
 static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
@@ -3354,6 +3384,8 @@ static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
 	rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
 	rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
 	rtl_writephy(tp, 0x1f, 0x0000);
+
+	r8168_aldps_enable_1(tp);
 }
 
 static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
@@ -3439,21 +3471,19 @@ static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
 	};
 
 	/* Disable ALDPS before ram code */
-	rtl_writephy(tp, 0x1f, 0x0000);
-	rtl_writephy(tp, 0x18, 0x0310);
-	msleep(100);
+	r810x_aldps_disable(tp);
 
 	rtl_apply_firmware(tp);
 
 	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+	r810x_aldps_enable(tp);
 }
 
 static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
 {
 	/* Disable ALDPS before setting firmware */
-	rtl_writephy(tp, 0x1f, 0x0000);
-	rtl_writephy(tp, 0x18, 0x0310);
-	msleep(20);
+	r810x_aldps_disable(tp);
 
 	rtl_apply_firmware(tp);
 
@@ -3463,6 +3493,8 @@ static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
 	rtl_writephy(tp, 0x10, 0x401f);
 	rtl_writephy(tp, 0x19, 0x7030);
 	rtl_writephy(tp, 0x1f, 0x0000);
+
+	r810x_aldps_enable(tp);
 }
 
 static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
@@ -3475,9 +3507,7 @@ static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
 	};
 
 	/* Disable ALDPS before ram code */
-	rtl_writephy(tp, 0x1f, 0x0000);
-	rtl_writephy(tp, 0x18, 0x0310);
-	msleep(100);
+	r810x_aldps_disable(tp);
 
 	rtl_apply_firmware(tp);
 
@@ -3485,6 +3515,8 @@ static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
 	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 
 	rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+
+	r810x_aldps_enable(tp);
 }
 
 static void rtl_hw_phy_config(struct net_device *dev)
@@ -5015,8 +5047,6 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
 
 	RTL_W8(MaxTxPacketSize, EarlySize);
 
-	rtl_disable_clock_request(pdev);
-
 	RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
 	RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
 
@@ -5025,7 +5055,8 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
 
 	RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
 	RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
-	RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
+	RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
+	RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
 }
 
 static void rtl_hw_start_8168f(struct rtl8169_private *tp)
@@ -5050,13 +5081,12 @@ static void rtl_hw_start_8168f(struct rtl8169_private *tp)
 
 	RTL_W8(MaxTxPacketSize, EarlySize);
 
-	rtl_disable_clock_request(pdev);
-
 	RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
 	RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
 	RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
-	RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
-	RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
+	RTL_W32(MISC, RTL_R32(MISC) | PWM_EN | FORCE_CLK);
+	RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
+	RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
 }
 
 static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
@@ -5113,8 +5143,10 @@ static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
 	rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
 
 	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
-	RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN);
+	RTL_W32(MISC, (RTL_R32(MISC) | FORCE_CLK) & ~RXDV_GATED_EN);
 	RTL_W8(MaxTxPacketSize, EarlySize);
+	RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
+	RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
 
 	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
 	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
@@ -5330,6 +5362,9 @@ static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
 
 	RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
 	RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
+	RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
+	RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
+	RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
 
 	rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
 }
@@ -5355,6 +5390,9 @@ static void rtl_hw_start_8402(struct rtl8169_private *tp)
 
 	RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
 	RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
+	RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
+	RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
+	RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
 
 	rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402));
 
@@ -5376,7 +5414,10 @@ static void rtl_hw_start_8106(struct rtl8169_private *tp)
 	/* Force LAN exit from ASPM if Rx/Tx are not idle */
 	RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
 
-	RTL_W32(MISC, (RTL_R32(MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN);
+	RTL_W32(MISC,
+		(RTL_R32(MISC) | DISABLE_LAN_EN | FORCE_CLK) & ~EARLY_TALLY_EN);
+	RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
+	RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
 	RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
 	RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
 }
@@ -5774,7 +5815,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
 	tp->tx_skb[entry].len = len;
 	txd->addr = cpu_to_le64(mapping);
 
-	opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb));
+	opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
 	opts[0] = DescOwn;
 
 	rtl8169_tso_csum(tp, skb, opts);
@@ -6992,15 +7033,4 @@ static struct pci_driver rtl8169_pci_driver = {
 	.driver.pm	= RTL8169_PM_OPS,
 };
 
-static int __init rtl8169_init_module(void)
-{
-	return pci_register_driver(&rtl8169_pci_driver);
-}
-
-static void __exit rtl8169_cleanup_module(void)
-{
-	pci_unregister_driver(&rtl8169_pci_driver);
-}
-
-module_init(rtl8169_init_module);
-module_exit(rtl8169_cleanup_module);
+module_pci_driver(rtl8169_pci_driver);
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index c8bfea0..3d70586 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -2286,7 +2286,7 @@ static int sh_mdio_init(struct net_device *ndev, int id,
 	for (i = 0; i < PHY_MAX_ADDR; i++)
 		mdp->mii_bus->irq[i] = PHY_POLL;
 
-	/* regist mdio bus */
+	/* register mdio bus */
 	ret = mdiobus_register(mdp->mii_bus);
 	if (ret)
 		goto out_free_irq;
diff --git a/drivers/net/ethernet/seeq/ether3.c b/drivers/net/ethernet/seeq/ether3.c
index 6a40dd0..72a0174 100644
--- a/drivers/net/ethernet/seeq/ether3.c
+++ b/drivers/net/ethernet/seeq/ether3.c
@@ -399,12 +399,6 @@ ether3_probe_bus_16(struct net_device *dev, int val)
 static int
 ether3_open(struct net_device *dev)
 {
-	if (!is_valid_ether_addr(dev->dev_addr)) {
-		printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
-			dev->name);
-		return -EINVAL;
-	}
-
 	if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev))
 		return -EAGAIN;
 
diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
index 25906c1..435b4f1 100644
--- a/drivers/net/ethernet/sfc/Kconfig
+++ b/drivers/net/ethernet/sfc/Kconfig
@@ -1,10 +1,11 @@
 config SFC
 	tristate "Solarflare SFC4000/SFC9000-family support"
-	depends on PCI && INET
+	depends on PCI
 	select MDIO
 	select CRC32
 	select I2C
 	select I2C_ALGOBIT
+	select PTP_1588_CLOCK
 	---help---
 	  This driver supports 10-gigabit Ethernet cards based on
 	  the Solarflare SFC4000 and SFC9000-family controllers.
@@ -34,10 +35,3 @@ config SFC_SRIOV
 	  This enables support for the SFC9000 I/O Virtualization
 	  features, allowing accelerated network performance in
 	  virtualized environments.
-config SFC_PTP
-	bool "Solarflare SFC9000-family PTP support"
-	depends on SFC && PTP_1588_CLOCK && !(SFC=y && PTP_1588_CLOCK=m)
-	default y
-	---help---
-	  This enables support for the Precision Time Protocol (PTP)
-	  on SFC9000-family NICs
diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
index e11f2ec..945bf06 100644
--- a/drivers/net/ethernet/sfc/Makefile
+++ b/drivers/net/ethernet/sfc/Makefile
@@ -2,9 +2,8 @@ sfc-y			+= efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \
 			   falcon_xmac.o mcdi_mac.o \
 			   selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
 			   tenxpress.o txc43128_phy.o falcon_boards.o \
-			   mcdi.o mcdi_phy.o mcdi_mon.o
+			   mcdi.o mcdi_phy.o mcdi_mon.o ptp.o
 sfc-$(CONFIG_SFC_MTD)	+= mtd.o
 sfc-$(CONFIG_SFC_SRIOV)	+= siena_sriov.o
-sfc-$(CONFIG_SFC_PTP)	+= ptp.o
 
 obj-$(CONFIG_SFC)	+= sfc.o
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 576a310..2487f58 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -868,9 +868,7 @@ struct efx_nic {
 	struct work_struct peer_work;
 #endif
 
-#ifdef CONFIG_SFC_PTP
 	struct efx_ptp_data *ptp_data;
-#endif
 
 	/* The following fields may be written more often */
 
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index 438cef1..7a9647a 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -252,7 +252,6 @@ extern int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf,
 				     bool spoofchk);
 
 struct ethtool_ts_info;
-#ifdef CONFIG_SFC_PTP
 extern void efx_ptp_probe(struct efx_nic *efx);
 extern int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd);
 extern int efx_ptp_get_ts_info(struct net_device *net_dev,
@@ -260,31 +259,6 @@ extern int efx_ptp_get_ts_info(struct net_device *net_dev,
 extern bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
 extern int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
 extern void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev);
-#else
-static inline void efx_ptp_probe(struct efx_nic *efx) {}
-static inline int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd)
-{
-	return -EOPNOTSUPP;
-}
-static inline int efx_ptp_get_ts_info(struct net_device *net_dev,
-				      struct ethtool_ts_info *ts_info)
-{
-	ts_info->so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
-				    SOF_TIMESTAMPING_RX_SOFTWARE);
-	ts_info->phc_index = -1;
-
-	return 0;
-}
-static inline bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
-{
-	return false;
-}
-static inline int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
-{
-	return NETDEV_TX_OK;
-}
-static inline void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev) {}
-#endif
 
 extern const struct efx_nic_type falcon_a1_nic_type;
 extern const struct efx_nic_type falcon_b0_nic_type;
diff --git a/drivers/net/ethernet/silan/Kconfig b/drivers/net/ethernet/silan/Kconfig
index ae1ce17..3409b3f 100644
--- a/drivers/net/ethernet/silan/Kconfig
+++ b/drivers/net/ethernet/silan/Kconfig
@@ -5,7 +5,7 @@
 config NET_VENDOR_SILAN
 	bool "Silan devices"
 	default y
-	depends on PCI && EXPERIMENTAL
+	depends on PCI
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y
 	  and read the Ethernet-HOWTO, available from
@@ -19,8 +19,8 @@ config NET_VENDOR_SILAN
 if NET_VENDOR_SILAN
 
 config SC92031
-	tristate "Silan SC92031 PCI Fast Ethernet Adapter driver (EXPERIMENTAL)"
-	depends on PCI && EXPERIMENTAL
+	tristate "Silan SC92031 PCI Fast Ethernet Adapter driver"
+	depends on PCI
 	select CRC32
 	---help---
 	  This is a driver for the Fast Ethernet PCI network cards based on
diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
index 8d15f7a..990f574 100644
--- a/drivers/net/ethernet/smsc/smc911x.c
+++ b/drivers/net/ethernet/smsc/smc911x.c
@@ -1400,16 +1400,6 @@ smc911x_open(struct net_device *dev)
 
 	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
 
-	/*
-	 * Check that the address is valid.  If its not, refuse
-	 * to bring the device up.	 The user must specify an
-	 * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
-	 */
-	if (!is_valid_ether_addr(dev->dev_addr)) {
-		PRINTK("%s: no valid ethernet hw addr\n", __func__);
-		return -EINVAL;
-	}
-
 	/* reset the hardware */
 	smc911x_reset(dev);
 
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index 318adc9..f516e5a 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -1474,16 +1474,6 @@ smc_open(struct net_device *dev)
 
 	DBG(2, "%s: %s\n", dev->name, __func__);
 
-	/*
-	 * Check that the address is valid.  If its not, refuse
-	 * to bring the device up.  The user must specify an
-	 * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
-	 */
-	if (!is_valid_ether_addr(dev->dev_addr)) {
-		PRINTK("%s: no valid ethernet hw addr\n", __func__);
-		return -EINVAL;
-	}
-
 	/* Setup the default Register Modes */
 	lp->tcr_cur_mode = TCR_DEFAULT;
 	lp->rcr_cur_mode = RCR_DEFAULT;
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index c53c0f4..cc02562 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -1463,11 +1463,6 @@ static int smsc911x_open(struct net_device *dev)
 		return -EAGAIN;
 	}
 
-	if (!is_valid_ether_addr(dev->dev_addr)) {
-		SMSC_WARN(pdata, hw, "dev_addr is not a valid MAC address");
-		return -EADDRNOTAVAIL;
-	}
-
 	/* Reset the LAN911x */
 	if (smsc911x_soft_reset(pdata)) {
 		SMSC_WARN(pdata, hw, "soft reset failed");
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 9f44827..1164930 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -54,31 +54,6 @@ config STMMAC_DA
 	  By default, the DMA arbitration scheme is based on Round-robin
 	  (rx:tx priority is 1:1).
 
-config STMMAC_TIMER
-	bool "STMMAC Timer optimisation"
-	default n
-	depends on RTC_HCTOSYS_DEVICE
-	---help---
-	  Use an external timer for mitigating the number of network
-	  interrupts. Currently, for SH architectures, it is possible
-	  to use the TMU channel 2 and the SH-RTC device.
-
-choice
-        prompt "Select Timer device"
-        depends on STMMAC_TIMER
-
-config STMMAC_TMU_TIMER
-        bool "TMU channel 2"
-        depends on CPU_SH4
-	---help---
-
-config STMMAC_RTC_TIMER
-        bool "Real time clock"
-        depends on RTC_CLASS
-	---help---
-
-endchoice
-
 choice
 	prompt "Select the DMA TX/RX descriptor operating modes"
 	depends on STMMAC_ETH
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index bc965ac..c8e8ea6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -1,5 +1,4 @@
 obj-$(CONFIG_STMMAC_ETH) += stmmac.o
-stmmac-$(CONFIG_STMMAC_TIMER) += stmmac_timer.o
 stmmac-$(CONFIG_STMMAC_RING) += ring_mode.o
 stmmac-$(CONFIG_STMMAC_CHAINED) += chain_mode.o
 stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 719be39..186d148 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -48,6 +48,10 @@
 #define CHIP_DBG(fmt, args...)  do { } while (0)
 #endif
 
+/* Synopsys Core versions */
+#define	DWMAC_CORE_3_40	0x34
+#define	DWMAC_CORE_3_50	0x35
+
 #undef FRAME_FILTER_DEBUG
 /* #define FRAME_FILTER_DEBUG */
 
@@ -81,7 +85,7 @@ struct stmmac_extra_stats {
 	unsigned long rx_missed_cntr;
 	unsigned long rx_overflow_cntr;
 	unsigned long rx_vlan;
-	/* Tx/Rx IRQ errors */
+	/* Tx/Rx IRQ error info */
 	unsigned long tx_undeflow_irq;
 	unsigned long tx_process_stopped_irq;
 	unsigned long tx_jabber_irq;
@@ -91,18 +95,23 @@ struct stmmac_extra_stats {
 	unsigned long rx_watchdog_irq;
 	unsigned long tx_early_irq;
 	unsigned long fatal_bus_error_irq;
-	/* Extra info */
+	/* Tx/Rx IRQ Events */
+	unsigned long rx_early_irq;
 	unsigned long threshold;
 	unsigned long tx_pkt_n;
 	unsigned long rx_pkt_n;
-	unsigned long poll_n;
-	unsigned long sched_timer_n;
 	unsigned long normal_irq_n;
+	unsigned long rx_normal_irq_n;
+	unsigned long napi_poll;
+	unsigned long tx_normal_irq_n;
+	unsigned long tx_clean;
+	unsigned long tx_reset_ic_bit;
+	unsigned long irq_receive_pmt_irq_n;
+	/* MMC info */
 	unsigned long mmc_tx_irq_n;
 	unsigned long mmc_rx_irq_n;
 	unsigned long mmc_rx_csum_offload_irq_n;
 	/* EEE */
-	unsigned long irq_receive_pmt_irq_n;
 	unsigned long irq_tx_path_in_lpi_mode_n;
 	unsigned long irq_tx_path_exit_lpi_mode_n;
 	unsigned long irq_rx_path_in_lpi_mode_n;
@@ -162,6 +171,15 @@ struct stmmac_extra_stats {
 #define DMA_HW_FEAT_ACTPHYIF	0x70000000 /* Active/selected PHY interface */
 #define DEFAULT_DMA_PBL		8
 
+/* Max/Min RI Watchdog Timer count value */
+#define MAX_DMA_RIWT		0xff
+#define MIN_DMA_RIWT		0x20
+/* Tx coalesce parameters */
+#define STMMAC_COAL_TX_TIMER	40000
+#define STMMAC_MAX_COAL_TX_TICK	100000
+#define STMMAC_TX_MAX_FRAMES	256
+#define STMMAC_TX_FRAMES	64
+
 enum rx_frame_status { /* IPC status */
 	good_frame = 0,
 	discard_frame = 1,
@@ -169,10 +187,11 @@ enum rx_frame_status { /* IPC status */
 	llc_snap = 4,
 };
 
-enum tx_dma_irq_status {
-	tx_hard_error = 1,
-	tx_hard_error_bump_tc = 2,
-	handle_tx_rx = 3,
+enum dma_irq_status {
+	tx_hard_error = 0x1,
+	tx_hard_error_bump_tc = 0x2,
+	handle_rx = 0x4,
+	handle_tx = 0x8,
 };
 
 enum core_specific_irq_mask {
@@ -296,6 +315,8 @@ struct stmmac_dma_ops {
 			      struct stmmac_extra_stats *x);
 	/* If supported then get the optional core features */
 	unsigned int (*get_hw_feature) (void __iomem *ioaddr);
+	/* Program the HW RX Watchdog */
+	void (*rx_watchdog) (void __iomem *ioaddr, u32 riwt);
 };
 
 struct stmmac_ops {
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index 0e4cace..7ad56af 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -230,8 +230,5 @@ enum rtc_control {
 #define GMAC_MMC_TX_INTR   0x108
 #define GMAC_MMC_RX_CSUM_OFFLOAD   0x208
 
-/* Synopsys Core versions */
-#define	DWMAC_CORE_3_40	0x34
-
 extern const struct stmmac_dma_ops dwmac1000_dma_ops;
 #endif /* __DWMAC1000_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index 0335000..bf83c03 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -174,6 +174,11 @@ static unsigned int dwmac1000_get_hw_feature(void __iomem *ioaddr)
 	return readl(ioaddr + DMA_HW_FEATURE);
 }
 
+static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt)
+{
+	writel(riwt, ioaddr + DMA_RX_WATCHDOG);
+}
+
 const struct stmmac_dma_ops dwmac1000_dma_ops = {
 	.init = dwmac1000_dma_init,
 	.dump_regs = dwmac1000_dump_dma_regs,
@@ -187,4 +192,5 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = {
 	.stop_rx = dwmac_dma_stop_rx,
 	.dma_interrupt = dwmac_dma_interrupt,
 	.get_hw_feature = dwmac1000_get_hw_feature,
+	.rx_watchdog = dwmac1000_rx_watchdog,
 };
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index e49c9a0..807f303 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -35,7 +35,10 @@
 #define DMA_CONTROL		0x00001018	/* Ctrl (Operational Mode) */
 #define DMA_INTR_ENA		0x0000101c	/* Interrupt Enable */
 #define DMA_MISSED_FRAME_CTR	0x00001020	/* Missed Frame Counter */
-#define DMA_AXI_BUS_MODE       0x00001028      /* AXI Bus Mode */
+/* Rx watchdog register */
+#define DMA_RX_WATCHDOG		0x00001024
+/* AXI Bus Mode */
+#define DMA_AXI_BUS_MODE	0x00001028
 #define DMA_CUR_TX_BUF_ADDR	0x00001050	/* Current Host Tx Buffer */
 #define DMA_CUR_RX_BUF_ADDR	0x00001054	/* Current Host Rx Buffer */
 #define DMA_HW_FEATURE		0x00001058	/* HW Feature Register */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index 4e0e18a..491d7e9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -204,16 +204,28 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
 		}
 	}
 	/* TX/RX NORMAL interrupts */
-	if (intr_status & DMA_STATUS_NIS) {
+	if (likely(intr_status & DMA_STATUS_NIS)) {
 		x->normal_irq_n++;
-		if (likely((intr_status & DMA_STATUS_RI) ||
-			 (intr_status & (DMA_STATUS_TI))))
-				ret = handle_tx_rx;
+		if (likely(intr_status & DMA_STATUS_RI)) {
+			u32 value = readl(ioaddr + DMA_INTR_ENA);
+			/* to schedule NAPI on real RIE event. */
+			if (likely(value & DMA_INTR_ENA_RIE)) {
+				x->rx_normal_irq_n++;
+				ret |= handle_rx;
+			}
+		}
+		if (likely(intr_status & DMA_STATUS_TI)) {
+			x->tx_normal_irq_n++;
+			ret |= handle_tx;
+		}
+		if (unlikely(intr_status & DMA_STATUS_ERI))
+			x->rx_early_irq++;
 	}
 	/* Optional hardware blocks, interrupts should be disabled */
 	if (unlikely(intr_status &
 		     (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
 		pr_info("%s: unexpected status %08x\n", __func__, intr_status);
+
 	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
 	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 7d51a65..023a4fb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -24,16 +24,13 @@
 #define __STMMAC_H__
 
 #define STMMAC_RESOURCE_NAME   "stmmaceth"
-#define DRV_MODULE_VERSION	"March_2012"
+#define DRV_MODULE_VERSION	"Nov_2012"
 
 #include <linux/clk.h>
 #include <linux/stmmac.h>
 #include <linux/phy.h>
 #include <linux/pci.h>
 #include "common.h"
-#ifdef CONFIG_STMMAC_TIMER
-#include "stmmac_timer.h"
-#endif
 
 struct stmmac_priv {
 	/* Frequently used values are kept adjacent for cache effect */
@@ -77,9 +74,6 @@ struct stmmac_priv {
 	spinlock_t tx_lock;
 	int wolopts;
 	int wol_irq;
-#ifdef CONFIG_STMMAC_TIMER
-	struct stmmac_timer *tm;
-#endif
 	struct plat_stmmacenet_data *plat;
 	struct stmmac_counters mmc;
 	struct dma_features dma_cap;
@@ -93,6 +87,12 @@ struct stmmac_priv {
 	int eee_enabled;
 	int eee_active;
 	int tx_lpi_timer;
+	struct timer_list txtimer;
+	u32 tx_count_frames;
+	u32 tx_coal_frames;
+	u32 tx_coal_timer;
+	int use_riwt;
+	u32 rx_riwt;
 };
 
 extern int phyaddr;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 76fd61a..1372ce2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -76,7 +76,7 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
 	STMMAC_STAT(rx_missed_cntr),
 	STMMAC_STAT(rx_overflow_cntr),
 	STMMAC_STAT(rx_vlan),
-	/* Tx/Rx IRQ errors */
+	/* Tx/Rx IRQ error info */
 	STMMAC_STAT(tx_undeflow_irq),
 	STMMAC_STAT(tx_process_stopped_irq),
 	STMMAC_STAT(tx_jabber_irq),
@@ -86,18 +86,23 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
 	STMMAC_STAT(rx_watchdog_irq),
 	STMMAC_STAT(tx_early_irq),
 	STMMAC_STAT(fatal_bus_error_irq),
-	/* Extra info */
+	/* Tx/Rx IRQ Events */
+	STMMAC_STAT(rx_early_irq),
 	STMMAC_STAT(threshold),
 	STMMAC_STAT(tx_pkt_n),
 	STMMAC_STAT(rx_pkt_n),
-	STMMAC_STAT(poll_n),
-	STMMAC_STAT(sched_timer_n),
-	STMMAC_STAT(normal_irq_n),
 	STMMAC_STAT(normal_irq_n),
+	STMMAC_STAT(rx_normal_irq_n),
+	STMMAC_STAT(napi_poll),
+	STMMAC_STAT(tx_normal_irq_n),
+	STMMAC_STAT(tx_clean),
+	STMMAC_STAT(tx_reset_ic_bit),
+	STMMAC_STAT(irq_receive_pmt_irq_n),
+	/* MMC info */
 	STMMAC_STAT(mmc_tx_irq_n),
 	STMMAC_STAT(mmc_rx_irq_n),
 	STMMAC_STAT(mmc_rx_csum_offload_irq_n),
-	STMMAC_STAT(irq_receive_pmt_irq_n),
+	/* EEE */
 	STMMAC_STAT(irq_tx_path_in_lpi_mode_n),
 	STMMAC_STAT(irq_tx_path_exit_lpi_mode_n),
 	STMMAC_STAT(irq_rx_path_in_lpi_mode_n),
@@ -519,6 +524,87 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,
 	return phy_ethtool_set_eee(priv->phydev, edata);
 }
 
+static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv)
+{
+	unsigned long clk = clk_get_rate(priv->stmmac_clk);
+
+	if (!clk)
+		return 0;
+
+	return (usec * (clk / 1000000)) / 256;
+}
+
+static u32 stmmac_riwt2usec(u32 riwt, struct stmmac_priv *priv)
+{
+	unsigned long clk = clk_get_rate(priv->stmmac_clk);
+
+	if (!clk)
+		return 0;
+
+	return (riwt * 256) / (clk / 1000000);
+}
+
+static int stmmac_get_coalesce(struct net_device *dev,
+			       struct ethtool_coalesce *ec)
+{
+	struct stmmac_priv *priv = netdev_priv(dev);
+
+	ec->tx_coalesce_usecs = priv->tx_coal_timer;
+	ec->tx_max_coalesced_frames = priv->tx_coal_frames;
+
+	if (priv->use_riwt)
+		ec->rx_coalesce_usecs = stmmac_riwt2usec(priv->rx_riwt, priv);
+
+	return 0;
+}
+
+static int stmmac_set_coalesce(struct net_device *dev,
+			       struct ethtool_coalesce *ec)
+{
+	struct stmmac_priv *priv = netdev_priv(dev);
+	unsigned int rx_riwt;
+
+	/* Check not supported parameters  */
+	if ((ec->rx_max_coalesced_frames) || (ec->rx_coalesce_usecs_irq) ||
+	    (ec->rx_max_coalesced_frames_irq) || (ec->tx_coalesce_usecs_irq) ||
+	    (ec->use_adaptive_rx_coalesce) || (ec->use_adaptive_tx_coalesce) ||
+	    (ec->pkt_rate_low) || (ec->rx_coalesce_usecs_low) ||
+	    (ec->rx_max_coalesced_frames_low) || (ec->tx_coalesce_usecs_high) ||
+	    (ec->tx_max_coalesced_frames_low) || (ec->pkt_rate_high) ||
+	    (ec->tx_coalesce_usecs_low) || (ec->rx_coalesce_usecs_high) ||
+	    (ec->rx_max_coalesced_frames_high) ||
+	    (ec->tx_max_coalesced_frames_irq) ||
+	    (ec->stats_block_coalesce_usecs) ||
+	    (ec->tx_max_coalesced_frames_high) || (ec->rate_sample_interval))
+		return -EOPNOTSUPP;
+
+	if (ec->rx_coalesce_usecs == 0)
+		return -EINVAL;
+
+	if ((ec->tx_coalesce_usecs == 0) &&
+	    (ec->tx_max_coalesced_frames == 0))
+		return -EINVAL;
+
+	if ((ec->tx_coalesce_usecs > STMMAC_COAL_TX_TIMER) ||
+	    (ec->tx_max_coalesced_frames > STMMAC_TX_MAX_FRAMES))
+		return -EINVAL;
+
+	rx_riwt = stmmac_usec2riwt(ec->rx_coalesce_usecs, priv);
+
+	if ((rx_riwt > MAX_DMA_RIWT) || (rx_riwt < MIN_DMA_RIWT))
+		return -EINVAL;
+	else if (!priv->use_riwt)
+		return -EOPNOTSUPP;
+
+	/* Only copy relevant parameters, ignore all others. */
+	priv->tx_coal_frames = ec->tx_max_coalesced_frames;
+	priv->tx_coal_timer = ec->tx_coalesce_usecs;
+	priv->rx_riwt = rx_riwt;
+	priv->hw->dma->rx_watchdog(priv->ioaddr, priv->rx_riwt);
+
+	return 0;
+}
+
 static const struct ethtool_ops stmmac_ethtool_ops = {
 	.begin = stmmac_check_if_running,
 	.get_drvinfo = stmmac_ethtool_getdrvinfo,
@@ -539,6 +625,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
 	.set_eee = stmmac_ethtool_op_set_eee,
 	.get_sset_count	= stmmac_get_sset_count,
 	.get_ts_info = ethtool_op_get_ts_info,
+	.get_coalesce = stmmac_get_coalesce,
+	.set_coalesce = stmmac_set_coalesce,
 };
 
 void stmmac_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c6cdbc4..542edbc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -115,16 +115,6 @@ static int tc = TC_DEFAULT;
 module_param(tc, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(tc, "DMA threshold control value");
 
-/* Pay attention to tune this parameter; take care of both
- * hardware capability and network stabitily/performance impact.
- * Many tests showed that ~4ms latency seems to be good enough. */
-#ifdef CONFIG_STMMAC_TIMER
-#define DEFAULT_PERIODIC_RATE	256
-static int tmrate = DEFAULT_PERIODIC_RATE;
-module_param(tmrate, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(tmrate, "External timer freq. (default: 256Hz)");
-#endif
-
 #define DMA_BUFFER_SIZE	BUF_SIZE_2KiB
 static int buf_sz = DMA_BUFFER_SIZE;
 module_param(buf_sz, int, S_IRUGO | S_IWUSR);
@@ -147,6 +137,8 @@ static int stmmac_init_fs(struct net_device *dev);
 static void stmmac_exit_fs(void);
 #endif
 
+#define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
+
 /**
  * stmmac_verify_args - verify the driver parameters.
  * Description: it verifies if some wrong parameter is passed to the driver.
@@ -536,12 +528,6 @@ static void init_dma_desc_rings(struct net_device *dev)
 	else
 		bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
 
-#ifdef CONFIG_STMMAC_TIMER
-	/* Disable interrupts on completion for the reception if timer is on */
-	if (likely(priv->tm->enable))
-		dis_ic = 1;
-#endif
-
 	DBG(probe, INFO, "stmmac: txsize %d, rxsize %d, bfsize %d\n",
 	    txsize, rxsize, bfsize);
 
@@ -617,6 +603,8 @@ static void init_dma_desc_rings(struct net_device *dev)
 	priv->dirty_tx = 0;
 	priv->cur_tx = 0;
 
+	if (priv->use_riwt)
+		dis_ic = 1;
 	/* Clear the Rx/Tx descriptors */
 	priv->hw->desc->init_rx_desc(priv->dma_rx, rxsize, dis_ic);
 	priv->hw->desc->init_tx_desc(priv->dma_tx, txsize);
@@ -704,16 +692,18 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
 }
 
 /**
- * stmmac_tx:
- * @priv: private driver structure
+ * stmmac_tx_clean:
+ * @priv: private data pointer
  * Description: it reclaims resources after transmission completes.
  */
-static void stmmac_tx(struct stmmac_priv *priv)
+static void stmmac_tx_clean(struct stmmac_priv *priv)
 {
 	unsigned int txsize = priv->dma_tx_size;
 
 	spin_lock(&priv->tx_lock);
 
+	priv->xstats.tx_clean++;
+
 	while (priv->dirty_tx != priv->cur_tx) {
 		int last;
 		unsigned int entry = priv->dirty_tx % txsize;
@@ -773,69 +763,16 @@ static void stmmac_tx(struct stmmac_priv *priv)
 	spin_unlock(&priv->tx_lock);
 }
 
-static inline void stmmac_enable_irq(struct stmmac_priv *priv)
-{
-#ifdef CONFIG_STMMAC_TIMER
-	if (likely(priv->tm->enable))
-		priv->tm->timer_start(tmrate);
-	else
-#endif
-		priv->hw->dma->enable_dma_irq(priv->ioaddr);
-}
-
-static inline void stmmac_disable_irq(struct stmmac_priv *priv)
-{
-#ifdef CONFIG_STMMAC_TIMER
-	if (likely(priv->tm->enable))
-		priv->tm->timer_stop();
-	else
-#endif
-		priv->hw->dma->disable_dma_irq(priv->ioaddr);
-}
-
-static int stmmac_has_work(struct stmmac_priv *priv)
-{
-	unsigned int has_work = 0;
-	int rxret, tx_work = 0;
-
-	rxret = priv->hw->desc->get_rx_owner(priv->dma_rx +
-		(priv->cur_rx % priv->dma_rx_size));
-
-	if (priv->dirty_tx != priv->cur_tx)
-		tx_work = 1;
-
-	if (likely(!rxret || tx_work))
-		has_work = 1;
-
-	return has_work;
-}
-
-static inline void _stmmac_schedule(struct stmmac_priv *priv)
+static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv)
 {
-	if (likely(stmmac_has_work(priv))) {
-		stmmac_disable_irq(priv);
-		napi_schedule(&priv->napi);
-	}
+	priv->hw->dma->enable_dma_irq(priv->ioaddr);
 }
 
-#ifdef CONFIG_STMMAC_TIMER
-void stmmac_schedule(struct net_device *dev)
+static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv)
 {
-	struct stmmac_priv *priv = netdev_priv(dev);
-
-	priv->xstats.sched_timer_n++;
-
-	_stmmac_schedule(priv);
+	priv->hw->dma->disable_dma_irq(priv->ioaddr);
 }
 
-static void stmmac_no_timer_started(unsigned int x)
-{;
-};
-
-static void stmmac_no_timer_stopped(void)
-{;
-};
-#endif
 
 /**
  * stmmac_tx_err:
@@ -858,16 +795,18 @@ static void stmmac_tx_err(struct stmmac_priv *priv)
 	netif_wake_queue(priv->dev);
 }
 
-
 static void stmmac_dma_interrupt(struct stmmac_priv *priv)
 {
 	int status;
 
 	status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
-	if (likely(status == handle_tx_rx))
-		_stmmac_schedule(priv);
-
-	else if (unlikely(status == tx_hard_error_bump_tc)) {
+	if (likely((status & handle_rx)) || (status & handle_tx)) {
+		if (likely(napi_schedule_prep(&priv->napi))) {
+			stmmac_disable_dma_irq(priv);
+			__napi_schedule(&priv->napi);
+		}
+	}
+	if (unlikely(status & tx_hard_error_bump_tc)) {
 		/* Try to bump up the dma threshold on this failure */
 		if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) {
 			tc += 64;
@@ -983,7 +922,6 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv)
 		/* Alternate (enhanced) DESC mode*/
 		priv->dma_cap.enh_desc =
 			(hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
-
 	}
 
 	return hw_cap;
@@ -1025,6 +963,38 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
 }
 
 /**
+ * stmmac_tx_timer:
+ * @data: data pointer
+ * Description:
+ * This is the timer handler to directly invoke the stmmac_tx_clean.
+ */
+static void stmmac_tx_timer(unsigned long data)
+{
+	struct stmmac_priv *priv = (struct stmmac_priv *)data;
+
+	stmmac_tx_clean(priv);
+}
+
+/**
+ * stmmac_tx_timer:
+ * @priv: private data structure
+ * Description:
+ * This inits the transmit coalesce parameters: i.e. timer rate,
+ * timer handler and default threshold used for enabling the
+ * interrupt on completion bit.
+ */
+static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
+{
+	priv->tx_coal_frames = STMMAC_TX_FRAMES;
+	priv->tx_coal_timer = STMMAC_COAL_TX_TIMER;
+	init_timer(&priv->txtimer);
+	priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer);
+	priv->txtimer.data = (unsigned long)priv;
+	priv->txtimer.function = stmmac_tx_timer;
+	add_timer(&priv->txtimer);
+}
+
+/**
  *  stmmac_open - open entry point of the driver
  *  @dev : pointer to the device structure.
  *  Description:
@@ -1038,23 +1008,6 @@ static int stmmac_open(struct net_device *dev)
 	struct stmmac_priv *priv = netdev_priv(dev);
 	int ret;
 
-#ifdef CONFIG_STMMAC_TIMER
-	priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
-	if (unlikely(priv->tm == NULL))
-		return -ENOMEM;
-
-	priv->tm->freq = tmrate;
-
-	/* Test if the external timer can be actually used.
-	 * In case of failure continue without timer. */
-	if (unlikely((stmmac_open_ext_timer(dev, priv->tm)) < 0)) {
-		pr_warning("stmmaceth: cannot attach the external timer.\n");
-		priv->tm->freq = 0;
-		priv->tm->timer_start = stmmac_no_timer_started;
-		priv->tm->timer_stop = stmmac_no_timer_stopped;
-	} else
-		priv->tm->enable = 1;
-#endif
 	clk_prepare_enable(priv->stmmac_clk);
 
 	stmmac_check_ether_addr(priv);
@@ -1141,10 +1094,6 @@ static int stmmac_open(struct net_device *dev)
 	priv->hw->dma->start_tx(priv->ioaddr);
 	priv->hw->dma->start_rx(priv->ioaddr);
 
-#ifdef CONFIG_STMMAC_TIMER
-	priv->tm->timer_start(tmrate);
-#endif
-
 	/* Dump DMA/MAC registers */
 	if (netif_msg_hw(priv)) {
 		priv->hw->mac->dump_regs(priv->ioaddr);
@@ -1157,6 +1106,13 @@ static int stmmac_open(struct net_device *dev)
 	priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS_TIMER;
 	priv->eee_enabled = stmmac_eee_init(priv);
 
+	stmmac_init_tx_coalesce(priv);
+
+	if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
+		priv->rx_riwt = MAX_DMA_RIWT;
+		priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
+	}
+
 	napi_enable(&priv->napi);
 	netif_start_queue(dev);
 
@@ -1170,9 +1126,6 @@ open_error_wolirq:
 	free_irq(dev->irq, dev);
 
 open_error:
-#ifdef CONFIG_STMMAC_TIMER
-	kfree(priv->tm);
-#endif
 	if (priv->phydev)
 		phy_disconnect(priv->phydev);
 
@@ -1203,14 +1156,10 @@ static int stmmac_release(struct net_device *dev)
 
 	netif_stop_queue(dev);
 
-#ifdef CONFIG_STMMAC_TIMER
-	/* Stop and release the timer */
-	stmmac_close_ext_timer();
-	if (priv->tm != NULL)
-		kfree(priv->tm);
-#endif
 	napi_disable(&priv->napi);
 
+	del_timer_sync(&priv->txtimer);
+
 	/* Free the IRQ lines */
 	free_irq(dev->irq, dev);
 	if (priv->wol_irq != dev->irq)
@@ -1273,11 +1222,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 #ifdef STMMAC_XMIT_DEBUG
 	if ((skb->len > ETH_FRAME_LEN) || nfrags)
-		pr_info("stmmac xmit:\n"
-		       "\tskb addr %p - len: %d - nopaged_len: %d\n"
-		       "\tn_frags: %d - ip_summed: %d - %s gso\n",
-		       skb, skb->len, nopaged_len, nfrags, skb->ip_summed,
-		       !skb_is_gso(skb) ? "isn't" : "is");
+		pr_debug("stmmac xmit: [entry %d]\n"
+			 "\tskb addr %p - len: %d - nopaged_len: %d\n"
+			 "\tn_frags: %d - ip_summed: %d - %s gso\n"
+			 "\ttx_count_frames %d\n", entry,
+			 skb, skb->len, nopaged_len, nfrags, skb->ip_summed,
+			 !skb_is_gso(skb) ? "isn't" : "is",
+			 priv->tx_count_frames);
 #endif
 
 	csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
@@ -1287,9 +1238,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 #ifdef STMMAC_XMIT_DEBUG
 	if ((nfrags > 0) || (skb->len > ETH_FRAME_LEN))
-		pr_debug("stmmac xmit: skb len: %d, nopaged_len: %d,\n"
-		       "\t\tn_frags: %d, ip_summed: %d\n",
-		       skb->len, nopaged_len, nfrags, skb->ip_summed);
+		pr_debug("\tskb len: %d, nopaged_len: %d,\n"
+			 "\t\tn_frags: %d, ip_summed: %d\n",
+			 skb->len, nopaged_len, nfrags, skb->ip_summed);
 #endif
 	priv->tx_skbuff[entry] = skb;
 
@@ -1320,16 +1271,24 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 		wmb();
 	}
 
-	/* Interrupt on completition only for the latest segment */
+	/* Finalize the latest segment. */
 	priv->hw->desc->close_tx_desc(desc);
 
-#ifdef CONFIG_STMMAC_TIMER
-	/* Clean IC while using timer */
-	if (likely(priv->tm->enable))
-		priv->hw->desc->clear_tx_ic(desc);
-#endif
-
 	wmb();
+	/* According to the coalesce parameter the IC bit for the latest
+	 * segment could be reset and the timer re-started to invoke the
+	 * stmmac_tx function. This approach takes care about the fragments.
+	 */
+	priv->tx_count_frames += nfrags + 1;
+	if (priv->tx_coal_frames > priv->tx_count_frames) {
+		priv->hw->desc->clear_tx_ic(desc);
+		priv->xstats.tx_reset_ic_bit++;
+		TX_DBG("\t[entry %d]: tx_count_frames %d\n", entry,
+		       priv->tx_count_frames);
+		mod_timer(&priv->txtimer,
+			  STMMAC_COAL_TIMER(priv->tx_coal_timer));
+	} else
+		priv->tx_count_frames = 0;
 
 	/* To avoid raise condition */
 	priv->hw->desc->set_tx_owner(first);
@@ -1471,14 +1430,12 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
 #endif
 			skb->protocol = eth_type_trans(skb, priv->dev);
 
-			if (unlikely(!priv->plat->rx_coe)) {
-				/* No RX COE for old mac10/100 devices */
+			if (unlikely(!priv->plat->rx_coe))
 				skb_checksum_none_assert(skb);
-				netif_receive_skb(skb);
-			} else {
+			else
 				skb->ip_summed = CHECKSUM_UNNECESSARY;
-				napi_gro_receive(&priv->napi, skb);
-			}
+
+			napi_gro_receive(&priv->napi, skb);
 
 			priv->dev->stats.rx_packets++;
 			priv->dev->stats.rx_bytes += frame_len;
@@ -1500,21 +1457,20 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
  *  @budget : maximum number of packets that the current CPU can receive from
  *	      all interfaces.
  *  Description :
- *   This function implements the the reception process.
- *   Also it runs the TX completion thread
+ *  To look at the incoming frames and clear the tx resources.
  */
 static int stmmac_poll(struct napi_struct *napi, int budget)
 {
 	struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi);
 	int work_done = 0;
 
-	priv->xstats.poll_n++;
-	stmmac_tx(priv);
-	work_done = stmmac_rx(priv, budget);
+	priv->xstats.napi_poll++;
+	stmmac_tx_clean(priv);
 
+	work_done = stmmac_rx(priv, budget);
 	if (work_done < budget) {
 		napi_complete(napi);
-		stmmac_enable_irq(priv);
+		stmmac_enable_dma_irq(priv);
 	}
 	return work_done;
 }
@@ -1523,7 +1479,7 @@ static int stmmac_poll(struct napi_struct *napi, int budget)
  *  stmmac_tx_timeout
  *  @dev : Pointer to net device structure
  *  Description: this function is called when a packet transmission fails to
- *   complete within a reasonable tmrate. The driver will mark the error in the
+ *   complete within a reasonable time. The driver will mark the error in the
  *   netdev structure and arrange for the device to be reset to a sane state
  *   in order to transmit a new packet.
  */
@@ -2050,6 +2006,16 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
 	if (flow_ctrl)
 		priv->flow_ctrl = FLOW_AUTO;	/* RX/TX pause on */
 
+	/* Rx Watchdog is available in the COREs newer than the 3.40.
+	 * In some case, for example on bugged HW this feature
+	 * has to be disable and this can be done by passing the
+	 * riwt_off field from the platform.
+	 */
+	if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) {
+		priv->use_riwt = 1;
+		pr_info(" Enable RX Mitigation via HW Watchdog Timer\n");
+	}
+
 	netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
 
 	spin_lock_init(&priv->lock);
@@ -2141,11 +2107,9 @@ int stmmac_suspend(struct net_device *ndev)
 	netif_device_detach(ndev);
 	netif_stop_queue(ndev);
 
-#ifdef CONFIG_STMMAC_TIMER
-	priv->tm->timer_stop();
-	if (likely(priv->tm->enable))
+	if (priv->use_riwt)
 		dis_ic = 1;
-#endif
+
 	napi_disable(&priv->napi);
 
 	/* Stop TX/RX DMA */
@@ -2196,10 +2160,6 @@ int stmmac_resume(struct net_device *ndev)
 	priv->hw->dma->start_tx(priv->ioaddr);
 	priv->hw->dma->start_rx(priv->ioaddr);
 
-#ifdef CONFIG_STMMAC_TIMER
-	if (likely(priv->tm->enable))
-		priv->tm->timer_start(tmrate);
-#endif
 	napi_enable(&priv->napi);
 
 	netif_start_queue(ndev);
@@ -2295,11 +2255,6 @@ static int __init stmmac_cmdline_opt(char *str)
 		} else if (!strncmp(opt, "eee_timer:", 6)) {
 			if (kstrtoint(opt + 10, 0, &eee_timer))
 				goto err;
-#ifdef CONFIG_STMMAC_TIMER
-		} else if (!strncmp(opt, "tmrate:", 7)) {
-			if (kstrtoint(opt + 7, 0, &tmrate))
-				goto err;
-#endif
 		}
 	}
 	return 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c
deleted file mode 100644
index 4ccd4e2..0000000
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*******************************************************************************
-  STMMAC external timer support.
-
-  Copyright (C) 2007-2009  STMicroelectronics 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, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
-*******************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/etherdevice.h>
-#include "stmmac_timer.h"
-
-static void stmmac_timer_handler(void *data)
-{
-	struct net_device *dev = (struct net_device *)data;
-
-	stmmac_schedule(dev);
-}
-
-#define STMMAC_TIMER_MSG(timer, freq) \
-printk(KERN_INFO "stmmac_timer: %s Timer ON (freq %dHz)\n", timer, freq);
-
-#if defined(CONFIG_STMMAC_RTC_TIMER)
-#include <linux/rtc.h>
-static struct rtc_device *stmmac_rtc;
-static rtc_task_t stmmac_task;
-
-static void stmmac_rtc_start(unsigned int new_freq)
-{
-	rtc_irq_set_freq(stmmac_rtc, &stmmac_task, new_freq);
-	rtc_irq_set_state(stmmac_rtc, &stmmac_task, 1);
-}
-
-static void stmmac_rtc_stop(void)
-{
-	rtc_irq_set_state(stmmac_rtc, &stmmac_task, 0);
-}
-
-int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
-{
-	stmmac_task.private_data = dev;
-	stmmac_task.func = stmmac_timer_handler;
-
-	stmmac_rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
-	if (stmmac_rtc == NULL) {
-		pr_err("open rtc device failed\n");
-		return -ENODEV;
-	}
-
-	rtc_irq_register(stmmac_rtc, &stmmac_task);
-
-	/* Periodic mode is not supported */
-	if ((rtc_irq_set_freq(stmmac_rtc, &stmmac_task, tm->freq) < 0)) {
-		pr_err("set periodic failed\n");
-		rtc_irq_unregister(stmmac_rtc, &stmmac_task);
-		rtc_class_close(stmmac_rtc);
-		return -1;
-	}
-
-	STMMAC_TIMER_MSG(CONFIG_RTC_HCTOSYS_DEVICE, tm->freq);
-
-	tm->timer_start = stmmac_rtc_start;
-	tm->timer_stop = stmmac_rtc_stop;
-
-	return 0;
-}
-
-int stmmac_close_ext_timer(void)
-{
-	rtc_irq_set_state(stmmac_rtc, &stmmac_task, 0);
-	rtc_irq_unregister(stmmac_rtc, &stmmac_task);
-	rtc_class_close(stmmac_rtc);
-	return 0;
-}
-
-#elif defined(CONFIG_STMMAC_TMU_TIMER)
-#include <linux/clk.h>
-#define TMU_CHANNEL "tmu2_clk"
-static struct clk *timer_clock;
-
-static void stmmac_tmu_start(unsigned int new_freq)
-{
-	clk_set_rate(timer_clock, new_freq);
-	clk_prepare_enable(timer_clock);
-}
-
-static void stmmac_tmu_stop(void)
-{
-	clk_disable_unprepare(timer_clock);
-}
-
-int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
-{
-	timer_clock = clk_get(NULL, TMU_CHANNEL);
-
-	if (IS_ERR(timer_clock))
-		return -1;
-
-	if (tmu2_register_user(stmmac_timer_handler, (void *)dev) < 0) {
-		timer_clock = NULL;
-		return -1;
-	}
-
-	STMMAC_TIMER_MSG("TMU2", tm->freq);
-	tm->timer_start = stmmac_tmu_start;
-	tm->timer_stop = stmmac_tmu_stop;
-
-	return 0;
-}
-
-int stmmac_close_ext_timer(void)
-{
-	clk_disable_unprepare(timer_clock);
-	tmu2_unregister_user();
-	clk_put(timer_clock);
-	return 0;
-}
-#endif
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h
deleted file mode 100644
index aea9b14..0000000
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
-  STMMAC external timer Header File.
-
-  Copyright (C) 2007-2009  STMicroelectronics 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, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
-*******************************************************************************/
-#ifndef __STMMAC_TIMER_H__
-#define __STMMAC_TIMER_H__
-
-struct stmmac_timer {
-	void (*timer_start) (unsigned int new_freq);
-	void (*timer_stop) (void);
-	unsigned int freq;
-	unsigned int enable;
-};
-
-/* Open the HW timer device and return 0 in case of success */
-int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm);
-/* Stop the timer and release it */
-int stmmac_close_ext_timer(void);
-/* Function used for scheduling task within the stmmac */
-void stmmac_schedule(struct net_device *dev);
-
-#if defined(CONFIG_STMMAC_TMU_TIMER)
-extern int tmu2_register_user(void *fnt, void *data);
-extern void tmu2_unregister_user(void);
-#endif
-
-#endif /* __STMMAC_TIMER_H__ */
diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
index 2c41894..de71b1e 100644
--- a/drivers/net/ethernet/ti/Kconfig
+++ b/drivers/net/ethernet/ti/Kconfig
@@ -60,6 +60,15 @@ config TI_CPSW
 	  To compile this driver as a module, choose M here: the module
 	  will be called cpsw.
 
+config TI_CPTS
+	boolean "TI Common Platform Time Sync (CPTS) Support"
+	depends on TI_CPSW
+	select PTP_1588_CLOCK
+	---help---
+	  This driver supports the Common Platform Time Sync unit of
+	  the CPSW Ethernet Switch. The unit can time stamp PTP UDP/IPv4
+	  and Layer 2 packets, and the driver offers a PTP Hardware Clock.
+
 config TLAN
 	tristate "TI ThunderLAN support"
 	depends on (PCI || EISA)
@@ -79,8 +88,8 @@ config TLAN
 	  Please email feedback to <torben.mathiasen@compaq.com>.
 
 config CPMAC
-	tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && AR7
+	tristate "TI AR7 CPMAC Ethernet support"
+	depends on AR7
 	select PHYLIB
 	---help---
 	  TI AR7 CPMAC Ethernet support
diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile
index 91bd8bb..c65148e 100644
--- a/drivers/net/ethernet/ti/Makefile
+++ b/drivers/net/ethernet/ti/Makefile
@@ -8,4 +8,4 @@ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
 obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
 obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o
 obj-$(CONFIG_TI_CPSW) += ti_cpsw.o
-ti_cpsw-y := cpsw_ale.o cpsw.o
+ti_cpsw-y := cpsw_ale.o cpsw.o cpts.o
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index df55e24..02c2477 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -24,6 +24,7 @@
 #include <linux/if_ether.h>
 #include <linux/etherdevice.h>
 #include <linux/netdevice.h>
+#include <linux/net_tstamp.h>
 #include <linux/phy.h>
 #include <linux/workqueue.h>
 #include <linux/delay.h>
@@ -35,6 +36,7 @@
 #include <linux/platform_data/cpsw.h>
 
 #include "cpsw_ale.h"
+#include "cpts.h"
 #include "davinci_cpdma.h"
 
 #define CPSW_DEBUG	(NETIF_MSG_HW		| NETIF_MSG_WOL		| \
@@ -70,10 +72,37 @@ do {								\
 		dev_notice(priv->dev, format, ## __VA_ARGS__);	\
 } while (0)
 
+#define ALE_ALL_PORTS		0x7
+
 #define CPSW_MAJOR_VERSION(reg)		(reg >> 8 & 0x7)
 #define CPSW_MINOR_VERSION(reg)		(reg & 0xff)
 #define CPSW_RTL_VERSION(reg)		((reg >> 11) & 0x1f)
 
+#define CPSW_VERSION_1		0x19010a
+#define CPSW_VERSION_2		0x19010c
+
+#define HOST_PORT_NUM		0
+#define SLIVER_SIZE		0x40
+
+#define CPSW1_HOST_PORT_OFFSET	0x028
+#define CPSW1_SLAVE_OFFSET	0x050
+#define CPSW1_SLAVE_SIZE	0x040
+#define CPSW1_CPDMA_OFFSET	0x100
+#define CPSW1_STATERAM_OFFSET	0x200
+#define CPSW1_CPTS_OFFSET	0x500
+#define CPSW1_ALE_OFFSET	0x600
+#define CPSW1_SLIVER_OFFSET	0x700
+
+#define CPSW2_HOST_PORT_OFFSET	0x108
+#define CPSW2_SLAVE_OFFSET	0x200
+#define CPSW2_SLAVE_SIZE	0x100
+#define CPSW2_CPDMA_OFFSET	0x800
+#define CPSW2_STATERAM_OFFSET	0xa00
+#define CPSW2_CPTS_OFFSET	0xc00
+#define CPSW2_ALE_OFFSET	0xd00
+#define CPSW2_SLIVER_OFFSET	0xd80
+#define CPSW2_BD_OFFSET		0x2000
+
 #define CPDMA_RXTHRESH		0x0c0
 #define CPDMA_RXFREE		0x0e0
 #define CPDMA_TXHDP		0x00
@@ -81,21 +110,6 @@ do {								\
 #define CPDMA_TXCP		0x40
 #define CPDMA_RXCP		0x60
 
-#define cpsw_dma_regs(base, offset)		\
-	(void __iomem *)((base) + (offset))
-#define cpsw_dma_rxthresh(base, offset)		\
-	(void __iomem *)((base) + (offset) + CPDMA_RXTHRESH)
-#define cpsw_dma_rxfree(base, offset)		\
-	(void __iomem *)((base) + (offset) + CPDMA_RXFREE)
-#define cpsw_dma_txhdp(base, offset)		\
-	(void __iomem *)((base) + (offset) + CPDMA_TXHDP)
-#define cpsw_dma_rxhdp(base, offset)		\
-	(void __iomem *)((base) + (offset) + CPDMA_RXHDP)
-#define cpsw_dma_txcp(base, offset)		\
-	(void __iomem *)((base) + (offset) + CPDMA_TXCP)
-#define cpsw_dma_rxcp(base, offset)		\
-	(void __iomem *)((base) + (offset) + CPDMA_RXCP)
-
 #define CPSW_POLL_WEIGHT	64
 #define CPSW_MIN_PACKET_SIZE	60
 #define CPSW_MAX_PACKET_SIZE	(1500 + 14 + 4 + 4)
@@ -129,7 +143,7 @@ static int rx_packet_max = CPSW_MAX_PACKET_SIZE;
 module_param(rx_packet_max, int, 0);
 MODULE_PARM_DESC(rx_packet_max, "maximum receive packet size (bytes)");
 
-struct cpsw_ss_regs {
+struct cpsw_wr_regs {
 	u32	id_ver;
 	u32	soft_reset;
 	u32	control;
@@ -140,26 +154,98 @@ struct cpsw_ss_regs {
 	u32	misc_en;
 };
 
-struct cpsw_regs {
+struct cpsw_ss_regs {
 	u32	id_ver;
 	u32	control;
 	u32	soft_reset;
 	u32	stat_port_en;
 	u32	ptype;
+	u32	soft_idle;
+	u32	thru_rate;
+	u32	gap_thresh;
+	u32	tx_start_wds;
+	u32	flow_control;
+	u32	vlan_ltype;
+	u32	ts_ltype;
+	u32	dlr_ltype;
 };
 
-struct cpsw_slave_regs {
-	u32	max_blks;
-	u32	blk_cnt;
-	u32	flow_thresh;
-	u32	port_vlan;
-	u32	tx_pri_map;
-	u32	ts_ctl;
-	u32	ts_seq_ltype;
-	u32	ts_vlan;
-	u32	sa_lo;
-	u32	sa_hi;
-};
+/* CPSW_PORT_V1 */
+#define CPSW1_MAX_BLKS      0x00 /* Maximum FIFO Blocks */
+#define CPSW1_BLK_CNT       0x04 /* FIFO Block Usage Count (Read Only) */
+#define CPSW1_TX_IN_CTL     0x08 /* Transmit FIFO Control */
+#define CPSW1_PORT_VLAN     0x0c /* VLAN Register */
+#define CPSW1_TX_PRI_MAP    0x10 /* Tx Header Priority to Switch Pri Mapping */
+#define CPSW1_TS_CTL        0x14 /* Time Sync Control */
+#define CPSW1_TS_SEQ_LTYPE  0x18 /* Time Sync Sequence ID Offset and Msg Type */
+#define CPSW1_TS_VLAN       0x1c /* Time Sync VLAN1 and VLAN2 */
+
+/* CPSW_PORT_V2 */
+#define CPSW2_CONTROL       0x00 /* Control Register */
+#define CPSW2_MAX_BLKS      0x08 /* Maximum FIFO Blocks */
+#define CPSW2_BLK_CNT       0x0c /* FIFO Block Usage Count (Read Only) */
+#define CPSW2_TX_IN_CTL     0x10 /* Transmit FIFO Control */
+#define CPSW2_PORT_VLAN     0x14 /* VLAN Register */
+#define CPSW2_TX_PRI_MAP    0x18 /* Tx Header Priority to Switch Pri Mapping */
+#define CPSW2_TS_SEQ_MTYPE  0x1c /* Time Sync Sequence ID Offset and Msg Type */
+
+/* CPSW_PORT_V1 and V2 */
+#define SA_LO               0x20 /* CPGMAC_SL Source Address Low */
+#define SA_HI               0x24 /* CPGMAC_SL Source Address High */
+#define SEND_PERCENT        0x28 /* Transmit Queue Send Percentages */
+
+/* CPSW_PORT_V2 only */
+#define RX_DSCP_PRI_MAP0    0x30 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP1    0x34 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP2    0x38 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP3    0x3c /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP4    0x40 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP5    0x44 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP6    0x48 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP7    0x4c /* Rx DSCP Priority to Rx Packet Mapping */
+
+/* Bit definitions for the CPSW2_CONTROL register */
+#define PASS_PRI_TAGGED     (1<<24) /* Pass Priority Tagged */
+#define VLAN_LTYPE2_EN      (1<<21) /* VLAN LTYPE 2 enable */
+#define VLAN_LTYPE1_EN      (1<<20) /* VLAN LTYPE 1 enable */
+#define DSCP_PRI_EN         (1<<16) /* DSCP Priority Enable */
+#define TS_320              (1<<14) /* Time Sync Dest Port 320 enable */
+#define TS_319              (1<<13) /* Time Sync Dest Port 319 enable */
+#define TS_132              (1<<12) /* Time Sync Dest IP Addr 132 enable */
+#define TS_131              (1<<11) /* Time Sync Dest IP Addr 131 enable */
+#define TS_130              (1<<10) /* Time Sync Dest IP Addr 130 enable */
+#define TS_129              (1<<9)  /* Time Sync Dest IP Addr 129 enable */
+#define TS_BIT8             (1<<8)  /* ts_ttl_nonzero? */
+#define TS_ANNEX_D_EN       (1<<4)  /* Time Sync Annex D enable */
+#define TS_LTYPE2_EN        (1<<3)  /* Time Sync LTYPE 2 enable */
+#define TS_LTYPE1_EN        (1<<2)  /* Time Sync LTYPE 1 enable */
+#define TS_TX_EN            (1<<1)  /* Time Sync Transmit Enable */
+#define TS_RX_EN            (1<<0)  /* Time Sync Receive Enable */
+
+#define CTRL_TS_BITS \
+	(TS_320 | TS_319 | TS_132 | TS_131 | TS_130 | TS_129 | TS_BIT8 | \
+	 TS_ANNEX_D_EN | TS_LTYPE1_EN)
+
+#define CTRL_ALL_TS_MASK (CTRL_TS_BITS | TS_TX_EN | TS_RX_EN)
+#define CTRL_TX_TS_BITS  (CTRL_TS_BITS | TS_TX_EN)
+#define CTRL_RX_TS_BITS  (CTRL_TS_BITS | TS_RX_EN)
+
+/* Bit definitions for the CPSW2_TS_SEQ_MTYPE register */
+#define TS_SEQ_ID_OFFSET_SHIFT   (16)    /* Time Sync Sequence ID Offset */
+#define TS_SEQ_ID_OFFSET_MASK    (0x3f)
+#define TS_MSG_TYPE_EN_SHIFT     (0)     /* Time Sync Message Type Enable */
+#define TS_MSG_TYPE_EN_MASK      (0xffff)
+
+/* The PTP event messages - Sync, Delay_Req, Pdelay_Req, and Pdelay_Resp. */
+#define EVENT_MSG_BITS ((1<<0) | (1<<1) | (1<<2) | (1<<3))
+
+/* Bit definitions for the CPSW1_TS_CTL register */
+#define CPSW_V1_TS_RX_EN		BIT(0)
+#define CPSW_V1_TS_TX_EN		BIT(4)
+#define CPSW_V1_MSG_TYPE_OFS		16
+
+/* Bit definitions for the CPSW1_TS_SEQ_LTYPE register */
+#define CPSW_V1_SEQ_ID_OFS_SHIFT	16
 
 struct cpsw_host_regs {
 	u32	max_blks;
@@ -185,7 +271,7 @@ struct cpsw_sliver_regs {
 };
 
 struct cpsw_slave {
-	struct cpsw_slave_regs __iomem	*regs;
+	void __iomem			*regs;
 	struct cpsw_sliver_regs __iomem	*sliver;
 	int				slave_num;
 	u32				mac_control;
@@ -193,19 +279,30 @@ struct cpsw_slave {
 	struct phy_device		*phy;
 };
 
+static inline u32 slave_read(struct cpsw_slave *slave, u32 offset)
+{
+	return __raw_readl(slave->regs + offset);
+}
+
+static inline void slave_write(struct cpsw_slave *slave, u32 val, u32 offset)
+{
+	__raw_writel(val, slave->regs + offset);
+}
+
 struct cpsw_priv {
 	spinlock_t			lock;
 	struct platform_device		*pdev;
 	struct net_device		*ndev;
 	struct resource			*cpsw_res;
-	struct resource			*cpsw_ss_res;
+	struct resource			*cpsw_wr_res;
 	struct napi_struct		napi;
 	struct device			*dev;
 	struct cpsw_platform_data	data;
-	struct cpsw_regs __iomem	*regs;
-	struct cpsw_ss_regs __iomem	*ss_regs;
+	struct cpsw_ss_regs __iomem	*regs;
+	struct cpsw_wr_regs __iomem	*wr_regs;
 	struct cpsw_host_regs __iomem	*host_port_regs;
 	u32				msg_enable;
+	u32				version;
 	struct net_device_stats		stats;
 	int				rx_packet_max;
 	int				host_port;
@@ -218,6 +315,7 @@ struct cpsw_priv {
 	/* snapshot of IRQ numbers */
 	u32 irqs_table[4];
 	u32 num_irqs;
+	struct cpts cpts;
 };
 
 #define napi_to_priv(napi)	container_of(napi, struct cpsw_priv, napi)
@@ -228,10 +326,34 @@ struct cpsw_priv {
 			(func)((priv)->slaves + idx, ##arg);	\
 	} while (0)
 
+static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
+{
+	struct cpsw_priv *priv = netdev_priv(ndev);
+
+	if (ndev->flags & IFF_PROMISC) {
+		/* Enable promiscuous mode */
+		dev_err(priv->dev, "Ignoring Promiscuous mode\n");
+		return;
+	}
+
+	/* Clear all mcast from ALE */
+	cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port);
+
+	if (!netdev_mc_empty(ndev)) {
+		struct netdev_hw_addr *ha;
+
+		/* program multicast address list into ALE register */
+		netdev_for_each_mc_addr(ha, ndev) {
+			cpsw_ale_add_mcast(priv->ale, (u8 *)ha->addr,
+				ALE_ALL_PORTS << priv->host_port, 0, 0);
+		}
+	}
+}
+
 static void cpsw_intr_enable(struct cpsw_priv *priv)
 {
-	__raw_writel(0xFF, &priv->ss_regs->tx_en);
-	__raw_writel(0xFF, &priv->ss_regs->rx_en);
+	__raw_writel(0xFF, &priv->wr_regs->tx_en);
+	__raw_writel(0xFF, &priv->wr_regs->rx_en);
 
 	cpdma_ctlr_int_ctrl(priv->dma, true);
 	return;
@@ -239,8 +361,8 @@ static void cpsw_intr_enable(struct cpsw_priv *priv)
 
 static void cpsw_intr_disable(struct cpsw_priv *priv)
 {
-	__raw_writel(0, &priv->ss_regs->tx_en);
-	__raw_writel(0, &priv->ss_regs->rx_en);
+	__raw_writel(0, &priv->wr_regs->tx_en);
+	__raw_writel(0, &priv->wr_regs->rx_en);
 
 	cpdma_ctlr_int_ctrl(priv->dma, false);
 	return;
@@ -254,6 +376,7 @@ void cpsw_tx_handler(void *token, int len, int status)
 
 	if (unlikely(netif_queue_stopped(ndev)))
 		netif_start_queue(ndev);
+	cpts_tx_timestamp(&priv->cpts, skb);
 	priv->stats.tx_packets++;
 	priv->stats.tx_bytes += len;
 	dev_kfree_skb_any(skb);
@@ -274,6 +397,7 @@ void cpsw_rx_handler(void *token, int len, int status)
 	}
 	if (likely(status >= 0)) {
 		skb_put(skb, len);
+		cpts_rx_timestamp(&priv->cpts, skb);
 		skb->protocol = eth_type_trans(skb, ndev);
 		netif_receive_skb(skb);
 		priv->stats.rx_bytes += len;
@@ -359,8 +483,8 @@ static inline void soft_reset(const char *module, void __iomem *reg)
 static void cpsw_set_slave_mac(struct cpsw_slave *slave,
 			       struct cpsw_priv *priv)
 {
-	__raw_writel(mac_hi(priv->mac_addr), &slave->regs->sa_hi);
-	__raw_writel(mac_lo(priv->mac_addr), &slave->regs->sa_lo);
+	slave_write(slave, mac_hi(priv->mac_addr), SA_HI);
+	slave_write(slave, mac_lo(priv->mac_addr), SA_LO);
 }
 
 static void _cpsw_adjust_link(struct cpsw_slave *slave,
@@ -446,7 +570,15 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
 
 	/* setup priority mapping */
 	__raw_writel(RX_PRIORITY_MAPPING, &slave->sliver->rx_pri_map);
-	__raw_writel(TX_PRIORITY_MAPPING, &slave->regs->tx_pri_map);
+
+	switch (priv->version) {
+	case CPSW_VERSION_1:
+		slave_write(slave, TX_PRIORITY_MAPPING, CPSW1_TX_PRI_MAP);
+		break;
+	case CPSW_VERSION_2:
+		slave_write(slave, TX_PRIORITY_MAPPING, CPSW2_TX_PRI_MAP);
+		break;
+	}
 
 	/* setup max packet size, and mac address */
 	__raw_writel(priv->rx_packet_max, &slave->sliver->rx_maxlen);
@@ -505,7 +637,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
 
 	pm_runtime_get_sync(&priv->pdev->dev);
 
-	reg = __raw_readl(&priv->regs->id_ver);
+	reg = priv->version;
 
 	dev_info(priv->dev, "initializing cpsw version %d.%d (%d)\n",
 		 CPSW_MAJOR_VERSION(reg), CPSW_MINOR_VERSION(reg),
@@ -566,12 +698,12 @@ static int cpsw_ndo_stop(struct net_device *ndev)
 	struct cpsw_priv *priv = netdev_priv(ndev);
 
 	cpsw_info(priv, ifdown, "shutting down cpsw device\n");
-	cpsw_intr_disable(priv);
-	cpdma_ctlr_int_ctrl(priv->dma, false);
-	cpdma_ctlr_stop(priv->dma);
 	netif_stop_queue(priv->ndev);
 	napi_disable(&priv->napi);
 	netif_carrier_off(priv->ndev);
+	cpsw_intr_disable(priv);
+	cpdma_ctlr_int_ctrl(priv->dma, false);
+	cpdma_ctlr_stop(priv->dma);
 	cpsw_ale_stop(priv->ale);
 	for_each_slave(priv, cpsw_slave_stop, priv);
 	pm_runtime_put_sync(&priv->pdev->dev);
@@ -592,6 +724,11 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
 		return NETDEV_TX_OK;
 	}
 
+	if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && priv->cpts.tx_enable)
+		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+
+	skb_tx_timestamp(skb);
+
 	ret = cpdma_chan_submit(priv->txch, skb, skb->data,
 				skb->len, GFP_KERNEL);
 	if (unlikely(ret != 0)) {
@@ -629,6 +766,130 @@ static void cpsw_ndo_change_rx_flags(struct net_device *ndev, int flags)
 		dev_err(&ndev->dev, "multicast traffic cannot be filtered!\n");
 }
 
+#ifdef CONFIG_TI_CPTS
+
+static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
+{
+	struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
+	u32 ts_en, seq_id;
+
+	if (!priv->cpts.tx_enable && !priv->cpts.rx_enable) {
+		slave_write(slave, 0, CPSW1_TS_CTL);
+		return;
+	}
+
+	seq_id = (30 << CPSW_V1_SEQ_ID_OFS_SHIFT) | ETH_P_1588;
+	ts_en = EVENT_MSG_BITS << CPSW_V1_MSG_TYPE_OFS;
+
+	if (priv->cpts.tx_enable)
+		ts_en |= CPSW_V1_TS_TX_EN;
+
+	if (priv->cpts.rx_enable)
+		ts_en |= CPSW_V1_TS_RX_EN;
+
+	slave_write(slave, ts_en, CPSW1_TS_CTL);
+	slave_write(slave, seq_id, CPSW1_TS_SEQ_LTYPE);
+}
+
+static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
+{
+	struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
+	u32 ctrl, mtype;
+
+	ctrl = slave_read(slave, CPSW2_CONTROL);
+	ctrl &= ~CTRL_ALL_TS_MASK;
+
+	if (priv->cpts.tx_enable)
+		ctrl |= CTRL_TX_TS_BITS;
+
+	if (priv->cpts.rx_enable)
+		ctrl |= CTRL_RX_TS_BITS;
+
+	mtype = (30 << TS_SEQ_ID_OFFSET_SHIFT) | EVENT_MSG_BITS;
+
+	slave_write(slave, mtype, CPSW2_TS_SEQ_MTYPE);
+	slave_write(slave, ctrl, CPSW2_CONTROL);
+	__raw_writel(ETH_P_1588, &priv->regs->ts_ltype);
+}
+
+static int cpsw_hwtstamp_ioctl(struct cpsw_priv *priv, struct ifreq *ifr)
+{
+	struct cpts *cpts = &priv->cpts;
+	struct hwtstamp_config cfg;
+
+	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
+		return -EFAULT;
+
+	/* reserved for future extensions */
+	if (cfg.flags)
+		return -EINVAL;
+
+	switch (cfg.tx_type) {
+	case HWTSTAMP_TX_OFF:
+		cpts->tx_enable = 0;
+		break;
+	case HWTSTAMP_TX_ON:
+		cpts->tx_enable = 1;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	switch (cfg.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		cpts->rx_enable = 0;
+		break;
+	case HWTSTAMP_FILTER_ALL:
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+		return -ERANGE;
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+		cpts->rx_enable = 1;
+		cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	switch (priv->version) {
+	case CPSW_VERSION_1:
+		cpsw_hwtstamp_v1(priv);
+		break;
+	case CPSW_VERSION_2:
+		cpsw_hwtstamp_v2(priv);
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+}
+
+#endif /*CONFIG_TI_CPTS*/
+
+static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+	struct cpsw_priv *priv = netdev_priv(dev);
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+#ifdef CONFIG_TI_CPTS
+	if (cmd == SIOCSHWTSTAMP)
+		return cpsw_hwtstamp_ioctl(priv, req);
+#endif
+	return -ENOTSUPP;
+}
+
 static void cpsw_ndo_tx_timeout(struct net_device *ndev)
 {
 	struct cpsw_priv *priv = netdev_priv(ndev);
@@ -669,10 +930,12 @@ static const struct net_device_ops cpsw_netdev_ops = {
 	.ndo_stop		= cpsw_ndo_stop,
 	.ndo_start_xmit		= cpsw_ndo_start_xmit,
 	.ndo_change_rx_flags	= cpsw_ndo_change_rx_flags,
+	.ndo_do_ioctl		= cpsw_ndo_ioctl,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_tx_timeout		= cpsw_ndo_tx_timeout,
 	.ndo_get_stats		= cpsw_ndo_get_stats,
+	.ndo_set_rx_mode	= cpsw_ndo_set_rx_mode,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= cpsw_ndo_poll_controller,
 #endif
@@ -699,22 +962,56 @@ static void cpsw_set_msglevel(struct net_device *ndev, u32 value)
 	priv->msg_enable = value;
 }
 
+static int cpsw_get_ts_info(struct net_device *ndev,
+			    struct ethtool_ts_info *info)
+{
+#ifdef CONFIG_TI_CPTS
+	struct cpsw_priv *priv = netdev_priv(ndev);
+
+	info->so_timestamping =
+		SOF_TIMESTAMPING_TX_HARDWARE |
+		SOF_TIMESTAMPING_TX_SOFTWARE |
+		SOF_TIMESTAMPING_RX_HARDWARE |
+		SOF_TIMESTAMPING_RX_SOFTWARE |
+		SOF_TIMESTAMPING_SOFTWARE |
+		SOF_TIMESTAMPING_RAW_HARDWARE;
+	info->phc_index = priv->cpts.phc_index;
+	info->tx_types =
+		(1 << HWTSTAMP_TX_OFF) |
+		(1 << HWTSTAMP_TX_ON);
+	info->rx_filters =
+		(1 << HWTSTAMP_FILTER_NONE) |
+		(1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
+#else
+	info->so_timestamping =
+		SOF_TIMESTAMPING_TX_SOFTWARE |
+		SOF_TIMESTAMPING_RX_SOFTWARE |
+		SOF_TIMESTAMPING_SOFTWARE;
+	info->phc_index = -1;
+	info->tx_types = 0;
+	info->rx_filters = 0;
+#endif
+	return 0;
+}
+
 static const struct ethtool_ops cpsw_ethtool_ops = {
 	.get_drvinfo	= cpsw_get_drvinfo,
 	.get_msglevel	= cpsw_get_msglevel,
 	.set_msglevel	= cpsw_set_msglevel,
 	.get_link	= ethtool_op_get_link,
+	.get_ts_info	= cpsw_get_ts_info,
 };
 
-static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv)
+static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
+			    u32 slave_reg_ofs, u32 sliver_reg_ofs)
 {
 	void __iomem		*regs = priv->regs;
 	int			slave_num = slave->slave_num;
 	struct cpsw_slave_data	*data = priv->data.slave_data + slave_num;
 
 	slave->data	= data;
-	slave->regs	= regs + data->slave_reg_ofs;
-	slave->sliver	= regs + data->sliver_reg_ofs;
+	slave->regs	= regs + slave_reg_ofs;
+	slave->sliver	= regs + sliver_reg_ofs;
 }
 
 static int cpsw_probe_dt(struct cpsw_platform_data *data,
@@ -734,49 +1031,40 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
 	}
 	data->slaves = prop;
 
-	data->slave_data = kzalloc(sizeof(struct cpsw_slave_data) *
-				   data->slaves, GFP_KERNEL);
-	if (!data->slave_data) {
-		pr_err("Could not allocate slave memory.\n");
-		return -EINVAL;
-	}
-
-	data->no_bd_ram = of_property_read_bool(node, "no_bd_ram");
-
-	if (of_property_read_u32(node, "cpdma_channels", &prop)) {
-		pr_err("Missing cpdma_channels property in the DT.\n");
+	if (of_property_read_u32(node, "cpts_active_slave", &prop)) {
+		pr_err("Missing cpts_active_slave property in the DT.\n");
 		ret = -EINVAL;
 		goto error_ret;
 	}
-	data->channels = prop;
+	data->cpts_active_slave = prop;
 
-	if (of_property_read_u32(node, "host_port_no", &prop)) {
-		pr_err("Missing host_port_no property in the DT.\n");
+	if (of_property_read_u32(node, "cpts_clock_mult", &prop)) {
+		pr_err("Missing cpts_clock_mult property in the DT.\n");
 		ret = -EINVAL;
 		goto error_ret;
 	}
-	data->host_port_num = prop;
+	data->cpts_clock_mult = prop;
 
-	if (of_property_read_u32(node, "cpdma_reg_ofs", &prop)) {
-		pr_err("Missing cpdma_reg_ofs property in the DT.\n");
+	if (of_property_read_u32(node, "cpts_clock_shift", &prop)) {
+		pr_err("Missing cpts_clock_shift property in the DT.\n");
 		ret = -EINVAL;
 		goto error_ret;
 	}
-	data->cpdma_reg_ofs = prop;
+	data->cpts_clock_shift = prop;
 
-	if (of_property_read_u32(node, "cpdma_sram_ofs", &prop)) {
-		pr_err("Missing cpdma_sram_ofs property in the DT.\n");
-		ret = -EINVAL;
-		goto error_ret;
+	data->slave_data = kzalloc(sizeof(struct cpsw_slave_data) *
+				   data->slaves, GFP_KERNEL);
+	if (!data->slave_data) {
+		pr_err("Could not allocate slave memory.\n");
+		return -EINVAL;
 	}
-	data->cpdma_sram_ofs = prop;
 
-	if (of_property_read_u32(node, "ale_reg_ofs", &prop)) {
-		pr_err("Missing ale_reg_ofs property in the DT.\n");
+	if (of_property_read_u32(node, "cpdma_channels", &prop)) {
+		pr_err("Missing cpdma_channels property in the DT.\n");
 		ret = -EINVAL;
 		goto error_ret;
 	}
-	data->ale_reg_ofs = prop;
+	data->channels = prop;
 
 	if (of_property_read_u32(node, "ale_entries", &prop)) {
 		pr_err("Missing ale_entries property in the DT.\n");
@@ -785,27 +1073,6 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
 	}
 	data->ale_entries = prop;
 
-	if (of_property_read_u32(node, "host_port_reg_ofs", &prop)) {
-		pr_err("Missing host_port_reg_ofs property in the DT.\n");
-		ret = -EINVAL;
-		goto error_ret;
-	}
-	data->host_port_reg_ofs = prop;
-
-	if (of_property_read_u32(node, "hw_stats_reg_ofs", &prop)) {
-		pr_err("Missing hw_stats_reg_ofs property in the DT.\n");
-		ret = -EINVAL;
-		goto error_ret;
-	}
-	data->hw_stats_reg_ofs = prop;
-
-	if (of_property_read_u32(node, "bd_ram_ofs", &prop)) {
-		pr_err("Missing bd_ram_ofs property in the DT.\n");
-		ret = -EINVAL;
-		goto error_ret;
-	}
-	data->bd_ram_ofs = prop;
-
 	if (of_property_read_u32(node, "bd_ram_size", &prop)) {
 		pr_err("Missing bd_ram_size property in the DT.\n");
 		ret = -EINVAL;
@@ -827,33 +1094,34 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
 	}
 	data->mac_control = prop;
 
-	for_each_child_of_node(node, slave_node) {
+	/*
+	 * Populate all the child nodes here...
+	 */
+	ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
+	/* We do not want to force this, as in some cases may not have child */
+	if (ret)
+		pr_warn("Doesn't have any child node\n");
+
+	for_each_node_by_name(slave_node, "slave") {
 		struct cpsw_slave_data *slave_data = data->slave_data + i;
-		const char *phy_id = NULL;
 		const void *mac_addr = NULL;
-
-		if (of_property_read_string(slave_node, "phy_id", &phy_id)) {
+		u32 phyid;
+		int lenp;
+		const __be32 *parp;
+		struct device_node *mdio_node;
+		struct platform_device *mdio;
+
+		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);
 			ret = -EINVAL;
 			goto error_ret;
 		}
-		slave_data->phy_id = phy_id;
-
-		if (of_property_read_u32(slave_node, "slave_reg_ofs", &prop)) {
-			pr_err("Missing slave[%d] slave_reg_ofs property\n", i);
-			ret = -EINVAL;
-			goto error_ret;
-		}
-		slave_data->slave_reg_ofs = prop;
-
-		if (of_property_read_u32(slave_node, "sliver_reg_ofs",
-					 &prop)) {
-			pr_err("Missing slave[%d] sliver_reg_ofs property\n",
-				i);
-			ret = -EINVAL;
-			goto error_ret;
-		}
-		slave_data->sliver_reg_ofs = prop;
+		mdio_node = of_find_node_by_phandle(be32_to_cpup(parp));
+		phyid = be32_to_cpup(parp+1);
+		mdio = of_find_device_by_node(mdio_node);
+		snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
+			 PHY_ID_FMT, mdio->name, phyid);
 
 		mac_addr = of_get_mac_address(slave_node);
 		if (mac_addr)
@@ -876,8 +1144,9 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
 	struct cpsw_priv		*priv;
 	struct cpdma_params		dma_params;
 	struct cpsw_ale_params		ale_params;
-	void __iomem			*regs;
+	void __iomem			*ss_regs, *wr_regs;
 	struct resource			*res;
+	u32 slave_offset, sliver_offset, slave_size;
 	int ret = 0, i, k = 0;
 
 	ndev = alloc_etherdev(sizeof(struct cpsw_priv));
@@ -895,6 +1164,11 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
 	priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
 	priv->rx_packet_max = max(rx_packet_max, 128);
 
+	/*
+	 * This may be required here for child devices.
+	 */
+	pm_runtime_enable(&pdev->dev);
+
 	if (cpsw_probe_dt(&priv->data, pdev)) {
 		pr_err("cpsw: platform data missing\n");
 		ret = -ENODEV;
@@ -921,7 +1195,6 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
 	for (i = 0; i < data->slaves; i++)
 		priv->slaves[i].slave_num = i;
 
-	pm_runtime_enable(&pdev->dev);
 	priv->clk = clk_get(&pdev->dev, "fck");
 	if (IS_ERR(priv->clk)) {
 		dev_err(&pdev->dev, "fck is not found\n");
@@ -935,63 +1208,86 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
 		ret = -ENOENT;
 		goto clean_clk_ret;
 	}
-
 	if (!request_mem_region(priv->cpsw_res->start,
 				resource_size(priv->cpsw_res), ndev->name)) {
 		dev_err(priv->dev, "failed request i/o region\n");
 		ret = -ENXIO;
 		goto clean_clk_ret;
 	}
-
-	regs = ioremap(priv->cpsw_res->start, resource_size(priv->cpsw_res));
-	if (!regs) {
+	ss_regs = ioremap(priv->cpsw_res->start, resource_size(priv->cpsw_res));
+	if (!ss_regs) {
 		dev_err(priv->dev, "unable to map i/o region\n");
 		goto clean_cpsw_iores_ret;
 	}
-	priv->regs = regs;
-	priv->host_port = data->host_port_num;
-	priv->host_port_regs = regs + data->host_port_reg_ofs;
+	priv->regs = ss_regs;
+	priv->version = __raw_readl(&priv->regs->id_ver);
+	priv->host_port = HOST_PORT_NUM;
 
-	priv->cpsw_ss_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (!priv->cpsw_ss_res) {
+	priv->cpsw_wr_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!priv->cpsw_wr_res) {
 		dev_err(priv->dev, "error getting i/o resource\n");
 		ret = -ENOENT;
-		goto clean_clk_ret;
+		goto clean_iomap_ret;
 	}
-
-	if (!request_mem_region(priv->cpsw_ss_res->start,
-			resource_size(priv->cpsw_ss_res), ndev->name)) {
+	if (!request_mem_region(priv->cpsw_wr_res->start,
+			resource_size(priv->cpsw_wr_res), ndev->name)) {
 		dev_err(priv->dev, "failed request i/o region\n");
 		ret = -ENXIO;
-		goto clean_clk_ret;
+		goto clean_iomap_ret;
 	}
-
-	regs = ioremap(priv->cpsw_ss_res->start,
-				resource_size(priv->cpsw_ss_res));
-	if (!regs) {
+	wr_regs = ioremap(priv->cpsw_wr_res->start,
+				resource_size(priv->cpsw_wr_res));
+	if (!wr_regs) {
 		dev_err(priv->dev, "unable to map i/o region\n");
-		goto clean_cpsw_ss_iores_ret;
+		goto clean_cpsw_wr_iores_ret;
 	}
-	priv->ss_regs = regs;
-
-	for_each_slave(priv, cpsw_slave_init, priv);
+	priv->wr_regs = wr_regs;
 
 	memset(&dma_params, 0, sizeof(dma_params));
+	memset(&ale_params, 0, sizeof(ale_params));
+
+	switch (priv->version) {
+	case CPSW_VERSION_1:
+		priv->host_port_regs = ss_regs + CPSW1_HOST_PORT_OFFSET;
+		priv->cpts.reg       = ss_regs + CPSW1_CPTS_OFFSET;
+		dma_params.dmaregs   = ss_regs + CPSW1_CPDMA_OFFSET;
+		dma_params.txhdp     = ss_regs + CPSW1_STATERAM_OFFSET;
+		ale_params.ale_regs  = ss_regs + CPSW1_ALE_OFFSET;
+		slave_offset         = CPSW1_SLAVE_OFFSET;
+		slave_size           = CPSW1_SLAVE_SIZE;
+		sliver_offset        = CPSW1_SLIVER_OFFSET;
+		dma_params.desc_mem_phys = 0;
+		break;
+	case CPSW_VERSION_2:
+		priv->host_port_regs = ss_regs + CPSW2_HOST_PORT_OFFSET;
+		priv->cpts.reg       = ss_regs + CPSW2_CPTS_OFFSET;
+		dma_params.dmaregs   = ss_regs + CPSW2_CPDMA_OFFSET;
+		dma_params.txhdp     = ss_regs + CPSW2_STATERAM_OFFSET;
+		ale_params.ale_regs  = ss_regs + CPSW2_ALE_OFFSET;
+		slave_offset         = CPSW2_SLAVE_OFFSET;
+		slave_size           = CPSW2_SLAVE_SIZE;
+		sliver_offset        = CPSW2_SLIVER_OFFSET;
+		dma_params.desc_mem_phys =
+			(u32 __force) priv->cpsw_res->start + CPSW2_BD_OFFSET;
+		break;
+	default:
+		dev_err(priv->dev, "unknown version 0x%08x\n", priv->version);
+		ret = -ENODEV;
+		goto clean_cpsw_wr_iores_ret;
+	}
+	for (i = 0; i < priv->data.slaves; i++) {
+		struct cpsw_slave *slave = &priv->slaves[i];
+		cpsw_slave_init(slave, priv, slave_offset, sliver_offset);
+		slave_offset  += slave_size;
+		sliver_offset += SLIVER_SIZE;
+	}
+
 	dma_params.dev		= &pdev->dev;
-	dma_params.dmaregs	= cpsw_dma_regs((u32)priv->regs,
-						data->cpdma_reg_ofs);
-	dma_params.rxthresh	= cpsw_dma_rxthresh((u32)priv->regs,
-						    data->cpdma_reg_ofs);
-	dma_params.rxfree	= cpsw_dma_rxfree((u32)priv->regs,
-						  data->cpdma_reg_ofs);
-	dma_params.txhdp	= cpsw_dma_txhdp((u32)priv->regs,
-						 data->cpdma_sram_ofs);
-	dma_params.rxhdp	= cpsw_dma_rxhdp((u32)priv->regs,
-						 data->cpdma_sram_ofs);
-	dma_params.txcp		= cpsw_dma_txcp((u32)priv->regs,
-						data->cpdma_sram_ofs);
-	dma_params.rxcp		= cpsw_dma_rxcp((u32)priv->regs,
-						data->cpdma_sram_ofs);
+	dma_params.rxthresh	= dma_params.dmaregs + CPDMA_RXTHRESH;
+	dma_params.rxfree	= dma_params.dmaregs + CPDMA_RXFREE;
+	dma_params.rxhdp	= dma_params.txhdp + CPDMA_RXHDP;
+	dma_params.txcp		= dma_params.txhdp + CPDMA_TXCP;
+	dma_params.rxcp		= dma_params.txhdp + CPDMA_RXCP;
 
 	dma_params.num_chan		= data->channels;
 	dma_params.has_soft_reset	= true;
@@ -999,16 +1295,13 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
 	dma_params.desc_mem_size	= data->bd_ram_size;
 	dma_params.desc_align		= 16;
 	dma_params.has_ext_regs		= true;
-	dma_params.desc_mem_phys        = data->no_bd_ram ? 0 :
-			(u32 __force)priv->cpsw_res->start + data->bd_ram_ofs;
-	dma_params.desc_hw_addr         = data->hw_ram_addr ?
-			data->hw_ram_addr : dma_params.desc_mem_phys ;
+	dma_params.desc_hw_addr         = dma_params.desc_mem_phys;
 
 	priv->dma = cpdma_ctlr_create(&dma_params);
 	if (!priv->dma) {
 		dev_err(priv->dev, "error initializing dma\n");
 		ret = -ENOMEM;
-		goto clean_iomap_ret;
+		goto clean_wr_iomap_ret;
 	}
 
 	priv->txch = cpdma_chan_create(priv->dma, tx_chan_num(0),
@@ -1022,10 +1315,7 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
 		goto clean_dma_ret;
 	}
 
-	memset(&ale_params, 0, sizeof(ale_params));
 	ale_params.dev			= &ndev->dev;
-	ale_params.ale_regs		= (void *)((u32)priv->regs) +
-						((u32)data->ale_reg_ofs);
 	ale_params.ale_ageout		= ale_ageout;
 	ale_params.ale_entries		= data->ale_entries;
 	ale_params.ale_ports		= data->slaves;
@@ -1072,6 +1362,10 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
 		goto clean_irq_ret;
 	}
 
+	if (cpts_register(&pdev->dev, &priv->cpts,
+			  data->cpts_clock_mult, data->cpts_clock_shift))
+		dev_err(priv->dev, "error registering cpts device\n");
+
 	cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n",
 		  priv->cpsw_res->start, ndev->irq);
 
@@ -1085,11 +1379,13 @@ clean_dma_ret:
 	cpdma_chan_destroy(priv->txch);
 	cpdma_chan_destroy(priv->rxch);
 	cpdma_ctlr_destroy(priv->dma);
+clean_wr_iomap_ret:
+	iounmap(priv->wr_regs);
+clean_cpsw_wr_iores_ret:
+	release_mem_region(priv->cpsw_wr_res->start,
+			   resource_size(priv->cpsw_wr_res));
 clean_iomap_ret:
 	iounmap(priv->regs);
-clean_cpsw_ss_iores_ret:
-	release_mem_region(priv->cpsw_ss_res->start,
-			   resource_size(priv->cpsw_ss_res));
 clean_cpsw_iores_ret:
 	release_mem_region(priv->cpsw_res->start,
 			   resource_size(priv->cpsw_res));
@@ -1111,6 +1407,7 @@ static int __devexit cpsw_remove(struct platform_device *pdev)
 	pr_info("removing device");
 	platform_set_drvdata(pdev, NULL);
 
+	cpts_unregister(&priv->cpts);
 	free_irq(ndev->irq, priv);
 	cpsw_ale_destroy(priv->ale);
 	cpdma_chan_destroy(priv->txch);
@@ -1119,8 +1416,9 @@ static int __devexit cpsw_remove(struct platform_device *pdev)
 	iounmap(priv->regs);
 	release_mem_region(priv->cpsw_res->start,
 			   resource_size(priv->cpsw_res));
-	release_mem_region(priv->cpsw_ss_res->start,
-			   resource_size(priv->cpsw_ss_res));
+	iounmap(priv->wr_regs);
+	release_mem_region(priv->cpsw_wr_res->start,
+			   resource_size(priv->cpsw_wr_res));
 	pm_runtime_disable(&pdev->dev);
 	clk_put(priv->clk);
 	kfree(priv->slaves);
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index ca0d48a..0e9ccc2 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -20,6 +20,7 @@
 #include <linux/io.h>
 #include <linux/stat.h>
 #include <linux/sysfs.h>
+#include <linux/etherdevice.h>
 
 #include "cpsw_ale.h"
 
@@ -211,10 +212,34 @@ static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry,
 	mask &= ~port_mask;
 
 	/* free if only remaining port is host port */
-	if (mask == BIT(ale->params.ale_ports))
-		cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
-	else
+	if (mask)
 		cpsw_ale_set_port_mask(ale_entry, mask);
+	else
+		cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
+}
+
+int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask)
+{
+	u32 ale_entry[ALE_ENTRY_WORDS];
+	int ret, idx;
+
+	for (idx = 0; idx < ale->params.ale_entries; idx++) {
+		cpsw_ale_read(ale, idx, ale_entry);
+		ret = cpsw_ale_get_entry_type(ale_entry);
+		if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR)
+			continue;
+
+		if (cpsw_ale_get_mcast(ale_entry)) {
+			u8 addr[6];
+
+			cpsw_ale_get_addr(ale_entry, addr);
+			if (!is_broadcast_ether_addr(addr))
+				cpsw_ale_flush_mcast(ale, ale_entry, port_mask);
+		}
+
+		cpsw_ale_write(ale, idx, ale_entry);
+	}
+	return 0;
 }
 
 static void cpsw_ale_flush_ucast(struct cpsw_ale *ale, u32 *ale_entry,
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index a95b37b..2bd09cb 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.h
+++ b/drivers/net/ethernet/ti/cpsw_ale.h
@@ -80,6 +80,7 @@ void cpsw_ale_stop(struct cpsw_ale *ale);
 
 int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout);
 int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask);
+int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask);
 int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags);
 int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port);
 int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c
new file mode 100644
index 0000000..3377667
--- /dev/null
+++ b/drivers/net/ethernet/ti/cpts.c
@@ -0,0 +1,427 @@
+/*
+ * TI Common Platform Time Sync
+ *
+ * Copyright (C) 2012 Richard Cochran <richardcochran@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/err.h>
+#include <linux/if.h>
+#include <linux/hrtimer.h>
+#include <linux/module.h>
+#include <linux/net_tstamp.h>
+#include <linux/ptp_classify.h>
+#include <linux/time.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+
+#include <plat/clock.h>
+
+#include "cpts.h"
+
+#ifdef CONFIG_TI_CPTS
+
+static struct sock_filter ptp_filter[] = {
+	PTP_FILTER
+};
+
+#define cpts_read32(c, r)	__raw_readl(&c->reg->r)
+#define cpts_write32(c, v, r)	__raw_writel(v, &c->reg->r)
+
+static int event_expired(struct cpts_event *event)
+{
+	return time_after(jiffies, event->tmo);
+}
+
+static int event_type(struct cpts_event *event)
+{
+	return (event->high >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK;
+}
+
+static int cpts_fifo_pop(struct cpts *cpts, u32 *high, u32 *low)
+{
+	u32 r = cpts_read32(cpts, intstat_raw);
+
+	if (r & TS_PEND_RAW) {
+		*high = cpts_read32(cpts, event_high);
+		*low  = cpts_read32(cpts, event_low);
+		cpts_write32(cpts, EVENT_POP, event_pop);
+		return 0;
+	}
+	return -1;
+}
+
+/*
+ * Returns zero if matching event type was found.
+ */
+static int cpts_fifo_read(struct cpts *cpts, int match)
+{
+	int i, type = -1;
+	u32 hi, lo;
+	struct cpts_event *event;
+
+	for (i = 0; i < CPTS_FIFO_DEPTH; i++) {
+		if (cpts_fifo_pop(cpts, &hi, &lo))
+			break;
+		if (list_empty(&cpts->pool)) {
+			pr_err("cpts: event pool is empty\n");
+			return -1;
+		}
+		event = list_first_entry(&cpts->pool, struct cpts_event, list);
+		event->tmo = jiffies + 2;
+		event->high = hi;
+		event->low = lo;
+		type = event_type(event);
+		switch (type) {
+		case CPTS_EV_PUSH:
+		case CPTS_EV_RX:
+		case CPTS_EV_TX:
+			list_del_init(&event->list);
+			list_add_tail(&event->list, &cpts->events);
+			break;
+		case CPTS_EV_ROLL:
+		case CPTS_EV_HALF:
+		case CPTS_EV_HW:
+			break;
+		default:
+			pr_err("cpts: unkown event type\n");
+			break;
+		}
+		if (type == match)
+			break;
+	}
+	return type == match ? 0 : -1;
+}
+
+static cycle_t cpts_systim_read(const struct cyclecounter *cc)
+{
+	u64 val = 0;
+	struct cpts_event *event;
+	struct list_head *this, *next;
+	struct cpts *cpts = container_of(cc, struct cpts, cc);
+
+	cpts_write32(cpts, TS_PUSH, ts_push);
+	if (cpts_fifo_read(cpts, CPTS_EV_PUSH))
+		pr_err("cpts: unable to obtain a time stamp\n");
+
+	list_for_each_safe(this, next, &cpts->events) {
+		event = list_entry(this, struct cpts_event, list);
+		if (event_type(event) == CPTS_EV_PUSH) {
+			list_del_init(&event->list);
+			list_add(&event->list, &cpts->pool);
+			val = event->low;
+			break;
+		}
+	}
+
+	return val;
+}
+
+/* PTP clock operations */
+
+static int cpts_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+	u64 adj;
+	u32 diff, mult;
+	int neg_adj = 0;
+	unsigned long flags;
+	struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+	if (ppb < 0) {
+		neg_adj = 1;
+		ppb = -ppb;
+	}
+	mult = cpts->cc_mult;
+	adj = mult;
+	adj *= ppb;
+	diff = div_u64(adj, 1000000000ULL);
+
+	spin_lock_irqsave(&cpts->lock, flags);
+
+	timecounter_read(&cpts->tc);
+
+	cpts->cc.mult = neg_adj ? mult - diff : mult + diff;
+
+	spin_unlock_irqrestore(&cpts->lock, flags);
+
+	return 0;
+}
+
+static int cpts_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	s64 now;
+	unsigned long flags;
+	struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+	spin_lock_irqsave(&cpts->lock, flags);
+	now = timecounter_read(&cpts->tc);
+	now += delta;
+	timecounter_init(&cpts->tc, &cpts->cc, now);
+	spin_unlock_irqrestore(&cpts->lock, flags);
+
+	return 0;
+}
+
+static int cpts_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+	u64 ns;
+	u32 remainder;
+	unsigned long flags;
+	struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+	spin_lock_irqsave(&cpts->lock, flags);
+	ns = timecounter_read(&cpts->tc);
+	spin_unlock_irqrestore(&cpts->lock, flags);
+
+	ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
+	ts->tv_nsec = remainder;
+
+	return 0;
+}
+
+static int cpts_ptp_settime(struct ptp_clock_info *ptp,
+			    const struct timespec *ts)
+{
+	u64 ns;
+	unsigned long flags;
+	struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+	ns = ts->tv_sec * 1000000000ULL;
+	ns += ts->tv_nsec;
+
+	spin_lock_irqsave(&cpts->lock, flags);
+	timecounter_init(&cpts->tc, &cpts->cc, ns);
+	spin_unlock_irqrestore(&cpts->lock, flags);
+
+	return 0;
+}
+
+static int cpts_ptp_enable(struct ptp_clock_info *ptp,
+			   struct ptp_clock_request *rq, int on)
+{
+	return -EOPNOTSUPP;
+}
+
+static struct ptp_clock_info cpts_info = {
+	.owner		= THIS_MODULE,
+	.name		= "CTPS timer",
+	.max_adj	= 1000000,
+	.n_ext_ts	= 0,
+	.pps		= 0,
+	.adjfreq	= cpts_ptp_adjfreq,
+	.adjtime	= cpts_ptp_adjtime,
+	.gettime	= cpts_ptp_gettime,
+	.settime	= cpts_ptp_settime,
+	.enable		= cpts_ptp_enable,
+};
+
+static void cpts_overflow_check(struct work_struct *work)
+{
+	struct timespec ts;
+	struct cpts *cpts = container_of(work, struct cpts, overflow_work.work);
+
+	cpts_write32(cpts, CPTS_EN, control);
+	cpts_write32(cpts, TS_PEND_EN, int_enable);
+	cpts_ptp_gettime(&cpts->info, &ts);
+	pr_debug("cpts overflow check at %ld.%09lu\n", ts.tv_sec, ts.tv_nsec);
+	schedule_delayed_work(&cpts->overflow_work, CPTS_OVERFLOW_PERIOD);
+}
+
+#define CPTS_REF_CLOCK_NAME "cpsw_cpts_rft_clk"
+
+static void cpts_clk_init(struct cpts *cpts)
+{
+	cpts->refclk = clk_get(NULL, CPTS_REF_CLOCK_NAME);
+	if (IS_ERR(cpts->refclk)) {
+		pr_err("Failed to clk_get %s\n", CPTS_REF_CLOCK_NAME);
+		cpts->refclk = NULL;
+		return;
+	}
+	clk_enable(cpts->refclk);
+	cpts->freq = cpts->refclk->recalc(cpts->refclk);
+}
+
+static void cpts_clk_release(struct cpts *cpts)
+{
+	clk_disable(cpts->refclk);
+	clk_put(cpts->refclk);
+}
+
+static int cpts_match(struct sk_buff *skb, unsigned int ptp_class,
+		      u16 ts_seqid, u8 ts_msgtype)
+{
+	u16 *seqid;
+	unsigned int offset;
+	u8 *msgtype, *data = skb->data;
+
+	switch (ptp_class) {
+	case PTP_CLASS_V1_IPV4:
+	case PTP_CLASS_V2_IPV4:
+		offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
+		break;
+	case PTP_CLASS_V1_IPV6:
+	case PTP_CLASS_V2_IPV6:
+		offset = OFF_PTP6;
+		break;
+	case PTP_CLASS_V2_L2:
+		offset = ETH_HLEN;
+		break;
+	case PTP_CLASS_V2_VLAN:
+		offset = ETH_HLEN + VLAN_HLEN;
+		break;
+	default:
+		return 0;
+	}
+
+	if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid))
+		return 0;
+
+	if (unlikely(ptp_class & PTP_CLASS_V1))
+		msgtype = data + offset + OFF_PTP_CONTROL;
+	else
+		msgtype = data + offset;
+
+	seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
+
+	return (ts_msgtype == (*msgtype & 0xf) && ts_seqid == ntohs(*seqid));
+}
+
+static u64 cpts_find_ts(struct cpts *cpts, struct sk_buff *skb, int ev_type)
+{
+	u64 ns = 0;
+	struct cpts_event *event;
+	struct list_head *this, *next;
+	unsigned int class = sk_run_filter(skb, ptp_filter);
+	unsigned long flags;
+	u16 seqid;
+	u8 mtype;
+
+	if (class == PTP_CLASS_NONE)
+		return 0;
+
+	spin_lock_irqsave(&cpts->lock, flags);
+	cpts_fifo_read(cpts, CPTS_EV_PUSH);
+	list_for_each_safe(this, next, &cpts->events) {
+		event = list_entry(this, struct cpts_event, list);
+		if (event_expired(event)) {
+			list_del_init(&event->list);
+			list_add(&event->list, &cpts->pool);
+			continue;
+		}
+		mtype = (event->high >> MESSAGE_TYPE_SHIFT) & MESSAGE_TYPE_MASK;
+		seqid = (event->high >> SEQUENCE_ID_SHIFT) & SEQUENCE_ID_MASK;
+		if (ev_type == event_type(event) &&
+		    cpts_match(skb, class, seqid, mtype)) {
+			ns = timecounter_cyc2time(&cpts->tc, event->low);
+			list_del_init(&event->list);
+			list_add(&event->list, &cpts->pool);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&cpts->lock, flags);
+
+	return ns;
+}
+
+void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb)
+{
+	u64 ns;
+	struct skb_shared_hwtstamps *ssh;
+
+	if (!cpts->rx_enable)
+		return;
+	ns = cpts_find_ts(cpts, skb, CPTS_EV_RX);
+	if (!ns)
+		return;
+	ssh = skb_hwtstamps(skb);
+	memset(ssh, 0, sizeof(*ssh));
+	ssh->hwtstamp = ns_to_ktime(ns);
+}
+
+void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb)
+{
+	u64 ns;
+	struct skb_shared_hwtstamps ssh;
+
+	if (!(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
+		return;
+	ns = cpts_find_ts(cpts, skb, CPTS_EV_TX);
+	if (!ns)
+		return;
+	memset(&ssh, 0, sizeof(ssh));
+	ssh.hwtstamp = ns_to_ktime(ns);
+	skb_tstamp_tx(skb, &ssh);
+}
+
+#endif /*CONFIG_TI_CPTS*/
+
+int cpts_register(struct device *dev, struct cpts *cpts,
+		  u32 mult, u32 shift)
+{
+#ifdef CONFIG_TI_CPTS
+	int err, i;
+	unsigned long flags;
+
+	if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) {
+		pr_err("cpts: bad ptp filter\n");
+		return -EINVAL;
+	}
+	cpts->info = cpts_info;
+	cpts->clock = ptp_clock_register(&cpts->info, dev);
+	if (IS_ERR(cpts->clock)) {
+		err = PTR_ERR(cpts->clock);
+		cpts->clock = NULL;
+		return err;
+	}
+	spin_lock_init(&cpts->lock);
+
+	cpts->cc.read = cpts_systim_read;
+	cpts->cc.mask = CLOCKSOURCE_MASK(32);
+	cpts->cc_mult = mult;
+	cpts->cc.mult = mult;
+	cpts->cc.shift = shift;
+
+	INIT_LIST_HEAD(&cpts->events);
+	INIT_LIST_HEAD(&cpts->pool);
+	for (i = 0; i < CPTS_MAX_EVENTS; i++)
+		list_add(&cpts->pool_data[i].list, &cpts->pool);
+
+	cpts_clk_init(cpts);
+	cpts_write32(cpts, CPTS_EN, control);
+	cpts_write32(cpts, TS_PEND_EN, int_enable);
+
+	spin_lock_irqsave(&cpts->lock, flags);
+	timecounter_init(&cpts->tc, &cpts->cc, ktime_to_ns(ktime_get_real()));
+	spin_unlock_irqrestore(&cpts->lock, flags);
+
+	INIT_DELAYED_WORK(&cpts->overflow_work, cpts_overflow_check);
+	schedule_delayed_work(&cpts->overflow_work, CPTS_OVERFLOW_PERIOD);
+
+	cpts->phc_index = ptp_clock_index(cpts->clock);
+#endif
+	return 0;
+}
+
+void cpts_unregister(struct cpts *cpts)
+{
+#ifdef CONFIG_TI_CPTS
+	if (cpts->clock) {
+		ptp_clock_unregister(cpts->clock);
+		cancel_delayed_work_sync(&cpts->overflow_work);
+	}
+	if (cpts->refclk)
+		cpts_clk_release(cpts);
+#endif
+}
diff --git a/drivers/net/ethernet/ti/cpts.h b/drivers/net/ethernet/ti/cpts.h
new file mode 100644
index 0000000..e1bba3a
--- /dev/null
+++ b/drivers/net/ethernet/ti/cpts.h
@@ -0,0 +1,146 @@
+/*
+ * TI Common Platform Time Sync
+ *
+ * Copyright (C) 2012 Richard Cochran <richardcochran@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef _TI_CPTS_H_
+#define _TI_CPTS_H_
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clocksource.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/skbuff.h>
+
+struct cpsw_cpts {
+	u32 idver;                /* Identification and version */
+	u32 control;              /* Time sync control */
+	u32 res1;
+	u32 ts_push;              /* Time stamp event push */
+	u32 ts_load_val;          /* Time stamp load value */
+	u32 ts_load_en;           /* Time stamp load enable */
+	u32 res2[2];
+	u32 intstat_raw;          /* Time sync interrupt status raw */
+	u32 intstat_masked;       /* Time sync interrupt status masked */
+	u32 int_enable;           /* Time sync interrupt enable */
+	u32 res3;
+	u32 event_pop;            /* Event interrupt pop */
+	u32 event_low;            /* 32 Bit Event Time Stamp */
+	u32 event_high;           /* Event Type Fields */
+};
+
+/* Bit definitions for the IDVER register */
+#define TX_IDENT_SHIFT       (16)    /* TX Identification Value */
+#define TX_IDENT_MASK        (0xffff)
+#define RTL_VER_SHIFT        (11)    /* RTL Version Value */
+#define RTL_VER_MASK         (0x1f)
+#define MAJOR_VER_SHIFT      (8)     /* Major Version Value */
+#define MAJOR_VER_MASK       (0x7)
+#define MINOR_VER_SHIFT      (0)     /* Minor Version Value */
+#define MINOR_VER_MASK       (0xff)
+
+/* Bit definitions for the CONTROL register */
+#define HW4_TS_PUSH_EN       (1<<11) /* Hardware push 4 enable */
+#define HW3_TS_PUSH_EN       (1<<10) /* Hardware push 3 enable */
+#define HW2_TS_PUSH_EN       (1<<9)  /* Hardware push 2 enable */
+#define HW1_TS_PUSH_EN       (1<<8)  /* Hardware push 1 enable */
+#define INT_TEST             (1<<1)  /* Interrupt Test */
+#define CPTS_EN              (1<<0)  /* Time Sync Enable */
+
+/*
+ * Definitions for the single bit resisters:
+ * TS_PUSH TS_LOAD_EN  INTSTAT_RAW INTSTAT_MASKED INT_ENABLE EVENT_POP
+ */
+#define TS_PUSH             (1<<0)  /* Time stamp event push */
+#define TS_LOAD_EN          (1<<0)  /* Time Stamp Load */
+#define TS_PEND_RAW         (1<<0)  /* int read (before enable) */
+#define TS_PEND             (1<<0)  /* masked interrupt read (after enable) */
+#define TS_PEND_EN          (1<<0)  /* masked interrupt enable */
+#define EVENT_POP           (1<<0)  /* writing discards one event */
+
+/* Bit definitions for the EVENT_HIGH register */
+#define PORT_NUMBER_SHIFT    (24)    /* Indicates Ethernet port or HW pin */
+#define PORT_NUMBER_MASK     (0x1f)
+#define EVENT_TYPE_SHIFT     (20)    /* Time sync event type */
+#define EVENT_TYPE_MASK      (0xf)
+#define MESSAGE_TYPE_SHIFT   (16)    /* PTP message type */
+#define MESSAGE_TYPE_MASK    (0xf)
+#define SEQUENCE_ID_SHIFT    (0)     /* PTP message sequence ID */
+#define SEQUENCE_ID_MASK     (0xffff)
+
+enum {
+	CPTS_EV_PUSH, /* Time Stamp Push Event */
+	CPTS_EV_ROLL, /* Time Stamp Rollover Event */
+	CPTS_EV_HALF, /* Time Stamp Half Rollover Event */
+	CPTS_EV_HW,   /* Hardware Time Stamp Push Event */
+	CPTS_EV_RX,   /* Ethernet Receive Event */
+	CPTS_EV_TX,   /* Ethernet Transmit Event */
+};
+
+/* This covers any input clock up to about 500 MHz. */
+#define CPTS_OVERFLOW_PERIOD (HZ * 8)
+
+#define CPTS_FIFO_DEPTH 16
+#define CPTS_MAX_EVENTS 32
+
+struct cpts_event {
+	struct list_head list;
+	unsigned long tmo;
+	u32 high;
+	u32 low;
+};
+
+struct cpts {
+	struct cpsw_cpts __iomem *reg;
+	int tx_enable;
+	int rx_enable;
+#ifdef CONFIG_TI_CPTS
+	struct ptp_clock_info info;
+	struct ptp_clock *clock;
+	spinlock_t lock; /* protects time registers */
+	u32 cc_mult; /* for the nominal frequency */
+	struct cyclecounter cc;
+	struct timecounter tc;
+	struct delayed_work overflow_work;
+	int phc_index;
+	struct clk *refclk;
+	unsigned long freq;
+	struct list_head events;
+	struct list_head pool;
+	struct cpts_event pool_data[CPTS_MAX_EVENTS];
+#endif
+};
+
+#ifdef CONFIG_TI_CPTS
+extern void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb);
+extern void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb);
+#else
+static inline void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb)
+{
+}
+static inline void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb)
+{
+}
+#endif
+
+extern int cpts_register(struct device *dev, struct cpts *cpts,
+			 u32 mult, u32 shift);
+extern void cpts_unregister(struct cpts *cpts);
+
+#endif
diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
index 51a96db..ae74280 100644
--- a/drivers/net/ethernet/ti/davinci_mdio.c
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
@@ -465,7 +465,7 @@ static int davinci_mdio_resume(struct device *dev)
 	u32 ctrl;
 
 	spin_lock(&data->lock);
-	pm_runtime_put_sync(data->dev);
+	pm_runtime_get_sync(data->dev);
 
 	/* restart the scan state machine */
 	ctrl = __raw_readl(&data->regs->control);
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
index 961c832..72b775f 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
@@ -452,7 +452,7 @@ static size_t gelic_wl_synthesize_ie(u8 *buf,
 	if (rsn)
 		*buf++ = WLAN_EID_RSN;
 	else
-		*buf++ = WLAN_EID_GENERIC;
+		*buf++ = WLAN_EID_VENDOR_SPECIFIC;
 
 	/* length filed; set later */
 	buf++;
@@ -540,7 +540,7 @@ static void gelic_wl_parse_ie(u8 *data, size_t len,
 			break;
 
 		switch (item_id) {
-		case WLAN_EID_GENERIC:
+		case WLAN_EID_VENDOR_SPECIFIC:
 			if ((OUI_LEN + 1 <= item_len) &&
 			    !memcmp(pos, wpa_oui, OUI_LEN) &&
 			    pos[OUI_LEN] == 0x01) {
diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c
index 2c08bf6..7daf92e 100644
--- a/drivers/net/ethernet/wiznet/w5100.c
+++ b/drivers/net/ethernet/wiznet/w5100.c
@@ -580,8 +580,6 @@ static int w5100_open(struct net_device *ndev)
 	struct w5100_priv *priv = netdev_priv(ndev);
 
 	netif_info(priv, ifup, ndev, "enabling\n");
-	if (!is_valid_ether_addr(ndev->dev_addr))
-		return -EINVAL;
 	w5100_hw_start(priv);
 	napi_enable(&priv->napi);
 	netif_start_queue(ndev);
diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c
index 88943d9..bd9eec6 100644
--- a/drivers/net/ethernet/wiznet/w5300.c
+++ b/drivers/net/ethernet/wiznet/w5300.c
@@ -500,8 +500,6 @@ static int w5300_open(struct net_device *ndev)
 	struct w5300_priv *priv = netdev_priv(ndev);
 
 	netif_info(priv, ifup, ndev, "enabling\n");
-	if (!is_valid_ether_addr(ndev->dev_addr))
-		return -EINVAL;
 	w5300_hw_start(priv);
 	napi_enable(&priv->napi);
 	netif_start_queue(ndev);
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 928148c..7fdeb52 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -363,11 +363,6 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
 
 	rndis_pkt = &msg->msg.pkt;
 
-	/*
-	 * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
-	 * netvsc packet (ie TotalDataBufferLength != MessageLength)
-	 */
-
 	/* Remove the rndis header and pass it back up the stack */
 	data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
 
diff --git a/drivers/net/irda/sh_irda.c b/drivers/net/irda/sh_irda.c
index 4b746d9..945360a 100644
--- a/drivers/net/irda/sh_irda.c
+++ b/drivers/net/irda/sh_irda.c
@@ -33,11 +33,7 @@
 
 #define DRIVER_NAME "sh_irda"
 
-#if defined(CONFIG_ARCH_SH7367) || defined(CONFIG_ARCH_SH7377)
-#define __IRDARAM_LEN	0x13FF
-#else
 #define __IRDARAM_LEN	0x1039
-#endif
 
 #define IRTMR		0x1F00 /* Transfer mode */
 #define IRCFR		0x1F02 /* Configuration */
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index b332112..6989ebe 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -56,6 +56,10 @@ static char config[MAX_PARAM_LENGTH];
 module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0);
 MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]");
 
+static bool oops_only = false;
+module_param(oops_only, bool, 0600);
+MODULE_PARM_DESC(oops_only, "Only log oops messages");
+
 #ifndef	MODULE
 static int __init option_setup(char *opt)
 {
@@ -683,6 +687,8 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
 	struct netconsole_target *nt;
 	const char *tmp;
 
+	if (oops_only && !oops_in_progress)
+		return;
 	/* Avoid taking lock and disabling interrupts unnecessarily */
 	if (list_empty(&target_list))
 		return;
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
index 81c7bc0..383e833 100644
--- a/drivers/net/phy/davicom.c
+++ b/drivers/net/phy/davicom.c
@@ -150,18 +150,24 @@ static struct phy_driver dm91xx_driver[] = {
 	.name		= "Davicom DM9161E",
 	.phy_id_mask	= 0x0ffffff0,
 	.features	= PHY_BASIC_FEATURES,
+	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= dm9161_config_init,
 	.config_aneg	= dm9161_config_aneg,
 	.read_status	= genphy_read_status,
+	.ack_interrupt	= dm9161_ack_interrupt,
+	.config_intr	= dm9161_config_intr,
 	.driver		= { .owner = THIS_MODULE,},
 }, {
 	.phy_id		= 0x0181b8a0,
 	.name		= "Davicom DM9161A",
 	.phy_id_mask	= 0x0ffffff0,
 	.features	= PHY_BASIC_FEATURES,
+	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= dm9161_config_init,
 	.config_aneg	= dm9161_config_aneg,
 	.read_status	= genphy_read_status,
+	.ack_interrupt	= dm9161_ack_interrupt,
+	.config_intr	= dm9161_config_intr,
 	.driver		= { .owner = THIS_MODULE,},
 }, {
 	.phy_id		= 0x00181b80,
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index c1ef300..044b532 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -431,10 +431,24 @@ static struct dev_pm_ops mdio_bus_pm_ops = {
 
 #endif /* CONFIG_PM */
 
+static ssize_t
+phy_id_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct phy_device *phydev = to_phy_device(dev);
+
+	return sprintf(buf, "0x%.8lx\n", (unsigned long)phydev->phy_id);
+}
+
+static struct device_attribute mdio_dev_attrs[] = {
+	__ATTR_RO(phy_id),
+	__ATTR_NULL
+};
+
 struct bus_type mdio_bus_type = {
 	.name		= "mdio_bus",
 	.match		= mdio_bus_match,
 	.pm		= MDIO_BUS_PM_OPS,
+	.dev_attrs	= mdio_dev_attrs,
 };
 EXPORT_SYMBOL(mdio_bus_type);
 
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 2165d5f..b983596 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -127,6 +127,39 @@ static int ks8051_config_init(struct phy_device *phydev)
 	return 0;
 }
 
+#define KSZ8873MLL_GLOBAL_CONTROL_4	0x06
+#define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX	(1 << 6)
+#define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED	(1 << 4)
+int ksz8873mll_read_status(struct phy_device *phydev)
+{
+	int regval;
+
+	/* dummy read */
+	regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
+
+	regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
+
+	if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX)
+		phydev->duplex = DUPLEX_HALF;
+	else
+		phydev->duplex = DUPLEX_FULL;
+
+	if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_SPEED)
+		phydev->speed = SPEED_10;
+	else
+		phydev->speed = SPEED_100;
+
+	phydev->link = 1;
+	phydev->pause = phydev->asym_pause = 0;
+
+	return 0;
+}
+
+static int ksz8873mll_config_aneg(struct phy_device *phydev)
+{
+	return 0;
+}
+
 static struct phy_driver ksphy_driver[] = {
 {
 	.phy_id		= PHY_ID_KS8737,
@@ -204,6 +237,16 @@ static struct phy_driver ksphy_driver[] = {
 	.ack_interrupt	= kszphy_ack_interrupt,
 	.config_intr	= ksz9021_config_intr,
 	.driver		= { .owner = THIS_MODULE, },
+}, {
+	.phy_id		= PHY_ID_KSZ8873MLL,
+	.phy_id_mask	= 0x00fffff0,
+	.name		= "Micrel KSZ8873MLL Switch",
+	.features	= (SUPPORTED_Pause | SUPPORTED_Asym_Pause),
+	.flags		= PHY_HAS_MAGICANEG,
+	.config_init	= kszphy_config_init,
+	.config_aneg	= ksz8873mll_config_aneg,
+	.read_status	= ksz8873mll_read_status,
+	.driver		= { .owner = THIS_MODULE, },
 } };
 
 static int __init ksphy_init(void)
@@ -232,6 +275,7 @@ static struct mdio_device_id __maybe_unused micrel_tbl[] = {
 	{ PHY_ID_KSZ8021, 0x00ffffff },
 	{ PHY_ID_KSZ8041, 0x00fffff0 },
 	{ PHY_ID_KSZ8051, 0x00fffff0 },
+	{ PHY_ID_KSZ8873MLL, 0x00fffff0 },
 	{ }
 };
 
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 88e3991..16dceed 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -56,35 +56,52 @@ static int smsc_phy_config_init(struct phy_device *phydev)
 	return smsc_phy_ack_interrupt (phydev);
 }
 
-static int lan87xx_config_init(struct phy_device *phydev)
+static int lan911x_config_init(struct phy_device *phydev)
 {
-	/*
-	 * Make sure the EDPWRDOWN bit is NOT set. Setting this bit on
-	 * LAN8710/LAN8720 PHY causes the PHY to misbehave, likely due
-	 * to a bug on the chip.
-	 *
-	 * When the system is powered on with the network cable being
-	 * disconnected all the way until after ifconfig ethX up is
-	 * issued for the LAN port with this PHY, connecting the cable
-	 * afterwards does not cause LINK change detection, while the
-	 * expected behavior is the Link UP being detected.
-	 */
-	int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
-	if (rc < 0)
-		return rc;
-
-	rc &= ~MII_LAN83C185_EDPWRDOWN;
-
-	rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc);
-	if (rc < 0)
-		return rc;
-
 	return smsc_phy_ack_interrupt(phydev);
 }
 
-static int lan911x_config_init(struct phy_device *phydev)
+/*
+ * The LAN8710/LAN8720 requires a minimum of 2 link pulses within 64ms of each
+ * other in order to set the ENERGYON bit and exit EDPD mode.  If a link partner
+ * does send the pulses within this interval, the PHY will remained powered
+ * down.
+ *
+ * This workaround will manually toggle the PHY on/off upon calls to read_status
+ * in order to generate link test pulses if the link is down.  If a link partner
+ * is present, it will respond to the pulses, which will cause the ENERGYON bit
+ * to be set and will cause the EDPD mode to be exited.
+ */
+static int lan87xx_read_status(struct phy_device *phydev)
 {
-	return smsc_phy_ack_interrupt(phydev);
+	int err = genphy_read_status(phydev);
+
+	if (!phydev->link) {
+		/* Disable EDPD to wake up PHY */
+		int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+		if (rc < 0)
+			return rc;
+
+		rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
+			       rc & ~MII_LAN83C185_EDPWRDOWN);
+		if (rc < 0)
+			return rc;
+
+		/* Sleep 64 ms to allow ~5 link test pulses to be sent */
+		msleep(64);
+
+		/* Re-enable EDPD */
+		rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+		if (rc < 0)
+			return rc;
+
+		rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
+			       rc | MII_LAN83C185_EDPWRDOWN);
+		if (rc < 0)
+			return rc;
+	}
+
+	return err;
 }
 
 static struct phy_driver smsc_phy_driver[] = {
@@ -187,8 +204,8 @@ static struct phy_driver smsc_phy_driver[] = {
 
 	/* basic functions */
 	.config_aneg	= genphy_config_aneg,
-	.read_status	= genphy_read_status,
-	.config_init	= lan87xx_config_init,
+	.read_status	= lan87xx_read_status,
+	.config_intr	= smsc_phy_config_intr,
 
 	/* IRQ related */
 	.ack_interrupt	= smsc_phy_ack_interrupt,
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index eb3f5ce..0b2706a 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -1034,7 +1034,7 @@ ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	return err;
 }
 
-struct rtnl_link_stats64*
+static struct rtnl_link_stats64*
 ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64)
 {
 	struct ppp *ppp = netdev_priv(dev);
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index 58f13ad..ae7cd7f 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -608,7 +608,7 @@ static int bcm5421_poll_link(struct mii_phy* phy)
 	if ( mode == BCM54XX_COPPER)
 		return genmii_poll_link(phy);
 
-	/* try to find out wether we have a link */
+	/* try to find out whether we have a link */
 	phy_write(phy, MII_NCONFIG, 0x2000);
 	phy_reg = phy_read(phy, MII_NCONFIG);
 
@@ -634,7 +634,7 @@ static int bcm5421_read_link(struct mii_phy* phy)
 
 	phy->speed = SPEED_1000;
 
-	/* find out wether we are running half- or full duplex */
+	/* find out whether we are running half- or full duplex */
 	phy_write(phy, MII_NCONFIG, 0x2000);
 	phy_reg = phy_read(phy, MII_NCONFIG);
 
@@ -681,7 +681,7 @@ static int bcm5461_poll_link(struct mii_phy* phy)
 	if ( mode == BCM54XX_COPPER)
 		return genmii_poll_link(phy);
 
-	/* find out wether we have a link */
+	/* find out whether we have a link */
 	phy_write(phy, MII_NCONFIG, 0x7000);
 	phy_reg = phy_read(phy, MII_NCONFIG);
 
@@ -710,7 +710,7 @@ static int bcm5461_read_link(struct mii_phy* phy)
 
 	phy->speed = SPEED_1000;
 
-	/* find out wether we are running half- or full duplex */
+	/* find out whether we are running half- or full duplex */
 	phy_write(phy, MII_NCONFIG, 0x7000);
 	phy_reg = phy_read(phy, MII_NCONFIG);
 
diff --git a/drivers/net/team/Kconfig b/drivers/net/team/Kconfig
index 6b08bd4..c3011af 100644
--- a/drivers/net/team/Kconfig
+++ b/drivers/net/team/Kconfig
@@ -1,6 +1,5 @@
 menuconfig NET_TEAM
-	tristate "Ethernet team driver support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	tristate "Ethernet team driver support"
 	---help---
 	  This allows one to create virtual interfaces that teams together
 	  multiple ethernet devices.
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index d44cca3..ad86660 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1794,10 +1794,12 @@ static void team_setup(struct net_device *dev)
 
 	dev->features |= NETIF_F_LLTX;
 	dev->features |= NETIF_F_GRO;
-	dev->hw_features = NETIF_F_HW_VLAN_TX |
+	dev->hw_features = TEAM_VLAN_FEATURES |
+			   NETIF_F_HW_VLAN_TX |
 			   NETIF_F_HW_VLAN_RX |
 			   NETIF_F_HW_VLAN_FILTER;
 
+	dev->hw_features &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_HW_CSUM);
 	dev->features |= dev->hw_features;
 }
 
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 0873cdc..607a3a5 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -68,7 +68,6 @@
 #include <net/netns/generic.h>
 #include <net/rtnetlink.h>
 #include <net/sock.h>
-#include <net/cls_cgroup.h>
 
 #include <asm/uaccess.h>
 
@@ -110,16 +109,56 @@ struct tap_filter {
 	unsigned char	addr[FLT_EXACT_COUNT][ETH_ALEN];
 };
 
+/* 1024 is probably a high enough limit: modern hypervisors seem to support on
+ * the order of 100-200 CPUs so this leaves us some breathing space if we want
+ * to match a queue per guest CPU.
+ */
+#define MAX_TAP_QUEUES 1024
+
+#define TUN_FLOW_EXPIRE (3 * HZ)
+
+/* A tun_file connects an open character device to a tuntap netdevice. It
+ * also contains all socket related strctures (except sock_fprog and tap_filter)
+ * to serve as one transmit queue for tuntap device. The sock_fprog and
+ * tap_filter were kept in tun_struct since they were used for filtering for the
+ * netdevice not for a specific queue (at least I didn't see the requirement for
+ * this).
+ *
+ * RCU usage:
+ * The tun_file and tun_struct are loosely coupled, the pointer from one to the
+ * other can only be read while rcu_read_lock or rtnl_lock is held.
+ */
 struct tun_file {
-	atomic_t count;
-	struct tun_struct *tun;
+	struct sock sk;
+	struct socket socket;
+	struct socket_wq wq;
+	struct tun_struct __rcu *tun;
 	struct net *net;
+	struct fasync_struct *fasync;
+	/* only used for fasnyc */
+	unsigned int flags;
+	u16 queue_index;
+};
+
+struct tun_flow_entry {
+	struct hlist_node hash_link;
+	struct rcu_head rcu;
+	struct tun_struct *tun;
+
+	u32 rxhash;
+	int queue_index;
+	unsigned long updated;
 };
 
-struct tun_sock;
+#define TUN_NUM_FLOW_ENTRIES 1024
 
+/* Since the socket were moved to tun_file, to preserve the behavior of persist
+ * device, socket filter, sndbuf and vnet header size were restore when the
+ * file were attached to a persist device.
+ */
 struct tun_struct {
-	struct tun_file		*tfile;
+	struct tun_file __rcu	*tfiles[MAX_TAP_QUEUES];
+	unsigned int            numqueues;
 	unsigned int 		flags;
 	kuid_t			owner;
 	kgid_t			group;
@@ -128,88 +167,352 @@ struct tun_struct {
 	netdev_features_t	set_features;
 #define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \
 			  NETIF_F_TSO6|NETIF_F_UFO)
-	struct fasync_struct	*fasync;
-
-	struct tap_filter       txflt;
-	struct socket		socket;
-	struct socket_wq	wq;
 
 	int			vnet_hdr_sz;
-
+	int			sndbuf;
+	struct tap_filter	txflt;
+	struct sock_fprog	fprog;
+	/* protected by rtnl lock */
+	bool			filter_attached;
 #ifdef TUN_DEBUG
 	int debug;
 #endif
+	spinlock_t lock;
+	struct kmem_cache *flow_cache;
+	struct hlist_head flows[TUN_NUM_FLOW_ENTRIES];
+	struct timer_list flow_gc_timer;
+	unsigned long ageing_time;
 };
 
-struct tun_sock {
-	struct sock		sk;
-	struct tun_struct	*tun;
-};
+static inline u32 tun_hashfn(u32 rxhash)
+{
+	return rxhash & 0x3ff;
+}
 
-static inline struct tun_sock *tun_sk(struct sock *sk)
+static struct tun_flow_entry *tun_flow_find(struct hlist_head *head, u32 rxhash)
 {
-	return container_of(sk, struct tun_sock, sk);
+	struct tun_flow_entry *e;
+	struct hlist_node *n;
+
+	hlist_for_each_entry_rcu(e, n, head, hash_link) {
+		if (e->rxhash == rxhash)
+			return e;
+	}
+	return NULL;
 }
 
-static int tun_attach(struct tun_struct *tun, struct file *file)
+static struct tun_flow_entry *tun_flow_create(struct tun_struct *tun,
+					      struct hlist_head *head,
+					      u32 rxhash, u16 queue_index)
 {
-	struct tun_file *tfile = file->private_data;
-	int err;
+	struct tun_flow_entry *e = kmem_cache_alloc(tun->flow_cache,
+						    GFP_ATOMIC);
+	if (e) {
+		tun_debug(KERN_INFO, tun, "create flow: hash %u index %u\n",
+			  rxhash, queue_index);
+		e->updated = jiffies;
+		e->rxhash = rxhash;
+		e->queue_index = queue_index;
+		e->tun = tun;
+		hlist_add_head_rcu(&e->hash_link, head);
+	}
+	return e;
+}
 
-	ASSERT_RTNL();
+static void tun_flow_free(struct rcu_head *head)
+{
+	struct tun_flow_entry *e
+		= container_of(head, struct tun_flow_entry, rcu);
+	kmem_cache_free(e->tun->flow_cache, e);
+}
 
-	netif_tx_lock_bh(tun->dev);
+static void tun_flow_delete(struct tun_struct *tun, struct tun_flow_entry *e)
+{
+	tun_debug(KERN_INFO, tun, "delete flow: hash %u index %u\n",
+		  e->rxhash, e->queue_index);
+	hlist_del_rcu(&e->hash_link);
+	call_rcu(&e->rcu, tun_flow_free);
+}
 
-	err = -EINVAL;
-	if (tfile->tun)
-		goto out;
+static void tun_flow_flush(struct tun_struct *tun)
+{
+	int i;
 
-	err = -EBUSY;
-	if (tun->tfile)
-		goto out;
+	spin_lock_bh(&tun->lock);
+	for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) {
+		struct tun_flow_entry *e;
+		struct hlist_node *h, *n;
 
-	err = 0;
-	tfile->tun = tun;
-	tun->tfile = tfile;
-	tun->socket.file = file;
-	netif_carrier_on(tun->dev);
-	dev_hold(tun->dev);
-	sock_hold(tun->socket.sk);
-	atomic_inc(&tfile->count);
+		hlist_for_each_entry_safe(e, h, n, &tun->flows[i], hash_link)
+			tun_flow_delete(tun, e);
+	}
+	spin_unlock_bh(&tun->lock);
+}
 
-out:
-	netif_tx_unlock_bh(tun->dev);
-	return err;
+static void tun_flow_delete_by_queue(struct tun_struct *tun, u16 queue_index)
+{
+	int i;
+
+	spin_lock_bh(&tun->lock);
+	for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) {
+		struct tun_flow_entry *e;
+		struct hlist_node *h, *n;
+
+		hlist_for_each_entry_safe(e, h, n, &tun->flows[i], hash_link) {
+			if (e->queue_index == queue_index)
+				tun_flow_delete(tun, e);
+		}
+	}
+	spin_unlock_bh(&tun->lock);
 }
 
-static void __tun_detach(struct tun_struct *tun)
+static void tun_flow_cleanup(unsigned long data)
 {
-	/* Detach from net device */
-	netif_tx_lock_bh(tun->dev);
-	netif_carrier_off(tun->dev);
-	tun->tfile = NULL;
-	netif_tx_unlock_bh(tun->dev);
+	struct tun_struct *tun = (struct tun_struct *)data;
+	unsigned long delay = tun->ageing_time;
+	unsigned long next_timer = jiffies + delay;
+	unsigned long count = 0;
+	int i;
 
-	/* Drop read queue */
-	skb_queue_purge(&tun->socket.sk->sk_receive_queue);
+	tun_debug(KERN_INFO, tun, "tun_flow_cleanup\n");
+
+	spin_lock_bh(&tun->lock);
+	for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) {
+		struct tun_flow_entry *e;
+		struct hlist_node *h, *n;
+
+		hlist_for_each_entry_safe(e, h, n, &tun->flows[i], hash_link) {
+			unsigned long this_timer;
+			count++;
+			this_timer = e->updated + delay;
+			if (time_before_eq(this_timer, jiffies))
+				tun_flow_delete(tun, e);
+			else if (time_before(this_timer, next_timer))
+				next_timer = this_timer;
+		}
+	}
 
-	/* Drop the extra count on the net device */
-	dev_put(tun->dev);
+	if (count)
+		mod_timer(&tun->flow_gc_timer, round_jiffies_up(next_timer));
+	spin_unlock_bh(&tun->lock);
+}
+
+static void tun_flow_update(struct tun_struct *tun, struct sk_buff *skb,
+			    u16 queue_index)
+{
+	struct hlist_head *head;
+	struct tun_flow_entry *e;
+	unsigned long delay = tun->ageing_time;
+	u32 rxhash = skb_get_rxhash(skb);
+
+	if (!rxhash)
+		return;
+	else
+		head = &tun->flows[tun_hashfn(rxhash)];
+
+	rcu_read_lock();
+
+	if (tun->numqueues == 1)
+		goto unlock;
+
+	e = tun_flow_find(head, rxhash);
+	if (likely(e)) {
+		/* TODO: keep queueing to old queue until it's empty? */
+		e->queue_index = queue_index;
+		e->updated = jiffies;
+	} else {
+		spin_lock_bh(&tun->lock);
+		if (!tun_flow_find(head, rxhash))
+			tun_flow_create(tun, head, rxhash, queue_index);
+
+		if (!timer_pending(&tun->flow_gc_timer))
+			mod_timer(&tun->flow_gc_timer,
+				  round_jiffies_up(jiffies + delay));
+		spin_unlock_bh(&tun->lock);
+	}
+
+unlock:
+	rcu_read_unlock();
+}
+
+/* We try to identify a flow through its rxhash first. The reason that
+ * we do not check rxq no. is becuase some cards(e.g 82599), chooses
+ * the rxq based on the txq where the last packet of the flow comes. As
+ * the userspace application move between processors, we may get a
+ * different rxq no. here. If we could not get rxhash, then we would
+ * hope the rxq no. may help here.
+ */
+static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+	struct tun_struct *tun = netdev_priv(dev);
+	struct tun_flow_entry *e;
+	u32 txq = 0;
+	u32 numqueues = 0;
+
+	rcu_read_lock();
+	numqueues = tun->numqueues;
+
+	txq = skb_get_rxhash(skb);
+	if (txq) {
+		e = tun_flow_find(&tun->flows[tun_hashfn(txq)], txq);
+		if (e)
+			txq = e->queue_index;
+		else
+			/* use multiply and shift instead of expensive divide */
+			txq = ((u64)txq * numqueues) >> 32;
+	} else if (likely(skb_rx_queue_recorded(skb))) {
+		txq = skb_get_rx_queue(skb);
+		while (unlikely(txq >= numqueues))
+			txq -= numqueues;
+	}
+
+	rcu_read_unlock();
+	return txq;
 }
 
-static void tun_detach(struct tun_struct *tun)
+static inline bool tun_not_capable(struct tun_struct *tun)
+{
+	const struct cred *cred = current_cred();
+	struct net *net = dev_net(tun->dev);
+
+	return ((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) ||
+		  (gid_valid(tun->group) && !in_egroup_p(tun->group))) &&
+		!ns_capable(net->user_ns, CAP_NET_ADMIN);
+}
+
+static void tun_set_real_num_queues(struct tun_struct *tun)
+{
+	netif_set_real_num_tx_queues(tun->dev, tun->numqueues);
+	netif_set_real_num_rx_queues(tun->dev, tun->numqueues);
+}
+
+static void __tun_detach(struct tun_file *tfile, bool clean)
+{
+	struct tun_file *ntfile;
+	struct tun_struct *tun;
+	struct net_device *dev;
+
+	tun = rcu_dereference_protected(tfile->tun,
+					lockdep_rtnl_is_held());
+	if (tun) {
+		u16 index = tfile->queue_index;
+		BUG_ON(index >= tun->numqueues);
+		dev = tun->dev;
+
+		rcu_assign_pointer(tun->tfiles[index],
+				   tun->tfiles[tun->numqueues - 1]);
+		rcu_assign_pointer(tfile->tun, NULL);
+		ntfile = rcu_dereference_protected(tun->tfiles[index],
+						   lockdep_rtnl_is_held());
+		ntfile->queue_index = index;
+
+		--tun->numqueues;
+		sock_put(&tfile->sk);
+
+		synchronize_net();
+		tun_flow_delete_by_queue(tun, tun->numqueues + 1);
+		/* Drop read queue */
+		skb_queue_purge(&tfile->sk.sk_receive_queue);
+		tun_set_real_num_queues(tun);
+
+		if (tun->numqueues == 0 && !(tun->flags & TUN_PERSIST))
+			if (dev->reg_state == NETREG_REGISTERED)
+				unregister_netdevice(dev);
+	}
+
+	if (clean) {
+		BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED,
+				 &tfile->socket.flags));
+		sk_release_kernel(&tfile->sk);
+	}
+}
+
+static void tun_detach(struct tun_file *tfile, bool clean)
 {
 	rtnl_lock();
-	__tun_detach(tun);
+	__tun_detach(tfile, clean);
 	rtnl_unlock();
 }
 
+static void tun_detach_all(struct net_device *dev)
+{
+	struct tun_struct *tun = netdev_priv(dev);
+	struct tun_file *tfile;
+	int i, n = tun->numqueues;
+
+	for (i = 0; i < n; i++) {
+		tfile = rcu_dereference_protected(tun->tfiles[i],
+						  lockdep_rtnl_is_held());
+		BUG_ON(!tfile);
+		wake_up_all(&tfile->wq.wait);
+		rcu_assign_pointer(tfile->tun, NULL);
+		--tun->numqueues;
+	}
+	BUG_ON(tun->numqueues != 0);
+
+	synchronize_net();
+	for (i = 0; i < n; i++) {
+		tfile = rcu_dereference_protected(tun->tfiles[i],
+						  lockdep_rtnl_is_held());
+		/* Drop read queue */
+		skb_queue_purge(&tfile->sk.sk_receive_queue);
+		sock_put(&tfile->sk);
+	}
+}
+
+static int tun_attach(struct tun_struct *tun, struct file *file)
+{
+	struct tun_file *tfile = file->private_data;
+	int err;
+
+	err = -EINVAL;
+	if (rcu_dereference_protected(tfile->tun, lockdep_rtnl_is_held()))
+		goto out;
+
+	err = -EBUSY;
+	if (!(tun->flags & TUN_TAP_MQ) && tun->numqueues == 1)
+		goto out;
+
+	err = -E2BIG;
+	if (tun->numqueues == MAX_TAP_QUEUES)
+		goto out;
+
+	err = 0;
+
+	/* Re-attach the filter to presist device */
+	if (tun->filter_attached == true) {
+		err = sk_attach_filter(&tun->fprog, tfile->socket.sk);
+		if (!err)
+			goto out;
+	}
+	tfile->queue_index = tun->numqueues;
+	rcu_assign_pointer(tfile->tun, tun);
+	rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
+	sock_hold(&tfile->sk);
+	tun->numqueues++;
+
+	tun_set_real_num_queues(tun);
+
+	if (tun->numqueues == 1)
+		netif_carrier_on(tun->dev);
+
+	/* device is allowed to go away first, so no need to hold extra
+	 * refcnt.
+	 */
+
+out:
+	return err;
+}
+
 static struct tun_struct *__tun_get(struct tun_file *tfile)
 {
-	struct tun_struct *tun = NULL;
+	struct tun_struct *tun;
 
-	if (atomic_inc_not_zero(&tfile->count))
-		tun = tfile->tun;
+	rcu_read_lock();
+	tun = rcu_dereference(tfile->tun);
+	if (tun)
+		dev_hold(tun->dev);
+	rcu_read_unlock();
 
 	return tun;
 }
@@ -221,10 +524,7 @@ static struct tun_struct *tun_get(struct file *file)
 
 static void tun_put(struct tun_struct *tun)
 {
-	struct tun_file *tfile = tun->tfile;
-
-	if (atomic_dec_and_test(&tfile->count))
-		tun_detach(tfile->tun);
+	dev_put(tun->dev);
 }
 
 /* TAP filtering */
@@ -344,38 +644,20 @@ static const struct ethtool_ops tun_ethtool_ops;
 /* Net device detach from fd. */
 static void tun_net_uninit(struct net_device *dev)
 {
-	struct tun_struct *tun = netdev_priv(dev);
-	struct tun_file *tfile = tun->tfile;
-
-	/* Inform the methods they need to stop using the dev.
-	 */
-	if (tfile) {
-		wake_up_all(&tun->wq.wait);
-		if (atomic_dec_and_test(&tfile->count))
-			__tun_detach(tun);
-	}
-}
-
-static void tun_free_netdev(struct net_device *dev)
-{
-	struct tun_struct *tun = netdev_priv(dev);
-
-	BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED, &tun->socket.flags));
-
-	sk_release_kernel(tun->socket.sk);
+	tun_detach_all(dev);
 }
 
 /* Net device open. */
 static int tun_net_open(struct net_device *dev)
 {
-	netif_start_queue(dev);
+	netif_tx_start_all_queues(dev);
 	return 0;
 }
 
 /* Net device close. */
 static int tun_net_close(struct net_device *dev)
 {
-	netif_stop_queue(dev);
+	netif_tx_stop_all_queues(dev);
 	return 0;
 }
 
@@ -383,28 +665,39 @@ static int tun_net_close(struct net_device *dev)
 static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct tun_struct *tun = netdev_priv(dev);
+	int txq = skb->queue_mapping;
+	struct tun_file *tfile;
 
-	tun_debug(KERN_INFO, tun, "tun_net_xmit %d\n", skb->len);
+	rcu_read_lock();
+	tfile = rcu_dereference(tun->tfiles[txq]);
 
 	/* Drop packet if interface is not attached */
-	if (!tun->tfile)
+	if (txq >= tun->numqueues)
 		goto drop;
 
+	tun_debug(KERN_INFO, tun, "tun_net_xmit %d\n", skb->len);
+
+	BUG_ON(!tfile);
+
 	/* Drop if the filter does not like it.
 	 * This is a noop if the filter is disabled.
 	 * Filter can be enabled only for the TAP devices. */
 	if (!check_filter(&tun->txflt, skb))
 		goto drop;
 
-	if (tun->socket.sk->sk_filter &&
-	    sk_filter(tun->socket.sk, skb))
+	if (tfile->socket.sk->sk_filter &&
+	    sk_filter(tfile->socket.sk, skb))
 		goto drop;
 
-	if (skb_queue_len(&tun->socket.sk->sk_receive_queue) >= dev->tx_queue_len) {
+	/* Limit the number of packets queued by dividing txq length with the
+	 * number of queues.
+	 */
+	if (skb_queue_len(&tfile->socket.sk->sk_receive_queue)
+			  >= dev->tx_queue_len / tun->numqueues){
 		if (!(tun->flags & TUN_ONE_QUEUE)) {
 			/* Normal queueing mode. */
 			/* Packet scheduler handles dropping of further packets. */
-			netif_stop_queue(dev);
+			netif_stop_subqueue(dev, txq);
 
 			/* We won't see all dropped packets individually, so overrun
 			 * error is more appropriate. */
@@ -423,18 +716,22 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
 	skb_orphan(skb);
 
 	/* Enqueue packet */
-	skb_queue_tail(&tun->socket.sk->sk_receive_queue, skb);
+	skb_queue_tail(&tfile->socket.sk->sk_receive_queue, skb);
 
 	/* Notify and wake up reader process */
-	if (tun->flags & TUN_FASYNC)
-		kill_fasync(&tun->fasync, SIGIO, POLL_IN);
-	wake_up_interruptible_poll(&tun->wq.wait, POLLIN |
+	if (tfile->flags & TUN_FASYNC)
+		kill_fasync(&tfile->fasync, SIGIO, POLL_IN);
+	wake_up_interruptible_poll(&tfile->wq.wait, POLLIN |
 				   POLLRDNORM | POLLRDBAND);
+
+	rcu_read_unlock();
 	return NETDEV_TX_OK;
 
 drop:
 	dev->stats.tx_dropped++;
+	skb_tx_error(skb);
 	kfree_skb(skb);
+	rcu_read_unlock();
 	return NETDEV_TX_OK;
 }
 
@@ -490,6 +787,7 @@ static const struct net_device_ops tun_netdev_ops = {
 	.ndo_start_xmit		= tun_net_xmit,
 	.ndo_change_mtu		= tun_net_change_mtu,
 	.ndo_fix_features	= tun_net_fix_features,
+	.ndo_select_queue	= tun_select_queue,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= tun_poll_controller,
 #endif
@@ -505,11 +803,43 @@ static const struct net_device_ops tap_netdev_ops = {
 	.ndo_set_rx_mode	= tun_net_mclist,
 	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_select_queue	= tun_select_queue,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= tun_poll_controller,
 #endif
 };
 
+static int tun_flow_init(struct tun_struct *tun)
+{
+	int i;
+
+	tun->flow_cache = kmem_cache_create("tun_flow_cache",
+					    sizeof(struct tun_flow_entry), 0, 0,
+					    NULL);
+	if (!tun->flow_cache)
+		return -ENOMEM;
+
+	for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++)
+		INIT_HLIST_HEAD(&tun->flows[i]);
+
+	tun->ageing_time = TUN_FLOW_EXPIRE;
+	setup_timer(&tun->flow_gc_timer, tun_flow_cleanup, (unsigned long)tun);
+	mod_timer(&tun->flow_gc_timer,
+		  round_jiffies_up(jiffies + tun->ageing_time));
+
+	return 0;
+}
+
+static void tun_flow_uninit(struct tun_struct *tun)
+{
+	del_timer_sync(&tun->flow_gc_timer);
+	tun_flow_flush(tun);
+
+	/* Wait for completion of call_rcu()'s */
+	rcu_barrier();
+	kmem_cache_destroy(tun->flow_cache);
+}
+
 /* Initialize net device. */
 static void tun_net_init(struct net_device *dev)
 {
@@ -546,7 +876,7 @@ static void tun_net_init(struct net_device *dev)
 /* Character device part */
 
 /* Poll */
-static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
+static unsigned int tun_chr_poll(struct file *file, poll_table *wait)
 {
 	struct tun_file *tfile = file->private_data;
 	struct tun_struct *tun = __tun_get(tfile);
@@ -556,11 +886,11 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
 	if (!tun)
 		return POLLERR;
 
-	sk = tun->socket.sk;
+	sk = tfile->socket.sk;
 
 	tun_debug(KERN_INFO, tun, "tun_chr_poll\n");
 
-	poll_wait(file, &tun->wq.wait, wait);
+	poll_wait(file, &tfile->wq.wait, wait);
 
 	if (!skb_queue_empty(&sk->sk_receive_queue))
 		mask |= POLLIN | POLLRDNORM;
@@ -579,16 +909,14 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
 
 /* prepad is the amount to reserve at front.  len is length after that.
  * linear is a hint as to how much to copy (usually headers). */
-static struct sk_buff *tun_alloc_skb(struct tun_struct *tun,
+static struct sk_buff *tun_alloc_skb(struct tun_file *tfile,
 				     size_t prepad, size_t len,
 				     size_t linear, int noblock)
 {
-	struct sock *sk = tun->socket.sk;
+	struct sock *sk = tfile->socket.sk;
 	struct sk_buff *skb;
 	int err;
 
-	sock_update_classid(sk);
-
 	/* Under a page?  Don't bother with paged skb. */
 	if (prepad + len < PAGE_SIZE || !linear)
 		linear = len;
@@ -685,9 +1013,9 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
 }
 
 /* Get packet from user space buffer */
-static ssize_t tun_get_user(struct tun_struct *tun, void *msg_control,
-			    const struct iovec *iv, size_t total_len,
-			    size_t count, int noblock)
+static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
+			    void *msg_control, const struct iovec *iv,
+			    size_t total_len, size_t count, int noblock)
 {
 	struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) };
 	struct sk_buff *skb;
@@ -757,7 +1085,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, void *msg_control,
 	} else
 		copylen = len;
 
-	skb = tun_alloc_skb(tun, align, copylen, gso.hdr_len, noblock);
+	skb = tun_alloc_skb(tfile, align, copylen, gso.hdr_len, noblock);
 	if (IS_ERR(skb)) {
 		if (PTR_ERR(skb) != -EAGAIN)
 			tun->dev->stats.rx_dropped++;
@@ -854,6 +1182,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, void *msg_control,
 	tun->dev->stats.rx_packets++;
 	tun->dev->stats.rx_bytes += len;
 
+	tun_flow_update(tun, skb, tfile->queue_index);
 	return total_len;
 }
 
@@ -862,6 +1191,7 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
 {
 	struct file *file = iocb->ki_filp;
 	struct tun_struct *tun = tun_get(file);
+	struct tun_file *tfile = file->private_data;
 	ssize_t result;
 
 	if (!tun)
@@ -869,8 +1199,8 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
 
 	tun_debug(KERN_INFO, tun, "tun_chr_write %ld\n", count);
 
-	result = tun_get_user(tun, NULL, iv, iov_length(iv, count), count,
-			      file->f_flags & O_NONBLOCK);
+	result = tun_get_user(tun, tfile, NULL, iv, iov_length(iv, count),
+			      count, file->f_flags & O_NONBLOCK);
 
 	tun_put(tun);
 	return result;
@@ -878,6 +1208,7 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
 
 /* Put packet to the user space buffer */
 static ssize_t tun_put_user(struct tun_struct *tun,
+			    struct tun_file *tfile,
 			    struct sk_buff *skb,
 			    const struct iovec *iv, int len)
 {
@@ -957,7 +1288,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
 	return total;
 }
 
-static ssize_t tun_do_read(struct tun_struct *tun,
+static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
 			   struct kiocb *iocb, const struct iovec *iv,
 			   ssize_t len, int noblock)
 {
@@ -965,15 +1296,15 @@ static ssize_t tun_do_read(struct tun_struct *tun,
 	struct sk_buff *skb;
 	ssize_t ret = 0;
 
-	tun_debug(KERN_INFO, tun, "tun_chr_read\n");
+	tun_debug(KERN_INFO, tun, "tun_do_read\n");
 
 	if (unlikely(!noblock))
-		add_wait_queue(&tun->wq.wait, &wait);
+		add_wait_queue(&tfile->wq.wait, &wait);
 	while (len) {
 		current->state = TASK_INTERRUPTIBLE;
 
 		/* Read frames from the queue */
-		if (!(skb=skb_dequeue(&tun->socket.sk->sk_receive_queue))) {
+		if (!(skb = skb_dequeue(&tfile->socket.sk->sk_receive_queue))) {
 			if (noblock) {
 				ret = -EAGAIN;
 				break;
@@ -991,16 +1322,16 @@ static ssize_t tun_do_read(struct tun_struct *tun,
 			schedule();
 			continue;
 		}
-		netif_wake_queue(tun->dev);
+		netif_wake_subqueue(tun->dev, tfile->queue_index);
 
-		ret = tun_put_user(tun, skb, iv, len);
+		ret = tun_put_user(tun, tfile, skb, iv, len);
 		kfree_skb(skb);
 		break;
 	}
 
 	current->state = TASK_RUNNING;
 	if (unlikely(!noblock))
-		remove_wait_queue(&tun->wq.wait, &wait);
+		remove_wait_queue(&tfile->wq.wait, &wait);
 
 	return ret;
 }
@@ -1021,13 +1352,22 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
 		goto out;
 	}
 
-	ret = tun_do_read(tun, iocb, iv, len, file->f_flags & O_NONBLOCK);
+	ret = tun_do_read(tun, tfile, iocb, iv, len,
+			  file->f_flags & O_NONBLOCK);
 	ret = min_t(ssize_t, ret, len);
 out:
 	tun_put(tun);
 	return ret;
 }
 
+static void tun_free_netdev(struct net_device *dev)
+{
+	struct tun_struct *tun = netdev_priv(dev);
+
+	tun_flow_uninit(tun);
+	free_netdev(dev);
+}
+
 static void tun_setup(struct net_device *dev)
 {
 	struct tun_struct *tun = netdev_priv(dev);
@@ -1056,7 +1396,7 @@ static struct rtnl_link_ops tun_link_ops __read_mostly = {
 
 static void tun_sock_write_space(struct sock *sk)
 {
-	struct tun_struct *tun;
+	struct tun_file *tfile;
 	wait_queue_head_t *wqueue;
 
 	if (!sock_writeable(sk))
@@ -1070,37 +1410,46 @@ static void tun_sock_write_space(struct sock *sk)
 		wake_up_interruptible_sync_poll(wqueue, POLLOUT |
 						POLLWRNORM | POLLWRBAND);
 
-	tun = tun_sk(sk)->tun;
-	kill_fasync(&tun->fasync, SIGIO, POLL_OUT);
-}
-
-static void tun_sock_destruct(struct sock *sk)
-{
-	free_netdev(tun_sk(sk)->tun->dev);
+	tfile = container_of(sk, struct tun_file, sk);
+	kill_fasync(&tfile->fasync, SIGIO, POLL_OUT);
 }
 
 static int tun_sendmsg(struct kiocb *iocb, struct socket *sock,
 		       struct msghdr *m, size_t total_len)
 {
-	struct tun_struct *tun = container_of(sock, struct tun_struct, socket);
-	return tun_get_user(tun, m->msg_control, m->msg_iov, total_len,
-			    m->msg_iovlen, m->msg_flags & MSG_DONTWAIT);
+	int ret;
+	struct tun_file *tfile = container_of(sock, struct tun_file, socket);
+	struct tun_struct *tun = __tun_get(tfile);
+
+	if (!tun)
+		return -EBADFD;
+	ret = tun_get_user(tun, tfile, m->msg_control, m->msg_iov, total_len,
+			   m->msg_iovlen, m->msg_flags & MSG_DONTWAIT);
+	tun_put(tun);
+	return ret;
 }
 
+
 static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
 		       struct msghdr *m, size_t total_len,
 		       int flags)
 {
-	struct tun_struct *tun = container_of(sock, struct tun_struct, socket);
+	struct tun_file *tfile = container_of(sock, struct tun_file, socket);
+	struct tun_struct *tun = __tun_get(tfile);
 	int ret;
+
+	if (!tun)
+		return -EBADFD;
+
 	if (flags & ~(MSG_DONTWAIT|MSG_TRUNC))
 		return -EINVAL;
-	ret = tun_do_read(tun, iocb, m->msg_iov, total_len,
+	ret = tun_do_read(tun, tfile, iocb, m->msg_iov, total_len,
 			  flags & MSG_DONTWAIT);
 	if (ret > total_len) {
 		m->msg_flags |= MSG_TRUNC;
 		ret = flags & MSG_TRUNC ? ret : total_len;
 	}
+	tun_put(tun);
 	return ret;
 }
 
@@ -1121,7 +1470,7 @@ static const struct proto_ops tun_socket_ops = {
 static struct proto tun_proto = {
 	.name		= "tun",
 	.owner		= THIS_MODULE,
-	.obj_size	= sizeof(struct tun_sock),
+	.obj_size	= sizeof(struct tun_file),
 };
 
 static int tun_flags(struct tun_struct *tun)
@@ -1142,6 +1491,9 @@ static int tun_flags(struct tun_struct *tun)
 	if (tun->flags & TUN_VNET_HDR)
 		flags |= IFF_VNET_HDR;
 
+	if (tun->flags & TUN_TAP_MQ)
+		flags |= IFF_MULTI_QUEUE;
+
 	return flags;
 }
 
@@ -1178,15 +1530,13 @@ static DEVICE_ATTR(group, 0444, tun_show_group, NULL);
 
 static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 {
-	struct sock *sk;
 	struct tun_struct *tun;
+	struct tun_file *tfile = file->private_data;
 	struct net_device *dev;
 	int err;
 
 	dev = __dev_get_by_name(net, ifr->ifr_name);
 	if (dev) {
-		const struct cred *cred = current_cred();
-
 		if (ifr->ifr_flags & IFF_TUN_EXCL)
 			return -EBUSY;
 		if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops)
@@ -1196,11 +1546,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 		else
 			return -EINVAL;
 
-		if (((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) ||
-		     (gid_valid(tun->group) && !in_egroup_p(tun->group))) &&
-		    !capable(CAP_NET_ADMIN))
+		if (tun_not_capable(tun))
 			return -EPERM;
-		err = security_tun_dev_attach(tun->socket.sk);
+		err = security_tun_dev_attach(tfile->socket.sk);
 		if (err < 0)
 			return err;
 
@@ -1212,7 +1560,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 		char *name;
 		unsigned long flags = 0;
 
-		if (!capable(CAP_NET_ADMIN))
+		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 			return -EPERM;
 		err = security_tun_dev_create();
 		if (err < 0)
@@ -1233,8 +1581,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 		if (*ifr->ifr_name)
 			name = ifr->ifr_name;
 
-		dev = alloc_netdev(sizeof(struct tun_struct), name,
-				   tun_setup);
+		dev = alloc_netdev_mqs(sizeof(struct tun_struct), name,
+				       tun_setup,
+				       MAX_TAP_QUEUES, MAX_TAP_QUEUES);
 		if (!dev)
 			return -ENOMEM;
 
@@ -1246,46 +1595,35 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 		tun->flags = flags;
 		tun->txflt.count = 0;
 		tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr);
-		set_bit(SOCK_EXTERNALLY_ALLOCATED, &tun->socket.flags);
 
-		err = -ENOMEM;
-		sk = sk_alloc(&init_net, AF_UNSPEC, GFP_KERNEL, &tun_proto);
-		if (!sk)
-			goto err_free_dev;
+		tun->filter_attached = false;
+		tun->sndbuf = tfile->socket.sk->sk_sndbuf;
 
-		sk_change_net(sk, net);
-		tun->socket.wq = &tun->wq;
-		init_waitqueue_head(&tun->wq.wait);
-		tun->socket.ops = &tun_socket_ops;
-		sock_init_data(&tun->socket, sk);
-		sk->sk_write_space = tun_sock_write_space;
-		sk->sk_sndbuf = INT_MAX;
-		sock_set_flag(sk, SOCK_ZEROCOPY);
+		spin_lock_init(&tun->lock);
 
-		tun_sk(sk)->tun = tun;
-
-		security_tun_dev_post_create(sk);
+		security_tun_dev_post_create(&tfile->sk);
 
 		tun_net_init(dev);
 
+		if (tun_flow_init(tun))
+			goto err_free_dev;
+
 		dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST |
 			TUN_USER_FEATURES;
 		dev->features = dev->hw_features;
 
 		err = register_netdevice(tun->dev);
 		if (err < 0)
-			goto err_free_sk;
+			goto err_free_dev;
 
 		if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) ||
 		    device_create_file(&tun->dev->dev, &dev_attr_owner) ||
 		    device_create_file(&tun->dev->dev, &dev_attr_group))
 			pr_err("Failed to create tun sysfs files\n");
 
-		sk->sk_destruct = tun_sock_destruct;
-
 		err = tun_attach(tun, file);
 		if (err < 0)
-			goto failed;
+			goto err_free_dev;
 	}
 
 	tun_debug(KERN_INFO, tun, "tun_set_iff\n");
@@ -1305,24 +1643,26 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 	else
 		tun->flags &= ~TUN_VNET_HDR;
 
+	if (ifr->ifr_flags & IFF_MULTI_QUEUE)
+		tun->flags |= TUN_TAP_MQ;
+	else
+		tun->flags &= ~TUN_TAP_MQ;
+
 	/* Make sure persistent devices do not get stuck in
 	 * xoff state.
 	 */
 	if (netif_running(tun->dev))
-		netif_wake_queue(tun->dev);
+		netif_tx_wake_all_queues(tun->dev);
 
 	strcpy(ifr->ifr_name, tun->dev->name);
 	return 0;
 
- err_free_sk:
-	tun_free_netdev(dev);
  err_free_dev:
 	free_netdev(dev);
- failed:
 	return err;
 }
 
-static int tun_get_iff(struct net *net, struct tun_struct *tun,
+static void tun_get_iff(struct net *net, struct tun_struct *tun,
 		       struct ifreq *ifr)
 {
 	tun_debug(KERN_INFO, tun, "tun_get_iff\n");
@@ -1331,7 +1671,6 @@ static int tun_get_iff(struct net *net, struct tun_struct *tun,
 
 	ifr->ifr_flags = tun_flags(tun);
 
-	return 0;
 }
 
 /* This is like a cut-down ethtool ops, except done via tun fd so no
@@ -1373,13 +1712,91 @@ static int set_offload(struct tun_struct *tun, unsigned long arg)
 	return 0;
 }
 
+static void tun_detach_filter(struct tun_struct *tun, int n)
+{
+	int i;
+	struct tun_file *tfile;
+
+	for (i = 0; i < n; i++) {
+		tfile = rcu_dereference_protected(tun->tfiles[i],
+						  lockdep_rtnl_is_held());
+		sk_detach_filter(tfile->socket.sk);
+	}
+
+	tun->filter_attached = false;
+}
+
+static int tun_attach_filter(struct tun_struct *tun)
+{
+	int i, ret = 0;
+	struct tun_file *tfile;
+
+	for (i = 0; i < tun->numqueues; i++) {
+		tfile = rcu_dereference_protected(tun->tfiles[i],
+						  lockdep_rtnl_is_held());
+		ret = sk_attach_filter(&tun->fprog, tfile->socket.sk);
+		if (ret) {
+			tun_detach_filter(tun, i);
+			return ret;
+		}
+	}
+
+	tun->filter_attached = true;
+	return ret;
+}
+
+static void tun_set_sndbuf(struct tun_struct *tun)
+{
+	struct tun_file *tfile;
+	int i;
+
+	for (i = 0; i < tun->numqueues; i++) {
+		tfile = rcu_dereference_protected(tun->tfiles[i],
+						lockdep_rtnl_is_held());
+		tfile->socket.sk->sk_sndbuf = tun->sndbuf;
+	}
+}
+
+static int tun_set_queue(struct file *file, struct ifreq *ifr)
+{
+	struct tun_file *tfile = file->private_data;
+	struct tun_struct *tun;
+	struct net_device *dev;
+	int ret = 0;
+
+	rtnl_lock();
+
+	if (ifr->ifr_flags & IFF_ATTACH_QUEUE) {
+		dev = __dev_get_by_name(tfile->net, ifr->ifr_name);
+		if (!dev) {
+			ret = -EINVAL;
+			goto unlock;
+		}
+
+		tun = netdev_priv(dev);
+		if (dev->netdev_ops != &tap_netdev_ops &&
+			dev->netdev_ops != &tun_netdev_ops)
+			ret = -EINVAL;
+		else if (tun_not_capable(tun))
+			ret = -EPERM;
+		else
+			ret = tun_attach(tun, file);
+	} else if (ifr->ifr_flags & IFF_DETACH_QUEUE)
+		__tun_detach(tfile, false);
+	else
+		ret = -EINVAL;
+
+unlock:
+	rtnl_unlock();
+	return ret;
+}
+
 static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 			    unsigned long arg, int ifreq_len)
 {
 	struct tun_file *tfile = file->private_data;
 	struct tun_struct *tun;
 	void __user* argp = (void __user*)arg;
-	struct sock_fprog fprog;
 	struct ifreq ifr;
 	kuid_t owner;
 	kgid_t group;
@@ -1387,7 +1804,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 	int vnet_hdr_sz;
 	int ret;
 
-	if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) {
+	if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) {
 		if (copy_from_user(&ifr, argp, ifreq_len))
 			return -EFAULT;
 	} else {
@@ -1398,10 +1815,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 		 * This is needed because we never checked for invalid flags on
 		 * TUNSETIFF. */
 		return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE |
-				IFF_VNET_HDR,
+				IFF_VNET_HDR | IFF_MULTI_QUEUE,
 				(unsigned int __user*)argp);
-	}
+	} else if (cmd == TUNSETQUEUE)
+		return tun_set_queue(file, &ifr);
 
+	ret = 0;
 	rtnl_lock();
 
 	tun = __tun_get(tfile);
@@ -1422,14 +1841,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 	if (!tun)
 		goto unlock;
 
-	tun_debug(KERN_INFO, tun, "tun_chr_ioctl cmd %d\n", cmd);
+	tun_debug(KERN_INFO, tun, "tun_chr_ioctl cmd %u\n", cmd);
 
 	ret = 0;
 	switch (cmd) {
 	case TUNGETIFF:
-		ret = tun_get_iff(current->nsproxy->net_ns, tun, &ifr);
-		if (ret)
-			break;
+		tun_get_iff(current->nsproxy->net_ns, tun, &ifr);
 
 		if (copy_to_user(argp, &ifr, ifreq_len))
 			ret = -EFAULT;
@@ -1444,11 +1861,16 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 		break;
 
 	case TUNSETPERSIST:
-		/* Disable/Enable persist mode */
-		if (arg)
+		/* Disable/Enable persist mode. Keep an extra reference to the
+		 * module to prevent the module being unprobed.
+		 */
+		if (arg) {
 			tun->flags |= TUN_PERSIST;
-		else
+			__module_get(THIS_MODULE);
+		} else {
 			tun->flags &= ~TUN_PERSIST;
+			module_put(THIS_MODULE);
+		}
 
 		tun_debug(KERN_INFO, tun, "persist %s\n",
 			  arg ? "enabled" : "disabled");
@@ -1462,7 +1884,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 			break;
 		}
 		tun->owner = owner;
-		tun_debug(KERN_INFO, tun, "owner set to %d\n",
+		tun_debug(KERN_INFO, tun, "owner set to %u\n",
 			  from_kuid(&init_user_ns, tun->owner));
 		break;
 
@@ -1474,7 +1896,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 			break;
 		}
 		tun->group = group;
-		tun_debug(KERN_INFO, tun, "group set to %d\n",
+		tun_debug(KERN_INFO, tun, "group set to %u\n",
 			  from_kgid(&init_user_ns, tun->group));
 		break;
 
@@ -1526,7 +1948,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 		break;
 
 	case TUNGETSNDBUF:
-		sndbuf = tun->socket.sk->sk_sndbuf;
+		sndbuf = tfile->socket.sk->sk_sndbuf;
 		if (copy_to_user(argp, &sndbuf, sizeof(sndbuf)))
 			ret = -EFAULT;
 		break;
@@ -1537,7 +1959,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 			break;
 		}
 
-		tun->socket.sk->sk_sndbuf = sndbuf;
+		tun->sndbuf = sndbuf;
+		tun_set_sndbuf(tun);
 		break;
 
 	case TUNGETVNETHDRSZ:
@@ -1565,10 +1988,10 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 		if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
 			break;
 		ret = -EFAULT;
-		if (copy_from_user(&fprog, argp, sizeof(fprog)))
+		if (copy_from_user(&tun->fprog, argp, sizeof(tun->fprog)))
 			break;
 
-		ret = sk_attach_filter(&fprog, tun->socket.sk);
+		ret = tun_attach_filter(tun);
 		break;
 
 	case TUNDETACHFILTER:
@@ -1576,7 +1999,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 		ret = -EINVAL;
 		if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
 			break;
-		ret = sk_detach_filter(tun->socket.sk);
+		ret = 0;
+		tun_detach_filter(tun, tun->numqueues);
 		break;
 
 	default:
@@ -1628,27 +2052,21 @@ static long tun_chr_compat_ioctl(struct file *file,
 
 static int tun_chr_fasync(int fd, struct file *file, int on)
 {
-	struct tun_struct *tun = tun_get(file);
+	struct tun_file *tfile = file->private_data;
 	int ret;
 
-	if (!tun)
-		return -EBADFD;
-
-	tun_debug(KERN_INFO, tun, "tun_chr_fasync %d\n", on);
-
-	if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0)
+	if ((ret = fasync_helper(fd, file, on, &tfile->fasync)) < 0)
 		goto out;
 
 	if (on) {
 		ret = __f_setown(file, task_pid(current), PIDTYPE_PID, 0);
 		if (ret)
 			goto out;
-		tun->flags |= TUN_FASYNC;
+		tfile->flags |= TUN_FASYNC;
 	} else
-		tun->flags &= ~TUN_FASYNC;
+		tfile->flags &= ~TUN_FASYNC;
 	ret = 0;
 out:
-	tun_put(tun);
 	return ret;
 }
 
@@ -1658,44 +2076,39 @@ static int tun_chr_open(struct inode *inode, struct file * file)
 
 	DBG1(KERN_INFO, "tunX: tun_chr_open\n");
 
-	tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
+	tfile = (struct tun_file *)sk_alloc(&init_net, AF_UNSPEC, GFP_KERNEL,
+					    &tun_proto);
 	if (!tfile)
 		return -ENOMEM;
-	atomic_set(&tfile->count, 0);
-	tfile->tun = NULL;
+	rcu_assign_pointer(tfile->tun, NULL);
 	tfile->net = get_net(current->nsproxy->net_ns);
+	tfile->flags = 0;
+
+	rcu_assign_pointer(tfile->socket.wq, &tfile->wq);
+	init_waitqueue_head(&tfile->wq.wait);
+
+	tfile->socket.file = file;
+	tfile->socket.ops = &tun_socket_ops;
+
+	sock_init_data(&tfile->socket, &tfile->sk);
+	sk_change_net(&tfile->sk, tfile->net);
+
+	tfile->sk.sk_write_space = tun_sock_write_space;
+	tfile->sk.sk_sndbuf = INT_MAX;
+
 	file->private_data = tfile;
+	set_bit(SOCK_EXTERNALLY_ALLOCATED, &tfile->socket.flags);
+
 	return 0;
 }
 
 static int tun_chr_close(struct inode *inode, struct file *file)
 {
 	struct tun_file *tfile = file->private_data;
-	struct tun_struct *tun;
+	struct net *net = tfile->net;
 
-	tun = __tun_get(tfile);
-	if (tun) {
-		struct net_device *dev = tun->dev;
-
-		tun_debug(KERN_INFO, tun, "tun_chr_close\n");
-
-		__tun_detach(tun);
-
-		/* If desirable, unregister the netdevice. */
-		if (!(tun->flags & TUN_PERSIST)) {
-			rtnl_lock();
-			if (dev->reg_state == NETREG_REGISTERED)
-				unregister_netdevice(dev);
-			rtnl_unlock();
-		}
-	}
-
-	tun = tfile->tun;
-	if (tun)
-		sock_put(tun->socket.sk);
-
-	put_net(tfile->net);
-	kfree(tfile);
+	tun_detach(tfile, true);
+	put_net(net);
 
 	return 0;
 }
@@ -1822,14 +2235,13 @@ static void tun_cleanup(void)
  * holding a reference to the file for as long as the socket is in use. */
 struct socket *tun_get_socket(struct file *file)
 {
-	struct tun_struct *tun;
+	struct tun_file *tfile;
 	if (file->f_op != &tun_fops)
 		return ERR_PTR(-EINVAL);
-	tun = tun_get(file);
-	if (!tun)
+	tfile = file->private_data;
+	if (!tfile)
 		return ERR_PTR(-EBADFD);
-	tun_put(tun);
-	return &tun->socket;
+	return &tfile->socket;
 }
 EXPORT_SYMBOL_GPL(tun_get_socket);
 
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index c1ae769..3a44a5d 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -8,8 +8,7 @@ menu "USB Network Adapters"
 	depends on USB && NET
 
 config USB_CATC
-	tristate "USB CATC NetMate-based Ethernet device support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	tristate "USB CATC NetMate-based Ethernet device support"
 	select CRC32
 	---help---
 	  Say Y if you want to use one of the following 10Mbps USB Ethernet
@@ -83,8 +82,7 @@ config USB_PEGASUS
 	  module will be called pegasus.
 
 config USB_RTL8150
-	tristate "USB RTL8150 based ethernet device support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	tristate "USB RTL8150 based ethernet device support"
 	select NET_CORE
 	select MII
 	help
@@ -188,7 +186,7 @@ config USB_NET_CDCETHER
 
 config USB_NET_CDC_EEM
 	tristate "CDC EEM support"
-	depends on USB_USBNET && EXPERIMENTAL
+	depends on USB_USBNET
 	help
 	  This option supports devices conforming to the Communication Device
 	  Class (CDC) Ethernet Emulation Model, a specification that's easy to
@@ -219,6 +217,24 @@ config USB_NET_CDC_NCM
 	    * ST-Ericsson M343 HSPA Mobile Broadband Modem (reference design)
 	    * Ericsson F5521gw Mobile Broadband Module
 
+config USB_NET_CDC_MBIM
+	tristate "CDC MBIM support"
+	depends on USB_USBNET
+	select USB_WDM
+	select USB_NET_CDC_NCM
+	help
+	  This driver provides support for CDC MBIM (Mobile Broadband
+	  Interface Model) devices. The CDC MBIM specification is
+	  available from <http://www.usb.org/>.
+
+	  MBIM devices require configuration using the management
+	  protocol defined by the MBIM specification.  This driver
+	  provides unfiltered access to the MBIM control channel
+	  through the associated /dev/cdc-wdmx character device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cdc_mbim.
+
 config USB_NET_DM9601
 	tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
 	depends on USB_USBNET
@@ -230,6 +246,8 @@ config USB_NET_DM9601
 config USB_NET_SMSC75XX
 	tristate "SMSC LAN75XX based USB 2.0 gigabit ethernet devices"
 	depends on USB_USBNET
+	select BITREVERSE
+	select CRC16
 	select CRC32
 	help
 	  This option adds support for SMSC LAN95XX based USB 2.0
@@ -238,6 +256,8 @@ config USB_NET_SMSC75XX
 config USB_NET_SMSC95XX
 	tristate "SMSC LAN95XX based USB 2.0 10/100 ethernet devices"
 	depends on USB_USBNET
+	select BITREVERSE
+	select CRC16
 	select CRC32
 	help
 	  This option adds support for SMSC LAN95XX based USB 2.0
@@ -265,7 +285,7 @@ config USB_NET_PLUSB
 	tristate "Prolific PL-2301/2302/25A1 based cables"
 	# if the handshake/init/reset problems, from original 'plusb',
 	# are ever resolved ... then remove "experimental"
-	depends on USB_USBNET && EXPERIMENTAL
+	depends on USB_USBNET
 	help
 	  Choose this option if you're using a host-to-host cable
 	  with one of these chips.
@@ -279,8 +299,8 @@ config USB_NET_MCS7830
 	  adapters marketed under the DeLOCK brand.
 
 config USB_NET_RNDIS_HOST
-	tristate "Host for RNDIS and ActiveSync devices (EXPERIMENTAL)"
-	depends on USB_USBNET && EXPERIMENTAL
+	tristate "Host for RNDIS and ActiveSync devices"
+	depends on USB_USBNET
 	select USB_NET_CDCETHER
 	help
 	  This option enables hosting "Remote NDIS" USB networking links,
@@ -358,7 +378,7 @@ config USB_EPSON2888
 
 config USB_KC2190
 	boolean "KT Technology KC2190 based cables (InstaNet)"
-	depends on USB_NET_CDC_SUBSET && EXPERIMENTAL
+	depends on USB_NET_CDC_SUBSET
 	help
 	  Choose this option if you're using a host-to-host cable
 	  with one of these chips.
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile
index bf06300..4786913 100644
--- a/drivers/net/usb/Makefile
+++ b/drivers/net/usb/Makefile
@@ -31,4 +31,5 @@ obj-$(CONFIG_USB_NET_CX82310_ETH)	+= cx82310_eth.o
 obj-$(CONFIG_USB_NET_CDC_NCM)	+= cdc_ncm.o
 obj-$(CONFIG_USB_VL600)		+= lg-vl600.o
 obj-$(CONFIG_USB_NET_QMI_WWAN)	+= qmi_wwan.o
+obj-$(CONFIG_USB_NET_CDC_MBIM)	+= cdc_mbim.o
 
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index 774d9ce..50d1673 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -25,121 +25,30 @@
 int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 		  u16 size, void *data)
 {
-	void *buf;
-	int err = -ENOMEM;
-
-	netdev_dbg(dev->net, "asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
-		   cmd, value, index, size);
-
-	buf = kmalloc(size, GFP_KERNEL);
-	if (!buf)
-		goto out;
-
-	err = usb_control_msg(
-		dev->udev,
-		usb_rcvctrlpipe(dev->udev, 0),
-		cmd,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		value,
-		index,
-		buf,
-		size,
-		USB_CTRL_GET_TIMEOUT);
-	if (err == size)
-		memcpy(data, buf, size);
-	else if (err >= 0)
-		err = -EINVAL;
-	kfree(buf);
+	int ret;
+	ret = usbnet_read_cmd(dev, cmd,
+			       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			       value, index, data, size);
 
-out:
-	return err;
+	if (ret != size && ret >= 0)
+		return -EINVAL;
+	return ret;
 }
 
 int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 		   u16 size, void *data)
 {
-	void *buf = NULL;
-	int err = -ENOMEM;
-
-	netdev_dbg(dev->net, "asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
-		   cmd, value, index, size);
-
-	if (data) {
-		buf = kmemdup(data, size, GFP_KERNEL);
-		if (!buf)
-			goto out;
-	}
-
-	err = usb_control_msg(
-		dev->udev,
-		usb_sndctrlpipe(dev->udev, 0),
-		cmd,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		value,
-		index,
-		buf,
-		size,
-		USB_CTRL_SET_TIMEOUT);
-	kfree(buf);
-
-out:
-	return err;
-}
-
-static void asix_async_cmd_callback(struct urb *urb)
-{
-	struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
-	int status = urb->status;
-
-	if (status < 0)
-		printk(KERN_DEBUG "asix_async_cmd_callback() failed with %d",
-			status);
-
-	kfree(req);
-	usb_free_urb(urb);
+	return usbnet_write_cmd(dev, cmd,
+				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+				value, index, data, size);
 }
 
 void asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 			  u16 size, void *data)
 {
-	struct usb_ctrlrequest *req;
-	int status;
-	struct urb *urb;
-
-	netdev_dbg(dev->net, "asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
-		   cmd, value, index, size);
-
-	urb = usb_alloc_urb(0, GFP_ATOMIC);
-	if (!urb) {
-		netdev_err(dev->net, "Error allocating URB in write_cmd_async!\n");
-		return;
-	}
-
-	req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
-	if (!req) {
-		netdev_err(dev->net, "Failed to allocate memory for control request\n");
-		usb_free_urb(urb);
-		return;
-	}
-
-	req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-	req->bRequest = cmd;
-	req->wValue = cpu_to_le16(value);
-	req->wIndex = cpu_to_le16(index);
-	req->wLength = cpu_to_le16(size);
-
-	usb_fill_control_urb(urb, dev->udev,
-			     usb_sndctrlpipe(dev->udev, 0),
-			     (void *)req, data, size,
-			     asix_async_cmd_callback, req);
-
-	status = usb_submit_urb(urb, GFP_ATOMIC);
-	if (status < 0) {
-		netdev_err(dev->net, "Error submitting the control message: status=%d\n",
-			   status);
-		kfree(req);
-		usb_free_urb(urb);
-	}
+	usbnet_write_cmd_async(dev, cmd,
+			       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			       value, index, data, size);
 }
 
 int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index 33ab824..7a6e758 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -64,6 +64,16 @@ static void asix_status(struct usbnet *dev, struct urb *urb)
 	}
 }
 
+static void asix_set_netdev_dev_addr(struct usbnet *dev, u8 *addr)
+{
+	if (is_valid_ether_addr(addr)) {
+		memcpy(dev->net->dev_addr, addr, ETH_ALEN);
+	} else {
+		netdev_info(dev->net, "invalid hw address, using random\n");
+		eth_hw_addr_random(dev->net);
+	}
+}
+
 /* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */
 static u32 asix_get_phyid(struct usbnet *dev)
 {
@@ -225,7 +235,8 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
 			   ret);
 		goto out;
 	}
-	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+	asix_set_netdev_dev_addr(dev, buf);
 
 	/* Initialize MII structure */
 	dev->mii.dev = dev->net;
@@ -423,7 +434,8 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 		netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret);
 		return ret;
 	}
-	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+	asix_set_netdev_dev_addr(dev, buf);
 
 	/* Initialize MII structure */
 	dev->mii.dev = dev->net;
@@ -777,7 +789,8 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
 		netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret);
 		return ret;
 	}
-	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+	asix_set_netdev_dev_addr(dev, buf);
 
 	/* Initialize MII structure */
 	dev->mii.dev = dev->net;
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
new file mode 100644
index 0000000..42f51c7
--- /dev/null
+++ b/drivers/net/usb/cdc_mbim.c
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2012  Smith Micro Software, Inc.
+ * Copyright (c) 2012  Bjørn Mork <bjorn@mork.no>
+ *
+ * This driver is based on and reuse most of cdc_ncm, which is
+ * Copyright (C) ST-Ericsson 2010-2012
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/usb/cdc.h>
+#include <linux/usb/usbnet.h>
+#include <linux/usb/cdc-wdm.h>
+#include <linux/usb/cdc_ncm.h>
+
+/* driver specific data - must match cdc_ncm usage */
+struct cdc_mbim_state {
+	struct cdc_ncm_ctx *ctx;
+	atomic_t pmcount;
+	struct usb_driver *subdriver;
+	struct usb_interface *control;
+	struct usb_interface *data;
+};
+
+/* using a counter to merge subdriver requests with our own into a combined state */
+static int cdc_mbim_manage_power(struct usbnet *dev, int on)
+{
+	struct cdc_mbim_state *info = (void *)&dev->data;
+	int rv = 0;
+
+	dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(&info->pmcount), on);
+
+	if ((on && atomic_add_return(1, &info->pmcount) == 1) || (!on && atomic_dec_and_test(&info->pmcount))) {
+		/* need autopm_get/put here to ensure the usbcore sees the new value */
+		rv = usb_autopm_get_interface(dev->intf);
+		if (rv < 0)
+			goto err;
+		dev->intf->needs_remote_wakeup = on;
+		usb_autopm_put_interface(dev->intf);
+	}
+err:
+	return rv;
+}
+
+static int cdc_mbim_wdm_manage_power(struct usb_interface *intf, int status)
+{
+	struct usbnet *dev = usb_get_intfdata(intf);
+
+	/* can be called while disconnecting */
+	if (!dev)
+		return 0;
+
+	return cdc_mbim_manage_power(dev, status);
+}
+
+
+static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	struct cdc_ncm_ctx *ctx;
+	struct usb_driver *subdriver = ERR_PTR(-ENODEV);
+	int ret = -ENODEV;
+	u8 data_altsetting = CDC_NCM_DATA_ALTSETTING_NCM;
+	struct cdc_mbim_state *info = (void *)&dev->data;
+
+	/* see if interface supports MBIM alternate setting */
+	if (intf->num_altsetting == 2) {
+		if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
+			usb_set_interface(dev->udev,
+					  intf->cur_altsetting->desc.bInterfaceNumber,
+					  CDC_NCM_COMM_ALTSETTING_MBIM);
+		data_altsetting = CDC_NCM_DATA_ALTSETTING_MBIM;
+	}
+
+	/* Probably NCM, defer for cdc_ncm_bind */
+	if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
+		goto err;
+
+	ret = cdc_ncm_bind_common(dev, intf, data_altsetting);
+	if (ret)
+		goto err;
+
+	ctx = info->ctx;
+
+	/* The MBIM descriptor and the status endpoint are required */
+	if (ctx->mbim_desc && dev->status)
+		subdriver = usb_cdc_wdm_register(ctx->control,
+						 &dev->status->desc,
+						 le16_to_cpu(ctx->mbim_desc->wMaxControlMessage),
+						 cdc_mbim_wdm_manage_power);
+	if (IS_ERR(subdriver)) {
+		ret = PTR_ERR(subdriver);
+		cdc_ncm_unbind(dev, intf);
+		goto err;
+	}
+
+	/* can't let usbnet use the interrupt endpoint */
+	dev->status = NULL;
+	info->subdriver = subdriver;
+
+	/* MBIM cannot do ARP */
+	dev->net->flags |= IFF_NOARP;
+
+	/* no need to put the VLAN tci in the packet headers */
+	dev->net->features |= NETIF_F_HW_VLAN_TX;
+err:
+	return ret;
+}
+
+static void cdc_mbim_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+	struct cdc_mbim_state *info = (void *)&dev->data;
+	struct cdc_ncm_ctx *ctx = info->ctx;
+
+	/* disconnect subdriver from control interface */
+	if (info->subdriver && info->subdriver->disconnect)
+		info->subdriver->disconnect(ctx->control);
+	info->subdriver = NULL;
+
+	/* let NCM unbind clean up both control and data interface */
+	cdc_ncm_unbind(dev, intf);
+}
+
+
+static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
+{
+	struct sk_buff *skb_out;
+	struct cdc_mbim_state *info = (void *)&dev->data;
+	struct cdc_ncm_ctx *ctx = info->ctx;
+	__le32 sign = cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN);
+	u16 tci = 0;
+	u8 *c;
+
+	if (!ctx)
+		goto error;
+
+	if (skb) {
+		if (skb->len <= sizeof(ETH_HLEN))
+			goto error;
+
+		/* mapping VLANs to MBIM sessions:
+		 *   no tag     => IPS session <0>
+		 *   1 - 255    => IPS session <vlanid>
+		 *   256 - 511  => DSS session <vlanid - 256>
+		 *   512 - 4095 => unsupported, drop
+		 */
+		vlan_get_tag(skb, &tci);
+
+		switch (tci & 0x0f00) {
+		case 0x0000: /* VLAN ID 0 - 255 */
+			/* verify that datagram is IPv4 or IPv6 */
+			skb_reset_mac_header(skb);
+			switch (eth_hdr(skb)->h_proto) {
+			case htons(ETH_P_IP):
+			case htons(ETH_P_IPV6):
+				break;
+			default:
+				goto error;
+			}
+			c = (u8 *)&sign;
+			c[3] = tci;
+			break;
+		case 0x0100: /* VLAN ID 256 - 511 */
+			sign = cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN);
+			c = (u8 *)&sign;
+			c[3] = tci;
+			break;
+		default:
+			netif_err(dev, tx_err, dev->net,
+				  "unsupported tci=0x%04x\n", tci);
+			goto error;
+		}
+		skb_pull(skb, ETH_HLEN);
+	}
+
+	spin_lock_bh(&ctx->mtx);
+	skb_out = cdc_ncm_fill_tx_frame(ctx, skb, sign);
+	spin_unlock_bh(&ctx->mtx);
+	return skb_out;
+
+error:
+	if (skb)
+		dev_kfree_skb_any(skb);
+
+	return NULL;
+}
+
+static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_t len, u16 tci)
+{
+	__be16 proto = htons(ETH_P_802_3);
+	struct sk_buff *skb = NULL;
+
+	if (tci < 256) { /* IPS session? */
+		if (len < sizeof(struct iphdr))
+			goto err;
+
+		switch (*buf & 0xf0) {
+		case 0x40:
+			proto = htons(ETH_P_IP);
+			break;
+		case 0x60:
+			proto = htons(ETH_P_IPV6);
+			break;
+		default:
+			goto err;
+		}
+	}
+
+	skb = netdev_alloc_skb_ip_align(dev->net,  len + ETH_HLEN);
+	if (!skb)
+		goto err;
+
+	/* add an ethernet header */
+	skb_put(skb, ETH_HLEN);
+	skb_reset_mac_header(skb);
+	eth_hdr(skb)->h_proto = proto;
+	memset(eth_hdr(skb)->h_source, 0, ETH_ALEN);
+	memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN);
+
+	/* add datagram */
+	memcpy(skb_put(skb, len), buf, len);
+
+	/* map MBIM session to VLAN */
+	if (tci)
+		vlan_put_tag(skb, tci);
+err:
+	return skb;
+}
+
+static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
+{
+	struct sk_buff *skb;
+	struct cdc_mbim_state *info = (void *)&dev->data;
+	struct cdc_ncm_ctx *ctx = info->ctx;
+	int len;
+	int nframes;
+	int x;
+	int offset;
+	struct usb_cdc_ncm_ndp16 *ndp16;
+	struct usb_cdc_ncm_dpe16 *dpe16;
+	int ndpoffset;
+	int loopcount = 50; /* arbitrary max preventing infinite loop */
+	u8 *c;
+	u16 tci;
+
+	ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
+	if (ndpoffset < 0)
+		goto error;
+
+next_ndp:
+	nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
+	if (nframes < 0)
+		goto error;
+
+	ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
+
+	switch (ndp16->dwSignature & cpu_to_le32(0x00ffffff)) {
+	case cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN):
+		c = (u8 *)&ndp16->dwSignature;
+		tci = c[3];
+		break;
+	case cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN):
+		c = (u8 *)&ndp16->dwSignature;
+		tci = c[3] + 256;
+		break;
+	default:
+		netif_dbg(dev, rx_err, dev->net,
+			  "unsupported NDP signature <0x%08x>\n",
+			  le32_to_cpu(ndp16->dwSignature));
+		goto err_ndp;
+
+	}
+
+	dpe16 = ndp16->dpe16;
+	for (x = 0; x < nframes; x++, dpe16++) {
+		offset = le16_to_cpu(dpe16->wDatagramIndex);
+		len = le16_to_cpu(dpe16->wDatagramLength);
+
+		/*
+		 * CDC NCM ch. 3.7
+		 * All entries after first NULL entry are to be ignored
+		 */
+		if ((offset == 0) || (len == 0)) {
+			if (!x)
+				goto err_ndp; /* empty NTB */
+			break;
+		}
+
+		/* sanity checking */
+		if (((offset + len) > skb_in->len) || (len > ctx->rx_max)) {
+			netif_dbg(dev, rx_err, dev->net,
+				  "invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%p\n",
+				  x, offset, len, skb_in);
+			if (!x)
+				goto err_ndp;
+			break;
+		} else {
+			skb = cdc_mbim_process_dgram(dev, skb_in->data + offset, len, tci);
+			if (!skb)
+				goto error;
+			usbnet_skb_return(dev, skb);
+		}
+	}
+err_ndp:
+	/* are there more NDPs to process? */
+	ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
+	if (ndpoffset && loopcount--)
+		goto next_ndp;
+
+	return 1;
+error:
+	return 0;
+}
+
+static int cdc_mbim_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	int ret = 0;
+	struct usbnet *dev = usb_get_intfdata(intf);
+	struct cdc_mbim_state *info = (void *)&dev->data;
+	struct cdc_ncm_ctx *ctx = info->ctx;
+
+	if (ctx == NULL) {
+		ret = -1;
+		goto error;
+	}
+
+	ret = usbnet_suspend(intf, message);
+	if (ret < 0)
+		goto error;
+
+	if (intf == ctx->control && info->subdriver && info->subdriver->suspend)
+		ret = info->subdriver->suspend(intf, message);
+	if (ret < 0)
+		usbnet_resume(intf);
+
+error:
+	return ret;
+}
+
+static int cdc_mbim_resume(struct usb_interface *intf)
+{
+	int  ret = 0;
+	struct usbnet *dev = usb_get_intfdata(intf);
+	struct cdc_mbim_state *info = (void *)&dev->data;
+	struct cdc_ncm_ctx *ctx = info->ctx;
+	bool callsub = (intf == ctx->control && info->subdriver && info->subdriver->resume);
+
+	if (callsub)
+		ret = info->subdriver->resume(intf);
+	if (ret < 0)
+		goto err;
+	ret = usbnet_resume(intf);
+	if (ret < 0 && callsub && info->subdriver->suspend)
+		info->subdriver->suspend(intf, PMSG_SUSPEND);
+err:
+	return ret;
+}
+
+static const struct driver_info cdc_mbim_info = {
+	.description = "CDC MBIM",
+	.flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN,
+	.bind = cdc_mbim_bind,
+	.unbind = cdc_mbim_unbind,
+	.manage_power = cdc_mbim_manage_power,
+	.rx_fixup = cdc_mbim_rx_fixup,
+	.tx_fixup = cdc_mbim_tx_fixup,
+};
+
+static const struct usb_device_id mbim_devs[] = {
+	/* This duplicate NCM entry is intentional. MBIM devices can
+	 * be disguised as NCM by default, and this is necessary to
+	 * allow us to bind the correct driver_info to such devices.
+	 *
+	 * bind() will sort out this for us, selecting the correct
+	 * entry and reject the other
+	 */
+	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
+	  .driver_info = (unsigned long)&cdc_mbim_info,
+	},
+	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
+	  .driver_info = (unsigned long)&cdc_mbim_info,
+	},
+	{
+	},
+};
+MODULE_DEVICE_TABLE(usb, mbim_devs);
+
+static struct usb_driver cdc_mbim_driver = {
+	.name = "cdc_mbim",
+	.id_table = mbim_devs,
+	.probe = usbnet_probe,
+	.disconnect = usbnet_disconnect,
+	.suspend = cdc_mbim_suspend,
+	.resume = cdc_mbim_resume,
+	.reset_resume =	cdc_mbim_resume,
+	.supports_autosuspend = 1,
+	.disable_hub_initiated_lpm = 1,
+};
+module_usb_driver(cdc_mbim_driver);
+
+MODULE_AUTHOR("Greg Suarez <gsuarez@smithmicro.com>");
+MODULE_AUTHOR("Bjørn Mork <bjorn@mork.no>");
+MODULE_DESCRIPTION("USB CDC MBIM host driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 74fab1a..d38bc20 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -51,90 +51,10 @@
 #include <linux/atomic.h>
 #include <linux/usb/usbnet.h>
 #include <linux/usb/cdc.h>
+#include <linux/usb/cdc_ncm.h>
 
 #define	DRIVER_VERSION				"14-Mar-2012"
 
-/* CDC NCM subclass 3.2.1 */
-#define USB_CDC_NCM_NDP16_LENGTH_MIN		0x10
-
-/* Maximum NTB length */
-#define	CDC_NCM_NTB_MAX_SIZE_TX			32768	/* bytes */
-#define	CDC_NCM_NTB_MAX_SIZE_RX			32768	/* bytes */
-
-/* Minimum value for MaxDatagramSize, ch. 6.2.9 */
-#define	CDC_NCM_MIN_DATAGRAM_SIZE		1514	/* bytes */
-
-#define	CDC_NCM_MIN_TX_PKT			512	/* bytes */
-
-/* Default value for MaxDatagramSize */
-#define	CDC_NCM_MAX_DATAGRAM_SIZE		8192	/* bytes */
-
-/*
- * Maximum amount of datagrams in NCM Datagram Pointer Table, not counting
- * the last NULL entry.
- */
-#define	CDC_NCM_DPT_DATAGRAMS_MAX		40
-
-/* Restart the timer, if amount of datagrams is less than given value */
-#define	CDC_NCM_RESTART_TIMER_DATAGRAM_CNT	3
-#define	CDC_NCM_TIMER_PENDING_CNT		2
-#define CDC_NCM_TIMER_INTERVAL			(400UL * NSEC_PER_USEC)
-
-/* The following macro defines the minimum header space */
-#define	CDC_NCM_MIN_HDR_SIZE \
-	(sizeof(struct usb_cdc_ncm_nth16) + sizeof(struct usb_cdc_ncm_ndp16) + \
-	(CDC_NCM_DPT_DATAGRAMS_MAX + 1) * sizeof(struct usb_cdc_ncm_dpe16))
-
-struct cdc_ncm_data {
-	struct usb_cdc_ncm_nth16 nth16;
-	struct usb_cdc_ncm_ndp16 ndp16;
-	struct usb_cdc_ncm_dpe16 dpe16[CDC_NCM_DPT_DATAGRAMS_MAX + 1];
-};
-
-struct cdc_ncm_ctx {
-	struct cdc_ncm_data tx_ncm;
-	struct usb_cdc_ncm_ntb_parameters ncm_parm;
-	struct hrtimer tx_timer;
-	struct tasklet_struct bh;
-
-	const struct usb_cdc_ncm_desc *func_desc;
-	const struct usb_cdc_header_desc *header_desc;
-	const struct usb_cdc_union_desc *union_desc;
-	const struct usb_cdc_ether_desc *ether_desc;
-
-	struct net_device *netdev;
-	struct usb_device *udev;
-	struct usb_host_endpoint *in_ep;
-	struct usb_host_endpoint *out_ep;
-	struct usb_host_endpoint *status_ep;
-	struct usb_interface *intf;
-	struct usb_interface *control;
-	struct usb_interface *data;
-
-	struct sk_buff *tx_curr_skb;
-	struct sk_buff *tx_rem_skb;
-
-	spinlock_t mtx;
-	atomic_t stop;
-
-	u32 tx_timer_pending;
-	u32 tx_curr_offset;
-	u32 tx_curr_last_offset;
-	u32 tx_curr_frame_num;
-	u32 rx_speed;
-	u32 tx_speed;
-	u32 rx_max;
-	u32 tx_max;
-	u32 max_datagram_size;
-	u16 tx_max_datagrams;
-	u16 tx_remainder;
-	u16 tx_modulus;
-	u16 tx_ndp_modulus;
-	u16 tx_seq;
-	u16 rx_seq;
-	u16 connected;
-};
-
 static void cdc_ncm_txpath_bh(unsigned long param);
 static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx);
 static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer);
@@ -158,17 +78,19 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
 	u8 flags;
 	u8 iface_no;
 	int err;
+	int eth_hlen;
 	u16 ntb_fmt_supported;
+	u32 min_dgram_size;
+	u32 min_hdr_size;
+	struct usbnet *dev = netdev_priv(ctx->netdev);
 
 	iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber;
 
-	err = usb_control_msg(ctx->udev,
-				usb_rcvctrlpipe(ctx->udev, 0),
-				USB_CDC_GET_NTB_PARAMETERS,
-				USB_TYPE_CLASS | USB_DIR_IN
-				 | USB_RECIP_INTERFACE,
-				0, iface_no, &ctx->ncm_parm,
-				sizeof(ctx->ncm_parm), 10000);
+	err = usbnet_read_cmd(dev, USB_CDC_GET_NTB_PARAMETERS,
+			      USB_TYPE_CLASS | USB_DIR_IN
+			      |USB_RECIP_INTERFACE,
+			      0, iface_no, &ctx->ncm_parm,
+			      sizeof(ctx->ncm_parm));
 	if (err < 0) {
 		pr_debug("failed GET_NTB_PARAMETERS\n");
 		return 1;
@@ -184,10 +106,19 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
 	ctx->tx_max_datagrams = le16_to_cpu(ctx->ncm_parm.wNtbOutMaxDatagrams);
 	ntb_fmt_supported = le16_to_cpu(ctx->ncm_parm.bmNtbFormatsSupported);
 
-	if (ctx->func_desc != NULL)
+	eth_hlen = ETH_HLEN;
+	min_dgram_size = CDC_NCM_MIN_DATAGRAM_SIZE;
+	min_hdr_size = CDC_NCM_MIN_HDR_SIZE;
+	if (ctx->mbim_desc != NULL) {
+		flags = ctx->mbim_desc->bmNetworkCapabilities;
+		eth_hlen = 0;
+		min_dgram_size = CDC_MBIM_MIN_DATAGRAM_SIZE;
+		min_hdr_size = 0;
+	} else if (ctx->func_desc != NULL) {
 		flags = ctx->func_desc->bmNetworkCapabilities;
-	else
+	} else {
 		flags = 0;
+	}
 
 	pr_debug("dwNtbInMaxSize=%u dwNtbOutMaxSize=%u "
 		 "wNdpOutPayloadRemainder=%u wNdpOutDivisor=%u "
@@ -215,49 +146,19 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
 
 	/* inform device about NTB input size changes */
 	if (ctx->rx_max != le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize)) {
+		__le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
 
-		if (flags & USB_CDC_NCM_NCAP_NTB_INPUT_SIZE) {
-			struct usb_cdc_ncm_ndp_input_size *ndp_in_sz;
-
-			ndp_in_sz = kzalloc(sizeof(*ndp_in_sz), GFP_KERNEL);
-			if (!ndp_in_sz) {
-				err = -ENOMEM;
-				goto size_err;
-			}
-
-			err = usb_control_msg(ctx->udev,
-					usb_sndctrlpipe(ctx->udev, 0),
-					USB_CDC_SET_NTB_INPUT_SIZE,
-					USB_TYPE_CLASS | USB_DIR_OUT
-					 | USB_RECIP_INTERFACE,
-					0, iface_no, ndp_in_sz, 8, 1000);
-			kfree(ndp_in_sz);
-		} else {
-			__le32 *dwNtbInMaxSize;
-			dwNtbInMaxSize = kzalloc(sizeof(*dwNtbInMaxSize),
-					GFP_KERNEL);
-			if (!dwNtbInMaxSize) {
-				err = -ENOMEM;
-				goto size_err;
-			}
-			*dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
-
-			err = usb_control_msg(ctx->udev,
-					usb_sndctrlpipe(ctx->udev, 0),
-					USB_CDC_SET_NTB_INPUT_SIZE,
-					USB_TYPE_CLASS | USB_DIR_OUT
-					 | USB_RECIP_INTERFACE,
-					0, iface_no, dwNtbInMaxSize, 4, 1000);
-			kfree(dwNtbInMaxSize);
-		}
-size_err:
+		err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_INPUT_SIZE,
+				       USB_TYPE_CLASS | USB_DIR_OUT
+				       | USB_RECIP_INTERFACE,
+				       0, iface_no, &dwNtbInMaxSize, 4);
 		if (err < 0)
 			pr_debug("Setting NTB Input Size failed\n");
 	}
 
 	/* verify maximum size of transmitted NTB in bytes */
 	if ((ctx->tx_max <
-	    (CDC_NCM_MIN_HDR_SIZE + CDC_NCM_MIN_DATAGRAM_SIZE)) ||
+	    (min_hdr_size + min_dgram_size)) ||
 	    (ctx->tx_max > CDC_NCM_NTB_MAX_SIZE_TX)) {
 		pr_debug("Using default maximum transmit length=%d\n",
 						CDC_NCM_NTB_MAX_SIZE_TX);
@@ -299,93 +200,85 @@ size_err:
 	}
 
 	/* adjust TX-remainder according to NCM specification. */
-	ctx->tx_remainder = ((ctx->tx_remainder - ETH_HLEN) &
-						(ctx->tx_modulus - 1));
+	ctx->tx_remainder = ((ctx->tx_remainder - eth_hlen) &
+			     (ctx->tx_modulus - 1));
 
 	/* additional configuration */
 
 	/* set CRC Mode */
 	if (flags & USB_CDC_NCM_NCAP_CRC_MODE) {
-		err = usb_control_msg(ctx->udev, usb_sndctrlpipe(ctx->udev, 0),
-				USB_CDC_SET_CRC_MODE,
-				USB_TYPE_CLASS | USB_DIR_OUT
-				 | USB_RECIP_INTERFACE,
-				USB_CDC_NCM_CRC_NOT_APPENDED,
-				iface_no, NULL, 0, 1000);
+		err = usbnet_write_cmd(dev, USB_CDC_SET_CRC_MODE,
+				       USB_TYPE_CLASS | USB_DIR_OUT
+				       | USB_RECIP_INTERFACE,
+				       USB_CDC_NCM_CRC_NOT_APPENDED,
+				       iface_no, NULL, 0);
 		if (err < 0)
 			pr_debug("Setting CRC mode off failed\n");
 	}
 
 	/* set NTB format, if both formats are supported */
 	if (ntb_fmt_supported & USB_CDC_NCM_NTH32_SIGN) {
-		err = usb_control_msg(ctx->udev, usb_sndctrlpipe(ctx->udev, 0),
-				USB_CDC_SET_NTB_FORMAT, USB_TYPE_CLASS
-				 | USB_DIR_OUT | USB_RECIP_INTERFACE,
-				USB_CDC_NCM_NTB16_FORMAT,
-				iface_no, NULL, 0, 1000);
+		err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT,
+				       USB_TYPE_CLASS | USB_DIR_OUT
+				       | USB_RECIP_INTERFACE,
+				       USB_CDC_NCM_NTB16_FORMAT,
+				       iface_no, NULL, 0);
 		if (err < 0)
 			pr_debug("Setting NTB format to 16-bit failed\n");
 	}
 
-	ctx->max_datagram_size = CDC_NCM_MIN_DATAGRAM_SIZE;
+	ctx->max_datagram_size = min_dgram_size;
 
 	/* set Max Datagram Size (MTU) */
 	if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) {
-		__le16 *max_datagram_size;
-		u16 eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
-
-		max_datagram_size = kzalloc(sizeof(*max_datagram_size),
-				GFP_KERNEL);
-		if (!max_datagram_size) {
-			err = -ENOMEM;
+		__le16 max_datagram_size;
+		u16 eth_max_sz;
+		if (ctx->ether_desc != NULL)
+			eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
+		else if (ctx->mbim_desc != NULL)
+			eth_max_sz = le16_to_cpu(ctx->mbim_desc->wMaxSegmentSize);
+		else
 			goto max_dgram_err;
-		}
 
-		err = usb_control_msg(ctx->udev, usb_rcvctrlpipe(ctx->udev, 0),
-				USB_CDC_GET_MAX_DATAGRAM_SIZE,
-				USB_TYPE_CLASS | USB_DIR_IN
-				 | USB_RECIP_INTERFACE,
-				0, iface_no, max_datagram_size,
-				2, 1000);
+		err = usbnet_read_cmd(dev, USB_CDC_GET_MAX_DATAGRAM_SIZE,
+				      USB_TYPE_CLASS | USB_DIR_IN
+				      | USB_RECIP_INTERFACE,
+				      0, iface_no, &max_datagram_size, 2);
 		if (err < 0) {
 			pr_debug("GET_MAX_DATAGRAM_SIZE failed, use size=%u\n",
-						CDC_NCM_MIN_DATAGRAM_SIZE);
+				 min_dgram_size);
 		} else {
 			ctx->max_datagram_size =
-				le16_to_cpu(*max_datagram_size);
+				le16_to_cpu(max_datagram_size);
 			/* Check Eth descriptor value */
 			if (ctx->max_datagram_size > eth_max_sz)
 					ctx->max_datagram_size = eth_max_sz;
 
 			if (ctx->max_datagram_size > CDC_NCM_MAX_DATAGRAM_SIZE)
-				ctx->max_datagram_size =
-						CDC_NCM_MAX_DATAGRAM_SIZE;
+				ctx->max_datagram_size = CDC_NCM_MAX_DATAGRAM_SIZE;
 
-			if (ctx->max_datagram_size < CDC_NCM_MIN_DATAGRAM_SIZE)
-				ctx->max_datagram_size =
-					CDC_NCM_MIN_DATAGRAM_SIZE;
+			if (ctx->max_datagram_size < min_dgram_size)
+				ctx->max_datagram_size = min_dgram_size;
 
 			/* if value changed, update device */
 			if (ctx->max_datagram_size !=
-					le16_to_cpu(*max_datagram_size)) {
-				err = usb_control_msg(ctx->udev,
-						usb_sndctrlpipe(ctx->udev, 0),
+					le16_to_cpu(max_datagram_size)) {
+				err = usbnet_write_cmd(dev,
 						USB_CDC_SET_MAX_DATAGRAM_SIZE,
 						USB_TYPE_CLASS | USB_DIR_OUT
 						 | USB_RECIP_INTERFACE,
 						0,
-						iface_no, max_datagram_size,
-						2, 1000);
+						iface_no, &max_datagram_size,
+						2);
 				if (err < 0)
 					pr_debug("SET_MAX_DGRAM_SIZE failed\n");
 			}
 		}
-		kfree(max_datagram_size);
 	}
 
 max_dgram_err:
-	if (ctx->netdev->mtu != (ctx->max_datagram_size - ETH_HLEN))
-		ctx->netdev->mtu = ctx->max_datagram_size - ETH_HLEN;
+	if (ctx->netdev->mtu != (ctx->max_datagram_size - eth_hlen))
+		ctx->netdev->mtu = ctx->max_datagram_size - eth_hlen;
 
 	return 0;
 }
@@ -451,7 +344,7 @@ static const struct ethtool_ops cdc_ncm_ethtool_ops = {
 	.nway_reset = usbnet_nway_reset,
 };
 
-static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
+int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting)
 {
 	struct cdc_ncm_ctx *ctx;
 	struct usb_driver *driver;
@@ -525,6 +418,13 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
 			ctx->func_desc = (const struct usb_cdc_ncm_desc *)buf;
 			break;
 
+		case USB_CDC_MBIM_TYPE:
+			if (buf[0] < sizeof(*(ctx->mbim_desc)))
+				break;
+
+			ctx->mbim_desc = (const struct usb_cdc_mbim_desc *)buf;
+			break;
+
 		default:
 			break;
 		}
@@ -537,7 +437,7 @@ advance:
 
 	/* check if we got everything */
 	if ((ctx->control == NULL) || (ctx->data == NULL) ||
-	    (ctx->ether_desc == NULL) || (ctx->control != intf))
+	    ((!ctx->mbim_desc) && ((ctx->ether_desc == NULL) || (ctx->control != intf))))
 		goto error;
 
 	/* claim data interface, if different from control */
@@ -559,7 +459,7 @@ advance:
 		goto error2;
 
 	/* configure data interface */
-	temp = usb_set_interface(dev->udev, iface_no, 1);
+	temp = usb_set_interface(dev->udev, iface_no, data_altsetting);
 	if (temp)
 		goto error2;
 
@@ -576,11 +476,13 @@ advance:
 	usb_set_intfdata(ctx->control, dev);
 	usb_set_intfdata(ctx->intf, dev);
 
-	temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress);
-	if (temp)
-		goto error2;
+	if (ctx->ether_desc) {
+		temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress);
+		if (temp)
+			goto error2;
+		dev_info(&dev->udev->dev, "MAC-Address: %pM\n", dev->net->dev_addr);
+	}
 
-	dev_info(&dev->udev->dev, "MAC-Address: %pM\n", dev->net->dev_addr);
 
 	dev->in = usb_rcvbulkpipe(dev->udev,
 		ctx->in_ep->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
@@ -589,13 +491,6 @@ advance:
 	dev->status = ctx->status_ep;
 	dev->rx_urb_size = ctx->rx_max;
 
-	/*
-	 * We should get an event when network connection is "connected" or
-	 * "disconnected". Set network connection in "disconnected" state
-	 * (carrier is OFF) during attach, so the IP network stack does not
-	 * start IPv6 negotiation and more.
-	 */
-	netif_carrier_off(dev->net);
 	ctx->tx_speed = ctx->rx_speed = 0;
 	return 0;
 
@@ -609,8 +504,9 @@ error:
 	dev_info(&dev->udev->dev, "bind() failure\n");
 	return -ENODEV;
 }
+EXPORT_SYMBOL_GPL(cdc_ncm_bind_common);
 
-static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
+void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
 {
 	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
 	struct usb_driver *driver = driver_of(intf);
@@ -644,52 +540,121 @@ static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
 	usb_set_intfdata(ctx->intf, NULL);
 	cdc_ncm_free(ctx);
 }
+EXPORT_SYMBOL_GPL(cdc_ncm_unbind);
 
-static void cdc_ncm_zero_fill(u8 *ptr, u32 first, u32 end, u32 max)
+static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
 {
-	if (first >= max)
-		return;
-	if (first >= end)
-		return;
-	if (end > max)
-		end = max;
-	memset(ptr + first, 0, end - first);
+	int ret;
+
+	/* The MBIM spec defines a NCM compatible default altsetting,
+	 * which we may have matched:
+	 *
+	 *  "Functions that implement both NCM 1.0 and MBIM (an
+	 *   “NCM/MBIM function”) according to this recommendation
+	 *   shall provide two alternate settings for the
+	 *   Communication Interface.  Alternate setting 0, and the
+	 *   associated class and endpoint descriptors, shall be
+	 *   constructed according to the rules given for the
+	 *   Communication Interface in section 5 of [USBNCM10].
+	 *   Alternate setting 1, and the associated class and
+	 *   endpoint descriptors, shall be constructed according to
+	 *   the rules given in section 6 (USB Device Model) of this
+	 *   specification."
+	 *
+	 * Do not bind to such interfaces, allowing cdc_mbim to handle
+	 * them
+	 */
+#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM)
+	if ((intf->num_altsetting == 2) &&
+	    !usb_set_interface(dev->udev,
+			       intf->cur_altsetting->desc.bInterfaceNumber,
+			       CDC_NCM_COMM_ALTSETTING_MBIM) &&
+	    cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
+		return -ENODEV;
+#endif
+
+	/* NCM data altsetting is always 1 */
+	ret = cdc_ncm_bind_common(dev, intf, 1);
+
+	/*
+	 * We should get an event when network connection is "connected" or
+	 * "disconnected". Set network connection in "disconnected" state
+	 * (carrier is OFF) during attach, so the IP network stack does not
+	 * start IPv6 negotiation and more.
+	 */
+	netif_carrier_off(dev->net);
+	return ret;
 }
 
-static struct sk_buff *
-cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
+static void cdc_ncm_align_tail(struct sk_buff *skb, size_t modulus, size_t remainder, size_t max)
 {
+	size_t align = ALIGN(skb->len, modulus) - skb->len + remainder;
+
+	if (skb->len + align > max)
+		align = max - skb->len;
+	if (align && skb_tailroom(skb) >= align)
+		memset(skb_put(skb, align), 0, align);
+}
+
+/* return a pointer to a valid struct usb_cdc_ncm_ndp16 of type sign, possibly
+ * allocating a new one within skb
+ */
+static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign, size_t reserve)
+{
+	struct usb_cdc_ncm_ndp16 *ndp16 = NULL;
+	struct usb_cdc_ncm_nth16 *nth16 = (void *)skb->data;
+	size_t ndpoffset = le16_to_cpu(nth16->wNdpIndex);
+
+	/* follow the chain of NDPs, looking for a match */
+	while (ndpoffset) {
+		ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb->data + ndpoffset);
+		if  (ndp16->dwSignature == sign)
+			return ndp16;
+		ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
+	}
+
+	/* align new NDP */
+	cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_max);
+
+	/* verify that there is room for the NDP and the datagram (reserve) */
+	if ((ctx->tx_max - skb->len - reserve) < CDC_NCM_NDP_SIZE)
+		return NULL;
+
+	/* link to it */
+	if (ndp16)
+		ndp16->wNextNdpIndex = cpu_to_le16(skb->len);
+	else
+		nth16->wNdpIndex = cpu_to_le16(skb->len);
+
+	/* push a new empty NDP */
+	ndp16 = (struct usb_cdc_ncm_ndp16 *)memset(skb_put(skb, CDC_NCM_NDP_SIZE), 0, CDC_NCM_NDP_SIZE);
+	ndp16->dwSignature = sign;
+	ndp16->wLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_ndp16) + sizeof(struct usb_cdc_ncm_dpe16));
+	return ndp16;
+}
+
+struct sk_buff *
+cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign)
+{
+	struct usb_cdc_ncm_nth16 *nth16;
+	struct usb_cdc_ncm_ndp16 *ndp16;
 	struct sk_buff *skb_out;
-	u32 rem;
-	u32 offset;
-	u32 last_offset;
-	u16 n = 0, index;
+	u16 n = 0, index, ndplen;
 	u8 ready2send = 0;
 
 	/* if there is a remaining skb, it gets priority */
-	if (skb != NULL)
+	if (skb != NULL) {
 		swap(skb, ctx->tx_rem_skb);
-	else
+		swap(sign, ctx->tx_rem_sign);
+	} else {
 		ready2send = 1;
-
-	/*
-	 * +----------------+
-	 * | skb_out        |
-	 * +----------------+
-	 *           ^ offset
-	 *        ^ last_offset
-	 */
+	}
 
 	/* check if we are resuming an OUT skb */
-	if (ctx->tx_curr_skb != NULL) {
-		/* pop variables */
-		skb_out = ctx->tx_curr_skb;
-		offset = ctx->tx_curr_offset;
-		last_offset = ctx->tx_curr_last_offset;
-		n = ctx->tx_curr_frame_num;
+	skb_out = ctx->tx_curr_skb;
 
-	} else {
-		/* reset variables */
+	/* allocate a new OUT skb */
+	if (!skb_out) {
 		skb_out = alloc_skb((ctx->tx_max + 1), GFP_ATOMIC);
 		if (skb_out == NULL) {
 			if (skb != NULL) {
@@ -698,35 +663,21 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
 			}
 			goto exit_no_skb;
 		}
+		/* fill out the initial 16-bit NTB header */
+		nth16 = (struct usb_cdc_ncm_nth16 *)memset(skb_put(skb_out, sizeof(struct usb_cdc_ncm_nth16)), 0, sizeof(struct usb_cdc_ncm_nth16));
+		nth16->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
+		nth16->wHeaderLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_nth16));
+		nth16->wSequence = cpu_to_le16(ctx->tx_seq++);
 
-		/* make room for NTH and NDP */
-		offset = ALIGN(sizeof(struct usb_cdc_ncm_nth16),
-					ctx->tx_ndp_modulus) +
-					sizeof(struct usb_cdc_ncm_ndp16) +
-					(ctx->tx_max_datagrams + 1) *
-					sizeof(struct usb_cdc_ncm_dpe16);
-
-		/* store last valid offset before alignment */
-		last_offset = offset;
-		/* align first Datagram offset correctly */
-		offset = ALIGN(offset, ctx->tx_modulus) + ctx->tx_remainder;
-		/* zero buffer till the first IP datagram */
-		cdc_ncm_zero_fill(skb_out->data, 0, offset, offset);
-		n = 0;
+		/* count total number of frames in this NTB */
 		ctx->tx_curr_frame_num = 0;
 	}
 
-	for (; n < ctx->tx_max_datagrams; n++) {
-		/* check if end of transmit buffer is reached */
-		if (offset >= ctx->tx_max) {
-			ready2send = 1;
-			break;
-		}
-		/* compute maximum buffer size */
-		rem = ctx->tx_max - offset;
-
+	for (n = ctx->tx_curr_frame_num; n < ctx->tx_max_datagrams; n++) {
+		/* send any remaining skb first */
 		if (skb == NULL) {
 			skb = ctx->tx_rem_skb;
+			sign = ctx->tx_rem_sign;
 			ctx->tx_rem_skb = NULL;
 
 			/* check for end of skb */
@@ -734,7 +685,14 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
 				break;
 		}
 
-		if (skb->len > rem) {
+		/* get the appropriate NDP for this skb */
+		ndp16 = cdc_ncm_ndp(ctx, skb_out, sign, skb->len + ctx->tx_modulus + ctx->tx_remainder);
+
+		/* align beginning of next frame */
+		cdc_ncm_align_tail(skb_out,  ctx->tx_modulus, ctx->tx_remainder, ctx->tx_max);
+
+		/* check if we had enough room left for both NDP and frame */
+		if (!ndp16 || skb_out->len + skb->len > ctx->tx_max) {
 			if (n == 0) {
 				/* won't fit, MTU problem? */
 				dev_kfree_skb_any(skb);
@@ -747,31 +705,30 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
 					ctx->netdev->stats.tx_dropped++;
 				}
 				ctx->tx_rem_skb = skb;
+				ctx->tx_rem_sign = sign;
 				skb = NULL;
 				ready2send = 1;
 			}
 			break;
 		}
 
-		memcpy(((u8 *)skb_out->data) + offset, skb->data, skb->len);
-
-		ctx->tx_ncm.dpe16[n].wDatagramLength = cpu_to_le16(skb->len);
-		ctx->tx_ncm.dpe16[n].wDatagramIndex = cpu_to_le16(offset);
-
-		/* update offset */
-		offset += skb->len;
-
-		/* store last valid offset before alignment */
-		last_offset = offset;
-
-		/* align offset correctly */
-		offset = ALIGN(offset, ctx->tx_modulus) + ctx->tx_remainder;
+		/* calculate frame number withing this NDP */
+		ndplen = le16_to_cpu(ndp16->wLength);
+		index = (ndplen - sizeof(struct usb_cdc_ncm_ndp16)) / sizeof(struct usb_cdc_ncm_dpe16) - 1;
 
-		/* zero padding */
-		cdc_ncm_zero_fill(skb_out->data, last_offset, offset,
-								ctx->tx_max);
+		/* OK, add this skb */
+		ndp16->dpe16[index].wDatagramLength = cpu_to_le16(skb->len);
+		ndp16->dpe16[index].wDatagramIndex = cpu_to_le16(skb_out->len);
+		ndp16->wLength = cpu_to_le16(ndplen + sizeof(struct usb_cdc_ncm_dpe16));
+		memcpy(skb_put(skb_out, skb->len), skb->data, skb->len);
 		dev_kfree_skb_any(skb);
 		skb = NULL;
+
+		/* send now if this NDP is full */
+		if (index >= CDC_NCM_DPT_DATAGRAMS_MAX) {
+			ready2send = 1;
+			break;
+		}
 	}
 
 	/* free up any dangling skb */
@@ -787,16 +744,12 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
 		/* wait for more frames */
 		/* push variables */
 		ctx->tx_curr_skb = skb_out;
-		ctx->tx_curr_offset = offset;
-		ctx->tx_curr_last_offset = last_offset;
 		goto exit_no_skb;
 
 	} else if ((n < ctx->tx_max_datagrams) && (ready2send == 0)) {
 		/* wait for more frames */
 		/* push variables */
 		ctx->tx_curr_skb = skb_out;
-		ctx->tx_curr_offset = offset;
-		ctx->tx_curr_last_offset = last_offset;
 		/* set the pending count */
 		if (n < CDC_NCM_RESTART_TIMER_DATAGRAM_CNT)
 			ctx->tx_timer_pending = CDC_NCM_TIMER_PENDING_CNT;
@@ -807,75 +760,24 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
 		/* variables will be reset at next call */
 	}
 
-	/* check for overflow */
-	if (last_offset > ctx->tx_max)
-		last_offset = ctx->tx_max;
-
-	/* revert offset */
-	offset = last_offset;
-
 	/*
 	 * If collected data size is less or equal CDC_NCM_MIN_TX_PKT bytes,
 	 * we send buffers as it is. If we get more data, it would be more
 	 * efficient for USB HS mobile device with DMA engine to receive a full
 	 * size NTB, than canceling DMA transfer and receiving a short packet.
 	 */
-	if (offset > CDC_NCM_MIN_TX_PKT)
-		offset = ctx->tx_max;
-
-	/* final zero padding */
-	cdc_ncm_zero_fill(skb_out->data, last_offset, offset, ctx->tx_max);
-
-	/* store last offset */
-	last_offset = offset;
-
-	if (((last_offset < ctx->tx_max) && ((last_offset %
-			le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0)) ||
-	    (((last_offset == ctx->tx_max) && ((ctx->tx_max %
-		le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0)) &&
-		(ctx->tx_max < le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize)))) {
-		/* force short packet */
-		*(((u8 *)skb_out->data) + last_offset) = 0;
-		last_offset++;
-	}
-
-	/* zero the rest of the DPEs plus the last NULL entry */
-	for (; n <= CDC_NCM_DPT_DATAGRAMS_MAX; n++) {
-		ctx->tx_ncm.dpe16[n].wDatagramLength = 0;
-		ctx->tx_ncm.dpe16[n].wDatagramIndex = 0;
-	}
+	if (skb_out->len > CDC_NCM_MIN_TX_PKT)
+		/* final zero padding */
+		memset(skb_put(skb_out, ctx->tx_max - skb_out->len), 0, ctx->tx_max - skb_out->len);
 
-	/* fill out 16-bit NTB header */
-	ctx->tx_ncm.nth16.dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
-	ctx->tx_ncm.nth16.wHeaderLength =
-					cpu_to_le16(sizeof(ctx->tx_ncm.nth16));
-	ctx->tx_ncm.nth16.wSequence = cpu_to_le16(ctx->tx_seq);
-	ctx->tx_ncm.nth16.wBlockLength = cpu_to_le16(last_offset);
-	index = ALIGN(sizeof(struct usb_cdc_ncm_nth16), ctx->tx_ndp_modulus);
-	ctx->tx_ncm.nth16.wNdpIndex = cpu_to_le16(index);
-
-	memcpy(skb_out->data, &(ctx->tx_ncm.nth16), sizeof(ctx->tx_ncm.nth16));
-	ctx->tx_seq++;
-
-	/* fill out 16-bit NDP table */
-	ctx->tx_ncm.ndp16.dwSignature =
-				cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN);
-	rem = sizeof(ctx->tx_ncm.ndp16) + ((ctx->tx_curr_frame_num + 1) *
-					sizeof(struct usb_cdc_ncm_dpe16));
-	ctx->tx_ncm.ndp16.wLength = cpu_to_le16(rem);
-	ctx->tx_ncm.ndp16.wNextNdpIndex = 0; /* reserved */
-
-	memcpy(((u8 *)skb_out->data) + index,
-						&(ctx->tx_ncm.ndp16),
-						sizeof(ctx->tx_ncm.ndp16));
+	/* do we need to prevent a ZLP? */
+	if (((skb_out->len % le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0) &&
+	    (skb_out->len < le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize)) && skb_tailroom(skb_out))
+		*skb_put(skb_out, 1) = 0;	/* force short packet */
 
-	memcpy(((u8 *)skb_out->data) + index + sizeof(ctx->tx_ncm.ndp16),
-					&(ctx->tx_ncm.dpe16),
-					(ctx->tx_curr_frame_num + 1) *
-					sizeof(struct usb_cdc_ncm_dpe16));
-
-	/* set frame length */
-	skb_put(skb_out, last_offset);
+	/* set final frame length */
+	nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
+	nth16->wBlockLength = cpu_to_le16(skb_out->len);
 
 	/* return skb */
 	ctx->tx_curr_skb = NULL;
@@ -888,6 +790,7 @@ exit_no_skb:
 		cdc_ncm_tx_timeout_start(ctx);
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(cdc_ncm_fill_tx_frame);
 
 static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx)
 {
@@ -922,6 +825,8 @@ static void cdc_ncm_txpath_bh(unsigned long param)
 		netif_tx_lock_bh(ctx->netdev);
 		usbnet_start_xmit(NULL, ctx->netdev);
 		netif_tx_unlock_bh(ctx->netdev);
+	} else {
+		spin_unlock_bh(&ctx->mtx);
 	}
 }
 
@@ -942,7 +847,7 @@ cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 		goto error;
 
 	spin_lock_bh(&ctx->mtx);
-	skb_out = cdc_ncm_fill_tx_frame(ctx, skb);
+	skb_out = cdc_ncm_fill_tx_frame(ctx, skb, cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN));
 	spin_unlock_bh(&ctx->mtx);
 	return skb_out;
 
@@ -953,17 +858,12 @@ error:
 	return NULL;
 }
 
-static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
+/* verify NTB header and return offset of first NDP, or negative error */
+int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in)
 {
-	struct sk_buff *skb;
-	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
-	int len;
-	int nframes;
-	int x;
-	int offset;
 	struct usb_cdc_ncm_nth16 *nth16;
-	struct usb_cdc_ncm_ndp16 *ndp16;
-	struct usb_cdc_ncm_dpe16 *dpe16;
+	int len;
+	int ret = -EINVAL;
 
 	if (ctx == NULL)
 		goto error;
@@ -997,20 +897,23 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
 	}
 	ctx->rx_seq = le16_to_cpu(nth16->wSequence);
 
-	len = le16_to_cpu(nth16->wNdpIndex);
-	if ((len + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) {
-		pr_debug("invalid DPT16 index <%u>\n",
-					le16_to_cpu(nth16->wNdpIndex));
-		goto error;
-	}
+	ret = le16_to_cpu(nth16->wNdpIndex);
+error:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_nth16);
 
-	ndp16 = (struct usb_cdc_ncm_ndp16 *)(((u8 *)skb_in->data) + len);
+/* verify NDP header and return number of datagrams, or negative error */
+int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset)
+{
+	struct usb_cdc_ncm_ndp16 *ndp16;
+	int ret = -EINVAL;
 
-	if (le32_to_cpu(ndp16->dwSignature) != USB_CDC_NCM_NDP16_NOCRC_SIGN) {
-		pr_debug("invalid DPT16 signature <%u>\n",
-					le32_to_cpu(ndp16->dwSignature));
+	if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) {
+		pr_debug("invalid NDP offset  <%u>\n", ndpoffset);
 		goto error;
 	}
+	ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
 
 	if (le16_to_cpu(ndp16->wLength) < USB_CDC_NCM_NDP16_LENGTH_MIN) {
 		pr_debug("invalid DPT16 length <%u>\n",
@@ -1018,20 +921,52 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
 		goto error;
 	}
 
-	nframes = ((le16_to_cpu(ndp16->wLength) -
+	ret = ((le16_to_cpu(ndp16->wLength) -
 					sizeof(struct usb_cdc_ncm_ndp16)) /
 					sizeof(struct usb_cdc_ncm_dpe16));
-	nframes--; /* we process NDP entries except for the last one */
-
-	len += sizeof(struct usb_cdc_ncm_ndp16);
+	ret--; /* we process NDP entries except for the last one */
 
-	if ((len + nframes * (sizeof(struct usb_cdc_ncm_dpe16))) >
+	if ((sizeof(struct usb_cdc_ncm_ndp16) + ret * (sizeof(struct usb_cdc_ncm_dpe16))) >
 								skb_in->len) {
-		pr_debug("Invalid nframes = %d\n", nframes);
-		goto error;
+		pr_debug("Invalid nframes = %d\n", ret);
+		ret = -EINVAL;
 	}
 
-	dpe16 = (struct usb_cdc_ncm_dpe16 *)(((u8 *)skb_in->data) + len);
+error:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_ndp16);
+
+static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
+{
+	struct sk_buff *skb;
+	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
+	int len;
+	int nframes;
+	int x;
+	int offset;
+	struct usb_cdc_ncm_ndp16 *ndp16;
+	struct usb_cdc_ncm_dpe16 *dpe16;
+	int ndpoffset;
+	int loopcount = 50; /* arbitrary max preventing infinite loop */
+
+	ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
+	if (ndpoffset < 0)
+		goto error;
+
+next_ndp:
+	nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
+	if (nframes < 0)
+		goto error;
+
+	ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
+
+	if (le32_to_cpu(ndp16->dwSignature) != USB_CDC_NCM_NDP16_NOCRC_SIGN) {
+		pr_debug("invalid DPT16 signature <%u>\n",
+			 le32_to_cpu(ndp16->dwSignature));
+		goto err_ndp;
+	}
+	dpe16 = ndp16->dpe16;
 
 	for (x = 0; x < nframes; x++, dpe16++) {
 		offset = le16_to_cpu(dpe16->wDatagramIndex);
@@ -1043,7 +978,7 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
 		 */
 		if ((offset == 0) || (len == 0)) {
 			if (!x)
-				goto error; /* empty NTB */
+				goto err_ndp; /* empty NTB */
 			break;
 		}
 
@@ -1054,7 +989,7 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
 					"offset[%u]=%u, length=%u, skb=%p\n",
 					x, offset, len, skb_in);
 			if (!x)
-				goto error;
+				goto err_ndp;
 			break;
 
 		} else {
@@ -1067,6 +1002,12 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
 			usbnet_skb_return(dev, skb);
 		}
 	}
+err_ndp:
+	/* are there more NDPs to process? */
+	ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
+	if (ndpoffset && loopcount--)
+		goto next_ndp;
+
 	return 1;
 error:
 	return 0;
@@ -1131,7 +1072,7 @@ static void cdc_ncm_status(struct usbnet *dev, struct urb *urb)
 		 * USB_CDC_NOTIFY_NETWORK_CONNECTION notification shall be
 		 * sent by device after USB_CDC_NOTIFY_SPEED_CHANGE.
 		 */
-		ctx->connected = event->wValue;
+		ctx->connected = le16_to_cpu(event->wValue);
 
 		printk(KERN_INFO KBUILD_MODNAME ": %s: network connection:"
 			" %sconnected\n",
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index e0433ce..3f554c1 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -56,27 +56,12 @@
 
 static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data)
 {
-	void *buf;
-	int err = -ENOMEM;
-
-	netdev_dbg(dev->net, "dm_read() reg=0x%02x length=%d\n", reg, length);
-
-	buf = kmalloc(length, GFP_KERNEL);
-	if (!buf)
-		goto out;
-
-	err = usb_control_msg(dev->udev,
-			      usb_rcvctrlpipe(dev->udev, 0),
-			      DM_READ_REGS,
-			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			      0, reg, buf, length, USB_CTRL_SET_TIMEOUT);
-	if (err == length)
-		memcpy(data, buf, length);
-	else if (err >= 0)
+	int err;
+	err = usbnet_read_cmd(dev, DM_READ_REGS,
+			       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			       0, reg, data, length);
+	if(err != length && err >= 0)
 		err = -EINVAL;
-	kfree(buf);
-
- out:
 	return err;
 }
 
@@ -87,91 +72,29 @@ static int dm_read_reg(struct usbnet *dev, u8 reg, u8 *value)
 
 static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data)
 {
-	void *buf = NULL;
-	int err = -ENOMEM;
-
-	netdev_dbg(dev->net, "dm_write() reg=0x%02x, length=%d\n", reg, length);
+	int err;
+	err = usbnet_write_cmd(dev, DM_WRITE_REGS,
+				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+				0, reg, data, length);
 
-	if (data) {
-		buf = kmemdup(data, length, GFP_KERNEL);
-		if (!buf)
-			goto out;
-	}
-
-	err = usb_control_msg(dev->udev,
-			      usb_sndctrlpipe(dev->udev, 0),
-			      DM_WRITE_REGS,
-			      USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE,
-			      0, reg, buf, length, USB_CTRL_SET_TIMEOUT);
-	kfree(buf);
 	if (err >= 0 && err < length)
 		err = -EINVAL;
- out:
 	return err;
 }
 
 static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value)
 {
-	netdev_dbg(dev->net, "dm_write_reg() reg=0x%02x, value=0x%02x\n",
-		   reg, value);
-	return usb_control_msg(dev->udev,
-			       usb_sndctrlpipe(dev->udev, 0),
-			       DM_WRITE_REG,
-			       USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE,
-			       value, reg, NULL, 0, USB_CTRL_SET_TIMEOUT);
-}
-
-static void dm_write_async_callback(struct urb *urb)
-{
-	struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
-	int status = urb->status;
-
-	if (status < 0)
-		printk(KERN_DEBUG "dm_write_async_callback() failed with %d\n",
-		       status);
-
-	kfree(req);
-	usb_free_urb(urb);
+	return usbnet_write_cmd(dev, DM_WRITE_REGS,
+				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+				value, reg, NULL, 0);
 }
 
 static void dm_write_async_helper(struct usbnet *dev, u8 reg, u8 value,
 				  u16 length, void *data)
 {
-	struct usb_ctrlrequest *req;
-	struct urb *urb;
-	int status;
-
-	urb = usb_alloc_urb(0, GFP_ATOMIC);
-	if (!urb) {
-		netdev_err(dev->net, "Error allocating URB in dm_write_async_helper!\n");
-		return;
-	}
-
-	req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
-	if (!req) {
-		netdev_err(dev->net, "Failed to allocate memory for control request\n");
-		usb_free_urb(urb);
-		return;
-	}
-
-	req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-	req->bRequest = length ? DM_WRITE_REGS : DM_WRITE_REG;
-	req->wValue = cpu_to_le16(value);
-	req->wIndex = cpu_to_le16(reg);
-	req->wLength = cpu_to_le16(length);
-
-	usb_fill_control_urb(urb, dev->udev,
-			     usb_sndctrlpipe(dev->udev, 0),
-			     (void *)req, data, length,
-			     dm_write_async_callback, req);
-
-	status = usb_submit_urb(urb, GFP_ATOMIC);
-	if (status < 0) {
-		netdev_err(dev->net, "Error submitting the control message: status=%d\n",
-			   status);
-		kfree(req);
-		usb_free_urb(urb);
-	}
+	usbnet_write_cmd_async(dev, DM_WRITE_REGS,
+			       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			       value, reg, data, length);
 }
 
 static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 605a4ba..cd8ccb2 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -2274,6 +2274,7 @@ static void hso_serial_common_free(struct hso_serial *serial)
 	/* unlink and free TX URB */
 	usb_free_urb(serial->tx_urb);
 	kfree(serial->tx_data);
+	tty_port_destroy(&serial->port);
 }
 
 static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,
@@ -2283,12 +2284,12 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,
 	int minor;
 	int i;
 
+	tty_port_init(&serial->port);
+
 	minor = get_free_serial_index();
 	if (minor < 0)
 		goto exit;
 
-	tty_port_init(&serial->port);
-
 	/* register our minor number */
 	serial->parent->dev = tty_port_register_device(&serial->port, tty_drv,
 			minor, &serial->parent->interface->dev);
diff --git a/drivers/net/usb/int51x1.c b/drivers/net/usb/int51x1.c
index 8de6417..ace9e74 100644
--- a/drivers/net/usb/int51x1.c
+++ b/drivers/net/usb/int51x1.c
@@ -116,23 +116,8 @@ static struct sk_buff *int51x1_tx_fixup(struct usbnet *dev,
 	return skb;
 }
 
-static void int51x1_async_cmd_callback(struct urb *urb)
-{
-	struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
-	int status = urb->status;
-
-	if (status < 0)
-		dev_warn(&urb->dev->dev, "async callback failed with %d\n", status);
-
-	kfree(req);
-	usb_free_urb(urb);
-}
-
 static void int51x1_set_multicast(struct net_device *netdev)
 {
-	struct usb_ctrlrequest *req;
-	int status;
-	struct urb *urb;
 	struct usbnet *dev = netdev_priv(netdev);
 	u16 filter = PACKET_TYPE_DIRECTED | PACKET_TYPE_BROADCAST;
 
@@ -149,40 +134,9 @@ static void int51x1_set_multicast(struct net_device *netdev)
 		netdev_dbg(dev->net, "receive own packets only\n");
 	}
 
-	urb = usb_alloc_urb(0, GFP_ATOMIC);
-	if (!urb) {
-		netdev_warn(dev->net, "Error allocating URB\n");
-		return;
-	}
-
-	req = kmalloc(sizeof(*req), GFP_ATOMIC);
-	if (!req) {
-		netdev_warn(dev->net, "Error allocating control msg\n");
-		goto out;
-	}
-
-	req->bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-	req->bRequest = SET_ETHERNET_PACKET_FILTER;
-	req->wValue = cpu_to_le16(filter);
-	req->wIndex = 0;
-	req->wLength = 0;
-
-	usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0),
-		(void *)req, NULL, 0,
-		int51x1_async_cmd_callback,
-		(void *)req);
-
-	status = usb_submit_urb(urb, GFP_ATOMIC);
-	if (status < 0) {
-		netdev_warn(dev->net, "Error submitting control msg, sts=%d\n",
-			    status);
-		goto out1;
-	}
-	return;
-out1:
-	kfree(req);
-out:
-	usb_free_urb(urb);
+	usbnet_write_cmd_async(dev, SET_ETHERNET_PACKET_FILTER,
+			       USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+			       filter, 0, NULL, 0);
 }
 
 static const struct net_device_ops int51x1_netdev_ops = {
diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c
index cc7e720..3f3f566 100644
--- a/drivers/net/usb/mcs7830.c
+++ b/drivers/net/usb/mcs7830.c
@@ -124,93 +124,20 @@ static const char driver_name[] = "MOSCHIP usb-ethernet driver";
 
 static int mcs7830_get_reg(struct usbnet *dev, u16 index, u16 size, void *data)
 {
-	struct usb_device *xdev = dev->udev;
-	int ret;
-	void *buffer;
-
-	buffer = kmalloc(size, GFP_NOIO);
-	if (buffer == NULL)
-		return -ENOMEM;
-
-	ret = usb_control_msg(xdev, usb_rcvctrlpipe(xdev, 0), MCS7830_RD_BREQ,
-			      MCS7830_RD_BMREQ, 0x0000, index, buffer,
-			      size, MCS7830_CTRL_TIMEOUT);
-	memcpy(data, buffer, size);
-	kfree(buffer);
-
-	return ret;
+	return usbnet_read_cmd(dev, MCS7830_RD_BREQ, MCS7830_RD_BMREQ,
+				0x0000, index, data, size);
 }
 
 static int mcs7830_set_reg(struct usbnet *dev, u16 index, u16 size, const void *data)
 {
-	struct usb_device *xdev = dev->udev;
-	int ret;
-	void *buffer;
-
-	buffer = kmemdup(data, size, GFP_NOIO);
-	if (buffer == NULL)
-		return -ENOMEM;
-
-	ret = usb_control_msg(xdev, usb_sndctrlpipe(xdev, 0), MCS7830_WR_BREQ,
-			      MCS7830_WR_BMREQ, 0x0000, index, buffer,
-			      size, MCS7830_CTRL_TIMEOUT);
-	kfree(buffer);
-	return ret;
-}
-
-static void mcs7830_async_cmd_callback(struct urb *urb)
-{
-	struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
-	int status = urb->status;
-
-	if (status < 0)
-		printk(KERN_DEBUG "%s() failed with %d\n",
-		       __func__, status);
-
-	kfree(req);
-	usb_free_urb(urb);
+	return usbnet_write_cmd(dev, MCS7830_WR_BREQ, MCS7830_WR_BMREQ,
+				0x0000, index, data, size);
 }
 
 static void mcs7830_set_reg_async(struct usbnet *dev, u16 index, u16 size, void *data)
 {
-	struct usb_ctrlrequest *req;
-	int ret;
-	struct urb *urb;
-
-	urb = usb_alloc_urb(0, GFP_ATOMIC);
-	if (!urb) {
-		dev_dbg(&dev->udev->dev,
-			"Error allocating URB in write_cmd_async!\n");
-		return;
-	}
-
-	req = kmalloc(sizeof *req, GFP_ATOMIC);
-	if (!req) {
-		dev_err(&dev->udev->dev,
-			"Failed to allocate memory for control request\n");
-		goto out;
-	}
-	req->bRequestType = MCS7830_WR_BMREQ;
-	req->bRequest = MCS7830_WR_BREQ;
-	req->wValue = 0;
-	req->wIndex = cpu_to_le16(index);
-	req->wLength = cpu_to_le16(size);
-
-	usb_fill_control_urb(urb, dev->udev,
-			     usb_sndctrlpipe(dev->udev, 0),
-			     (void *)req, data, size,
-			     mcs7830_async_cmd_callback, req);
-
-	ret = usb_submit_urb(urb, GFP_ATOMIC);
-	if (ret < 0) {
-		dev_err(&dev->udev->dev,
-			"Error submitting the control message: ret=%d\n", ret);
-		goto out;
-	}
-	return;
-out:
-	kfree(req);
-	usb_free_urb(urb);
+	usbnet_write_cmd_async(dev, MCS7830_WR_BREQ, MCS7830_WR_BMREQ,
+				0x0000, index, data, size);
 }
 
 static int mcs7830_hif_get_mac_address(struct usbnet *dev, unsigned char *addr)
diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c
index c062a3e..93e0716 100644
--- a/drivers/net/usb/net1080.c
+++ b/drivers/net/usb/net1080.c
@@ -109,13 +109,11 @@ struct nc_trailer {
 static int
 nc_vendor_read(struct usbnet *dev, u8 req, u8 regnum, u16 *retval_ptr)
 {
-	int status = usb_control_msg(dev->udev,
-		usb_rcvctrlpipe(dev->udev, 0),
-		req,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		0, regnum,
-		retval_ptr, sizeof *retval_ptr,
-		USB_CTRL_GET_TIMEOUT);
+	int status = usbnet_read_cmd(dev, req,
+				     USB_DIR_IN | USB_TYPE_VENDOR |
+				     USB_RECIP_DEVICE,
+				     0, regnum, retval_ptr,
+				     sizeof *retval_ptr);
 	if (status > 0)
 		status = 0;
 	if (!status)
@@ -133,13 +131,9 @@ nc_register_read(struct usbnet *dev, u8 regnum, u16 *retval_ptr)
 static void
 nc_vendor_write(struct usbnet *dev, u8 req, u8 regnum, u16 value)
 {
-	usb_control_msg(dev->udev,
-		usb_sndctrlpipe(dev->udev, 0),
-		req,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		value, regnum,
-		NULL, 0,			// data is in setup packet
-		USB_CTRL_SET_TIMEOUT);
+	usbnet_write_cmd(dev, req,
+			 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			 value, regnum, NULL, 0);
 }
 
 static inline void
@@ -288,37 +282,34 @@ static inline void nc_dump_ttl(struct usbnet *dev, u16 ttl)
 static int net1080_reset(struct usbnet *dev)
 {
 	u16		usbctl, status, ttl;
-	u16		*vp = kmalloc(sizeof (u16), GFP_KERNEL);
+	u16		vp;
 	int		retval;
 
-	if (!vp)
-		return -ENOMEM;
-
 	// nc_dump_registers(dev);
 
-	if ((retval = nc_register_read(dev, REG_STATUS, vp)) < 0) {
+	if ((retval = nc_register_read(dev, REG_STATUS, &vp)) < 0) {
 		netdev_dbg(dev->net, "can't read %s-%s status: %d\n",
 			   dev->udev->bus->bus_name, dev->udev->devpath, retval);
 		goto done;
 	}
-	status = *vp;
+	status = vp;
 	nc_dump_status(dev, status);
 
-	if ((retval = nc_register_read(dev, REG_USBCTL, vp)) < 0) {
+	if ((retval = nc_register_read(dev, REG_USBCTL, &vp)) < 0) {
 		netdev_dbg(dev->net, "can't read USBCTL, %d\n", retval);
 		goto done;
 	}
-	usbctl = *vp;
+	usbctl = vp;
 	nc_dump_usbctl(dev, usbctl);
 
 	nc_register_write(dev, REG_USBCTL,
 			USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER);
 
-	if ((retval = nc_register_read(dev, REG_TTL, vp)) < 0) {
+	if ((retval = nc_register_read(dev, REG_TTL, &vp)) < 0) {
 		netdev_dbg(dev->net, "can't read TTL, %d\n", retval);
 		goto done;
 	}
-	ttl = *vp;
+	ttl = vp;
 	// nc_dump_ttl(dev, ttl);
 
 	nc_register_write(dev, REG_TTL,
@@ -331,7 +322,6 @@ static int net1080_reset(struct usbnet *dev)
 	retval = 0;
 
 done:
-	kfree(vp);
 	return retval;
 }
 
@@ -339,13 +329,10 @@ static int net1080_check_connect(struct usbnet *dev)
 {
 	int			retval;
 	u16			status;
-	u16			*vp = kmalloc(sizeof (u16), GFP_KERNEL);
+	u16			vp;
 
-	if (!vp)
-		return -ENOMEM;
-	retval = nc_register_read(dev, REG_STATUS, vp);
-	status = *vp;
-	kfree(vp);
+	retval = nc_register_read(dev, REG_STATUS, &vp);
+	status = vp;
 	if (retval != 0) {
 		netdev_dbg(dev->net, "net1080_check_conn read - %d\n", retval);
 		return retval;
@@ -355,59 +342,22 @@ static int net1080_check_connect(struct usbnet *dev)
 	return 0;
 }
 
-static void nc_flush_complete(struct urb *urb)
-{
-	kfree(urb->context);
-	usb_free_urb(urb);
-}
-
 static void nc_ensure_sync(struct usbnet *dev)
 {
-	dev->frame_errors++;
-	if (dev->frame_errors > 5) {
-		struct urb		*urb;
-		struct usb_ctrlrequest	*req;
-		int			status;
-
-		/* Send a flush */
-		urb = usb_alloc_urb(0, GFP_ATOMIC);
-		if (!urb)
-			return;
-
-		req = kmalloc(sizeof *req, GFP_ATOMIC);
-		if (!req) {
-			usb_free_urb(urb);
-			return;
-		}
+	if (++dev->frame_errors <= 5)
+		return;
 
-		req->bRequestType = USB_DIR_OUT
-			| USB_TYPE_VENDOR
-			| USB_RECIP_DEVICE;
-		req->bRequest = REQUEST_REGISTER;
-		req->wValue = cpu_to_le16(USBCTL_FLUSH_THIS
-				| USBCTL_FLUSH_OTHER);
-		req->wIndex = cpu_to_le16(REG_USBCTL);
-		req->wLength = cpu_to_le16(0);
-
-		/* queue an async control request, we don't need
-		 * to do anything when it finishes except clean up.
-		 */
-		usb_fill_control_urb(urb, dev->udev,
-			usb_sndctrlpipe(dev->udev, 0),
-			(unsigned char *) req,
-			NULL, 0,
-			nc_flush_complete, req);
-		status = usb_submit_urb(urb, GFP_ATOMIC);
-		if (status) {
-			kfree(req);
-			usb_free_urb(urb);
-			return;
-		}
+	if (usbnet_write_cmd_async(dev, REQUEST_REGISTER,
+					USB_DIR_OUT | USB_TYPE_VENDOR |
+					USB_RECIP_DEVICE,
+					USBCTL_FLUSH_THIS |
+					USBCTL_FLUSH_OTHER,
+					REG_USBCTL, NULL, 0))
+		return;
 
-		netif_dbg(dev, rx_err, dev->net,
-			  "flush net1080; too many framing errors\n");
-		dev->frame_errors = 0;
-	}
+	netif_dbg(dev, rx_err, dev->net,
+		  "flush net1080; too many framing errors\n");
+	dev->frame_errors = 0;
 }
 
 static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c
index 4584b9a..0fcc8e6 100644
--- a/drivers/net/usb/plusb.c
+++ b/drivers/net/usb/plusb.c
@@ -71,13 +71,10 @@
 static inline int
 pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index)
 {
-	return usb_control_msg(dev->udev,
-		usb_rcvctrlpipe(dev->udev, 0),
-		req,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		val, index,
-		NULL, 0,
-		USB_CTRL_GET_TIMEOUT);
+	return usbnet_read_cmd(dev, req,
+				USB_DIR_IN | USB_TYPE_VENDOR |
+				USB_RECIP_DEVICE,
+				val, index, NULL, 0);
 }
 
 static inline int
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 3b566fa..1ea91f4 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -385,6 +385,7 @@ static const struct usb_device_id products[] = {
 	},
 
 	/* 3. Combined interface devices matching on interface number */
+	{QMI_FIXED_INTF(0x12d1, 0x140c, 1)},	/* Huawei E173 */
 	{QMI_FIXED_INTF(0x19d2, 0x0002, 1)},
 	{QMI_FIXED_INTF(0x19d2, 0x0012, 1)},
 	{QMI_FIXED_INTF(0x19d2, 0x0017, 3)},
diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c
index c27d277..18dd425 100644
--- a/drivers/net/usb/sierra_net.c
+++ b/drivers/net/usb/sierra_net.c
@@ -311,10 +311,9 @@ static int sierra_net_send_cmd(struct usbnet *dev,
 	struct sierra_net_data *priv = sierra_net_get_private(dev);
 	int  status;
 
-	status = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-			USB_CDC_SEND_ENCAPSULATED_COMMAND,
-			USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE,	0,
-			priv->ifnum, cmd, cmdlen, USB_CTRL_SET_TIMEOUT);
+	status = usbnet_write_cmd(dev, USB_CDC_SEND_ENCAPSULATED_COMMAND,
+				  USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE,
+				  0, priv->ifnum, cmd, cmdlen);
 
 	if (status != cmdlen && status != -ENODEV)
 		netdev_err(dev->net, "Submit %s failed %d\n", cmd_name, status);
@@ -340,7 +339,7 @@ static void sierra_net_set_ctx_index(struct sierra_net_data *priv, u8 ctx_ix)
 	dev_dbg(&(priv->usbnet->udev->dev), "%s %d", __func__, ctx_ix);
 	priv->tx_hdr_template[0] = 0x3F;
 	priv->tx_hdr_template[1] = ctx_ix;
-	*((u16 *)&priv->tx_hdr_template[2]) =
+	*((__be16 *)&priv->tx_hdr_template[2]) =
 		cpu_to_be16(SIERRA_NET_HIP_EXT_IP_OUT_ID);
 }
 
@@ -632,32 +631,22 @@ static int sierra_net_change_mtu(struct net_device *net, int new_mtu)
 static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap)
 {
 	int result = 0;
-	u16 *attrdata;
-
-	attrdata = kmalloc(sizeof(*attrdata), GFP_KERNEL);
-	if (!attrdata)
-		return -ENOMEM;
-
-	result = usb_control_msg(
-			dev->udev,
-			usb_rcvctrlpipe(dev->udev, 0),
-			/* _u8 vendor specific request */
-			SWI_USB_REQUEST_GET_FW_ATTR,
-			USB_DIR_IN | USB_TYPE_VENDOR,	/* __u8 request type */
-			0x0000,		/* __u16 value not used */
-			0x0000,		/* __u16 index  not used */
-			attrdata,	/* char *data */
-			sizeof(*attrdata),		/* __u16 size */
-			USB_CTRL_SET_TIMEOUT);	/* int timeout */
-
-	if (result < 0) {
-		kfree(attrdata);
+	__le16 attrdata;
+
+	result = usbnet_read_cmd(dev,
+				/* _u8 vendor specific request */
+				SWI_USB_REQUEST_GET_FW_ATTR,
+				USB_DIR_IN | USB_TYPE_VENDOR,	/* __u8 request type */
+				0x0000,		/* __u16 value not used */
+				0x0000,		/* __u16 index  not used */
+				&attrdata,	/* char *data */
+				sizeof(attrdata)	/* __u16 size */
+				);
+
+	if (result < 0)
 		return -EIO;
-	}
-
-	*datap = le16_to_cpu(*attrdata);
 
-	kfree(attrdata);
+	*datap = le16_to_cpu(attrdata);
 	return result;
 }
 
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index b77ae76..1823806 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -26,6 +26,8 @@
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
+#include <linux/bitrev.h>
+#include <linux/crc16.h>
 #include <linux/crc32.h>
 #include <linux/usb/usbnet.h>
 #include <linux/slab.h>
@@ -52,7 +54,15 @@
 #define USB_PRODUCT_ID_LAN7500		(0x7500)
 #define USB_PRODUCT_ID_LAN7505		(0x7505)
 #define RXW_PADDING			2
-#define SUPPORTED_WAKE			(WAKE_MAGIC)
+#define SUPPORTED_WAKE			(WAKE_PHY | WAKE_UCAST | WAKE_BCAST | \
+					 WAKE_MCAST | WAKE_ARP | WAKE_MAGIC)
+
+#define SUSPEND_SUSPEND0		(0x01)
+#define SUSPEND_SUSPEND1		(0x02)
+#define SUSPEND_SUSPEND2		(0x04)
+#define SUSPEND_SUSPEND3		(0x08)
+#define SUSPEND_ALLMODES		(SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
+					 SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3)
 
 #define check_warn(ret, fmt, args...) \
 	({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
@@ -71,6 +81,7 @@ struct smsc75xx_priv {
 	struct mutex dataport_mutex;
 	spinlock_t rfe_ctl_lock;
 	struct work_struct set_multicast;
+	u8 suspend_flags;
 };
 
 struct usb_context {
@@ -82,96 +93,96 @@ static bool turbo_mode = true;
 module_param(turbo_mode, bool, 0644);
 MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
 
-static int __must_check smsc75xx_read_reg(struct usbnet *dev, u32 index,
-					  u32 *data)
+static int __must_check __smsc75xx_read_reg(struct usbnet *dev, u32 index,
+					    u32 *data, int in_pm)
 {
-	u32 *buf = kmalloc(4, GFP_KERNEL);
+	u32 buf;
 	int ret;
+	int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
 
 	BUG_ON(!dev);
 
-	if (!buf)
-		return -ENOMEM;
-
-	ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
-		USB_VENDOR_REQUEST_READ_REGISTER,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		00, index, buf, 4, USB_CTRL_GET_TIMEOUT);
+	if (!in_pm)
+		fn = usbnet_read_cmd;
+	else
+		fn = usbnet_read_cmd_nopm;
 
+	ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN
+		 | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		 0, index, &buf, 4);
 	if (unlikely(ret < 0))
-		netdev_warn(dev->net,
-			"Failed to read reg index 0x%08x: %d", index, ret);
+		netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n",
+			    index, ret);
 
-	le32_to_cpus(buf);
-	*data = *buf;
-	kfree(buf);
+	le32_to_cpus(&buf);
+	*data = buf;
 
 	return ret;
 }
 
-static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index,
-					   u32 data)
+static int __must_check __smsc75xx_write_reg(struct usbnet *dev, u32 index,
+					     u32 data, int in_pm)
 {
-	u32 *buf = kmalloc(4, GFP_KERNEL);
+	u32 buf;
 	int ret;
+	int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16);
 
 	BUG_ON(!dev);
 
-	if (!buf)
-		return -ENOMEM;
-
-	*buf = data;
-	cpu_to_le32s(buf);
+	if (!in_pm)
+		fn = usbnet_write_cmd;
+	else
+		fn = usbnet_write_cmd_nopm;
 
-	ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-		USB_VENDOR_REQUEST_WRITE_REGISTER,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		00, index, buf, 4, USB_CTRL_SET_TIMEOUT);
+	buf = data;
+	cpu_to_le32s(&buf);
 
+	ret = fn(dev, USB_VENDOR_REQUEST_WRITE_REGISTER, USB_DIR_OUT
+		 | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		 0, index, &buf, 4);
 	if (unlikely(ret < 0))
-		netdev_warn(dev->net,
-			"Failed to write reg index 0x%08x: %d", index, ret);
-
-	kfree(buf);
+		netdev_warn(dev->net, "Failed to write reg index 0x%08x: %d\n",
+			    index, ret);
 
 	return ret;
 }
 
-static int smsc75xx_set_feature(struct usbnet *dev, u32 feature)
+static int __must_check smsc75xx_read_reg_nopm(struct usbnet *dev, u32 index,
+					       u32 *data)
 {
-	if (WARN_ON_ONCE(!dev))
-		return -EINVAL;
-
-	cpu_to_le32s(&feature);
-
-	return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-		USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
-		USB_CTRL_SET_TIMEOUT);
+	return __smsc75xx_read_reg(dev, index, data, 1);
 }
 
-static int smsc75xx_clear_feature(struct usbnet *dev, u32 feature)
+static int __must_check smsc75xx_write_reg_nopm(struct usbnet *dev, u32 index,
+						u32 data)
 {
-	if (WARN_ON_ONCE(!dev))
-		return -EINVAL;
+	return __smsc75xx_write_reg(dev, index, data, 1);
+}
 
-	cpu_to_le32s(&feature);
+static int __must_check smsc75xx_read_reg(struct usbnet *dev, u32 index,
+					  u32 *data)
+{
+	return __smsc75xx_read_reg(dev, index, data, 0);
+}
 
-	return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-		USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
-		USB_CTRL_SET_TIMEOUT);
+static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index,
+					   u32 data)
+{
+	return __smsc75xx_write_reg(dev, index, data, 0);
 }
 
 /* Loop until the read is completed with timeout
  * called with phy_mutex held */
-static int smsc75xx_phy_wait_not_busy(struct usbnet *dev)
+static __must_check int __smsc75xx_phy_wait_not_busy(struct usbnet *dev,
+						     int in_pm)
 {
 	unsigned long start_time = jiffies;
 	u32 val;
 	int ret;
 
 	do {
-		ret = smsc75xx_read_reg(dev, MII_ACCESS, &val);
-		check_warn_return(ret, "Error reading MII_ACCESS");
+		ret = __smsc75xx_read_reg(dev, MII_ACCESS, &val, in_pm);
+		check_warn_return(ret, "Error reading MII_ACCESS\n");
 
 		if (!(val & MII_ACCESS_BUSY))
 			return 0;
@@ -180,7 +191,8 @@ static int smsc75xx_phy_wait_not_busy(struct usbnet *dev)
 	return -EIO;
 }
 
-static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
+static int __smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx,
+				int in_pm)
 {
 	struct usbnet *dev = netdev_priv(netdev);
 	u32 val, addr;
@@ -189,8 +201,8 @@ static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
 	mutex_lock(&dev->phy_mutex);
 
 	/* confirm MII not busy */
-	ret = smsc75xx_phy_wait_not_busy(dev);
-	check_warn_goto_done(ret, "MII is busy in smsc75xx_mdio_read");
+	ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
+	check_warn_goto_done(ret, "MII is busy in smsc75xx_mdio_read\n");
 
 	/* set the address, index & direction (read from PHY) */
 	phy_id &= dev->mii.phy_id_mask;
@@ -198,14 +210,14 @@ static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
 	addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
 		| ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
 		| MII_ACCESS_READ | MII_ACCESS_BUSY;
-	ret = smsc75xx_write_reg(dev, MII_ACCESS, addr);
-	check_warn_goto_done(ret, "Error writing MII_ACCESS");
+	ret = __smsc75xx_write_reg(dev, MII_ACCESS, addr, in_pm);
+	check_warn_goto_done(ret, "Error writing MII_ACCESS\n");
 
-	ret = smsc75xx_phy_wait_not_busy(dev);
-	check_warn_goto_done(ret, "Timed out reading MII reg %02X", idx);
+	ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
+	check_warn_goto_done(ret, "Timed out reading MII reg %02X\n", idx);
 
-	ret = smsc75xx_read_reg(dev, MII_DATA, &val);
-	check_warn_goto_done(ret, "Error reading MII_DATA");
+	ret = __smsc75xx_read_reg(dev, MII_DATA, &val, in_pm);
+	check_warn_goto_done(ret, "Error reading MII_DATA\n");
 
 	ret = (u16)(val & 0xFFFF);
 
@@ -214,8 +226,8 @@ done:
 	return ret;
 }
 
-static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
-				int regval)
+static void __smsc75xx_mdio_write(struct net_device *netdev, int phy_id,
+				  int idx, int regval, int in_pm)
 {
 	struct usbnet *dev = netdev_priv(netdev);
 	u32 val, addr;
@@ -224,12 +236,12 @@ static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
 	mutex_lock(&dev->phy_mutex);
 
 	/* confirm MII not busy */
-	ret = smsc75xx_phy_wait_not_busy(dev);
-	check_warn_goto_done(ret, "MII is busy in smsc75xx_mdio_write");
+	ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
+	check_warn_goto_done(ret, "MII is busy in smsc75xx_mdio_write\n");
 
 	val = regval;
-	ret = smsc75xx_write_reg(dev, MII_DATA, val);
-	check_warn_goto_done(ret, "Error writing MII_DATA");
+	ret = __smsc75xx_write_reg(dev, MII_DATA, val, in_pm);
+	check_warn_goto_done(ret, "Error writing MII_DATA\n");
 
 	/* set the address, index & direction (write to PHY) */
 	phy_id &= dev->mii.phy_id_mask;
@@ -237,16 +249,39 @@ static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
 	addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
 		| ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
 		| MII_ACCESS_WRITE | MII_ACCESS_BUSY;
-	ret = smsc75xx_write_reg(dev, MII_ACCESS, addr);
-	check_warn_goto_done(ret, "Error writing MII_ACCESS");
+	ret = __smsc75xx_write_reg(dev, MII_ACCESS, addr, in_pm);
+	check_warn_goto_done(ret, "Error writing MII_ACCESS\n");
 
-	ret = smsc75xx_phy_wait_not_busy(dev);
-	check_warn_goto_done(ret, "Timed out writing MII reg %02X", idx);
+	ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
+	check_warn_goto_done(ret, "Timed out writing MII reg %02X\n", idx);
 
 done:
 	mutex_unlock(&dev->phy_mutex);
 }
 
+static int smsc75xx_mdio_read_nopm(struct net_device *netdev, int phy_id,
+				   int idx)
+{
+	return __smsc75xx_mdio_read(netdev, phy_id, idx, 1);
+}
+
+static void smsc75xx_mdio_write_nopm(struct net_device *netdev, int phy_id,
+				     int idx, int regval)
+{
+	__smsc75xx_mdio_write(netdev, phy_id, idx, regval, 1);
+}
+
+static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
+{
+	return __smsc75xx_mdio_read(netdev, phy_id, idx, 0);
+}
+
+static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
+				int regval)
+{
+	__smsc75xx_mdio_write(netdev, phy_id, idx, regval, 0);
+}
+
 static int smsc75xx_wait_eeprom(struct usbnet *dev)
 {
 	unsigned long start_time = jiffies;
@@ -255,7 +290,7 @@ static int smsc75xx_wait_eeprom(struct usbnet *dev)
 
 	do {
 		ret = smsc75xx_read_reg(dev, E2P_CMD, &val);
-		check_warn_return(ret, "Error reading E2P_CMD");
+		check_warn_return(ret, "Error reading E2P_CMD\n");
 
 		if (!(val & E2P_CMD_BUSY) || (val & E2P_CMD_TIMEOUT))
 			break;
@@ -263,7 +298,7 @@ static int smsc75xx_wait_eeprom(struct usbnet *dev)
 	} while (!time_after(jiffies, start_time + HZ));
 
 	if (val & (E2P_CMD_TIMEOUT | E2P_CMD_BUSY)) {
-		netdev_warn(dev->net, "EEPROM read operation timeout");
+		netdev_warn(dev->net, "EEPROM read operation timeout\n");
 		return -EIO;
 	}
 
@@ -278,7 +313,7 @@ static int smsc75xx_eeprom_confirm_not_busy(struct usbnet *dev)
 
 	do {
 		ret = smsc75xx_read_reg(dev, E2P_CMD, &val);
-		check_warn_return(ret, "Error reading E2P_CMD");
+		check_warn_return(ret, "Error reading E2P_CMD\n");
 
 		if (!(val & E2P_CMD_BUSY))
 			return 0;
@@ -286,7 +321,7 @@ static int smsc75xx_eeprom_confirm_not_busy(struct usbnet *dev)
 		udelay(40);
 	} while (!time_after(jiffies, start_time + HZ));
 
-	netdev_warn(dev->net, "EEPROM is busy");
+	netdev_warn(dev->net, "EEPROM is busy\n");
 	return -EIO;
 }
 
@@ -306,14 +341,14 @@ static int smsc75xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length,
 	for (i = 0; i < length; i++) {
 		val = E2P_CMD_BUSY | E2P_CMD_READ | (offset & E2P_CMD_ADDR);
 		ret = smsc75xx_write_reg(dev, E2P_CMD, val);
-		check_warn_return(ret, "Error writing E2P_CMD");
+		check_warn_return(ret, "Error writing E2P_CMD\n");
 
 		ret = smsc75xx_wait_eeprom(dev);
 		if (ret < 0)
 			return ret;
 
 		ret = smsc75xx_read_reg(dev, E2P_DATA, &val);
-		check_warn_return(ret, "Error reading E2P_DATA");
+		check_warn_return(ret, "Error reading E2P_DATA\n");
 
 		data[i] = val & 0xFF;
 		offset++;
@@ -338,7 +373,7 @@ static int smsc75xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
 	/* Issue write/erase enable command */
 	val = E2P_CMD_BUSY | E2P_CMD_EWEN;
 	ret = smsc75xx_write_reg(dev, E2P_CMD, val);
-	check_warn_return(ret, "Error writing E2P_CMD");
+	check_warn_return(ret, "Error writing E2P_CMD\n");
 
 	ret = smsc75xx_wait_eeprom(dev);
 	if (ret < 0)
@@ -349,12 +384,12 @@ static int smsc75xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
 		/* Fill data register */
 		val = data[i];
 		ret = smsc75xx_write_reg(dev, E2P_DATA, val);
-		check_warn_return(ret, "Error writing E2P_DATA");
+		check_warn_return(ret, "Error writing E2P_DATA\n");
 
 		/* Send "write" command */
 		val = E2P_CMD_BUSY | E2P_CMD_WRITE | (offset & E2P_CMD_ADDR);
 		ret = smsc75xx_write_reg(dev, E2P_CMD, val);
-		check_warn_return(ret, "Error writing E2P_CMD");
+		check_warn_return(ret, "Error writing E2P_CMD\n");
 
 		ret = smsc75xx_wait_eeprom(dev);
 		if (ret < 0)
@@ -373,7 +408,7 @@ static int smsc75xx_dataport_wait_not_busy(struct usbnet *dev)
 	for (i = 0; i < 100; i++) {
 		u32 dp_sel;
 		ret = smsc75xx_read_reg(dev, DP_SEL, &dp_sel);
-		check_warn_return(ret, "Error reading DP_SEL");
+		check_warn_return(ret, "Error reading DP_SEL\n");
 
 		if (dp_sel & DP_SEL_DPRDY)
 			return 0;
@@ -381,7 +416,7 @@ static int smsc75xx_dataport_wait_not_busy(struct usbnet *dev)
 		udelay(40);
 	}
 
-	netdev_warn(dev->net, "smsc75xx_dataport_wait_not_busy timed out");
+	netdev_warn(dev->net, "smsc75xx_dataport_wait_not_busy timed out\n");
 
 	return -EIO;
 }
@@ -396,28 +431,28 @@ static int smsc75xx_dataport_write(struct usbnet *dev, u32 ram_select, u32 addr,
 	mutex_lock(&pdata->dataport_mutex);
 
 	ret = smsc75xx_dataport_wait_not_busy(dev);
-	check_warn_goto_done(ret, "smsc75xx_dataport_write busy on entry");
+	check_warn_goto_done(ret, "smsc75xx_dataport_write busy on entry\n");
 
 	ret = smsc75xx_read_reg(dev, DP_SEL, &dp_sel);
-	check_warn_goto_done(ret, "Error reading DP_SEL");
+	check_warn_goto_done(ret, "Error reading DP_SEL\n");
 
 	dp_sel &= ~DP_SEL_RSEL;
 	dp_sel |= ram_select;
 	ret = smsc75xx_write_reg(dev, DP_SEL, dp_sel);
-	check_warn_goto_done(ret, "Error writing DP_SEL");
+	check_warn_goto_done(ret, "Error writing DP_SEL\n");
 
 	for (i = 0; i < length; i++) {
 		ret = smsc75xx_write_reg(dev, DP_ADDR, addr + i);
-		check_warn_goto_done(ret, "Error writing DP_ADDR");
+		check_warn_goto_done(ret, "Error writing DP_ADDR\n");
 
 		ret = smsc75xx_write_reg(dev, DP_DATA, buf[i]);
-		check_warn_goto_done(ret, "Error writing DP_DATA");
+		check_warn_goto_done(ret, "Error writing DP_DATA\n");
 
 		ret = smsc75xx_write_reg(dev, DP_CMD, DP_CMD_WRITE);
-		check_warn_goto_done(ret, "Error writing DP_CMD");
+		check_warn_goto_done(ret, "Error writing DP_CMD\n");
 
 		ret = smsc75xx_dataport_wait_not_busy(dev);
-		check_warn_goto_done(ret, "smsc75xx_dataport_write timeout");
+		check_warn_goto_done(ret, "smsc75xx_dataport_write timeout\n");
 	}
 
 done:
@@ -438,14 +473,14 @@ static void smsc75xx_deferred_multicast_write(struct work_struct *param)
 	struct usbnet *dev = pdata->dev;
 	int ret;
 
-	netif_dbg(dev, drv, dev->net, "deferred multicast write 0x%08x",
-		pdata->rfe_ctl);
+	netif_dbg(dev, drv, dev->net, "deferred multicast write 0x%08x\n",
+		  pdata->rfe_ctl);
 
 	smsc75xx_dataport_write(dev, DP_SEL_VHF, DP_SEL_VHF_VLAN_LEN,
 		DP_SEL_VHF_HASH_LEN, pdata->multicast_hash_table);
 
 	ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
-	check_warn(ret, "Error writing RFE_CRL");
+	check_warn(ret, "Error writing RFE_CRL\n");
 }
 
 static void smsc75xx_set_multicast(struct net_device *netdev)
@@ -465,15 +500,15 @@ static void smsc75xx_set_multicast(struct net_device *netdev)
 		pdata->multicast_hash_table[i] = 0;
 
 	if (dev->net->flags & IFF_PROMISC) {
-		netif_dbg(dev, drv, dev->net, "promiscuous mode enabled");
+		netif_dbg(dev, drv, dev->net, "promiscuous mode enabled\n");
 		pdata->rfe_ctl |= RFE_CTL_AM | RFE_CTL_AU;
 	} else if (dev->net->flags & IFF_ALLMULTI) {
-		netif_dbg(dev, drv, dev->net, "receive all multicast enabled");
+		netif_dbg(dev, drv, dev->net, "receive all multicast enabled\n");
 		pdata->rfe_ctl |= RFE_CTL_AM | RFE_CTL_DPF;
 	} else if (!netdev_mc_empty(dev->net)) {
 		struct netdev_hw_addr *ha;
 
-		netif_dbg(dev, drv, dev->net, "receive multicast hash filter");
+		netif_dbg(dev, drv, dev->net, "receive multicast hash filter\n");
 
 		pdata->rfe_ctl |= RFE_CTL_MHF | RFE_CTL_DPF;
 
@@ -483,7 +518,7 @@ static void smsc75xx_set_multicast(struct net_device *netdev)
 				(1 << (bitnum % 32));
 		}
 	} else {
-		netif_dbg(dev, drv, dev->net, "receive own packets only");
+		netif_dbg(dev, drv, dev->net, "receive own packets only\n");
 		pdata->rfe_ctl |= RFE_CTL_DPF;
 	}
 
@@ -511,18 +546,18 @@ static int smsc75xx_update_flowcontrol(struct usbnet *dev, u8 duplex,
 		if (cap & FLOW_CTRL_RX)
 			flow |= FLOW_RX_FCEN;
 
-		netif_dbg(dev, link, dev->net, "rx pause %s, tx pause %s",
-			(cap & FLOW_CTRL_RX ? "enabled" : "disabled"),
-			(cap & FLOW_CTRL_TX ? "enabled" : "disabled"));
+		netif_dbg(dev, link, dev->net, "rx pause %s, tx pause %s\n",
+			  (cap & FLOW_CTRL_RX ? "enabled" : "disabled"),
+			  (cap & FLOW_CTRL_TX ? "enabled" : "disabled"));
 	} else {
-		netif_dbg(dev, link, dev->net, "half duplex");
+		netif_dbg(dev, link, dev->net, "half duplex\n");
 	}
 
 	ret = smsc75xx_write_reg(dev, FLOW, flow);
-	check_warn_return(ret, "Error writing FLOW");
+	check_warn_return(ret, "Error writing FLOW\n");
 
 	ret = smsc75xx_write_reg(dev, FCT_FLOW, fct_flow);
-	check_warn_return(ret, "Error writing FCT_FLOW");
+	check_warn_return(ret, "Error writing FCT_FLOW\n");
 
 	return 0;
 }
@@ -539,16 +574,15 @@ static int smsc75xx_link_reset(struct usbnet *dev)
 		PHY_INT_SRC_CLEAR_ALL);
 
 	ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL);
-	check_warn_return(ret, "Error writing INT_STS");
+	check_warn_return(ret, "Error writing INT_STS\n");
 
 	mii_check_media(mii, 1, 1);
 	mii_ethtool_gset(&dev->mii, &ecmd);
 	lcladv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE);
 	rmtadv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_LPA);
 
-	netif_dbg(dev, link, dev->net, "speed: %u duplex: %d lcladv: %04x"
-		  " rmtadv: %04x", ethtool_cmd_speed(&ecmd),
-		  ecmd.duplex, lcladv, rmtadv);
+	netif_dbg(dev, link, dev->net, "speed: %u duplex: %d lcladv: %04x rmtadv: %04x\n",
+		  ethtool_cmd_speed(&ecmd), ecmd.duplex, lcladv, rmtadv);
 
 	return smsc75xx_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv);
 }
@@ -558,21 +592,21 @@ static void smsc75xx_status(struct usbnet *dev, struct urb *urb)
 	u32 intdata;
 
 	if (urb->actual_length != 4) {
-		netdev_warn(dev->net,
-			"unexpected urb length %d", urb->actual_length);
+		netdev_warn(dev->net, "unexpected urb length %d\n",
+			    urb->actual_length);
 		return;
 	}
 
 	memcpy(&intdata, urb->transfer_buffer, 4);
 	le32_to_cpus(&intdata);
 
-	netif_dbg(dev, link, dev->net, "intdata: 0x%08X", intdata);
+	netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n", intdata);
 
 	if (intdata & INT_ENP_PHY_INT)
 		usbnet_defer_kevent(dev, EVENT_LINK_RESET);
 	else
-		netdev_warn(dev->net,
-			"unexpected interrupt, intdata=0x%08X", intdata);
+		netdev_warn(dev->net, "unexpected interrupt, intdata=0x%08X\n",
+			    intdata);
 }
 
 static int smsc75xx_ethtool_get_eeprom_len(struct net_device *net)
@@ -596,8 +630,8 @@ static int smsc75xx_ethtool_set_eeprom(struct net_device *netdev,
 	struct usbnet *dev = netdev_priv(netdev);
 
 	if (ee->magic != LAN75XX_EEPROM_MAGIC) {
-		netdev_warn(dev->net,
-			"EEPROM: magic value mismatch: 0x%x", ee->magic);
+		netdev_warn(dev->net, "EEPROM: magic value mismatch: 0x%x\n",
+			    ee->magic);
 		return -EINVAL;
 	}
 
@@ -619,8 +653,13 @@ static int smsc75xx_ethtool_set_wol(struct net_device *net,
 {
 	struct usbnet *dev = netdev_priv(net);
 	struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+	int ret;
 
 	pdata->wolopts = wolinfo->wolopts & SUPPORTED_WAKE;
+
+	ret = device_set_wakeup_enable(&dev->udev->dev, pdata->wolopts);
+	check_warn_return(ret, "device_set_wakeup_enable error %d\n", ret);
+
 	return 0;
 }
 
@@ -657,14 +696,14 @@ static void smsc75xx_init_mac_address(struct usbnet *dev)
 		if (is_valid_ether_addr(dev->net->dev_addr)) {
 			/* eeprom values are valid so use them */
 			netif_dbg(dev, ifup, dev->net,
-				"MAC address read from EEPROM");
+				  "MAC address read from EEPROM\n");
 			return;
 		}
 	}
 
 	/* no eeprom, or eeprom values are invalid. generate random MAC */
 	eth_hw_addr_random(dev->net);
-	netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr");
+	netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n");
 }
 
 static int smsc75xx_set_mac_address(struct usbnet *dev)
@@ -674,17 +713,17 @@ static int smsc75xx_set_mac_address(struct usbnet *dev)
 	u32 addr_hi = dev->net->dev_addr[4] | dev->net->dev_addr[5] << 8;
 
 	int ret = smsc75xx_write_reg(dev, RX_ADDRH, addr_hi);
-	check_warn_return(ret, "Failed to write RX_ADDRH: %d", ret);
+	check_warn_return(ret, "Failed to write RX_ADDRH: %d\n", ret);
 
 	ret = smsc75xx_write_reg(dev, RX_ADDRL, addr_lo);
-	check_warn_return(ret, "Failed to write RX_ADDRL: %d", ret);
+	check_warn_return(ret, "Failed to write RX_ADDRL: %d\n", ret);
 
 	addr_hi |= ADDR_FILTX_FB_VALID;
 	ret = smsc75xx_write_reg(dev, ADDR_FILTX, addr_hi);
-	check_warn_return(ret, "Failed to write ADDR_FILTX: %d", ret);
+	check_warn_return(ret, "Failed to write ADDR_FILTX: %d\n", ret);
 
 	ret = smsc75xx_write_reg(dev, ADDR_FILTX + 4, addr_lo);
-	check_warn_return(ret, "Failed to write ADDR_FILTX+4: %d", ret);
+	check_warn_return(ret, "Failed to write ADDR_FILTX+4: %d\n", ret);
 
 	return 0;
 }
@@ -708,12 +747,12 @@ static int smsc75xx_phy_initialize(struct usbnet *dev)
 	do {
 		msleep(10);
 		bmcr = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR);
-		check_warn_return(bmcr, "Error reading MII_BMCR");
+		check_warn_return(bmcr, "Error reading MII_BMCR\n");
 		timeout++;
 	} while ((bmcr & BMCR_RESET) && (timeout < 100));
 
 	if (timeout >= 100) {
-		netdev_warn(dev->net, "timeout on PHY Reset");
+		netdev_warn(dev->net, "timeout on PHY Reset\n");
 		return -EIO;
 	}
 
@@ -725,14 +764,14 @@ static int smsc75xx_phy_initialize(struct usbnet *dev)
 
 	/* read and write to clear phy interrupt status */
 	ret = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
-	check_warn_return(ret, "Error reading PHY_INT_SRC");
+	check_warn_return(ret, "Error reading PHY_INT_SRC\n");
 	smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_SRC, 0xffff);
 
 	smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK,
 		PHY_INT_MASK_DEFAULT);
 	mii_nway_restart(&dev->mii);
 
-	netif_dbg(dev, ifup, dev->net, "phy initialised successfully");
+	netif_dbg(dev, ifup, dev->net, "phy initialised successfully\n");
 	return 0;
 }
 
@@ -743,14 +782,14 @@ static int smsc75xx_set_rx_max_frame_length(struct usbnet *dev, int size)
 	bool rxenabled;
 
 	ret = smsc75xx_read_reg(dev, MAC_RX, &buf);
-	check_warn_return(ret, "Failed to read MAC_RX: %d", ret);
+	check_warn_return(ret, "Failed to read MAC_RX: %d\n", ret);
 
 	rxenabled = ((buf & MAC_RX_RXEN) != 0);
 
 	if (rxenabled) {
 		buf &= ~MAC_RX_RXEN;
 		ret = smsc75xx_write_reg(dev, MAC_RX, buf);
-		check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+		check_warn_return(ret, "Failed to write MAC_RX: %d\n", ret);
 	}
 
 	/* add 4 to size for FCS */
@@ -758,12 +797,12 @@ static int smsc75xx_set_rx_max_frame_length(struct usbnet *dev, int size)
 	buf |= (((size + 4) << MAC_RX_MAX_SIZE_SHIFT) & MAC_RX_MAX_SIZE);
 
 	ret = smsc75xx_write_reg(dev, MAC_RX, buf);
-	check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+	check_warn_return(ret, "Failed to write MAC_RX: %d\n", ret);
 
 	if (rxenabled) {
 		buf |= MAC_RX_RXEN;
 		ret = smsc75xx_write_reg(dev, MAC_RX, buf);
-		check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+		check_warn_return(ret, "Failed to write MAC_RX: %d\n", ret);
 	}
 
 	return 0;
@@ -774,7 +813,7 @@ static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu)
 	struct usbnet *dev = netdev_priv(netdev);
 
 	int ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu);
-	check_warn_return(ret, "Failed to set mac rx frame length");
+	check_warn_return(ret, "Failed to set mac rx frame length\n");
 
 	return usbnet_change_mtu(netdev, new_mtu);
 }
@@ -799,19 +838,22 @@ static int smsc75xx_set_features(struct net_device *netdev,
 	/* it's racing here! */
 
 	ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
-	check_warn_return(ret, "Error writing RFE_CTL");
+	check_warn_return(ret, "Error writing RFE_CTL\n");
 
 	return 0;
 }
 
-static int smsc75xx_wait_ready(struct usbnet *dev)
+static int smsc75xx_wait_ready(struct usbnet *dev, int in_pm)
 {
 	int timeout = 0;
 
 	do {
 		u32 buf;
-		int ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
-		check_warn_return(ret, "Failed to read PMT_CTL: %d", ret);
+		int ret;
+
+		ret = __smsc75xx_read_reg(dev, PMT_CTL, &buf, in_pm);
+
+		check_warn_return(ret, "Failed to read PMT_CTL: %d\n", ret);
 
 		if (buf & PMT_CTL_DEV_RDY)
 			return 0;
@@ -820,7 +862,7 @@ static int smsc75xx_wait_ready(struct usbnet *dev)
 		timeout++;
 	} while (timeout < 100);
 
-	netdev_warn(dev->net, "timeout waiting for device ready");
+	netdev_warn(dev->net, "timeout waiting for device ready\n");
 	return -EIO;
 }
 
@@ -830,79 +872,81 @@ static int smsc75xx_reset(struct usbnet *dev)
 	u32 buf;
 	int ret = 0, timeout;
 
-	netif_dbg(dev, ifup, dev->net, "entering smsc75xx_reset");
+	netif_dbg(dev, ifup, dev->net, "entering smsc75xx_reset\n");
 
-	ret = smsc75xx_wait_ready(dev);
-	check_warn_return(ret, "device not ready in smsc75xx_reset");
+	ret = smsc75xx_wait_ready(dev, 0);
+	check_warn_return(ret, "device not ready in smsc75xx_reset\n");
 
 	ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-	check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+	check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
 
 	buf |= HW_CFG_LRST;
 
 	ret = smsc75xx_write_reg(dev, HW_CFG, buf);
-	check_warn_return(ret, "Failed to write HW_CFG: %d", ret);
+	check_warn_return(ret, "Failed to write HW_CFG: %d\n", ret);
 
 	timeout = 0;
 	do {
 		msleep(10);
 		ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-		check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+		check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
 		timeout++;
 	} while ((buf & HW_CFG_LRST) && (timeout < 100));
 
 	if (timeout >= 100) {
-		netdev_warn(dev->net, "timeout on completion of Lite Reset");
+		netdev_warn(dev->net, "timeout on completion of Lite Reset\n");
 		return -EIO;
 	}
 
-	netif_dbg(dev, ifup, dev->net, "Lite reset complete, resetting PHY");
+	netif_dbg(dev, ifup, dev->net, "Lite reset complete, resetting PHY\n");
 
 	ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
-	check_warn_return(ret, "Failed to read PMT_CTL: %d", ret);
+	check_warn_return(ret, "Failed to read PMT_CTL: %d\n", ret);
 
 	buf |= PMT_CTL_PHY_RST;
 
 	ret = smsc75xx_write_reg(dev, PMT_CTL, buf);
-	check_warn_return(ret, "Failed to write PMT_CTL: %d", ret);
+	check_warn_return(ret, "Failed to write PMT_CTL: %d\n", ret);
 
 	timeout = 0;
 	do {
 		msleep(10);
 		ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
-		check_warn_return(ret, "Failed to read PMT_CTL: %d", ret);
+		check_warn_return(ret, "Failed to read PMT_CTL: %d\n", ret);
 		timeout++;
 	} while ((buf & PMT_CTL_PHY_RST) && (timeout < 100));
 
 	if (timeout >= 100) {
-		netdev_warn(dev->net, "timeout waiting for PHY Reset");
+		netdev_warn(dev->net, "timeout waiting for PHY Reset\n");
 		return -EIO;
 	}
 
-	netif_dbg(dev, ifup, dev->net, "PHY reset complete");
+	netif_dbg(dev, ifup, dev->net, "PHY reset complete\n");
 
 	smsc75xx_init_mac_address(dev);
 
 	ret = smsc75xx_set_mac_address(dev);
-	check_warn_return(ret, "Failed to set mac address");
+	check_warn_return(ret, "Failed to set mac address\n");
 
-	netif_dbg(dev, ifup, dev->net, "MAC Address: %pM", dev->net->dev_addr);
+	netif_dbg(dev, ifup, dev->net, "MAC Address: %pM\n",
+		  dev->net->dev_addr);
 
 	ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-	check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+	check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
 
-	netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG : 0x%08x", buf);
+	netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG : 0x%08x\n",
+		  buf);
 
 	buf |= HW_CFG_BIR;
 
 	ret = smsc75xx_write_reg(dev, HW_CFG, buf);
-	check_warn_return(ret, "Failed to write HW_CFG: %d", ret);
+	check_warn_return(ret, "Failed to write HW_CFG: %d\n", ret);
 
 	ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-	check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+	check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
 
-	netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG after "
-			"writing HW_CFG_BIR: 0x%08x", buf);
+	netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG after writing HW_CFG_BIR: 0x%08x\n",
+		  buf);
 
 	if (!turbo_mode) {
 		buf = 0;
@@ -915,99 +959,102 @@ static int smsc75xx_reset(struct usbnet *dev)
 		dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
 	}
 
-	netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld",
-		(ulong)dev->rx_urb_size);
+	netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n",
+		  (ulong)dev->rx_urb_size);
 
 	ret = smsc75xx_write_reg(dev, BURST_CAP, buf);
-	check_warn_return(ret, "Failed to write BURST_CAP: %d", ret);
+	check_warn_return(ret, "Failed to write BURST_CAP: %d\n", ret);
 
 	ret = smsc75xx_read_reg(dev, BURST_CAP, &buf);
-	check_warn_return(ret, "Failed to read BURST_CAP: %d", ret);
+	check_warn_return(ret, "Failed to read BURST_CAP: %d\n", ret);
 
 	netif_dbg(dev, ifup, dev->net,
-		"Read Value from BURST_CAP after writing: 0x%08x", buf);
+		  "Read Value from BURST_CAP after writing: 0x%08x\n", buf);
 
 	ret = smsc75xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY);
-	check_warn_return(ret, "Failed to write BULK_IN_DLY: %d", ret);
+	check_warn_return(ret, "Failed to write BULK_IN_DLY: %d\n", ret);
 
 	ret = smsc75xx_read_reg(dev, BULK_IN_DLY, &buf);
-	check_warn_return(ret, "Failed to read BULK_IN_DLY: %d", ret);
+	check_warn_return(ret, "Failed to read BULK_IN_DLY: %d\n", ret);
 
 	netif_dbg(dev, ifup, dev->net,
-		"Read Value from BULK_IN_DLY after writing: 0x%08x", buf);
+		  "Read Value from BULK_IN_DLY after writing: 0x%08x\n", buf);
 
 	if (turbo_mode) {
 		ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-		check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+		check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
 
-		netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x", buf);
+		netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x\n", buf);
 
 		buf |= (HW_CFG_MEF | HW_CFG_BCE);
 
 		ret = smsc75xx_write_reg(dev, HW_CFG, buf);
-		check_warn_return(ret, "Failed to write HW_CFG: %d", ret);
+		check_warn_return(ret, "Failed to write HW_CFG: %d\n", ret);
 
 		ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-		check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+		check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
 
-		netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x", buf);
+		netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x\n", buf);
 	}
 
 	/* set FIFO sizes */
 	buf = (MAX_RX_FIFO_SIZE - 512) / 512;
 	ret = smsc75xx_write_reg(dev, FCT_RX_FIFO_END, buf);
-	check_warn_return(ret, "Failed to write FCT_RX_FIFO_END: %d", ret);
+	check_warn_return(ret, "Failed to write FCT_RX_FIFO_END: %d\n", ret);
 
-	netif_dbg(dev, ifup, dev->net, "FCT_RX_FIFO_END set to 0x%08x", buf);
+	netif_dbg(dev, ifup, dev->net, "FCT_RX_FIFO_END set to 0x%08x\n", buf);
 
 	buf = (MAX_TX_FIFO_SIZE - 512) / 512;
 	ret = smsc75xx_write_reg(dev, FCT_TX_FIFO_END, buf);
-	check_warn_return(ret, "Failed to write FCT_TX_FIFO_END: %d", ret);
+	check_warn_return(ret, "Failed to write FCT_TX_FIFO_END: %d\n", ret);
 
-	netif_dbg(dev, ifup, dev->net, "FCT_TX_FIFO_END set to 0x%08x", buf);
+	netif_dbg(dev, ifup, dev->net, "FCT_TX_FIFO_END set to 0x%08x\n", buf);
 
 	ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL);
-	check_warn_return(ret, "Failed to write INT_STS: %d", ret);
+	check_warn_return(ret, "Failed to write INT_STS: %d\n", ret);
 
 	ret = smsc75xx_read_reg(dev, ID_REV, &buf);
-	check_warn_return(ret, "Failed to read ID_REV: %d", ret);
+	check_warn_return(ret, "Failed to read ID_REV: %d\n", ret);
 
-	netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x", buf);
+	netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x\n", buf);
 
 	ret = smsc75xx_read_reg(dev, E2P_CMD, &buf);
-	check_warn_return(ret, "Failed to read E2P_CMD: %d", ret);
+	check_warn_return(ret, "Failed to read E2P_CMD: %d\n", ret);
 
 	/* only set default GPIO/LED settings if no EEPROM is detected */
 	if (!(buf & E2P_CMD_LOADED)) {
 		ret = smsc75xx_read_reg(dev, LED_GPIO_CFG, &buf);
-		check_warn_return(ret, "Failed to read LED_GPIO_CFG: %d", ret);
+		check_warn_return(ret, "Failed to read LED_GPIO_CFG: %d\n",
+				  ret);
 
 		buf &= ~(LED_GPIO_CFG_LED2_FUN_SEL | LED_GPIO_CFG_LED10_FUN_SEL);
 		buf |= LED_GPIO_CFG_LEDGPIO_EN | LED_GPIO_CFG_LED2_FUN_SEL;
 
 		ret = smsc75xx_write_reg(dev, LED_GPIO_CFG, buf);
-		check_warn_return(ret, "Failed to write LED_GPIO_CFG: %d", ret);
+		check_warn_return(ret, "Failed to write LED_GPIO_CFG: %d\n",
+				  ret);
 	}
 
 	ret = smsc75xx_write_reg(dev, FLOW, 0);
-	check_warn_return(ret, "Failed to write FLOW: %d", ret);
+	check_warn_return(ret, "Failed to write FLOW: %d\n", ret);
 
 	ret = smsc75xx_write_reg(dev, FCT_FLOW, 0);
-	check_warn_return(ret, "Failed to write FCT_FLOW: %d", ret);
+	check_warn_return(ret, "Failed to write FCT_FLOW: %d\n", ret);
 
 	/* Don't need rfe_ctl_lock during initialisation */
 	ret = smsc75xx_read_reg(dev, RFE_CTL, &pdata->rfe_ctl);
-	check_warn_return(ret, "Failed to read RFE_CTL: %d", ret);
+	check_warn_return(ret, "Failed to read RFE_CTL: %d\n", ret);
 
 	pdata->rfe_ctl |= RFE_CTL_AB | RFE_CTL_DPF;
 
 	ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
-	check_warn_return(ret, "Failed to write RFE_CTL: %d", ret);
+	check_warn_return(ret, "Failed to write RFE_CTL: %d\n", ret);
 
 	ret = smsc75xx_read_reg(dev, RFE_CTL, &pdata->rfe_ctl);
-	check_warn_return(ret, "Failed to read RFE_CTL: %d", ret);
+	check_warn_return(ret, "Failed to read RFE_CTL: %d\n", ret);
 
-	netif_dbg(dev, ifup, dev->net, "RFE_CTL set to 0x%08x", pdata->rfe_ctl);
+	netif_dbg(dev, ifup, dev->net, "RFE_CTL set to 0x%08x\n",
+		  pdata->rfe_ctl);
 
 	/* Enable or disable checksum offload engines */
 	smsc75xx_set_features(dev->net, dev->net->features);
@@ -1015,69 +1062,69 @@ static int smsc75xx_reset(struct usbnet *dev)
 	smsc75xx_set_multicast(dev->net);
 
 	ret = smsc75xx_phy_initialize(dev);
-	check_warn_return(ret, "Failed to initialize PHY: %d", ret);
+	check_warn_return(ret, "Failed to initialize PHY: %d\n", ret);
 
 	ret = smsc75xx_read_reg(dev, INT_EP_CTL, &buf);
-	check_warn_return(ret, "Failed to read INT_EP_CTL: %d", ret);
+	check_warn_return(ret, "Failed to read INT_EP_CTL: %d\n", ret);
 
 	/* enable PHY interrupts */
 	buf |= INT_ENP_PHY_INT;
 
 	ret = smsc75xx_write_reg(dev, INT_EP_CTL, buf);
-	check_warn_return(ret, "Failed to write INT_EP_CTL: %d", ret);
+	check_warn_return(ret, "Failed to write INT_EP_CTL: %d\n", ret);
 
 	/* allow mac to detect speed and duplex from phy */
 	ret = smsc75xx_read_reg(dev, MAC_CR, &buf);
-	check_warn_return(ret, "Failed to read MAC_CR: %d", ret);
+	check_warn_return(ret, "Failed to read MAC_CR: %d\n", ret);
 
 	buf |= (MAC_CR_ADD | MAC_CR_ASD);
 	ret = smsc75xx_write_reg(dev, MAC_CR, buf);
-	check_warn_return(ret, "Failed to write MAC_CR: %d", ret);
+	check_warn_return(ret, "Failed to write MAC_CR: %d\n", ret);
 
 	ret = smsc75xx_read_reg(dev, MAC_TX, &buf);
-	check_warn_return(ret, "Failed to read MAC_TX: %d", ret);
+	check_warn_return(ret, "Failed to read MAC_TX: %d\n", ret);
 
 	buf |= MAC_TX_TXEN;
 
 	ret = smsc75xx_write_reg(dev, MAC_TX, buf);
-	check_warn_return(ret, "Failed to write MAC_TX: %d", ret);
+	check_warn_return(ret, "Failed to write MAC_TX: %d\n", ret);
 
-	netif_dbg(dev, ifup, dev->net, "MAC_TX set to 0x%08x", buf);
+	netif_dbg(dev, ifup, dev->net, "MAC_TX set to 0x%08x\n", buf);
 
 	ret = smsc75xx_read_reg(dev, FCT_TX_CTL, &buf);
-	check_warn_return(ret, "Failed to read FCT_TX_CTL: %d", ret);
+	check_warn_return(ret, "Failed to read FCT_TX_CTL: %d\n", ret);
 
 	buf |= FCT_TX_CTL_EN;
 
 	ret = smsc75xx_write_reg(dev, FCT_TX_CTL, buf);
-	check_warn_return(ret, "Failed to write FCT_TX_CTL: %d", ret);
+	check_warn_return(ret, "Failed to write FCT_TX_CTL: %d\n", ret);
 
-	netif_dbg(dev, ifup, dev->net, "FCT_TX_CTL set to 0x%08x", buf);
+	netif_dbg(dev, ifup, dev->net, "FCT_TX_CTL set to 0x%08x\n", buf);
 
 	ret = smsc75xx_set_rx_max_frame_length(dev, 1514);
-	check_warn_return(ret, "Failed to set max rx frame length");
+	check_warn_return(ret, "Failed to set max rx frame length\n");
 
 	ret = smsc75xx_read_reg(dev, MAC_RX, &buf);
-	check_warn_return(ret, "Failed to read MAC_RX: %d", ret);
+	check_warn_return(ret, "Failed to read MAC_RX: %d\n", ret);
 
 	buf |= MAC_RX_RXEN;
 
 	ret = smsc75xx_write_reg(dev, MAC_RX, buf);
-	check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+	check_warn_return(ret, "Failed to write MAC_RX: %d\n", ret);
 
-	netif_dbg(dev, ifup, dev->net, "MAC_RX set to 0x%08x", buf);
+	netif_dbg(dev, ifup, dev->net, "MAC_RX set to 0x%08x\n", buf);
 
 	ret = smsc75xx_read_reg(dev, FCT_RX_CTL, &buf);
-	check_warn_return(ret, "Failed to read FCT_RX_CTL: %d", ret);
+	check_warn_return(ret, "Failed to read FCT_RX_CTL: %d\n", ret);
 
 	buf |= FCT_RX_CTL_EN;
 
 	ret = smsc75xx_write_reg(dev, FCT_RX_CTL, buf);
-	check_warn_return(ret, "Failed to write FCT_RX_CTL: %d", ret);
+	check_warn_return(ret, "Failed to write FCT_RX_CTL: %d\n", ret);
 
-	netif_dbg(dev, ifup, dev->net, "FCT_RX_CTL set to 0x%08x", buf);
+	netif_dbg(dev, ifup, dev->net, "FCT_RX_CTL set to 0x%08x\n", buf);
 
-	netif_dbg(dev, ifup, dev->net, "smsc75xx_reset, return 0");
+	netif_dbg(dev, ifup, dev->net, "smsc75xx_reset, return 0\n");
 	return 0;
 }
 
@@ -1102,14 +1149,14 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
 	printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n");
 
 	ret = usbnet_get_endpoints(dev, intf);
-	check_warn_return(ret, "usbnet_get_endpoints failed: %d", ret);
+	check_warn_return(ret, "usbnet_get_endpoints failed: %d\n", ret);
 
 	dev->data[0] = (unsigned long)kzalloc(sizeof(struct smsc75xx_priv),
 		GFP_KERNEL);
 
 	pdata = (struct smsc75xx_priv *)(dev->data[0]);
 	if (!pdata) {
-		netdev_warn(dev->net, "Unable to allocate smsc75xx_priv");
+		netdev_warn(dev->net, "Unable to allocate smsc75xx_priv\n");
 		return -ENOMEM;
 	}
 
@@ -1134,6 +1181,7 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
 
 	/* Init all registers */
 	ret = smsc75xx_reset(dev);
+	check_warn_return(ret, "smsc75xx_reset error %d\n", ret);
 
 	dev->net->netdev_ops = &smsc75xx_netdev_ops;
 	dev->net->ethtool_ops = &smsc75xx_ethtool_ops;
@@ -1147,172 +1195,476 @@ static void smsc75xx_unbind(struct usbnet *dev, struct usb_interface *intf)
 {
 	struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
 	if (pdata) {
-		netif_dbg(dev, ifdown, dev->net, "free pdata");
+		netif_dbg(dev, ifdown, dev->net, "free pdata\n");
 		kfree(pdata);
 		pdata = NULL;
 		dev->data[0] = 0;
 	}
 }
 
+static u16 smsc_crc(const u8 *buffer, size_t len)
+{
+	return bitrev16(crc16(0xFFFF, buffer, len));
+}
+
+static int smsc75xx_write_wuff(struct usbnet *dev, int filter, u32 wuf_cfg,
+			       u32 wuf_mask1)
+{
+	int cfg_base = WUF_CFGX + filter * 4;
+	int mask_base = WUF_MASKX + filter * 16;
+	int ret;
+
+	ret = smsc75xx_write_reg(dev, cfg_base, wuf_cfg);
+	check_warn_return(ret, "Error writing WUF_CFGX\n");
+
+	ret = smsc75xx_write_reg(dev, mask_base, wuf_mask1);
+	check_warn_return(ret, "Error writing WUF_MASKX\n");
+
+	ret = smsc75xx_write_reg(dev, mask_base + 4, 0);
+	check_warn_return(ret, "Error writing WUF_MASKX\n");
+
+	ret = smsc75xx_write_reg(dev, mask_base + 8, 0);
+	check_warn_return(ret, "Error writing WUF_MASKX\n");
+
+	ret = smsc75xx_write_reg(dev, mask_base + 12, 0);
+	check_warn_return(ret, "Error writing WUF_MASKX\n");
+
+	return 0;
+}
+
+static int smsc75xx_enter_suspend0(struct usbnet *dev)
+{
+	struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+	u32 val;
+	int ret;
+
+	ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+	check_warn_return(ret, "Error reading PMT_CTL\n");
+
+	val &= (~(PMT_CTL_SUS_MODE | PMT_CTL_PHY_RST));
+	val |= PMT_CTL_SUS_MODE_0 | PMT_CTL_WOL_EN | PMT_CTL_WUPS;
+
+	ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+	check_warn_return(ret, "Error writing PMT_CTL\n");
+
+	pdata->suspend_flags |= SUSPEND_SUSPEND0;
+
+	return 0;
+}
+
+static int smsc75xx_enter_suspend1(struct usbnet *dev)
+{
+	struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+	u32 val;
+	int ret;
+
+	ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+	check_warn_return(ret, "Error reading PMT_CTL\n");
+
+	val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
+	val |= PMT_CTL_SUS_MODE_1;
+
+	ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+	check_warn_return(ret, "Error writing PMT_CTL\n");
+
+	/* clear wol status, enable energy detection */
+	val &= ~PMT_CTL_WUPS;
+	val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN);
+
+	ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+	check_warn_return(ret, "Error writing PMT_CTL\n");
+
+	pdata->suspend_flags |= SUSPEND_SUSPEND1;
+
+	return 0;
+}
+
+static int smsc75xx_enter_suspend2(struct usbnet *dev)
+{
+	struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+	u32 val;
+	int ret;
+
+	ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+	check_warn_return(ret, "Error reading PMT_CTL\n");
+
+	val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
+	val |= PMT_CTL_SUS_MODE_2;
+
+	ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+	check_warn_return(ret, "Error writing PMT_CTL\n");
+
+	pdata->suspend_flags |= SUSPEND_SUSPEND2;
+
+	return 0;
+}
+
+static int smsc75xx_enter_suspend3(struct usbnet *dev)
+{
+	struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+	u32 val;
+	int ret;
+
+	ret = smsc75xx_read_reg_nopm(dev, FCT_RX_CTL, &val);
+	check_warn_return(ret, "Error reading FCT_RX_CTL\n");
+
+	if (val & FCT_RX_CTL_RXUSED) {
+		netdev_dbg(dev->net, "rx fifo not empty in autosuspend\n");
+		return -EBUSY;
+	}
+
+	ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+	check_warn_return(ret, "Error reading PMT_CTL\n");
+
+	val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
+	val |= PMT_CTL_SUS_MODE_3 | PMT_CTL_RES_CLR_WKP_EN;
+
+	ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+	check_warn_return(ret, "Error writing PMT_CTL\n");
+
+	/* clear wol status */
+	val &= ~PMT_CTL_WUPS;
+	val |= PMT_CTL_WUPS_WOL;
+
+	ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+	check_warn_return(ret, "Error writing PMT_CTL\n");
+
+	pdata->suspend_flags |= SUSPEND_SUSPEND3;
+
+	return 0;
+}
+
+static int smsc75xx_enable_phy_wakeup_interrupts(struct usbnet *dev, u16 mask)
+{
+	struct mii_if_info *mii = &dev->mii;
+	int ret;
+
+	netdev_dbg(dev->net, "enabling PHY wakeup interrupts\n");
+
+	/* read to clear */
+	ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_SRC);
+	check_warn_return(ret, "Error reading PHY_INT_SRC\n");
+
+	/* enable interrupt source */
+	ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_MASK);
+	check_warn_return(ret, "Error reading PHY_INT_MASK\n");
+
+	ret |= mask;
+
+	smsc75xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_INT_MASK, ret);
+
+	return 0;
+}
+
+static int smsc75xx_link_ok_nopm(struct usbnet *dev)
+{
+	struct mii_if_info *mii = &dev->mii;
+	int ret;
+
+	/* first, a dummy read, needed to latch some MII phys */
+	ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
+	check_warn_return(ret, "Error reading MII_BMSR\n");
+
+	ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
+	check_warn_return(ret, "Error reading MII_BMSR\n");
+
+	return !!(ret & BMSR_LSTATUS);
+}
+
+static int smsc75xx_autosuspend(struct usbnet *dev, u32 link_up)
+{
+	int ret;
+
+	if (!netif_running(dev->net)) {
+		/* interface is ifconfig down so fully power down hw */
+		netdev_dbg(dev->net, "autosuspend entering SUSPEND2\n");
+		return smsc75xx_enter_suspend2(dev);
+	}
+
+	if (!link_up) {
+		/* link is down so enter EDPD mode */
+		netdev_dbg(dev->net, "autosuspend entering SUSPEND1\n");
+
+		/* enable PHY wakeup events for if cable is attached */
+		ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
+			PHY_INT_MASK_ANEG_COMP);
+		check_warn_return(ret, "error enabling PHY wakeup ints\n");
+
+		netdev_info(dev->net, "entering SUSPEND1 mode\n");
+		return smsc75xx_enter_suspend1(dev);
+	}
+
+	/* enable PHY wakeup events so we remote wakeup if cable is pulled */
+	ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
+		PHY_INT_MASK_LINK_DOWN);
+	check_warn_return(ret, "error enabling PHY wakeup ints\n");
+
+	netdev_dbg(dev->net, "autosuspend entering SUSPEND3\n");
+	return smsc75xx_enter_suspend3(dev);
+}
+
 static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct usbnet *dev = usb_get_intfdata(intf);
 	struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+	u32 val, link_up;
 	int ret;
-	u32 val;
 
 	ret = usbnet_suspend(intf, message);
-	check_warn_return(ret, "usbnet_suspend error");
+	check_warn_goto_done(ret, "usbnet_suspend error\n");
+
+	if (pdata->suspend_flags) {
+		netdev_warn(dev->net, "error during last resume\n");
+		pdata->suspend_flags = 0;
+	}
+
+	/* determine if link is up using only _nopm functions */
+	link_up = smsc75xx_link_ok_nopm(dev);
+
+	if (message.event == PM_EVENT_AUTO_SUSPEND) {
+		ret = smsc75xx_autosuspend(dev, link_up);
+		goto done;
+	}
 
-	/* if no wol options set, enter lowest power SUSPEND2 mode */
-	if (!(pdata->wolopts & SUPPORTED_WAKE)) {
-		netdev_info(dev->net, "entering SUSPEND2 mode");
+	/* if we get this far we're not autosuspending */
+	/* if no wol options set, or if link is down and we're not waking on
+	 * PHY activity, enter lowest power SUSPEND2 mode
+	 */
+	if (!(pdata->wolopts & SUPPORTED_WAKE) ||
+		!(link_up || (pdata->wolopts & WAKE_PHY))) {
+		netdev_info(dev->net, "entering SUSPEND2 mode\n");
 
 		/* disable energy detect (link up) & wake up events */
-		ret = smsc75xx_read_reg(dev, WUCSR, &val);
-		check_warn_return(ret, "Error reading WUCSR");
+		ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+		check_warn_goto_done(ret, "Error reading WUCSR\n");
 
 		val &= ~(WUCSR_MPEN | WUCSR_WUEN);
 
-		ret = smsc75xx_write_reg(dev, WUCSR, val);
-		check_warn_return(ret, "Error writing WUCSR");
+		ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+		check_warn_goto_done(ret, "Error writing WUCSR\n");
 
-		ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
-		check_warn_return(ret, "Error reading PMT_CTL");
+		ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+		check_warn_goto_done(ret, "Error reading PMT_CTL\n");
 
 		val &= ~(PMT_CTL_ED_EN | PMT_CTL_WOL_EN);
 
-		ret = smsc75xx_write_reg(dev, PMT_CTL, val);
-		check_warn_return(ret, "Error writing PMT_CTL");
+		ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+		check_warn_goto_done(ret, "Error writing PMT_CTL\n");
 
-		/* enter suspend2 mode */
-		ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
-		check_warn_return(ret, "Error reading PMT_CTL");
+		ret = smsc75xx_enter_suspend2(dev);
+		goto done;
+	}
 
-		val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
-		val |= PMT_CTL_SUS_MODE_2;
+	if (pdata->wolopts & WAKE_PHY) {
+		ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
+			(PHY_INT_MASK_ANEG_COMP | PHY_INT_MASK_LINK_DOWN));
+		check_warn_goto_done(ret, "error enabling PHY wakeup ints\n");
 
-		ret = smsc75xx_write_reg(dev, PMT_CTL, val);
-		check_warn_return(ret, "Error writing PMT_CTL");
+		/* if link is down then configure EDPD and enter SUSPEND1,
+		 * otherwise enter SUSPEND0 below
+		 */
+		if (!link_up) {
+			struct mii_if_info *mii = &dev->mii;
+			netdev_info(dev->net, "entering SUSPEND1 mode\n");
 
-		return 0;
-	}
+			/* enable energy detect power-down mode */
+			ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id,
+				PHY_MODE_CTRL_STS);
+			check_warn_goto_done(ret, "Error reading PHY_MODE_CTRL_STS\n");
 
-	if (pdata->wolopts & WAKE_MAGIC) {
-		/* clear any pending magic packet status */
-		ret = smsc75xx_read_reg(dev, WUCSR, &val);
-		check_warn_return(ret, "Error reading WUCSR");
+			ret |= MODE_CTRL_STS_EDPWRDOWN;
 
-		val |= WUCSR_MPR;
+			smsc75xx_mdio_write_nopm(dev->net, mii->phy_id,
+				PHY_MODE_CTRL_STS, ret);
 
-		ret = smsc75xx_write_reg(dev, WUCSR, val);
-		check_warn_return(ret, "Error writing WUCSR");
+			/* enter SUSPEND1 mode */
+			ret = smsc75xx_enter_suspend1(dev);
+			goto done;
+		}
 	}
 
-	/* enable/disable magic packup wake */
-	ret = smsc75xx_read_reg(dev, WUCSR, &val);
-	check_warn_return(ret, "Error reading WUCSR");
+	if (pdata->wolopts & (WAKE_MCAST | WAKE_ARP)) {
+		int i, filter = 0;
 
-	if (pdata->wolopts & WAKE_MAGIC) {
-		netdev_info(dev->net, "enabling magic packet wakeup");
-		val |= WUCSR_MPEN;
+		/* disable all filters */
+		for (i = 0; i < WUF_NUM; i++) {
+			ret = smsc75xx_write_reg_nopm(dev, WUF_CFGX + i * 4, 0);
+			check_warn_goto_done(ret, "Error writing WUF_CFGX\n");
+		}
+
+		if (pdata->wolopts & WAKE_MCAST) {
+			const u8 mcast[] = {0x01, 0x00, 0x5E};
+			netdev_info(dev->net, "enabling multicast detection\n");
+
+			val = WUF_CFGX_EN | WUF_CFGX_ATYPE_MULTICAST
+				| smsc_crc(mcast, 3);
+			ret = smsc75xx_write_wuff(dev, filter++, val, 0x0007);
+			check_warn_goto_done(ret, "Error writing wakeup filter\n");
+		}
+
+		if (pdata->wolopts & WAKE_ARP) {
+			const u8 arp[] = {0x08, 0x06};
+			netdev_info(dev->net, "enabling ARP detection\n");
+
+			val = WUF_CFGX_EN | WUF_CFGX_ATYPE_ALL | (0x0C << 16)
+				| smsc_crc(arp, 2);
+			ret = smsc75xx_write_wuff(dev, filter++, val, 0x0003);
+			check_warn_goto_done(ret, "Error writing wakeup filter\n");
+		}
+
+		/* clear any pending pattern match packet status */
+		ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+		check_warn_goto_done(ret, "Error reading WUCSR\n");
+
+		val |= WUCSR_WUFR;
+
+		ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+		check_warn_goto_done(ret, "Error writing WUCSR\n");
+
+		netdev_info(dev->net, "enabling packet match detection\n");
+		ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+		check_warn_goto_done(ret, "Error reading WUCSR\n");
+
+		val |= WUCSR_WUEN;
+
+		ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+		check_warn_goto_done(ret, "Error writing WUCSR\n");
 	} else {
-		netdev_info(dev->net, "disabling magic packet wakeup");
-		val &= ~WUCSR_MPEN;
+		netdev_info(dev->net, "disabling packet match detection\n");
+		ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+		check_warn_goto_done(ret, "Error reading WUCSR\n");
+
+		val &= ~WUCSR_WUEN;
+
+		ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+		check_warn_goto_done(ret, "Error writing WUCSR\n");
 	}
 
-	ret = smsc75xx_write_reg(dev, WUCSR, val);
-	check_warn_return(ret, "Error writing WUCSR");
+	/* disable magic, bcast & unicast wakeup sources */
+	ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+	check_warn_goto_done(ret, "Error reading WUCSR\n");
 
-	/* enable wol wakeup source */
-	ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
-	check_warn_return(ret, "Error reading PMT_CTL");
+	val &= ~(WUCSR_MPEN | WUCSR_BCST_EN | WUCSR_PFDA_EN);
 
-	val |= PMT_CTL_WOL_EN;
+	ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+	check_warn_goto_done(ret, "Error writing WUCSR\n");
 
-	ret = smsc75xx_write_reg(dev, PMT_CTL, val);
-	check_warn_return(ret, "Error writing PMT_CTL");
+	if (pdata->wolopts & WAKE_PHY) {
+		netdev_info(dev->net, "enabling PHY wakeup\n");
 
-	/* enable receiver */
-	ret = smsc75xx_read_reg(dev, MAC_RX, &val);
-	check_warn_return(ret, "Failed to read MAC_RX: %d", ret);
+		ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+		check_warn_goto_done(ret, "Error reading PMT_CTL\n");
 
-	val |= MAC_RX_RXEN;
+		/* clear wol status, enable energy detection */
+		val &= ~PMT_CTL_WUPS;
+		val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN);
 
-	ret = smsc75xx_write_reg(dev, MAC_RX, val);
-	check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+		ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+		check_warn_goto_done(ret, "Error writing PMT_CTL\n");
+	}
 
-	/* some wol options are enabled, so enter SUSPEND0 */
-	netdev_info(dev->net, "entering SUSPEND0 mode");
+	if (pdata->wolopts & WAKE_MAGIC) {
+		netdev_info(dev->net, "enabling magic packet wakeup\n");
+		ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+		check_warn_goto_done(ret, "Error reading WUCSR\n");
 
-	ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
-	check_warn_return(ret, "Error reading PMT_CTL");
+		/* clear any pending magic packet status */
+		val |= WUCSR_MPR | WUCSR_MPEN;
 
-	val &= (~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST));
-	val |= PMT_CTL_SUS_MODE_0;
+		ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+		check_warn_goto_done(ret, "Error writing WUCSR\n");
+	}
 
-	ret = smsc75xx_write_reg(dev, PMT_CTL, val);
-	check_warn_return(ret, "Error writing PMT_CTL");
+	if (pdata->wolopts & WAKE_BCAST) {
+		netdev_info(dev->net, "enabling broadcast detection\n");
+		ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+		check_warn_goto_done(ret, "Error reading WUCSR\n");
 
-	/* clear wol status */
-	val &= ~PMT_CTL_WUPS;
-	val |= PMT_CTL_WUPS_WOL;
-	ret = smsc75xx_write_reg(dev, PMT_CTL, val);
-	check_warn_return(ret, "Error writing PMT_CTL");
+		val |= WUCSR_BCAST_FR | WUCSR_BCST_EN;
 
-	/* read back PMT_CTL */
-	ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
-	check_warn_return(ret, "Error reading PMT_CTL");
+		ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+		check_warn_goto_done(ret, "Error writing WUCSR\n");
+	}
 
-	smsc75xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+	if (pdata->wolopts & WAKE_UCAST) {
+		netdev_info(dev->net, "enabling unicast detection\n");
+		ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+		check_warn_goto_done(ret, "Error reading WUCSR\n");
 
-	return 0;
+		val |= WUCSR_WUFR | WUCSR_PFDA_EN;
+
+		ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+		check_warn_goto_done(ret, "Error writing WUCSR\n");
+	}
+
+	/* enable receiver to enable frame reception */
+	ret = smsc75xx_read_reg_nopm(dev, MAC_RX, &val);
+	check_warn_goto_done(ret, "Failed to read MAC_RX: %d\n", ret);
+
+	val |= MAC_RX_RXEN;
+
+	ret = smsc75xx_write_reg_nopm(dev, MAC_RX, val);
+	check_warn_goto_done(ret, "Failed to write MAC_RX: %d\n", ret);
+
+	/* some wol options are enabled, so enter SUSPEND0 */
+	netdev_info(dev->net, "entering SUSPEND0 mode\n");
+	ret = smsc75xx_enter_suspend0(dev);
+
+done:
+	if (ret)
+		usbnet_resume(intf);
+	return ret;
 }
 
 static int smsc75xx_resume(struct usb_interface *intf)
 {
 	struct usbnet *dev = usb_get_intfdata(intf);
 	struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+	u8 suspend_flags = pdata->suspend_flags;
 	int ret;
 	u32 val;
 
-	if (pdata->wolopts & WAKE_MAGIC) {
-		netdev_info(dev->net, "resuming from SUSPEND0");
+	netdev_dbg(dev->net, "resume suspend_flags=0x%02x\n", suspend_flags);
 
-		smsc75xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+	/* do this first to ensure it's cleared even in error case */
+	pdata->suspend_flags = 0;
 
-		/* Disable magic packup wake */
-		ret = smsc75xx_read_reg(dev, WUCSR, &val);
-		check_warn_return(ret, "Error reading WUCSR");
+	if (suspend_flags & SUSPEND_ALLMODES) {
+		/* Disable wakeup sources */
+		ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+		check_warn_return(ret, "Error reading WUCSR\n");
 
-		val &= ~WUCSR_MPEN;
+		val &= ~(WUCSR_WUEN | WUCSR_MPEN | WUCSR_PFDA_EN
+			| WUCSR_BCST_EN);
 
-		ret = smsc75xx_write_reg(dev, WUCSR, val);
-		check_warn_return(ret, "Error writing WUCSR");
+		ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+		check_warn_return(ret, "Error writing WUCSR\n");
 
 		/* clear wake-up status */
-		ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
-		check_warn_return(ret, "Error reading PMT_CTL");
+		ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+		check_warn_return(ret, "Error reading PMT_CTL\n");
 
 		val &= ~PMT_CTL_WOL_EN;
 		val |= PMT_CTL_WUPS;
 
-		ret = smsc75xx_write_reg(dev, PMT_CTL, val);
-		check_warn_return(ret, "Error writing PMT_CTL");
-	} else {
-		netdev_info(dev->net, "resuming from SUSPEND2");
+		ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+		check_warn_return(ret, "Error writing PMT_CTL\n");
+	}
+
+	if (suspend_flags & SUSPEND_SUSPEND2) {
+		netdev_info(dev->net, "resuming from SUSPEND2\n");
 
-		ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
-		check_warn_return(ret, "Error reading PMT_CTL");
+		ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+		check_warn_return(ret, "Error reading PMT_CTL\n");
 
 		val |= PMT_CTL_PHY_PWRUP;
 
-		ret = smsc75xx_write_reg(dev, PMT_CTL, val);
-		check_warn_return(ret, "Error writing PMT_CTL");
+		ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+		check_warn_return(ret, "Error writing PMT_CTL\n");
 	}
 
-	ret = smsc75xx_wait_ready(dev);
-	check_warn_return(ret, "device not ready in smsc75xx_resume");
+	ret = smsc75xx_wait_ready(dev, 1);
+	check_warn_return(ret, "device not ready in smsc75xx_resume\n");
 
 	return usbnet_resume(intf);
 }
@@ -1352,7 +1704,7 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 
 		if (unlikely(rx_cmd_a & RX_CMD_A_RED)) {
 			netif_dbg(dev, rx_err, dev->net,
-				"Error rx_cmd_a=0x%08x", rx_cmd_a);
+				  "Error rx_cmd_a=0x%08x\n", rx_cmd_a);
 			dev->net->stats.rx_errors++;
 			dev->net->stats.rx_dropped++;
 
@@ -1364,7 +1716,8 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 			/* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */
 			if (unlikely(size > (ETH_FRAME_LEN + 12))) {
 				netif_dbg(dev, rx_err, dev->net,
-					"size err rx_cmd_a=0x%08x", rx_cmd_a);
+					  "size err rx_cmd_a=0x%08x\n",
+					  rx_cmd_a);
 				return 0;
 			}
 
@@ -1381,7 +1734,7 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 
 			ax_skb = skb_clone(skb, GFP_ATOMIC);
 			if (unlikely(!ax_skb)) {
-				netdev_warn(dev->net, "Error allocating skb");
+				netdev_warn(dev->net, "Error allocating skb\n");
 				return 0;
 			}
 
@@ -1406,7 +1759,7 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 	}
 
 	if (unlikely(skb->len < 0)) {
-		netdev_warn(dev->net, "invalid rx length<0 %d", skb->len);
+		netdev_warn(dev->net, "invalid rx length<0 %d\n", skb->len);
 		return 0;
 	}
 
@@ -1454,6 +1807,12 @@ static struct sk_buff *smsc75xx_tx_fixup(struct usbnet *dev,
 	return skb;
 }
 
+static int smsc75xx_manage_power(struct usbnet *dev, int on)
+{
+	dev->intf->needs_remote_wakeup = on;
+	return 0;
+}
+
 static const struct driver_info smsc75xx_info = {
 	.description	= "smsc75xx USB 2.0 Gigabit Ethernet",
 	.bind		= smsc75xx_bind,
@@ -1463,6 +1822,7 @@ static const struct driver_info smsc75xx_info = {
 	.rx_fixup	= smsc75xx_rx_fixup,
 	.tx_fixup	= smsc75xx_tx_fixup,
 	.status		= smsc75xx_status,
+	.manage_power	= smsc75xx_manage_power,
 	.flags		= FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR,
 };
 
@@ -1490,6 +1850,7 @@ static struct usb_driver smsc75xx_driver = {
 	.reset_resume	= smsc75xx_resume,
 	.disconnect	= usbnet_disconnect,
 	.disable_hub_initiated_lpm = 1,
+	.supports_autosuspend = 1,
 };
 
 module_usb_driver(smsc75xx_driver);
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 362cb8c..79d495d 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -26,6 +26,8 @@
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
+#include <linux/bitrev.h>
+#include <linux/crc16.h>
 #include <linux/crc32.h>
 #include <linux/usb/usbnet.h>
 #include <linux/slab.h>
@@ -46,7 +48,12 @@
 #define SMSC95XX_INTERNAL_PHY_ID	(1)
 #define SMSC95XX_TX_OVERHEAD		(8)
 #define SMSC95XX_TX_OVERHEAD_CSUM	(12)
-#define SUPPORTED_WAKE			(WAKE_MAGIC)
+#define SUPPORTED_WAKE			(WAKE_PHY | WAKE_UCAST | WAKE_BCAST | \
+					 WAKE_MCAST | WAKE_ARP | WAKE_MAGIC)
+
+#define FEATURE_8_WAKEUP_FILTERS	(0x01)
+#define FEATURE_PHY_NLP_CROSSOVER	(0x02)
+#define FEATURE_AUTOSUSPEND		(0x04)
 
 #define check_warn(ret, fmt, args...) \
 	({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
@@ -63,80 +70,98 @@ struct smsc95xx_priv {
 	u32 hash_lo;
 	u32 wolopts;
 	spinlock_t mac_cr_lock;
-};
-
-struct usb_context {
-	struct usb_ctrlrequest req;
-	struct usbnet *dev;
+	u8 features;
 };
 
 static bool turbo_mode = true;
 module_param(turbo_mode, bool, 0644);
 MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
 
-static int __must_check smsc95xx_read_reg(struct usbnet *dev, u32 index,
-					  u32 *data)
+static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index,
+					    u32 *data, int in_pm)
 {
-	u32 *buf = kmalloc(4, GFP_KERNEL);
+	u32 buf;
 	int ret;
+	int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
 
 	BUG_ON(!dev);
 
-	if (!buf)
-		return -ENOMEM;
-
-	ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
-		USB_VENDOR_REQUEST_READ_REGISTER,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		00, index, buf, 4, USB_CTRL_GET_TIMEOUT);
+	if (!in_pm)
+		fn = usbnet_read_cmd;
+	else
+		fn = usbnet_read_cmd_nopm;
 
+	ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN
+		 | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		 0, index, &buf, 4);
 	if (unlikely(ret < 0))
-		netdev_warn(dev->net, "Failed to read register index 0x%08x\n", index);
+		netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n",
+			    index, ret);
 
-	le32_to_cpus(buf);
-	*data = *buf;
-	kfree(buf);
+	le32_to_cpus(&buf);
+	*data = buf;
 
 	return ret;
 }
 
-static int __must_check smsc95xx_write_reg(struct usbnet *dev, u32 index,
-					   u32 data)
+static int __must_check __smsc95xx_write_reg(struct usbnet *dev, u32 index,
+					     u32 data, int in_pm)
 {
-	u32 *buf = kmalloc(4, GFP_KERNEL);
+	u32 buf;
 	int ret;
+	int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16);
 
 	BUG_ON(!dev);
 
-	if (!buf)
-		return -ENOMEM;
-
-	*buf = data;
-	cpu_to_le32s(buf);
+	if (!in_pm)
+		fn = usbnet_write_cmd;
+	else
+		fn = usbnet_write_cmd_nopm;
 
-	ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-		USB_VENDOR_REQUEST_WRITE_REGISTER,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		00, index, buf, 4, USB_CTRL_SET_TIMEOUT);
+	buf = data;
+	cpu_to_le32s(&buf);
 
+	ret = fn(dev, USB_VENDOR_REQUEST_WRITE_REGISTER, USB_DIR_OUT
+		 | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		 0, index, &buf, 4);
 	if (unlikely(ret < 0))
-		netdev_warn(dev->net, "Failed to write register index 0x%08x\n", index);
-
-	kfree(buf);
+		netdev_warn(dev->net, "Failed to write reg index 0x%08x: %d\n",
+			    index, ret);
 
 	return ret;
 }
 
+static int __must_check smsc95xx_read_reg_nopm(struct usbnet *dev, u32 index,
+					       u32 *data)
+{
+	return __smsc95xx_read_reg(dev, index, data, 1);
+}
+
+static int __must_check smsc95xx_write_reg_nopm(struct usbnet *dev, u32 index,
+						u32 data)
+{
+	return __smsc95xx_write_reg(dev, index, data, 1);
+}
+
+static int __must_check smsc95xx_read_reg(struct usbnet *dev, u32 index,
+					  u32 *data)
+{
+	return __smsc95xx_read_reg(dev, index, data, 0);
+}
+
+static int __must_check smsc95xx_write_reg(struct usbnet *dev, u32 index,
+					   u32 data)
+{
+	return __smsc95xx_write_reg(dev, index, data, 0);
+}
 static int smsc95xx_set_feature(struct usbnet *dev, u32 feature)
 {
 	if (WARN_ON_ONCE(!dev))
 		return -EINVAL;
 
-	cpu_to_le32s(&feature);
-
-	return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-		USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
-		USB_CTRL_SET_TIMEOUT);
+	return usbnet_write_cmd_nopm(dev, USB_REQ_SET_FEATURE,
+				     USB_RECIP_DEVICE, feature, 0,
+				     NULL, 0);
 }
 
 static int smsc95xx_clear_feature(struct usbnet *dev, u32 feature)
@@ -144,24 +169,23 @@ static int smsc95xx_clear_feature(struct usbnet *dev, u32 feature)
 	if (WARN_ON_ONCE(!dev))
 		return -EINVAL;
 
-	cpu_to_le32s(&feature);
-
-	return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-		USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
-		USB_CTRL_SET_TIMEOUT);
+	return usbnet_write_cmd_nopm(dev, USB_REQ_CLEAR_FEATURE,
+				     USB_RECIP_DEVICE, feature,
+				     0, NULL, 0);
 }
 
 /* Loop until the read is completed with timeout
  * called with phy_mutex held */
-static int __must_check smsc95xx_phy_wait_not_busy(struct usbnet *dev)
+static int __must_check __smsc95xx_phy_wait_not_busy(struct usbnet *dev,
+						     int in_pm)
 {
 	unsigned long start_time = jiffies;
 	u32 val;
 	int ret;
 
 	do {
-		ret = smsc95xx_read_reg(dev, MII_ADDR, &val);
-		check_warn_return(ret, "Error reading MII_ACCESS");
+		ret = __smsc95xx_read_reg(dev, MII_ADDR, &val, in_pm);
+		check_warn_return(ret, "Error reading MII_ACCESS\n");
 		if (!(val & MII_BUSY_))
 			return 0;
 	} while (!time_after(jiffies, start_time + HZ));
@@ -169,7 +193,8 @@ static int __must_check smsc95xx_phy_wait_not_busy(struct usbnet *dev)
 	return -EIO;
 }
 
-static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
+static int __smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx,
+				int in_pm)
 {
 	struct usbnet *dev = netdev_priv(netdev);
 	u32 val, addr;
@@ -178,21 +203,21 @@ static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
 	mutex_lock(&dev->phy_mutex);
 
 	/* confirm MII not busy */
-	ret = smsc95xx_phy_wait_not_busy(dev);
-	check_warn_goto_done(ret, "MII is busy in smsc95xx_mdio_read");
+	ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
+	check_warn_goto_done(ret, "MII is busy in smsc95xx_mdio_read\n");
 
 	/* set the address, index & direction (read from PHY) */
 	phy_id &= dev->mii.phy_id_mask;
 	idx &= dev->mii.reg_num_mask;
 	addr = (phy_id << 11) | (idx << 6) | MII_READ_ | MII_BUSY_;
-	ret = smsc95xx_write_reg(dev, MII_ADDR, addr);
-	check_warn_goto_done(ret, "Error writing MII_ADDR");
+	ret = __smsc95xx_write_reg(dev, MII_ADDR, addr, in_pm);
+	check_warn_goto_done(ret, "Error writing MII_ADDR\n");
 
-	ret = smsc95xx_phy_wait_not_busy(dev);
-	check_warn_goto_done(ret, "Timed out reading MII reg %02X", idx);
+	ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
+	check_warn_goto_done(ret, "Timed out reading MII reg %02X\n", idx);
 
-	ret = smsc95xx_read_reg(dev, MII_DATA, &val);
-	check_warn_goto_done(ret, "Error reading MII_DATA");
+	ret = __smsc95xx_read_reg(dev, MII_DATA, &val, in_pm);
+	check_warn_goto_done(ret, "Error reading MII_DATA\n");
 
 	ret = (u16)(val & 0xFFFF);
 
@@ -201,8 +226,8 @@ done:
 	return ret;
 }
 
-static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
-				int regval)
+static void __smsc95xx_mdio_write(struct net_device *netdev, int phy_id,
+				  int idx, int regval, int in_pm)
 {
 	struct usbnet *dev = netdev_priv(netdev);
 	u32 val, addr;
@@ -211,27 +236,50 @@ static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
 	mutex_lock(&dev->phy_mutex);
 
 	/* confirm MII not busy */
-	ret = smsc95xx_phy_wait_not_busy(dev);
-	check_warn_goto_done(ret, "MII is busy in smsc95xx_mdio_write");
+	ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
+	check_warn_goto_done(ret, "MII is busy in smsc95xx_mdio_write\n");
 
 	val = regval;
-	ret = smsc95xx_write_reg(dev, MII_DATA, val);
-	check_warn_goto_done(ret, "Error writing MII_DATA");
+	ret = __smsc95xx_write_reg(dev, MII_DATA, val, in_pm);
+	check_warn_goto_done(ret, "Error writing MII_DATA\n");
 
 	/* set the address, index & direction (write to PHY) */
 	phy_id &= dev->mii.phy_id_mask;
 	idx &= dev->mii.reg_num_mask;
 	addr = (phy_id << 11) | (idx << 6) | MII_WRITE_ | MII_BUSY_;
-	ret = smsc95xx_write_reg(dev, MII_ADDR, addr);
-	check_warn_goto_done(ret, "Error writing MII_ADDR");
+	ret = __smsc95xx_write_reg(dev, MII_ADDR, addr, in_pm);
+	check_warn_goto_done(ret, "Error writing MII_ADDR\n");
 
-	ret = smsc95xx_phy_wait_not_busy(dev);
-	check_warn_goto_done(ret, "Timed out writing MII reg %02X", idx);
+	ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
+	check_warn_goto_done(ret, "Timed out writing MII reg %02X\n", idx);
 
 done:
 	mutex_unlock(&dev->phy_mutex);
 }
 
+static int smsc95xx_mdio_read_nopm(struct net_device *netdev, int phy_id,
+				   int idx)
+{
+	return __smsc95xx_mdio_read(netdev, phy_id, idx, 1);
+}
+
+static void smsc95xx_mdio_write_nopm(struct net_device *netdev, int phy_id,
+				     int idx, int regval)
+{
+	__smsc95xx_mdio_write(netdev, phy_id, idx, regval, 1);
+}
+
+static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
+{
+	return __smsc95xx_mdio_read(netdev, phy_id, idx, 0);
+}
+
+static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
+				int regval)
+{
+	__smsc95xx_mdio_write(netdev, phy_id, idx, regval, 0);
+}
+
 static int __must_check smsc95xx_wait_eeprom(struct usbnet *dev)
 {
 	unsigned long start_time = jiffies;
@@ -240,7 +288,7 @@ static int __must_check smsc95xx_wait_eeprom(struct usbnet *dev)
 
 	do {
 		ret = smsc95xx_read_reg(dev, E2P_CMD, &val);
-		check_warn_return(ret, "Error reading E2P_CMD");
+		check_warn_return(ret, "Error reading E2P_CMD\n");
 		if (!(val & E2P_CMD_BUSY_) || (val & E2P_CMD_TIMEOUT_))
 			break;
 		udelay(40);
@@ -262,7 +310,7 @@ static int __must_check smsc95xx_eeprom_confirm_not_busy(struct usbnet *dev)
 
 	do {
 		ret = smsc95xx_read_reg(dev, E2P_CMD, &val);
-		check_warn_return(ret, "Error reading E2P_CMD");
+		check_warn_return(ret, "Error reading E2P_CMD\n");
 
 		if (!(val & E2P_CMD_BUSY_))
 			return 0;
@@ -290,14 +338,14 @@ static int smsc95xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length,
 	for (i = 0; i < length; i++) {
 		val = E2P_CMD_BUSY_ | E2P_CMD_READ_ | (offset & E2P_CMD_ADDR_);
 		ret = smsc95xx_write_reg(dev, E2P_CMD, val);
-		check_warn_return(ret, "Error writing E2P_CMD");
+		check_warn_return(ret, "Error writing E2P_CMD\n");
 
 		ret = smsc95xx_wait_eeprom(dev);
 		if (ret < 0)
 			return ret;
 
 		ret = smsc95xx_read_reg(dev, E2P_DATA, &val);
-		check_warn_return(ret, "Error reading E2P_DATA");
+		check_warn_return(ret, "Error reading E2P_DATA\n");
 
 		data[i] = val & 0xFF;
 		offset++;
@@ -322,7 +370,7 @@ static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
 	/* Issue write/erase enable command */
 	val = E2P_CMD_BUSY_ | E2P_CMD_EWEN_;
 	ret = smsc95xx_write_reg(dev, E2P_CMD, val);
-	check_warn_return(ret, "Error writing E2P_DATA");
+	check_warn_return(ret, "Error writing E2P_DATA\n");
 
 	ret = smsc95xx_wait_eeprom(dev);
 	if (ret < 0)
@@ -333,12 +381,12 @@ static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
 		/* Fill data register */
 		val = data[i];
 		ret = smsc95xx_write_reg(dev, E2P_DATA, val);
-		check_warn_return(ret, "Error writing E2P_DATA");
+		check_warn_return(ret, "Error writing E2P_DATA\n");
 
 		/* Send "write" command */
 		val = E2P_CMD_BUSY_ | E2P_CMD_WRITE_ | (offset & E2P_CMD_ADDR_);
 		ret = smsc95xx_write_reg(dev, E2P_CMD, val);
-		check_warn_return(ret, "Error writing E2P_CMD");
+		check_warn_return(ret, "Error writing E2P_CMD\n");
 
 		ret = smsc95xx_wait_eeprom(dev);
 		if (ret < 0)
@@ -350,60 +398,20 @@ static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
 	return 0;
 }
 
-static void smsc95xx_async_cmd_callback(struct urb *urb)
-{
-	struct usb_context *usb_context = urb->context;
-	struct usbnet *dev = usb_context->dev;
-	int status = urb->status;
-
-	check_warn(status, "async callback failed with %d\n", status);
-
-	kfree(usb_context);
-	usb_free_urb(urb);
-}
-
 static int __must_check smsc95xx_write_reg_async(struct usbnet *dev, u16 index,
 						 u32 *data)
 {
-	struct usb_context *usb_context;
-	int status;
-	struct urb *urb;
 	const u16 size = 4;
+	int ret;
 
-	urb = usb_alloc_urb(0, GFP_ATOMIC);
-	if (!urb) {
-		netdev_warn(dev->net, "Error allocating URB\n");
-		return -ENOMEM;
-	}
-
-	usb_context = kmalloc(sizeof(struct usb_context), GFP_ATOMIC);
-	if (usb_context == NULL) {
-		netdev_warn(dev->net, "Error allocating control msg\n");
-		usb_free_urb(urb);
-		return -ENOMEM;
-	}
-
-	usb_context->req.bRequestType =
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-	usb_context->req.bRequest = USB_VENDOR_REQUEST_WRITE_REGISTER;
-	usb_context->req.wValue = 00;
-	usb_context->req.wIndex = cpu_to_le16(index);
-	usb_context->req.wLength = cpu_to_le16(size);
-
-	usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0),
-		(void *)&usb_context->req, data, size,
-		smsc95xx_async_cmd_callback,
-		(void *)usb_context);
-
-	status = usb_submit_urb(urb, GFP_ATOMIC);
-	if (status < 0) {
-		netdev_warn(dev->net, "Error submitting control msg, sts=%d\n",
-			    status);
-		kfree(usb_context);
-		usb_free_urb(urb);
-	}
-
-	return status;
+	ret = usbnet_write_cmd_async(dev, USB_VENDOR_REQUEST_WRITE_REGISTER,
+				     USB_DIR_OUT | USB_TYPE_VENDOR |
+				     USB_RECIP_DEVICE,
+				     0, index, data, size);
+	if (ret < 0)
+		netdev_warn(dev->net, "Error write async cmd, sts=%d\n",
+			    ret);
+	return ret;
 }
 
 /* returns hash bit number for given MAC address
@@ -461,13 +469,13 @@ static void smsc95xx_set_multicast(struct net_device *netdev)
 
 	/* Initiate async writes, as we can't wait for completion here */
 	ret = smsc95xx_write_reg_async(dev, HASHH, &pdata->hash_hi);
-	check_warn(ret, "failed to initiate async write to HASHH");
+	check_warn(ret, "failed to initiate async write to HASHH\n");
 
 	ret = smsc95xx_write_reg_async(dev, HASHL, &pdata->hash_lo);
-	check_warn(ret, "failed to initiate async write to HASHL");
+	check_warn(ret, "failed to initiate async write to HASHL\n");
 
 	ret = smsc95xx_write_reg_async(dev, MAC_CR, &pdata->mac_cr);
-	check_warn(ret, "failed to initiate async write to MAC_CR");
+	check_warn(ret, "failed to initiate async write to MAC_CR\n");
 }
 
 static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
@@ -476,7 +484,7 @@ static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
 	u32 flow, afc_cfg = 0;
 
 	int ret = smsc95xx_read_reg(dev, AFC_CFG, &afc_cfg);
-	check_warn_return(ret, "Error reading AFC_CFG");
+	check_warn_return(ret, "Error reading AFC_CFG\n");
 
 	if (duplex == DUPLEX_FULL) {
 		u8 cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
@@ -501,10 +509,10 @@ static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
 	}
 
 	ret = smsc95xx_write_reg(dev, FLOW, flow);
-	check_warn_return(ret, "Error writing FLOW");
+	check_warn_return(ret, "Error writing FLOW\n");
 
 	ret = smsc95xx_write_reg(dev, AFC_CFG, afc_cfg);
-	check_warn_return(ret, "Error writing AFC_CFG");
+	check_warn_return(ret, "Error writing AFC_CFG\n");
 
 	return 0;
 }
@@ -520,10 +528,10 @@ static int smsc95xx_link_reset(struct usbnet *dev)
 
 	/* clear interrupt status */
 	ret = smsc95xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC);
-	check_warn_return(ret, "Error reading PHY_INT_SRC");
+	check_warn_return(ret, "Error reading PHY_INT_SRC\n");
 
 	ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
-	check_warn_return(ret, "Error writing INT_STS");
+	check_warn_return(ret, "Error writing INT_STS\n");
 
 	mii_check_media(mii, 1, 1);
 	mii_ethtool_gset(&dev->mii, &ecmd);
@@ -545,10 +553,10 @@ static int smsc95xx_link_reset(struct usbnet *dev)
 	spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
 
 	ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
-	check_warn_return(ret, "Error writing MAC_CR");
+	check_warn_return(ret, "Error writing MAC_CR\n");
 
 	ret = smsc95xx_phy_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv);
-	check_warn_return(ret, "Error updating PHY flow control");
+	check_warn_return(ret, "Error updating PHY flow control\n");
 
 	return 0;
 }
@@ -765,7 +773,7 @@ static int smsc95xx_start_tx_path(struct usbnet *dev)
 }
 
 /* Starts the Receive path */
-static int smsc95xx_start_rx_path(struct usbnet *dev)
+static int smsc95xx_start_rx_path(struct usbnet *dev, int in_pm)
 {
 	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
 	unsigned long flags;
@@ -775,7 +783,7 @@ static int smsc95xx_start_rx_path(struct usbnet *dev)
 	pdata->mac_cr |= MAC_CR_RXEN_;
 	spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
 
-	ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
+	ret = __smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr, in_pm);
 	check_warn_return(ret, "Failed to write MAC_CR: %d\n", ret);
 
 	return 0;
@@ -813,7 +821,7 @@ static int smsc95xx_phy_initialize(struct usbnet *dev)
 
 	/* read to clear */
 	ret = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
-	check_warn_return(ret, "Failed to read PHY_INT_SRC during init");
+	check_warn_return(ret, "Failed to read PHY_INT_SRC during init\n");
 
 	smsc95xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK,
 		PHY_INT_MASK_DEFAULT_);
@@ -867,14 +875,14 @@ static int smsc95xx_reset(struct usbnet *dev)
 	if (ret < 0)
 		return ret;
 
-	netif_dbg(dev, ifup, dev->net,
-		  "MAC Address: %pM\n", dev->net->dev_addr);
+	netif_dbg(dev, ifup, dev->net, "MAC Address: %pM\n",
+		  dev->net->dev_addr);
 
 	ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
 	check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
 
-	netif_dbg(dev, ifup, dev->net,
-		  "Read Value from HW_CFG : 0x%08x\n", read_buf);
+	netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG : 0x%08x\n",
+		  read_buf);
 
 	read_buf |= HW_CFG_BIR_;
 
@@ -898,8 +906,8 @@ static int smsc95xx_reset(struct usbnet *dev)
 		dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
 	}
 
-	netif_dbg(dev, ifup, dev->net,
-		  "rx_urb_size=%ld\n", (ulong)dev->rx_urb_size);
+	netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n",
+		  (ulong)dev->rx_urb_size);
 
 	ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap);
 	check_warn_return(ret, "Failed to write BURST_CAP: %d\n", ret);
@@ -924,8 +932,8 @@ static int smsc95xx_reset(struct usbnet *dev)
 	ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
 	check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
 
-	netif_dbg(dev, ifup, dev->net,
-		  "Read Value from HW_CFG: 0x%08x\n", read_buf);
+	netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG: 0x%08x\n",
+		  read_buf);
 
 	if (turbo_mode)
 		read_buf |= (HW_CFG_MEF_ | HW_CFG_BCE_);
@@ -975,12 +983,12 @@ static int smsc95xx_reset(struct usbnet *dev)
 
 	/* Enable or disable checksum offload engines */
 	ret = smsc95xx_set_features(dev->net, dev->net->features);
-	check_warn_return(ret, "Failed to set checksum offload features");
+	check_warn_return(ret, "Failed to set checksum offload features\n");
 
 	smsc95xx_set_multicast(dev->net);
 
 	ret = smsc95xx_phy_initialize(dev);
-	check_warn_return(ret, "Failed to init PHY");
+	check_warn_return(ret, "Failed to init PHY\n");
 
 	ret = smsc95xx_read_reg(dev, INT_EP_CTL, &read_buf);
 	check_warn_return(ret, "Failed to read INT_EP_CTL: %d\n", ret);
@@ -992,10 +1000,10 @@ static int smsc95xx_reset(struct usbnet *dev)
 	check_warn_return(ret, "Failed to write INT_EP_CTL: %d\n", ret);
 
 	ret = smsc95xx_start_tx_path(dev);
-	check_warn_return(ret, "Failed to start TX path");
+	check_warn_return(ret, "Failed to start TX path\n");
 
-	ret = smsc95xx_start_rx_path(dev);
-	check_warn_return(ret, "Failed to start RX path");
+	ret = smsc95xx_start_rx_path(dev, 0);
+	check_warn_return(ret, "Failed to start RX path\n");
 
 	netif_dbg(dev, ifup, dev->net, "smsc95xx_reset, return 0\n");
 	return 0;
@@ -1017,6 +1025,7 @@ static const struct net_device_ops smsc95xx_netdev_ops = {
 static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	struct smsc95xx_priv *pdata = NULL;
+	u32 val;
 	int ret;
 
 	printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n");
@@ -1047,6 +1056,19 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
 	/* Init all registers */
 	ret = smsc95xx_reset(dev);
 
+	/* detect device revision as different features may be available */
+	ret = smsc95xx_read_reg(dev, ID_REV, &val);
+	check_warn_return(ret, "Failed to read ID_REV: %d\n", ret);
+	val >>= 16;
+
+	if ((val == ID_REV_CHIP_ID_9500A_) || (val == ID_REV_CHIP_ID_9530_) ||
+	    (val == ID_REV_CHIP_ID_89530_) || (val == ID_REV_CHIP_ID_9730_))
+		pdata->features = (FEATURE_8_WAKEUP_FILTERS |
+			FEATURE_PHY_NLP_CROSSOVER |
+			FEATURE_AUTOSUSPEND);
+	else if (val == ID_REV_CHIP_ID_9512_)
+		pdata->features = FEATURE_8_WAKEUP_FILTERS;
+
 	dev->net->netdev_ops = &smsc95xx_netdev_ops;
 	dev->net->ethtool_ops = &smsc95xx_ethtool_ops;
 	dev->net->flags |= IFF_MULTICAST;
@@ -1066,113 +1088,349 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
 	}
 }
 
+static u16 smsc_crc(const u8 *buffer, size_t len, int filter)
+{
+	return bitrev16(crc16(0xFFFF, buffer, len)) << ((filter % 2) * 16);
+}
+
+static int smsc95xx_enable_phy_wakeup_interrupts(struct usbnet *dev, u16 mask)
+{
+	struct mii_if_info *mii = &dev->mii;
+	int ret;
+
+	netdev_dbg(dev->net, "enabling PHY wakeup interrupts\n");
+
+	/* read to clear */
+	ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_SRC);
+	check_warn_return(ret, "Error reading PHY_INT_SRC\n");
+
+	/* enable interrupt source */
+	ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_MASK);
+	check_warn_return(ret, "Error reading PHY_INT_MASK\n");
+
+	ret |= mask;
+
+	smsc95xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_INT_MASK, ret);
+
+	return 0;
+}
+
+static int smsc95xx_link_ok_nopm(struct usbnet *dev)
+{
+	struct mii_if_info *mii = &dev->mii;
+	int ret;
+
+	/* first, a dummy read, needed to latch some MII phys */
+	ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
+	check_warn_return(ret, "Error reading MII_BMSR\n");
+
+	ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
+	check_warn_return(ret, "Error reading MII_BMSR\n");
+
+	return !!(ret & BMSR_LSTATUS);
+}
+
+static int smsc95xx_enter_suspend0(struct usbnet *dev)
+{
+	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	u32 val;
+	int ret;
+
+	ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+	check_warn_return(ret, "Error reading PM_CTRL\n");
+
+	val &= (~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_));
+	val |= PM_CTL_SUS_MODE_0;
+
+	ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+	check_warn_return(ret, "Error writing PM_CTRL\n");
+
+	/* clear wol status */
+	val &= ~PM_CTL_WUPS_;
+	val |= PM_CTL_WUPS_WOL_;
+
+	/* enable energy detection */
+	if (pdata->wolopts & WAKE_PHY)
+		val |= PM_CTL_WUPS_ED_;
+
+	ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+	check_warn_return(ret, "Error writing PM_CTRL\n");
+
+	/* read back PM_CTRL */
+	ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+	check_warn_return(ret, "Error reading PM_CTRL\n");
+
+	smsc95xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+
+	return 0;
+}
+
+static int smsc95xx_enter_suspend1(struct usbnet *dev)
+{
+	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct mii_if_info *mii = &dev->mii;
+	u32 val;
+	int ret;
+
+	/* reconfigure link pulse detection timing for
+	 * compatibility with non-standard link partners
+	 */
+	if (pdata->features & FEATURE_PHY_NLP_CROSSOVER)
+		smsc95xx_mdio_write_nopm(dev->net, mii->phy_id,	PHY_EDPD_CONFIG,
+			PHY_EDPD_CONFIG_DEFAULT);
+
+	/* enable energy detect power-down mode */
+	ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_MODE_CTRL_STS);
+	check_warn_return(ret, "Error reading PHY_MODE_CTRL_STS\n");
+
+	ret |= MODE_CTRL_STS_EDPWRDOWN_;
+
+	smsc95xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_MODE_CTRL_STS, ret);
+
+	/* enter SUSPEND1 mode */
+	ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+	check_warn_return(ret, "Error reading PM_CTRL\n");
+
+	val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
+	val |= PM_CTL_SUS_MODE_1;
+
+	ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+	check_warn_return(ret, "Error writing PM_CTRL\n");
+
+	/* clear wol status, enable energy detection */
+	val &= ~PM_CTL_WUPS_;
+	val |= (PM_CTL_WUPS_ED_ | PM_CTL_ED_EN_);
+
+	ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+	check_warn_return(ret, "Error writing PM_CTRL\n");
+
+	smsc95xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+
+	return 0;
+}
+
+static int smsc95xx_enter_suspend2(struct usbnet *dev)
+{
+	u32 val;
+	int ret;
+
+	ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+	check_warn_return(ret, "Error reading PM_CTRL\n");
+
+	val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
+	val |= PM_CTL_SUS_MODE_2;
+
+	ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+	check_warn_return(ret, "Error writing PM_CTRL\n");
+
+	return 0;
+}
+
 static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct usbnet *dev = usb_get_intfdata(intf);
 	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	u32 val, link_up;
 	int ret;
-	u32 val;
 
 	ret = usbnet_suspend(intf, message);
-	check_warn_return(ret, "usbnet_suspend error");
+	check_warn_return(ret, "usbnet_suspend error\n");
+
+	/* determine if link is up using only _nopm functions */
+	link_up = smsc95xx_link_ok_nopm(dev);
 
-	/* if no wol options set, enter lowest power SUSPEND2 mode */
-	if (!(pdata->wolopts & SUPPORTED_WAKE)) {
-		netdev_info(dev->net, "entering SUSPEND2 mode");
+	/* if no wol options set, or if link is down and we're not waking on
+	 * PHY activity, enter lowest power SUSPEND2 mode
+	 */
+	if (!(pdata->wolopts & SUPPORTED_WAKE) ||
+		!(link_up || (pdata->wolopts & WAKE_PHY))) {
+		netdev_info(dev->net, "entering SUSPEND2 mode\n");
 
 		/* disable energy detect (link up) & wake up events */
-		ret = smsc95xx_read_reg(dev, WUCSR, &val);
-		check_warn_return(ret, "Error reading WUCSR");
+		ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
+		check_warn_return(ret, "Error reading WUCSR\n");
 
 		val &= ~(WUCSR_MPEN_ | WUCSR_WAKE_EN_);
 
-		ret = smsc95xx_write_reg(dev, WUCSR, val);
-		check_warn_return(ret, "Error writing WUCSR");
+		ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
+		check_warn_return(ret, "Error writing WUCSR\n");
 
-		ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
-		check_warn_return(ret, "Error reading PM_CTRL");
+		ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+		check_warn_return(ret, "Error reading PM_CTRL\n");
 
 		val &= ~(PM_CTL_ED_EN_ | PM_CTL_WOL_EN_);
 
-		ret = smsc95xx_write_reg(dev, PM_CTRL, val);
-		check_warn_return(ret, "Error writing PM_CTRL");
+		ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+		check_warn_return(ret, "Error writing PM_CTRL\n");
 
-		/* enter suspend2 mode */
-		ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
-		check_warn_return(ret, "Error reading PM_CTRL");
+		return smsc95xx_enter_suspend2(dev);
+	}
 
-		val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
-		val |= PM_CTL_SUS_MODE_2;
+	if (pdata->wolopts & WAKE_PHY) {
+		ret = smsc95xx_enable_phy_wakeup_interrupts(dev,
+			(PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_LINK_DOWN_));
+		check_warn_return(ret, "error enabling PHY wakeup ints\n");
+
+		/* if link is down then configure EDPD and enter SUSPEND1,
+		 * otherwise enter SUSPEND0 below
+		 */
+		if (!link_up) {
+			netdev_info(dev->net, "entering SUSPEND1 mode\n");
+			return smsc95xx_enter_suspend1(dev);
+		}
+	}
 
-		ret = smsc95xx_write_reg(dev, PM_CTRL, val);
-		check_warn_return(ret, "Error writing PM_CTRL");
+	if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) {
+		u32 *filter_mask = kzalloc(32, GFP_KERNEL);
+		u32 command[2];
+		u32 offset[2];
+		u32 crc[4];
+		int wuff_filter_count =
+			(pdata->features & FEATURE_8_WAKEUP_FILTERS) ?
+			LAN9500A_WUFF_NUM : LAN9500_WUFF_NUM;
+		int i, filter = 0;
+
+		memset(command, 0, sizeof(command));
+		memset(offset, 0, sizeof(offset));
+		memset(crc, 0, sizeof(crc));
+
+		if (pdata->wolopts & WAKE_BCAST) {
+			const u8 bcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+			netdev_info(dev->net, "enabling broadcast detection\n");
+			filter_mask[filter * 4] = 0x003F;
+			filter_mask[filter * 4 + 1] = 0x00;
+			filter_mask[filter * 4 + 2] = 0x00;
+			filter_mask[filter * 4 + 3] = 0x00;
+			command[filter/4] |= 0x05UL << ((filter % 4) * 8);
+			offset[filter/4] |= 0x00 << ((filter % 4) * 8);
+			crc[filter/2] |= smsc_crc(bcast, 6, filter);
+			filter++;
+		}
 
-		return 0;
+		if (pdata->wolopts & WAKE_MCAST) {
+			const u8 mcast[] = {0x01, 0x00, 0x5E};
+			netdev_info(dev->net, "enabling multicast detection\n");
+			filter_mask[filter * 4] = 0x0007;
+			filter_mask[filter * 4 + 1] = 0x00;
+			filter_mask[filter * 4 + 2] = 0x00;
+			filter_mask[filter * 4 + 3] = 0x00;
+			command[filter/4] |= 0x09UL << ((filter % 4) * 8);
+			offset[filter/4] |= 0x00  << ((filter % 4) * 8);
+			crc[filter/2] |= smsc_crc(mcast, 3, filter);
+			filter++;
+		}
+
+		if (pdata->wolopts & WAKE_ARP) {
+			const u8 arp[] = {0x08, 0x06};
+			netdev_info(dev->net, "enabling ARP detection\n");
+			filter_mask[filter * 4] = 0x0003;
+			filter_mask[filter * 4 + 1] = 0x00;
+			filter_mask[filter * 4 + 2] = 0x00;
+			filter_mask[filter * 4 + 3] = 0x00;
+			command[filter/4] |= 0x05UL << ((filter % 4) * 8);
+			offset[filter/4] |= 0x0C << ((filter % 4) * 8);
+			crc[filter/2] |= smsc_crc(arp, 2, filter);
+			filter++;
+		}
+
+		if (pdata->wolopts & WAKE_UCAST) {
+			netdev_info(dev->net, "enabling unicast detection\n");
+			filter_mask[filter * 4] = 0x003F;
+			filter_mask[filter * 4 + 1] = 0x00;
+			filter_mask[filter * 4 + 2] = 0x00;
+			filter_mask[filter * 4 + 3] = 0x00;
+			command[filter/4] |= 0x01UL << ((filter % 4) * 8);
+			offset[filter/4] |= 0x00 << ((filter % 4) * 8);
+			crc[filter/2] |= smsc_crc(dev->net->dev_addr, ETH_ALEN, filter);
+			filter++;
+		}
+
+		for (i = 0; i < (wuff_filter_count * 4); i++) {
+			ret = smsc95xx_write_reg_nopm(dev, WUFF, filter_mask[i]);
+			if (ret < 0)
+				kfree(filter_mask);
+			check_warn_return(ret, "Error writing WUFF\n");
+		}
+		kfree(filter_mask);
+
+		for (i = 0; i < (wuff_filter_count / 4); i++) {
+			ret = smsc95xx_write_reg_nopm(dev, WUFF, command[i]);
+			check_warn_return(ret, "Error writing WUFF\n");
+		}
+
+		for (i = 0; i < (wuff_filter_count / 4); i++) {
+			ret = smsc95xx_write_reg_nopm(dev, WUFF, offset[i]);
+			check_warn_return(ret, "Error writing WUFF\n");
+		}
+
+		for (i = 0; i < (wuff_filter_count / 2); i++) {
+			ret = smsc95xx_write_reg_nopm(dev, WUFF, crc[i]);
+			check_warn_return(ret, "Error writing WUFF\n");
+		}
+
+		/* clear any pending pattern match packet status */
+		ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
+		check_warn_return(ret, "Error reading WUCSR\n");
+
+		val |= WUCSR_WUFR_;
+
+		ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
+		check_warn_return(ret, "Error writing WUCSR\n");
 	}
 
 	if (pdata->wolopts & WAKE_MAGIC) {
 		/* clear any pending magic packet status */
-		ret = smsc95xx_read_reg(dev, WUCSR, &val);
-		check_warn_return(ret, "Error reading WUCSR");
+		ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
+		check_warn_return(ret, "Error reading WUCSR\n");
 
 		val |= WUCSR_MPR_;
 
-		ret = smsc95xx_write_reg(dev, WUCSR, val);
-		check_warn_return(ret, "Error writing WUCSR");
+		ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
+		check_warn_return(ret, "Error writing WUCSR\n");
 	}
 
-	/* enable/disable magic packup wake */
-	ret = smsc95xx_read_reg(dev, WUCSR, &val);
-	check_warn_return(ret, "Error reading WUCSR");
+	/* enable/disable wakeup sources */
+	ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
+	check_warn_return(ret, "Error reading WUCSR\n");
+
+	if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) {
+		netdev_info(dev->net, "enabling pattern match wakeup\n");
+		val |= WUCSR_WAKE_EN_;
+	} else {
+		netdev_info(dev->net, "disabling pattern match wakeup\n");
+		val &= ~WUCSR_WAKE_EN_;
+	}
 
 	if (pdata->wolopts & WAKE_MAGIC) {
-		netdev_info(dev->net, "enabling magic packet wakeup");
+		netdev_info(dev->net, "enabling magic packet wakeup\n");
 		val |= WUCSR_MPEN_;
 	} else {
-		netdev_info(dev->net, "disabling magic packet wakeup");
+		netdev_info(dev->net, "disabling magic packet wakeup\n");
 		val &= ~WUCSR_MPEN_;
 	}
 
-	ret = smsc95xx_write_reg(dev, WUCSR, val);
-	check_warn_return(ret, "Error writing WUCSR");
+	ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
+	check_warn_return(ret, "Error writing WUCSR\n");
 
 	/* enable wol wakeup source */
-	ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
-	check_warn_return(ret, "Error reading PM_CTRL");
+	ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+	check_warn_return(ret, "Error reading PM_CTRL\n");
 
 	val |= PM_CTL_WOL_EN_;
 
-	ret = smsc95xx_write_reg(dev, PM_CTRL, val);
-	check_warn_return(ret, "Error writing PM_CTRL");
-
-	/* enable receiver */
-	smsc95xx_start_rx_path(dev);
-
-	/* some wol options are enabled, so enter SUSPEND0 */
-	netdev_info(dev->net, "entering SUSPEND0 mode");
-
-	ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
-	check_warn_return(ret, "Error reading PM_CTRL");
-
-	val &= (~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_));
-	val |= PM_CTL_SUS_MODE_0;
-
-	ret = smsc95xx_write_reg(dev, PM_CTRL, val);
-	check_warn_return(ret, "Error writing PM_CTRL");
-
-	/* clear wol status */
-	val &= ~PM_CTL_WUPS_;
-	val |= PM_CTL_WUPS_WOL_;
-	ret = smsc95xx_write_reg(dev, PM_CTRL, val);
-	check_warn_return(ret, "Error writing PM_CTRL");
+	/* phy energy detect wakeup source */
+	if (pdata->wolopts & WAKE_PHY)
+		val |= PM_CTL_ED_EN_;
 
-	/* read back PM_CTRL */
-	ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
-	check_warn_return(ret, "Error reading PM_CTRL");
+	ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+	check_warn_return(ret, "Error writing PM_CTRL\n");
 
-	smsc95xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+	/* enable receiver to enable frame reception */
+	smsc95xx_start_rx_path(dev, 1);
 
-	return 0;
+	/* some wol options are enabled, so enter SUSPEND0 */
+	netdev_info(dev->net, "entering SUSPEND0 mode\n");
+	return smsc95xx_enter_suspend0(dev);
 }
 
 static int smsc95xx_resume(struct usb_interface *intf)
@@ -1184,31 +1442,31 @@ static int smsc95xx_resume(struct usb_interface *intf)
 
 	BUG_ON(!dev);
 
-	if (pdata->wolopts & WAKE_MAGIC) {
+	if (pdata->wolopts) {
 		smsc95xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
 
-		/* Disable magic packup wake */
-		ret = smsc95xx_read_reg(dev, WUCSR, &val);
-		check_warn_return(ret, "Error reading WUCSR");
+		/* clear wake-up sources */
+		ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
+		check_warn_return(ret, "Error reading WUCSR\n");
 
-		val &= ~WUCSR_MPEN_;
+		val &= ~(WUCSR_WAKE_EN_ | WUCSR_MPEN_);
 
-		ret = smsc95xx_write_reg(dev, WUCSR, val);
-		check_warn_return(ret, "Error writing WUCSR");
+		ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
+		check_warn_return(ret, "Error writing WUCSR\n");
 
 		/* clear wake-up status */
-		ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
-		check_warn_return(ret, "Error reading PM_CTRL");
+		ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+		check_warn_return(ret, "Error reading PM_CTRL\n");
 
 		val &= ~PM_CTL_WOL_EN_;
 		val |= PM_CTL_WUPS_;
 
-		ret = smsc95xx_write_reg(dev, PM_CTRL, val);
-		check_warn_return(ret, "Error writing PM_CTRL");
+		ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+		check_warn_return(ret, "Error writing PM_CTRL\n");
 	}
 
-	return usbnet_resume(intf);
-	check_warn_return(ret, "usbnet_resume error");
+	ret = usbnet_resume(intf);
+	check_warn_return(ret, "usbnet_resume error\n");
 
 	return 0;
 }
diff --git a/drivers/net/usb/smsc95xx.h b/drivers/net/usb/smsc95xx.h
index 2ff9815..f360ee3 100644
--- a/drivers/net/usb/smsc95xx.h
+++ b/drivers/net/usb/smsc95xx.h
@@ -53,6 +53,11 @@
 #define ID_REV_CHIP_ID_MASK_		(0xFFFF0000)
 #define ID_REV_CHIP_REV_MASK_		(0x0000FFFF)
 #define ID_REV_CHIP_ID_9500_		(0x9500)
+#define ID_REV_CHIP_ID_9500A_		(0x9E00)
+#define ID_REV_CHIP_ID_9512_		(0xEC00)
+#define ID_REV_CHIP_ID_9530_		(0x9530)
+#define ID_REV_CHIP_ID_89530_		(0x9E08)
+#define ID_REV_CHIP_ID_9730_		(0x9730)
 
 #define INT_STS				(0x08)
 #define INT_STS_TX_STOP_		(0x00020000)
@@ -203,8 +208,11 @@
 #define VLAN2				(0x124)
 
 #define WUFF				(0x128)
+#define LAN9500_WUFF_NUM		(4)
+#define LAN9500A_WUFF_NUM		(8)
 
 #define WUCSR				(0x12C)
+#define WUCSR_WFF_PTR_RST_		(0x80000000)
 #define WUCSR_GUE_			(0x00000200)
 #define WUCSR_WUFR_			(0x00000040)
 #define WUCSR_MPR_			(0x00000020)
@@ -218,6 +226,23 @@
 
 /* Vendor-specific PHY Definitions */
 
+/* EDPD NLP / crossover time configuration (LAN9500A only) */
+#define PHY_EDPD_CONFIG			(16)
+#define PHY_EDPD_CONFIG_TX_NLP_EN_	((u16)0x8000)
+#define PHY_EDPD_CONFIG_TX_NLP_1000_	((u16)0x0000)
+#define PHY_EDPD_CONFIG_TX_NLP_768_	((u16)0x2000)
+#define PHY_EDPD_CONFIG_TX_NLP_512_	((u16)0x4000)
+#define PHY_EDPD_CONFIG_TX_NLP_256_	((u16)0x6000)
+#define PHY_EDPD_CONFIG_RX_1_NLP_	((u16)0x1000)
+#define PHY_EDPD_CONFIG_RX_NLP_64_	((u16)0x0000)
+#define PHY_EDPD_CONFIG_RX_NLP_256_	((u16)0x0400)
+#define PHY_EDPD_CONFIG_RX_NLP_512_	((u16)0x0800)
+#define PHY_EDPD_CONFIG_RX_NLP_1000_	((u16)0x0C00)
+#define PHY_EDPD_CONFIG_EXT_CROSSOVER_	((u16)0x0001)
+#define PHY_EDPD_CONFIG_DEFAULT		(PHY_EDPD_CONFIG_TX_NLP_EN_ | \
+					 PHY_EDPD_CONFIG_TX_NLP_768_ | \
+					 PHY_EDPD_CONFIG_RX_1_NLP_)
+
 /* Mode Control/Status Register */
 #define PHY_MODE_CTRL_STS		(17)
 #define MODE_CTRL_STS_EDPWRDOWN_	((u16)0x2000)
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index edb81ed..c04110b 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1616,6 +1616,202 @@ void usbnet_device_suggests_idle(struct usbnet *dev)
 EXPORT_SYMBOL(usbnet_device_suggests_idle);
 
 /*-------------------------------------------------------------------------*/
+static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+			     u16 value, u16 index, void *data, u16 size)
+{
+	void *buf = NULL;
+	int err = -ENOMEM;
+
+	netdev_dbg(dev->net, "usbnet_read_cmd cmd=0x%02x reqtype=%02x"
+		   " value=0x%04x index=0x%04x size=%d\n",
+		   cmd, reqtype, value, index, size);
+
+	if (data) {
+		buf = kmalloc(size, GFP_KERNEL);
+		if (!buf)
+			goto out;
+	}
+
+	err = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+			      cmd, reqtype, value, index, buf, size,
+			      USB_CTRL_GET_TIMEOUT);
+	if (err > 0 && err <= size)
+		memcpy(data, buf, err);
+	kfree(buf);
+out:
+	return err;
+}
+
+static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+			      u16 value, u16 index, const void *data,
+			      u16 size)
+{
+	void *buf = NULL;
+	int err = -ENOMEM;
+
+	netdev_dbg(dev->net, "usbnet_write_cmd cmd=0x%02x reqtype=%02x"
+		   " value=0x%04x index=0x%04x size=%d\n",
+		   cmd, reqtype, value, index, size);
+
+	if (data) {
+		buf = kmemdup(data, size, GFP_KERNEL);
+		if (!buf)
+			goto out;
+	}
+
+	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+			      cmd, reqtype, value, index, buf, size,
+			      USB_CTRL_SET_TIMEOUT);
+	kfree(buf);
+
+out:
+	return err;
+}
+
+/*
+ * The function can't be called inside suspend/resume callback,
+ * otherwise deadlock will be caused.
+ */
+int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+		    u16 value, u16 index, void *data, u16 size)
+{
+	int ret;
+
+	if (usb_autopm_get_interface(dev->intf) < 0)
+		return -ENODEV;
+	ret = __usbnet_read_cmd(dev, cmd, reqtype, value, index,
+				data, size);
+	usb_autopm_put_interface(dev->intf);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(usbnet_read_cmd);
+
+/*
+ * The function can't be called inside suspend/resume callback,
+ * otherwise deadlock will be caused.
+ */
+int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+		     u16 value, u16 index, const void *data, u16 size)
+{
+	int ret;
+
+	if (usb_autopm_get_interface(dev->intf) < 0)
+		return -ENODEV;
+	ret = __usbnet_write_cmd(dev, cmd, reqtype, value, index,
+				 data, size);
+	usb_autopm_put_interface(dev->intf);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(usbnet_write_cmd);
+
+/*
+ * The function can be called inside suspend/resume callback safely
+ * and should only be called by suspend/resume callback generally.
+ */
+int usbnet_read_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
+			  u16 value, u16 index, void *data, u16 size)
+{
+	return __usbnet_read_cmd(dev, cmd, reqtype, value, index,
+				 data, size);
+}
+EXPORT_SYMBOL_GPL(usbnet_read_cmd_nopm);
+
+/*
+ * The function can be called inside suspend/resume callback safely
+ * and should only be called by suspend/resume callback generally.
+ */
+int usbnet_write_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
+			  u16 value, u16 index, const void *data,
+			  u16 size)
+{
+	return __usbnet_write_cmd(dev, cmd, reqtype, value, index,
+				  data, size);
+}
+EXPORT_SYMBOL_GPL(usbnet_write_cmd_nopm);
+
+static void usbnet_async_cmd_cb(struct urb *urb)
+{
+	struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
+	int status = urb->status;
+
+	if (status < 0)
+		dev_dbg(&urb->dev->dev, "%s failed with %d",
+			__func__, status);
+
+	kfree(req);
+	usb_free_urb(urb);
+}
+
+/*
+ * The caller must make sure that device can't be put into suspend
+ * state until the control URB completes.
+ */
+int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
+			   u16 value, u16 index, const void *data, u16 size)
+{
+	struct usb_ctrlrequest *req = NULL;
+	struct urb *urb;
+	int err = -ENOMEM;
+	void *buf = NULL;
+
+	netdev_dbg(dev->net, "usbnet_write_cmd cmd=0x%02x reqtype=%02x"
+		   " value=0x%04x index=0x%04x size=%d\n",
+		   cmd, reqtype, value, index, size);
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		netdev_err(dev->net, "Error allocating URB in"
+			   " %s!\n", __func__);
+		goto fail;
+	}
+
+	if (data) {
+		buf = kmemdup(data, size, GFP_ATOMIC);
+		if (!buf) {
+			netdev_err(dev->net, "Error allocating buffer"
+				   " in %s!\n", __func__);
+			goto fail_free;
+		}
+	}
+
+	req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
+	if (!req) {
+		netdev_err(dev->net, "Failed to allocate memory for %s\n",
+			   __func__);
+		goto fail_free_buf;
+	}
+
+	req->bRequestType = reqtype;
+	req->bRequest = cmd;
+	req->wValue = cpu_to_le16(value);
+	req->wIndex = cpu_to_le16(index);
+	req->wLength = cpu_to_le16(size);
+
+	usb_fill_control_urb(urb, dev->udev,
+			     usb_sndctrlpipe(dev->udev, 0),
+			     (void *)req, buf, size,
+			     usbnet_async_cmd_cb, req);
+	urb->transfer_flags |= URB_FREE_BUFFER;
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err < 0) {
+		netdev_err(dev->net, "Error submitting the control"
+			   " message: status=%d\n", err);
+		goto fail_free;
+	}
+	return 0;
+
+fail_free_buf:
+	kfree(buf);
+fail_free:
+	kfree(req);
+	usb_free_urb(urb);
+fail:
+	return err;
+
+}
+EXPORT_SYMBOL_GPL(usbnet_write_cmd_async);
+/*-------------------------------------------------------------------------*/
 
 static int __init usbnet_init(void)
 {
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index e522ff7..24f6b27 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -264,6 +264,7 @@ static void veth_setup(struct net_device *dev)
 	ether_setup(dev);
 
 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
 	dev->netdev_ops = &veth_netdev_ops;
 	dev->ethtool_ops = &veth_ethtool_ops;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index cbf8b06..97f4ff8 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -95,7 +95,6 @@ struct skb_vnet_hdr {
 		struct virtio_net_hdr hdr;
 		struct virtio_net_hdr_mrg_rxbuf mhdr;
 	};
-	unsigned int num_sg;
 };
 
 struct padded_vnet_hdr {
@@ -212,8 +211,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
 	 * the case of a broken device.
 	 */
 	if (unlikely(len > MAX_SKB_FRAGS * PAGE_SIZE)) {
-		if (net_ratelimit())
-			pr_debug("%s: too much data\n", skb->dev->name);
+		net_dbg_ratelimited("%s: too much data\n", skb->dev->name);
 		dev_kfree_skb(skb);
 		return NULL;
 	}
@@ -333,9 +331,8 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
 			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
 			break;
 		default:
-			if (net_ratelimit())
-				printk(KERN_WARNING "%s: bad gso type %u.\n",
-				       dev->name, hdr->hdr.gso_type);
+			net_warn_ratelimited("%s: bad gso type %u.\n",
+					     dev->name, hdr->hdr.gso_type);
 			goto frame_err;
 		}
 
@@ -344,9 +341,7 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
 
 		skb_shinfo(skb)->gso_size = hdr->hdr.gso_size;
 		if (skb_shinfo(skb)->gso_size == 0) {
-			if (net_ratelimit())
-				printk(KERN_WARNING "%s: zero gso size.\n",
-				       dev->name);
+			net_warn_ratelimited("%s: zero gso size.\n", dev->name);
 			goto frame_err;
 		}
 
@@ -472,10 +467,11 @@ static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
 			err = add_recvbuf_small(vi, gfp);
 
 		oom = err == -ENOMEM;
-		if (err < 0)
+		if (err)
 			break;
 		++vi->num;
-	} while (err > 0);
+	} while (vi->rvq->num_free);
+
 	if (unlikely(vi->num > vi->max))
 		vi->max = vi->num;
 	virtqueue_kick(vi->rvq);
@@ -557,10 +553,10 @@ again:
 	return received;
 }
 
-static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
+static void free_old_xmit_skbs(struct virtnet_info *vi)
 {
 	struct sk_buff *skb;
-	unsigned int len, tot_sgs = 0;
+	unsigned int len;
 	struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
 
 	while ((skb = virtqueue_get_buf(vi->svq, &len)) != NULL) {
@@ -571,16 +567,15 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
 		stats->tx_packets++;
 		u64_stats_update_end(&stats->tx_syncp);
 
-		tot_sgs += skb_vnet_hdr(skb)->num_sg;
 		dev_kfree_skb_any(skb);
 	}
-	return tot_sgs;
 }
 
 static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
 {
 	struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb);
 	const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
+	unsigned num_sg;
 
 	pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest);
 
@@ -619,35 +614,28 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
 	else
 		sg_set_buf(vi->tx_sg, &hdr->hdr, sizeof hdr->hdr);
 
-	hdr->num_sg = skb_to_sgvec(skb, vi->tx_sg + 1, 0, skb->len) + 1;
-	return virtqueue_add_buf(vi->svq, vi->tx_sg, hdr->num_sg,
+	num_sg = skb_to_sgvec(skb, vi->tx_sg + 1, 0, skb->len) + 1;
+	return virtqueue_add_buf(vi->svq, vi->tx_sg, num_sg,
 				 0, skb, GFP_ATOMIC);
 }
 
 static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct virtnet_info *vi = netdev_priv(dev);
-	int capacity;
+	int err;
 
 	/* Free up any pending old buffers before queueing new ones. */
 	free_old_xmit_skbs(vi);
 
 	/* Try to transmit */
-	capacity = xmit_skb(vi, skb);
-
-	/* This can happen with OOM and indirect buffers. */
-	if (unlikely(capacity < 0)) {
-		if (likely(capacity == -ENOMEM)) {
-			if (net_ratelimit())
-				dev_warn(&dev->dev,
-					 "TX queue failure: out of memory\n");
-		} else {
-			dev->stats.tx_fifo_errors++;
-			if (net_ratelimit())
-				dev_warn(&dev->dev,
-					 "Unexpected TX queue failure: %d\n",
-					 capacity);
-		}
+	err = xmit_skb(vi, skb);
+
+	/* This should not happen! */
+	if (unlikely(err)) {
+		dev->stats.tx_fifo_errors++;
+		if (net_ratelimit())
+			dev_warn(&dev->dev,
+				 "Unexpected TX queue failure: %d\n", err);
 		dev->stats.tx_dropped++;
 		kfree_skb(skb);
 		return NETDEV_TX_OK;
@@ -660,12 +648,12 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	/* Apparently nice girls don't return TX_BUSY; stop the queue
 	 * before it gets out of hand.  Naturally, this wastes entries. */
-	if (capacity < 2+MAX_SKB_FRAGS) {
+	if (vi->svq->num_free < 2+MAX_SKB_FRAGS) {
 		netif_stop_queue(dev);
 		if (unlikely(!virtqueue_enable_cb_delayed(vi->svq))) {
 			/* More just got used, free them then recheck. */
-			capacity += free_old_xmit_skbs(vi);
-			if (capacity >= 2+MAX_SKB_FRAGS) {
+			free_old_xmit_skbs(vi);
+			if (vi->svq->num_free >= 2+MAX_SKB_FRAGS) {
 				netif_start_queue(dev);
 				virtqueue_disable_cb(vi->svq);
 			}
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 0ae1bcc..e4a192b 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -1094,10 +1094,10 @@ vmxnet3_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 
-		BUG_ON(skb->queue_mapping > adapter->num_tx_queues);
-		return vmxnet3_tq_xmit(skb,
-				       &adapter->tx_queue[skb->queue_mapping],
-				       adapter, netdev);
+	BUG_ON(skb->queue_mapping > adapter->num_tx_queues);
+	return vmxnet3_tq_xmit(skb,
+			       &adapter->tx_queue[skb->queue_mapping],
+			       adapter, netdev);
 }
 
 
@@ -1243,8 +1243,8 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
 			skb_reserve(new_skb, NET_IP_ALIGN);
 			rbi->skb = new_skb;
 			rbi->dma_addr = pci_map_single(adapter->pdev,
-					rbi->skb->data, rbi->len,
-					PCI_DMA_FROMDEVICE);
+						       rbi->skb->data, rbi->len,
+						       PCI_DMA_FROMDEVICE);
 			rxd->addr = cpu_to_le64(rbi->dma_addr);
 			rxd->len = rbi->len;
 
@@ -1331,14 +1331,14 @@ rcd_done:
 		/* if needed, update the register */
 		if (unlikely(rq->shared->updateRxProd)) {
 			VMXNET3_WRITE_BAR0_REG(adapter,
-				rxprod_reg[ring_idx] + rq->qid * 8,
-				ring->next2fill);
+					       rxprod_reg[ring_idx] + rq->qid * 8,
+					       ring->next2fill);
 			rq->uncommitted[ring_idx] = 0;
 		}
 
 		vmxnet3_comp_ring_adv_next2proc(&rq->comp_ring);
 		vmxnet3_getRxComp(rcd,
-		     &rq->comp_ring.base[rq->comp_ring.next2proc].rcd, &rxComp);
+				  &rq->comp_ring.base[rq->comp_ring.next2proc].rcd, &rxComp);
 	}
 
 	return num_rxd;
@@ -1922,7 +1922,7 @@ vmxnet3_free_irqs(struct vmxnet3_adapter *adapter)
 		free_irq(adapter->pdev->irq, adapter->netdev);
 		break;
 	default:
-		BUG_ON(true);
+		BUG();
 	}
 }
 
@@ -2949,11 +2949,11 @@ vmxnet3_probe_device(struct pci_dev *pdev,
 
 	spin_lock_init(&adapter->cmd_lock);
 	adapter->shared = pci_alloc_consistent(adapter->pdev,
-			  sizeof(struct Vmxnet3_DriverShared),
-			  &adapter->shared_pa);
+					       sizeof(struct Vmxnet3_DriverShared),
+					       &adapter->shared_pa);
 	if (!adapter->shared) {
 		printk(KERN_ERR "Failed to allocate memory for %s\n",
-			pci_name(pdev));
+		       pci_name(pdev));
 		err = -ENOMEM;
 		goto err_alloc_shared;
 	}
@@ -2964,16 +2964,16 @@ vmxnet3_probe_device(struct pci_dev *pdev,
 	size = sizeof(struct Vmxnet3_TxQueueDesc) * adapter->num_tx_queues;
 	size += sizeof(struct Vmxnet3_RxQueueDesc) * adapter->num_rx_queues;
 	adapter->tqd_start = pci_alloc_consistent(adapter->pdev, size,
-			     &adapter->queue_desc_pa);
+						  &adapter->queue_desc_pa);
 
 	if (!adapter->tqd_start) {
 		printk(KERN_ERR "Failed to allocate memory for %s\n",
-			pci_name(pdev));
+		       pci_name(pdev));
 		err = -ENOMEM;
 		goto err_alloc_queue_desc;
 	}
 	adapter->rqd_start = (struct Vmxnet3_RxQueueDesc *)(adapter->tqd_start +
-							adapter->num_tx_queues);
+							    adapter->num_tx_queues);
 
 	adapter->pm_conf = kmalloc(sizeof(struct Vmxnet3_PMConf), GFP_KERNEL);
 	if (adapter->pm_conf == NULL) {
@@ -3019,7 +3019,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
 
 	adapter->dev_number = atomic_read(&devices_found);
 
-	 adapter->share_intr = irq_share_mode;
+	adapter->share_intr = irq_share_mode;
 	if (adapter->share_intr == VMXNET3_INTR_BUDDYSHARE &&
 	    adapter->num_tx_queues != adapter->num_rx_queues)
 		adapter->share_intr = VMXNET3_INTR_DONTSHARE;
@@ -3065,7 +3065,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
 
 	if (err) {
 		printk(KERN_ERR "Failed to register adapter %s\n",
-			pci_name(pdev));
+		       pci_name(pdev));
 		goto err_register;
 	}
 
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 8b5c619..ce77b8b 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -29,6 +29,8 @@
 #include <linux/etherdevice.h>
 #include <linux/if_ether.h>
 #include <linux/hash.h>
+#include <net/arp.h>
+#include <net/ndisc.h>
 #include <net/ip.h>
 #include <net/icmp.h>
 #include <net/udp.h>
@@ -110,18 +112,23 @@ struct vxlan_dev {
 	__u16		  port_max;
 	__u8		  tos;		/* TOS override */
 	__u8		  ttl;
-	bool		  learn;
+	u32		  flags;	/* VXLAN_F_* below */
 
 	unsigned long	  age_interval;
 	struct timer_list age_timer;
 	spinlock_t	  hash_lock;
 	unsigned int	  addrcnt;
 	unsigned int	  addrmax;
-	unsigned int	  addrexceeded;
 
 	struct hlist_head fdb_head[FDB_HASH_SIZE];
 };
 
+#define VXLAN_F_LEARN	0x01
+#define VXLAN_F_PROXY	0x02
+#define VXLAN_F_RSC	0x04
+#define VXLAN_F_L2MISS	0x08
+#define VXLAN_F_L3MISS	0x10
+
 /* salt for hash table */
 static u32 vxlan_salt __read_mostly;
 
@@ -155,6 +162,7 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
 	struct nda_cacheinfo ci;
 	struct nlmsghdr *nlh;
 	struct ndmsg *ndm;
+	bool send_ip, send_eth;
 
 	nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags);
 	if (nlh == NULL)
@@ -162,16 +170,24 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
 
 	ndm = nlmsg_data(nlh);
 	memset(ndm, 0, sizeof(*ndm));
-	ndm->ndm_family	= AF_BRIDGE;
+
+	send_eth = send_ip = true;
+
+	if (type == RTM_GETNEIGH) {
+		ndm->ndm_family	= AF_INET;
+		send_ip = fdb->remote_ip != 0;
+		send_eth = !is_zero_ether_addr(fdb->eth_addr);
+	} else
+		ndm->ndm_family	= AF_BRIDGE;
 	ndm->ndm_state = fdb->state;
 	ndm->ndm_ifindex = vxlan->dev->ifindex;
 	ndm->ndm_flags = NTF_SELF;
 	ndm->ndm_type = NDA_DST;
 
-	if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr))
+	if (send_eth && nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr))
 		goto nla_put_failure;
 
-	if (nla_put_be32(skb, NDA_DST, fdb->remote_ip))
+	if (send_ip && nla_put_be32(skb, NDA_DST, fdb->remote_ip))
 		goto nla_put_failure;
 
 	ci.ndm_used	 = jiffies_to_clock_t(now - fdb->used);
@@ -223,6 +239,29 @@ errout:
 		rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
 }
 
+static void vxlan_ip_miss(struct net_device *dev, __be32 ipa)
+{
+	struct vxlan_dev *vxlan = netdev_priv(dev);
+	struct vxlan_fdb f;
+
+	memset(&f, 0, sizeof f);
+	f.state = NUD_STALE;
+	f.remote_ip = ipa; /* goes to NDA_DST */
+
+	vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH);
+}
+
+static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN])
+{
+	struct vxlan_fdb	f;
+
+	memset(&f, 0, sizeof f);
+	f.state = NUD_STALE;
+	memcpy(f.eth_addr, eth_addr, ETH_ALEN);
+
+	vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH);
+}
+
 /* Hash Ethernet address */
 static u32 eth_hash(const unsigned char *addr)
 {
@@ -552,6 +591,8 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 		goto drop;
 	}
 
+	skb_reset_mac_header(skb);
+
 	/* Re-examine inner Ethernet packet */
 	oip = ip_hdr(skb);
 	skb->protocol = eth_type_trans(skb, vxlan->dev);
@@ -561,7 +602,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 			       vxlan->dev->dev_addr) == 0)
 		goto drop;
 
-	if (vxlan->learn)
+	if (vxlan->flags & VXLAN_F_LEARN)
 		vxlan_snoop(skb->dev, oip->saddr, eth_hdr(skb)->h_source);
 
 	__skb_tunnel_rx(skb, vxlan->dev);
@@ -600,6 +641,117 @@ drop:
 	return 0;
 }
 
+static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
+{
+	struct vxlan_dev *vxlan = netdev_priv(dev);
+	struct arphdr *parp;
+	u8 *arpptr, *sha;
+	__be32 sip, tip;
+	struct neighbour *n;
+
+	if (dev->flags & IFF_NOARP)
+		goto out;
+
+	if (!pskb_may_pull(skb, arp_hdr_len(dev))) {
+		dev->stats.tx_dropped++;
+		goto out;
+	}
+	parp = arp_hdr(skb);
+
+	if ((parp->ar_hrd != htons(ARPHRD_ETHER) &&
+	     parp->ar_hrd != htons(ARPHRD_IEEE802)) ||
+	    parp->ar_pro != htons(ETH_P_IP) ||
+	    parp->ar_op != htons(ARPOP_REQUEST) ||
+	    parp->ar_hln != dev->addr_len ||
+	    parp->ar_pln != 4)
+		goto out;
+	arpptr = (u8 *)parp + sizeof(struct arphdr);
+	sha = arpptr;
+	arpptr += dev->addr_len;	/* sha */
+	memcpy(&sip, arpptr, sizeof(sip));
+	arpptr += sizeof(sip);
+	arpptr += dev->addr_len;	/* tha */
+	memcpy(&tip, arpptr, sizeof(tip));
+
+	if (ipv4_is_loopback(tip) ||
+	    ipv4_is_multicast(tip))
+		goto out;
+
+	n = neigh_lookup(&arp_tbl, &tip, dev);
+
+	if (n) {
+		struct vxlan_dev *vxlan = netdev_priv(dev);
+		struct vxlan_fdb *f;
+		struct sk_buff	*reply;
+
+		if (!(n->nud_state & NUD_CONNECTED)) {
+			neigh_release(n);
+			goto out;
+		}
+
+		f = vxlan_find_mac(vxlan, n->ha);
+		if (f && f->remote_ip == 0) {
+			/* bridge-local neighbor */
+			neigh_release(n);
+			goto out;
+		}
+
+		reply = arp_create(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
+				n->ha, sha);
+
+		neigh_release(n);
+
+		skb_reset_mac_header(reply);
+		__skb_pull(reply, skb_network_offset(reply));
+		reply->ip_summed = CHECKSUM_UNNECESSARY;
+		reply->pkt_type = PACKET_HOST;
+
+		if (netif_rx_ni(reply) == NET_RX_DROP)
+			dev->stats.rx_dropped++;
+	} else if (vxlan->flags & VXLAN_F_L3MISS)
+		vxlan_ip_miss(dev, tip);
+out:
+	consume_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
+{
+	struct vxlan_dev *vxlan = netdev_priv(dev);
+	struct neighbour *n;
+	struct iphdr *pip;
+
+	if (is_multicast_ether_addr(eth_hdr(skb)->h_dest))
+		return false;
+
+	n = NULL;
+	switch (ntohs(eth_hdr(skb)->h_proto)) {
+	case ETH_P_IP:
+		if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+			return false;
+		pip = ip_hdr(skb);
+		n = neigh_lookup(&arp_tbl, &pip->daddr, dev);
+		break;
+	default:
+		return false;
+	}
+
+	if (n) {
+		bool diff;
+
+		diff = compare_ether_addr(eth_hdr(skb)->h_dest, n->ha) != 0;
+		if (diff) {
+			memcpy(eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
+				dev->addr_len);
+			memcpy(eth_hdr(skb)->h_dest, n->ha, dev->addr_len);
+		}
+		neigh_release(n);
+		return diff;
+	} else if (vxlan->flags & VXLAN_F_L3MISS)
+		vxlan_ip_miss(dev, pip->daddr);
+	return false;
+}
+
 /* Extract dsfield from inner protocol */
 static inline u8 vxlan_get_dsfield(const struct iphdr *iph,
 				   const struct sk_buff *skb)
@@ -622,22 +774,6 @@ static inline u8 vxlan_ecn_encap(u8 tos,
 	return INET_ECN_encapsulate(tos, inner);
 }
 
-static __be32 vxlan_find_dst(struct vxlan_dev *vxlan, struct sk_buff *skb)
-{
-	const struct ethhdr *eth = (struct ethhdr *) skb->data;
-	const struct vxlan_fdb *f;
-
-	if (is_multicast_ether_addr(eth->h_dest))
-		return vxlan->gaddr;
-
-	f = vxlan_find_mac(vxlan, eth->h_dest);
-	if (f)
-		return f->remote_ip;
-	else
-		return vxlan->gaddr;
-
-}
-
 static void vxlan_sock_free(struct sk_buff *skb)
 {
 	sock_put(skb->sk);
@@ -684,6 +820,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	struct rtable *rt;
 	const struct iphdr *old_iph;
+	struct ethhdr *eth;
 	struct iphdr *iph;
 	struct vxlanhdr *vxh;
 	struct udphdr *uh;
@@ -694,10 +831,50 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
 	__be16 df = 0;
 	__u8 tos, ttl;
 	int err;
+	bool did_rsc = false;
+	const struct vxlan_fdb *f;
+
+	skb_reset_mac_header(skb);
+	eth = eth_hdr(skb);
 
-	dst = vxlan_find_dst(vxlan, skb);
-	if (!dst)
+	if ((vxlan->flags & VXLAN_F_PROXY) && ntohs(eth->h_proto) == ETH_P_ARP)
+		return arp_reduce(dev, skb);
+	else if ((vxlan->flags&VXLAN_F_RSC) && ntohs(eth->h_proto) == ETH_P_IP)
+		did_rsc = route_shortcircuit(dev, skb);
+
+	f = vxlan_find_mac(vxlan, eth->h_dest);
+	if (f == NULL) {
+		did_rsc = false;
+		dst = vxlan->gaddr;
+		if (!dst && (vxlan->flags & VXLAN_F_L2MISS) &&
+		    !is_multicast_ether_addr(eth->h_dest))
+			vxlan_fdb_miss(vxlan, eth->h_dest);
+	} else
+		dst = f->remote_ip;
+
+	if (!dst) {
+		if (did_rsc) {
+			__skb_pull(skb, skb_network_offset(skb));
+			skb->ip_summed = CHECKSUM_NONE;
+			skb->pkt_type = PACKET_HOST;
+
+			/* short-circuited back to local bridge */
+			if (netif_rx(skb) == NET_RX_SUCCESS) {
+				struct vxlan_stats *stats =
+						this_cpu_ptr(vxlan->stats);
+
+				u64_stats_update_begin(&stats->syncp);
+				stats->tx_packets++;
+				stats->tx_bytes += pkt_len;
+				u64_stats_update_end(&stats->syncp);
+			} else {
+				dev->stats.tx_errors++;
+				dev->stats.tx_aborted_errors++;
+			}
+			return NETDEV_TX_OK;
+		}
 		goto drop;
+	}
 
 	/* Need space for new headers (invalidates iph ptr) */
 	if (skb_cow_head(skb, VXLAN_HEADROOM))
@@ -769,7 +946,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	vxlan_set_owner(dev, skb);
 
-	/* See __IPTUNNEL_XMIT */
+	/* See iptunnel_xmit() */
 	skb->ip_summed = CHECKSUM_NONE;
 	ip_select_ident(iph, &rt->dst, NULL);
 
@@ -1020,6 +1197,10 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
 	[IFLA_VXLAN_AGEING]	= { .type = NLA_U32 },
 	[IFLA_VXLAN_LIMIT]	= { .type = NLA_U32 },
 	[IFLA_VXLAN_PORT_RANGE] = { .len  = sizeof(struct ifla_vxlan_port_range) },
+	[IFLA_VXLAN_PROXY]	= { .type = NLA_U8 },
+	[IFLA_VXLAN_RSC]	= { .type = NLA_U8 },
+	[IFLA_VXLAN_L2MISS]	= { .type = NLA_U8 },
+	[IFLA_VXLAN_L3MISS]	= { .type = NLA_U8 },
 };
 
 static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -1111,14 +1292,29 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
 	if (data[IFLA_VXLAN_TOS])
 		vxlan->tos  = nla_get_u8(data[IFLA_VXLAN_TOS]);
 
+	if (data[IFLA_VXLAN_TTL])
+		vxlan->ttl = nla_get_u8(data[IFLA_VXLAN_TTL]);
+
 	if (!data[IFLA_VXLAN_LEARNING] || nla_get_u8(data[IFLA_VXLAN_LEARNING]))
-		vxlan->learn = true;
+		vxlan->flags |= VXLAN_F_LEARN;
 
 	if (data[IFLA_VXLAN_AGEING])
 		vxlan->age_interval = nla_get_u32(data[IFLA_VXLAN_AGEING]);
 	else
 		vxlan->age_interval = FDB_AGE_DEFAULT;
 
+	if (data[IFLA_VXLAN_PROXY] && nla_get_u8(data[IFLA_VXLAN_PROXY]))
+		vxlan->flags |= VXLAN_F_PROXY;
+
+	if (data[IFLA_VXLAN_RSC] && nla_get_u8(data[IFLA_VXLAN_RSC]))
+		vxlan->flags |= VXLAN_F_RSC;
+
+	if (data[IFLA_VXLAN_L2MISS] && nla_get_u8(data[IFLA_VXLAN_L2MISS]))
+		vxlan->flags |= VXLAN_F_L2MISS;
+
+	if (data[IFLA_VXLAN_L3MISS] && nla_get_u8(data[IFLA_VXLAN_L3MISS]))
+		vxlan->flags |= VXLAN_F_L3MISS;
+
 	if (data[IFLA_VXLAN_LIMIT])
 		vxlan->addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]);
 
@@ -1155,6 +1351,10 @@ static size_t vxlan_get_size(const struct net_device *dev)
 		nla_total_size(sizeof(__u8)) +	/* IFLA_VXLAN_TTL */
 		nla_total_size(sizeof(__u8)) +	/* IFLA_VXLAN_TOS */
 		nla_total_size(sizeof(__u8)) +	/* IFLA_VXLAN_LEARNING */
+		nla_total_size(sizeof(__u8)) +	/* IFLA_VXLAN_PROXY */
+		nla_total_size(sizeof(__u8)) +	/* IFLA_VXLAN_RSC */
+		nla_total_size(sizeof(__u8)) +	/* IFLA_VXLAN_L2MISS */
+		nla_total_size(sizeof(__u8)) +	/* IFLA_VXLAN_L3MISS */
 		nla_total_size(sizeof(__u32)) +	/* IFLA_VXLAN_AGEING */
 		nla_total_size(sizeof(__u32)) +	/* IFLA_VXLAN_LIMIT */
 		nla_total_size(sizeof(struct ifla_vxlan_port_range)) +
@@ -1183,7 +1383,15 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
 
 	if (nla_put_u8(skb, IFLA_VXLAN_TTL, vxlan->ttl) ||
 	    nla_put_u8(skb, IFLA_VXLAN_TOS, vxlan->tos) ||
-	    nla_put_u8(skb, IFLA_VXLAN_LEARNING, vxlan->learn) ||
+	    nla_put_u8(skb, IFLA_VXLAN_LEARNING,
+			!!(vxlan->flags & VXLAN_F_LEARN)) ||
+	    nla_put_u8(skb, IFLA_VXLAN_PROXY,
+			!!(vxlan->flags & VXLAN_F_PROXY)) ||
+	    nla_put_u8(skb, IFLA_VXLAN_RSC, !!(vxlan->flags & VXLAN_F_RSC)) ||
+	    nla_put_u8(skb, IFLA_VXLAN_L2MISS,
+			!!(vxlan->flags & VXLAN_F_L2MISS)) ||
+	    nla_put_u8(skb, IFLA_VXLAN_L3MISS,
+			!!(vxlan->flags & VXLAN_F_L3MISS)) ||
 	    nla_put_u32(skb, IFLA_VXLAN_AGEING, vxlan->age_interval) ||
 	    nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->addrmax))
 		goto nla_put_failure;
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index d58431e..c0cd88d 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -375,7 +375,7 @@ config WAN_ROUTER_DRIVERS
 	  If unsure, say N.
 
 config CYCLADES_SYNC
-	tristate "Cyclom 2X(tm) cards (EXPERIMENTAL)"
+	tristate "Cyclom 2X(tm) cards"
 	depends on WAN_ROUTER_DRIVERS && (PCI || ISA)
 	---help---
 	  Cyclom 2X from Cyclades Corporation <http://www.avocent.com/> is an
@@ -403,7 +403,7 @@ config CYCLADES_SYNC
 	  module will be called cyclomx.
 
 config CYCLOMX_X25
-	bool "Cyclom 2X X.25 support (EXPERIMENTAL)"
+	bool "Cyclom 2X X.25 support"
 	depends on CYCLADES_SYNC
 	help
 	  Connect a Cyclom 2X card to an X.25 network.
@@ -412,7 +412,7 @@ config CYCLOMX_X25
 
 # X.25 network drivers
 config LAPBETHER
-	tristate "LAPB over Ethernet driver (EXPERIMENTAL)"
+	tristate "LAPB over Ethernet driver"
 	depends on LAPB && X25
 	---help---
 	  Driver for a pseudo device (typically called /dev/lapb0) which allows
@@ -428,7 +428,7 @@ config LAPBETHER
 	  If unsure, say N.
 
 config X25_ASY
-	tristate "X.25 async driver (EXPERIMENTAL)"
+	tristate "X.25 async driver"
 	depends on LAPB && X25
 	---help---
 	  Send and receive X.25 frames over regular asynchronous serial
diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
index eac709b..df70248 100644
--- a/drivers/net/wan/Makefile
+++ b/drivers/net/wan/Makefile
@@ -52,9 +52,9 @@ endif
 
 quiet_cmd_build_wanxlfw = BLD FW  $@
       cmd_build_wanxlfw = \
-	$(CPP) -Wp,-MD,$(depfile) -I$(srctree)/include $< | $(AS68K) -m68360 -o $(obj)/wanxlfw.o; \
+	$(CPP) -D__ASSEMBLY__ -Wp,-MD,$(depfile) -I$(srctree)/include/uapi $< | $(AS68K) -m68360 -o $(obj)/wanxlfw.o; \
 	$(LD68K) --oformat binary -Ttext 0x1000 $(obj)/wanxlfw.o -o $(obj)/wanxlfw.bin; \
-	hexdump -ve '"\n" 16/1 "0x%02X,"' $(obj)/wanxlfw.bin | sed 's/0x  ,//g;1s/^/static u8 firmware[]={/;$$s/,$$/\n};\n/' >$(obj)/wanxlfw.inc; \
+	hexdump -ve '"\n" 16/1 "0x%02X,"' $(obj)/wanxlfw.bin | sed 's/0x  ,//g;1s/^/static const u8 firmware[]={/;$$s/,$$/\n};\n/' >$(obj)/wanxlfw.inc; \
 	rm -f $(obj)/wanxlfw.bin $(obj)/wanxlfw.o
 
 $(obj)/wanxlfw.inc:	$(src)/wanxlfw.S
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index e9a3da5..760776b 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -1365,7 +1365,7 @@ static int __devinit hss_init_one(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, port);
 
-	netdev_info(dev, "HSS-%i\n", port->id);
+	netdev_info(dev, "initialized\n");
 	return 0;
 
 err_free_netdev:
diff --git a/drivers/net/wan/wanxlfw.S b/drivers/net/wan/wanxlfw.S
index 73aae2b..21565d5 100644
--- a/drivers/net/wan/wanxlfw.S
+++ b/drivers/net/wan/wanxlfw.S
@@ -35,6 +35,7 @@
 */
 
 #include <linux/hdlc.h>
+#include <linux/hdlc/ioctl.h>
 #include "wanxl.h"
 
 /* memory addresses and offsets */
diff --git a/drivers/net/wimax/i2400m/debugfs.c b/drivers/net/wimax/i2400m/debugfs.c
index 4b66ab1..6702da8 100644
--- a/drivers/net/wimax/i2400m/debugfs.c
+++ b/drivers/net/wimax/i2400m/debugfs.c
@@ -209,6 +209,7 @@ int debugfs_i2400m_reset_set(void *data, u64 val)
 		result = i2400m_reset(i2400m, rt);
 		if (result >= 0)
 			result = 0;
+		break;
 	default:
 		result = -EINVAL;
 	}
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 6deaae1..28aa05f 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -156,11 +156,7 @@ config PRISM54
 	---help---
 	  This enables support for FullMAC PCI/Cardbus prism54 devices. This
 	  driver is now deprecated in favor for the SoftMAC driver, p54pci.
-	  p54pci supports FullMAC PCI/Cardbus devices as well. For details on
-	  the scheduled removal of this driver on the kernel see the feature
-	  removal schedule:
-
-	  Documentation/feature-removal-schedule.txt
+	  p54pci supports FullMAC PCI/Cardbus devices as well.
 
 	  For more information refer to the p54 wiki:
 
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 3cd05a71..57f7db1 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -7433,7 +7433,7 @@ static inline char *airo_translate_scan(struct net_device *dev,
 					num_null_ies++;
 				break;
 
-			case WLAN_EID_GENERIC:
+			case WLAN_EID_VENDOR_SPECIFIC:
 				if (ie[1] >= 4 &&
 				    ie[2] == 0x00 &&
 				    ie[3] == 0x50 &&
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index 99b9ddf..77fa428 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -379,7 +379,7 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
 		 manifest_sync_timeout);
 
 	if (!size) {
-		dev_printk(KERN_ERR, &udev->dev, "FW buffer length invalid!\n");
+		dev_err(&udev->dev, "FW buffer length invalid!\n");
 		return -EINVAL;
 	}
 
@@ -391,8 +391,8 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
 		if (need_dfu_state) {
 			ret = at76_dfu_get_state(udev, &dfu_state);
 			if (ret < 0) {
-				dev_printk(KERN_ERR, &udev->dev,
-					   "cannot get DFU state: %d\n", ret);
+				dev_err(&udev->dev,
+					"cannot get DFU state: %d\n", ret);
 				goto exit;
 			}
 			need_dfu_state = 0;
@@ -407,9 +407,9 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
 				dfu_timeout = at76_get_timeout(&dfu_stat_buf);
 				need_dfu_state = 0;
 			} else
-				dev_printk(KERN_ERR, &udev->dev,
-					   "at76_dfu_get_status returned %d\n",
-					   ret);
+				dev_err(&udev->dev,
+					"at76_dfu_get_status returned %d\n",
+					ret);
 			break;
 
 		case STATE_DFU_DOWNLOAD_BUSY:
@@ -438,9 +438,9 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
 			blockno++;
 
 			if (ret != bsize)
-				dev_printk(KERN_ERR, &udev->dev,
-					   "at76_load_int_fw_block "
-					   "returned %d\n", ret);
+				dev_err(&udev->dev,
+					"at76_load_int_fw_block returned %d\n",
+					ret);
 			need_dfu_state = 1;
 			break;
 
@@ -1255,8 +1255,7 @@ static int at76_load_external_fw(struct usb_device *udev, struct fwentry *fwe)
 	at76_dbg(DBG_DEVSTART, "opmode %d", op_mode);
 
 	if (op_mode != OPMODE_NORMAL_NIC_WITHOUT_FLASH) {
-		dev_printk(KERN_ERR, &udev->dev, "unexpected opmode %d\n",
-			   op_mode);
+		dev_err(&udev->dev, "unexpected opmode %d\n", op_mode);
 		return -EINVAL;
 	}
 
@@ -1275,9 +1274,9 @@ static int at76_load_external_fw(struct usb_device *udev, struct fwentry *fwe)
 			 size, bsize, blockno);
 		ret = at76_load_ext_fw_block(udev, blockno, block, bsize);
 		if (ret != bsize) {
-			dev_printk(KERN_ERR, &udev->dev,
-				   "loading %dth firmware block failed: %d\n",
-				   blockno, ret);
+			dev_err(&udev->dev,
+				"loading %dth firmware block failed: %d\n",
+				blockno, ret);
 			goto exit;
 		}
 		buf += bsize;
@@ -1293,8 +1292,8 @@ static int at76_load_external_fw(struct usb_device *udev, struct fwentry *fwe)
 exit:
 	kfree(block);
 	if (ret < 0)
-		dev_printk(KERN_ERR, &udev->dev,
-			   "downloading external firmware failed: %d\n", ret);
+		dev_err(&udev->dev,
+			"downloading external firmware failed: %d\n", ret);
 	return ret;
 }
 
@@ -1308,8 +1307,8 @@ static int at76_load_internal_fw(struct usb_device *udev, struct fwentry *fwe)
 				   need_remap ? 0 : 2 * HZ);
 
 	if (ret < 0) {
-		dev_printk(KERN_ERR, &udev->dev,
-			   "downloading internal fw failed with %d\n", ret);
+		dev_err(&udev->dev,
+			"downloading internal fw failed with %d\n", ret);
 		goto exit;
 	}
 
@@ -1319,8 +1318,8 @@ static int at76_load_internal_fw(struct usb_device *udev, struct fwentry *fwe)
 	if (need_remap) {
 		ret = at76_remap(udev);
 		if (ret < 0) {
-			dev_printk(KERN_ERR, &udev->dev,
-				   "sending REMAP failed with %d\n", ret);
+			dev_err(&udev->dev,
+				"sending REMAP failed with %d\n", ret);
 			goto exit;
 		}
 	}
@@ -1555,11 +1554,10 @@ static struct fwentry *at76_load_firmware(struct usb_device *udev,
 	at76_dbg(DBG_FW, "downloading firmware %s", fwe->fwname);
 	ret = request_firmware(&fwe->fw, fwe->fwname, &udev->dev);
 	if (ret < 0) {
-		dev_printk(KERN_ERR, &udev->dev, "firmware %s not found!\n",
-			   fwe->fwname);
-		dev_printk(KERN_ERR, &udev->dev,
-			   "you may need to download the firmware from "
-			   "http://developer.berlios.de/projects/at76c503a/\n");
+		dev_err(&udev->dev, "firmware %s not found!\n",
+			fwe->fwname);
+		dev_err(&udev->dev,
+			"you may need to download the firmware from http://developer.berlios.de/projects/at76c503a/\n");
 		goto exit;
 	}
 
@@ -1567,17 +1565,17 @@ static struct fwentry *at76_load_firmware(struct usb_device *udev,
 	fwh = (struct at76_fw_header *)(fwe->fw->data);
 
 	if (fwe->fw->size <= sizeof(*fwh)) {
-		dev_printk(KERN_ERR, &udev->dev,
-			   "firmware is too short (0x%zx)\n", fwe->fw->size);
+		dev_err(&udev->dev,
+			"firmware is too short (0x%zx)\n", fwe->fw->size);
 		goto exit;
 	}
 
 	/* CRC currently not checked */
 	fwe->board_type = le32_to_cpu(fwh->board_type);
 	if (fwe->board_type != board_type) {
-		dev_printk(KERN_ERR, &udev->dev,
-			   "board type mismatch, requested %u, got %u\n",
-			   board_type, fwe->board_type);
+		dev_err(&udev->dev,
+			"board type mismatch, requested %u, got %u\n",
+			board_type, fwe->board_type);
 		goto exit;
 	}
 
@@ -2150,8 +2148,7 @@ static int at76_alloc_urbs(struct at76_priv *priv,
 	}
 
 	if (!ep_in || !ep_out) {
-		dev_printk(KERN_ERR, &interface->dev,
-			   "bulk endpoints missing\n");
+		dev_err(&interface->dev, "bulk endpoints missing\n");
 		return -ENXIO;
 	}
 
@@ -2161,15 +2158,14 @@ static int at76_alloc_urbs(struct at76_priv *priv,
 	priv->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
 	priv->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!priv->rx_urb || !priv->tx_urb) {
-		dev_printk(KERN_ERR, &interface->dev, "cannot allocate URB\n");
+		dev_err(&interface->dev, "cannot allocate URB\n");
 		return -ENOMEM;
 	}
 
 	buffer_size = sizeof(struct at76_tx_buffer) + MAX_PADDING_SIZE;
 	priv->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
 	if (!priv->bulk_out_buffer) {
-		dev_printk(KERN_ERR, &interface->dev,
-			   "cannot allocate output buffer\n");
+		dev_err(&interface->dev, "cannot allocate output buffer\n");
 		return -ENOMEM;
 	}
 
@@ -2230,8 +2226,7 @@ static int at76_init_new_device(struct at76_priv *priv,
 	/* MAC address */
 	ret = at76_get_hw_config(priv);
 	if (ret < 0) {
-		dev_printk(KERN_ERR, &interface->dev,
-			   "cannot get MAC address\n");
+		dev_err(&interface->dev, "cannot get MAC address\n");
 		goto exit;
 	}
 
@@ -2358,8 +2353,8 @@ static int at76_probe(struct usb_interface *interface,
 	   we get 204 with 2.4.23, Fiberline FL-WL240u (505A+RFMD2958) ??? */
 
 	if (op_mode == OPMODE_HW_CONFIG_MODE) {
-		dev_printk(KERN_ERR, &interface->dev,
-			   "cannot handle a device in HW_CONFIG_MODE\n");
+		dev_err(&interface->dev,
+			"cannot handle a device in HW_CONFIG_MODE\n");
 		ret = -EBUSY;
 		goto error;
 	}
@@ -2371,9 +2366,9 @@ static int at76_probe(struct usb_interface *interface,
 			   "downloading internal firmware\n");
 		ret = at76_load_internal_fw(udev, fwe);
 		if (ret < 0) {
-			dev_printk(KERN_ERR, &interface->dev,
-				   "error %d downloading internal firmware\n",
-				   ret);
+			dev_err(&interface->dev,
+				"error %d downloading internal firmware\n",
+				ret);
 			goto error;
 		}
 		usb_put_dev(udev);
@@ -2408,8 +2403,8 @@ static int at76_probe(struct usb_interface *interface,
 		/* Re-check firmware version */
 		ret = at76_get_mib(udev, MIB_FW_VERSION, &fwv, sizeof(fwv));
 		if (ret < 0) {
-			dev_printk(KERN_ERR, &interface->dev,
-				   "error %d getting firmware version\n", ret);
+			dev_err(&interface->dev,
+				"error %d getting firmware version\n", ret);
 			goto error;
 		}
 	}
@@ -2449,7 +2444,7 @@ static void at76_disconnect(struct usb_interface *interface)
 
 	wiphy_info(priv->hw->wiphy, "disconnecting\n");
 	at76_delete_device(priv);
-	dev_printk(KERN_INFO, &interface->dev, "disconnected\n");
+	dev_info(&interface->dev, "disconnected\n");
 }
 
 /* Structure for registering this driver with the USB subsystem */
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
index 0960224..c25dcf1 100644
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -26,5 +26,6 @@ source "drivers/net/wireless/ath/ath5k/Kconfig"
 source "drivers/net/wireless/ath/ath9k/Kconfig"
 source "drivers/net/wireless/ath/carl9170/Kconfig"
 source "drivers/net/wireless/ath/ath6kl/Kconfig"
+source "drivers/net/wireless/ath/ar5523/Kconfig"
 
 endif
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile
index d716b74..1e18621 100644
--- a/drivers/net/wireless/ath/Makefile
+++ b/drivers/net/wireless/ath/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_ATH5K)		+= ath5k/
 obj-$(CONFIG_ATH9K_HW)		+= ath9k/
 obj-$(CONFIG_CARL9170)		+= carl9170/
 obj-$(CONFIG_ATH6KL)		+= ath6kl/
+obj-$(CONFIG_AR5523)		+= ar5523/
 
 obj-$(CONFIG_ATH_COMMON)	+= ath.o
 
diff --git a/drivers/net/wireless/ath/ar5523/Kconfig b/drivers/net/wireless/ath/ar5523/Kconfig
new file mode 100644
index 0000000..11d99ee
--- /dev/null
+++ b/drivers/net/wireless/ath/ar5523/Kconfig
@@ -0,0 +1,7 @@
+config AR5523
+       tristate "Atheros AR5523 wireless driver support"
+       depends on MAC80211 && USB
+       select FW_LOADER
+       ---help---
+         This module add support for AR5523 based USB dongles such as D-Link
+         DWL-G132, Netgear WPN111 and many more.
diff --git a/drivers/net/wireless/ath/ar5523/Makefile b/drivers/net/wireless/ath/ar5523/Makefile
new file mode 100644
index 0000000..ebf7f3b
--- /dev/null
+++ b/drivers/net/wireless/ath/ar5523/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_AR5523)   := ar5523.o
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c
new file mode 100644
index 0000000..7157f7d
--- /dev/null
+++ b/drivers/net/wireless/ath/ar5523/ar5523.c
@@ -0,0 +1,1798 @@
+/*
+ * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * Copyright (c) 2007 Christoph Hellwig <hch@lst.de>
+ * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org>
+ * Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This driver is based on the uath driver written by Damien Bergamini for
+ * OpenBSD, who did black-box analysis of the Windows binary driver to find
+ * out how the hardware works.  It contains a lot magic numbers because of
+ * that and only has minimal functionality.
+ */
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/completion.h>
+#include <linux/firmware.h>
+#include <linux/skbuff.h>
+#include <linux/usb.h>
+#include <net/mac80211.h>
+
+#include "ar5523.h"
+#include "ar5523_hw.h"
+
+/*
+ * Various supported device vendors/products.
+ * UB51: AR5005UG 802.11b/g, UB52: AR5005UX 802.11a/b/g
+ */
+
+static int ar5523_submit_rx_cmd(struct ar5523 *ar);
+static void ar5523_data_tx_pkt_put(struct ar5523 *ar);
+
+static void ar5523_read_reply(struct ar5523 *ar, struct ar5523_cmd_hdr *hdr,
+			      struct ar5523_tx_cmd *cmd)
+{
+	int dlen, olen;
+	__be32 *rp;
+
+	dlen = be32_to_cpu(hdr->len) - sizeof(*hdr);
+
+	if (dlen < 0) {
+		WARN_ON(1);
+		goto out;
+	}
+
+	ar5523_dbg(ar, "Code = %d len = %d\n", be32_to_cpu(hdr->code) & 0xff,
+		   dlen);
+
+	rp = (__be32 *)(hdr + 1);
+	if (dlen >= sizeof(u32)) {
+		olen = be32_to_cpu(rp[0]);
+		dlen -= sizeof(u32);
+		if (olen == 0) {
+			/* convention is 0 =>'s one word */
+			olen = sizeof(u32);
+		}
+	} else
+		olen = 0;
+
+	if (cmd->odata) {
+		if (cmd->olen < olen) {
+			ar5523_err(ar, "olen to small %d < %d\n",
+				   cmd->olen, olen);
+			cmd->olen = 0;
+			cmd->res = -EOVERFLOW;
+		} else {
+			cmd->olen = olen;
+			memcpy(cmd->odata, &rp[1], olen);
+			cmd->res = 0;
+		}
+	}
+
+out:
+	complete(&cmd->done);
+}
+
+static void ar5523_cmd_rx_cb(struct urb *urb)
+{
+	struct ar5523 *ar = urb->context;
+	struct ar5523_tx_cmd *cmd = &ar->tx_cmd;
+	struct ar5523_cmd_hdr *hdr = ar->rx_cmd_buf;
+	int dlen;
+	u32 code, hdrlen;
+
+	if (urb->status) {
+		if (urb->status != -ESHUTDOWN)
+			ar5523_err(ar, "RX USB error %d.\n", urb->status);
+		goto skip;
+	}
+
+	if (urb->actual_length < sizeof(struct ar5523_cmd_hdr)) {
+		ar5523_err(ar, "RX USB to short.\n");
+		goto skip;
+	}
+
+	ar5523_dbg(ar, "%s code %02x priv %d\n", __func__,
+		   be32_to_cpu(hdr->code) & 0xff, hdr->priv);
+
+	code = be32_to_cpu(hdr->code);
+	hdrlen = be32_to_cpu(hdr->len);
+
+	switch (code & 0xff) {
+	default:
+		/* reply to a read command */
+		if (hdr->priv != AR5523_CMD_ID) {
+			ar5523_err(ar, "Unexpected command id: %02x\n",
+				   code & 0xff);
+			goto skip;
+		}
+		ar5523_read_reply(ar, hdr, cmd);
+		break;
+
+	case WDCMSG_DEVICE_AVAIL:
+		ar5523_dbg(ar, "WDCMSG_DEVICE_AVAIL\n");
+		cmd->res = 0;
+		cmd->olen = 0;
+		complete(&cmd->done);
+		break;
+
+	case WDCMSG_SEND_COMPLETE:
+		ar5523_dbg(ar, "WDCMSG_SEND_COMPLETE: %d pending\n",
+			atomic_read(&ar->tx_nr_pending));
+		if (!test_bit(AR5523_HW_UP, &ar->flags))
+			ar5523_dbg(ar, "Unexpected WDCMSG_SEND_COMPLETE\n");
+		else {
+			mod_timer(&ar->tx_wd_timer,
+				  jiffies + AR5523_TX_WD_TIMEOUT);
+			ar5523_data_tx_pkt_put(ar);
+
+		}
+		break;
+
+	case WDCMSG_TARGET_START:
+		/* This command returns a bogus id so it needs special
+		   handling */
+		dlen = hdrlen - sizeof(*hdr);
+		if (dlen != (int)sizeof(u32)) {
+			ar5523_err(ar, "Invalid reply to WDCMSG_TARGET_START");
+			return;
+		}
+		memcpy(cmd->odata, hdr + 1, sizeof(u32));
+		cmd->olen = sizeof(u32);
+		cmd->res = 0;
+		complete(&cmd->done);
+		break;
+
+	case WDCMSG_STATS_UPDATE:
+		ar5523_dbg(ar, "WDCMSG_STATS_UPDATE\n");
+		break;
+	}
+
+skip:
+	ar5523_submit_rx_cmd(ar);
+}
+
+static int ar5523_alloc_rx_cmd(struct ar5523 *ar)
+{
+	ar->rx_cmd_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ar->rx_cmd_urb)
+		return -ENOMEM;
+
+	ar->rx_cmd_buf = usb_alloc_coherent(ar->dev, AR5523_MAX_RXCMDSZ,
+					    GFP_KERNEL,
+					    &ar->rx_cmd_urb->transfer_dma);
+	if (!ar->rx_cmd_buf) {
+		usb_free_urb(ar->rx_cmd_urb);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static void ar5523_cancel_rx_cmd(struct ar5523 *ar)
+{
+	usb_kill_urb(ar->rx_cmd_urb);
+}
+
+static void ar5523_free_rx_cmd(struct ar5523 *ar)
+{
+	usb_free_coherent(ar->dev, AR5523_MAX_RXCMDSZ,
+			  ar->rx_cmd_buf, ar->rx_cmd_urb->transfer_dma);
+	usb_free_urb(ar->rx_cmd_urb);
+}
+
+static int ar5523_submit_rx_cmd(struct ar5523 *ar)
+{
+	int error;
+
+	usb_fill_bulk_urb(ar->rx_cmd_urb, ar->dev,
+			  ar5523_cmd_rx_pipe(ar->dev), ar->rx_cmd_buf,
+			  AR5523_MAX_RXCMDSZ, ar5523_cmd_rx_cb, ar);
+	ar->rx_cmd_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	error = usb_submit_urb(ar->rx_cmd_urb, GFP_ATOMIC);
+	if (error) {
+		if (error != -ENODEV)
+			ar5523_err(ar, "error %d when submitting rx urb\n",
+				   error);
+		return error;
+	}
+	return 0;
+}
+
+/*
+ * Command submitted cb
+ */
+static void ar5523_cmd_tx_cb(struct urb *urb)
+{
+	struct ar5523_tx_cmd *cmd = urb->context;
+	struct ar5523 *ar = cmd->ar;
+
+	if (urb->status) {
+		ar5523_err(ar, "Failed to TX command. Status = %d\n",
+			   urb->status);
+		cmd->res = urb->status;
+		complete(&cmd->done);
+		return;
+	}
+
+	if (!(cmd->flags & AR5523_CMD_FLAG_READ)) {
+		cmd->res = 0;
+		complete(&cmd->done);
+	}
+}
+
+static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata,
+		      int ilen, void *odata, int olen, int flags)
+{
+	struct ar5523_cmd_hdr *hdr;
+	struct ar5523_tx_cmd *cmd = &ar->tx_cmd;
+	int xferlen, error;
+
+	/* always bulk-out a multiple of 4 bytes */
+	xferlen = (sizeof(struct ar5523_cmd_hdr) + ilen + 3) & ~3;
+
+	hdr = (struct ar5523_cmd_hdr *)cmd->buf_tx;
+	memset(hdr, 0, sizeof(struct ar5523_cmd_hdr));
+	hdr->len  = cpu_to_be32(xferlen);
+	hdr->code = cpu_to_be32(code);
+	hdr->priv = AR5523_CMD_ID;
+
+	if (flags & AR5523_CMD_FLAG_MAGIC)
+		hdr->magic = cpu_to_be32(1 << 24);
+	memcpy(hdr + 1, idata, ilen);
+
+	cmd->odata = odata;
+	cmd->olen = olen;
+	cmd->flags = flags;
+
+	ar5523_dbg(ar, "do cmd %02x\n", code);
+
+	usb_fill_bulk_urb(cmd->urb_tx, ar->dev, ar5523_cmd_tx_pipe(ar->dev),
+			  cmd->buf_tx, xferlen, ar5523_cmd_tx_cb, cmd);
+	cmd->urb_tx->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	error = usb_submit_urb(cmd->urb_tx, GFP_KERNEL);
+	if (error) {
+		ar5523_err(ar, "could not send command 0x%x, error=%d\n",
+			   code, error);
+		return error;
+	}
+
+	if (!wait_for_completion_timeout(&cmd->done, 2 * HZ)) {
+		cmd->odata = NULL;
+		ar5523_err(ar, "timeout waiting for command %02x reply\n",
+			   code);
+		cmd->res = -ETIMEDOUT;
+	}
+	return cmd->res;
+}
+
+static int ar5523_cmd_write(struct ar5523 *ar, u32 code, const void *data,
+			    int len, int flags)
+{
+	flags &= ~AR5523_CMD_FLAG_READ;
+	return ar5523_cmd(ar, code, data, len, NULL, 0, flags);
+}
+
+static int ar5523_cmd_read(struct ar5523 *ar, u32 code, const void *idata,
+			   int ilen, void *odata, int olen, int flags)
+{
+	flags |= AR5523_CMD_FLAG_READ;
+	return ar5523_cmd(ar, code, idata, ilen, odata, olen, flags);
+}
+
+static int ar5523_config(struct ar5523 *ar, u32 reg, u32 val)
+{
+	struct ar5523_write_mac write;
+	int error;
+
+	write.reg = cpu_to_be32(reg);
+	write.len = cpu_to_be32(0);	/* 0 = single write */
+	*(__be32 *)write.data = cpu_to_be32(val);
+
+	error = ar5523_cmd_write(ar, WDCMSG_TARGET_SET_CONFIG, &write,
+				 3 * sizeof(u32), 0);
+	if (error != 0)
+		ar5523_err(ar, "could not write register 0x%02x\n", reg);
+	return error;
+}
+
+static int ar5523_config_multi(struct ar5523 *ar, u32 reg, const void *data,
+			       int len)
+{
+	struct ar5523_write_mac write;
+	int error;
+
+	write.reg = cpu_to_be32(reg);
+	write.len = cpu_to_be32(len);
+	memcpy(write.data, data, len);
+
+	/* properly handle the case where len is zero (reset) */
+	error = ar5523_cmd_write(ar, WDCMSG_TARGET_SET_CONFIG, &write,
+	    (len == 0) ? sizeof(u32) : 2 * sizeof(u32) + len, 0);
+	if (error != 0)
+		ar5523_err(ar, "could not write %d bytes to register 0x%02x\n",
+			   len, reg);
+	return error;
+}
+
+static int ar5523_get_status(struct ar5523 *ar, u32 which, void *odata,
+			     int olen)
+{
+	int error;
+	__be32 which_be;
+
+	which_be = cpu_to_be32(which);
+	error = ar5523_cmd_read(ar, WDCMSG_TARGET_GET_STATUS,
+	    &which_be, sizeof(which_be), odata, olen, AR5523_CMD_FLAG_MAGIC);
+	if (error != 0)
+		ar5523_err(ar, "could not read EEPROM offset 0x%02x\n", which);
+	return error;
+}
+
+static int ar5523_get_capability(struct ar5523 *ar, u32 cap, u32 *val)
+{
+	int error;
+	__be32 cap_be, val_be;
+
+	cap_be = cpu_to_be32(cap);
+	error = ar5523_cmd_read(ar, WDCMSG_TARGET_GET_CAPABILITY, &cap_be,
+				sizeof(cap_be), &val_be, sizeof(__be32),
+				AR5523_CMD_FLAG_MAGIC);
+	if (error != 0) {
+		ar5523_err(ar, "could not read capability %u\n", cap);
+		return error;
+	}
+	*val = be32_to_cpu(val_be);
+	return error;
+}
+
+static int ar5523_get_devcap(struct ar5523 *ar)
+{
+#define	GETCAP(x) do {				\
+	error = ar5523_get_capability(ar, x, &cap);		\
+	if (error != 0)					\
+		return error;				\
+	ar5523_info(ar, "Cap: "			\
+	    "%s=0x%08x\n", #x, cap);	\
+} while (0)
+	int error;
+	u32 cap;
+
+	/* collect device capabilities */
+	GETCAP(CAP_TARGET_VERSION);
+	GETCAP(CAP_TARGET_REVISION);
+	GETCAP(CAP_MAC_VERSION);
+	GETCAP(CAP_MAC_REVISION);
+	GETCAP(CAP_PHY_REVISION);
+	GETCAP(CAP_ANALOG_5GHz_REVISION);
+	GETCAP(CAP_ANALOG_2GHz_REVISION);
+
+	GETCAP(CAP_REG_DOMAIN);
+	GETCAP(CAP_REG_CAP_BITS);
+	GETCAP(CAP_WIRELESS_MODES);
+	GETCAP(CAP_CHAN_SPREAD_SUPPORT);
+	GETCAP(CAP_COMPRESS_SUPPORT);
+	GETCAP(CAP_BURST_SUPPORT);
+	GETCAP(CAP_FAST_FRAMES_SUPPORT);
+	GETCAP(CAP_CHAP_TUNING_SUPPORT);
+	GETCAP(CAP_TURBOG_SUPPORT);
+	GETCAP(CAP_TURBO_PRIME_SUPPORT);
+	GETCAP(CAP_DEVICE_TYPE);
+	GETCAP(CAP_WME_SUPPORT);
+	GETCAP(CAP_TOTAL_QUEUES);
+	GETCAP(CAP_CONNECTION_ID_MAX);
+
+	GETCAP(CAP_LOW_5GHZ_CHAN);
+	GETCAP(CAP_HIGH_5GHZ_CHAN);
+	GETCAP(CAP_LOW_2GHZ_CHAN);
+	GETCAP(CAP_HIGH_2GHZ_CHAN);
+	GETCAP(CAP_TWICE_ANTENNAGAIN_5G);
+	GETCAP(CAP_TWICE_ANTENNAGAIN_2G);
+
+	GETCAP(CAP_CIPHER_AES_CCM);
+	GETCAP(CAP_CIPHER_TKIP);
+	GETCAP(CAP_MIC_TKIP);
+	return 0;
+}
+
+static int ar5523_set_ledsteady(struct ar5523 *ar, int lednum, int ledmode)
+{
+	struct ar5523_cmd_ledsteady led;
+
+	led.lednum = cpu_to_be32(lednum);
+	led.ledmode = cpu_to_be32(ledmode);
+
+	ar5523_dbg(ar, "set %s led %s (steady)\n",
+		   (lednum == UATH_LED_LINK) ? "link" : "activity",
+		   ledmode ? "on" : "off");
+	return ar5523_cmd_write(ar, WDCMSG_SET_LED_STEADY, &led, sizeof(led),
+				 0);
+}
+
+static int ar5523_set_rxfilter(struct ar5523 *ar, u32 bits, u32 op)
+{
+	struct ar5523_cmd_rx_filter rxfilter;
+
+	rxfilter.bits = cpu_to_be32(bits);
+	rxfilter.op = cpu_to_be32(op);
+
+	ar5523_dbg(ar, "setting Rx filter=0x%x flags=0x%x\n", bits, op);
+	return ar5523_cmd_write(ar, WDCMSG_RX_FILTER, &rxfilter,
+				 sizeof(rxfilter), 0);
+}
+
+static int ar5523_reset_tx_queues(struct ar5523 *ar)
+{
+	__be32 qid = cpu_to_be32(0);
+
+	ar5523_dbg(ar, "resetting Tx queue\n");
+	return ar5523_cmd_write(ar, WDCMSG_RELEASE_TX_QUEUE,
+				 &qid, sizeof(qid), 0);
+}
+
+static int ar5523_set_chan(struct ar5523 *ar)
+{
+	struct ieee80211_conf *conf = &ar->hw->conf;
+
+	struct ar5523_cmd_reset reset;
+
+	memset(&reset, 0, sizeof(reset));
+	reset.flags |= cpu_to_be32(UATH_CHAN_2GHZ);
+	reset.flags |= cpu_to_be32(UATH_CHAN_OFDM);
+	reset.freq = cpu_to_be32(conf->channel->center_freq);
+	reset.maxrdpower = cpu_to_be32(50);	/* XXX */
+	reset.channelchange = cpu_to_be32(1);
+	reset.keeprccontent = cpu_to_be32(0);
+
+	ar5523_dbg(ar, "set chan flags 0x%x freq %d\n",
+		   be32_to_cpu(reset.flags),
+		   conf->channel->center_freq);
+	return ar5523_cmd_write(ar, WDCMSG_RESET, &reset, sizeof(reset), 0);
+}
+
+static int ar5523_queue_init(struct ar5523 *ar)
+{
+	struct ar5523_cmd_txq_setup qinfo;
+
+	ar5523_dbg(ar, "setting up Tx queue\n");
+	qinfo.qid	     = cpu_to_be32(0);
+	qinfo.len	     = cpu_to_be32(sizeof(qinfo.attr));
+	qinfo.attr.priority  = cpu_to_be32(0);	/* XXX */
+	qinfo.attr.aifs	     = cpu_to_be32(3);
+	qinfo.attr.logcwmin  = cpu_to_be32(4);
+	qinfo.attr.logcwmax  = cpu_to_be32(10);
+	qinfo.attr.bursttime = cpu_to_be32(0);
+	qinfo.attr.mode	     = cpu_to_be32(0);
+	qinfo.attr.qflags    = cpu_to_be32(1);	/* XXX? */
+	return ar5523_cmd_write(ar, WDCMSG_SETUP_TX_QUEUE, &qinfo,
+				 sizeof(qinfo), 0);
+}
+
+static int ar5523_switch_chan(struct ar5523 *ar)
+{
+	int error;
+
+	error = ar5523_set_chan(ar);
+	if (error) {
+		ar5523_err(ar, "could not set chan, error %d\n", error);
+		goto out_err;
+	}
+
+	/* reset Tx rings */
+	error = ar5523_reset_tx_queues(ar);
+	if (error) {
+		ar5523_err(ar, "could not reset Tx queues, error %d\n",
+			   error);
+		goto out_err;
+	}
+	/* set Tx rings WME properties */
+	error = ar5523_queue_init(ar);
+	if (error)
+		ar5523_err(ar, "could not init wme, error %d\n", error);
+
+out_err:
+	return error;
+}
+
+static void ar5523_rx_data_put(struct ar5523 *ar,
+				struct ar5523_rx_data *data)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&ar->rx_data_list_lock, flags);
+	list_move(&data->list, &ar->rx_data_free);
+	spin_unlock_irqrestore(&ar->rx_data_list_lock, flags);
+}
+
+static void ar5523_data_rx_cb(struct urb *urb)
+{
+	struct ar5523_rx_data *data = urb->context;
+	struct ar5523 *ar = data->ar;
+	struct ar5523_rx_desc *desc;
+	struct ar5523_chunk *chunk;
+	struct ieee80211_hw *hw = ar->hw;
+	struct ieee80211_rx_status *rx_status;
+	u32 rxlen;
+	int usblen = urb->actual_length;
+	int hdrlen, pad;
+
+	ar5523_dbg(ar, "%s\n", __func__);
+	/* sync/async unlink faults aren't errors */
+	if (urb->status) {
+		if (urb->status != -ESHUTDOWN)
+			ar5523_err(ar, "%s: USB err: %d\n", __func__,
+				   urb->status);
+		goto skip;
+	}
+
+	if (usblen < AR5523_MIN_RXBUFSZ) {
+		ar5523_err(ar, "RX: wrong xfer size (usblen=%d)\n", usblen);
+		goto skip;
+	}
+
+	chunk = (struct ar5523_chunk *) data->skb->data;
+
+	if (((chunk->flags & UATH_CFLAGS_FINAL) == 0) ||
+		chunk->seqnum != 0) {
+		ar5523_dbg(ar, "RX: No final flag. s: %d f: %02x l: %d\n",
+			   chunk->seqnum, chunk->flags,
+			   be16_to_cpu(chunk->length));
+		goto skip;
+	}
+
+	/* Rx descriptor is located at the end, 32-bit aligned */
+	desc = (struct ar5523_rx_desc *)
+		(data->skb->data + usblen - sizeof(struct ar5523_rx_desc));
+
+	rxlen = be32_to_cpu(desc->len);
+	if (rxlen > ar->rxbufsz) {
+		ar5523_dbg(ar, "RX: Bad descriptor (len=%d)\n",
+			   be32_to_cpu(desc->len));
+		goto skip;
+	}
+
+	if (!rxlen) {
+		ar5523_dbg(ar, "RX: rxlen is 0\n");
+		goto skip;
+	}
+
+	if (be32_to_cpu(desc->status) != 0) {
+		ar5523_dbg(ar, "Bad RX status (0x%x len = %d). Skip\n",
+			   be32_to_cpu(desc->status), be32_to_cpu(desc->len));
+		goto skip;
+	}
+
+	skb_reserve(data->skb, sizeof(*chunk));
+	skb_put(data->skb, rxlen - sizeof(struct ar5523_rx_desc));
+
+	hdrlen = ieee80211_get_hdrlen_from_skb(data->skb);
+	if (!IS_ALIGNED(hdrlen, 4)) {
+		ar5523_dbg(ar, "eek, alignment workaround activated\n");
+		pad = ALIGN(hdrlen, 4) - hdrlen;
+		memmove(data->skb->data + pad, data->skb->data, hdrlen);
+		skb_pull(data->skb, pad);
+		skb_put(data->skb, pad);
+	}
+
+	rx_status = IEEE80211_SKB_RXCB(data->skb);
+	memset(rx_status, 0, sizeof(*rx_status));
+	rx_status->freq = be32_to_cpu(desc->channel);
+	rx_status->band = hw->conf.channel->band;
+	rx_status->signal = -95 + be32_to_cpu(desc->rssi);
+
+	ieee80211_rx_irqsafe(hw, data->skb);
+	data->skb = NULL;
+
+skip:
+	if (data->skb) {
+		dev_kfree_skb_irq(data->skb);
+		data->skb = NULL;
+	}
+
+	ar5523_rx_data_put(ar, data);
+	if (atomic_inc_return(&ar->rx_data_free_cnt) >=
+	    AR5523_RX_DATA_REFILL_COUNT &&
+	    test_bit(AR5523_HW_UP, &ar->flags))
+		queue_work(ar->wq, &ar->rx_refill_work);
+}
+
+static void ar5523_rx_refill_work(struct work_struct *work)
+{
+	struct ar5523 *ar = container_of(work, struct ar5523, rx_refill_work);
+	struct ar5523_rx_data *data;
+	unsigned long flags;
+	int error;
+
+	ar5523_dbg(ar, "%s\n", __func__);
+	do {
+		spin_lock_irqsave(&ar->rx_data_list_lock, flags);
+
+		if (!list_empty(&ar->rx_data_free))
+			data = (struct ar5523_rx_data *) ar->rx_data_free.next;
+		else
+			data = NULL;
+		spin_unlock_irqrestore(&ar->rx_data_list_lock, flags);
+
+		if (!data)
+			goto done;
+
+		data->skb = alloc_skb(ar->rxbufsz, GFP_KERNEL);
+		if (!data->skb) {
+			ar5523_err(ar, "could not allocate rx skbuff\n");
+			return;
+		}
+
+		usb_fill_bulk_urb(data->urb, ar->dev,
+				  ar5523_data_rx_pipe(ar->dev), data->skb->data,
+				  ar->rxbufsz, ar5523_data_rx_cb, data);
+
+		spin_lock_irqsave(&ar->rx_data_list_lock, flags);
+		list_move(&data->list, &ar->rx_data_used);
+		spin_unlock_irqrestore(&ar->rx_data_list_lock, flags);
+		atomic_dec(&ar->rx_data_free_cnt);
+
+		error = usb_submit_urb(data->urb, GFP_KERNEL);
+		if (error) {
+			kfree_skb(data->skb);
+			if (error != -ENODEV)
+				ar5523_err(ar, "Err sending rx data urb %d\n",
+					   error);
+			ar5523_rx_data_put(ar, data);
+			atomic_inc(&ar->rx_data_free_cnt);
+			return;
+		}
+
+	} while (true);
+done:
+	return;
+}
+
+static void ar5523_cancel_rx_bufs(struct ar5523 *ar)
+{
+	struct ar5523_rx_data *data;
+	unsigned long flags;
+
+	do {
+		spin_lock_irqsave(&ar->rx_data_list_lock, flags);
+		if (!list_empty(&ar->rx_data_used))
+			data = (struct ar5523_rx_data *) ar->rx_data_used.next;
+		else
+			data = NULL;
+		spin_unlock_irqrestore(&ar->rx_data_list_lock, flags);
+
+		if (!data)
+			break;
+
+		usb_kill_urb(data->urb);
+		list_move(&data->list, &ar->rx_data_free);
+		atomic_inc(&ar->rx_data_free_cnt);
+	} while (data);
+}
+
+static void ar5523_free_rx_bufs(struct ar5523 *ar)
+{
+	struct ar5523_rx_data *data;
+
+	ar5523_cancel_rx_bufs(ar);
+	while (!list_empty(&ar->rx_data_free)) {
+		data = (struct ar5523_rx_data *) ar->rx_data_free.next;
+		list_del(&data->list);
+		usb_free_urb(data->urb);
+	}
+}
+
+static int ar5523_alloc_rx_bufs(struct ar5523 *ar)
+{
+	int i;
+
+	for (i = 0; i < AR5523_RX_DATA_COUNT; i++) {
+		struct ar5523_rx_data *data = &ar->rx_data[i];
+
+		data->ar = ar;
+		data->urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!data->urb) {
+			ar5523_err(ar, "could not allocate rx data urb\n");
+			goto err;
+		}
+		list_add_tail(&data->list, &ar->rx_data_free);
+		atomic_inc(&ar->rx_data_free_cnt);
+	}
+	return 0;
+
+err:
+	ar5523_free_rx_bufs(ar);
+	return -ENOMEM;
+}
+
+static void ar5523_data_tx_pkt_put(struct ar5523 *ar)
+{
+	atomic_dec(&ar->tx_nr_total);
+	if (!atomic_dec_return(&ar->tx_nr_pending)) {
+		del_timer(&ar->tx_wd_timer);
+		wake_up(&ar->tx_flush_waitq);
+	}
+
+	if (atomic_read(&ar->tx_nr_total) < AR5523_TX_DATA_RESTART_COUNT) {
+		ar5523_dbg(ar, "restart tx queue\n");
+		ieee80211_wake_queues(ar->hw);
+	}
+}
+
+static void ar5523_data_tx_cb(struct urb *urb)
+{
+	struct sk_buff *skb = urb->context;
+	struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb);
+	struct ar5523_tx_data *data = (struct ar5523_tx_data *)
+				       txi->driver_data;
+	struct ar5523 *ar = data->ar;
+	unsigned long flags;
+
+	ar5523_dbg(ar, "data tx urb completed: %d\n", urb->status);
+
+	spin_lock_irqsave(&ar->tx_data_list_lock, flags);
+	list_del(&data->list);
+	spin_unlock_irqrestore(&ar->tx_data_list_lock, flags);
+
+	if (urb->status) {
+		ar5523_dbg(ar, "%s: urb status: %d\n", __func__, urb->status);
+		ar5523_data_tx_pkt_put(ar);
+		ieee80211_free_txskb(ar->hw, skb);
+	} else {
+		skb_pull(skb, sizeof(struct ar5523_tx_desc) + sizeof(__be32));
+		ieee80211_tx_status_irqsafe(ar->hw, skb);
+	}
+	usb_free_urb(urb);
+}
+
+static void ar5523_tx(struct ieee80211_hw *hw,
+		       struct ieee80211_tx_control *control,
+		       struct sk_buff *skb)
+{
+	struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb);
+	struct ar5523_tx_data *data = (struct ar5523_tx_data *)
+					txi->driver_data;
+	struct ar5523 *ar = hw->priv;
+	unsigned long flags;
+
+	ar5523_dbg(ar, "tx called\n");
+	if (atomic_inc_return(&ar->tx_nr_total) >= AR5523_TX_DATA_COUNT) {
+		ar5523_dbg(ar, "tx queue full\n");
+		ar5523_dbg(ar, "stop queues (tot %d pend %d)\n",
+			   atomic_read(&ar->tx_nr_total),
+			   atomic_read(&ar->tx_nr_pending));
+		ieee80211_stop_queues(hw);
+	}
+
+	data->skb = skb;
+
+	spin_lock_irqsave(&ar->tx_data_list_lock, flags);
+	list_add_tail(&data->list, &ar->tx_queue_pending);
+	spin_unlock_irqrestore(&ar->tx_data_list_lock, flags);
+
+	ieee80211_queue_work(ar->hw, &ar->tx_work);
+}
+
+static void ar5523_tx_work_locked(struct ar5523 *ar)
+{
+	struct ar5523_tx_data *data;
+	struct ar5523_tx_desc *desc;
+	struct ar5523_chunk *chunk;
+	struct ieee80211_tx_info *txi;
+	struct urb *urb;
+	struct sk_buff *skb;
+	int error = 0, paylen;
+	u32 txqid;
+	unsigned long flags;
+
+	BUILD_BUG_ON(sizeof(struct ar5523_tx_data) >
+		     IEEE80211_TX_INFO_DRIVER_DATA_SIZE);
+
+	ar5523_dbg(ar, "%s\n", __func__);
+	do {
+		spin_lock_irqsave(&ar->tx_data_list_lock, flags);
+		if (!list_empty(&ar->tx_queue_pending)) {
+			data = (struct ar5523_tx_data *)
+				ar->tx_queue_pending.next;
+			list_del(&data->list);
+		} else
+			data = NULL;
+		spin_unlock_irqrestore(&ar->tx_data_list_lock, flags);
+
+		if (!data)
+			break;
+
+		skb = data->skb;
+		txqid = 0;
+		txi = IEEE80211_SKB_CB(skb);
+		paylen = skb->len;
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb) {
+			ar5523_err(ar, "Failed to allocate TX urb\n");
+			ieee80211_free_txskb(ar->hw, skb);
+			continue;
+		}
+
+		data->ar = ar;
+		data->urb = urb;
+
+		desc = (struct ar5523_tx_desc *)skb_push(skb, sizeof(*desc));
+		chunk = (struct ar5523_chunk *)skb_push(skb, sizeof(*chunk));
+
+		chunk->seqnum = 0;
+		chunk->flags = UATH_CFLAGS_FINAL;
+		chunk->length = cpu_to_be16(skb->len);
+
+		desc->msglen = cpu_to_be32(skb->len);
+		desc->msgid  = AR5523_DATA_ID;
+		desc->buflen = cpu_to_be32(paylen);
+		desc->type   = cpu_to_be32(WDCMSG_SEND);
+		desc->flags  = cpu_to_be32(UATH_TX_NOTIFY);
+
+		if (test_bit(AR5523_CONNECTED, &ar->flags))
+			desc->connid = cpu_to_be32(AR5523_ID_BSS);
+		else
+			desc->connid = cpu_to_be32(AR5523_ID_BROADCAST);
+
+		if (txi->flags & IEEE80211_TX_CTL_USE_MINRATE)
+			txqid |= UATH_TXQID_MINRATE;
+
+		desc->txqid = cpu_to_be32(txqid);
+
+		urb->transfer_flags = URB_ZERO_PACKET;
+		usb_fill_bulk_urb(urb, ar->dev, ar5523_data_tx_pipe(ar->dev),
+				  skb->data, skb->len, ar5523_data_tx_cb, skb);
+
+		spin_lock_irqsave(&ar->tx_data_list_lock, flags);
+		list_add_tail(&data->list, &ar->tx_queue_submitted);
+		spin_unlock_irqrestore(&ar->tx_data_list_lock, flags);
+		mod_timer(&ar->tx_wd_timer, jiffies + AR5523_TX_WD_TIMEOUT);
+		atomic_inc(&ar->tx_nr_pending);
+
+		ar5523_dbg(ar, "TX Frame (%d pending)\n",
+			   atomic_read(&ar->tx_nr_pending));
+		error = usb_submit_urb(urb, GFP_KERNEL);
+		if (error) {
+			ar5523_err(ar, "error %d when submitting tx urb\n",
+				   error);
+			spin_lock_irqsave(&ar->tx_data_list_lock, flags);
+			list_del(&data->list);
+			spin_unlock_irqrestore(&ar->tx_data_list_lock, flags);
+			atomic_dec(&ar->tx_nr_pending);
+			ar5523_data_tx_pkt_put(ar);
+			usb_free_urb(urb);
+			ieee80211_free_txskb(ar->hw, skb);
+		}
+	} while (true);
+}
+
+static void ar5523_tx_work(struct work_struct *work)
+{
+	struct ar5523 *ar = container_of(work, struct ar5523, tx_work);
+
+	ar5523_dbg(ar, "%s\n", __func__);
+	mutex_lock(&ar->mutex);
+	ar5523_tx_work_locked(ar);
+	mutex_unlock(&ar->mutex);
+}
+
+static void ar5523_tx_wd_timer(unsigned long arg)
+{
+	struct ar5523 *ar = (struct ar5523 *) arg;
+
+	ar5523_dbg(ar, "TX watchdog timer triggered\n");
+	ieee80211_queue_work(ar->hw, &ar->tx_wd_work);
+}
+
+static void ar5523_tx_wd_work(struct work_struct *work)
+{
+	struct ar5523 *ar = container_of(work, struct ar5523, tx_wd_work);
+
+	/* Occasionally the TX queues stop responding. The only way to
+	 * recover seems to be to reset the dongle.
+	 */
+
+	mutex_lock(&ar->mutex);
+	ar5523_err(ar, "TX queue stuck (tot %d pend %d)\n",
+		   atomic_read(&ar->tx_nr_total),
+		   atomic_read(&ar->tx_nr_pending));
+
+	ar5523_err(ar, "Will restart dongle.\n");
+	ar5523_cmd_write(ar, WDCMSG_TARGET_RESET, NULL, 0, 0);
+	mutex_unlock(&ar->mutex);
+}
+
+static void ar5523_flush_tx(struct ar5523 *ar)
+{
+	ar5523_tx_work_locked(ar);
+
+	/* Don't waste time trying to flush if USB is disconnected */
+	if (test_bit(AR5523_USB_DISCONNECTED, &ar->flags))
+		return;
+	if (!wait_event_timeout(ar->tx_flush_waitq,
+	    !atomic_read(&ar->tx_nr_pending), AR5523_FLUSH_TIMEOUT))
+		ar5523_err(ar, "flush timeout (tot %d pend %d)\n",
+			   atomic_read(&ar->tx_nr_total),
+			   atomic_read(&ar->tx_nr_pending));
+}
+
+static void ar5523_free_tx_cmd(struct ar5523 *ar)
+{
+	struct ar5523_tx_cmd *cmd = &ar->tx_cmd;
+
+	usb_free_coherent(ar->dev, AR5523_MAX_RXCMDSZ, cmd->buf_tx,
+			  cmd->urb_tx->transfer_dma);
+	usb_free_urb(cmd->urb_tx);
+}
+
+static int ar5523_alloc_tx_cmd(struct ar5523 *ar)
+{
+	struct ar5523_tx_cmd *cmd = &ar->tx_cmd;
+
+	cmd->ar = ar;
+	init_completion(&cmd->done);
+
+	cmd->urb_tx = usb_alloc_urb(0, GFP_KERNEL);
+	if (!cmd->urb_tx) {
+		ar5523_err(ar, "could not allocate urb\n");
+		return -ENOMEM;
+	}
+	cmd->buf_tx = usb_alloc_coherent(ar->dev, AR5523_MAX_TXCMDSZ,
+					 GFP_KERNEL,
+					 &cmd->urb_tx->transfer_dma);
+	if (!cmd->buf_tx) {
+		usb_free_urb(cmd->urb_tx);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+/*
+ * This function is called periodically (every second) when associated to
+ * query device statistics.
+ */
+static void ar5523_stat_work(struct work_struct *work)
+{
+	struct ar5523 *ar = container_of(work, struct ar5523, stat_work.work);
+	int error;
+
+	ar5523_dbg(ar, "%s\n", __func__);
+	mutex_lock(&ar->mutex);
+
+	/*
+	 * Send request for statistics asynchronously once a second. This
+	 * seems to be important. Throughput is a lot better if this is done.
+	 */
+	error = ar5523_cmd_write(ar, WDCMSG_TARGET_GET_STATS, NULL, 0, 0);
+	if (error)
+		ar5523_err(ar, "could not query stats, error %d\n", error);
+	mutex_unlock(&ar->mutex);
+	ieee80211_queue_delayed_work(ar->hw, &ar->stat_work, HZ);
+}
+
+/*
+ * Interface routines to the mac80211 stack.
+ */
+static int ar5523_start(struct ieee80211_hw *hw)
+{
+	struct ar5523 *ar = hw->priv;
+	int error;
+	__be32 val;
+
+	ar5523_dbg(ar, "start called\n");
+
+	mutex_lock(&ar->mutex);
+	val = cpu_to_be32(0);
+	ar5523_cmd_write(ar, WDCMSG_BIND, &val, sizeof(val), 0);
+
+	/* set MAC address */
+	ar5523_config_multi(ar, CFG_MAC_ADDR, &ar->hw->wiphy->perm_addr,
+			    ETH_ALEN);
+
+	/* XXX honor net80211 state */
+	ar5523_config(ar, CFG_RATE_CONTROL_ENABLE, 0x00000001);
+	ar5523_config(ar, CFG_DIVERSITY_CTL, 0x00000001);
+	ar5523_config(ar, CFG_ABOLT, 0x0000003f);
+	ar5523_config(ar, CFG_WME_ENABLED, 0x00000000);
+
+	ar5523_config(ar, CFG_SERVICE_TYPE, 1);
+	ar5523_config(ar, CFG_TP_SCALE, 0x00000000);
+	ar5523_config(ar, CFG_TPC_HALF_DBM5, 0x0000003c);
+	ar5523_config(ar, CFG_TPC_HALF_DBM2, 0x0000003c);
+	ar5523_config(ar, CFG_OVERRD_TX_POWER, 0x00000000);
+	ar5523_config(ar, CFG_GMODE_PROTECTION, 0x00000000);
+	ar5523_config(ar, CFG_GMODE_PROTECT_RATE_INDEX, 0x00000003);
+	ar5523_config(ar, CFG_PROTECTION_TYPE, 0x00000000);
+	ar5523_config(ar, CFG_MODE_CTS, 0x00000002);
+
+	error = ar5523_cmd_read(ar, WDCMSG_TARGET_START, NULL, 0,
+	    &val, sizeof(val), AR5523_CMD_FLAG_MAGIC);
+	if (error) {
+		ar5523_dbg(ar, "could not start target, error %d\n", error);
+		goto err;
+	}
+	ar5523_dbg(ar, "WDCMSG_TARGET_START returns handle: 0x%x\n",
+		   be32_to_cpu(val));
+
+	ar5523_switch_chan(ar);
+
+	val = cpu_to_be32(TARGET_DEVICE_AWAKE);
+	ar5523_cmd_write(ar, WDCMSG_SET_PWR_MODE, &val, sizeof(val), 0);
+	/* XXX? check */
+	ar5523_cmd_write(ar, WDCMSG_RESET_KEY_CACHE, NULL, 0, 0);
+
+	set_bit(AR5523_HW_UP, &ar->flags);
+	queue_work(ar->wq, &ar->rx_refill_work);
+
+	/* enable Rx */
+	ar5523_set_rxfilter(ar, 0, UATH_FILTER_OP_INIT);
+	ar5523_set_rxfilter(ar,
+			    UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST |
+			    UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON,
+			    UATH_FILTER_OP_SET);
+
+	ar5523_set_ledsteady(ar, UATH_LED_ACTIVITY, UATH_LED_ON);
+	ar5523_dbg(ar, "start OK\n");
+
+err:
+	mutex_unlock(&ar->mutex);
+	return error;
+}
+
+static void ar5523_stop(struct ieee80211_hw *hw)
+{
+	struct ar5523 *ar = hw->priv;
+
+	ar5523_dbg(ar, "stop called\n");
+
+	cancel_delayed_work_sync(&ar->stat_work);
+	mutex_lock(&ar->mutex);
+	clear_bit(AR5523_HW_UP, &ar->flags);
+
+	ar5523_set_ledsteady(ar, UATH_LED_LINK, UATH_LED_OFF);
+	ar5523_set_ledsteady(ar, UATH_LED_ACTIVITY, UATH_LED_OFF);
+
+	ar5523_cmd_write(ar, WDCMSG_TARGET_STOP, NULL, 0, 0);
+
+	del_timer_sync(&ar->tx_wd_timer);
+	cancel_work_sync(&ar->tx_wd_work);
+	cancel_work_sync(&ar->rx_refill_work);
+	ar5523_cancel_rx_bufs(ar);
+	mutex_unlock(&ar->mutex);
+}
+
+static int ar5523_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+{
+	struct ar5523 *ar = hw->priv;
+	int ret;
+
+	ar5523_dbg(ar, "set_rts_threshold called\n");
+	mutex_lock(&ar->mutex);
+
+	ret = ar5523_config(ar, CFG_USER_RTS_THRESHOLD, value);
+
+	mutex_unlock(&ar->mutex);
+	return ret;
+}
+
+static void ar5523_flush(struct ieee80211_hw *hw, bool drop)
+{
+	struct ar5523 *ar = hw->priv;
+
+	ar5523_dbg(ar, "flush called\n");
+	ar5523_flush_tx(ar);
+}
+
+static int ar5523_add_interface(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif)
+{
+	struct ar5523 *ar = hw->priv;
+
+	ar5523_dbg(ar, "add interface called\n");
+
+	if (ar->vif) {
+		ar5523_dbg(ar, "invalid add_interface\n");
+		return -EOPNOTSUPP;
+	}
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		ar->vif = vif;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
+static void ar5523_remove_interface(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif)
+{
+	struct ar5523 *ar = hw->priv;
+
+	ar5523_dbg(ar, "remove interface called\n");
+	ar->vif = NULL;
+}
+
+static int ar5523_hwconfig(struct ieee80211_hw *hw, u32 changed)
+{
+	struct ar5523 *ar = hw->priv;
+
+	ar5523_dbg(ar, "config called\n");
+	mutex_lock(&ar->mutex);
+	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+		ar5523_dbg(ar, "Do channel switch\n");
+		ar5523_flush_tx(ar);
+		ar5523_switch_chan(ar);
+	}
+	mutex_unlock(&ar->mutex);
+	return 0;
+}
+
+static int ar5523_get_wlan_mode(struct ar5523 *ar,
+				struct ieee80211_bss_conf *bss_conf)
+{
+	struct ieee80211_supported_band *band;
+	int bit;
+	struct ieee80211_sta *sta;
+	u32 sta_rate_set;
+
+	band = ar->hw->wiphy->bands[ar->hw->conf.channel->band];
+	sta = ieee80211_find_sta(ar->vif, bss_conf->bssid);
+	if (!sta) {
+		ar5523_info(ar, "STA not found!\n");
+		return WLAN_MODE_11b;
+	}
+	sta_rate_set = sta->supp_rates[ar->hw->conf.channel->band];
+
+	for (bit = 0; bit < band->n_bitrates; bit++) {
+		if (sta_rate_set & 1) {
+			int rate = band->bitrates[bit].bitrate;
+			switch (rate) {
+			case 60:
+			case 90:
+			case 120:
+			case 180:
+			case 240:
+			case 360:
+			case 480:
+			case 540:
+				return WLAN_MODE_11g;
+			}
+		}
+		sta_rate_set >>= 1;
+	}
+	return WLAN_MODE_11b;
+}
+
+static void ar5523_create_rateset(struct ar5523 *ar,
+				  struct ieee80211_bss_conf *bss_conf,
+				  struct ar5523_cmd_rateset *rs,
+				  bool basic)
+{
+	struct ieee80211_supported_band *band;
+	struct ieee80211_sta *sta;
+	int bit, i = 0;
+	u32 sta_rate_set, basic_rate_set;
+
+	sta = ieee80211_find_sta(ar->vif, bss_conf->bssid);
+	basic_rate_set = bss_conf->basic_rates;
+	if (!sta) {
+		ar5523_info(ar, "STA not found. Cannot set rates\n");
+		sta_rate_set = bss_conf->basic_rates;
+	} else
+		sta_rate_set = sta->supp_rates[ar->hw->conf.channel->band];
+
+	ar5523_dbg(ar, "sta rate_set = %08x\n", sta_rate_set);
+
+	band = ar->hw->wiphy->bands[ar->hw->conf.channel->band];
+	for (bit = 0; bit < band->n_bitrates; bit++) {
+		BUG_ON(i >= AR5523_MAX_NRATES);
+		ar5523_dbg(ar, "Considering rate %d : %d\n",
+			   band->bitrates[bit].hw_value, sta_rate_set & 1);
+		if (sta_rate_set & 1) {
+			rs->set[i] = band->bitrates[bit].hw_value;
+			if (basic_rate_set & 1 && basic)
+				rs->set[i] |= 0x80;
+			i++;
+		}
+		sta_rate_set >>= 1;
+		basic_rate_set >>= 1;
+	}
+
+	rs->length = i;
+}
+
+static int ar5523_set_basic_rates(struct ar5523 *ar,
+				  struct ieee80211_bss_conf *bss)
+{
+	struct ar5523_cmd_rates rates;
+
+	memset(&rates, 0, sizeof(rates));
+	rates.connid = cpu_to_be32(2);		/* XXX */
+	rates.size   = cpu_to_be32(sizeof(struct ar5523_cmd_rateset));
+	ar5523_create_rateset(ar, bss, &rates.rateset, true);
+
+	return ar5523_cmd_write(ar, WDCMSG_SET_BASIC_RATE, &rates,
+				sizeof(rates), 0);
+}
+
+static int ar5523_create_connection(struct ar5523 *ar,
+				    struct ieee80211_vif *vif,
+				    struct ieee80211_bss_conf *bss)
+{
+	struct ar5523_cmd_create_connection create;
+	int wlan_mode;
+
+	memset(&create, 0, sizeof(create));
+	create.connid = cpu_to_be32(2);
+	create.bssid = cpu_to_be32(0);
+	/* XXX packed or not?  */
+	create.size = cpu_to_be32(sizeof(struct ar5523_cmd_rateset));
+
+	ar5523_create_rateset(ar, bss, &create.connattr.rateset, false);
+
+	wlan_mode = ar5523_get_wlan_mode(ar, bss);
+	create.connattr.wlanmode = cpu_to_be32(wlan_mode);
+
+	return ar5523_cmd_write(ar, WDCMSG_CREATE_CONNECTION, &create,
+				sizeof(create), 0);
+}
+
+static int ar5523_write_associd(struct ar5523 *ar,
+				struct ieee80211_bss_conf *bss)
+{
+	struct ar5523_cmd_set_associd associd;
+
+	memset(&associd, 0, sizeof(associd));
+	associd.defaultrateix = cpu_to_be32(0);	/* XXX */
+	associd.associd = cpu_to_be32(bss->aid);
+	associd.timoffset = cpu_to_be32(0x3b);	/* XXX */
+	memcpy(associd.bssid, bss->bssid, ETH_ALEN);
+	return ar5523_cmd_write(ar, WDCMSG_WRITE_ASSOCID, &associd,
+				sizeof(associd), 0);
+}
+
+static void ar5523_bss_info_changed(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif,
+				    struct ieee80211_bss_conf *bss,
+				    u32 changed)
+{
+	struct ar5523 *ar = hw->priv;
+	int error;
+
+	ar5523_dbg(ar, "bss_info_changed called\n");
+	mutex_lock(&ar->mutex);
+
+	if (!(changed & BSS_CHANGED_ASSOC))
+		goto out_unlock;
+
+	if (bss->assoc) {
+		error = ar5523_create_connection(ar, vif, bss);
+		if (error) {
+			ar5523_err(ar, "could not create connection\n");
+			goto out_unlock;
+		}
+
+		error = ar5523_set_basic_rates(ar, bss);
+		if (error) {
+			ar5523_err(ar, "could not set negotiated rate set\n");
+			goto out_unlock;
+		}
+
+		error = ar5523_write_associd(ar, bss);
+		if (error) {
+			ar5523_err(ar, "could not set association\n");
+			goto out_unlock;
+		}
+
+		/* turn link LED on */
+		ar5523_set_ledsteady(ar, UATH_LED_LINK, UATH_LED_ON);
+		set_bit(AR5523_CONNECTED, &ar->flags);
+		ieee80211_queue_delayed_work(hw, &ar->stat_work, HZ);
+
+	} else {
+		cancel_delayed_work(&ar->stat_work);
+		clear_bit(AR5523_CONNECTED, &ar->flags);
+		ar5523_set_ledsteady(ar, UATH_LED_LINK, UATH_LED_OFF);
+	}
+
+out_unlock:
+	mutex_unlock(&ar->mutex);
+
+}
+
+#define AR5523_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
+				  FIF_ALLMULTI | \
+				  FIF_FCSFAIL | \
+				  FIF_OTHER_BSS)
+
+static void ar5523_configure_filter(struct ieee80211_hw *hw,
+				    unsigned int changed_flags,
+				    unsigned int *total_flags,
+				    u64 multicast)
+{
+	struct ar5523 *ar = hw->priv;
+	u32 filter = 0;
+
+	ar5523_dbg(ar, "configure_filter called\n");
+	mutex_lock(&ar->mutex);
+	ar5523_flush_tx(ar);
+
+	*total_flags &= AR5523_SUPPORTED_FILTERS;
+
+	/* The filters seems strange. UATH_FILTER_RX_BCAST and
+	 * UATH_FILTER_RX_MCAST does not result in those frames being RXed.
+	 * The only way I have found to get [mb]cast frames seems to be
+	 * to set UATH_FILTER_RX_PROM. */
+	filter |= UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST |
+		  UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON |
+		  UATH_FILTER_RX_PROM;
+
+	ar5523_set_rxfilter(ar, 0, UATH_FILTER_OP_INIT);
+	ar5523_set_rxfilter(ar, filter, UATH_FILTER_OP_SET);
+
+	mutex_unlock(&ar->mutex);
+}
+
+static const struct ieee80211_ops ar5523_ops = {
+	.start			= ar5523_start,
+	.stop			= ar5523_stop,
+	.tx			= ar5523_tx,
+	.set_rts_threshold	= ar5523_set_rts_threshold,
+	.add_interface		= ar5523_add_interface,
+	.remove_interface	= ar5523_remove_interface,
+	.config			= ar5523_hwconfig,
+	.bss_info_changed	= ar5523_bss_info_changed,
+	.configure_filter	= ar5523_configure_filter,
+	.flush			= ar5523_flush,
+};
+
+static int ar5523_host_available(struct ar5523 *ar)
+{
+	struct ar5523_cmd_host_available setup;
+
+	/* inform target the host is available */
+	setup.sw_ver_major = cpu_to_be32(ATH_SW_VER_MAJOR);
+	setup.sw_ver_minor = cpu_to_be32(ATH_SW_VER_MINOR);
+	setup.sw_ver_patch = cpu_to_be32(ATH_SW_VER_PATCH);
+	setup.sw_ver_build = cpu_to_be32(ATH_SW_VER_BUILD);
+	return ar5523_cmd_read(ar, WDCMSG_HOST_AVAILABLE,
+			       &setup, sizeof(setup), NULL, 0, 0);
+}
+
+static int ar5523_get_devstatus(struct ar5523 *ar)
+{
+	u8 macaddr[ETH_ALEN];
+	int error;
+
+	/* retrieve MAC address */
+	error = ar5523_get_status(ar, ST_MAC_ADDR, macaddr, ETH_ALEN);
+	if (error) {
+		ar5523_err(ar, "could not read MAC address\n");
+		return error;
+	}
+
+	SET_IEEE80211_PERM_ADDR(ar->hw, macaddr);
+
+	error = ar5523_get_status(ar, ST_SERIAL_NUMBER,
+	    &ar->serial[0], sizeof(ar->serial));
+	if (error) {
+		ar5523_err(ar, "could not read device serial number\n");
+		return error;
+	}
+	return 0;
+}
+
+#define AR5523_SANE_RXBUFSZ 2000
+
+static int ar5523_get_max_rxsz(struct ar5523 *ar)
+{
+	int error;
+	__be32 rxsize;
+
+	/* Get max rx size */
+	error = ar5523_get_status(ar, ST_WDC_TRANSPORT_CHUNK_SIZE, &rxsize,
+				  sizeof(rxsize));
+	if (error != 0) {
+		ar5523_err(ar, "could not read max RX size\n");
+		return error;
+	}
+
+	ar->rxbufsz = be32_to_cpu(rxsize);
+
+	if (!ar->rxbufsz || ar->rxbufsz > AR5523_SANE_RXBUFSZ) {
+		ar5523_err(ar, "Bad rxbufsz from device. Using %d instead\n",
+			   AR5523_SANE_RXBUFSZ);
+		ar->rxbufsz = AR5523_SANE_RXBUFSZ;
+	}
+
+	ar5523_dbg(ar, "Max RX buf size: %d\n", ar->rxbufsz);
+	return 0;
+}
+
+/*
+ * This is copied from rtl818x, but we should probably move this
+ * to common code as in OpenBSD.
+ */
+static const struct ieee80211_rate ar5523_rates[] = {
+	{ .bitrate = 10, .hw_value = 2, },
+	{ .bitrate = 20, .hw_value = 4 },
+	{ .bitrate = 55, .hw_value = 11, },
+	{ .bitrate = 110, .hw_value = 22, },
+	{ .bitrate = 60, .hw_value = 12, },
+	{ .bitrate = 90, .hw_value = 18, },
+	{ .bitrate = 120, .hw_value = 24, },
+	{ .bitrate = 180, .hw_value = 36, },
+	{ .bitrate = 240, .hw_value = 48, },
+	{ .bitrate = 360, .hw_value = 72, },
+	{ .bitrate = 480, .hw_value = 96, },
+	{ .bitrate = 540, .hw_value = 108, },
+};
+
+static const struct ieee80211_channel ar5523_channels[] = {
+	{ .center_freq = 2412 },
+	{ .center_freq = 2417 },
+	{ .center_freq = 2422 },
+	{ .center_freq = 2427 },
+	{ .center_freq = 2432 },
+	{ .center_freq = 2437 },
+	{ .center_freq = 2442 },
+	{ .center_freq = 2447 },
+	{ .center_freq = 2452 },
+	{ .center_freq = 2457 },
+	{ .center_freq = 2462 },
+	{ .center_freq = 2467 },
+	{ .center_freq = 2472 },
+	{ .center_freq = 2484 },
+};
+
+static int ar5523_init_modes(struct ar5523 *ar)
+{
+	BUILD_BUG_ON(sizeof(ar->channels) != sizeof(ar5523_channels));
+	BUILD_BUG_ON(sizeof(ar->rates) != sizeof(ar5523_rates));
+
+	memcpy(ar->channels, ar5523_channels, sizeof(ar5523_channels));
+	memcpy(ar->rates, ar5523_rates, sizeof(ar5523_rates));
+
+	ar->band.band = IEEE80211_BAND_2GHZ;
+	ar->band.channels = ar->channels;
+	ar->band.n_channels = ARRAY_SIZE(ar5523_channels);
+	ar->band.bitrates = ar->rates;
+	ar->band.n_bitrates = ARRAY_SIZE(ar5523_rates);
+	ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar->band;
+	return 0;
+}
+
+/*
+ * Load the MIPS R4000 microcode into the device.  Once the image is loaded,
+ * the device will detach itself from the bus and reattach later with a new
+ * product Id (a la ezusb).
+ */
+static int ar5523_load_firmware(struct usb_device *dev)
+{
+	struct ar5523_fwblock *txblock, *rxblock;
+	const struct firmware *fw;
+	void *fwbuf;
+	int len, offset;
+	int foolen; /* XXX(hch): handle short transfers */
+	int error = -ENXIO;
+
+	if (request_firmware(&fw, AR5523_FIRMWARE_FILE, &dev->dev)) {
+		dev_err(&dev->dev, "no firmware found: %s\n",
+			AR5523_FIRMWARE_FILE);
+		return -ENOENT;
+	}
+
+	txblock = kmalloc(sizeof(*txblock), GFP_KERNEL);
+	if (!txblock)
+		goto out;
+
+	rxblock = kmalloc(sizeof(*rxblock), GFP_KERNEL);
+	if (!rxblock)
+		goto out_free_txblock;
+
+	fwbuf = kmalloc(AR5523_MAX_FWBLOCK_SIZE, GFP_KERNEL);
+	if (!fwbuf)
+		goto out_free_rxblock;
+
+	memset(txblock, 0, sizeof(struct ar5523_fwblock));
+	txblock->flags = cpu_to_be32(AR5523_WRITE_BLOCK);
+	txblock->total = cpu_to_be32(fw->size);
+
+	offset = 0;
+	len = fw->size;
+	while (len > 0) {
+		int mlen = min(len, AR5523_MAX_FWBLOCK_SIZE);
+
+		txblock->remain = cpu_to_be32(len - mlen);
+		txblock->len = cpu_to_be32(mlen);
+
+		/* send firmware block meta-data */
+		error = usb_bulk_msg(dev, ar5523_cmd_tx_pipe(dev),
+				     txblock, sizeof(*txblock), &foolen,
+				     AR5523_CMD_TIMEOUT);
+		if (error) {
+			dev_err(&dev->dev,
+				"could not send firmware block info\n");
+			goto out_free_fwbuf;
+		}
+
+		/* send firmware block data */
+		memcpy(fwbuf, fw->data + offset, mlen);
+		error = usb_bulk_msg(dev, ar5523_data_tx_pipe(dev),
+				     fwbuf, mlen, &foolen,
+				     AR5523_DATA_TIMEOUT);
+		if (error) {
+			dev_err(&dev->dev,
+				"could not send firmware block data\n");
+			goto out_free_fwbuf;
+		}
+
+		/* wait for ack from firmware */
+		error = usb_bulk_msg(dev, ar5523_cmd_rx_pipe(dev),
+				     rxblock, sizeof(*rxblock), &foolen,
+				     AR5523_CMD_TIMEOUT);
+		if (error) {
+			dev_err(&dev->dev,
+				"could not read firmware answer\n");
+			goto out_free_fwbuf;
+		}
+
+		len -= mlen;
+		offset += mlen;
+	}
+
+	/*
+	 * Set the error to -ENXIO to make sure we continue probing for
+	 * a driver.
+	 */
+	error = -ENXIO;
+
+ out_free_fwbuf:
+	kfree(fwbuf);
+ out_free_rxblock:
+	kfree(rxblock);
+ out_free_txblock:
+	kfree(txblock);
+ out:
+	release_firmware(fw);
+	return error;
+}
+
+static int ar5523_probe(struct usb_interface *intf,
+			const struct usb_device_id *id)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct ieee80211_hw *hw;
+	struct ar5523 *ar;
+	int error = -ENOMEM;
+
+	/*
+	 * Load firmware if the device requires it.  This will return
+	 * -ENXIO on success and we'll get called back afer the usb
+	 * id changes to indicate that the firmware is present.
+	 */
+	if (id->driver_info & AR5523_FLAG_PRE_FIRMWARE)
+		return ar5523_load_firmware(dev);
+
+
+	hw = ieee80211_alloc_hw(sizeof(*ar), &ar5523_ops);
+	if (!hw)
+		goto out;
+	SET_IEEE80211_DEV(hw, &intf->dev);
+
+	ar = hw->priv;
+	ar->hw = hw;
+	ar->dev = dev;
+	mutex_init(&ar->mutex);
+
+	INIT_DELAYED_WORK(&ar->stat_work, ar5523_stat_work);
+	init_timer(&ar->tx_wd_timer);
+	setup_timer(&ar->tx_wd_timer, ar5523_tx_wd_timer, (unsigned long) ar);
+	INIT_WORK(&ar->tx_wd_work, ar5523_tx_wd_work);
+	INIT_WORK(&ar->tx_work, ar5523_tx_work);
+	INIT_LIST_HEAD(&ar->tx_queue_pending);
+	INIT_LIST_HEAD(&ar->tx_queue_submitted);
+	spin_lock_init(&ar->tx_data_list_lock);
+	atomic_set(&ar->tx_nr_total, 0);
+	atomic_set(&ar->tx_nr_pending, 0);
+	init_waitqueue_head(&ar->tx_flush_waitq);
+
+	atomic_set(&ar->rx_data_free_cnt, 0);
+	INIT_WORK(&ar->rx_refill_work, ar5523_rx_refill_work);
+	INIT_LIST_HEAD(&ar->rx_data_free);
+	INIT_LIST_HEAD(&ar->rx_data_used);
+	spin_lock_init(&ar->rx_data_list_lock);
+
+	ar->wq = create_singlethread_workqueue("ar5523");
+	if (!ar->wq) {
+		ar5523_err(ar, "Could not create wq\n");
+		goto out_free_ar;
+	}
+
+	error = ar5523_alloc_rx_bufs(ar);
+	if (error) {
+		ar5523_err(ar, "Could not allocate rx buffers\n");
+		goto out_free_wq;
+	}
+
+	error = ar5523_alloc_rx_cmd(ar);
+	if (error) {
+		ar5523_err(ar, "Could not allocate rx command buffers\n");
+		goto out_free_rx_bufs;
+	}
+
+	error = ar5523_alloc_tx_cmd(ar);
+	if (error) {
+		ar5523_err(ar, "Could not allocate tx command buffers\n");
+		goto out_free_rx_cmd;
+	}
+
+	error = ar5523_submit_rx_cmd(ar);
+	if (error) {
+		ar5523_err(ar, "Failed to submit rx cmd\n");
+		goto out_free_tx_cmd;
+	}
+
+	/*
+	 * We're now ready to send/receive firmware commands.
+	 */
+	error = ar5523_host_available(ar);
+	if (error) {
+		ar5523_err(ar, "could not initialize adapter\n");
+		goto out_cancel_rx_cmd;
+	}
+
+	error = ar5523_get_max_rxsz(ar);
+	if (error) {
+		ar5523_err(ar, "could not get caps from adapter\n");
+		goto out_cancel_rx_cmd;
+	}
+
+	error = ar5523_get_devcap(ar);
+	if (error) {
+		ar5523_err(ar, "could not get caps from adapter\n");
+		goto out_cancel_rx_cmd;
+	}
+
+	error = ar5523_get_devstatus(ar);
+	if (error != 0) {
+		ar5523_err(ar, "could not get device status\n");
+		goto out_cancel_rx_cmd;
+	}
+
+	ar5523_info(ar, "MAC/BBP AR5523, RF AR%c112\n",
+			(id->driver_info & AR5523_FLAG_ABG) ? '5' : '2');
+
+	ar->vif = NULL;
+	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+		    IEEE80211_HW_SIGNAL_DBM |
+		    IEEE80211_HW_HAS_RATE_CONTROL;
+	hw->extra_tx_headroom = sizeof(struct ar5523_tx_desc) +
+				sizeof(struct ar5523_chunk);
+	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+	hw->queues = 1;
+
+	error = ar5523_init_modes(ar);
+	if (error)
+		goto out_cancel_rx_cmd;
+
+	usb_set_intfdata(intf, hw);
+
+	error = ieee80211_register_hw(hw);
+	if (error) {
+		ar5523_err(ar, "could not register device\n");
+		goto out_cancel_rx_cmd;
+	}
+
+	ar5523_info(ar, "Found and initialized AR5523 device\n");
+	return 0;
+
+out_cancel_rx_cmd:
+	ar5523_cancel_rx_cmd(ar);
+out_free_tx_cmd:
+	ar5523_free_tx_cmd(ar);
+out_free_rx_cmd:
+	ar5523_free_rx_cmd(ar);
+out_free_rx_bufs:
+	ar5523_free_rx_bufs(ar);
+out_free_wq:
+	destroy_workqueue(ar->wq);
+out_free_ar:
+	ieee80211_free_hw(hw);
+out:
+	return error;
+}
+
+static void ar5523_disconnect(struct usb_interface *intf)
+{
+	struct ieee80211_hw *hw = usb_get_intfdata(intf);
+	struct ar5523 *ar = hw->priv;
+
+	ar5523_dbg(ar, "detaching\n");
+	set_bit(AR5523_USB_DISCONNECTED, &ar->flags);
+
+	ieee80211_unregister_hw(hw);
+
+	ar5523_cancel_rx_cmd(ar);
+	ar5523_free_tx_cmd(ar);
+	ar5523_free_rx_cmd(ar);
+	ar5523_free_rx_bufs(ar);
+
+	destroy_workqueue(ar->wq);
+
+	ieee80211_free_hw(hw);
+	usb_set_intfdata(intf, NULL);
+}
+
+#define AR5523_DEVICE_UG(vendor, device) \
+	{ USB_DEVICE((vendor), (device)) }, \
+	{ USB_DEVICE((vendor), (device) + 1), \
+		.driver_info = AR5523_FLAG_PRE_FIRMWARE }
+#define AR5523_DEVICE_UX(vendor, device) \
+	{ USB_DEVICE((vendor), (device)), \
+		.driver_info = AR5523_FLAG_ABG }, \
+	{ USB_DEVICE((vendor), (device) + 1), \
+		.driver_info = AR5523_FLAG_ABG|AR5523_FLAG_PRE_FIRMWARE }
+
+static struct usb_device_id ar5523_id_table[] = {
+	AR5523_DEVICE_UG(0x168c, 0x0001),	/* Atheros / AR5523 */
+	AR5523_DEVICE_UG(0x0cf3, 0x0001),	/* Atheros2 / AR5523_1 */
+	AR5523_DEVICE_UG(0x0cf3, 0x0003),	/* Atheros2 / AR5523_2 */
+	AR5523_DEVICE_UX(0x0cf3, 0x0005),	/* Atheros2 / AR5523_3 */
+	AR5523_DEVICE_UG(0x0d8e, 0x7801),	/* Conceptronic / AR5523_1 */
+	AR5523_DEVICE_UX(0x0d8e, 0x7811),	/* Conceptronic / AR5523_2 */
+	AR5523_DEVICE_UX(0x2001, 0x3a00),	/* Dlink / DWLAG132 */
+	AR5523_DEVICE_UG(0x2001, 0x3a02),	/* Dlink / DWLG132 */
+	AR5523_DEVICE_UX(0x2001, 0x3a04),	/* Dlink / DWLAG122 */
+	AR5523_DEVICE_UG(0x1690, 0x0712),	/* Gigaset / AR5523 */
+	AR5523_DEVICE_UG(0x1690, 0x0710),	/* Gigaset / SMCWUSBTG */
+	AR5523_DEVICE_UG(0x129b, 0x160c),	/* Gigaset / USB stick 108
+						   (CyberTAN Technology) */
+	AR5523_DEVICE_UG(0x16ab, 0x7801),	/* Globalsun / AR5523_1 */
+	AR5523_DEVICE_UX(0x16ab, 0x7811),	/* Globalsun / AR5523_2 */
+	AR5523_DEVICE_UG(0x0d8e, 0x7802),	/* Globalsun / AR5523_3 */
+	AR5523_DEVICE_UX(0x0846, 0x4300),	/* Netgear / WG111U */
+	AR5523_DEVICE_UG(0x0846, 0x4250),	/* Netgear / WG111T */
+	AR5523_DEVICE_UG(0x0846, 0x5f00),	/* Netgear / WPN111 */
+	AR5523_DEVICE_UG(0x157e, 0x3006),	/* Umedia / AR5523_1 */
+	AR5523_DEVICE_UX(0x157e, 0x3205),	/* Umedia / AR5523_2 */
+	AR5523_DEVICE_UG(0x157e, 0x3006),	/* Umedia / TEW444UBEU */
+	AR5523_DEVICE_UG(0x1435, 0x0826),	/* Wistronneweb / AR5523_1 */
+	AR5523_DEVICE_UX(0x1435, 0x0828),	/* Wistronneweb / AR5523_2 */
+	AR5523_DEVICE_UG(0x0cde, 0x0012),	/* Zcom / AR5523 */
+	AR5523_DEVICE_UG(0x1385, 0x4250),	/* Netgear3 / WG111T (2) */
+	AR5523_DEVICE_UG(0x1385, 0x5f00),	/* Netgear / WPN111 */
+	AR5523_DEVICE_UG(0x1385, 0x5f02),	/* Netgear / WPN111 */
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, ar5523_id_table);
+
+static struct usb_driver ar5523_driver = {
+	.name		= "ar5523",
+	.id_table	= ar5523_id_table,
+	.probe		= ar5523_probe,
+	.disconnect	= ar5523_disconnect,
+};
+
+module_usb_driver(ar5523_driver);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_FIRMWARE(AR5523_FIRMWARE_FILE);
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.h b/drivers/net/wireless/ath/ar5523/ar5523.h
new file mode 100644
index 0000000..00c6fd3
--- /dev/null
+++ b/drivers/net/wireless/ath/ar5523/ar5523.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * Copyright (c) 2007 Christoph Hellwig <hch@lst.de>
+ * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org>
+ * Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define AR5523_FLAG_PRE_FIRMWARE	(1 << 0)
+#define AR5523_FLAG_ABG			(1 << 1)
+
+#define AR5523_FIRMWARE_FILE	"ar5523.bin"
+
+#define AR5523_CMD_TX_PIPE	0x01
+#define	AR5523_DATA_TX_PIPE	0x02
+#define	AR5523_CMD_RX_PIPE	0x81
+#define	AR5523_DATA_RX_PIPE	0x82
+
+#define ar5523_cmd_tx_pipe(dev) \
+	usb_sndbulkpipe((dev), AR5523_CMD_TX_PIPE)
+#define ar5523_data_tx_pipe(dev) \
+	usb_sndbulkpipe((dev), AR5523_DATA_TX_PIPE)
+#define ar5523_cmd_rx_pipe(dev) \
+	usb_rcvbulkpipe((dev), AR5523_CMD_RX_PIPE)
+#define ar5523_data_rx_pipe(dev) \
+	usb_rcvbulkpipe((dev), AR5523_DATA_RX_PIPE)
+
+#define	AR5523_DATA_TIMEOUT	10000
+#define	AR5523_CMD_TIMEOUT	1000
+
+#define AR5523_TX_DATA_COUNT		8
+#define AR5523_TX_DATA_RESTART_COUNT	2
+#define AR5523_RX_DATA_COUNT		16
+#define AR5523_RX_DATA_REFILL_COUNT	8
+
+#define AR5523_CMD_ID	1
+#define AR5523_DATA_ID	2
+
+#define AR5523_TX_WD_TIMEOUT	(HZ * 2)
+#define AR5523_FLUSH_TIMEOUT	(HZ * 3)
+
+enum AR5523_flags {
+	AR5523_HW_UP,
+	AR5523_USB_DISCONNECTED,
+	AR5523_CONNECTED
+};
+
+struct ar5523_tx_cmd {
+	struct ar5523		*ar;
+	struct urb		*urb_tx;
+	void			*buf_tx;
+	void			*odata;
+	int			olen;
+	int			flags;
+	int			res;
+	struct completion	done;
+};
+
+/* This struct is placed in tx_info->driver_data. It must not be larger
+ *  than IEEE80211_TX_INFO_DRIVER_DATA_SIZE.
+ */
+struct ar5523_tx_data {
+	struct list_head	list;
+	struct ar5523		*ar;
+	struct sk_buff		*skb;
+	struct urb		*urb;
+};
+
+struct ar5523_rx_data {
+	struct	list_head	list;
+	struct ar5523		*ar;
+	struct urb		*urb;
+	struct sk_buff		*skb;
+};
+
+struct ar5523 {
+	struct usb_device	*dev;
+	struct ieee80211_hw	*hw;
+
+	unsigned long		flags;
+	struct mutex		mutex;
+	struct workqueue_struct *wq;
+
+	struct ar5523_tx_cmd	tx_cmd;
+
+	struct delayed_work	stat_work;
+
+	struct timer_list	tx_wd_timer;
+	struct work_struct	tx_wd_work;
+	struct work_struct	tx_work;
+	struct list_head	tx_queue_pending;
+	struct list_head	tx_queue_submitted;
+	spinlock_t		tx_data_list_lock;
+	wait_queue_head_t	tx_flush_waitq;
+
+	/* Queued + Submitted TX frames */
+	atomic_t		tx_nr_total;
+
+	/* Submitted TX frames */
+	atomic_t		tx_nr_pending;
+
+	void			*rx_cmd_buf;
+	struct urb		*rx_cmd_urb;
+
+	struct ar5523_rx_data	rx_data[AR5523_RX_DATA_COUNT];
+	spinlock_t		rx_data_list_lock;
+	struct list_head	rx_data_free;
+	struct list_head	rx_data_used;
+	atomic_t		rx_data_free_cnt;
+
+	struct work_struct	rx_refill_work;
+
+	unsigned int		rxbufsz;
+	u8			serial[16];
+
+	struct ieee80211_channel channels[14];
+	struct ieee80211_rate	rates[12];
+	struct ieee80211_supported_band band;
+	struct ieee80211_vif	*vif;
+};
+
+/* flags for sending firmware commands */
+#define AR5523_CMD_FLAG_READ	(1 << 1)
+#define AR5523_CMD_FLAG_MAGIC	(1 << 2)
+
+#define ar5523_dbg(ar, format, arg...) \
+	dev_dbg(&(ar)->dev->dev, format, ## arg)
+
+/* On USB hot-unplug there can be a lot of URBs in flight and they'll all
+ * fail. Instead of dealing with them in every possible place just surpress
+ * any messages on USB disconnect.
+ */
+#define ar5523_err(ar, format, arg...) \
+do { \
+	if (!test_bit(AR5523_USB_DISCONNECTED, &ar->flags)) { \
+		dev_err(&(ar)->dev->dev, format, ## arg); \
+	} \
+} while (0)
+#define ar5523_info(ar, format, arg...)	\
+	dev_info(&(ar)->dev->dev, format, ## arg)
diff --git a/drivers/net/wireless/ath/ar5523/ar5523_hw.h b/drivers/net/wireless/ath/ar5523/ar5523_hw.h
new file mode 100644
index 0000000..0fe2c80
--- /dev/null
+++ b/drivers/net/wireless/ath/ar5523/ar5523_hw.h
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * Copyright (c) 2007 Christoph Hellwig <hch@lst.de>
+ * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org>
+ * Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* all fields are big endian */
+struct ar5523_fwblock {
+	__be32		flags;
+#define AR5523_WRITE_BLOCK	(1 << 4)
+
+	__be32	len;
+#define AR5523_MAX_FWBLOCK_SIZE	2048
+
+	__be32		total;
+	__be32		remain;
+	__be32		rxtotal;
+	__be32		pad[123];
+} __packed;
+
+#define AR5523_MAX_RXCMDSZ	1024
+#define AR5523_MAX_TXCMDSZ	1024
+
+struct ar5523_cmd_hdr {
+	__be32		len;
+	__be32		code;
+/* NB: these are defined for rev 1.5 firmware; rev 1.6 is different */
+/* messages from Host -> Target */
+#define	WDCMSG_HOST_AVAILABLE		0x01
+#define WDCMSG_BIND			0x02
+#define WDCMSG_TARGET_RESET		0x03
+#define WDCMSG_TARGET_GET_CAPABILITY	0x04
+#define WDCMSG_TARGET_SET_CONFIG	0x05
+#define WDCMSG_TARGET_GET_STATUS	0x06
+#define WDCMSG_TARGET_GET_STATS		0x07
+#define WDCMSG_TARGET_START		0x08
+#define WDCMSG_TARGET_STOP		0x09
+#define WDCMSG_TARGET_ENABLE		0x0a
+#define WDCMSG_TARGET_DISABLE		0x0b
+#define	WDCMSG_CREATE_CONNECTION	0x0c
+#define WDCMSG_UPDATE_CONNECT_ATTR	0x0d
+#define	WDCMSG_DELETE_CONNECT		0x0e
+#define	WDCMSG_SEND			0x0f
+#define WDCMSG_FLUSH			0x10
+/* messages from Target -> Host */
+#define	WDCMSG_STATS_UPDATE		0x11
+#define	WDCMSG_BMISS			0x12
+#define	WDCMSG_DEVICE_AVAIL		0x13
+#define	WDCMSG_SEND_COMPLETE		0x14
+#define	WDCMSG_DATA_AVAIL		0x15
+#define	WDCMSG_SET_PWR_MODE		0x16
+#define	WDCMSG_BMISS_ACK		0x17
+#define	WDCMSG_SET_LED_STEADY		0x18
+#define	WDCMSG_SET_LED_BLINK		0x19
+/* more messages */
+#define	WDCMSG_SETUP_BEACON_DESC	0x1a
+#define	WDCMSG_BEACON_INIT		0x1b
+#define	WDCMSG_RESET_KEY_CACHE		0x1c
+#define	WDCMSG_RESET_KEY_CACHE_ENTRY	0x1d
+#define	WDCMSG_SET_KEY_CACHE_ENTRY	0x1e
+#define	WDCMSG_SET_DECOMP_MASK		0x1f
+#define	WDCMSG_SET_REGULATORY_DOMAIN	0x20
+#define	WDCMSG_SET_LED_STATE		0x21
+#define	WDCMSG_WRITE_ASSOCID		0x22
+#define	WDCMSG_SET_STA_BEACON_TIMERS	0x23
+#define	WDCMSG_GET_TSF			0x24
+#define	WDCMSG_RESET_TSF		0x25
+#define	WDCMSG_SET_ADHOC_MODE		0x26
+#define	WDCMSG_SET_BASIC_RATE		0x27
+#define	WDCMSG_MIB_CONTROL		0x28
+#define	WDCMSG_GET_CHANNEL_DATA		0x29
+#define	WDCMSG_GET_CUR_RSSI		0x2a
+#define	WDCMSG_SET_ANTENNA_SWITCH	0x2b
+#define	WDCMSG_USE_SHORT_SLOT_TIME	0x2f
+#define	WDCMSG_SET_POWER_MODE		0x30
+#define	WDCMSG_SETUP_PSPOLL_DESC	0x31
+#define	WDCMSG_SET_RX_MULTICAST_FILTER	0x32
+#define	WDCMSG_RX_FILTER		0x33
+#define	WDCMSG_PER_CALIBRATION		0x34
+#define	WDCMSG_RESET			0x35
+#define	WDCMSG_DISABLE			0x36
+#define	WDCMSG_PHY_DISABLE		0x37
+#define	WDCMSG_SET_TX_POWER_LIMIT	0x38
+#define	WDCMSG_SET_TX_QUEUE_PARAMS	0x39
+#define	WDCMSG_SETUP_TX_QUEUE		0x3a
+#define	WDCMSG_RELEASE_TX_QUEUE		0x3b
+#define	WDCMSG_SET_DEFAULT_KEY		0x43
+
+	__u32		priv;	/* driver private data,
+				   don't care about endianess */
+	__be32		magic;
+	__be32		reserved2[4];
+};
+
+struct ar5523_cmd_host_available {
+	__be32	sw_ver_major;
+	__be32	sw_ver_minor;
+	__be32	sw_ver_patch;
+	__be32	sw_ver_build;
+} __packed;
+
+#define	ATH_SW_VER_MAJOR	1
+#define	ATH_SW_VER_MINOR	5
+#define	ATH_SW_VER_PATCH	0
+#define	ATH_SW_VER_BUILD	9999
+
+struct ar5523_chunk {
+	u8		seqnum;		/* sequence number for ordering */
+	u8		flags;
+#define	UATH_CFLAGS_FINAL	0x01	/* final chunk of a msg */
+#define	UATH_CFLAGS_RXMSG	0x02	/* chunk contains rx completion */
+#define	UATH_CFLAGS_DEBUG	0x04	/* for debugging */
+	__be16		length;		/* chunk size in bytes */
+	/* chunk data follows */
+} __packed;
+
+/*
+ * Message format for a WDCMSG_DATA_AVAIL message from Target to Host.
+ */
+struct ar5523_rx_desc {
+	__be32	len;		/* msg length including header */
+	__be32	code;		/* WDCMSG_DATA_AVAIL */
+	__be32	gennum;		/* generation number */
+	__be32	status;		/* start of RECEIVE_INFO */
+#define	UATH_STATUS_OK			0
+#define	UATH_STATUS_STOP_IN_PROGRESS	1
+#define	UATH_STATUS_CRC_ERR		2
+#define	UATH_STATUS_PHY_ERR		3
+#define	UATH_STATUS_DECRYPT_CRC_ERR	4
+#define	UATH_STATUS_DECRYPT_MIC_ERR	5
+#define	UATH_STATUS_DECOMP_ERR		6
+#define	UATH_STATUS_KEY_ERR		7
+#define	UATH_STATUS_ERR			8
+	__be32	tstamp_low;	/* low-order 32-bits of rx timestamp */
+	__be32	tstamp_high;	/* high-order 32-bits of rx timestamp */
+	__be32	framelen;	/* frame length */
+	__be32	rate;		/* rx rate code */
+	__be32	antenna;
+	__be32	rssi;
+	__be32	channel;
+	__be32	phyerror;
+	__be32	connix;		/* key table ix for bss traffic */
+	__be32	decrypterror;
+	__be32	keycachemiss;
+	__be32	pad;		/* XXX? */
+} __packed;
+
+struct ar5523_tx_desc {
+	__be32	msglen;
+	u32	msgid;		/* msg id (supplied by host) */
+	__be32	type;		/* opcode: WDMSG_SEND or WDCMSG_FLUSH */
+	__be32	txqid;		/* tx queue id and flags */
+#define	UATH_TXQID_MASK		0x0f
+#define	UATH_TXQID_MINRATE	0x10	/* use min tx rate */
+#define	UATH_TXQID_FF		0x20	/* content is fast frame */
+	__be32	connid;		/* tx connection id */
+#define UATH_ID_INVALID	0xffffffff	/* for sending prior to connection */
+	__be32	flags;		/* non-zero if response desired */
+#define UATH_TX_NOTIFY	(1 << 24)	/* f/w will send a UATH_NOTIF_TX */
+	__be32	buflen;		/* payload length */
+} __packed;
+
+
+#define AR5523_ID_BSS		2
+#define AR5523_ID_BROADCAST	0xffffffff
+
+/* structure for command UATH_CMD_WRITE_MAC */
+struct ar5523_write_mac {
+	__be32	reg;
+	__be32	len;
+	u8		data[32];
+} __packed;
+
+struct ar5523_cmd_rateset {
+	__u8		length;
+#define AR5523_MAX_NRATES	32
+	__u8		set[AR5523_MAX_NRATES];
+};
+
+struct ar5523_cmd_set_associd {		/* AR5523_WRITE_ASSOCID */
+	__be32	defaultrateix;
+	__be32	associd;
+	__be32	timoffset;
+	__be32	turboprime;
+	__u8	bssid[6];
+} __packed;
+
+/* structure for command WDCMSG_RESET */
+struct ar5523_cmd_reset {
+	__be32	flags;		/* channel flags */
+#define	UATH_CHAN_TURBO	0x0100
+#define	UATH_CHAN_CCK	0x0200
+#define	UATH_CHAN_OFDM	0x0400
+#define	UATH_CHAN_2GHZ	0x1000
+#define	UATH_CHAN_5GHZ	0x2000
+	__be32	freq;		/* channel frequency */
+	__be32	maxrdpower;
+	__be32	cfgctl;
+	__be32	twiceantennareduction;
+	__be32	channelchange;
+	__be32	keeprccontent;
+} __packed;
+
+/* structure for command WDCMSG_SET_BASIC_RATE */
+struct ar5523_cmd_rates {
+	__be32	connid;
+	__be32	keeprccontent;
+	__be32	size;
+	struct ar5523_cmd_rateset rateset;
+} __packed;
+
+enum {
+	WLAN_MODE_NONE = 0,
+	WLAN_MODE_11b,
+	WLAN_MODE_11a,
+	WLAN_MODE_11g,
+	WLAN_MODE_11a_TURBO,
+	WLAN_MODE_11g_TURBO,
+	WLAN_MODE_11a_TURBO_PRIME,
+	WLAN_MODE_11g_TURBO_PRIME,
+	WLAN_MODE_11a_XR,
+	WLAN_MODE_11g_XR,
+};
+
+struct ar5523_cmd_connection_attr {
+	__be32	longpreambleonly;
+	struct ar5523_cmd_rateset	rateset;
+	__be32	wlanmode;
+} __packed;
+
+/* structure for command AR5523_CREATE_CONNECTION */
+struct ar5523_cmd_create_connection {
+	__be32	connid;
+	__be32	bssid;
+	__be32	size;
+	struct ar5523_cmd_connection_attr	connattr;
+} __packed;
+
+struct ar5523_cmd_ledsteady {		/* WDCMSG_SET_LED_STEADY */
+	__be32	lednum;
+#define UATH_LED_LINK		0
+#define UATH_LED_ACTIVITY	1
+	__be32	ledmode;
+#define UATH_LED_OFF	0
+#define UATH_LED_ON	1
+} __packed;
+
+struct ar5523_cmd_ledblink {		/* WDCMSG_SET_LED_BLINK */
+	__be32	lednum;
+	__be32	ledmode;
+	__be32	blinkrate;
+	__be32	slowmode;
+} __packed;
+
+struct ar5523_cmd_ledstate {		/* WDCMSG_SET_LED_STATE */
+	__be32	connected;
+} __packed;
+
+struct ar5523_cmd_txq_attr {
+	__be32	priority;
+	__be32	aifs;
+	__be32	logcwmin;
+	__be32	logcwmax;
+	__be32	bursttime;
+	__be32	mode;
+	__be32	qflags;
+} __packed;
+
+struct ar5523_cmd_txq_setup {		/* WDCMSG_SETUP_TX_QUEUE */
+	__be32	qid;
+	__be32	len;
+	struct ar5523_cmd_txq_attr attr;
+} __packed;
+
+struct ar5523_cmd_rx_filter {		/* WDCMSG_RX_FILTER */
+	__be32	bits;
+#define UATH_FILTER_RX_UCAST		0x00000001
+#define UATH_FILTER_RX_MCAST		0x00000002
+#define UATH_FILTER_RX_BCAST		0x00000004
+#define UATH_FILTER_RX_CONTROL		0x00000008
+#define UATH_FILTER_RX_BEACON		0x00000010	/* beacon frames */
+#define UATH_FILTER_RX_PROM		0x00000020	/* promiscuous mode */
+#define UATH_FILTER_RX_PHY_ERR		0x00000040	/* phy errors */
+#define UATH_FILTER_RX_PHY_RADAR	0x00000080	/* radar phy errors */
+#define UATH_FILTER_RX_XR_POOL		0x00000400	/* XR group polls */
+#define UATH_FILTER_RX_PROBE_REQ	0x00000800
+	__be32	op;
+#define UATH_FILTER_OP_INIT		0x0
+#define UATH_FILTER_OP_SET		0x1
+#define UATH_FILTER_OP_CLEAR		0x2
+#define UATH_FILTER_OP_TEMP		0x3
+#define UATH_FILTER_OP_RESTORE		0x4
+} __packed;
+
+enum {
+	CFG_NONE,			/* Sentinal to indicate "no config" */
+	CFG_REG_DOMAIN,			/* Regulatory Domain */
+	CFG_RATE_CONTROL_ENABLE,
+	CFG_DEF_XMIT_DATA_RATE,		/* NB: if rate control is not enabled */
+	CFG_HW_TX_RETRIES,
+	CFG_SW_TX_RETRIES,
+	CFG_SLOW_CLOCK_ENABLE,
+	CFG_COMP_PROC,
+	CFG_USER_RTS_THRESHOLD,
+	CFG_XR2NORM_RATE_THRESHOLD,
+	CFG_XRMODE_SWITCH_COUNT,
+	CFG_PROTECTION_TYPE,
+	CFG_BURST_SEQ_THRESHOLD,
+	CFG_ABOLT,
+	CFG_IQ_LOG_COUNT_MAX,
+	CFG_MODE_CTS,
+	CFG_WME_ENABLED,
+	CFG_GPRS_CBR_PERIOD,
+	CFG_SERVICE_TYPE,
+	/* MAC Address to use.  Overrides EEPROM */
+	CFG_MAC_ADDR,
+	CFG_DEBUG_EAR,
+	CFG_INIT_REGS,
+	/* An ID for use in error & debug messages */
+	CFG_DEBUG_ID,
+	CFG_COMP_WIN_SZ,
+	CFG_DIVERSITY_CTL,
+	CFG_TP_SCALE,
+	CFG_TPC_HALF_DBM5,
+	CFG_TPC_HALF_DBM2,
+	CFG_OVERRD_TX_POWER,
+	CFG_USE_32KHZ_CLOCK,
+	CFG_GMODE_PROTECTION,
+	CFG_GMODE_PROTECT_RATE_INDEX,
+	CFG_GMODE_NON_ERP_PREAMBLE,
+	CFG_WDC_TRANSPORT_CHUNK_SIZE,
+};
+
+enum {
+	/* Sentinal to indicate "no capability" */
+	CAP_NONE,
+	CAP_ALL,			/* ALL capabilities */
+	CAP_TARGET_VERSION,
+	CAP_TARGET_REVISION,
+	CAP_MAC_VERSION,
+	CAP_MAC_REVISION,
+	CAP_PHY_REVISION,
+	CAP_ANALOG_5GHz_REVISION,
+	CAP_ANALOG_2GHz_REVISION,
+	/* Target supports WDC message debug features */
+	CAP_DEBUG_WDCMSG_SUPPORT,
+
+	CAP_REG_DOMAIN,
+	CAP_COUNTRY_CODE,
+	CAP_REG_CAP_BITS,
+
+	CAP_WIRELESS_MODES,
+	CAP_CHAN_SPREAD_SUPPORT,
+	CAP_SLEEP_AFTER_BEACON_BROKEN,
+	CAP_COMPRESS_SUPPORT,
+	CAP_BURST_SUPPORT,
+	CAP_FAST_FRAMES_SUPPORT,
+	CAP_CHAP_TUNING_SUPPORT,
+	CAP_TURBOG_SUPPORT,
+	CAP_TURBO_PRIME_SUPPORT,
+	CAP_DEVICE_TYPE,
+	CAP_XR_SUPPORT,
+	CAP_WME_SUPPORT,
+	CAP_TOTAL_QUEUES,
+	CAP_CONNECTION_ID_MAX,		/* Should absorb CAP_KEY_CACHE_SIZE */
+
+	CAP_LOW_5GHZ_CHAN,
+	CAP_HIGH_5GHZ_CHAN,
+	CAP_LOW_2GHZ_CHAN,
+	CAP_HIGH_2GHZ_CHAN,
+
+	CAP_MIC_AES_CCM,
+	CAP_MIC_CKIP,
+	CAP_MIC_TKIP,
+	CAP_MIC_TKIP_WME,
+	CAP_CIPHER_AES_CCM,
+	CAP_CIPHER_CKIP,
+	CAP_CIPHER_TKIP,
+
+	CAP_TWICE_ANTENNAGAIN_5G,
+	CAP_TWICE_ANTENNAGAIN_2G,
+};
+
+enum {
+	ST_NONE,                    /* Sentinal to indicate "no status" */
+	ST_ALL,
+	ST_SERVICE_TYPE,
+	ST_WLAN_MODE,
+	ST_FREQ,
+	ST_BAND,
+	ST_LAST_RSSI,
+	ST_PS_FRAMES_DROPPED,
+	ST_CACHED_DEF_ANT,
+	ST_COUNT_OTHER_RX_ANT,
+	ST_USE_FAST_DIVERSITY,
+	ST_MAC_ADDR,
+	ST_RX_GENERATION_NUM,
+	ST_TX_QUEUE_DEPTH,
+	ST_SERIAL_NUMBER,
+	ST_WDC_TRANSPORT_CHUNK_SIZE,
+};
+
+enum {
+	TARGET_DEVICE_AWAKE,
+	TARGET_DEVICE_SLEEP,
+	TARGET_DEVICE_PWRDN,
+	TARGET_DEVICE_PWRSAVE,
+	TARGET_DEVICE_SUSPEND,
+	TARGET_DEVICE_RESUME,
+};
+
+/* this is in net/ieee80211.h, but that conflicts with the mac80211 headers */
+#define IEEE80211_2ADDR_LEN	16
+
+#define AR5523_MIN_RXBUFSZ				\
+	(((sizeof(__be32) + IEEE80211_2ADDR_LEN +	\
+	   sizeof(struct ar5523_rx_desc)) + 3) & ~3)
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
index aec33cc..8e8bcc7a 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -236,17 +236,4 @@ static struct platform_driver ath_ahb_driver = {
 	},
 };
 
-static int __init
-ath5k_ahb_init(void)
-{
-	return platform_driver_register(&ath_ahb_driver);
-}
-
-static void __exit
-ath5k_ahb_exit(void)
-{
-	platform_driver_unregister(&ath_ahb_driver);
-}
-
-module_init(ath5k_ahb_init);
-module_exit(ath5k_ahb_exit);
+module_platform_driver(ath_ahb_driver);
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 9f31cfa..2fd5bab 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -511,8 +511,9 @@ ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah,
 		ath5k_vif_iter(&iter_data, vif->addr, vif);
 
 	/* Get list of all active MAC addresses */
-	ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
-						   &iter_data);
+	ieee80211_iterate_active_interfaces_atomic(
+		ah->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+		ath5k_vif_iter, &iter_data);
 	memcpy(ah->bssidmask, iter_data.mask, ETH_ALEN);
 
 	ah->opmode = iter_data.opmode;
@@ -1348,7 +1349,7 @@ ath5k_receive_frame(struct ath5k_hw *ah, struct sk_buff *skb,
 	 * right now, so it's not too bad...
 	 */
 	rxs->mactime = ath5k_extend_tsf(ah, rs->rs_tstamp);
-	rxs->flag |= RX_FLAG_MACTIME_MPDU;
+	rxs->flag |= RX_FLAG_MACTIME_START;
 
 	rxs->freq = ah->curchan->center_freq;
 	rxs->band = ah->curchan->band;
@@ -3045,8 +3046,9 @@ ath5k_any_vif_assoc(struct ath5k_hw *ah)
 	iter_data.need_set_hw_addr = false;
 	iter_data.found_active = true;
 
-	ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
-						   &iter_data);
+	ieee80211_iterate_active_interfaces_atomic(
+		ah->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+		ath5k_vif_iter, &iter_data);
 	return iter_data.any_assoc;
 }
 
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 7a28538..1ea8c87 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -452,8 +452,9 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
 	iter_data.hw_macaddr = NULL;
 	iter_data.n_stas = 0;
 	iter_data.need_set_hw_addr = false;
-	ieee80211_iterate_active_interfaces_atomic(ah->hw, ath5k_vif_iter,
-						   &iter_data);
+	ieee80211_iterate_active_interfaces_atomic(
+		ah->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+		ath5k_vif_iter, &iter_data);
 
 	/* Set up RX Filter */
 	if (iter_data.n_stas > 1) {
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 0c2dd47..4084b10 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -789,9 +789,9 @@ ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel)
 		 * (I don't think it supports 44MHz) */
 		/* On 2425 initvals TURBO_SHORT is not present */
 		if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
-			turbo = AR5K_PHY_TURBO_MODE |
-				(ah->ah_radio == AR5K_RF2425) ? 0 :
-				AR5K_PHY_TURBO_SHORT;
+			turbo = AR5K_PHY_TURBO_MODE;
+			if (ah->ah_radio != AR5K_RF2425)
+				turbo |= AR5K_PHY_TURBO_SHORT;
 		} else if (ah->ah_bwmode != AR5K_BWMODE_DEFAULT) {
 			if (ah->ah_radio == AR5K_RF5413) {
 				mode |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ?
diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig
index d755a5e..26c4b72 100644
--- a/drivers/net/wireless/ath/ath6kl/Kconfig
+++ b/drivers/net/wireless/ath/ath6kl/Kconfig
@@ -30,3 +30,12 @@ config ATH6KL_DEBUG
 	depends on ATH6KL
 	---help---
 	  Enables debug support
+
+config ATH6KL_REGDOMAIN
+	bool "Atheros ath6kl regdomain support"
+	depends on ATH6KL
+	depends on CFG80211_CERTIFICATION_ONUS
+	---help---
+	  Enabling this makes it possible to change the regdomain in
+	  the firmware. This can be only enabled if regulatory requirements
+	  are taken into account.
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile
index 8cae888..cab0ec0 100644
--- a/drivers/net/wireless/ath/ath6kl/Makefile
+++ b/drivers/net/wireless/ath/ath6kl/Makefile
@@ -34,6 +34,7 @@ ath6kl_core-y += main.o
 ath6kl_core-y += txrx.o
 ath6kl_core-y += wmi.o
 ath6kl_core-y += core.o
+ath6kl_core-y += recovery.o
 ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
 
 obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 7089f81..5516a8c 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -147,15 +147,15 @@ static bool __ath6kl_cfg80211_sscan_stop(struct ath6kl_vif *vif)
 {
 	struct ath6kl *ar = vif->ar;
 
-	if (ar->state != ATH6KL_STATE_SCHED_SCAN)
+	if (!test_and_clear_bit(SCHED_SCANNING, &vif->flags))
 		return false;
 
 	del_timer_sync(&vif->sched_scan_timer);
 
-	ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
-					   ATH6KL_HOST_MODE_AWAKE);
+	if (ar->state == ATH6KL_STATE_RECOVERY)
+		return true;
 
-	ar->state = ATH6KL_STATE_ON;
+	ath6kl_wmi_enable_sched_scan_cmd(ar->wmi, vif->fw_vif_idx, false);
 
 	return true;
 }
@@ -301,7 +301,7 @@ static bool ath6kl_cfg80211_ready(struct ath6kl_vif *vif)
 
 static bool ath6kl_is_wpa_ie(const u8 *pos)
 {
-	return pos[0] == WLAN_EID_WPA && pos[1] >= 4 &&
+	return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
 		pos[2] == 0x00 && pos[3] == 0x50 &&
 		pos[4] == 0xf2 && pos[5] == 0x01;
 }
@@ -369,17 +369,13 @@ static int ath6kl_nliftype_to_drv_iftype(enum nl80211_iftype type, u8 *nw_type)
 {
 	switch (type) {
 	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_P2P_CLIENT:
 		*nw_type = INFRA_NETWORK;
 		break;
 	case NL80211_IFTYPE_ADHOC:
 		*nw_type = ADHOC_NETWORK;
 		break;
 	case NL80211_IFTYPE_AP:
-		*nw_type = AP_NETWORK;
-		break;
-	case NL80211_IFTYPE_P2P_CLIENT:
-		*nw_type = INFRA_NETWORK;
-		break;
 	case NL80211_IFTYPE_P2P_GO:
 		*nw_type = AP_NETWORK;
 		break;
@@ -1031,30 +1027,15 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy,
 
 	vif->scan_req = request;
 
-	if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
-		     ar->fw_capabilities)) {
-		/*
-		 * If capable of doing P2P mgmt operations using
-		 * station interface, send additional information like
-		 * supported rates to advertise and xmit rates for
-		 * probe requests
-		 */
-		ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
-						WMI_LONG_SCAN, force_fg_scan,
-						false, 0,
-						ATH6KL_FG_SCAN_INTERVAL,
-						n_channels, channels,
-						request->no_cck,
-						request->rates);
-	} else {
-		ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx,
-						WMI_LONG_SCAN, force_fg_scan,
-						false, 0,
-						ATH6KL_FG_SCAN_INTERVAL,
-						n_channels, channels);
-	}
+	ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
+				       WMI_LONG_SCAN, force_fg_scan,
+				       false, 0,
+				       ATH6KL_FG_SCAN_INTERVAL,
+				       n_channels, channels,
+				       request->no_cck,
+				       request->rates);
 	if (ret) {
-		ath6kl_err("wmi_startscan_cmd failed\n");
+		ath6kl_err("failed to start scan: %d\n", ret);
 		vif->scan_req = NULL;
 	}
 
@@ -1093,15 +1074,18 @@ out:
 void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
 				      enum wmi_phy_mode mode)
 {
-	enum nl80211_channel_type type;
+	struct cfg80211_chan_def chandef;
 
 	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
 		   "channel switch notify nw_type %d freq %d mode %d\n",
 		   vif->nw_type, freq, mode);
 
-	type = (mode == WMI_11G_HT20) ? NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT;
+	cfg80211_chandef_create(&chandef,
+				ieee80211_get_channel(vif->ar->wiphy, freq),
+				(mode == WMI_11G_HT20) ?
+					NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT);
 
-	cfg80211_ch_switch_notify(vif->ndev, freq, type);
+	cfg80211_ch_switch_notify(vif->ndev, &chandef);
 }
 
 static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
@@ -1384,11 +1368,8 @@ static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 	return 0;
 }
 
-/*
- * The type nl80211_tx_power_setting replaces the following
- * data type from 2.6.36 onwards
-*/
 static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
+				       struct wireless_dev *wdev,
 				       enum nl80211_tx_power_setting type,
 				       int mbm)
 {
@@ -1423,7 +1404,9 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
 	return 0;
 }
 
-static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
+static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy,
+				       struct wireless_dev *wdev,
+				       int *dbm)
 {
 	struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
 	struct ath6kl_vif *vif;
@@ -1614,8 +1597,8 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
 	vif->ssid_len = ibss_param->ssid_len;
 	memcpy(vif->ssid, ibss_param->ssid, vif->ssid_len);
 
-	if (ibss_param->channel)
-		vif->ch_hint = ibss_param->channel->center_freq;
+	if (ibss_param->chandef.chan)
+		vif->ch_hint = ibss_param->chandef.chan->center_freq;
 
 	if (ibss_param->channel_fixed) {
 		/*
@@ -1889,7 +1872,7 @@ static int ath6kl_wow_usr(struct ath6kl *ar, struct ath6kl_vif *vif,
 			  struct cfg80211_wowlan *wow, u32 *filter)
 {
 	int ret, pos;
-	u8 mask[WOW_MASK_SIZE];
+	u8 mask[WOW_PATTERN_SIZE];
 	u16 i;
 
 	/* Configure the patterns that we received from the user. */
@@ -2107,33 +2090,16 @@ static int ath6kl_cfg80211_host_sleep(struct ath6kl *ar, struct ath6kl_vif *vif)
 	return ret;
 }
 
-static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
+static int ath6kl_wow_suspend_vif(struct ath6kl_vif *vif,
+				  struct cfg80211_wowlan *wow, u32 *filter)
 {
+	struct ath6kl *ar = vif->ar;
 	struct in_device *in_dev;
 	struct in_ifaddr *ifa;
-	struct ath6kl_vif *vif;
 	int ret;
-	u32 filter = 0;
 	u16 i, bmiss_time;
-	u8 index = 0;
 	__be32 ips[MAX_IP_ADDRS];
-
-	/* The FW currently can't support multi-vif WoW properly. */
-	if (ar->num_vif > 1)
-		return -EIO;
-
-	vif = ath6kl_vif_first(ar);
-	if (!vif)
-		return -EIO;
-
-	if (!ath6kl_cfg80211_ready(vif))
-		return -EIO;
-
-	if (!test_bit(CONNECTED, &vif->flags))
-		return -ENOTCONN;
-
-	if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
-		return -EINVAL;
+	u8 index = 0;
 
 	if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags) &&
 	    test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
@@ -2155,7 +2121,7 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
 	 * the user.
 	 */
 	if (wow)
-		ret = ath6kl_wow_usr(ar, vif, wow, &filter);
+		ret = ath6kl_wow_usr(ar, vif, wow, filter);
 	else if (vif->nw_type == AP_NETWORK)
 		ret = ath6kl_wow_ap(ar, vif);
 	else
@@ -2190,12 +2156,10 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
 			return ret;
 	}
 
-	ar->state = ATH6KL_STATE_SUSPENDING;
-
 	/* Setup own IP addr for ARP agent. */
 	in_dev = __in_dev_get_rtnl(vif->ndev);
 	if (!in_dev)
-		goto skip_arp;
+		return 0;
 
 	ifa = in_dev->ifa_list;
 	memset(&ips, 0, sizeof(ips));
@@ -2218,41 +2182,61 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
 		return ret;
 	}
 
-skip_arp:
-	ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
+	return ret;
+}
+
+static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
+{
+	struct ath6kl_vif *first_vif, *vif;
+	int ret = 0;
+	u32 filter = 0;
+	bool connected = false;
+
+	/* enter / leave wow suspend on first vif always */
+	first_vif = ath6kl_vif_first(ar);
+	if (WARN_ON(unlikely(!first_vif)) ||
+	    !ath6kl_cfg80211_ready(first_vif))
+		return -EIO;
+
+	if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
+		return -EINVAL;
+
+	/* install filters for each connected vif */
+	spin_lock_bh(&ar->list_lock);
+	list_for_each_entry(vif, &ar->vif_list, list) {
+		if (!test_bit(CONNECTED, &vif->flags) ||
+		    !ath6kl_cfg80211_ready(vif))
+			continue;
+		connected = true;
+
+		ret = ath6kl_wow_suspend_vif(vif, wow, &filter);
+		if (ret)
+			break;
+	}
+	spin_unlock_bh(&ar->list_lock);
+
+	if (!connected)
+		return -ENOTCONN;
+	else if (ret)
+		return ret;
+
+	ar->state = ATH6KL_STATE_SUSPENDING;
+
+	ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, first_vif->fw_vif_idx,
 					  ATH6KL_WOW_MODE_ENABLE,
 					  filter,
 					  WOW_HOST_REQ_DELAY);
 	if (ret)
 		return ret;
 
-	ret = ath6kl_cfg80211_host_sleep(ar, vif);
-	if (ret)
-		return ret;
-
-	return 0;
+	return ath6kl_cfg80211_host_sleep(ar, first_vif);
 }
 
-static int ath6kl_wow_resume(struct ath6kl *ar)
+static int ath6kl_wow_resume_vif(struct ath6kl_vif *vif)
 {
-	struct ath6kl_vif *vif;
+	struct ath6kl *ar = vif->ar;
 	int ret;
 
-	vif = ath6kl_vif_first(ar);
-	if (!vif)
-		return -EIO;
-
-	ar->state = ATH6KL_STATE_RESUMING;
-
-	ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
-						 ATH6KL_HOST_MODE_AWAKE);
-	if (ret) {
-		ath6kl_warn("Failed to configure host sleep mode for wow resume: %d\n",
-			    ret);
-		ar->state = ATH6KL_STATE_WOW;
-		return ret;
-	}
-
 	if (vif->nw_type != AP_NETWORK) {
 		ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
 						0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
@@ -2270,13 +2254,11 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
 			return ret;
 	}
 
-	ar->state = ATH6KL_STATE_ON;
-
 	if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags) &&
 	    test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
 		     ar->fw_capabilities)) {
 		ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
-					vif->fw_vif_idx, true);
+						  vif->fw_vif_idx, true);
 		if (ret)
 			return ret;
 	}
@@ -2286,6 +2268,48 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
 	return 0;
 }
 
+static int ath6kl_wow_resume(struct ath6kl *ar)
+{
+	struct ath6kl_vif *vif;
+	int ret;
+
+	vif = ath6kl_vif_first(ar);
+	if (WARN_ON(unlikely(!vif)) ||
+	    !ath6kl_cfg80211_ready(vif))
+		return -EIO;
+
+	ar->state = ATH6KL_STATE_RESUMING;
+
+	ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
+						 ATH6KL_HOST_MODE_AWAKE);
+	if (ret) {
+		ath6kl_warn("Failed to configure host sleep mode for wow resume: %d\n",
+			    ret);
+		goto cleanup;
+	}
+
+	spin_lock_bh(&ar->list_lock);
+	list_for_each_entry(vif, &ar->vif_list, list) {
+		if (!test_bit(CONNECTED, &vif->flags) ||
+		    !ath6kl_cfg80211_ready(vif))
+			continue;
+		ret = ath6kl_wow_resume_vif(vif);
+		if (ret)
+			break;
+	}
+	spin_unlock_bh(&ar->list_lock);
+
+	if (ret)
+		goto cleanup;
+
+	ar->state = ATH6KL_STATE_ON;
+	return 0;
+
+cleanup:
+	ar->state = ATH6KL_STATE_WOW;
+	return ret;
+}
+
 static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar)
 {
 	struct ath6kl_vif *vif;
@@ -2422,13 +2446,6 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
 
 		break;
 
-	case ATH6KL_CFG_SUSPEND_SCHED_SCAN:
-		/*
-		 * Nothing needed for schedule scan, firmware is already in
-		 * wow mode and sleeping most of the time.
-		 */
-		break;
-
 	default:
 		break;
 	}
@@ -2476,9 +2493,6 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar)
 		}
 		break;
 
-	case ATH6KL_STATE_SCHED_SCAN:
-		break;
-
 	default:
 		break;
 	}
@@ -2495,14 +2509,23 @@ static int __ath6kl_cfg80211_suspend(struct wiphy *wiphy,
 {
 	struct ath6kl *ar = wiphy_priv(wiphy);
 
+	ath6kl_recovery_suspend(ar);
+
 	return ath6kl_hif_suspend(ar, wow);
 }
 
 static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
 {
 	struct ath6kl *ar = wiphy_priv(wiphy);
+	int err;
 
-	return ath6kl_hif_resume(ar);
+	err = ath6kl_hif_resume(ar);
+	if (err)
+		return err;
+
+	ath6kl_recovery_resume(ar);
+
+	return 0;
 }
 
 /*
@@ -2739,6 +2762,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
 	int res;
 	int i, ret;
 	u16 rsn_capab = 0;
+	int inactivity_timeout = 0;
 
 	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s:\n", __func__);
 
@@ -2857,7 +2881,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
 	p.ssid_len = vif->ssid_len;
 	memcpy(p.ssid, vif->ssid, vif->ssid_len);
 	p.dot11_auth_mode = vif->dot11_auth_mode;
-	p.ch = cpu_to_le16(info->channel->center_freq);
+	p.ch = cpu_to_le16(info->chandef.chan->center_freq);
 
 	/* Enable uAPSD support by default */
 	res = ath6kl_wmi_ap_set_apsd(ar->wmi, vif->fw_vif_idx, true);
@@ -2875,14 +2899,22 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
 	}
 
 	if (info->inactivity_timeout) {
+
+		inactivity_timeout = info->inactivity_timeout;
+
+		if (ar->hw.flags & ATH6KL_HW_AP_INACTIVITY_MINS)
+			inactivity_timeout = DIV_ROUND_UP(inactivity_timeout,
+							  60);
+
 		res = ath6kl_wmi_set_inact_period(ar->wmi, vif->fw_vif_idx,
-						  info->inactivity_timeout);
+						  inactivity_timeout);
 		if (res < 0)
 			return res;
 	}
 
-	if (ath6kl_set_htcap(vif, info->channel->band,
-			     info->channel_type != NL80211_CHAN_NO_HT))
+	if (ath6kl_set_htcap(vif, info->chandef.chan->band,
+			     cfg80211_get_chandef_type(&info->chandef)
+					!= NL80211_CHAN_NO_HT))
 		return -EIO;
 
 	/*
@@ -2898,6 +2930,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
 					    WLAN_EID_RSN, WMI_RSN_IE_CAPB,
 					    (const u8 *) &rsn_capab,
 					    sizeof(rsn_capab));
+		vif->rsn_capab = rsn_capab;
 		if (res < 0)
 			return res;
 	}
@@ -2977,7 +3010,6 @@ static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
 static int ath6kl_remain_on_channel(struct wiphy *wiphy,
 				    struct wireless_dev *wdev,
 				    struct ieee80211_channel *chan,
-				    enum nl80211_channel_type channel_type,
 				    unsigned int duration,
 				    u64 *cookie)
 {
@@ -3136,10 +3168,8 @@ static bool ath6kl_is_p2p_go_ssid(const u8 *buf, size_t len)
 
 static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 			  struct ieee80211_channel *chan, bool offchan,
-			  enum nl80211_channel_type channel_type,
-			  bool channel_type_valid, unsigned int wait,
-			  const u8 *buf, size_t len, bool no_cck,
-			  bool dont_wait_for_ack, u64 *cookie)
+			  unsigned int wait, const u8 *buf, size_t len,
+			  bool no_cck, bool dont_wait_for_ack, u64 *cookie)
 {
 	struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
 	struct ath6kl *ar = ath6kl_priv(vif->ndev);
@@ -3211,7 +3241,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
 	struct ath6kl *ar = ath6kl_priv(dev);
 	struct ath6kl_vif *vif = netdev_priv(dev);
 	u16 interval;
-	int ret;
+	int ret, rssi_thold;
 
 	if (ar->state != ATH6KL_STATE_ON)
 		return -EIO;
@@ -3219,10 +3249,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
 	if (vif->sme_state != SME_DISCONNECTED)
 		return -EBUSY;
 
-	/* The FW currently can't support multi-vif WoW properly. */
-	if (ar->num_vif > 1)
-		return -EIO;
-
 	ath6kl_cfg80211_scan_complete_event(vif, true);
 
 	ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
@@ -3244,6 +3270,23 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
 			return ret;
 	}
 
+	if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
+		     ar->fw_capabilities)) {
+		if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
+			rssi_thold = 0;
+		else if (request->rssi_thold < -127)
+			rssi_thold = -127;
+		else
+			rssi_thold = request->rssi_thold;
+
+		ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx,
+						     rssi_thold);
+		if (ret) {
+			ath6kl_err("failed to set RSSI threshold for scan\n");
+			return ret;
+		}
+	}
+
 	/* fw uses seconds, also make sure that it's >0 */
 	interval = max_t(u16, 1, request->interval / 1000);
 
@@ -3251,15 +3294,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
 				  interval, interval,
 				  vif->bg_scan_period, 0, 0, 0, 3, 0, 0, 0);
 
-	ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
-					  ATH6KL_WOW_MODE_ENABLE,
-					  WOW_FILTER_SSID,
-					  WOW_HOST_REQ_DELAY);
-	if (ret) {
-		ath6kl_warn("Failed to enable wow with ssid filter: %d\n", ret);
-		return ret;
-	}
-
 	/* this also clears IE in fw if it's not set */
 	ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
 				       WMI_FRAME_PROBE_REQ,
@@ -3270,17 +3304,13 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
 		return ret;
 	}
 
-	ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
-						 ATH6KL_HOST_MODE_ASLEEP);
-	if (ret) {
-		ath6kl_warn("Failed to enable host sleep mode for sched scan: %d\n",
-			    ret);
+	ret = ath6kl_wmi_enable_sched_scan_cmd(ar->wmi, vif->fw_vif_idx, true);
+	if (ret)
 		return ret;
-	}
 
-	ar->state = ATH6KL_STATE_SCHED_SCAN;
+	set_bit(SCHED_SCANNING, &vif->flags);
 
-	return ret;
+	return 0;
 }
 
 static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
@@ -3309,6 +3339,27 @@ static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy,
 					   mask);
 }
 
+static int ath6kl_cfg80211_set_txe_config(struct wiphy *wiphy,
+					  struct net_device *dev,
+					  u32 rate, u32 pkts, u32 intvl)
+{
+	struct ath6kl *ar = ath6kl_priv(dev);
+	struct ath6kl_vif *vif = netdev_priv(dev);
+
+	if (vif->nw_type != INFRA_NETWORK ||
+	    !test_bit(ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY, ar->fw_capabilities))
+		return -EOPNOTSUPP;
+
+	if (vif->sme_state != SME_CONNECTED)
+		return -ENOTCONN;
+
+	/* save this since the firmware won't report the interval */
+	vif->txe_intvl = intvl;
+
+	return ath6kl_wmi_set_txe_notify(ar->wmi, vif->fw_vif_idx,
+					 rate, pkts, intvl);
+}
+
 static const struct ieee80211_txrx_stypes
 ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
 	[NL80211_IFTYPE_STATION] = {
@@ -3375,6 +3426,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
 	.sched_scan_start = ath6kl_cfg80211_sscan_start,
 	.sched_scan_stop = ath6kl_cfg80211_sscan_stop,
 	.set_bitrate_mask = ath6kl_cfg80211_set_bitrate,
+	.set_cqm_txe_config = ath6kl_cfg80211_set_txe_config,
 };
 
 void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
@@ -3395,16 +3447,22 @@ void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
 		break;
 	}
 
-	if (test_bit(CONNECTED, &vif->flags) ||
-	    test_bit(CONNECT_PEND, &vif->flags))
+	if (vif->ar->state != ATH6KL_STATE_RECOVERY &&
+	    (test_bit(CONNECTED, &vif->flags) ||
+	    test_bit(CONNECT_PEND, &vif->flags)))
 		ath6kl_wmi_disconnect_cmd(vif->ar->wmi, vif->fw_vif_idx);
 
 	vif->sme_state = SME_DISCONNECTED;
 	clear_bit(CONNECTED, &vif->flags);
 	clear_bit(CONNECT_PEND, &vif->flags);
 
+	/* Stop netdev queues, needed during recovery */
+	netif_stop_queue(vif->ndev);
+	netif_carrier_off(vif->ndev);
+
 	/* disable scanning */
-	if (ath6kl_wmi_scanparams_cmd(vif->ar->wmi, vif->fw_vif_idx, 0xFFFF,
+	if (vif->ar->state != ATH6KL_STATE_RECOVERY &&
+	    ath6kl_wmi_scanparams_cmd(vif->ar->wmi, vif->fw_vif_idx, 0xFFFF,
 				      0, 0, 0, 0, 0, 0, 0, 0, 0) != 0)
 		ath6kl_warn("failed to disable scan during stop\n");
 
@@ -3416,7 +3474,7 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
 	struct ath6kl_vif *vif;
 
 	vif = ath6kl_vif_first(ar);
-	if (!vif) {
+	if (!vif && ar->state != ATH6KL_STATE_RECOVERY) {
 		/* save the current power mode before enabling power save */
 		ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
 
@@ -3434,6 +3492,56 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
 		ath6kl_cfg80211_stop(vif);
 }
 
+static int ath6kl_cfg80211_reg_notify(struct wiphy *wiphy,
+				      struct regulatory_request *request)
+{
+	struct ath6kl *ar = wiphy_priv(wiphy);
+	u32 rates[IEEE80211_NUM_BANDS];
+	int ret, i;
+
+	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+		   "cfg reg_notify %c%c%s%s initiator %d hint_type %d\n",
+		   request->alpha2[0], request->alpha2[1],
+		   request->intersect ? " intersect" : "",
+		   request->processed ? " processed" : "",
+		   request->initiator, request->user_reg_hint_type);
+
+	/*
+	 * As firmware is not able intersect regdoms, we can only listen to
+	 * cellular hints.
+	 */
+	if (request->user_reg_hint_type != NL80211_USER_REG_HINT_CELL_BASE)
+		return -EOPNOTSUPP;
+
+	ret = ath6kl_wmi_set_regdomain_cmd(ar->wmi, request->alpha2);
+	if (ret) {
+		ath6kl_err("failed to set regdomain: %d\n", ret);
+		return ret;
+	}
+
+	/*
+	 * Firmware will apply the regdomain change only after a scan is
+	 * issued and it will send a WMI_REGDOMAIN_EVENTID when it has been
+	 * changed.
+	 */
+
+	for (i = 0; i < IEEE80211_NUM_BANDS; i++)
+		if (wiphy->bands[i])
+			rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
+
+
+	ret = ath6kl_wmi_beginscan_cmd(ar->wmi, 0, WMI_LONG_SCAN, false,
+				       false, 0, ATH6KL_FG_SCAN_INTERVAL,
+				       0, NULL, false, rates);
+	if (ret) {
+		ath6kl_err("failed to start scan for a regdomain change: %d\n",
+			   ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif)
 {
 	vif->aggr_cntxt = aggr_init(vif);
@@ -3506,9 +3614,13 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
 	vif->htcap[IEEE80211_BAND_5GHZ].ht_enable = true;
 
 	memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
-	if (fw_vif_idx != 0)
+	if (fw_vif_idx != 0) {
 		ndev->dev_addr[0] = (ndev->dev_addr[0] ^ (1 << fw_vif_idx)) |
 				     0x2;
+		if (test_bit(ATH6KL_FW_CAPABILITY_CUSTOM_MAC_ADDR,
+			     ar->fw_capabilities))
+			ndev->dev_addr[4] ^= 0x80;
+	}
 
 	init_netdev(ndev);
 
@@ -3562,6 +3674,12 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
 					  BIT(NL80211_IFTYPE_P2P_CLIENT);
 	}
 
+	if (config_enabled(CONFIG_ATH6KL_REGDOMAIN) &&
+	    test_bit(ATH6KL_FW_CAPABILITY_REGDOMAIN, ar->fw_capabilities)) {
+		wiphy->reg_notifier = ath6kl_cfg80211_reg_notify;
+		ar->wiphy->features |= NL80211_FEATURE_CELL_BASE_REG_HINTS;
+	}
+
 	/* max num of ssids that can be probed during scanning */
 	wiphy->max_scan_ssids = MAX_PROBED_SSIDS;
 
@@ -3607,7 +3725,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
 		ath6kl_band_5ghz.ht_cap.ht_supported = false;
 	}
 
-	if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) {
+	if (ar->hw.flags & ATH6KL_HW_64BIT_RATES) {
 		ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
 		ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
 		ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
@@ -3646,12 +3764,12 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
 			    WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
 			    WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
 
-	if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities))
+	if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, ar->fw_capabilities))
 		ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
 
 	if (test_bit(ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT,
 		     ar->fw_capabilities))
-		ar->wiphy->features = NL80211_FEATURE_INACTIVITY_TIMER;
+		ar->wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
 
 	ar->wiphy->probe_resp_offload =
 		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h
index 780f777..e5e70f3 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.h
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h
@@ -22,7 +22,6 @@ enum ath6kl_cfg_suspend_mode {
 	ATH6KL_CFG_SUSPEND_DEEPSLEEP,
 	ATH6KL_CFG_SUSPEND_CUTPOWER,
 	ATH6KL_CFG_SUSPEND_WOW,
-	ATH6KL_CFG_SUSPEND_SCHED_SCAN,
 };
 
 struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c
index 82c4dd2..4b46adb 100644
--- a/drivers/net/wireless/ath/ath6kl/core.c
+++ b/drivers/net/wireless/ath/ath6kl/core.c
@@ -33,6 +33,8 @@ static unsigned int wow_mode;
 static unsigned int uart_debug;
 static unsigned int ath6kl_p2p;
 static unsigned int testmode;
+static unsigned int recovery_enable;
+static unsigned int heart_beat_poll;
 
 module_param(debug_mask, uint, 0644);
 module_param(suspend_mode, uint, 0644);
@@ -40,6 +42,12 @@ module_param(wow_mode, uint, 0644);
 module_param(uart_debug, uint, 0644);
 module_param(ath6kl_p2p, uint, 0644);
 module_param(testmode, uint, 0644);
+module_param(recovery_enable, uint, 0644);
+module_param(heart_beat_poll, uint, 0644);
+MODULE_PARM_DESC(recovery_enable, "Enable recovery from firmware error");
+MODULE_PARM_DESC(heart_beat_poll, "Enable fw error detection periodic"   \
+		 "polling. This also specifies the polling interval in"  \
+		 "msecs. Set reocvery_enable for this to be effective");
 
 void ath6kl_core_tx_complete(struct ath6kl *ar, struct sk_buff *skb)
 {
@@ -202,6 +210,17 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
 	ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
 		   __func__, wdev->netdev->name, wdev->netdev, ar);
 
+	ar->fw_recovery.enable = !!recovery_enable;
+	if (!ar->fw_recovery.enable)
+		return ret;
+
+	if (heart_beat_poll &&
+	    test_bit(ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL,
+		     ar->fw_capabilities))
+		ar->fw_recovery.hb_poll = heart_beat_poll;
+
+	ath6kl_recovery_init(ar);
+
 	return ret;
 
 err_rxbuf_cleanup:
@@ -291,6 +310,8 @@ void ath6kl_core_cleanup(struct ath6kl *ar)
 {
 	ath6kl_hif_power_off(ar);
 
+	ath6kl_recovery_cleanup(ar);
+
 	destroy_workqueue(ar->ath6kl_wq);
 
 	if (ar->htc_target)
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index cec49a3..189d8fa 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -115,6 +115,27 @@ enum ath6kl_fw_capability {
 	 */
 	ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,
 
+	/* Firmware supports filtering BSS results by RSSI */
+	ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
+
+	/* FW sets mac_addr[4] ^= 0x80 for newly created interfaces */
+	ATH6KL_FW_CAPABILITY_CUSTOM_MAC_ADDR,
+
+	/* Firmware supports TX error rate notification */
+	ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY,
+
+	/* supports WMI_SET_REGDOMAIN_CMDID command */
+	ATH6KL_FW_CAPABILITY_REGDOMAIN,
+
+	/* Firmware supports sched scan decoupled from host sleep */
+	ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2,
+
+	/*
+	 * Firmware capability for hang detection through heart beat
+	 * challenge messages.
+	 */
+	ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL,
+
 	/* this needs to be last */
 	ATH6KL_FW_CAPABILITY_MAX,
 };
@@ -128,11 +149,15 @@ struct ath6kl_fw_ie {
 };
 
 enum ath6kl_hw_flags {
-	ATH6KL_HW_FLAG_64BIT_RATES	= BIT(0),
+	ATH6KL_HW_64BIT_RATES		= BIT(0),
+	ATH6KL_HW_AP_INACTIVITY_MINS	= BIT(1),
+	ATH6KL_HW_MAP_LP_ENDPOINT	= BIT(2),
+	ATH6KL_HW_SDIO_CRC_ERROR_WAR	= BIT(3),
 };
 
 #define ATH6KL_FW_API2_FILE "fw-2.bin"
 #define ATH6KL_FW_API3_FILE "fw-3.bin"
+#define ATH6KL_FW_API4_FILE "fw-4.bin"
 
 /* AR6003 1.0 definitions */
 #define AR6003_HW_1_0_VERSION                 0x300002ba
@@ -186,6 +211,13 @@ enum ath6kl_hw_flags {
 #define AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE \
 	AR6004_HW_1_2_FW_DIR "/bdata.bin"
 
+/* AR6004 1.3 definitions */
+#define AR6004_HW_1_3_VERSION			0x31c8088a
+#define AR6004_HW_1_3_FW_DIR			"ath6k/AR6004/hw1.3"
+#define AR6004_HW_1_3_FIRMWARE_FILE		"fw.ram.bin"
+#define AR6004_HW_1_3_BOARD_DATA_FILE		"ath6k/AR6004/hw1.3/bdata.bin"
+#define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE	"ath6k/AR6004/hw1.3/bdata.bin"
+
 /* Per STA data, used in AP mode */
 #define STA_PS_AWAKE		BIT(0)
 #define	STA_PS_SLEEP		BIT(1)
@@ -536,6 +568,7 @@ enum ath6kl_vif_state {
 	HOST_SLEEP_MODE_CMD_PROCESSED,
 	NETDEV_MCAST_ALL_ON,
 	NETDEV_MCAST_ALL_OFF,
+	SCHED_SCANNING,
 };
 
 struct ath6kl_vif {
@@ -580,11 +613,13 @@ struct ath6kl_vif {
 	u16 assoc_bss_beacon_int;
 	u16 listen_intvl_t;
 	u16 bmiss_time_t;
+	u32 txe_intvl;
 	u16 bg_scan_period;
 	u8 assoc_bss_dtim_period;
 	struct net_device_stats net_stats;
 	struct target_stats target_stats;
 	struct wmi_connect_cmd profile;
+	u16 rsn_capab;
 
 	struct list_head mc_filter;
 };
@@ -609,6 +644,7 @@ enum ath6kl_dev_state {
 	SKIP_SCAN,
 	ROAM_TBL_PEND,
 	FIRST_BOOT,
+	RECOVERY_CLEANUP,
 };
 
 enum ath6kl_state {
@@ -619,7 +655,16 @@ enum ath6kl_state {
 	ATH6KL_STATE_DEEPSLEEP,
 	ATH6KL_STATE_CUTPOWER,
 	ATH6KL_STATE_WOW,
-	ATH6KL_STATE_SCHED_SCAN,
+	ATH6KL_STATE_RECOVERY,
+};
+
+/* Fw error recovery */
+#define ATH6KL_HB_RESP_MISS_THRES	5
+
+enum ath6kl_fw_err {
+	ATH6KL_FW_ASSERT,
+	ATH6KL_FW_HB_RESP_FAILURE,
+	ATH6KL_FW_EP_FULL,
 };
 
 struct ath6kl {
@@ -679,6 +724,7 @@ struct ath6kl {
 	struct ath6kl_req_key ap_mode_bkey;
 	struct sk_buff_head mcastpsq;
 	u32 want_ch_switch;
+	u16 last_ch;
 
 	/*
 	 * FIXME: protects access to mcastpsq but is actually useless as
@@ -764,6 +810,17 @@ struct ath6kl {
 
 	bool wiphy_registered;
 
+	struct ath6kl_fw_recovery {
+		struct work_struct recovery_work;
+		unsigned long err_reason;
+		unsigned long hb_poll;
+		struct timer_list hb_timer;
+		u32 seq_num;
+		bool hb_pending;
+		u8 hb_misscnt;
+		bool enable;
+	} fw_recovery;
+
 #ifdef CONFIG_ATH6KL_DEBUG
 	struct {
 		struct sk_buff_head fwlog_queue;
@@ -899,4 +956,12 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type);
 void ath6kl_core_cleanup(struct ath6kl *ar);
 void ath6kl_core_destroy(struct ath6kl *ar);
 
+/* Fw error recovery */
+void ath6kl_init_hw_restart(struct ath6kl *ar);
+void ath6kl_recovery_err_notify(struct ath6kl *ar, enum ath6kl_fw_err reason);
+void ath6kl_recovery_hb_event(struct ath6kl *ar, u32 cookie);
+void ath6kl_recovery_init(struct ath6kl *ar);
+void ath6kl_recovery_cleanup(struct ath6kl *ar);
+void ath6kl_recovery_suspend(struct ath6kl *ar);
+void ath6kl_recovery_resume(struct ath6kl *ar);
 #endif /* CORE_H */
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
index 49639d8..f97cd4e 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.h
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -44,6 +44,7 @@ enum ATH6K_DEBUG_MASK {
 	ATH6KL_DBG_SUSPEND	= BIT(20),
 	ATH6KL_DBG_USB		= BIT(21),
 	ATH6KL_DBG_USB_BULK	= BIT(22),
+	ATH6KL_DBG_RECOVERY	= BIT(23),
 	ATH6KL_DBG_ANY	        = 0xffffffff  /* enable all logs */
 };
 
diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c
index 68ed6c2..a6b6144 100644
--- a/drivers/net/wireless/ath/ath6kl/hif.c
+++ b/drivers/net/wireless/ath/ath6kl/hif.c
@@ -136,6 +136,7 @@ static int ath6kl_hif_proc_dbg_intr(struct ath6kl_device *dev)
 
 	ath6kl_hif_dump_fw_crash(dev->ar);
 	ath6kl_read_fwlogs(dev->ar);
+	ath6kl_recovery_err_notify(dev->ar, ATH6KL_FW_ASSERT);
 
 	return ret;
 }
@@ -338,8 +339,7 @@ static int ath6kl_hif_proc_err_intr(struct ath6kl_device *dev)
 	status = hif_read_write_sync(dev->ar, ERROR_INT_STATUS_ADDRESS,
 				     reg_buf, 4, HIF_WR_SYNC_BYTE_FIX);
 
-	if (status)
-		WARN_ON(1);
+	WARN_ON(status);
 
 	return status;
 }
@@ -383,8 +383,7 @@ static int ath6kl_hif_proc_cpu_intr(struct ath6kl_device *dev)
 	status = hif_read_write_sync(dev->ar, CPU_INT_STATUS_ADDRESS,
 				     reg_buf, 4, HIF_WR_SYNC_BYTE_FIX);
 
-	if (status)
-		WARN_ON(1);
+	WARN_ON(status);
 
 	return status;
 }
@@ -695,11 +694,6 @@ int ath6kl_hif_setup(struct ath6kl_device *dev)
 	ath6kl_dbg(ATH6KL_DBG_HIF, "hif block size %d mbox addr 0x%x\n",
 		   dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr);
 
-	/* usb doesn't support enabling interrupts */
-	/* FIXME: remove check once USB support is implemented */
-	if (dev->ar->hif_type == ATH6KL_HIF_TYPE_USB)
-		return 0;
-
 	status = ath6kl_hif_disable_intrs(dev);
 
 fail_setup:
diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c
index cd0e1ba..fbb78df 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c
@@ -2492,7 +2492,8 @@ static int ath6kl_htc_mbox_conn_service(struct htc_target *target,
 		max_msg_sz = le16_to_cpu(resp_msg->max_msg_sz);
 	}
 
-	if (assigned_ep >= ENDPOINT_MAX || !max_msg_sz) {
+	if (WARN_ON_ONCE(assigned_ep == ENDPOINT_UNUSED ||
+			 assigned_ep >= ENDPOINT_MAX || !max_msg_sz)) {
 		status = -ENOMEM;
 		goto fail_tx;
 	}
@@ -2655,12 +2656,6 @@ static int ath6kl_htc_mbox_wait_target(struct htc_target *target)
 	struct htc_service_connect_resp resp;
 	int status;
 
-	/* FIXME: remove once USB support is implemented */
-	if (target->dev->ar->hif_type == ATH6KL_HIF_TYPE_USB) {
-		ath6kl_err("HTC doesn't support USB yet. Patience!\n");
-		return -EOPNOTSUPP;
-	}
-
 	/* we should be getting 1 control message that the target is ready */
 	packet = htc_wait_for_ctrl_msg(target);
 
@@ -2890,9 +2885,7 @@ static void ath6kl_htc_mbox_cleanup(struct htc_target *target)
 {
 	struct htc_packet *packet, *tmp_packet;
 
-	/* FIXME: remove check once USB support is implemented */
-	if (target->dev->ar->hif_type != ATH6KL_HIF_TYPE_USB)
-		ath6kl_hif_cleanup_scatter(target->dev->ar);
+	ath6kl_hif_cleanup_scatter(target->dev->ar);
 
 	list_for_each_entry_safe(packet, tmp_packet,
 				 &target->free_ctrl_txbuf, list) {
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
index f9626c7..ba6bd49 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
@@ -374,9 +374,8 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target,
 				packet = list_first_entry(txq,
 							  struct htc_packet,
 							  list);
-				list_del(&packet->list);
-				/* insert into local queue */
-				list_add_tail(&packet->list, &send_queue);
+				/* move to local queue */
+				list_move_tail(&packet->list, &send_queue);
 			}
 
 			/*
@@ -399,11 +398,10 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target,
 					 * for cleanup */
 				} else {
 					/* callback wants to keep this packet,
-					 * remove from caller's queue */
-					list_del(&packet->list);
-					/* put it in the send queue */
-					list_add_tail(&packet->list,
-						      &send_queue);
+					 * move from caller's queue to the send
+					 * queue */
+					list_move_tail(&packet->list,
+						       &send_queue);
 				}
 
 			}
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index f90b5db..f21fa32 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -42,7 +42,7 @@ static const struct ath6kl_hw hw_list[] = {
 		.reserved_ram_size		= 6912,
 		.refclk_hz			= 26000000,
 		.uarttx_pin			= 8,
-		.flags				= 0,
+		.flags				= ATH6KL_HW_SDIO_CRC_ERROR_WAR,
 
 		/* hw2.0 needs override address hardcoded */
 		.app_start_override_addr	= 0x944C00,
@@ -68,7 +68,7 @@ static const struct ath6kl_hw hw_list[] = {
 		.refclk_hz			= 26000000,
 		.uarttx_pin			= 8,
 		.testscript_addr		= 0x57ef74,
-		.flags				= 0,
+		.flags				= ATH6KL_HW_SDIO_CRC_ERROR_WAR,
 
 		.fw = {
 			.dir		= AR6003_HW_2_1_1_FW_DIR,
@@ -93,7 +93,8 @@ static const struct ath6kl_hw hw_list[] = {
 		.board_addr			= 0x433900,
 		.refclk_hz			= 26000000,
 		.uarttx_pin			= 11,
-		.flags				= ATH6KL_HW_FLAG_64BIT_RATES,
+		.flags				= ATH6KL_HW_64BIT_RATES |
+						  ATH6KL_HW_AP_INACTIVITY_MINS,
 
 		.fw = {
 			.dir		= AR6004_HW_1_0_FW_DIR,
@@ -113,8 +114,8 @@ static const struct ath6kl_hw hw_list[] = {
 		.board_addr			= 0x43d400,
 		.refclk_hz			= 40000000,
 		.uarttx_pin			= 11,
-		.flags				= ATH6KL_HW_FLAG_64BIT_RATES,
-
+		.flags				= ATH6KL_HW_64BIT_RATES |
+						  ATH6KL_HW_AP_INACTIVITY_MINS,
 		.fw = {
 			.dir		= AR6004_HW_1_1_FW_DIR,
 			.fw		= AR6004_HW_1_1_FIRMWARE_FILE,
@@ -133,7 +134,8 @@ static const struct ath6kl_hw hw_list[] = {
 		.board_addr			= 0x435c00,
 		.refclk_hz			= 40000000,
 		.uarttx_pin			= 11,
-		.flags				= ATH6KL_HW_FLAG_64BIT_RATES,
+		.flags				= ATH6KL_HW_64BIT_RATES |
+						  ATH6KL_HW_AP_INACTIVITY_MINS,
 
 		.fw = {
 			.dir		= AR6004_HW_1_2_FW_DIR,
@@ -142,6 +144,28 @@ static const struct ath6kl_hw hw_list[] = {
 		.fw_board		= AR6004_HW_1_2_BOARD_DATA_FILE,
 		.fw_default_board	= AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE,
 	},
+	{
+		.id				= AR6004_HW_1_3_VERSION,
+		.name				= "ar6004 hw 1.3",
+		.dataset_patch_addr		= 0x437860,
+		.app_load_addr			= 0x1234,
+		.board_ext_data_addr		= 0x437000,
+		.reserved_ram_size		= 7168,
+		.board_addr			= 0x436400,
+		.refclk_hz                      = 40000000,
+		.uarttx_pin                     = 11,
+		.flags				= ATH6KL_HW_64BIT_RATES |
+						  ATH6KL_HW_AP_INACTIVITY_MINS |
+						  ATH6KL_HW_MAP_LP_ENDPOINT,
+
+		.fw = {
+			.dir            = AR6004_HW_1_3_FW_DIR,
+			.fw             = AR6004_HW_1_3_FIRMWARE_FILE,
+		},
+
+		.fw_board               = AR6004_HW_1_3_BOARD_DATA_FILE,
+		.fw_default_board       = AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE,
+	},
 };
 
 /*
@@ -337,7 +361,7 @@ static int ath6kl_init_service_ep(struct ath6kl *ar)
 	if (ath6kl_connectservice(ar, &connect, "WMI DATA BK"))
 		return -EIO;
 
-	/* connect to Video service, map this to to HI PRI */
+	/* connect to Video service, map this to HI PRI */
 	connect.svc_id = WMI_DATA_VI_SVC;
 	if (ath6kl_connectservice(ar, &connect, "WMI DATA VI"))
 		return -EIO;
@@ -1088,6 +1112,12 @@ int ath6kl_init_fetch_firmwares(struct ath6kl *ar)
 	if (ret)
 		return ret;
 
+	ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API4_FILE);
+	if (ret == 0) {
+		ar->fw_api = 4;
+		goto out;
+	}
+
 	ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API3_FILE);
 	if (ret == 0) {
 		ar->fw_api = 3;
@@ -1401,8 +1431,7 @@ static int ath6kl_init_upload(struct ath6kl *ar)
 		return status;
 
 	/* WAR to avoid SDIO CRC err */
-	if (ar->version.target_ver == AR6003_HW_2_0_VERSION ||
-	    ar->version.target_ver == AR6003_HW_2_1_1_VERSION) {
+	if (ar->hw.flags & ATH6KL_HW_SDIO_CRC_ERROR_WAR) {
 		ath6kl_err("temporary war to avoid sdio crc error\n");
 
 		param = 0x28;
@@ -1520,7 +1549,7 @@ static const char *ath6kl_init_get_hif_name(enum ath6kl_hif_type type)
 	return NULL;
 }
 
-int ath6kl_init_hw_start(struct ath6kl *ar)
+static int __ath6kl_init_hw_start(struct ath6kl *ar)
 {
 	long timeleft;
 	int ret, i;
@@ -1616,8 +1645,6 @@ int ath6kl_init_hw_start(struct ath6kl *ar)
 			goto err_htc_stop;
 	}
 
-	ar->state = ATH6KL_STATE_ON;
-
 	return 0;
 
 err_htc_stop:
@@ -1630,7 +1657,18 @@ err_power_off:
 	return ret;
 }
 
-int ath6kl_init_hw_stop(struct ath6kl *ar)
+int ath6kl_init_hw_start(struct ath6kl *ar)
+{
+	int err;
+
+	err = __ath6kl_init_hw_start(ar);
+	if (err)
+		return err;
+	ar->state = ATH6KL_STATE_ON;
+	return 0;
+}
+
+static int __ath6kl_init_hw_stop(struct ath6kl *ar)
 {
 	int ret;
 
@@ -1646,11 +1684,37 @@ int ath6kl_init_hw_stop(struct ath6kl *ar)
 	if (ret)
 		ath6kl_warn("failed to power off hif: %d\n", ret);
 
-	ar->state = ATH6KL_STATE_OFF;
+	return 0;
+}
 
+int ath6kl_init_hw_stop(struct ath6kl *ar)
+{
+	int err;
+
+	err = __ath6kl_init_hw_stop(ar);
+	if (err)
+		return err;
+	ar->state = ATH6KL_STATE_OFF;
 	return 0;
 }
 
+void ath6kl_init_hw_restart(struct ath6kl *ar)
+{
+	clear_bit(WMI_READY, &ar->flag);
+
+	ath6kl_cfg80211_stop_all(ar);
+
+	if (__ath6kl_init_hw_stop(ar)) {
+		ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Failed to stop during fw error recovery\n");
+		return;
+	}
+
+	if (__ath6kl_init_hw_start(ar)) {
+		ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Failed to restart during fw error recovery\n");
+		return;
+	}
+}
+
 /* FIXME: move this to cfg80211.c and rename to ath6kl_cfg80211_vif_stop() */
 void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
 {
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index c189e28..bd50b6b 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -293,13 +293,17 @@ int ath6kl_read_fwlogs(struct ath6kl *ar)
 	}
 
 	address = TARG_VTOP(ar->target_type, debug_hdr_addr);
-	ath6kl_diag_read(ar, address, &debug_hdr, sizeof(debug_hdr));
+	ret = ath6kl_diag_read(ar, address, &debug_hdr, sizeof(debug_hdr));
+	if (ret)
+		goto out;
 
 	address = TARG_VTOP(ar->target_type,
 			    le32_to_cpu(debug_hdr.dbuf_addr));
 	firstbuf = address;
 	dropped = le32_to_cpu(debug_hdr.dropped);
-	ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf));
+	ret = ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf));
+	if (ret)
+		goto out;
 
 	loop = 100;
 
@@ -322,7 +326,8 @@ int ath6kl_read_fwlogs(struct ath6kl *ar)
 
 		address = TARG_VTOP(ar->target_type,
 				    le32_to_cpu(debug_buf.next));
-		ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf));
+		ret = ath6kl_diag_read(ar, address, &debug_buf,
+				       sizeof(debug_buf));
 		if (ret)
 			goto out;
 
@@ -436,12 +441,9 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)
 		break;
 	}
 
-	if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) {
-		ar->want_ch_switch &= ~(1 << vif->fw_vif_idx);
+	if (ar->last_ch != channel)
 		/* we actually don't know the phymode, default to HT20 */
-		ath6kl_cfg80211_ch_switch_notify(vif, channel,
-						 WMI_11G_HT20);
-	}
+		ath6kl_cfg80211_ch_switch_notify(vif, channel, WMI_11G_HT20);
 
 	ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0);
 	set_bit(CONNECTED, &vif->flags);
@@ -606,6 +608,18 @@ static int ath6kl_commit_ch_switch(struct ath6kl_vif *vif, u16 channel)
 
 	switch (vif->nw_type) {
 	case AP_NETWORK:
+		/*
+		 * reconfigure any saved RSN IE capabilites in the beacon /
+		 * probe response to stay in sync with the supplicant.
+		 */
+		if (vif->rsn_capab &&
+		    test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,
+			     ar->fw_capabilities))
+			ath6kl_wmi_set_ie_cmd(ar->wmi, vif->fw_vif_idx,
+					      WLAN_EID_RSN, WMI_RSN_IE_CAPB,
+					      (const u8 *) &vif->rsn_capab,
+					      sizeof(vif->rsn_capab));
+
 		return ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx,
 						    &vif->profile);
 	default:
@@ -628,6 +642,9 @@ static void ath6kl_check_ch_switch(struct ath6kl *ar, u16 channel)
 		if (ar->want_ch_switch & (1 << vif->fw_vif_idx))
 			res = ath6kl_commit_ch_switch(vif, channel);
 
+		/* if channel switch failed, oh well we tried */
+		ar->want_ch_switch &= ~(1 << vif->fw_vif_idx);
+
 		if (res)
 			ath6kl_err("channel switch failed nw_type %d res %d\n",
 				   vif->nw_type, res);
@@ -981,8 +998,25 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
 	if (vif->nw_type == AP_NETWORK) {
 		/* disconnect due to other STA vif switching channels */
 		if (reason == BSS_DISCONNECTED &&
-		    prot_reason_status == WMI_AP_REASON_STA_ROAM)
+		    prot_reason_status == WMI_AP_REASON_STA_ROAM) {
 			ar->want_ch_switch |= 1 << vif->fw_vif_idx;
+			/* bail back to this channel if STA vif fails connect */
+			ar->last_ch = le16_to_cpu(vif->profile.ch);
+		}
+
+		if (prot_reason_status == WMI_AP_REASON_MAX_STA) {
+			/* send max client reached notification to user space */
+			cfg80211_conn_failed(vif->ndev, bssid,
+					     NL80211_CONN_FAIL_MAX_CLIENTS,
+					     GFP_KERNEL);
+		}
+
+		if (prot_reason_status == WMI_AP_REASON_ACL) {
+			/* send blocked client notification to user space */
+			cfg80211_conn_failed(vif->ndev, bssid,
+					     NL80211_CONN_FAIL_BLOCKED_CLIENT,
+					     GFP_KERNEL);
+		}
 
 		if (!ath6kl_remove_sta(ar, bssid, prot_reason_status))
 			return;
@@ -1041,6 +1075,9 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
 		}
 	}
 
+	/* restart disconnected concurrent vifs waiting for new channel */
+	ath6kl_check_ch_switch(ar, ar->last_ch);
+
 	/* update connect & link status atomically */
 	spin_lock_bh(&vif->if_lock);
 	clear_bit(CONNECTED, &vif->flags);
diff --git a/drivers/net/wireless/ath/ath6kl/recovery.c b/drivers/net/wireless/ath/ath6kl/recovery.c
new file mode 100644
index 0000000..3a8d5e9
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/recovery.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "core.h"
+#include "cfg80211.h"
+#include "debug.h"
+
+static void ath6kl_recovery_work(struct work_struct *work)
+{
+	struct ath6kl *ar = container_of(work, struct ath6kl,
+					 fw_recovery.recovery_work);
+
+	ar->state = ATH6KL_STATE_RECOVERY;
+
+	del_timer_sync(&ar->fw_recovery.hb_timer);
+
+	ath6kl_init_hw_restart(ar);
+
+	ar->state = ATH6KL_STATE_ON;
+	clear_bit(WMI_CTRL_EP_FULL, &ar->flag);
+
+	ar->fw_recovery.err_reason = 0;
+
+	if (ar->fw_recovery.hb_poll)
+		mod_timer(&ar->fw_recovery.hb_timer, jiffies +
+			  msecs_to_jiffies(ar->fw_recovery.hb_poll));
+}
+
+void ath6kl_recovery_err_notify(struct ath6kl *ar, enum ath6kl_fw_err reason)
+{
+	if (!ar->fw_recovery.enable)
+		return;
+
+	ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Fw error detected, reason:%d\n",
+		   reason);
+
+	set_bit(reason, &ar->fw_recovery.err_reason);
+
+	if (!test_bit(RECOVERY_CLEANUP, &ar->flag) &&
+	    ar->state != ATH6KL_STATE_RECOVERY)
+		queue_work(ar->ath6kl_wq, &ar->fw_recovery.recovery_work);
+}
+
+void ath6kl_recovery_hb_event(struct ath6kl *ar, u32 cookie)
+{
+	if (cookie == ar->fw_recovery.seq_num)
+		ar->fw_recovery.hb_pending = false;
+}
+
+static void ath6kl_recovery_hb_timer(unsigned long data)
+{
+	struct ath6kl *ar = (struct ath6kl *) data;
+	int err;
+
+	if (test_bit(RECOVERY_CLEANUP, &ar->flag) ||
+	    (ar->state == ATH6KL_STATE_RECOVERY))
+		return;
+
+	if (ar->fw_recovery.hb_pending)
+		ar->fw_recovery.hb_misscnt++;
+	else
+		ar->fw_recovery.hb_misscnt = 0;
+
+	if (ar->fw_recovery.hb_misscnt > ATH6KL_HB_RESP_MISS_THRES) {
+		ar->fw_recovery.hb_misscnt = 0;
+		ar->fw_recovery.seq_num = 0;
+		ar->fw_recovery.hb_pending = false;
+		ath6kl_recovery_err_notify(ar, ATH6KL_FW_HB_RESP_FAILURE);
+		return;
+	}
+
+	ar->fw_recovery.seq_num++;
+	ar->fw_recovery.hb_pending = true;
+
+	err = ath6kl_wmi_get_challenge_resp_cmd(ar->wmi,
+						ar->fw_recovery.seq_num, 0);
+	if (err)
+		ath6kl_warn("Failed to send hb challenge request, err:%d\n",
+			    err);
+
+	mod_timer(&ar->fw_recovery.hb_timer, jiffies +
+		  msecs_to_jiffies(ar->fw_recovery.hb_poll));
+}
+
+void ath6kl_recovery_init(struct ath6kl *ar)
+{
+	struct ath6kl_fw_recovery *recovery = &ar->fw_recovery;
+
+	clear_bit(RECOVERY_CLEANUP, &ar->flag);
+	INIT_WORK(&recovery->recovery_work, ath6kl_recovery_work);
+	recovery->seq_num = 0;
+	recovery->hb_misscnt = 0;
+	ar->fw_recovery.hb_pending = false;
+	ar->fw_recovery.hb_timer.function = ath6kl_recovery_hb_timer;
+	ar->fw_recovery.hb_timer.data = (unsigned long) ar;
+	init_timer_deferrable(&ar->fw_recovery.hb_timer);
+
+	if (ar->fw_recovery.hb_poll)
+		mod_timer(&ar->fw_recovery.hb_timer, jiffies +
+			  msecs_to_jiffies(ar->fw_recovery.hb_poll));
+}
+
+void ath6kl_recovery_cleanup(struct ath6kl *ar)
+{
+	if (!ar->fw_recovery.enable)
+		return;
+
+	set_bit(RECOVERY_CLEANUP, &ar->flag);
+
+	del_timer_sync(&ar->fw_recovery.hb_timer);
+	cancel_work_sync(&ar->fw_recovery.recovery_work);
+}
+
+void ath6kl_recovery_suspend(struct ath6kl *ar)
+{
+	if (!ar->fw_recovery.enable)
+		return;
+
+	ath6kl_recovery_cleanup(ar);
+
+	if (!ar->fw_recovery.err_reason)
+		return;
+
+	/* Process pending fw error detection */
+	ar->fw_recovery.err_reason = 0;
+	WARN_ON(ar->state != ATH6KL_STATE_ON);
+	ar->state = ATH6KL_STATE_RECOVERY;
+	ath6kl_init_hw_restart(ar);
+	ar->state = ATH6KL_STATE_ON;
+}
+
+void ath6kl_recovery_resume(struct ath6kl *ar)
+{
+	if (!ar->fw_recovery.enable)
+		return;
+
+	clear_bit(RECOVERY_CLEANUP, &ar->flag);
+
+	if (!ar->fw_recovery.hb_poll)
+		return;
+
+	ar->fw_recovery.hb_pending = false;
+	ar->fw_recovery.seq_num = 0;
+	ar->fw_recovery.hb_misscnt = 0;
+	mod_timer(&ar->fw_recovery.hb_timer,
+		  jiffies + msecs_to_jiffies(ar->fw_recovery.hb_poll));
+}
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index 05b9540..d111980 100644
--- a/drivers/net/wireless/ath/ath6kl/sdio.c
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -709,7 +709,7 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
 {
 	struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
 	struct htc_target *target = ar->htc_target;
-	int ret;
+	int ret = 0;
 	bool virt_scat = false;
 
 	if (ar_sdio->scatter_enabled)
@@ -844,22 +844,6 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
 	bool try_deepsleep = false;
 	int ret;
 
-	if (ar->state == ATH6KL_STATE_SCHED_SCAN) {
-		ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sched scan is in progress\n");
-
-		ret = ath6kl_set_sdio_pm_caps(ar);
-		if (ret)
-			goto cut_pwr;
-
-		ret =  ath6kl_cfg80211_suspend(ar,
-					       ATH6KL_CFG_SUSPEND_SCHED_SCAN,
-					       NULL);
-		if (ret)
-			goto cut_pwr;
-
-		return 0;
-	}
-
 	if (ar->suspend_mode == WLAN_POWER_STATE_WOW ||
 	    (!ar->suspend_mode && wow)) {
 
@@ -942,14 +926,14 @@ static int ath6kl_sdio_resume(struct ath6kl *ar)
 	case ATH6KL_STATE_WOW:
 		break;
 
-	case ATH6KL_STATE_SCHED_SCAN:
-		break;
-
 	case ATH6KL_STATE_SUSPENDING:
 		break;
 
 	case ATH6KL_STATE_RESUMING:
 		break;
+
+	case ATH6KL_STATE_RECOVERY:
+		break;
 	}
 
 	ath6kl_cfg80211_resume(ar);
@@ -1462,3 +1446,6 @@ MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE);
 MODULE_FIRMWARE(AR6004_HW_1_2_FW_DIR "/" AR6004_HW_1_2_FIRMWARE_FILE);
 MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE);
 MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_3_FW_DIR "/" AR6004_HW_1_3_FIRMWARE_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_3_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE);
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c
index 7dfa0fd..78b3692 100644
--- a/drivers/net/wireless/ath/ath6kl/txrx.c
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -288,8 +288,16 @@ int ath6kl_control_tx(void *devt, struct sk_buff *skb,
 	int status = 0;
 	struct ath6kl_cookie *cookie = NULL;
 
-	if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW))
+	if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW)) {
+		dev_kfree_skb(skb);
 		return -EACCES;
+	}
+
+	if (WARN_ON_ONCE(eid == ENDPOINT_UNUSED ||
+			 eid >= ENDPOINT_MAX)) {
+		status = -EINVAL;
+		goto fail_ctrl_tx;
+	}
 
 	spin_lock_bh(&ar->lock);
 
@@ -591,6 +599,7 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
 		 */
 		set_bit(WMI_CTRL_EP_FULL, &ar->flag);
 		ath6kl_err("wmi ctrl ep is full\n");
+		ath6kl_recovery_err_notify(ar, ATH6KL_FW_EP_FULL);
 		return action;
 	}
 
@@ -695,22 +704,31 @@ void ath6kl_tx_complete(struct htc_target *target,
 					  list);
 		list_del(&packet->list);
 
+		if (WARN_ON_ONCE(packet->endpoint == ENDPOINT_UNUSED ||
+				 packet->endpoint >= ENDPOINT_MAX))
+			continue;
+
 		ath6kl_cookie = (struct ath6kl_cookie *)packet->pkt_cntxt;
-		if (!ath6kl_cookie)
-			goto fatal;
+		if (WARN_ON_ONCE(!ath6kl_cookie))
+			continue;
 
 		status = packet->status;
 		skb = ath6kl_cookie->skb;
 		eid = packet->endpoint;
 		map_no = ath6kl_cookie->map_no;
 
-		if (!skb || !skb->data)
-			goto fatal;
+		if (WARN_ON_ONCE(!skb || !skb->data)) {
+			dev_kfree_skb(skb);
+			ath6kl_free_cookie(ar, ath6kl_cookie);
+			continue;
+		}
 
 		__skb_queue_tail(&skb_queue, skb);
 
-		if (!status && (packet->act_len != skb->len))
-			goto fatal;
+		if (WARN_ON_ONCE(!status && (packet->act_len != skb->len))) {
+			ath6kl_free_cookie(ar, ath6kl_cookie);
+			continue;
+		}
 
 		ar->tx_pending[eid]--;
 
@@ -792,11 +810,6 @@ void ath6kl_tx_complete(struct htc_target *target,
 		wake_up(&ar->event_wq);
 
 	return;
-
-fatal:
-	WARN_ON(1);
-	spin_unlock_bh(&ar->lock);
-	return;
 }
 
 void ath6kl_tx_data_cleanup(struct ath6kl *ar)
@@ -885,8 +898,11 @@ void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint)
 			break;
 
 		packet = (struct htc_packet *) skb->head;
-		if (!IS_ALIGNED((unsigned long) skb->data, 4))
+		if (!IS_ALIGNED((unsigned long) skb->data, 4)) {
+			size_t len = skb_headlen(skb);
 			skb->data = PTR_ALIGN(skb->data - 4, 4);
+			skb_set_tail_pointer(skb, len);
+		}
 		set_htc_rxpkt_info(packet, skb, skb->data,
 				   ATH6KL_BUFFER_SIZE, endpoint);
 		packet->skb = skb;
@@ -908,8 +924,11 @@ void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count)
 			return;
 
 		packet = (struct htc_packet *) skb->head;
-		if (!IS_ALIGNED((unsigned long) skb->data, 4))
+		if (!IS_ALIGNED((unsigned long) skb->data, 4)) {
+			size_t len = skb_headlen(skb);
 			skb->data = PTR_ALIGN(skb->data - 4, 4);
+			skb_set_tail_pointer(skb, len);
+		}
 		set_htc_rxpkt_info(packet, skb, skb->data,
 				   ATH6KL_AMSDU_BUFFER_SIZE, 0);
 		packet->skb = skb;
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c
index 3740c3d..62bcc0d 100644
--- a/drivers/net/wireless/ath/ath6kl/usb.c
+++ b/drivers/net/wireless/ath/ath6kl/usb.c
@@ -185,9 +185,10 @@ static int ath6kl_usb_alloc_pipe_resources(struct ath6kl_usb_pipe *pipe,
 	for (i = 0; i < urb_cnt; i++) {
 		urb_context = kzalloc(sizeof(struct ath6kl_urb_context),
 				      GFP_KERNEL);
-		if (urb_context == NULL)
-			/* FIXME: set status to -ENOMEM */
-			break;
+		if (urb_context == NULL) {
+			status = -ENOMEM;
+			goto fail_alloc_pipe_resources;
+		}
 
 		urb_context->pipe = pipe;
 
@@ -204,6 +205,7 @@ static int ath6kl_usb_alloc_pipe_resources(struct ath6kl_usb_pipe *pipe,
 		   pipe->logical_pipe_num, pipe->usb_pipe_handle,
 		   pipe->urb_alloc);
 
+fail_alloc_pipe_resources:
 	return status;
 }
 
@@ -803,7 +805,11 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
 		*dl_pipe = ATH6KL_USB_PIPE_RX_DATA;
 		break;
 	case WMI_DATA_VI_SVC:
-		*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
+
+		if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT)
+			*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
+		else
+			*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
 		/*
 		* Disable rxdata2 directly, it will be enabled
 		* if FW enable rxdata2
@@ -811,7 +817,11 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
 		*dl_pipe = ATH6KL_USB_PIPE_RX_DATA;
 		break;
 	case WMI_DATA_VO_SVC:
-		*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_HP;
+
+		if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT)
+			*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
+		else
+			*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
 		/*
 		* Disable rxdata2 directly, it will be enabled
 		* if FW enable rxdata2
@@ -1196,7 +1206,14 @@ static struct usb_driver ath6kl_usb_driver = {
 
 static int ath6kl_usb_init(void)
 {
-	usb_register(&ath6kl_usb_driver);
+	int ret;
+
+	ret = usb_register(&ath6kl_usb_driver);
+	if (ret) {
+		ath6kl_err("usb registration failed: %d\n", ret);
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -1220,3 +1237,6 @@ MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE);
 MODULE_FIRMWARE(AR6004_HW_1_2_FIRMWARE_FILE);
 MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE);
 MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_3_FW_DIR "/" AR6004_HW_1_3_FIRMWARE_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_3_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE);
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index c30ab4b..998f8b0 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -474,7 +474,7 @@ static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap,
 		return -EINVAL;
 	}
 	id = vif->last_roc_id;
-	cfg80211_ready_on_channel(&vif->wdev, id, chan, NL80211_CHAN_NO_HT,
+	cfg80211_ready_on_channel(&vif->wdev, id, chan,
 				  dur, GFP_ATOMIC);
 
 	return 0;
@@ -513,8 +513,7 @@ static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi,
 	else
 		id = vif->last_roc_id; /* timeout on uncanceled r-o-c */
 	vif->last_cancel_roc_id = 0;
-	cfg80211_remain_on_channel_expired(&vif->wdev, id, chan,
-					   NL80211_CHAN_NO_HT, GFP_ATOMIC);
+	cfg80211_remain_on_channel_expired(&vif->wdev, id, chan, GFP_ATOMIC);
 
 	return 0;
 }
@@ -936,8 +935,12 @@ static void ath6kl_wmi_regdomain_event(struct wmi *wmi, u8 *datap, int len)
 
 		regpair = ath6kl_get_regpair((u16) reg_code);
 		country = ath6kl_regd_find_country_by_rd((u16) reg_code);
-		ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n",
-			   regpair->regDmnEnum);
+		if (regpair)
+			ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n",
+				   regpair->regDmnEnum);
+		else
+			ath6kl_warn("Regpair not found reg_code 0x%0x\n",
+				    reg_code);
 	}
 
 	if (country && wmi->parent_dev->wiphy_registered) {
@@ -1116,7 +1119,7 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
 	 * the timer would not ever fire if the scan interval is short
 	 * enough.
 	 */
-	if (ar->state == ATH6KL_STATE_SCHED_SCAN &&
+	if (test_bit(SCHED_SCANNING, &vif->flags) &&
 	    !timer_pending(&vif->sched_scan_timer)) {
 		mod_timer(&vif->sched_scan_timer, jiffies +
 			  msecs_to_jiffies(ATH6KL_SCHED_SCAN_RESULT_DELAY));
@@ -1170,6 +1173,9 @@ static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len)
 		rate = RATE_AUTO;
 	} else {
 		index = reply->rate_index & 0x7f;
+		if (WARN_ON_ONCE(index > (RATE_MCS_7_40 + 1)))
+			return -EINVAL;
+
 		sgi = (reply->rate_index & 0x80) ? 1 : 0;
 		rate = wmi_rate_tbl[index][sgi];
 	}
@@ -1531,6 +1537,68 @@ static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len,
 	return 0;
 }
 
+static int ath6kl_wmi_txe_notify_event_rx(struct wmi *wmi, u8 *datap, int len,
+					  struct ath6kl_vif *vif)
+{
+	struct wmi_txe_notify_event *ev;
+	u32 rate, pkts;
+
+	if (len < sizeof(*ev))
+		return -EINVAL;
+
+	if (vif->sme_state != SME_CONNECTED)
+		return -ENOTCONN;
+
+	ev = (struct wmi_txe_notify_event *) datap;
+	rate = le32_to_cpu(ev->rate);
+	pkts = le32_to_cpu(ev->pkts);
+
+	ath6kl_dbg(ATH6KL_DBG_WMI, "TXE notify event: peer %pM rate %d% pkts %d intvl %ds\n",
+		   vif->bssid, rate, pkts, vif->txe_intvl);
+
+	cfg80211_cqm_txe_notify(vif->ndev, vif->bssid, pkts,
+				rate, vif->txe_intvl, GFP_KERNEL);
+
+	return 0;
+}
+
+int ath6kl_wmi_set_txe_notify(struct wmi *wmi, u8 idx,
+			      u32 rate, u32 pkts, u32 intvl)
+{
+	struct sk_buff *skb;
+	struct wmi_txe_notify_cmd *cmd;
+
+	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_txe_notify_cmd *) skb->data;
+	cmd->rate = cpu_to_le32(rate);
+	cmd->pkts = cpu_to_le32(pkts);
+	cmd->intvl = cpu_to_le32(intvl);
+
+	return ath6kl_wmi_cmd_send(wmi, idx, skb, WMI_SET_TXE_NOTIFY_CMDID,
+				   NO_SYNC_WMIFLAG);
+}
+
+int ath6kl_wmi_set_rssi_filter_cmd(struct wmi *wmi, u8 if_idx, s8 rssi)
+{
+	struct sk_buff *skb;
+	struct wmi_set_rssi_filter_cmd *cmd;
+	int ret;
+
+	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_set_rssi_filter_cmd *) skb->data;
+	cmd->rssi = rssi;
+
+	ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_RSSI_FILTER_CMDID,
+				  NO_SYNC_WMIFLAG);
+	return ret;
+}
+
 static int ath6kl_wmi_send_snr_threshold_params(struct wmi *wmi,
 			struct wmi_snr_threshold_params_cmd *snr_cmd)
 {
@@ -1677,8 +1745,11 @@ int ath6kl_wmi_cmd_send(struct wmi *wmi, u8 if_idx, struct sk_buff *skb,
 	int ret;
 	u16 info1;
 
-	if (WARN_ON(skb == NULL || (if_idx > (wmi->parent_dev->vif_max - 1))))
+	if (WARN_ON(skb == NULL ||
+		    (if_idx > (wmi->parent_dev->vif_max - 1)))) {
+		dev_kfree_skb(skb);
 		return -EINVAL;
+	}
 
 	ath6kl_dbg(ATH6KL_DBG_WMI, "wmi tx id %d len %d flag %d\n",
 		   cmd_id, skb->len, sync_flag);
@@ -1833,6 +1904,59 @@ int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx)
 	return ret;
 }
 
+/* ath6kl_wmi_start_scan_cmd is to be deprecated. Use
+ * ath6kl_wmi_begin_scan_cmd instead. The new function supports P2P
+ * mgmt operations using station interface.
+ */
+static int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
+				    enum wmi_scan_type scan_type,
+				    u32 force_fgscan, u32 is_legacy,
+				    u32 home_dwell_time,
+				    u32 force_scan_interval,
+				    s8 num_chan, u16 *ch_list)
+{
+	struct sk_buff *skb;
+	struct wmi_start_scan_cmd *sc;
+	s8 size;
+	int i, ret;
+
+	size = sizeof(struct wmi_start_scan_cmd);
+
+	if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
+		return -EINVAL;
+
+	if (num_chan > WMI_MAX_CHANNELS)
+		return -EINVAL;
+
+	if (num_chan)
+		size += sizeof(u16) * (num_chan - 1);
+
+	skb = ath6kl_wmi_get_new_buf(size);
+	if (!skb)
+		return -ENOMEM;
+
+	sc = (struct wmi_start_scan_cmd *) skb->data;
+	sc->scan_type = scan_type;
+	sc->force_fg_scan = cpu_to_le32(force_fgscan);
+	sc->is_legacy = cpu_to_le32(is_legacy);
+	sc->home_dwell_time = cpu_to_le32(home_dwell_time);
+	sc->force_scan_intvl = cpu_to_le32(force_scan_interval);
+	sc->num_ch = num_chan;
+
+	for (i = 0; i < num_chan; i++)
+		sc->ch_list[i] = cpu_to_le16(ch_list[i]);
+
+	ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_START_SCAN_CMDID,
+				  NO_SYNC_WMIFLAG);
+
+	return ret;
+}
+
+/*
+ * beginscan supports (compared to old startscan) P2P mgmt operations using
+ * station interface, send additional information like supported rates to
+ * advertise and xmit rates for probe requests
+ */
 int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
 			     enum wmi_scan_type scan_type,
 			     u32 force_fgscan, u32 is_legacy,
@@ -1848,6 +1972,15 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
 	int num_rates;
 	u32 ratemask;
 
+	if (!test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
+		      ar->fw_capabilities)) {
+		return ath6kl_wmi_startscan_cmd(wmi, if_idx,
+						scan_type, force_fgscan,
+						is_legacy, home_dwell_time,
+						force_scan_interval,
+						num_chan, ch_list);
+	}
+
 	size = sizeof(struct wmi_begin_scan_cmd);
 
 	if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
@@ -1900,50 +2033,24 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
 	return ret;
 }
 
-/* ath6kl_wmi_start_scan_cmd is to be deprecated. Use
- * ath6kl_wmi_begin_scan_cmd instead. The new function supports P2P
- * mgmt operations using station interface.
- */
-int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
-			     enum wmi_scan_type scan_type,
-			     u32 force_fgscan, u32 is_legacy,
-			     u32 home_dwell_time, u32 force_scan_interval,
-			     s8 num_chan, u16 *ch_list)
+int ath6kl_wmi_enable_sched_scan_cmd(struct wmi *wmi, u8 if_idx, bool enable)
 {
 	struct sk_buff *skb;
-	struct wmi_start_scan_cmd *sc;
-	s8 size;
-	int i, ret;
-
-	size = sizeof(struct wmi_start_scan_cmd);
-
-	if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
-		return -EINVAL;
-
-	if (num_chan > WMI_MAX_CHANNELS)
-		return -EINVAL;
-
-	if (num_chan)
-		size += sizeof(u16) * (num_chan - 1);
+	struct wmi_enable_sched_scan_cmd *sc;
+	int ret;
 
-	skb = ath6kl_wmi_get_new_buf(size);
+	skb = ath6kl_wmi_get_new_buf(sizeof(*sc));
 	if (!skb)
 		return -ENOMEM;
 
-	sc = (struct wmi_start_scan_cmd *) skb->data;
-	sc->scan_type = scan_type;
-	sc->force_fg_scan = cpu_to_le32(force_fgscan);
-	sc->is_legacy = cpu_to_le32(is_legacy);
-	sc->home_dwell_time = cpu_to_le32(home_dwell_time);
-	sc->force_scan_intvl = cpu_to_le32(force_scan_interval);
-	sc->num_ch = num_chan;
-
-	for (i = 0; i < num_chan; i++)
-		sc->ch_list[i] = cpu_to_le16(ch_list[i]);
+	ath6kl_dbg(ATH6KL_DBG_WMI, "%s scheduled scan on vif %d\n",
+		   enable ? "enabling" : "disabling", if_idx);
+	sc = (struct wmi_enable_sched_scan_cmd *) skb->data;
+	sc->enable = enable ? 1 : 0;
 
-	ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_START_SCAN_CMDID,
+	ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
+				  WMI_ENABLE_SCHED_SCAN_CMDID,
 				  NO_SYNC_WMIFLAG);
-
 	return ret;
 }
 
@@ -2275,8 +2382,10 @@ static int ath6kl_wmi_data_sync_send(struct wmi *wmi, struct sk_buff *skb,
 	struct wmi_data_hdr *data_hdr;
 	int ret;
 
-	if (WARN_ON(skb == NULL || ep_id == wmi->ep_id))
+	if (WARN_ON(skb == NULL || ep_id == wmi->ep_id)) {
+		dev_kfree_skb(skb);
 		return -EINVAL;
+	}
 
 	skb_push(skb, sizeof(struct wmi_data_hdr));
 
@@ -2313,10 +2422,8 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
 	spin_unlock_bh(&wmi->lock);
 
 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
-	if (!skb) {
-		ret = -ENOMEM;
-		goto free_skb;
-	}
+	if (!skb)
+		return -ENOMEM;
 
 	cmd = (struct wmi_sync_cmd *) skb->data;
 
@@ -2339,7 +2446,7 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
 	 * then do not send the Synchronize cmd on the control ep
 	 */
 	if (ret)
-		goto free_skb;
+		goto free_cmd_skb;
 
 	/*
 	 * Send sync cmd followed by sync data messages on all
@@ -2349,15 +2456,12 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
 				  NO_SYNC_WMIFLAG);
 
 	if (ret)
-		goto free_skb;
-
-	/* cmd buffer sent, we no longer own it */
-	skb = NULL;
+		goto free_data_skb;
 
 	for (index = 0; index < num_pri_streams; index++) {
 
 		if (WARN_ON(!data_sync_bufs[index].skb))
-			break;
+			goto free_data_skb;
 
 		ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev,
 					       data_sync_bufs[index].
@@ -2366,17 +2470,20 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
 		    ath6kl_wmi_data_sync_send(wmi, data_sync_bufs[index].skb,
 					      ep_id, if_idx);
 
-		if (ret)
-			break;
-
 		data_sync_bufs[index].skb = NULL;
+
+		if (ret)
+			goto free_data_skb;
 	}
 
-free_skb:
+	return 0;
+
+free_cmd_skb:
 	/* free up any resources left over (possibly due to an error) */
 	if (skb)
 		dev_kfree_skb(skb);
 
+free_data_skb:
 	for (index = 0; index < num_pri_streams; index++) {
 		if (data_sync_bufs[index].skb != NULL) {
 			dev_kfree_skb((struct sk_buff *)data_sync_bufs[index].
@@ -2618,11 +2725,13 @@ static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
 {
 	struct sk_buff *skb;
 	int ret, mode, band;
-	u64 mcsrate, ratemask[IEEE80211_NUM_BANDS];
+	u64 mcsrate, ratemask[ATH6KL_NUM_BANDS];
 	struct wmi_set_tx_select_rates64_cmd *cmd;
 
 	memset(&ratemask, 0, sizeof(ratemask));
-	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+
+	/* only check 2.4 and 5 GHz bands, skip the rest */
+	for (band = 0; band <= IEEE80211_BAND_5GHZ; band++) {
 		/* copy legacy rate mask */
 		ratemask[band] = mask->control[band].legacy;
 		if (band == IEEE80211_BAND_5GHZ)
@@ -2668,11 +2777,13 @@ static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
 {
 	struct sk_buff *skb;
 	int ret, mode, band;
-	u32 mcsrate, ratemask[IEEE80211_NUM_BANDS];
+	u32 mcsrate, ratemask[ATH6KL_NUM_BANDS];
 	struct wmi_set_tx_select_rates32_cmd *cmd;
 
 	memset(&ratemask, 0, sizeof(ratemask));
-	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+
+	/* only check 2.4 and 5 GHz bands, skip the rest */
+	for (band = 0; band <= IEEE80211_BAND_5GHZ; band++) {
 		/* copy legacy rate mask */
 		ratemask[band] = mask->control[band].legacy;
 		if (band == IEEE80211_BAND_5GHZ)
@@ -2716,7 +2827,7 @@ int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
 {
 	struct ath6kl *ar = wmi->parent_dev;
 
-	if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES)
+	if (ar->hw.flags & ATH6KL_HW_64BIT_RATES)
 		return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
 	else
 		return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
@@ -3139,12 +3250,40 @@ int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enhance)
 	return ret;
 }
 
+int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2)
+{
+	struct sk_buff *skb;
+	struct wmi_set_regdomain_cmd *cmd;
+
+	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_set_regdomain_cmd *) skb->data;
+	memcpy(cmd->iso_name, alpha2, 2);
+
+	return ath6kl_wmi_cmd_send(wmi, 0, skb,
+				   WMI_SET_REGDOMAIN_CMDID,
+				   NO_SYNC_WMIFLAG);
+}
+
 s32 ath6kl_wmi_get_rate(s8 rate_index)
 {
+	u8 sgi = 0;
+
 	if (rate_index == RATE_AUTO)
 		return 0;
 
-	return wmi_rate_tbl[(u32) rate_index][0];
+	/* SGI is stored as the MSB of the rate_index */
+	if (rate_index & RATE_INDEX_MSB) {
+		rate_index &= RATE_INDEX_WITHOUT_SGI_MASK;
+		sgi = 1;
+	}
+
+	if (WARN_ON(rate_index > RATE_MCS_7_40))
+		rate_index = RATE_MCS_7_40;
+
+	return wmi_rate_tbl[(u32) rate_index][sgi];
 }
 
 static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,
@@ -3634,6 +3773,19 @@ int ath6kl_wmi_set_inact_period(struct wmi *wmi, u8 if_idx, int inact_timeout)
 				   NO_SYNC_WMIFLAG);
 }
 
+static void ath6kl_wmi_hb_challenge_resp_event(struct wmi *wmi, u8 *datap,
+					       int len)
+{
+	struct wmix_hb_challenge_resp_cmd *cmd;
+
+	if (len < sizeof(struct wmix_hb_challenge_resp_cmd))
+		return;
+
+	cmd = (struct wmix_hb_challenge_resp_cmd *) datap;
+	ath6kl_recovery_hb_event(wmi->parent_dev,
+				 le32_to_cpu(cmd->cookie));
+}
+
 static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
 {
 	struct wmix_cmd_hdr *cmd;
@@ -3658,6 +3810,7 @@ static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
 	switch (id) {
 	case WMIX_HB_CHALLENGE_RESP_EVENTID:
 		ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event hb challenge resp\n");
+		ath6kl_wmi_hb_challenge_resp_event(wmi, datap, len);
 		break;
 	case WMIX_DBGLOG_EVENTID:
 		ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event dbglog len %d\n", len);
@@ -3750,6 +3903,9 @@ static int ath6kl_wmi_proc_events_vif(struct wmi *wmi, u16 if_idx, u16 cmd_id,
 	case WMI_RX_ACTION_EVENTID:
 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_ACTION_EVENTID\n");
 		return ath6kl_wmi_rx_action_event_rx(wmi, datap, len, vif);
+	case WMI_TXE_NOTIFY_EVENTID:
+		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TXE_NOTIFY_EVENTID\n");
+		return ath6kl_wmi_txe_notify_event_rx(wmi, datap, len, vif);
 	default:
 		ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", cmd_id);
 		return -EINVAL;
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index 43339ac..98b1755 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -48,7 +48,7 @@
 
 #define A_BAND_24GHZ           0
 #define A_BAND_5GHZ            1
-#define A_NUM_BANDS            2
+#define ATH6KL_NUM_BANDS       2
 
 /* in ms */
 #define WMI_IMPLICIT_PSTREAM_INACTIVITY_INT 5000
@@ -628,6 +628,20 @@ enum wmi_cmd_id {
 	WMI_SET_MCASTRATE,
 
 	WMI_STA_BMISS_ENHANCE_CMDID,
+
+	WMI_SET_REGDOMAIN_CMDID,
+
+	WMI_SET_RSSI_FILTER_CMDID,
+
+	WMI_SET_KEEP_ALIVE_EXT,
+
+	WMI_VOICE_DETECTION_ENABLE_CMDID,
+
+	WMI_SET_TXE_NOTIFY_CMDID,
+
+	WMI_SET_RECOVERY_TEST_PARAMETER_CMDID, /*0xf094*/
+
+	WMI_ENABLE_SCHED_SCAN_CMDID,
 };
 
 enum wmi_mgmt_frame_type {
@@ -843,7 +857,7 @@ struct wmi_begin_scan_cmd {
 	u8 scan_type;
 
 	/* Supported rates to advertise in the probe request frames */
-	struct wmi_supp_rates supp_rates[IEEE80211_NUM_BANDS];
+	struct wmi_supp_rates supp_rates[ATH6KL_NUM_BANDS];
 
 	/* how many channels follow */
 	u8 num_ch;
@@ -941,6 +955,11 @@ struct wmi_scan_params_cmd {
 	__le32 max_dfsch_act_time;
 } __packed;
 
+/* WMI_ENABLE_SCHED_SCAN_CMDID */
+struct wmi_enable_sched_scan_cmd {
+	u8 enable;
+} __packed;
+
 /* WMI_SET_BSS_FILTER_CMDID */
 enum wmi_bss_filter {
 	/* no beacons forwarded */
@@ -1032,6 +1051,11 @@ struct wmi_sta_bmiss_enhance_cmd {
 	u8 enable;
 } __packed;
 
+struct wmi_set_regdomain_cmd {
+	u8 length;
+	u8 iso_name[2];
+} __packed;
+
 /* WMI_SET_POWER_MODE_CMDID */
 enum wmi_power_mode {
 	REC_POWER = 0x01,
@@ -1276,6 +1300,11 @@ struct wmi_snr_threshold_params_cmd {
 	u8 reserved[3];
 } __packed;
 
+/* Don't report BSSs with signal (RSSI) below this threshold */
+struct wmi_set_rssi_filter_cmd {
+	s8 rssi;
+} __packed;
+
 enum wmi_preamble_policy {
 	WMI_IGNORE_BARKER_IN_ERP = 0,
 	WMI_FOLLOW_BARKER_IN_ERP,
@@ -1455,6 +1484,20 @@ enum wmi_event_id {
 	WMI_P2P_CAPABILITIES_EVENTID,
 	WMI_RX_ACTION_EVENTID,
 	WMI_P2P_INFO_EVENTID,
+
+	/* WPS Events */
+	WMI_WPS_GET_STATUS_EVENTID,
+	WMI_WPS_PROFILE_EVENTID,
+
+	/* more P2P events */
+	WMI_NOA_INFO_EVENTID,
+	WMI_OPPPS_INFO_EVENTID,
+	WMI_PORT_STATUS_EVENTID,
+
+	/* 802.11w */
+	WMI_GET_RSN_CAP_EVENTID,
+
+	WMI_TXE_NOTIFY_EVENTID,
 };
 
 struct wmi_ready_event_2 {
@@ -1749,6 +1792,9 @@ struct rx_stats {
 	a_sle32 ucast_rate;
 } __packed;
 
+#define RATE_INDEX_WITHOUT_SGI_MASK     0x7f
+#define RATE_INDEX_MSB     0x80
+
 struct tkip_ccmp_stats {
 	__le32 tkip_local_mic_fail;
 	__le32 tkip_cnter_measures_invoked;
@@ -2019,7 +2065,6 @@ struct wmi_set_ie_cmd {
 
 #define WOW_MAX_FILTERS_PER_LIST 4
 #define WOW_PATTERN_SIZE	 64
-#define WOW_MASK_SIZE		 64
 
 #define MAC_MAX_FILTERS_PER_LIST 4
 
@@ -2028,7 +2073,7 @@ struct wow_filter {
 	u8 wow_filter_id;
 	u8 wow_filter_size;
 	u8 wow_filter_offset;
-	u8 wow_filter_mask[WOW_MASK_SIZE];
+	u8 wow_filter_mask[WOW_PATTERN_SIZE];
 	u8 wow_filter_pattern[WOW_PATTERN_SIZE];
 } __packed;
 
@@ -2087,6 +2132,19 @@ struct wmi_del_wow_pattern_cmd {
 	__le16 filter_id;
 } __packed;
 
+/* WMI_SET_TXE_NOTIFY_CMDID */
+struct wmi_txe_notify_cmd {
+	__le32 rate;
+	__le32 pkts;
+	__le32 intvl;
+} __packed;
+
+/* WMI_TXE_NOTIFY_EVENTID */
+struct wmi_txe_notify_event {
+	__le32 rate;
+	__le32 pkts;
+} __packed;
+
 /* WMI_SET_AKMP_PARAMS_CMD */
 
 struct wmi_pmkid {
@@ -2505,11 +2563,6 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx,
 int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 if_idx, u8 *bssid,
 			     u16 channel);
 int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx);
-int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
-			     enum wmi_scan_type scan_type,
-			     u32 force_fgscan, u32 is_legacy,
-			     u32 home_dwell_time, u32 force_scan_interval,
-			     s8 num_chan, u16 *ch_list);
 
 int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
 			     enum wmi_scan_type scan_type,
@@ -2517,6 +2570,7 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
 			     u32 home_dwell_time, u32 force_scan_interval,
 			     s8 num_chan, u16 *ch_list, u32 no_cck,
 			     u32 *rates);
+int ath6kl_wmi_enable_sched_scan_cmd(struct wmi *wmi, u8 if_idx, bool enable);
 
 int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u8 if_idx, u16 fg_start_sec,
 			      u16 fg_end_sec, u16 bg_sec,
@@ -2592,6 +2646,7 @@ int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
 				   const u8 *mask);
 int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
 				   u16 list_id, u16 filter_id);
+int ath6kl_wmi_set_rssi_filter_cmd(struct wmi *wmi, u8 if_idx, s8 rssi);
 int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
 int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period);
 int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid);
@@ -2600,6 +2655,9 @@ int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on);
 int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
 					u8 *filter, bool add_filter);
 int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enable);
+int ath6kl_wmi_set_txe_notify(struct wmi *wmi, u8 idx,
+			      u32 rate, u32 pkts, u32 intvl);
+int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2);
 
 /* AP mode uAPSD */
 int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable);
@@ -2658,6 +2716,8 @@ int ath6kl_wmi_set_inact_period(struct wmi *wmi, u8 if_idx, int inact_timeout);
 
 void ath6kl_wmi_sscan_timer(unsigned long ptr);
 
+int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source);
+
 struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx);
 void *ath6kl_wmi_init(struct ath6kl *devt);
 void ath6kl_wmi_shutdown(struct wmi *wmi);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 84b558d..8b0d8dc 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -276,6 +276,11 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
 				offset_array[i],
 				REG_READ(ah, offset_array[i]));
 
+			if (AR_SREV_9565(ah) &&
+			    (iCoff == 63 || qCoff == 63 ||
+			     iCoff == -63 || qCoff == -63))
+				return;
+
 			REG_RMW_FIELD(ah, offset_array[i],
 				      AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
 				      iCoff);
@@ -886,6 +891,74 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah)
 		      AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
 }
 
+static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
+{
+	int offset[8], total = 0, test;
+	int agc_out, i;
+
+	REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
+		      AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0x1);
+	REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
+		      AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC, 0x0);
+	if (is_2g)
+		REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
+			      AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR, 0x0);
+	else
+		REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
+			      AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR, 0x0);
+
+	REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
+		      AR_PHY_65NM_RXTX2_RXON_OVR, 0x1);
+	REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
+		      AR_PHY_65NM_RXTX2_RXON, 0x0);
+
+	REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+		      AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1);
+	REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+		      AR_PHY_65NM_RXRF_AGC_AGC_ON_OVR, 0x1);
+	REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+		      AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0x1);
+	if (is_2g)
+		REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+			      AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, 0x0);
+	else
+		REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+			      AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR, 0x0);
+
+	for (i = 6; i > 0; i--) {
+		offset[i] = BIT(i - 1);
+		test = total + offset[i];
+
+		if (is_2g)
+			REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+				      AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR,
+				      test);
+		else
+			REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+				      AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR,
+				      test);
+		udelay(100);
+		agc_out = REG_READ_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+					 AR_PHY_65NM_RXRF_AGC_AGC_OUT);
+		offset[i] = (agc_out) ? 0 : 1;
+		total += (offset[i] << (i - 1));
+	}
+
+	if (is_2g)
+		REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+			      AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, total);
+	else
+		REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+			      AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR, total);
+
+	REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
+		      AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0);
+	REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
+		      AR_PHY_65NM_RXTX2_RXON_OVR, 0);
+	REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+		      AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0);
+}
+
 static bool ar9003_hw_init_cal(struct ath_hw *ah,
 			       struct ath9k_channel *chan)
 {
@@ -984,6 +1057,14 @@ skip_tx_iqcal:
 		status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
 				       AR_PHY_AGC_CONTROL_CAL,
 				       0, AH_WAIT_TIMEOUT);
+		if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
+			for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+				if (!(ah->rxchainmask & (1 << i)))
+					continue;
+				ar9003_hw_manual_peak_cal(ah, i,
+							  IS_CHAN_2GHZ(chan));
+			}
+		}
 	}
 
 	if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 5bbe505..c86cb640 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -18,6 +18,7 @@
 #include "hw.h"
 #include "ar9003_phy.h"
 #include "ar9003_eeprom.h"
+#include "ar9003_mci.h"
 
 #define COMP_HDR_LEN 4
 #define COMP_CKSUM_LEN 2
@@ -41,7 +42,6 @@
 static int ar9003_hw_power_interpolate(int32_t x,
 				       int32_t *px, int32_t *py, u_int16_t np);
 
-
 static const struct ar9300_eeprom ar9300_default = {
 	.eepromVersion = 2,
 	.templateVersion = 2,
@@ -2989,7 +2989,7 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
 	case EEP_PAPRD:
 		if (AR_SREV_9462(ah))
 			return false;
-		if (!ah->config.enable_paprd);
+		if (!ah->config.enable_paprd)
 			return false;
 		return !!(pBase->featureEnable & BIT(5));
 	case EEP_CHAIN_MASK_REDUCE:
@@ -3601,7 +3601,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
 	 *   7:4 R/W  SWITCH_TABLE_COM_SPDT_WLAN_IDLE
 	 * SWITCH_TABLE_COM_SPDT_WLAN_IDLE
 	 */
-	if (AR_SREV_9462_20_OR_LATER(ah)) {
+	if (AR_SREV_9462_20(ah) || AR_SREV_9565(ah)) {
 		value = ar9003_switch_com_spdt_get(ah, is2ghz);
 		REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL,
 				AR_SWITCH_TABLE_COM_SPDT_ALL, value);
@@ -5037,16 +5037,28 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
 		case CTL_5GHT20:
 		case CTL_2GHT20:
 			for (i = ALL_TARGET_HT20_0_8_16;
-			     i <= ALL_TARGET_HT20_23; i++)
+			     i <= ALL_TARGET_HT20_23; i++) {
 				pPwrArray[i] = (u8)min((u16)pPwrArray[i],
 						       minCtlPower);
+				if (ath9k_hw_mci_is_enabled(ah))
+					pPwrArray[i] =
+						(u8)min((u16)pPwrArray[i],
+						ar9003_mci_get_max_txpower(ah,
+							pCtlMode[ctlMode]));
+			}
 			break;
 		case CTL_5GHT40:
 		case CTL_2GHT40:
 			for (i = ALL_TARGET_HT40_0_8_16;
-			     i <= ALL_TARGET_HT40_23; i++)
+			     i <= ALL_TARGET_HT40_23; i++) {
 				pPwrArray[i] = (u8)min((u16)pPwrArray[i],
 						       minCtlPower);
+				if (ath9k_hw_mci_is_enabled(ah))
+					pPwrArray[i] =
+						(u8)min((u16)pPwrArray[i],
+						ar9003_mci_get_max_txpower(ah,
+							pCtlMode[ctlMode]));
+			}
 			break;
 		default:
 			break;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 1a36fa2..74fd397 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -35,12 +35,6 @@
  */
 static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
 {
-#define AR9462_BB_CTX_COEFJ(x)	\
-		ar9462_##x##_baseband_core_txfir_coeff_japan_2484
-
-#define AR9462_BBC_TXIFR_COEFFJ \
-		ar9462_2p0_baseband_core_txfir_coeff_japan_2484
-
 	if (AR_SREV_9330_11(ah)) {
 		/* mac */
 		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
@@ -70,6 +64,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
 		INIT_INI_ARRAY(&ah->iniModesTxGain,
 				ar9331_modes_lowest_ob_db_tx_gain_1p1);
 
+		/* Japan 2484 Mhz CCK */
+		INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+			       ar9331_1p1_baseband_core_txfir_coeff_japan_2484);
+
 		/* additional clock settings */
 		if (ah->is_clk_25mhz)
 			INIT_INI_ARRAY(&ah->iniAdditional,
@@ -106,6 +104,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
 		INIT_INI_ARRAY(&ah->iniModesTxGain,
 				ar9331_modes_lowest_ob_db_tx_gain_1p2);
 
+		/* Japan 2484 Mhz CCK */
+		INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+			       ar9331_1p2_baseband_core_txfir_coeff_japan_2484);
+
 		/* additional clock settings */
 		if (ah->is_clk_25mhz)
 			INIT_INI_ARRAY(&ah->iniAdditional,
@@ -180,6 +182,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
 		INIT_INI_ARRAY(&ah->iniModesTxGain,
 				ar9485_modes_lowest_ob_db_tx_gain_1_1);
 
+		/* Japan 2484 Mhz CCK */
+		INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+			       ar9485_1_1_baseband_core_txfir_coeff_japan_2484);
+
 		/* Load PCIE SERDES settings from INI */
 
 		/* Awake Setting */
@@ -219,19 +225,17 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
 
 		/* Awake -> Sleep Setting */
 		INIT_INI_ARRAY(&ah->iniPcieSerdes,
-			       ar9462_pciephy_pll_on_clkreq_disable_L1_2p0);
+			       ar9462_pciephy_clkreq_disable_L1_2p0);
 		/* Sleep -> Awake Setting */
 		INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
-			       ar9462_pciephy_pll_on_clkreq_disable_L1_2p0);
+			       ar9462_pciephy_clkreq_disable_L1_2p0);
 
 		/* Fast clock modal settings */
 		INIT_INI_ARRAY(&ah->iniModesFastClock,
 				ar9462_modes_fast_clock_2p0);
 
 		INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
-				AR9462_BB_CTX_COEFJ(2p0));
-
-		INIT_INI_ARRAY(&ah->ini_japan2484, AR9462_BBC_TXIFR_COEFFJ);
+			       ar9462_2p0_baseband_core_txfir_coeff_japan_2484);
 	} else if (AR_SREV_9550(ah)) {
 		/* mac */
 		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
@@ -328,9 +332,9 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
 			       ar9565_1p0_Modes_lowest_ob_db_tx_gain_table);
 
 		INIT_INI_ARRAY(&ah->iniPcieSerdes,
-			       ar9565_1p0_pciephy_pll_on_clkreq_disable_L1);
+			       ar9565_1p0_pciephy_clkreq_disable_L1);
 		INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
-			       ar9565_1p0_pciephy_pll_on_clkreq_disable_L1);
+			       ar9565_1p0_pciephy_clkreq_disable_L1);
 
 		INIT_INI_ARRAY(&ah->iniModesFastClock,
 				ar9565_1p0_modes_fast_clock);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
index 44c202c..8dd0692 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
@@ -714,7 +714,6 @@ bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan)
 
 	return true;
 }
-EXPORT_SYMBOL(ar9003_mci_start_reset);
 
 int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 			 struct ath9k_hw_cal_data *caldata)
@@ -750,6 +749,9 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
 	mci_hw->bt_state = MCI_BT_AWAKE;
 
+	REG_CLR_BIT(ah, AR_PHY_TIMING4,
+		    1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT);
+
 	if (caldata) {
 		caldata->done_txiqcal_once = false;
 		caldata->done_txclcal_once = false;
@@ -759,6 +761,9 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 	if (!ath9k_hw_init_cal(ah, chan))
 		return -EIO;
 
+	REG_SET_BIT(ah, AR_PHY_TIMING4,
+		    1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT);
+
 exit:
 	ar9003_mci_enable_interrupt(ah);
 	return 0;
@@ -799,6 +804,9 @@ static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable)
 	REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2,
 		      AR_MCI_SCHD_TABLE_2_MEM_BASED, 1);
 
+	if (AR_SREV_9565(ah))
+		REG_RMW_FIELD(ah, AR_MCI_MISC, AR_MCI_MISC_HW_FIX_EN, 1);
+
 	if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) {
 		thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH);
 		REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
@@ -818,7 +826,7 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
 {
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
-	u32 regval;
+	u32 regval, i;
 
 	ath_dbg(common, MCI, "MCI Reset (full_sleep = %d, is_2g = %d)\n",
 		is_full_sleep, is_2g);
@@ -847,11 +855,18 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
 		 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
 		 SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
 		 SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
-		 SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
-		 SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
 		 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
 		 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
 		 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
+	if (AR_SREV_9565(ah)) {
+		regval |= SM(1, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
+			  SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK);
+		REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
+			      AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x1);
+	} else {
+		regval |= SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
+			  SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK);
+	}
 
 	REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
 
@@ -865,9 +880,24 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
 	REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3,
 		      AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20);
 
-	REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 1);
+	REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 0);
 	REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
 
+	/* Set the time out to 3.125ms (5 BT slots) */
+	REG_RMW_FIELD(ah, AR_BTCOEX_WL_LNA, AR_BTCOEX_WL_LNA_TIMEOUT, 0x3D090);
+
+	/* concurrent tx priority */
+	if (mci->config & ATH_MCI_CONFIG_CONCUR_TX) {
+		REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
+			      AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE, 0);
+		REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
+			      AR_BTCOEX_CTRL2_TXPWR_THRESH, 0x7f);
+		REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
+			      AR_BTCOEX_CTRL_REDUCE_TXPWR, 0);
+		for (i = 0; i < 8; i++)
+			REG_WRITE(ah, AR_BTCOEX_MAX_TXPWR(i), 0x7f7f7f7f);
+	}
+
 	regval = MS(mci->config, ATH_MCI_CONFIG_CLK_DIV);
 	REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval);
 	REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN);
@@ -910,6 +940,9 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
 	mci->ready = true;
 	ar9003_mci_prep_interface(ah);
 
+	if (AR_SREV_9565(ah))
+		REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL,
+			      AR_MCI_DBG_CNT_CTRL_ENABLE, 0);
 	if (en_int)
 		ar9003_mci_enable_interrupt(ah);
 
@@ -1028,7 +1061,9 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)
 
 		if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
 			ar9003_mci_osla_setup(ah, true);
-		REG_WRITE(ah, AR_SELFGEN_MASK, 0x02);
+
+		if (AR_SREV_9462(ah))
+			REG_WRITE(ah, AR_SELFGEN_MASK, 0x02);
 	} else {
 		ar9003_mci_send_lna_take(ah, true);
 		udelay(5);
@@ -1170,7 +1205,7 @@ EXPORT_SYMBOL(ar9003_mci_cleanup);
 u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type)
 {
 	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
-	u32 value = 0;
+	u32 value = 0, tsf;
 	u8 query_type;
 
 	switch (state_type) {
@@ -1228,6 +1263,14 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type)
 		ar9003_mci_send_coex_bt_status_query(ah, true, query_type);
 		break;
 	case MCI_STATE_RECOVER_RX:
+		tsf = ath9k_hw_gettsf32(ah);
+		if ((tsf - mci->last_recovery) <= MCI_RECOVERY_DUR_TSF) {
+			ath_dbg(ath9k_hw_common(ah), MCI,
+				"(MCI) ignore Rx recovery\n");
+			break;
+		}
+		ath_dbg(ath9k_hw_common(ah), MCI, "(MCI) RECOVER RX\n");
+		mci->last_recovery = tsf;
 		ar9003_mci_prep_interface(ah);
 		mci->query_bt = true;
 		mci->need_flush_btinfo = true;
@@ -1426,3 +1469,17 @@ void ar9003_mci_send_wlan_channels(struct ath_hw *ah)
 	ar9003_mci_send_coex_wlan_channels(ah, true);
 }
 EXPORT_SYMBOL(ar9003_mci_send_wlan_channels);
+
+u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode)
+{
+	if (!ah->btcoex_hw.mci.concur_tx)
+		goto out;
+
+	if (ctlmode == CTL_2GHT20)
+		return ATH_BTCOEX_HT20_MAX_TXPOWER;
+	else if (ctlmode == CTL_2GHT40)
+		return ATH_BTCOEX_HT40_MAX_TXPOWER;
+
+out:
+	return -1;
+}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.h b/drivers/net/wireless/ath/ath9k/ar9003_mci.h
index 2a2d018..66d7ab9 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mci.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.h
@@ -18,6 +18,7 @@
 #define AR9003_MCI_H
 
 #define MCI_FLAG_DISABLE_TIMESTAMP      0x00000001      /* Disable time stamp */
+#define MCI_RECOVERY_DUR_TSF		(100 * 1000)    /* 100 ms */
 
 /* Default remote BT device MCI COEX version */
 #define MCI_GPM_COEX_MAJOR_VERSION_DEFAULT  3
@@ -125,6 +126,7 @@ enum ath_mci_gpm_coex_profile_type {
 	MCI_GPM_COEX_PROFILE_HID,
 	MCI_GPM_COEX_PROFILE_BNEP,
 	MCI_GPM_COEX_PROFILE_VOICE,
+	MCI_GPM_COEX_PROFILE_A2DPVO,
 	MCI_GPM_COEX_PROFILE_MAX
 };
 
@@ -196,7 +198,6 @@ enum mci_state_type {
 	MCI_STATE_SEND_WLAN_COEX_VERSION,
 	MCI_STATE_SEND_VERSION_QUERY,
 	MCI_STATE_SEND_STATUS_QUERY,
-	MCI_STATE_SET_CONCUR_TX_PRI,
 	MCI_STATE_RECOVER_RX,
 	MCI_STATE_NEED_FTP_STOMP,
 	MCI_STATE_DEBUG,
@@ -278,6 +279,7 @@ void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked);
 void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah);
 void ar9003_mci_set_power_awake(struct ath_hw *ah);
 void ar9003_mci_check_gpm_offset(struct ath_hw *ah);
+u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode);
 
 #else
 
@@ -324,6 +326,10 @@ static inline void ar9003_mci_set_power_awake(struct ath_hw *ah)
 static inline void ar9003_mci_check_gpm_offset(struct ath_hw *ah)
 {
 }
+static inline u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode)
+{
+	return -1;
+}
 #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
 
 #endif
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 759f5f5..ce19c09 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -784,7 +784,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
 	REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
 
 	if (chan->channel == 2484)
-		ar9003_hw_prog_ini(ah, &ah->ini_japan2484, 1);
+		ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1);
 
 	if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
 		REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index 9a48e3d..4c3d06d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -32,6 +32,7 @@
 #define AR_PHY_SPUR_REG     (AR_CHAN_BASE + 0x1c)
 #define AR_PHY_RX_IQCAL_CORR_B0    (AR_CHAN_BASE + 0xdc)
 #define AR_PHY_TX_IQCAL_CONTROL_3  (AR_CHAN_BASE + 0xb0)
+#define AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT 16
 
 #define AR_PHY_TIMING11_SPUR_FREQ_SD    0x3FF00000
 #define AR_PHY_TIMING11_SPUR_FREQ_SD_S  20
@@ -697,13 +698,6 @@
 #define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT   0x0000ff00
 #define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT_S 8
 
-#define AR_PHY_65NM_CH0_RXTX1       0x16100
-#define AR_PHY_65NM_CH0_RXTX2       0x16104
-#define AR_PHY_65NM_CH1_RXTX1       0x16500
-#define AR_PHY_65NM_CH1_RXTX2       0x16504
-#define AR_PHY_65NM_CH2_RXTX1       0x16900
-#define AR_PHY_65NM_CH2_RXTX2       0x16904
-
 #define AR_CH0_TOP2		(AR_SREV_9300(ah) ? 0x1628c : \
 					(AR_SREV_9462(ah) ? 0x16290 : 0x16284))
 #define AR_CH0_TOP2_XPABIASLVL		0xf000
@@ -1285,4 +1279,43 @@
 #define AR_BTCOEX_WL_LNADIV_BT_INACTIVE_THRESHOLD          0xFC000000
 #define AR_BTCOEX_WL_LNADIV_BT_INACTIVE_THRESHOLD_S        26
 
+/* Manual Peak detector calibration */
+#define AR_PHY_65NM_BASE                               0x16000
+#define AR_PHY_65NM_RXRF_GAINSTAGES(i)                 (AR_PHY_65NM_BASE + \
+							(i * 0x400) + 0x8)
+#define AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE        0x80000000
+#define AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE_S      31
+#define AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC        0x00000002
+#define AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC_S      1
+#define AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR     0x70000000
+#define AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR_S   28
+#define AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR     0x03800000
+#define AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR_S   23
+
+#define AR_PHY_65NM_RXTX2(i)                           (AR_PHY_65NM_BASE + \
+							(i * 0x400) + 0x104)
+#define AR_PHY_65NM_RXTX2_RXON_OVR                     0x00001000
+#define AR_PHY_65NM_RXTX2_RXON_OVR_S                   12
+#define AR_PHY_65NM_RXTX2_RXON                         0x00000800
+#define AR_PHY_65NM_RXTX2_RXON_S                       11
+
+#define AR_PHY_65NM_RXRF_AGC(i)                        (AR_PHY_65NM_BASE + \
+							(i * 0x400) + 0xc)
+#define AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE              0x80000000
+#define AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE_S            31
+#define AR_PHY_65NM_RXRF_AGC_AGC_ON_OVR                0x40000000
+#define AR_PHY_65NM_RXRF_AGC_AGC_ON_OVR_S              30
+#define AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR               0x20000000
+#define AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR_S             29
+#define AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR           0x1E000000
+#define AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR_S         25
+#define AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR           0x00078000
+#define AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR_S         15
+#define AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR          0x01F80000
+#define AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR_S        19
+#define AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR          0x00007e00
+#define AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR_S        9
+#define AR_PHY_65NM_RXRF_AGC_AGC_OUT                   0x00000004
+#define AR_PHY_65NM_RXRF_AGC_AGC_OUT_S                 2
+
 #endif  /* AR9003_PHY_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
index 58f30f6..ccc42a7 100644
--- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
@@ -78,7 +78,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
 	{0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
 	{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
 	{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
-	{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+	{0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
 	{0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
 	{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
 	{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
index fb4497f..a3710f3 100644
--- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
@@ -18,7 +18,7 @@
 #ifndef INITVALS_9485_H
 #define INITVALS_9485_H
 
-/* AR9485 1.0 */
+/* AR9485 1.1 */
 
 #define ar9485_1_1_mac_postamble ar9300_2p2_mac_postamble
 
@@ -31,6 +31,11 @@ static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = {
 
 static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = {
 	/* Addr      allmodes  */
+	{0x00009e00, 0x037216a0},
+	{0x00009e04, 0x00182020},
+	{0x00009e18, 0x00000000},
+	{0x00009e2c, 0x00004121},
+	{0x00009e44, 0x02282324},
 	{0x0000a000, 0x00060005},
 	{0x0000a004, 0x00810080},
 	{0x0000a008, 0x00830082},
@@ -164,6 +169,11 @@ static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = {
 static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
 	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
 	{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+	{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a},
+	{0x0000a2dc, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+	{0x0000a2e0, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+	{0x0000a2e4, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+	{0x0000a2e8, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
 	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
 	{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
@@ -198,6 +208,22 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
 	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
 	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
 	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a58c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a590, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a594, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a598, 0x00000000, 0x00000000, 0x01404501, 0x01404501},
+	{0x0000a59c, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
+	{0x0000a5a0, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
+	{0x0000a5a4, 0x00000000, 0x00000000, 0x02808803, 0x02808803},
+	{0x0000a5a8, 0x00000000, 0x00000000, 0x04c14b04, 0x04c14b04},
+	{0x0000a5ac, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+	{0x0000a5b0, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+	{0x0000a5b4, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+	{0x0000a5b8, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+	{0x0000a5bc, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
 	{0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
@@ -234,9 +260,193 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
 	{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
 };
 
-#define ar9485Modes_high_ob_db_tx_gain_1_1 ar9485Modes_high_power_tx_gain_1_1
+static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = {
+	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+	{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+	{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a},
+	{0x0000a2dc, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+	{0x0000a2e0, 0x00000000, 0x00000000, 0xffc63a84, 0xffc63a84},
+	{0x0000a2e4, 0x00000000, 0x00000000, 0xfe0fc000, 0xfe0fc000},
+	{0x0000a2e8, 0x00000000, 0x00000000, 0xfff00000, 0xfff00000},
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+	{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a58c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a590, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a594, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a598, 0x00000000, 0x00000000, 0x01404501, 0x01404501},
+	{0x0000a59c, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
+	{0x0000a5a0, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
+	{0x0000a5a4, 0x00000000, 0x00000000, 0x02808803, 0x02808803},
+	{0x0000a5a8, 0x00000000, 0x00000000, 0x04c14b04, 0x04c14b04},
+	{0x0000a5ac, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+	{0x0000a5b0, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+	{0x0000a5b4, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+	{0x0000a5b8, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+	{0x0000a5bc, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+	{0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+	{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
 
-#define ar9485Modes_low_ob_db_tx_gain_1_1 ar9485Modes_high_ob_db_tx_gain_1_1
+static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {
+	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+	{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+	{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a},
+	{0x0000a2dc, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+	{0x0000a2e0, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+	{0x0000a2e4, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+	{0x0000a2e8, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+	{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a58c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a590, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a594, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a598, 0x00000000, 0x00000000, 0x01404501, 0x01404501},
+	{0x0000a59c, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
+	{0x0000a5a0, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
+	{0x0000a5a4, 0x00000000, 0x00000000, 0x02808803, 0x02808803},
+	{0x0000a5a8, 0x00000000, 0x00000000, 0x04c14b04, 0x04c14b04},
+	{0x0000a5ac, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+	{0x0000a5b0, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+	{0x0000a5b4, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+	{0x0000a5b8, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+	{0x0000a5bc, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+	{0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+	{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
 
 #define ar9485_modes_lowest_ob_db_tx_gain_1_1 ar9485Modes_low_ob_db_tx_gain_1_1
 
@@ -245,19 +455,19 @@ static const u32 ar9485_1_1[][2] = {
 	{0x0000a580, 0x00000000},
 	{0x0000a584, 0x00000000},
 	{0x0000a588, 0x00000000},
-	{0x0000a58c, 0x00000000},
-	{0x0000a590, 0x00000000},
-	{0x0000a594, 0x00000000},
-	{0x0000a598, 0x00000000},
-	{0x0000a59c, 0x00000000},
-	{0x0000a5a0, 0x00000000},
-	{0x0000a5a4, 0x00000000},
-	{0x0000a5a8, 0x00000000},
-	{0x0000a5ac, 0x00000000},
-	{0x0000a5b0, 0x00000000},
-	{0x0000a5b4, 0x00000000},
-	{0x0000a5b8, 0x00000000},
-	{0x0000a5bc, 0x00000000},
+	{0x0000a58c, 0x01804000},
+	{0x0000a590, 0x02808a02},
+	{0x0000a594, 0x0340ca02},
+	{0x0000a598, 0x0340cd03},
+	{0x0000a59c, 0x0340cd03},
+	{0x0000a5a0, 0x06415304},
+	{0x0000a5a4, 0x04c11905},
+	{0x0000a5a8, 0x06415905},
+	{0x0000a5ac, 0x06415905},
+	{0x0000a5b0, 0x06415905},
+	{0x0000a5b4, 0x06415905},
+	{0x0000a5b8, 0x06415905},
+	{0x0000a5bc, 0x06415905},
 };
 
 static const u32 ar9485_1_1_radio_core[][2] = {
@@ -340,7 +550,7 @@ static const u32 ar9485_1_1_baseband_core[][2] = {
 	{0x00009880, 0x201fff00},
 	{0x00009884, 0x00001042},
 	{0x000098a4, 0x00200400},
-	{0x000098b0, 0x52440bbe},
+	{0x000098b0, 0x32840bbe},
 	{0x000098d0, 0x004b6a8e},
 	{0x000098d4, 0x00000820},
 	{0x000098dc, 0x00000000},
@@ -362,7 +572,7 @@ static const u32 ar9485_1_1_baseband_core[][2] = {
 	{0x00009d18, 0x00000000},
 	{0x00009d1c, 0x00000000},
 	{0x00009e08, 0x0038233c},
-	{0x00009e24, 0x9927b515},
+	{0x00009e24, 0x992bb515},
 	{0x00009e28, 0x12ef0200},
 	{0x00009e30, 0x06336f77},
 	{0x00009e34, 0x6af6532f},
@@ -427,7 +637,7 @@ static const u32 ar9485_1_1_baseband_core[][2] = {
 	{0x0000a408, 0x0e79e5c6},
 	{0x0000a40c, 0x00820820},
 	{0x0000a414, 0x1ce739cf},
-	{0x0000a418, 0x2d0019ce},
+	{0x0000a418, 0x2d0021ce},
 	{0x0000a41c, 0x1ce739ce},
 	{0x0000a420, 0x000001ce},
 	{0x0000a424, 0x1ce739ce},
@@ -443,8 +653,8 @@ static const u32 ar9485_1_1_baseband_core[][2] = {
 	{0x0000a44c, 0x00000001},
 	{0x0000a450, 0x00010000},
 	{0x0000a5c4, 0xbfad9d74},
-	{0x0000a5c8, 0x0048060a},
-	{0x0000a5cc, 0x00000637},
+	{0x0000a5c8, 0x00480605},
+	{0x0000a5cc, 0x00002e37},
 	{0x0000a760, 0x03020100},
 	{0x0000a764, 0x09080504},
 	{0x0000a768, 0x0d0c0b0a},
@@ -464,17 +674,22 @@ static const u32 ar9485_1_1_baseband_core[][2] = {
 
 static const u32 ar9485_common_rx_gain_1_1[][2] = {
 	/* Addr      allmodes  */
-	{0x0000a000, 0x00010000},
-	{0x0000a004, 0x00030002},
-	{0x0000a008, 0x00050004},
-	{0x0000a00c, 0x00810080},
-	{0x0000a010, 0x01800082},
-	{0x0000a014, 0x01820181},
-	{0x0000a018, 0x01840183},
-	{0x0000a01c, 0x01880185},
-	{0x0000a020, 0x018a0189},
-	{0x0000a024, 0x02850284},
-	{0x0000a028, 0x02890288},
+	{0x00009e00, 0x03721b20},
+	{0x00009e04, 0x00082020},
+	{0x00009e18, 0x0300501e},
+	{0x00009e2c, 0x00002e21},
+	{0x00009e44, 0x02182324},
+	{0x0000a000, 0x00060005},
+	{0x0000a004, 0x00810080},
+	{0x0000a008, 0x00830082},
+	{0x0000a00c, 0x00850084},
+	{0x0000a010, 0x01820181},
+	{0x0000a014, 0x01840183},
+	{0x0000a018, 0x01880185},
+	{0x0000a01c, 0x018a0189},
+	{0x0000a020, 0x02850284},
+	{0x0000a024, 0x02890288},
+	{0x0000a028, 0x028b028a},
 	{0x0000a02c, 0x03850384},
 	{0x0000a030, 0x03890388},
 	{0x0000a034, 0x038b038a},
@@ -496,15 +711,15 @@ static const u32 ar9485_common_rx_gain_1_1[][2] = {
 	{0x0000a074, 0x00000000},
 	{0x0000a078, 0x00000000},
 	{0x0000a07c, 0x00000000},
-	{0x0000a080, 0x28282828},
-	{0x0000a084, 0x28282828},
-	{0x0000a088, 0x28282828},
-	{0x0000a08c, 0x28282828},
-	{0x0000a090, 0x28282828},
-	{0x0000a094, 0x21212128},
-	{0x0000a098, 0x171c1c1c},
-	{0x0000a09c, 0x02020212},
-	{0x0000a0a0, 0x00000202},
+	{0x0000a080, 0x18181818},
+	{0x0000a084, 0x18181818},
+	{0x0000a088, 0x18181818},
+	{0x0000a08c, 0x18181818},
+	{0x0000a090, 0x18181818},
+	{0x0000a094, 0x18181818},
+	{0x0000a098, 0x17181818},
+	{0x0000a09c, 0x02020b0b},
+	{0x0000a0a0, 0x02020202},
 	{0x0000a0a4, 0x00000000},
 	{0x0000a0a8, 0x00000000},
 	{0x0000a0ac, 0x00000000},
@@ -512,22 +727,22 @@ static const u32 ar9485_common_rx_gain_1_1[][2] = {
 	{0x0000a0b4, 0x00000000},
 	{0x0000a0b8, 0x00000000},
 	{0x0000a0bc, 0x00000000},
-	{0x0000a0c0, 0x001f0000},
-	{0x0000a0c4, 0x111f1100},
-	{0x0000a0c8, 0x111d111e},
-	{0x0000a0cc, 0x111b111c},
-	{0x0000a0d0, 0x22032204},
-	{0x0000a0d4, 0x22012202},
-	{0x0000a0d8, 0x221f2200},
-	{0x0000a0dc, 0x221d221e},
-	{0x0000a0e0, 0x33013302},
-	{0x0000a0e4, 0x331f3300},
-	{0x0000a0e8, 0x4402331e},
-	{0x0000a0ec, 0x44004401},
-	{0x0000a0f0, 0x441e441f},
-	{0x0000a0f4, 0x55015502},
-	{0x0000a0f8, 0x551f5500},
-	{0x0000a0fc, 0x6602551e},
+	{0x0000a0c0, 0x22072208},
+	{0x0000a0c4, 0x22052206},
+	{0x0000a0c8, 0x22032204},
+	{0x0000a0cc, 0x22012202},
+	{0x0000a0d0, 0x221f2200},
+	{0x0000a0d4, 0x221d221e},
+	{0x0000a0d8, 0x33023303},
+	{0x0000a0dc, 0x33003301},
+	{0x0000a0e0, 0x331e331f},
+	{0x0000a0e4, 0x4402331d},
+	{0x0000a0e8, 0x44004401},
+	{0x0000a0ec, 0x441e441f},
+	{0x0000a0f0, 0x55025503},
+	{0x0000a0f4, 0x55005501},
+	{0x0000a0f8, 0x551e551f},
+	{0x0000a0fc, 0x6602551d},
 	{0x0000a100, 0x66006601},
 	{0x0000a104, 0x661e661f},
 	{0x0000a108, 0x7703661d},
@@ -636,17 +851,12 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = {
 	{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
 	{0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
 	{0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
-	{0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
-	{0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
 	{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
 	{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e},
-	{0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
-	{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00009e14, 0x31395d53, 0x31396053, 0x312e6053, 0x312e5d53},
 	{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
 	{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
-	{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
 	{0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
-	{0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
 	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
 	{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
 	{0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0},
@@ -850,4 +1060,6 @@ static const u32 ar9485_1_1_mac_core[][2] = {
 	{0x000083d0, 0x000301ff},
 };
 
+#define ar9485_1_1_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
+
 #endif /* INITVALS_9485_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
index 843e79f..0c2ac0c 100644
--- a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
@@ -768,9 +768,9 @@ static const u32 ar9565_1p0_Modes_lowest_ob_db_tx_gain_table[][5] = {
 	{0x00016054, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 };
 
-static const u32 ar9565_1p0_pciephy_pll_on_clkreq_disable_L1[][2] = {
+static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = {
 	/* Addr      allmodes  */
-	{0x00018c00, 0x18212ede},
+	{0x00018c00, 0x18213ede},
 	{0x00018c04, 0x000801d8},
 	{0x00018c08, 0x0003780c},
 };
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index dfe6a47..80bab1b 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -129,10 +129,10 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
 #define ATH_TXMAXTRY            13
 
 #define TID_TO_WME_AC(_tid)				\
-	((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE :	\
-	 (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK :	\
-	 (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI :	\
-	 WME_AC_VO)
+	((((_tid) == 0) || ((_tid) == 3)) ? IEEE80211_AC_BE :	\
+	 (((_tid) == 1) || ((_tid) == 2)) ? IEEE80211_AC_BK :	\
+	 (((_tid) == 4) || ((_tid) == 5)) ? IEEE80211_AC_VI :	\
+	 IEEE80211_AC_VO)
 
 #define ATH_AGGR_DELIM_SZ          4
 #define ATH_AGGR_MINPLEN           256 /* in bytes, minimum packet length */
@@ -259,13 +259,10 @@ struct ath_atx_tid {
 };
 
 struct ath_node {
-#ifdef CONFIG_ATH9K_DEBUGFS
-	struct list_head list; /* for sc->nodes */
-#endif
 	struct ieee80211_sta *sta; /* station struct we're part of */
 	struct ieee80211_vif *vif; /* interface with which we're associated */
 	struct ath_atx_tid tid[WME_NUM_TID];
-	struct ath_atx_ac ac[WME_NUM_AC];
+	struct ath_atx_ac ac[IEEE80211_NUM_ACS];
 	int ps_key;
 
 	u16 maxampdu;
@@ -299,9 +296,9 @@ struct ath_tx {
 	struct list_head txbuf;
 	struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
 	struct ath_descdma txdma;
-	struct ath_txq *txq_map[WME_NUM_AC];
-	u32 txq_max_pending[WME_NUM_AC];
-	u16 max_aggr_framelen[WME_NUM_AC][4][32];
+	struct ath_txq *txq_map[IEEE80211_NUM_ACS];
+	u32 txq_max_pending[IEEE80211_NUM_ACS];
+	u16 max_aggr_framelen[IEEE80211_NUM_ACS][4][32];
 };
 
 struct ath_rx_edma {
@@ -437,6 +434,7 @@ void ath9k_set_beacon(struct ath_softc *sc);
 #define ATH_LONG_CALINTERVAL_INT  1000    /* 1000 ms */
 #define ATH_LONG_CALINTERVAL      30000   /* 30 seconds */
 #define ATH_RESTART_CALINTERVAL   1200000 /* 20 minutes */
+#define ATH_ANI_MAX_SKIP_COUNT  10
 
 #define ATH_PAPRD_TIMEOUT	100 /* msecs */
 #define ATH_PLL_WORK_INTERVAL   100
@@ -460,6 +458,12 @@ void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
 /* BTCOEX */
 /**********/
 
+#define ATH_DUMP_BTCOEX(_s, _val)				\
+	do {							\
+		len += snprintf(buf + len, size - len,		\
+				"%20s : %10d\n", _s, (_val));	\
+	} while (0)
+
 enum bt_op_flags {
 	BT_OP_PRIORITY_DETECTED,
 	BT_OP_SCAN,
@@ -478,8 +482,10 @@ struct ath_btcoex {
 	u32 btscan_no_stomp; /* in usec */
 	u32 duty_cycle;
 	u32 bt_wait_time;
+	int rssi_count;
 	struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
 	struct ath_mci_profile mci;
+	u8 stomp_audio;
 };
 
 #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
@@ -492,6 +498,7 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc);
 void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status);
 u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen);
 void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc);
+int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size);
 #else
 static inline int ath9k_init_btcoex(struct ath_softc *sc)
 {
@@ -518,6 +525,10 @@ static inline u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc,
 static inline void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
 {
 }
+static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
+{
+	return 0;
+}
 #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
 
 struct ath9k_wow_pattern {
@@ -642,6 +653,7 @@ enum sc_op_flags {
 #define PS_WAIT_FOR_PSPOLL_DATA   BIT(2)
 #define PS_WAIT_FOR_TX_ACK        BIT(3)
 #define PS_BEACON_SYNC            BIT(4)
+#define PS_WAIT_FOR_ANI           BIT(5)
 
 struct ath_rate_table;
 
@@ -708,9 +720,6 @@ struct ath_softc {
 
 #ifdef CONFIG_ATH9K_DEBUGFS
 	struct ath9k_debug debug;
-	spinlock_t nodes_lock;
-	struct list_head nodes; /* basically, stations */
-	unsigned int tx_complete_poll_work_seen;
 #endif
 	struct ath_beacon_config cur_beacon_conf;
 	struct delayed_work tx_complete_work;
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 1b48414..531fffd 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -46,7 +46,7 @@ static void ath9k_beaconq_config(struct ath_softc *sc)
 		qi.tqi_cwmax = 0;
 	} else {
 		/* Adhoc mode; important thing is to use 2x cwmin. */
-		txq = sc->tx.txq_map[WME_AC_BE];
+		txq = sc->tx.txq_map[IEEE80211_AC_BE];
 		ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
 		qi.tqi_aifs = qi_be.tqi_aifs;
 		if (ah->slottime == ATH9K_SLOT_TIME_20)
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c
index 419e9a3..9963b0b 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.c
+++ b/drivers/net/wireless/ath/ath9k/btcoex.c
@@ -49,6 +49,7 @@ static const u32 mci_wlan_weights[ATH_BTCOEX_STOMP_MAX]
 	{ 0x01017d01, 0x3b3b3b01, 0x3b3b3b01, 0x3b3b3b3b }, /* STOMP_LOW */
 	{ 0x01017d01, 0x01010101, 0x01010101, 0x01010101 }, /* STOMP_NONE */
 	{ 0x01017d01, 0x013b0101, 0x3b3b0101, 0x3b3b013b }, /* STOMP_LOW_FTP */
+	{ 0xffffff01, 0xffffffff, 0xffffff01, 0xffffffff }, /* STOMP_AUDIO */
 };
 
 void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
@@ -195,7 +196,7 @@ void ath9k_hw_btcoex_init_mci(struct ath_hw *ah)
 	ah->btcoex_hw.mci.need_flush_btinfo = false;
 	ah->btcoex_hw.mci.wlan_cal_seq = 0;
 	ah->btcoex_hw.mci.wlan_cal_done = 0;
-	ah->btcoex_hw.mci.config = 0x2201;
+	ah->btcoex_hw.mci.config = (AR_SREV_9462(ah)) ? 0x2201 : 0xa4c1;
 }
 EXPORT_SYMBOL(ath9k_hw_btcoex_init_mci);
 
@@ -218,27 +219,45 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
 				enum ath_stomp_type stomp_type)
 {
 	struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+	struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
+	u8 txprio_shift[] = { 24, 16, 16, 0 }; /* tx priority weight */
+	bool concur_tx = (mci_hw->concur_tx && btcoex_hw->tx_prio[stomp_type]);
+	const u32 *weight = ar9003_wlan_weights[stomp_type];
+	int i;
 
-	if (AR_SREV_9300_20_OR_LATER(ah)) {
-		const u32 *weight = ar9003_wlan_weights[stomp_type];
-		int i;
-
-		if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
-			if ((stomp_type == ATH_BTCOEX_STOMP_LOW) &&
-			    btcoex_hw->mci.stomp_ftp)
-				stomp_type = ATH_BTCOEX_STOMP_LOW_FTP;
-			weight = mci_wlan_weights[stomp_type];
-		}
-
-		for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) {
-			btcoex_hw->bt_weight[i] = AR9300_BT_WGHT;
-			btcoex_hw->wlan_weight[i] = weight[i];
-		}
-	} else {
+	if (!AR_SREV_9300_20_OR_LATER(ah)) {
 		btcoex_hw->bt_coex_weights =
 			SM(bt_weight, AR_BTCOEX_BT_WGHT) |
 			SM(wlan_weight, AR_BTCOEX_WL_WGHT);
+		return;
+	}
+
+	if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
+		enum ath_stomp_type stype =
+			((stomp_type == ATH_BTCOEX_STOMP_LOW) &&
+			 btcoex_hw->mci.stomp_ftp) ?
+			ATH_BTCOEX_STOMP_LOW_FTP : stomp_type;
+		weight = mci_wlan_weights[stype];
 	}
+
+	for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) {
+		btcoex_hw->bt_weight[i] = AR9300_BT_WGHT;
+		btcoex_hw->wlan_weight[i] = weight[i];
+		if (concur_tx && i) {
+			btcoex_hw->wlan_weight[i] &=
+				~(0xff << txprio_shift[i-1]);
+			btcoex_hw->wlan_weight[i] |=
+				(btcoex_hw->tx_prio[stomp_type] <<
+				 txprio_shift[i-1]);
+		}
+	}
+	/* Last WLAN weight has to be adjusted wrt tx priority */
+	if (concur_tx) {
+		btcoex_hw->wlan_weight[i-1] &= ~(0xff << txprio_shift[i-1]);
+		btcoex_hw->wlan_weight[i-1] |= (btcoex_hw->tx_prio[stomp_type]
+						      << txprio_shift[i-1]);
+	}
+
 }
 EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight);
 
@@ -385,3 +404,13 @@ void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
 	}
 }
 EXPORT_SYMBOL(ath9k_hw_btcoex_bt_stomp);
+
+void ath9k_hw_btcoex_set_concur_txprio(struct ath_hw *ah, u8 *stomp_txprio)
+{
+	struct ath_btcoex_hw *btcoex = &ah->btcoex_hw;
+	int i;
+
+	for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++)
+		btcoex->tx_prio[i] = stomp_txprio[i];
+}
+EXPORT_SYMBOL(ath9k_hw_btcoex_set_concur_txprio);
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h
index 385197a..6de26ea 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.h
+++ b/drivers/net/wireless/ath/ath9k/btcoex.h
@@ -39,6 +39,9 @@
 #define ATH_BTCOEX_RX_WAIT_TIME       100
 #define ATH_BTCOEX_STOMP_FTP_THRESH   5
 
+#define ATH_BTCOEX_HT20_MAX_TXPOWER   0x14
+#define ATH_BTCOEX_HT40_MAX_TXPOWER   0x10
+
 #define AR9300_NUM_BT_WEIGHTS   4
 #define AR9300_NUM_WLAN_WEIGHTS 4
 /* Defines the BT AR_BT_COEX_WGHT used */
@@ -47,6 +50,7 @@ enum ath_stomp_type {
 	ATH_BTCOEX_STOMP_LOW,
 	ATH_BTCOEX_STOMP_NONE,
 	ATH_BTCOEX_STOMP_LOW_FTP,
+	ATH_BTCOEX_STOMP_AUDIO,
 	ATH_BTCOEX_STOMP_MAX
 };
 
@@ -84,6 +88,8 @@ struct ath9k_hw_mci {
 	u8 bt_ver_minor;
 	u8 bt_state;
 	u8 stomp_ftp;
+	bool concur_tx;
+	u32 last_recovery;
 };
 
 struct ath_btcoex_hw {
@@ -98,6 +104,7 @@ struct ath_btcoex_hw {
 	u32 bt_coex_mode2; 	/* Register setting for AR_BT_COEX_MODE2 */
 	u32 bt_weight[AR9300_NUM_BT_WEIGHTS];
 	u32 wlan_weight[AR9300_NUM_WLAN_WEIGHTS];
+	u8 tx_prio[ATH_BTCOEX_STOMP_MAX];
 };
 
 void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah);
@@ -112,5 +119,6 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
 void ath9k_hw_btcoex_disable(struct ath_hw *ah);
 void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
 			      enum ath_stomp_type stomp_type);
+void ath9k_hw_btcoex_set_concur_txprio(struct ath_hw *ah, u8 *stomp_txprio);
 
 #endif
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index e5cceb0..f3448a0 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -410,6 +410,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
 
 	ah->caldata->channel = chan->channel;
 	ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT;
+	ah->caldata->chanmode = chan->chanmode;
 	h = ah->caldata->nfCalHist;
 	default_nf = ath9k_hw_get_default_nf(ah, chan);
 	for (i = 0; i < NUM_NF_READINGS; i++) {
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index ad14fec..76b5439 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -28,13 +28,6 @@
 #define WME_MAX_BA              WME_BA_BMP_SIZE
 #define ATH_TID_MAX_BUFS        (2 * WME_MAX_BA)
 
-/* These must match mac80211 skb queue mapping numbers */
-#define WME_AC_VO   0
-#define WME_AC_VI   1
-#define WME_AC_BE   2
-#define WME_AC_BK   3
-#define WME_NUM_AC  4
-
 #define ATH_RSSI_DUMMY_MARKER   0x127
 #define ATH_RSSI_LPF_LEN 		10
 #define RSSI_LPF_THRESHOLD		-20
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 6727b56..939308c 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -512,62 +512,19 @@ static const struct file_operations fops_interrupt = {
 	.llseek = default_llseek,
 };
 
-#define PR_QNUM(_n) sc->tx.txq_map[_n]->axq_qnum
-#define PR(str, elem)							\
-	do {								\
-		len += snprintf(buf + len, size - len,			\
-				"%s%13u%11u%10u%10u\n", str,		\
-		sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].elem, \
-		sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].elem, \
-		sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].elem, \
-		sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].elem); \
-		if (len >= size)			  \
-			goto done;			  \
-} while(0)
-
-#define PRX(str, elem)							\
-do {									\
-	len += snprintf(buf + len, size - len,				\
-			"%s%13u%11u%10u%10u\n", str,			\
-			(unsigned int)(sc->tx.txq_map[WME_AC_BE]->elem),	\
-			(unsigned int)(sc->tx.txq_map[WME_AC_BK]->elem),	\
-			(unsigned int)(sc->tx.txq_map[WME_AC_VI]->elem),	\
-			(unsigned int)(sc->tx.txq_map[WME_AC_VO]->elem));	\
-	if (len >= size)						\
-		goto done;						\
-} while(0)
-
-#define PRQLE(str, elem)						\
-do {									\
-	len += snprintf(buf + len, size - len,				\
-			"%s%13i%11i%10i%10i\n", str,			\
-			list_empty(&sc->tx.txq_map[WME_AC_BE]->elem),	\
-			list_empty(&sc->tx.txq_map[WME_AC_BK]->elem),	\
-			list_empty(&sc->tx.txq_map[WME_AC_VI]->elem),	\
-			list_empty(&sc->tx.txq_map[WME_AC_VO]->elem));	\
-	if (len >= size)						\
-		goto done;						\
-} while (0)
-
 static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
 			      size_t count, loff_t *ppos)
 {
 	struct ath_softc *sc = file->private_data;
 	char *buf;
-	unsigned int len = 0, size = 8000;
-	int i;
+	unsigned int len = 0, size = 2048;
 	ssize_t retval = 0;
-	char tmp[32];
 
 	buf = kzalloc(size, GFP_KERNEL);
 	if (buf == NULL)
 		return -ENOMEM;
 
-	len += sprintf(buf, "Num-Tx-Queues: %i  tx-queues-setup: 0x%x"
-		       " poll-work-seen: %u\n"
-		       "%30s %10s%10s%10s\n\n",
-		       ATH9K_NUM_TX_QUEUES, sc->tx.txqsetup,
-		       sc->tx_complete_poll_work_seen,
+	len += sprintf(buf, "%30s %10s%10s%10s\n\n",
 		       "BE", "BK", "VI", "VO");
 
 	PR("MPDUs Queued:    ", queued);
@@ -587,62 +544,11 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
 	PR("DELIM Underrun:  ", delim_underrun);
 	PR("TX-Pkts-All:     ", tx_pkts_all);
 	PR("TX-Bytes-All:    ", tx_bytes_all);
-	PR("hw-put-tx-buf:   ", puttxbuf);
-	PR("hw-tx-start:     ", txstart);
-	PR("hw-tx-proc-desc: ", txprocdesc);
+	PR("HW-put-tx-buf:   ", puttxbuf);
+	PR("HW-tx-start:     ", txstart);
+	PR("HW-tx-proc-desc: ", txprocdesc);
 	PR("TX-Failed:       ", txfailed);
-	len += snprintf(buf + len, size - len,
-			"%s%11p%11p%10p%10p\n", "txq-memory-address:",
-			sc->tx.txq_map[WME_AC_BE],
-			sc->tx.txq_map[WME_AC_BK],
-			sc->tx.txq_map[WME_AC_VI],
-			sc->tx.txq_map[WME_AC_VO]);
-	if (len >= size)
-		goto done;
-
-	PRX("axq-qnum:        ", axq_qnum);
-	PRX("axq-depth:       ", axq_depth);
-	PRX("axq-ampdu_depth: ", axq_ampdu_depth);
-	PRX("axq-stopped      ", stopped);
-	PRX("tx-in-progress   ", axq_tx_inprogress);
-	PRX("pending-frames   ", pending_frames);
-	PRX("txq_headidx:     ", txq_headidx);
-	PRX("txq_tailidx:     ", txq_headidx);
-
-	PRQLE("axq_q empty:       ", axq_q);
-	PRQLE("axq_acq empty:     ", axq_acq);
-	for (i = 0; i < ATH_TXFIFO_DEPTH; i++) {
-		snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i);
-		PRQLE(tmp, txq_fifo[i]);
-	}
-
-	/* Print out more detailed queue-info */
-	for (i = 0; i <= WME_AC_BK; i++) {
-		struct ath_txq *txq = &(sc->tx.txq[i]);
-		struct ath_atx_ac *ac;
-		struct ath_atx_tid *tid;
-		if (len >= size)
-			goto done;
-		spin_lock_bh(&txq->axq_lock);
-		if (!list_empty(&txq->axq_acq)) {
-			ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac,
-					      list);
-			len += snprintf(buf + len, size - len,
-					"txq[%i] first-ac: %p sched: %i\n",
-					i, ac, ac->sched);
-			if (list_empty(&ac->tid_q) || (len >= size))
-				goto done_for;
-			tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
-					       list);
-			len += snprintf(buf + len, size - len,
-					" first-tid: %p sched: %i paused: %i\n",
-					tid, tid->sched, tid->paused);
-		}
-	done_for:
-		spin_unlock_bh(&txq->axq_lock);
-	}
 
-done:
 	if (len > size)
 		len = size;
 
@@ -652,62 +558,41 @@ done:
 	return retval;
 }
 
-static ssize_t read_file_stations(struct file *file, char __user *user_buf,
-				  size_t count, loff_t *ppos)
+static ssize_t read_file_queues(struct file *file, char __user *user_buf,
+				size_t count, loff_t *ppos)
 {
 	struct ath_softc *sc = file->private_data;
+	struct ath_txq *txq;
 	char *buf;
-	unsigned int len = 0, size = 64000;
-	struct ath_node *an = NULL;
+	unsigned int len = 0, size = 1024;
 	ssize_t retval = 0;
-	int q;
+	int i;
+	char *qname[4] = {"VO", "VI", "BE", "BK"};
 
 	buf = kzalloc(size, GFP_KERNEL);
 	if (buf == NULL)
 		return -ENOMEM;
 
-	len += snprintf(buf + len, size - len,
-			"Stations:\n"
-			" tid: addr sched paused buf_q-empty an ac baw\n"
-			" ac: addr sched tid_q-empty txq\n");
-
-	spin_lock(&sc->nodes_lock);
-	list_for_each_entry(an, &sc->nodes, list) {
-		unsigned short ma = an->maxampdu;
-		if (ma == 0)
-			ma = 65535; /* see ath_lookup_rate */
-		len += snprintf(buf + len, size - len,
-				"iface: %pM  sta: %pM max-ampdu: %hu mpdu-density: %uus\n",
-				an->vif->addr, an->sta->addr, ma,
-				(unsigned int)(an->mpdudensity));
-		if (len >= size)
-			goto done;
-
-		for (q = 0; q < WME_NUM_TID; q++) {
-			struct ath_atx_tid *tid = &(an->tid[q]);
-			len += snprintf(buf + len, size - len,
-					" tid: %p %s %s %i %p %p %hu\n",
-					tid, tid->sched ? "sched" : "idle",
-					tid->paused ? "paused" : "running",
-					skb_queue_empty(&tid->buf_q),
-					tid->an, tid->ac, tid->baw_size);
-			if (len >= size)
-				goto done;
-		}
+	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+		txq = sc->tx.txq_map[i];
+		len += snprintf(buf + len, size - len, "(%s): ", qname[i]);
 
-		for (q = 0; q < WME_NUM_AC; q++) {
-			struct ath_atx_ac *ac = &(an->ac[q]);
-			len += snprintf(buf + len, size - len,
-					" ac: %p %s %i %p\n",
-					ac, ac->sched ? "sched" : "idle",
-					list_empty(&ac->tid_q), ac->txq);
-			if (len >= size)
-				goto done;
-		}
+		ath_txq_lock(sc, txq);
+
+		len += snprintf(buf + len, size - len, "%s: %d ",
+				"qnum", txq->axq_qnum);
+		len += snprintf(buf + len, size - len, "%s: %2d ",
+				"qdepth", txq->axq_depth);
+		len += snprintf(buf + len, size - len, "%s: %2d ",
+				"ampdu-depth", txq->axq_ampdu_depth);
+		len += snprintf(buf + len, size - len, "%s: %3d ",
+				"pending", txq->pending_frames);
+		len += snprintf(buf + len, size - len, "%s: %d\n",
+				"stopped", txq->stopped);
+
+		ath_txq_unlock(sc, txq);
 	}
 
-done:
-	spin_unlock(&sc->nodes_lock);
 	if (len > size)
 		len = size;
 
@@ -837,6 +722,9 @@ static ssize_t read_file_reset(struct file *file, char __user *user_buf,
 	len += snprintf(buf + len, sizeof(buf) - len,
 			"%17s: %2d\n", "PLL RX Hang",
 			sc->debug.stats.reset[RESET_TYPE_PLL_HANG]);
+	len += snprintf(buf + len, sizeof(buf) - len,
+			"%17s: %2d\n", "MCI Reset",
+			sc->debug.stats.reset[RESET_TYPE_MCI]);
 
 	if (len > sizeof(buf))
 		len = sizeof(buf);
@@ -919,8 +807,8 @@ static const struct file_operations fops_xmit = {
 	.llseek = default_llseek,
 };
 
-static const struct file_operations fops_stations = {
-	.read = read_file_stations,
+static const struct file_operations fops_queues = {
+	.read = read_file_queues,
 	.open = simple_open,
 	.owner = THIS_MODULE,
 	.llseek = default_llseek,
@@ -1586,6 +1474,41 @@ static const struct file_operations fops_samps = {
 
 #endif
 
+#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+static ssize_t read_file_btcoex(struct file *file, char __user *user_buf,
+				size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	u32 len = 0, size = 1500;
+	char *buf;
+	size_t retval;
+
+	buf = kzalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	if (!sc->sc_ah->common.btcoex_enabled) {
+		len = snprintf(buf, size, "%s\n",
+			       "BTCOEX is disabled");
+		goto exit;
+	}
+
+	len = ath9k_dump_btcoex(sc, buf, size);
+exit:
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+
+	return retval;
+}
+
+static const struct file_operations fops_btcoex = {
+	.read = read_file_btcoex,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+#endif
+
 int ath9k_init_debug(struct ath_hw *ah)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
@@ -1609,16 +1532,16 @@ int ath9k_init_debug(struct ath_hw *ah)
 			    &fops_interrupt);
 	debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc,
 			    &fops_xmit);
+	debugfs_create_file("queues", S_IRUSR, sc->debug.debugfs_phy, sc,
+			    &fops_queues);
 	debugfs_create_u32("qlen_bk", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
-			   &sc->tx.txq_max_pending[WME_AC_BK]);
+			   &sc->tx.txq_max_pending[IEEE80211_AC_BK]);
 	debugfs_create_u32("qlen_be", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
-			   &sc->tx.txq_max_pending[WME_AC_BE]);
+			   &sc->tx.txq_max_pending[IEEE80211_AC_BE]);
 	debugfs_create_u32("qlen_vi", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
-			   &sc->tx.txq_max_pending[WME_AC_VI]);
+			   &sc->tx.txq_max_pending[IEEE80211_AC_VI]);
 	debugfs_create_u32("qlen_vo", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
-			   &sc->tx.txq_max_pending[WME_AC_VO]);
-	debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, sc,
-			    &fops_stations);
+			   &sc->tx.txq_max_pending[IEEE80211_AC_VO]);
 	debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc,
 			    &fops_misc);
 	debugfs_create_file("reset", S_IRUSR, sc->debug.debugfs_phy, sc,
@@ -1658,6 +1581,9 @@ int ath9k_init_debug(struct ath_hw *ah)
 			   sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
 	debugfs_create_file("diversity", S_IRUSR | S_IWUSR,
 			    sc->debug.debugfs_phy, sc, &fops_ant_diversity);
-
+#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+	debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc,
+			    &fops_btcoex);
+#endif
 	return 0;
 }
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 2ed9785..f9bee18 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -41,6 +41,7 @@ enum ath_reset_type {
 	RESET_TYPE_PLL_HANG,
 	RESET_TYPE_MAC_HANG,
 	RESET_TYPE_BEACON_STUCK,
+	RESET_TYPE_MCI,
 	__RESET_TYPE_MAX
 };
 
@@ -178,6 +179,21 @@ struct ath_tx_stats {
 	u32 txfailed;
 };
 
+/*
+ * Various utility macros to print TX/Queue counters.
+ */
+#define PR_QNUM(_n) sc->tx.txq_map[_n]->axq_qnum
+#define TXSTATS sc->debug.stats.txstats
+#define PR(str, elem)							\
+	do {								\
+		len += snprintf(buf + len, size - len,			\
+				"%s%13u%11u%10u%10u\n", str,		\
+				TXSTATS[PR_QNUM(IEEE80211_AC_BE)].elem,	\
+				TXSTATS[PR_QNUM(IEEE80211_AC_BK)].elem,	\
+				TXSTATS[PR_QNUM(IEEE80211_AC_VI)].elem,	\
+				TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \
+	} while(0)
+
 #define RX_STAT_INC(c) (sc->debug.stats.rxstats.c++)
 
 /**
@@ -226,7 +242,7 @@ struct ath_rx_stats {
 
 struct ath_stats {
 	struct ath_interrupt_stats istats;
-	struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
+	struct ath_tx_stats txstats[IEEE80211_NUM_ACS];
 	struct ath_rx_stats rxstats;
 	struct ath_dfs_stats dfs_stats;
 	u32 reset[__RESET_TYPE_MAX];
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
index ea2a6cf..24877b0 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
+++ b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
@@ -42,10 +42,15 @@ struct radar_types {
 #define MIN_PPB_THRESH	50
 #define PPB_THRESH(PPB) ((PPB * MIN_PPB_THRESH + 50) / 100)
 #define PRF2PRI(PRF) ((1000000 + PRF / 2) / PRF)
+/* percentage of pulse width tolerance */
+#define WIDTH_TOLERANCE 5
+#define WIDTH_LOWER(X) ((X*(100-WIDTH_TOLERANCE)+50)/100)
+#define WIDTH_UPPER(X) ((X*(100+WIDTH_TOLERANCE)+50)/100)
 
 #define ETSI_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB)	\
 {								\
-	ID, WMIN, WMAX, (PRF2PRI(PMAX) - PRI_TOLERANCE),	\
+	ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX),		\
+	(PRF2PRI(PMAX) - PRI_TOLERANCE),			\
 	(PRF2PRI(PMIN) * PRF + PRI_TOLERANCE), PRF, PPB * PRF,	\
 	PPB_THRESH(PPB), PRI_TOLERANCE,				\
 }
@@ -274,7 +279,7 @@ static bool dpd_set_domain(struct dfs_pattern_detector *dpd,
 
 static struct dfs_pattern_detector default_dpd = {
 	.exit		= dpd_exit,
-	.set_domain	= dpd_set_domain,
+	.set_dfs_domain	= dpd_set_domain,
 	.add_pulse	= dpd_add_pulse,
 	.region		= NL80211_DFS_UNSET,
 };
@@ -291,10 +296,11 @@ dfs_pattern_detector_init(enum nl80211_dfs_regions region)
 	*dpd = default_dpd;
 	INIT_LIST_HEAD(&dpd->channel_detectors);
 
-	if (dpd->set_domain(dpd, region))
+	if (dpd->set_dfs_domain(dpd, region))
 		return dpd;
 
 	pr_err("Could not set DFS domain to %d. ", region);
+	kfree(dpd);
 	return NULL;
 }
 EXPORT_SYMBOL(dfs_pattern_detector_init);
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h
index fd0328a..cda52f3 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h
+++ b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h
@@ -62,7 +62,7 @@ struct radar_detector_specs {
 /**
  * struct dfs_pattern_detector - DFS pattern detector
  * @exit(): destructor
- * @set_domain(): set DFS domain, resets detector lines upon domain changes
+ * @set_dfs_domain(): set DFS domain, resets detector lines upon domain changes
  * @add_pulse(): add radar pulse to detector, returns true on detection
  * @region: active DFS region, NL80211_DFS_UNSET until set
  * @num_radar_types: number of different radar types
@@ -72,7 +72,7 @@ struct radar_detector_specs {
  */
 struct dfs_pattern_detector {
 	void (*exit)(struct dfs_pattern_detector *dpd);
-	bool (*set_domain)(struct dfs_pattern_detector *dpd,
+	bool (*set_dfs_domain)(struct dfs_pattern_detector *dpd,
 			   enum nl80211_dfs_regions region);
 	bool (*add_pulse)(struct dfs_pattern_detector *dpd,
 			  struct pulse_event *pe);
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index d9ed141..4b412aa 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -187,6 +187,24 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
 	}
 }
 
+static void ath_mci_ftp_adjust(struct ath_softc *sc)
+{
+	struct ath_btcoex *btcoex = &sc->btcoex;
+	struct ath_mci_profile *mci = &btcoex->mci;
+	struct ath_hw *ah = sc->sc_ah;
+
+	if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) {
+		if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) &&
+		    (mci->num_pan || mci->num_other_acl))
+			ah->btcoex_hw.mci.stomp_ftp =
+				(sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH);
+		else
+			ah->btcoex_hw.mci.stomp_ftp = false;
+		btcoex->bt_wait_time = 0;
+		sc->rx.num_pkts = 0;
+	}
+}
+
 /*
  * This is the master bt coex timer which runs for every
  * 45ms, bt traffic will be given priority during 55% of this
@@ -197,41 +215,46 @@ static void ath_btcoex_period_timer(unsigned long data)
 	struct ath_softc *sc = (struct ath_softc *) data;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_btcoex *btcoex = &sc->btcoex;
-	struct ath_mci_profile *mci = &btcoex->mci;
+	enum ath_stomp_type stomp_type;
 	u32 timer_period;
-	bool is_btscan;
 	unsigned long flags;
 
 	spin_lock_irqsave(&sc->sc_pm_lock, flags);
 	if (sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP) {
+		btcoex->bt_wait_time += btcoex->btcoex_period;
 		spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 		goto skip_hw_wakeup;
 	}
 	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 
+	ath9k_mci_update_rssi(sc);
+
 	ath9k_ps_wakeup(sc);
+
 	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
 		ath_detect_bt_priority(sc);
-	is_btscan = test_bit(BT_OP_SCAN, &btcoex->op_flags);
 
-	btcoex->bt_wait_time += btcoex->btcoex_period;
-	if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) {
-		if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) &&
-		    (mci->num_pan || mci->num_other_acl))
-			ah->btcoex_hw.mci.stomp_ftp =
-				(sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH);
-		else
-			ah->btcoex_hw.mci.stomp_ftp = false;
-		btcoex->bt_wait_time = 0;
-		sc->rx.num_pkts = 0;
-	}
+	if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
+		ath_mci_ftp_adjust(sc);
 
 	spin_lock_bh(&btcoex->btcoex_lock);
 
-	ath9k_hw_btcoex_bt_stomp(ah, is_btscan ? ATH_BTCOEX_STOMP_ALL :
-			      btcoex->bt_stomp_type);
+	stomp_type = btcoex->bt_stomp_type;
+	timer_period = btcoex->btcoex_no_stomp;
+
+	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) {
+		if (test_bit(BT_OP_SCAN, &btcoex->op_flags)) {
+			stomp_type = ATH_BTCOEX_STOMP_ALL;
+			timer_period = btcoex->btscan_no_stomp;
+		}
+	} else if (btcoex->stomp_audio >= 5) {
+		stomp_type = ATH_BTCOEX_STOMP_AUDIO;
+		btcoex->stomp_audio = 0;
+	}
 
+	ath9k_hw_btcoex_bt_stomp(ah, stomp_type);
 	ath9k_hw_btcoex_enable(ah);
+
 	spin_unlock_bh(&btcoex->btcoex_lock);
 
 	/*
@@ -243,17 +266,16 @@ static void ath_btcoex_period_timer(unsigned long data)
 		if (btcoex->hw_timer_enabled)
 			ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
 
-		timer_period = is_btscan ? btcoex->btscan_no_stomp :
-					   btcoex->btcoex_no_stomp;
 		ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period,
 				      timer_period * 10);
 		btcoex->hw_timer_enabled = true;
 	}
 
 	ath9k_ps_restore(sc);
+
 skip_hw_wakeup:
-	timer_period = btcoex->btcoex_period;
-	mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period));
+	mod_timer(&btcoex->period_timer,
+		  jiffies + msecs_to_jiffies(btcoex->btcoex_period));
 }
 
 /*
@@ -273,9 +295,10 @@ static void ath_btcoex_no_stomp_timer(void *arg)
 	spin_lock_bh(&btcoex->btcoex_lock);
 
 	if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW ||
-	    test_bit(BT_OP_SCAN, &btcoex->op_flags))
+	    (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI) &&
+	     test_bit(BT_OP_SCAN, &btcoex->op_flags)))
 		ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
-	 else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
+	else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
 		ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
 
 	ath9k_hw_btcoex_enable(ah);
@@ -451,7 +474,7 @@ int ath9k_init_btcoex(struct ath_softc *sc)
 		r = ath_init_btcoex_timer(sc);
 		if (r)
 			return -1;
-		txq = sc->tx.txq_map[WME_AC_BE];
+		txq = sc->tx.txq_map[IEEE80211_AC_BE];
 		ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
 		sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
 		if (ath9k_hw_mci_is_enabled(ah)) {
@@ -474,4 +497,71 @@ int ath9k_init_btcoex(struct ath_softc *sc)
 	return 0;
 }
 
+static int ath9k_dump_mci_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
+{
+	struct ath_btcoex *btcoex = &sc->btcoex;
+	struct ath_mci_profile *mci = &btcoex->mci;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+	u32 len = 0;
+	int i;
+
+	ATH_DUMP_BTCOEX("Total BT profiles", NUM_PROF(mci));
+	ATH_DUMP_BTCOEX("MGMT", mci->num_mgmt);
+	ATH_DUMP_BTCOEX("SCO", mci->num_sco);
+	ATH_DUMP_BTCOEX("A2DP", mci->num_a2dp);
+	ATH_DUMP_BTCOEX("HID", mci->num_hid);
+	ATH_DUMP_BTCOEX("PAN", mci->num_pan);
+	ATH_DUMP_BTCOEX("ACL", mci->num_other_acl);
+	ATH_DUMP_BTCOEX("BDR", mci->num_bdr);
+	ATH_DUMP_BTCOEX("Aggr. Limit", mci->aggr_limit);
+	ATH_DUMP_BTCOEX("Stomp Type", btcoex->bt_stomp_type);
+	ATH_DUMP_BTCOEX("BTCoex Period (msec)", btcoex->btcoex_period);
+	ATH_DUMP_BTCOEX("Duty Cycle", btcoex->duty_cycle);
+	ATH_DUMP_BTCOEX("BT Wait time", btcoex->bt_wait_time);
+	ATH_DUMP_BTCOEX("Concurrent Tx", btcoex_hw->mci.concur_tx);
+	ATH_DUMP_BTCOEX("Concurrent RSSI cnt", btcoex->rssi_count);
+
+	len += snprintf(buf + len, size - len, "BT Weights: ");
+	for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
+		len += snprintf(buf + len, size - len, "%08x ",
+				btcoex_hw->bt_weight[i]);
+	len += snprintf(buf + len, size - len, "\n");
+	len += snprintf(buf + len, size - len, "WLAN Weights: ");
+	for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
+		len += snprintf(buf + len, size - len, "%08x ",
+				btcoex_hw->wlan_weight[i]);
+	len += snprintf(buf + len, size - len, "\n");
+	len += snprintf(buf + len, size - len, "Tx Priorities: ");
+	for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++)
+		len += snprintf(buf + len, size - len, "%08x ",
+				btcoex_hw->tx_prio[i]);
+
+	len += snprintf(buf + len, size - len, "\n");
+
+	return len;
+}
+
+static int ath9k_dump_legacy_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
+{
+
+	struct ath_btcoex *btcoex = &sc->btcoex;
+	u32 len = 0;
+
+	ATH_DUMP_BTCOEX("Stomp Type", btcoex->bt_stomp_type);
+	ATH_DUMP_BTCOEX("BTCoex Period (msec)", btcoex->btcoex_period);
+	ATH_DUMP_BTCOEX("Duty Cycle", btcoex->duty_cycle);
+	ATH_DUMP_BTCOEX("BT Wait time", btcoex->bt_wait_time);
+
+	return len;
+}
+
+int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
+{
+	if (ath9k_hw_mci_is_enabled(sc->sc_ah))
+		return ath9k_dump_mci_btcoex(sc, buf, size);
+	else
+		return ath9k_dump_legacy_btcoex(sc, buf, size);
+}
+
 #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index b30596f..96bfb18 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -331,7 +331,7 @@ struct ath_tx_stats {
 	u32 skb_success;
 	u32 skb_failed;
 	u32 cab_queued;
-	u32 queue_stats[WME_NUM_AC];
+	u32 queue_stats[IEEE80211_NUM_ACS];
 };
 
 struct ath_rx_stats {
@@ -493,7 +493,7 @@ struct ath9k_htc_priv {
 
 	int beaconq;
 	int cabq;
-	int hwq_map[WME_NUM_AC];
+	int hwq_map[IEEE80211_NUM_ACS];
 
 #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
 	struct ath_btcoex btcoex;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index f42d2eb..d0ce1f5 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -33,7 +33,7 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
 		qi.tqi_cwmin = 0;
 		qi.tqi_cwmax = 0;
 	} else if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) {
-		int qnum = priv->hwq_map[WME_AC_BE];
+		int qnum = priv->hwq_map[IEEE80211_AC_BE];
 
 		ath9k_hw_get_txq_props(ah, qnum, &qi_be);
 
@@ -587,9 +587,9 @@ static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv,
 	    (priv->num_sta_vif > 1) &&
 	    (vif->type == NL80211_IFTYPE_STATION)) {
 		beacon_configured = false;
-		ieee80211_iterate_active_interfaces_atomic(priv->hw,
-							   ath9k_htc_beacon_iter,
-							   &beacon_configured);
+		ieee80211_iterate_active_interfaces_atomic(
+			priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+			ath9k_htc_beacon_iter, &beacon_configured);
 
 		if (beacon_configured) {
 			ath_dbg(common, CONFIG,
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index 3035deb..87110de5 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -218,16 +218,16 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
 
 	len += snprintf(buf + len, sizeof(buf) - len,
 			"%20s : %10u\n", "BE queued",
-			priv->debug.tx_stats.queue_stats[WME_AC_BE]);
+			priv->debug.tx_stats.queue_stats[IEEE80211_AC_BE]);
 	len += snprintf(buf + len, sizeof(buf) - len,
 			"%20s : %10u\n", "BK queued",
-			priv->debug.tx_stats.queue_stats[WME_AC_BK]);
+			priv->debug.tx_stats.queue_stats[IEEE80211_AC_BK]);
 	len += snprintf(buf + len, sizeof(buf) - len,
 			"%20s : %10u\n", "VI queued",
-			priv->debug.tx_stats.queue_stats[WME_AC_VI]);
+			priv->debug.tx_stats.queue_stats[IEEE80211_AC_VI]);
 	len += snprintf(buf + len, sizeof(buf) - len,
 			"%20s : %10u\n", "VO queued",
-			priv->debug.tx_stats.queue_stats[WME_AC_VO]);
+			priv->debug.tx_stats.queue_stats[IEEE80211_AC_VO]);
 
 	if (len > sizeof(buf))
 		len = sizeof(buf);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
index 0eacfc1..105582d 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
@@ -207,7 +207,7 @@ void ath9k_htc_init_btcoex(struct ath9k_htc_priv *priv, char *product)
 		priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
 		ath9k_hw_btcoex_init_3wire(priv->ah);
 		ath_htc_init_btcoex_work(priv);
-		qnum = priv->hwq_map[WME_AC_BE];
+		qnum = priv->hwq_map[IEEE80211_AC_BE];
 		ath9k_hw_init_btcoex_hw(priv->ah, qnum);
 		break;
 	default:
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index d98255e..05d5ba6 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -549,20 +549,20 @@ static int ath9k_init_queues(struct ath9k_htc_priv *priv)
 		goto err;
 	}
 
-	if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) {
+	if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_BE)) {
 		ath_err(common, "Unable to setup xmit queue for BE traffic\n");
 		goto err;
 	}
 
-	if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) {
+	if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_BK)) {
 		ath_err(common, "Unable to setup xmit queue for BK traffic\n");
 		goto err;
 	}
-	if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) {
+	if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_VI)) {
 		ath_err(common, "Unable to setup xmit queue for VI traffic\n");
 		goto err;
 	}
-	if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) {
+	if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_VO)) {
 		ath_err(common, "Unable to setup xmit queue for VO traffic\n");
 		goto err;
 	}
@@ -694,6 +694,20 @@ err_hw:
 	return ret;
 }
 
+static const struct ieee80211_iface_limit if_limits[] = {
+	{ .max = 2,	.types = BIT(NL80211_IFTYPE_STATION) |
+				 BIT(NL80211_IFTYPE_P2P_CLIENT) },
+	{ .max = 2,	.types = BIT(NL80211_IFTYPE_AP) |
+				 BIT(NL80211_IFTYPE_P2P_GO) },
+};
+
+static const struct ieee80211_iface_combination if_comb = {
+	.limits = if_limits,
+	.n_limits = ARRAY_SIZE(if_limits),
+	.max_interfaces = 2,
+	.num_different_channels = 1,
+};
+
 static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
 			       struct ieee80211_hw *hw)
 {
@@ -716,6 +730,9 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
 		BIT(NL80211_IFTYPE_P2P_GO) |
 		BIT(NL80211_IFTYPE_P2P_CLIENT);
 
+	hw->wiphy->iface_combinations = &if_comb;
+	hw->wiphy->n_iface_combinations = 1;
+
 	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
 	hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index ca78e33..9c07a8f 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -127,8 +127,9 @@ static void ath9k_htc_vif_reconfig(struct ath9k_htc_priv *priv)
 	priv->rearm_ani = false;
 	priv->reconfig_beacon = false;
 
-	ieee80211_iterate_active_interfaces_atomic(priv->hw,
-						   ath9k_htc_vif_iter, priv);
+	ieee80211_iterate_active_interfaces_atomic(
+		priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+		ath9k_htc_vif_iter, priv);
 	if (priv->rearm_ani)
 		ath9k_htc_start_ani(priv);
 
@@ -165,8 +166,9 @@ static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
 		ath9k_htc_bssid_iter(&iter_data, vif->addr, vif);
 
 	/* Get list of all active MAC addresses */
-	ieee80211_iterate_active_interfaces_atomic(priv->hw, ath9k_htc_bssid_iter,
-						   &iter_data);
+	ieee80211_iterate_active_interfaces_atomic(
+		priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+		ath9k_htc_bssid_iter, &iter_data);
 
 	memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
 	ath_hw_setbssidmask(common);
@@ -1036,26 +1038,6 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
 
 	mutex_lock(&priv->mutex);
 
-	if (priv->nvifs >= ATH9K_HTC_MAX_VIF) {
-		mutex_unlock(&priv->mutex);
-		return -ENOBUFS;
-	}
-
-	if (priv->num_ibss_vif ||
-	    (priv->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
-		ath_err(common, "IBSS coexistence with other modes is not allowed\n");
-		mutex_unlock(&priv->mutex);
-		return -ENOBUFS;
-	}
-
-	if (((vif->type == NL80211_IFTYPE_AP) ||
-	     (vif->type == NL80211_IFTYPE_ADHOC)) &&
-	    ((priv->num_ap_vif + priv->num_ibss_vif) >= ATH9K_HTC_MAX_BCN_VIF)) {
-		ath_err(common, "Max. number of beaconing interfaces reached\n");
-		mutex_unlock(&priv->mutex);
-		return -ENOBUFS;
-	}
-
 	ath9k_htc_ps_wakeup(priv);
 	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
 	memcpy(&hvif.myaddr, vif->addr, ETH_ALEN);
@@ -1164,8 +1146,9 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
 	 */
 	if ((vif->type == NL80211_IFTYPE_AP) && (priv->num_ap_vif == 0)) {
 		priv->rearm_ani = false;
-		ieee80211_iterate_active_interfaces_atomic(priv->hw,
-						   ath9k_htc_vif_iter, priv);
+		ieee80211_iterate_active_interfaces_atomic(
+			priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+			ath9k_htc_vif_iter, priv);
 		if (!priv->rearm_ani)
 			ath9k_htc_stop_ani(priv);
 	}
@@ -1366,7 +1349,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
 	struct ath9k_tx_queue_info qi;
 	int ret = 0, qnum;
 
-	if (queue >= WME_NUM_AC)
+	if (queue >= IEEE80211_NUM_ACS)
 		return 0;
 
 	mutex_lock(&priv->mutex);
@@ -1393,7 +1376,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
 	}
 
 	if ((priv->ah->opmode == NL80211_IFTYPE_ADHOC) &&
-	    (qnum == priv->hwq_map[WME_AC_BE]))
+	    (qnum == priv->hwq_map[IEEE80211_AC_BE]))
 		    ath9k_htc_beaconq_config(priv);
 out:
 	ath9k_htc_ps_restore(priv);
@@ -1486,8 +1469,9 @@ static void ath9k_htc_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 static void ath9k_htc_choose_set_bssid(struct ath9k_htc_priv *priv)
 {
 	if (priv->num_sta_assoc_vif == 1) {
-		ieee80211_iterate_active_interfaces_atomic(priv->hw,
-							   ath9k_htc_bss_iter, priv);
+		ieee80211_iterate_active_interfaces_atomic(
+			priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+			ath9k_htc_bss_iter, priv);
 		ath9k_htc_set_bssid(priv);
 	}
 }
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 06cdcb7..28cd50e 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -21,10 +21,10 @@
 /******/
 
 static const int subtype_txq_to_hwq[] = {
-	[WME_AC_BE] = ATH_TXQ_AC_BE,
-	[WME_AC_BK] = ATH_TXQ_AC_BK,
-	[WME_AC_VI] = ATH_TXQ_AC_VI,
-	[WME_AC_VO] = ATH_TXQ_AC_VO,
+	[IEEE80211_AC_BE] = ATH_TXQ_AC_BE,
+	[IEEE80211_AC_BK] = ATH_TXQ_AC_BK,
+	[IEEE80211_AC_VI] = ATH_TXQ_AC_VI,
+	[IEEE80211_AC_VO] = ATH_TXQ_AC_VO,
 };
 
 #define ATH9K_HTC_INIT_TXQ(subtype) do {			\
@@ -41,15 +41,15 @@ int get_hw_qnum(u16 queue, int *hwq_map)
 {
 	switch (queue) {
 	case 0:
-		return hwq_map[WME_AC_VO];
+		return hwq_map[IEEE80211_AC_VO];
 	case 1:
-		return hwq_map[WME_AC_VI];
+		return hwq_map[IEEE80211_AC_VI];
 	case 2:
-		return hwq_map[WME_AC_BE];
+		return hwq_map[IEEE80211_AC_BE];
 	case 3:
-		return hwq_map[WME_AC_BK];
+		return hwq_map[IEEE80211_AC_BK];
 	default:
-		return hwq_map[WME_AC_BE];
+		return hwq_map[IEEE80211_AC_BE];
 	}
 }
 
@@ -106,20 +106,20 @@ static inline enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv,
 
 	switch (qnum) {
 	case 0:
-		TX_QSTAT_INC(WME_AC_VO);
+		TX_QSTAT_INC(IEEE80211_AC_VO);
 		epid = priv->data_vo_ep;
 		break;
 	case 1:
-		TX_QSTAT_INC(WME_AC_VI);
+		TX_QSTAT_INC(IEEE80211_AC_VI);
 		epid = priv->data_vi_ep;
 		break;
 	case 2:
-		TX_QSTAT_INC(WME_AC_BE);
+		TX_QSTAT_INC(IEEE80211_AC_BE);
 		epid = priv->data_be_ep;
 		break;
 	case 3:
 	default:
-		TX_QSTAT_INC(WME_AC_BK);
+		TX_QSTAT_INC(IEEE80211_AC_BK);
 		epid = priv->data_bk_ep;
 		break;
 	}
@@ -1082,7 +1082,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
 	rx_status->freq = hw->conf.channel->center_freq;
 	rx_status->signal =  rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR;
 	rx_status->antenna = rxbuf->rxstatus.rs_antenna;
-	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+	rx_status->flag |= RX_FLAG_MACTIME_START;
 
 	return true;
 
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 1829b44..e06bcec 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2153,9 +2153,6 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah)
 		    AR_RTC_FORCE_WAKE_EN);
 	udelay(50);
 
-	if (ath9k_hw_mci_is_enabled(ah))
-		ar9003_mci_set_power_awake(ah);
-
 	for (i = POWER_UP_TIME / 50; i > 0; i--) {
 		val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
 		if (val == AR_RTC_STATUS_ON)
@@ -2171,6 +2168,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah)
 		return false;
 	}
 
+	if (ath9k_hw_mci_is_enabled(ah))
+		ar9003_mci_set_power_awake(ah);
+
 	REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
 
 	return true;
@@ -2561,11 +2561,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 			pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB;
 	}
 
-	if (AR_SREV_9485_10(ah)) {
-		pCap->pcie_lcr_extsync_en = true;
-		pCap->pcie_lcr_offset = 0x80;
-	}
-
 	if (ath9k_hw_dfs_tested(ah))
 		pCap->hw_caps |= ATH9K_HW_CAP_DFS;
 
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index dbc1b7a..3636dab 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -273,8 +273,6 @@ struct ath9k_hw_capabilities {
 	u8 rx_status_len;
 	u8 tx_desc_len;
 	u8 txs_len;
-	u16 pcie_lcr_offset;
-	bool pcie_lcr_extsync_en;
 };
 
 struct ath9k_ops_config {
@@ -401,6 +399,7 @@ enum ath9k_int {
 struct ath9k_hw_cal_data {
 	u16 channel;
 	u32 channelFlags;
+	u32 chanmode;
 	int32_t CalValid;
 	int8_t iCoff;
 	int8_t qCoff;
@@ -834,6 +833,7 @@ struct ath_hw {
 	int coarse_low[5];
 	int firpwr[5];
 	enum ath9k_ani_cmd ani_function;
+	u32 ani_skip_count;
 
 #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
 	struct ath_btcoex_hw btcoex_hw;
@@ -875,7 +875,6 @@ struct ath_hw {
 	struct ar5416IniArray iniModesTxGain;
 	struct ar5416IniArray iniCckfirNormal;
 	struct ar5416IniArray iniCckfirJapan2484;
-	struct ar5416IniArray ini_japan2484;
 	struct ar5416IniArray iniModes_9271_ANI_reg;
 	struct ar5416IniArray ini_radio_post_sys2ant;
 
@@ -928,7 +927,6 @@ struct ath_bus_ops {
 	void (*read_cachesize)(struct ath_common *common, int *csz);
 	bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
 	void (*bt_coex_prep)(struct ath_common *common);
-	void (*extn_synch_en)(struct ath_common *common);
 	void (*aspm_init)(struct ath_common *common);
 };
 
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index fad3ccd..80cae53 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -435,7 +435,7 @@ static int ath9k_init_queues(struct ath_softc *sc)
 	sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
 	ath_cabq_update(sc);
 
-	for (i = 0; i < WME_NUM_AC; i++) {
+	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
 		sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
 		sc->tx.txq_map[i]->mac80211_qnum = i;
 		sc->tx.txq_max_pending[i] = ATH_MAX_QDEPTH;
@@ -563,10 +563,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
 	spin_lock_init(&sc->sc_serial_rw);
 	spin_lock_init(&sc->sc_pm_lock);
 	mutex_init(&sc->mutex);
-#ifdef CONFIG_ATH9K_DEBUGFS
-	spin_lock_init(&sc->nodes_lock);
-	INIT_LIST_HEAD(&sc->nodes);
-#endif
 #ifdef CONFIG_ATH9K_MAC_DEBUG
 	spin_lock_init(&sc->debug.samp_lock);
 #endif
@@ -687,6 +683,7 @@ static const struct ieee80211_iface_combination if_comb = {
 	.n_limits = ARRAY_SIZE(if_limits),
 	.max_interfaces = 2048,
 	.num_different_channels = 1,
+	.beacon_int_infra_match = true,
 };
 
 void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index 7b88b9c..fc6b075 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -27,9 +27,6 @@ void ath_tx_complete_poll_work(struct work_struct *work)
 	struct ath_txq *txq;
 	int i;
 	bool needreset = false;
-#ifdef CONFIG_ATH9K_DEBUGFS
-	sc->tx_complete_poll_work_seen++;
-#endif
 
 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
 		if (ATH_TXQ_SETUP(sc, i)) {
@@ -211,7 +208,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
 	int time_left;
 
 	memset(&txctl, 0, sizeof(txctl));
-	txctl.txq = sc->tx.txq_map[WME_AC_BE];
+	txctl.txq = sc->tx.txq_map[IEEE80211_AC_BE];
 
 	memset(tx_info, 0, sizeof(*tx_info));
 	tx_info->band = hw->conf.channel->band;
@@ -350,8 +347,18 @@ void ath_ani_calibrate(unsigned long data)
 		ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
 
 	/* Only calibrate if awake */
-	if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE)
+	if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) {
+		if (++ah->ani_skip_count >= ATH_ANI_MAX_SKIP_COUNT) {
+			spin_lock_irqsave(&sc->sc_pm_lock, flags);
+			sc->ps_flags |= PS_WAIT_FOR_ANI;
+			spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+		}
 		goto set_timer;
+	}
+	ah->ani_skip_count = 0;
+	spin_lock_irqsave(&sc->sc_pm_lock, flags);
+	sc->ps_flags &= ~PS_WAIT_FOR_ANI;
+	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 
 	ath9k_ps_wakeup(sc);
 
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index dd45edf..0653dbc 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -131,7 +131,8 @@ void ath9k_ps_restore(struct ath_softc *sc)
 		   !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
 				     PS_WAIT_FOR_CAB |
 				     PS_WAIT_FOR_PSPOLL_DATA |
-				     PS_WAIT_FOR_TX_ACK))) {
+				     PS_WAIT_FOR_TX_ACK |
+				     PS_WAIT_FOR_ANI))) {
 		mode = ATH9K_PM_NETWORK_SLEEP;
 		if (ath9k_hw_btcoex_is_enabled(sc->sc_ah))
 			ath9k_btcoex_stop_gen_timer(sc);
@@ -292,6 +293,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
 		goto out;
 	}
 
+	if (ath9k_hw_mci_is_enabled(sc->sc_ah) &&
+	    (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
+		ath9k_mci_set_txpower(sc, true, false);
+
 	if (!ath_complete_reset(sc, true))
 		r = -EIO;
 
@@ -326,11 +331,6 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
 	u8 density;
 	an = (struct ath_node *)sta->drv_priv;
 
-#ifdef CONFIG_ATH9K_DEBUGFS
-	spin_lock(&sc->nodes_lock);
-	list_add(&an->list, &sc->nodes);
-	spin_unlock(&sc->nodes_lock);
-#endif
 	an->sta = sta;
 	an->vif = vif;
 
@@ -347,13 +347,6 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
 {
 	struct ath_node *an = (struct ath_node *)sta->drv_priv;
 
-#ifdef CONFIG_ATH9K_DEBUGFS
-	spin_lock(&sc->nodes_lock);
-	list_del(&an->list);
-	spin_unlock(&sc->nodes_lock);
-	an->sta = NULL;
-#endif
-
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
 		ath_tx_node_cleanup(sc, an);
 }
@@ -489,17 +482,6 @@ irqreturn_t ath_isr(int irq, void *dev)
 	if (status & SCHED_INTR)
 		sched = true;
 
-#ifdef CONFIG_PM_SLEEP
-	if (status & ATH9K_INT_BMISS) {
-		if (atomic_read(&sc->wow_sleep_proc_intr) == 0) {
-			ath_dbg(common, ANY, "during WoW we got a BMISS\n");
-			atomic_inc(&sc->wow_got_bmiss_intr);
-			atomic_dec(&sc->wow_sleep_proc_intr);
-		}
-	ath_dbg(common, INTERRUPT, "beacon miss interrupt\n");
-	}
-#endif
-
 	/*
 	 * If a FATAL or RXORN interrupt is received, we have to reset the
 	 * chip immediately.
@@ -518,7 +500,15 @@ irqreturn_t ath_isr(int irq, void *dev)
 
 		goto chip_reset;
 	}
-
+#ifdef CONFIG_PM_SLEEP
+	if (status & ATH9K_INT_BMISS) {
+		if (atomic_read(&sc->wow_sleep_proc_intr) == 0) {
+			ath_dbg(common, ANY, "during WoW we got a BMISS\n");
+			atomic_inc(&sc->wow_got_bmiss_intr);
+			atomic_dec(&sc->wow_sleep_proc_intr);
+		}
+	}
+#endif
 	if (status & ATH9K_INT_SWBA)
 		tasklet_schedule(&sc->bcon_tasklet);
 
@@ -681,9 +671,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
 
 	spin_unlock_bh(&sc->sc_pcu_lock);
 
-	if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en)
-		common->bus_ops->extn_synch_en(common);
-
 	mutex_unlock(&sc->mutex);
 
 	ath9k_ps_restore(sc);
@@ -919,8 +906,9 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
 		ath9k_vif_iter(iter_data, vif->addr, vif);
 
 	/* Get list of all active MAC addresses */
-	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter,
-						   iter_data);
+	ieee80211_iterate_active_interfaces_atomic(
+		sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+		ath9k_vif_iter, iter_data);
 }
 
 /* Called with sc->mutex held. */
@@ -970,8 +958,9 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
 	if (ah->opmode == NL80211_IFTYPE_STATION &&
 	    old_opmode == NL80211_IFTYPE_AP &&
 	    test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
-		ieee80211_iterate_active_interfaces_atomic(sc->hw,
-						   ath9k_sta_vif_iter, sc);
+		ieee80211_iterate_active_interfaces_atomic(
+			sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+			ath9k_sta_vif_iter, sc);
 	}
 }
 
@@ -1324,7 +1313,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw,
 	struct ath9k_tx_queue_info qi;
 	int ret = 0;
 
-	if (queue >= WME_NUM_AC)
+	if (queue >= IEEE80211_NUM_ACS)
 		return 0;
 
 	txq = sc->tx.txq_map[queue];
@@ -1449,6 +1438,9 @@ static void ath9k_set_assoc_state(struct ath_softc *sc,
 	sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
 	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 
+	if (ath9k_hw_mci_is_enabled(sc->sc_ah))
+		ath9k_mci_update_wlan_channels(sc, false);
+
 	ath_dbg(common, CONFIG,
 		"Primary Station interface: %pM, BSSID: %pM\n",
 		vif->addr, common->curbssid);
@@ -1497,14 +1489,17 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
 				clear_bit(SC_OP_BEACONS, &sc->sc_flags);
 		}
 
-		ieee80211_iterate_active_interfaces_atomic(sc->hw,
-						   ath9k_bss_assoc_iter, sc);
+		ieee80211_iterate_active_interfaces_atomic(
+			sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+			ath9k_bss_assoc_iter, sc);
 
 		if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags) &&
 		    ah->opmode == NL80211_IFTYPE_STATION) {
 			memset(common->curbssid, 0, ETH_ALEN);
 			common->curaid = 0;
 			ath9k_hw_write_associd(sc->sc_ah);
+			if (ath9k_hw_mci_is_enabled(sc->sc_ah))
+				ath9k_mci_update_wlan_channels(sc, true);
 		}
 	}
 
@@ -1946,13 +1941,12 @@ static int ath9k_get_et_sset_count(struct ieee80211_hw *hw,
 	return 0;
 }
 
-#define PR_QNUM(_n) (sc->tx.txq_map[_n]->axq_qnum)
 #define AWDATA(elem)							\
 	do {								\
-		data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].elem; \
-		data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].elem; \
-		data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].elem; \
-		data[i++] = sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].elem; \
+		data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].elem; \
+		data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].elem; \
+		data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].elem; \
+		data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].elem; \
 	} while (0)
 
 #define AWDATA_RX(elem)						\
@@ -1967,14 +1961,14 @@ static void ath9k_get_et_stats(struct ieee80211_hw *hw,
 	struct ath_softc *sc = hw->priv;
 	int i = 0;
 
-	data[i++] = (sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].tx_pkts_all +
-		     sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].tx_pkts_all +
-		     sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].tx_pkts_all +
-		     sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].tx_pkts_all);
-	data[i++] = (sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].tx_bytes_all +
-		     sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].tx_bytes_all +
-		     sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].tx_bytes_all +
-		     sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].tx_bytes_all);
+	data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_pkts_all +
+		     sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_pkts_all +
+		     sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_pkts_all +
+		     sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_pkts_all);
+	data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_bytes_all +
+		     sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_bytes_all +
+		     sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_bytes_all +
+		     sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_bytes_all);
 	AWDATA_RX(rx_pkts_all);
 	AWDATA_RX(rx_bytes_all);
 
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c
index ec2d7c8..706378e 100644
--- a/drivers/net/wireless/ath/ath9k/mci.c
+++ b/drivers/net/wireless/ath/ath9k/mci.c
@@ -43,6 +43,7 @@ static bool ath_mci_add_profile(struct ath_common *common,
 				struct ath_mci_profile_info *info)
 {
 	struct ath_mci_profile_info *entry;
+	u8 voice_priority[] = { 110, 110, 110, 112, 110, 110, 114, 116, 118 };
 
 	if ((mci->num_sco == ATH_MCI_MAX_SCO_PROFILE) &&
 	    (info->type == MCI_GPM_COEX_PROFILE_VOICE))
@@ -59,6 +60,12 @@ static bool ath_mci_add_profile(struct ath_common *common,
 	memcpy(entry, info, 10);
 	INC_PROF(mci, info);
 	list_add_tail(&entry->list, &mci->info);
+	if (info->type == MCI_GPM_COEX_PROFILE_VOICE) {
+		if (info->voice_type < sizeof(voice_priority))
+			mci->voice_priority = voice_priority[info->voice_type];
+		else
+			mci->voice_priority = 110;
+	}
 
 	return true;
 }
@@ -150,7 +157,7 @@ static void ath_mci_update_scheme(struct ath_softc *sc)
 			 * For single PAN/FTP profile, allocate 35% for BT
 			 * to improve WLAN throughput.
 			 */
-			btcoex->duty_cycle = 35;
+			btcoex->duty_cycle = AR_SREV_9565(sc->sc_ah) ? 40 : 35;
 			btcoex->btcoex_period = 53;
 			ath_dbg(common, MCI,
 				"Single PAN/FTP bt period %d ms dutycycle %d\n",
@@ -200,23 +207,6 @@ skip_tuning:
 	ath9k_btcoex_timer_resume(sc);
 }
 
-static void ath_mci_wait_btcal_done(struct ath_softc *sc)
-{
-	struct ath_hw *ah = sc->sc_ah;
-
-	/* Stop tx & rx */
-	ieee80211_stop_queues(sc->hw);
-	ath_stoprecv(sc);
-	ath_drain_all_txq(sc, false);
-
-	/* Wait for cal done */
-	ar9003_mci_start_reset(ah, ah->curchan);
-
-	/* Resume tx & rx */
-	ath_startrecv(sc);
-	ieee80211_wake_queues(sc->hw);
-}
-
 static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
 {
 	struct ath_hw *ah = sc->sc_ah;
@@ -228,7 +218,7 @@ static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
 	case MCI_GPM_BT_CAL_REQ:
 		if (mci_hw->bt_state == MCI_BT_AWAKE) {
 			mci_hw->bt_state = MCI_BT_CAL_START;
-			ath_mci_wait_btcal_done(sc);
+			ath9k_queue_reset(sc, RESET_TYPE_MCI);
 		}
 		ath_dbg(common, MCI, "MCI State : %d\n", mci_hw->bt_state);
 		break;
@@ -250,6 +240,57 @@ static void ath9k_mci_work(struct work_struct *work)
 	ath_mci_update_scheme(sc);
 }
 
+static void ath_mci_update_stomp_txprio(u8 cur_txprio, u8 *stomp_prio)
+{
+	if (cur_txprio < stomp_prio[ATH_BTCOEX_STOMP_NONE])
+		stomp_prio[ATH_BTCOEX_STOMP_NONE] = cur_txprio;
+
+	if (cur_txprio > stomp_prio[ATH_BTCOEX_STOMP_ALL])
+		stomp_prio[ATH_BTCOEX_STOMP_ALL] = cur_txprio;
+
+	if ((cur_txprio > ATH_MCI_HI_PRIO) &&
+	    (cur_txprio < stomp_prio[ATH_BTCOEX_STOMP_LOW]))
+		stomp_prio[ATH_BTCOEX_STOMP_LOW] = cur_txprio;
+}
+
+static void ath_mci_set_concur_txprio(struct ath_softc *sc)
+{
+	struct ath_btcoex *btcoex = &sc->btcoex;
+	struct ath_mci_profile *mci = &btcoex->mci;
+	u8 stomp_txprio[] = { 0, 0, 0, 0 }; /* all, low, none, low_ftp */
+
+	if (mci->num_mgmt) {
+		stomp_txprio[ATH_BTCOEX_STOMP_ALL] = ATH_MCI_INQUIRY_PRIO;
+		if (!mci->num_pan && !mci->num_other_acl)
+			stomp_txprio[ATH_BTCOEX_STOMP_NONE] =
+				ATH_MCI_INQUIRY_PRIO;
+	} else {
+		u8 prof_prio[] = { 50, 90, 94, 52 };/* RFCOMM, A2DP, HID, PAN */
+
+		stomp_txprio[ATH_BTCOEX_STOMP_LOW] =
+		stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0xff;
+
+		if (mci->num_sco)
+			ath_mci_update_stomp_txprio(mci->voice_priority,
+						    stomp_txprio);
+		if (mci->num_other_acl)
+			ath_mci_update_stomp_txprio(prof_prio[0], stomp_txprio);
+		if (mci->num_a2dp)
+			ath_mci_update_stomp_txprio(prof_prio[1], stomp_txprio);
+		if (mci->num_hid)
+			ath_mci_update_stomp_txprio(prof_prio[2], stomp_txprio);
+		if (mci->num_pan)
+			ath_mci_update_stomp_txprio(prof_prio[3], stomp_txprio);
+
+		if (stomp_txprio[ATH_BTCOEX_STOMP_NONE] == 0xff)
+			stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0;
+
+		if (stomp_txprio[ATH_BTCOEX_STOMP_LOW] == 0xff)
+			stomp_txprio[ATH_BTCOEX_STOMP_LOW] = 0;
+	}
+	ath9k_hw_btcoex_set_concur_txprio(sc->sc_ah, stomp_txprio);
+}
+
 static u8 ath_mci_process_profile(struct ath_softc *sc,
 				  struct ath_mci_profile_info *info)
 {
@@ -281,6 +322,7 @@ static u8 ath_mci_process_profile(struct ath_softc *sc,
 	} else
 		ath_mci_del_profile(common, mci, entry);
 
+	ath_mci_set_concur_txprio(sc);
 	return 1;
 }
 
@@ -314,6 +356,7 @@ static u8 ath_mci_process_status(struct ath_softc *sc,
 			mci->num_mgmt++;
 	} while (++i < ATH_MCI_MAX_PROFILE);
 
+	ath_mci_set_concur_txprio(sc);
 	if (old_num_mgmt != mci->num_mgmt)
 		return 1;
 
@@ -518,6 +561,8 @@ void ath_mci_intr(struct ath_softc *sc)
 		mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_GPM;
 
 		while (more_data == MCI_GPM_MORE) {
+			if (test_bit(SC_OP_HW_RESET, &sc->sc_flags))
+				return;
 
 			pgpm = mci->gpm_buf.bf_addr;
 			offset = ar9003_mci_get_next_gpm_offset(ah, false,
@@ -600,3 +645,130 @@ void ath_mci_enable(struct ath_softc *sc)
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
 		sc->sc_ah->imask |= ATH9K_INT_MCI;
 }
+
+void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+	struct ath9k_channel *chan = ah->curchan;
+	u32 channelmap[] = {0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff};
+	int i;
+	s16 chan_start, chan_end;
+	u16 wlan_chan;
+
+	if (!chan || !IS_CHAN_2GHZ(chan))
+		return;
+
+	if (allow_all)
+		goto send_wlan_chan;
+
+	wlan_chan = chan->channel - 2402;
+
+	chan_start = wlan_chan - 10;
+	chan_end = wlan_chan + 10;
+
+	if (chan->chanmode == CHANNEL_G_HT40PLUS)
+		chan_end += 20;
+	else if (chan->chanmode == CHANNEL_G_HT40MINUS)
+		chan_start -= 20;
+
+	/* adjust side band */
+	chan_start -= 7;
+	chan_end += 7;
+
+	if (chan_start <= 0)
+		chan_start = 0;
+	if (chan_end >= ATH_MCI_NUM_BT_CHANNELS)
+		chan_end = ATH_MCI_NUM_BT_CHANNELS - 1;
+
+	ath_dbg(ath9k_hw_common(ah), MCI,
+		"WLAN current channel %d mask BT channel %d - %d\n",
+		wlan_chan, chan_start, chan_end);
+
+	for (i = chan_start; i < chan_end; i++)
+		MCI_GPM_CLR_CHANNEL_BIT(&channelmap, i);
+
+send_wlan_chan:
+	/* update and send wlan channels info to BT */
+	for (i = 0; i < 4; i++)
+		mci->wlan_channels[i] = channelmap[i];
+	ar9003_mci_send_wlan_channels(ah);
+	ar9003_mci_state(ah, MCI_STATE_SEND_VERSION_QUERY);
+}
+
+void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel,
+			   bool concur_tx)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath9k_hw_mci *mci_hw = &sc->sc_ah->btcoex_hw.mci;
+	bool old_concur_tx = mci_hw->concur_tx;
+
+	if (!(mci_hw->config & ATH_MCI_CONFIG_CONCUR_TX)) {
+		mci_hw->concur_tx = false;
+		return;
+	}
+
+	if (!IS_CHAN_2GHZ(ah->curchan))
+		return;
+
+	if (setchannel) {
+		struct ath9k_hw_cal_data *caldata = &sc->caldata;
+		if ((caldata->chanmode == CHANNEL_G_HT40PLUS) &&
+		    (ah->curchan->channel > caldata->channel) &&
+		    (ah->curchan->channel <= caldata->channel + 20))
+			return;
+		if ((caldata->chanmode == CHANNEL_G_HT40MINUS) &&
+		    (ah->curchan->channel < caldata->channel) &&
+		    (ah->curchan->channel >= caldata->channel - 20))
+			return;
+		mci_hw->concur_tx = false;
+	} else
+		mci_hw->concur_tx = concur_tx;
+
+	if (old_concur_tx != mci_hw->concur_tx)
+		ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
+}
+
+static void ath9k_mci_stomp_audio(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_btcoex *btcoex = &sc->btcoex;
+	struct ath_mci_profile *mci = &btcoex->mci;
+
+	if (!mci->num_sco && !mci->num_a2dp)
+		return;
+
+	if (ah->stats.avgbrssi > 25) {
+		btcoex->stomp_audio = 0;
+		return;
+	}
+
+	btcoex->stomp_audio++;
+}
+void ath9k_mci_update_rssi(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_btcoex *btcoex = &sc->btcoex;
+	struct ath9k_hw_mci *mci_hw = &sc->sc_ah->btcoex_hw.mci;
+
+	ath9k_mci_stomp_audio(sc);
+
+	if (!(mci_hw->config & ATH_MCI_CONFIG_CONCUR_TX))
+		return;
+
+	if (ah->stats.avgbrssi >= 40) {
+		if (btcoex->rssi_count < 0)
+			btcoex->rssi_count = 0;
+		if (++btcoex->rssi_count >= ATH_MCI_CONCUR_TX_SWITCH) {
+			btcoex->rssi_count = 0;
+			ath9k_mci_set_txpower(sc, false, true);
+		}
+	} else {
+		if (btcoex->rssi_count > 0)
+			btcoex->rssi_count = 0;
+		if (--btcoex->rssi_count <= -ATH_MCI_CONCUR_TX_SWITCH) {
+			btcoex->rssi_count = 0;
+			ath9k_mci_set_txpower(sc, false, false);
+		}
+	}
+}
diff --git a/drivers/net/wireless/ath/ath9k/mci.h b/drivers/net/wireless/ath/ath9k/mci.h
index fc14eea..0695883 100644
--- a/drivers/net/wireless/ath/ath9k/mci.h
+++ b/drivers/net/wireless/ath/ath9k/mci.h
@@ -32,6 +32,27 @@
 #define ATH_MCI_MAX_PROFILE		(ATH_MCI_MAX_ACL_PROFILE +\
 					 ATH_MCI_MAX_SCO_PROFILE)
 
+#define ATH_MCI_INQUIRY_PRIO         62
+#define ATH_MCI_HI_PRIO              60
+#define ATH_MCI_NUM_BT_CHANNELS      79
+#define ATH_MCI_CONCUR_TX_SWITCH      5
+
+#define MCI_GPM_SET_CHANNEL_BIT(_p_gpm, _bt_chan)			  \
+	do {								  \
+		if (_bt_chan < ATH_MCI_NUM_BT_CHANNELS) {		  \
+			*(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_CHANNEL_MAP + \
+				(_bt_chan / 8)) |= (1 << (_bt_chan & 7)); \
+		}							  \
+	} while (0)
+
+#define MCI_GPM_CLR_CHANNEL_BIT(_p_gpm, _bt_chan)			  \
+	do {								  \
+		if (_bt_chan < ATH_MCI_NUM_BT_CHANNELS) {		  \
+			*(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_CHANNEL_MAP + \
+				(_bt_chan / 8)) &= ~(1 << (_bt_chan & 7));\
+		}							  \
+	} while (0)
+
 #define INC_PROF(_mci, _info) do {		 \
 		switch (_info->type) {		 \
 		case MCI_GPM_COEX_PROFILE_RFCOMM:\
@@ -49,6 +70,7 @@
 			_mci->num_pan++;	 \
 			break;			 \
 		case MCI_GPM_COEX_PROFILE_VOICE: \
+		case MCI_GPM_COEX_PROFILE_A2DPVO:\
 			_mci->num_sco++;	 \
 			break;			 \
 		default:			 \
@@ -73,6 +95,7 @@
 			_mci->num_pan--;	 \
 			break;			 \
 		case MCI_GPM_COEX_PROFILE_VOICE: \
+		case MCI_GPM_COEX_PROFILE_A2DPVO:\
 			_mci->num_sco--;	 \
 			break;			 \
 		default:			 \
@@ -113,6 +136,7 @@ struct ath_mci_profile {
 	u8 num_pan;
 	u8 num_other_acl;
 	u8 num_bdr;
+	u8 voice_priority;
 };
 
 struct ath_mci_buf {
@@ -130,13 +154,25 @@ void ath_mci_flush_profile(struct ath_mci_profile *mci);
 int ath_mci_setup(struct ath_softc *sc);
 void ath_mci_cleanup(struct ath_softc *sc);
 void ath_mci_intr(struct ath_softc *sc);
+void ath9k_mci_update_rssi(struct ath_softc *sc);
 
 #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
 void ath_mci_enable(struct ath_softc *sc);
+void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all);
+void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel,
+			   bool concur_tx);
 #else
 static inline void ath_mci_enable(struct ath_softc *sc)
 {
 }
+static inline void ath9k_mci_update_wlan_channels(struct ath_softc *sc,
+						  bool allow_all)
+{
+}
+static inline void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel,
+					 bool concur_tx)
+{
+}
 #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
 
 #endif /* MCI_H*/
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index f088f4b..9553203 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -96,17 +96,6 @@ static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
 	return true;
 }
 
-static void ath_pci_extn_synch_enable(struct ath_common *common)
-{
-	struct ath_softc *sc = (struct ath_softc *) common->priv;
-	struct pci_dev *pdev = to_pci_dev(sc->dev);
-	u8 lnkctl;
-
-	pci_read_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, &lnkctl);
-	lnkctl |= PCI_EXP_LNKCTL_ES;
-	pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl);
-}
-
 /* Need to be called after we discover btcoex capabilities */
 static void ath_pci_aspm_init(struct ath_common *common)
 {
@@ -153,7 +142,6 @@ static const struct ath_bus_ops ath_pci_bus_ops = {
 	.ath_bus_type = ATH_PCI,
 	.read_cachesize = ath_pci_read_cachesize,
 	.eeprom_read = ath_pci_eeprom_read,
-	.extn_synch_en = ath_pci_extn_synch_enable,
 	.aspm_init = ath_pci_aspm_init,
 };
 
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 27ed80b..714558d 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -982,16 +982,6 @@ static void ath_rc_update_per(struct ath_softc *sc,
 	}
 }
 
-static void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
-				   int xretries, int retries, u8 per)
-{
-	struct ath_rc_stats *stats = &rc->rcstats[rix];
-
-	stats->xretries += xretries;
-	stats->retries += retries;
-	stats->per = per;
-}
-
 static void ath_rc_update_ht(struct ath_softc *sc,
 			     struct ath_rate_priv *ath_rc_priv,
 			     struct ieee80211_tx_info *tx_info,
@@ -1065,14 +1055,6 @@ static void ath_rc_update_ht(struct ath_softc *sc,
 
 }
 
-static void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
-{
-	struct ath_rc_stats *stats;
-
-	stats = &rc->rcstats[final_rate];
-	stats->success++;
-}
-
 static void ath_rc_tx_status(struct ath_softc *sc,
 			     struct ath_rate_priv *ath_rc_priv,
 			     struct sk_buff *skb)
@@ -1350,7 +1332,25 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
 	}
 }
 
-#ifdef CONFIG_ATH9K_DEBUGFS
+#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
+
+void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
+{
+	struct ath_rc_stats *stats;
+
+	stats = &rc->rcstats[final_rate];
+	stats->success++;
+}
+
+void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
+			    int xretries, int retries, u8 per)
+{
+	struct ath_rc_stats *stats = &rc->rcstats[rix];
+
+	stats->xretries += xretries;
+	stats->retries += retries;
+	stats->per = per;
+}
 
 static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
 				size_t count, loff_t *ppos)
@@ -1428,10 +1428,17 @@ static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta,
 				     struct dentry *dir)
 {
 	struct ath_rate_priv *rc = priv_sta;
-	debugfs_create_file("rc_stats", S_IRUGO, dir, rc, &fops_rcstat);
+	rc->debugfs_rcstats = debugfs_create_file("rc_stats", S_IRUGO,
+						  dir, rc, &fops_rcstat);
+}
+
+static void ath_rate_remove_sta_debugfs(void *priv, void *priv_sta)
+{
+	struct ath_rate_priv *rc = priv_sta;
+	debugfs_remove(rc->debugfs_rcstats);
 }
 
-#endif /* CONFIG_ATH9K_DEBUGFS */
+#endif /* CONFIG_MAC80211_DEBUGFS && CONFIG_ATH9K_DEBUGFS */
 
 static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
 {
@@ -1476,8 +1483,10 @@ static struct rate_control_ops ath_rate_ops = {
 	.free = ath_rate_free,
 	.alloc_sta = ath_rate_alloc_sta,
 	.free_sta = ath_rate_free_sta,
-#ifdef CONFIG_ATH9K_DEBUGFS
+
+#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
 	.add_sta_debugfs = ath_rate_add_sta_debugfs,
+	.remove_sta_debugfs = ath_rate_remove_sta_debugfs,
 #endif
 };
 
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
index 268e67d..267dbfc 100644
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ b/drivers/net/wireless/ath/ath9k/rc.h
@@ -211,10 +211,26 @@ struct ath_rate_priv {
 	struct ath_rateset neg_ht_rates;
 	const struct ath_rate_table *rate_table;
 
+#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
 	struct dentry *debugfs_rcstats;
 	struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
+#endif
 };
 
+#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS)
+void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate);
+void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
+			    int xretries, int retries, u8 per);
+#else
+static inline void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
+{
+}
+static inline void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
+					  int xretries, int retries, u8 per)
+{
+}
+#endif
+
 #ifdef CONFIG_ATH9K_RATE_CONTROL
 int ath_rate_control_register(void);
 void ath_rate_control_unregister(void);
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 83d16e7..6aafbb7 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -976,7 +976,7 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
 	rx_status->freq = hw->conf.channel->center_freq;
 	rx_status->signal = ah->noise + rx_stats->rs_rssi;
 	rx_status->antenna = rx_stats->rs_antenna;
-	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+	rx_status->flag |= RX_FLAG_MACTIME_START;
 	if (rx_stats->rs_moreaggr)
 		rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
 
@@ -1105,7 +1105,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 		else
 			rs.is_mybeacon = false;
 
-		sc->rx.num_pkts++;
+		if (ieee80211_is_data_present(hdr->frame_control) &&
+		    !ieee80211_is_qos_nullfunc(hdr->frame_control))
+			sc->rx.num_pkts++;
+
 		ath_debug_stat_rx(sc, &rs);
 
 		/*
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 4e6760f..ad3c82c 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -907,10 +907,6 @@
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
 	((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20))
 
-#define AR_SREV_9462_20_OR_LATER(_ah) \
-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
-	((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20))
-
 #define AR_SREV_9565(_ah) \
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565))
 
@@ -2315,6 +2311,8 @@ enum {
 #define AR_BTCOEX_MAX_TXPWR(_x)				(0x18c0 + ((_x) << 2))
 #define AR_BTCOEX_WL_LNA				0x1940
 #define AR_BTCOEX_RFGAIN_CTRL				0x1944
+#define AR_BTCOEX_WL_LNA_TIMEOUT			0x003FFFFF
+#define AR_BTCOEX_WL_LNA_TIMEOUT_S			0
 
 #define AR_BTCOEX_CTRL2					0x1948
 #define AR_BTCOEX_CTRL2_TXPWR_THRESH			0x0007F800
@@ -2360,4 +2358,11 @@ enum {
 #define AR_GLB_SWREG_DISCONT_MODE         0x2002c
 #define AR_GLB_SWREG_DISCONT_EN_BT_WLAN   0x3
 
+#define AR_MCI_MISC                    0x1a74
+#define AR_MCI_MISC_HW_FIX_EN          0x00000001
+#define AR_MCI_MISC_HW_FIX_EN_S        0
+#define AR_MCI_DBG_CNT_CTRL            0x1a78
+#define AR_MCI_DBG_CNT_CTRL_ENABLE     0x00000001
+#define AR_MCI_DBG_CNT_CTRL_ENABLE_S   0
+
 #endif
diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c
index a483d51..9f85630 100644
--- a/drivers/net/wireless/ath/ath9k/wow.c
+++ b/drivers/net/wireless/ath/ath9k/wow.c
@@ -118,7 +118,7 @@ static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah)
 		       (ap_mac_addr[1] << 8) | (ap_mac_addr[0]);
 	data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]);
 
-	if (AR_SREV_9462_20_OR_LATER(ah)) {
+	if (AR_SREV_9462_20(ah)) {
 		/* AR9462 2.0 has an extra descriptor word (time based
 		 * discard) compared to other chips */
 		REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0);
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 741918a..3413094 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1354,10 +1354,10 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath9k_tx_queue_info qi;
 	static const int subtype_txq_to_hwq[] = {
-		[WME_AC_BE] = ATH_TXQ_AC_BE,
-		[WME_AC_BK] = ATH_TXQ_AC_BK,
-		[WME_AC_VI] = ATH_TXQ_AC_VI,
-		[WME_AC_VO] = ATH_TXQ_AC_VO,
+		[IEEE80211_AC_BE] = ATH_TXQ_AC_BE,
+		[IEEE80211_AC_BK] = ATH_TXQ_AC_BK,
+		[IEEE80211_AC_VI] = ATH_TXQ_AC_VI,
+		[IEEE80211_AC_VO] = ATH_TXQ_AC_VO,
 	};
 	int axq_qnum, i;
 
@@ -2319,6 +2319,8 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
 
 		ath_txq_lock(sc, txq);
 
+		TX_STAT_INC(txq->axq_qnum, txprocdesc);
+
 		if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
 			ath_txq_unlock(sc, txq);
 			return;
@@ -2464,7 +2466,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
 	}
 
 	for (acno = 0, ac = &an->ac[acno];
-	     acno < WME_NUM_AC; acno++, ac++) {
+	     acno < IEEE80211_NUM_ACS; acno++, ac++) {
 		ac->sched    = false;
 		ac->txq = sc->tx.txq_map[acno];
 		INIT_LIST_HEAD(&ac->tid_q);
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c
index 24ac287..aaebecd 100644
--- a/drivers/net/wireless/ath/carl9170/fw.c
+++ b/drivers/net/wireless/ath/carl9170/fw.c
@@ -28,11 +28,6 @@
 #include "fwcmd.h"
 #include "version.h"
 
-#define MAKE_STR(symbol) #symbol
-#define TO_STR(symbol) MAKE_STR(symbol)
-#define CARL9170FW_API_VER_STR TO_STR(CARL9170FW_API_MAX_VER)
-MODULE_VERSION(CARL9170FW_API_VER_STR ":" CARL9170FW_VERSION_GIT);
-
 static const u8 otus_magic[4] = { OTUS_MAGIC };
 
 static const void *carl9170_fw_find_desc(struct ar9170 *ar, const u8 descid[4],
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c
index e3b1b6e..24d75ab 100644
--- a/drivers/net/wireless/ath/carl9170/mac.c
+++ b/drivers/net/wireless/ath/carl9170/mac.c
@@ -343,7 +343,24 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
 			break;
 		}
 	} else {
-		mac_addr = NULL;
+		/*
+		 * Enable monitor mode
+		 *
+		 * rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER;
+		 * sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC;
+		 *
+		 * When the hardware is in SNIFFER_PROMISC mode,
+		 * it generates spurious ACKs for every incoming
+		 * frame. This confuses every peer in the
+		 * vicinity and the network throughput will suffer
+		 * badly.
+		 *
+		 * Hence, the hardware will be put into station
+		 * mode and just the rx filters are disabled.
+		 */
+		cam_mode |= AR9170_MAC_CAM_STA;
+		rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST;
+		mac_addr = common->macaddr;
 		bssid = NULL;
 	}
 	rcu_read_unlock();
@@ -355,8 +372,6 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
 		enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
 
 	if (ar->sniffer_enabled) {
-		rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER;
-		sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC;
 		enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
 	}
 
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index a0b7230..6d22382 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -164,9 +164,6 @@ void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
 	struct carl9170_rsp *cmd = buf;
 	struct ieee80211_vif *vif;
 
-	if (carl9170_check_sequence(ar, cmd->hdr.seq))
-		return;
-
 	if ((cmd->hdr.cmd & CARL9170_RSP_FLAG) != CARL9170_RSP_FLAG) {
 		if (!(cmd->hdr.cmd & CARL9170_CMD_ASYNC_FLAG))
 			carl9170_cmd_callback(ar, len, buf);
@@ -663,6 +660,35 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms,
 	return false;
 }
 
+static int carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len,
+				struct ieee80211_rx_status *status)
+{
+	struct sk_buff *skb;
+
+	/* (driver) frame trap handler
+	 *
+	 * Because power-saving mode handing has to be implemented by
+	 * the driver/firmware. We have to check each incoming beacon
+	 * from the associated AP, if there's new data for us (either
+	 * broadcast/multicast or unicast) we have to react quickly.
+	 *
+	 * So, if you have you want to add additional frame trap
+	 * handlers, this would be the perfect place!
+	 */
+
+	carl9170_ps_beacon(ar, buf, len);
+
+	carl9170_ba_check(ar, buf, len);
+
+	skb = carl9170_rx_copy_data(buf, len);
+	if (!skb)
+		return -ENOMEM;
+
+	memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+	ieee80211_rx(ar->hw, skb);
+	return 0;
+}
+
 /*
  * If the frame alignment is right (or the kernel has
  * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
@@ -672,14 +698,12 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms,
  * mode, and we need to observe the proper ordering,
  * this is non-trivial.
  */
-
-static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
+static void carl9170_rx_untie_data(struct ar9170 *ar, u8 *buf, int len)
 {
 	struct ar9170_rx_head *head;
 	struct ar9170_rx_macstatus *mac;
 	struct ar9170_rx_phystatus *phy = NULL;
 	struct ieee80211_rx_status status;
-	struct sk_buff *skb;
 	int mpdu_len;
 	u8 mac_status;
 
@@ -791,18 +815,10 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
 	if (phy)
 		carl9170_rx_phy_status(ar, phy, &status);
 
-	carl9170_ps_beacon(ar, buf, mpdu_len);
-
-	carl9170_ba_check(ar, buf, mpdu_len);
-
-	skb = carl9170_rx_copy_data(buf, mpdu_len);
-	if (!skb)
+	if (carl9170_handle_mpdu(ar, buf, mpdu_len, &status))
 		goto drop;
 
-	memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
-	ieee80211_rx(ar->hw, skb);
 	return;
-
 drop:
 	ar->rx_dropped++;
 }
@@ -820,6 +836,9 @@ static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf,
 		if (unlikely(i > resplen))
 			break;
 
+		if (carl9170_check_sequence(ar, cmd->hdr.seq))
+			break;
+
 		carl9170_handle_command_response(ar, cmd, cmd->hdr.len + 4);
 	}
 
@@ -851,7 +870,7 @@ static void __carl9170_rx(struct ar9170 *ar, u8 *buf, unsigned int len)
 	if (i == 12)
 		carl9170_rx_untie_cmds(ar, buf, len);
 	else
-		carl9170_handle_mpdu(ar, buf, len);
+		carl9170_rx_untie_data(ar, buf, len);
 }
 
 static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len)
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
index 888152c..307bc0d 100644
--- a/drivers/net/wireless/ath/carl9170/usb.c
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -295,6 +295,13 @@ static void carl9170_usb_rx_irq_complete(struct urb *urb)
 		goto resubmit;
 	}
 
+	/*
+	 * While the carl9170 firmware does not use this EP, the
+	 * firmware loader in the EEPROM unfortunately does.
+	 * Therefore we need to be ready to handle out-of-band
+	 * responses and traps in case the firmware crashed and
+	 * the loader took over again.
+	 */
 	carl9170_handle_command_response(ar, urb->transfer_buffer,
 					 urb->actual_length);
 
diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c
index 19befb3..39e8a59 100644
--- a/drivers/net/wireless/ath/hw.c
+++ b/drivers/net/wireless/ath/hw.c
@@ -20,8 +20,8 @@
 #include "ath.h"
 #include "reg.h"
 
-#define REG_READ	(common->ops->read)
-#define REG_WRITE	(common->ops->write)
+#define REG_READ			(common->ops->read)
+#define REG_WRITE(_ah, _reg, _val)	(common->ops->write)(_ah, _val, _reg)
 
 /**
  * ath_hw_set_bssid_mask - filter out bssids we listen
@@ -119,8 +119,8 @@ void ath_hw_setbssidmask(struct ath_common *common)
 {
 	void *ah = common->ah;
 
-	REG_WRITE(ah, get_unaligned_le32(common->bssidmask), AR_BSSMSKL);
-	REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU);
+	REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(common->bssidmask));
+	REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(common->bssidmask + 4));
 }
 EXPORT_SYMBOL(ath_hw_setbssidmask);
 
@@ -139,7 +139,7 @@ void ath_hw_cycle_counters_update(struct ath_common *common)
 	void *ah = common->ah;
 
 	/* freeze */
-	REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC);
+	REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
 
 	/* read */
 	cycles = REG_READ(ah, AR_CCCNT);
@@ -148,13 +148,13 @@ void ath_hw_cycle_counters_update(struct ath_common *common)
 	tx = REG_READ(ah, AR_TFCNT);
 
 	/* clear */
-	REG_WRITE(ah, 0, AR_CCCNT);
-	REG_WRITE(ah, 0, AR_RFCNT);
-	REG_WRITE(ah, 0, AR_RCCNT);
-	REG_WRITE(ah, 0, AR_TFCNT);
+	REG_WRITE(ah, AR_CCCNT, 0);
+	REG_WRITE(ah, AR_RFCNT, 0);
+	REG_WRITE(ah, AR_RCCNT, 0);
+	REG_WRITE(ah, AR_TFCNT, 0);
 
 	/* unfreeze */
-	REG_WRITE(ah, 0, AR_MIBC);
+	REG_WRITE(ah, AR_MIBC, 0);
 
 	/* update all cycle counters here */
 	common->cc_ani.cycles += cycles;
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 4a4e98f..4374079 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -2963,7 +2963,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
 	ssid_el_p[1] = priv->SSID_size;
 	memcpy(ssid_el_p + 2, priv->SSID, priv->SSID_size);
 	ssid_el_p[2 + priv->SSID_size] = WLAN_EID_SUPP_RATES;
-	ssid_el_p[3 + priv->SSID_size] = 4; /* len of suported rates */
+	ssid_el_p[3 + priv->SSID_size] = 4; /* len of supported rates */
 	memcpy(ssid_el_p + 4 + priv->SSID_size, atmel_basic_rates, 4);
 
 	atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index c5a99c8..ddd6a4f 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -4652,7 +4652,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
 	switch (dev->dev->bus_type) {
 #ifdef CONFIG_B43_BCMA
 	case B43_BUS_BCMA:
-		bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci,
+		bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci[0],
 				      dev->dev->bdev, true);
 		break;
 #endif
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 136510e..8cb206a 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -796,7 +796,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
 		status.mactime += mactime;
 		if (low_mactime_now <= mactime)
 			status.mactime -= 0x10000;
-		status.flag |= RX_FLAG_MACTIME_MPDU;
+		status.flag |= RX_FLAG_MACTIME_START;
 	}
 
 	chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index b8ffea6..849a28c 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -557,7 +557,7 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
 		status.mactime += mactime;
 		if (low_mactime_now <= mactime)
 			status.mactime -= 0x10000;
-		status.flag |= RX_FLAG_MACTIME_MPDU;
+		status.flag |= RX_FLAG_MACTIME_START;
 	}
 
 	chanid = (chanstat & B43legacy_RX_CHAN_ID) >>
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index c9d811e..1d92d87 100644
--- a/drivers/net/wireless/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -55,13 +55,16 @@ config BRCMFMAC_USB
 	  IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
 	  use the driver for an USB wireless card.
 
-config BRCMISCAN
-	bool "Broadcom I-Scan (OBSOLETE)"
-	depends on BRCMFMAC
+config BRCM_TRACING
+	bool "Broadcom device tracing"
+	depends on BRCMSMAC || BRCMFMAC
 	---help---
-	  This option enables the I-Scan method. By default fullmac uses the
-	  new E-Scan method which uses less memory in firmware and gives no
-	  limitation on the number of scan results.
+	  If you say Y here, the Broadcom wireless drivers will register
+	  with ftrace to dump event information into the trace ringbuffer.
+	  Tracing can be enabled at runtime to aid in debugging wireless
+	  issues. This option adds a small amount of overhead when tracing
+	  is disabled. If unsure, say Y to allow developers to better help
+	  you when wireless problems occur.
 
 config BRCMDBG
 	bool "Broadcom driver debug functions"
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index 9d5170b..1a6661a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -24,6 +24,8 @@ ccflags-y += -D__CHECK_ENDIAN__
 obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
 brcmfmac-objs += \
 		wl_cfg80211.o \
+		fwil.o \
+		fweh.o \
 		dhd_cdc.o \
 		dhd_common.o \
 		dhd_linux.o
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 3b2c4c2..334ddab 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -42,7 +42,8 @@
 #ifdef CONFIG_BRCMFMAC_SDIO_OOB
 static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id)
 {
-	struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(dev_id);
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev_id);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
 
 	brcmf_dbg(INTR, "oob intr triggered\n");
 
@@ -71,7 +72,7 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
 	brcmf_dbg(ERROR, "requesting irq %d\n", sdiodev->irq);
 	ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler,
 			  sdiodev->irq_flags, "brcmf_oob_intr",
-			  &sdiodev->func[1]->card->dev);
+			  &sdiodev->func[1]->dev);
 	if (ret != 0)
 		return ret;
 	spin_lock_init(&sdiodev->irq_en_lock);
@@ -84,6 +85,8 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
 		return ret;
 	sdiodev->irq_wake = true;
 
+	sdio_claim_host(sdiodev->func[1]);
+
 	/* must configure SDIO_CCCR_IENx to enable irq */
 	data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
 	data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
@@ -95,6 +98,8 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
 		data |= SDIO_SEPINT_ACT_HI;
 	brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
 
+	sdio_release_host(sdiodev->func[1]);
+
 	return 0;
 }
 
@@ -102,14 +107,16 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
 {
 	brcmf_dbg(TRACE, "Entering\n");
 
+	sdio_claim_host(sdiodev->func[1]);
 	brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
 	brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
+	sdio_release_host(sdiodev->func[1]);
 
 	if (sdiodev->irq_wake) {
 		disable_irq_wake(sdiodev->irq);
 		sdiodev->irq_wake = false;
 	}
-	free_irq(sdiodev->irq, &sdiodev->func[1]->card->dev);
+	free_irq(sdiodev->irq, &sdiodev->func[1]->dev);
 	sdiodev->irq_en = false;
 
 	return 0;
@@ -117,7 +124,8 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
 #else		/* CONFIG_BRCMFMAC_SDIO_OOB */
 static void brcmf_sdio_irqhandler(struct sdio_func *func)
 {
-	struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
+	struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
 
 	brcmf_dbg(INTR, "ib intr triggered\n");
 
@@ -249,9 +257,7 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
 	int retval;
 
 	brcmf_dbg(INFO, "addr:0x%08x\n", addr);
-	sdio_claim_host(sdiodev->func[1]);
 	retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
-	sdio_release_host(sdiodev->func[1]);
 	brcmf_dbg(INFO, "data:0x%02x\n", data);
 
 	if (ret)
@@ -266,9 +272,7 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
 	int retval;
 
 	brcmf_dbg(INFO, "addr:0x%08x\n", addr);
-	sdio_claim_host(sdiodev->func[1]);
 	retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
-	sdio_release_host(sdiodev->func[1]);
 	brcmf_dbg(INFO, "data:0x%08x\n", data);
 
 	if (ret)
@@ -283,9 +287,7 @@ void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
 	int retval;
 
 	brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data);
-	sdio_claim_host(sdiodev->func[1]);
 	retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
-	sdio_release_host(sdiodev->func[1]);
 
 	if (ret)
 		*ret = retval;
@@ -297,9 +299,7 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
 	int retval;
 
 	brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data);
-	sdio_claim_host(sdiodev->func[1]);
 	retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
-	sdio_release_host(sdiodev->func[1]);
 
 	if (ret)
 		*ret = retval;
@@ -364,8 +364,6 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 	brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
 		  fn, addr, pkt->len);
 
-	sdio_claim_host(sdiodev->func[1]);
-
 	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
 	err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
 	if (err)
@@ -376,8 +374,6 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 					 fn, addr, pkt);
 
 done:
-	sdio_release_host(sdiodev->func[1]);
-
 	return err;
 }
 
@@ -391,8 +387,6 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 	brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
 		  fn, addr, pktq->qlen);
 
-	sdio_claim_host(sdiodev->func[1]);
-
 	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
 	err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
 	if (err)
@@ -403,8 +397,6 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 					pktq);
 
 done:
-	sdio_release_host(sdiodev->func[1]);
-
 	return err;
 }
 
@@ -446,8 +438,6 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 	if (flags & SDIO_REQ_ASYNC)
 		return -ENOTSUPP;
 
-	sdio_claim_host(sdiodev->func[1]);
-
 	if (bar0 != sdiodev->sbwad) {
 		err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
 		if (err)
@@ -467,8 +457,6 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 					 addr, pkt);
 
 done:
-	sdio_release_host(sdiodev->func[1]);
-
 	return err;
 }
 
@@ -510,10 +498,8 @@ int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
 	brcmf_dbg(TRACE, "Enter\n");
 
 	/* issue abort cmd52 command through F0 */
-	sdio_claim_host(sdiodev->func[1]);
 	brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
 				 SDIO_CCCR_ABORT, &t_func);
-	sdio_release_host(sdiodev->func[1]);
 
 	brcmf_dbg(TRACE, "Exit\n");
 	return 0;
@@ -530,9 +516,6 @@ int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
 
 	regs = SI_ENUM_BASE;
 
-	/* Report the BAR, to fix if needed */
-	sdiodev->sbwad = SI_ENUM_BASE;
-
 	/* try to attach to the target device */
 	sdiodev->bus = brcmf_sdbrcm_probe(regs, sdiodev);
 	if (!sdiodev->bus) {
@@ -551,6 +534,8 @@ EXPORT_SYMBOL(brcmf_sdio_probe);
 
 int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
 {
+	sdiodev->bus_if->state = BRCMF_BUS_DOWN;
+
 	if (sdiodev->bus) {
 		brcmf_sdbrcm_disconnect(sdiodev->bus);
 		sdiodev->bus = NULL;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index c3247d5..a800502 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -372,9 +372,7 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev)
 	}
 
 	/* Enable Function 1 */
-	sdio_claim_host(sdiodev->func[1]);
 	err_ret = sdio_enable_func(sdiodev->func[1]);
-	sdio_release_host(sdiodev->func[1]);
 	if (err_ret)
 		brcmf_dbg(ERROR, "Failed to enable F1 Err: 0x%08x\n", err_ret);
 
@@ -393,16 +391,14 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
 	sdiodev->num_funcs = 2;
 
 	sdio_claim_host(sdiodev->func[1]);
+
 	err_ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE);
-	sdio_release_host(sdiodev->func[1]);
 	if (err_ret) {
 		brcmf_dbg(ERROR, "Failed to set F1 blocksize\n");
 		goto out;
 	}
 
-	sdio_claim_host(sdiodev->func[2]);
 	err_ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE);
-	sdio_release_host(sdiodev->func[2]);
 	if (err_ret) {
 		brcmf_dbg(ERROR, "Failed to set F2 blocksize\n");
 		goto out;
@@ -411,6 +407,7 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
 	brcmf_sdioh_enablefuncs(sdiodev);
 
 out:
+	sdio_release_host(sdiodev->func[1]);
 	brcmf_dbg(TRACE, "Done\n");
 	return err_ret;
 }
@@ -459,95 +456,106 @@ static inline int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
 #endif		/* CONFIG_BRCMFMAC_SDIO_OOB */
 
 static int brcmf_ops_sdio_probe(struct sdio_func *func,
-			      const struct sdio_device_id *id)
+				const struct sdio_device_id *id)
 {
-	int ret = 0;
+	int err;
 	struct brcmf_sdio_dev *sdiodev;
 	struct brcmf_bus *bus_if;
 
 	brcmf_dbg(TRACE, "Enter\n");
-	brcmf_dbg(TRACE, "func->class=%x\n", func->class);
-	brcmf_dbg(TRACE, "sdio_vendor: 0x%04x\n", func->vendor);
-	brcmf_dbg(TRACE, "sdio_device: 0x%04x\n", func->device);
-	brcmf_dbg(TRACE, "Function#: 0x%04x\n", func->num);
-
-	if (func->num == 1) {
-		if (dev_get_drvdata(&func->card->dev)) {
-			brcmf_dbg(ERROR, "card private drvdata occupied\n");
-			return -ENXIO;
-		}
-		bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL);
-		if (!bus_if)
-			return -ENOMEM;
-		sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
-		if (!sdiodev) {
-			kfree(bus_if);
-			return -ENOMEM;
-		}
-		sdiodev->func[0] = func;
-		sdiodev->func[1] = func;
-		sdiodev->bus_if = bus_if;
-		bus_if->bus_priv.sdio = sdiodev;
-		bus_if->type = SDIO_BUS;
-		bus_if->align = BRCMF_SDALIGN;
-		dev_set_drvdata(&func->card->dev, sdiodev);
-
-		atomic_set(&sdiodev->suspend, false);
-		init_waitqueue_head(&sdiodev->request_byte_wait);
-		init_waitqueue_head(&sdiodev->request_word_wait);
-		init_waitqueue_head(&sdiodev->request_chain_wait);
-		init_waitqueue_head(&sdiodev->request_buffer_wait);
+	brcmf_dbg(TRACE, "Class=%x\n", func->class);
+	brcmf_dbg(TRACE, "sdio vendor ID: 0x%04x\n", func->vendor);
+	brcmf_dbg(TRACE, "sdio device ID: 0x%04x\n", func->device);
+	brcmf_dbg(TRACE, "Function#: %d\n", func->num);
+
+	/* Consume func num 1 but dont do anything with it. */
+	if (func->num == 1)
+		return 0;
+
+	/* Ignore anything but func 2 */
+	if (func->num != 2)
+		return -ENODEV;
+
+	bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL);
+	if (!bus_if)
+		return -ENOMEM;
+	sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
+	if (!sdiodev) {
+		kfree(bus_if);
+		return -ENOMEM;
 	}
 
-	if (func->num == 2) {
-		sdiodev = dev_get_drvdata(&func->card->dev);
-		if ((!sdiodev) || (sdiodev->func[1]->card != func->card))
-			return -ENODEV;
-
-		ret = brcmf_sdio_getintrcfg(sdiodev);
-		if (ret)
-			return ret;
-		sdiodev->func[2] = func;
+	sdiodev->func[0] = func->card->sdio_func[0];
+	sdiodev->func[1] = func->card->sdio_func[0];
+	sdiodev->func[2] = func;
 
-		bus_if = sdiodev->bus_if;
-		sdiodev->dev = &func->dev;
-		dev_set_drvdata(&func->dev, bus_if);
+	sdiodev->bus_if = bus_if;
+	bus_if->bus_priv.sdio = sdiodev;
+	bus_if->align = BRCMF_SDALIGN;
+	dev_set_drvdata(&func->dev, bus_if);
+	dev_set_drvdata(&sdiodev->func[1]->dev, bus_if);
+	sdiodev->dev = &sdiodev->func[1]->dev;
 
-		brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n");
-		ret = brcmf_sdio_probe(sdiodev);
+	atomic_set(&sdiodev->suspend, false);
+	init_waitqueue_head(&sdiodev->request_byte_wait);
+	init_waitqueue_head(&sdiodev->request_word_wait);
+	init_waitqueue_head(&sdiodev->request_chain_wait);
+	init_waitqueue_head(&sdiodev->request_buffer_wait);
+	err = brcmf_sdio_getintrcfg(sdiodev);
+	if (err)
+		goto fail;
+
+	brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n");
+	err = brcmf_sdio_probe(sdiodev);
+	if (err) {
+		brcmf_dbg(ERROR, "F2 error, probe failed %d...\n", err);
+		goto fail;
 	}
+	brcmf_dbg(TRACE, "F2 init completed...\n");
+	return 0;
 
-	return ret;
+fail:
+	dev_set_drvdata(&func->dev, NULL);
+	dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
+	kfree(sdiodev);
+	kfree(bus_if);
+	return err;
 }
 
 static void brcmf_ops_sdio_remove(struct sdio_func *func)
 {
 	struct brcmf_bus *bus_if;
 	struct brcmf_sdio_dev *sdiodev;
+
 	brcmf_dbg(TRACE, "Enter\n");
-	brcmf_dbg(INFO, "func->class=%x\n", func->class);
-	brcmf_dbg(INFO, "sdio_vendor: 0x%04x\n", func->vendor);
-	brcmf_dbg(INFO, "sdio_device: 0x%04x\n", func->device);
-	brcmf_dbg(INFO, "Function#: 0x%04x\n", func->num);
+	brcmf_dbg(TRACE, "sdio vendor ID: 0x%04x\n", func->vendor);
+	brcmf_dbg(TRACE, "sdio device ID: 0x%04x\n", func->device);
+	brcmf_dbg(TRACE, "Function: %d\n", func->num);
 
-	if (func->num == 2) {
-		bus_if = dev_get_drvdata(&func->dev);
+	if (func->num != 1 && func->num != 2)
+		return;
+
+	bus_if = dev_get_drvdata(&func->dev);
+	if (bus_if) {
 		sdiodev = bus_if->bus_priv.sdio;
-		brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n");
 		brcmf_sdio_remove(sdiodev);
-		dev_set_drvdata(&func->card->dev, NULL);
-		dev_set_drvdata(&func->dev, NULL);
+
+		dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
+		dev_set_drvdata(&sdiodev->func[2]->dev, NULL);
+
 		kfree(bus_if);
 		kfree(sdiodev);
 	}
+
+	brcmf_dbg(TRACE, "Exit\n");
 }
 
 #ifdef CONFIG_PM_SLEEP
 static int brcmf_sdio_suspend(struct device *dev)
 {
 	mmc_pm_flag_t sdio_flags;
-	struct sdio_func *func = dev_to_sdio_func(dev);
-	struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
 	int ret = 0;
 
 	brcmf_dbg(TRACE, "\n");
@@ -573,8 +581,8 @@ static int brcmf_sdio_suspend(struct device *dev)
 
 static int brcmf_sdio_resume(struct device *dev)
 {
-	struct sdio_func *func = dev_to_sdio_func(dev);
-	struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
 
 	brcmf_sdio_wdtmr_enable(sdiodev, true);
 	atomic_set(&sdiodev->suspend, false);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index 17e7ae7..24bc4e3 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -23,6 +23,8 @@
 
 #define BRCMF_VERSION_STR		"4.218.248.5"
 
+#include "fweh.h"
+
 /*******************************************************************************
  * IO codes that are interpreted by dongle firmware
  ******************************************************************************/
@@ -38,8 +40,11 @@
 #define BRCMF_C_GET_SSID			25
 #define BRCMF_C_SET_SSID			26
 #define BRCMF_C_GET_CHANNEL			29
+#define BRCMF_C_SET_CHANNEL			30
 #define BRCMF_C_GET_SRL				31
+#define BRCMF_C_SET_SRL				32
 #define BRCMF_C_GET_LRL				33
+#define BRCMF_C_SET_LRL				34
 #define BRCMF_C_GET_RADIO			37
 #define BRCMF_C_SET_RADIO			38
 #define BRCMF_C_GET_PHYTYPE			39
@@ -58,6 +63,7 @@
 #define BRCMF_C_SET_COUNTRY			84
 #define BRCMF_C_GET_PM				85
 #define BRCMF_C_SET_PM				86
+#define BRCMF_C_GET_CURR_RATESET		114
 #define BRCMF_C_GET_AP				117
 #define BRCMF_C_SET_AP				118
 #define BRCMF_C_GET_RSSI			127
@@ -65,6 +71,7 @@
 #define BRCMF_C_SET_WSEC			134
 #define BRCMF_C_GET_PHY_NOISE			135
 #define BRCMF_C_GET_BSS_INFO			136
+#define BRCMF_C_GET_PHYLIST			180
 #define BRCMF_C_SET_SCAN_CHANNEL_TIME		185
 #define BRCMF_C_SET_SCAN_UNASSOC_TIME		187
 #define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON	201
@@ -100,29 +107,8 @@
 #define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff
 #define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16
 
-#define BRCMF_SCAN_ACTION_START      1
-#define BRCMF_SCAN_ACTION_CONTINUE   2
-#define WL_SCAN_ACTION_ABORT      3
-
-#define BRCMF_ISCAN_REQ_VERSION 1
-
-/* brcmf_iscan_results status values */
-#define BRCMF_SCAN_RESULTS_SUCCESS	0
-#define BRCMF_SCAN_RESULTS_PARTIAL	1
-#define BRCMF_SCAN_RESULTS_PENDING	2
-#define BRCMF_SCAN_RESULTS_ABORTED	3
-#define BRCMF_SCAN_RESULTS_NO_MEM	4
-
-/* Indicates this key is using soft encrypt */
-#define WL_SOFT_KEY	(1 << 0)
 /* primary (ie tx) key */
 #define BRCMF_PRIMARY_KEY	(1 << 1)
-/* Reserved for backward compat */
-#define WL_KF_RES_4	(1 << 4)
-/* Reserved for backward compat */
-#define WL_KF_RES_5	(1 << 5)
-/* Indicates a group key for a IBSS PEER */
-#define WL_IBSS_PEER_GROUP_KEY	(1 << 6)
 
 /* For supporting multiple interfaces */
 #define BRCMF_MAX_IFS	16
@@ -130,10 +116,6 @@
 #define DOT11_BSSTYPE_ANY			2
 #define DOT11_MAX_DEFAULT_KEYS	4
 
-#define BRCMF_EVENT_MSG_LINK		0x01
-#define BRCMF_EVENT_MSG_FLUSHTXQ	0x02
-#define BRCMF_EVENT_MSG_GROUP		0x04
-
 #define BRCMF_ESCAN_REQ_VERSION 1
 
 #define WLC_BSS_RSSI_ON_CHANNEL		0x0002
@@ -141,108 +123,6 @@
 #define BRCMF_MAXRATES_IN_SET		16	/* max # of rates in rateset */
 #define BRCMF_STA_ASSOC			0x10		/* Associated */
 
-struct brcmf_event_msg {
-	__be16 version;
-	__be16 flags;
-	__be32 event_type;
-	__be32 status;
-	__be32 reason;
-	__be32 auth_type;
-	__be32 datalen;
-	u8 addr[ETH_ALEN];
-	char ifname[IFNAMSIZ];
-	u8 ifidx;
-	u8 bsscfgidx;
-} __packed;
-
-struct brcm_ethhdr {
-	u16 subtype;
-	u16 length;
-	u8 version;
-	u8 oui[3];
-	u16 usr_subtype;
-} __packed;
-
-struct brcmf_event {
-	struct ethhdr eth;
-	struct brcm_ethhdr hdr;
-	struct brcmf_event_msg msg;
-} __packed;
-
-/* event codes sent by the dongle to this driver */
-#define BRCMF_E_SET_SSID			0
-#define BRCMF_E_JOIN				1
-#define BRCMF_E_START				2
-#define BRCMF_E_AUTH				3
-#define BRCMF_E_AUTH_IND			4
-#define BRCMF_E_DEAUTH				5
-#define BRCMF_E_DEAUTH_IND			6
-#define BRCMF_E_ASSOC				7
-#define BRCMF_E_ASSOC_IND			8
-#define BRCMF_E_REASSOC				9
-#define BRCMF_E_REASSOC_IND			10
-#define BRCMF_E_DISASSOC			11
-#define BRCMF_E_DISASSOC_IND			12
-#define BRCMF_E_QUIET_START			13
-#define BRCMF_E_QUIET_END			14
-#define BRCMF_E_BEACON_RX			15
-#define BRCMF_E_LINK				16
-#define BRCMF_E_MIC_ERROR			17
-#define BRCMF_E_NDIS_LINK			18
-#define BRCMF_E_ROAM				19
-#define BRCMF_E_TXFAIL				20
-#define BRCMF_E_PMKID_CACHE			21
-#define BRCMF_E_RETROGRADE_TSF			22
-#define BRCMF_E_PRUNE				23
-#define BRCMF_E_AUTOAUTH			24
-#define BRCMF_E_EAPOL_MSG			25
-#define BRCMF_E_SCAN_COMPLETE			26
-#define BRCMF_E_ADDTS_IND			27
-#define BRCMF_E_DELTS_IND			28
-#define BRCMF_E_BCNSENT_IND			29
-#define BRCMF_E_BCNRX_MSG			30
-#define BRCMF_E_BCNLOST_MSG			31
-#define BRCMF_E_ROAM_PREP			32
-#define BRCMF_E_PFN_NET_FOUND			33
-#define BRCMF_E_PFN_NET_LOST			34
-#define BRCMF_E_RESET_COMPLETE			35
-#define BRCMF_E_JOIN_START			36
-#define BRCMF_E_ROAM_START			37
-#define BRCMF_E_ASSOC_START			38
-#define BRCMF_E_IBSS_ASSOC			39
-#define BRCMF_E_RADIO				40
-#define BRCMF_E_PSM_WATCHDOG			41
-#define BRCMF_E_PROBREQ_MSG			44
-#define BRCMF_E_SCAN_CONFIRM_IND		45
-#define BRCMF_E_PSK_SUP				46
-#define BRCMF_E_COUNTRY_CODE_CHANGED		47
-#define	BRCMF_E_EXCEEDED_MEDIUM_TIME		48
-#define BRCMF_E_ICV_ERROR			49
-#define BRCMF_E_UNICAST_DECODE_ERROR		50
-#define BRCMF_E_MULTICAST_DECODE_ERROR		51
-#define BRCMF_E_TRACE				52
-#define BRCMF_E_IF				54
-#define BRCMF_E_RSSI				56
-#define BRCMF_E_PFN_SCAN_COMPLETE		57
-#define BRCMF_E_EXTLOG_MSG			58
-#define BRCMF_E_ACTION_FRAME			59
-#define BRCMF_E_ACTION_FRAME_COMPLETE		60
-#define BRCMF_E_PRE_ASSOC_IND			61
-#define BRCMF_E_PRE_REASSOC_IND			62
-#define BRCMF_E_CHANNEL_ADOPTED			63
-#define BRCMF_E_AP_STARTED			64
-#define BRCMF_E_DFS_AP_STOP			65
-#define BRCMF_E_DFS_AP_RESUME			66
-#define BRCMF_E_RESERVED1			67
-#define BRCMF_E_RESERVED2			68
-#define BRCMF_E_ESCAN_RESULT			69
-#define BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE	70
-#define BRCMF_E_DCS_REQUEST			73
-
-#define BRCMF_E_FIFO_CREDIT_MAP			74
-
-#define BRCMF_E_LAST				75
-
 #define BRCMF_E_STATUS_SUCCESS			0
 #define BRCMF_E_STATUS_FAIL			1
 #define BRCMF_E_STATUS_TIMEOUT			2
@@ -318,6 +198,12 @@ struct brcmf_event {
 #define BRCMF_E_LINK_ASSOC_REC			3
 #define BRCMF_E_LINK_BSSCFG_DIS			4
 
+/* Small, medium and maximum buffer size for dcmd
+ */
+#define BRCMF_DCMD_SMLEN	256
+#define BRCMF_DCMD_MEDLEN	1536
+#define BRCMF_DCMD_MAXLEN	8192
+
 /* Pattern matching filter. Specifies an offset within received packets to
  * start matching, the pattern to match, the size of the pattern, and a bitmask
  * that indicates which bits within the pattern should be matched.
@@ -397,7 +283,7 @@ struct brcm_rateset_le {
 	/* # rates in this set */
 	__le32 count;
 	/* rates in 500kbps units w/hi bit set if basic */
-	u8 rates[WL_NUMRATES];
+	u8 rates[BRCMF_MAXRATES_IN_SET];
 };
 
 struct brcmf_ssid {
@@ -446,14 +332,6 @@ struct brcmf_scan_params_le {
 	__le16 channel_list[1];	/* list of chanspecs */
 };
 
-/* incremental scan struct */
-struct brcmf_iscan_params_le {
-	__le32 version;
-	__le16 action;
-	__le16 scan_duration;
-	struct brcmf_scan_params_le params_le;
-};
-
 struct brcmf_scan_results {
 	u32 buflen;
 	u32 version;
@@ -461,12 +339,6 @@ struct brcmf_scan_results {
 	struct brcmf_bss_info_le bss_info_le[];
 };
 
-struct brcmf_scan_results_le {
-	__le32 buflen;
-	__le32 version;
-	__le32 count;
-};
-
 struct brcmf_escan_params_le {
 	__le32 version;
 	__le16 action;
@@ -502,23 +374,6 @@ struct brcmf_join_params {
 	struct brcmf_assoc_params_le params_le;
 };
 
-/* incremental scan results struct */
-struct brcmf_iscan_results {
-	union {
-		u32 status;
-		__le32 status_le;
-	};
-	union {
-		struct brcmf_scan_results results;
-		struct brcmf_scan_results_le results_le;
-	};
-};
-
-/* size of brcmf_iscan_results not including variable length array */
-#define BRCMF_ISCAN_RESULTS_FIXED_SIZE \
-	(sizeof(struct brcmf_scan_results) + \
-	 offsetof(struct brcmf_iscan_results, results))
-
 struct brcmf_wsec_key {
 	u32 index;		/* key index */
 	u32 len;		/* key length */
@@ -623,7 +478,6 @@ struct brcmf_pub {
 	u8 wme_dp;		/* wme discard priority */
 
 	/* Dongle media info */
-	bool iswl;		/* Dongle-resident driver is wl */
 	unsigned long drv_version;	/* Version of dongle-resident driver */
 	u8 mac[ETH_ALEN];		/* MAC address obtained from dongle */
 
@@ -651,26 +505,26 @@ struct brcmf_pub {
 	int in_suspend;		/* flag set to 1 when early suspend called */
 	int dtim_skip;		/* dtim skip , default 0 means wake each dtim */
 
-	/* Pkt filter defination */
-	char *pktfilter[100];
-	int pktfilter_count;
-
-	u8 country_code[BRCM_CNTRY_BUF_SZ];
-	char eventmask[BRCMF_EVENTING_MASK_LEN];
-
 	struct brcmf_if *iflist[BRCMF_MAX_IFS];
 
 	struct mutex proto_block;
+	unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
 
-	struct work_struct setmacaddr_work;
-	struct work_struct multicast_work;
 	u8 macvalue[ETH_ALEN];
 	atomic_t pend_8021x_cnt;
+	wait_queue_head_t pend_8021x_wait;
+
+	struct brcmf_fweh_info fweh;
 #ifdef DEBUG
 	struct dentry *dbgfs_dir;
 #endif
 };
 
+struct bcmevent_name {
+	uint event;
+	const char *name;
+};
+
 struct brcmf_if_event {
 	u8 ifidx;
 	u8 action;
@@ -678,47 +532,54 @@ struct brcmf_if_event {
 	u8 bssidx;
 };
 
-struct bcmevent_name {
-	uint event;
-	const char *name;
+/* forward declaration */
+struct brcmf_cfg80211_vif;
+
+/**
+ * struct brcmf_if - interface control information.
+ *
+ * @drvr: points to device related information.
+ * @vif: points to cfg80211 specific interface information.
+ * @ndev: associated network device.
+ * @stats: interface specific network statistics.
+ * @idx: interface index in device firmware.
+ * @bssidx: index of bss associated with this interface.
+ * @mac_addr: assigned mac address.
+ */
+struct brcmf_if {
+	struct brcmf_pub *drvr;
+	struct brcmf_cfg80211_vif *vif;
+	struct net_device *ndev;
+	struct net_device_stats stats;
+	struct work_struct setmacaddr_work;
+	struct work_struct multicast_work;
+	int idx;
+	s32 bssidx;
+	u8 mac_addr[ETH_ALEN];
 };
 
-extern const struct bcmevent_name bcmevent_names[];
+static inline s32 brcmf_ndev_bssidx(struct net_device *ndev)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	return ifp->bssidx;
+}
 
-extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen,
-			  char *buf, uint len);
-extern uint brcmf_c_mkiovar_bsscfg(char *name, char *data, uint datalen,
-				   char *buf, uint buflen, s32 bssidx);
+extern const struct bcmevent_name bcmevent_names[];
 
 extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev);
 
-extern s32 brcmf_exec_dcmd(struct net_device *dev, u32 cmd, void *arg, u32 len);
-extern int brcmf_netlink_dcmd(struct net_device *ndev, struct brcmf_dcmd *dcmd);
-
 /* Return pointer to interface name */
 extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
 
 /* Query dongle */
 extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx,
 				       uint cmd, void *buf, uint len);
+extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
+				    void *buf, uint len);
 
-#ifdef DEBUG
-extern int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size);
-#endif				/* DEBUG */
-
-extern int brcmf_ifname2idx(struct brcmf_pub *drvr, char *name);
-extern int brcmf_c_host_event(struct brcmf_pub *drvr, int *idx,
-			      void *pktdata, struct brcmf_event_msg *,
-			      void **data_ptr);
-
+extern int brcmf_net_attach(struct brcmf_if *ifp);
+extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx,
+				     s32 bssidx, char *name, u8 *mac_addr);
 extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx);
 
-extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg);
-extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg,
-					     int enable, int master_mode);
-
-#define	BRCMF_DCMD_SMLEN	256	/* "small" cmd buffer required */
-#define BRCMF_DCMD_MEDLEN	1536	/* "med" cmd buffer required */
-#define	BRCMF_DCMD_MAXLEN	8192	/* max length cmd buffer required */
-
 #endif				/* _BRCMF_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index 9b8ee19..b8f2487 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -45,7 +45,6 @@ struct brcmf_bus_dcmd {
 
 /* interface structure between common and bus layer */
 struct brcmf_bus {
-	u8 type;		/* bus type */
 	union {
 		struct brcmf_sdio_dev *sdio;
 		struct brcmf_usbdev *usb;
@@ -85,7 +84,7 @@ extern bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
 			 struct sk_buff *pkt, int prec);
 
 /* Receive frame for delivery to OS.  Callee disposes of rxp. */
-extern void brcmf_rx_frame(struct device *dev, int ifidx,
+extern void brcmf_rx_frame(struct device *dev, u8 ifidx,
 			   struct sk_buff_head *rxlist);
 static inline void brcmf_rx_packet(struct device *dev, int ifidx,
 				   struct sk_buff *pkt)
@@ -111,9 +110,6 @@ extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp,
 
 extern int brcmf_bus_start(struct device *dev);
 
-extern int brcmf_add_if(struct device *dev, int ifidx,
-			char *name, u8 *mac_addr);
-
 #ifdef CONFIG_BRCMFMAC_SDIO
 extern void brcmf_sdio_exit(void);
 extern void brcmf_sdio_init(void);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
index a5c15ca..87536d3 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
@@ -23,8 +23,6 @@
 
 #include <linux/types.h>
 #include <linux/netdevice.h>
-#include <linux/sched.h>
-#include <defs.h>
 
 #include <brcmu_utils.h>
 #include <brcmu_wifi.h>
@@ -277,76 +275,6 @@ done:
 	return ret;
 }
 
-int
-brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, struct brcmf_dcmd *dcmd,
-		  int len)
-{
-	struct brcmf_proto *prot = drvr->prot;
-	int ret = -1;
-
-	if (drvr->bus_if->state == BRCMF_BUS_DOWN) {
-		brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n");
-		return ret;
-	}
-	mutex_lock(&drvr->proto_block);
-
-	brcmf_dbg(TRACE, "Enter\n");
-
-	if (len > BRCMF_DCMD_MAXLEN)
-		goto done;
-
-	if (prot->pending == true) {
-		brcmf_dbg(TRACE, "CDC packet is pending!!!! cmd=0x%x (%lu) lastcmd=0x%x (%lu)\n",
-			  dcmd->cmd, (unsigned long)dcmd->cmd, prot->lastcmd,
-			  (unsigned long)prot->lastcmd);
-		if (dcmd->cmd == BRCMF_C_SET_VAR ||
-		    dcmd->cmd == BRCMF_C_GET_VAR)
-			brcmf_dbg(TRACE, "iovar cmd=%s\n", (char *)dcmd->buf);
-
-		goto done;
-	}
-
-	prot->pending = true;
-	prot->lastcmd = dcmd->cmd;
-	if (dcmd->set)
-		ret = brcmf_proto_cdc_set_dcmd(drvr, ifidx, dcmd->cmd,
-						   dcmd->buf, len);
-	else {
-		ret = brcmf_proto_cdc_query_dcmd(drvr, ifidx, dcmd->cmd,
-						     dcmd->buf, len);
-		if (ret > 0)
-			dcmd->used = ret -
-					sizeof(struct brcmf_proto_cdc_dcmd);
-	}
-
-	if (ret >= 0)
-		ret = 0;
-	else {
-		struct brcmf_proto_cdc_dcmd *msg = &prot->msg;
-		/* len == needed when set/query fails from dongle */
-		dcmd->needed = le32_to_cpu(msg->len);
-	}
-
-	/* Intercept the wme_dp dongle cmd here */
-	if (!ret && dcmd->cmd == BRCMF_C_SET_VAR &&
-	    !strcmp(dcmd->buf, "wme_dp")) {
-		int slen;
-		__le32 val = 0;
-
-		slen = strlen("wme_dp") + 1;
-		if (len >= (int)(slen + sizeof(int)))
-			memcpy(&val, (char *)dcmd->buf + slen, sizeof(int));
-		drvr->wme_dp = (u8) le32_to_cpu(val);
-	}
-
-	prot->pending = false;
-
-done:
-	mutex_unlock(&drvr->proto_block);
-
-	return ret;
-}
-
 static bool pkt_sum_needed(struct sk_buff *skb)
 {
 	return skb->ip_summed == CHECKSUM_PARTIAL;
@@ -458,35 +386,6 @@ void brcmf_proto_detach(struct brcmf_pub *drvr)
 	drvr->prot = NULL;
 }
 
-int brcmf_proto_init(struct brcmf_pub *drvr)
-{
-	int ret = 0;
-	char buf[128];
-
-	brcmf_dbg(TRACE, "Enter\n");
-
-	mutex_lock(&drvr->proto_block);
-
-	/* Get the device MAC address */
-	strcpy(buf, "cur_etheraddr");
-	ret = brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR,
-					  buf, sizeof(buf));
-	if (ret < 0) {
-		mutex_unlock(&drvr->proto_block);
-		return ret;
-	}
-	memcpy(drvr->mac, buf, ETH_ALEN);
-
-	mutex_unlock(&drvr->proto_block);
-
-	ret = brcmf_c_preinit_dcmds(drvr);
-
-	/* Always assumes wl for now */
-	drvr->iswl = true;
-
-	return ret;
-}
-
 void brcmf_proto_stop(struct brcmf_pub *drvr)
 {
 	/* Nothing to do for CDC */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
index 15c5db5..eee7175 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
@@ -18,28 +18,21 @@
 
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/sched.h>
 #include <linux/netdevice.h>
-#include <asm/unaligned.h>
-#include <defs.h>
 #include <brcmu_wifi.h>
 #include <brcmu_utils.h>
 #include "dhd.h"
 #include "dhd_bus.h"
 #include "dhd_proto.h"
 #include "dhd_dbg.h"
+#include "fwil.h"
 
-#define BRCM_OUI			"\x00\x10\x18"
-#define DOT11_OUI_LEN			3
-#define BCMILCP_BCM_SUBTYPE_EVENT	1
-#define PKTFILTER_BUF_SIZE		2048
+#define PKTFILTER_BUF_SIZE		128
 #define BRCMF_ARPOL_MODE		0xb	/* agent|snoop|peer_autoreply */
-
-#define MSGTRACE_VERSION	1
-
-#define BRCMF_PKT_FILTER_FIXED_LEN	offsetof(struct brcmf_pkt_filter_le, u)
-#define BRCMF_PKT_FILTER_PATTERN_FIXED_LEN	\
-	offsetof(struct brcmf_pkt_filter_pattern_le, mask_and_pattern)
+#define BRCMF_DEFAULT_BCN_TIMEOUT	3
+#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME	40
+#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME	40
+#define BRCMF_DEFAULT_PACKET_FILTER	"100 0 0 0 0x01 0x00"
 
 #ifdef DEBUG
 static const char brcmf_version[] =
@@ -50,89 +43,6 @@ static const char brcmf_version[] =
 	"Dongle Host Driver, version " BRCMF_VERSION_STR;
 #endif
 
-/* Message trace header */
-struct msgtrace_hdr {
-	u8 version;
-	u8 spare;
-	__be16 len;		/* Len of the trace */
-	__be32 seqnum;		/* Sequence number of message. Useful
-				 * if the messsage has been lost
-				 * because of DMA error or a bus reset
-				 * (ex: SDIO Func2)
-				 */
-	__be32 discarded_bytes;	/* Number of discarded bytes because of
-				 trace overflow  */
-	__be32 discarded_printf;	/* Number of discarded printf
-				 because of trace overflow */
-} __packed;
-
-
-uint
-brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
-{
-	uint len;
-
-	len = strlen(name) + 1;
-
-	if ((len + datalen) > buflen)
-		return 0;
-
-	strncpy(buf, name, buflen);
-
-	/* append data onto the end of the name string */
-	if (data && datalen) {
-		memcpy(&buf[len], data, datalen);
-		len += datalen;
-	}
-
-	return len;
-}
-
-uint
-brcmf_c_mkiovar_bsscfg(char *name, char *data, uint datalen,
-		       char *buf, uint buflen, s32 bssidx)
-{
-	const s8 *prefix = "bsscfg:";
-	s8 *p;
-	u32 prefixlen;
-	u32 namelen;
-	u32 iolen;
-	__le32 bssidx_le;
-
-	if (bssidx == 0)
-		return brcmf_c_mkiovar(name, data, datalen, buf, buflen);
-
-	prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */
-	namelen = (u32) strlen(name) + 1; /* lengh of iovar  name + null */
-	iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen;
-
-	if (buflen < 0 || iolen > (u32)buflen) {
-		brcmf_dbg(ERROR, "buffer is too short\n");
-		return 0;
-	}
-
-	p = buf;
-
-	/* copy prefix, no null */
-	memcpy(p, prefix, prefixlen);
-	p += prefixlen;
-
-	/* copy iovar name including null */
-	memcpy(p, name, namelen);
-	p += namelen;
-
-	/* bss config index as first data */
-	bssidx_le = cpu_to_le32(bssidx);
-	memcpy(p, &bssidx_le, sizeof(bssidx_le));
-	p += sizeof(bssidx_le);
-
-	/* parameter buffer follows */
-	if (datalen)
-		memcpy(p, data, datalen);
-
-	return iolen;
-
-}
 
 bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
 		      struct sk_buff *pkt, int prec)
@@ -184,399 +94,6 @@ bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
 	return p != NULL;
 }
 
-#ifdef DEBUG
-static void
-brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data)
-{
-	uint i, status, reason;
-	bool group = false, flush_txq = false, link = false;
-	char *auth_str, *event_name;
-	unsigned char *buf;
-	char err_msg[256], eabuf[ETHER_ADDR_STR_LEN];
-	static struct {
-		uint event;
-		char *event_name;
-	} event_names[] = {
-		{
-		BRCMF_E_SET_SSID, "SET_SSID"}, {
-		BRCMF_E_JOIN, "JOIN"}, {
-		BRCMF_E_START, "START"}, {
-		BRCMF_E_AUTH, "AUTH"}, {
-		BRCMF_E_AUTH_IND, "AUTH_IND"}, {
-		BRCMF_E_DEAUTH, "DEAUTH"}, {
-		BRCMF_E_DEAUTH_IND, "DEAUTH_IND"}, {
-		BRCMF_E_ASSOC, "ASSOC"}, {
-		BRCMF_E_ASSOC_IND, "ASSOC_IND"}, {
-		BRCMF_E_REASSOC, "REASSOC"}, {
-		BRCMF_E_REASSOC_IND, "REASSOC_IND"}, {
-		BRCMF_E_DISASSOC, "DISASSOC"}, {
-		BRCMF_E_DISASSOC_IND, "DISASSOC_IND"}, {
-		BRCMF_E_QUIET_START, "START_QUIET"}, {
-		BRCMF_E_QUIET_END, "END_QUIET"}, {
-		BRCMF_E_BEACON_RX, "BEACON_RX"}, {
-		BRCMF_E_LINK, "LINK"}, {
-		BRCMF_E_MIC_ERROR, "MIC_ERROR"}, {
-		BRCMF_E_NDIS_LINK, "NDIS_LINK"}, {
-		BRCMF_E_ROAM, "ROAM"}, {
-		BRCMF_E_TXFAIL, "TXFAIL"}, {
-		BRCMF_E_PMKID_CACHE, "PMKID_CACHE"}, {
-		BRCMF_E_RETROGRADE_TSF, "RETROGRADE_TSF"}, {
-		BRCMF_E_PRUNE, "PRUNE"}, {
-		BRCMF_E_AUTOAUTH, "AUTOAUTH"}, {
-		BRCMF_E_EAPOL_MSG, "EAPOL_MSG"}, {
-		BRCMF_E_SCAN_COMPLETE, "SCAN_COMPLETE"}, {
-		BRCMF_E_ADDTS_IND, "ADDTS_IND"}, {
-		BRCMF_E_DELTS_IND, "DELTS_IND"}, {
-		BRCMF_E_BCNSENT_IND, "BCNSENT_IND"}, {
-		BRCMF_E_BCNRX_MSG, "BCNRX_MSG"}, {
-		BRCMF_E_BCNLOST_MSG, "BCNLOST_MSG"}, {
-		BRCMF_E_ROAM_PREP, "ROAM_PREP"}, {
-		BRCMF_E_PFN_NET_FOUND, "PNO_NET_FOUND"}, {
-		BRCMF_E_PFN_NET_LOST, "PNO_NET_LOST"}, {
-		BRCMF_E_RESET_COMPLETE, "RESET_COMPLETE"}, {
-		BRCMF_E_JOIN_START, "JOIN_START"}, {
-		BRCMF_E_ROAM_START, "ROAM_START"}, {
-		BRCMF_E_ASSOC_START, "ASSOC_START"}, {
-		BRCMF_E_IBSS_ASSOC, "IBSS_ASSOC"}, {
-		BRCMF_E_RADIO, "RADIO"}, {
-		BRCMF_E_PSM_WATCHDOG, "PSM_WATCHDOG"}, {
-		BRCMF_E_PROBREQ_MSG, "PROBREQ_MSG"}, {
-		BRCMF_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND"}, {
-		BRCMF_E_PSK_SUP, "PSK_SUP"}, {
-		BRCMF_E_COUNTRY_CODE_CHANGED, "COUNTRY_CODE_CHANGED"}, {
-		BRCMF_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME"}, {
-		BRCMF_E_ICV_ERROR, "ICV_ERROR"}, {
-		BRCMF_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR"}, {
-		BRCMF_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR"}, {
-		BRCMF_E_TRACE, "TRACE"}, {
-		BRCMF_E_ACTION_FRAME, "ACTION FRAME"}, {
-		BRCMF_E_ACTION_FRAME_COMPLETE, "ACTION FRAME TX COMPLETE"}, {
-		BRCMF_E_IF, "IF"}, {
-		BRCMF_E_RSSI, "RSSI"}, {
-		BRCMF_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"}, {
-		BRCMF_E_ESCAN_RESULT, "ESCAN_RESULT"}
-	};
-	uint event_type, flags, auth_type, datalen;
-	static u32 seqnum_prev;
-	struct msgtrace_hdr hdr;
-	u32 nblost;
-	char *s, *p;
-
-	event_type = be32_to_cpu(event->event_type);
-	flags = be16_to_cpu(event->flags);
-	status = be32_to_cpu(event->status);
-	reason = be32_to_cpu(event->reason);
-	auth_type = be32_to_cpu(event->auth_type);
-	datalen = be32_to_cpu(event->datalen);
-	/* debug dump of event messages */
-	sprintf(eabuf, "%pM", event->addr);
-
-	event_name = "UNKNOWN";
-	for (i = 0; i < ARRAY_SIZE(event_names); i++) {
-		if (event_names[i].event == event_type)
-			event_name = event_names[i].event_name;
-	}
-
-	brcmf_dbg(EVENT, "EVENT: %s, event ID = %d\n", event_name, event_type);
-	brcmf_dbg(EVENT, "flags 0x%04x, status %d, reason %d, auth_type %d MAC %s\n",
-		  flags, status, reason, auth_type, eabuf);
-
-	if (flags & BRCMF_EVENT_MSG_LINK)
-		link = true;
-	if (flags & BRCMF_EVENT_MSG_GROUP)
-		group = true;
-	if (flags & BRCMF_EVENT_MSG_FLUSHTXQ)
-		flush_txq = true;
-
-	switch (event_type) {
-	case BRCMF_E_START:
-	case BRCMF_E_DEAUTH:
-	case BRCMF_E_DISASSOC:
-		brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf);
-		break;
-
-	case BRCMF_E_ASSOC_IND:
-	case BRCMF_E_REASSOC_IND:
-		brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf);
-		break;
-
-	case BRCMF_E_ASSOC:
-	case BRCMF_E_REASSOC:
-		if (status == BRCMF_E_STATUS_SUCCESS)
-			brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, SUCCESS\n",
-				  event_name, eabuf);
-		else if (status == BRCMF_E_STATUS_TIMEOUT)
-			brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, TIMEOUT\n",
-				  event_name, eabuf);
-		else if (status == BRCMF_E_STATUS_FAIL)
-			brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, FAILURE, reason %d\n",
-				  event_name, eabuf, (int)reason);
-		else
-			brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, unexpected status %d\n",
-				  event_name, eabuf, (int)status);
-		break;
-
-	case BRCMF_E_DEAUTH_IND:
-	case BRCMF_E_DISASSOC_IND:
-		brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, reason %d\n",
-			  event_name, eabuf, (int)reason);
-		break;
-
-	case BRCMF_E_AUTH:
-	case BRCMF_E_AUTH_IND:
-		if (auth_type == WLAN_AUTH_OPEN)
-			auth_str = "Open System";
-		else if (auth_type == WLAN_AUTH_SHARED_KEY)
-			auth_str = "Shared Key";
-		else {
-			sprintf(err_msg, "AUTH unknown: %d", (int)auth_type);
-			auth_str = err_msg;
-		}
-		if (event_type == BRCMF_E_AUTH_IND)
-			brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s\n",
-				  event_name, eabuf, auth_str);
-		else if (status == BRCMF_E_STATUS_SUCCESS)
-			brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, SUCCESS\n",
-				  event_name, eabuf, auth_str);
-		else if (status == BRCMF_E_STATUS_TIMEOUT)
-			brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, TIMEOUT\n",
-				  event_name, eabuf, auth_str);
-		else if (status == BRCMF_E_STATUS_FAIL) {
-			brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, FAILURE, reason %d\n",
-				  event_name, eabuf, auth_str, (int)reason);
-		}
-
-		break;
-
-	case BRCMF_E_JOIN:
-	case BRCMF_E_ROAM:
-	case BRCMF_E_SET_SSID:
-		if (status == BRCMF_E_STATUS_SUCCESS)
-			brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n",
-				  event_name, eabuf);
-		else if (status == BRCMF_E_STATUS_FAIL)
-			brcmf_dbg(EVENT, "MACEVENT: %s, failed\n", event_name);
-		else if (status == BRCMF_E_STATUS_NO_NETWORKS)
-			brcmf_dbg(EVENT, "MACEVENT: %s, no networks found\n",
-				  event_name);
-		else
-			brcmf_dbg(EVENT, "MACEVENT: %s, unexpected status %d\n",
-				  event_name, (int)status);
-		break;
-
-	case BRCMF_E_BEACON_RX:
-		if (status == BRCMF_E_STATUS_SUCCESS)
-			brcmf_dbg(EVENT, "MACEVENT: %s, SUCCESS\n", event_name);
-		else if (status == BRCMF_E_STATUS_FAIL)
-			brcmf_dbg(EVENT, "MACEVENT: %s, FAIL\n", event_name);
-		else
-			brcmf_dbg(EVENT, "MACEVENT: %s, status %d\n",
-				  event_name, status);
-		break;
-
-	case BRCMF_E_LINK:
-		brcmf_dbg(EVENT, "MACEVENT: %s %s\n",
-			  event_name, link ? "UP" : "DOWN");
-		break;
-
-	case BRCMF_E_MIC_ERROR:
-		brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, Group %d, Flush %d\n",
-			  event_name, eabuf, group, flush_txq);
-		break;
-
-	case BRCMF_E_ICV_ERROR:
-	case BRCMF_E_UNICAST_DECODE_ERROR:
-	case BRCMF_E_MULTICAST_DECODE_ERROR:
-		brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf);
-		break;
-
-	case BRCMF_E_TXFAIL:
-		brcmf_dbg(EVENT, "MACEVENT: %s, RA %s\n", event_name, eabuf);
-		break;
-
-	case BRCMF_E_SCAN_COMPLETE:
-	case BRCMF_E_PMKID_CACHE:
-		brcmf_dbg(EVENT, "MACEVENT: %s\n", event_name);
-		break;
-
-	case BRCMF_E_ESCAN_RESULT:
-		brcmf_dbg(EVENT, "MACEVENT: %s\n", event_name);
-		datalen = 0;
-		break;
-
-	case BRCMF_E_PFN_NET_FOUND:
-	case BRCMF_E_PFN_NET_LOST:
-	case BRCMF_E_PFN_SCAN_COMPLETE:
-		brcmf_dbg(EVENT, "PNOEVENT: %s\n", event_name);
-		break;
-
-	case BRCMF_E_PSK_SUP:
-	case BRCMF_E_PRUNE:
-		brcmf_dbg(EVENT, "MACEVENT: %s, status %d, reason %d\n",
-			  event_name, (int)status, (int)reason);
-		break;
-
-	case BRCMF_E_TRACE:
-		buf = (unsigned char *) event_data;
-		memcpy(&hdr, buf, sizeof(struct msgtrace_hdr));
-
-		if (hdr.version != MSGTRACE_VERSION) {
-			brcmf_dbg(ERROR,
-				  "MACEVENT: %s [unsupported version --> brcmf"
-				  " version:%d dongle version:%d]\n",
-				  event_name, MSGTRACE_VERSION, hdr.version);
-			/* Reset datalen to avoid display below */
-			datalen = 0;
-			break;
-		}
-
-		/* There are 2 bytes available at the end of data */
-		*(buf + sizeof(struct msgtrace_hdr)
-			 + be16_to_cpu(hdr.len)) = '\0';
-
-		if (be32_to_cpu(hdr.discarded_bytes)
-		    || be32_to_cpu(hdr.discarded_printf))
-			brcmf_dbg(ERROR,
-				  "WLC_E_TRACE: [Discarded traces in dongle -->"
-				  " discarded_bytes %d discarded_printf %d]\n",
-				  be32_to_cpu(hdr.discarded_bytes),
-				  be32_to_cpu(hdr.discarded_printf));
-
-		nblost = be32_to_cpu(hdr.seqnum) - seqnum_prev - 1;
-		if (nblost > 0)
-			brcmf_dbg(ERROR, "WLC_E_TRACE: [Event lost --> seqnum "
-				  " %d nblost %d\n", be32_to_cpu(hdr.seqnum),
-				  nblost);
-		seqnum_prev = be32_to_cpu(hdr.seqnum);
-
-		/* Display the trace buffer. Advance from \n to \n to
-		 * avoid display big
-		 * printf (issue with Linux printk )
-		 */
-		p = (char *)&buf[sizeof(struct msgtrace_hdr)];
-		while ((s = strstr(p, "\n")) != NULL) {
-			*s = '\0';
-			pr_debug("%s\n", p);
-			p = s + 1;
-		}
-		pr_debug("%s\n", p);
-
-		/* Reset datalen to avoid display below */
-		datalen = 0;
-		break;
-
-	case BRCMF_E_RSSI:
-		brcmf_dbg(EVENT, "MACEVENT: %s %d\n",
-			  event_name, be32_to_cpu(*((__be32 *)event_data)));
-		break;
-
-	default:
-		brcmf_dbg(EVENT,
-			  "MACEVENT: %s %d, MAC %s, status %d, reason %d, "
-			  "auth %d\n", event_name, event_type, eabuf,
-			  (int)status, (int)reason, (int)auth_type);
-		break;
-	}
-
-	/* show any appended data */
-	brcmf_dbg_hex_dump(datalen, event_data, datalen, "Received data");
-}
-#endif				/* DEBUG */
-
-int
-brcmf_c_host_event(struct brcmf_pub *drvr, int *ifidx, void *pktdata,
-		   struct brcmf_event_msg *event, void **data_ptr)
-{
-	/* check whether packet is a BRCM event pkt */
-	struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata;
-	struct brcmf_if_event *ifevent;
-	char *event_data;
-	u32 type, status;
-	u16 flags;
-	int evlen;
-
-	if (memcmp(BRCM_OUI, &pvt_data->hdr.oui[0], DOT11_OUI_LEN)) {
-		brcmf_dbg(ERROR, "mismatched OUI, bailing\n");
-		return -EBADE;
-	}
-
-	/* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */
-	if (get_unaligned_be16(&pvt_data->hdr.usr_subtype) !=
-	    BCMILCP_BCM_SUBTYPE_EVENT) {
-		brcmf_dbg(ERROR, "mismatched subtype, bailing\n");
-		return -EBADE;
-	}
-
-	*data_ptr = &pvt_data[1];
-	event_data = *data_ptr;
-
-	/* memcpy since BRCM event pkt may be unaligned. */
-	memcpy(event, &pvt_data->msg, sizeof(struct brcmf_event_msg));
-
-	type = get_unaligned_be32(&event->event_type);
-	flags = get_unaligned_be16(&event->flags);
-	status = get_unaligned_be32(&event->status);
-	evlen = get_unaligned_be32(&event->datalen) +
-		sizeof(struct brcmf_event);
-
-	switch (type) {
-	case BRCMF_E_IF:
-		ifevent = (struct brcmf_if_event *) event_data;
-		brcmf_dbg(TRACE, "if event\n");
-
-		if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) {
-			if (ifevent->action == BRCMF_E_IF_ADD)
-				brcmf_add_if(drvr->dev, ifevent->ifidx,
-					     event->ifname,
-					     pvt_data->eth.h_dest);
-			else
-				brcmf_del_if(drvr, ifevent->ifidx);
-		} else {
-			brcmf_dbg(ERROR, "Invalid ifidx %d for %s\n",
-				  ifevent->ifidx, event->ifname);
-		}
-
-		/* send up the if event: btamp user needs it */
-		*ifidx = brcmf_ifname2idx(drvr, event->ifname);
-		break;
-
-		/* These are what external supplicant/authenticator wants */
-	case BRCMF_E_LINK:
-	case BRCMF_E_ASSOC_IND:
-	case BRCMF_E_REASSOC_IND:
-	case BRCMF_E_DISASSOC_IND:
-	case BRCMF_E_MIC_ERROR:
-	default:
-		/* Fall through: this should get _everything_  */
-
-		*ifidx = brcmf_ifname2idx(drvr, event->ifname);
-		brcmf_dbg(TRACE, "MAC event %d, flags %x, status %x\n",
-			  type, flags, status);
-
-		/* put it back to BRCMF_E_NDIS_LINK */
-		if (type == BRCMF_E_NDIS_LINK) {
-			u32 temp1;
-			__be32 temp2;
-
-			temp1 = get_unaligned_be32(&event->event_type);
-			brcmf_dbg(TRACE, "Converted to WLC_E_LINK type %d\n",
-				  temp1);
-
-			temp2 = cpu_to_be32(BRCMF_E_NDIS_LINK);
-			memcpy((void *)(&pvt_data->msg.event_type), &temp2,
-			       sizeof(pvt_data->msg.event_type));
-		}
-		break;
-	}
-
-#ifdef DEBUG
-	if (BRCMF_EVENT_ON())
-		brcmf_c_show_host_event(event, event_data);
-#endif /* DEBUG */
-
-	return 0;
-}
-
 /* Convert user's input in hex pattern to byte-size mask */
 static int brcmf_c_pattern_atoh(char *src, char *dst)
 {
@@ -603,90 +120,57 @@ static int brcmf_c_pattern_atoh(char *src, char *dst)
 	return i;
 }
 
-void
-brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable,
-			     int master_mode)
+static void
+brcmf_c_pktfilter_offload_enable(struct brcmf_if *ifp, char *arg, int enable,
+				 int master_mode)
 {
 	unsigned long res;
-	char *argv[8];
-	int i = 0;
-	const char *str;
-	int buf_len;
-	int str_len;
+	char *argv;
 	char *arg_save = NULL, *arg_org = NULL;
-	int rc;
-	char buf[128];
+	s32 err;
 	struct brcmf_pkt_filter_enable_le enable_parm;
-	struct brcmf_pkt_filter_enable_le *pkt_filterp;
-	__le32 mmode_le;
 
-	arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC);
+	arg_save = kstrdup(arg, GFP_ATOMIC);
 	if (!arg_save)
 		goto fail;
 
 	arg_org = arg_save;
-	memcpy(arg_save, arg, strlen(arg) + 1);
 
-	argv[i] = strsep(&arg_save, " ");
+	argv = strsep(&arg_save, " ");
 
-	i = 0;
-	if (NULL == argv[i]) {
+	if (argv == NULL) {
 		brcmf_dbg(ERROR, "No args provided\n");
 		goto fail;
 	}
 
-	str = "pkt_filter_enable";
-	str_len = strlen(str);
-	strncpy(buf, str, str_len);
-	buf[str_len] = '\0';
-	buf_len = str_len + 1;
-
-	pkt_filterp = (struct brcmf_pkt_filter_enable_le *) (buf + str_len + 1);
-
 	/* Parse packet filter id. */
 	enable_parm.id = 0;
-	if (!kstrtoul(argv[i], 0, &res))
+	if (!kstrtoul(argv, 0, &res))
 		enable_parm.id = cpu_to_le32((u32)res);
 
-	/* Parse enable/disable value. */
+	/* Enable/disable the specified filter. */
 	enable_parm.enable = cpu_to_le32(enable);
 
-	buf_len += sizeof(enable_parm);
-	memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm));
+	err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_enable", &enable_parm,
+				       sizeof(enable_parm));
+	if (err)
+		brcmf_dbg(ERROR, "Set pkt_filter_enable error (%d)\n", err);
 
-	/* Enable/disable the specified filter. */
-	rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
-	rc = rc >= 0 ? 0 : rc;
-	if (rc)
-		brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n",
-			  arg, rc);
-	else
-		brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg);
-
-	/* Contorl the master mode */
-	mmode_le = cpu_to_le32(master_mode);
-	brcmf_c_mkiovar("pkt_filter_mode", (char *)&mmode_le, 4, buf,
-		    sizeof(buf));
-	rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf,
-				       sizeof(buf));
-	rc = rc >= 0 ? 0 : rc;
-	if (rc)
-		brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n",
-			  arg, rc);
+	/* Control the master mode */
+	err = brcmf_fil_iovar_int_set(ifp, "pkt_filter_mode", master_mode);
+	if (err)
+		brcmf_dbg(ERROR, "Set pkt_filter_mode error (%d)\n", err);
 
 fail:
 	kfree(arg_org);
 }
 
-void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
+static void brcmf_c_pktfilter_offload_set(struct brcmf_if *ifp, char *arg)
 {
-	const char *str;
-	struct brcmf_pkt_filter_le pkt_filter;
-	struct brcmf_pkt_filter_le *pkt_filterp;
+	struct brcmf_pkt_filter_le *pkt_filter;
 	unsigned long res;
 	int buf_len;
-	int str_len;
-	int rc;
+	s32 err;
 	u32 mask_size;
 	u32 pattern_size;
 	char *argv[8], *buf = NULL;
@@ -704,104 +188,64 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
 		goto fail;
 
 	argv[i] = strsep(&arg_save, " ");
-	while (argv[i++])
+	while (argv[i]) {
+		i++;
+		if (i >= 8) {
+			brcmf_dbg(ERROR, "Too many parameters\n");
+			goto fail;
+		}
 		argv[i] = strsep(&arg_save, " ");
+	}
 
-	i = 0;
-	if (NULL == argv[i]) {
-		brcmf_dbg(ERROR, "No args provided\n");
+	if (i != 6) {
+		brcmf_dbg(ERROR, "Not enough args provided %d\n", i);
 		goto fail;
 	}
 
-	str = "pkt_filter_add";
-	strcpy(buf, str);
-	str_len = strlen(str);
-	buf_len = str_len + 1;
-
-	pkt_filterp = (struct brcmf_pkt_filter_le *) (buf + str_len + 1);
+	pkt_filter = (struct brcmf_pkt_filter_le *)buf;
 
 	/* Parse packet filter id. */
-	pkt_filter.id = 0;
-	if (!kstrtoul(argv[i], 0, &res))
-		pkt_filter.id = cpu_to_le32((u32)res);
-
-	if (NULL == argv[++i]) {
-		brcmf_dbg(ERROR, "Polarity not provided\n");
-		goto fail;
-	}
+	pkt_filter->id = 0;
+	if (!kstrtoul(argv[0], 0, &res))
+		pkt_filter->id = cpu_to_le32((u32)res);
 
 	/* Parse filter polarity. */
-	pkt_filter.negate_match = 0;
-	if (!kstrtoul(argv[i], 0, &res))
-		pkt_filter.negate_match = cpu_to_le32((u32)res);
-
-	if (NULL == argv[++i]) {
-		brcmf_dbg(ERROR, "Filter type not provided\n");
-		goto fail;
-	}
+	pkt_filter->negate_match = 0;
+	if (!kstrtoul(argv[1], 0, &res))
+		pkt_filter->negate_match = cpu_to_le32((u32)res);
 
 	/* Parse filter type. */
-	pkt_filter.type = 0;
-	if (!kstrtoul(argv[i], 0, &res))
-		pkt_filter.type = cpu_to_le32((u32)res);
-
-	if (NULL == argv[++i]) {
-		brcmf_dbg(ERROR, "Offset not provided\n");
-		goto fail;
-	}
+	pkt_filter->type = 0;
+	if (!kstrtoul(argv[2], 0, &res))
+		pkt_filter->type = cpu_to_le32((u32)res);
 
 	/* Parse pattern filter offset. */
-	pkt_filter.u.pattern.offset = 0;
-	if (!kstrtoul(argv[i], 0, &res))
-		pkt_filter.u.pattern.offset = cpu_to_le32((u32)res);
-
-	if (NULL == argv[++i]) {
-		brcmf_dbg(ERROR, "Bitmask not provided\n");
-		goto fail;
-	}
+	pkt_filter->u.pattern.offset = 0;
+	if (!kstrtoul(argv[3], 0, &res))
+		pkt_filter->u.pattern.offset = cpu_to_le32((u32)res);
 
 	/* Parse pattern filter mask. */
-	mask_size =
-	    brcmf_c_pattern_atoh
-		   (argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern);
-
-	if (NULL == argv[++i]) {
-		brcmf_dbg(ERROR, "Pattern not provided\n");
-		goto fail;
-	}
+	mask_size = brcmf_c_pattern_atoh(argv[4],
+			(char *)pkt_filter->u.pattern.mask_and_pattern);
 
 	/* Parse pattern filter pattern. */
-	pattern_size =
-	    brcmf_c_pattern_atoh(argv[i],
-				   (char *)&pkt_filterp->u.pattern.
-				   mask_and_pattern[mask_size]);
+	pattern_size = brcmf_c_pattern_atoh(argv[5],
+		(char *)&pkt_filter->u.pattern.mask_and_pattern[mask_size]);
 
 	if (mask_size != pattern_size) {
 		brcmf_dbg(ERROR, "Mask and pattern not the same size\n");
 		goto fail;
 	}
 
-	pkt_filter.u.pattern.size_bytes = cpu_to_le32(mask_size);
-	buf_len += BRCMF_PKT_FILTER_FIXED_LEN;
-	buf_len += (BRCMF_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
-
-	/* Keep-alive attributes are set in local
-	 * variable (keep_alive_pkt), and
-	 ** then memcpy'ed into buffer (keep_alive_pktp) since there is no
-	 ** guarantee that the buffer is properly aligned.
-	 */
-	memcpy((char *)pkt_filterp,
-	       &pkt_filter,
-	       BRCMF_PKT_FILTER_FIXED_LEN + BRCMF_PKT_FILTER_PATTERN_FIXED_LEN);
-
-	rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
-	rc = rc >= 0 ? 0 : rc;
+	pkt_filter->u.pattern.size_bytes = cpu_to_le32(mask_size);
+	buf_len = offsetof(struct brcmf_pkt_filter_le,
+			   u.pattern.mask_and_pattern);
+	buf_len += mask_size + pattern_size;
 
-	if (rc)
-		brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n",
-			  arg, rc);
-	else
-		brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg);
+	err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_add", pkt_filter,
+				       buf_len);
+	if (err)
+		brcmf_dbg(ERROR, "Set pkt_filter_add error (%d)\n", err);
 
 fail:
 	kfree(arg_org);
@@ -809,130 +253,125 @@ fail:
 	kfree(buf);
 }
 
-static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode)
+int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
 {
-	char iovbuf[32];
-	int retcode;
-	__le32 arp_mode_le;
-
-	arp_mode_le = cpu_to_le32(arp_mode);
-	brcmf_c_mkiovar("arp_ol", (char *)&arp_mode_le, 4, iovbuf,
-			sizeof(iovbuf));
-	retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
-				   iovbuf, sizeof(iovbuf));
-	retcode = retcode >= 0 ? 0 : retcode;
-	if (retcode)
-		brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, retcode = %d\n",
-			  arp_mode, retcode);
-	else
-		brcmf_dbg(TRACE, "successfully set ARP offload mode to 0x%x\n",
-			  arp_mode);
-}
-
-static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable)
-{
-	char iovbuf[32];
-	int retcode;
-	__le32 arp_enable_le;
-
-	arp_enable_le = cpu_to_le32(arp_enable);
-
-	brcmf_c_mkiovar("arpoe", (char *)&arp_enable_le, 4,
-			iovbuf, sizeof(iovbuf));
-	retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
-				   iovbuf, sizeof(iovbuf));
-	retcode = retcode >= 0 ? 0 : retcode;
-	if (retcode)
-		brcmf_dbg(TRACE, "failed to enable ARP offload to %d, retcode = %d\n",
-			  arp_enable, retcode);
-	else
-		brcmf_dbg(TRACE, "successfully enabled ARP offload to %d\n",
-			  arp_enable);
-}
-
-int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
-{
-	char iovbuf[BRCMF_EVENTING_MASK_LEN + 12];	/*  Room for
-				 "event_msgs" + '\0' + bitvec  */
-	char buf[128], *ptr;
-	__le32 roaming_le = cpu_to_le32(1);
-	__le32 bcn_timeout_le = cpu_to_le32(3);
-	__le32 scan_assoc_time_le = cpu_to_le32(40);
-	__le32 scan_unassoc_time_le = cpu_to_le32(40);
-	int i;
+	s8 eventmask[BRCMF_EVENTING_MASK_LEN];
+	u8 buf[BRCMF_DCMD_SMLEN];
+	char *ptr;
+	s32 err;
 	struct brcmf_bus_dcmd *cmdlst;
 	struct list_head *cur, *q;
 
-	mutex_lock(&drvr->proto_block);
-
-	/* Set Country code */
-	if (drvr->country_code[0] != 0) {
-		if (brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_COUNTRY,
-					      drvr->country_code,
-					      sizeof(drvr->country_code)) < 0)
-			brcmf_dbg(ERROR, "country code setting failed\n");
+	/* retreive mac address */
+	err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
+				       sizeof(ifp->mac_addr));
+	if (err < 0) {
+		brcmf_dbg(ERROR, "Retreiving cur_etheraddr failed, %d\n",
+			  err);
+		goto done;
 	}
+	memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
 
 	/* query for 'ver' to get version info from firmware */
 	memset(buf, 0, sizeof(buf));
-	ptr = buf;
-	brcmf_c_mkiovar("ver", NULL, 0, buf, sizeof(buf));
-	brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, buf, sizeof(buf));
+	strcpy(buf, "ver");
+	err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
+	if (err < 0) {
+		brcmf_dbg(ERROR, "Retreiving version information failed, %d\n",
+			  err);
+		goto done;
+	}
+	ptr = (char *)buf;
 	strsep(&ptr, "\n");
 	/* Print fw version info */
 	brcmf_dbg(ERROR, "Firmware version = %s\n", buf);
 
-	/* Setup timeout if Beacons are lost and roam is off to report
-		 link down */
-	brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout_le, 4, iovbuf,
-		    sizeof(iovbuf));
-	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
-				  sizeof(iovbuf));
+	/*
+	 * Setup timeout if Beacons are lost and roam is off to report
+	 * link down
+	 */
+	err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout",
+				      BRCMF_DEFAULT_BCN_TIMEOUT);
+	if (err) {
+		brcmf_dbg(ERROR, "bcn_timeout error (%d)\n", err);
+		goto done;
+	}
 
 	/* Enable/Disable build-in roaming to allowed ext supplicant to take
-		 of romaing */
-	brcmf_c_mkiovar("roam_off", (char *)&roaming_le, 4,
-		      iovbuf, sizeof(iovbuf));
-	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
-				  sizeof(iovbuf));
-
-	/* Setup event_msgs */
-	brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
-		      iovbuf, sizeof(iovbuf));
-	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
-				  sizeof(iovbuf));
-
-	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME,
-		 (char *)&scan_assoc_time_le, sizeof(scan_assoc_time_le));
-	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME,
-		 (char *)&scan_unassoc_time_le, sizeof(scan_unassoc_time_le));
-
-	/* Set and enable ARP offload feature */
-	brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE);
-	brcmf_c_arp_offload_enable(drvr, true);
-
-	/* Set up pkt filter */
-	for (i = 0; i < drvr->pktfilter_count; i++) {
-		brcmf_c_pktfilter_offload_set(drvr, drvr->pktfilter[i]);
-		brcmf_c_pktfilter_offload_enable(drvr, drvr->pktfilter[i],
-						 0, true);
+	 * of romaing
+	 */
+	err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1);
+	if (err) {
+		brcmf_dbg(ERROR, "roam_off error (%d)\n", err);
+		goto done;
+	}
+
+	/* Setup event_msgs, enable E_IF */
+	err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
+				       BRCMF_EVENTING_MASK_LEN);
+	if (err) {
+		brcmf_dbg(ERROR, "Get event_msgs error (%d)\n", err);
+		goto done;
+	}
+	setbit(eventmask, BRCMF_E_IF);
+	err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask,
+				       BRCMF_EVENTING_MASK_LEN);
+	if (err) {
+		brcmf_dbg(ERROR, "Set event_msgs error (%d)\n", err);
+		goto done;
 	}
 
+	/* Setup default scan channel time */
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
+				    BRCMF_DEFAULT_SCAN_CHANNEL_TIME);
+	if (err) {
+		brcmf_dbg(ERROR, "BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n",
+			  err);
+		goto done;
+	}
+
+	/* Setup default scan unassoc time */
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
+				    BRCMF_DEFAULT_SCAN_UNASSOC_TIME);
+	if (err) {
+		brcmf_dbg(ERROR, "BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n",
+			  err);
+		goto done;
+	}
+
+	/* Try to set and enable ARP offload feature, this may fail */
+	err = brcmf_fil_iovar_int_set(ifp, "arp_ol", BRCMF_ARPOL_MODE);
+	if (err) {
+		brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n",
+			  BRCMF_ARPOL_MODE, err);
+		err = 0;
+	} else {
+		err = brcmf_fil_iovar_int_set(ifp, "arpoe", 1);
+		if (err) {
+			brcmf_dbg(TRACE, "failed to enable ARP offload err = %d\n",
+				  err);
+			err = 0;
+		} else
+			brcmf_dbg(TRACE, "successfully enabled ARP offload to 0x%x\n",
+				  BRCMF_ARPOL_MODE);
+	}
+
+	/* Setup packet filter */
+	brcmf_c_pktfilter_offload_set(ifp, BRCMF_DEFAULT_PACKET_FILTER);
+	brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER,
+					 0, true);
+
 	/* set bus specific command if there is any */
-	list_for_each_safe(cur, q, &drvr->bus_if->dcmd_list) {
+	list_for_each_safe(cur, q, &ifp->drvr->bus_if->dcmd_list) {
 		cmdlst = list_entry(cur, struct brcmf_bus_dcmd, list);
 		if (cmdlst->name && cmdlst->param && cmdlst->param_len) {
-			brcmf_c_mkiovar(cmdlst->name, cmdlst->param,
-					cmdlst->param_len, iovbuf,
-					sizeof(iovbuf));
-			brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
-						 iovbuf, sizeof(iovbuf));
+			brcmf_fil_iovar_data_set(ifp, cmdlst->name,
+						 cmdlst->param,
+						 cmdlst->param_len);
 		}
 		list_del(cur);
 		kfree(cmdlst);
 	}
-
-	mutex_unlock(&drvr->proto_block);
-
-	return 0;
+done:
+	return err;
 }
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
index 7f89540..7e58e8c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
@@ -14,16 +14,12 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 #include <linux/debugfs.h>
-#include <linux/if_ether.h>
-#include <linux/if.h>
-#include <linux/ieee80211.h>
+#include <linux/netdevice.h>
 #include <linux/module.h>
 
-#include <defs.h>
 #include <brcmu_wifi.h>
 #include <brcmu_utils.h>
 #include "dhd.h"
-#include "dhd_bus.h"
 #include "dhd_dbg.h"
 
 static struct dentry *root_folder;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
index fb508c2..a0e18a1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
@@ -27,10 +27,11 @@
 #define BRCMF_HDRS_VAL	0x0040
 #define BRCMF_BYTES_VAL	0x0080
 #define BRCMF_INTR_VAL	0x0100
-#define BRCMF_GLOM_VAL	0x0400
-#define BRCMF_EVENT_VAL	0x0800
-#define BRCMF_BTA_VAL	0x1000
-#define BRCMF_ISCAN_VAL 0x2000
+#define BRCMF_GLOM_VAL	0x0200
+#define BRCMF_EVENT_VAL	0x0400
+#define BRCMF_BTA_VAL	0x0800
+#define BRCMF_FIL_VAL	0x1000
+#define BRCMF_USB_VAL	0x2000
 
 #if defined(DEBUG)
 
@@ -56,6 +57,7 @@ do {									\
 #define BRCMF_BYTES_ON()	(brcmf_msg_level & BRCMF_BYTES_VAL)
 #define BRCMF_GLOM_ON()		(brcmf_msg_level & BRCMF_GLOM_VAL)
 #define BRCMF_EVENT_ON()	(brcmf_msg_level & BRCMF_EVENT_VAL)
+#define BRCMF_FIL_ON()		(brcmf_msg_level & BRCMF_FIL_VAL)
 
 #else	/* (defined DEBUG) || (defined DEBUG) */
 
@@ -67,6 +69,7 @@ do {									\
 #define BRCMF_BYTES_ON()	0
 #define BRCMF_GLOM_ON()		0
 #define BRCMF_EVENT_ON()	0
+#define BRCMF_FIL_ON()		0
 
 #endif				/* defined(DEBUG) */
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index d7c76ce..b6c86b0 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -16,27 +16,11 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
 #include <linux/etherdevice.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/random.h>
-#include <linux/spinlock.h>
-#include <linux/ethtool.h>
-#include <linux/fcntl.h>
-#include <linux/fs.h>
-#include <linux/uaccess.h>
-#include <linux/hardirq.h>
-#include <linux/mutex.h>
-#include <linux/wait.h>
 #include <linux/module.h>
 #include <net/cfg80211.h>
 #include <net/rtnetlink.h>
-#include <defs.h>
 #include <brcmu_utils.h>
 #include <brcmu_wifi.h>
 
@@ -45,45 +29,19 @@
 #include "dhd_proto.h"
 #include "dhd_dbg.h"
 #include "wl_cfg80211.h"
+#include "fwil.h"
 
 MODULE_AUTHOR("Broadcom Corporation");
-MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac driver.");
-MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards");
+MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
+MODULE_SUPPORTED_DEVICE("Broadcom 802.11 WLAN fullmac cards");
 MODULE_LICENSE("Dual BSD/GPL");
 
-
-/* Interface control information */
-struct brcmf_if {
-	struct brcmf_pub *drvr;	/* back pointer to brcmf_pub */
-	/* OS/stack specifics */
-	struct net_device *ndev;
-	struct net_device_stats stats;
-	int idx;		/* iface idx in dongle */
-	u8 mac_addr[ETH_ALEN];	/* assigned MAC address */
-};
+#define MAX_WAIT_FOR_8021X_TX		50	/* msecs */
 
 /* Error bits */
 int brcmf_msg_level = BRCMF_ERROR_VAL;
 module_param(brcmf_msg_level, int, 0);
 
-int brcmf_ifname2idx(struct brcmf_pub *drvr, char *name)
-{
-	int i = BRCMF_MAX_IFS;
-	struct brcmf_if *ifp;
-
-	if (name == NULL || *name == '\0')
-		return 0;
-
-	while (--i > 0) {
-		ifp = drvr->iflist[i];
-		if (ifp && !strncmp(ifp->ndev->name, name, IFNAMSIZ))
-			break;
-	}
-
-	brcmf_dbg(TRACE, "return idx %d for \"%s\"\n", i, name);
-
-	return i;		/* default - the primary interface */
-}
 
 char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
 {
@@ -105,38 +63,33 @@ char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
 
 static void _brcmf_set_multicast_list(struct work_struct *work)
 {
+	struct brcmf_if *ifp;
 	struct net_device *ndev;
 	struct netdev_hw_addr *ha;
-	u32 dcmd_value, cnt;
+	u32 cmd_value, cnt;
 	__le32 cnt_le;
-	__le32 dcmd_le_value;
-
-	struct brcmf_dcmd dcmd;
 	char *buf, *bufp;
-	uint buflen;
-	int ret;
+	u32 buflen;
+	s32 err;
 
-	struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
-						    multicast_work);
+	brcmf_dbg(TRACE, "enter\n");
 
-	ndev = drvr->iflist[0]->ndev;
-	cnt = netdev_mc_count(ndev);
+	ifp = container_of(work, struct brcmf_if, multicast_work);
+	ndev = ifp->ndev;
 
 	/* Determine initial value of allmulti flag */
-	dcmd_value = (ndev->flags & IFF_ALLMULTI) ? true : false;
+	cmd_value = (ndev->flags & IFF_ALLMULTI) ? true : false;
 
 	/* Send down the multicast list first. */
-
-	buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETH_ALEN);
-	bufp = buf = kmalloc(buflen, GFP_ATOMIC);
-	if (!bufp)
+	cnt = netdev_mc_count(ndev);
+	buflen = sizeof(cnt) + (cnt * ETH_ALEN);
+	buf = kmalloc(buflen, GFP_ATOMIC);
+	if (!buf)
 		return;
-
-	strcpy(bufp, "mcast_list");
-	bufp += strlen("mcast_list") + 1;
+	bufp = buf;
 
 	cnt_le = cpu_to_le32(cnt);
-	memcpy(bufp, &cnt_le, sizeof(cnt));
+	memcpy(bufp, &cnt_le, sizeof(cnt_le));
 	bufp += sizeof(cnt_le);
 
 	netdev_for_each_mc_addr(ha, ndev) {
@@ -147,129 +100,66 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
 		cnt--;
 	}
 
-	memset(&dcmd, 0, sizeof(dcmd));
-	dcmd.cmd = BRCMF_C_SET_VAR;
-	dcmd.buf = buf;
-	dcmd.len = buflen;
-	dcmd.set = true;
-
-	ret = brcmf_proto_dcmd(drvr, 0, &dcmd, dcmd.len);
-	if (ret < 0) {
-		brcmf_dbg(ERROR, "%s: set mcast_list failed, cnt %d\n",
-			  brcmf_ifname(drvr, 0), cnt);
-		dcmd_value = cnt ? true : dcmd_value;
+	err = brcmf_fil_iovar_data_set(ifp, "mcast_list", buf, buflen);
+	if (err < 0) {
+		brcmf_dbg(ERROR, "Setting mcast_list failed, %d\n", err);
+		cmd_value = cnt ? true : cmd_value;
 	}
 
 	kfree(buf);
 
-	/* Now send the allmulti setting.  This is based on the setting in the
+	/*
+	 * Now send the allmulti setting.  This is based on the setting in the
 	 * net_device flags, but might be modified above to be turned on if we
 	 * were trying to set some addresses and dongle rejected it...
 	 */
+	err = brcmf_fil_iovar_int_set(ifp, "allmulti", cmd_value);
+	if (err < 0)
+		brcmf_dbg(ERROR, "Setting allmulti failed, %d\n", err);
 
-	buflen = sizeof("allmulti") + sizeof(dcmd_value);
-	buf = kmalloc(buflen, GFP_ATOMIC);
-	if (!buf)
-		return;
-
-	dcmd_le_value = cpu_to_le32(dcmd_value);
-
-	if (!brcmf_c_mkiovar
-	    ("allmulti", (void *)&dcmd_le_value,
-	    sizeof(dcmd_le_value), buf, buflen)) {
-		brcmf_dbg(ERROR, "%s: mkiovar failed for allmulti, datalen %d buflen %u\n",
-			  brcmf_ifname(drvr, 0),
-			  (int)sizeof(dcmd_value), buflen);
-		kfree(buf);
-		return;
-	}
-
-	memset(&dcmd, 0, sizeof(dcmd));
-	dcmd.cmd = BRCMF_C_SET_VAR;
-	dcmd.buf = buf;
-	dcmd.len = buflen;
-	dcmd.set = true;
-
-	ret = brcmf_proto_dcmd(drvr, 0, &dcmd, dcmd.len);
-	if (ret < 0) {
-		brcmf_dbg(ERROR, "%s: set allmulti %d failed\n",
-			  brcmf_ifname(drvr, 0),
-			  le32_to_cpu(dcmd_le_value));
-	}
-
-	kfree(buf);
-
-	/* Finally, pick up the PROMISC flag as well, like the NIC
-		 driver does */
-
-	dcmd_value = (ndev->flags & IFF_PROMISC) ? true : false;
-	dcmd_le_value = cpu_to_le32(dcmd_value);
-
-	memset(&dcmd, 0, sizeof(dcmd));
-	dcmd.cmd = BRCMF_C_SET_PROMISC;
-	dcmd.buf = &dcmd_le_value;
-	dcmd.len = sizeof(dcmd_le_value);
-	dcmd.set = true;
-
-	ret = brcmf_proto_dcmd(drvr, 0, &dcmd, dcmd.len);
-	if (ret < 0) {
-		brcmf_dbg(ERROR, "%s: set promisc %d failed\n",
-			  brcmf_ifname(drvr, 0),
-			  le32_to_cpu(dcmd_le_value));
-	}
+	/*Finally, pick up the PROMISC flag */
+	cmd_value = (ndev->flags & IFF_PROMISC) ? true : false;
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PROMISC, cmd_value);
+	if (err < 0)
+		brcmf_dbg(ERROR, "Setting BRCMF_C_SET_PROMISC failed, %d\n",
+			  err);
 }
 
 static void
 _brcmf_set_mac_address(struct work_struct *work)
 {
-	char buf[32];
-	struct brcmf_dcmd dcmd;
-	int ret;
-
-	struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
-						    setmacaddr_work);
+	struct brcmf_if *ifp;
+	s32 err;
 
 	brcmf_dbg(TRACE, "enter\n");
-	if (!brcmf_c_mkiovar("cur_etheraddr", (char *)drvr->macvalue,
-			   ETH_ALEN, buf, 32)) {
-		brcmf_dbg(ERROR, "%s: mkiovar failed for cur_etheraddr\n",
-			  brcmf_ifname(drvr, 0));
-		return;
-	}
-	memset(&dcmd, 0, sizeof(dcmd));
-	dcmd.cmd = BRCMF_C_SET_VAR;
-	dcmd.buf = buf;
-	dcmd.len = 32;
-	dcmd.set = true;
-
-	ret = brcmf_proto_dcmd(drvr, 0, &dcmd, dcmd.len);
-	if (ret < 0)
-		brcmf_dbg(ERROR, "%s: set cur_etheraddr failed\n",
-			  brcmf_ifname(drvr, 0));
-	else
-		memcpy(drvr->iflist[0]->ndev->dev_addr,
-		       drvr->macvalue, ETH_ALEN);
 
-	return;
+	ifp = container_of(work, struct brcmf_if, setmacaddr_work);
+	err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
+				       ETH_ALEN);
+	if (err < 0) {
+		brcmf_dbg(ERROR, "Setting cur_etheraddr failed, %d\n", err);
+	} else {
+		brcmf_dbg(TRACE, "MAC address updated to %pM\n",
+			  ifp->mac_addr);
+		memcpy(ifp->ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
+	}
 }
 
 static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
 {
 	struct brcmf_if *ifp = netdev_priv(ndev);
-	struct brcmf_pub *drvr = ifp->drvr;
 	struct sockaddr *sa = (struct sockaddr *)addr;
 
-	memcpy(&drvr->macvalue, sa->sa_data, ETH_ALEN);
-	schedule_work(&drvr->setmacaddr_work);
+	memcpy(&ifp->mac_addr, sa->sa_data, ETH_ALEN);
+	schedule_work(&ifp->setmacaddr_work);
 	return 0;
 }
 
 static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
 {
 	struct brcmf_if *ifp = netdev_priv(ndev);
-	struct brcmf_pub *drvr = ifp->drvr;
 
-	schedule_work(&drvr->multicast_work);
+	schedule_work(&ifp->multicast_work);
 }
 
 static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
@@ -282,7 +172,7 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 
 	/* Reject if down */
 	if (!drvr->bus_if->drvr_up ||
-	    (drvr->bus_if->state == BRCMF_BUS_DOWN)) {
+	    (drvr->bus_if->state != BRCMF_BUS_DATA)) {
 		brcmf_dbg(ERROR, "xmit rejected drvup=%d state=%d\n",
 			  drvr->bus_if->drvr_up,
 			  drvr->bus_if->state);
@@ -360,32 +250,13 @@ void brcmf_txflowblock(struct device *dev, bool state)
 		}
 }
 
-static int brcmf_host_event(struct brcmf_pub *drvr, int *ifidx,
-			    void *pktdata, struct brcmf_event_msg *event,
-			    void **data)
-{
-	int bcmerror = 0;
-
-	bcmerror = brcmf_c_host_event(drvr, ifidx, pktdata, event, data);
-	if (bcmerror != 0)
-		return bcmerror;
-
-	if (drvr->iflist[*ifidx]->ndev)
-		brcmf_cfg80211_event(drvr->iflist[*ifidx]->ndev,
-				     event, *data);
-
-	return bcmerror;
-}
-
-void brcmf_rx_frame(struct device *dev, int ifidx,
+void brcmf_rx_frame(struct device *dev, u8 ifidx,
 		    struct sk_buff_head *skb_list)
 {
 	unsigned char *eth;
 	uint len;
-	void *data;
 	struct sk_buff *skb, *pnext;
 	struct brcmf_if *ifp;
-	struct brcmf_event_msg event;
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
 	struct brcmf_pub *drvr = bus_if->drvr;
 
@@ -432,10 +303,7 @@ void brcmf_rx_frame(struct device *dev, int ifidx,
 		skb_pull(skb, ETH_HLEN);
 
 		/* Process special event packets and then discard them */
-		if (ntohs(skb->protocol) == ETH_P_LINK_CTL)
-			brcmf_host_event(drvr, &ifidx,
-					  skb_mac_header(skb),
-					  &event, &data);
+		brcmf_fweh_process_skb(drvr, skb, &ifidx);
 
 		if (drvr->iflist[ifidx]) {
 			ifp = drvr->iflist[ifidx];
@@ -471,9 +339,11 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
 	eh = (struct ethhdr *)(txp->data);
 	type = ntohs(eh->h_proto);
 
-	if (type == ETH_P_PAE)
+	if (type == ETH_P_PAE) {
 		atomic_dec(&drvr->pend_8021x_cnt);
-
+		if (waitqueue_active(&drvr->pend_8021x_wait))
+			wake_up(&drvr->pend_8021x_wait);
+	}
 }
 
 static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
@@ -497,83 +367,26 @@ static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
 	return &ifp->stats;
 }
 
-/* Retrieve current toe component enables, which are kept
-	 as a bitmap in toe_ol iovar */
-static int brcmf_toe_get(struct brcmf_pub *drvr, int ifidx, u32 *toe_ol)
-{
-	struct brcmf_dcmd dcmd;
-	__le32 toe_le;
-	char buf[32];
-	int ret;
-
-	memset(&dcmd, 0, sizeof(dcmd));
-
-	dcmd.cmd = BRCMF_C_GET_VAR;
-	dcmd.buf = buf;
-	dcmd.len = (uint) sizeof(buf);
-	dcmd.set = false;
-
-	strcpy(buf, "toe_ol");
-	ret = brcmf_proto_dcmd(drvr, ifidx, &dcmd, dcmd.len);
-	if (ret < 0) {
-		/* Check for older dongle image that doesn't support toe_ol */
-		if (ret == -EIO) {
-			brcmf_dbg(ERROR, "%s: toe not supported by device\n",
-				  brcmf_ifname(drvr, ifidx));
-			return -EOPNOTSUPP;
-		}
-
-		brcmf_dbg(INFO, "%s: could not get toe_ol: ret=%d\n",
-			  brcmf_ifname(drvr, ifidx), ret);
-		return ret;
-	}
-
-	memcpy(&toe_le, buf, sizeof(u32));
-	*toe_ol = le32_to_cpu(toe_le);
-	return 0;
-}
-
-/* Set current toe component enables in toe_ol iovar,
-	 and set toe global enable iovar */
-static int brcmf_toe_set(struct brcmf_pub *drvr, int ifidx, u32 toe_ol)
+/*
+ * Set current toe component enables in toe_ol iovar,
+ * and set toe global enable iovar
+ */
+static int brcmf_toe_set(struct brcmf_if *ifp, u32 toe_ol)
 {
-	struct brcmf_dcmd dcmd;
-	char buf[32];
-	int ret;
-	__le32 toe_le = cpu_to_le32(toe_ol);
-
-	memset(&dcmd, 0, sizeof(dcmd));
-
-	dcmd.cmd = BRCMF_C_SET_VAR;
-	dcmd.buf = buf;
-	dcmd.len = (uint) sizeof(buf);
-	dcmd.set = true;
-
-	/* Set toe_ol as requested */
-	strcpy(buf, "toe_ol");
-	memcpy(&buf[sizeof("toe_ol")], &toe_le, sizeof(u32));
+	s32 err;
 
-	ret = brcmf_proto_dcmd(drvr, ifidx, &dcmd, dcmd.len);
-	if (ret < 0) {
-		brcmf_dbg(ERROR, "%s: could not set toe_ol: ret=%d\n",
-			  brcmf_ifname(drvr, ifidx), ret);
-		return ret;
+	err = brcmf_fil_iovar_int_set(ifp, "toe_ol", toe_ol);
+	if (err < 0) {
+		brcmf_dbg(ERROR, "Setting toe_ol failed, %d\n", err);
+		return err;
 	}
 
-	/* Enable toe globally only if any components are enabled. */
-	toe_le = cpu_to_le32(toe_ol != 0);
-
-	strcpy(buf, "toe");
-	memcpy(&buf[sizeof("toe")], &toe_le, sizeof(u32));
+	err = brcmf_fil_iovar_int_set(ifp, "toe", (toe_ol != 0));
+	if (err < 0)
+		brcmf_dbg(ERROR, "Setting toe failed, %d\n", err);
 
-	ret = brcmf_proto_dcmd(drvr, ifidx, &dcmd, dcmd.len);
-	if (ret < 0) {
-		brcmf_dbg(ERROR, "%s: could not set toe: ret=%d\n",
-			  brcmf_ifname(drvr, ifidx), ret);
-		return ret;
-	}
+	return err;
 
-	return 0;
 }
 
 static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
@@ -591,8 +404,9 @@ static const struct ethtool_ops brcmf_ethtool_ops = {
 	.get_drvinfo = brcmf_ethtool_get_drvinfo,
 };
 
-static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr)
+static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
 {
+	struct brcmf_pub *drvr = ifp->drvr;
 	struct ethtool_drvinfo info;
 	char drvname[sizeof(info.driver)];
 	u32 cmd;
@@ -629,12 +443,9 @@ static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr)
 			brcmf_dbg(ERROR, "dongle is not up\n");
 			return -ENODEV;
 		}
-
 		/* finally, report dongle driver type */
-		else if (drvr->iswl)
-			sprintf(info.driver, "wl");
 		else
-			sprintf(info.driver, "xx");
+			sprintf(info.driver, "wl");
 
 		sprintf(info.version, "%lu", drvr->drv_version);
 		if (copy_to_user(uaddr, &info, sizeof(info)))
@@ -646,7 +457,7 @@ static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr)
 		/* Get toe offload components from dongle */
 	case ETHTOOL_GRXCSUM:
 	case ETHTOOL_GTXCSUM:
-		ret = brcmf_toe_get(drvr, 0, &toe_cmpnt);
+		ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt);
 		if (ret < 0)
 			return ret;
 
@@ -667,7 +478,7 @@ static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr)
 			return -EFAULT;
 
 		/* Read the current settings, update and write back */
-		ret = brcmf_toe_get(drvr, 0, &toe_cmpnt);
+		ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt);
 		if (ret < 0)
 			return ret;
 
@@ -679,18 +490,16 @@ static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr)
 		else
 			toe_cmpnt &= ~csum_dir;
 
-		ret = brcmf_toe_set(drvr, 0, toe_cmpnt);
+		ret = brcmf_toe_set(ifp, toe_cmpnt);
 		if (ret < 0)
 			return ret;
 
 		/* If setting TX checksum mode, tell Linux the new mode */
 		if (cmd == ETHTOOL_STXCSUM) {
 			if (edata.data)
-				drvr->iflist[0]->ndev->features |=
-				    NETIF_F_IP_CSUM;
+				ifp->ndev->features |= NETIF_F_IP_CSUM;
 			else
-				drvr->iflist[0]->ndev->features &=
-				    ~NETIF_F_IP_CSUM;
+				ifp->ndev->features &= ~NETIF_F_IP_CSUM;
 		}
 
 		break;
@@ -714,80 +523,23 @@ static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
 		return -1;
 
 	if (cmd == SIOCETHTOOL)
-		return brcmf_ethtool(drvr, ifr->ifr_data);
+		return brcmf_ethtool(ifp, ifr->ifr_data);
 
 	return -EOPNOTSUPP;
 }
 
-/* called only from within this driver. Sends a command to the dongle. */
-s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
-{
-	struct brcmf_dcmd dcmd;
-	s32 err = 0;
-	int buflen = 0;
-	bool is_set_key_cmd;
-	struct brcmf_if *ifp = netdev_priv(ndev);
-	struct brcmf_pub *drvr = ifp->drvr;
-
-	memset(&dcmd, 0, sizeof(dcmd));
-	dcmd.cmd = cmd;
-	dcmd.buf = arg;
-	dcmd.len = len;
-
-	if (dcmd.buf != NULL)
-		buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN);
-
-	/* send to dongle (must be up, and wl) */
-	if ((drvr->bus_if->state != BRCMF_BUS_DATA)) {
-		brcmf_dbg(ERROR, "DONGLE_DOWN\n");
-		err = -EIO;
-		goto done;
-	}
-
-	if (!drvr->iswl) {
-		err = -EIO;
-		goto done;
-	}
-
-	/*
-	 * Intercept BRCMF_C_SET_KEY CMD - serialize M4 send and
-	 * set key CMD to prevent M4 encryption.
-	 */
-	is_set_key_cmd = ((dcmd.cmd == BRCMF_C_SET_KEY) ||
-			  ((dcmd.cmd == BRCMF_C_SET_VAR) &&
-			   !(strncmp("wsec_key", dcmd.buf, 9))) ||
-			  ((dcmd.cmd == BRCMF_C_SET_VAR) &&
-			   !(strncmp("bsscfg:wsec_key", dcmd.buf, 15))));
-	if (is_set_key_cmd)
-		brcmf_netdev_wait_pend8021x(ndev);
-
-	err = brcmf_proto_dcmd(drvr, ifp->idx, &dcmd, buflen);
-
-done:
-	if (err > 0)
-		err = 0;
-
-	return err;
-}
-
-int brcmf_netlink_dcmd(struct net_device *ndev, struct brcmf_dcmd *dcmd)
-{
-	brcmf_dbg(TRACE, "enter: cmd %x buf %p len %d\n",
-		  dcmd->cmd, dcmd->buf, dcmd->len);
-
-	return brcmf_exec_dcmd(ndev, dcmd->cmd, dcmd->buf, dcmd->len);
-}
-
 static int brcmf_netdev_stop(struct net_device *ndev)
 {
 	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_pub *drvr = ifp->drvr;
 
 	brcmf_dbg(TRACE, "Enter\n");
-	brcmf_cfg80211_down(drvr->config);
+
 	if (drvr->bus_if->drvr_up == 0)
 		return 0;
 
+	brcmf_cfg80211_down(ndev);
+
 	/* Set state and stop OS transmissions */
 	drvr->bus_if->drvr_up = false;
 	netif_stop_queue(ndev);
@@ -802,38 +554,35 @@ static int brcmf_netdev_open(struct net_device *ndev)
 	struct brcmf_bus *bus_if = drvr->bus_if;
 	u32 toe_ol;
 	s32 ret = 0;
-	uint up = 0;
 
 	brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
 
-	if (ifp->idx == 0) {	/* do it only for primary eth0 */
-		/* If bus is not ready, can't continue */
-		if (bus_if->state != BRCMF_BUS_DATA) {
-			brcmf_dbg(ERROR, "failed bus is not ready\n");
-			return -EAGAIN;
-		}
+	/* If bus is not ready, can't continue */
+	if (bus_if->state != BRCMF_BUS_DATA) {
+		brcmf_dbg(ERROR, "failed bus is not ready\n");
+		return -EAGAIN;
+	}
 
-		atomic_set(&drvr->pend_8021x_cnt, 0);
+	atomic_set(&drvr->pend_8021x_cnt, 0);
 
-		memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN);
+	memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN);
 
-		/* Get current TOE mode from dongle */
-		if (brcmf_toe_get(drvr, ifp->idx, &toe_ol) >= 0
-		    && (toe_ol & TOE_TX_CSUM_OL) != 0)
-			drvr->iflist[ifp->idx]->ndev->features |=
-				NETIF_F_IP_CSUM;
-		else
-			drvr->iflist[ifp->idx]->ndev->features &=
-				~NETIF_F_IP_CSUM;
-	}
+	/* Get current TOE mode from dongle */
+	if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0
+	    && (toe_ol & TOE_TX_CSUM_OL) != 0)
+		drvr->iflist[ifp->idx]->ndev->features |=
+			NETIF_F_IP_CSUM;
+	else
+		drvr->iflist[ifp->idx]->ndev->features &=
+			~NETIF_F_IP_CSUM;
 
 	/* make sure RF is ready for work */
-	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_UP, (char *)&up, sizeof(up));
+	brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
 
 	/* Allow transmit calls */
 	netif_start_queue(ndev);
 	drvr->bus_if->drvr_up = true;
-	if (brcmf_cfg80211_up(drvr->config)) {
+	if (brcmf_cfg80211_up(ndev)) {
 		brcmf_dbg(ERROR, "failed to bring up cfg80211\n");
 		return -1;
 	}
@@ -851,48 +600,38 @@ static const struct net_device_ops brcmf_netdev_ops_pri = {
 	.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
 };
 
-static int brcmf_net_attach(struct brcmf_if *ifp)
+static const struct net_device_ops brcmf_netdev_ops_virt = {
+	.ndo_open = brcmf_cfg80211_up,
+	.ndo_stop = brcmf_cfg80211_down,
+	.ndo_get_stats = brcmf_netdev_get_stats,
+	.ndo_do_ioctl = brcmf_netdev_ioctl_entry,
+	.ndo_start_xmit = brcmf_netdev_start_xmit,
+	.ndo_set_mac_address = brcmf_netdev_set_mac_address,
+	.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
+};
+
+int brcmf_net_attach(struct brcmf_if *ifp)
 {
 	struct brcmf_pub *drvr = ifp->drvr;
 	struct net_device *ndev;
-	u8 temp_addr[ETH_ALEN];
-
-	brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
 
-	ndev = drvr->iflist[ifp->idx]->ndev;
-	ndev->netdev_ops = &brcmf_netdev_ops_pri;
+	brcmf_dbg(TRACE, "ifidx %d mac %pM\n", ifp->idx, ifp->mac_addr);
+	ndev = ifp->ndev;
 
-	/*
-	 * determine mac address to use
-	 */
-	if (is_valid_ether_addr(ifp->mac_addr))
-		memcpy(temp_addr, ifp->mac_addr, ETH_ALEN);
+	/* set appropriate operations */
+	if (!ifp->idx)
+		ndev->netdev_ops = &brcmf_netdev_ops_pri;
 	else
-		memcpy(temp_addr, drvr->mac, ETH_ALEN);
-
-	if (ifp->idx == 1) {
-		brcmf_dbg(TRACE, "ACCESS POINT MAC:\n");
-		/*  ACCESSPOINT INTERFACE CASE */
-		temp_addr[0] |= 0X02;	/* set bit 2 ,
-			 - Locally Administered address  */
+		ndev->netdev_ops = &brcmf_netdev_ops_virt;
 
-	}
 	ndev->hard_header_len = ETH_HLEN + drvr->hdrlen;
 	ndev->ethtool_ops = &brcmf_ethtool_ops;
 
 	drvr->rxsz = ndev->mtu + ndev->hard_header_len +
 			      drvr->hdrlen;
 
-	memcpy(ndev->dev_addr, temp_addr, ETH_ALEN);
-
-	/* attach to cfg80211 for primary interface */
-	if (!ifp->idx) {
-		drvr->config = brcmf_cfg80211_attach(ndev, drvr->dev, drvr);
-		if (drvr->config == NULL) {
-			brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n");
-			goto fail;
-		}
-	}
+	/* set the mac address */
+	memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
 
 	if (register_netdev(ndev) != 0) {
 		brcmf_dbg(ERROR, "couldn't register the net device\n");
@@ -908,13 +647,12 @@ fail:
 	return -EBADE;
 }
 
-int
-brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr)
+struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
+			      char *name, u8 *addr_mask)
 {
 	struct brcmf_if *ifp;
 	struct net_device *ndev;
-	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-	struct brcmf_pub *drvr = bus_if->drvr;
+	int i;
 
 	brcmf_dbg(TRACE, "idx %d\n", ifidx);
 
@@ -924,19 +662,24 @@ brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr)
 	 * in case we missed the BRCMF_E_IF_DEL event.
 	 */
 	if (ifp) {
-		brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n",
+		brcmf_dbg(ERROR, "ERROR: netdev:%s already exists\n",
 			  ifp->ndev->name);
-		netif_stop_queue(ifp->ndev);
-		unregister_netdev(ifp->ndev);
-		free_netdev(ifp->ndev);
-		drvr->iflist[ifidx] = NULL;
+		if (ifidx) {
+			netif_stop_queue(ifp->ndev);
+			unregister_netdev(ifp->ndev);
+			free_netdev(ifp->ndev);
+			drvr->iflist[ifidx] = NULL;
+		} else {
+			brcmf_dbg(ERROR, "ignore IF event\n");
+			return ERR_PTR(-EINVAL);
+		}
 	}
 
 	/* Allocate netdev, including space for private structure */
 	ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
 	if (!ndev) {
 		brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 	}
 
 	ifp = netdev_priv(ndev);
@@ -944,20 +687,19 @@ brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr)
 	ifp->drvr = drvr;
 	drvr->iflist[ifidx] = ifp;
 	ifp->idx = ifidx;
-	if (mac_addr != NULL)
-		memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
+	ifp->bssidx = bssidx;
 
-	if (brcmf_net_attach(ifp)) {
-		brcmf_dbg(ERROR, "brcmf_net_attach failed");
-		free_netdev(ifp->ndev);
-		drvr->iflist[ifidx] = NULL;
-		return -EOPNOTSUPP;
-	}
+	INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
+	INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
 
-	brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n",
-		  current->pid, ifp->ndev->name);
+	if (addr_mask != NULL)
+		for (i = 0; i < ETH_ALEN; i++)
+			ifp->mac_addr[i] = drvr->mac[i] ^ addr_mask[i];
 
-	return 0;
+	brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n",
+		  current->pid, ifp->ndev->name, ifp->mac_addr);
+
+	return ifp;
 }
 
 void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
@@ -982,6 +724,9 @@ void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
 			netif_stop_queue(ifp->ndev);
 		}
 
+		cancel_work_sync(&ifp->setmacaddr_work);
+		cancel_work_sync(&ifp->multicast_work);
+
 		unregister_netdev(ifp->ndev);
 		drvr->iflist[ifidx] = NULL;
 		if (ifidx == 0)
@@ -1020,11 +765,13 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
 		goto fail;
 	}
 
-	INIT_WORK(&drvr->setmacaddr_work, _brcmf_set_mac_address);
-	INIT_WORK(&drvr->multicast_work, _brcmf_set_multicast_list);
+	/* attach firmware event handler */
+	brcmf_fweh_attach(drvr);
 
 	INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);
 
+	init_waitqueue_head(&drvr->pend_8021x_wait);
+
 	return ret;
 
 fail:
@@ -1036,10 +783,9 @@ fail:
 int brcmf_bus_start(struct device *dev)
 {
 	int ret = -1;
-	/* Room for "event_msgs" + '\0' + bitvec */
-	char iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
 	struct brcmf_pub *drvr = bus_if->drvr;
+	struct brcmf_if *ifp;
 
 	brcmf_dbg(TRACE, "\n");
 
@@ -1050,49 +796,40 @@ int brcmf_bus_start(struct device *dev)
 		return ret;
 	}
 
-	brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
-		      iovbuf, sizeof(iovbuf));
-	brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, iovbuf,
-				    sizeof(iovbuf));
-	memcpy(drvr->eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
-
-	setbit(drvr->eventmask, BRCMF_E_SET_SSID);
-	setbit(drvr->eventmask, BRCMF_E_PRUNE);
-	setbit(drvr->eventmask, BRCMF_E_AUTH);
-	setbit(drvr->eventmask, BRCMF_E_REASSOC);
-	setbit(drvr->eventmask, BRCMF_E_REASSOC_IND);
-	setbit(drvr->eventmask, BRCMF_E_DEAUTH_IND);
-	setbit(drvr->eventmask, BRCMF_E_DISASSOC_IND);
-	setbit(drvr->eventmask, BRCMF_E_DISASSOC);
-	setbit(drvr->eventmask, BRCMF_E_JOIN);
-	setbit(drvr->eventmask, BRCMF_E_ASSOC_IND);
-	setbit(drvr->eventmask, BRCMF_E_PSK_SUP);
-	setbit(drvr->eventmask, BRCMF_E_LINK);
-	setbit(drvr->eventmask, BRCMF_E_NDIS_LINK);
-	setbit(drvr->eventmask, BRCMF_E_MIC_ERROR);
-	setbit(drvr->eventmask, BRCMF_E_PMKID_CACHE);
-	setbit(drvr->eventmask, BRCMF_E_TXFAIL);
-	setbit(drvr->eventmask, BRCMF_E_JOIN_START);
-	setbit(drvr->eventmask, BRCMF_E_SCAN_COMPLETE);
-
-/* enable dongle roaming event */
-
-	drvr->pktfilter_count = 1;
-	/* Setup filter to allow only unicast */
-	drvr->pktfilter[0] = "100 0 0 0 0x01 0x00";
-
-	/* Bus is ready, do any protocol initialization */
-	ret = brcmf_proto_init(drvr);
+	/* add primary networking interface */
+	ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
+	if (IS_ERR(ifp))
+		return PTR_ERR(ifp);
+
+	/* signal bus ready */
+	bus_if->state = BRCMF_BUS_DATA;
+
+	/* Bus is ready, do any initialization */
+	ret = brcmf_c_preinit_dcmds(ifp);
 	if (ret < 0)
-		return ret;
+		goto fail;
 
-	/* add primary networking interface */
-	ret = brcmf_add_if(dev, 0, "wlan%d", drvr->mac);
+	drvr->config = brcmf_cfg80211_attach(drvr);
+	if (drvr->config == NULL) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	ret = brcmf_fweh_activate_events(ifp);
 	if (ret < 0)
+		goto fail;
+
+	ret = brcmf_net_attach(ifp);
+fail:
+	if (ret < 0) {
+		brcmf_dbg(ERROR, "failed: %d\n", ret);
+		if (drvr->config)
+			brcmf_cfg80211_detach(drvr->config);
+		free_netdev(drvr->iflist[0]->ndev);
+		drvr->iflist[0] = NULL;
 		return ret;
+	}
 
-	/* signal bus ready */
-	bus_if->state = BRCMF_BUS_DATA;
 	return 0;
 }
 
@@ -1117,6 +854,11 @@ void brcmf_detach(struct device *dev)
 
 	brcmf_dbg(TRACE, "Enter\n");
 
+	if (drvr == NULL)
+		return;
+
+	/* stop firmware event handling */
+	brcmf_fweh_detach(drvr);
 
 	/* make sure primary interface removed last */
 	for (i = BRCMF_MAX_IFS-1; i > -1; i--)
@@ -1126,8 +868,6 @@ void brcmf_detach(struct device *dev)
 	brcmf_bus_detach(drvr);
 
 	if (drvr->prot) {
-		cancel_work_sync(&drvr->setmacaddr_work);
-		cancel_work_sync(&drvr->multicast_work);
 		brcmf_proto_detach(drvr);
 	}
 
@@ -1141,63 +881,20 @@ static int brcmf_get_pend_8021x_cnt(struct brcmf_pub *drvr)
 	return atomic_read(&drvr->pend_8021x_cnt);
 }
 
-#define MAX_WAIT_FOR_8021X_TX	10
-
 int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
 {
 	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_pub *drvr = ifp->drvr;
-	int timeout = 10 * HZ / 1000;
-	int ntimes = MAX_WAIT_FOR_8021X_TX;
-	int pend = brcmf_get_pend_8021x_cnt(drvr);
-
-	while (ntimes && pend) {
-		if (pend) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(timeout);
-			set_current_state(TASK_RUNNING);
-			ntimes--;
-		}
-		pend = brcmf_get_pend_8021x_cnt(drvr);
-	}
-	return pend;
-}
+	int err;
 
-#ifdef DEBUG
-int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size)
-{
-	int ret = 0;
-	struct file *fp;
-	mm_segment_t old_fs;
-	loff_t pos = 0;
-
-	/* change to KERNEL_DS address limit */
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-
-	/* open file to write */
-	fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640);
-	if (!fp) {
-		brcmf_dbg(ERROR, "open file error\n");
-		ret = -1;
-		goto exit;
-	}
+	err = wait_event_timeout(drvr->pend_8021x_wait,
+				 !brcmf_get_pend_8021x_cnt(drvr),
+				 msecs_to_jiffies(MAX_WAIT_FOR_8021X_TX));
 
-	/* Write buf to file */
-	fp->f_op->write(fp, (char __user *)buf, size, &pos);
+	WARN_ON(!err);
 
-exit:
-	/* free buf before return */
-	kfree(buf);
-	/* close file before return */
-	if (fp)
-		filp_close(fp, NULL);
-	/* restore previous address limit */
-	set_fs(old_fs);
-
-	return ret;
+	return !err;
 }
-#endif				/* DEBUG */
 
 static void brcmf_driver_init(struct work_struct *work)
 {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
index 6bc4425..48fa703 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
@@ -27,11 +27,6 @@ extern int brcmf_proto_attach(struct brcmf_pub *drvr);
 /* Unlink, frees allocated protocol memory (including brcmf_proto) */
 extern void brcmf_proto_detach(struct brcmf_pub *drvr);
 
-/* Initialize protocol: sync w/dongle state.
- * Sets dongle media info (iswl, drv_version, mac address).
- */
-extern int brcmf_proto_init(struct brcmf_pub *drvr);
-
 /* Stop protocol: sync w/dongle state. */
 extern void brcmf_proto_stop(struct brcmf_pub *drvr);
 
@@ -41,13 +36,7 @@ extern void brcmf_proto_stop(struct brcmf_pub *drvr);
 extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx,
 				struct sk_buff *txp);
 
-/* Use protocol to issue command to dongle */
-extern int brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx,
-				struct brcmf_dcmd *dcmd, int len);
-
-extern int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr);
-
-extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx,
-				     uint cmd, void *buf, uint len);
+/* Sets dongle media info (drv_version, mac address). */
+extern int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
 
 #endif				/* _BRCMF_PROTO_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 3564686..4572545 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -533,9 +533,11 @@ struct brcmf_sdio {
 	u8 *rxbuf;		/* Buffer for receiving control packets */
 	uint rxblen;		/* Allocated length of rxbuf */
 	u8 *rxctl;		/* Aligned pointer into rxbuf */
+	u8 *rxctl_orig;		/* pointer for freeing rxctl */
 	u8 *databuf;		/* Buffer for receiving big glom packet */
 	u8 *dataptr;		/* Aligned pointer into databuf */
 	uint rxlen;		/* Length of valid data in buffer */
+	spinlock_t rxctl_lock;	/* protection lock for ctrl frame resources */
 
 	u8 sdpcm_ver;	/* Bus protocol reported by dongle */
 
@@ -582,8 +584,6 @@ struct brcmf_sdio {
 	struct list_head dpc_tsklst;
 	spinlock_t dpc_tl_lock;
 
-	struct semaphore sdsem;
-
 	const struct firmware *firmware;
 	u32 fw_ptr;
 
@@ -614,6 +614,12 @@ static const uint max_roundup = 512;
 
 #define ALIGNMENT  4
 
+enum brcmf_sdio_frmtype {
+	BRCMF_SDIO_FT_NORMAL,
+	BRCMF_SDIO_FT_SUPER,
+	BRCMF_SDIO_FT_SUB,
+};
+
 static void pkt_align(struct sk_buff *p, int len, int align)
 {
 	uint datalign;
@@ -1031,8 +1037,9 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus)
 	}
 }
 
-static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
-				struct brcmf_sdio_read *rd)
+static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
+			       struct brcmf_sdio_read *rd,
+			       enum brcmf_sdio_frmtype type)
 {
 	u16 len, checksum;
 	u8 rx_seq, fc, tx_seq_max;
@@ -1047,17 +1054,26 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
 	/* All zero means no more to read */
 	if (!(len | checksum)) {
 		bus->rxpending = false;
-		return false;
+		return -ENODATA;
 	}
 	if ((u16)(~(len ^ checksum))) {
 		brcmf_dbg(ERROR, "HW header checksum error\n");
 		bus->sdcnt.rx_badhdr++;
 		brcmf_sdbrcm_rxfail(bus, false, false);
-		return false;
+		return -EIO;
 	}
 	if (len < SDPCM_HDRLEN) {
 		brcmf_dbg(ERROR, "HW header length error\n");
-		return false;
+		return -EPROTO;
+	}
+	if (type == BRCMF_SDIO_FT_SUPER &&
+	    (roundup(len, bus->blocksize) != rd->len)) {
+		brcmf_dbg(ERROR, "HW superframe header length error\n");
+		return -EPROTO;
+	}
+	if (type == BRCMF_SDIO_FT_SUB && len > rd->len) {
+		brcmf_dbg(ERROR, "HW subframe header length error\n");
+		return -EPROTO;
 	}
 	rd->len = len;
 
@@ -1071,15 +1087,33 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
 	 * Byte 5: Maximum Sequence number allow for Tx
 	 * Byte 6~7: Reserved
 	 */
+	if (type == BRCMF_SDIO_FT_SUPER &&
+	    SDPCM_GLOMDESC(&header[SDPCM_FRAMETAG_LEN])) {
+		brcmf_dbg(ERROR, "Glom descriptor found in superframe head\n");
+		rd->len = 0;
+		return -EINVAL;
+	}
 	rx_seq = SDPCM_PACKET_SEQUENCE(&header[SDPCM_FRAMETAG_LEN]);
 	rd->channel = SDPCM_PACKET_CHANNEL(&header[SDPCM_FRAMETAG_LEN]);
-	if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL) {
+	if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL &&
+	    type != BRCMF_SDIO_FT_SUPER) {
 		brcmf_dbg(ERROR, "HW header length too long\n");
 		bus->sdiodev->bus_if->dstats.rx_errors++;
 		bus->sdcnt.rx_toolong++;
 		brcmf_sdbrcm_rxfail(bus, false, false);
 		rd->len = 0;
-		return false;
+		return -EPROTO;
+	}
+	if (type == BRCMF_SDIO_FT_SUPER && rd->channel != SDPCM_GLOM_CHANNEL) {
+		brcmf_dbg(ERROR, "Wrong channel for superframe\n");
+		rd->len = 0;
+		return -EINVAL;
+	}
+	if (type == BRCMF_SDIO_FT_SUB && rd->channel != SDPCM_DATA_CHANNEL &&
+	    rd->channel != SDPCM_EVENT_CHANNEL) {
+		brcmf_dbg(ERROR, "Wrong channel for subframe\n");
+		rd->len = 0;
+		return -EINVAL;
 	}
 	rd->dat_offset = SDPCM_DOFFSET_VALUE(&header[SDPCM_FRAMETAG_LEN]);
 	if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) {
@@ -1087,7 +1121,7 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
 		bus->sdcnt.rx_badhdr++;
 		brcmf_sdbrcm_rxfail(bus, false, false);
 		rd->len = 0;
-		return false;
+		return -ENXIO;
 	}
 	if (rd->seq_num != rx_seq) {
 		brcmf_dbg(ERROR, "seq %d: sequence number error, expect %d\n",
@@ -1095,6 +1129,9 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
 		bus->sdcnt.rx_badseq++;
 		rd->seq_num = rx_seq;
 	}
+	/* no need to check the reset for subframe */
+	if (type == BRCMF_SDIO_FT_SUB)
+		return 0;
 	rd->len_nxtfrm = header[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
 	if (rd->len_nxtfrm << 4 > MAX_RX_DATASZ) {
 		/* only warm for NON glom packet */
@@ -1118,7 +1155,7 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
 	}
 	bus->tx_max = tx_seq_max;
 
-	return true;
+	return 0;
 }
 
 static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
@@ -1126,16 +1163,16 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
 	u16 dlen, totlen;
 	u8 *dptr, num = 0;
 
-	u16 sublen, check;
+	u16 sublen;
 	struct sk_buff *pfirst, *pnext;
 
 	int errcode;
-	u8 chan, seq, doff, sfdoff;
-	u8 txmax;
+	u8 doff, sfdoff;
 
 	int ifidx = 0;
 	bool usechain = bus->use_rxchain;
-	u16 next_len;
+
+	struct brcmf_sdio_read rd_new;
 
 	/* If packets, issue read(s) and send up packet chain */
 	/* Return sequence numbers consumed? */
@@ -1235,6 +1272,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
 		 * read directly into the chained packet, or allocate a large
 		 * packet and and copy into the chain.
 		 */
+		sdio_claim_host(bus->sdiodev->func[1]);
 		if (usechain) {
 			errcode = brcmf_sdcard_recv_chain(bus->sdiodev,
 					bus->sdiodev->sbwad,
@@ -1256,6 +1294,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
 				  dlen);
 			errcode = -1;
 		}
+		sdio_release_host(bus->sdiodev->func[1]);
 		bus->sdcnt.f2rxdata++;
 
 		/* On failure, kill the superframe, allow a couple retries */
@@ -1264,6 +1303,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
 				  dlen, errcode);
 			bus->sdiodev->bus_if->dstats.rx_errors++;
 
+			sdio_claim_host(bus->sdiodev->func[1]);
 			if (bus->glomerr++ < 3) {
 				brcmf_sdbrcm_rxfail(bus, true, true);
 			} else {
@@ -1272,6 +1312,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
 				bus->sdcnt.rxglomfail++;
 				brcmf_sdbrcm_free_glom(bus);
 			}
+			sdio_release_host(bus->sdiodev->func[1]);
 			return 0;
 		}
 
@@ -1279,68 +1320,17 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
 				   pfirst->data, min_t(int, pfirst->len, 48),
 				   "SUPERFRAME:\n");
 
-		/* Validate the superframe header */
-		dptr = (u8 *) (pfirst->data);
-		sublen = get_unaligned_le16(dptr);
-		check = get_unaligned_le16(dptr + sizeof(u16));
-
-		chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
-		seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
-		next_len = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
-		if ((next_len << 4) > MAX_RX_DATASZ) {
-			brcmf_dbg(INFO, "nextlen too large (%d) seq %d\n",
-				  next_len, seq);
-			next_len = 0;
-		}
-		bus->cur_read.len = next_len << 4;
-		doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
-		txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
-
-		errcode = 0;
-		if ((u16)~(sublen ^ check)) {
-			brcmf_dbg(ERROR, "(superframe): HW hdr error: len/check 0x%04x/0x%04x\n",
-				  sublen, check);
-			errcode = -1;
-		} else if (roundup(sublen, bus->blocksize) != dlen) {
-			brcmf_dbg(ERROR, "(superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n",
-				  sublen, roundup(sublen, bus->blocksize),
-				  dlen);
-			errcode = -1;
-		} else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) !=
-			   SDPCM_GLOM_CHANNEL) {
-			brcmf_dbg(ERROR, "(superframe): bad channel %d\n",
-				  SDPCM_PACKET_CHANNEL(
-					  &dptr[SDPCM_FRAMETAG_LEN]));
-			errcode = -1;
-		} else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
-			brcmf_dbg(ERROR, "(superframe): got 2nd descriptor?\n");
-			errcode = -1;
-		} else if ((doff < SDPCM_HDRLEN) ||
-			   (doff > (pfirst->len - SDPCM_HDRLEN))) {
-			brcmf_dbg(ERROR, "(superframe): Bad data offset %d: HW %d pkt %d min %d\n",
-				  doff, sublen, pfirst->len, SDPCM_HDRLEN);
-			errcode = -1;
-		}
-
-		/* Check sequence number of superframe SW header */
-		if (rxseq != seq) {
-			brcmf_dbg(INFO, "(superframe) rx_seq %d, expected %d\n",
-				  seq, rxseq);
-			bus->sdcnt.rx_badseq++;
-			rxseq = seq;
-		}
-
-		/* Check window for sanity */
-		if ((u8) (txmax - bus->tx_seq) > 0x40) {
-			brcmf_dbg(ERROR, "unlikely tx max %d with tx_seq %d\n",
-				  txmax, bus->tx_seq);
-			txmax = bus->tx_seq + 2;
-		}
-		bus->tx_max = txmax;
+		rd_new.seq_num = rxseq;
+		rd_new.len = dlen;
+		sdio_claim_host(bus->sdiodev->func[1]);
+		errcode = brcmf_sdio_hdparser(bus, pfirst->data, &rd_new,
+					      BRCMF_SDIO_FT_SUPER);
+		sdio_release_host(bus->sdiodev->func[1]);
+		bus->cur_read.len = rd_new.len_nxtfrm << 4;
 
 		/* Remove superframe header, remember offset */
-		skb_pull(pfirst, doff);
-		sfdoff = doff;
+		skb_pull(pfirst, rd_new.dat_offset);
+		sfdoff = rd_new.dat_offset;
 		num = 0;
 
 		/* Validate all the subframe headers */
@@ -1349,40 +1339,22 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
 			if (errcode)
 				break;
 
-			dptr = (u8 *) (pnext->data);
-			dlen = (u16) (pnext->len);
-			sublen = get_unaligned_le16(dptr);
-			check = get_unaligned_le16(dptr + sizeof(u16));
-			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
-			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
+			rd_new.len = pnext->len;
+			rd_new.seq_num = rxseq++;
+			sdio_claim_host(bus->sdiodev->func[1]);
+			errcode = brcmf_sdio_hdparser(bus, pnext->data, &rd_new,
+						      BRCMF_SDIO_FT_SUB);
+			sdio_release_host(bus->sdiodev->func[1]);
 			brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
-					   dptr, 32, "subframe:\n");
+					   pnext->data, 32, "subframe:\n");
 
-			if ((u16)~(sublen ^ check)) {
-				brcmf_dbg(ERROR, "(subframe %d): HW hdr error: len/check 0x%04x/0x%04x\n",
-					  num, sublen, check);
-				errcode = -1;
-			} else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
-				brcmf_dbg(ERROR, "(subframe %d): length mismatch: len 0x%04x, expect 0x%04x\n",
-					  num, sublen, dlen);
-				errcode = -1;
-			} else if ((chan != SDPCM_DATA_CHANNEL) &&
-				   (chan != SDPCM_EVENT_CHANNEL)) {
-				brcmf_dbg(ERROR, "(subframe %d): bad channel %d\n",
-					  num, chan);
-				errcode = -1;
-			} else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
-				brcmf_dbg(ERROR, "(subframe %d): Bad data offset %d: HW %d min %d\n",
-					  num, doff, sublen, SDPCM_HDRLEN);
-				errcode = -1;
-			}
-			/* increase the subframe count */
 			num++;
 		}
 
 		if (errcode) {
 			/* Terminate frame on error, request
 				 a couple retries */
+			sdio_claim_host(bus->sdiodev->func[1]);
 			if (bus->glomerr++ < 3) {
 				/* Restore superframe header space */
 				skb_push(pfirst, sfdoff);
@@ -1393,6 +1365,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
 				bus->sdcnt.rxglomfail++;
 				brcmf_sdbrcm_free_glom(bus);
 			}
+			sdio_release_host(bus->sdiodev->func[1]);
 			bus->cur_read.len = 0;
 			return 0;
 		}
@@ -1402,27 +1375,11 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
 		skb_queue_walk_safe(&bus->glom, pfirst, pnext) {
 			dptr = (u8 *) (pfirst->data);
 			sublen = get_unaligned_le16(dptr);
-			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
-			seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
 			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
 
-			brcmf_dbg(GLOM, "Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n",
-				  num, pfirst, pfirst->data,
-				  pfirst->len, sublen, chan, seq);
-
-			/* precondition: chan == SDPCM_DATA_CHANNEL ||
-					 chan == SDPCM_EVENT_CHANNEL */
-
-			if (rxseq != seq) {
-				brcmf_dbg(GLOM, "rx_seq %d, expected %d\n",
-					  seq, rxseq);
-				bus->sdcnt.rx_badseq++;
-				rxseq = seq;
-			}
-			rxseq++;
-
 			brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(),
-					   dptr, dlen, "Rx Subframe Data:\n");
+					   dptr, pfirst->len,
+					   "Rx Subframe Data:\n");
 
 			__skb_trim(pfirst, sublen);
 			skb_pull(pfirst, doff);
@@ -1449,11 +1406,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
 					   pfirst->prev);
 		}
 		/* sent any remaining packets up */
-		if (bus->glom.qlen) {
-			up(&bus->sdsem);
+		if (bus->glom.qlen)
 			brcmf_rx_frame(bus->sdiodev->dev, ifidx, &bus->glom);
-			down(&bus->sdsem);
-		}
 
 		bus->sdcnt.rxglomframes++;
 		bus->sdcnt.rxglompkts += bus->glom.qlen;
@@ -1494,21 +1448,24 @@ static void
 brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
 {
 	uint rdlen, pad;
-
+	u8 *buf = NULL, *rbuf;
 	int sdret;
 
 	brcmf_dbg(TRACE, "Enter\n");
 
-	/* Set rxctl for frame (w/optional alignment) */
-	bus->rxctl = bus->rxbuf;
-	bus->rxctl += BRCMF_FIRSTREAD;
-	pad = ((unsigned long)bus->rxctl % BRCMF_SDALIGN);
+	if (bus->rxblen)
+		buf = vzalloc(bus->rxblen);
+	if (!buf) {
+		brcmf_dbg(ERROR, "no memory for control frame\n");
+		goto done;
+	}
+	rbuf = bus->rxbuf;
+	pad = ((unsigned long)rbuf % BRCMF_SDALIGN);
 	if (pad)
-		bus->rxctl += (BRCMF_SDALIGN - pad);
-	bus->rxctl -= BRCMF_FIRSTREAD;
+		rbuf += (BRCMF_SDALIGN - pad);
 
 	/* Copy the already-read portion over */
-	memcpy(bus->rxctl, hdr, BRCMF_FIRSTREAD);
+	memcpy(buf, hdr, BRCMF_FIRSTREAD);
 	if (len <= BRCMF_FIRSTREAD)
 		goto gotpkt;
 
@@ -1545,11 +1502,11 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
 		goto done;
 	}
 
-	/* Read remainder of frame body into the rxctl buffer */
+	/* Read remain of frame body */
 	sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
 				bus->sdiodev->sbwad,
 				SDIO_FUNC_2,
-				F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen);
+				F2SYNC, rbuf, rdlen);
 	bus->sdcnt.f2rxdata++;
 
 	/* Control frame failures need retransmission */
@@ -1559,16 +1516,26 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
 		bus->sdcnt.rxc_errors++;
 		brcmf_sdbrcm_rxfail(bus, true, true);
 		goto done;
-	}
+	} else
+		memcpy(buf + BRCMF_FIRSTREAD, rbuf, rdlen);
 
 gotpkt:
 
 	brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_CTL_ON(),
-			   bus->rxctl, len, "RxCtrl:\n");
+			   buf, len, "RxCtrl:\n");
 
 	/* Point to valid data and indicate its length */
-	bus->rxctl += doff;
+	spin_lock_bh(&bus->rxctl_lock);
+	if (bus->rxctl) {
+		brcmf_dbg(ERROR, "last control frame is being processed.\n");
+		spin_unlock_bh(&bus->rxctl_lock);
+		vfree(buf);
+		goto done;
+	}
+	bus->rxctl = buf + doff;
+	bus->rxctl_orig = buf;
 	bus->rxlen = len - doff;
+	spin_unlock_bh(&bus->rxctl_lock);
 
 done:
 	/* Awake any waiters */
@@ -1623,6 +1590,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 
 		rd->len_left = rd->len;
 		/* read header first for unknow frame length */
+		sdio_claim_host(bus->sdiodev->func[1]);
 		if (!rd->len) {
 			sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
 						      bus->sdiodev->sbwad,
@@ -1635,6 +1603,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 					  sdret);
 				bus->sdcnt.rx_hdrfail++;
 				brcmf_sdbrcm_rxfail(bus, true, true);
+				sdio_release_host(bus->sdiodev->func[1]);
 				continue;
 			}
 
@@ -1642,7 +1611,9 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 					   bus->rxhdr, SDPCM_HDRLEN,
 					   "RxHdr:\n");
 
-			if (!brcmf_sdio_hdparser(bus, bus->rxhdr, rd)) {
+			if (brcmf_sdio_hdparser(bus, bus->rxhdr, rd,
+						BRCMF_SDIO_FT_NORMAL)) {
+				sdio_release_host(bus->sdiodev->func[1]);
 				if (!bus->rxpending)
 					break;
 				else
@@ -1658,6 +1629,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 				rd->len_nxtfrm = 0;
 				/* treat all packet as event if we don't know */
 				rd->channel = SDPCM_EVENT_CHANNEL;
+				sdio_release_host(bus->sdiodev->func[1]);
 				continue;
 			}
 			rd->len_left = rd->len > BRCMF_FIRSTREAD ?
@@ -1675,6 +1647,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 			bus->sdiodev->bus_if->dstats.rx_dropped++;
 			brcmf_sdbrcm_rxfail(bus, false,
 					    RETRYCHAN(rd->channel));
+			sdio_release_host(bus->sdiodev->func[1]);
 			continue;
 		}
 		skb_pull(pkt, head_read);
@@ -1683,14 +1656,17 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 		sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
 					      SDIO_FUNC_2, F2SYNC, pkt);
 		bus->sdcnt.f2rxdata++;
+		sdio_release_host(bus->sdiodev->func[1]);
 
 		if (sdret < 0) {
 			brcmf_dbg(ERROR, "read %d bytes from channel %d failed: %d\n",
 				  rd->len, rd->channel, sdret);
 			brcmu_pkt_buf_free_skb(pkt);
 			bus->sdiodev->bus_if->dstats.rx_errors++;
+			sdio_claim_host(bus->sdiodev->func[1]);
 			brcmf_sdbrcm_rxfail(bus, true,
 					    RETRYCHAN(rd->channel));
+			sdio_release_host(bus->sdiodev->func[1]);
 			continue;
 		}
 
@@ -1701,7 +1677,9 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 		} else {
 			memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN);
 			rd_new.seq_num = rd->seq_num;
-			if (!brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new)) {
+			sdio_claim_host(bus->sdiodev->func[1]);
+			if (brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new,
+						BRCMF_SDIO_FT_NORMAL)) {
 				rd->len = 0;
 				brcmu_pkt_buf_free_skb(pkt);
 			}
@@ -1712,9 +1690,11 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 					  roundup(rd_new.len, 16) >> 4);
 				rd->len = 0;
 				brcmf_sdbrcm_rxfail(bus, true, true);
+				sdio_release_host(bus->sdiodev->func[1]);
 				brcmu_pkt_buf_free_skb(pkt);
 				continue;
 			}
+			sdio_release_host(bus->sdiodev->func[1]);
 			rd->len_nxtfrm = rd_new.len_nxtfrm;
 			rd->channel = rd_new.channel;
 			rd->dat_offset = rd_new.dat_offset;
@@ -1730,7 +1710,9 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 					  rd_new.seq_num);
 				/* Force retry w/normal header read */
 				rd->len = 0;
+				sdio_claim_host(bus->sdiodev->func[1]);
 				brcmf_sdbrcm_rxfail(bus, false, true);
+				sdio_release_host(bus->sdiodev->func[1]);
 				brcmu_pkt_buf_free_skb(pkt);
 				continue;
 			}
@@ -1753,7 +1735,9 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 			} else {
 				brcmf_dbg(ERROR, "%s: glom superframe w/o "
 					  "descriptor!\n", __func__);
+				sdio_claim_host(bus->sdiodev->func[1]);
 				brcmf_sdbrcm_rxfail(bus, false, false);
+				sdio_release_host(bus->sdiodev->func[1]);
 			}
 			/* prepare the descriptor for the next read */
 			rd->len = rd->len_nxtfrm << 4;
@@ -1784,10 +1768,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 			continue;
 		}
 
-		/* Unlock during rx call */
-		up(&bus->sdsem);
 		brcmf_rx_packet(bus->sdiodev->dev, ifidx, pkt);
-		down(&bus->sdsem);
 	}
 
 	rxcount = maxframes - rxleft;
@@ -1805,15 +1786,6 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 }
 
 static void
-brcmf_sdbrcm_wait_for_event(struct brcmf_sdio *bus, bool *lockvar)
-{
-	up(&bus->sdsem);
-	wait_event_interruptible_timeout(bus->ctrl_wait, !*lockvar, HZ * 2);
-	down(&bus->sdsem);
-	return;
-}
-
-static void
 brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus)
 {
 	if (waitqueue_active(&bus->ctrl_wait))
@@ -1914,6 +1886,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
 	if (len & (ALIGNMENT - 1))
 			len = roundup(len, ALIGNMENT);
 
+	sdio_claim_host(bus->sdiodev->func[1]);
 	ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad,
 				    SDIO_FUNC_2, F2SYNC, pkt);
 	bus->sdcnt.f2txdata++;
@@ -1941,15 +1914,14 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
 		}
 
 	}
+	sdio_release_host(bus->sdiodev->func[1]);
 	if (ret == 0)
 		bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
 
 done:
 	/* restore pkt buffer pointer before calling tx complete routine */
 	skb_pull(pkt, SDPCM_HDRLEN + pad);
-	up(&bus->sdsem);
 	brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0);
-	down(&bus->sdsem);
 
 	if (free_pkt)
 		brcmu_pkt_buf_free_skb(pkt);
@@ -1990,9 +1962,11 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
 		/* In poll mode, need to check for other events */
 		if (!bus->intr && cnt) {
 			/* Check device status, signal pending interrupt */
+			sdio_claim_host(bus->sdiodev->func[1]);
 			ret = r_sdreg32(bus, &intstatus,
 					offsetof(struct sdpcmd_regs,
 						 intstatus));
+			sdio_release_host(bus->sdiodev->func[1]);
 			bus->sdcnt.f2txdata++;
 			if (ret != 0)
 				break;
@@ -2029,7 +2003,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
 		bus->watchdog_tsk = NULL;
 	}
 
-	down(&bus->sdsem);
+	sdio_claim_host(bus->sdiodev->func[1]);
 
 	/* Enable clock for device interrupts */
 	brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
@@ -2063,6 +2037,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
 
 	/* Turn off the backplane clock (only) */
 	brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
+	sdio_release_host(bus->sdiodev->func[1]);
 
 	/* Clear the data packet queues */
 	brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
@@ -2073,14 +2048,14 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
 	brcmf_sdbrcm_free_glom(bus);
 
 	/* Clear rx control and wake any waiters */
+	spin_lock_bh(&bus->rxctl_lock);
 	bus->rxlen = 0;
+	spin_unlock_bh(&bus->rxctl_lock);
 	brcmf_sdbrcm_dcmd_resp_wake(bus);
 
 	/* Reset some F2 state stuff */
 	bus->rxskip = false;
 	bus->tx_seq = bus->rx_seq = 0;
-
-	up(&bus->sdsem);
 }
 
 #ifdef CONFIG_BRCMFMAC_SDIO_OOB
@@ -2164,7 +2139,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
 
 	brcmf_dbg(TRACE, "Enter\n");
 
-	down(&bus->sdsem);
+	sdio_claim_host(bus->sdiodev->func[1]);
 
 	/* If waiting for HTAVAIL, check status */
 	if (bus->clkstate == CLK_PENDING) {
@@ -2218,9 +2193,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
 	/* Pending interrupt indicates new device status */
 	if (atomic_read(&bus->ipend) > 0) {
 		atomic_set(&bus->ipend, 0);
-		sdio_claim_host(bus->sdiodev->func[1]);
 		err = brcmf_sdio_intr_rstatus(bus);
-		sdio_release_host(bus->sdiodev->func[1]);
 	}
 
 	/* Start with leftover status bits */
@@ -2249,6 +2222,8 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
 		intstatus |= brcmf_sdbrcm_hostmail(bus);
 	}
 
+	sdio_release_host(bus->sdiodev->func[1]);
+
 	/* Generally don't ask for these, can get CRC errors... */
 	if (intstatus & I_WR_OOSYNC) {
 		brcmf_dbg(ERROR, "Dongle reports WR_OOSYNC\n");
@@ -2295,6 +2270,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
 		(bus->clkstate == CLK_AVAIL)) {
 		int i;
 
+		sdio_claim_host(bus->sdiodev->func[1]);
 		err = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad,
 			SDIO_FUNC_2, F2SYNC, bus->ctrl_frame_buf,
 			(u32) bus->ctrl_frame_len);
@@ -2328,6 +2304,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
 		} else {
 			bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
 		}
+		sdio_release_host(bus->sdiodev->func[1]);
 		bus->ctrl_frame_stat = false;
 		brcmf_sdbrcm_wait_event_wakeup(bus);
 	}
@@ -2357,10 +2334,10 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
 	if ((bus->clkstate != CLK_PENDING)
 	    && bus->idletime == BRCMF_IDLE_IMMEDIATE) {
 		bus->activity = false;
+		sdio_claim_host(bus->sdiodev->func[1]);
 		brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+		sdio_release_host(bus->sdiodev->func[1]);
 	}
-
-	up(&bus->sdsem);
 }
 
 static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
@@ -2651,11 +2628,10 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
 
 	/* precondition: IS_ALIGNED((unsigned long)frame, 2) */
 
-	/* Need to lock here to protect txseq and SDIO tx calls */
-	down(&bus->sdsem);
-
 	/* Make sure backplane clock is on */
+	sdio_claim_host(bus->sdiodev->func[1]);
 	brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+	sdio_release_host(bus->sdiodev->func[1]);
 
 	/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
 	*(__le16 *) frame = cpu_to_le16((u16) msglen);
@@ -2678,7 +2654,9 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
 		bus->ctrl_frame_buf = frame;
 		bus->ctrl_frame_len = len;
 
-		brcmf_sdbrcm_wait_for_event(bus, &bus->ctrl_frame_stat);
+		wait_event_interruptible_timeout(bus->ctrl_wait,
+						 !bus->ctrl_frame_stat,
+						 msecs_to_jiffies(2000));
 
 		if (!bus->ctrl_frame_stat) {
 			brcmf_dbg(INFO, "ctrl_frame_stat == false\n");
@@ -2697,7 +2675,9 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
 				   frame, min_t(u16, len, 16), "TxHdr:\n");
 
 		do {
+			sdio_claim_host(bus->sdiodev->func[1]);
 			ret = brcmf_tx_frame(bus, frame, len);
+			sdio_release_host(bus->sdiodev->func[1]);
 		} while (ret < 0 && retries++ < TXRETRIES);
 	}
 
@@ -2707,13 +2687,13 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
 		spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
 
 		bus->activity = false;
+		sdio_claim_host(bus->sdiodev->func[1]);
 		brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
+		sdio_release_host(bus->sdiodev->func[1]);
 	} else {
 		spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
 	}
 
-	up(&bus->sdsem);
-
 	if (ret)
 		bus->sdcnt.tx_ctlerrs++;
 	else
@@ -2743,8 +2723,10 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
 	 * Read last word in socram to determine
 	 * address of sdpcm_shared structure
 	 */
+	sdio_claim_host(bus->sdiodev->func[1]);
 	rv = brcmf_sdbrcm_membytes(bus, false, shaddr,
 				   (u8 *)&addr_le, 4);
+	sdio_claim_host(bus->sdiodev->func[1]);
 	if (rv < 0)
 		return rv;
 
@@ -2763,8 +2745,10 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
 	}
 
 	/* Read hndrte_shared structure */
+	sdio_claim_host(bus->sdiodev->func[1]);
 	rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le,
 				   sizeof(struct sdpcm_shared_le));
+	sdio_release_host(bus->sdiodev->func[1]);
 	if (rv < 0)
 		return rv;
 
@@ -2867,12 +2851,14 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
 	if ((sh->flags & SDPCM_SHARED_TRAP) == 0)
 		return 0;
 
+	sdio_claim_host(bus->sdiodev->func[1]);
 	error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
 				      sizeof(struct brcmf_trap_info));
 	if (error < 0)
 		return error;
 
 	nbytes = brcmf_sdio_dump_console(bus, sh, data, count);
+	sdio_release_host(bus->sdiodev->func[1]);
 	if (nbytes < 0)
 		return nbytes;
 
@@ -2918,6 +2904,7 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
 		return 0;
 	}
 
+	sdio_claim_host(bus->sdiodev->func[1]);
 	if (sh->assert_file_addr != 0) {
 		error = brcmf_sdbrcm_membytes(bus, false, sh->assert_file_addr,
 					      (u8 *)file, 80);
@@ -2930,6 +2917,7 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
 		if (error < 0)
 			return error;
 	}
+	sdio_release_host(bus->sdiodev->func[1]);
 
 	res = scnprintf(buf, sizeof(buf),
 			"dongle assert: %s:%d: assert(%s)\n",
@@ -2942,9 +2930,7 @@ static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus)
 	int error;
 	struct sdpcm_shared sh;
 
-	down(&bus->sdsem);
 	error = brcmf_sdio_readshared(bus, &sh);
-	up(&bus->sdsem);
 
 	if (error < 0)
 		return error;
@@ -2971,7 +2957,6 @@ static int brcmf_sdbrcm_died_dump(struct brcmf_sdio *bus, char __user *data,
 	if (pos != 0)
 		return 0;
 
-	down(&bus->sdsem);
 	error = brcmf_sdio_readshared(bus, &sh);
 	if (error < 0)
 		goto done;
@@ -2988,7 +2973,6 @@ static int brcmf_sdbrcm_died_dump(struct brcmf_sdio *bus, char __user *data,
 	error += nbytes;
 	*ppos += error;
 done:
-	up(&bus->sdsem);
 	return error;
 }
 
@@ -3039,6 +3023,7 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
 	int timeleft;
 	uint rxlen = 0;
 	bool pending;
+	u8 *buf;
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
 	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
 	struct brcmf_sdio *bus = sdiodev->bus;
@@ -3048,11 +3033,15 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
 	/* Wait until control frame is available */
 	timeleft = brcmf_sdbrcm_dcmd_resp_wait(bus, &bus->rxlen, &pending);
 
-	down(&bus->sdsem);
+	spin_lock_bh(&bus->rxctl_lock);
 	rxlen = bus->rxlen;
 	memcpy(msg, bus->rxctl, min(msglen, rxlen));
+	bus->rxctl = NULL;
+	buf = bus->rxctl_orig;
+	bus->rxctl_orig = NULL;
 	bus->rxlen = 0;
-	up(&bus->sdsem);
+	spin_unlock_bh(&bus->rxctl_lock);
+	vfree(buf);
 
 	if (rxlen) {
 		brcmf_dbg(CTL, "resumed on rxctl frame, got %d expected %d\n",
@@ -3388,13 +3377,16 @@ brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
 {
 	bool ret;
 
-	/* Download the firmware */
+	sdio_claim_host(bus->sdiodev->func[1]);
+
 	brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
 
 	ret = _brcmf_sdbrcm_download_firmware(bus) == 0;
 
 	brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
 
+	sdio_release_host(bus->sdiodev->func[1]);
+
 	return ret;
 }
 
@@ -3423,7 +3415,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
 	bus->sdcnt.tickcnt = 0;
 	brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
 
-	down(&bus->sdsem);
+	sdio_claim_host(bus->sdiodev->func[1]);
 
 	/* Make sure backplane clock is on, needed to generate F2 interrupt */
 	brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
@@ -3492,7 +3484,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
 		brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
 
 exit:
-	up(&bus->sdsem);
+	sdio_release_host(bus->sdiodev->func[1]);
 
 	return ret;
 }
@@ -3539,8 +3531,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
 
 	brcmf_dbg(TIMER, "Enter\n");
 
-	down(&bus->sdsem);
-
 	/* Poll period: check device if appropriate. */
 	if (bus->poll && (++bus->polltick >= bus->pollrate)) {
 		u32 intstatus = 0;
@@ -3557,9 +3547,11 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
 				u8 devpend;
 				spin_unlock_irqrestore(&bus->dpc_tl_lock,
 						       flags);
+				sdio_claim_host(bus->sdiodev->func[1]);
 				devpend = brcmf_sdio_regrb(bus->sdiodev,
 							   SDIO_CCCR_INTx,
 							   NULL);
+				sdio_release_host(bus->sdiodev->func[1]);
 				intstatus =
 				    devpend & (INTR_STATUS_FUNC1 |
 					       INTR_STATUS_FUNC2);
@@ -3584,16 +3576,18 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
 	}
 #ifdef DEBUG
 	/* Poll for console output periodically */
-	if (bus_if->state == BRCMF_BUS_DATA &&
+	if (bus_if && bus_if->state == BRCMF_BUS_DATA &&
 	    bus->console_interval != 0) {
 		bus->console.count += BRCMF_WD_POLL_MS;
 		if (bus->console.count >= bus->console_interval) {
 			bus->console.count -= bus->console_interval;
+			sdio_claim_host(bus->sdiodev->func[1]);
 			/* Make sure backplane clock is on */
 			brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
 			if (brcmf_sdbrcm_readconsole(bus) < 0)
 				/* stop on error */
 				bus->console_interval = 0;
+			sdio_release_host(bus->sdiodev->func[1]);
 		}
 	}
 #endif				/* DEBUG */
@@ -3606,13 +3600,13 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
 				bus->activity = false;
 				brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
 			} else {
+				sdio_claim_host(bus->sdiodev->func[1]);
 				brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+				sdio_release_host(bus->sdiodev->func[1]);
 			}
 		}
 	}
 
-	up(&bus->sdsem);
-
 	return (atomic_read(&bus->ipend) > 0);
 }
 
@@ -3707,6 +3701,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
 
 	bus->alp_only = true;
 
+	sdio_claim_host(bus->sdiodev->func[1]);
+
 	pr_debug("F1 signature read @0x18000000=0x%4x\n",
 		 brcmf_sdio_regrl(bus->sdiodev, SI_ENUM_BASE, NULL));
 
@@ -3754,6 +3750,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
 	reg_val = brcmf_sdio_regrl(bus->sdiodev, reg_addr, NULL);
 	brcmf_sdio_regwl(bus->sdiodev, reg_addr, reg_val | CC_BPRESEN, NULL);
 
+	sdio_release_host(bus->sdiodev->func[1]);
+
 	brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
 
 	/* Locate an appropriately-aligned portion of hdrbuf */
@@ -3769,6 +3767,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
 	return true;
 
 fail:
+	sdio_release_host(bus->sdiodev->func[1]);
 	return false;
 }
 
@@ -3776,6 +3775,8 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
 {
 	brcmf_dbg(TRACE, "Enter\n");
 
+	sdio_claim_host(bus->sdiodev->func[1]);
+
 	/* Disable F2 to clear any intermediate frame state on the dongle */
 	brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx,
 			 SDIO_FUNC_ENABLE_1, NULL);
@@ -3786,6 +3787,8 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
 	/* Done with backplane-dependent accesses, can drop clock... */
 	brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
 
+	sdio_release_host(bus->sdiodev->func[1]);
+
 	/* ...and initialize clock/power states */
 	bus->clkstate = CLK_SDONLY;
 	bus->idletime = BRCMF_IDLE_INTERVAL;
@@ -3841,8 +3844,10 @@ static void brcmf_sdbrcm_release_dongle(struct brcmf_sdio *bus)
 	brcmf_dbg(TRACE, "Enter\n");
 
 	if (bus->ci) {
+		sdio_claim_host(bus->sdiodev->func[1]);
 		brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
 		brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+		sdio_release_host(bus->sdiodev->func[1]);
 		brcmf_sdio_chip_detach(&bus->ci);
 		if (bus->vars && bus->varsz)
 			kfree(bus->vars);
@@ -3862,7 +3867,8 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus)
 		brcmf_sdio_intr_unregister(bus->sdiodev);
 
 		cancel_work_sync(&bus->datawork);
-		destroy_workqueue(bus->brcmf_wq);
+		if (bus->brcmf_wq)
+			destroy_workqueue(bus->brcmf_wq);
 
 		if (bus->sdiodev->bus_if->drvr) {
 			brcmf_detach(bus->sdiodev->dev);
@@ -3904,31 +3910,29 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
 	bus->txminmax = BRCMF_TXMINMAX;
 	bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
 
+	INIT_WORK(&bus->datawork, brcmf_sdio_dataworker);
+	bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq");
+	if (bus->brcmf_wq == NULL) {
+		brcmf_dbg(ERROR, "insufficient memory to create txworkqueue\n");
+		goto fail;
+	}
+
 	/* attempt to attach to the dongle */
 	if (!(brcmf_sdbrcm_probe_attach(bus, regsva))) {
 		brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_attach failed\n");
 		goto fail;
 	}
 
+	spin_lock_init(&bus->rxctl_lock);
 	spin_lock_init(&bus->txqlock);
 	init_waitqueue_head(&bus->ctrl_wait);
 	init_waitqueue_head(&bus->dcmd_resp_wait);
 
-	bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq");
-	if (bus->brcmf_wq == NULL) {
-		brcmf_dbg(ERROR, "insufficient memory to create txworkqueue\n");
-		goto fail;
-	}
-	INIT_WORK(&bus->datawork, brcmf_sdio_dataworker);
-
 	/* Set up the watchdog timer */
 	init_timer(&bus->timer);
 	bus->timer.data = (unsigned long)bus;
 	bus->timer.function = brcmf_sdbrcm_watchdog;
 
-	/* Initialize thread based operation and lock */
-	sema_init(&bus->sdsem, 1);
-
 	/* Initialize watchdog thread */
 	init_completion(&bus->watchdog_wait);
 	bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread,
@@ -3991,10 +3995,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
 	/* if firmware path present try to download and bring up bus */
 	ret = brcmf_bus_start(bus->sdiodev->dev);
 	if (ret != 0) {
-		if (ret == -ENOLINK) {
-			brcmf_dbg(ERROR, "dongle is not responding\n");
-			goto fail;
-		}
+		brcmf_dbg(ERROR, "dongle is not responding\n");
+		goto fail;
 	}
 
 	return bus;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
new file mode 100644
index 0000000..fa8fc44
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/netdevice.h>
+
+#include "brcmu_wifi.h"
+#include "brcmu_utils.h"
+
+#include "dhd.h"
+#include "dhd_dbg.h"
+#include "fweh.h"
+#include "fwil.h"
+
+/**
+ * struct brcm_ethhdr - broadcom specific ether header.
+ *
+ * @subtype: subtype for this packet.
+ * @length: TODO: length of appended data.
+ * @version: version indication.
+ * @oui: OUI of this packet.
+ * @usr_subtype: subtype for this OUI.
+ */
+struct brcm_ethhdr {
+	__be16 subtype;
+	__be16 length;
+	u8 version;
+	u8 oui[3];
+	__be16 usr_subtype;
+} __packed;
+
+struct brcmf_event_msg_be {
+	__be16 version;
+	__be16 flags;
+	__be32 event_type;
+	__be32 status;
+	__be32 reason;
+	__be32 auth_type;
+	__be32 datalen;
+	u8 addr[ETH_ALEN];
+	char ifname[IFNAMSIZ];
+	u8 ifidx;
+	u8 bsscfgidx;
+} __packed;
+
+/**
+ * struct brcmf_event - contents of broadcom event packet.
+ *
+ * @eth: standard ether header.
+ * @hdr: broadcom specific ether header.
+ * @msg: common part of the actual event message.
+ */
+struct brcmf_event {
+	struct ethhdr eth;
+	struct brcm_ethhdr hdr;
+	struct brcmf_event_msg_be msg;
+} __packed;
+
+/**
+ * struct brcmf_fweh_queue_item - event item on event queue.
+ *
+ * @q: list element for queuing.
+ * @code: event code.
+ * @ifidx: interface index related to this event.
+ * @ifaddr: ethernet address for interface.
+ * @emsg: common parameters of the firmware event message.
+ * @data: event specific data part of the firmware event.
+ */
+struct brcmf_fweh_queue_item {
+	struct list_head q;
+	enum brcmf_fweh_event_code code;
+	u8 ifidx;
+	u8 ifaddr[ETH_ALEN];
+	struct brcmf_event_msg_be emsg;
+	u8 data[0];
+};
+
+/**
+ * struct brcmf_fweh_event_name - code, name mapping entry.
+ */
+struct brcmf_fweh_event_name {
+	enum brcmf_fweh_event_code code;
+	const char *name;
+};
+
+#ifdef DEBUG
+/* array for mapping code to event name */
+static struct brcmf_fweh_event_name fweh_event_names[] = {
+	{ BRCMF_E_SET_SSID, "SET_SSID" },
+	{ BRCMF_E_JOIN, "JOIN" },
+	{ BRCMF_E_START, "START" },
+	{ BRCMF_E_AUTH, "AUTH" },
+	{ BRCMF_E_AUTH_IND, "AUTH_IND" },
+	{ BRCMF_E_DEAUTH, "DEAUTH" },
+	{ BRCMF_E_DEAUTH_IND, "DEAUTH_IND" },
+	{ BRCMF_E_ASSOC, "ASSOC" },
+	{ BRCMF_E_ASSOC_IND, "ASSOC_IND" },
+	{ BRCMF_E_REASSOC, "REASSOC" },
+	{ BRCMF_E_REASSOC_IND, "REASSOC_IND" },
+	{ BRCMF_E_DISASSOC, "DISASSOC" },
+	{ BRCMF_E_DISASSOC_IND, "DISASSOC_IND" },
+	{ BRCMF_E_QUIET_START, "START_QUIET" },
+	{ BRCMF_E_QUIET_END, "END_QUIET" },
+	{ BRCMF_E_BEACON_RX, "BEACON_RX" },
+	{ BRCMF_E_LINK, "LINK" },
+	{ BRCMF_E_MIC_ERROR, "MIC_ERROR" },
+	{ BRCMF_E_NDIS_LINK, "NDIS_LINK" },
+	{ BRCMF_E_ROAM, "ROAM" },
+	{ BRCMF_E_TXFAIL, "TXFAIL" },
+	{ BRCMF_E_PMKID_CACHE, "PMKID_CACHE" },
+	{ BRCMF_E_RETROGRADE_TSF, "RETROGRADE_TSF" },
+	{ BRCMF_E_PRUNE, "PRUNE" },
+	{ BRCMF_E_AUTOAUTH, "AUTOAUTH" },
+	{ BRCMF_E_EAPOL_MSG, "EAPOL_MSG" },
+	{ BRCMF_E_SCAN_COMPLETE, "SCAN_COMPLETE" },
+	{ BRCMF_E_ADDTS_IND, "ADDTS_IND" },
+	{ BRCMF_E_DELTS_IND, "DELTS_IND" },
+	{ BRCMF_E_BCNSENT_IND, "BCNSENT_IND" },
+	{ BRCMF_E_BCNRX_MSG, "BCNRX_MSG" },
+	{ BRCMF_E_BCNLOST_MSG, "BCNLOST_MSG" },
+	{ BRCMF_E_ROAM_PREP, "ROAM_PREP" },
+	{ BRCMF_E_PFN_NET_FOUND, "PNO_NET_FOUND" },
+	{ BRCMF_E_PFN_NET_LOST, "PNO_NET_LOST" },
+	{ BRCMF_E_RESET_COMPLETE, "RESET_COMPLETE" },
+	{ BRCMF_E_JOIN_START, "JOIN_START" },
+	{ BRCMF_E_ROAM_START, "ROAM_START" },
+	{ BRCMF_E_ASSOC_START, "ASSOC_START" },
+	{ BRCMF_E_IBSS_ASSOC, "IBSS_ASSOC" },
+	{ BRCMF_E_RADIO, "RADIO" },
+	{ BRCMF_E_PSM_WATCHDOG, "PSM_WATCHDOG" },
+	{ BRCMF_E_PROBREQ_MSG, "PROBREQ_MSG" },
+	{ BRCMF_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND" },
+	{ BRCMF_E_PSK_SUP, "PSK_SUP" },
+	{ BRCMF_E_COUNTRY_CODE_CHANGED, "COUNTRY_CODE_CHANGED" },
+	{ BRCMF_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME" },
+	{ BRCMF_E_ICV_ERROR, "ICV_ERROR" },
+	{ BRCMF_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR" },
+	{ BRCMF_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR" },
+	{ BRCMF_E_TRACE, "TRACE" },
+	{ BRCMF_E_IF, "IF" },
+	{ BRCMF_E_RSSI, "RSSI" },
+	{ BRCMF_E_PFN_SCAN_COMPLETE, "PFN_SCAN_COMPLETE" },
+	{ BRCMF_E_EXTLOG_MSG, "EXTLOG_MSG" },
+	{ BRCMF_E_ACTION_FRAME, "ACTION_FRAME" },
+	{ BRCMF_E_ACTION_FRAME_COMPLETE, "ACTION_FRAME_COMPLETE" },
+	{ BRCMF_E_PRE_ASSOC_IND, "PRE_ASSOC_IND" },
+	{ BRCMF_E_PRE_REASSOC_IND, "PRE_REASSOC_IND" },
+	{ BRCMF_E_CHANNEL_ADOPTED, "CHANNEL_ADOPTED" },
+	{ BRCMF_E_AP_STARTED, "AP_STARTED" },
+	{ BRCMF_E_DFS_AP_STOP, "DFS_AP_STOP" },
+	{ BRCMF_E_DFS_AP_RESUME, "DFS_AP_RESUME" },
+	{ BRCMF_E_ESCAN_RESULT, "ESCAN_RESULT" },
+	{ BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE, "ACTION_FRM_OFF_CHAN_CMPLT" },
+	{ BRCMF_E_DCS_REQUEST, "DCS_REQUEST" },
+	{ BRCMF_E_FIFO_CREDIT_MAP, "FIFO_CREDIT_MAP"}
+};
+
+/**
+ * brcmf_fweh_event_name() - returns name for given event code.
+ *
+ * @code: code to lookup.
+ */
+static const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(fweh_event_names); i++) {
+		if (fweh_event_names[i].code == code)
+			return fweh_event_names[i].name;
+	}
+	return "unknown";
+}
+#else
+static const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
+{
+	return "nodebug";
+}
+#endif
+
+/**
+ * brcmf_fweh_queue_event() - create and queue event.
+ *
+ * @fweh: firmware event handling info.
+ * @event: event queue entry.
+ */
+static void brcmf_fweh_queue_event(struct brcmf_fweh_info *fweh,
+				   struct brcmf_fweh_queue_item *event)
+{
+	ulong flags;
+
+	spin_lock_irqsave(&fweh->evt_q_lock, flags);
+	list_add_tail(&event->q, &fweh->event_q);
+	spin_unlock_irqrestore(&fweh->evt_q_lock, flags);
+	schedule_work(&fweh->event_work);
+}
+
+static int brcmf_fweh_call_event_handler(struct brcmf_if *ifp,
+					 enum brcmf_fweh_event_code code,
+					 struct brcmf_event_msg *emsg,
+					 void *data)
+{
+	struct brcmf_fweh_info *fweh;
+	int err = -EINVAL;
+
+	if (ifp) {
+		fweh = &ifp->drvr->fweh;
+
+		/* handle the event if valid interface and handler */
+		if (ifp->ndev && fweh->evt_handler[code])
+			err = fweh->evt_handler[code](ifp, emsg, data);
+		else
+			brcmf_dbg(ERROR, "unhandled event %d ignored\n", code);
+	} else {
+		brcmf_dbg(ERROR, "no interface object\n");
+	}
+	return err;
+}
+
+/**
+ * brcmf_fweh_handle_if_event() - handle IF event.
+ *
+ * @drvr: driver information object.
+ * @item: queue entry.
+ * @ifpp: interface object (may change upon ADD action).
+ */
+static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
+				       struct brcmf_event_msg *emsg,
+				       void *data)
+{
+	struct brcmf_if_event *ifevent = data;
+	struct brcmf_if *ifp;
+	int err = 0;
+
+	brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u\n",
+		  ifevent->action, ifevent->ifidx,
+		  ifevent->bssidx, ifevent->flags);
+
+	if (ifevent->ifidx >= BRCMF_MAX_IFS) {
+		brcmf_dbg(ERROR, "invalid interface index: %u\n",
+			  ifevent->ifidx);
+		return;
+	}
+
+	ifp = drvr->iflist[ifevent->ifidx];
+
+	if (ifevent->action == BRCMF_E_IF_ADD) {
+		brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
+			  emsg->addr);
+		ifp = brcmf_add_if(drvr, ifevent->ifidx, ifevent->bssidx,
+				   emsg->ifname, emsg->addr);
+		if (IS_ERR(ifp))
+			return;
+
+		if (!drvr->fweh.evt_handler[BRCMF_E_IF])
+			err = brcmf_net_attach(ifp);
+	}
+
+	err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
+
+	if (ifevent->action == BRCMF_E_IF_DEL)
+		brcmf_del_if(drvr, ifevent->ifidx);
+}
+
+/**
+ * brcmf_fweh_dequeue_event() - get event from the queue.
+ *
+ * @fweh: firmware event handling info.
+ */
+static struct brcmf_fweh_queue_item *
+brcmf_fweh_dequeue_event(struct brcmf_fweh_info *fweh)
+{
+	struct brcmf_fweh_queue_item *event = NULL;
+	ulong flags;
+
+	spin_lock_irqsave(&fweh->evt_q_lock, flags);
+	if (!list_empty(&fweh->event_q)) {
+		event = list_first_entry(&fweh->event_q,
+					 struct brcmf_fweh_queue_item, q);
+		list_del(&event->q);
+	}
+	spin_unlock_irqrestore(&fweh->evt_q_lock, flags);
+
+	return event;
+}
+
+/**
+ * brcmf_fweh_event_worker() - firmware event worker.
+ *
+ * @work: worker object.
+ */
+static void brcmf_fweh_event_worker(struct work_struct *work)
+{
+	struct brcmf_pub *drvr;
+	struct brcmf_if *ifp;
+	struct brcmf_fweh_info *fweh;
+	struct brcmf_fweh_queue_item *event;
+	int err = 0;
+	struct brcmf_event_msg_be *emsg_be;
+	struct brcmf_event_msg emsg;
+
+	fweh = container_of(work, struct brcmf_fweh_info, event_work);
+	drvr = container_of(fweh, struct brcmf_pub, fweh);
+
+	while ((event = brcmf_fweh_dequeue_event(fweh))) {
+		ifp = drvr->iflist[event->ifidx];
+
+		brcmf_dbg(EVENT, "event %s (%u) ifidx %u bsscfg %u addr %pM:\n",
+			  brcmf_fweh_event_name(event->code), event->code,
+			  event->emsg.ifidx, event->emsg.bsscfgidx,
+			  event->emsg.addr);
+
+		/* convert event message */
+		emsg_be = &event->emsg;
+		emsg.version = be16_to_cpu(emsg_be->version);
+		emsg.flags = be16_to_cpu(emsg_be->flags);
+		emsg.event_code = event->code;
+		emsg.status = be32_to_cpu(emsg_be->status);
+		emsg.reason = be32_to_cpu(emsg_be->reason);
+		emsg.auth_type = be32_to_cpu(emsg_be->auth_type);
+		emsg.datalen = be32_to_cpu(emsg_be->datalen);
+		memcpy(emsg.addr, emsg_be->addr, ETH_ALEN);
+		memcpy(emsg.ifname, emsg_be->ifname, sizeof(emsg.ifname));
+		emsg.ifidx = emsg_be->ifidx;
+		emsg.bsscfgidx = emsg_be->bsscfgidx;
+
+		brcmf_dbg(EVENT, "  version %u flags %u status %u reason %u\n",
+			  emsg.version, emsg.flags, emsg.status, emsg.reason);
+		brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), event->data,
+				   min_t(u32, emsg.datalen, 64),
+				   "appended:");
+
+		/* special handling of interface event */
+		if (event->code == BRCMF_E_IF) {
+			brcmf_fweh_handle_if_event(drvr, &emsg, event->data);
+			goto event_free;
+		}
+
+		err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
+						    event->data);
+		if (err) {
+			brcmf_dbg(ERROR, "event handler failed (%d)\n",
+				  event->code);
+			err = 0;
+		}
+event_free:
+		kfree(event);
+	}
+}
+
+/**
+ * brcmf_fweh_attach() - initialize firmware event handling.
+ *
+ * @drvr: driver information object.
+ */
+void brcmf_fweh_attach(struct brcmf_pub *drvr)
+{
+	struct brcmf_fweh_info *fweh = &drvr->fweh;
+	INIT_WORK(&fweh->event_work, brcmf_fweh_event_worker);
+	spin_lock_init(&fweh->evt_q_lock);
+	INIT_LIST_HEAD(&fweh->event_q);
+}
+
+/**
+ * brcmf_fweh_detach() - cleanup firmware event handling.
+ *
+ * @drvr: driver information object.
+ */
+void brcmf_fweh_detach(struct brcmf_pub *drvr)
+{
+	struct brcmf_fweh_info *fweh = &drvr->fweh;
+	struct brcmf_if *ifp = drvr->iflist[0];
+	s8 eventmask[BRCMF_EVENTING_MASK_LEN];
+
+	if (ifp) {
+		/* clear all events */
+		memset(eventmask, 0, BRCMF_EVENTING_MASK_LEN);
+		(void)brcmf_fil_iovar_data_set(ifp, "event_msgs",
+					       eventmask,
+					       BRCMF_EVENTING_MASK_LEN);
+	}
+	/* cancel the worker */
+	cancel_work_sync(&fweh->event_work);
+	WARN_ON(!list_empty(&fweh->event_q));
+	memset(fweh->evt_handler, 0, sizeof(fweh->evt_handler));
+}
+
+/**
+ * brcmf_fweh_register() - register handler for given event code.
+ *
+ * @drvr: driver information object.
+ * @code: event code.
+ * @handler: handler for the given event code.
+ */
+int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code,
+			brcmf_fweh_handler_t handler)
+{
+	if (drvr->fweh.evt_handler[code]) {
+		brcmf_dbg(ERROR, "event code %d already registered\n", code);
+		return -ENOSPC;
+	}
+	drvr->fweh.evt_handler[code] = handler;
+	brcmf_dbg(TRACE, "event handler registered for %s\n",
+		  brcmf_fweh_event_name(code));
+	return 0;
+}
+
+/**
+ * brcmf_fweh_unregister() - remove handler for given code.
+ *
+ * @drvr: driver information object.
+ * @code: event code.
+ */
+void brcmf_fweh_unregister(struct brcmf_pub *drvr,
+			   enum brcmf_fweh_event_code code)
+{
+	brcmf_dbg(TRACE, "event handler cleared for %s\n",
+		  brcmf_fweh_event_name(code));
+	drvr->fweh.evt_handler[code] = NULL;
+}
+
+/**
+ * brcmf_fweh_activate_events() - enables firmware events registered.
+ *
+ * @ifp: primary interface object.
+ */
+int brcmf_fweh_activate_events(struct brcmf_if *ifp)
+{
+	int i, err;
+	s8 eventmask[BRCMF_EVENTING_MASK_LEN];
+
+	for (i = 0; i < BRCMF_E_LAST; i++) {
+		if (ifp->drvr->fweh.evt_handler[i]) {
+			brcmf_dbg(EVENT, "enable event %s\n",
+				  brcmf_fweh_event_name(i));
+			setbit(eventmask, i);
+		}
+	}
+
+	/* want to handle IF event as well */
+	brcmf_dbg(EVENT, "enable event IF\n");
+	setbit(eventmask, BRCMF_E_IF);
+
+	err = brcmf_fil_iovar_data_set(ifp, "event_msgs",
+				       eventmask, BRCMF_EVENTING_MASK_LEN);
+	if (err)
+		brcmf_dbg(ERROR, "Set event_msgs error (%d)\n", err);
+
+	return err;
+}
+
+/**
+ * brcmf_fweh_process_event() - process skb as firmware event.
+ *
+ * @drvr: driver information object.
+ * @event_packet: event packet to process.
+ * @ifidx: index of the firmware interface (may change).
+ *
+ * If the packet buffer contains a firmware event message it will
+ * dispatch the event to a registered handler (using worker).
+ */
+void brcmf_fweh_process_event(struct brcmf_pub *drvr,
+			      struct brcmf_event *event_packet, u8 *ifidx)
+{
+	enum brcmf_fweh_event_code code;
+	struct brcmf_fweh_info *fweh = &drvr->fweh;
+	struct brcmf_fweh_queue_item *event;
+	gfp_t alloc_flag = GFP_KERNEL;
+	void *data;
+	u32 datalen;
+
+	/* get event info */
+	code = get_unaligned_be32(&event_packet->msg.event_type);
+	datalen = get_unaligned_be32(&event_packet->msg.datalen);
+	*ifidx = event_packet->msg.ifidx;
+	data = &event_packet[1];
+
+	if (code >= BRCMF_E_LAST)
+		return;
+
+	if (code != BRCMF_E_IF && !fweh->evt_handler[code])
+		return;
+
+	if (in_interrupt())
+		alloc_flag = GFP_ATOMIC;
+
+	event = kzalloc(sizeof(*event) + datalen, alloc_flag);
+	if (!event)
+		return;
+
+	event->code = code;
+	event->ifidx = *ifidx;
+
+	/* use memcpy to get aligned event message */
+	memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg));
+	memcpy(event->data, data, datalen);
+	memcpy(event->ifaddr, event_packet->eth.h_dest, ETH_ALEN);
+
+	brcmf_fweh_queue_event(fweh, event);
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
new file mode 100644
index 0000000..b39246a
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef FWEH_H_
+#define FWEH_H_
+
+#include <asm/unaligned.h>
+#include <linux/skbuff.h>
+#include <linux/if_ether.h>
+#include <linux/if.h>
+
+/* formward declarations */
+struct brcmf_pub;
+struct brcmf_if;
+struct brcmf_cfg80211_info;
+struct brcmf_event;
+
+/* firmware event codes sent by the dongle */
+enum brcmf_fweh_event_code {
+	BRCMF_E_SET_SSID		= 0,
+	BRCMF_E_JOIN			= 1,
+	BRCMF_E_START			= 2,
+	BRCMF_E_AUTH			= 3,
+	BRCMF_E_AUTH_IND		= 4,
+	BRCMF_E_DEAUTH			= 5,
+	BRCMF_E_DEAUTH_IND		= 6,
+	BRCMF_E_ASSOC			= 7,
+	BRCMF_E_ASSOC_IND		= 8,
+	BRCMF_E_REASSOC			= 9,
+	BRCMF_E_REASSOC_IND		= 10,
+	BRCMF_E_DISASSOC		= 11,
+	BRCMF_E_DISASSOC_IND		= 12,
+	BRCMF_E_QUIET_START		= 13,
+	BRCMF_E_QUIET_END		= 14,
+	BRCMF_E_BEACON_RX		= 15,
+	BRCMF_E_LINK			= 16,
+	BRCMF_E_MIC_ERROR		= 17,
+	BRCMF_E_NDIS_LINK		= 18,
+	BRCMF_E_ROAM			= 19,
+	BRCMF_E_TXFAIL			= 20,
+	BRCMF_E_PMKID_CACHE		= 21,
+	BRCMF_E_RETROGRADE_TSF		= 22,
+	BRCMF_E_PRUNE			= 23,
+	BRCMF_E_AUTOAUTH		= 24,
+	BRCMF_E_EAPOL_MSG		= 25,
+	BRCMF_E_SCAN_COMPLETE		= 26,
+	BRCMF_E_ADDTS_IND		= 27,
+	BRCMF_E_DELTS_IND		= 28,
+	BRCMF_E_BCNSENT_IND		= 29,
+	BRCMF_E_BCNRX_MSG		= 30,
+	BRCMF_E_BCNLOST_MSG		= 31,
+	BRCMF_E_ROAM_PREP		= 32,
+	BRCMF_E_PFN_NET_FOUND		= 33,
+	BRCMF_E_PFN_NET_LOST		= 34,
+	BRCMF_E_RESET_COMPLETE		= 35,
+	BRCMF_E_JOIN_START		= 36,
+	BRCMF_E_ROAM_START		= 37,
+	BRCMF_E_ASSOC_START		= 38,
+	BRCMF_E_IBSS_ASSOC		= 39,
+	BRCMF_E_RADIO			= 40,
+	BRCMF_E_PSM_WATCHDOG		= 41,
+	BRCMF_E_PROBREQ_MSG		= 44,
+	BRCMF_E_SCAN_CONFIRM_IND	= 45,
+	BRCMF_E_PSK_SUP			= 46,
+	BRCMF_E_COUNTRY_CODE_CHANGED	= 47,
+	BRCMF_E_EXCEEDED_MEDIUM_TIME	= 48,
+	BRCMF_E_ICV_ERROR		= 49,
+	BRCMF_E_UNICAST_DECODE_ERROR	= 50,
+	BRCMF_E_MULTICAST_DECODE_ERROR	= 51,
+	BRCMF_E_TRACE			= 52,
+	BRCMF_E_IF			= 54,
+	BRCMF_E_RSSI			= 56,
+	BRCMF_E_PFN_SCAN_COMPLETE	= 57,
+	BRCMF_E_EXTLOG_MSG		= 58,
+	BRCMF_E_ACTION_FRAME		= 59,
+	BRCMF_E_ACTION_FRAME_COMPLETE	= 60,
+	BRCMF_E_PRE_ASSOC_IND		= 61,
+	BRCMF_E_PRE_REASSOC_IND		= 62,
+	BRCMF_E_CHANNEL_ADOPTED		= 63,
+	BRCMF_E_AP_STARTED		= 64,
+	BRCMF_E_DFS_AP_STOP		= 65,
+	BRCMF_E_DFS_AP_RESUME		= 66,
+	BRCMF_E_ESCAN_RESULT		= 69,
+	BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE	= 70,
+	BRCMF_E_DCS_REQUEST		= 73,
+	BRCMF_E_FIFO_CREDIT_MAP		= 74,
+	BRCMF_E_LAST
+};
+
+/* flags field values in struct brcmf_event_msg */
+#define BRCMF_EVENT_MSG_LINK		0x01
+#define BRCMF_EVENT_MSG_FLUSHTXQ	0x02
+#define BRCMF_EVENT_MSG_GROUP		0x04
+
+/**
+ * definitions for event packet validation.
+ */
+#define BRCMF_EVENT_OUI_OFFSET		19
+#define BRCM_OUI			"\x00\x10\x18"
+#define DOT11_OUI_LEN			3
+#define BCMILCP_BCM_SUBTYPE_EVENT	1
+
+
+/**
+ * struct brcmf_event_msg - firmware event message.
+ *
+ * @version: version information.
+ * @flags: event flags.
+ * @event_code: firmware event code.
+ * @status: status information.
+ * @reason: reason code.
+ * @auth_type: authentication type.
+ * @datalen: lenght of event data buffer.
+ * @addr: ether address.
+ * @ifname: interface name.
+ * @ifidx: interface index.
+ * @bsscfgidx: bsscfg index.
+ */
+struct brcmf_event_msg {
+	u16 version;
+	u16 flags;
+	u32 event_code;
+	u32 status;
+	u32 reason;
+	s32 auth_type;
+	u32 datalen;
+	u8 addr[ETH_ALEN];
+	char ifname[IFNAMSIZ];
+	u8 ifidx;
+	u8 bsscfgidx;
+};
+
+typedef int (*brcmf_fweh_handler_t)(struct brcmf_if *ifp,
+				    const struct brcmf_event_msg *evtmsg,
+				    void *data);
+
+/**
+ * struct brcmf_fweh_info - firmware event handling information.
+ *
+ * @event_work: event worker.
+ * @evt_q_lock: lock for event queue protection.
+ * @event_q: event queue.
+ * @evt_handler: registered event handlers.
+ */
+struct brcmf_fweh_info {
+	struct work_struct event_work;
+	struct spinlock evt_q_lock;
+	struct list_head event_q;
+	int (*evt_handler[BRCMF_E_LAST])(struct brcmf_if *ifp,
+					 const struct brcmf_event_msg *evtmsg,
+					 void *data);
+};
+
+void brcmf_fweh_attach(struct brcmf_pub *drvr);
+void brcmf_fweh_detach(struct brcmf_pub *drvr);
+int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code,
+			int (*handler)(struct brcmf_if *ifp,
+				       const struct brcmf_event_msg *evtmsg,
+				       void *data));
+void brcmf_fweh_unregister(struct brcmf_pub *drvr,
+			   enum brcmf_fweh_event_code code);
+int brcmf_fweh_activate_events(struct brcmf_if *ifp);
+void brcmf_fweh_process_event(struct brcmf_pub *drvr,
+			      struct brcmf_event *event_packet, u8 *ifidx);
+
+static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
+					  struct sk_buff *skb, u8 *ifidx)
+{
+	struct brcmf_event *event_packet;
+	u8 *data;
+	u16 usr_stype;
+
+	/* only process events when protocol matches */
+	if (skb->protocol != cpu_to_be16(ETH_P_LINK_CTL))
+		return;
+
+	/* check for BRCM oui match */
+	event_packet = (struct brcmf_event *)skb_mac_header(skb);
+	data = (u8 *)event_packet;
+	data += BRCMF_EVENT_OUI_OFFSET;
+	if (memcmp(BRCM_OUI, data, DOT11_OUI_LEN))
+		return;
+
+	/* final match on usr_subtype */
+	data += DOT11_OUI_LEN;
+	usr_stype = get_unaligned_be16(data);
+	if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT)
+		return;
+
+	brcmf_fweh_process_event(drvr, event_packet, ifidx);
+}
+
+#endif /* FWEH_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
new file mode 100644
index 0000000..51a1450
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* FWIL is the Firmware Interface Layer. In this module the support functions
+ * are located to set and get variables to and from the firmware.
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
+#include "fwil.h"
+
+
+#define MAX_HEX_DUMP_LEN	64
+
+
+static s32
+brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
+{
+	struct brcmf_pub *drvr = ifp->drvr;
+	s32 err;
+
+	if (drvr->bus_if->state != BRCMF_BUS_DATA) {
+		brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n");
+		return -EIO;
+	}
+
+	if (data != NULL)
+		len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
+	if (set)
+		err = brcmf_proto_cdc_set_dcmd(drvr, ifp->idx, cmd, data, len);
+	else
+		err = brcmf_proto_cdc_query_dcmd(drvr, ifp->idx, cmd, data,
+						 len);
+
+	if (err >= 0)
+		err = 0;
+	else
+		brcmf_dbg(ERROR, "Failed err=%d\n", err);
+
+	return err;
+}
+
+s32
+brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
+{
+	s32 err;
+
+	mutex_lock(&ifp->drvr->proto_block);
+
+	brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
+	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+
+	err = brcmf_fil_cmd_data(ifp, cmd, data, len, true);
+	mutex_unlock(&ifp->drvr->proto_block);
+
+	return err;
+}
+
+s32
+brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
+{
+	s32 err;
+
+	mutex_lock(&ifp->drvr->proto_block);
+	err = brcmf_fil_cmd_data(ifp, cmd, data, len, false);
+
+	brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
+	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+
+	mutex_unlock(&ifp->drvr->proto_block);
+
+	return err;
+}
+
+
+s32
+brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data)
+{
+	s32 err;
+	__le32 data_le = cpu_to_le32(data);
+
+	mutex_lock(&ifp->drvr->proto_block);
+	err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true);
+	mutex_unlock(&ifp->drvr->proto_block);
+
+	return err;
+}
+
+s32
+brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data)
+{
+	s32 err;
+	__le32 data_le = cpu_to_le32(*data);
+
+	mutex_lock(&ifp->drvr->proto_block);
+	err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false);
+	mutex_unlock(&ifp->drvr->proto_block);
+	*data = le32_to_cpu(data_le);
+
+	return err;
+}
+
+static u32
+brcmf_create_iovar(char *name, char *data, u32 datalen, char *buf, u32 buflen)
+{
+	u32 len;
+
+	len = strlen(name) + 1;
+
+	if ((len + datalen) > buflen)
+		return 0;
+
+	memcpy(buf, name, len);
+
+	/* append data onto the end of the name string */
+	if (data && datalen)
+		memcpy(&buf[len], data, datalen);
+
+	return len + datalen;
+}
+
+
+s32
+brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
+			 u32 len)
+{
+	struct brcmf_pub *drvr = ifp->drvr;
+	s32 err;
+	u32 buflen;
+
+	mutex_lock(&drvr->proto_block);
+
+	brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
+	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+
+	buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
+				    sizeof(drvr->proto_buf));
+	if (buflen) {
+		err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
+					 buflen, true);
+	} else {
+		err = -EPERM;
+		brcmf_dbg(ERROR, "Creating iovar failed\n");
+	}
+
+	mutex_unlock(&drvr->proto_block);
+	return err;
+}
+
+s32
+brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
+			 u32 len)
+{
+	struct brcmf_pub *drvr = ifp->drvr;
+	s32 err;
+	u32 buflen;
+
+	mutex_lock(&drvr->proto_block);
+
+	buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
+				    sizeof(drvr->proto_buf));
+	if (buflen) {
+		err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
+					 buflen, false);
+		if (err == 0)
+			memcpy(data, drvr->proto_buf, len);
+	} else {
+		err = -EPERM;
+		brcmf_dbg(ERROR, "Creating iovar failed\n");
+	}
+
+	brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
+	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+
+	mutex_unlock(&drvr->proto_block);
+	return err;
+}
+
+s32
+brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data)
+{
+	__le32 data_le = cpu_to_le32(data);
+
+	return brcmf_fil_iovar_data_set(ifp, name, &data_le, sizeof(data_le));
+}
+
+s32
+brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data)
+{
+	__le32 data_le = cpu_to_le32(*data);
+	s32 err;
+
+	err = brcmf_fil_iovar_data_get(ifp, name, &data_le, sizeof(data_le));
+	if (err == 0)
+		*data = le32_to_cpu(data_le);
+	return err;
+}
+
+static u32
+brcmf_create_bsscfg(s32 bssidx, char *name, char *data, u32 datalen, char *buf,
+		    u32 buflen)
+{
+	const s8 *prefix = "bsscfg:";
+	s8 *p;
+	u32 prefixlen;
+	u32 namelen;
+	u32 iolen;
+	__le32 bssidx_le;
+
+	if (bssidx == 0)
+		return brcmf_create_iovar(name, data, datalen, buf, buflen);
+
+	prefixlen = strlen(prefix);
+	namelen = strlen(name) + 1; /* lengh of iovar  name + null */
+	iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen;
+
+	if (buflen < iolen) {
+		brcmf_dbg(ERROR, "buffer is too short\n");
+		return 0;
+	}
+
+	p = buf;
+
+	/* copy prefix, no null */
+	memcpy(p, prefix, prefixlen);
+	p += prefixlen;
+
+	/* copy iovar name including null */
+	memcpy(p, name, namelen);
+	p += namelen;
+
+	/* bss config index as first data */
+	bssidx_le = cpu_to_le32(bssidx);
+	memcpy(p, &bssidx_le, sizeof(bssidx_le));
+	p += sizeof(bssidx_le);
+
+	/* parameter buffer follows */
+	if (datalen)
+		memcpy(p, data, datalen);
+
+	return iolen;
+}
+
+s32
+brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name,
+			  void *data, u32 len)
+{
+	struct brcmf_pub *drvr = ifp->drvr;
+	s32 err;
+	u32 buflen;
+
+	mutex_lock(&drvr->proto_block);
+
+	brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
+	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+
+	buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len,
+				     drvr->proto_buf, sizeof(drvr->proto_buf));
+	if (buflen) {
+		err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
+					 buflen, true);
+	} else {
+		err = -EPERM;
+		brcmf_dbg(ERROR, "Creating bsscfg failed\n");
+	}
+
+	mutex_unlock(&drvr->proto_block);
+	return err;
+}
+
+s32
+brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name,
+			  void *data, u32 len)
+{
+	struct brcmf_pub *drvr = ifp->drvr;
+	s32 err;
+	u32 buflen;
+
+	mutex_lock(&drvr->proto_block);
+
+	buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len,
+				     drvr->proto_buf, sizeof(drvr->proto_buf));
+	if (buflen) {
+		err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
+					 buflen, false);
+		if (err == 0)
+			memcpy(data, drvr->proto_buf, len);
+	} else {
+		err = -EPERM;
+		brcmf_dbg(ERROR, "Creating bsscfg failed\n");
+	}
+	brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
+	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
+
+	mutex_unlock(&drvr->proto_block);
+	return err;
+
+}
+
+s32
+brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data)
+{
+	__le32 data_le = cpu_to_le32(data);
+
+	return brcmf_fil_bsscfg_data_set(ifp, name, &data_le,
+					 sizeof(data_le));
+}
+
+s32
+brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data)
+{
+	__le32 data_le = cpu_to_le32(*data);
+	s32 err;
+
+	err = brcmf_fil_bsscfg_data_get(ifp, name, &data_le,
+					sizeof(data_le));
+	if (err == 0)
+		*data = le32_to_cpu(data_le);
+	return err;
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h
new file mode 100644
index 0000000..16eb820
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _fwil_h_
+#define _fwil_h_
+
+s32 brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len);
+s32 brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len);
+s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data);
+s32 brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data);
+
+s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
+			     u32 len);
+s32 brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
+			     u32 len);
+s32 brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data);
+s32 brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data);
+
+s32 brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name, void *data,
+			      u32 len);
+s32 brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, void *data,
+			      u32 len);
+s32 brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data);
+s32 brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data);
+
+#endif /* _fwil_h_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index 7a6dfdc..39a5baa 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -14,24 +14,12 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/kthread.h>
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/spinlock.h>
-#include <linux/ethtool.h>
-#include <linux/fcntl.h>
-#include <linux/fs.h>
-#include <linux/uaccess.h>
 #include <linux/firmware.h>
 #include <linux/usb.h>
 #include <linux/vmalloc.h>
-#include <net/cfg80211.h>
 
-#include <defs.h>
 #include <brcmu_utils.h>
 #include <brcmu_wifi.h>
 #include <dhd_bus.h>
@@ -42,14 +30,11 @@
 
 #define IOCTL_RESP_TIMEOUT  2000
 
-#define BRCMF_USB_SYNC_TIMEOUT		300	/* ms */
-#define BRCMF_USB_DLIMAGE_SPINWAIT	100	/* in unit of ms */
-#define BRCMF_USB_DLIMAGE_LIMIT		500	/* spinwait limit (ms) */
+#define BRCMF_USB_RESET_GETVER_SPINWAIT	100	/* in unit of ms */
+#define BRCMF_USB_RESET_GETVER_LOOP_CNT	10
 
 #define BRCMF_POSTBOOT_ID		0xA123  /* ID to detect if dongle
 						   has boot up */
-#define BRCMF_USB_RESETCFG_SPINWAIT	1	/* wait after resetcfg (ms) */
-
 #define BRCMF_USB_NRXQ	50
 #define BRCMF_USB_NTXQ	50
 
@@ -70,16 +55,6 @@
 #define BRCMF_USB_43236_FW_NAME	"brcm/brcmfmac43236b.bin"
 #define BRCMF_USB_43242_FW_NAME	"brcm/brcmfmac43242a.bin"
 
-enum usbdev_suspend_state {
-	USBOS_SUSPEND_STATE_DEVICE_ACTIVE = 0, /* Device is busy, won't allow
-						  suspend */
-	USBOS_SUSPEND_STATE_SUSPEND_PENDING,	/* Device is idle, can be
-						 * suspended. Wating PM to
-						 * suspend the device
-						 */
-	USBOS_SUSPEND_STATE_SUSPENDED	/* Device suspended */
-};
-
 struct brcmf_usb_image {
 	struct list_head list;
 	s8 *fwname;
@@ -100,10 +75,8 @@ struct brcmf_usbdev_info {
 	struct list_head rx_postq;
 	struct list_head tx_freeq;
 	struct list_head tx_postq;
-	enum usbdev_suspend_state suspend_state;
 	uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2;
 
-	bool activity;
 	int rx_low_watermark;
 	int tx_low_watermark;
 	int tx_high_watermark;
@@ -116,10 +89,6 @@ struct brcmf_usbdev_info {
 	u8 *image;	/* buffer for combine fw and nvram */
 	int image_len;
 
-	wait_queue_head_t wait;
-	bool waitdone;
-	int sync_urb_status;
-
 	struct usb_device *usbdev;
 	struct device *dev;
 
@@ -131,7 +100,6 @@ struct brcmf_usbdev_info {
 	int ctl_urb_status;
 	int ctl_completed;
 	wait_queue_head_t ioctl_resp_wait;
-	wait_queue_head_t ctrl_wait;
 	ulong ctl_op;
 
 	struct urb *bulk_urb; /* used for FW download */
@@ -176,6 +144,7 @@ static void brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo)
 static void
 brcmf_usb_ctl_complete(struct brcmf_usbdev_info *devinfo, int type, int status)
 {
+	brcmf_dbg(USB, "Enter, status=%d\n", status);
 
 	if (unlikely(devinfo == NULL))
 		return;
@@ -203,6 +172,7 @@ brcmf_usb_ctlread_complete(struct urb *urb)
 	struct brcmf_usbdev_info *devinfo =
 		(struct brcmf_usbdev_info *)urb->context;
 
+	brcmf_dbg(USB, "Enter\n");
 	devinfo->ctl_urb_actual_length = urb->actual_length;
 	brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_READ,
 		urb->status);
@@ -214,33 +184,22 @@ brcmf_usb_ctlwrite_complete(struct urb *urb)
 	struct brcmf_usbdev_info *devinfo =
 		(struct brcmf_usbdev_info *)urb->context;
 
+	brcmf_dbg(USB, "Enter\n");
 	brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_WRITE,
 		urb->status);
 }
 
-static int brcmf_usb_pnp(struct brcmf_usbdev_info *devinfo, uint state)
-{
-	return 0;
-}
-
 static int
 brcmf_usb_send_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
 {
 	int ret;
 	u16 size;
 
+	brcmf_dbg(USB, "Enter\n");
 	if (devinfo == NULL || buf == NULL ||
 	    len == 0 || devinfo->ctl_urb == NULL)
 		return -EINVAL;
 
-	/* If the USB/HSIC bus in sleep state, wake it up */
-	if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED)
-		if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) {
-			brcmf_dbg(ERROR, "Could not Resume the bus!\n");
-			return -EIO;
-		}
-
-	devinfo->activity = true;
 	size = len;
 	devinfo->ctl_write.wLength = cpu_to_le16p(&size);
 	devinfo->ctl_urb->transfer_buffer_length = size;
@@ -268,6 +227,7 @@ brcmf_usb_recv_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
 	int ret;
 	u16 size;
 
+	brcmf_dbg(USB, "Enter\n");
 	if ((devinfo == NULL) || (buf == NULL) || (len == 0)
 		|| (devinfo->ctl_urb == NULL))
 		return -EINVAL;
@@ -301,10 +261,9 @@ static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len)
 	int timeout = 0;
 	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
 
-	if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
-		/* TODO: handle suspend/resume */
+	brcmf_dbg(USB, "Enter\n");
+	if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
 		return -EIO;
-	}
 
 	if (test_and_set_bit(0, &devinfo->ctl_op))
 		return -EIO;
@@ -331,10 +290,10 @@ static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len)
 	int timeout = 0;
 	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
 
-	if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
-		/* TODO: handle suspend/resume */
+	brcmf_dbg(USB, "Enter\n");
+	if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
 		return -EIO;
-	}
+
 	if (test_and_set_bit(0, &devinfo->ctl_op))
 		return -EIO;
 
@@ -459,6 +418,8 @@ static void brcmf_usb_tx_complete(struct urb *urb)
 	struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context;
 	struct brcmf_usbdev_info *devinfo = req->devinfo;
 
+	brcmf_dbg(USB, "Enter, urb->status=%d, skb=%p\n", urb->status,
+		  req->skb);
 	brcmf_usb_del_fromq(devinfo, req);
 	if (urb->status == 0)
 		devinfo->bus_pub.bus->dstats.tx_packets++;
@@ -484,6 +445,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)
 	struct sk_buff *skb;
 	int ifidx = 0;
 
+	brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status);
 	brcmf_usb_del_fromq(devinfo, req);
 	skb = req->skb;
 	req->skb = NULL;
@@ -497,7 +459,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)
 		return;
 	}
 
-	if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP) {
+	if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) {
 		skb_put(skb, urb->actual_length);
 		if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) {
 			brcmf_dbg(ERROR, "rx protocol error\n");
@@ -550,8 +512,8 @@ static void brcmf_usb_rx_fill_all(struct brcmf_usbdev_info *devinfo)
 {
 	struct brcmf_usbreq *req;
 
-	if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
-		brcmf_dbg(ERROR, "bus is not up\n");
+	if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) {
+		brcmf_dbg(ERROR, "bus is not up=%d\n", devinfo->bus_pub.state);
 		return;
 	}
 	while ((req = brcmf_usb_deq(devinfo, &devinfo->rx_freeq, NULL)) != NULL)
@@ -564,29 +526,24 @@ brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
 	struct brcmf_bus *bcmf_bus = devinfo->bus_pub.bus;
 	int old_state;
 
+	brcmf_dbg(USB, "Enter, current state=%d, new state=%d\n",
+		  devinfo->bus_pub.state, state);
 
 	if (devinfo->bus_pub.state == state)
 		return;
 
 	old_state = devinfo->bus_pub.state;
-	brcmf_dbg(TRACE, "dbus state change from %d to to %d\n",
-		  old_state, state);
-
-	/* Don't update state if it's PnP firmware re-download */
-	if (state != BCMFMAC_USB_STATE_PNP_FWDL) /* TODO */
-		devinfo->bus_pub.state = state;
-
-	if ((old_state  == BCMFMAC_USB_STATE_SLEEP)
-		&& (state == BCMFMAC_USB_STATE_UP)) {
-		brcmf_usb_rx_fill_all(devinfo);
-	}
+	devinfo->bus_pub.state = state;
 
 	/* update state of upper layer */
-	if (state == BCMFMAC_USB_STATE_DOWN) {
-		brcmf_dbg(INFO, "DBUS is down\n");
+	if (state == BRCMFMAC_USB_STATE_DOWN) {
+		brcmf_dbg(USB, "DBUS is down\n");
 		bcmf_bus->state = BRCMF_BUS_DOWN;
+	} else if (state == BRCMFMAC_USB_STATE_UP) {
+		brcmf_dbg(USB, "DBUS is up\n");
+		bcmf_bus->state = BRCMF_BUS_DATA;
 	} else {
-		brcmf_dbg(INFO, "DBUS current state=%d\n", state);
+		brcmf_dbg(USB, "DBUS current state=%d\n", state);
 	}
 }
 
@@ -595,30 +552,32 @@ brcmf_usb_intr_complete(struct urb *urb)
 {
 	struct brcmf_usbdev_info *devinfo =
 			(struct brcmf_usbdev_info *)urb->context;
-	bool killed;
+	int err;
+
+	brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status);
 
 	if (devinfo == NULL)
 		return;
 
 	if (unlikely(urb->status)) {
-		if (devinfo->suspend_state ==
-			USBOS_SUSPEND_STATE_SUSPEND_PENDING)
-			killed = true;
-
-		if ((urb->status == -ENOENT && (!killed))
-			|| urb->status == -ESHUTDOWN ||
-			urb->status == -ENODEV) {
-			brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN);
+		if (urb->status == -ENOENT ||
+		    urb->status == -ESHUTDOWN ||
+		    urb->status == -ENODEV) {
+			brcmf_usb_state_change(devinfo,
+					       BRCMFMAC_USB_STATE_DOWN);
 		}
 	}
 
-	if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN) {
+	if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_DOWN) {
 		brcmf_dbg(ERROR, "intr cb when DBUS down, ignoring\n");
 		return;
 	}
 
-	if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
-		usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
+	if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) {
+		err = usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
+		if (err)
+			brcmf_dbg(ERROR, "usb_submit_urb, err=%d\n", err);
+	}
 }
 
 static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
@@ -627,10 +586,9 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
 	struct brcmf_usbreq  *req;
 	int ret;
 
-	if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
-		/* TODO: handle suspend/resume */
+	brcmf_dbg(USB, "Enter, skb=%p\n", skb);
+	if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
 		return -EIO;
-	}
 
 	req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq,
 					&devinfo->tx_freecount);
@@ -670,25 +628,16 @@ static int brcmf_usb_up(struct device *dev)
 {
 	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
 	u16 ifnum;
+	int ret;
 
-	if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
+	brcmf_dbg(USB, "Enter\n");
+	if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP)
 		return 0;
 
-	/* If the USB/HSIC bus in sleep state, wake it up */
-	if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED) {
-		if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) {
-			brcmf_dbg(ERROR, "Could not Resume the bus!\n");
-			return -EIO;
-		}
-	}
-	devinfo->activity = true;
-
 	/* Success, indicate devinfo is fully up */
-	brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_UP);
+	brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_UP);
 
 	if (devinfo->intr_urb) {
-		int ret;
-
 		usb_fill_int_urb(devinfo->intr_urb, devinfo->usbdev,
 			devinfo->intr_pipe,
 			&devinfo->intr,
@@ -733,14 +682,14 @@ static void brcmf_usb_down(struct device *dev)
 {
 	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
 
+	brcmf_dbg(USB, "Enter\n");
 	if (devinfo == NULL)
 		return;
 
-	brcmf_dbg(TRACE, "enter\n");
-	if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN)
+	if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_DOWN)
 		return;
 
-	brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN);
+	brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_DOWN);
 	if (devinfo->intr_urb)
 		usb_kill_urb(devinfo->intr_urb);
 
@@ -754,34 +703,14 @@ static void brcmf_usb_down(struct device *dev)
 	brcmf_usb_free_q(&devinfo->rx_postq, true);
 }
 
-static int
-brcmf_usb_sync_wait(struct brcmf_usbdev_info *devinfo, u16 time)
-{
-	int ret;
-	int err = 0;
-	int ms = time;
-
-	ret = wait_event_interruptible_timeout(devinfo->wait,
-		devinfo->waitdone == true, (ms * HZ / 1000));
-
-	if ((devinfo->waitdone == false) || (devinfo->sync_urb_status)) {
-		brcmf_dbg(ERROR, "timeout(%d) or urb err=%d\n",
-			  ret, devinfo->sync_urb_status);
-		err = -EINVAL;
-	}
-	devinfo->waitdone = false;
-	return err;
-}
-
 static void
 brcmf_usb_sync_complete(struct urb *urb)
 {
 	struct brcmf_usbdev_info *devinfo =
 			(struct brcmf_usbdev_info *)urb->context;
 
-	devinfo->waitdone = true;
-	wake_up_interruptible(&devinfo->wait);
-	devinfo->sync_urb_status = urb->status;
+	devinfo->ctl_completed = true;
+	brcmf_usb_ioctl_resp_wake(devinfo);
 }
 
 static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
@@ -813,6 +742,7 @@ static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
 		(void *) tmpbuf, size,
 		(usb_complete_t)brcmf_usb_sync_complete, devinfo);
 
+	devinfo->ctl_completed = false;
 	ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
 	if (ret < 0) {
 		brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
@@ -820,11 +750,11 @@ static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
 		return false;
 	}
 
-	ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT);
+	ret = brcmf_usb_ioctl_resp_wait(devinfo);
 	memcpy(buffer, tmpbuf, buflen);
 	kfree(tmpbuf);
 
-	return (ret == 0);
+	return ret;
 }
 
 static bool
@@ -833,27 +763,25 @@ brcmf_usb_dlneeded(struct brcmf_usbdev_info *devinfo)
 	struct bootrom_id_le id;
 	u32 chipid, chiprev;
 
-	brcmf_dbg(TRACE, "enter\n");
+	brcmf_dbg(USB, "Enter\n");
 
 	if (devinfo == NULL)
 		return false;
 
 	/* Check if firmware downloaded already by querying runtime ID */
 	id.chip = cpu_to_le32(0xDEAD);
-	brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id,
-		sizeof(struct bootrom_id_le));
+	brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, sizeof(id));
 
 	chipid = le32_to_cpu(id.chip);
 	chiprev = le32_to_cpu(id.chiprev);
 
 	if ((chipid & 0x4300) == 0x4300)
-		brcmf_dbg(INFO, "chip %x rev 0x%x\n", chipid, chiprev);
+		brcmf_dbg(USB, "chip %x rev 0x%x\n", chipid, chiprev);
 	else
-		brcmf_dbg(INFO, "chip %d rev 0x%x\n", chipid, chiprev);
+		brcmf_dbg(USB, "chip %d rev 0x%x\n", chipid, chiprev);
 	if (chipid == BRCMF_POSTBOOT_ID) {
-		brcmf_dbg(INFO, "firmware already downloaded\n");
-		brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id,
-			sizeof(struct bootrom_id_le));
+		brcmf_dbg(USB, "firmware already downloaded\n");
+		brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id, sizeof(id));
 		return false;
 	} else {
 		devinfo->bus_pub.devid = chipid;
@@ -866,38 +794,29 @@ static int
 brcmf_usb_resetcfg(struct brcmf_usbdev_info *devinfo)
 {
 	struct bootrom_id_le id;
-	u16 wait = 0, wait_time;
+	u32 loop_cnt;
 
-	brcmf_dbg(TRACE, "enter\n");
+	brcmf_dbg(USB, "Enter\n");
 
-	if (devinfo == NULL)
-		return -EINVAL;
-
-	/* Give dongle chance to boot */
-	wait_time = BRCMF_USB_DLIMAGE_SPINWAIT;
-	while (wait < BRCMF_USB_DLIMAGE_LIMIT) {
-		mdelay(wait_time);
-		wait += wait_time;
+	loop_cnt = 0;
+	do {
+		mdelay(BRCMF_USB_RESET_GETVER_SPINWAIT);
+		loop_cnt++;
 		id.chip = cpu_to_le32(0xDEAD);       /* Get the ID */
-		brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id,
-			sizeof(struct bootrom_id_le));
+		brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, sizeof(id));
 		if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID))
 			break;
-	}
+	} while (loop_cnt < BRCMF_USB_RESET_GETVER_LOOP_CNT);
 
 	if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID)) {
-		brcmf_dbg(INFO, "download done %d ms postboot chip 0x%x/rev 0x%x\n",
-			  wait, le32_to_cpu(id.chip), le32_to_cpu(id.chiprev));
-
-		brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id,
-			sizeof(struct bootrom_id_le));
+		brcmf_dbg(USB, "postboot chip 0x%x/rev 0x%x\n",
+			  le32_to_cpu(id.chip), le32_to_cpu(id.chiprev));
 
-		/* XXX this wait may not be necessary */
-		mdelay(BRCMF_USB_RESETCFG_SPINWAIT);
+		brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id, sizeof(id));
 		return 0;
 	} else {
 		brcmf_dbg(ERROR, "Cannot talk to Dongle. Firmware is not UP, %d ms\n",
-			  wait);
+			  BRCMF_USB_RESET_GETVER_SPINWAIT * loop_cnt);
 		return -EINVAL;
 	}
 }
@@ -918,13 +837,14 @@ brcmf_usb_dl_send_bulk(struct brcmf_usbdev_info *devinfo, void *buffer, int len)
 
 	devinfo->bulk_urb->transfer_flags |= URB_ZERO_PACKET;
 
+	devinfo->ctl_completed = false;
 	ret = usb_submit_urb(devinfo->bulk_urb, GFP_ATOMIC);
 	if (ret) {
 		brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
 		return ret;
 	}
-	ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT);
-	return ret;
+	ret = brcmf_usb_ioctl_resp_wait(devinfo);
+	return (ret == 0);
 }
 
 static int
@@ -935,7 +855,8 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen)
 	struct rdl_state_le state;
 	u32 rdlstate, rdlbytes;
 	int err = 0;
-	brcmf_dbg(TRACE, "fw %p, len %d\n", fw, fwlen);
+
+	brcmf_dbg(USB, "Enter, fw %p, len %d\n", fw, fwlen);
 
 	bulkchunk = kmalloc(RDL_CHUNK, GFP_ATOMIC);
 	if (bulkchunk == NULL) {
@@ -1010,7 +931,7 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen)
 
 fail:
 	kfree(bulkchunk);
-	brcmf_dbg(TRACE, "err=%d\n", err);
+	brcmf_dbg(USB, "Exit, err=%d\n", err);
 	return err;
 }
 
@@ -1018,7 +939,7 @@ static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len)
 {
 	int err;
 
-	brcmf_dbg(TRACE, "enter\n");
+	brcmf_dbg(USB, "Enter\n");
 
 	if (devinfo == NULL)
 		return -EINVAL;
@@ -1028,10 +949,10 @@ static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len)
 
 	err = brcmf_usb_dl_writeimage(devinfo, fw, len);
 	if (err == 0)
-		devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_DONE;
+		devinfo->bus_pub.state = BRCMFMAC_USB_STATE_DL_DONE;
 	else
-		devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_PENDING;
-	brcmf_dbg(TRACE, "exit: err=%d\n", err);
+		devinfo->bus_pub.state = BRCMFMAC_USB_STATE_DL_FAIL;
+	brcmf_dbg(USB, "Exit, err=%d\n", err);
 
 	return err;
 }
@@ -1040,7 +961,7 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
 {
 	struct rdl_state_le state;
 
-	brcmf_dbg(TRACE, "enter\n");
+	brcmf_dbg(USB, "Enter\n");
 	if (!devinfo)
 		return -EINVAL;
 
@@ -1063,7 +984,7 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
 		brcmf_dbg(ERROR, "Dongle not runnable\n");
 		return -EINVAL;
 	}
-	brcmf_dbg(TRACE, "exit\n");
+	brcmf_dbg(USB, "Exit\n");
 	return 0;
 }
 
@@ -1090,7 +1011,7 @@ brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
 	int devid, chiprev;
 	int err;
 
-	brcmf_dbg(TRACE, "enter\n");
+	brcmf_dbg(USB, "Enter\n");
 	if (devinfo == NULL)
 		return -ENODEV;
 
@@ -1118,7 +1039,7 @@ brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
 
 static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo)
 {
-	brcmf_dbg(TRACE, "devinfo %p\n", devinfo);
+	brcmf_dbg(USB, "Enter, devinfo %p\n", devinfo);
 
 	/* free the URBS */
 	brcmf_usb_free_q(&devinfo->rx_freeq, false);
@@ -1153,6 +1074,7 @@ static int check_file(const u8 *headers)
 	struct trx_header_le *trx;
 	int actual_len = -1;
 
+	brcmf_dbg(USB, "Enter\n");
 	/* Extract trx header */
 	trx = (struct trx_header_le *) headers;
 	if (trx->magic != cpu_to_le32(TRX_MAGIC))
@@ -1174,6 +1096,7 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
 	struct brcmf_usb_image *fw_image;
 	int err;
 
+	brcmf_dbg(USB, "Enter\n");
 	switch (devinfo->bus_pub.devid) {
 	case 43143:
 		fwname = BRCMF_USB_43143_FW_NAME;
@@ -1190,7 +1113,7 @@ static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
 		return -EINVAL;
 		break;
 	}
-
+	brcmf_dbg(USB, "Loading FW %s\n", fwname);
 	list_for_each_entry(fw_image, &fw_image_list, list) {
 		if (fw_image->fwname == fwname) {
 			devinfo->image = fw_image->image;
@@ -1235,10 +1158,13 @@ static
 struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
 				      int nrxq, int ntxq)
 {
+	brcmf_dbg(USB, "Enter\n");
+
 	devinfo->bus_pub.nrxq = nrxq;
 	devinfo->rx_low_watermark = nrxq / 2;
 	devinfo->bus_pub.devinfo = devinfo;
 	devinfo->bus_pub.ntxq = ntxq;
+	devinfo->bus_pub.state = BRCMFMAC_USB_STATE_DOWN;
 
 	/* flow control when too many tx urbs posted */
 	devinfo->tx_low_watermark = ntxq / 4;
@@ -1284,11 +1210,10 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
 		goto error;
 	}
 
-	init_waitqueue_head(&devinfo->wait);
 	if (!brcmf_usb_dlneeded(devinfo))
 		return &devinfo->bus_pub;
 
-	brcmf_dbg(TRACE, "start fw downloading\n");
+	brcmf_dbg(USB, "Start fw downloading\n");
 	if (brcmf_usb_get_fw(devinfo))
 		goto error;
 
@@ -1303,14 +1228,14 @@ error:
 	return NULL;
 }
 
-static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
-			      const char *desc,	u32 bustype, u32 hdrlen)
+static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
 {
 	struct brcmf_bus *bus = NULL;
 	struct brcmf_usbdev *bus_pub = NULL;
 	int ret;
 	struct device *dev = devinfo->dev;
 
+	brcmf_dbg(USB, "Enter\n");
 	bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ);
 	if (!bus_pub)
 		return -ENODEV;
@@ -1327,14 +1252,13 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
 	bus->brcmf_bus_stop = brcmf_usb_down;
 	bus->brcmf_bus_txctl = brcmf_usb_tx_ctlpkt;
 	bus->brcmf_bus_rxctl = brcmf_usb_rx_ctlpkt;
-	bus->type = bustype;
 	bus->bus_priv.usb = bus_pub;
 	dev_set_drvdata(dev, bus);
 
 	/* Attach to the common driver interface */
-	ret = brcmf_attach(hdrlen, dev);
+	ret = brcmf_attach(0, dev);
 	if (ret) {
-		brcmf_dbg(ERROR, "dhd_attach failed\n");
+		brcmf_dbg(ERROR, "brcmf_attach failed\n");
 		goto fail;
 	}
 
@@ -1358,7 +1282,7 @@ brcmf_usb_disconnect_cb(struct brcmf_usbdev_info *devinfo)
 {
 	if (!devinfo)
 		return;
-	brcmf_dbg(TRACE, "enter: bus_pub %p\n", devinfo);
+	brcmf_dbg(USB, "Enter, bus_pub %p\n", devinfo);
 
 	brcmf_detach(devinfo->dev);
 	kfree(devinfo->bus_pub.bus);
@@ -1376,7 +1300,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
 	u8 endpoint_num;
 	struct brcmf_usbdev_info *devinfo;
 
-	brcmf_dbg(TRACE, "enter\n");
+	brcmf_dbg(USB, "Enter\n");
 
 	devinfo = kzalloc(sizeof(*devinfo), GFP_ATOMIC);
 	if (devinfo == NULL)
@@ -1477,11 +1401,11 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
 	devinfo->interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval;
 
 	if (usb->speed == USB_SPEED_HIGH)
-		brcmf_dbg(INFO, "Broadcom high speed USB wireless device detected\n");
+		brcmf_dbg(USB, "Broadcom high speed USB wireless device detected\n");
 	else
-		brcmf_dbg(INFO, "Broadcom full speed USB wireless device detected\n");
+		brcmf_dbg(USB, "Broadcom full speed USB wireless device detected\n");
 
-	ret = brcmf_usb_probe_cb(devinfo, "", USB_BUS, 0);
+	ret = brcmf_usb_probe_cb(devinfo);
 	if (ret)
 		goto fail;
 
@@ -1501,40 +1425,55 @@ brcmf_usb_disconnect(struct usb_interface *intf)
 {
 	struct brcmf_usbdev_info *devinfo;
 
-	brcmf_dbg(TRACE, "enter\n");
+	brcmf_dbg(USB, "Enter\n");
 	devinfo = (struct brcmf_usbdev_info *)usb_get_intfdata(intf);
 	brcmf_usb_disconnect_cb(devinfo);
 	kfree(devinfo);
+	brcmf_dbg(USB, "Exit\n");
 }
 
 /*
- *	only need to signal the bus being down and update the suspend state.
+ * only need to signal the bus being down and update the state.
  */
 static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state)
 {
 	struct usb_device *usb = interface_to_usbdev(intf);
 	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
 
-	brcmf_dbg(TRACE, "enter\n");
-	devinfo->bus_pub.state = BCMFMAC_USB_STATE_DOWN;
-	devinfo->suspend_state = USBOS_SUSPEND_STATE_SUSPENDED;
+	brcmf_dbg(USB, "Enter\n");
+	devinfo->bus_pub.state = BRCMFMAC_USB_STATE_SLEEP;
+	brcmf_detach(&usb->dev);
 	return 0;
 }
 
 /*
- *	mark suspend state active and crank up the bus.
+ * (re-) start the bus.
  */
 static int brcmf_usb_resume(struct usb_interface *intf)
 {
 	struct usb_device *usb = interface_to_usbdev(intf);
 	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
 
-	brcmf_dbg(TRACE, "enter\n");
-	devinfo->suspend_state = USBOS_SUSPEND_STATE_DEVICE_ACTIVE;
-	brcmf_bus_start(&usb->dev);
+	brcmf_dbg(USB, "Enter\n");
+	if (!brcmf_attach(0, devinfo->dev))
+		return brcmf_bus_start(&usb->dev);
+
 	return 0;
 }
 
+static int brcmf_usb_reset_resume(struct usb_interface *intf)
+{
+	struct usb_device *usb = interface_to_usbdev(intf);
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
+
+	brcmf_dbg(USB, "Enter\n");
+
+	if (!brcmf_usb_fw_download(devinfo))
+		return brcmf_usb_resume(intf);
+
+	return -EIO;
+}
+
 #define BRCMF_USB_VENDOR_ID_BROADCOM	0x0a5c
 #define BRCMF_USB_DEVICE_ID_43143	0xbd1e
 #define BRCMF_USB_DEVICE_ID_43236	0xbd17
@@ -1554,7 +1493,6 @@ MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME);
 MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME);
 MODULE_FIRMWARE(BRCMF_USB_43242_FW_NAME);
 
-/* TODO: suspend and resume entries */
 static struct usb_driver brcmf_usbdrvr = {
 	.name = KBUILD_MODNAME,
 	.probe = brcmf_usb_probe,
@@ -1562,6 +1500,7 @@ static struct usb_driver brcmf_usbdrvr = {
 	.id_table = brcmf_usb_devid_table,
 	.suspend = brcmf_usb_suspend,
 	.resume = brcmf_usb_resume,
+	.reset_resume = brcmf_usb_reset_resume,
 	.supports_autosuspend = 1,
 	.disable_hub_initiated_lpm = 1,
 };
@@ -1579,12 +1518,14 @@ static void brcmf_release_fw(struct list_head *q)
 
 void brcmf_usb_exit(void)
 {
+	brcmf_dbg(USB, "Enter\n");
 	usb_deregister(&brcmf_usbdrvr);
 	brcmf_release_fw(&fw_image_list);
 }
 
 void brcmf_usb_init(void)
 {
+	brcmf_dbg(USB, "Enter\n");
 	INIT_LIST_HEAD(&fw_image_list);
 	usb_register(&brcmf_usbdrvr);
 }
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.h b/drivers/net/wireless/brcm80211/brcmfmac/usb.h
index acfa5e8..f483a8c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.h
@@ -17,19 +17,11 @@
 #define BRCMFMAC_USB_H
 
 enum brcmf_usb_state {
-	BCMFMAC_USB_STATE_DL_PENDING,
-	BCMFMAC_USB_STATE_DL_DONE,
-	BCMFMAC_USB_STATE_UP,
-	BCMFMAC_USB_STATE_DOWN,
-	BCMFMAC_USB_STATE_PNP_FWDL,
-	BCMFMAC_USB_STATE_DISCONNECT,
-	BCMFMAC_USB_STATE_SLEEP
-};
-
-enum brcmf_usb_pnp_state {
-	BCMFMAC_USB_PNP_DISCONNECT,
-	BCMFMAC_USB_PNP_SLEEP,
-	BCMFMAC_USB_PNP_RESUME,
+	BRCMFMAC_USB_STATE_DOWN,
+	BRCMFMAC_USB_STATE_DL_FAIL,
+	BRCMFMAC_USB_STATE_DL_DONE,
+	BRCMFMAC_USB_STATE_UP,
+	BRCMFMAC_USB_STATE_SLEEP
 };
 
 struct brcmf_stats {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 481345c..2044fdb 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -19,14 +19,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/kernel.h>
-#include <linux/if_arp.h>
-#include <linux/sched.h>
-#include <linux/kthread.h>
-#include <linux/netdevice.h>
-#include <linux/bitops.h>
 #include <linux/etherdevice.h>
-#include <linux/ieee80211.h>
-#include <linux/uaccess.h>
 #include <net/cfg80211.h>
 #include <net/netlink.h>
 
@@ -35,6 +28,7 @@
 #include <brcmu_wifi.h>
 #include "dhd.h"
 #include "wl_cfg80211.h"
+#include "fwil.h"
 
 #define BRCMF_SCAN_IE_LEN_MAX		2048
 #define BRCMF_PNO_VERSION		2
@@ -48,6 +42,8 @@
 #define BRCMF_PNO_SCAN_COMPLETE		1
 #define BRCMF_PNO_SCAN_INCOMPLETE	0
 
+#define BRCMF_IFACE_MAX_CNT		2
+
 #define TLV_LEN_OFF			1	/* length offset */
 #define TLV_HDR_LEN			2	/* header length */
 #define TLV_BODY_OFF			2	/* body offset */
@@ -91,16 +87,13 @@
 #define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
 	(sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
 
-static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
-
 static u32 brcmf_dbg_level = WL_DBG_ERR;
 
-static bool check_sys_up(struct wiphy *wiphy)
+static bool check_vif_up(struct brcmf_cfg80211_vif *vif)
 {
-	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-	if (!test_bit(WL_STATUS_READY, &cfg->status)) {
-		WL_INFO("device is not ready : status (%d)\n",
-			(int)cfg->status);
+	if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state)) {
+		WL_INFO("device is not ready : status (%lu)\n",
+			vif->sme_state);
 		return false;
 	}
 	return true;
@@ -391,55 +384,29 @@ static u8 brcmf_mw_to_qdbm(u16 mw)
 	return qdbm;
 }
 
-/* function for reading/writing a single u32 from/to the dongle */
-static int
-brcmf_exec_dcmd_u32(struct net_device *ndev, u32 cmd, u32 *par)
-{
-	int err;
-	__le32 par_le = cpu_to_le32(*par);
-
-	err = brcmf_exec_dcmd(ndev, cmd, &par_le, sizeof(__le32));
-	*par = le32_to_cpu(par_le);
-
-	return err;
-}
-
-static s32
-brcmf_dev_iovar_setbuf_bsscfg(struct net_device *ndev, s8 *name,
-			      void *param, s32 paramlen,
-			      void *buf, s32 buflen, s32 bssidx)
+static u16 channel_to_chanspec(struct ieee80211_channel *ch)
 {
-	s32 err = -ENOMEM;
-	u32 len;
-
-	len = brcmf_c_mkiovar_bsscfg(name, param, paramlen,
-				     buf, buflen, bssidx);
-	BUG_ON(!len);
-	if (len > 0)
-		err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len);
-	if (err)
-		WL_ERR("error (%d)\n", err);
+	u16 chanspec;
 
-	return err;
-}
+	chanspec = ieee80211_frequency_to_channel(ch->center_freq);
+	chanspec &= WL_CHANSPEC_CHAN_MASK;
 
-static s32
-brcmf_dev_iovar_getbuf_bsscfg(struct net_device *ndev, s8 *name,
-			      void *param, s32 paramlen,
-			      void *buf, s32 buflen, s32 bssidx)
-{
-	s32 err = -ENOMEM;
-	u32 len;
-
-	len = brcmf_c_mkiovar_bsscfg(name, param, paramlen,
-				     buf, buflen, bssidx);
-	BUG_ON(!len);
-	if (len > 0)
-		err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, buf, len);
-	if (err)
-		WL_ERR("error (%d)\n", err);
+	if (ch->band == IEEE80211_BAND_2GHZ)
+		chanspec |= WL_CHANSPEC_BAND_2G;
+	else
+		chanspec |= WL_CHANSPEC_BAND_5G;
 
-	return err;
+	if (ch->flags & IEEE80211_CHAN_NO_HT40) {
+		chanspec |= WL_CHANSPEC_BW_20;
+		chanspec |= WL_CHANSPEC_CTL_SB_NONE;
+	} else {
+		chanspec |= WL_CHANSPEC_BW_40;
+		if (ch->flags & IEEE80211_CHAN_NO_HT40PLUS)
+			chanspec |= WL_CHANSPEC_CTL_SB_LOWER;
+		else
+			chanspec |= WL_CHANSPEC_CTL_SB_UPPER;
+	}
+	return chanspec;
 }
 
 static void convert_key_from_CPU(struct brcmf_wsec_key *key,
@@ -457,18 +424,17 @@ static void convert_key_from_CPU(struct brcmf_wsec_key *key,
 }
 
 static int
-send_key_to_dongle(struct brcmf_cfg80211_info *cfg, s32 bssidx,
-		   struct net_device *ndev, struct brcmf_wsec_key *key)
+send_key_to_dongle(struct net_device *ndev, struct brcmf_wsec_key *key)
 {
 	int err;
 	struct brcmf_wsec_key_le key_le;
 
 	convert_key_from_CPU(key, &key_le);
 
-	err  = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le,
-					     sizeof(key_le),
-					     cfg->extra_buf,
-					     WL_EXTRA_BUF_MAX, bssidx);
+	brcmf_netdev_wait_pend8021x(ndev);
+
+	err = brcmf_fil_bsscfg_data_set(netdev_priv(ndev), "wsec_key", &key_le,
+					sizeof(key_le));
 
 	if (err)
 		WL_ERR("wsec_key error (%d)\n", err);
@@ -480,6 +446,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
 			 enum nl80211_iftype type, u32 *flags,
 			 struct vif_params *params)
 {
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
 	s32 infra = 0;
 	s32 ap = 0;
@@ -511,17 +478,11 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
 	}
 
 	if (ap) {
-		set_bit(WL_STATUS_AP_CREATING, &cfg->status);
-		if (!cfg->ap_info)
-			cfg->ap_info = kzalloc(sizeof(*cfg->ap_info),
-					       GFP_KERNEL);
-		if (!cfg->ap_info) {
-			err = -ENOMEM;
-			goto done;
-		}
+		set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
 		WL_INFO("IF Type = AP\n");
 	} else {
-		err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
+		err = brcmf_fil_cmd_int_set(netdev_priv(ndev),
+					    BRCMF_C_SET_INFRA, infra);
 		if (err) {
 			WL_ERR("WLC_SET_INFRA error (%d)\n", err);
 			err = -EAGAIN;
@@ -539,99 +500,13 @@ done:
 	return err;
 }
 
-static s32 brcmf_dev_intvar_set(struct net_device *ndev, s8 *name, s32 val)
-{
-	s8 buf[BRCMF_DCMD_SMLEN];
-	u32 len;
-	s32 err = 0;
-	__le32 val_le;
-
-	val_le = cpu_to_le32(val);
-	len = brcmf_c_mkiovar(name, (char *)(&val_le), sizeof(val_le), buf,
-			    sizeof(buf));
-	BUG_ON(!len);
-
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len);
-	if (err)
-		WL_ERR("error (%d)\n", err);
-
-	return err;
-}
-
-static s32
-brcmf_dev_intvar_get(struct net_device *ndev, s8 *name, s32 *retval)
-{
-	union {
-		s8 buf[BRCMF_DCMD_SMLEN];
-		__le32 val;
-	} var;
-	u32 len;
-	u32 data_null;
-	s32 err = 0;
-
-	len =
-	    brcmf_c_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
-			sizeof(var.buf));
-	BUG_ON(!len);
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, &var, len);
-	if (err)
-		WL_ERR("error (%d)\n", err);
-
-	*retval = le32_to_cpu(var.val);
-
-	return err;
-}
-
-static s32
-brcmf_dev_intvar_set_bsscfg(struct net_device *ndev, s8 *name, u32 val,
-			    s32 bssidx)
-{
-	s8 buf[BRCMF_DCMD_SMLEN];
-	__le32 val_le;
-
-	val_le = cpu_to_le32(val);
-
-	return brcmf_dev_iovar_setbuf_bsscfg(ndev, name, &val_le,
-					     sizeof(val_le), buf, sizeof(buf),
-					     bssidx);
-}
-
-static s32
-brcmf_dev_intvar_get_bsscfg(struct net_device *ndev, s8 *name, s32 *val,
-			    s32 bssidx)
-{
-	s8 buf[BRCMF_DCMD_SMLEN];
-	s32 err;
-	__le32 val_le;
-
-	memset(buf, 0, sizeof(buf));
-	err = brcmf_dev_iovar_getbuf_bsscfg(ndev, name, val, sizeof(*val), buf,
-					    sizeof(buf), bssidx);
-	if (err == 0) {
-		memcpy(&val_le, buf, sizeof(val_le));
-		*val = le32_to_cpu(val_le);
-	}
-	return err;
-}
-
-
-/*
- * For now brcmf_find_bssidx will return 0. Once p2p gets implemented this
- * should return the ndev matching bssidx.
- */
-static s32
-brcmf_find_bssidx(struct brcmf_cfg80211_info *cfg, struct net_device *ndev)
-{
-	return 0;
-}
-
 static void brcmf_set_mpc(struct net_device *ndev, int mpc)
 {
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	s32 err = 0;
-	struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
 
-	if (test_bit(WL_STATUS_READY, &cfg->status)) {
-		err = brcmf_dev_intvar_set(ndev, "mpc", mpc);
+	if (check_vif_up(ifp->vif)) {
+		err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc);
 		if (err) {
 			WL_ERR("fail to set mpc\n");
 			return;
@@ -640,209 +515,6 @@ static void brcmf_set_mpc(struct net_device *ndev, int mpc)
 	}
 }
 
-static void brcmf_iscan_prep(struct brcmf_scan_params_le *params_le,
-			     struct brcmf_ssid *ssid)
-{
-	memcpy(params_le->bssid, ether_bcast, ETH_ALEN);
-	params_le->bss_type = DOT11_BSSTYPE_ANY;
-	params_le->scan_type = 0;
-	params_le->channel_num = 0;
-	params_le->nprobes = cpu_to_le32(-1);
-	params_le->active_time = cpu_to_le32(-1);
-	params_le->passive_time = cpu_to_le32(-1);
-	params_le->home_time = cpu_to_le32(-1);
-	if (ssid && ssid->SSID_len) {
-		params_le->ssid_le.SSID_len = cpu_to_le32(ssid->SSID_len);
-		memcpy(&params_le->ssid_le.SSID, ssid->SSID, ssid->SSID_len);
-	}
-}
-
-static s32
-brcmf_dev_iovar_setbuf(struct net_device *ndev, s8 * iovar, void *param,
-		    s32 paramlen, void *bufptr, s32 buflen)
-{
-	s32 iolen;
-
-	iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
-	BUG_ON(!iolen);
-
-	return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, bufptr, iolen);
-}
-
-static s32
-brcmf_dev_iovar_getbuf(struct net_device *ndev, s8 * iovar, void *param,
-		    s32 paramlen, void *bufptr, s32 buflen)
-{
-	s32 iolen;
-
-	iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
-	BUG_ON(!iolen);
-
-	return brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, bufptr, buflen);
-}
-
-static s32
-brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
-		struct brcmf_ssid *ssid, u16 action)
-{
-	s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
-			  offsetof(struct brcmf_iscan_params_le, params_le);
-	struct brcmf_iscan_params_le *params;
-	s32 err = 0;
-
-	if (ssid && ssid->SSID_len)
-		params_size += sizeof(struct brcmf_ssid);
-	params = kzalloc(params_size, GFP_KERNEL);
-	if (!params)
-		return -ENOMEM;
-	BUG_ON(params_size >= BRCMF_DCMD_SMLEN);
-
-	brcmf_iscan_prep(&params->params_le, ssid);
-
-	params->version = cpu_to_le32(BRCMF_ISCAN_REQ_VERSION);
-	params->action = cpu_to_le16(action);
-	params->scan_duration = cpu_to_le16(0);
-
-	err = brcmf_dev_iovar_setbuf(iscan->ndev, "iscan", params, params_size,
-				     iscan->dcmd_buf, BRCMF_DCMD_SMLEN);
-	if (err) {
-		if (err == -EBUSY)
-			WL_INFO("system busy : iscan canceled\n");
-		else
-			WL_ERR("error (%d)\n", err);
-	}
-
-	kfree(params);
-	return err;
-}
-
-static s32 brcmf_do_iscan(struct brcmf_cfg80211_info *cfg)
-{
-	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg);
-	struct net_device *ndev = cfg_to_ndev(cfg);
-	struct brcmf_ssid ssid;
-	__le32 passive_scan;
-	s32 err = 0;
-
-	/* Broadcast scan by default */
-	memset(&ssid, 0, sizeof(ssid));
-
-	iscan->state = WL_ISCAN_STATE_SCANING;
-
-	passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1);
-	err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCMF_C_SET_PASSIVE_SCAN,
-			&passive_scan, sizeof(passive_scan));
-	if (err) {
-		WL_ERR("error (%d)\n", err);
-		return err;
-	}
-	brcmf_set_mpc(ndev, 0);
-	cfg->iscan_kickstart = true;
-	err = brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START);
-	if (err) {
-		brcmf_set_mpc(ndev, 1);
-		cfg->iscan_kickstart = false;
-		return err;
-	}
-	mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
-	iscan->timer_on = 1;
-	return err;
-}
-
-static s32
-brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev,
-		     struct cfg80211_scan_request *request,
-		     struct cfg80211_ssid *this_ssid)
-{
-	struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
-	struct cfg80211_ssid *ssids;
-	struct brcmf_cfg80211_scan_req *sr = cfg->scan_req_int;
-	__le32 passive_scan;
-	bool iscan_req;
-	bool spec_scan;
-	s32 err = 0;
-	u32 SSID_len;
-
-	if (test_bit(WL_STATUS_SCANNING, &cfg->status)) {
-		WL_ERR("Scanning already : status (%lu)\n", cfg->status);
-		return -EAGAIN;
-	}
-	if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg->status)) {
-		WL_ERR("Scanning being aborted : status (%lu)\n",
-		       cfg->status);
-		return -EAGAIN;
-	}
-	if (test_bit(WL_STATUS_CONNECTING, &cfg->status)) {
-		WL_ERR("Connecting : status (%lu)\n",
-		       cfg->status);
-		return -EAGAIN;
-	}
-
-	iscan_req = false;
-	spec_scan = false;
-	if (request) {
-		/* scan bss */
-		ssids = request->ssids;
-		if (cfg->iscan_on && (!ssids || !ssids->ssid_len))
-			iscan_req = true;
-	} else {
-		/* scan in ibss */
-		/* we don't do iscan in ibss */
-		ssids = this_ssid;
-	}
-
-	cfg->scan_request = request;
-	set_bit(WL_STATUS_SCANNING, &cfg->status);
-	if (iscan_req) {
-		err = brcmf_do_iscan(cfg);
-		if (!err)
-			return err;
-		else
-			goto scan_out;
-	} else {
-		WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
-		       ssids->ssid, ssids->ssid_len);
-		memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
-		SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
-		sr->ssid_le.SSID_len = cpu_to_le32(0);
-		if (SSID_len) {
-			memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
-			sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
-			spec_scan = true;
-		} else {
-			WL_SCAN("Broadcast scan\n");
-		}
-
-		passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1);
-		err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
-				&passive_scan, sizeof(passive_scan));
-		if (err) {
-			WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
-			goto scan_out;
-		}
-		brcmf_set_mpc(ndev, 0);
-		err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le,
-				      sizeof(sr->ssid_le));
-		if (err) {
-			if (err == -EBUSY)
-				WL_INFO("system busy : scan for \"%s\" "
-					"canceled\n", sr->ssid_le.SSID);
-			else
-				WL_ERR("WLC_SCAN error (%d)\n", err);
-
-			brcmf_set_mpc(ndev, 1);
-			goto scan_out;
-		}
-	}
-
-	return 0;
-
-scan_out:
-	clear_bit(WL_STATUS_SCANNING, &cfg->status);
-	cfg->scan_request = NULL;
-	return err;
-}
-
 static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
 			     struct cfg80211_scan_request *request)
 {
@@ -851,12 +523,10 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
 	s32 i;
 	s32 offset;
 	u16 chanspec;
-	u16 channel;
-	struct ieee80211_channel *req_channel;
 	char *ptr;
 	struct brcmf_ssid_le ssid_le;
 
-	memcpy(params_le->bssid, ether_bcast, ETH_ALEN);
+	memset(params_le->bssid, 0xFF, ETH_ALEN);
 	params_le->bss_type = DOT11_BSSTYPE_ANY;
 	params_le->scan_type = 0;
 	params_le->channel_num = 0;
@@ -876,30 +546,9 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
 	WL_SCAN("### List of channelspecs to scan ### %d\n", n_channels);
 	if (n_channels > 0) {
 		for (i = 0; i < n_channels; i++) {
-			chanspec = 0;
-			req_channel = request->channels[i];
-			channel = ieee80211_frequency_to_channel(
-					req_channel->center_freq);
-			if (req_channel->band == IEEE80211_BAND_2GHZ)
-				chanspec |= WL_CHANSPEC_BAND_2G;
-			else
-				chanspec |= WL_CHANSPEC_BAND_5G;
-
-			if (req_channel->flags & IEEE80211_CHAN_NO_HT40) {
-				chanspec |= WL_CHANSPEC_BW_20;
-				chanspec |= WL_CHANSPEC_CTL_SB_NONE;
-			} else {
-				chanspec |= WL_CHANSPEC_BW_40;
-				if (req_channel->flags &
-						IEEE80211_CHAN_NO_HT40PLUS)
-					chanspec |= WL_CHANSPEC_CTL_SB_LOWER;
-				else
-					chanspec |= WL_CHANSPEC_CTL_SB_UPPER;
-			}
-
-			chanspec |= (channel & WL_CHANSPEC_CHAN_MASK);
+			chanspec = channel_to_chanspec(request->channels[i]);
 			WL_SCAN("Chan : %d, Channel spec: %x\n",
-				channel, chanspec);
+				request->channels[i]->hw_value, chanspec);
 			params_le->channel_list[i] = cpu_to_le16(chanspec);
 		}
 	} else {
@@ -966,7 +615,7 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
 		/* Do a scan abort to stop the driver's scan engine */
 		WL_SCAN("ABORT scan in firmware\n");
 		memset(&params_le, 0, sizeof(params_le));
-		memcpy(params_le.bssid, ether_bcast, ETH_ALEN);
+		memset(params_le.bssid, 0xFF, ETH_ALEN);
 		params_le.bss_type = DOT11_BSSTYPE_ANY;
 		params_le.scan_type = 0;
 		params_le.channel_num = cpu_to_le32(1);
@@ -977,8 +626,8 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
 		/* Scan is aborted by setting channel_list[0] to -1 */
 		params_le.channel_list[0] = cpu_to_le16(-1);
 		/* E-Scan (or anyother type) can be aborted by SCAN */
-		err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &params_le,
-			sizeof(params_le));
+		err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_SCAN,
+					     &params_le, sizeof(params_le));
 		if (err)
 			WL_ERR("Scan abort  failed\n");
 	}
@@ -998,7 +647,7 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
 		cfg80211_scan_done(scan_request, aborted);
 		brcmf_set_mpc(ndev, 1);
 	}
-	if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) {
+	if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
 		WL_ERR("Scan complete while device not scanning\n");
 		return -EPERM;
 	}
@@ -1036,8 +685,8 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev,
 	params->action = cpu_to_le16(action);
 	params->sync_id = cpu_to_le16(0x1234);
 
-	err = brcmf_dev_iovar_setbuf(ndev, "escan", params, params_size,
-			cfg->escan_ioctl_buf, BRCMF_DCMD_MEDLEN);
+	err = brcmf_fil_iovar_data_set(netdev_priv(ndev), "escan",
+				       params, params_size);
 	if (err) {
 		if (err == -EBUSY)
 			WL_INFO("system busy : escan canceled\n");
@@ -1055,16 +704,16 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy,
 	       struct net_device *ndev, struct cfg80211_scan_request *request)
 {
 	s32 err;
-	__le32 passive_scan;
+	u32 passive_scan;
 	struct brcmf_scan_results *results;
 
 	WL_SCAN("Enter\n");
 	cfg->escan_info.ndev = ndev;
 	cfg->escan_info.wiphy = wiphy;
 	cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANNING;
-	passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1);
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
-			&passive_scan, sizeof(passive_scan));
+	passive_scan = cfg->active_scan ? 0 : 1;
+	err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PASSIVE_SCAN,
+				    passive_scan);
 	if (err) {
 		WL_ERR("error (%d)\n", err);
 		return err;
@@ -1086,10 +735,11 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
 		     struct cfg80211_scan_request *request,
 		     struct cfg80211_ssid *this_ssid)
 {
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
 	struct cfg80211_ssid *ssids;
-	struct brcmf_cfg80211_scan_req *sr = cfg->scan_req_int;
-	__le32 passive_scan;
+	struct brcmf_cfg80211_scan_req *sr = &cfg->scan_req_int;
+	u32 passive_scan;
 	bool escan_req;
 	bool spec_scan;
 	s32 err;
@@ -1097,18 +747,17 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
 
 	WL_SCAN("START ESCAN\n");
 
-	if (test_bit(WL_STATUS_SCANNING, &cfg->status)) {
-		WL_ERR("Scanning already : status (%lu)\n", cfg->status);
+	if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
+		WL_ERR("Scanning already: status (%lu)\n", cfg->scan_status);
 		return -EAGAIN;
 	}
-	if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg->status)) {
-		WL_ERR("Scanning being aborted : status (%lu)\n",
-		       cfg->status);
+	if (test_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status)) {
+		WL_ERR("Scanning being aborted: status (%lu)\n",
+		       cfg->scan_status);
 		return -EAGAIN;
 	}
-	if (test_bit(WL_STATUS_CONNECTING, &cfg->status)) {
-		WL_ERR("Connecting : status (%lu)\n",
-		       cfg->status);
+	if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) {
+		WL_ERR("Connecting: status (%lu)\n", ifp->vif->sme_state);
 		return -EAGAIN;
 	}
 
@@ -1128,12 +777,10 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
 	}
 
 	cfg->scan_request = request;
-	set_bit(WL_STATUS_SCANNING, &cfg->status);
+	set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
 	if (escan_req) {
 		err = brcmf_do_escan(cfg, wiphy, ndev, request);
-		if (!err)
-			return err;
-		else
+		if (err)
 			goto scan_out;
 	} else {
 		WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
@@ -1149,16 +796,16 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
 		} else
 			WL_SCAN("Broadcast scan\n");
 
-		passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1);
-		err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
-				&passive_scan, sizeof(passive_scan));
+		passive_scan = cfg->active_scan ? 0 : 1;
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN,
+					    passive_scan);
 		if (err) {
 			WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
 			goto scan_out;
 		}
 		brcmf_set_mpc(ndev, 0);
-		err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le,
-				      sizeof(sr->ssid_le));
+		err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
+					     &sr->ssid_le, sizeof(sr->ssid_le));
 		if (err) {
 			if (err == -EBUSY)
 				WL_INFO("BUSY: scan for \"%s\" canceled\n",
@@ -1174,7 +821,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
 	return 0;
 
 scan_out:
-	clear_bit(WL_STATUS_SCANNING, &cfg->status);
+	clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
 	if (timer_pending(&cfg->escan_timeout))
 		del_timer_sync(&cfg->escan_timeout);
 	cfg->scan_request = NULL;
@@ -1182,22 +829,18 @@ scan_out:
 }
 
 static s32
-brcmf_cfg80211_scan(struct wiphy *wiphy,
-		 struct cfg80211_scan_request *request)
+brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
 {
 	struct net_device *ndev = request->wdev->netdev;
-	struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
 	s32 err = 0;
 
 	WL_TRACE("Enter\n");
 
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(container_of(request->wdev,
+				       struct brcmf_cfg80211_vif, wdev)))
 		return -EIO;
 
-	if (cfg->iscan_on)
-		err = brcmf_cfg80211_iscan(wiphy, ndev, request, NULL);
-	else if (cfg->escan_on)
-		err = brcmf_cfg80211_escan(wiphy, ndev, request, NULL);
+	err = brcmf_cfg80211_escan(wiphy, ndev, request, NULL);
 
 	if (err)
 		WL_ERR("scan error (%d)\n", err);
@@ -1210,7 +853,8 @@ static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
 {
 	s32 err = 0;
 
-	err = brcmf_dev_intvar_set(ndev, "rtsthresh", rts_threshold);
+	err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "rtsthresh",
+				      rts_threshold);
 	if (err)
 		WL_ERR("Error (%d)\n", err);
 
@@ -1221,7 +865,8 @@ static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)
 {
 	s32 err = 0;
 
-	err = brcmf_dev_intvar_set(ndev, "fragthresh", frag_threshold);
+	err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "fragthresh",
+				      frag_threshold);
 	if (err)
 		WL_ERR("Error (%d)\n", err);
 
@@ -1231,9 +876,9 @@ static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)
 static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l)
 {
 	s32 err = 0;
-	u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL);
+	u32 cmd = (l ? BRCMF_C_SET_LRL : BRCMF_C_SET_SRL);
 
-	err = brcmf_exec_dcmd_u32(ndev, cmd, &retry);
+	err = brcmf_fil_cmd_int_set(netdev_priv(ndev), cmd, retry);
 	if (err) {
 		WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
 		return err;
@@ -1245,10 +890,11 @@ static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 {
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
 	struct net_device *ndev = cfg_to_ndev(cfg);
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	s32 err = 0;
 
 	WL_TRACE("Enter\n");
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
 	if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
@@ -1327,7 +973,8 @@ static void brcmf_link_down(struct brcmf_cfg80211_info *cfg)
 	if (cfg->link_up) {
 		ndev = cfg_to_ndev(cfg);
 		WL_INFO("Call WLC_DISASSOC to stop excess roaming\n ");
-		err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, NULL, 0);
+		err = brcmf_fil_cmd_data_set(netdev_priv(ndev),
+					     BRCMF_C_DISASSOC, NULL, 0);
 		if (err)
 			WL_ERR("WLC_DISASSOC failed (%d)\n", err);
 		cfg->link_up = false;
@@ -1340,7 +987,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
 		      struct cfg80211_ibss_params *params)
 {
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-	struct brcmf_cfg80211_profile *profile = cfg->profile;
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
 	struct brcmf_join_params join_params;
 	size_t join_params_size = 0;
 	s32 err = 0;
@@ -1348,7 +996,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
 	s32 bcnprd;
 
 	WL_TRACE("Enter\n");
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
 	if (params->ssid)
@@ -1358,15 +1006,15 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
 		return -EOPNOTSUPP;
 	}
 
-	set_bit(WL_STATUS_CONNECTING, &cfg->status);
+	set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
 
 	if (params->bssid)
 		WL_CONN("BSSID: %pM\n", params->bssid);
 	else
 		WL_CONN("No BSSID specified\n");
 
-	if (params->channel)
-		WL_CONN("channel: %d\n", params->channel->center_freq);
+	if (params->chandef.chan)
+		WL_CONN("channel: %d\n", params->chandef.chan->center_freq);
 	else
 		WL_CONN("no channel specified\n");
 
@@ -1399,7 +1047,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
 	if (params->privacy)
 		wsec |= WEP_ENABLED;
 
-	err = brcmf_dev_intvar_set(ndev, "wsec", wsec);
+	err = brcmf_fil_iovar_int_set(ifp, "wsec", wsec);
 	if (err) {
 		WL_ERR("wsec failed (%d)\n", err);
 		goto done;
@@ -1411,7 +1059,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
 	else
 		bcnprd = 100;
 
-	err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_BCNPRD, &bcnprd);
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, bcnprd);
 	if (err) {
 		WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err);
 		goto done;
@@ -1434,17 +1082,17 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
 				   BRCMF_ASSOC_PARAMS_FIXED_SIZE;
 		memcpy(profile->bssid, params->bssid, ETH_ALEN);
 	} else {
-		memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN);
+		memset(join_params.params_le.bssid, 0xFF, ETH_ALEN);
 		memset(profile->bssid, 0, ETH_ALEN);
 	}
 
 	/* Channel */
-	if (params->channel) {
+	if (params->chandef.chan) {
 		u32 target_channel;
 
 		cfg->channel =
 			ieee80211_frequency_to_channel(
-				params->channel->center_freq);
+				params->chandef.chan->center_freq);
 		if (params->channel_fixed) {
 			/* adding chanspec */
 			brcmf_ch_to_chanspec(cfg->channel,
@@ -1453,8 +1101,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
 
 		/* set channel for starter */
 		target_channel = cfg->channel;
-		err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_CHANNEL,
-					  &target_channel);
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_CHANNEL,
+					    target_channel);
 		if (err) {
 			WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err);
 			goto done;
@@ -1465,8 +1113,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
 	cfg->ibss_starter = false;
 
 
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID,
-			   &join_params, join_params_size);
+	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
+				     &join_params, join_params_size);
 	if (err) {
 		WL_ERR("WLC_SET_SSID failed (%d)\n", err);
 		goto done;
@@ -1474,7 +1122,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
 
 done:
 	if (err)
-		clear_bit(WL_STATUS_CONNECTING, &cfg->status);
+		clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
 	WL_TRACE("Exit\n");
 	return err;
 }
@@ -1483,10 +1131,11 @@ static s32
 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
 {
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	s32 err = 0;
 
 	WL_TRACE("Enter\n");
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
 	brcmf_link_down(cfg);
@@ -1499,8 +1148,7 @@ brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
 static s32 brcmf_set_wpa_version(struct net_device *ndev,
 				 struct cfg80211_connect_params *sme)
 {
-	struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
-	struct brcmf_cfg80211_profile *profile = cfg->profile;
+	struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
 	struct brcmf_cfg80211_security *sec;
 	s32 val = 0;
 	s32 err = 0;
@@ -1512,7 +1160,7 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev,
 	else
 		val = WPA_AUTH_DISABLED;
 	WL_CONN("setting wpa_auth to 0x%0x\n", val);
-	err = brcmf_dev_intvar_set(ndev, "wpa_auth", val);
+	err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "wpa_auth", val);
 	if (err) {
 		WL_ERR("set wpa_auth failed (%d)\n", err);
 		return err;
@@ -1525,8 +1173,7 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev,
 static s32 brcmf_set_auth_type(struct net_device *ndev,
 			       struct cfg80211_connect_params *sme)
 {
-	struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
-	struct brcmf_cfg80211_profile *profile = cfg->profile;
+	struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
 	struct brcmf_cfg80211_security *sec;
 	s32 val = 0;
 	s32 err = 0;
@@ -1552,7 +1199,7 @@ static s32 brcmf_set_auth_type(struct net_device *ndev,
 		break;
 	}
 
-	err = brcmf_dev_intvar_set(ndev, "auth", val);
+	err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "auth", val);
 	if (err) {
 		WL_ERR("set auth failed (%d)\n", err);
 		return err;
@@ -1566,8 +1213,7 @@ static s32
 brcmf_set_set_cipher(struct net_device *ndev,
 		     struct cfg80211_connect_params *sme)
 {
-	struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
-	struct brcmf_cfg80211_profile *profile = cfg->profile;
+	struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
 	struct brcmf_cfg80211_security *sec;
 	s32 pval = 0;
 	s32 gval = 0;
@@ -1617,7 +1263,7 @@ brcmf_set_set_cipher(struct net_device *ndev,
 	}
 
 	WL_CONN("pval (%d) gval (%d)\n", pval, gval);
-	err = brcmf_dev_intvar_set(ndev, "wsec", pval | gval);
+	err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "wsec", pval | gval);
 	if (err) {
 		WL_ERR("error (%d)\n", err);
 		return err;
@@ -1633,14 +1279,14 @@ brcmf_set_set_cipher(struct net_device *ndev,
 static s32
 brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
 {
-	struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
-	struct brcmf_cfg80211_profile *profile = cfg->profile;
+	struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
 	struct brcmf_cfg80211_security *sec;
 	s32 val = 0;
 	s32 err = 0;
 
 	if (sme->crypto.n_akm_suites) {
-		err = brcmf_dev_intvar_get(ndev, "wpa_auth", &val);
+		err = brcmf_fil_iovar_int_get(netdev_priv(ndev),
+					      "wpa_auth", &val);
 		if (err) {
 			WL_ERR("could not get wpa_auth (%d)\n", err);
 			return err;
@@ -1674,7 +1320,8 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
 		}
 
 		WL_CONN("setting wpa_auth to %d\n", val);
-		err = brcmf_dev_intvar_set(ndev, "wpa_auth", val);
+		err = brcmf_fil_iovar_int_set(netdev_priv(ndev),
+					      "wpa_auth", val);
 		if (err) {
 			WL_ERR("could not set wpa_auth (%d)\n", err);
 			return err;
@@ -1690,13 +1337,11 @@ static s32
 brcmf_set_sharedkey(struct net_device *ndev,
 		    struct cfg80211_connect_params *sme)
 {
-	struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
-	struct brcmf_cfg80211_profile *profile = cfg->profile;
+	struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
 	struct brcmf_cfg80211_security *sec;
 	struct brcmf_wsec_key key;
 	s32 val;
 	s32 err = 0;
-	s32 bssidx;
 
 	WL_CONN("key len (%d)\n", sme->key_len);
 
@@ -1739,15 +1384,14 @@ brcmf_set_sharedkey(struct net_device *ndev,
 	WL_CONN("key length (%d) key index (%d) algo (%d)\n",
 		key.len, key.index, key.algo);
 	WL_CONN("key \"%s\"\n", key.data);
-	bssidx = brcmf_find_bssidx(cfg, ndev);
-	err = send_key_to_dongle(cfg, bssidx, ndev, &key);
+	err = send_key_to_dongle(ndev, &key);
 	if (err)
 		return err;
 
 	if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
 		WL_CONN("set auth_type to shared key\n");
 		val = WL_AUTH_SHARED_KEY;	/* shared key */
-		err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", val, bssidx);
+		err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "auth", val);
 		if (err)
 			WL_ERR("set auth failed (%d)\n", err);
 	}
@@ -1759,7 +1403,8 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
 		    struct cfg80211_connect_params *sme)
 {
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-	struct brcmf_cfg80211_profile *profile = cfg->profile;
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
 	struct ieee80211_channel *chan = sme->channel;
 	struct brcmf_join_params join_params;
 	size_t join_params_size;
@@ -1768,7 +1413,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
 	s32 err = 0;
 
 	WL_TRACE("Enter\n");
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
 	if (!sme->ssid) {
@@ -1776,7 +1421,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
 		return -EOPNOTSUPP;
 	}
 
-	set_bit(WL_STATUS_CONNECTING, &cfg->status);
+	set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
 
 	if (chan) {
 		cfg->channel =
@@ -1827,7 +1472,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
 	memcpy(&profile->ssid.SSID, sme->ssid, profile->ssid.SSID_len);
 	join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
 
-	memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN);
+	memset(join_params.params_le.bssid, 0xFF, ETH_ALEN);
 
 	if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN)
 		WL_CONN("ssid \"%s\", len (%d)\n",
@@ -1835,14 +1480,14 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
 
 	brcmf_ch_to_chanspec(cfg->channel,
 			     &join_params, &join_params_size);
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID,
-			   &join_params, join_params_size);
+	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
+				     &join_params, join_params_size);
 	if (err)
 		WL_ERR("WLC_SET_SSID failed (%d)\n", err);
 
 done:
 	if (err)
-		clear_bit(WL_STATUS_CONNECTING, &cfg->status);
+		clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
 	WL_TRACE("Exit\n");
 	return err;
 }
@@ -1852,20 +1497,21 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
 		       u16 reason_code)
 {
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-	struct brcmf_cfg80211_profile *profile = cfg->profile;
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
 	struct brcmf_scb_val_le scbval;
 	s32 err = 0;
 
 	WL_TRACE("Enter. Reason code = %d\n", reason_code);
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
-	clear_bit(WL_STATUS_CONNECTED, &cfg->status);
+	clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
 
 	memcpy(&scbval.ea, &profile->bssid, ETH_ALEN);
 	scbval.val = cpu_to_le32(reason_code);
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, &scbval,
-			      sizeof(struct brcmf_scb_val_le));
+	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_DISASSOC,
+				     &scbval, sizeof(scbval));
 	if (err)
 		WL_ERR("error (%d)\n", err);
 
@@ -1876,19 +1522,20 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
 }
 
 static s32
-brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
+brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
 			    enum nl80211_tx_power_setting type, s32 mbm)
 {
 
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
 	struct net_device *ndev = cfg_to_ndev(cfg);
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	u16 txpwrmw;
 	s32 err = 0;
 	s32 disable = 0;
 	s32 dbm = MBM_TO_DBM(mbm);
 
 	WL_TRACE("Enter\n");
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
 	switch (type) {
@@ -1905,7 +1552,7 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
 	}
 	/* Make sure radio is off or on as far as software is concerned */
 	disable = WL_RADIO_SW_DISABLE << 16;
-	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_RADIO, &disable);
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_RADIO, disable);
 	if (err)
 		WL_ERR("WLC_SET_RADIO error (%d)\n", err);
 
@@ -1913,8 +1560,8 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
 		txpwrmw = 0xffff;
 	else
 		txpwrmw = (u16) dbm;
-	err = brcmf_dev_intvar_set(ndev, "qtxpower",
-			(s32) (brcmf_mw_to_qdbm(txpwrmw)));
+	err = brcmf_fil_iovar_int_set(ifp, "qtxpower",
+				      (s32)brcmf_mw_to_qdbm(txpwrmw));
 	if (err)
 		WL_ERR("qtxpower error (%d)\n", err);
 	cfg->conf->tx_power = dbm;
@@ -1924,19 +1571,21 @@ done:
 	return err;
 }
 
-static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
+static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy,
+				       struct wireless_dev *wdev,
+				       s32 *dbm)
 {
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-	struct net_device *ndev = cfg_to_ndev(cfg);
+	struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
 	s32 txpwrdbm;
 	u8 result;
 	s32 err = 0;
 
 	WL_TRACE("Enter\n");
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
-	err = brcmf_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
+	err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &txpwrdbm);
 	if (err) {
 		WL_ERR("error (%d)\n", err);
 		goto done;
@@ -1954,19 +1603,17 @@ static s32
 brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
 			       u8 key_idx, bool unicast, bool multicast)
 {
-	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	u32 index;
 	u32 wsec;
 	s32 err = 0;
-	s32 bssidx;
 
 	WL_TRACE("Enter\n");
 	WL_CONN("key index (%d)\n", key_idx);
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
-	bssidx = brcmf_find_bssidx(cfg, ndev);
-	err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx);
+	err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
 	if (err) {
 		WL_ERR("WLC_GET_WSEC error (%d)\n", err);
 		goto done;
@@ -1975,8 +1622,8 @@ brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
 	if (wsec & WEP_ENABLED) {
 		/* Just select a new current key */
 		index = key_idx;
-		err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_KEY_PRIMARY,
-					  &index);
+		err = brcmf_fil_cmd_int_set(ifp,
+					    BRCMF_C_SET_KEY_PRIMARY, index);
 		if (err)
 			WL_ERR("error (%d)\n", err);
 	}
@@ -1989,11 +1636,8 @@ static s32
 brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
 	      u8 key_idx, const u8 *mac_addr, struct key_params *params)
 {
-	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
 	struct brcmf_wsec_key key;
-	struct brcmf_wsec_key_le key_le;
 	s32 err = 0;
-	s32 bssidx;
 
 	memset(&key, 0, sizeof(key));
 	key.index = (u32) key_idx;
@@ -2002,11 +1646,10 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
 	if (!is_multicast_ether_addr(mac_addr))
 		memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN);
 	key.len = (u32) params->key_len;
-	bssidx = brcmf_find_bssidx(cfg, ndev);
 	/* check for key index change */
 	if (key.len == 0) {
 		/* key delete */
-		err = send_key_to_dongle(cfg, bssidx, ndev, &key);
+		err = send_key_to_dongle(ndev, &key);
 		if (err)
 			WL_ERR("key delete error (%d)\n", err);
 	} else {
@@ -2061,13 +1704,7 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
 			WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
 			return -EINVAL;
 		}
-		convert_key_from_CPU(&key, &key_le);
-
-		brcmf_netdev_wait_pend8021x(ndev);
-		err  = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le,
-						     sizeof(key_le),
-						     cfg->extra_buf,
-						     WL_EXTRA_BUF_MAX, bssidx);
+		err = send_key_to_dongle(ndev, &key);
 		if (err)
 			WL_ERR("wsec_key error (%d)\n", err);
 	}
@@ -2080,16 +1717,16 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
 		    struct key_params *params)
 {
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_wsec_key key;
 	s32 val;
 	s32 wsec;
 	s32 err = 0;
 	u8 keybuf[8];
-	s32 bssidx;
 
 	WL_TRACE("Enter\n");
 	WL_CONN("key index (%d)\n", key_idx);
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
 	if (mac_addr) {
@@ -2147,18 +1784,17 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
 		goto done;
 	}
 
-	bssidx = brcmf_find_bssidx(cfg, ndev);
-	err = send_key_to_dongle(cfg, bssidx, ndev, &key);
+	err = send_key_to_dongle(ndev, &key);
 	if (err)
 		goto done;
 
-	err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx);
+	err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
 	if (err) {
 		WL_ERR("get wsec error (%d)\n", err);
 		goto done;
 	}
 	wsec |= val;
-	err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", wsec, bssidx);
+	err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
 	if (err) {
 		WL_ERR("set wsec error (%d)\n", err);
 		goto done;
@@ -2173,15 +1809,20 @@ static s32
 brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
 		    u8 key_idx, bool pairwise, const u8 *mac_addr)
 {
-	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_wsec_key key;
 	s32 err = 0;
-	s32 bssidx;
 
 	WL_TRACE("Enter\n");
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
+	if (key_idx >= DOT11_MAX_DEFAULT_KEYS) {
+		/* we ignore this key index in this case */
+		WL_ERR("invalid key index (%d)\n", key_idx);
+		return -EINVAL;
+	}
+
 	memset(&key, 0, sizeof(key));
 
 	key.index = (u32) key_idx;
@@ -2191,17 +1832,7 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
 	WL_CONN("key index (%d)\n", key_idx);
 
 	/* Set the new key/index */
-	bssidx = brcmf_find_bssidx(cfg, ndev);
-	err = send_key_to_dongle(cfg, bssidx, ndev, &key);
-	if (err) {
-		if (err == -EINVAL) {
-			if (key.index >= DOT11_MAX_DEFAULT_KEYS)
-				/* we ignore this key index in this case */
-				WL_ERR("invalid key index (%d)\n", key_idx);
-		}
-		/* Ignore this error, may happen during DISASSOC */
-		err = -EAGAIN;
-	}
+	err = send_key_to_dongle(ndev, &key);
 
 	WL_TRACE("Exit\n");
 	return err;
@@ -2213,22 +1844,20 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
 		    void (*callback) (void *cookie, struct key_params * params))
 {
 	struct key_params params;
-	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-	struct brcmf_cfg80211_profile *profile = cfg->profile;
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
 	struct brcmf_cfg80211_security *sec;
 	s32 wsec;
 	s32 err = 0;
-	s32 bssidx;
 
 	WL_TRACE("Enter\n");
 	WL_CONN("key index (%d)\n", key_idx);
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
 	memset(&params, 0, sizeof(params));
 
-	bssidx = brcmf_find_bssidx(cfg, ndev);
-	err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx);
+	err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
 	if (err) {
 		WL_ERR("WLC_GET_WSEC error (%d)\n", err);
 		/* Ignore this error, may happen during DISASSOC */
@@ -2280,33 +1909,33 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
 			   u8 *mac, struct station_info *sinfo)
 {
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-	struct brcmf_cfg80211_profile *profile = cfg->profile;
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
 	struct brcmf_scb_val_le scb_val;
 	int rssi;
 	s32 rate;
 	s32 err = 0;
 	u8 *bssid = profile->bssid;
-	struct brcmf_sta_info_le *sta_info_le;
+	struct brcmf_sta_info_le sta_info_le;
 
 	WL_TRACE("Enter, MAC %pM\n", mac);
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
 	if (cfg->conf->mode == WL_MODE_AP) {
-		err = brcmf_dev_iovar_getbuf(ndev, "sta_info", mac, ETH_ALEN,
-					     cfg->dcmd_buf,
-					     WL_DCMD_LEN_MAX);
+		memcpy(&sta_info_le, mac, ETH_ALEN);
+		err = brcmf_fil_iovar_data_get(ifp, "sta_info",
+					       &sta_info_le,
+					       sizeof(sta_info_le));
 		if (err < 0) {
 			WL_ERR("GET STA INFO failed, %d\n", err);
 			goto done;
 		}
-		sta_info_le = (struct brcmf_sta_info_le *)cfg->dcmd_buf;
-
 		sinfo->filled = STATION_INFO_INACTIVE_TIME;
-		sinfo->inactive_time = le32_to_cpu(sta_info_le->idle) * 1000;
-		if (le32_to_cpu(sta_info_le->flags) & BRCMF_STA_ASSOC) {
+		sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
+		if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) {
 			sinfo->filled |= STATION_INFO_CONNECTED_TIME;
-			sinfo->connected_time = le32_to_cpu(sta_info_le->in);
+			sinfo->connected_time = le32_to_cpu(sta_info_le.in);
 		}
 		WL_TRACE("STA idle time : %d ms, connected time :%d sec\n",
 			 sinfo->inactive_time, sinfo->connected_time);
@@ -2318,7 +1947,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
 			goto done;
 		}
 		/* Report the current tx rate */
-		err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate);
+	err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate);
 		if (err) {
 			WL_ERR("Could not get rate (%d)\n", err);
 			goto done;
@@ -2328,10 +1957,11 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
 			WL_CONN("Rate %d Mbps\n", rate / 2);
 		}
 
-		if (test_bit(WL_STATUS_CONNECTED, &cfg->status)) {
+		if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
+			     &ifp->vif->sme_state)) {
 			memset(&scb_val, 0, sizeof(scb_val));
-			err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val,
-					      sizeof(scb_val));
+			err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
+						     &scb_val, sizeof(scb_val));
 			if (err) {
 				WL_ERR("Could not get rssi (%d)\n", err);
 				goto done;
@@ -2356,6 +1986,7 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
 	s32 pm;
 	s32 err = 0;
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
 
 	WL_TRACE("Enter\n");
 
@@ -2367,7 +1998,7 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
 	 * FW later while initializing the dongle
 	 */
 	cfg->pwr_save = enabled;
-	if (!test_bit(WL_STATUS_READY, &cfg->status)) {
+	if (!check_vif_up(ifp->vif)) {
 
 		WL_INFO("Device is not ready, storing the value in cfg_info struct\n");
 		goto done;
@@ -2376,7 +2007,7 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
 	pm = enabled ? PM_FAST : PM_OFF;
 	WL_INFO("power save %s\n", (pm ? "enabled" : "disabled"));
 
-	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &pm);
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, pm);
 	if (err) {
 		if (err == -ENODEV)
 			WL_ERR("net_device is not ready yet\n");
@@ -2393,6 +2024,7 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
 			     const u8 *addr,
 			     const struct cfg80211_bitrate_mask *mask)
 {
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcm_rateset_le rateset_le;
 	s32 rate;
 	s32 val;
@@ -2402,13 +2034,13 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
 	s32 err = 0;
 
 	WL_TRACE("Enter\n");
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
 	/* addr param is always NULL. ignore it */
 	/* Get current rateset */
-	err = brcmf_exec_dcmd(ndev, BRCM_GET_CURR_RATESET, &rateset_le,
-			      sizeof(rateset_le));
+	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CURR_RATESET,
+				     &rateset_le, sizeof(rateset_le));
 	if (err) {
 		WL_ERR("could not get current rateset (%d)\n", err);
 		goto done;
@@ -2435,8 +2067,8 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
 	 *      Set rate override,
 	 *      Since the is a/b/g-blind, both a/bg_rate are enforced.
 	 */
-	err_bg = brcmf_dev_intvar_set(ndev, "bg_rate", rate);
-	err_a = brcmf_dev_intvar_set(ndev, "a_rate", rate);
+	err_bg = brcmf_fil_iovar_int_set(ifp, "bg_rate", rate);
+	err_a = brcmf_fil_iovar_int_set(ifp, "a_rate", rate);
 	if (err_bg && err_a) {
 		WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a);
 		err = err_bg | err_a;
@@ -2522,13 +2154,14 @@ static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg)
 	int i;
 
 	bss_list = cfg->bss_list;
-	if (bss_list->version != BRCMF_BSS_INFO_VERSION) {
+	if (bss_list->count != 0 &&
+	    bss_list->version != BRCMF_BSS_INFO_VERSION) {
 		WL_ERR("Version %d != WL_BSS_INFO_VERSION\n",
 		       bss_list->version);
 		return -EOPNOTSUPP;
 	}
 	WL_SCAN("scanned AP count (%d)\n", bss_list->count);
-	for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) {
+	for (i = 0; i < bss_list->count; i++) {
 		bi = next_bss_le(bss_list, bi);
 		err = brcmf_inform_single_bss(cfg, bi);
 		if (err)
@@ -2565,7 +2198,8 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
 
 	*(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
 
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
+	err = brcmf_fil_cmd_data_get(netdev_priv(ndev), BRCMF_C_GET_BSS_INFO,
+				     buf, WL_BSS_INFO_MAX);
 	if (err) {
 		WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err);
 		goto CleanUp;
@@ -2674,12 +2308,12 @@ brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len,
 	return false;
 }
 
-struct brcmf_vs_tlv *
+static struct brcmf_vs_tlv *
 brcmf_find_wpaie(u8 *parse, u32 len)
 {
 	struct brcmf_tlv *ie;
 
-	while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_WPA))) {
+	while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
 		if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,
 				     WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE))
 			return (struct brcmf_vs_tlv *)ie;
@@ -2689,7 +2323,9 @@ brcmf_find_wpaie(u8 *parse, u32 len)
 
 static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg)
 {
-	struct brcmf_cfg80211_profile *profile = cfg->profile;
+	struct net_device *ndev = cfg_to_ndev(cfg);
+	struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_bss_info_le *bi;
 	struct brcmf_ssid *ssid;
 	struct brcmf_tlv *tim;
@@ -2706,8 +2342,8 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg)
 	ssid = &profile->ssid;
 
 	*(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
-	err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCMF_C_GET_BSS_INFO,
-			cfg->extra_buf, WL_EXTRA_BUF_MAX);
+	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
+				     cfg->extra_buf, WL_EXTRA_BUF_MAX);
 	if (err) {
 		WL_ERR("Could not get bss info %d\n", err);
 		goto update_bss_info_out;
@@ -2732,8 +2368,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg)
 		* so we speficially query dtim information to dongle.
 		*/
 		u32 var;
-		err = brcmf_dev_intvar_get(cfg_to_ndev(cfg),
-					   "dtim_assoc", &var);
+		err = brcmf_fil_iovar_int_get(ifp, "dtim_assoc", &var);
 		if (err) {
 			WL_ERR("wl dtim_assoc failed (%d)\n", err);
 			goto update_bss_info_out;
@@ -2741,9 +2376,6 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg)
 		dtim_period = (u8)var;
 	}
 
-	profile->beacon_interval = beacon_interval;
-	profile->dtim_period = dtim_period;
-
 update_bss_info_out:
 	WL_TRACE("Exit");
 	return err;
@@ -2751,240 +2383,22 @@ update_bss_info_out:
 
 static void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg)
 {
-	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg);
 	struct escan_info *escan = &cfg->escan_info;
-	struct brcmf_ssid ssid;
 
-	set_bit(WL_STATUS_SCAN_ABORTING, &cfg->status);
-	if (cfg->iscan_on) {
-		iscan->state = WL_ISCAN_STATE_IDLE;
-
-		if (iscan->timer_on) {
-			del_timer_sync(&iscan->timer);
-			iscan->timer_on = 0;
-		}
-
-		cancel_work_sync(&iscan->work);
-
-		/* Abort iscan running in FW */
-		memset(&ssid, 0, sizeof(ssid));
-		brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT);
-
-		if (cfg->scan_request) {
-			/* Indidate scan abort to cfg80211 layer */
-			WL_INFO("Terminating scan in progress\n");
-			cfg80211_scan_done(cfg->scan_request, true);
-			cfg->scan_request = NULL;
-		}
-	}
-	if (cfg->escan_on && cfg->scan_request) {
+	set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
+	if (cfg->scan_request) {
 		escan->escan_state = WL_ESCAN_STATE_IDLE;
 		brcmf_notify_escan_complete(cfg, escan->ndev, true, true);
 	}
-	clear_bit(WL_STATUS_SCANNING, &cfg->status);
-	clear_bit(WL_STATUS_SCAN_ABORTING, &cfg->status);
+	clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
+	clear_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
 }
 
-static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
-					bool aborted)
+static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work)
 {
-	struct brcmf_cfg80211_info *cfg = iscan_to_cfg(iscan);
-	struct net_device *ndev = cfg_to_ndev(cfg);
-
-	if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) {
-		WL_ERR("Scan complete while device not scanning\n");
-		return;
-	}
-	if (cfg->scan_request) {
-		WL_SCAN("ISCAN Completed scan: %s\n",
-				aborted ? "Aborted" : "Done");
-		cfg80211_scan_done(cfg->scan_request, aborted);
-		brcmf_set_mpc(ndev, 1);
-		cfg->scan_request = NULL;
-	}
-	cfg->iscan_kickstart = false;
-}
-
-static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan)
-{
-	if (iscan->state != WL_ISCAN_STATE_IDLE) {
-		WL_SCAN("wake up iscan\n");
-		schedule_work(&iscan->work);
-		return 0;
-	}
-
-	return -EIO;
-}
-
-static s32
-brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status,
-		     struct brcmf_scan_results **bss_list)
-{
-	struct brcmf_iscan_results list;
-	struct brcmf_scan_results *results;
-	struct brcmf_scan_results_le *results_le;
-	struct brcmf_iscan_results *list_buf;
-	s32 err = 0;
-
-	memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
-	list_buf = (struct brcmf_iscan_results *)iscan->scan_buf;
-	results = &list_buf->results;
-	results_le = &list_buf->results_le;
-	results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE;
-	results->version = 0;
-	results->count = 0;
-
-	memset(&list, 0, sizeof(list));
-	list.results_le.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX);
-	err = brcmf_dev_iovar_getbuf(iscan->ndev, "iscanresults", &list,
-				     BRCMF_ISCAN_RESULTS_FIXED_SIZE,
-				     iscan->scan_buf, WL_ISCAN_BUF_MAX);
-	if (err) {
-		WL_ERR("error (%d)\n", err);
-		return err;
-	}
-	results->buflen = le32_to_cpu(results_le->buflen);
-	results->version = le32_to_cpu(results_le->version);
-	results->count = le32_to_cpu(results_le->count);
-	WL_SCAN("results->count = %d\n", results_le->count);
-	WL_SCAN("results->buflen = %d\n", results_le->buflen);
-	*status = le32_to_cpu(list_buf->status_le);
-	WL_SCAN("status = %d\n", *status);
-	*bss_list = results;
-
-	return err;
-}
-
-static s32 brcmf_iscan_done(struct brcmf_cfg80211_info *cfg)
-{
-	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan;
-	s32 err = 0;
-
-	iscan->state = WL_ISCAN_STATE_IDLE;
-	brcmf_inform_bss(cfg);
-	brcmf_notify_iscan_complete(iscan, false);
-
-	return err;
-}
-
-static s32 brcmf_iscan_pending(struct brcmf_cfg80211_info *cfg)
-{
-	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan;
-	s32 err = 0;
-
-	/* Reschedule the timer */
-	mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
-	iscan->timer_on = 1;
-
-	return err;
-}
-
-static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_info *cfg)
-{
-	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan;
-	s32 err = 0;
-
-	brcmf_inform_bss(cfg);
-	brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE);
-	/* Reschedule the timer */
-	mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
-	iscan->timer_on = 1;
-
-	return err;
-}
-
-static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_info *cfg)
-{
-	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan;
-	s32 err = 0;
-
-	iscan->state = WL_ISCAN_STATE_IDLE;
-	brcmf_notify_iscan_complete(iscan, true);
-
-	return err;
-}
-
-static void brcmf_cfg80211_iscan_handler(struct work_struct *work)
-{
-	struct brcmf_cfg80211_iscan_ctrl *iscan =
-			container_of(work, struct brcmf_cfg80211_iscan_ctrl,
-				     work);
-	struct brcmf_cfg80211_info *cfg = iscan_to_cfg(iscan);
-	struct brcmf_cfg80211_iscan_eloop *el = &iscan->el;
-	u32 status = BRCMF_SCAN_RESULTS_PARTIAL;
-
-	if (iscan->timer_on) {
-		del_timer_sync(&iscan->timer);
-		iscan->timer_on = 0;
-	}
-
-	if (brcmf_get_iscan_results(iscan, &status, &cfg->bss_list)) {
-		status = BRCMF_SCAN_RESULTS_ABORTED;
-		WL_ERR("Abort iscan\n");
-	}
-
-	el->handler[status](cfg);
-}
-
-static void brcmf_iscan_timer(unsigned long data)
-{
-	struct brcmf_cfg80211_iscan_ctrl *iscan =
-			(struct brcmf_cfg80211_iscan_ctrl *)data;
-
-	if (iscan) {
-		iscan->timer_on = 0;
-		WL_SCAN("timer expired\n");
-		brcmf_wakeup_iscan(iscan);
-	}
-}
-
-static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_info *cfg)
-{
-	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg);
-
-	if (cfg->iscan_on) {
-		iscan->state = WL_ISCAN_STATE_IDLE;
-		INIT_WORK(&iscan->work, brcmf_cfg80211_iscan_handler);
-	}
-
-	return 0;
-}
-
-static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el)
-{
-	memset(el, 0, sizeof(*el));
-	el->handler[BRCMF_SCAN_RESULTS_SUCCESS] = brcmf_iscan_done;
-	el->handler[BRCMF_SCAN_RESULTS_PARTIAL] = brcmf_iscan_inprogress;
-	el->handler[BRCMF_SCAN_RESULTS_PENDING] = brcmf_iscan_pending;
-	el->handler[BRCMF_SCAN_RESULTS_ABORTED] = brcmf_iscan_aborted;
-	el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted;
-}
-
-static s32 brcmf_init_iscan(struct brcmf_cfg80211_info *cfg)
-{
-	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg);
-	int err = 0;
-
-	if (cfg->iscan_on) {
-		iscan->ndev = cfg_to_ndev(cfg);
-		brcmf_init_iscan_eloop(&iscan->el);
-		iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
-		init_timer(&iscan->timer);
-		iscan->timer.data = (unsigned long) iscan;
-		iscan->timer.function = brcmf_iscan_timer;
-		err = brcmf_invoke_iscan(cfg);
-		if (!err)
-			iscan->data = cfg;
-	}
-
-	return err;
-}
-
-static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work)
-{
-	struct brcmf_cfg80211_info *cfg =
-			container_of(work, struct brcmf_cfg80211_info,
-				     escan_timeout_work);
+	struct brcmf_cfg80211_info *cfg =
+			container_of(work, struct brcmf_cfg80211_info,
+				     escan_timeout_work);
 
 	brcmf_notify_escan_complete(cfg,
 		cfg->escan_info.ndev, true, true);
@@ -2997,8 +2411,7 @@ static void brcmf_escan_timeout(unsigned long data)
 
 	if (cfg->scan_request) {
 		WL_ERR("timer expired\n");
-		if (cfg->escan_on)
-			schedule_work(&cfg->escan_timeout_work);
+		schedule_work(&cfg->escan_timeout_work);
 	}
 }
 
@@ -3035,10 +2448,11 @@ brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss,
 }
 
 static s32
-brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg,
-			     struct net_device *ndev,
+brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
 			     const struct brcmf_event_msg *e, void *data)
 {
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	struct net_device *ndev = ifp->ndev;
 	s32 status;
 	s32 err = 0;
 	struct brcmf_escan_result_le *escan_result_le;
@@ -3049,13 +2463,11 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg,
 	u32 i;
 	bool aborted;
 
-	status = be32_to_cpu(e->status);
+	status = e->status;
 
-	if (!ndev || !cfg->escan_on ||
-			!test_bit(WL_STATUS_SCANNING, &cfg->status)) {
-		WL_ERR("scan not ready ndev %p wl->escan_on %d drv_status %x\n",
-			ndev, cfg->escan_on,
-			!test_bit(WL_STATUS_SCANNING, &cfg->status));
+	if (!ndev || !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
+		WL_ERR("scan not ready ndev %p drv_status %x\n", ndev,
+		       !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status));
 		return -EPERM;
 	}
 
@@ -3132,18 +2544,15 @@ exit:
 
 static void brcmf_init_escan(struct brcmf_cfg80211_info *cfg)
 {
-
-	if (cfg->escan_on) {
-		cfg->el.handler[BRCMF_E_ESCAN_RESULT] =
-			brcmf_cfg80211_escan_handler;
-		cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
-		/* Init scan_timeout timer */
-		init_timer(&cfg->escan_timeout);
-		cfg->escan_timeout.data = (unsigned long) cfg;
-		cfg->escan_timeout.function = brcmf_escan_timeout;
-		INIT_WORK(&cfg->escan_timeout_work,
-			brcmf_cfg80211_escan_timeout_worker);
-	}
+	brcmf_fweh_register(cfg->pub, BRCMF_E_ESCAN_RESULT,
+			    brcmf_cfg80211_escan_handler);
+	cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
+	/* Init scan_timeout timer */
+	init_timer(&cfg->escan_timeout);
+	cfg->escan_timeout.data = (unsigned long) cfg;
+	cfg->escan_timeout.function = brcmf_escan_timeout;
+	INIT_WORK(&cfg->escan_timeout_work,
+		  brcmf_cfg80211_escan_timeout_worker);
 }
 
 static __always_inline void brcmf_delay(u32 ms)
@@ -3158,19 +2567,8 @@ static __always_inline void brcmf_delay(u32 ms)
 
 static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
 {
-	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-
-	/*
-	 * Check for WL_STATUS_READY before any function call which
-	 * could result is bus access. Don't block the resume for
-	 * any driver error conditions
-	 */
 	WL_TRACE("Enter\n");
 
-	if (test_bit(WL_STATUS_READY, &cfg->status))
-		brcmf_invoke_iscan(wiphy_to_cfg(wiphy));
-
-	WL_TRACE("Exit\n");
 	return 0;
 }
 
@@ -3179,85 +2577,53 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
 {
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
 	struct net_device *ndev = cfg_to_ndev(cfg);
+	struct brcmf_cfg80211_vif *vif;
 
 	WL_TRACE("Enter\n");
 
 	/*
-	 * Check for WL_STATUS_READY before any function call which
-	 * could result is bus access. Don't block the suspend for
-	 * any driver error conditions
-	 */
-
-	/*
-	 * While going to suspend if associated with AP disassociate
-	 * from AP to save power while system is in suspended state
+	 * if the primary net_device is not READY there is nothing
+	 * we can do but pray resume goes smoothly.
 	 */
-	if ((test_bit(WL_STATUS_CONNECTED, &cfg->status) ||
-	     test_bit(WL_STATUS_CONNECTING, &cfg->status)) &&
-	     test_bit(WL_STATUS_READY, &cfg->status)) {
-		WL_INFO("Disassociating from AP"
-			" while entering suspend state\n");
-		brcmf_link_down(cfg);
+	vif = ((struct brcmf_if *)netdev_priv(ndev))->vif;
+	if (!check_vif_up(vif))
+		goto exit;
 
+	list_for_each_entry(vif, &cfg->vif_list, list) {
+		if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state))
+			continue;
 		/*
-		 * Make sure WPA_Supplicant receives all the event
-		 * generated due to DISASSOC call to the fw to keep
-		 * the state fw and WPA_Supplicant state consistent
+		 * While going to suspend if associated with AP disassociate
+		 * from AP to save power while system is in suspended state
 		 */
-		brcmf_delay(500);
+		if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state) ||
+		    test_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state)) {
+			WL_INFO("Disassociating from AP before suspend\n");
+			brcmf_link_down(cfg);
+
+			/* Make sure WPA_Supplicant receives all the event
+			 * generated due to DISASSOC call to the fw to keep
+			 * the state fw and WPA_Supplicant state consistent
+			 */
+			brcmf_delay(500);
+		}
 	}
 
-	if (test_bit(WL_STATUS_READY, &cfg->status))
+	/* end any scanning */
+	if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))
 		brcmf_abort_scanning(cfg);
-	else
-		clear_bit(WL_STATUS_SCANNING, &cfg->status);
 
 	/* Turn off watchdog timer */
-	if (test_bit(WL_STATUS_READY, &cfg->status))
-		brcmf_set_mpc(ndev, 1);
+	brcmf_set_mpc(ndev, 1);
 
+exit:
 	WL_TRACE("Exit\n");
-
+	/* clear any scanning activity */
+	cfg->scan_status = 0;
 	return 0;
 }
 
 static __used s32
-brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len)
-{
-	struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
-	u32 buflen;
-
-	buflen = brcmf_c_mkiovar(name, buf, len, cfg->dcmd_buf,
-			       WL_DCMD_LEN_MAX);
-	BUG_ON(!buflen);
-
-	return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg->dcmd_buf,
-			       buflen);
-}
-
-static s32
-brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf,
-		  s32 buf_len)
-{
-	struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
-	u32 len;
-	s32 err = 0;
-
-	len = brcmf_c_mkiovar(name, NULL, 0, cfg->dcmd_buf,
-			    WL_DCMD_LEN_MAX);
-	BUG_ON(!len);
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg->dcmd_buf,
-			      WL_DCMD_LEN_MAX);
-	if (err) {
-		WL_ERR("error (%d)\n", err);
-		return err;
-	}
-	memcpy(buf, cfg->dcmd_buf, buf_len);
-
-	return err;
-}
-
-static __used s32
 brcmf_update_pmklist(struct net_device *ndev,
 		     struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
 {
@@ -3275,8 +2641,8 @@ brcmf_update_pmklist(struct net_device *ndev,
 	}
 
 	if (!err)
-		brcmf_dev_bufvar_set(ndev, "pmkid_info", (char *)pmk_list,
-					sizeof(*pmk_list));
+		brcmf_fil_iovar_data_set(netdev_priv(ndev), "pmkid_info",
+					 (char *)pmk_list, sizeof(*pmk_list));
 
 	return err;
 }
@@ -3286,13 +2652,14 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
 			 struct cfg80211_pmksa *pmksa)
 {
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct pmkid_list *pmkids = &cfg->pmk_list->pmkids;
 	s32 err = 0;
 	int i;
 	int pmkid_len;
 
 	WL_TRACE("Enter\n");
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
 	pmkid_len = le32_to_cpu(pmkids->npmkid);
@@ -3325,12 +2692,13 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
 		      struct cfg80211_pmksa *pmksa)
 {
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct pmkid_list pmkid;
 	s32 err = 0;
 	int i, pmkid_len;
 
 	WL_TRACE("Enter\n");
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
 	memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
@@ -3375,10 +2743,11 @@ static s32
 brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
 {
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	s32 err = 0;
 
 	WL_TRACE("Enter\n");
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
 	memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list));
@@ -3398,10 +2767,11 @@ brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
  * cfg80211_scan_request one out of the received PNO event.
  */
 static s32
-brcmf_notify_sched_scan_results(struct brcmf_cfg80211_info *cfg,
-				struct net_device *ndev,
+brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
 				const struct brcmf_event_msg *e, void *data)
 {
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	struct net_device *ndev = ifp->ndev;
 	struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
 	struct cfg80211_scan_request *request = NULL;
 	struct cfg80211_ssid *ssid = NULL;
@@ -3416,7 +2786,7 @@ brcmf_notify_sched_scan_results(struct brcmf_cfg80211_info *cfg,
 
 	WL_SCAN("Enter\n");
 
-	if (e->event_type == cpu_to_be32(BRCMF_E_PFN_NET_LOST)) {
+	if (e->event_code == BRCMF_E_PFN_NET_LOST) {
 		WL_SCAN("PFN NET LOST event. Do Nothing\n");
 		return 0;
 	}
@@ -3478,15 +2848,15 @@ brcmf_notify_sched_scan_results(struct brcmf_cfg80211_info *cfg,
 		if (request->n_ssids)
 			request->ssids = &ssid[0];
 
-		if (test_bit(WL_STATUS_SCANNING, &cfg->status)) {
+		if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
 			/* Abort any on-going scan */
 			brcmf_abort_scanning(cfg);
 		}
 
-		set_bit(WL_STATUS_SCANNING, &cfg->status);
+		set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
 		err = brcmf_do_escan(cfg, wiphy, ndev, request);
 		if (err) {
-			clear_bit(WL_STATUS_SCANNING, &cfg->status);
+			clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
 			goto out_err;
 		}
 		cfg->sched_escan = true;
@@ -3509,18 +2879,16 @@ out_err:
 	return err;
 }
 
-#ifndef CONFIG_BRCMISCAN
 static int brcmf_dev_pno_clean(struct net_device *ndev)
 {
-	char iovbuf[128];
 	int ret;
 
 	/* Disable pfn */
-	ret = brcmf_dev_intvar_set(ndev, "pfn", 0);
+	ret = brcmf_fil_iovar_int_set(netdev_priv(ndev), "pfn", 0);
 	if (ret == 0) {
 		/* clear pfn */
-		ret = brcmf_dev_iovar_setbuf(ndev, "pfnclear", NULL, 0,
-					     iovbuf, sizeof(iovbuf));
+		ret = brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfnclear",
+					       NULL, 0);
 	}
 	if (ret < 0)
 		WL_ERR("failed code %d\n", ret);
@@ -3531,7 +2899,6 @@ static int brcmf_dev_pno_clean(struct net_device *ndev)
 static int brcmf_dev_pno_config(struct net_device *ndev)
 {
 	struct brcmf_pno_param_le pfn_param;
-	char iovbuf[128];
 
 	memset(&pfn_param, 0, sizeof(pfn_param));
 	pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION);
@@ -3544,9 +2911,8 @@ static int brcmf_dev_pno_config(struct net_device *ndev)
 	/* set up pno scan fr */
 	pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME);
 
-	return brcmf_dev_iovar_setbuf(ndev, "pfn_set",
-				      &pfn_param, sizeof(pfn_param),
-				      iovbuf, sizeof(iovbuf));
+	return brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfn_set",
+					&pfn_param, sizeof(pfn_param));
 }
 
 static int
@@ -3554,7 +2920,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
 				struct net_device *ndev,
 				struct cfg80211_sched_scan_request *request)
 {
-	char iovbuf[128];
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
 	struct brcmf_pno_net_param_le pfn;
 	int i;
@@ -3562,8 +2928,8 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
 
 	WL_SCAN("Enter n_match_sets:%d   n_ssids:%d\n",
 		request->n_match_sets, request->n_ssids);
-	if (test_bit(WL_STATUS_SCANNING, &cfg->status)) {
-		WL_ERR("Scanning already : status (%lu)\n", cfg->status);
+	if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
+		WL_ERR("Scanning already: status (%lu)\n", cfg->scan_status);
 		return -EAGAIN;
 	}
 
@@ -3620,15 +2986,14 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
 			pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
 			pfn.ssid.SSID_len = cpu_to_le32(ssid_len);
 			memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len);
-			ret = brcmf_dev_iovar_setbuf(ndev, "pfn_add",
-						     &pfn, sizeof(pfn),
-						     iovbuf, sizeof(iovbuf));
+			ret = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn,
+						       sizeof(pfn));
 			WL_SCAN(">>> PNO filter %s for ssid (%s)\n",
 				ret == 0 ? "set" : "failed",
 				ssid->ssid);
 		}
 		/* Enable the PNO */
-		if (brcmf_dev_intvar_set(ndev, "pfn", 1) < 0) {
+		if (brcmf_fil_iovar_int_set(ifp, "pfn", 1) < 0) {
 			WL_ERR("PNO enable failed!! ret=%d\n", ret);
 			return -EINVAL;
 		}
@@ -3650,18 +3015,25 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
 		brcmf_notify_escan_complete(cfg, ndev, true, true);
 	return 0;
 }
-#endif /* CONFIG_BRCMISCAN */
 
 #ifdef CONFIG_NL80211_TESTMODE
 static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
 {
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-	struct net_device *ndev = cfg->wdev->netdev;
+	struct net_device *ndev = cfg_to_ndev(cfg);
 	struct brcmf_dcmd *dcmd = data;
 	struct sk_buff *reply;
 	int ret;
 
-	ret = brcmf_netlink_dcmd(ndev, dcmd);
+	WL_TRACE("cmd %x set %d buf %p len %d\n", dcmd->cmd, dcmd->set,
+		 dcmd->buf, dcmd->len);
+
+	if (dcmd->set)
+		ret = brcmf_fil_cmd_data_set(netdev_priv(ndev), dcmd->cmd,
+					     dcmd->buf, dcmd->len);
+	else
+		ret = brcmf_fil_cmd_data_get(netdev_priv(ndev), dcmd->cmd,
+					     dcmd->buf, dcmd->len);
 	if (ret == 0) {
 		reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd));
 		nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd);
@@ -3673,23 +3045,23 @@ static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
 
 static s32 brcmf_configure_opensecurity(struct net_device *ndev, s32 bssidx)
 {
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	s32 err;
 
 	/* set auth */
-	err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", 0, bssidx);
+	err = brcmf_fil_bsscfg_int_set(ifp, "auth", 0);
 	if (err < 0) {
 		WL_ERR("auth error %d\n", err);
 		return err;
 	}
 	/* set wsec */
-	err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", 0, bssidx);
+	err = brcmf_fil_bsscfg_int_set(ifp, "wsec", 0);
 	if (err < 0) {
 		WL_ERR("wsec error %d\n", err);
 		return err;
 	}
 	/* set upper-layer auth */
-	err = brcmf_dev_intvar_set_bsscfg(ndev, "wpa_auth",
-					  WPA_AUTH_NONE, bssidx);
+	err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", WPA_AUTH_NONE);
 	if (err < 0) {
 		WL_ERR("wpa_auth error %d\n", err);
 		return err;
@@ -3708,8 +3080,9 @@ static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie)
 
 static s32
 brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
-		     bool is_rsn_ie, s32 bssidx)
+		     bool is_rsn_ie)
 {
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	u32 auth = 0; /* d11 open authentication */
 	u16 count;
 	s32 err = 0;
@@ -3850,8 +3223,8 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
 				wme_bss_disable = 0;
 		}
 		/* set wme_bss_disable to sync RSN Capabilities */
-		err = brcmf_dev_intvar_set_bsscfg(ndev, "wme_bss_disable",
-						  wme_bss_disable, bssidx);
+		err = brcmf_fil_bsscfg_int_set(ifp, "wme_bss_disable",
+					       wme_bss_disable);
 		if (err < 0) {
 			WL_ERR("wme_bss_disable error %d\n", err);
 			goto exit;
@@ -3861,19 +3234,19 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
 	wsec = (pval | gval | SES_OW_ENABLED);
 
 	/* set auth */
-	err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", auth, bssidx);
+	err = brcmf_fil_bsscfg_int_set(ifp, "auth", auth);
 	if (err < 0) {
 		WL_ERR("auth error %d\n", err);
 		goto exit;
 	}
 	/* set wsec */
-	err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", wsec, bssidx);
+	err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
 	if (err < 0) {
 		WL_ERR("wsec error %d\n", err);
 		goto exit;
 	}
 	/* set upper-layer auth */
-	err = brcmf_dev_intvar_set_bsscfg(ndev, "wpa_auth", wpa_auth, bssidx);
+	err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_auth);
 	if (err < 0) {
 		WL_ERR("wpa_auth error %d\n", err);
 		goto exit;
@@ -3884,7 +3257,7 @@ exit:
 }
 
 static s32
-brcmf_parse_vndr_ies(u8 *vndr_ie_buf, u32 vndr_ie_len,
+brcmf_parse_vndr_ies(const u8 *vndr_ie_buf, u32 vndr_ie_len,
 		     struct parsed_vndr_ies *vndr_ies)
 {
 	s32 err = 0;
@@ -3963,17 +3336,18 @@ brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd)
 	return ie_len + VNDR_IE_HDR_SIZE;
 }
 
-s32
-brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
-			struct net_device *ndev, s32 bssidx, s32 pktflag,
-			u8 *vndr_ie_buf, u32 vndr_ie_len)
+static
+s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
+			  const u8 *vndr_ie_buf, u32 vndr_ie_len)
 {
+	struct brcmf_if *ifp;
+	struct vif_saved_ie *saved_ie;
 	s32 err = 0;
 	u8  *iovar_ie_buf;
 	u8  *curr_ie_buf;
 	u8  *mgmt_ie_buf = NULL;
 	int mgmt_ie_buf_len;
-	u32 *mgmt_ie_len = 0;
+	u32 *mgmt_ie_len;
 	u32 del_add_ie_buf_len = 0;
 	u32 total_ie_buf_len = 0;
 	u32 parsed_ie_buf_len = 0;
@@ -3984,31 +3358,33 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
 	u8 *ptr;
 	int remained_buf_len;
 
-	WL_TRACE("bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag);
+	if (!vif)
+		return -ENODEV;
+	ifp = vif->ifp;
+	saved_ie = &vif->saved_ie;
+
+	WL_TRACE("bssidx %d, pktflag : 0x%02X\n", ifp->bssidx, pktflag);
 	iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
 	if (!iovar_ie_buf)
 		return -ENOMEM;
 	curr_ie_buf = iovar_ie_buf;
-	if (test_bit(WL_STATUS_AP_CREATING, &cfg->status) ||
-	    test_bit(WL_STATUS_AP_CREATED, &cfg->status)) {
+	if (ifp->vif->mode == WL_MODE_AP) {
 		switch (pktflag) {
 		case VNDR_IE_PRBRSP_FLAG:
-			mgmt_ie_buf = cfg->ap_info->probe_res_ie;
-			mgmt_ie_len = &cfg->ap_info->probe_res_ie_len;
-			mgmt_ie_buf_len =
-				sizeof(cfg->ap_info->probe_res_ie);
+			mgmt_ie_buf = saved_ie->probe_res_ie;
+			mgmt_ie_len = &saved_ie->probe_res_ie_len;
+			mgmt_ie_buf_len = sizeof(saved_ie->probe_res_ie);
 			break;
 		case VNDR_IE_BEACON_FLAG:
-			mgmt_ie_buf = cfg->ap_info->beacon_ie;
-			mgmt_ie_len = &cfg->ap_info->beacon_ie_len;
-			mgmt_ie_buf_len = sizeof(cfg->ap_info->beacon_ie);
+			mgmt_ie_buf = saved_ie->beacon_ie;
+			mgmt_ie_len = &saved_ie->beacon_ie_len;
+			mgmt_ie_buf_len = sizeof(saved_ie->beacon_ie);
 			break;
 		default:
 			err = -EPERM;
 			WL_ERR("not suitable type\n");
 			goto exit;
 		}
-		bssidx = 0;
 	} else {
 		err = -EPERM;
 		WL_ERR("not suitable type\n");
@@ -4104,11 +3480,8 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
 		}
 	}
 	if (total_ie_buf_len) {
-		err  = brcmf_dev_iovar_setbuf_bsscfg(ndev, "vndr_ie",
-						     iovar_ie_buf,
-						     total_ie_buf_len,
-						     cfg->extra_buf,
-						     WL_EXTRA_BUF_MAX, bssidx);
+		err  = brcmf_fil_bsscfg_data_set(ifp, "vndr_ie", iovar_ie_buf,
+						 total_ie_buf_len);
 		if (err)
 			WL_ERR("vndr ie set error : %d\n", err);
 	}
@@ -4123,24 +3496,24 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
 			struct cfg80211_ap_settings *settings)
 {
 	s32 ie_offset;
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_tlv *ssid_ie;
 	struct brcmf_ssid_le ssid_le;
-	s32 ioctl_value;
 	s32 err = -EPERM;
 	struct brcmf_tlv *rsn_ie;
 	struct brcmf_vs_tlv *wpa_ie;
 	struct brcmf_join_params join_params;
-	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
 	s32 bssidx = 0;
 
 	WL_TRACE("channel_type=%d, beacon_interval=%d, dtim_period=%d,\n",
-		 settings->channel_type, settings->beacon_interval,
+		 cfg80211_get_chandef_type(&settings->chandef),
+		 settings->beacon_interval,
 		 settings->dtim_period);
-	WL_TRACE("ssid=%s(%d), auth_type=%d, inactivity_timeout=%d\n",
+	WL_TRACE("ssid=%s(%zu), auth_type=%d, inactivity_timeout=%d\n",
 		 settings->ssid, settings->ssid_len, settings->auth_type,
 		 settings->inactivity_timeout);
 
-	if (!test_bit(WL_STATUS_AP_CREATING, &cfg->status)) {
+	if (!test_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state)) {
 		WL_ERR("Not in AP creation mode\n");
 		return -EPERM;
 	}
@@ -4164,20 +3537,17 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
 	}
 
 	brcmf_set_mpc(ndev, 0);
-	ioctl_value = 1;
-	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_DOWN, &ioctl_value);
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
 	if (err < 0) {
 		WL_ERR("BRCMF_C_DOWN error %d\n", err);
 		goto exit;
 	}
-	ioctl_value = 1;
-	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &ioctl_value);
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1);
 	if (err < 0) {
 		WL_ERR("SET INFRA error %d\n", err);
 		goto exit;
 	}
-	ioctl_value = 1;
-	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AP, &ioctl_value);
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1);
 	if (err < 0) {
 		WL_ERR("setting AP mode failed %d\n", err);
 		goto exit;
@@ -4191,80 +3561,61 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
 	wpa_ie = brcmf_find_wpaie((u8 *)settings->beacon.tail,
 				  settings->beacon.tail_len);
 
-	kfree(cfg->ap_info->rsn_ie);
-	cfg->ap_info->rsn_ie = NULL;
-	kfree(cfg->ap_info->wpa_ie);
-	cfg->ap_info->wpa_ie = NULL;
-
 	if ((wpa_ie != NULL || rsn_ie != NULL)) {
 		WL_TRACE("WPA(2) IE is found\n");
 		if (wpa_ie != NULL) {
 			/* WPA IE */
-			err = brcmf_configure_wpaie(ndev, wpa_ie, false,
-						    bssidx);
+			err = brcmf_configure_wpaie(ndev, wpa_ie, false);
 			if (err < 0)
 				goto exit;
-			cfg->ap_info->wpa_ie = kmemdup(wpa_ie,
-							    wpa_ie->len +
-							    TLV_HDR_LEN,
-							    GFP_KERNEL);
 		} else {
 			/* RSN IE */
 			err = brcmf_configure_wpaie(ndev,
-				(struct brcmf_vs_tlv *)rsn_ie, true, bssidx);
+				(struct brcmf_vs_tlv *)rsn_ie, true);
 			if (err < 0)
 				goto exit;
-			cfg->ap_info->rsn_ie = kmemdup(rsn_ie,
-							    rsn_ie->len +
-							    TLV_HDR_LEN,
-							    GFP_KERNEL);
 		}
-		cfg->ap_info->security_mode = true;
 	} else {
 		WL_TRACE("No WPA(2) IEs found\n");
 		brcmf_configure_opensecurity(ndev, bssidx);
-		cfg->ap_info->security_mode = false;
 	}
 	/* Set Beacon IEs to FW */
-	err = brcmf_set_management_ie(cfg, ndev, bssidx,
-				      VNDR_IE_BEACON_FLAG,
-				      (u8 *)settings->beacon.tail,
-				      settings->beacon.tail_len);
+	err = brcmf_vif_set_mgmt_ie(ndev_to_vif(ndev),
+				    VNDR_IE_BEACON_FLAG,
+				    settings->beacon.tail,
+				    settings->beacon.tail_len);
 	if (err)
 		WL_ERR("Set Beacon IE Failed\n");
 	else
 		WL_TRACE("Applied Vndr IEs for Beacon\n");
 
 	/* Set Probe Response IEs to FW */
-	err = brcmf_set_management_ie(cfg, ndev, bssidx,
-				      VNDR_IE_PRBRSP_FLAG,
-				      (u8 *)settings->beacon.proberesp_ies,
-				      settings->beacon.proberesp_ies_len);
+	err = brcmf_vif_set_mgmt_ie(ndev_to_vif(ndev),
+				    VNDR_IE_PRBRSP_FLAG,
+				    settings->beacon.proberesp_ies,
+				    settings->beacon.proberesp_ies_len);
 	if (err)
 		WL_ERR("Set Probe Resp IE Failed\n");
 	else
 		WL_TRACE("Applied Vndr IEs for Probe Resp\n");
 
 	if (settings->beacon_interval) {
-		ioctl_value = settings->beacon_interval;
-		err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_BCNPRD,
-					  &ioctl_value);
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
+					    settings->beacon_interval);
 		if (err < 0) {
 			WL_ERR("Beacon Interval Set Error, %d\n", err);
 			goto exit;
 		}
 	}
 	if (settings->dtim_period) {
-		ioctl_value = settings->dtim_period;
-		err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_DTIMPRD,
-					  &ioctl_value);
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD,
+					    settings->dtim_period);
 		if (err < 0) {
 			WL_ERR("DTIM Interval Set Error, %d\n", err);
 			goto exit;
 		}
 	}
-	ioctl_value = 1;
-	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_UP, &ioctl_value);
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
 	if (err < 0) {
 		WL_ERR("BRCMF_C_UP error (%d)\n", err);
 		goto exit;
@@ -4274,14 +3625,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
 	/* join parameters starts with ssid */
 	memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le));
 	/* create softap */
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, &join_params,
-			      sizeof(join_params));
+	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
+				     &join_params, sizeof(join_params));
 	if (err < 0) {
 		WL_ERR("SET SSID error (%d)\n", err);
 		goto exit;
 	}
-	clear_bit(WL_STATUS_AP_CREATING, &cfg->status);
-	set_bit(WL_STATUS_AP_CREATED, &cfg->status);
+	clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
+	set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
 
 exit:
 	if (err)
@@ -4291,8 +3642,8 @@ exit:
 
 static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
 {
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-	s32 ioctl_value;
 	s32 err = -EPERM;
 
 	WL_TRACE("Enter\n");
@@ -4301,21 +3652,20 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
 		/* Due to most likely deauths outstanding we sleep */
 		/* first to make sure they get processed by fw. */
 		msleep(400);
-		ioctl_value = 0;
-		err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AP, &ioctl_value);
+		err = brcmf_fil_cmd_int_set(netdev_priv(ndev),
+					    BRCMF_C_SET_AP, 0);
 		if (err < 0) {
 			WL_ERR("setting AP mode failed %d\n", err);
 			goto exit;
 		}
-		ioctl_value = 0;
-		err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_UP, &ioctl_value);
+		err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_UP, 0);
 		if (err < 0) {
 			WL_ERR("BRCMF_C_UP error %d\n", err);
 			goto exit;
 		}
 		brcmf_set_mpc(ndev, 1);
-		clear_bit(WL_STATUS_AP_CREATING, &cfg->status);
-		clear_bit(WL_STATUS_AP_CREATED, &cfg->status);
+		clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
+		clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
 	}
 exit:
 	return err;
@@ -4326,6 +3676,7 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
 			   u8 *mac)
 {
 	struct brcmf_scb_val_le scbval;
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	s32 err;
 
 	if (!mac)
@@ -4333,13 +3684,13 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
 
 	WL_TRACE("Enter %pM\n", mac);
 
-	if (!check_sys_up(wiphy))
+	if (!check_vif_up(ifp->vif))
 		return -EIO;
 
 	memcpy(&scbval.ea, mac, ETH_ALEN);
 	scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING);
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON,
-			      &scbval, sizeof(scbval));
+	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON,
+				     &scbval, sizeof(scbval));
 	if (err)
 		WL_ERR("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err);
 
@@ -4373,11 +3724,8 @@ static struct cfg80211_ops wl_cfg80211_ops = {
 	.start_ap = brcmf_cfg80211_start_ap,
 	.stop_ap = brcmf_cfg80211_stop_ap,
 	.del_station = brcmf_cfg80211_del_station,
-#ifndef CONFIG_BRCMISCAN
-	/* scheduled scan need e-scan, which is mutual exclusive with i-scan */
 	.sched_scan_start = brcmf_cfg80211_sched_scan_start,
 	.sched_scan_stop = brcmf_cfg80211_sched_scan_stop,
-#endif
 #ifdef CONFIG_NL80211_TESTMODE
 	.testmode_cmd = brcmf_cfg80211_testmode
 #endif
@@ -4401,88 +3749,111 @@ static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
 
 static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
 {
-#ifndef CONFIG_BRCMISCAN
 	/* scheduled scan settings */
 	wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
 	wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
 	wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
 	wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
-#endif
 }
 
-static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev)
+static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
 {
-	struct wireless_dev *wdev;
+	struct wiphy *wiphy;
 	s32 err = 0;
 
-	wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
-	if (!wdev)
-		return ERR_PTR(-ENOMEM);
-
-	wdev->wiphy = wiphy_new(&wl_cfg80211_ops,
-				sizeof(struct brcmf_cfg80211_info));
-	if (!wdev->wiphy) {
+	wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
+	if (!wiphy) {
 		WL_ERR("Could not allocate wiphy device\n");
-		err = -ENOMEM;
-		goto wiphy_new_out;
-	}
-	set_wiphy_dev(wdev->wiphy, ndev);
-	wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
-	wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
-	wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
-				       BIT(NL80211_IFTYPE_ADHOC) |
-				       BIT(NL80211_IFTYPE_AP);
-	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
-	wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a;	/* Set
+		return ERR_PTR(-ENOMEM);
+	}
+	set_wiphy_dev(wiphy, phydev);
+	wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
+	wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
+	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+				 BIT(NL80211_IFTYPE_ADHOC) |
+				 BIT(NL80211_IFTYPE_AP);
+	wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
+	wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a;	/* Set
 						* it as 11a by default.
 						* This will be updated with
 						* 11n phy tables in
 						* "ifconfig up"
 						* if phy has 11n capability
 						*/
-	wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
-	wdev->wiphy->cipher_suites = __wl_cipher_suites;
-	wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
-	wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;	/* enable power
+	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+	wiphy->cipher_suites = __wl_cipher_suites;
+	wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
+	wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;	/* enable power
 								 * save mode
 								 * by default
 								 */
-	brcmf_wiphy_pno_params(wdev->wiphy);
-	err = wiphy_register(wdev->wiphy);
+	brcmf_wiphy_pno_params(wiphy);
+	err = wiphy_register(wiphy);
 	if (err < 0) {
 		WL_ERR("Could not register wiphy device (%d)\n", err);
-		goto wiphy_register_out;
+		wiphy_free(wiphy);
+		return ERR_PTR(err);
 	}
-	return wdev;
+	return wiphy;
+}
 
-wiphy_register_out:
-	wiphy_free(wdev->wiphy);
+static
+struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
+					   struct net_device *netdev,
+					   s32 mode, bool pm_block)
+{
+	struct brcmf_cfg80211_vif *vif;
 
-wiphy_new_out:
-	kfree(wdev);
+	if (cfg->vif_cnt == BRCMF_IFACE_MAX_CNT)
+		return ERR_PTR(-ENOSPC);
 
-	return ERR_PTR(err);
+	vif = kzalloc(sizeof(*vif), GFP_KERNEL);
+	if (!vif)
+		return ERR_PTR(-ENOMEM);
+
+	vif->wdev.wiphy = cfg->wiphy;
+	vif->wdev.netdev = netdev;
+	vif->wdev.iftype = brcmf_mode_to_nl80211_iftype(mode);
+
+	if (netdev) {
+		vif->ifp = netdev_priv(netdev);
+		netdev->ieee80211_ptr = &vif->wdev;
+		SET_NETDEV_DEV(netdev, wiphy_dev(cfg->wiphy));
+	}
+
+	vif->mode = mode;
+	vif->pm_block = pm_block;
+	vif->roam_off = -1;
+
+	brcmf_init_prof(&vif->profile);
+
+	list_add_tail(&vif->list, &cfg->vif_list);
+	cfg->vif_cnt++;
+	return vif;
 }
 
-static void brcmf_free_wdev(struct brcmf_cfg80211_info *cfg)
+static void brcmf_free_vif(struct brcmf_cfg80211_vif *vif)
 {
-	struct wireless_dev *wdev = cfg->wdev;
+	struct brcmf_cfg80211_info *cfg;
+	struct wiphy *wiphy;
 
-	if (!wdev) {
-		WL_ERR("wdev is invalid\n");
-		return;
+	wiphy = vif->wdev.wiphy;
+	cfg = wiphy_priv(wiphy);
+	list_del(&vif->list);
+	cfg->vif_cnt--;
+
+	kfree(vif);
+	if (!cfg->vif_cnt) {
+		wiphy_unregister(wiphy);
+		wiphy_free(wiphy);
 	}
-	wiphy_unregister(wdev->wiphy);
-	wiphy_free(wdev->wiphy);
-	kfree(wdev);
-	cfg->wdev = NULL;
 }
 
 static bool brcmf_is_linkup(struct brcmf_cfg80211_info *cfg,
 			    const struct brcmf_event_msg *e)
 {
-	u32 event = be32_to_cpu(e->event_type);
-	u32 status = be32_to_cpu(e->status);
+	u32 event = e->event_code;
+	u32 status = e->status;
 
 	if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
 		WL_CONN("Processing set ssid\n");
@@ -4496,8 +3867,8 @@ static bool brcmf_is_linkup(struct brcmf_cfg80211_info *cfg,
 static bool brcmf_is_linkdown(struct brcmf_cfg80211_info *cfg,
 			      const struct brcmf_event_msg *e)
 {
-	u32 event = be32_to_cpu(e->event_type);
-	u16 flags = be16_to_cpu(e->flags);
+	u32 event = e->event_code;
+	u16 flags = e->flags;
 
 	if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) {
 		WL_CONN("Processing link down\n");
@@ -4509,13 +3880,12 @@ static bool brcmf_is_linkdown(struct brcmf_cfg80211_info *cfg,
 static bool brcmf_is_nonetwork(struct brcmf_cfg80211_info *cfg,
 			       const struct brcmf_event_msg *e)
 {
-	u32 event = be32_to_cpu(e->event_type);
-	u32 status = be32_to_cpu(e->status);
+	u32 event = e->event_code;
+	u32 status = e->status;
 
 	if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {
 		WL_CONN("Processing Link %s & no network found\n",
-				be16_to_cpu(e->flags) & BRCMF_EVENT_MSG_LINK ?
-				"up" : "down");
+			e->flags & BRCMF_EVENT_MSG_LINK ? "up" : "down");
 		return true;
 	}
 
@@ -4541,7 +3911,7 @@ static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg)
 
 static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg)
 {
-	struct net_device *ndev = cfg_to_ndev(cfg);
+	struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
 	struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
 	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
 	u32 req_len;
@@ -4550,8 +3920,8 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg)
 
 	brcmf_clear_assoc_ies(cfg);
 
-	err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg->extra_buf,
-				WL_ASSOC_INFO_MAX);
+	err = brcmf_fil_iovar_data_get(ifp, "assoc_info",
+				       cfg->extra_buf, WL_ASSOC_INFO_MAX);
 	if (err) {
 		WL_ERR("could not get assoc info (%d)\n", err);
 		return err;
@@ -4561,9 +3931,9 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg)
 	req_len = le32_to_cpu(assoc_info->req_len);
 	resp_len = le32_to_cpu(assoc_info->resp_len);
 	if (req_len) {
-		err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies",
-					   cfg->extra_buf,
-					   WL_ASSOC_INFO_MAX);
+		err = brcmf_fil_iovar_data_get(ifp, "assoc_req_ies",
+					       cfg->extra_buf,
+					       WL_ASSOC_INFO_MAX);
 		if (err) {
 			WL_ERR("could not get assoc req (%d)\n", err);
 			return err;
@@ -4577,9 +3947,9 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg)
 		conn_info->req_ie = NULL;
 	}
 	if (resp_len) {
-		err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies",
-					   cfg->extra_buf,
-					   WL_ASSOC_INFO_MAX);
+		err = brcmf_fil_iovar_data_get(ifp, "assoc_resp_ies",
+					       cfg->extra_buf,
+					       WL_ASSOC_INFO_MAX);
 		if (err) {
 			WL_ERR("could not get assoc resp (%d)\n", err);
 			return err;
@@ -4603,7 +3973,8 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
 		       struct net_device *ndev,
 		       const struct brcmf_event_msg *e)
 {
-	struct brcmf_cfg80211_profile *profile = cfg->profile;
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
 	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
 	struct wiphy *wiphy = cfg_to_wiphy(cfg);
 	struct ieee80211_channel *notify_channel = NULL;
@@ -4628,7 +3999,8 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
 
 	/* data sent to dongle has to be little endian */
 	*(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
+	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
+				     buf, WL_BSS_INFO_MAX);
 
 	if (err)
 		goto done;
@@ -4652,7 +4024,7 @@ done:
 			conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
 	WL_CONN("Report roaming result\n");
 
-	set_bit(WL_STATUS_CONNECTED, &cfg->status);
+	set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
 	WL_TRACE("Exit\n");
 	return err;
 }
@@ -4662,13 +4034,15 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg,
 		       struct net_device *ndev, const struct brcmf_event_msg *e,
 		       bool completed)
 {
-	struct brcmf_cfg80211_profile *profile = cfg->profile;
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
 	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
 	s32 err = 0;
 
 	WL_TRACE("Enter\n");
 
-	if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg->status)) {
+	if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTING,
+			       &ifp->vif->sme_state)) {
 		if (completed) {
 			brcmf_get_assoc_ies(cfg);
 			memcpy(profile->bssid, e->addr, ETH_ALEN);
@@ -4684,7 +4058,8 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg,
 						    WLAN_STATUS_AUTH_TIMEOUT,
 					GFP_KERNEL);
 		if (completed)
-			set_bit(WL_STATUS_CONNECTED, &cfg->status);
+			set_bit(BRCMF_VIF_STATUS_CONNECTED,
+				&ifp->vif->sme_state);
 		WL_CONN("Report connect result - connection %s\n",
 				completed ? "succeeded" : "failed");
 	}
@@ -4698,9 +4073,9 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
 			       const struct brcmf_event_msg *e, void *data)
 {
 	s32 err = 0;
-	u32 event = be32_to_cpu(e->event_type);
-	u32 reason = be32_to_cpu(e->reason);
-	u32 len = be32_to_cpu(e->datalen);
+	u32 event = e->event_code;
+	u32 reason = e->reason;
+	u32 len = e->datalen;
 	static int generation;
 
 	struct station_info sinfo;
@@ -4732,11 +4107,12 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
 }
 
 static s32
-brcmf_notify_connect_status(struct brcmf_cfg80211_info *cfg,
-			    struct net_device *ndev,
+brcmf_notify_connect_status(struct brcmf_if *ifp,
 			    const struct brcmf_event_msg *e, void *data)
 {
-	struct brcmf_cfg80211_profile *profile = cfg->profile;
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	struct net_device *ndev = ifp->ndev;
+	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
 	s32 err = 0;
 
 	if (cfg->conf->mode == WL_MODE_AP) {
@@ -4747,30 +4123,34 @@ brcmf_notify_connect_status(struct brcmf_cfg80211_info *cfg,
 			memcpy(profile->bssid, e->addr, ETH_ALEN);
 			wl_inform_ibss(cfg, ndev, e->addr);
 			cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
-			clear_bit(WL_STATUS_CONNECTING, &cfg->status);
-			set_bit(WL_STATUS_CONNECTED, &cfg->status);
+			clear_bit(BRCMF_VIF_STATUS_CONNECTING,
+				  &ifp->vif->sme_state);
+			set_bit(BRCMF_VIF_STATUS_CONNECTED,
+				&ifp->vif->sme_state);
 		} else
 			brcmf_bss_connect_done(cfg, ndev, e, true);
 	} else if (brcmf_is_linkdown(cfg, e)) {
 		WL_CONN("Linkdown\n");
 		if (brcmf_is_ibssmode(cfg)) {
-			clear_bit(WL_STATUS_CONNECTING, &cfg->status);
-			if (test_and_clear_bit(WL_STATUS_CONNECTED,
-				&cfg->status))
+			clear_bit(BRCMF_VIF_STATUS_CONNECTING,
+				  &ifp->vif->sme_state);
+			if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED,
+					       &ifp->vif->sme_state))
 				brcmf_link_down(cfg);
 		} else {
 			brcmf_bss_connect_done(cfg, ndev, e, false);
-			if (test_and_clear_bit(WL_STATUS_CONNECTED,
-				&cfg->status)) {
+			if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED,
+					       &ifp->vif->sme_state)) {
 				cfg80211_disconnected(ndev, 0, NULL, 0,
-					GFP_KERNEL);
+						      GFP_KERNEL);
 				brcmf_link_down(cfg);
 			}
 		}
-		brcmf_init_prof(cfg->profile);
+		brcmf_init_prof(ndev_to_prof(ndev));
 	} else if (brcmf_is_nonetwork(cfg, e)) {
 		if (brcmf_is_ibssmode(cfg))
-			clear_bit(WL_STATUS_CONNECTING, &cfg->status);
+			clear_bit(BRCMF_VIF_STATUS_CONNECTING,
+				  &ifp->vif->sme_state);
 		else
 			brcmf_bss_connect_done(cfg, ndev, e, false);
 	}
@@ -4779,30 +4159,29 @@ brcmf_notify_connect_status(struct brcmf_cfg80211_info *cfg,
 }
 
 static s32
-brcmf_notify_roaming_status(struct brcmf_cfg80211_info *cfg,
-			    struct net_device *ndev,
+brcmf_notify_roaming_status(struct brcmf_if *ifp,
 			    const struct brcmf_event_msg *e, void *data)
 {
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
 	s32 err = 0;
-	u32 event = be32_to_cpu(e->event_type);
-	u32 status = be32_to_cpu(e->status);
+	u32 event = e->event_code;
+	u32 status = e->status;
 
 	if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
-		if (test_bit(WL_STATUS_CONNECTED, &cfg->status))
-			brcmf_bss_roaming_done(cfg, ndev, e);
+		if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))
+			brcmf_bss_roaming_done(cfg, ifp->ndev, e);
 		else
-			brcmf_bss_connect_done(cfg, ndev, e, true);
+			brcmf_bss_connect_done(cfg, ifp->ndev, e, true);
 	}
 
 	return err;
 }
 
 static s32
-brcmf_notify_mic_status(struct brcmf_cfg80211_info *cfg,
-			struct net_device *ndev,
+brcmf_notify_mic_status(struct brcmf_if *ifp,
 			const struct brcmf_event_msg *e, void *data)
 {
-	u16 flags = be16_to_cpu(e->flags);
+	u16 flags = e->flags;
 	enum nl80211_key_type key_type;
 
 	if (flags & BRCMF_EVENT_MSG_GROUP)
@@ -4810,82 +4189,12 @@ brcmf_notify_mic_status(struct brcmf_cfg80211_info *cfg,
 	else
 		key_type = NL80211_KEYTYPE_PAIRWISE;
 
-	cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
+	cfg80211_michael_mic_failure(ifp->ndev, (u8 *)&e->addr, key_type, -1,
 				     NULL, GFP_KERNEL);
 
 	return 0;
 }
 
-static s32
-brcmf_notify_scan_status(struct brcmf_cfg80211_info *cfg,
-			 struct net_device *ndev,
-			 const struct brcmf_event_msg *e, void *data)
-{
-	struct brcmf_channel_info_le channel_inform_le;
-	struct brcmf_scan_results_le *bss_list_le;
-	u32 len = WL_SCAN_BUF_MAX;
-	s32 err = 0;
-	bool scan_abort = false;
-	u32 scan_channel;
-
-	WL_TRACE("Enter\n");
-
-	if (cfg->iscan_on && cfg->iscan_kickstart) {
-		WL_TRACE("Exit\n");
-		return brcmf_wakeup_iscan(cfg_to_iscan(cfg));
-	}
-
-	if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) {
-		WL_ERR("Scan complete while device not scanning\n");
-		scan_abort = true;
-		err = -EINVAL;
-		goto scan_done_out;
-	}
-
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_inform_le,
-			      sizeof(channel_inform_le));
-	if (err) {
-		WL_ERR("scan busy (%d)\n", err);
-		scan_abort = true;
-		goto scan_done_out;
-	}
-	scan_channel = le32_to_cpu(channel_inform_le.scan_channel);
-	if (scan_channel)
-		WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel);
-	cfg->bss_list = cfg->scan_results;
-	bss_list_le = (struct brcmf_scan_results_le *) cfg->bss_list;
-
-	memset(cfg->scan_results, 0, len);
-	bss_list_le->buflen = cpu_to_le32(len);
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS,
-			      cfg->scan_results, len);
-	if (err) {
-		WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
-		err = -EINVAL;
-		scan_abort = true;
-		goto scan_done_out;
-	}
-	cfg->scan_results->buflen = le32_to_cpu(bss_list_le->buflen);
-	cfg->scan_results->version = le32_to_cpu(bss_list_le->version);
-	cfg->scan_results->count = le32_to_cpu(bss_list_le->count);
-
-	err = brcmf_inform_bss(cfg);
-	if (err)
-		scan_abort = true;
-
-scan_done_out:
-	if (cfg->scan_request) {
-		WL_SCAN("calling cfg80211_scan_done\n");
-		cfg80211_scan_done(cfg->scan_request, scan_abort);
-		brcmf_set_mpc(ndev, 1);
-		cfg->scan_request = NULL;
-	}
-
-	WL_TRACE("Exit\n");
-
-	return err;
-}
-
 static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
 {
 	conf->mode = (u32)-1;
@@ -4896,82 +4205,53 @@ static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
 	conf->tx_power = -1;
 }
 
-static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
-{
-	memset(el, 0, sizeof(*el));
-	el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status;
-	el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status;
-	el->handler[BRCMF_E_DEAUTH_IND] = brcmf_notify_connect_status;
-	el->handler[BRCMF_E_DEAUTH] = brcmf_notify_connect_status;
-	el->handler[BRCMF_E_DISASSOC_IND] = brcmf_notify_connect_status;
-	el->handler[BRCMF_E_ASSOC_IND] = brcmf_notify_connect_status;
-	el->handler[BRCMF_E_REASSOC_IND] = brcmf_notify_connect_status;
-	el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status;
-	el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status;
-	el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status;
-	el->handler[BRCMF_E_PFN_NET_FOUND] = brcmf_notify_sched_scan_results;
+static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
+{
+	brcmf_fweh_register(cfg->pub, BRCMF_E_LINK,
+			    brcmf_notify_connect_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_DEAUTH_IND,
+			    brcmf_notify_connect_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_DEAUTH,
+			    brcmf_notify_connect_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_DISASSOC_IND,
+			    brcmf_notify_connect_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_ASSOC_IND,
+			    brcmf_notify_connect_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_REASSOC_IND,
+			    brcmf_notify_connect_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_ROAM,
+			    brcmf_notify_roaming_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_MIC_ERROR,
+			    brcmf_notify_mic_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_SET_SSID,
+			    brcmf_notify_connect_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND,
+			    brcmf_notify_sched_scan_results);
 }
 
 static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)
 {
-	kfree(cfg->scan_results);
-	cfg->scan_results = NULL;
-	kfree(cfg->bss_info);
-	cfg->bss_info = NULL;
 	kfree(cfg->conf);
 	cfg->conf = NULL;
-	kfree(cfg->profile);
-	cfg->profile = NULL;
-	kfree(cfg->scan_req_int);
-	cfg->scan_req_int = NULL;
 	kfree(cfg->escan_ioctl_buf);
 	cfg->escan_ioctl_buf = NULL;
-	kfree(cfg->dcmd_buf);
-	cfg->dcmd_buf = NULL;
 	kfree(cfg->extra_buf);
 	cfg->extra_buf = NULL;
-	kfree(cfg->iscan);
-	cfg->iscan = NULL;
 	kfree(cfg->pmk_list);
 	cfg->pmk_list = NULL;
-	if (cfg->ap_info) {
-		kfree(cfg->ap_info->wpa_ie);
-		kfree(cfg->ap_info->rsn_ie);
-		kfree(cfg->ap_info);
-		cfg->ap_info = NULL;
-	}
 }
 
 static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg)
 {
-	cfg->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
-	if (!cfg->scan_results)
-		goto init_priv_mem_out;
 	cfg->conf = kzalloc(sizeof(*cfg->conf), GFP_KERNEL);
 	if (!cfg->conf)
 		goto init_priv_mem_out;
-	cfg->profile = kzalloc(sizeof(*cfg->profile), GFP_KERNEL);
-	if (!cfg->profile)
-		goto init_priv_mem_out;
-	cfg->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
-	if (!cfg->bss_info)
-		goto init_priv_mem_out;
-	cfg->scan_req_int = kzalloc(sizeof(*cfg->scan_req_int),
-					 GFP_KERNEL);
-	if (!cfg->scan_req_int)
-		goto init_priv_mem_out;
 	cfg->escan_ioctl_buf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
 	if (!cfg->escan_ioctl_buf)
 		goto init_priv_mem_out;
-	cfg->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL);
-	if (!cfg->dcmd_buf)
-		goto init_priv_mem_out;
 	cfg->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
 	if (!cfg->extra_buf)
 		goto init_priv_mem_out;
-	cfg->iscan = kzalloc(sizeof(*cfg->iscan), GFP_KERNEL);
-	if (!cfg->iscan)
-		goto init_priv_mem_out;
 	cfg->pmk_list = kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL);
 	if (!cfg->pmk_list)
 		goto init_priv_mem_out;
@@ -4984,152 +4264,24 @@ init_priv_mem_out:
 	return -ENOMEM;
 }
 
-/*
-* retrieve first queued event from head
-*/
-
-static struct brcmf_cfg80211_event_q *brcmf_deq_event(
-	struct brcmf_cfg80211_info *cfg)
-{
-	struct brcmf_cfg80211_event_q *e = NULL;
-
-	spin_lock_irq(&cfg->evt_q_lock);
-	if (!list_empty(&cfg->evt_q_list)) {
-		e = list_first_entry(&cfg->evt_q_list,
-				     struct brcmf_cfg80211_event_q, evt_q_list);
-		list_del(&e->evt_q_list);
-	}
-	spin_unlock_irq(&cfg->evt_q_lock);
-
-	return e;
-}
-
-/*
-*	push event to tail of the queue
-*
-*	remark: this function may not sleep as it is called in atomic context.
-*/
-
-static s32
-brcmf_enq_event(struct brcmf_cfg80211_info *cfg, u32 event,
-		const struct brcmf_event_msg *msg, void *data)
-{
-	struct brcmf_cfg80211_event_q *e;
-	s32 err = 0;
-	ulong flags;
-	u32 data_len;
-	u32 total_len;
-
-	total_len = sizeof(struct brcmf_cfg80211_event_q);
-	if (data)
-		data_len = be32_to_cpu(msg->datalen);
-	else
-		data_len = 0;
-	total_len += data_len;
-	e = kzalloc(total_len, GFP_ATOMIC);
-	if (!e)
-		return -ENOMEM;
-
-	e->etype = event;
-	memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
-	if (data)
-		memcpy(&e->edata, data, data_len);
-
-	spin_lock_irqsave(&cfg->evt_q_lock, flags);
-	list_add_tail(&e->evt_q_list, &cfg->evt_q_list);
-	spin_unlock_irqrestore(&cfg->evt_q_lock, flags);
-
-	return err;
-}
-
-static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
-{
-	kfree(e);
-}
-
-static void brcmf_cfg80211_event_handler(struct work_struct *work)
-{
-	struct brcmf_cfg80211_info *cfg =
-			container_of(work, struct brcmf_cfg80211_info,
-				     event_work);
-	struct brcmf_cfg80211_event_q *e;
-
-	e = brcmf_deq_event(cfg);
-	if (unlikely(!e)) {
-		WL_ERR("event queue empty...\n");
-		return;
-	}
-
-	do {
-		WL_INFO("event type (%d)\n", e->etype);
-		if (cfg->el.handler[e->etype])
-			cfg->el.handler[e->etype](cfg,
-						       cfg_to_ndev(cfg),
-						       &e->emsg, e->edata);
-		else
-			WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
-		brcmf_put_event(e);
-	} while ((e = brcmf_deq_event(cfg)));
-
-}
-
-static void brcmf_init_eq(struct brcmf_cfg80211_info *cfg)
-{
-	spin_lock_init(&cfg->evt_q_lock);
-	INIT_LIST_HEAD(&cfg->evt_q_list);
-}
-
-static void brcmf_flush_eq(struct brcmf_cfg80211_info *cfg)
-{
-	struct brcmf_cfg80211_event_q *e;
-
-	spin_lock_irq(&cfg->evt_q_lock);
-	while (!list_empty(&cfg->evt_q_list)) {
-		e = list_first_entry(&cfg->evt_q_list,
-				     struct brcmf_cfg80211_event_q, evt_q_list);
-		list_del(&e->evt_q_list);
-		kfree(e);
-	}
-	spin_unlock_irq(&cfg->evt_q_lock);
-}
-
 static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg)
 {
 	s32 err = 0;
 
 	cfg->scan_request = NULL;
 	cfg->pwr_save = true;
-#ifdef CONFIG_BRCMISCAN
-	cfg->iscan_on = true;	/* iscan on & off switch.
-				 we enable iscan per default */
-	cfg->escan_on = false;	/* escan on & off switch.
-				 we disable escan per default */
-#else
-	cfg->iscan_on = false;	/* iscan on & off switch.
-				 we disable iscan per default */
-	cfg->escan_on = true;	/* escan on & off switch.
-				 we enable escan per default */
-#endif
 	cfg->roam_on = true;	/* roam on & off switch.
 				 we enable roam per default */
-
-	cfg->iscan_kickstart = false;
 	cfg->active_scan = true;	/* we do active scan for
 				 specific scan per default */
 	cfg->dongle_up = false;	/* dongle is not up yet */
-	brcmf_init_eq(cfg);
 	err = brcmf_init_priv_mem(cfg);
 	if (err)
 		return err;
-	INIT_WORK(&cfg->event_work, brcmf_cfg80211_event_handler);
-	brcmf_init_eloop_handler(&cfg->el);
+	brcmf_register_event_handlers(cfg);
 	mutex_init(&cfg->usr_sync);
-	err = brcmf_init_iscan(cfg);
-	if (err)
-		return err;
 	brcmf_init_escan(cfg);
 	brcmf_init_conf(cfg->conf);
-	brcmf_init_prof(cfg->profile);
 	brcmf_link_down(cfg);
 
 	return err;
@@ -5137,20 +4289,20 @@ static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg)
 
 static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg)
 {
-	cancel_work_sync(&cfg->event_work);
 	cfg->dongle_up = false;	/* dongle down */
-	brcmf_flush_eq(cfg);
 	brcmf_link_down(cfg);
 	brcmf_abort_scanning(cfg);
 	brcmf_deinit_priv_mem(cfg);
 }
 
-struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev,
-						  struct device *busdev,
-						  struct brcmf_pub *drvr)
+struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr)
 {
-	struct wireless_dev *wdev;
+	struct net_device *ndev = drvr->iflist[0]->ndev;
+	struct device *busdev = drvr->dev;
 	struct brcmf_cfg80211_info *cfg;
+	struct wiphy *wiphy;
+	struct brcmf_cfg80211_vif *vif;
+	struct brcmf_if *ifp;
 	s32 err = 0;
 
 	if (!ndev) {
@@ -5158,122 +4310,61 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev,
 		return NULL;
 	}
 
-	wdev = brcmf_alloc_wdev(busdev);
-	if (IS_ERR(wdev)) {
+	ifp = netdev_priv(ndev);
+	wiphy = brcmf_setup_wiphy(busdev);
+	if (IS_ERR(wiphy))
 		return NULL;
-	}
 
-	wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS);
-	cfg = wdev_to_cfg(wdev);
-	cfg->wdev = wdev;
+	cfg = wiphy_priv(wiphy);
+	cfg->wiphy = wiphy;
 	cfg->pub = drvr;
-	ndev->ieee80211_ptr = wdev;
-	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
-	wdev->netdev = ndev;
+	INIT_LIST_HEAD(&cfg->vif_list);
+
+	vif = brcmf_alloc_vif(cfg, ndev, WL_MODE_BSS, false);
+	if (IS_ERR(vif)) {
+		wiphy_free(wiphy);
+		return NULL;
+	}
+
 	err = wl_init_priv(cfg);
 	if (err) {
 		WL_ERR("Failed to init iwm_priv (%d)\n", err);
 		goto cfg80211_attach_out;
 	}
 
+	ifp->vif = vif;
 	return cfg;
 
 cfg80211_attach_out:
-	brcmf_free_wdev(cfg);
+	brcmf_free_vif(vif);
 	return NULL;
 }
 
 void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
 {
-	wl_deinit_priv(cfg);
-	brcmf_free_wdev(cfg);
-}
-
-void
-brcmf_cfg80211_event(struct net_device *ndev,
-		  const struct brcmf_event_msg *e, void *data)
-{
-	u32 event_type = be32_to_cpu(e->event_type);
-	struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
-
-	if (!brcmf_enq_event(cfg, event_type, e, data))
-		schedule_work(&cfg->event_work);
-}
-
-static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
-{
-	/* Room for "event_msgs" + '\0' + bitvec */
-	s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
-	s8 eventmask[BRCMF_EVENTING_MASK_LEN];
-	s32 err = 0;
+	struct brcmf_cfg80211_vif *vif;
+	struct brcmf_cfg80211_vif *tmp;
 
-	WL_TRACE("Enter\n");
-
-	/* Setup event_msgs */
-	brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
-			iovbuf, sizeof(iovbuf));
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf));
-	if (err) {
-		WL_ERR("Get event_msgs error (%d)\n", err);
-		goto dongle_eventmsg_out;
-	}
-	memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
-
-	setbit(eventmask, BRCMF_E_SET_SSID);
-	setbit(eventmask, BRCMF_E_ROAM);
-	setbit(eventmask, BRCMF_E_PRUNE);
-	setbit(eventmask, BRCMF_E_AUTH);
-	setbit(eventmask, BRCMF_E_REASSOC);
-	setbit(eventmask, BRCMF_E_REASSOC_IND);
-	setbit(eventmask, BRCMF_E_DEAUTH_IND);
-	setbit(eventmask, BRCMF_E_DISASSOC_IND);
-	setbit(eventmask, BRCMF_E_DISASSOC);
-	setbit(eventmask, BRCMF_E_JOIN);
-	setbit(eventmask, BRCMF_E_ASSOC_IND);
-	setbit(eventmask, BRCMF_E_PSK_SUP);
-	setbit(eventmask, BRCMF_E_LINK);
-	setbit(eventmask, BRCMF_E_NDIS_LINK);
-	setbit(eventmask, BRCMF_E_MIC_ERROR);
-	setbit(eventmask, BRCMF_E_PMKID_CACHE);
-	setbit(eventmask, BRCMF_E_TXFAIL);
-	setbit(eventmask, BRCMF_E_JOIN_START);
-	setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
-	setbit(eventmask, BRCMF_E_ESCAN_RESULT);
-	setbit(eventmask, BRCMF_E_PFN_NET_FOUND);
-
-	brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
-			iovbuf, sizeof(iovbuf));
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
-	if (err) {
-		WL_ERR("Set event_msgs error (%d)\n", err);
-		goto dongle_eventmsg_out;
+	wl_deinit_priv(cfg);
+	list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) {
+		brcmf_free_vif(vif);
 	}
-
-dongle_eventmsg_out:
-	WL_TRACE("Exit\n");
-	return err;
 }
 
 static s32
 brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
 {
-	s8 iovbuf[32];
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	s32 err = 0;
 	__le32 roamtrigger[2];
 	__le32 roam_delta[2];
-	__le32 bcn_to_le;
-	__le32 roamvar_le;
 
 	/*
 	 * Setup timeout if Beacons are lost and roam is
 	 * off to report link down
 	 */
 	if (roamvar) {
-		bcn_to_le = cpu_to_le32(bcn_timeout);
-		brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_to_le,
-			sizeof(bcn_to_le), iovbuf, sizeof(iovbuf));
-		err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR,
-				   iovbuf, sizeof(iovbuf));
+		err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout);
 		if (err) {
 			WL_ERR("bcn_timeout error (%d)\n", err);
 			goto dongle_rom_out;
@@ -5285,10 +4376,7 @@ brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
 	 * to take care of roaming
 	 */
 	WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
-	roamvar_le = cpu_to_le32(roamvar);
-	brcmf_c_mkiovar("roam_off", (char *)&roamvar_le,
-				sizeof(roamvar_le), iovbuf, sizeof(iovbuf));
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
+	err = brcmf_fil_iovar_int_set(ifp, "roam_off", roamvar);
 	if (err) {
 		WL_ERR("roam_off error (%d)\n", err);
 		goto dongle_rom_out;
@@ -5296,8 +4384,8 @@ brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
 
 	roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
 	roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_TRIGGER,
-			(void *)roamtrigger, sizeof(roamtrigger));
+	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_TRIGGER,
+				     (void *)roamtrigger, sizeof(roamtrigger));
 	if (err) {
 		WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
 		goto dongle_rom_out;
@@ -5305,8 +4393,8 @@ brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
 
 	roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
 	roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL);
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_DELTA,
-				(void *)roam_delta, sizeof(roam_delta));
+	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_DELTA,
+				     (void *)roam_delta, sizeof(roam_delta));
 	if (err) {
 		WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err);
 		goto dongle_rom_out;
@@ -5320,13 +4408,11 @@ static s32
 brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
 		      s32 scan_unassoc_time, s32 scan_passive_time)
 {
+	struct brcmf_if *ifp = netdev_priv(ndev);
 	s32 err = 0;
-	__le32 scan_assoc_tm_le = cpu_to_le32(scan_assoc_time);
-	__le32 scan_unassoc_tm_le = cpu_to_le32(scan_unassoc_time);
-	__le32 scan_passive_tm_le = cpu_to_le32(scan_passive_time);
 
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
-			   &scan_assoc_tm_le, sizeof(scan_assoc_tm_le));
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
+				    scan_assoc_time);
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			WL_INFO("Scan assoc time is not supported\n");
@@ -5334,8 +4420,8 @@ brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
 			WL_ERR("Scan assoc time error (%d)\n", err);
 		goto dongle_scantime_out;
 	}
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
-			   &scan_unassoc_tm_le, sizeof(scan_unassoc_tm_le));
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
+				    scan_unassoc_time);
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			WL_INFO("Scan unassoc time is not supported\n");
@@ -5344,8 +4430,8 @@ brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
 		goto dongle_scantime_out;
 	}
 
-	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
-			   &scan_passive_tm_le, sizeof(scan_passive_tm_le));
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_PASSIVE_TIME,
+				    scan_passive_time);
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			WL_INFO("Scan passive time is not supported\n");
@@ -5360,13 +4446,14 @@ dongle_scantime_out:
 
 static s32 wl_update_wiphybands(struct brcmf_cfg80211_info *cfg)
 {
+	struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
 	struct wiphy *wiphy;
 	s32 phy_list;
 	s8 phy;
 	s32 err = 0;
 
-	err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCM_GET_PHYLIST,
-			      &phy_list, sizeof(phy_list));
+	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST,
+				     &phy_list, sizeof(phy_list));
 	if (err) {
 		WL_ERR("error (%d)\n", err);
 		return err;
@@ -5403,12 +4490,9 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
 	brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
 			WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
 
-	err = brcmf_dongle_eventmsg(ndev);
-	if (err)
-		goto default_conf_out;
-
 	power_mode = cfg->pwr_save ? PM_FAST : PM_OFF;
-	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode);
+	err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PM,
+				    power_mode);
 	if (err)
 		goto default_conf_out;
 	WL_INFO("power save set to %s\n",
@@ -5436,66 +4520,26 @@ default_conf_out:
 
 }
 
-static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_info *cfg)
+static s32 __brcmf_cfg80211_up(struct brcmf_if *ifp)
 {
-	char buf[10+IFNAMSIZ];
-	struct dentry *fd;
-	s32 err = 0;
-
-	sprintf(buf, "netdev:%s", cfg_to_ndev(cfg)->name);
-	cfg->debugfsdir = debugfs_create_dir(buf,
-					cfg_to_wiphy(cfg)->debugfsdir);
-
-	fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg->debugfsdir,
-		(u16 *)&cfg->profile->beacon_interval);
-	if (!fd) {
-		err = -ENOMEM;
-		goto err_out;
-	}
-
-	fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg->debugfsdir,
-		(u8 *)&cfg->profile->dtim_period);
-	if (!fd) {
-		err = -ENOMEM;
-		goto err_out;
-	}
-
-err_out:
-	return err;
-}
+	set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
+	if (ifp->idx)
+		return 0;
 
-static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_info *cfg)
-{
-	debugfs_remove_recursive(cfg->debugfsdir);
-	cfg->debugfsdir = NULL;
+	return brcmf_config_dongle(ifp->drvr->config);
 }
 
-static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg)
+static s32 __brcmf_cfg80211_down(struct brcmf_if *ifp)
 {
-	s32 err = 0;
-
-	set_bit(WL_STATUS_READY, &cfg->status);
-
-	brcmf_debugfs_add_netdev_params(cfg);
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
 
-	err = brcmf_config_dongle(cfg);
-	if (err)
-		return err;
-
-	brcmf_invoke_iscan(cfg);
-
-	return err;
-}
-
-static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg)
-{
 	/*
 	 * While going down, if associated with AP disassociate
 	 * from AP to save power
 	 */
-	if ((test_bit(WL_STATUS_CONNECTED, &cfg->status) ||
-	     test_bit(WL_STATUS_CONNECTING, &cfg->status)) &&
-	     test_bit(WL_STATUS_READY, &cfg->status)) {
+	if ((test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state) ||
+	     test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) &&
+	     check_vif_up(ifp->vif)) {
 		WL_INFO("Disassociating from AP");
 		brcmf_link_down(cfg);
 
@@ -5507,30 +4551,32 @@ static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg)
 	}
 
 	brcmf_abort_scanning(cfg);
-	clear_bit(WL_STATUS_READY, &cfg->status);
-
-	brcmf_debugfs_remove_netdev(cfg);
+	clear_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
 
 	return 0;
 }
 
-s32 brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg)
+s32 brcmf_cfg80211_up(struct net_device *ndev)
 {
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
 	s32 err = 0;
 
 	mutex_lock(&cfg->usr_sync);
-	err = __brcmf_cfg80211_up(cfg);
+	err = __brcmf_cfg80211_up(ifp);
 	mutex_unlock(&cfg->usr_sync);
 
 	return err;
 }
 
-s32 brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg)
+s32 brcmf_cfg80211_down(struct net_device *ndev)
 {
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
 	s32 err = 0;
 
 	mutex_lock(&cfg->usr_sync);
-	err = __brcmf_cfg80211_down(cfg);
+	err = __brcmf_cfg80211_down(ifp);
 	mutex_unlock(&cfg->usr_sync);
 
 	return err;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
index 71ced17..e2ef851 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
@@ -84,31 +84,12 @@ do {								\
 #define	WL_CONN(fmt, args...)
 #endif /* (defined DEBUG) */
 
-#define WL_NUM_SCAN_MAX		1
-#define WL_NUM_PMKIDS_MAX	MAXPMKID	/* will be used
-						 * for 2.6.33 kernel
-						 * or later
-						 */
-#define WL_SCAN_BUF_MAX			(1024 * 8)
+#define WL_NUM_SCAN_MAX			10
+#define WL_NUM_PMKIDS_MAX		MAXPMKID
 #define WL_TLV_INFO_MAX			1024
 #define WL_BSS_INFO_MAX			2048
-#define WL_ASSOC_INFO_MAX	512	/*
-				 * needs to grab assoc info from dongle to
-				 * report it to cfg80211 through "connect"
-				 * event
-				 */
-#define WL_DCMD_LEN_MAX	1024
-#define WL_EXTRA_BUF_MAX	2048
-#define WL_ISCAN_BUF_MAX	2048	/*
-				 * the buf length can be BRCMF_DCMD_MAXLEN
-				 * to reduce iteration
-				 */
-#define WL_ISCAN_TIMER_INTERVAL_MS	3000
-#define WL_SCAN_ERSULTS_LAST	(BRCMF_SCAN_RESULTS_NO_MEM+1)
-#define WL_AP_MAX	256	/* virtually unlimitted as long
-				 * as kernel memory allows
-				 */
-
+#define WL_ASSOC_INFO_MAX		512	/* assoc related fil max buf */
+#define WL_EXTRA_BUF_MAX		2048
 #define WL_ROAM_TRIGGER_LEVEL		-75
 #define WL_ROAM_DELTA			20
 #define WL_BEACON_TIMEOUT		3
@@ -127,15 +108,15 @@ do {								\
 #define WL_AUTH_SHARED_KEY		1	/* d11 shared authentication */
 #define IE_MAX_LEN			512
 
-/* dongle status */
-enum wl_status {
-	WL_STATUS_READY,
-	WL_STATUS_SCANNING,
-	WL_STATUS_SCAN_ABORTING,
-	WL_STATUS_CONNECTING,
-	WL_STATUS_CONNECTED,
-	WL_STATUS_AP_CREATING,
-	WL_STATUS_AP_CREATED
+/**
+ * enum brcmf_scan_status - dongle scan status
+ *
+ * @BRCMF_SCAN_STATUS_BUSY: scanning in progress on dongle.
+ * @BRCMF_SCAN_STATUS_ABORT: scan being aborted on dongle.
+ */
+enum brcmf_scan_status {
+	BRCMF_SCAN_STATUS_BUSY,
+	BRCMF_SCAN_STATUS_ABORT,
 };
 
 /* wi-fi mode */
@@ -145,25 +126,6 @@ enum wl_mode {
 	WL_MODE_AP
 };
 
-/* dongle profile list */
-enum wl_prof_list {
-	WL_PROF_MODE,
-	WL_PROF_SSID,
-	WL_PROF_SEC,
-	WL_PROF_IBSS,
-	WL_PROF_BAND,
-	WL_PROF_BSSID,
-	WL_PROF_ACT,
-	WL_PROF_BEACONINT,
-	WL_PROF_DTIMPERIOD
-};
-
-/* dongle iscan state */
-enum wl_iscan_state {
-	WL_ISCAN_STATE_IDLE,
-	WL_ISCAN_STATE_SCANING
-};
-
 /* dongle configuration */
 struct brcmf_cfg80211_conf {
 	u32 mode;		/* adhoc , infrastructure or ap */
@@ -175,17 +137,6 @@ struct brcmf_cfg80211_conf {
 	struct ieee80211_channel channel;
 };
 
-/* forward declaration */
-struct brcmf_cfg80211_info;
-
-/* cfg80211 main event loop */
-struct brcmf_cfg80211_event_loop {
-	s32(*handler[BRCMF_E_LAST]) (struct brcmf_cfg80211_info *cfg,
-				     struct net_device *ndev,
-				     const struct brcmf_event_msg *e,
-				     void *data);
-};
-
 /* basic structure of scan request */
 struct brcmf_cfg80211_scan_req {
 	struct brcmf_ssid_le ssid_le;
@@ -197,14 +148,6 @@ struct brcmf_cfg80211_ie {
 	u8 buf[WL_TLV_INFO_MAX];
 };
 
-/* event queue for cfg80211 main event */
-struct brcmf_cfg80211_event_q {
-	struct list_head evt_q_list;
-	u32 etype;
-	struct brcmf_event_msg emsg;
-	s8 edata[1];
-};
-
 /* security information with currently associated ap */
 struct brcmf_cfg80211_security {
 	u32 wpa_versions;
@@ -214,45 +157,73 @@ struct brcmf_cfg80211_security {
 	u32 wpa_auth;
 };
 
-/* ibss information for currently joined ibss network */
-struct brcmf_cfg80211_ibss {
-	u8 beacon_interval;	/* in millisecond */
-	u8 atim;		/* in millisecond */
-	s8 join_only;
-	u8 band;
-	u8 channel;
-};
-
-/* dongle profile */
+/**
+ * struct brcmf_cfg80211_profile - profile information.
+ *
+ * @ssid: ssid of associated/associating ap.
+ * @bssid: bssid of joined/joining ibss.
+ * @sec: security information.
+ */
 struct brcmf_cfg80211_profile {
-	u32 mode;
 	struct brcmf_ssid ssid;
 	u8 bssid[ETH_ALEN];
-	u16 beacon_interval;
-	u8 dtim_period;
 	struct brcmf_cfg80211_security sec;
-	struct brcmf_cfg80211_ibss ibss;
-	s32 band;
 };
 
-/* dongle iscan event loop */
-struct brcmf_cfg80211_iscan_eloop {
-	s32 (*handler[WL_SCAN_ERSULTS_LAST])
-		(struct brcmf_cfg80211_info *cfg);
+/**
+ * enum brcmf_vif_status - bit indices for vif status.
+ *
+ * @BRCMF_VIF_STATUS_READY: ready for operation.
+ * @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress.
+ * @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully.
+ * @BRCMF_VIF_STATUS_AP_CREATING: interface configured for AP operation.
+ * @BRCMF_VIF_STATUS_AP_CREATED: AP operation started.
+ */
+enum brcmf_vif_status {
+	BRCMF_VIF_STATUS_READY,
+	BRCMF_VIF_STATUS_CONNECTING,
+	BRCMF_VIF_STATUS_CONNECTED,
+	BRCMF_VIF_STATUS_AP_CREATING,
+	BRCMF_VIF_STATUS_AP_CREATED
+};
+
+/**
+ * struct vif_saved_ie - holds saved IEs for a virtual interface.
+ *
+ * @probe_res_ie: IE info for probe response.
+ * @beacon_ie: IE info for beacon frame.
+ * @probe_res_ie_len: IE info length for probe response.
+ * @beacon_ie_len: IE info length for beacon frame.
+ */
+struct vif_saved_ie {
+	u8  probe_res_ie[IE_MAX_LEN];
+	u8  beacon_ie[IE_MAX_LEN];
+	u32 probe_res_ie_len;
+	u32 beacon_ie_len;
 };
 
-/* dongle iscan controller */
-struct brcmf_cfg80211_iscan_ctrl {
-	struct net_device *ndev;
-	struct timer_list timer;
-	u32 timer_ms;
-	u32 timer_on;
-	s32 state;
-	struct work_struct work;
-	struct brcmf_cfg80211_iscan_eloop el;
-	void *data;
-	s8 dcmd_buf[BRCMF_DCMD_SMLEN];
-	s8 scan_buf[WL_ISCAN_BUF_MAX];
+/**
+ * struct brcmf_cfg80211_vif - virtual interface specific information.
+ *
+ * @ifp: lower layer interface pointer
+ * @wdev: wireless device.
+ * @profile: profile information.
+ * @mode: operating mode.
+ * @roam_off: roaming state.
+ * @sme_state: SME state using enum brcmf_vif_status bits.
+ * @pm_block: power-management blocked.
+ * @list: linked list.
+ */
+struct brcmf_cfg80211_vif {
+	struct brcmf_if *ifp;
+	struct wireless_dev wdev;
+	struct brcmf_cfg80211_profile profile;
+	s32 mode;
+	s32 roam_off;
+	unsigned long sme_state;
+	bool pm_block;
+	struct vif_saved_ie saved_ie;
+	struct list_head list;
 };
 
 /* association inform */
@@ -288,17 +259,6 @@ struct escan_info {
 	struct net_device *ndev;
 };
 
-/* Structure to hold WPS, WPA IEs for a AP */
-struct ap_info {
-	u8 probe_res_ie[IE_MAX_LEN];
-	u8 beacon_ie[IE_MAX_LEN];
-	u32 probe_res_ie_len;
-	u32 beacon_ie_len;
-	u8 *wpa_ie;
-	u8 *rsn_ie;
-	bool security_mode;
-};
-
 /**
  * struct brcmf_pno_param_le - PNO scan configuration parameters
  *
@@ -383,28 +343,19 @@ struct brcmf_pno_scanresults_le {
 /**
  * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface
  *
- * @wdev: representing wl cfg80211 device.
+ * @wiphy: wiphy object for cfg80211 interface.
  * @conf: dongle configuration.
  * @scan_request: cfg80211 scan request object.
- * @el: main event loop.
- * @evt_q_list: used for event queue.
- * @evt_q_lock: for event queue synchronization.
  * @usr_sync: mainly for dongle up/down synchronization.
  * @bss_list: bss_list holding scanned ap information.
- * @scan_results: results of the last scan.
  * @scan_req_int: internal scan request object.
  * @bss_info: bss information for cfg80211 layer.
  * @ie: information element object for internal purpose.
- * @profile: holding dongle profile.
- * @iscan: iscan controller information.
  * @conn_info: association info.
  * @pmk_list: wpa2 pmk list.
- * @event_work: event handler work struct.
- * @status: current dongle status.
+ * @scan_status: scan activity on the dongle.
  * @pub: common driver information.
  * @channel: current channel.
- * @iscan_on: iscan on/off switch.
- * @iscan_kickstart: indicate iscan already started.
  * @active_scan: current scan mode.
  * @sched_escan: e-scan for scheduled scan support running.
  * @ibss_starter: indicates this sta is ibss starter.
@@ -416,37 +367,27 @@ struct brcmf_pno_scanresults_le {
  * @dcmd_buf: dcmd buffer.
  * @extra_buf: mainly to grab assoc information.
  * @debugfsdir: debugfs folder for this device.
- * @escan_on: escan on/off switch.
  * @escan_info: escan information.
  * @escan_timeout: Timer for catch scan timeout.
  * @escan_timeout_work: scan timeout worker.
  * @escan_ioctl_buf: dongle command buffer for escan commands.
- * @ap_info: host ap information.
- * @ci: used to link this structure to netdev private data.
+ * @vif_list: linked list of vif instances.
+ * @vif_cnt: number of vif instances.
  */
 struct brcmf_cfg80211_info {
-	struct wireless_dev *wdev;
+	struct wiphy *wiphy;
 	struct brcmf_cfg80211_conf *conf;
 	struct cfg80211_scan_request *scan_request;
-	struct brcmf_cfg80211_event_loop el;
-	struct list_head evt_q_list;
-	spinlock_t	 evt_q_lock;
 	struct mutex usr_sync;
 	struct brcmf_scan_results *bss_list;
-	struct brcmf_scan_results *scan_results;
-	struct brcmf_cfg80211_scan_req *scan_req_int;
+	struct brcmf_cfg80211_scan_req scan_req_int;
 	struct wl_cfg80211_bss_info *bss_info;
 	struct brcmf_cfg80211_ie ie;
-	struct brcmf_cfg80211_profile *profile;
-	struct brcmf_cfg80211_iscan_ctrl *iscan;
 	struct brcmf_cfg80211_connect_info conn_info;
 	struct brcmf_cfg80211_pmk_list *pmk_list;
-	struct work_struct event_work;
-	unsigned long status;
+	unsigned long scan_status;
 	struct brcmf_pub *pub;
 	u32 channel;
-	bool iscan_on;
-	bool iscan_kickstart;
 	bool active_scan;
 	bool sched_escan;
 	bool ibss_starter;
@@ -458,17 +399,17 @@ struct brcmf_cfg80211_info {
 	u8 *dcmd_buf;
 	u8 *extra_buf;
 	struct dentry *debugfsdir;
-	bool escan_on;
 	struct escan_info escan_info;
 	struct timer_list escan_timeout;
 	struct work_struct escan_timeout_work;
 	u8 *escan_ioctl_buf;
-	struct ap_info *ap_info;
+	struct list_head vif_list;
+	u8 vif_cnt;
 };
 
-static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *w)
+static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *cfg)
 {
-	return w->wdev->wiphy;
+	return cfg->wiphy;
 }
 
 static inline struct brcmf_cfg80211_info *wiphy_to_cfg(struct wiphy *w)
@@ -481,9 +422,12 @@ static inline struct brcmf_cfg80211_info *wdev_to_cfg(struct wireless_dev *wd)
 	return (struct brcmf_cfg80211_info *)(wdev_priv(wd));
 }
 
-static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg)
+static inline
+struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg)
 {
-	return cfg->wdev->netdev;
+	struct brcmf_cfg80211_vif *vif;
+	vif = list_first_entry(&cfg->vif_list, struct brcmf_cfg80211_vif, list);
+	return vif->wdev.netdev;
 }
 
 static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev)
@@ -491,8 +435,17 @@ static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev)
 	return wdev_to_cfg(ndev->ieee80211_ptr);
 }
 
-#define iscan_to_cfg(i) ((struct brcmf_cfg80211_info *)(i->data))
-#define cfg_to_iscan(w) (w->iscan)
+static inline struct brcmf_cfg80211_profile *ndev_to_prof(struct net_device *nd)
+{
+	struct brcmf_if *ifp = netdev_priv(nd);
+	return &ifp->vif->profile;
+}
+
+static inline struct brcmf_cfg80211_vif *ndev_to_vif(struct net_device *ndev)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	return ifp->vif;
+}
 
 static inline struct
 brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg)
@@ -500,15 +453,9 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg)
 	return &cfg->conn_info;
 }
 
-struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev,
-						  struct device *busdev,
-						  struct brcmf_pub *drvr);
+struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr);
 void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
-
-/* event handler from dongle */
-void brcmf_cfg80211_event(struct net_device *ndev,
-			  const struct brcmf_event_msg *e, void *data);
-s32 brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg);
-s32 brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg);
+s32 brcmf_cfg80211_up(struct net_device *ndev);
+s32 brcmf_cfg80211_down(struct net_device *ndev);
 
 #endif				/* _wl_cfg80211_h_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/Makefile b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
index e227c4c..d3d4151 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
@@ -40,7 +40,8 @@ BRCMSMAC_OFILES := \
 	phy/phytbl_n.o \
 	phy/phy_qmath.o \
 	dma.o \
-	brcms_trace_events.o
+	brcms_trace_events.o \
+	debug.o
 
 MODULEPFX := brcmsmac
 
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
index b89f127..de96290 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
@@ -692,7 +692,7 @@ void ai_pci_up(struct si_pub *sih)
 	sii = container_of(sih, struct si_info, pub);
 
 	if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
-		bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, true);
+		bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci[0], true);
 }
 
 /* Unconfigure and/or apply various WARs when going down */
@@ -703,7 +703,7 @@ void ai_pci_down(struct si_pub *sih)
 	sii = container_of(sih, struct si_info, pub);
 
 	if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
-		bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, false);
+		bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci[0], false);
 }
 
 /* Enable BT-COEX & Ex-PA for 4313 */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
index be5bcfb..1de94f3 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
@@ -21,6 +21,8 @@
 #include "antsel.h"
 #include "main.h"
 #include "ampdu.h"
+#include "debug.h"
+#include "brcms_trace_events.h"
 
 /* max number of mpdus in an ampdu */
 #define AMPDU_MAX_MPDU			32
@@ -40,8 +42,6 @@
 #define AMPDU_DEF_RETRY_LIMIT		5
 /* default tx retry limit at reg rate */
 #define AMPDU_DEF_RR_RETRY_LIMIT	2
-/* default weight of ampdu in txfifo */
-#define AMPDU_DEF_TXPKT_WEIGHT		2
 /* default ffpld reserved bytes */
 #define AMPDU_DEF_FFPLD_RSVD		2048
 /* # of inis to be freed on detach */
@@ -114,7 +114,6 @@ struct brcms_fifo_info {
  * mpdu_density: min mpdu spacing (0-7) ==> 2^(x-1)/8 usec
  * max_pdu: max pdus allowed in ampdu
  * dur: max duration of an ampdu (in msec)
- * txpkt_weight: weight of ampdu in txfifo; reduces rate lag
  * rx_factor: maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes
  * ffpld_rsvd: number of bytes to reserve for preload
  * max_txlen: max size of ampdu per mcs, bw and sgi
@@ -136,7 +135,6 @@ struct ampdu_info {
 	u8 mpdu_density;
 	s8 max_pdu;
 	u8 dur;
-	u8 txpkt_weight;
 	u8 rx_factor;
 	u32 ffpld_rsvd;
 	u32 max_txlen[MCS_TABLE_SIZE][2][2];
@@ -183,18 +181,19 @@ static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu)
 static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on)
 {
 	struct brcms_c_info *wlc = ampdu->wlc;
+	struct bcma_device *core = wlc->hw->d11core;
 
 	wlc->pub->_ampdu = false;
 
 	if (on) {
 		if (!(wlc->pub->_n_enab & SUPPORT_11N)) {
-			wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not "
-				"nmode enabled\n", wlc->pub->unit);
+			brcms_err(core, "wl%d: driver not nmode enabled\n",
+				  wlc->pub->unit);
 			return -ENOTSUPP;
 		}
 		if (!brcms_c_ampdu_cap(ampdu)) {
-			wiphy_err(ampdu->wlc->wiphy, "wl%d: device not "
-				"ampdu capable\n", wlc->pub->unit);
+			brcms_err(core, "wl%d: device not ampdu capable\n",
+				  wlc->pub->unit);
 			return -ENOTSUPP;
 		}
 		wlc->pub->_ampdu = on;
@@ -247,7 +246,6 @@ struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
 	ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
 	ampdu->max_pdu = AUTO;
 	ampdu->dur = AMPDU_MAX_DUR;
-	ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
 
 	ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
 	/*
@@ -374,7 +372,8 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
 				      offsetof(struct macstat, txfunfl[fid]));
 	new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
 	if (new_txunfl == 0) {
-		BCMMSG(wlc->wiphy, "TX status FRAG set but no tx underflows\n");
+		brcms_dbg_ht(wlc->hw->d11core,
+			     "TX status FRAG set but no tx underflows\n");
 		return -1;
 	}
 	fifo->prev_txfunfl = cur_txunfl;
@@ -396,8 +395,8 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
 	if (fifo->accum_txfunfl < 10)
 		return 0;
 
-	BCMMSG(wlc->wiphy, "ampdu_count %d  tx_underflows %d\n",
-		current_ampdu_cnt, fifo->accum_txfunfl);
+	brcms_dbg_ht(wlc->hw->d11core, "ampdu_count %d  tx_underflows %d\n",
+		     current_ampdu_cnt, fifo->accum_txfunfl);
 
 	/*
 	   compute the current ratio of tx unfl per ampdu.
@@ -450,9 +449,10 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
 		      (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
 		     / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
 
-		BCMMSG(wlc->wiphy, "DMA estimated transfer rate %d; "
-			"pre-load size %d\n",
-			fifo->dmaxferrate, fifo->ampdu_pld_size);
+		brcms_dbg_ht(wlc->hw->d11core,
+			     "DMA estimated transfer rate %d; "
+			     "pre-load size %d\n",
+			     fifo->dmaxferrate, fifo->ampdu_pld_size);
 	} else {
 
 		/* decrease ampdu size */
@@ -486,7 +486,7 @@ brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
 	scb_ampdu = &scb->scb_ampdu;
 
 	if (!ampdu->ini_enable[tid]) {
-		wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n",
+		brcms_err(wlc->hw->d11core, "%s: Rejecting tid %d\n",
 			  __func__, tid);
 		return;
 	}
@@ -498,378 +498,324 @@ brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
 	scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes;
 }
 
-int
-brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
-	      struct sk_buff **pdu, int prec)
+void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session,
+				 struct brcms_c_info *wlc)
 {
-	struct brcms_c_info *wlc;
-	struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
-	u8 tid, ndelim;
-	int err = 0;
-	u8 preamble_type = BRCMS_GF_PREAMBLE;
-	u8 fbr_preamble_type = BRCMS_GF_PREAMBLE;
-	u8 rts_preamble_type = BRCMS_LONG_PREAMBLE;
-	u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE;
+	session->wlc = wlc;
+	skb_queue_head_init(&session->skb_list);
+	session->max_ampdu_len = 0;    /* determined from first MPDU */
+	session->max_ampdu_frames = 0; /* determined from first MPDU */
+	session->ampdu_len = 0;
+	session->dma_len = 0;
+}
 
-	bool rr = true, fbr = false;
-	uint i, count = 0, fifo, seg_cnt = 0;
-	u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
-	u32 ampdu_len, max_ampdu_bytes = 0;
-	struct d11txh *txh = NULL;
+/*
+ * Preps the given packet for AMPDU based on the session data. If the
+ * frame cannot be accomodated in the current session, -ENOSPC is
+ * returned.
+ */
+int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,
+			    struct sk_buff *p)
+{
+	struct brcms_c_info *wlc = session->wlc;
+	struct ampdu_info *ampdu = wlc->ampdu;
+	struct scb *scb = &wlc->pri_scb;
+	struct scb_ampdu *scb_ampdu = &scb->scb_ampdu;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
+	struct ieee80211_tx_rate *txrate = tx_info->status.rates;
+	struct d11txh *txh = (struct d11txh *)p->data;
+	unsigned ampdu_frames;
+	u8 ndelim, tid;
 	u8 *plcp;
-	struct ieee80211_hdr *h;
-	struct scb *scb;
-	struct scb_ampdu *scb_ampdu;
-	struct scb_ampdu_tid_ini *ini;
-	u8 mcs = 0;
-	bool use_rts = false, use_cts = false;
-	u32 rspec = 0, rspec_fallback = 0;
-	u32 rts_rspec = 0, rts_rspec_fallback = 0;
-	u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
-	struct ieee80211_rts *rts;
-	u8 rr_retry_limit;
-	struct brcms_fifo_info *f;
+	uint len;
+	u16 mcl;
 	bool fbr_iscck;
-	struct ieee80211_tx_info *tx_info;
-	u16 qlen;
-	struct wiphy *wiphy;
-
-	wlc = ampdu->wlc;
-	wiphy = wlc->wiphy;
-	p = *pdu;
-
-	tid = (u8) (p->priority);
+	bool rr;
 
-	f = ampdu->fifo_tb + prio2fifo[tid];
+	ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
+	plcp = (u8 *)(txh + 1);
+	fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x03);
+	len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) :
+			  BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
+	len = roundup(len, 4) + (ndelim + 1) * AMPDU_DELIMITER_LEN;
 
-	scb = &wlc->pri_scb;
-	scb_ampdu = &scb->scb_ampdu;
-	ini = &scb_ampdu->ini[tid];
+	ampdu_frames = skb_queue_len(&session->skb_list);
+	if (ampdu_frames != 0) {
+		struct sk_buff *first;
 
-	/* Let pressure continue to build ... */
-	qlen = pktq_plen(&qi->q, prec);
-	if (ini->tx_in_transit > 0 &&
-	    qlen < min(scb_ampdu->max_pdu, ini->ba_wsize))
-		/* Collect multiple MPDU's to be sent in the next AMPDU */
-		return -EBUSY;
+		if (ampdu_frames + 1 > session->max_ampdu_frames ||
+		    session->ampdu_len + len > session->max_ampdu_len)
+			return -ENOSPC;
 
-	/* at this point we intend to transmit an AMPDU */
-	rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
-	ampdu_len = 0;
-	dma_len = 0;
-	while (p) {
-		struct ieee80211_tx_rate *txrate;
-
-		tx_info = IEEE80211_SKB_CB(p);
-		txrate = tx_info->status.rates;
+		/*
+		 * We aren't really out of space if the new frame is of
+		 * a different priority, but we want the same behaviour
+		 * so return -ENOSPC anyway.
+		 *
+		 * XXX: The old AMPDU code did this, but is it really
+		 * necessary?
+		 */
+		first = skb_peek(&session->skb_list);
+		if (p->priority != first->priority)
+			return -ENOSPC;
+	}
 
-		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
-			err = brcms_c_prep_pdu(wlc, p, &fifo);
-		} else {
-			wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__);
-			*pdu = NULL;
-			err = 0;
-			break;
-		}
+	/*
+	 * Now that we're sure this frame can be accomodated, update the
+	 * session information.
+	 */
+	session->ampdu_len += len;
+	session->dma_len += p->len;
 
-		if (err) {
-			if (err == -EBUSY) {
-				wiphy_err(wiphy, "wl%d: sendampdu: "
-					  "prep_xdu retry; seq 0x%x\n",
-					  wlc->pub->unit, seq);
-				*pdu = p;
-				break;
-			}
+	tid = (u8)p->priority;
 
-			/* error in the packet; reject it */
-			wiphy_err(wiphy, "wl%d: sendampdu: prep_xdu "
-				  "rejected; seq 0x%x\n", wlc->pub->unit, seq);
-			*pdu = NULL;
-			break;
-		}
+	/* Handle retry limits */
+	if (txrate[0].count <= ampdu->rr_retry_limit_tid[tid]) {
+		txrate[0].count++;
+		rr = true;
+	} else {
+		txrate[1].count++;
+		rr = false;
+	}
 
-		/* pkt is good to be aggregated */
-		txh = (struct d11txh *) p->data;
-		plcp = (u8 *) (txh + 1);
-		h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
-		seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
-		index = TX_SEQ_TO_INDEX(seq);
+	if (ampdu_frames == 0) {
+		u8 plcp0, plcp3, is40, sgi, mcs;
+		uint fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
+		struct brcms_fifo_info *f = &ampdu->fifo_tb[fifo];
 
-		/* check mcl fields and test whether it can be agg'd */
-		mcl = le16_to_cpu(txh->MacTxControlLow);
-		mcl &= ~TXC_AMPDU_MASK;
-		fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3);
-		txh->PreloadSize = 0;	/* always default to 0 */
-
-		/*  Handle retry limits */
-		if (txrate[0].count <= rr_retry_limit) {
-			txrate[0].count++;
-			rr = true;
-			fbr = false;
+		if (rr) {
+			plcp0 = plcp[0];
+			plcp3 = plcp[3];
 		} else {
-			fbr = true;
-			rr = false;
-			txrate[1].count++;
-		}
-
-		/* extract the length info */
-		len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
-		    : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
-
-		/* retrieve null delimiter count */
-		ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
-		seg_cnt += 1;
+			plcp0 = txh->FragPLCPFallback[0];
+			plcp3 = txh->FragPLCPFallback[3];
 
-		BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n",
-			wlc->pub->unit, count, len);
-
-		/*
-		 * aggregateable mpdu. For ucode/hw agg,
-		 * test whether need to break or change the epoch
-		 */
-		if (count == 0) {
-			mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
-			/* refill the bits since might be a retx mpdu */
-			mcl |= TXC_STARTMSDU;
-			rts = (struct ieee80211_rts *)&txh->rts_frame;
-
-			if (ieee80211_is_rts(rts->frame_control)) {
-				mcl |= TXC_SENDRTS;
-				use_rts = true;
-			}
-			if (ieee80211_is_cts(rts->frame_control)) {
-				mcl |= TXC_SENDCTS;
-				use_cts = true;
-			}
-		} else {
-			mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
-			mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
 		}
 
-		len = roundup(len, 4);
-		ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
+		/* Limit AMPDU size based on MCS */
+		is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
+		sgi = plcp3_issgi(plcp3) ? 1 : 0;
+		mcs = plcp0 & ~MIMO_PLCP_40MHZ;
+		session->max_ampdu_len = min(scb_ampdu->max_rx_ampdu_bytes,
+					     ampdu->max_txlen[mcs][is40][sgi]);
 
-		dma_len += (u16) p->len;
+		session->max_ampdu_frames = scb_ampdu->max_pdu;
+		if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
+			session->max_ampdu_frames =
+				min_t(u16, f->mcs2ampdu_table[mcs],
+				      session->max_ampdu_frames);
+		}
+	}
 
-		BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d"
-			" seg_cnt %d null delim %d\n",
-			wlc->pub->unit, ampdu_len, seg_cnt, ndelim);
+	/*
+	 * Treat all frames as "middle" frames of AMPDU here. First and
+	 * last frames must be fixed up after all MPDUs have been prepped.
+	 */
+	mcl = le16_to_cpu(txh->MacTxControlLow);
+	mcl &= ~TXC_AMPDU_MASK;
+	mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
+	mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
+	txh->MacTxControlLow = cpu_to_le16(mcl);
+	txh->PreloadSize = 0;	/* always default to 0 */
 
-		txh->MacTxControlLow = cpu_to_le16(mcl);
+	skb_queue_tail(&session->skb_list, p);
 
-		/* this packet is added */
-		pkt[count++] = p;
+	return 0;
+}
 
-		/* patch the first MPDU */
-		if (count == 1) {
-			u8 plcp0, plcp3, is40, sgi;
+void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session)
+{
+	struct brcms_c_info *wlc = session->wlc;
+	struct ampdu_info *ampdu = wlc->ampdu;
+	struct sk_buff *first, *last;
+	struct d11txh *txh;
+	struct ieee80211_tx_info *tx_info;
+	struct ieee80211_tx_rate *txrate;
+	u8 ndelim;
+	u8 *plcp;
+	uint len;
+	uint fifo;
+	struct brcms_fifo_info *f;
+	u16 mcl;
+	bool fbr;
+	bool fbr_iscck;
+	struct ieee80211_rts *rts;
+	bool use_rts = false, use_cts = false;
+	u16 dma_len = session->dma_len;
+	u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
+	u32 rspec = 0, rspec_fallback = 0;
+	u32 rts_rspec = 0, rts_rspec_fallback = 0;
+	u8 plcp0, plcp3, is40, sgi, mcs;
+	u16 mch;
+	u8 preamble_type = BRCMS_GF_PREAMBLE;
+	u8 fbr_preamble_type = BRCMS_GF_PREAMBLE;
+	u8 rts_preamble_type = BRCMS_LONG_PREAMBLE;
+	u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE;
 
-			if (rr) {
-				plcp0 = plcp[0];
-				plcp3 = plcp[3];
-			} else {
-				plcp0 = txh->FragPLCPFallback[0];
-				plcp3 = txh->FragPLCPFallback[3];
+	if (skb_queue_empty(&session->skb_list))
+		return;
 
-			}
-			is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
-			sgi = plcp3_issgi(plcp3) ? 1 : 0;
-			mcs = plcp0 & ~MIMO_PLCP_40MHZ;
-			max_ampdu_bytes =
-			    min(scb_ampdu->max_rx_ampdu_bytes,
-				ampdu->max_txlen[mcs][is40][sgi]);
-
-			if (is40)
-				mimo_ctlchbw =
-				   CHSPEC_SB_UPPER(wlc_phy_chanspec_get(
-								 wlc->band->pi))
-				   ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
-
-			/* rebuild the rspec and rspec_fallback */
-			rspec = RSPEC_MIMORATE;
-			rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
-			if (plcp[0] & MIMO_PLCP_40MHZ)
-				rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
-
-			if (fbr_iscck)	/* CCK */
-				rspec_fallback = cck_rspec(cck_phy2mac_rate
-						    (txh->FragPLCPFallback[0]));
-			else {	/* MIMO */
-				rspec_fallback = RSPEC_MIMORATE;
-				rspec_fallback |=
-				    txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
-				if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
-					rspec_fallback |=
-					    (PHY_TXC1_BW_40MHZ <<
-					     RSPEC_BW_SHIFT);
-			}
+	first = skb_peek(&session->skb_list);
+	last = skb_peek_tail(&session->skb_list);
+
+	/* Need to fix up last MPDU first to adjust AMPDU length */
+	txh = (struct d11txh *)last->data;
+	fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
+	f = &ampdu->fifo_tb[fifo];
+
+	mcl = le16_to_cpu(txh->MacTxControlLow);
+	mcl &= ~TXC_AMPDU_MASK;
+	mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
+	txh->MacTxControlLow = cpu_to_le16(mcl);
+
+	/* remove the null delimiter after last mpdu */
+	ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
+	txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
+	session->ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
+
+	/* remove the pad len from last mpdu */
+	fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
+	len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) :
+			  BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
+	session->ampdu_len -= roundup(len, 4) - len;
+
+	/* Now fix up the first MPDU */
+	tx_info = IEEE80211_SKB_CB(first);
+	txrate = tx_info->status.rates;
+	txh = (struct d11txh *)first->data;
+	plcp = (u8 *)(txh + 1);
+	rts = (struct ieee80211_rts *)&txh->rts_frame;
+
+	mcl = le16_to_cpu(txh->MacTxControlLow);
+	/* If only one MPDU leave it marked as last */
+	if (first != last) {
+		mcl &= ~TXC_AMPDU_MASK;
+		mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
+	}
+	mcl |= TXC_STARTMSDU;
+	if (ieee80211_is_rts(rts->frame_control)) {
+		mcl |= TXC_SENDRTS;
+		use_rts = true;
+	}
+	if (ieee80211_is_cts(rts->frame_control)) {
+		mcl |= TXC_SENDCTS;
+		use_cts = true;
+	}
+	txh->MacTxControlLow = cpu_to_le16(mcl);
 
-			if (use_rts || use_cts) {
-				rts_rspec =
-				    brcms_c_rspec_to_rts_rspec(wlc,
-					rspec, false, mimo_ctlchbw);
-				rts_rspec_fallback =
-				    brcms_c_rspec_to_rts_rspec(wlc,
-					rspec_fallback, false, mimo_ctlchbw);
-			}
-		}
+	fbr = txrate[1].count > 0;
+	if (!fbr) {
+		plcp0 = plcp[0];
+		plcp3 = plcp[3];
+	} else {
+		plcp0 = txh->FragPLCPFallback[0];
+		plcp3 = txh->FragPLCPFallback[3];
+	}
+	is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
+	sgi = plcp3_issgi(plcp3) ? 1 : 0;
+	mcs = plcp0 & ~MIMO_PLCP_40MHZ;
+
+	if (is40) {
+		if (CHSPEC_SB_UPPER(wlc_phy_chanspec_get(wlc->band->pi)))
+			mimo_ctlchbw = PHY_TXC1_BW_20MHZ_UP;
+		else
+			mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
+	}
 
-		/* if (first mpdu for host agg) */
-		/* test whether to add more */
-		if ((mcs_2_rate(mcs, true, false) >= f->dmaxferrate) &&
-		    (count == f->mcs2ampdu_table[mcs])) {
-			BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping"
-				" ampdu at %d for mcs %d\n",
-				wlc->pub->unit, count, mcs);
-			break;
-		}
+	/* rebuild the rspec and rspec_fallback */
+	rspec = RSPEC_MIMORATE;
+	rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
+	if (plcp[0] & MIMO_PLCP_40MHZ)
+		rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
 
-		if (count == scb_ampdu->max_pdu)
-			break;
+	fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x03);
+	if (fbr_iscck) {
+		rspec_fallback =
+			cck_rspec(cck_phy2mac_rate(txh->FragPLCPFallback[0]));
+	} else {
+		rspec_fallback = RSPEC_MIMORATE;
+		rspec_fallback |= txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
+		if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
+			rspec_fallback |= PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT;
+	}
 
-		/*
-		 * check to see if the next pkt is
-		 * a candidate for aggregation
-		 */
-		p = pktq_ppeek(&qi->q, prec);
-		if (p) {
-			tx_info = IEEE80211_SKB_CB(p);
-			if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
-			    ((u8) (p->priority) == tid)) {
-				plen = p->len + AMPDU_MAX_MPDU_OVERHEAD;
-				plen = max(scb_ampdu->min_len, plen);
+	if (use_rts || use_cts) {
+		rts_rspec =
+			brcms_c_rspec_to_rts_rspec(wlc, rspec,
+						   false, mimo_ctlchbw);
+		rts_rspec_fallback =
+			brcms_c_rspec_to_rts_rspec(wlc, rspec_fallback,
+						   false, mimo_ctlchbw);
+	}
 
-				if ((plen + ampdu_len) > max_ampdu_bytes) {
-					p = NULL;
-					continue;
-				}
+	BRCMS_SET_MIMO_PLCP_LEN(plcp, session->ampdu_len);
+	/* mark plcp to indicate ampdu */
+	BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
 
-				/*
-				 * check if there are enough
-				 * descriptors available
-				 */
-				if (*wlc->core->txavail[fifo] <= seg_cnt + 1) {
-					wiphy_err(wiphy, "%s: No fifo space  "
-						  "!!\n", __func__);
-					p = NULL;
-					continue;
-				}
-				/* next packet fit for aggregation so dequeue */
-				p = brcmu_pktq_pdeq(&qi->q, prec);
-			} else {
-				p = NULL;
-			}
-		}
-	}			/* end while(p) */
+	/* reset the mixed mode header durations */
+	if (txh->MModeLen) {
+		u16 mmodelen = brcms_c_calc_lsig_len(wlc, rspec,
+						     session->ampdu_len);
+		txh->MModeLen = cpu_to_le16(mmodelen);
+		preamble_type = BRCMS_MM_PREAMBLE;
+	}
+	if (txh->MModeFbrLen) {
+		u16 mmfbrlen = brcms_c_calc_lsig_len(wlc, rspec_fallback,
+						     session->ampdu_len);
+		txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
+		fbr_preamble_type = BRCMS_MM_PREAMBLE;
+	}
 
-	ini->tx_in_transit += count;
+	/* set the preload length */
+	if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
+		dma_len = min(dma_len, f->ampdu_pld_size);
+		txh->PreloadSize = cpu_to_le16(dma_len);
+	} else {
+		txh->PreloadSize = 0;
+	}
 
-	if (count) {
-		/* patch up the last txh */
-		txh = (struct d11txh *) pkt[count - 1]->data;
-		mcl = le16_to_cpu(txh->MacTxControlLow);
-		mcl &= ~TXC_AMPDU_MASK;
-		mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
-		txh->MacTxControlLow = cpu_to_le16(mcl);
-
-		/* remove the null delimiter after last mpdu */
-		ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
-		txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
-		ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
-
-		/* remove the pad len from last mpdu */
-		fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
-		len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
-		    : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
-		ampdu_len -= roundup(len, 4) - len;
-
-		/* patch up the first txh & plcp */
-		txh = (struct d11txh *) pkt[0]->data;
-		plcp = (u8 *) (txh + 1);
+	mch = le16_to_cpu(txh->MacTxControlHigh);
 
-		BRCMS_SET_MIMO_PLCP_LEN(plcp, ampdu_len);
-		/* mark plcp to indicate ampdu */
-		BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
+	/* update RTS dur fields */
+	if (use_rts || use_cts) {
+		u16 durid;
+		if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
+		    TXC_PREAMBLE_RTS_MAIN_SHORT)
+			rts_preamble_type = BRCMS_SHORT_PREAMBLE;
 
-		/* reset the mixed mode header durations */
-		if (txh->MModeLen) {
-			u16 mmodelen =
-			    brcms_c_calc_lsig_len(wlc, rspec, ampdu_len);
-			txh->MModeLen = cpu_to_le16(mmodelen);
-			preamble_type = BRCMS_MM_PREAMBLE;
-		}
-		if (txh->MModeFbrLen) {
-			u16 mmfbrlen =
-			    brcms_c_calc_lsig_len(wlc, rspec_fallback,
-						  ampdu_len);
-			txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
-			fbr_preamble_type = BRCMS_MM_PREAMBLE;
-		}
+		if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
+		     TXC_PREAMBLE_RTS_FB_SHORT)
+			rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE;
 
-		/* set the preload length */
-		if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
-			dma_len = min(dma_len, f->ampdu_pld_size);
-			txh->PreloadSize = cpu_to_le16(dma_len);
-		} else
-			txh->PreloadSize = 0;
-
-		mch = le16_to_cpu(txh->MacTxControlHigh);
-
-		/* update RTS dur fields */
-		if (use_rts || use_cts) {
-			u16 durid;
-			rts = (struct ieee80211_rts *)&txh->rts_frame;
-			if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
-			    TXC_PREAMBLE_RTS_MAIN_SHORT)
-				rts_preamble_type = BRCMS_SHORT_PREAMBLE;
-
-			if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
-			    TXC_PREAMBLE_RTS_FB_SHORT)
-				rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE;
-
-			durid =
-			    brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec,
+		durid = brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec,
 						   rspec, rts_preamble_type,
-						   preamble_type, ampdu_len,
-						   true);
-			rts->duration = cpu_to_le16(durid);
-			durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
-						       rts_rspec_fallback,
-						       rspec_fallback,
-						       rts_fbr_preamble_type,
-						       fbr_preamble_type,
-						       ampdu_len, true);
-			txh->RTSDurFallback = cpu_to_le16(durid);
-			/* set TxFesTimeNormal */
-			txh->TxFesTimeNormal = rts->duration;
-			/* set fallback rate version of TxFesTimeNormal */
-			txh->TxFesTimeFallback = txh->RTSDurFallback;
-		}
-
-		/* set flag and plcp for fallback rate */
-		if (fbr) {
-			mch |= TXC_AMPDU_FBR;
-			txh->MacTxControlHigh = cpu_to_le16(mch);
-			BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
-			BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
-		}
-
-		BCMMSG(wlc->wiphy, "wl%d: count %d ampdu_len %d\n",
-			wlc->pub->unit, count, ampdu_len);
-
-		/* inform rate_sel if it this is a rate probe pkt */
-		frameid = le16_to_cpu(txh->TxFrameID);
-		if (frameid & TXFID_RATE_PROBE_MASK)
-			wiphy_err(wiphy, "%s: XXX what to do with "
-				  "TXFID_RATE_PROBE_MASK!?\n", __func__);
-
-		for (i = 0; i < count; i++)
-			brcms_c_txfifo(wlc, fifo, pkt[i], i == (count - 1),
-				   ampdu->txpkt_weight);
+						   preamble_type,
+						   session->ampdu_len, true);
+		rts->duration = cpu_to_le16(durid);
+		durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
+						   rts_rspec_fallback,
+						   rspec_fallback,
+						   rts_fbr_preamble_type,
+						   fbr_preamble_type,
+						   session->ampdu_len, true);
+		txh->RTSDurFallback = cpu_to_le16(durid);
+		/* set TxFesTimeNormal */
+		txh->TxFesTimeNormal = rts->duration;
+		/* set fallback rate version of TxFesTimeNormal */
+		txh->TxFesTimeFallback = txh->RTSDurFallback;
+	}
 
+	/* set flag and plcp for fallback rate */
+	if (fbr) {
+		mch |= TXC_AMPDU_FBR;
+		txh->MacTxControlHigh = cpu_to_le16(mch);
+		BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
+		BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
 	}
-	/* endif (count) */
-	return err;
+
+	brcms_dbg_ht(wlc->hw->d11core, "wl%d: count %d ampdu_len %d\n",
+		     wlc->pub->unit, skb_queue_len(&session->skb_list),
+		     session->ampdu_len);
 }
 
 static void
@@ -909,7 +855,6 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
 	u8 antselid = 0;
 	u8 retry_limit, rr_retry_limit;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
-	struct wiphy *wiphy = wlc->wiphy;
 
 #ifdef DEBUG
 	u8 hole[AMPDU_MAX_MPDU];
@@ -955,13 +900,14 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
 		if (supr_status) {
 			update_rate = false;
 			if (supr_status == TX_STATUS_SUPR_BADCH) {
-				wiphy_err(wiphy,
+				brcms_err(wlc->hw->d11core,
 					  "%s: Pkt tx suppressed, illegal channel possibly %d\n",
 					  __func__, CHSPEC_CHANNEL(
 					  wlc->default_bss->chanspec));
 			} else {
 				if (supr_status != TX_STATUS_SUPR_FRAG)
-					wiphy_err(wiphy, "%s: supr_status 0x%x\n",
+					brcms_err(wlc->hw->d11core,
+						  "%s: supr_status 0x%x\n",
 						  __func__, supr_status);
 			}
 			/* no need to retry for badch; will fail again */
@@ -977,20 +923,14 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
 				 * if there were underflows, but pre-loading
 				 * is not active, notify rate adaptation.
 				 */
-				if (brcms_c_ffpld_check_txfunfl(wlc,
-					prio2fifo[tid]) > 0)
+				if (brcms_c_ffpld_check_txfunfl(wlc, queue) > 0)
 					tx_error = true;
 			}
 		} else if (txs->phyerr) {
 			update_rate = false;
-			wiphy_err(wiphy, "%s: ampdu tx phy error (0x%x)\n",
+			brcms_err(wlc->hw->d11core,
+				  "%s: ampdu tx phy error (0x%x)\n",
 				  __func__, txs->phyerr);
-
-			if (brcm_msg_level & LOG_ERROR_VAL) {
-				brcmu_prpkt("txpkt (AMPDU)", p);
-				brcms_c_print_txdesc((struct d11txh *) p->data);
-			}
-			brcms_c_print_txstatus(txs);
 		}
 	}
 
@@ -1003,6 +943,8 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
 		h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
 		seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
 
+		trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, sizeof(*txh));
+
 		if (tot_mpdu == 0) {
 			mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
 			mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
@@ -1012,10 +954,10 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
 		ack_recd = false;
 		if (ba_recd) {
 			bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
-			BCMMSG(wiphy,
-			       "tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n",
-			       tid, seq, start_seq, bindex,
-			       isset(bitmap, bindex), index);
+			brcms_dbg_ht(wlc->hw->d11core,
+				     "tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n",
+				     tid, seq, start_seq, bindex,
+				     isset(bitmap, bindex), index);
 			/* if acked then clear bit and free packet */
 			if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
 			    && isset(bitmap, bindex)) {
@@ -1046,14 +988,16 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
 		/* either retransmit or send bar if ack not recd */
 		if (!ack_recd) {
 			if (retry && (ini->txretry[index] < (int)retry_limit)) {
+				int ret;
 				ini->txretry[index]++;
 				ini->tx_in_transit--;
+				ret = brcms_c_txfifo(wlc, queue, p);
 				/*
-				 * Use high prededence for retransmit to
-				 * give some punch
+				 * We shouldn't be out of space in the DMA
+				 * ring here since we're reinserting a frame
+				 * that was just pulled out.
 				 */
-				brcms_c_txq_enq(wlc, scb, p,
-						BRCMS_PRIO_TO_HI_PREC(tid));
+				WARN_ONCE(ret, "queue %d out of txds\n", queue);
 			} else {
 				/* Retry timeout */
 				ini->tx_in_transit--;
@@ -1064,9 +1008,9 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
 				    IEEE80211_TX_STAT_AMPDU_NO_BACK;
 				skb_pull(p, D11_PHY_HDR_LEN);
 				skb_pull(p, D11_TXH_LEN);
-				BCMMSG(wiphy,
-				       "BA Timeout, seq %d, in_transit %d\n",
-				       seq, ini->tx_in_transit);
+				brcms_dbg_ht(wlc->hw->d11core,
+					     "BA Timeout, seq %d, in_transit %d\n",
+					     seq, ini->tx_in_transit);
 				ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
 							    p);
 			}
@@ -1080,12 +1024,9 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
 
 		p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
 	}
-	brcms_c_send_q(wlc);
 
 	/* update rate state */
 	antselid = brcms_c_antsel_antsel2id(wlc->asi, mimoantsel);
-
-	brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
 }
 
 void
@@ -1133,6 +1074,8 @@ brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
 		while (p) {
 			tx_info = IEEE80211_SKB_CB(p);
 			txh = (struct d11txh *) p->data;
+			trace_brcms_txdesc(&wlc->hw->d11core->dev, txh,
+					   sizeof(*txh));
 			mcl = le16_to_cpu(txh->MacTxControlLow);
 			brcmu_pkt_buf_free_skb(p);
 			/* break out if last packet of ampdu */
@@ -1142,7 +1085,6 @@ brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
 			p = dma_getnexttxp(wlc->hw->di[queue],
 					   DMA_RANGE_TRANSMITTED);
 		}
-		brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
 	}
 }
 
@@ -1182,23 +1124,6 @@ void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu)
 }
 
 /*
- * callback function that helps flushing ampdu packets from a priority queue
- */
-static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a)
-{
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu);
-	struct cb_del_ampdu_pars *ampdu_pars =
-				 (struct cb_del_ampdu_pars *)arg_a;
-	bool rc;
-
-	rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false;
-	rc = rc && (tx_info->rate_driver_data[0] == NULL || ampdu_pars->sta == NULL ||
-		    tx_info->rate_driver_data[0] == ampdu_pars->sta);
-	rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid);
-	return rc;
-}
-
-/*
  * callback function that helps invalidating ampdu packets in a DMA queue
  */
 static void dma_cb_fn_ampdu(void *txi, void *arg_a)
@@ -1218,15 +1143,5 @@ static void dma_cb_fn_ampdu(void *txi, void *arg_a)
 void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
 		     struct ieee80211_sta *sta, u16 tid)
 {
-	struct brcms_txq_info *qi = wlc->pkt_queue;
-	struct pktq *pq = &qi->q;
-	int prec;
-	struct cb_del_ampdu_pars ampdu_pars;
-
-	ampdu_pars.sta = sta;
-	ampdu_pars.tid = tid;
-	for (prec = 0; prec < pq->num_prec; prec++)
-		brcmu_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
-			    (void *)&ampdu_pars);
 	brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);
 }
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h
index 421f4ba..73d01e5 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h
@@ -17,11 +17,34 @@
 #ifndef _BRCM_AMPDU_H_
 #define _BRCM_AMPDU_H_
 
+/*
+ * Data structure representing an in-progress session for accumulating
+ * frames for AMPDU.
+ *
+ * wlc: pointer to common driver data
+ * skb_list: queue of skb's for AMPDU
+ * max_ampdu_len: maximum length for this AMPDU
+ * max_ampdu_frames: maximum number of frames for this AMPDU
+ * ampdu_len: total number of bytes accumulated for this AMPDU
+ * dma_len: DMA length of this AMPDU
+ */
+struct brcms_ampdu_session {
+	struct brcms_c_info *wlc;
+	struct sk_buff_head skb_list;
+	unsigned max_ampdu_len;
+	u16 max_ampdu_frames;
+	u16 ampdu_len;
+	u16 dma_len;
+};
+
+extern void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session,
+					struct brcms_c_info *wlc);
+extern int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,
+				   struct sk_buff *p);
+extern void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session);
+
 extern struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc);
 extern void brcms_c_ampdu_detach(struct ampdu_info *ampdu);
-extern int brcms_c_sendampdu(struct ampdu_info *ampdu,
-			     struct brcms_txq_info *qi,
-			     struct sk_buff **aggp, int prec);
 extern void brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
 				 struct sk_buff *p, struct tx_status *txs);
 extern void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/antsel.c b/drivers/net/wireless/brcm80211/brcmsmac/antsel.c
index 55e12c3..54c6169 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/antsel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/antsel.c
@@ -21,6 +21,7 @@
 #include "main.h"
 #include "phy_shim.h"
 #include "antsel.h"
+#include "debug.h"
 
 #define ANT_SELCFG_AUTO		0x80	/* bit indicates antenna sel AUTO */
 #define ANT_SELCFG_MASK		0x33	/* antenna configuration mask */
@@ -137,7 +138,8 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc)
 				asi->antsel_avail = false;
 			} else {
 				asi->antsel_avail = false;
-				wiphy_err(wlc->wiphy, "antsel_attach: 2o3 "
+				brcms_err(wlc->hw->d11core,
+					  "antsel_attach: 2o3 "
 					  "board cfg invalid\n");
 			}
 
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h b/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h
index 27dd73e..871781e 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h
@@ -14,22 +14,29 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM brcmsmac
-
 #if !defined(__TRACE_BRCMSMAC_H) || defined(TRACE_HEADER_MULTI_READ)
 
 #define __TRACE_BRCMSMAC_H
 
+#include <linux/types.h>
+#include <linux/device.h>
 #include <linux/tracepoint.h>
 #include "mac80211_if.h"
 
-#ifndef CONFIG_BRCMDBG
+#ifndef CONFIG_BRCM_TRACING
 #undef TRACE_EVENT
 #define TRACE_EVENT(name, proto, ...) \
 static inline void trace_ ## name(proto) {}
+#undef DECLARE_EVENT_CLASS
+#define DECLARE_EVENT_CLASS(...)
+#undef DEFINE_EVENT
+#define DEFINE_EVENT(evt_class, name, proto, ...) \
+static inline void trace_ ## name(proto) {}
 #endif
 
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM brcmsmac
+
 /*
  * We define a tracepoint, its arguments, its printk format and its
  * 'fast binary record' layout.
@@ -78,9 +85,165 @@ TRACE_EVENT(brcms_dpc,
 	)
 );
 
+TRACE_EVENT(brcms_macintstatus,
+	TP_PROTO(const struct device *dev, int in_isr, u32 macintstatus,
+		 u32 mask),
+	TP_ARGS(dev, in_isr, macintstatus, mask),
+	TP_STRUCT__entry(
+		__string(dev, dev_name(dev))
+		__field(int, in_isr)
+		__field(u32, macintstatus)
+		__field(u32, mask)
+	),
+	TP_fast_assign(
+		__assign_str(dev, dev_name(dev));
+		__entry->in_isr = in_isr;
+		__entry->macintstatus = macintstatus;
+		__entry->mask = mask;
+	),
+	TP_printk("[%s] in_isr=%d macintstatus=%#x mask=%#x", __get_str(dev),
+		  __entry->in_isr, __entry->macintstatus, __entry->mask)
+);
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM brcmsmac_tx
+
+TRACE_EVENT(brcms_txdesc,
+	TP_PROTO(const struct device *dev,
+		 void *txh, size_t txh_len),
+	TP_ARGS(dev, txh, txh_len),
+	TP_STRUCT__entry(
+		__string(dev, dev_name(dev))
+		__dynamic_array(u8, txh, txh_len)
+	),
+	TP_fast_assign(
+		__assign_str(dev, dev_name(dev));
+		memcpy(__get_dynamic_array(txh), txh, txh_len);
+	),
+	TP_printk("[%s] txdesc", __get_str(dev))
+);
+
+TRACE_EVENT(brcms_txstatus,
+	TP_PROTO(const struct device *dev, u16 framelen, u16 frameid,
+		 u16 status, u16 lasttxtime, u16 sequence, u16 phyerr,
+		 u16 ackphyrxsh),
+	TP_ARGS(dev, framelen, frameid, status, lasttxtime, sequence, phyerr,
+		ackphyrxsh),
+	TP_STRUCT__entry(
+		__string(dev, dev_name(dev))
+		__field(u16, framelen)
+		__field(u16, frameid)
+		__field(u16, status)
+		__field(u16, lasttxtime)
+		__field(u16, sequence)
+		__field(u16, phyerr)
+		__field(u16, ackphyrxsh)
+	),
+	TP_fast_assign(
+		__assign_str(dev, dev_name(dev));
+		__entry->framelen = framelen;
+		__entry->frameid = frameid;
+		__entry->status = status;
+		__entry->lasttxtime = lasttxtime;
+		__entry->sequence = sequence;
+		__entry->phyerr = phyerr;
+		__entry->ackphyrxsh = ackphyrxsh;
+	),
+	TP_printk("[%s] FrameId %#04x TxStatus %#04x LastTxTime %#04x "
+		  "Seq %#04x PHYTxStatus %#04x RxAck %#04x",
+		  __get_str(dev), __entry->frameid, __entry->status,
+		  __entry->lasttxtime, __entry->sequence, __entry->phyerr,
+		  __entry->ackphyrxsh)
+);
+
+TRACE_EVENT(brcms_ampdu_session,
+	TP_PROTO(const struct device *dev, unsigned max_ampdu_len,
+		 u16 max_ampdu_frames, u16 ampdu_len, u16 ampdu_frames,
+		 u16 dma_len),
+	TP_ARGS(dev, max_ampdu_len, max_ampdu_frames, ampdu_len, ampdu_frames,
+		dma_len),
+	TP_STRUCT__entry(
+		__string(dev, dev_name(dev))
+		__field(unsigned, max_ampdu_len)
+		__field(u16, max_ampdu_frames)
+		__field(u16, ampdu_len)
+		__field(u16, ampdu_frames)
+		__field(u16, dma_len)
+	),
+	TP_fast_assign(
+		__assign_str(dev, dev_name(dev));
+		__entry->max_ampdu_len = max_ampdu_len;
+		__entry->max_ampdu_frames = max_ampdu_frames;
+		__entry->ampdu_len = ampdu_len;
+		__entry->ampdu_frames = ampdu_frames;
+		__entry->dma_len = dma_len;
+	),
+	TP_printk("[%s] ampdu session max_len=%u max_frames=%u len=%u frames=%u dma_len=%u",
+		  __get_str(dev), __entry->max_ampdu_len,
+		  __entry->max_ampdu_frames, __entry->ampdu_len,
+		  __entry->ampdu_frames, __entry->dma_len)
+);
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM brcmsmac_msg
+
+#define MAX_MSG_LEN	100
+
+DECLARE_EVENT_CLASS(brcms_msg_event,
+	TP_PROTO(struct va_format *vaf),
+	TP_ARGS(vaf),
+	TP_STRUCT__entry(
+		__dynamic_array(char, msg, MAX_MSG_LEN)
+	),
+	TP_fast_assign(
+		WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+				       MAX_MSG_LEN, vaf->fmt,
+				       *vaf->va) >= MAX_MSG_LEN);
+	),
+	TP_printk("%s", __get_str(msg))
+);
+
+DEFINE_EVENT(brcms_msg_event, brcms_info,
+	TP_PROTO(struct va_format *vaf),
+	TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(brcms_msg_event, brcms_warn,
+	TP_PROTO(struct va_format *vaf),
+	TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(brcms_msg_event, brcms_err,
+	TP_PROTO(struct va_format *vaf),
+	TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(brcms_msg_event, brcms_crit,
+	TP_PROTO(struct va_format *vaf),
+	TP_ARGS(vaf)
+);
+
+TRACE_EVENT(brcms_dbg,
+	TP_PROTO(u32 level, const char *func, struct va_format *vaf),
+	TP_ARGS(level, func, vaf),
+	TP_STRUCT__entry(
+		__field(u32, level)
+		__string(func, func)
+		__dynamic_array(char, msg, MAX_MSG_LEN)
+	),
+	TP_fast_assign(
+		__entry->level = level;
+		__assign_str(func, func);
+		WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+				       MAX_MSG_LEN, vaf->fmt,
+				       *vaf->va) >= MAX_MSG_LEN);
+	),
+	TP_printk("%s: %s", __get_str(func), __get_str(msg))
+);
+
 #endif /* __TRACE_BRCMSMAC_H */
 
-#ifdef CONFIG_BRCMDBG
+#ifdef CONFIG_BRCM_TRACING
 
 #undef TRACE_INCLUDE_PATH
 #define TRACE_INCLUDE_PATH .
@@ -89,4 +252,4 @@ TRACE_EVENT(brcms_dpc,
 
 #include <trace/define_trace.h>
 
-#endif /* CONFIG_BRCMDBG */
+#endif /* CONFIG_BRCM_TRACING */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index 64a48f0..a90b722 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -26,6 +26,7 @@
 #include "stf.h"
 #include "channel.h"
 #include "mac80211_if.h"
+#include "debug.h"
 
 /* QDB() macro takes a dB value and converts to a quarter dB value */
 #define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
@@ -336,8 +337,6 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
 	const char *ccode = sprom->alpha2;
 	int ccode_len = sizeof(sprom->alpha2);
 
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
 	wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC);
 	if (wlc_cm == NULL)
 		return NULL;
@@ -615,8 +614,8 @@ brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec)
 
 	/* check the chanspec */
 	if (brcms_c_chspec_malformed(chspec)) {
-		wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n",
-			wlc->pub->unit, chspec);
+		brcms_err(wlc->hw->d11core, "wl%d: malformed chanspec 0x%x\n",
+			  wlc->pub->unit, chspec);
 		return false;
 	}
 
@@ -738,7 +737,8 @@ static int brcms_reg_notifier(struct wiphy *wiphy,
 		mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
 	} else {
 		mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
-		wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\"\n",
+		brcms_err(wlc->hw->d11core,
+			  "wl%d: %s: no valid channel for \"%s\"\n",
 			  wlc->pub->unit, __func__, request->alpha2);
 	}
 
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/brcm80211/brcmsmac/debug.c
new file mode 100644
index 0000000..6ba4136
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/debug.c
@@ -0,0 +1,44 @@
+#include <linux/net.h>
+#include "types.h"
+#include "debug.h"
+#include "brcms_trace_events.h"
+
+#define __brcms_fn(fn)						\
+void __brcms_ ##fn(struct device *dev, const char *fmt, ...)	\
+{								\
+	struct va_format vaf = {				\
+		.fmt = fmt,					\
+	};							\
+	va_list args;						\
+								\
+	va_start(args, fmt);					\
+	vaf.va = &args;						\
+	dev_ ##fn(dev, "%pV", &vaf);				\
+	trace_brcms_ ##fn(&vaf);				\
+	va_end(args);						\
+}
+
+__brcms_fn(info)
+__brcms_fn(warn)
+__brcms_fn(err)
+__brcms_fn(crit)
+
+#if defined(CONFIG_BRCMDBG) || defined(CONFIG_BRCM_TRACING)
+void __brcms_dbg(struct device *dev, u32 level, const char *func,
+		 const char *fmt, ...)
+{
+	struct va_format vaf = {
+		.fmt = fmt,
+	};
+	va_list args;
+
+	va_start(args, fmt);
+	vaf.va = &args;
+#ifdef CONFIG_BRCMDBG
+	if ((brcm_msg_level & level) && net_ratelimit())
+		dev_err(dev, "%s %pV", func, &vaf);
+#endif
+	trace_brcms_dbg(level, func, &vaf);
+	va_end(args);
+}
+#endif
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/debug.h b/drivers/net/wireless/brcm80211/brcmsmac/debug.h
new file mode 100644
index 0000000..f77066b
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/debug.h
@@ -0,0 +1,52 @@
+#ifndef _BRCMS_DEBUG_H_
+#define _BRCMS_DEBUG_H_
+
+#include <linux/device.h>
+#include <linux/bcma/bcma.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+#include "main.h"
+#include "mac80211_if.h"
+
+__printf(2, 3)
+void __brcms_info(struct device *dev, const char *fmt, ...);
+__printf(2, 3)
+void __brcms_warn(struct device *dev, const char *fmt, ...);
+__printf(2, 3)
+void __brcms_err(struct device *dev, const char *fmt, ...);
+__printf(2, 3)
+void __brcms_crit(struct device *dev, const char *fmt, ...);
+
+#if defined(CONFIG_BRCMDBG) || defined(CONFIG_BRCM_TRACING)
+__printf(4, 5)
+void __brcms_dbg(struct device *dev, u32 level, const char *func,
+		 const char *fmt, ...);
+#else
+static inline __printf(4, 5)
+void __brcms_dbg(struct device *dev, u32 level, const char *func,
+		 const char *fmt, ...)
+{
+}
+#endif
+
+/*
+ * Debug macros cannot be used when wlc is uninitialized. Generally
+ * this means any code that could run before brcms_c_attach() has
+ * returned successfully probably shouldn't use the following macros.
+ */
+
+#define brcms_dbg(core, l, f, a...)	__brcms_dbg(&(core)->dev, l, __func__, f, ##a)
+#define brcms_info(core, f, a...)	__brcms_info(&(core)->dev, f, ##a)
+#define brcms_warn(core, f, a...)	__brcms_warn(&(core)->dev, f, ##a)
+#define brcms_err(core, f, a...)	__brcms_err(&(core)->dev, f, ##a)
+#define brcms_crit(core, f, a...)	__brcms_crit(&(core)->dev, f, ##a)
+
+#define brcms_dbg_info(core, f, a...)		brcms_dbg(core, BRCM_DL_INFO, f, ##a)
+#define brcms_dbg_mac80211(core, f, a...)	brcms_dbg(core, BRCM_DL_MAC80211, f, ##a)
+#define brcms_dbg_rx(core, f, a...)		brcms_dbg(core, BRCM_DL_RX, f, ##a)
+#define brcms_dbg_tx(core, f, a...)		brcms_dbg(core, BRCM_DL_TX, f, ##a)
+#define brcms_dbg_int(core, f, a...)		brcms_dbg(core, BRCM_DL_INT, f, ##a)
+#define brcms_dbg_dma(core, f, a...)		brcms_dbg(core, BRCM_DL_DMA, f, ##a)
+#define brcms_dbg_ht(core, f, a...)		brcms_dbg(core, BRCM_DL_HT, f, ##a)
+
+#endif /* _BRCMS_DEBUG_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c
index 5e53305..511e457 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/dma.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c
@@ -14,17 +14,22 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
 
 #include <brcmu_utils.h>
 #include <aiutils.h>
 #include "types.h"
+#include "main.h"
 #include "dma.h"
 #include "soc.h"
+#include "scb.h"
+#include "ampdu.h"
+#include "debug.h"
+#include "brcms_trace_events.h"
 
 /*
  * dma register field offset calculation
@@ -176,28 +181,6 @@
 
 #define BCMEXTRAHDROOM 172
 
-/* debug/trace */
-#ifdef DEBUG
-#define	DMA_ERROR(fmt, ...)					\
-do {								\
-	if (*di->msg_level & 1)					\
-		pr_debug("%s: " fmt, __func__, ##__VA_ARGS__);	\
-} while (0)
-#define	DMA_TRACE(fmt, ...)					\
-do {								\
-	if (*di->msg_level & 2)					\
-		pr_debug("%s: " fmt, __func__, ##__VA_ARGS__);	\
-} while (0)
-#else
-#define	DMA_ERROR(fmt, ...)			\
-	no_printk(fmt, ##__VA_ARGS__)
-#define	DMA_TRACE(fmt, ...)			\
-	no_printk(fmt, ##__VA_ARGS__)
-#endif				/* DEBUG */
-
-#define	DMA_NONE(fmt, ...)			\
-	no_printk(fmt, ##__VA_ARGS__)
-
 #define	MAXNAMEL	8	/* 8 char names */
 
 /* macros to convert between byte offsets and indexes */
@@ -224,12 +207,14 @@ struct dma64desc {
 /* dma engine software state */
 struct dma_info {
 	struct dma_pub dma; /* exported structure */
-	uint *msg_level;	/* message level pointer */
 	char name[MAXNAMEL];	/* callers name for diag msgs */
 
 	struct bcma_device *core;
 	struct device *dmadev;
 
+	/* session information for AMPDU */
+	struct brcms_ampdu_session ampdu_session;
+
 	bool dma64;	/* this dma engine is operating in 64-bit mode */
 	bool addrext;	/* this dma engine supports DmaExtendedAddrChanges */
 
@@ -298,12 +283,6 @@ struct dma_info {
 	bool aligndesc_4k;
 };
 
-/*
- * default dma message level (if input msg_level
- * pointer is null in dma_attach())
- */
-static uint dma_msg_level;
-
 /* Check for odd number of 1's */
 static u32 parity32(__le32 data)
 {
@@ -353,7 +332,7 @@ static uint prevtxd(struct dma_info *di, uint i)
 
 static uint nextrxd(struct dma_info *di, uint i)
 {
-	return txd(di, i + 1);
+	return rxd(di, i + 1);
 }
 
 static uint ntxdactive(struct dma_info *di, uint h, uint t)
@@ -371,7 +350,7 @@ static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
 	uint dmactrlflags;
 
 	if (di == NULL) {
-		DMA_ERROR("NULL dma handle\n");
+		brcms_dbg_dma(di->core, "NULL dma handle\n");
 		return 0;
 	}
 
@@ -423,13 +402,15 @@ static bool _dma_isaddrext(struct dma_info *di)
 	/* not all tx or rx channel are available */
 	if (di->d64txregbase != 0) {
 		if (!_dma64_addrext(di, DMA64TXREGOFFS(di, control)))
-			DMA_ERROR("%s: DMA64 tx doesn't have AE set\n",
-				  di->name);
+			brcms_dbg_dma(di->core,
+				      "%s: DMA64 tx doesn't have AE set\n",
+				      di->name);
 		return true;
 	} else if (di->d64rxregbase != 0) {
 		if (!_dma64_addrext(di, DMA64RXREGOFFS(di, control)))
-			DMA_ERROR("%s: DMA64 rx doesn't have AE set\n",
-				  di->name);
+			brcms_dbg_dma(di->core,
+				      "%s: DMA64 rx doesn't have AE set\n",
+				      di->name);
 		return true;
 	}
 
@@ -530,8 +511,9 @@ static bool dma64_alloc(struct dma_info *di, uint direction)
 		va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
 			&alloced, &di->txdpaorig);
 		if (va == NULL) {
-			DMA_ERROR("%s: DMA_ALLOC_CONSISTENT(ntxd) failed\n",
-				  di->name);
+			brcms_dbg_dma(di->core,
+				      "%s: DMA_ALLOC_CONSISTENT(ntxd) failed\n",
+				      di->name);
 			return false;
 		}
 		align = (1 << align_bits);
@@ -544,8 +526,9 @@ static bool dma64_alloc(struct dma_info *di, uint direction)
 		va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
 			&alloced, &di->rxdpaorig);
 		if (va == NULL) {
-			DMA_ERROR("%s: DMA_ALLOC_CONSISTENT(nrxd) failed\n",
-				  di->name);
+			brcms_dbg_dma(di->core,
+				      "%s: DMA_ALLOC_CONSISTENT(nrxd) failed\n",
+				      di->name);
 			return false;
 		}
 		align = (1 << align_bits);
@@ -564,12 +547,13 @@ static bool _dma_alloc(struct dma_info *di, uint direction)
 	return dma64_alloc(di, direction);
 }
 
-struct dma_pub *dma_attach(char *name, struct si_pub *sih,
-			   struct bcma_device *core,
+struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc,
 			   uint txregbase, uint rxregbase, uint ntxd, uint nrxd,
 			   uint rxbufsize, int rxextheadroom,
-			   uint nrxpost, uint rxoffset, uint *msg_level)
+			   uint nrxpost, uint rxoffset)
 {
+	struct si_pub *sih = wlc->hw->sih;
+	struct bcma_device *core = wlc->hw->d11core;
 	struct dma_info *di;
 	u8 rev = core->id.rev;
 	uint size;
@@ -580,9 +564,6 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
 	if (di == NULL)
 		return NULL;
 
-	di->msg_level = msg_level ? msg_level : &dma_msg_level;
-
-
 	di->dma64 =
 		((bcma_aread32(core, BCMA_IOST) & SISF_DMA64) == SISF_DMA64);
 
@@ -598,11 +579,11 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
 	 */
 	_dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0);
 
-	DMA_TRACE("%s: %s flags 0x%x ntxd %d nrxd %d "
-		  "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
-		  "txregbase %u rxregbase %u\n", name, "DMA64",
-		  di->dma.dmactrlflags, ntxd, nrxd, rxbufsize,
-		  rxextheadroom, nrxpost, rxoffset, txregbase, rxregbase);
+	brcms_dbg_dma(di->core, "%s: %s flags 0x%x ntxd %d nrxd %d "
+		      "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
+		      "txregbase %u rxregbase %u\n", name, "DMA64",
+		      di->dma.dmactrlflags, ntxd, nrxd, rxbufsize,
+		      rxextheadroom, nrxpost, rxoffset, txregbase, rxregbase);
 
 	/* make a private copy of our callers name */
 	strncpy(di->name, name, MAXNAMEL);
@@ -664,8 +645,8 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
 		di->dmadesc_align = 4;	/* 16 byte alignment */
 	}
 
-	DMA_NONE("DMA descriptor align_needed %d, align %d\n",
-		 di->aligndesc_4k, di->dmadesc_align);
+	brcms_dbg_dma(di->core, "DMA descriptor align_needed %d, align %d\n",
+		      di->aligndesc_4k, di->dmadesc_align);
 
 	/* allocate tx packet pointer vector */
 	if (ntxd) {
@@ -703,21 +684,27 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
 
 	if ((di->ddoffsetlow != 0) && !di->addrext) {
 		if (di->txdpa > SI_PCI_DMA_SZ) {
-			DMA_ERROR("%s: txdpa 0x%x: addrext not supported\n",
-				  di->name, (u32)di->txdpa);
+			brcms_dbg_dma(di->core,
+				      "%s: txdpa 0x%x: addrext not supported\n",
+				      di->name, (u32)di->txdpa);
 			goto fail;
 		}
 		if (di->rxdpa > SI_PCI_DMA_SZ) {
-			DMA_ERROR("%s: rxdpa 0x%x: addrext not supported\n",
-				  di->name, (u32)di->rxdpa);
+			brcms_dbg_dma(di->core,
+				      "%s: rxdpa 0x%x: addrext not supported\n",
+				      di->name, (u32)di->rxdpa);
 			goto fail;
 		}
 	}
 
-	DMA_TRACE("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh 0x%x addrext %d\n",
-		  di->ddoffsetlow, di->ddoffsethigh,
-		  di->dataoffsetlow, di->dataoffsethigh,
-		  di->addrext);
+	/* Initialize AMPDU session */
+	brcms_c_ampdu_reset_session(&di->ampdu_session, wlc);
+
+	brcms_dbg_dma(di->core,
+		      "ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh 0x%x addrext %d\n",
+		      di->ddoffsetlow, di->ddoffsethigh,
+		      di->dataoffsetlow, di->dataoffsethigh,
+		      di->addrext);
 
 	return (struct dma_pub *) di;
 
@@ -763,7 +750,7 @@ void dma_detach(struct dma_pub *pub)
 {
 	struct dma_info *di = (struct dma_info *)pub;
 
-	DMA_TRACE("%s:\n", di->name);
+	brcms_dbg_dma(di->core, "%s:\n", di->name);
 
 	/* free dma descriptor rings */
 	if (di->txd64)
@@ -839,7 +826,7 @@ static void _dma_rxenable(struct dma_info *di)
 	uint dmactrlflags = di->dma.dmactrlflags;
 	u32 control;
 
-	DMA_TRACE("%s:\n", di->name);
+	brcms_dbg_dma(di->core, "%s:\n", di->name);
 
 	control = D64_RC_RE | (bcma_read32(di->core,
 					   DMA64RXREGOFFS(di, control)) &
@@ -859,7 +846,7 @@ void dma_rxinit(struct dma_pub *pub)
 {
 	struct dma_info *di = (struct dma_info *)pub;
 
-	DMA_TRACE("%s:\n", di->name);
+	brcms_dbg_dma(di->core, "%s:\n", di->name);
 
 	if (di->nrxd == 0)
 		return;
@@ -954,7 +941,7 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
 		return 0;
 
 	len = le16_to_cpu(*(__le16 *) (p->data));
-	DMA_TRACE("%s: dma_rx len %d\n", di->name, len);
+	brcms_dbg_dma(di->core, "%s: dma_rx len %d\n", di->name, len);
 	dma_spin_for_len(len, p);
 
 	/* set actual length */
@@ -981,14 +968,15 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
 					      DMA64RXREGOFFS(di, status0)) &
 				  D64_RS0_CD_MASK) - di->rcvptrbase) &
 				D64_RS0_CD_MASK, struct dma64desc);
-			DMA_ERROR("rxin %d rxout %d, hw_curr %d\n",
-				   di->rxin, di->rxout, cur);
+			brcms_dbg_dma(di->core,
+				      "rxin %d rxout %d, hw_curr %d\n",
+				      di->rxin, di->rxout, cur);
 		}
 #endif				/* DEBUG */
 
 		if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) {
-			DMA_ERROR("%s: bad frame length (%d)\n",
-				  di->name, len);
+			brcms_dbg_dma(di->core, "%s: bad frame length (%d)\n",
+				      di->name, len);
 			skb_queue_walk_safe(&dma_frames, p, next) {
 				skb_unlink(p, &dma_frames);
 				brcmu_pkt_buf_free_skb(p);
@@ -1005,7 +993,7 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
 
 static bool dma64_rxidle(struct dma_info *di)
 {
-	DMA_TRACE("%s:\n", di->name);
+	brcms_dbg_dma(di->core, "%s:\n", di->name);
 
 	if (di->nrxd == 0)
 		return true;
@@ -1016,6 +1004,17 @@ static bool dma64_rxidle(struct dma_info *di)
 		 D64_RS0_CD_MASK));
 }
 
+static bool dma64_txidle(struct dma_info *di)
+{
+	if (di->ntxd == 0)
+		return true;
+
+	return ((bcma_read32(di->core,
+			     DMA64TXREGOFFS(di, status0)) & D64_XS0_CD_MASK) ==
+		(bcma_read32(di->core, DMA64TXREGOFFS(di, ptr)) &
+		 D64_XS0_CD_MASK));
+}
+
 /*
  * post receive buffers
  *  return false is refill failed completely and ring is empty this will stall
@@ -1047,7 +1046,7 @@ bool dma_rxfill(struct dma_pub *pub)
 
 	n = di->nrxpost - nrxdactive(di, rxin, rxout);
 
-	DMA_TRACE("%s: post %d\n", di->name, n);
+	brcms_dbg_dma(di->core, "%s: post %d\n", di->name, n);
 
 	if (di->rxbufsize > BCMEXTRAHDROOM)
 		extra_offset = di->rxextrahdrroom;
@@ -1060,9 +1059,11 @@ bool dma_rxfill(struct dma_pub *pub)
 		p = brcmu_pkt_buf_get_skb(di->rxbufsize + extra_offset);
 
 		if (p == NULL) {
-			DMA_ERROR("%s: out of rxbufs\n", di->name);
+			brcms_dbg_dma(di->core, "%s: out of rxbufs\n",
+				      di->name);
 			if (i == 0 && dma64_rxidle(di)) {
-				DMA_ERROR("%s: ring is empty !\n", di->name);
+				brcms_dbg_dma(di->core, "%s: ring is empty !\n",
+					      di->name);
 				ring_empty = true;
 			}
 			di->dma.rxnobuf++;
@@ -1107,7 +1108,7 @@ void dma_rxreclaim(struct dma_pub *pub)
 	struct dma_info *di = (struct dma_info *)pub;
 	struct sk_buff *p;
 
-	DMA_TRACE("%s:\n", di->name);
+	brcms_dbg_dma(di->core, "%s:\n", di->name);
 
 	while ((p = _dma_getnextrxp(di, true)))
 		brcmu_pkt_buf_free_skb(p);
@@ -1138,7 +1139,7 @@ void dma_txinit(struct dma_pub *pub)
 	struct dma_info *di = (struct dma_info *)pub;
 	u32 control = D64_XC_XE;
 
-	DMA_TRACE("%s:\n", di->name);
+	brcms_dbg_dma(di->core, "%s:\n", di->name);
 
 	if (di->ntxd == 0)
 		return;
@@ -1170,7 +1171,7 @@ void dma_txsuspend(struct dma_pub *pub)
 {
 	struct dma_info *di = (struct dma_info *)pub;
 
-	DMA_TRACE("%s:\n", di->name);
+	brcms_dbg_dma(di->core, "%s:\n", di->name);
 
 	if (di->ntxd == 0)
 		return;
@@ -1182,7 +1183,7 @@ void dma_txresume(struct dma_pub *pub)
 {
 	struct dma_info *di = (struct dma_info *)pub;
 
-	DMA_TRACE("%s:\n", di->name);
+	brcms_dbg_dma(di->core, "%s:\n", di->name);
 
 	if (di->ntxd == 0)
 		return;
@@ -1205,11 +1206,11 @@ void dma_txreclaim(struct dma_pub *pub, enum txd_range range)
 	struct dma_info *di = (struct dma_info *)pub;
 	struct sk_buff *p;
 
-	DMA_TRACE("%s: %s\n",
-		  di->name,
-		  range == DMA_RANGE_ALL ? "all" :
-		  range == DMA_RANGE_TRANSMITTED ? "transmitted" :
-		  "transferred");
+	brcms_dbg_dma(di->core, "%s: %s\n",
+		      di->name,
+		      range == DMA_RANGE_ALL ? "all" :
+		      range == DMA_RANGE_TRANSMITTED ? "transmitted" :
+		      "transferred");
 
 	if (di->txin == di->txout)
 		return;
@@ -1264,39 +1265,25 @@ bool dma_rxreset(struct dma_pub *pub)
 	return status == D64_RS0_RS_DISABLED;
 }
 
-/*
- * !! tx entry routine
- * WARNING: call must check the return value for error.
- *   the error(toss frames) could be fatal and cause many subsequent hard
- *   to debug problems
- */
-int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit)
+static void dma_txenq(struct dma_info *di, struct sk_buff *p)
 {
-	struct dma_info *di = (struct dma_info *)pub;
 	unsigned char *data;
 	uint len;
 	u16 txout;
 	u32 flags = 0;
 	dma_addr_t pa;
 
-	DMA_TRACE("%s:\n", di->name);
-
 	txout = di->txout;
 
+	if (WARN_ON(nexttxd(di, txout) == di->txin))
+		return;
+
 	/*
 	 * obtain and initialize transmit descriptor entry.
 	 */
 	data = p->data;
 	len = p->len;
 
-	/* no use to transmit a zero length packet */
-	if (len == 0)
-		return 0;
-
-	/* return nonzero if out of tx descriptors */
-	if (nexttxd(di, txout) == di->txin)
-		goto outoftxd;
-
 	/* get physical address of buffer start */
 	pa = dma_map_single(di->dmadev, data, len, DMA_TO_DEVICE);
 
@@ -1318,23 +1305,147 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit)
 
 	/* bump the tx descriptor index */
 	di->txout = txout;
+}
 
-	/* kick the chip */
-	if (commit)
-		bcma_write32(di->core, DMA64TXREGOFFS(di, ptr),
-		      di->xmtptrbase + I2B(txout, struct dma64desc));
+static void ampdu_finalize(struct dma_info *di)
+{
+	struct brcms_ampdu_session *session = &di->ampdu_session;
+	struct sk_buff *p;
+
+	trace_brcms_ampdu_session(&session->wlc->hw->d11core->dev,
+				  session->max_ampdu_len,
+				  session->max_ampdu_frames,
+				  session->ampdu_len,
+				  skb_queue_len(&session->skb_list),
+				  session->dma_len);
+
+	if (WARN_ON(skb_queue_empty(&session->skb_list)))
+		return;
+
+	brcms_c_ampdu_finalize(session);
+
+	while (!skb_queue_empty(&session->skb_list)) {
+		p = skb_dequeue(&session->skb_list);
+		dma_txenq(di, p);
+	}
+
+	bcma_write32(di->core, DMA64TXREGOFFS(di, ptr),
+		     di->xmtptrbase + I2B(di->txout, struct dma64desc));
+	brcms_c_ampdu_reset_session(session, session->wlc);
+}
+
+static void prep_ampdu_frame(struct dma_info *di, struct sk_buff *p)
+{
+	struct brcms_ampdu_session *session = &di->ampdu_session;
+	int ret;
+
+	ret = brcms_c_ampdu_add_frame(session, p);
+	if (ret == -ENOSPC) {
+		/*
+		 * AMPDU cannot accomodate this frame. Close out the in-
+		 * progress AMPDU session and start a new one.
+		 */
+		ampdu_finalize(di);
+		ret = brcms_c_ampdu_add_frame(session, p);
+	}
+
+	WARN_ON(ret);
+}
+
+/* Update count of available tx descriptors based on current DMA state */
+static void dma_update_txavail(struct dma_info *di)
+{
+	/*
+	 * Available space is number of descriptors less the number of
+	 * active descriptors and the number of queued AMPDU frames.
+	 */
+	di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) -
+			  skb_queue_len(&di->ampdu_session.skb_list) - 1;
+}
+
+/*
+ * !! tx entry routine
+ * WARNING: call must check the return value for error.
+ *   the error(toss frames) could be fatal and cause many subsequent hard
+ *   to debug problems
+ */
+int dma_txfast(struct brcms_c_info *wlc, struct dma_pub *pub,
+	       struct sk_buff *p)
+{
+	struct dma_info *di = (struct dma_info *)pub;
+	struct brcms_ampdu_session *session = &di->ampdu_session;
+	struct ieee80211_tx_info *tx_info;
+	bool is_ampdu;
+
+	/* no use to transmit a zero length packet */
+	if (p->len == 0)
+		return 0;
+
+	/* return nonzero if out of tx descriptors */
+	if (di->dma.txavail == 0 || nexttxd(di, di->txout) == di->txin)
+		goto outoftxd;
+
+	tx_info = IEEE80211_SKB_CB(p);
+	is_ampdu = tx_info->flags & IEEE80211_TX_CTL_AMPDU;
+	if (is_ampdu)
+		prep_ampdu_frame(di, p);
+	else
+		dma_txenq(di, p);
 
 	/* tx flow control */
-	di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1;
+	dma_update_txavail(di);
+
+	/* kick the chip */
+	if (is_ampdu) {
+		/*
+		 * Start sending data if we've got a full AMPDU, there's
+		 * no more space in the DMA ring, or the ring isn't
+		 * currently transmitting.
+		 */
+		if (skb_queue_len(&session->skb_list) == session->max_ampdu_frames ||
+		    di->dma.txavail == 0 || dma64_txidle(di))
+			ampdu_finalize(di);
+	} else {
+		bcma_write32(di->core, DMA64TXREGOFFS(di, ptr),
+			     di->xmtptrbase + I2B(di->txout, struct dma64desc));
+	}
 
 	return 0;
 
  outoftxd:
-	DMA_ERROR("%s: out of txds !!!\n", di->name);
+	brcms_dbg_dma(di->core, "%s: out of txds !!!\n", di->name);
 	brcmu_pkt_buf_free_skb(p);
 	di->dma.txavail = 0;
 	di->dma.txnobuf++;
-	return -1;
+	return -ENOSPC;
+}
+
+void dma_txflush(struct dma_pub *pub)
+{
+	struct dma_info *di = (struct dma_info *)pub;
+	struct brcms_ampdu_session *session = &di->ampdu_session;
+
+	if (!skb_queue_empty(&session->skb_list))
+		ampdu_finalize(di);
+}
+
+int dma_txpending(struct dma_pub *pub)
+{
+	struct dma_info *di = (struct dma_info *)pub;
+	return ntxdactive(di, di->txin, di->txout);
+}
+
+/*
+ * If we have an active AMPDU session and are not transmitting,
+ * this function will force tx to start.
+ */
+void dma_kick_tx(struct dma_pub *pub)
+{
+	struct dma_info *di = (struct dma_info *)pub;
+	struct brcms_ampdu_session *session = &di->ampdu_session;
+
+	if (!skb_queue_empty(&session->skb_list) && dma64_txidle(di))
+		ampdu_finalize(di);
 }
 
 /*
@@ -1354,11 +1465,11 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range)
 	u16 active_desc;
 	struct sk_buff *txp;
 
-	DMA_TRACE("%s: %s\n",
-		  di->name,
-		  range == DMA_RANGE_ALL ? "all" :
-		  range == DMA_RANGE_TRANSMITTED ? "transmitted" :
-		  "transferred");
+	brcms_dbg_dma(di->core, "%s: %s\n",
+		      di->name,
+		      range == DMA_RANGE_ALL ? "all" :
+		      range == DMA_RANGE_TRANSMITTED ? "transmitted" :
+		      "transferred");
 
 	if (di->ntxd == 0)
 		return NULL;
@@ -1412,13 +1523,13 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range)
 	di->txin = i;
 
 	/* tx flow control */
-	di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1;
+	dma_update_txavail(di);
 
 	return txp;
 
  bogus:
-	DMA_NONE("bogus curr: start %d end %d txout %d\n",
-		 start, end, di->txout);
+	brcms_dbg_dma(di->core, "bogus curr: start %d end %d txout %d\n",
+		      start, end, di->txout);
 	return NULL;
 }
 
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.h b/drivers/net/wireless/brcm80211/brcmsmac/dma.h
index cc269ee..ff5b80b 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/dma.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.h
@@ -74,12 +74,11 @@ struct dma_pub {
 	uint txnobuf;		/* tx out of dma descriptors */
 };
 
-extern struct dma_pub *dma_attach(char *name, struct si_pub *sih,
-				  struct bcma_device *d11core,
+extern struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc,
 				  uint txregbase, uint rxregbase,
 				  uint ntxd, uint nrxd,
 				  uint rxbufsize, int rxextheadroom,
-				  uint nrxpost, uint rxoffset, uint *msg_level);
+				  uint nrxpost, uint rxoffset);
 
 void dma_rxinit(struct dma_pub *pub);
 int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list);
@@ -87,7 +86,11 @@ bool dma_rxfill(struct dma_pub *pub);
 bool dma_rxreset(struct dma_pub *pub);
 bool dma_txreset(struct dma_pub *pub);
 void dma_txinit(struct dma_pub *pub);
-int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit);
+int dma_txfast(struct brcms_c_info *wlc, struct dma_pub *pub,
+	       struct sk_buff *p0);
+void dma_txflush(struct dma_pub *pub);
+int dma_txpending(struct dma_pub *pub);
+void dma_kick_tx(struct dma_pub *pub);
 void dma_txsuspend(struct dma_pub *pub);
 bool dma_txsuspended(struct dma_pub *pub);
 void dma_txresume(struct dma_pub *pub);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index a744ea5..1710ccb 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -33,6 +33,7 @@
 #include "ucode_loader.h"
 #include "mac80211_if.h"
 #include "main.h"
+#include "debug.h"
 
 #define N_TX_QUEUES	4 /* #tx queues on mac80211<->driver interface */
 
@@ -98,10 +99,14 @@ static struct bcma_device_id brcms_coreid_table[] = {
 };
 MODULE_DEVICE_TABLE(bcma, brcms_coreid_table);
 
-#ifdef DEBUG
-static int msglevel = 0xdeadbeef;
-module_param(msglevel, int, 0);
-#endif				/* DEBUG */
+#if defined(CONFIG_BRCMDBG)
+/*
+ * Module parameter for setting the debug message level. Available
+ * flags are specified by the BRCM_DL_* macros in
+ * drivers/net/wireless/brcm80211/include/defs.h.
+ */
+module_param_named(debug, brcm_msg_level, uint, S_IRUGO | S_IWUSR);
+#endif
 
 static struct ieee80211_channel brcms_2ghz_chantable[] = {
 	CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS),
@@ -276,7 +281,7 @@ static void brcms_ops_tx(struct ieee80211_hw *hw,
 
 	spin_lock_bh(&wl->lock);
 	if (!wl->pub->up) {
-		wiphy_err(wl->wiphy, "ops->tx called while down\n");
+		brcms_err(wl->wlc->hw->d11core, "ops->tx called while down\n");
 		kfree_skb(skb);
 		goto done;
 	}
@@ -313,8 +318,8 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
 	spin_unlock_bh(&wl->lock);
 
 	if (err != 0)
-		wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__,
-			  err);
+		brcms_err(wl->wlc->hw->d11core, "%s: brcms_up() returned %d\n",
+			  __func__, err);
 	return err;
 }
 
@@ -332,7 +337,7 @@ static void brcms_ops_stop(struct ieee80211_hw *hw)
 	status = brcms_c_chipmatch(wl->wlc->hw->d11core);
 	spin_unlock_bh(&wl->lock);
 	if (!status) {
-		wiphy_err(wl->wiphy,
+		brcms_err(wl->wlc->hw->d11core,
 			  "wl: brcms_ops_stop: chipmatch failed\n");
 		return;
 	}
@@ -350,8 +355,9 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 
 	/* Just STA for now */
 	if (vif->type != NL80211_IFTYPE_STATION) {
-		wiphy_err(hw->wiphy, "%s: Attempt to add type %d, only"
-			  " STA for now\n", __func__, vif->type);
+		brcms_err(wl->wlc->hw->d11core,
+			  "%s: Attempt to add type %d, only STA for now\n",
+			  __func__, vif->type);
 		return -EOPNOTSUPP;
 	}
 
@@ -370,9 +376,9 @@ static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct ieee80211_conf *conf = &hw->conf;
 	struct brcms_info *wl = hw->priv;
+	struct bcma_device *core = wl->wlc->hw->d11core;
 	int err = 0;
 	int new_int;
-	struct wiphy *wiphy = hw->wiphy;
 
 	spin_lock_bh(&wl->lock);
 	if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
@@ -380,25 +386,26 @@ static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
 						   conf->listen_interval);
 	}
 	if (changed & IEEE80211_CONF_CHANGE_MONITOR)
-		wiphy_dbg(wiphy, "%s: change monitor mode: %s\n",
-			  __func__, conf->flags & IEEE80211_CONF_MONITOR ?
-			  "true" : "false");
+		brcms_dbg_info(core, "%s: change monitor mode: %s\n",
+			       __func__, conf->flags & IEEE80211_CONF_MONITOR ?
+			       "true" : "false");
 	if (changed & IEEE80211_CONF_CHANGE_PS)
-		wiphy_err(wiphy, "%s: change power-save mode: %s (implement)\n",
+		brcms_err(core, "%s: change power-save mode: %s (implement)\n",
 			  __func__, conf->flags & IEEE80211_CONF_PS ?
 			  "true" : "false");
 
 	if (changed & IEEE80211_CONF_CHANGE_POWER) {
 		err = brcms_c_set_tx_power(wl->wlc, conf->power_level);
 		if (err < 0) {
-			wiphy_err(wiphy, "%s: Error setting power_level\n",
+			brcms_err(core, "%s: Error setting power_level\n",
 				  __func__);
 			goto config_out;
 		}
 		new_int = brcms_c_get_tx_power(wl->wlc);
 		if (new_int != conf->power_level)
-			wiphy_err(wiphy, "%s: Power level req != actual, %d %d"
-				  "\n", __func__, conf->power_level,
+			brcms_err(core,
+				  "%s: Power level req != actual, %d %d\n",
+				  __func__, conf->power_level,
 				  new_int);
 	}
 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
@@ -425,13 +432,13 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
 			struct ieee80211_bss_conf *info, u32 changed)
 {
 	struct brcms_info *wl = hw->priv;
-	struct wiphy *wiphy = hw->wiphy;
+	struct bcma_device *core = wl->wlc->hw->d11core;
 
 	if (changed & BSS_CHANGED_ASSOC) {
 		/* association status changed (associated/disassociated)
 		 * also implies a change in the AID.
 		 */
-		wiphy_err(wiphy, "%s: %s: %sassociated\n", KBUILD_MODNAME,
+		brcms_err(core, "%s: %s: %sassociated\n", KBUILD_MODNAME,
 			  __func__, info->assoc ? "" : "dis");
 		spin_lock_bh(&wl->lock);
 		brcms_c_associate_upd(wl->wlc, info->assoc);
@@ -491,7 +498,7 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
 		error = brcms_c_set_rateset(wl->wlc, &rs);
 		spin_unlock_bh(&wl->lock);
 		if (error)
-			wiphy_err(wiphy, "changing basic rates failed: %d\n",
+			brcms_err(core, "changing basic rates failed: %d\n",
 				  error);
 	}
 	if (changed & BSS_CHANGED_BEACON_INT) {
@@ -508,30 +515,30 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
 	}
 	if (changed & BSS_CHANGED_BEACON)
 		/* Beacon data changed, retrieve new beacon (beaconing modes) */
-		wiphy_err(wiphy, "%s: beacon changed\n", __func__);
+		brcms_err(core, "%s: beacon changed\n", __func__);
 
 	if (changed & BSS_CHANGED_BEACON_ENABLED) {
 		/* Beaconing should be enabled/disabled (beaconing modes) */
-		wiphy_err(wiphy, "%s: Beacon enabled: %s\n", __func__,
+		brcms_err(core, "%s: Beacon enabled: %s\n", __func__,
 			  info->enable_beacon ? "true" : "false");
 	}
 
 	if (changed & BSS_CHANGED_CQM) {
 		/* Connection quality monitor config changed */
-		wiphy_err(wiphy, "%s: cqm change: threshold %d, hys %d "
+		brcms_err(core, "%s: cqm change: threshold %d, hys %d "
 			  " (implement)\n", __func__, info->cqm_rssi_thold,
 			  info->cqm_rssi_hyst);
 	}
 
 	if (changed & BSS_CHANGED_IBSS) {
 		/* IBSS join status changed */
-		wiphy_err(wiphy, "%s: IBSS joined: %s (implement)\n", __func__,
-			  info->ibss_joined ? "true" : "false");
+		brcms_err(core, "%s: IBSS joined: %s (implement)\n",
+			  __func__, info->ibss_joined ? "true" : "false");
 	}
 
 	if (changed & BSS_CHANGED_ARP_FILTER) {
 		/* Hardware ARP filter address list or state changed */
-		wiphy_err(wiphy, "%s: arp filtering: enabled %s, count %d"
+		brcms_err(core, "%s: arp filtering: enabled %s, count %d"
 			  " (implement)\n", __func__, info->arp_filter_enabled ?
 			  "true" : "false", info->arp_addr_cnt);
 	}
@@ -541,8 +548,8 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
 		 * QoS for this association was enabled/disabled.
 		 * Note that it is only ever disabled for station mode.
 		 */
-		wiphy_err(wiphy, "%s: qos enabled: %s (implement)\n", __func__,
-			  info->qos ? "true" : "false");
+		brcms_err(core, "%s: qos enabled: %s (implement)\n",
+			  __func__, info->qos ? "true" : "false");
 	}
 	return;
 }
@@ -553,25 +560,25 @@ brcms_ops_configure_filter(struct ieee80211_hw *hw,
 			unsigned int *total_flags, u64 multicast)
 {
 	struct brcms_info *wl = hw->priv;
-	struct wiphy *wiphy = hw->wiphy;
+	struct bcma_device *core = wl->wlc->hw->d11core;
 
 	changed_flags &= MAC_FILTERS;
 	*total_flags &= MAC_FILTERS;
 
 	if (changed_flags & FIF_PROMISC_IN_BSS)
-		wiphy_dbg(wiphy, "FIF_PROMISC_IN_BSS\n");
+		brcms_dbg_info(core, "FIF_PROMISC_IN_BSS\n");
 	if (changed_flags & FIF_ALLMULTI)
-		wiphy_dbg(wiphy, "FIF_ALLMULTI\n");
+		brcms_dbg_info(core, "FIF_ALLMULTI\n");
 	if (changed_flags & FIF_FCSFAIL)
-		wiphy_dbg(wiphy, "FIF_FCSFAIL\n");
+		brcms_dbg_info(core, "FIF_FCSFAIL\n");
 	if (changed_flags & FIF_CONTROL)
-		wiphy_dbg(wiphy, "FIF_CONTROL\n");
+		brcms_dbg_info(core, "FIF_CONTROL\n");
 	if (changed_flags & FIF_OTHER_BSS)
-		wiphy_dbg(wiphy, "FIF_OTHER_BSS\n");
+		brcms_dbg_info(core, "FIF_OTHER_BSS\n");
 	if (changed_flags & FIF_PSPOLL)
-		wiphy_dbg(wiphy, "FIF_PSPOLL\n");
+		brcms_dbg_info(core, "FIF_PSPOLL\n");
 	if (changed_flags & FIF_BCN_PRBRESP_PROMISC)
-		wiphy_dbg(wiphy, "FIF_BCN_PRBRESP_PROMISC\n");
+		brcms_dbg_info(core, "FIF_BCN_PRBRESP_PROMISC\n");
 
 	spin_lock_bh(&wl->lock);
 	brcms_c_mac_promisc(wl->wlc, *total_flags);
@@ -653,8 +660,8 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
 		status = brcms_c_aggregatable(wl->wlc, tid);
 		spin_unlock_bh(&wl->lock);
 		if (!status) {
-			wiphy_err(wl->wiphy, "START: tid %d is not agg\'able\n",
-				  tid);
+			brcms_err(wl->wlc->hw->d11core,
+				  "START: tid %d is not agg\'able\n", tid);
 			return -EINVAL;
 		}
 		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
@@ -681,8 +688,8 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
 		/* Power save wakeup */
 		break;
 	default:
-		wiphy_err(wl->wiphy, "%s: Invalid command, ignoring\n",
-			  __func__);
+		brcms_err(wl->wlc->hw->d11core,
+			  "%s: Invalid command, ignoring\n", __func__);
 	}
 
 	return 0;
@@ -1144,14 +1151,13 @@ static int brcms_suspend(struct bcma_device *pdev)
 	wl->pub->hw_up = false;
 	spin_unlock_bh(&wl->lock);
 
-	pr_debug("brcms_suspend ok\n");
+	brcms_dbg_info(wl->wlc->hw->d11core, "brcms_suspend ok\n");
 
 	return 0;
 }
 
 static int brcms_resume(struct bcma_device *pdev)
 {
-	pr_debug("brcms_resume ok\n");
 	return 0;
 }
 
@@ -1184,10 +1190,6 @@ static DECLARE_WORK(brcms_driver_work, brcms_driver_init);
 
 static int __init brcms_module_init(void)
 {
-#ifdef DEBUG
-	if (msglevel != 0xdeadbeef)
-		brcm_msg_level = msglevel;
-#endif
 	if (!schedule_work(&brcms_driver_work))
 		return -EBUSY;
 
@@ -1216,7 +1218,7 @@ module_exit(brcms_module_exit);
 void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
 			 bool state, int prio)
 {
-	wiphy_err(wl->wiphy, "Shouldn't be here %s\n", __func__);
+	brcms_err(wl->wlc->hw->d11core, "Shouldn't be here %s\n", __func__);
 }
 
 /*
@@ -1224,7 +1226,8 @@ void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
  */
 void brcms_init(struct brcms_info *wl)
 {
-	BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit);
+	brcms_dbg_info(wl->wlc->hw->d11core, "Initializing wl%d\n",
+		       wl->pub->unit);
 	brcms_reset(wl);
 	brcms_c_init(wl->wlc, wl->mute_tx);
 }
@@ -1234,7 +1237,7 @@ void brcms_init(struct brcms_info *wl)
  */
 uint brcms_reset(struct brcms_info *wl)
 {
-	BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit);
+	brcms_dbg_info(wl->wlc->hw->d11core, "Resetting wl%d\n", wl->pub->unit);
 	brcms_c_reset(wl->wlc);
 
 	/* dpc will not be rescheduled */
@@ -1248,7 +1251,7 @@ uint brcms_reset(struct brcms_info *wl)
 
 void brcms_fatal_error(struct brcms_info *wl)
 {
-	wiphy_err(wl->wlc->wiphy, "wl%d: fatal error, reinitializing\n",
+	brcms_err(wl->wlc->hw->d11core, "wl%d: fatal error, reinitializing\n",
 		  wl->wlc->pub->unit);
 	brcms_reset(wl);
 	ieee80211_restart_hw(wl->pub->ieee_hw);
@@ -1396,8 +1399,9 @@ void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic)
 
 #ifdef DEBUG
 	if (t->set)
-		wiphy_err(hw->wiphy, "%s: Already set. Name: %s, per %d\n",
-			  __func__, t->name, periodic);
+		brcms_dbg_info(t->wl->wlc->hw->d11core,
+			       "%s: Already set. Name: %s, per %d\n",
+			       __func__, t->name, periodic);
 #endif
 	t->ms = ms;
 	t->periodic = (bool) periodic;
@@ -1486,8 +1490,8 @@ int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx)
 			}
 		}
 	}
-	wiphy_err(wl->wiphy, "ERROR: ucode buf tag:%d can not be found!\n",
-		  idx);
+	brcms_err(wl->wlc->hw->d11core,
+		  "ERROR: ucode buf tag:%d can not be found!\n", idx);
 	*pbuf = NULL;
 fail:
 	return -ENODATA;
@@ -1510,7 +1514,7 @@ int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx)
 				pdata = wl->fw.fw_bin[i]->data +
 					le32_to_cpu(hdr->offset);
 				if (le32_to_cpu(hdr->len) != 4) {
-					wiphy_err(wl->wiphy,
+					brcms_err(wl->wlc->hw->d11core,
 						  "ERROR: fw hdr len\n");
 					return -ENOMSG;
 				}
@@ -1519,7 +1523,8 @@ int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx)
 			}
 		}
 	}
-	wiphy_err(wl->wiphy, "ERROR: ucode tag:%d can not be found!\n", idx);
+	brcms_err(wl->wlc->hw->d11core,
+		  "ERROR: ucode tag:%d can not be found!\n", idx);
 	return -ENOMSG;
 }
 
@@ -1560,8 +1565,8 @@ int brcms_check_firmwares(struct brcms_info *wl)
 				sizeof(struct firmware_hdr));
 			rc = -EBADF;
 		} else if (fw->size < MIN_FW_SIZE || fw->size > MAX_FW_SIZE) {
-			wiphy_err(wl->wiphy, "%s: out of bounds fw file size "
-				  "%zu\n", __func__, fw->size);
+			wiphy_err(wl->wiphy, "%s: out of bounds fw file size %zu\n",
+				  __func__, fw->size);
 			rc = -EBADF;
 		} else {
 			/* check if ucode section overruns firmware image */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 75086b3..2a44593 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -34,12 +34,9 @@
 #include "ucode_loader.h"
 #include "main.h"
 #include "soc.h"
-
-/*
- * Indication for txflowcontrol that all priority bits in
- * TXQ_STOP_FOR_PRIOFC_MASK are to be considered.
- */
-#define ALLPRIO				-1
+#include "dma.h"
+#include "debug.h"
+#include "brcms_trace_events.h"
 
 /* watchdog timer, in unit of ms */
 #define TIMER_INTERVAL_WATCHDOG		1000
@@ -126,21 +123,6 @@
 
 #define BRCMS_TEMPSENSE_PERIOD		10	/* 10 second timeout */
 
-/* precedences numbers for wlc queues. These are twice as may levels as
- * 802.1D priorities.
- * Odd numbers are used for HI priority traffic at same precedence levels
- * These constants are used ONLY by wlc_prio2prec_map.  Do not use them
- * elsewhere.
- */
-#define _BRCMS_PREC_NONE		0	/* None = - */
-#define _BRCMS_PREC_BK			2	/* BK - Background */
-#define _BRCMS_PREC_BE			4	/* BE - Best-effort */
-#define _BRCMS_PREC_EE			6	/* EE - Excellent-effort */
-#define _BRCMS_PREC_CL			8	/* CL - Controlled Load */
-#define _BRCMS_PREC_VI			10	/* Vi - Video */
-#define _BRCMS_PREC_VO			12	/* Vo - Voice */
-#define _BRCMS_PREC_NC			14	/* NC - Network Control */
-
 /* synthpu_dly times in us */
 #define SYNTHPU_DLY_APHY_US		3700
 #define SYNTHPU_DLY_BPHY_US		1050
@@ -237,17 +219,17 @@
 
 #define MAX_DMA_SEGS			4
 
-/* Max # of entries in Tx FIFO based on 4kb page size */
-#define NTXD				256
+/* # of entries in Tx FIFO */
+#define NTXD				64
 /* Max # of entries in Rx FIFO based on 4kb page size */
 #define NRXD				256
 
+/* Amount of headroom to leave in Tx FIFO */
+#define TX_HEADROOM			4
+
 /* try to keep this # rbufs posted to the chip */
 #define NRXBUFPOST			32
 
-/* data msg txq hiwat mark */
-#define BRCMS_DATAHIWAT			50
-
 /* max # frames to process in brcms_c_recv() */
 #define RXBND				8
 /* max # tx status to process in wlc_txstatus() */
@@ -283,24 +265,8 @@ struct edcf_acparam {
 	u16 TXOP;
 } __packed;
 
-const u8 prio2fifo[NUMPRIO] = {
-	TX_AC_BE_FIFO,		/* 0    BE      AC_BE   Best Effort */
-	TX_AC_BK_FIFO,		/* 1    BK      AC_BK   Background */
-	TX_AC_BK_FIFO,		/* 2    --      AC_BK   Background */
-	TX_AC_BE_FIFO,		/* 3    EE      AC_BE   Best Effort */
-	TX_AC_VI_FIFO,		/* 4    CL      AC_VI   Video */
-	TX_AC_VI_FIFO,		/* 5    VI      AC_VI   Video */
-	TX_AC_VO_FIFO,		/* 6    VO      AC_VO   Voice */
-	TX_AC_VO_FIFO		/* 7    NC      AC_VO   Voice */
-};
-
 /* debug/trace */
-uint brcm_msg_level =
-#if defined(DEBUG)
-	LOG_ERROR_VAL;
-#else
-	0;
-#endif				/* DEBUG */
+uint brcm_msg_level;
 
 /* TX FIFO number to WME/802.1E Access Category */
 static const u8 wme_fifo2ac[] = {
@@ -320,18 +286,6 @@ static const u8 wme_ac2fifo[] = {
 	TX_AC_BK_FIFO
 };
 
-/* 802.1D Priority to precedence queue mapping */
-const u8 wlc_prio2prec_map[] = {
-	_BRCMS_PREC_BE,		/* 0 BE - Best-effort */
-	_BRCMS_PREC_BK,		/* 1 BK - Background */
-	_BRCMS_PREC_NONE,		/* 2 None = - */
-	_BRCMS_PREC_EE,		/* 3 EE - Excellent-effort */
-	_BRCMS_PREC_CL,		/* 4 CL - Controlled Load */
-	_BRCMS_PREC_VI,		/* 5 Vi - Video */
-	_BRCMS_PREC_VO,		/* 6 Vo - Voice */
-	_BRCMS_PREC_NC,		/* 7 NC - Network Control */
-};
-
 static const u16 xmtfifo_sz[][NFIFO] = {
 	/* corerev 17: 5120, 49152, 49152, 5376, 4352, 1280 */
 	{20, 192, 192, 21, 17, 5},
@@ -371,6 +325,36 @@ static const char fifo_names[6][0];
 static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL);
 #endif
 
+/* Mapping of ieee80211 AC numbers to tx fifos */
+static const u8 ac_to_fifo_mapping[IEEE80211_NUM_ACS] = {
+	[IEEE80211_AC_VO]	= TX_AC_VO_FIFO,
+	[IEEE80211_AC_VI]	= TX_AC_VI_FIFO,
+	[IEEE80211_AC_BE]	= TX_AC_BE_FIFO,
+	[IEEE80211_AC_BK]	= TX_AC_BK_FIFO,
+};
+
+/* Mapping of tx fifos to ieee80211 AC numbers */
+static const u8 fifo_to_ac_mapping[IEEE80211_NUM_ACS] = {
+	[TX_AC_BK_FIFO]	= IEEE80211_AC_BK,
+	[TX_AC_BE_FIFO]	= IEEE80211_AC_BE,
+	[TX_AC_VI_FIFO]	= IEEE80211_AC_VI,
+	[TX_AC_VO_FIFO]	= IEEE80211_AC_VO,
+};
+
+static u8 brcms_ac_to_fifo(u8 ac)
+{
+	if (ac >= ARRAY_SIZE(ac_to_fifo_mapping))
+		return TX_AC_BE_FIFO;
+	return ac_to_fifo_mapping[ac];
+}
+
+static u8 brcms_fifo_to_ac(u8 fifo)
+{
+	if (fifo >= ARRAY_SIZE(fifo_to_ac_mapping))
+		return IEEE80211_AC_BE;
+	return fifo_to_ac_mapping[fifo];
+}
+
 /* Find basic rate for a given rate */
 static u8 brcms_basic_rate(struct brcms_c_info *wlc, u32 rspec)
 {
@@ -415,10 +399,15 @@ static bool brcms_deviceremoved(struct brcms_c_info *wlc)
 }
 
 /* sum the individual fifo tx pending packet counts */
-static s16 brcms_txpktpendtot(struct brcms_c_info *wlc)
+static int brcms_txpktpendtot(struct brcms_c_info *wlc)
 {
-	return wlc->core->txpktpend[0] + wlc->core->txpktpend[1] +
-	       wlc->core->txpktpend[2] + wlc->core->txpktpend[3];
+	int i;
+	int pending = 0;
+
+	for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++)
+		if (wlc->hw->di[i])
+			pending += dma_txpending(wlc->hw->di[i]);
+	return pending;
 }
 
 static bool brcms_is_mband_unlocked(struct brcms_c_info *wlc)
@@ -626,14 +615,11 @@ static uint brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec,
 	uint rate = rspec2rate(ratespec);
 
 	if (rate == 0) {
-		wiphy_err(wlc->wiphy, "wl%d: WAR: using rate of 1 mbps\n",
+		brcms_err(wlc->hw->d11core, "wl%d: WAR: using rate of 1 mbps\n",
 			  wlc->pub->unit);
 		rate = BRCM_RATE_1M;
 	}
 
-	BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, len%d\n",
-		 wlc->pub->unit, ratespec, preamble_type, mac_len);
-
 	if (is_mcs_rate(ratespec)) {
 		uint mcs = ratespec & RSPEC_RATE_MASK;
 		int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec);
@@ -696,7 +682,7 @@ static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
 	u16 size;
 	u32 value;
 
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+	brcms_dbg_info(wlc_hw->d11core, "wl%d\n", wlc_hw->unit);
 
 	for (i = 0; inits[i].addr != cpu_to_le16(0xffff); i++) {
 		size = le16_to_cpu(inits[i].size);
@@ -725,7 +711,6 @@ static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs)
 
 static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw)
 {
-	struct wiphy *wiphy = wlc_hw->wlc->wiphy;
 	struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode;
 
 	/* init microcode host flags */
@@ -736,8 +721,9 @@ static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw)
 		if (BRCMS_ISNPHY(wlc_hw->band))
 			brcms_c_write_inits(wlc_hw, ucode->d11n0bsinitvals16);
 		else
-			wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
-				  " %d\n", __func__, wlc_hw->unit,
+			brcms_err(wlc_hw->d11core,
+				  "%s: wl%d: unsupported phy in corerev %d\n",
+				  __func__, wlc_hw->unit,
 				  wlc_hw->corerev);
 	} else {
 		if (D11REV_IS(wlc_hw->corerev, 24)) {
@@ -745,12 +731,14 @@ static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw)
 				brcms_c_write_inits(wlc_hw,
 						    ucode->d11lcn0bsinitvals24);
 			else
-				wiphy_err(wiphy, "%s: wl%d: unsupported phy in"
-					  " core rev %d\n", __func__,
-					  wlc_hw->unit, wlc_hw->corerev);
+				brcms_err(wlc_hw->d11core,
+					  "%s: wl%d: unsupported phy in core rev %d\n",
+					  __func__, wlc_hw->unit,
+					  wlc_hw->corerev);
 		} else {
-			wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
-				__func__, wlc_hw->unit, wlc_hw->corerev);
+			brcms_err(wlc_hw->d11core,
+				  "%s: wl%d: unsupported corerev %d\n",
+				  __func__, wlc_hw->unit, wlc_hw->corerev);
 		}
 	}
 }
@@ -765,7 +753,7 @@ static void brcms_b_core_ioctl(struct brcms_hardware *wlc_hw, u32 m, u32 v)
 
 static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk)
 {
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk);
+	brcms_dbg_info(wlc_hw->d11core, "wl%d: clk %d\n", wlc_hw->unit, clk);
 
 	wlc_hw->phyclk = clk;
 
@@ -790,8 +778,8 @@ static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk)
 /* low-level band switch utility routine */
 static void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit)
 {
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
-		bandunit);
+	brcms_dbg_mac80211(wlc_hw->d11core, "wl%d: bandunit %d\n", wlc_hw->unit,
+			   bandunit);
 
 	wlc_hw->band = wlc_hw->bandstate[bandunit];
 
@@ -819,7 +807,7 @@ static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit)
 	u32 macintmask;
 	u32 macctrl;
 
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
+	brcms_dbg_mac80211(wlc_hw->d11core, "wl%d\n", wlc_hw->unit);
 	macctrl = bcma_read32(wlc_hw->d11core,
 			      D11REGOFFS(maccontrol));
 	WARN_ON((macctrl & MCTL_EN_MAC) != 0);
@@ -841,9 +829,10 @@ static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit)
 static bool
 brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
 {
-	struct sk_buff *p;
-	uint queue;
-	struct d11txh *txh;
+	struct sk_buff *p = NULL;
+	uint queue = NFIFO;
+	struct dma_pub *dma = NULL;
+	struct d11txh *txh = NULL;
 	struct scb *scb = NULL;
 	bool free_pdu;
 	int tx_rts, tx_frame_count, tx_rts_count;
@@ -854,6 +843,11 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
 	struct ieee80211_tx_info *tx_info;
 	struct ieee80211_tx_rate *txrate;
 	int i;
+	bool fatal = true;
+
+	trace_brcms_txstatus(&wlc->hw->d11core->dev, txs->framelen,
+			     txs->frameid, txs->status, txs->lasttxtime,
+			     txs->sequence, txs->phyerr, txs->ackphyrxsh);
 
 	/* discard intermediate indications for ucode with one legitimate case:
 	 *   e.g. if "useRTS" is set. ucode did a successful rts/cts exchange,
@@ -862,34 +856,36 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
 	 */
 	if (!(txs->status & TX_STATUS_AMPDU)
 	    && (txs->status & TX_STATUS_INTERMEDIATE)) {
-		BCMMSG(wlc->wiphy, "INTERMEDIATE but not AMPDU\n");
-		return false;
+		brcms_dbg_tx(wlc->hw->d11core, "INTERMEDIATE but not AMPDU\n");
+		fatal = false;
+		goto out;
 	}
 
 	queue = txs->frameid & TXFID_QUEUE_MASK;
 	if (queue >= NFIFO) {
-		p = NULL;
-		goto fatal;
+		brcms_err(wlc->hw->d11core, "queue %u >= NFIFO\n", queue);
+		goto out;
 	}
 
+	dma = wlc->hw->di[queue];
+
 	p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
-	if (p == NULL)
-		goto fatal;
+	if (p == NULL) {
+		brcms_err(wlc->hw->d11core, "dma_getnexttxp returned null!\n");
+		goto out;
+	}
 
 	txh = (struct d11txh *) (p->data);
 	mcl = le16_to_cpu(txh->MacTxControlLow);
 
-	if (txs->phyerr) {
-		if (brcm_msg_level & LOG_ERROR_VAL) {
-			wiphy_err(wlc->wiphy, "phyerr 0x%x, rate 0x%x\n",
-				  txs->phyerr, txh->MainRates);
-			brcms_c_print_txdesc(txh);
-		}
-		brcms_c_print_txstatus(txs);
-	}
+	if (txs->phyerr)
+		brcms_err(wlc->hw->d11core, "phyerr 0x%x, rate 0x%x\n",
+			  txs->phyerr, txh->MainRates);
 
-	if (txs->frameid != le16_to_cpu(txh->TxFrameID))
-		goto fatal;
+	if (txs->frameid != le16_to_cpu(txh->TxFrameID)) {
+		brcms_err(wlc->hw->d11core, "frameid != txh->TxFrameID\n");
+		goto out;
+	}
 	tx_info = IEEE80211_SKB_CB(p);
 	h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
 
@@ -898,14 +894,24 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
 
 	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
 		brcms_c_ampdu_dotxstatus(wlc->ampdu, scb, p, txs);
-		return false;
+		fatal = false;
+		goto out;
 	}
 
+	/*
+	 * brcms_c_ampdu_dotxstatus() will trace tx descriptors for AMPDU
+	 * frames; this traces them for the rest.
+	 */
+	trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, sizeof(*txh));
+
 	supr_status = txs->status & TX_STATUS_SUPR_MASK;
-	if (supr_status == TX_STATUS_SUPR_BADCH)
-		BCMMSG(wlc->wiphy,
-		       "%s: Pkt tx suppressed, possibly channel %d\n",
-		       __func__, CHSPEC_CHANNEL(wlc->default_bss->chanspec));
+	if (supr_status == TX_STATUS_SUPR_BADCH) {
+		unsigned xfts = le16_to_cpu(txh->XtraFrameTypes);
+		brcms_dbg_tx(wlc->hw->d11core,
+			     "Pkt tx suppressed, dest chan %u, current %d\n",
+			     (xfts >> XFTS_CHANNEL_SHIFT) & 0xff,
+			     CHSPEC_CHANNEL(wlc->default_bss->chanspec));
+	}
 
 	tx_rts = le16_to_cpu(txh->MacTxControlLow) & TXC_SENDRTS;
 	tx_frame_count =
@@ -916,7 +922,7 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
 	lastframe = !ieee80211_has_morefrags(h->frame_control);
 
 	if (!lastframe) {
-		wiphy_err(wlc->wiphy, "Not last frame!\n");
+		brcms_err(wlc->hw->d11core, "Not last frame!\n");
 	} else {
 		/*
 		 * Set information to be consumed by Minstrel ht.
@@ -982,26 +988,37 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
 	totlen = p->len;
 	free_pdu = true;
 
-	brcms_c_txfifo_complete(wlc, queue, 1);
-
 	if (lastframe) {
 		/* remove PLCP & Broadcom tx descriptor header */
 		skb_pull(p, D11_PHY_HDR_LEN);
 		skb_pull(p, D11_TXH_LEN);
 		ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, p);
 	} else {
-		wiphy_err(wlc->wiphy, "%s: Not last frame => not calling "
-			  "tx_status\n", __func__);
+		brcms_err(wlc->hw->d11core,
+			  "%s: Not last frame => not calling tx_status\n",
+			  __func__);
 	}
 
-	return false;
+	fatal = false;
 
- fatal:
-	if (p)
-		brcmu_pkt_buf_free_skb(p);
+ out:
+	if (fatal) {
+		if (txh)
+			trace_brcms_txdesc(&wlc->hw->d11core->dev, txh,
+					   sizeof(*txh));
+		if (p)
+			brcmu_pkt_buf_free_skb(p);
+	}
 
-	return true;
+	if (dma && queue < NFIFO) {
+		u16 ac_queue = brcms_fifo_to_ac(queue);
+		if (dma->txavail > TX_HEADROOM && queue < TX_BCMC_FIFO &&
+		    ieee80211_queue_stopped(wlc->pub->ieee_hw, ac_queue))
+			ieee80211_wake_queue(wlc->pub->ieee_hw, ac_queue);
+		dma_kick_tx(dma);
+	}
 
+	return fatal;
 }
 
 /* process tx completion events in BMAC
@@ -1011,7 +1028,6 @@ static bool
 brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
 {
 	bool morepending = false;
-	struct brcms_c_info *wlc = wlc_hw->wlc;
 	struct bcma_device *core;
 	struct tx_status txstatus, *txs;
 	u32 s1, s2;
@@ -1022,8 +1038,6 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
 	 */
 	uint max_tx_num = bound ? TXSBND : -1;
 
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
 	txs = &txstatus;
 	core = wlc_hw->d11core;
 	*fatal = false;
@@ -1032,8 +1046,8 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
 	       && (s1 & TXS_V)) {
 
 		if (s1 == 0xffffffff) {
-			wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n",
-				wlc_hw->unit, __func__);
+			brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
+				  __func__);
 			return morepending;
 		}
 		s2 = bcma_read32(core, D11REGOFFS(frmtxstatus2));
@@ -1058,9 +1072,6 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
 	if (n >= max_tx_num)
 		morepending = true;
 
-	if (!pktq_empty(&wlc->pkt_queue->q))
-		brcms_c_send_q(wlc);
-
 	return morepending;
 }
 
@@ -1112,7 +1123,6 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
 	u16 pio_mhf2 = 0;
 	struct brcms_hardware *wlc_hw = wlc->hw;
 	uint unit = wlc_hw->unit;
-	struct wiphy *wiphy = wlc->wiphy;
 
 	/* name and offsets for dma_attach */
 	snprintf(name, sizeof(name), "wl%d", unit);
@@ -1125,12 +1135,12 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
 		 * TX: TX_AC_BK_FIFO (TX AC Background data packets)
 		 * RX: RX_FIFO (RX data packets)
 		 */
-		wlc_hw->di[0] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core,
+		wlc_hw->di[0] = dma_attach(name, wlc,
 					   (wme ? dmareg(DMA_TX, 0) : 0),
 					   dmareg(DMA_RX, 0),
 					   (wme ? NTXD : 0), NRXD,
 					   RXBUFSZ, -1, NRXBUFPOST,
-					   BRCMS_HWRXOFF, &brcm_msg_level);
+					   BRCMS_HWRXOFF);
 		dma_attach_err |= (NULL == wlc_hw->di[0]);
 
 		/*
@@ -1139,10 +1149,9 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
 		 *   (legacy) TX_DATA_FIFO (TX data packets)
 		 * RX: UNUSED
 		 */
-		wlc_hw->di[1] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core,
+		wlc_hw->di[1] = dma_attach(name, wlc,
 					   dmareg(DMA_TX, 1), 0,
-					   NTXD, 0, 0, -1, 0, 0,
-					   &brcm_msg_level);
+					   NTXD, 0, 0, -1, 0, 0);
 		dma_attach_err |= (NULL == wlc_hw->di[1]);
 
 		/*
@@ -1150,26 +1159,26 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
 		 * TX: TX_AC_VI_FIFO (TX AC Video data packets)
 		 * RX: UNUSED
 		 */
-		wlc_hw->di[2] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core,
+		wlc_hw->di[2] = dma_attach(name, wlc,
 					   dmareg(DMA_TX, 2), 0,
-					   NTXD, 0, 0, -1, 0, 0,
-					   &brcm_msg_level);
+					   NTXD, 0, 0, -1, 0, 0);
 		dma_attach_err |= (NULL == wlc_hw->di[2]);
 		/*
 		 * FIFO 3
 		 * TX: TX_AC_VO_FIFO (TX AC Voice data packets)
 		 *   (legacy) TX_CTL_FIFO (TX control & mgmt packets)
 		 */
-		wlc_hw->di[3] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core,
+		wlc_hw->di[3] = dma_attach(name, wlc,
 					   dmareg(DMA_TX, 3),
 					   0, NTXD, 0, 0, -1,
-					   0, 0, &brcm_msg_level);
+					   0, 0);
 		dma_attach_err |= (NULL == wlc_hw->di[3]);
 /* Cleaner to leave this as if with AP defined */
 
 		if (dma_attach_err) {
-			wiphy_err(wiphy, "wl%d: wlc_attach: dma_attach failed"
-				  "\n", unit);
+			brcms_err(wlc_hw->d11core,
+				  "wl%d: wlc_attach: dma_attach failed\n",
+				  unit);
 			return false;
 		}
 
@@ -1503,8 +1512,7 @@ brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset,
 	u16 mac_m;
 	u16 mac_h;
 
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n",
-		 wlc_hw->unit);
+	brcms_dbg_rx(core, "wl%d: brcms_b_set_addrmatch\n", wlc_hw->unit);
 
 	mac_l = addr[0] | (addr[1] << 8);
 	mac_m = addr[2] | (addr[3] << 8);
@@ -1527,7 +1535,7 @@ brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len,
 	__le32 word_le;
 	__be32 word_be;
 	bool be_bit;
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+	brcms_dbg_info(core, "wl%d\n", wlc_hw->unit);
 
 	bcma_write32(core, D11REGOFFS(tplatewrptr), offset);
 
@@ -1700,8 +1708,8 @@ static void brcms_b_bsinit(struct brcms_c_info *wlc, u16 chanspec)
 {
 	struct brcms_hardware *wlc_hw = wlc->hw;
 
-	BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
-		wlc_hw->band->bandunit);
+	brcms_dbg_mac80211(wlc_hw->d11core, "wl%d: bandunit %d\n", wlc_hw->unit,
+			   wlc_hw->band->bandunit);
 
 	brcms_c_ucode_bsinit(wlc_hw);
 
@@ -1736,8 +1744,6 @@ static void brcms_b_bsinit(struct brcms_c_info *wlc, u16 chanspec)
 /* Perform a soft reset of the PHY PLL */
 void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw)
 {
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
 	ai_cc_reg(wlc_hw->sih, offsetof(struct chipcregs, chipcontrol_addr),
 		  ~0, 0);
 	udelay(1);
@@ -1782,7 +1788,7 @@ void brcms_b_phy_reset(struct brcms_hardware *wlc_hw)
 	u32 phy_bw_clkbits;
 	bool phy_in_reset = false;
 
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+	brcms_dbg_info(wlc_hw->d11core, "wl%d: reset phy\n", wlc_hw->unit);
 
 	if (pih == NULL)
 		return;
@@ -1916,7 +1922,7 @@ static void brcms_c_get_macaddr(struct brcms_hardware *wlc_hw, u8 etheraddr[ETH_
 /* power both the pll and external oscillator on/off */
 static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want)
 {
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: want %d\n", wlc_hw->unit, want);
+	brcms_dbg_info(wlc_hw->d11core, "wl%d: want %d\n", wlc_hw->unit, want);
 
 	/*
 	 * dont power down if plldown is false or
@@ -2005,7 +2011,7 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
 	if (flags == BRCMS_USE_COREFLAGS)
 		flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0);
 
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+	brcms_dbg_info(wlc_hw->d11core, "wl%d: core reset\n", wlc_hw->unit);
 
 	/* request FAST clock if not on  */
 	fastclk = wlc_hw->forcefastclk;
@@ -2016,13 +2022,13 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
 	if (bcma_core_is_enabled(wlc_hw->d11core)) {
 		for (i = 0; i < NFIFO; i++)
 			if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i])))
-				wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: "
+				brcms_err(wlc_hw->d11core, "wl%d: %s: "
 					  "dma_txreset[%d]: cannot stop dma\n",
 					   wlc_hw->unit, __func__, i);
 
 		if ((wlc_hw->di[RX_FIFO])
 		    && (!wlc_dma_rxreset(wlc_hw, RX_FIFO)))
-			wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: dma_rxreset"
+			brcms_err(wlc_hw->d11core, "wl%d: %s: dma_rxreset"
 				  "[%d]: cannot stop dma\n",
 				  wlc_hw->unit, __func__, RX_FIFO);
 	}
@@ -2235,7 +2241,7 @@ static void brcms_ucode_write(struct brcms_hardware *wlc_hw,
 	uint i;
 	uint count;
 
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+	brcms_dbg_info(wlc_hw->d11core, "wl%d\n", wlc_hw->unit);
 
 	count = (nbytes / sizeof(u32));
 
@@ -2263,8 +2269,8 @@ static void brcms_ucode_download(struct brcms_hardware *wlc_hw)
 					  ucode->bcm43xx_16_mimosz);
 			wlc_hw->ucode_loaded = true;
 		} else
-			wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
-				  "corerev %d\n",
+			brcms_err(wlc_hw->d11core,
+				  "%s: wl%d: unsupported phy in corerev %d\n",
 				  __func__, wlc_hw->unit, wlc_hw->corerev);
 	} else if (D11REV_IS(wlc_hw->corerev, 24)) {
 		if (BRCMS_ISLCNPHY(wlc_hw->band)) {
@@ -2272,8 +2278,8 @@ static void brcms_ucode_download(struct brcms_hardware *wlc_hw)
 					  ucode->bcm43xx_24_lcnsz);
 			wlc_hw->ucode_loaded = true;
 		} else {
-			wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
-				  "corerev %d\n",
+			brcms_err(wlc_hw->d11core,
+				  "%s: wl%d: unsupported phy in corerev %d\n",
 				  __func__, wlc_hw->unit, wlc_hw->corerev);
 		}
 	}
@@ -2310,7 +2316,6 @@ static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
 	uint unit;
 	uint intstatus, idx;
 	struct bcma_device *core = wlc_hw->d11core;
-	struct wiphy *wiphy = wlc_hw->wlc->wiphy;
 
 	unit = wlc_hw->unit;
 
@@ -2323,39 +2328,39 @@ static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
 		if (!intstatus)
 			continue;
 
-		BCMMSG(wlc_hw->wlc->wiphy, "wl%d: intstatus%d 0x%x\n",
-			unit, idx, intstatus);
+		brcms_dbg_int(core, "wl%d: intstatus%d 0x%x\n",
+			      unit, idx, intstatus);
 
 		if (intstatus & I_RO) {
-			wiphy_err(wiphy, "wl%d: fifo %d: receive fifo "
+			brcms_err(core, "wl%d: fifo %d: receive fifo "
 				  "overflow\n", unit, idx);
 			fatal = true;
 		}
 
 		if (intstatus & I_PC) {
-			wiphy_err(wiphy, "wl%d: fifo %d: descriptor error\n",
-				 unit, idx);
+			brcms_err(core, "wl%d: fifo %d: descriptor error\n",
+				  unit, idx);
 			fatal = true;
 		}
 
 		if (intstatus & I_PD) {
-			wiphy_err(wiphy, "wl%d: fifo %d: data error\n", unit,
+			brcms_err(core, "wl%d: fifo %d: data error\n", unit,
 				  idx);
 			fatal = true;
 		}
 
 		if (intstatus & I_DE) {
-			wiphy_err(wiphy, "wl%d: fifo %d: descriptor protocol "
+			brcms_err(core, "wl%d: fifo %d: descriptor protocol "
 				  "error\n", unit, idx);
 			fatal = true;
 		}
 
 		if (intstatus & I_RU)
-			wiphy_err(wiphy, "wl%d: fifo %d: receive descriptor "
+			brcms_err(core, "wl%d: fifo %d: receive descriptor "
 				  "underflow\n", idx, unit);
 
 		if (intstatus & I_XU) {
-			wiphy_err(wiphy, "wl%d: fifo %d: transmit fifo "
+			brcms_err(core, "wl%d: fifo %d: transmit fifo "
 				  "underflow\n", idx, unit);
 			fatal = true;
 		}
@@ -2516,13 +2521,13 @@ static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr)
 {
 	struct brcms_hardware *wlc_hw = wlc->hw;
 	struct bcma_device *core = wlc_hw->d11core;
-	u32 macintstatus;
+	u32 macintstatus, mask;
 
 	/* macintstatus includes a DMA interrupt summary bit */
 	macintstatus = bcma_read32(core, D11REGOFFS(macintstatus));
+	mask = in_isr ? wlc->macintmask : wlc->defmacintmask;
 
-	BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit,
-		 macintstatus);
+	trace_brcms_macintstatus(&core->dev, in_isr, macintstatus, mask);
 
 	/* detect cardbus removed, in power down(suspend) and in reset */
 	if (brcms_deviceremoved(wlc))
@@ -2535,7 +2540,7 @@ static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr)
 		return 0;
 
 	/* defer unsolicited interrupts */
-	macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask);
+	macintstatus &= mask;
 
 	/* if not for us */
 	if (macintstatus == 0)
@@ -2605,8 +2610,8 @@ bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc)
 	macintstatus = wlc_intstatus(wlc, true);
 
 	if (macintstatus == 0xffffffff)
-		wiphy_err(wlc->wiphy, "DEVICEREMOVED detected in the ISR code"
-			  " path\n");
+		brcms_err(wlc_hw->d11core,
+			  "DEVICEREMOVED detected in the ISR code path\n");
 
 	/* it is not for us */
 	if (macintstatus == 0)
@@ -2626,10 +2631,9 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
 	struct brcms_hardware *wlc_hw = wlc->hw;
 	struct bcma_device *core = wlc_hw->d11core;
 	u32 mc, mi;
-	struct wiphy *wiphy = wlc->wiphy;
 
-	BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
-		wlc_hw->band->bandunit);
+	brcms_dbg_mac80211(core, "wl%d: bandunit %d\n", wlc_hw->unit,
+			   wlc_hw->band->bandunit);
 
 	/*
 	 * Track overlapping suspend requests
@@ -2644,7 +2648,7 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
 	mc = bcma_read32(core, D11REGOFFS(maccontrol));
 
 	if (mc == 0xffffffff) {
-		wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+		brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
 			  __func__);
 		brcms_down(wlc->wl);
 		return;
@@ -2655,7 +2659,7 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
 
 	mi = bcma_read32(core, D11REGOFFS(macintstatus));
 	if (mi == 0xffffffff) {
-		wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+		brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
 			  __func__);
 		brcms_down(wlc->wl);
 		return;
@@ -2668,10 +2672,10 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
 		 BRCMS_MAX_MAC_SUSPEND);
 
 	if (!(bcma_read32(core, D11REGOFFS(macintstatus)) & MI_MACSSPNDD)) {
-		wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS"
+		brcms_err(core, "wl%d: wlc_suspend_mac_and_wait: waited %d uS"
 			  " and MI_MACSSPNDD is still not on.\n",
 			  wlc_hw->unit, BRCMS_MAX_MAC_SUSPEND);
-		wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, "
+		brcms_err(core, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, "
 			  "psm_brc 0x%04x\n", wlc_hw->unit,
 			  bcma_read32(core, D11REGOFFS(psmdebug)),
 			  bcma_read32(core, D11REGOFFS(phydebug)),
@@ -2680,7 +2684,7 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
 
 	mc = bcma_read32(core, D11REGOFFS(maccontrol));
 	if (mc == 0xffffffff) {
-		wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+		brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
 			  __func__);
 		brcms_down(wlc->wl);
 		return;
@@ -2696,8 +2700,8 @@ void brcms_c_enable_mac(struct brcms_c_info *wlc)
 	struct bcma_device *core = wlc_hw->d11core;
 	u32 mc, mi;
 
-	BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
-		wlc->band->bandunit);
+	brcms_dbg_mac80211(core, "wl%d: bandunit %d\n", wlc_hw->unit,
+			   wlc->band->bandunit);
 
 	/*
 	 * Track overlapping suspend requests
@@ -2740,8 +2744,6 @@ static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw)
 	u32 w, val;
 	struct wiphy *wiphy = wlc_hw->wlc->wiphy;
 
-	BCMMSG(wiphy, "wl%d\n", wlc_hw->unit);
-
 	/* Validate dchip register access */
 
 	bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0);
@@ -2802,7 +2804,7 @@ void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
 	struct bcma_device *core = wlc_hw->d11core;
 	u32 tmp;
 
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+	brcms_dbg_info(core, "wl%d\n", wlc_hw->unit);
 
 	tmp = 0;
 
@@ -2818,8 +2820,8 @@ void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
 
 			tmp = bcma_read32(core, D11REGOFFS(clk_ctl_st));
 			if ((tmp & CCS_ERSRC_AVAIL_HT) != CCS_ERSRC_AVAIL_HT)
-				wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY"
-					  " PLL failed\n", __func__);
+				brcms_err(core, "%s: turn on PHY PLL failed\n",
+					  __func__);
 		} else {
 			bcma_set32(core, D11REGOFFS(clk_ctl_st),
 				   tmp | CCS_ERSRC_REQ_D11PLL |
@@ -2835,8 +2837,8 @@ void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
 			     (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
 			    !=
 			    (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
-				wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on "
-					  "PHY PLL failed\n", __func__);
+				brcms_err(core, "%s: turn on PHY PLL failed\n",
+					  __func__);
 		}
 	} else {
 		/*
@@ -2854,7 +2856,7 @@ static void brcms_c_coredisable(struct brcms_hardware *wlc_hw)
 {
 	bool dev_gone;
 
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+	brcms_dbg_info(wlc_hw->d11core, "wl%d: disable core\n", wlc_hw->unit);
 
 	dev_gone = brcms_deviceremoved(wlc_hw->wlc);
 
@@ -2884,12 +2886,14 @@ static void brcms_c_flushqueues(struct brcms_c_info *wlc)
 	uint i;
 
 	/* free any posted tx packets */
-	for (i = 0; i < NFIFO; i++)
+	for (i = 0; i < NFIFO; i++) {
 		if (wlc_hw->di[i]) {
 			dma_txreclaim(wlc_hw->di[i], DMA_RANGE_ALL);
-			wlc->core->txpktpend[i] = 0;
-			BCMMSG(wlc->wiphy, "pktpend fifo %d clrd\n", i);
+			if (i < TX_BCMC_FIFO)
+				ieee80211_wake_queue(wlc->pub->ieee_hw,
+						     brcms_fifo_to_ac(i));
 		}
+	}
 
 	/* free any posted rx packets */
 	dma_rxreclaim(wlc_hw->di[RX_FIFO]);
@@ -3109,7 +3113,7 @@ static void brcms_c_statsupd(struct brcms_c_info *wlc)
 	/* check for rx fifo 0 overflow */
 	delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl);
 	if (delta)
-		wiphy_err(wlc->wiphy, "wl%d: %u rx fifo 0 overflows!\n",
+		brcms_err(wlc->hw->d11core, "wl%d: %u rx fifo 0 overflows!\n",
 			  wlc->pub->unit, delta);
 
 	/* check for tx fifo underflows */
@@ -3118,8 +3122,9 @@ static void brcms_c_statsupd(struct brcms_c_info *wlc)
 		    (u16) (wlc->core->macstat_snapshot->txfunfl[i] -
 			      txfunfl[i]);
 		if (delta)
-			wiphy_err(wlc->wiphy, "wl%d: %u tx fifo %d underflows!"
-				  "\n", wlc->pub->unit, delta, i);
+			brcms_err(wlc->hw->d11core,
+				  "wl%d: %u tx fifo %d underflows!\n",
+				  wlc->pub->unit, delta, i);
 	}
 #endif				/* DEBUG */
 
@@ -3132,8 +3137,6 @@ static void brcms_c_statsupd(struct brcms_c_info *wlc)
 
 static void brcms_b_reset(struct brcms_hardware *wlc_hw)
 {
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
 	/* reset the core */
 	if (!brcms_deviceremoved(wlc_hw->wlc))
 		brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
@@ -3144,7 +3147,7 @@ static void brcms_b_reset(struct brcms_hardware *wlc_hw)
 
 void brcms_c_reset(struct brcms_c_info *wlc)
 {
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+	brcms_dbg_info(wlc->hw->d11core, "wl%d\n", wlc->pub->unit);
 
 	/* slurp up hw mac counters before core reset */
 	brcms_c_statsupd(wlc);
@@ -3189,10 +3192,9 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc)
 	bool fifosz_fixup = false;
 	int err = 0;
 	u16 buf[NFIFO];
-	struct wiphy *wiphy = wlc->wiphy;
 	struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode;
 
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
+	brcms_dbg_info(core, "wl%d: core init\n", wlc_hw->unit);
 
 	/* reset PSM */
 	brcms_b_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE));
@@ -3212,7 +3214,7 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc)
 	SPINWAIT(((bcma_read32(core, D11REGOFFS(macintstatus)) &
 		   MI_MACSSPNDD) == 0), 1000 * 1000);
 	if ((bcma_read32(core, D11REGOFFS(macintstatus)) & MI_MACSSPNDD) == 0)
-		wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-"
+		brcms_err(core, "wl%d: wlc_coreinit: ucode did not self-"
 			  "suspend!\n", wlc_hw->unit);
 
 	brcms_c_gpio_init(wlc);
@@ -3223,18 +3225,18 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc)
 		if (BRCMS_ISNPHY(wlc_hw->band))
 			brcms_c_write_inits(wlc_hw, ucode->d11n0initvals16);
 		else
-			wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
+			brcms_err(core, "%s: wl%d: unsupported phy in corerev"
 				  " %d\n", __func__, wlc_hw->unit,
 				  wlc_hw->corerev);
 	} else if (D11REV_IS(wlc_hw->corerev, 24)) {
 		if (BRCMS_ISLCNPHY(wlc_hw->band))
 			brcms_c_write_inits(wlc_hw, ucode->d11lcn0initvals24);
 		else
-			wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
+			brcms_err(core, "%s: wl%d: unsupported phy in corerev"
 				  " %d\n", __func__, wlc_hw->unit,
 				  wlc_hw->corerev);
 	} else {
-		wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
+		brcms_err(core, "%s: wl%d: unsupported corerev %d\n",
 			  __func__, wlc_hw->unit, wlc_hw->corerev);
 	}
 
@@ -3276,7 +3278,7 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc)
 		err = -1;
 	}
 	if (err != 0)
-		wiphy_err(wiphy, "wlc_coreinit: txfifo mismatch: ucode size %d"
+		brcms_err(core, "wlc_coreinit: txfifo mismatch: ucode size %d"
 			  " driver size %d index %d\n", buf[i],
 			  wlc_hw->xmtfifo_sz[i], i);
 
@@ -3359,8 +3361,6 @@ static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec) {
 	bool fastclk;
 	struct brcms_c_info *wlc = wlc_hw->wlc;
 
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
 	/* request FAST clock if not on */
 	fastclk = wlc_hw->forcefastclk;
 	if (!fastclk)
@@ -3453,7 +3453,7 @@ static void brcms_c_rate_lookup_init(struct brcms_c_info *wlc,
 		rate = (rateset->rates[i] & BRCMS_RATE_MASK);
 
 		if (rate > BRCM_MAXRATE) {
-			wiphy_err(wlc->wiphy, "brcms_c_rate_lookup_init: "
+			brcms_err(wlc->hw->d11core, "brcms_c_rate_lookup_init: "
 				  "invalid rate 0x%X in rate set\n",
 				  rateset->rates[i]);
 			continue;
@@ -3529,7 +3529,6 @@ static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc,
 	uint parkband;
 	uint i, band_order[2];
 
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
 	/*
 	 * We might have been bandlocked during down and the chip
 	 * power-cycled (hibernate). Figure out the right band to park on
@@ -3710,8 +3709,8 @@ static void brcms_c_set_ratetable(struct brcms_c_info *wlc)
 /* band-specific init */
 static void brcms_c_bsinit(struct brcms_c_info *wlc)
 {
-	BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n",
-		 wlc->pub->unit, wlc->band->bandunit);
+	brcms_dbg_info(wlc->hw->d11core, "wl%d: bandunit %d\n",
+		       wlc->pub->unit, wlc->band->bandunit);
 
 	/* write ucode ACK/CTS rate table */
 	brcms_c_set_ratetable(wlc);
@@ -3734,7 +3733,8 @@ brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM,
 	    isOFDM ? M_TX_IDLE_BUSY_RATIO_X_16_OFDM :
 	    M_TX_IDLE_BUSY_RATIO_X_16_CCK;
 	if (duty_cycle > 100 || duty_cycle < 0) {
-		wiphy_err(wlc->wiphy, "wl%d:  duty cycle value off limit\n",
+		brcms_err(wlc->hw->d11core,
+			  "wl%d:  duty cycle value off limit\n",
 			  wlc->pub->unit);
 		return -EINVAL;
 	}
@@ -3752,40 +3752,6 @@ brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM,
 	return 0;
 }
 
-/*
- * Initialize the base precedence map for dequeueing
- * from txq based on WME settings
- */
-static void brcms_c_tx_prec_map_init(struct brcms_c_info *wlc)
-{
-	wlc->tx_prec_map = BRCMS_PREC_BMP_ALL;
-	memset(wlc->fifo2prec_map, 0, NFIFO * sizeof(u16));
-
-	wlc->fifo2prec_map[TX_AC_BK_FIFO] = BRCMS_PREC_BMP_AC_BK;
-	wlc->fifo2prec_map[TX_AC_BE_FIFO] = BRCMS_PREC_BMP_AC_BE;
-	wlc->fifo2prec_map[TX_AC_VI_FIFO] = BRCMS_PREC_BMP_AC_VI;
-	wlc->fifo2prec_map[TX_AC_VO_FIFO] = BRCMS_PREC_BMP_AC_VO;
-}
-
-static void
-brcms_c_txflowcontrol_signal(struct brcms_c_info *wlc,
-			     struct brcms_txq_info *qi, bool on, int prio)
-{
-	/* transmit flowcontrol is not yet implemented */
-}
-
-static void brcms_c_txflowcontrol_reset(struct brcms_c_info *wlc)
-{
-	struct brcms_txq_info *qi;
-
-	for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) {
-		if (qi->stopped) {
-			brcms_c_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
-			qi->stopped = 0;
-		}
-	}
-}
-
 /* push sw hps and wake state through hardware */
 static void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc)
 {
@@ -3795,7 +3761,8 @@ static void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc)
 
 	hps = brcms_c_ps_allowed(wlc);
 
-	BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps);
+	brcms_dbg_mac80211(wlc->hw->d11core, "wl%d: hps %d\n", wlc->pub->unit,
+			   hps);
 
 	v1 = bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol));
 	v2 = MCTL_WAKE;
@@ -3881,7 +3848,8 @@ brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec,
 {
 	uint bandunit;
 
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d: 0x%x\n", wlc_hw->unit, chanspec);
+	brcms_dbg_mac80211(wlc_hw->d11core, "wl%d: 0x%x\n", wlc_hw->unit,
+			   chanspec);
 
 	wlc_hw->chanspec = chanspec;
 
@@ -3942,7 +3910,7 @@ static void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec)
 	u16 old_chanspec = wlc->chanspec;
 
 	if (!brcms_c_valid_chanspec_db(wlc->cmi, chanspec)) {
-		wiphy_err(wlc->wiphy, "wl%d: %s: Bad channel %d\n",
+		brcms_err(wlc->hw->d11core, "wl%d: %s: Bad channel %d\n",
 			  wlc->pub->unit, __func__, CHSPEC_CHANNEL(chanspec));
 		return;
 	}
@@ -3953,8 +3921,8 @@ static void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec)
 		if (wlc->band->bandunit != bandunit || wlc->bandinit_pending) {
 			switchband = true;
 			if (wlc->bandlocked) {
-				wiphy_err(wlc->wiphy, "wl%d: %s: chspec %d "
-					  "band is locked!\n",
+				brcms_err(wlc->hw->d11core,
+					  "wl%d: %s: chspec %d band is locked!\n",
 					  wlc->pub->unit, __func__,
 					  CHSPEC_CHANNEL(chanspec));
 				return;
@@ -4018,6 +3986,10 @@ void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,
  */
 void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val)
 {
+	/*
+	 * Cannot use brcms_dbg_* here because this function is called
+	 * before wlc is sufficiently initialized.
+	 */
 	BCMMSG(wlc->wiphy, "idx %d, val %d\n", idx, val);
 
 	switch (idx) {
@@ -4090,8 +4062,8 @@ void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
 
 	/* Only apply params if the core is out of reset and has clocks */
 	if (!wlc->clk) {
-		wiphy_err(wlc->wiphy, "wl%d: %s : no-clock\n", wlc->pub->unit,
-			  __func__);
+		brcms_err(wlc->hw->d11core, "wl%d: %s : no-clock\n",
+			  wlc->pub->unit, __func__);
 		return;
 	}
 
@@ -4109,7 +4081,7 @@ void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
 
 	if (acp_shm.aifs < EDCF_AIFSN_MIN
 	    || acp_shm.aifs > EDCF_AIFSN_MAX) {
-		wiphy_err(wlc->wiphy, "wl%d: edcf_setparams: bad "
+		brcms_err(wlc->hw->d11core, "wl%d: edcf_setparams: bad "
 			  "aifs %d\n", wlc->pub->unit, acp_shm.aifs);
 	} else {
 		acp_shm.cwmin = params->cw_min;
@@ -4224,8 +4196,8 @@ static void brcms_c_radio_timer(void *arg)
 	struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
 
 	if (brcms_deviceremoved(wlc)) {
-		wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
-			__func__);
+		brcms_err(wlc->hw->d11core, "wl%d: %s: dead chip\n",
+			  wlc->pub->unit, __func__);
 		brcms_down(wlc->wl);
 		return;
 	}
@@ -4238,8 +4210,6 @@ static void brcms_b_watchdog(struct brcms_c_info *wlc)
 {
 	struct brcms_hardware *wlc_hw = wlc->hw;
 
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
 	if (!wlc_hw->up)
 		return;
 
@@ -4258,14 +4228,14 @@ static void brcms_b_watchdog(struct brcms_c_info *wlc)
 /* common watchdog code */
 static void brcms_c_watchdog(struct brcms_c_info *wlc)
 {
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+	brcms_dbg_info(wlc->hw->d11core, "wl%d\n", wlc->pub->unit);
 
 	if (!wlc->pub->up)
 		return;
 
 	if (brcms_deviceremoved(wlc)) {
-		wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
-			  __func__);
+		brcms_err(wlc->hw->d11core, "wl%d: %s: dead chip\n",
+			  wlc->pub->unit, __func__);
 		brcms_down(wlc->wl);
 		return;
 	}
@@ -4437,13 +4407,13 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
 	struct ssb_sprom *sprom = &core->bus->sprom;
 
 	if (core->bus->hosttype == BCMA_HOSTTYPE_PCI)
-		BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit,
-		       pcidev->vendor,
-		       pcidev->device);
+		brcms_dbg_info(core, "wl%d: vendor 0x%x device 0x%x\n", unit,
+			       pcidev->vendor,
+			       pcidev->device);
 	else
-		BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit,
-		       core->bus->boardinfo.vendor,
-		       core->bus->boardinfo.type);
+		brcms_dbg_info(core, "wl%d: vendor 0x%x device 0x%x\n", unit,
+			       core->bus->boardinfo.vendor,
+			       core->bus->boardinfo.type);
 
 	wme = true;
 
@@ -4715,8 +4685,9 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
 		goto fail;
 	}
 
-	BCMMSG(wlc->wiphy, "deviceid 0x%x nbands %d board 0x%x\n",
-	       wlc_hw->deviceid, wlc_hw->_nbands, ai_get_boardtype(wlc_hw->sih));
+	brcms_dbg_info(wlc_hw->d11core, "deviceid 0x%x nbands %d board 0x%x\n",
+		       wlc_hw->deviceid, wlc_hw->_nbands,
+		       ai_get_boardtype(wlc_hw->sih));
 
 	return err;
 
@@ -4836,56 +4807,6 @@ static void brcms_c_bss_default_init(struct brcms_c_info *wlc)
 		bi->flags |= BRCMS_BSS_HT;
 }
 
-static struct brcms_txq_info *brcms_c_txq_alloc(struct brcms_c_info *wlc)
-{
-	struct brcms_txq_info *qi, *p;
-
-	qi = kzalloc(sizeof(struct brcms_txq_info), GFP_ATOMIC);
-	if (qi != NULL) {
-		/*
-		 * Have enough room for control packets along with HI watermark
-		 * Also, add room to txq for total psq packets if all the SCBs
-		 * leave PS mode. The watermark for flowcontrol to OS packets
-		 * will remain the same
-		 */
-		brcmu_pktq_init(&qi->q, BRCMS_PREC_COUNT,
-			  2 * BRCMS_DATAHIWAT + PKTQ_LEN_DEFAULT);
-
-		/* add this queue to the the global list */
-		p = wlc->tx_queues;
-		if (p == NULL) {
-			wlc->tx_queues = qi;
-		} else {
-			while (p->next != NULL)
-				p = p->next;
-			p->next = qi;
-		}
-	}
-	return qi;
-}
-
-static void brcms_c_txq_free(struct brcms_c_info *wlc,
-			     struct brcms_txq_info *qi)
-{
-	struct brcms_txq_info *p;
-
-	if (qi == NULL)
-		return;
-
-	/* remove the queue from the linked list */
-	p = wlc->tx_queues;
-	if (p == qi)
-		wlc->tx_queues = p->next;
-	else {
-		while (p != NULL && p->next != qi)
-			p = p->next;
-		if (p != NULL)
-			p->next = p->next->next;
-	}
-
-	kfree(qi);
-}
-
 static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap)
 {
 	uint i;
@@ -4991,8 +4912,6 @@ uint brcms_c_detach(struct brcms_c_info *wlc)
 	if (wlc == NULL)
 		return 0;
 
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
 	callbacks += brcms_b_detach(wlc);
 
 	/* delete software timers */
@@ -5005,10 +4924,6 @@ uint brcms_c_detach(struct brcms_c_info *wlc)
 
 	brcms_c_detach_module(wlc);
 
-
-	while (wlc->tx_queues != NULL)
-		brcms_c_txq_free(wlc, wlc->tx_queues);
-
 	brcms_c_detach_mfree(wlc);
 	return callbacks;
 }
@@ -5026,7 +4941,7 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw)
 	if (wlc_hw->wlc->pub->hw_up)
 		return;
 
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+	brcms_dbg_info(wlc_hw->d11core, "wl%d\n", wlc_hw->unit);
 
 	/*
 	 * Enable pll and xtal, initialize the power control registers,
@@ -5063,7 +4978,7 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw)
 
 static int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
 {
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
+	brcms_dbg_info(wlc_hw->d11core, "wl%d\n", wlc_hw->unit);
 
 	/*
 	 * Enable pll and xtal, initialize the power control registers,
@@ -5077,7 +4992,7 @@ static int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
 	 * Configure pci/pcmcia here instead of in brcms_c_attach()
 	 * to allow mfg hotswap:  down, hotswap (chip power cycle), up.
 	 */
-	bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci, wlc_hw->d11core,
+	bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci[0], wlc_hw->d11core,
 			      true);
 
 	/*
@@ -5102,8 +5017,6 @@ static int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
 
 static int brcms_b_up_finish(struct brcms_hardware *wlc_hw)
 {
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
 	wlc_hw->up = true;
 	wlc_phy_hw_state_upd(wlc_hw->band->pi, true);
 
@@ -5135,7 +5048,7 @@ int brcms_c_up(struct brcms_c_info *wlc)
 {
 	struct ieee80211_channel *ch;
 
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+	brcms_dbg_info(wlc->hw->d11core, "wl%d\n", wlc->pub->unit);
 
 	/* HW is turned off so don't try to access it */
 	if (wlc->pub->hw_off || brcms_deviceremoved(wlc))
@@ -5176,8 +5089,8 @@ int brcms_c_up(struct brcms_c_info *wlc)
 					 WL_RADIO_HW_DISABLE);
 
 				if (bsscfg->enable && bsscfg->BSS)
-					wiphy_err(wlc->wiphy, "wl%d: up"
-						  ": rfdisable -> "
+					brcms_err(wlc->hw->d11core,
+						  "wl%d: up: rfdisable -> "
 						  "bsscfg_disable()\n",
 						   wlc->pub->unit);
 			}
@@ -5237,8 +5150,6 @@ static int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw)
 	bool dev_gone;
 	uint callbacks = 0;
 
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
 	if (!wlc_hw->up)
 		return callbacks;
 
@@ -5265,8 +5176,6 @@ static int brcms_b_down_finish(struct brcms_hardware *wlc_hw)
 	uint callbacks = 0;
 	bool dev_gone;
 
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
 	if (!wlc_hw->up)
 		return callbacks;
 
@@ -5314,14 +5223,14 @@ uint brcms_c_down(struct brcms_c_info *wlc)
 	uint callbacks = 0;
 	int i;
 	bool dev_gone = false;
-	struct brcms_txq_info *qi;
 
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+	brcms_dbg_info(wlc->hw->d11core, "wl%d\n", wlc->pub->unit);
 
 	/* check if we are already in the going down path */
 	if (wlc->going_down) {
-		wiphy_err(wlc->wiphy, "wl%d: %s: Driver going down so return"
-			  "\n", wlc->pub->unit, __func__);
+		brcms_err(wlc->hw->d11core,
+			  "wl%d: %s: Driver going down so return\n",
+			  wlc->pub->unit, __func__);
 		return 0;
 	}
 	if (!wlc->pub->up)
@@ -5353,13 +5262,6 @@ uint brcms_c_down(struct brcms_c_info *wlc)
 
 	wlc_phy_mute_upd(wlc->band->pi, false, PHY_MUTE_ALL);
 
-	/* clear txq flow control */
-	brcms_c_txflowcontrol_reset(wlc);
-
-	/* flush tx queues */
-	for (qi = wlc->tx_queues; qi != NULL; qi = qi->next)
-		brcmu_pktq_flush(&qi->q, true, NULL, NULL);
-
 	callbacks += brcms_b_down_finish(wlc->hw);
 
 	/* brcms_b_down_finish has done brcms_c_coredisable(). so clk is off */
@@ -5441,7 +5343,7 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
 
 	default:
 		/* Error */
-		wiphy_err(wlc->wiphy, "wl%d: %s: invalid gmode %d\n",
+		brcms_err(wlc->hw->d11core, "wl%d: %s: invalid gmode %d\n",
 			  wlc->pub->unit, __func__, gmode);
 		return -ENOTSUPP;
 	}
@@ -5745,45 +5647,6 @@ int brcms_c_module_unregister(struct brcms_pub *pub, const char *name,
 	return -ENODATA;
 }
 
-void brcms_c_print_txstatus(struct tx_status *txs)
-{
-	pr_debug("\ntxpkt (MPDU) Complete\n");
-
-	pr_debug("FrameID: %04x   TxStatus: %04x\n", txs->frameid, txs->status);
-
-	pr_debug("[15:12]  %d  frame attempts\n",
-		  (txs->status & TX_STATUS_FRM_RTX_MASK) >>
-		 TX_STATUS_FRM_RTX_SHIFT);
-	pr_debug(" [11:8]  %d  rts attempts\n",
-		 (txs->status & TX_STATUS_RTS_RTX_MASK) >>
-		 TX_STATUS_RTS_RTX_SHIFT);
-	pr_debug("    [7]  %d  PM mode indicated\n",
-		 txs->status & TX_STATUS_PMINDCTD ? 1 : 0);
-	pr_debug("    [6]  %d  intermediate status\n",
-		 txs->status & TX_STATUS_INTERMEDIATE ? 1 : 0);
-	pr_debug("    [5]  %d  AMPDU\n",
-		 txs->status & TX_STATUS_AMPDU ? 1 : 0);
-	pr_debug("  [4:2]  %d  Frame Suppressed Reason (%s)\n",
-		 (txs->status & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT,
-		 (const char *[]) {
-			"None",
-			"PMQ Entry",
-			"Flush request",
-			"Previous frag failure",
-			"Channel mismatch",
-			"Lifetime Expiry",
-			"Underflow"
-		 } [(txs->status & TX_STATUS_SUPR_MASK) >>
-		    TX_STATUS_SUPR_SHIFT]);
-	pr_debug("    [1]  %d  acked\n",
-		 txs->status & TX_STATUS_ACK_RCV ? 1 : 0);
-
-	pr_debug("LastTxTime: %04x Seq: %04x PHYTxStatus: %04x RxAckRSSI: %04x RxAckSQ: %04x\n",
-		 txs->lasttxtime, txs->sequence, txs->phyerr,
-		 (txs->ackphyrxsh & PRXS1_JSSI_MASK) >> PRXS1_JSSI_SHIFT,
-		 (txs->ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT);
-}
-
 static bool brcms_c_chipmatch_pci(struct bcma_device *core)
 {
 	struct pci_dev *pcidev = core->bus->host_pci;
@@ -5832,184 +5695,6 @@ bool brcms_c_chipmatch(struct bcma_device *core)
 	}
 }
 
-#if defined(DEBUG)
-void brcms_c_print_txdesc(struct d11txh *txh)
-{
-	u16 mtcl = le16_to_cpu(txh->MacTxControlLow);
-	u16 mtch = le16_to_cpu(txh->MacTxControlHigh);
-	u16 mfc = le16_to_cpu(txh->MacFrameControl);
-	u16 tfest = le16_to_cpu(txh->TxFesTimeNormal);
-	u16 ptcw = le16_to_cpu(txh->PhyTxControlWord);
-	u16 ptcw_1 = le16_to_cpu(txh->PhyTxControlWord_1);
-	u16 ptcw_1_Fbr = le16_to_cpu(txh->PhyTxControlWord_1_Fbr);
-	u16 ptcw_1_Rts = le16_to_cpu(txh->PhyTxControlWord_1_Rts);
-	u16 ptcw_1_FbrRts = le16_to_cpu(txh->PhyTxControlWord_1_FbrRts);
-	u16 mainrates = le16_to_cpu(txh->MainRates);
-	u16 xtraft = le16_to_cpu(txh->XtraFrameTypes);
-	u8 *iv = txh->IV;
-	u8 *ra = txh->TxFrameRA;
-	u16 tfestfb = le16_to_cpu(txh->TxFesTimeFallback);
-	u8 *rtspfb = txh->RTSPLCPFallback;
-	u16 rtsdfb = le16_to_cpu(txh->RTSDurFallback);
-	u8 *fragpfb = txh->FragPLCPFallback;
-	u16 fragdfb = le16_to_cpu(txh->FragDurFallback);
-	u16 mmodelen = le16_to_cpu(txh->MModeLen);
-	u16 mmodefbrlen = le16_to_cpu(txh->MModeFbrLen);
-	u16 tfid = le16_to_cpu(txh->TxFrameID);
-	u16 txs = le16_to_cpu(txh->TxStatus);
-	u16 mnmpdu = le16_to_cpu(txh->MaxNMpdus);
-	u16 mabyte = le16_to_cpu(txh->MaxABytes_MRT);
-	u16 mabyte_f = le16_to_cpu(txh->MaxABytes_FBR);
-	u16 mmbyte = le16_to_cpu(txh->MinMBytes);
-
-	u8 *rtsph = txh->RTSPhyHeader;
-	struct ieee80211_rts rts = txh->rts_frame;
-
-	/* add plcp header along with txh descriptor */
-	brcmu_dbg_hex_dump(txh, sizeof(struct d11txh) + 48,
-			   "Raw TxDesc + plcp header:\n");
-
-	pr_debug("TxCtlLow: %04x ", mtcl);
-	pr_debug("TxCtlHigh: %04x ", mtch);
-	pr_debug("FC: %04x ", mfc);
-	pr_debug("FES Time: %04x\n", tfest);
-	pr_debug("PhyCtl: %04x%s ", ptcw,
-	       (ptcw & PHY_TXC_SHORT_HDR) ? " short" : "");
-	pr_debug("PhyCtl_1: %04x ", ptcw_1);
-	pr_debug("PhyCtl_1_Fbr: %04x\n", ptcw_1_Fbr);
-	pr_debug("PhyCtl_1_Rts: %04x ", ptcw_1_Rts);
-	pr_debug("PhyCtl_1_Fbr_Rts: %04x\n", ptcw_1_FbrRts);
-	pr_debug("MainRates: %04x ", mainrates);
-	pr_debug("XtraFrameTypes: %04x ", xtraft);
-	pr_debug("\n");
-
-	print_hex_dump_bytes("SecIV:", DUMP_PREFIX_OFFSET, iv, sizeof(txh->IV));
-	print_hex_dump_bytes("RA:", DUMP_PREFIX_OFFSET,
-			     ra, sizeof(txh->TxFrameRA));
-
-	pr_debug("Fb FES Time: %04x ", tfestfb);
-	print_hex_dump_bytes("Fb RTS PLCP:", DUMP_PREFIX_OFFSET,
-			     rtspfb, sizeof(txh->RTSPLCPFallback));
-	pr_debug("RTS DUR: %04x ", rtsdfb);
-	print_hex_dump_bytes("PLCP:", DUMP_PREFIX_OFFSET,
-			     fragpfb, sizeof(txh->FragPLCPFallback));
-	pr_debug("DUR: %04x", fragdfb);
-	pr_debug("\n");
-
-	pr_debug("MModeLen: %04x ", mmodelen);
-	pr_debug("MModeFbrLen: %04x\n", mmodefbrlen);
-
-	pr_debug("FrameID:     %04x\n", tfid);
-	pr_debug("TxStatus:    %04x\n", txs);
-
-	pr_debug("MaxNumMpdu:  %04x\n", mnmpdu);
-	pr_debug("MaxAggbyte:  %04x\n", mabyte);
-	pr_debug("MaxAggbyte_fb:  %04x\n", mabyte_f);
-	pr_debug("MinByte:     %04x\n", mmbyte);
-
-	print_hex_dump_bytes("RTS PLCP:", DUMP_PREFIX_OFFSET,
-			     rtsph, sizeof(txh->RTSPhyHeader));
-	print_hex_dump_bytes("RTS Frame:", DUMP_PREFIX_OFFSET,
-			     (u8 *)&rts, sizeof(txh->rts_frame));
-	pr_debug("\n");
-}
-#endif				/* defined(DEBUG) */
-
-#if defined(DEBUG)
-static int
-brcms_c_format_flags(const struct brcms_c_bit_desc *bd, u32 flags, char *buf,
-		     int len)
-{
-	int i;
-	char *p = buf;
-	char hexstr[16];
-	int slen = 0, nlen = 0;
-	u32 bit;
-	const char *name;
-
-	if (len < 2 || !buf)
-		return 0;
-
-	buf[0] = '\0';
-
-	for (i = 0; flags != 0; i++) {
-		bit = bd[i].bit;
-		name = bd[i].name;
-		if (bit == 0 && flags != 0) {
-			/* print any unnamed bits */
-			snprintf(hexstr, 16, "0x%X", flags);
-			name = hexstr;
-			flags = 0;	/* exit loop */
-		} else if ((flags & bit) == 0)
-			continue;
-		flags &= ~bit;
-		nlen = strlen(name);
-		slen += nlen;
-		/* count btwn flag space */
-		if (flags != 0)
-			slen += 1;
-		/* need NULL char as well */
-		if (len <= slen)
-			break;
-		/* copy NULL char but don't count it */
-		strncpy(p, name, nlen + 1);
-		p += nlen;
-		/* copy btwn flag space and NULL char */
-		if (flags != 0)
-			p += snprintf(p, 2, " ");
-		len -= slen;
-	}
-
-	/* indicate the str was too short */
-	if (flags != 0) {
-		if (len < 2)
-			p -= 2 - len;	/* overwrite last char */
-		p += snprintf(p, 2, ">");
-	}
-
-	return (int)(p - buf);
-}
-#endif				/* defined(DEBUG) */
-
-#if defined(DEBUG)
-void brcms_c_print_rxh(struct d11rxhdr *rxh)
-{
-	u16 len = rxh->RxFrameSize;
-	u16 phystatus_0 = rxh->PhyRxStatus_0;
-	u16 phystatus_1 = rxh->PhyRxStatus_1;
-	u16 phystatus_2 = rxh->PhyRxStatus_2;
-	u16 phystatus_3 = rxh->PhyRxStatus_3;
-	u16 macstatus1 = rxh->RxStatus1;
-	u16 macstatus2 = rxh->RxStatus2;
-	char flagstr[64];
-	char lenbuf[20];
-	static const struct brcms_c_bit_desc macstat_flags[] = {
-		{RXS_FCSERR, "FCSErr"},
-		{RXS_RESPFRAMETX, "Reply"},
-		{RXS_PBPRES, "PADDING"},
-		{RXS_DECATMPT, "DeCr"},
-		{RXS_DECERR, "DeCrErr"},
-		{RXS_BCNSENT, "Bcn"},
-		{0, NULL}
-	};
-
-	brcmu_dbg_hex_dump(rxh, sizeof(struct d11rxhdr), "Raw RxDesc:\n");
-
-	brcms_c_format_flags(macstat_flags, macstatus1, flagstr, 64);
-
-	snprintf(lenbuf, sizeof(lenbuf), "0x%x", len);
-
-	pr_debug("RxFrameSize:     %6s (%d)%s\n", lenbuf, len,
-	       (rxh->PhyRxStatus_0 & PRXS0_SHORTH) ? " short preamble" : "");
-	pr_debug("RxPHYStatus:     %04x %04x %04x %04x\n",
-	       phystatus_0, phystatus_1, phystatus_2, phystatus_3);
-	pr_debug("RxMACStatus:     %x %s\n", macstatus1, flagstr);
-	pr_debug("RXMACaggtype:    %x\n",
-	       (macstatus2 & RXS_AGGTYPE_MASK));
-	pr_debug("RxTSFTime:       %04x\n", rxh->RxTSFTime);
-}
-#endif				/* defined(DEBUG) */
-
 u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate)
 {
 	u16 table_ptr;
@@ -6033,86 +5718,6 @@ u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate)
 	return 2 * brcms_b_read_shm(wlc_hw, table_ptr + (index * 2));
 }
 
-static bool
-brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q,
-		      struct sk_buff *pkt, int prec, bool head)
-{
-	struct sk_buff *p;
-	int eprec = -1;		/* precedence to evict from */
-
-	/* Determine precedence from which to evict packet, if any */
-	if (pktq_pfull(q, prec))
-		eprec = prec;
-	else if (pktq_full(q)) {
-		p = brcmu_pktq_peek_tail(q, &eprec);
-		if (eprec > prec) {
-			wiphy_err(wlc->wiphy, "%s: Failing: eprec %d > prec %d"
-				  "\n", __func__, eprec, prec);
-			return false;
-		}
-	}
-
-	/* Evict if needed */
-	if (eprec >= 0) {
-		bool discard_oldest;
-
-		discard_oldest = ac_bitmap_tst(0, eprec);
-
-		/* Refuse newer packet unless configured to discard oldest */
-		if (eprec == prec && !discard_oldest) {
-			wiphy_err(wlc->wiphy, "%s: No where to go, prec == %d"
-				  "\n", __func__, prec);
-			return false;
-		}
-
-		/* Evict packet according to discard policy */
-		p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) :
-			brcmu_pktq_pdeq_tail(q, eprec);
-		brcmu_pkt_buf_free_skb(p);
-	}
-
-	/* Enqueue */
-	if (head)
-		p = brcmu_pktq_penq_head(q, prec, pkt);
-	else
-		p = brcmu_pktq_penq(q, prec, pkt);
-
-	return true;
-}
-
-/*
- * Attempts to queue a packet onto a multiple-precedence queue,
- * if necessary evicting a lower precedence packet from the queue.
- *
- * 'prec' is the precedence number that has already been mapped
- * from the packet priority.
- *
- * Returns true if packet consumed (queued), false if not.
- */
-static bool brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q,
-		      struct sk_buff *pkt, int prec)
-{
-	return brcms_c_prec_enq_head(wlc, q, pkt, prec, false);
-}
-
-void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb,
-		     struct sk_buff *sdu, uint prec)
-{
-	struct brcms_txq_info *qi = wlc->pkt_queue;	/* Check me */
-	struct pktq *q = &qi->q;
-	int prio;
-
-	prio = sdu->priority;
-
-	if (!brcms_c_prec_enq(wlc, q, sdu, prec)) {
-		/*
-		 * we might hit this condtion in case
-		 * packet flooding from mac80211 stack
-		 */
-		brcmu_pkt_buf_free_skb(sdu);
-	}
-}
-
 /*
  * bcmc_fid_generate:
  * Generate frame ID for a BCMC packet.  The frag field is not used
@@ -6140,8 +5745,6 @@ brcms_c_calc_ack_time(struct brcms_c_info *wlc, u32 rspec,
 {
 	uint dur = 0;
 
-	BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d\n",
-		wlc->pub->unit, rspec, preamble_type);
 	/*
 	 * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that
 	 * is less than or equal to the rate of the immediately previous
@@ -6159,8 +5762,6 @@ static uint
 brcms_c_calc_cts_time(struct brcms_c_info *wlc, u32 rspec,
 		      u8 preamble_type)
 {
-	BCMMSG(wlc->wiphy, "wl%d: ratespec 0x%x, preamble_type %d\n",
-		wlc->pub->unit, rspec, preamble_type);
 	return brcms_c_calc_ack_time(wlc, rspec, preamble_type);
 }
 
@@ -6168,8 +5769,6 @@ static uint
 brcms_c_calc_ba_time(struct brcms_c_info *wlc, u32 rspec,
 		     u8 preamble_type)
 {
-	BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, "
-		 "preamble_type %d\n", wlc->pub->unit, rspec, preamble_type);
 	/*
 	 * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that
 	 * is less than or equal to the rate of the immediately previous
@@ -6223,9 +5822,6 @@ brcms_c_calc_frame_len(struct brcms_c_info *wlc, u32 ratespec,
 	uint nsyms, mac_len, Ndps, kNdps;
 	uint rate = rspec2rate(ratespec);
 
-	BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, dur %d\n",
-		 wlc->pub->unit, ratespec, preamble_type, dur);
-
 	if (is_mcs_rate(ratespec)) {
 		uint mcs = ratespec & RSPEC_RATE_MASK;
 		int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec);
@@ -6292,7 +5888,7 @@ static bool brcms_c_valid_rate(struct brcms_c_info *wlc, u32 rspec, int band,
 			return true;
  error:
 	if (verbose)
-		wiphy_err(wlc->wiphy, "wl%d: valid_rate: rate spec 0x%x "
+		brcms_err(wlc->hw->d11core, "wl%d: valid_rate: rate spec 0x%x "
 			  "not in hw_rateset\n", wlc->pub->unit, rspec);
 
 	return false;
@@ -6302,6 +5898,7 @@ static u32
 mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
 		       u32 int_val)
 {
+	struct bcma_device *core = wlc->hw->d11core;
 	u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT;
 	u8 rate = int_val & NRATE_RATE_MASK;
 	u32 rspec;
@@ -6318,7 +5915,7 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
 	if ((wlc->pub->_n_enab & SUPPORT_11N) && ismcs) {
 		/* mcs only allowed when nmode */
 		if (stf > PHY_TXC1_MODE_SDM) {
-			wiphy_err(wlc->wiphy, "wl%d: %s: Invalid stf\n",
+			brcms_err(core, "wl%d: %s: Invalid stf\n",
 				  wlc->pub->unit, __func__);
 			bcmerror = -EINVAL;
 			goto done;
@@ -6329,8 +5926,8 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
 			if (!CHSPEC_IS40(wlc->home_chanspec) ||
 			    ((stf != PHY_TXC1_MODE_SISO)
 			     && (stf != PHY_TXC1_MODE_CDD))) {
-				wiphy_err(wlc->wiphy, "wl%d: %s: Invalid mcs "
-					  "32\n", wlc->pub->unit, __func__);
+				brcms_err(core, "wl%d: %s: Invalid mcs 32\n",
+					  wlc->pub->unit, __func__);
 				bcmerror = -EINVAL;
 				goto done;
 			}
@@ -6338,9 +5935,9 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
 		} else if (rate > HIGHEST_SINGLE_STREAM_MCS) {
 			/* mcs > 7 must use stf SDM */
 			if (stf != PHY_TXC1_MODE_SDM) {
-				BCMMSG(wlc->wiphy, "wl%d: enabling "
-				       "SDM mode for mcs %d\n",
-				       wlc->pub->unit, rate);
+				brcms_dbg_mac80211(core, "wl%d: enabling "
+						   "SDM mode for mcs %d\n",
+						   wlc->pub->unit, rate);
 				stf = PHY_TXC1_MODE_SDM;
 			}
 		} else {
@@ -6351,15 +5948,15 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
 			if ((stf > PHY_TXC1_MODE_STBC) ||
 			    (!BRCMS_STBC_CAP_PHY(wlc)
 			     && (stf == PHY_TXC1_MODE_STBC))) {
-				wiphy_err(wlc->wiphy, "wl%d: %s: Invalid STBC"
-					  "\n", wlc->pub->unit, __func__);
+				brcms_err(core, "wl%d: %s: Invalid STBC\n",
+					  wlc->pub->unit, __func__);
 				bcmerror = -EINVAL;
 				goto done;
 			}
 		}
 	} else if (is_ofdm_rate(rate)) {
 		if ((stf != PHY_TXC1_MODE_CDD) && (stf != PHY_TXC1_MODE_SISO)) {
-			wiphy_err(wlc->wiphy, "wl%d: %s: Invalid OFDM\n",
+			brcms_err(core, "wl%d: %s: Invalid OFDM\n",
 				  wlc->pub->unit, __func__);
 			bcmerror = -EINVAL;
 			goto done;
@@ -6367,20 +5964,20 @@ mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
 	} else if (is_cck_rate(rate)) {
 		if ((cur_band->bandtype != BRCM_BAND_2G)
 		    || (stf != PHY_TXC1_MODE_SISO)) {
-			wiphy_err(wlc->wiphy, "wl%d: %s: Invalid CCK\n",
+			brcms_err(core, "wl%d: %s: Invalid CCK\n",
 				  wlc->pub->unit, __func__);
 			bcmerror = -EINVAL;
 			goto done;
 		}
 	} else {
-		wiphy_err(wlc->wiphy, "wl%d: %s: Unknown rate type\n",
+		brcms_err(core, "wl%d: %s: Unknown rate type\n",
 			  wlc->pub->unit, __func__);
 		bcmerror = -EINVAL;
 		goto done;
 	}
 	/* make sure multiple antennae are available for non-siso rates */
 	if ((stf != PHY_TXC1_MODE_SISO) && (wlc->stf->txstreams == 1)) {
-		wiphy_err(wlc->wiphy, "wl%d: %s: SISO antenna but !SISO "
+		brcms_err(core, "wl%d: %s: SISO antenna but !SISO "
 			  "request\n", wlc->pub->unit, __func__);
 		bcmerror = -EINVAL;
 		goto done;
@@ -6449,7 +6046,7 @@ static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500,
 		break;
 
 	default:
-		wiphy_err(wlc->wiphy,
+		brcms_err(wlc->hw->d11core,
 			  "brcms_c_cck_plcp_set: unsupported rate %d\n",
 			  rate_500);
 		rate_500 = BRCM_RATE_1M;
@@ -6582,7 +6179,7 @@ static u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec)
 		bw = rspec_get_bw(rspec);
 		/* 10Mhz is not supported yet */
 		if (bw < PHY_TXC1_BW_20MHZ) {
-			wiphy_err(wlc->wiphy, "phytxctl1_calc: bw %d is "
+			brcms_err(wlc->hw->d11core, "phytxctl1_calc: bw %d is "
 				  "not supported yet, set to 20L\n", bw);
 			bw = PHY_TXC1_BW_20MHZ;
 		}
@@ -6609,7 +6206,7 @@ static u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec)
 		/* get the phyctl byte from rate phycfg table */
 		phycfg = brcms_c_rate_legacy_phyctl(rspec2rate(rspec));
 		if (phycfg == -1) {
-			wiphy_err(wlc->wiphy, "phytxctl1_calc: wrong "
+			brcms_err(wlc->hw->d11core, "phytxctl1_calc: wrong "
 				  "legacy OFDM/CCK rate\n");
 			phycfg = 0;
 		}
@@ -6689,8 +6286,9 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
 	if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
 		/* non-AP STA should never use BCMC queue */
 		if (queue == TX_BCMC_FIFO) {
-			wiphy_err(wlc->wiphy, "wl%d: %s: ASSERT queue == "
-				  "TX_BCMC!\n", wlc->pub->unit, __func__);
+			brcms_err(wlc->hw->d11core,
+				  "wl%d: %s: ASSERT queue == TX_BCMC!\n",
+				  wlc->pub->unit, __func__);
 			frameid = bcmc_fid_generate(wlc, NULL, txh);
 		} else {
 			/* Increment the counter for first fragment */
@@ -6860,7 +6458,8 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
 
 			if ((txrate[k]->flags & IEEE80211_TX_RC_MCS)
 			    && (!is_mcs_rate(rspec[k]))) {
-				wiphy_err(wlc->wiphy, "wl%d: %s: IEEE80211_TX_"
+				brcms_err(wlc->hw->d11core,
+					  "wl%d: %s: IEEE80211_TX_"
 					  "RC_MCS != is_mcs_rate(rspec)\n",
 					  wlc->pub->unit, __func__);
 			}
@@ -7254,14 +6853,16 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
 					wlc->fragthresh[queue] =
 					    (u16) newfragthresh;
 			} else {
-				wiphy_err(wlc->wiphy, "wl%d: %s txop invalid "
+				brcms_err(wlc->hw->d11core,
+					  "wl%d: %s txop invalid "
 					  "for rate %d\n",
 					  wlc->pub->unit, fifo_names[queue],
 					  rspec2rate(rspec[0]));
 			}
 
 			if (dur > wlc->edcf_txop[ac])
-				wiphy_err(wlc->wiphy, "wl%d: %s: %s txop "
+				brcms_err(wlc->hw->d11core,
+					  "wl%d: %s: %s txop "
 					  "exceeded phylen %d/%d dur %d/%d\n",
 					  wlc->pub->unit, __func__,
 					  fifo_names[queue],
@@ -7273,79 +6874,33 @@ brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
 	return 0;
 }
 
-void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu,
-			      struct ieee80211_hw *hw)
+static int brcms_c_tx(struct brcms_c_info *wlc, struct sk_buff *skb)
 {
-	u8 prio;
-	uint fifo;
-	struct scb *scb = &wlc->pri_scb;
-	struct ieee80211_hdr *d11_header = (struct ieee80211_hdr *)(sdu->data);
-
-	/*
-	 * 802.11 standard requires management traffic
-	 * to go at highest priority
-	 */
-	prio = ieee80211_is_data(d11_header->frame_control) ? sdu->priority :
-		MAXPRIO;
-	fifo = prio2fifo[prio];
-	if (brcms_c_d11hdrs_mac80211(wlc, hw, sdu, scb, 0, 1, fifo, 0))
-		return;
-	brcms_c_txq_enq(wlc, scb, sdu, BRCMS_PRIO_TO_PREC(prio));
-	brcms_c_send_q(wlc);
-}
-
-void brcms_c_send_q(struct brcms_c_info *wlc)
-{
-	struct sk_buff *pkt[DOT11_MAXNUMFRAGS];
-	int prec;
-	u16 prec_map;
-	int err = 0, i, count;
-	uint fifo;
-	struct brcms_txq_info *qi = wlc->pkt_queue;
-	struct pktq *q = &qi->q;
-	struct ieee80211_tx_info *tx_info;
-
-	prec_map = wlc->tx_prec_map;
+	struct dma_pub *dma;
+	int fifo, ret = -ENOSPC;
+	struct d11txh *txh;
+	u16 frameid = INVALIDFID;
 
-	/* Send all the enq'd pkts that we can.
-	 * Dequeue packets with precedence with empty HW fifo only
-	 */
-	while (prec_map && (pkt[0] = brcmu_pktq_mdeq(q, prec_map, &prec))) {
-		tx_info = IEEE80211_SKB_CB(pkt[0]);
-		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
-			err = brcms_c_sendampdu(wlc->ampdu, qi, pkt, prec);
-		} else {
-			count = 1;
-			err = brcms_c_prep_pdu(wlc, pkt[0], &fifo);
-			if (!err) {
-				for (i = 0; i < count; i++)
-					brcms_c_txfifo(wlc, fifo, pkt[i], true,
-						       1);
-			}
-		}
+	fifo = brcms_ac_to_fifo(skb_get_queue_mapping(skb));
+	dma = wlc->hw->di[fifo];
+	txh = (struct d11txh *)(skb->data);
 
-		if (err == -EBUSY) {
-			brcmu_pktq_penq_head(q, prec, pkt[0]);
-			/*
-			 * If send failed due to any other reason than a
-			 * change in HW FIFO condition, quit. Otherwise,
-			 * read the new prec_map!
-			 */
-			if (prec_map == wlc->tx_prec_map)
-				break;
-			prec_map = wlc->tx_prec_map;
-		}
+	if (dma->txavail == 0) {
+		/*
+		 * We sometimes get a frame from mac80211 after stopping
+		 * the queues. This only ever seems to be a single frame
+		 * and is seems likely to be a race. TX_HEADROOM should
+		 * ensure that we have enough space to handle these stray
+		 * packets, so warn if there isn't. If we're out of space
+		 * in the tx ring and the tx queue isn't stopped then
+		 * we've really got a bug; warn loudly if that happens.
+		 */
+		brcms_warn(wlc->hw->d11core,
+			   "Received frame for tx with no space in DMA ring\n");
+		WARN_ON(!ieee80211_queue_stopped(wlc->pub->ieee_hw,
+						 skb_get_queue_mapping(skb)));
+		return -ENOSPC;
 	}
-}
-
-void
-brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p,
-	       bool commit, s8 txpktpend)
-{
-	u16 frameid = INVALIDFID;
-	struct d11txh *txh;
-
-	txh = (struct d11txh *) (p->data);
 
 	/* When a BC/MC frame is being committed to the BCMC fifo
 	 * via DMA (NOT PIO), update ucode or BSS info as appropriate.
@@ -7353,16 +6908,6 @@ brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p,
 	if (fifo == TX_BCMC_FIFO)
 		frameid = le16_to_cpu(txh->TxFrameID);
 
-	/*
-	 * Bump up pending count for if not using rpc. If rpc is
-	 * used, this will be handled in brcms_b_txfifo()
-	 */
-	if (commit) {
-		wlc->core->txpktpend[fifo] += txpktpend;
-		BCMMSG(wlc->wiphy, "pktpend inc %d to %d\n",
-			 txpktpend, wlc->core->txpktpend[fifo]);
-	}
-
 	/* Commit BCMC sequence number in the SHM frame ID location */
 	if (frameid != INVALIDFID) {
 		/*
@@ -7372,8 +6917,52 @@ brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p,
 		brcms_b_write_shm(wlc->hw, M_BCMC_FID, frameid);
 	}
 
-	if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0)
+	ret = brcms_c_txfifo(wlc, fifo, skb);
+	/*
+	 * The only reason for brcms_c_txfifo to fail is because
+	 * there weren't any DMA descriptors, but we've already
+	 * checked for that. So if it does fail yell loudly.
+	 */
+	WARN_ON_ONCE(ret);
+
+	return ret;
+}
+
+void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu,
+			      struct ieee80211_hw *hw)
+{
+	uint fifo;
+	struct scb *scb = &wlc->pri_scb;
+
+	fifo = brcms_ac_to_fifo(skb_get_queue_mapping(sdu));
+	if (brcms_c_d11hdrs_mac80211(wlc, hw, sdu, scb, 0, 1, fifo, 0))
+		return;
+	if (brcms_c_tx(wlc, sdu))
+		dev_kfree_skb_any(sdu);
+}
+
+int
+brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p)
+{
+	struct dma_pub *dma = wlc->hw->di[fifo];
+	int ret;
+	u16 queue;
+
+	ret = dma_txfast(wlc, dma, p);
+	if (ret	< 0)
 		wiphy_err(wlc->wiphy, "txfifo: fatal, toss frames !!!\n");
+
+	/*
+	 * Stop queue if DMA ring is full. Reserve some free descriptors,
+	 * as we sometimes receive a frame from mac80211 after the queues
+	 * are stopped.
+	 */
+	queue = skb_get_queue_mapping(p);
+	if (dma->txavail <= TX_HEADROOM && fifo < TX_BCMC_FIFO &&
+	    !ieee80211_queue_stopped(wlc->pub->ieee_hw, queue))
+		ieee80211_stop_queue(wlc->pub->ieee_hw, queue);
+
+	return ret;
 }
 
 u32
@@ -7423,19 +7012,6 @@ brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec,
 	return rts_rspec;
 }
 
-void
-brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, s8 txpktpend)
-{
-	wlc->core->txpktpend[fifo] -= txpktpend;
-	BCMMSG(wlc->wiphy, "pktpend dec %d to %d\n", txpktpend,
-	       wlc->core->txpktpend[fifo]);
-
-	/* There is more room; mark precedences related to this FIFO sendable */
-	wlc->tx_prec_map |= wlc->fifo2prec_map[fifo];
-
-	/* figure out which bsscfg is being worked on... */
-}
-
 /* Update beacon listen interval in shared memory */
 static void brcms_c_bcn_li_upd(struct brcms_c_info *wlc)
 {
@@ -7508,7 +7084,7 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
 
 	/* fill in TSF and flag its presence */
 	rx_status->mactime = brcms_c_recover_tsf64(wlc, rxh);
-	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+	rx_status->flag |= RX_FLAG_MACTIME_START;
 
 	channel = BRCMS_CHAN_CHANNEL(rxh->RxChan);
 
@@ -7571,7 +7147,8 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
 			rx_status->rate_idx = 11;
 			break;
 		default:
-			wiphy_err(wlc->wiphy, "%s: Unknown rate\n", __func__);
+			brcms_err(wlc->hw->d11core,
+				  "%s: Unknown rate\n", __func__);
 		}
 
 		/*
@@ -7590,7 +7167,7 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
 		} else if (is_ofdm_rate(rspec)) {
 			rx_status->flag |= RX_FLAG_SHORTPRE;
 		} else {
-			wiphy_err(wlc->wiphy, "%s: Unknown modulation\n",
+			brcms_err(wlc->hw->d11core, "%s: Unknown modulation\n",
 				  __func__);
 		}
 	}
@@ -7600,12 +7177,12 @@ prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
 
 	if (rxh->RxStatus1 & RXS_DECERR) {
 		rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;
-		wiphy_err(wlc->wiphy, "%s:  RX_FLAG_FAILED_PLCP_CRC\n",
+		brcms_err(wlc->hw->d11core, "%s:  RX_FLAG_FAILED_PLCP_CRC\n",
 			  __func__);
 	}
 	if (rxh->RxStatus1 & RXS_FCSERR) {
 		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
-		wiphy_err(wlc->wiphy, "%s:  RX_FLAG_FAILED_FCS_CRC\n",
+		brcms_err(wlc->hw->d11core, "%s:  RX_FLAG_FAILED_FCS_CRC\n",
 			  __func__);
 	}
 }
@@ -7649,9 +7226,6 @@ brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec,
 {
 	uint nsyms, len = 0, kNdps;
 
-	BCMMSG(wlc->wiphy, "wl%d: rate %d, len%d\n",
-		 wlc->pub->unit, rspec2rate(ratespec), mac_len);
-
 	if (is_mcs_rate(ratespec)) {
 		uint mcs = ratespec & RSPEC_RATE_MASK;
 		int tot_streams = (mcs_2_txstreams(mcs) + 1) +
@@ -7883,35 +7457,6 @@ void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
 		brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
 }
 
-/* prepares pdu for transmission. returns BCM error codes */
-int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu, uint *fifop)
-{
-	uint fifo;
-	struct d11txh *txh;
-	struct ieee80211_hdr *h;
-	struct scb *scb;
-
-	txh = (struct d11txh *) (pdu->data);
-	h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
-
-	/* get the pkt queue info. This was put at brcms_c_sendctl or
-	 * brcms_c_send for PDU */
-	fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
-
-	scb = NULL;
-
-	*fifop = fifo;
-
-	/* return if insufficient dma resources */
-	if (*wlc->core->txavail[fifo] < MAX_DMA_SEGS) {
-		/* Mark precedences related to this FIFO, unsendable */
-		/* A fifo is full. Clear precedences related to that FIFO */
-		wlc->tx_prec_map &= ~(wlc->fifo2prec_map[fifo]);
-		return -EBUSY;
-	}
-	return 0;
-}
-
 int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
 			   uint *blocks)
 {
@@ -7977,13 +7522,15 @@ int brcms_c_get_curband(struct brcms_c_info *wlc)
 void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
 {
 	int timeout = 20;
+	int i;
 
-	/* flush packet queue when requested */
-	if (drop)
-		brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL);
+	/* Kick DMA to send any pending AMPDU */
+	for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++)
+		if (wlc->hw->di[i])
+			dma_txflush(wlc->hw->di[i]);
 
 	/* wait for queue and DMA fifos to run dry */
-	while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0) {
+	while (brcms_txpktpendtot(wlc) > 0) {
 		brcms_msleep(wlc->wl, 1);
 
 		if (--timeout == 0)
@@ -8032,8 +7579,6 @@ static void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p)
 	uint len;
 	bool is_amsdu;
 
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
-
 	/* frame starts with rxhdr */
 	rxh = (struct d11rxhdr *) (p->data);
 
@@ -8043,8 +7588,9 @@ static void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p)
 	/* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */
 	if (rxh->RxStatus1 & RXS_PBPRES) {
 		if (p->len < 2) {
-			wiphy_err(wlc->wiphy, "wl%d: recv: rcvd runt of "
-				  "len %d\n", wlc->pub->unit, p->len);
+			brcms_err(wlc->hw->d11core,
+				  "wl%d: recv: rcvd runt of len %d\n",
+				  wlc->pub->unit, p->len);
 			goto toss;
 		}
 		skb_pull(p, 2);
@@ -8089,7 +7635,6 @@ brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound)
 	uint n = 0;
 	uint bound_limit = bound ? RXBND : -1;
 
-	BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
 	skb_queue_head_init(&recv_frames);
 
 	/* gather received frames */
@@ -8140,10 +7685,9 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
 	u32 macintstatus;
 	struct brcms_hardware *wlc_hw = wlc->hw;
 	struct bcma_device *core = wlc_hw->d11core;
-	struct wiphy *wiphy = wlc->wiphy;
 
 	if (brcms_deviceremoved(wlc)) {
-		wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
+		brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
 			  __func__);
 		brcms_down(wlc->wl);
 		return false;
@@ -8153,8 +7697,8 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
 	macintstatus = wlc->macintstatus;
 	wlc->macintstatus = 0;
 
-	BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n",
-	       wlc_hw->unit, macintstatus);
+	brcms_dbg_int(core, "wl%d: macintstatus 0x%x\n",
+		      wlc_hw->unit, macintstatus);
 
 	WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */
 
@@ -8164,7 +7708,7 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
 		if (brcms_b_txstatus(wlc->hw, bounded, &fatal))
 			wlc->macintstatus |= MI_TFS;
 		if (fatal) {
-			wiphy_err(wiphy, "MI_TFS: fatal\n");
+			brcms_err(core, "MI_TFS: fatal\n");
 			goto fatal;
 		}
 	}
@@ -8174,7 +7718,7 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
 
 	/* ATIM window end */
 	if (macintstatus & MI_ATIMWINEND) {
-		BCMMSG(wlc->wiphy, "end of ATIM window\n");
+		brcms_dbg_info(core, "end of ATIM window\n");
 		bcma_set32(core, D11REGOFFS(maccommand), wlc->qvalid);
 		wlc->qvalid = 0;
 	}
@@ -8192,7 +7736,7 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
 		wlc_phy_noise_sample_intr(wlc_hw->band->pi);
 
 	if (macintstatus & MI_GP0) {
-		wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d "
+		brcms_err(core, "wl%d: PSM microcode watchdog fired at %d "
 			  "(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now);
 
 		printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
@@ -8206,15 +7750,11 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
 		bcma_write32(core, D11REGOFFS(gptimer), 0);
 
 	if (macintstatus & MI_RFDISABLE) {
-		BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the"
-		       " RF Disable Input\n", wlc_hw->unit);
+		brcms_dbg_info(core, "wl%d: BMAC Detected a change on the"
+			       " RF Disable Input\n", wlc_hw->unit);
 		brcms_rfkill_set_hw_state(wlc->wl);
 	}
 
-	/* send any enq'd tx packets. Just makes sure to jump start tx */
-	if (!pktq_empty(&wlc->pkt_queue->q))
-		brcms_c_send_q(wlc);
-
 	/* it isn't done and needs to be resched if macintstatus is non-zero */
 	return wlc->macintstatus != 0;
 
@@ -8229,7 +7769,7 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
 	struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
 	u16 chanspec;
 
-	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
+	brcms_dbg_info(core, "wl%d\n", wlc->pub->unit);
 
 	chanspec = ch20mhz_chspec(ch->hw_value);
 
@@ -8286,9 +7826,6 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
 	bcma_set16(core, D11REGOFFS(ifs_ctl), IFS_USEEDCF);
 	brcms_c_edcf_setparams(wlc, false);
 
-	/* Init precedence maps for empty FIFOs */
-	brcms_c_tx_prec_map_init(wlc);
-
 	/* read the ucode version if we have not yet done so */
 	if (wlc->ucode_rev == 0) {
 		wlc->ucode_rev =
@@ -8303,9 +7840,6 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
 	if (mute_tx)
 		brcms_b_mute(wlc->hw, true);
 
-	/* clear tx flow control */
-	brcms_c_txflowcontrol_reset(wlc);
-
 	/* enable the RF Disable Delay timer */
 	bcma_write32(core, D11REGOFFS(rfdisabledly), RFDISABLE_DEFAULT);
 
@@ -8464,15 +7998,6 @@ brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit,
 	 * Complete the wlc default state initializations..
 	 */
 
-	/* allocate our initial queue */
-	wlc->pkt_queue = brcms_c_txq_alloc(wlc);
-	if (wlc->pkt_queue == NULL) {
-		wiphy_err(wl->wiphy, "wl%d: %s: failed to malloc tx queue\n",
-			  unit, __func__);
-		err = 100;
-		goto fail;
-	}
-
 	wlc->bsscfg->wlc = wlc;
 
 	wlc->mimoft = FT_HT;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h
index 8debc74..fb44774 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h
@@ -101,9 +101,6 @@
 
 #define DATA_BLOCK_TX_SUPR	(1 << 4)
 
-/* 802.1D Priority to TX FIFO number for wme */
-extern const u8 prio2fifo[];
-
 /* Ucode MCTL_WAKE override bits */
 #define BRCMS_WAKE_OVERRIDE_CLKCTL	0x01
 #define BRCMS_WAKE_OVERRIDE_PHYREG	0x02
@@ -242,7 +239,6 @@ struct brcms_core {
 
 	/* fifo */
 	uint *txavail[NFIFO];	/* # tx descriptors available */
-	s16 txpktpend[NFIFO];	/* tx admission control */
 
 	struct macstat *macstat_snapshot;	/* mac hw prev read values */
 };
@@ -382,19 +378,6 @@ struct brcms_hardware {
 				 */
 };
 
-/* TX Queue information
- *
- * Each flow of traffic out of the device has a TX Queue with independent
- * flow control. Several interfaces may be associated with a single TX Queue
- * if they belong to the same flow of traffic from the device. For multi-channel
- * operation there are independent TX Queues for each channel.
- */
-struct brcms_txq_info {
-	struct brcms_txq_info *next;
-	struct pktq q;
-	uint stopped;		/* tx flow control bits */
-};
-
 /*
  * Principal common driver data structure.
  *
@@ -435,11 +418,8 @@ struct brcms_txq_info {
  * WDlast: last time wlc_watchdog() was called.
  * edcf_txop[IEEE80211_NUM_ACS]: current txop for each ac.
  * wme_retries: per-AC retry limits.
- * tx_prec_map: Precedence map based on HW FIFO space.
- * fifo2prec_map[NFIFO]: pointer to fifo2_prec map based on WME.
  * bsscfg: set of BSS configurations, idx 0 is default and always valid.
  * cfg: the primary bsscfg (can be AP or STA).
- * tx_queues: common TX Queue list.
  * modulecb:
  * mimoft: SIGN or 11N.
  * cck_40txbw: 11N, cck tx b/w override when in 40MHZ mode.
@@ -469,7 +449,6 @@ struct brcms_txq_info {
  * tempsense_lasttime;
  * tx_duty_cycle_ofdm: maximum allowed duty cycle for OFDM.
  * tx_duty_cycle_cck: maximum allowed duty cycle for CCK.
- * pkt_queue: txq for transmit packets.
  * wiphy:
  * pri_scb: primary Station Control Block
  */
@@ -533,14 +512,9 @@ struct brcms_c_info {
 	u16 edcf_txop[IEEE80211_NUM_ACS];
 
 	u16 wme_retries[IEEE80211_NUM_ACS];
-	u16 tx_prec_map;
-	u16 fifo2prec_map[NFIFO];
 
 	struct brcms_bss_cfg *bsscfg;
 
-	/* tx queue */
-	struct brcms_txq_info *tx_queues;
-
 	struct modulecb *modulecb;
 
 	u8 mimoft;
@@ -585,7 +559,6 @@ struct brcms_c_info {
 	u16 tx_duty_cycle_ofdm;
 	u16 tx_duty_cycle_cck;
 
-	struct brcms_txq_info *pkt_queue;
 	struct wiphy *wiphy;
 	struct scb pri_scb;
 };
@@ -637,30 +610,13 @@ struct brcms_bss_cfg {
 	struct brcms_bss_info *current_bss;
 };
 
-extern void brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo,
-			   struct sk_buff *p,
-			   bool commit, s8 txpktpend);
-extern void brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo,
-				    s8 txpktpend);
-extern void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb,
-			    struct sk_buff *sdu, uint prec);
-extern void brcms_c_print_txstatus(struct tx_status *txs);
+extern int brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo,
+			   struct sk_buff *p);
 extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
 		   uint *blocks);
 
-#if defined(DEBUG)
-extern void brcms_c_print_txdesc(struct d11txh *txh);
-#else
-static inline void brcms_c_print_txdesc(struct d11txh *txh)
-{
-}
-#endif
-
 extern int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config);
 extern void brcms_c_mac_promisc(struct brcms_c_info *wlc, uint filter_flags);
-extern void brcms_c_send_q(struct brcms_c_info *wlc);
-extern int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu,
-			    uint *fifo);
 extern u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec,
 				uint mac_len);
 extern u32 brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc,
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
index 5855f4f..0148dec 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
@@ -200,43 +200,6 @@ enum wlc_par_id {
 /* WL11N Support */
 #define AMPDU_AGG_HOST	1
 
-/* pri is priority encoded in the packet. This maps the Packet priority to
- * enqueue precedence as defined in wlc_prec_map
- */
-extern const u8 wlc_prio2prec_map[];
-#define BRCMS_PRIO_TO_PREC(pri)	wlc_prio2prec_map[(pri) & 7]
-
-#define	BRCMS_PREC_COUNT	16	/* Max precedence level implemented */
-
-/* Mask to describe all precedence levels */
-#define BRCMS_PREC_BMP_ALL		MAXBITVAL(BRCMS_PREC_COUNT)
-
-/*
- * This maps priority to one precedence higher - Used by PS-Poll response
- * packets to simulate enqueue-at-head operation, but still maintain the
- * order on the queue
- */
-#define BRCMS_PRIO_TO_HI_PREC(pri)	min(BRCMS_PRIO_TO_PREC(pri) + 1,\
-					    BRCMS_PREC_COUNT - 1)
-
-/* Define a bitmap of precedences comprised by each AC */
-#define BRCMS_PREC_BMP_AC_BE	(NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BE)) | \
-			NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BE)) |	\
-			NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_EE)) |	\
-			NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_EE)))
-#define BRCMS_PREC_BMP_AC_BK	(NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BK)) | \
-			NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BK)) |	\
-			NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NONE)) |	\
-			NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NONE)))
-#define BRCMS_PREC_BMP_AC_VI	(NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_CL)) | \
-			NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_CL)) |	\
-			NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VI)) |	\
-			NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VI)))
-#define BRCMS_PREC_BMP_AC_VO	(NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VO)) | \
-			NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VO)) |	\
-			NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NC)) |	\
-			NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NC)))
-
 /* network protection config */
 #define	BRCMS_PROT_G_SPEC		1	/* SPEC g protection */
 #define	BRCMS_PROT_G_OVR		2	/* SPEC g prot override */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/stf.c b/drivers/net/wireless/brcm80211/brcmsmac/stf.c
index ed1d1aa..dd91627 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/stf.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/stf.c
@@ -23,6 +23,7 @@
 #include "channel.h"
 #include "main.h"
 #include "stf.h"
+#include "debug.h"
 
 #define MIN_SPATIAL_EXPANSION	0
 #define MAX_SPATIAL_EXPANSION	1
@@ -160,8 +161,8 @@ bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val)
 static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts,
 				  u8 core_mask)
 {
-	BCMMSG(wlc->wiphy, "wl%d: Nsts %d core_mask %x\n",
-		 wlc->pub->unit, Nsts, core_mask);
+	brcms_dbg_ht(wlc->hw->d11core, "wl%d: Nsts %d core_mask %x\n",
+		     wlc->pub->unit, Nsts, core_mask);
 
 	if (hweight8(core_mask) > wlc->stf->txstreams)
 		core_mask = 0;
@@ -194,7 +195,8 @@ static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val)
 	int i;
 	u8 core_mask = 0;
 
-	BCMMSG(wlc->wiphy, "wl%d: val %x\n", wlc->pub->unit, val);
+	brcms_dbg_ht(wlc->hw->d11core, "wl%d: val %x\n", wlc->pub->unit,
+		     val);
 
 	wlc->stf->spatial_policy = (s8) val;
 	for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) {
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/types.h b/drivers/net/wireless/brcm80211/brcmsmac/types.h
index e11ae83..ae1f3ad 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/types.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/types.h
@@ -246,7 +246,7 @@
 
 #define BCMMSG(dev, fmt, args...)		\
 do {						\
-	if (brcm_msg_level & LOG_TRACE_VAL)	\
+	if (brcm_msg_level & BRCM_DL_INFO)	\
 		wiphy_err(dev, "%s: " fmt, __func__, ##args);	\
 } while (0)
 
@@ -281,7 +281,6 @@ struct ieee80211_tx_queue_params;
 struct brcms_info;
 struct brcms_c_info;
 struct brcms_hardware;
-struct brcms_txq_info;
 struct brcms_band;
 struct dma_pub;
 struct si_pub;
diff --git a/drivers/net/wireless/brcm80211/include/defs.h b/drivers/net/wireless/brcm80211/include/defs.h
index f0d8c04..fb7cbcf 100644
--- a/drivers/net/wireless/brcm80211/include/defs.h
+++ b/drivers/net/wireless/brcm80211/include/defs.h
@@ -78,9 +78,14 @@
 #define PM_OFF	0
 #define PM_MAX	1
 
-/* Message levels */
-#define LOG_ERROR_VAL		0x00000001
-#define LOG_TRACE_VAL		0x00000002
+/* Debug levels */
+#define BRCM_DL_INFO		0x00000001
+#define BRCM_DL_MAC80211	0x00000002
+#define BRCM_DL_RX		0x00000004
+#define BRCM_DL_TX		0x00000008
+#define BRCM_DL_INT		0x00000010
+#define BRCM_DL_DMA		0x00000020
+#define BRCM_DL_HT		0x00000040
 
 #define PM_OFF	0
 #define PM_MAX	1
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
index df7050a..d39e3e2 100644
--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -415,7 +415,7 @@ static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb,
 			ssid = pos + 2;
 			ssid_len = pos[1];
 			break;
-		case WLAN_EID_GENERIC:
+		case WLAN_EID_VENDOR_SPECIFIC:
 			if (pos[1] >= 4 &&
 			    pos[2] == 0x00 && pos[3] == 0x50 &&
 			    pos[4] == 0xf2 && pos[5] == 1) {
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 29b8fa1..46938bc 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -1788,10 +1788,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
 	}
 
 	/* Initialize the geo */
-	if (libipw_set_geo(priv->ieee, &ipw_geos[0])) {
-		printk(KERN_WARNING DRV_NAME "Could not set geo\n");
-		return 0;
-	}
+	libipw_set_geo(priv->ieee, &ipw_geos[0]);
 	priv->ieee->freq_band = LIBIPW_24GHZ_BAND;
 
 	lock = LOCK_NONE;
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.h b/drivers/net/wireless/ipw2x00/ipw2100.h
index 9731252..5fe17cb 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.h
+++ b/drivers/net/wireless/ipw2x00/ipw2100.h
@@ -1045,7 +1045,7 @@ typedef enum _ORDINAL_TABLE_1 {	// NS - means Not Supported by FW
 	IPW_ORD_POWER_MGMT_MODE,	// Power mode - 0=CAM, 1=PSP
 	IPW_ORD_POWER_MGMT_INDEX,	//NS //
 	IPW_ORD_COUNTRY_CODE,	// IEEE country code as recv'd from beacon
-	IPW_ORD_COUNTRY_CHANNELS,	// channels suported by country
+	IPW_ORD_COUNTRY_CHANNELS,	// channels supported by country
 // IPW_ORD_COUNTRY_CHANNELS:
 // For 11b the lower 2-byte are used for channels from 1-14
 //   and the higher 2-byte are not used.
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index 768bf61..482f505 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -11269,10 +11269,31 @@ static const struct libipw_geo ipw_geos[] = {
 	 }
 };
 
+static void ipw_set_geo(struct ipw_priv *priv)
+{
+	int j;
+
+	for (j = 0; j < ARRAY_SIZE(ipw_geos); j++) {
+		if (!memcmp(&priv->eeprom[EEPROM_COUNTRY_CODE],
+			    ipw_geos[j].name, 3))
+			break;
+	}
+
+	if (j == ARRAY_SIZE(ipw_geos)) {
+		IPW_WARNING("SKU [%c%c%c] not recognized.\n",
+			    priv->eeprom[EEPROM_COUNTRY_CODE + 0],
+			    priv->eeprom[EEPROM_COUNTRY_CODE + 1],
+			    priv->eeprom[EEPROM_COUNTRY_CODE + 2]);
+		j = 0;
+	}
+
+	libipw_set_geo(priv->ieee, &ipw_geos[j]);
+}
+
 #define MAX_HW_RESTARTS 5
 static int ipw_up(struct ipw_priv *priv)
 {
-	int rc, i, j;
+	int rc, i;
 
 	/* Age scan list entries found before suspend */
 	if (priv->suspend_time) {
@@ -11310,22 +11331,7 @@ static int ipw_up(struct ipw_priv *priv)
 		memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN);
 		memcpy(priv->net_dev->perm_addr, priv->mac_addr, ETH_ALEN);
 
-		for (j = 0; j < ARRAY_SIZE(ipw_geos); j++) {
-			if (!memcmp(&priv->eeprom[EEPROM_COUNTRY_CODE],
-				    ipw_geos[j].name, 3))
-				break;
-		}
-		if (j == ARRAY_SIZE(ipw_geos)) {
-			IPW_WARNING("SKU [%c%c%c] not recognized.\n",
-				    priv->eeprom[EEPROM_COUNTRY_CODE + 0],
-				    priv->eeprom[EEPROM_COUNTRY_CODE + 1],
-				    priv->eeprom[EEPROM_COUNTRY_CODE + 2]);
-			j = 0;
-		}
-		if (libipw_set_geo(priv->ieee, &ipw_geos[j])) {
-			IPW_WARNING("Could not set geography.");
-			return 0;
-		}
+		ipw_set_geo(priv);
 
 		if (priv->status & STATUS_RF_KILL_SW) {
 			IPW_WARNING("Radio disabled by module parameter.\n");
diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h
index 0b22fb4..6eede52 100644
--- a/drivers/net/wireless/ipw2x00/libipw.h
+++ b/drivers/net/wireless/ipw2x00/libipw.h
@@ -978,7 +978,7 @@ extern void libipw_network_reset(struct libipw_network *network);
 /* libipw_geo.c */
 extern const struct libipw_geo *libipw_get_geo(struct libipw_device
 						     *ieee);
-extern int libipw_set_geo(struct libipw_device *ieee,
+extern void libipw_set_geo(struct libipw_device *ieee,
 			     const struct libipw_geo *geo);
 
 extern int libipw_is_valid_channel(struct libipw_device *ieee,
diff --git a/drivers/net/wireless/ipw2x00/libipw_geo.c b/drivers/net/wireless/ipw2x00/libipw_geo.c
index c9fe3c9..218f2a3 100644
--- a/drivers/net/wireless/ipw2x00/libipw_geo.c
+++ b/drivers/net/wireless/ipw2x00/libipw_geo.c
@@ -132,7 +132,7 @@ u8 libipw_freq_to_channel(struct libipw_device * ieee, u32 freq)
 	return 0;
 }
 
-int libipw_set_geo(struct libipw_device *ieee,
+void libipw_set_geo(struct libipw_device *ieee,
 		      const struct libipw_geo *geo)
 {
 	memcpy(ieee->geo.name, geo->name, 3);
@@ -143,7 +143,6 @@ int libipw_set_geo(struct libipw_device *ieee,
 	       sizeof(struct libipw_channel));
 	memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels *
 	       sizeof(struct libipw_channel));
-	return 0;
 }
 
 const struct libipw_geo *libipw_get_geo(struct libipw_device *ieee)
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c
index 02e0579..95a1ca1 100644
--- a/drivers/net/wireless/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_rx.c
@@ -1108,7 +1108,7 @@ static const char *get_info_element_string(u16 id)
 		MFIE_STRING(ERP_INFO);
 		MFIE_STRING(RSN);
 		MFIE_STRING(EXT_SUPP_RATES);
-		MFIE_STRING(GENERIC);
+		MFIE_STRING(VENDOR_SPECIFIC);
 		MFIE_STRING(QOS_PARAMETER);
 	default:
 		return "UNKNOWN";
@@ -1248,8 +1248,8 @@ static int libipw_parse_info_param(struct libipw_info_element
 			LIBIPW_DEBUG_MGMT("WLAN_EID_CHALLENGE: ignored\n");
 			break;
 
-		case WLAN_EID_GENERIC:
-			LIBIPW_DEBUG_MGMT("WLAN_EID_GENERIC: %d bytes\n",
+		case WLAN_EID_VENDOR_SPECIFIC:
+			LIBIPW_DEBUG_MGMT("WLAN_EID_VENDOR_SPECIFIC: %d bytes\n",
 					     info_element->len);
 			if (!libipw_parse_qos_info_param_IE(info_element,
 							       network))
diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c
index 87e5398..e0b9d7f 100644
--- a/drivers/net/wireless/iwlegacy/3945.c
+++ b/drivers/net/wireless/iwlegacy/3945.c
@@ -516,7 +516,7 @@ static void
 il3945_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
 {
 	struct ieee80211_hdr *header;
-	struct ieee80211_rx_status rx_status;
+	struct ieee80211_rx_status rx_status = {};
 	struct il_rx_pkt *pkt = rxb_addr(rxb);
 	struct il3945_rx_frame_stats *rx_stats = IL_RX_STATS(pkt);
 	struct il3945_rx_frame_hdr *rx_hdr = IL_RX_HDR(pkt);
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index eac4dc8..07ffa57 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -613,7 +613,7 @@ void
 il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
 {
 	struct ieee80211_hdr *header;
-	struct ieee80211_rx_status rx_status;
+	struct ieee80211_rx_status rx_status = {};
 	struct il_rx_pkt *pkt = rxb_addr(rxb);
 	struct il_rx_phy_res *phy_res;
 	__le32 rx_pkt_status;
@@ -686,7 +686,7 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
 
 	/* TSF isn't reliable. In order to allow smooth user experience,
 	 * this W/A doesn't propagate it to the mac80211 */
-	/*rx_status.flag |= RX_FLAG_MACTIME_MPDU; */
+	/*rx_status.flag |= RX_FLAG_MACTIME_START; */
 
 	il->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
 
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h
index b4bb813..e254cba 100644
--- a/drivers/net/wireless/iwlegacy/common.h
+++ b/drivers/net/wireless/iwlegacy/common.h
@@ -2919,9 +2919,8 @@ do {									\
 #define IL_DBG(level, fmt, args...)					\
 do {									\
 	if (il_get_debug_level(il) & level)				\
-		dev_printk(KERN_ERR, &il->hw->wiphy->dev,		\
-			 "%c %s " fmt, in_interrupt() ? 'I' : 'U',	\
-			__func__ , ## args);				\
+		dev_err(&il->hw->wiphy->dev, "%c %s " fmt,		\
+			in_interrupt() ? 'I' : 'U', __func__ , ##args); \
 } while (0)
 
 #define il_print_hex_dump(il, level, p, len)				\
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 727fbb5..5cf4323 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -133,12 +133,3 @@ config IWLWIFI_P2P
 	  support when it is loaded.
 
 	  Say Y only if you want to experiment with P2P.
-
-config IWLWIFI_EXPERIMENTAL_MFP
-	bool "support MFP (802.11w) even if uCode doesn't advertise"
-	depends on IWLWIFI
-	help
-	  This option enables experimental MFP (802.11W) support
-	  even if the microcode doesn't advertise it.
-
-	  Say Y only if you want to experiment with MFP.
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h
index 75e12f2..33b3ad2 100644
--- a/drivers/net/wireless/iwlwifi/dvm/agn.h
+++ b/drivers/net/wireless/iwlwifi/dvm/agn.h
@@ -176,8 +176,8 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr);
 /* lib */
 int iwlagn_send_tx_power(struct iwl_priv *priv);
 void iwlagn_temperature(struct iwl_priv *priv);
-int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
-void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
+int iwlagn_txfifo_flush(struct iwl_priv *priv);
+void iwlagn_dev_txfifo_flush(struct iwl_priv *priv);
 int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
 int iwl_send_statistics_request(struct iwl_priv *priv,
 				u8 flags, bool clear);
diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h
index 01128c9..71ab76b 100644
--- a/drivers/net/wireless/iwlwifi/dvm/commands.h
+++ b/drivers/net/wireless/iwlwifi/dvm/commands.h
@@ -986,8 +986,7 @@ struct iwl_rem_sta_cmd {
 
 #define IWL_AGG_TX_QUEUE_MSK		cpu_to_le32(0xffc00)
 
-#define IWL_DROP_SINGLE		0
-#define IWL_DROP_ALL		(BIT(IWL_RXON_CTX_BSS) | BIT(IWL_RXON_CTX_PAN))
+#define IWL_DROP_ALL			BIT(1)
 
 /*
  * REPLY_TXFIFO_FLUSH = 0x1e(command and response)
@@ -1004,14 +1003,14 @@ struct iwl_rem_sta_cmd {
  * the flush operation ends when both the scheduler DMA done and TXFIFO empty
  * are set.
  *
- * @fifo_control: bit mask for which queues to flush
+ * @queue_control: bit mask for which queues to flush
  * @flush_control: flush controls
  *	0: Dump single MSDU
  *	1: Dump multiple MSDU according to PS, INVALID STA, TTL, TID disable.
  *	2: Dump all FIFO
  */
 struct iwl_txfifo_flush_cmd {
-	__le32 fifo_control;
+	__le32 queue_control;
 	__le16 flush_control;
 	__le16 reserved;
 } __packed;
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
index 1a98fa3..769a08b 100644
--- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
@@ -2101,7 +2101,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,
 	if (iwl_is_rfkill(priv))
 		return -EFAULT;
 
-	iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
+	iwlagn_dev_txfifo_flush(priv);
 
 	return count;
 }
diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h
index 8141f91..29c571a 100644
--- a/drivers/net/wireless/iwlwifi/dvm/dev.h
+++ b/drivers/net/wireless/iwlwifi/dvm/dev.h
@@ -789,7 +789,6 @@ struct iwl_priv {
 	/* remain-on-channel offload support */
 	struct ieee80211_channel *hw_roc_channel;
 	struct delayed_work hw_roc_disable_work;
-	enum nl80211_channel_type hw_roc_chantype;
 	int hw_roc_duration;
 	bool hw_roc_setup, hw_roc_start_notified;
 
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c
index bef88c1..7e59be4 100644
--- a/drivers/net/wireless/iwlwifi/dvm/lib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/lib.c
@@ -136,7 +136,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
  *  1. acquire mutex before calling
  *  2. make sure rf is on and not in exit state
  */
-int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
+int iwlagn_txfifo_flush(struct iwl_priv *priv)
 {
 	struct iwl_txfifo_flush_cmd flush_cmd;
 	struct iwl_host_cmd cmd = {
@@ -146,35 +146,34 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
 		.data = { &flush_cmd, },
 	};
 
-	might_sleep();
-
 	memset(&flush_cmd, 0, sizeof(flush_cmd));
-	if (flush_control & BIT(IWL_RXON_CTX_BSS))
-		flush_cmd.fifo_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
-				 IWL_SCD_BE_MSK | IWL_SCD_BK_MSK |
-				 IWL_SCD_MGMT_MSK;
-	if ((flush_control & BIT(IWL_RXON_CTX_PAN)) &&
-	    (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
-		flush_cmd.fifo_control |= IWL_PAN_SCD_VO_MSK |
-				IWL_PAN_SCD_VI_MSK | IWL_PAN_SCD_BE_MSK |
-				IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
-				IWL_PAN_SCD_MULTICAST_MSK;
+
+	flush_cmd.queue_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
+				  IWL_SCD_BE_MSK | IWL_SCD_BK_MSK |
+				  IWL_SCD_MGMT_MSK;
+	if ((priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
+		flush_cmd.queue_control |= IWL_PAN_SCD_VO_MSK |
+					   IWL_PAN_SCD_VI_MSK |
+					   IWL_PAN_SCD_BE_MSK |
+					   IWL_PAN_SCD_BK_MSK |
+					   IWL_PAN_SCD_MGMT_MSK |
+					   IWL_PAN_SCD_MULTICAST_MSK;
 
 	if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE)
-		flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
+		flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK;
 
-	IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
-		       flush_cmd.fifo_control);
-	flush_cmd.flush_control = cpu_to_le16(flush_control);
+	IWL_DEBUG_INFO(priv, "queue control: 0x%x\n",
+		       flush_cmd.queue_control);
+	flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL);
 
 	return iwl_dvm_send_cmd(priv, &cmd);
 }
 
-void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
+void iwlagn_dev_txfifo_flush(struct iwl_priv *priv)
 {
 	mutex_lock(&priv->mutex);
 	ieee80211_stop_queues(priv->hw);
-	if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
+	if (iwlagn_txfifo_flush(priv)) {
 		IWL_ERR(priv, "flush request fail\n");
 		goto done;
 	}
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index 2d9eee9..fb959b0 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -168,10 +168,13 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
 		hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
 			     IEEE80211_HW_SUPPORTS_STATIC_SMPS;
 
-#ifndef CONFIG_IWLWIFI_EXPERIMENTAL_MFP
-	/* enable 11w if the uCode advertise */
-	if (capa->flags & IWL_UCODE_TLV_FLAGS_MFP)
-#endif /* !CONFIG_IWLWIFI_EXPERIMENTAL_MFP */
+	/*
+	 * Enable 11w if advertised by firmware and software crypto
+	 * is not enabled (as the firmware will interpret some mgmt
+	 * packets, so enabling it with software crypto isn't safe)
+	 */
+	if (priv->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_MFP &&
+	    !iwlwifi_mod_params.sw_crypto)
 		hw->flags |= IEEE80211_HW_MFP_CAPABLE;
 
 	hw->sta_data_size = sizeof(struct iwl_station_priv);
@@ -1019,7 +1022,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
 	 */
 	if (drop) {
 		IWL_DEBUG_MAC80211(priv, "send flush command\n");
-		if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
+		if (iwlagn_txfifo_flush(priv)) {
 			IWL_ERR(priv, "flush request fail\n");
 			goto done;
 		}
@@ -1032,8 +1035,8 @@ done:
 }
 
 static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
+				     struct ieee80211_vif *vif,
 				     struct ieee80211_channel *channel,
-				     enum nl80211_channel_type channel_type,
 				     int duration)
 {
 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
@@ -1065,7 +1068,6 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
 	}
 
 	priv->hw_roc_channel = channel;
-	priv->hw_roc_chantype = channel_type;
 	/* convert from ms to TU */
 	priv->hw_roc_duration = DIV_ROUND_UP(1000 * duration, 1024);
 	priv->hw_roc_start_notified = false;
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
index 408132c..e3a07c9 100644
--- a/drivers/net/wireless/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/iwlwifi/dvm/main.c
@@ -511,7 +511,7 @@ static void iwl_bg_tx_flush(struct work_struct *work)
 		return;
 
 	IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
-	iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
+	iwlagn_dev_txfifo_flush(priv);
 }
 
 /*
@@ -1191,10 +1191,6 @@ static void iwl_option_config(struct iwl_priv *priv)
 
 static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
 {
-	u16 radio_cfg;
-
-	priv->eeprom_data->sku = priv->eeprom_data->sku;
-
 	if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE &&
 	    !priv->cfg->ht_params) {
 		IWL_ERR(priv, "Invalid 11n configuration\n");
@@ -1206,9 +1202,7 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
 		return -EINVAL;
 	}
 
-	IWL_INFO(priv, "Device SKU: 0x%X\n", priv->eeprom_data->sku);
-
-	radio_cfg = priv->eeprom_data->radio_cfg;
+	IWL_DEBUG_INFO(priv, "Device SKU: 0x%X\n", priv->eeprom_data->sku);
 
 	priv->hw_params.tx_chains_num =
 		num_of_ant(priv->eeprom_data->valid_tx_ant);
@@ -1218,9 +1212,9 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
 		priv->hw_params.rx_chains_num =
 			num_of_ant(priv->eeprom_data->valid_rx_ant);
 
-	IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
-		 priv->eeprom_data->valid_tx_ant,
-		 priv->eeprom_data->valid_rx_ant);
+	IWL_DEBUG_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
+		       priv->eeprom_data->valid_tx_ant,
+		       priv->eeprom_data->valid_rx_ant);
 
 	return 0;
 }
@@ -1235,7 +1229,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
 	struct iwl_op_mode *op_mode;
 	u16 num_mac;
 	u32 ucode_flags;
-	struct iwl_trans_config trans_cfg;
+	struct iwl_trans_config trans_cfg = {};
 	static const u8 no_reclaim_cmds[] = {
 		REPLY_RX_PHY_CMD,
 		REPLY_RX_MPDU_CMD,
@@ -1334,6 +1328,9 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
 	/* Configure transport layer */
 	iwl_trans_configure(priv->trans, &trans_cfg);
 
+	trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
+	trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start);
+
 	/* At this point both hw and priv are allocated. */
 
 	SET_IEEE80211_DEV(priv->hw, priv->trans->dev);
@@ -1508,10 +1505,6 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
 
 	iwl_tt_exit(priv);
 
-	/*This will stop the queues, move the device to low power state */
-	priv->ucode_loaded = false;
-	iwl_trans_stop_device(priv->trans);
-
 	kfree(priv->eeprom_blob);
 	iwl_free_eeprom_data(priv->eeprom_data);
 
@@ -1927,8 +1920,6 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
 	 * commands by clearing the ready bit */
 	clear_bit(STATUS_READY, &priv->status);
 
-	wake_up(&priv->trans->wait_command_queue);
-
 	if (!ondemand) {
 		/*
 		 * If firmware keep reloading, then it indicate something
@@ -2152,8 +2143,6 @@ static int __init iwl_init(void)
 {
 
 	int ret;
-	pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
-	pr_info(DRV_COPYRIGHT "\n");
 
 	ret = iwlagn_rate_control_register();
 	if (ret) {
diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c
index 5a9c325..cac4f37 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rx.c
@@ -631,8 +631,6 @@ static int iwlagn_rx_card_state_notif(struct iwl_priv *priv,
 	     test_bit(STATUS_RF_KILL_HW, &priv->status)))
 		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
 			test_bit(STATUS_RF_KILL_HW, &priv->status));
-	else
-		wake_up(&priv->trans->wait_command_queue);
 	return 0;
 }
 
@@ -901,7 +899,7 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
 			    struct iwl_device_cmd *cmd)
 {
 	struct ieee80211_hdr *header;
-	struct ieee80211_rx_status rx_status;
+	struct ieee80211_rx_status rx_status = {};
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	struct iwl_rx_phy_res *phy_res;
 	__le32 rx_pkt_status;
@@ -951,7 +949,7 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
 
 	/* TSF isn't reliable. In order to allow smooth user experience,
 	 * this W/A doesn't propagate it to the mac80211 */
-	/*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/
+	/*rx_status.flag |= RX_FLAG_MACTIME_START;*/
 
 	priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
 
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c
index 1089639..2830ea2 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rxon.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c
@@ -1012,12 +1012,12 @@ static void iwl_calc_basic_rates(struct iwl_priv *priv,
 	 * As a consequence, it's not as complicated as it sounds, just add
 	 * any lower rates to the ACK rate bitmap.
 	 */
-	if (IWL_RATE_11M_INDEX < lowest_present_ofdm)
-		ofdm |= IWL_RATE_11M_MASK >> IWL_FIRST_CCK_RATE;
-	if (IWL_RATE_5M_INDEX < lowest_present_ofdm)
-		ofdm |= IWL_RATE_5M_MASK >> IWL_FIRST_CCK_RATE;
-	if (IWL_RATE_2M_INDEX < lowest_present_ofdm)
-		ofdm |= IWL_RATE_2M_MASK >> IWL_FIRST_CCK_RATE;
+	if (IWL_RATE_11M_INDEX < lowest_present_cck)
+		cck |= IWL_RATE_11M_MASK >> IWL_FIRST_CCK_RATE;
+	if (IWL_RATE_5M_INDEX < lowest_present_cck)
+		cck |= IWL_RATE_5M_MASK >> IWL_FIRST_CCK_RATE;
+	if (IWL_RATE_2M_INDEX < lowest_present_cck)
+		cck |= IWL_RATE_2M_MASK >> IWL_FIRST_CCK_RATE;
 	/* 1M already there or needed so always add */
 	cck |= IWL_RATE_1M_MASK >> IWL_FIRST_CCK_RATE;
 
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c
index f5ca73a..4ae031f 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
@@ -1075,14 +1075,11 @@ static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status)
 
 static void iwlagn_set_tx_status(struct iwl_priv *priv,
 				 struct ieee80211_tx_info *info,
-				 struct iwlagn_tx_resp *tx_resp,
-				 bool is_agg)
+				 struct iwlagn_tx_resp *tx_resp)
 {
-	u16  status = le16_to_cpu(tx_resp->status.status);
+	u16 status = le16_to_cpu(tx_resp->status.status);
 
 	info->status.rates[0].count = tx_resp->failure_frame + 1;
-	if (is_agg)
-		info->flags &= ~IEEE80211_TX_CTL_AMPDU;
 	info->flags |= iwl_tx_status_to_mac80211(status);
 	iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
 				    info);
@@ -1231,7 +1228,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
 			if (is_agg && !iwl_is_tx_success(status))
 				info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
 			iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(skb),
-				     tx_resp, is_agg);
+				     tx_resp);
 			if (!is_agg)
 				iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1);
 
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c
index 2cb1efb..95e6d33 100644
--- a/drivers/net/wireless/iwlwifi/dvm/ucode.c
+++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c
@@ -254,7 +254,7 @@ static int iwl_alive_notify(struct iwl_priv *priv)
 	int ret;
 	int i;
 
-	iwl_trans_fw_alive(priv->trans);
+	iwl_trans_fw_alive(priv->trans, 0);
 
 	if (priv->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN &&
 	    priv->eeprom_data->sku & EEPROM_SKU_CAP_IPAN_ENABLE) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index 87f465a..196266a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -150,7 +150,7 @@ enum iwl_led_mode {
 struct iwl_base_params {
 	int eeprom_size;
 	int num_of_queues;	/* def: HW dependent */
-	/* for iwl_apm_init() */
+	/* for iwl_pcie_apm_init() */
 	u32 pll_cfg_val;
 
 	const u16 max_ll_items;
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
index 59a5f78..b3fde5f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h
+++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
@@ -25,6 +25,39 @@
  *****************************************************************************/
 
 #if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ)
+#include <linux/skbuff.h>
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+#include "iwl-trans.h"
+#if !defined(__IWLWIFI_DEVICE_TRACE)
+static inline bool iwl_trace_data(struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr = (void *)skb->data;
+
+	if (ieee80211_is_data(hdr->frame_control))
+		return skb->protocol != cpu_to_be16(ETH_P_PAE);
+	return false;
+}
+
+static inline size_t iwl_rx_trace_len(const struct iwl_trans *trans,
+				      void *rxbuf, size_t len)
+{
+	struct iwl_cmd_header *cmd = (void *)((u8 *)rxbuf + sizeof(__le32));
+	struct ieee80211_hdr *hdr;
+
+	if (cmd->cmd != trans->rx_mpdu_cmd)
+		return len;
+
+	hdr = (void *)((u8 *)cmd + sizeof(struct iwl_cmd_header) +
+			trans->rx_mpdu_cmd_hdr_size);
+	if (!ieee80211_is_data(hdr->frame_control))
+		return len;
+	/* maybe try to identify EAPOL frames? */
+	return sizeof(__le32) + sizeof(*cmd) + trans->rx_mpdu_cmd_hdr_size +
+		ieee80211_hdrlen(hdr->frame_control);
+}
+#endif
+
 #define __IWLWIFI_DEVICE_TRACE
 
 #include <linux/tracepoint.h>
@@ -235,6 +268,48 @@ TRACE_EVENT(iwlwifi_dbg,
 );
 
 #undef TRACE_SYSTEM
+#define TRACE_SYSTEM iwlwifi_data
+
+TRACE_EVENT(iwlwifi_dev_tx_data,
+	TP_PROTO(const struct device *dev,
+		 struct sk_buff *skb,
+		 void *data, size_t data_len),
+	TP_ARGS(dev, skb, data, data_len),
+	TP_STRUCT__entry(
+		DEV_ENTRY
+
+		__dynamic_array(u8, data, iwl_trace_data(skb) ? data_len : 0)
+	),
+	TP_fast_assign(
+		DEV_ASSIGN;
+		if (iwl_trace_data(skb))
+			memcpy(__get_dynamic_array(data), data, data_len);
+	),
+	TP_printk("[%s] TX frame data", __get_str(dev))
+);
+
+TRACE_EVENT(iwlwifi_dev_rx_data,
+	TP_PROTO(const struct device *dev,
+		 const struct iwl_trans *trans,
+		 void *rxbuf, size_t len),
+	TP_ARGS(dev, trans, rxbuf, len),
+	TP_STRUCT__entry(
+		DEV_ENTRY
+
+		__dynamic_array(u8, data,
+				len - iwl_rx_trace_len(trans, rxbuf, len))
+	),
+	TP_fast_assign(
+		size_t offs = iwl_rx_trace_len(trans, rxbuf, len);
+		DEV_ASSIGN;
+		if (offs < len)
+			memcpy(__get_dynamic_array(data),
+			       ((u8 *)rxbuf) + offs, len - offs);
+	),
+	TP_printk("[%s] RX frame data", __get_str(dev))
+);
+
+#undef TRACE_SYSTEM
 #define TRACE_SYSTEM iwlwifi
 
 TRACE_EVENT(iwlwifi_dev_hcmd,
@@ -270,25 +345,28 @@ TRACE_EVENT(iwlwifi_dev_hcmd,
 );
 
 TRACE_EVENT(iwlwifi_dev_rx,
-	TP_PROTO(const struct device *dev, void *rxbuf, size_t len),
-	TP_ARGS(dev, rxbuf, len),
+	TP_PROTO(const struct device *dev, const struct iwl_trans *trans,
+		 void *rxbuf, size_t len),
+	TP_ARGS(dev, trans, rxbuf, len),
 	TP_STRUCT__entry(
 		DEV_ENTRY
-		__dynamic_array(u8, rxbuf, len)
+		__dynamic_array(u8, rxbuf, iwl_rx_trace_len(trans, rxbuf, len))
 	),
 	TP_fast_assign(
 		DEV_ASSIGN;
-		memcpy(__get_dynamic_array(rxbuf), rxbuf, len);
+		memcpy(__get_dynamic_array(rxbuf), rxbuf,
+		       iwl_rx_trace_len(trans, rxbuf, len));
 	),
 	TP_printk("[%s] RX cmd %#.2x",
 		  __get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4])
 );
 
 TRACE_EVENT(iwlwifi_dev_tx,
-	TP_PROTO(const struct device *dev, void *tfd, size_t tfdlen,
+	TP_PROTO(const struct device *dev, struct sk_buff *skb,
+		 void *tfd, size_t tfdlen,
 		 void *buf0, size_t buf0_len,
 		 void *buf1, size_t buf1_len),
-	TP_ARGS(dev, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
+	TP_ARGS(dev, skb, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
 	TP_STRUCT__entry(
 		DEV_ENTRY
 
@@ -301,14 +379,15 @@ TRACE_EVENT(iwlwifi_dev_tx,
 		 * for the possible padding).
 		 */
 		__dynamic_array(u8, buf0, buf0_len)
-		__dynamic_array(u8, buf1, buf1_len)
+		__dynamic_array(u8, buf1, iwl_trace_data(skb) ? 0 : buf1_len)
 	),
 	TP_fast_assign(
 		DEV_ASSIGN;
 		__entry->framelen = buf0_len + buf1_len;
 		memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
 		memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
-		memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
+		if (!iwl_trace_data(skb))
+			memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
 	),
 	TP_printk("[%s] TX %.2x (%zu bytes)",
 		  __get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0],
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
index f10170f..4a9dc96 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
@@ -889,8 +889,8 @@ int iwl_eeprom_check_version(struct iwl_eeprom_data *data,
 {
 	if (data->eeprom_version >= trans->cfg->eeprom_ver ||
 	    data->calib_version >= trans->cfg->eeprom_calib_ver) {
-		IWL_INFO(trans, "device EEPROM VER=0x%x, CALIB=0x%x\n",
-			 data->eeprom_version, data->calib_version);
+		IWL_DEBUG_INFO(trans, "device EEPROM VER=0x%x, CALIB=0x%x\n",
+			       data->eeprom_version, data->calib_version);
 		return 0;
 	}
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h
index 8060466..ec48563 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fh.h
@@ -267,7 +267,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl)
 
 #define FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS	(20)
 #define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS	(4)
-#define RX_RB_TIMEOUT	(0x10)
+#define RX_RB_TIMEOUT	(0x11)
 
 #define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL         (0x00000000)
 #define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_EOF_VAL     (0x40000000)
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c
index 3dfebfb..54c41b4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/iwlwifi/iwl-io.c
@@ -327,11 +327,11 @@ u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr)
 EXPORT_SYMBOL_GPL(iwl_read_targ_mem);
 
 int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
-			       void *buf, int dwords)
+			       const void *buf, int dwords)
 {
 	unsigned long flags;
 	int offs, result = 0;
-	u32 *vals = buf;
+	const u32 *vals = buf;
 
 	spin_lock_irqsave(&trans->reg_lock, flags);
 	if (likely(iwl_grab_nic_access(trans))) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index 50d3819..e1aa69f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -87,7 +87,7 @@ void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
 	} while (0)
 
 int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
-			       void *buf, int dwords);
+			       const void *buf, int dwords);
 
 u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr);
 int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val);
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index 9253ef1..c3a4bb4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -213,6 +213,9 @@
 #define SCD_CONTEXT_QUEUE_OFFSET(x)\
 	(SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8))
 
+#define SCD_TX_STTS_QUEUE_OFFSET(x)\
+	(SCD_TX_STTS_MEM_LOWER_BOUND + ((x) * 16))
+
 #define SCD_TRANS_TBL_OFFSET_QUEUE(x) \
 	((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index ff11542..e378ea6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -221,14 +221,21 @@ struct iwl_device_cmd {
 /**
  * struct iwl_hcmd_dataflag - flag for each one of the chunks of the command
  *
- * IWL_HCMD_DFL_NOCOPY: By default, the command is copied to the host command's
+ * @IWL_HCMD_DFL_NOCOPY: By default, the command is copied to the host command's
  *	ring. The transport layer doesn't map the command's buffer to DMA, but
  *	rather copies it to an previously allocated DMA buffer. This flag tells
  *	the transport layer not to copy the command, but to map the existing
- *	buffer. This can save memcpy and is worth with very big comamnds.
+ *	buffer (that is passed in) instead. This saves the memcpy and allows
+ *	commands that are bigger than the fixed buffer to be submitted.
+ *	Note that a TFD entry after a NOCOPY one cannot be a normal copied one.
+ * @IWL_HCMD_DFL_DUP: Only valid without NOCOPY, duplicate the memory for this
+ *	chunk internally and free it again after the command completes. This
+ *	can (currently) be used only once per command.
+ *	Note that a TFD entry after a DUP one cannot be a normal copied one.
  */
 enum iwl_hcmd_dataflag {
 	IWL_HCMD_DFL_NOCOPY	= BIT(0),
+	IWL_HCMD_DFL_DUP	= BIT(1),
 };
 
 /**
@@ -348,14 +355,17 @@ struct iwl_trans;
  * @start_fw: allocates and inits all the resources for the transport
  *	layer. Also kick a fw image.
  *	May sleep
- * @fw_alive: called when the fw sends alive notification
+ * @fw_alive: called when the fw sends alive notification. If the fw provides
+ *	the SCD base address in SRAM, then provide it here, or 0 otherwise.
  *	May sleep
  * @stop_device:stops the whole device (embedded CPU put to reset)
  *	May sleep
  * @wowlan_suspend: put the device into the correct mode for WoWLAN during
  *	suspend. This is optional, if not implemented WoWLAN will not be
  *	supported. This callback may sleep.
- * @send_cmd:send a host command
+ * @send_cmd:send a host command. Must return -ERFKILL if RFkill is asserted.
+ *	If RFkill is asserted in the middle of a SYNC host command, it must
+ *	return -ERFKILL straight away.
  *	May sleep only if CMD_SYNC is set
  * @tx: send an skb
  *	Must be atomic
@@ -385,7 +395,7 @@ struct iwl_trans_ops {
 	int (*start_hw)(struct iwl_trans *iwl_trans);
 	void (*stop_hw)(struct iwl_trans *iwl_trans, bool op_mode_leaving);
 	int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw);
-	void (*fw_alive)(struct iwl_trans *trans);
+	void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr);
 	void (*stop_device)(struct iwl_trans *trans);
 
 	void (*wowlan_suspend)(struct iwl_trans *trans);
@@ -438,12 +448,15 @@ enum iwl_trans_state {
  *	Set during transport allocation.
  * @hw_id_str: a string with info about HW ID. Set during transport allocation.
  * @pm_support: set to true in start_hw if link pm is supported
- * @wait_command_queue: the wait_queue for SYNC host commands
  * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
  *	The user should use iwl_trans_{alloc,free}_tx_cmd.
  * @dev_cmd_headroom: room needed for the transport's private use before the
  *	device_cmd for Tx - for internal use only
  *	The user should use iwl_trans_{alloc,free}_tx_cmd.
+ * @rx_mpdu_cmd: MPDU RX command ID, must be assigned by opmode before
+ *	starting the firmware, used for tracing
+ * @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the
+ *	start of the 802.11 header in the @rx_mpdu_cmd
  */
 struct iwl_trans {
 	const struct iwl_trans_ops *ops;
@@ -457,9 +470,9 @@ struct iwl_trans {
 	u32 hw_id;
 	char hw_id_str[52];
 
-	bool pm_support;
+	u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
 
-	wait_queue_head_t wait_command_queue;
+	bool pm_support;
 
 	/* The following fields are internal only */
 	struct kmem_cache *dev_cmd_pool;
@@ -502,13 +515,13 @@ static inline void iwl_trans_stop_hw(struct iwl_trans *trans,
 	trans->state = IWL_TRANS_NO_FW;
 }
 
-static inline void iwl_trans_fw_alive(struct iwl_trans *trans)
+static inline void iwl_trans_fw_alive(struct iwl_trans *trans, u32 scd_addr)
 {
 	might_sleep();
 
 	trans->state = IWL_TRANS_FW_ALIVE;
 
-	trans->ops->fw_alive(trans);
+	trans->ops->fw_alive(trans, scd_addr);
 }
 
 static inline int iwl_trans_start_fw(struct iwl_trans *trans,
@@ -516,6 +529,8 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans,
 {
 	might_sleep();
 
+	WARN_ON_ONCE(!trans->rx_mpdu_cmd);
+
 	return trans->ops->start_fw(trans, fw);
 }
 
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index 2a46753..956fe6c 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -69,7 +69,6 @@
 
 #include "iwl-trans.h"
 #include "iwl-drv.h"
-#include "iwl-trans.h"
 
 #include "cfg.h"
 #include "internal.h"
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index 401178f..d91d2e8 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -73,7 +73,7 @@ struct isr_statistics {
 };
 
 /**
- * struct iwl_rx_queue - Rx queue
+ * struct iwl_rxq - Rx queue
  * @bd: driver's pointer to buffer of receive buffer descriptors (rbd)
  * @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
  * @pool:
@@ -91,7 +91,7 @@ struct isr_statistics {
  *
  * NOTE:  rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
  */
-struct iwl_rx_queue {
+struct iwl_rxq {
 	__le32 *bd;
 	dma_addr_t bd_dma;
 	struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
@@ -157,8 +157,8 @@ struct iwl_cmd_meta {
  * 32 since we don't need so many commands pending. Since the HW
  * still uses 256 BDs for DMA though, n_bd stays 256. As a result,
  * the software buffers (in the variables @meta, @txb in struct
- * iwl_tx_queue) only have 32 entries, while the HW buffers (@tfds
- * in the same struct) have 256.
+ * iwl_txq) only have 32 entries, while the HW buffers (@tfds in
+ * the same struct) have 256.
  * This means that we end up with the following:
  *  HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 |
  *  SW entries:           | 0      | ... | 31          |
@@ -182,15 +182,17 @@ struct iwl_queue {
 #define TFD_TX_CMD_SLOTS 256
 #define TFD_CMD_SLOTS 32
 
-struct iwl_pcie_tx_queue_entry {
+struct iwl_pcie_txq_entry {
 	struct iwl_device_cmd *cmd;
 	struct iwl_device_cmd *copy_cmd;
 	struct sk_buff *skb;
+	/* buffer to free after command completes */
+	const void *free_buf;
 	struct iwl_cmd_meta meta;
 };
 
 /**
- * struct iwl_tx_queue - Tx Queue for DMA
+ * struct iwl_txq - Tx Queue for DMA
  * @q: generic Rx/Tx queue descriptor
  * @tfds: transmit frame descriptors (DMA memory)
  * @entries: transmit entries (driver state)
@@ -203,10 +205,10 @@ struct iwl_pcie_tx_queue_entry {
  * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
  * descriptors) and required locking structures.
  */
-struct iwl_tx_queue {
+struct iwl_txq {
 	struct iwl_queue q;
 	struct iwl_tfd *tfds;
-	struct iwl_pcie_tx_queue_entry *entries;
+	struct iwl_pcie_txq_entry *entries;
 	spinlock_t lock;
 	struct timer_list stuck_timer;
 	struct iwl_trans_pcie *trans_pcie;
@@ -236,7 +238,7 @@ struct iwl_tx_queue {
  * @wd_timeout: queue watchdog timeout (jiffies)
  */
 struct iwl_trans_pcie {
-	struct iwl_rx_queue rxq;
+	struct iwl_rxq rxq;
 	struct work_struct rx_replenish;
 	struct iwl_trans *trans;
 	struct iwl_drv *drv;
@@ -258,7 +260,7 @@ struct iwl_trans_pcie {
 	struct iwl_dma_ptr scd_bc_tbls;
 	struct iwl_dma_ptr kw;
 
-	struct iwl_tx_queue *txq;
+	struct iwl_txq *txq;
 	unsigned long queue_used[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
 	unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
 
@@ -268,6 +270,8 @@ struct iwl_trans_pcie {
 
 	bool ucode_write_complete;
 	wait_queue_head_t ucode_write_waitq;
+	wait_queue_head_t wait_command_queue;
+
 	unsigned long status;
 	u8 cmd_queue;
 	u8 cmd_fifo;
@@ -283,13 +287,23 @@ struct iwl_trans_pcie {
 	unsigned long wd_timeout;
 };
 
-/*****************************************************
-* DRIVER STATUS FUNCTIONS
-******************************************************/
-#define STATUS_HCMD_ACTIVE	0
-#define STATUS_DEVICE_ENABLED	1
-#define STATUS_TPOWER_PMI	2
-#define STATUS_INT_ENABLED	3
+/**
+ * enum iwl_pcie_status: status of the PCIe transport
+ * @STATUS_HCMD_ACTIVE: a SYNC command is being processed
+ * @STATUS_DEVICE_ENABLED: APM is enabled
+ * @STATUS_TPOWER_PMI: the device might be asleep (need to wake it up)
+ * @STATUS_INT_ENABLED: interrupts are enabled
+ * @STATUS_RFKILL: the HW RFkill switch is in KILL position
+ * @STATUS_FW_ERROR: the fw is in error state
+ */
+enum iwl_pcie_status {
+	STATUS_HCMD_ACTIVE,
+	STATUS_DEVICE_ENABLED,
+	STATUS_TPOWER_PMI,
+	STATUS_INT_ENABLED,
+	STATUS_RFKILL,
+	STATUS_FW_ERROR,
+};
 
 #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
 	((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific))
@@ -301,6 +315,10 @@ iwl_trans_pcie_get_trans(struct iwl_trans_pcie *trans_pcie)
 			    trans_specific);
 }
 
+/*
+ * Convention: trans API functions: iwl_trans_pcie_XXX
+ *	Other functions: iwl_pcie_XXX
+ */
 struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
 				       const struct pci_device_id *ent,
 				       const struct iwl_cfg *cfg);
@@ -309,50 +327,43 @@ void iwl_trans_pcie_free(struct iwl_trans *trans);
 /*****************************************************
 * RX
 ******************************************************/
-void iwl_bg_rx_replenish(struct work_struct *data);
-void iwl_irq_tasklet(struct iwl_trans *trans);
-void iwl_rx_replenish(struct iwl_trans *trans);
-void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
-				   struct iwl_rx_queue *q);
+int iwl_pcie_rx_init(struct iwl_trans *trans);
+void iwl_pcie_tasklet(struct iwl_trans *trans);
+int iwl_pcie_rx_stop(struct iwl_trans *trans);
+void iwl_pcie_rx_free(struct iwl_trans *trans);
 
 /*****************************************************
-* ICT
+* ICT - interrupt handling
 ******************************************************/
-void iwl_reset_ict(struct iwl_trans *trans);
-void iwl_disable_ict(struct iwl_trans *trans);
-int iwl_alloc_isr_ict(struct iwl_trans *trans);
-void iwl_free_isr_ict(struct iwl_trans *trans);
-irqreturn_t iwl_isr_ict(int irq, void *data);
+irqreturn_t iwl_pcie_isr_ict(int irq, void *data);
+int iwl_pcie_alloc_ict(struct iwl_trans *trans);
+void iwl_pcie_free_ict(struct iwl_trans *trans);
+void iwl_pcie_reset_ict(struct iwl_trans *trans);
+void iwl_pcie_disable_ict(struct iwl_trans *trans);
 
 /*****************************************************
 * TX / HCMD
 ******************************************************/
-void iwl_txq_update_write_ptr(struct iwl_trans *trans,
-			      struct iwl_tx_queue *txq);
-int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
-				 struct iwl_tx_queue *txq,
-				 dma_addr_t addr, u16 len, u8 reset);
-int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id);
-int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
-void iwl_tx_cmd_complete(struct iwl_trans *trans,
-			 struct iwl_rx_cmd_buffer *rxb, int handler_status);
-void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
-				       struct iwl_tx_queue *txq,
-				       u16 byte_cnt);
+int iwl_pcie_tx_init(struct iwl_trans *trans);
+void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr);
+int iwl_pcie_tx_stop(struct iwl_trans *trans);
+void iwl_pcie_tx_free(struct iwl_trans *trans);
 void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
 			       int sta_id, int tid, int frame_limit, u16 ssn);
 void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue);
-void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
-		      enum dma_data_direction dma_dir);
-int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
-			 struct sk_buff_head *skbs);
-int iwl_queue_space(const struct iwl_queue *q);
-
+int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
+		      struct iwl_device_cmd *dev_cmd, int txq_id);
+void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq);
+int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
+void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
+			    struct iwl_rx_cmd_buffer *rxb, int handler_status);
+void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
+			    struct sk_buff_head *skbs);
 /*****************************************************
 * Error handling
 ******************************************************/
-int iwl_dump_fh(struct iwl_trans *trans, char **buf);
-void iwl_dump_csr(struct iwl_trans *trans);
+int iwl_pcie_dump_fh(struct iwl_trans *trans, char **buf);
+void iwl_pcie_dump_csr(struct iwl_trans *trans);
 
 /*****************************************************
 * Helpers
@@ -388,7 +399,7 @@ static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
 }
 
 static inline void iwl_wake_queue(struct iwl_trans *trans,
-				  struct iwl_tx_queue *txq)
+				  struct iwl_txq *txq)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
@@ -399,7 +410,7 @@ static inline void iwl_wake_queue(struct iwl_trans *trans,
 }
 
 static inline void iwl_stop_queue(struct iwl_trans *trans,
-				  struct iwl_tx_queue *txq)
+				  struct iwl_txq *txq)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
@@ -411,7 +422,7 @@ static inline void iwl_stop_queue(struct iwl_trans *trans,
 				    txq->q.id);
 }
 
-static inline int iwl_queue_used(const struct iwl_queue *q, int i)
+static inline bool iwl_queue_used(const struct iwl_queue *q, int i)
 {
 	return q->write_ptr >= q->read_ptr ?
 		(i >= q->read_ptr && i < q->write_ptr) :
@@ -423,8 +434,8 @@ static inline u8 get_cmd_index(struct iwl_queue *q, u32 index)
 	return index & (q->n_window - 1);
 }
 
-static inline const char *
-trans_pcie_get_cmd_string(struct iwl_trans_pcie *trans_pcie, u8 cmd)
+static inline const char *get_cmd_string(struct iwl_trans_pcie *trans_pcie,
+					 u8 cmd)
 {
 	if (!trans_pcie->command_names || !trans_pcie->command_names[cmd])
 		return "UNKNOWN";
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index bb69f8f..bb32510 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -76,7 +76,7 @@
  * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free.  When
  *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
  *   to replenish the iwl->rxq->rx_free.
- * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the
+ * + In iwl_pcie_rx_replenish (scheduled) if 'processed' != 'read' then the
  *   iwl->rxq is replenished and the READ INDEX is updated (updating the
  *   'processed' and 'read' driver indexes as well)
  * + A received packet is processed and handed to the kernel network stack,
@@ -89,28 +89,28 @@
  *
  * Driver sequence:
  *
- * iwl_rx_queue_alloc()   Allocates rx_free
- * iwl_rx_replenish()     Replenishes rx_free list from rx_used, and calls
- *                            iwl_rx_queue_restock
- * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx
+ * iwl_rxq_alloc()            Allocates rx_free
+ * iwl_pcie_rx_replenish()    Replenishes rx_free list from rx_used, and calls
+ *                            iwl_pcie_rxq_restock
+ * iwl_pcie_rxq_restock()     Moves available buffers from rx_free into Rx
  *                            queue, updates firmware pointers, and updates
  *                            the WRITE index.  If insufficient rx_free buffers
- *                            are available, schedules iwl_rx_replenish
+ *                            are available, schedules iwl_pcie_rx_replenish
  *
  * -- enable interrupts --
- * ISR - iwl_rx()         Detach iwl_rx_mem_buffers from pool up to the
+ * ISR - iwl_rx()             Detach iwl_rx_mem_buffers from pool up to the
  *                            READ INDEX, detaching the SKB from the pool.
  *                            Moves the packet buffer from queue to rx_used.
- *                            Calls iwl_rx_queue_restock to refill any empty
+ *                            Calls iwl_pcie_rxq_restock to refill any empty
  *                            slots.
  * ...
  *
  */
 
-/**
- * iwl_rx_queue_space - Return number of free slots available in queue.
+/*
+ * iwl_rxq_space - Return number of free slots available in queue.
  */
-static int iwl_rx_queue_space(const struct iwl_rx_queue *q)
+static int iwl_rxq_space(const struct iwl_rxq *q)
 {
 	int s = q->read - q->write;
 	if (s <= 0)
@@ -122,11 +122,28 @@ static int iwl_rx_queue_space(const struct iwl_rx_queue *q)
 	return s;
 }
 
-/**
- * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
+/*
+ * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
+ */
+static inline __le32 iwl_pcie_dma_addr2rbd_ptr(dma_addr_t dma_addr)
+{
+	return cpu_to_le32((u32)(dma_addr >> 8));
+}
+
+/*
+ * iwl_pcie_rx_stop - stops the Rx DMA
+ */
+int iwl_pcie_rx_stop(struct iwl_trans *trans)
+{
+	iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+	return iwl_poll_direct_bit(trans, FH_MEM_RSSR_RX_STATUS_REG,
+				   FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
+}
+
+/*
+ * iwl_pcie_rxq_inc_wr_ptr - Update the write pointer for the RX queue
  */
-void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
-				   struct iwl_rx_queue *q)
+static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_rxq *q)
 {
 	unsigned long flags;
 	u32 reg;
@@ -176,16 +193,8 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
 	spin_unlock_irqrestore(&q->lock, flags);
 }
 
-/**
- * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
- */
-static inline __le32 iwl_dma_addr2rbd_ptr(dma_addr_t dma_addr)
-{
-	return cpu_to_le32((u32)(dma_addr >> 8));
-}
-
-/**
- * iwl_rx_queue_restock - refill RX queue from pre-allocated pool
+/*
+ * iwl_pcie_rxq_restock - refill RX queue from pre-allocated pool
  *
  * If there are slots in the RX queue that need to be restocked,
  * and we have free pre-allocated buffers, fill the ranks as much
@@ -195,11 +204,10 @@ static inline __le32 iwl_dma_addr2rbd_ptr(dma_addr_t dma_addr)
  * also updates the memory address in the firmware to reference the new
  * target buffer.
  */
-static void iwl_rx_queue_restock(struct iwl_trans *trans)
+static void iwl_pcie_rxq_restock(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-	struct list_head *element;
+	struct iwl_rxq *rxq = &trans_pcie->rxq;
 	struct iwl_rx_mem_buffer *rxb;
 	unsigned long flags;
 
@@ -215,18 +223,18 @@ static void iwl_rx_queue_restock(struct iwl_trans *trans)
 		return;
 
 	spin_lock_irqsave(&rxq->lock, flags);
-	while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
+	while ((iwl_rxq_space(rxq) > 0) && (rxq->free_count)) {
 		/* The overwritten rxb must be a used one */
 		rxb = rxq->queue[rxq->write];
 		BUG_ON(rxb && rxb->page);
 
 		/* Get next free Rx buffer, remove from free list */
-		element = rxq->rx_free.next;
-		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-		list_del(element);
+		rxb = list_first_entry(&rxq->rx_free, struct iwl_rx_mem_buffer,
+				       list);
+		list_del(&rxb->list);
 
 		/* Point to Rx buffer via next RBD in circular buffer */
-		rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(rxb->page_dma);
+		rxq->bd[rxq->write] = iwl_pcie_dma_addr2rbd_ptr(rxb->page_dma);
 		rxq->queue[rxq->write] = rxb;
 		rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
 		rxq->free_count--;
@@ -243,24 +251,23 @@ static void iwl_rx_queue_restock(struct iwl_trans *trans)
 		spin_lock_irqsave(&rxq->lock, flags);
 		rxq->need_update = 1;
 		spin_unlock_irqrestore(&rxq->lock, flags);
-		iwl_rx_queue_update_write_ptr(trans, rxq);
+		iwl_pcie_rxq_inc_wr_ptr(trans, rxq);
 	}
 }
 
 /*
- * iwl_rx_allocate - allocate a page for each used RBD
+ * iwl_pcie_rxq_alloc_rbs - allocate a page for each used RBD
  *
  * A used RBD is an Rx buffer that has been given to the stack. To use it again
  * a page must be allocated and the RBD must point to the page. This function
  * doesn't change the HW pointer but handles the list of pages that is used by
- * iwl_rx_queue_restock. The latter function will update the HW to use the newly
+ * iwl_pcie_rxq_restock. The latter function will update the HW to use the newly
  * allocated buffers.
  */
-static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority)
+static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-	struct list_head *element;
+	struct iwl_rxq *rxq = &trans_pcie->rxq;
 	struct iwl_rx_mem_buffer *rxb;
 	struct page *page;
 	unsigned long flags;
@@ -308,10 +315,9 @@ static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority)
 			__free_pages(page, trans_pcie->rx_page_order);
 			return;
 		}
-		element = rxq->rx_used.next;
-		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-		list_del(element);
-
+		rxb = list_first_entry(&rxq->rx_used, struct iwl_rx_mem_buffer,
+				       list);
+		list_del(&rxb->list);
 		spin_unlock_irqrestore(&rxq->lock, flags);
 
 		BUG_ON(rxb->page);
@@ -343,47 +349,227 @@ static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority)
 	}
 }
 
+static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	struct iwl_rxq *rxq = &trans_pcie->rxq;
+	int i;
+
+	/* Fill the rx_used queue with _all_ of the Rx buffers */
+	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
+		/* In the reset function, these buffers may have been allocated
+		 * to an SKB, so we need to unmap and free potential storage */
+		if (rxq->pool[i].page != NULL) {
+			dma_unmap_page(trans->dev, rxq->pool[i].page_dma,
+				       PAGE_SIZE << trans_pcie->rx_page_order,
+				       DMA_FROM_DEVICE);
+			__free_pages(rxq->pool[i].page,
+				     trans_pcie->rx_page_order);
+			rxq->pool[i].page = NULL;
+		}
+		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+	}
+}
+
 /*
- * iwl_rx_replenish - Move all used buffers from rx_used to rx_free
+ * iwl_pcie_rx_replenish - Move all used buffers from rx_used to rx_free
  *
  * When moving to rx_free an page is allocated for the slot.
  *
- * Also restock the Rx queue via iwl_rx_queue_restock.
+ * Also restock the Rx queue via iwl_pcie_rxq_restock.
  * This is called as a scheduled work item (except for during initialization)
  */
-void iwl_rx_replenish(struct iwl_trans *trans)
+static void iwl_pcie_rx_replenish(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	unsigned long flags;
 
-	iwl_rx_allocate(trans, GFP_KERNEL);
+	iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL);
 
 	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
-	iwl_rx_queue_restock(trans);
+	iwl_pcie_rxq_restock(trans);
 	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 }
 
-static void iwl_rx_replenish_now(struct iwl_trans *trans)
+static void iwl_pcie_rx_replenish_now(struct iwl_trans *trans)
 {
-	iwl_rx_allocate(trans, GFP_ATOMIC);
+	iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC);
 
-	iwl_rx_queue_restock(trans);
+	iwl_pcie_rxq_restock(trans);
 }
 
-void iwl_bg_rx_replenish(struct work_struct *data)
+static void iwl_pcie_rx_replenish_work(struct work_struct *data)
 {
 	struct iwl_trans_pcie *trans_pcie =
 	    container_of(data, struct iwl_trans_pcie, rx_replenish);
 
-	iwl_rx_replenish(trans_pcie->trans);
+	iwl_pcie_rx_replenish(trans_pcie->trans);
+}
+
+static int iwl_pcie_rx_alloc(struct iwl_trans *trans)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	struct iwl_rxq *rxq = &trans_pcie->rxq;
+	struct device *dev = trans->dev;
+
+	memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq));
+
+	spin_lock_init(&rxq->lock);
+
+	if (WARN_ON(rxq->bd || rxq->rb_stts))
+		return -EINVAL;
+
+	/* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */
+	rxq->bd = dma_zalloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
+				      &rxq->bd_dma, GFP_KERNEL);
+	if (!rxq->bd)
+		goto err_bd;
+
+	/*Allocate the driver's pointer to receive buffer status */
+	rxq->rb_stts = dma_zalloc_coherent(dev, sizeof(*rxq->rb_stts),
+					   &rxq->rb_stts_dma, GFP_KERNEL);
+	if (!rxq->rb_stts)
+		goto err_rb_stts;
+
+	return 0;
+
+err_rb_stts:
+	dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
+			  rxq->bd, rxq->bd_dma);
+	memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
+	rxq->bd = NULL;
+err_bd:
+	return -ENOMEM;
+}
+
+static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	u32 rb_size;
+	const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
+
+	if (trans_pcie->rx_buf_size_8k)
+		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
+	else
+		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
+
+	/* Stop Rx DMA */
+	iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+
+	/* Reset driver's Rx queue write index */
+	iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
+
+	/* Tell device where to find RBD circular buffer in DRAM */
+	iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
+			   (u32)(rxq->bd_dma >> 8));
+
+	/* Tell device where in DRAM to update its Rx status */
+	iwl_write_direct32(trans, FH_RSCSR_CHNL0_STTS_WPTR_REG,
+			   rxq->rb_stts_dma >> 4);
+
+	/* Enable Rx DMA
+	 * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in
+	 *      the credit mechanism in 5000 HW RX FIFO
+	 * Direct rx interrupts to hosts
+	 * Rx buffer size 4 or 8k
+	 * RB timeout 0x10
+	 * 256 RBDs
+	 */
+	iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG,
+			   FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
+			   FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY |
+			   FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
+			   rb_size|
+			   (RX_RB_TIMEOUT << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
+			   (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
+
+	/* Set interrupt coalescing timer to default (2048 usecs) */
+	iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
+}
+
+int iwl_pcie_rx_init(struct iwl_trans *trans)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	struct iwl_rxq *rxq = &trans_pcie->rxq;
+
+	int i, err;
+	unsigned long flags;
+
+	if (!rxq->bd) {
+		err = iwl_pcie_rx_alloc(trans);
+		if (err)
+			return err;
+	}
+
+	spin_lock_irqsave(&rxq->lock, flags);
+	INIT_LIST_HEAD(&rxq->rx_free);
+	INIT_LIST_HEAD(&rxq->rx_used);
+
+	INIT_WORK(&trans_pcie->rx_replenish,
+		  iwl_pcie_rx_replenish_work);
+
+	iwl_pcie_rxq_free_rbs(trans);
+
+	for (i = 0; i < RX_QUEUE_SIZE; i++)
+		rxq->queue[i] = NULL;
+
+	/* Set us so that we have processed and used all buffers, but have
+	 * not restocked the Rx queue with fresh buffers */
+	rxq->read = rxq->write = 0;
+	rxq->write_actual = 0;
+	rxq->free_count = 0;
+	spin_unlock_irqrestore(&rxq->lock, flags);
+
+	iwl_pcie_rx_replenish(trans);
+
+	iwl_pcie_rx_hw_init(trans, rxq);
+
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+	rxq->need_update = 1;
+	iwl_pcie_rxq_inc_wr_ptr(trans, rxq);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+
+	return 0;
+}
+
+void iwl_pcie_rx_free(struct iwl_trans *trans)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	struct iwl_rxq *rxq = &trans_pcie->rxq;
+	unsigned long flags;
+
+	/*if rxq->bd is NULL, it means that nothing has been allocated,
+	 * exit now */
+	if (!rxq->bd) {
+		IWL_DEBUG_INFO(trans, "Free NULL rx context\n");
+		return;
+	}
+
+	spin_lock_irqsave(&rxq->lock, flags);
+	iwl_pcie_rxq_free_rbs(trans);
+	spin_unlock_irqrestore(&rxq->lock, flags);
+
+	dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE,
+			  rxq->bd, rxq->bd_dma);
+	memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
+	rxq->bd = NULL;
+
+	if (rxq->rb_stts)
+		dma_free_coherent(trans->dev,
+				  sizeof(struct iwl_rb_status),
+				  rxq->rb_stts, rxq->rb_stts_dma);
+	else
+		IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n");
+	memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma));
+	rxq->rb_stts = NULL;
 }
 
-static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
+static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
 				struct iwl_rx_mem_buffer *rxb)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-	struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
+	struct iwl_rxq *rxq = &trans_pcie->rxq;
+	struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
 	unsigned long flags;
 	bool page_stolen = false;
 	int max_len = PAGE_SIZE << trans_pcie->rx_page_order;
@@ -413,13 +599,13 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
 			break;
 
 		IWL_DEBUG_RX(trans, "cmd at offset %d: %s (0x%.2x)\n",
-			rxcb._offset,
-			trans_pcie_get_cmd_string(trans_pcie, pkt->hdr.cmd),
+			rxcb._offset, get_cmd_string(trans_pcie, pkt->hdr.cmd),
 			pkt->hdr.cmd);
 
 		len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
 		len += sizeof(u32); /* account for status word */
-		trace_iwlwifi_dev_rx(trans->dev, pkt, len);
+		trace_iwlwifi_dev_rx(trans->dev, trans, pkt, len);
+		trace_iwlwifi_dev_rx_data(trans->dev, trans, pkt, len);
 
 		/* Reclaim a command buffer only if this packet is a response
 		 *   to a (driver-originated) command.
@@ -445,7 +631,7 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
 		cmd_index = get_cmd_index(&txq->q, index);
 
 		if (reclaim) {
-			struct iwl_pcie_tx_queue_entry *ent;
+			struct iwl_pcie_txq_entry *ent;
 			ent = &txq->entries[cmd_index];
 			cmd = ent->copy_cmd;
 			WARN_ON_ONCE(!cmd && ent->meta.flags & CMD_WANT_HCMD);
@@ -459,6 +645,9 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
 			/* The original command isn't needed any more */
 			kfree(txq->entries[cmd_index].copy_cmd);
 			txq->entries[cmd_index].copy_cmd = NULL;
+			/* nor is the duplicated part of the command */
+			kfree(txq->entries[cmd_index].free_buf);
+			txq->entries[cmd_index].free_buf = NULL;
 		}
 
 		/*
@@ -472,7 +661,7 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
 			 * iwl_trans_send_cmd()
 			 * as we reclaim the driver command queue */
 			if (!rxcb._page_stolen)
-				iwl_tx_cmd_complete(trans, &rxcb, err);
+				iwl_pcie_hcmd_complete(trans, &rxcb, err);
 			else
 				IWL_WARN(trans, "Claim null rxb?\n");
 		}
@@ -514,17 +703,13 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
 	spin_unlock_irqrestore(&rxq->lock, flags);
 }
 
-/**
- * iwl_rx_handle - Main entry function for receiving responses from uCode
- *
- * Uses the priv->rx_handlers callback function array to invoke
- * the appropriate handlers, including command responses,
- * frame-received notifications, and other notifications.
+/*
+ * iwl_pcie_rx_handle - Main entry function for receiving responses from fw
  */
-static void iwl_rx_handle(struct iwl_trans *trans)
+static void iwl_pcie_rx_handle(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_rx_queue *rxq = &trans_pcie->rxq;
+	struct iwl_rxq *rxq = &trans_pcie->rxq;
 	u32 r, i;
 	u8 fill_rx = 0;
 	u32 count = 8;
@@ -555,7 +740,7 @@ static void iwl_rx_handle(struct iwl_trans *trans)
 
 		IWL_DEBUG_RX(trans, "rxbuf: HW = %d, SW = %d (%p)\n",
 			     r, i, rxb);
-		iwl_rx_handle_rxbuf(trans, rxb);
+		iwl_pcie_rx_handle_rb(trans, rxb);
 
 		i = (i + 1) & RX_QUEUE_MASK;
 		/* If there are a lot of unused frames,
@@ -564,7 +749,7 @@ static void iwl_rx_handle(struct iwl_trans *trans)
 			count++;
 			if (count >= 8) {
 				rxq->read = i;
-				iwl_rx_replenish_now(trans);
+				iwl_pcie_rx_replenish_now(trans);
 				count = 0;
 			}
 		}
@@ -573,39 +758,41 @@ static void iwl_rx_handle(struct iwl_trans *trans)
 	/* Backtrack one entry */
 	rxq->read = i;
 	if (fill_rx)
-		iwl_rx_replenish_now(trans);
+		iwl_pcie_rx_replenish_now(trans);
 	else
-		iwl_rx_queue_restock(trans);
+		iwl_pcie_rxq_restock(trans);
 }
 
-/**
- * iwl_irq_handle_error - called for HW or SW error interrupt from card
+/*
+ * iwl_pcie_irq_handle_error - called for HW or SW error interrupt from card
  */
-static void iwl_irq_handle_error(struct iwl_trans *trans)
+static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
 {
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
 	/* W/A for WiFi/WiMAX coex and WiMAX own the RF */
 	if (trans->cfg->internal_wimax_coex &&
 	    (!(iwl_read_prph(trans, APMG_CLK_CTRL_REG) &
 			     APMS_CLK_VAL_MRB_FUNC_MODE) ||
 	     (iwl_read_prph(trans, APMG_PS_CTRL_REG) &
 			    APMG_PS_CTRL_VAL_RESET_REQ))) {
-		struct iwl_trans_pcie *trans_pcie =
-			IWL_TRANS_GET_PCIE_TRANS(trans);
-
 		clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
 		iwl_op_mode_wimax_active(trans->op_mode);
-		wake_up(&trans->wait_command_queue);
+		wake_up(&trans_pcie->wait_command_queue);
 		return;
 	}
 
-	iwl_dump_csr(trans);
-	iwl_dump_fh(trans, NULL);
+	iwl_pcie_dump_csr(trans);
+	iwl_pcie_dump_fh(trans, NULL);
+
+	set_bit(STATUS_FW_ERROR, &trans_pcie->status);
+	clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
+	wake_up(&trans_pcie->wait_command_queue);
 
 	iwl_op_mode_nic_error(trans->op_mode);
 }
 
-/* tasklet for iwlagn interrupt */
-void iwl_irq_tasklet(struct iwl_trans *trans)
+void iwl_pcie_tasklet(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
@@ -657,7 +844,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
 		iwl_disable_interrupts(trans);
 
 		isr_stats->hw++;
-		iwl_irq_handle_error(trans);
+		iwl_pcie_irq_handle_error(trans);
 
 		handled |= CSR_INT_BIT_HW_ERR;
 
@@ -694,6 +881,16 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
 		isr_stats->rfkill++;
 
 		iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
+		if (hw_rfkill) {
+			set_bit(STATUS_RFKILL, &trans_pcie->status);
+			if (test_and_clear_bit(STATUS_HCMD_ACTIVE,
+					       &trans_pcie->status))
+				IWL_DEBUG_RF_KILL(trans,
+						  "Rfkill while SYNC HCMD in flight\n");
+			wake_up(&trans_pcie->wait_command_queue);
+		} else {
+			clear_bit(STATUS_RFKILL, &trans_pcie->status);
+		}
 
 		handled |= CSR_INT_BIT_RF_KILL;
 	}
@@ -710,17 +907,16 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
 		IWL_ERR(trans, "Microcode SW error detected. "
 			" Restarting 0x%X.\n", inta);
 		isr_stats->sw++;
-		iwl_irq_handle_error(trans);
+		iwl_pcie_irq_handle_error(trans);
 		handled |= CSR_INT_BIT_SW_ERR;
 	}
 
 	/* uCode wakes up after power-down sleep */
 	if (inta & CSR_INT_BIT_WAKEUP) {
 		IWL_DEBUG_ISR(trans, "Wakeup interrupt\n");
-		iwl_rx_queue_update_write_ptr(trans, &trans_pcie->rxq);
+		iwl_pcie_rxq_inc_wr_ptr(trans, &trans_pcie->rxq);
 		for (i = 0; i < trans->cfg->base_params->num_of_queues; i++)
-			iwl_txq_update_write_ptr(trans,
-						 &trans_pcie->txq[i]);
+			iwl_pcie_txq_inc_wr_ptr(trans, &trans_pcie->txq[i]);
 
 		isr_stats->wakeup++;
 
@@ -758,7 +954,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
 		iwl_write8(trans, CSR_INT_PERIODIC_REG,
 			    CSR_INT_PERIODIC_DIS);
 
-		iwl_rx_handle(trans);
+		iwl_pcie_rx_handle(trans);
 
 		/*
 		 * Enable periodic interrupt in 8 msec only if we received
@@ -816,7 +1012,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
 #define ICT_COUNT	(ICT_SIZE / sizeof(u32))
 
 /* Free dram table */
-void iwl_free_isr_ict(struct iwl_trans *trans)
+void iwl_pcie_free_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
@@ -829,13 +1025,12 @@ void iwl_free_isr_ict(struct iwl_trans *trans)
 	}
 }
 
-
 /*
  * allocate dram shared table, it is an aligned memory
  * block of ICT_SIZE.
  * also reset all data related to ICT table interrupt.
  */
-int iwl_alloc_isr_ict(struct iwl_trans *trans)
+int iwl_pcie_alloc_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
@@ -848,7 +1043,7 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans)
 
 	/* just an API sanity check ... it is guaranteed to be aligned */
 	if (WARN_ON(trans_pcie->ict_tbl_dma & (ICT_SIZE - 1))) {
-		iwl_free_isr_ict(trans);
+		iwl_pcie_free_ict(trans);
 		return -EINVAL;
 	}
 
@@ -869,7 +1064,7 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans)
 /* Device is going up inform it about using ICT interrupt table,
  * also we need to tell the driver to start using ICT interrupt.
  */
-void iwl_reset_ict(struct iwl_trans *trans)
+void iwl_pcie_reset_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	u32 val;
@@ -899,7 +1094,7 @@ void iwl_reset_ict(struct iwl_trans *trans)
 }
 
 /* Device is going down disable ict interrupt usage */
-void iwl_disable_ict(struct iwl_trans *trans)
+void iwl_pcie_disable_ict(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	unsigned long flags;
@@ -910,7 +1105,7 @@ void iwl_disable_ict(struct iwl_trans *trans)
 }
 
 /* legacy (non-ICT) ISR. Assumes that trans_pcie->irq_lock is held */
-static irqreturn_t iwl_isr(int irq, void *data)
+static irqreturn_t iwl_pcie_isr(int irq, void *data)
 {
 	struct iwl_trans *trans = data;
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -957,7 +1152,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
 #endif
 
 	trans_pcie->inta |= inta;
-	/* iwl_irq_tasklet() will service interrupts and re-enable them */
+	/* iwl_pcie_tasklet() will service interrupts and re-enable them */
 	if (likely(inta))
 		tasklet_schedule(&trans_pcie->irq_tasklet);
 	else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
@@ -982,7 +1177,7 @@ none:
  * the interrupt we need to service, driver will set the entries back to 0 and
  * set index.
  */
-irqreturn_t iwl_isr_ict(int irq, void *data)
+irqreturn_t iwl_pcie_isr_ict(int irq, void *data)
 {
 	struct iwl_trans *trans = data;
 	struct iwl_trans_pcie *trans_pcie;
@@ -1002,14 +1197,13 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
 	 * use legacy interrupt.
 	 */
 	if (unlikely(!trans_pcie->use_ict)) {
-		irqreturn_t ret = iwl_isr(irq, data);
+		irqreturn_t ret = iwl_pcie_isr(irq, data);
 		spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 		return ret;
 	}
 
 	trace_iwlwifi_dev_irq(trans->dev);
 
-
 	/* Disable (but don't clear!) interrupts here to avoid
 	 * back-to-back ISRs and sporadic interrupts from our NIC.
 	 * If we have something to service, the tasklet will re-enable ints.
@@ -1018,7 +1212,6 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
 	inta_mask = iwl_read32(trans, CSR_INT_MASK);  /* just for debug */
 	iwl_write32(trans, CSR_INT_MASK, 0x00000000);
 
-
 	/* Ignore interrupt if there's nothing in NIC to service.
 	 * This may be due to IRQ shared with another device,
 	 * or due to sporadic interrupts thrown from our NIC. */
@@ -1067,7 +1260,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
 	inta &= trans_pcie->inta_mask;
 	trans_pcie->inta |= inta;
 
-	/* iwl_irq_tasklet() will service interrupts and re-enable them */
+	/* iwl_pcie_tasklet() will service interrupts and re-enable them */
 	if (likely(inta))
 		tasklet_schedule(&trans_pcie->irq_tasklet);
 	else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index fe0fffd..f6c21e7 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -74,584 +74,8 @@
 #include "iwl-prph.h"
 #include "iwl-agn-hw.h"
 #include "internal.h"
-/* FIXME: need to abstract out TX command (once we know what it looks like) */
-#include "dvm/commands.h"
 
-#define SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie)	\
-	(((1<<trans->cfg->base_params->num_of_queues) - 1) &\
-	(~(1<<(trans_pcie)->cmd_queue)))
-
-static int iwl_trans_rx_alloc(struct iwl_trans *trans)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-	struct device *dev = trans->dev;
-
-	memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq));
-
-	spin_lock_init(&rxq->lock);
-
-	if (WARN_ON(rxq->bd || rxq->rb_stts))
-		return -EINVAL;
-
-	/* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */
-	rxq->bd = dma_zalloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
-				      &rxq->bd_dma, GFP_KERNEL);
-	if (!rxq->bd)
-		goto err_bd;
-
-	/*Allocate the driver's pointer to receive buffer status */
-	rxq->rb_stts = dma_zalloc_coherent(dev, sizeof(*rxq->rb_stts),
-					   &rxq->rb_stts_dma, GFP_KERNEL);
-	if (!rxq->rb_stts)
-		goto err_rb_stts;
-
-	return 0;
-
-err_rb_stts:
-	dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
-			  rxq->bd, rxq->bd_dma);
-	memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
-	rxq->bd = NULL;
-err_bd:
-	return -ENOMEM;
-}
-
-static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-	int i;
-
-	/* Fill the rx_used queue with _all_ of the Rx buffers */
-	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
-		/* In the reset function, these buffers may have been allocated
-		 * to an SKB, so we need to unmap and free potential storage */
-		if (rxq->pool[i].page != NULL) {
-			dma_unmap_page(trans->dev, rxq->pool[i].page_dma,
-				       PAGE_SIZE << trans_pcie->rx_page_order,
-				       DMA_FROM_DEVICE);
-			__free_pages(rxq->pool[i].page,
-				     trans_pcie->rx_page_order);
-			rxq->pool[i].page = NULL;
-		}
-		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
-	}
-}
-
-static void iwl_trans_rx_hw_init(struct iwl_trans *trans,
-				 struct iwl_rx_queue *rxq)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	u32 rb_size;
-	const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
-	u32 rb_timeout = RX_RB_TIMEOUT; /* FIXME: RX_RB_TIMEOUT for all devices? */
-
-	if (trans_pcie->rx_buf_size_8k)
-		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
-	else
-		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
-
-	/* Stop Rx DMA */
-	iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-
-	/* Reset driver's Rx queue write index */
-	iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
-
-	/* Tell device where to find RBD circular buffer in DRAM */
-	iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
-			   (u32)(rxq->bd_dma >> 8));
-
-	/* Tell device where in DRAM to update its Rx status */
-	iwl_write_direct32(trans, FH_RSCSR_CHNL0_STTS_WPTR_REG,
-			   rxq->rb_stts_dma >> 4);
-
-	/* Enable Rx DMA
-	 * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in
-	 *      the credit mechanism in 5000 HW RX FIFO
-	 * Direct rx interrupts to hosts
-	 * Rx buffer size 4 or 8k
-	 * RB timeout 0x10
-	 * 256 RBDs
-	 */
-	iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG,
-			   FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
-			   FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY |
-			   FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
-			   rb_size|
-			   (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
-			   (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
-
-	/* Set interrupt coalescing timer to default (2048 usecs) */
-	iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
-}
-
-static int iwl_rx_init(struct iwl_trans *trans)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-
-	int i, err;
-	unsigned long flags;
-
-	if (!rxq->bd) {
-		err = iwl_trans_rx_alloc(trans);
-		if (err)
-			return err;
-	}
-
-	spin_lock_irqsave(&rxq->lock, flags);
-	INIT_LIST_HEAD(&rxq->rx_free);
-	INIT_LIST_HEAD(&rxq->rx_used);
-
-	iwl_trans_rxq_free_rx_bufs(trans);
-
-	for (i = 0; i < RX_QUEUE_SIZE; i++)
-		rxq->queue[i] = NULL;
-
-	/* Set us so that we have processed and used all buffers, but have
-	 * not restocked the Rx queue with fresh buffers */
-	rxq->read = rxq->write = 0;
-	rxq->write_actual = 0;
-	rxq->free_count = 0;
-	spin_unlock_irqrestore(&rxq->lock, flags);
-
-	iwl_rx_replenish(trans);
-
-	iwl_trans_rx_hw_init(trans, rxq);
-
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
-	rxq->need_update = 1;
-	iwl_rx_queue_update_write_ptr(trans, rxq);
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-
-	return 0;
-}
-
-static void iwl_trans_pcie_rx_free(struct iwl_trans *trans)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-	unsigned long flags;
-
-	/*if rxq->bd is NULL, it means that nothing has been allocated,
-	 * exit now */
-	if (!rxq->bd) {
-		IWL_DEBUG_INFO(trans, "Free NULL rx context\n");
-		return;
-	}
-
-	spin_lock_irqsave(&rxq->lock, flags);
-	iwl_trans_rxq_free_rx_bufs(trans);
-	spin_unlock_irqrestore(&rxq->lock, flags);
-
-	dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE,
-			  rxq->bd, rxq->bd_dma);
-	memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
-	rxq->bd = NULL;
-
-	if (rxq->rb_stts)
-		dma_free_coherent(trans->dev,
-				  sizeof(struct iwl_rb_status),
-				  rxq->rb_stts, rxq->rb_stts_dma);
-	else
-		IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n");
-	memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma));
-	rxq->rb_stts = NULL;
-}
-
-static int iwl_trans_rx_stop(struct iwl_trans *trans)
-{
-
-	/* stop Rx DMA */
-	iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-	return iwl_poll_direct_bit(trans, FH_MEM_RSSR_RX_STATUS_REG,
-				   FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
-}
-
-static int iwlagn_alloc_dma_ptr(struct iwl_trans *trans,
-				struct iwl_dma_ptr *ptr, size_t size)
-{
-	if (WARN_ON(ptr->addr))
-		return -EINVAL;
-
-	ptr->addr = dma_alloc_coherent(trans->dev, size,
-				       &ptr->dma, GFP_KERNEL);
-	if (!ptr->addr)
-		return -ENOMEM;
-	ptr->size = size;
-	return 0;
-}
-
-static void iwlagn_free_dma_ptr(struct iwl_trans *trans,
-				struct iwl_dma_ptr *ptr)
-{
-	if (unlikely(!ptr->addr))
-		return;
-
-	dma_free_coherent(trans->dev, ptr->size, ptr->addr, ptr->dma);
-	memset(ptr, 0, sizeof(*ptr));
-}
-
-static void iwl_trans_pcie_queue_stuck_timer(unsigned long data)
-{
-	struct iwl_tx_queue *txq = (void *)data;
-	struct iwl_queue *q = &txq->q;
-	struct iwl_trans_pcie *trans_pcie = txq->trans_pcie;
-	struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie);
-	u32 scd_sram_addr = trans_pcie->scd_base_addr +
-		SCD_TX_STTS_MEM_LOWER_BOUND + (16 * txq->q.id);
-	u8 buf[16];
-	int i;
-
-	spin_lock(&txq->lock);
-	/* check if triggered erroneously */
-	if (txq->q.read_ptr == txq->q.write_ptr) {
-		spin_unlock(&txq->lock);
-		return;
-	}
-	spin_unlock(&txq->lock);
-
-	IWL_ERR(trans, "Queue %d stuck for %u ms.\n", txq->q.id,
-		jiffies_to_msecs(trans_pcie->wd_timeout));
-	IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n",
-		txq->q.read_ptr, txq->q.write_ptr);
-
-	iwl_read_targ_mem_bytes(trans, scd_sram_addr, buf, sizeof(buf));
-
-	iwl_print_hex_error(trans, buf, sizeof(buf));
-
-	for (i = 0; i < FH_TCSR_CHNL_NUM; i++)
-		IWL_ERR(trans, "FH TRBs(%d) = 0x%08x\n", i,
-			iwl_read_direct32(trans, FH_TX_TRB_REG(i)));
-
-	for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) {
-		u32 status = iwl_read_prph(trans, SCD_QUEUE_STATUS_BITS(i));
-		u8 fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7;
-		bool active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE));
-		u32 tbl_dw =
-			iwl_read_targ_mem(trans,
-					  trans_pcie->scd_base_addr +
-					  SCD_TRANS_TBL_OFFSET_QUEUE(i));
-
-		if (i & 0x1)
-			tbl_dw = (tbl_dw & 0xFFFF0000) >> 16;
-		else
-			tbl_dw = tbl_dw & 0x0000FFFF;
-
-		IWL_ERR(trans,
-			"Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n",
-			i, active ? "" : "in", fifo, tbl_dw,
-			iwl_read_prph(trans,
-				      SCD_QUEUE_RDPTR(i)) & (txq->q.n_bd - 1),
-			iwl_read_prph(trans, SCD_QUEUE_WRPTR(i)));
-	}
-
-	for (i = q->read_ptr; i != q->write_ptr;
-	     i = iwl_queue_inc_wrap(i, q->n_bd)) {
-		struct iwl_tx_cmd *tx_cmd =
-			(struct iwl_tx_cmd *)txq->entries[i].cmd->payload;
-		IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
-			get_unaligned_le32(&tx_cmd->scratch));
-	}
-
-	iwl_op_mode_nic_error(trans->op_mode);
-}
-
-static int iwl_trans_txq_alloc(struct iwl_trans *trans,
-			       struct iwl_tx_queue *txq, int slots_num,
-			       u32 txq_id)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX;
-	int i;
-
-	if (WARN_ON(txq->entries || txq->tfds))
-		return -EINVAL;
-
-	setup_timer(&txq->stuck_timer, iwl_trans_pcie_queue_stuck_timer,
-		    (unsigned long)txq);
-	txq->trans_pcie = trans_pcie;
-
-	txq->q.n_window = slots_num;
-
-	txq->entries = kcalloc(slots_num,
-			       sizeof(struct iwl_pcie_tx_queue_entry),
-			       GFP_KERNEL);
-
-	if (!txq->entries)
-		goto error;
-
-	if (txq_id == trans_pcie->cmd_queue)
-		for (i = 0; i < slots_num; i++) {
-			txq->entries[i].cmd =
-				kmalloc(sizeof(struct iwl_device_cmd),
-					GFP_KERNEL);
-			if (!txq->entries[i].cmd)
-				goto error;
-		}
-
-	/* Circular buffer of transmit frame descriptors (TFDs),
-	 * shared with device */
-	txq->tfds = dma_alloc_coherent(trans->dev, tfd_sz,
-				       &txq->q.dma_addr, GFP_KERNEL);
-	if (!txq->tfds) {
-		IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz);
-		goto error;
-	}
-	txq->q.id = txq_id;
-
-	return 0;
-error:
-	if (txq->entries && txq_id == trans_pcie->cmd_queue)
-		for (i = 0; i < slots_num; i++)
-			kfree(txq->entries[i].cmd);
-	kfree(txq->entries);
-	txq->entries = NULL;
-
-	return -ENOMEM;
-
-}
-
-static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq,
-			      int slots_num, u32 txq_id)
-{
-	int ret;
-
-	txq->need_update = 0;
-
-	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
-	 * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
-	BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
-
-	/* Initialize queue's high/low-water marks, and head/tail indexes */
-	ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num,
-			txq_id);
-	if (ret)
-		return ret;
-
-	spin_lock_init(&txq->lock);
-
-	/*
-	 * Tell nic where to find circular buffer of Tx Frame Descriptors for
-	 * given Tx queue, and enable the DMA channel used for that queue.
-	 * Circular buffer (TFD queue in DRAM) physical base address */
-	iwl_write_direct32(trans, FH_MEM_CBBC_QUEUE(txq_id),
-			     txq->q.dma_addr >> 8);
-
-	return 0;
-}
-
-/**
- * iwl_tx_queue_unmap -  Unmap any remaining DMA mappings and free skb's
- */
-static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
-	struct iwl_queue *q = &txq->q;
-	enum dma_data_direction dma_dir;
-
-	if (!q->n_bd)
-		return;
-
-	/* In the command queue, all the TBs are mapped as BIDI
-	 * so unmap them as such.
-	 */
-	if (txq_id == trans_pcie->cmd_queue)
-		dma_dir = DMA_BIDIRECTIONAL;
-	else
-		dma_dir = DMA_TO_DEVICE;
-
-	spin_lock_bh(&txq->lock);
-	while (q->write_ptr != q->read_ptr) {
-		iwl_txq_free_tfd(trans, txq, dma_dir);
-		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
-	}
-	spin_unlock_bh(&txq->lock);
-}
-
-/**
- * iwl_tx_queue_free - Deallocate DMA queue.
- * @txq: Transmit queue to deallocate.
- *
- * Empty queue by removing and destroying all BD's.
- * Free all buffers.
- * 0-fill, but do not free "txq" descriptor structure.
- */
-static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
-	struct device *dev = trans->dev;
-	int i;
-
-	if (WARN_ON(!txq))
-		return;
-
-	iwl_tx_queue_unmap(trans, txq_id);
-
-	/* De-alloc array of command/tx buffers */
-	if (txq_id == trans_pcie->cmd_queue)
-		for (i = 0; i < txq->q.n_window; i++) {
-			kfree(txq->entries[i].cmd);
-			kfree(txq->entries[i].copy_cmd);
-		}
-
-	/* De-alloc circular buffer of TFDs */
-	if (txq->q.n_bd) {
-		dma_free_coherent(dev, sizeof(struct iwl_tfd) *
-				  txq->q.n_bd, txq->tfds, txq->q.dma_addr);
-		memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr));
-	}
-
-	kfree(txq->entries);
-	txq->entries = NULL;
-
-	del_timer_sync(&txq->stuck_timer);
-
-	/* 0-fill queue descriptor structure */
-	memset(txq, 0, sizeof(*txq));
-}
-
-/**
- * iwl_trans_tx_free - Free TXQ Context
- *
- * Destroy all TX DMA queues and structures
- */
-static void iwl_trans_pcie_tx_free(struct iwl_trans *trans)
-{
-	int txq_id;
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
-	/* Tx queues */
-	if (trans_pcie->txq) {
-		for (txq_id = 0;
-		     txq_id < trans->cfg->base_params->num_of_queues; txq_id++)
-			iwl_tx_queue_free(trans, txq_id);
-	}
-
-	kfree(trans_pcie->txq);
-	trans_pcie->txq = NULL;
-
-	iwlagn_free_dma_ptr(trans, &trans_pcie->kw);
-
-	iwlagn_free_dma_ptr(trans, &trans_pcie->scd_bc_tbls);
-}
-
-/**
- * iwl_trans_tx_alloc - allocate TX context
- * Allocate all Tx DMA structures and initialize them
- *
- * @param priv
- * @return error code
- */
-static int iwl_trans_tx_alloc(struct iwl_trans *trans)
-{
-	int ret;
-	int txq_id, slots_num;
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
-	u16 scd_bc_tbls_size = trans->cfg->base_params->num_of_queues *
-			sizeof(struct iwlagn_scd_bc_tbl);
-
-	/*It is not allowed to alloc twice, so warn when this happens.
-	 * We cannot rely on the previous allocation, so free and fail */
-	if (WARN_ON(trans_pcie->txq)) {
-		ret = -EINVAL;
-		goto error;
-	}
-
-	ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->scd_bc_tbls,
-				   scd_bc_tbls_size);
-	if (ret) {
-		IWL_ERR(trans, "Scheduler BC Table allocation failed\n");
-		goto error;
-	}
-
-	/* Alloc keep-warm buffer */
-	ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->kw, IWL_KW_SIZE);
-	if (ret) {
-		IWL_ERR(trans, "Keep Warm allocation failed\n");
-		goto error;
-	}
-
-	trans_pcie->txq = kcalloc(trans->cfg->base_params->num_of_queues,
-				  sizeof(struct iwl_tx_queue), GFP_KERNEL);
-	if (!trans_pcie->txq) {
-		IWL_ERR(trans, "Not enough memory for txq\n");
-		ret = ENOMEM;
-		goto error;
-	}
-
-	/* Alloc and init all Tx queues, including the command queue (#4/#9) */
-	for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
-	     txq_id++) {
-		slots_num = (txq_id == trans_pcie->cmd_queue) ?
-					TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-		ret = iwl_trans_txq_alloc(trans, &trans_pcie->txq[txq_id],
-					  slots_num, txq_id);
-		if (ret) {
-			IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id);
-			goto error;
-		}
-	}
-
-	return 0;
-
-error:
-	iwl_trans_pcie_tx_free(trans);
-
-	return ret;
-}
-static int iwl_tx_init(struct iwl_trans *trans)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	int ret;
-	int txq_id, slots_num;
-	unsigned long flags;
-	bool alloc = false;
-
-	if (!trans_pcie->txq) {
-		ret = iwl_trans_tx_alloc(trans);
-		if (ret)
-			goto error;
-		alloc = true;
-	}
-
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
-
-	/* Turn off all Tx DMA fifos */
-	iwl_write_prph(trans, SCD_TXFACT, 0);
-
-	/* Tell NIC where to find the "keep warm" buffer */
-	iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG,
-			   trans_pcie->kw.dma >> 4);
-
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-
-	/* Alloc and init all Tx queues, including the command queue (#4/#9) */
-	for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
-	     txq_id++) {
-		slots_num = (txq_id == trans_pcie->cmd_queue) ?
-					TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-		ret = iwl_trans_txq_init(trans, &trans_pcie->txq[txq_id],
-					 slots_num, txq_id);
-		if (ret) {
-			IWL_ERR(trans, "Tx %d queue init failed\n", txq_id);
-			goto error;
-		}
-	}
-
-	return 0;
-error:
-	/*Upon error, free only if we allocated something */
-	if (alloc)
-		iwl_trans_pcie_tx_free(trans);
-	return ret;
-}
-
-static void iwl_set_pwr_vmain(struct iwl_trans *trans)
+static void iwl_pcie_set_pwr_vmain(struct iwl_trans *trans)
 {
 /*
  * (for documentation purposes)
@@ -673,18 +97,11 @@ static void iwl_set_pwr_vmain(struct iwl_trans *trans)
 #define PCI_CFG_LINK_CTRL_VAL_L0S_EN	0x01
 #define PCI_CFG_LINK_CTRL_VAL_L1_EN	0x02
 
-static u16 iwl_pciexp_link_ctrl(struct iwl_trans *trans)
+static void iwl_pcie_apm_config(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	u16 pci_lnk_ctl;
-
-	pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL,
-				  &pci_lnk_ctl);
-	return pci_lnk_ctl;
-}
+	u16 lctl;
 
-static void iwl_apm_config(struct iwl_trans *trans)
-{
 	/*
 	 * HW bug W/A for instability in PCIe bus L0S->L1 transition.
 	 * Check if BIOS (or OS) enabled L1-ASPM on this device.
@@ -693,29 +110,27 @@ static void iwl_apm_config(struct iwl_trans *trans)
 	 * If not (unlikely), enable L0S, so there is at least some
 	 *    power savings, even without L1.
 	 */
-	u16 lctl = iwl_pciexp_link_ctrl(trans);
+	pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl);
 
 	if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
 				PCI_CFG_LINK_CTRL_VAL_L1_EN) {
 		/* L1-ASPM enabled; disable(!) L0S */
 		iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
-		dev_printk(KERN_INFO, trans->dev,
-			   "L1 Enabled; Disabling L0S\n");
+		dev_info(trans->dev, "L1 Enabled; Disabling L0S\n");
 	} else {
 		/* L1-ASPM disabled; enable(!) L0S */
 		iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
-		dev_printk(KERN_INFO, trans->dev,
-			   "L1 Disabled; Enabling L0S\n");
+		dev_info(trans->dev, "L1 Disabled; Enabling L0S\n");
 	}
 	trans->pm_support = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
 }
 
 /*
  * Start up NIC's basic functionality after it has been reset
- * (e.g. after platform boot, or shutdown via iwl_apm_stop())
+ * (e.g. after platform boot, or shutdown via iwl_pcie_apm_stop())
  * NOTE:  This does not load uCode nor start the embedded processor
  */
-static int iwl_apm_init(struct iwl_trans *trans)
+static int iwl_pcie_apm_init(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	int ret = 0;
@@ -747,7 +162,7 @@ static int iwl_apm_init(struct iwl_trans *trans)
 	iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
 		    CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
 
-	iwl_apm_config(trans);
+	iwl_pcie_apm_config(trans);
 
 	/* Configure analog phase-lock-loop before activating to D0A */
 	if (trans->cfg->base_params->pll_cfg_val)
@@ -793,7 +208,7 @@ out:
 	return ret;
 }
 
-static int iwl_apm_stop_master(struct iwl_trans *trans)
+static int iwl_pcie_apm_stop_master(struct iwl_trans *trans)
 {
 	int ret = 0;
 
@@ -811,7 +226,7 @@ static int iwl_apm_stop_master(struct iwl_trans *trans)
 	return ret;
 }
 
-static void iwl_apm_stop(struct iwl_trans *trans)
+static void iwl_pcie_apm_stop(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	IWL_DEBUG_INFO(trans, "Stop card, put in low power state\n");
@@ -819,7 +234,7 @@ static void iwl_apm_stop(struct iwl_trans *trans)
 	clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status);
 
 	/* Stop device's DMA activity */
-	iwl_apm_stop_master(trans);
+	iwl_pcie_apm_stop_master(trans);
 
 	/* Reset the entire device */
 	iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
@@ -834,29 +249,29 @@ static void iwl_apm_stop(struct iwl_trans *trans)
 		      CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
 }
 
-static int iwl_nic_init(struct iwl_trans *trans)
+static int iwl_pcie_nic_init(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	unsigned long flags;
 
 	/* nic_init */
 	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
-	iwl_apm_init(trans);
+	iwl_pcie_apm_init(trans);
 
 	/* Set interrupt coalescing calibration timer to default (512 usecs) */
 	iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF);
 
 	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
-	iwl_set_pwr_vmain(trans);
+	iwl_pcie_set_pwr_vmain(trans);
 
 	iwl_op_mode_nic_config(trans->op_mode);
 
 	/* Allocate the RX queue, or reset if it is already allocated */
-	iwl_rx_init(trans);
+	iwl_pcie_rx_init(trans);
 
 	/* Allocate or reset and init all Tx and Command queues */
-	if (iwl_tx_init(trans))
+	if (iwl_pcie_tx_init(trans))
 		return -ENOMEM;
 
 	if (trans->cfg->base_params->shadow_reg_enable) {
@@ -871,7 +286,7 @@ static int iwl_nic_init(struct iwl_trans *trans)
 #define HW_READY_TIMEOUT (50)
 
 /* Note: returns poll_bit return value, which is >= 0 if success */
-static int iwl_set_hw_ready(struct iwl_trans *trans)
+static int iwl_pcie_set_hw_ready(struct iwl_trans *trans)
 {
 	int ret;
 
@@ -889,14 +304,14 @@ static int iwl_set_hw_ready(struct iwl_trans *trans)
 }
 
 /* Note: returns standard 0/-ERROR code */
-static int iwl_prepare_card_hw(struct iwl_trans *trans)
+static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
 {
 	int ret;
 	int t = 0;
 
 	IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n");
 
-	ret = iwl_set_hw_ready(trans);
+	ret = iwl_pcie_set_hw_ready(trans);
 	/* If the card is ready, exit 0 */
 	if (ret >= 0)
 		return 0;
@@ -906,7 +321,7 @@ static int iwl_prepare_card_hw(struct iwl_trans *trans)
 		    CSR_HW_IF_CONFIG_REG_PREPARE);
 
 	do {
-		ret = iwl_set_hw_ready(trans);
+		ret = iwl_pcie_set_hw_ready(trans);
 		if (ret >= 0)
 			return 0;
 
@@ -920,7 +335,7 @@ static int iwl_prepare_card_hw(struct iwl_trans *trans)
 /*
  * ucode
  */
-static int iwl_load_firmware_chunk(struct iwl_trans *trans, u32 dst_addr,
+static int iwl_pcie_load_firmware_chunk(struct iwl_trans *trans, u32 dst_addr,
 				   dma_addr_t phy_addr, u32 byte_cnt)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -967,7 +382,7 @@ static int iwl_load_firmware_chunk(struct iwl_trans *trans, u32 dst_addr,
 	return 0;
 }
 
-static int iwl_load_section(struct iwl_trans *trans, u8 section_num,
+static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num,
 			    const struct fw_desc *section)
 {
 	u8 *v_addr;
@@ -988,8 +403,9 @@ static int iwl_load_section(struct iwl_trans *trans, u8 section_num,
 		copy_size = min_t(u32, PAGE_SIZE, section->len - offset);
 
 		memcpy(v_addr, (u8 *)section->data + offset, copy_size);
-		ret = iwl_load_firmware_chunk(trans, section->offset + offset,
-					      p_addr, copy_size);
+		ret = iwl_pcie_load_firmware_chunk(trans,
+						   section->offset + offset,
+						   p_addr, copy_size);
 		if (ret) {
 			IWL_ERR(trans,
 				"Could not load the [%d] uCode section\n",
@@ -1002,7 +418,7 @@ static int iwl_load_section(struct iwl_trans *trans, u8 section_num,
 	return ret;
 }
 
-static int iwl_load_given_ucode(struct iwl_trans *trans,
+static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
 				const struct fw_img *image)
 {
 	int i, ret = 0;
@@ -1011,7 +427,7 @@ static int iwl_load_given_ucode(struct iwl_trans *trans,
 		if (!image->sec[i].data)
 			break;
 
-		ret = iwl_load_section(trans, i, &image->sec[i]);
+		ret = iwl_pcie_load_section(trans, i, &image->sec[i]);
 		if (ret)
 			return ret;
 	}
@@ -1025,15 +441,18 @@ static int iwl_load_given_ucode(struct iwl_trans *trans,
 static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
 				   const struct fw_img *fw)
 {
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	int ret;
 	bool hw_rfkill;
 
 	/* This may fail if AMT took ownership of the device */
-	if (iwl_prepare_card_hw(trans)) {
+	if (iwl_pcie_prepare_card_hw(trans)) {
 		IWL_WARN(trans, "Exit HW not ready\n");
 		return -EIO;
 	}
 
+	clear_bit(STATUS_FW_ERROR, &trans_pcie->status);
+
 	iwl_enable_rfkill_int(trans);
 
 	/* If platform's RF_KILL switch is NOT set to KILL */
@@ -1044,7 +463,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
 
 	iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
 
-	ret = iwl_nic_init(trans);
+	ret = iwl_pcie_nic_init(trans);
 	if (ret) {
 		IWL_ERR(trans, "Unable to init nic\n");
 		return ret;
@@ -1064,125 +483,13 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
 	iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
 
 	/* Load the given image to the HW */
-	return iwl_load_given_ucode(trans, fw);
+	return iwl_pcie_load_given_ucode(trans, fw);
 }
 
-/*
- * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
- */
-static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask)
+static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
 {
-	struct iwl_trans_pcie __maybe_unused *trans_pcie =
-		IWL_TRANS_GET_PCIE_TRANS(trans);
-
-	iwl_write_prph(trans, SCD_TXFACT, mask);
-}
-
-static void iwl_tx_start(struct iwl_trans *trans)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	u32 a;
-	int chan;
-	u32 reg_val;
-
-	/* make sure all queue are not stopped/used */
-	memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped));
-	memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used));
-
-	trans_pcie->scd_base_addr =
-		iwl_read_prph(trans, SCD_SRAM_BASE_ADDR);
-	a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND;
-	/* reset conext data memory */
-	for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND;
-		a += 4)
-		iwl_write_targ_mem(trans, a, 0);
-	/* reset tx status memory */
-	for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND;
-		a += 4)
-		iwl_write_targ_mem(trans, a, 0);
-	for (; a < trans_pcie->scd_base_addr +
-	       SCD_TRANS_TBL_OFFSET_QUEUE(
-				trans->cfg->base_params->num_of_queues);
-	       a += 4)
-		iwl_write_targ_mem(trans, a, 0);
-
-	iwl_write_prph(trans, SCD_DRAM_BASE_ADDR,
-		       trans_pcie->scd_bc_tbls.dma >> 10);
-
-	/* The chain extension of the SCD doesn't work well. This feature is
-	 * enabled by default by the HW, so we need to disable it manually.
-	 */
-	iwl_write_prph(trans, SCD_CHAINEXT_EN, 0);
-
-	iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue,
-				trans_pcie->cmd_fifo);
-
-	/* Activate all Tx DMA/FIFO channels */
-	iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7));
-
-	/* Enable DMA channel */
-	for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++)
-		iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan),
-				   FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
-				   FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
-
-	/* Update FH chicken bits */
-	reg_val = iwl_read_direct32(trans, FH_TX_CHICKEN_BITS_REG);
-	iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG,
-			   reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
-
-	/* Enable L1-Active */
-	iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG,
-			    APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
-}
-
-static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans)
-{
-	iwl_reset_ict(trans);
-	iwl_tx_start(trans);
-}
-
-/**
- * iwlagn_txq_ctx_stop - Stop all Tx DMA channels
- */
-static int iwl_trans_tx_stop(struct iwl_trans *trans)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	int ch, txq_id, ret;
-	unsigned long flags;
-
-	/* Turn off all Tx DMA fifos */
-	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
-
-	iwl_trans_txq_set_sched(trans, 0);
-
-	/* Stop each Tx DMA channel, and wait for it to be idle */
-	for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) {
-		iwl_write_direct32(trans,
-				   FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
-		ret = iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG,
-			FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000);
-		if (ret < 0)
-			IWL_ERR(trans,
-				"Failing on timeout while stopping DMA channel %d [0x%08x]\n",
-				ch,
-				iwl_read_direct32(trans,
-						  FH_TSSR_TX_STATUS_REG));
-	}
-	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-
-	if (!trans_pcie->txq) {
-		IWL_WARN(trans,
-			 "Stopping tx queues that aren't allocated...\n");
-		return 0;
-	}
-
-	/* Unmap DMA from host system and free skb's */
-	for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
-	     txq_id++)
-		iwl_tx_queue_unmap(trans, txq_id);
-
-	return 0;
+	iwl_pcie_reset_ict(trans);
+	iwl_pcie_tx_start(trans, scd_addr);
 }
 
 static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
@@ -1196,7 +503,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
 	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
 	/* device going down, Stop using ICT table */
-	iwl_disable_ict(trans);
+	iwl_pcie_disable_ict(trans);
 
 	/*
 	 * If a HW restart happens during firmware loading,
@@ -1206,8 +513,8 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
 	 * already dead.
 	 */
 	if (test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) {
-		iwl_trans_tx_stop(trans);
-		iwl_trans_rx_stop(trans);
+		iwl_pcie_tx_stop(trans);
+		iwl_pcie_rx_stop(trans);
 
 		/* Power-down device's busmaster DMA clocks */
 		iwl_write_prph(trans, APMG_CLK_DIS_REG,
@@ -1220,7 +527,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
 		      CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 
 	/* Stop the device, and put it in low power state */
-	iwl_apm_stop(trans);
+	iwl_pcie_apm_stop(trans);
 
 	/* Upon stop, the APM issues an interrupt if HW RF kill is set.
 	 * Clean again the interrupt here
@@ -1245,6 +552,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
 	clear_bit(STATUS_INT_ENABLED, &trans_pcie->status);
 	clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status);
 	clear_bit(STATUS_TPOWER_PMI, &trans_pcie->status);
+	clear_bit(STATUS_RFKILL, &trans_pcie->status);
 }
 
 static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans)
@@ -1258,169 +566,6 @@ static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans)
 		      CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 }
 
-static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
-			     struct iwl_device_cmd *dev_cmd, int txq_id)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct iwl_tx_cmd *tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload;
-	struct iwl_cmd_meta *out_meta;
-	struct iwl_tx_queue *txq;
-	struct iwl_queue *q;
-	dma_addr_t phys_addr = 0;
-	dma_addr_t txcmd_phys;
-	dma_addr_t scratch_phys;
-	u16 len, firstlen, secondlen;
-	u8 wait_write_ptr = 0;
-	__le16 fc = hdr->frame_control;
-	u8 hdr_len = ieee80211_hdrlen(fc);
-	u16 __maybe_unused wifi_seq;
-
-	txq = &trans_pcie->txq[txq_id];
-	q = &txq->q;
-
-	if (unlikely(!test_bit(txq_id, trans_pcie->queue_used))) {
-		WARN_ON_ONCE(1);
-		return -EINVAL;
-	}
-
-	spin_lock(&txq->lock);
-
-	/* In AGG mode, the index in the ring must correspond to the WiFi
-	 * sequence number. This is a HW requirements to help the SCD to parse
-	 * the BA.
-	 * Check here that the packets are in the right place on the ring.
-	 */
-#ifdef CONFIG_IWLWIFI_DEBUG
-	wifi_seq = SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
-	WARN_ONCE((iwl_read_prph(trans, SCD_AGGR_SEL) & BIT(txq_id)) &&
-		  ((wifi_seq & 0xff) != q->write_ptr),
-		  "Q: %d WiFi Seq %d tfdNum %d",
-		  txq_id, wifi_seq, q->write_ptr);
-#endif
-
-	/* Set up driver data for this TFD */
-	txq->entries[q->write_ptr].skb = skb;
-	txq->entries[q->write_ptr].cmd = dev_cmd;
-
-	dev_cmd->hdr.cmd = REPLY_TX;
-	dev_cmd->hdr.sequence =
-		cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
-			    INDEX_TO_SEQ(q->write_ptr)));
-
-	/* Set up first empty entry in queue's array of Tx/cmd buffers */
-	out_meta = &txq->entries[q->write_ptr].meta;
-
-	/*
-	 * Use the first empty entry in this queue's command buffer array
-	 * to contain the Tx command and MAC header concatenated together
-	 * (payload data will be in another buffer).
-	 * Size of this varies, due to varying MAC header length.
-	 * If end is not dword aligned, we'll have 2 extra bytes at the end
-	 * of the MAC header (device reads on dword boundaries).
-	 * We'll tell device about this padding later.
-	 */
-	len = sizeof(struct iwl_tx_cmd) +
-		sizeof(struct iwl_cmd_header) + hdr_len;
-	firstlen = (len + 3) & ~3;
-
-	/* Tell NIC about any 2-byte padding after MAC header */
-	if (firstlen != len)
-		tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
-
-	/* Physical address of this Tx command's header (not MAC header!),
-	 * within command buffer array. */
-	txcmd_phys = dma_map_single(trans->dev,
-				    &dev_cmd->hdr, firstlen,
-				    DMA_BIDIRECTIONAL);
-	if (unlikely(dma_mapping_error(trans->dev, txcmd_phys)))
-		goto out_err;
-	dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
-	dma_unmap_len_set(out_meta, len, firstlen);
-
-	if (!ieee80211_has_morefrags(fc)) {
-		txq->need_update = 1;
-	} else {
-		wait_write_ptr = 1;
-		txq->need_update = 0;
-	}
-
-	/* Set up TFD's 2nd entry to point directly to remainder of skb,
-	 * if any (802.11 null frames have no payload). */
-	secondlen = skb->len - hdr_len;
-	if (secondlen > 0) {
-		phys_addr = dma_map_single(trans->dev, skb->data + hdr_len,
-					   secondlen, DMA_TO_DEVICE);
-		if (unlikely(dma_mapping_error(trans->dev, phys_addr))) {
-			dma_unmap_single(trans->dev,
-					 dma_unmap_addr(out_meta, mapping),
-					 dma_unmap_len(out_meta, len),
-					 DMA_BIDIRECTIONAL);
-			goto out_err;
-		}
-	}
-
-	/* Attach buffers to TFD */
-	iwlagn_txq_attach_buf_to_tfd(trans, txq, txcmd_phys, firstlen, 1);
-	if (secondlen > 0)
-		iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr,
-					     secondlen, 0);
-
-	scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
-				offsetof(struct iwl_tx_cmd, scratch);
-
-	/* take back ownership of DMA buffer to enable update */
-	dma_sync_single_for_cpu(trans->dev, txcmd_phys, firstlen,
-				DMA_BIDIRECTIONAL);
-	tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
-	tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
-
-	IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n",
-		     le16_to_cpu(dev_cmd->hdr.sequence));
-	IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
-
-	/* Set up entry for this TFD in Tx byte-count array */
-	iwl_trans_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len));
-
-	dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen,
-				   DMA_BIDIRECTIONAL);
-
-	trace_iwlwifi_dev_tx(trans->dev,
-			     &txq->tfds[txq->q.write_ptr],
-			     sizeof(struct iwl_tfd),
-			     &dev_cmd->hdr, firstlen,
-			     skb->data + hdr_len, secondlen);
-
-	/* start timer if queue currently empty */
-	if (txq->need_update && q->read_ptr == q->write_ptr &&
-	    trans_pcie->wd_timeout)
-		mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
-
-	/* Tell device the write index *just past* this latest filled TFD */
-	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
-	iwl_txq_update_write_ptr(trans, txq);
-
-	/*
-	 * At this point the frame is "transmitted" successfully
-	 * and we will get a TX status notification eventually,
-	 * regardless of the value of ret. "ret" only indicates
-	 * whether or not we should update the write pointer.
-	 */
-	if (iwl_queue_space(q) < q->high_mark) {
-		if (wait_write_ptr) {
-			txq->need_update = 1;
-			iwl_txq_update_write_ptr(trans, txq);
-		} else {
-			iwl_stop_queue(trans, txq);
-		}
-	}
-	spin_unlock(&txq->lock);
-	return 0;
- out_err:
-	spin_unlock(&txq->lock);
-	return -1;
-}
-
 static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -1431,29 +576,28 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
 
 	if (!trans_pcie->irq_requested) {
 		tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long))
-			iwl_irq_tasklet, (unsigned long)trans);
+			iwl_pcie_tasklet, (unsigned long)trans);
 
-		iwl_alloc_isr_ict(trans);
+		iwl_pcie_alloc_ict(trans);
 
-		err = request_irq(trans_pcie->irq, iwl_isr_ict, IRQF_SHARED,
-				  DRV_NAME, trans);
+		err = request_irq(trans_pcie->irq, iwl_pcie_isr_ict,
+				  IRQF_SHARED, DRV_NAME, trans);
 		if (err) {
 			IWL_ERR(trans, "Error allocating IRQ %d\n",
 				trans_pcie->irq);
 			goto error;
 		}
 
-		INIT_WORK(&trans_pcie->rx_replenish, iwl_bg_rx_replenish);
 		trans_pcie->irq_requested = true;
 	}
 
-	err = iwl_prepare_card_hw(trans);
+	err = iwl_pcie_prepare_card_hw(trans);
 	if (err) {
 		IWL_ERR(trans, "Error while preparing HW: %d\n", err);
 		goto err_free_irq;
 	}
 
-	iwl_apm_init(trans);
+	iwl_pcie_apm_init(trans);
 
 	/* From now on, the op_mode will be kept updated about RF kill state */
 	iwl_enable_rfkill_int(trans);
@@ -1467,7 +611,7 @@ err_free_irq:
 	trans_pcie->irq_requested = false;
 	free_irq(trans_pcie->irq, trans);
 error:
-	iwl_free_isr_ict(trans);
+	iwl_pcie_free_ict(trans);
 	tasklet_kill(&trans_pcie->irq_tasklet);
 	return err;
 }
@@ -1483,7 +627,7 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans,
 	iwl_disable_interrupts(trans);
 	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
-	iwl_apm_stop(trans);
+	iwl_pcie_apm_stop(trans);
 
 	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 	iwl_disable_interrupts(trans);
@@ -1507,28 +651,6 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans,
 	}
 }
 
-static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
-				   struct sk_buff_head *skbs)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
-	/* n_bd is usually 256 => n_bd - 1 = 0xff */
-	int tfd_num = ssn & (txq->q.n_bd - 1);
-	int freed = 0;
-
-	spin_lock(&txq->lock);
-
-	if (txq->q.read_ptr != tfd_num) {
-		IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n",
-				   txq_id, txq->q.read_ptr, tfd_num, ssn);
-		freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
-		if (iwl_queue_space(&txq->q) > txq->q.low_mark)
-			iwl_wake_queue(trans, txq);
-	}
-
-	spin_unlock(&txq->lock);
-}
-
 static void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val)
 {
 	writeb(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
@@ -1575,12 +697,12 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
-	iwl_trans_pcie_tx_free(trans);
-	iwl_trans_pcie_rx_free(trans);
+	iwl_pcie_tx_free(trans);
+	iwl_pcie_rx_free(trans);
 
 	if (trans_pcie->irq_requested == true) {
 		free_irq(trans_pcie->irq, trans);
-		iwl_free_isr_ict(trans);
+		iwl_pcie_free_ict(trans);
 	}
 
 	pci_disable_msi(trans_pcie->pci_dev);
@@ -1626,10 +748,10 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans)
 
 #define IWL_FLUSH_WAIT_MS	2000
 
-static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans)
+static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_tx_queue *txq;
+	struct iwl_txq *txq;
 	struct iwl_queue *q;
 	int cnt;
 	unsigned long now = jiffies;
@@ -1673,7 +795,7 @@ static const char *get_fh_string(int cmd)
 #undef IWL_CMD
 }
 
-int iwl_dump_fh(struct iwl_trans *trans, char **buf)
+int iwl_pcie_dump_fh(struct iwl_trans *trans, char **buf)
 {
 	int i;
 	static const u32 fh_tbl[] = {
@@ -1752,7 +874,7 @@ static const char *get_csr_string(int cmd)
 #undef IWL_CMD
 }
 
-void iwl_dump_csr(struct iwl_trans *trans)
+void iwl_pcie_dump_csr(struct iwl_trans *trans)
 {
 	int i;
 	static const u32 csr_tbl[] = {
@@ -1809,7 +931,6 @@ static ssize_t iwl_dbgfs_##name##_write(struct file *file,              \
 					const char __user *user_buf,    \
 					size_t count, loff_t *ppos);
 
-
 #define DEBUGFS_READ_FILE_OPS(name)					\
 	DEBUGFS_READ_FUNC(name);					\
 static const struct file_operations iwl_dbgfs_##name##_ops = {		\
@@ -1842,7 +963,7 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
 {
 	struct iwl_trans *trans = file->private_data;
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_tx_queue *txq;
+	struct iwl_txq *txq;
 	struct iwl_queue *q;
 	char *buf;
 	int pos = 0;
@@ -1879,7 +1000,7 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
 {
 	struct iwl_trans *trans = file->private_data;
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_rx_queue *rxq = &trans_pcie->rxq;
+	struct iwl_rxq *rxq = &trans_pcie->rxq;
 	char buf[256];
 	int pos = 0;
 	const size_t bufsz = sizeof(buf);
@@ -1998,7 +1119,7 @@ static ssize_t iwl_dbgfs_csr_write(struct file *file,
 	if (sscanf(buf, "%d", &csr) != 1)
 		return -EFAULT;
 
-	iwl_dump_csr(trans);
+	iwl_pcie_dump_csr(trans);
 
 	return count;
 }
@@ -2012,7 +1133,7 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
 	int pos = 0;
 	ssize_t ret = -EFAULT;
 
-	ret = pos = iwl_dump_fh(trans, &buf);
+	ret = pos = iwl_pcie_dump_fh(trans, &buf);
 	if (buf) {
 		ret = simple_read_from_buffer(user_buf,
 					      count, ppos, buf, pos);
@@ -2081,7 +1202,7 @@ static const struct iwl_trans_ops trans_ops_pcie = {
 
 	.wowlan_suspend = iwl_trans_pcie_wowlan_suspend,
 
-	.send_cmd = iwl_trans_pcie_send_cmd,
+	.send_cmd = iwl_trans_pcie_send_hcmd,
 
 	.tx = iwl_trans_pcie_tx,
 	.reclaim = iwl_trans_pcie_reclaim,
@@ -2091,7 +1212,7 @@ static const struct iwl_trans_ops trans_ops_pcie = {
 
 	.dbgfs_register = iwl_trans_pcie_dbgfs_register,
 
-	.wait_tx_queue_empty = iwl_trans_pcie_wait_tx_queue_empty,
+	.wait_tx_queue_empty = iwl_trans_pcie_wait_txq_empty,
 
 #ifdef CONFIG_PM_SLEEP
 	.suspend = iwl_trans_pcie_suspend,
@@ -2116,7 +1237,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
 	trans = kzalloc(sizeof(struct iwl_trans) +
 			sizeof(struct iwl_trans_pcie), GFP_KERNEL);
 
-	if (WARN_ON(!trans))
+	if (!trans)
 		return NULL;
 
 	trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -2149,43 +1270,38 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
 							  DMA_BIT_MASK(32));
 		/* both attempts failed: */
 		if (err) {
-			dev_printk(KERN_ERR, &pdev->dev,
-				   "No suitable DMA available.\n");
+			dev_err(&pdev->dev, "No suitable DMA available\n");
 			goto out_pci_disable_device;
 		}
 	}
 
 	err = pci_request_regions(pdev, DRV_NAME);
 	if (err) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "pci_request_regions failed\n");
+		dev_err(&pdev->dev, "pci_request_regions failed\n");
 		goto out_pci_disable_device;
 	}
 
 	trans_pcie->hw_base = pci_ioremap_bar(pdev, 0);
 	if (!trans_pcie->hw_base) {
-		dev_printk(KERN_ERR, &pdev->dev, "pci_ioremap_bar failed\n");
+		dev_err(&pdev->dev, "pci_ioremap_bar failed\n");
 		err = -ENODEV;
 		goto out_pci_release_regions;
 	}
 
-	dev_printk(KERN_INFO, &pdev->dev,
-		   "pci_resource_len = 0x%08llx\n",
-		   (unsigned long long) pci_resource_len(pdev, 0));
-	dev_printk(KERN_INFO, &pdev->dev,
-		   "pci_resource_base = %p\n", trans_pcie->hw_base);
-
-	dev_printk(KERN_INFO, &pdev->dev,
-		   "HW Revision ID = 0x%X\n", pdev->revision);
-
 	/* We disable the RETRY_TIMEOUT register (0x41) to keep
 	 * PCI Tx retries from interfering with C3 CPU state */
 	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
 
 	err = pci_enable_msi(pdev);
-	if (err)
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "pci_enable_msi failed(0X%x)\n", err);
+	if (err) {
+		dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", err);
+		/* enable rfkill interrupt: hw bug w/a */
+		pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
+		if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
+			pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
+			pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
+		}
+	}
 
 	trans->dev = &pdev->dev;
 	trans_pcie->irq = pdev->irq;
@@ -2195,16 +1311,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
 	snprintf(trans->hw_id_str, sizeof(trans->hw_id_str),
 		 "PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device);
 
-	/* TODO: Move this away, not needed if not MSI */
-	/* enable rfkill interrupt: hw bug w/a */
-	pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
-	if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
-		pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
-		pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
-	}
-
 	/* Initialize the wait queue for commands */
-	init_waitqueue_head(&trans->wait_command_queue);
+	init_waitqueue_head(&trans_pcie->wait_command_queue);
 	spin_lock_init(&trans->reg_lock);
 
 	snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 79a4ddc..6c5b867 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -42,12 +42,170 @@
 #define IWL_TX_CRC_SIZE 4
 #define IWL_TX_DELIMITER_SIZE 4
 
-/**
- * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
+/*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
+ * DMA services
+ *
+ * Theory of operation
+ *
+ * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
+ * of buffer descriptors, each of which points to one or more data buffers for
+ * the device to read from or fill.  Driver and device exchange status of each
+ * queue via "read" and "write" pointers.  Driver keeps minimum of 2 empty
+ * entries in each circular buffer, to protect against confusing empty and full
+ * queue states.
+ *
+ * The device reads or writes the data in the queues via the device's several
+ * DMA/FIFO channels.  Each queue is mapped to a single DMA channel.
+ *
+ * For Tx queue, there are low mark and high mark limits. If, after queuing
+ * the packet for Tx, free space become < low mark, Tx queue stopped. When
+ * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
+ * Tx queue resumed.
+ *
+ ***************************************************/
+static int iwl_queue_space(const struct iwl_queue *q)
+{
+	int s = q->read_ptr - q->write_ptr;
+
+	if (q->read_ptr > q->write_ptr)
+		s -= q->n_bd;
+
+	if (s <= 0)
+		s += q->n_window;
+	/* keep some reserve to not confuse empty and full situations */
+	s -= 2;
+	if (s < 0)
+		s = 0;
+	return s;
+}
+
+/*
+ * iwl_queue_init - Initialize queue's high/low-water and read/write indexes
  */
-void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
-				       struct iwl_tx_queue *txq,
-				       u16 byte_cnt)
+static int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id)
+{
+	q->n_bd = count;
+	q->n_window = slots_num;
+	q->id = id;
+
+	/* count must be power-of-two size, otherwise iwl_queue_inc_wrap
+	 * and iwl_queue_dec_wrap are broken. */
+	if (WARN_ON(!is_power_of_2(count)))
+		return -EINVAL;
+
+	/* slots_num must be power-of-two size, otherwise
+	 * get_cmd_index is broken. */
+	if (WARN_ON(!is_power_of_2(slots_num)))
+		return -EINVAL;
+
+	q->low_mark = q->n_window / 4;
+	if (q->low_mark < 4)
+		q->low_mark = 4;
+
+	q->high_mark = q->n_window / 8;
+	if (q->high_mark < 2)
+		q->high_mark = 2;
+
+	q->write_ptr = 0;
+	q->read_ptr = 0;
+
+	return 0;
+}
+
+static int iwl_pcie_alloc_dma_ptr(struct iwl_trans *trans,
+				  struct iwl_dma_ptr *ptr, size_t size)
+{
+	if (WARN_ON(ptr->addr))
+		return -EINVAL;
+
+	ptr->addr = dma_alloc_coherent(trans->dev, size,
+				       &ptr->dma, GFP_KERNEL);
+	if (!ptr->addr)
+		return -ENOMEM;
+	ptr->size = size;
+	return 0;
+}
+
+static void iwl_pcie_free_dma_ptr(struct iwl_trans *trans,
+				  struct iwl_dma_ptr *ptr)
+{
+	if (unlikely(!ptr->addr))
+		return;
+
+	dma_free_coherent(trans->dev, ptr->size, ptr->addr, ptr->dma);
+	memset(ptr, 0, sizeof(*ptr));
+}
+
+static void iwl_pcie_txq_stuck_timer(unsigned long data)
+{
+	struct iwl_txq *txq = (void *)data;
+	struct iwl_queue *q = &txq->q;
+	struct iwl_trans_pcie *trans_pcie = txq->trans_pcie;
+	struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie);
+	u32 scd_sram_addr = trans_pcie->scd_base_addr +
+				SCD_TX_STTS_QUEUE_OFFSET(txq->q.id);
+	u8 buf[16];
+	int i;
+
+	spin_lock(&txq->lock);
+	/* check if triggered erroneously */
+	if (txq->q.read_ptr == txq->q.write_ptr) {
+		spin_unlock(&txq->lock);
+		return;
+	}
+	spin_unlock(&txq->lock);
+
+	IWL_ERR(trans, "Queue %d stuck for %u ms.\n", txq->q.id,
+		jiffies_to_msecs(trans_pcie->wd_timeout));
+	IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n",
+		txq->q.read_ptr, txq->q.write_ptr);
+
+	iwl_read_targ_mem_bytes(trans, scd_sram_addr, buf, sizeof(buf));
+
+	iwl_print_hex_error(trans, buf, sizeof(buf));
+
+	for (i = 0; i < FH_TCSR_CHNL_NUM; i++)
+		IWL_ERR(trans, "FH TRBs(%d) = 0x%08x\n", i,
+			iwl_read_direct32(trans, FH_TX_TRB_REG(i)));
+
+	for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) {
+		u32 status = iwl_read_prph(trans, SCD_QUEUE_STATUS_BITS(i));
+		u8 fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7;
+		bool active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE));
+		u32 tbl_dw =
+			iwl_read_targ_mem(trans,
+					  trans_pcie->scd_base_addr +
+					  SCD_TRANS_TBL_OFFSET_QUEUE(i));
+
+		if (i & 0x1)
+			tbl_dw = (tbl_dw & 0xFFFF0000) >> 16;
+		else
+			tbl_dw = tbl_dw & 0x0000FFFF;
+
+		IWL_ERR(trans,
+			"Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n",
+			i, active ? "" : "in", fifo, tbl_dw,
+			iwl_read_prph(trans,
+				      SCD_QUEUE_RDPTR(i)) & (txq->q.n_bd - 1),
+			iwl_read_prph(trans, SCD_QUEUE_WRPTR(i)));
+	}
+
+	for (i = q->read_ptr; i != q->write_ptr;
+	     i = iwl_queue_inc_wrap(i, q->n_bd)) {
+		struct iwl_tx_cmd *tx_cmd =
+			(struct iwl_tx_cmd *)txq->entries[i].cmd->payload;
+		IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
+			get_unaligned_le32(&tx_cmd->scratch));
+	}
+
+	iwl_op_mode_nic_error(trans->op_mode);
+}
+
+/*
+ * iwl_pcie_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
+ */
+static void iwl_pcie_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
+					     struct iwl_txq *txq, u16 byte_cnt)
 {
 	struct iwlagn_scd_bc_tbl *scd_bc_tbl;
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -88,10 +246,36 @@ void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
 			tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
 }
 
-/**
- * iwl_txq_update_write_ptr - Send new write index to hardware
+static void iwl_pcie_txq_inval_byte_cnt_tbl(struct iwl_trans *trans,
+					    struct iwl_txq *txq)
+{
+	struct iwl_trans_pcie *trans_pcie =
+		IWL_TRANS_GET_PCIE_TRANS(trans);
+	struct iwlagn_scd_bc_tbl *scd_bc_tbl = trans_pcie->scd_bc_tbls.addr;
+	int txq_id = txq->q.id;
+	int read_ptr = txq->q.read_ptr;
+	u8 sta_id = 0;
+	__le16 bc_ent;
+	struct iwl_tx_cmd *tx_cmd =
+		(void *)txq->entries[txq->q.read_ptr].cmd->payload;
+
+	WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
+
+	if (txq_id != trans_pcie->cmd_queue)
+		sta_id = tx_cmd->sta_id;
+
+	bc_ent = cpu_to_le16(1 | (sta_id << 12));
+	scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
+
+	if (read_ptr < TFD_QUEUE_SIZE_BC_DUP)
+		scd_bc_tbl[txq_id].
+			tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
+}
+
+/*
+ * iwl_pcie_txq_inc_wr_ptr - Send new write index to hardware
  */
-void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq)
+void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq)
 {
 	u32 reg = 0;
 	int txq_id = txq->q.id;
@@ -137,7 +321,7 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq)
 	txq->need_update = 0;
 }
 
-static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
+static inline dma_addr_t iwl_pcie_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
 {
 	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
 
@@ -149,15 +333,15 @@ static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
 	return addr;
 }
 
-static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
+static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
 {
 	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
 
 	return le16_to_cpu(tb->hi_n_len) >> 4;
 }
 
-static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
-				  dma_addr_t addr, u16 len)
+static inline void iwl_pcie_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
+				       dma_addr_t addr, u16 len)
 {
 	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
 	u16 hi_n_len = len << 4;
@@ -171,19 +355,20 @@ static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
 	tfd->num_tbs = idx + 1;
 }
 
-static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
+static inline u8 iwl_pcie_tfd_get_num_tbs(struct iwl_tfd *tfd)
 {
 	return tfd->num_tbs & 0x1f;
 }
 
-static void iwl_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta,
-			  struct iwl_tfd *tfd, enum dma_data_direction dma_dir)
+static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
+			       struct iwl_cmd_meta *meta, struct iwl_tfd *tfd,
+			       enum dma_data_direction dma_dir)
 {
 	int i;
 	int num_tbs;
 
 	/* Sanity check on number of chunks */
-	num_tbs = iwl_tfd_get_num_tbs(tfd);
+	num_tbs = iwl_pcie_tfd_get_num_tbs(tfd);
 
 	if (num_tbs >= IWL_NUM_OF_TBS) {
 		IWL_ERR(trans, "Too many chunks: %i\n", num_tbs);
@@ -200,14 +385,14 @@ static void iwl_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta,
 
 	/* Unmap chunks, if any. */
 	for (i = 1; i < num_tbs; i++)
-		dma_unmap_single(trans->dev, iwl_tfd_tb_get_addr(tfd, i),
-				iwl_tfd_tb_get_len(tfd, i), dma_dir);
+		dma_unmap_single(trans->dev, iwl_pcie_tfd_tb_get_addr(tfd, i),
+				 iwl_pcie_tfd_tb_get_len(tfd, i), dma_dir);
 
 	tfd->num_tbs = 0;
 }
 
-/**
- * iwl_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
+/*
+ * iwl_pcie_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
  * @trans - transport private data
  * @txq - tx queue
  * @dma_dir - the direction of the DMA mapping
@@ -215,8 +400,8 @@ static void iwl_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta,
  * Does NOT advance any TFD circular buffer read/write indexes
  * Does NOT free the TFD itself (which is within circular buffer)
  */
-void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
-		      enum dma_data_direction dma_dir)
+static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq,
+				  enum dma_data_direction dma_dir)
 {
 	struct iwl_tfd *tfd_tmp = txq->tfds;
 
@@ -227,8 +412,8 @@ void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
 	lockdep_assert_held(&txq->lock);
 
 	/* We have only q->n_window txq->entries, but we use q->n_bd tfds */
-	iwl_unmap_tfd(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr],
-		      dma_dir);
+	iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr],
+			   dma_dir);
 
 	/* free SKB */
 	if (txq->entries) {
@@ -247,10 +432,8 @@ void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
 	}
 }
 
-int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
-				 struct iwl_tx_queue *txq,
-				 dma_addr_t addr, u16 len,
-				 u8 reset)
+static int iwl_pcie_txq_build_tfd(struct iwl_trans *trans, struct iwl_txq *txq,
+				  dma_addr_t addr, u16 len, u8 reset)
 {
 	struct iwl_queue *q;
 	struct iwl_tfd *tfd, *tfd_tmp;
@@ -263,7 +446,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
 	if (reset)
 		memset(tfd, 0, sizeof(*tfd));
 
-	num_tbs = iwl_tfd_get_num_tbs(tfd);
+	num_tbs = iwl_pcie_tfd_get_num_tbs(tfd);
 
 	/* Each TFD can point to a maximum 20 Tx buffers */
 	if (num_tbs >= IWL_NUM_OF_TBS) {
@@ -272,115 +455,541 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
 		return -EINVAL;
 	}
 
-	if (WARN_ON(addr & ~DMA_BIT_MASK(36)))
-		return -EINVAL;
+	if (WARN_ON(addr & ~DMA_BIT_MASK(36)))
+		return -EINVAL;
+
+	if (unlikely(addr & ~IWL_TX_DMA_MASK))
+		IWL_ERR(trans, "Unaligned address = %llx\n",
+			(unsigned long long)addr);
+
+	iwl_pcie_tfd_set_tb(tfd, num_tbs, addr, len);
+
+	return 0;
+}
+
+static int iwl_pcie_txq_alloc(struct iwl_trans *trans,
+			       struct iwl_txq *txq, int slots_num,
+			       u32 txq_id)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX;
+	int i;
+
+	if (WARN_ON(txq->entries || txq->tfds))
+		return -EINVAL;
+
+	setup_timer(&txq->stuck_timer, iwl_pcie_txq_stuck_timer,
+		    (unsigned long)txq);
+	txq->trans_pcie = trans_pcie;
+
+	txq->q.n_window = slots_num;
+
+	txq->entries = kcalloc(slots_num,
+			       sizeof(struct iwl_pcie_txq_entry),
+			       GFP_KERNEL);
+
+	if (!txq->entries)
+		goto error;
+
+	if (txq_id == trans_pcie->cmd_queue)
+		for (i = 0; i < slots_num; i++) {
+			txq->entries[i].cmd =
+				kmalloc(sizeof(struct iwl_device_cmd),
+					GFP_KERNEL);
+			if (!txq->entries[i].cmd)
+				goto error;
+		}
+
+	/* Circular buffer of transmit frame descriptors (TFDs),
+	 * shared with device */
+	txq->tfds = dma_alloc_coherent(trans->dev, tfd_sz,
+				       &txq->q.dma_addr, GFP_KERNEL);
+	if (!txq->tfds) {
+		IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz);
+		goto error;
+	}
+	txq->q.id = txq_id;
+
+	return 0;
+error:
+	if (txq->entries && txq_id == trans_pcie->cmd_queue)
+		for (i = 0; i < slots_num; i++)
+			kfree(txq->entries[i].cmd);
+	kfree(txq->entries);
+	txq->entries = NULL;
+
+	return -ENOMEM;
+
+}
+
+static int iwl_pcie_txq_init(struct iwl_trans *trans, struct iwl_txq *txq,
+			      int slots_num, u32 txq_id)
+{
+	int ret;
+
+	txq->need_update = 0;
+
+	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
+	 * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
+	BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
+
+	/* Initialize queue's high/low-water marks, and head/tail indexes */
+	ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num,
+			txq_id);
+	if (ret)
+		return ret;
+
+	spin_lock_init(&txq->lock);
+
+	/*
+	 * Tell nic where to find circular buffer of Tx Frame Descriptors for
+	 * given Tx queue, and enable the DMA channel used for that queue.
+	 * Circular buffer (TFD queue in DRAM) physical base address */
+	iwl_write_direct32(trans, FH_MEM_CBBC_QUEUE(txq_id),
+			   txq->q.dma_addr >> 8);
+
+	return 0;
+}
+
+/*
+ * iwl_pcie_txq_unmap -  Unmap any remaining DMA mappings and free skb's
+ */
+static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	struct iwl_txq *txq = &trans_pcie->txq[txq_id];
+	struct iwl_queue *q = &txq->q;
+	enum dma_data_direction dma_dir;
+
+	if (!q->n_bd)
+		return;
+
+	/* In the command queue, all the TBs are mapped as BIDI
+	 * so unmap them as such.
+	 */
+	if (txq_id == trans_pcie->cmd_queue)
+		dma_dir = DMA_BIDIRECTIONAL;
+	else
+		dma_dir = DMA_TO_DEVICE;
+
+	spin_lock_bh(&txq->lock);
+	while (q->write_ptr != q->read_ptr) {
+		iwl_pcie_txq_free_tfd(trans, txq, dma_dir);
+		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
+	}
+	spin_unlock_bh(&txq->lock);
+}
+
+/*
+ * iwl_pcie_txq_free - Deallocate DMA queue.
+ * @txq: Transmit queue to deallocate.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	struct iwl_txq *txq = &trans_pcie->txq[txq_id];
+	struct device *dev = trans->dev;
+	int i;
+
+	if (WARN_ON(!txq))
+		return;
+
+	iwl_pcie_txq_unmap(trans, txq_id);
+
+	/* De-alloc array of command/tx buffers */
+	if (txq_id == trans_pcie->cmd_queue)
+		for (i = 0; i < txq->q.n_window; i++) {
+			kfree(txq->entries[i].cmd);
+			kfree(txq->entries[i].copy_cmd);
+			kfree(txq->entries[i].free_buf);
+		}
+
+	/* De-alloc circular buffer of TFDs */
+	if (txq->q.n_bd) {
+		dma_free_coherent(dev, sizeof(struct iwl_tfd) *
+				  txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+		memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr));
+	}
+
+	kfree(txq->entries);
+	txq->entries = NULL;
+
+	del_timer_sync(&txq->stuck_timer);
+
+	/* 0-fill queue descriptor structure */
+	memset(txq, 0, sizeof(*txq));
+}
+
+/*
+ * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
+ */
+static void iwl_pcie_txq_set_sched(struct iwl_trans *trans, u32 mask)
+{
+	struct iwl_trans_pcie __maybe_unused *trans_pcie =
+		IWL_TRANS_GET_PCIE_TRANS(trans);
+
+	iwl_write_prph(trans, SCD_TXFACT, mask);
+}
+
+void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	u32 a;
+	int chan;
+	u32 reg_val;
+
+	/* make sure all queue are not stopped/used */
+	memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped));
+	memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used));
+
+	trans_pcie->scd_base_addr =
+		iwl_read_prph(trans, SCD_SRAM_BASE_ADDR);
+
+	WARN_ON(scd_base_addr != 0 &&
+		scd_base_addr != trans_pcie->scd_base_addr);
+
+	a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND;
+	/* reset conext data memory */
+	for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND;
+		a += 4)
+		iwl_write_targ_mem(trans, a, 0);
+	/* reset tx status memory */
+	for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND;
+		a += 4)
+		iwl_write_targ_mem(trans, a, 0);
+	for (; a < trans_pcie->scd_base_addr +
+	       SCD_TRANS_TBL_OFFSET_QUEUE(
+				trans->cfg->base_params->num_of_queues);
+	       a += 4)
+		iwl_write_targ_mem(trans, a, 0);
+
+	iwl_write_prph(trans, SCD_DRAM_BASE_ADDR,
+		       trans_pcie->scd_bc_tbls.dma >> 10);
+
+	/* The chain extension of the SCD doesn't work well. This feature is
+	 * enabled by default by the HW, so we need to disable it manually.
+	 */
+	iwl_write_prph(trans, SCD_CHAINEXT_EN, 0);
+
+	iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue,
+				trans_pcie->cmd_fifo);
+
+	/* Activate all Tx DMA/FIFO channels */
+	iwl_pcie_txq_set_sched(trans, IWL_MASK(0, 7));
+
+	/* Enable DMA channel */
+	for (chan = 0; chan < FH_TCSR_CHNL_NUM; chan++)
+		iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan),
+				   FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+				   FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
+
+	/* Update FH chicken bits */
+	reg_val = iwl_read_direct32(trans, FH_TX_CHICKEN_BITS_REG);
+	iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG,
+			   reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
+
+	/* Enable L1-Active */
+	iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG,
+			    APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+}
+
+/*
+ * iwl_pcie_tx_stop - Stop all Tx DMA channels
+ */
+int iwl_pcie_tx_stop(struct iwl_trans *trans)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	int ch, txq_id, ret;
+	unsigned long flags;
+
+	/* Turn off all Tx DMA fifos */
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+
+	iwl_pcie_txq_set_sched(trans, 0);
+
+	/* Stop each Tx DMA channel, and wait for it to be idle */
+	for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) {
+		iwl_write_direct32(trans,
+				   FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
+		ret = iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG,
+			FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000);
+		if (ret < 0)
+			IWL_ERR(trans,
+				"Failing on timeout while stopping DMA channel %d [0x%08x]\n",
+				ch,
+				iwl_read_direct32(trans,
+						  FH_TSSR_TX_STATUS_REG));
+	}
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+
+	if (!trans_pcie->txq) {
+		IWL_WARN(trans,
+			 "Stopping tx queues that aren't allocated...\n");
+		return 0;
+	}
+
+	/* Unmap DMA from host system and free skb's */
+	for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
+	     txq_id++)
+		iwl_pcie_txq_unmap(trans, txq_id);
+
+	return 0;
+}
+
+/*
+ * iwl_trans_tx_free - Free TXQ Context
+ *
+ * Destroy all TX DMA queues and structures
+ */
+void iwl_pcie_tx_free(struct iwl_trans *trans)
+{
+	int txq_id;
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+	/* Tx queues */
+	if (trans_pcie->txq) {
+		for (txq_id = 0;
+		     txq_id < trans->cfg->base_params->num_of_queues; txq_id++)
+			iwl_pcie_txq_free(trans, txq_id);
+	}
+
+	kfree(trans_pcie->txq);
+	trans_pcie->txq = NULL;
+
+	iwl_pcie_free_dma_ptr(trans, &trans_pcie->kw);
+
+	iwl_pcie_free_dma_ptr(trans, &trans_pcie->scd_bc_tbls);
+}
+
+/*
+ * iwl_pcie_tx_alloc - allocate TX context
+ * Allocate all Tx DMA structures and initialize them
+ */
+static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
+{
+	int ret;
+	int txq_id, slots_num;
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+	u16 scd_bc_tbls_size = trans->cfg->base_params->num_of_queues *
+			sizeof(struct iwlagn_scd_bc_tbl);
+
+	/*It is not allowed to alloc twice, so warn when this happens.
+	 * We cannot rely on the previous allocation, so free and fail */
+	if (WARN_ON(trans_pcie->txq)) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	ret = iwl_pcie_alloc_dma_ptr(trans, &trans_pcie->scd_bc_tbls,
+				   scd_bc_tbls_size);
+	if (ret) {
+		IWL_ERR(trans, "Scheduler BC Table allocation failed\n");
+		goto error;
+	}
+
+	/* Alloc keep-warm buffer */
+	ret = iwl_pcie_alloc_dma_ptr(trans, &trans_pcie->kw, IWL_KW_SIZE);
+	if (ret) {
+		IWL_ERR(trans, "Keep Warm allocation failed\n");
+		goto error;
+	}
+
+	trans_pcie->txq = kcalloc(trans->cfg->base_params->num_of_queues,
+				  sizeof(struct iwl_txq), GFP_KERNEL);
+	if (!trans_pcie->txq) {
+		IWL_ERR(trans, "Not enough memory for txq\n");
+		ret = ENOMEM;
+		goto error;
+	}
+
+	/* Alloc and init all Tx queues, including the command queue (#4/#9) */
+	for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
+	     txq_id++) {
+		slots_num = (txq_id == trans_pcie->cmd_queue) ?
+					TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+		ret = iwl_pcie_txq_alloc(trans, &trans_pcie->txq[txq_id],
+					  slots_num, txq_id);
+		if (ret) {
+			IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id);
+			goto error;
+		}
+	}
+
+	return 0;
+
+error:
+	iwl_pcie_tx_free(trans);
+
+	return ret;
+}
+int iwl_pcie_tx_init(struct iwl_trans *trans)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	int ret;
+	int txq_id, slots_num;
+	unsigned long flags;
+	bool alloc = false;
+
+	if (!trans_pcie->txq) {
+		ret = iwl_pcie_tx_alloc(trans);
+		if (ret)
+			goto error;
+		alloc = true;
+	}
+
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+
+	/* Turn off all Tx DMA fifos */
+	iwl_write_prph(trans, SCD_TXFACT, 0);
+
+	/* Tell NIC where to find the "keep warm" buffer */
+	iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG,
+			   trans_pcie->kw.dma >> 4);
+
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+
+	/* Alloc and init all Tx queues, including the command queue (#4/#9) */
+	for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
+	     txq_id++) {
+		slots_num = (txq_id == trans_pcie->cmd_queue) ?
+					TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+		ret = iwl_pcie_txq_init(trans, &trans_pcie->txq[txq_id],
+					 slots_num, txq_id);
+		if (ret) {
+			IWL_ERR(trans, "Tx %d queue init failed\n", txq_id);
+			goto error;
+		}
+	}
+
+	return 0;
+error:
+	/*Upon error, free only if we allocated something */
+	if (alloc)
+		iwl_pcie_tx_free(trans);
+	return ret;
+}
+
+static inline void iwl_pcie_txq_progress(struct iwl_trans_pcie *trans_pcie,
+					   struct iwl_txq *txq)
+{
+	if (!trans_pcie->wd_timeout)
+		return;
+
+	/*
+	 * if empty delete timer, otherwise move timer forward
+	 * since we're making progress on this queue
+	 */
+	if (txq->q.read_ptr == txq->q.write_ptr)
+		del_timer(&txq->stuck_timer);
+	else
+		mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
+}
+
+/* Frees buffers until index _not_ inclusive */
+void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
+			    struct sk_buff_head *skbs)
+{
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	struct iwl_txq *txq = &trans_pcie->txq[txq_id];
+	/* n_bd is usually 256 => n_bd - 1 = 0xff */
+	int tfd_num = ssn & (txq->q.n_bd - 1);
+	struct iwl_queue *q = &txq->q;
+	int last_to_free;
 
-	if (unlikely(addr & ~IWL_TX_DMA_MASK))
-		IWL_ERR(trans, "Unaligned address = %llx\n",
-			(unsigned long long)addr);
+	/* This function is not meant to release cmd queue*/
+	if (WARN_ON(txq_id == trans_pcie->cmd_queue))
+		return;
 
-	iwl_tfd_set_tb(tfd, num_tbs, addr, len);
+	spin_lock(&txq->lock);
 
-	return 0;
-}
+	if (txq->q.read_ptr == tfd_num)
+		goto out;
 
-/*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
- * DMA services
- *
- * Theory of operation
- *
- * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
- * of buffer descriptors, each of which points to one or more data buffers for
- * the device to read from or fill.  Driver and device exchange status of each
- * queue via "read" and "write" pointers.  Driver keeps minimum of 2 empty
- * entries in each circular buffer, to protect against confusing empty and full
- * queue states.
- *
- * The device reads or writes the data in the queues via the device's several
- * DMA/FIFO channels.  Each queue is mapped to a single DMA channel.
- *
- * For Tx queue, there are low mark and high mark limits. If, after queuing
- * the packet for Tx, free space become < low mark, Tx queue stopped. When
- * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
- * Tx queue resumed.
- *
- ***************************************************/
+	IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n",
+			   txq_id, txq->q.read_ptr, tfd_num, ssn);
 
-int iwl_queue_space(const struct iwl_queue *q)
-{
-	int s = q->read_ptr - q->write_ptr;
+	/*Since we free until index _not_ inclusive, the one before index is
+	 * the last we will free. This one must be used */
+	last_to_free = iwl_queue_dec_wrap(tfd_num, q->n_bd);
 
-	if (q->read_ptr > q->write_ptr)
-		s -= q->n_bd;
+	if (!iwl_queue_used(q, last_to_free)) {
+		IWL_ERR(trans,
+			"%s: Read index for DMA queue txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n",
+			__func__, txq_id, last_to_free, q->n_bd,
+			q->write_ptr, q->read_ptr);
+		goto out;
+	}
 
-	if (s <= 0)
-		s += q->n_window;
-	/* keep some reserve to not confuse empty and full situations */
-	s -= 2;
-	if (s < 0)
-		s = 0;
-	return s;
-}
+	if (WARN_ON(!skb_queue_empty(skbs)))
+		goto out;
 
-/**
- * iwl_queue_init - Initialize queue's high/low-water and read/write indexes
- */
-int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id)
-{
-	q->n_bd = count;
-	q->n_window = slots_num;
-	q->id = id;
+	for (;
+	     q->read_ptr != tfd_num;
+	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
 
-	/* count must be power-of-two size, otherwise iwl_queue_inc_wrap
-	 * and iwl_queue_dec_wrap are broken. */
-	if (WARN_ON(!is_power_of_2(count)))
-		return -EINVAL;
+		if (WARN_ON_ONCE(txq->entries[txq->q.read_ptr].skb == NULL))
+			continue;
 
-	/* slots_num must be power-of-two size, otherwise
-	 * get_cmd_index is broken. */
-	if (WARN_ON(!is_power_of_2(slots_num)))
-		return -EINVAL;
+		__skb_queue_tail(skbs, txq->entries[txq->q.read_ptr].skb);
 
-	q->low_mark = q->n_window / 4;
-	if (q->low_mark < 4)
-		q->low_mark = 4;
+		txq->entries[txq->q.read_ptr].skb = NULL;
 
-	q->high_mark = q->n_window / 8;
-	if (q->high_mark < 2)
-		q->high_mark = 2;
+		iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq);
 
-	q->write_ptr = q->read_ptr = 0;
+		iwl_pcie_txq_free_tfd(trans, txq, DMA_TO_DEVICE);
+	}
 
-	return 0;
+	iwl_pcie_txq_progress(trans_pcie, txq);
+
+	if (iwl_queue_space(&txq->q) > txq->q.low_mark)
+		iwl_wake_queue(trans, txq);
+out:
+	spin_unlock(&txq->lock);
 }
 
-static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans,
-					  struct iwl_tx_queue *txq)
+/*
+ * iwl_pcie_cmdq_reclaim - Reclaim TX command queue entries already Tx'd
+ *
+ * When FW advances 'R' index, all entries between old and new 'R' index
+ * need to be reclaimed. As result, some free space forms.  If there is
+ * enough free space (> low mark), wake the stack that feeds us.
+ */
+static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
 {
-	struct iwl_trans_pcie *trans_pcie =
-		IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwlagn_scd_bc_tbl *scd_bc_tbl = trans_pcie->scd_bc_tbls.addr;
-	int txq_id = txq->q.id;
-	int read_ptr = txq->q.read_ptr;
-	u8 sta_id = 0;
-	__le16 bc_ent;
-	struct iwl_tx_cmd *tx_cmd =
-		(void *)txq->entries[txq->q.read_ptr].cmd->payload;
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	struct iwl_txq *txq = &trans_pcie->txq[txq_id];
+	struct iwl_queue *q = &txq->q;
+	int nfreed = 0;
 
-	WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
+	lockdep_assert_held(&txq->lock);
 
-	if (txq_id != trans_pcie->cmd_queue)
-		sta_id = tx_cmd->sta_id;
+	if ((idx >= q->n_bd) || (!iwl_queue_used(q, idx))) {
+		IWL_ERR(trans,
+			"%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n",
+			__func__, txq_id, idx, q->n_bd,
+			q->write_ptr, q->read_ptr);
+		return;
+	}
 
-	bc_ent = cpu_to_le16(1 | (sta_id << 12));
-	scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
+	for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
+	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
 
-	if (read_ptr < TFD_QUEUE_SIZE_BC_DUP)
-		scd_bc_tbl[txq_id].
-			tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
+		if (nfreed++ > 0) {
+			IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n",
+				idx, q->write_ptr, q->read_ptr);
+			iwl_op_mode_nic_error(trans->op_mode);
+		}
+	}
+
+	iwl_pcie_txq_progress(trans_pcie, txq);
 }
 
-static int iwl_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid,
+static int iwl_pcie_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid,
 				 u16 txq_id)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -405,7 +1014,8 @@ static int iwl_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid,
 	return 0;
 }
 
-static inline void iwl_txq_set_inactive(struct iwl_trans *trans, u16 txq_id)
+static inline void iwl_pcie_txq_set_inactive(struct iwl_trans *trans,
+					     u16 txq_id)
 {
 	/* Simply stop the queue, but don't change any configuration;
 	 * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
@@ -424,7 +1034,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
 		WARN_ONCE(1, "queue %d already used - expect issues", txq_id);
 
 	/* Stop this Tx queue before configuring it */
-	iwl_txq_set_inactive(trans, txq_id);
+	iwl_pcie_txq_set_inactive(trans, txq_id);
 
 	/* Set this queue as a chain-building queue unless it is CMD queue */
 	if (txq_id != trans_pcie->cmd_queue)
@@ -435,7 +1045,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
 		u16 ra_tid = BUILD_RAxTID(sta_id, tid);
 
 		/* Map receiver-address / traffic-ID to this queue */
-		iwl_txq_set_ratid_map(trans, ra_tid, txq_id);
+		iwl_pcie_txq_set_ratid_map(trans, ra_tid, txq_id);
 
 		/* enable aggregations for the queue */
 		iwl_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id));
@@ -480,20 +1090,29 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
 void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	u32 stts_addr = trans_pcie->scd_base_addr +
+			SCD_TX_STTS_QUEUE_OFFSET(txq_id);
+	static const u32 zero_val[4] = {};
 
 	if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) {
 		WARN_ONCE(1, "queue %d not used", txq_id);
 		return;
 	}
 
-	iwl_txq_set_inactive(trans, txq_id);
+	iwl_pcie_txq_set_inactive(trans, txq_id);
+
+	_iwl_write_targ_mem_dwords(trans, stts_addr,
+				   zero_val, ARRAY_SIZE(zero_val));
+
+	iwl_pcie_txq_unmap(trans, txq_id);
+
 	IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id);
 }
 
 /*************** HOST COMMAND QUEUE FUNCTIONS   *****/
 
-/**
- * iwl_enqueue_hcmd - enqueue a uCode command
+/*
+ * iwl_pcie_enqueue_hcmd - enqueue a uCode command
  * @priv: device private data point
  * @cmd: a point to the ucode command structure
  *
@@ -501,15 +1120,17 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id)
  * failed. On success, it turns the index (> 0) of command in the
  * command queue.
  */
-static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
+static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
+				 struct iwl_host_cmd *cmd)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
+	struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
 	struct iwl_queue *q = &txq->q;
 	struct iwl_device_cmd *out_cmd;
 	struct iwl_cmd_meta *out_meta;
+	void *dup_buf = NULL;
 	dma_addr_t phys_addr;
-	u32 idx;
+	int idx;
 	u16 copy_size, cmd_size;
 	bool had_nocopy = false;
 	int i;
@@ -526,10 +1147,33 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
 			continue;
 		if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) {
 			had_nocopy = true;
+			if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) {
+				idx = -EINVAL;
+				goto free_dup_buf;
+			}
+		} else if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP) {
+			/*
+			 * This is also a chunk that isn't copied
+			 * to the static buffer so set had_nocopy.
+			 */
+			had_nocopy = true;
+
+			/* only allowed once */
+			if (WARN_ON(dup_buf)) {
+				idx = -EINVAL;
+				goto free_dup_buf;
+			}
+
+			dup_buf = kmemdup(cmd->data[i], cmd->len[i],
+					  GFP_ATOMIC);
+			if (!dup_buf)
+				return -ENOMEM;
 		} else {
 			/* NOCOPY must not be followed by normal! */
-			if (WARN_ON(had_nocopy))
-				return -EINVAL;
+			if (WARN_ON(had_nocopy)) {
+				idx = -EINVAL;
+				goto free_dup_buf;
+			}
 			copy_size += cmd->len[i];
 		}
 		cmd_size += cmd->len[i];
@@ -541,8 +1185,12 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
 	 * allocated into separate TFDs, then we will need to
 	 * increase the size of the buffers.
 	 */
-	if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE))
-		return -EINVAL;
+	if (WARN(copy_size > TFD_MAX_PAYLOAD_SIZE,
+		 "Command %s (%#x) is too large (%d bytes)\n",
+		 get_cmd_string(trans_pcie, cmd->id), cmd->id, copy_size)) {
+		idx = -EINVAL;
+		goto free_dup_buf;
+	}
 
 	spin_lock_bh(&txq->lock);
 
@@ -551,7 +1199,8 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
 
 		IWL_ERR(trans, "No space in command queue\n");
 		iwl_op_mode_cmd_queue_full(trans->op_mode);
-		return -ENOSPC;
+		idx = -ENOSPC;
+		goto free_dup_buf;
 	}
 
 	idx = get_cmd_index(q, q->write_ptr);
@@ -575,7 +1224,8 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
 	for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
 		if (!cmd->len[i])
 			continue;
-		if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)
+		if (cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
+					 IWL_HCMD_DFL_DUP))
 			break;
 		memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]);
 		cmd_pos += cmd->len[i];
@@ -600,7 +1250,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
 
 	IWL_DEBUG_HC(trans,
 		     "Sending command %s (#%x), seq: 0x%04X, %d bytes at %d[%d]:%d\n",
-		     trans_pcie_get_cmd_string(trans_pcie, out_cmd->hdr.cmd),
+		     get_cmd_string(trans_pcie, out_cmd->hdr.cmd),
 		     out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
 		     cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue);
 
@@ -614,28 +1264,35 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
 	dma_unmap_addr_set(out_meta, mapping, phys_addr);
 	dma_unmap_len_set(out_meta, len, copy_size);
 
-	iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, copy_size, 1);
+	iwl_pcie_txq_build_tfd(trans, txq, phys_addr, copy_size, 1);
 
 	for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+		const void *data = cmd->data[i];
+
 		if (!cmd->len[i])
 			continue;
-		if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
+		if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
+					   IWL_HCMD_DFL_DUP)))
 			continue;
-		phys_addr = dma_map_single(trans->dev, (void *)cmd->data[i],
+		if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP)
+			data = dup_buf;
+		phys_addr = dma_map_single(trans->dev, (void *)data,
 					   cmd->len[i], DMA_BIDIRECTIONAL);
 		if (dma_mapping_error(trans->dev, phys_addr)) {
-			iwl_unmap_tfd(trans, out_meta,
-				      &txq->tfds[q->write_ptr],
-				      DMA_BIDIRECTIONAL);
+			iwl_pcie_tfd_unmap(trans, out_meta,
+					   &txq->tfds[q->write_ptr],
+					   DMA_BIDIRECTIONAL);
 			idx = -ENOMEM;
 			goto out;
 		}
 
-		iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr,
-					     cmd->len[i], 0);
+		iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmd->len[i], 0);
 	}
 
 	out_meta->flags = cmd->flags;
+	if (WARN_ON_ONCE(txq->entries[idx].free_buf))
+		kfree(txq->entries[idx].free_buf);
+	txq->entries[idx].free_buf = dup_buf;
 
 	txq->need_update = 1;
 
@@ -648,70 +1305,18 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
 
 	/* Increment and update queue's write index */
 	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
-	iwl_txq_update_write_ptr(trans, txq);
+	iwl_pcie_txq_inc_wr_ptr(trans, txq);
 
  out:
 	spin_unlock_bh(&txq->lock);
+ free_dup_buf:
+	if (idx < 0)
+		kfree(dup_buf);
 	return idx;
 }
 
-static inline void iwl_queue_progress(struct iwl_trans_pcie *trans_pcie,
-				      struct iwl_tx_queue *txq)
-{
-	if (!trans_pcie->wd_timeout)
-		return;
-
-	/*
-	 * if empty delete timer, otherwise move timer forward
-	 * since we're making progress on this queue
-	 */
-	if (txq->q.read_ptr == txq->q.write_ptr)
-		del_timer(&txq->stuck_timer);
-	else
-		mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
-}
-
-/**
- * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd
- *
- * When FW advances 'R' index, all entries between old and new 'R' index
- * need to be reclaimed. As result, some free space forms.  If there is
- * enough free space (> low mark), wake the stack that feeds us.
- */
-static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id,
-				   int idx)
-{
-	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
-	struct iwl_queue *q = &txq->q;
-	int nfreed = 0;
-
-	lockdep_assert_held(&txq->lock);
-
-	if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
-		IWL_ERR(trans,
-			"%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n",
-			__func__, txq_id, idx, q->n_bd,
-			q->write_ptr, q->read_ptr);
-		return;
-	}
-
-	for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
-	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
-
-		if (nfreed++ > 0) {
-			IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n",
-				idx, q->write_ptr, q->read_ptr);
-			iwl_op_mode_nic_error(trans->op_mode);
-		}
-
-	}
-
-	iwl_queue_progress(trans_pcie, txq);
-}
-
-/**
- * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
+/*
+ * iwl_pcie_hcmd_complete - Pull unused buffers off the queue and reclaim them
  * @rxb: Rx buffer to reclaim
  * @handler_status: return value of the handler of the command
  *	(put in setup_rx_handlers)
@@ -720,8 +1325,8 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id,
  * will be executed.  The attached skb (if present) will only be freed
  * if the callback returns 1
  */
-void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb,
-			 int handler_status)
+void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
+			    struct iwl_rx_cmd_buffer *rxb, int handler_status)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
@@ -731,7 +1336,7 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb,
 	struct iwl_device_cmd *cmd;
 	struct iwl_cmd_meta *meta;
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
+	struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
 
 	/* If a Tx command is being handled and it isn't in the actual
 	 * command queue then there a command routing bug has been introduced
@@ -751,7 +1356,7 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb,
 	cmd = txq->entries[cmd_index].cmd;
 	meta = &txq->entries[cmd_index].meta;
 
-	iwl_unmap_tfd(trans, meta, &txq->tfds[index], DMA_BIDIRECTIONAL);
+	iwl_pcie_tfd_unmap(trans, meta, &txq->tfds[index], DMA_BIDIRECTIONAL);
 
 	/* Input error checking is done when commands are added to queue. */
 	if (meta->flags & CMD_WANT_SKB) {
@@ -763,20 +1368,18 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb,
 		meta->source->handler_status = handler_status;
 	}
 
-	iwl_hcmd_queue_reclaim(trans, txq_id, index);
+	iwl_pcie_cmdq_reclaim(trans, txq_id, index);
 
 	if (!(meta->flags & CMD_ASYNC)) {
 		if (!test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) {
 			IWL_WARN(trans,
 				 "HCMD_ACTIVE already clear for command %s\n",
-				 trans_pcie_get_cmd_string(trans_pcie,
-							   cmd->hdr.cmd));
+				 get_cmd_string(trans_pcie, cmd->hdr.cmd));
 		}
 		clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
 		IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n",
-			       trans_pcie_get_cmd_string(trans_pcie,
-							 cmd->hdr.cmd));
-		wake_up(&trans->wait_command_queue);
+			       get_cmd_string(trans_pcie, cmd->hdr.cmd));
+		wake_up(&trans_pcie->wait_command_queue);
 	}
 
 	meta->flags = 0;
@@ -786,7 +1389,8 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb,
 
 #define HOST_COMPLETE_TIMEOUT (2 * HZ)
 
-static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
+static int iwl_pcie_send_hcmd_async(struct iwl_trans *trans,
+				    struct iwl_host_cmd *cmd)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	int ret;
@@ -795,59 +1399,59 @@ static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
 	if (WARN_ON(cmd->flags & CMD_WANT_SKB))
 		return -EINVAL;
 
-
-	ret = iwl_enqueue_hcmd(trans, cmd);
+	ret = iwl_pcie_enqueue_hcmd(trans, cmd);
 	if (ret < 0) {
 		IWL_ERR(trans,
 			"Error sending %s: enqueue_hcmd failed: %d\n",
-			trans_pcie_get_cmd_string(trans_pcie, cmd->id), ret);
+			get_cmd_string(trans_pcie, cmd->id), ret);
 		return ret;
 	}
 	return 0;
 }
 
-static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
+static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
+				   struct iwl_host_cmd *cmd)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	int cmd_idx;
 	int ret;
 
 	IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n",
-		       trans_pcie_get_cmd_string(trans_pcie, cmd->id));
+		       get_cmd_string(trans_pcie, cmd->id));
 
 	if (WARN_ON(test_and_set_bit(STATUS_HCMD_ACTIVE,
 				     &trans_pcie->status))) {
 		IWL_ERR(trans, "Command %s: a command is already active!\n",
-			trans_pcie_get_cmd_string(trans_pcie, cmd->id));
+			get_cmd_string(trans_pcie, cmd->id));
 		return -EIO;
 	}
 
 	IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n",
-		       trans_pcie_get_cmd_string(trans_pcie, cmd->id));
+		       get_cmd_string(trans_pcie, cmd->id));
 
-	cmd_idx = iwl_enqueue_hcmd(trans, cmd);
+	cmd_idx = iwl_pcie_enqueue_hcmd(trans, cmd);
 	if (cmd_idx < 0) {
 		ret = cmd_idx;
 		clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
 		IWL_ERR(trans,
 			"Error sending %s: enqueue_hcmd failed: %d\n",
-			trans_pcie_get_cmd_string(trans_pcie, cmd->id), ret);
+			get_cmd_string(trans_pcie, cmd->id), ret);
 		return ret;
 	}
 
-	ret = wait_event_timeout(trans->wait_command_queue,
+	ret = wait_event_timeout(trans_pcie->wait_command_queue,
 				 !test_bit(STATUS_HCMD_ACTIVE,
 					   &trans_pcie->status),
 				 HOST_COMPLETE_TIMEOUT);
 	if (!ret) {
 		if (test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) {
-			struct iwl_tx_queue *txq =
+			struct iwl_txq *txq =
 				&trans_pcie->txq[trans_pcie->cmd_queue];
 			struct iwl_queue *q = &txq->q;
 
 			IWL_ERR(trans,
 				"Error sending %s: time out after %dms.\n",
-				trans_pcie_get_cmd_string(trans_pcie, cmd->id),
+				get_cmd_string(trans_pcie, cmd->id),
 				jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
 
 			IWL_ERR(trans,
@@ -857,16 +1461,28 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
 			clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
 			IWL_DEBUG_INFO(trans,
 				       "Clearing HCMD_ACTIVE for command %s\n",
-				       trans_pcie_get_cmd_string(trans_pcie,
-								 cmd->id));
+				       get_cmd_string(trans_pcie, cmd->id));
 			ret = -ETIMEDOUT;
 			goto cancel;
 		}
 	}
 
+	if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) {
+		IWL_ERR(trans, "FW error in SYNC CMD %s\n",
+			get_cmd_string(trans_pcie, cmd->id));
+		ret = -EIO;
+		goto cancel;
+	}
+
+	if (test_bit(STATUS_RFKILL, &trans_pcie->status)) {
+		IWL_DEBUG_RF_KILL(trans, "RFKILL in SYNC CMD... no rsp\n");
+		ret = -ERFKILL;
+		goto cancel;
+	}
+
 	if ((cmd->flags & CMD_WANT_SKB) && !cmd->resp_pkt) {
 		IWL_ERR(trans, "Error: Response NULL in '%s'\n",
-			trans_pcie_get_cmd_string(trans_pcie, cmd->id));
+			get_cmd_string(trans_pcie, cmd->id));
 		ret = -EIO;
 		goto cancel;
 	}
@@ -893,64 +1509,183 @@ cancel:
 	return ret;
 }
 
-int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
+int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
 {
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+	if (test_bit(STATUS_FW_ERROR, &trans_pcie->status))
+		return -EIO;
+
+	if (test_bit(STATUS_RFKILL, &trans_pcie->status))
+		return -ERFKILL;
+
 	if (cmd->flags & CMD_ASYNC)
-		return iwl_send_cmd_async(trans, cmd);
+		return iwl_pcie_send_hcmd_async(trans, cmd);
 
-	return iwl_send_cmd_sync(trans, cmd);
+	/* We still can fail on RFKILL that can be asserted while we wait */
+	return iwl_pcie_send_hcmd_sync(trans, cmd);
 }
 
-/* Frees buffers until index _not_ inclusive */
-int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
-			 struct sk_buff_head *skbs)
+int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
+		      struct iwl_device_cmd *dev_cmd, int txq_id)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
-	struct iwl_queue *q = &txq->q;
-	int last_to_free;
-	int freed = 0;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct iwl_tx_cmd *tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;
+	struct iwl_cmd_meta *out_meta;
+	struct iwl_txq *txq;
+	struct iwl_queue *q;
+	dma_addr_t phys_addr = 0;
+	dma_addr_t txcmd_phys;
+	dma_addr_t scratch_phys;
+	u16 len, firstlen, secondlen;
+	u8 wait_write_ptr = 0;
+	__le16 fc = hdr->frame_control;
+	u8 hdr_len = ieee80211_hdrlen(fc);
+	u16 __maybe_unused wifi_seq;
+
+	txq = &trans_pcie->txq[txq_id];
+	q = &txq->q;
 
-	/* This function is not meant to release cmd queue*/
-	if (WARN_ON(txq_id == trans_pcie->cmd_queue))
-		return 0;
+	if (unlikely(!test_bit(txq_id, trans_pcie->queue_used))) {
+		WARN_ON_ONCE(1);
+		return -EINVAL;
+	}
 
-	lockdep_assert_held(&txq->lock);
+	spin_lock(&txq->lock);
 
-	/*Since we free until index _not_ inclusive, the one before index is
-	 * the last we will free. This one must be used */
-	last_to_free = iwl_queue_dec_wrap(index, q->n_bd);
+	/* In AGG mode, the index in the ring must correspond to the WiFi
+	 * sequence number. This is a HW requirements to help the SCD to parse
+	 * the BA.
+	 * Check here that the packets are in the right place on the ring.
+	 */
+#ifdef CONFIG_IWLWIFI_DEBUG
+	wifi_seq = SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
+	WARN_ONCE((iwl_read_prph(trans, SCD_AGGR_SEL) & BIT(txq_id)) &&
+		  ((wifi_seq & 0xff) != q->write_ptr),
+		  "Q: %d WiFi Seq %d tfdNum %d",
+		  txq_id, wifi_seq, q->write_ptr);
+#endif
+
+	/* Set up driver data for this TFD */
+	txq->entries[q->write_ptr].skb = skb;
+	txq->entries[q->write_ptr].cmd = dev_cmd;
+
+	dev_cmd->hdr.cmd = REPLY_TX;
+	dev_cmd->hdr.sequence =
+		cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
+			    INDEX_TO_SEQ(q->write_ptr)));
+
+	/* Set up first empty entry in queue's array of Tx/cmd buffers */
+	out_meta = &txq->entries[q->write_ptr].meta;
 
-	if ((index >= q->n_bd) ||
-	   (iwl_queue_used(q, last_to_free) == 0)) {
-		IWL_ERR(trans,
-			"%s: Read index for DMA queue txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n",
-			__func__, txq_id, last_to_free, q->n_bd,
-			q->write_ptr, q->read_ptr);
-		return 0;
+	/*
+	 * Use the first empty entry in this queue's command buffer array
+	 * to contain the Tx command and MAC header concatenated together
+	 * (payload data will be in another buffer).
+	 * Size of this varies, due to varying MAC header length.
+	 * If end is not dword aligned, we'll have 2 extra bytes at the end
+	 * of the MAC header (device reads on dword boundaries).
+	 * We'll tell device about this padding later.
+	 */
+	len = sizeof(struct iwl_tx_cmd) +
+		sizeof(struct iwl_cmd_header) + hdr_len;
+	firstlen = (len + 3) & ~3;
+
+	/* Tell NIC about any 2-byte padding after MAC header */
+	if (firstlen != len)
+		tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
+
+	/* Physical address of this Tx command's header (not MAC header!),
+	 * within command buffer array. */
+	txcmd_phys = dma_map_single(trans->dev,
+				    &dev_cmd->hdr, firstlen,
+				    DMA_BIDIRECTIONAL);
+	if (unlikely(dma_mapping_error(trans->dev, txcmd_phys)))
+		goto out_err;
+	dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
+	dma_unmap_len_set(out_meta, len, firstlen);
+
+	if (!ieee80211_has_morefrags(fc)) {
+		txq->need_update = 1;
+	} else {
+		wait_write_ptr = 1;
+		txq->need_update = 0;
 	}
 
-	if (WARN_ON(!skb_queue_empty(skbs)))
-		return 0;
+	/* Set up TFD's 2nd entry to point directly to remainder of skb,
+	 * if any (802.11 null frames have no payload). */
+	secondlen = skb->len - hdr_len;
+	if (secondlen > 0) {
+		phys_addr = dma_map_single(trans->dev, skb->data + hdr_len,
+					   secondlen, DMA_TO_DEVICE);
+		if (unlikely(dma_mapping_error(trans->dev, phys_addr))) {
+			dma_unmap_single(trans->dev,
+					 dma_unmap_addr(out_meta, mapping),
+					 dma_unmap_len(out_meta, len),
+					 DMA_BIDIRECTIONAL);
+			goto out_err;
+		}
+	}
 
-	for (;
-	     q->read_ptr != index;
-	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+	/* Attach buffers to TFD */
+	iwl_pcie_txq_build_tfd(trans, txq, txcmd_phys, firstlen, 1);
+	if (secondlen > 0)
+		iwl_pcie_txq_build_tfd(trans, txq, phys_addr, secondlen, 0);
 
-		if (WARN_ON_ONCE(txq->entries[txq->q.read_ptr].skb == NULL))
-			continue;
+	scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
+				offsetof(struct iwl_tx_cmd, scratch);
 
-		__skb_queue_tail(skbs, txq->entries[txq->q.read_ptr].skb);
+	/* take back ownership of DMA buffer to enable update */
+	dma_sync_single_for_cpu(trans->dev, txcmd_phys, firstlen,
+				DMA_BIDIRECTIONAL);
+	tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
+	tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
 
-		txq->entries[txq->q.read_ptr].skb = NULL;
+	IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n",
+		     le16_to_cpu(dev_cmd->hdr.sequence));
+	IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
 
-		iwlagn_txq_inval_byte_cnt_tbl(trans, txq);
+	/* Set up entry for this TFD in Tx byte-count array */
+	iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len));
 
-		iwl_txq_free_tfd(trans, txq, DMA_TO_DEVICE);
-		freed++;
-	}
+	dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen,
+				   DMA_BIDIRECTIONAL);
+
+	trace_iwlwifi_dev_tx(trans->dev, skb,
+			     &txq->tfds[txq->q.write_ptr],
+			     sizeof(struct iwl_tfd),
+			     &dev_cmd->hdr, firstlen,
+			     skb->data + hdr_len, secondlen);
+	trace_iwlwifi_dev_tx_data(trans->dev, skb,
+				  skb->data + hdr_len, secondlen);
 
-	iwl_queue_progress(trans_pcie, txq);
+	/* start timer if queue currently empty */
+	if (txq->need_update && q->read_ptr == q->write_ptr &&
+	    trans_pcie->wd_timeout)
+		mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
+
+	/* Tell device the write index *just past* this latest filled TFD */
+	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
+	iwl_pcie_txq_inc_wr_ptr(trans, txq);
 
-	return freed;
+	/*
+	 * At this point the frame is "transmitted" successfully
+	 * and we will get a TX status notification eventually,
+	 * regardless of the value of ret. "ret" only indicates
+	 * whether or not we should update the write pointer.
+	 */
+	if (iwl_queue_space(q) < q->high_mark) {
+		if (wait_write_ptr) {
+			txq->need_update = 1;
+			iwl_pcie_txq_inc_wr_ptr(trans, txq);
+		} else {
+			iwl_stop_queue(trans, txq);
+		}
+	}
+	spin_unlock(&txq->lock);
+	return 0;
+out_err:
+	spin_unlock(&txq->lock);
+	return -1;
 }
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 1c10b54..ec36868 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -436,19 +436,19 @@ static int lbs_add_wpa_tlv(u8 *tlv, const u8 *ie, u8 ie_len)
  */
 
 static int lbs_cfg_set_monitor_channel(struct wiphy *wiphy,
-				       struct ieee80211_channel *channel,
-				       enum nl80211_channel_type channel_type)
+				       struct cfg80211_chan_def *chandef)
 {
 	struct lbs_private *priv = wiphy_priv(wiphy);
 	int ret = -ENOTSUPP;
 
 	lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d",
-			   channel->center_freq, channel_type);
+			   chandef->chan->center_freq,
+			   cfg80211_get_chandef_type(chandef));
 
-	if (channel_type != NL80211_CHAN_NO_HT)
+	if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT)
 		goto out;
 
-	ret = lbs_set_channel(priv, channel->hw_value);
+	ret = lbs_set_channel(priv, chandef->chan->hw_value);
 
  out:
 	lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
@@ -1734,7 +1734,7 @@ static void lbs_join_post(struct lbs_private *priv,
 	/* Fake DS channel IE */
 	*fake++ = WLAN_EID_DS_PARAMS;
 	*fake++ = 1;
-	*fake++ = params->channel->hw_value;
+	*fake++ = params->chandef.chan->hw_value;
 	/* Fake IBSS params IE */
 	*fake++ = WLAN_EID_IBSS_PARAMS;
 	*fake++ = 2;
@@ -1755,7 +1755,7 @@ static void lbs_join_post(struct lbs_private *priv,
 	lbs_deb_hex(LBS_DEB_CFG80211, "IE", fake_ie, fake - fake_ie);
 
 	bss = cfg80211_inform_bss(priv->wdev->wiphy,
-				  params->channel,
+				  params->chandef.chan,
 				  bssid,
 				  0,
 				  capability,
@@ -1833,7 +1833,7 @@ static int lbs_ibss_join_existing(struct lbs_private *priv,
 	cmd.bss.beaconperiod = cpu_to_le16(params->beacon_interval);
 	cmd.bss.ds.header.id = WLAN_EID_DS_PARAMS;
 	cmd.bss.ds.header.len = 1;
-	cmd.bss.ds.channel = params->channel->hw_value;
+	cmd.bss.ds.channel = params->chandef.chan->hw_value;
 	cmd.bss.ibss.header.id = WLAN_EID_IBSS_PARAMS;
 	cmd.bss.ibss.header.len = 2;
 	cmd.bss.ibss.atimwindow = 0;
@@ -1942,7 +1942,7 @@ static int lbs_ibss_start_new(struct lbs_private *priv,
 	cmd.ibss.atimwindow = 0;
 	cmd.ds.header.id = WLAN_EID_DS_PARAMS;
 	cmd.ds.header.len = 1;
-	cmd.ds.channel = params->channel->hw_value;
+	cmd.ds.channel = params->chandef.chan->hw_value;
 	/* Only v8 and below support setting probe delay */
 	if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8)
 		cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
@@ -1987,18 +1987,18 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 
 	lbs_deb_enter(LBS_DEB_CFG80211);
 
-	if (!params->channel) {
+	if (!params->chandef.chan) {
 		ret = -ENOTSUPP;
 		goto out;
 	}
 
-	ret = lbs_set_channel(priv, params->channel->hw_value);
+	ret = lbs_set_channel(priv, params->chandef.chan->hw_value);
 	if (ret)
 		goto out;
 
 	/* Search if someone is beaconing. This assumes that the
 	 * bss list is populated already */
-	bss = cfg80211_get_bss(wiphy, params->channel, params->bssid,
+	bss = cfg80211_get_bss(wiphy, params->chandef.chan, params->bssid,
 		params->ssid, params->ssid_len,
 		WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
 
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 4cb2343..739309e 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -588,17 +588,38 @@ static int if_sdio_prog_real(struct if_sdio_card *card,
 	size = fw->size;
 
 	while (size) {
-		ret = if_sdio_wait_status(card, FW_DL_READY_STATUS);
-		if (ret)
-			goto release;
+		timeout = jiffies + HZ;
+		while (1) {
+			ret = if_sdio_wait_status(card, FW_DL_READY_STATUS);
+			if (ret)
+				goto release;
 
-		req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret);
-		if (ret)
-			goto release;
+			req_size = sdio_readb(card->func, IF_SDIO_RD_BASE,
+					&ret);
+			if (ret)
+				goto release;
+
+			req_size |= sdio_readb(card->func, IF_SDIO_RD_BASE + 1,
+					&ret) << 8;
+			if (ret)
+				goto release;
+
+			/*
+			 * For SD8688 wait until the length is not 0, 1 or 2
+			 * before downloading the first FW block,
+			 * since BOOT code writes the register to indicate the
+			 * helper/FW download winner,
+			 * the value could be 1 or 2 (Func1 or Func2).
+			 */
+			if ((size != fw->size) || (req_size > 2))
+				break;
+			if (time_after(jiffies, timeout)) {
+				ret = -ETIMEDOUT;
+				goto release;
+			}
+			mdelay(1);
+		}
 
-		req_size |= sdio_readb(card->func, IF_SDIO_RD_BASE + 1, &ret) << 8;
-		if (ret)
-			goto release;
 /*
 		lbs_deb_sdio("firmware wants %d bytes\n", (int)req_size);
 */
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index 9780775..3e81264 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -101,7 +101,7 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
 
 	switch (action) {
 	case CMD_ACT_MESH_CONFIG_START:
-		ie->id = WLAN_EID_GENERIC;
+		ie->id = WLAN_EID_VENDOR_SPECIFIC;
 		ie->val.oui[0] = 0x00;
 		ie->val.oui[1] = 0x50;
 		ie->val.oui[2] = 0x43;
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 429ca32..2aa8a1a 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -44,9 +44,9 @@ static int radios = 2;
 module_param(radios, int, 0444);
 MODULE_PARM_DESC(radios, "Number of simulated radios");
 
-static bool fake_hw_scan;
-module_param(fake_hw_scan, bool, 0444);
-MODULE_PARM_DESC(fake_hw_scan, "Install fake (no-op) hw-scan handler");
+static int channels = 1;
+module_param(channels, int, 0444);
+MODULE_PARM_DESC(channels, "Number of concurrent channels");
 
 /**
  * enum hwsim_regtest - the type of regulatory tests we offer
@@ -166,7 +166,9 @@ struct hwsim_vif_priv {
 static inline void hwsim_check_magic(struct ieee80211_vif *vif)
 {
 	struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
-	WARN_ON(vp->magic != HWSIM_VIF_MAGIC);
+	WARN(vp->magic != HWSIM_VIF_MAGIC,
+	     "Invalid VIF (%p) magic %#x, %pM, %d/%d\n",
+	     vif, vp->magic, vif->addr, vif->type, vif->p2p);
 }
 
 static inline void hwsim_set_magic(struct ieee80211_vif *vif)
@@ -185,7 +187,7 @@ struct hwsim_sta_priv {
 	u32 magic;
 };
 
-#define HWSIM_STA_MAGIC	0x6d537748
+#define HWSIM_STA_MAGIC	0x6d537749
 
 static inline void hwsim_check_sta_magic(struct ieee80211_sta *sta)
 {
@@ -205,6 +207,30 @@ static inline void hwsim_clear_sta_magic(struct ieee80211_sta *sta)
 	sp->magic = 0;
 }
 
+struct hwsim_chanctx_priv {
+	u32 magic;
+};
+
+#define HWSIM_CHANCTX_MAGIC 0x6d53774a
+
+static inline void hwsim_check_chanctx_magic(struct ieee80211_chanctx_conf *c)
+{
+	struct hwsim_chanctx_priv *cp = (void *)c->drv_priv;
+	WARN_ON(cp->magic != HWSIM_CHANCTX_MAGIC);
+}
+
+static inline void hwsim_set_chanctx_magic(struct ieee80211_chanctx_conf *c)
+{
+	struct hwsim_chanctx_priv *cp = (void *)c->drv_priv;
+	cp->magic = HWSIM_CHANCTX_MAGIC;
+}
+
+static inline void hwsim_clear_chanctx_magic(struct ieee80211_chanctx_conf *c)
+{
+	struct hwsim_chanctx_priv *cp = (void *)c->drv_priv;
+	cp->magic = 0;
+}
+
 static struct class *hwsim_class;
 
 static struct net_device *hwsim_mon; /* global monitor netdev */
@@ -299,6 +325,13 @@ struct mac80211_hwsim_data {
 
 	struct mac_address addresses[2];
 
+	struct ieee80211_channel *tmp_chan;
+	struct delayed_work roc_done;
+	struct delayed_work hw_scan;
+	struct cfg80211_scan_request *hw_scan_request;
+	struct ieee80211_vif *hw_scan_vif;
+	int scan_chan_idx;
+
 	struct ieee80211_channel *channel;
 	unsigned long beacon_int; /* in jiffies unit */
 	unsigned int rx_filter;
@@ -396,7 +429,8 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
 }
 
 static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
-				      struct sk_buff *tx_skb)
+				      struct sk_buff *tx_skb,
+				      struct ieee80211_channel *chan)
 {
 	struct mac80211_hwsim_data *data = hw->priv;
 	struct sk_buff *skb;
@@ -423,7 +457,7 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
 	hdr->rt_tsft = __mac80211_hwsim_get_tsf(data);
 	hdr->rt_flags = 0;
 	hdr->rt_rate = txrate->bitrate / 5;
-	hdr->rt_channel = cpu_to_le16(data->channel->center_freq);
+	hdr->rt_channel = cpu_to_le16(chan->center_freq);
 	flags = IEEE80211_CHAN_2GHZ;
 	if (txrate->flags & IEEE80211_RATE_ERP_G)
 		flags |= IEEE80211_CHAN_OFDM;
@@ -441,9 +475,9 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
 }
 
 
-static void mac80211_hwsim_monitor_ack(struct ieee80211_hw *hw, const u8 *addr)
+static void mac80211_hwsim_monitor_ack(struct ieee80211_channel *chan,
+				       const u8 *addr)
 {
-	struct mac80211_hwsim_data *data = hw->priv;
 	struct sk_buff *skb;
 	struct hwsim_radiotap_hdr *hdr;
 	u16 flags;
@@ -464,7 +498,7 @@ static void mac80211_hwsim_monitor_ack(struct ieee80211_hw *hw, const u8 *addr)
 					  (1 << IEEE80211_RADIOTAP_CHANNEL));
 	hdr->rt_flags = 0;
 	hdr->rt_rate = 0;
-	hdr->rt_channel = cpu_to_le16(data->channel->center_freq);
+	hdr->rt_channel = cpu_to_le16(chan->center_freq);
 	flags = IEEE80211_CHAN_2GHZ;
 	hdr->rt_chbitmask = cpu_to_le16(flags);
 
@@ -537,6 +571,7 @@ static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data,
 	md.ret = false;
 	md.addr = addr;
 	ieee80211_iterate_active_interfaces_atomic(data->hw,
+						   IEEE80211_IFACE_ITER_NORMAL,
 						   mac80211_hwsim_addr_iter,
 						   &md);
 
@@ -556,12 +591,6 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
 	int i;
 	struct hwsim_tx_rate tx_attempts[IEEE80211_TX_MAX_RATES];
 
-	if (data->idle) {
-		wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n");
-		dev_kfree_skb(my_skb);
-		return;
-	}
-
 	if (data->ps != PS_DISABLED)
 		hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
 	/* If the queue contains MAX_QUEUE skb's drop some */
@@ -629,8 +658,38 @@ nla_put_failure:
 	printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__);
 }
 
+static bool hwsim_chans_compat(struct ieee80211_channel *c1,
+			       struct ieee80211_channel *c2)
+{
+	if (!c1 || !c2)
+		return false;
+
+	return c1->center_freq == c2->center_freq;
+}
+
+struct tx_iter_data {
+	struct ieee80211_channel *channel;
+	bool receive;
+};
+
+static void mac80211_hwsim_tx_iter(void *_data, u8 *addr,
+				   struct ieee80211_vif *vif)
+{
+	struct tx_iter_data *data = _data;
+
+	if (!vif->chanctx_conf)
+		return;
+
+	if (!hwsim_chans_compat(data->channel,
+				rcu_dereference(vif->chanctx_conf)->def.chan))
+		return;
+
+	data->receive = true;
+}
+
 static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
-					  struct sk_buff *skb)
+					  struct sk_buff *skb,
+					  struct ieee80211_channel *chan)
 {
 	struct mac80211_hwsim_data *data = hw->priv, *data2;
 	bool ack = false;
@@ -639,15 +698,10 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
 	struct ieee80211_rx_status rx_status;
 	struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info);
 
-	if (data->idle) {
-		wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n");
-		return false;
-	}
-
 	memset(&rx_status, 0, sizeof(rx_status));
-	rx_status.flag |= RX_FLAG_MACTIME_MPDU;
-	rx_status.freq = data->channel->center_freq;
-	rx_status.band = data->channel->band;
+	rx_status.flag |= RX_FLAG_MACTIME_START;
+	rx_status.freq = chan->center_freq;
+	rx_status.band = chan->band;
 	rx_status.rate_idx = info->control.rates[0].idx;
 	if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
 		rx_status.flag |= RX_FLAG_HT;
@@ -673,17 +727,35 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
 	list_for_each_entry(data2, &hwsim_radios, list) {
 		struct sk_buff *nskb;
 		struct ieee80211_mgmt *mgmt;
+		struct tx_iter_data tx_iter_data = {
+			.receive = false,
+			.channel = chan,
+		};
 
 		if (data == data2)
 			continue;
 
-		if (data2->idle || !data2->started ||
-		    !hwsim_ps_rx_ok(data2, skb) || !data2->channel ||
-		    data->channel->center_freq != data2->channel->center_freq ||
-		    !(data->group & data2->group))
+		if (!data2->started || (data2->idle && !data2->tmp_chan) ||
+		    !hwsim_ps_rx_ok(data2, skb))
 			continue;
 
-		nskb = skb_copy(skb, GFP_ATOMIC);
+		if (!(data->group & data2->group))
+			continue;
+
+		if (!hwsim_chans_compat(chan, data2->tmp_chan) &&
+		    !hwsim_chans_compat(chan, data2->channel)) {
+			ieee80211_iterate_active_interfaces_atomic(
+				data2->hw, IEEE80211_IFACE_ITER_NORMAL,
+				mac80211_hwsim_tx_iter, &tx_iter_data);
+			if (!tx_iter_data.receive)
+				continue;
+		}
+
+		/*
+		 * reserve some space for our vendor and the normal
+		 * radiotap header, since we're copying anyway
+		 */
+		nskb = skb_copy_expand(skb, 64, 0, GFP_ATOMIC);
 		if (nskb == NULL)
 			continue;
 
@@ -701,6 +773,33 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
 				(data->tsf_offset - data2->tsf_offset) +
 				24 * 8 * 10 / txrate->bitrate);
 
+#if 0
+		/*
+		 * Don't enable this code by default as the OUI 00:00:00
+		 * is registered to Xerox so we shouldn't use it here, it
+		 * might find its way into pcap files.
+		 * Note that this code requires the headroom in the SKB
+		 * that was allocated earlier.
+		 */
+		rx_status.vendor_radiotap_oui[0] = 0x00;
+		rx_status.vendor_radiotap_oui[1] = 0x00;
+		rx_status.vendor_radiotap_oui[2] = 0x00;
+		rx_status.vendor_radiotap_subns = 127;
+		/*
+		 * Radiotap vendor namespaces can (and should) also be
+		 * split into fields by using the standard radiotap
+		 * presence bitmap mechanism. Use just BIT(0) here for
+		 * the presence bitmap.
+		 */
+		rx_status.vendor_radiotap_bitmap = BIT(0);
+		/* We have 8 bytes of (dummy) data */
+		rx_status.vendor_radiotap_len = 8;
+		/* For testing, also require it to be aligned */
+		rx_status.vendor_radiotap_align = 8;
+		/* push the data */
+		memcpy(skb_push(nskb, 8), "ABCDEFGH", 8);
+#endif
+
 		memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status));
 		ieee80211_rx_irqsafe(data2->hw, nskb);
 	}
@@ -713,18 +812,51 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
 			      struct ieee80211_tx_control *control,
 			      struct sk_buff *skb)
 {
+	struct mac80211_hwsim_data *data = hw->priv;
+	struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb);
+	struct ieee80211_chanctx_conf *chanctx_conf;
+	struct ieee80211_channel *channel;
 	bool ack;
-	struct ieee80211_tx_info *txi;
 	u32 _portid;
 
-	mac80211_hwsim_monitor_rx(hw, skb);
-
-	if (skb->len < 10) {
+	if (WARN_ON(skb->len < 10)) {
 		/* Should not happen; just a sanity check for addr1 use */
 		dev_kfree_skb(skb);
 		return;
 	}
 
+	if (channels == 1) {
+		channel = data->channel;
+	} else if (txi->hw_queue == 4) {
+		channel = data->tmp_chan;
+	} else {
+		chanctx_conf = rcu_dereference(txi->control.vif->chanctx_conf);
+		if (chanctx_conf)
+			channel = chanctx_conf->def.chan;
+		else
+			channel = NULL;
+	}
+
+	if (WARN(!channel, "TX w/o channel - queue = %d\n", txi->hw_queue)) {
+		dev_kfree_skb(skb);
+		return;
+	}
+
+	if (data->idle && !data->tmp_chan) {
+		wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n");
+		dev_kfree_skb(skb);
+		return;
+	}
+
+	if (txi->control.vif)
+		hwsim_check_magic(txi->control.vif);
+	if (control->sta)
+		hwsim_check_sta_magic(control->sta);
+
+	txi->rate_driver_data[0] = channel;
+
+	mac80211_hwsim_monitor_rx(hw, skb, channel);
+
 	/* wmediumd mode check */
 	_portid = ACCESS_ONCE(wmediumd_portid);
 
@@ -732,15 +864,13 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
 		return mac80211_hwsim_tx_frame_nl(hw, skb, _portid);
 
 	/* NO wmediumd detected, perfect medium simulation */
-	ack = mac80211_hwsim_tx_frame_no_nl(hw, skb);
+	ack = mac80211_hwsim_tx_frame_no_nl(hw, skb, channel);
 
 	if (ack && skb->len >= 16) {
 		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-		mac80211_hwsim_monitor_ack(hw, hdr->addr2);
+		mac80211_hwsim_monitor_ack(channel, hdr->addr2);
 	}
 
-	txi = IEEE80211_SKB_CB(skb);
-
 	ieee80211_tx_info_clear_status(txi);
 
 	/* frame was transmitted at most favorable rate at first attempt */
@@ -778,6 +908,13 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
 		    __func__, ieee80211_vif_type_p2p(vif),
 		    vif->addr);
 	hwsim_set_magic(vif);
+
+	vif->cab_queue = 0;
+	vif->hw_queue[IEEE80211_AC_VO] = 0;
+	vif->hw_queue[IEEE80211_AC_VI] = 1;
+	vif->hw_queue[IEEE80211_AC_BE] = 2;
+	vif->hw_queue[IEEE80211_AC_BK] = 3;
+
 	return 0;
 }
 
@@ -807,14 +944,26 @@ static void mac80211_hwsim_remove_interface(
 	hwsim_clear_magic(vif);
 }
 
+static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
+				    struct sk_buff *skb,
+				    struct ieee80211_channel *chan)
+{
+	u32 _pid = ACCESS_ONCE(wmediumd_portid);
+
+	mac80211_hwsim_monitor_rx(hw, skb, chan);
+
+	if (_pid)
+		return mac80211_hwsim_tx_frame_nl(hw, skb, _pid);
+
+	mac80211_hwsim_tx_frame_no_nl(hw, skb, chan);
+	dev_kfree_skb(skb);
+}
 
 static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
 				     struct ieee80211_vif *vif)
 {
 	struct ieee80211_hw *hw = arg;
 	struct sk_buff *skb;
-	struct ieee80211_tx_info *info;
-	u32 _portid;
 
 	hwsim_check_magic(vif);
 
@@ -826,18 +975,9 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
 	skb = ieee80211_beacon_get(hw, vif);
 	if (skb == NULL)
 		return;
-	info = IEEE80211_SKB_CB(skb);
-
-	mac80211_hwsim_monitor_rx(hw, skb);
-
-	/* wmediumd mode check */
-	_portid = ACCESS_ONCE(wmediumd_portid);
-
-	if (_portid)
-		return mac80211_hwsim_tx_frame_nl(hw, skb, _portid);
 
-	mac80211_hwsim_tx_frame_no_nl(hw, skb);
-	dev_kfree_skb(skb);
+	mac80211_hwsim_tx_frame(hw, skb,
+				rcu_dereference(vif->chanctx_conf)->def.chan);
 }
 
 
@@ -850,7 +990,8 @@ static void mac80211_hwsim_beacon(unsigned long arg)
 		return;
 
 	ieee80211_iterate_active_interfaces_atomic(
-		hw, mac80211_hwsim_beacon_tx, hw);
+		hw, IEEE80211_IFACE_ITER_NORMAL,
+		mac80211_hwsim_beacon_tx, hw);
 
 	data->beacon_timer.expires = jiffies + data->beacon_int;
 	add_timer(&data->beacon_timer);
@@ -877,7 +1018,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
 	wiphy_debug(hw->wiphy,
 		    "%s (freq=%d/%s idle=%d ps=%d smps=%s)\n",
 		    __func__,
-		    conf->channel->center_freq,
+		    conf->channel ? conf->channel->center_freq : 0,
 		    hwsim_chantypes[conf->channel_type],
 		    !!(conf->flags & IEEE80211_CONF_IDLE),
 		    !!(conf->flags & IEEE80211_CONF_PS),
@@ -886,6 +1027,9 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
 	data->idle = !!(conf->flags & IEEE80211_CONF_IDLE);
 
 	data->channel = conf->channel;
+
+	WARN_ON(data->channel && channels > 1);
+
 	data->power_level = conf->power_level;
 	if (!data->started || !data->beacon_int)
 		del_timer(&data->beacon_timer);
@@ -963,15 +1107,17 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
 	}
 
 	if (changed & BSS_CHANGED_HT) {
-		wiphy_debug(hw->wiphy, "  HT: op_mode=0x%x, chantype=%s\n",
-			    info->ht_operation_mode,
-			    hwsim_chantypes[info->channel_type]);
+		wiphy_debug(hw->wiphy, "  HT: op_mode=0x%x\n",
+			    info->ht_operation_mode);
 	}
 
 	if (changed & BSS_CHANGED_BASIC_RATES) {
 		wiphy_debug(hw->wiphy, "  BASIC_RATES: 0x%llx\n",
 			    (unsigned long long) info->basic_rates);
 	}
+
+	if (changed & BSS_CHANGED_TXPOWER)
+		wiphy_debug(hw->wiphy, "  TX Power: %d dBm\n", info->txpower);
 }
 
 static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw,
@@ -1166,45 +1312,96 @@ static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop)
 	/* Not implemented, queues only on kernel side */
 }
 
-struct hw_scan_done {
-	struct delayed_work w;
-	struct ieee80211_hw *hw;
-};
-
-static void hw_scan_done(struct work_struct *work)
+static void hw_scan_work(struct work_struct *work)
 {
-	struct hw_scan_done *hsd =
-		container_of(work, struct hw_scan_done, w.work);
+	struct mac80211_hwsim_data *hwsim =
+		container_of(work, struct mac80211_hwsim_data, hw_scan.work);
+	struct cfg80211_scan_request *req = hwsim->hw_scan_request;
+	int dwell, i;
+
+	mutex_lock(&hwsim->mutex);
+	if (hwsim->scan_chan_idx >= req->n_channels) {
+		wiphy_debug(hwsim->hw->wiphy, "hw scan complete\n");
+		ieee80211_scan_completed(hwsim->hw, false);
+		hwsim->hw_scan_request = NULL;
+		hwsim->hw_scan_vif = NULL;
+		hwsim->tmp_chan = NULL;
+		mutex_unlock(&hwsim->mutex);
+		return;
+	}
 
-	ieee80211_scan_completed(hsd->hw, false);
-	kfree(hsd);
+	wiphy_debug(hwsim->hw->wiphy, "hw scan %d MHz\n",
+		    req->channels[hwsim->scan_chan_idx]->center_freq);
+
+	hwsim->tmp_chan = req->channels[hwsim->scan_chan_idx];
+	if (hwsim->tmp_chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
+	    !req->n_ssids) {
+		dwell = 120;
+	} else {
+		dwell = 30;
+		/* send probes */
+		for (i = 0; i < req->n_ssids; i++) {
+			struct sk_buff *probe;
+
+			probe = ieee80211_probereq_get(hwsim->hw,
+						       hwsim->hw_scan_vif,
+						       req->ssids[i].ssid,
+						       req->ssids[i].ssid_len,
+						       req->ie, req->ie_len);
+			if (!probe)
+				continue;
+			local_bh_disable();
+			mac80211_hwsim_tx_frame(hwsim->hw, probe,
+						hwsim->tmp_chan);
+			local_bh_enable();
+		}
+	}
+	ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan,
+				     msecs_to_jiffies(dwell));
+	hwsim->scan_chan_idx++;
+	mutex_unlock(&hwsim->mutex);
 }
 
 static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw,
 				  struct ieee80211_vif *vif,
 				  struct cfg80211_scan_request *req)
 {
-	struct hw_scan_done *hsd = kzalloc(sizeof(*hsd), GFP_KERNEL);
-	int i;
-
-	if (!hsd)
-		return -ENOMEM;
+	struct mac80211_hwsim_data *hwsim = hw->priv;
 
-	hsd->hw = hw;
-	INIT_DELAYED_WORK(&hsd->w, hw_scan_done);
+	mutex_lock(&hwsim->mutex);
+	if (WARN_ON(hwsim->tmp_chan || hwsim->hw_scan_request)) {
+		mutex_unlock(&hwsim->mutex);
+		return -EBUSY;
+	}
+	hwsim->hw_scan_request = req;
+	hwsim->hw_scan_vif = vif;
+	hwsim->scan_chan_idx = 0;
+	mutex_unlock(&hwsim->mutex);
 
-	printk(KERN_DEBUG "hwsim hw_scan request\n");
-	for (i = 0; i < req->n_channels; i++)
-		printk(KERN_DEBUG "hwsim hw_scan freq %d\n",
-			req->channels[i]->center_freq);
-	print_hex_dump(KERN_DEBUG, "scan IEs: ", DUMP_PREFIX_OFFSET,
-			16, 1, req->ie, req->ie_len, 1);
+	wiphy_debug(hw->wiphy, "hwsim hw_scan request\n");
 
-	ieee80211_queue_delayed_work(hw, &hsd->w, 2 * HZ);
+	ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, 0);
 
 	return 0;
 }
 
+static void mac80211_hwsim_cancel_hw_scan(struct ieee80211_hw *hw,
+					  struct ieee80211_vif *vif)
+{
+	struct mac80211_hwsim_data *hwsim = hw->priv;
+
+	wiphy_debug(hw->wiphy, "hwsim cancel_hw_scan\n");
+
+	cancel_delayed_work_sync(&hwsim->hw_scan);
+
+	mutex_lock(&hwsim->mutex);
+	ieee80211_scan_completed(hwsim->hw, true);
+	hwsim->tmp_chan = NULL;
+	hwsim->hw_scan_request = NULL;
+	hwsim->hw_scan_vif = NULL;
+	mutex_unlock(&hwsim->mutex);
+}
+
 static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw)
 {
 	struct mac80211_hwsim_data *hwsim = hw->priv;
@@ -1235,6 +1432,111 @@ static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw)
 	mutex_unlock(&hwsim->mutex);
 }
 
+static void hw_roc_done(struct work_struct *work)
+{
+	struct mac80211_hwsim_data *hwsim =
+		container_of(work, struct mac80211_hwsim_data, roc_done.work);
+
+	mutex_lock(&hwsim->mutex);
+	ieee80211_remain_on_channel_expired(hwsim->hw);
+	hwsim->tmp_chan = NULL;
+	mutex_unlock(&hwsim->mutex);
+
+	wiphy_debug(hwsim->hw->wiphy, "hwsim ROC expired\n");
+}
+
+static int mac80211_hwsim_roc(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif,
+			      struct ieee80211_channel *chan,
+			      int duration)
+{
+	struct mac80211_hwsim_data *hwsim = hw->priv;
+
+	mutex_lock(&hwsim->mutex);
+	if (WARN_ON(hwsim->tmp_chan || hwsim->hw_scan_request)) {
+		mutex_unlock(&hwsim->mutex);
+		return -EBUSY;
+	}
+
+	hwsim->tmp_chan = chan;
+	mutex_unlock(&hwsim->mutex);
+
+	wiphy_debug(hw->wiphy, "hwsim ROC (%d MHz, %d ms)\n",
+		    chan->center_freq, duration);
+
+	ieee80211_ready_on_channel(hw);
+
+	ieee80211_queue_delayed_work(hw, &hwsim->roc_done,
+				     msecs_to_jiffies(duration));
+	return 0;
+}
+
+static int mac80211_hwsim_croc(struct ieee80211_hw *hw)
+{
+	struct mac80211_hwsim_data *hwsim = hw->priv;
+
+	cancel_delayed_work_sync(&hwsim->roc_done);
+
+	mutex_lock(&hwsim->mutex);
+	hwsim->tmp_chan = NULL;
+	mutex_unlock(&hwsim->mutex);
+
+	wiphy_debug(hw->wiphy, "hwsim ROC canceled\n");
+
+	return 0;
+}
+
+static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw,
+				      struct ieee80211_chanctx_conf *ctx)
+{
+	hwsim_set_chanctx_magic(ctx);
+	wiphy_debug(hw->wiphy,
+		    "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
+		    ctx->def.chan->center_freq, ctx->def.width,
+		    ctx->def.center_freq1, ctx->def.center_freq2);
+	return 0;
+}
+
+static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw,
+					  struct ieee80211_chanctx_conf *ctx)
+{
+	wiphy_debug(hw->wiphy,
+		    "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
+		    ctx->def.chan->center_freq, ctx->def.width,
+		    ctx->def.center_freq1, ctx->def.center_freq2);
+	hwsim_check_chanctx_magic(ctx);
+	hwsim_clear_chanctx_magic(ctx);
+}
+
+static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw,
+					  struct ieee80211_chanctx_conf *ctx,
+					  u32 changed)
+{
+	hwsim_check_chanctx_magic(ctx);
+	wiphy_debug(hw->wiphy,
+		    "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
+		    ctx->def.chan->center_freq, ctx->def.width,
+		    ctx->def.center_freq1, ctx->def.center_freq2);
+}
+
+static int mac80211_hwsim_assign_vif_chanctx(struct ieee80211_hw *hw,
+					     struct ieee80211_vif *vif,
+					     struct ieee80211_chanctx_conf *ctx)
+{
+	hwsim_check_magic(vif);
+	hwsim_check_chanctx_magic(ctx);
+
+	return 0;
+}
+
+static void mac80211_hwsim_unassign_vif_chanctx(struct ieee80211_hw *hw,
+						struct ieee80211_vif *vif,
+						struct ieee80211_chanctx_conf *ctx)
+{
+	hwsim_check_magic(vif);
+	hwsim_check_chanctx_magic(ctx);
+}
+
 static struct ieee80211_ops mac80211_hwsim_ops =
 {
 	.tx = mac80211_hwsim_tx,
@@ -1315,7 +1617,6 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
 	struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
 	struct sk_buff *skb;
 	struct ieee80211_pspoll *pspoll;
-	u32 _portid;
 
 	if (!vp->assoc)
 		return;
@@ -1335,25 +1636,18 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
 	memcpy(pspoll->bssid, vp->bssid, ETH_ALEN);
 	memcpy(pspoll->ta, mac, ETH_ALEN);
 
-	/* wmediumd mode check */
-	_portid = ACCESS_ONCE(wmediumd_portid);
-
-	if (_portid)
-		return mac80211_hwsim_tx_frame_nl(data->hw, skb, _portid);
-
-	if (!mac80211_hwsim_tx_frame_no_nl(data->hw, skb))
-		printk(KERN_DEBUG "%s: PS-poll frame not ack'ed\n", __func__);
-	dev_kfree_skb(skb);
+	rcu_read_lock();
+	mac80211_hwsim_tx_frame(data->hw, skb,
+				rcu_dereference(vif->chanctx_conf)->def.chan);
+	rcu_read_unlock();
 }
 
-
 static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
 				struct ieee80211_vif *vif, int ps)
 {
 	struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
 	struct sk_buff *skb;
 	struct ieee80211_hdr *hdr;
-	u32 _portid;
 
 	if (!vp->assoc)
 		return;
@@ -1374,15 +1668,10 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
 	memcpy(hdr->addr2, mac, ETH_ALEN);
 	memcpy(hdr->addr3, vp->bssid, ETH_ALEN);
 
-	/* wmediumd mode check */
-	_portid = ACCESS_ONCE(wmediumd_portid);
-
-	if (_portid)
-		return mac80211_hwsim_tx_frame_nl(data->hw, skb, _portid);
-
-	if (!mac80211_hwsim_tx_frame_no_nl(data->hw, skb))
-		printk(KERN_DEBUG "%s: nullfunc frame not ack'ed\n", __func__);
-	dev_kfree_skb(skb);
+	rcu_read_lock();
+	mac80211_hwsim_tx_frame(data->hw, skb,
+				rcu_dereference(vif->chanctx_conf)->def.chan);
+	rcu_read_unlock();
 }
 
 
@@ -1423,14 +1712,17 @@ static int hwsim_fops_ps_write(void *dat, u64 val)
 
 	if (val == PS_MANUAL_POLL) {
 		ieee80211_iterate_active_interfaces(data->hw,
+						    IEEE80211_IFACE_ITER_NORMAL,
 						    hwsim_send_ps_poll, data);
 		data->ps_poll_pending = true;
 	} else if (old_ps == PS_DISABLED && val != PS_DISABLED) {
 		ieee80211_iterate_active_interfaces(data->hw,
+						    IEEE80211_IFACE_ITER_NORMAL,
 						    hwsim_send_nullfunc_ps,
 						    data);
 	} else if (old_ps != PS_DISABLED && val == PS_DISABLED) {
 		ieee80211_iterate_active_interfaces(data->hw,
+						    IEEE80211_IFACE_ITER_NORMAL,
 						    hwsim_send_nullfunc_no_ps,
 						    data);
 	}
@@ -1551,7 +1843,8 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
 	   (hwsim_flags & HWSIM_TX_STAT_ACK)) {
 		if (skb->len >= 16) {
 			hdr = (struct ieee80211_hdr *) skb->data;
-			mac80211_hwsim_monitor_ack(data2->hw, hdr->addr2);
+			mac80211_hwsim_monitor_ack(txi->rate_driver_data[0],
+						   hdr->addr2);
 		}
 		txi->flags |= IEEE80211_TX_STAT_ACK;
 	}
@@ -1566,7 +1859,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
 					  struct genl_info *info)
 {
 
-	struct mac80211_hwsim_data  *data2;
+	struct mac80211_hwsim_data *data2;
 	struct ieee80211_rx_status rx_status;
 	struct mac_address *dst;
 	int frame_data_len;
@@ -1574,9 +1867,9 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
 	struct sk_buff *skb = NULL;
 
 	if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] ||
-	   !info->attrs[HWSIM_ATTR_FRAME] ||
-	   !info->attrs[HWSIM_ATTR_RX_RATE] ||
-	   !info->attrs[HWSIM_ATTR_SIGNAL])
+	    !info->attrs[HWSIM_ATTR_FRAME] ||
+	    !info->attrs[HWSIM_ATTR_RX_RATE] ||
+	    !info->attrs[HWSIM_ATTR_SIGNAL])
 		goto out;
 
 	dst = (struct mac_address *)nla_data(
@@ -1604,7 +1897,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
 
 	/* check if radio is configured properly */
 
-	if (data2->idle || !data2->started || !data2->channel)
+	if (data2->idle || !data2->started)
 		goto out;
 
 	/*A frame is received from user space*/
@@ -1688,6 +1981,11 @@ static struct notifier_block hwsim_netlink_notifier = {
 static int hwsim_init_netlink(void)
 {
 	int rc;
+
+	/* userspace test API hasn't been adjusted for multi-channel */
+	if (channels > 1)
+		return 0;
+
 	printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
 
 	rc = genl_register_family_with_ops(&hwsim_genl_family,
@@ -1710,6 +2008,10 @@ static void hwsim_exit_netlink(void)
 {
 	int ret;
 
+	/* userspace test API hasn't been adjusted for multi-channel */
+	if (channels > 1)
+		return;
+
 	printk(KERN_INFO "mac80211_hwsim: closing netlink\n");
 	/* unregister the notifier */
 	netlink_unregister_notifier(&hwsim_netlink_notifier);
@@ -1732,7 +2034,7 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = {
 	{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) },
 };
 
-static const struct ieee80211_iface_combination hwsim_if_comb = {
+static struct ieee80211_iface_combination hwsim_if_comb = {
 	.limits = hwsim_if_limits,
 	.n_limits = ARRAY_SIZE(hwsim_if_limits),
 	.max_interfaces = 2048,
@@ -1750,10 +2052,30 @@ static int __init init_mac80211_hwsim(void)
 	if (radios < 1 || radios > 100)
 		return -EINVAL;
 
-	if (fake_hw_scan) {
+	if (channels < 1)
+		return -EINVAL;
+
+	if (channels > 1) {
+		hwsim_if_comb.num_different_channels = channels;
 		mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan;
+		mac80211_hwsim_ops.cancel_hw_scan =
+			mac80211_hwsim_cancel_hw_scan;
 		mac80211_hwsim_ops.sw_scan_start = NULL;
 		mac80211_hwsim_ops.sw_scan_complete = NULL;
+		mac80211_hwsim_ops.remain_on_channel =
+			mac80211_hwsim_roc;
+		mac80211_hwsim_ops.cancel_remain_on_channel =
+			mac80211_hwsim_croc;
+		mac80211_hwsim_ops.add_chanctx =
+			mac80211_hwsim_add_chanctx;
+		mac80211_hwsim_ops.remove_chanctx =
+			mac80211_hwsim_remove_chanctx;
+		mac80211_hwsim_ops.change_chanctx =
+			mac80211_hwsim_change_chanctx;
+		mac80211_hwsim_ops.assign_vif_chanctx =
+			mac80211_hwsim_assign_vif_chanctx;
+		mac80211_hwsim_ops.unassign_vif_chanctx =
+			mac80211_hwsim_unassign_vif_chanctx;
 	}
 
 	spin_lock_init(&hwsim_radio_lock);
@@ -1803,13 +2125,18 @@ static int __init init_mac80211_hwsim(void)
 		hw->wiphy->iface_combinations = &hwsim_if_comb;
 		hw->wiphy->n_iface_combinations = 1;
 
-		if (fake_hw_scan) {
+		if (channels > 1) {
 			hw->wiphy->max_scan_ssids = 255;
 			hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
+			hw->wiphy->max_remain_on_channel_duration = 1000;
 		}
 
+		INIT_DELAYED_WORK(&data->roc_done, hw_roc_done);
+		INIT_DELAYED_WORK(&data->hw_scan, hw_scan_work);
+
 		hw->channel_change_time = 1;
-		hw->queues = 4;
+		hw->queues = 5;
+		hw->offchannel_tx_hw_queue = 4;
 		hw->wiphy->interface_modes =
 			BIT(NL80211_IFTYPE_STATION) |
 			BIT(NL80211_IFTYPE_AP) |
@@ -1824,7 +2151,8 @@ static int __init init_mac80211_hwsim(void)
 			    IEEE80211_HW_SUPPORTS_STATIC_SMPS |
 			    IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
 			    IEEE80211_HW_AMPDU_AGGREGATION |
-			    IEEE80211_HW_WANT_MONITOR_VIF;
+			    IEEE80211_HW_WANT_MONITOR_VIF |
+			    IEEE80211_HW_QUEUE_CONTROL;
 
 		hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
 				    WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
@@ -1874,6 +2202,34 @@ static int __init init_mac80211_hwsim(void)
 			sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
 
 			hw->wiphy->bands[band] = sband;
+
+			if (channels == 1)
+				continue;
+
+			sband->vht_cap.vht_supported = true;
+			sband->vht_cap.cap =
+				IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
+				IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ |
+				IEEE80211_VHT_CAP_RXLDPC |
+				IEEE80211_VHT_CAP_SHORT_GI_80 |
+				IEEE80211_VHT_CAP_SHORT_GI_160 |
+				IEEE80211_VHT_CAP_TXSTBC |
+				IEEE80211_VHT_CAP_RXSTBC_1 |
+				IEEE80211_VHT_CAP_RXSTBC_2 |
+				IEEE80211_VHT_CAP_RXSTBC_3 |
+				IEEE80211_VHT_CAP_RXSTBC_4 |
+				IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT;
+			sband->vht_cap.vht_mcs.rx_mcs_map =
+				cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_8 << 0 |
+					    IEEE80211_VHT_MCS_SUPPORT_0_8 << 2 |
+					    IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 |
+					    IEEE80211_VHT_MCS_SUPPORT_0_8 << 6 |
+					    IEEE80211_VHT_MCS_SUPPORT_0_8 << 8 |
+					    IEEE80211_VHT_MCS_SUPPORT_0_9 << 10 |
+					    IEEE80211_VHT_MCS_SUPPORT_0_9 << 12 |
+					    IEEE80211_VHT_MCS_SUPPORT_0_8 << 14);
+			sband->vht_cap.vht_mcs.tx_mcs_map =
+				sband->vht_cap.vht_mcs.rx_mcs_map;
 		}
 		/* By default all radios are belonging to the first group */
 		data->group = 1;
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index 395f1bf..68d52cf 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -197,7 +197,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
 				       ra_list_flags);
 		mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad);
 
-		mwifiex_write_data_complete(adapter, skb_src, 0);
+		mwifiex_write_data_complete(adapter, skb_src, 0, 0);
 
 		spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
 
@@ -256,7 +256,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
 		if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) {
 			spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
 					       ra_list_flags);
-			mwifiex_write_data_complete(adapter, skb_aggr, -1);
+			mwifiex_write_data_complete(adapter, skb_aggr, 1, -1);
 			return -1;
 		}
 		if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
@@ -282,13 +282,13 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
 		dev_err(adapter->dev, "%s: host_to_card failed: %#x\n",
 			__func__, ret);
 		adapter->dbg.num_tx_host_to_card_failure++;
-		mwifiex_write_data_complete(adapter, skb_aggr, ret);
+		mwifiex_write_data_complete(adapter, skb_aggr, 1, ret);
 		return 0;
 	case -EINPROGRESS:
 		adapter->data_sent = false;
 		break;
 	case 0:
-		mwifiex_write_data_complete(adapter, skb_aggr, ret);
+		mwifiex_write_data_complete(adapter, skb_aggr, 1, ret);
 		break;
 	default:
 		break;
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index 9402b93..4a97acd 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -58,8 +58,7 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv,
 			if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
 				mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
 			else
-				mwifiex_process_rx_packet(priv->adapter,
-							  rx_tmp_ptr);
+				mwifiex_process_rx_packet(priv, rx_tmp_ptr);
 		}
 	}
 
@@ -106,7 +105,7 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
 		if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
 			mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
 		else
-			mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
+			mwifiex_process_rx_packet(priv, rx_tmp_ptr);
 	}
 
 	spin_lock_irqsave(&priv->rx_pkt_lock, flags);
@@ -442,8 +441,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
 			if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
 				mwifiex_handle_uap_rx_forward(priv, payload);
 			else
-				mwifiex_process_rx_packet(priv->adapter,
-							  payload);
+				mwifiex_process_rx_packet(priv, payload);
 		}
 		return 0;
 	}
diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig
index 8e384fa..b2e2772 100644
--- a/drivers/net/wireless/mwifiex/Kconfig
+++ b/drivers/net/wireless/mwifiex/Kconfig
@@ -1,7 +1,6 @@
 config MWIFIEX
 	tristate "Marvell WiFi-Ex Driver"
 	depends on CFG80211
-	select LIB80211
 	---help---
 	  This adds support for wireless adapters based on Marvell
 	  802.11n chipsets.
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 780d3e1..3b1c277 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -180,10 +180,8 @@ mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len)
 static int
 mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 			 struct ieee80211_channel *chan, bool offchan,
-			 enum nl80211_channel_type channel_type,
-			 bool channel_type_valid, unsigned int wait,
-			 const u8 *buf, size_t len, bool no_cck,
-			 bool dont_wait_for_ack, u64 *cookie)
+			 unsigned int wait, const u8 *buf, size_t len,
+			 bool no_cck, bool dont_wait_for_ack, u64 *cookie)
 {
 	struct sk_buff *skb;
 	u16 pkt_len;
@@ -253,7 +251,6 @@ static int
 mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
 				   struct wireless_dev *wdev,
 				   struct ieee80211_channel *chan,
-				   enum nl80211_channel_type channel_type,
 				   unsigned int duration, u64 *cookie)
 {
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
@@ -271,15 +268,14 @@ mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
 	}
 
 	ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan,
-					 &channel_type, duration);
+					 duration);
 
 	if (!ret) {
 		*cookie = random32() | 1;
 		priv->roc_cfg.cookie = *cookie;
 		priv->roc_cfg.chan = *chan;
-		priv->roc_cfg.chan_type = channel_type;
 
-		cfg80211_ready_on_channel(wdev, *cookie, chan, channel_type,
+		cfg80211_ready_on_channel(wdev, *cookie, chan,
 					  duration, GFP_ATOMIC);
 
 		wiphy_dbg(wiphy, "info: ROC, cookie = 0x%llx\n", *cookie);
@@ -302,13 +298,11 @@ mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
 		return -ENOENT;
 
 	ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE,
-					 &priv->roc_cfg.chan,
-					 &priv->roc_cfg.chan_type, 0);
+					 &priv->roc_cfg.chan, 0);
 
 	if (!ret) {
 		cfg80211_remain_on_channel_expired(wdev, cookie,
 						   &priv->roc_cfg.chan,
-						   priv->roc_cfg.chan_type,
 						   GFP_ATOMIC);
 
 		memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg));
@@ -324,6 +318,7 @@ mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
  */
 static int
 mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy,
+			      struct wireless_dev *wdev,
 			      enum nl80211_tx_power_setting type,
 			      int mbm)
 {
@@ -471,13 +466,13 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
 			flag = 1;
 			first_chan = (u32) ch->hw_value;
 			next_chan = first_chan;
-			max_pwr = ch->max_reg_power;
+			max_pwr = ch->max_power;
 			no_of_parsed_chan = 1;
 			continue;
 		}
 
 		if (ch->hw_value == next_chan + 1 &&
-		    ch->max_reg_power == max_pwr) {
+		    ch->max_power == max_pwr) {
 			next_chan++;
 			no_of_parsed_chan++;
 		} else {
@@ -488,7 +483,7 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
 			no_of_triplet++;
 			first_chan = (u32) ch->hw_value;
 			next_chan = first_chan;
-			max_pwr = ch->max_reg_power;
+			max_pwr = ch->max_power;
 			no_of_parsed_chan = 1;
 		}
 	}
@@ -1296,21 +1291,23 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
 		return -EINVAL;
 	}
 
-	bss_cfg->channel =
-	    (u8)ieee80211_frequency_to_channel(params->channel->center_freq);
+	bss_cfg->channel = ieee80211_frequency_to_channel(
+				params->chandef.chan->center_freq);
 
 	/* Set appropriate bands */
-	if (params->channel->band == IEEE80211_BAND_2GHZ) {
+	if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) {
 		bss_cfg->band_cfg = BAND_CONFIG_BG;
 
-		if (params->channel_type == NL80211_CHAN_NO_HT)
+		if (cfg80211_get_chandef_type(&params->chandef) ==
+						NL80211_CHAN_NO_HT)
 			config_bands = BAND_B | BAND_G;
 		else
 			config_bands = BAND_B | BAND_G | BAND_GN;
 	} else {
 		bss_cfg->band_cfg = BAND_CONFIG_A;
 
-		if (params->channel_type == NL80211_CHAN_NO_HT)
+		if (cfg80211_get_chandef_type(&params->chandef) ==
+						NL80211_CHAN_NO_HT)
 			config_bands = BAND_A;
 		else
 			config_bands = BAND_AN | BAND_A;
@@ -1683,7 +1680,7 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
 	int index = 0, i;
 	u8 config_bands = 0;
 
-	if (params->channel->band == IEEE80211_BAND_2GHZ) {
+	if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) {
 		if (!params->basic_rates) {
 			config_bands = BAND_B | BAND_G;
 		} else {
@@ -1708,10 +1705,12 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
 			}
 		}
 
-		if (params->channel_type != NL80211_CHAN_NO_HT)
+		if (cfg80211_get_chandef_type(&params->chandef) !=
+						NL80211_CHAN_NO_HT)
 			config_bands |= BAND_GN;
 	} else {
-		if (params->channel_type == NL80211_CHAN_NO_HT)
+		if (cfg80211_get_chandef_type(&params->chandef) !=
+						NL80211_CHAN_NO_HT)
 			config_bands = BAND_A;
 		else
 			config_bands = BAND_AN | BAND_A;
@@ -1728,9 +1727,10 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
 	}
 
 	adapter->sec_chan_offset =
-		mwifiex_chan_type_to_sec_chan_offset(params->channel_type);
-	priv->adhoc_channel =
-		ieee80211_frequency_to_channel(params->channel->center_freq);
+		mwifiex_chan_type_to_sec_chan_offset(
+			cfg80211_get_chandef_type(&params->chandef));
+	priv->adhoc_channel = ieee80211_frequency_to_channel(
+				params->chandef.chan->center_freq);
 
 	wiphy_dbg(wiphy, "info: set ibss band %d, chan %d, chan offset %d\n",
 		  config_bands, priv->adhoc_channel, adapter->sec_chan_offset);
@@ -1764,7 +1764,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 
 	ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,
 				     params->bssid, priv->bss_mode,
-				     params->channel, NULL, params->privacy);
+				     params->chandef.chan, NULL,
+				     params->privacy);
 done:
 	if (!ret) {
 		cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
@@ -1819,12 +1820,18 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
 
 	wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name);
 
-	if (atomic_read(&priv->wmm.tx_pkts_queued) >=
+	if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
+	    atomic_read(&priv->wmm.tx_pkts_queued) >=
 	    MWIFIEX_MIN_TX_PENDING_TO_CANCEL_SCAN) {
 		dev_dbg(priv->adapter->dev, "scan rejected due to traffic\n");
 		return -EBUSY;
 	}
 
+	if (priv->user_scan_cfg) {
+		dev_err(priv->adapter->dev, "cmd: Scan already in process..\n");
+		return -EBUSY;
+	}
+
 	priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg),
 				      GFP_KERNEL);
 	if (!priv->user_scan_cfg) {
@@ -2074,8 +2081,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 		return ERR_PTR(-EINVAL);
 	}
 
-	dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), name,
-			      ether_setup, 1);
+	dev = alloc_netdev_mqs(sizeof(struct mwifiex_private *), name,
+			       ether_setup, IEEE80211_NUM_ACS, 1);
 	if (!dev) {
 		wiphy_err(wiphy, "no memory available for netdevice\n");
 		priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
@@ -2116,7 +2123,6 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 	}
 
 	sema_init(&priv->async_sem, 1);
-	priv->scan_pending_on_block = false;
 
 	dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name);
 
@@ -2138,8 +2144,7 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
 	mwifiex_dev_debugfs_remove(priv);
 #endif
 
-	if (!netif_queue_stopped(priv->netdev))
-		netif_stop_queue(priv->netdev);
+	mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
 
 	if (netif_carrier_ok(priv->netdev))
 		netif_carrier_off(priv->netdev);
@@ -2253,8 +2258,9 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
 	wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
 	wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
 
-	wiphy->features = NL80211_FEATURE_HT_IBSS |
-			  NL80211_FEATURE_INACTIVITY_TIMER;
+	wiphy->features |= NL80211_FEATURE_HT_IBSS |
+			   NL80211_FEATURE_INACTIVITY_TIMER |
+			   NL80211_FEATURE_LOW_PRIORITY_SCAN;
 
 	/* Reserve space for mwifiex specific private data for BSS */
 	wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index ae9010e..5f438e6 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -914,21 +914,24 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
 
 		dev_err(adapter->dev, "last_cmd_index = %d\n",
 			adapter->dbg.last_cmd_index);
-		print_hex_dump_bytes("last_cmd_id: ", DUMP_PREFIX_OFFSET,
-				     adapter->dbg.last_cmd_id, DBG_CMD_NUM);
-		print_hex_dump_bytes("last_cmd_act: ", DUMP_PREFIX_OFFSET,
-				     adapter->dbg.last_cmd_act, DBG_CMD_NUM);
+		dev_err(adapter->dev, "last_cmd_id: %*ph\n",
+			(int)sizeof(adapter->dbg.last_cmd_id),
+			adapter->dbg.last_cmd_id);
+		dev_err(adapter->dev, "last_cmd_act: %*ph\n",
+			(int)sizeof(adapter->dbg.last_cmd_act),
+			adapter->dbg.last_cmd_act);
 
 		dev_err(adapter->dev, "last_cmd_resp_index = %d\n",
 			adapter->dbg.last_cmd_resp_index);
-		print_hex_dump_bytes("last_cmd_resp_id: ", DUMP_PREFIX_OFFSET,
-				     adapter->dbg.last_cmd_resp_id,
-				     DBG_CMD_NUM);
+		dev_err(adapter->dev, "last_cmd_resp_id: %*ph\n",
+			(int)sizeof(adapter->dbg.last_cmd_resp_id),
+			adapter->dbg.last_cmd_resp_id);
 
 		dev_err(adapter->dev, "last_event_index = %d\n",
 			adapter->dbg.last_event_index);
-		print_hex_dump_bytes("last_event: ", DUMP_PREFIX_OFFSET,
-				     adapter->dbg.last_event, DBG_CMD_NUM);
+		dev_err(adapter->dev, "last_event: %*ph\n",
+			(int)sizeof(adapter->dbg.last_event),
+			adapter->dbg.last_event);
 
 		dev_err(adapter->dev, "data_sent=%d cmd_sent=%d\n",
 			adapter->data_sent, adapter->cmd_sent);
@@ -946,6 +949,9 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
 	}
 	if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
 		mwifiex_init_fw_complete(adapter);
+
+	if (adapter->if_ops.card_reset)
+		adapter->if_ops.card_reset(adapter);
 }
 
 /*
diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c
index a870b58..46e34aa 100644
--- a/drivers/net/wireless/mwifiex/debugfs.c
+++ b/drivers/net/wireless/mwifiex/debugfs.c
@@ -178,6 +178,7 @@ mwifiex_info_read(struct file *file, char __user *ubuf,
 		(struct mwifiex_private *) file->private_data;
 	struct net_device *netdev = priv->netdev;
 	struct netdev_hw_addr *ha;
+	struct netdev_queue *txq;
 	unsigned long page = get_zeroed_page(GFP_KERNEL);
 	char *p = (char *) page, fmt[64];
 	struct mwifiex_bss_info info;
@@ -229,8 +230,13 @@ mwifiex_info_read(struct file *file, char __user *ubuf,
 	p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
 	p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev))
 					 ? "on" : "off"));
-	p += sprintf(p, "tx queue %s\n", ((netif_queue_stopped(priv->netdev))
-					  ? "stopped" : "started"));
+	p += sprintf(p, "tx queue");
+	for (i = 0; i < netdev->num_tx_queues; i++) {
+		txq = netdev_get_tx_queue(netdev, i);
+		p += sprintf(p, " %d:%s", i, netif_tx_queue_stopped(txq) ?
+			     "stopped" : "started");
+	}
+	p += sprintf(p, "\n");
 
 	ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
 				      (unsigned long) p - page);
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index b5d37a8..39f03ce 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -84,18 +84,19 @@ static void scan_delay_timer_fn(unsigned long data)
 		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
 
 		if (priv->user_scan_cfg) {
-			dev_dbg(priv->adapter->dev,
-				"info: %s: scan aborted\n", __func__);
-			cfg80211_scan_done(priv->scan_request, 1);
-			priv->scan_request = NULL;
+			if (priv->scan_request) {
+				dev_dbg(priv->adapter->dev,
+					"info: aborting scan\n");
+				cfg80211_scan_done(priv->scan_request, 1);
+				priv->scan_request = NULL;
+			} else {
+				dev_dbg(priv->adapter->dev,
+					"info: scan already aborted\n");
+			}
+
 			kfree(priv->user_scan_cfg);
 			priv->user_scan_cfg = NULL;
 		}
-
-		if (priv->scan_pending_on_block) {
-			priv->scan_pending_on_block = false;
-			up(&priv->async_sem);
-		}
 		goto done;
 	}
 
@@ -387,9 +388,17 @@ void mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
 					struct mwifiex_adapter *adapter)
 {
 	unsigned long dev_queue_flags;
+	unsigned int i;
 
 	spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
-	netif_tx_wake_all_queues(netdev);
+
+	for (i = 0; i < netdev->num_tx_queues; i++) {
+		struct netdev_queue *txq = netdev_get_tx_queue(netdev, i);
+
+		if (netif_tx_queue_stopped(txq))
+			netif_tx_wake_queue(txq);
+	}
+
 	spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
 }
 
@@ -400,9 +409,17 @@ void mwifiex_stop_net_dev_queue(struct net_device *netdev,
 					struct mwifiex_adapter *adapter)
 {
 	unsigned long dev_queue_flags;
+	unsigned int i;
 
 	spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
-	netif_tx_stop_all_queues(netdev);
+
+	for (i = 0; i < netdev->num_tx_queues; i++) {
+		struct netdev_queue *txq = netdev_get_tx_queue(netdev, i);
+
+		if (!netif_tx_queue_stopped(txq))
+			netif_tx_stop_queue(txq);
+	}
+
 	spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
 }
 
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 7b0858a..88664ae 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -721,8 +721,7 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
 
 	if (!netif_carrier_ok(priv->netdev))
 		netif_carrier_on(priv->netdev);
-	if (netif_queue_stopped(priv->netdev))
-		netif_wake_queue(priv->netdev);
+	mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
 
 	if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
 		priv->scan_block = true;
@@ -1238,8 +1237,7 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
 
 	if (!netif_carrier_ok(priv->netdev))
 		netif_carrier_on(priv->netdev);
-	if (netif_queue_stopped(priv->netdev))
-		netif_wake_queue(priv->netdev);
+	mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
 
 	mwifiex_save_curr_bcn(priv);
 
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index eb22dd2..9c802ed 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -282,6 +282,7 @@ exit_main_proc:
 		mwifiex_shutdown_drv(adapter);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(mwifiex_main_process);
 
 /*
  * This function frees the adapter structure.
@@ -412,49 +413,6 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
 }
 
 /*
- * This function fills a driver buffer.
- *
- * The function associates a given SKB with the provided driver buffer
- * and also updates some of the SKB parameters, including IP header,
- * priority and timestamp.
- */
-static void
-mwifiex_fill_buffer(struct sk_buff *skb)
-{
-	struct ethhdr *eth;
-	struct iphdr *iph;
-	struct timeval tv;
-	u8 tid = 0;
-
-	eth = (struct ethhdr *) skb->data;
-	switch (eth->h_proto) {
-	case __constant_htons(ETH_P_IP):
-		iph = ip_hdr(skb);
-		tid = IPTOS_PREC(iph->tos);
-		pr_debug("data: packet type ETH_P_IP: %04x, tid=%#x prio=%#x\n",
-			 eth->h_proto, tid, skb->priority);
-		break;
-	case __constant_htons(ETH_P_ARP):
-		pr_debug("data: ARP packet: %04x\n", eth->h_proto);
-	default:
-		break;
-	}
-/* Offset for TOS field in the IP header */
-#define IPTOS_OFFSET 5
-	tid = (tid >> IPTOS_OFFSET);
-	skb->priority = tid;
-	/* Record the current time the packet was queued; used to
-	   determine the amount of time the packet was queued in
-	   the driver before it was sent to the firmware.
-	   The delay is then sent along with the packet to the
-	   firmware for aggregate delay calculation for stats and
-	   MSDU lifetime expiry.
-	 */
-	do_gettimeofday(&tv);
-	skb->tstamp = timeval_to_ktime(tv);
-}
-
-/*
  * CFG802.11 network device handler for open.
  *
  * Starts the data queue.
@@ -472,6 +430,14 @@ mwifiex_open(struct net_device *dev)
 static int
 mwifiex_close(struct net_device *dev)
 {
+	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+	if (priv->scan_request) {
+		dev_dbg(priv->adapter->dev, "aborting scan on ndo_stop\n");
+		cfg80211_scan_done(priv->scan_request, 1);
+		priv->scan_request = NULL;
+	}
+
 	return 0;
 }
 
@@ -480,17 +446,23 @@ mwifiex_close(struct net_device *dev)
  */
 int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb)
 {
-	mwifiex_wmm_add_buf_txqueue(priv, skb);
+	struct netdev_queue *txq;
+	int index = mwifiex_1d_to_wmm_queue[skb->priority];
+
+	if (atomic_inc_return(&priv->wmm_tx_pending[index]) >= MAX_TX_PENDING) {
+		txq = netdev_get_tx_queue(priv->netdev, index);
+		if (!netif_tx_queue_stopped(txq)) {
+			netif_tx_stop_queue(txq);
+			dev_dbg(priv->adapter->dev, "stop queue: %d\n", index);
+		}
+	}
+
 	atomic_inc(&priv->adapter->tx_pending);
+	mwifiex_wmm_add_buf_txqueue(priv, skb);
 
 	if (priv->adapter->scan_delay_cnt)
 		atomic_set(&priv->adapter->is_tx_received, true);
 
-	if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) {
-		mwifiex_set_trans_start(priv->netdev);
-		mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
-	}
-
 	queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
 
 	return 0;
@@ -505,6 +477,7 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 	struct sk_buff *new_skb;
 	struct mwifiex_txinfo *tx_info;
+	struct timeval tv;
 
 	dev_dbg(priv->adapter->dev, "data: %lu BSS(%d-%d): Data <= kernel\n",
 		jiffies, priv->bss_type, priv->bss_num);
@@ -542,7 +515,16 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	tx_info = MWIFIEX_SKB_TXCB(skb);
 	tx_info->bss_num = priv->bss_num;
 	tx_info->bss_type = priv->bss_type;
-	mwifiex_fill_buffer(skb);
+
+	/* Record the current time the packet was queued; used to
+	 * determine the amount of time the packet was queued in
+	 * the driver before it was sent to the firmware.
+	 * The delay is then sent along with the packet to the
+	 * firmware for aggregate delay calculation for stats and
+	 * MSDU lifetime expiry.
+	 */
+	do_gettimeofday(&tv);
+	skb->tstamp = timeval_to_ktime(tv);
 
 	mwifiex_queue_tx_pkt(priv, skb);
 
@@ -622,6 +604,13 @@ static struct net_device_stats *mwifiex_get_stats(struct net_device *dev)
 	return &priv->stats;
 }
 
+static u16
+mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb)
+{
+	skb->priority = cfg80211_classify8021d(skb);
+	return mwifiex_1d_to_wmm_queue[skb->priority];
+}
+
 /* Network device handlers */
 static const struct net_device_ops mwifiex_netdev_ops = {
 	.ndo_open = mwifiex_open,
@@ -631,6 +620,7 @@ static const struct net_device_ops mwifiex_netdev_ops = {
 	.ndo_tx_timeout = mwifiex_tx_timeout,
 	.ndo_get_stats = mwifiex_get_stats,
 	.ndo_set_rx_mode = mwifiex_set_multicast_list,
+	.ndo_select_queue = mwifiex_netdev_select_wmm_queue,
 };
 
 /*
@@ -830,9 +820,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
 	for (i = 0; i < adapter->priv_num; i++) {
 		priv = adapter->priv[i];
 		if (priv && priv->netdev) {
-			if (!netif_queue_stopped(priv->netdev))
-				mwifiex_stop_net_dev_queue(priv->netdev,
-							   adapter);
+			mwifiex_stop_net_dev_queue(priv->netdev, adapter);
 			if (netif_carrier_ok(priv->netdev))
 				netif_carrier_off(priv->netdev);
 		}
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index c2d0ab1..1b3cfc8 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -115,8 +115,6 @@ enum {
 #define MWIFIEX_TYPE_DATA				0
 #define MWIFIEX_TYPE_EVENT				3
 
-#define DBG_CMD_NUM						5
-
 #define MAX_BITMAP_RATES_SIZE			10
 
 #define MAX_CHANNEL_BAND_BG     14
@@ -373,7 +371,6 @@ struct wps {
 struct mwifiex_roc_cfg {
 	u64 cookie;
 	struct ieee80211_channel chan;
-	enum nl80211_channel_type chan_type;
 };
 
 struct mwifiex_adapter;
@@ -442,6 +439,7 @@ struct mwifiex_private {
 	u8 wmm_enabled;
 	u8 wmm_qosinfo;
 	struct mwifiex_wmm_desc wmm;
+	atomic_t wmm_tx_pending[IEEE80211_NUM_ACS];
 	struct list_head sta_list;
 	/* spin lock for associated station list */
 	spinlock_t sta_list_spinlock;
@@ -484,7 +482,6 @@ struct mwifiex_private {
 	u8 nick_name[16];
 	u16 current_key_index;
 	struct semaphore async_sem;
-	u8 scan_pending_on_block;
 	u8 report_scan_result;
 	struct cfg80211_scan_request *scan_request;
 	struct mwifiex_user_scan_cfg *user_scan_cfg;
@@ -603,6 +600,7 @@ struct mwifiex_if_ops {
 	int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *);
 	int (*data_complete) (struct mwifiex_adapter *, struct sk_buff *);
 	int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *);
+	void (*card_reset) (struct mwifiex_adapter *);
 };
 
 struct mwifiex_adapter {
@@ -750,9 +748,9 @@ int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter);
 
 int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *);
 
-int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb);
+int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb);
 
-int mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter,
+int mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
 				struct sk_buff *skb);
 
 int mwifiex_process_event(struct mwifiex_adapter *adapter);
@@ -791,7 +789,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
 		       struct mwifiex_tx_param *tx_param);
 int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags);
 int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
-				struct sk_buff *skb, int status);
+				struct sk_buff *skb, int aggr, int status);
 void mwifiex_clean_txrx(struct mwifiex_private *priv);
 u8 mwifiex_check_last_packet_indication(struct mwifiex_private *priv);
 void mwifiex_check_ps_cond(struct mwifiex_adapter *adapter);
@@ -809,7 +807,7 @@ void mwifiex_hs_activated_event(struct mwifiex_private *priv,
 					u8 activated);
 int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
 			      struct host_cmd_ds_command *resp);
-int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
+int mwifiex_process_rx_packet(struct mwifiex_private *priv,
 			      struct sk_buff *skb);
 int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no,
 			    u16 cmd_action, u32 cmd_oid,
@@ -819,9 +817,9 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
 			    void *data_buf, void *cmd_buf);
 int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
 				struct host_cmd_ds_command *resp);
-int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,
+int mwifiex_process_sta_rx_packet(struct mwifiex_private *,
 				  struct sk_buff *skb);
-int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
+int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
 				  struct sk_buff *skb);
 int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
 				  struct sk_buff *skb);
@@ -1019,7 +1017,6 @@ int mwifiex_get_ver_ext(struct mwifiex_private *priv);
 
 int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
 			       struct ieee80211_channel *chan,
-			       enum nl80211_channel_type *channel_type,
 			       unsigned int duration);
 
 int mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 9171aae..9189a32 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -153,7 +153,7 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
 
 	if (((bss_desc->bcn_wpa_ie) &&
 	     ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id ==
-	      WLAN_EID_WPA))) {
+	      WLAN_EID_VENDOR_SPECIFIC))) {
 		iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data;
 		oui = &mwifiex_wpa_oui[cipher][0];
 		ret = mwifiex_search_oui_in_ie(iebody, oui);
@@ -202,7 +202,7 @@ mwifiex_is_bss_no_sec(struct mwifiex_private *priv,
 	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
 	    !priv->sec_info.wpa2_enabled && ((!bss_desc->bcn_wpa_ie) ||
 		((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id !=
-		 WLAN_EID_WPA)) &&
+		 WLAN_EID_VENDOR_SPECIFIC)) &&
 	    ((!bss_desc->bcn_rsn_ie) ||
 		((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id !=
 		 WLAN_EID_RSN)) &&
@@ -237,7 +237,8 @@ mwifiex_is_bss_wpa(struct mwifiex_private *priv,
 {
 	if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled &&
 	    !priv->sec_info.wpa2_enabled && ((bss_desc->bcn_wpa_ie) &&
-	    ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id == WLAN_EID_WPA))
+	    ((*(bss_desc->bcn_wpa_ie)).
+	     vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC))
 	   /*
 	    * Privacy bit may NOT be set in some APs like
 	    * LinkSys WRT54G && bss_desc->privacy
@@ -309,7 +310,8 @@ mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv,
 	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
 	    !priv->sec_info.wpa2_enabled &&
 	    ((!bss_desc->bcn_wpa_ie) ||
-	     ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != WLAN_EID_WPA)) &&
+	     ((*(bss_desc->bcn_wpa_ie)).
+	      vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) &&
 	    ((!bss_desc->bcn_rsn_ie) ||
 	     ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
 	    !priv->sec_info.encryption_mode && bss_desc->privacy) {
@@ -329,7 +331,8 @@ mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv,
 	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
 	    !priv->sec_info.wpa2_enabled &&
 	    ((!bss_desc->bcn_wpa_ie) ||
-	     ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != WLAN_EID_WPA)) &&
+	     ((*(bss_desc->bcn_wpa_ie)).
+	      vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) &&
 	    ((!bss_desc->bcn_rsn_ie) ||
 	     ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
 	    priv->sec_info.encryption_mode && bss_desc->privacy) {
@@ -938,6 +941,11 @@ mwifiex_config_scan(struct mwifiex_private *priv,
 				 chan_idx)->chan_scan_mode_bitmap
 					&= ~MWIFIEX_PASSIVE_SCAN;
 
+			if (*filtered_scan)
+				(scan_chan_list +
+				 chan_idx)->chan_scan_mode_bitmap
+					|= MWIFIEX_DISABLE_CHAN_FILT;
+
 			if (user_scan_in->chan_list[chan_idx].scan_time) {
 				scan_dur = (u16) user_scan_in->
 					chan_list[chan_idx].scan_time;
@@ -1759,26 +1767,39 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
 		}
 		if (priv->report_scan_result)
 			priv->report_scan_result = false;
-		if (priv->scan_pending_on_block) {
-			priv->scan_pending_on_block = false;
-			up(&priv->async_sem);
-		}
 
 		if (priv->user_scan_cfg) {
-			dev_dbg(priv->adapter->dev,
-				"info: %s: sending scan results\n", __func__);
-			cfg80211_scan_done(priv->scan_request, 0);
-			priv->scan_request = NULL;
+			if (priv->scan_request) {
+				dev_dbg(priv->adapter->dev,
+					"info: notifying scan done\n");
+				cfg80211_scan_done(priv->scan_request, 0);
+				priv->scan_request = NULL;
+			} else {
+				dev_dbg(priv->adapter->dev,
+					"info: scan already aborted\n");
+			}
+
 			kfree(priv->user_scan_cfg);
 			priv->user_scan_cfg = NULL;
 		}
 	} else {
-		if (!mwifiex_wmm_lists_empty(adapter)) {
+		if (priv->user_scan_cfg && !priv->scan_request) {
+			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
+					       flags);
+			adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT;
+			mod_timer(&priv->scan_delay_timer, jiffies);
+			dev_dbg(priv->adapter->dev,
+				"info: %s: triggerring scan abort\n", __func__);
+		} else if (!mwifiex_wmm_lists_empty(adapter) &&
+			   (priv->scan_request && (priv->scan_request->flags &
+					    NL80211_SCAN_FLAG_LOW_PRIORITY))) {
 			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
 					       flags);
 			adapter->scan_delay_cnt = 1;
 			mod_timer(&priv->scan_delay_timer, jiffies +
 				  msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
+			dev_dbg(priv->adapter->dev,
+				"info: %s: deferring scan\n", __func__);
 		} else {
 			/* Get scan command from scan_pending_q and put to
 			   cmd_pending_q */
@@ -1891,7 +1912,6 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
 			__func__);
 		return -1;
 	}
-	priv->scan_pending_on_block = true;
 
 	priv->adapter->scan_wait_q_woken = false;
 
@@ -1905,10 +1925,7 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
 	if (!ret)
 		ret = mwifiex_wait_queue_complete(priv->adapter);
 
-	if (ret == -1) {
-		priv->scan_pending_on_block = false;
-		up(&priv->async_sem);
-	}
+	up(&priv->async_sem);
 
 	return ret;
 }
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 82cf0fa..5a1c1d0 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -906,8 +906,8 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
 /*
  * SDIO interrupt handler.
  *
- * This function reads the interrupt status from firmware and assigns
- * the main process in workqueue which will handle the interrupt.
+ * This function reads the interrupt status from firmware and handles
+ * the interrupt in current thread (ksdioirqd) right away.
  */
 static void
 mwifiex_sdio_interrupt(struct sdio_func *func)
@@ -930,7 +930,7 @@ mwifiex_sdio_interrupt(struct sdio_func *func)
 		adapter->ps_state = PS_STATE_AWAKE;
 
 	mwifiex_interrupt_status(adapter);
-	queue_work(adapter->workqueue, &adapter->main_work);
+	mwifiex_main_process(adapter);
 }
 
 /*
@@ -1749,6 +1749,37 @@ mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port)
 		port, card->mp_data_port_mask);
 }
 
+static struct mmc_host *reset_host;
+static void sdio_card_reset_worker(struct work_struct *work)
+{
+	/* The actual reset operation must be run outside of driver thread.
+	 * This is because mmc_remove_host() will cause the device to be
+	 * instantly destroyed, and the driver then needs to end its thread,
+	 * leading to a deadlock.
+	 *
+	 * We run it in a totally independent workqueue.
+	 */
+
+	pr_err("Resetting card...\n");
+	mmc_remove_host(reset_host);
+	/* 20ms delay is based on experiment with sdhci controller */
+	mdelay(20);
+	mmc_add_host(reset_host);
+}
+static DECLARE_WORK(card_reset_work, sdio_card_reset_worker);
+
+/* This function resets the card */
+static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter)
+{
+	struct sdio_mmc_card *card = adapter->card;
+
+	if (work_pending(&card_reset_work))
+		return;
+
+	reset_host = card->func->card->host;
+	schedule_work(&card_reset_work);
+}
+
 static struct mwifiex_if_ops sdio_ops = {
 	.init_if = mwifiex_init_sdio,
 	.cleanup_if = mwifiex_cleanup_sdio,
@@ -1767,6 +1798,7 @@ static struct mwifiex_if_ops sdio_ops = {
 	.cleanup_mpa_buf = mwifiex_cleanup_mpa_buf,
 	.cmdrsp_complete = mwifiex_sdio_cmdrsp_complete,
 	.event_complete = mwifiex_sdio_event_complete,
+	.card_reset = mwifiex_sdio_card_reset,
 };
 
 /*
@@ -1804,6 +1836,7 @@ mwifiex_sdio_cleanup_module(void)
 	/* Set the flag as user is removing this module. */
 	user_rmmod = 1;
 
+	cancel_work_sync(&card_reset_work);
 	sdio_unregister_driver(&mwifiex_sdio);
 }
 
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
index 2103373..8cc5468 100644
--- a/drivers/net/wireless/mwifiex/sdio.h
+++ b/drivers/net/wireless/mwifiex/sdio.h
@@ -25,6 +25,7 @@
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
 
 #include "main.h"
 
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 09e6a26..65c12eb 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -85,10 +85,6 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
 		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
 		if (priv->report_scan_result)
 			priv->report_scan_result = false;
-		if (priv->scan_pending_on_block) {
-			priv->scan_pending_on_block = false;
-			up(&priv->async_sem);
-		}
 		break;
 
 	case HostCmd_CMD_MAC_CONTROL:
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index 8132119..41aafc7 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -124,8 +124,7 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
 	}
 	memset(priv->cfg_bssid, 0, ETH_ALEN);
 
-	if (!netif_queue_stopped(priv->netdev))
-		mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+	mwifiex_stop_net_dev_queue(priv->netdev, adapter);
 	if (netif_carrier_ok(priv->netdev))
 		netif_carrier_off(priv->netdev);
 }
@@ -197,8 +196,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 		dev_dbg(adapter->dev, "event: LINK_SENSED\n");
 		if (!netif_carrier_ok(priv->netdev))
 			netif_carrier_on(priv->netdev);
-		if (netif_queue_stopped(priv->netdev))
-			mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
+		mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
 		break;
 
 	case EVENT_DEAUTHENTICATED:
@@ -306,8 +304,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 		dev_dbg(adapter->dev, "event: ADHOC_BCN_LOST\n");
 		priv->adhoc_is_link_sensed = false;
 		mwifiex_clean_txrx(priv);
-		if (!netif_queue_stopped(priv->netdev))
-			mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+		mwifiex_stop_net_dev_queue(priv->netdev, adapter);
 		if (netif_carrier_ok(priv->netdev))
 			netif_carrier_off(priv->netdev);
 		break;
@@ -424,7 +421,6 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 		cfg80211_remain_on_channel_expired(priv->wdev,
 						   priv->roc_cfg.cookie,
 						   &priv->roc_cfg.chan,
-						   priv->roc_cfg.chan_type,
 						   GFP_ATOMIC);
 
 		memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg));
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 0c9f70b..237c8d2b 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -276,8 +276,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
 		dev_dbg(adapter->dev, "info: SSID found in scan list ... "
 				      "associating...\n");
 
-		if (!netif_queue_stopped(priv->netdev))
-			mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+		mwifiex_stop_net_dev_queue(priv->netdev, adapter);
 		if (netif_carrier_ok(priv->netdev))
 			netif_carrier_off(priv->netdev);
 
@@ -318,8 +317,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
 
 		ret = mwifiex_check_network_compatibility(priv, bss_desc);
 
-		if (!netif_queue_stopped(priv->netdev))
-			mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+		mwifiex_stop_net_dev_queue(priv->netdev, adapter);
 		if (netif_carrier_ok(priv->netdev))
 			netif_carrier_off(priv->netdev);
 
@@ -713,7 +711,7 @@ static int mwifiex_set_wpa_ie_helper(struct mwifiex_private *priv,
 		dev_dbg(priv->adapter->dev, "cmd: Set Wpa_ie_len=%d IE=%#x\n",
 			priv->wpa_ie_len, priv->wpa_ie[0]);
 
-		if (priv->wpa_ie[0] == WLAN_EID_WPA) {
+		if (priv->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
 			priv->sec_info.wpa_enabled = true;
 		} else if (priv->wpa_ie[0] == WLAN_EID_RSN) {
 			priv->sec_info.wpa2_enabled = true;
@@ -1046,7 +1044,6 @@ mwifiex_get_ver_ext(struct mwifiex_private *priv)
 int
 mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
 			   struct ieee80211_channel *chan,
-			   enum nl80211_channel_type *ct,
 			   unsigned int duration)
 {
 	struct host_cmd_ds_remain_on_chan roc_cfg;
@@ -1056,7 +1053,7 @@ mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
 	roc_cfg.action = cpu_to_le16(action);
 	if (action == HostCmd_ACT_GEN_SET) {
 		roc_cfg.band_cfg = chan->band;
-		sc = mwifiex_chan_type_to_sec_chan_offset(*ct);
+		sc = mwifiex_chan_type_to_sec_chan_offset(NL80211_CHAN_NO_HT);
 		roc_cfg.band_cfg |= (sc << 2);
 
 		roc_cfg.channel =
@@ -1253,7 +1250,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
 	}
 	pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
 	/* Test to see if it is a WPA IE, if not, then it is a gen IE */
-	if (((pvendor_ie->element_id == WLAN_EID_WPA) &&
+	if (((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
 	     (!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) ||
 	    (pvendor_ie->element_id == WLAN_EID_RSN)) {
 
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index 07d32b7..b5c1095 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -38,14 +38,10 @@
  *
  * The completion callback is called after processing in complete.
  */
-int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
+int mwifiex_process_rx_packet(struct mwifiex_private *priv,
 			      struct sk_buff *skb)
 {
 	int ret;
-	struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
-	struct mwifiex_private *priv =
-			mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
-					       rx_info->bss_type);
 	struct rx_packet_hdr *rx_pkt_hdr;
 	struct rxpd *local_rx_pd;
 	int hdr_chop;
@@ -98,9 +94,9 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
 
 	priv->rxpd_htinfo = local_rx_pd->ht_info;
 
-	ret = mwifiex_recv_packet(adapter, skb);
+	ret = mwifiex_recv_packet(priv, skb);
 	if (ret == -1)
-		dev_err(adapter->dev, "recv packet failed\n");
+		dev_err(priv->adapter->dev, "recv packet failed\n");
 
 	return ret;
 }
@@ -117,21 +113,15 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
  *
  * The completion callback is called after processing in complete.
  */
-int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
+int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
 				  struct sk_buff *skb)
 {
+	struct mwifiex_adapter *adapter = priv->adapter;
 	int ret = 0;
 	struct rxpd *local_rx_pd;
-	struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
 	struct rx_packet_hdr *rx_pkt_hdr;
 	u8 ta[ETH_ALEN];
 	u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num;
-	struct mwifiex_private *priv =
-			mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
-					       rx_info->bss_type);
-
-	if (!priv)
-		return -1;
 
 	local_rx_pd = (struct rxpd *) (skb->data);
 	rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type);
@@ -169,13 +159,13 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
 
 		while (!skb_queue_empty(&list)) {
 			rx_skb = __skb_dequeue(&list);
-			ret = mwifiex_recv_packet(adapter, rx_skb);
+			ret = mwifiex_recv_packet(priv, rx_skb);
 			if (ret == -1)
 				dev_err(adapter->dev, "Rx of A-MSDU failed");
 		}
 		return 0;
 	} else if (rx_pkt_type == PKT_TYPE_MGMT) {
-		ret = mwifiex_process_mgmt_packet(adapter, skb);
+		ret = mwifiex_process_mgmt_packet(priv, skb);
 		if (ret)
 			dev_err(adapter->dev, "Rx of mgmt packet failed");
 		dev_kfree_skb_any(skb);
@@ -188,7 +178,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
 	 */
 	if (!IS_11N_ENABLED(priv) ||
 	    memcmp(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN)) {
-		mwifiex_process_rx_packet(adapter, skb);
+		mwifiex_process_rx_packet(priv, skb);
 		return ret;
 	}
 
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index 2af2639..8c80024 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -48,13 +48,19 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
 	if (!priv)
 		priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 
+	if (!priv) {
+		dev_err(adapter->dev, "data: priv not found. Drop RX packet\n");
+		dev_kfree_skb_any(skb);
+		return -1;
+	}
+
 	rx_info->bss_num = priv->bss_num;
 	rx_info->bss_type = priv->bss_type;
 
 	if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
-		return mwifiex_process_uap_rx_packet(adapter, skb);
+		return mwifiex_process_uap_rx_packet(priv, skb);
 
-	return mwifiex_process_sta_rx_packet(adapter, skb);
+	return mwifiex_process_sta_rx_packet(priv, skb);
 }
 EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);
 
@@ -115,13 +121,13 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
 		dev_err(adapter->dev, "mwifiex_write_data_async failed: 0x%X\n",
 			ret);
 		adapter->dbg.num_tx_host_to_card_failure++;
-		mwifiex_write_data_complete(adapter, skb, ret);
+		mwifiex_write_data_complete(adapter, skb, 0, ret);
 		break;
 	case -EINPROGRESS:
 		adapter->data_sent = false;
 		break;
 	case 0:
-		mwifiex_write_data_complete(adapter, skb, ret);
+		mwifiex_write_data_complete(adapter, skb, 0, ret);
 		break;
 	default:
 		break;
@@ -138,11 +144,12 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
  * wakes up stalled traffic queue if required, and then frees the buffer.
  */
 int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
-				struct sk_buff *skb, int status)
+				struct sk_buff *skb, int aggr, int status)
 {
-	struct mwifiex_private *priv, *tpriv;
+	struct mwifiex_private *priv;
 	struct mwifiex_txinfo *tx_info;
-	int i;
+	struct netdev_queue *txq;
+	int index;
 
 	if (!skb)
 		return 0;
@@ -166,15 +173,20 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
 
 	if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT)
 		atomic_dec_return(&adapter->pending_bridged_pkts);
-	if (atomic_dec_return(&adapter->tx_pending) >= LOW_TX_PENDING)
+
+	if (aggr)
+		/* For skb_aggr, do not wake up tx queue */
 		goto done;
 
-	for (i = 0; i < adapter->priv_num; i++) {
-		tpriv = adapter->priv[i];
+	atomic_dec(&adapter->tx_pending);
 
-		if (tpriv->media_connected &&
-		    netif_queue_stopped(tpriv->netdev))
-			mwifiex_wake_up_net_dev_queue(tpriv->netdev, adapter);
+	index = mwifiex_1d_to_wmm_queue[skb->priority];
+	if (atomic_dec_return(&priv->wmm_tx_pending[index]) < LOW_TX_PENDING) {
+		txq = netdev_get_tx_queue(priv->netdev, index);
+		if (netif_tx_queue_stopped(txq)) {
+			netif_tx_wake_queue(txq);
+			dev_dbg(adapter->dev, "wake queue: %d\n", index);
+		}
 	}
 done:
 	dev_kfree_skb_any(skb);
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c
index d95a2d5..8dd7224 100644
--- a/drivers/net/wireless/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/mwifiex/uap_cmd.c
@@ -188,10 +188,19 @@ mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
 	int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
 	const u8 *var_pos = params->beacon.head + var_offset;
 	int len = params->beacon.head_len - var_offset;
+	u8 rate_len = 0;
 
 	rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len);
-	if (rate_ie)
+	if (rate_ie) {
 		memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len);
+		rate_len = rate_ie->len;
+	}
+
+	rate_ie = (void *)cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES,
+					   params->beacon.tail,
+					   params->beacon.tail_len);
+	if (rate_ie)
+		memcpy(bss_cfg->rates + rate_len, rate_ie + 1, rate_ie->len);
 
 	return;
 }
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index a33fa39..21c640d 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -235,11 +235,18 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
 		break;
 	case EVENT_UAP_BSS_IDLE:
 		priv->media_connected = false;
+		if (netif_carrier_ok(priv->netdev))
+			netif_carrier_off(priv->netdev);
+		mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+
 		mwifiex_clean_txrx(priv);
 		mwifiex_del_all_sta_list(priv);
 		break;
 	case EVENT_UAP_BSS_ACTIVE:
 		priv->media_connected = true;
+		if (!netif_carrier_ok(priv->netdev))
+			netif_carrier_on(priv->netdev);
+		mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
 		break;
 	case EVENT_UAP_BSS_START:
 		dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c
index 0966ac2..a018e42 100644
--- a/drivers/net/wireless/mwifiex/uap_txrx.c
+++ b/drivers/net/wireless/mwifiex/uap_txrx.c
@@ -146,7 +146,7 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
 	}
 
 	/* Forward unicat/Inter-BSS packets to kernel. */
-	return mwifiex_process_rx_packet(adapter, skb);
+	return mwifiex_process_rx_packet(priv, skb);
 }
 
 /*
@@ -159,24 +159,17 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
  *
  * The completion callback is called after processing is complete.
  */
-int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
+int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
 				  struct sk_buff *skb)
 {
+	struct mwifiex_adapter *adapter = priv->adapter;
 	int ret;
 	struct uap_rxpd *uap_rx_pd;
-	struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
 	struct rx_packet_hdr *rx_pkt_hdr;
 	u16 rx_pkt_type;
 	u8 ta[ETH_ALEN], pkt_type;
 	struct mwifiex_sta_node *node;
 
-	struct mwifiex_private *priv =
-			mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
-					       rx_info->bss_type);
-
-	if (!priv)
-		return -1;
-
 	uap_rx_pd = (struct uap_rxpd *)(skb->data);
 	rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type);
 	rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
@@ -210,7 +203,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
 
 		while (!skb_queue_empty(&list)) {
 			rx_skb = __skb_dequeue(&list);
-			ret = mwifiex_recv_packet(adapter, rx_skb);
+			ret = mwifiex_recv_packet(priv, rx_skb);
 			if (ret)
 				dev_err(adapter->dev,
 					"AP:Rx A-MSDU failed");
@@ -218,7 +211,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
 
 		return 0;
 	} else if (rx_pkt_type == PKT_TYPE_MGMT) {
-		ret = mwifiex_process_mgmt_packet(adapter, skb);
+		ret = mwifiex_process_mgmt_packet(priv, skb);
 		if (ret)
 			dev_err(adapter->dev, "Rx of mgmt packet failed");
 		dev_kfree_skb_any(skb);
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c
index 22a5916..bbe1f35 100644
--- a/drivers/net/wireless/mwifiex/usb.c
+++ b/drivers/net/wireless/mwifiex/usb.c
@@ -238,7 +238,7 @@ static void mwifiex_usb_tx_complete(struct urb *urb)
 	} else {
 		dev_dbg(adapter->dev, "%s: DATA\n", __func__);
 		atomic_dec(&card->tx_data_urb_pending);
-		mwifiex_write_data_complete(adapter, context->skb,
+		mwifiex_write_data_complete(adapter, context->skb, 0,
 					    urb->status ? -1 : 0);
 	}
 
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c
index ae88f80..0982375 100644
--- a/drivers/net/wireless/mwifiex/util.c
+++ b/drivers/net/wireless/mwifiex/util.c
@@ -146,20 +146,16 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv,
  * to the kernel.
  */
 int
-mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter,
+mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
 			    struct sk_buff *skb)
 {
 	struct rxpd *rx_pd;
-	struct mwifiex_private *priv;
 	u16 pkt_len;
 
 	if (!skb)
 		return -1;
 
 	rx_pd = (struct rxpd *)skb->data;
-	priv = mwifiex_get_priv_by_id(adapter, rx_pd->bss_num, rx_pd->bss_type);
-	if (!priv)
-		return -1;
 
 	skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset));
 	skb_pull(skb, sizeof(pkt_len));
@@ -190,20 +186,11 @@ mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter,
  * the function creates a blank SKB, fills it with the data from the
  * received buffer and then sends this new SKB to the kernel.
  */
-int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb)
+int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
 {
-	struct mwifiex_rxinfo *rx_info;
-	struct mwifiex_private *priv;
-
 	if (!skb)
 		return -1;
 
-	rx_info = MWIFIEX_SKB_RXCB(skb);
-	priv = mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
-				      rx_info->bss_type);
-	if (!priv)
-		return -1;
-
 	skb->dev = priv->netdev;
 	skb->protocol = eth_type_trans(skb, priv->netdev);
 	skb->ip_summed = CHECKSUM_NONE;
@@ -225,7 +212,7 @@ int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb)
 	 * fragments. Currently we fail the Filesndl-ht.scr script
 	 * for UDP, hence this fix
 	 */
-	if ((adapter->iface_type == MWIFIEX_USB) &&
+	if ((priv->adapter->iface_type == MWIFIEX_USB) &&
 	    (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE))
 		skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE);
 
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 600d819..818f871 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -483,7 +483,7 @@ mwifiex_wmm_del_pkts_in_ralist_node(struct mwifiex_private *priv,
 	struct sk_buff *skb, *tmp;
 
 	skb_queue_walk_safe(&ra_list->skb_head, skb, tmp)
-		mwifiex_write_data_complete(adapter, skb, -1);
+		mwifiex_write_data_complete(adapter, skb, 0, -1);
 }
 
 /*
@@ -650,7 +650,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
 
 	if (!priv->media_connected && !mwifiex_is_skb_mgmt_frame(skb)) {
 		dev_dbg(adapter->dev, "data: drop packet in disconnect\n");
-		mwifiex_write_data_complete(adapter, skb, -1);
+		mwifiex_write_data_complete(adapter, skb, 0, -1);
 		return;
 	}
 
@@ -680,7 +680,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
 
 	if (!ra_list) {
 		spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
-		mwifiex_write_data_complete(adapter, skb, -1);
+		mwifiex_write_data_complete(adapter, skb, 0, -1);
 		return;
 	}
 
@@ -1090,7 +1090,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
 		if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
 			spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
 					       ra_list_flags);
-			mwifiex_write_data_complete(adapter, skb, -1);
+			mwifiex_write_data_complete(adapter, skb, 0, -1);
 			return;
 		}
 
@@ -1195,7 +1195,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
 		if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
 			spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
 					       ra_list_flags);
-			mwifiex_write_data_complete(adapter, skb, -1);
+			mwifiex_write_data_complete(adapter, skb, 0, -1);
 			return;
 		}
 
@@ -1209,7 +1209,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
 		adapter->data_sent = false;
 		dev_err(adapter->dev, "host_to_card failed: %#x\n", ret);
 		adapter->dbg.num_tx_host_to_card_failure++;
-		mwifiex_write_data_complete(adapter, skb, ret);
+		mwifiex_write_data_complete(adapter, skb, 0, ret);
 		break;
 	case -EINPROGRESS:
 		adapter->data_sent = false;
diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h
index ec83995..b92f39d 100644
--- a/drivers/net/wireless/mwifiex/wmm.h
+++ b/drivers/net/wireless/mwifiex/wmm.h
@@ -31,6 +31,8 @@ enum ieee_types_wmm_ecw_bitmasks {
 	MWIFIEX_ECW_MAX = (BIT(4) | BIT(5) | BIT(6) | BIT(7)),
 };
 
+static const u16 mwifiex_1d_to_wmm_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
+
 /*
  * This function retrieves the TID of the given RA list.
  */
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 5099e53..0cdae66 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1851,6 +1851,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw,
 	bool start_ba_session = false;
 	bool mgmtframe = false;
 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
+	bool eapol_frame = false;
 
 	wh = (struct ieee80211_hdr *)skb->data;
 	if (ieee80211_is_data_qos(wh->frame_control))
@@ -1858,6 +1859,9 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw,
 	else
 		qos = 0;
 
+	if (skb->protocol == cpu_to_be16(ETH_P_PAE))
+		eapol_frame = true;
+
 	if (ieee80211_is_mgmt(wh->frame_control))
 		mgmtframe = true;
 
@@ -1916,9 +1920,8 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw,
 
 	txpriority = index;
 
-	if (priv->ap_fw && sta && sta->ht_cap.ht_supported
-			&& skb->protocol != cpu_to_be16(ETH_P_PAE)
-			&& ieee80211_is_data_qos(wh->frame_control)) {
+	if (priv->ap_fw && sta && sta->ht_cap.ht_supported && !eapol_frame &&
+	    ieee80211_is_data_qos(wh->frame_control)) {
 		tid = qos & 0xf;
 		mwl8k_tx_count_packet(sta, tid);
 		spin_lock(&priv->stream_lock);
@@ -2005,6 +2008,8 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw,
 				spin_unlock(&priv->stream_lock);
 			}
 			spin_unlock_bh(&priv->tx_lock);
+			pci_unmap_single(priv->pdev, dma, skb->len,
+					 PCI_DMA_TODEVICE);
 			dev_kfree_skb(skb);
 			return;
 		}
@@ -2025,9 +2030,11 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw,
 	else
 		tx->peer_id = 0;
 
-	if (priv->ap_fw)
+	if (priv->ap_fw && ieee80211_is_data(wh->frame_control) && !eapol_frame)
 		tx->timestamp = cpu_to_le32(ioread32(priv->regs +
 						MWL8K_HW_TIMER_REGISTER));
+	else
+		tx->timestamp = 0;
 
 	wmb();
 	tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus);
@@ -3679,7 +3686,8 @@ struct mwl8k_cmd_bastream {
 } __packed;
 
 static int
-mwl8k_check_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream)
+mwl8k_check_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream,
+	       struct ieee80211_vif *vif)
 {
 	struct mwl8k_cmd_bastream *cmd;
 	int rc;
@@ -3702,7 +3710,7 @@ mwl8k_check_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream)
 		cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE) |
 		cpu_to_le32(BASTREAM_FLAG_DIRECTION_UPSTREAM);
 
-	rc = mwl8k_post_cmd(hw, &cmd->header);
+	rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
 
 	kfree(cmd);
 
@@ -3711,7 +3719,7 @@ mwl8k_check_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream)
 
 static int
 mwl8k_create_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream,
-		u8 buf_size)
+		u8 buf_size, struct ieee80211_vif *vif)
 {
 	struct mwl8k_cmd_bastream *cmd;
 	int rc;
@@ -3745,7 +3753,7 @@ mwl8k_create_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream,
 		cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE |
 					BASTREAM_FLAG_DIRECTION_UPSTREAM);
 
-	rc = mwl8k_post_cmd(hw, &cmd->header);
+	rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
 
 	wiphy_debug(hw->wiphy, "Created a BA stream for %pM : tid %d\n",
 		stream->sta->addr, stream->tid);
@@ -5085,6 +5093,7 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	struct mwl8k_priv *priv = hw->priv;
 	struct mwl8k_ampdu_stream *stream;
 	u8 *addr = sta->addr;
+	struct mwl8k_sta *sta_info = MWL8K_STA(sta);
 
 	if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION))
 		return -ENOTSUPP;
@@ -5127,7 +5136,16 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		/* Release the lock before we do the time consuming stuff */
 		spin_unlock(&priv->stream_lock);
 		for (i = 0; i < MAX_AMPDU_ATTEMPTS; i++) {
-			rc = mwl8k_check_ba(hw, stream);
+
+			/* Check if link is still valid */
+			if (!sta_info->is_ampdu_allowed) {
+				spin_lock(&priv->stream_lock);
+				mwl8k_remove_stream(hw, stream);
+				spin_unlock(&priv->stream_lock);
+				return -EBUSY;
+			}
+
+			rc = mwl8k_check_ba(hw, stream, vif);
 
 			/* If HW restart is in progress mwl8k_post_cmd will
 			 * return -EBUSY. Avoid retrying mwl8k_check_ba in
@@ -5167,7 +5185,7 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		BUG_ON(stream == NULL);
 		BUG_ON(stream->state != AMPDU_STREAM_IN_PROGRESS);
 		spin_unlock(&priv->stream_lock);
-		rc = mwl8k_create_ba(hw, stream, buf_size);
+		rc = mwl8k_create_ba(hw, stream, buf_size, vif);
 		spin_lock(&priv->stream_lock);
 		if (!rc)
 			stream->state = AMPDU_STREAM_ACTIVE;
@@ -5617,6 +5635,18 @@ fail:
 	return rc;
 }
 
+static const struct ieee80211_iface_limit ap_if_limits[] = {
+	{ .max = 8,	.types = BIT(NL80211_IFTYPE_AP) },
+};
+
+static const struct ieee80211_iface_combination ap_if_comb = {
+	.limits = ap_if_limits,
+	.n_limits = ARRAY_SIZE(ap_if_limits),
+	.max_interfaces = 8,
+	.num_different_channels = 1,
+};
+
+
 static int mwl8k_firmware_load_success(struct mwl8k_priv *priv)
 {
 	struct ieee80211_hw *hw = priv->hw;
@@ -5696,8 +5726,13 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv)
 		goto err_free_cookie;
 
 	hw->wiphy->interface_modes = 0;
-	if (priv->ap_macids_supported || priv->device_info->fw_image_ap)
+
+	if (priv->ap_macids_supported || priv->device_info->fw_image_ap) {
 		hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP);
+		hw->wiphy->iface_combinations = &ap_if_comb;
+		hw->wiphy->n_iface_combinations = 1;
+	}
+
 	if (priv->sta_macids_supported || priv->device_info->fw_image_sta)
 		hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION);
 
diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c
index 7b751fb..d01edd2 100644
--- a/drivers/net/wireless/orinoco/cfg.c
+++ b/drivers/net/wireless/orinoco/cfg.c
@@ -161,24 +161,23 @@ static int orinoco_scan(struct wiphy *wiphy,
 }
 
 static int orinoco_set_monitor_channel(struct wiphy *wiphy,
-				       struct ieee80211_channel *chan,
-				       enum nl80211_channel_type channel_type)
+				       struct cfg80211_chan_def *chandef)
 {
 	struct orinoco_private *priv = wiphy_priv(wiphy);
 	int err = 0;
 	unsigned long flags;
 	int channel;
 
-	if (!chan)
+	if (!chandef->chan)
 		return -EINVAL;
 
-	if (channel_type != NL80211_CHAN_NO_HT)
+	if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT)
 		return -EINVAL;
 
-	if (chan->band != IEEE80211_BAND_2GHZ)
+	if (chandef->chan->band != IEEE80211_BAND_2GHZ)
 		return -EINVAL;
 
-	channel = ieee80211_freq_to_dsss_chan(chan->center_freq);
+	channel = ieee80211_freq_to_dsss_chan(chandef->chan->center_freq);
 
 	if ((channel < 1) || (channel > NUM_CHANNELS) ||
 	     !(priv->channel_mask & (1 << (channel - 1))))
diff --git a/drivers/net/wireless/orinoco/main.h b/drivers/net/wireless/orinoco/main.h
index 4dadf98..5a8fec2 100644
--- a/drivers/net/wireless/orinoco/main.h
+++ b/drivers/net/wireless/orinoco/main.h
@@ -39,7 +39,7 @@ static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len)
 {
 	u8 *p = data;
 	while ((p + 2 + WPA_SELECTOR_LEN) < (data + len)) {
-		if ((p[0] == WLAN_EID_GENERIC) &&
+		if ((p[0] == WLAN_EID_VENDOR_SPECIFIC) &&
 		    (memcmp(&p[2], WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0))
 			return p;
 		p += p[1] + 2;
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c
index 7f53cea2..01624dc 100644
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
@@ -865,7 +865,7 @@ static int ezusb_firmware_download(struct ezusb_priv *upriv,
 static int ezusb_access_ltv(struct ezusb_priv *upriv,
 			    struct request_context *ctx,
 			    u16 length, const void *data, u16 frame_type,
-			    void *ans_buff, int ans_size, u16 *ans_length)
+			    void *ans_buff, unsigned ans_size, u16 *ans_length)
 {
 	int req_size;
 	int retval = 0;
@@ -933,7 +933,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
 	}
 	if (ctx->in_rid) {
 		struct ezusb_packet *ans = ctx->buf;
-		int exp_len;
+		unsigned exp_len;
 
 		if (ans->hermes_len != 0)
 			exp_len = le16_to_cpu(ans->hermes_len) * 2 + 12;
@@ -949,8 +949,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
 		}
 
 		if (ans_buff)
-			memcpy(ans_buff, ans->data,
-			       min_t(int, exp_len, ans_size));
+			memcpy(ans_buff, ans->data, min(exp_len, ans_size));
 		if (ans_length)
 			*ans_length = le16_to_cpu(ans->hermes_len);
 	}
@@ -995,7 +994,7 @@ static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid,
 	struct ezusb_priv *upriv = hw->priv;
 	struct request_context *ctx;
 
-	if ((bufsize < 0) || (bufsize % 2))
+	if (bufsize % 2)
 		return -EINVAL;
 
 	ctx = ezusb_alloc_ctx(upriv, rid, rid);
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index 5861e13..12f0a34 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -369,7 +369,11 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb)
 	rx_status->mactime = ((u64)priv->tsf_high32) << 32 | tsf32;
 	priv->tsf_low32 = tsf32;
 
-	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+	/* LMAC API Page 10/29 - s_lm_data_in - clock
+	 * "usec accurate timestamp of hardware clock
+	 * at end of frame (before OFDM SIFS EOF padding"
+	 */
+	rx_status->flag |= RX_FLAG_MACTIME_END;
 
 	if (hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
 		header_len += hdr->align[0];
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index bd1f0cb..abe1d03 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -490,9 +490,12 @@ static int rndis_scan(struct wiphy *wiphy,
 static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed);
 
 static int rndis_set_tx_power(struct wiphy *wiphy,
+			      struct wireless_dev *wdev,
 			      enum nl80211_tx_power_setting type,
 			      int mbm);
-static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm);
+static int rndis_get_tx_power(struct wiphy *wiphy,
+			      struct wireless_dev *wdev,
+			      int *dbm);
 
 static int rndis_connect(struct wiphy *wiphy, struct net_device *dev,
 				struct cfg80211_connect_params *sme);
@@ -1903,6 +1906,7 @@ static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 }
 
 static int rndis_set_tx_power(struct wiphy *wiphy,
+			      struct wireless_dev *wdev,
 			      enum nl80211_tx_power_setting type,
 			      int mbm)
 {
@@ -1930,7 +1934,9 @@ static int rndis_set_tx_power(struct wiphy *wiphy,
 	return -ENOTSUPP;
 }
 
-static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm)
+static int rndis_get_tx_power(struct wiphy *wiphy,
+			      struct wireless_dev *wdev,
+			      int *dbm)
 {
 	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
 	struct usbnet *usbdev = priv->usbdev;
@@ -2287,7 +2293,7 @@ static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 {
 	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
 	struct usbnet *usbdev = priv->usbdev;
-	struct ieee80211_channel *channel = params->channel;
+	struct ieee80211_channel *channel = params->chandef.chan;
 	struct ndis_80211_ssid ssid;
 	enum nl80211_auth_type auth_type;
 	int ret, alg, length, chan = -1;
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 59474ae..c0441a7 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2520,20 +2520,37 @@ static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev,
 	return comp_value;
 }
 
+static int rt2800_get_txpower_reg_delta(struct rt2x00_dev *rt2x00dev,
+					int power_level, int max_power)
+{
+	int delta;
+
+	if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags))
+		return 0;
+
+	/*
+	 * XXX: We don't know the maximum transmit power of our hardware since
+	 * the EEPROM doesn't expose it. We only know that we are calibrated
+	 * to 100% tx power.
+	 *
+	 * Hence, we assume the regulatory limit that cfg80211 calulated for
+	 * the current channel is our maximum and if we are requested to lower
+	 * the value we just reduce our tx power accordingly.
+	 */
+	delta = power_level - max_power;
+	return min(delta, 0);
+}
+
 static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
 				   enum ieee80211_band band, int power_level,
 				   u8 txpower, int delta)
 {
-	u32 reg;
 	u16 eeprom;
 	u8 criterion;
 	u8 eirp_txpower;
 	u8 eirp_txpower_criterion;
 	u8 reg_limit;
 
-	if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b))
-		return txpower;
-
 	if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) {
 		/*
 		 * Check if eirp txpower exceed txpower_limit.
@@ -2542,11 +2559,13 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
 		 * .11b data rate need add additional 4dbm
 		 * when calculating eirp txpower.
 		 */
-		rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, &reg);
-		criterion = rt2x00_get_field32(reg, TX_PWR_CFG_0_6MBS);
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + 1,
+				   &eeprom);
+		criterion = rt2x00_get_field16(eeprom,
+					       EEPROM_TXPOWER_BYRATE_RATE0);
 
-		rt2x00_eeprom_read(rt2x00dev,
-				   EEPROM_EIRP_MAX_TX_POWER, &eeprom);
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER,
+				   &eeprom);
 
 		if (band == IEEE80211_BAND_2GHZ)
 			eirp_txpower_criterion = rt2x00_get_field16(eeprom,
@@ -2563,36 +2582,71 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
 	} else
 		reg_limit = 0;
 
-	return txpower + delta - reg_limit;
+	txpower = max(0, txpower + delta - reg_limit);
+	return min_t(u8, txpower, 0xc);
 }
 
+/*
+ * We configure transmit power using MAC TX_PWR_CFG_{0,...,N} registers and
+ * BBP R1 register. TX_PWR_CFG_X allow to configure per rate TX power values,
+ * 4 bits for each rate (tune from 0 to 15 dBm). BBP_R1 controls transmit power
+ * for all rates, but allow to set only 4 discrete values: -12, -6, 0 and 6 dBm.
+ * Reference per rate transmit power values are located in the EEPROM at
+ * EEPROM_TXPOWER_BYRATE offset. We adjust them and BBP R1 settings according to
+ * current conditions (i.e. band, bandwidth, temperature, user settings).
+ */
 static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
-				  enum ieee80211_band band,
+				  struct ieee80211_channel *chan,
 				  int power_level)
 {
-	u8 txpower;
+	u8 txpower, r1;
 	u16 eeprom;
-	int i, is_rate_b;
-	u32 reg;
-	u8 r1;
-	u32 offset;
-	int delta;
+	u32 reg, offset;
+	int i, is_rate_b, delta, power_ctrl;
+	enum ieee80211_band band = chan->band;
 
 	/*
-	 * Calculate HT40 compensation delta
+	 * Calculate HT40 compensation. For 40MHz we need to add or subtract
+	 * value read from EEPROM (different for 2GHz and for 5GHz).
 	 */
 	delta = rt2800_get_txpower_bw_comp(rt2x00dev, band);
 
 	/*
-	 * calculate temperature compensation delta
+	 * Calculate temperature compensation. Depends on measurement of current
+	 * TSSI (Transmitter Signal Strength Indication) we know TX power (due
+	 * to temperature or maybe other factors) is smaller or bigger than
+	 * expected. We adjust it, based on TSSI reference and boundaries values
+	 * provided in EEPROM.
 	 */
 	delta += rt2800_get_gain_calibration_delta(rt2x00dev);
 
 	/*
-	 * set to normal bbp tx power control mode: +/- 0dBm
+	 * Decrease power according to user settings, on devices with unknown
+	 * maximum tx power. For other devices we take user power_level into
+	 * consideration on rt2800_compensate_txpower().
+	 */
+	delta += rt2800_get_txpower_reg_delta(rt2x00dev, power_level,
+					      chan->max_power);
+
+	/*
+	 * BBP_R1 controls TX power for all rates, it allow to set the following
+	 * gains -12, -6, 0, +6 dBm by setting values 2, 1, 0, 3 respectively.
+	 *
+	 * TODO: we do not use +6 dBm option to do not increase power beyond
+	 * regulatory limit, however this could be utilized for devices with
+	 * CAPABILITY_POWER_LIMIT.
 	 */
 	rt2800_bbp_read(rt2x00dev, 1, &r1);
-	rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, 0);
+	if (delta <= -12) {
+		power_ctrl = 2;
+		delta += 12;
+	} else if (delta <= -6) {
+		power_ctrl = 1;
+		delta += 6;
+	} else {
+		power_ctrl = 0;
+	}
+	rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl);
 	rt2800_bbp_write(rt2x00dev, 1, r1);
 	offset = TX_PWR_CFG_0;
 
@@ -2710,7 +2764,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
 
 void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev)
 {
-	rt2800_config_txpower(rt2x00dev, rt2x00dev->curr_band,
+	rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.channel,
 			      rt2x00dev->tx_power);
 }
 EXPORT_SYMBOL_GPL(rt2800_gain_calibration);
@@ -2845,11 +2899,11 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev,
 	if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {
 		rt2800_config_channel(rt2x00dev, libconf->conf,
 				      &libconf->rf, &libconf->channel);
-		rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band,
+		rt2800_config_txpower(rt2x00dev, libconf->conf->channel,
 				      libconf->conf->power_level);
 	}
 	if (flags & IEEE80211_CONF_CHANGE_POWER)
-		rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band,
+		rt2800_config_txpower(rt2x00dev, libconf->conf->channel,
 				      libconf->conf->power_level);
 	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
 		rt2800_config_retry_limit(rt2x00dev, libconf);
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 3b8fb5a..0230812 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -1096,6 +1096,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	{ USB_DEVICE(0x177f, 0x0153) },
 	{ USB_DEVICE(0x177f, 0x0302) },
 	{ USB_DEVICE(0x177f, 0x0313) },
+	{ USB_DEVICE(0x177f, 0x0323) },
 	/* U-Media */
 	{ USB_DEVICE(0x157e, 0x300e) },
 	{ USB_DEVICE(0x157e, 0x3013) },
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 69097d1..67d1679 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -157,6 +157,7 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work)
 	 * requested configurations.
 	 */
 	ieee80211_iterate_active_interfaces(rt2x00dev->hw,
+					    IEEE80211_IFACE_ITER_RESUME_ALL,
 					    rt2x00lib_intf_scheduled_iter,
 					    rt2x00dev);
 }
@@ -225,9 +226,9 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
 		return;
 
 	/* send buffered bc/mc frames out for every bssid */
-	ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
-						   rt2x00lib_bc_buffer_iter,
-						   rt2x00dev);
+	ieee80211_iterate_active_interfaces_atomic(
+		rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+		rt2x00lib_bc_buffer_iter, rt2x00dev);
 	/*
 	 * Devices with pre tbtt interrupt don't need to update the beacon
 	 * here as they will fetch the next beacon directly prior to
@@ -237,9 +238,9 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
 		return;
 
 	/* fetch next beacon */
-	ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
-						   rt2x00lib_beaconupdate_iter,
-						   rt2x00dev);
+	ieee80211_iterate_active_interfaces_atomic(
+		rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+		rt2x00lib_beaconupdate_iter, rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
 
@@ -249,9 +250,9 @@ void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev)
 		return;
 
 	/* fetch next beacon */
-	ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
-						   rt2x00lib_beaconupdate_iter,
-						   rt2x00dev);
+	ieee80211_iterate_active_interfaces_atomic(
+		rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+		rt2x00lib_beaconupdate_iter, rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 98a9e48..ed7a1bb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -424,9 +424,9 @@ int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
 	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		return 0;
 
-	ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
-						   rt2x00mac_set_tim_iter,
-						   rt2x00dev);
+	ieee80211_iterate_active_interfaces_atomic(
+		rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+		rt2x00mac_set_tim_iter, rt2x00dev);
 
 	/* queue work to upodate the beacon template */
 	ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work);
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index 021d83e..b4218a5 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -150,7 +150,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
 			rx_status.freq = dev->conf.channel->center_freq;
 			rx_status.band = dev->conf.channel->band;
 			rx_status.mactime = le64_to_cpu(entry->tsft);
-			rx_status.flag |= RX_FLAG_MACTIME_MPDU;
+			rx_status.flag |= RX_FLAG_MACTIME_START;
 			if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
 				rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
 
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c
index 7811b63..52e6beb 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c
@@ -381,7 +381,7 @@ static void rtl8187_rx_cb(struct urb *urb)
 	rx_status.rate_idx = rate;
 	rx_status.freq = dev->conf.channel->center_freq;
 	rx_status.band = dev->conf.channel->band;
-	rx_status.flag |= RX_FLAG_MACTIME_MPDU;
+	rx_status.flag |= RX_FLAG_MACTIME_START;
 	if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
 		rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
 	memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig
index 6b28e92..21b1bbb 100644
--- a/drivers/net/wireless/rtlwifi/Kconfig
+++ b/drivers/net/wireless/rtlwifi/Kconfig
@@ -32,6 +32,17 @@ config RTL8192DE
 
 	If you choose to build it as a module, it will be called rtl8192de
 
+config RTL8723AE
+	tristate "Realtek RTL8723AE PCIe Wireless Network Adapter"
+	depends on MAC80211 && PCI && EXPERIMENTAL
+	select FW_LOADER
+	select RTLWIFI
+	---help---
+	This is the driver for Realtek RTL8723AE 802.11n PCIe
+	wireless network adapters.
+
+	If you choose to build it as a module, it will be called rtl8723ae
+
 config RTL8192CU
 	tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter"
 	depends on MAC80211 && USB
diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/rtlwifi/Makefile
index 97935c5..3b1cbac 100644
--- a/drivers/net/wireless/rtlwifi/Makefile
+++ b/drivers/net/wireless/rtlwifi/Makefile
@@ -7,7 +7,8 @@ rtlwifi-objs	:=		\
 		efuse.o		\
 		ps.o		\
 		rc.o		\
-		regd.o
+		regd.o		\
+		stats.o
 
 rtl8192c_common-objs +=		\
 
@@ -24,5 +25,6 @@ obj-$(CONFIG_RTL8192CE)		+= rtl8192ce/
 obj-$(CONFIG_RTL8192CU)		+= rtl8192cu/
 obj-$(CONFIG_RTL8192SE)		+= rtl8192se/
 obj-$(CONFIG_RTL8192DE)		+= rtl8192de/
+obj-$(CONFIG_RTL8723AE)		+= rtl8723ae/
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index 59381fe..4494d13 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -826,6 +826,30 @@ int rtlwifi_rate_mapping(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(rtlwifi_rate_mapping);
 
+bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	__le16 fc = rtl_get_fc(skb);
+
+	if (rtlpriv->dm.supp_phymode_switch &&
+	    mac->link_state < MAC80211_LINKED &&
+	    (ieee80211_is_auth(fc) || ieee80211_is_probe_req(fc))) {
+		if (rtlpriv->cfg->ops->check_switch_to_dmdp)
+			rtlpriv->cfg->ops->check_switch_to_dmdp(hw);
+	}
+	if (ieee80211_is_auth(fc)) {
+		RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
+		rtl_ips_nic_on(hw);
+
+		mac->link_state = MAC80211_LINKING;
+		/* Dual mac */
+		rtlpriv->phy.need_iqk = true;
+	}
+
+	return true;
+}
+
 void rtl_get_tcb_desc(struct ieee80211_hw *hw,
 		      struct ieee80211_tx_info *info,
 		      struct ieee80211_sta *sta,
diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h
index f35af0f..5a8c80e 100644
--- a/drivers/net/wireless/rtlwifi/base.h
+++ b/drivers/net/wireless/rtlwifi/base.h
@@ -142,4 +142,6 @@ u8 rtl_tid_to_ac(u8 tid);
 extern struct attribute_group rtl_attribute_group;
 int rtlwifi_rate_mapping(struct ieee80211_hw *hw,
 			 bool isht, u8 desc_rate, bool first_ampdu);
+bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb);
+
 #endif
diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c
index 5b4b4d4..0e510f7 100644
--- a/drivers/net/wireless/rtlwifi/cam.c
+++ b/drivers/net/wireless/rtlwifi/cam.c
@@ -52,11 +52,8 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no,
 	u32 target_content = 0;
 	u8 entry_i;
 
-	RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
-		 "key_cont_128:\n %x:%x:%x:%x:%x:%x\n",
-		 key_cont_128[0], key_cont_128[1],
-		 key_cont_128[2], key_cont_128[3],
-		 key_cont_128[4], key_cont_128[5]);
+	RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "key_cont_128: %6phC\n",
+		 key_cont_128);
 
 	for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
 		target_command = entry_i + CAM_CONTENT_COUNT * entry_no;
@@ -340,7 +337,7 @@ void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr)
 		if (((bitmap & BIT(0)) == BIT(0)) &&
 		    (memcmp(addr, sta_addr, ETH_ALEN) == 0)) {
 			/* Remove from HW Security CAM */
-			memset(rtlpriv->sec.hwsec_cam_sta_addr[i], 0, ETH_ALEN);
+			eth_zero_addr(rtlpriv->sec.hwsec_cam_sta_addr[i]);
 			rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i);
 			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
 				 "del CAM entry %d\n", i);
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index a7c0e52..be33aa1 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -962,7 +962,6 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 	int err = 0;
 	u8 mac_addr[ETH_ALEN];
 	u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-	u8 zero_addr[ETH_ALEN] = { 0 };
 
 	if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
@@ -1057,7 +1056,7 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 			memcpy(rtlpriv->sec.key_buf[key_idx],
 			       key->key, key->keylen);
 			rtlpriv->sec.key_len[key_idx] = key->keylen;
-			memcpy(mac_addr, zero_addr, ETH_ALEN);
+			eth_zero_addr(mac_addr);
 		} else if (group_key) {	/* group key */
 			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
 				 "set group key\n");
@@ -1108,7 +1107,7 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		}
 		memset(rtlpriv->sec.key_buf[key_idx], 0, key->keylen);
 		rtlpriv->sec.key_len[key_idx] = 0;
-		memcpy(mac_addr, zero_addr, ETH_ALEN);
+		eth_zero_addr(mac_addr);
 		/*
 		 *mac80211 will delete entrys one by one,
 		 *so don't use rtl_cam_reset_all_entry
diff --git a/drivers/net/wireless/rtlwifi/debug.h b/drivers/net/wireless/rtlwifi/debug.h
index 07493d2..fd3269f 100644
--- a/drivers/net/wireless/rtlwifi/debug.h
+++ b/drivers/net/wireless/rtlwifi/debug.h
@@ -106,6 +106,8 @@
 #define COMP_REGD			BIT(27)
 #define COMP_CHAN			BIT(28)
 #define COMP_USB			BIT(29)
+#define COMP_EASY_CONCURRENT	COMP_USB /* reuse of this bit is OK */
+#define COMP_BT_COEXIST			BIT(30)
 
 /*--------------------------------------------------------------
 		Define the rt_print components
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index abc306b..f38e30a 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -1309,6 +1309,7 @@ static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw,
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_sta_info *sta_entry = NULL;
 	u8 tid = rtl_get_tid(skb);
+	__le16 fc = rtl_get_fc(skb);
 
 	if (!sta)
 		return false;
@@ -1316,6 +1317,12 @@ static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw,
 
 	if (!rtlpriv->rtlhal.earlymode_enable)
 		return false;
+	if (ieee80211_is_nullfunc(fc))
+		return false;
+	if (ieee80211_is_qos_nullfunc(fc))
+		return false;
+	if (ieee80211_is_pspoll(fc))
+		return false;
 	if (sta_entry->tids[tid].agg.agg_state != RTL_AGG_OPERATIONAL)
 		return false;
 	if (_rtl_mac_to_hwqueue(hw, skb) > VO_QUEUE)
@@ -1357,10 +1364,8 @@ static int rtl_pci_tx(struct ieee80211_hw *hw,
 	u8 own;
 	u8 temp_one = 1;
 
-	if (ieee80211_is_auth(fc)) {
-		RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
-		rtl_ips_nic_on(hw);
-	}
+	if (ieee80211_is_mgmt(fc))
+		rtl_tx_mgmt_proc(hw, skb);
 
 	if (rtlpriv->psc.sw_ps_enabled) {
 		if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) &&
@@ -1628,7 +1633,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
 				 "8192 PCI-E is found - vid/did=%x/%x\n",
 				 venderid, deviceid);
 			rtlhal->hw_type = HARDWARE_TYPE_RTL8192E;
-			break;
+			return false;
 		case RTL_PCI_REVISION_ID_8192SE:
 			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 				 "8192SE is found - vid/did=%x/%x\n",
@@ -1643,6 +1648,11 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
 			break;
 
 		}
+	} else if (deviceid == RTL_PCI_8723AE_DID) {
+		rtlhal->hw_type = HARDWARE_TYPE_RTL8723AE;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 "8723AE PCI-E is found - "
+			 "vid/did=%x/%x\n", venderid, deviceid);
 	} else if (deviceid == RTL_PCI_8192CET_DID ||
 		   deviceid == RTL_PCI_8192CE_DID ||
 		   deviceid == RTL_PCI_8191CE_DID ||
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h
index 241448f..f71b12a 100644
--- a/drivers/net/wireless/rtlwifi/pci.h
+++ b/drivers/net/wireless/rtlwifi/pci.h
@@ -79,6 +79,7 @@
 #define RTL_PCI_8173_DID	0x8173	/*8191 SE Crab */
 #define RTL_PCI_8172_DID	0x8172	/*8191 SE RE */
 #define RTL_PCI_8171_DID	0x8171	/*8191 SE Unicron */
+#define RTL_PCI_8723AE_DID	0x8723	/*8723AE */
 #define RTL_PCI_0045_DID	0x0045	/*8190 PCI for Ceraga */
 #define RTL_PCI_0046_DID	0x0046	/*8190 Cardbus for Ceraga */
 #define RTL_PCI_0044_DID	0x0044	/*8192e PCIE for Ceraga */
@@ -152,6 +153,7 @@ struct rtl8192_rx_ring {
 
 struct rtl_pci {
 	struct pci_dev *pdev;
+	bool irq_enabled;
 
 	bool driver_is_goingto_unload;
 	bool up_first_time;
diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c
index d5cbf01..c1e065f 100644
--- a/drivers/net/wireless/rtlwifi/rc.c
+++ b/drivers/net/wireless/rtlwifi/rc.c
@@ -55,7 +55,8 @@ static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv,
 	 *      1M we will not use FW rate but user rate.
 	 */
 	if (rtlmac->opmode == NL80211_IFTYPE_AP ||
-		rtlmac->opmode == NL80211_IFTYPE_ADHOC) {
+	    rtlmac->opmode == NL80211_IFTYPE_ADHOC ||
+	    rtlmac->opmode == NL80211_IFTYPE_MESH_POINT) {
 		if (sta) {
 			sta_entry = (struct rtl_sta_info *) sta->drv_priv;
 			wireless_mode = sta_entry->wireless_mode;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
index 1ca4e25..1cdf5a2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
@@ -43,8 +43,8 @@
 #define GET_UNDECORATED_AVERAGE_RSSI(_priv)	\
 	((RTLPRIV(_priv))->mac80211.opmode == \
 			     NL80211_IFTYPE_ADHOC) ?	\
-	((RTLPRIV(_priv))->dm.entry_min_undecoratedsmoothed_pwdb) : \
-	((RTLPRIV(_priv))->dm.undecorated_smoothed_pwdb)
+	((RTLPRIV(_priv))->dm.entry_min_undec_sm_pwdb) : \
+	((RTLPRIV(_priv))->dm.undec_sm_pwdb)
 
 static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
 	0x7f8001fe,
@@ -167,18 +167,18 @@ static void rtl92c_dm_diginit(struct ieee80211_hw *hw)
 	dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
 	dm_digtable->cur_igvalue = 0x20;
 	dm_digtable->pre_igvalue = 0x0;
-	dm_digtable->cursta_connectstate = DIG_STA_DISCONNECT;
-	dm_digtable->presta_connectstate = DIG_STA_DISCONNECT;
-	dm_digtable->curmultista_connectstate = DIG_MULTISTA_DISCONNECT;
+	dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;
+	dm_digtable->presta_cstate = DIG_STA_DISCONNECT;
+	dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT;
 	dm_digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
 	dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
 	dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
 	dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
 	dm_digtable->rx_gain_range_max = DM_DIG_MAX;
 	dm_digtable->rx_gain_range_min = DM_DIG_MIN;
-	dm_digtable->backoff_val = DM_DIG_BACKOFF_DEFAULT;
-	dm_digtable->backoff_val_range_max = DM_DIG_BACKOFF_MAX;
-	dm_digtable->backoff_val_range_min = DM_DIG_BACKOFF_MIN;
+	dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
+	dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX;
+	dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN;
 	dm_digtable->pre_cck_pd_state = CCK_PD_STAGE_MAX;
 	dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX;
 }
@@ -189,22 +189,21 @@ static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
 	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 	long rssi_val_min = 0;
 
-	if ((dm_digtable->curmultista_connectstate == DIG_MULTISTA_CONNECT) &&
-	    (dm_digtable->cursta_connectstate == DIG_STA_CONNECT)) {
-		if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb != 0)
+	if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) &&
+	    (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) {
+		if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0)
 			rssi_val_min =
-			    (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb >
-			     rtlpriv->dm.undecorated_smoothed_pwdb) ?
-			    rtlpriv->dm.undecorated_smoothed_pwdb :
-			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+			    (rtlpriv->dm.entry_min_undec_sm_pwdb >
+			     rtlpriv->dm.undec_sm_pwdb) ?
+			    rtlpriv->dm.undec_sm_pwdb :
+			    rtlpriv->dm.entry_min_undec_sm_pwdb;
 		else
-			rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb;
-	} else if (dm_digtable->cursta_connectstate == DIG_STA_CONNECT ||
-		   dm_digtable->cursta_connectstate == DIG_STA_BEFORE_CONNECT) {
-		rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb;
-	} else if (dm_digtable->curmultista_connectstate ==
-		   DIG_MULTISTA_CONNECT) {
-		rssi_val_min = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+			rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
+	} else if (dm_digtable->cursta_cstate == DIG_STA_CONNECT ||
+		   dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT) {
+		rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
+	} else if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
+		rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;
 	}
 
 	return (u8) rssi_val_min;
@@ -286,37 +285,33 @@ static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)
 static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+	struct dig_t *digtable = &rtlpriv->dm_digtable;
 
-	if (rtlpriv->falsealm_cnt.cnt_all > dm_digtable->fa_highthresh) {
-		if ((dm_digtable->backoff_val - 2) <
-		    dm_digtable->backoff_val_range_min)
-			dm_digtable->backoff_val =
-			    dm_digtable->backoff_val_range_min;
+	if (rtlpriv->falsealm_cnt.cnt_all > digtable->fa_highthresh) {
+		if ((digtable->back_val - 2) < digtable->back_range_min)
+			digtable->back_val = digtable->back_range_min;
 		else
-			dm_digtable->backoff_val -= 2;
-	} else if (rtlpriv->falsealm_cnt.cnt_all < dm_digtable->fa_lowthresh) {
-		if ((dm_digtable->backoff_val + 2) >
-		    dm_digtable->backoff_val_range_max)
-			dm_digtable->backoff_val =
-			    dm_digtable->backoff_val_range_max;
+			digtable->back_val -= 2;
+	} else if (rtlpriv->falsealm_cnt.cnt_all < digtable->fa_lowthresh) {
+		if ((digtable->back_val + 2) > digtable->back_range_max)
+			digtable->back_val = digtable->back_range_max;
 		else
-			dm_digtable->backoff_val += 2;
+			digtable->back_val += 2;
 	}
 
-	if ((dm_digtable->rssi_val_min + 10 - dm_digtable->backoff_val) >
-	    dm_digtable->rx_gain_range_max)
-		dm_digtable->cur_igvalue = dm_digtable->rx_gain_range_max;
-	else if ((dm_digtable->rssi_val_min + 10 -
-		  dm_digtable->backoff_val) < dm_digtable->rx_gain_range_min)
-		dm_digtable->cur_igvalue = dm_digtable->rx_gain_range_min;
+	if ((digtable->rssi_val_min + 10 - digtable->back_val) >
+	    digtable->rx_gain_range_max)
+		digtable->cur_igvalue = digtable->rx_gain_range_max;
+	else if ((digtable->rssi_val_min + 10 -
+		  digtable->back_val) < digtable->rx_gain_range_min)
+		digtable->cur_igvalue = digtable->rx_gain_range_min;
 	else
-		dm_digtable->cur_igvalue = dm_digtable->rssi_val_min + 10 -
-		    dm_digtable->backoff_val;
+		digtable->cur_igvalue = digtable->rssi_val_min + 10 -
+		    digtable->back_val;
 
 	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 "rssi_val_min = %x backoff_val %x\n",
-		 dm_digtable->rssi_val_min, dm_digtable->backoff_val);
+		 "rssi_val_min = %x back_val %x\n",
+		 digtable->rssi_val_min, digtable->back_val);
 
 	rtl92c_dm_write_dig(hw);
 }
@@ -327,14 +322,14 @@ static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	long rssi_strength = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+	long rssi_strength = rtlpriv->dm.entry_min_undec_sm_pwdb;
 	bool multi_sta = false;
 
 	if (mac->opmode == NL80211_IFTYPE_ADHOC)
 		multi_sta = true;
 
 	if (!multi_sta ||
-	    dm_digtable->cursta_connectstate != DIG_STA_DISCONNECT) {
+	    dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {
 		initialized = false;
 		dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
 		return;
@@ -345,7 +340,7 @@ static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
 		rtl92c_dm_write_dig(hw);
 	}
 
-	if (dm_digtable->curmultista_connectstate == DIG_MULTISTA_CONNECT) {
+	if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
 		if ((rssi_strength < dm_digtable->rssi_lowthresh) &&
 		    (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) {
 
@@ -367,8 +362,8 @@ static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
 	}
 
 	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 "curmultista_connectstate = %x dig_ext_port_stage %x\n",
-		 dm_digtable->curmultista_connectstate,
+		 "curmultista_cstate = %x dig_ext_port_stage %x\n",
+		 dm_digtable->curmultista_cstate,
 		 dm_digtable->dig_ext_port_stage);
 }
 
@@ -378,15 +373,14 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
 	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 
 	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 "presta_connectstate = %x, cursta_connectstate = %x\n",
-		 dm_digtable->presta_connectstate,
-		 dm_digtable->cursta_connectstate);
+		 "presta_cstate = %x, cursta_cstate = %x\n",
+		 dm_digtable->presta_cstate, dm_digtable->cursta_cstate);
 
-	if (dm_digtable->presta_connectstate == dm_digtable->cursta_connectstate
-	    || dm_digtable->cursta_connectstate == DIG_STA_BEFORE_CONNECT
-	    || dm_digtable->cursta_connectstate == DIG_STA_CONNECT) {
+	if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate ||
+	    dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT ||
+	    dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
 
-		if (dm_digtable->cursta_connectstate != DIG_STA_DISCONNECT) {
+		if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {
 			dm_digtable->rssi_val_min =
 			    rtl92c_dm_initial_gain_min_pwdb(hw);
 			rtl92c_dm_ctrl_initgain_by_rssi(hw);
@@ -394,7 +388,7 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
 	} else {
 		dm_digtable->rssi_val_min = 0;
 		dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
-		dm_digtable->backoff_val = DM_DIG_BACKOFF_DEFAULT;
+		dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
 		dm_digtable->cur_igvalue = 0x20;
 		dm_digtable->pre_igvalue = 0;
 		rtl92c_dm_write_dig(hw);
@@ -407,7 +401,7 @@ static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 
-	if (dm_digtable->cursta_connectstate == DIG_STA_CONNECT) {
+	if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
 		dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw);
 
 		if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LowRssi) {
@@ -484,15 +478,15 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
 		return;
 
 	if (mac->link_state >= MAC80211_LINKED)
-		dm_digtable->cursta_connectstate = DIG_STA_CONNECT;
+		dm_digtable->cursta_cstate = DIG_STA_CONNECT;
 	else
-		dm_digtable->cursta_connectstate = DIG_STA_DISCONNECT;
+		dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;
 
 	rtl92c_dm_initial_gain_sta(hw);
 	rtl92c_dm_initial_gain_multi_sta(hw);
 	rtl92c_dm_cck_packet_detection_thresh(hw);
 
-	dm_digtable->presta_connectstate = dm_digtable->cursta_connectstate;
+	dm_digtable->presta_cstate = dm_digtable->cursta_cstate;
 
 }
 
@@ -526,9 +520,9 @@ void rtl92c_dm_write_dig(struct ieee80211_hw *hw)
 	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 
 	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
-		 "cur_igvalue = 0x%x, pre_igvalue = 0x%x, backoff_val = %d\n",
+		 "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n",
 		 dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
-		 dm_digtable->backoff_val);
+		 dm_digtable->back_val);
 
 	dm_digtable->cur_igvalue += 2;
 	if (dm_digtable->cur_igvalue > 0x3f)
@@ -555,20 +549,18 @@ static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw)
 	return;
 
 	if (tmpentry_max_pwdb != 0) {
-		rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb =
-		    tmpentry_max_pwdb;
+		rtlpriv->dm.entry_max_undec_sm_pwdb = tmpentry_max_pwdb;
 	} else {
-		rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb = 0;
+		rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
 	}
 
 	if (tmpentry_min_pwdb != 0xff) {
-		rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb =
-		    tmpentry_min_pwdb;
+		rtlpriv->dm.entry_min_undec_sm_pwdb = tmpentry_min_pwdb;
 	} else {
-		rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb = 0;
+		rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
 	}
 
-	h2c_parameter[2] = (u8) (rtlpriv->dm.undecorated_smoothed_pwdb & 0xFF);
+	h2c_parameter[2] = (u8) (rtlpriv->dm.undec_sm_pwdb & 0xFF);
 	h2c_parameter[0] = 0;
 
 	rtl92c_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, h2c_parameter);
@@ -1160,7 +1152,7 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rate_adaptive *p_ra = &(rtlpriv->ra);
-	u32 low_rssithresh_for_ra, high_rssithresh_for_ra;
+	u32 low_rssi_thresh, high_rssi_thresh;
 	struct ieee80211_sta *sta = NULL;
 
 	if (is_hal_stop(rtlhal)) {
@@ -1179,35 +1171,33 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
 	    mac->opmode == NL80211_IFTYPE_STATION) {
 		switch (p_ra->pre_ratr_state) {
 		case DM_RATR_STA_HIGH:
-			high_rssithresh_for_ra = 50;
-			low_rssithresh_for_ra = 20;
+			high_rssi_thresh = 50;
+			low_rssi_thresh = 20;
 			break;
 		case DM_RATR_STA_MIDDLE:
-			high_rssithresh_for_ra = 55;
-			low_rssithresh_for_ra = 20;
+			high_rssi_thresh = 55;
+			low_rssi_thresh = 20;
 			break;
 		case DM_RATR_STA_LOW:
-			high_rssithresh_for_ra = 50;
-			low_rssithresh_for_ra = 25;
+			high_rssi_thresh = 50;
+			low_rssi_thresh = 25;
 			break;
 		default:
-			high_rssithresh_for_ra = 50;
-			low_rssithresh_for_ra = 20;
+			high_rssi_thresh = 50;
+			low_rssi_thresh = 20;
 			break;
 		}
 
-		if (rtlpriv->dm.undecorated_smoothed_pwdb >
-		    (long)high_rssithresh_for_ra)
+		if (rtlpriv->dm.undec_sm_pwdb > (long)high_rssi_thresh)
 			p_ra->ratr_state = DM_RATR_STA_HIGH;
-		else if (rtlpriv->dm.undecorated_smoothed_pwdb >
-			 (long)low_rssithresh_for_ra)
+		else if (rtlpriv->dm.undec_sm_pwdb > (long)low_rssi_thresh)
 			p_ra->ratr_state = DM_RATR_STA_MIDDLE;
 		else
 			p_ra->ratr_state = DM_RATR_STA_LOW;
 
 		if (p_ra->pre_ratr_state != p_ra->ratr_state) {
 			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, "RSSI = %ld\n",
-				 rtlpriv->dm.undecorated_smoothed_pwdb);
+				 rtlpriv->dm.undec_sm_pwdb);
 			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
 				 "RSSI_LEVEL = %d\n", p_ra->ratr_state);
 			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
@@ -1315,7 +1305,7 @@ static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 
 	if (((mac->link_state == MAC80211_NOLINK)) &&
-	    (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
+	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
 		dm_pstable->rssi_val_min = 0;
 		RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, "Not connected to any\n");
 	}
@@ -1323,20 +1313,19 @@ static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
 	if (mac->link_state == MAC80211_LINKED) {
 		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
 			dm_pstable->rssi_val_min =
-			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+			    rtlpriv->dm.entry_min_undec_sm_pwdb;
 			RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
 				 "AP Client PWDB = 0x%lx\n",
 				 dm_pstable->rssi_val_min);
 		} else {
-			dm_pstable->rssi_val_min =
-			    rtlpriv->dm.undecorated_smoothed_pwdb;
+			dm_pstable->rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
 			RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
 				 "STA Default Port PWDB = 0x%lx\n",
 				 dm_pstable->rssi_val_min);
 		}
 	} else {
 		dm_pstable->rssi_val_min =
-		    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+		    rtlpriv->dm.entry_min_undec_sm_pwdb;
 
 		RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
 			 "AP Ext Port PWDB = 0x%lx\n",
@@ -1368,7 +1357,7 @@ void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	long undecorated_smoothed_pwdb;
+	long undec_sm_pwdb;
 
 	if (!rtlpriv->dm.dynamic_txpower_enable)
 		return;
@@ -1379,7 +1368,7 @@ void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
 	}
 
 	if ((mac->link_state < MAC80211_LINKED) &&
-	    (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
+	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
 			 "Not connected to any\n");
 
@@ -1391,41 +1380,35 @@ void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
 
 	if (mac->link_state >= MAC80211_LINKED) {
 		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
-			undecorated_smoothed_pwdb =
-			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+			undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
 			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 				 "AP Client PWDB = 0x%lx\n",
-				 undecorated_smoothed_pwdb);
+				 undec_sm_pwdb);
 		} else {
-			undecorated_smoothed_pwdb =
-			    rtlpriv->dm.undecorated_smoothed_pwdb;
+			undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
 			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 				 "STA Default Port PWDB = 0x%lx\n",
-				 undecorated_smoothed_pwdb);
+				 undec_sm_pwdb);
 		}
 	} else {
-		undecorated_smoothed_pwdb =
-		    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+		undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
 
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			 "AP Ext Port PWDB = 0x%lx\n",
-			 undecorated_smoothed_pwdb);
+			 undec_sm_pwdb);
 	}
 
-	if (undecorated_smoothed_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
+	if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
 		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
-	} else if ((undecorated_smoothed_pwdb <
-		    (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
-		   (undecorated_smoothed_pwdb >=
-		    TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
+	} else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
+		   (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
 
 		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
-	} else if (undecorated_smoothed_pwdb <
-		   (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
+	} else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
 		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			 "TXHIGHPWRLEVEL_NORMAL\n");
@@ -1473,48 +1456,46 @@ u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
-	long undecorated_smoothed_pwdb;
+	long undec_sm_pwdb;
 	u8 curr_bt_rssi_state = 0x00;
 
 	if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
-		undecorated_smoothed_pwdb =
-				 GET_UNDECORATED_AVERAGE_RSSI(rtlpriv);
+		undec_sm_pwdb = GET_UNDECORATED_AVERAGE_RSSI(rtlpriv);
 	} else {
-		if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)
-			undecorated_smoothed_pwdb = 100;
+		if (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)
+			undec_sm_pwdb = 100;
 		else
-			undecorated_smoothed_pwdb =
-				rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+			undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
 	}
 
 	/* Check RSSI to determine HighPower/NormalPower state for
 	 * BT coexistence. */
-	if (undecorated_smoothed_pwdb >= 67)
+	if (undec_sm_pwdb >= 67)
 		curr_bt_rssi_state &= (~BT_RSSI_STATE_NORMAL_POWER);
-	else if (undecorated_smoothed_pwdb < 62)
+	else if (undec_sm_pwdb < 62)
 		curr_bt_rssi_state |= BT_RSSI_STATE_NORMAL_POWER;
 
 	/* Check RSSI to determine AMPDU setting for BT coexistence. */
-	if (undecorated_smoothed_pwdb >= 40)
+	if (undec_sm_pwdb >= 40)
 		curr_bt_rssi_state &= (~BT_RSSI_STATE_AMDPU_OFF);
-	else if (undecorated_smoothed_pwdb <= 32)
+	else if (undec_sm_pwdb <= 32)
 		curr_bt_rssi_state |= BT_RSSI_STATE_AMDPU_OFF;
 
 	/* Marked RSSI state. It will be used to determine BT coexistence
 	 * setting later. */
-	if (undecorated_smoothed_pwdb < 35)
+	if (undec_sm_pwdb < 35)
 		curr_bt_rssi_state |=  BT_RSSI_STATE_SPECIAL_LOW;
 	else
 		curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW);
 
 	/* Set Tx Power according to BT status. */
-	if (undecorated_smoothed_pwdb >= 30)
+	if (undec_sm_pwdb >= 30)
 		curr_bt_rssi_state |=  BT_RSSI_STATE_TXPOWER_LOW;
-	else if (undecorated_smoothed_pwdb < 25)
+	else if (undec_sm_pwdb < 25)
 		curr_bt_rssi_state &= (~BT_RSSI_STATE_TXPOWER_LOW);
 
 	/* Check BT state related to BT_Idle in B/G mode. */
-	if (undecorated_smoothed_pwdb < 15)
+	if (undec_sm_pwdb < 15)
 		curr_bt_rssi_state |=  BT_RSSI_STATE_BG_EDCA_LOW;
 	else
 		curr_bt_rssi_state &= (~BT_RSSI_STATE_BG_EDCA_LOW);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
index cdcad7d..1d5d360 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
@@ -34,9 +34,6 @@
 #include "dm_common.h"
 #include "phy_common.h"
 
-/* Define macro to shorten lines */
-#define MCS_TXPWR	mcs_txpwrlevel_origoffset
-
 u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -138,13 +135,13 @@ u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw,
 		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1,
 						 BIT(8));
 	if (rfpi_enable)
-		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi,
+		retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi,
 					 BLSSIREADBACKDATA);
 	else
-		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback,
+		retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb,
 					 BLSSIREADBACKDATA);
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]=0x%x\n",
-		 rfpath, pphyreg->rflssi_readback, retvalue);
+		 rfpath, pphyreg->rf_rb, retvalue);
 	return retvalue;
 }
 EXPORT_SYMBOL(_rtl92c_phy_rf_serial_read);
@@ -290,11 +287,11 @@ void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw,
 	else
 		return;
 
-	rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][index] = data;
+	rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index] = data;
 	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 		 "MCSTxPowerLevelOriginalOffset[%d][%d] = 0x%x\n",
 		 rtlphy->pwrgroup_cnt, index,
-		 rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][index]);
+		 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index]);
 
 	if (index == 13)
 		rtlphy->pwrgroup_cnt++;
@@ -374,14 +371,10 @@ void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
 	rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2;
 	rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2;
 
-	rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control =
-	    RFPGA0_XAB_SWITCHCONTROL;
-	rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control =
-	    RFPGA0_XAB_SWITCHCONTROL;
-	rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control =
-	    RFPGA0_XCD_SWITCHCONTROL;
-	rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control =
-	    RFPGA0_XCD_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
 
 	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1;
 	rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1;
@@ -393,47 +386,33 @@ void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
 	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2;
 	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
 
-	rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance =
-	    ROFDM0_XARXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance =
-	    ROFDM0_XBRXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance =
-	    ROFDM0_XCRXIQIMBANLANCE;
-	rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance =
-	    ROFDM0_XDRXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBANLANCE;
+	rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE;
 
 	rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE;
 	rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE;
 	rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE;
 	rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
 
-	rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance =
-	    ROFDM0_XATXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance =
-	    ROFDM0_XBTXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance =
-	    ROFDM0_XCTXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance =
-	    ROFDM0_XDTXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE;
 
 	rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE;
 	rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE;
 	rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE;
 	rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE;
 
-	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback =
-	    RFPGA0_XA_LSSIREADBACK;
-	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback =
-	    RFPGA0_XB_LSSIREADBACK;
-	rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback =
-	    RFPGA0_XC_LSSIREADBACK;
-	rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback =
-	    RFPGA0_XD_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK;
 
-	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi =
-	    TRANSCEIVEA_HSPI_READBACK;
-	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi =
-	    TRANSCEIVEB_HSPI_READBACK;
+	rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVEA_HSPI_READBACK;
+	rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVEB_HSPI_READBACK;
 
 }
 EXPORT_SYMBOL(_rtl92c_phy_init_bb_rf_register_definition);
@@ -724,6 +703,26 @@ u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw)
 }
 EXPORT_SYMBOL(rtl92c_phy_sw_chnl);
 
+static void _rtl92c_phy_sw_rf_setting(struct ieee80211_hw *hw, u8 channel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+		if (channel == 6 && rtlphy->current_chan_bw ==
+		    HT_CHANNEL_WIDTH_20)
+			rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD,
+				      0x00255);
+		else{
+			u32 backupRF0x1A = (u32)rtl_get_rfreg(hw, RF90_PATH_A,
+					    RF_RX_G1, RFREG_OFFSET_MASK);
+			rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD,
+				      backupRF0x1A);
+		}
+	}
+}
+
 static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
 					     u32 cmdtableidx, u32 cmdtablesz,
 					     enum swchnlcmd_id cmdid,
@@ -837,6 +836,7 @@ bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
 					      currentcmd->para1,
 					      RFREG_OFFSET_MASK,
 					      rtlphy->rfreg_chnlval[rfpath]);
+			_rtl92c_phy_sw_rf_setting(hw, channel);
 			}
 			break;
 		default:
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
index 2925094..3cfa1bb 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
@@ -116,6 +116,9 @@
 	LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12)
 
 #define CHIP_VER_B			BIT(4)
+#define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3)
+#define CHIP_BONDING_92C_1T2R		0x1
+#define RF_TYPE_1T2R			BIT(1)
 #define CHIP_92C_BITMASK		BIT(0)
 #define CHIP_UNKNOWN			BIT(7)
 #define CHIP_92C_1T2R			0x03
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c
index 27b3af8..74f9c08 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c
@@ -41,7 +41,7 @@ void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	long undecorated_smoothed_pwdb;
+	long undec_sm_pwdb;
 
 	if (!rtlpriv->dm.dynamic_txpower_enable)
 		return;
@@ -52,7 +52,7 @@ void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw)
 	}
 
 	if ((mac->link_state < MAC80211_LINKED) &&
-	    (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
+	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
 			 "Not connected to any\n");
 
@@ -64,41 +64,35 @@ void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw)
 
 	if (mac->link_state >= MAC80211_LINKED) {
 		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
-			undecorated_smoothed_pwdb =
-			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+			undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
 			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 				 "AP Client PWDB = 0x%lx\n",
-				 undecorated_smoothed_pwdb);
+				 undec_sm_pwdb);
 		} else {
-			undecorated_smoothed_pwdb =
-			    rtlpriv->dm.undecorated_smoothed_pwdb;
+			undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
 			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 				 "STA Default Port PWDB = 0x%lx\n",
-				 undecorated_smoothed_pwdb);
+				 undec_sm_pwdb);
 		}
 	} else {
-		undecorated_smoothed_pwdb =
-		    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+		undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
 
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			 "AP Ext Port PWDB = 0x%lx\n",
-			 undecorated_smoothed_pwdb);
+			 undec_sm_pwdb);
 	}
 
-	if (undecorated_smoothed_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
+	if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
 		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
-	} else if ((undecorated_smoothed_pwdb <
-		    (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
-		   (undecorated_smoothed_pwdb >=
-		    TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
+	} else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
+		   (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
 
 		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
-	} else if (undecorated_smoothed_pwdb <
-		   (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
+	} else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
 		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			 "TXHIGHPWRLEVEL_NORMAL\n");
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index 86d73b3..d1f34f6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -896,7 +896,6 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-	static bool iqk_initialized; /* initialized to false */
 	bool rtstatus = true;
 	bool is92c;
 	int err;
@@ -921,9 +920,28 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
 
 	rtlhal->last_hmeboxnum = 0;
 	rtl92c_phy_mac_config(hw);
+	/* because last function modify RCR, so we update
+	 * rcr var here, or TP will unstable for receive_config
+	 * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx
+	 * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252*/
+	rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR);
+	rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
+	rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
 	rtl92c_phy_bb_config(hw);
 	rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
 	rtl92c_phy_rf_config(hw);
+	if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
+	    !IS_92C_SERIAL(rtlhal->version)) {
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00);
+	} else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x0C, MASKDWORD, 0x894AE);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x0A, MASKDWORD, 0x1AF31);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_IPA, MASKDWORD, 0x8F425);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_SYN_G2, MASKDWORD, 0x4F200);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK1, MASKDWORD, 0x44053);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK2, MASKDWORD, 0x80201);
+	}
 	rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
 						 RF_CHNLBW, RFREG_OFFSET_MASK);
 	rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1,
@@ -945,11 +963,11 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
 
 	if (ppsc->rfpwr_state == ERFON) {
 		rtl92c_phy_set_rfpath_switch(hw, 1);
-		if (iqk_initialized) {
+		if (rtlphy->iqk_initialized) {
 			rtl92c_phy_iq_calibrate(hw, true);
 		} else {
 			rtl92c_phy_iq_calibrate(hw, false);
-			iqk_initialized = true;
+			rtlphy->iqk_initialized = true;
 		}
 
 		rtl92c_dm_check_txpower_tracking(hw);
@@ -1004,6 +1022,13 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw)
 				   ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) |
 				   CHIP_VENDOR_UMC));
 		}
+		if (IS_92C_SERIAL(version)) {
+			value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM);
+			version = (enum version_8192c)(version |
+				   ((CHIP_BONDING_IDENTIFIER(value32)
+				   == CHIP_BONDING_92C_1T2R) ?
+				   RF_TYPE_1T2R : 0));
+		}
 	}
 
 	switch (version) {
@@ -1019,12 +1044,30 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw)
 	case VERSION_A_CHIP_88C:
 		versionid = "A_CHIP_88C";
 		break;
+	case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT:
+		versionid = "A_CUT_92C_1T2R";
+		break;
+	case VERSION_NORMAL_UMC_CHIP_92C_A_CUT:
+		versionid = "A_CUT_92C";
+		break;
+	case VERSION_NORMAL_UMC_CHIP_88C_A_CUT:
+		versionid = "A_CUT_88C";
+		break;
+	case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT:
+		versionid = "B_CUT_92C_1T2R";
+		break;
+	case VERSION_NORMAL_UMC_CHIP_92C_B_CUT:
+		versionid = "B_CUT_92C";
+		break;
+	case VERSION_NORMAL_UMC_CHIP_88C_B_CUT:
+		versionid = "B_CUT_88C";
+		break;
 	default:
 		versionid = "Unknown. Bug?";
 		break;
 	}
 
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
 		 "Chip Version ID: %s\n", versionid);
 
 	switch (version & 0x3) {
@@ -1197,6 +1240,7 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
 	u8 u1b_tmp;
 	u32 u4b_tmp;
 
@@ -1225,7 +1269,8 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
 	rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790);
 	rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080);
 	rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80);
-	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23);
+	if (!IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
+		rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23);
 	if (rtlpcipriv->bt_coexist.bt_coexistence) {
 		u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL);
 		u4b_tmp |= 0x03824800;
@@ -1254,6 +1299,9 @@ void rtl92ce_card_disable(struct ieee80211_hw *hw)
 		rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
 	RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
 	_rtl92ce_poweroff_adapter(hw);
+
+	/* after power off we should do iqk again */
+	rtlpriv->phy.iqk_initialized = false;
 }
 
 void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw,
@@ -1355,9 +1403,9 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 			tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i];
 		else
 			tempval = EEPROM_DEFAULT_HT40_2SDIFF;
-		rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_A][i] =
+		rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_A][i] =
 		    (tempval & 0xf);
-		rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_B][i] =
+		rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_B][i] =
 		    ((tempval & 0xf0) >> 4);
 	}
 
@@ -1381,7 +1429,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 				"RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n",
 				rf_path, i,
 				rtlefuse->
-				eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][i]);
+				eprom_chnl_txpwr_ht40_2sdf[rf_path][i]);
 
 	for (rf_path = 0; rf_path < 2; rf_path++) {
 		for (i = 0; i < 14; i++) {
@@ -1396,14 +1444,14 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 			if ((rtlefuse->
 			     eeprom_chnlarea_txpwr_ht40_1s[rf_path][index] -
 			     rtlefuse->
-			     eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][index])
+			     eprom_chnl_txpwr_ht40_2sdf[rf_path][index])
 			    > 0) {
 				rtlefuse->txpwrlevel_ht40_2s[rf_path][i] =
 				    rtlefuse->
 				    eeprom_chnlarea_txpwr_ht40_1s[rf_path]
 				    [index] -
 				    rtlefuse->
-				    eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path]
+				    eprom_chnl_txpwr_ht40_2sdf[rf_path]
 				    [index];
 			} else {
 				rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0;
@@ -1912,16 +1960,16 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw,
 			ratr_bitmap &= 0x0f0ff0ff;
 		break;
 	}
+	sta_entry->ratr_index = ratr_index;
+
 	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
 		 "ratr_bitmap :%x\n", ratr_bitmap);
 	*(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) |
 				     (ratr_index << 28);
 	rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
 	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
-		 "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n",
-		 ratr_index, ratr_bitmap,
-		 rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3],
-		 rate_mask[4]);
+		 "Rate_index:%x, ratr_val:%x, %5phC\n",
+		 ratr_index, ratr_bitmap, rate_mask);
 	rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
 
 	if (macid != 0)
@@ -2176,7 +2224,7 @@ static void rtl8192ce_bt_var_init(struct ieee80211_hw *hw)
 
 	if (rtlpcipriv->bt_coexist.reg_bt_iso == 2)
 		rtlpcipriv->bt_coexist.bt_ant_isolation =
-			rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation;
+			rtlpcipriv->bt_coexist.eeprom_bt_ant_isol;
 	else
 		rtlpcipriv->bt_coexist.bt_ant_isolation =
 			rtlpcipriv->bt_coexist.reg_bt_iso;
@@ -2207,23 +2255,22 @@ void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
 					      bool auto_load_fail, u8 *hwinfo)
 {
 	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
-	u8 value;
+	u8 val;
 
 	if (!auto_load_fail) {
 		rtlpcipriv->bt_coexist.eeprom_bt_coexist =
 					((hwinfo[RF_OPTION1] & 0xe0) >> 5);
-		value = hwinfo[RF_OPTION4];
-		rtlpcipriv->bt_coexist.eeprom_bt_type = ((value & 0xe) >> 1);
-		rtlpcipriv->bt_coexist.eeprom_bt_ant_num = (value & 0x1);
-		rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation =
-							 ((value & 0x10) >> 4);
+		val = hwinfo[RF_OPTION4];
+		rtlpcipriv->bt_coexist.eeprom_bt_type = ((val & 0xe) >> 1);
+		rtlpcipriv->bt_coexist.eeprom_bt_ant_num = (val & 0x1);
+		rtlpcipriv->bt_coexist.eeprom_bt_ant_isol = ((val & 0x10) >> 4);
 		rtlpcipriv->bt_coexist.eeprom_bt_radio_shared =
-							 ((value & 0x20) >> 5);
+							 ((val & 0x20) >> 5);
 	} else {
 		rtlpcipriv->bt_coexist.eeprom_bt_coexist = 0;
 		rtlpcipriv->bt_coexist.eeprom_bt_type = BT_2WIRE;
 		rtlpcipriv->bt_coexist.eeprom_bt_ant_num = ANT_X2;
-		rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation = 0;
+		rtlpcipriv->bt_coexist.eeprom_bt_ant_isol = 0;
 		rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = BT_RADIO_SHARED;
 	}
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
index 88deae6..73262ca 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
@@ -82,6 +82,8 @@ bool rtl92c_phy_mac_config(struct ieee80211_hw *hw)
 
 	if (is92c)
 		rtl_write_byte(rtlpriv, 0x14, 0x71);
+	else
+		rtl_write_byte(rtlpriv, 0x04CA, 0x0A);
 	return rtstatus;
 }
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
index 54c7614..a9c406f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
@@ -97,15 +97,12 @@ void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
 		}
 
 		if (rtlefuse->eeprom_regulatory == 0) {
-			tmpval =
-			    (rtlphy->mcs_txpwrlevel_origoffset[0][6]) +
-			    (rtlphy->mcs_txpwrlevel_origoffset[0][7] <<
-			     8);
+			tmpval = (rtlphy->mcs_offset[0][6]) +
+			    (rtlphy->mcs_offset[0][7] << 8);
 			tx_agc[RF90_PATH_A] += tmpval;
 
-			tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) +
-				 (rtlphy->mcs_txpwrlevel_origoffset[0][15] <<
-				 24);
+			tmpval = (rtlphy->mcs_offset[0][14]) +
+				 (rtlphy->mcs_offset[0][15] << 24);
 			tx_agc[RF90_PATH_B] += tmpval;
 		}
 	}
@@ -209,8 +206,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
 		case 0:
 			chnlgroup = 0;
 
-			writeVal =
-			    rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index +
+			writeVal = rtlphy->mcs_offset[chnlgroup][index +
 			    (rf ? 8 : 0)]
 			    + ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
 
@@ -240,8 +236,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
 						chnlgroup++;
 				}
 
-				writeVal =
-				    rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
+				writeVal = rtlphy->mcs_offset[chnlgroup]
 				    [index + (rf ? 8 : 0)] + ((index < 2) ?
 							      powerBase0[rf] :
 							      powerBase1[rf]);
@@ -276,8 +271,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
 								    1]);
 			}
 			for (i = 0; i < 4; i++) {
-				pwr_diff_limit[i] =
-				    (u8) ((rtlphy->mcs_txpwrlevel_origoffset
+				pwr_diff_limit[i] = (u8) ((rtlphy->mcs_offset
 					  [chnlgroup][index +
 					  (rf ? 8 : 0)] & (0x7f << (i * 8))) >>
 					  (i * 8));
@@ -317,8 +311,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
 			break;
 		default:
 			chnlgroup = 0;
-			writeVal =
-			    rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
+			writeVal = rtlphy->mcs_offset[chnlgroup]
 			    [index + (rf ? 8 : 0)]
 			    + ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
index ea2e1bd..60451ee 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
@@ -162,12 +162,10 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
 
 	/* request fw */
 	if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
-	    !IS_92C_SERIAL(rtlhal->version)) {
+	    !IS_92C_SERIAL(rtlhal->version))
 		rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin";
-	} else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+	else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
 		rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin";
-		pr_info("****** This B_CUT device may not work with kernels 3.6 and earlier\n");
-	}
 
 	rtlpriv->max_fw_size = 0x4000;
 	pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
index 390d6d4..1734247 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
@@ -127,11 +127,11 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct phy_sts_cck_8192s_t *cck_buf;
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
 	s8 rx_pwr_all = 0, rx_pwr[4];
 	u8 evm, pwdb_all, rf_rx_num = 0;
 	u8 i, max_spatial_stream;
 	u32 rssi, total_rssi = 0;
-	bool in_powersavemode = false;
 	bool is_cck_rate;
 
 	is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
@@ -140,14 +140,14 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 	pstats->is_cck = is_cck_rate;
 	pstats->packet_beacon = packet_beacon;
 	pstats->is_cck = is_cck_rate;
-	pstats->rx_mimo_signalquality[0] = -1;
-	pstats->rx_mimo_signalquality[1] = -1;
+	pstats->rx_mimo_sig_qual[0] = -1;
+	pstats->rx_mimo_sig_qual[1] = -1;
 
 	if (is_cck_rate) {
 		u8 report, cck_highpwr;
 		cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
 
-		if (!in_powersavemode)
+		if (ppsc->rfpwr_state == ERFON)
 			cck_highpwr = (u8) rtl_get_bbreg(hw,
 						 RFPGA0_XA_HSSIPARAMETER2,
 						 BIT(9));
@@ -211,8 +211,8 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 			}
 
 			pstats->signalquality = sq;
-			pstats->rx_mimo_signalquality[0] = sq;
-			pstats->rx_mimo_signalquality[1] = -1;
+			pstats->rx_mimo_sig_qual[0] = sq;
+			pstats->rx_mimo_sig_qual[1] = -1;
 		}
 	} else {
 		rtlpriv->dm.rfpath_rxenable[0] =
@@ -251,8 +251,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 				if (i == 0)
 					pstats->signalquality =
 					    (u8) (evm & 0xff);
-				pstats->rx_mimo_signalquality[i] =
-				    (u8) (evm & 0xff);
+				pstats->rx_mimo_sig_qual[i] = (u8) (evm & 0xff);
 			}
 		}
 	}
@@ -362,36 +361,31 @@ static void _rtl92ce_process_pwdb(struct ieee80211_hw *hw,
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	long undecorated_smoothed_pwdb;
+	long undec_sm_pwdb;
 
 	if (mac->opmode == NL80211_IFTYPE_ADHOC) {
 		return;
 	} else {
-		undecorated_smoothed_pwdb =
-		    rtlpriv->dm.undecorated_smoothed_pwdb;
+		undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
 	}
 
 	if (pstats->packet_toself || pstats->packet_beacon) {
-		if (undecorated_smoothed_pwdb < 0)
-			undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
+		if (undec_sm_pwdb < 0)
+			undec_sm_pwdb = pstats->rx_pwdb_all;
 
-		if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
-			undecorated_smoothed_pwdb =
-			    (((undecorated_smoothed_pwdb) *
+		if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) {
+			undec_sm_pwdb = (((undec_sm_pwdb) *
 			      (RX_SMOOTH_FACTOR - 1)) +
 			     (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
 
-			undecorated_smoothed_pwdb = undecorated_smoothed_pwdb
-			    + 1;
+			undec_sm_pwdb += 1;
 		} else {
-			undecorated_smoothed_pwdb =
-			    (((undecorated_smoothed_pwdb) *
+			undec_sm_pwdb = (((undec_sm_pwdb) *
 			      (RX_SMOOTH_FACTOR - 1)) +
 			     (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
 		}
 
-		rtlpriv->dm.undecorated_smoothed_pwdb =
-		    undecorated_smoothed_pwdb;
+		rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
 		_rtl92ce_update_rxsignalstatistics(hw, pstats);
 	}
 }
@@ -438,15 +432,14 @@ static void _rtl92ce_process_ui_link_quality(struct ieee80211_hw *hw,
 			for (n_spatialstream = 0; n_spatialstream < 2;
 			     n_spatialstream++) {
 				if (pstats->
-				    rx_mimo_signalquality[n_spatialstream] !=
-				    -1) {
+				    rx_mimo_sig_qual[n_spatialstream] != -1) {
 					if (rtlpriv->stats.
 					    rx_evm_percentage[n_spatialstream]
 					    == 0) {
 						rtlpriv->stats.
 						   rx_evm_percentage
 						   [n_spatialstream] =
-						   pstats->rx_mimo_signalquality
+						   pstats->rx_mimo_sig_qual
 						   [n_spatialstream];
 					}
 
@@ -456,8 +449,7 @@ static void _rtl92ce_process_ui_link_quality(struct ieee80211_hw *hw,
 					      stats.rx_evm_percentage
 					      [n_spatialstream] *
 					      (RX_SMOOTH_FACTOR - 1)) +
-					     (pstats->
-					      rx_mimo_signalquality
+					     (pstats->rx_mimo_sig_qual
 					      [n_spatialstream] * 1)) /
 					    (RX_SMOOTH_FACTOR);
 				}
@@ -567,7 +559,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
 	if (GET_RX_DESC_RXHT(pdesc))
 		rx_status->flag |= RX_FLAG_HT;
 
-	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+	rx_status->flag |= RX_FLAG_MACTIME_START;
 
 	if (stats->decrypted)
 		rx_status->flag |= RX_FLAG_DECRYPTED;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c
index 6fd39ea..16a0b9e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c
@@ -39,7 +39,7 @@ void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	long undecorated_smoothed_pwdb;
+	long undec_sm_pwdb;
 
 	if (!rtlpriv->dm.dynamic_txpower_enable)
 		return;
@@ -50,7 +50,7 @@ void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw)
 	}
 
 	if ((mac->link_state < MAC80211_LINKED) &&
-	    (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
+	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
 			 "Not connected to any\n");
 
@@ -62,41 +62,35 @@ void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw)
 
 	if (mac->link_state >= MAC80211_LINKED) {
 		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
-			undecorated_smoothed_pwdb =
-			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+			undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
 			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 				 "AP Client PWDB = 0x%lx\n",
-				 undecorated_smoothed_pwdb);
+				 undec_sm_pwdb);
 		} else {
-			undecorated_smoothed_pwdb =
-			    rtlpriv->dm.undecorated_smoothed_pwdb;
+			undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
 			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 				 "STA Default Port PWDB = 0x%lx\n",
-				 undecorated_smoothed_pwdb);
+				 undec_sm_pwdb);
 		}
 	} else {
-		undecorated_smoothed_pwdb =
-		    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+		undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
 
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			 "AP Ext Port PWDB = 0x%lx\n",
-			 undecorated_smoothed_pwdb);
+			 undec_sm_pwdb);
 	}
 
-	if (undecorated_smoothed_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
+	if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
 		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
-	} else if ((undecorated_smoothed_pwdb <
-		    (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
-		   (undecorated_smoothed_pwdb >=
-		    TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
+	} else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
+		   (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
 
 		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
-	} else if (undecorated_smoothed_pwdb <
-		   (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
+	} else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
 		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			 "TXHIGHPWRLEVEL_NORMAL\n");
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
index 4bbb711..b1ccff4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -152,9 +152,9 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 			tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i];
 		else
 			tempval = EEPROM_DEFAULT_HT40_2SDIFF;
-		rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_A][i] =
+		rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_A][i] =
 		    (tempval & 0xf);
-		rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_B][i] =
+		rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_B][i] =
 		    ((tempval & 0xf0) >> 4);
 	}
 	for (rf_path = 0; rf_path < 2; rf_path++)
@@ -177,7 +177,7 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 				"RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n",
 				rf_path, i,
 				rtlefuse->
-				eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][i]);
+				eprom_chnl_txpwr_ht40_2sdf[rf_path][i]);
 	for (rf_path = 0; rf_path < 2; rf_path++) {
 		for (i = 0; i < 14; i++) {
 			index = _rtl92c_get_chnl_group((u8) i);
@@ -189,13 +189,13 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 			if ((rtlefuse->
 			     eeprom_chnlarea_txpwr_ht40_1s[rf_path][index] -
 			     rtlefuse->
-			     eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][index])
+			     eprom_chnl_txpwr_ht40_2sdf[rf_path][index])
 			    > 0) {
 				rtlefuse->txpwrlevel_ht40_2s[rf_path][i] =
 				    rtlefuse->
 				    eeprom_chnlarea_txpwr_ht40_1s[rf_path]
 				    [index] - rtlefuse->
-				    eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path]
+				    eprom_chnl_txpwr_ht40_2sdf[rf_path]
 				    [index];
 			} else {
 				rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0;
@@ -2169,10 +2169,8 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
 				      ratr_index << 28);
 	rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
 	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
-		 "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n",
-		 ratr_index, ratr_bitmap,
-		 rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3],
-		 rate_mask[4]);
+		 "Rate_index:%x, ratr_val:%x, %5phC\n",
+		 ratr_index, ratr_bitmap, rate_mask);
 	rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
 }
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
index 7e91c76..32ff959 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
@@ -46,7 +46,7 @@
 
 #define LINK_Q	ui_link_quality
 #define RX_EVM	rx_evm_percentage
-#define RX_SIGQ	rx_mimo_signalquality
+#define RX_SIGQ	rx_mimo_sig_qual
 
 
 void rtl92c_read_chip_version(struct ieee80211_hw *hw)
@@ -982,32 +982,27 @@ static void _rtl92c_process_pwdb(struct ieee80211_hw *hw,
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	long undecorated_smoothed_pwdb = 0;
+	long undec_sm_pwdb = 0;
 
 	if (mac->opmode == NL80211_IFTYPE_ADHOC) {
 		return;
 	} else {
-		undecorated_smoothed_pwdb =
-		    rtlpriv->dm.undecorated_smoothed_pwdb;
+		undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
 	}
 	if (pstats->packet_toself || pstats->packet_beacon) {
-		if (undecorated_smoothed_pwdb < 0)
-			undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
-		if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
-			undecorated_smoothed_pwdb =
-			    (((undecorated_smoothed_pwdb) *
+		if (undec_sm_pwdb < 0)
+			undec_sm_pwdb = pstats->rx_pwdb_all;
+		if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) {
+			undec_sm_pwdb = (((undec_sm_pwdb) *
 			      (RX_SMOOTH_FACTOR - 1)) +
 			     (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
-			undecorated_smoothed_pwdb = undecorated_smoothed_pwdb
-			    + 1;
+			undec_sm_pwdb += 1;
 		} else {
-			undecorated_smoothed_pwdb =
-			    (((undecorated_smoothed_pwdb) *
+			undec_sm_pwdb = (((undec_sm_pwdb) *
 			      (RX_SMOOTH_FACTOR - 1)) +
 			     (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
 		}
-		rtlpriv->dm.undecorated_smoothed_pwdb =
-		    undecorated_smoothed_pwdb;
+		rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
 		_rtl92c_update_rxsignalstatistics(hw, pstats);
 	}
 }
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
index 506b9a0..953f1a0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
@@ -115,15 +115,11 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
 				    (ppowerlevel[idx1] << 24);
 			}
 			if (rtlefuse->eeprom_regulatory == 0) {
-				tmpval = (rtlphy->mcs_txpwrlevel_origoffset
-					[0][6]) +
-					(rtlphy->mcs_txpwrlevel_origoffset
-					[0][7] <<  8);
+				tmpval = (rtlphy->mcs_offset[0][6]) +
+					(rtlphy->mcs_offset[0][7] <<  8);
 				tx_agc[RF90_PATH_A] += tmpval;
-				tmpval = (rtlphy->mcs_txpwrlevel_origoffset
-					[0][14]) +
-					(rtlphy->mcs_txpwrlevel_origoffset
-					[0][15] << 24);
+				tmpval = (rtlphy->mcs_offset[0][14]) +
+					(rtlphy->mcs_offset[0][15] << 24);
 				tx_agc[RF90_PATH_B] += tmpval;
 			}
 		}
@@ -215,7 +211,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
 		switch (rtlefuse->eeprom_regulatory) {
 		case 0:
 			chnlgroup = 0;
-			writeVal = rtlphy->mcs_txpwrlevel_origoffset
+			writeVal = rtlphy->mcs_offset
 			    [chnlgroup][index + (rf ? 8 : 0)]
 			    + ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
 			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
@@ -238,8 +234,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
 				else
 					chnlgroup += 4;
 			}
-			writeVal = rtlphy->mcs_txpwrlevel_origoffset
-					[chnlgroup][index +
+			writeVal = rtlphy->mcs_offset[chnlgroup][index +
 					(rf ? 8 : 0)] +
 					((index < 2) ? powerBase0[rf] :
 					powerBase1[rf]);
@@ -271,8 +266,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
 					[channel - 1]);
 			}
 			for (i = 0; i < 4; i++) {
-				pwr_diff_limit[i] =
-				    (u8) ((rtlphy->mcs_txpwrlevel_origoffset
+				pwr_diff_limit[i] = (u8) ((rtlphy->mcs_offset
 				    [chnlgroup][index + (rf ? 8 : 0)]
 				    & (0x7f << (i * 8))) >> (i * 8));
 				if (rtlphy->current_chan_bw ==
@@ -306,7 +300,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
 			break;
 		default:
 			chnlgroup = 0;
-			writeVal = rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
+			writeVal = rtlphy->mcs_offset[chnlgroup]
 				   [index + (rf ? 8 : 0)] + ((index < 2) ?
 				   powerBase0[rf] : powerBase1[rf]);
 			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
index 6e66f04..b6222ee 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
@@ -334,7 +334,7 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
 		rx_status->flag |= RX_FLAG_40MHZ;
 	if (GET_RX_DESC_RX_HT(pdesc))
 		rx_status->flag |= RX_FLAG_HT;
-	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+	rx_status->flag |= RX_FLAG_MACTIME_START;
 	if (stats->decrypted)
 		rx_status->flag |= RX_FLAG_DECRYPTED;
 	rx_status->rate_idx = rtlwifi_rate_mapping(hw,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
index ed868c3..fd8df23 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c
@@ -35,7 +35,7 @@
 #include "dm.h"
 #include "fw.h"
 
-#define UNDEC_SM_PWDB	entry_min_undecoratedsmoothed_pwdb
+#define UNDEC_SM_PWDB	entry_min_undec_sm_pwdb
 
 static const u32 ofdmswing_table[OFDM_TABLE_SIZE_92D] = {
 	0x7f8001fe,		/* 0, +6.0dB */
@@ -164,18 +164,18 @@ static void rtl92d_dm_diginit(struct ieee80211_hw *hw)
 	de_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
 	de_digtable->cur_igvalue = 0x20;
 	de_digtable->pre_igvalue = 0x0;
-	de_digtable->cursta_connectstate = DIG_STA_DISCONNECT;
-	de_digtable->presta_connectstate = DIG_STA_DISCONNECT;
-	de_digtable->curmultista_connectstate = DIG_MULTISTA_DISCONNECT;
+	de_digtable->cursta_cstate = DIG_STA_DISCONNECT;
+	de_digtable->presta_cstate = DIG_STA_DISCONNECT;
+	de_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT;
 	de_digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
 	de_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
 	de_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
 	de_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
 	de_digtable->rx_gain_range_max = DM_DIG_FA_UPPER;
 	de_digtable->rx_gain_range_min = DM_DIG_FA_LOWER;
-	de_digtable->backoff_val = DM_DIG_BACKOFF_DEFAULT;
-	de_digtable->backoff_val_range_max = DM_DIG_BACKOFF_MAX;
-	de_digtable->backoff_val_range_min = DM_DIG_BACKOFF_MIN;
+	de_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
+	de_digtable->back_range_max = DM_DIG_BACKOFF_MAX;
+	de_digtable->back_range_min = DM_DIG_BACKOFF_MIN;
 	de_digtable->pre_cck_pd_state = CCK_PD_STAGE_LOWRSSI;
 	de_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX;
 	de_digtable->large_fa_hit = 0;
@@ -273,35 +273,34 @@ static void rtl92d_dm_find_minimum_rssi(struct ieee80211_hw *hw)
 	/* Determine the minimum RSSI  */
 	if ((mac->link_state < MAC80211_LINKED) &&
 	    (rtlpriv->dm.UNDEC_SM_PWDB == 0)) {
-		de_digtable->min_undecorated_pwdb_for_dm = 0;
+		de_digtable->min_undec_pwdb_for_dm = 0;
 		RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 			 "Not connected to any\n");
 	}
 	if (mac->link_state >= MAC80211_LINKED) {
 		if (mac->opmode == NL80211_IFTYPE_AP ||
 		    mac->opmode == NL80211_IFTYPE_ADHOC) {
-			de_digtable->min_undecorated_pwdb_for_dm =
+			de_digtable->min_undec_pwdb_for_dm =
 			    rtlpriv->dm.UNDEC_SM_PWDB;
 			RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 				 "AP Client PWDB = 0x%lx\n",
 				 rtlpriv->dm.UNDEC_SM_PWDB);
 		} else {
-			de_digtable->min_undecorated_pwdb_for_dm =
-			    rtlpriv->dm.undecorated_smoothed_pwdb;
+			de_digtable->min_undec_pwdb_for_dm =
+			    rtlpriv->dm.undec_sm_pwdb;
 			RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 				 "STA Default Port PWDB = 0x%x\n",
-				 de_digtable->min_undecorated_pwdb_for_dm);
+				 de_digtable->min_undec_pwdb_for_dm);
 		}
 	} else {
-		de_digtable->min_undecorated_pwdb_for_dm =
-		    rtlpriv->dm.UNDEC_SM_PWDB;
+		de_digtable->min_undec_pwdb_for_dm = rtlpriv->dm.UNDEC_SM_PWDB;
 		RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 			 "AP Ext Port or disconnect PWDB = 0x%x\n",
-			 de_digtable->min_undecorated_pwdb_for_dm);
+			 de_digtable->min_undec_pwdb_for_dm);
 	}
 
 	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n",
-		 de_digtable->min_undecorated_pwdb_for_dm);
+		 de_digtable->min_undec_pwdb_for_dm);
 }
 
 static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
@@ -310,16 +309,16 @@ static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
 	struct dig_t *de_digtable = &rtlpriv->dm_digtable;
 	unsigned long flag = 0;
 
-	if (de_digtable->cursta_connectstate == DIG_STA_CONNECT) {
+	if (de_digtable->cursta_cstate == DIG_STA_CONNECT) {
 		if (de_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
-			if (de_digtable->min_undecorated_pwdb_for_dm <= 25)
+			if (de_digtable->min_undec_pwdb_for_dm <= 25)
 				de_digtable->cur_cck_pd_state =
 							 CCK_PD_STAGE_LOWRSSI;
 			else
 				de_digtable->cur_cck_pd_state =
 							 CCK_PD_STAGE_HIGHRSSI;
 		} else {
-			if (de_digtable->min_undecorated_pwdb_for_dm <= 20)
+			if (de_digtable->min_undec_pwdb_for_dm <= 20)
 				de_digtable->cur_cck_pd_state =
 							 CCK_PD_STAGE_LOWRSSI;
 			else
@@ -342,7 +341,7 @@ static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
 		de_digtable->pre_cck_pd_state = de_digtable->cur_cck_pd_state;
 	}
 	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "CurSTAConnectState=%s\n",
-		 de_digtable->cursta_connectstate == DIG_STA_CONNECT ?
+		 de_digtable->cursta_cstate == DIG_STA_CONNECT ?
 		 "DIG_STA_CONNECT " : "DIG_STA_DISCONNECT");
 	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "CCKPDStage=%s\n",
 		 de_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI ?
@@ -358,9 +357,9 @@ void rtl92d_dm_write_dig(struct ieee80211_hw *hw)
 	struct dig_t *de_digtable = &rtlpriv->dm_digtable;
 
 	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
-		 "cur_igvalue = 0x%x, pre_igvalue = 0x%x, backoff_val = %d\n",
+		 "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n",
 		 de_digtable->cur_igvalue, de_digtable->pre_igvalue,
-		 de_digtable->backoff_val);
+		 de_digtable->back_val);
 	if (de_digtable->dig_enable_flag == false) {
 		RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "DIG is disabled\n");
 		de_digtable->pre_igvalue = 0x17;
@@ -382,13 +381,13 @@ static void rtl92d_early_mode_enabled(struct rtl_priv *rtlpriv)
 	if ((rtlpriv->mac80211.link_state >= MAC80211_LINKED) &&
 	    (rtlpriv->mac80211.vendor == PEER_CISCO)) {
 		RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "IOT_PEER = CISCO\n");
-		if (de_digtable->last_min_undecorated_pwdb_for_dm >= 50
-		    && de_digtable->min_undecorated_pwdb_for_dm < 50) {
+		if (de_digtable->last_min_undec_pwdb_for_dm >= 50
+		    && de_digtable->min_undec_pwdb_for_dm < 50) {
 			rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x00);
 			RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 				 "Early Mode Off\n");
-		} else if (de_digtable->last_min_undecorated_pwdb_for_dm <= 55 &&
-			   de_digtable->min_undecorated_pwdb_for_dm > 55) {
+		} else if (de_digtable->last_min_undec_pwdb_for_dm <= 55 &&
+			   de_digtable->min_undec_pwdb_for_dm > 55) {
 			rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f);
 			RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
 				 "Early Mode On\n");
@@ -409,8 +408,8 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw)
 	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "==>\n");
 	if (rtlpriv->rtlhal.earlymode_enable) {
 		rtl92d_early_mode_enabled(rtlpriv);
-		de_digtable->last_min_undecorated_pwdb_for_dm =
-				 de_digtable->min_undecorated_pwdb_for_dm;
+		de_digtable->last_min_undec_pwdb_for_dm =
+				 de_digtable->min_undec_pwdb_for_dm;
 	}
 	if (!rtlpriv->dm.dm_initialgain_enable)
 		return;
@@ -428,9 +427,9 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw)
 	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "progress\n");
 	/* Decide the current status and if modify initial gain or not */
 	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED)
-		de_digtable->cursta_connectstate = DIG_STA_CONNECT;
+		de_digtable->cursta_cstate = DIG_STA_CONNECT;
 	else
-		de_digtable->cursta_connectstate = DIG_STA_DISCONNECT;
+		de_digtable->cursta_cstate = DIG_STA_DISCONNECT;
 
 	/* adjust initial gain according to false alarm counter */
 	if (falsealm_cnt->cnt_all < DM_DIG_FA_TH0)
@@ -522,7 +521,7 @@ static void rtl92d_dm_dynamic_txpower(struct ieee80211_hw *hw)
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	long undecorated_smoothed_pwdb;
+	long undec_sm_pwdb;
 
 	if ((!rtlpriv->dm.dynamic_txpower_enable)
 	    || rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
@@ -539,62 +538,62 @@ static void rtl92d_dm_dynamic_txpower(struct ieee80211_hw *hw)
 	}
 	if (mac->link_state >= MAC80211_LINKED) {
 		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
-			undecorated_smoothed_pwdb =
+			undec_sm_pwdb =
 			    rtlpriv->dm.UNDEC_SM_PWDB;
 			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 				 "IBSS Client PWDB = 0x%lx\n",
-				 undecorated_smoothed_pwdb);
+				 undec_sm_pwdb);
 		} else {
-			undecorated_smoothed_pwdb =
-			    rtlpriv->dm.undecorated_smoothed_pwdb;
+			undec_sm_pwdb =
+			    rtlpriv->dm.undec_sm_pwdb;
 			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 				 "STA Default Port PWDB = 0x%lx\n",
-				 undecorated_smoothed_pwdb);
+				 undec_sm_pwdb);
 		}
 	} else {
-		undecorated_smoothed_pwdb =
+		undec_sm_pwdb =
 		    rtlpriv->dm.UNDEC_SM_PWDB;
 
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			 "AP Ext Port PWDB = 0x%lx\n",
-			 undecorated_smoothed_pwdb);
+			 undec_sm_pwdb);
 	}
 	if (rtlhal->current_bandtype == BAND_ON_5G) {
-		if (undecorated_smoothed_pwdb >= 0x33) {
+		if (undec_sm_pwdb >= 0x33) {
 			rtlpriv->dm.dynamic_txhighpower_lvl =
 						 TXHIGHPWRLEVEL_LEVEL2;
 			RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD,
 				 "5G:TxHighPwrLevel_Level2 (TxPwr=0x0)\n");
-		} else if ((undecorated_smoothed_pwdb < 0x33)
-			   && (undecorated_smoothed_pwdb >= 0x2b)) {
+		} else if ((undec_sm_pwdb < 0x33)
+			   && (undec_sm_pwdb >= 0x2b)) {
 			rtlpriv->dm.dynamic_txhighpower_lvl =
 						 TXHIGHPWRLEVEL_LEVEL1;
 			RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD,
 				 "5G:TxHighPwrLevel_Level1 (TxPwr=0x10)\n");
-		} else if (undecorated_smoothed_pwdb < 0x2b) {
+		} else if (undec_sm_pwdb < 0x2b) {
 			rtlpriv->dm.dynamic_txhighpower_lvl =
 						 TXHIGHPWRLEVEL_NORMAL;
 			RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD,
 				 "5G:TxHighPwrLevel_Normal\n");
 		}
 	} else {
-		if (undecorated_smoothed_pwdb >=
+		if (undec_sm_pwdb >=
 		    TX_POWER_NEAR_FIELD_THRESH_LVL2) {
 			rtlpriv->dm.dynamic_txhighpower_lvl =
 						 TXHIGHPWRLEVEL_LEVEL2;
 			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 				 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
 		} else
-		    if ((undecorated_smoothed_pwdb <
+		    if ((undec_sm_pwdb <
 			 (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3))
-			&& (undecorated_smoothed_pwdb >=
+			&& (undec_sm_pwdb >=
 			    TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
 
 			rtlpriv->dm.dynamic_txhighpower_lvl =
 						 TXHIGHPWRLEVEL_LEVEL1;
 			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 				 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
-		} else if (undecorated_smoothed_pwdb <
+		} else if (undec_sm_pwdb <
 			   (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
 			rtlpriv->dm.dynamic_txhighpower_lvl =
 						 TXHIGHPWRLEVEL_NORMAL;
@@ -620,7 +619,7 @@ static void rtl92d_dm_pwdb_monitor(struct ieee80211_hw *hw)
 		return;
 	/* Indicate Rx signal strength to FW. */
 	if (rtlpriv->dm.useramask) {
-		u32 temp = rtlpriv->dm.undecorated_smoothed_pwdb;
+		u32 temp = rtlpriv->dm.undec_sm_pwdb;
 
 		temp <<= 16;
 		temp |= 0x100;
@@ -629,7 +628,7 @@ static void rtl92d_dm_pwdb_monitor(struct ieee80211_hw *hw)
 		rtl92d_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, (u8 *) (&temp));
 	} else {
 		rtl_write_byte(rtlpriv, 0x4fe,
-			       (u8) rtlpriv->dm.undecorated_smoothed_pwdb);
+			       (u8) rtlpriv->dm.undec_sm_pwdb);
 	}
 }
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
index db00860..33041bd 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
@@ -298,13 +298,13 @@ static u32 _rtl92d_phy_rf_serial_read(struct ieee80211_hw *hw,
 		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1,
 			      BIT(8));
 	if (rfpi_enable)
-		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi,
+		retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi,
 			BLSSIREADBACKDATA);
 	else
-		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback,
+		retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb,
 			BLSSIREADBACKDATA);
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x] = 0x%x\n",
-		 rfpath, pphyreg->rflssi_readback, retvalue);
+		 rfpath, pphyreg->rf_rb, retvalue);
 	return retvalue;
 }
 
@@ -478,14 +478,10 @@ static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
 
 	/* RF switch Control */
 	/* TR/Ant switch control */
-	rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control =
-		RFPGA0_XAB_SWITCHCONTROL;
-	rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control =
-	    RFPGA0_XAB_SWITCHCONTROL;
-	rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control =
-	    RFPGA0_XCD_SWITCHCONTROL;
-	rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control =
-	    RFPGA0_XCD_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
 
 	/* AGC control 1 */
 	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1;
@@ -500,14 +496,10 @@ static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
 	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
 
 	/* RX AFE control 1 */
-	rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance =
-	    ROFDM0_XARXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance =
-	    ROFDM0_XBRXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance =
-	    ROFDM0_XCRXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance =
-	    ROFDM0_XDRXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE;
 
 	/*RX AFE control 1 */
 	rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE;
@@ -516,14 +508,10 @@ static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
 	rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
 
 	/* Tx AFE control 1 */
-	rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance =
-	    ROFDM0_XATxIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance =
-	    ROFDM0_XBTxIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance =
-	    ROFDM0_XCTxIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance =
-	    ROFDM0_XDTxIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATxIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTxIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTxIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTxIQIMBALANCE;
 
 	/* Tx AFE control 2 */
 	rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATxAFE;
@@ -532,20 +520,14 @@ static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
 	rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTxAFE;
 
 	/* Tranceiver LSSI Readback SI mode */
-	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback =
-	    RFPGA0_XA_LSSIREADBACK;
-	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback =
-	    RFPGA0_XB_LSSIREADBACK;
-	rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback =
-	    RFPGA0_XC_LSSIREADBACK;
-	rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback =
-	    RFPGA0_XD_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK;
 
 	/* Tranceiver LSSI Readback PI mode */
-	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi =
-	    TRANSCEIVERA_HSPI_READBACK;
-	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi =
-	    TRANSCEIVERB_HSPI_READBACK;
+	rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVERA_HSPI_READBACK;
+	rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVERB_HSPI_READBACK;
 }
 
 static bool _rtl92d_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
@@ -702,12 +684,11 @@ static void _rtl92d_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw,
 	else
 		return;
 
-	rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][index] = data;
+	rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index] = data;
 	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 		 "MCSTxPowerLevelOriginalOffset[%d][%d] = 0x%ulx\n",
 		 rtlphy->pwrgroup_cnt, index,
-		 rtlphy->mcs_txpwrlevel_origoffset
-		 [rtlphy->pwrgroup_cnt][index]);
+		 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index]);
 	if (index == 13)
 		rtlphy->pwrgroup_cnt++;
 }
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.c b/drivers/net/wireless/rtlwifi/rtl8192de/rf.c
index 3066a7fb..20144e0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/rf.c
@@ -106,11 +106,11 @@ void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
 			    (ppowerlevel[idx1] << 24);
 		}
 		if (rtlefuse->eeprom_regulatory == 0) {
-			tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][6]) +
-			    (rtlphy->mcs_txpwrlevel_origoffset[0][7] << 8);
+			tmpval = (rtlphy->mcs_offset[0][6]) +
+			    (rtlphy->mcs_offset[0][7] << 8);
 			tx_agc[RF90_PATH_A] += tmpval;
-			tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) +
-			    (rtlphy->mcs_txpwrlevel_origoffset[0][15] << 24);
+			tmpval = (rtlphy->mcs_offset[0][14]) +
+			    (rtlphy->mcs_offset[0][15] << 24);
 			tx_agc[RF90_PATH_B] += tmpval;
 		}
 	}
@@ -227,7 +227,7 @@ static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
 		switch (rtlefuse->eeprom_regulatory) {
 		case 0:
 			chnlgroup = 0;
-			writeval = rtlphy->mcs_txpwrlevel_origoffset
+			writeval = rtlphy->mcs_offset
 					[chnlgroup][index +
 					(rf ? 8 : 0)] + ((index < 2) ?
 					powerbase0[rf] :
@@ -247,7 +247,7 @@ static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
 					chnlgroup++;
 				else
 					chnlgroup += 4;
-				writeval = rtlphy->mcs_txpwrlevel_origoffset
+				writeval = rtlphy->mcs_offset
 						[chnlgroup][index +
 						(rf ? 8 : 0)] + ((index < 2) ?
 						powerbase0[rf] :
@@ -280,8 +280,7 @@ static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
 					[channel - 1]);
 			}
 			for (i = 0; i < 4; i++) {
-				pwr_diff_limit[i] =
-					(u8)((rtlphy->mcs_txpwrlevel_origoffset
+				pwr_diff_limit[i] = (u8)((rtlphy->mcs_offset
 					[chnlgroup][index + (rf ? 8 : 0)] &
 					(0x7f << (i * 8))) >> (i * 8));
 				if (rtlphy->current_chan_bw ==
@@ -316,8 +315,7 @@ static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
 			break;
 		default:
 			chnlgroup = 0;
-			writeval = rtlphy->mcs_txpwrlevel_origoffset
-				   [chnlgroup][index +
+			writeval = rtlphy->mcs_offset[chnlgroup][index +
 				   (rf ? 8 : 0)] + ((index < 2) ?
 				   powerbase0[rf] : powerbase1[rf]);
 			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
index 4686f34..f9f3861 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
@@ -132,8 +132,8 @@ static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw,
 	pstats->packet_toself = packet_toself;
 	pstats->packet_beacon = packet_beacon;
 	pstats->is_cck = is_cck_rate;
-	pstats->rx_mimo_signalquality[0] = -1;
-	pstats->rx_mimo_signalquality[1] = -1;
+	pstats->rx_mimo_sig_qual[0] = -1;
+	pstats->rx_mimo_sig_qual[1] = -1;
 
 	if (is_cck_rate) {
 		u8 report, cck_highpwr;
@@ -212,8 +212,8 @@ static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw,
 					sq = ((64 - sq) * 100) / 44;
 			}
 			pstats->signalquality = sq;
-			pstats->rx_mimo_signalquality[0] = sq;
-			pstats->rx_mimo_signalquality[1] = -1;
+			pstats->rx_mimo_sig_qual[0] = sq;
+			pstats->rx_mimo_sig_qual[1] = -1;
 		}
 	} else {
 		rtlpriv->dm.rfpath_rxenable[0] = true;
@@ -246,7 +246,7 @@ static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw,
 				if (i == 0)
 					pstats->signalquality =
 						 (u8)(evm & 0xff);
-				pstats->rx_mimo_signalquality[i] =
+				pstats->rx_mimo_sig_qual[i] =
 						 (u8)(evm & 0xff);
 			}
 		}
@@ -345,33 +345,28 @@ static void _rtl92de_process_pwdb(struct ieee80211_hw *hw,
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	long undecorated_smoothed_pwdb;
+	long undec_sm_pwdb;
 
 	if (mac->opmode == NL80211_IFTYPE_ADHOC	||
 		mac->opmode == NL80211_IFTYPE_AP)
 		return;
 	else
-		undecorated_smoothed_pwdb =
-		    rtlpriv->dm.undecorated_smoothed_pwdb;
+		undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
 
 	if (pstats->packet_toself || pstats->packet_beacon) {
-		if (undecorated_smoothed_pwdb < 0)
-			undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
-		if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
-			undecorated_smoothed_pwdb =
-			      (((undecorated_smoothed_pwdb) *
+		if (undec_sm_pwdb < 0)
+			undec_sm_pwdb = pstats->rx_pwdb_all;
+		if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) {
+			undec_sm_pwdb = (((undec_sm_pwdb) *
 			      (RX_SMOOTH_FACTOR - 1)) +
 			      (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
-			undecorated_smoothed_pwdb =
-			      undecorated_smoothed_pwdb + 1;
+			undec_sm_pwdb = undec_sm_pwdb + 1;
 		} else {
-			undecorated_smoothed_pwdb =
-			      (((undecorated_smoothed_pwdb) *
+			undec_sm_pwdb = (((undec_sm_pwdb) *
 			      (RX_SMOOTH_FACTOR - 1)) +
 			      (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
 		}
-		rtlpriv->dm.undecorated_smoothed_pwdb =
-				 undecorated_smoothed_pwdb;
+		rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
 		_rtl92de_update_rxsignalstatistics(hw, pstats);
 	}
 }
@@ -383,15 +378,15 @@ static void rtl92d_loop_over_streams(struct ieee80211_hw *hw,
 	int stream;
 
 	for (stream = 0; stream < 2; stream++) {
-		if (pstats->rx_mimo_signalquality[stream] != -1) {
+		if (pstats->rx_mimo_sig_qual[stream] != -1) {
 			if (rtlpriv->stats.rx_evm_percentage[stream] == 0) {
 				rtlpriv->stats.rx_evm_percentage[stream] =
-				    pstats->rx_mimo_signalquality[stream];
+				    pstats->rx_mimo_sig_qual[stream];
 			}
 			rtlpriv->stats.rx_evm_percentage[stream] =
 			    ((rtlpriv->stats.rx_evm_percentage[stream]
 			      * (RX_SMOOTH_FACTOR - 1)) +
-			     (pstats->rx_mimo_signalquality[stream] * 1)) /
+			     (pstats->rx_mimo_sig_qual[stream] * 1)) /
 			    (RX_SMOOTH_FACTOR);
 		}
 	}
@@ -514,7 +509,7 @@ bool rtl92de_rx_query_desc(struct ieee80211_hw *hw,	struct rtl_stats *stats,
 		rx_status->flag |= RX_FLAG_40MHZ;
 	if (GET_RX_DESC_RXHT(pdesc))
 		rx_status->flag |= RX_FLAG_HT;
-	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+	rx_status->flag |= RX_FLAG_MACTIME_START;
 	if (stats->decrypted)
 		rx_status->flag |= RX_FLAG_DECRYPTED;
 	rx_status->rate_idx = rtlwifi_rate_mapping(hw,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
index 465f581..bf79a52 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c
@@ -267,13 +267,12 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
 			break;
 		}
 
-		if (rtlpriv->dm.undecorated_smoothed_pwdb >
-		    (long)high_rssi_thresh) {
+		if (rtlpriv->dm.undec_sm_pwdb > (long)high_rssi_thresh) {
 			ra->ratr_state = DM_RATR_STA_HIGH;
-		} else if (rtlpriv->dm.undecorated_smoothed_pwdb >
+		} else if (rtlpriv->dm.undec_sm_pwdb >
 			   (long)middle_rssi_thresh) {
 			ra->ratr_state = DM_RATR_STA_LOW;
-		} else if (rtlpriv->dm.undecorated_smoothed_pwdb >
+		} else if (rtlpriv->dm.undec_sm_pwdb >
 			   (long)low_rssi_thresh) {
 			ra->ratr_state = DM_RATR_STA_LOW;
 		} else {
@@ -283,8 +282,7 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
 		if (ra->pre_ratr_state != ra->ratr_state) {
 			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
 				 "RSSI = %ld RSSI_LEVEL = %d PreState = %d, CurState = %d\n",
-				 rtlpriv->dm.undecorated_smoothed_pwdb,
-				 ra->ratr_state,
+				 rtlpriv->dm.undec_sm_pwdb, ra->ratr_state,
 				 ra->pre_ratr_state, ra->ratr_state);
 
 			rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
@@ -316,7 +314,7 @@ static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw)
 	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MRC, (u8 *)(&current_mrc));
 
 	if (mac->link_state >= MAC80211_LINKED) {
-		if (rtlpriv->dm.undecorated_smoothed_pwdb > tmpentry_maxpwdb) {
+		if (rtlpriv->dm.undec_sm_pwdb > tmpentry_maxpwdb) {
 			rssi_a = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_A];
 			rssi_b = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_B];
 		}
@@ -424,18 +422,18 @@ static void rtl92s_backoff_enable_flag(struct ieee80211_hw *hw)
 	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
 
 	if (falsealm_cnt->cnt_all > digtable->fa_highthresh) {
-		if ((digtable->backoff_val - 6) <
+		if ((digtable->back_val - 6) <
 			digtable->backoffval_range_min)
-			digtable->backoff_val = digtable->backoffval_range_min;
+			digtable->back_val = digtable->backoffval_range_min;
 		else
-			digtable->backoff_val -= 6;
+			digtable->back_val -= 6;
 	} else if (falsealm_cnt->cnt_all < digtable->fa_lowthresh) {
-		if ((digtable->backoff_val + 6) >
+		if ((digtable->back_val + 6) >
 			digtable->backoffval_range_max)
-			digtable->backoff_val =
+			digtable->back_val =
 				 digtable->backoffval_range_max;
 		else
-			digtable->backoff_val += 6;
+			digtable->back_val += 6;
 	}
 }
 
@@ -447,28 +445,28 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
 	static u8 initialized, force_write;
 	u8 initial_gain = 0;
 
-	if ((digtable->pre_sta_connectstate == digtable->cur_sta_connectstate) ||
-		(digtable->cur_sta_connectstate == DIG_STA_BEFORE_CONNECT)) {
-		if (digtable->cur_sta_connectstate == DIG_STA_BEFORE_CONNECT) {
+	if ((digtable->pre_sta_cstate == digtable->cur_sta_cstate) ||
+	    (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT)) {
+		if (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT) {
 			if (rtlpriv->psc.rfpwr_state != ERFON)
 				return;
 
 			if (digtable->backoff_enable_flag)
 				rtl92s_backoff_enable_flag(hw);
 			else
-				digtable->backoff_val = DM_DIG_BACKOFF;
+				digtable->back_val = DM_DIG_BACKOFF;
 
-			if ((digtable->rssi_val + 10 - digtable->backoff_val) >
+			if ((digtable->rssi_val + 10 - digtable->back_val) >
 				digtable->rx_gain_range_max)
 				digtable->cur_igvalue =
 						digtable->rx_gain_range_max;
-			else if ((digtable->rssi_val + 10 - digtable->backoff_val)
+			else if ((digtable->rssi_val + 10 - digtable->back_val)
 				 < digtable->rx_gain_range_min)
 				digtable->cur_igvalue =
 						digtable->rx_gain_range_min;
 			else
 				digtable->cur_igvalue = digtable->rssi_val + 10 -
-						digtable->backoff_val;
+						digtable->back_val;
 
 			if (falsealm_cnt->cnt_all > 10000)
 				digtable->cur_igvalue =
@@ -490,7 +488,7 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
 		digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
 		rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_ENABLE);
 
-		digtable->backoff_val = DM_DIG_BACKOFF;
+		digtable->back_val = DM_DIG_BACKOFF;
 		digtable->cur_igvalue = rtlpriv->phy.default_initialgain[0];
 		digtable->pre_igvalue = 0;
 		return;
@@ -528,14 +526,14 @@ static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw)
 	/* Decide the current status and if modify initial gain or not */
 	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED ||
 	    rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC)
-		digtable->cur_sta_connectstate = DIG_STA_CONNECT;
+		digtable->cur_sta_cstate = DIG_STA_CONNECT;
 	else
-		digtable->cur_sta_connectstate = DIG_STA_DISCONNECT;
+		digtable->cur_sta_cstate = DIG_STA_DISCONNECT;
 
-	digtable->rssi_val = rtlpriv->dm.undecorated_smoothed_pwdb;
+	digtable->rssi_val = rtlpriv->dm.undec_sm_pwdb;
 
 	/* Change dig mode to rssi */
-	if (digtable->cur_sta_connectstate != DIG_STA_DISCONNECT) {
+	if (digtable->cur_sta_cstate != DIG_STA_DISCONNECT) {
 		if (digtable->dig_twoport_algorithm ==
 		    DIG_TWO_PORT_ALGO_FALSE_ALARM) {
 			digtable->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI;
@@ -546,7 +544,7 @@ static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw)
 	_rtl92s_dm_false_alarm_counter_statistics(hw);
 	_rtl92s_dm_initial_gain_sta_beforeconnect(hw);
 
-	digtable->pre_sta_connectstate = digtable->cur_sta_connectstate;
+	digtable->pre_sta_cstate = digtable->cur_sta_cstate;
 }
 
 static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw)
@@ -573,7 +571,7 @@ static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	long undecorated_smoothed_pwdb;
+	long undec_sm_pwdb;
 	long txpwr_threshold_lv1, txpwr_threshold_lv2;
 
 	/* 2T2R TP issue */
@@ -587,7 +585,7 @@ static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw)
 	}
 
 	if ((mac->link_state < MAC80211_LINKED) &&
-	    (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
+	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
 			 "Not connected to any\n");
 
@@ -599,25 +597,22 @@ static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw)
 
 	if (mac->link_state >= MAC80211_LINKED) {
 		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
-			undecorated_smoothed_pwdb =
-			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+			undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
 			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 				 "AP Client PWDB = 0x%lx\n",
-				 undecorated_smoothed_pwdb);
+				 undec_sm_pwdb);
 		} else {
-			undecorated_smoothed_pwdb =
-			    rtlpriv->dm.undecorated_smoothed_pwdb;
+			undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
 			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 				 "STA Default Port PWDB = 0x%lx\n",
-				 undecorated_smoothed_pwdb);
+				 undec_sm_pwdb);
 		}
 	} else {
-		undecorated_smoothed_pwdb =
-		    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+		undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
 
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			 "AP Ext Port PWDB = 0x%lx\n",
-			 undecorated_smoothed_pwdb);
+			 undec_sm_pwdb);
 	}
 
 	txpwr_threshold_lv2 = TX_POWER_NEAR_FIELD_THRESH_LVL2;
@@ -625,12 +620,12 @@ static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw)
 
 	if (rtl_get_bbreg(hw, 0xc90, MASKBYTE0) == 1)
 		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
-	else if (undecorated_smoothed_pwdb >= txpwr_threshold_lv2)
+	else if (undec_sm_pwdb >= txpwr_threshold_lv2)
 		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL2;
-	else if ((undecorated_smoothed_pwdb < (txpwr_threshold_lv2 - 3)) &&
-		(undecorated_smoothed_pwdb >= txpwr_threshold_lv1))
+	else if ((undec_sm_pwdb < (txpwr_threshold_lv2 - 3)) &&
+		(undec_sm_pwdb >= txpwr_threshold_lv1))
 		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL1;
-	else if (undecorated_smoothed_pwdb < (txpwr_threshold_lv1 - 3))
+	else if (undec_sm_pwdb < (txpwr_threshold_lv1 - 3))
 		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
 
 	if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl))
@@ -665,10 +660,10 @@ static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw)
 	digtable->dig_state = DM_STA_DIG_MAX;
 	digtable->dig_highpwrstate = DM_STA_DIG_MAX;
 
-	digtable->cur_sta_connectstate = DIG_STA_DISCONNECT;
-	digtable->pre_sta_connectstate = DIG_STA_DISCONNECT;
-	digtable->cur_ap_connectstate = DIG_AP_DISCONNECT;
-	digtable->pre_ap_connectstate = DIG_AP_DISCONNECT;
+	digtable->cur_sta_cstate = DIG_STA_DISCONNECT;
+	digtable->pre_sta_cstate = DIG_STA_DISCONNECT;
+	digtable->cur_ap_cstate = DIG_AP_DISCONNECT;
+	digtable->pre_ap_cstate = DIG_AP_DISCONNECT;
 
 	digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
 	digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
@@ -681,7 +676,7 @@ static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw)
 
 	/* for dig debug rssi value */
 	digtable->rssi_val = 50;
-	digtable->backoff_val = DM_DIG_BACKOFF;
+	digtable->back_val = DM_DIG_BACKOFF;
 	digtable->rx_gain_range_max = DM_DIG_MAX;
 
 	digtable->rx_gain_range_min = DM_DIG_MIN;
@@ -709,7 +704,7 @@ void rtl92s_dm_init(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
 	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
-	rtlpriv->dm.undecorated_smoothed_pwdb = -1;
+	rtlpriv->dm.undec_sm_pwdb = -1;
 
 	_rtl92s_dm_init_dynamic_txpower(hw);
 	rtl92s_dm_init_edca_turbo(hw);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
index 4542e69..1d72779 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
@@ -1697,7 +1697,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
 			hwinfo[EEPROM_TXPOWERBASE + 6 + rf_path * 3 + i];
 
 			/* Read OFDM RF A & B Tx power for 2T */
-			rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][i]
+			rtlefuse->eprom_chnl_txpwr_ht40_2sdf[rf_path][i]
 				 = hwinfo[EEPROM_TXPOWERBASE + 12 +
 				   rf_path * 3 + i];
 		}
@@ -1722,7 +1722,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
 			RTPRINT(rtlpriv, FINIT, INIT_EEPROM,
 				"RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n",
 				rf_path, i,
-				rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif
+				rtlefuse->eprom_chnl_txpwr_ht40_2sdf
 				[rf_path][i]);
 
 	for (rf_path = 0; rf_path < 2; rf_path++) {
@@ -1748,7 +1748,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
 				rtlefuse->eeprom_chnlarea_txpwr_ht40_1s
 							[rf_path][index];
 			rtlefuse->txpwrlevel_ht40_2s[rf_path][i]  =
-				rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif
+				rtlefuse->eprom_chnl_txpwr_ht40_2sdf
 							[rf_path][index];
 		}
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
index b917a2a..6740497 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
@@ -139,17 +139,17 @@ static u32 _rtl92s_phy_rf_serial_read(struct ieee80211_hw *hw,
 						BIT(8));
 
 	if (rfpi_enable)
-		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi,
+		retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi,
 					 BLSSI_READBACK_DATA);
 	else
-		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback,
+		retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb,
 					 BLSSI_READBACK_DATA);
 
-	retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback,
+	retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb,
 				 BLSSI_READBACK_DATA);
 
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]=0x%x\n",
-		 rfpath, pphyreg->rflssi_readback, retvalue);
+		 rfpath, pphyreg->rf_rb, retvalue);
 
 	return retvalue;
 
@@ -696,7 +696,7 @@ static void _rtl92s_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw,
 	else
 		return;
 
-	rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][index] = data;
+	rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index] = data;
 	if (index == 5)
 		rtlphy->pwrgroup_cnt++;
 }
@@ -765,14 +765,10 @@ static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw)
 	rtlphy->phyreg_def[RF90_PATH_D].rfhssi_para2 = RFPGA0_XD_HSSIPARAMETER2;
 
 	/* RF switch Control */
-	rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control =
-						 RFPGA0_XAB_SWITCHCONTROL;
-	rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control =
-						 RFPGA0_XAB_SWITCHCONTROL;
-	rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control =
-						 RFPGA0_XCD_SWITCHCONTROL;
-	rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control =
-						 RFPGA0_XCD_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
 
 	/* AGC control 1  */
 	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1;
@@ -787,14 +783,10 @@ static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw)
 	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
 
 	/* RX AFE control 1  */
-	rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance =
-						 ROFDM0_XARXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance =
-						 ROFDM0_XBRXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance =
-						 ROFDM0_XCRXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance =
-						 ROFDM0_XDRXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE;
 
 	/* RX AFE control 1   */
 	rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE;
@@ -803,14 +795,10 @@ static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw)
 	rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
 
 	/* Tx AFE control 1  */
-	rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance =
-						 ROFDM0_XATXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance =
-						 ROFDM0_XBTXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance =
-						 ROFDM0_XCTXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance =
-						 ROFDM0_XDTXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE;
 
 	/* Tx AFE control 2  */
 	rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE;
@@ -819,20 +807,14 @@ static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw)
 	rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE;
 
 	/* Tranceiver LSSI Readback */
-	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback =
-			 RFPGA0_XA_LSSIREADBACK;
-	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback =
-			 RFPGA0_XB_LSSIREADBACK;
-	rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback =
-			 RFPGA0_XC_LSSIREADBACK;
-	rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback =
-			 RFPGA0_XD_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK;
 
 	/* Tranceiver LSSI Readback PI mode  */
-	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi =
-			 TRANSCEIVERA_HSPI_READBACK;
-	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi =
-			 TRANSCEIVERB_HSPI_READBACK;
+	rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVERA_HSPI_READBACK;
+	rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVERB_HSPI_READBACK;
 }
 
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
index 08c2f56..5061f1d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c
@@ -192,8 +192,7 @@ static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw,
 		 * defined by Realtek for large power */
 		chnlgroup = 0;
 
-		writeval = rtlphy->mcs_txpwrlevel_origoffset
-				[chnlgroup][index] +
+		writeval = rtlphy->mcs_offset[chnlgroup][index] +
 				((index < 2) ? pwrbase0 : pwrbase1);
 
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
@@ -223,8 +222,7 @@ static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw,
 					chnlgroup++;
 			}
 
-			writeval = rtlphy->mcs_txpwrlevel_origoffset
-					[chnlgroup][index]
+			writeval = rtlphy->mcs_offset[chnlgroup][index]
 					+ ((index < 2) ?
 					pwrbase0 : pwrbase1);
 
@@ -257,8 +255,7 @@ static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw,
 		}
 
 		for (i = 0; i < 4; i++) {
-			pwrdiff_limit[i] =
-				(u8)((rtlphy->mcs_txpwrlevel_origoffset
+			pwrdiff_limit[i] = (u8)((rtlphy->mcs_offset
 				[chnlgroup][index] & (0x7f << (i * 8)))
 				>> (i * 8));
 
@@ -296,7 +293,7 @@ static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw,
 		break;
 	default:
 		chnlgroup = 0;
-		writeval = rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index] +
+		writeval = rtlphy->mcs_offset[chnlgroup][index] +
 				((index < 2) ? pwrbase0 : pwrbase1);
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			 "RTK better performance, writeval = 0x%x\n", writeval);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index e3cf4c0..0e9f6eb 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -129,8 +129,8 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
 	pstats->packet_matchbssid = packet_match_bssid;
 	pstats->packet_toself = packet_toself;
 	pstats->packet_beacon = packet_beacon;
-	pstats->rx_mimo_signalquality[0] = -1;
-	pstats->rx_mimo_signalquality[1] = -1;
+	pstats->rx_mimo_sig_qual[0] = -1;
+	pstats->rx_mimo_sig_qual[1] = -1;
 
 	if (is_cck) {
 		u8 report, cck_highpwr;
@@ -216,8 +216,8 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
 			}
 
 			pstats->signalquality = sq;
-			pstats->rx_mimo_signalquality[0] = sq;
-			pstats->rx_mimo_signalquality[1] = -1;
+			pstats->rx_mimo_sig_qual[0] = sq;
+			pstats->rx_mimo_sig_qual[1] = -1;
 		}
 	} else {
 		rtlpriv->dm.rfpath_rxenable[0] =
@@ -256,8 +256,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
 				if (i == 0)
 					pstats->signalquality = (u8)(evm &
 								 0xff);
-				pstats->rx_mimo_signalquality[i] =
-							 (u8) (evm & 0xff);
+				pstats->rx_mimo_sig_qual[i] = (u8) (evm & 0xff);
 			}
 		}
 	}
@@ -366,7 +365,7 @@ static void _rtl92se_process_pwdb(struct ieee80211_hw *hw,
 		return;
 	} else {
 		undec_sm_pwdb =
-		    rtlpriv->dm.undecorated_smoothed_pwdb;
+		    rtlpriv->dm.undec_sm_pwdb;
 	}
 
 	if (pstats->packet_toself || pstats->packet_beacon) {
@@ -386,7 +385,7 @@ static void _rtl92se_process_pwdb(struct ieee80211_hw *hw,
 			      (RX_SMOOTH_FACTOR);
 		}
 
-		rtlpriv->dm.undecorated_smoothed_pwdb = undec_sm_pwdb;
+		rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
 		_rtl92se_update_rxsignalstatistics(hw, pstats);
 	}
 }
@@ -398,16 +397,16 @@ static void rtl_92s_process_streams(struct ieee80211_hw *hw,
 	u32 stream;
 
 	for (stream = 0; stream < 2; stream++) {
-		if (pstats->rx_mimo_signalquality[stream] != -1) {
+		if (pstats->rx_mimo_sig_qual[stream] != -1) {
 			if (rtlpriv->stats.rx_evm_percentage[stream] == 0) {
 				rtlpriv->stats.rx_evm_percentage[stream] =
-				    pstats->rx_mimo_signalquality[stream];
+				    pstats->rx_mimo_sig_qual[stream];
 			}
 
 			rtlpriv->stats.rx_evm_percentage[stream] =
 			    ((rtlpriv->stats.rx_evm_percentage[stream] *
 					(RX_SMOOTH_FACTOR - 1)) +
-			     (pstats->rx_mimo_signalquality[stream] *
+			     (pstats->rx_mimo_sig_qual[stream] *
 					1)) / (RX_SMOOTH_FACTOR);
 		}
 	}
@@ -554,7 +553,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
 	if (stats->is_ht)
 		rx_status->flag |= RX_FLAG_HT;
 
-	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+	rx_status->flag |= RX_FLAG_MACTIME_START;
 
 	/* hw will set stats->decrypted true, if it finds the
 	 * frame is open data frame or mgmt frame,
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile b/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile
new file mode 100644
index 0000000..4ed731f
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile
@@ -0,0 +1,22 @@
+obj-m := rtl8723ae.o
+
+
+rtl8723ae-objs :=		\
+		dm.o		\
+		fw.o		\
+		hal_btc.o	\
+		hal_bt_coexist.o\
+		hw.o		\
+		led.o		\
+		phy.o		\
+		pwrseq.o	\
+		pwrseqcmd.o	\
+		rf.o		\
+		sw.o		\
+		table.o		\
+		trx.o		\
+
+
+obj-$(CONFIG_RTL8723AE) += rtl8723ae.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/btc.h b/drivers/net/wireless/rtlwifi/rtl8723ae/btc.h
new file mode 100644
index 0000000..417afee
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/btc.h
@@ -0,0 +1,41 @@
+/******************************************************************************
+ **
+ ** Copyright(c) 2009-2012  Realtek Corporation.
+ **
+ ** 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
+ **
+ ** The full GNU General Public License is included in this distribution in the
+ ** file called LICENSE.
+ **
+ ** Contact Information:
+ ** wlanfae <wlanfae@realtek.com>
+ ** Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ ** Hsinchu 300, Taiwan.
+ ** Larry Finger <Larry.Finger@lwfinger.net>
+ **
+ *****************************************************************************
+ */
+
+#ifndef __RTL8723E_BTC_H__
+#define __RTL8723E_BTC_H__
+
+#include "../wifi.h"
+#include "hal_bt_coexist.h"
+
+struct bt_coexist_c2h_info {
+	u8 no_parse_c2h;
+	u8 has_c2h;
+};
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/def.h b/drivers/net/wireless/rtlwifi/rtl8723ae/def.h
new file mode 100644
index 0000000..8c11035
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/def.h
@@ -0,0 +1,163 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ****************************************************************************
+ */
+
+#ifndef __RTL8723E_DEF_H__
+#define __RTL8723E_DEF_H__
+
+#define HAL_PRIME_CHNL_OFFSET_LOWER			1
+
+#define RX_MPDU_QUEUE					0
+
+#define CHIP_8723			BIT(0)
+#define NORMAL_CHIP			BIT(3)
+#define RF_TYPE_1T2R			BIT(4)
+#define RF_TYPE_2T2R			BIT(5)
+#define CHIP_VENDOR_UMC			BIT(7)
+#define B_CUT_VERSION			BIT(12)
+#define C_CUT_VERSION			BIT(13)
+#define D_CUT_VERSION			((BIT(12)|BIT(13)))
+#define E_CUT_VERSION			BIT(14)
+#define	RF_RL_ID			(BIT(31)|BIT(30)|BIT(29)|BIT(28))
+
+enum version_8723e {
+	VERSION_TEST_UMC_CHIP_8723 = 0x0081,
+	VERSION_NORMAL_UMC_CHIP_8723_1T1R_A_CUT = 0x0089,
+	VERSION_NORMAL_UMC_CHIP_8723_1T1R_B_CUT = 0x1089,
+};
+
+/* MASK */
+#define IC_TYPE_MASK			(BIT(0)|BIT(1)|BIT(2))
+#define CHIP_TYPE_MASK			BIT(3)
+#define RF_TYPE_MASK			(BIT(4)|BIT(5)|BIT(6))
+#define MANUFACTUER_MASK		BIT(7)
+#define ROM_VERSION_MASK		(BIT(11)|BIT(10)|BIT(9)|BIT(8))
+#define CUT_VERSION_MASK		(BIT(15)|BIT(14)|BIT(13)|BIT(12))
+
+/* Get element */
+#define GET_CVID_IC_TYPE(version)	((version) & IC_TYPE_MASK)
+#define GET_CVID_MANUFACTUER(version)	((version) & MANUFACTUER_MASK)
+#define GET_CVID_CUT_VERSION(version)	((version) & CUT_VERSION_MASK)
+
+#define IS_81XXC(version)		((GET_CVID_IC_TYPE(version) == 0) ?\
+					true : false)
+#define IS_8723_SERIES(version)						\
+		((GET_CVID_IC_TYPE(version) == CHIP_8723) ? true : false)
+#define IS_CHIP_VENDOR_UMC(version)					\
+		((GET_CVID_MANUFACTUER(version)) ? true : false)
+
+#define IS_VENDOR_UMC_A_CUT(version)	((IS_CHIP_VENDOR_UMC(version)) ? \
+		((GET_CVID_CUT_VERSION(version)) ? false : true) : false)
+#define IS_VENDOR_8723_A_CUT(version)	((IS_8723_SERIES(version)) ?	\
+		((GET_CVID_CUT_VERSION(version)) ? false : true) : false)
+#define IS_81xxC_VENDOR_UMC_B_CUT(version)	((IS_CHIP_VENDOR_UMC(version)) \
+		? ((GET_CVID_CUT_VERSION(version) == B_CUT_VERSION) ? \
+		true : false) : false)
+
+enum rf_optype {
+	RF_OP_BY_SW_3WIRE = 0,
+	RF_OP_BY_FW,
+	RF_OP_MAX
+};
+
+enum rf_power_state {
+	RF_ON,
+	RF_OFF,
+	RF_SLEEP,
+	RF_SHUT_DOWN,
+};
+
+enum power_save_mode {
+	POWER_SAVE_MODE_ACTIVE,
+	POWER_SAVE_MODE_SAVE,
+};
+
+enum power_polocy_config {
+	POWERCFG_MAX_POWER_SAVINGS,
+	POWERCFG_GLOBAL_POWER_SAVINGS,
+	POWERCFG_LOCAL_POWER_SAVINGS,
+	POWERCFG_LENOVO,
+};
+
+enum interface_select_pci {
+	INTF_SEL1_MINICARD = 0,
+	INTF_SEL0_PCIE = 1,
+	INTF_SEL2_RSV = 2,
+	INTF_SEL3_RSV = 3,
+};
+
+enum hal_fw_c2h_cmd_id {
+	HAL_FW_C2H_CMD_Read_MACREG = 0,
+	HAL_FW_C2H_CMD_Read_BBREG = 1,
+	HAL_FW_C2H_CMD_Read_RFREG = 2,
+	HAL_FW_C2H_CMD_Read_EEPROM = 3,
+	HAL_FW_C2H_CMD_Read_EFUSE = 4,
+	HAL_FW_C2H_CMD_Read_CAM = 5,
+	HAL_FW_C2H_CMD_Get_BasicRate = 6,
+	HAL_FW_C2H_CMD_Get_DataRate = 7,
+	HAL_FW_C2H_CMD_Survey = 8,
+	HAL_FW_C2H_CMD_SurveyDone = 9,
+	HAL_FW_C2H_CMD_JoinBss = 10,
+	HAL_FW_C2H_CMD_AddSTA = 11,
+	HAL_FW_C2H_CMD_DelSTA = 12,
+	HAL_FW_C2H_CMD_AtimDone = 13,
+	HAL_FW_C2H_CMD_TX_Report = 14,
+	HAL_FW_C2H_CMD_CCX_Report = 15,
+	HAL_FW_C2H_CMD_DTM_Report = 16,
+	HAL_FW_C2H_CMD_TX_Rate_Statistics = 17,
+	HAL_FW_C2H_CMD_C2HLBK = 18,
+	HAL_FW_C2H_CMD_C2HDBG = 19,
+	HAL_FW_C2H_CMD_C2HFEEDBACK = 20,
+	HAL_FW_C2H_CMD_MAX
+};
+
+enum rtl_desc_qsel {
+	QSLT_BK = 0x2,
+	QSLT_BE = 0x0,
+	QSLT_VI = 0x5,
+	QSLT_VO = 0x7,
+	QSLT_BEACON = 0x10,
+	QSLT_HIGH = 0x11,
+	QSLT_MGNT = 0x12,
+	QSLT_CMD = 0x13,
+};
+
+struct phy_sts_cck_8723e_t {
+	u8 adc_pwdb_X[4];
+	u8 sq_rpt;
+	u8 cck_agc_rpt;
+};
+
+struct h2c_cmd_8723e {
+	u8 element_id;
+	u32 cmd_len;
+	u8 *p_cmdbuffer;
+};
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c
new file mode 100644
index 0000000..12e2a3c
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c
@@ -0,0 +1,920 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ****************************************************************************
+ */
+
+#include "../wifi.h"
+#include "../base.h"
+#include "../pci.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+#include "fw.h"
+#include "hal_btc.h"
+
+static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
+	0x7f8001fe,
+	0x788001e2,
+	0x71c001c7,
+	0x6b8001ae,
+	0x65400195,
+	0x5fc0017f,
+	0x5a400169,
+	0x55400155,
+	0x50800142,
+	0x4c000130,
+	0x47c0011f,
+	0x43c0010f,
+	0x40000100,
+	0x3c8000f2,
+	0x390000e4,
+	0x35c000d7,
+	0x32c000cb,
+	0x300000c0,
+	0x2d4000b5,
+	0x2ac000ab,
+	0x288000a2,
+	0x26000098,
+	0x24000090,
+	0x22000088,
+	0x20000080,
+	0x1e400079,
+	0x1c800072,
+	0x1b00006c,
+	0x19800066,
+	0x18000060,
+	0x16c0005b,
+	0x15800056,
+	0x14400051,
+	0x1300004c,
+	0x12000048,
+	0x11000044,
+	0x10000040,
+};
+
+static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
+	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},
+	{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},
+	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},
+	{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},
+	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},
+	{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},
+	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},
+	{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},
+	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},
+	{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},
+	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},
+	{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},
+	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},
+	{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},
+	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},
+	{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},
+	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},
+	{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},
+	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},
+	{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
+	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
+	{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},
+	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},
+	{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},
+	{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},
+	{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},
+	{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},
+	{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},
+	{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},
+	{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},
+	{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},
+	{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},
+	{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}
+};
+
+static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
+	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},
+	{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},
+	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},
+	{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},
+	{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},
+	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},
+	{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},
+	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},
+	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},
+	{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
+	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
+	{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
+	{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
+	{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
+	{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
+	{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
+	{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}
+};
+
+static void rtl8723ae_dm_diginit(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+
+	dm_digtable->dig_enable_flag = true;
+	dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
+	dm_digtable->cur_igvalue = 0x20;
+	dm_digtable->pre_igvalue = 0x0;
+	dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;
+	dm_digtable->presta_cstate = DIG_STA_DISCONNECT;
+	dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT;
+	dm_digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
+	dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
+	dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
+	dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
+	dm_digtable->rx_gain_range_max = DM_DIG_MAX;
+	dm_digtable->rx_gain_range_min = DM_DIG_MIN;
+	dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
+	dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX;
+	dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN;
+	dm_digtable->pre_cck_pd_state = CCK_PD_STAGE_MAX;
+	dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX;
+}
+
+static u8 rtl_init_gain_min_pwdb(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+	long rssi_val_min = 0;
+
+	if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) &&
+	    (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) {
+		if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0)
+			rssi_val_min =
+			    (rtlpriv->dm.entry_min_undec_sm_pwdb >
+			     rtlpriv->dm.undec_sm_pwdb) ?
+			    rtlpriv->dm.undec_sm_pwdb :
+			    rtlpriv->dm.entry_min_undec_sm_pwdb;
+		else
+			rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
+	} else if (dm_digtable->cursta_cstate == DIG_STA_CONNECT ||
+		   dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT) {
+		rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
+	} else if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
+		rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;
+	}
+
+	return (u8) rssi_val_min;
+}
+
+static void rtl8723ae_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
+{
+	u32 ret_value;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
+
+	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
+	falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
+
+	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
+	falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
+	falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
+
+	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
+	falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
+	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
+	    falsealm_cnt->cnt_rate_illegal +
+	    falsealm_cnt->cnt_crc8_fail + falsealm_cnt->cnt_mcs_fail;
+
+	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
+	ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
+	falsealm_cnt->cnt_cck_fail = ret_value;
+
+	ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
+	falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
+	falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail +
+				 falsealm_cnt->cnt_rate_illegal +
+				 falsealm_cnt->cnt_crc8_fail +
+				 falsealm_cnt->cnt_mcs_fail +
+				 falsealm_cnt->cnt_cck_fail);
+
+	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
+	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
+	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
+	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2);
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 "cnt_parity_fail = %d, cnt_rate_illegal = %d, "
+		 "cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
+		 falsealm_cnt->cnt_parity_fail,
+		 falsealm_cnt->cnt_rate_illegal,
+		 falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail);
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
+		 falsealm_cnt->cnt_ofdm_fail,
+		 falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all);
+}
+
+static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+	u8 value_igi = dm_digtable->cur_igvalue;
+
+	if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
+		value_igi--;
+	else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)
+		value_igi += 0;
+	else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2)
+		value_igi++;
+	else
+		value_igi += 2;
+
+	value_igi = clamp(value_igi, (u8)DM_DIG_FA_LOWER, (u8)DM_DIG_FA_UPPER);
+	if (rtlpriv->falsealm_cnt.cnt_all > 10000)
+		value_igi = 0x32;
+
+	dm_digtable->cur_igvalue = value_igi;
+	rtl8723ae_dm_write_dig(hw);
+}
+
+static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct dig_t *dgtbl = &rtlpriv->dm_digtable;
+
+	if (rtlpriv->falsealm_cnt.cnt_all > dgtbl->fa_highthresh) {
+		if ((dgtbl->back_val - 2) < dgtbl->back_range_min)
+			dgtbl->back_val = dgtbl->back_range_min;
+		else
+			dgtbl->back_val -= 2;
+	} else if (rtlpriv->falsealm_cnt.cnt_all < dgtbl->fa_lowthresh) {
+		if ((dgtbl->back_val + 2) > dgtbl->back_range_max)
+			dgtbl->back_val = dgtbl->back_range_max;
+		else
+			dgtbl->back_val += 2;
+	}
+
+	if ((dgtbl->rssi_val_min + 10 - dgtbl->back_val) >
+	    dgtbl->rx_gain_range_max)
+		dgtbl->cur_igvalue = dgtbl->rx_gain_range_max;
+	else if ((dgtbl->rssi_val_min + 10 -
+		  dgtbl->back_val) < dgtbl->rx_gain_range_min)
+		dgtbl->cur_igvalue = dgtbl->rx_gain_range_min;
+	else
+		dgtbl->cur_igvalue = dgtbl->rssi_val_min + 10 - dgtbl->back_val;
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 "rssi_val_min = %x back_val %x\n",
+		 dgtbl->rssi_val_min, dgtbl->back_val);
+
+	rtl8723ae_dm_write_dig(hw);
+}
+
+static void rtl8723ae_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+	long rssi_strength = rtlpriv->dm.entry_min_undec_sm_pwdb;
+	bool multi_sta = false;
+
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		multi_sta = true;
+
+	if ((!multi_sta) ||
+	    (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT)) {
+		rtlpriv->initialized = false;
+		dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
+		return;
+	} else if (!rtlpriv->initialized) {
+		rtlpriv->initialized = true;
+		dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
+		dm_digtable->cur_igvalue = 0x20;
+		rtl8723ae_dm_write_dig(hw);
+	}
+
+	if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
+		if ((rssi_strength < dm_digtable->rssi_lowthresh) &&
+		    (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) {
+
+			if (dm_digtable->dig_ext_port_stage ==
+			    DIG_EXT_PORT_STAGE_2) {
+				dm_digtable->cur_igvalue = 0x20;
+				rtl8723ae_dm_write_dig(hw);
+			}
+
+			dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_1;
+		} else if (rssi_strength > dm_digtable->rssi_highthresh) {
+			dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_2;
+			rtl92c_dm_ctrl_initgain_by_fa(hw);
+		}
+	} else if (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) {
+		dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
+		dm_digtable->cur_igvalue = 0x20;
+		rtl8723ae_dm_write_dig(hw);
+	}
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 "curmultista_cstate = %x dig_ext_port_stage %x\n",
+		 dm_digtable->curmultista_cstate,
+		 dm_digtable->dig_ext_port_stage);
+}
+
+static void rtl8723ae_dm_initial_gain_sta(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 "presta_cstate = %x, cursta_cstate = %x\n",
+		 dm_digtable->presta_cstate,
+		 dm_digtable->cursta_cstate);
+
+	if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate ||
+	    dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT ||
+	    dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
+
+		if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {
+			dm_digtable->rssi_val_min = rtl_init_gain_min_pwdb(hw);
+			rtl92c_dm_ctrl_initgain_by_rssi(hw);
+		}
+	} else {
+		dm_digtable->rssi_val_min = 0;
+		dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
+		dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
+		dm_digtable->cur_igvalue = 0x20;
+		dm_digtable->pre_igvalue = 0;
+		rtl8723ae_dm_write_dig(hw);
+	}
+}
+static void rtl8723ae_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+
+	if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
+		dm_digtable->rssi_val_min = rtl_init_gain_min_pwdb(hw);
+
+		if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LowRssi) {
+			if (dm_digtable->rssi_val_min <= 25)
+				dm_digtable->cur_cck_pd_state =
+				    CCK_PD_STAGE_LowRssi;
+			else
+				dm_digtable->cur_cck_pd_state =
+				    CCK_PD_STAGE_HighRssi;
+		} else {
+			if (dm_digtable->rssi_val_min <= 20)
+				dm_digtable->cur_cck_pd_state =
+				    CCK_PD_STAGE_LowRssi;
+			else
+				dm_digtable->cur_cck_pd_state =
+				    CCK_PD_STAGE_HighRssi;
+		}
+	} else {
+		dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX;
+	}
+
+	if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) {
+		if (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LowRssi) {
+			if (rtlpriv->falsealm_cnt.cnt_cck_fail > 800)
+				dm_digtable->cur_cck_fa_state =
+				    CCK_FA_STAGE_High;
+			else
+				dm_digtable->cur_cck_fa_state =
+							 CCK_FA_STAGE_Low;
+
+			if (dm_digtable->pre_cck_fa_state !=
+			    dm_digtable->cur_cck_fa_state) {
+				if (dm_digtable->cur_cck_fa_state ==
+				    CCK_FA_STAGE_Low)
+					rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
+						      0x83);
+				else
+					rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
+						      0xcd);
+
+				dm_digtable->pre_cck_fa_state =
+				    dm_digtable->cur_cck_fa_state;
+			}
+
+			rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x40);
+
+		} else {
+			rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
+			rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47);
+
+		}
+		dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state;
+	}
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 "CCKPDStage=%x\n", dm_digtable->cur_cck_pd_state);
+
+}
+
+static void rtl8723ae_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
+{
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+
+	if (mac->act_scanning == true)
+		return;
+
+	if (mac->link_state >= MAC80211_LINKED)
+		dm_digtable->cursta_cstate = DIG_STA_CONNECT;
+	else
+		dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;
+
+	rtl8723ae_dm_initial_gain_sta(hw);
+	rtl8723ae_dm_initial_gain_multi_sta(hw);
+	rtl8723ae_dm_cck_packet_detection_thresh(hw);
+
+	dm_digtable->presta_cstate = dm_digtable->cursta_cstate;
+
+}
+
+static void rtl8723ae_dm_dig(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+
+	if (rtlpriv->dm.dm_initialgain_enable == false)
+		return;
+	if (dm_digtable->dig_enable_flag == false)
+		return;
+
+	rtl8723ae_dm_ctrl_initgain_by_twoport(hw);
+}
+
+static void rtl8723ae_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.dynamic_txpower_enable = false;
+
+	rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
+	rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+}
+
+static void rtl8723ae_dm_dynamic_txpower(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	long undec_sm_pwdb;
+
+	if (!rtlpriv->dm.dynamic_txpower_enable)
+		return;
+
+	if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+		return;
+	}
+
+	if ((mac->link_state < MAC80211_LINKED) &&
+	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
+			 "Not connected\n");
+
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+
+		rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
+		return;
+	}
+
+	if (mac->link_state >= MAC80211_LINKED) {
+		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+			undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+				 "AP Client PWDB = 0x%lx\n",
+				 undec_sm_pwdb);
+		} else {
+			undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+				 "STA Default Port PWDB = 0x%lx\n",
+				 undec_sm_pwdb);
+		}
+	} else {
+		undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
+
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 "AP Ext Port PWDB = 0x%lx\n",
+			  undec_sm_pwdb);
+	}
+
+	if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
+	} else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
+		   (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
+	} else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 "TXHIGHPWRLEVEL_NORMAL\n");
+	}
+
+	if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 "PHY_SetTxPowerLevel8192S() Channel = %d\n",
+			  rtlphy->current_channel);
+		rtl8723ae_phy_set_txpower_level(hw, rtlphy->current_channel);
+	}
+
+	rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
+}
+
+void rtl8723ae_dm_write_dig(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+		 "cur_igvalue = 0x%x, "
+		 "pre_igvalue = 0x%x, back_val = %d\n",
+		 dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
+		 dm_digtable->back_val);
+
+	if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) {
+		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
+			      dm_digtable->cur_igvalue);
+		rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
+			      dm_digtable->cur_igvalue);
+
+		dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;
+	}
+}
+
+static void rtl8723ae_dm_pwdmonitor(struct ieee80211_hw *hw)
+{
+}
+
+void rtl8723ae_dm_init_edca_turbo(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.current_turbo_edca = false;
+	rtlpriv->dm.is_any_nonbepkts = false;
+	rtlpriv->dm.is_cur_rdlstate = false;
+}
+
+static void rtl8723ae_dm_check_edca_turbo(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+
+	u64 cur_txok_cnt = 0;
+	u64 cur_rxok_cnt = 0;
+	u32 edca_be_ul = 0x5ea42b;
+	u32 edca_be_dl = 0x5ea42b;
+	bool bt_change_edca = false;
+
+	if ((mac->last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) ||
+	    (mac->last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) {
+		rtlpriv->dm.current_turbo_edca = false;
+		mac->last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
+		mac->last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl;
+	}
+
+	if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) {
+		edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
+		bt_change_edca = true;
+	}
+
+	if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) {
+		edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl;
+		bt_change_edca = true;
+	}
+
+	if (mac->link_state != MAC80211_LINKED) {
+		rtlpriv->dm.current_turbo_edca = false;
+		return;
+	}
+
+	if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) {
+		if (!(edca_be_ul & 0xffff0000))
+			edca_be_ul |= 0x005e0000;
+
+		if (!(edca_be_dl & 0xffff0000))
+			edca_be_dl |= 0x005e0000;
+	}
+
+	if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) &&
+	     (!rtlpriv->dm.disable_framebursting))) {
+
+		cur_txok_cnt = rtlpriv->stats.txbytesunicast -
+			       mac->last_txok_cnt;
+		cur_rxok_cnt = rtlpriv->stats.rxbytesunicast -
+			       mac->last_rxok_cnt;
+
+		if (cur_rxok_cnt > 4 * cur_txok_cnt) {
+			if (!rtlpriv->dm.is_cur_rdlstate ||
+			    !rtlpriv->dm.current_turbo_edca) {
+				rtl_write_dword(rtlpriv,
+						REG_EDCA_BE_PARAM,
+						edca_be_dl);
+				rtlpriv->dm.is_cur_rdlstate = true;
+			}
+		} else {
+			if (rtlpriv->dm.is_cur_rdlstate ||
+			    !rtlpriv->dm.current_turbo_edca) {
+				rtl_write_dword(rtlpriv,
+						REG_EDCA_BE_PARAM,
+						edca_be_ul);
+				rtlpriv->dm.is_cur_rdlstate = false;
+			}
+		}
+		rtlpriv->dm.current_turbo_edca = true;
+	} else {
+		if (rtlpriv->dm.current_turbo_edca) {
+			u8 tmp = AC0_BE;
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+						      HW_VAR_AC_PARAM,
+						      (u8 *) (&tmp));
+			rtlpriv->dm.current_turbo_edca = false;
+		}
+	}
+
+	rtlpriv->dm.is_any_nonbepkts = false;
+	mac->last_txok_cnt = rtlpriv->stats.txbytesunicast;
+	mac->last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
+}
+
+static void rtl8723ae_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.txpower_tracking = true;
+	rtlpriv->dm.txpower_trackinginit = false;
+
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+		 "pMgntInfo->txpower_tracking = %d\n",
+		 rtlpriv->dm.txpower_tracking);
+}
+
+void rtl8723ae_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rate_adaptive *p_ra = &(rtlpriv->ra);
+
+	p_ra->ratr_state = DM_RATR_STA_INIT;
+	p_ra->pre_ratr_state = DM_RATR_STA_INIT;
+
+	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
+		rtlpriv->dm.useramask = true;
+	else
+		rtlpriv->dm.useramask = false;
+}
+
+static void rtl8723ae_dm_init_dynamic_bpowersaving(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm_pstable.pre_ccastate = CCA_MAX;
+	rtlpriv->dm_pstable.cur_ccasate = CCA_MAX;
+	rtlpriv->dm_pstable.pre_rfstate = RF_MAX;
+	rtlpriv->dm_pstable.cur_rfstate = RF_MAX;
+	rtlpriv->dm_pstable.rssi_val_min = 0;
+}
+
+void rtl8723ae_dm_rf_saving(struct ieee80211_hw *hw, u8 force_in_normal)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
+
+	if (!rtlpriv->reg_init) {
+		rtlpriv->reg_874 = (rtl_get_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+				    MASKDWORD) & 0x1CC000) >> 14;
+
+		rtlpriv->reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1,
+				    MASKDWORD) & BIT(3)) >> 3;
+
+		rtlpriv->reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
+				    MASKDWORD) & 0xFF000000) >> 24;
+
+		rtlpriv->reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) &
+				   0xF000) >> 12;
+
+		rtlpriv->reg_init = true;
+	}
+
+	if (!force_in_normal) {
+		if (dm_pstable->rssi_val_min != 0) {
+			if (dm_pstable->pre_rfstate == RF_NORMAL) {
+				if (dm_pstable->rssi_val_min >= 30)
+					dm_pstable->cur_rfstate = RF_SAVE;
+				else
+					dm_pstable->cur_rfstate = RF_NORMAL;
+			} else {
+				if (dm_pstable->rssi_val_min <= 25)
+					dm_pstable->cur_rfstate = RF_NORMAL;
+				else
+					dm_pstable->cur_rfstate = RF_SAVE;
+			}
+		} else {
+			dm_pstable->cur_rfstate = RF_MAX;
+		}
+	} else {
+		dm_pstable->cur_rfstate = RF_NORMAL;
+	}
+
+	if (dm_pstable->pre_rfstate != dm_pstable->cur_rfstate) {
+		if (dm_pstable->cur_rfstate == RF_SAVE) {
+
+			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+				      BIT(5), 0x1);
+			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+				      0x1C0000, 0x2);
+			rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0);
+			rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
+				      0xFF000000, 0x63);
+			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+				      0xC000, 0x2);
+			rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3);
+			rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
+			rtl_set_bbreg(hw, 0x818, BIT(28), 0x1);
+		} else {
+			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+				      0x1CC000, rtlpriv->reg_874);
+			rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3),
+				      rtlpriv->reg_c70);
+			rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000,
+				      rtlpriv->reg_85c);
+			rtl_set_bbreg(hw, 0xa74, 0xF000, rtlpriv->reg_a74);
+			rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
+			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+				      BIT(5), 0x0);
+		}
+
+		dm_pstable->pre_rfstate = dm_pstable->cur_rfstate;
+	}
+}
+
+static void rtl8723ae_dm_dynamic_bpowersaving(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
+
+	if (((mac->link_state == MAC80211_NOLINK)) &&
+	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
+		dm_pstable->rssi_val_min = 0;
+		RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
+			 "Not connected to any\n");
+	}
+
+	if (mac->link_state == MAC80211_LINKED) {
+		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+			dm_pstable->rssi_val_min =
+			    rtlpriv->dm.entry_min_undec_sm_pwdb;
+			RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
+				 "AP Client PWDB = 0x%lx\n",
+				 dm_pstable->rssi_val_min);
+		} else {
+			dm_pstable->rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
+			RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
+				 "STA Default Port PWDB = 0x%lx\n",
+				 dm_pstable->rssi_val_min);
+		}
+	} else {
+		dm_pstable->rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;
+
+		RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
+			 "AP Ext Port PWDB = 0x%lx\n",
+			 dm_pstable->rssi_val_min);
+	}
+
+	rtl8723ae_dm_rf_saving(hw, false);
+}
+
+void rtl8723ae_dm_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
+	rtl8723ae_dm_diginit(hw);
+	rtl8723ae_dm_init_dynamic_txpower(hw);
+	rtl8723ae_dm_init_edca_turbo(hw);
+	rtl8723ae_dm_init_rate_adaptive_mask(hw);
+	rtl8723ae_dm_initialize_txpower_tracking(hw);
+	rtl8723ae_dm_init_dynamic_bpowersaving(hw);
+}
+
+void rtl8723ae_dm_watchdog(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	bool fw_current_inpsmode = false;
+	bool fw_ps_awake = true;
+	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
+				      (u8 *) (&fw_current_inpsmode));
+	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
+				      (u8 *) (&fw_ps_awake));
+
+	if ((ppsc->rfpwr_state == ERFON) &&
+	    ((!fw_current_inpsmode) && fw_ps_awake) &&
+	    (!ppsc->rfchange_inprogress)) {
+		rtl8723ae_dm_pwdmonitor(hw);
+		rtl8723ae_dm_dig(hw);
+		rtl8723ae_dm_false_alarm_counter_statistics(hw);
+		rtl8723ae_dm_dynamic_bpowersaving(hw);
+		rtl8723ae_dm_dynamic_txpower(hw);
+		/* rtl92c_dm_refresh_rate_adaptive_mask(hw); */
+		rtl8723ae_dm_bt_coexist(hw);
+		rtl8723ae_dm_check_edca_turbo(hw);
+	}
+	if (rtlpcipriv->bt_coexist.init_set)
+		rtl_write_byte(rtlpriv, 0x76e, 0xc);
+}
+
+static void rtl8723ae_dm_init_bt_coexist(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+
+	rtlpcipriv->bt_coexist.bt_rfreg_origin_1e
+		= rtl_get_rfreg(hw, (enum radio_path)0, RF_RCK1, 0xfffff);
+	rtlpcipriv->bt_coexist.bt_rfreg_origin_1f
+		= rtl_get_rfreg(hw, (enum radio_path)0, RF_RCK2, 0xf0);
+
+	rtlpcipriv->bt_coexist.cstate = 0;
+	rtlpcipriv->bt_coexist.previous_state = 0;
+	rtlpcipriv->bt_coexist.cstate_h = 0;
+	rtlpcipriv->bt_coexist.previous_state_h = 0;
+	rtlpcipriv->bt_coexist.lps_counter = 0;
+
+	/*  Enable counter statistics */
+	rtl_write_byte(rtlpriv, 0x76e, 0x4);
+	rtl_write_byte(rtlpriv, 0x778, 0x3);
+	rtl_write_byte(rtlpriv, 0x40, 0x20);
+
+	rtlpcipriv->bt_coexist.init_set = true;
+}
+
+void rtl8723ae_dm_bt_coexist(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	u8 tmp_byte = 0;
+	if (!rtlpcipriv->bt_coexist.bt_coexistence) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+			 "[DM]{BT], BT not exist!!\n");
+		return;
+	}
+
+	if (!rtlpcipriv->bt_coexist.init_set) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+			 "[DM][BT], rtl8723ae_dm_bt_coexist()\n");
+
+		rtl8723ae_dm_init_bt_coexist(hw);
+	}
+
+	tmp_byte = rtl_read_byte(rtlpriv, 0x40);
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
+		 "[DM][BT], 0x40 is 0x%x", tmp_byte);
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+		 "[DM][BT], bt_dm_coexist start");
+	rtl8723ae_dm_bt_coexist_8723(hw);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h
new file mode 100644
index 0000000..39d2461
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h
@@ -0,0 +1,149 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ****************************************************************************
+ */
+
+#ifndef	__RTL8723E_DM_H__
+#define __RTL8723E_DM_H__
+
+#define HAL_DM_HIPWR_DISABLE			BIT(1)
+
+#define OFDM_TABLE_SIZE				37
+#define CCK_TABLE_SIZE				33
+
+#define DM_DIG_THRESH_HIGH			40
+#define DM_DIG_THRESH_LOW			35
+
+#define DM_FALSEALARM_THRESH_LOW		400
+#define DM_FALSEALARM_THRESH_HIGH		1000
+
+#define DM_DIG_MAX				0x3e
+#define DM_DIG_MIN				0x1e
+
+#define DM_DIG_FA_UPPER				0x32
+#define DM_DIG_FA_LOWER				0x20
+#define DM_DIG_FA_TH0				0x20
+#define DM_DIG_FA_TH1				0x100
+#define DM_DIG_FA_TH2				0x200
+
+#define DM_DIG_BACKOFF_MAX			12
+#define DM_DIG_BACKOFF_MIN			-4
+#define DM_DIG_BACKOFF_DEFAULT			10
+
+#define DM_RATR_STA_INIT			0
+
+#define TXHIGHPWRLEVEL_NORMAL			0
+#define TXHIGHPWRLEVEL_LEVEL1			1
+#define TXHIGHPWRLEVEL_LEVEL2			2
+#define TXHIGHPWRLEVEL_BT1			3
+#define TXHIGHPWRLEVEL_BT2			4
+
+#define DM_TYPE_BYDRIVER			1
+
+#define TX_POWER_NEAR_FIELD_THRESH_LVL2		74
+#define TX_POWER_NEAR_FIELD_THRESH_LVL1		67
+
+struct swat_t {
+	u8 failure_cnt;
+	u8 try_flag;
+	u8 stop_trying;
+	long pre_rssi;
+	long trying_threshold;
+	u8 cur_antenna;
+	u8 pre_antenna;
+};
+
+enum tag_dynamic_init_gain_operation_type_definition {
+	DIG_TYPE_THRESH_HIGH = 0,
+	DIG_TYPE_THRESH_LOW = 1,
+	DIG_TYPE_BACKOFF = 2,
+	DIG_TYPE_RX_GAIN_MIN = 3,
+	DIG_TYPE_RX_GAIN_MAX = 4,
+	DIG_TYPE_ENABLE = 5,
+	DIG_TYPE_DISABLE = 6,
+	DIG_OP_TYPE_MAX
+};
+
+enum tag_cck_packet_detection_threshold_type_definition {
+	CCK_PD_STAGE_LowRssi = 0,
+	CCK_PD_STAGE_HighRssi = 1,
+	CCK_FA_STAGE_Low = 2,
+	CCK_FA_STAGE_High = 3,
+	CCK_PD_STAGE_MAX = 4,
+};
+
+enum dm_1r_cca_e {
+	CCA_1R = 0,
+	CCA_2R = 1,
+	CCA_MAX = 2,
+};
+
+enum dm_rf_e {
+	RF_SAVE = 0,
+	RF_NORMAL = 1,
+	RF_MAX = 2,
+};
+
+enum dm_sw_ant_switch_e {
+	ANS_ANTENNA_B = 1,
+	ANS_ANTENNA_A = 2,
+	ANS_ANTENNA_MAX = 3,
+};
+
+enum dm_dig_ext_port_alg_e {
+	DIG_EXT_PORT_STAGE_0 = 0,
+	DIG_EXT_PORT_STAGE_1 = 1,
+	DIG_EXT_PORT_STAGE_2 = 2,
+	DIG_EXT_PORT_STAGE_3 = 3,
+	DIG_EXT_PORT_STAGE_MAX = 4,
+};
+
+enum dm_dig_connect_e {
+	DIG_STA_DISCONNECT = 0,
+	DIG_STA_CONNECT = 1,
+	DIG_STA_BEFORE_CONNECT = 2,
+	DIG_MULTISTA_DISCONNECT = 3,
+	DIG_MULTISTA_CONNECT = 4,
+	DIG_CONNECT_MAX
+};
+
+#define GET_UNDECORATED_AVERAGE_RSSI(_priv)     \
+	((((struct rtl_priv *)(_priv))->mac80211.opmode ==	\
+	NL80211_IFTYPE_ADHOC) ?  \
+	(((struct rtl_priv *)(_priv))->dm.entry_min_undec_sm_pwdb) \
+	: (((struct rtl_priv *)(_priv))->dm.undec_sm_pwdb))
+
+void rtl8723ae_dm_init(struct ieee80211_hw *hw);
+void rtl8723ae_dm_watchdog(struct ieee80211_hw *hw);
+void rtl8723ae_dm_write_dig(struct ieee80211_hw *hw);
+void rtl8723ae_dm_init_edca_turbo(struct ieee80211_hw *hw);
+void rtl8723ae_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw);
+void rtl8723ae_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal);
+void rtl8723ae_dm_bt_coexist(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c
new file mode 100644
index 0000000..f55b176
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c
@@ -0,0 +1,745 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ****************************************************************************
+ */
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "fw.h"
+
+static void _rtl8723ae_enable_fw_download(struct ieee80211_hw *hw, bool enable)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 tmp;
+	if (enable) {
+		tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
+
+		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
+		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
+
+		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
+		rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
+	} else {
+		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
+		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
+
+		rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
+	}
+}
+
+static void _rtl8723ae_fw_block_write(struct ieee80211_hw *hw,
+				      const u8 *buffer, u32 size)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 blockSize = sizeof(u32);
+	u8 *bufferPtr = (u8 *) buffer;
+	u32 *pu4BytePtr = (u32 *) buffer;
+	u32 i, offset, blockCount, remainSize;
+
+	blockCount = size / blockSize;
+	remainSize = size % blockSize;
+
+	for (i = 0; i < blockCount; i++) {
+		offset = i * blockSize;
+		rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
+				*(pu4BytePtr + i));
+	}
+
+	if (remainSize) {
+		offset = blockCount * blockSize;
+		bufferPtr += offset;
+		for (i = 0; i < remainSize; i++) {
+			rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
+						 offset + i), *(bufferPtr + i));
+		}
+	}
+}
+
+static void _rtl8723ae_fw_page_write(struct ieee80211_hw *hw,
+				     u32 page, const u8 *buffer, u32 size)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 value8;
+	u8 u8page = (u8) (page & 0x07);
+
+	value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
+
+	rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
+	_rtl8723ae_fw_block_write(hw, buffer, size);
+}
+
+static void _rtl8723ae_write_fw(struct ieee80211_hw *hw,
+				enum version_8723e version, u8 *buffer,
+				u32 size)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 *bufferPtr = (u8 *) buffer;
+	u32 page_nums, remain_size;
+	u32 page, offset;
+
+	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);
+
+	page_nums = size / FW_8192C_PAGE_SIZE;
+	remain_size = size % FW_8192C_PAGE_SIZE;
+
+	if (page_nums > 6) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "Page numbers should not be greater then 6\n");
+	}
+
+	for (page = 0; page < page_nums; page++) {
+		offset = page * FW_8192C_PAGE_SIZE;
+		_rtl8723ae_fw_page_write(hw, page, (bufferPtr + offset),
+					 FW_8192C_PAGE_SIZE);
+	}
+
+	if (remain_size) {
+		offset = page_nums * FW_8192C_PAGE_SIZE;
+		page = page_nums;
+		_rtl8723ae_fw_page_write(hw, page, (bufferPtr + offset),
+					 remain_size);
+	}
+
+	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW write done.\n");
+}
+
+static int _rtl8723ae_fw_free_to_go(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int err = -EIO;
+	u32 counter = 0;
+	u32 value32;
+
+	do {
+		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+	} while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
+		 (!(value32 & FWDL_ChkSum_rpt)));
+
+	if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "chksum report faill ! REG_MCUFWDL:0x%08x .\n",
+			 value32);
+		goto exit;
+	}
+
+	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+		 "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32);
+
+	value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+	value32 |= MCUFWDL_RDY;
+	value32 &= ~WINTINI_RDY;
+	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
+
+	counter = 0;
+
+	do {
+		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+		if (value32 & WINTINI_RDY) {
+			RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+				 "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n",
+				 value32);
+			err = 0;
+			goto exit;
+		}
+
+		mdelay(FW_8192C_POLLING_DELAY);
+
+	} while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
+
+	RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+		 "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32);
+
+exit:
+	return err;
+}
+
+int rtl8723ae_download_fw(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl8723ae_firmware_header *pfwheader;
+	u8 *pfwdata;
+	u32 fwsize;
+	int err;
+	enum version_8723e version = rtlhal->version;
+
+	if (!rtlhal->pfirmware)
+		return 1;
+
+	pfwheader = (struct rtl8723ae_firmware_header *)rtlhal->pfirmware;
+	pfwdata = (u8 *) rtlhal->pfirmware;
+	fwsize = rtlhal->fwsize;
+
+	if (IS_FW_HEADER_EXIST(pfwheader)) {
+		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+			 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
+			 pfwheader->version, pfwheader->signature,
+			 (int)sizeof(struct rtl8723ae_firmware_header));
+
+		pfwdata = pfwdata + sizeof(struct rtl8723ae_firmware_header);
+		fwsize = fwsize - sizeof(struct rtl8723ae_firmware_header);
+	}
+
+	if (rtl_read_byte(rtlpriv, REG_MCUFWDL)&BIT(7)) {
+		rtl8723ae_firmware_selfreset(hw);
+		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
+	}
+	_rtl8723ae_enable_fw_download(hw, true);
+	_rtl8723ae_write_fw(hw, version, pfwdata, fwsize);
+	_rtl8723ae_enable_fw_download(hw, false);
+
+	err = _rtl8723ae_fw_free_to_go(hw);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "Firmware is not ready to run!\n");
+	} else {
+		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+			 "Firmware is ready to run!\n");
+	}
+	return 0;
+}
+
+static bool rtl8723ae_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 val_hmetfr, val_mcutst_1;
+	bool result = false;
+
+	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
+	val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
+
+	if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
+		result = true;
+	return result;
+}
+
+static void _rtl8723ae_fill_h2c_command(struct ieee80211_hw *hw,
+					u8 element_id, u32 cmd_len,
+					u8 *p_cmdbuffer)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 boxnum;
+	u16 box_reg = 0, box_extreg = 0;
+	u8 u1tmp;
+	bool isfw_rd = false;
+	bool bwrite_sucess = false;
+	u8 wait_h2c_limmit = 100;
+	u8 wait_writeh2c_limmit = 100;
+	u8 boxcontent[4], boxextcontent[2];
+	u32 h2c_waitcounter = 0;
+	unsigned long flag;
+	u8 idx;
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
+
+	while (true) {
+		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+		if (rtlhal->h2c_setinprogress) {
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+				 "H2C set in progress! Wait to set..element_id(%d).\n",
+				 element_id);
+
+			while (rtlhal->h2c_setinprogress) {
+				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
+						       flag);
+				h2c_waitcounter++;
+				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+					 "Wait 100 us (%d times)...\n",
+					 h2c_waitcounter);
+				udelay(100);
+
+				if (h2c_waitcounter > 1000)
+					return;
+				spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
+						  flag);
+			}
+			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+		} else {
+			rtlhal->h2c_setinprogress = true;
+			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+			break;
+		}
+	}
+
+	while (!bwrite_sucess) {
+		wait_writeh2c_limmit--;
+		if (wait_writeh2c_limmit == 0) {
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 "Write H2C fail because no trigger "
+				 "for FW INT!\n");
+			break;
+		}
+
+		boxnum = rtlhal->last_hmeboxnum;
+		switch (boxnum) {
+		case 0:
+			box_reg = REG_HMEBOX_0;
+			box_extreg = REG_HMEBOX_EXT_0;
+			break;
+		case 1:
+			box_reg = REG_HMEBOX_1;
+			box_extreg = REG_HMEBOX_EXT_1;
+			break;
+		case 2:
+			box_reg = REG_HMEBOX_2;
+			box_extreg = REG_HMEBOX_EXT_2;
+			break;
+		case 3:
+			box_reg = REG_HMEBOX_3;
+			box_extreg = REG_HMEBOX_EXT_3;
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 "switch case not processed\n");
+			break;
+		}
+
+		isfw_rd = rtl8723ae_check_fw_read_last_h2c(hw, boxnum);
+		while (!isfw_rd) {
+
+			wait_h2c_limmit--;
+			if (wait_h2c_limmit == 0) {
+				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+					 "Wating too long for FW read clear HMEBox(%d)!\n",
+					 boxnum);
+				break;
+			}
+
+			udelay(10);
+
+			isfw_rd = rtl8723ae_check_fw_read_last_h2c(hw, boxnum);
+			u1tmp = rtl_read_byte(rtlpriv, 0x1BF);
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+				 "Wating for FW read clear HMEBox(%d)!!! "
+				 "0x1BF = %2x\n", boxnum, u1tmp);
+		}
+
+		if (!isfw_rd) {
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+				 "Write H2C register BOX[%d] fail!!!!! "
+				 "Fw do not read.\n", boxnum);
+			break;
+		}
+
+		memset(boxcontent, 0, sizeof(boxcontent));
+		memset(boxextcontent, 0, sizeof(boxextcontent));
+		boxcontent[0] = element_id;
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+			 "Write element_id box_reg(%4x) = %2x\n",
+			  box_reg, element_id);
+
+		switch (cmd_len) {
+		case 1:
+			boxcontent[0] &= ~(BIT(7));
+			memcpy((u8 *) (boxcontent) + 1,
+			       p_cmdbuffer, 1);
+
+			for (idx = 0; idx < 4; idx++) {
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			}
+			break;
+		case 2:
+			boxcontent[0] &= ~(BIT(7));
+			memcpy((u8 *) (boxcontent) + 1,
+			       p_cmdbuffer, 2);
+
+			for (idx = 0; idx < 4; idx++) {
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			}
+			break;
+		case 3:
+			boxcontent[0] &= ~(BIT(7));
+			memcpy((u8 *) (boxcontent) + 1,
+			       p_cmdbuffer, 3);
+
+			for (idx = 0; idx < 4; idx++) {
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			}
+			break;
+		case 4:
+			boxcontent[0] |= (BIT(7));
+			memcpy((u8 *) (boxextcontent),
+			       p_cmdbuffer, 2);
+			memcpy((u8 *) (boxcontent) + 1,
+			       p_cmdbuffer + 2, 2);
+
+			for (idx = 0; idx < 2; idx++) {
+				rtl_write_byte(rtlpriv, box_extreg + idx,
+					       boxextcontent[idx]);
+			}
+
+			for (idx = 0; idx < 4; idx++) {
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			}
+			break;
+		case 5:
+			boxcontent[0] |= (BIT(7));
+			memcpy((u8 *) (boxextcontent),
+			       p_cmdbuffer, 2);
+			memcpy((u8 *) (boxcontent) + 1,
+			       p_cmdbuffer + 2, 3);
+
+			for (idx = 0; idx < 2; idx++) {
+				rtl_write_byte(rtlpriv, box_extreg + idx,
+					       boxextcontent[idx]);
+			}
+
+			for (idx = 0; idx < 4; idx++) {
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			}
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 "switch case not process\n");
+			break;
+		}
+
+		bwrite_sucess = true;
+
+		rtlhal->last_hmeboxnum = boxnum + 1;
+		if (rtlhal->last_hmeboxnum == 4)
+			rtlhal->last_hmeboxnum = 0;
+
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+			 "pHalData->last_hmeboxnum  = %d\n",
+			 rtlhal->last_hmeboxnum);
+	}
+
+	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+	rtlhal->h2c_setinprogress = false;
+	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
+}
+
+void rtl8723ae_fill_h2c_cmd(struct ieee80211_hw *hw,
+			    u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+	if (rtlhal->fw_ready == false) {
+		RT_ASSERT(false,
+			 "return H2C cmd because of Fw download fail!!!\n");
+		return;
+	}
+
+	_rtl8723ae_fill_h2c_command(hw, element_id, cmd_len, p_cmdbuffer);
+	return;
+}
+
+void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw)
+{
+	u8 u1tmp;
+	u8 delay = 100;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
+	u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+
+	while (u1tmp & BIT(2)) {
+		delay--;
+		if (delay == 0)
+			break;
+		udelay(50);
+		u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+	}
+	if (delay == 0) {
+		u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, u1tmp&(~BIT(2)));
+	}
+}
+
+void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 u1_h2c_set_pwrmode[3] = { 0 };
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+	RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
+
+	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
+	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
+	SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
+					      ppsc->reg_max_lps_awakeintvl);
+
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+		      "rtl8723ae_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
+		      u1_h2c_set_pwrmode, 3);
+	rtl8723ae_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
+
+}
+
+static bool _rtl8723ae_cmd_send_packet(struct ieee80211_hw *hw,
+				       struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl8192_tx_ring *ring;
+	struct rtl_tx_desc *pdesc;
+	u8 own;
+	unsigned long flags;
+	struct sk_buff *pskb = NULL;
+
+	ring = &rtlpci->tx_ring[BEACON_QUEUE];
+
+	pskb = __skb_dequeue(&ring->queue);
+	if (pskb)
+		kfree_skb(pskb);
+
+	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
+
+	pdesc = &ring->desc[0];
+	own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
+
+	rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
+
+	__skb_queue_tail(&ring->queue, skb);
+
+	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
+
+	rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
+
+	return true;
+}
+
+static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
+	/* page 0 beacon */
+	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
+	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
+	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
+	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
+	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
+	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
+	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
+	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+	/* page 1 beacon */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	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, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+	/* page 2  ps-poll */
+	0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
+	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+	/* page 3  null */
+	0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
+	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+	/* page 4  probe_resp */
+	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
+	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
+	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
+	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
+	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
+	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
+	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
+	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
+	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
+	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
+	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+	/* page 5  probe_resp */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+void rtl8723ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct sk_buff *skb = NULL;
+
+	u32 totalpacketlen;
+	bool rtstatus;
+	u8 u1RsvdPageLoc[3] = { 0 };
+	bool dlok = false;
+
+	u8 *beacon;
+	u8 *p_pspoll;
+	u8 *nullfunc;
+	u8 *p_probersp;
+	/*---------------------------------------------------------
+				(1) beacon
+	---------------------------------------------------------
+	*/
+	beacon = &reserved_page_packet[BEACON_PG * 128];
+	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
+	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
+
+	/*-------------------------------------------------------
+				(2) ps-poll
+	--------------------------------------------------------
+	*/
+	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
+	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
+	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
+	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
+
+	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
+
+	/*--------------------------------------------------------
+				(3) null data
+	---------------------------------------------------------i
+	*/
+	nullfunc = &reserved_page_packet[NULL_PG * 128];
+	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
+	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
+	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
+
+	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
+
+	/*---------------------------------------------------------
+				(4) probe response
+	----------------------------------------------------------
+	*/
+	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
+	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
+	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
+	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
+
+	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
+
+	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
+
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
+		      "rtl8723ae_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+		      &reserved_page_packet[0], totalpacketlen);
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+		      "rtl8723ae_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+		      u1RsvdPageLoc, 3);
+
+	skb = dev_alloc_skb(totalpacketlen);
+	memcpy((u8 *) skb_put(skb, totalpacketlen),
+	       &reserved_page_packet, totalpacketlen);
+
+	rtstatus = _rtl8723ae_cmd_send_packet(hw, skb);
+
+	if (rtstatus)
+		dlok = true;
+
+	if (dlok) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 "Set RSVD page location to Fw.\n");
+		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+				"H2C_RSVDPAGE:\n",
+				u1RsvdPageLoc, 3);
+		rtl8723ae_fill_h2c_cmd(hw, H2C_RSVDPAGE,
+				       sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
+	} else
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			 "Set RSVD page location to Fw FAIL!!!!!!.\n");
+}
+
+void rtl8723ae_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
+{
+	u8 u1_joinbssrpt_parm[1] = { 0 };
+
+	SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
+
+	rtl8723ae_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h
new file mode 100644
index 0000000..89994e1
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h
@@ -0,0 +1,101 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ****************************************************************************
+ */
+
+#ifndef __RTL92C__FW__H__
+#define __RTL92C__FW__H__
+
+#define FW_8192C_START_ADDRESS			0x1000
+#define FW_8192C_END_ADDRESS			0x3FFF
+#define FW_8192C_PAGE_SIZE			4096
+#define FW_8192C_POLLING_DELAY			5
+#define FW_8192C_POLLING_TIMEOUT_COUNT		1000
+
+#define BEACON_PG				0
+#define PSPOLL_PG				2
+#define NULL_PG					3
+#define PROBERSP_PG				4 /* ->5 */
+
+#define TOTAL_RESERVED_PKT_LEN			768
+
+#define IS_FW_HEADER_EXIST(_pfwhdr)		\
+	((_pfwhdr->signature&0xFF00) == 0x2300)
+
+struct rtl8723ae_firmware_header {
+	u16 signature;
+	u8 category;
+	u8 function;
+	u16 version;
+	u8 subversion;
+	u8 rsvd1;
+	u8 month;
+	u8 date;
+	u8 hour;
+	u8 minute;
+	u16 ramcodeSize;
+	u16 rsvd2;
+	u32 svnindex;
+	u32 rsvd3;
+	u32 rsvd4;
+	u32 rsvd5;
+};
+
+enum rtl8192c_h2c_cmd {
+	H2C_AP_OFFLOAD = 0,
+	H2C_SETPWRMODE = 1,
+	H2C_JOINBSSRPT = 2,
+	H2C_RSVDPAGE = 3,
+	H2C_RSSI_REPORT = 5,
+	H2C_RA_MASK = 6,
+	MAX_H2CCMD
+};
+
+#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val)			\
+	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val)		\
+	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val)	\
+	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val)
+#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val)		\
+	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val)		\
+	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val)		\
+	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val)		\
+	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val)
+
+int rtl8723ae_download_fw(struct ieee80211_hw *hw);
+void rtl8723ae_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
+			    u32 cmd_len, u8 *p_cmdbuffer);
+void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw);
+void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
+void rtl8723ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
+void rtl8723ae_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c
new file mode 100644
index 0000000..3d092e4
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c
@@ -0,0 +1,542 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "hal_bt_coexist.h"
+#include "../pci.h"
+#include "dm.h"
+#include "fw.h"
+#include "phy.h"
+#include "reg.h"
+#include "hal_btc.h"
+
+void rtl8723ae_dm_bt_reject_ap_aggregated_packet(struct ieee80211_hw *hw,
+						 bool reject)
+{
+}
+
+void _rtl8723_dm_bt_check_wifi_state(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	if (rtlpriv->link_info.busytraffic) {
+		rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_WIFI_IDLE;
+
+		if (rtlpriv->link_info.tx_busy_traffic)
+			rtlpcipriv->bt_coexist.cstate |=
+					BT_COEX_STATE_WIFI_UPLINK;
+		else
+			rtlpcipriv->bt_coexist.cstate &=
+					~BT_COEX_STATE_WIFI_UPLINK;
+
+		if (rtlpriv->link_info.rx_busy_traffic)
+			rtlpcipriv->bt_coexist.cstate |=
+					BT_COEX_STATE_WIFI_DOWNLINK;
+		else
+			rtlpcipriv->bt_coexist.cstate &=
+					~BT_COEX_STATE_WIFI_DOWNLINK;
+	} else {
+		rtlpcipriv->bt_coexist.cstate |= BT_COEX_STATE_WIFI_IDLE;
+		rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_WIFI_UPLINK;
+		rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_WIFI_DOWNLINK;
+	}
+
+	if (rtlpriv->mac80211.mode == WIRELESS_MODE_G ||
+	    rtlpriv->mac80211.mode == WIRELESS_MODE_B) {
+		rtlpcipriv->bt_coexist.cstate |= BT_COEX_STATE_WIFI_LEGACY;
+		rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_WIFI_HT20;
+		rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_WIFI_HT40;
+	} else {
+		rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_WIFI_LEGACY;
+		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
+			rtlpcipriv->bt_coexist.cstate |=
+					BT_COEX_STATE_WIFI_HT40;
+			rtlpcipriv->bt_coexist.cstate &=
+					~BT_COEX_STATE_WIFI_HT20;
+		} else {
+			rtlpcipriv->bt_coexist.cstate |=
+					BT_COEX_STATE_WIFI_HT20;
+			rtlpcipriv->bt_coexist.cstate &=
+					~BT_COEX_STATE_WIFI_HT40;
+		}
+	}
+
+	if (rtlpriv->bt_operation_on)
+		rtlpcipriv->bt_coexist.cstate |= BT_COEX_STATE_BT30;
+	else
+		rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_BT30;
+}
+
+u8 rtl8723ae_dm_bt_check_coex_rssi_state1(struct ieee80211_hw *hw,
+					  u8 level_num, u8 rssi_thresh,
+					  u8 rssi_thresh1)
+
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	long smooth;
+	u8 bt_rssi_state = 0;
+
+	smooth =  rtl8723ae_dm_bt_get_rx_ss(hw);
+
+	if (level_num == 2) {
+		rtlpcipriv->bt_coexist.cstate &=
+				~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
+
+		if ((rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+		    BT_RSSI_STATE_LOW) ||
+		    (rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+		    BT_RSSI_STATE_STAY_LOW)) {
+			if (smooth >= (rssi_thresh +
+			    BT_FW_COEX_THRESH_TOL)) {
+				bt_rssi_state = BT_RSSI_STATE_HIGH;
+				rtlpcipriv->bt_coexist.cstate |=
+					BT_COEX_STATE_WIFI_RSSI_1_HIGH;
+				rtlpcipriv->bt_coexist.cstate &=
+					~BT_COEX_STATE_WIFI_RSSI_1_LOW;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI_1 state switch to High\n");
+			} else {
+				bt_rssi_state = BT_RSSI_STATE_STAY_LOW;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI_1 state stay at Low\n");
+			}
+		} else {
+			if (smooth < rssi_thresh) {
+				bt_rssi_state = BT_RSSI_STATE_LOW;
+				rtlpcipriv->bt_coexist.cstate |=
+					 BT_COEX_STATE_WIFI_RSSI_1_LOW;
+				rtlpcipriv->bt_coexist.cstate &=
+					 ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI_1 state switch to Low\n");
+			} else {
+				bt_rssi_state = BT_RSSI_STATE_STAY_HIGH;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI_1 state stay at High\n");
+			}
+		}
+	} else if (level_num == 3) {
+		if (rssi_thresh > rssi_thresh1) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "[DM][BT], RSSI_1 thresh error!!\n");
+			return rtlpcipriv->bt_coexist.bt_pre_rssi_state;
+		}
+
+		if ((rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+		    BT_RSSI_STATE_LOW) ||
+		    (rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+		    BT_RSSI_STATE_STAY_LOW)) {
+			if (smooth >=
+			    (rssi_thresh+BT_FW_COEX_THRESH_TOL)) {
+				bt_rssi_state = BT_RSSI_STATE_MEDIUM;
+				rtlpcipriv->bt_coexist.cstate |=
+					 BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
+				rtlpcipriv->bt_coexist.cstate &=
+					 ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
+				rtlpcipriv->bt_coexist.cstate &=
+					 ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI_1 state switch to Medium\n");
+			} else {
+				bt_rssi_state = BT_RSSI_STATE_STAY_LOW;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI_1 state stay at Low\n");
+			}
+		} else if ((rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+			   BT_RSSI_STATE_MEDIUM) ||
+			   (rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+			   BT_RSSI_STATE_STAY_MEDIUM)) {
+			if (smooth >= (rssi_thresh1 +
+			    BT_FW_COEX_THRESH_TOL)) {
+				bt_rssi_state = BT_RSSI_STATE_HIGH;
+				rtlpcipriv->bt_coexist.cstate |=
+					 BT_COEX_STATE_WIFI_RSSI_1_HIGH;
+				rtlpcipriv->bt_coexist.cstate &=
+					 ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
+				rtlpcipriv->bt_coexist.cstate &=
+					 ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI_1 state switch to High\n");
+			} else if (smooth < rssi_thresh) {
+				bt_rssi_state = BT_RSSI_STATE_LOW;
+				rtlpcipriv->bt_coexist.cstate |=
+					BT_COEX_STATE_WIFI_RSSI_1_LOW;
+				rtlpcipriv->bt_coexist.cstate &=
+					~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
+				rtlpcipriv->bt_coexist.cstate &=
+					~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI_1 state switch to Low\n");
+			} else {
+				bt_rssi_state = BT_RSSI_STATE_STAY_MEDIUM;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI_1 state stay at Medium\n");
+			}
+		} else {
+			if (smooth < rssi_thresh1) {
+				bt_rssi_state = BT_RSSI_STATE_MEDIUM;
+				rtlpcipriv->bt_coexist.cstate |=
+					BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
+				rtlpcipriv->bt_coexist.cstate &=
+					~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
+				rtlpcipriv->bt_coexist.cstate &=
+					~BT_COEX_STATE_WIFI_RSSI_1_LOW;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI_1 state switch to Medium\n");
+			} else {
+				bt_rssi_state = BT_RSSI_STATE_STAY_HIGH;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI_1 state stay at High\n");
+			}
+		}
+	}
+
+	rtlpcipriv->bt_coexist.bt_pre_rssi_state1 = bt_rssi_state;
+
+	return bt_rssi_state;
+}
+
+u8 rtl8723ae_dm_bt_check_coex_rssi_state(struct ieee80211_hw *hw,
+					 u8 level_num, u8 rssi_thresh,
+					 u8 rssi_thresh1)
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	long smooth;
+	u8 bt_rssi_state = 0;
+
+	smooth = rtl8723ae_dm_bt_get_rx_ss(hw);
+
+	if (level_num == 2) {
+		rtlpcipriv->bt_coexist.cstate &=
+					 ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;
+
+		if ((rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+		    BT_RSSI_STATE_LOW) ||
+		    (rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+		    BT_RSSI_STATE_STAY_LOW)){
+			if (smooth >=
+			    (rssi_thresh + BT_FW_COEX_THRESH_TOL)) {
+				bt_rssi_state = BT_RSSI_STATE_HIGH;
+				rtlpcipriv->bt_coexist.cstate |=
+					BT_COEX_STATE_WIFI_RSSI_HIGH;
+				rtlpcipriv->bt_coexist.cstate &=
+					~BT_COEX_STATE_WIFI_RSSI_LOW;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI state switch to High\n");
+			} else {
+				bt_rssi_state = BT_RSSI_STATE_STAY_LOW;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI state stay at Low\n");
+			}
+		} else {
+			if (smooth < rssi_thresh) {
+				bt_rssi_state = BT_RSSI_STATE_LOW;
+				rtlpcipriv->bt_coexist.cstate |=
+					BT_COEX_STATE_WIFI_RSSI_LOW;
+				rtlpcipriv->bt_coexist.cstate &=
+					~BT_COEX_STATE_WIFI_RSSI_HIGH;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI state switch to Low\n");
+			} else {
+				bt_rssi_state = BT_RSSI_STATE_STAY_HIGH;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI state stay at High\n");
+			}
+		}
+	} else if (level_num == 3) {
+		if (rssi_thresh > rssi_thresh1) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "[DM][BT], RSSI thresh error!!\n");
+			return rtlpcipriv->bt_coexist.bt_pre_rssi_state;
+		}
+		if ((rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+		    BT_RSSI_STATE_LOW) ||
+		    (rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+		    BT_RSSI_STATE_STAY_LOW)) {
+			if (smooth >=
+			    (rssi_thresh + BT_FW_COEX_THRESH_TOL)) {
+				bt_rssi_state = BT_RSSI_STATE_MEDIUM;
+				rtlpcipriv->bt_coexist.cstate
+					|= BT_COEX_STATE_WIFI_RSSI_MEDIUM;
+				rtlpcipriv->bt_coexist.cstate
+					&= ~BT_COEX_STATE_WIFI_RSSI_LOW;
+				rtlpcipriv->bt_coexist.cstate
+					&= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI state switch to Medium\n");
+			} else {
+				bt_rssi_state = BT_RSSI_STATE_STAY_LOW;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI state stay at Low\n");
+			}
+		} else if ((rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+			   BT_RSSI_STATE_MEDIUM) ||
+			   (rtlpcipriv->bt_coexist.bt_pre_rssi_state ==
+			   BT_RSSI_STATE_STAY_MEDIUM)) {
+			if (smooth >=
+			    (rssi_thresh1 + BT_FW_COEX_THRESH_TOL)) {
+				bt_rssi_state = BT_RSSI_STATE_HIGH;
+				rtlpcipriv->bt_coexist.cstate
+					|= BT_COEX_STATE_WIFI_RSSI_HIGH;
+				rtlpcipriv->bt_coexist.cstate
+					&= ~BT_COEX_STATE_WIFI_RSSI_LOW;
+				rtlpcipriv->bt_coexist.cstate
+					&= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI state switch to High\n");
+			} else if (smooth < rssi_thresh) {
+				bt_rssi_state = BT_RSSI_STATE_LOW;
+				rtlpcipriv->bt_coexist.cstate
+					|= BT_COEX_STATE_WIFI_RSSI_LOW;
+				rtlpcipriv->bt_coexist.cstate
+					&= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
+				rtlpcipriv->bt_coexist.cstate
+					&= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI state switch to Low\n");
+			} else {
+				bt_rssi_state = BT_RSSI_STATE_STAY_MEDIUM;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI state stay at Medium\n");
+			}
+		} else {
+			if (smooth < rssi_thresh1) {
+				bt_rssi_state = BT_RSSI_STATE_MEDIUM;
+				rtlpcipriv->bt_coexist.cstate
+					|= BT_COEX_STATE_WIFI_RSSI_MEDIUM;
+				rtlpcipriv->bt_coexist.cstate
+					&= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
+				rtlpcipriv->bt_coexist.cstate
+					&= ~BT_COEX_STATE_WIFI_RSSI_LOW;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI state switch to Medium\n");
+			} else {
+				bt_rssi_state = BT_RSSI_STATE_STAY_HIGH;
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+					 "[DM][BT], RSSI state stay at High\n");
+			}
+		}
+	}
+
+	rtlpcipriv->bt_coexist.bt_pre_rssi_state = bt_rssi_state;
+	return bt_rssi_state;
+}
+
+long rtl8723ae_dm_bt_get_rx_ss(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	long smooth = 0;
+
+	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED)
+		smooth = GET_UNDECORATED_AVERAGE_RSSI(rtlpriv);
+	else
+		smooth = rtlpriv->dm.entry_min_undec_sm_pwdb;
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "rtl8723ae_dm_bt_get_rx_ss() = %ld\n", smooth);
+
+	return smooth;
+}
+
+void rtl8723ae_dm_bt_balance(struct ieee80211_hw *hw,
+			     bool balance_on, u8 ms0, u8 ms1)
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 h2c_parameter[3] = {0};
+
+	if (balance_on) {
+		h2c_parameter[2] = 1;
+		h2c_parameter[1] = ms1;
+		h2c_parameter[0] = ms0;
+		rtlpcipriv->bt_coexist.fw_coexist_all_off = false;
+	} else {
+		h2c_parameter[2] = 0;
+		h2c_parameter[1] = 0;
+		h2c_parameter[0] = 0;
+	}
+	rtlpcipriv->bt_coexist.balance_on = balance_on;
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[DM][BT], Balance=[%s:%dms:%dms], write 0xc=0x%x\n",
+		 balance_on ? "ON" : "OFF", ms0, ms1,
+		 h2c_parameter[0]<<16 | h2c_parameter[1]<<8 | h2c_parameter[2]);
+
+	rtl8723ae_fill_h2c_cmd(hw, 0xc, 3, h2c_parameter);
+}
+
+
+void rtl8723ae_dm_bt_agc_table(struct ieee80211_hw *hw, u8 type)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+
+	if (type == BT_AGCTABLE_OFF) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BT]AGCTable Off!\n");
+		rtl_write_dword(rtlpriv, 0xc78, 0x641c0001);
+		rtl_write_dword(rtlpriv, 0xc78, 0x631d0001);
+		rtl_write_dword(rtlpriv, 0xc78, 0x621e0001);
+		rtl_write_dword(rtlpriv, 0xc78, 0x611f0001);
+		rtl_write_dword(rtlpriv, 0xc78, 0x60200001);
+
+		rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+					RF_RX_AGC_HP, 0xfffff, 0x32000);
+		rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+					RF_RX_AGC_HP, 0xfffff, 0x71000);
+		rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+					RF_RX_AGC_HP, 0xfffff, 0xb0000);
+		rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+					RF_RX_AGC_HP, 0xfffff, 0xfc000);
+		rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+					RF_RX_G1, 0xfffff, 0x30355);
+	} else if (type == BT_AGCTABLE_ON) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BT]AGCTable On!\n");
+		rtl_write_dword(rtlpriv, 0xc78, 0x4e1c0001);
+		rtl_write_dword(rtlpriv, 0xc78, 0x4d1d0001);
+		rtl_write_dword(rtlpriv, 0xc78, 0x4c1e0001);
+		rtl_write_dword(rtlpriv, 0xc78, 0x4b1f0001);
+		rtl_write_dword(rtlpriv, 0xc78, 0x4a200001);
+
+		rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+					RF_RX_AGC_HP, 0xfffff, 0xdc000);
+		rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+					RF_RX_AGC_HP, 0xfffff, 0x90000);
+		rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+					RF_RX_AGC_HP, 0xfffff, 0x51000);
+		rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+					RF_RX_AGC_HP, 0xfffff, 0x12000);
+		rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A,
+					RF_RX_G1, 0xfffff, 0x00355);
+
+		rtlpcipriv->bt_coexist.sw_coexist_all_off = false;
+	}
+}
+
+void rtl8723ae_dm_bt_bback_off_level(struct ieee80211_hw *hw, u8 type)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+
+	if (type == BT_BB_BACKOFF_OFF) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BT]BBBackOffLevel Off!\n");
+		rtl_write_dword(rtlpriv, 0xc04, 0x3a05611);
+	} else if (type == BT_BB_BACKOFF_ON) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BT]BBBackOffLevel On!\n");
+		rtl_write_dword(rtlpriv, 0xc04, 0x3a07611);
+		rtlpcipriv->bt_coexist.sw_coexist_all_off = false;
+	}
+}
+
+void rtl8723ae_dm_bt_fw_coex_all_off(struct ieee80211_hw *hw)
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "rtl8723ae_dm_bt_fw_coex_all_off()\n");
+
+	if (rtlpcipriv->bt_coexist.fw_coexist_all_off)
+		return;
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "rtl8723ae_dm_bt_fw_coex_all_off(), real Do\n");
+	rtl8723ae_dm_bt_fw_coex_all_off_8723a(hw);
+	rtlpcipriv->bt_coexist.fw_coexist_all_off = true;
+}
+
+void rtl8723ae_dm_bt_sw_coex_all_off(struct ieee80211_hw *hw)
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "rtl8723ae_dm_bt_sw_coex_all_off()\n");
+
+	if (rtlpcipriv->bt_coexist.sw_coexist_all_off)
+		return;
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "rtl8723ae_dm_bt_sw_coex_all_off(), real Do\n");
+	rtl8723ae_dm_bt_sw_coex_all_off_8723a(hw);
+	rtlpcipriv->bt_coexist.sw_coexist_all_off = true;
+}
+
+void rtl8723ae_dm_bt_hw_coex_all_off(struct ieee80211_hw *hw)
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "rtl8723ae_dm_bt_hw_coex_all_off()\n");
+
+	if (rtlpcipriv->bt_coexist.hw_coexist_all_off)
+		return;
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "rtl8723ae_dm_bt_hw_coex_all_off(), real Do\n");
+
+	rtl8723ae_dm_bt_hw_coex_all_off_8723a(hw);
+
+	rtlpcipriv->bt_coexist.hw_coexist_all_off = true;
+}
+
+void rtl8723ae_btdm_coex_all_off(struct ieee80211_hw *hw)
+{
+	rtl8723ae_dm_bt_fw_coex_all_off(hw);
+	rtl8723ae_dm_bt_sw_coex_all_off(hw);
+	rtl8723ae_dm_bt_hw_coex_all_off(hw);
+}
+
+bool rtl8723ae_dm_bt_is_coexist_state_changed(struct ieee80211_hw *hw)
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+
+	if ((rtlpcipriv->bt_coexist.previous_state ==
+	    rtlpcipriv->bt_coexist.cstate) &&
+	    (rtlpcipriv->bt_coexist.previous_state_h ==
+	    rtlpcipriv->bt_coexist.cstate_h))
+		return false;
+	else
+		return true;
+}
+
+bool rtl8723ae_dm_bt_is_wifi_up_link(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (rtlpriv->link_info.tx_busy_traffic)
+		return true;
+	else
+		return false;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h
new file mode 100644
index 0000000..76f4d12
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h
@@ -0,0 +1,160 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_HAL_BT_COEXIST_H__
+#define __RTL8723E_HAL_BT_COEXIST_H__
+
+#include "../wifi.h"
+
+/* The reg define is for 8723 */
+#define	REG_HIGH_PRIORITY_TXRX			0x770
+#define	REG_LOW_PRIORITY_TXRX			0x774
+
+#define BT_FW_COEX_THRESH_TOL			6
+#define BT_FW_COEX_THRESH_20			20
+#define BT_FW_COEX_THRESH_23			23
+#define BT_FW_COEX_THRESH_25			25
+#define BT_FW_COEX_THRESH_30			30
+#define BT_FW_COEX_THRESH_35			35
+#define BT_FW_COEX_THRESH_40			40
+#define BT_FW_COEX_THRESH_45			45
+#define BT_FW_COEX_THRESH_47			47
+#define BT_FW_COEX_THRESH_50			50
+#define BT_FW_COEX_THRESH_55			55
+
+#define BT_COEX_STATE_BT30			BIT(0)
+#define BT_COEX_STATE_WIFI_HT20			BIT(1)
+#define BT_COEX_STATE_WIFI_HT40			BIT(2)
+#define BT_COEX_STATE_WIFI_LEGACY		BIT(3)
+
+#define BT_COEX_STATE_WIFI_RSSI_LOW		BIT(4)
+#define BT_COEX_STATE_WIFI_RSSI_MEDIUM		BIT(5)
+#define BT_COEX_STATE_WIFI_RSSI_HIGH		BIT(6)
+#define BT_COEX_STATE_DEC_BT_POWER		BIT(7)
+
+#define BT_COEX_STATE_WIFI_IDLE			BIT(8)
+#define BT_COEX_STATE_WIFI_UPLINK		BIT(9)
+#define BT_COEX_STATE_WIFI_DOWNLINK		BIT(10)
+
+#define BT_COEX_STATE_BT_INQ_PAGE		BIT(11)
+#define BT_COEX_STATE_BT_IDLE			BIT(12)
+#define BT_COEX_STATE_BT_UPLINK			BIT(13)
+#define BT_COEX_STATE_BT_DOWNLINK		BIT(14)
+
+#define BT_COEX_STATE_HOLD_FOR_BT_OPERATION	BIT(15)
+#define BT_COEX_STATE_BT_RSSI_LOW		BIT(19)
+
+#define BT_COEX_STATE_PROFILE_HID		BIT(20)
+#define BT_COEX_STATE_PROFILE_A2DP		BIT(21)
+#define BT_COEX_STATE_PROFILE_PAN		BIT(22)
+#define BT_COEX_STATE_PROFILE_SCO		BIT(23)
+
+#define BT_COEX_STATE_WIFI_RSSI_1_LOW		BIT(24)
+#define BT_COEX_STATE_WIFI_RSSI_1_MEDIUM	BIT(25)
+#define BT_COEX_STATE_WIFI_RSSI_1_HIGH		BIT(26)
+
+#define BT_COEX_STATE_BTINFO_COMMON		BIT(30)
+#define BT_COEX_STATE_BTINFO_B_HID_SCOESCO	BIT(31)
+#define BT_COEX_STATE_BTINFO_B_FTP_A2DP		BIT(29)
+
+#define BT_COEX_STATE_BT_CNT_LEVEL_0		BIT(0)
+#define BT_COEX_STATE_BT_CNT_LEVEL_1		BIT(1)
+#define BT_COEX_STATE_BT_CNT_LEVEL_2		BIT(2)
+#define BT_COEX_STATE_BT_CNT_LEVEL_3		BIT(3)
+
+#define BT_RSSI_STATE_HIGH			0
+#define BT_RSSI_STATE_MEDIUM			1
+#define BT_RSSI_STATE_LOW			2
+#define BT_RSSI_STATE_STAY_HIGH			3
+#define BT_RSSI_STATE_STAY_MEDIUM		4
+#define BT_RSSI_STATE_STAY_LOW			5
+
+#define	BT_AGCTABLE_OFF				0
+#define	BT_AGCTABLE_ON				1
+#define	BT_BB_BACKOFF_OFF			0
+#define	BT_BB_BACKOFF_ON			1
+#define	BT_FW_NAV_OFF				0
+#define	BT_FW_NAV_ON				1
+
+#define	BT_COEX_MECH_NONE			0
+#define	BT_COEX_MECH_SCO			1
+#define	BT_COEX_MECH_HID			2
+#define	BT_COEX_MECH_A2DP			3
+#define	BT_COEX_MECH_PAN			4
+#define	BT_COEX_MECH_HID_A2DP			5
+#define	BT_COEX_MECH_HID_PAN			6
+#define	BT_COEX_MECH_PAN_A2DP			7
+#define	BT_COEX_MECH_HID_SCO_ESCO		8
+#define	BT_COEX_MECH_FTP_A2DP			9
+#define	BT_COEX_MECH_COMMON			10
+#define	BT_COEX_MECH_MAX			11
+
+#define	BT_DBG_PROFILE_NONE			0
+#define	BT_DBG_PROFILE_SCO			1
+#define	BT_DBG_PROFILE_HID			2
+#define	BT_DBG_PROFILE_A2DP			3
+#define	BT_DBG_PROFILE_PAN			4
+#define	BT_DBG_PROFILE_HID_A2DP			5
+#define	BT_DBG_PROFILE_HID_PAN			6
+#define	BT_DBG_PROFILE_PAN_A2DP			7
+#define	BT_DBG_PROFILE_MAX			9
+
+#define	BTINFO_B_FTP				BIT(7)
+#define	BTINFO_B_A2DP				BIT(6)
+#define	BTINFO_B_HID				BIT(5)
+#define	BTINFO_B_SCO_BUSY			BIT(4)
+#define	BTINFO_B_ACL_BUSY			BIT(3)
+#define	BTINFO_B_INQ_PAGE			BIT(2)
+#define	BTINFO_B_SCO_ESCO			BIT(1)
+#define	BTINFO_B_CONNECTION			BIT(0)
+
+
+void rtl8723ae_btdm_coex_all_off(struct ieee80211_hw *hw);
+void rtl8723ae_dm_bt_fw_coex_all_off(struct ieee80211_hw *hw);
+
+void rtl8723ae_dm_bt_sw_coex_all_off(struct ieee80211_hw *hw);
+void rtl8723ae_dm_bt_hw_coex_all_off(struct ieee80211_hw *hw);
+long rtl8723ae_dm_bt_get_rx_ss(struct ieee80211_hw *hw);
+void rtl8723ae_dm_bt_balance(struct ieee80211_hw *hw,
+			    bool balance_on, u8 ms0, u8 ms1);
+void rtl8723ae_dm_bt_agc_table(struct ieee80211_hw *hw, u8 type);
+void rtl8723ae_dm_bt_bback_off_level(struct ieee80211_hw *hw, u8 type);
+u8 rtl8723ae_dm_bt_check_coex_rssi_state(struct ieee80211_hw *hw,
+					u8 level_num, u8 rssi_thresh,
+					u8 rssi_thresh1);
+u8 rtl8723ae_dm_bt_check_coex_rssi_state1(struct ieee80211_hw *hw,
+					 u8  level_num, u8 rssi_thresh,
+					 u8 rssi_thresh1);
+void _rtl8723_dm_bt_check_wifi_state(struct ieee80211_hw *hw);
+void rtl8723ae_dm_bt_reject_ap_aggregated_packet(struct ieee80211_hw *hw,
+						bool reject);
+
+bool rtl8723ae_dm_bt_is_coexist_state_changed(struct ieee80211_hw *hw);
+bool rtl8723ae_dm_bt_is_wifi_up_link(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c
new file mode 100644
index 0000000..887d521
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c
@@ -0,0 +1,1786 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ****************************************************************************
+ */
+#include "hal_btc.h"
+#include "../pci.h"
+#include "phy.h"
+#include "fw.h"
+#include "reg.h"
+#include "def.h"
+
+void rtl8723ae_bt_coex_off_before_lps(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+	if (!rtlpcipriv->bt_coexist.bt_coexistence)
+		return;
+
+	if (ppsc->inactiveps) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BT][DM], Before enter IPS, turn off all Coexist DM\n");
+		rtlpcipriv->bt_coexist.cstate = 0;
+		rtlpcipriv->bt_coexist.previous_state = 0;
+		rtlpcipriv->bt_coexist.cstate_h = 0;
+		rtlpcipriv->bt_coexist.previous_state_h = 0;
+		rtl8723ae_btdm_coex_all_off(hw);
+	}
+}
+
+static enum _RT_MEDIA_STATUS mgnt_link_status_query(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	enum _RT_MEDIA_STATUS m_status = RT_MEDIA_DISCONNECT;
+
+	u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0;
+
+	if (bibss || rtlpriv->mac80211.link_state >= MAC80211_LINKED)
+		m_status = RT_MEDIA_CONNECT;
+
+	return m_status;
+}
+
+void rtl_8723e_bt_wifi_media_status_notify(struct ieee80211_hw *hw,
+					   bool mstatus)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u8 h2c_parameter[3] = {0};
+	u8 chnl;
+
+	if (!rtlpcipriv->bt_coexist.bt_coexistence)
+		return;
+
+	if (RT_MEDIA_CONNECT == mstatus)
+		h2c_parameter[0] = 0x1; /* 0: disconnected, 1:connected */
+	else
+		h2c_parameter[0] = 0x0;
+
+	if (mgnt_link_status_query(hw))	{
+		chnl = rtlphy->current_channel;
+		h2c_parameter[1] = chnl;
+	}
+
+	if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40)
+		h2c_parameter[2] = 0x30;
+	else
+		h2c_parameter[2] = 0x20;
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+		 "[BTCoex], FW write 0x19 = 0x%x\n",
+		 h2c_parameter[0]<<16|h2c_parameter[1]<<8|h2c_parameter[2]);
+
+	rtl8723ae_fill_h2c_cmd(hw, 0x19, 3, h2c_parameter);
+
+}
+
+static bool rtl8723ae_dm_bt_is_wifi_busy(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	if (rtlpriv->link_info.busytraffic ||
+		rtlpriv->link_info.rx_busy_traffic ||
+		rtlpriv->link_info.tx_busy_traffic)
+		return true;
+	else
+		return false;
+}
+
+static void rtl8723ae_dm_bt_set_fw_3a(struct ieee80211_hw *hw,
+				      u8 byte1, u8 byte2, u8 byte3,
+				      u8 byte4, u8 byte5)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 h2c_parameter[5] = {0};
+
+	h2c_parameter[0] = byte1;
+	h2c_parameter[1] = byte2;
+	h2c_parameter[2] = byte3;
+	h2c_parameter[3] = byte4;
+	h2c_parameter[4] = byte5;
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[BTCoex], FW write 0x3a(4bytes) = 0x%x%8x\n",
+		 h2c_parameter[0], h2c_parameter[1]<<24 | h2c_parameter[2]<<16 |
+		 h2c_parameter[3]<<8 | h2c_parameter[4]);
+	rtl8723ae_fill_h2c_cmd(hw, 0x3a, 5, h2c_parameter);
+}
+
+static bool rtl8723ae_dm_bt_need_to_dec_bt_pwr(struct ieee80211_hw *hw)
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (mgnt_link_status_query(hw) == RT_MEDIA_CONNECT) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "Need to decrease bt power\n");
+		rtlpcipriv->bt_coexist.cstate |= BT_COEX_STATE_DEC_BT_POWER;
+		return true;
+	}
+
+	rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_DEC_BT_POWER;
+	return false;
+}
+
+static bool rtl8723ae_dm_bt_is_same_coexist_state(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+
+	if ((rtlpcipriv->bt_coexist.previous_state ==
+	    rtlpcipriv->bt_coexist.cstate) &&
+	    (rtlpcipriv->bt_coexist.previous_state_h ==
+	    rtlpcipriv->bt_coexist.cstate_h)) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[DM][BT], Coexist state do not chang!!\n");
+		return true;
+	} else {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[DM][BT], Coexist state changed!!\n");
+		return false;
+	}
+}
+
+static void rtl8723ae_dm_bt_set_coex_table(struct ieee80211_hw *hw,
+					   u32 val_0x6c0, u32 val_0x6c8,
+					   u32 val_0x6cc)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "set coex table, set 0x6c0 = 0x%x\n", val_0x6c0);
+	rtl_write_dword(rtlpriv, 0x6c0, val_0x6c0);
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "set coex table, set 0x6c8 = 0x%x\n", val_0x6c8);
+	rtl_write_dword(rtlpriv, 0x6c8, val_0x6c8);
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "set coex table, set 0x6cc = 0x%x\n", val_0x6cc);
+	rtl_write_byte(rtlpriv, 0x6cc, val_0x6cc);
+}
+
+static void rtl8723ae_dm_bt_set_hw_pta_mode(struct ieee80211_hw *hw, bool mode)
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (BT_PTA_MODE_ON == mode) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, "PTA mode on, ");
+		/*  Enable GPIO 0/1/2/3/8 pins for bt */
+		rtl_write_byte(rtlpriv, 0x40, 0x20);
+		rtlpcipriv->bt_coexist.hw_coexist_all_off = false;
+	} else {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, "PTA mode off\n");
+		rtl_write_byte(rtlpriv, 0x40, 0x0);
+	}
+}
+
+static void rtl8723ae_dm_bt_set_sw_rf_rx_lpf_corner(struct ieee80211_hw *hw,
+						    u8 type)
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (BT_RF_RX_LPF_CORNER_SHRINK == type) {
+		/* Shrink RF Rx LPF corner, 0x1e[7:4]=1111 ==> [11:4] by Jenyu*/
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "Shrink RF Rx LPF corner!!\n");
+		rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A, 0x1e, 0xfffff,
+					0xf0ff7);
+		rtlpcipriv->bt_coexist.sw_coexist_all_off = false;
+	} else if (BT_RF_RX_LPF_CORNER_RESUME == type) {
+		/*Resume RF Rx LPF corner*/
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "Resume RF Rx LPF corner!!\n");
+		rtl8723ae_phy_set_rf_reg(hw, RF90_PATH_A, 0x1e, 0xfffff,
+			rtlpcipriv->bt_coexist.bt_rfreg_origin_1e);
+	}
+}
+
+static void rtl8723ae_bt_set_penalty_tx_rate_adap(struct ieee80211_hw *hw,
+						  u8 ra_type)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	u8 tmu1;
+
+	tmu1 = rtl_read_byte(rtlpriv, 0x4fd);
+	tmu1 |= BIT(0);
+	if (BT_TX_RATE_ADAPTIVE_LOW_PENALTY == ra_type) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "Tx rate adaptive, set low penalty!!\n");
+		tmu1 &= ~BIT(2);
+		rtlpcipriv->bt_coexist.sw_coexist_all_off = false;
+	} else if (BT_TX_RATE_ADAPTIVE_NORMAL == ra_type) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "Tx rate adaptive, set normal!!\n");
+		tmu1 |= BIT(2);
+	}
+	rtl_write_byte(rtlpriv, 0x4fd, tmu1);
+}
+
+static void rtl8723ae_dm_bt_btdm_structure_reload(struct ieee80211_hw *hw,
+						 struct btdm_8723 *btdm)
+{
+	btdm->all_off = false;
+	btdm->agc_table_en = false;
+	btdm->adc_back_off_on = false;
+	btdm->b2_ant_hid_en = false;
+	btdm->low_penalty_rate_adaptive = false;
+	btdm->rf_rx_lpf_shrink = false;
+	btdm->reject_aggre_pkt = false;
+
+	btdm->tdma_on = false;
+	btdm->tdma_ant = TDMA_2ANT;
+	btdm->tdma_nav = TDMA_NAV_OFF;
+	btdm->tdma_dac_swing = TDMA_DAC_SWING_OFF;
+	btdm->fw_dac_swing_lvl = 0x20;
+
+	btdm->tra_tdma_on = false;
+	btdm->tra_tdma_ant = TDMA_2ANT;
+	btdm->tra_tdma_nav = TDMA_NAV_OFF;
+	btdm->ignore_wlan_act = false;
+
+	btdm->ps_tdma_on = false;
+	btdm->ps_tdma_byte[0] = 0x0;
+	btdm->ps_tdma_byte[1] = 0x0;
+	btdm->ps_tdma_byte[2] = 0x0;
+	btdm->ps_tdma_byte[3] = 0x8;
+	btdm->ps_tdma_byte[4] = 0x0;
+
+	btdm->pta_on = true;
+	btdm->val_0x6c0 = 0x5a5aaaaa;
+	btdm->val_0x6c8 = 0xcc;
+	btdm->val_0x6cc = 0x3;
+
+	btdm->sw_dac_swing_on = false;
+	btdm->sw_dac_swing_lvl = 0xc0;
+	btdm->wlan_act_hi = 0x20;
+	btdm->wlan_act_lo = 0x10;
+	btdm->bt_retry_index = 2;
+
+	btdm->dec_bt_pwr = false;
+}
+
+static void dm_bt_btdm_structure_reload_all_off(struct ieee80211_hw *hw,
+						struct btdm_8723 *btdm)
+{
+	rtl8723ae_dm_bt_btdm_structure_reload(hw, btdm);
+	btdm->all_off = true;
+	btdm->pta_on = false;
+	btdm->wlan_act_hi = 0x10;
+}
+
+static bool rtl8723ae_dm_bt_is_2_ant_common_action(struct ieee80211_hw *hw)
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct btdm_8723 btdm8723;
+	bool common = false;
+
+	rtl8723ae_dm_bt_btdm_structure_reload(hw, &btdm8723);
+
+	if (!rtl8723ae_dm_bt_is_wifi_busy(hw)
+	    && !rtlpcipriv->bt_coexist.bt_busy) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "Wifi idle + Bt idle, bt coex mechanism always off!!\n");
+		dm_bt_btdm_structure_reload_all_off(hw, &btdm8723);
+		common = true;
+	} else if (rtl8723ae_dm_bt_is_wifi_busy(hw)
+		   && !rtlpcipriv->bt_coexist.bt_busy) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "Wifi non-idle + Bt disabled/idle!!\n");
+		btdm8723.low_penalty_rate_adaptive = true;
+		btdm8723.rf_rx_lpf_shrink = false;
+		btdm8723.reject_aggre_pkt = false;
+
+		/* sw mechanism */
+		btdm8723.agc_table_en = false;
+		btdm8723.adc_back_off_on = false;
+		btdm8723.sw_dac_swing_on = false;
+
+		btdm8723.pta_on = true;
+		btdm8723.val_0x6c0 = 0x5a5aaaaa;
+		btdm8723.val_0x6c8 = 0xcccc;
+		btdm8723.val_0x6cc = 0x3;
+
+		btdm8723.tdma_on = false;
+		btdm8723.tdma_dac_swing = TDMA_DAC_SWING_OFF;
+		btdm8723.b2_ant_hid_en = false;
+
+		common = true;
+	} else if (rtlpcipriv->bt_coexist.bt_busy) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "Bt non-idle!\n");
+		if (mgnt_link_status_query(hw) == RT_MEDIA_CONNECT) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "Wifi connection exist\n");
+			common = false;
+		} else {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "No Wifi connection!\n");
+			btdm8723.rf_rx_lpf_shrink = true;
+			btdm8723.low_penalty_rate_adaptive = false;
+			btdm8723.reject_aggre_pkt = false;
+
+			/* sw mechanism */
+			btdm8723.agc_table_en = false;
+			btdm8723.adc_back_off_on = false;
+			btdm8723.sw_dac_swing_on = false;
+
+			btdm8723.pta_on = true;
+			btdm8723.val_0x6c0 = 0x55555555;
+			btdm8723.val_0x6c8 = 0x0000ffff;
+			btdm8723.val_0x6cc = 0x3;
+
+			btdm8723.tdma_on = false;
+			btdm8723.tdma_dac_swing = TDMA_DAC_SWING_OFF;
+			btdm8723.b2_ant_hid_en = false;
+
+			common = true;
+		}
+	}
+
+	if (rtl8723ae_dm_bt_need_to_dec_bt_pwr(hw))
+		btdm8723.dec_bt_pwr = true;
+
+	if (common)
+		rtlpcipriv->bt_coexist.cstate |= BT_COEX_STATE_BTINFO_COMMON;
+
+	if (common && rtl8723ae_dm_bt_is_coexist_state_changed(hw))
+		rtl8723ae_dm_bt_set_bt_dm(hw, &btdm8723);
+
+	return common;
+}
+
+static void rtl8723ae_dm_bt_set_sw_full_time_dac_swing(struct ieee80211_hw *hw,
+						       bool sw_dac_swing_on,
+						       u32 sw_dac_swing_lvl)
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (sw_dac_swing_on) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BTCoex], SwDacSwing = 0x%x\n", sw_dac_swing_lvl);
+		rtl8723ae_phy_set_bb_reg(hw, 0x880, 0xff000000,
+					 sw_dac_swing_lvl);
+		rtlpcipriv->bt_coexist.sw_coexist_all_off = false;
+	} else {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BTCoex], SwDacSwing Off!\n");
+		rtl8723ae_phy_set_bb_reg(hw, 0x880, 0xff000000, 0xc0);
+	}
+}
+
+static void rtl8723ae_dm_bt_set_fw_dec_bt_pwr(struct ieee80211_hw *hw,
+					      bool dec_bt_pwr)
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 h2c_parameter[1] = {0};
+
+	h2c_parameter[0] = 0;
+
+	if (dec_bt_pwr) {
+		h2c_parameter[0] |= BIT(1);
+		rtlpcipriv->bt_coexist.fw_coexist_all_off = false;
+	}
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[BTCoex], decrease Bt Power : %s, write 0x21 = 0x%x\n",
+		 (dec_bt_pwr ? "Yes!!" : "No!!"), h2c_parameter[0]);
+
+	rtl8723ae_fill_h2c_cmd(hw, 0x21, 1, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_set_fw_2_ant_hid(struct ieee80211_hw *hw,
+					    bool enable, bool dac_swing_on)
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 h2c_parameter[1] = {0};
+
+	if (enable) {
+		h2c_parameter[0] |= BIT(0);
+		rtlpcipriv->bt_coexist.fw_coexist_all_off = false;
+	}
+	if (dac_swing_on)
+		h2c_parameter[0] |= BIT(1); /* Dac Swing default enable */
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[BTCoex], turn 2-Ant+HID mode %s, DACSwing:%s, write 0x15 = 0x%x\n",
+		 (enable ? "ON!!" : "OFF!!"), (dac_swing_on ? "ON" : "OFF"),
+		 h2c_parameter[0]);
+
+	rtl8723ae_fill_h2c_cmd(hw, 0x15, 1, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_set_fw_tdma_ctrl(struct ieee80211_hw *hw,
+					     bool enable, u8 ant_num, u8 nav_en,
+					     u8 dac_swing_en)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	u8 h2c_parameter[1] = {0};
+	u8 h2c_parameter1[1] = {0};
+
+	h2c_parameter[0] = 0;
+	h2c_parameter1[0] = 0;
+
+	if (enable) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BTCoex], set BT PTA update manager to trigger update!!\n");
+		h2c_parameter1[0] |= BIT(0);
+
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BTCoex], turn TDMA mode ON!!\n");
+		h2c_parameter[0] |= BIT(0);		/* function enable */
+		if (TDMA_1ANT == ant_num) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "[BTCoex], TDMA_1ANT\n");
+			h2c_parameter[0] |= BIT(1);
+		} else if (TDMA_2ANT == ant_num) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "[BTCoex], TDMA_2ANT\n");
+		} else {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "[BTCoex], Unknown Ant\n");
+		}
+
+		if (TDMA_NAV_OFF == nav_en) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "[BTCoex], TDMA_NAV_OFF\n");
+		} else if (TDMA_NAV_ON == nav_en) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "[BTCoex], TDMA_NAV_ON\n");
+			h2c_parameter[0] |= BIT(2);
+		}
+
+		if (TDMA_DAC_SWING_OFF == dac_swing_en) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "[BTCoex], TDMA_DAC_SWING_OFF\n");
+		} else if (TDMA_DAC_SWING_ON == dac_swing_en) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "[BTCoex], TDMA_DAC_SWING_ON\n");
+			h2c_parameter[0] |= BIT(4);
+		}
+		rtlpcipriv->bt_coexist.fw_coexist_all_off = false;
+	} else {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BTCoex], set BT PTA update manager to no update!!\n");
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BTCoex], turn TDMA mode OFF!!\n");
+	}
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[BTCoex], FW2AntTDMA, write 0x26 = 0x%x\n",
+		 h2c_parameter1[0]);
+	rtl8723ae_fill_h2c_cmd(hw, 0x26, 1, h2c_parameter1);
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[BTCoex], FW2AntTDMA, write 0x14 = 0x%x\n", h2c_parameter[0]);
+	rtl8723ae_fill_h2c_cmd(hw, 0x14, 1, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_set_fw_ignore_wlan_act(struct ieee80211_hw *hw,
+						   bool enable)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	u8 h2c_parameter[1] = {0};
+
+	if (enable) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BTCoex], BT Ignore Wlan_Act !!\n");
+		h2c_parameter[0] |= BIT(0);		/* function enable */
+		rtlpcipriv->bt_coexist.fw_coexist_all_off = false;
+	} else {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BTCoex], BT don't ignore Wlan_Act !!\n");
+	}
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[BTCoex], set FW for BT Ignore Wlan_Act, write 0x25 = 0x%x\n",
+		 h2c_parameter[0]);
+
+	rtl8723ae_fill_h2c_cmd(hw, 0x25, 1, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_set_fw_tra_tdma_ctrl(struct ieee80211_hw *hw,
+						 bool enable, u8 ant_num,
+						 u8 nav_en)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 h2c_parameter[2] = {0};
+
+	/* Only 8723 B cut should do this */
+	if (IS_VENDOR_8723_A_CUT(rtlhal->version)) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BTCoex], not 8723B cut, don't set Traditional TDMA!!\n");
+		return;
+	}
+
+	if (enable) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BTCoex], turn TTDMA mode ON!!\n");
+		h2c_parameter[0] |= BIT(0);		/* function enable */
+		if (TDMA_1ANT == ant_num) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "[BTCoex], TTDMA_1ANT\n");
+			h2c_parameter[0] |= BIT(1);
+		} else if (TDMA_2ANT == ant_num) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "[BTCoex], TTDMA_2ANT\n");
+		} else {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "[BTCoex], Unknown Ant\n");
+		}
+
+		if (TDMA_NAV_OFF == nav_en) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "[BTCoex], TTDMA_NAV_OFF\n");
+		} else if (TDMA_NAV_ON == nav_en) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "[BTCoex], TTDMA_NAV_ON\n");
+			h2c_parameter[1] |= BIT(0);
+		}
+
+		rtlpcipriv->bt_coexist.fw_coexist_all_off = false;
+	} else {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BTCoex], turn TTDMA mode OFF!!\n");
+	}
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[BTCoex], FW Traditional TDMA, write 0x33 = 0x%x\n",
+		 h2c_parameter[0] << 8 | h2c_parameter[1]);
+
+	rtl8723ae_fill_h2c_cmd(hw, 0x33, 2, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_set_fw_dac_swing_level(struct ieee80211_hw *hw,
+						   u8 dac_swing_lvl)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 h2c_parameter[1] = {0};
+
+	h2c_parameter[0] = dac_swing_lvl;
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[BTCoex], Set Dac Swing Level = 0x%x\n", dac_swing_lvl);
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[BTCoex], write 0x29 = 0x%x\n", h2c_parameter[0]);
+
+	rtl8723ae_fill_h2c_cmd(hw, 0x29, 1, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_set_fw_bt_hid_info(struct ieee80211_hw *hw,
+					       bool enable)
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 h2c_parameter[1] = {0};
+
+	h2c_parameter[0] = 0;
+
+	if (enable) {
+		h2c_parameter[0] |= BIT(0);
+		rtlpcipriv->bt_coexist.fw_coexist_all_off = false;
+	}
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[BTCoex], Set BT HID information = 0x%x\n", enable);
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[BTCoex], write 0x24 = 0x%x\n", h2c_parameter[0]);
+
+	rtl8723ae_fill_h2c_cmd(hw, 0x24, 1, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_set_fw_bt_retry_index(struct ieee80211_hw *hw,
+						  u8 retry_index)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 h2c_parameter[1] = {0};
+
+	h2c_parameter[0] = retry_index;
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[BTCoex], Set BT Retry Index=%d\n", retry_index);
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[BTCoex], write 0x23 = 0x%x\n", h2c_parameter[0]);
+
+	rtl8723ae_fill_h2c_cmd(hw, 0x23, 1, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_set_fw_wlan_act(struct ieee80211_hw *hw,
+					    u8 wlan_act_hi, u8 wlan_act_lo)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 h2c_parameter_hi[1] = {0};
+	u8 h2c_parameter_lo[1] = {0};
+
+	h2c_parameter_hi[0] = wlan_act_hi;
+	h2c_parameter_lo[0] = wlan_act_lo;
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[BTCoex], Set WLAN_ACT Hi:Lo = 0x%x/0x%x\n", wlan_act_hi,
+		 wlan_act_lo);
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[BTCoex], write 0x22 = 0x%x\n", h2c_parameter_hi[0]);
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "[BTCoex], write 0x11 = 0x%x\n", h2c_parameter_lo[0]);
+
+	/* WLAN_ACT = High duration, unit:ms */
+	rtl8723ae_fill_h2c_cmd(hw, 0x22, 1, h2c_parameter_hi);
+	/*  WLAN_ACT = Low duration, unit:3*625us */
+	rtl8723ae_fill_h2c_cmd(hw, 0x11, 1, h2c_parameter_lo);
+}
+
+void rtl8723ae_dm_bt_set_bt_dm(struct ieee80211_hw *hw, struct btdm_8723 *btdm)
+{
+	struct rtl_pci_priv	*rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_priv	*rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	struct btdm_8723 *btdm_8723 = &rtlhal->hal_coex_8723.btdm;
+	u8 i;
+	bool fw_current_inpsmode = false;
+	bool fw_ps_awake = true;
+
+	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
+				      (u8 *)(&fw_current_inpsmode));
+	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
+				      (u8 *)(&fw_ps_awake));
+
+	/* check new setting is different than the old one,
+	 * if all the same, don't do the setting again.
+	 */
+	if (memcmp(btdm_8723, btdm, sizeof(struct btdm_8723)) == 0) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], the same coexist setting, return!!\n");
+		return;
+	} else {	/* save the new coexist setting */
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], UPDATE TO NEW COEX SETTING!!\n");
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new bAllOff = 0x%x/ 0x%x\n",
+			 btdm_8723->all_off, btdm->all_off);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new agc_table_en = 0x%x/ 0x%x\n",
+			 btdm_8723->agc_table_en, btdm->agc_table_en);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new adc_back_off_on = 0x%x/ 0x%x\n",
+			 btdm_8723->adc_back_off_on, btdm->adc_back_off_on);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new b2_ant_hid_en = 0x%x/ 0x%x\n",
+			 btdm_8723->b2_ant_hid_en, btdm->b2_ant_hid_en);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new bLowPenaltyRateAdaptive = 0x%x/ 0x%x\n",
+			 btdm_8723->low_penalty_rate_adaptive,
+			 btdm->low_penalty_rate_adaptive);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new bRfRxLpfShrink = 0x%x/ 0x%x\n",
+			 btdm_8723->rf_rx_lpf_shrink, btdm->rf_rx_lpf_shrink);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new bRejectAggrePkt = 0x%x/ 0x%x\n",
+			 btdm_8723->reject_aggre_pkt, btdm->reject_aggre_pkt);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new tdma_on = 0x%x/ 0x%x\n",
+			 btdm_8723->tdma_on, btdm->tdma_on);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new tdmaAnt = 0x%x/ 0x%x\n",
+			 btdm_8723->tdma_ant, btdm->tdma_ant);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new tdmaNav = 0x%x/ 0x%x\n",
+			 btdm_8723->tdma_nav, btdm->tdma_nav);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new tdma_dac_swing = 0x%x/ 0x%x\n",
+			 btdm_8723->tdma_dac_swing, btdm->tdma_dac_swing);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new fwDacSwingLvl = 0x%x/ 0x%x\n",
+			 btdm_8723->fw_dac_swing_lvl, btdm->fw_dac_swing_lvl);
+
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new bTraTdmaOn = 0x%x/ 0x%x\n",
+			 btdm_8723->tra_tdma_on, btdm->tra_tdma_on);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new traTdmaAnt = 0x%x/ 0x%x\n",
+			 btdm_8723->tra_tdma_ant, btdm->tra_tdma_ant);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new traTdmaNav = 0x%x/ 0x%x\n",
+			 btdm_8723->tra_tdma_nav, btdm->tra_tdma_nav);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new bPsTdmaOn = 0x%x/ 0x%x\n",
+			 btdm_8723->ps_tdma_on, btdm->ps_tdma_on);
+		for (i = 0; i < 5; i++) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "[BTCoex], original/new psTdmaByte[i] = 0x%x/ 0x%x\n",
+				 btdm_8723->ps_tdma_byte[i],
+				 btdm->ps_tdma_byte[i]);
+		}
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new bIgnoreWlanAct = 0x%x/ 0x%x\n",
+			 btdm_8723->ignore_wlan_act, btdm->ignore_wlan_act);
+
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new bPtaOn = 0x%x/ 0x%x\n",
+			 btdm_8723->pta_on, btdm->pta_on);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new val_0x6c0 = 0x%x/ 0x%x\n",
+			 btdm_8723->val_0x6c0, btdm->val_0x6c0);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new val_0x6c8 = 0x%x/ 0x%x\n",
+			 btdm_8723->val_0x6c8, btdm->val_0x6c8);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new val_0x6cc = 0x%x/ 0x%x\n",
+			 btdm_8723->val_0x6cc, btdm->val_0x6cc);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new sw_dac_swing_on = 0x%x/ 0x%x\n",
+			 btdm_8723->sw_dac_swing_on, btdm->sw_dac_swing_on);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new sw_dac_swing_lvl = 0x%x/ 0x%x\n",
+			 btdm_8723->sw_dac_swing_lvl,
+			 btdm->sw_dac_swing_lvl);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new wlanActHi = 0x%x/ 0x%x\n",
+			 btdm_8723->wlan_act_hi, btdm->wlan_act_hi);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new wlanActLo = 0x%x/ 0x%x\n",
+			 btdm_8723->wlan_act_lo, btdm->wlan_act_lo);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], original/new btRetryIndex = 0x%x/ 0x%x\n",
+			btdm_8723->bt_retry_index, btdm->bt_retry_index);
+
+		memcpy(btdm_8723, btdm, sizeof(struct btdm_8723));
+	}
+	/*
+	 * Here we only consider when Bt Operation
+	 * inquiry/paging/pairing is ON
+	 * we only need to turn off TDMA
+	 */
+
+	if (rtlpcipriv->bt_coexist.hold_for_bt_operation) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BTCoex], set to ignore wlanAct for BT OP!!\n");
+		rtl8723ae_dm_bt_set_fw_ignore_wlan_act(hw, true);
+		return;
+	}
+
+	if (btdm->all_off) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BTCoex], disable all coexist mechanism !!\n");
+		rtl8723ae_btdm_coex_all_off(hw);
+		return;
+	}
+
+	rtl8723ae_dm_bt_reject_ap_aggregated_packet(hw, btdm->reject_aggre_pkt);
+
+	if (btdm->low_penalty_rate_adaptive)
+		rtl8723ae_bt_set_penalty_tx_rate_adap(hw,
+			BT_TX_RATE_ADAPTIVE_LOW_PENALTY);
+	else
+		rtl8723ae_bt_set_penalty_tx_rate_adap(hw,
+			BT_TX_RATE_ADAPTIVE_NORMAL);
+
+	if (btdm->rf_rx_lpf_shrink)
+		rtl8723ae_dm_bt_set_sw_rf_rx_lpf_corner(hw,
+					 BT_RF_RX_LPF_CORNER_SHRINK);
+	else
+		rtl8723ae_dm_bt_set_sw_rf_rx_lpf_corner(hw,
+					 BT_RF_RX_LPF_CORNER_RESUME);
+
+	if (btdm->agc_table_en)
+		rtl8723ae_dm_bt_agc_table(hw, BT_AGCTABLE_ON);
+	else
+		rtl8723ae_dm_bt_agc_table(hw, BT_AGCTABLE_OFF);
+
+	if (btdm->adc_back_off_on)
+		rtl8723ae_dm_bt_bback_off_level(hw, BT_BB_BACKOFF_ON);
+	else
+		rtl8723ae_dm_bt_bback_off_level(hw, BT_BB_BACKOFF_OFF);
+
+	rtl8723ae_dm_bt_set_fw_bt_retry_index(hw, btdm->bt_retry_index);
+
+	rtl8723ae_dm_bt_set_fw_dac_swing_level(hw, btdm->fw_dac_swing_lvl);
+	rtl8723ae_dm_bt_set_fw_wlan_act(hw, btdm->wlan_act_hi,
+				       btdm->wlan_act_lo);
+
+	rtl8723ae_dm_bt_set_coex_table(hw, btdm->val_0x6c0,
+		btdm->val_0x6c8, btdm->val_0x6cc);
+	rtl8723ae_dm_bt_set_hw_pta_mode(hw, btdm->pta_on);
+
+	/* Note: There is a constraint between TDMA and 2AntHID
+	 * Only one of 2AntHid and tdma can be turned on
+	 * We should turn off those mechanisms first
+	 * and then turn on them on.
+	*/
+	if (btdm->b2_ant_hid_en) {
+		/* turn off tdma */
+		rtl8723ae_dm_bt_set_fw_tra_tdma_ctrl(hw, btdm->tra_tdma_on,
+						    btdm->tra_tdma_ant,
+						    btdm->tra_tdma_nav);
+		rtl8723ae_dm_bt_set_fw_tdma_ctrl(hw, false, btdm->tdma_ant,
+						btdm->tdma_nav,
+						btdm->tdma_dac_swing);
+
+		/* turn off Pstdma */
+		rtl8723ae_dm_bt_set_fw_ignore_wlan_act(hw,
+						      btdm->ignore_wlan_act);
+		/* Antenna control by PTA, 0x870 = 0x300. */
+		rtl8723ae_dm_bt_set_fw_3a(hw, 0x0, 0x0, 0x0, 0x8, 0x0);
+
+		/* turn on 2AntHid */
+		rtl8723ae_dm_bt_set_fw_bt_hid_info(hw, true);
+		rtl8723ae_dm_bt_set_fw_2_ant_hid(hw, true, true);
+	} else if (btdm->tdma_on) {
+		/* turn off 2AntHid */
+		rtl8723ae_dm_bt_set_fw_bt_hid_info(hw, false);
+		rtl8723ae_dm_bt_set_fw_2_ant_hid(hw, false, false);
+
+		/* turn off pstdma */
+		rtl8723ae_dm_bt_set_fw_ignore_wlan_act(hw,
+						      btdm->ignore_wlan_act);
+		/* Antenna control by PTA, 0x870 = 0x300. */
+		rtl8723ae_dm_bt_set_fw_3a(hw, 0x0, 0x0, 0x0, 0x8, 0x0);
+
+		/* turn on tdma */
+		rtl8723ae_dm_bt_set_fw_tra_tdma_ctrl(hw, btdm->tra_tdma_on,
+				 btdm->tra_tdma_ant, btdm->tra_tdma_nav);
+		rtl8723ae_dm_bt_set_fw_tdma_ctrl(hw, true, btdm->tdma_ant,
+				 btdm->tdma_nav, btdm->tdma_dac_swing);
+	} else if (btdm->ps_tdma_on) {
+		/* turn off 2AntHid */
+		rtl8723ae_dm_bt_set_fw_bt_hid_info(hw, false);
+		rtl8723ae_dm_bt_set_fw_2_ant_hid(hw, false, false);
+
+		/* turn off tdma */
+		rtl8723ae_dm_bt_set_fw_tra_tdma_ctrl(hw, btdm->tra_tdma_on,
+				 btdm->tra_tdma_ant, btdm->tra_tdma_nav);
+		rtl8723ae_dm_bt_set_fw_tdma_ctrl(hw, false, btdm->tdma_ant,
+				 btdm->tdma_nav, btdm->tdma_dac_swing);
+
+		/* turn on pstdma */
+		rtl8723ae_dm_bt_set_fw_ignore_wlan_act(hw,
+				 btdm->ignore_wlan_act);
+		rtl8723ae_dm_bt_set_fw_3a(hw,
+			btdm->ps_tdma_byte[0],
+			btdm->ps_tdma_byte[1],
+			btdm->ps_tdma_byte[2],
+			btdm->ps_tdma_byte[3],
+			btdm->ps_tdma_byte[4]);
+	} else {
+		/* turn off 2AntHid */
+		rtl8723ae_dm_bt_set_fw_bt_hid_info(hw, false);
+		rtl8723ae_dm_bt_set_fw_2_ant_hid(hw, false, false);
+
+		/* turn off tdma */
+		rtl8723ae_dm_bt_set_fw_tra_tdma_ctrl(hw, btdm->tra_tdma_on,
+				 btdm->tra_tdma_ant, btdm->tra_tdma_nav);
+		rtl8723ae_dm_bt_set_fw_tdma_ctrl(hw, false, btdm->tdma_ant,
+				 btdm->tdma_nav, btdm->tdma_dac_swing);
+
+		/* turn off pstdma */
+		rtl8723ae_dm_bt_set_fw_ignore_wlan_act(hw,
+						      btdm->ignore_wlan_act);
+		/* Antenna control by PTA, 0x870 = 0x300. */
+		rtl8723ae_dm_bt_set_fw_3a(hw, 0x0, 0x0, 0x0, 0x8, 0x0);
+	}
+
+	/* Note:
+	 * We should add delay for making sure sw DacSwing can be set
+	 *  sucessfully. Because of that rtl8723ae_dm_bt_set_fw_2_ant_hid()
+	 * and rtl8723ae_dm_bt_set_fw_tdma_ctrl()
+	 * will overwrite the reg 0x880.
+	*/
+	mdelay(30);
+	rtl8723ae_dm_bt_set_sw_full_time_dac_swing(hw,
+		btdm->sw_dac_swing_on, btdm->sw_dac_swing_lvl);
+	rtl8723ae_dm_bt_set_fw_dec_bt_pwr(hw, btdm->dec_bt_pwr);
+}
+
+/*============================================================
+ * extern function start with BTDM_
+ *============================================================
+ */
+static u32 rtl8723ae_dm_bt_tx_rx_couter_h(struct ieee80211_hw *hw)
+{
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u32 counters = 0;
+
+	counters = rtlhal->hal_coex_8723.high_priority_tx +
+		   rtlhal->hal_coex_8723.high_priority_rx;
+	return counters;
+}
+
+static u32 rtl8723ae_dm_bt_tx_rx_couter_l(struct ieee80211_hw *hw)
+{
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	return rtlhal->hal_coex_8723.low_priority_tx +
+	       rtlhal->hal_coex_8723.low_priority_rx;
+}
+
+static u8 rtl8723ae_dm_bt_bt_tx_rx_counter_level(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	u32 bt_tx_rx_cnt = 0;
+	u8 bt_tx_rx_cnt_lvl = 0;
+
+	bt_tx_rx_cnt = rtl8723ae_dm_bt_tx_rx_couter_h(hw) +
+		       rtl8723ae_dm_bt_tx_rx_couter_l(hw);
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+		 "[BTCoex], BT TxRx Counters = %d\n", bt_tx_rx_cnt);
+
+	rtlpcipriv->bt_coexist.cstate_h &=
+		 ~(BT_COEX_STATE_BT_CNT_LEVEL_0 | BT_COEX_STATE_BT_CNT_LEVEL_1 |
+		  BT_COEX_STATE_BT_CNT_LEVEL_2);
+
+	if (bt_tx_rx_cnt >= BT_TXRX_CNT_THRES_3) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], BT TxRx Counters at level 3\n");
+		bt_tx_rx_cnt_lvl = BT_TXRX_CNT_LEVEL_3;
+		rtlpcipriv->bt_coexist.cstate_h |= BT_COEX_STATE_BT_CNT_LEVEL_3;
+	} else if (bt_tx_rx_cnt >= BT_TXRX_CNT_THRES_2) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], BT TxRx Counters at level 2\n");
+		bt_tx_rx_cnt_lvl = BT_TXRX_CNT_LEVEL_2;
+		rtlpcipriv->bt_coexist.cstate_h |= BT_COEX_STATE_BT_CNT_LEVEL_2;
+	} else if (bt_tx_rx_cnt >= BT_TXRX_CNT_THRES_1) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], BT TxRx Counters at level 1\n");
+		bt_tx_rx_cnt_lvl = BT_TXRX_CNT_LEVEL_1;
+		rtlpcipriv->bt_coexist.cstate_h |= BT_COEX_STATE_BT_CNT_LEVEL_1;
+	} else {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], BT TxRx Counters at level 0\n");
+		bt_tx_rx_cnt_lvl = BT_TXRX_CNT_LEVEL_0;
+		rtlpcipriv->bt_coexist.cstate_h |= BT_COEX_STATE_BT_CNT_LEVEL_0;
+	}
+	return bt_tx_rx_cnt_lvl;
+}
+
+static void rtl8723ae_dm_bt_2_ant_hid_sco_esco(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct btdm_8723 btdm8723;
+	u8 bt_rssi_state, bt_rssi_state1;
+	u8 bt_tx_rx_cnt_lvl;
+
+	rtl8723ae_dm_bt_btdm_structure_reload(hw, &btdm8723);
+
+	btdm8723.rf_rx_lpf_shrink = true;
+	btdm8723.low_penalty_rate_adaptive = true;
+	btdm8723.reject_aggre_pkt = false;
+
+	bt_tx_rx_cnt_lvl = rtl8723ae_dm_bt_bt_tx_rx_counter_level(hw);
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+		 "[BTCoex], BT TxRx Counters = %d\n", bt_tx_rx_cnt_lvl);
+
+	if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, "HT40\n");
+		/* coex table */
+		btdm8723.val_0x6c0 = 0x55555555;
+		btdm8723.val_0x6c8 = 0xffff;
+		btdm8723.val_0x6cc = 0x3;
+
+		/* sw mechanism */
+		btdm8723.agc_table_en = false;
+		btdm8723.adc_back_off_on = false;
+		btdm8723.sw_dac_swing_on = false;
+
+		/* fw mechanism */
+		btdm8723.ps_tdma_on = true;
+		if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "[BTCoex], BT TxRx Counters >= 1400\n");
+			btdm8723.ps_tdma_byte[0] = 0xa3;
+			btdm8723.ps_tdma_byte[1] = 0x5;
+			btdm8723.ps_tdma_byte[2] = 0x5;
+			btdm8723.ps_tdma_byte[3] = 0x2;
+			btdm8723.ps_tdma_byte[4] = 0x80;
+		} else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n");
+			btdm8723.ps_tdma_byte[0] = 0xa3;
+			btdm8723.ps_tdma_byte[1] = 0xa;
+			btdm8723.ps_tdma_byte[2] = 0xa;
+			btdm8723.ps_tdma_byte[3] = 0x2;
+			btdm8723.ps_tdma_byte[4] = 0x80;
+		} else {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "[BTCoex], BT TxRx Counters < 1200\n");
+			btdm8723.ps_tdma_byte[0] = 0xa3;
+			btdm8723.ps_tdma_byte[1] = 0xf;
+			btdm8723.ps_tdma_byte[2] = 0xf;
+			btdm8723.ps_tdma_byte[3] = 0x2;
+			btdm8723.ps_tdma_byte[4] = 0x80;
+		}
+	} else {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "HT20 or Legacy\n");
+		bt_rssi_state = rtl8723ae_dm_bt_check_coex_rssi_state(hw, 2,
+								     47, 0);
+		bt_rssi_state1 = rtl8723ae_dm_bt_check_coex_rssi_state1(hw, 2,
+								       27, 0);
+
+		/* coex table */
+		btdm8723.val_0x6c0 = 0x55555555;
+		btdm8723.val_0x6c8 = 0xffff;
+		btdm8723.val_0x6cc = 0x3;
+
+		/* sw mechanism */
+		if ((bt_rssi_state == BT_RSSI_STATE_HIGH) ||
+		    (bt_rssi_state == BT_RSSI_STATE_STAY_HIGH)) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "Wifi rssi high\n");
+			btdm8723.agc_table_en = true;
+			btdm8723.adc_back_off_on = true;
+			btdm8723.sw_dac_swing_on = false;
+		} else {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "Wifi rssi low\n");
+			btdm8723.agc_table_en = false;
+			btdm8723.adc_back_off_on = false;
+			btdm8723.sw_dac_swing_on = false;
+		}
+
+		/* fw mechanism */
+		btdm8723.ps_tdma_on = true;
+		if ((bt_rssi_state1 == BT_RSSI_STATE_HIGH) ||
+		    (bt_rssi_state1 == BT_RSSI_STATE_STAY_HIGH)) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "Wifi rssi-1 high\n");
+			/* only rssi high we need to do this,
+			 * when rssi low, the value will modified by fw
+			 */
+			rtl_write_byte(rtlpriv, 0x883, 0x40);
+			if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters >= 1400\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0x5;
+				btdm8723.ps_tdma_byte[2] = 0x5;
+				btdm8723.ps_tdma_byte[3] = 0x83;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			} else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0xa;
+				btdm8723.ps_tdma_byte[2] = 0xa;
+				btdm8723.ps_tdma_byte[3] = 0x83;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			} else {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters < 1200\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0xf;
+				btdm8723.ps_tdma_byte[2] = 0xf;
+				btdm8723.ps_tdma_byte[3] = 0x83;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			}
+		} else {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "Wifi rssi-1 low\n");
+			if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters >= 1400\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0x5;
+				btdm8723.ps_tdma_byte[2] = 0x5;
+				btdm8723.ps_tdma_byte[3] = 0x2;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			} else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0xa;
+				btdm8723.ps_tdma_byte[2] = 0xa;
+				btdm8723.ps_tdma_byte[3] = 0x2;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			} else {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters < 1200\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0xf;
+				btdm8723.ps_tdma_byte[2] = 0xf;
+				btdm8723.ps_tdma_byte[3] = 0x2;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			}
+		}
+	}
+
+	if (rtl8723ae_dm_bt_need_to_dec_bt_pwr(hw))
+		btdm8723.dec_bt_pwr = true;
+
+	/* Always ignore WlanAct if bHid|bSCOBusy|bSCOeSCO */
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+		 "[BTCoex], BT btInqPageStartTime = 0x%x, btTxRxCntLvl = %d\n",
+		 rtlhal->hal_coex_8723.bt_inq_page_start_time,
+		 bt_tx_rx_cnt_lvl);
+	if ((rtlhal->hal_coex_8723.bt_inq_page_start_time) ||
+	    (BT_TXRX_CNT_LEVEL_3 == bt_tx_rx_cnt_lvl)) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], Set BT inquiry / page scan 0x3a setting\n");
+		btdm8723.ps_tdma_on = true;
+		btdm8723.ps_tdma_byte[0] = 0xa3;
+		btdm8723.ps_tdma_byte[1] = 0x5;
+		btdm8723.ps_tdma_byte[2] = 0x5;
+		btdm8723.ps_tdma_byte[3] = 0x2;
+		btdm8723.ps_tdma_byte[4] = 0x80;
+	}
+
+	if (rtl8723ae_dm_bt_is_coexist_state_changed(hw))
+		rtl8723ae_dm_bt_set_bt_dm(hw, &btdm8723);
+}
+
+static void rtl8723ae_dm_bt_2_ant_fta2dp(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct btdm_8723 btdm8723;
+	u8 bt_rssi_state, bt_rssi_state1;
+	u32 bt_tx_rx_cnt_lvl;
+
+	rtl8723ae_dm_bt_btdm_structure_reload(hw, &btdm8723);
+	btdm8723.rf_rx_lpf_shrink = true;
+	btdm8723.low_penalty_rate_adaptive = true;
+	btdm8723.reject_aggre_pkt = false;
+
+	bt_tx_rx_cnt_lvl = rtl8723ae_dm_bt_bt_tx_rx_counter_level(hw);
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+		 "[BTCoex], BT TxRx Counters = %d\n", bt_tx_rx_cnt_lvl);
+
+	if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, "HT40\n");
+		bt_rssi_state = rtl8723ae_dm_bt_check_coex_rssi_state(hw, 2,
+								     37, 0);
+
+		/* coex table */
+		btdm8723.val_0x6c0 = 0x55555555;
+		btdm8723.val_0x6c8 = 0xffff;
+		btdm8723.val_0x6cc = 0x3;
+
+		/* sw mechanism */
+		btdm8723.agc_table_en = false;
+		btdm8723.adc_back_off_on = true;
+		btdm8723.sw_dac_swing_on = false;
+
+		/* fw mechanism */
+		btdm8723.ps_tdma_on = true;
+		if ((bt_rssi_state == BT_RSSI_STATE_HIGH) ||
+		    (bt_rssi_state == BT_RSSI_STATE_STAY_HIGH)) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "Wifi rssi high\n");
+			if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters >= 1400\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0x5;
+				btdm8723.ps_tdma_byte[2] = 0x5;
+				btdm8723.ps_tdma_byte[3] = 0x81;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			} else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0xa;
+				btdm8723.ps_tdma_byte[2] = 0xa;
+				btdm8723.ps_tdma_byte[3] = 0x81;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			} else {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters < 1200\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0xf;
+				btdm8723.ps_tdma_byte[2] = 0xf;
+				btdm8723.ps_tdma_byte[3] = 0x81;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			}
+		} else {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "Wifi rssi low\n");
+			if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters >= 1400\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0x5;
+				btdm8723.ps_tdma_byte[2] = 0x5;
+				btdm8723.ps_tdma_byte[3] = 0x0;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			} else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0xa;
+				btdm8723.ps_tdma_byte[2] = 0xa;
+				btdm8723.ps_tdma_byte[3] = 0x0;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			} else {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters < 1200\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0xf;
+				btdm8723.ps_tdma_byte[2] = 0xf;
+				btdm8723.ps_tdma_byte[3] = 0x0;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			}
+		}
+	} else {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "HT20 or Legacy\n");
+		bt_rssi_state = rtl8723ae_dm_bt_check_coex_rssi_state(hw, 2,
+								     47, 0);
+		bt_rssi_state1 = rtl8723ae_dm_bt_check_coex_rssi_state1(hw, 2,
+								       27, 0);
+
+		/* coex table */
+		btdm8723.val_0x6c0 = 0x55555555;
+		btdm8723.val_0x6c8 = 0xffff;
+		btdm8723.val_0x6cc = 0x3;
+
+		/* sw mechanism */
+		if ((bt_rssi_state == BT_RSSI_STATE_HIGH) ||
+		    (bt_rssi_state == BT_RSSI_STATE_STAY_HIGH)) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "Wifi rssi high\n");
+			btdm8723.agc_table_en = true;
+			btdm8723.adc_back_off_on = true;
+			btdm8723.sw_dac_swing_on = false;
+		} else {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "Wifi rssi low\n");
+			btdm8723.agc_table_en = false;
+			btdm8723.adc_back_off_on = false;
+			btdm8723.sw_dac_swing_on = false;
+		}
+
+		/* fw mechanism */
+		btdm8723.ps_tdma_on = true;
+		if ((bt_rssi_state1 == BT_RSSI_STATE_HIGH) ||
+		    (bt_rssi_state1 == BT_RSSI_STATE_STAY_HIGH)) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "Wifi rssi-1 high\n");
+			/* only rssi high we need to do this,
+			 * when rssi low, the value will modified by fw
+			 */
+			rtl_write_byte(rtlpriv, 0x883, 0x40);
+			if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters >= 1400\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0x5;
+				btdm8723.ps_tdma_byte[2] = 0x5;
+				btdm8723.ps_tdma_byte[3] = 0x81;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			} else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0xa;
+				btdm8723.ps_tdma_byte[2] = 0xa;
+				btdm8723.ps_tdma_byte[3] = 0x81;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			} else {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters < 1200\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0xf;
+				btdm8723.ps_tdma_byte[2] = 0xf;
+				btdm8723.ps_tdma_byte[3] = 0x81;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			}
+		} else {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "Wifi rssi-1 low\n");
+			if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters >= 1400\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0x5;
+				btdm8723.ps_tdma_byte[2] = 0x5;
+				btdm8723.ps_tdma_byte[3] = 0x0;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			} else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0xa;
+				btdm8723.ps_tdma_byte[2] = 0xa;
+				btdm8723.ps_tdma_byte[3] = 0x0;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			} else {
+				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+					 "[BTCoex], BT TxRx Counters < 1200\n");
+				btdm8723.ps_tdma_byte[0] = 0xa3;
+				btdm8723.ps_tdma_byte[1] = 0xf;
+				btdm8723.ps_tdma_byte[2] = 0xf;
+				btdm8723.ps_tdma_byte[3] = 0x0;
+				btdm8723.ps_tdma_byte[4] = 0x80;
+			}
+		}
+	}
+
+	if (rtl8723ae_dm_bt_need_to_dec_bt_pwr(hw))
+		btdm8723.dec_bt_pwr = true;
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+		 "[BTCoex], BT btInqPageStartTime = 0x%x, btTxRxCntLvl = %d\n",
+		 rtlhal->hal_coex_8723.bt_inq_page_start_time,
+		 bt_tx_rx_cnt_lvl);
+
+	if ((rtlhal->hal_coex_8723.bt_inq_page_start_time) ||
+	    (BT_TXRX_CNT_LEVEL_3 == bt_tx_rx_cnt_lvl)) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], Set BT inquiry / page scan 0x3a setting\n");
+		btdm8723.ps_tdma_on = true;
+		btdm8723.ps_tdma_byte[0] = 0xa3;
+		btdm8723.ps_tdma_byte[1] = 0x5;
+		btdm8723.ps_tdma_byte[2] = 0x5;
+		btdm8723.ps_tdma_byte[3] = 0x83;
+		btdm8723.ps_tdma_byte[4] = 0x80;
+	}
+
+	if (rtl8723ae_dm_bt_is_coexist_state_changed(hw))
+		rtl8723ae_dm_bt_set_bt_dm(hw, &btdm8723);
+}
+
+static void rtl8723ae_dm_bt_inq_page_monitor(struct ieee80211_hw *hw)
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	u32 cur_time = jiffies;
+
+	if (rtlhal->hal_coex_8723.c2h_bt_inquiry_page) {
+		/* bt inquiry or page is started. */
+		if (rtlhal->hal_coex_8723.bt_inq_page_start_time == 0) {
+			rtlpcipriv->bt_coexist.cstate |=
+					 BT_COEX_STATE_BT_INQ_PAGE;
+			rtlhal->hal_coex_8723.bt_inq_page_start_time = cur_time;
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "[BTCoex], BT Inquiry/page is started at time : 0x%x\n",
+				 rtlhal->hal_coex_8723.bt_inq_page_start_time);
+		}
+	}
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+		 "[BTCoex], BT Inquiry/page started time : 0x%x, cur_time : 0x%x\n",
+		 rtlhal->hal_coex_8723.bt_inq_page_start_time, cur_time);
+
+	if (rtlhal->hal_coex_8723.bt_inq_page_start_time) {
+		if ((((long)cur_time -
+		    (long)rtlhal->hal_coex_8723.bt_inq_page_start_time) / HZ) >=
+		    10) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "[BTCoex], BT Inquiry/page >= 10sec!!!");
+			rtlhal->hal_coex_8723.bt_inq_page_start_time = 0;
+			rtlpcipriv->bt_coexist.cstate &=
+						 ~BT_COEX_STATE_BT_INQ_PAGE;
+		}
+	}
+}
+
+static void rtl8723ae_dm_bt_reset_action_profile_state(struct ieee80211_hw *hw)
+{
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+
+	rtlpcipriv->bt_coexist.cstate &=
+		~(BT_COEX_STATE_PROFILE_HID | BT_COEX_STATE_PROFILE_A2DP |
+		BT_COEX_STATE_PROFILE_PAN | BT_COEX_STATE_PROFILE_SCO);
+
+	rtlpcipriv->bt_coexist.cstate &=
+		~(BT_COEX_STATE_BTINFO_COMMON |
+		BT_COEX_STATE_BTINFO_B_HID_SCOESCO |
+		BT_COEX_STATE_BTINFO_B_FTP_A2DP);
+}
+
+static void _rtl8723ae_dm_bt_coexist_2_ant(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	u8 bt_retry_cnt;
+	u8 bt_info_original;
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+		 "[BTCoex] Get bt info by fw!!\n");
+
+	_rtl8723_dm_bt_check_wifi_state(hw);
+
+	if (rtlhal->hal_coex_8723.c2h_bt_info_req_sent) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "[BTCoex] c2h for btInfo not rcvd yet!!\n");
+	}
+
+	bt_retry_cnt = rtlhal->hal_coex_8723.bt_retry_cnt;
+	bt_info_original = rtlhal->hal_coex_8723.c2h_bt_info_original;
+
+	/* when bt inquiry or page scan, we have to set h2c 0x25
+	 * ignore wlanact for continuous 4x2secs
+	 */
+	rtl8723ae_dm_bt_inq_page_monitor(hw);
+	rtl8723ae_dm_bt_reset_action_profile_state(hw);
+
+	if (rtl8723ae_dm_bt_is_2_ant_common_action(hw)) {
+		rtlpcipriv->bt_coexist.bt_profile_case = BT_COEX_MECH_COMMON;
+		rtlpcipriv->bt_coexist.bt_profile_action = BT_COEX_MECH_COMMON;
+
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "Action 2-Ant common.\n");
+	} else {
+		if ((bt_info_original & BTINFO_B_HID) ||
+		    (bt_info_original & BTINFO_B_SCO_BUSY) ||
+		    (bt_info_original & BTINFO_B_SCO_ESCO)) {
+			rtlpcipriv->bt_coexist.cstate |=
+					BT_COEX_STATE_BTINFO_B_HID_SCOESCO;
+			rtlpcipriv->bt_coexist.bt_profile_case =
+					BT_COEX_MECH_HID_SCO_ESCO;
+			rtlpcipriv->bt_coexist.bt_profile_action =
+					BT_COEX_MECH_HID_SCO_ESCO;
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "[BTCoex], BTInfo: bHid|bSCOBusy|bSCOeSCO\n");
+			rtl8723ae_dm_bt_2_ant_hid_sco_esco(hw);
+		} else if ((bt_info_original & BTINFO_B_FTP) ||
+			   (bt_info_original & BTINFO_B_A2DP)) {
+			rtlpcipriv->bt_coexist.cstate |=
+					BT_COEX_STATE_BTINFO_B_FTP_A2DP;
+			rtlpcipriv->bt_coexist.bt_profile_case =
+					BT_COEX_MECH_FTP_A2DP;
+			rtlpcipriv->bt_coexist.bt_profile_action =
+					BT_COEX_MECH_FTP_A2DP;
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "BTInfo: bFTP|bA2DP\n");
+			rtl8723ae_dm_bt_2_ant_fta2dp(hw);
+		} else {
+			rtlpcipriv->bt_coexist.cstate |=
+					 BT_COEX_STATE_BTINFO_B_HID_SCOESCO;
+			rtlpcipriv->bt_coexist.bt_profile_case =
+					 BT_COEX_MECH_NONE;
+			rtlpcipriv->bt_coexist.bt_profile_action =
+					 BT_COEX_MECH_NONE;
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+				 "[BTCoex], BTInfo: undefined case!!!!\n");
+			rtl8723ae_dm_bt_2_ant_hid_sco_esco(hw);
+		}
+	}
+}
+
+static void _rtl8723ae_dm_bt_coexist_1_ant(struct ieee80211_hw *hw)
+{
+}
+
+void rtl8723ae_dm_bt_hw_coex_all_off_8723a(struct ieee80211_hw *hw)
+{
+	rtl8723ae_dm_bt_set_coex_table(hw, 0x5a5aaaaa, 0xcc, 0x3);
+	rtl8723ae_dm_bt_set_hw_pta_mode(hw, true);
+}
+
+void rtl8723ae_dm_bt_fw_coex_all_off_8723a(struct ieee80211_hw *hw)
+{
+	rtl8723ae_dm_bt_set_fw_ignore_wlan_act(hw, false);
+	rtl8723ae_dm_bt_set_fw_3a(hw, 0x0, 0x0, 0x0, 0x8, 0x0);
+	rtl8723ae_dm_bt_set_fw_2_ant_hid(hw, false, false);
+	rtl8723ae_dm_bt_set_fw_tra_tdma_ctrl(hw, false,
+					     TDMA_2ANT, TDMA_NAV_OFF);
+	rtl8723ae_dm_bt_set_fw_tdma_ctrl(hw, false, TDMA_2ANT,
+				TDMA_NAV_OFF, TDMA_DAC_SWING_OFF);
+	rtl8723ae_dm_bt_set_fw_dac_swing_level(hw, 0);
+	rtl8723ae_dm_bt_set_fw_bt_hid_info(hw, false);
+	rtl8723ae_dm_bt_set_fw_bt_retry_index(hw, 2);
+	rtl8723ae_dm_bt_set_fw_wlan_act(hw, 0x10, 0x10);
+	rtl8723ae_dm_bt_set_fw_dec_bt_pwr(hw, false);
+}
+
+void rtl8723ae_dm_bt_sw_coex_all_off_8723a(struct ieee80211_hw *hw)
+{
+	rtl8723ae_dm_bt_agc_table(hw, BT_AGCTABLE_OFF);
+	rtl8723ae_dm_bt_bback_off_level(hw, BT_BB_BACKOFF_OFF);
+	rtl8723ae_dm_bt_reject_ap_aggregated_packet(hw, false);
+
+	rtl8723ae_bt_set_penalty_tx_rate_adap(hw, BT_TX_RATE_ADAPTIVE_NORMAL);
+	rtl8723ae_dm_bt_set_sw_rf_rx_lpf_corner(hw, BT_RF_RX_LPF_CORNER_RESUME);
+	rtl8723ae_dm_bt_set_sw_full_time_dac_swing(hw, false, 0xc0);
+}
+
+static void rtl8723ae_dm_bt_query_bt_information(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	u8 h2c_parameter[1] = {0};
+
+	rtlhal->hal_coex_8723.c2h_bt_info_req_sent = true;
+
+	h2c_parameter[0] |=  BIT(0);
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "Query Bt information, write 0x38 = 0x%x\n",
+		 h2c_parameter[0]);
+
+	rtl8723ae_fill_h2c_cmd(hw, 0x38, 1, h2c_parameter);
+}
+
+static void rtl8723ae_dm_bt_bt_hw_counters_monitor(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	u32 reg_htx_rx, reg_ltx_rx, u32_tmp;
+	u32 reg_htx, reg_hrx, reg_ltx, reg_lrx;
+
+	reg_htx_rx = REG_HIGH_PRIORITY_TXRX;
+	reg_ltx_rx = REG_LOW_PRIORITY_TXRX;
+
+	u32_tmp = rtl_read_dword(rtlpriv, reg_htx_rx);
+	reg_htx = u32_tmp & MASKLWORD;
+	reg_hrx = (u32_tmp & MASKHWORD)>>16;
+
+	u32_tmp = rtl_read_dword(rtlpriv, reg_ltx_rx);
+	reg_ltx = u32_tmp & MASKLWORD;
+	reg_lrx = (u32_tmp & MASKHWORD)>>16;
+
+	if (rtlpcipriv->bt_coexist.lps_counter > 1) {
+		reg_htx %= rtlpcipriv->bt_coexist.lps_counter;
+		reg_hrx %= rtlpcipriv->bt_coexist.lps_counter;
+		reg_ltx %= rtlpcipriv->bt_coexist.lps_counter;
+		reg_lrx %= rtlpcipriv->bt_coexist.lps_counter;
+	}
+
+	rtlhal->hal_coex_8723.high_priority_tx = reg_htx;
+	rtlhal->hal_coex_8723.high_priority_rx = reg_hrx;
+	rtlhal->hal_coex_8723.low_priority_tx = reg_ltx;
+	rtlhal->hal_coex_8723.low_priority_rx = reg_lrx;
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+		 "High Priority Tx/Rx (reg 0x%x)=%x(%d)/%x(%d)\n",
+		 reg_htx_rx, reg_htx, reg_htx, reg_hrx, reg_hrx);
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+		 "Low Priority Tx/Rx (reg 0x%x)=%x(%d)/%x(%d)\n",
+		 reg_ltx_rx, reg_ltx, reg_ltx, reg_lrx, reg_lrx);
+	rtlpcipriv->bt_coexist.lps_counter = 0;
+}
+
+static void rtl8723ae_dm_bt_bt_enable_disable_check(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	bool bt_alife = true;
+
+	if (rtlhal->hal_coex_8723.high_priority_tx == 0 &&
+	    rtlhal->hal_coex_8723.high_priority_rx == 0 &&
+	    rtlhal->hal_coex_8723.low_priority_tx == 0 &&
+	    rtlhal->hal_coex_8723.low_priority_rx == 0)
+		bt_alife = false;
+	if (rtlhal->hal_coex_8723.high_priority_tx == 0xeaea &&
+	    rtlhal->hal_coex_8723.high_priority_rx == 0xeaea &&
+	    rtlhal->hal_coex_8723.low_priority_tx == 0xeaea &&
+	    rtlhal->hal_coex_8723.low_priority_rx == 0xeaea)
+		bt_alife = false;
+	if (rtlhal->hal_coex_8723.high_priority_tx == 0xffff &&
+	    rtlhal->hal_coex_8723.high_priority_rx == 0xffff &&
+	    rtlhal->hal_coex_8723.low_priority_tx == 0xffff &&
+	    rtlhal->hal_coex_8723.low_priority_rx == 0xffff)
+		bt_alife = false;
+	if (bt_alife) {
+		rtlpcipriv->bt_coexist.bt_active_zero_cnt = 0;
+		rtlpcipriv->bt_coexist.cur_bt_disabled = false;
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "8723A BT is enabled !!\n");
+	} else {
+		rtlpcipriv->bt_coexist.bt_active_zero_cnt++;
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "8723A bt all counters = 0, %d times!!\n",
+			 rtlpcipriv->bt_coexist.bt_active_zero_cnt);
+		if (rtlpcipriv->bt_coexist.bt_active_zero_cnt >= 2) {
+			rtlpcipriv->bt_coexist.cur_bt_disabled = true;
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "8723A BT is disabled !!\n");
+		}
+	}
+	if (rtlpcipriv->bt_coexist.pre_bt_disabled !=
+		rtlpcipriv->bt_coexist.cur_bt_disabled) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "8723A BT is from %s to %s!!\n",
+			 (rtlpcipriv->bt_coexist.pre_bt_disabled ?
+			 "disabled" : "enabled"),
+			 (rtlpcipriv->bt_coexist.cur_bt_disabled ?
+			 "disabled" : "enabled"));
+		rtlpcipriv->bt_coexist.pre_bt_disabled
+			= rtlpcipriv->bt_coexist.cur_bt_disabled;
+	}
+}
+
+
+void rtl8723ae_dm_bt_coexist_8723(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+
+	rtl8723ae_dm_bt_query_bt_information(hw);
+	rtl8723ae_dm_bt_bt_hw_counters_monitor(hw);
+	rtl8723ae_dm_bt_bt_enable_disable_check(hw);
+
+	if (rtlpcipriv->bt_coexist.bt_ant_num == ANT_X2) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], 2 Ant mechanism\n");
+		_rtl8723ae_dm_bt_coexist_2_ant(hw);
+	} else {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "[BTCoex], 1 Ant mechanism\n");
+		_rtl8723ae_dm_bt_coexist_1_ant(hw);
+	}
+
+	if (!rtl8723ae_dm_bt_is_same_coexist_state(hw)) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTCoex], Coexist State[bitMap] change from 0x%x%8x to 0x%x%8x\n",
+			 rtlpcipriv->bt_coexist.previous_state_h,
+			 rtlpcipriv->bt_coexist.previous_state,
+			 rtlpcipriv->bt_coexist.cstate_h,
+			 rtlpcipriv->bt_coexist.cstate);
+		rtlpcipriv->bt_coexist.previous_state
+			= rtlpcipriv->bt_coexist.cstate;
+		rtlpcipriv->bt_coexist.previous_state_h
+			= rtlpcipriv->bt_coexist.cstate_h;
+	}
+}
+
+static void rtl8723ae_dm_bt_parse_bt_info(struct ieee80211_hw *hw,
+					  u8 *tmbuf, u8 len)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
+	u8 bt_info;
+	u8 i;
+
+	rtlhal->hal_coex_8723.c2h_bt_info_req_sent = false;
+	rtlhal->hal_coex_8723.bt_retry_cnt = 0;
+	for (i = 0; i < len; i++) {
+		if (i == 0)
+			rtlhal->hal_coex_8723.c2h_bt_info_original = tmbuf[i];
+		else if (i == 1)
+			rtlhal->hal_coex_8723.bt_retry_cnt = tmbuf[i];
+		if (i == len-1) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "0x%2x]", tmbuf[i]);
+		} else {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "0x%2x, ", tmbuf[i]);
+		}
+	}
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+		 "BT info bt_info (Data)= 0x%x\n",
+		 rtlhal->hal_coex_8723.c2h_bt_info_original);
+	bt_info = rtlhal->hal_coex_8723.c2h_bt_info_original;
+
+	if (bt_info & BIT(2))
+		rtlhal->hal_coex_8723.c2h_bt_inquiry_page = true;
+	else
+		rtlhal->hal_coex_8723.c2h_bt_inquiry_page = false;
+
+	if (bt_info & BTINFO_B_CONNECTION) {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTC2H], BTInfo: bConnect=true\n");
+		rtlpcipriv->bt_coexist.bt_busy = true;
+		rtlpcipriv->bt_coexist.cstate &= ~BT_COEX_STATE_BT_IDLE;
+	} else {
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+			 "[BTC2H], BTInfo: bConnect=false\n");
+		rtlpcipriv->bt_coexist.bt_busy = false;
+		rtlpcipriv->bt_coexist.cstate |= BT_COEX_STATE_BT_IDLE;
+	}
+}
+void rtl_8723e_c2h_command_handle(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct c2h_evt_hdr c2h_event;
+	u8 *ptmbuf;
+	u8 index;
+	u8 u1tmp;
+
+	memset(&c2h_event, 0, sizeof(c2h_event));
+	u1tmp = rtl_read_byte(rtlpriv, REG_C2HEVT_MSG_NORMAL);
+	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+		 "&&&&&&: REG_C2HEVT_MSG_NORMAL is 0x%x\n", u1tmp);
+	c2h_event.cmd_id = u1tmp & 0xF;
+	c2h_event.cmd_len = (u1tmp & 0xF0) >> 4;
+	c2h_event.cmd_seq = rtl_read_byte(rtlpriv, REG_C2HEVT_MSG_NORMAL + 1);
+	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+		 "cmd_id: %d, cmd_len: %d, cmd_seq: %d\n",
+		 c2h_event.cmd_id , c2h_event.cmd_len, c2h_event.cmd_seq);
+	u1tmp = rtl_read_byte(rtlpriv, 0x01AF);
+	if (u1tmp == C2H_EVT_HOST_CLOSE) {
+		return;
+	} else if (u1tmp != C2H_EVT_FW_CLOSE) {
+		rtl_write_byte(rtlpriv, 0x1AF, 0x00);
+		return;
+	}
+	ptmbuf = kmalloc(c2h_event.cmd_len, GFP_KERNEL);
+	if (ptmbuf == NULL) {
+		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+			 "malloc cmd buf failed\n");
+		return;
+	}
+
+	/* Read the content */
+	for (index = 0; index < c2h_event.cmd_len; index++)
+		ptmbuf[index] = rtl_read_byte(rtlpriv, REG_C2HEVT_MSG_NORMAL +
+				  2 + index);
+
+	switch (c2h_event.cmd_id) {
+	case C2H_BT_RSSI:
+		break;
+
+	case C2H_BT_OP_MODE:
+			break;
+
+	case BT_INFO:
+		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+			 "BT info Byte[0] (ID) is 0x%x\n", c2h_event.cmd_id);
+		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+			 "BT info Byte[1] (Seq) is 0x%x\n", c2h_event.cmd_seq);
+		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+			 "BT info Byte[2] (Data)= 0x%x\n", ptmbuf[0]);
+
+		rtl8723ae_dm_bt_parse_bt_info(hw, ptmbuf, c2h_event.cmd_len);
+		break;
+	default:
+		break;
+	}
+	kfree(ptmbuf);
+
+	rtl_write_byte(rtlpriv, 0x01AF, C2H_EVT_HOST_CLOSE);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h
new file mode 100644
index 0000000..4325ecd
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h
@@ -0,0 +1,151 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ ****************************************************************************
+ */
+
+#ifndef __RTL8723E_HAL_BTC_H__
+#define __RTL8723E_HAL_BTC_H__
+
+#include "../wifi.h"
+#include "btc.h"
+#include "hal_bt_coexist.h"
+
+#define	BT_TXRX_CNT_THRES_1		1200
+#define	BT_TXRX_CNT_THRES_2		1400
+#define	BT_TXRX_CNT_THRES_3		3000
+#define	BT_TXRX_CNT_LEVEL_0		0	/* < 1200 */
+#define	BT_TXRX_CNT_LEVEL_1		1	/* >= 1200 && < 1400 */
+#define	BT_TXRX_CNT_LEVEL_2		2	/* >= 1400 */
+#define	BT_TXRX_CNT_LEVEL_3		3
+
+/* TDMA mode definition */
+#define	TDMA_2ANT		0
+#define	TDMA_1ANT		1
+#define	TDMA_NAV_OFF		0
+#define	TDMA_NAV_ON		1
+#define	TDMA_DAC_SWING_OFF	0
+#define	TDMA_DAC_SWING_ON	1
+
+/* PTA mode related definition */
+#define	BT_PTA_MODE_OFF		0
+#define	BT_PTA_MODE_ON		1
+
+/* Penalty Tx Rate Adaptive */
+#define	BT_TX_RATE_ADAPTIVE_NORMAL	0
+#define	BT_TX_RATE_ADAPTIVE_LOW_PENALTY	1
+
+/* RF Corner */
+#define	BT_RF_RX_LPF_CORNER_RESUME	0
+#define	BT_RF_RX_LPF_CORNER_SHRINK	1
+
+#define C2H_EVT_HOST_CLOSE		0x00
+#define C2H_EVT_FW_CLOSE		0xFF
+
+enum bt_traffic_mode {
+	BT_MOTOR_EXT_BE = 0x00,
+	BT_MOTOR_EXT_GUL = 0x01,
+	BT_MOTOR_EXT_GUB = 0x02,
+	BT_MOTOR_EXT_GULB = 0x03
+};
+
+enum bt_traffic_mode_profile {
+	BT_PROFILE_NONE,
+	BT_PROFILE_A2DP,
+	BT_PROFILE_PAN,
+	BT_PROFILE_HID,
+	BT_PROFILE_SCO
+};
+
+enum hci_ext_bt_operation {
+	HCI_BT_OP_NONE = 0x0,
+	HCI_BT_OP_INQUIRE_START	= 0x1,
+	HCI_BT_OP_INQUIRE_FINISH = 0x2,
+	HCI_BT_OP_PAGING_START = 0x3,
+	HCI_BT_OP_PAGING_SUCCESS = 0x4,
+	HCI_BT_OP_PAGING_UNSUCCESS = 0x5,
+	HCI_BT_OP_PAIRING_START = 0x6,
+	HCI_BT_OP_PAIRING_FINISH = 0x7,
+	HCI_BT_OP_BT_DEV_ENABLE = 0x8,
+	HCI_BT_OP_BT_DEV_DISABLE = 0x9,
+	HCI_BT_OP_MAX,
+};
+
+enum bt_spec {
+	BT_SPEC_1_0_b = 0x00,
+	BT_SPEC_1_1 = 0x01,
+	BT_SPEC_1_2 = 0x02,
+	BT_SPEC_2_0_EDR = 0x03,
+	BT_SPEC_2_1_EDR = 0x04,
+	BT_SPEC_3_0_HS = 0x05,
+	BT_SPEC_4_0 = 0x06
+};
+
+struct c2h_evt_hdr {
+	u8 cmd_id;
+	u8 cmd_len;
+	u8 cmd_seq;
+};
+
+enum bt_state {
+	BT_INFO_STATE_DISABLED = 0,
+	BT_INFO_STATE_NO_CONNECTION = 1,
+	BT_INFO_STATE_CONNECT_IDLE = 2,
+	BT_INFO_STATE_INQ_OR_PAG = 3,
+	BT_INFO_STATE_ACL_ONLY_BUSY = 4,
+	BT_INFO_STATE_SCO_ONLY_BUSY = 5,
+	BT_INFO_STATE_ACL_SCO_BUSY = 6,
+	BT_INFO_STATE_HID_BUSY = 7,
+	BT_INFO_STATE_HID_SCO_BUSY = 8,
+	BT_INFO_STATE_MAX = 7
+};
+
+enum rtl8723ae_c2h_evt {
+	C2H_DBG = 0,
+	C2H_TSF = 1,
+	C2H_AP_RPT_RSP = 2,
+	C2H_CCX_TX_RPT = 3,	/* The FW notify the report of the specific */
+				/* tx packet. */
+	C2H_BT_RSSI = 4,
+	C2H_BT_OP_MODE = 5,
+	C2H_HW_INFO_EXCH = 10,
+	C2H_C2H_H2C_TEST = 11,
+	BT_INFO = 12,
+	MAX_C2HEVENT
+};
+
+void rtl8723ae_dm_bt_fw_coex_all_off_8723a(struct ieee80211_hw *hw);
+void rtl8723ae_dm_bt_sw_coex_all_off_8723a(struct ieee80211_hw *hw);
+void rtl8723ae_dm_bt_hw_coex_all_off_8723a(struct ieee80211_hw *hw);
+void rtl8723ae_dm_bt_coexist_8723(struct ieee80211_hw *hw);
+void rtl8723ae_dm_bt_set_bt_dm(struct ieee80211_hw *hw,
+			      struct btdm_8723 *p_btdm);
+void rtl_8723e_c2h_command_handle(struct ieee80211_hw *hw);
+void rtl_8723e_bt_wifi_media_status_notify(struct ieee80211_hw *hw,
+					   bool mstatus);
+void rtl8723ae_bt_coex_off_before_lps(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
new file mode 100644
index 0000000..0a8c038
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
@@ -0,0 +1,2380 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../efuse.h"
+#include "../base.h"
+#include "../regd.h"
+#include "../cam.h"
+#include "../ps.h"
+#include "../pci.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+#include "fw.h"
+#include "led.h"
+#include "hw.h"
+#include "pwrseqcmd.h"
+#include "pwrseq.h"
+#include "btc.h"
+
+static void _rtl8723ae_set_bcn_ctrl_reg(struct ieee80211_hw *hw,
+					u8 set_bits, u8 clear_bits)
+{
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpci->reg_bcn_ctrl_val |= set_bits;
+	rtlpci->reg_bcn_ctrl_val &= ~clear_bits;
+
+	rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val);
+}
+
+static void _rtl8723ae_stop_tx_beacon(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 tmp1byte;
+
+	tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
+	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6)));
+	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64);
+	tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2);
+	tmp1byte &= ~(BIT(0));
+	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte);
+}
+
+static void _rtl8723ae_resume_tx_beacon(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 tmp1byte;
+
+	tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
+	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6));
+	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff);
+	tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2);
+	tmp1byte |= BIT(1);
+	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte);
+}
+
+static void _rtl8723ae_enable_bcn_sufunc(struct ieee80211_hw *hw)
+{
+	_rtl8723ae_set_bcn_ctrl_reg(hw, 0, BIT(1));
+}
+
+static void _rtl8723ae_disable_bcn_sufunc(struct ieee80211_hw *hw)
+{
+	_rtl8723ae_set_bcn_ctrl_reg(hw, BIT(1), 0);
+}
+
+void rtl8723ae_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+	switch (variable) {
+	case HW_VAR_RCR:
+		*((u32 *) (val)) = rtlpci->receive_config;
+		break;
+	case HW_VAR_RF_STATE:
+		*((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state;
+		break;
+	case HW_VAR_FWLPS_RF_ON:{
+		enum rf_pwrstate rfState;
+		u32 val_rcr;
+
+		rtlpriv->cfg->ops->get_hw_reg(hw,
+					      HW_VAR_RF_STATE,
+					      (u8 *) (&rfState));
+		if (rfState == ERFOFF) {
+			*((bool *) (val)) = true;
+		} else {
+			val_rcr = rtl_read_dword(rtlpriv, REG_RCR);
+			val_rcr &= 0x00070000;
+			if (val_rcr)
+				*((bool *) (val)) = false;
+			else
+				*((bool *) (val)) = true;
+		}
+		break; }
+	case HW_VAR_FW_PSMODE_STATUS:
+		*((bool *) (val)) = ppsc->fw_current_inpsmode;
+		break;
+	case HW_VAR_CORRECT_TSF:{
+		u64 tsf;
+		u32 *ptsf_low = (u32 *)&tsf;
+		u32 *ptsf_high = ((u32 *)&tsf) + 1;
+
+		*ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4));
+		*ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
+
+		*((u64 *) (val)) = tsf;
+
+		break; }
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "switch case not process\n");
+		break;
+	}
+}
+
+void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	u8 idx;
+
+	switch (variable) {
+	case HW_VAR_ETHER_ADDR:
+		for (idx = 0; idx < ETH_ALEN; idx++) {
+			rtl_write_byte(rtlpriv, (REG_MACID + idx),
+				       val[idx]);
+		}
+		break;
+	case HW_VAR_BASIC_RATE:{
+		u16 rate_cfg = ((u16 *) val)[0];
+		u8 rate_index = 0;
+		rate_cfg = rate_cfg & 0x15f;
+		rate_cfg |= 0x01;
+		rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff);
+		rtl_write_byte(rtlpriv, REG_RRSR + 1,
+			       (rate_cfg >> 8) & 0xff);
+		while (rate_cfg > 0x1) {
+			rate_cfg = (rate_cfg >> 1);
+			rate_index++;
+		}
+		rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL,
+			       rate_index);
+		break; }
+	case HW_VAR_BSSID:
+		for (idx = 0; idx < ETH_ALEN; idx++) {
+			rtl_write_byte(rtlpriv, (REG_BSSID + idx),
+				       val[idx]);
+		}
+		break;
+	case HW_VAR_SIFS:
+		rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]);
+		rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]);
+
+		rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]);
+		rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]);
+
+		if (!mac->ht_enable)
+			rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM,
+				       0x0e0e);
+		else
+			rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM,
+				       *((u16 *) val));
+		break;
+	case HW_VAR_SLOT_TIME:{
+		u8 e_aci;
+
+		RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+			 "HW_VAR_SLOT_TIME %x\n", val[0]);
+
+		rtl_write_byte(rtlpriv, REG_SLOT, val[0]);
+
+		for (e_aci = 0; e_aci < AC_MAX; e_aci++) {
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+						      HW_VAR_AC_PARAM,
+						      (u8 *) (&e_aci));
+		}
+		break; }
+	case HW_VAR_ACK_PREAMBLE:{
+		u8 reg_tmp;
+		u8 short_preamble = (bool) (*(u8 *) val);
+		reg_tmp = (mac->cur_40_prime_sc) << 5;
+		if (short_preamble)
+			reg_tmp |= 0x80;
+
+		rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp);
+		break; }
+	case HW_VAR_AMPDU_MIN_SPACE:{
+		u8 min_spacing_to_set;
+		u8 sec_min_space;
+
+		min_spacing_to_set = *((u8 *) val);
+		if (min_spacing_to_set <= 7) {
+			sec_min_space = 0;
+
+			if (min_spacing_to_set < sec_min_space)
+				min_spacing_to_set = sec_min_space;
+
+			mac->min_space_cfg = ((mac->min_space_cfg &
+					       0xf8) |
+					      min_spacing_to_set);
+
+			*val = min_spacing_to_set;
+
+			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+				 "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n",
+				  mac->min_space_cfg);
+
+			rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE,
+				       mac->min_space_cfg);
+		}
+		break; }
+	case HW_VAR_SHORTGI_DENSITY:{
+		u8 density_to_set;
+
+		density_to_set = *((u8 *) val);
+		mac->min_space_cfg |= (density_to_set << 3);
+
+		RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+			 "Set HW_VAR_SHORTGI_DENSITY: %#x\n",
+			 mac->min_space_cfg);
+
+		rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE,
+			       mac->min_space_cfg);
+
+		break; }
+	case HW_VAR_AMPDU_FACTOR:{
+		u8 regtoset_normal[4] = {0x41, 0xa8, 0x72, 0xb9};
+		u8 regtoset_bt[4] = {0x31, 0x74, 0x42, 0x97};
+		u8 factor_toset;
+		u8 *p_regtoset = NULL;
+		u8 index;
+
+		if ((pcipriv->bt_coexist.bt_coexistence) &&
+		    (pcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4))
+			p_regtoset = regtoset_bt;
+		else
+			p_regtoset = regtoset_normal;
+
+		factor_toset = *((u8 *) val);
+		if (factor_toset <= 3) {
+			factor_toset = (1 << (factor_toset + 2));
+			if (factor_toset > 0xf)
+				factor_toset = 0xf;
+
+			for (index = 0; index < 4; index++) {
+				if ((p_regtoset[index] & 0xf0) >
+				    (factor_toset << 4))
+					p_regtoset[index] =
+					    (p_regtoset[index] & 0x0f) |
+					    (factor_toset << 4);
+
+				if ((p_regtoset[index] & 0x0f) >
+				    factor_toset)
+					p_regtoset[index] =
+					    (p_regtoset[index] & 0xf0) |
+					    (factor_toset);
+
+				rtl_write_byte(rtlpriv,
+					       (REG_AGGLEN_LMT + index),
+					       p_regtoset[index]);
+
+			}
+
+			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+				 "Set HW_VAR_AMPDU_FACTOR: %#x\n",
+				 factor_toset);
+		}
+		break; }
+	case HW_VAR_AC_PARAM:{
+		u8 e_aci = *((u8 *) val);
+		rtl8723ae_dm_init_edca_turbo(hw);
+
+		if (rtlpci->acm_method != eAcmWay2_SW)
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+						      HW_VAR_ACM_CTRL,
+						      (u8 *) (&e_aci));
+		break; }
+	case HW_VAR_ACM_CTRL:{
+		u8 e_aci = *((u8 *) val);
+		union aci_aifsn *p_aci_aifsn =
+		    (union aci_aifsn *)(&(mac->ac[0].aifs));
+		u8 acm = p_aci_aifsn->f.acm;
+		u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL);
+
+		acm_ctrl |= ((rtlpci->acm_method == 2) ? 0x0 : 0x1);
+
+		if (acm) {
+			switch (e_aci) {
+			case AC0_BE:
+				acm_ctrl |= AcmHw_BeqEn;
+				break;
+			case AC2_VI:
+				acm_ctrl |= AcmHw_ViqEn;
+				break;
+			case AC3_VO:
+				acm_ctrl |= AcmHw_VoqEn;
+				break;
+			default:
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+					 "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n",
+					 acm);
+				break;
+			}
+		} else {
+			switch (e_aci) {
+			case AC0_BE:
+				acm_ctrl &= (~AcmHw_BeqEn);
+				break;
+			case AC2_VI:
+				acm_ctrl &= (~AcmHw_ViqEn);
+				break;
+			case AC3_VO:
+				acm_ctrl &= (~AcmHw_BeqEn);
+				break;
+			default:
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+					 "switch case not processed\n");
+				break;
+			}
+		}
+
+		RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE,
+			 "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n",
+			 acm_ctrl);
+		rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl);
+		break; }
+	case HW_VAR_RCR:
+		rtl_write_dword(rtlpriv, REG_RCR, ((u32 *) (val))[0]);
+		rtlpci->receive_config = ((u32 *) (val))[0];
+		break;
+	case HW_VAR_RETRY_LIMIT:{
+		u8 retry_limit = ((u8 *) (val))[0];
+
+		rtl_write_word(rtlpriv, REG_RL,
+			       retry_limit << RETRY_LIMIT_SHORT_SHIFT |
+			       retry_limit << RETRY_LIMIT_LONG_SHIFT);
+		break; }
+	case HW_VAR_DUAL_TSF_RST:
+		rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
+		break;
+	case HW_VAR_EFUSE_BYTES:
+		rtlefuse->efuse_usedbytes = *((u16 *) val);
+		break;
+	case HW_VAR_EFUSE_USAGE:
+		rtlefuse->efuse_usedpercentage = *((u8 *) val);
+		break;
+	case HW_VAR_IO_CMD:
+		rtl8723ae_phy_set_io_cmd(hw, (*(enum io_type *)val));
+		break;
+	case HW_VAR_WPA_CONFIG:
+		rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *) val));
+		break;
+	case HW_VAR_SET_RPWM:{
+		u8 rpwm_val;
+
+		rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM);
+		udelay(1);
+
+		if (rpwm_val & BIT(7)) {
+			rtl_write_byte(rtlpriv, REG_PCIE_HRPWM,
+				       (*(u8 *) val));
+		} else {
+			rtl_write_byte(rtlpriv, REG_PCIE_HRPWM,
+				       ((*(u8 *) val) | BIT(7)));
+		}
+
+		break; }
+	case HW_VAR_H2C_FW_PWRMODE:{
+		u8 psmode = (*(u8 *) val);
+
+		if (psmode != FW_PS_ACTIVE_MODE)
+			rtl8723ae_dm_rf_saving(hw, true);
+
+		rtl8723ae_set_fw_pwrmode_cmd(hw, (*(u8 *) val));
+		break; }
+	case HW_VAR_FW_PSMODE_STATUS:
+		ppsc->fw_current_inpsmode = *((bool *) val);
+		break;
+	case HW_VAR_H2C_FW_JOINBSSRPT:{
+		u8 mstatus = (*(u8 *) val);
+		u8 tmp_regcr, tmp_reg422;
+		bool recover = false;
+
+		if (mstatus == RT_MEDIA_CONNECT) {
+			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL);
+
+			tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1);
+			rtl_write_byte(rtlpriv, REG_CR + 1,
+				       (tmp_regcr | BIT(0)));
+
+			_rtl8723ae_set_bcn_ctrl_reg(hw, 0, BIT(3));
+			_rtl8723ae_set_bcn_ctrl_reg(hw, BIT(4), 0);
+
+			tmp_reg422 = rtl_read_byte(rtlpriv,
+				     REG_FWHW_TXQ_CTRL + 2);
+			if (tmp_reg422 & BIT(6))
+				recover = true;
+			rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
+				       tmp_reg422 & (~BIT(6)));
+
+			rtl8723ae_set_fw_rsvdpagepkt(hw, 0);
+
+			_rtl8723ae_set_bcn_ctrl_reg(hw, BIT(3), 0);
+			_rtl8723ae_set_bcn_ctrl_reg(hw, 0, BIT(4));
+
+			if (recover)
+				rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
+					       tmp_reg422);
+
+			rtl_write_byte(rtlpriv, REG_CR + 1,
+				       (tmp_regcr & ~(BIT(0))));
+		}
+		rtl8723ae_set_fw_joinbss_report_cmd(hw, (*(u8 *) val));
+
+		break; }
+	case HW_VAR_AID:{
+		u16 u2btmp;
+		u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT);
+		u2btmp &= 0xC000;
+		rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp |
+				mac->assoc_id));
+		break; }
+	case HW_VAR_CORRECT_TSF:{
+		u8 btype_ibss = ((u8 *) (val))[0];
+
+		if (btype_ibss == true)
+			_rtl8723ae_stop_tx_beacon(hw);
+
+		_rtl8723ae_set_bcn_ctrl_reg(hw, 0, BIT(3));
+
+		rtl_write_dword(rtlpriv, REG_TSFTR,
+				(u32) (mac->tsf & 0xffffffff));
+		rtl_write_dword(rtlpriv, REG_TSFTR + 4,
+				(u32) ((mac->tsf >> 32) & 0xffffffff));
+
+		_rtl8723ae_set_bcn_ctrl_reg(hw, BIT(3), 0);
+
+		if (btype_ibss == true)
+			_rtl8723ae_resume_tx_beacon(hw);
+		break; }
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "switch case not processed\n");
+		break;
+	}
+}
+
+static bool _rtl8723ae_llt_write(struct ieee80211_hw *hw, u32 address, u32 data)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	bool status = true;
+	long count = 0;
+	u32 value = _LLT_INIT_ADDR(address) |
+	    _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS);
+
+	rtl_write_dword(rtlpriv, REG_LLT_INIT, value);
+
+	do {
+		value = rtl_read_dword(rtlpriv, REG_LLT_INIT);
+		if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value))
+			break;
+
+		if (count > POLLING_LLT_THRESHOLD) {
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 "Failed to polling write LLT done at address %d!\n",
+				 address);
+			status = false;
+			break;
+		}
+	} while (++count);
+
+	return status;
+}
+
+static bool _rtl8723ae_llt_table_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	unsigned short i;
+	u8 txpktbuf_bndy;
+	u8 maxPage;
+	bool status;
+	u8 ubyte;
+
+	maxPage = 255;
+	txpktbuf_bndy = 246;
+
+	rtl_write_byte(rtlpriv, REG_CR, 0x8B);
+
+	rtl_write_word(rtlpriv, REG_RQPN_NPQ, 0x0000);
+
+	rtl_write_dword(rtlpriv, REG_RQPN, 0x80ac1c29);
+	rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x03);
+
+	rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, (0x27FF0000 | txpktbuf_bndy));
+	rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy);
+
+	rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
+	rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
+
+	rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy);
+	rtl_write_byte(rtlpriv, REG_PBP, 0x11);
+	rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4);
+
+	for (i = 0; i < (txpktbuf_bndy - 1); i++) {
+		status = _rtl8723ae_llt_write(hw, i, i + 1);
+		if (true != status)
+			return status;
+	}
+
+	status = _rtl8723ae_llt_write(hw, (txpktbuf_bndy - 1), 0xFF);
+	if (true != status)
+		return status;
+
+	for (i = txpktbuf_bndy; i < maxPage; i++) {
+		status = _rtl8723ae_llt_write(hw, i, (i + 1));
+		if (true != status)
+			return status;
+	}
+
+	status = _rtl8723ae_llt_write(hw, maxPage, txpktbuf_bndy);
+	if (true != status)
+		return status;
+
+	rtl_write_byte(rtlpriv, REG_CR, 0xff);
+	ubyte = rtl_read_byte(rtlpriv, REG_RQPN + 3);
+	rtl_write_byte(rtlpriv, REG_RQPN + 3, ubyte | BIT(7));
+
+	return true;
+}
+
+static void _rtl8723ae_gen_refresh_led_state(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
+
+	if (rtlpriv->rtlhal.up_first_time)
+		return;
+
+	if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
+		rtl8723ae_sw_led_on(hw, pLed0);
+	else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
+		rtl8723ae_sw_led_on(hw, pLed0);
+	else
+		rtl8723ae_sw_led_off(hw, pLed0);
+}
+
+static bool _rtl8712e_init_mac(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	unsigned char bytetmp;
+	unsigned short wordtmp;
+	u16 retry = 0;
+	u16 tmpu2b;
+	bool mac_func_enable;
+
+	rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00);
+	bytetmp = rtl_read_byte(rtlpriv, REG_CR);
+	if (bytetmp == 0xFF)
+		mac_func_enable = true;
+	else
+		mac_func_enable = false;
+
+
+	/* HW Power on sequence */
+	if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
+		PWR_INTF_PCI_MSK, Rtl8723_NIC_ENABLE_FLOW))
+		return false;
+
+	bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG+2);
+	rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+2, bytetmp | BIT(4));
+
+	/* eMAC time out function enable, 0x369[7]=1 */
+	bytetmp = rtl_read_byte(rtlpriv, 0x369);
+	rtl_write_byte(rtlpriv, 0x369, bytetmp | BIT(7));
+
+	/* ePHY reg 0x1e bit[4]=1 using MDIO interface,
+	 * we should do this before Enabling ASPM backdoor.
+	 */
+	do {
+		rtl_write_word(rtlpriv, 0x358, 0x5e);
+		udelay(100);
+		rtl_write_word(rtlpriv, 0x356, 0xc280);
+		rtl_write_word(rtlpriv, 0x354, 0xc290);
+		rtl_write_word(rtlpriv, 0x358, 0x3e);
+		udelay(100);
+		rtl_write_word(rtlpriv, 0x358, 0x5e);
+		udelay(100);
+		tmpu2b = rtl_read_word(rtlpriv, 0x356);
+		retry++;
+	} while (tmpu2b != 0xc290 && retry < 100);
+
+	if (retry >= 100) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+			 "InitMAC(): ePHY configure fail!!!\n");
+		return false;
+	}
+
+	rtl_write_word(rtlpriv, REG_CR, 0x2ff);
+	rtl_write_word(rtlpriv, REG_CR + 1, 0x06);
+
+	if (!mac_func_enable) {
+		if (_rtl8723ae_llt_table_init(hw) == false)
+			return false;
+	}
+
+	rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff);
+	rtl_write_byte(rtlpriv, REG_HISRE, 0xff);
+
+	rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x27ff);
+
+	wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL) & 0xf;
+	wordtmp |= 0xF771;
+	rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp);
+
+	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F);
+	rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
+	rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xFFFF);
+	rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config);
+
+	rtl_write_byte(rtlpriv, 0x4d0, 0x0);
+
+	rtl_write_dword(rtlpriv, REG_BCNQ_DESA,
+			((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) &
+			DMA_BIT_MASK(32));
+	rtl_write_dword(rtlpriv, REG_MGQ_DESA,
+			(u64) rtlpci->tx_ring[MGNT_QUEUE].dma &
+			DMA_BIT_MASK(32));
+	rtl_write_dword(rtlpriv, REG_VOQ_DESA,
+			(u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32));
+	rtl_write_dword(rtlpriv, REG_VIQ_DESA,
+			(u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32));
+	rtl_write_dword(rtlpriv, REG_BEQ_DESA,
+			(u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32));
+	rtl_write_dword(rtlpriv, REG_BKQ_DESA,
+			(u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32));
+	rtl_write_dword(rtlpriv, REG_HQ_DESA,
+			(u64) rtlpci->tx_ring[HIGH_QUEUE].dma &
+			DMA_BIT_MASK(32));
+	rtl_write_dword(rtlpriv, REG_RX_DESA,
+			(u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma &
+			DMA_BIT_MASK(32));
+
+	rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x74);
+
+	rtl_write_dword(rtlpriv, REG_INT_MIG, 0);
+
+	bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL);
+	rtl_write_byte(rtlpriv, REG_APSD_CTRL, bytetmp & ~BIT(6));
+	do {
+		retry++;
+		bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL);
+	} while ((retry < 200) && (bytetmp & BIT(7)));
+
+	_rtl8723ae_gen_refresh_led_state(hw);
+
+	rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0);
+
+	return true;
+}
+
+static void _rtl8723ae_hw_configure(struct ieee80211_hw *hw)
+{
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	u8 reg_bw_opmode;
+	u32 reg_ratr, reg_prsr;
+
+	reg_bw_opmode = BW_OPMODE_20MHZ;
+	reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG |
+	    RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
+	reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+
+	rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8);
+
+	rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+
+	rtl_write_dword(rtlpriv, REG_RRSR, reg_prsr);
+
+	rtl_write_byte(rtlpriv, REG_SLOT, 0x09);
+
+	rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, 0x0);
+
+	rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F80);
+
+	rtl_write_word(rtlpriv, REG_RL, 0x0707);
+
+	rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x02012802);
+
+	rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF);
+
+	rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000);
+	rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504);
+	rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000);
+	rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504);
+
+	if ((pcipriv->bt_coexist.bt_coexistence) &&
+	    (pcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4))
+		rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x97427431);
+	else
+		rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841);
+
+	rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2);
+
+	rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xff);
+
+	rtlpci->reg_bcn_ctrl_val = 0x1f;
+	rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val);
+
+	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff);
+
+	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff);
+
+	rtl_write_byte(rtlpriv, REG_PIFS, 0x1C);
+	rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
+
+	if ((pcipriv->bt_coexist.bt_coexistence) &&
+	    (pcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) {
+		rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020);
+		rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0402);
+	} else {
+		rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020);
+		rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020);
+	}
+
+	if ((pcipriv->bt_coexist.bt_coexistence) &&
+	     (pcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4))
+		rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666);
+	else
+		rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x086666);
+
+	rtl_write_byte(rtlpriv, REG_ACKTO, 0x40);
+
+	rtl_write_word(rtlpriv, REG_SPEC_SIFS, 0x1010);
+	rtl_write_word(rtlpriv, REG_MAC_SPEC_SIFS, 0x1010);
+
+	rtl_write_word(rtlpriv, REG_SIFS_CTX, 0x1010);
+
+	rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x1010);
+
+	rtl_write_dword(rtlpriv, REG_MAR, 0xffffffff);
+	rtl_write_dword(rtlpriv, REG_MAR + 4, 0xffffffff);
+
+	rtl_write_dword(rtlpriv, 0x394, 0x1);
+}
+
+static void _rtl8723ae_enable_aspm_back_door(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+	rtl_write_byte(rtlpriv, 0x34b, 0x93);
+	rtl_write_word(rtlpriv, 0x350, 0x870c);
+	rtl_write_byte(rtlpriv, 0x352, 0x1);
+
+	if (ppsc->support_backdoor)
+		rtl_write_byte(rtlpriv, 0x349, 0x1b);
+	else
+		rtl_write_byte(rtlpriv, 0x349, 0x03);
+
+	rtl_write_word(rtlpriv, 0x350, 0x2718);
+	rtl_write_byte(rtlpriv, 0x352, 0x1);
+}
+
+void rtl8723ae_enable_hw_security_config(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 sec_reg_value;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+		 "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n",
+		 rtlpriv->sec.pairwise_enc_algorithm,
+		 rtlpriv->sec.group_enc_algorithm);
+
+	if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
+		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+			 "not open hw encryption\n");
+		return;
+	}
+
+	sec_reg_value = SCR_TxEncEnable | SCR_RxDecEnable;
+
+	if (rtlpriv->sec.use_defaultkey) {
+		sec_reg_value |= SCR_TxUseDK;
+		sec_reg_value |= SCR_RxUseDK;
+	}
+
+	sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK);
+
+	rtl_write_byte(rtlpriv, REG_CR + 1, 0x02);
+
+	RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+		 "The SECR-value %x\n", sec_reg_value);
+
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value);
+
+}
+
+int rtl8723ae_hw_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	bool rtstatus = true;
+	int err;
+	u8 tmp_u1b;
+
+	rtlpriv->rtlhal.being_init_adapter = true;
+	rtlpriv->intf_ops->disable_aspm(hw);
+	rtstatus = _rtl8712e_init_mac(hw);
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n");
+		err = 1;
+		return err;
+	}
+
+	err = rtl8723ae_download_fw(hw);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			 "Failed to download FW. Init HW without FW now..\n");
+		err = 1;
+		rtlhal->fw_ready = false;
+		return err;
+	} else {
+		rtlhal->fw_ready = true;
+	}
+
+	rtlhal->last_hmeboxnum = 0;
+	rtl8723ae_phy_mac_config(hw);
+	/* because the last function modifies RCR, we update
+	 * rcr var here, or TP will be unstable as ther receive_config
+	 * is wrong, RX RCR_ACRC32 will cause TP unstable & Rx
+	 * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252
+	 */
+	rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR);
+	rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
+	rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
+
+	rtl8723ae_phy_bb_config(hw);
+	rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
+	rtl8723ae_phy_rf_config(hw);
+	if (IS_VENDOR_UMC_A_CUT(rtlhal->version)) {
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00);
+	} else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x0C, MASKDWORD, 0x894AE);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x0A, MASKDWORD, 0x1AF31);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_IPA, MASKDWORD, 0x8F425);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_SYN_G2, MASKDWORD, 0x4F200);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK1, MASKDWORD, 0x44053);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK2, MASKDWORD, 0x80201);
+	}
+	rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
+						 RF_CHNLBW, RFREG_OFFSET_MASK);
+	rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1,
+						 RF_CHNLBW, RFREG_OFFSET_MASK);
+	rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1);
+	rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1);
+	rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);
+	_rtl8723ae_hw_configure(hw);
+	rtl_cam_reset_all_entry(hw);
+	rtl8723ae_enable_hw_security_config(hw);
+
+	ppsc->rfpwr_state = ERFON;
+
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
+	_rtl8723ae_enable_aspm_back_door(hw);
+	rtlpriv->intf_ops->enable_aspm(hw);
+
+	rtl8723ae_bt_hw_init(hw);
+
+	if (ppsc->rfpwr_state == ERFON) {
+		rtl8723ae_phy_set_rfpath_switch(hw, 1);
+		if (rtlphy->iqk_initialized) {
+			rtl8723ae_phy_iq_calibrate(hw, true);
+		} else {
+			rtl8723ae_phy_iq_calibrate(hw, false);
+			rtlphy->iqk_initialized = true;
+		}
+
+		rtl8723ae_phy_lc_calibrate(hw);
+	}
+
+	tmp_u1b = efuse_read_1byte(hw, 0x1FA);
+	if (!(tmp_u1b & BIT(0))) {
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0F, 0x05);
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "PA BIAS path A\n");
+	}
+
+	if (!(tmp_u1b & BIT(4))) {
+		tmp_u1b = rtl_read_byte(rtlpriv, 0x16) & 0x0F;
+		rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x80);
+		udelay(10);
+		rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x90);
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "under 1.5V\n");
+	}
+	rtl8723ae_dm_init(hw);
+	rtlpriv->rtlhal.being_init_adapter = false;
+	return err;
+}
+
+static enum version_8723e _rtl8723ae_read_chip_version(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	enum version_8723e version = 0x0000;
+	u32 value32;
+
+	value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG);
+	if (value32 & TRP_VAUX_EN) {
+		version = (enum version_8723e)(version |
+			  ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0));
+		/* RTL8723 with BT function. */
+		version = (enum version_8723e)(version |
+			  ((value32 & BT_FUNC) ? CHIP_8723 : 0));
+
+	} else {
+		/* Normal mass production chip. */
+		version = (enum version_8723e) NORMAL_CHIP;
+		version = (enum version_8723e)(version |
+			  ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0));
+		/* RTL8723 with BT function. */
+		version = (enum version_8723e)(version |
+			  ((value32 & BT_FUNC) ? CHIP_8723 : 0));
+		if (IS_CHIP_VENDOR_UMC(version))
+			version = (enum version_8723e)(version |
+			((value32 & CHIP_VER_RTL_MASK)));/* IC version (CUT) */
+		if (IS_8723_SERIES(version)) {
+			value32 = rtl_read_dword(rtlpriv, REG_GPIO_OUTSTS);
+			/* ROM code version */
+			version = (enum version_8723e)(version |
+				  ((value32 & RF_RL_ID)>>20));
+		}
+	}
+
+	if (IS_8723_SERIES(version)) {
+		value32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL);
+		rtlphy->polarity_ctl = ((value32 & WL_HWPDN_SL) ?
+				       RT_POLARITY_HIGH_ACT :
+				       RT_POLARITY_LOW_ACT);
+	}
+	switch (version) {
+	case VERSION_TEST_UMC_CHIP_8723:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Chip Version ID: VERSION_TEST_UMC_CHIP_8723.\n");
+		break;
+	case VERSION_NORMAL_UMC_CHIP_8723_1T1R_A_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Chip Version ID: VERSION_NORMAL_UMC_CHIP_8723_1T1R_A_CUT.\n");
+		break;
+	case VERSION_NORMAL_UMC_CHIP_8723_1T1R_B_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Chip Version ID: VERSION_NORMAL_UMC_CHIP_8723_1T1R_B_CUT.\n");
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "Chip Version ID: Unknown. Bug?\n");
+		break;
+	}
+
+	if (IS_8723_SERIES(version))
+		rtlphy->rf_type = RF_1T1R;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Chip RF Type: %s\n",
+		(rtlphy->rf_type == RF_2T2R) ? "RF_2T2R" : "RF_1T1R");
+
+	return version;
+}
+
+static int _rtl8723ae_set_media_status(struct ieee80211_hw *hw,
+				     enum nl80211_iftype type)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 bt_msr = rtl_read_byte(rtlpriv, MSR) & 0xfc;
+	enum led_ctl_mode ledaction = LED_CTL_NO_LINK;
+
+	rtl_write_dword(rtlpriv, REG_BCN_CTRL, 0);
+	RT_TRACE(rtlpriv, COMP_BEACON, DBG_LOUD,
+		 "clear 0x550 when set HW_VAR_MEDIA_STATUS\n");
+
+	if (type == NL80211_IFTYPE_UNSPECIFIED ||
+	    type == NL80211_IFTYPE_STATION) {
+		_rtl8723ae_stop_tx_beacon(hw);
+		_rtl8723ae_enable_bcn_sufunc(hw);
+	} else if (type == NL80211_IFTYPE_ADHOC ||
+		type == NL80211_IFTYPE_AP) {
+		_rtl8723ae_resume_tx_beacon(hw);
+		_rtl8723ae_disable_bcn_sufunc(hw);
+	} else {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			 "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n",
+			 type);
+	}
+
+	switch (type) {
+	case NL80211_IFTYPE_UNSPECIFIED:
+		bt_msr |= MSR_NOLINK;
+		ledaction = LED_CTL_LINK;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Set Network type to NO LINK!\n");
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		bt_msr |= MSR_ADHOC;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Set Network type to Ad Hoc!\n");
+		break;
+	case NL80211_IFTYPE_STATION:
+		bt_msr |= MSR_INFRA;
+		ledaction = LED_CTL_LINK;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Set Network type to STA!\n");
+		break;
+	case NL80211_IFTYPE_AP:
+		bt_msr |= MSR_AP;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "Set Network type to AP!\n");
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "Network type %d not supported!\n",
+			 type);
+		return 1;
+		break;
+
+	}
+
+	rtl_write_byte(rtlpriv, (MSR), bt_msr);
+	rtlpriv->cfg->ops->led_control(hw, ledaction);
+	if ((bt_msr & 0x03) == MSR_AP)
+		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
+	else
+		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
+	return 0;
+}
+
+void rtl8723ae_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	u32 reg_rcr = rtlpci->receive_config;
+
+	if (rtlpriv->psc.rfpwr_state != ERFON)
+		return;
+
+	if (check_bssid == true) {
+		reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
+					      (u8 *)(&reg_rcr));
+		_rtl8723ae_set_bcn_ctrl_reg(hw, 0, BIT(4));
+	} else if (check_bssid == false) {
+		reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
+		_rtl8723ae_set_bcn_ctrl_reg(hw, BIT(4), 0);
+		rtlpriv->cfg->ops->set_hw_reg(hw,
+			HW_VAR_RCR, (u8 *) (&reg_rcr));
+	}
+}
+
+int rtl8723ae_set_network_type(struct ieee80211_hw *hw,
+			       enum nl80211_iftype type)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (_rtl8723ae_set_media_status(hw, type))
+		return -EOPNOTSUPP;
+
+	if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
+		if (type != NL80211_IFTYPE_AP)
+			rtl8723ae_set_check_bssid(hw, true);
+	} else {
+		rtl8723ae_set_check_bssid(hw, false);
+	}
+	return 0;
+}
+
+/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */
+void rtl8723ae_set_qos(struct ieee80211_hw *hw, int aci)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl8723ae_dm_init_edca_turbo(hw);
+	switch (aci) {
+	case AC1_BK:
+		rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f);
+		break;
+	case AC0_BE:
+		/* rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4ac_param); */
+		break;
+	case AC2_VI:
+		rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322);
+		break;
+	case AC3_VO:
+		rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222);
+		break;
+	default:
+		RT_ASSERT(false, "invalid aci: %d !\n", aci);
+		break;
+	}
+}
+
+void rtl8723ae_enable_interrupt(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+	rtl_write_dword(rtlpriv, 0x3a8, rtlpci->irq_mask[0] & 0xFFFFFFFF);
+	rtl_write_dword(rtlpriv, 0x3ac, rtlpci->irq_mask[1] & 0xFFFFFFFF);
+	rtlpci->irq_enabled = true;
+}
+
+void rtl8723ae_disable_interrupt(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+	rtl_write_dword(rtlpriv, 0x3a8, IMR8190_DISABLED);
+	rtl_write_dword(rtlpriv, 0x3ac, IMR8190_DISABLED);
+	rtlpci->irq_enabled = false;
+	synchronize_irq(rtlpci->pdev->irq);
+}
+
+static void _rtl8723ae_poweroff_adapter(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 u1tmp;
+
+	/* Combo (PCIe + USB) Card and PCIe-MF Card */
+	/* 1. Run LPS WL RFOFF flow */
+	rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
+		PWR_INTF_PCI_MSK, Rtl8723_NIC_LPS_ENTER_FLOW);
+
+	/* 2. 0x1F[7:0] = 0 */
+	/* turn off RF */
+	rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00);
+	if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready)
+		rtl8723ae_firmware_selfreset(hw);
+
+	/* Reset MCU. Suggested by Filen. */
+	u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1tmp & (~BIT(2))));
+
+	/* g.	MCUFWDL 0x80[1:0]=0	 */
+	/* reset MCU ready status */
+	rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
+
+	/* HW card disable configuration. */
+	rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
+		PWR_INTF_PCI_MSK, Rtl8723_NIC_DISABLE_FLOW);
+
+	/* Reset MCU IO Wrapper */
+	u1tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
+	rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1tmp & (~BIT(0))));
+	u1tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
+	rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, u1tmp | BIT(0));
+
+	/* 7. RSV_CTRL 0x1C[7:0] = 0x0E */
+	/* lock ISO/CLK/Power control register */
+	rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e);
+}
+
+void rtl8723ae_card_disable(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	enum nl80211_iftype opmode;
+
+	mac->link_state = MAC80211_NOLINK;
+	opmode = NL80211_IFTYPE_UNSPECIFIED;
+	_rtl8723ae_set_media_status(hw, opmode);
+	if (rtlpci->driver_is_goingto_unload ||
+	    ppsc->rfoff_reason > RF_CHANGE_BY_PS)
+		rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
+	RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+	_rtl8723ae_poweroff_adapter(hw);
+
+	/* after power off we should do iqk again */
+	rtlpriv->phy.iqk_initialized = false;
+}
+
+void rtl8723ae_interrupt_recognized(struct ieee80211_hw *hw,
+				    u32 *p_inta, u32 *p_intb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+	*p_inta = rtl_read_dword(rtlpriv, 0x3a0) & rtlpci->irq_mask[0];
+	rtl_write_dword(rtlpriv, 0x3a0, *p_inta);
+}
+
+void rtl8723ae_set_beacon_related_registers(struct ieee80211_hw *hw)
+{
+
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u16 bcn_interval, atim_window;
+
+	bcn_interval = mac->beacon_interval;
+	atim_window = 2;	/*FIX MERGE */
+	rtl8723ae_disable_interrupt(hw);
+	rtl_write_word(rtlpriv, REG_ATIMWND, atim_window);
+	rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
+	rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f);
+	rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18);
+	rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18);
+	rtl_write_byte(rtlpriv, 0x606, 0x30);
+	rtl8723ae_enable_interrupt(hw);
+}
+
+void rtl8723ae_set_beacon_interval(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u16 bcn_interval = mac->beacon_interval;
+
+	RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
+		 "beacon_interval:%d\n", bcn_interval);
+	rtl8723ae_disable_interrupt(hw);
+	rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
+	rtl8723ae_enable_interrupt(hw);
+}
+
+void rtl8723ae_update_interrupt_mask(struct ieee80211_hw *hw,
+				     u32 add_msr, u32 rm_msr)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+	RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
+		 "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr);
+
+	if (add_msr)
+		rtlpci->irq_mask[0] |= add_msr;
+	if (rm_msr)
+		rtlpci->irq_mask[0] &= (~rm_msr);
+	rtl8723ae_disable_interrupt(hw);
+	rtl8723ae_enable_interrupt(hw);
+}
+
+static u8 _rtl8723ae_get_chnl_group(u8 chnl)
+{
+	u8 group;
+
+	if (chnl < 3)
+		group = 0;
+	else if (chnl < 9)
+		group = 1;
+	else
+		group = 2;
+	return group;
+}
+
+static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
+						   bool autoload_fail,
+						   u8 *hwinfo)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 rf_path, index, tempval;
+	u16 i;
+
+	for (rf_path = 0; rf_path < 1; rf_path++) {
+		for (i = 0; i < 3; i++) {
+			if (!autoload_fail) {
+				rtlefuse->eeprom_chnlarea_txpwr_cck
+				    [rf_path][i] =
+				    hwinfo[EEPROM_TXPOWERCCK + rf_path * 3 + i];
+				rtlefuse->eeprom_chnlarea_txpwr_ht40_1s
+				    [rf_path][i] =
+				    hwinfo[EEPROM_TXPOWERHT40_1S + rf_path *
+				    3 + i];
+			} else {
+				rtlefuse->eeprom_chnlarea_txpwr_cck
+				    [rf_path][i] =
+				    EEPROM_DEFAULT_TXPOWERLEVEL;
+				rtlefuse->eeprom_chnlarea_txpwr_ht40_1s
+				    [rf_path][i] =
+				    EEPROM_DEFAULT_TXPOWERLEVEL;
+			}
+		}
+	}
+
+	for (i = 0; i < 3; i++) {
+		if (!autoload_fail)
+			tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i];
+		else
+			tempval = EEPROM_DEFAULT_HT40_2SDIFF;
+		rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_A][i] =
+		    (tempval & 0xf);
+		rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_B][i] =
+		    ((tempval & 0xf0) >> 4);
+	}
+
+	for (rf_path = 0; rf_path < 2; rf_path++)
+		for (i = 0; i < 3; i++)
+			RTPRINT(rtlpriv, FINIT, INIT_EEPROM,
+				"RF(%d) EEPROM CCK Area(%d) = 0x%x\n", rf_path,
+				i, rtlefuse->eeprom_chnlarea_txpwr_cck
+				[rf_path][i]);
+	for (rf_path = 0; rf_path < 2; rf_path++)
+		for (i = 0; i < 3; i++)
+			RTPRINT(rtlpriv, FINIT, INIT_EEPROM,
+				"RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n",
+				rf_path, i,
+				rtlefuse->eeprom_chnlarea_txpwr_ht40_1s
+				[rf_path][i]);
+	for (rf_path = 0; rf_path < 2; rf_path++)
+		for (i = 0; i < 3; i++)
+			RTPRINT(rtlpriv, FINIT, INIT_EEPROM,
+				"RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n",
+				rf_path, i,
+				rtlefuse->eprom_chnl_txpwr_ht40_2sdf
+				[rf_path][i]);
+
+	for (rf_path = 0; rf_path < 2; rf_path++) {
+		for (i = 0; i < 14; i++) {
+			index = _rtl8723ae_get_chnl_group((u8) i);
+
+			rtlefuse->txpwrlevel_cck[rf_path][i] =
+				rtlefuse->eeprom_chnlarea_txpwr_cck
+							[rf_path][index];
+			rtlefuse->txpwrlevel_ht40_1s[rf_path][i] =
+				rtlefuse->eeprom_chnlarea_txpwr_ht40_1s
+							[rf_path][index];
+
+			if ((rtlefuse->eeprom_chnlarea_txpwr_ht40_1s
+			    [rf_path][index] -
+			    rtlefuse->eprom_chnl_txpwr_ht40_2sdf[rf_path]
+			    [index]) > 0) {
+				rtlefuse->txpwrlevel_ht40_2s[rf_path][i] =
+					rtlefuse->eeprom_chnlarea_txpwr_ht40_1s
+					[rf_path][index] -
+					rtlefuse->eprom_chnl_txpwr_ht40_2sdf
+					[rf_path][index];
+			} else {
+				rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0;
+			}
+		}
+
+		for (i = 0; i < 14; i++) {
+			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+				"RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = "
+				"[0x%x / 0x%x / 0x%x]\n", rf_path, i,
+				rtlefuse->txpwrlevel_cck[rf_path][i],
+				rtlefuse->txpwrlevel_ht40_1s[rf_path][i],
+				rtlefuse->txpwrlevel_ht40_2s[rf_path][i]);
+		}
+	}
+
+	for (i = 0; i < 3; i++) {
+		if (!autoload_fail) {
+			rtlefuse->eeprom_pwrlimit_ht40[i] =
+			    hwinfo[EEPROM_TXPWR_GROUP + i];
+			rtlefuse->eeprom_pwrlimit_ht20[i] =
+			    hwinfo[EEPROM_TXPWR_GROUP + 3 + i];
+		} else {
+			rtlefuse->eeprom_pwrlimit_ht40[i] = 0;
+			rtlefuse->eeprom_pwrlimit_ht20[i] = 0;
+		}
+	}
+
+	for (rf_path = 0; rf_path < 2; rf_path++) {
+		for (i = 0; i < 14; i++) {
+			index = _rtl8723ae_get_chnl_group((u8) i);
+
+			if (rf_path == RF90_PATH_A) {
+				rtlefuse->pwrgroup_ht20[rf_path][i] =
+				    (rtlefuse->eeprom_pwrlimit_ht20[index] &
+				    0xf);
+				rtlefuse->pwrgroup_ht40[rf_path][i] =
+				    (rtlefuse->eeprom_pwrlimit_ht40[index] &
+				    0xf);
+			} else if (rf_path == RF90_PATH_B) {
+				rtlefuse->pwrgroup_ht20[rf_path][i] =
+				    ((rtlefuse->eeprom_pwrlimit_ht20[index] &
+				    0xf0) >> 4);
+				rtlefuse->pwrgroup_ht40[rf_path][i] =
+				    ((rtlefuse->eeprom_pwrlimit_ht40[index] &
+				    0xf0) >> 4);
+			}
+
+			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+				"RF-%d pwrgroup_ht20[%d] = 0x%x\n", rf_path, i,
+				rtlefuse->pwrgroup_ht20[rf_path][i]);
+			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+				"RF-%d pwrgroup_ht40[%d] = 0x%x\n", rf_path, i,
+				rtlefuse->pwrgroup_ht40[rf_path][i]);
+		}
+	}
+
+	for (i = 0; i < 14; i++) {
+		index = _rtl8723ae_get_chnl_group((u8) i);
+
+		if (!autoload_fail)
+			tempval = hwinfo[EEPROM_TXPOWERHT20DIFF + index];
+		else
+			tempval = EEPROM_DEFAULT_HT20_DIFF;
+
+		rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF);
+		rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] =
+		    ((tempval >> 4) & 0xF);
+
+		if (rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] & BIT(3))
+			rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] |= 0xF0;
+
+		if (rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] & BIT(3))
+			rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] |= 0xF0;
+
+		index = _rtl8723ae_get_chnl_group((u8) i);
+
+		if (!autoload_fail)
+			tempval = hwinfo[EEPROM_TXPOWER_OFDMDIFF + index];
+		else
+			tempval = EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF;
+
+		rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = (tempval & 0xF);
+		rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] =
+		    ((tempval >> 4) & 0xF);
+	}
+
+	rtlefuse->legacy_ht_txpowerdiff =
+	    rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7];
+
+	for (i = 0; i < 14; i++)
+		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			"RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", i,
+			rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]);
+	for (i = 0; i < 14; i++)
+		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			"RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", i,
+			rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]);
+	for (i = 0; i < 14; i++)
+		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			"RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", i,
+			rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]);
+	for (i = 0; i < 14; i++)
+		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			"RF-B Legacy to HT40 Diff[%d] = 0x%x\n", i,
+			rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]);
+
+	if (!autoload_fail)
+		rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7);
+	else
+		rtlefuse->eeprom_regulatory = 0;
+	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		"eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory);
+
+	if (!autoload_fail)
+		rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A];
+	else
+		rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI;
+	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		"TSSI_A = 0x%x, TSSI_B = 0x%x\n",
+		rtlefuse->eeprom_tssi[RF90_PATH_A],
+		rtlefuse->eeprom_tssi[RF90_PATH_B]);
+
+	if (!autoload_fail)
+		tempval = hwinfo[EEPROM_THERMAL_METER];
+	else
+		tempval = EEPROM_DEFAULT_THERMALMETER;
+	rtlefuse->eeprom_thermalmeter = (tempval & 0x1f);
+
+	if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail)
+		rtlefuse->apk_thermalmeterignore = true;
+
+	rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter;
+	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		"thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter);
+}
+
+static void _rtl8723ae_read_adapter_info(struct ieee80211_hw *hw,
+					 bool pseudo_test)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u16 i, usvalue;
+	u8 hwinfo[HWSET_MAX_SIZE];
+	u16 eeprom_id;
+
+	if (pseudo_test) {
+		/* need add */
+		return;
+	}
+	if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) {
+		rtl_efuse_shadow_map_update(hw);
+
+		memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
+		       HWSET_MAX_SIZE);
+	} else if (rtlefuse->epromtype == EEPROM_93C46) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "RTL819X Not boot from eeprom, check it !!");
+	}
+
+	RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"),
+		      hwinfo, HWSET_MAX_SIZE);
+
+	eeprom_id = *((u16 *)&hwinfo[0]);
+	if (eeprom_id != RTL8190_EEPROM_ID) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			 "EEPROM ID(%#x) is invalid!!\n", eeprom_id);
+		rtlefuse->autoload_failflag = true;
+	} else {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n");
+		rtlefuse->autoload_failflag = false;
+	}
+
+	if (rtlefuse->autoload_failflag == true)
+		return;
+
+	rtlefuse->eeprom_vid = *(u16 *) &hwinfo[EEPROM_VID];
+	rtlefuse->eeprom_did = *(u16 *) &hwinfo[EEPROM_DID];
+	rtlefuse->eeprom_svid = *(u16 *) &hwinfo[EEPROM_SVID];
+	rtlefuse->eeprom_smid = *(u16 *) &hwinfo[EEPROM_SMID];
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 "EEPROMId = 0x%4x\n", eeprom_id);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid);
+
+	for (i = 0; i < 6; i += 2) {
+		usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i];
+		*((u16 *) (&rtlefuse->dev_addr[i])) = usvalue;
+	}
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+		 "dev_addr: %pM\n", rtlefuse->dev_addr);
+
+	_rtl8723ae_read_txpower_info_from_hwpg(hw,
+			rtlefuse->autoload_failflag, hwinfo);
+
+	rtl8723ae_read_bt_coexist_info_from_hwpg(hw,
+			rtlefuse->autoload_failflag, hwinfo);
+
+	rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN];
+	rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION];
+	rtlefuse->txpwr_fromeprom = true;
+	rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID];
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid);
+
+	/* set channel paln to world wide 13 */
+	rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13;
+
+	if (rtlhal->oem_id == RT_CID_DEFAULT) {
+		switch (rtlefuse->eeprom_oemid) {
+		case EEPROM_CID_DEFAULT:
+			if (rtlefuse->eeprom_did == 0x8176) {
+				if (CHK_SVID_SMID(0x10EC, 0x6151) ||
+				    CHK_SVID_SMID(0x10EC, 0x6152) ||
+				    CHK_SVID_SMID(0x10EC, 0x6154) ||
+				    CHK_SVID_SMID(0x10EC, 0x6155) ||
+				    CHK_SVID_SMID(0x10EC, 0x6177) ||
+				    CHK_SVID_SMID(0x10EC, 0x6178) ||
+				    CHK_SVID_SMID(0x10EC, 0x6179) ||
+				    CHK_SVID_SMID(0x10EC, 0x6180) ||
+				    CHK_SVID_SMID(0x10EC, 0x8151) ||
+				    CHK_SVID_SMID(0x10EC, 0x8152) ||
+				    CHK_SVID_SMID(0x10EC, 0x8154) ||
+				    CHK_SVID_SMID(0x10EC, 0x8155) ||
+				    CHK_SVID_SMID(0x10EC, 0x8181) ||
+				    CHK_SVID_SMID(0x10EC, 0x8182) ||
+				    CHK_SVID_SMID(0x10EC, 0x8184) ||
+				    CHK_SVID_SMID(0x10EC, 0x8185) ||
+				    CHK_SVID_SMID(0x10EC, 0x9151) ||
+				    CHK_SVID_SMID(0x10EC, 0x9152) ||
+				    CHK_SVID_SMID(0x10EC, 0x9154) ||
+				    CHK_SVID_SMID(0x10EC, 0x9155) ||
+				    CHK_SVID_SMID(0x10EC, 0x9181) ||
+				    CHK_SVID_SMID(0x10EC, 0x9182) ||
+				    CHK_SVID_SMID(0x10EC, 0x9184) ||
+				    CHK_SVID_SMID(0x10EC, 0x9185))
+					rtlhal->oem_id = RT_CID_TOSHIBA;
+				else if (rtlefuse->eeprom_svid == 0x1025)
+					rtlhal->oem_id = RT_CID_819x_Acer;
+				else if (CHK_SVID_SMID(0x10EC, 0x6191) ||
+					 CHK_SVID_SMID(0x10EC, 0x6192) ||
+					 CHK_SVID_SMID(0x10EC, 0x6193) ||
+					 CHK_SVID_SMID(0x10EC, 0x7191) ||
+					 CHK_SVID_SMID(0x10EC, 0x7192) ||
+					 CHK_SVID_SMID(0x10EC, 0x7193) ||
+					 CHK_SVID_SMID(0x10EC, 0x8191) ||
+					 CHK_SVID_SMID(0x10EC, 0x8192) ||
+					 CHK_SVID_SMID(0x10EC, 0x8193))
+					rtlhal->oem_id = RT_CID_819x_SAMSUNG;
+				else if (CHK_SVID_SMID(0x10EC, 0x8195) ||
+					 CHK_SVID_SMID(0x10EC, 0x9195) ||
+					 CHK_SVID_SMID(0x10EC, 0x7194) ||
+					 CHK_SVID_SMID(0x10EC, 0x8200) ||
+					 CHK_SVID_SMID(0x10EC, 0x8201) ||
+					 CHK_SVID_SMID(0x10EC, 0x8202) ||
+					 CHK_SVID_SMID(0x10EC, 0x9200))
+					rtlhal->oem_id = RT_CID_819x_Lenovo;
+				else if (CHK_SVID_SMID(0x10EC, 0x8197) ||
+					 CHK_SVID_SMID(0x10EC, 0x9196))
+					rtlhal->oem_id = RT_CID_819x_CLEVO;
+				else if (CHK_SVID_SMID(0x1028, 0x8194) ||
+					 CHK_SVID_SMID(0x1028, 0x8198) ||
+					 CHK_SVID_SMID(0x1028, 0x9197) ||
+					 CHK_SVID_SMID(0x1028, 0x9198))
+					rtlhal->oem_id = RT_CID_819x_DELL;
+				else if (CHK_SVID_SMID(0x103C, 0x1629))
+					rtlhal->oem_id = RT_CID_819x_HP;
+				else if (CHK_SVID_SMID(0x1A32, 0x2315))
+					rtlhal->oem_id = RT_CID_819x_QMI;
+				else if (CHK_SVID_SMID(0x10EC, 0x8203))
+					rtlhal->oem_id = RT_CID_819x_PRONETS;
+				else if (CHK_SVID_SMID(0x1043, 0x84B5))
+					rtlhal->oem_id =
+						 RT_CID_819x_Edimax_ASUS;
+				else
+					rtlhal->oem_id = RT_CID_DEFAULT;
+			} else if (rtlefuse->eeprom_did == 0x8178) {
+				if (CHK_SVID_SMID(0x10EC, 0x6181) ||
+				    CHK_SVID_SMID(0x10EC, 0x6182) ||
+				    CHK_SVID_SMID(0x10EC, 0x6184) ||
+				    CHK_SVID_SMID(0x10EC, 0x6185) ||
+				    CHK_SVID_SMID(0x10EC, 0x7181) ||
+				    CHK_SVID_SMID(0x10EC, 0x7182) ||
+				    CHK_SVID_SMID(0x10EC, 0x7184) ||
+				    CHK_SVID_SMID(0x10EC, 0x7185) ||
+				    CHK_SVID_SMID(0x10EC, 0x8181) ||
+				    CHK_SVID_SMID(0x10EC, 0x8182) ||
+				    CHK_SVID_SMID(0x10EC, 0x8184) ||
+				    CHK_SVID_SMID(0x10EC, 0x8185) ||
+				    CHK_SVID_SMID(0x10EC, 0x9181) ||
+				    CHK_SVID_SMID(0x10EC, 0x9182) ||
+				    CHK_SVID_SMID(0x10EC, 0x9184) ||
+				    CHK_SVID_SMID(0x10EC, 0x9185))
+					rtlhal->oem_id = RT_CID_TOSHIBA;
+				else if (rtlefuse->eeprom_svid == 0x1025)
+					rtlhal->oem_id = RT_CID_819x_Acer;
+				else if (CHK_SVID_SMID(0x10EC, 0x8186))
+					rtlhal->oem_id = RT_CID_819x_PRONETS;
+				else if (CHK_SVID_SMID(0x1043, 0x8486))
+					rtlhal->oem_id =
+						     RT_CID_819x_Edimax_ASUS;
+				else
+					rtlhal->oem_id = RT_CID_DEFAULT;
+			} else {
+					rtlhal->oem_id = RT_CID_DEFAULT;
+			}
+			break;
+		case EEPROM_CID_TOSHIBA:
+			rtlhal->oem_id = RT_CID_TOSHIBA;
+			break;
+		case EEPROM_CID_CCX:
+			rtlhal->oem_id = RT_CID_CCX;
+			break;
+		case EEPROM_CID_QMI:
+			rtlhal->oem_id = RT_CID_819x_QMI;
+			break;
+		case EEPROM_CID_WHQL:
+				break;
+		default:
+			rtlhal->oem_id = RT_CID_DEFAULT;
+			break;
+
+		}
+	}
+}
+
+static void _rtl8723ae_hal_customized_behavior(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	switch (rtlhal->oem_id) {
+	case RT_CID_819x_HP:
+		pcipriv->ledctl.led_opendrain = true;
+		break;
+	case RT_CID_819x_Lenovo:
+	case RT_CID_DEFAULT:
+	case RT_CID_TOSHIBA:
+	case RT_CID_CCX:
+	case RT_CID_819x_Acer:
+	case RT_CID_WHQL:
+	default:
+		break;
+	}
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+		 "RT Customized ID: 0x%02X\n", rtlhal->oem_id);
+}
+
+void rtl8723ae_read_eeprom_info(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 tmp_u1b;
+	u32 value32;
+
+	value32 = rtl_read_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST]);
+	value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0);
+	rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST], value32);
+
+	rtlhal->version = _rtl8723ae_read_chip_version(hw);
+
+	if (get_rf_type(rtlphy) == RF_1T1R)
+		rtlpriv->dm.rfpath_rxenable[0] = true;
+	else
+		rtlpriv->dm.rfpath_rxenable[0] =
+		    rtlpriv->dm.rfpath_rxenable[1] = true;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n",
+		 rtlhal->version);
+
+	tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR);
+	if (tmp_u1b & BIT(4)) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n");
+		rtlefuse->epromtype = EEPROM_93C46;
+	} else {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n");
+		rtlefuse->epromtype = EEPROM_BOOT_EFUSE;
+	}
+	if (tmp_u1b & BIT(5)) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n");
+		rtlefuse->autoload_failflag = false;
+		_rtl8723ae_read_adapter_info(hw, false);
+	} else {
+		rtlefuse->autoload_failflag = true;
+		_rtl8723ae_read_adapter_info(hw, false);
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n");
+	}
+	_rtl8723ae_hal_customized_behavior(hw);
+}
+
+static void rtl8723ae_update_hal_rate_table(struct ieee80211_hw *hw,
+					    struct ieee80211_sta *sta)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u32 ratr_value;
+	u8 ratr_index = 0;
+	u8 nmode = mac->ht_enable;
+	u8 mimo_ps = IEEE80211_SMPS_OFF;
+	u8 curtxbw_40mhz = mac->bw_40;
+	u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
+				1 : 0;
+	u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
+				1 : 0;
+	enum wireless_mode wirelessmode = mac->mode;
+
+	if (rtlhal->current_bandtype == BAND_ON_5G)
+		ratr_value = sta->supp_rates[1] << 4;
+	else
+		ratr_value = sta->supp_rates[0];
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		ratr_value = 0xfff;
+	ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
+		       sta->ht_cap.mcs.rx_mask[0] << 12);
+	switch (wirelessmode) {
+	case WIRELESS_MODE_B:
+		if (ratr_value & 0x0000000c)
+			ratr_value &= 0x0000000d;
+		else
+			ratr_value &= 0x0000000f;
+		break;
+	case WIRELESS_MODE_G:
+		ratr_value &= 0x00000FF5;
+		break;
+	case WIRELESS_MODE_N_24G:
+	case WIRELESS_MODE_N_5G:
+		nmode = 1;
+		if (mimo_ps == IEEE80211_SMPS_STATIC) {
+			ratr_value &= 0x0007F005;
+		} else {
+			u32 ratr_mask;
+
+			if (get_rf_type(rtlphy) == RF_1T2R ||
+			    get_rf_type(rtlphy) == RF_1T1R)
+				ratr_mask = 0x000ff005;
+			else
+				ratr_mask = 0x0f0ff005;
+
+			ratr_value &= ratr_mask;
+		}
+		break;
+	default:
+		if (rtlphy->rf_type == RF_1T2R)
+			ratr_value &= 0x000ff0ff;
+		else
+			ratr_value &= 0x0f0ff0ff;
+
+		break;
+	}
+
+	if ((pcipriv->bt_coexist.bt_coexistence) &&
+	    (pcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) &&
+	    (pcipriv->bt_coexist.bt_cur_state) &&
+	    (pcipriv->bt_coexist.bt_ant_isolation) &&
+	    ((pcipriv->bt_coexist.bt_service == BT_SCO) ||
+	    (pcipriv->bt_coexist.bt_service == BT_BUSY)))
+		ratr_value &= 0x0fffcfc0;
+	else
+		ratr_value &= 0x0FFFFFFF;
+
+	if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) ||
+	   (!curtxbw_40mhz && curshortgi_20mhz)))
+		ratr_value |= 0x10000000;
+
+	rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value);
+
+	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
+		 "%x\n", rtl_read_dword(rtlpriv, REG_ARFR0));
+}
+
+static void rtl8723ae_update_hal_rate_mask(struct ieee80211_hw *hw,
+		struct ieee80211_sta *sta, u8 rssi_level)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_sta_info *sta_entry = NULL;
+	u32 ratr_bitmap;
+	u8 ratr_index;
+	u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
+				? 1 : 0;
+	u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
+				1 : 0;
+	u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
+				1 : 0;
+	enum wireless_mode wirelessmode = 0;
+	bool shortgi = false;
+	u8 rate_mask[5];
+	u8 macid = 0;
+	u8 mimo_ps = IEEE80211_SMPS_OFF;
+
+	sta_entry = (struct rtl_sta_info *) sta->drv_priv;
+	wirelessmode = sta_entry->wireless_mode;
+	if (mac->opmode == NL80211_IFTYPE_STATION)
+		curtxbw_40mhz = mac->bw_40;
+	else if (mac->opmode == NL80211_IFTYPE_AP ||
+		mac->opmode == NL80211_IFTYPE_ADHOC)
+		macid = sta->aid + 1;
+
+	if (rtlhal->current_bandtype == BAND_ON_5G)
+		ratr_bitmap = sta->supp_rates[1] << 4;
+	else
+		ratr_bitmap = sta->supp_rates[0];
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		ratr_bitmap = 0xfff;
+	ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
+			sta->ht_cap.mcs.rx_mask[0] << 12);
+	switch (wirelessmode) {
+	case WIRELESS_MODE_B:
+		ratr_index = RATR_INX_WIRELESS_B;
+		if (ratr_bitmap & 0x0000000c)
+			ratr_bitmap &= 0x0000000d;
+		else
+			ratr_bitmap &= 0x0000000f;
+		break;
+	case WIRELESS_MODE_G:
+		ratr_index = RATR_INX_WIRELESS_GB;
+
+		if (rssi_level == 1)
+			ratr_bitmap &= 0x00000f00;
+		else if (rssi_level == 2)
+			ratr_bitmap &= 0x00000ff0;
+		else
+			ratr_bitmap &= 0x00000ff5;
+		break;
+	case WIRELESS_MODE_A:
+		ratr_index = RATR_INX_WIRELESS_A;
+		ratr_bitmap &= 0x00000ff0;
+		break;
+	case WIRELESS_MODE_N_24G:
+	case WIRELESS_MODE_N_5G:
+		ratr_index = RATR_INX_WIRELESS_NGB;
+
+		if (mimo_ps == IEEE80211_SMPS_STATIC) {
+			if (rssi_level == 1)
+				ratr_bitmap &= 0x00070000;
+			else if (rssi_level == 2)
+				ratr_bitmap &= 0x0007f000;
+			else
+				ratr_bitmap &= 0x0007f005;
+		} else {
+			if (rtlphy->rf_type == RF_1T2R ||
+			    rtlphy->rf_type == RF_1T1R) {
+				if (curtxbw_40mhz) {
+					if (rssi_level == 1)
+						ratr_bitmap &= 0x000f0000;
+					else if (rssi_level == 2)
+						ratr_bitmap &= 0x000ff000;
+					else
+						ratr_bitmap &= 0x000ff015;
+				} else {
+					if (rssi_level == 1)
+						ratr_bitmap &= 0x000f0000;
+					else if (rssi_level == 2)
+						ratr_bitmap &= 0x000ff000;
+					else
+						ratr_bitmap &= 0x000ff005;
+				}
+			} else {
+				if (curtxbw_40mhz) {
+					if (rssi_level == 1)
+						ratr_bitmap &= 0x0f0f0000;
+					else if (rssi_level == 2)
+						ratr_bitmap &= 0x0f0ff000;
+					else
+						ratr_bitmap &= 0x0f0ff015;
+				} else {
+					if (rssi_level == 1)
+						ratr_bitmap &= 0x0f0f0000;
+					else if (rssi_level == 2)
+						ratr_bitmap &= 0x0f0ff000;
+					else
+						ratr_bitmap &= 0x0f0ff005;
+				}
+			}
+		}
+
+		if ((curtxbw_40mhz && curshortgi_40mhz) ||
+		    (!curtxbw_40mhz && curshortgi_20mhz)) {
+			if (macid == 0)
+				shortgi = true;
+			else if (macid == 1)
+				shortgi = false;
+		}
+		break;
+	default:
+		ratr_index = RATR_INX_WIRELESS_NGB;
+
+		if (rtlphy->rf_type == RF_1T2R)
+			ratr_bitmap &= 0x000ff0ff;
+		else
+			ratr_bitmap &= 0x0f0ff0ff;
+		break;
+	}
+	sta_entry->ratr_index = ratr_index;
+
+	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
+		 "ratr_bitmap :%x\n", ratr_bitmap);
+	/* convert ratr_bitmap to le byte array */
+	rate_mask[0] = ratr_bitmap;
+	rate_mask[1] = (ratr_bitmap >>= 8);
+	rate_mask[2] = (ratr_bitmap >>= 8);
+	rate_mask[3] = ((ratr_bitmap >> 8) & 0x0f) | (ratr_index << 4);
+	rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
+	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
+		 "Rate_index:%x, ratr_bitmap: %*phC\n",
+		 ratr_index, 5, rate_mask);
+	rtl8723ae_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
+}
+
+void rtl8723ae_update_hal_rate_tbl(struct ieee80211_hw *hw,
+		struct ieee80211_sta *sta, u8 rssi_level)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (rtlpriv->dm.useramask)
+		rtl8723ae_update_hal_rate_mask(hw, sta, rssi_level);
+	else
+		rtl8723ae_update_hal_rate_table(hw, sta);
+}
+
+void rtl8723ae_update_channel_access_setting(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u16 sifs_timer;
+
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME,
+				      (u8 *)&mac->slot_time);
+	if (!mac->ht_enable)
+		sifs_timer = 0x0a0a;
+	else
+		sifs_timer = 0x1010;
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer);
+}
+
+bool rtl8723ae_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate;
+	u8 u1tmp;
+	bool actuallyset = false;
+
+	if (rtlpriv->rtlhal.being_init_adapter)
+		return false;
+
+	if (ppsc->swrf_processing)
+		return false;
+
+	spin_lock(&rtlpriv->locks.rf_ps_lock);
+	if (ppsc->rfchange_inprogress) {
+		spin_unlock(&rtlpriv->locks.rf_ps_lock);
+		return false;
+	} else {
+		ppsc->rfchange_inprogress = true;
+		spin_unlock(&rtlpriv->locks.rf_ps_lock);
+	}
+
+	cur_rfstate = ppsc->rfpwr_state;
+
+	rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL_2,
+		       rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL_2)&~(BIT(1)));
+
+	u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL_2);
+
+	if (rtlphy->polarity_ctl)
+		e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFOFF : ERFON;
+	else
+		e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFON : ERFOFF;
+
+	if ((ppsc->hwradiooff == true) && (e_rfpowerstate_toset == ERFON)) {
+		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+			 "GPIOChangeRF  - HW Radio ON, RF ON\n");
+
+		e_rfpowerstate_toset = ERFON;
+		ppsc->hwradiooff = false;
+		actuallyset = true;
+	} else if ((ppsc->hwradiooff == false)
+		   && (e_rfpowerstate_toset == ERFOFF)) {
+		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+			 "GPIOChangeRF  - HW Radio OFF, RF OFF\n");
+
+		e_rfpowerstate_toset = ERFOFF;
+		ppsc->hwradiooff = true;
+		actuallyset = true;
+	}
+
+	if (actuallyset) {
+		spin_lock(&rtlpriv->locks.rf_ps_lock);
+		ppsc->rfchange_inprogress = false;
+		spin_unlock(&rtlpriv->locks.rf_ps_lock);
+	} else {
+		if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC)
+			RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+
+		spin_lock(&rtlpriv->locks.rf_ps_lock);
+		ppsc->rfchange_inprogress = false;
+		spin_unlock(&rtlpriv->locks.rf_ps_lock);
+	}
+
+	*valid = 1;
+	return !ppsc->hwradiooff;
+}
+
+void rtl8723ae_set_key(struct ieee80211_hw *hw, u32 key_index,
+		       u8 *p_macaddr, bool is_group, u8 enc_algo,
+		       bool is_wepkey, bool clear_all)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 *macaddr = p_macaddr;
+	u32 entry_id = 0;
+	bool is_pairwise = false;
+	static u8 cam_const_addr[4][6] = {
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
+	};
+	static u8 cam_const_broad[] = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+	};
+
+	if (clear_all) {
+		u8 idx = 0;
+		u8 cam_offset = 0;
+		u8 clear_number = 5;
+
+		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n");
+
+		for (idx = 0; idx < clear_number; idx++) {
+			rtl_cam_mark_invalid(hw, cam_offset + idx);
+			rtl_cam_empty_entry(hw, cam_offset + idx);
+
+			if (idx < 5) {
+				memset(rtlpriv->sec.key_buf[idx], 0,
+				       MAX_KEY_LEN);
+				rtlpriv->sec.key_len[idx] = 0;
+			}
+		}
+	} else {
+		switch (enc_algo) {
+		case WEP40_ENCRYPTION:
+			enc_algo = CAM_WEP40;
+			break;
+		case WEP104_ENCRYPTION:
+			enc_algo = CAM_WEP104;
+			break;
+		case TKIP_ENCRYPTION:
+			enc_algo = CAM_TKIP;
+			break;
+		case AESCCMP_ENCRYPTION:
+			enc_algo = CAM_AES;
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 "switch case not processed\n");
+			enc_algo = CAM_TKIP;
+			break;
+		}
+
+		if (is_wepkey || rtlpriv->sec.use_defaultkey) {
+			macaddr = cam_const_addr[key_index];
+			entry_id = key_index;
+		} else {
+			if (is_group) {
+				macaddr = cam_const_broad;
+				entry_id = key_index;
+			} else {
+				if (mac->opmode == NL80211_IFTYPE_AP) {
+					entry_id = rtl_cam_get_free_entry(hw,
+								macaddr);
+					if (entry_id >=  TOTAL_CAM_ENTRY) {
+						RT_TRACE(rtlpriv, COMP_SEC,
+							 DBG_EMERG,
+							 "Can not find free hw security cam entry\n");
+						return;
+					}
+				} else {
+					entry_id = CAM_PAIRWISE_KEY_POSITION;
+				}
+
+				key_index = PAIRWISE_KEYIDX;
+				is_pairwise = true;
+			}
+		}
+
+		if (rtlpriv->sec.key_len[key_index] == 0) {
+			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+				 "delete one entry, entry_id is %d\n",
+				 entry_id);
+			if (mac->opmode == NL80211_IFTYPE_AP)
+				rtl_cam_del_entry(hw, p_macaddr);
+			rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
+		} else {
+			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+				 "add one entry\n");
+			if (is_pairwise) {
+				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+					 "set Pairwiase key\n");
+
+				rtl_cam_add_one_entry(hw, macaddr, key_index,
+					entry_id, enc_algo,
+					CAM_CONFIG_NO_USEDK,
+					rtlpriv->sec.key_buf[key_index]);
+			} else {
+				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+					 "set group key\n");
+
+				if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+					rtl_cam_add_one_entry(hw,
+						rtlefuse->dev_addr,
+						PAIRWISE_KEYIDX,
+						CAM_PAIRWISE_KEY_POSITION,
+						enc_algo,
+						CAM_CONFIG_NO_USEDK,
+						rtlpriv->sec.key_buf
+						[entry_id]);
+				}
+
+				rtl_cam_add_one_entry(hw, macaddr, key_index,
+						entry_id, enc_algo,
+						CAM_CONFIG_NO_USEDK,
+						rtlpriv->sec.key_buf[entry_id]);
+			}
+
+		}
+	}
+}
+
+static void rtl8723ae_bt_var_init(struct ieee80211_hw *hw)
+{
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	pcipriv->bt_coexist.bt_coexistence =
+					pcipriv->bt_coexist.eeprom_bt_coexist;
+	pcipriv->bt_coexist.bt_ant_num =
+					pcipriv->bt_coexist.eeprom_bt_ant_num;
+	pcipriv->bt_coexist.bt_coexist_type =
+					pcipriv->bt_coexist.eeprom_bt_type;
+
+		pcipriv->bt_coexist.bt_ant_isolation =
+				pcipriv->bt_coexist.eeprom_bt_ant_isol;
+
+	pcipriv->bt_coexist.bt_radio_shared_type =
+				pcipriv->bt_coexist.eeprom_bt_radio_shared;
+
+	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+		 "BT Coexistance = 0x%x\n",
+		 pcipriv->bt_coexist.bt_coexistence);
+
+	if (pcipriv->bt_coexist.bt_coexistence) {
+		pcipriv->bt_coexist.bt_busy_traffic = false;
+		pcipriv->bt_coexist.bt_traffic_mode_set = false;
+		pcipriv->bt_coexist.bt_non_traffic_mode_set = false;
+
+		pcipriv->bt_coexist.cstate = 0;
+		pcipriv->bt_coexist.previous_state = 0;
+
+		if (pcipriv->bt_coexist.bt_ant_num == ANT_X2) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "BlueTooth BT_Ant_Num = Antx2\n");
+		} else if (pcipriv->bt_coexist.bt_ant_num == ANT_X1) {
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "BlueTooth BT_Ant_Num = Antx1\n");
+		}
+
+		switch (pcipriv->bt_coexist.bt_coexist_type) {
+		case BT_2WIRE:
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "BlueTooth BT_CoexistType = BT_2Wire\n");
+			break;
+		case BT_ISSC_3WIRE:
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "BlueTooth BT_CoexistType = BT_ISSC_3Wire\n");
+			break;
+		case BT_ACCEL:
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "BlueTooth BT_CoexistType = BT_ACCEL\n");
+			break;
+		case BT_CSR_BC4:
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "BlueTooth BT_CoexistType = BT_CSR_BC4\n");
+			break;
+		case BT_CSR_BC8:
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "BlueTooth BT_CoexistType = BT_CSR_BC8\n");
+			break;
+		case BT_RTL8756:
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "BlueTooth BT_CoexistType = BT_RTL8756\n");
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+				 "BlueTooth BT_CoexistType = Unknown\n");
+			break;
+		}
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "BlueTooth BT_Ant_isolation = %d\n",
+			 pcipriv->bt_coexist.bt_ant_isolation);
+		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
+			 "BT_RadioSharedType = 0x%x\n",
+			 pcipriv->bt_coexist.bt_radio_shared_type);
+		pcipriv->bt_coexist.bt_active_zero_cnt = 0;
+		pcipriv->bt_coexist.cur_bt_disabled = false;
+		pcipriv->bt_coexist.pre_bt_disabled = false;
+	}
+}
+
+void rtl8723ae_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
+					      bool auto_load_fail, u8 *hwinfo)
+{
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 value;
+	u32 tmpu_32;
+
+	if (!auto_load_fail) {
+		tmpu_32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL);
+		if (tmpu_32 & BIT(18))
+			pcipriv->bt_coexist.eeprom_bt_coexist = 1;
+		else
+			pcipriv->bt_coexist.eeprom_bt_coexist = 0;
+		value = hwinfo[RF_OPTION4];
+		pcipriv->bt_coexist.eeprom_bt_type = BT_RTL8723A;
+		pcipriv->bt_coexist.eeprom_bt_ant_num = (value & 0x1);
+		pcipriv->bt_coexist.eeprom_bt_ant_isol = ((value & 0x10) >> 4);
+		pcipriv->bt_coexist.eeprom_bt_radio_shared =
+				((value & 0x20) >> 5);
+	} else {
+		pcipriv->bt_coexist.eeprom_bt_coexist = 0;
+		pcipriv->bt_coexist.eeprom_bt_type = BT_RTL8723A;
+		pcipriv->bt_coexist.eeprom_bt_ant_num = ANT_X2;
+		pcipriv->bt_coexist.eeprom_bt_ant_isol = 0;
+		pcipriv->bt_coexist.eeprom_bt_radio_shared = BT_RADIO_SHARED;
+	}
+
+	rtl8723ae_bt_var_init(hw);
+}
+
+void rtl8723ae_bt_reg_init(struct ieee80211_hw *hw)
+{
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+
+	/* 0:Low, 1:High, 2:From Efuse. */
+	pcipriv->bt_coexist.reg_bt_iso = 2;
+	/* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */
+	pcipriv->bt_coexist.reg_bt_sco = 3;
+	/* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */
+	pcipriv->bt_coexist.reg_bt_sco = 0;
+}
+
+
+void rtl8723ae_bt_hw_init(struct ieee80211_hw *hw)
+{
+}
+
+void rtl8723ae_suspend(struct ieee80211_hw *hw)
+{
+}
+
+void rtl8723ae_resume(struct ieee80211_hw *hw)
+{
+}
+
+/* Turn on AAP (RCR:bit 0) for promicuous mode. */
+void rtl8723ae_allow_all_destaddr(struct ieee80211_hw *hw,
+	bool allow_all_da, bool write_into_reg)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+	if (allow_all_da) /* Set BIT0 */
+		rtlpci->receive_config |= RCR_AAP;
+	else /* Clear BIT0 */
+		rtlpci->receive_config &= ~RCR_AAP;
+
+	if (write_into_reg)
+		rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
+
+
+	RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD,
+		 "receive_config=0x%08X, write_into_reg=%d\n",
+		 rtlpci->receive_config, write_into_reg);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h
new file mode 100644
index 0000000..6fa24f7
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h
@@ -0,0 +1,73 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_HW_H__
+#define __RTL8723E_HW_H__
+
+#define CHK_SVID_SMID(_val1, _val2)				\
+	((rtlefuse->eeprom_svid == (_val1)) &&			\
+	 (rtlefuse->eeprom_smid == (_val2)))
+
+void rtl8723ae_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl8723ae_read_eeprom_info(struct ieee80211_hw *hw);
+
+void rtl8723ae_interrupt_recognized(struct ieee80211_hw *hw,
+				    u32 *p_inta, u32 *p_intb);
+int rtl8723ae_hw_init(struct ieee80211_hw *hw);
+void rtl8723ae_card_disable(struct ieee80211_hw *hw);
+void rtl8723ae_enable_interrupt(struct ieee80211_hw *hw);
+void rtl8723ae_disable_interrupt(struct ieee80211_hw *hw);
+int rtl8723ae_set_network_type(struct ieee80211_hw *hw,
+			       enum nl80211_iftype type);
+void rtl8723ae_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
+void rtl8723ae_set_qos(struct ieee80211_hw *hw, int aci);
+void rtl8723ae_set_beacon_related_registers(struct ieee80211_hw *hw);
+void rtl8723ae_set_beacon_interval(struct ieee80211_hw *hw);
+void rtl8723ae_update_interrupt_mask(struct ieee80211_hw *hw,
+				     u32 add_msr, u32 rm_msr);
+void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl8723ae_update_hal_rate_tbl(struct ieee80211_hw *hw,
+				   struct ieee80211_sta *sta, u8 rssi_level);
+void rtl8723ae_update_channel_access_setting(struct ieee80211_hw *hw);
+bool rtl8723ae_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid);
+void rtl8723ae_enable_hw_security_config(struct ieee80211_hw *hw);
+void rtl8723ae_set_key(struct ieee80211_hw *hw, u32 key_index,
+		       u8 *p_macaddr, bool is_group, u8 enc_algo,
+		       bool is_wepkey, bool clear_all);
+
+void rtl8723ae_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
+					      bool autoload_fail, u8 *hwinfo);
+void rtl8723ae_bt_reg_init(struct ieee80211_hw *hw);
+void rtl8723ae_bt_hw_init(struct ieee80211_hw *hw);
+void rtl8723ae_suspend(struct ieee80211_hw *hw);
+void rtl8723ae_resume(struct ieee80211_hw *hw);
+void rtl8723ae_allow_all_destaddr(struct ieee80211_hw *hw,
+				  bool allow_all_da, bool write_into_reg);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/led.c b/drivers/net/wireless/rtlwifi/rtl8723ae/led.c
new file mode 100644
index 0000000..9c4e1d8
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/led.c
@@ -0,0 +1,151 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "reg.h"
+#include "led.h"
+
+static void _rtl8723ae_init_led(struct ieee80211_hw *hw,
+				struct rtl_led *pled, enum rtl_led_pin ledpin)
+{
+	pled->hw = hw;
+	pled->ledpin = ledpin;
+	pled->ledon = false;
+}
+
+void rtl8723ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 ledcfg;
+
+	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
+		 "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+
+	ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
+
+	switch (pled->ledpin) {
+	case LED_PIN_GPIO0:
+		break;
+	case LED_PIN_LED0:
+		rtl_write_byte(rtlpriv,
+			       REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5) | BIT(6));
+		break;
+	case LED_PIN_LED1:
+		rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5));
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "switch case not processed\n");
+		break;
+	}
+	pled->ledon = true;
+}
+
+void rtl8723ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	u8 ledcfg;
+
+	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
+		 "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+
+	ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
+
+	switch (pled->ledpin) {
+	case LED_PIN_GPIO0:
+		break;
+	case LED_PIN_LED0:
+		ledcfg &= 0xf0;
+		if (pcipriv->ledctl.led_opendrain)
+			rtl_write_byte(rtlpriv, REG_LEDCFG2,
+				       (ledcfg | BIT(1) | BIT(5) | BIT(6)));
+		else
+			rtl_write_byte(rtlpriv, REG_LEDCFG2,
+				       (ledcfg | BIT(3) | BIT(5) | BIT(6)));
+		break;
+	case LED_PIN_LED1:
+		ledcfg &= 0x0f;
+		rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3)));
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "switch case not processed\n");
+		break;
+	}
+	pled->ledon = false;
+}
+
+void rtl8723ae_init_sw_leds(struct ieee80211_hw *hw)
+{
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+
+	_rtl8723ae_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0);
+	_rtl8723ae_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1);
+}
+
+static void _rtl8723ae_sw_led_control(struct ieee80211_hw *hw,
+				    enum led_ctl_mode ledaction)
+{
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
+
+	switch (ledaction) {
+	case LED_CTL_POWER_ON:
+	case LED_CTL_LINK:
+	case LED_CTL_NO_LINK:
+		rtl8723ae_sw_led_on(hw, pLed0);
+		break;
+	case LED_CTL_POWER_OFF:
+		rtl8723ae_sw_led_off(hw, pLed0);
+		break;
+	default:
+		break;
+	}
+}
+
+void rtl8723ae_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+	if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) &&
+	    (ledaction == LED_CTL_TX ||
+	     ledaction == LED_CTL_RX ||
+	     ledaction == LED_CTL_SITE_SURVEY ||
+	     ledaction == LED_CTL_LINK ||
+	     ledaction == LED_CTL_NO_LINK ||
+	     ledaction == LED_CTL_START_TO_LINK ||
+	     ledaction == LED_CTL_POWER_ON)) {
+		return;
+	}
+	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d,\n", ledaction);
+	_rtl8723ae_sw_led_control(hw, ledaction);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/led.h b/drivers/net/wireless/rtlwifi/rtl8723ae/led.h
new file mode 100644
index 0000000..2cb88e7
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/led.h
@@ -0,0 +1,39 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CE_LED_H__
+#define __RTL92CE_LED_H__
+
+void rtl8723ae_init_sw_leds(struct ieee80211_hw *hw);
+void rtl8723ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl8723ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl8723ae_led_control(struct ieee80211_hw *hw,
+			   enum led_ctl_mode ledaction);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c
new file mode 100644
index 0000000..39cc793
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c
@@ -0,0 +1,2044 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../ps.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+#include "table.h"
+
+/* static forward definitions */
+static u32 _phy_fw_rf_serial_read(struct ieee80211_hw *hw,
+				  enum radio_path rfpath, u32 offset);
+static void _phy_fw_rf_serial_write(struct ieee80211_hw *hw,
+				    enum radio_path rfpath,
+				    u32 offset, u32 data);
+static u32 _phy_rf_serial_read(struct ieee80211_hw *hw,
+			       enum radio_path rfpath, u32 offset);
+static void _phy_rf_serial_write(struct ieee80211_hw *hw,
+				 enum radio_path rfpath, u32 offset, u32 data);
+static u32 _phy_calculate_bit_shift(u32 bitmask);
+static bool _phy_bb8192c_config_parafile(struct ieee80211_hw *hw);
+static bool _phy_cfg_mac_w_header(struct ieee80211_hw *hw);
+static bool _phy_cfg_bb_w_header(struct ieee80211_hw *hw, u8 configtype);
+static bool _phy_cfg_bb_w_pgheader(struct ieee80211_hw *hw, u8 configtype);
+static void _phy_init_bb_rf_reg_def(struct ieee80211_hw *hw);
+static bool _phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
+				      u32 cmdtableidx, u32 cmdtablesz,
+				      enum swchnlcmd_id cmdid,
+				      u32 para1, u32 para2,
+				      u32 msdelay);
+static bool _phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, u8 channel,
+				      u8 *stage, u8 *step, u32 *delay);
+static u8 _phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw,
+				enum wireless_mode wirelessmode,
+				long power_indbm);
+static long _phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw,
+				  enum wireless_mode wirelessmode, u8 txpwridx);
+static void rtl8723ae_phy_set_io(struct ieee80211_hw *hw);
+
+u32 rtl8723ae_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr,
+			       u32 bitmask)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 returnvalue, originalvalue, bitshift;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+		 "regaddr(%#x), bitmask(%#x)\n", regaddr, bitmask);
+	originalvalue = rtl_read_dword(rtlpriv, regaddr);
+	bitshift = _phy_calculate_bit_shift(bitmask);
+	returnvalue = (originalvalue & bitmask) >> bitshift;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+		 "BBR MASK=0x%x Addr[0x%x]=0x%x\n", bitmask, regaddr,
+		 originalvalue);
+
+	return returnvalue;
+}
+
+void rtl8723ae_phy_set_bb_reg(struct ieee80211_hw *hw,
+			      u32 regaddr, u32 bitmask, u32 data)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 originalvalue, bitshift;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+		 "regaddr(%#x), bitmask(%#x), data(%#x)\n", regaddr,
+		 bitmask, data);
+
+	if (bitmask != MASKDWORD) {
+		originalvalue = rtl_read_dword(rtlpriv, regaddr);
+		bitshift = _phy_calculate_bit_shift(bitmask);
+		data = ((originalvalue & (~bitmask)) | (data << bitshift));
+	}
+
+	rtl_write_dword(rtlpriv, regaddr, data);
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+		 "regaddr(%#x), bitmask(%#x), data(%#x)\n",
+		 regaddr, bitmask, data);
+}
+
+u32 rtl8723ae_phy_query_rf_reg(struct ieee80211_hw *hw,
+			       enum radio_path rfpath, u32 regaddr, u32 bitmask)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 original_value, readback_value, bitshift;
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	unsigned long flags;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+		 "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n",
+		 regaddr, rfpath, bitmask);
+
+	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+
+	if (rtlphy->rf_mode != RF_OP_BY_FW)
+		original_value = _phy_rf_serial_read(hw, rfpath, regaddr);
+	else
+		original_value = _phy_fw_rf_serial_read(hw, rfpath, regaddr);
+
+	bitshift = _phy_calculate_bit_shift(bitmask);
+	readback_value = (original_value & bitmask) >> bitshift;
+
+	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+		 "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n",
+		 regaddr, rfpath, bitmask, original_value);
+
+	return readback_value;
+}
+
+void rtl8723ae_phy_set_rf_reg(struct ieee80211_hw *hw,
+			      enum radio_path rfpath,
+			      u32 regaddr, u32 bitmask, u32 data)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 original_value, bitshift;
+	unsigned long flags;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+		 "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
+		 regaddr, bitmask, data, rfpath);
+
+	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
+
+	if (rtlphy->rf_mode != RF_OP_BY_FW) {
+		if (bitmask != RFREG_OFFSET_MASK) {
+			original_value = _phy_rf_serial_read(hw, rfpath,
+							     regaddr);
+			bitshift = _phy_calculate_bit_shift(bitmask);
+			data = ((original_value & (~bitmask)) |
+			       (data << bitshift));
+		}
+
+		_phy_rf_serial_write(hw, rfpath, regaddr, data);
+	} else {
+		if (bitmask != RFREG_OFFSET_MASK) {
+			original_value = _phy_fw_rf_serial_read(hw, rfpath,
+								regaddr);
+			bitshift = _phy_calculate_bit_shift(bitmask);
+			data = ((original_value & (~bitmask)) |
+			       (data << bitshift));
+		}
+		_phy_fw_rf_serial_write(hw, rfpath, regaddr, data);
+	}
+
+	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+		 "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
+		 regaddr, bitmask, data, rfpath);
+}
+
+static u32 _phy_fw_rf_serial_read(struct ieee80211_hw *hw,
+					    enum radio_path rfpath, u32 offset)
+{
+	RT_ASSERT(false, "deprecated!\n");
+	return 0;
+}
+
+static void _phy_fw_rf_serial_write(struct ieee80211_hw *hw,
+				    enum radio_path rfpath,
+				    u32 offset, u32 data)
+{
+	RT_ASSERT(false, "deprecated!\n");
+}
+
+static u32 _phy_rf_serial_read(struct ieee80211_hw *hw,
+			       enum radio_path rfpath, u32 offset)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+	u32 newoffset;
+	u32 tmplong, tmplong2;
+	u8 rfpi_enable = 0;
+	u32 retvalue;
+
+	offset &= 0x3f;
+	newoffset = offset;
+	if (RT_CANNOT_IO(hw)) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "return all one\n");
+		return 0xFFFFFFFF;
+	}
+	tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD);
+	if (rfpath == RF90_PATH_A)
+		tmplong2 = tmplong;
+	else
+		tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD);
+	tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) |
+	    (newoffset << 23) | BLSSIREADEDGE;
+	rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD,
+		      tmplong & (~BLSSIREADEDGE));
+	mdelay(1);
+	rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2);
+	mdelay(1);
+	rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD,
+		      tmplong | BLSSIREADEDGE);
+	mdelay(1);
+	if (rfpath == RF90_PATH_A)
+		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1,
+						 BIT(8));
+	else if (rfpath == RF90_PATH_B)
+		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1,
+						 BIT(8));
+	if (rfpi_enable)
+		retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi,
+					 BLSSIREADBACKDATA);
+	else
+		retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb,
+					 BLSSIREADBACKDATA);
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]=0x%x\n",
+		 rfpath, pphyreg->rf_rb, retvalue);
+	return retvalue;
+}
+
+static void _phy_rf_serial_write(struct ieee80211_hw *hw,
+				 enum radio_path rfpath, u32 offset, u32 data)
+{
+	u32 data_and_addr;
+	u32 newoffset;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+
+	if (RT_CANNOT_IO(hw)) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "stop\n");
+		return;
+	}
+	offset &= 0x3f;
+	newoffset = offset;
+	data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff;
+	rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr);
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFW-%d Addr[0x%x]=0x%x\n",
+		 rfpath, pphyreg->rf3wire_offset, data_and_addr);
+}
+
+static u32 _phy_calculate_bit_shift(u32 bitmask)
+{
+	u32 i;
+
+	for (i = 0; i <= 31; i++) {
+		if (((bitmask >> i) & 0x1) == 1)
+			break;
+	}
+	return i;
+}
+
+static void _rtl8723ae_phy_bb_config_1t(struct ieee80211_hw *hw)
+{
+	rtl_set_bbreg(hw, RFPGA0_TXINFO, 0x3, 0x2);
+	rtl_set_bbreg(hw, RFPGA1_TXINFO, 0x300033, 0x200022);
+	rtl_set_bbreg(hw, RCCK0_AFESETTING, MASKBYTE3, 0x45);
+	rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x23);
+	rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, 0x30, 0x1);
+	rtl_set_bbreg(hw, 0xe74, 0x0c000000, 0x2);
+	rtl_set_bbreg(hw, 0xe78, 0x0c000000, 0x2);
+	rtl_set_bbreg(hw, 0xe7c, 0x0c000000, 0x2);
+	rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2);
+	rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2);
+}
+
+bool rtl8723ae_phy_mac_config(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	bool rtstatus = _phy_cfg_mac_w_header(hw);
+	rtl_write_byte(rtlpriv, 0x04CA, 0x0A);
+	return rtstatus;
+}
+
+bool rtl8723ae_phy_bb_config(struct ieee80211_hw *hw)
+{
+	bool rtstatus = true;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 tmpu1b;
+	u8 reg_hwparafile = 1;
+
+	_phy_init_bb_rf_reg_def(hw);
+
+	/* 1. 0x28[1] = 1 */
+	tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_PLL_CTRL);
+	udelay(2);
+	rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, (tmpu1b|BIT(1)));
+	udelay(2);
+	/* 2. 0x29[7:0] = 0xFF */
+	rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL+1, 0xff);
+	udelay(2);
+
+	/* 3. 0x02[1:0] = 2b'11 */
+	tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, (tmpu1b |
+		       FEN_BB_GLB_RSTn | FEN_BBRSTB));
+
+	/* 4. 0x25[6] = 0 */
+	tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+1);
+	rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+1, (tmpu1b&(~BIT(6))));
+
+	/* 5. 0x24[20] = 0	Advised by SD3 Alex Wang. 2011.02.09. */
+	tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+2);
+	rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+2, (tmpu1b&(~BIT(4))));
+
+	/* 6. 0x1f[7:0] = 0x07 */
+	rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x07);
+
+	if (reg_hwparafile == 1)
+		rtstatus = _phy_bb8192c_config_parafile(hw);
+	return rtstatus;
+}
+
+bool rtl8723ae_phy_rf_config(struct ieee80211_hw *hw)
+{
+	return rtl8723ae_phy_rf6052_config(hw);
+}
+
+static bool _phy_bb8192c_config_parafile(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	bool rtstatus;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "==>\n");
+	rtstatus = _phy_cfg_bb_w_header(hw, BASEBAND_CONFIG_PHY_REG);
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!");
+		return false;
+	}
+
+	if (rtlphy->rf_type == RF_1T2R) {
+		_rtl8723ae_phy_bb_config_1t(hw);
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Config to 1T!!\n");
+	}
+	if (rtlefuse->autoload_failflag == false) {
+		rtlphy->pwrgroup_cnt = 0;
+		rtstatus = _phy_cfg_bb_w_pgheader(hw, BASEBAND_CONFIG_PHY_REG);
+	}
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!");
+		return false;
+	}
+	rtstatus = _phy_cfg_bb_w_header(hw, BASEBAND_CONFIG_AGC_TAB);
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n");
+		return false;
+	}
+	rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw,
+					 RFPGA0_XA_HSSIPARAMETER2, 0x200));
+	return true;
+}
+
+static bool _phy_cfg_mac_w_header(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i;
+	u32 arraylength;
+	u32 *ptrarray;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl723MACPHY_Array\n");
+	arraylength = RTL8723E_MACARRAYLENGTH;
+	ptrarray = RTL8723EMAC_ARRAY;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+		 "Img:RTL8192CEMAC_2T_ARRAY\n");
+	for (i = 0; i < arraylength; i = i + 2)
+		rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]);
+	return true;
+}
+
+static bool _phy_cfg_bb_w_header(struct ieee80211_hw *hw, u8 configtype)
+{
+	int i;
+	u32 *phy_regarray_table;
+	u32 *agctab_array_table;
+	u16 phy_reg_arraylen, agctab_arraylen;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	agctab_arraylen = RTL8723E_AGCTAB_1TARRAYLENGTH;
+	agctab_array_table = RTL8723EAGCTAB_1TARRAY;
+	phy_reg_arraylen = RTL8723E_PHY_REG_1TARRAY_LENGTH;
+	phy_regarray_table = RTL8723EPHY_REG_1TARRAY;
+	if (configtype == BASEBAND_CONFIG_PHY_REG) {
+		for (i = 0; i < phy_reg_arraylen; i = i + 2) {
+			if (phy_regarray_table[i] == 0xfe)
+				mdelay(50);
+			else if (phy_regarray_table[i] == 0xfd)
+				mdelay(5);
+			else if (phy_regarray_table[i] == 0xfc)
+				mdelay(1);
+			else if (phy_regarray_table[i] == 0xfb)
+				udelay(50);
+			else if (phy_regarray_table[i] == 0xfa)
+				udelay(5);
+			else if (phy_regarray_table[i] == 0xf9)
+				udelay(1);
+			rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD,
+				      phy_regarray_table[i + 1]);
+			udelay(1);
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+				 "The phy_regarray_table[0] is %x"
+				 " Rtl819XPHY_REGArray[1] is %x\n",
+				 phy_regarray_table[i],
+				 phy_regarray_table[i + 1]);
+		}
+	} else if (configtype == BASEBAND_CONFIG_AGC_TAB) {
+		for (i = 0; i < agctab_arraylen; i = i + 2) {
+			rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD,
+				      agctab_array_table[i + 1]);
+			udelay(1);
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+				 "The agctab_array_table[0] is "
+				 "%x Rtl819XPHY_REGArray[1] is %x\n",
+				 agctab_array_table[i],
+				 agctab_array_table[i + 1]);
+		}
+	}
+	return true;
+}
+
+static void _st_pwrIdx_dfrate_off(struct ieee80211_hw *hw, u32 regaddr,
+				  u32 bitmask, u32 data)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	switch (regaddr) {
+	case RTXAGC_A_RATE18_06:
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][0] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][0]);
+		break;
+	case RTXAGC_A_RATE54_24:
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][1] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][1]);
+		break;
+	case RTXAGC_A_CCK1_MCS32:
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][6] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][6]);
+		break;
+	case RTXAGC_B_CCK11_A_CCK2_11:
+		if (bitmask == 0xffffff00) {
+			rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][7] = data;
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+				 "MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n",
+				 rtlphy->pwrgroup_cnt,
+				 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][7]);
+		}
+		if (bitmask == 0x000000ff) {
+			rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][15] = data;
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+				 "MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n",
+				 rtlphy->pwrgroup_cnt,
+				 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][15]);
+		}
+		break;
+	case RTXAGC_A_MCS03_MCS00:
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][2] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][2]);
+		break;
+	case RTXAGC_A_MCS07_MCS04:
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][3] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][3]);
+		break;
+	case RTXAGC_A_MCS11_MCS08:
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][4] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][4]);
+		break;
+	case RTXAGC_A_MCS15_MCS12:
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][5] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][5]);
+		break;
+	case RTXAGC_B_RATE18_06:
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][8] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][8]);
+		break;
+	case RTXAGC_B_RATE54_24:
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][9] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][9]);
+		break;
+	case RTXAGC_B_CCK1_55_MCS32:
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][14] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][14]);
+		break;
+	case RTXAGC_B_MCS03_MCS00:
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][10] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][10]);
+		break;
+	case RTXAGC_B_MCS07_MCS04:
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][11] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][11]);
+		break;
+	case RTXAGC_B_MCS11_MCS08:
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][12] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][12]);
+		break;
+	case RTXAGC_B_MCS15_MCS12:
+		rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][13] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 "MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n",
+			 rtlphy->pwrgroup_cnt,
+			 rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][13]);
+		rtlphy->pwrgroup_cnt++;
+		break;
+	}
+}
+
+static bool _phy_cfg_bb_w_pgheader(struct ieee80211_hw *hw, u8 configtype)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int i;
+	u32 *phy_regarray_table_pg;
+	u16 phy_regarray_pg_len;
+
+	phy_regarray_pg_len = RTL8723E_PHY_REG_ARRAY_PGLENGTH;
+	phy_regarray_table_pg = RTL8723EPHY_REG_ARRAY_PG;
+
+	if (configtype == BASEBAND_CONFIG_PHY_REG) {
+		for (i = 0; i < phy_regarray_pg_len; i = i + 3) {
+			if (phy_regarray_table_pg[i] == 0xfe)
+				mdelay(50);
+			else if (phy_regarray_table_pg[i] == 0xfd)
+				mdelay(5);
+			else if (phy_regarray_table_pg[i] == 0xfc)
+				mdelay(1);
+			else if (phy_regarray_table_pg[i] == 0xfb)
+				udelay(50);
+			else if (phy_regarray_table_pg[i] == 0xfa)
+				udelay(5);
+			else if (phy_regarray_table_pg[i] == 0xf9)
+				udelay(1);
+
+			_st_pwrIdx_dfrate_off(hw, phy_regarray_table_pg[i],
+					      phy_regarray_table_pg[i + 1],
+					      phy_regarray_table_pg[i + 2]);
+		}
+	} else {
+		RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+			 "configtype != BaseBand_Config_PHY_REG\n");
+	}
+	return true;
+}
+
+bool rtl8723ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+					     enum radio_path rfpath)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int i;
+	bool rtstatus = true;
+	u32 *radioa_array_table;
+	u32 *radiob_array_table;
+	u16 radioa_arraylen, radiob_arraylen;
+
+	radioa_arraylen = Rtl8723ERADIOA_1TARRAYLENGTH;
+	radioa_array_table = RTL8723E_RADIOA_1TARRAY;
+	radiob_arraylen = RTL8723E_RADIOB_1TARRAYLENGTH;
+	radiob_array_table = RTL8723E_RADIOB_1TARRAY;
+
+	rtstatus = true;
+
+	switch (rfpath) {
+	case RF90_PATH_A:
+		for (i = 0; i < radioa_arraylen; i = i + 2) {
+			if (radioa_array_table[i] == 0xfe)
+				mdelay(50);
+			else if (radioa_array_table[i] == 0xfd)
+				mdelay(5);
+			else if (radioa_array_table[i] == 0xfc)
+				mdelay(1);
+			else if (radioa_array_table[i] == 0xfb)
+				udelay(50);
+			else if (radioa_array_table[i] == 0xfa)
+				udelay(5);
+			else if (radioa_array_table[i] == 0xf9)
+				udelay(1);
+			else {
+				rtl_set_rfreg(hw, rfpath, radioa_array_table[i],
+					      RFREG_OFFSET_MASK,
+					      radioa_array_table[i + 1]);
+				udelay(1);
+			}
+		}
+		break;
+	case RF90_PATH_B:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "switch case not process\n");
+		break;
+	case RF90_PATH_C:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "switch case not process\n");
+		break;
+	case RF90_PATH_D:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "switch case not process\n");
+		break;
+	}
+	return true;
+}
+
+void rtl8723ae_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	rtlphy->default_initialgain[0] =
+	    (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
+	rtlphy->default_initialgain[1] =
+	    (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
+	rtlphy->default_initialgain[2] =
+	    (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0);
+	rtlphy->default_initialgain[3] =
+	    (u8) rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0);
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+		 "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n",
+		  rtlphy->default_initialgain[0],
+		  rtlphy->default_initialgain[1],
+		  rtlphy->default_initialgain[2],
+		  rtlphy->default_initialgain[3]);
+
+	rtlphy->framesync = (u8) rtl_get_bbreg(hw,
+					       ROFDM0_RXDETECTOR3, MASKBYTE0);
+	rtlphy->framesync_c34 = rtl_get_bbreg(hw,
+					      ROFDM0_RXDETECTOR2, MASKDWORD);
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+		 "Default framesync (0x%x) = 0x%x\n",
+		 ROFDM0_RXDETECTOR3, rtlphy->framesync);
+}
+
+static void _phy_init_bb_rf_reg_def(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+	rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+	rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW;
+	rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB;
+	rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB;
+	rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB;
+	rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset =
+			    RFPGA0_XA_LSSIPARAMETER;
+	rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset =
+			    RFPGA0_XB_LSSIPARAMETER;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = rFPGA0_XAB_RFPARAMETER;
+	rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = rFPGA0_XAB_RFPARAMETER;
+	rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = rFPGA0_XCD_RFPARAMETER;
+	rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = rFPGA0_XCD_RFPARAMETER;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+	rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+	rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+	rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1;
+	rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2;
+	rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1;
+	rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1;
+	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1;
+	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2;
+	rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2;
+	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2;
+	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBANLANCE;
+	rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE;
+	rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE;
+	rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE;
+	rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE;
+	rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE;
+	rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVEA_HSPI_READBACK;
+	rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVEB_HSPI_READBACK;
+}
+
+void rtl8723ae_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 txpwr_level;
+	long txpwr_dbm;
+
+	txpwr_level = rtlphy->cur_cck_txpwridx;
+	txpwr_dbm = _phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_B, txpwr_level);
+	txpwr_level = rtlphy->cur_ofdm24g_txpwridx +
+	    rtlefuse->legacy_ht_txpowerdiff;
+	if (_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, txpwr_level) > txpwr_dbm)
+		txpwr_dbm = _phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G,
+						  txpwr_level);
+	txpwr_level = rtlphy->cur_ofdm24g_txpwridx;
+	if (_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, txpwr_level) >
+	    txpwr_dbm)
+		txpwr_dbm = _phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G,
+						  txpwr_level);
+	*powerlevel = txpwr_dbm;
+}
+
+static void _rtl8723ae_get_txpower_index(struct ieee80211_hw *hw, u8 channel,
+					 u8 *cckpowerlevel, u8 *ofdmpowerlevel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 index = (channel - 1);
+
+	cckpowerlevel[RF90_PATH_A] =
+	    rtlefuse->txpwrlevel_cck[RF90_PATH_A][index];
+	cckpowerlevel[RF90_PATH_B] =
+	    rtlefuse->txpwrlevel_cck[RF90_PATH_B][index];
+	if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_1T1R) {
+		ofdmpowerlevel[RF90_PATH_A] =
+		    rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index];
+		ofdmpowerlevel[RF90_PATH_B] =
+		    rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index];
+	} else if (get_rf_type(rtlphy) == RF_2T2R) {
+		ofdmpowerlevel[RF90_PATH_A] =
+		    rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index];
+		ofdmpowerlevel[RF90_PATH_B] =
+		    rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index];
+	}
+}
+
+static void _rtl8723ae_ccxpower_index_check(struct ieee80211_hw *hw,
+					    u8 channel, u8 *cckpowerlevel,
+					    u8 *ofdmpowerlevel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	rtlphy->cur_cck_txpwridx = cckpowerlevel[0];
+	rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0];
+}
+
+void rtl8723ae_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel)
+{
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 cckpowerlevel[2], ofdmpowerlevel[2];
+
+	if (rtlefuse->txpwr_fromeprom == false)
+		return;
+	_rtl8723ae_get_txpower_index(hw, channel, &cckpowerlevel[0],
+				     &ofdmpowerlevel[0]);
+	_rtl8723ae_ccxpower_index_check(hw, channel, &cckpowerlevel[0],
+					&ofdmpowerlevel[0]);
+	rtl8723ae_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]);
+	rtl8723ae_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel);
+}
+
+bool rtl8723ae_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 idx;
+	u8 rf_path;
+	u8 ccktxpwridx = _phy_dbm_to_txpwr_Idx(hw, WIRELESS_MODE_B,
+					       power_indbm);
+	u8 ofdmtxpwridx = _phy_dbm_to_txpwr_Idx(hw, WIRELESS_MODE_N_24G,
+						power_indbm);
+	if (ofdmtxpwridx - rtlefuse->legacy_ht_txpowerdiff > 0)
+		ofdmtxpwridx -= rtlefuse->legacy_ht_txpowerdiff;
+	else
+		ofdmtxpwridx = 0;
+	RT_TRACE(rtlpriv, COMP_TXAGC, DBG_TRACE,
+		 "%lx dBm, ccktxpwridx = %d, ofdmtxpwridx = %d\n",
+		 power_indbm, ccktxpwridx, ofdmtxpwridx);
+	for (idx = 0; idx < 14; idx++) {
+		for (rf_path = 0; rf_path < 2; rf_path++) {
+			rtlefuse->txpwrlevel_cck[rf_path][idx] = ccktxpwridx;
+			rtlefuse->txpwrlevel_ht40_1s[rf_path][idx] =
+							    ofdmtxpwridx;
+			rtlefuse->txpwrlevel_ht40_2s[rf_path][idx] =
+							    ofdmtxpwridx;
+		}
+	}
+	rtl8723ae_phy_set_txpower_level(hw, rtlphy->current_channel);
+	return true;
+}
+
+static u8 _phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw,
+				enum wireless_mode wirelessmode,
+				long power_indbm)
+{
+	u8 txpwridx;
+	long offset;
+
+	switch (wirelessmode) {
+	case WIRELESS_MODE_B:
+		offset = -7;
+		break;
+	case WIRELESS_MODE_G:
+	case WIRELESS_MODE_N_24G:
+		offset = -8;
+		break;
+	default:
+		offset = -8;
+		break;
+	}
+
+	if ((power_indbm - offset) > 0)
+		txpwridx = (u8) ((power_indbm - offset) * 2);
+	else
+		txpwridx = 0;
+
+	if (txpwridx > MAX_TXPWR_IDX_NMODE_92S)
+		txpwridx = MAX_TXPWR_IDX_NMODE_92S;
+
+	return txpwridx;
+}
+
+static long _phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw,
+				  enum wireless_mode wirelessmode, u8 txpwridx)
+{
+	long offset;
+	long pwrout_dbm;
+
+	switch (wirelessmode) {
+	case WIRELESS_MODE_B:
+		offset = -7;
+		break;
+	case WIRELESS_MODE_G:
+	case WIRELESS_MODE_N_24G:
+		offset = -8;
+		break;
+	default:
+		offset = -8;
+		break;
+	}
+	pwrout_dbm = txpwridx / 2 + offset;
+	return pwrout_dbm;
+}
+
+void rtl8723ae_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	enum io_type iotype;
+
+	if (!is_hal_stop(rtlhal)) {
+		switch (operation) {
+		case SCAN_OPT_BACKUP:
+			iotype = IO_CMD_PAUSE_DM_BY_SCAN;
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+						      HW_VAR_IO_CMD,
+						      (u8 *)&iotype);
+
+			break;
+		case SCAN_OPT_RESTORE:
+			iotype = IO_CMD_RESUME_DM_BY_SCAN;
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+						      HW_VAR_IO_CMD,
+						      (u8 *)&iotype);
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 "Unknown Scan Backup operation.\n");
+			break;
+		}
+	}
+}
+
+void rtl8723ae_phy_set_bw_mode_callback(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u8 reg_bw_opmode;
+	u8 reg_prsr_rsc;
+
+	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
+		 "Switch to %s bandwidth\n",
+		 rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
+		 "20MHz" : "40MHz");
+
+	if (is_hal_stop(rtlhal)) {
+		rtlphy->set_bwmode_inprogress = false;
+		return;
+	}
+
+	reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE);
+	reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2);
+
+	switch (rtlphy->current_chan_bw) {
+	case HT_CHANNEL_WIDTH_20:
+		reg_bw_opmode |= BW_OPMODE_20MHZ;
+		rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+		break;
+	case HT_CHANNEL_WIDTH_20_40:
+		reg_bw_opmode &= ~BW_OPMODE_20MHZ;
+		rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+		reg_prsr_rsc =
+		    (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5);
+		rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "unknown bandwidth: %#X\n", rtlphy->current_chan_bw);
+		break;
+	}
+
+	switch (rtlphy->current_chan_bw) {
+	case HT_CHANNEL_WIDTH_20:
+		rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0);
+		rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0);
+		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);
+		break;
+	case HT_CHANNEL_WIDTH_20_40:
+		rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1);
+		rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1);
+
+		rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND,
+			      (mac->cur_40_prime_sc >> 1));
+		rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc);
+		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);
+
+		rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)),
+			      (mac->cur_40_prime_sc ==
+			       HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "unknown bandwidth: %#X\n", rtlphy->current_chan_bw);
+		break;
+	}
+	rtl8723ae_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
+	rtlphy->set_bwmode_inprogress = false;
+	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n");
+}
+
+void rtl8723ae_phy_set_bw_mode(struct ieee80211_hw *hw,
+			       enum nl80211_channel_type ch_type)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 tmp_bw = rtlphy->current_chan_bw;
+
+	if (rtlphy->set_bwmode_inprogress)
+		return;
+	rtlphy->set_bwmode_inprogress = true;
+	if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
+		rtl8723ae_phy_set_bw_mode_callback(hw);
+	} else {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			 "FALSE driver sleep or unload\n");
+		rtlphy->set_bwmode_inprogress = false;
+		rtlphy->current_chan_bw = tmp_bw;
+	}
+}
+
+void rtl8723ae_phy_sw_chnl_callback(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 delay;
+
+	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
+		 "switch to channel%d\n", rtlphy->current_channel);
+	if (is_hal_stop(rtlhal))
+		return;
+	do {
+		if (!rtlphy->sw_chnl_inprogress)
+			break;
+		if (!_phy_sw_chnl_step_by_step
+		    (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage,
+		     &rtlphy->sw_chnl_step, &delay)) {
+			if (delay > 0)
+				mdelay(delay);
+			else
+				continue;
+		} else {
+			rtlphy->sw_chnl_inprogress = false;
+		}
+		break;
+	} while (true);
+	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n");
+}
+
+u8 rtl8723ae_phy_sw_chnl(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (rtlphy->sw_chnl_inprogress)
+		return 0;
+	if (rtlphy->set_bwmode_inprogress)
+		return 0;
+	RT_ASSERT((rtlphy->current_channel <= 14),
+		  "WIRELESS_MODE_G but channel>14");
+	rtlphy->sw_chnl_inprogress = true;
+	rtlphy->sw_chnl_stage = 0;
+	rtlphy->sw_chnl_step = 0;
+	if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
+		rtl8723ae_phy_sw_chnl_callback(hw);
+		RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
+			 "sw_chnl_inprogress false schdule workitem\n");
+		rtlphy->sw_chnl_inprogress = false;
+	} else {
+		RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
+			 "sw_chnl_inprogress false driver sleep or unload\n");
+		rtlphy->sw_chnl_inprogress = false;
+	}
+	return 1;
+}
+
+static void _rtl8723ae_phy_sw_rf_seting(struct ieee80211_hw *hw, u8 channel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
+		if (channel == 6 && rtlphy->current_chan_bw ==
+		    HT_CHANNEL_WIDTH_20)
+			rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD,
+				      0x00255);
+		else{
+			u32 backupRF0x1A = (u32)rtl_get_rfreg(hw, RF90_PATH_A,
+					   RF_RX_G1, RFREG_OFFSET_MASK);
+			rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD,
+				      backupRF0x1A);
+		}
+	}
+}
+
+static bool _phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, u8 channel,
+				      u8 *stage, u8 *step, u32 *delay)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct swchnlcmd precommoncmd[MAX_PRECMD_CNT];
+	u32 precommoncmdcnt;
+	struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT];
+	u32 postcommoncmdcnt;
+	struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT];
+	u32 rfdependcmdcnt;
+	struct swchnlcmd *currentcmd = NULL;
+	u8 rfpath;
+	u8 num_total_rfpath = rtlphy->num_total_rfpath;
+
+	precommoncmdcnt = 0;
+	_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+				  MAX_PRECMD_CNT, CMDID_SET_TXPOWEROWER_LEVEL,
+				  0, 0, 0);
+	_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+				  MAX_PRECMD_CNT, CMDID_END, 0, 0, 0);
+	postcommoncmdcnt = 0;
+
+	_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++,
+				  MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0);
+	rfdependcmdcnt = 0;
+
+	RT_ASSERT((channel >= 1 && channel <= 14),
+		  "illegal channel for Zebra: %d\n", channel);
+
+	_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
+				  MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG,
+				  RF_CHNLBW, channel, 10);
+
+	_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
+				  MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, 0);
+
+	do {
+		switch (*stage) {
+		case 0:
+			currentcmd = &precommoncmd[*step];
+			break;
+		case 1:
+			currentcmd = &rfdependcmd[*step];
+			break;
+		case 2:
+			currentcmd = &postcommoncmd[*step];
+			break;
+		}
+
+		if (currentcmd->cmdid == CMDID_END) {
+			if ((*stage) == 2) {
+				return true;
+			} else {
+				(*stage)++;
+				(*step) = 0;
+				continue;
+			}
+		}
+
+		switch (currentcmd->cmdid) {
+		case CMDID_SET_TXPOWEROWER_LEVEL:
+			rtl8723ae_phy_set_txpower_level(hw, channel);
+			break;
+		case CMDID_WRITEPORT_ULONG:
+			rtl_write_dword(rtlpriv, currentcmd->para1,
+					currentcmd->para2);
+			break;
+		case CMDID_WRITEPORT_USHORT:
+			rtl_write_word(rtlpriv, currentcmd->para1,
+				       (u16) currentcmd->para2);
+			break;
+		case CMDID_WRITEPORT_UCHAR:
+			rtl_write_byte(rtlpriv, currentcmd->para1,
+				       (u8) currentcmd->para2);
+			break;
+		case CMDID_RF_WRITEREG:
+			for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) {
+				rtlphy->rfreg_chnlval[rfpath] =
+				    ((rtlphy->rfreg_chnlval[rfpath] &
+				      0xfffffc00) | currentcmd->para2);
+
+				rtl_set_rfreg(hw, (enum radio_path)rfpath,
+					      currentcmd->para1,
+					      RFREG_OFFSET_MASK,
+					      rtlphy->rfreg_chnlval[rfpath]);
+			}
+			_rtl8723ae_phy_sw_rf_seting(hw, channel);
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 "switch case not process\n");
+			break;
+		}
+
+		break;
+	} while (true);
+
+	(*delay) = currentcmd->msdelay;
+	(*step)++;
+	return false;
+}
+
+static bool _phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
+				      u32 cmdtableidx, u32 cmdtablesz,
+				      enum swchnlcmd_id cmdid, u32 para1,
+				      u32 para2, u32 msdelay)
+{
+	struct swchnlcmd *pcmd;
+
+	if (cmdtable == NULL) {
+		RT_ASSERT(false, "cmdtable cannot be NULL.\n");
+		return false;
+	}
+
+	if (cmdtableidx >= cmdtablesz)
+		return false;
+
+	pcmd = cmdtable + cmdtableidx;
+	pcmd->cmdid = cmdid;
+	pcmd->para1 = para1;
+	pcmd->para2 = para2;
+	pcmd->msdelay = msdelay;
+	return true;
+}
+
+static u8 _rtl8723ae_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb)
+{
+	u32 reg_eac, reg_e94, reg_e9c, reg_ea4;
+	u8 result = 0x00;
+
+	rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1f);
+	rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c1f);
+	rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140102);
+	rtl_set_bbreg(hw, 0xe3c, MASKDWORD,
+		      config_pathb ? 0x28160202 : 0x28160502);
+
+	if (config_pathb) {
+		rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x10008c22);
+		rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x10008c22);
+		rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140102);
+		rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x28160202);
+	}
+
+	rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x001028d1);
+	rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000);
+	rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000);
+
+	mdelay(IQK_DELAY_TIME);
+
+	reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD);
+	reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD);
+	reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD);
+	reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD);
+
+	if (!(reg_eac & BIT(28)) &&
+	    (((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
+	    (((reg_e9c & 0x03FF0000) >> 16) != 0x42))
+		result |= 0x01;
+	else
+		return result;
+
+	if (!(reg_eac & BIT(27)) &&
+	    (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) &&
+	    (((reg_eac & 0x03FF0000) >> 16) != 0x36))
+		result |= 0x02;
+	return result;
+}
+
+static u8 _rtl8723ae_phy_path_b_iqk(struct ieee80211_hw *hw)
+{
+	u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc;
+	u8 result = 0x00;
+
+	rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002);
+	rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000);
+	mdelay(IQK_DELAY_TIME);
+	reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD);
+	reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD);
+	reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD);
+	reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD);
+	reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD);
+
+	if (!(reg_eac & BIT(31)) &&
+	    (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) &&
+	    (((reg_ebc & 0x03FF0000) >> 16) != 0x42))
+		result |= 0x01;
+	else
+		return result;
+	if (!(reg_eac & BIT(30)) &&
+	    (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) &&
+	    (((reg_ecc & 0x03FF0000) >> 16) != 0x36))
+		result |= 0x02;
+	return result;
+}
+
+static void phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw, bool iqk_ok,
+				       long result[][8], u8 final_candidate,
+				       bool btxonly)
+{
+	u32 oldval_0, x, tx0_a, reg;
+	long y, tx0_c;
+
+	if (final_candidate == 0xFF) {
+		return;
+	} else if (iqk_ok) {
+		oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
+					  MASKDWORD) >> 22) & 0x3FF;
+		x = result[final_candidate][0];
+		if ((x & 0x00000200) != 0)
+			x = x | 0xFFFFFC00;
+		tx0_a = (x * oldval_0) >> 8;
+		rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a);
+		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(31),
+			      ((x * oldval_0 >> 7) & 0x1));
+		y = result[final_candidate][1];
+		if ((y & 0x00000200) != 0)
+			y = y | 0xFFFFFC00;
+		tx0_c = (y * oldval_0) >> 8;
+		rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000,
+			      ((tx0_c & 0x3C0) >> 6));
+		rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000,
+			      (tx0_c & 0x3F));
+		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(29),
+			      ((y * oldval_0 >> 7) & 0x1));
+		if (btxonly)
+			return;
+		reg = result[final_candidate][2];
+		rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg);
+		reg = result[final_candidate][3] & 0x3F;
+		rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg);
+		reg = (result[final_candidate][3] >> 6) & 0xF;
+		rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg);
+	}
+}
+
+static void phy_save_adda_regs(struct ieee80211_hw *hw,
+					       u32 *addareg, u32 *addabackup,
+					       u32 registernum)
+{
+	u32 i;
+
+	for (i = 0; i < registernum; i++)
+		addabackup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD);
+}
+
+static void phy_save_mac_regs(struct ieee80211_hw *hw, u32 *macreg,
+			      u32 *macbackup)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i;
+
+	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
+		macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]);
+	macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]);
+}
+
+static void phy_reload_adda_regs(struct ieee80211_hw *hw, u32 *addareg,
+				 u32 *addabackup, u32 regiesternum)
+{
+	u32 i;
+
+	for (i = 0; i < regiesternum; i++)
+		rtl_set_bbreg(hw, addareg[i], MASKDWORD, addabackup[i]);
+}
+
+static void phy_reload_mac_regs(struct ieee80211_hw *hw, u32 *macreg,
+				u32 *macbackup)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i;
+
+	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
+		rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]);
+	rtl_write_dword(rtlpriv, macreg[i], macbackup[i]);
+}
+
+static void _rtl8723ae_phy_path_adda_on(struct ieee80211_hw *hw,
+					u32 *addareg, bool is_patha_on,
+					bool is2t)
+{
+	u32 pathOn;
+	u32 i;
+
+	pathOn = is_patha_on ? 0x04db25a4 : 0x0b1b25a4;
+	if (false == is2t) {
+		pathOn = 0x0bdb25a0;
+		rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0);
+	} else {
+		rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathOn);
+	}
+
+	for (i = 1; i < IQK_ADDA_REG_NUM; i++)
+		rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathOn);
+}
+
+static void _rtl8723ae_phy_mac_setting_calibration(struct ieee80211_hw *hw,
+						   u32 *macreg, u32 *macbackup)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i = 0;
+
+	rtl_write_byte(rtlpriv, macreg[i], 0x3F);
+
+	for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++)
+		rtl_write_byte(rtlpriv, macreg[i],
+			       (u8) (macbackup[i] & (~BIT(3))));
+	rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5))));
+}
+
+static void _rtl8723ae_phy_path_a_standby(struct ieee80211_hw *hw)
+{
+	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0);
+	rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000);
+	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000);
+}
+
+static void _rtl8723ae_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode)
+{
+	u32 mode;
+
+	mode = pi_mode ? 0x01000100 : 0x01000000;
+	rtl_set_bbreg(hw, 0x820, MASKDWORD, mode);
+	rtl_set_bbreg(hw, 0x828, MASKDWORD, mode);
+}
+
+static bool phy_simularity_comp(struct ieee80211_hw *hw, long result[][8],
+				u8 c1, u8 c2)
+{
+	u32 i, j, diff, simularity_bitmap, bound;
+
+	u8 final_candidate[2] = { 0xFF, 0xFF };
+	bool bresult = true;
+
+	bound = 4;
+
+	simularity_bitmap = 0;
+
+	for (i = 0; i < bound; i++) {
+		diff = (result[c1][i] > result[c2][i]) ?
+		    (result[c1][i] - result[c2][i]) :
+		    (result[c2][i] - result[c1][i]);
+
+		if (diff > MAX_TOLERANCE) {
+			if ((i == 2 || i == 6) && !simularity_bitmap) {
+				if (result[c1][i] + result[c1][i + 1] == 0)
+					final_candidate[(i / 4)] = c2;
+				else if (result[c2][i] + result[c2][i + 1] == 0)
+					final_candidate[(i / 4)] = c1;
+				else
+					simularity_bitmap = simularity_bitmap |
+					    (1 << i);
+			} else
+				simularity_bitmap =
+				    simularity_bitmap | (1 << i);
+		}
+	}
+
+	if (simularity_bitmap == 0) {
+		for (i = 0; i < (bound / 4); i++) {
+			if (final_candidate[i] != 0xFF) {
+				for (j = i * 4; j < (i + 1) * 4 - 2; j++)
+					result[3][j] =
+					    result[final_candidate[i]][j];
+				bresult = false;
+			}
+		}
+		return bresult;
+	} else if (!(simularity_bitmap & 0x0F)) {
+		for (i = 0; i < 4; i++)
+			result[3][i] = result[c1][i];
+		return false;
+	} else {
+		return false;
+	}
+
+}
+
+static void _rtl8723ae_phy_iq_calibrate(struct ieee80211_hw *hw,
+					long result[][8], u8 t, bool is2t)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 i;
+	u8 patha_ok, pathb_ok;
+	u32 adda_reg[IQK_ADDA_REG_NUM] = {
+		0x85c, 0xe6c, 0xe70, 0xe74,
+		0xe78, 0xe7c, 0xe80, 0xe84,
+		0xe88, 0xe8c, 0xed0, 0xed4,
+		0xed8, 0xedc, 0xee0, 0xeec
+	};
+	u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
+		0x522, 0x550, 0x551, 0x040
+	};
+	const u32 retrycount = 2;
+	u32 bbvalue;
+
+	if (t == 0) {
+		bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD);
+
+		phy_save_adda_regs(hw, adda_reg, rtlphy->adda_backup, 16);
+		phy_save_mac_regs(hw, iqk_mac_reg, rtlphy->iqk_mac_backup);
+	}
+	_rtl8723ae_phy_path_adda_on(hw, adda_reg, true, is2t);
+	if (t == 0) {
+		rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw,
+						 RFPGA0_XA_HSSIPARAMETER1,
+						 BIT(8));
+	}
+
+	if (!rtlphy->rfpi_enable)
+		_rtl8723ae_phy_pi_mode_switch(hw, true);
+	if (t == 0) {
+		rtlphy->reg_c04 = rtl_get_bbreg(hw, 0xc04, MASKDWORD);
+		rtlphy->reg_c08 = rtl_get_bbreg(hw, 0xc08, MASKDWORD);
+		rtlphy->reg_874 = rtl_get_bbreg(hw, 0x874, MASKDWORD);
+	}
+	rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600);
+	rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4);
+	rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000);
+	if (is2t) {
+		rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000);
+		rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000);
+	}
+	_rtl8723ae_phy_mac_setting_calibration(hw, iqk_mac_reg,
+					    rtlphy->iqk_mac_backup);
+	rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x00080000);
+	if (is2t)
+		rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x00080000);
+	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000);
+	rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00);
+	rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800);
+	for (i = 0; i < retrycount; i++) {
+		patha_ok = _rtl8723ae_phy_path_a_iqk(hw, is2t);
+		if (patha_ok == 0x03) {
+			result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) &
+					0x3FF0000) >> 16;
+			result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) &
+					0x3FF0000) >> 16;
+			result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) &
+					0x3FF0000) >> 16;
+			result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) &
+					0x3FF0000) >> 16;
+			break;
+		} else if (i == (retrycount - 1) && patha_ok == 0x01)
+
+			result[t][0] = (rtl_get_bbreg(hw, 0xe94,
+					MASKDWORD) & 0x3FF0000) >> 16;
+		result[t][1] =
+		    (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16;
+
+	}
+
+	if (is2t) {
+		_rtl8723ae_phy_path_a_standby(hw);
+		_rtl8723ae_phy_path_adda_on(hw, adda_reg, false, is2t);
+		for (i = 0; i < retrycount; i++) {
+			pathb_ok = _rtl8723ae_phy_path_b_iqk(hw);
+			if (pathb_ok == 0x03) {
+				result[t][4] =
+				    (rtl_get_bbreg(hw, 0xeb4, MASKDWORD) &
+				     0x3FF0000) >> 16;
+				result[t][5] =
+				    (rtl_get_bbreg(hw, 0xebc, MASKDWORD) &
+				     0x3FF0000) >> 16;
+				result[t][6] =
+				    (rtl_get_bbreg(hw, 0xec4, MASKDWORD) &
+				     0x3FF0000) >> 16;
+				result[t][7] =
+				    (rtl_get_bbreg(hw, 0xecc, MASKDWORD) &
+				     0x3FF0000) >> 16;
+				break;
+			} else if (i == (retrycount - 1) && pathb_ok == 0x01) {
+				result[t][4] =
+				    (rtl_get_bbreg(hw, 0xeb4, MASKDWORD) &
+				     0x3FF0000) >> 16;
+			}
+			result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) &
+					0x3FF0000) >> 16;
+		}
+	}
+	rtl_set_bbreg(hw, 0xc04, MASKDWORD, rtlphy->reg_c04);
+	rtl_set_bbreg(hw, 0x874, MASKDWORD, rtlphy->reg_874);
+	rtl_set_bbreg(hw, 0xc08, MASKDWORD, rtlphy->reg_c08);
+	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0);
+	rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3);
+	if (is2t)
+		rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3);
+	if (t != 0) {
+		if (!rtlphy->rfpi_enable)
+			_rtl8723ae_phy_pi_mode_switch(hw, false);
+		phy_reload_adda_regs(hw, adda_reg, rtlphy->adda_backup, 16);
+		phy_reload_mac_regs(hw, iqk_mac_reg, rtlphy->iqk_mac_backup);
+	}
+}
+
+static void _rtl8723ae_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 tmpreg;
+	u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
+
+	tmpreg = rtl_read_byte(rtlpriv, 0xd03);
+
+	if ((tmpreg & 0x70) != 0)
+		rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F);
+	else
+		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+
+	if ((tmpreg & 0x70) != 0) {
+		rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS);
+
+		if (is2t)
+			rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00,
+						  MASK12BITS);
+
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS,
+			      (rf_a_mode & 0x8FFFF) | 0x10000);
+
+		if (is2t)
+			rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
+				      (rf_b_mode & 0x8FFFF) | 0x10000);
+	}
+	lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS);
+
+	rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000);
+
+	mdelay(100);
+
+	if ((tmpreg & 0x70) != 0) {
+		rtl_write_byte(rtlpriv, 0xd03, tmpreg);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode);
+
+		if (is2t)
+			rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
+				      rf_b_mode);
+	} else {
+		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+	}
+}
+
+static void _rtl8723ae_phy_set_rfpath_switch(struct ieee80211_hw *hw,
+					     bool bmain, bool is2t)
+{
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (is_hal_stop(rtlhal)) {
+		rtl_set_bbreg(hw, REG_LEDCFG0, BIT(23), 0x01);
+		rtl_set_bbreg(hw, rFPGA0_XAB_RFPARAMETER, BIT(13), 0x01);
+	}
+	if (is2t) {
+		if (bmain)
+			rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
+				      BIT(5) | BIT(6), 0x1);
+		else
+			rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
+				      BIT(5) | BIT(6), 0x2);
+	} else {
+		if (bmain)
+			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x2);
+		else
+			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1);
+
+	}
+}
+
+#undef IQK_ADDA_REG_NUM
+#undef IQK_DELAY_TIME
+
+void rtl8723ae_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	long result[4][8];
+	u8 i, final_candidate;
+	bool patha_ok, pathb_ok;
+	long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4,
+	    reg_ecc, reg_tmp = 0;
+	bool is12simular, is13simular, is23simular;
+	bool start_conttx = false, singletone = false;
+	u32 iqk_bb_reg[10] = {
+		ROFDM0_XARXIQIMBALANCE,
+		ROFDM0_XBRXIQIMBALANCE,
+		ROFDM0_ECCATHRESHOLD,
+		ROFDM0_AGCRSSITABLE,
+		ROFDM0_XATXIQIMBALANCE,
+		ROFDM0_XBTXIQIMBALANCE,
+		ROFDM0_XCTXIQIMBALANCE,
+		ROFDM0_XCTXAFE,
+		ROFDM0_XDTXAFE,
+		ROFDM0_RXIQEXTANTA
+	};
+
+	if (recovery) {
+		phy_reload_adda_regs(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, 10);
+		return;
+	}
+	if (start_conttx || singletone)
+		return;
+	for (i = 0; i < 8; i++) {
+		result[0][i] = 0;
+		result[1][i] = 0;
+		result[2][i] = 0;
+		result[3][i] = 0;
+	}
+	final_candidate = 0xff;
+	patha_ok = false;
+	pathb_ok = false;
+	is12simular = false;
+	is23simular = false;
+	is13simular = false;
+	for (i = 0; i < 3; i++) {
+		_rtl8723ae_phy_iq_calibrate(hw, result, i, false);
+		if (i == 1) {
+			is12simular = phy_simularity_comp(hw, result, 0, 1);
+			if (is12simular) {
+				final_candidate = 0;
+				break;
+			}
+		}
+		if (i == 2) {
+			is13simular = phy_simularity_comp(hw, result, 0, 2);
+			if (is13simular) {
+				final_candidate = 0;
+				break;
+			}
+			is23simular = phy_simularity_comp(hw, result, 1, 2);
+			if (is23simular) {
+				final_candidate = 1;
+			} else {
+				for (i = 0; i < 8; i++)
+					reg_tmp += result[3][i];
+
+				if (reg_tmp != 0)
+					final_candidate = 3;
+				else
+					final_candidate = 0xFF;
+			}
+		}
+	}
+	for (i = 0; i < 4; i++) {
+		reg_e94 = result[i][0];
+		reg_e9c = result[i][1];
+		reg_ea4 = result[i][2];
+		reg_eac = result[i][3];
+		reg_eb4 = result[i][4];
+		reg_ebc = result[i][5];
+		reg_ec4 = result[i][6];
+		reg_ecc = result[i][7];
+	}
+	if (final_candidate != 0xff) {
+		rtlphy->reg_e94 = reg_e94 = result[final_candidate][0];
+		rtlphy->reg_e9c = reg_e9c = result[final_candidate][1];
+		reg_ea4 = result[final_candidate][2];
+		reg_eac = result[final_candidate][3];
+		rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4];
+		rtlphy->reg_ebc = reg_ebc = result[final_candidate][5];
+		reg_ec4 = result[final_candidate][6];
+		reg_ecc = result[final_candidate][7];
+		patha_ok = pathb_ok = true;
+	} else {
+		rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100;
+		rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0;
+	}
+	if (reg_e94 != 0) /*&&(reg_ea4 != 0) */
+		phy_path_a_fill_iqk_matrix(hw, patha_ok, result,
+					   final_candidate, (reg_ea4 == 0));
+	phy_save_adda_regs(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, 10);
+}
+
+void rtl8723ae_phy_lc_calibrate(struct ieee80211_hw *hw)
+{
+	bool start_conttx = false, singletone = false;
+
+	if (start_conttx || singletone)
+		return;
+	_rtl8723ae_phy_lc_calibrate(hw, false);
+}
+
+void rtl8723ae_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain)
+{
+	_rtl8723ae_phy_set_rfpath_switch(hw, bmain, false);
+}
+
+bool rtl8723ae_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	bool postprocessing = false;
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+		 "-->IO Cmd(%#x), set_io_inprogress(%d)\n",
+		 iotype, rtlphy->set_io_inprogress);
+	do {
+		switch (iotype) {
+		case IO_CMD_RESUME_DM_BY_SCAN:
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+				 "[IO CMD] Resume DM after scan.\n");
+			postprocessing = true;
+			break;
+		case IO_CMD_PAUSE_DM_BY_SCAN:
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+				 "[IO CMD] Pause DM before scan.\n");
+			postprocessing = true;
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 "switch case not process\n");
+			break;
+		}
+	} while (false);
+	if (postprocessing && !rtlphy->set_io_inprogress) {
+		rtlphy->set_io_inprogress = true;
+		rtlphy->current_io_type = iotype;
+	} else {
+		return false;
+	}
+	rtl8723ae_phy_set_io(hw);
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "<--IO Type(%#x)\n", iotype);
+	return true;
+}
+
+static void rtl8723ae_phy_set_io(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+		 "--->Cmd(%#x), set_io_inprogress(%d)\n",
+		 rtlphy->current_io_type, rtlphy->set_io_inprogress);
+	switch (rtlphy->current_io_type) {
+	case IO_CMD_RESUME_DM_BY_SCAN:
+		dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1;
+		rtl8723ae_dm_write_dig(hw);
+		rtl8723ae_phy_set_txpower_level(hw, rtlphy->current_channel);
+		break;
+	case IO_CMD_PAUSE_DM_BY_SCAN:
+		rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue;
+		dm_digtable->cur_igvalue = 0x17;
+		rtl8723ae_dm_write_dig(hw);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "switch case not process\n");
+		break;
+	}
+	rtlphy->set_io_inprogress = false;
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+		 "<---(%#x)\n", rtlphy->current_io_type);
+}
+
+static void rtl8723ae_phy_set_rf_on(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+	rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+}
+
+static void _rtl8723ae_phy_set_rf_sleep(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 u4b_tmp;
+	u8 delay = 5;
+
+	rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+	rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
+	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+	u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK);
+	while (u4b_tmp != 0 && delay > 0) {
+		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
+		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+		u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK);
+		delay--;
+	}
+	if (delay == 0) {
+		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
+			 "Switch RF timeout !!!.\n");
+		return;
+	}
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22);
+}
+
+static bool _rtl8723ae_phy_set_rf_power_state(struct ieee80211_hw *hw,
+					      enum rf_pwrstate rfpwr_state)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl8192_tx_ring *ring = NULL;
+	bool bresult = true;
+	u8 i, queue_id;
+
+	switch (rfpwr_state) {
+	case ERFON:
+		if ((ppsc->rfpwr_state == ERFOFF) &&
+		    RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
+			bool rtstatus;
+			u32 InitializeCount = 0;
+			do {
+				InitializeCount++;
+				RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+					 "IPS Set eRf nic enable\n");
+				rtstatus = rtl_ps_enable_nic(hw);
+			} while ((rtstatus != true) && (InitializeCount < 10));
+			RT_CLEAR_PS_LEVEL(ppsc,
+					  RT_RF_OFF_LEVL_HALT_NIC);
+		} else {
+			RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+				 "Set ERFON sleeped:%d ms\n",
+				 jiffies_to_msecs(jiffies -
+				 ppsc->last_sleep_jiffies));
+			ppsc->last_awake_jiffies = jiffies;
+			rtl8723ae_phy_set_rf_on(hw);
+		}
+		if (mac->link_state == MAC80211_LINKED) {
+			rtlpriv->cfg->ops->led_control(hw,
+					LED_CTL_LINK);
+		} else {
+			rtlpriv->cfg->ops->led_control(hw,
+					LED_CTL_NO_LINK);
+		}
+		break;
+	case ERFOFF:
+		if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) {
+			RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+				 "IPS Set eRf nic disable\n");
+			rtl_ps_disable_nic(hw);
+			RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+		} else {
+			if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) {
+				rtlpriv->cfg->ops->led_control(hw,
+					LED_CTL_NO_LINK);
+			} else {
+				rtlpriv->cfg->ops->led_control(hw,
+					LED_CTL_POWER_OFF);
+			}
+		}
+		break;
+	case ERFSLEEP:
+		if (ppsc->rfpwr_state == ERFOFF)
+			break;
+		for (queue_id = 0, i = 0;
+		     queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
+			ring = &pcipriv->dev.tx_ring[queue_id];
+			if (skb_queue_len(&ring->queue) == 0) {
+				queue_id++;
+				continue;
+			} else {
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+					 "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n",
+					 (i + 1), queue_id,
+					 skb_queue_len(&ring->queue));
+
+				udelay(10);
+				i++;
+			}
+			if (i >= MAX_DOZE_WAITING_TIMES_9x) {
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+					 "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n",
+					 MAX_DOZE_WAITING_TIMES_9x,
+					 queue_id,
+					 skb_queue_len(&ring->queue));
+				break;
+			}
+		}
+		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+			 "Set ERFSLEEP awaked:%d ms\n",
+			 jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies));
+		ppsc->last_sleep_jiffies = jiffies;
+		_rtl8723ae_phy_set_rf_sleep(hw);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "switch case not processed\n");
+		bresult = false;
+		break;
+	}
+	if (bresult)
+		ppsc->rfpwr_state = rfpwr_state;
+	return bresult;
+}
+
+bool rtl8723ae_phy_set_rf_power_state(struct ieee80211_hw *hw,
+				      enum rf_pwrstate rfpwr_state)
+{
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	bool bresult = false;
+
+	if (rfpwr_state == ppsc->rfpwr_state)
+		return bresult;
+	bresult = _rtl8723ae_phy_set_rf_power_state(hw, rfpwr_state);
+	return bresult;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h
new file mode 100644
index 0000000..e7a59eb
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h
@@ -0,0 +1,224 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92C_PHY_H__
+#define __RTL92C_PHY_H__
+
+#define MAX_PRECMD_CNT				16
+#define MAX_RFDEPENDCMD_CNT			16
+#define MAX_POSTCMD_CNT				16
+
+#define MAX_DOZE_WAITING_TIMES_9x		64
+
+#define RT_CANNOT_IO(hw)			false
+#define HIGHPOWER_RADIOA_ARRAYLEN		22
+
+#define MAX_TOLERANCE				5
+#define	IQK_DELAY_TIME				1
+
+#define	APK_BB_REG_NUM				5
+#define	APK_AFE_REG_NUM				16
+#define	APK_CURVE_REG_NUM			4
+#define	PATH_NUM				2
+
+#define LOOP_LIMIT				5
+#define MAX_STALL_TIME				50
+#define AntennaDiversityValue			0x80
+#define MAX_TXPWR_IDX_NMODE_92S			63
+#define Reset_Cnt_Limit				3
+
+#define IQK_MAC_REG_NUM				4
+
+#define RF6052_MAX_PATH				2
+
+#define CT_OFFSET_MAC_ADDR			0X16
+
+#define CT_OFFSET_CCK_TX_PWR_IDX		0x5A
+#define CT_OFFSET_HT401S_TX_PWR_IDX		0x60
+#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF	0x66
+#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF		0x69
+#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF		0x6C
+
+#define CT_OFFSET_HT40_MAX_PWR_OFFSET		0x6F
+#define CT_OFFSET_HT20_MAX_PWR_OFFSET		0x72
+
+#define CT_OFFSET_CHANNEL_PLAH			0x75
+#define CT_OFFSET_THERMAL_METER			0x78
+#define CT_OFFSET_RF_OPTION			0x79
+#define CT_OFFSET_VERSION			0x7E
+#define CT_OFFSET_CUSTOMER_ID			0x7F
+
+#define RTL92C_MAX_PATH_NUM			2
+
+enum swchnlcmd_id {
+	CMDID_END,
+	CMDID_SET_TXPOWEROWER_LEVEL,
+	CMDID_BBREGWRITE10,
+	CMDID_WRITEPORT_ULONG,
+	CMDID_WRITEPORT_USHORT,
+	CMDID_WRITEPORT_UCHAR,
+	CMDID_RF_WRITEREG,
+};
+
+struct swchnlcmd {
+	enum swchnlcmd_id cmdid;
+	u32 para1;
+	u32 para2;
+	u32 msdelay;
+};
+
+enum hw90_block_e {
+	HW90_BLOCK_MAC = 0,
+	HW90_BLOCK_PHY0 = 1,
+	HW90_BLOCK_PHY1 = 2,
+	HW90_BLOCK_RF = 3,
+	HW90_BLOCK_MAXIMUM = 4,
+};
+
+enum baseband_config_type {
+	BASEBAND_CONFIG_PHY_REG = 0,
+	BASEBAND_CONFIG_AGC_TAB = 1,
+};
+
+enum ra_offset_area {
+	RA_OFFSET_LEGACY_OFDM1,
+	RA_OFFSET_LEGACY_OFDM2,
+	RA_OFFSET_HT_OFDM1,
+	RA_OFFSET_HT_OFDM2,
+	RA_OFFSET_HT_OFDM3,
+	RA_OFFSET_HT_OFDM4,
+	RA_OFFSET_HT_CCK,
+};
+
+enum antenna_path {
+	ANTENNA_NONE,
+	ANTENNA_D,
+	ANTENNA_C,
+	ANTENNA_CD,
+	ANTENNA_B,
+	ANTENNA_BD,
+	ANTENNA_BC,
+	ANTENNA_BCD,
+	ANTENNA_A,
+	ANTENNA_AD,
+	ANTENNA_AC,
+	ANTENNA_ACD,
+	ANTENNA_AB,
+	ANTENNA_ABD,
+	ANTENNA_ABC,
+	ANTENNA_ABCD
+};
+
+struct r_antenna_select_ofdm {
+	u32 r_tx_antenna:4;
+	u32 r_ant_l:4;
+	u32 r_ant_non_ht:4;
+	u32 r_ant_ht1:4;
+	u32 r_ant_ht2:4;
+	u32 r_ant_ht_s1:4;
+	u32 r_ant_non_ht_s1:4;
+	u32 ofdm_txsc:2;
+	u32 reserved:2;
+};
+
+struct r_antenna_select_cck {
+	u8 r_cckrx_enable_2:2;
+	u8 r_cckrx_enable:2;
+	u8 r_ccktx_enable:4;
+};
+
+struct efuse_contents {
+	u8 mac_addr[ETH_ALEN];
+	u8 cck_tx_power_idx[6];
+	u8 ht40_1s_tx_power_idx[6];
+	u8 ht40_2s_tx_power_idx_diff[3];
+	u8 ht20_tx_power_idx_diff[3];
+	u8 ofdm_tx_power_idx_diff[3];
+	u8 ht40_max_power_offset[3];
+	u8 ht20_max_power_offset[3];
+	u8 channel_plan;
+	u8 thermal_meter;
+	u8 rf_option[5];
+	u8 version;
+	u8 oem_id;
+	u8 regulatory;
+};
+
+struct tx_power_struct {
+	u8 cck[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 ht40_1s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 ht40_2s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 ht20_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 legacy_ht_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 legacy_ht_txpowerdiff;
+	u8 groupht20[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 groupht40[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 pwrgroup_cnt;
+	u32 mcs_original_offset[4][16];
+};
+
+extern u32 rtl8723ae_phy_query_bb_reg(struct ieee80211_hw *hw,
+				      u32 regaddr, u32 bitmask);
+extern void rtl8723ae_phy_set_bb_reg(struct ieee80211_hw *hw,
+				     u32 regaddr, u32 bitmask, u32 data);
+extern u32 rtl8723ae_phy_query_rf_reg(struct ieee80211_hw *hw,
+				      enum radio_path rfpath, u32 regaddr,
+				      u32 bitmask);
+extern void rtl8723ae_phy_set_rf_reg(struct ieee80211_hw *hw,
+				     enum radio_path rfpath, u32 regaddr,
+				     u32 bitmask, u32 data);
+extern bool rtl8723ae_phy_mac_config(struct ieee80211_hw *hw);
+extern bool rtl8723ae_phy_bb_config(struct ieee80211_hw *hw);
+extern bool rtl8723ae_phy_rf_config(struct ieee80211_hw *hw);
+extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw,
+						 enum radio_path rfpath);
+extern void rtl8723ae_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
+extern void rtl8723ae_phy_get_txpower_level(struct ieee80211_hw *hw,
+					    long *powerlevel);
+extern void rtl8723ae_phy_set_txpower_level(struct ieee80211_hw *hw,
+					    u8 channel);
+extern bool rtl8723ae_phy_update_txpower_dbm(struct ieee80211_hw *hw,
+					     long power_indbm);
+extern void rtl8723ae_phy_scan_operation_backup(struct ieee80211_hw *hw,
+						u8 operation);
+extern void rtl8723ae_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
+extern void rtl8723ae_phy_set_bw_mode(struct ieee80211_hw *hw,
+				      enum nl80211_channel_type ch_type);
+extern void rtl8723ae_phy_sw_chnl_callback(struct ieee80211_hw *hw);
+extern u8 rtl8723ae_phy_sw_chnl(struct ieee80211_hw *hw);
+extern void rtl8723ae_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery);
+void rtl8723ae_phy_lc_calibrate(struct ieee80211_hw *hw);
+void rtl8723ae_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain);
+bool rtl8723ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+					     enum radio_path rfpath);
+bool rtl8723ae_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
+extern bool rtl8723ae_phy_set_rf_power_state(struct ieee80211_hw *hw,
+					     enum rf_pwrstate rfpwr_state);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c
new file mode 100644
index 0000000..df6ca9a
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c
@@ -0,0 +1,109 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "pwrseqcmd.h"
+#include "pwrseq.h"
+
+/* drivers should parse arrays below and do the corresponding actions */
+
+/*3 Power on  Array*/
+struct wlan_pwr_cfg rtl8723A_power_on_flow[RTL8723A_TRANS_CARDEMU_TO_ACT_STPS
+					+ RTL8723A_TRANS_END_STPS] = {
+	RTL8723A_TRANS_CARDEMU_TO_ACT,
+	RTL8723A_TRANS_END
+};
+
+/*3Radio off GPIO Array */
+struct wlan_pwr_cfg rtl8723A_radio_off_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+					+ RTL8723A_TRANS_END_STPS] = {
+	RTL8723A_TRANS_ACT_TO_CARDEMU,
+	RTL8723A_TRANS_END
+};
+
+/*3Card Disable Array*/
+struct wlan_pwr_cfg
+rtl8723A_card_disable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+			  + RTL8723A_TRANS_CARDEMU_TO_PDN_STPS
+			  + RTL8723A_TRANS_END_STPS] = {
+	RTL8723A_TRANS_ACT_TO_CARDEMU,
+	RTL8723A_TRANS_CARDEMU_TO_CARDDIS,
+	RTL8723A_TRANS_END
+};
+
+/*3 Card Enable Array*/
+struct wlan_pwr_cfg rtl8723A_card_enable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+					+ RTL8723A_TRANS_CARDEMU_TO_PDN_STPS
+					+ RTL8723A_TRANS_END_STPS] = {
+	RTL8723A_TRANS_CARDDIS_TO_CARDEMU,
+	RTL8723A_TRANS_CARDEMU_TO_ACT,
+	RTL8723A_TRANS_END
+};
+
+/*3Suspend Array*/
+struct wlan_pwr_cfg rtl8723A_suspend_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+					+ RTL8723A_TRANS_CARDEMU_TO_SUS_STPS
+					+ RTL8723A_TRANS_END_STPS] = {
+	RTL8723A_TRANS_ACT_TO_CARDEMU,
+	RTL8723A_TRANS_CARDEMU_TO_SUS,
+	RTL8723A_TRANS_END
+};
+
+/*3 Resume Array*/
+struct wlan_pwr_cfg rtl8723A_resume_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+					+ RTL8723A_TRANS_CARDEMU_TO_SUS_STPS
+					+ RTL8723A_TRANS_END_STPS] = {
+	RTL8723A_TRANS_SUS_TO_CARDEMU,
+	RTL8723A_TRANS_CARDEMU_TO_ACT,
+	RTL8723A_TRANS_END
+};
+
+/*3HWPDN Array*/
+struct wlan_pwr_cfg rtl8723A_hwpdn_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+				+ RTL8723A_TRANS_CARDEMU_TO_PDN_STPS
+				+ RTL8723A_TRANS_END_STPS] = {
+	RTL8723A_TRANS_ACT_TO_CARDEMU,
+	RTL8723A_TRANS_CARDEMU_TO_PDN,
+	RTL8723A_TRANS_END
+};
+
+/*3 Enter LPS */
+struct wlan_pwr_cfg rtl8723A_enter_lps_flow[RTL8723A_TRANS_ACT_TO_LPS_STPS
+					+ RTL8723A_TRANS_END_STPS] = {
+	/*FW behavior*/
+	RTL8723A_TRANS_ACT_TO_LPS,
+	RTL8723A_TRANS_END
+};
+
+/*3 Leave LPS */
+struct wlan_pwr_cfg rtl8723A_leave_lps_flow[RTL8723A_TRANS_LPS_TO_ACT_STPS
+					+ RTL8723A_TRANS_END_STPS] = {
+	/*FW behavior*/
+	RTL8723A_TRANS_LPS_TO_ACT,
+	RTL8723A_TRANS_END
+};
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h
new file mode 100644
index 0000000..7a46f9f
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h
@@ -0,0 +1,322 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_PWRSEQ_H__
+#define __RTL8723E_PWRSEQ_H__
+
+#include "pwrseqcmd.h"
+/*
+	Check document WM-20110607-Paul-RTL8723A_Power_Architecture-R02.vsd
+	There are 6 HW Power States:
+	0: POFF--Power Off
+	1: PDN--Power Down
+	2: CARDEMU--Card Emulation
+	3: ACT--Active Mode
+	4: LPS--Low Power State
+	5: SUS--Suspend
+
+	The transision from different states are defined below
+	TRANS_CARDEMU_TO_ACT
+	TRANS_ACT_TO_CARDEMU
+	TRANS_CARDEMU_TO_SUS
+	TRANS_SUS_TO_CARDEMU
+	TRANS_CARDEMU_TO_PDN
+	TRANS_ACT_TO_LPS
+	TRANS_LPS_TO_ACT
+
+	TRANS_END
+*/
+
+#define	RTL8723A_TRANS_CARDEMU_TO_ACT_STPS	10
+#define	RTL8723A_TRANS_ACT_TO_CARDEMU_STPS	10
+#define	RTL8723A_TRANS_CARDEMU_TO_SUS_STPS	10
+#define	RTL8723A_TRANS_SUS_TO_CARDEMU_STPS	10
+#define	RTL8723A_TRANS_CARDEMU_TO_PDN_STPS	10
+#define	RTL8723A_TRANS_PDN_TO_CARDEMU_STPS	10
+#define	RTL8723A_TRANS_ACT_TO_LPS_STPS		15
+#define	RTL8723A_TRANS_LPS_TO_ACT_STPS		15
+#define	RTL8723A_TRANS_END_STPS			1
+
+
+#define RTL8723A_TRANS_CARDEMU_TO_ACT					\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, \
+	 *  comments here*/						\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(2), 0},		\
+		/* disable SW LPS 0x04[10]=0*/				\
+	{0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)},	\
+		/* wait till 0x04[17] = 1    power ready*/		\
+	{0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)},	\
+		/* release WLON reset  0x04[16]=1*/			\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},		\
+		/* disable HWPDN 0x04[15]=0*/				\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT(4)|BIT(3)), 0},	\
+	/* disable WL suspend*/						\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)},	\
+		/* polling until return 0*/				\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0}
+
+#define RTL8723A_TRANS_ACT_TO_CARDEMU					\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, \
+	 *  comments here*/						\
+	{0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0},		\
+		/*0x1F[7:0] = 0 turn off RF*/				\
+	{0x004E, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},		\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)},	\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0}
+
+#define RTL8723A_TRANS_CARDEMU_TO_SUS					\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, \
+	 *  comments here*/						\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4)|BIT(3),		\
+		(BIT(4)|BIT(3))},					\
+		/*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/	\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK |	\
+		PWR_INTF_SDIO_MSK,					\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)},\
+		 /*0x04[12:11] = 2b'01 enable WL suspend*/		\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,	\
+		PWR_BASEADDR_MAC,					\
+		PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)|BIT(4)},		\
+		 /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/	\
+	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+		PWR_BASEADDR_SDIO,					\
+		PWR_CMD_WRITE, BIT(0), BIT(0)},				\
+		/*Set SDIO suspend local register*/			\
+	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+		PWR_BASEADDR_SDIO,					\
+		PWR_CMD_POLLING, BIT(1), 0}				\
+		/*wait power state to suspend*/
+
+#define RTL8723A_TRANS_SUS_TO_CARDEMU					\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+		PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0},		\
+		/*Set SDIO suspend local register*/			\
+	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+		PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)},	\
+		/*wait power state to suspend*/				\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}	\
+		/*0x04[12:11] = 2b'01enable WL suspend*/
+
+#define RTL8723A_TRANS_CARDEMU_TO_CARDDIS				\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,			\
+	PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,				\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)},\
+		/*0x04[12:11] = 2b'01 enable WL suspend*/		\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(2), BIT(2)},	\
+		/*0x04[10] = 1, enable SW LPS*/				\
+	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+		PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)},	\
+		/*Set SDIO suspend local register*/			\
+	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+		PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0}		\
+		/*wait power state to suspend*/
+
+#define RTL8723A_TRANS_CARDDIS_TO_CARDEMU				\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+		PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0},		\
+		/*Set SDIO suspend local register*/			\
+	{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+		PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)},	\
+		/*wait power state to suspend*/				\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0},	\
+		/*0x04[12:11] = 2b'00enable WL suspend*/		\
+	{0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}		\
+		/*PCIe DMA start*/
+
+#define RTL8723A_TRANS_CARDEMU_TO_PDN					\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+	{0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},		\
+		/* 0x04[16] = 0*/\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)}	\
+		/* 0x04[15] = 1*/
+
+#define RTL8723A_TRANS_PDN_TO_CARDEMU					\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+	{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0}		\
+		/* 0x04[15] = 0*/
+
+#define RTL8723A_TRANS_ACT_TO_LPS					\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+	{0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF},		\
+		/*PCIe DMA stop*/					\
+	{0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x7F},		\
+		/*Tx Pause*/						\
+	{0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},		\
+		/*Should be zero if no packet is transmitting*/		\
+	{0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},		\
+		/*Should be zero if no packet is transmitting*/		\
+	{0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},		\
+		/*Should be zero if no packet is transmitting*/		\
+	{0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},		\
+		/*Should be zero if no packet is transmitting*/		\
+	{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},		\
+		/*CCK and OFDM are disabled,and clock are gated*/	\
+	{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US},	\
+		/*Delay 1us*/						\
+	{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0},		\
+		/*Whole BB is reset*/					\
+	{0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x3F},		\
+		/*Reset MAC TRX*/					\
+	{0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0},		\
+		/*check if removed later*/				\
+	{0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)}	\
+		/*Respond TxOK to scheduler*/
+
+#define RTL8723A_TRANS_LPS_TO_ACT					\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+	{0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,	\
+		 PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84},		\
+		 /*SDIO RPWM*/						\
+	{0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84},		\
+		/*USB RPWM*/						\
+	{0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84},		\
+		/*PCIe RPWM*/						\
+	{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		 PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS},	\
+		/*Delay*/						\
+	{0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0},		\
+		/* 0x08[4] = 0 switch TSF to 40M*/			\
+	{0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0},		\
+		/*Polling 0x109[7]=0  TSF in 40M*/			\
+	{0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6)|BIT(7), 0},	\
+		/*.	0x29[7:6] = 2b'00	 enable BB clock*/	\
+	{0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)},	\
+		/*.	0x101[1] = 1*/					\
+	{0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF},		\
+		/* 0x100[7:0] = 0xFF enable WMAC TRX*/			\
+	{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1)|BIT(0),		\
+		BIT(1)|BIT(0)},						\
+		/* 0x02[1:0] = 2b'11  enable BB macro*/			\
+	{0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+		PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}		\
+		/*.	0x522 = 0*/
+
+#define RTL8723A_TRANS_END						\
+	/* format */							\
+	/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
+	{0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,	\
+	0, PWR_CMD_END, 0, 0}
+
+extern struct
+wlan_pwr_cfg rtl8723A_power_on_flow[RTL8723A_TRANS_CARDEMU_TO_ACT_STPS
+				    + RTL8723A_TRANS_END_STPS];
+extern struct
+wlan_pwr_cfg rtl8723A_radio_off_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+				     + RTL8723A_TRANS_END_STPS];
+extern struct
+wlan_pwr_cfg rtl8723A_card_disable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+					+ RTL8723A_TRANS_CARDEMU_TO_PDN_STPS
+					+ RTL8723A_TRANS_END_STPS];
+extern struct
+wlan_pwr_cfg rtl8723A_card_enable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+				       + RTL8723A_TRANS_CARDEMU_TO_PDN_STPS
+				       + RTL8723A_TRANS_END_STPS];
+extern struct
+wlan_pwr_cfg rtl8723A_suspend_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+				   + RTL8723A_TRANS_CARDEMU_TO_SUS_STPS
+				   + RTL8723A_TRANS_END_STPS];
+extern struct
+wlan_pwr_cfg rtl8723A_resume_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+				  + RTL8723A_TRANS_CARDEMU_TO_SUS_STPS
+				  + RTL8723A_TRANS_END_STPS];
+extern struct
+wlan_pwr_cfg rtl8723A_hwpdn_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STPS
+				 + RTL8723A_TRANS_CARDEMU_TO_PDN_STPS
+				 + RTL8723A_TRANS_END_STPS];
+extern struct
+wlan_pwr_cfg rtl8723A_enter_lps_flow[RTL8723A_TRANS_ACT_TO_LPS_STPS
+				     + RTL8723A_TRANS_END_STPS];
+extern struct
+wlan_pwr_cfg rtl8723A_leave_lps_flow[RTL8723A_TRANS_LPS_TO_ACT_STPS
+				     + RTL8723A_TRANS_END_STPS];
+
+/* RTL8723 Power Configuration CMDs for PCIe interface */
+#define Rtl8723_NIC_PWR_ON_FLOW		rtl8723A_power_on_flow
+#define Rtl8723_NIC_RF_OFF_FLOW		rtl8723A_radio_off_flow
+#define Rtl8723_NIC_DISABLE_FLOW	rtl8723A_card_disable_flow
+#define Rtl8723_NIC_ENABLE_FLOW		rtl8723A_card_enable_flow
+#define Rtl8723_NIC_SUSPEND_FLOW	rtl8723A_suspend_flow
+#define Rtl8723_NIC_RESUME_FLOW		rtl8723A_resume_flow
+#define Rtl8723_NIC_PDN_FLOW		rtl8723A_hwpdn_flow
+#define Rtl8723_NIC_LPS_ENTER_FLOW	rtl8723A_enter_lps_flow
+#define Rtl8723_NIC_LPS_LEAVE_FLOW	rtl8723A_leave_lps_flow
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.c b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.c
new file mode 100644
index 0000000..2044b59
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.c
@@ -0,0 +1,129 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "pwrseq.h"
+
+/*	Description:
+ *		This routine deals with the Power Configuration CMD
+ *		 parsing for RTL8723/RTL8188E Series IC.
+ *	Assumption:
+ *		We should follow specific format that was released from HW SD.
+ */
+bool rtl_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version,
+			      u8 faversion, u8 interface_type,
+			      struct wlan_pwr_cfg pwrcfgcmd[])
+{
+	struct wlan_pwr_cfg cfg_cmd = {0};
+	bool polling_bit = false;
+	u32 ary_idx = 0;
+	u8 value = 0;
+	u32 offset = 0;
+	u32 polling_count = 0;
+	u32 max_polling_cnt = 5000;
+
+	do {
+		cfg_cmd = pwrcfgcmd[ary_idx];
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			"rtl_hal_pwrseqcmdparsing(): offset(%#x),cut_msk(%#x), famsk(%#x),"
+			"interface_msk(%#x), base(%#x), cmd(%#x), msk(%#x), value(%#x)\n",
+			GET_PWR_CFG_OFFSET(cfg_cmd),
+					   GET_PWR_CFG_CUT_MASK(cfg_cmd),
+			GET_PWR_CFG_FAB_MASK(cfg_cmd),
+					     GET_PWR_CFG_INTF_MASK(cfg_cmd),
+			GET_PWR_CFG_BASE(cfg_cmd), GET_PWR_CFG_CMD(cfg_cmd),
+			GET_PWR_CFG_MASK(cfg_cmd), GET_PWR_CFG_VALUE(cfg_cmd));
+
+		if ((GET_PWR_CFG_FAB_MASK(cfg_cmd)&faversion) &&
+		    (GET_PWR_CFG_CUT_MASK(cfg_cmd)&cut_version) &&
+		    (GET_PWR_CFG_INTF_MASK(cfg_cmd)&interface_type)) {
+			switch (GET_PWR_CFG_CMD(cfg_cmd)) {
+			case PWR_CMD_READ:
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+					"rtl_hal_pwrseqcmdparsing(): PWR_CMD_READ\n");
+				break;
+			case PWR_CMD_WRITE:
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+					"rtl_hal_pwrseqcmdparsing(): PWR_CMD_WRITE\n");
+				offset = GET_PWR_CFG_OFFSET(cfg_cmd);
+
+				/*Read the value from system register*/
+				value = rtl_read_byte(rtlpriv, offset);
+				value &= (~(GET_PWR_CFG_MASK(cfg_cmd)));
+				value |= (GET_PWR_CFG_VALUE(cfg_cmd) &
+					  GET_PWR_CFG_MASK(cfg_cmd));
+
+				/*Write the value back to sytem register*/
+				rtl_write_byte(rtlpriv, offset, value);
+				break;
+			case PWR_CMD_POLLING:
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+					"rtl_hal_pwrseqcmdparsing(): PWR_CMD_POLLING\n");
+				polling_bit = false;
+				offset = GET_PWR_CFG_OFFSET(cfg_cmd);
+
+				do {
+					value = rtl_read_byte(rtlpriv, offset);
+
+					value &= GET_PWR_CFG_MASK(cfg_cmd);
+					if (value ==
+					    (GET_PWR_CFG_VALUE(cfg_cmd)
+					    & GET_PWR_CFG_MASK(cfg_cmd)))
+						polling_bit = true;
+					else
+						udelay(10);
+
+					if (polling_count++ > max_polling_cnt)
+						return false;
+				} while (!polling_bit);
+				break;
+			case PWR_CMD_DELAY:
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+					"rtl_hal_pwrseqcmdparsing(): PWR_CMD_DELAY\n");
+				if (GET_PWR_CFG_VALUE(cfg_cmd) ==
+				    PWRSEQ_DELAY_US)
+					udelay(GET_PWR_CFG_OFFSET(cfg_cmd));
+				else
+					mdelay(GET_PWR_CFG_OFFSET(cfg_cmd));
+				break;
+			case PWR_CMD_END:
+				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+					 "rtl_hal_pwrseqcmdparsing(): PWR_CMD_END\n");
+				return true;
+			default:
+				RT_ASSERT(false,
+					 "rtl_hal_pwrseqcmdparsing(): Unknown CMD!!\n");
+				break;
+			}
+
+		}
+		ary_idx++;
+	} while (1);
+
+	return true;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.h b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.h
new file mode 100644
index 0000000..6e0f3ea
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.h
@@ -0,0 +1,98 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_PWRSEQCMD_H__
+#define __RTL8723E_PWRSEQCMD_H__
+
+#include "../wifi.h"
+/*---------------------------------------------
+ * 3 The value of cmd: 4 bits
+ *---------------------------------------------
+ */
+#define    PWR_CMD_READ		0x00
+#define    PWR_CMD_WRITE	0x01
+#define    PWR_CMD_POLLING	0x02
+#define    PWR_CMD_DELAY	0x03
+#define    PWR_CMD_END		0x04
+
+/* define the base address of each block */
+#define   PWR_BASEADDR_MAC	0x00
+#define   PWR_BASEADDR_USB	0x01
+#define   PWR_BASEADDR_PCIE	0x02
+#define   PWR_BASEADDR_SDIO	0x03
+
+#define	PWR_INTF_SDIO_MSK	BIT(0)
+#define	PWR_INTF_USB_MSK	BIT(1)
+#define	PWR_INTF_PCI_MSK	BIT(2)
+#define	PWR_INTF_ALL_MSK	(BIT(0)|BIT(1)|BIT(2)|BIT(3))
+
+#define	PWR_FAB_TSMC_MSK	BIT(0)
+#define	PWR_FAB_UMC_MSK		BIT(1)
+#define	PWR_FAB_ALL_MSK		(BIT(0)|BIT(1)|BIT(2)|BIT(3))
+
+#define	PWR_CUT_TESTCHIP_MSK	BIT(0)
+#define	PWR_CUT_A_MSK		BIT(1)
+#define	PWR_CUT_B_MSK		BIT(2)
+#define	PWR_CUT_C_MSK		BIT(3)
+#define	PWR_CUT_D_MSK		BIT(4)
+#define	PWR_CUT_E_MSK		BIT(5)
+#define	PWR_CUT_F_MSK		BIT(6)
+#define	PWR_CUT_G_MSK		BIT(7)
+#define	PWR_CUT_ALL_MSK		0xFF
+
+enum pwrseq_delay_unit {
+	PWRSEQ_DELAY_US,
+	PWRSEQ_DELAY_MS,
+};
+
+struct wlan_pwr_cfg {
+	u16 offset;
+	u8 cut_msk;
+	u8 fab_msk:4;
+	u8 interface_msk:4;
+	u8 base:4;
+	u8 cmd:4;
+	u8 msk;
+	u8 value;
+};
+
+#define	GET_PWR_CFG_OFFSET(__PWR_CMD)	(__PWR_CMD.offset)
+#define	GET_PWR_CFG_CUT_MASK(__PWR_CMD)	(__PWR_CMD.cut_msk)
+#define	GET_PWR_CFG_FAB_MASK(__PWR_CMD)	(__PWR_CMD.fab_msk)
+#define	GET_PWR_CFG_INTF_MASK(__PWR_CMD)	(__PWR_CMD.interface_msk)
+#define	GET_PWR_CFG_BASE(__PWR_CMD)	(__PWR_CMD.base)
+#define	GET_PWR_CFG_CMD(__PWR_CMD)	(__PWR_CMD.cmd)
+#define	GET_PWR_CFG_MASK(__PWR_CMD)	(__PWR_CMD.msk)
+#define	GET_PWR_CFG_VALUE(__PWR_CMD)	(__PWR_CMD.value)
+
+bool rtl_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version,
+			      u8 fab_version, u8 interface_type,
+			      struct wlan_pwr_cfg pwrcfgcmd[]);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h b/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h
new file mode 100644
index 0000000..199da36
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h
@@ -0,0 +1,2097 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_REG_H__
+#define __RTL8723E_REG_H__
+
+#define REG_SYS_ISO_CTRL			0x0000
+#define REG_SYS_FUNC_EN				0x0002
+#define REG_APS_FSMCO				0x0004
+#define REG_SYS_CLKR				0x0008
+#define REG_9346CR				0x000A
+#define REG_EE_VPD				0x000C
+#define REG_AFE_MISC				0x0010
+#define REG_SPS0_CTRL				0x0011
+#define REG_SPS_OCP_CFG				0x0018
+#define REG_RSV_CTRL				0x001C
+#define REG_RF_CTRL				0x001F
+#define REG_LDOA15_CTRL				0x0020
+#define REG_LDOV12D_CTRL			0x0021
+#define REG_LDOHCI12_CTRL			0x0022
+#define REG_LPLDO_CTRL				0x0023
+#define REG_AFE_XTAL_CTRL			0x0024
+#define REG_AFE_PLL_CTRL			0x0028
+#define REG_EFUSE_CTRL				0x0030
+#define REG_EFUSE_TEST				0x0034
+#define REG_PWR_DATA				0x0038
+#define REG_CAL_TIMER				0x003C
+#define REG_ACLK_MON				0x003E
+#define REG_GPIO_MUXCFG				0x0040
+#define REG_GPIO_IO_SEL				0x0042
+#define REG_MAC_PINMUX_CFG			0x0043
+#define REG_GPIO_PIN_CTRL			0x0044
+#define REG_GPIO_INTM				0x0048
+#define REG_LEDCFG0				0x004C
+#define REG_LEDCFG1				0x004D
+#define REG_LEDCFG2				0x004E
+#define REG_LEDCFG3				0x004F
+#define REG_FSIMR				0x0050
+#define REG_FSISR				0x0054
+#define REG_GPIO_PIN_CTRL_2			0x0060
+#define REG_GPIO_IO_SEL_2			0x0062
+#define REG_MULTI_FUNC_CTRL			0x0068
+
+#define REG_MCUFWDL				0x0080
+
+#define REG_HMEBOX_EXT_0			0x0088
+#define REG_HMEBOX_EXT_1			0x008A
+#define REG_HMEBOX_EXT_2			0x008C
+#define REG_HMEBOX_EXT_3			0x008E
+
+#define REG_BIST_SCAN				0x00D0
+#define REG_BIST_RPT				0x00D4
+#define REG_BIST_ROM_RPT			0x00D8
+#define REG_USB_SIE_INTF			0x00E0
+#define REG_PCIE_MIO_INTF			0x00E4
+#define REG_PCIE_MIO_INTD			0x00E8
+#define REG_SYS_CFG				0x00F0
+#define REG_GPIO_OUTSTS				0x00F4
+
+#define REG_CR					0x0100
+#define REG_PBP					0x0104
+#define REG_TRXDMA_CTRL				0x010C
+#define REG_TRXFF_BNDY				0x0114
+#define REG_TRXFF_STATUS			0x0118
+#define REG_RXFF_PTR				0x011C
+#define REG_HIMR				0x0120
+#define REG_HISR				0x0124
+#define REG_HIMRE				0x0128
+#define REG_HISRE				0x012C
+#define REG_CPWM				0x012F
+#define REG_FWIMR				0x0130
+#define REG_FWISR				0x0134
+#define REG_PKTBUF_DBG_CTRL			0x0140
+#define REG_PKTBUF_DBG_DATA_L			0x0144
+#define REG_PKTBUF_DBG_DATA_H			0x0148
+
+#define REG_TC0_CTRL				0x0150
+#define REG_TC1_CTRL				0x0154
+#define REG_TC2_CTRL				0x0158
+#define REG_TC3_CTRL				0x015C
+#define REG_TC4_CTRL				0x0160
+#define REG_TCUNIT_BASE				0x0164
+#define REG_MBIST_START				0x0174
+#define REG_MBIST_DONE				0x0178
+#define REG_MBIST_FAIL				0x017C
+#define REG_C2HEVT_MSG_NORMAL			0x01A0
+#define REG_C2HEVT_MSG_TEST			0x01B8
+#define REG_MCUTST_1				0x01c0
+#define REG_FMETHR				0x01C8
+#define REG_HMETFR				0x01CC
+#define REG_HMEBOX_0				0x01D0
+#define REG_HMEBOX_1				0x01D4
+#define REG_HMEBOX_2				0x01D8
+#define REG_HMEBOX_3				0x01DC
+
+#define REG_LLT_INIT				0x01E0
+#define REG_BB_ACCEESS_CTRL			0x01E8
+#define REG_BB_ACCESS_DATA			0x01EC
+
+#define REG_RQPN				0x0200
+#define REG_FIFOPAGE				0x0204
+#define REG_TDECTRL				0x0208
+#define REG_TXDMA_OFFSET_CHK			0x020C
+#define REG_TXDMA_STATUS			0x0210
+#define REG_RQPN_NPQ				0x0214
+
+#define REG_RXDMA_AGG_PG_TH			0x0280
+#define REG_RXPKT_NUM				0x0284
+#define REG_RXDMA_STATUS			0x0288
+
+#define	REG_PCIE_CTRL_REG			0x0300
+#define	REG_INT_MIG				0x0304
+#define	REG_BCNQ_DESA				0x0308
+#define	REG_HQ_DESA				0x0310
+#define	REG_MGQ_DESA				0x0318
+#define	REG_VOQ_DESA				0x0320
+#define	REG_VIQ_DESA				0x0328
+#define	REG_BEQ_DESA				0x0330
+#define	REG_BKQ_DESA				0x0338
+#define	REG_RX_DESA				0x0340
+#define	REG_DBI					0x0348
+#define	REG_MDIO				0x0354
+#define	REG_DBG_SEL				0x0360
+#define	REG_PCIE_HRPWM				0x0361
+#define	REG_PCIE_HCPWM				0x0363
+#define	REG_UART_CTRL				0x0364
+#define	REG_UART_TX_DESA			0x0370
+#define	REG_UART_RX_DESA			0x0378
+
+#define	REG_HDAQ_DESA_NODEF			0x0000
+#define	REG_CMDQ_DESA_NODEF			0x0000
+
+#define REG_VOQ_INFORMATION			0x0400
+#define REG_VIQ_INFORMATION			0x0404
+#define REG_BEQ_INFORMATION			0x0408
+#define REG_BKQ_INFORMATION			0x040C
+#define REG_MGQ_INFORMATION			0x0410
+#define REG_HGQ_INFORMATION			0x0414
+#define REG_BCNQ_INFORMATION			0x0418
+
+#define REG_CPU_MGQ_INFORMATION			0x041C
+#define REG_FWHW_TXQ_CTRL			0x0420
+#define REG_HWSEQ_CTRL				0x0423
+#define REG_TXPKTBUF_BCNQ_BDNY			0x0424
+#define REG_TXPKTBUF_MGQ_BDNY			0x0425
+#define REG_MULTI_BCNQ_EN			0x0426
+#define REG_MULTI_BCNQ_OFFSET			0x0427
+#define REG_SPEC_SIFS				0x0428
+#define REG_RL					0x042A
+#define REG_DARFRC				0x0430
+#define REG_RARFRC				0x0438
+#define REG_RRSR				0x0440
+#define REG_ARFR0				0x0444
+#define REG_ARFR1				0x0448
+#define REG_ARFR2				0x044C
+#define REG_ARFR3				0x0450
+#define REG_AGGLEN_LMT				0x0458
+#define REG_AMPDU_MIN_SPACE			0x045C
+#define REG_TXPKTBUF_WMAC_LBK_BF_HD		0x045D
+#define REG_FAST_EDCA_CTRL			0x0460
+#define REG_RD_RESP_PKT_TH			0x0463
+#define REG_INIRTS_RATE_SEL			0x0480
+#define REG_INIDATA_RATE_SEL			0x0484
+#define REG_POWER_STATUS			0x04A4
+#define REG_POWER_STAGE1			0x04B4
+#define REG_POWER_STAGE2			0x04B8
+#define REG_PKT_LIFE_TIME			0x04C0
+#define REG_STBC_SETTING			0x04C4
+#define REG_PROT_MODE_CTRL			0x04C8
+#define REG_BAR_MODE_CTRL			0x04CC
+#define REG_RA_TRY_RATE_AGG_LMT			0x04CF
+#define REG_NQOS_SEQ				0x04DC
+#define REG_QOS_SEQ				0x04DE
+#define REG_NEED_CPU_HANDLE			0x04E0
+#define REG_PKT_LOSE_RPT			0x04E1
+#define REG_PTCL_ERR_STATUS			0x04E2
+#define REG_DUMMY				0x04FC
+
+#define REG_EDCA_VO_PARAM			0x0500
+#define REG_EDCA_VI_PARAM			0x0504
+#define REG_EDCA_BE_PARAM			0x0508
+#define REG_EDCA_BK_PARAM			0x050C
+#define REG_BCNTCFG				0x0510
+#define REG_PIFS				0x0512
+#define REG_RDG_PIFS				0x0513
+#define REG_SIFS_CTX				0x0514
+#define REG_SIFS_TRX				0x0516
+#define REG_AGGR_BREAK_TIME			0x051A
+#define REG_SLOT				0x051B
+#define REG_TX_PTCL_CTRL			0x0520
+#define REG_TXPAUSE				0x0522
+#define REG_DIS_TXREQ_CLR			0x0523
+#define REG_RD_CTRL				0x0524
+#define REG_TBTT_PROHIBIT			0x0540
+#define REG_RD_NAV_NXT				0x0544
+#define REG_NAV_PROT_LEN			0x0546
+#define REG_BCN_CTRL				0x0550
+#define REG_USTIME_TSF				0x0551
+#define REG_MBID_NUM				0x0552
+#define REG_DUAL_TSF_RST			0x0553
+#define REG_BCN_INTERVAL			0x0554
+#define REG_MBSSID_BCN_SPACE			0x0554
+#define REG_DRVERLYINT				0x0558
+#define REG_BCNDMATIM				0x0559
+#define REG_ATIMWND				0x055A
+#define REG_BCN_MAX_ERR				0x055D
+#define REG_RXTSF_OFFSET_CCK			0x055E
+#define REG_RXTSF_OFFSET_OFDM			0x055F
+#define REG_TSFTR				0x0560
+#define REG_INIT_TSFTR				0x0564
+#define REG_PSTIMER				0x0580
+#define REG_TIMER0				0x0584
+#define REG_TIMER1				0x0588
+#define REG_ACMHWCTRL				0x05C0
+#define REG_ACMRSTCTRL				0x05C1
+#define REG_ACMAVG				0x05C2
+#define REG_VO_ADMTIME				0x05C4
+#define REG_VI_ADMTIME				0x05C6
+#define REG_BE_ADMTIME				0x05C8
+#define REG_EDCA_RANDOM_GEN			0x05CC
+#define REG_SCH_TXCMD				0x05D0
+
+#define REG_APSD_CTRL				0x0600
+#define REG_BWOPMODE				0x0603
+#define REG_TCR					0x0604
+#define REG_RCR					0x0608
+#define REG_RX_PKT_LIMIT			0x060C
+#define REG_RX_DLK_TIME				0x060D
+#define REG_RX_DRVINFO_SZ			0x060F
+
+#define REG_MACID				0x0610
+#define REG_BSSID				0x0618
+#define REG_MAR					0x0620
+#define REG_MBIDCAMCFG				0x0628
+
+#define REG_USTIME_EDCA				0x0638
+#define REG_MAC_SPEC_SIFS			0x063A
+#define REG_RESP_SIFS_CCK			0x063C
+#define REG_RESP_SIFS_OFDM			0x063E
+#define REG_ACKTO				0x0640
+#define REG_CTS2TO				0x0641
+#define REG_EIFS				0x0642
+
+#define REG_NAV_CTRL				0x0650
+#define REG_BACAMCMD				0x0654
+#define REG_BACAMCONTENT			0x0658
+#define REG_LBDLY				0x0660
+#define REG_FWDLY				0x0661
+#define REG_RXERR_RPT				0x0664
+#define REG_WMAC_TRXPTCL_CTL			0x0668
+
+#define REG_CAMCMD				0x0670
+#define REG_CAMWRITE				0x0674
+#define REG_CAMREAD				0x0678
+#define REG_CAMDBG				0x067C
+#define REG_SECCFG				0x0680
+
+#define REG_WOW_CTRL				0x0690
+#define REG_PSSTATUS				0x0691
+#define REG_PS_RX_INFO				0x0692
+#define REG_LPNAV_CTRL				0x0694
+#define REG_WKFMCAM_CMD				0x0698
+#define REG_WKFMCAM_RWD				0x069C
+#define REG_RXFLTMAP0				0x06A0
+#define REG_RXFLTMAP1				0x06A2
+#define REG_RXFLTMAP2				0x06A4
+#define REG_BCN_PSR_RPT				0x06A8
+#define REG_CALB32K_CTRL			0x06AC
+#define REG_PKT_MON_CTRL			0x06B4
+#define REG_BT_COEX_TABLE			0x06C0
+#define REG_WMAC_RESP_TXINFO			0x06D8
+
+#define REG_USB_INFO				0xFE17
+#define REG_USB_SPECIAL_OPTION			0xFE55
+#define REG_USB_DMA_AGG_TO			0xFE5B
+#define REG_USB_AGG_TO				0xFE5C
+#define REG_USB_AGG_TH				0xFE5D
+
+#define REG_TEST_USB_TXQS			0xFE48
+#define REG_TEST_SIE_VID			0xFE60
+#define REG_TEST_SIE_PID			0xFE62
+#define REG_TEST_SIE_OPTIONAL			0xFE64
+#define REG_TEST_SIE_CHIRP_K			0xFE65
+#define REG_TEST_SIE_PHY			0xFE66
+#define REG_TEST_SIE_MAC_ADDR			0xFE70
+#define REG_TEST_SIE_STRING			0xFE80
+
+#define REG_NORMAL_SIE_VID			0xFE60
+#define REG_NORMAL_SIE_PID			0xFE62
+#define REG_NORMAL_SIE_OPTIONAL			0xFE64
+#define REG_NORMAL_SIE_EP			0xFE65
+#define REG_NORMAL_SIE_PHY			0xFE68
+#define REG_NORMAL_SIE_MAC_ADDR			0xFE70
+#define REG_NORMAL_SIE_STRING			0xFE80
+
+#define	CR9346					REG_9346CR
+#define	MSR					(REG_CR + 2)
+#define	ISR					REG_HISR
+#define	TSFR					REG_TSFTR
+
+#define	MACIDR0					REG_MACID
+#define	MACIDR4					(REG_MACID + 4)
+
+#define PBP					REG_PBP
+
+#define	IDR0					MACIDR0
+#define	IDR4					MACIDR4
+
+#define	UNUSED_REGISTER				0x1BF
+#define	DCAM					UNUSED_REGISTER
+#define	PSR					UNUSED_REGISTER
+#define BBADDR					UNUSED_REGISTER
+#define	PHYDATAR				UNUSED_REGISTER
+
+#define	INVALID_BBRF_VALUE			0x12345678
+
+#define	MAX_MSS_DENSITY_2T			0x13
+#define	MAX_MSS_DENSITY_1T			0x0A
+
+#define	CMDEEPROM_EN				BIT(5)
+#define	CMDEEPROM_SEL				BIT(4)
+#define	CMD9346CR_9356SEL			BIT(4)
+#define	AUTOLOAD_EEPROM				(CMDEEPROM_EN|CMDEEPROM_SEL)
+#define	AUTOLOAD_EFUSE				CMDEEPROM_EN
+
+#define	GPIOSEL_GPIO				0
+#define	GPIOSEL_ENBT				BIT(5)
+
+#define	GPIO_IN					REG_GPIO_PIN_CTRL
+#define	GPIO_OUT				(REG_GPIO_PIN_CTRL+1)
+#define	GPIO_IO_SEL				(REG_GPIO_PIN_CTRL+2)
+#define	GPIO_MOD				(REG_GPIO_PIN_CTRL+3)
+
+#define	MSR_NOLINK				0x00
+#define	MSR_ADHOC				0x01
+#define	MSR_INFRA				0x02
+#define	MSR_AP					0x03
+
+#define	RRSR_RSC_OFFSET				21
+#define	RRSR_SHORT_OFFSET			23
+#define	RRSR_RSC_BW_40M				0x600000
+#define	RRSR_RSC_UPSUBCHNL			0x400000
+#define	RRSR_RSC_LOWSUBCHNL			0x200000
+#define	RRSR_SHORT				0x800000
+#define	RRSR_1M					BIT(0)
+#define	RRSR_2M					BIT(1)
+#define	RRSR_5_5M				BIT(2)
+#define	RRSR_11M				BIT(3)
+#define	RRSR_6M					BIT(4)
+#define	RRSR_9M					BIT(5)
+#define	RRSR_12M				BIT(6)
+#define	RRSR_18M				BIT(7)
+#define	RRSR_24M				BIT(8)
+#define	RRSR_36M				BIT(9)
+#define	RRSR_48M				BIT(10)
+#define	RRSR_54M				BIT(11)
+#define	RRSR_MCS0				BIT(12)
+#define	RRSR_MCS1				BIT(13)
+#define	RRSR_MCS2				BIT(14)
+#define	RRSR_MCS3				BIT(15)
+#define	RRSR_MCS4				BIT(16)
+#define	RRSR_MCS5				BIT(17)
+#define	RRSR_MCS6				BIT(18)
+#define	RRSR_MCS7				BIT(19)
+#define	BRSR_ACKSHORTPMB			BIT(23)
+
+#define	RATR_1M					0x00000001
+#define	RATR_2M					0x00000002
+#define	RATR_55M				0x00000004
+#define	RATR_11M				0x00000008
+#define	RATR_6M					0x00000010
+#define	RATR_9M					0x00000020
+#define	RATR_12M				0x00000040
+#define	RATR_18M				0x00000080
+#define	RATR_24M				0x00000100
+#define	RATR_36M				0x00000200
+#define	RATR_48M				0x00000400
+#define	RATR_54M				0x00000800
+#define	RATR_MCS0				0x00001000
+#define	RATR_MCS1				0x00002000
+#define	RATR_MCS2				0x00004000
+#define	RATR_MCS3				0x00008000
+#define	RATR_MCS4				0x00010000
+#define	RATR_MCS5				0x00020000
+#define	RATR_MCS6				0x00040000
+#define	RATR_MCS7				0x00080000
+#define	RATR_MCS8				0x00100000
+#define	RATR_MCS9				0x00200000
+#define	RATR_MCS10				0x00400000
+#define	RATR_MCS11				0x00800000
+#define	RATR_MCS12				0x01000000
+#define	RATR_MCS13				0x02000000
+#define	RATR_MCS14				0x04000000
+#define	RATR_MCS15				0x08000000
+
+#define	RATE_ALL_CCK		(RATR_1M | RATR_2M | RATR_55M | RATR_11M)
+#define	RATE_ALL_OFDM_AG	(RATR_6M | RATR_9M | RATR_12M | RATR_18M |\
+				RATR_24M | RATR_36M | RATR_48M | RATR_54M)
+#define	RATE_ALL_OFDM_1SS	(RATR_MCS0 | RATR_MCS1 | RATR_MCS2 |\
+				RATR_MCS3 | RATR_MCS4 | RATR_MCS5 |\
+				RATR_MCS6 | RATR_MCS7)
+#define	RATE_ALL_OFDM_2SS	(RATR_MCS8 | RATR_MCS9 | RATR_MCS10 |\
+				RATR_MCS11 | RATR_MCS12 | RATR_MCS13 |\
+				RATR_MCS14 | RATR_MCS15)
+
+#define	BW_OPMODE_20MHZ				BIT(2)
+#define	BW_OPMODE_5G				BIT(1)
+#define	BW_OPMODE_11J				BIT(0)
+
+#define	CAM_VALID				BIT(15)
+#define	CAM_NOTVALID				0x0000
+#define	CAM_USEDK				BIT(5)
+
+#define	CAM_NONE				0x0
+#define	CAM_WEP40				0x01
+#define	CAM_TKIP				0x02
+#define	CAM_AES					0x04
+#define	CAM_WEP104				0x05
+
+#define	TOTAL_CAM_ENTRY				32
+#define	HALF_CAM_ENTRY				16
+
+#define	CAM_WRITE				BIT(16)
+#define	CAM_READ				0x00000000
+#define	CAM_POLLINIG				BIT(31)
+
+#define	SCR_USEDK				0x01
+#define	SCR_TXSEC_ENABLE			0x02
+#define	SCR_RXSEC_ENABLE			0x04
+
+#define	WOW_PMEN				BIT(0)
+#define	WOW_WOMEN				BIT(1)
+#define	WOW_MAGIC				BIT(2)
+#define	WOW_UWF					BIT(3)
+
+#define	IMR8190_DISABLED			0x0
+#define	IMR_BCNDMAINT6				BIT(31)
+#define	IMR_BCNDMAINT5				BIT(30)
+#define	IMR_BCNDMAINT4				BIT(29)
+#define	IMR_BCNDMAINT3				BIT(28)
+#define	IMR_BCNDMAINT2				BIT(27)
+#define	IMR_BCNDMAINT1				BIT(26)
+#define	IMR_BCNDOK8				BIT(25)
+#define	IMR_BCNDOK7				BIT(24)
+#define	IMR_BCNDOK6				BIT(23)
+#define	IMR_BCNDOK5				BIT(22)
+#define	IMR_BCNDOK4				BIT(21)
+#define	IMR_BCNDOK3				BIT(20)
+#define	IMR_BCNDOK2				BIT(19)
+#define	IMR_BCNDOK1				BIT(18)
+#define	IMR_TIMEOUT2				BIT(17)
+#define	IMR_TIMEOUT1				BIT(16)
+#define	IMR_TXFOVW				BIT(15)
+#define	IMR_PSTIMEOUT				BIT(14)
+#define	IMR_BCNINT				BIT(13)
+#define	IMR_RXFOVW				BIT(12)
+#define	IMR_RDU					BIT(11)
+#define	IMR_ATIMEND				BIT(10)
+#define	IMR_BDOK				BIT(9)
+#define	IMR_HIGHDOK				BIT(8)
+#define	IMR_TBDOK				BIT(7)
+#define	IMR_MGNTDOK				BIT(6)
+#define	IMR_TBDER				BIT(5)
+#define	IMR_BKDOK				BIT(4)
+#define	IMR_BEDOK				BIT(3)
+#define	IMR_VIDOK				BIT(2)
+#define	IMR_VODOK				BIT(1)
+#define	IMR_ROK					BIT(0)
+
+#define	IMR_TXERR				BIT(11)
+#define	IMR_RXERR				BIT(10)
+#define	IMR_CPWM				BIT(8)
+#define	IMR_OCPINT				BIT(1)
+#define	IMR_WLANOFF				BIT(0)
+
+/* 8723E series PCIE Host IMR/ISR bit */
+/* IMR DW0 Bit 0-31 */
+#define	PHIMR_TIMEOUT2				BIT(31)
+#define	PHIMR_TIMEOUT1				BIT(30)
+#define	PHIMR_PSTIMEOUT				BIT(29)
+#define	PHIMR_GTINT4				BIT(28)
+#define	PHIMR_GTINT3				BIT(27)
+#define	PHIMR_TXBCNERR				BIT(26)
+#define	PHIMR_TXBCNOK				BIT(25)
+#define	PHIMR_TSF_BIT32_TOGGLE			BIT(24)
+#define	PHIMR_BCNDMAINT3			BIT(23)
+#define	PHIMR_BCNDMAINT2			BIT(22)
+#define	PHIMR_BCNDMAINT1			BIT(21)
+#define	PHIMR_BCNDMAINT0			BIT(20)
+#define	PHIMR_BCNDOK3				BIT(19)
+#define	PHIMR_BCNDOK2				BIT(18)
+#define	PHIMR_BCNDOK1				BIT(17)
+#define	PHIMR_BCNDOK0				BIT(16)
+#define	PHIMR_HSISR_IND_ON			BIT(15)
+#define	PHIMR_BCNDMAINT_E			BIT(14)
+#define	PHIMR_ATIMEND_E				BIT(13)
+#define	PHIMR_ATIM_CTW_END			BIT(12)
+#define	PHIMR_HISRE_IND				BIT(11)
+#define	PHIMR_C2HCMD				BIT(10)
+#define	PHIMR_CPWM2				BIT(9)
+#define	PHIMR_CPWM				BIT(8)
+#define	PHIMR_HIGHDOK				BIT(7)
+#define	PHIMR_MGNTDOK				BIT(6)
+#define	PHIMR_BKDOK				BIT(5)
+#define	PHIMR_BEDOK				BIT(4)
+#define	PHIMR_VIDOK				BIT(3)
+#define	PHIMR_VODOK				BIT(2)
+#define	PHIMR_RDU				BIT(1)
+#define	PHIMR_ROK				BIT(0)
+
+/* PCIE Host Interrupt Status Extension bit */
+#define	PHIMR_BCNDMAINT7			BIT(23)
+#define	PHIMR_BCNDMAINT6			BIT(22)
+#define	PHIMR_BCNDMAINT5			BIT(21)
+#define	PHIMR_BCNDMAINT4			BIT(20)
+#define	PHIMR_BCNDOK7				BIT(19)
+#define	PHIMR_BCNDOK6				BIT(18)
+#define	PHIMR_BCNDOK5				BIT(17)
+#define	PHIMR_BCNDOK4				BIT(16)
+/* bit12-15: RSVD */
+#define	PHIMR_TXERR				BIT(11)
+#define	PHIMR_RXERR				BIT(10)
+#define	PHIMR_TXFOVW				BIT(9)
+#define	PHIMR_RXFOVW				BIT(8)
+/* bit2-7: RSV */
+#define	PHIMR_OCPINT				BIT(1)
+
+#define	HWSET_MAX_SIZE				256
+#define EFUSE_MAX_SECTION			32
+#define EFUSE_REAL_CONTENT_LEN			512
+#define EFUSE_OOB_PROTECT_BYTES			15
+
+#define	EEPROM_DEFAULT_TSSI			0x0
+#define EEPROM_DEFAULT_TXPOWERDIFF		0x0
+#define EEPROM_DEFAULT_CRYSTALCAP		0x5
+#define EEPROM_DEFAULT_BOARDTYPE		0x02
+#define EEPROM_DEFAULT_TXPOWER			0x1010
+#define	EEPROM_DEFAULT_HT2T_TXPWR		0x10
+
+#define	EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF	0x3
+#define	EEPROM_DEFAULT_THERMALMETER		0x12
+#define	EEPROM_DEFAULT_ANTTXPOWERDIFF		0x0
+#define	EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP	0x5
+#define	EEPROM_DEFAULT_TXPOWERLEVEL		0x22
+#define	EEPROM_DEFAULT_HT40_2SDIFF		0x0
+#define EEPROM_DEFAULT_HT20_DIFF		2
+#define	EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF	0x3
+#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET	0
+#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET	0
+
+
+#define EEPROM_DEFAULT_PID			0x1234
+#define EEPROM_DEFAULT_VID			0x5678
+#define EEPROM_DEFAULT_CUSTOMERID		0xAB
+#define EEPROM_DEFAULT_SUBCUSTOMERID		0xCD
+#define EEPROM_DEFAULT_VERSION			0
+
+#define	EEPROM_CHANNEL_PLAN_FCC			0x0
+#define	EEPROM_CHANNEL_PLAN_IC			0x1
+#define	EEPROM_CHANNEL_PLAN_ETSI		0x2
+#define	EEPROM_CHANNEL_PLAN_SPAIN		0x3
+#define	EEPROM_CHANNEL_PLAN_FRANCE		0x4
+#define	EEPROM_CHANNEL_PLAN_MKK			0x5
+#define	EEPROM_CHANNEL_PLAN_MKK1		0x6
+#define	EEPROM_CHANNEL_PLAN_ISRAEL		0x7
+#define	EEPROM_CHANNEL_PLAN_TELEC		0x8
+#define	EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN	0x9
+#define	EEPROM_CHANNEL_PLAN_WORLD_WIDE_13	0xA
+#define	EEPROM_CHANNEL_PLAN_NCC			0xB
+#define	EEPROM_CHANNEL_PLAN_BY_HW_MASK		0x80
+
+#define EEPROM_CID_DEFAULT			0x0
+#define EEPROM_CID_TOSHIBA			0x4
+#define	EEPROM_CID_CCX				0x10
+#define	EEPROM_CID_QMI				0x0D
+#define EEPROM_CID_WHQL				0xFE
+
+#define	RTL8192_EEPROM_ID			0x8129
+
+#define RTL8190_EEPROM_ID			0x8129
+#define EEPROM_HPON				0x02
+#define EEPROM_CLK				0x06
+#define EEPROM_TESTR				0x08
+
+#define EEPROM_VID				0x49
+#define EEPROM_DID				0x4B
+#define EEPROM_SVID				0x4D
+#define EEPROM_SMID				0x4F
+
+#define EEPROM_MAC_ADDR				0x67
+
+#define EEPROM_CCK_TX_PWR_INX			0x5A
+#define EEPROM_HT40_1S_TX_PWR_INX		0x60
+#define EEPROM_HT40_2S_TX_PWR_INX_DIFF		0x66
+#define EEPROM_HT20_TX_PWR_INX_DIFF		0x69
+#define EEPROM_OFDM_TX_PWR_INX_DIFF		0x6C
+#define EEPROM_HT40_MAX_PWR_OFFSET		0x25
+#define EEPROM_HT20_MAX_PWR_OFFSET		0x22
+
+#define EEPROM_THERMAL_METER			0x2a
+#define EEPROM_XTAL_K				0x78
+#define EEPROM_RF_OPT1				0x79
+#define EEPROM_RF_OPT2				0x7A
+#define EEPROM_RF_OPT3				0x7B
+#define EEPROM_RF_OPT4				0x7C
+#define EEPROM_CHANNEL_PLAN			0x28
+#define EEPROM_VERSION				0x30
+#define EEPROM_CUSTOMER_ID			0x31
+
+#define EEPROM_PWRDIFF				0x54
+
+#define EEPROM_TXPOWERCCK			0x10
+#define	EEPROM_TXPOWERHT40_1S			0x16
+#define	EEPROM_TXPOWERHT40_2SDIFF		0x66
+#define EEPROM_TXPOWERHT20DIFF			0x1C
+#define EEPROM_TXPOWER_OFDMDIFF			0x1F
+
+#define	EEPROM_TXPWR_GROUP			0x22
+
+#define EEPROM_TSSI_A				0x29
+#define EEPROM_TSSI_B				0x77
+
+#define EEPROM_CHANNELPLAN			0x28
+
+#define RF_OPTION1				0x2B
+#define RF_OPTION2				0x2C
+#define RF_OPTION3				0x2D
+#define RF_OPTION4				0x2E
+
+#define	STOPBECON				BIT(6)
+#define	STOPHIGHT				BIT(5)
+#define	STOPMGT					BIT(4)
+#define	STOPVO					BIT(3)
+#define	STOPVI					BIT(2)
+#define	STOPBE					BIT(1)
+#define	STOPBK					BIT(0)
+
+#define	RCR_APPFCS				BIT(31)
+#define	RCR_APP_MIC				BIT(30)
+#define	RCR_APP_ICV				BIT(29)
+#define	RCR_APP_PHYST_RXFF			BIT(28)
+#define	RCR_APP_BA_SSN				BIT(27)
+#define	RCR_ENMBID				BIT(24)
+#define	RCR_LSIGEN				BIT(23)
+#define	RCR_MFBEN				BIT(22)
+#define	RCR_HTC_LOC_CTRL			BIT(14)
+#define	RCR_AMF					BIT(13)
+#define	RCR_ACF					BIT(12)
+#define	RCR_ADF					BIT(11)
+#define	RCR_AICV				BIT(9)
+#define	RCR_ACRC32				BIT(8)
+#define	RCR_CBSSID_BCN				BIT(7)
+#define	RCR_CBSSID_DATA				BIT(6)
+#define	RCR_CBSSID				RCR_CBSSID_DATA
+#define	RCR_APWRMGT				BIT(5)
+#define	RCR_ADD3				BIT(4)
+#define	RCR_AB					BIT(3)
+#define	RCR_AM					BIT(2)
+#define	RCR_APM					BIT(1)
+#define	RCR_AAP					BIT(0)
+#define	RCR_MXDMA_OFFSET			8
+#define	RCR_FIFO_OFFSET				13
+
+#define RSV_CTRL				0x001C
+#define RD_CTRL					0x0524
+
+#define REG_USB_INFO				0xFE17
+#define REG_USB_SPECIAL_OPTION			0xFE55
+#define REG_USB_DMA_AGG_TO			0xFE5B
+#define REG_USB_AGG_TO				0xFE5C
+#define REG_USB_AGG_TH				0xFE5D
+
+#define REG_USB_VID				0xFE60
+#define REG_USB_PID				0xFE62
+#define REG_USB_OPTIONAL			0xFE64
+#define REG_USB_CHIRP_K				0xFE65
+#define REG_USB_PHY				0xFE66
+#define REG_USB_MAC_ADDR			0xFE70
+#define REG_USB_HRPWM				0xFE58
+#define REG_USB_HCPWM				0xFE57
+
+#define SW18_FPWM				BIT(3)
+
+#define ISO_MD2PP				BIT(0)
+#define ISO_UA2USB				BIT(1)
+#define ISO_UD2CORE				BIT(2)
+#define ISO_PA2PCIE				BIT(3)
+#define ISO_PD2CORE				BIT(4)
+#define ISO_IP2MAC				BIT(5)
+#define ISO_DIOP				BIT(6)
+#define ISO_DIOE				BIT(7)
+#define ISO_EB2CORE				BIT(8)
+#define ISO_DIOR				BIT(9)
+
+#define PWC_EV25V				BIT(14)
+#define PWC_EV12V				BIT(15)
+
+#define FEN_BBRSTB				BIT(0)
+#define FEN_BB_GLB_RSTn				BIT(1)
+#define FEN_USBA				BIT(2)
+#define FEN_UPLL				BIT(3)
+#define FEN_USBD				BIT(4)
+#define FEN_DIO_PCIE				BIT(5)
+#define FEN_PCIEA				BIT(6)
+#define FEN_PPLL				BIT(7)
+#define FEN_PCIED				BIT(8)
+#define FEN_DIOE				BIT(9)
+#define FEN_CPUEN				BIT(10)
+#define FEN_DCORE				BIT(11)
+#define FEN_ELDR				BIT(12)
+#define FEN_DIO_RF				BIT(13)
+#define FEN_HWPDN				BIT(14)
+#define FEN_MREGEN				BIT(15)
+
+#define PFM_LDALL				BIT(0)
+#define PFM_ALDN				BIT(1)
+#define PFM_LDKP				BIT(2)
+#define PFM_WOWL				BIT(3)
+#define EnPDN					BIT(4)
+#define PDN_PL					BIT(5)
+#define APFM_ONMAC				BIT(8)
+#define APFM_OFF				BIT(9)
+#define APFM_RSM				BIT(10)
+#define AFSM_HSUS				BIT(11)
+#define AFSM_PCIE				BIT(12)
+#define APDM_MAC				BIT(13)
+#define APDM_HOST				BIT(14)
+#define APDM_HPDN				BIT(15)
+#define RDY_MACON				BIT(16)
+#define SUS_HOST				BIT(17)
+#define ROP_ALD					BIT(20)
+#define ROP_PWR					BIT(21)
+#define ROP_SPS					BIT(22)
+#define SOP_MRST				BIT(25)
+#define SOP_FUSE				BIT(26)
+#define SOP_ABG					BIT(27)
+#define SOP_AMB					BIT(28)
+#define SOP_RCK					BIT(29)
+#define SOP_A8M					BIT(30)
+#define XOP_BTCK				BIT(31)
+
+#define ANAD16V_EN				BIT(0)
+#define ANA8M					BIT(1)
+#define MACSLP					BIT(4)
+#define LOADER_CLK_EN				BIT(5)
+#define _80M_SSC_DIS				BIT(7)
+#define _80M_SSC_EN_HO				BIT(8)
+#define PHY_SSC_RSTB				BIT(9)
+#define SEC_CLK_EN				BIT(10)
+#define MAC_CLK_EN				BIT(11)
+#define SYS_CLK_EN				BIT(12)
+#define RING_CLK_EN				BIT(13)
+
+#define	BOOT_FROM_EEPROM			BIT(4)
+#define	EEPROM_EN				BIT(5)
+
+#define AFE_BGEN				BIT(0)
+#define AFE_MBEN				BIT(1)
+#define MAC_ID_EN				BIT(7)
+
+#define WLOCK_ALL				BIT(0)
+#define WLOCK_00				BIT(1)
+#define WLOCK_04				BIT(2)
+#define WLOCK_08				BIT(3)
+#define WLOCK_40				BIT(4)
+#define R_DIS_PRST_0				BIT(5)
+#define R_DIS_PRST_1				BIT(6)
+#define LOCK_ALL_EN				BIT(7)
+
+#define RF_EN					BIT(0)
+#define RF_RSTB					BIT(1)
+#define RF_SDMRSTB				BIT(2)
+
+#define LDA15_EN				BIT(0)
+#define LDA15_STBY				BIT(1)
+#define LDA15_OBUF				BIT(2)
+#define LDA15_REG_VOS				BIT(3)
+#define _LDA15_VOADJ(x)				(((x) & 0x7) << 4)
+
+#define LDV12_EN				BIT(0)
+#define LDV12_SDBY				BIT(1)
+#define LPLDO_HSM				BIT(2)
+#define LPLDO_LSM_DIS				BIT(3)
+#define _LDV12_VADJ(x)				(((x) & 0xF) << 4)
+
+#define XTAL_EN					BIT(0)
+#define XTAL_BSEL				BIT(1)
+#define _XTAL_BOSC(x)				(((x) & 0x3) << 2)
+#define _XTAL_CADJ(x)				(((x) & 0xF) << 4)
+#define XTAL_GATE_USB				BIT(8)
+#define _XTAL_USB_DRV(x)			(((x) & 0x3) << 9)
+#define XTAL_GATE_AFE				BIT(11)
+#define _XTAL_AFE_DRV(x)			(((x) & 0x3) << 12)
+#define XTAL_RF_GATE				BIT(14)
+#define _XTAL_RF_DRV(x)				(((x) & 0x3) << 15)
+#define XTAL_GATE_DIG				BIT(17)
+#define _XTAL_DIG_DRV(x)			(((x) & 0x3) << 18)
+#define XTAL_BT_GATE				BIT(20)
+#define _XTAL_BT_DRV(x)				(((x) & 0x3) << 21)
+#define _XTAL_GPIO(x)				(((x) & 0x7) << 23)
+
+#define CKDLY_AFE				BIT(26)
+#define CKDLY_USB				BIT(27)
+#define CKDLY_DIG				BIT(28)
+#define CKDLY_BT				BIT(29)
+
+#define APLL_EN					BIT(0)
+#define APLL_320_EN				BIT(1)
+#define APLL_FREF_SEL				BIT(2)
+#define APLL_EDGE_SEL				BIT(3)
+#define APLL_WDOGB				BIT(4)
+#define APLL_LPFEN				BIT(5)
+
+#define APLL_REF_CLK_13MHZ			0x1
+#define APLL_REF_CLK_19_2MHZ			0x2
+#define APLL_REF_CLK_20MHZ			0x3
+#define APLL_REF_CLK_25MHZ			0x4
+#define APLL_REF_CLK_26MHZ			0x5
+#define APLL_REF_CLK_38_4MHZ			0x6
+#define APLL_REF_CLK_40MHZ			0x7
+
+#define APLL_320EN				BIT(14)
+#define APLL_80EN				BIT(15)
+#define APLL_1MEN				BIT(24)
+
+#define ALD_EN					BIT(18)
+#define EF_PD					BIT(19)
+#define EF_FLAG					BIT(31)
+
+#define EF_TRPT					BIT(7)
+#define LDOE25_EN				BIT(31)
+
+#define RSM_EN					BIT(0)
+#define Timer_EN				BIT(4)
+
+#define TRSW0EN					BIT(2)
+#define TRSW1EN					BIT(3)
+#define EROM_EN					BIT(4)
+#define EnBT					BIT(5)
+#define EnUart					BIT(8)
+#define Uart_910				BIT(9)
+#define EnPMAC					BIT(10)
+#define SIC_SWRST				BIT(11)
+#define EnSIC					BIT(12)
+#define SIC_23					BIT(13)
+#define EnHDP					BIT(14)
+#define SIC_LBK					BIT(15)
+
+#define LED0PL					BIT(4)
+#define LED1PL					BIT(12)
+#define LED0DIS					BIT(7)
+
+#define MCUFWDL_EN				BIT(0)
+#define MCUFWDL_RDY				BIT(1)
+#define FWDL_ChkSum_rpt				BIT(2)
+#define MACINI_RDY				BIT(3)
+#define BBINI_RDY				BIT(4)
+#define RFINI_RDY				BIT(5)
+#define WINTINI_RDY				BIT(6)
+#define CPRST					BIT(23)
+
+#define XCLK_VLD				BIT(0)
+#define ACLK_VLD				BIT(1)
+#define UCLK_VLD				BIT(2)
+#define PCLK_VLD				BIT(3)
+#define PCIRSTB					BIT(4)
+#define V15_VLD					BIT(5)
+#define TRP_B15V_EN				BIT(7)
+#define SIC_IDLE				BIT(8)
+#define BD_MAC2					BIT(9)
+#define BD_MAC1					BIT(10)
+#define IC_MACPHY_MODE				BIT(11)
+#define BT_FUNC					BIT(16)
+#define VENDOR_ID				BIT(19)
+#define PAD_HWPD_IDN				BIT(22)
+#define TRP_VAUX_EN				BIT(23)
+#define TRP_BT_EN				BIT(24)
+#define BD_PKG_SEL				BIT(25)
+#define BD_HCI_SEL				BIT(26)
+#define TYPE_ID					BIT(27)
+
+#define CHIP_VER_RTL_MASK			0xF000
+#define CHIP_VER_RTL_SHIFT			12
+
+#define REG_LBMODE				(REG_CR + 3)
+
+#define HCI_TXDMA_EN				BIT(0)
+#define HCI_RXDMA_EN				BIT(1)
+#define TXDMA_EN				BIT(2)
+#define RXDMA_EN				BIT(3)
+#define PROTOCOL_EN				BIT(4)
+#define SCHEDULE_EN				BIT(5)
+#define MACTXEN					BIT(6)
+#define MACRXEN					BIT(7)
+#define ENSWBCN					BIT(8)
+#define ENSEC					BIT(9)
+
+#define _NETTYPE(x)				(((x) & 0x3) << 16)
+#define MASK_NETTYPE				0x30000
+#define NT_NO_LINK				0x0
+#define NT_LINK_AD_HOC				0x1
+#define NT_LINK_AP				0x2
+#define NT_AS_AP				0x3
+
+#define _LBMODE(x)				(((x) & 0xF) << 24)
+#define MASK_LBMODE				0xF000000
+#define LOOPBACK_NORMAL				0x0
+#define LOOPBACK_IMMEDIATELY			0xB
+#define LOOPBACK_MAC_DELAY			0x3
+#define LOOPBACK_PHY				0x1
+#define LOOPBACK_DMA				0x7
+
+#define GET_RX_PAGE_SIZE(value)			((value) & 0xF)
+#define GET_TX_PAGE_SIZE(value)			(((value) & 0xF0) >> 4)
+#define _PSRX_MASK				0xF
+#define _PSTX_MASK				0xF0
+#define _PSRX(x)				(x)
+#define _PSTX(x)				((x) << 4)
+
+#define PBP_64					0x0
+#define PBP_128					0x1
+#define PBP_256					0x2
+#define PBP_512					0x3
+#define PBP_1024				0x4
+
+#define RXDMA_ARBBW_EN				BIT(0)
+#define RXSHFT_EN				BIT(1)
+#define RXDMA_AGG_EN				BIT(2)
+#define QS_VO_QUEUE				BIT(8)
+#define QS_VI_QUEUE				BIT(9)
+#define QS_BE_QUEUE				BIT(10)
+#define QS_BK_QUEUE				BIT(11)
+#define QS_MANAGER_QUEUE			BIT(12)
+#define QS_HIGH_QUEUE				BIT(13)
+
+#define HQSEL_VOQ				BIT(0)
+#define HQSEL_VIQ				BIT(1)
+#define HQSEL_BEQ				BIT(2)
+#define HQSEL_BKQ				BIT(3)
+#define HQSEL_MGTQ				BIT(4)
+#define HQSEL_HIQ				BIT(5)
+
+#define _TXDMA_HIQ_MAP(x)			(((x)&0x3) << 14)
+#define _TXDMA_MGQ_MAP(x)			(((x)&0x3) << 12)
+#define _TXDMA_BKQ_MAP(x)			(((x)&0x3) << 10)
+#define _TXDMA_BEQ_MAP(x)			(((x)&0x3) << 8)
+#define _TXDMA_VIQ_MAP(x)			(((x)&0x3) << 6)
+#define _TXDMA_VOQ_MAP(x)			(((x)&0x3) << 4)
+
+#define QUEUE_LOW				1
+#define QUEUE_NORMAL				2
+#define QUEUE_HIGH				3
+
+#define _LLT_NO_ACTIVE				0x0
+#define _LLT_WRITE_ACCESS			0x1
+#define _LLT_READ_ACCESS			0x2
+
+#define _LLT_INIT_DATA(x)			((x) & 0xFF)
+#define _LLT_INIT_ADDR(x)			(((x) & 0xFF) << 8)
+#define _LLT_OP(x)				(((x) & 0x3) << 30)
+#define _LLT_OP_VALUE(x)			(((x) >> 30) & 0x3)
+
+#define BB_WRITE_READ_MASK			(BIT(31) | BIT(30))
+#define BB_WRITE_EN				BIT(30)
+#define BB_READ_EN				BIT(31)
+
+#define _HPQ(x)					((x) & 0xFF)
+#define _LPQ(x)					(((x) & 0xFF) << 8)
+#define _PUBQ(x)				(((x) & 0xFF) << 16)
+#define _NPQ(x)					((x) & 0xFF)
+
+#define HPQ_PUBLIC_DIS				BIT(24)
+#define LPQ_PUBLIC_DIS				BIT(25)
+#define LD_RQPN					BIT(31)
+
+#define BCN_VALID				BIT(16)
+#define BCN_HEAD(x)				(((x) & 0xFF) << 8)
+#define	BCN_HEAD_MASK				0xFF00
+
+#define BLK_DESC_NUM_SHIFT			4
+#define BLK_DESC_NUM_MASK			0xF
+
+#define DROP_DATA_EN				BIT(9)
+
+#define EN_AMPDU_RTY_NEW			BIT(7)
+
+#define _INIRTSMCS_SEL(x)			((x) & 0x3F)
+
+#define _SPEC_SIFS_CCK(x)			((x) & 0xFF)
+#define _SPEC_SIFS_OFDM(x)			(((x) & 0xFF) << 8)
+
+#define RATE_REG_BITMAP_ALL			0xFFFFF
+
+#define _RRSC_BITMAP(x)				((x) & 0xFFFFF)
+
+#define _RRSR_RSC(x)				(((x) & 0x3) << 21)
+#define RRSR_RSC_RESERVED			0x0
+#define RRSR_RSC_UPPER_SUBCHANNEL		0x1
+#define RRSR_RSC_LOWER_SUBCHANNEL		0x2
+#define RRSR_RSC_DUPLICATE_MODE			0x3
+
+#define USE_SHORT_G1				BIT(20)
+
+#define _AGGLMT_MCS0(x)				((x) & 0xF)
+#define _AGGLMT_MCS1(x)				(((x) & 0xF) << 4)
+#define _AGGLMT_MCS2(x)				(((x) & 0xF) << 8)
+#define _AGGLMT_MCS3(x)				(((x) & 0xF) << 12)
+#define _AGGLMT_MCS4(x)				(((x) & 0xF) << 16)
+#define _AGGLMT_MCS5(x)				(((x) & 0xF) << 20)
+#define _AGGLMT_MCS6(x)				(((x) & 0xF) << 24)
+#define _AGGLMT_MCS7(x)				(((x) & 0xF) << 28)
+
+#define	RETRY_LIMIT_SHORT_SHIFT			8
+#define	RETRY_LIMIT_LONG_SHIFT			0
+
+#define _DARF_RC1(x)				((x) & 0x1F)
+#define _DARF_RC2(x)				(((x) & 0x1F) << 8)
+#define _DARF_RC3(x)				(((x) & 0x1F) << 16)
+#define _DARF_RC4(x)				(((x) & 0x1F) << 24)
+#define _DARF_RC5(x)				((x) & 0x1F)
+#define _DARF_RC6(x)				(((x) & 0x1F) << 8)
+#define _DARF_RC7(x)				(((x) & 0x1F) << 16)
+#define _DARF_RC8(x)				(((x) & 0x1F) << 24)
+
+#define _RARF_RC1(x)				((x) & 0x1F)
+#define _RARF_RC2(x)				(((x) & 0x1F) << 8)
+#define _RARF_RC3(x)				(((x) & 0x1F) << 16)
+#define _RARF_RC4(x)				(((x) & 0x1F) << 24)
+#define _RARF_RC5(x)				((x) & 0x1F)
+#define _RARF_RC6(x)				(((x) & 0x1F) << 8)
+#define _RARF_RC7(x)				(((x) & 0x1F) << 16)
+#define _RARF_RC8(x)				(((x) & 0x1F) << 24)
+
+#define AC_PARAM_TXOP_LIMIT_OFFSET		16
+#define AC_PARAM_ECW_MAX_OFFSET			12
+#define AC_PARAM_ECW_MIN_OFFSET			8
+#define AC_PARAM_AIFS_OFFSET			0
+
+#define _AIFS(x)				(x)
+#define _ECW_MAX_MIN(x)				((x) << 8)
+#define _TXOP_LIMIT(x)				((x) << 16)
+
+#define _BCNIFS(x)				((x) & 0xFF)
+#define _BCNECW(x)				((((x) & 0xF)) << 8)
+
+#define _LRL(x)					((x) & 0x3F)
+#define _SRL(x)					(((x) & 0x3F) << 8)
+
+#define _SIFS_CCK_CTX(x)			((x) & 0xFF)
+#define _SIFS_CCK_TRX(x)			(((x) & 0xFF) << 8);
+
+#define _SIFS_OFDM_CTX(x)			((x) & 0xFF)
+#define _SIFS_OFDM_TRX(x)			(((x) & 0xFF) << 8);
+
+#define _TBTT_PROHIBIT_HOLD(x)			(((x) & 0xFF) << 8)
+
+#define DIS_EDCA_CNT_DWN			BIT(11)
+
+#define EN_MBSSID				BIT(1)
+#define EN_TXBCN_RPT				BIT(2)
+#define	EN_BCN_FUNCTION				BIT(3)
+
+#define TSFTR_RST				BIT(0)
+#define TSFTR1_RST				BIT(1)
+
+#define STOP_BCNQ				BIT(6)
+
+#define	DIS_TSF_UDT0_NORMAL_CHIP		BIT(4)
+#define	DIS_TSF_UDT0_TEST_CHIP			BIT(5)
+
+#define	AcmHw_HwEn				BIT(0)
+#define	AcmHw_BeqEn				BIT(1)
+#define	AcmHw_ViqEn				BIT(2)
+#define	AcmHw_VoqEn				BIT(3)
+#define	AcmHw_BeqStatus				BIT(4)
+#define	AcmHw_ViqStatus				BIT(5)
+#define	AcmHw_VoqStatus				BIT(6)
+
+#define APSDOFF					BIT(6)
+#define APSDOFF_STATUS				BIT(7)
+
+#define BW_20MHZ				BIT(2)
+
+#define RATE_BITMAP_ALL				0xFFFFF
+
+#define RATE_RRSR_CCK_ONLY_1M			0xFFFF1
+
+#define TSFRST					BIT(0)
+#define DIS_GCLK				BIT(1)
+#define PAD_SEL					BIT(2)
+#define PWR_ST					BIT(6)
+#define PWRBIT_OW_EN				BIT(7)
+#define ACRC					BIT(8)
+#define CFENDFORM				BIT(9)
+#define ICV					BIT(10)
+
+#define AAP					BIT(0)
+#define APM					BIT(1)
+#define AM					BIT(2)
+#define AB					BIT(3)
+#define ADD3					BIT(4)
+#define APWRMGT					BIT(5)
+#define CBSSID					BIT(6)
+#define CBSSID_DATA				BIT(6)
+#define CBSSID_BCN				BIT(7)
+#define ACRC32					BIT(8)
+#define AICV					BIT(9)
+#define ADF					BIT(11)
+#define ACF					BIT(12)
+#define AMF					BIT(13)
+#define HTC_LOC_CTRL				BIT(14)
+#define UC_DATA_EN				BIT(16)
+#define BM_DATA_EN				BIT(17)
+#define MFBEN					BIT(22)
+#define LSIGEN					BIT(23)
+#define EnMBID					BIT(24)
+#define APP_BASSN				BIT(27)
+#define APP_PHYSTS				BIT(28)
+#define APP_ICV					BIT(29)
+#define APP_MIC					BIT(30)
+#define APP_FCS					BIT(31)
+
+#define _MIN_SPACE(x)				((x) & 0x7)
+#define _SHORT_GI_PADDING(x)			(((x) & 0x1F) << 3)
+
+#define RXERR_TYPE_OFDM_PPDU			0
+#define RXERR_TYPE_OFDM_FALSE_ALARM		1
+#define	RXERR_TYPE_OFDM_MPDU_OK			2
+#define RXERR_TYPE_OFDM_MPDU_FAIL		3
+#define RXERR_TYPE_CCK_PPDU			4
+#define RXERR_TYPE_CCK_FALSE_ALARM		5
+#define RXERR_TYPE_CCK_MPDU_OK			6
+#define RXERR_TYPE_CCK_MPDU_FAIL		7
+#define RXERR_TYPE_HT_PPDU			8
+#define RXERR_TYPE_HT_FALSE_ALARM		9
+#define RXERR_TYPE_HT_MPDU_TOTAL		10
+#define RXERR_TYPE_HT_MPDU_OK			11
+#define RXERR_TYPE_HT_MPDU_FAIL			12
+#define RXERR_TYPE_RX_FULL_DROP			15
+
+#define RXERR_COUNTER_MASK			0xFFFFF
+#define RXERR_RPT_RST				BIT(27)
+#define _RXERR_RPT_SEL(type)			((type) << 28)
+
+#define	SCR_TxUseDK				BIT(0)
+#define	SCR_RxUseDK				BIT(1)
+#define	SCR_TxEncEnable				BIT(2)
+#define	SCR_RxDecEnable				BIT(3)
+#define	SCR_SKByA2				BIT(4)
+#define	SCR_NoSKMC				BIT(5)
+#define SCR_TXBCUSEDK				BIT(6)
+#define SCR_RXBCUSEDK				BIT(7)
+
+#define USB_IS_HIGH_SPEED			0
+#define USB_IS_FULL_SPEED			1
+#define USB_SPEED_MASK				BIT(5)
+
+#define USB_NORMAL_SIE_EP_MASK			0xF
+#define USB_NORMAL_SIE_EP_SHIFT			4
+
+#define USB_TEST_EP_MASK			0x30
+#define USB_TEST_EP_SHIFT			4
+
+#define USB_AGG_EN				BIT(3)
+
+#define MAC_ADDR_LEN				6
+#define LAST_ENTRY_OF_TX_PKT_BUFFER		255
+
+#define POLLING_LLT_THRESHOLD			20
+#define POLLING_READY_TIMEOUT_COUNT		1000
+
+#define	MAX_MSS_DENSITY_2T			0x13
+#define	MAX_MSS_DENSITY_1T			0x0A
+
+#define EPROM_CMD_OPERATING_MODE_MASK		((1<<7)|(1<<6))
+#define EPROM_CMD_CONFIG			0x3
+#define EPROM_CMD_LOAD				1
+
+#define	HWSET_MAX_SIZE_92S			HWSET_MAX_SIZE
+
+#define	HAL_8192C_HW_GPIO_WPS_BIT		BIT(2)
+
+#define	RPMAC_RESET				0x100
+#define	RPMAC_TXSTART				0x104
+#define	RPMAC_TXLEGACYSIG			0x108
+#define	RPMAC_TXHTSIG1				0x10c
+#define	RPMAC_TXHTSIG2				0x110
+#define	RPMAC_PHYDEBUG				0x114
+#define	RPMAC_TXPACKETNUM			0x118
+#define	RPMAC_TXIDLE				0x11c
+#define	RPMAC_TXMACHEADER0			0x120
+#define	RPMAC_TXMACHEADER1			0x124
+#define	RPMAC_TXMACHEADER2			0x128
+#define	RPMAC_TXMACHEADER3			0x12c
+#define	RPMAC_TXMACHEADER4			0x130
+#define	RPMAC_TXMACHEADER5			0x134
+#define	RPMAC_TXDADATYPE			0x138
+#define	RPMAC_TXRANDOMSEED			0x13c
+#define	RPMAC_CCKPLCPPREAMBLE			0x140
+#define	RPMAC_CCKPLCPHEADER			0x144
+#define	RPMAC_CCKCRC16				0x148
+#define	RPMAC_OFDMRXCRC32OK			0x170
+#define	RPMAC_OFDMRXCRC32Er			0x174
+#define	RPMAC_OFDMRXPARITYER			0x178
+#define	RPMAC_OFDMRXCRC8ER			0x17c
+#define	RPMAC_CCKCRXRC16ER			0x180
+#define	RPMAC_CCKCRXRC32ER			0x184
+#define	RPMAC_CCKCRXRC32OK			0x188
+#define	RPMAC_TXSTATUS				0x18c
+
+#define	RFPGA0_RFMOD				0x800
+
+#define	RFPGA0_TXINFO				0x804
+#define	RFPGA0_PSDFUNCTION			0x808
+
+#define	RFPGA0_TXGAINSTAGE			0x80c
+
+#define	RFPGA0_RFTIMING1			0x810
+#define	RFPGA0_RFTIMING2			0x814
+
+#define	RFPGA0_XA_HSSIPARAMETER1		0x820
+#define	RFPGA0_XA_HSSIPARAMETER2		0x824
+#define	RFPGA0_XB_HSSIPARAMETER1		0x828
+#define	RFPGA0_XB_HSSIPARAMETER2		0x82c
+
+#define	RFPGA0_XA_LSSIPARAMETER			0x840
+#define	RFPGA0_XB_LSSIPARAMETER			0x844
+
+#define	RFPGA0_RFWAKEUPPARAMETER		0x850
+#define	RFPGA0_RFSLEEPUPPARAMETER		0x854
+
+#define	RFPGA0_XAB_SWITCHCONTROL		0x858
+#define	RFPGA0_XCD_SWITCHCONTROL		0x85c
+
+#define	RFPGA0_XA_RFINTERFACEOE			0x860
+#define	RFPGA0_XB_RFINTERFACEOE			0x864
+
+#define	RFPGA0_XAB_RFINTERFACESW		0x870
+#define	RFPGA0_XCD_RFINTERFACESW		0x874
+
+#define	rFPGA0_XAB_RFPARAMETER			0x878
+#define	rFPGA0_XCD_RFPARAMETER			0x87c
+
+#define	RFPGA0_ANALOGPARAMETER1			0x880
+#define	RFPGA0_ANALOGPARAMETER2			0x884
+#define	RFPGA0_ANALOGPARAMETER3			0x888
+#define	RFPGA0_ANALOGPARAMETER4			0x88c
+
+#define	RFPGA0_XA_LSSIREADBACK			0x8a0
+#define	RFPGA0_XB_LSSIREADBACK			0x8a4
+#define	RFPGA0_XC_LSSIREADBACK			0x8a8
+#define	RFPGA0_XD_LSSIREADBACK			0x8ac
+
+#define	RFPGA0_PSDREPORT			0x8b4
+#define	TRANSCEIVEA_HSPI_READBACK		0x8b8
+#define	TRANSCEIVEB_HSPI_READBACK		0x8bc
+#define	RFPGA0_XAB_RFINTERFACERB		0x8e0
+#define	RFPGA0_XCD_RFINTERFACERB		0x8e4
+
+#define	RFPGA1_RFMOD				0x900
+
+#define	RFPGA1_TXBLOCK				0x904
+#define	RFPGA1_DEBUGSELECT			0x908
+#define	RFPGA1_TXINFO				0x90c
+
+#define	RCCK0_SYSTEM				0xa00
+
+#define	RCCK0_AFESETTING			0xa04
+#define	RCCK0_CCA				0xa08
+
+#define	RCCK0_RXAGC1				0xa0c
+#define	RCCK0_RXAGC2				0xa10
+
+#define	RCCK0_RXHP				0xa14
+
+#define	RCCK0_DSPPARAMETER1			0xa18
+#define	RCCK0_DSPPARAMETER2			0xa1c
+
+#define	RCCK0_TXFILTER1				0xa20
+#define	RCCK0_TXFILTER2				0xa24
+#define	RCCK0_DEBUGPORT				0xa28
+#define	RCCK0_FALSEALARMREPORT			0xa2c
+#define	RCCK0_TRSSIREPORT			0xa50
+#define	RCCK0_RXREPORT				0xa54
+#define	RCCK0_FACOUNTERLOWER			0xa5c
+#define	RCCK0_FACOUNTERUPPER			0xa58
+
+#define	ROFDM0_LSTF				0xc00
+
+#define	ROFDM0_TRXPATHENABLE			0xc04
+#define	ROFDM0_TRMUXPAR				0xc08
+#define	ROFDM0_TRSWISOLATION			0xc0c
+
+#define	ROFDM0_XARXAFE				0xc10
+#define	ROFDM0_XARXIQIMBALANCE			0xc14
+#define	ROFDM0_XBRXAFE				0xc18
+#define	ROFDM0_XBRXIQIMBALANCE			0xc1c
+#define	ROFDM0_XCRXAFE				0xc20
+#define	ROFDM0_XCRXIQIMBANLANCE			0xc24
+#define	ROFDM0_XDRXAFE				0xc28
+#define	ROFDM0_XDRXIQIMBALANCE			0xc2c
+
+#define	ROFDM0_RXDETECTOR1			0xc30
+#define	ROFDM0_RXDETECTOR2			0xc34
+#define	ROFDM0_RXDETECTOR3			0xc38
+#define	ROFDM0_RXDETECTOR4			0xc3c
+
+#define	ROFDM0_RXDSP				0xc40
+#define	ROFDM0_CFOANDDAGC			0xc44
+#define	ROFDM0_CCADROPTHRESHOLD			0xc48
+#define	ROFDM0_ECCATHRESHOLD			0xc4c
+
+#define	ROFDM0_XAAGCCORE1			0xc50
+#define	ROFDM0_XAAGCCORE2			0xc54
+#define	ROFDM0_XBAGCCORE1			0xc58
+#define	ROFDM0_XBAGCCORE2			0xc5c
+#define	ROFDM0_XCAGCCORE1			0xc60
+#define	ROFDM0_XCAGCCORE2			0xc64
+#define	ROFDM0_XDAGCCORE1			0xc68
+#define	ROFDM0_XDAGCCORE2			0xc6c
+
+#define	ROFDM0_AGCPARAMETER1			0xc70
+#define	ROFDM0_AGCPARAMETER2			0xc74
+#define	ROFDM0_AGCRSSITABLE			0xc78
+#define	ROFDM0_HTSTFAGC				0xc7c
+
+#define	ROFDM0_XATXIQIMBALANCE			0xc80
+#define	ROFDM0_XATXAFE				0xc84
+#define	ROFDM0_XBTXIQIMBALANCE			0xc88
+#define	ROFDM0_XBTXAFE				0xc8c
+#define	ROFDM0_XCTXIQIMBALANCE			0xc90
+#define	ROFDM0_XCTXAFE				0xc94
+#define	ROFDM0_XDTXIQIMBALANCE			0xc98
+#define	ROFDM0_XDTXAFE				0xc9c
+
+#define ROFDM0_RXIQEXTANTA			0xca0
+
+#define	ROFDM0_RXHPPARAMETER			0xce0
+#define	ROFDM0_TXPSEUDONOISEWGT			0xce4
+#define	ROFDM0_FRAMESYNC			0xcf0
+#define	ROFDM0_DFSREPORT			0xcf4
+#define	ROFDM0_TXCOEFF1				0xca4
+#define	ROFDM0_TXCOEFF2				0xca8
+#define	ROFDM0_TXCOEFF3				0xcac
+#define	ROFDM0_TXCOEFF4				0xcb0
+#define	ROFDM0_TXCOEFF5				0xcb4
+#define	ROFDM0_TXCOEFF6				0xcb8
+
+#define	ROFDM1_LSTF				0xd00
+#define	ROFDM1_TRXPATHENABLE			0xd04
+
+#define	ROFDM1_CF0				0xd08
+#define	ROFDM1_CSI1				0xd10
+#define	ROFDM1_SBD				0xd14
+#define	ROFDM1_CSI2				0xd18
+#define	ROFDM1_CFOTRACKING			0xd2c
+#define	ROFDM1_TRXMESAURE1			0xd34
+#define	ROFDM1_INTFDET				0xd3c
+#define	ROFDM1_PSEUDONOISESTATEAB		0xd50
+#define	ROFDM1_PSEUDONOISESTATECD		0xd54
+#define	ROFDM1_RXPSEUDONOISEWGT			0xd58
+
+#define	ROFDM_PHYCOUNTER1			0xda0
+#define	ROFDM_PHYCOUNTER2			0xda4
+#define	ROFDM_PHYCOUNTER3			0xda8
+
+#define	ROFDM_SHORTCFOAB			0xdac
+#define	ROFDM_SHORTCFOCD			0xdb0
+#define	ROFDM_LONGCFOAB				0xdb4
+#define	ROFDM_LONGCFOCD				0xdb8
+#define	ROFDM_TAILCF0AB				0xdbc
+#define	ROFDM_TAILCF0CD				0xdc0
+#define	ROFDM_PWMEASURE1			0xdc4
+#define	ROFDM_PWMEASURE2			0xdc8
+#define	ROFDM_BWREPORT				0xdcc
+#define	ROFDM_AGCREPORT				0xdd0
+#define	ROFDM_RXSNR				0xdd4
+#define	ROFDM_RXEVMCSI				0xdd8
+#define	ROFDM_SIGREPORT				0xddc
+
+#define	RTXAGC_A_RATE18_06			0xe00
+#define	RTXAGC_A_RATE54_24			0xe04
+#define	RTXAGC_A_CCK1_MCS32			0xe08
+#define	RTXAGC_A_MCS03_MCS00			0xe10
+#define	RTXAGC_A_MCS07_MCS04			0xe14
+#define	RTXAGC_A_MCS11_MCS08			0xe18
+#define	RTXAGC_A_MCS15_MCS12			0xe1c
+
+#define	RTXAGC_B_RATE18_06			0x830
+#define	RTXAGC_B_RATE54_24			0x834
+#define	RTXAGC_B_CCK1_55_MCS32			0x838
+#define	RTXAGC_B_MCS03_MCS00			0x83c
+#define	RTXAGC_B_MCS07_MCS04			0x848
+#define	RTXAGC_B_MCS11_MCS08			0x84c
+#define	RTXAGC_B_MCS15_MCS12			0x868
+#define	RTXAGC_B_CCK11_A_CCK2_11		0x86c
+
+#define	RZEBRA1_HSSIENABLE			0x0
+#define	RZEBRA1_TRXENABLE1			0x1
+#define	RZEBRA1_TRXENABLE2			0x2
+#define	RZEBRA1_AGC				0x4
+#define	RZEBRA1_CHARGEPUMP			0x5
+#define	RZEBRA1_CHANNEL				0x7
+
+#define	RZEBRA1_TXGAIN				0x8
+#define	RZEBRA1_TXLPF				0x9
+#define	RZEBRA1_RXLPF				0xb
+#define	RZEBRA1_RXHPFCORNER			0xc
+
+#define	RGLOBALCTRL				0
+#define	RRTL8256_TXLPF				19
+#define	RRTL8256_RXLPF				11
+#define	RRTL8258_TXLPF				0x11
+#define	RRTL8258_RXLPF				0x13
+#define	RRTL8258_RSSILPF			0xa
+
+#define	RF_AC					0x00
+
+#define	RF_IQADJ_G1				0x01
+#define	RF_IQADJ_G2				0x02
+#define	RF_POW_TRSW				0x05
+
+#define	RF_GAIN_RX				0x06
+#define	RF_GAIN_TX				0x07
+
+#define	RF_TXM_IDAC				0x08
+#define	RF_BS_IQGEN				0x0F
+
+#define	RF_MODE1				0x10
+#define	RF_MODE2				0x11
+
+#define	RF_RX_AGC_HP				0x12
+#define	RF_TX_AGC				0x13
+#define	RF_BIAS					0x14
+#define	RF_IPA					0x15
+#define	RF_POW_ABILITY				0x17
+#define	RF_MODE_AG				0x18
+#define	RRFCHANNEL				0x18
+#define	RF_CHNLBW				0x18
+#define	RF_TOP					0x19
+
+#define	RF_RX_G1				0x1A
+#define	RF_RX_G2				0x1B
+
+#define	RF_RX_BB2				0x1C
+#define	RF_RX_BB1				0x1D
+
+#define	RF_RCK1					0x1E
+#define	RF_RCK2					0x1F
+
+#define	RF_TX_G1				0x20
+#define	RF_TX_G2				0x21
+#define	RF_TX_G3				0x22
+
+#define	RF_TX_BB1				0x23
+#define	RF_T_METER				0x24
+
+#define	RF_SYN_G1				0x25
+#define	RF_SYN_G2				0x26
+#define	RF_SYN_G3				0x27
+#define	RF_SYN_G4				0x28
+#define	RF_SYN_G5				0x29
+#define	RF_SYN_G6				0x2A
+#define	RF_SYN_G7				0x2B
+#define	RF_SYN_G8				0x2C
+
+#define	RF_RCK_OS				0x30
+#define	RF_TXPA_G1				0x31
+#define	RF_TXPA_G2				0x32
+#define	RF_TXPA_G3				0x33
+
+#define	BBBRESETB				0x100
+#define	BGLOBALRESETB				0x200
+#define	BOFDMTXSTART				0x4
+#define	BCCKTXSTART				0x8
+#define	BCRC32DEBUG				0x100
+#define	BPMACLOOPBACK				0x10
+#define	BTXLSIG					0xffffff
+#define	BOFDMTXRATE				0xf
+#define	BOFDMTXRESERVED				0x10
+#define	BOFDMTXLENGTH				0x1ffe0
+#define	BOFDMTXPARITY				0x20000
+#define	BTXHTSIG1				0xffffff
+#define	BTXHTMCSRATE				0x7f
+#define	BTXHTBW					0x80
+#define	BTXHTLENGTH				0xffff00
+#define	BTXHTSIG2				0xffffff
+#define	BTXHTSMOOTHING				0x1
+#define	BTXHTSOUNDING				0x2
+#define	BTXHTRESERVED				0x4
+#define	BTXHTAGGREATION				0x8
+#define	BTXHTSTBC				0x30
+#define	BTXHTADVANCECODING			0x40
+#define	BTXHTSHORTGI				0x80
+#define	BTXHTNUMBERHT_LTF			0x300
+#define	BTXHTCRC8				0x3fc00
+#define	BCOUNTERRESET				0x10000
+#define	BNUMOFOFDMTX				0xffff
+#define	BNUMOFCCKTX				0xffff0000
+#define	BTXIDLEINTERVAL				0xffff
+#define	BOFDMSERVICE				0xffff0000
+#define	BTXMACHEADER				0xffffffff
+#define	BTXDATAINIT				0xff
+#define	BTXHTMODE				0x100
+#define	BTXDATATYPE				0x30000
+#define	BTXRANDOMSEED				0xffffffff
+#define	BCCKTXPREAMBLE				0x1
+#define	BCCKTXSFD				0xffff0000
+#define	BCCKTXSIG				0xff
+#define	BCCKTXSERVICE				0xff00
+#define	BCCKLENGTHEXT				0x8000
+#define	BCCKTXLENGHT				0xffff0000
+#define	BCCKTXCRC16				0xffff
+#define	BCCKTXSTATUS				0x1
+#define	BOFDMTXSTATUS				0x2
+#define IS_BB_REG_OFFSET_92S(_Offset)	\
+	((_Offset >= 0x800) && (_Offset <= 0xfff))
+
+#define	BRFMOD					0x1
+#define	BJAPANMODE				0x2
+#define	BCCKTXSC				0x30
+#define	BCCKEN					0x1000000
+#define	BOFDMEN					0x2000000
+
+#define	BOFDMRXADCPHASE				0x10000
+#define	BOFDMTXDACPHASE				0x40000
+#define	BXATXAGC				0x3f
+
+#define	BXBTXAGC				0xf00
+#define	BXCTXAGC				0xf000
+#define	BXDTXAGC				0xf0000
+
+#define	BPASTART				0xf0000000
+#define	BTRSTART				0x00f00000
+#define	BRFSTART				0x0000f000
+#define	BBBSTART				0x000000f0
+#define	BBBCCKSTART				0x0000000f
+#define	BPAEND					0xf
+#define	BTREND					0x0f000000
+#define	BRFEND					0x000f0000
+#define	BCCAMASK				0x000000f0
+#define	BR2RCCAMASK				0x00000f00
+#define	BHSSI_R2TDELAY				0xf8000000
+#define	BHSSI_T2RDELAY				0xf80000
+#define	BCONTXHSSI				0x400
+#define	BIGFROMCCK				0x200
+#define	BAGCADDRESS				0x3f
+#define	BRXHPTX					0x7000
+#define	BRXHP2RX				0x38000
+#define	BRXHPCCKINI				0xc0000
+#define	BAGCTXCODE				0xc00000
+#define	BAGCRXCODE				0x300000
+
+#define	B3WIREDATALENGTH			0x800
+#define	B3WIREADDREAALENGTH			0x400
+
+#define	B3WIRERFPOWERDOWN			0x1
+#define	B5GPAPEPOLARITY				0x40000000
+#define	B2GPAPEPOLARITY				0x80000000
+#define	BRFSW_TXDEFAULTANT			0x3
+#define	BRFSW_TXOPTIONANT			0x30
+#define	BRFSW_RXDEFAULTANT			0x300
+#define	BRFSW_RXOPTIONANT			0x3000
+#define	BRFSI_3WIREDATA				0x1
+#define	BRFSI_3WIRECLOCK			0x2
+#define	BRFSI_3WIRELOAD				0x4
+#define	BRFSI_3WIRERW				0x8
+#define	BRFSI_3WIRE				0xf
+
+#define	BRFSI_RFENV				0x10
+
+#define	BRFSI_TRSW				0x20
+#define	BRFSI_TRSWB				0x40
+#define	BRFSI_ANTSW				0x100
+#define	BRFSI_ANTSWB				0x200
+#define	BRFSI_PAPE				0x400
+#define	BRFSI_PAPE5G				0x800
+#define	BBANDSELECT				0x1
+#define	BHTSIG2_GI				0x80
+#define	BHTSIG2_SMOOTHING			0x01
+#define	BHTSIG2_SOUNDING			0x02
+#define	BHTSIG2_AGGREATON			0x08
+#define	BHTSIG2_STBC				0x30
+#define	BHTSIG2_ADVCODING			0x40
+#define	BHTSIG2_NUMOFHTLTF			0x300
+#define	BHTSIG2_CRC8				0x3fc
+#define	BHTSIG1_MCS				0x7f
+#define	BHTSIG1_BANDWIDTH			0x80
+#define	BHTSIG1_HTLENGTH			0xffff
+#define	BLSIG_RATE				0xf
+#define	BLSIG_RESERVED				0x10
+#define	BLSIG_LENGTH				0x1fffe
+#define	BLSIG_PARITY				0x20
+#define	BCCKRXPHASE				0x4
+
+#define	BLSSIREADADDRESS			0x7f800000
+#define	BLSSIREADEDGE				0x80000000
+
+#define	BLSSIREADBACKDATA			0xfffff
+
+#define	BLSSIREADOKFLAG				0x1000
+#define	BCCKSAMPLERATE				0x8
+#define	BREGULATOR0STANDBY			0x1
+#define	BREGULATORPLLSTANDBY			0x2
+#define	BREGULATOR1STANDBY			0x4
+#define	BPLLPOWERUP				0x8
+#define	BDPLLPOWERUP				0x10
+#define	BDA10POWERUP				0x20
+#define	BAD7POWERUP				0x200
+#define	BDA6POWERUP				0x2000
+#define	BXTALPOWERUP				0x4000
+#define	B40MDCLKPOWERUP				0x8000
+#define	BDA6DEBUGMODE				0x20000
+#define	BDA6SWING				0x380000
+
+#define	BADCLKPHASE				0x4000000
+#define	B80MCLKDELAY				0x18000000
+#define	BAFEWATCHDOGENABLE			0x20000000
+
+#define	BXTALCAP01				0xc0000000
+#define	BXTALCAP23				0x3
+#define	BXTALCAP92X				0x0f000000
+#define BXTALCAP				0x0f000000
+
+#define	BINTDIFCLKENABLE			0x400
+#define	BEXTSIGCLKENABLE			0x800
+#define	BBANDGAP_MBIAS_POWERUP			0x10000
+#define	BAD11SH_GAIN				0xc0000
+#define	BAD11NPUT_RANGE				0x700000
+#define	BAD110P_CURRENT				0x3800000
+#define	BLPATH_LOOPBACK				0x4000000
+#define	BQPATH_LOOPBACK				0x8000000
+#define	BAFE_LOOPBACK				0x10000000
+#define	BDA10_SWING				0x7e0
+#define	BDA10_REVERSE				0x800
+#define	BDA_CLK_SOURCE				0x1000
+#define	BDA7INPUT_RANGE				0x6000
+#define	BDA7_GAIN				0x38000
+#define	BDA7OUTPUT_CM_MODE			0x40000
+#define	BDA7INPUT_CM_MODE			0x380000
+#define	BDA7CURRENT				0xc00000
+#define	BREGULATOR_ADJUST			0x7000000
+#define	BAD11POWERUP_ATTX			0x1
+#define	BDA10PS_ATTX				0x10
+#define	BAD11POWERUP_ATRX			0x100
+#define	BDA10PS_ATRX				0x1000
+#define	BCCKRX_AGC_FORMAT			0x200
+#define	BPSDFFT_SAMPLE_POINT			0xc000
+#define	BPSD_AVERAGE_NUM			0x3000
+#define	BIQPATH_CONTROL				0xc00
+#define	BPSD_FREQ				0x3ff
+#define	BPSD_ANTENNA_PATH			0x30
+#define	BPSD_IQ_SWITCH				0x40
+#define	BPSD_RX_TRIGGER				0x400000
+#define	BPSD_TX_TRIGGER				0x80000000
+#define	BPSD_SINE_TONE_SCALE			0x7f000000
+#define	BPSD_REPORT				0xffff
+
+#define	BOFDM_TXSC				0x30000000
+#define	BCCK_TXON				0x1
+#define	BOFDM_TXON				0x2
+#define	BDEBUG_PAGE				0xfff
+#define	BDEBUG_ITEM				0xff
+#define	BANTL					0x10
+#define	BANT_NONHT				0x100
+#define	BANT_HT1				0x1000
+#define	BANT_HT2				0x10000
+#define	BANT_HT1S1				0x100000
+#define	BANT_NONHTS1				0x1000000
+
+#define	BCCK_BBMODE				0x3
+#define	BCCK_TXPOWERSAVING			0x80
+#define	BCCK_RXPOWERSAVING			0x40
+
+#define	BCCK_SIDEBAND				0x10
+
+#define	BCCK_SCRAMBLE				0x8
+#define	BCCK_ANTDIVERSITY			0x8000
+#define	BCCK_CARRIER_RECOVERY			0x4000
+#define	BCCK_TXRATE				0x3000
+#define	BCCK_DCCANCEL				0x0800
+#define	BCCK_ISICANCEL				0x0400
+#define	BCCK_MATCH_FILTER			0x0200
+#define	BCCK_EQUALIZER				0x0100
+#define	BCCK_PREAMBLE_DETECT			0x800000
+#define	BCCK_FAST_FALSECCAi			0x400000
+#define	BCCK_CH_ESTSTARTi			0x300000
+#define	BCCK_CCA_COUNTi				0x080000
+#define	BCCK_CS_LIM				0x070000
+#define	BCCK_BIST_MODEi				0x80000000
+#define	BCCK_CCAMASK				0x40000000
+#define	BCCK_TX_DAC_PHASE			0x4
+#define	BCCK_RX_ADC_PHASE			0x20000000
+#define	BCCKR_CP_MODE				0x0100
+#define	BCCK_TXDC_OFFSET			0xf0
+#define	BCCK_RXDC_OFFSET			0xf
+#define	BCCK_CCA_MODE				0xc000
+#define	BCCK_FALSECS_LIM			0x3f00
+#define	BCCK_CS_RATIO				0xc00000
+#define	BCCK_CORGBIT_SEL			0x300000
+#define	BCCK_PD_LIM				0x0f0000
+#define	BCCK_NEWCCA				0x80000000
+#define	BCCK_RXHP_OF_IG				0x8000
+#define	BCCK_RXIG				0x7f00
+#define	BCCK_LNA_POLARITY			0x800000
+#define	BCCK_RX1ST_BAIN				0x7f0000
+#define	BCCK_RF_EXTEND				0x20000000
+#define	BCCK_RXAGC_SATLEVEL			0x1f000000
+#define	BCCK_RXAGC_SATCOUNT			0xe0
+#define	bCCKRxRFSettle				0x1f
+#define	BCCK_FIXED_RXAGC			0x8000
+#define	BCCK_ANTENNA_POLARITY			0x2000
+#define	BCCK_TXFILTER_TYPE			0x0c00
+#define	BCCK_RXAGC_REPORTTYPE			0x0300
+#define	BCCK_RXDAGC_EN				0x80000000
+#define	BCCK_RXDAGC_PERIOD			0x20000000
+#define	BCCK_RXDAGC_SATLEVEL			0x1f000000
+#define	BCCK_TIMING_RECOVERY			0x800000
+#define	BCCK_TXC0				0x3f0000
+#define	BCCK_TXC1				0x3f000000
+#define	BCCK_TXC2				0x3f
+#define	BCCK_TXC3				0x3f00
+#define	BCCK_TXC4				0x3f0000
+#define	BCCK_TXC5				0x3f000000
+#define	BCCK_TXC6				0x3f
+#define	BCCK_TXC7				0x3f00
+#define	BCCK_DEBUGPORT				0xff0000
+#define	BCCK_DAC_DEBUG				0x0f000000
+#define	BCCK_FALSEALARM_ENABLE			0x8000
+#define	BCCK_FALSEALARM_READ			0x4000
+#define	BCCK_TRSSI				0x7f
+#define	BCCK_RXAGC_REPORT			0xfe
+#define	BCCK_RXREPORT_ANTSEL			0x80000000
+#define	BCCK_RXREPORT_MFOFF			0x40000000
+#define	BCCK_RXREPORT_SQLOSS			0x20000000
+#define	BCCK_RXREPORT_PKTLOSS			0x10000000
+#define	BCCK_RXREPORT_LOCKEDBIT			0x08000000
+#define	BCCK_RXREPORT_RATEERROR			0x04000000
+#define	BCCK_RXREPORT_RXRATE			0x03000000
+#define	BCCK_RXFA_COUNTER_LOWER			0xff
+#define	BCCK_RXFA_COUNTER_UPPER			0xff000000
+#define	BCCK_RXHPAGC_START			0xe000
+#define	BCCK_RXHPAGC_FINAL			0x1c00
+#define	BCCK_RXFALSEALARM_ENABLE		0x8000
+#define	BCCK_FACOUNTER_FREEZE			0x4000
+#define	BCCK_TXPATH_SEL				0x10000000
+#define	BCCK_DEFAULT_RXPATH			0xc000000
+#define	BCCK_OPTION_RXPATH			0x3000000
+
+#define	BNUM_OFSTF				0x3
+#define	BSHIFT_L				0xc0
+#define	BGI_TH					0xc
+#define	BRXPATH_A				0x1
+#define	BRXPATH_B				0x2
+#define	BRXPATH_C				0x4
+#define	BRXPATH_D				0x8
+#define	BTXPATH_A				0x1
+#define	BTXPATH_B				0x2
+#define	BTXPATH_C				0x4
+#define	BTXPATH_D				0x8
+#define	BTRSSI_FREQ				0x200
+#define	BADC_BACKOFF				0x3000
+#define	BDFIR_BACKOFF				0xc000
+#define	BTRSSI_LATCH_PHASE			0x10000
+#define	BRX_LDC_OFFSET				0xff
+#define	BRX_QDC_OFFSET				0xff00
+#define	BRX_DFIR_MODE				0x1800000
+#define	BRX_DCNF_TYPE				0xe000000
+#define	BRXIQIMB_A				0x3ff
+#define	BRXIQIMB_B				0xfc00
+#define	BRXIQIMB_C				0x3f0000
+#define	BRXIQIMB_D				0xffc00000
+#define	BDC_DC_NOTCH				0x60000
+#define	BRXNB_NOTCH				0x1f000000
+#define	BPD_TH					0xf
+#define	BPD_TH_OPT2				0xc000
+#define	BPWED_TH				0x700
+#define	BIFMF_WIN_L				0x800
+#define	BPD_OPTION				0x1000
+#define	BMF_WIN_L				0xe000
+#define	BBW_SEARCH_L				0x30000
+#define	BWIN_ENH_L				0xc0000
+#define	BBW_TH					0x700000
+#define	BED_TH2					0x3800000
+#define	BBW_OPTION				0x4000000
+#define	BRADIO_TH				0x18000000
+#define	BWINDOW_L				0xe0000000
+#define	BSBD_OPTION				0x1
+#define	BFRAME_TH				0x1c
+#define	BFS_OPTION				0x60
+#define	BDC_SLOPE_CHECK				0x80
+#define	BFGUARD_COUNTER_DC_L			0xe00
+#define	BFRAME_WEIGHT_SHORT			0x7000
+#define	BSUB_TUNE				0xe00000
+#define	BFRAME_DC_LENGTH			0xe000000
+#define	BSBD_START_OFFSET			0x30000000
+#define	BFRAME_TH_2				0x7
+#define	BFRAME_GI2_TH				0x38
+#define	BGI2_SYNC_EN				0x40
+#define	BSARCH_SHORT_EARLY			0x300
+#define	BSARCH_SHORT_LATE			0xc00
+#define	BSARCH_GI2_LATE				0x70000
+#define	BCFOANTSUM				0x1
+#define	BCFOACC					0x2
+#define	BCFOSTARTOFFSET				0xc
+#define	BCFOLOOPBACK				0x70
+#define	BCFOSUMWEIGHT				0x80
+#define	BDAGCENABLE				0x10000
+#define	BTXIQIMB_A				0x3ff
+#define	BTXIQIMB_b				0xfc00
+#define	BTXIQIMB_C				0x3f0000
+#define	BTXIQIMB_D				0xffc00000
+#define	BTXIDCOFFSET				0xff
+#define	BTXIQDCOFFSET				0xff00
+#define	BTXDFIRMODE				0x10000
+#define	BTXPESUDO_NOISEON			0x4000000
+#define	BTXPESUDO_NOISE_A			0xff
+#define	BTXPESUDO_NOISE_B			0xff00
+#define	BTXPESUDO_NOISE_C			0xff0000
+#define	BTXPESUDO_NOISE_D			0xff000000
+#define	BCCA_DROPOPTION				0x20000
+#define	BCCA_DROPTHRES				0xfff00000
+#define	BEDCCA_H				0xf
+#define	BEDCCA_L				0xf0
+#define	BLAMBDA_ED				0x300
+#define	BRX_INITIALGAIN				0x7f
+#define	BRX_ANTDIV_EN				0x80
+#define	BRX_AGC_ADDRESS_FOR_LNA			0x7f00
+#define	BRX_HIGHPOWER_FLOW			0x8000
+#define	BRX_AGC_FREEZE_THRES			0xc0000
+#define	BRX_FREEZESTEP_AGC1			0x300000
+#define	BRX_FREEZESTEP_AGC2			0xc00000
+#define	BRX_FREEZESTEP_AGC3			0x3000000
+#define	BRX_FREEZESTEP_AGC0			0xc000000
+#define	BRXRSSI_CMP_EN				0x10000000
+#define	BRXQUICK_AGCEN				0x20000000
+#define	BRXAGC_FREEZE_THRES_MODE		0x40000000
+#define	BRX_OVERFLOW_CHECKTYPE			0x80000000
+#define	BRX_AGCSHIFT				0x7f
+#define	BTRSW_TRI_ONLY				0x80
+#define	BPOWER_THRES				0x300
+#define	BRXAGC_EN				0x1
+#define	BRXAGC_TOGETHER_EN			0x2
+#define	BRXAGC_MIN				0x4
+#define	BRXHP_INI				0x7
+#define	BRXHP_TRLNA				0x70
+#define	BRXHP_RSSI				0x700
+#define	BRXHP_BBP1				0x7000
+#define	BRXHP_BBP2				0x70000
+#define	BRXHP_BBP3				0x700000
+#define	BRSSI_H					0x7f0000
+#define	BRSSI_GEN				0x7f000000
+#define	BRXSETTLE_TRSW				0x7
+#define	BRXSETTLE_LNA				0x38
+#define	BRXSETTLE_RSSI				0x1c0
+#define	BRXSETTLE_BBP				0xe00
+#define	BRXSETTLE_RXHP				0x7000
+#define	BRXSETTLE_ANTSW_RSSI			0x38000
+#define	BRXSETTLE_ANTSW				0xc0000
+#define	BRXPROCESS_TIME_DAGC			0x300000
+#define	BRXSETTLE_HSSI				0x400000
+#define	BRXPROCESS_TIME_BBPPW			0x800000
+#define	BRXANTENNA_POWER_SHIFT			0x3000000
+#define	BRSSI_TABLE_SELECT			0xc000000
+#define	BRXHP_FINAL				0x7000000
+#define	BRXHPSETTLE_BBP				0x7
+#define	BRXHTSETTLE_HSSI			0x8
+#define	BRXHTSETTLE_RXHP			0x70
+#define	BRXHTSETTLE_BBPPW			0x80
+#define	BRXHTSETTLE_IDLE			0x300
+#define	BRXHTSETTLE_RESERVED			0x1c00
+#define	BRXHT_RXHP_EN				0x8000
+#define	BRXAGC_FREEZE_THRES			0x30000
+#define	BRXAGC_TOGETHEREN			0x40000
+#define	BRXHTAGC_MIN				0x80000
+#define	BRXHTAGC_EN				0x100000
+#define	BRXHTDAGC_EN				0x200000
+#define	BRXHT_RXHP_BBP				0x1c00000
+#define	BRXHT_RXHP_FINAL			0xe0000000
+#define	BRXPW_RADIO_TH				0x3
+#define	BRXPW_RADIO_EN				0x4
+#define	BRXMF_HOLD				0x3800
+#define	BRXPD_DELAY_TH1				0x38
+#define	BRXPD_DELAY_TH2				0x1c0
+#define	BRXPD_DC_COUNT_MAX			0x600
+#define	BRXPD_DELAY_TH				0x8000
+#define	BRXPROCESS_DELAY			0xf0000
+#define	BRXSEARCHRANGE_GI2_EARLY		0x700000
+#define	BRXFRAME_FUARD_COUNTER_L		0x3800000
+#define	BRXSGI_GUARD_L				0xc000000
+#define	BRXSGI_SEARCH_L				0x30000000
+#define	BRXSGI_TH				0xc0000000
+#define	BDFSCNT0				0xff
+#define	BDFSCNT1				0xff00
+#define	BDFSFLAG				0xf0000
+#define	BMF_WEIGHT_SUM				0x300000
+#define	BMINIDX_TH				0x7f000000
+#define	BDAFORMAT				0x40000
+#define	BTXCH_EMU_ENABLE			0x01000000
+#define	BTRSW_ISOLATION_A			0x7f
+#define	BTRSW_ISOLATION_B			0x7f00
+#define	BTRSW_ISOLATION_C			0x7f0000
+#define	BTRSW_ISOLATION_D			0x7f000000
+#define	BEXT_LNA_GAIN				0x7c00
+
+#define	BSTBC_EN				0x4
+#define	BANTENNA_MAPPING			0x10
+#define	BNSS					0x20
+#define	BCFO_ANTSUM_ID				0x200
+#define	BPHY_COUNTER_RESET			0x8000000
+#define	BCFO_REPORT_GET				0x4000000
+#define	BOFDM_CONTINUE_TX			0x10000000
+#define	BOFDM_SINGLE_CARRIER			0x20000000
+#define	BOFDM_SINGLE_TONE			0x40000000
+#define	BHT_DETECT				0x100
+#define	BCFOEN					0x10000
+#define	BCFOVALUE				0xfff00000
+#define	BSIGTONE_RE				0x3f
+#define	BSIGTONE_IM				0x7f00
+#define	BCOUNTER_CCA				0xffff
+#define	BCOUNTER_PARITYFAIL			0xffff0000
+#define	BCOUNTER_RATEILLEGAL			0xffff
+#define	BCOUNTER_CRC8FAIL			0xffff0000
+#define	BCOUNTER_MCSNOSUPPORT			0xffff
+#define	BCOUNTER_FASTSYNC			0xffff
+#define	BSHORTCFO				0xfff
+#define	BSHORTCFOT_LENGTH			12
+#define	BSHORTCFOF_LENGTH			11
+#define	BLONGCFO				0x7ff
+#define	BLONGCFOT_LENGTH			11
+#define	BLONGCFOF_LENGTH			11
+#define	BTAILCFO				0x1fff
+#define	BTAILCFOT_LENGTH			13
+#define	BTAILCFOF_LENGTH			12
+#define	BNOISE_EN_PWDB				0xffff
+#define	BCC_POWER_DB				0xffff0000
+#define	BMOISE_PWDB				0xffff
+#define	BPOWERMEAST_LENGTH			10
+#define	BPOWERMEASF_LENGTH			3
+#define	BRX_HT_BW				0x1
+#define	BRXSC					0x6
+#define	BRX_HT					0x8
+#define	BNB_INTF_DET_ON				0x1
+#define	BINTF_WIN_LEN_CFG			0x30
+#define	BNB_INTF_TH_CFG				0x1c0
+#define	BRFGAIN					0x3f
+#define	BTABLESEL				0x40
+#define	BTRSW					0x80
+#define	BRXSNR_A				0xff
+#define	BRXSNR_B				0xff00
+#define	BRXSNR_C				0xff0000
+#define	BRXSNR_D				0xff000000
+#define	BSNR_EVMT_LENGTH			8
+#define	BSNR_EVMF_LENGTH			1
+#define	BCSI1ST					0xff
+#define	BCSI2ND					0xff00
+#define	BRXEVM1ST				0xff0000
+#define	BRXEVM2ND				0xff000000
+#define	BSIGEVM					0xff
+#define	BPWDB					0xff00
+#define	BSGIEN					0x10000
+
+#define	BSFACTOR_QMA1				0xf
+#define	BSFACTOR_QMA2				0xf0
+#define	BSFACTOR_QMA3				0xf00
+#define	BSFACTOR_QMA4				0xf000
+#define	BSFACTOR_QMA5				0xf0000
+#define	BSFACTOR_QMA6				0xf0000
+#define	BSFACTOR_QMA7				0xf00000
+#define	BSFACTOR_QMA8				0xf000000
+#define	BSFACTOR_QMA9				0xf0000000
+#define	BCSI_SCHEME				0x100000
+
+#define	BNOISE_LVL_TOP_SET			0x3
+#define	BCHSMOOTH				0x4
+#define	BCHSMOOTH_CFG1				0x38
+#define	BCHSMOOTH_CFG2				0x1c0
+#define	BCHSMOOTH_CFG3				0xe00
+#define	BCHSMOOTH_CFG4				0x7000
+#define	BMRCMODE				0x800000
+#define	BTHEVMCFG				0x7000000
+
+#define	BLOOP_FIT_TYPE				0x1
+#define	BUPD_CFO				0x40
+#define	BUPD_CFO_OFFDATA			0x80
+#define	BADV_UPD_CFO				0x100
+#define	BADV_TIME_CTRL				0x800
+#define	BUPD_CLKO				0x1000
+#define	BFC					0x6000
+#define	BTRACKING_MODE				0x8000
+#define	BPHCMP_ENABLE				0x10000
+#define	BUPD_CLKO_LTF				0x20000
+#define	BCOM_CH_CFO				0x40000
+#define	BCSI_ESTI_MODE				0x80000
+#define	BADV_UPD_EQZ				0x100000
+#define	BUCHCFG					0x7000000
+#define	BUPDEQZ					0x8000000
+
+#define	BRX_PESUDO_NOISE_ON			0x20000000
+#define	BRX_PESUDO_NOISE_A			0xff
+#define	BRX_PESUDO_NOISE_B			0xff00
+#define	BRX_PESUDO_NOISE_C			0xff0000
+#define	BRX_PESUDO_NOISE_D			0xff000000
+#define	BRX_PESUDO_NOISESTATE_A			0xffff
+#define	BRX_PESUDO_NOISESTATE_B			0xffff0000
+#define	BRX_PESUDO_NOISESTATE_C			0xffff
+#define	BRX_PESUDO_NOISESTATE_D			0xffff0000
+
+#define	BZEBRA1_HSSIENABLE			0x8
+#define	BZEBRA1_TRXCONTROL			0xc00
+#define	BZEBRA1_TRXGAINSETTING			0x07f
+#define	BZEBRA1_RXCOUNTER			0xc00
+#define	BZEBRA1_TXCHANGEPUMP			0x38
+#define	BZEBRA1_RXCHANGEPUMP			0x7
+#define	BZEBRA1_CHANNEL_NUM			0xf80
+#define	BZEBRA1_TXLPFBW				0x400
+#define	BZEBRA1_RXLPFBW				0x600
+
+#define	BRTL8256REG_MODE_CTRL1			0x100
+#define	BRTL8256REG_MODE_CTRL0			0x40
+#define	BRTL8256REG_TXLPFBW			0x18
+#define	BRTL8256REG_RXLPFBW			0x600
+
+#define	BRTL8258_TXLPFBW			0xc
+#define	BRTL8258_RXLPFBW			0xc00
+#define	BRTL8258_RSSILPFBW			0xc0
+
+#define	BBYTE0					0x1
+#define	BBYTE1					0x2
+#define	BBYTE2					0x4
+#define	BBYTE3					0x8
+#define	BWORD0					0x3
+#define	BWORD1					0xc
+#define	BWORD					0xf
+
+#define	MASKBYTE0				0xff
+#define	MASKBYTE1				0xff00
+#define	MASKBYTE2				0xff0000
+#define	MASKBYTE3				0xff000000
+#define	MASKHWORD				0xffff0000
+#define	MASKLWORD				0x0000ffff
+#define	MASKDWORD				0xffffffff
+#define	MASK12BITS				0xfff
+#define	MASKH4BITS				0xf0000000
+#define MASKOFDM_D				0xffc00000
+#define	MASKCCK					0x3f3f3f3f
+
+#define	MASK4BITS				0x0f
+#define	MASK20BITS				0xfffff
+#define RFREG_OFFSET_MASK			0xfffff
+
+#define	BENABLE					0x1
+#define	BDISABLE				0x0
+
+#define	LEFT_ANTENNA				0x0
+#define	RIGHT_ANTENNA				0x1
+
+#define	TCHECK_TXSTATUS				500
+#define	TUPDATE_RXCOUNTER			100
+
+/* 2 EFUSE_TEST (For RTL8723 partially) */
+#define EFUSE_SEL(x)				(((x) & 0x3) << 8)
+#define EFUSE_SEL_MASK				0x300
+#define EFUSE_WIFI_SEL_0			0x0
+
+/* Enable GPIO[9] as WiFi HW PDn source*/
+#define	WL_HWPDN_EN				BIT(0)
+/* WiFi HW PDn polarity control*/
+#define	WL_HWPDN_SL				BIT(1)
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.c b/drivers/net/wireless/rtlwifi/rtl8723ae/rf.c
new file mode 100644
index 0000000..50dd2fb
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/rf.c
@@ -0,0 +1,505 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+
+void rtl8723ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	switch (bandwidth) {
+	case HT_CHANNEL_WIDTH_20:
+		rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
+					     0xfffff3ff) | 0x0400);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
+			      rtlphy->rfreg_chnlval[0]);
+		break;
+	case HT_CHANNEL_WIDTH_20_40:
+		rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
+					     0xfffff3ff));
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
+			      rtlphy->rfreg_chnlval[0]);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "unknown bandwidth: %#X\n", bandwidth);
+		break;
+	}
+}
+
+void rtl8723ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+					  u8 *ppowerlevel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u32 tx_agc[2] = {0, 0}, tmpval;
+	bool turbo_scanoff = false;
+	u8 idx1, idx2;
+	u8 *ptr;
+
+	if (rtlefuse->eeprom_regulatory != 0)
+		turbo_scanoff = true;
+
+	if (mac->act_scanning == true) {
+		tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
+		tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
+
+		if (turbo_scanoff) {
+			for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+				tx_agc[idx1] = ppowerlevel[idx1] |
+				    (ppowerlevel[idx1] << 8) |
+				    (ppowerlevel[idx1] << 16) |
+				    (ppowerlevel[idx1] << 24);
+			}
+		}
+	} else {
+		for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+			tx_agc[idx1] = ppowerlevel[idx1] |
+				       (ppowerlevel[idx1] << 8) |
+				       (ppowerlevel[idx1] << 16) |
+				       (ppowerlevel[idx1] << 24);
+		}
+
+		if (rtlefuse->eeprom_regulatory == 0) {
+			tmpval = (rtlphy->mcs_offset[0][6]) +
+				(rtlphy->mcs_offset[0][7] << 8);
+			tx_agc[RF90_PATH_A] += tmpval;
+
+			tmpval = (rtlphy->mcs_offset[0][14]) +
+			    (rtlphy->mcs_offset[0][15] << 24);
+			tx_agc[RF90_PATH_B] += tmpval;
+		}
+	}
+
+	for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+		ptr = (u8 *) (&(tx_agc[idx1]));
+		for (idx2 = 0; idx2 < 4; idx2++) {
+			if (*ptr > RF6052_MAX_TX_PWR)
+				*ptr = RF6052_MAX_TX_PWR;
+			ptr++;
+		}
+	}
+
+	tmpval = tx_agc[RF90_PATH_A] & 0xff;
+	rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval);
+
+	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+		"CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
+		RTXAGC_A_CCK1_MCS32);
+
+	tmpval = tx_agc[RF90_PATH_A] >> 8;
+
+	tmpval = tmpval & 0xff00ffff;
+
+	rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
+
+	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+		"CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
+		RTXAGC_B_CCK11_A_CCK2_11);
+
+	tmpval = tx_agc[RF90_PATH_B] >> 24;
+	rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval);
+
+	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+		"CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
+		RTXAGC_B_CCK11_A_CCK2_11);
+
+	tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;
+	rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);
+
+	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+		"CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
+		RTXAGC_B_CCK1_55_MCS32);
+}
+
+static void rtl8723ae_phy_get_power_base(struct ieee80211_hw *hw,
+					 u8 *ppowerlevel, u8 channel,
+					 u32 *ofdmbase, u32 *mcsbase)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u32 powerBase0, powerBase1;
+	u8 legacy_pwrdiff, ht20_pwrdiff;
+	u8 i, powerlevel[2];
+
+	for (i = 0; i < 2; i++) {
+		powerlevel[i] = ppowerlevel[i];
+		legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1];
+		powerBase0 = powerlevel[i] + legacy_pwrdiff;
+
+		powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) |
+		    (powerBase0 << 8) | powerBase0;
+		*(ofdmbase + i) = powerBase0;
+		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+			" [OFDM power base index rf(%c) = 0x%x]\n",
+			((i == 0) ? 'A' : 'B'), *(ofdmbase + i));
+	}
+
+	for (i = 0; i < 2; i++) {
+		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
+			ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1];
+			powerlevel[i] += ht20_pwrdiff;
+		}
+		powerBase1 = powerlevel[i];
+		powerBase1 = (powerBase1 << 24) |
+		    (powerBase1 << 16) | (powerBase1 << 8) | powerBase1;
+
+		*(mcsbase + i) = powerBase1;
+
+		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+			" [MCS power base index rf(%c) = 0x%x]\n",
+			((i == 0) ? 'A' : 'B'), *(mcsbase + i));
+	}
+}
+
+static void rtl8723ae_get_txpwr_val_by_reg(struct ieee80211_hw *hw,
+					   u8 channel, u8 index,
+					   u32 *powerBase0,
+					   u32 *powerBase1,
+					   u32 *p_outwriteval)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 i, chnlgroup = 0, pwr_diff_limit[4];
+	u32 writeVal, customer_limit, rf;
+
+	for (rf = 0; rf < 2; rf++) {
+		switch (rtlefuse->eeprom_regulatory) {
+		case 0:
+			chnlgroup = 0;
+
+			writeVal = rtlphy->mcs_offset[chnlgroup]
+				   [index + (rf ? 8 : 0)] +
+				   ((index < 2) ? powerBase0[rf] :
+				   powerBase1[rf]);
+
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				"RTK better performance, "
+				"writeVal(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), writeVal);
+			break;
+		case 1:
+			if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
+				writeVal = ((index < 2) ? powerBase0[rf] :
+					    powerBase1[rf]);
+
+				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+					"Realtek regulatory, 40MHz, "
+					"writeVal(%c) = 0x%x\n",
+					((rf == 0) ? 'A' : 'B'), writeVal);
+			} else {
+				if (rtlphy->pwrgroup_cnt == 1)
+					chnlgroup = 0;
+				if (rtlphy->pwrgroup_cnt >= 3) {
+					if (channel <= 3)
+						chnlgroup = 0;
+					else if (channel >= 4 && channel <= 9)
+						chnlgroup = 1;
+					else if (channel > 9)
+						chnlgroup = 2;
+					if (rtlphy->current_chan_bw ==
+					    HT_CHANNEL_WIDTH_20)
+						chnlgroup++;
+					else
+						chnlgroup += 4;
+				}
+
+				writeVal = rtlphy->mcs_offset[chnlgroup]
+				    [index + (rf ? 8 : 0)] + ((index < 2) ?
+							      powerBase0[rf] :
+							      powerBase1[rf]);
+
+				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+					"Realtek regulatory, 20MHz, writeVal(%c) = 0x%x\n",
+					((rf == 0) ? 'A' : 'B'), writeVal);
+			}
+			break;
+		case 2:
+			writeVal =
+			    ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
+
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				"Better regulatory, writeVal(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), writeVal);
+			break;
+		case 3:
+			chnlgroup = 0;
+
+			if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
+				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+					"customer's limit, 40MHz rf(%c) = 0x%x\n",
+					((rf == 0) ? 'A' : 'B'),
+					rtlefuse->pwrgroup_ht40[rf][channel-1]);
+			} else {
+				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+					"customer's limit, 20MHz rf(%c) = 0x%x\n",
+					((rf == 0) ? 'A' : 'B'),
+					rtlefuse->pwrgroup_ht20[rf][channel-1]);
+			}
+			for (i = 0; i < 4; i++) {
+				pwr_diff_limit[i] =
+					(u8) ((rtlphy->mcs_offset
+					[chnlgroup][index + (rf ? 8 : 0)] &
+					(0x7f << (i * 8))) >> (i * 8));
+
+				if (rtlphy->current_chan_bw ==
+				    HT_CHANNEL_WIDTH_20_40) {
+					if (pwr_diff_limit[i] >
+					    rtlefuse->
+					    pwrgroup_ht40[rf][channel - 1])
+						pwr_diff_limit[i] =
+						    rtlefuse->pwrgroup_ht40[rf]
+						    [channel - 1];
+				} else {
+					if (pwr_diff_limit[i] >
+					    rtlefuse->
+					    pwrgroup_ht20[rf][channel - 1])
+						pwr_diff_limit[i] =
+						    rtlefuse->pwrgroup_ht20[rf]
+						    [channel - 1];
+				}
+			}
+
+			customer_limit = (pwr_diff_limit[3] << 24) |
+			    (pwr_diff_limit[2] << 16) |
+			    (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);
+
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				"Customer's limit rf(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), customer_limit);
+
+			writeVal = customer_limit +
+			    ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
+
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				"Customer, writeVal rf(%c)= 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), writeVal);
+			break;
+		default:
+			chnlgroup = 0;
+			writeVal = rtlphy->mcs_offset[chnlgroup][index +
+			    (rf ? 8 : 0)] + ((index < 2) ? powerBase0[rf] :
+			    powerBase1[rf]);
+
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				"RTK better performance, writeVal rf(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), writeVal);
+			break;
+		}
+
+		if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
+			writeVal = writeVal - 0x06060606;
+		else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+			 TXHIGHPWRLEVEL_BT2)
+			writeVal = writeVal - 0x0c0c0c0c;
+		*(p_outwriteval + rf) = writeVal;
+	}
+}
+
+static void _rtl8723ae_write_ofdm_power_reg(struct ieee80211_hw *hw,
+					    u8 index, u32 *pValue)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	u16 regoffset_a[6] = {
+		RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,
+		RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
+		RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
+	};
+	u16 regoffset_b[6] = {
+		RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,
+		RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
+		RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
+	};
+	u8 i, rf, pwr_val[4];
+	u32 writeVal;
+	u16 regoffset;
+
+	for (rf = 0; rf < 2; rf++) {
+		writeVal = pValue[rf];
+		for (i = 0; i < 4; i++) {
+			pwr_val[i] = (u8) ((writeVal & (0x7f <<
+							(i * 8))) >> (i * 8));
+
+			if (pwr_val[i] > RF6052_MAX_TX_PWR)
+				pwr_val[i] = RF6052_MAX_TX_PWR;
+		}
+		writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
+		    (pwr_val[1] << 8) | pwr_val[0];
+
+		if (rf == 0)
+			regoffset = regoffset_a[index];
+		else
+			regoffset = regoffset_b[index];
+		rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal);
+
+		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+			"Set 0x%x = %08x\n", regoffset, writeVal);
+
+		if (((get_rf_type(rtlphy) == RF_2T2R) &&
+		     (regoffset == RTXAGC_A_MCS15_MCS12 ||
+		      regoffset == RTXAGC_B_MCS15_MCS12)) ||
+		    ((get_rf_type(rtlphy) != RF_2T2R) &&
+		     (regoffset == RTXAGC_A_MCS07_MCS04 ||
+		      regoffset == RTXAGC_B_MCS07_MCS04))) {
+
+			writeVal = pwr_val[3];
+			if (regoffset == RTXAGC_A_MCS15_MCS12 ||
+			    regoffset == RTXAGC_A_MCS07_MCS04)
+				regoffset = 0xc90;
+			if (regoffset == RTXAGC_B_MCS15_MCS12 ||
+			    regoffset == RTXAGC_B_MCS07_MCS04)
+				regoffset = 0xc98;
+
+			for (i = 0; i < 3; i++) {
+				writeVal = (writeVal > 6) ? (writeVal - 6) : 0;
+				rtl_write_byte(rtlpriv, (u32) (regoffset + i),
+					       (u8) writeVal);
+			}
+		}
+	}
+}
+
+void rtl8723ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+					   u8 *ppowerlevel, u8 channel)
+{
+	u32 writeVal[2], powerBase0[2], powerBase1[2];
+	u8 index;
+
+	rtl8723ae_phy_get_power_base(hw, ppowerlevel,
+				  channel, &powerBase0[0], &powerBase1[0]);
+
+	for (index = 0; index < 6; index++) {
+		rtl8723ae_get_txpwr_val_by_reg(hw, channel, index,
+					      &powerBase0[0],
+					      &powerBase1[0],
+					      &writeVal[0]);
+
+		_rtl8723ae_write_ofdm_power_reg(hw, index, &writeVal[0]);
+	}
+}
+
+static bool _rtl8723ae_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 u4_regvalue = 0;
+	u8 rfpath;
+	bool rtstatus = true;
+	struct bb_reg_def *pphyreg;
+
+	for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
+
+		pphyreg = &rtlphy->phyreg_def[rfpath];
+
+		switch (rfpath) {
+		case RF90_PATH_A:
+		case RF90_PATH_C:
+			u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
+						    BRFSI_RFENV);
+			break;
+		case RF90_PATH_B:
+		case RF90_PATH_D:
+			u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
+						    BRFSI_RFENV << 16);
+			break;
+		}
+
+		rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
+		udelay(1);
+
+		rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
+		udelay(1);
+
+		rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
+			      B3WIREADDREAALENGTH, 0x0);
+		udelay(1);
+
+		rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
+		udelay(1);
+
+		switch (rfpath) {
+		case RF90_PATH_A:
+			rtstatus = rtl8723ae_phy_config_rf_with_headerfile(hw,
+						(enum radio_path)rfpath);
+			break;
+		case RF90_PATH_B:
+			rtstatus = rtl8723ae_phy_config_rf_with_headerfile(hw,
+						(enum radio_path)rfpath);
+			break;
+		case RF90_PATH_C:
+			break;
+		case RF90_PATH_D:
+			break;
+		}
+		switch (rfpath) {
+		case RF90_PATH_A:
+		case RF90_PATH_C:
+			rtl_set_bbreg(hw, pphyreg->rfintfs,
+				      BRFSI_RFENV, u4_regvalue);
+			break;
+		case RF90_PATH_B:
+		case RF90_PATH_D:
+			rtl_set_bbreg(hw, pphyreg->rfintfs,
+				      BRFSI_RFENV << 16, u4_regvalue);
+			break;
+		}
+		if (rtstatus != true) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+				 "Radio[%d] Fail!!", rfpath);
+			return false;
+		}
+	}
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n");
+	return rtstatus;
+}
+
+bool rtl8723ae_phy_rf6052_config(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	if (rtlphy->rf_type == RF_1T1R)
+		rtlphy->num_total_rfpath = 1;
+	else
+		rtlphy->num_total_rfpath = 2;
+
+	return _rtl8723ae_phy_rf6052_config_parafile(hw);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h b/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h
new file mode 100644
index 0000000..d0f9dd7
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h
@@ -0,0 +1,43 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_RF_H__
+#define __RTL8723E_RF_H__
+
+#define RF6052_MAX_TX_PWR		0x3F
+
+extern void rtl8723ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw,
+					    u8 bandwidth);
+extern void rtl8723ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+					      u8 *ppowerlevel);
+extern void rtl8723ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+					       u8 *ppowerlevel, u8 channel);
+extern bool rtl8723ae_phy_rf6052_config(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c
new file mode 100644
index 0000000..0afdc24
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c
@@ -0,0 +1,387 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+
+#include "../core.h"
+#include "../pci.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+#include "hw.h"
+#include "sw.h"
+#include "trx.h"
+#include "led.h"
+#include "table.h"
+#include "hal_btc.h"
+
+static void rtl8723ae_init_aspm_vars(struct ieee80211_hw *hw)
+{
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+
+	/*close ASPM for AMD defaultly */
+	rtlpci->const_amdpci_aspm = 0;
+
+	/* ASPM PS mode.
+	 * 0 - Disable ASPM,
+	 * 1 - Enable ASPM without Clock Req,
+	 * 2 - Enable ASPM with Clock Req,
+	 * 3 - Alwyas Enable ASPM with Clock Req,
+	 * 4 - Always Enable ASPM without Clock Req.
+	 * set defult to RTL8192CE:3 RTL8192E:2
+	 */
+	rtlpci->const_pci_aspm = 3;
+
+	/*Setting for PCI-E device */
+	rtlpci->const_devicepci_aspm_setting = 0x03;
+
+	/*Setting for PCI-E bridge */
+	rtlpci->const_hostpci_aspm_setting = 0x02;
+
+	/* In Hw/Sw Radio Off situation.
+	 * 0 - Default,
+	 * 1 - From ASPM setting without low Mac Pwr,
+	 * 2 - From ASPM setting with low Mac Pwr,
+	 * 3 - Bus D3
+	 * set default to RTL8192CE:0 RTL8192SE:2
+	 */
+	rtlpci->const_hwsw_rfoff_d3 = 0;
+
+	/* This setting works for those device with
+	 * backdoor ASPM setting such as EPHY setting.
+	 * 0 - Not support ASPM,
+	 * 1 - Support ASPM,
+	 * 2 - According to chipset.
+	 */
+	rtlpci->const_support_pciaspm = 1;
+}
+
+int rtl8723ae_init_sw_vars(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	int err;
+
+	rtl8723ae_bt_reg_init(hw);
+	rtlpriv->dm.dm_initialgain_enable = 1;
+	rtlpriv->dm.dm_flag = 0;
+	rtlpriv->dm.disable_framebursting = 0;
+	rtlpriv->dm.thermalvalue = 0;
+	rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13);
+
+	/* compatible 5G band 88ce just 2.4G band & smsp */
+	rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G;
+	rtlpriv->rtlhal.bandset = BAND_ON_2_4G;
+	rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY;
+
+	rtlpci->receive_config = (RCR_APPFCS |
+				  RCR_APP_MIC |
+				  RCR_APP_ICV |
+				  RCR_APP_PHYST_RXFF |
+				  RCR_HTC_LOC_CTRL |
+				  RCR_AMF |
+				  RCR_ACF |
+				  RCR_ADF |
+				  RCR_AICV |
+				  RCR_AB |
+				  RCR_AM |
+				  RCR_APM |
+				  0);
+
+	rtlpci->irq_mask[0] =
+	    (u32) (PHIMR_ROK |
+		   PHIMR_RDU |
+		   PHIMR_VODOK |
+		   PHIMR_VIDOK |
+		   PHIMR_BEDOK |
+		   PHIMR_BKDOK |
+		   PHIMR_MGNTDOK |
+		   PHIMR_HIGHDOK |
+		   PHIMR_C2HCMD |
+		   PHIMR_HISRE_IND |
+		   PHIMR_TSF_BIT32_TOGGLE |
+		   PHIMR_TXBCNOK |
+		   PHIMR_PSTIMEOUT |
+		   0);
+
+	rtlpci->irq_mask[1] = (u32)(PHIMR_RXFOVW | 0);
+
+	/* for debug level */
+	rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
+	/* for LPS & IPS */
+	rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
+	rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
+	rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+	rtlpriv->psc.reg_fwctrl_lps = 3;
+	rtlpriv->psc.reg_max_lps_awakeintvl = 5;
+	/* for ASPM, you can close aspm through
+	 * set const_support_pciaspm = 0
+	 */
+	rtl8723ae_init_aspm_vars(hw);
+
+	if (rtlpriv->psc.reg_fwctrl_lps == 1)
+		rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE;
+	else if (rtlpriv->psc.reg_fwctrl_lps == 2)
+		rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE;
+	else if (rtlpriv->psc.reg_fwctrl_lps == 3)
+		rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE;
+
+	/* for firmware buf */
+	rtlpriv->rtlhal.pfirmware = vmalloc(0x6000);
+	if (!rtlpriv->rtlhal.pfirmware) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "Can't alloc buffer for fw.\n");
+		return 1;
+	}
+
+	if (IS_VENDOR_8723_A_CUT(rtlhal->version))
+		rtlpriv->cfg->fw_name = "rtlwifi/rtl8723fw.bin";
+	else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
+		rtlpriv->cfg->fw_name = "rtlwifi/rtl8723fw_B.bin";
+
+	rtlpriv->max_fw_size = 0x6000;
+	pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
+	err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
+				      rtlpriv->io.dev, GFP_KERNEL, hw,
+				      rtl_fw_cb);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 "Failed to request firmware!\n");
+		return 1;
+	}
+	return 0;
+}
+
+void rtl8723ae_deinit_sw_vars(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (rtlpriv->rtlhal.pfirmware) {
+		vfree(rtlpriv->rtlhal.pfirmware);
+		rtlpriv->rtlhal.pfirmware = NULL;
+	}
+}
+
+static struct rtl_hal_ops rtl8723ae_hal_ops = {
+	.init_sw_vars = rtl8723ae_init_sw_vars,
+	.deinit_sw_vars = rtl8723ae_deinit_sw_vars,
+	.read_eeprom_info = rtl8723ae_read_eeprom_info,
+	.interrupt_recognized = rtl8723ae_interrupt_recognized,
+	.hw_init = rtl8723ae_hw_init,
+	.hw_disable = rtl8723ae_card_disable,
+	.hw_suspend = rtl8723ae_suspend,
+	.hw_resume = rtl8723ae_resume,
+	.enable_interrupt = rtl8723ae_enable_interrupt,
+	.disable_interrupt = rtl8723ae_disable_interrupt,
+	.set_network_type = rtl8723ae_set_network_type,
+	.set_chk_bssid = rtl8723ae_set_check_bssid,
+	.set_qos = rtl8723ae_set_qos,
+	.set_bcn_reg = rtl8723ae_set_beacon_related_registers,
+	.set_bcn_intv = rtl8723ae_set_beacon_interval,
+	.update_interrupt_mask = rtl8723ae_update_interrupt_mask,
+	.get_hw_reg = rtl8723ae_get_hw_reg,
+	.set_hw_reg = rtl8723ae_set_hw_reg,
+	.update_rate_tbl = rtl8723ae_update_hal_rate_tbl,
+	.fill_tx_desc = rtl8723ae_tx_fill_desc,
+	.fill_tx_cmddesc = rtl8723ae_tx_fill_cmddesc,
+	.query_rx_desc = rtl8723ae_rx_query_desc,
+	.set_channel_access = rtl8723ae_update_channel_access_setting,
+	.radio_onoff_checking = rtl8723ae_gpio_radio_on_off_checking,
+	.set_bw_mode = rtl8723ae_phy_set_bw_mode,
+	.switch_channel = rtl8723ae_phy_sw_chnl,
+	.dm_watchdog = rtl8723ae_dm_watchdog,
+	.scan_operation_backup = rtl8723ae_phy_scan_operation_backup,
+	.set_rf_power_state = rtl8723ae_phy_set_rf_power_state,
+	.led_control = rtl8723ae_led_control,
+	.set_desc = rtl8723ae_set_desc,
+	.get_desc = rtl8723ae_get_desc,
+	.tx_polling = rtl8723ae_tx_polling,
+	.enable_hw_sec = rtl8723ae_enable_hw_security_config,
+	.set_key = rtl8723ae_set_key,
+	.init_sw_leds = rtl8723ae_init_sw_leds,
+	.allow_all_destaddr = rtl8723ae_allow_all_destaddr,
+	.get_bbreg = rtl8723ae_phy_query_bb_reg,
+	.set_bbreg = rtl8723ae_phy_set_bb_reg,
+	.get_rfreg = rtl8723ae_phy_query_rf_reg,
+	.set_rfreg = rtl8723ae_phy_set_rf_reg,
+	.c2h_command_handle = rtl_8723e_c2h_command_handle,
+	.bt_wifi_media_status_notify = rtl_8723e_bt_wifi_media_status_notify,
+	.bt_coex_off_before_lps = rtl8723ae_bt_coex_off_before_lps,
+};
+
+static struct rtl_mod_params rtl8723ae_mod_params = {
+	.sw_crypto = false,
+	.inactiveps = true,
+	.swctrl_lps = false,
+	.fwctrl_lps = true,
+	.debug = DBG_EMERG,
+};
+
+static struct rtl_hal_cfg rtl8723ae_hal_cfg = {
+	.bar_id = 2,
+	.write_readback = true,
+	.name = "rtl8723ae_pci",
+	.fw_name = "rtlwifi/rtl8723aefw.bin",
+	.ops = &rtl8723ae_hal_ops,
+	.mod_params = &rtl8723ae_mod_params,
+	.maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL,
+	.maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN,
+	.maps[SYS_CLK] = REG_SYS_CLKR,
+	.maps[MAC_RCR_AM] = AM,
+	.maps[MAC_RCR_AB] = AB,
+	.maps[MAC_RCR_ACRC32] = ACRC32,
+	.maps[MAC_RCR_ACF] = ACF,
+	.maps[MAC_RCR_AAP] = AAP,
+	.maps[EFUSE_TEST] = REG_EFUSE_TEST,
+	.maps[EFUSE_CTRL] = REG_EFUSE_CTRL,
+	.maps[EFUSE_CLK] = 0,
+	.maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL,
+	.maps[EFUSE_PWC_EV12V] = PWC_EV12V,
+	.maps[EFUSE_FEN_ELDR] = FEN_ELDR,
+	.maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN,
+	.maps[EFUSE_ANA8M] = ANA8M,
+	.maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE,
+	.maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION,
+	.maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN,
+	.maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES,
+
+	.maps[RWCAM] = REG_CAMCMD,
+	.maps[WCAMI] = REG_CAMWRITE,
+	.maps[RCAMO] = REG_CAMREAD,
+	.maps[CAMDBG] = REG_CAMDBG,
+	.maps[SECR] = REG_SECCFG,
+	.maps[SEC_CAM_NONE] = CAM_NONE,
+	.maps[SEC_CAM_WEP40] = CAM_WEP40,
+	.maps[SEC_CAM_TKIP] = CAM_TKIP,
+	.maps[SEC_CAM_AES] = CAM_AES,
+	.maps[SEC_CAM_WEP104] = CAM_WEP104,
+
+	.maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6,
+	.maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5,
+	.maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4,
+	.maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3,
+	.maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2,
+	.maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1,
+	.maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8,
+	.maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7,
+	.maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6,
+	.maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5,
+	.maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4,
+	.maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3,
+	.maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2,
+	.maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1,
+	.maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,
+	.maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,
+
+	.maps[RTL_IMR_TXFOVW] = PHIMR_TXFOVW,
+	.maps[RTL_IMR_PSTIMEOUT] = PHIMR_PSTIMEOUT,
+	.maps[RTL_IMR_BcnInt] = PHIMR_BCNDMAINT0,
+	.maps[RTL_IMR_RXFOVW] = PHIMR_RXFOVW,
+	.maps[RTL_IMR_RDU] = PHIMR_RDU,
+	.maps[RTL_IMR_ATIMEND] = PHIMR_ATIMEND_E,
+	.maps[RTL_IMR_BDOK] = PHIMR_BCNDOK0,
+	.maps[RTL_IMR_MGNTDOK] = PHIMR_MGNTDOK,
+	.maps[RTL_IMR_TBDER] = PHIMR_TXBCNERR,
+	.maps[RTL_IMR_HIGHDOK] = PHIMR_HIGHDOK,
+	.maps[RTL_IMR_TBDOK] = PHIMR_TXBCNOK,
+	.maps[RTL_IMR_BKDOK] = PHIMR_BKDOK,
+	.maps[RTL_IMR_BEDOK] = PHIMR_BEDOK,
+	.maps[RTL_IMR_VIDOK] = PHIMR_VIDOK,
+	.maps[RTL_IMR_VODOK] = PHIMR_VODOK,
+	.maps[RTL_IMR_ROK] = PHIMR_ROK,
+	.maps[RTL_IBSS_INT_MASKS] = (PHIMR_BCNDMAINT0 |
+				     PHIMR_TXBCNOK | PHIMR_TXBCNERR),
+	.maps[RTL_IMR_C2HCMD] = PHIMR_C2HCMD,
+
+
+	.maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M,
+	.maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M,
+	.maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M,
+	.maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M,
+	.maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M,
+	.maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M,
+	.maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M,
+	.maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M,
+	.maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M,
+	.maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M,
+	.maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M,
+	.maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M,
+
+	.maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7,
+	.maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,
+};
+
+static struct pci_device_id rtl8723ae_pci_ids[] __devinitdata = {
+	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8723, rtl8723ae_hal_cfg)},
+	{},
+};
+
+MODULE_DEVICE_TABLE(pci, rtl8723ae_pci_ids);
+
+MODULE_AUTHOR("lizhaoming	<chaoming_li@realsil.com.cn>");
+MODULE_AUTHOR("Realtek WlanFAE	<wlanfae@realtek.com>");
+MODULE_AUTHOR("Larry Finger	<Larry.Finger@lwfinger.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek 8723E 802.11n PCI wireless");
+MODULE_FIRMWARE("rtlwifi/rtl8723aefw.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8723aefw_B.bin");
+
+module_param_named(swenc, rtl8723ae_mod_params.sw_crypto, bool, 0444);
+module_param_named(debug, rtl8723ae_mod_params.debug, int, 0444);
+module_param_named(ips, rtl8723ae_mod_params.inactiveps, bool, 0444);
+module_param_named(swlps, rtl8723ae_mod_params.swctrl_lps, bool, 0444);
+module_param_named(fwlps, rtl8723ae_mod_params.fwctrl_lps, bool, 0444);
+MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
+MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
+MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
+MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
+MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
+
+static const struct dev_pm_ops rtlwifi_pm_ops = {
+	.suspend = rtl_pci_suspend,
+	.resume = rtl_pci_resume,
+	.freeze = rtl_pci_suspend,
+	.thaw = rtl_pci_resume,
+	.poweroff = rtl_pci_suspend,
+	.restore = rtl_pci_resume,
+};
+
+static struct pci_driver rtl8723ae_driver = {
+	.name = KBUILD_MODNAME,
+	.id_table = rtl8723ae_pci_ids,
+	.probe = rtl_pci_probe,
+	.remove = rtl_pci_disconnect,
+	.driver.pm = &rtlwifi_pm_ops,
+};
+
+module_pci_driver(rtl8723ae_driver);
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.h b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.h
new file mode 100644
index 0000000..fc4fde5
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.h
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_SW_H__
+#define __RTL8723E_SW_H__
+
+int rtl8723ae_init_sw_vars(struct ieee80211_hw *hw);
+void rtl8723ae_deinit_sw_vars(struct ieee80211_hw *hw);
+void rtl8723ae_init_var_map(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/table.c b/drivers/net/wireless/rtlwifi/rtl8723ae/table.c
new file mode 100644
index 0000000..9b0b50c
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/table.c
@@ -0,0 +1,738 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Created on  2010/ 5/18,  1:41
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "table.h"
+
+u32 RTL8723EPHY_REG_1TARRAY[RTL8723E_PHY_REG_1TARRAY_LENGTH] = {
+	0x800, 0x80040000,
+	0x804, 0x00000003,
+	0x808, 0x0000fc00,
+	0x80c, 0x0000000a,
+	0x810, 0x10005388,
+	0x814, 0x020c3d10,
+	0x818, 0x02200385,
+	0x81c, 0x00000000,
+	0x820, 0x01000100,
+	0x824, 0x00390004,
+	0x828, 0x00000000,
+	0x82c, 0x00000000,
+	0x830, 0x00000000,
+	0x834, 0x00000000,
+	0x838, 0x00000000,
+	0x83c, 0x00000000,
+	0x840, 0x00010000,
+	0x844, 0x00000000,
+	0x848, 0x00000000,
+	0x84c, 0x00000000,
+	0x850, 0x00000000,
+	0x854, 0x00000000,
+	0x858, 0x569a569a,
+	0x85c, 0x001b25a4,
+	0x860, 0x66f60110,
+	0x864, 0x061f0130,
+	0x868, 0x00000000,
+	0x86c, 0x32323200,
+	0x870, 0x07000760,
+	0x874, 0x22004000,
+	0x878, 0x00000808,
+	0x87c, 0x00000000,
+	0x880, 0xc0083070,
+	0x884, 0x000004d5,
+	0x888, 0x00000000,
+	0x88c, 0xccc000c0,
+	0x890, 0x00000800,
+	0x894, 0xfffffffe,
+	0x898, 0x40302010,
+	0x89c, 0x00706050,
+	0x900, 0x00000000,
+	0x904, 0x00000023,
+	0x908, 0x00000000,
+	0x90c, 0x81121111,
+	0xa00, 0x00d047c8,
+	0xa04, 0x80ff000c,
+	0xa08, 0x8c838300,
+	0xa0c, 0x2e68120f,
+	0xa10, 0x9500bb78,
+	0xa14, 0x11144028,
+	0xa18, 0x00881117,
+	0xa1c, 0x89140f00,
+	0xa20, 0x1a1b0000,
+	0xa24, 0x090e1317,
+	0xa28, 0x00000204,
+	0xa2c, 0x00d30000,
+	0xa70, 0x101fbf00,
+	0xa74, 0x00000007,
+	0xa78, 0x00000900,
+	0xc00, 0x48071d40,
+	0xc04, 0x03a05611,
+	0xc08, 0x000000e4,
+	0xc0c, 0x6c6c6c6c,
+	0xc10, 0x08800000,
+	0xc14, 0x40000100,
+	0xc18, 0x08800000,
+	0xc1c, 0x40000100,
+	0xc20, 0x00000000,
+	0xc24, 0x00000000,
+	0xc28, 0x00000000,
+	0xc2c, 0x00000000,
+	0xc30, 0x69e9ac44,
+	0xc34, 0x469652cf,
+	0xc38, 0x49795994,
+	0xc3c, 0x0a97971c,
+	0xc40, 0x1f7c403f,
+	0xc44, 0x000100b7,
+	0xc48, 0xec020107,
+	0xc4c, 0x007f037f,
+	0xc50, 0x69543420,
+	0xc54, 0x43bc0094,
+	0xc58, 0x69543420,
+	0xc5c, 0x433c0094,
+	0xc60, 0x00000000,
+	0xc64, 0x7116848b,
+	0xc68, 0x47c00bff,
+	0xc6c, 0x00000036,
+	0xc70, 0x2c7f000d,
+	0xc74, 0x018610db,
+	0xc78, 0x0000001f,
+	0xc7c, 0x00b91612,
+	0xc80, 0x40000100,
+	0xc84, 0x20f60000,
+	0xc88, 0x40000100,
+	0xc8c, 0x20200000,
+	0xc90, 0x00121820,
+	0xc94, 0x00000000,
+	0xc98, 0x00121820,
+	0xc9c, 0x00007f7f,
+	0xca0, 0x00000000,
+	0xca4, 0x00000080,
+	0xca8, 0x00000000,
+	0xcac, 0x00000000,
+	0xcb0, 0x00000000,
+	0xcb4, 0x00000000,
+	0xcb8, 0x00000000,
+	0xcbc, 0x28000000,
+	0xcc0, 0x00000000,
+	0xcc4, 0x00000000,
+	0xcc8, 0x00000000,
+	0xccc, 0x00000000,
+	0xcd0, 0x00000000,
+	0xcd4, 0x00000000,
+	0xcd8, 0x64b22427,
+	0xcdc, 0x00766932,
+	0xce0, 0x00222222,
+	0xce4, 0x00000000,
+	0xce8, 0x37644302,
+	0xcec, 0x2f97d40c,
+	0xd00, 0x00080740,
+	0xd04, 0x00020401,
+	0xd08, 0x0000907f,
+	0xd0c, 0x20010201,
+	0xd10, 0xa0633333,
+	0xd14, 0x3333bc43,
+	0xd18, 0x7a8f5b6b,
+	0xd2c, 0xcc979975,
+	0xd30, 0x00000000,
+	0xd34, 0x80608000,
+	0xd38, 0x00000000,
+	0xd3c, 0x00027293,
+	0xd40, 0x00000000,
+	0xd44, 0x00000000,
+	0xd48, 0x00000000,
+	0xd4c, 0x00000000,
+	0xd50, 0x6437140a,
+	0xd54, 0x00000000,
+	0xd58, 0x00000000,
+	0xd5c, 0x30032064,
+	0xd60, 0x4653de68,
+	0xd64, 0x04518a3c,
+	0xd68, 0x00002101,
+	0xd6c, 0x2a201c16,
+	0xd70, 0x1812362e,
+	0xd74, 0x322c2220,
+	0xd78, 0x000e3c24,
+	0xe00, 0x2a2a2a2a,
+	0xe04, 0x2a2a2a2a,
+	0xe08, 0x03902a2a,
+	0xe10, 0x2a2a2a2a,
+	0xe14, 0x2a2a2a2a,
+	0xe18, 0x2a2a2a2a,
+	0xe1c, 0x2a2a2a2a,
+	0xe28, 0x00000000,
+	0xe30, 0x1000dc1f,
+	0xe34, 0x10008c1f,
+	0xe38, 0x02140102,
+	0xe3c, 0x681604c2,
+	0xe40, 0x01007c00,
+	0xe44, 0x01004800,
+	0xe48, 0xfb000000,
+	0xe4c, 0x000028d1,
+	0xe50, 0x1000dc1f,
+	0xe54, 0x10008c1f,
+	0xe58, 0x02140102,
+	0xe5c, 0x28160d05,
+	0xe60, 0x00000008,
+	0xe68, 0x001b25a4,
+	0xe6c, 0x631b25a0,
+	0xe70, 0x631b25a0,
+	0xe74, 0x081b25a0,
+	0xe78, 0x081b25a0,
+	0xe7c, 0x081b25a0,
+	0xe80, 0x081b25a0,
+	0xe84, 0x631b25a0,
+	0xe88, 0x081b25a0,
+	0xe8c, 0x631b25a0,
+	0xed0, 0x631b25a0,
+	0xed4, 0x631b25a0,
+	0xed8, 0x631b25a0,
+	0xedc, 0x001b25a0,
+	0xee0, 0x001b25a0,
+	0xeec, 0x6b1b25a0,
+	0xf14, 0x00000003,
+	0xf4c, 0x00000000,
+	0xf00, 0x00000300,
+};
+
+u32 RTL8723EPHY_REG_ARRAY_PG[RTL8723E_PHY_REG_ARRAY_PGLENGTH] = {
+	0xe00, 0xffffffff, 0x0a0c0c0c,
+	0xe04, 0xffffffff, 0x02040608,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x0a0c0d0e,
+	0xe14, 0xffffffff, 0x02040608,
+	0xe18, 0xffffffff, 0x0a0c0d0e,
+	0xe1c, 0xffffffff, 0x02040608,
+	0x830, 0xffffffff, 0x0a0c0c0c,
+	0x834, 0xffffffff, 0x02040608,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x0a0c0d0e,
+	0x848, 0xffffffff, 0x02040608,
+	0x84c, 0xffffffff, 0x0a0c0d0e,
+	0x868, 0xffffffff, 0x02040608,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x04040404,
+	0xe04, 0xffffffff, 0x00020204,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x06060606,
+	0xe14, 0xffffffff, 0x00020406,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x04040404,
+	0x834, 0xffffffff, 0x00020204,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x06060606,
+	0x848, 0xffffffff, 0x00020406,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x04040404,
+	0xe04, 0xffffffff, 0x00020204,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x04040404,
+	0x834, 0xffffffff, 0x00020204,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+};
+
+u32 RTL8723E_RADIOA_1TARRAY[Rtl8723ERADIOA_1TARRAYLENGTH] = {
+	0x000, 0x00030159,
+	0x001, 0x00031284,
+	0x002, 0x00098000,
+	0x003, 0x00018c63,
+	0x004, 0x000210e7,
+	0x009, 0x0002044f,
+	0x00a, 0x0001a3f1,
+	0x00b, 0x00014787,
+	0x00c, 0x000896fe,
+	0x00d, 0x0000e02c,
+	0x00e, 0x00039ce7,
+	0x00f, 0x00000451,
+	0x019, 0x00000000,
+	0x01a, 0x00030355,
+	0x01b, 0x00060a00,
+	0x01c, 0x000fc378,
+	0x01d, 0x000a1250,
+	0x01e, 0x0004445f,
+	0x01f, 0x00080001,
+	0x020, 0x0000b614,
+	0x021, 0x0006c000,
+	0x022, 0x00000000,
+	0x023, 0x00001558,
+	0x024, 0x00000060,
+	0x025, 0x00000483,
+	0x026, 0x0004f000,
+	0x027, 0x000ec7d9,
+	0x028, 0x00057730,
+	0x029, 0x00004783,
+	0x02a, 0x00000001,
+	0x02b, 0x00021334,
+	0x02a, 0x00000000,
+	0x02b, 0x00000054,
+	0x02a, 0x00000001,
+	0x02b, 0x00000808,
+	0x02b, 0x00053333,
+	0x02c, 0x0000000c,
+	0x02a, 0x00000002,
+	0x02b, 0x00000808,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000003,
+	0x02b, 0x00000808,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000004,
+	0x02b, 0x00000808,
+	0x02b, 0x0006b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000005,
+	0x02b, 0x00000808,
+	0x02b, 0x00073333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000006,
+	0x02b, 0x00000709,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000007,
+	0x02b, 0x00000709,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000008,
+	0x02b, 0x0000060a,
+	0x02b, 0x0004b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000009,
+	0x02b, 0x0000060a,
+	0x02b, 0x00053333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000a,
+	0x02b, 0x0000060a,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000b,
+	0x02b, 0x0000060a,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000c,
+	0x02b, 0x0000060a,
+	0x02b, 0x0006b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000d,
+	0x02b, 0x0000060a,
+	0x02b, 0x00073333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000e,
+	0x02b, 0x0000050b,
+	0x02b, 0x00066666,
+	0x02c, 0x0000001a,
+	0x02a, 0x000e0000,
+	0x010, 0x0004000f,
+	0x011, 0x000e31fc,
+	0x010, 0x0006000f,
+	0x011, 0x000ff9f8,
+	0x010, 0x0002000f,
+	0x011, 0x000203f9,
+	0x010, 0x0003000f,
+	0x011, 0x000ff500,
+	0x010, 0x00000000,
+	0x011, 0x00000000,
+	0x010, 0x0008000f,
+	0x011, 0x0003f100,
+	0x010, 0x0009000f,
+	0x011, 0x00023100,
+	0x012, 0x00032000,
+	0x012, 0x00071000,
+	0x012, 0x000b0000,
+	0x012, 0x000fc000,
+	0x013, 0x000287b3,
+	0x013, 0x000244b7,
+	0x013, 0x000204ab,
+	0x013, 0x0001c49f,
+	0x013, 0x00018493,
+	0x013, 0x0001429b,
+	0x013, 0x00010299,
+	0x013, 0x0000c29c,
+	0x013, 0x000081a0,
+	0x013, 0x000040ac,
+	0x013, 0x00000020,
+	0x014, 0x0001944c,
+	0x014, 0x00059444,
+	0x014, 0x0009944c,
+	0x014, 0x000d9444,
+	0x015, 0x0000f424,
+	0x015, 0x0004f407,
+	0x015, 0x0008f424,
+	0x015, 0x000cf424,
+	0x016, 0x00000339,
+	0x016, 0x00040339,
+	0x016, 0x00080339,
+	0x016, 0x000c0336,
+	0x000, 0x00010159,
+	0x018, 0x0000f401,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01f, 0x00080003,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01e, 0x00044457,
+	0x01f, 0x00080000,
+	0x000, 0x00030159,
+};
+
+
+u32 RTL8723E_RADIOB_1TARRAY[RTL8723E_RADIOB_1TARRAYLENGTH] = {
+	0x0,
+};
+
+
+u32 RTL8723EMAC_ARRAY[RTL8723E_MACARRAYLENGTH] = {
+	0x420, 0x00000080,
+	0x423, 0x00000000,
+	0x430, 0x00000000,
+	0x431, 0x00000000,
+	0x432, 0x00000000,
+	0x433, 0x00000001,
+	0x434, 0x00000004,
+	0x435, 0x00000005,
+	0x436, 0x00000006,
+	0x437, 0x00000007,
+	0x438, 0x00000000,
+	0x439, 0x00000000,
+	0x43a, 0x00000000,
+	0x43b, 0x00000001,
+	0x43c, 0x00000004,
+	0x43d, 0x00000005,
+	0x43e, 0x00000006,
+	0x43f, 0x00000007,
+	0x440, 0x0000005d,
+	0x441, 0x00000001,
+	0x442, 0x00000000,
+	0x444, 0x00000015,
+	0x445, 0x000000f0,
+	0x446, 0x0000000f,
+	0x447, 0x00000000,
+	0x458, 0x00000041,
+	0x459, 0x000000a8,
+	0x45a, 0x00000072,
+	0x45b, 0x000000b9,
+	0x460, 0x00000066,
+	0x461, 0x00000066,
+	0x462, 0x00000008,
+	0x463, 0x00000003,
+	0x4c8, 0x000000ff,
+	0x4c9, 0x00000008,
+	0x4cc, 0x000000ff,
+	0x4cd, 0x000000ff,
+	0x4ce, 0x00000001,
+	0x500, 0x00000026,
+	0x501, 0x000000a2,
+	0x502, 0x0000002f,
+	0x503, 0x00000000,
+	0x504, 0x00000028,
+	0x505, 0x000000a3,
+	0x506, 0x0000005e,
+	0x507, 0x00000000,
+	0x508, 0x0000002b,
+	0x509, 0x000000a4,
+	0x50a, 0x0000005e,
+	0x50b, 0x00000000,
+	0x50c, 0x0000004f,
+	0x50d, 0x000000a4,
+	0x50e, 0x00000000,
+	0x50f, 0x00000000,
+	0x512, 0x0000001c,
+	0x514, 0x0000000a,
+	0x515, 0x00000010,
+	0x516, 0x0000000a,
+	0x517, 0x00000010,
+	0x51a, 0x00000016,
+	0x524, 0x0000000f,
+	0x525, 0x0000004f,
+	0x546, 0x00000040,
+	0x547, 0x00000000,
+	0x550, 0x00000010,
+	0x551, 0x00000010,
+	0x559, 0x00000002,
+	0x55a, 0x00000002,
+	0x55d, 0x000000ff,
+	0x605, 0x00000030,
+	0x608, 0x0000000e,
+	0x609, 0x0000002a,
+	0x652, 0x00000020,
+	0x63c, 0x0000000a,
+	0x63d, 0x0000000e,
+	0x63e, 0x0000000a,
+	0x63f, 0x0000000e,
+	0x66e, 0x00000005,
+	0x700, 0x00000021,
+	0x701, 0x00000043,
+	0x702, 0x00000065,
+	0x703, 0x00000087,
+	0x708, 0x00000021,
+	0x709, 0x00000043,
+	0x70a, 0x00000065,
+	0x70b, 0x00000087,
+};
+
+u32 RTL8723EAGCTAB_1TARRAY[RTL8723E_AGCTAB_1TARRAYLENGTH] = {
+	0xc78, 0x7b000001,
+	0xc78, 0x7b010001,
+	0xc78, 0x7b020001,
+	0xc78, 0x7b030001,
+	0xc78, 0x7b040001,
+	0xc78, 0x7b050001,
+	0xc78, 0x7a060001,
+	0xc78, 0x79070001,
+	0xc78, 0x78080001,
+	0xc78, 0x77090001,
+	0xc78, 0x760a0001,
+	0xc78, 0x750b0001,
+	0xc78, 0x740c0001,
+	0xc78, 0x730d0001,
+	0xc78, 0x720e0001,
+	0xc78, 0x710f0001,
+	0xc78, 0x70100001,
+	0xc78, 0x6f110001,
+	0xc78, 0x6e120001,
+	0xc78, 0x6d130001,
+	0xc78, 0x6c140001,
+	0xc78, 0x6b150001,
+	0xc78, 0x6a160001,
+	0xc78, 0x69170001,
+	0xc78, 0x68180001,
+	0xc78, 0x67190001,
+	0xc78, 0x661a0001,
+	0xc78, 0x651b0001,
+	0xc78, 0x641c0001,
+	0xc78, 0x631d0001,
+	0xc78, 0x621e0001,
+	0xc78, 0x611f0001,
+	0xc78, 0x60200001,
+	0xc78, 0x49210001,
+	0xc78, 0x48220001,
+	0xc78, 0x47230001,
+	0xc78, 0x46240001,
+	0xc78, 0x45250001,
+	0xc78, 0x44260001,
+	0xc78, 0x43270001,
+	0xc78, 0x42280001,
+	0xc78, 0x41290001,
+	0xc78, 0x402a0001,
+	0xc78, 0x262b0001,
+	0xc78, 0x252c0001,
+	0xc78, 0x242d0001,
+	0xc78, 0x232e0001,
+	0xc78, 0x222f0001,
+	0xc78, 0x21300001,
+	0xc78, 0x20310001,
+	0xc78, 0x06320001,
+	0xc78, 0x05330001,
+	0xc78, 0x04340001,
+	0xc78, 0x03350001,
+	0xc78, 0x02360001,
+	0xc78, 0x01370001,
+	0xc78, 0x00380001,
+	0xc78, 0x00390001,
+	0xc78, 0x003a0001,
+	0xc78, 0x003b0001,
+	0xc78, 0x003c0001,
+	0xc78, 0x003d0001,
+	0xc78, 0x003e0001,
+	0xc78, 0x003f0001,
+	0xc78, 0x7b400001,
+	0xc78, 0x7b410001,
+	0xc78, 0x7b420001,
+	0xc78, 0x7b430001,
+	0xc78, 0x7b440001,
+	0xc78, 0x7b450001,
+	0xc78, 0x7a460001,
+	0xc78, 0x79470001,
+	0xc78, 0x78480001,
+	0xc78, 0x77490001,
+	0xc78, 0x764a0001,
+	0xc78, 0x754b0001,
+	0xc78, 0x744c0001,
+	0xc78, 0x734d0001,
+	0xc78, 0x724e0001,
+	0xc78, 0x714f0001,
+	0xc78, 0x70500001,
+	0xc78, 0x6f510001,
+	0xc78, 0x6e520001,
+	0xc78, 0x6d530001,
+	0xc78, 0x6c540001,
+	0xc78, 0x6b550001,
+	0xc78, 0x6a560001,
+	0xc78, 0x69570001,
+	0xc78, 0x68580001,
+	0xc78, 0x67590001,
+	0xc78, 0x665a0001,
+	0xc78, 0x655b0001,
+	0xc78, 0x645c0001,
+	0xc78, 0x635d0001,
+	0xc78, 0x625e0001,
+	0xc78, 0x615f0001,
+	0xc78, 0x60600001,
+	0xc78, 0x49610001,
+	0xc78, 0x48620001,
+	0xc78, 0x47630001,
+	0xc78, 0x46640001,
+	0xc78, 0x45650001,
+	0xc78, 0x44660001,
+	0xc78, 0x43670001,
+	0xc78, 0x42680001,
+	0xc78, 0x41690001,
+	0xc78, 0x406a0001,
+	0xc78, 0x266b0001,
+	0xc78, 0x256c0001,
+	0xc78, 0x246d0001,
+	0xc78, 0x236e0001,
+	0xc78, 0x226f0001,
+	0xc78, 0x21700001,
+	0xc78, 0x20710001,
+	0xc78, 0x06720001,
+	0xc78, 0x05730001,
+	0xc78, 0x04740001,
+	0xc78, 0x03750001,
+	0xc78, 0x02760001,
+	0xc78, 0x01770001,
+	0xc78, 0x00780001,
+	0xc78, 0x00790001,
+	0xc78, 0x007a0001,
+	0xc78, 0x007b0001,
+	0xc78, 0x007c0001,
+	0xc78, 0x007d0001,
+	0xc78, 0x007e0001,
+	0xc78, 0x007f0001,
+	0xc78, 0x3800001e,
+	0xc78, 0x3801001e,
+	0xc78, 0x3802001e,
+	0xc78, 0x3803001e,
+	0xc78, 0x3804001e,
+	0xc78, 0x3805001e,
+	0xc78, 0x3806001e,
+	0xc78, 0x3807001e,
+	0xc78, 0x3808001e,
+	0xc78, 0x3c09001e,
+	0xc78, 0x3e0a001e,
+	0xc78, 0x400b001e,
+	0xc78, 0x440c001e,
+	0xc78, 0x480d001e,
+	0xc78, 0x4c0e001e,
+	0xc78, 0x500f001e,
+	0xc78, 0x5210001e,
+	0xc78, 0x5611001e,
+	0xc78, 0x5a12001e,
+	0xc78, 0x5e13001e,
+	0xc78, 0x6014001e,
+	0xc78, 0x6015001e,
+	0xc78, 0x6016001e,
+	0xc78, 0x6217001e,
+	0xc78, 0x6218001e,
+	0xc78, 0x6219001e,
+	0xc78, 0x621a001e,
+	0xc78, 0x621b001e,
+	0xc78, 0x621c001e,
+	0xc78, 0x621d001e,
+	0xc78, 0x621e001e,
+	0xc78, 0x621f001e,
+};
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/table.h b/drivers/net/wireless/rtlwifi/rtl8723ae/table.h
new file mode 100644
index 0000000..f5ce713
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/table.h
@@ -0,0 +1,50 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Created on  2010/ 5/18,  1:41
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_TABLE__H_
+#define __RTL8723E_TABLE__H_
+
+#include <linux/types.h>
+
+#define RTL8723E_PHY_REG_1TARRAY_LENGTH		372
+extern u32 RTL8723EPHY_REG_1TARRAY[RTL8723E_PHY_REG_1TARRAY_LENGTH];
+#define RTL8723E_PHY_REG_ARRAY_PGLENGTH		336
+extern u32 RTL8723EPHY_REG_ARRAY_PG[RTL8723E_PHY_REG_ARRAY_PGLENGTH];
+#define Rtl8723ERADIOA_1TARRAYLENGTH		 282
+extern u32 RTL8723E_RADIOA_1TARRAY[Rtl8723ERADIOA_1TARRAYLENGTH];
+#define RTL8723E_RADIOB_1TARRAYLENGTH		1
+extern u32 RTL8723E_RADIOB_1TARRAY[RTL8723E_RADIOB_1TARRAYLENGTH];
+#define RTL8723E_MACARRAYLENGTH			172
+extern u32 RTL8723EMAC_ARRAY[RTL8723E_MACARRAYLENGTH];
+#define RTL8723E_AGCTAB_1TARRAYLENGTH		320
+extern u32 RTL8723EAGCTAB_1TARRAY[RTL8723E_AGCTAB_1TARRAYLENGTH];
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
new file mode 100644
index 0000000..87331d8
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
@@ -0,0 +1,670 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../base.h"
+#include "../stats.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "trx.h"
+#include "led.h"
+
+static u8 _rtl8723ae_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
+{
+	__le16 fc = rtl_get_fc(skb);
+
+	if (unlikely(ieee80211_is_beacon(fc)))
+		return QSLT_BEACON;
+	if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))
+		return QSLT_MGNT;
+
+	return skb->priority;
+}
+
+static void _rtl8723ae_query_rxphystatus(struct ieee80211_hw *hw,
+			struct rtl_stats *pstatus, u8 *pdesc,
+			struct rx_fwinfo_8723e *p_drvinfo,
+			bool bpacket_match_bssid,
+			bool bpacket_toself, bool packet_beacon)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
+	struct phy_sts_cck_8723e_t *cck_buf;
+	s8 rx_pwr_all, rx_pwr[4];
+	u8 rf_rx_num = 0, evm, pwdb_all;
+	u8 i, max_spatial_stream;
+	u32 rssi, total_rssi = 0;
+	bool is_cck = pstatus->is_cck;
+
+	/* Record it for next packet processing */
+	pstatus->packet_matchbssid = bpacket_match_bssid;
+	pstatus->packet_toself = bpacket_toself;
+	pstatus->packet_beacon = packet_beacon;
+	pstatus->rx_mimo_sig_qual[0] = -1;
+	pstatus->rx_mimo_sig_qual[1] = -1;
+
+	if (is_cck) {
+		u8 report, cck_highpwr;
+
+		/* CCK Driver info Structure is not the same as OFDM packet. */
+		cck_buf = (struct phy_sts_cck_8723e_t *)p_drvinfo;
+
+		/* (1)Hardware does not provide RSSI for CCK
+		 * (2)PWDB, Average PWDB cacluated by
+		 * hardware (for rate adaptive)
+		 */
+		if (ppsc->rfpwr_state == ERFON)
+			cck_highpwr = (u8) rtl_get_bbreg(hw,
+						 RFPGA0_XA_HSSIPARAMETER2,
+						 BIT(9));
+		else
+			cck_highpwr = false;
+
+		if (!cck_highpwr) {
+			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+			report = cck_buf->cck_agc_rpt & 0xc0;
+			report = report >> 6;
+			switch (report) {
+			case 0x3:
+				rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
+				break;
+			case 0x2:
+				rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
+				break;
+			case 0x1:
+				rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
+				break;
+			case 0x0:
+				rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
+				break;
+			}
+		} else {
+			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+			report = p_drvinfo->cfosho[0] & 0x60;
+			report = report >> 5;
+			switch (report) {
+			case 0x3:
+				rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
+				break;
+			case 0x2:
+				rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
+				break;
+			case 0x1:
+				rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
+				break;
+			case 0x0:
+				rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
+				break;
+			}
+		}
+
+		pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
+		/* CCK gain is smaller than OFDM/MCS gain,
+		 * so we add gain diff. From experience, the val is 6
+		 */
+		pwdb_all += 6;
+		if (pwdb_all > 100)
+			pwdb_all = 100;
+		/* modify the offset to make the same
+		 * gain index with OFDM.
+		 */
+		if (pwdb_all > 34 && pwdb_all <= 42)
+			pwdb_all -= 2;
+		else if (pwdb_all > 26 && pwdb_all <= 34)
+			pwdb_all -= 6;
+		else if (pwdb_all > 14 && pwdb_all <= 26)
+			pwdb_all -= 8;
+		else if (pwdb_all > 4 && pwdb_all <= 14)
+			pwdb_all -= 4;
+
+		pstatus->rx_pwdb_all = pwdb_all;
+		pstatus->recvsignalpower = rx_pwr_all;
+
+		/* (3) Get Signal Quality (EVM) */
+		if (bpacket_match_bssid) {
+			u8 sq;
+
+			if (pstatus->rx_pwdb_all > 40) {
+				sq = 100;
+			} else {
+				sq = cck_buf->sq_rpt;
+				if (sq > 64)
+					sq = 0;
+				else if (sq < 20)
+					sq = 100;
+				else
+					sq = ((64 - sq) * 100) / 44;
+			}
+
+			pstatus->signalquality = sq;
+			pstatus->rx_mimo_sig_qual[0] = sq;
+			pstatus->rx_mimo_sig_qual[1] = -1;
+		}
+	} else {
+		rtlpriv->dm.rfpath_rxenable[0] =
+		    rtlpriv->dm.rfpath_rxenable[1] = true;
+
+		/* (1)Get RSSI for HT rate */
+		for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) {
+
+			/* we will judge RF RX path now. */
+			if (rtlpriv->dm.rfpath_rxenable[i])
+				rf_rx_num++;
+
+			rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & 0x3f)*2) - 110;
+
+			/* Translate DBM to percentage. */
+			rssi = rtl_query_rxpwrpercentage(rx_pwr[i]);
+			total_rssi += rssi;
+
+			/* Get Rx snr value in DB */
+			rtlpriv->stats.rx_snr_db[i] = (p_drvinfo->rxsnr[i] / 2);
+
+			/* Record Signal Strength for next packet */
+			if (bpacket_match_bssid)
+				pstatus->rx_mimo_signalstrength[i] = (u8) rssi;
+		}
+
+		/* (2)PWDB, Average PWDB cacluated by
+		 * hardware (for rate adaptive)
+		 */
+		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
+
+		pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
+		pstatus->rx_pwdb_all = pwdb_all;
+		pstatus->rxpower = rx_pwr_all;
+		pstatus->recvsignalpower = rx_pwr_all;
+
+		/* (3)EVM of HT rate */
+		if (pstatus->is_ht && pstatus->rate >= DESC92_RATEMCS8 &&
+		    pstatus->rate <= DESC92_RATEMCS15)
+			max_spatial_stream = 2;
+		else
+			max_spatial_stream = 1;
+
+		for (i = 0; i < max_spatial_stream; i++) {
+			evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]);
+
+			if (bpacket_match_bssid) {
+				/* Fill value in RFD, Get the first
+				 * spatial stream only
+				 */
+				if (i == 0)
+					pstatus->signalquality = (evm & 0xff);
+				pstatus->rx_mimo_sig_qual[i] = (evm & 0xff);
+			}
+		}
+	}
+
+	/* UI BSS List signal strength(in percentage),
+	 * make it good looking, from 0~100.
+	 */
+	if (is_cck)
+		pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw,
+			pwdb_all));
+	else if (rf_rx_num != 0)
+		pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw,
+			total_rssi /= rf_rx_num));
+}
+
+static void _rtl8723ae_translate_rx_signal_stuff(struct ieee80211_hw *hw,
+		struct sk_buff *skb, struct rtl_stats *pstatus,
+		u8 *pdesc, struct rx_fwinfo_8723e *p_drvinfo)
+{
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct ieee80211_hdr *hdr;
+	u8 *tmp_buf;
+	u8 *praddr;
+	u8 *psaddr;
+	__le16 fc;
+	u16 type;
+	bool packet_matchbssid, packet_toself, packet_beacon;
+
+	tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift;
+
+	hdr = (struct ieee80211_hdr *)tmp_buf;
+	fc = hdr->frame_control;
+	type = WLAN_FC_GET_TYPE(fc);
+	praddr = hdr->addr1;
+	psaddr = ieee80211_get_SA(hdr);
+
+	packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) &&
+			    (!compare_ether_addr(mac->bssid,
+			    (le16_to_cpu(fc) & IEEE80211_FCTL_TODS) ?
+			    hdr->addr1 : (le16_to_cpu(fc) &
+			    IEEE80211_FCTL_FROMDS) ?
+			    hdr->addr2 : hdr->addr3)) && (!pstatus->hwerror) &&
+			    (!pstatus->crc) && (!pstatus->icv));
+
+	packet_toself = packet_matchbssid &&
+	    (!compare_ether_addr(praddr, rtlefuse->dev_addr));
+
+	if (ieee80211_is_beacon(fc))
+		packet_beacon = true;
+
+	_rtl8723ae_query_rxphystatus(hw, pstatus, pdesc, p_drvinfo,
+				   packet_matchbssid, packet_toself,
+				   packet_beacon);
+
+	rtl_process_phyinfo(hw, tmp_buf, pstatus);
+}
+
+bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw,
+			     struct rtl_stats *status,
+			     struct ieee80211_rx_status *rx_status,
+			     u8 *pdesc, struct sk_buff *skb)
+{
+	struct rx_fwinfo_8723e *p_drvinfo;
+	struct ieee80211_hdr *hdr;
+	u32 phystatus = GET_RX_DESC_PHYST(pdesc);
+
+	status->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
+	status->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) *
+				   RX_DRV_INFO_SIZE_UNIT;
+	status->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03);
+	status->icv = (u16) GET_RX_DESC_ICV(pdesc);
+	status->crc = (u16) GET_RX_DESC_CRC32(pdesc);
+	status->hwerror = (status->crc | status->icv);
+	status->decrypted = !GET_RX_DESC_SWDEC(pdesc);
+	status->rate = (u8) GET_RX_DESC_RXMCS(pdesc);
+	status->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
+	status->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
+	status->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
+				 && (GET_RX_DESC_FAGGR(pdesc) == 1));
+	status->timestamp_low = GET_RX_DESC_TSFL(pdesc);
+	status->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
+	status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc);
+
+	status->is_cck = RTL8723E_RX_HAL_IS_CCK_RATE(status->rate);
+
+	rx_status->freq = hw->conf.channel->center_freq;
+	rx_status->band = hw->conf.channel->band;
+
+	hdr = (struct ieee80211_hdr *)(skb->data + status->rx_drvinfo_size
+		+ status->rx_bufshift);
+
+	if (status->crc)
+		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+
+	if (status->rx_is40Mhzpacket)
+		rx_status->flag |= RX_FLAG_40MHZ;
+
+	if (status->is_ht)
+		rx_status->flag |= RX_FLAG_HT;
+
+	rx_status->flag |= RX_FLAG_MACTIME_START;
+
+	/* hw will set status->decrypted true, if it finds the
+	 * frame is open data frame or mgmt frame.
+	 * Thus hw will not decrypt a robust managment frame
+	 * for IEEE80211w but still set status->decrypted
+	 * true, so here we should set it back to undecrypted
+	 * for IEEE80211w frame, and mac80211 sw will help
+	 * to decrypt it
+	 */
+	if (status->decrypted) {
+		if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
+			(ieee80211_has_protected(hdr->frame_control)))
+			rx_status->flag &= ~RX_FLAG_DECRYPTED;
+		else
+			rx_status->flag |= RX_FLAG_DECRYPTED;
+	}
+
+	/* rate_idx: index of data rate into band's
+	 * supported rates or MCS index if HT rates
+	 * are use (RX_FLAG_HT)
+	 */
+	rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht,
+						   status->rate, false);
+
+	rx_status->mactime = status->timestamp_low;
+	if (phystatus == true) {
+		p_drvinfo = (struct rx_fwinfo_8723e *)(skb->data +
+			     status->rx_bufshift);
+
+		_rtl8723ae_translate_rx_signal_stuff(hw,
+			   skb, status, pdesc, p_drvinfo);
+	}
+
+	/*rx_status->qual = status->signal; */
+	rx_status->signal = status->recvsignalpower + 10;
+	/*rx_status->noise = -status->noise; */
+
+	return true;
+}
+
+void rtl8723ae_tx_fill_desc(struct ieee80211_hw *hw,
+			    struct ieee80211_hdr *hdr, u8 *pdesc_tx,
+			    struct ieee80211_tx_info *info,
+			    struct ieee80211_sta *sta,
+			    struct sk_buff *skb, u8 hw_queue,
+			    struct rtl_tcb_desc *ptcdesc)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	bool defaultadapter = true;
+	u8 *pdesc = (u8 *) pdesc_tx;
+	u16 seq_number;
+	__le16 fc = hdr->frame_control;
+	u8 fw_qsel = _rtl8723ae_map_hwqueue_to_fwqueue(skb, hw_queue);
+	bool firstseg = ((hdr->seq_ctrl &
+			    cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
+	bool lastseg = ((hdr->frame_control &
+			   cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
+	dma_addr_t mapping = pci_map_single(rtlpci->pdev,
+					    skb->data, skb->len,
+					    PCI_DMA_TODEVICE);
+	u8 bw_40 = 0;
+
+	if (mac->opmode == NL80211_IFTYPE_STATION) {
+		bw_40 = mac->bw_40;
+	} else if (mac->opmode == NL80211_IFTYPE_AP ||
+		mac->opmode == NL80211_IFTYPE_ADHOC) {
+		if (sta)
+			bw_40 = sta->ht_cap.cap &
+				IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+	}
+
+	seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
+
+	rtl_get_tcb_desc(hw, info, sta, skb, ptcdesc);
+
+	CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_8723e));
+
+	if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) {
+		firstseg = true;
+		lastseg = true;
+	}
+
+	if (firstseg) {
+		SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
+
+		SET_TX_DESC_TX_RATE(pdesc, ptcdesc->hw_rate);
+
+		if (ptcdesc->use_shortgi || ptcdesc->use_shortpreamble)
+			SET_TX_DESC_DATA_SHORTGI(pdesc, 1);
+
+		if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+			SET_TX_DESC_AGG_BREAK(pdesc, 1);
+			SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14);
+		}
+		SET_TX_DESC_SEQ(pdesc, seq_number);
+
+		SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcdesc->rts_enable &&
+						!ptcdesc->
+						cts_enable) ? 1 : 0));
+		SET_TX_DESC_HW_RTS_ENABLE(pdesc,
+					  ((ptcdesc->rts_enable
+					    || ptcdesc->cts_enable) ? 1 : 0));
+		SET_TX_DESC_CTS2SELF(pdesc, ((ptcdesc->cts_enable) ? 1 : 0));
+		SET_TX_DESC_RTS_STBC(pdesc, ((ptcdesc->rts_stbc) ? 1 : 0));
+
+		SET_TX_DESC_RTS_RATE(pdesc, ptcdesc->rts_rate);
+		SET_TX_DESC_RTS_BW(pdesc, 0);
+		SET_TX_DESC_RTS_SC(pdesc, ptcdesc->rts_sc);
+		SET_TX_DESC_RTS_SHORT(pdesc,
+				      ((ptcdesc->rts_rate <= DESC92_RATE54M) ?
+				       (ptcdesc->rts_use_shortpreamble ? 1 : 0)
+				       : (ptcdesc->rts_use_shortgi ? 1 : 0)));
+
+		if (bw_40) {
+			if (ptcdesc->packet_bw) {
+				SET_TX_DESC_DATA_BW(pdesc, 1);
+				SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3);
+			} else {
+				SET_TX_DESC_DATA_BW(pdesc, 0);
+				SET_TX_DESC_TX_SUB_CARRIER(pdesc,
+							 mac->cur_40_prime_sc);
+			}
+		} else {
+			SET_TX_DESC_DATA_BW(pdesc, 0);
+			SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0);
+		}
+
+		SET_TX_DESC_LINIP(pdesc, 0);
+		SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len);
+
+		if (sta) {
+			u8 ampdu_density = sta->ht_cap.ampdu_density;
+			SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density);
+		}
+
+		if (info->control.hw_key) {
+			struct ieee80211_key_conf *keyconf =
+			    info->control.hw_key;
+
+			switch (keyconf->cipher) {
+			case WLAN_CIPHER_SUITE_WEP40:
+			case WLAN_CIPHER_SUITE_WEP104:
+			case WLAN_CIPHER_SUITE_TKIP:
+				SET_TX_DESC_SEC_TYPE(pdesc, 0x1);
+				break;
+			case WLAN_CIPHER_SUITE_CCMP:
+				SET_TX_DESC_SEC_TYPE(pdesc, 0x3);
+				break;
+			default:
+				SET_TX_DESC_SEC_TYPE(pdesc, 0x0);
+				break;
+			}
+		}
+
+		SET_TX_DESC_PKT_ID(pdesc, 0);
+		SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel);
+
+		SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F);
+		SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF);
+		SET_TX_DESC_DISABLE_FB(pdesc, 0);
+		SET_TX_DESC_USE_RATE(pdesc, ptcdesc->use_driver_rate ? 1 : 0);
+
+		if (ieee80211_is_data_qos(fc)) {
+			if (mac->rdg_en) {
+				RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+					 "Enable RDG function.\n");
+				SET_TX_DESC_RDG_ENABLE(pdesc, 1);
+				SET_TX_DESC_HTC(pdesc, 1);
+			}
+		}
+	}
+
+	SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0));
+	SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0));
+
+	SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len);
+
+	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
+
+	if (rtlpriv->dm.useramask) {
+		SET_TX_DESC_RATE_ID(pdesc, ptcdesc->ratr_index);
+		SET_TX_DESC_MACID(pdesc, ptcdesc->mac_id);
+	} else {
+		SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcdesc->ratr_index);
+		SET_TX_DESC_MACID(pdesc, ptcdesc->ratr_index);
+	}
+
+	if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) {
+		SET_TX_DESC_HWSEQ_EN_8723(pdesc, 1);
+
+		if (!defaultadapter)
+			SET_TX_DESC_HWSEQ_SEL_8723(pdesc, 1);
+	}
+
+	SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1));
+
+	if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
+	    is_broadcast_ether_addr(ieee80211_get_DA(hdr))) {
+		SET_TX_DESC_BMC(pdesc, 1);
+	}
+
+	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n");
+}
+
+void rtl8723ae_tx_fill_cmddesc(struct ieee80211_hw *hw,
+			      u8 *pdesc, bool firstseg,
+			      bool lastseg, struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+	u8 fw_queue = QSLT_BEACON;
+	dma_addr_t mapping = pci_map_single(rtlpci->pdev,
+					    skb->data, skb->len,
+					    PCI_DMA_TODEVICE);
+	__le16 fc = hdr->frame_control;
+
+	CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE);
+
+	if (firstseg)
+		SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
+
+	SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M);
+
+	SET_TX_DESC_SEQ(pdesc, 0);
+
+	SET_TX_DESC_LINIP(pdesc, 0);
+
+	SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue);
+
+	SET_TX_DESC_FIRST_SEG(pdesc, 1);
+	SET_TX_DESC_LAST_SEG(pdesc, 1);
+
+	SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len));
+
+	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
+
+	SET_TX_DESC_RATE_ID(pdesc, 7);
+	SET_TX_DESC_MACID(pdesc, 0);
+
+	SET_TX_DESC_OWN(pdesc, 1);
+
+	SET_TX_DESC_PKT_SIZE((u8 *) pdesc, (u16) (skb->len));
+
+	SET_TX_DESC_FIRST_SEG(pdesc, 1);
+	SET_TX_DESC_LAST_SEG(pdesc, 1);
+
+	SET_TX_DESC_OFFSET(pdesc, 0x20);
+
+	SET_TX_DESC_USE_RATE(pdesc, 1);
+
+	if (!ieee80211_is_data_qos(fc)) {
+		SET_TX_DESC_HWSEQ_EN_8723(pdesc, 1);
+		/* SET_TX_DESC_HWSEQ_EN(pdesc, 1); */
+		/* SET_TX_DESC_PKT_ID(pdesc, 8); */
+	}
+
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
+		      "H2C Tx Cmd Content\n",
+		      pdesc, TX_DESC_SIZE);
+}
+
+void rtl8723ae_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
+{
+	if (istx == true) {
+		switch (desc_name) {
+		case HW_DESC_OWN:
+			SET_TX_DESC_OWN(pdesc, 1);
+			break;
+		case HW_DESC_TX_NEXTDESC_ADDR:
+			SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val);
+			break;
+		default:
+			RT_ASSERT(false, "ERR txdesc :%d not process\n",
+				  desc_name);
+			break;
+		}
+	} else {
+		switch (desc_name) {
+		case HW_DESC_RXOWN:
+			SET_RX_DESC_OWN(pdesc, 1);
+			break;
+		case HW_DESC_RXBUFF_ADDR:
+			SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val);
+			break;
+		case HW_DESC_RXPKT_LEN:
+			SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val);
+			break;
+		case HW_DESC_RXERO:
+			SET_RX_DESC_EOR(pdesc, 1);
+			break;
+		default:
+			RT_ASSERT(false, "ERR rxdesc :%d not process\n",
+				  desc_name);
+			break;
+		}
+	}
+}
+
+u32 rtl8723ae_get_desc(u8 *pdesc, bool istx, u8 desc_name)
+{
+	u32 ret = 0;
+
+	if (istx == true) {
+		switch (desc_name) {
+		case HW_DESC_OWN:
+			ret = GET_TX_DESC_OWN(pdesc);
+			break;
+		case HW_DESC_TXBUFF_ADDR:
+			ret = GET_TX_DESC_TX_BUFFER_ADDRESS(pdesc);
+			break;
+		default:
+			RT_ASSERT(false, "ERR txdesc :%d not process\n",
+				  desc_name);
+			break;
+		}
+	} else {
+		switch (desc_name) {
+		case HW_DESC_OWN:
+			ret = GET_RX_DESC_OWN(pdesc);
+			break;
+		case HW_DESC_RXPKT_LEN:
+			ret = GET_RX_DESC_PKT_LEN(pdesc);
+			break;
+		default:
+			RT_ASSERT(false, "ERR rxdesc :%d not process\n",
+				  desc_name);
+			break;
+		}
+	}
+	return ret;
+}
+
+void rtl8723ae_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	if (hw_queue == BEACON_QUEUE) {
+		rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4));
+	} else {
+		rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG,
+			       BIT(0) << (hw_queue));
+	}
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.h b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.h
new file mode 100644
index 0000000..ad05b54
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.h
@@ -0,0 +1,725 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL8723E_TRX_H__
+#define __RTL8723E_TRX_H__
+
+#define TX_DESC_SIZE				64
+#define TX_DESC_AGGR_SUBFRAME_SIZE		32
+
+#define RX_DESC_SIZE				32
+#define RX_DRV_INFO_SIZE_UNIT			8
+
+#define	TX_DESC_NEXT_DESC_OFFSET		40
+#define USB_HWDESC_HEADER_LEN			32
+#define CRCLENGTH				4
+
+#define SET_TX_DESC_PKT_SIZE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val)
+#define SET_TX_DESC_OFFSET(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val)
+#define SET_TX_DESC_BMC(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val)
+#define SET_TX_DESC_HTC(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val)
+#define SET_TX_DESC_LAST_SEG(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val)
+#define SET_TX_DESC_FIRST_SEG(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val)
+#define SET_TX_DESC_LINIP(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val)
+#define SET_TX_DESC_NO_ACM(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val)
+#define SET_TX_DESC_GF(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val)
+#define SET_TX_DESC_OWN(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val)
+
+#define GET_TX_DESC_PKT_SIZE(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 0, 16)
+#define GET_TX_DESC_OFFSET(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 16, 8)
+#define GET_TX_DESC_BMC(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 24, 1)
+#define GET_TX_DESC_HTC(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 25, 1)
+#define GET_TX_DESC_LAST_SEG(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 26, 1)
+#define GET_TX_DESC_FIRST_SEG(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 27, 1)
+#define GET_TX_DESC_LINIP(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 28, 1)
+#define GET_TX_DESC_NO_ACM(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 29, 1)
+#define GET_TX_DESC_GF(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc, 30, 1)
+#define GET_TX_DESC_OWN(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 31, 1)
+
+#define SET_TX_DESC_MACID(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 5, __val)
+#define SET_TX_DESC_AGG_BREAK(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 5, 1, __val)
+#define SET_TX_DESC_BK(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 6, 1, __val)
+#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 7, 1, __val)
+#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val)
+#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val)
+#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val)
+#define SET_TX_DESC_PIFS(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val)
+#define SET_TX_DESC_RATE_ID(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 4, __val)
+#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 20, 1, __val)
+#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val)
+#define SET_TX_DESC_SEC_TYPE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val)
+#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 8, __val)
+
+#define GET_TX_DESC_MACID(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 0, 5)
+#define GET_TX_DESC_AGG_ENABLE(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+4, 5, 1)
+#define GET_TX_DESC_AGG_BREAK(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 6, 1)
+#define GET_TX_DESC_RDG_ENABLE(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+4, 7, 1)
+#define GET_TX_DESC_QUEUE_SEL(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 8, 5)
+#define GET_TX_DESC_RDG_NAV_EXT(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+4, 13, 1)
+#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+4, 14, 1)
+#define GET_TX_DESC_PIFS(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 15, 1)
+#define GET_TX_DESC_RATE_ID(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 16, 4)
+#define GET_TX_DESC_NAV_USE_HDR(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+4, 20, 1)
+#define GET_TX_DESC_EN_DESC_ID(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+4, 21, 1)
+#define GET_TX_DESC_SEC_TYPE(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 22, 2)
+#define GET_TX_DESC_PKT_OFFSET(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+4, 24, 8)
+
+#define SET_TX_DESC_RTS_RC(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 6, __val)
+#define SET_TX_DESC_DATA_RC(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 6, 6, __val)
+#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val)
+#define SET_TX_DESC_MORE_FRAG(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val)
+#define SET_TX_DESC_RAW(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val)
+#define SET_TX_DESC_CCX(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val)
+#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val)
+#define SET_TX_DESC_ANTSEL_A(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 1, __val)
+#define SET_TX_DESC_ANTSEL_B(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 25, 1, __val)
+#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 26, 2, __val)
+#define SET_TX_DESC_TX_ANTL(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 28, 2, __val)
+#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+8, 30, 2, __val)
+
+#define GET_TX_DESC_RTS_RC(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 0, 6)
+#define GET_TX_DESC_DATA_RC(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 6, 6)
+#define GET_TX_DESC_BAR_RTY_TH(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+8, 14, 2)
+#define GET_TX_DESC_MORE_FRAG(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 17, 1)
+#define GET_TX_DESC_RAW(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 18, 1)
+#define GET_TX_DESC_CCX(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 19, 1)
+#define GET_TX_DESC_AMPDU_DENSITY(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+8, 20, 3)
+#define GET_TX_DESC_ANTSEL_A(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 24, 1)
+#define GET_TX_DESC_ANTSEL_B(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 25, 1)
+#define GET_TX_DESC_TX_ANT_CCK(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+8, 26, 2)
+#define GET_TX_DESC_TX_ANTL(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 28, 2)
+#define GET_TX_DESC_TX_ANT_HT(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 30, 2)
+
+#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 8, __val)
+#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 8, __val)
+#define SET_TX_DESC_SEQ(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 12, __val)
+#define SET_TX_DESC_PKT_ID(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+12, 28, 4, __val)
+
+#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+12, 0, 8)
+#define GET_TX_DESC_TAIL_PAGE(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+12, 8, 8)
+#define GET_TX_DESC_SEQ(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+12, 16, 12)
+#define GET_TX_DESC_PKT_ID(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+12, 28, 4)
+
+/* For RTL8723 */
+#define SET_TX_DESC_TRIGGER_INT(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+12, 30, 1, __val)
+#define SET_TX_DESC_HWSEQ_EN_8723(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+12, 31, 1, __val)
+#define SET_TX_DESC_HWSEQ_SEL_8723(__pTxDesc, __Value)	\
+	SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 6, 2, __Value)
+
+#define SET_TX_DESC_RTS_RATE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 5, __val)
+#define SET_TX_DESC_AP_DCFE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 5, 1, __val)
+#define SET_TX_DESC_QOS(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 6, 1, __val)
+#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 7, 1, __val)
+#define SET_TX_DESC_USE_RATE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 1, __val)
+#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 9, 1, __val)
+#define SET_TX_DESC_DISABLE_FB(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 10, 1, __val)
+#define SET_TX_DESC_CTS2SELF(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 11, 1, __val)
+#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 12, 1, __val)
+#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 1, __val)
+#define SET_TX_DESC_PORT_ID(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 14, 1, __val)
+#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 1, __val)
+#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 19, 1, __val)
+#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 20, 2, __val)
+#define SET_TX_DESC_TX_STBC(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 22, 2, __val)
+#define SET_TX_DESC_DATA_SHORT(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 1, __val)
+#define SET_TX_DESC_DATA_BW(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 25, 1, __val)
+#define SET_TX_DESC_RTS_SHORT(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 26, 1, __val)
+#define SET_TX_DESC_RTS_BW(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 27, 1, __val)
+#define SET_TX_DESC_RTS_SC(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 28, 2, __val)
+#define SET_TX_DESC_RTS_STBC(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val)
+
+#define GET_TX_DESC_RTS_RATE(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 0, 5)
+#define GET_TX_DESC_AP_DCFE(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 5, 1)
+#define GET_TX_DESC_QOS(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 6, 1)
+#define GET_TX_DESC_HWSEQ_EN(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 7, 1)
+#define GET_TX_DESC_USE_RATE(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 8, 1)
+#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+16, 9, 1)
+#define GET_TX_DESC_DISABLE_FB(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+16, 10, 1)
+#define GET_TX_DESC_CTS2SELF(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 11, 1)
+#define GET_TX_DESC_RTS_ENABLE(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+16, 12, 1)
+#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+16, 13, 1)
+#define GET_TX_DESC_PORT_ID(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 14, 1)
+#define GET_TX_DESC_WAIT_DCTS(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 18, 1)
+#define GET_TX_DESC_CTS2AP_EN(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 19, 1)
+#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+16, 20, 2)
+#define GET_TX_DESC_TX_STBC(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 22, 2)
+#define GET_TX_DESC_DATA_SHORT(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+16, 24, 1)
+#define GET_TX_DESC_DATA_BW(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 25, 1)
+#define GET_TX_DESC_RTS_SHORT(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 26, 1)
+#define GET_TX_DESC_RTS_BW(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 27, 1)
+#define GET_TX_DESC_RTS_SC(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 28, 2)
+#define GET_TX_DESC_RTS_STBC(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 30, 2)
+
+#define SET_TX_DESC_TX_RATE(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 6, __val)
+#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+20, 6, 1, __val)
+#define SET_TX_DESC_CCX_TAG(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val)
+#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 5, __val)
+#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val)
+#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+20, 17, 1, __val)
+#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+20, 18, 6, __val)
+#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 8, __val)
+
+#define GET_TX_DESC_TX_RATE(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+20, 0, 6)
+#define GET_TX_DESC_DATA_SHORTGI(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+20, 6, 1)
+#define GET_TX_DESC_CCX_TAG(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+20, 7, 1)
+#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc)	\
+	LE_BITS_TO_4BYTE(__pdesc+20, 8, 5)
+#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+20, 13, 4)
+#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc)	\
+	LE_BITS_TO_4BYTE(__pdesc+20, 17, 1)
+#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+20, 18, 6)
+#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+20, 24, 8)
+
+#define SET_TX_DESC_TXAGC_A(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 5, __val)
+#define SET_TX_DESC_TXAGC_B(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 5, 5, __val)
+#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 10, 1, __val)
+#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 11, 5, __val)
+#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 4, __val)
+#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 20, 4, __val)
+#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 24, 4, __val)
+#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val)\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 28, 4, __val)
+
+#define GET_TX_DESC_TXAGC_A(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+24, 0, 5)
+#define GET_TX_DESC_TXAGC_B(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+24, 5, 5)
+#define GET_TX_DESC_USE_MAX_LEN(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+24, 10, 1)
+#define GET_TX_DESC_MAX_AGG_NUM(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+24, 11, 5)
+#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+24, 16, 4)
+#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+24, 20, 4)
+#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+24, 24, 4)
+#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+24, 28, 4)
+
+#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val)
+#define SET_TX_DESC_MCSG4_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+28, 16, 4, __val)
+#define SET_TX_DESC_MCSG5_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+28, 20, 4, __val)
+#define SET_TX_DESC_MCSG6_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+28, 24, 4, __val)
+#define SET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+28, 28, 4, __val)
+
+#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+28, 0, 16)
+#define GET_TX_DESC_MCSG4_MAX_LEN(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+28, 16, 4)
+#define GET_TX_DESC_MCSG5_MAX_LEN(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+28, 20, 4)
+#define GET_TX_DESC_MCSG6_MAX_LEN(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+28, 24, 4)
+#define GET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+28, 28, 4)
+
+#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 32, __val)
+#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \
+	SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 32, __val)
+
+#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+32, 0, 32)
+#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc)	\
+	LE_BITS_TO_4BYTE(__pdesc+36, 0, 32)
+
+#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val)	\
+	SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val)
+#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \
+	SET_BITS_TO_LE_4BYTE(__pdesc+44, 0, 32, __val)
+
+#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+40, 0, 32)
+#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc)	\
+	LE_BITS_TO_4BYTE(__pdesc+44, 0, 32)
+
+#define GET_RX_DESC_PKT_LEN(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 0, 14)
+#define GET_RX_DESC_CRC32(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 14, 1)
+#define GET_RX_DESC_ICV(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 15, 1)
+#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc, 16, 4)
+#define GET_RX_DESC_SECURITY(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 20, 3)
+#define GET_RX_DESC_QOS(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 23, 1)
+#define GET_RX_DESC_SHIFT(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 24, 2)
+#define GET_RX_DESC_PHYST(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 26, 1)
+#define GET_RX_DESC_SWDEC(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 27, 1)
+#define GET_RX_DESC_LS(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc, 28, 1)
+#define GET_RX_DESC_FS(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc, 29, 1)
+#define GET_RX_DESC_EOR(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 30, 1)
+#define GET_RX_DESC_OWN(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc, 31, 1)
+
+#define SET_RX_DESC_PKT_LEN(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val)
+#define SET_RX_DESC_EOR(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val)
+#define SET_RX_DESC_OWN(__pdesc, __val)			\
+	SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val)
+
+#define GET_RX_DESC_MACID(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 0, 5)
+#define GET_RX_DESC_TID(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 5, 4)
+#define GET_RX_DESC_HWRSVD(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 9, 5)
+#define GET_RX_DESC_PAGGR(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 14, 1)
+#define GET_RX_DESC_FAGGR(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 15, 1)
+#define GET_RX_DESC_A1_FIT(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 16, 4)
+#define GET_RX_DESC_A2_FIT(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 20, 4)
+#define GET_RX_DESC_PAM(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 24, 1)
+#define GET_RX_DESC_PWR(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 25, 1)
+#define GET_RX_DESC_MD(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 26, 1)
+#define GET_RX_DESC_MF(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 27, 1)
+#define GET_RX_DESC_TYPE(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+4, 28, 2)
+#define GET_RX_DESC_MC(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 30, 1)
+#define GET_RX_DESC_BC(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+4, 31, 1)
+#define GET_RX_DESC_SEQ(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 0, 12)
+#define GET_RX_DESC_FRAG(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 12, 4)
+#define GET_RX_DESC_NEXT_PKT_LEN(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+8, 16, 14)
+#define GET_RX_DESC_NEXT_IND(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 30, 1)
+#define GET_RX_DESC_RSVD(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+8, 31, 1)
+
+#define GET_RX_DESC_RXMCS(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+12, 0, 6)
+#define GET_RX_DESC_RXHT(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+12, 6, 1)
+#define GET_RX_DESC_SPLCP(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+12, 8, 1)
+#define GET_RX_DESC_BW(__pdesc)				\
+	LE_BITS_TO_4BYTE(__pdesc+12, 9, 1)
+#define GET_RX_DESC_HTC(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+12, 10, 1)
+#define GET_RX_DESC_HWPC_ERR(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+12, 14, 1)
+#define GET_RX_DESC_HWPC_IND(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+12, 15, 1)
+#define GET_RX_DESC_IV0(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+12, 16, 16)
+
+#define GET_RX_DESC_IV1(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+16, 0, 32)
+#define GET_RX_DESC_TSFL(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+20, 0, 32)
+
+#define GET_RX_DESC_BUFF_ADDR(__pdesc)			\
+	LE_BITS_TO_4BYTE(__pdesc+24, 0, 32)
+#define GET_RX_DESC_BUFF_ADDR64(__pdesc)		\
+	LE_BITS_TO_4BYTE(__pdesc+28, 0, 32)
+
+#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val)
+#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val)		\
+	SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val)
+
+#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size)	\
+do {							\
+	if (_size > TX_DESC_NEXT_DESC_OFFSET)		\
+		memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET);	\
+	else						\
+		memset(__pdesc, 0, _size);		\
+} while (0)
+
+#define RTL8723E_RX_HAL_IS_CCK_RATE(rxmcs)		\
+	((rxmcs) == DESC92_RATE1M ||			\
+	 (rxmcs) == DESC92_RATE2M ||			\
+	 (rxmcs) == DESC92_RATE5_5M ||			\
+	 (rxmcs) == DESC92_RATE11M)
+
+struct rx_fwinfo_8723e {
+	u8 gain_trsw[4];
+	u8 pwdb_all;
+	u8 cfosho[4];
+	u8 cfotail[4];
+	char rxevm[2];
+	char rxsnr[4];
+	u8 pdsnr[2];
+	u8 csi_current[2];
+	u8 csi_target[2];
+	u8 sigevm;
+	u8 max_ex_pwr;
+	u8 ex_intf_flag:1;
+	u8 sgi_en:1;
+	u8 rxsc:2;
+	u8 reserve:4;
+} __packed;
+
+struct tx_desc_8723e {
+	u32 pktsize:16;
+	u32 offset:8;
+	u32 bmc:1;
+	u32 htc:1;
+	u32 lastseg:1;
+	u32 firstseg:1;
+	u32 linip:1;
+	u32 noacm:1;
+	u32 gf:1;
+	u32 own:1;
+
+	u32 macid:5;
+	u32 agg_en:1;
+	u32 bk:1;
+	u32 rdg_en:1;
+	u32 queuesel:5;
+	u32 rd_nav_ext:1;
+	u32 lsig_txop_en:1;
+	u32 pifs:1;
+	u32 rateid:4;
+	u32 nav_usehdr:1;
+	u32 en_descid:1;
+	u32 sectype:2;
+	u32 pktoffset:8;
+
+	u32 rts_rc:6;
+	u32 data_rc:6;
+	u32 rsvd0:2;
+	u32 bar_retryht:2;
+	u32 rsvd1:1;
+	u32 morefrag:1;
+	u32 raw:1;
+	u32 ccx:1;
+	u32 ampdudensity:3;
+	u32 rsvd2:1;
+	u32 ant_sela:1;
+	u32 ant_selb:1;
+	u32 txant_cck:2;
+	u32 txant_l:2;
+	u32 txant_ht:2;
+
+	u32 nextheadpage:8;
+	u32 tailpage:8;
+	u32 seq:12;
+	u32 pktid:4;
+
+	u32 rtsrate:5;
+	u32 apdcfe:1;
+	u32 qos:1;
+	u32 hwseq_enable:1;
+	u32 userrate:1;
+	u32 dis_rtsfb:1;
+	u32 dis_datafb:1;
+	u32 cts2self:1;
+	u32 rts_en:1;
+	u32 hwrts_en:1;
+	u32 portid:1;
+	u32 rsvd3:3;
+	u32 waitdcts:1;
+	u32 cts2ap_en:1;
+	u32 txsc:2;
+	u32 stbc:2;
+	u32 txshort:1;
+	u32 txbw:1;
+	u32 rtsshort:1;
+	u32 rtsbw:1;
+	u32 rtssc:2;
+	u32 rtsstbc:2;
+
+	u32 txrate:6;
+	u32 shortgi:1;
+	u32 ccxt:1;
+	u32 txrate_fb_lmt:5;
+	u32 rtsrate_fb_lmt:4;
+	u32 retrylmt_en:1;
+	u32 txretrylmt:6;
+	u32 usb_txaggnum:8;
+
+	u32 txagca:5;
+	u32 txagcb:5;
+	u32 usemaxlen:1;
+	u32 maxaggnum:5;
+	u32 mcsg1maxlen:4;
+	u32 mcsg2maxlen:4;
+	u32 mcsg3maxlen:4;
+	u32 mcs7sgimaxlen:4;
+
+	u32 txbuffersize:16;
+	u32 mcsg4maxlen:4;
+	u32 mcsg5maxlen:4;
+	u32 mcsg6maxlen:4;
+	u32 mcsg15sgimaxlen:4;
+
+	u32 txbuffaddr;
+	u32 txbufferaddr64;
+	u32 nextdescaddress;
+	u32 nextdescaddress64;
+
+	u32 reserve_pass_pcie_mm_limit[4];
+} __packed;
+
+struct rx_desc_8723e {
+	u32 length:14;
+	u32 crc32:1;
+	u32 icverror:1;
+	u32 drv_infosize:4;
+	u32 security:3;
+	u32 qos:1;
+	u32 shift:2;
+	u32 phystatus:1;
+	u32 swdec:1;
+	u32 lastseg:1;
+	u32 firstseg:1;
+	u32 eor:1;
+	u32 own:1;
+
+	u32 macid:5;
+	u32 tid:4;
+	u32 hwrsvd:5;
+	u32 paggr:1;
+	u32 faggr:1;
+	u32 a1_fit:4;
+	u32 a2_fit:4;
+	u32 pam:1;
+	u32 pwr:1;
+	u32 moredata:1;
+	u32 morefrag:1;
+	u32 type:2;
+	u32 mc:1;
+	u32 bc:1;
+
+	u32 seq:12;
+	u32 frag:4;
+	u32 nextpktlen:14;
+	u32 nextind:1;
+	u32 rsvd:1;
+
+	u32 rxmcs:6;
+	u32 rxht:1;
+	u32 amsdu:1;
+	u32 splcp:1;
+	u32 bandwidth:1;
+	u32 htc:1;
+	u32 tcpchk_rpt:1;
+	u32 ipcchk_rpt:1;
+	u32 tcpchk_valid:1;
+	u32 hwpcerr:1;
+	u32 hwpcind:1;
+	u32 iv0:16;
+
+	u32 iv1;
+
+	u32 tsfl;
+
+	u32 bufferaddress;
+	u32 bufferaddress64;
+
+} __packed;
+
+void rtl8723ae_tx_fill_desc(struct ieee80211_hw *hw,
+			    struct ieee80211_hdr *hdr, u8 *pdesc_tx,
+			    struct ieee80211_tx_info *info,
+			    struct ieee80211_sta *sta,
+			    struct sk_buff *skb, u8 hw_queue,
+			    struct rtl_tcb_desc *ptcb_desc);
+bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw,
+			     struct rtl_stats *status,
+			     struct ieee80211_rx_status *rx_status,
+			     u8 *pdesc, struct sk_buff *skb);
+void rtl8723ae_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val);
+u32 rtl8723ae_get_desc(u8 *pdesc, bool istx, u8 desc_name);
+void rtl8723ae_tx_polling(struct ieee80211_hw *hw, u8 hw_queue);
+void rtl8723ae_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
+			       bool b_firstseg, bool b_lastseg,
+			       struct sk_buff *skb);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/stats.c b/drivers/net/wireless/rtlwifi/stats.c
new file mode 100644
index 0000000..8ed3174
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/stats.c
@@ -0,0 +1,268 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+#include "wifi.h"
+#include "stats.h"
+#include <linux/export.h>
+
+u8 rtl_query_rxpwrpercentage(char antpower)
+{
+	if ((antpower <= -100) || (antpower >= 20))
+		return 0;
+	else if (antpower >= 0)
+		return 100;
+	else
+		return 100 + antpower;
+}
+EXPORT_SYMBOL(rtl_query_rxpwrpercentage);
+
+u8 rtl_evm_db_to_percentage(char value)
+{
+	char ret_val;
+	ret_val = value;
+
+	if (ret_val >= 0)
+		ret_val = 0;
+	if (ret_val <= -33)
+		ret_val = -33;
+	ret_val = 0 - ret_val;
+	ret_val *= 3;
+	if (ret_val == 99)
+		ret_val = 100;
+
+	return ret_val;
+}
+EXPORT_SYMBOL(rtl_evm_db_to_percentage);
+
+static long rtl_translate_todbm(struct ieee80211_hw *hw,
+				u8 signal_strength_index)
+{
+	long signal_power;
+
+	signal_power = (long)((signal_strength_index + 1) >> 1);
+	signal_power -= 95;
+	return signal_power;
+}
+
+long rtl_signal_scale_mapping(struct ieee80211_hw *hw, long currsig)
+{
+	long retsig;
+
+	if (currsig >= 61 && currsig <= 100)
+		retsig = 90 + ((currsig - 60) / 4);
+	else if (currsig >= 41 && currsig <= 60)
+		retsig = 78 + ((currsig - 40) / 2);
+	else if (currsig >= 31 && currsig <= 40)
+		retsig = 66 + (currsig - 30);
+	else if (currsig >= 21 && currsig <= 30)
+		retsig = 54 + (currsig - 20);
+	else if (currsig >= 5 && currsig <= 20)
+		retsig = 42 + (((currsig - 5) * 2) / 3);
+	else if (currsig == 4)
+		retsig = 36;
+	else if (currsig == 3)
+		retsig = 27;
+	else if (currsig == 2)
+		retsig = 18;
+	else if (currsig == 1)
+		retsig = 9;
+	else
+		retsig = currsig;
+
+	return retsig;
+}
+EXPORT_SYMBOL(rtl_signal_scale_mapping);
+
+static void rtl_process_ui_rssi(struct ieee80211_hw *hw,
+				struct rtl_stats *pstatus)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u8 rfpath;
+	u32 last_rssi, tmpval;
+
+	rtlpriv->stats.rssi_calculate_cnt++;
+
+	if (rtlpriv->stats.ui_rssi.total_num++ >= PHY_RSSI_SLID_WIN_MAX) {
+		rtlpriv->stats.ui_rssi.total_num = PHY_RSSI_SLID_WIN_MAX;
+		last_rssi = rtlpriv->stats.ui_rssi.elements[
+			rtlpriv->stats.ui_rssi.index];
+		rtlpriv->stats.ui_rssi.total_val -= last_rssi;
+	}
+	rtlpriv->stats.ui_rssi.total_val += pstatus->signalstrength;
+	rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.index++] =
+	    pstatus->signalstrength;
+	if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
+		rtlpriv->stats.ui_rssi.index = 0;
+	tmpval = rtlpriv->stats.ui_rssi.total_val /
+		rtlpriv->stats.ui_rssi.total_num;
+	rtlpriv->stats.signal_strength = rtl_translate_todbm(hw,
+		(u8) tmpval);
+	pstatus->rssi = rtlpriv->stats.signal_strength;
+
+	if (pstatus->is_cck)
+		return;
+
+	for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
+	     rfpath++) {
+		if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
+			rtlpriv->stats.rx_rssi_percentage[rfpath] =
+			    pstatus->rx_mimo_signalstrength[rfpath];
+
+		}
+		if (pstatus->rx_mimo_signalstrength[rfpath] >
+		    rtlpriv->stats.rx_rssi_percentage[rfpath]) {
+			rtlpriv->stats.rx_rssi_percentage[rfpath] =
+			    ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
+			      (RX_SMOOTH_FACTOR - 1)) +
+			     (pstatus->rx_mimo_signalstrength[rfpath])) /
+			    (RX_SMOOTH_FACTOR);
+			rtlpriv->stats.rx_rssi_percentage[rfpath] =
+			    rtlpriv->stats.rx_rssi_percentage[rfpath] + 1;
+		} else {
+			rtlpriv->stats.rx_rssi_percentage[rfpath] =
+			    ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
+			      (RX_SMOOTH_FACTOR - 1)) +
+			     (pstatus->rx_mimo_signalstrength[rfpath])) /
+			    (RX_SMOOTH_FACTOR);
+		}
+	}
+}
+
+static void rtl_update_rxsignalstatistics(struct ieee80211_hw *hw,
+					  struct rtl_stats *pstatus)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int weighting = 0;
+
+	if (rtlpriv->stats.recv_signal_power == 0)
+		rtlpriv->stats.recv_signal_power = pstatus->recvsignalpower;
+	if (pstatus->recvsignalpower > rtlpriv->stats.recv_signal_power)
+		weighting = 5;
+	else if (pstatus->recvsignalpower < rtlpriv->stats.recv_signal_power)
+		weighting = (-5);
+	rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power *
+		5 + pstatus->recvsignalpower + weighting) / 6;
+}
+
+static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_sta_info *drv_priv = NULL;
+	struct ieee80211_sta *sta = NULL;
+	long undec_sm_pwdb;
+
+	rcu_read_lock();
+	if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
+		sta = rtl_find_sta(hw, pstatus->psaddr);
+
+	/* adhoc or ap mode */
+	if (sta) {
+		drv_priv = (struct rtl_sta_info *) sta->drv_priv;
+		undec_sm_pwdb = drv_priv->rssi_stat.undec_sm_pwdb;
+	} else {
+		undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
+	}
+
+	if (undec_sm_pwdb < 0)
+		undec_sm_pwdb = pstatus->rx_pwdb_all;
+	if (pstatus->rx_pwdb_all > (u32) undec_sm_pwdb) {
+		undec_sm_pwdb = (((undec_sm_pwdb) *
+		      (RX_SMOOTH_FACTOR - 1)) +
+		     (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
+		undec_sm_pwdb = undec_sm_pwdb + 1;
+	} else {
+		undec_sm_pwdb = (((undec_sm_pwdb) * (RX_SMOOTH_FACTOR - 1)) +
+		     (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
+	}
+
+	if (sta) {
+		drv_priv->rssi_stat.undec_sm_pwdb = undec_sm_pwdb;
+	} else {
+		rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
+	}
+	rcu_read_unlock();
+
+	rtl_update_rxsignalstatistics(hw, pstatus);
+}
+
+static void rtl_process_ui_link_quality(struct ieee80211_hw *hw,
+					struct rtl_stats *pstatus)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 last_evm, n_stream, tmpval;
+
+	if (pstatus->signalquality == 0)
+		return;
+
+	if (rtlpriv->stats.ui_link_quality.total_num++ >=
+	    PHY_LINKQUALITY_SLID_WIN_MAX) {
+		rtlpriv->stats.ui_link_quality.total_num =
+		    PHY_LINKQUALITY_SLID_WIN_MAX;
+		last_evm = rtlpriv->stats.ui_link_quality.elements[
+			rtlpriv->stats.ui_link_quality.index];
+		rtlpriv->stats.ui_link_quality.total_val -= last_evm;
+	}
+	rtlpriv->stats.ui_link_quality.total_val += pstatus->signalquality;
+	rtlpriv->stats.ui_link_quality.elements[
+		rtlpriv->stats.ui_link_quality.index++] =
+						 pstatus->signalquality;
+	if (rtlpriv->stats.ui_link_quality.index >=
+	    PHY_LINKQUALITY_SLID_WIN_MAX)
+		rtlpriv->stats.ui_link_quality.index = 0;
+	tmpval = rtlpriv->stats.ui_link_quality.total_val /
+	    rtlpriv->stats.ui_link_quality.total_num;
+	rtlpriv->stats.signal_quality = tmpval;
+	rtlpriv->stats.last_sigstrength_inpercent = tmpval;
+	for (n_stream = 0; n_stream < 2; n_stream++) {
+		if (pstatus->rx_mimo_sig_qual[n_stream] != -1) {
+			if (rtlpriv->stats.rx_evm_percentage[n_stream] == 0) {
+				rtlpriv->stats.rx_evm_percentage[n_stream] =
+				    pstatus->rx_mimo_sig_qual[n_stream];
+			}
+			rtlpriv->stats.rx_evm_percentage[n_stream] =
+			    ((rtlpriv->stats.rx_evm_percentage[n_stream]
+			      * (RX_SMOOTH_FACTOR - 1)) +
+			     (pstatus->rx_mimo_sig_qual[n_stream] * 1)) /
+			    (RX_SMOOTH_FACTOR);
+		}
+	}
+}
+
+void rtl_process_phyinfo(struct ieee80211_hw *hw, u8 *buffer,
+	struct rtl_stats *pstatus)
+{
+
+	if (!pstatus->packet_matchbssid)
+		return;
+
+	rtl_process_ui_rssi(hw, pstatus);
+	rtl_process_pwdb(hw, pstatus);
+	rtl_process_ui_link_quality(hw, pstatus);
+}
+EXPORT_SYMBOL(rtl_process_phyinfo);
diff --git a/drivers/net/wireless/rtlwifi/stats.h b/drivers/net/wireless/rtlwifi/stats.h
new file mode 100644
index 0000000..0dbdc52
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/stats.h
@@ -0,0 +1,46 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2012  Realtek Corporation.
+ *
+ * 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL_STATS_H__
+#define __RTL_STATS_H__
+
+#define	PHY_RSSI_SLID_WIN_MAX			100
+#define	PHY_LINKQUALITY_SLID_WIN_MAX		20
+#define	PHY_BEACON_RSSI_SLID_WIN_MAX		10
+
+/* Rx smooth factor */
+#define	RX_SMOOTH_FACTOR			20
+
+u8 rtl_query_rxpwrpercentage(char antpower);
+u8 rtl_evm_db_to_percentage(char value);
+long rtl_signal_scale_mapping(struct ieee80211_hw *hw, long currsig);
+void rtl_process_phyinfo(struct ieee80211_hw *hw, u8 *buffer,
+	struct rtl_stats *pstatus);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index f1b6bc6..21a5f4f 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -198,15 +198,15 @@ struct bb_reg_def {
 	u32 rftxgain_stage;
 	u32 rfhssi_para1;
 	u32 rfhssi_para2;
-	u32 rfswitch_control;
+	u32 rfsw_ctrl;
 	u32 rfagc_control1;
 	u32 rfagc_control2;
-	u32 rfrxiq_imbalance;
+	u32 rfrxiq_imbal;
 	u32 rfrx_afe;
-	u32 rftxiq_imbalance;
+	u32 rftxiq_imbal;
 	u32 rftx_afe;
-	u32 rflssi_readback;
-	u32 rflssi_readbackpi;
+	u32 rf_rb;		/* rflssi_readback */
+	u32 rf_rbpi;		/* rflssi_readbackpi */
 };
 
 enum io_type {
@@ -350,6 +350,11 @@ enum rt_oem_id {
 	RT_CID_819x_WNC_COREGA = 31,
 	RT_CID_819x_Foxcoon = 32,
 	RT_CID_819x_DELL = 33,
+	RT_CID_819x_PRONETS = 34,
+	RT_CID_819x_Edimax_ASUS = 35,
+	RT_CID_NETGEAR = 36,
+	RT_CID_PLANEX = 37,
+	RT_CID_CC_C = 38,
 };
 
 enum hw_descs {
@@ -505,6 +510,7 @@ enum rtl_var_map {
 	RTL_IMR_ROK,		/*Receive DMA OK Interrupt */
 	RTL_IBSS_INT_MASKS,	/*(RTL_IMR_BcnInt | RTL_IMR_TBDOK |
 				 * RTL_IMR_TBDER) */
+	RTL_IMR_C2HCMD,		/*fw interrupt*/
 
 	/*CCK Rates, TxHT = 0 */
 	RTL_RC_CCK_RATE1M,
@@ -661,6 +667,11 @@ enum ba_action {
 	ACT_DELBA = 2,
 };
 
+enum rt_polarity_ctl {
+	RT_POLARITY_LOW_ACT = 0,
+	RT_POLARITY_HIGH_ACT = 1,
+};
+
 struct octet_string {
 	u8 *octet;
 	u16 length;
@@ -885,7 +896,7 @@ struct rtl_phy {
 	u8 pwrgroup_cnt;
 	u8 cck_high_power;
 	/* MAX_PG_GROUP groups of pwr diff by rates */
-	u32 mcs_txpwrlevel_origoffset[MAX_PG_GROUP][16];
+	u32 mcs_offset[MAX_PG_GROUP][16];
 	u8 default_initialgain[4];
 
 	/* the current Tx power level */
@@ -903,6 +914,8 @@ struct rtl_phy {
 	u8 num_total_rfpath;
 	struct phy_parameters hwparam_tables[MAX_TAB];
 	u16 rf_pathmap;
+
+	enum rt_polarity_ctl polarity_ctl;
 };
 
 #define MAX_TID_COUNT				9
@@ -933,7 +946,7 @@ struct rtl_tid_data {
 };
 
 struct rssi_sta {
-	long undecorated_smoothed_pwdb;
+	long undec_sm_pwdb;
 };
 
 struct rtl_sta_info {
@@ -1042,13 +1055,64 @@ struct rtl_mac {
 	/*QOS & EDCA */
 	struct ieee80211_tx_queue_params edca_param[RTL_MAC80211_NUM_QUEUE];
 	struct rtl_qos_parameters ac[AC_MAX];
+
+	/* counters */
+	u64 last_txok_cnt;
+	u64 last_rxok_cnt;
+	u32 last_bt_edca_ul;
+	u32 last_bt_edca_dl;
+};
+
+struct btdm_8723 {
+	bool all_off;
+	bool agc_table_en;
+	bool adc_back_off_on;
+	bool b2_ant_hid_en;
+	bool low_penalty_rate_adaptive;
+	bool rf_rx_lpf_shrink;
+	bool reject_aggre_pkt;
+	bool tra_tdma_on;
+	u8 tra_tdma_nav;
+	u8 tra_tdma_ant;
+	bool tdma_on;
+	u8 tdma_ant;
+	u8 tdma_nav;
+	u8 tdma_dac_swing;
+	u8 fw_dac_swing_lvl;
+	bool ps_tdma_on;
+	u8 ps_tdma_byte[5];
+	bool pta_on;
+	u32 val_0x6c0;
+	u32 val_0x6c8;
+	u32 val_0x6cc;
+	bool sw_dac_swing_on;
+	u32 sw_dac_swing_lvl;
+	u32 wlan_act_hi;
+	u32 wlan_act_lo;
+	u32 bt_retry_index;
+	bool dec_bt_pwr;
+	bool ignore_wlan_act;
+};
+
+struct bt_coexist_8723 {
+	u32 high_priority_tx;
+	u32 high_priority_rx;
+	u32 low_priority_tx;
+	u32 low_priority_rx;
+	u8 c2h_bt_info;
+	bool c2h_bt_info_req_sent;
+	bool c2h_bt_inquiry_page;
+	u32 bt_inq_page_start_time;
+	u8 bt_retry_cnt;
+	u8 c2h_bt_info_original;
+	u8 bt_inquiry_page_cnt;
+	struct btdm_8723 btdm;
 };
 
 struct rtl_hal {
 	struct ieee80211_hw *hw;
-
+	struct bt_coexist_8723 hal_coex_8723;
 	bool up_first_time;
-	bool first_init;
 	bool being_init_adapter;
 	bool bbrf_ready;
 
@@ -1131,9 +1195,9 @@ struct rtl_security {
 
 struct rtl_dm {
 	/*PHY status for Dynamic Management */
-	long entry_min_undecoratedsmoothed_pwdb;
-	long undecorated_smoothed_pwdb;	/*out dm */
-	long entry_max_undecoratedsmoothed_pwdb;
+	long entry_min_undec_sm_pwdb;
+	long undec_sm_pwdb;	/*out dm */
+	long entry_max_undec_sm_pwdb;
 	bool dm_initialgain_enable;
 	bool dynamic_txpower_enable;
 	bool current_turbo_edca;
@@ -1209,7 +1273,7 @@ struct rtl_efuse {
 	u8 eeprom_pwrlimit_ht40[CHANNEL_GROUP_MAX];
 	u8 eeprom_chnlarea_txpwr_cck[2][CHANNEL_GROUP_MAX_2G];
 	u8 eeprom_chnlarea_txpwr_ht40_1s[2][CHANNEL_GROUP_MAX];
-	u8 eeprom_chnlarea_txpwr_ht40_2sdiif[2][CHANNEL_GROUP_MAX];
+	u8 eprom_chnl_txpwr_ht40_2sdf[2][CHANNEL_GROUP_MAX];
 	u8 txpwrlevel_cck[2][CHANNEL_MAX_NUMBER_2G];
 	u8 txpwrlevel_ht40_1s[2][CHANNEL_MAX_NUMBER];	/*For HT 40MHZ pwr */
 	u8 txpwrlevel_ht40_2s[2][CHANNEL_MAX_NUMBER];	/*For HT 40MHZ pwr */
@@ -1312,6 +1376,7 @@ struct rtl_ps_ctl {
 };
 
 struct rtl_stats {
+	u8 psaddr[ETH_ALEN];
 	u32 mac_time[2];
 	s8 rssi;
 	u8 signal;
@@ -1351,7 +1416,7 @@ struct rtl_stats {
 	bool rx_is40Mhzpacket;
 	u32 rx_pwdb_all;
 	u8 rx_mimo_signalstrength[4];	/*in 0~100 index */
-	s8 rx_mimo_signalquality[2];
+	s8 rx_mimo_sig_qual[2];
 	bool packet_matchbssid;
 	bool is_cck;
 	bool is_ht;
@@ -1503,6 +1568,10 @@ struct rtl_hal_ops {
 	void (*phy_lc_calibrate) (struct ieee80211_hw *hw, bool is2t);
 	void (*phy_set_bw_mode_callback) (struct ieee80211_hw *hw);
 	void (*dm_dynamic_txpower) (struct ieee80211_hw *hw);
+	void (*c2h_command_handle) (struct ieee80211_hw *hw);
+	void (*bt_wifi_media_status_notify) (struct ieee80211_hw *hw,
+					     bool mstate);
+	void (*bt_coex_off_before_lps) (struct ieee80211_hw *hw);
 };
 
 struct rtl_intf_ops {
@@ -1679,7 +1748,7 @@ struct dig_t {
 	u32 rssi_highthresh;
 	u32 fa_lowthresh;
 	u32 fa_highthresh;
-	long last_min_undecorated_pwdb_for_dm;
+	long last_min_undec_pwdb_for_dm;
 	long rssi_highpower_lowthresh;
 	long rssi_highpower_highthresh;
 	u32 recover_cnt;
@@ -1692,15 +1761,15 @@ struct dig_t {
 	u8 dig_twoport_algorithm;
 	u8 dig_dbgmode;
 	u8 dig_slgorithm_switch;
-	u8 cursta_connectstate;
-	u8 presta_connectstate;
-	u8 curmultista_connectstate;
-	char backoff_val;
-	char backoff_val_range_max;
-	char backoff_val_range_min;
+	u8 cursta_cstate;
+	u8 presta_cstate;
+	u8 curmultista_cstate;
+	char back_val;
+	char back_range_max;
+	char back_range_min;
 	u8 rx_gain_range_max;
 	u8 rx_gain_range_min;
-	u8 min_undecorated_pwdb_for_dm;
+	u8 min_undec_pwdb_for_dm;
 	u8 rssi_val_min;
 	u8 pre_cck_pd_state;
 	u8 cur_cck_pd_state;
@@ -1712,10 +1781,10 @@ struct dig_t {
 	u8 forbidden_igi;
 	u8 dig_state;
 	u8 dig_highpwrstate;
-	u8 cur_sta_connectstate;
-	u8 pre_sta_connectstate;
-	u8 cur_ap_connectstate;
-	u8 pre_ap_connectstate;
+	u8 cur_sta_cstate;
+	u8 pre_sta_cstate;
+	u8 cur_ap_cstate;
+	u8 pre_ap_cstate;
 	u8 cur_pd_thstate;
 	u8 pre_pd_thstate;
 	u8 cur_cs_ratiostate;
@@ -1781,9 +1850,22 @@ struct rtl_priv {
 	struct dig_t dm_digtable;
 	struct ps_t dm_pstable;
 
-	/* data buffer pointer for USB reads */
-	__le32 *usb_data;
-	int usb_data_index;
+	/* section shared by individual drivers */
+	union {
+		struct {	/* data buffer pointer for USB reads */
+			__le32 *usb_data;
+			int usb_data_index;
+			bool initialized;
+		};
+		struct {	/* section for 8723ae */
+			bool reg_init;	/* true if regs saved */
+			u32 reg_874;
+			u32 reg_c70;
+			u32 reg_85c;
+			u32 reg_a74;
+			bool bt_operation_on;
+		};
+	};
 
 	/*This must be the last item so
 	   that it points to the data allocated
@@ -1815,6 +1897,7 @@ enum bt_co_type {
 	BT_CSR_BC4 = 3,
 	BT_CSR_BC8 = 4,
 	BT_RTL8756 = 5,
+	BT_RTL8723A = 6,
 };
 
 enum bt_cur_state {
@@ -1846,7 +1929,7 @@ struct bt_coexist_info {
 	u8 eeprom_bt_coexist;
 	u8 eeprom_bt_type;
 	u8 eeprom_bt_ant_num;
-	u8 eeprom_bt_ant_isolation;
+	u8 eeprom_bt_ant_isol;
 	u8 eeprom_bt_radio_shared;
 
 	u8 bt_coexistence;
@@ -1873,13 +1956,27 @@ struct bt_coexist_info {
 
 	bool fw_coexist_all_off;
 	bool sw_coexist_all_off;
-	u32 current_state;
+	bool hw_coexist_all_off;
+	u32 cstate;
 	u32 previous_state;
+	u32 cstate_h;
+	u32 previous_state_h;
+
 	u8 bt_pre_rssi_state;
+	u8 bt_pre_rssi_state1;
 
 	u8 reg_bt_iso;
 	u8 reg_bt_sco;
-
+	bool balance_on;
+	u8 bt_active_zero_cnt;
+	bool cur_bt_disabled;
+	bool pre_bt_disabled;
+
+	u8 bt_profile_case;
+	u8 bt_profile_action;
+	bool bt_busy;
+	bool hold_for_bt_operation;
+	u8 lps_counter;
 };
 
 
diff --git a/drivers/net/wireless/ti/wl1251/rx.c b/drivers/net/wireless/ti/wl1251/rx.c
index 6af3526..23289d4 100644
--- a/drivers/net/wireless/ti/wl1251/rx.c
+++ b/drivers/net/wireless/ti/wl1251/rx.c
@@ -81,7 +81,7 @@ static void wl1251_rx_status(struct wl1251 *wl,
 	status->freq = ieee80211_channel_to_frequency(desc->channel,
 						      status->band);
 
-	status->flag |= RX_FLAG_MACTIME_MPDU;
+	status->flag |= RX_FLAG_MACTIME_START;
 
 	if (desc->flags & RX_DESC_ENCRYPTION_MASK) {
 		status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 25530c8..4f1a05b 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -677,7 +677,7 @@ static void wl12xx_get_vif_count(struct ieee80211_hw *hw,
 	memset(data, 0, sizeof(*data));
 	data->cur_vif = cur_vif;
 
-	ieee80211_iterate_active_interfaces(hw,
+	ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL,
 					    wl12xx_vif_count_iter, data);
 }
 
@@ -3791,7 +3791,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
 
 	/* Handle HT information change */
 	if ((changed & BSS_CHANGED_HT) &&
-	    (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+	    (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) {
 		ret = wl1271_acx_set_ht_information(wl, wlvif,
 					bss_conf->ht_operation_mode);
 		if (ret < 0) {
@@ -3905,7 +3905,8 @@ sta_not_found:
 			u32 rates;
 			int ieoffset;
 			wlvif->aid = bss_conf->aid;
-			wlvif->channel_type = bss_conf->channel_type;
+			wlvif->channel_type =
+				cfg80211_get_chandef_type(&bss_conf->chandef);
 			wlvif->beacon_int = bss_conf->beacon_int;
 			do_join = true;
 			set_assoc = true;
@@ -4071,7 +4072,7 @@ sta_not_found:
 	/* Handle new association with HT. Do this after join. */
 	if (sta_exists) {
 		if ((changed & BSS_CHANGED_HT) &&
-		    (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+		    (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) {
 			ret = wl1271_acx_set_ht_capabilities(wl,
 							     &sta_ht_cap,
 							     true,
@@ -4098,7 +4099,7 @@ sta_not_found:
 
 	/* Handle HT information change. Done after join. */
 	if ((changed & BSS_CHANGED_HT) &&
-	    (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+	    (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) {
 		ret = wl1271_acx_set_ht_information(wl, wlvif,
 					bss_conf->ht_operation_mode);
 		if (ret < 0) {
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index ff306d7..71ab320 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -1155,7 +1155,7 @@ int zd_chip_init_hw(struct zd_chip *chip)
 	if (r)
 		goto out;
 	/* Currently we support IEEE 802.11g for full and high speed USB.
-	 * It might be discussed, whether we should suppport pure b mode for
+	 * It might be discussed, whether we should support pure b mode for
 	 * full speed USB.
 	 */
 	r = set_mandatory_rates(chip, 1);
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index f2d6b78..aab8677 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -666,7 +666,9 @@ static void xen_netbk_rx_action(struct xen_netbk *netbk)
 		return;
 
 	BUG_ON(npo.copy_prod > ARRAY_SIZE(netbk->grant_copy_op));
-	gnttab_batch_copy(netbk->grant_copy_op, npo.copy_prod);
+	ret = HYPERVISOR_grant_table_op(GNTTABOP_copy, &netbk->grant_copy_op,
+					npo.copy_prod);
+	BUG_ON(ret != 0);
 
 	while ((skb = __skb_dequeue(&rxq)) != NULL) {
 		sco = (struct skb_cb_overlay *)skb->cb;
@@ -1489,15 +1491,18 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk)
 static void xen_netbk_tx_action(struct xen_netbk *netbk)
 {
 	unsigned nr_gops;
+	int ret;
 
 	nr_gops = xen_netbk_tx_build_gops(netbk);
 
 	if (nr_gops == 0)
 		return;
-
-	gnttab_batch_copy(netbk->tx_copy_ops, nr_gops);
+	ret = HYPERVISOR_grant_table_op(GNTTABOP_copy,
+					netbk->tx_copy_ops, nr_gops);
+	BUG_ON(ret);
 
 	xen_netbk_tx_submit(netbk);
+
 }
 
 static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx)
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile
index bf05831..36c3590 100644
--- a/drivers/nfc/Makefile
+++ b/drivers/nfc/Makefile
@@ -2,7 +2,7 @@
 # Makefile for nfc devices
 #
 
-obj-$(CONFIG_PN544_HCI_NFC)	+= pn544_hci.o
+obj-$(CONFIG_PN544_HCI_NFC)	+= pn544/
 obj-$(CONFIG_NFC_PN533)		+= pn533.o
 obj-$(CONFIG_NFC_WILINK)	+= nfcwilink.o
 
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 30ae18a..ada681b 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -84,6 +84,10 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
 #define PN533_LISTEN_TIME 2
 
 /* frame definitions */
+#define PN533_NORMAL_FRAME_MAX_LEN 262  /* 6   (PREAMBLE, SOF, LEN, LCS, TFI)
+					   254 (DATA)
+					   2   (DCS, postamble) */
+
 #define PN533_FRAME_TAIL_SIZE 2
 #define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \
 				PN533_FRAME_TAIL_SIZE)
@@ -1166,8 +1170,7 @@ static void pn533_poll_create_mod_list(struct pn533 *dev,
 		pn533_poll_add_mod(dev, PN533_LISTEN_MOD);
 }
 
-static int pn533_start_poll_complete(struct pn533 *dev, void *arg,
-				     u8 *params, int params_len)
+static int pn533_start_poll_complete(struct pn533 *dev, u8 *params, int params_len)
 {
 	struct pn533_poll_response *resp;
 	int rc;
@@ -1305,8 +1308,7 @@ static void pn533_wq_tg_get_data(struct work_struct *work)
 }
 
 #define ATR_REQ_GB_OFFSET 17
-static int pn533_init_target_complete(struct pn533 *dev, void *arg,
-				      u8 *params, int params_len)
+static int pn533_init_target_complete(struct pn533 *dev, u8 *params, int params_len)
 {
 	struct pn533_cmd_init_target_response *resp;
 	u8 frame, comm_mode = NFC_COMM_PASSIVE, *gb;
@@ -1403,9 +1405,9 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg,
 	if (cur_mod->len == 0) {
 		del_timer(&dev->listen_timer);
 
-		return pn533_init_target_complete(dev, arg, params, params_len);
+		return pn533_init_target_complete(dev, params, params_len);
 	} else {
-		rc = pn533_start_poll_complete(dev, arg, params, params_len);
+		rc = pn533_start_poll_complete(dev, params, params_len);
 		if (!rc)
 			return rc;
 	}
@@ -2376,9 +2378,9 @@ static int pn533_probe(struct usb_interface *interface,
 		goto error;
 	}
 
-	dev->in_frame = kmalloc(dev->in_maxlen, GFP_KERNEL);
+	dev->in_frame = kmalloc(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL);
 	dev->in_urb = usb_alloc_urb(0, GFP_KERNEL);
-	dev->out_frame = kmalloc(dev->out_maxlen, GFP_KERNEL);
+	dev->out_frame = kmalloc(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL);
 	dev->out_urb = usb_alloc_urb(0, GFP_KERNEL);
 
 	if (!dev->in_frame || !dev->out_frame ||
diff --git a/drivers/nfc/pn544/Makefile b/drivers/nfc/pn544/Makefile
new file mode 100644
index 0000000..7257338
--- /dev/null
+++ b/drivers/nfc/pn544/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for PN544 HCI based NFC driver
+#
+
+obj-$(CONFIG_PN544_HCI_NFC)	+= pn544_i2c.o
+
+pn544_i2c-y		:= pn544.o i2c.o
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c
new file mode 100644
index 0000000..7da9071
--- /dev/null
+++ b/drivers/nfc/pn544/i2c.c
@@ -0,0 +1,500 @@
+/*
+ * I2C Link Layer for PN544 HCI based Driver
+ *
+ * Copyright (C) 2012  Intel Corporation. All rights reserved.
+ *
+ * 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 that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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/crc-ccitt.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/miscdevice.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <linux/platform_data/pn544.h>
+
+#include <net/nfc/hci.h>
+#include <net/nfc/llc.h>
+
+#include "pn544.h"
+
+#define PN544_I2C_FRAME_HEADROOM 1
+#define PN544_I2C_FRAME_TAILROOM 2
+
+/* framing in HCI mode */
+#define PN544_HCI_I2C_LLC_LEN		1
+#define PN544_HCI_I2C_LLC_CRC		2
+#define PN544_HCI_I2C_LLC_LEN_CRC	(PN544_HCI_I2C_LLC_LEN + \
+					 PN544_HCI_I2C_LLC_CRC)
+#define PN544_HCI_I2C_LLC_MIN_SIZE	(1 + PN544_HCI_I2C_LLC_LEN_CRC)
+#define PN544_HCI_I2C_LLC_MAX_PAYLOAD	29
+#define PN544_HCI_I2C_LLC_MAX_SIZE	(PN544_HCI_I2C_LLC_LEN_CRC + 1 + \
+					 PN544_HCI_I2C_LLC_MAX_PAYLOAD)
+
+static struct i2c_device_id pn544_hci_i2c_id_table[] = {
+	{"pn544", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, pn544_hci_i2c_id_table);
+
+#define PN544_HCI_I2C_DRIVER_NAME "pn544_hci_i2c"
+
+struct pn544_i2c_phy {
+	struct i2c_client *i2c_dev;
+	struct nfc_hci_dev *hdev;
+
+	unsigned int gpio_en;
+	unsigned int gpio_irq;
+	unsigned int gpio_fw;
+	unsigned int en_polarity;
+
+	int powered;
+
+	int hard_fault;		/*
+				 * < 0 if hardware error occured (e.g. i2c err)
+				 * and prevents normal operation.
+				 */
+};
+
+#define I2C_DUMP_SKB(info, skb)					\
+do {								\
+	pr_debug("%s:\n", info);				\
+	print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET,	\
+		       16, 1, (skb)->data, (skb)->len, 0);	\
+} while (0)
+
+static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy)
+{
+	int polarity, retry, ret;
+	char rset_cmd[] = { 0x05, 0xF9, 0x04, 0x00, 0xC3, 0xE5 };
+	int count = sizeof(rset_cmd);
+
+	pr_info(DRIVER_DESC ": %s\n", __func__);
+	dev_info(&phy->i2c_dev->dev, "Detecting nfc_en polarity\n");
+
+	/* Disable fw download */
+	gpio_set_value(phy->gpio_fw, 0);
+
+	for (polarity = 0; polarity < 2; polarity++) {
+		phy->en_polarity = polarity;
+		retry = 3;
+		while (retry--) {
+			/* power off */
+			gpio_set_value(phy->gpio_en, !phy->en_polarity);
+			usleep_range(10000, 15000);
+
+			/* power on */
+			gpio_set_value(phy->gpio_en, phy->en_polarity);
+			usleep_range(10000, 15000);
+
+			/* send reset */
+			dev_dbg(&phy->i2c_dev->dev, "Sending reset cmd\n");
+			ret = i2c_master_send(phy->i2c_dev, rset_cmd, count);
+			if (ret == count) {
+				dev_info(&phy->i2c_dev->dev,
+					 "nfc_en polarity : active %s\n",
+					 (polarity == 0 ? "low" : "high"));
+				goto out;
+			}
+		}
+	}
+
+	dev_err(&phy->i2c_dev->dev,
+		"Could not detect nfc_en polarity, fallback to active high\n");
+
+out:
+	gpio_set_value(phy->gpio_en, !phy->en_polarity);
+}
+
+static int pn544_hci_i2c_enable(void *phy_id)
+{
+	struct pn544_i2c_phy *phy = phy_id;
+
+	pr_info(DRIVER_DESC ": %s\n", __func__);
+
+	gpio_set_value(phy->gpio_fw, 0);
+	gpio_set_value(phy->gpio_en, phy->en_polarity);
+	usleep_range(10000, 15000);
+
+	phy->powered = 1;
+
+	return 0;
+}
+
+static void pn544_hci_i2c_disable(void *phy_id)
+{
+	struct pn544_i2c_phy *phy = phy_id;
+
+	pr_info(DRIVER_DESC ": %s\n", __func__);
+
+	gpio_set_value(phy->gpio_fw, 0);
+	gpio_set_value(phy->gpio_en, !phy->en_polarity);
+	usleep_range(10000, 15000);
+
+	gpio_set_value(phy->gpio_en, phy->en_polarity);
+	usleep_range(10000, 15000);
+
+	gpio_set_value(phy->gpio_en, !phy->en_polarity);
+	usleep_range(10000, 15000);
+
+	phy->powered = 0;
+}
+
+static void pn544_hci_i2c_add_len_crc(struct sk_buff *skb)
+{
+	u16 crc;
+	int len;
+
+	len = skb->len + 2;
+	*skb_push(skb, 1) = len;
+
+	crc = crc_ccitt(0xffff, skb->data, skb->len);
+	crc = ~crc;
+	*skb_put(skb, 1) = crc & 0xff;
+	*skb_put(skb, 1) = crc >> 8;
+}
+
+static void pn544_hci_i2c_remove_len_crc(struct sk_buff *skb)
+{
+	skb_pull(skb, PN544_I2C_FRAME_HEADROOM);
+	skb_trim(skb, PN544_I2C_FRAME_TAILROOM);
+}
+
+/*
+ * Writing a frame must not return the number of written bytes.
+ * It must return either zero for success, or <0 for error.
+ * In addition, it must not alter the skb
+ */
+static int pn544_hci_i2c_write(void *phy_id, struct sk_buff *skb)
+{
+	int r;
+	struct pn544_i2c_phy *phy = phy_id;
+	struct i2c_client *client = phy->i2c_dev;
+
+	if (phy->hard_fault != 0)
+		return phy->hard_fault;
+
+	usleep_range(3000, 6000);
+
+	pn544_hci_i2c_add_len_crc(skb);
+
+	I2C_DUMP_SKB("i2c frame written", skb);
+
+	r = i2c_master_send(client, skb->data, skb->len);
+
+	if (r == -EREMOTEIO) {	/* Retry, chip was in standby */
+		usleep_range(6000, 10000);
+		r = i2c_master_send(client, skb->data, skb->len);
+	}
+
+	if (r >= 0) {
+		if (r != skb->len)
+			r = -EREMOTEIO;
+		else
+			r = 0;
+	}
+
+	pn544_hci_i2c_remove_len_crc(skb);
+
+	return r;
+}
+
+static int check_crc(u8 *buf, int buflen)
+{
+	int len;
+	u16 crc;
+
+	len = buf[0] + 1;
+	crc = crc_ccitt(0xffff, buf, len - 2);
+	crc = ~crc;
+
+	if (buf[len - 2] != (crc & 0xff) || buf[len - 1] != (crc >> 8)) {
+		pr_err(PN544_HCI_I2C_DRIVER_NAME
+		       ": CRC error 0x%x != 0x%x 0x%x\n",
+		       crc, buf[len - 1], buf[len - 2]);
+
+		pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__);
+		print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE,
+			       16, 2, buf, buflen, false);
+		return -EPERM;
+	}
+	return 0;
+}
+
+/*
+ * Reads an shdlc frame and returns it in a newly allocated sk_buff. Guarantees
+ * that i2c bus will be flushed and that next read will start on a new frame.
+ * returned skb contains only LLC header and payload.
+ * returns:
+ * -EREMOTEIO : i2c read error (fatal)
+ * -EBADMSG : frame was incorrect and discarded
+ * -ENOMEM : cannot allocate skb, frame dropped
+ */
+static int pn544_hci_i2c_read(struct pn544_i2c_phy *phy, struct sk_buff **skb)
+{
+	int r;
+	u8 len;
+	u8 tmp[PN544_HCI_I2C_LLC_MAX_SIZE - 1];
+	struct i2c_client *client = phy->i2c_dev;
+
+	r = i2c_master_recv(client, &len, 1);
+	if (r != 1) {
+		dev_err(&client->dev, "cannot read len byte\n");
+		return -EREMOTEIO;
+	}
+
+	if ((len < (PN544_HCI_I2C_LLC_MIN_SIZE - 1)) ||
+	    (len > (PN544_HCI_I2C_LLC_MAX_SIZE - 1))) {
+		dev_err(&client->dev, "invalid len byte\n");
+		r = -EBADMSG;
+		goto flush;
+	}
+
+	*skb = alloc_skb(1 + len, GFP_KERNEL);
+	if (*skb == NULL) {
+		r = -ENOMEM;
+		goto flush;
+	}
+
+	*skb_put(*skb, 1) = len;
+
+	r = i2c_master_recv(client, skb_put(*skb, len), len);
+	if (r != len) {
+		kfree_skb(*skb);
+		return -EREMOTEIO;
+	}
+
+	I2C_DUMP_SKB("i2c frame read", *skb);
+
+	r = check_crc((*skb)->data, (*skb)->len);
+	if (r != 0) {
+		kfree_skb(*skb);
+		r = -EBADMSG;
+		goto flush;
+	}
+
+	skb_pull(*skb, 1);
+	skb_trim(*skb, (*skb)->len - 2);
+
+	usleep_range(3000, 6000);
+
+	return 0;
+
+flush:
+	if (i2c_master_recv(client, tmp, sizeof(tmp)) < 0)
+		r = -EREMOTEIO;
+
+	usleep_range(3000, 6000);
+
+	return r;
+}
+
+/*
+ * Reads an shdlc frame from the chip. This is not as straightforward as it
+ * seems. There are cases where we could loose the frame start synchronization.
+ * The frame format is len-data-crc, and corruption can occur anywhere while
+ * transiting on i2c bus, such that we could read an invalid len.
+ * In order to recover synchronization with the next frame, we must be sure
+ * to read the real amount of data without using the len byte. We do this by
+ * assuming the following:
+ * - the chip will always present only one single complete frame on the bus
+ *   before triggering the interrupt
+ * - the chip will not present a new frame until we have completely read
+ *   the previous one (or until we have handled the interrupt).
+ * The tricky case is when we read a corrupted len that is less than the real
+ * len. We must detect this here in order to determine that we need to flush
+ * the bus. This is the reason why we check the crc here.
+ */
+static irqreturn_t pn544_hci_i2c_irq_thread_fn(int irq, void *phy_id)
+{
+	struct pn544_i2c_phy *phy = phy_id;
+	struct i2c_client *client;
+	struct sk_buff *skb = NULL;
+	int r;
+
+	if (!phy || irq != phy->i2c_dev->irq) {
+		WARN_ON_ONCE(1);
+		return IRQ_NONE;
+	}
+
+	client = phy->i2c_dev;
+	dev_dbg(&client->dev, "IRQ\n");
+
+	if (phy->hard_fault != 0)
+		return IRQ_HANDLED;
+
+	r = pn544_hci_i2c_read(phy, &skb);
+	if (r == -EREMOTEIO) {
+		phy->hard_fault = r;
+
+		nfc_hci_recv_frame(phy->hdev, NULL);
+
+		return IRQ_HANDLED;
+	} else if ((r == -ENOMEM) || (r == -EBADMSG)) {
+		return IRQ_HANDLED;
+	}
+
+	nfc_hci_recv_frame(phy->hdev, skb);
+
+	return IRQ_HANDLED;
+}
+
+static struct nfc_phy_ops i2c_phy_ops = {
+	.write = pn544_hci_i2c_write,
+	.enable = pn544_hci_i2c_enable,
+	.disable = pn544_hci_i2c_disable,
+};
+
+static int __devinit pn544_hci_i2c_probe(struct i2c_client *client,
+				     const struct i2c_device_id *id)
+{
+	struct pn544_i2c_phy *phy;
+	struct pn544_nfc_platform_data *pdata;
+	int r = 0;
+
+	dev_dbg(&client->dev, "%s\n", __func__);
+	dev_dbg(&client->dev, "IRQ: %d\n", client->irq);
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "Need I2C_FUNC_I2C\n");
+		return -ENODEV;
+	}
+
+	phy = kzalloc(sizeof(struct pn544_i2c_phy), GFP_KERNEL);
+	if (!phy) {
+		dev_err(&client->dev,
+			"Cannot allocate memory for pn544 i2c phy.\n");
+		r = -ENOMEM;
+		goto err_phy_alloc;
+	}
+
+	phy->i2c_dev = client;
+	i2c_set_clientdata(client, phy);
+
+	pdata = client->dev.platform_data;
+	if (pdata == NULL) {
+		dev_err(&client->dev, "No platform data\n");
+		r = -EINVAL;
+		goto err_pdata;
+	}
+
+	if (pdata->request_resources == NULL) {
+		dev_err(&client->dev, "request_resources() missing\n");
+		r = -EINVAL;
+		goto err_pdata;
+	}
+
+	r = pdata->request_resources(client);
+	if (r) {
+		dev_err(&client->dev, "Cannot get platform resources\n");
+		goto err_pdata;
+	}
+
+	phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE);
+	phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET);
+	phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ);
+
+	pn544_hci_i2c_platform_init(phy);
+
+	r = request_threaded_irq(client->irq, NULL, pn544_hci_i2c_irq_thread_fn,
+				 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+				 PN544_HCI_I2C_DRIVER_NAME, phy);
+	if (r < 0) {
+		dev_err(&client->dev, "Unable to register IRQ handler\n");
+		goto err_rti;
+	}
+
+	r = pn544_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME,
+			    PN544_I2C_FRAME_HEADROOM, PN544_I2C_FRAME_TAILROOM,
+			    PN544_HCI_I2C_LLC_MAX_PAYLOAD, &phy->hdev);
+	if (r < 0)
+		goto err_hci;
+
+	return 0;
+
+err_hci:
+	free_irq(client->irq, phy);
+
+err_rti:
+	if (pdata->free_resources != NULL)
+		pdata->free_resources();
+
+err_pdata:
+	kfree(phy);
+
+err_phy_alloc:
+	return r;
+}
+
+static __devexit int pn544_hci_i2c_remove(struct i2c_client *client)
+{
+	struct pn544_i2c_phy *phy = i2c_get_clientdata(client);
+	struct pn544_nfc_platform_data *pdata = client->dev.platform_data;
+
+	dev_dbg(&client->dev, "%s\n", __func__);
+
+	pn544_hci_remove(phy->hdev);
+
+	if (phy->powered)
+		pn544_hci_i2c_disable(phy);
+
+	free_irq(client->irq, phy);
+	if (pdata->free_resources)
+		pdata->free_resources();
+
+	kfree(phy);
+
+	return 0;
+}
+
+static struct i2c_driver pn544_hci_i2c_driver = {
+	.driver = {
+		   .name = PN544_HCI_I2C_DRIVER_NAME,
+		  },
+	.probe = pn544_hci_i2c_probe,
+	.id_table = pn544_hci_i2c_id_table,
+	.remove = __devexit_p(pn544_hci_i2c_remove),
+};
+
+static int __init pn544_hci_i2c_init(void)
+{
+	int r;
+
+	pr_debug(DRIVER_DESC ": %s\n", __func__);
+
+	r = i2c_add_driver(&pn544_hci_i2c_driver);
+	if (r) {
+		pr_err(PN544_HCI_I2C_DRIVER_NAME
+		       ": driver registration failed\n");
+		return r;
+	}
+
+	return 0;
+}
+
+static void __exit pn544_hci_i2c_exit(void)
+{
+	i2c_del_driver(&pn544_hci_i2c_driver);
+}
+
+module_init(pn544_hci_i2c_init);
+module_exit(pn544_hci_i2c_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c
new file mode 100644
index 0000000..cc666de
--- /dev/null
+++ b/drivers/nfc/pn544/pn544.c
@@ -0,0 +1,862 @@
+/*
+ * HCI based Driver for NXP PN544 NFC Chip
+ *
+ * Copyright (C) 2012  Intel Corporation. All rights reserved.
+ *
+ * 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 that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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/slab.h>
+
+#include <linux/nfc.h>
+#include <net/nfc/hci.h>
+#include <net/nfc/llc.h>
+
+#include "pn544.h"
+
+/* Timing restrictions (ms) */
+#define PN544_HCI_RESETVEN_TIME		30
+
+#define HCI_MODE 0
+#define FW_MODE 1
+
+enum pn544_state {
+	PN544_ST_COLD,
+	PN544_ST_FW_READY,
+	PN544_ST_READY,
+};
+
+#define FULL_VERSION_LEN 11
+
+/* Proprietary commands */
+#define PN544_WRITE		0x3f
+
+/* Proprietary gates, events, commands and registers */
+
+/* NFC_HCI_RF_READER_A_GATE additional registers and commands */
+#define PN544_RF_READER_A_AUTO_ACTIVATION			0x10
+#define PN544_RF_READER_A_CMD_CONTINUE_ACTIVATION		0x12
+#define PN544_MIFARE_CMD					0x21
+
+/* Commands that apply to all RF readers */
+#define PN544_RF_READER_CMD_PRESENCE_CHECK	0x30
+#define PN544_RF_READER_CMD_ACTIVATE_NEXT	0x32
+
+/* NFC_HCI_ID_MGMT_GATE additional registers */
+#define PN544_ID_MGMT_FULL_VERSION_SW		0x10
+
+#define PN544_RF_READER_ISO15693_GATE		0x12
+
+#define PN544_RF_READER_F_GATE			0x14
+#define PN544_FELICA_ID				0x04
+#define PN544_FELICA_RAW			0x20
+
+#define PN544_RF_READER_JEWEL_GATE		0x15
+#define PN544_JEWEL_RAW_CMD			0x23
+
+#define PN544_RF_READER_NFCIP1_INITIATOR_GATE	0x30
+#define PN544_RF_READER_NFCIP1_TARGET_GATE	0x31
+
+#define PN544_SYS_MGMT_GATE			0x90
+#define PN544_SYS_MGMT_INFO_NOTIFICATION	0x02
+
+#define PN544_POLLING_LOOP_MGMT_GATE		0x94
+#define PN544_DEP_MODE				0x01
+#define PN544_DEP_ATR_REQ			0x02
+#define PN544_DEP_ATR_RES			0x03
+#define PN544_DEP_MERGE				0x0D
+#define PN544_PL_RDPHASES			0x06
+#define PN544_PL_EMULATION			0x07
+#define PN544_PL_NFCT_DEACTIVATED		0x09
+
+#define PN544_SWP_MGMT_GATE			0xA0
+
+#define PN544_NFC_WI_MGMT_GATE			0xA1
+
+#define PN544_HCI_EVT_SND_DATA			0x01
+#define PN544_HCI_EVT_ACTIVATED			0x02
+#define PN544_HCI_EVT_DEACTIVATED		0x03
+#define PN544_HCI_EVT_RCV_DATA			0x04
+#define PN544_HCI_EVT_CONTINUE_MI		0x05
+
+#define PN544_HCI_CMD_ATTREQUEST		0x12
+#define PN544_HCI_CMD_CONTINUE_ACTIVATION	0x13
+
+static struct nfc_hci_gate pn544_gates[] = {
+	{NFC_HCI_ADMIN_GATE, NFC_HCI_INVALID_PIPE},
+	{NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE},
+	{NFC_HCI_ID_MGMT_GATE, NFC_HCI_INVALID_PIPE},
+	{NFC_HCI_LINK_MGMT_GATE, NFC_HCI_INVALID_PIPE},
+	{NFC_HCI_RF_READER_B_GATE, NFC_HCI_INVALID_PIPE},
+	{NFC_HCI_RF_READER_A_GATE, NFC_HCI_INVALID_PIPE},
+	{PN544_SYS_MGMT_GATE, NFC_HCI_INVALID_PIPE},
+	{PN544_SWP_MGMT_GATE, NFC_HCI_INVALID_PIPE},
+	{PN544_POLLING_LOOP_MGMT_GATE, NFC_HCI_INVALID_PIPE},
+	{PN544_NFC_WI_MGMT_GATE, NFC_HCI_INVALID_PIPE},
+	{PN544_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE},
+	{PN544_RF_READER_JEWEL_GATE, NFC_HCI_INVALID_PIPE},
+	{PN544_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE},
+	{PN544_RF_READER_NFCIP1_INITIATOR_GATE, NFC_HCI_INVALID_PIPE},
+	{PN544_RF_READER_NFCIP1_TARGET_GATE, NFC_HCI_INVALID_PIPE}
+};
+
+/* Largest headroom needed for outgoing custom commands */
+#define PN544_CMDS_HEADROOM	2
+
+struct pn544_hci_info {
+	struct nfc_phy_ops *phy_ops;
+	void *phy_id;
+
+	struct nfc_hci_dev *hdev;
+
+	enum pn544_state state;
+
+	struct mutex info_lock;
+
+	int async_cb_type;
+	data_exchange_cb_t async_cb;
+	void *async_cb_context;
+};
+
+static int pn544_hci_open(struct nfc_hci_dev *hdev)
+{
+	struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev);
+	int r = 0;
+
+	mutex_lock(&info->info_lock);
+
+	if (info->state != PN544_ST_COLD) {
+		r = -EBUSY;
+		goto out;
+	}
+
+	r = info->phy_ops->enable(info->phy_id);
+
+	if (r == 0)
+		info->state = PN544_ST_READY;
+
+out:
+	mutex_unlock(&info->info_lock);
+	return r;
+}
+
+static void pn544_hci_close(struct nfc_hci_dev *hdev)
+{
+	struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	mutex_lock(&info->info_lock);
+
+	if (info->state == PN544_ST_COLD)
+		goto out;
+
+	info->phy_ops->disable(info->phy_id);
+
+	info->state = PN544_ST_COLD;
+
+out:
+	mutex_unlock(&info->info_lock);
+}
+
+static int pn544_hci_ready(struct nfc_hci_dev *hdev)
+{
+	struct sk_buff *skb;
+	static struct hw_config {
+		u8 adr[2];
+		u8 value;
+	} hw_config[] = {
+		{{0x9f, 0x9a}, 0x00},
+
+		{{0x98, 0x10}, 0xbc},
+
+		{{0x9e, 0x71}, 0x00},
+
+		{{0x98, 0x09}, 0x00},
+
+		{{0x9e, 0xb4}, 0x00},
+
+		{{0x9e, 0xd9}, 0xff},
+		{{0x9e, 0xda}, 0xff},
+		{{0x9e, 0xdb}, 0x23},
+		{{0x9e, 0xdc}, 0x21},
+		{{0x9e, 0xdd}, 0x22},
+		{{0x9e, 0xde}, 0x24},
+
+		{{0x9c, 0x01}, 0x08},
+
+		{{0x9e, 0xaa}, 0x01},
+
+		{{0x9b, 0xd1}, 0x0d},
+		{{0x9b, 0xd2}, 0x24},
+		{{0x9b, 0xd3}, 0x0a},
+		{{0x9b, 0xd4}, 0x22},
+		{{0x9b, 0xd5}, 0x08},
+		{{0x9b, 0xd6}, 0x1e},
+		{{0x9b, 0xdd}, 0x1c},
+
+		{{0x9b, 0x84}, 0x13},
+		{{0x99, 0x81}, 0x7f},
+		{{0x99, 0x31}, 0x70},
+
+		{{0x98, 0x00}, 0x3f},
+
+		{{0x9f, 0x09}, 0x00},
+
+		{{0x9f, 0x0a}, 0x05},
+
+		{{0x9e, 0xd1}, 0xa1},
+		{{0x99, 0x23}, 0x00},
+
+		{{0x9e, 0x74}, 0x80},
+
+		{{0x9f, 0x28}, 0x10},
+
+		{{0x9f, 0x35}, 0x14},
+
+		{{0x9f, 0x36}, 0x60},
+
+		{{0x9c, 0x31}, 0x00},
+
+		{{0x9c, 0x32}, 0xc8},
+
+		{{0x9c, 0x19}, 0x40},
+
+		{{0x9c, 0x1a}, 0x40},
+
+		{{0x9c, 0x0c}, 0x00},
+
+		{{0x9c, 0x0d}, 0x00},
+
+		{{0x9c, 0x12}, 0x00},
+
+		{{0x9c, 0x13}, 0x00},
+
+		{{0x98, 0xa2}, 0x0e},
+
+		{{0x98, 0x93}, 0x40},
+
+		{{0x98, 0x7d}, 0x02},
+		{{0x98, 0x7e}, 0x00},
+		{{0x9f, 0xc8}, 0x01},
+	};
+	struct hw_config *p = hw_config;
+	int count = ARRAY_SIZE(hw_config);
+	struct sk_buff *res_skb;
+	u8 param[4];
+	int r;
+
+	param[0] = 0;
+	while (count--) {
+		param[1] = p->adr[0];
+		param[2] = p->adr[1];
+		param[3] = p->value;
+
+		r = nfc_hci_send_cmd(hdev, PN544_SYS_MGMT_GATE, PN544_WRITE,
+				     param, 4, &res_skb);
+		if (r < 0)
+			return r;
+
+		if (res_skb->len != 1) {
+			kfree_skb(res_skb);
+			return -EPROTO;
+		}
+
+		if (res_skb->data[0] != p->value) {
+			kfree_skb(res_skb);
+			return -EIO;
+		}
+
+		kfree_skb(res_skb);
+
+		p++;
+	}
+
+	param[0] = NFC_HCI_UICC_HOST_ID;
+	r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE,
+			      NFC_HCI_ADMIN_WHITELIST, param, 1);
+	if (r < 0)
+		return r;
+
+	param[0] = 0x3d;
+	r = nfc_hci_set_param(hdev, PN544_SYS_MGMT_GATE,
+			      PN544_SYS_MGMT_INFO_NOTIFICATION, param, 1);
+	if (r < 0)
+		return r;
+
+	param[0] = 0x0;
+	r = nfc_hci_set_param(hdev, NFC_HCI_RF_READER_A_GATE,
+			      PN544_RF_READER_A_AUTO_ACTIVATION, param, 1);
+	if (r < 0)
+		return r;
+
+	r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
+			       NFC_HCI_EVT_END_OPERATION, NULL, 0);
+	if (r < 0)
+		return r;
+
+	param[0] = 0x1;
+	r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE,
+			      PN544_PL_NFCT_DEACTIVATED, param, 1);
+	if (r < 0)
+		return r;
+
+	param[0] = 0x0;
+	r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE,
+			      PN544_PL_RDPHASES, param, 1);
+	if (r < 0)
+		return r;
+
+	r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE,
+			      PN544_ID_MGMT_FULL_VERSION_SW, &skb);
+	if (r < 0)
+		return r;
+
+	if (skb->len != FULL_VERSION_LEN) {
+		kfree_skb(skb);
+		return -EINVAL;
+	}
+
+	print_hex_dump(KERN_DEBUG, "FULL VERSION SOFTWARE INFO: ",
+		       DUMP_PREFIX_NONE, 16, 1,
+		       skb->data, FULL_VERSION_LEN, false);
+
+	kfree_skb(skb);
+
+	return 0;
+}
+
+static int pn544_hci_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+{
+	struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	return info->phy_ops->write(info->phy_id, skb);
+}
+
+static int pn544_hci_start_poll(struct nfc_hci_dev *hdev,
+				u32 im_protocols, u32 tm_protocols)
+{
+	u8 phases = 0;
+	int r;
+	u8 duration[2];
+	u8 activated;
+	u8 i_mode = 0x3f; /* Enable all supported modes */
+	u8 t_mode = 0x0f;
+	u8 t_merge = 0x01; /* Enable merge by default */
+
+	pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n",
+		__func__, im_protocols, tm_protocols);
+
+	r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
+			       NFC_HCI_EVT_END_OPERATION, NULL, 0);
+	if (r < 0)
+		return r;
+
+	duration[0] = 0x18;
+	duration[1] = 0x6a;
+	r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE,
+			      PN544_PL_EMULATION, duration, 2);
+	if (r < 0)
+		return r;
+
+	activated = 0;
+	r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE,
+			      PN544_PL_NFCT_DEACTIVATED, &activated, 1);
+	if (r < 0)
+		return r;
+
+	if (im_protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK |
+			 NFC_PROTO_JEWEL_MASK))
+		phases |= 1;		/* Type A */
+	if (im_protocols & NFC_PROTO_FELICA_MASK) {
+		phases |= (1 << 2);	/* Type F 212 */
+		phases |= (1 << 3);	/* Type F 424 */
+	}
+
+	phases |= (1 << 5);		/* NFC active */
+
+	r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE,
+			      PN544_PL_RDPHASES, &phases, 1);
+	if (r < 0)
+		return r;
+
+	if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) {
+		hdev->gb = nfc_get_local_general_bytes(hdev->ndev,
+							&hdev->gb_len);
+		pr_debug("generate local bytes %p", hdev->gb);
+		if (hdev->gb == NULL || hdev->gb_len == 0) {
+			im_protocols &= ~NFC_PROTO_NFC_DEP_MASK;
+			tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK;
+		}
+	}
+
+	if (im_protocols & NFC_PROTO_NFC_DEP_MASK) {
+		r = nfc_hci_send_event(hdev,
+				PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+				NFC_HCI_EVT_END_OPERATION, NULL, 0);
+		if (r < 0)
+			return r;
+
+		r = nfc_hci_set_param(hdev,
+				PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+				PN544_DEP_MODE, &i_mode, 1);
+		if (r < 0)
+			return r;
+
+		r = nfc_hci_set_param(hdev,
+				PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+				PN544_DEP_ATR_REQ, hdev->gb, hdev->gb_len);
+		if (r < 0)
+			return r;
+
+		r = nfc_hci_send_event(hdev,
+				PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+				NFC_HCI_EVT_READER_REQUESTED, NULL, 0);
+		if (r < 0)
+			nfc_hci_send_event(hdev,
+					PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+					NFC_HCI_EVT_END_OPERATION, NULL, 0);
+	}
+
+	if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) {
+		r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE,
+				PN544_DEP_MODE, &t_mode, 1);
+		if (r < 0)
+			return r;
+
+		r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE,
+				PN544_DEP_ATR_RES, hdev->gb, hdev->gb_len);
+		if (r < 0)
+			return r;
+
+		r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE,
+				PN544_DEP_MERGE, &t_merge, 1);
+		if (r < 0)
+			return r;
+	}
+
+	r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
+			       NFC_HCI_EVT_READER_REQUESTED, NULL, 0);
+	if (r < 0)
+		nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
+				   NFC_HCI_EVT_END_OPERATION, NULL, 0);
+
+	return r;
+}
+
+static int pn544_hci_dep_link_up(struct nfc_hci_dev *hdev,
+				struct nfc_target *target, u8 comm_mode,
+				u8 *gb, size_t gb_len)
+{
+	struct sk_buff *rgb_skb = NULL;
+	int r;
+
+	r = nfc_hci_get_param(hdev, target->hci_reader_gate,
+				PN544_DEP_ATR_RES, &rgb_skb);
+	if (r < 0)
+		return r;
+
+	if (rgb_skb->len == 0 || rgb_skb->len > NFC_GB_MAXSIZE) {
+		r = -EPROTO;
+		goto exit;
+	}
+	print_hex_dump(KERN_DEBUG, "remote gb: ", DUMP_PREFIX_OFFSET,
+			16, 1, rgb_skb->data, rgb_skb->len, true);
+
+	r = nfc_set_remote_general_bytes(hdev->ndev, rgb_skb->data,
+						rgb_skb->len);
+
+	if (r == 0)
+		r = nfc_dep_link_is_up(hdev->ndev, target->idx, comm_mode,
+					NFC_RF_INITIATOR);
+exit:
+	kfree_skb(rgb_skb);
+	return r;
+}
+
+static int pn544_hci_dep_link_down(struct nfc_hci_dev *hdev)
+{
+
+	return nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+					NFC_HCI_EVT_END_OPERATION, NULL, 0);
+}
+
+static int pn544_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate,
+				      struct nfc_target *target)
+{
+	switch (gate) {
+	case PN544_RF_READER_F_GATE:
+		target->supported_protocols = NFC_PROTO_FELICA_MASK;
+		break;
+	case PN544_RF_READER_JEWEL_GATE:
+		target->supported_protocols = NFC_PROTO_JEWEL_MASK;
+		target->sens_res = 0x0c00;
+		break;
+	case PN544_RF_READER_NFCIP1_INITIATOR_GATE:
+		target->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
+		break;
+	default:
+		return -EPROTO;
+	}
+
+	return 0;
+}
+
+static int pn544_hci_complete_target_discovered(struct nfc_hci_dev *hdev,
+						u8 gate,
+						struct nfc_target *target)
+{
+	struct sk_buff *uid_skb;
+	int r = 0;
+
+	if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE)
+		return r;
+
+	if (target->supported_protocols & NFC_PROTO_NFC_DEP_MASK) {
+		r = nfc_hci_send_cmd(hdev,
+			PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+			PN544_HCI_CMD_CONTINUE_ACTIVATION, NULL, 0, NULL);
+		if (r < 0)
+			return r;
+
+		target->hci_reader_gate = PN544_RF_READER_NFCIP1_INITIATOR_GATE;
+	} else if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) {
+		if (target->nfcid1_len != 4 && target->nfcid1_len != 7 &&
+		    target->nfcid1_len != 10)
+			return -EPROTO;
+
+		r = nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE,
+				     PN544_RF_READER_CMD_ACTIVATE_NEXT,
+				     target->nfcid1, target->nfcid1_len, NULL);
+	} else if (target->supported_protocols & NFC_PROTO_FELICA_MASK) {
+		r = nfc_hci_get_param(hdev, PN544_RF_READER_F_GATE,
+				      PN544_FELICA_ID, &uid_skb);
+		if (r < 0)
+			return r;
+
+		if (uid_skb->len != 8) {
+			kfree_skb(uid_skb);
+			return -EPROTO;
+		}
+
+		r = nfc_hci_send_cmd(hdev, PN544_RF_READER_F_GATE,
+				     PN544_RF_READER_CMD_ACTIVATE_NEXT,
+				     uid_skb->data, uid_skb->len, NULL);
+		kfree_skb(uid_skb);
+
+		r = nfc_hci_send_cmd(hdev,
+					PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+					PN544_HCI_CMD_CONTINUE_ACTIVATION,
+					NULL, 0, NULL);
+		if (r < 0)
+			return r;
+
+		target->hci_reader_gate = PN544_RF_READER_NFCIP1_INITIATOR_GATE;
+		target->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
+	} else if (target->supported_protocols & NFC_PROTO_ISO14443_MASK) {
+		/*
+		 * TODO: maybe other ISO 14443 require some kind of continue
+		 * activation, but for now we've seen only this one below.
+		 */
+		if (target->sens_res == 0x4403)	/* Type 4 Mifare DESFire */
+			r = nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE,
+			      PN544_RF_READER_A_CMD_CONTINUE_ACTIVATION,
+			      NULL, 0, NULL);
+	}
+
+	return r;
+}
+
+#define PN544_CB_TYPE_READER_F 1
+
+static void pn544_hci_data_exchange_cb(void *context, struct sk_buff *skb,
+				       int err)
+{
+	struct pn544_hci_info *info = context;
+
+	switch (info->async_cb_type) {
+	case PN544_CB_TYPE_READER_F:
+		if (err == 0)
+			skb_pull(skb, 1);
+		info->async_cb(info->async_cb_context, skb, err);
+		break;
+	default:
+		if (err == 0)
+			kfree_skb(skb);
+		break;
+	}
+}
+
+#define MIFARE_CMD_AUTH_KEY_A	0x60
+#define MIFARE_CMD_AUTH_KEY_B	0x61
+#define MIFARE_CMD_HEADER	2
+#define MIFARE_UID_LEN		4
+#define MIFARE_KEY_LEN		6
+#define MIFARE_CMD_LEN		12
+/*
+ * Returns:
+ * <= 0: driver handled the data exchange
+ *    1: driver doesn't especially handle, please do standard processing
+ */
+static int pn544_hci_im_transceive(struct nfc_hci_dev *hdev,
+				   struct nfc_target *target,
+				   struct sk_buff *skb, data_exchange_cb_t cb,
+				   void *cb_context)
+{
+	struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	pr_info(DRIVER_DESC ": %s for gate=%d\n", __func__,
+		target->hci_reader_gate);
+
+	switch (target->hci_reader_gate) {
+	case NFC_HCI_RF_READER_A_GATE:
+		if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) {
+			/*
+			 * It seems that pn544 is inverting key and UID for
+			 * MIFARE authentication commands.
+			 */
+			if (skb->len == MIFARE_CMD_LEN &&
+			    (skb->data[0] == MIFARE_CMD_AUTH_KEY_A ||
+			     skb->data[0] == MIFARE_CMD_AUTH_KEY_B)) {
+				u8 uid[MIFARE_UID_LEN];
+				u8 *data = skb->data + MIFARE_CMD_HEADER;
+
+				memcpy(uid, data + MIFARE_KEY_LEN,
+				       MIFARE_UID_LEN);
+				memmove(data + MIFARE_UID_LEN, data,
+					MIFARE_KEY_LEN);
+				memcpy(data, uid, MIFARE_UID_LEN);
+			}
+
+			return nfc_hci_send_cmd_async(hdev,
+						      target->hci_reader_gate,
+						      PN544_MIFARE_CMD,
+						      skb->data, skb->len,
+						      cb, cb_context);
+		} else
+			return 1;
+	case PN544_RF_READER_F_GATE:
+		*skb_push(skb, 1) = 0;
+		*skb_push(skb, 1) = 0;
+
+		info->async_cb_type = PN544_CB_TYPE_READER_F;
+		info->async_cb = cb;
+		info->async_cb_context = cb_context;
+
+		return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,
+					      PN544_FELICA_RAW, skb->data,
+					      skb->len,
+					      pn544_hci_data_exchange_cb, info);
+	case PN544_RF_READER_JEWEL_GATE:
+		return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,
+					      PN544_JEWEL_RAW_CMD, skb->data,
+					      skb->len, cb, cb_context);
+	case PN544_RF_READER_NFCIP1_INITIATOR_GATE:
+		*skb_push(skb, 1) = 0;
+
+		return nfc_hci_send_event(hdev, target->hci_reader_gate,
+					PN544_HCI_EVT_SND_DATA, skb->data,
+					skb->len);
+	default:
+		return 1;
+	}
+}
+
+static int pn544_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+{
+	/* Set default false for multiple information chaining */
+	*skb_push(skb, 1) = 0;
+
+	return nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE,
+				PN544_HCI_EVT_SND_DATA, skb->data, skb->len);
+}
+
+static int pn544_hci_check_presence(struct nfc_hci_dev *hdev,
+				   struct nfc_target *target)
+{
+	pr_debug("supported protocol %d", target->supported_protocols);
+	if (target->supported_protocols & (NFC_PROTO_ISO14443_MASK |
+					NFC_PROTO_ISO14443_B_MASK)) {
+		return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
+					PN544_RF_READER_CMD_PRESENCE_CHECK,
+					NULL, 0, NULL);
+	} else if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) {
+		if (target->nfcid1_len != 4 && target->nfcid1_len != 7 &&
+		    target->nfcid1_len != 10)
+			return -EOPNOTSUPP;
+
+		 return nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE,
+				     PN544_RF_READER_CMD_ACTIVATE_NEXT,
+				     target->nfcid1, target->nfcid1_len, NULL);
+	} else if (target->supported_protocols & NFC_PROTO_JEWEL_MASK) {
+		return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
+					PN544_JEWEL_RAW_CMD, NULL, 0, NULL);
+	} else if (target->supported_protocols & NFC_PROTO_FELICA_MASK) {
+		return nfc_hci_send_cmd(hdev, PN544_RF_READER_F_GATE,
+					PN544_FELICA_RAW, NULL, 0, NULL);
+	} else if (target->supported_protocols & NFC_PROTO_NFC_DEP_MASK) {
+		return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
+					PN544_HCI_CMD_ATTREQUEST,
+					NULL, 0, NULL);
+	}
+
+	return 0;
+}
+
+static void pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate,
+					u8 event, struct sk_buff *skb)
+{
+	struct sk_buff *rgb_skb = NULL;
+	int r = 0;
+
+	pr_debug("hci event %d", event);
+	switch (event) {
+	case PN544_HCI_EVT_ACTIVATED:
+		if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE)
+			nfc_hci_target_discovered(hdev, gate);
+		else if (gate == PN544_RF_READER_NFCIP1_TARGET_GATE) {
+			r = nfc_hci_get_param(hdev, gate, PN544_DEP_ATR_REQ,
+						&rgb_skb);
+
+			if (r < 0)
+				goto exit;
+
+			nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK,
+					NFC_COMM_PASSIVE, rgb_skb->data,
+					rgb_skb->len);
+
+			kfree_skb(rgb_skb);
+		}
+
+		break;
+	case PN544_HCI_EVT_DEACTIVATED:
+		nfc_hci_send_event(hdev, gate,
+			NFC_HCI_EVT_END_OPERATION, NULL, 0);
+		break;
+	case PN544_HCI_EVT_RCV_DATA:
+		if (skb->len < 2) {
+			r = -EPROTO;
+			goto exit;
+		}
+
+		if (skb->data[0] != 0) {
+			pr_debug("data0 %d", skb->data[0]);
+			r = -EPROTO;
+			goto exit;
+		}
+
+		skb_pull(skb, 2);
+		nfc_tm_data_received(hdev->ndev, skb);
+
+		return;
+	default:
+		break;
+	}
+
+exit:
+	kfree_skb(skb);
+}
+
+static struct nfc_hci_ops pn544_hci_ops = {
+	.open = pn544_hci_open,
+	.close = pn544_hci_close,
+	.hci_ready = pn544_hci_ready,
+	.xmit = pn544_hci_xmit,
+	.start_poll = pn544_hci_start_poll,
+	.dep_link_up = pn544_hci_dep_link_up,
+	.dep_link_down = pn544_hci_dep_link_down,
+	.target_from_gate = pn544_hci_target_from_gate,
+	.complete_target_discovered = pn544_hci_complete_target_discovered,
+	.im_transceive = pn544_hci_im_transceive,
+	.tm_send = pn544_hci_tm_send,
+	.check_presence = pn544_hci_check_presence,
+	.event_received = pn544_hci_event_received,
+};
+
+int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name,
+		    int phy_headroom, int phy_tailroom, int phy_payload,
+		    struct nfc_hci_dev **hdev)
+{
+	struct pn544_hci_info *info;
+	u32 protocols;
+	struct nfc_hci_init_data init_data;
+	int r;
+
+	info = kzalloc(sizeof(struct pn544_hci_info), GFP_KERNEL);
+	if (!info) {
+		pr_err("Cannot allocate memory for pn544_hci_info.\n");
+		r = -ENOMEM;
+		goto err_info_alloc;
+	}
+
+	info->phy_ops = phy_ops;
+	info->phy_id = phy_id;
+	info->state = PN544_ST_COLD;
+	mutex_init(&info->info_lock);
+
+	init_data.gate_count = ARRAY_SIZE(pn544_gates);
+
+	memcpy(init_data.gates, pn544_gates, sizeof(pn544_gates));
+
+	/*
+	 * TODO: Session id must include the driver name + some bus addr
+	 * persistent info to discriminate 2 identical chips
+	 */
+	strcpy(init_data.session_id, "ID544HCI");
+
+	protocols = NFC_PROTO_JEWEL_MASK |
+		    NFC_PROTO_MIFARE_MASK |
+		    NFC_PROTO_FELICA_MASK |
+		    NFC_PROTO_ISO14443_MASK |
+		    NFC_PROTO_ISO14443_B_MASK |
+		    NFC_PROTO_NFC_DEP_MASK;
+
+	info->hdev = nfc_hci_allocate_device(&pn544_hci_ops, &init_data,
+					     protocols, llc_name,
+					     phy_headroom + PN544_CMDS_HEADROOM,
+					     phy_tailroom, phy_payload);
+	if (!info->hdev) {
+		pr_err("Cannot allocate nfc hdev.\n");
+		r = -ENOMEM;
+		goto err_alloc_hdev;
+	}
+
+	nfc_hci_set_clientdata(info->hdev, info);
+
+	r = nfc_hci_register_device(info->hdev);
+	if (r)
+		goto err_regdev;
+
+	*hdev = info->hdev;
+
+	return 0;
+
+err_regdev:
+	nfc_hci_free_device(info->hdev);
+
+err_alloc_hdev:
+	kfree(info);
+
+err_info_alloc:
+	return r;
+}
+
+void pn544_hci_remove(struct nfc_hci_dev *hdev)
+{
+	struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+	nfc_hci_unregister_device(hdev);
+	nfc_hci_free_device(hdev);
+	kfree(info);
+}
diff --git a/drivers/nfc/pn544/pn544.h b/drivers/nfc/pn544/pn544.h
new file mode 100644
index 0000000..f47c645
--- /dev/null
+++ b/drivers/nfc/pn544/pn544.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 - 2012  Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __LOCAL_PN544_H_
+#define __LOCAL_PN544_H_
+
+#include <net/nfc/hci.h>
+
+#define DRIVER_DESC "HCI NFC driver for PN544"
+
+int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name,
+		    int phy_headroom, int phy_tailroom, int phy_payload,
+		    struct nfc_hci_dev **hdev);
+void pn544_hci_remove(struct nfc_hci_dev *hdev);
+
+#endif /* __LOCAL_PN544_H_ */
diff --git a/drivers/nfc/pn544_hci.c b/drivers/nfc/pn544_hci.c
deleted file mode 100644
index c9c8570..0000000
--- a/drivers/nfc/pn544_hci.c
+++ /dev/null
@@ -1,1023 +0,0 @@
-/*
- * HCI based Driver for NXP PN544 NFC Chip
- *
- * Copyright (C) 2012  Intel Corporation. All rights reserved.
- *
- * 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 that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You 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/crc-ccitt.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/miscdevice.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-
-#include <linux/nfc.h>
-#include <net/nfc/hci.h>
-#include <net/nfc/llc.h>
-
-#include <linux/nfc/pn544.h>
-
-#define DRIVER_DESC "HCI NFC driver for PN544"
-
-#define PN544_HCI_DRIVER_NAME "pn544_hci"
-
-/* Timing restrictions (ms) */
-#define PN544_HCI_RESETVEN_TIME		30
-
-static struct i2c_device_id pn544_hci_id_table[] = {
-	{"pn544", 0},
-	{}
-};
-
-MODULE_DEVICE_TABLE(i2c, pn544_hci_id_table);
-
-#define HCI_MODE 0
-#define FW_MODE 1
-
-/* framing in HCI mode */
-#define PN544_HCI_LLC_LEN		1
-#define PN544_HCI_LLC_CRC		2
-#define PN544_HCI_LLC_LEN_CRC		(PN544_HCI_LLC_LEN + PN544_HCI_LLC_CRC)
-#define PN544_HCI_LLC_MIN_SIZE		(1 + PN544_HCI_LLC_LEN_CRC)
-#define PN544_HCI_LLC_MAX_PAYLOAD	29
-#define PN544_HCI_LLC_MAX_SIZE		(PN544_HCI_LLC_LEN_CRC + 1 + \
-					 PN544_HCI_LLC_MAX_PAYLOAD)
-
-enum pn544_state {
-	PN544_ST_COLD,
-	PN544_ST_FW_READY,
-	PN544_ST_READY,
-};
-
-#define FULL_VERSION_LEN 11
-
-/* Proprietary commands */
-#define PN544_WRITE		0x3f
-
-/* Proprietary gates, events, commands and registers */
-
-/* NFC_HCI_RF_READER_A_GATE additional registers and commands */
-#define PN544_RF_READER_A_AUTO_ACTIVATION			0x10
-#define PN544_RF_READER_A_CMD_CONTINUE_ACTIVATION		0x12
-#define PN544_MIFARE_CMD					0x21
-
-/* Commands that apply to all RF readers */
-#define PN544_RF_READER_CMD_PRESENCE_CHECK	0x30
-#define PN544_RF_READER_CMD_ACTIVATE_NEXT	0x32
-
-/* NFC_HCI_ID_MGMT_GATE additional registers */
-#define PN544_ID_MGMT_FULL_VERSION_SW		0x10
-
-#define PN544_RF_READER_ISO15693_GATE		0x12
-
-#define PN544_RF_READER_F_GATE			0x14
-#define PN544_FELICA_ID				0x04
-#define PN544_FELICA_RAW			0x20
-
-#define PN544_RF_READER_JEWEL_GATE		0x15
-#define PN544_JEWEL_RAW_CMD			0x23
-
-#define PN544_RF_READER_NFCIP1_INITIATOR_GATE	0x30
-#define PN544_RF_READER_NFCIP1_TARGET_GATE	0x31
-
-#define PN544_SYS_MGMT_GATE			0x90
-#define PN544_SYS_MGMT_INFO_NOTIFICATION	0x02
-
-#define PN544_POLLING_LOOP_MGMT_GATE		0x94
-#define PN544_PL_RDPHASES			0x06
-#define PN544_PL_EMULATION			0x07
-#define PN544_PL_NFCT_DEACTIVATED		0x09
-
-#define PN544_SWP_MGMT_GATE			0xA0
-
-#define PN544_NFC_WI_MGMT_GATE			0xA1
-
-static struct nfc_hci_gate pn544_gates[] = {
-	{NFC_HCI_ADMIN_GATE, NFC_HCI_INVALID_PIPE},
-	{NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE},
-	{NFC_HCI_ID_MGMT_GATE, NFC_HCI_INVALID_PIPE},
-	{NFC_HCI_LINK_MGMT_GATE, NFC_HCI_INVALID_PIPE},
-	{NFC_HCI_RF_READER_B_GATE, NFC_HCI_INVALID_PIPE},
-	{NFC_HCI_RF_READER_A_GATE, NFC_HCI_INVALID_PIPE},
-	{PN544_SYS_MGMT_GATE, NFC_HCI_INVALID_PIPE},
-	{PN544_SWP_MGMT_GATE, NFC_HCI_INVALID_PIPE},
-	{PN544_POLLING_LOOP_MGMT_GATE, NFC_HCI_INVALID_PIPE},
-	{PN544_NFC_WI_MGMT_GATE, NFC_HCI_INVALID_PIPE},
-	{PN544_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE},
-	{PN544_RF_READER_JEWEL_GATE, NFC_HCI_INVALID_PIPE},
-	{PN544_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE},
-	{PN544_RF_READER_NFCIP1_INITIATOR_GATE, NFC_HCI_INVALID_PIPE},
-	{PN544_RF_READER_NFCIP1_TARGET_GATE, NFC_HCI_INVALID_PIPE}
-};
-
-/* Largest headroom needed for outgoing custom commands */
-#define PN544_CMDS_HEADROOM	2
-#define PN544_FRAME_HEADROOM 1
-#define PN544_FRAME_TAILROOM 2
-
-struct pn544_hci_info {
-	struct i2c_client *i2c_dev;
-	struct nfc_hci_dev *hdev;
-
-	enum pn544_state state;
-
-	struct mutex info_lock;
-
-	unsigned int gpio_en;
-	unsigned int gpio_irq;
-	unsigned int gpio_fw;
-	unsigned int en_polarity;
-
-	int hard_fault;		/*
-				 * < 0 if hardware error occured (e.g. i2c err)
-				 * and prevents normal operation.
-				 */
-	int async_cb_type;
-	data_exchange_cb_t async_cb;
-	void *async_cb_context;
-};
-
-static void pn544_hci_platform_init(struct pn544_hci_info *info)
-{
-	int polarity, retry, ret;
-	char rset_cmd[] = { 0x05, 0xF9, 0x04, 0x00, 0xC3, 0xE5 };
-	int count = sizeof(rset_cmd);
-
-	pr_info(DRIVER_DESC ": %s\n", __func__);
-	dev_info(&info->i2c_dev->dev, "Detecting nfc_en polarity\n");
-
-	/* Disable fw download */
-	gpio_set_value(info->gpio_fw, 0);
-
-	for (polarity = 0; polarity < 2; polarity++) {
-		info->en_polarity = polarity;
-		retry = 3;
-		while (retry--) {
-			/* power off */
-			gpio_set_value(info->gpio_en, !info->en_polarity);
-			usleep_range(10000, 15000);
-
-			/* power on */
-			gpio_set_value(info->gpio_en, info->en_polarity);
-			usleep_range(10000, 15000);
-
-			/* send reset */
-			dev_dbg(&info->i2c_dev->dev, "Sending reset cmd\n");
-			ret = i2c_master_send(info->i2c_dev, rset_cmd, count);
-			if (ret == count) {
-				dev_info(&info->i2c_dev->dev,
-					 "nfc_en polarity : active %s\n",
-					 (polarity == 0 ? "low" : "high"));
-				goto out;
-			}
-		}
-	}
-
-	dev_err(&info->i2c_dev->dev,
-		"Could not detect nfc_en polarity, fallback to active high\n");
-
-out:
-	gpio_set_value(info->gpio_en, !info->en_polarity);
-}
-
-static int pn544_hci_enable(struct pn544_hci_info *info, int mode)
-{
-	pr_info(DRIVER_DESC ": %s\n", __func__);
-
-	gpio_set_value(info->gpio_fw, 0);
-	gpio_set_value(info->gpio_en, info->en_polarity);
-	usleep_range(10000, 15000);
-
-	return 0;
-}
-
-static void pn544_hci_disable(struct pn544_hci_info *info)
-{
-	pr_info(DRIVER_DESC ": %s\n", __func__);
-
-	gpio_set_value(info->gpio_fw, 0);
-	gpio_set_value(info->gpio_en, !info->en_polarity);
-	usleep_range(10000, 15000);
-
-	gpio_set_value(info->gpio_en, info->en_polarity);
-	usleep_range(10000, 15000);
-
-	gpio_set_value(info->gpio_en, !info->en_polarity);
-	usleep_range(10000, 15000);
-}
-
-static int pn544_hci_i2c_write(struct i2c_client *client, u8 *buf, int len)
-{
-	int r;
-
-	usleep_range(3000, 6000);
-
-	r = i2c_master_send(client, buf, len);
-
-	if (r == -EREMOTEIO) {	/* Retry, chip was in standby */
-		usleep_range(6000, 10000);
-		r = i2c_master_send(client, buf, len);
-	}
-
-	if (r >= 0) {
-		if (r != len)
-			return -EREMOTEIO;
-		else
-			return 0;
-	}
-
-	return r;
-}
-
-static int check_crc(u8 *buf, int buflen)
-{
-	int len;
-	u16 crc;
-
-	len = buf[0] + 1;
-	crc = crc_ccitt(0xffff, buf, len - 2);
-	crc = ~crc;
-
-	if (buf[len - 2] != (crc & 0xff) || buf[len - 1] != (crc >> 8)) {
-		pr_err(PN544_HCI_DRIVER_NAME ": CRC error 0x%x != 0x%x 0x%x\n",
-		       crc, buf[len - 1], buf[len - 2]);
-
-		pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__);
-		print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE,
-			       16, 2, buf, buflen, false);
-		return -EPERM;
-	}
-	return 0;
-}
-
-/*
- * Reads an shdlc frame and returns it in a newly allocated sk_buff. Guarantees
- * that i2c bus will be flushed and that next read will start on a new frame.
- * returned skb contains only LLC header and payload.
- * returns:
- * -EREMOTEIO : i2c read error (fatal)
- * -EBADMSG : frame was incorrect and discarded
- * -ENOMEM : cannot allocate skb, frame dropped
- */
-static int pn544_hci_i2c_read(struct i2c_client *client, struct sk_buff **skb)
-{
-	int r;
-	u8 len;
-	u8 tmp[PN544_HCI_LLC_MAX_SIZE - 1];
-
-	r = i2c_master_recv(client, &len, 1);
-	if (r != 1) {
-		dev_err(&client->dev, "cannot read len byte\n");
-		return -EREMOTEIO;
-	}
-
-	if ((len < (PN544_HCI_LLC_MIN_SIZE - 1)) ||
-	    (len > (PN544_HCI_LLC_MAX_SIZE - 1))) {
-		dev_err(&client->dev, "invalid len byte\n");
-		r = -EBADMSG;
-		goto flush;
-	}
-
-	*skb = alloc_skb(1 + len, GFP_KERNEL);
-	if (*skb == NULL) {
-		r = -ENOMEM;
-		goto flush;
-	}
-
-	*skb_put(*skb, 1) = len;
-
-	r = i2c_master_recv(client, skb_put(*skb, len), len);
-	if (r != len) {
-		kfree_skb(*skb);
-		return -EREMOTEIO;
-	}
-
-	r = check_crc((*skb)->data, (*skb)->len);
-	if (r != 0) {
-		kfree_skb(*skb);
-		r = -EBADMSG;
-		goto flush;
-	}
-
-	skb_pull(*skb, 1);
-	skb_trim(*skb, (*skb)->len - 2);
-
-	usleep_range(3000, 6000);
-
-	return 0;
-
-flush:
-	if (i2c_master_recv(client, tmp, sizeof(tmp)) < 0)
-		r = -EREMOTEIO;
-
-	usleep_range(3000, 6000);
-
-	return r;
-}
-
-/*
- * Reads an shdlc frame from the chip. This is not as straightforward as it
- * seems. There are cases where we could loose the frame start synchronization.
- * The frame format is len-data-crc, and corruption can occur anywhere while
- * transiting on i2c bus, such that we could read an invalid len.
- * In order to recover synchronization with the next frame, we must be sure
- * to read the real amount of data without using the len byte. We do this by
- * assuming the following:
- * - the chip will always present only one single complete frame on the bus
- *   before triggering the interrupt
- * - the chip will not present a new frame until we have completely read
- *   the previous one (or until we have handled the interrupt).
- * The tricky case is when we read a corrupted len that is less than the real
- * len. We must detect this here in order to determine that we need to flush
- * the bus. This is the reason why we check the crc here.
- */
-static irqreturn_t pn544_hci_irq_thread_fn(int irq, void *dev_id)
-{
-	struct pn544_hci_info *info = dev_id;
-	struct i2c_client *client;
-	struct sk_buff *skb = NULL;
-	int r;
-
-	if (!info || irq != info->i2c_dev->irq) {
-		WARN_ON_ONCE(1);
-		return IRQ_NONE;
-	}
-
-	client = info->i2c_dev;
-	dev_dbg(&client->dev, "IRQ\n");
-
-	if (info->hard_fault != 0)
-		return IRQ_HANDLED;
-
-	r = pn544_hci_i2c_read(client, &skb);
-	if (r == -EREMOTEIO) {
-		info->hard_fault = r;
-
-		nfc_hci_recv_frame(info->hdev, NULL);
-
-		return IRQ_HANDLED;
-	} else if ((r == -ENOMEM) || (r == -EBADMSG)) {
-		return IRQ_HANDLED;
-	}
-
-	nfc_hci_recv_frame(info->hdev, skb);
-
-	return IRQ_HANDLED;
-}
-
-static int pn544_hci_open(struct nfc_hci_dev *hdev)
-{
-	struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev);
-	int r = 0;
-
-	mutex_lock(&info->info_lock);
-
-	if (info->state != PN544_ST_COLD) {
-		r = -EBUSY;
-		goto out;
-	}
-
-	r = pn544_hci_enable(info, HCI_MODE);
-
-	if (r == 0)
-		info->state = PN544_ST_READY;
-
-out:
-	mutex_unlock(&info->info_lock);
-	return r;
-}
-
-static void pn544_hci_close(struct nfc_hci_dev *hdev)
-{
-	struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	mutex_lock(&info->info_lock);
-
-	if (info->state == PN544_ST_COLD)
-		goto out;
-
-	pn544_hci_disable(info);
-
-	info->state = PN544_ST_COLD;
-
-out:
-	mutex_unlock(&info->info_lock);
-}
-
-static int pn544_hci_ready(struct nfc_hci_dev *hdev)
-{
-	struct sk_buff *skb;
-	static struct hw_config {
-		u8 adr[2];
-		u8 value;
-	} hw_config[] = {
-		{{0x9f, 0x9a}, 0x00},
-
-		{{0x98, 0x10}, 0xbc},
-
-		{{0x9e, 0x71}, 0x00},
-
-		{{0x98, 0x09}, 0x00},
-
-		{{0x9e, 0xb4}, 0x00},
-
-		{{0x9e, 0xd9}, 0xff},
-		{{0x9e, 0xda}, 0xff},
-		{{0x9e, 0xdb}, 0x23},
-		{{0x9e, 0xdc}, 0x21},
-		{{0x9e, 0xdd}, 0x22},
-		{{0x9e, 0xde}, 0x24},
-
-		{{0x9c, 0x01}, 0x08},
-
-		{{0x9e, 0xaa}, 0x01},
-
-		{{0x9b, 0xd1}, 0x0d},
-		{{0x9b, 0xd2}, 0x24},
-		{{0x9b, 0xd3}, 0x0a},
-		{{0x9b, 0xd4}, 0x22},
-		{{0x9b, 0xd5}, 0x08},
-		{{0x9b, 0xd6}, 0x1e},
-		{{0x9b, 0xdd}, 0x1c},
-
-		{{0x9b, 0x84}, 0x13},
-		{{0x99, 0x81}, 0x7f},
-		{{0x99, 0x31}, 0x70},
-
-		{{0x98, 0x00}, 0x3f},
-
-		{{0x9f, 0x09}, 0x00},
-
-		{{0x9f, 0x0a}, 0x05},
-
-		{{0x9e, 0xd1}, 0xa1},
-		{{0x99, 0x23}, 0x00},
-
-		{{0x9e, 0x74}, 0x80},
-
-		{{0x9f, 0x28}, 0x10},
-
-		{{0x9f, 0x35}, 0x14},
-
-		{{0x9f, 0x36}, 0x60},
-
-		{{0x9c, 0x31}, 0x00},
-
-		{{0x9c, 0x32}, 0xc8},
-
-		{{0x9c, 0x19}, 0x40},
-
-		{{0x9c, 0x1a}, 0x40},
-
-		{{0x9c, 0x0c}, 0x00},
-
-		{{0x9c, 0x0d}, 0x00},
-
-		{{0x9c, 0x12}, 0x00},
-
-		{{0x9c, 0x13}, 0x00},
-
-		{{0x98, 0xa2}, 0x0e},
-
-		{{0x98, 0x93}, 0x40},
-
-		{{0x98, 0x7d}, 0x02},
-		{{0x98, 0x7e}, 0x00},
-		{{0x9f, 0xc8}, 0x01},
-	};
-	struct hw_config *p = hw_config;
-	int count = ARRAY_SIZE(hw_config);
-	struct sk_buff *res_skb;
-	u8 param[4];
-	int r;
-
-	param[0] = 0;
-	while (count--) {
-		param[1] = p->adr[0];
-		param[2] = p->adr[1];
-		param[3] = p->value;
-
-		r = nfc_hci_send_cmd(hdev, PN544_SYS_MGMT_GATE, PN544_WRITE,
-				     param, 4, &res_skb);
-		if (r < 0)
-			return r;
-
-		if (res_skb->len != 1) {
-			kfree_skb(res_skb);
-			return -EPROTO;
-		}
-
-		if (res_skb->data[0] != p->value) {
-			kfree_skb(res_skb);
-			return -EIO;
-		}
-
-		kfree_skb(res_skb);
-
-		p++;
-	}
-
-	param[0] = NFC_HCI_UICC_HOST_ID;
-	r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE,
-			      NFC_HCI_ADMIN_WHITELIST, param, 1);
-	if (r < 0)
-		return r;
-
-	param[0] = 0x3d;
-	r = nfc_hci_set_param(hdev, PN544_SYS_MGMT_GATE,
-			      PN544_SYS_MGMT_INFO_NOTIFICATION, param, 1);
-	if (r < 0)
-		return r;
-
-	param[0] = 0x0;
-	r = nfc_hci_set_param(hdev, NFC_HCI_RF_READER_A_GATE,
-			      PN544_RF_READER_A_AUTO_ACTIVATION, param, 1);
-	if (r < 0)
-		return r;
-
-	r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
-			       NFC_HCI_EVT_END_OPERATION, NULL, 0);
-	if (r < 0)
-		return r;
-
-	param[0] = 0x1;
-	r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE,
-			      PN544_PL_NFCT_DEACTIVATED, param, 1);
-	if (r < 0)
-		return r;
-
-	param[0] = 0x0;
-	r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE,
-			      PN544_PL_RDPHASES, param, 1);
-	if (r < 0)
-		return r;
-
-	r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE,
-			      PN544_ID_MGMT_FULL_VERSION_SW, &skb);
-	if (r < 0)
-		return r;
-
-	if (skb->len != FULL_VERSION_LEN) {
-		kfree_skb(skb);
-		return -EINVAL;
-	}
-
-	print_hex_dump(KERN_DEBUG, "FULL VERSION SOFTWARE INFO: ",
-		       DUMP_PREFIX_NONE, 16, 1,
-		       skb->data, FULL_VERSION_LEN, false);
-
-	kfree_skb(skb);
-
-	return 0;
-}
-
-static void pn544_hci_add_len_crc(struct sk_buff *skb)
-{
-	u16 crc;
-	int len;
-
-	len = skb->len + 2;
-	*skb_push(skb, 1) = len;
-
-	crc = crc_ccitt(0xffff, skb->data, skb->len);
-	crc = ~crc;
-	*skb_put(skb, 1) = crc & 0xff;
-	*skb_put(skb, 1) = crc >> 8;
-}
-
-static void pn544_hci_remove_len_crc(struct sk_buff *skb)
-{
-	skb_pull(skb, PN544_FRAME_HEADROOM);
-	skb_trim(skb, PN544_FRAME_TAILROOM);
-}
-
-static int pn544_hci_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb)
-{
-	struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev);
-	struct i2c_client *client = info->i2c_dev;
-	int r;
-
-	if (info->hard_fault != 0)
-		return info->hard_fault;
-
-	pn544_hci_add_len_crc(skb);
-	r = pn544_hci_i2c_write(client, skb->data, skb->len);
-	pn544_hci_remove_len_crc(skb);
-
-	return r;
-}
-
-static int pn544_hci_start_poll(struct nfc_hci_dev *hdev,
-				u32 im_protocols, u32 tm_protocols)
-{
-	u8 phases = 0;
-	int r;
-	u8 duration[2];
-	u8 activated;
-
-	pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n",
-		__func__, im_protocols, tm_protocols);
-
-	r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
-			       NFC_HCI_EVT_END_OPERATION, NULL, 0);
-	if (r < 0)
-		return r;
-
-	duration[0] = 0x18;
-	duration[1] = 0x6a;
-	r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE,
-			      PN544_PL_EMULATION, duration, 2);
-	if (r < 0)
-		return r;
-
-	activated = 0;
-	r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE,
-			      PN544_PL_NFCT_DEACTIVATED, &activated, 1);
-	if (r < 0)
-		return r;
-
-	if (im_protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK |
-			 NFC_PROTO_JEWEL_MASK))
-		phases |= 1;		/* Type A */
-	if (im_protocols & NFC_PROTO_FELICA_MASK) {
-		phases |= (1 << 2);	/* Type F 212 */
-		phases |= (1 << 3);	/* Type F 424 */
-	}
-
-	phases |= (1 << 5);		/* NFC active */
-
-	r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE,
-			      PN544_PL_RDPHASES, &phases, 1);
-	if (r < 0)
-		return r;
-
-	r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
-			       NFC_HCI_EVT_READER_REQUESTED, NULL, 0);
-	if (r < 0)
-		nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
-				   NFC_HCI_EVT_END_OPERATION, NULL, 0);
-
-	return r;
-}
-
-static int pn544_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate,
-				      struct nfc_target *target)
-{
-	switch (gate) {
-	case PN544_RF_READER_F_GATE:
-		target->supported_protocols = NFC_PROTO_FELICA_MASK;
-		break;
-	case PN544_RF_READER_JEWEL_GATE:
-		target->supported_protocols = NFC_PROTO_JEWEL_MASK;
-		target->sens_res = 0x0c00;
-		break;
-	default:
-		return -EPROTO;
-	}
-
-	return 0;
-}
-
-static int pn544_hci_complete_target_discovered(struct nfc_hci_dev *hdev,
-						u8 gate,
-						struct nfc_target *target)
-{
-	struct sk_buff *uid_skb;
-	int r = 0;
-
-	if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) {
-		if (target->nfcid1_len != 4 && target->nfcid1_len != 7 &&
-		    target->nfcid1_len != 10)
-			return -EPROTO;
-
-		r = nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE,
-				     PN544_RF_READER_CMD_ACTIVATE_NEXT,
-				     target->nfcid1, target->nfcid1_len, NULL);
-	} else if (target->supported_protocols & NFC_PROTO_FELICA_MASK) {
-		r = nfc_hci_get_param(hdev, PN544_RF_READER_F_GATE,
-				      PN544_FELICA_ID, &uid_skb);
-		if (r < 0)
-			return r;
-
-		if (uid_skb->len != 8) {
-			kfree_skb(uid_skb);
-			return -EPROTO;
-		}
-
-		r = nfc_hci_send_cmd(hdev, PN544_RF_READER_F_GATE,
-				     PN544_RF_READER_CMD_ACTIVATE_NEXT,
-				     uid_skb->data, uid_skb->len, NULL);
-		kfree_skb(uid_skb);
-	} else if (target->supported_protocols & NFC_PROTO_ISO14443_MASK) {
-		/*
-		 * TODO: maybe other ISO 14443 require some kind of continue
-		 * activation, but for now we've seen only this one below.
-		 */
-		if (target->sens_res == 0x4403)	/* Type 4 Mifare DESFire */
-			r = nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE,
-			      PN544_RF_READER_A_CMD_CONTINUE_ACTIVATION,
-			      NULL, 0, NULL);
-	}
-
-	return r;
-}
-
-#define PN544_CB_TYPE_READER_F 1
-
-static void pn544_hci_data_exchange_cb(void *context, struct sk_buff *skb,
-				       int err)
-{
-	struct pn544_hci_info *info = context;
-
-	switch (info->async_cb_type) {
-	case PN544_CB_TYPE_READER_F:
-		if (err == 0)
-			skb_pull(skb, 1);
-		info->async_cb(info->async_cb_context, skb, err);
-		break;
-	default:
-		if (err == 0)
-			kfree_skb(skb);
-		break;
-	}
-}
-
-#define MIFARE_CMD_AUTH_KEY_A	0x60
-#define MIFARE_CMD_AUTH_KEY_B	0x61
-#define MIFARE_CMD_HEADER	2
-#define MIFARE_UID_LEN		4
-#define MIFARE_KEY_LEN		6
-#define MIFARE_CMD_LEN		12
-/*
- * Returns:
- * <= 0: driver handled the data exchange
- *    1: driver doesn't especially handle, please do standard processing
- */
-static int pn544_hci_data_exchange(struct nfc_hci_dev *hdev,
-				   struct nfc_target *target,
-				   struct sk_buff *skb, data_exchange_cb_t cb,
-				   void *cb_context)
-{
-	struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev);
-
-	pr_info(DRIVER_DESC ": %s for gate=%d\n", __func__,
-		target->hci_reader_gate);
-
-	switch (target->hci_reader_gate) {
-	case NFC_HCI_RF_READER_A_GATE:
-		if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) {
-			/*
-			 * It seems that pn544 is inverting key and UID for
-			 * MIFARE authentication commands.
-			 */
-			if (skb->len == MIFARE_CMD_LEN &&
-			    (skb->data[0] == MIFARE_CMD_AUTH_KEY_A ||
-			     skb->data[0] == MIFARE_CMD_AUTH_KEY_B)) {
-				u8 uid[MIFARE_UID_LEN];
-				u8 *data = skb->data + MIFARE_CMD_HEADER;
-
-				memcpy(uid, data + MIFARE_KEY_LEN,
-				       MIFARE_UID_LEN);
-				memmove(data + MIFARE_UID_LEN, data,
-					MIFARE_KEY_LEN);
-				memcpy(data, uid, MIFARE_UID_LEN);
-			}
-
-			return nfc_hci_send_cmd_async(hdev,
-						      target->hci_reader_gate,
-						      PN544_MIFARE_CMD,
-						      skb->data, skb->len,
-						      cb, cb_context);
-		} else
-			return 1;
-	case PN544_RF_READER_F_GATE:
-		*skb_push(skb, 1) = 0;
-		*skb_push(skb, 1) = 0;
-
-		info->async_cb_type = PN544_CB_TYPE_READER_F;
-		info->async_cb = cb;
-		info->async_cb_context = cb_context;
-
-		return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,
-					      PN544_FELICA_RAW, skb->data,
-					      skb->len,
-					      pn544_hci_data_exchange_cb, info);
-	case PN544_RF_READER_JEWEL_GATE:
-		return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,
-					      PN544_JEWEL_RAW_CMD, skb->data,
-					      skb->len, cb, cb_context);
-	default:
-		return 1;
-	}
-}
-
-static int pn544_hci_check_presence(struct nfc_hci_dev *hdev,
-				   struct nfc_target *target)
-{
-	return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
-				PN544_RF_READER_CMD_PRESENCE_CHECK,
-				NULL, 0, NULL);
-}
-
-static struct nfc_hci_ops pn544_hci_ops = {
-	.open = pn544_hci_open,
-	.close = pn544_hci_close,
-	.hci_ready = pn544_hci_ready,
-	.xmit = pn544_hci_xmit,
-	.start_poll = pn544_hci_start_poll,
-	.target_from_gate = pn544_hci_target_from_gate,
-	.complete_target_discovered = pn544_hci_complete_target_discovered,
-	.data_exchange = pn544_hci_data_exchange,
-	.check_presence = pn544_hci_check_presence,
-};
-
-static int __devinit pn544_hci_probe(struct i2c_client *client,
-				     const struct i2c_device_id *id)
-{
-	struct pn544_hci_info *info;
-	struct pn544_nfc_platform_data *pdata;
-	int r = 0;
-	u32 protocols;
-	struct nfc_hci_init_data init_data;
-
-	dev_dbg(&client->dev, "%s\n", __func__);
-	dev_dbg(&client->dev, "IRQ: %d\n", client->irq);
-
-	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-		dev_err(&client->dev, "Need I2C_FUNC_I2C\n");
-		return -ENODEV;
-	}
-
-	info = kzalloc(sizeof(struct pn544_hci_info), GFP_KERNEL);
-	if (!info) {
-		dev_err(&client->dev,
-			"Cannot allocate memory for pn544_hci_info.\n");
-		r = -ENOMEM;
-		goto err_info_alloc;
-	}
-
-	info->i2c_dev = client;
-	info->state = PN544_ST_COLD;
-	mutex_init(&info->info_lock);
-	i2c_set_clientdata(client, info);
-
-	pdata = client->dev.platform_data;
-	if (pdata == NULL) {
-		dev_err(&client->dev, "No platform data\n");
-		r = -EINVAL;
-		goto err_pdata;
-	}
-
-	if (pdata->request_resources == NULL) {
-		dev_err(&client->dev, "request_resources() missing\n");
-		r = -EINVAL;
-		goto err_pdata;
-	}
-
-	r = pdata->request_resources(client);
-	if (r) {
-		dev_err(&client->dev, "Cannot get platform resources\n");
-		goto err_pdata;
-	}
-
-	info->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE);
-	info->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET);
-	info->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ);
-
-	pn544_hci_platform_init(info);
-
-	r = request_threaded_irq(client->irq, NULL, pn544_hci_irq_thread_fn,
-				 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
-				 PN544_HCI_DRIVER_NAME, info);
-	if (r < 0) {
-		dev_err(&client->dev, "Unable to register IRQ handler\n");
-		goto err_rti;
-	}
-
-	init_data.gate_count = ARRAY_SIZE(pn544_gates);
-
-	memcpy(init_data.gates, pn544_gates, sizeof(pn544_gates));
-
-	/*
-	 * TODO: Session id must include the driver name + some bus addr
-	 * persistent info to discriminate 2 identical chips
-	 */
-	strcpy(init_data.session_id, "ID544HCI");
-
-	protocols = NFC_PROTO_JEWEL_MASK |
-		    NFC_PROTO_MIFARE_MASK |
-		    NFC_PROTO_FELICA_MASK |
-		    NFC_PROTO_ISO14443_MASK |
-		    NFC_PROTO_ISO14443_B_MASK |
-		    NFC_PROTO_NFC_DEP_MASK;
-
-	info->hdev = nfc_hci_allocate_device(&pn544_hci_ops, &init_data,
-					     protocols, LLC_SHDLC_NAME,
-					     PN544_FRAME_HEADROOM +
-					     PN544_CMDS_HEADROOM,
-					     PN544_FRAME_TAILROOM,
-					     PN544_HCI_LLC_MAX_PAYLOAD);
-	if (!info->hdev) {
-		dev_err(&client->dev, "Cannot allocate nfc hdev.\n");
-		r = -ENOMEM;
-		goto err_alloc_hdev;
-	}
-
-	nfc_hci_set_clientdata(info->hdev, info);
-
-	r = nfc_hci_register_device(info->hdev);
-	if (r)
-		goto err_regdev;
-
-	return 0;
-
-err_regdev:
-	nfc_hci_free_device(info->hdev);
-
-err_alloc_hdev:
-	free_irq(client->irq, info);
-
-err_rti:
-	if (pdata->free_resources != NULL)
-		pdata->free_resources();
-
-err_pdata:
-	kfree(info);
-
-err_info_alloc:
-	return r;
-}
-
-static __devexit int pn544_hci_remove(struct i2c_client *client)
-{
-	struct pn544_hci_info *info = i2c_get_clientdata(client);
-	struct pn544_nfc_platform_data *pdata = client->dev.platform_data;
-
-	dev_dbg(&client->dev, "%s\n", __func__);
-
-	nfc_hci_free_device(info->hdev);
-
-	if (info->state != PN544_ST_COLD) {
-		if (pdata->disable)
-			pdata->disable();
-	}
-
-	free_irq(client->irq, info);
-	if (pdata->free_resources)
-		pdata->free_resources();
-
-	kfree(info);
-
-	return 0;
-}
-
-static struct i2c_driver pn544_hci_driver = {
-	.driver = {
-		   .name = PN544_HCI_DRIVER_NAME,
-		  },
-	.probe = pn544_hci_probe,
-	.id_table = pn544_hci_id_table,
-	.remove = __devexit_p(pn544_hci_remove),
-};
-
-static int __init pn544_hci_init(void)
-{
-	int r;
-
-	pr_debug(DRIVER_DESC ": %s\n", __func__);
-
-	r = i2c_add_driver(&pn544_hci_driver);
-	if (r) {
-		pr_err(PN544_HCI_DRIVER_NAME ": driver registration failed\n");
-		return r;
-	}
-
-	return 0;
-}
-
-static void __exit pn544_hci_exit(void)
-{
-	i2c_del_driver(&pn544_hci_driver);
-}
-
-module_init(pn544_hci_init);
-module_exit(pn544_hci_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index e027f44..eafa107 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -1,4 +1,4 @@
-obj-y = base.o
+obj-y = base.o dma.o
 obj-$(CONFIG_OF_FLATTREE) += fdt.o
 obj-$(CONFIG_OF_PROMTREE) += pdt.o
 obj-$(CONFIG_OF_ADDRESS)  += address.o
diff --git a/drivers/of/base.c b/drivers/of/base.c
index af3b22a..676e259 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -594,27 +594,35 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
 EXPORT_SYMBOL(of_match_node);
 
 /**
- *	of_find_matching_node - Find a node based on an of_device_id match
- *				table.
+ *	of_find_matching_node_and_match - Find a node based on an of_device_id
+ *					  match table.
  *	@from:		The node to start searching from or NULL, the node
  *			you pass will not be searched, only the next one
  *			will; typically, you pass what the previous call
  *			returned. of_node_put() will be called on it
  *	@matches:	array of of device match structures to search in
+ *	@match		Updated to point at the matches entry which matched
  *
  *	Returns a node pointer with refcount incremented, use
  *	of_node_put() on it when done.
  */
-struct device_node *of_find_matching_node(struct device_node *from,
-					  const struct of_device_id *matches)
+struct device_node *of_find_matching_node_and_match(struct device_node *from,
+					const struct of_device_id *matches,
+					const struct of_device_id **match)
 {
 	struct device_node *np;
 
+	if (match)
+		*match = NULL;
+
 	read_lock(&devtree_lock);
 	np = from ? from->allnext : allnodes;
 	for (; np; np = np->allnext) {
-		if (of_match_node(matches, np) && of_node_get(np))
+		if (of_match_node(matches, np) && of_node_get(np)) {
+			if (match)
+				*match = matches;
 			break;
+		}
 	}
 	of_node_put(from);
 	read_unlock(&devtree_lock);
@@ -671,12 +679,89 @@ struct device_node *of_find_node_by_phandle(phandle handle)
 EXPORT_SYMBOL(of_find_node_by_phandle);
 
 /**
+ * of_property_read_u8_array - Find and read an array of u8 from a property.
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @out_value:	pointer to return value, modified only if return value is 0.
+ * @sz:		number of array elements to read
+ *
+ * Search for a property in a device node and read 8-bit value(s) from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * dts entry of array should be like:
+ *	property = /bits/ 8 <0x50 0x60 0x70>;
+ *
+ * The out_value is modified only if a valid u8 value can be decoded.
+ */
+int of_property_read_u8_array(const struct device_node *np,
+			const char *propname, u8 *out_values, size_t sz)
+{
+	struct property *prop = of_find_property(np, propname, NULL);
+	const u8 *val;
+
+	if (!prop)
+		return -EINVAL;
+	if (!prop->value)
+		return -ENODATA;
+	if ((sz * sizeof(*out_values)) > prop->length)
+		return -EOVERFLOW;
+
+	val = prop->value;
+	while (sz--)
+		*out_values++ = *val++;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u8_array);
+
+/**
+ * of_property_read_u16_array - Find and read an array of u16 from a property.
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @out_value:	pointer to return value, modified only if return value is 0.
+ * @sz:		number of array elements to read
+ *
+ * Search for a property in a device node and read 16-bit value(s) from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * dts entry of array should be like:
+ *	property = /bits/ 16 <0x5000 0x6000 0x7000>;
+ *
+ * The out_value is modified only if a valid u16 value can be decoded.
+ */
+int of_property_read_u16_array(const struct device_node *np,
+			const char *propname, u16 *out_values, size_t sz)
+{
+	struct property *prop = of_find_property(np, propname, NULL);
+	const __be16 *val;
+
+	if (!prop)
+		return -EINVAL;
+	if (!prop->value)
+		return -ENODATA;
+	if ((sz * sizeof(*out_values)) > prop->length)
+		return -EOVERFLOW;
+
+	val = prop->value;
+	while (sz--)
+		*out_values++ = be16_to_cpup(val++);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u16_array);
+
+/**
  * of_property_read_u32_array - Find and read an array of 32 bit integers
  * from a property.
  *
  * @np:		device node from which the property value is to be read.
  * @propname:	name of the property to be searched.
  * @out_value:	pointer to return value, modified only if return value is 0.
+ * @sz:		number of array elements to read
  *
  * Search for a property in a device node and read 32-bit value(s) from
  * it. Returns 0 on success, -EINVAL if the property does not exist,
@@ -1028,13 +1113,36 @@ int of_parse_phandle_with_args(struct device_node *np, const char *list_name,
 }
 EXPORT_SYMBOL(of_parse_phandle_with_args);
 
+#if defined(CONFIG_OF_DYNAMIC)
+static int of_property_notify(int action, struct device_node *np,
+			      struct property *prop)
+{
+	struct of_prop_reconfig pr;
+
+	pr.dn = np;
+	pr.prop = prop;
+	return of_reconfig_notify(action, &pr);
+}
+#else
+static int of_property_notify(int action, struct device_node *np,
+			      struct property *prop)
+{
+	return 0;
+}
+#endif
+
 /**
- * prom_add_property - Add a property to a node
+ * of_add_property - Add a property to a node
  */
-int prom_add_property(struct device_node *np, struct property *prop)
+int of_add_property(struct device_node *np, struct property *prop)
 {
 	struct property **next;
 	unsigned long flags;
+	int rc;
+
+	rc = of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop);
+	if (rc)
+		return rc;
 
 	prop->next = NULL;
 	write_lock_irqsave(&devtree_lock, flags);
@@ -1060,18 +1168,23 @@ int prom_add_property(struct device_node *np, struct property *prop)
 }
 
 /**
- * prom_remove_property - Remove a property from a node.
+ * of_remove_property - Remove a property from a node.
  *
  * Note that we don't actually remove it, since we have given out
  * who-knows-how-many pointers to the data using get-property.
  * Instead we just move the property to the "dead properties"
  * list, so it won't be found any more.
  */
-int prom_remove_property(struct device_node *np, struct property *prop)
+int of_remove_property(struct device_node *np, struct property *prop)
 {
 	struct property **next;
 	unsigned long flags;
 	int found = 0;
+	int rc;
+
+	rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop);
+	if (rc)
+		return rc;
 
 	write_lock_irqsave(&devtree_lock, flags);
 	next = &np->properties;
@@ -1101,7 +1214,7 @@ int prom_remove_property(struct device_node *np, struct property *prop)
 }
 
 /*
- * prom_update_property - Update a property in a node, if the property does
+ * of_update_property - Update a property in a node, if the property does
  * not exist, add it.
  *
  * Note that we don't actually remove it, since we have given out
@@ -1109,19 +1222,22 @@ int prom_remove_property(struct device_node *np, struct property *prop)
  * Instead we just move the property to the "dead properties" list,
  * and add the new property to the property list
  */
-int prom_update_property(struct device_node *np,
-			 struct property *newprop)
+int of_update_property(struct device_node *np, struct property *newprop)
 {
 	struct property **next, *oldprop;
 	unsigned long flags;
-	int found = 0;
+	int rc, found = 0;
+
+	rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
+	if (rc)
+		return rc;
 
 	if (!newprop->name)
 		return -EINVAL;
 
 	oldprop = of_find_property(np, newprop->name, NULL);
 	if (!oldprop)
-		return prom_add_property(np, newprop);
+		return of_add_property(np, newprop);
 
 	write_lock_irqsave(&devtree_lock, flags);
 	next = &np->properties;
@@ -1160,12 +1276,53 @@ int prom_update_property(struct device_node *np,
  * device tree nodes.
  */
 
+static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
+
+int of_reconfig_notifier_register(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&of_reconfig_chain, nb);
+}
+
+int of_reconfig_notifier_unregister(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
+}
+
+int of_reconfig_notify(unsigned long action, void *p)
+{
+	int rc;
+
+	rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
+	return notifier_to_errno(rc);
+}
+
+#ifdef CONFIG_PROC_DEVICETREE
+static void of_add_proc_dt_entry(struct device_node *dn)
+{
+	struct proc_dir_entry *ent;
+
+	ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde);
+	if (ent)
+		proc_device_tree_add_node(dn, ent);
+}
+#else
+static void of_add_proc_dt_entry(struct device_node *dn)
+{
+	return;
+}
+#endif
+
 /**
  * of_attach_node - Plug a device node into the tree and global list.
  */
-void of_attach_node(struct device_node *np)
+int of_attach_node(struct device_node *np)
 {
 	unsigned long flags;
+	int rc;
+
+	rc = of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np);
+	if (rc)
+		return rc;
 
 	write_lock_irqsave(&devtree_lock, flags);
 	np->sibling = np->parent->child;
@@ -1173,7 +1330,31 @@ void of_attach_node(struct device_node *np)
 	np->parent->child = np;
 	allnodes = np;
 	write_unlock_irqrestore(&devtree_lock, flags);
+
+	of_add_proc_dt_entry(np);
+	return 0;
+}
+
+#ifdef CONFIG_PROC_DEVICETREE
+static void of_remove_proc_dt_entry(struct device_node *dn)
+{
+	struct device_node *parent = dn->parent;
+	struct property *prop = dn->properties;
+
+	while (prop) {
+		remove_proc_entry(prop->name, dn->pde);
+		prop = prop->next;
+	}
+
+	if (dn->pde)
+		remove_proc_entry(dn->pde->name, parent->pde);
 }
+#else
+static void of_remove_proc_dt_entry(struct device_node *dn)
+{
+	return;
+}
+#endif
 
 /**
  * of_detach_node - "Unplug" a node from the device tree.
@@ -1181,16 +1362,29 @@ void of_attach_node(struct device_node *np)
  * The caller must hold a reference to the node.  The memory associated with
  * the node is not freed until its refcount goes to zero.
  */
-void of_detach_node(struct device_node *np)
+int of_detach_node(struct device_node *np)
 {
 	struct device_node *parent;
 	unsigned long flags;
+	int rc = 0;
+
+	rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
+	if (rc)
+		return rc;
 
 	write_lock_irqsave(&devtree_lock, flags);
 
+	if (of_node_check_flag(np, OF_DETACHED)) {
+		/* someone already detached it */
+		write_unlock_irqrestore(&devtree_lock, flags);
+		return rc;
+	}
+
 	parent = np->parent;
-	if (!parent)
-		goto out_unlock;
+	if (!parent) {
+		write_unlock_irqrestore(&devtree_lock, flags);
+		return rc;
+	}
 
 	if (allnodes == np)
 		allnodes = np->allnext;
@@ -1215,9 +1409,10 @@ void of_detach_node(struct device_node *np)
 	}
 
 	of_node_set_flag(np, OF_DETACHED);
-
-out_unlock:
 	write_unlock_irqrestore(&devtree_lock, flags);
+
+	of_remove_proc_dt_entry(np);
+	return rc;
 }
 #endif /* defined(CONFIG_OF_DYNAMIC) */
 
diff --git a/drivers/of/dma.c b/drivers/of/dma.c
new file mode 100644
index 0000000..59631b2
--- /dev/null
+++ b/drivers/of/dma.c
@@ -0,0 +1,264 @@
+/*
+ * Device tree helpers for DMA request / controller
+ *
+ * Based on of_gpio.c
+ *
+ * Copyright (C) 2012 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.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/rculist.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_dma.h>
+
+static LIST_HEAD(of_dma_list);
+static DEFINE_SPINLOCK(of_dma_lock);
+
+/**
+ * of_dma_get_controller - Get a DMA controller in DT DMA helpers list
+ * @dma_spec:	pointer to DMA specifier as found in the device tree
+ *
+ * Finds a DMA controller with matching device node and number for dma cells
+ * in a list of registered DMA controllers. If a match is found the use_count
+ * variable is increased and a valid pointer to the DMA data stored is retuned.
+ * A NULL pointer is returned if no match is found.
+ */
+static struct of_dma *of_dma_get_controller(struct of_phandle_args *dma_spec)
+{
+	struct of_dma *ofdma;
+
+	spin_lock(&of_dma_lock);
+
+	if (list_empty(&of_dma_list)) {
+		spin_unlock(&of_dma_lock);
+		return NULL;
+	}
+
+	list_for_each_entry(ofdma, &of_dma_list, of_dma_controllers)
+		if ((ofdma->of_node == dma_spec->np) &&
+		    (ofdma->of_dma_nbcells == dma_spec->args_count)) {
+			ofdma->use_count++;
+			spin_unlock(&of_dma_lock);
+			return ofdma;
+		}
+
+	spin_unlock(&of_dma_lock);
+
+	pr_debug("%s: can't find DMA controller %s\n", __func__,
+		 dma_spec->np->full_name);
+
+	return NULL;
+}
+
+/**
+ * of_dma_put_controller - Decrement use count for a registered DMA controller
+ * @of_dma:	pointer to DMA controller data
+ *
+ * Decrements the use_count variable in the DMA data structure. This function
+ * should be called only when a valid pointer is returned from
+ * of_dma_get_controller() and no further accesses to data referenced by that
+ * pointer are needed.
+ */
+static void of_dma_put_controller(struct of_dma *ofdma)
+{
+	spin_lock(&of_dma_lock);
+	ofdma->use_count--;
+	spin_unlock(&of_dma_lock);
+}
+
+/**
+ * of_dma_controller_register - Register a DMA controller to DT DMA helpers
+ * @np:			device node of DMA controller
+ * @of_dma_xlate:	translation function which converts a phandle
+ *			arguments list into a dma_chan structure
+ * @data		pointer to controller specific data to be used by
+ *			translation function
+ *
+ * Returns 0 on success or appropriate errno value on error.
+ *
+ * Allocated memory should be freed with appropriate of_dma_controller_free()
+ * call.
+ */
+int of_dma_controller_register(struct device_node *np,
+				struct dma_chan *(*of_dma_xlate)
+				(struct of_phandle_args *, struct of_dma *),
+				void *data)
+{
+	struct of_dma	*ofdma;
+	int		nbcells;
+
+	if (!np || !of_dma_xlate) {
+		pr_err("%s: not enough information provided\n", __func__);
+		return -EINVAL;
+	}
+
+	ofdma = kzalloc(sizeof(*ofdma), GFP_KERNEL);
+	if (!ofdma)
+		return -ENOMEM;
+
+	nbcells = be32_to_cpup(of_get_property(np, "#dma-cells", NULL));
+	if (!nbcells) {
+		pr_err("%s: #dma-cells property is missing or invalid\n",
+		       __func__);
+		return -EINVAL;
+	}
+
+	ofdma->of_node = np;
+	ofdma->of_dma_nbcells = nbcells;
+	ofdma->of_dma_xlate = of_dma_xlate;
+	ofdma->of_dma_data = data;
+	ofdma->use_count = 0;
+
+	/* Now queue of_dma controller structure in list */
+	list_add_tail(&ofdma->of_dma_controllers, &of_dma_list);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_dma_controller_register);
+
+/**
+ * of_dma_controller_free - Remove a DMA controller from DT DMA helpers list
+ * @np:		device node of DMA controller
+ *
+ * Memory allocated by of_dma_controller_register() is freed here.
+ */
+int of_dma_controller_free(struct device_node *np)
+{
+	struct of_dma *ofdma;
+
+	spin_lock(&of_dma_lock);
+
+	if (list_empty(&of_dma_list)) {
+		spin_unlock(&of_dma_lock);
+		return -ENODEV;
+	}
+
+	list_for_each_entry(ofdma, &of_dma_list, of_dma_controllers)
+		if (ofdma->of_node == np) {
+			if (ofdma->use_count) {
+				spin_unlock(&of_dma_lock);
+				return -EBUSY;
+			}
+
+			list_del(&ofdma->of_dma_controllers);
+			spin_unlock(&of_dma_lock);
+			kfree(ofdma);
+			return 0;
+		}
+
+	spin_unlock(&of_dma_lock);
+	return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(of_dma_controller_free);
+
+/**
+ * of_dma_match_channel - Check if a DMA specifier matches name
+ * @np:		device node to look for DMA channels
+ * @name:	channel name to be matched
+ * @index:	index of DMA specifier in list of DMA specifiers
+ * @dma_spec:	pointer to DMA specifier as found in the device tree
+ *
+ * Check if the DMA specifier pointed to by the index in a list of DMA
+ * specifiers, matches the name provided. Returns 0 if the name matches and
+ * a valid pointer to the DMA specifier is found. Otherwise returns -ENODEV.
+ */
+static int of_dma_match_channel(struct device_node *np, char *name, int index,
+				struct of_phandle_args *dma_spec)
+{
+	const char *s;
+
+	if (of_property_read_string_index(np, "dma-names", index, &s))
+		return -ENODEV;
+
+	if (strcmp(name, s))
+		return -ENODEV;
+
+	if (of_parse_phandle_with_args(np, "dmas", "#dma-cells", index,
+				       dma_spec))
+		return -ENODEV;
+
+	return 0;
+}
+
+/**
+ * of_dma_request_slave_channel - Get the DMA slave channel
+ * @np:		device node to get DMA request from
+ * @name:	name of desired channel
+ *
+ * Returns pointer to appropriate dma channel on success or NULL on error.
+ */
+struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
+					      char *name)
+{
+	struct of_phandle_args	dma_spec;
+	struct of_dma		*ofdma;
+	struct dma_chan		*chan;
+	int			count, i;
+
+	if (!np || !name) {
+		pr_err("%s: not enough information provided\n", __func__);
+		return NULL;
+	}
+
+	count = of_property_count_strings(np, "dma-names");
+	if (count < 0) {
+		pr_err("%s: dma-names property missing or empty\n", __func__);
+		return NULL;
+	}
+
+	for (i = 0; i < count; i++) {
+		if (of_dma_match_channel(np, name, i, &dma_spec))
+			continue;
+
+		ofdma = of_dma_get_controller(&dma_spec);
+
+		if (!ofdma)
+			continue;
+
+		chan = ofdma->of_dma_xlate(&dma_spec, ofdma);
+
+		of_dma_put_controller(ofdma);
+
+		of_node_put(dma_spec.np);
+
+		if (chan)
+			return chan;
+	}
+
+	return NULL;
+}
+
+/**
+ * of_dma_simple_xlate - Simple DMA engine translation function
+ * @dma_spec:	pointer to DMA specifier as found in the device tree
+ * @of_dma:	pointer to DMA controller data
+ *
+ * A simple translation function for devices that use a 32-bit value for the
+ * filter_param when calling the DMA engine dma_request_channel() function.
+ * Note that this translation function requires that #dma-cells is equal to 1
+ * and the argument of the dma specifier is the 32-bit filter_param. Returns
+ * pointer to appropriate dma channel on success or NULL on error.
+ */
+struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
+						struct of_dma *ofdma)
+{
+	int count = dma_spec->args_count;
+	struct of_dma_filter_info *info = ofdma->of_dma_data;
+
+	if (!info || !info->filter_fn)
+		return NULL;
+
+	if (count != 1)
+		return NULL;
+
+	return dma_request_channel(info->dma_cap, info->filter_fn,
+			&dma_spec->args[0]);
+}
+EXPORT_SYMBOL_GPL(of_dma_simple_xlate);
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 91a375f..c52f361 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -186,6 +186,8 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob,
 			 */
 			fpsize = 1;
 			allocl = 2;
+			l = 1;
+			*pathp = '\0';
 		} else {
 			/* account for '/' and path size minus terminal 0
 			 * already in 'l'
@@ -198,10 +200,10 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob,
 	np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
 				__alignof__(struct device_node));
 	if (allnextpp) {
+		char *fn;
 		memset(np, 0, sizeof(*np));
-		np->full_name = ((char *)np) + sizeof(struct device_node);
+		np->full_name = fn = ((char *)np) + sizeof(*np);
 		if (new_format) {
-			char *fn = np->full_name;
 			/* rebuild full path for new format */
 			if (dad && dad->parent) {
 				strcpy(fn, dad->full_name);
@@ -215,9 +217,9 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob,
 				fn += strlen(fn);
 			}
 			*(fn++) = '/';
-			memcpy(fn, pathp, l);
-		} else
-			memcpy(np->full_name, pathp, l);
+		}
+		memcpy(fn, pathp, l);
+
 		prev_pp = &np->properties;
 		**allnextpp = np;
 		*allnextpp = &np->allnext;
@@ -459,7 +461,7 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
 
 	do {
 		u32 tag = be32_to_cpup((__be32 *)p);
-		char *pathp;
+		const char *pathp;
 
 		p += 4;
 		if (tag == OF_DT_END_NODE) {
@@ -486,14 +488,8 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
 		depth++;
 		pathp = (char *)p;
 		p = ALIGN(p + strlen(pathp) + 1, 4);
-		if ((*pathp) == '/') {
-			char *lp, *np;
-			for (lp = NULL, np = pathp; *np; np++)
-				if ((*np) == '/')
-					lp = np+1;
-			if (lp != NULL)
-				pathp = lp;
-		}
+		if (*pathp == '/')
+			pathp = kbasename(pathp);
 		rc = it(p, pathp, depth, data);
 		if (rc != 0)
 			break;
diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
index 3550f3b..2552fc5 100644
--- a/drivers/of/of_i2c.c
+++ b/drivers/of/of_i2c.c
@@ -37,6 +37,9 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
 
 		dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name);
 
+		if (!of_device_is_available(node))
+			continue;
+
 		if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
 			dev_err(&adap->dev, "of_i2c: modalias failure on %s\n",
 				node->full_name);
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index 4b6e4e7..0e60438 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -57,8 +57,8 @@ config PARPORT_SERIAL
 	  will be called parport_serial.
 
 config PARPORT_PC_FIFO
-	bool "Use FIFO/DMA if available (EXPERIMENTAL)"
-	depends on PARPORT_PC && EXPERIMENTAL
+	bool "Use FIFO/DMA if available"
+	depends on PARPORT_PC
 	help
 	  Many parallel port chipsets provide hardware that can speed up
 	  printing. Say Y here if you want to take advantage of that.
@@ -70,8 +70,8 @@ config PARPORT_PC_FIFO
 	  specify which IRQ/DMA to use.
 
 config PARPORT_PC_SUPERIO
-	bool "SuperIO chipset support (EXPERIMENTAL)"
-	depends on PARPORT_PC && EXPERIMENTAL
+	bool "SuperIO chipset support"
+	depends on PARPORT_PC
 	help
 	  Saying Y here enables some probes for Super-IO chipsets in order to
 	  find out things like base addresses, IRQ lines and DMA channels.  It
@@ -85,8 +85,8 @@ config PARPORT_PC_PCMCIA
 	  ports. If unsure, say N.
 
 config PARPORT_IP32
-	tristate "SGI IP32 builtin port (EXPERIMENTAL)"
-	depends on SGI_IP32 && EXPERIMENTAL
+	tristate "SGI IP32 builtin port"
+	depends on SGI_IP32
 	select PARPORT_NOT_PC
 	help
 	  Say Y here if you need support for the parallel port on
@@ -126,8 +126,8 @@ config PARPORT_GSC
 	select PARPORT_NOT_PC
 
 config PARPORT_SUNBPP
-	tristate "Sparc hardware (EXPERIMENTAL)"
-	depends on SBUS && EXPERIMENTAL
+	tristate "Sparc hardware"
+	depends on SBUS
 	select PARPORT_NOT_PC
 	help
 	  This driver provides support for the bidirectional parallel port
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 8d688b2..0c3efcf 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -4,7 +4,7 @@
 
 obj-y		+= access.o bus.o probe.o host-bridge.o remove.o pci.o \
 			pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
-			irq.o vpd.o
+			irq.o vpd.o setup-bus.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSFS) += slot.o
 
@@ -15,8 +15,6 @@ obj-$(CONFIG_PCIEPORTBUS) += pcie/
 
 obj-$(CONFIG_PCI_IOAPIC) += ioapic.o
 
-obj-$(CONFIG_HOTPLUG) += hotplug.o
-
 # Build the PCI Hotplug drivers if we were asked to
 obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
 ifdef CONFIG_HOTPLUG_PCI
@@ -60,9 +58,6 @@ obj-$(CONFIG_ACPI)    += pci-acpi.o
 # SMBIOS provided firmware instance and labels
 obj-$(CONFIG_PCI_LABEL) += pci-label.o
 
-# Cardbus & CompactPCI use setup-bus
-obj-$(CONFIG_HOTPLUG) += setup-bus.o
-
 obj-$(CONFIG_PCI_SYSCALL) += syscall.o
 
 obj-$(CONFIG_PCI_STUB) += pci-stub.o
diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
deleted file mode 100644
index 2b5352a..0000000
--- a/drivers/pci/hotplug.c
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/module.h>
-#include "pci.h"
-
-int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-	struct pci_dev *pdev;
-
-	if (!dev)
-		return -ENODEV;
-
-	pdev = to_pci_dev(dev);
-	if (!pdev)
-		return -ENODEV;
-
-	if (add_uevent_var(env, "PCI_CLASS=%04X", pdev->class))
-		return -ENOMEM;
-
-	if (add_uevent_var(env, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
-		return -ENOMEM;
-
-	if (add_uevent_var(env, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
-			   pdev->subsystem_device))
-		return -ENOMEM;
-
-	if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev)))
-		return -ENOMEM;
-
-	if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
-			   pdev->vendor, pdev->device,
-			   pdev->subsystem_vendor, pdev->subsystem_device,
-			   (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
-			   (u8)(pdev->class)))
-		return -ENOMEM;
-	return 0;
-}
diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c
index 6bf8d2a..449b4bb 100644
--- a/drivers/pci/hotplug/cpcihp_zt5550.c
+++ b/drivers/pci/hotplug/cpcihp_zt5550.c
@@ -271,7 +271,7 @@ init_hc_error:
 
 }
 
-static void __devexit zt5550_hc_remove_one(struct pci_dev *pdev)
+static void zt5550_hc_remove_one(struct pci_dev *pdev)
 {
 	cpci_hp_stop();
 	cpci_hp_unregister_bus(bus0);
@@ -290,7 +290,7 @@ static struct pci_driver zt5550_hc_driver = {
 	.name		= "zt5550_hc",
 	.id_table	= zt5550_hc_pci_tbl,
 	.probe		= zt5550_hc_init_one,
-	.remove		= __devexit_p(zt5550_hc_remove_one),
+	.remove		= zt5550_hc_remove_one,
 };
 
 static int __init zt5550_init(void)
diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
index 205af8d..3c6bbdd 100644
--- a/drivers/pci/ioapic.c
+++ b/drivers/pci/ioapic.c
@@ -27,7 +27,7 @@ struct ioapic {
 	u32		gsi_base;
 };
 
-static int __devinit ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
 {
 	acpi_handle handle;
 	acpi_status status;
@@ -88,7 +88,7 @@ exit_free:
 	return -ENODEV;
 }
 
-static void __devexit ioapic_remove(struct pci_dev *dev)
+static void ioapic_remove(struct pci_dev *dev)
 {
 	struct ioapic *ioapic = pci_get_drvdata(dev);
 
@@ -110,7 +110,7 @@ static struct pci_driver ioapic_driver = {
 	.name		= "ioapic",
 	.id_table	= ioapic_devices,
 	.probe		= ioapic_probe,
-	.remove		= __devexit_p(ioapic_remove),
+	.remove		= ioapic_remove,
 };
 
 static int __init ioapic_init(void)
@@ -125,3 +125,5 @@ static void __exit ioapic_exit(void)
 
 module_init(ioapic_init);
 module_exit(ioapic_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index aeccc91..bafd2bb 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -106,7 +106,7 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
 		virtfn->resource[i].name = pci_name(virtfn);
 		virtfn->resource[i].flags = res->flags;
 		size = resource_size(res);
-		do_div(size, iov->total);
+		do_div(size, iov->total_VFs);
 		virtfn->resource[i].start = res->start + size * id;
 		virtfn->resource[i].end = virtfn->resource[i].start + size - 1;
 		rc = request_resource(res, &virtfn->resource[i]);
@@ -194,7 +194,7 @@ static int sriov_migration(struct pci_dev *dev)
 	u16 status;
 	struct pci_sriov *iov = dev->sriov;
 
-	if (!iov->nr_virtfn)
+	if (!iov->num_VFs)
 		return 0;
 
 	if (!(iov->cap & PCI_SRIOV_CAP_VFM))
@@ -216,7 +216,7 @@ static void sriov_migration_task(struct work_struct *work)
 	u16 status;
 	struct pci_sriov *iov = container_of(work, struct pci_sriov, mtask);
 
-	for (i = iov->initial; i < iov->nr_virtfn; i++) {
+	for (i = iov->initial_VFs; i < iov->num_VFs; i++) {
 		state = readb(iov->mstate + i);
 		if (state == PCI_SRIOV_VFM_MI) {
 			writeb(PCI_SRIOV_VFM_AV, iov->mstate + i);
@@ -244,7 +244,7 @@ static int sriov_enable_migration(struct pci_dev *dev, int nr_virtfn)
 	resource_size_t pa;
 	struct pci_sriov *iov = dev->sriov;
 
-	if (nr_virtfn <= iov->initial)
+	if (nr_virtfn <= iov->initial_VFs)
 		return 0;
 
 	pci_read_config_dword(dev, iov->pos + PCI_SRIOV_VFM, &table);
@@ -294,15 +294,15 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
 	if (!nr_virtfn)
 		return 0;
 
-	if (iov->nr_virtfn)
+	if (iov->num_VFs)
 		return -EINVAL;
 
 	pci_read_config_word(dev, iov->pos + PCI_SRIOV_INITIAL_VF, &initial);
-	if (initial > iov->total ||
-	    (!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total)))
+	if (initial > iov->total_VFs ||
+	    (!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total_VFs)))
 		return -EIO;
 
-	if (nr_virtfn < 0 || nr_virtfn > iov->total ||
+	if (nr_virtfn < 0 || nr_virtfn > iov->total_VFs ||
 	    (!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial)))
 		return -EINVAL;
 
@@ -359,7 +359,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
 	msleep(100);
 	pci_cfg_access_unlock(dev);
 
-	iov->initial = initial;
+	iov->initial_VFs = initial;
 	if (nr_virtfn < initial)
 		initial = nr_virtfn;
 
@@ -376,7 +376,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
 	}
 
 	kobject_uevent(&dev->dev.kobj, KOBJ_CHANGE);
-	iov->nr_virtfn = nr_virtfn;
+	iov->num_VFs = nr_virtfn;
 
 	return 0;
 
@@ -401,13 +401,13 @@ static void sriov_disable(struct pci_dev *dev)
 	int i;
 	struct pci_sriov *iov = dev->sriov;
 
-	if (!iov->nr_virtfn)
+	if (!iov->num_VFs)
 		return;
 
 	if (iov->cap & PCI_SRIOV_CAP_VFM)
 		sriov_disable_migration(dev);
 
-	for (i = 0; i < iov->nr_virtfn; i++)
+	for (i = 0; i < iov->num_VFs; i++)
 		virtfn_remove(dev, i, 0);
 
 	iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
@@ -419,7 +419,7 @@ static void sriov_disable(struct pci_dev *dev)
 	if (iov->link != dev->devfn)
 		sysfs_remove_link(&dev->dev.kobj, "dep_link");
 
-	iov->nr_virtfn = 0;
+	iov->num_VFs = 0;
 }
 
 static int sriov_init(struct pci_dev *dev, int pos)
@@ -496,7 +496,7 @@ found:
 	iov->pos = pos;
 	iov->nres = nres;
 	iov->ctrl = ctrl;
-	iov->total = total;
+	iov->total_VFs = total;
 	iov->offset = offset;
 	iov->stride = stride;
 	iov->pgsz = pgsz;
@@ -529,7 +529,7 @@ failed:
 
 static void sriov_release(struct pci_dev *dev)
 {
-	BUG_ON(dev->sriov->nr_virtfn);
+	BUG_ON(dev->sriov->num_VFs);
 
 	if (dev != dev->sriov->dev)
 		pci_dev_put(dev->sriov->dev);
@@ -554,7 +554,7 @@ static void sriov_restore_state(struct pci_dev *dev)
 		pci_update_resource(dev, i);
 
 	pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz);
-	pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, iov->nr_virtfn);
+	pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, iov->num_VFs);
 	pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
 	if (iov->ctrl & PCI_SRIOV_CTRL_VFE)
 		msleep(100);
@@ -661,7 +661,7 @@ int pci_iov_bus_range(struct pci_bus *bus)
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		if (!dev->is_physfn)
 			continue;
-		busnr = virtfn_bus(dev, dev->sriov->total - 1);
+		busnr = virtfn_bus(dev, dev->sriov->total_VFs - 1);
 		if (busnr > max)
 			max = busnr;
 	}
@@ -729,9 +729,56 @@ EXPORT_SYMBOL_GPL(pci_sriov_migration);
  */
 int pci_num_vf(struct pci_dev *dev)
 {
-	if (!dev || !dev->is_physfn)
+	if (!dev->is_physfn)
 		return 0;
-	else
-		return dev->sriov->nr_virtfn;
+
+	return dev->sriov->num_VFs;
 }
 EXPORT_SYMBOL_GPL(pci_num_vf);
+
+/**
+ * pci_sriov_set_totalvfs -- reduce the TotalVFs available
+ * @dev: the PCI PF device
+ * numvfs: number that should be used for TotalVFs supported
+ *
+ * Should be called from PF driver's probe routine with
+ * device's mutex held.
+ *
+ * Returns 0 if PF is an SRIOV-capable device and
+ * value of numvfs valid. If not a PF with VFS, return -EINVAL;
+ * if VFs already enabled, return -EBUSY.
+ */
+int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
+{
+	if (!dev->is_physfn || (numvfs > dev->sriov->total_VFs))
+		return -EINVAL;
+
+	/* Shouldn't change if VFs already enabled */
+	if (dev->sriov->ctrl & PCI_SRIOV_CTRL_VFE)
+		return -EBUSY;
+	else
+		dev->sriov->driver_max_VFs = numvfs;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pci_sriov_set_totalvfs);
+
+/**
+ * pci_sriov_get_totalvfs -- get total VFs supported on this devic3
+ * @dev: the PCI PF device
+ *
+ * For a PCIe device with SRIOV support, return the PCIe
+ * SRIOV capability value of TotalVFs or the value of driver_max_VFs
+ * if the driver reduced it.  Otherwise, -EINVAL.
+ */
+int pci_sriov_get_totalvfs(struct pci_dev *dev)
+{
+	if (!dev->is_physfn)
+		return -EINVAL;
+
+	if (dev->sriov->driver_max_VFs)
+		return dev->sriov->driver_max_VFs;
+
+	return dev->sriov->total_VFs;
+}
+EXPORT_SYMBOL_GPL(pci_sriov_get_totalvfs);
diff --git a/drivers/pci/irq.c b/drivers/pci/irq.c
index e5f69a4..b008cf8 100644
--- a/drivers/pci/irq.c
+++ b/drivers/pci/irq.c
@@ -14,11 +14,11 @@ static void pci_note_irq_problem(struct pci_dev *pdev, const char *reason)
 {
 	struct pci_dev *parent = to_pci_dev(pdev->dev.parent);
 
-	dev_printk(KERN_ERR, &pdev->dev,
-		   "Potentially misrouted IRQ (Bridge %s %04x:%04x)\n",
-		   dev_name(&parent->dev), parent->vendor, parent->device);
-	dev_printk(KERN_ERR, &pdev->dev, "%s\n", reason);
-	dev_printk(KERN_ERR, &pdev->dev, "Please report to linux-kernel@vger.kernel.org\n");
+	dev_err(&pdev->dev,
+		"Potentially misrouted IRQ (Bridge %s %04x:%04x)\n",
+		dev_name(&parent->dev), parent->vendor, parent->device);
+	dev_err(&pdev->dev, "%s\n", reason);
+	dev_err(&pdev->dev, "Please report to linux-kernel@vger.kernel.org\n");
 	WARN_ON(1);
 }
 
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index c5792d6..1af4008 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -17,10 +17,9 @@
 
 #include <linux/pci-acpi.h>
 #include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
 #include "pci.h"
 
-static DEFINE_MUTEX(pci_acpi_pm_notify_mtx);
-
 /**
  * pci_acpi_wake_bus - Wake-up notification handler for root buses.
  * @handle: ACPI handle of a device the notification is for.
@@ -68,67 +67,6 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
 }
 
 /**
- * add_pm_notifier - Register PM notifier for given ACPI device.
- * @dev: ACPI device to add the notifier for.
- * @context: PCI device or bus to check for PME status if an event is signaled.
- *
- * NOTE: @dev need not be a run-wake or wake-up device to be a valid source of
- * PM wake-up events.  For example, wake-up events may be generated for bridges
- * if one of the devices below the bridge is signaling PME, even if the bridge
- * itself doesn't have a wake-up GPE associated with it.
- */
-static acpi_status add_pm_notifier(struct acpi_device *dev,
-				   acpi_notify_handler handler,
-				   void *context)
-{
-	acpi_status status = AE_ALREADY_EXISTS;
-
-	mutex_lock(&pci_acpi_pm_notify_mtx);
-
-	if (dev->wakeup.flags.notifier_present)
-		goto out;
-
-	status = acpi_install_notify_handler(dev->handle,
-					     ACPI_SYSTEM_NOTIFY,
-					     handler, context);
-	if (ACPI_FAILURE(status))
-		goto out;
-
-	dev->wakeup.flags.notifier_present = true;
-
- out:
-	mutex_unlock(&pci_acpi_pm_notify_mtx);
-	return status;
-}
-
-/**
- * remove_pm_notifier - Unregister PM notifier from given ACPI device.
- * @dev: ACPI device to remove the notifier from.
- */
-static acpi_status remove_pm_notifier(struct acpi_device *dev,
-				      acpi_notify_handler handler)
-{
-	acpi_status status = AE_BAD_PARAMETER;
-
-	mutex_lock(&pci_acpi_pm_notify_mtx);
-
-	if (!dev->wakeup.flags.notifier_present)
-		goto out;
-
-	status = acpi_remove_notify_handler(dev->handle,
-					    ACPI_SYSTEM_NOTIFY,
-					    handler);
-	if (ACPI_FAILURE(status))
-		goto out;
-
-	dev->wakeup.flags.notifier_present = false;
-
- out:
-	mutex_unlock(&pci_acpi_pm_notify_mtx);
-	return status;
-}
-
-/**
  * pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus.
  * @dev: ACPI device to add the notifier for.
  * @pci_bus: PCI bus to walk checking for PME status if an event is signaled.
@@ -136,7 +74,7 @@ static acpi_status remove_pm_notifier(struct acpi_device *dev,
 acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev,
 					 struct pci_bus *pci_bus)
 {
-	return add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus);
+	return acpi_add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus);
 }
 
 /**
@@ -145,7 +83,7 @@ acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev,
  */
 acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
 {
-	return remove_pm_notifier(dev, pci_acpi_wake_bus);
+	return acpi_remove_pm_notifier(dev, pci_acpi_wake_bus);
 }
 
 /**
@@ -156,7 +94,7 @@ acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
 acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
 				     struct pci_dev *pci_dev)
 {
-	return add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev);
+	return acpi_add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev);
 }
 
 /**
@@ -165,7 +103,7 @@ acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
  */
 acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
 {
-	return remove_pm_notifier(dev, pci_acpi_wake_dev);
+	return acpi_remove_pm_notifier(dev, pci_acpi_wake_dev);
 }
 
 phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
@@ -257,11 +195,16 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
 		return -ENODEV;
 
 	switch (state) {
+	case PCI_D3cold:
+		if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) ==
+				PM_QOS_FLAGS_ALL) {
+			error = -EBUSY;
+			break;
+		}
 	case PCI_D0:
 	case PCI_D1:
 	case PCI_D2:
 	case PCI_D3hot:
-	case PCI_D3cold:
 		error = acpi_bus_set_power(handle, state_conv[state]);
 	}
 
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 6c94fc9..f7b96cb 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -89,10 +89,6 @@ static void pci_free_dynids(struct pci_driver *drv)
 	spin_unlock(&drv->dynids.lock);
 }
 
-/*
- * Dynamic device ID manipulation via sysfs is disabled for !CONFIG_HOTPLUG
- */
-#ifdef CONFIG_HOTPLUG
 /**
  * store_new_id - sysfs frontend to pci_add_dynid()
  * @driver: target device driver
@@ -191,10 +187,6 @@ static struct driver_attribute pci_drv_attrs[] = {
 	__ATTR_NULL,
 };
 
-#else
-#define pci_drv_attrs	NULL
-#endif /* CONFIG_HOTPLUG */
-
 /**
  * pci_match_id - See if a pci device matches a given pci_id table
  * @ids: array of PCI device id structures to search in
@@ -1015,10 +1007,10 @@ static int pci_pm_runtime_suspend(struct device *dev)
 		return 0;
 	}
 
-	if (!pci_dev->state_saved)
+	if (!pci_dev->state_saved) {
 		pci_save_state(pci_dev);
-
-	pci_finish_runtime_suspend(pci_dev);
+		pci_finish_runtime_suspend(pci_dev);
+	}
 
 	return 0;
 }
@@ -1223,12 +1215,38 @@ void pci_dev_put(struct pci_dev *dev)
 		put_device(&dev->dev);
 }
 
-#ifndef CONFIG_HOTPLUG
-int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
+static int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
-	return -ENODEV;
+	struct pci_dev *pdev;
+
+	if (!dev)
+		return -ENODEV;
+
+	pdev = to_pci_dev(dev);
+	if (!pdev)
+		return -ENODEV;
+
+	if (add_uevent_var(env, "PCI_CLASS=%04X", pdev->class))
+		return -ENOMEM;
+
+	if (add_uevent_var(env, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
+		return -ENOMEM;
+
+	if (add_uevent_var(env, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
+			   pdev->subsystem_device))
+		return -ENOMEM;
+
+	if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev)))
+		return -ENOMEM;
+
+	if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
+			   pdev->vendor, pdev->device,
+			   pdev->subsystem_vendor, pdev->subsystem_device,
+			   (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
+			   (u8)(pdev->class)))
+		return -ENOMEM;
+	return 0;
 }
-#endif
 
 struct bus_type pci_bus_type = {
 	.name		= "pci",
diff --git a/drivers/pci/pci-stub.c b/drivers/pci/pci-stub.c
index 775e933..6e47c51 100644
--- a/drivers/pci/pci-stub.c
+++ b/drivers/pci/pci-stub.c
@@ -28,7 +28,7 @@ MODULE_PARM_DESC(ids, "Initial PCI IDs to add to the stub driver, format is "
 
 static int pci_stub_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
-	dev_printk(KERN_INFO, &dev->dev, "claimed by stub\n");
+	dev_info(&dev->dev, "claimed by stub\n");
 	return 0;
 }
 
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index f39378d..05b78b1 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -284,7 +284,6 @@ msi_bus_store(struct device *dev, struct device_attribute *attr,
 	return count;
 }
 
-#ifdef CONFIG_HOTPLUG
 static DEFINE_MUTEX(pci_remove_rescan_mutex);
 static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf,
 				size_t count)
@@ -377,8 +376,6 @@ dev_bus_rescan_store(struct device *dev, struct device_attribute *attr,
 	return count;
 }
 
-#endif
-
 #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI)
 static ssize_t d3cold_allowed_store(struct device *dev,
 				    struct device_attribute *attr,
@@ -404,6 +401,106 @@ static ssize_t d3cold_allowed_show(struct device *dev,
 }
 #endif
 
+#ifdef CONFIG_PCI_IOV
+static ssize_t sriov_totalvfs_show(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buf)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+
+	return sprintf(buf, "%u\n", pci_sriov_get_totalvfs(pdev));
+}
+
+
+static ssize_t sriov_numvfs_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+
+	return sprintf(buf, "%u\n", pdev->sriov->num_VFs);
+}
+
+/*
+ * num_vfs > 0; number of vfs to enable
+ * num_vfs = 0; disable all vfs
+ *
+ * Note: SRIOV spec doesn't allow partial VF
+ *       disable, so its all or none.
+ */
+static ssize_t sriov_numvfs_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	int num_vfs_enabled = 0;
+	int num_vfs;
+	int ret = 0;
+	u16 total;
+
+	if (kstrtoint(buf, 0, &num_vfs) < 0)
+		return -EINVAL;
+
+	/* is PF driver loaded w/callback */
+	if (!pdev->driver || !pdev->driver->sriov_configure) {
+		dev_info(&pdev->dev,
+			 "Driver doesn't support SRIOV configuration via sysfs\n");
+		return -ENOSYS;
+	}
+
+	/* if enabling vf's ... */
+	total = pci_sriov_get_totalvfs(pdev);
+	/* Requested VFs to enable < totalvfs and none enabled already */
+	if ((num_vfs > 0) && (num_vfs <= total)) {
+		if (pdev->sriov->num_VFs == 0) {
+			num_vfs_enabled =
+				pdev->driver->sriov_configure(pdev, num_vfs);
+			if ((num_vfs_enabled >= 0) &&
+			    (num_vfs_enabled != num_vfs)) {
+				dev_warn(&pdev->dev,
+					 "Only %d VFs enabled\n",
+					 num_vfs_enabled);
+				return count;
+			} else if (num_vfs_enabled < 0)
+				/* error code from driver callback */
+				return num_vfs_enabled;
+		} else if (num_vfs == pdev->sriov->num_VFs) {
+			dev_warn(&pdev->dev,
+				 "%d VFs already enabled; no enable action taken\n",
+				 num_vfs);
+			return count;
+		} else {
+			dev_warn(&pdev->dev,
+				 "%d VFs already enabled. Disable before enabling %d VFs\n",
+				 pdev->sriov->num_VFs, num_vfs);
+			return -EINVAL;
+		}
+	}
+
+	/* disable vfs */
+	if (num_vfs == 0) {
+		if (pdev->sriov->num_VFs != 0) {
+			ret = pdev->driver->sriov_configure(pdev, 0);
+			return ret ? ret : count;
+		} else {
+			dev_warn(&pdev->dev,
+				 "All VFs disabled; no disable action taken\n");
+			return count;
+		}
+	}
+
+	dev_err(&pdev->dev,
+		"Invalid value for number of VFs to enable: %d\n", num_vfs);
+
+	return -EINVAL;
+}
+
+static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs);
+static struct device_attribute sriov_numvfs_attr =
+		__ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP),
+		       sriov_numvfs_show, sriov_numvfs_store);
+#endif /* CONFIG_PCI_IOV */
+
 struct device_attribute pci_dev_attrs[] = {
 	__ATTR_RO(resource),
 	__ATTR_RO(vendor),
@@ -424,10 +521,8 @@ struct device_attribute pci_dev_attrs[] = {
 	__ATTR(broken_parity_status,(S_IRUGO|S_IWUSR),
 		broken_parity_status_show,broken_parity_status_store),
 	__ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store),
-#ifdef CONFIG_HOTPLUG
 	__ATTR(remove, (S_IWUSR|S_IWGRP), NULL, remove_store),
 	__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_rescan_store),
-#endif
 #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI)
 	__ATTR(d3cold_allowed, 0644, d3cold_allowed_show, d3cold_allowed_store),
 #endif
@@ -435,9 +530,7 @@ struct device_attribute pci_dev_attrs[] = {
 };
 
 struct device_attribute pcibus_dev_attrs[] = {
-#ifdef CONFIG_HOTPLUG
 	__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store),
-#endif
 	__ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpumaskaffinity, NULL),
 	__ATTR(cpulistaffinity, S_IRUGO, pci_bus_show_cpulistaffinity, NULL),
 	__ATTR_NULL,
@@ -1269,29 +1362,20 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
 		pdev->rom_attr = attr;
 	}
 
-	if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
-		retval = device_create_file(&pdev->dev, &vga_attr);
-		if (retval)
-			goto err_rom_file;
-	}
-
 	/* add platform-specific attributes */
 	retval = pcibios_add_platform_entries(pdev);
 	if (retval)
-		goto err_vga_file;
+		goto err_rom_file;
 
 	/* add sysfs entries for various capabilities */
 	retval = pci_create_capabilities_sysfs(pdev);
 	if (retval)
-		goto err_vga_file;
+		goto err_rom_file;
 
 	pci_create_firmware_label_files(pdev);
 
 	return 0;
 
-err_vga_file:
-	if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
-		device_remove_file(&pdev->dev, &vga_attr);
 err_rom_file:
 	if (rom_size) {
 		sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
@@ -1377,3 +1461,62 @@ static int __init pci_sysfs_init(void)
 }
 
 late_initcall(pci_sysfs_init);
+
+static struct attribute *pci_dev_dev_attrs[] = {
+	&vga_attr.attr,
+	NULL,
+};
+
+static umode_t pci_dev_attrs_are_visible(struct kobject *kobj,
+						struct attribute *a, int n)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct pci_dev *pdev = to_pci_dev(dev);
+
+	if (a == &vga_attr.attr)
+		if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+			return 0;
+
+	return a->mode;
+}
+
+#ifdef CONFIG_PCI_IOV
+static struct attribute *sriov_dev_attrs[] = {
+	&sriov_totalvfs_attr.attr,
+	&sriov_numvfs_attr.attr,
+	NULL,
+};
+
+static umode_t sriov_attrs_are_visible(struct kobject *kobj,
+					 struct attribute *a, int n)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+
+	if (!dev_is_pf(dev))
+		return 0;
+
+	return a->mode;
+}
+
+static struct attribute_group sriov_dev_attr_group = {
+	.attrs = sriov_dev_attrs,
+	.is_visible = sriov_attrs_are_visible,
+};
+#endif /* CONFIG_PCI_IOV */
+
+static struct attribute_group pci_dev_attr_group = {
+	.attrs = pci_dev_dev_attrs,
+	.is_visible = pci_dev_attrs_are_visible,
+};
+
+static const struct attribute_group *pci_dev_attr_groups[] = {
+	&pci_dev_attr_group,
+#ifdef CONFIG_PCI_IOV
+	&sriov_dev_attr_group,
+#endif
+	NULL,
+};
+
+struct device_type pci_dev_type = {
+	.groups = pci_dev_attr_groups,
+};
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index aabf647..f3ad6f5 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -86,7 +86,7 @@ enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_TUNE_OFF;
  * the dfl or actual value as it sees fit.  Don't forget this is
  * measured in 32-bit words, not bytes.
  */
-u8 pci_dfl_cache_line_size __devinitdata = L1_CACHE_BYTES >> 2;
+u8 pci_dfl_cache_line_size = L1_CACHE_BYTES >> 2;
 u8 pci_cache_line_size;
 
 /*
@@ -1578,15 +1578,25 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
 
 	pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
 
-	/* PCI (as opposed to PCIe) PME requires that the device have
-	   its PME# line hooked up correctly. Not all hardware vendors
-	   do this, so the PME never gets delivered and the device
-	   remains asleep. The easiest way around this is to
-	   periodically walk the list of suspended devices and check
-	   whether any have their PME flag set. The assumption is that
-	   we'll wake up often enough anyway that this won't be a huge
-	   hit, and the power savings from the devices will still be a
-	   win. */
+	/*
+	 * PCI (as opposed to PCIe) PME requires that the device have
+	 * its PME# line hooked up correctly. Not all hardware vendors
+	 * do this, so the PME never gets delivered and the device
+	 * remains asleep. The easiest way around this is to
+	 * periodically walk the list of suspended devices and check
+	 * whether any have their PME flag set. The assumption is that
+	 * we'll wake up often enough anyway that this won't be a huge
+	 * hit, and the power savings from the devices will still be a
+	 * win.
+	 *
+	 * Although PCIe uses in-band PME message instead of PME# line
+	 * to report PME, PME does not work for some PCIe devices in
+	 * reality.  For example, there are devices that set their PME
+	 * status bits, but don't really bother to send a PME message;
+	 * there are PCI Express Root Ports that don't bother to
+	 * trigger interrupts when they receive PME messages from the
+	 * devices below.  So PME poll is used for PCIe devices too.
+	 */
 
 	if (dev->pme_poll) {
 		struct pci_pme_device *pme_dev;
@@ -3857,7 +3867,7 @@ static int __init pci_resource_alignment_sysfs_init(void)
 
 late_initcall(pci_resource_alignment_sysfs_init);
 
-static void __devinit pci_no_domains(void)
+static void pci_no_domains(void)
 {
 #ifdef CONFIG_PCI_DOMAINS
 	pci_domains_supported = 0;
@@ -3865,14 +3875,13 @@ static void __devinit pci_no_domains(void)
 }
 
 /**
- * pci_ext_cfg_enabled - can we access extended PCI config space?
- * @dev: The PCI device of the root bridge.
+ * pci_ext_cfg_avail - can we access extended PCI config space?
  *
  * Returns 1 if we can access PCI extended config space (offsets
  * greater than 0xff). This is the default implementation. Architecture
  * implementations can override this.
  */
-int __weak pci_ext_cfg_avail(struct pci_dev *dev)
+int __weak pci_ext_cfg_avail(void)
 {
 	return 1;
 }
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index fd92aab..e851829 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -8,7 +8,6 @@
 
 /* Functions internal to the PCI core code */
 
-extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
 extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
 extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
 #if !defined(CONFIG_DMI) && !defined(CONFIG_ACPI)
@@ -159,11 +158,8 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
 }
 extern struct device_attribute pci_dev_attrs[];
 extern struct device_attribute pcibus_dev_attrs[];
-#ifdef CONFIG_HOTPLUG
+extern struct device_type pci_dev_type;
 extern struct bus_attribute pci_bus_attrs[];
-#else
-#define pci_bus_attrs	NULL
-#endif
 
 
 /**
@@ -234,13 +230,14 @@ struct pci_sriov {
 	int nres;		/* number of resources */
 	u32 cap;		/* SR-IOV Capabilities */
 	u16 ctrl;		/* SR-IOV Control */
-	u16 total;		/* total VFs associated with the PF */
-	u16 initial;		/* initial VFs associated with the PF */
-	u16 nr_virtfn;		/* number of VFs available */
+	u16 total_VFs;		/* total VFs associated with the PF */
+	u16 initial_VFs;	/* initial VFs associated with the PF */
+	u16 num_VFs;		/* number of VFs available */
 	u16 offset;		/* first VF Routing ID offset */
 	u16 stride;		/* following VF stride */
 	u32 pgsz;		/* page size for BAR alignment */
 	u8 link;		/* Function Dependency Link */
+	u16 driver_max_VFs;	/* max num VFs driver supports */
 	struct pci_dev *dev;	/* lowest numbered PF */
 	struct pci_dev *self;	/* this PF */
 	struct mutex lock;	/* lock for VF bus */
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index 030cf12..76ef634 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -41,7 +41,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-static int __devinit aer_probe(struct pcie_device *dev);
+static int aer_probe(struct pcie_device *dev);
 static void aer_remove(struct pcie_device *dev);
 static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
 	enum pci_channel_state error);
@@ -300,7 +300,7 @@ static void aer_remove(struct pcie_device *dev)
  *
  * Invoked when PCI Express bus loads AER service driver.
  */
-static int __devinit aer_probe(struct pcie_device *dev)
+static int aer_probe(struct pcie_device *dev)
 {
 	int status;
 	struct aer_rpc *rpc;
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
index 94a7598..22f840f 100644
--- a/drivers/pci/pcie/aer/aerdrv.h
+++ b/drivers/pci/pcie/aer/aerdrv.h
@@ -87,6 +87,9 @@ struct aer_broadcast_data {
 static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
 		enum pci_ers_result new)
 {
+	if (new == PCI_ERS_RESULT_NO_AER_DRIVER)
+		return PCI_ERS_RESULT_NO_AER_DRIVER;
+
 	if (new == PCI_ERS_RESULT_NONE)
 		return orig;
 
@@ -97,7 +100,7 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
 		break;
 	case PCI_ERS_RESULT_DISCONNECT:
 		if (new == PCI_ERS_RESULT_NEED_RESET)
-			orig = new;
+			orig = PCI_ERS_RESULT_NEED_RESET;
 		break;
 	default:
 		break;
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index af4e31c..421bbc5 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -232,13 +232,27 @@ static int report_error_detected(struct pci_dev *dev, void *data)
 				   dev->driver ?
 				   "no AER-aware driver" : "no driver");
 		}
-		goto out;
+
+		/*
+		 * If there's any device in the subtree that does not
+		 * have an error_detected callback, returning
+		 * PCI_ERS_RESULT_NO_AER_DRIVER prevents calling of
+		 * the subsequent mmio_enabled/slot_reset/resume
+		 * callbacks of "any" device in the subtree. All the
+		 * devices in the subtree are left in the error state
+		 * without recovery.
+		 */
+
+		if (!(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE))
+			vote = PCI_ERS_RESULT_NO_AER_DRIVER;
+		else
+			vote = PCI_ERS_RESULT_NONE;
+	} else {
+		err_handler = dev->driver->err_handler;
+		vote = err_handler->error_detected(dev, result_data->state);
 	}
 
-	err_handler = dev->driver->err_handler;
-	vote = err_handler->error_detected(dev, result_data->state);
 	result_data->result = merge_result(result_data->result, vote);
-out:
 	device_unlock(&dev->dev);
 	return 0;
 }
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 213753b..3da9ecc 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -242,8 +242,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
 		return;
 
 	/* Training failed. Restore common clock configurations */
-	dev_printk(KERN_ERR, &parent->dev,
-		   "ASPM: Could not configure common clock\n");
+	dev_err(&parent->dev, "ASPM: Could not configure common clock\n");
 	list_for_each_entry(child, &linkbus->devices, bus_list)
 		pcie_capability_write_word(child, PCI_EXP_LNKCTL,
 					   child_reg[PCI_FUNC(child->devfn)]);
@@ -507,9 +506,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
 		 */
 		pcie_capability_read_dword(child, PCI_EXP_DEVCAP, &reg32);
 		if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) {
-			dev_printk(KERN_INFO, &child->dev, "disabling ASPM"
-				" on pre-1.1 PCIe device.  You can enable it"
-				" with 'pcie_aspm=force'\n");
+			dev_info(&child->dev, "disabling ASPM on pre-1.1 PCIe device.  You can enable it with 'pcie_aspm=force'\n");
 			return -EINVAL;
 		}
 	}
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 0761d90..d4824cb 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -182,7 +182,7 @@ static const struct pci_device_id port_runtime_pm_black_list[] = {
  * this port device.
  *
  */
-static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
+static int pcie_portdrv_probe(struct pci_dev *dev,
 					const struct pci_device_id *id)
 {
 	int status;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ec909af..edc3d12 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -305,7 +305,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
 	}
 }
 
-static void __devinit pci_read_bridge_io(struct pci_bus *child)
+static void pci_read_bridge_io(struct pci_bus *child)
 {
 	struct pci_dev *dev = child->self;
 	u8 io_base_lo, io_limit_lo;
@@ -345,7 +345,7 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
 	}
 }
 
-static void __devinit pci_read_bridge_mmio(struct pci_bus *child)
+static void pci_read_bridge_mmio(struct pci_bus *child)
 {
 	struct pci_dev *dev = child->self;
 	u16 mem_base_lo, mem_limit_lo;
@@ -367,7 +367,7 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child)
 	}
 }
 
-static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
+static void pci_read_bridge_mmio_pref(struct pci_bus *child)
 {
 	struct pci_dev *dev = child->self;
 	u16 mem_base_lo, mem_limit_lo;
@@ -417,7 +417,7 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
 	}
 }
 
-void __devinit pci_read_bridge_bases(struct pci_bus *child)
+void pci_read_bridge_bases(struct pci_bus *child)
 {
 	struct pci_dev *dev = child->self;
 	struct resource *res;
@@ -705,7 +705,7 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
  * them, we proceed to assigning numbers to the remaining buses in
  * order to avoid overlaps between old and new bus numbers.
  */
-int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
+int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 {
 	struct pci_bus *child;
 	int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
@@ -975,6 +975,7 @@ int pci_setup_device(struct pci_dev *dev)
 	dev->sysdata = dev->bus->sysdata;
 	dev->dev.parent = dev->bus->bridge;
 	dev->dev.bus = &pci_bus_type;
+	dev->dev.type = &pci_dev_type;
 	dev->hdr_type = hdr_type & 0x7f;
 	dev->multifunction = !!(hdr_type & 0x80);
 	dev->error_state = pci_channel_io_normal;
@@ -1586,7 +1587,7 @@ void pcie_bus_configure_settings(struct pci_bus *bus, u8 mpss)
 }
 EXPORT_SYMBOL_GPL(pcie_bus_configure_settings);
 
-unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
+unsigned int pci_scan_child_bus(struct pci_bus *bus)
 {
 	unsigned int devfn, pass, max = bus->busn_res.start;
 	struct pci_dev *dev;
@@ -1790,7 +1791,7 @@ void pci_bus_release_busn_res(struct pci_bus *b)
 			res, ret ? "can not be" : "is");
 }
 
-struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
+struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
 		struct pci_ops *ops, void *sysdata, struct list_head *resources)
 {
 	struct pci_host_bridge_window *window;
@@ -1826,7 +1827,7 @@ struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
 EXPORT_SYMBOL(pci_scan_root_bus);
 
 /* Deprecated; use pci_scan_root_bus() instead */
-struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
+struct pci_bus *pci_scan_bus_parented(struct device *parent,
 		int bus, struct pci_ops *ops, void *sysdata)
 {
 	LIST_HEAD(resources);
@@ -1844,7 +1845,7 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
 }
 EXPORT_SYMBOL(pci_scan_bus_parented);
 
-struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops,
+struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops,
 					void *sysdata)
 {
 	LIST_HEAD(resources);
@@ -1864,7 +1865,6 @@ struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops,
 }
 EXPORT_SYMBOL(pci_scan_bus);
 
-#ifdef CONFIG_HOTPLUG
 /**
  * pci_rescan_bus_bridge_resize - scan a PCI bus for devices.
  * @bridge: PCI bridge for the bus to scan
@@ -1890,11 +1890,32 @@ unsigned int __ref pci_rescan_bus_bridge_resize(struct pci_dev *bridge)
 	return max;
 }
 
+/**
+ * pci_rescan_bus - scan a PCI bus for devices.
+ * @bus: PCI bus to scan
+ *
+ * Scan a PCI bus and child buses for new devices, adds them,
+ * and enables them.
+ *
+ * Returns the max number of subordinate bus discovered.
+ */
+unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
+{
+	unsigned int max;
+
+	max = pci_scan_child_bus(bus);
+	pci_assign_unassigned_bus_resources(bus);
+	pci_enable_bridges(bus);
+	pci_bus_add_devices(bus);
+
+	return max;
+}
+EXPORT_SYMBOL_GPL(pci_rescan_bus);
+
 EXPORT_SYMBOL(pci_add_new_bus);
 EXPORT_SYMBOL(pci_scan_slot);
 EXPORT_SYMBOL(pci_scan_bridge);
 EXPORT_SYMBOL_GPL(pci_scan_child_bus);
-#endif
 
 static int __init pci_sort_bf_cmp(const struct device *d_a, const struct device *d_b)
 {
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 7a451ff..8f7a634 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -37,7 +37,7 @@
  * key system devices. For devices that need to have mmio decoding always-on,
  * we need to set the dev->mmio_always_on bit.
  */
-static void __devinit quirk_mmio_always_on(struct pci_dev *dev)
+static void quirk_mmio_always_on(struct pci_dev *dev)
 {
 	dev->mmio_always_on = 1;
 }
@@ -48,7 +48,7 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_ANY_ID, PCI_ANY_ID,
  * Mark this device with a broken_parity_status, to allow
  * PCI scanning code to "skip" this now blacklisted device.
  */
-static void __devinit quirk_mellanox_tavor(struct pci_dev *dev)
+static void quirk_mellanox_tavor(struct pci_dev *dev)
 {
 	dev->broken_parity_status = 1;	/* This device gives false positives */
 }
@@ -83,7 +83,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_p
     This appears to be BIOS not version dependent. So presumably there is a 
     chipset level fix */
     
-static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev)
+static void quirk_isa_dma_hangs(struct pci_dev *dev)
 {
 	if (!isa_dma_bridge_buggy) {
 		isa_dma_bridge_buggy=1;
@@ -106,7 +106,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_3,	quirk_isa_d
  * Intel NM10 "TigerPoint" LPC PM1a_STS.BM_STS must be clear
  * for some HT machines to use C4 w/o hanging.
  */
-static void __devinit quirk_tigerpoint_bm_sts(struct pci_dev *dev)
+static void quirk_tigerpoint_bm_sts(struct pci_dev *dev)
 {
 	u32 pmbase;
 	u16 pm1a;
@@ -125,7 +125,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGP_LPC, quirk
 /*
  *	Chipsets where PCI->PCI transfers vanish or hang
  */
-static void __devinit quirk_nopcipci(struct pci_dev *dev)
+static void quirk_nopcipci(struct pci_dev *dev)
 {
 	if ((pci_pci_problems & PCIPCI_FAIL)==0) {
 		dev_info(&dev->dev, "Disabling direct PCI/PCI transfers\n");
@@ -135,7 +135,7 @@ static void __devinit quirk_nopcipci(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5597,		quirk_nopcipci);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_496,		quirk_nopcipci);
 
-static void __devinit quirk_nopciamd(struct pci_dev *dev)
+static void quirk_nopciamd(struct pci_dev *dev)
 {
 	u8 rev;
 	pci_read_config_byte(dev, 0x08, &rev);
@@ -150,7 +150,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_8151_0,	quirk_nopci
 /*
  *	Triton requires workarounds to be used by the drivers
  */
-static void __devinit quirk_triton(struct pci_dev *dev)
+static void quirk_triton(struct pci_dev *dev)
 {
 	if ((pci_pci_problems&PCIPCI_TRITON)==0) {
 		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
@@ -229,7 +229,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8361,		quirk_viala
 /*
  *	VIA Apollo VP3 needs ETBF on BT848/878
  */
-static void __devinit quirk_viaetbf(struct pci_dev *dev)
+static void quirk_viaetbf(struct pci_dev *dev)
 {
 	if ((pci_pci_problems&PCIPCI_VIAETBF)==0) {
 		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
@@ -238,7 +238,7 @@ static void __devinit quirk_viaetbf(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C597_0,	quirk_viaetbf);
 
-static void __devinit quirk_vsfx(struct pci_dev *dev)
+static void quirk_vsfx(struct pci_dev *dev)
 {
 	if ((pci_pci_problems&PCIPCI_VSFX)==0) {
 		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
@@ -253,7 +253,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C576,	quirk_vsfx)
  *	workaround applied too
  *	[Info kindly provided by ALi]
  */	
-static void __devinit quirk_alimagik(struct pci_dev *dev)
+static void quirk_alimagik(struct pci_dev *dev)
 {
 	if ((pci_pci_problems&PCIPCI_ALIMAGIK)==0) {
 		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
@@ -267,7 +267,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1651, 	quirk_alimag
  *	Natoma has some interesting boundary conditions with Zoran stuff
  *	at least
  */
-static void __devinit quirk_natoma(struct pci_dev *dev)
+static void quirk_natoma(struct pci_dev *dev)
 {
 	if ((pci_pci_problems&PCIPCI_NATOMA)==0) {
 		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
@@ -285,7 +285,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_2, 	qu
  *  This chip can cause PCI parity errors if config register 0xA0 is read
  *  while DMAs are occurring.
  */
-static void __devinit quirk_citrine(struct pci_dev *dev)
+static void quirk_citrine(struct pci_dev *dev)
 {
 	dev->cfg_size = 0xA0;
 }
@@ -295,7 +295,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM,	PCI_DEVICE_ID_IBM_CITRINE,	quirk_cit
  *  S3 868 and 968 chips report region size equal to 32M, but they decode 64M.
  *  If it's needed, re-allocate the region.
  */
-static void __devinit quirk_s3_64M(struct pci_dev *dev)
+static void quirk_s3_64M(struct pci_dev *dev)
 {
 	struct resource *r = &dev->resource[0];
 
@@ -313,7 +313,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_968,		quirk_s3_64M);
  * BAR0 should be 8 bytes; instead, it may be set to something like 8k
  * (which conflicts w/ BAR1's memory range).
  */
-static void __devinit quirk_cs5536_vsa(struct pci_dev *dev)
+static void quirk_cs5536_vsa(struct pci_dev *dev)
 {
 	if (pci_resource_len(dev, 0) != 8) {
 		struct resource *res = &dev->resource[0];
@@ -324,7 +324,7 @@ static void __devinit quirk_cs5536_vsa(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa);
 
-static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
+static void quirk_io_region(struct pci_dev *dev, unsigned region,
 	unsigned size, int nr, const char *name)
 {
 	region &= ~(size-1);
@@ -352,7 +352,7 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
  *	ATI Northbridge setups MCE the processor if you even
  *	read somewhere between 0x3b0->0x3bb or read 0x3d3
  */
-static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev)
+static void quirk_ati_exploding_mce(struct pci_dev *dev)
 {
 	dev_info(&dev->dev, "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb\n");
 	/* Mae rhaid i ni beidio ag edrych ar y lleoliadiau I/O hyn */
@@ -372,7 +372,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI,	PCI_DEVICE_ID_ATI_RS100,   quirk_ati_
  *	0xE0 (64 bytes of ACPI registers)
  *	0xE2 (32 bytes of SMB registers)
  */
-static void __devinit quirk_ali7101_acpi(struct pci_dev *dev)
+static void quirk_ali7101_acpi(struct pci_dev *dev)
 {
 	u16 region;
 
@@ -440,7 +440,7 @@ static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int
  *	0x90 (16 bytes of SMB registers)
  * and a few strange programmable PIIX4 device resources.
  */
-static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
+static void quirk_piix4_acpi(struct pci_dev *dev)
 {
 	u32 region, res_a;
 
@@ -489,7 +489,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82443MX_3,	qui
  *	0x40 (128 bytes of ACPI, GPIO & TCO registers)
  *	0x58 (64 bytes of GPIO I/O space)
  */
-static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev)
+static void quirk_ich4_lpc_acpi(struct pci_dev *dev)
 {
 	u32 region;
 	u8 enable;
@@ -531,7 +531,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801DB_12,
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801EB_0,		quirk_ich4_lpc_acpi);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_ESB_1,		quirk_ich4_lpc_acpi);
 
-static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev)
+static void ich6_lpc_acpi_gpio(struct pci_dev *dev)
 {
 	u32 region;
 	u8 enable;
@@ -555,7 +555,7 @@ static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev)
 	}
 }
 
-static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize)
+static void ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize)
 {
 	u32 val;
 	u32 size, base;
@@ -583,7 +583,7 @@ static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg,
 	dev_info(&dev->dev, "%s PIO at %04x-%04x\n", name, base, base+size-1);
 }
 
-static void __devinit quirk_ich6_lpc(struct pci_dev *dev)
+static void quirk_ich6_lpc(struct pci_dev *dev)
 {
 	/* Shared ACPI/GPIO decode with all ICH6+ */
 	ich6_lpc_acpi_gpio(dev);
@@ -595,7 +595,7 @@ static void __devinit quirk_ich6_lpc(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc);
 
-static void __devinit ich7_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name)
+static void ich7_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name)
 {
 	u32 val;
 	u32 mask, base;
@@ -619,7 +619,7 @@ static void __devinit ich7_lpc_generic_decode(struct pci_dev *dev, unsigned reg,
 }
 
 /* ICH7-10 has the same common LPC generic IO decode registers */
-static void __devinit quirk_ich7_lpc(struct pci_dev *dev)
+static void quirk_ich7_lpc(struct pci_dev *dev)
 {
 	/* We share the common ACPI/GPIO decode with ICH6 */
 	ich6_lpc_acpi_gpio(dev);
@@ -648,7 +648,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_ICH10_1, qui
  * VIA ACPI: One IO region pointed to by longword at
  *	0x48 or 0x20 (256 bytes of ACPI registers)
  */
-static void __devinit quirk_vt82c586_acpi(struct pci_dev *dev)
+static void quirk_vt82c586_acpi(struct pci_dev *dev)
 {
 	u32 region;
 
@@ -666,7 +666,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_vt
  *	0x70 (128 bytes of hardware monitoring register)
  *	0x90 (16 bytes of SMB registers)
  */
-static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev)
+static void quirk_vt82c686_acpi(struct pci_dev *dev)
 {
 	u16 hm;
 	u32 smb;
@@ -688,7 +688,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_vt
  *	0x88 (128 bytes of power management registers)
  *	0xd0 (16 bytes of SMB registers)
  */
-static void __devinit quirk_vt8235_acpi(struct pci_dev *dev)
+static void quirk_vt8235_acpi(struct pci_dev *dev)
 {
 	u16 pm, smb;
 
@@ -706,7 +706,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8235,	quirk_vt8235
  * TI XIO2000a PCIe-PCI Bridge erroneously reports it supports fast back-to-back:
  *	Disable fast back-to-back on the secondary bus segment
  */
-static void __devinit quirk_xio2000a(struct pci_dev *dev)
+static void quirk_xio2000a(struct pci_dev *dev)
 {
 	struct pci_dev *pdev;
 	u16 command;
@@ -780,7 +780,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8237,		quirk
  * noapic specified. For the moment we assume it's the erratum. We may be wrong
  * of course. However the advice is demonstrably good even if so..
  */
-static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
+static void quirk_amd_ioapic(struct pci_dev *dev)
 {
 	if (dev->revision >= 0x02) {
 		dev_warn(&dev->dev, "I/O APIC: AMD Erratum #22 may be present. In the event of instability try\n");
@@ -789,7 +789,7 @@ static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_VIPER_7410,	quirk_amd_ioapic);
 
-static void __devinit quirk_ioapic_rmw(struct pci_dev *dev)
+static void quirk_ioapic_rmw(struct pci_dev *dev)
 {
 	if (dev->devfn == 0 && dev->bus->number == 0)
 		sis_apic_bug = 1;
@@ -801,7 +801,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_ANY_ID,			quirk_ioapic_rmw);
  * Some settings of MMRBC can lead to data corruption so block changes.
  * See AMD 8131 HyperTransport PCI-X Tunnel Revision Guide
  */
-static void __devinit quirk_amd_8131_mmrbc(struct pci_dev *dev)
+static void quirk_amd_8131_mmrbc(struct pci_dev *dev)
 {
 	if (dev->subordinate && dev->revision <= 0x12) {
 		dev_info(&dev->dev, "AMD8131 rev %x detected; "
@@ -819,7 +819,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_
  * value of the ACPI SCI interrupt is only done for convenience.
  *	-jgarzik
  */
-static void __devinit quirk_via_acpi(struct pci_dev *d)
+static void quirk_via_acpi(struct pci_dev *d)
 {
 	/*
 	 * VIA ACPI device: SCI IRQ line in PCI config byte 0x42
@@ -926,7 +926,7 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_vlink);
  * We need to switch it off to be able to recognize the real
  * type of the chip.
  */
-static void __devinit quirk_vt82c598_id(struct pci_dev *dev)
+static void quirk_vt82c598_id(struct pci_dev *dev)
 {
 	pci_write_config_byte(dev, 0xfc, 0);
 	pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
@@ -978,7 +978,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_FE_GATE_700C
  *	assigned to it. We force a larger allocation to ensure that
  *	nothing gets put too close to it.
  */
-static void __devinit quirk_dunord ( struct pci_dev * dev )
+static void quirk_dunord(struct pci_dev *dev)
 {
 	struct resource *r = &dev->resource [1];
 	r->start = 0;
@@ -992,7 +992,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DUNORD,	PCI_DEVICE_ID_DUNORD_I3000,	quirk
  * in the ProgIf. Unfortunately, the ProgIf value is wrong - 0x80
  * instead of 0x01.
  */
-static void __devinit quirk_transparent_bridge(struct pci_dev *dev)
+static void quirk_transparent_bridge(struct pci_dev *dev)
 {
 	dev->transparent = 1;
 }
@@ -1066,7 +1066,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SATA
 /*
  *	Serverworks CSB5 IDE does not fully support native mode
  */
-static void __devinit quirk_svwks_csb5ide(struct pci_dev *pdev)
+static void quirk_svwks_csb5ide(struct pci_dev *pdev)
 {
 	u8 prog;
 	pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);
@@ -1082,7 +1082,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB
 /*
  *	Intel 82801CAM ICH3-M datasheet says IDE modes must be the same
  */
-static void __devinit quirk_ide_samemode(struct pci_dev *pdev)
+static void quirk_ide_samemode(struct pci_dev *pdev)
 {
 	u8 prog;
 
@@ -1101,7 +1101,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, qui
  * Some ATA devices break if put into D3
  */
 
-static void __devinit quirk_no_ata_d3(struct pci_dev *pdev)
+static void quirk_no_ata_d3(struct pci_dev *pdev)
 {
 	pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3;
 }
@@ -1121,7 +1121,7 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_VIA, PCI_ANY_ID,
 /* This was originally an Alpha specific thing, but it really fits here.
  * The i82375 PCI/EISA bridge appears as non-classified. Fix that.
  */
-static void __devinit quirk_eisa_bridge(struct pci_dev *dev)
+static void quirk_eisa_bridge(struct pci_dev *dev)
 {
 	dev->class = PCI_CLASS_BRIDGE_EISA << 8;
 }
@@ -1155,7 +1155,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82375,	quirk_e
  */
 static int asus_hides_smbus;
 
-static void __devinit asus_hides_smbus_hostbridge(struct pci_dev *dev)
+static void asus_hides_smbus_hostbridge(struct pci_dev *dev)
 {
 	if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) {
 		if (dev->device == PCI_DEVICE_ID_INTEL_82845_HB)
@@ -1538,7 +1538,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB3
 #endif
 
 #ifdef CONFIG_X86_IO_APIC
-static void __devinit quirk_alder_ioapic(struct pci_dev *pdev)
+static void quirk_alder_ioapic(struct pci_dev *pdev)
 {
 	int i;
 
@@ -1561,7 +1561,7 @@ static void __devinit quirk_alder_ioapic(struct pci_dev *pdev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_EESSC,	quirk_alder_ioapic);
 #endif
 
-static void __devinit quirk_pcie_mch(struct pci_dev *pdev)
+static void quirk_pcie_mch(struct pci_dev *pdev)
 {
 	pci_msi_off(pdev);
 	pdev->no_msi = 1;
@@ -1575,7 +1575,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7525_MCH,	quir
  * It's possible for the MSI to get corrupted if shpc and acpi
  * are used together on certain PXH-based systems.
  */
-static void __devinit quirk_pcie_pxh(struct pci_dev *dev)
+static void quirk_pcie_pxh(struct pci_dev *dev)
 {
 	pci_msi_off(dev);
 	dev->no_msi = 1;
@@ -1777,7 +1777,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD,   PCI_DEVICE_ID_AMD_8111_SMBUS, 	qui
  * but the PIO transfers won't work if BAR0 falls at the odd 8 bytes.
  * Re-allocate the region if needed...
  */
-static void __devinit quirk_tc86c001_ide(struct pci_dev *dev)
+static void quirk_tc86c001_ide(struct pci_dev *dev)
 {
 	struct resource *r = &dev->resource[0];
 
@@ -1790,7 +1790,46 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2,
 			 PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE,
 			 quirk_tc86c001_ide);
 
-static void __devinit quirk_netmos(struct pci_dev *dev)
+/*
+ * PLX PCI 9050 PCI Target bridge controller has an errata that prevents the
+ * local configuration registers accessible via BAR0 (memory) or BAR1 (i/o)
+ * being read correctly if bit 7 of the base address is set.
+ * The BAR0 or BAR1 region may be disabled (size 0) or enabled (size 128).
+ * Re-allocate the regions to a 256-byte boundary if necessary.
+ */
+static void quirk_plx_pci9050(struct pci_dev *dev)
+{
+	unsigned int bar;
+
+	/* Fixed in revision 2 (PCI 9052). */
+	if (dev->revision >= 2)
+		return;
+	for (bar = 0; bar <= 1; bar++)
+		if (pci_resource_len(dev, bar) == 0x80 &&
+		    (pci_resource_start(dev, bar) & 0x80)) {
+			struct resource *r = &dev->resource[bar];
+			dev_info(&dev->dev,
+				 "Re-allocating PLX PCI 9050 BAR %u to length 256 to avoid bit 7 bug\n",
+				 bar);
+			r->start = 0;
+			r->end = 0xff;
+		}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+			 quirk_plx_pci9050);
+/*
+ * The following Meilhaus (vendor ID 0x1402) device IDs (amongst others)
+ * may be using the PLX PCI 9050: 0x0630, 0x0940, 0x0950, 0x0960, 0x100b,
+ * 0x1400, 0x140a, 0x140b, 0x14e0, 0x14ea, 0x14eb, 0x1604, 0x1608, 0x160c,
+ * 0x168f, 0x2000, 0x2600, 0x3000, 0x810a, 0x810b.
+ *
+ * Currently, device IDs 0x2000 and 0x2600 are used by the Comedi "me_daq"
+ * driver.
+ */
+DECLARE_PCI_FIXUP_HEADER(0x1402, 0x2000, quirk_plx_pci9050);
+DECLARE_PCI_FIXUP_HEADER(0x1402, 0x2600, quirk_plx_pci9050);
+
+static void quirk_netmos(struct pci_dev *dev)
 {
 	unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;
 	unsigned int num_serial = dev->subsystem_device & 0xf;
@@ -1828,7 +1867,7 @@ static void __devinit quirk_netmos(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID,
 			 PCI_CLASS_COMMUNICATION_SERIAL, 8, quirk_netmos);
 
-static void __devinit quirk_e100_interrupt(struct pci_dev *dev)
+static void quirk_e100_interrupt(struct pci_dev *dev)
 {
 	u16 command, pmcsr;
 	u8 __iomem *csr;
@@ -1901,7 +1940,7 @@ DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
  * The 82575 and 82598 may experience data corruption issues when transitioning
  * out of L0S.  To prevent this we need to disable L0S on the pci-e link
  */
-static void __devinit quirk_disable_aspm_l0s(struct pci_dev *dev)
+static void quirk_disable_aspm_l0s(struct pci_dev *dev)
 {
 	dev_info(&dev->dev, "Disabling L0s\n");
 	pci_disable_link_state(dev, PCIE_LINK_STATE_L0S);
@@ -1921,7 +1960,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f1, quirk_disable_aspm_l0s);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f4, quirk_disable_aspm_l0s);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s);
 
-static void __devinit fixup_rev1_53c810(struct pci_dev* dev)
+static void fixup_rev1_53c810(struct pci_dev *dev)
 {
 	/* rev 1 ncr53c810 chips don't set the class at all which means
 	 * they don't get their resources remapped. Fix that here.
@@ -1935,7 +1974,7 @@ static void __devinit fixup_rev1_53c810(struct pci_dev* dev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
 
 /* Enable 1k I/O space granularity on the Intel P64H2 */
-static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
+static void quirk_p64h2_1k_io(struct pci_dev *dev)
 {
 	u16 en1k;
 
@@ -1968,7 +2007,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA,  PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_NVIDIA,  PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
 			quirk_nvidia_ck804_pcie_aer_ext_cap);
 
-static void __devinit quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)
+static void quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)
 {
 	/*
 	 * Disable PCI Bus Parking and PCI Master read caching on CX700
@@ -2031,7 +2070,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0x324e, quirk_via_cx700_pci_parking_c
  * We believe that it is legal to read beyond the end tag and
  * therefore the solution is to limit the read/write length.
  */
-static void __devinit quirk_brcm_570x_limit_vpd(struct pci_dev *dev)
+static void quirk_brcm_570x_limit_vpd(struct pci_dev *dev)
 {
 	/*
 	 * Only disable the VPD capability for 5706, 5706S, 5708,
@@ -2091,7 +2130,7 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_BROADCOM,
  * the DRBs - this is where we expose device 6.
  * http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm
  */
-static void __devinit quirk_unhide_mch_dev6(struct pci_dev *dev)
+static void quirk_unhide_mch_dev6(struct pci_dev *dev)
 {
 	u8 reg;
 
@@ -2115,7 +2154,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB,
  * supports link speed auto negotiation, but falsely sets
  * the link speed to 5GT/s.
  */
-static void __devinit quirk_tile_plx_gen1(struct pci_dev *dev)
+static void quirk_tile_plx_gen1(struct pci_dev *dev)
 {
 	if (tile_plx_gen1) {
 		pci_write_config_dword(dev, 0x98, 0x1);
@@ -2132,7 +2171,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1);
  * aware of it.  Instead of setting the flag on all busses in the
  * machine, simply disable MSI globally.
  */
-static void __devinit quirk_disable_all_msi(struct pci_dev *dev)
+static void quirk_disable_all_msi(struct pci_dev *dev)
 {
 	pci_no_msi();
 	dev_warn(&dev->dev, "MSI quirk detected; MSI disabled\n");
@@ -2146,7 +2185,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3364, quirk_disab
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8380_0, quirk_disable_all_msi);
 
 /* Disable MSI on chipsets that are known to not support it */
-static void __devinit quirk_disable_msi(struct pci_dev *dev)
+static void quirk_disable_msi(struct pci_dev *dev)
 {
 	if (dev->subordinate) {
 		dev_warn(&dev->dev, "MSI quirk detected; "
@@ -2164,7 +2203,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x5a3f, quirk_disable_msi);
  * we use the possible vendor/device IDs of the host bridge for the
  * declared quirk, and search for the APC bridge by slot number.
  */
-static void __devinit quirk_amd_780_apc_msi(struct pci_dev *host_bridge)
+static void quirk_amd_780_apc_msi(struct pci_dev *host_bridge)
 {
 	struct pci_dev *apc_bridge;
 
@@ -2272,7 +2311,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE,
  * for the MCP55 NIC. It is not yet determined whether the msi problem
  * also affects other devices. As for now, turn off msi for this device.
  */
-static void __devinit nvenet_msi_disable(struct pci_dev *dev)
+static void nvenet_msi_disable(struct pci_dev *dev)
 {
 	const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
 
@@ -2298,7 +2337,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
  * we have it set correctly.
  * Note this is an undocumented register.
  */
-static void __devinit nvbridge_check_legacy_irq_routing(struct pci_dev *dev)
+static void nvbridge_check_legacy_irq_routing(struct pci_dev *dev)
 {
 	u32 cfg;
 
@@ -2534,11 +2573,11 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_q
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk_all);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk_all);
 
-static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev)
+static void quirk_msi_intx_disable_bug(struct pci_dev *dev)
 {
 	dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG;
 }
-static void __devinit quirk_msi_intx_disable_ati_bug(struct pci_dev *dev)
+static void quirk_msi_intx_disable_ati_bug(struct pci_dev *dev)
 {
 	struct pci_dev *p;
 
@@ -2612,7 +2651,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1083,
  * kernel fails to allocate resources when hotplug device is 
  * inserted and PCI bus is rescanned.
  */
-static void __devinit quirk_hotplug_bridge(struct pci_dev *dev)
+static void quirk_hotplug_bridge(struct pci_dev *dev)
 {
 	dev->is_hotplug_bridge = 1;
 }
@@ -2752,7 +2791,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, vtd_mask_spec_errors);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors);
 #endif
 
-static void __devinit fixup_ti816x_class(struct pci_dev* dev)
+static void fixup_ti816x_class(struct pci_dev *dev)
 {
 	/* TI 816x devices do not have class code set when in PCIe boot mode */
 	dev_info(&dev->dev, "Setting PCI class for 816x PCIe device\n");
@@ -2764,7 +2803,7 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_TI, 0xb800,
 /* Some PCIe devices do not work reliably with the claimed maximum
  * payload size supported.
  */
-static void __devinit fixup_mpss_256(struct pci_dev *dev)
+static void fixup_mpss_256(struct pci_dev *dev)
 {
 	dev->pcie_mpss = 1; /* 256 bytes */
 }
@@ -2782,7 +2821,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SOLARFLARE,
  * coalescing must be disabled.  Unfortunately, it cannot be re-enabled because
  * it is possible to hotplug a device with MPS of 256B.
  */
-static void __devinit quirk_intel_mc_errata(struct pci_dev *dev)
+static void quirk_intel_mc_errata(struct pci_dev *dev)
 {
 	int err;
 	u16 rcc;
@@ -2888,7 +2927,7 @@ static void fixup_debug_report(struct pci_dev *dev, ktime_t calltime,
  * This resolves crashes often seen on monitor unplug.
  */
 #define I915_DEIER_REG 0x4400c
-static void __devinit disable_igfx_irq(struct pci_dev *dev)
+static void disable_igfx_irq(struct pci_dev *dev)
 {
 	void __iomem *regs = pci_iomap(dev, 0, 0);
 	if (regs == NULL) {
@@ -2914,7 +2953,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);
  * PCI_COMMAND_INTX_DISABLE works though they actually do not properly
  * support this feature.
  */
-static void __devinit quirk_broken_intx_masking(struct pci_dev *dev)
+static void quirk_broken_intx_masking(struct pci_dev *dev)
 {
 	dev->broken_intx_masking = 1;
 }
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 513972f..7c0fd92 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -111,3 +111,39 @@ void pci_stop_and_remove_bus_device(struct pci_dev *dev)
 	pci_remove_bus_device(dev);
 }
 EXPORT_SYMBOL(pci_stop_and_remove_bus_device);
+
+void pci_stop_root_bus(struct pci_bus *bus)
+{
+	struct pci_dev *child, *tmp;
+	struct pci_host_bridge *host_bridge;
+
+	if (!pci_is_root_bus(bus))
+		return;
+
+	host_bridge = to_pci_host_bridge(bus->bridge);
+	list_for_each_entry_safe_reverse(child, tmp,
+					 &bus->devices, bus_list)
+		pci_stop_bus_device(child);
+
+	/* stop the host bridge */
+	device_del(&host_bridge->dev);
+}
+
+void pci_remove_root_bus(struct pci_bus *bus)
+{
+	struct pci_dev *child, *tmp;
+	struct pci_host_bridge *host_bridge;
+
+	if (!pci_is_root_bus(bus))
+		return;
+
+	host_bridge = to_pci_host_bridge(bus->bridge);
+	list_for_each_entry_safe(child, tmp,
+				 &bus->devices, bus_list)
+		pci_remove_bus_device(child);
+	pci_remove_bus(bus);
+	host_bridge->bus = NULL;
+
+	/* remove the host bridge */
+	put_device(&host_bridge->dev);
+}
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 1e808ca..6d3591d 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1550,25 +1550,12 @@ enable_all:
 }
 EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
 
-#ifdef CONFIG_HOTPLUG
-/**
- * pci_rescan_bus - scan a PCI bus for devices.
- * @bus: PCI bus to scan
- *
- * Scan a PCI bus and child buses for new devices, adds them,
- * and enables them.
- *
- * Returns the max number of subordinate bus discovered.
- */
-unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
+void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
 {
-	unsigned int max;
 	struct pci_dev *dev;
 	LIST_HEAD(add_list); /* list of resources that
 					want additional resources */
 
-	max = pci_scan_child_bus(bus);
-
 	down_read(&pci_bus_sem);
 	list_for_each_entry(dev, &bus->devices, bus_list)
 		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
@@ -1579,11 +1566,4 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
 	up_read(&pci_bus_sem);
 	__pci_bus_assign_resources(bus, &add_list, NULL);
 	BUG_ON(!list_empty(&add_list));
-
-	pci_enable_bridges(bus);
-	pci_bus_add_devices(bus);
-
-	return max;
 }
-EXPORT_SYMBOL_GPL(pci_rescan_bus);
-#endif
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index 0aab85a..db542f4 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -412,7 +412,7 @@ static int pcifront_claim_resource(struct pci_dev *dev, void *data)
 	return 0;
 }
 
-static int __devinit pcifront_scan_bus(struct pcifront_device *pdev,
+static int pcifront_scan_bus(struct pcifront_device *pdev,
 				unsigned int domain, unsigned int bus,
 				struct pci_bus *b)
 {
@@ -441,7 +441,7 @@ static int __devinit pcifront_scan_bus(struct pcifront_device *pdev,
 	return 0;
 }
 
-static int __devinit pcifront_scan_root(struct pcifront_device *pdev,
+static int pcifront_scan_root(struct pcifront_device *pdev,
 				 unsigned int domain, unsigned int bus)
 {
 	struct pci_bus *b;
@@ -503,7 +503,7 @@ err_out:
 	return err;
 }
 
-static int __devinit pcifront_rescan_root(struct pcifront_device *pdev,
+static int pcifront_rescan_root(struct pcifront_device *pdev,
 				   unsigned int domain, unsigned int bus)
 {
 	int err;
@@ -834,7 +834,7 @@ out:
 	return err;
 }
 
-static int __devinit pcifront_try_connect(struct pcifront_device *pdev)
+static int pcifront_try_connect(struct pcifront_device *pdev)
 {
 	int err = -EFAULT;
 	int i, num_roots, len;
@@ -924,7 +924,7 @@ out:
 	return err;
 }
 
-static int __devinit pcifront_attach_devices(struct pcifront_device *pdev)
+static int pcifront_attach_devices(struct pcifront_device *pdev)
 {
 	int err = -EFAULT;
 	int i, num_roots, len;
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 8fd255f..b90f85b 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -36,8 +36,8 @@ config PCMCIA
 	   If unsure, say Y.
 
 config PCMCIA_LOAD_CIS
-	bool "Load CIS updates from userspace (EXPERIMENTAL)"
-	depends on PCMCIA && EXPERIMENTAL
+	bool "Load CIS updates from userspace"
+	depends on PCMCIA
 	select FW_LOADER
 	default y
 	help
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index 9694c1e..01463c7 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
+#include <linux/platform_data/atmel.h>
 
 #include <pcmcia/ss.h>
 
@@ -24,7 +25,6 @@
 #include <asm/io.h>
 #include <asm/sizes.h>
 
-#include <mach/board.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 
diff --git a/drivers/pcmcia/bcm63xx_pcmcia.c b/drivers/pcmcia/bcm63xx_pcmcia.c
index c2e997a..0c6aac1 100644
--- a/drivers/pcmcia/bcm63xx_pcmcia.c
+++ b/drivers/pcmcia/bcm63xx_pcmcia.c
@@ -323,7 +323,7 @@ static struct pccard_operations bcm63xx_pcmcia_operations = {
 /*
  * register pcmcia socket to core
  */
-static int __devinit bcm63xx_drv_pcmcia_probe(struct platform_device *pdev)
+static int bcm63xx_drv_pcmcia_probe(struct platform_device *pdev)
 {
 	struct bcm63xx_pcmcia_socket *skt;
 	struct pcmcia_socket *sock;
@@ -436,7 +436,7 @@ err:
 	return ret;
 }
 
-static int __devexit bcm63xx_drv_pcmcia_remove(struct platform_device *pdev)
+static int bcm63xx_drv_pcmcia_remove(struct platform_device *pdev)
 {
 	struct bcm63xx_pcmcia_socket *skt;
 	struct resource *res;
@@ -453,7 +453,7 @@ static int __devexit bcm63xx_drv_pcmcia_remove(struct platform_device *pdev)
 
 struct platform_driver bcm63xx_pcmcia_driver = {
 	.probe	= bcm63xx_drv_pcmcia_probe,
-	.remove	= __devexit_p(bcm63xx_drv_pcmcia_remove),
+	.remove	= bcm63xx_drv_pcmcia_remove,
 	.driver	= {
 		.name	= "bcm63xx_pcmcia",
 		.owner  = THIS_MODULE,
@@ -461,7 +461,7 @@ struct platform_driver bcm63xx_pcmcia_driver = {
 };
 
 #ifdef CONFIG_CARDBUS
-static int __devinit bcm63xx_cb_probe(struct pci_dev *dev,
+static int bcm63xx_cb_probe(struct pci_dev *dev,
 				      const struct pci_device_id *id)
 {
 	/* keep pci device */
@@ -469,7 +469,7 @@ static int __devinit bcm63xx_cb_probe(struct pci_dev *dev,
 	return platform_driver_register(&bcm63xx_pcmcia_driver);
 }
 
-static void __devexit bcm63xx_cb_exit(struct pci_dev *dev)
+static void bcm63xx_cb_exit(struct pci_dev *dev)
 {
 	platform_driver_unregister(&bcm63xx_pcmcia_driver);
 	bcm63xx_cb_dev = NULL;
@@ -503,7 +503,7 @@ static struct pci_driver bcm63xx_cardbus_driver = {
 	.name		= "bcm63xx_cardbus",
 	.id_table	= bcm63xx_cb_table,
 	.probe		= bcm63xx_cb_probe,
-	.remove		= __devexit_p(bcm63xx_cb_exit),
+	.remove		= bcm63xx_cb_exit,
 };
 #endif
 
diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c
index ac1a223..ed3b522 100644
--- a/drivers/pcmcia/bfin_cf_pcmcia.c
+++ b/drivers/pcmcia/bfin_cf_pcmcia.c
@@ -195,7 +195,7 @@ static struct pccard_operations bfin_cf_ops = {
 
 /*--------------------------------------------------------------------------*/
 
-static int __devinit bfin_cf_probe(struct platform_device *pdev)
+static int bfin_cf_probe(struct platform_device *pdev)
 {
 	struct bfin_cf_socket *cf;
 	struct resource *io_mem, *attr_mem;
@@ -286,7 +286,7 @@ fail0:
 	return status;
 }
 
-static int __devexit bfin_cf_remove(struct platform_device *pdev)
+static int bfin_cf_remove(struct platform_device *pdev)
 {
 	struct bfin_cf_socket *cf = platform_get_drvdata(pdev);
 
@@ -307,7 +307,7 @@ static struct platform_driver bfin_cf_driver = {
 		   .owner = THIS_MODULE,
 		   },
 	.probe = bfin_cf_probe,
-	.remove = __devexit_p(bfin_cf_remove),
+	.remove = bfin_cf_remove,
 };
 
 module_platform_driver(bfin_cf_driver);
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 673c14e..5292db6 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -484,7 +484,7 @@ static int socket_early_resume(struct pcmcia_socket *skt)
 
 static int socket_late_resume(struct pcmcia_socket *skt)
 {
-	int ret;
+	int ret = 0;
 
 	mutex_lock(&skt->ops_mutex);
 	skt->state &= ~SOCKET_SUSPEND;
@@ -511,19 +511,31 @@ static int socket_late_resume(struct pcmcia_socket *skt)
 		return socket_insert(skt);
 	}
 
+	if (!(skt->state & SOCKET_CARDBUS) && (skt->callback))
+		ret = skt->callback->early_resume(skt);
+	return ret;
+}
+
+/*
+ * Finalize the resume. In case of a cardbus socket, we have
+ * to rebind the devices as we can't be certain that it has been
+ * replaced, or not.
+ */
+static int socket_complete_resume(struct pcmcia_socket *skt)
+{
+	int ret = 0;
 #ifdef CONFIG_CARDBUS
 	if (skt->state & SOCKET_CARDBUS) {
 		/* We can't be sure the CardBus card is the same
 		 * as the one previously inserted. Therefore, remove
 		 * and re-add... */
 		cb_free(skt);
-		cb_alloc(skt);
-		return 0;
+		ret = cb_alloc(skt);
+		if (ret)
+			cb_free(skt);
 	}
 #endif
-	if (!(skt->state & SOCKET_CARDBUS) && (skt->callback))
-		skt->callback->early_resume(skt);
-	return 0;
+	return ret;
 }
 
 /*
@@ -533,11 +545,15 @@ static int socket_late_resume(struct pcmcia_socket *skt)
  */
 static int socket_resume(struct pcmcia_socket *skt)
 {
+	int err;
 	if (!(skt->state & SOCKET_SUSPEND))
 		return -EBUSY;
 
 	socket_early_resume(skt);
-	return socket_late_resume(skt);
+	err = socket_late_resume(skt);
+	if (!err)
+		err = socket_complete_resume(skt);
+	return err;
 }
 
 static void socket_remove(struct pcmcia_socket *skt)
@@ -848,6 +864,12 @@ static int __used pcmcia_socket_dev_resume(struct device *dev)
 	return __pcmcia_pm_op(dev, socket_late_resume);
 }
 
+static void __used pcmcia_socket_dev_complete(struct device *dev)
+{
+	WARN(__pcmcia_pm_op(dev, socket_complete_resume),
+		"failed to complete resume");
+}
+
 static const struct dev_pm_ops pcmcia_socket_pm_ops = {
 	/* dev_resume may be called with IRQs enabled */
 	SET_SYSTEM_SLEEP_PM_OPS(NULL,
@@ -862,6 +884,7 @@ static const struct dev_pm_ops pcmcia_socket_pm_ops = {
 	.resume_noirq = pcmcia_socket_dev_resume_noirq,
 	.thaw_noirq = pcmcia_socket_dev_resume_noirq,
 	.restore_noirq = pcmcia_socket_dev_resume_noirq,
+	.complete = pcmcia_socket_dev_complete,
 };
 
 #define PCMCIA_SOCKET_CLASS_PM_OPS (&pcmcia_socket_pm_ops)
diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c
index a484b1f..a31e69e 100644
--- a/drivers/pcmcia/db1xxx_ss.c
+++ b/drivers/pcmcia/db1xxx_ss.c
@@ -409,7 +409,7 @@ static struct pccard_operations db1x_pcmcia_operations = {
 	.set_mem_map		= au1x00_pcmcia_set_mem_map,
 };
 
-static int __devinit db1x_pcmcia_socket_probe(struct platform_device *pdev)
+static int db1x_pcmcia_socket_probe(struct platform_device *pdev)
 {
 	struct db1x_pcmcia_sock *sock;
 	struct resource *r;
@@ -559,7 +559,7 @@ out0:
 	return ret;
 }
 
-static int __devexit db1x_pcmcia_socket_remove(struct platform_device *pdev)
+static int db1x_pcmcia_socket_remove(struct platform_device *pdev)
 {
 	struct db1x_pcmcia_sock *sock = platform_get_drvdata(pdev);
 
@@ -577,7 +577,7 @@ static struct platform_driver db1x_pcmcia_socket_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= db1x_pcmcia_socket_probe,
-	.remove		= __devexit_p(db1x_pcmcia_socket_remove),
+	.remove		= db1x_pcmcia_socket_remove,
 };
 
 module_platform_driver(db1x_pcmcia_socket_driver);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 079629b..2deacbb 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -920,8 +920,6 @@ static int pcmcia_bus_match(struct device *dev, struct device_driver *drv)
 	return 0;
 }
 
-#ifdef CONFIG_HOTPLUG
-
 static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
 	struct pcmcia_device *p_dev;
@@ -962,15 +960,6 @@ static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
 	return 0;
 }
 
-#else
-
-static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-	return -ENODEV;
-}
-
-#endif
-
 /************************ runtime PM support ***************************/
 
 static int pcmcia_dev_suspend(struct device *dev, pm_message_t state);
@@ -1329,7 +1318,7 @@ static struct pcmcia_callback pcmcia_bus_callback = {
 	.resume = pcmcia_bus_resume,
 };
 
-static int __devinit pcmcia_bus_add_socket(struct device *dev,
+static int pcmcia_bus_add_socket(struct device *dev,
 					   struct class_interface *class_intf)
 {
 	struct pcmcia_socket *socket = dev_get_drvdata(dev);
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
index 7647d23..a007321a 100644
--- a/drivers/pcmcia/electra_cf.c
+++ b/drivers/pcmcia/electra_cf.c
@@ -181,7 +181,7 @@ static struct pccard_operations electra_cf_ops = {
 	.set_mem_map		= electra_cf_set_mem_map,
 };
 
-static int __devinit electra_cf_probe(struct platform_device *ofdev)
+static int electra_cf_probe(struct platform_device *ofdev)
 {
 	struct device *device = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
@@ -324,7 +324,7 @@ fail1:
 
 }
 
-static int __devexit electra_cf_remove(struct platform_device *ofdev)
+static int electra_cf_remove(struct platform_device *ofdev)
 {
 	struct device *device = &ofdev->dev;
 	struct electra_cf_socket *cf;
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index 4e8831b..3578e1c 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -35,7 +35,7 @@ static struct pci_driver i82092aa_pci_driver = {
 	.name           = "i82092aa",
 	.id_table       = i82092aa_pci_ids,
 	.probe          = i82092aa_pci_probe,
-	.remove         = __devexit_p(i82092aa_pci_remove),
+	.remove         = i82092aa_pci_remove,
 };
 
 
@@ -67,7 +67,7 @@ static struct socket_info sockets[MAX_SOCKETS];
 static int socket_count;  /* shortcut */                                  	                                	
 
 
-static int __devinit i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	unsigned char configbyte;
 	int i, ret;
@@ -162,7 +162,7 @@ err_out_disable:
 	return ret;			
 }
 
-static void __devexit i82092aa_pci_remove(struct pci_dev *dev)
+static void i82092aa_pci_remove(struct pci_dev *dev)
 {
 	struct pcmcia_socket *socket = pci_get_drvdata(dev);
 
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index fa74efe..25c4b19 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -25,7 +25,7 @@
 #include <asm/sizes.h>
 
 #include <mach/mux.h>
-#include <plat/tc.h>
+#include <mach/tc.h>
 
 
 /* NOTE:  don't expect this to support many I/O cards.  The 16xx chips have
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 253e386..b29d97e 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -589,7 +589,7 @@ static int pd6729_check_irq(int irq)
 	return 0;
 }
 
-static u_int __devinit pd6729_isa_scan(void)
+static u_int pd6729_isa_scan(void)
 {
 	u_int mask0, mask = 0;
 	int i;
@@ -620,7 +620,7 @@ static u_int __devinit pd6729_isa_scan(void)
 	return mask;
 }
 
-static int __devinit pd6729_pci_probe(struct pci_dev *dev,
+static int pd6729_pci_probe(struct pci_dev *dev,
 				      const struct pci_device_id *id)
 {
 	int i, j, ret;
@@ -739,7 +739,7 @@ err_out_free_mem:
 	return ret;
 }
 
-static void __devexit pd6729_pci_remove(struct pci_dev *dev)
+static void pd6729_pci_remove(struct pci_dev *dev)
 {
 	int i;
 	struct pd6729_socket *socket = pci_get_drvdata(dev);
@@ -772,7 +772,7 @@ static struct pci_driver pd6729_pci_driver = {
 	.name		= "pd6729",
 	.id_table	= pd6729_pci_ids,
 	.probe		= pd6729_pci_probe,
-	.remove		= __devexit_p(pd6729_pci_remove),
+	.remove		= pd6729_pci_remove,
 };
 
 static int pd6729_module_init(void)
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index 7dd879c..89ebd8c 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -208,7 +208,7 @@ static struct pcmcia_low_level sharpsl_pcmcia_ops = {
 #ifdef CONFIG_SA1100_COLLIE
 #include "sa11xx_base.h"
 
-int __devinit pcmcia_collie_init(struct device *dev)
+int pcmcia_collie_init(struct device *dev)
 {
        int ret = -ENODEV;
 
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 9da9656..430a9ac 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -1199,7 +1199,7 @@ static const struct attribute_group rsrc_attributes = {
 	.attrs = pccard_rsrc_attributes,
 };
 
-static int __devinit pccard_sysfs_add_rsrc(struct device *dev,
+static int pccard_sysfs_add_rsrc(struct device *dev,
 					   struct class_interface *class_intf)
 {
 	struct pcmcia_socket *s = dev_get_drvdata(dev);
@@ -1209,7 +1209,7 @@ static int __devinit pccard_sysfs_add_rsrc(struct device *dev,
 	return sysfs_create_group(&dev->kobj, &rsrc_attributes);
 }
 
-static void __devexit pccard_sysfs_remove_rsrc(struct device *dev,
+static void pccard_sysfs_remove_rsrc(struct device *dev,
 					       struct class_interface *class_intf)
 {
 	struct pcmcia_socket *s = dev_get_drvdata(dev);
@@ -1222,7 +1222,7 @@ static void __devexit pccard_sysfs_remove_rsrc(struct device *dev,
 static struct class_interface pccard_rsrc_interface __refdata = {
 	.class = &pcmcia_socket_class,
 	.add_dev = &pccard_sysfs_add_rsrc,
-	.remove_dev = __devexit_p(&pccard_sysfs_remove_rsrc),
+	.remove_dev = &pccard_sysfs_remove_rsrc,
 };
 
 static int __init nonstatic_sysfs_init(void)
diff --git a/drivers/pcmcia/sa1100_assabet.c b/drivers/pcmcia/sa1100_assabet.c
index ba8557e..44cfc44 100644
--- a/drivers/pcmcia/sa1100_assabet.c
+++ b/drivers/pcmcia/sa1100_assabet.c
@@ -95,7 +95,7 @@ static struct pcmcia_low_level assabet_pcmcia_ops = {
 	.socket_suspend		= assabet_pcmcia_socket_suspend,
 };
 
-int __devinit pcmcia_assabet_init(struct device *dev)
+int pcmcia_assabet_init(struct device *dev)
 {
 	int ret = -ENODEV;
 
diff --git a/drivers/pcmcia/sa1100_cerf.c b/drivers/pcmcia/sa1100_cerf.c
index c59c449..b3774e5 100644
--- a/drivers/pcmcia/sa1100_cerf.c
+++ b/drivers/pcmcia/sa1100_cerf.c
@@ -81,7 +81,7 @@ static struct pcmcia_low_level cerf_pcmcia_ops = {
 	.configure_socket	= cerf_pcmcia_configure_socket,
 };
 
-int __devinit pcmcia_cerf_init(struct device *dev)
+int pcmcia_cerf_init(struct device *dev)
 {
 	int ret = -ENODEV;
 
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index 2eea664..ff8a027 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -43,7 +43,7 @@
 
 int __init pcmcia_collie_init(struct device *dev);
 
-static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) __devinitdata = {
+static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = {
 #ifdef CONFIG_SA1100_ASSABET
 	pcmcia_assabet_init,
 #endif
@@ -67,7 +67,7 @@ static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) __devinitdata = {
 #endif
 };
 
-static int __devinit sa11x0_drv_pcmcia_probe(struct platform_device *dev)
+static int sa11x0_drv_pcmcia_probe(struct platform_device *dev)
 {
 	int i, ret = -ENODEV;
 
diff --git a/drivers/pcmcia/sa1100_h3600.c b/drivers/pcmcia/sa1100_h3600.c
index d9c7337..431d8b0 100644
--- a/drivers/pcmcia/sa1100_h3600.c
+++ b/drivers/pcmcia/sa1100_h3600.c
@@ -153,7 +153,7 @@ struct pcmcia_low_level h3600_pcmcia_ops = {
 	.socket_suspend		= h3600_pcmcia_socket_suspend,
 };
 
-int __devinit pcmcia_h3600_init(struct device *dev)
+int pcmcia_h3600_init(struct device *dev)
 {
 	int ret = -ENODEV;
 
diff --git a/drivers/pcmcia/sa1100_shannon.c b/drivers/pcmcia/sa1100_shannon.c
index 56ab739..b07a2dc 100644
--- a/drivers/pcmcia/sa1100_shannon.c
+++ b/drivers/pcmcia/sa1100_shannon.c
@@ -92,7 +92,7 @@ static struct pcmcia_low_level shannon_pcmcia_ops = {
 	.configure_socket	= shannon_pcmcia_configure_socket,
 };
 
-int __devinit pcmcia_shannon_init(struct device *dev)
+int pcmcia_shannon_init(struct device *dev)
 {
 	int ret = -ENODEV;
 
diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c
index 8647b17..73fd379 100644
--- a/drivers/pcmcia/sa1100_simpad.c
+++ b/drivers/pcmcia/sa1100_simpad.c
@@ -109,7 +109,7 @@ static struct pcmcia_low_level simpad_pcmcia_ops = {
 	.socket_suspend		= simpad_pcmcia_socket_suspend,
 };
 
-int __devinit pcmcia_simpad_init(struct device *dev)
+int pcmcia_simpad_init(struct device *dev)
 {
 	int ret = -ENODEV;
 
diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
index 70f728c..65b02c3 100644
--- a/drivers/pcmcia/sa1111_generic.c
+++ b/drivers/pcmcia/sa1111_generic.c
@@ -211,7 +211,7 @@ static int pcmcia_probe(struct sa1111_dev *dev)
 	return 0;
 }
 
-static int __devexit pcmcia_remove(struct sa1111_dev *dev)
+static int pcmcia_remove(struct sa1111_dev *dev)
 {
 	struct sa1111_pcmcia_socket *next, *s = dev_get_drvdata(&dev->dev);
 
@@ -234,7 +234,7 @@ static struct sa1111_driver pcmcia_driver = {
 	},
 	.devid		= SA1111_DEVID_PCMCIA,
 	.probe		= pcmcia_probe,
-	.remove		= __devexit_p(pcmcia_remove),
+	.remove		= pcmcia_remove,
 };
 
 static int __init sa1111_drv_pcmcia_init(void)
diff --git a/drivers/pcmcia/sa1111_jornada720.c b/drivers/pcmcia/sa1111_jornada720.c
index 69428d1..3baa3ef 100644
--- a/drivers/pcmcia/sa1111_jornada720.c
+++ b/drivers/pcmcia/sa1111_jornada720.c
@@ -91,7 +91,7 @@ static struct pcmcia_low_level jornada720_pcmcia_ops = {
 	.nr			= 2,
 };
 
-int __devinit pcmcia_jornada720_init(struct device *dev)
+int pcmcia_jornada720_init(struct device *dev)
 {
 	int ret = -ENODEV;
 
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index 86e4a1a..75806be 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -564,7 +564,7 @@ static inline void reserve_using_irq(int slot)
 	vrc4171_irq_mask &= ~(1 << irq);
 }
 
-static int __devinit vrc4171_add_sockets(void)
+static int vrc4171_add_sockets(void)
 {
 	vrc4171_socket_t *socket;
 	int slot, retval;
@@ -631,7 +631,7 @@ static void vrc4171_remove_sockets(void)
 	}
 }
 
-static int __devinit vrc4171_card_setup(char *options)
+static int vrc4171_card_setup(char *options)
 {
 	if (options == NULL || *options == '\0')
 		return 1;
@@ -712,7 +712,7 @@ static struct platform_driver vrc4171_card_driver = {
 	},
 };
 
-static int __devinit vrc4171_card_init(void)
+static int vrc4171_card_init(void)
 {
 	int retval;
 
@@ -746,7 +746,7 @@ static int __devinit vrc4171_card_init(void)
 	return 0;
 }
 
-static void __devexit vrc4171_card_exit(void)
+static void vrc4171_card_exit(void)
 {
 	free_irq(vrc4171_irq, vrc4171_sockets);
 	vrc4171_remove_sockets();
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c
index cd0a315..d926920 100644
--- a/drivers/pcmcia/vrc4173_cardu.c
+++ b/drivers/pcmcia/vrc4173_cardu.c
@@ -456,7 +456,7 @@ static void cardu_interrupt(int irq, void *dev_id)
 	}
 }
 
-static int __devinit vrc4173_cardu_probe(struct pci_dev *dev,
+static int vrc4173_cardu_probe(struct pci_dev *dev,
                                          const struct pci_device_id *ent)
 {
 	vrc4173_socket_t *socket;
@@ -533,7 +533,7 @@ disable:
 	return ret;
 }
 
-static int __devinit vrc4173_cardu_setup(char *options)
+static int vrc4173_cardu_setup(char *options)
 {
 	if (options == NULL || *options == '\0')
 		return 1;
@@ -574,14 +574,14 @@ static struct pci_driver vrc4173_cardu_driver = {
 	.id_table	= vrc4173_cardu_id_table,
 };
 
-static int __devinit vrc4173_cardu_init(void)
+static int vrc4173_cardu_init(void)
 {
 	vrc4173_cardu_slots = 0;
 
 	return pci_register_driver(&vrc4173_cardu_driver);
 }
 
-static void __devexit vrc4173_cardu_exit(void)
+static void vrc4173_cardu_exit(void)
 {
 	pci_unregister_driver(&vrc4173_cardu_driver);
 }
diff --git a/drivers/pcmcia/xxs1500_ss.c b/drivers/pcmcia/xxs1500_ss.c
index fd5fbd1..95f5b27 100644
--- a/drivers/pcmcia/xxs1500_ss.c
+++ b/drivers/pcmcia/xxs1500_ss.c
@@ -204,7 +204,7 @@ static struct pccard_operations xxs1500_pcmcia_operations = {
 	.set_mem_map		= au1x00_pcmcia_set_mem_map,
 };
 
-static int __devinit xxs1500_pcmcia_probe(struct platform_device *pdev)
+static int xxs1500_pcmcia_probe(struct platform_device *pdev)
 {
 	struct xxs1500_pcmcia_sock *sock;
 	struct resource *r;
@@ -299,7 +299,7 @@ out0:
 	return ret;
 }
 
-static int __devexit xxs1500_pcmcia_remove(struct platform_device *pdev)
+static int xxs1500_pcmcia_remove(struct platform_device *pdev)
 {
 	struct xxs1500_pcmcia_sock *sock = platform_get_drvdata(pdev);
 
@@ -317,7 +317,7 @@ static struct platform_driver xxs1500_pcmcia_socket_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= xxs1500_pcmcia_probe,
-	.remove		= __devexit_p(xxs1500_pcmcia_remove),
+	.remove		= xxs1500_pcmcia_remove,
 };
 
 module_platform_driver(xxs1500_pcmcia_socket_driver);
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 667678d..6b4ff09 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -783,7 +783,7 @@ static void yenta_free_resources(struct yenta_socket *socket)
 /*
  * Close it down - release our resources and go home..
  */
-static void __devexit yenta_close(struct pci_dev *dev)
+static void yenta_close(struct pci_dev *dev)
 {
 	struct yenta_socket *sock = pci_get_drvdata(dev);
 
@@ -1142,7 +1142,7 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
  * interrupt, and that we can map the cardbus area. Fill in the
  * socket information structure..
  */
-static int __devinit yenta_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int yenta_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	struct yenta_socket *socket;
 	int ret;
@@ -1435,7 +1435,7 @@ static struct pci_driver yenta_cardbus_driver = {
 	.name		= "yenta_cardbus",
 	.id_table	= yenta_table,
 	.probe		= yenta_probe,
-	.remove		= __devexit_p(yenta_close),
+	.remove		= yenta_close,
 	.driver.pm	= YENTA_PM_OPS,
 };
 
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index aeecf0f..f06a073 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -26,6 +26,15 @@ config DEBUG_PINCTRL
 	help
 	  Say Y here to add some extra checks and diagnostics to PINCTRL calls.
 
+config PINCTRL_AT91
+	bool "AT91 pinctrl driver"
+	depends on OF
+	depends on ARCH_AT91
+	select PINMUX
+	select PINCONF
+	help
+	  Say Y here to enable the at91 pinctrl driver
+
 config PINCTRL_BCM2835
 	bool
 	select PINMUX
@@ -91,17 +100,15 @@ config PINCTRL_MMP2
 
 config PINCTRL_MXS
 	bool
+	select PINMUX
+	select PINCONF
 
 config PINCTRL_IMX23
 	bool
-	select PINMUX
-	select PINCONF
 	select PINCTRL_MXS
 
 config PINCTRL_IMX28
 	bool
-	select PINMUX
-	select PINCONF
 	select PINCTRL_MXS
 
 config PINCTRL_NOMADIK
@@ -143,23 +150,21 @@ config PINCTRL_SINGLE
 	  This selects the device tree based generic pinctrl driver.
 
 config PINCTRL_SIRF
-	bool "CSR SiRFprimaII pin controller driver"
-	depends on ARCH_PRIMA2
+	bool "CSR SiRFprimaII/SiRFmarco pin controller driver"
+	depends on ARCH_SIRF
 	select PINMUX
 
 config PINCTRL_TEGRA
 	bool
+	select PINMUX
+	select PINCONF
 
 config PINCTRL_TEGRA20
 	bool
-	select PINMUX
-	select PINCONF
 	select PINCTRL_TEGRA
 
 config PINCTRL_TEGRA30
 	bool
-	select PINMUX
-	select PINCONF
 	select PINCTRL_TEGRA
 
 config PINCTRL_U300
@@ -188,27 +193,12 @@ config PINCTRL_EXYNOS4
 	depends on OF && GPIOLIB
 	select PINCTRL_SAMSUNG
 
-config PINCTRL_MVEBU
-	bool
-	depends on ARCH_MVEBU
+config PINCTRL_EXYNOS5440
+	bool "Samsung EXYNOS5440 SoC pinctrl driver"
 	select PINMUX
 	select PINCONF
 
-config PINCTRL_DOVE
-	bool
-	select PINCTRL_MVEBU
-
-config PINCTRL_KIRKWOOD
-	bool
-	select PINCTRL_MVEBU
-
-config PINCTRL_ARMADA_370
-	bool
-	select PINCTRL_MVEBU
-
-config PINCTRL_ARMADA_XP
-	bool
-	select PINCTRL_MVEBU
+source "drivers/pinctrl/mvebu/Kconfig"
 
 source "drivers/pinctrl/spear/Kconfig"
 
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index f395ba5..fc4606f 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -9,6 +9,7 @@ ifeq ($(CONFIG_OF),y)
 obj-$(CONFIG_PINCTRL)		+= devicetree.o
 endif
 obj-$(CONFIG_GENERIC_PINCONF)	+= pinconf-generic.o
+obj-$(CONFIG_PINCTRL_AT91)	+= pinctrl-at91.o
 obj-$(CONFIG_PINCTRL_BCM2835)	+= pinctrl-bcm2835.o
 obj-$(CONFIG_PINCTRL_IMX)	+= pinctrl-imx.o
 obj-$(CONFIG_PINCTRL_IMX35)	+= pinctrl-imx35.o
@@ -36,12 +37,9 @@ obj-$(CONFIG_PINCTRL_U300)	+= pinctrl-u300.o
 obj-$(CONFIG_PINCTRL_COH901)	+= pinctrl-coh901.o
 obj-$(CONFIG_PINCTRL_SAMSUNG)	+= pinctrl-samsung.o
 obj-$(CONFIG_PINCTRL_EXYNOS4)	+= pinctrl-exynos.o
-obj-$(CONFIG_PINCTRL_MVEBU)	+= pinctrl-mvebu.o
-obj-$(CONFIG_PINCTRL_DOVE)	+= pinctrl-dove.o
-obj-$(CONFIG_PINCTRL_KIRKWOOD)	+= pinctrl-kirkwood.o
-obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
-obj-$(CONFIG_PINCTRL_ARMADA_XP)  += pinctrl-armada-xp.o
+obj-$(CONFIG_PINCTRL_EXYNOS5440)	+= pinctrl-exynos5440.o
 obj-$(CONFIG_PINCTRL_XWAY)	+= pinctrl-xway.o
 obj-$(CONFIG_PINCTRL_LANTIQ)	+= pinctrl-lantiq.o
 
+obj-$(CONFIG_PLAT_ORION)        += mvebu/
 obj-$(CONFIG_PLAT_SPEAR)	+= spear/
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 2e39c04..5cdee86 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -345,6 +345,62 @@ void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
 }
 EXPORT_SYMBOL_GPL(pinctrl_add_gpio_ranges);
 
+struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname,
+		struct pinctrl_gpio_range *range)
+{
+	struct pinctrl_dev *pctldev = get_pinctrl_dev_from_devname(devname);
+
+	/*
+	 * If we can't find this device, let's assume that is because
+	 * it has not probed yet, so the driver trying to register this
+	 * range need to defer probing.
+	 */
+	if (!pctldev)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	pinctrl_add_gpio_range(pctldev, range);
+	return pctldev;
+}
+EXPORT_SYMBOL_GPL(pinctrl_find_and_add_gpio_range);
+
+/**
+ * pinctrl_find_gpio_range_from_pin() - locate the GPIO range for a pin
+ * @pctldev: the pin controller device to look in
+ * @pin: a controller-local number to find the range for
+ */
+struct pinctrl_gpio_range *
+pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev,
+				 unsigned int pin)
+{
+	struct pinctrl_gpio_range *range = NULL;
+
+	/* Loop over the ranges */
+	list_for_each_entry(range, &pctldev->gpio_ranges, node) {
+		/* Check if we're in the valid range */
+		if (pin >= range->pin_base &&
+		    pin < range->pin_base + range->npins) {
+			return range;
+		}
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(pinctrl_find_gpio_range_from_pin);
+
+/**
+ * pinctrl_remove_gpio_range() - remove a range of GPIOs fro a pin controller
+ * @pctldev: pin controller device to remove the range from
+ * @range: the GPIO range to remove
+ */
+void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
+			       struct pinctrl_gpio_range *range)
+{
+	mutex_lock(&pinctrl_mutex);
+	list_del(&range->node);
+	mutex_unlock(&pinctrl_mutex);
+}
+EXPORT_SYMBOL_GPL(pinctrl_remove_gpio_range);
+
 /**
  * pinctrl_get_group_selector() - returns the group selector for a group
  * @pctldev: the pin controller handling the group
@@ -563,6 +619,8 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
 		return -EPROBE_DEFER;
 	}
 
+	setting->dev_name = map->dev_name;
+
 	switch (map->type) {
 	case PIN_MAP_TYPE_MUX_GROUP:
 		ret = pinmux_map_to_setting(map, setting);
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index 1f40ff6..12f5694 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -105,12 +105,14 @@ struct pinctrl_setting_configs {
  * @type: the type of setting
  * @pctldev: pin control device handling to be programmed. Not used for
  *   PIN_MAP_TYPE_DUMMY_STATE.
+ * @dev_name: the name of the device using this state
  * @data: Data specific to the setting type
  */
 struct pinctrl_setting {
 	struct list_head node;
 	enum pinctrl_map_type type;
 	struct pinctrl_dev *pctldev;
+	const char *dev_name;
 	union {
 		struct pinctrl_setting_mux mux;
 		struct pinctrl_setting_configs configs;
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
index fcb1de4..fe2d1af 100644
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -106,6 +106,17 @@ static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np)
 	return NULL;
 }
 
+struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
+{
+	struct pinctrl_dev *pctldev;
+
+	pctldev = find_pinctrl_by_of_node(np);
+	if (!pctldev)
+		return NULL;
+
+	return pctldev;
+}
+
 static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
 				struct device_node *np_config)
 {
diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig
new file mode 100644
index 0000000..366fa54
--- /dev/null
+++ b/drivers/pinctrl/mvebu/Kconfig
@@ -0,0 +1,24 @@
+if PLAT_ORION
+
+config PINCTRL_MVEBU
+	bool
+	select PINMUX
+	select PINCONF
+
+config PINCTRL_DOVE
+	bool
+	select PINCTRL_MVEBU
+
+config PINCTRL_KIRKWOOD
+	bool
+	select PINCTRL_MVEBU
+
+config PINCTRL_ARMADA_370
+	bool
+	select PINCTRL_MVEBU
+
+config PINCTRL_ARMADA_XP
+	bool
+	select PINCTRL_MVEBU
+
+endif
diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile
new file mode 100644
index 0000000..37c2532
--- /dev/null
+++ b/drivers/pinctrl/mvebu/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_PINCTRL_MVEBU)	+= pinctrl-mvebu.o
+obj-$(CONFIG_PINCTRL_DOVE)	+= pinctrl-dove.o
+obj-$(CONFIG_PINCTRL_KIRKWOOD)	+= pinctrl-kirkwood.o
+obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
+obj-$(CONFIG_PINCTRL_ARMADA_XP)  += pinctrl-armada-xp.o
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-370.c b/drivers/pinctrl/mvebu/pinctrl-armada-370.c
new file mode 100644
index 0000000..c907647
--- /dev/null
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-370.c
@@ -0,0 +1,421 @@
+/*
+ * Marvell Armada 370 pinctrl driver based on mvebu pinctrl core
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@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.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-mvebu.h"
+
+static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = {
+	MPP_MODE(0,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "uart0", "rxd")),
+	MPP_MODE(1,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "uart0", "txd")),
+	MPP_MODE(2,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "i2c0", "sck"),
+	   MPP_FUNCTION(0x2, "uart0", "txd")),
+	MPP_MODE(3,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "i2c0", "sda"),
+	   MPP_FUNCTION(0x2, "uart0", "rxd")),
+	MPP_MODE(4,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "cpu_pd", "vdd")),
+	MPP_MODE(5,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "txclko"),
+	   MPP_FUNCTION(0x2, "uart1", "txd"),
+	   MPP_FUNCTION(0x4, "spi1", "clk"),
+	   MPP_FUNCTION(0x5, "audio", "mclk")),
+	MPP_MODE(6,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "txd0"),
+	   MPP_FUNCTION(0x2, "sata0", "prsnt"),
+	   MPP_FUNCTION(0x4, "tdm", "rst"),
+	   MPP_FUNCTION(0x5, "audio", "sdo")),
+	MPP_MODE(7,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "txd1"),
+	   MPP_FUNCTION(0x4, "tdm", "tdx"),
+	   MPP_FUNCTION(0x5, "audio", "lrclk")),
+	MPP_MODE(8,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "txd2"),
+	   MPP_FUNCTION(0x2, "uart0", "rts"),
+	   MPP_FUNCTION(0x4, "tdm", "drx"),
+	   MPP_FUNCTION(0x5, "audio", "bclk")),
+	MPP_MODE(9,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "txd3"),
+	   MPP_FUNCTION(0x2, "uart1", "txd"),
+	   MPP_FUNCTION(0x3, "sd0", "clk"),
+	   MPP_FUNCTION(0x5, "audio", "spdifo")),
+	MPP_MODE(10,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "txctl"),
+	   MPP_FUNCTION(0x2, "uart0", "cts"),
+	   MPP_FUNCTION(0x4, "tdm", "fsync"),
+	   MPP_FUNCTION(0x5, "audio", "sdi")),
+	MPP_MODE(11,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "rxd0"),
+	   MPP_FUNCTION(0x2, "uart1", "rxd"),
+	   MPP_FUNCTION(0x3, "sd0", "cmd"),
+	   MPP_FUNCTION(0x4, "spi0", "cs1"),
+	   MPP_FUNCTION(0x5, "sata1", "prsnt"),
+	   MPP_FUNCTION(0x6, "spi1", "cs1")),
+	MPP_MODE(12,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "rxd1"),
+	   MPP_FUNCTION(0x2, "i2c1", "sda"),
+	   MPP_FUNCTION(0x3, "sd0", "d0"),
+	   MPP_FUNCTION(0x4, "spi1", "cs0"),
+	   MPP_FUNCTION(0x5, "audio", "spdifi")),
+	MPP_MODE(13,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "rxd2"),
+	   MPP_FUNCTION(0x2, "i2c1", "sck"),
+	   MPP_FUNCTION(0x3, "sd0", "d1"),
+	   MPP_FUNCTION(0x4, "tdm", "pclk"),
+	   MPP_FUNCTION(0x5, "audio", "rmclk")),
+	MPP_MODE(14,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "rxd3"),
+	   MPP_FUNCTION(0x2, "pcie", "clkreq0"),
+	   MPP_FUNCTION(0x3, "sd0", "d2"),
+	   MPP_FUNCTION(0x4, "spi1", "mosi"),
+	   MPP_FUNCTION(0x5, "spi0", "cs2")),
+	MPP_MODE(15,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "rxctl"),
+	   MPP_FUNCTION(0x2, "pcie", "clkreq1"),
+	   MPP_FUNCTION(0x3, "sd0", "d3"),
+	   MPP_FUNCTION(0x4, "spi1", "miso"),
+	   MPP_FUNCTION(0x5, "spi0", "cs3")),
+	MPP_MODE(16,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "rxclk"),
+	   MPP_FUNCTION(0x2, "uart1", "rxd"),
+	   MPP_FUNCTION(0x4, "tdm", "int"),
+	   MPP_FUNCTION(0x5, "audio", "extclk")),
+	MPP_MODE(17,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "ge", "mdc")),
+	MPP_MODE(18,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge", "mdio")),
+	MPP_MODE(19,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "txclk"),
+	   MPP_FUNCTION(0x2, "ge1", "txclkout"),
+	   MPP_FUNCTION(0x4, "tdm", "pclk")),
+	MPP_MODE(20,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "txd4"),
+	   MPP_FUNCTION(0x2, "ge1", "txd0")),
+	MPP_MODE(21,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "txd5"),
+	   MPP_FUNCTION(0x2, "ge1", "txd1"),
+	   MPP_FUNCTION(0x4, "uart1", "txd")),
+	MPP_MODE(22,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "txd6"),
+	   MPP_FUNCTION(0x2, "ge1", "txd2"),
+	   MPP_FUNCTION(0x4, "uart0", "rts")),
+	MPP_MODE(23,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "txd7"),
+	   MPP_FUNCTION(0x2, "ge1", "txd3"),
+	   MPP_FUNCTION(0x4, "spi1", "mosi")),
+	MPP_MODE(24,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "col"),
+	   MPP_FUNCTION(0x2, "ge1", "txctl"),
+	   MPP_FUNCTION(0x4, "spi1", "cs0")),
+	MPP_MODE(25,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "rxerr"),
+	   MPP_FUNCTION(0x2, "ge1", "rxd0"),
+	   MPP_FUNCTION(0x4, "uart1", "rxd")),
+	MPP_MODE(26,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "crs"),
+	   MPP_FUNCTION(0x2, "ge1", "rxd1"),
+	   MPP_FUNCTION(0x4, "spi1", "miso")),
+	MPP_MODE(27,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "rxd4"),
+	   MPP_FUNCTION(0x2, "ge1", "rxd2"),
+	   MPP_FUNCTION(0x4, "uart0", "cts")),
+	MPP_MODE(28,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "rxd5"),
+	   MPP_FUNCTION(0x2, "ge1", "rxd3")),
+	MPP_MODE(29,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "rxd6"),
+	   MPP_FUNCTION(0x2, "ge1", "rxctl"),
+	   MPP_FUNCTION(0x4, "i2c1", "sda")),
+	MPP_MODE(30,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "ge0", "rxd7"),
+	   MPP_FUNCTION(0x2, "ge1", "rxclk"),
+	   MPP_FUNCTION(0x4, "i2c1", "sck")),
+	MPP_MODE(31,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x3, "tclk", NULL),
+	   MPP_FUNCTION(0x4, "ge0", "txerr")),
+	MPP_MODE(32,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "spi0", "cs0")),
+	MPP_MODE(33,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "dev", "bootcs"),
+	   MPP_FUNCTION(0x2, "spi0", "cs0")),
+	MPP_MODE(34,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "dev", "wen0"),
+	   MPP_FUNCTION(0x2, "spi0", "mosi")),
+	MPP_MODE(35,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "dev", "oen"),
+	   MPP_FUNCTION(0x2, "spi0", "sck")),
+	MPP_MODE(36,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "dev", "a1"),
+	   MPP_FUNCTION(0x2, "spi0", "miso")),
+	MPP_MODE(37,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "dev", "a0"),
+	   MPP_FUNCTION(0x2, "sata0", "prsnt")),
+	MPP_MODE(38,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ready"),
+	   MPP_FUNCTION(0x2, "uart1", "cts"),
+	   MPP_FUNCTION(0x3, "uart0", "cts")),
+	MPP_MODE(39,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ad0"),
+	   MPP_FUNCTION(0x2, "audio", "spdifo")),
+	MPP_MODE(40,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ad1"),
+	   MPP_FUNCTION(0x2, "uart1", "rts"),
+	   MPP_FUNCTION(0x3, "uart0", "rts")),
+	MPP_MODE(41,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ad2"),
+	   MPP_FUNCTION(0x2, "uart1", "rxd")),
+	MPP_MODE(42,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ad3"),
+	   MPP_FUNCTION(0x2, "uart1", "txd")),
+	MPP_MODE(43,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ad4"),
+	   MPP_FUNCTION(0x2, "audio", "bclk")),
+	MPP_MODE(44,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ad5"),
+	   MPP_FUNCTION(0x2, "audio", "mclk")),
+	MPP_MODE(45,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ad6"),
+	   MPP_FUNCTION(0x2, "audio", "lrclk")),
+	MPP_MODE(46,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ad7"),
+	   MPP_FUNCTION(0x2, "audio", "sdo")),
+	MPP_MODE(47,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ad8"),
+	   MPP_FUNCTION(0x3, "sd0", "clk"),
+	   MPP_FUNCTION(0x5, "audio", "spdifo")),
+	MPP_MODE(48,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ad9"),
+	   MPP_FUNCTION(0x2, "uart0", "rts"),
+	   MPP_FUNCTION(0x3, "sd0", "cmd"),
+	   MPP_FUNCTION(0x4, "sata1", "prsnt"),
+	   MPP_FUNCTION(0x5, "spi0", "cs1")),
+	MPP_MODE(49,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ad10"),
+	   MPP_FUNCTION(0x2, "pcie", "clkreq1"),
+	   MPP_FUNCTION(0x3, "sd0", "d0"),
+	   MPP_FUNCTION(0x4, "spi1", "cs0"),
+	   MPP_FUNCTION(0x5, "audio", "spdifi")),
+	MPP_MODE(50,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ad11"),
+	   MPP_FUNCTION(0x2, "uart0", "cts"),
+	   MPP_FUNCTION(0x3, "sd0", "d1"),
+	   MPP_FUNCTION(0x4, "spi1", "miso"),
+	   MPP_FUNCTION(0x5, "audio", "rmclk")),
+	MPP_MODE(51,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ad12"),
+	   MPP_FUNCTION(0x2, "i2c1", "sda"),
+	   MPP_FUNCTION(0x3, "sd0", "d2"),
+	   MPP_FUNCTION(0x4, "spi1", "mosi")),
+	MPP_MODE(52,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ad13"),
+	   MPP_FUNCTION(0x2, "i2c1", "sck"),
+	   MPP_FUNCTION(0x3, "sd0", "d3"),
+	   MPP_FUNCTION(0x4, "spi1", "sck")),
+	MPP_MODE(53,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ad14"),
+	   MPP_FUNCTION(0x2, "sd0", "clk"),
+	   MPP_FUNCTION(0x3, "tdm", "pclk"),
+	   MPP_FUNCTION(0x4, "spi0", "cs2"),
+	   MPP_FUNCTION(0x5, "pcie", "clkreq1")),
+	MPP_MODE(54,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ad15"),
+	   MPP_FUNCTION(0x3, "tdm", "dtx")),
+	MPP_MODE(55,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "dev", "cs1"),
+	   MPP_FUNCTION(0x2, "uart1", "txd"),
+	   MPP_FUNCTION(0x3, "tdm", "rst"),
+	   MPP_FUNCTION(0x4, "sata1", "prsnt"),
+	   MPP_FUNCTION(0x5, "sata0", "prsnt")),
+	MPP_MODE(56,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "dev", "cs2"),
+	   MPP_FUNCTION(0x2, "uart1", "cts"),
+	   MPP_FUNCTION(0x3, "uart0", "cts"),
+	   MPP_FUNCTION(0x4, "spi0", "cs3"),
+	   MPP_FUNCTION(0x5, "pcie", "clkreq0"),
+	   MPP_FUNCTION(0x6, "spi1", "cs1")),
+	MPP_MODE(57,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "dev", "cs3"),
+	   MPP_FUNCTION(0x2, "uart1", "rxd"),
+	   MPP_FUNCTION(0x3, "tdm", "fsync"),
+	   MPP_FUNCTION(0x4, "sata0", "prsnt"),
+	   MPP_FUNCTION(0x5, "audio", "sdo")),
+	MPP_MODE(58,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "dev", "cs0"),
+	   MPP_FUNCTION(0x2, "uart1", "rts"),
+	   MPP_FUNCTION(0x3, "tdm", "int"),
+	   MPP_FUNCTION(0x5, "audio", "extclk"),
+	   MPP_FUNCTION(0x6, "uart0", "rts")),
+	MPP_MODE(59,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ale0"),
+	   MPP_FUNCTION(0x2, "uart1", "rts"),
+	   MPP_FUNCTION(0x3, "uart0", "rts"),
+	   MPP_FUNCTION(0x5, "audio", "bclk")),
+	MPP_MODE(60,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "dev", "ale1"),
+	   MPP_FUNCTION(0x2, "uart1", "rxd"),
+	   MPP_FUNCTION(0x3, "sata0", "prsnt"),
+	   MPP_FUNCTION(0x4, "pcie", "rst-out"),
+	   MPP_FUNCTION(0x5, "audio", "sdi")),
+	MPP_MODE(61,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "dev", "wen1"),
+	   MPP_FUNCTION(0x2, "uart1", "txd"),
+	   MPP_FUNCTION(0x5, "audio", "rclk")),
+	MPP_MODE(62,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "dev", "a2"),
+	   MPP_FUNCTION(0x2, "uart1", "cts"),
+	   MPP_FUNCTION(0x3, "tdm", "drx"),
+	   MPP_FUNCTION(0x4, "pcie", "clkreq0"),
+	   MPP_FUNCTION(0x5, "audio", "mclk"),
+	   MPP_FUNCTION(0x6, "uart0", "cts")),
+	MPP_MODE(63,
+	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x1, "spi0", "sck"),
+	   MPP_FUNCTION(0x2, "tclk", NULL)),
+	MPP_MODE(64,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "spi0", "miso"),
+	   MPP_FUNCTION(0x2, "spi0-1", "cs1")),
+	MPP_MODE(65,
+	   MPP_FUNCTION(0x0, "gpio", NULL),
+	   MPP_FUNCTION(0x1, "spi0", "mosi"),
+	   MPP_FUNCTION(0x2, "spi0-1", "cs2")),
+};
+
+static struct mvebu_pinctrl_soc_info armada_370_pinctrl_info;
+
+static struct of_device_id armada_370_pinctrl_of_match[] __devinitdata = {
+	{ .compatible = "marvell,mv88f6710-pinctrl" },
+	{ },
+};
+
+static struct mvebu_mpp_ctrl mv88f6710_mpp_controls[] = {
+	MPP_REG_CTRL(0, 65),
+};
+
+static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = {
+	MPP_GPIO_RANGE(0,   0,  0, 32),
+	MPP_GPIO_RANGE(1,  32, 32, 32),
+	MPP_GPIO_RANGE(2,  64, 64,  2),
+};
+
+static int __devinit armada_370_pinctrl_probe(struct platform_device *pdev)
+{
+	struct mvebu_pinctrl_soc_info *soc = &armada_370_pinctrl_info;
+
+	soc->variant = 0; /* no variants for Armada 370 */
+	soc->controls = mv88f6710_mpp_controls;
+	soc->ncontrols = ARRAY_SIZE(mv88f6710_mpp_controls);
+	soc->modes = mv88f6710_mpp_modes;
+	soc->nmodes = ARRAY_SIZE(mv88f6710_mpp_modes);
+	soc->gpioranges = mv88f6710_mpp_gpio_ranges;
+	soc->ngpioranges = ARRAY_SIZE(mv88f6710_mpp_gpio_ranges);
+
+	pdev->dev.platform_data = soc;
+
+	return mvebu_pinctrl_probe(pdev);
+}
+
+static int __devexit armada_370_pinctrl_remove(struct platform_device *pdev)
+{
+	return mvebu_pinctrl_remove(pdev);
+}
+
+static struct platform_driver armada_370_pinctrl_driver = {
+	.driver = {
+		.name = "armada-370-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(armada_370_pinctrl_of_match),
+	},
+	.probe = armada_370_pinctrl_probe,
+	.remove = __devexit_p(armada_370_pinctrl_remove),
+};
+
+module_platform_driver(armada_370_pinctrl_driver);
+
+MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
+MODULE_DESCRIPTION("Marvell Armada 370 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
new file mode 100644
index 0000000..40bd52a
--- /dev/null
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
@@ -0,0 +1,468 @@
+/*
+ * Marvell Armada XP pinctrl driver based on mvebu pinctrl core
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@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 file supports the three variants of Armada XP SoCs that are
+ * available: mv78230, mv78260 and mv78460. From a pin muxing
+ * perspective, the mv78230 has 49 MPP pins. The mv78260 and mv78460
+ * both have 67 MPP pins (more GPIOs and address lines for the memory
+ * bus mainly). The only difference between the mv78260 and the
+ * mv78460 in terms of pin muxing is the addition of two functions on
+ * pins 43 and 56 to access the VDD of the CPU2 and 3 (mv78260 has two
+ * cores, mv78460 has four cores).
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/bitops.h>
+
+#include "pinctrl-mvebu.h"
+
+enum armada_xp_variant {
+	V_MV78230	= BIT(0),
+	V_MV78260	= BIT(1),
+	V_MV78460	= BIT(2),
+	V_MV78230_PLUS	= (V_MV78230 | V_MV78260 | V_MV78460),
+	V_MV78260_PLUS	= (V_MV78260 | V_MV78460),
+};
+
+static struct mvebu_mpp_mode armada_xp_mpp_modes[] = {
+	MPP_MODE(0,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "txclko",     V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d0",         V_MV78230_PLUS)),
+	MPP_MODE(1,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "txd0",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d1",         V_MV78230_PLUS)),
+	MPP_MODE(2,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "txd1",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d2",         V_MV78230_PLUS)),
+	MPP_MODE(3,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "txd2",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d3",         V_MV78230_PLUS)),
+	MPP_MODE(4,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "txd3",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d4",         V_MV78230_PLUS)),
+	MPP_MODE(5,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "txctl",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d5",         V_MV78230_PLUS)),
+	MPP_MODE(6,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "rxd0",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d6",         V_MV78230_PLUS)),
+	MPP_MODE(7,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "rxd1",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d7",         V_MV78230_PLUS)),
+	MPP_MODE(8,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "rxd2",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d8",         V_MV78230_PLUS)),
+	MPP_MODE(9,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "rxd3",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d9",         V_MV78230_PLUS)),
+	MPP_MODE(10,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "rxctl",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d10",        V_MV78230_PLUS)),
+	MPP_MODE(11,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "rxclk",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d11",        V_MV78230_PLUS)),
+	MPP_MODE(12,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "txd4",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "ge1", "clkout",     V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d12",        V_MV78230_PLUS)),
+	MPP_MODE(13,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "txd5",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "ge1", "txd0",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d13",        V_MV78230_PLUS)),
+	MPP_MODE(14,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "txd6",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "ge1", "txd1",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d14",        V_MV78230_PLUS)),
+	MPP_MODE(15,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "txd7",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "ge1", "txd2",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d15",        V_MV78230_PLUS)),
+	MPP_MODE(16,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "txclk",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "ge1", "txd3",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d16",        V_MV78230_PLUS)),
+	MPP_MODE(17,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "col",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "ge1", "txctl",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d17",        V_MV78230_PLUS)),
+	MPP_MODE(18,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "rxerr",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "ge1", "rxd0",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "ptp", "trig",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d18",        V_MV78230_PLUS)),
+	MPP_MODE(19,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "crs",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "ge1", "rxd1",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "ptp", "evreq",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d19",        V_MV78230_PLUS)),
+	MPP_MODE(20,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "rxd4",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "ge1", "rxd2",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "ptp", "clk",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d20",        V_MV78230_PLUS)),
+	MPP_MODE(21,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "rxd5",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "ge1", "rxd3",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "mem", "bat",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d21",        V_MV78230_PLUS)),
+	MPP_MODE(22,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "rxd6",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "ge1", "rxctl",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "sata0", "prsnt",    V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d22",        V_MV78230_PLUS)),
+	MPP_MODE(23,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ge0", "rxd7",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "ge1", "rxclk",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "sata1", "prsnt",    V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "d23",        V_MV78230_PLUS)),
+	MPP_MODE(24,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "sata1", "prsnt",    V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "nf", "bootcs-re",   V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "tdm", "rst",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "hsync",      V_MV78230_PLUS)),
+	MPP_MODE(25,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "sata0", "prsnt",    V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "nf", "bootcs-we",   V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "tdm", "pclk",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "vsync",      V_MV78230_PLUS)),
+	MPP_MODE(26,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "tdm", "fsync",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "clk",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd",    V_MV78230_PLUS)),
+	MPP_MODE(27,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ptp", "trig",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "tdm", "dtx",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "e",          V_MV78230_PLUS)),
+	MPP_MODE(28,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ptp", "evreq",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "tdm", "drx",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "pwm",        V_MV78230_PLUS)),
+	MPP_MODE(29,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "ptp", "clk",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "tdm", "int0",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "ref-clk",    V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd",    V_MV78230_PLUS)),
+	MPP_MODE(30,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "sd0", "clk",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "tdm", "int1",       V_MV78230_PLUS)),
+	MPP_MODE(31,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "sd0", "cmd",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "tdm", "int2",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd",    V_MV78230_PLUS)),
+	MPP_MODE(32,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "sd0", "d0",         V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "tdm", "int3",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd",    V_MV78230_PLUS)),
+	MPP_MODE(33,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "sd0", "d1",         V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "tdm", "int4",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "mem", "bat",        V_MV78230_PLUS)),
+	MPP_MODE(34,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "sd0", "d2",         V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "sata0", "prsnt",    V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "tdm", "int5",       V_MV78230_PLUS)),
+	MPP_MODE(35,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "sd0", "d3",         V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "sata1", "prsnt",    V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "tdm", "int6",       V_MV78230_PLUS)),
+	MPP_MODE(36,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "spi", "mosi",       V_MV78230_PLUS)),
+	MPP_MODE(37,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "spi", "miso",       V_MV78230_PLUS)),
+	MPP_MODE(38,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "spi", "sck",        V_MV78230_PLUS)),
+	MPP_MODE(39,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "spi", "cs0",        V_MV78230_PLUS)),
+	MPP_MODE(40,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "spi", "cs1",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "uart2", "cts",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "vdd", "cpu1-pd",    V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "vga-hsync",  V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x5, "pcie", "clkreq0",   V_MV78230_PLUS)),
+	MPP_MODE(41,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "spi", "cs2",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "uart2", "rts",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "sata1", "prsnt",    V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "lcd", "vga-vsync",  V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x5, "pcie", "clkreq1",   V_MV78230_PLUS)),
+	MPP_MODE(42,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "uart2", "rxd",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "uart0", "cts",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "tdm", "int7",       V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "tdm-1", "timer",    V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd",    V_MV78230_PLUS)),
+	MPP_MODE(43,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "uart2", "txd",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "uart0", "rts",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "spi", "cs3",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "pcie", "rstout",    V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x5, "vdd", "cpu2-3-pd",  V_MV78460)),
+	MPP_MODE(44,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "uart2", "cts",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "uart3", "rxd",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "spi", "cs4",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "mem", "bat",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x5, "pcie", "clkreq2",   V_MV78230_PLUS)),
+	MPP_MODE(45,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "uart2", "rts",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "uart3", "txd",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "spi", "cs5",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "sata1", "prsnt",    V_MV78230_PLUS)),
+	MPP_MODE(46,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "uart3", "rts",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "uart1", "rts",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "spi", "cs6",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "sata0", "prsnt",    V_MV78230_PLUS)),
+	MPP_MODE(47,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "uart3", "cts",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "uart1", "cts",      V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x3, "spi", "cs7",        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x4, "ref", "clkout",     V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x5, "pcie", "clkreq3",   V_MV78230_PLUS)),
+	MPP_MODE(48,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "tclk", NULL,        V_MV78230_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "dev", "burst/last", V_MV78230_PLUS)),
+	MPP_MODE(49,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "we3",        V_MV78260_PLUS)),
+	MPP_MODE(50,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "we2",        V_MV78260_PLUS)),
+	MPP_MODE(51,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "ad16",       V_MV78260_PLUS)),
+	MPP_MODE(52,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "ad17",       V_MV78260_PLUS)),
+	MPP_MODE(53,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "ad18",       V_MV78260_PLUS)),
+	MPP_MODE(54,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "ad19",       V_MV78260_PLUS)),
+	MPP_MODE(55,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "ad20",       V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "vdd", "cpu0-pd",    V_MV78260_PLUS)),
+	MPP_MODE(56,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "ad21",       V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "vdd", "cpu1-pd",    V_MV78260_PLUS)),
+	MPP_MODE(57,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "ad22",       V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x2, "vdd", "cpu2-3-pd",  V_MV78460)),
+	MPP_MODE(58,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "ad23",       V_MV78260_PLUS)),
+	MPP_MODE(59,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "ad24",       V_MV78260_PLUS)),
+	MPP_MODE(60,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "ad25",       V_MV78260_PLUS)),
+	MPP_MODE(61,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "ad26",       V_MV78260_PLUS)),
+	MPP_MODE(62,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "ad27",       V_MV78260_PLUS)),
+	MPP_MODE(63,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "ad28",       V_MV78260_PLUS)),
+	MPP_MODE(64,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "ad29",       V_MV78260_PLUS)),
+	MPP_MODE(65,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "ad30",       V_MV78260_PLUS)),
+	MPP_MODE(66,
+		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+		 MPP_VAR_FUNCTION(0x1, "dev", "ad31",       V_MV78260_PLUS)),
+};
+
+static struct mvebu_pinctrl_soc_info armada_xp_pinctrl_info;
+
+static struct of_device_id armada_xp_pinctrl_of_match[] __devinitdata = {
+	{
+		.compatible = "marvell,mv78230-pinctrl",
+		.data       = (void *) V_MV78230,
+	},
+	{
+		.compatible = "marvell,mv78260-pinctrl",
+		.data       = (void *) V_MV78260,
+	},
+	{
+		.compatible = "marvell,mv78460-pinctrl",
+		.data       = (void *) V_MV78460,
+	},
+	{ },
+};
+
+static struct mvebu_mpp_ctrl mv78230_mpp_controls[] = {
+	MPP_REG_CTRL(0, 48),
+};
+
+static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = {
+	MPP_GPIO_RANGE(0,   0,  0, 32),
+	MPP_GPIO_RANGE(1,  32, 32, 17),
+};
+
+static struct mvebu_mpp_ctrl mv78260_mpp_controls[] = {
+	MPP_REG_CTRL(0, 66),
+};
+
+static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = {
+	MPP_GPIO_RANGE(0,   0,  0, 32),
+	MPP_GPIO_RANGE(1,  32, 32, 32),
+	MPP_GPIO_RANGE(2,  64, 64,  3),
+};
+
+static struct mvebu_mpp_ctrl mv78460_mpp_controls[] = {
+	MPP_REG_CTRL(0, 66),
+};
+
+static struct pinctrl_gpio_range mv78460_mpp_gpio_ranges[] = {
+	MPP_GPIO_RANGE(0,   0,  0, 32),
+	MPP_GPIO_RANGE(1,  32, 32, 32),
+	MPP_GPIO_RANGE(2,  64, 64,  3),
+};
+
+static int __devinit armada_xp_pinctrl_probe(struct platform_device *pdev)
+{
+	struct mvebu_pinctrl_soc_info *soc = &armada_xp_pinctrl_info;
+	const struct of_device_id *match =
+		of_match_device(armada_xp_pinctrl_of_match, &pdev->dev);
+
+	if (!match)
+		return -ENODEV;
+
+	soc->variant = (unsigned) match->data & 0xff;
+
+	switch (soc->variant) {
+	case V_MV78230:
+		soc->controls = mv78230_mpp_controls;
+		soc->ncontrols = ARRAY_SIZE(mv78230_mpp_controls);
+		soc->modes = armada_xp_mpp_modes;
+		/* We don't necessarily want the full list of the
+		 * armada_xp_mpp_modes, but only the first 'n' ones
+		 * that are available on this SoC */
+		soc->nmodes = mv78230_mpp_controls[0].npins;
+		soc->gpioranges = mv78230_mpp_gpio_ranges;
+		soc->ngpioranges = ARRAY_SIZE(mv78230_mpp_gpio_ranges);
+		break;
+	case V_MV78260:
+		soc->controls = mv78260_mpp_controls;
+		soc->ncontrols = ARRAY_SIZE(mv78260_mpp_controls);
+		soc->modes = armada_xp_mpp_modes;
+		/* We don't necessarily want the full list of the
+		 * armada_xp_mpp_modes, but only the first 'n' ones
+		 * that are available on this SoC */
+		soc->nmodes = mv78260_mpp_controls[0].npins;
+		soc->gpioranges = mv78260_mpp_gpio_ranges;
+		soc->ngpioranges = ARRAY_SIZE(mv78260_mpp_gpio_ranges);
+		break;
+	case V_MV78460:
+		soc->controls = mv78460_mpp_controls;
+		soc->ncontrols = ARRAY_SIZE(mv78460_mpp_controls);
+		soc->modes = armada_xp_mpp_modes;
+		/* We don't necessarily want the full list of the
+		 * armada_xp_mpp_modes, but only the first 'n' ones
+		 * that are available on this SoC */
+		soc->nmodes = mv78460_mpp_controls[0].npins;
+		soc->gpioranges = mv78460_mpp_gpio_ranges;
+		soc->ngpioranges = ARRAY_SIZE(mv78460_mpp_gpio_ranges);
+		break;
+	}
+
+	pdev->dev.platform_data = soc;
+
+	return mvebu_pinctrl_probe(pdev);
+}
+
+static int __devexit armada_xp_pinctrl_remove(struct platform_device *pdev)
+{
+	return mvebu_pinctrl_remove(pdev);
+}
+
+static struct platform_driver armada_xp_pinctrl_driver = {
+	.driver = {
+		.name = "armada-xp-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(armada_xp_pinctrl_of_match),
+	},
+	.probe = armada_xp_pinctrl_probe,
+	.remove = __devexit_p(armada_xp_pinctrl_remove),
+};
+
+module_platform_driver(armada_xp_pinctrl_driver);
+
+MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
+MODULE_DESCRIPTION("Marvell Armada XP pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/mvebu/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c
new file mode 100644
index 0000000..40c9c3e
--- /dev/null
+++ b/drivers/pinctrl/mvebu/pinctrl-dove.c
@@ -0,0 +1,628 @@
+/*
+ * Marvell Dove pinctrl driver based on mvebu pinctrl core
+ *
+ * Author: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-mvebu.h"
+
+#define DOVE_SB_REGS_VIRT_BASE		IOMEM(0xfde00000)
+#define DOVE_MPP_VIRT_BASE		(DOVE_SB_REGS_VIRT_BASE + 0xd0200)
+#define DOVE_PMU_MPP_GENERAL_CTRL	(DOVE_MPP_VIRT_BASE + 0x10)
+#define  DOVE_AU0_AC97_SEL		BIT(16)
+#define DOVE_GLOBAL_CONFIG_1		(DOVE_SB_REGS_VIRT_BASE + 0xe802C)
+#define  DOVE_TWSI_ENABLE_OPTION1	BIT(7)
+#define DOVE_GLOBAL_CONFIG_2		(DOVE_SB_REGS_VIRT_BASE + 0xe8030)
+#define  DOVE_TWSI_ENABLE_OPTION2	BIT(20)
+#define  DOVE_TWSI_ENABLE_OPTION3	BIT(21)
+#define  DOVE_TWSI_OPTION3_GPIO		BIT(22)
+#define DOVE_SSP_CTRL_STATUS_1		(DOVE_SB_REGS_VIRT_BASE + 0xe8034)
+#define  DOVE_SSP_ON_AU1		BIT(0)
+#define DOVE_MPP_GENERAL_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0xe803c)
+#define  DOVE_AU1_SPDIFO_GPIO_EN	BIT(1)
+#define  DOVE_NAND_GPIO_EN		BIT(0)
+#define DOVE_GPIO_LO_VIRT_BASE		(DOVE_SB_REGS_VIRT_BASE + 0xd0400)
+#define DOVE_MPP_CTRL4_VIRT_BASE	(DOVE_GPIO_LO_VIRT_BASE + 0x40)
+#define  DOVE_SPI_GPIO_SEL		BIT(5)
+#define  DOVE_UART1_GPIO_SEL		BIT(4)
+#define  DOVE_AU1_GPIO_SEL		BIT(3)
+#define  DOVE_CAM_GPIO_SEL		BIT(2)
+#define  DOVE_SD1_GPIO_SEL		BIT(1)
+#define  DOVE_SD0_GPIO_SEL		BIT(0)
+
+#define MPPS_PER_REG	8
+#define MPP_BITS	4
+#define MPP_MASK	0xf
+
+#define CONFIG_PMU	BIT(4)
+
+static int dove_pmu_mpp_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+				 unsigned long *config)
+{
+	unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS;
+	unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS;
+	unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+	unsigned long mpp = readl(DOVE_MPP_VIRT_BASE + off);
+
+	if (pmu & (1 << ctrl->pid))
+		*config = CONFIG_PMU;
+	else
+		*config = (mpp >> shift) & MPP_MASK;
+	return 0;
+}
+
+static int dove_pmu_mpp_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+				 unsigned long config)
+{
+	unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS;
+	unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS;
+	unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+	unsigned long mpp = readl(DOVE_MPP_VIRT_BASE + off);
+
+	if (config == CONFIG_PMU)
+		writel(pmu | (1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
+	else {
+		writel(pmu & ~(1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
+		mpp &= ~(MPP_MASK << shift);
+		mpp |= config << shift;
+		writel(mpp, DOVE_MPP_VIRT_BASE + off);
+	}
+	return 0;
+}
+
+static int dove_mpp4_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+			      unsigned long *config)
+{
+	unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
+	unsigned long mask;
+
+	switch (ctrl->pid) {
+	case 24: /* mpp_camera */
+		mask = DOVE_CAM_GPIO_SEL;
+		break;
+	case 40: /* mpp_sdio0 */
+		mask = DOVE_SD0_GPIO_SEL;
+		break;
+	case 46: /* mpp_sdio1 */
+		mask = DOVE_SD1_GPIO_SEL;
+		break;
+	case 58: /* mpp_spi0 */
+		mask = DOVE_SPI_GPIO_SEL;
+		break;
+	case 62: /* mpp_uart1 */
+		mask = DOVE_UART1_GPIO_SEL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	*config = ((mpp4 & mask) != 0);
+
+	return 0;
+}
+
+static int dove_mpp4_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+			      unsigned long config)
+{
+	unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
+	unsigned long mask;
+
+	switch (ctrl->pid) {
+	case 24: /* mpp_camera */
+		mask = DOVE_CAM_GPIO_SEL;
+		break;
+	case 40: /* mpp_sdio0 */
+		mask = DOVE_SD0_GPIO_SEL;
+		break;
+	case 46: /* mpp_sdio1 */
+		mask = DOVE_SD1_GPIO_SEL;
+		break;
+	case 58: /* mpp_spi0 */
+		mask = DOVE_SPI_GPIO_SEL;
+		break;
+	case 62: /* mpp_uart1 */
+		mask = DOVE_UART1_GPIO_SEL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mpp4 &= ~mask;
+	if (config)
+		mpp4 |= mask;
+
+	writel(mpp4, DOVE_MPP_CTRL4_VIRT_BASE);
+
+	return 0;
+}
+
+static int dove_nand_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+			      unsigned long *config)
+{
+	unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+
+	*config = ((gmpp & DOVE_NAND_GPIO_EN) != 0);
+
+	return 0;
+}
+
+static int dove_nand_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+			      unsigned long config)
+{
+	unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+
+	gmpp &= ~DOVE_NAND_GPIO_EN;
+	if (config)
+		gmpp |= DOVE_NAND_GPIO_EN;
+
+	writel(gmpp, DOVE_MPP_GENERAL_VIRT_BASE);
+
+	return 0;
+}
+
+static int dove_audio0_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+				unsigned long *config)
+{
+	unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+
+	*config = ((pmu & DOVE_AU0_AC97_SEL) != 0);
+
+	return 0;
+}
+
+static int dove_audio0_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+				unsigned long config)
+{
+	unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+
+	pmu &= ~DOVE_AU0_AC97_SEL;
+	if (config)
+		pmu |= DOVE_AU0_AC97_SEL;
+	writel(pmu, DOVE_PMU_MPP_GENERAL_CTRL);
+
+	return 0;
+}
+
+static int dove_audio1_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+				unsigned long *config)
+{
+	unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
+	unsigned long sspc1 = readl(DOVE_SSP_CTRL_STATUS_1);
+	unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+	unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+
+	*config = 0;
+	if (mpp4 & DOVE_AU1_GPIO_SEL)
+		*config |= BIT(3);
+	if (sspc1 & DOVE_SSP_ON_AU1)
+		*config |= BIT(2);
+	if (gmpp & DOVE_AU1_SPDIFO_GPIO_EN)
+		*config |= BIT(1);
+	if (gcfg2 & DOVE_TWSI_OPTION3_GPIO)
+		*config |= BIT(0);
+
+	/* SSP/TWSI only if I2S1 not set*/
+	if ((*config & BIT(3)) == 0)
+		*config &= ~(BIT(2) | BIT(0));
+	/* TWSI only if SPDIFO not set*/
+	if ((*config & BIT(1)) == 0)
+		*config &= ~BIT(0);
+	return 0;
+}
+
+static int dove_audio1_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+				unsigned long config)
+{
+	unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
+	unsigned long sspc1 = readl(DOVE_SSP_CTRL_STATUS_1);
+	unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+	unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+
+	/*
+	 * clear all audio1 related bits before configure
+	 */
+	gcfg2 &= ~DOVE_TWSI_OPTION3_GPIO;
+	gmpp &= ~DOVE_AU1_SPDIFO_GPIO_EN;
+	sspc1 &= ~DOVE_SSP_ON_AU1;
+	mpp4 &= ~DOVE_AU1_GPIO_SEL;
+
+	if (config & BIT(0))
+		gcfg2 |= DOVE_TWSI_OPTION3_GPIO;
+	if (config & BIT(1))
+		gmpp |= DOVE_AU1_SPDIFO_GPIO_EN;
+	if (config & BIT(2))
+		sspc1 |= DOVE_SSP_ON_AU1;
+	if (config & BIT(3))
+		mpp4 |= DOVE_AU1_GPIO_SEL;
+
+	writel(mpp4, DOVE_MPP_CTRL4_VIRT_BASE);
+	writel(sspc1, DOVE_SSP_CTRL_STATUS_1);
+	writel(gmpp, DOVE_MPP_GENERAL_VIRT_BASE);
+	writel(gcfg2, DOVE_GLOBAL_CONFIG_2);
+
+	return 0;
+}
+
+/* mpp[52:57] gpio pins depend heavily on current config;
+ * gpio_req does not try to mux in gpio capabilities to not
+ * break other functions. If you require all mpps as gpio
+ * enforce gpio setting by pinctrl mapping.
+ */
+static int dove_audio1_ctrl_gpio_req(struct mvebu_mpp_ctrl *ctrl, u8 pid)
+{
+	unsigned long config;
+
+	dove_audio1_ctrl_get(ctrl, &config);
+
+	switch (config) {
+	case 0x02: /* i2s1 : gpio[56:57] */
+	case 0x0e: /* ssp  : gpio[56:57] */
+		if (pid >= 56)
+			return 0;
+		return -ENOTSUPP;
+	case 0x08: /* spdifo : gpio[52:55] */
+	case 0x0b: /* twsi   : gpio[52:55] */
+		if (pid <= 55)
+			return 0;
+		return -ENOTSUPP;
+	case 0x0a: /* all gpio */
+		return 0;
+	/* 0x00 : i2s1/spdifo : no gpio */
+	/* 0x0c : ssp/spdifo  : no gpio */
+	/* 0x0f : ssp/twsi    : no gpio */
+	}
+	return -ENOTSUPP;
+}
+
+/* mpp[52:57] has gpio pins capable of in and out */
+static int dove_audio1_ctrl_gpio_dir(struct mvebu_mpp_ctrl *ctrl, u8 pid,
+				bool input)
+{
+	if (pid < 52 || pid > 57)
+		return -ENOTSUPP;
+	return 0;
+}
+
+static int dove_twsi_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+			      unsigned long *config)
+{
+	unsigned long gcfg1 = readl(DOVE_GLOBAL_CONFIG_1);
+	unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+
+	*config = 0;
+	if (gcfg1 & DOVE_TWSI_ENABLE_OPTION1)
+		*config = 1;
+	else if (gcfg2 & DOVE_TWSI_ENABLE_OPTION2)
+		*config = 2;
+	else if (gcfg2 & DOVE_TWSI_ENABLE_OPTION3)
+		*config = 3;
+
+	return 0;
+}
+
+static int dove_twsi_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+				unsigned long config)
+{
+	unsigned long gcfg1 = readl(DOVE_GLOBAL_CONFIG_1);
+	unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+
+	gcfg1 &= ~DOVE_TWSI_ENABLE_OPTION1;
+	gcfg2 &= ~(DOVE_TWSI_ENABLE_OPTION2 | DOVE_TWSI_ENABLE_OPTION2);
+
+	switch (config) {
+	case 1:
+		gcfg1 |= DOVE_TWSI_ENABLE_OPTION1;
+		break;
+	case 2:
+		gcfg2 |= DOVE_TWSI_ENABLE_OPTION2;
+		break;
+	case 3:
+		gcfg2 |= DOVE_TWSI_ENABLE_OPTION3;
+		break;
+	}
+
+	writel(gcfg1, DOVE_GLOBAL_CONFIG_1);
+	writel(gcfg2, DOVE_GLOBAL_CONFIG_2);
+
+	return 0;
+}
+
+static struct mvebu_mpp_ctrl dove_mpp_controls[] = {
+	MPP_FUNC_CTRL(0, 0, "mpp0", dove_pmu_mpp_ctrl),
+	MPP_FUNC_CTRL(1, 1, "mpp1", dove_pmu_mpp_ctrl),
+	MPP_FUNC_CTRL(2, 2, "mpp2", dove_pmu_mpp_ctrl),
+	MPP_FUNC_CTRL(3, 3, "mpp3", dove_pmu_mpp_ctrl),
+	MPP_FUNC_CTRL(4, 4, "mpp4", dove_pmu_mpp_ctrl),
+	MPP_FUNC_CTRL(5, 5, "mpp5", dove_pmu_mpp_ctrl),
+	MPP_FUNC_CTRL(6, 6, "mpp6", dove_pmu_mpp_ctrl),
+	MPP_FUNC_CTRL(7, 7, "mpp7", dove_pmu_mpp_ctrl),
+	MPP_FUNC_CTRL(8, 8, "mpp8", dove_pmu_mpp_ctrl),
+	MPP_FUNC_CTRL(9, 9, "mpp9", dove_pmu_mpp_ctrl),
+	MPP_FUNC_CTRL(10, 10, "mpp10", dove_pmu_mpp_ctrl),
+	MPP_FUNC_CTRL(11, 11, "mpp11", dove_pmu_mpp_ctrl),
+	MPP_FUNC_CTRL(12, 12, "mpp12", dove_pmu_mpp_ctrl),
+	MPP_FUNC_CTRL(13, 13, "mpp13", dove_pmu_mpp_ctrl),
+	MPP_FUNC_CTRL(14, 14, "mpp14", dove_pmu_mpp_ctrl),
+	MPP_FUNC_CTRL(15, 15, "mpp15", dove_pmu_mpp_ctrl),
+	MPP_REG_CTRL(16, 23),
+	MPP_FUNC_CTRL(24, 39, "mpp_camera", dove_mpp4_ctrl),
+	MPP_FUNC_CTRL(40, 45, "mpp_sdio0", dove_mpp4_ctrl),
+	MPP_FUNC_CTRL(46, 51, "mpp_sdio1", dove_mpp4_ctrl),
+	MPP_FUNC_GPIO_CTRL(52, 57, "mpp_audio1", dove_audio1_ctrl),
+	MPP_FUNC_CTRL(58, 61, "mpp_spi0", dove_mpp4_ctrl),
+	MPP_FUNC_CTRL(62, 63, "mpp_uart1", dove_mpp4_ctrl),
+	MPP_FUNC_CTRL(64, 71, "mpp_nand", dove_nand_ctrl),
+	MPP_FUNC_CTRL(72, 72, "audio0", dove_audio0_ctrl),
+	MPP_FUNC_CTRL(73, 73, "twsi", dove_twsi_ctrl),
+};
+
+static struct mvebu_mpp_mode dove_mpp_modes[] = {
+	MPP_MODE(0,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x02, "uart2", "rts"),
+		MPP_FUNCTION(0x03, "sdio0", "cd"),
+		MPP_FUNCTION(0x0f, "lcd0", "pwm"),
+		MPP_FUNCTION(0x10, "pmu", NULL)),
+	MPP_MODE(1,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x02, "uart2", "cts"),
+		MPP_FUNCTION(0x03, "sdio0", "wp"),
+		MPP_FUNCTION(0x0f, "lcd1", "pwm"),
+		MPP_FUNCTION(0x10, "pmu", NULL)),
+	MPP_MODE(2,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x01, "sata", "prsnt"),
+		MPP_FUNCTION(0x02, "uart2", "txd"),
+		MPP_FUNCTION(0x03, "sdio0", "buspwr"),
+		MPP_FUNCTION(0x04, "uart1", "rts"),
+		MPP_FUNCTION(0x10, "pmu", NULL)),
+	MPP_MODE(3,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x01, "sata", "act"),
+		MPP_FUNCTION(0x02, "uart2", "rxd"),
+		MPP_FUNCTION(0x03, "sdio0", "ledctrl"),
+		MPP_FUNCTION(0x04, "uart1", "cts"),
+		MPP_FUNCTION(0x0f, "lcd-spi", "cs1"),
+		MPP_FUNCTION(0x10, "pmu", NULL)),
+	MPP_MODE(4,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x02, "uart3", "rts"),
+		MPP_FUNCTION(0x03, "sdio1", "cd"),
+		MPP_FUNCTION(0x04, "spi1", "miso"),
+		MPP_FUNCTION(0x10, "pmu", NULL)),
+	MPP_MODE(5,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x02, "uart3", "cts"),
+		MPP_FUNCTION(0x03, "sdio1", "wp"),
+		MPP_FUNCTION(0x04, "spi1", "cs"),
+		MPP_FUNCTION(0x10, "pmu", NULL)),
+	MPP_MODE(6,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x02, "uart3", "txd"),
+		MPP_FUNCTION(0x03, "sdio1", "buspwr"),
+		MPP_FUNCTION(0x04, "spi1", "mosi"),
+		MPP_FUNCTION(0x10, "pmu", NULL)),
+	MPP_MODE(7,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x02, "uart3", "rxd"),
+		MPP_FUNCTION(0x03, "sdio1", "ledctrl"),
+		MPP_FUNCTION(0x04, "spi1", "sck"),
+		MPP_FUNCTION(0x10, "pmu", NULL)),
+	MPP_MODE(8,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x01, "watchdog", "rstout"),
+		MPP_FUNCTION(0x10, "pmu", NULL)),
+	MPP_MODE(9,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x05, "pex1", "clkreq"),
+		MPP_FUNCTION(0x10, "pmu", NULL)),
+	MPP_MODE(10,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x05, "ssp", "sclk"),
+		MPP_FUNCTION(0x10, "pmu", NULL)),
+	MPP_MODE(11,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x01, "sata", "prsnt"),
+		MPP_FUNCTION(0x02, "sata-1", "act"),
+		MPP_FUNCTION(0x03, "sdio0", "ledctrl"),
+		MPP_FUNCTION(0x04, "sdio1", "ledctrl"),
+		MPP_FUNCTION(0x05, "pex0", "clkreq"),
+		MPP_FUNCTION(0x10, "pmu", NULL)),
+	MPP_MODE(12,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x01, "sata", "act"),
+		MPP_FUNCTION(0x02, "uart2", "rts"),
+		MPP_FUNCTION(0x03, "audio0", "extclk"),
+		MPP_FUNCTION(0x04, "sdio1", "cd"),
+		MPP_FUNCTION(0x10, "pmu", NULL)),
+	MPP_MODE(13,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x02, "uart2", "cts"),
+		MPP_FUNCTION(0x03, "audio1", "extclk"),
+		MPP_FUNCTION(0x04, "sdio1", "wp"),
+		MPP_FUNCTION(0x05, "ssp", "extclk"),
+		MPP_FUNCTION(0x10, "pmu", NULL)),
+	MPP_MODE(14,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x02, "uart2", "txd"),
+		MPP_FUNCTION(0x04, "sdio1", "buspwr"),
+		MPP_FUNCTION(0x05, "ssp", "rxd"),
+		MPP_FUNCTION(0x10, "pmu", NULL)),
+	MPP_MODE(15,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x02, "uart2", "rxd"),
+		MPP_FUNCTION(0x04, "sdio1", "ledctrl"),
+		MPP_FUNCTION(0x05, "ssp", "sfrm"),
+		MPP_FUNCTION(0x10, "pmu", NULL)),
+	MPP_MODE(16,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x02, "uart3", "rts"),
+		MPP_FUNCTION(0x03, "sdio0", "cd"),
+		MPP_FUNCTION(0x04, "lcd-spi", "cs1"),
+		MPP_FUNCTION(0x05, "ac97", "sdi1")),
+	MPP_MODE(17,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x01, "ac97-1", "sysclko"),
+		MPP_FUNCTION(0x02, "uart3", "cts"),
+		MPP_FUNCTION(0x03, "sdio0", "wp"),
+		MPP_FUNCTION(0x04, "twsi", "sda"),
+		MPP_FUNCTION(0x05, "ac97", "sdi2")),
+	MPP_MODE(18,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x02, "uart3", "txd"),
+		MPP_FUNCTION(0x03, "sdio0", "buspwr"),
+		MPP_FUNCTION(0x04, "lcd0", "pwm"),
+		MPP_FUNCTION(0x05, "ac97", "sdi3")),
+	MPP_MODE(19,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x02, "uart3", "rxd"),
+		MPP_FUNCTION(0x03, "sdio0", "ledctrl"),
+		MPP_FUNCTION(0x04, "twsi", "sck")),
+	MPP_MODE(20,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x01, "ac97", "sysclko"),
+		MPP_FUNCTION(0x02, "lcd-spi", "miso"),
+		MPP_FUNCTION(0x03, "sdio1", "cd"),
+		MPP_FUNCTION(0x05, "sdio0", "cd"),
+		MPP_FUNCTION(0x06, "spi1", "miso")),
+	MPP_MODE(21,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x01, "uart1", "rts"),
+		MPP_FUNCTION(0x02, "lcd-spi", "cs0"),
+		MPP_FUNCTION(0x03, "sdio1", "wp"),
+		MPP_FUNCTION(0x04, "ssp", "sfrm"),
+		MPP_FUNCTION(0x05, "sdio0", "wp"),
+		MPP_FUNCTION(0x06, "spi1", "cs")),
+	MPP_MODE(22,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x01, "uart1", "cts"),
+		MPP_FUNCTION(0x02, "lcd-spi", "mosi"),
+		MPP_FUNCTION(0x03, "sdio1", "buspwr"),
+		MPP_FUNCTION(0x04, "ssp", "txd"),
+		MPP_FUNCTION(0x05, "sdio0", "buspwr"),
+		MPP_FUNCTION(0x06, "spi1", "mosi")),
+	MPP_MODE(23,
+		MPP_FUNCTION(0x00, "gpio", NULL),
+		MPP_FUNCTION(0x02, "lcd-spi", "sck"),
+		MPP_FUNCTION(0x03, "sdio1", "ledctrl"),
+		MPP_FUNCTION(0x04, "ssp", "sclk"),
+		MPP_FUNCTION(0x05, "sdio0", "ledctrl"),
+		MPP_FUNCTION(0x06, "spi1", "sck")),
+	MPP_MODE(24,
+		MPP_FUNCTION(0x00, "camera", NULL),
+		MPP_FUNCTION(0x01, "gpio", NULL)),
+	MPP_MODE(40,
+		MPP_FUNCTION(0x00, "sdio0", NULL),
+		MPP_FUNCTION(0x01, "gpio", NULL)),
+	MPP_MODE(46,
+		MPP_FUNCTION(0x00, "sdio1", NULL),
+		MPP_FUNCTION(0x01, "gpio", NULL)),
+	MPP_MODE(52,
+		MPP_FUNCTION(0x00, "i2s1/spdifo", NULL),
+		MPP_FUNCTION(0x02, "i2s1", NULL),
+		MPP_FUNCTION(0x08, "spdifo", NULL),
+		MPP_FUNCTION(0x0a, "gpio", NULL),
+		MPP_FUNCTION(0x0b, "twsi", NULL),
+		MPP_FUNCTION(0x0c, "ssp/spdifo", NULL),
+		MPP_FUNCTION(0x0e, "ssp", NULL),
+		MPP_FUNCTION(0x0f, "ssp/twsi", NULL)),
+	MPP_MODE(58,
+		MPP_FUNCTION(0x00, "spi0", NULL),
+		MPP_FUNCTION(0x01, "gpio", NULL)),
+	MPP_MODE(62,
+		MPP_FUNCTION(0x00, "uart1", NULL),
+		MPP_FUNCTION(0x01, "gpio", NULL)),
+	MPP_MODE(64,
+		MPP_FUNCTION(0x00, "nand", NULL),
+		MPP_FUNCTION(0x01, "gpo", NULL)),
+	MPP_MODE(72,
+		MPP_FUNCTION(0x00, "i2s", NULL),
+		MPP_FUNCTION(0x01, "ac97", NULL)),
+	MPP_MODE(73,
+		MPP_FUNCTION(0x00, "twsi-none", NULL),
+		MPP_FUNCTION(0x01, "twsi-opt1", NULL),
+		MPP_FUNCTION(0x02, "twsi-opt2", NULL),
+		MPP_FUNCTION(0x03, "twsi-opt3", NULL)),
+};
+
+static struct pinctrl_gpio_range dove_mpp_gpio_ranges[] = {
+	MPP_GPIO_RANGE(0,  0,  0, 32),
+	MPP_GPIO_RANGE(1, 32, 32, 32),
+	MPP_GPIO_RANGE(2, 64, 64,  8),
+};
+
+static struct mvebu_pinctrl_soc_info dove_pinctrl_info = {
+	.controls = dove_mpp_controls,
+	.ncontrols = ARRAY_SIZE(dove_mpp_controls),
+	.modes = dove_mpp_modes,
+	.nmodes = ARRAY_SIZE(dove_mpp_modes),
+	.gpioranges = dove_mpp_gpio_ranges,
+	.ngpioranges = ARRAY_SIZE(dove_mpp_gpio_ranges),
+	.variant = 0,
+};
+
+static struct clk *clk;
+
+static struct of_device_id dove_pinctrl_of_match[] __devinitdata = {
+	{ .compatible = "marvell,dove-pinctrl", .data = &dove_pinctrl_info },
+	{ }
+};
+
+static int __devinit dove_pinctrl_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match =
+		of_match_device(dove_pinctrl_of_match, &pdev->dev);
+	pdev->dev.platform_data = match->data;
+
+	/*
+	 * General MPP Configuration Register is part of pdma registers.
+	 * grab clk to make sure it is ticking.
+	 */
+	clk = devm_clk_get(&pdev->dev, NULL);
+	if (!IS_ERR(clk))
+		clk_prepare_enable(clk);
+
+	return mvebu_pinctrl_probe(pdev);
+}
+
+static int __devexit dove_pinctrl_remove(struct platform_device *pdev)
+{
+	int ret;
+
+	ret = mvebu_pinctrl_remove(pdev);
+	if (!IS_ERR(clk))
+		clk_disable_unprepare(clk);
+	return ret;
+}
+
+static struct platform_driver dove_pinctrl_driver = {
+	.driver = {
+		.name = "dove-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(dove_pinctrl_of_match),
+	},
+	.probe = dove_pinctrl_probe,
+	.remove = __devexit_p(dove_pinctrl_remove),
+};
+
+module_platform_driver(dove_pinctrl_driver);
+
+MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
+MODULE_DESCRIPTION("Marvell Dove pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
new file mode 100644
index 0000000..fa6ce31
--- /dev/null
+++ b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
@@ -0,0 +1,484 @@
+/*
+ * Marvell Kirkwood pinctrl driver based on mvebu pinctrl core
+ *
+ * Author: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-mvebu.h"
+
+#define V(f6180, f6190, f6192, f6281, f6282, dx4122)	\
+	((f6180 << 0) | (f6190 << 1) | (f6192 << 2) |	\
+	 (f6281 << 3) | (f6282 << 4) | (dx4122 << 5))
+
+enum kirkwood_variant {
+	VARIANT_MV88F6180	= V(1, 0, 0, 0, 0, 0),
+	VARIANT_MV88F6190	= V(0, 1, 0, 0, 0, 0),
+	VARIANT_MV88F6192	= V(0, 0, 1, 0, 0, 0),
+	VARIANT_MV88F6281	= V(0, 0, 0, 1, 0, 0),
+	VARIANT_MV88F6282	= V(0, 0, 0, 0, 1, 0),
+	VARIANT_MV98DX4122	= V(0, 0, 0, 0, 0, 1),
+};
+
+static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
+	MPP_MODE(0,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "nand", "io2",     V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "spi", "cs",       V(1, 1, 1, 1, 1, 1))),
+	MPP_MODE(1,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "nand", "io3",     V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "spi", "mosi",     V(1, 1, 1, 1, 1, 1))),
+	MPP_MODE(2,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "nand", "io4",     V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "spi", "sck",      V(1, 1, 1, 1, 1, 1))),
+	MPP_MODE(3,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "nand", "io5",     V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "spi", "miso",     V(1, 1, 1, 1, 1, 1))),
+	MPP_MODE(4,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "nand", "io6",     V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "uart0", "rxd",    V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "hsync",    V(0, 0, 0, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0xd, "ptp", "clk",      V(1, 1, 1, 1, 0, 0))),
+	MPP_MODE(5,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "nand", "io7",     V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "uart0", "txd",    V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "ptp", "trig",     V(1, 1, 1, 1, 0, 0)),
+		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "vsync",    V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(6,
+		MPP_VAR_FUNCTION(0x0, "sysrst", "out",   V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "spi", "mosi",     V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "ptp", "trig",     V(1, 1, 1, 1, 0, 0))),
+	MPP_MODE(7,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "pex", "rsto",     V(1, 1, 1, 1, 0, 1)),
+		MPP_VAR_FUNCTION(0x2, "spi", "cs",       V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ptp", "trig",     V(1, 1, 1, 1, 0, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "pwm",      V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(8,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "twsi0", "sda",    V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "uart0", "rts",    V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "uart1", "rts",    V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "mii-1", "rxerr",  V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x5, "sata1", "prsnt",  V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xc, "ptp", "clk",      V(1, 1, 1, 1, 0, 0)),
+		MPP_VAR_FUNCTION(0xd, "mii", "col",      V(1, 1, 1, 1, 1, 0))),
+	MPP_MODE(9,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "twsi0", "sck",    V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "uart0", "cts",    V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "uart1", "cts",    V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x5, "sata0", "prsnt",  V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xc, "ptp", "evreq",    V(1, 1, 1, 1, 0, 0)),
+		MPP_VAR_FUNCTION(0xd, "mii", "crs",      V(1, 1, 1, 1, 1, 0))),
+	MPP_MODE(10,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "spi", "sck",      V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0X3, "uart0", "txd",    V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xc, "ptp", "trig",     V(1, 1, 1, 1, 0, 0))),
+	MPP_MODE(11,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "spi", "miso",     V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "uart0", "rxd",    V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "ptp-1", "evreq",  V(1, 1, 1, 1, 0, 0)),
+		MPP_VAR_FUNCTION(0xc, "ptp-2", "trig",   V(1, 1, 1, 1, 0, 0)),
+		MPP_VAR_FUNCTION(0xd, "ptp", "clk",      V(1, 1, 1, 1, 0, 0)),
+		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1, 0))),
+	MPP_MODE(12,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 0, 0)),
+		MPP_VAR_FUNCTION(0x1, "sdio", "clk",     V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xa, "audio", "spdifo", V(0, 0, 0, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "spi", "mosi",     V(0, 0, 0, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0xd, "twsi1", "sda",    V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(13,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "sdio", "cmd",     V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "uart1", "txd",    V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xa, "audio", "rmclk",  V(0, 0, 0, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "pwm",      V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(14,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "sdio", "d0",      V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "uart1", "rxd",    V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "sata1", "prsnt",  V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xa, "audio", "spdifi", V(0, 0, 0, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "audio-1", "sdi",  V(0, 0, 0, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0xd, "mii", "col",      V(1, 1, 1, 1, 1, 0))),
+	MPP_MODE(15,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "sdio", "d1",      V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "uart0", "rts",    V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "uart1", "txd",    V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "sata0", "act",    V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "spi", "cs",       V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(16,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "sdio", "d2",      V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "uart0", "cts",    V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "uart1", "rxd",    V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "sata1", "act",    V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "extclk",   V(0, 0, 0, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0xd, "mii", "crs",      V(1, 1, 1, 1, 1, 0))),
+	MPP_MODE(17,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "sdio", "d3",      V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "sata0", "prsnt",  V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xa, "sata1", "act",    V(0, 0, 0, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0xd, "twsi1", "sck",    V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(18,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "nand", "io0",     V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "pex", "clkreq",   V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(19,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "nand", "io1",     V(1, 1, 1, 1, 1, 1))),
+	MPP_MODE(20,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp0",       V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql",    V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "txd0",     V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d0",       V(0, 0, 0, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0xc, "mii", "rxerr",    V(1, 0, 0, 0, 0, 0))),
+	MPP_MODE(21,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp1",       V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql",    V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "txd1",     V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(1, 0, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d1",       V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(22,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp2",       V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql",    V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "txd2",     V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(1, 0, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "rmclk",  V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x5, "sata1", "prsnt",  V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d2",       V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(23,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp3",       V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql",    V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "txd3",     V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "rmclk",  V(1, 0, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "bclk",   V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x5, "sata0", "prsnt",  V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d3",       V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(24,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp4",       V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0",  V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "rxd0",     V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "bclk",   V(1, 0, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "sdo",    V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d4",       V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(25,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp5",       V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck",  V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "rxd1",     V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "sdo",    V(1, 0, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "lrclk",  V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d5",       V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(26,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp6",       V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "rxd2",     V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "lrclk",  V(1, 0, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "mclk",   V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d6",       V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(27,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp7",       V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "rxd3",     V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "mclk",   V(1, 0, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "sdi",    V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d7",       V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(28,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp8",       V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "int",      V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "col",      V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "sdi",    V(1, 0, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d8",       V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(29,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp9",       V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "rst",      V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "txclk",    V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(1, 0, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d9",       V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(30,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp10",      V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "pclk",     V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "rxctl",    V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d10",      V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(31,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp11",      V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "fs",       V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "rxclk",    V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d11",      V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(32,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp12",      V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "drx",      V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "txclko",   V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d12",      V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(33,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "dtx",      V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "txctl",    V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d13",      V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(34,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1",  V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "txen",     V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d14",      V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(35,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql",    V(0, 0, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "rxerr",    V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d15",      V(0, 0, 0, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0xc, "mii", "rxerr",    V(0, 1, 1, 1, 1, 0))),
+	MPP_MODE(36,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp0",       V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1",  V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "twsi1", "sda",    V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(37,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp1",       V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql",    V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "twsi1", "sck",    V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(38,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp2",       V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql",    V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "rmclk",  V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d18",      V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(39,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp3",       V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0",  V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "bclk",   V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d19",      V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(40,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp4",       V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck",  V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "sdo",    V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d20",      V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(41,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp5",       V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "lrclk",  V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d21",      V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(42,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp6",       V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "mclk",   V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d22",      V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(43,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp7",       V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "int",      V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "sdi",    V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d23",      V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(44,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp8",       V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "rst",      V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "clk",      V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(45,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp9",       V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "pclk",     V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "e",        V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(46,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp10",      V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "fs",       V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "hsync",    V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(47,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp11",      V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "drx",      V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "vsync",    V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(48,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp12",      V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "dtx",      V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d16",      V(0, 0, 0, 0, 1, 0))),
+	MPP_MODE(49,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 0, 1)),
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(0, 0, 0, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp9",       V(0, 0, 0, 1, 0, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql",    V(0, 0, 0, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x5, "ptp", "clk",      V(0, 0, 0, 1, 0, 0)),
+		MPP_VAR_FUNCTION(0xa, "pex", "clkreq",   V(0, 0, 0, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d17",      V(0, 0, 0, 0, 1, 0))),
+};
+
+static struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
+	MPP_REG_CTRL(0, 29),
+};
+
+static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
+	MPP_GPIO_RANGE(0, 0, 0, 30),
+};
+
+static struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = {
+	MPP_REG_CTRL(0, 35),
+};
+
+static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
+	MPP_GPIO_RANGE(0,  0,  0, 32),
+	MPP_GPIO_RANGE(1, 32, 32,  4),
+};
+
+static struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = {
+	MPP_REG_CTRL(0, 49),
+};
+
+static struct pinctrl_gpio_range mv88f628x_gpio_ranges[] = {
+	MPP_GPIO_RANGE(0,  0,  0, 32),
+	MPP_GPIO_RANGE(1, 32, 32, 18),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6180_info = {
+	.variant = VARIANT_MV88F6180,
+	.controls = mv88f6180_mpp_controls,
+	.ncontrols = ARRAY_SIZE(mv88f6180_mpp_controls),
+	.modes = mv88f6xxx_mpp_modes,
+	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+	.gpioranges = mv88f6180_gpio_ranges,
+	.ngpioranges = ARRAY_SIZE(mv88f6180_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6190_info = {
+	.variant = VARIANT_MV88F6190,
+	.controls = mv88f619x_mpp_controls,
+	.ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls),
+	.modes = mv88f6xxx_mpp_modes,
+	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+	.gpioranges = mv88f619x_gpio_ranges,
+	.ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6192_info = {
+	.variant = VARIANT_MV88F6192,
+	.controls = mv88f619x_mpp_controls,
+	.ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls),
+	.modes = mv88f6xxx_mpp_modes,
+	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+	.gpioranges = mv88f619x_gpio_ranges,
+	.ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6281_info = {
+	.variant = VARIANT_MV88F6281,
+	.controls = mv88f628x_mpp_controls,
+	.ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
+	.modes = mv88f6xxx_mpp_modes,
+	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+	.gpioranges = mv88f628x_gpio_ranges,
+	.ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6282_info = {
+	.variant = VARIANT_MV88F6282,
+	.controls = mv88f628x_mpp_controls,
+	.ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
+	.modes = mv88f6xxx_mpp_modes,
+	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+	.gpioranges = mv88f628x_gpio_ranges,
+	.ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv98dx4122_info = {
+	.variant = VARIANT_MV98DX4122,
+	.controls = mv88f628x_mpp_controls,
+	.ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
+	.modes = mv88f6xxx_mpp_modes,
+	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+	.gpioranges = mv88f628x_gpio_ranges,
+	.ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
+};
+
+static struct of_device_id kirkwood_pinctrl_of_match[] __devinitdata = {
+	{ .compatible = "marvell,88f6180-pinctrl", .data = &mv88f6180_info },
+	{ .compatible = "marvell,88f6190-pinctrl", .data = &mv88f6190_info },
+	{ .compatible = "marvell,88f6192-pinctrl", .data = &mv88f6192_info },
+	{ .compatible = "marvell,88f6281-pinctrl", .data = &mv88f6281_info },
+	{ .compatible = "marvell,88f6282-pinctrl", .data = &mv88f6282_info },
+	{ .compatible = "marvell,98dx4122-pinctrl", .data = &mv98dx4122_info },
+	{ }
+};
+
+static int __devinit kirkwood_pinctrl_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match =
+		of_match_device(kirkwood_pinctrl_of_match, &pdev->dev);
+	pdev->dev.platform_data = match->data;
+	return mvebu_pinctrl_probe(pdev);
+}
+
+static int __devexit kirkwood_pinctrl_remove(struct platform_device *pdev)
+{
+	return mvebu_pinctrl_remove(pdev);
+}
+
+static struct platform_driver kirkwood_pinctrl_driver = {
+	.driver = {
+		.name = "kirkwood-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(kirkwood_pinctrl_of_match),
+	},
+	.probe = kirkwood_pinctrl_probe,
+	.remove = __devexit_p(kirkwood_pinctrl_remove),
+};
+
+module_platform_driver(kirkwood_pinctrl_driver);
+
+MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
+MODULE_DESCRIPTION("Marvell Kirkwood pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
new file mode 100644
index 0000000..6c44b7e
--- /dev/null
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -0,0 +1,753 @@
+/*
+ * Marvell MVEBU pinctrl core driver
+ *
+ * Authors: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *          Thomas Petazzoni <thomas.petazzoni@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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "pinctrl-mvebu.h"
+
+#define MPPS_PER_REG	8
+#define MPP_BITS	4
+#define MPP_MASK	0xf
+
+struct mvebu_pinctrl_function {
+	const char *name;
+	const char **groups;
+	unsigned num_groups;
+};
+
+struct mvebu_pinctrl_group {
+	const char *name;
+	struct mvebu_mpp_ctrl *ctrl;
+	struct mvebu_mpp_ctrl_setting *settings;
+	unsigned num_settings;
+	unsigned gid;
+	unsigned *pins;
+	unsigned npins;
+};
+
+struct mvebu_pinctrl {
+	struct device *dev;
+	struct pinctrl_dev *pctldev;
+	struct pinctrl_desc desc;
+	void __iomem *base;
+	struct mvebu_pinctrl_group *groups;
+	unsigned num_groups;
+	struct mvebu_pinctrl_function *functions;
+	unsigned num_functions;
+	u8 variant;
+};
+
+static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_pid(
+	struct mvebu_pinctrl *pctl, unsigned pid)
+{
+	unsigned n;
+	for (n = 0; n < pctl->num_groups; n++) {
+		if (pid >= pctl->groups[n].pins[0] &&
+		    pid < pctl->groups[n].pins[0] +
+			pctl->groups[n].npins)
+			return &pctl->groups[n];
+	}
+	return NULL;
+}
+
+static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_name(
+	struct mvebu_pinctrl *pctl, const char *name)
+{
+	unsigned n;
+	for (n = 0; n < pctl->num_groups; n++) {
+		if (strcmp(name, pctl->groups[n].name) == 0)
+			return &pctl->groups[n];
+	}
+	return NULL;
+}
+
+static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_val(
+	struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp,
+	unsigned long config)
+{
+	unsigned n;
+	for (n = 0; n < grp->num_settings; n++) {
+		if (config == grp->settings[n].val) {
+			if (!pctl->variant || (pctl->variant &
+					       grp->settings[n].variant))
+				return &grp->settings[n];
+		}
+	}
+	return NULL;
+}
+
+static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_name(
+	struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp,
+	const char *name)
+{
+	unsigned n;
+	for (n = 0; n < grp->num_settings; n++) {
+		if (strcmp(name, grp->settings[n].name) == 0) {
+			if (!pctl->variant || (pctl->variant &
+					       grp->settings[n].variant))
+				return &grp->settings[n];
+		}
+	}
+	return NULL;
+}
+
+static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_gpio_setting(
+	struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp)
+{
+	unsigned n;
+	for (n = 0; n < grp->num_settings; n++) {
+		if (grp->settings[n].flags &
+			(MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {
+			if (!pctl->variant || (pctl->variant &
+						grp->settings[n].variant))
+				return &grp->settings[n];
+		}
+	}
+	return NULL;
+}
+
+static struct mvebu_pinctrl_function *mvebu_pinctrl_find_function_by_name(
+	struct mvebu_pinctrl *pctl, const char *name)
+{
+	unsigned n;
+	for (n = 0; n < pctl->num_functions; n++) {
+		if (strcmp(name, pctl->functions[n].name) == 0)
+			return &pctl->functions[n];
+	}
+	return NULL;
+}
+
+/*
+ * Common mpp pin configuration registers on MVEBU are
+ * registers of eight 4-bit values for each mpp setting.
+ * Register offset and bit mask are calculated accordingly below.
+ */
+static int mvebu_common_mpp_get(struct mvebu_pinctrl *pctl,
+				struct mvebu_pinctrl_group *grp,
+				unsigned long *config)
+{
+	unsigned pin = grp->gid;
+	unsigned off = (pin / MPPS_PER_REG) * MPP_BITS;
+	unsigned shift = (pin % MPPS_PER_REG) * MPP_BITS;
+
+	*config = readl(pctl->base + off);
+	*config >>= shift;
+	*config &= MPP_MASK;
+
+	return 0;
+}
+
+static int mvebu_common_mpp_set(struct mvebu_pinctrl *pctl,
+				struct mvebu_pinctrl_group *grp,
+				unsigned long config)
+{
+	unsigned pin = grp->gid;
+	unsigned off = (pin / MPPS_PER_REG) * MPP_BITS;
+	unsigned shift = (pin % MPPS_PER_REG) * MPP_BITS;
+	unsigned long reg;
+
+	reg = readl(pctl->base + off);
+	reg &= ~(MPP_MASK << shift);
+	reg |= (config << shift);
+	writel(reg, pctl->base + off);
+
+	return 0;
+}
+
+static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev,
+				unsigned gid, unsigned long *config)
+{
+	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
+
+	if (!grp->ctrl)
+		return -EINVAL;
+
+	if (grp->ctrl->mpp_get)
+		return grp->ctrl->mpp_get(grp->ctrl, config);
+
+	return mvebu_common_mpp_get(pctl, grp, config);
+}
+
+static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev,
+				unsigned gid, unsigned long config)
+{
+	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
+
+	if (!grp->ctrl)
+		return -EINVAL;
+
+	if (grp->ctrl->mpp_set)
+		return grp->ctrl->mpp_set(grp->ctrl, config);
+
+	return mvebu_common_mpp_set(pctl, grp, config);
+}
+
+static void mvebu_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+					struct seq_file *s, unsigned gid)
+{
+	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
+	struct mvebu_mpp_ctrl_setting *curr;
+	unsigned long config;
+	unsigned n;
+
+	if (mvebu_pinconf_group_get(pctldev, gid, &config))
+		return;
+
+	curr = mvebu_pinctrl_find_setting_by_val(pctl, grp, config);
+
+	if (curr) {
+		seq_printf(s, "current: %s", curr->name);
+		if (curr->subname)
+			seq_printf(s, "(%s)", curr->subname);
+		if (curr->flags & (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {
+			seq_printf(s, "(");
+			if (curr->flags & MVEBU_SETTING_GPI)
+				seq_printf(s, "i");
+			if (curr->flags & MVEBU_SETTING_GPO)
+				seq_printf(s, "o");
+			seq_printf(s, ")");
+		}
+	} else
+		seq_printf(s, "current: UNKNOWN");
+
+	if (grp->num_settings > 1) {
+		seq_printf(s, ", available = [");
+		for (n = 0; n < grp->num_settings; n++) {
+			if (curr == &grp->settings[n])
+				continue;
+
+			/* skip unsupported settings for this variant */
+			if (pctl->variant &&
+			    !(pctl->variant & grp->settings[n].variant))
+				continue;
+
+			seq_printf(s, " %s", grp->settings[n].name);
+			if (grp->settings[n].subname)
+				seq_printf(s, "(%s)", grp->settings[n].subname);
+			if (grp->settings[n].flags &
+				(MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {
+				seq_printf(s, "(");
+				if (grp->settings[n].flags & MVEBU_SETTING_GPI)
+					seq_printf(s, "i");
+				if (grp->settings[n].flags & MVEBU_SETTING_GPO)
+					seq_printf(s, "o");
+				seq_printf(s, ")");
+			}
+		}
+		seq_printf(s, " ]");
+	}
+	return;
+}
+
+static struct pinconf_ops mvebu_pinconf_ops = {
+	.pin_config_group_get = mvebu_pinconf_group_get,
+	.pin_config_group_set = mvebu_pinconf_group_set,
+	.pin_config_group_dbg_show = mvebu_pinconf_group_dbg_show,
+};
+
+static int mvebu_pinmux_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pctl->num_functions;
+}
+
+static const char *mvebu_pinmux_get_func_name(struct pinctrl_dev *pctldev,
+					unsigned fid)
+{
+	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pctl->functions[fid].name;
+}
+
+static int mvebu_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned fid,
+				const char * const **groups,
+				unsigned * const num_groups)
+{
+	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = pctl->functions[fid].groups;
+	*num_groups = pctl->functions[fid].num_groups;
+	return 0;
+}
+
+static int mvebu_pinmux_enable(struct pinctrl_dev *pctldev, unsigned fid,
+			unsigned gid)
+{
+	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	struct mvebu_pinctrl_function *func = &pctl->functions[fid];
+	struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
+	struct mvebu_mpp_ctrl_setting *setting;
+	int ret;
+
+	setting = mvebu_pinctrl_find_setting_by_name(pctl, grp,
+						     func->name);
+	if (!setting) {
+		dev_err(pctl->dev,
+			"unable to find setting %s in group %s\n",
+			func->name, func->groups[gid]);
+		return -EINVAL;
+	}
+
+	ret = mvebu_pinconf_group_set(pctldev, grp->gid, setting->val);
+	if (ret) {
+		dev_err(pctl->dev, "cannot set group %s to %s\n",
+			func->groups[gid], func->name);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int mvebu_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
+			struct pinctrl_gpio_range *range, unsigned offset)
+{
+	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	struct mvebu_pinctrl_group *grp;
+	struct mvebu_mpp_ctrl_setting *setting;
+
+	grp = mvebu_pinctrl_find_group_by_pid(pctl, offset);
+	if (!grp)
+		return -EINVAL;
+
+	if (grp->ctrl->mpp_gpio_req)
+		return grp->ctrl->mpp_gpio_req(grp->ctrl, offset);
+
+	setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
+	if (!setting)
+		return -ENOTSUPP;
+
+	return mvebu_pinconf_group_set(pctldev, grp->gid, setting->val);
+}
+
+static int mvebu_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
+	   struct pinctrl_gpio_range *range, unsigned offset, bool input)
+{
+	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	struct mvebu_pinctrl_group *grp;
+	struct mvebu_mpp_ctrl_setting *setting;
+
+	grp = mvebu_pinctrl_find_group_by_pid(pctl, offset);
+	if (!grp)
+		return -EINVAL;
+
+	if (grp->ctrl->mpp_gpio_dir)
+		return grp->ctrl->mpp_gpio_dir(grp->ctrl, offset, input);
+
+	setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
+	if (!setting)
+		return -ENOTSUPP;
+
+	if ((input && (setting->flags & MVEBU_SETTING_GPI)) ||
+	    (!input && (setting->flags & MVEBU_SETTING_GPO)))
+		return 0;
+
+	return -ENOTSUPP;
+}
+
+static struct pinmux_ops mvebu_pinmux_ops = {
+	.get_functions_count = mvebu_pinmux_get_funcs_count,
+	.get_function_name = mvebu_pinmux_get_func_name,
+	.get_function_groups = mvebu_pinmux_get_groups,
+	.gpio_request_enable = mvebu_pinmux_gpio_request_enable,
+	.gpio_set_direction = mvebu_pinmux_gpio_set_direction,
+	.enable = mvebu_pinmux_enable,
+};
+
+static int mvebu_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	return pctl->num_groups;
+}
+
+static const char *mvebu_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+						unsigned gid)
+{
+	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	return pctl->groups[gid].name;
+}
+
+static int mvebu_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+					unsigned gid, const unsigned **pins,
+					unsigned *num_pins)
+{
+	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	*pins = pctl->groups[gid].pins;
+	*num_pins = pctl->groups[gid].npins;
+	return 0;
+}
+
+static int mvebu_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+					struct device_node *np,
+					struct pinctrl_map **map,
+					unsigned *num_maps)
+{
+	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	struct property *prop;
+	const char *function;
+	const char *group;
+	int ret, nmaps, n;
+
+	*map = NULL;
+	*num_maps = 0;
+
+	ret = of_property_read_string(np, "marvell,function", &function);
+	if (ret) {
+		dev_err(pctl->dev,
+			"missing marvell,function in node %s\n", np->name);
+		return 0;
+	}
+
+	nmaps = of_property_count_strings(np, "marvell,pins");
+	if (nmaps < 0) {
+		dev_err(pctl->dev,
+			"missing marvell,pins in node %s\n", np->name);
+		return 0;
+	}
+
+	*map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL);
+	if (map == NULL) {
+		dev_err(pctl->dev,
+			"cannot allocate pinctrl_map memory for %s\n",
+			np->name);
+		return -ENOMEM;
+	}
+
+	n = 0;
+	of_property_for_each_string(np, "marvell,pins", prop, group) {
+		struct mvebu_pinctrl_group *grp =
+			mvebu_pinctrl_find_group_by_name(pctl, group);
+
+		if (!grp) {
+			dev_err(pctl->dev, "unknown pin %s", group);
+			continue;
+		}
+
+		if (!mvebu_pinctrl_find_setting_by_name(pctl, grp, function)) {
+			dev_err(pctl->dev, "unsupported function %s on pin %s",
+				function, group);
+			continue;
+		}
+
+		(*map)[n].type = PIN_MAP_TYPE_MUX_GROUP;
+		(*map)[n].data.mux.group = group;
+		(*map)[n].data.mux.function = function;
+		n++;
+	}
+
+	*num_maps = nmaps;
+
+	return 0;
+}
+
+static void mvebu_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+				struct pinctrl_map *map, unsigned num_maps)
+{
+	kfree(map);
+}
+
+static struct pinctrl_ops mvebu_pinctrl_ops = {
+	.get_groups_count = mvebu_pinctrl_get_groups_count,
+	.get_group_name = mvebu_pinctrl_get_group_name,
+	.get_group_pins = mvebu_pinctrl_get_group_pins,
+	.dt_node_to_map = mvebu_pinctrl_dt_node_to_map,
+	.dt_free_map = mvebu_pinctrl_dt_free_map,
+};
+
+static int __devinit _add_function(struct mvebu_pinctrl_function *funcs,
+				   const char *name)
+{
+	while (funcs->num_groups) {
+		/* function already there */
+		if (strcmp(funcs->name, name) == 0) {
+			funcs->num_groups++;
+			return -EEXIST;
+		}
+		funcs++;
+	}
+	funcs->name = name;
+	funcs->num_groups = 1;
+	return 0;
+}
+
+static int __devinit mvebu_pinctrl_build_functions(struct platform_device *pdev,
+						   struct mvebu_pinctrl *pctl)
+{
+	struct mvebu_pinctrl_function *funcs;
+	int num = 0;
+	int n, s;
+
+	/* we allocate functions for number of pins and hope
+	 * there are less unique functions than pins available */
+	funcs = devm_kzalloc(&pdev->dev, pctl->desc.npins *
+			     sizeof(struct mvebu_pinctrl_function), GFP_KERNEL);
+	if (!funcs)
+		return -ENOMEM;
+
+	for (n = 0; n < pctl->num_groups; n++) {
+		struct mvebu_pinctrl_group *grp = &pctl->groups[n];
+		for (s = 0; s < grp->num_settings; s++) {
+			/* skip unsupported settings on this variant */
+			if (pctl->variant &&
+			    !(pctl->variant & grp->settings[s].variant))
+				continue;
+
+			/* check for unique functions and count groups */
+			if (_add_function(funcs, grp->settings[s].name))
+				continue;
+
+			num++;
+		}
+	}
+
+	/* with the number of unique functions and it's groups known,
+	   reallocate functions and assign group names */
+	funcs = krealloc(funcs, num * sizeof(struct mvebu_pinctrl_function),
+			 GFP_KERNEL);
+	if (!funcs)
+		return -ENOMEM;
+
+	pctl->num_functions = num;
+	pctl->functions = funcs;
+
+	for (n = 0; n < pctl->num_groups; n++) {
+		struct mvebu_pinctrl_group *grp = &pctl->groups[n];
+		for (s = 0; s < grp->num_settings; s++) {
+			struct mvebu_pinctrl_function *f;
+			const char **groups;
+
+			/* skip unsupported settings on this variant */
+			if (pctl->variant &&
+			    !(pctl->variant & grp->settings[s].variant))
+				continue;
+
+			f = mvebu_pinctrl_find_function_by_name(pctl,
+							grp->settings[s].name);
+
+			/* allocate group name array if not done already */
+			if (!f->groups) {
+				f->groups = devm_kzalloc(&pdev->dev,
+						 f->num_groups * sizeof(char *),
+						 GFP_KERNEL);
+				if (!f->groups)
+					return -ENOMEM;
+			}
+
+			/* find next free group name and assign current name */
+			groups = f->groups;
+			while (*groups)
+				groups++;
+			*groups = grp->name;
+		}
+	}
+
+	return 0;
+}
+
+int __devinit mvebu_pinctrl_probe(struct platform_device *pdev)
+{
+	struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev);
+	struct device_node *np = pdev->dev.of_node;
+	struct mvebu_pinctrl *pctl;
+	void __iomem *base;
+	struct pinctrl_pin_desc *pdesc;
+	unsigned gid, n, k;
+	int ret;
+
+	if (!soc || !soc->controls || !soc->modes) {
+		dev_err(&pdev->dev, "wrong pinctrl soc info\n");
+		return -EINVAL;
+	}
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		dev_err(&pdev->dev, "unable to get base address\n");
+		return -ENODEV;
+	}
+
+	pctl = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pinctrl),
+			GFP_KERNEL);
+	if (!pctl) {
+		dev_err(&pdev->dev, "unable to alloc driver\n");
+		return -ENOMEM;
+	}
+
+	pctl->desc.name = dev_name(&pdev->dev);
+	pctl->desc.owner = THIS_MODULE;
+	pctl->desc.pctlops = &mvebu_pinctrl_ops;
+	pctl->desc.pmxops = &mvebu_pinmux_ops;
+	pctl->desc.confops = &mvebu_pinconf_ops;
+	pctl->variant = soc->variant;
+	pctl->base = base;
+	pctl->dev = &pdev->dev;
+	platform_set_drvdata(pdev, pctl);
+
+	/* count controls and create names for mvebu generic
+	   register controls; also does sanity checks */
+	pctl->num_groups = 0;
+	pctl->desc.npins = 0;
+	for (n = 0; n < soc->ncontrols; n++) {
+		struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
+		char *names;
+
+		pctl->desc.npins += ctrl->npins;
+		/* initial control pins */
+		for (k = 0; k < ctrl->npins; k++)
+			ctrl->pins[k] = ctrl->pid + k;
+
+		/* special soc specific control */
+		if (ctrl->mpp_get || ctrl->mpp_set) {
+			if (!ctrl->name || !ctrl->mpp_set || !ctrl->mpp_set) {
+				dev_err(&pdev->dev, "wrong soc control info\n");
+				return -EINVAL;
+			}
+			pctl->num_groups += 1;
+			continue;
+		}
+
+		/* generic mvebu register control */
+		names = devm_kzalloc(&pdev->dev, ctrl->npins * 8, GFP_KERNEL);
+		if (!names) {
+			dev_err(&pdev->dev, "failed to alloc mpp names\n");
+			return -ENOMEM;
+		}
+		for (k = 0; k < ctrl->npins; k++)
+			sprintf(names + 8*k, "mpp%d", ctrl->pid+k);
+		ctrl->name = names;
+		pctl->num_groups += ctrl->npins;
+	}
+
+	pdesc = devm_kzalloc(&pdev->dev, pctl->desc.npins *
+			     sizeof(struct pinctrl_pin_desc), GFP_KERNEL);
+	if (!pdesc) {
+		dev_err(&pdev->dev, "failed to alloc pinctrl pins\n");
+		return -ENOMEM;
+	}
+
+	for (n = 0; n < pctl->desc.npins; n++)
+		pdesc[n].number = n;
+	pctl->desc.pins = pdesc;
+
+	pctl->groups = devm_kzalloc(&pdev->dev, pctl->num_groups *
+			     sizeof(struct mvebu_pinctrl_group), GFP_KERNEL);
+	if (!pctl->groups) {
+		dev_err(&pdev->dev, "failed to alloc pinctrl groups\n");
+		return -ENOMEM;
+	}
+
+	/* assign mpp controls to groups */
+	gid = 0;
+	for (n = 0; n < soc->ncontrols; n++) {
+		struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
+		pctl->groups[gid].gid = gid;
+		pctl->groups[gid].ctrl = ctrl;
+		pctl->groups[gid].name = ctrl->name;
+		pctl->groups[gid].pins = ctrl->pins;
+		pctl->groups[gid].npins = ctrl->npins;
+
+		/* generic mvebu register control maps to a number of groups */
+		if (!ctrl->mpp_get && !ctrl->mpp_set) {
+			pctl->groups[gid].npins = 1;
+
+			for (k = 1; k < ctrl->npins; k++) {
+				gid++;
+				pctl->groups[gid].gid = gid;
+				pctl->groups[gid].ctrl = ctrl;
+				pctl->groups[gid].name = &ctrl->name[8*k];
+				pctl->groups[gid].pins = &ctrl->pins[k];
+				pctl->groups[gid].npins = 1;
+			}
+		}
+		gid++;
+	}
+
+	/* assign mpp modes to groups */
+	for (n = 0; n < soc->nmodes; n++) {
+		struct mvebu_mpp_mode *mode = &soc->modes[n];
+		struct mvebu_pinctrl_group *grp =
+			mvebu_pinctrl_find_group_by_pid(pctl, mode->pid);
+		unsigned num_settings;
+
+		if (!grp) {
+			dev_warn(&pdev->dev, "unknown pinctrl group %d\n",
+				mode->pid);
+			continue;
+		}
+
+		for (num_settings = 0; ;) {
+			struct mvebu_mpp_ctrl_setting *set =
+				&mode->settings[num_settings];
+
+			if (!set->name)
+				break;
+			num_settings++;
+
+			/* skip unsupported settings for this variant */
+			if (pctl->variant && !(pctl->variant & set->variant))
+				continue;
+
+			/* find gpio/gpo/gpi settings */
+			if (strcmp(set->name, "gpio") == 0)
+				set->flags = MVEBU_SETTING_GPI |
+					MVEBU_SETTING_GPO;
+			else if (strcmp(set->name, "gpo") == 0)
+				set->flags = MVEBU_SETTING_GPO;
+			else if (strcmp(set->name, "gpi") == 0)
+				set->flags = MVEBU_SETTING_GPI;
+		}
+
+		grp->settings = mode->settings;
+		grp->num_settings = num_settings;
+	}
+
+	ret = mvebu_pinctrl_build_functions(pdev, pctl);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to build functions\n");
+		return ret;
+	}
+
+	pctl->pctldev = pinctrl_register(&pctl->desc, &pdev->dev, pctl);
+	if (!pctl->pctldev) {
+		dev_err(&pdev->dev, "unable to register pinctrl driver\n");
+		return -EINVAL;
+	}
+
+	dev_info(&pdev->dev, "registered pinctrl driver\n");
+
+	/* register gpio ranges */
+	for (n = 0; n < soc->ngpioranges; n++)
+		pinctrl_add_gpio_range(pctl->pctldev, &soc->gpioranges[n]);
+
+	return 0;
+}
+
+int __devexit mvebu_pinctrl_remove(struct platform_device *pdev)
+{
+	struct mvebu_pinctrl *pctl = platform_get_drvdata(pdev);
+	pinctrl_unregister(pctl->pctldev);
+	return 0;
+}
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.h b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
new file mode 100644
index 0000000..90bd3be
--- /dev/null
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
@@ -0,0 +1,192 @@
+/*
+ * Marvell MVEBU pinctrl driver
+ *
+ * Authors: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *          Thomas Petazzoni <thomas.petazzoni@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.
+ */
+
+#ifndef __PINCTRL_MVEBU_H__
+#define __PINCTRL_MVEBU_H__
+
+/**
+ * struct mvebu_mpp_ctrl - describe a mpp control
+ * @name: name of the control group
+ * @pid: first pin id handled by this control
+ * @npins: number of pins controlled by this control
+ * @mpp_get: (optional) special function to get mpp setting
+ * @mpp_set: (optional) special function to set mpp setting
+ * @mpp_gpio_req: (optional) special function to request gpio
+ * @mpp_gpio_dir: (optional) special function to set gpio direction
+ *
+ * A mpp_ctrl describes a muxable unit, e.g. pin, group of pins, or
+ * internal function, inside the SoC. Each muxable unit can be switched
+ * between two or more different settings, e.g. assign mpp pin 13 to
+ * uart1 or sata.
+ *
+ * If optional mpp_get/_set functions are set these are used to get/set
+ * a specific mode. Otherwise it is assumed that the mpp control is based
+ * on 4-bit groups in subsequent registers. The optional mpp_gpio_req/_dir
+ * functions can be used to allow pin settings with varying gpio pins.
+ */
+struct mvebu_mpp_ctrl {
+	const char *name;
+	u8 pid;
+	u8 npins;
+	unsigned *pins;
+	int (*mpp_get)(struct mvebu_mpp_ctrl *ctrl, unsigned long *config);
+	int (*mpp_set)(struct mvebu_mpp_ctrl *ctrl, unsigned long config);
+	int (*mpp_gpio_req)(struct mvebu_mpp_ctrl *ctrl, u8 pid);
+	int (*mpp_gpio_dir)(struct mvebu_mpp_ctrl *ctrl, u8 pid, bool input);
+};
+
+/**
+ * struct mvebu_mpp_ctrl_setting - describe a mpp ctrl setting
+ * @val: ctrl setting value
+ * @name: ctrl setting name, e.g. uart2, spi0 - unique per mpp_mode
+ * @subname: (optional) additional ctrl setting name, e.g. rts, cts
+ * @variant: (optional) variant identifier mask
+ * @flags: (private) flags to store gpi/gpo/gpio capabilities
+ *
+ * A ctrl_setting describes a specific internal mux function that a mpp pin
+ * can be switched to. The value (val) will be written in the corresponding
+ * register for common mpp pin configuration registers on MVEBU. SoC specific
+ * mpp_get/_set function may use val to distinguish between different settings.
+ *
+ * The name will be used to switch to this setting in DT description, e.g.
+ * marvell,function = "uart2". subname is only for debugging purposes.
+ *
+ * If name is one of "gpi", "gpo", "gpio" gpio capabilities are
+ * parsed during initialization and stored in flags.
+ *
+ * The variant can be used to combine different revisions of one SoC to a
+ * common pinctrl driver. It is matched (AND) with variant of soc_info to
+ * determine if a setting is available on the current SoC revision.
+ */
+struct mvebu_mpp_ctrl_setting {
+	u8 val;
+	const char *name;
+	const char *subname;
+	u8 variant;
+	u8 flags;
+#define  MVEBU_SETTING_GPO	(1 << 0)
+#define  MVEBU_SETTING_GPI	(1 << 1)
+};
+
+/**
+ * struct mvebu_mpp_mode - link ctrl and settings
+ * @pid: first pin id handled by this mode
+ * @settings: list of settings available for this mode
+ *
+ * A mode connects all available settings with the corresponding mpp_ctrl
+ * given by pid.
+ */
+struct mvebu_mpp_mode {
+	u8 pid;
+	struct mvebu_mpp_ctrl_setting *settings;
+};
+
+/**
+ * struct mvebu_pinctrl_soc_info - SoC specific info passed to pinctrl-mvebu
+ * @variant: variant mask of soc_info
+ * @controls: list of available mvebu_mpp_ctrls
+ * @ncontrols: number of available mvebu_mpp_ctrls
+ * @modes: list of available mvebu_mpp_modes
+ * @nmodes: number of available mvebu_mpp_modes
+ * @gpioranges: list of pinctrl_gpio_ranges
+ * @ngpioranges: number of available pinctrl_gpio_ranges
+ *
+ * This struct describes all pinctrl related information for a specific SoC.
+ * If variant is unequal 0 it will be matched (AND) with variant of each
+ * setting and allows to distinguish between different revisions of one SoC.
+ */
+struct mvebu_pinctrl_soc_info {
+	u8 variant;
+	struct mvebu_mpp_ctrl *controls;
+	int ncontrols;
+	struct mvebu_mpp_mode *modes;
+	int nmodes;
+	struct pinctrl_gpio_range *gpioranges;
+	int ngpioranges;
+};
+
+#define MPP_REG_CTRL(_idl, _idh)				\
+	{							\
+		.name = NULL,					\
+		.pid = _idl,					\
+		.npins = _idh - _idl + 1,			\
+		.pins = (unsigned[_idh - _idl + 1]) { },	\
+		.mpp_get = NULL,				\
+		.mpp_set = NULL,				\
+		.mpp_gpio_req = NULL,				\
+		.mpp_gpio_dir = NULL,				\
+	}
+
+#define MPP_FUNC_CTRL(_idl, _idh, _name, _func)			\
+	{							\
+		.name = _name,					\
+		.pid = _idl,					\
+		.npins = _idh - _idl + 1,			\
+		.pins = (unsigned[_idh - _idl + 1]) { },	\
+		.mpp_get = _func ## _get,			\
+		.mpp_set = _func ## _set,			\
+		.mpp_gpio_req = NULL,				\
+		.mpp_gpio_dir = NULL,				\
+	}
+
+#define MPP_FUNC_GPIO_CTRL(_idl, _idh, _name, _func)		\
+	{							\
+		.name = _name,					\
+		.pid = _idl,					\
+		.npins = _idh - _idl + 1,			\
+		.pins = (unsigned[_idh - _idl + 1]) { },	\
+		.mpp_get = _func ## _get,			\
+		.mpp_set = _func ## _set,			\
+		.mpp_gpio_req = _func ## _gpio_req,		\
+		.mpp_gpio_dir = _func ## _gpio_dir,		\
+	}
+
+#define _MPP_VAR_FUNCTION(_val, _name, _subname, _mask)		\
+	{							\
+		.val = _val,					\
+		.name = _name,					\
+		.subname = _subname,				\
+		.variant = _mask,				\
+		.flags = 0,					\
+	}
+
+#if defined(CONFIG_DEBUG_FS)
+#define MPP_VAR_FUNCTION(_val, _name, _subname, _mask)		\
+	_MPP_VAR_FUNCTION(_val, _name, _subname, _mask)
+#else
+#define MPP_VAR_FUNCTION(_val, _name, _subname, _mask)		\
+	_MPP_VAR_FUNCTION(_val, _name, NULL, _mask)
+#endif
+
+#define MPP_FUNCTION(_val, _name, _subname)			\
+	MPP_VAR_FUNCTION(_val, _name, _subname, (u8)-1)
+
+#define MPP_MODE(_id, ...)					\
+	{							\
+		.pid = _id,					\
+		.settings = (struct mvebu_mpp_ctrl_setting[]){	\
+			__VA_ARGS__, { } },			\
+	}
+
+#define MPP_GPIO_RANGE(_id, _pinbase, _gpiobase, _npins)	\
+	{							\
+		.name = "mvebu-gpio",				\
+		.id = _id,					\
+		.pin_base = _pinbase,				\
+		.base = _gpiobase,				\
+		.npins = _npins,				\
+	}
+
+int mvebu_pinctrl_probe(struct platform_device *pdev);
+int mvebu_pinctrl_remove(struct platform_device *pdev);
+
+#endif
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 33fbaea..833a364 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -41,6 +41,7 @@ struct pin_config_item conf_items[] = {
 	PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL),
 	PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL),
 	PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL),
+	PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT_DISABLE, "input schmitt disabled", NULL),
 	PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL),
 	PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "time units"),
 	PCONFDUMP(PIN_CONFIG_POWER_SOURCE, "pin power source", "selector"),
diff --git a/drivers/pinctrl/pinctrl-armada-370.c b/drivers/pinctrl/pinctrl-armada-370.c
deleted file mode 100644
index c907647..0000000
--- a/drivers/pinctrl/pinctrl-armada-370.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Marvell Armada 370 pinctrl driver based on mvebu pinctrl core
- *
- * Copyright (C) 2012 Marvell
- *
- * Thomas Petazzoni <thomas.petazzoni@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.
- */
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/pinctrl/pinctrl.h>
-
-#include "pinctrl-mvebu.h"
-
-static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = {
-	MPP_MODE(0,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "uart0", "rxd")),
-	MPP_MODE(1,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "uart0", "txd")),
-	MPP_MODE(2,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "i2c0", "sck"),
-	   MPP_FUNCTION(0x2, "uart0", "txd")),
-	MPP_MODE(3,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "i2c0", "sda"),
-	   MPP_FUNCTION(0x2, "uart0", "rxd")),
-	MPP_MODE(4,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "cpu_pd", "vdd")),
-	MPP_MODE(5,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "txclko"),
-	   MPP_FUNCTION(0x2, "uart1", "txd"),
-	   MPP_FUNCTION(0x4, "spi1", "clk"),
-	   MPP_FUNCTION(0x5, "audio", "mclk")),
-	MPP_MODE(6,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "txd0"),
-	   MPP_FUNCTION(0x2, "sata0", "prsnt"),
-	   MPP_FUNCTION(0x4, "tdm", "rst"),
-	   MPP_FUNCTION(0x5, "audio", "sdo")),
-	MPP_MODE(7,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "txd1"),
-	   MPP_FUNCTION(0x4, "tdm", "tdx"),
-	   MPP_FUNCTION(0x5, "audio", "lrclk")),
-	MPP_MODE(8,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "txd2"),
-	   MPP_FUNCTION(0x2, "uart0", "rts"),
-	   MPP_FUNCTION(0x4, "tdm", "drx"),
-	   MPP_FUNCTION(0x5, "audio", "bclk")),
-	MPP_MODE(9,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "txd3"),
-	   MPP_FUNCTION(0x2, "uart1", "txd"),
-	   MPP_FUNCTION(0x3, "sd0", "clk"),
-	   MPP_FUNCTION(0x5, "audio", "spdifo")),
-	MPP_MODE(10,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "txctl"),
-	   MPP_FUNCTION(0x2, "uart0", "cts"),
-	   MPP_FUNCTION(0x4, "tdm", "fsync"),
-	   MPP_FUNCTION(0x5, "audio", "sdi")),
-	MPP_MODE(11,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "rxd0"),
-	   MPP_FUNCTION(0x2, "uart1", "rxd"),
-	   MPP_FUNCTION(0x3, "sd0", "cmd"),
-	   MPP_FUNCTION(0x4, "spi0", "cs1"),
-	   MPP_FUNCTION(0x5, "sata1", "prsnt"),
-	   MPP_FUNCTION(0x6, "spi1", "cs1")),
-	MPP_MODE(12,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "rxd1"),
-	   MPP_FUNCTION(0x2, "i2c1", "sda"),
-	   MPP_FUNCTION(0x3, "sd0", "d0"),
-	   MPP_FUNCTION(0x4, "spi1", "cs0"),
-	   MPP_FUNCTION(0x5, "audio", "spdifi")),
-	MPP_MODE(13,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "rxd2"),
-	   MPP_FUNCTION(0x2, "i2c1", "sck"),
-	   MPP_FUNCTION(0x3, "sd0", "d1"),
-	   MPP_FUNCTION(0x4, "tdm", "pclk"),
-	   MPP_FUNCTION(0x5, "audio", "rmclk")),
-	MPP_MODE(14,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "rxd3"),
-	   MPP_FUNCTION(0x2, "pcie", "clkreq0"),
-	   MPP_FUNCTION(0x3, "sd0", "d2"),
-	   MPP_FUNCTION(0x4, "spi1", "mosi"),
-	   MPP_FUNCTION(0x5, "spi0", "cs2")),
-	MPP_MODE(15,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "rxctl"),
-	   MPP_FUNCTION(0x2, "pcie", "clkreq1"),
-	   MPP_FUNCTION(0x3, "sd0", "d3"),
-	   MPP_FUNCTION(0x4, "spi1", "miso"),
-	   MPP_FUNCTION(0x5, "spi0", "cs3")),
-	MPP_MODE(16,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "rxclk"),
-	   MPP_FUNCTION(0x2, "uart1", "rxd"),
-	   MPP_FUNCTION(0x4, "tdm", "int"),
-	   MPP_FUNCTION(0x5, "audio", "extclk")),
-	MPP_MODE(17,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "ge", "mdc")),
-	MPP_MODE(18,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge", "mdio")),
-	MPP_MODE(19,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "txclk"),
-	   MPP_FUNCTION(0x2, "ge1", "txclkout"),
-	   MPP_FUNCTION(0x4, "tdm", "pclk")),
-	MPP_MODE(20,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "txd4"),
-	   MPP_FUNCTION(0x2, "ge1", "txd0")),
-	MPP_MODE(21,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "txd5"),
-	   MPP_FUNCTION(0x2, "ge1", "txd1"),
-	   MPP_FUNCTION(0x4, "uart1", "txd")),
-	MPP_MODE(22,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "txd6"),
-	   MPP_FUNCTION(0x2, "ge1", "txd2"),
-	   MPP_FUNCTION(0x4, "uart0", "rts")),
-	MPP_MODE(23,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "txd7"),
-	   MPP_FUNCTION(0x2, "ge1", "txd3"),
-	   MPP_FUNCTION(0x4, "spi1", "mosi")),
-	MPP_MODE(24,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "col"),
-	   MPP_FUNCTION(0x2, "ge1", "txctl"),
-	   MPP_FUNCTION(0x4, "spi1", "cs0")),
-	MPP_MODE(25,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "rxerr"),
-	   MPP_FUNCTION(0x2, "ge1", "rxd0"),
-	   MPP_FUNCTION(0x4, "uart1", "rxd")),
-	MPP_MODE(26,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "crs"),
-	   MPP_FUNCTION(0x2, "ge1", "rxd1"),
-	   MPP_FUNCTION(0x4, "spi1", "miso")),
-	MPP_MODE(27,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "rxd4"),
-	   MPP_FUNCTION(0x2, "ge1", "rxd2"),
-	   MPP_FUNCTION(0x4, "uart0", "cts")),
-	MPP_MODE(28,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "rxd5"),
-	   MPP_FUNCTION(0x2, "ge1", "rxd3")),
-	MPP_MODE(29,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "rxd6"),
-	   MPP_FUNCTION(0x2, "ge1", "rxctl"),
-	   MPP_FUNCTION(0x4, "i2c1", "sda")),
-	MPP_MODE(30,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "ge0", "rxd7"),
-	   MPP_FUNCTION(0x2, "ge1", "rxclk"),
-	   MPP_FUNCTION(0x4, "i2c1", "sck")),
-	MPP_MODE(31,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x3, "tclk", NULL),
-	   MPP_FUNCTION(0x4, "ge0", "txerr")),
-	MPP_MODE(32,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "spi0", "cs0")),
-	MPP_MODE(33,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "dev", "bootcs"),
-	   MPP_FUNCTION(0x2, "spi0", "cs0")),
-	MPP_MODE(34,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "dev", "wen0"),
-	   MPP_FUNCTION(0x2, "spi0", "mosi")),
-	MPP_MODE(35,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "dev", "oen"),
-	   MPP_FUNCTION(0x2, "spi0", "sck")),
-	MPP_MODE(36,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "dev", "a1"),
-	   MPP_FUNCTION(0x2, "spi0", "miso")),
-	MPP_MODE(37,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "dev", "a0"),
-	   MPP_FUNCTION(0x2, "sata0", "prsnt")),
-	MPP_MODE(38,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ready"),
-	   MPP_FUNCTION(0x2, "uart1", "cts"),
-	   MPP_FUNCTION(0x3, "uart0", "cts")),
-	MPP_MODE(39,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ad0"),
-	   MPP_FUNCTION(0x2, "audio", "spdifo")),
-	MPP_MODE(40,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ad1"),
-	   MPP_FUNCTION(0x2, "uart1", "rts"),
-	   MPP_FUNCTION(0x3, "uart0", "rts")),
-	MPP_MODE(41,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ad2"),
-	   MPP_FUNCTION(0x2, "uart1", "rxd")),
-	MPP_MODE(42,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ad3"),
-	   MPP_FUNCTION(0x2, "uart1", "txd")),
-	MPP_MODE(43,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ad4"),
-	   MPP_FUNCTION(0x2, "audio", "bclk")),
-	MPP_MODE(44,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ad5"),
-	   MPP_FUNCTION(0x2, "audio", "mclk")),
-	MPP_MODE(45,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ad6"),
-	   MPP_FUNCTION(0x2, "audio", "lrclk")),
-	MPP_MODE(46,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ad7"),
-	   MPP_FUNCTION(0x2, "audio", "sdo")),
-	MPP_MODE(47,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ad8"),
-	   MPP_FUNCTION(0x3, "sd0", "clk"),
-	   MPP_FUNCTION(0x5, "audio", "spdifo")),
-	MPP_MODE(48,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ad9"),
-	   MPP_FUNCTION(0x2, "uart0", "rts"),
-	   MPP_FUNCTION(0x3, "sd0", "cmd"),
-	   MPP_FUNCTION(0x4, "sata1", "prsnt"),
-	   MPP_FUNCTION(0x5, "spi0", "cs1")),
-	MPP_MODE(49,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ad10"),
-	   MPP_FUNCTION(0x2, "pcie", "clkreq1"),
-	   MPP_FUNCTION(0x3, "sd0", "d0"),
-	   MPP_FUNCTION(0x4, "spi1", "cs0"),
-	   MPP_FUNCTION(0x5, "audio", "spdifi")),
-	MPP_MODE(50,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ad11"),
-	   MPP_FUNCTION(0x2, "uart0", "cts"),
-	   MPP_FUNCTION(0x3, "sd0", "d1"),
-	   MPP_FUNCTION(0x4, "spi1", "miso"),
-	   MPP_FUNCTION(0x5, "audio", "rmclk")),
-	MPP_MODE(51,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ad12"),
-	   MPP_FUNCTION(0x2, "i2c1", "sda"),
-	   MPP_FUNCTION(0x3, "sd0", "d2"),
-	   MPP_FUNCTION(0x4, "spi1", "mosi")),
-	MPP_MODE(52,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ad13"),
-	   MPP_FUNCTION(0x2, "i2c1", "sck"),
-	   MPP_FUNCTION(0x3, "sd0", "d3"),
-	   MPP_FUNCTION(0x4, "spi1", "sck")),
-	MPP_MODE(53,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ad14"),
-	   MPP_FUNCTION(0x2, "sd0", "clk"),
-	   MPP_FUNCTION(0x3, "tdm", "pclk"),
-	   MPP_FUNCTION(0x4, "spi0", "cs2"),
-	   MPP_FUNCTION(0x5, "pcie", "clkreq1")),
-	MPP_MODE(54,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ad15"),
-	   MPP_FUNCTION(0x3, "tdm", "dtx")),
-	MPP_MODE(55,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "dev", "cs1"),
-	   MPP_FUNCTION(0x2, "uart1", "txd"),
-	   MPP_FUNCTION(0x3, "tdm", "rst"),
-	   MPP_FUNCTION(0x4, "sata1", "prsnt"),
-	   MPP_FUNCTION(0x5, "sata0", "prsnt")),
-	MPP_MODE(56,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "dev", "cs2"),
-	   MPP_FUNCTION(0x2, "uart1", "cts"),
-	   MPP_FUNCTION(0x3, "uart0", "cts"),
-	   MPP_FUNCTION(0x4, "spi0", "cs3"),
-	   MPP_FUNCTION(0x5, "pcie", "clkreq0"),
-	   MPP_FUNCTION(0x6, "spi1", "cs1")),
-	MPP_MODE(57,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "dev", "cs3"),
-	   MPP_FUNCTION(0x2, "uart1", "rxd"),
-	   MPP_FUNCTION(0x3, "tdm", "fsync"),
-	   MPP_FUNCTION(0x4, "sata0", "prsnt"),
-	   MPP_FUNCTION(0x5, "audio", "sdo")),
-	MPP_MODE(58,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "dev", "cs0"),
-	   MPP_FUNCTION(0x2, "uart1", "rts"),
-	   MPP_FUNCTION(0x3, "tdm", "int"),
-	   MPP_FUNCTION(0x5, "audio", "extclk"),
-	   MPP_FUNCTION(0x6, "uart0", "rts")),
-	MPP_MODE(59,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ale0"),
-	   MPP_FUNCTION(0x2, "uart1", "rts"),
-	   MPP_FUNCTION(0x3, "uart0", "rts"),
-	   MPP_FUNCTION(0x5, "audio", "bclk")),
-	MPP_MODE(60,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "dev", "ale1"),
-	   MPP_FUNCTION(0x2, "uart1", "rxd"),
-	   MPP_FUNCTION(0x3, "sata0", "prsnt"),
-	   MPP_FUNCTION(0x4, "pcie", "rst-out"),
-	   MPP_FUNCTION(0x5, "audio", "sdi")),
-	MPP_MODE(61,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "dev", "wen1"),
-	   MPP_FUNCTION(0x2, "uart1", "txd"),
-	   MPP_FUNCTION(0x5, "audio", "rclk")),
-	MPP_MODE(62,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "dev", "a2"),
-	   MPP_FUNCTION(0x2, "uart1", "cts"),
-	   MPP_FUNCTION(0x3, "tdm", "drx"),
-	   MPP_FUNCTION(0x4, "pcie", "clkreq0"),
-	   MPP_FUNCTION(0x5, "audio", "mclk"),
-	   MPP_FUNCTION(0x6, "uart0", "cts")),
-	MPP_MODE(63,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
-	   MPP_FUNCTION(0x1, "spi0", "sck"),
-	   MPP_FUNCTION(0x2, "tclk", NULL)),
-	MPP_MODE(64,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "spi0", "miso"),
-	   MPP_FUNCTION(0x2, "spi0-1", "cs1")),
-	MPP_MODE(65,
-	   MPP_FUNCTION(0x0, "gpio", NULL),
-	   MPP_FUNCTION(0x1, "spi0", "mosi"),
-	   MPP_FUNCTION(0x2, "spi0-1", "cs2")),
-};
-
-static struct mvebu_pinctrl_soc_info armada_370_pinctrl_info;
-
-static struct of_device_id armada_370_pinctrl_of_match[] __devinitdata = {
-	{ .compatible = "marvell,mv88f6710-pinctrl" },
-	{ },
-};
-
-static struct mvebu_mpp_ctrl mv88f6710_mpp_controls[] = {
-	MPP_REG_CTRL(0, 65),
-};
-
-static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = {
-	MPP_GPIO_RANGE(0,   0,  0, 32),
-	MPP_GPIO_RANGE(1,  32, 32, 32),
-	MPP_GPIO_RANGE(2,  64, 64,  2),
-};
-
-static int __devinit armada_370_pinctrl_probe(struct platform_device *pdev)
-{
-	struct mvebu_pinctrl_soc_info *soc = &armada_370_pinctrl_info;
-
-	soc->variant = 0; /* no variants for Armada 370 */
-	soc->controls = mv88f6710_mpp_controls;
-	soc->ncontrols = ARRAY_SIZE(mv88f6710_mpp_controls);
-	soc->modes = mv88f6710_mpp_modes;
-	soc->nmodes = ARRAY_SIZE(mv88f6710_mpp_modes);
-	soc->gpioranges = mv88f6710_mpp_gpio_ranges;
-	soc->ngpioranges = ARRAY_SIZE(mv88f6710_mpp_gpio_ranges);
-
-	pdev->dev.platform_data = soc;
-
-	return mvebu_pinctrl_probe(pdev);
-}
-
-static int __devexit armada_370_pinctrl_remove(struct platform_device *pdev)
-{
-	return mvebu_pinctrl_remove(pdev);
-}
-
-static struct platform_driver armada_370_pinctrl_driver = {
-	.driver = {
-		.name = "armada-370-pinctrl",
-		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(armada_370_pinctrl_of_match),
-	},
-	.probe = armada_370_pinctrl_probe,
-	.remove = __devexit_p(armada_370_pinctrl_remove),
-};
-
-module_platform_driver(armada_370_pinctrl_driver);
-
-MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
-MODULE_DESCRIPTION("Marvell Armada 370 pinctrl driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-armada-xp.c b/drivers/pinctrl/pinctrl-armada-xp.c
deleted file mode 100644
index 40bd52a..0000000
--- a/drivers/pinctrl/pinctrl-armada-xp.c
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
- * Marvell Armada XP pinctrl driver based on mvebu pinctrl core
- *
- * Copyright (C) 2012 Marvell
- *
- * Thomas Petazzoni <thomas.petazzoni@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 file supports the three variants of Armada XP SoCs that are
- * available: mv78230, mv78260 and mv78460. From a pin muxing
- * perspective, the mv78230 has 49 MPP pins. The mv78260 and mv78460
- * both have 67 MPP pins (more GPIOs and address lines for the memory
- * bus mainly). The only difference between the mv78260 and the
- * mv78460 in terms of pin muxing is the addition of two functions on
- * pins 43 and 56 to access the VDD of the CPU2 and 3 (mv78260 has two
- * cores, mv78460 has four cores).
- */
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/bitops.h>
-
-#include "pinctrl-mvebu.h"
-
-enum armada_xp_variant {
-	V_MV78230	= BIT(0),
-	V_MV78260	= BIT(1),
-	V_MV78460	= BIT(2),
-	V_MV78230_PLUS	= (V_MV78230 | V_MV78260 | V_MV78460),
-	V_MV78260_PLUS	= (V_MV78260 | V_MV78460),
-};
-
-static struct mvebu_mpp_mode armada_xp_mpp_modes[] = {
-	MPP_MODE(0,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "txclko",     V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d0",         V_MV78230_PLUS)),
-	MPP_MODE(1,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "txd0",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d1",         V_MV78230_PLUS)),
-	MPP_MODE(2,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "txd1",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d2",         V_MV78230_PLUS)),
-	MPP_MODE(3,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "txd2",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d3",         V_MV78230_PLUS)),
-	MPP_MODE(4,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "txd3",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d4",         V_MV78230_PLUS)),
-	MPP_MODE(5,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "txctl",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d5",         V_MV78230_PLUS)),
-	MPP_MODE(6,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "rxd0",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d6",         V_MV78230_PLUS)),
-	MPP_MODE(7,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "rxd1",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d7",         V_MV78230_PLUS)),
-	MPP_MODE(8,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "rxd2",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d8",         V_MV78230_PLUS)),
-	MPP_MODE(9,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "rxd3",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d9",         V_MV78230_PLUS)),
-	MPP_MODE(10,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "rxctl",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d10",        V_MV78230_PLUS)),
-	MPP_MODE(11,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "rxclk",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d11",        V_MV78230_PLUS)),
-	MPP_MODE(12,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "txd4",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "ge1", "clkout",     V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d12",        V_MV78230_PLUS)),
-	MPP_MODE(13,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "txd5",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "ge1", "txd0",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d13",        V_MV78230_PLUS)),
-	MPP_MODE(14,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "txd6",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "ge1", "txd1",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d14",        V_MV78230_PLUS)),
-	MPP_MODE(15,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "txd7",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "ge1", "txd2",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d15",        V_MV78230_PLUS)),
-	MPP_MODE(16,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "txclk",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "ge1", "txd3",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d16",        V_MV78230_PLUS)),
-	MPP_MODE(17,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "col",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "ge1", "txctl",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d17",        V_MV78230_PLUS)),
-	MPP_MODE(18,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "rxerr",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "ge1", "rxd0",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "ptp", "trig",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d18",        V_MV78230_PLUS)),
-	MPP_MODE(19,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "crs",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "ge1", "rxd1",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "ptp", "evreq",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d19",        V_MV78230_PLUS)),
-	MPP_MODE(20,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "rxd4",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "ge1", "rxd2",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "ptp", "clk",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d20",        V_MV78230_PLUS)),
-	MPP_MODE(21,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "rxd5",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "ge1", "rxd3",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "mem", "bat",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d21",        V_MV78230_PLUS)),
-	MPP_MODE(22,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "rxd6",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "ge1", "rxctl",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "sata0", "prsnt",    V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d22",        V_MV78230_PLUS)),
-	MPP_MODE(23,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ge0", "rxd7",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "ge1", "rxclk",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "sata1", "prsnt",    V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "d23",        V_MV78230_PLUS)),
-	MPP_MODE(24,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "sata1", "prsnt",    V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "nf", "bootcs-re",   V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "tdm", "rst",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "hsync",      V_MV78230_PLUS)),
-	MPP_MODE(25,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "sata0", "prsnt",    V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "nf", "bootcs-we",   V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "tdm", "pclk",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "vsync",      V_MV78230_PLUS)),
-	MPP_MODE(26,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "tdm", "fsync",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "clk",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd",    V_MV78230_PLUS)),
-	MPP_MODE(27,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ptp", "trig",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "tdm", "dtx",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "e",          V_MV78230_PLUS)),
-	MPP_MODE(28,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ptp", "evreq",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "tdm", "drx",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "pwm",        V_MV78230_PLUS)),
-	MPP_MODE(29,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "ptp", "clk",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "tdm", "int0",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "ref-clk",    V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd",    V_MV78230_PLUS)),
-	MPP_MODE(30,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "sd0", "clk",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "tdm", "int1",       V_MV78230_PLUS)),
-	MPP_MODE(31,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "sd0", "cmd",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "tdm", "int2",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd",    V_MV78230_PLUS)),
-	MPP_MODE(32,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "sd0", "d0",         V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "tdm", "int3",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd",    V_MV78230_PLUS)),
-	MPP_MODE(33,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "sd0", "d1",         V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "tdm", "int4",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "mem", "bat",        V_MV78230_PLUS)),
-	MPP_MODE(34,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "sd0", "d2",         V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "sata0", "prsnt",    V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "tdm", "int5",       V_MV78230_PLUS)),
-	MPP_MODE(35,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "sd0", "d3",         V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "sata1", "prsnt",    V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "tdm", "int6",       V_MV78230_PLUS)),
-	MPP_MODE(36,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "spi", "mosi",       V_MV78230_PLUS)),
-	MPP_MODE(37,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "spi", "miso",       V_MV78230_PLUS)),
-	MPP_MODE(38,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "spi", "sck",        V_MV78230_PLUS)),
-	MPP_MODE(39,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "spi", "cs0",        V_MV78230_PLUS)),
-	MPP_MODE(40,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "spi", "cs1",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "uart2", "cts",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "vdd", "cpu1-pd",    V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "vga-hsync",  V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x5, "pcie", "clkreq0",   V_MV78230_PLUS)),
-	MPP_MODE(41,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "spi", "cs2",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "uart2", "rts",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "sata1", "prsnt",    V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "lcd", "vga-vsync",  V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x5, "pcie", "clkreq1",   V_MV78230_PLUS)),
-	MPP_MODE(42,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "uart2", "rxd",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "uart0", "cts",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "tdm", "int7",       V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "tdm-1", "timer",    V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd",    V_MV78230_PLUS)),
-	MPP_MODE(43,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "uart2", "txd",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "uart0", "rts",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "spi", "cs3",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "pcie", "rstout",    V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x5, "vdd", "cpu2-3-pd",  V_MV78460)),
-	MPP_MODE(44,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "uart2", "cts",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "uart3", "rxd",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "spi", "cs4",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "mem", "bat",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x5, "pcie", "clkreq2",   V_MV78230_PLUS)),
-	MPP_MODE(45,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "uart2", "rts",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "uart3", "txd",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "spi", "cs5",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "sata1", "prsnt",    V_MV78230_PLUS)),
-	MPP_MODE(46,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "uart3", "rts",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "uart1", "rts",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "spi", "cs6",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "sata0", "prsnt",    V_MV78230_PLUS)),
-	MPP_MODE(47,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "uart3", "cts",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "uart1", "cts",      V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x3, "spi", "cs7",        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "ref", "clkout",     V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x5, "pcie", "clkreq3",   V_MV78230_PLUS)),
-	MPP_MODE(48,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "tclk", NULL,        V_MV78230_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "dev", "burst/last", V_MV78230_PLUS)),
-	MPP_MODE(49,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "we3",        V_MV78260_PLUS)),
-	MPP_MODE(50,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "we2",        V_MV78260_PLUS)),
-	MPP_MODE(51,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "ad16",       V_MV78260_PLUS)),
-	MPP_MODE(52,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "ad17",       V_MV78260_PLUS)),
-	MPP_MODE(53,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "ad18",       V_MV78260_PLUS)),
-	MPP_MODE(54,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "ad19",       V_MV78260_PLUS)),
-	MPP_MODE(55,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "ad20",       V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "vdd", "cpu0-pd",    V_MV78260_PLUS)),
-	MPP_MODE(56,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "ad21",       V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "vdd", "cpu1-pd",    V_MV78260_PLUS)),
-	MPP_MODE(57,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "ad22",       V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x2, "vdd", "cpu2-3-pd",  V_MV78460)),
-	MPP_MODE(58,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "ad23",       V_MV78260_PLUS)),
-	MPP_MODE(59,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "ad24",       V_MV78260_PLUS)),
-	MPP_MODE(60,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "ad25",       V_MV78260_PLUS)),
-	MPP_MODE(61,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "ad26",       V_MV78260_PLUS)),
-	MPP_MODE(62,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "ad27",       V_MV78260_PLUS)),
-	MPP_MODE(63,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "ad28",       V_MV78260_PLUS)),
-	MPP_MODE(64,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "ad29",       V_MV78260_PLUS)),
-	MPP_MODE(65,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "ad30",       V_MV78260_PLUS)),
-	MPP_MODE(66,
-		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
-		 MPP_VAR_FUNCTION(0x1, "dev", "ad31",       V_MV78260_PLUS)),
-};
-
-static struct mvebu_pinctrl_soc_info armada_xp_pinctrl_info;
-
-static struct of_device_id armada_xp_pinctrl_of_match[] __devinitdata = {
-	{
-		.compatible = "marvell,mv78230-pinctrl",
-		.data       = (void *) V_MV78230,
-	},
-	{
-		.compatible = "marvell,mv78260-pinctrl",
-		.data       = (void *) V_MV78260,
-	},
-	{
-		.compatible = "marvell,mv78460-pinctrl",
-		.data       = (void *) V_MV78460,
-	},
-	{ },
-};
-
-static struct mvebu_mpp_ctrl mv78230_mpp_controls[] = {
-	MPP_REG_CTRL(0, 48),
-};
-
-static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = {
-	MPP_GPIO_RANGE(0,   0,  0, 32),
-	MPP_GPIO_RANGE(1,  32, 32, 17),
-};
-
-static struct mvebu_mpp_ctrl mv78260_mpp_controls[] = {
-	MPP_REG_CTRL(0, 66),
-};
-
-static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = {
-	MPP_GPIO_RANGE(0,   0,  0, 32),
-	MPP_GPIO_RANGE(1,  32, 32, 32),
-	MPP_GPIO_RANGE(2,  64, 64,  3),
-};
-
-static struct mvebu_mpp_ctrl mv78460_mpp_controls[] = {
-	MPP_REG_CTRL(0, 66),
-};
-
-static struct pinctrl_gpio_range mv78460_mpp_gpio_ranges[] = {
-	MPP_GPIO_RANGE(0,   0,  0, 32),
-	MPP_GPIO_RANGE(1,  32, 32, 32),
-	MPP_GPIO_RANGE(2,  64, 64,  3),
-};
-
-static int __devinit armada_xp_pinctrl_probe(struct platform_device *pdev)
-{
-	struct mvebu_pinctrl_soc_info *soc = &armada_xp_pinctrl_info;
-	const struct of_device_id *match =
-		of_match_device(armada_xp_pinctrl_of_match, &pdev->dev);
-
-	if (!match)
-		return -ENODEV;
-
-	soc->variant = (unsigned) match->data & 0xff;
-
-	switch (soc->variant) {
-	case V_MV78230:
-		soc->controls = mv78230_mpp_controls;
-		soc->ncontrols = ARRAY_SIZE(mv78230_mpp_controls);
-		soc->modes = armada_xp_mpp_modes;
-		/* We don't necessarily want the full list of the
-		 * armada_xp_mpp_modes, but only the first 'n' ones
-		 * that are available on this SoC */
-		soc->nmodes = mv78230_mpp_controls[0].npins;
-		soc->gpioranges = mv78230_mpp_gpio_ranges;
-		soc->ngpioranges = ARRAY_SIZE(mv78230_mpp_gpio_ranges);
-		break;
-	case V_MV78260:
-		soc->controls = mv78260_mpp_controls;
-		soc->ncontrols = ARRAY_SIZE(mv78260_mpp_controls);
-		soc->modes = armada_xp_mpp_modes;
-		/* We don't necessarily want the full list of the
-		 * armada_xp_mpp_modes, but only the first 'n' ones
-		 * that are available on this SoC */
-		soc->nmodes = mv78260_mpp_controls[0].npins;
-		soc->gpioranges = mv78260_mpp_gpio_ranges;
-		soc->ngpioranges = ARRAY_SIZE(mv78260_mpp_gpio_ranges);
-		break;
-	case V_MV78460:
-		soc->controls = mv78460_mpp_controls;
-		soc->ncontrols = ARRAY_SIZE(mv78460_mpp_controls);
-		soc->modes = armada_xp_mpp_modes;
-		/* We don't necessarily want the full list of the
-		 * armada_xp_mpp_modes, but only the first 'n' ones
-		 * that are available on this SoC */
-		soc->nmodes = mv78460_mpp_controls[0].npins;
-		soc->gpioranges = mv78460_mpp_gpio_ranges;
-		soc->ngpioranges = ARRAY_SIZE(mv78460_mpp_gpio_ranges);
-		break;
-	}
-
-	pdev->dev.platform_data = soc;
-
-	return mvebu_pinctrl_probe(pdev);
-}
-
-static int __devexit armada_xp_pinctrl_remove(struct platform_device *pdev)
-{
-	return mvebu_pinctrl_remove(pdev);
-}
-
-static struct platform_driver armada_xp_pinctrl_driver = {
-	.driver = {
-		.name = "armada-xp-pinctrl",
-		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(armada_xp_pinctrl_of_match),
-	},
-	.probe = armada_xp_pinctrl_probe,
-	.remove = __devexit_p(armada_xp_pinctrl_remove),
-};
-
-module_platform_driver(armada_xp_pinctrl_driver);
-
-MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
-MODULE_DESCRIPTION("Marvell Armada XP pinctrl driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
new file mode 100644
index 0000000..c5e7571
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -0,0 +1,1634 @@
+/*
+ * at91 pinctrl driver based on at91 pinmux core
+ *
+ * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+/* Since we request GPIOs from ourself */
+#include <linux/pinctrl/consumer.h>
+
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/at91_pio.h>
+
+#include "core.h"
+
+#define MAX_NB_GPIO_PER_BANK	32
+
+struct at91_pinctrl_mux_ops;
+
+struct at91_gpio_chip {
+	struct gpio_chip	chip;
+	struct pinctrl_gpio_range range;
+	struct at91_gpio_chip	*next;		/* Bank sharing same clock */
+	int			pioc_hwirq;	/* PIO bank interrupt identifier on AIC */
+	int			pioc_virq;	/* PIO bank Linux virtual interrupt */
+	int			pioc_idx;	/* PIO bank index */
+	void __iomem		*regbase;	/* PIO bank virtual address */
+	struct clk		*clock;		/* associated clock */
+	struct irq_domain	*domain;	/* associated irq domain */
+	struct at91_pinctrl_mux_ops *ops;	/* ops */
+};
+
+#define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip)
+
+static struct at91_gpio_chip *gpio_chips[MAX_GPIO_BANKS];
+
+static int gpio_banks;
+
+#define PULL_UP		(1 << 0)
+#define MULTI_DRIVE	(1 << 1)
+#define DEGLITCH	(1 << 2)
+#define PULL_DOWN	(1 << 3)
+#define DIS_SCHMIT	(1 << 4)
+#define DEBOUNCE	(1 << 16)
+#define DEBOUNCE_VAL_SHIFT	17
+#define DEBOUNCE_VAL	(0x3fff << DEBOUNCE_VAL_SHIFT)
+
+/**
+ * struct at91_pmx_func - describes AT91 pinmux functions
+ * @name: the name of this specific function
+ * @groups: corresponding pin groups
+ * @ngroups: the number of groups
+ */
+struct at91_pmx_func {
+	const char	*name;
+	const char	**groups;
+	unsigned	ngroups;
+};
+
+enum at91_mux {
+	AT91_MUX_GPIO = 0,
+	AT91_MUX_PERIPH_A = 1,
+	AT91_MUX_PERIPH_B = 2,
+	AT91_MUX_PERIPH_C = 3,
+	AT91_MUX_PERIPH_D = 4,
+};
+
+/**
+ * struct at91_pmx_pin - describes an At91 pin mux
+ * @bank: the bank of the pin
+ * @pin: the pin number in the @bank
+ * @mux: the mux mode : gpio or periph_x of the pin i.e. alternate function.
+ * @conf: the configuration of the pin: PULL_UP, MULTIDRIVE etc...
+ */
+struct at91_pmx_pin {
+	uint32_t	bank;
+	uint32_t	pin;
+	enum at91_mux	mux;
+	unsigned long	conf;
+};
+
+/**
+ * struct at91_pin_group - describes an At91 pin group
+ * @name: the name of this specific pin group
+ * @pins_conf: the mux mode for each pin in this group. The size of this
+ *	array is the same as pins.
+ * @pins: an array of discrete physical pins used in this group, taken
+ *	from the driver-local pin enumeration space
+ * @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 at91_pin_group {
+	const char		*name;
+	struct at91_pmx_pin	*pins_conf;
+	unsigned int		*pins;
+	unsigned		npins;
+};
+
+/**
+ * struct at91_pinctrl_mux_ops - describes an At91 mux ops group
+ * on new IP with support for periph C and D the way to mux in
+ * periph A and B has changed
+ * So provide the right call back
+ * if not present means the IP does not support it
+ * @get_periph: return the periph mode configured
+ * @mux_A_periph: mux as periph A
+ * @mux_B_periph: mux as periph B
+ * @mux_C_periph: mux as periph C
+ * @mux_D_periph: mux as periph D
+ * @get_deglitch: get deglitch status
+ * @set_deglitch: enable/disable deglitch
+ * @get_debounce: get debounce status
+ * @set_debounce: enable/disable debounce
+ * @get_pulldown: get pulldown status
+ * @set_pulldown: enable/disable pulldown
+ * @get_schmitt_trig: get schmitt trigger status
+ * @disable_schmitt_trig: disable schmitt trigger
+ * @irq_type: return irq type
+ */
+struct at91_pinctrl_mux_ops {
+	enum at91_mux (*get_periph)(void __iomem *pio, unsigned mask);
+	void (*mux_A_periph)(void __iomem *pio, unsigned mask);
+	void (*mux_B_periph)(void __iomem *pio, unsigned mask);
+	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);
+	bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
+	void (*set_debounce)(void __iomem *pio, unsigned mask, bool in_on, u32 div);
+	bool (*get_pulldown)(void __iomem *pio, unsigned pin);
+	void (*set_pulldown)(void __iomem *pio, unsigned mask, bool in_on);
+	bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
+	void (*disable_schmitt_trig)(void __iomem *pio, unsigned mask);
+	/* irq */
+	int (*irq_type)(struct irq_data *d, unsigned type);
+};
+
+static int gpio_irq_type(struct irq_data *d, unsigned type);
+static int alt_gpio_irq_type(struct irq_data *d, unsigned type);
+
+struct at91_pinctrl {
+	struct device		*dev;
+	struct pinctrl_dev	*pctl;
+
+	int			nbanks;
+
+	uint32_t		*mux_mask;
+	int			nmux;
+
+	struct at91_pmx_func	*functions;
+	int			nfunctions;
+
+	struct at91_pin_group	*groups;
+	int			ngroups;
+
+	struct at91_pinctrl_mux_ops *ops;
+};
+
+static const inline struct at91_pin_group *at91_pinctrl_find_group_by_name(
+				const struct at91_pinctrl *info,
+				const char *name)
+{
+	const struct at91_pin_group *grp = NULL;
+	int i;
+
+	for (i = 0; i < info->ngroups; i++) {
+		if (strcmp(info->groups[i].name, name))
+			continue;
+
+		grp = &info->groups[i];
+		dev_dbg(info->dev, "%s: %d 0:%d\n", name, grp->npins, grp->pins[0]);
+		break;
+	}
+
+	return grp;
+}
+
+static int at91_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->ngroups;
+}
+
+static const char *at91_get_group_name(struct pinctrl_dev *pctldev,
+				       unsigned selector)
+{
+	struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->groups[selector].name;
+}
+
+static int at91_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+			       const unsigned **pins,
+			       unsigned *npins)
+{
+	struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	if (selector >= info->ngroups)
+		return -EINVAL;
+
+	*pins = info->groups[selector].pins;
+	*npins = info->groups[selector].npins;
+
+	return 0;
+}
+
+static void at91_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+		   unsigned offset)
+{
+	seq_printf(s, "%s", dev_name(pctldev->dev));
+}
+
+static int at91_dt_node_to_map(struct pinctrl_dev *pctldev,
+			struct device_node *np,
+			struct pinctrl_map **map, unsigned *num_maps)
+{
+	struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	const struct at91_pin_group *grp;
+	struct pinctrl_map *new_map;
+	struct device_node *parent;
+	int map_num = 1;
+	int i;
+
+	/*
+	 * first find the group of this node and check if we need create
+	 * config maps for pins
+	 */
+	grp = at91_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;
+	}
+
+	map_num += grp->npins;
+	new_map = devm_kzalloc(pctldev->dev, sizeof(*new_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 = 0; i < grp->npins; i++) {
+		new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
+		new_map[i].data.configs.group_or_pin =
+				pin_get_name(pctldev, grp->pins[i]);
+		new_map[i].data.configs.configs = &grp->pins_conf[i].conf;
+		new_map[i].data.configs.num_configs = 1;
+	}
+
+	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 at91_dt_free_map(struct pinctrl_dev *pctldev,
+				struct pinctrl_map *map, unsigned num_maps)
+{
+}
+
+static struct pinctrl_ops at91_pctrl_ops = {
+	.get_groups_count	= at91_get_groups_count,
+	.get_group_name		= at91_get_group_name,
+	.get_group_pins		= at91_get_group_pins,
+	.pin_dbg_show		= at91_pin_dbg_show,
+	.dt_node_to_map		= at91_dt_node_to_map,
+	.dt_free_map		= at91_dt_free_map,
+};
+
+static void __iomem * pin_to_controller(struct at91_pinctrl *info,
+				 unsigned int bank)
+{
+	return gpio_chips[bank]->regbase;
+}
+
+static inline int pin_to_bank(unsigned pin)
+{
+	return pin /= MAX_NB_GPIO_PER_BANK;
+}
+
+static unsigned pin_to_mask(unsigned int pin)
+{
+	return 1 << pin;
+}
+
+static void at91_mux_disable_interrupt(void __iomem *pio, unsigned mask)
+{
+	writel_relaxed(mask, pio + PIO_IDR);
+}
+
+static unsigned at91_mux_get_pullup(void __iomem *pio, unsigned pin)
+{
+	return (readl_relaxed(pio + PIO_PUSR) >> pin) & 0x1;
+}
+
+static void at91_mux_set_pullup(void __iomem *pio, unsigned mask, bool on)
+{
+	writel_relaxed(mask, pio + (on ? PIO_PUER : PIO_PUDR));
+}
+
+static unsigned at91_mux_get_multidrive(void __iomem *pio, unsigned pin)
+{
+	return (readl_relaxed(pio + PIO_MDSR) >> pin) & 0x1;
+}
+
+static void at91_mux_set_multidrive(void __iomem *pio, unsigned mask, bool on)
+{
+	writel_relaxed(mask, pio + (on ? PIO_MDER : PIO_MDDR));
+}
+
+static void at91_mux_set_A_periph(void __iomem *pio, unsigned mask)
+{
+	writel_relaxed(mask, pio + PIO_ASR);
+}
+
+static void at91_mux_set_B_periph(void __iomem *pio, unsigned mask)
+{
+	writel_relaxed(mask, pio + PIO_BSR);
+}
+
+static void at91_mux_pio3_set_A_periph(void __iomem *pio, unsigned mask)
+{
+
+	writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) & ~mask,
+						pio + PIO_ABCDSR1);
+	writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) & ~mask,
+						pio + PIO_ABCDSR2);
+}
+
+static void at91_mux_pio3_set_B_periph(void __iomem *pio, unsigned mask)
+{
+	writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) | mask,
+						pio + PIO_ABCDSR1);
+	writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) & ~mask,
+						pio + PIO_ABCDSR2);
+}
+
+static void at91_mux_pio3_set_C_periph(void __iomem *pio, unsigned mask)
+{
+	writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) & ~mask, pio + PIO_ABCDSR1);
+	writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2);
+}
+
+static void at91_mux_pio3_set_D_periph(void __iomem *pio, unsigned mask)
+{
+	writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) | mask, pio + PIO_ABCDSR1);
+	writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2);
+}
+
+static enum at91_mux at91_mux_pio3_get_periph(void __iomem *pio, unsigned mask)
+{
+	unsigned select;
+
+	if (readl_relaxed(pio + PIO_PSR) & mask)
+		return AT91_MUX_GPIO;
+
+	select = !!(readl_relaxed(pio + PIO_ABCDSR1) & mask);
+	select |= (!!(readl_relaxed(pio + PIO_ABCDSR2) & mask) << 1);
+
+	return select + 1;
+}
+
+static enum at91_mux at91_mux_get_periph(void __iomem *pio, unsigned mask)
+{
+	unsigned select;
+
+	if (readl_relaxed(pio + PIO_PSR) & mask)
+		return AT91_MUX_GPIO;
+
+	select = readl_relaxed(pio + PIO_ABSR) & mask;
+
+	return select + 1;
+}
+
+static bool at91_mux_get_deglitch(void __iomem *pio, unsigned pin)
+{
+	return (__raw_readl(pio + PIO_IFSR) >> pin) & 0x1;
+}
+
+static void at91_mux_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
+{
+	__raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR));
+}
+
+static void at91_mux_pio3_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
+{
+	if (is_on)
+		__raw_writel(mask, pio + PIO_IFSCDR);
+	at91_mux_set_deglitch(pio, mask, is_on);
+}
+
+static bool at91_mux_pio3_get_debounce(void __iomem *pio, unsigned pin, u32 *div)
+{
+	*div = __raw_readl(pio + PIO_SCDR);
+
+	return (__raw_readl(pio + PIO_IFSCSR) >> pin) & 0x1;
+}
+
+static void at91_mux_pio3_set_debounce(void __iomem *pio, unsigned mask,
+				bool is_on, u32 div)
+{
+	if (is_on) {
+		__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);
+	}
+}
+
+static bool at91_mux_pio3_get_pulldown(void __iomem *pio, unsigned pin)
+{
+	return (__raw_readl(pio + PIO_PPDSR) >> pin) & 0x1;
+}
+
+static void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is_on)
+{
+	__raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
+}
+
+static void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio, unsigned mask)
+{
+	__raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
+}
+
+static bool at91_mux_pio3_get_schmitt_trig(void __iomem *pio, unsigned pin)
+{
+	return (__raw_readl(pio + PIO_SCHMITT) >> pin) & 0x1;
+}
+
+static struct at91_pinctrl_mux_ops at91rm9200_ops = {
+	.get_periph	= at91_mux_get_periph,
+	.mux_A_periph	= at91_mux_set_A_periph,
+	.mux_B_periph	= at91_mux_set_B_periph,
+	.get_deglitch	= at91_mux_get_deglitch,
+	.set_deglitch	= at91_mux_set_deglitch,
+	.irq_type	= gpio_irq_type,
+};
+
+static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
+	.get_periph	= at91_mux_pio3_get_periph,
+	.mux_A_periph	= at91_mux_pio3_set_A_periph,
+	.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,
+	.set_deglitch	= at91_mux_pio3_set_deglitch,
+	.get_debounce	= at91_mux_pio3_get_debounce,
+	.set_debounce	= at91_mux_pio3_set_debounce,
+	.get_pulldown	= at91_mux_pio3_get_pulldown,
+	.set_pulldown	= at91_mux_pio3_set_pulldown,
+	.get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
+	.disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
+	.irq_type	= alt_gpio_irq_type,
+};
+
+static void at91_pin_dbg(const struct device *dev, const struct at91_pmx_pin *pin)
+{
+	if (pin->mux) {
+		dev_dbg(dev, "pio%c%d configured as periph%c with conf = 0x%lu\n",
+			pin->bank + 'A', pin->pin, pin->mux - 1 + 'A', pin->conf);
+	} else {
+		dev_dbg(dev, "pio%c%d configured as gpio with conf = 0x%lu\n",
+			pin->bank + 'A', pin->pin, pin->conf);
+	}
+}
+
+static int pin_check_config(struct at91_pinctrl *info, const char* name,
+			    int index, const struct at91_pmx_pin *pin)
+{
+	int mux;
+
+	/* check if it's a valid config */
+	if (pin->bank >= info->nbanks) {
+		dev_err(info->dev, "%s: pin conf %d bank_id %d >= nbanks %d\n",
+			name, index, pin->bank, info->nbanks);
+		return -EINVAL;
+	}
+
+	if (pin->pin >= MAX_NB_GPIO_PER_BANK) {
+		dev_err(info->dev, "%s: pin conf %d pin_bank_id %d >= %d\n",
+			name, index, pin->pin, MAX_NB_GPIO_PER_BANK);
+		return -EINVAL;
+	}
+
+	if (!pin->mux)
+		return 0;
+
+	mux = pin->mux - 1;
+
+	if (mux >= info->nmux) {
+		dev_err(info->dev, "%s: pin conf %d mux_id %d >= nmux %d\n",
+			name, index, mux, info->nmux);
+		return -EINVAL;
+	}
+
+	if (!(info->mux_mask[pin->bank * info->nmux + mux] & 1 << pin->pin)) {
+		dev_err(info->dev, "%s: pin conf %d mux_id %d not supported for pio%c%d\n",
+			name, index, mux, pin->bank + 'A', pin->pin);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void at91_mux_gpio_disable(void __iomem *pio, unsigned mask)
+{
+	writel_relaxed(mask, pio + PIO_PDR);
+}
+
+static void at91_mux_gpio_enable(void __iomem *pio, unsigned mask, bool input)
+{
+	writel_relaxed(mask, pio + PIO_PER);
+	writel_relaxed(mask, pio + (input ? PIO_ODR : PIO_OER));
+}
+
+static int at91_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
+			   unsigned group)
+{
+	struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	const struct at91_pmx_pin *pins_conf = info->groups[group].pins_conf;
+	const struct at91_pmx_pin *pin;
+	uint32_t npins = info->groups[group].npins;
+	int i, ret;
+	unsigned mask;
+	void __iomem *pio;
+
+	dev_dbg(info->dev, "enable function %s group %s\n",
+		info->functions[selector].name, info->groups[group].name);
+
+	/* first check that all the pins of the group are valid with a valid
+	 * paramter */
+	for (i = 0; i < npins; i++) {
+		pin = &pins_conf[i];
+		ret = pin_check_config(info, info->groups[group].name, i, pin);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < npins; i++) {
+		pin = &pins_conf[i];
+		at91_pin_dbg(info->dev, pin);
+		pio = pin_to_controller(info, pin->bank);
+		mask = pin_to_mask(pin->pin);
+		at91_mux_disable_interrupt(pio, mask);
+		switch(pin->mux) {
+		case AT91_MUX_GPIO:
+			at91_mux_gpio_enable(pio, mask, 1);
+			break;
+		case AT91_MUX_PERIPH_A:
+			info->ops->mux_A_periph(pio, mask);
+			break;
+		case AT91_MUX_PERIPH_B:
+			info->ops->mux_B_periph(pio, mask);
+			break;
+		case AT91_MUX_PERIPH_C:
+			if (!info->ops->mux_C_periph)
+				return -EINVAL;
+			info->ops->mux_C_periph(pio, mask);
+			break;
+		case AT91_MUX_PERIPH_D:
+			if (!info->ops->mux_D_periph)
+				return -EINVAL;
+			info->ops->mux_D_periph(pio, mask);
+			break;
+		}
+		if (pin->mux)
+			at91_mux_gpio_disable(pio, mask);
+	}
+
+	return 0;
+}
+
+static void at91_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
+			   unsigned group)
+{
+	struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	const struct at91_pmx_pin *pins_conf = info->groups[group].pins_conf;
+	const struct at91_pmx_pin *pin;
+	uint32_t npins = info->groups[group].npins;
+	int i;
+	unsigned mask;
+	void __iomem *pio;
+
+	for (i = 0; i < npins; i++) {
+		pin = &pins_conf[i];
+		at91_pin_dbg(info->dev, pin);
+		pio = pin_to_controller(info, pin->bank);
+		mask = pin_to_mask(pin->pin);
+		at91_mux_gpio_enable(pio, mask, 1);
+	}
+}
+
+static int at91_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+	struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->nfunctions;
+}
+
+static const char *at91_pmx_get_func_name(struct pinctrl_dev *pctldev,
+					  unsigned selector)
+{
+	struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->functions[selector].name;
+}
+
+static int at91_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+			       const char * const **groups,
+			       unsigned * const num_groups)
+{
+	struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = info->functions[selector].groups;
+	*num_groups = info->functions[selector].ngroups;
+
+	return 0;
+}
+
+static int at91_gpio_request_enable(struct pinctrl_dev *pctldev,
+				    struct pinctrl_gpio_range *range,
+				    unsigned offset)
+{
+	struct at91_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+	struct at91_gpio_chip *at91_chip;
+	struct gpio_chip *chip;
+	unsigned mask;
+
+	if (!range) {
+		dev_err(npct->dev, "invalid range\n");
+		return -EINVAL;
+	}
+	if (!range->gc) {
+		dev_err(npct->dev, "missing GPIO chip in range\n");
+		return -EINVAL;
+	}
+	chip = range->gc;
+	at91_chip = container_of(chip, struct at91_gpio_chip, chip);
+
+	dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset);
+
+	mask = 1 << (offset - chip->base);
+
+	dev_dbg(npct->dev, "enable pin %u as PIO%c%d 0x%x\n",
+		offset, 'A' + range->id, offset - chip->base, mask);
+
+	writel_relaxed(mask, at91_chip->regbase + PIO_PER);
+
+	return 0;
+}
+
+static void at91_gpio_disable_free(struct pinctrl_dev *pctldev,
+				   struct pinctrl_gpio_range *range,
+				   unsigned offset)
+{
+	struct at91_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+
+	dev_dbg(npct->dev, "disable pin %u as GPIO\n", offset);
+	/* Set the pin to some default state, GPIO is usually default */
+}
+
+static struct pinmux_ops at91_pmx_ops = {
+	.get_functions_count	= at91_pmx_get_funcs_count,
+	.get_function_name	= at91_pmx_get_func_name,
+	.get_function_groups	= at91_pmx_get_groups,
+	.enable			= at91_pmx_enable,
+	.disable		= at91_pmx_disable,
+	.gpio_request_enable	= at91_gpio_request_enable,
+	.gpio_disable_free	= at91_gpio_disable_free,
+};
+
+static int at91_pinconf_get(struct pinctrl_dev *pctldev,
+			     unsigned pin_id, unsigned long *config)
+{
+	struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	void __iomem *pio;
+	unsigned pin;
+	int div;
+
+	dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, *config);
+	pio = pin_to_controller(info, pin_to_bank(pin_id));
+	pin = pin_id % MAX_NB_GPIO_PER_BANK;
+
+	if (at91_mux_get_multidrive(pio, pin))
+		*config |= MULTI_DRIVE;
+
+	if (at91_mux_get_pullup(pio, pin))
+		*config |= PULL_UP;
+
+	if (info->ops->get_deglitch && info->ops->get_deglitch(pio, pin))
+		*config |= DEGLITCH;
+	if (info->ops->get_debounce && info->ops->get_debounce(pio, pin, &div))
+		*config |= DEBOUNCE | (div << DEBOUNCE_VAL_SHIFT);
+	if (info->ops->get_pulldown && info->ops->get_pulldown(pio, pin))
+		*config |= PULL_DOWN;
+	if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin))
+		*config |= DIS_SCHMIT;
+
+	return 0;
+}
+
+static int at91_pinconf_set(struct pinctrl_dev *pctldev,
+			     unsigned pin_id, unsigned long config)
+{
+	struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	unsigned mask;
+	void __iomem *pio;
+
+	dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, config);
+	pio = pin_to_controller(info, pin_to_bank(pin_id));
+	mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK);
+
+	if (config & PULL_UP && config & PULL_DOWN)
+		return -EINVAL;
+
+	at91_mux_set_pullup(pio, mask, config & PULL_UP);
+	at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE);
+	if (info->ops->set_deglitch)
+		info->ops->set_deglitch(pio, mask, config & DEGLITCH);
+	if (info->ops->set_debounce)
+		info->ops->set_debounce(pio, mask, config & DEBOUNCE,
+				(config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
+	if (info->ops->set_pulldown)
+		info->ops->set_pulldown(pio, mask, config & PULL_DOWN);
+	if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT)
+		info->ops->disable_schmitt_trig(pio, mask);
+
+	return 0;
+}
+
+static void at91_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+				   struct seq_file *s, unsigned pin_id)
+{
+
+}
+
+static void at91_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+					 struct seq_file *s, unsigned group)
+{
+}
+
+static struct pinconf_ops at91_pinconf_ops = {
+	.pin_config_get			= at91_pinconf_get,
+	.pin_config_set			= at91_pinconf_set,
+	.pin_config_dbg_show		= at91_pinconf_dbg_show,
+	.pin_config_group_dbg_show	= at91_pinconf_group_dbg_show,
+};
+
+static struct pinctrl_desc at91_pinctrl_desc = {
+	.pctlops	= &at91_pctrl_ops,
+	.pmxops		= &at91_pmx_ops,
+	.confops	= &at91_pinconf_ops,
+	.owner		= THIS_MODULE,
+};
+
+static const char *gpio_compat = "atmel,at91rm9200-gpio";
+
+static void __devinit at91_pinctrl_child_count(struct at91_pinctrl *info,
+					      struct device_node *np)
+{
+	struct device_node *child;
+
+	for_each_child_of_node(np, child) {
+		if (of_device_is_compatible(child, gpio_compat)) {
+			info->nbanks++;
+		} else {
+			info->nfunctions++;
+			info->ngroups += of_get_child_count(child);
+		}
+	}
+}
+
+static int __devinit at91_pinctrl_mux_mask(struct at91_pinctrl *info,
+					  struct device_node *np)
+{
+	int ret = 0;
+	int size;
+	const const __be32 *list;
+
+	list = of_get_property(np, "atmel,mux-mask", &size);
+	if (!list) {
+		dev_err(info->dev, "can not read the mux-mask of %d\n", size);
+		return -EINVAL;
+	}
+
+	size /= sizeof(*list);
+	if (!size || size % info->nbanks) {
+		dev_err(info->dev, "wrong mux mask array should be by %d\n", info->nbanks);
+		return -EINVAL;
+	}
+	info->nmux = size / info->nbanks;
+
+	info->mux_mask = devm_kzalloc(info->dev, sizeof(u32) * size, GFP_KERNEL);
+	if (!info->mux_mask) {
+		dev_err(info->dev, "could not alloc mux_mask\n");
+		return -ENOMEM;
+	}
+
+	ret = of_property_read_u32_array(np, "atmel,mux-mask",
+					  info->mux_mask, size);
+	if (ret)
+		dev_err(info->dev, "can not read the mux-mask of %d\n", size);
+	return ret;
+}
+
+static int __devinit at91_pinctrl_parse_groups(struct device_node *np,
+				struct at91_pin_group *grp,
+				struct at91_pinctrl *info,
+				u32 index)
+{
+	struct at91_pmx_pin *pin;
+	int size;
+	const const __be32 *list;
+	int i, j;
+
+	dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
+
+	/* Initialise group */
+	grp->name = np->name;
+
+	/*
+	 * the binding format is atmel,pins = <bank pin mux CONFIG ...>,
+	 * do sanity check and calculate pins number
+	 */
+	list = of_get_property(np, "atmel,pins", &size);
+	/* we do not check return since it's safe node passed down */
+	size /= sizeof(*list);
+	if (!size || size % 4) {
+		dev_err(info->dev, "wrong pins number or pins and configs should be by 4\n");
+		return -EINVAL;
+	}
+
+	grp->npins = size / 4;
+	pin = grp->pins_conf = devm_kzalloc(info->dev, grp->npins * sizeof(struct at91_pmx_pin),
+				GFP_KERNEL);
+	grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
+				GFP_KERNEL);
+	if (!grp->pins_conf || !grp->pins)
+		return -ENOMEM;
+
+	for (i = 0, j = 0; i < size; i += 4, j++) {
+		pin->bank = be32_to_cpu(*list++);
+		pin->pin = be32_to_cpu(*list++);
+		grp->pins[j] = pin->bank * MAX_NB_GPIO_PER_BANK + pin->pin;
+		pin->mux = be32_to_cpu(*list++);
+		pin->conf = be32_to_cpu(*list++);
+
+		at91_pin_dbg(info->dev, pin);
+		pin++;
+	}
+
+	return 0;
+}
+
+static int __devinit at91_pinctrl_parse_functions(struct device_node *np,
+			struct at91_pinctrl *info, u32 index)
+{
+	struct device_node *child;
+	struct at91_pmx_func *func;
+	struct at91_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->ngroups = of_get_child_count(np);
+	if (func->ngroups <= 0) {
+		dev_err(info->dev, "no groups defined\n");
+		return -EINVAL;
+	}
+	func->groups = devm_kzalloc(info->dev,
+			func->ngroups * 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 = at91_pinctrl_parse_groups(child, grp, info, i++);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static struct of_device_id at91_pinctrl_of_match[] __devinitdata = {
+	{ .compatible = "atmel,at91sam9x5-pinctrl", .data = &at91sam9x5_ops },
+	{ .compatible = "atmel,at91rm9200-pinctrl", .data = &at91rm9200_ops },
+	{ /* sentinel */ }
+};
+
+static int __devinit at91_pinctrl_probe_dt(struct platform_device *pdev,
+					   struct at91_pinctrl *info)
+{
+	int ret = 0;
+	int i, j;
+	uint32_t *tmp;
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *child;
+
+	if (!np)
+		return -ENODEV;
+
+	info->dev = &pdev->dev;
+	info->ops = (struct at91_pinctrl_mux_ops*)
+		of_match_device(at91_pinctrl_of_match, &pdev->dev)->data;
+	at91_pinctrl_child_count(info, np);
+
+	if (info->nbanks < 1) {
+		dev_err(&pdev->dev, "you need to specify atleast one gpio-controller\n");
+		return -EINVAL;
+	}
+
+	ret = at91_pinctrl_mux_mask(info, np);
+	if (ret)
+		return ret;
+
+	dev_dbg(&pdev->dev, "nmux = %d\n", info->nmux);
+
+	dev_dbg(&pdev->dev, "mux-mask\n");
+	tmp = info->mux_mask;
+	for (i = 0; i < info->nbanks; i++) {
+		for (j = 0; j < info->nmux; j++, tmp++) {
+			dev_dbg(&pdev->dev, "%d:%d\t0x%x\n", i, j, tmp[0]);
+		}
+	}
+
+	dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+	dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
+	info->functions = devm_kzalloc(&pdev->dev, info->nfunctions * sizeof(struct at91_pmx_func),
+					GFP_KERNEL);
+	if (!info->functions)
+		return -ENOMEM;
+
+	info->groups = devm_kzalloc(&pdev->dev, info->ngroups * sizeof(struct at91_pin_group),
+					GFP_KERNEL);
+	if (!info->groups)
+		return -ENOMEM;
+
+	dev_dbg(&pdev->dev, "nbanks = %d\n", info->nbanks);
+	dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+	dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
+
+	i = 0;
+
+	for_each_child_of_node(np, child) {
+		if (of_device_is_compatible(child, gpio_compat))
+			continue;
+		ret = at91_pinctrl_parse_functions(child, info, i++);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to parse function\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int __devinit at91_pinctrl_probe(struct platform_device *pdev)
+{
+	struct at91_pinctrl *info;
+	struct pinctrl_pin_desc *pdesc;
+	int ret, i, j ,k;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	ret = at91_pinctrl_probe_dt(pdev, info);
+	if (ret)
+		return ret;
+
+	/*
+	 * We need all the GPIO drivers to probe FIRST, or we will not be able
+	 * to obtain references to the struct gpio_chip * for them, and we
+	 * need this to proceed.
+	 */
+	for (i = 0; i < info->nbanks; i++) {
+		if (!gpio_chips[i]) {
+			dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i);
+			devm_kfree(&pdev->dev, info);
+			return -EPROBE_DEFER;
+		}
+	}
+
+	at91_pinctrl_desc.name = dev_name(&pdev->dev);
+	at91_pinctrl_desc.npins = info->nbanks * MAX_NB_GPIO_PER_BANK;
+	at91_pinctrl_desc.pins = pdesc =
+		devm_kzalloc(&pdev->dev, sizeof(*pdesc) * at91_pinctrl_desc.npins, GFP_KERNEL);
+
+	if (!at91_pinctrl_desc.pins)
+		return -ENOMEM;
+
+	for (i = 0 , k = 0; i < info->nbanks; i++) {
+		for (j = 0; j < MAX_NB_GPIO_PER_BANK; j++, k++) {
+			pdesc->number = k;
+			pdesc->name = kasprintf(GFP_KERNEL, "pio%c%d", i + 'A', j);
+			pdesc++;
+		}
+	}
+
+	platform_set_drvdata(pdev, info);
+	info->pctl = pinctrl_register(&at91_pinctrl_desc, &pdev->dev, info);
+
+	if (!info->pctl) {
+		dev_err(&pdev->dev, "could not register AT91 pinctrl driver\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* We will handle a range of GPIO pins */
+	for (i = 0; i < info->nbanks; i++)
+		pinctrl_add_gpio_range(info->pctl, &gpio_chips[i]->range);
+
+	dev_info(&pdev->dev, "initialized AT91 pinctrl driver\n");
+
+	return 0;
+
+err:
+	return ret;
+}
+
+static int __devexit at91_pinctrl_remove(struct platform_device *pdev)
+{
+	struct at91_pinctrl *info = platform_get_drvdata(pdev);
+
+	pinctrl_unregister(info->pctl);
+
+	return 0;
+}
+
+static int at91_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	/*
+	 * Map back to global GPIO space and request muxing, the direction
+	 * parameter does not matter for this controller.
+	 */
+	int gpio = chip->base + offset;
+	int bank = chip->base / chip->ngpio;
+
+	dev_dbg(chip->dev, "%s:%d pio%c%d(%d)\n", __func__, __LINE__,
+		 'A' + bank, offset, gpio);
+
+	return pinctrl_request_gpio(gpio);
+}
+
+static void at91_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	int gpio = chip->base + offset;
+
+	pinctrl_free_gpio(gpio);
+}
+
+static int at91_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+	void __iomem *pio = at91_gpio->regbase;
+	unsigned mask = 1 << offset;
+
+	writel_relaxed(mask, pio + PIO_ODR);
+	return 0;
+}
+
+static int at91_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+	void __iomem *pio = at91_gpio->regbase;
+	unsigned mask = 1 << offset;
+	u32 pdsr;
+
+	pdsr = readl_relaxed(pio + PIO_PDSR);
+	return (pdsr & mask) != 0;
+}
+
+static void at91_gpio_set(struct gpio_chip *chip, unsigned offset,
+				int val)
+{
+	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+	void __iomem *pio = at91_gpio->regbase;
+	unsigned mask = 1 << offset;
+
+	writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR));
+}
+
+static int at91_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+				int val)
+{
+	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+	void __iomem *pio = at91_gpio->regbase;
+	unsigned mask = 1 << offset;
+
+	writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR));
+	writel_relaxed(mask, pio + PIO_OER);
+
+	return 0;
+}
+
+static int at91_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+	int virq;
+
+	if (offset < chip->ngpio)
+		virq = irq_create_mapping(at91_gpio->domain, offset);
+	else
+		virq = -ENXIO;
+
+	dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
+				chip->label, offset + chip->base, virq);
+	return virq;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void at91_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	enum at91_mux mode;
+	int i;
+	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+	void __iomem *pio = at91_gpio->regbase;
+
+	for (i = 0; i < chip->ngpio; i++) {
+		unsigned pin = chip->base + i;
+		unsigned mask = pin_to_mask(pin);
+		const char *gpio_label;
+		u32 pdsr;
+
+		gpio_label = gpiochip_is_requested(chip, i);
+		if (!gpio_label)
+			continue;
+		mode = at91_gpio->ops->get_periph(pio, mask);
+		seq_printf(s, "[%s] GPIO%s%d: ",
+			   gpio_label, chip->label, i);
+		if (mode == AT91_MUX_GPIO) {
+			pdsr = readl_relaxed(pio + PIO_PDSR);
+
+			seq_printf(s, "[gpio] %s\n",
+				   pdsr & mask ?
+				   "set" : "clear");
+		} else {
+			seq_printf(s, "[periph %c]\n",
+				   mode + 'A' - 1);
+		}
+	}
+}
+#else
+#define at91_gpio_dbg_show	NULL
+#endif
+
+/* Several AIC controller irqs are dispatched through this GPIO handler.
+ * To use any AT91_PIN_* as an externally triggered IRQ, first call
+ * at91_set_gpio_input() then maybe enable its glitch filter.
+ * Then just request_irq() with the pin ID; it works like any ARM IRQ
+ * handler.
+ * First implementation always triggers on rising and falling edges
+ * whereas the newer PIO3 can be additionally configured to trigger on
+ * level, edge with any polarity.
+ *
+ * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after
+ * configuring them with at91_set_a_periph() or at91_set_b_periph().
+ * IRQ0..IRQ6 should be configurable, e.g. level vs edge triggering.
+ */
+
+static void gpio_irq_mask(struct irq_data *d)
+{
+	struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
+	void __iomem	*pio = at91_gpio->regbase;
+	unsigned	mask = 1 << d->hwirq;
+
+	if (pio)
+		writel_relaxed(mask, pio + PIO_IDR);
+}
+
+static void gpio_irq_unmask(struct irq_data *d)
+{
+	struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
+	void __iomem	*pio = at91_gpio->regbase;
+	unsigned	mask = 1 << d->hwirq;
+
+	if (pio)
+		writel_relaxed(mask, pio + PIO_IER);
+}
+
+static int gpio_irq_type(struct irq_data *d, unsigned type)
+{
+	switch (type) {
+	case IRQ_TYPE_NONE:
+	case IRQ_TYPE_EDGE_BOTH:
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+/* Alternate irq type for PIO3 support */
+static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
+{
+	struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
+	void __iomem	*pio = at91_gpio->regbase;
+	unsigned	mask = 1 << d->hwirq;
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		writel_relaxed(mask, pio + PIO_ESR);
+		writel_relaxed(mask, pio + PIO_REHLSR);
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		writel_relaxed(mask, pio + PIO_ESR);
+		writel_relaxed(mask, pio + PIO_FELLSR);
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		writel_relaxed(mask, pio + PIO_LSR);
+		writel_relaxed(mask, pio + PIO_FELLSR);
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		writel_relaxed(mask, pio + PIO_LSR);
+		writel_relaxed(mask, pio + PIO_REHLSR);
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		/*
+		 * disable additional interrupt modes:
+		 * fall back to default behavior
+		 */
+		writel_relaxed(mask, pio + PIO_AIMDR);
+		return 0;
+	case IRQ_TYPE_NONE:
+	default:
+		pr_warn("AT91: No type for irq %d\n", gpio_to_irq(d->irq));
+		return -EINVAL;
+	}
+
+	/* enable additional interrupt modes */
+	writel_relaxed(mask, pio + PIO_AIMER);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int gpio_irq_set_wake(struct irq_data *d, unsigned state)
+{
+	struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
+	unsigned	bank = at91_gpio->pioc_idx;
+
+	if (unlikely(bank >= MAX_GPIO_BANKS))
+		return -EINVAL;
+
+	irq_set_irq_wake(at91_gpio->pioc_virq, state);
+
+	return 0;
+}
+#else
+#define gpio_irq_set_wake	NULL
+#endif
+
+static struct irq_chip gpio_irqchip = {
+	.name		= "GPIO",
+	.irq_disable	= gpio_irq_mask,
+	.irq_mask	= gpio_irq_mask,
+	.irq_unmask	= gpio_irq_unmask,
+	/* .irq_set_type is set dynamically */
+	.irq_set_wake	= gpio_irq_set_wake,
+};
+
+static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct irq_data *idata = irq_desc_get_irq_data(desc);
+	struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata);
+	void __iomem	*pio = at91_gpio->regbase;
+	unsigned long	isr;
+	int		n;
+
+	chained_irq_enter(chip, desc);
+	for (;;) {
+		/* Reading ISR acks pending (edge triggered) GPIO interrupts.
+		 * When there none are pending, we're finished unless we need
+		 * to process multiple banks (like ID_PIOCDE on sam9263).
+		 */
+		isr = readl_relaxed(pio + PIO_ISR) & readl_relaxed(pio + PIO_IMR);
+		if (!isr) {
+			if (!at91_gpio->next)
+				break;
+			at91_gpio = at91_gpio->next;
+			pio = at91_gpio->regbase;
+			continue;
+		}
+
+		for_each_set_bit(n, &isr, BITS_PER_LONG) {
+			generic_handle_irq(irq_find_mapping(at91_gpio->domain, n));
+		}
+	}
+	chained_irq_exit(chip, desc);
+	/* now it may re-trigger */
+}
+
+/*
+ * 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 at91_gpio_irq_map(struct irq_domain *h, unsigned int virq,
+							irq_hw_number_t hw)
+{
+	struct at91_gpio_chip	*at91_gpio = h->host_data;
+
+	irq_set_lockdep_class(virq, &gpio_lock_class);
+
+	/*
+	 * Can use the "simple" and not "edge" handler since it's
+	 * shorter, and the AIC handles interrupts sanely.
+	 */
+	irq_set_chip_and_handler(virq, &gpio_irqchip,
+				 handle_simple_irq);
+	set_irq_flags(virq, IRQF_VALID);
+	irq_set_chip_data(virq, at91_gpio);
+
+	return 0;
+}
+
+static int at91_gpio_irq_domain_xlate(struct irq_domain *d,
+				      struct device_node *ctrlr,
+				      const u32 *intspec, unsigned int intsize,
+				      irq_hw_number_t *out_hwirq,
+				      unsigned int *out_type)
+{
+	struct at91_gpio_chip *at91_gpio = d->host_data;
+	int ret;
+	int pin = at91_gpio->chip.base + intspec[0];
+
+	if (WARN_ON(intsize < 2))
+		return -EINVAL;
+	*out_hwirq = intspec[0];
+	*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+
+	ret = gpio_request(pin, ctrlr->full_name);
+	if (ret)
+		return ret;
+
+	ret = gpio_direction_input(pin);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static struct irq_domain_ops at91_gpio_ops = {
+	.map	= at91_gpio_irq_map,
+	.xlate	= at91_gpio_irq_domain_xlate,
+};
+
+static int at91_gpio_of_irq_setup(struct device_node *node,
+				  struct at91_gpio_chip *at91_gpio)
+{
+	struct at91_gpio_chip	*prev = NULL;
+	struct irq_data		*d = irq_get_irq_data(at91_gpio->pioc_virq);
+
+	at91_gpio->pioc_hwirq = irqd_to_hwirq(d);
+
+	/* Setup proper .irq_set_type function */
+	gpio_irqchip.irq_set_type = at91_gpio->ops->irq_type;
+
+	/* Disable irqs of this PIO controller */
+	writel_relaxed(~0, at91_gpio->regbase + PIO_IDR);
+
+	/* Setup irq domain */
+	at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio,
+						&at91_gpio_ops, at91_gpio);
+	if (!at91_gpio->domain)
+		panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n",
+			at91_gpio->pioc_idx);
+
+	/* Setup chained handler */
+	if (at91_gpio->pioc_idx)
+		prev = gpio_chips[at91_gpio->pioc_idx - 1];
+
+	/* The toplevel 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.
+	 */
+	if (prev && prev->next == at91_gpio)
+		return 0;
+
+	irq_set_chip_data(at91_gpio->pioc_virq, at91_gpio);
+	irq_set_chained_handler(at91_gpio->pioc_virq, gpio_irq_handler);
+
+	return 0;
+}
+
+/* This structure is replicated for each GPIO block allocated at probe time */
+static struct gpio_chip at91_gpio_template = {
+	.request		= at91_gpio_request,
+	.free			= at91_gpio_free,
+	.direction_input	= at91_gpio_direction_input,
+	.get			= at91_gpio_get,
+	.direction_output	= at91_gpio_direction_output,
+	.set			= at91_gpio_set,
+	.to_irq			= at91_gpio_to_irq,
+	.dbg_show		= at91_gpio_dbg_show,
+	.can_sleep		= 0,
+	.ngpio			= MAX_NB_GPIO_PER_BANK,
+};
+
+static void __devinit at91_gpio_probe_fixup(void)
+{
+	unsigned i;
+	struct at91_gpio_chip *at91_gpio, *last = NULL;
+
+	for (i = 0; i < gpio_banks; i++) {
+		at91_gpio = gpio_chips[i];
+
+		/*
+		 * GPIO controller are grouped on some SoC:
+		 * PIOC, PIOD and PIOE can share the same IRQ line
+		 */
+		if (last && last->pioc_virq == at91_gpio->pioc_virq)
+			last->next = at91_gpio;
+		last = at91_gpio;
+	}
+}
+
+static struct of_device_id at91_gpio_of_match[] __devinitdata = {
+	{ .compatible = "atmel,at91sam9x5-gpio", .data = &at91sam9x5_ops, },
+	{ .compatible = "atmel,at91rm9200-gpio", .data = &at91rm9200_ops },
+	{ /* sentinel */ }
+};
+
+static int __devinit at91_gpio_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+	struct at91_gpio_chip *at91_chip = NULL;
+	struct gpio_chip *chip;
+	struct pinctrl_gpio_range *range;
+	int ret = 0;
+	int irq, i;
+	int alias_idx = of_alias_get_id(np, "gpio");
+	uint32_t ngpio;
+	char **names;
+
+	BUG_ON(alias_idx >= ARRAY_SIZE(gpio_chips));
+	if (gpio_chips[alias_idx]) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		ret = -ENOENT;
+		goto err;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = irq;
+		goto err;
+	}
+
+	at91_chip = devm_kzalloc(&pdev->dev, sizeof(*at91_chip), GFP_KERNEL);
+	if (!at91_chip) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	at91_chip->regbase = devm_request_and_ioremap(&pdev->dev, res);
+	if (!at91_chip->regbase) {
+		dev_err(&pdev->dev, "failed to map registers, ignoring.\n");
+		ret = -EBUSY;
+		goto err;
+	}
+
+	at91_chip->ops = (struct at91_pinctrl_mux_ops*)
+		of_match_device(at91_gpio_of_match, &pdev->dev)->data;
+	at91_chip->pioc_virq = irq;
+	at91_chip->pioc_idx = alias_idx;
+
+	at91_chip->clock = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(at91_chip->clock)) {
+		dev_err(&pdev->dev, "failed to get clock, ignoring.\n");
+		goto err;
+	}
+
+	if (clk_prepare(at91_chip->clock))
+		goto clk_prep_err;
+
+	/* enable PIO controller's clock */
+	if (clk_enable(at91_chip->clock)) {
+		dev_err(&pdev->dev, "failed to enable clock, ignoring.\n");
+		goto clk_err;
+	}
+
+	at91_chip->chip = at91_gpio_template;
+
+	chip = &at91_chip->chip;
+	chip->of_node = np;
+	chip->label = dev_name(&pdev->dev);
+	chip->dev = &pdev->dev;
+	chip->owner = THIS_MODULE;
+	chip->base = alias_idx * MAX_NB_GPIO_PER_BANK;
+
+	if (!of_property_read_u32(np, "#gpio-lines", &ngpio)) {
+		if (ngpio >= MAX_NB_GPIO_PER_BANK)
+			pr_err("at91_gpio.%d, gpio-nb >= %d failback to %d\n",
+			       alias_idx, MAX_NB_GPIO_PER_BANK, MAX_NB_GPIO_PER_BANK);
+		else
+			chip->ngpio = ngpio;
+	}
+
+	names = devm_kzalloc(&pdev->dev, sizeof(char*) * chip->ngpio, GFP_KERNEL);
+
+	if (!names) {
+		ret = -ENOMEM;
+		goto clk_err;
+	}
+
+	for (i = 0; i < chip->ngpio; i++)
+		names[i] = kasprintf(GFP_KERNEL, "pio%c%d", alias_idx + 'A', i);
+
+	chip->names = (const char*const*)names;
+
+	range = &at91_chip->range;
+	range->name = chip->label;
+	range->id = alias_idx;
+	range->pin_base = range->base = range->id * MAX_NB_GPIO_PER_BANK;
+
+	range->npins = chip->ngpio;
+	range->gc = chip;
+
+	ret = gpiochip_add(chip);
+	if (ret)
+		goto clk_err;
+
+	gpio_chips[alias_idx] = at91_chip;
+	gpio_banks = max(gpio_banks, alias_idx + 1);
+
+	at91_gpio_probe_fixup();
+
+	at91_gpio_of_irq_setup(np, at91_chip);
+
+	dev_info(&pdev->dev, "at address %p\n", at91_chip->regbase);
+
+	return 0;
+
+clk_err:
+	clk_unprepare(at91_chip->clock);
+clk_prep_err:
+	clk_put(at91_chip->clock);
+err:
+	dev_err(&pdev->dev, "Failure %i for GPIO %i\n", ret, alias_idx);
+
+	return ret;
+}
+
+static struct platform_driver at91_gpio_driver = {
+	.driver = {
+		.name = "gpio-at91",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(at91_gpio_of_match),
+	},
+	.probe = at91_gpio_probe,
+};
+
+static struct platform_driver at91_pinctrl_driver = {
+	.driver = {
+		.name = "pinctrl-at91",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(at91_pinctrl_of_match),
+	},
+	.probe = at91_pinctrl_probe,
+	.remove = __devexit_p(at91_pinctrl_remove),
+};
+
+static int __init at91_pinctrl_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&at91_gpio_driver);
+	if (ret)
+		return ret;
+	return platform_driver_register(&at91_pinctrl_driver);
+}
+arch_initcall(at91_pinctrl_init);
+
+static void __exit at91_pinctrl_exit(void)
+{
+	platform_driver_unregister(&at91_pinctrl_driver);
+}
+
+module_exit(at91_pinctrl_exit);
+MODULE_AUTHOR("Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>");
+MODULE_DESCRIPTION("Atmel AT91 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c
index 7e9be18..0b0e9b4 100644
--- a/drivers/pinctrl/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/pinctrl-bcm2835.c
@@ -372,7 +372,7 @@ static int bcm2835_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 	return irq_linear_revmap(pc->irq_domain, offset);
 }
 
-static struct gpio_chip bcm2835_gpio_chip __devinitconst = {
+static struct gpio_chip bcm2835_gpio_chip = {
 	.label = MODULE_NAME,
 	.owner = THIS_MODULE,
 	.request = bcm2835_gpio_request,
@@ -916,7 +916,7 @@ static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev,
 	return 0;
 }
 
-struct pinconf_ops bcm2835_pinconf_ops = {
+static struct pinconf_ops bcm2835_pinconf_ops = {
 	.pin_config_get = bcm2835_pinconf_get,
 	.pin_config_set = bcm2835_pinconf_set,
 };
@@ -931,7 +931,7 @@ static struct pinctrl_desc bcm2835_pinctrl_desc = {
 	.owner = THIS_MODULE,
 };
 
-static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range __devinitconst = {
+static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = {
 	.name = MODULE_NAME,
 	.npins = BCM2835_NUM_GPIOS,
 };
@@ -1042,7 +1042,7 @@ static int __devinit bcm2835_pinctrl_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit bcm2835_pinctrl_remove(struct platform_device *pdev)
+static int bcm2835_pinctrl_remove(struct platform_device *pdev)
 {
 	struct bcm2835_pinctrl *pc = platform_get_drvdata(pdev);
 
@@ -1052,7 +1052,7 @@ static int __devexit bcm2835_pinctrl_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static struct of_device_id bcm2835_pinctrl_match[] __devinitconst = {
+static struct of_device_id bcm2835_pinctrl_match[] = {
 	{ .compatible = "brcm,bcm2835-gpio" },
 	{}
 };
diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c
index b446c96..fbb3715 100644
--- a/drivers/pinctrl/pinctrl-coh901.c
+++ b/drivers/pinctrl/pinctrl-coh901.c
@@ -13,6 +13,7 @@
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/io.h>
+#include <linux/irqdomain.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
@@ -64,10 +65,8 @@ struct u300_gpio {
 	struct gpio_chip chip;
 	struct list_head port_list;
 	struct clk *clk;
-	struct resource *memres;
 	void __iomem *base;
 	struct device *dev;
-	int irq_base;
 	u32 stride;
 	/* Register offsets */
 	u32 pcr;
@@ -83,6 +82,7 @@ struct u300_gpio_port {
 	struct list_head node;
 	struct u300_gpio *gpio;
 	char name[8];
+	struct irq_domain *domain;
 	int irq;
 	int number;
 	u8 toggle_edge_mode;
@@ -314,10 +314,30 @@ static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
 static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
 	struct u300_gpio *gpio = to_u300_gpio(chip);
-	int retirq = gpio->irq_base + offset;
+	int portno = offset >> 3;
+	struct u300_gpio_port *port = NULL;
+	struct list_head *p;
+	int retirq;
 
-	dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d\n", offset,
-		retirq);
+	list_for_each(p, &gpio->port_list) {
+		port = list_entry(p, struct u300_gpio_port, node);
+		if (port->number == portno)
+			break;
+	}
+	if (port == NULL) {
+		dev_err(gpio->dev, "could not locate port for GPIO %d IRQ\n",
+			offset);
+		return -EINVAL;
+	}
+
+	/*
+	 * The local hwirqs on the port are the lower three bits, there
+	 * are exactly 8 IRQs per port since they are 8-bit
+	 */
+	retirq = irq_find_mapping(port->domain, (offset & 0x7));
+
+	dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d from port %d\n",
+		offset, retirq, port->number);
 	return retirq;
 }
 
@@ -467,7 +487,7 @@ static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger)
 {
 	struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
 	struct u300_gpio *gpio = port->gpio;
-	int offset = d->irq - gpio->irq_base;
+	int offset = (port->number << 3) + d->hwirq;
 	u32 val;
 
 	if ((trigger & IRQF_TRIGGER_RISING) &&
@@ -503,10 +523,12 @@ static void u300_gpio_irq_enable(struct irq_data *d)
 {
 	struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
 	struct u300_gpio *gpio = port->gpio;
-	int offset = d->irq - gpio->irq_base;
+	int offset = (port->number << 3) + d->hwirq;
 	u32 val;
 	unsigned long flags;
 
+	dev_dbg(gpio->dev, "enable IRQ for hwirq %lu on port %s, offset %d\n",
+		 d->hwirq, port->name, offset);
 	local_irq_save(flags);
 	val = readl(U300_PIN_REG(offset, ien));
 	writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien));
@@ -517,7 +539,7 @@ static void u300_gpio_irq_disable(struct irq_data *d)
 {
 	struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
 	struct u300_gpio *gpio = port->gpio;
-	int offset = d->irq - gpio->irq_base;
+	int offset = (port->number << 3) + d->hwirq;
 	u32 val;
 	unsigned long flags;
 
@@ -555,8 +577,7 @@ static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 		int irqoffset;
 
 		for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) {
-			int pin_irq = gpio->irq_base + (port->number << 3)
-				+ irqoffset;
+			int pin_irq = irq_find_mapping(port->domain, irqoffset);
 			int offset = pinoffset + irqoffset;
 
 			dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n",
@@ -631,64 +652,86 @@ static inline void u300_gpio_free_ports(struct u300_gpio *gpio)
 	list_for_each_safe(p, n, &gpio->port_list) {
 		port = list_entry(p, struct u300_gpio_port, node);
 		list_del(&port->node);
+		if (port->domain)
+			irq_domain_remove(port->domain);
 		kfree(port);
 	}
 }
 
+/*
+ * Here we map a GPIO in the local gpio_chip pin space to a pin in
+ * the local pinctrl pin space. The pin controller used is
+ * pinctrl-u300.
+ */
+struct coh901_pinpair {
+	unsigned int offset;
+	unsigned int pin_base;
+};
+
+#define COH901_PINRANGE(a, b) { .offset = a, .pin_base = b }
+
+static struct coh901_pinpair coh901_pintable[] = {
+	COH901_PINRANGE(10, 426),
+	COH901_PINRANGE(11, 180),
+	COH901_PINRANGE(12, 165), /* MS/MMC card insertion */
+	COH901_PINRANGE(13, 179),
+	COH901_PINRANGE(14, 178),
+	COH901_PINRANGE(16, 194),
+	COH901_PINRANGE(17, 193),
+	COH901_PINRANGE(18, 192),
+	COH901_PINRANGE(19, 191),
+	COH901_PINRANGE(20, 186),
+	COH901_PINRANGE(21, 185),
+	COH901_PINRANGE(22, 184),
+	COH901_PINRANGE(23, 183),
+	COH901_PINRANGE(24, 182),
+	COH901_PINRANGE(25, 181),
+};
+
 static int __init u300_gpio_probe(struct platform_device *pdev)
 {
 	struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev);
 	struct u300_gpio *gpio;
+	struct resource *memres;
 	int err = 0;
 	int portno;
 	u32 val;
 	u32 ifr;
 	int i;
 
-	gpio = kzalloc(sizeof(struct u300_gpio), GFP_KERNEL);
-	if (gpio == NULL) {
-		dev_err(&pdev->dev, "failed to allocate memory\n");
+	gpio = devm_kzalloc(&pdev->dev, sizeof(struct u300_gpio), GFP_KERNEL);
+	if (gpio == NULL)
 		return -ENOMEM;
-	}
 
 	gpio->chip = u300_gpio_chip;
 	gpio->chip.ngpio = plat->ports * U300_GPIO_PINS_PER_PORT;
-	gpio->irq_base = plat->gpio_irq_base;
 	gpio->chip.dev = &pdev->dev;
 	gpio->chip.base = plat->gpio_base;
 	gpio->dev = &pdev->dev;
 
-	/* Get GPIO clock */
-	gpio->clk = clk_get(gpio->dev, NULL);
+	memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!memres) {
+		dev_err(gpio->dev, "could not get GPIO memory resource\n");
+		return -ENODEV;
+	}
+
+	gpio->base = devm_request_and_ioremap(&pdev->dev, memres);
+	if (!gpio->base) {
+		dev_err(gpio->dev, "could not get remap memory\n");
+		return -ENOMEM;
+	}
+
+	gpio->clk = devm_clk_get(gpio->dev, NULL);
 	if (IS_ERR(gpio->clk)) {
 		err = PTR_ERR(gpio->clk);
 		dev_err(gpio->dev, "could not get GPIO clock\n");
-		goto err_no_clk;
+		return err;
 	}
+
 	err = clk_prepare_enable(gpio->clk);
 	if (err) {
 		dev_err(gpio->dev, "could not enable GPIO clock\n");
-		goto err_no_clk_enable;
-	}
-
-	gpio->memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!gpio->memres) {
-		dev_err(gpio->dev, "could not get GPIO memory resource\n");
-		err = -ENODEV;
-		goto err_no_resource;
-	}
-
-	if (!request_mem_region(gpio->memres->start,
-				resource_size(gpio->memres),
-				"GPIO Controller")) {
-		err = -ENODEV;
-		goto err_no_ioregion;
-	}
-
-	gpio->base = ioremap(gpio->memres->start, resource_size(gpio->memres));
-	if (!gpio->base) {
-		err = -ENOMEM;
-		goto err_no_ioremap;
+		return err;
 	}
 
 	dev_info(gpio->dev,
@@ -732,18 +775,28 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
 		port->irq = platform_get_irq_byname(pdev,
 						    port->name);
 
-		dev_dbg(gpio->dev, "register IRQ %d for %s\n", port->irq,
+		dev_dbg(gpio->dev, "register IRQ %d for port %s\n", port->irq,
 			port->name);
 
+		port->domain = irq_domain_add_linear(pdev->dev.of_node,
+						     U300_GPIO_PINS_PER_PORT,
+						     &irq_domain_simple_ops,
+						     port);
+		if (!port->domain) {
+			err = -ENOMEM;
+			goto err_no_domain;
+		}
+
 		irq_set_chained_handler(port->irq, u300_gpio_irq_handler);
 		irq_set_handler_data(port->irq, port);
 
 		/* For each GPIO pin set the unique IRQ handler */
 		for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) {
-			int irqno = gpio->irq_base + (portno << 3) + i;
+			int irqno = irq_create_mapping(port->domain, i);
 
-			dev_dbg(gpio->dev, "handler for IRQ %d on %s\n",
-				irqno, port->name);
+			dev_dbg(gpio->dev, "GPIO%d on port %s gets IRQ %d\n",
+				gpio->chip.base + (port->number << 3) + i,
+				port->name, irqno);
 			irq_set_chip_and_handler(irqno, &u300_gpio_irqchip,
 						 handle_simple_irq);
 			set_irq_flags(irqno, IRQF_VALID);
@@ -763,32 +816,31 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
 		goto err_no_chip;
 	}
 
-	/* Spawn pin controller device as child of the GPIO, pass gpio chip */
-	plat->pinctrl_device->dev.platform_data = &gpio->chip;
-	err = platform_device_register(plat->pinctrl_device);
-	if (err)
-		goto err_no_pinctrl;
+	/*
+	 * Add pinctrl pin ranges, the pin controller must be registered
+	 * at this point
+	 */
+	for (i = 0; i < ARRAY_SIZE(coh901_pintable); i++) {
+		struct coh901_pinpair *p = &coh901_pintable[i];
+
+		err = gpiochip_add_pin_range(&gpio->chip, "pinctrl-u300",
+					     p->offset, p->pin_base, 1);
+		if (err)
+			goto err_no_range;
+	}
 
 	platform_set_drvdata(pdev, gpio);
 
 	return 0;
 
-err_no_pinctrl:
+err_no_range:
 	err = gpiochip_remove(&gpio->chip);
 err_no_chip:
+err_no_domain:
 err_no_port:
 	u300_gpio_free_ports(gpio);
-	iounmap(gpio->base);
-err_no_ioremap:
-	release_mem_region(gpio->memres->start, resource_size(gpio->memres));
-err_no_ioregion:
-err_no_resource:
 	clk_disable_unprepare(gpio->clk);
-err_no_clk_enable:
-	clk_put(gpio->clk);
-err_no_clk:
-	kfree(gpio);
-	dev_info(&pdev->dev, "module ERROR:%d\n", err);
+	dev_err(&pdev->dev, "module ERROR:%d\n", err);
 	return err;
 }
 
@@ -806,13 +858,8 @@ static int __exit u300_gpio_remove(struct platform_device *pdev)
 		return err;
 	}
 	u300_gpio_free_ports(gpio);
-	iounmap(gpio->base);
-	release_mem_region(gpio->memres->start,
-			   resource_size(gpio->memres));
 	clk_disable_unprepare(gpio->clk);
-	clk_put(gpio->clk);
 	platform_set_drvdata(pdev, NULL);
-	kfree(gpio);
 	return 0;
 }
 
diff --git a/drivers/pinctrl/pinctrl-dove.c b/drivers/pinctrl/pinctrl-dove.c
deleted file mode 100644
index ffe74b2..0000000
--- a/drivers/pinctrl/pinctrl-dove.c
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * Marvell Dove pinctrl driver based on mvebu pinctrl core
- *
- * Author: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/bitops.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/pinctrl/pinctrl.h>
-
-#include "pinctrl-mvebu.h"
-
-#define DOVE_SB_REGS_VIRT_BASE		0xfde00000
-#define DOVE_MPP_VIRT_BASE		(DOVE_SB_REGS_VIRT_BASE | 0xd0200)
-#define DOVE_PMU_MPP_GENERAL_CTRL	(DOVE_MPP_VIRT_BASE + 0x10)
-#define  DOVE_AU0_AC97_SEL		BIT(16)
-#define DOVE_GLOBAL_CONFIG_1		(DOVE_SB_REGS_VIRT_BASE | 0xe802C)
-#define  DOVE_TWSI_ENABLE_OPTION1	BIT(7)
-#define DOVE_GLOBAL_CONFIG_2		(DOVE_SB_REGS_VIRT_BASE | 0xe8030)
-#define  DOVE_TWSI_ENABLE_OPTION2	BIT(20)
-#define  DOVE_TWSI_ENABLE_OPTION3	BIT(21)
-#define  DOVE_TWSI_OPTION3_GPIO		BIT(22)
-#define DOVE_SSP_CTRL_STATUS_1		(DOVE_SB_REGS_VIRT_BASE | 0xe8034)
-#define  DOVE_SSP_ON_AU1		BIT(0)
-#define DOVE_MPP_GENERAL_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xe803c)
-#define  DOVE_AU1_SPDIFO_GPIO_EN	BIT(1)
-#define  DOVE_NAND_GPIO_EN		BIT(0)
-#define DOVE_GPIO_LO_VIRT_BASE		(DOVE_SB_REGS_VIRT_BASE | 0xd0400)
-#define DOVE_MPP_CTRL4_VIRT_BASE	(DOVE_GPIO_LO_VIRT_BASE + 0x40)
-#define  DOVE_SPI_GPIO_SEL		BIT(5)
-#define  DOVE_UART1_GPIO_SEL		BIT(4)
-#define  DOVE_AU1_GPIO_SEL		BIT(3)
-#define  DOVE_CAM_GPIO_SEL		BIT(2)
-#define  DOVE_SD1_GPIO_SEL		BIT(1)
-#define  DOVE_SD0_GPIO_SEL		BIT(0)
-
-#define MPPS_PER_REG	8
-#define MPP_BITS	4
-#define MPP_MASK	0xf
-
-#define CONFIG_PMU	BIT(4)
-
-static int dove_pmu_mpp_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
-				 unsigned long *config)
-{
-	unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS;
-	unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS;
-	unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
-	unsigned long mpp = readl(DOVE_MPP_VIRT_BASE + off);
-
-	if (pmu & (1 << ctrl->pid))
-		*config = CONFIG_PMU;
-	else
-		*config = (mpp >> shift) & MPP_MASK;
-	return 0;
-}
-
-static int dove_pmu_mpp_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
-				 unsigned long config)
-{
-	unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS;
-	unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS;
-	unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
-	unsigned long mpp = readl(DOVE_MPP_VIRT_BASE + off);
-
-	if (config == CONFIG_PMU)
-		writel(pmu | (1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
-	else {
-		writel(pmu & ~(1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
-		mpp &= ~(MPP_MASK << shift);
-		mpp |= config << shift;
-		writel(mpp, DOVE_MPP_VIRT_BASE + off);
-	}
-	return 0;
-}
-
-static int dove_mpp4_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
-			      unsigned long *config)
-{
-	unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
-	unsigned long mask;
-
-	switch (ctrl->pid) {
-	case 24: /* mpp_camera */
-		mask = DOVE_CAM_GPIO_SEL;
-		break;
-	case 40: /* mpp_sdio0 */
-		mask = DOVE_SD0_GPIO_SEL;
-		break;
-	case 46: /* mpp_sdio1 */
-		mask = DOVE_SD1_GPIO_SEL;
-		break;
-	case 58: /* mpp_spi0 */
-		mask = DOVE_SPI_GPIO_SEL;
-		break;
-	case 62: /* mpp_uart1 */
-		mask = DOVE_UART1_GPIO_SEL;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	*config = ((mpp4 & mask) != 0);
-
-	return 0;
-}
-
-static int dove_mpp4_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
-			      unsigned long config)
-{
-	unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
-	unsigned long mask;
-
-	switch (ctrl->pid) {
-	case 24: /* mpp_camera */
-		mask = DOVE_CAM_GPIO_SEL;
-		break;
-	case 40: /* mpp_sdio0 */
-		mask = DOVE_SD0_GPIO_SEL;
-		break;
-	case 46: /* mpp_sdio1 */
-		mask = DOVE_SD1_GPIO_SEL;
-		break;
-	case 58: /* mpp_spi0 */
-		mask = DOVE_SPI_GPIO_SEL;
-		break;
-	case 62: /* mpp_uart1 */
-		mask = DOVE_UART1_GPIO_SEL;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	mpp4 &= ~mask;
-	if (config)
-		mpp4 |= mask;
-
-	writel(mpp4, DOVE_MPP_CTRL4_VIRT_BASE);
-
-	return 0;
-}
-
-static int dove_nand_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
-			      unsigned long *config)
-{
-	unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
-
-	*config = ((gmpp & DOVE_NAND_GPIO_EN) != 0);
-
-	return 0;
-}
-
-static int dove_nand_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
-			      unsigned long config)
-{
-	unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
-
-	gmpp &= ~DOVE_NAND_GPIO_EN;
-	if (config)
-		gmpp |= DOVE_NAND_GPIO_EN;
-
-	writel(gmpp, DOVE_MPP_GENERAL_VIRT_BASE);
-
-	return 0;
-}
-
-static int dove_audio0_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
-				unsigned long *config)
-{
-	unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
-
-	*config = ((pmu & DOVE_AU0_AC97_SEL) != 0);
-
-	return 0;
-}
-
-static int dove_audio0_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
-				unsigned long config)
-{
-	unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
-
-	pmu &= ~DOVE_AU0_AC97_SEL;
-	if (config)
-		pmu |= DOVE_AU0_AC97_SEL;
-	writel(pmu, DOVE_PMU_MPP_GENERAL_CTRL);
-
-	return 0;
-}
-
-static int dove_audio1_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
-				unsigned long *config)
-{
-	unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
-	unsigned long sspc1 = readl(DOVE_SSP_CTRL_STATUS_1);
-	unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
-	unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
-
-	*config = 0;
-	if (mpp4 & DOVE_AU1_GPIO_SEL)
-		*config |= BIT(3);
-	if (sspc1 & DOVE_SSP_ON_AU1)
-		*config |= BIT(2);
-	if (gmpp & DOVE_AU1_SPDIFO_GPIO_EN)
-		*config |= BIT(1);
-	if (gcfg2 & DOVE_TWSI_OPTION3_GPIO)
-		*config |= BIT(0);
-
-	/* SSP/TWSI only if I2S1 not set*/
-	if ((*config & BIT(3)) == 0)
-		*config &= ~(BIT(2) | BIT(0));
-	/* TWSI only if SPDIFO not set*/
-	if ((*config & BIT(1)) == 0)
-		*config &= ~BIT(0);
-	return 0;
-}
-
-static int dove_audio1_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
-				unsigned long config)
-{
-	unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
-	unsigned long sspc1 = readl(DOVE_SSP_CTRL_STATUS_1);
-	unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
-	unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
-
-	if (config & BIT(0))
-		gcfg2 |= DOVE_TWSI_OPTION3_GPIO;
-	if (config & BIT(1))
-		gmpp |= DOVE_AU1_SPDIFO_GPIO_EN;
-	if (config & BIT(2))
-		sspc1 |= DOVE_SSP_ON_AU1;
-	if (config & BIT(3))
-		mpp4 |= DOVE_AU1_GPIO_SEL;
-
-	writel(mpp4, DOVE_MPP_CTRL4_VIRT_BASE);
-	writel(sspc1, DOVE_SSP_CTRL_STATUS_1);
-	writel(gmpp, DOVE_MPP_GENERAL_VIRT_BASE);
-	writel(gcfg2, DOVE_GLOBAL_CONFIG_2);
-
-	return 0;
-}
-
-/* mpp[52:57] gpio pins depend heavily on current config;
- * gpio_req does not try to mux in gpio capabilities to not
- * break other functions. If you require all mpps as gpio
- * enforce gpio setting by pinctrl mapping.
- */
-static int dove_audio1_ctrl_gpio_req(struct mvebu_mpp_ctrl *ctrl, u8 pid)
-{
-	unsigned long config;
-
-	dove_audio1_ctrl_get(ctrl, &config);
-
-	switch (config) {
-	case 0x02: /* i2s1 : gpio[56:57] */
-	case 0x0e: /* ssp  : gpio[56:57] */
-		if (pid >= 56)
-			return 0;
-		return -ENOTSUPP;
-	case 0x08: /* spdifo : gpio[52:55] */
-	case 0x0b: /* twsi   : gpio[52:55] */
-		if (pid <= 55)
-			return 0;
-		return -ENOTSUPP;
-	case 0x0a: /* all gpio */
-		return 0;
-	/* 0x00 : i2s1/spdifo : no gpio */
-	/* 0x0c : ssp/spdifo  : no gpio */
-	/* 0x0f : ssp/twsi    : no gpio */
-	}
-	return -ENOTSUPP;
-}
-
-/* mpp[52:57] has gpio pins capable of in and out */
-static int dove_audio1_ctrl_gpio_dir(struct mvebu_mpp_ctrl *ctrl, u8 pid,
-				bool input)
-{
-	if (pid < 52 || pid > 57)
-		return -ENOTSUPP;
-	return 0;
-}
-
-static int dove_twsi_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
-			      unsigned long *config)
-{
-	unsigned long gcfg1 = readl(DOVE_GLOBAL_CONFIG_1);
-	unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
-
-	*config = 0;
-	if (gcfg1 & DOVE_TWSI_ENABLE_OPTION1)
-		*config = 1;
-	else if (gcfg2 & DOVE_TWSI_ENABLE_OPTION2)
-		*config = 2;
-	else if (gcfg2 & DOVE_TWSI_ENABLE_OPTION3)
-		*config = 3;
-
-	return 0;
-}
-
-static int dove_twsi_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
-				unsigned long config)
-{
-	unsigned long gcfg1 = readl(DOVE_GLOBAL_CONFIG_1);
-	unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
-
-	gcfg1 &= ~DOVE_TWSI_ENABLE_OPTION1;
-	gcfg2 &= ~(DOVE_TWSI_ENABLE_OPTION2 | DOVE_TWSI_ENABLE_OPTION2);
-
-	switch (config) {
-	case 1:
-		gcfg1 |= DOVE_TWSI_ENABLE_OPTION1;
-		break;
-	case 2:
-		gcfg2 |= DOVE_TWSI_ENABLE_OPTION2;
-		break;
-	case 3:
-		gcfg2 |= DOVE_TWSI_ENABLE_OPTION3;
-		break;
-	}
-
-	writel(gcfg1, DOVE_GLOBAL_CONFIG_1);
-	writel(gcfg2, DOVE_GLOBAL_CONFIG_2);
-
-	return 0;
-}
-
-static struct mvebu_mpp_ctrl dove_mpp_controls[] = {
-	MPP_FUNC_CTRL(0, 0, "mpp0", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(1, 1, "mpp1", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(2, 2, "mpp2", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(3, 3, "mpp3", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(4, 4, "mpp4", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(5, 5, "mpp5", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(6, 6, "mpp6", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(7, 7, "mpp7", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(8, 8, "mpp8", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(9, 9, "mpp9", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(10, 10, "mpp10", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(11, 11, "mpp11", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(12, 12, "mpp12", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(13, 13, "mpp13", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(14, 14, "mpp14", dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(15, 15, "mpp15", dove_pmu_mpp_ctrl),
-	MPP_REG_CTRL(16, 23),
-	MPP_FUNC_CTRL(24, 39, "mpp_camera", dove_mpp4_ctrl),
-	MPP_FUNC_CTRL(40, 45, "mpp_sdio0", dove_mpp4_ctrl),
-	MPP_FUNC_CTRL(46, 51, "mpp_sdio1", dove_mpp4_ctrl),
-	MPP_FUNC_GPIO_CTRL(52, 57, "mpp_audio1", dove_audio1_ctrl),
-	MPP_FUNC_CTRL(58, 61, "mpp_spi0", dove_mpp4_ctrl),
-	MPP_FUNC_CTRL(62, 63, "mpp_uart1", dove_mpp4_ctrl),
-	MPP_FUNC_CTRL(64, 71, "mpp_nand", dove_nand_ctrl),
-	MPP_FUNC_CTRL(72, 72, "audio0", dove_audio0_ctrl),
-	MPP_FUNC_CTRL(73, 73, "twsi", dove_twsi_ctrl),
-};
-
-static struct mvebu_mpp_mode dove_mpp_modes[] = {
-	MPP_MODE(0,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x02, "uart2", "rts"),
-		MPP_FUNCTION(0x03, "sdio0", "cd"),
-		MPP_FUNCTION(0x0f, "lcd0", "pwm"),
-		MPP_FUNCTION(0x10, "pmu", NULL)),
-	MPP_MODE(1,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x02, "uart2", "cts"),
-		MPP_FUNCTION(0x03, "sdio0", "wp"),
-		MPP_FUNCTION(0x0f, "lcd1", "pwm"),
-		MPP_FUNCTION(0x10, "pmu", NULL)),
-	MPP_MODE(2,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x01, "sata", "prsnt"),
-		MPP_FUNCTION(0x02, "uart2", "txd"),
-		MPP_FUNCTION(0x03, "sdio0", "buspwr"),
-		MPP_FUNCTION(0x04, "uart1", "rts"),
-		MPP_FUNCTION(0x10, "pmu", NULL)),
-	MPP_MODE(3,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x01, "sata", "act"),
-		MPP_FUNCTION(0x02, "uart2", "rxd"),
-		MPP_FUNCTION(0x03, "sdio0", "ledctrl"),
-		MPP_FUNCTION(0x04, "uart1", "cts"),
-		MPP_FUNCTION(0x0f, "lcd-spi", "cs1"),
-		MPP_FUNCTION(0x10, "pmu", NULL)),
-	MPP_MODE(4,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x02, "uart3", "rts"),
-		MPP_FUNCTION(0x03, "sdio1", "cd"),
-		MPP_FUNCTION(0x04, "spi1", "miso"),
-		MPP_FUNCTION(0x10, "pmu", NULL)),
-	MPP_MODE(5,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x02, "uart3", "cts"),
-		MPP_FUNCTION(0x03, "sdio1", "wp"),
-		MPP_FUNCTION(0x04, "spi1", "cs"),
-		MPP_FUNCTION(0x10, "pmu", NULL)),
-	MPP_MODE(6,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x02, "uart3", "txd"),
-		MPP_FUNCTION(0x03, "sdio1", "buspwr"),
-		MPP_FUNCTION(0x04, "spi1", "mosi"),
-		MPP_FUNCTION(0x10, "pmu", NULL)),
-	MPP_MODE(7,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x02, "uart3", "rxd"),
-		MPP_FUNCTION(0x03, "sdio1", "ledctrl"),
-		MPP_FUNCTION(0x04, "spi1", "sck"),
-		MPP_FUNCTION(0x10, "pmu", NULL)),
-	MPP_MODE(8,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x01, "watchdog", "rstout"),
-		MPP_FUNCTION(0x10, "pmu", NULL)),
-	MPP_MODE(9,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x05, "pex1", "clkreq"),
-		MPP_FUNCTION(0x10, "pmu", NULL)),
-	MPP_MODE(10,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x05, "ssp", "sclk"),
-		MPP_FUNCTION(0x10, "pmu", NULL)),
-	MPP_MODE(11,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x01, "sata", "prsnt"),
-		MPP_FUNCTION(0x02, "sata-1", "act"),
-		MPP_FUNCTION(0x03, "sdio0", "ledctrl"),
-		MPP_FUNCTION(0x04, "sdio1", "ledctrl"),
-		MPP_FUNCTION(0x05, "pex0", "clkreq"),
-		MPP_FUNCTION(0x10, "pmu", NULL)),
-	MPP_MODE(12,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x01, "sata", "act"),
-		MPP_FUNCTION(0x02, "uart2", "rts"),
-		MPP_FUNCTION(0x03, "audio0", "extclk"),
-		MPP_FUNCTION(0x04, "sdio1", "cd"),
-		MPP_FUNCTION(0x10, "pmu", NULL)),
-	MPP_MODE(13,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x02, "uart2", "cts"),
-		MPP_FUNCTION(0x03, "audio1", "extclk"),
-		MPP_FUNCTION(0x04, "sdio1", "wp"),
-		MPP_FUNCTION(0x05, "ssp", "extclk"),
-		MPP_FUNCTION(0x10, "pmu", NULL)),
-	MPP_MODE(14,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x02, "uart2", "txd"),
-		MPP_FUNCTION(0x04, "sdio1", "buspwr"),
-		MPP_FUNCTION(0x05, "ssp", "rxd"),
-		MPP_FUNCTION(0x10, "pmu", NULL)),
-	MPP_MODE(15,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x02, "uart2", "rxd"),
-		MPP_FUNCTION(0x04, "sdio1", "ledctrl"),
-		MPP_FUNCTION(0x05, "ssp", "sfrm"),
-		MPP_FUNCTION(0x10, "pmu", NULL)),
-	MPP_MODE(16,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x02, "uart3", "rts"),
-		MPP_FUNCTION(0x03, "sdio0", "cd"),
-		MPP_FUNCTION(0x04, "lcd-spi", "cs1"),
-		MPP_FUNCTION(0x05, "ac97", "sdi1")),
-	MPP_MODE(17,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x01, "ac97-1", "sysclko"),
-		MPP_FUNCTION(0x02, "uart3", "cts"),
-		MPP_FUNCTION(0x03, "sdio0", "wp"),
-		MPP_FUNCTION(0x04, "twsi", "sda"),
-		MPP_FUNCTION(0x05, "ac97", "sdi2")),
-	MPP_MODE(18,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x02, "uart3", "txd"),
-		MPP_FUNCTION(0x03, "sdio0", "buspwr"),
-		MPP_FUNCTION(0x04, "lcd0", "pwm"),
-		MPP_FUNCTION(0x05, "ac97", "sdi3")),
-	MPP_MODE(19,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x02, "uart3", "rxd"),
-		MPP_FUNCTION(0x03, "sdio0", "ledctrl"),
-		MPP_FUNCTION(0x04, "twsi", "sck")),
-	MPP_MODE(20,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x01, "ac97", "sysclko"),
-		MPP_FUNCTION(0x02, "lcd-spi", "miso"),
-		MPP_FUNCTION(0x03, "sdio1", "cd"),
-		MPP_FUNCTION(0x05, "sdio0", "cd"),
-		MPP_FUNCTION(0x06, "spi1", "miso")),
-	MPP_MODE(21,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x01, "uart1", "rts"),
-		MPP_FUNCTION(0x02, "lcd-spi", "cs0"),
-		MPP_FUNCTION(0x03, "sdio1", "wp"),
-		MPP_FUNCTION(0x04, "ssp", "sfrm"),
-		MPP_FUNCTION(0x05, "sdio0", "wp"),
-		MPP_FUNCTION(0x06, "spi1", "cs")),
-	MPP_MODE(22,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x01, "uart1", "cts"),
-		MPP_FUNCTION(0x02, "lcd-spi", "mosi"),
-		MPP_FUNCTION(0x03, "sdio1", "buspwr"),
-		MPP_FUNCTION(0x04, "ssp", "txd"),
-		MPP_FUNCTION(0x05, "sdio0", "buspwr"),
-		MPP_FUNCTION(0x06, "spi1", "mosi")),
-	MPP_MODE(23,
-		MPP_FUNCTION(0x00, "gpio", NULL),
-		MPP_FUNCTION(0x02, "lcd-spi", "sck"),
-		MPP_FUNCTION(0x03, "sdio1", "ledctrl"),
-		MPP_FUNCTION(0x04, "ssp", "sclk"),
-		MPP_FUNCTION(0x05, "sdio0", "ledctrl"),
-		MPP_FUNCTION(0x06, "spi1", "sck")),
-	MPP_MODE(24,
-		MPP_FUNCTION(0x00, "camera", NULL),
-		MPP_FUNCTION(0x01, "gpio", NULL)),
-	MPP_MODE(40,
-		MPP_FUNCTION(0x00, "sdio0", NULL),
-		MPP_FUNCTION(0x01, "gpio", NULL)),
-	MPP_MODE(46,
-		MPP_FUNCTION(0x00, "sdio1", NULL),
-		MPP_FUNCTION(0x01, "gpio", NULL)),
-	MPP_MODE(52,
-		MPP_FUNCTION(0x00, "i2s1/spdifo", NULL),
-		MPP_FUNCTION(0x02, "i2s1", NULL),
-		MPP_FUNCTION(0x08, "spdifo", NULL),
-		MPP_FUNCTION(0x0a, "gpio", NULL),
-		MPP_FUNCTION(0x0b, "twsi", NULL),
-		MPP_FUNCTION(0x0c, "ssp/spdifo", NULL),
-		MPP_FUNCTION(0x0e, "ssp", NULL),
-		MPP_FUNCTION(0x0f, "ssp/twsi", NULL)),
-	MPP_MODE(58,
-		MPP_FUNCTION(0x00, "spi0", NULL),
-		MPP_FUNCTION(0x01, "gpio", NULL)),
-	MPP_MODE(62,
-		MPP_FUNCTION(0x00, "uart1", NULL),
-		MPP_FUNCTION(0x01, "gpio", NULL)),
-	MPP_MODE(64,
-		MPP_FUNCTION(0x00, "nand", NULL),
-		MPP_FUNCTION(0x01, "gpo", NULL)),
-	MPP_MODE(72,
-		MPP_FUNCTION(0x00, "i2s", NULL),
-		MPP_FUNCTION(0x01, "ac97", NULL)),
-	MPP_MODE(73,
-		MPP_FUNCTION(0x00, "twsi-none", NULL),
-		MPP_FUNCTION(0x01, "twsi-opt1", NULL),
-		MPP_FUNCTION(0x02, "twsi-opt2", NULL),
-		MPP_FUNCTION(0x03, "twsi-opt3", NULL)),
-};
-
-static struct pinctrl_gpio_range dove_mpp_gpio_ranges[] = {
-	MPP_GPIO_RANGE(0,  0,  0, 32),
-	MPP_GPIO_RANGE(1, 32, 32, 32),
-	MPP_GPIO_RANGE(2, 64, 64,  8),
-};
-
-static struct mvebu_pinctrl_soc_info dove_pinctrl_info = {
-	.controls = dove_mpp_controls,
-	.ncontrols = ARRAY_SIZE(dove_mpp_controls),
-	.modes = dove_mpp_modes,
-	.nmodes = ARRAY_SIZE(dove_mpp_modes),
-	.gpioranges = dove_mpp_gpio_ranges,
-	.ngpioranges = ARRAY_SIZE(dove_mpp_gpio_ranges),
-	.variant = 0,
-};
-
-static struct clk *clk;
-
-static struct of_device_id dove_pinctrl_of_match[] __devinitdata = {
-	{ .compatible = "marvell,dove-pinctrl", .data = &dove_pinctrl_info },
-	{ }
-};
-
-static int __devinit dove_pinctrl_probe(struct platform_device *pdev)
-{
-	const struct of_device_id *match =
-		of_match_device(dove_pinctrl_of_match, &pdev->dev);
-	pdev->dev.platform_data = match->data;
-
-	/*
-	 * General MPP Configuration Register is part of pdma registers.
-	 * grab clk to make sure it is ticking.
-	 */
-	clk = devm_clk_get(&pdev->dev, NULL);
-	if (!IS_ERR(clk))
-		clk_prepare_enable(clk);
-
-	return mvebu_pinctrl_probe(pdev);
-}
-
-static int __devexit dove_pinctrl_remove(struct platform_device *pdev)
-{
-	int ret;
-
-	ret = mvebu_pinctrl_remove(pdev);
-	if (!IS_ERR(clk))
-		clk_disable_unprepare(clk);
-	return ret;
-}
-
-static struct platform_driver dove_pinctrl_driver = {
-	.driver = {
-		.name = "dove-pinctrl",
-		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(dove_pinctrl_of_match),
-	},
-	.probe = dove_pinctrl_probe,
-	.remove = __devexit_p(dove_pinctrl_remove),
-};
-
-module_platform_driver(dove_pinctrl_driver);
-
-MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
-MODULE_DESCRIPTION("Marvell Dove pinctrl driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
index 21362f4..538b9dd 100644
--- a/drivers/pinctrl/pinctrl-exynos.c
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -36,50 +36,51 @@
 /* list of external wakeup controllers supported */
 static const struct of_device_id exynos_wkup_irq_ids[] = {
 	{ .compatible = "samsung,exynos4210-wakeup-eint", },
+	{ }
 };
 
 static void exynos_gpio_irq_unmask(struct irq_data *irqd)
 {
-	struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
-	struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
-	unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset;
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
 	unsigned long mask;
 
 	mask = readl(d->virt_base + reg_mask);
-	mask &= ~(1 << edata->pin);
+	mask &= ~(1 << irqd->hwirq);
 	writel(mask, d->virt_base + reg_mask);
 }
 
 static void exynos_gpio_irq_mask(struct irq_data *irqd)
 {
-	struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
-	struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
-	unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset;
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
 	unsigned long mask;
 
 	mask = readl(d->virt_base + reg_mask);
-	mask |= 1 << edata->pin;
+	mask |= 1 << irqd->hwirq;
 	writel(mask, d->virt_base + reg_mask);
 }
 
 static void exynos_gpio_irq_ack(struct irq_data *irqd)
 {
-	struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
-	struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
-	unsigned long reg_pend = d->ctrl->geint_pend + edata->eint_offset;
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned long reg_pend = d->ctrl->geint_pend + bank->eint_offset;
 
-	writel(1 << edata->pin, d->virt_base + reg_pend);
+	writel(1 << irqd->hwirq, d->virt_base + reg_pend);
 }
 
 static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
 {
-	struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
 	struct samsung_pin_ctrl *ctrl = d->ctrl;
-	struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
-	struct samsung_pin_bank *bank = edata->bank;
-	unsigned int shift = EXYNOS_EINT_CON_LEN * edata->pin;
+	unsigned int pin = irqd->hwirq;
+	unsigned int shift = EXYNOS_EINT_CON_LEN * pin;
 	unsigned int con, trig_type;
-	unsigned long reg_con = ctrl->geint_con + edata->eint_offset;
+	unsigned long reg_con = ctrl->geint_con + bank->eint_offset;
 	unsigned int mask;
 
 	switch (type) {
@@ -114,7 +115,7 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
 	writel(con, d->virt_base + reg_con);
 
 	reg_con = bank->pctl_offset;
-	shift = edata->pin * bank->func_width;
+	shift = pin * bank->func_width;
 	mask = (1 << bank->func_width) - 1;
 
 	con = readl(d->virt_base + reg_con);
@@ -136,82 +137,23 @@ static struct irq_chip exynos_gpio_irq_chip = {
 	.irq_set_type	= exynos_gpio_irq_set_type,
 };
 
-/*
- * given a controller-local external gpio interrupt number, prepare the handler
- * data for it.
- */
-static struct exynos_geint_data *exynos_get_eint_data(irq_hw_number_t hw,
-				struct samsung_pinctrl_drv_data *d)
-{
-	struct samsung_pin_bank *bank = d->ctrl->pin_banks;
-	struct exynos_geint_data *eint_data;
-	unsigned int nr_banks = d->ctrl->nr_banks, idx;
-	unsigned int irq_base = 0, eint_offset = 0;
-
-	if (hw >= d->ctrl->nr_gint) {
-		dev_err(d->dev, "unsupported ext-gpio interrupt\n");
-		return NULL;
-	}
-
-	for (idx = 0; idx < nr_banks; idx++, bank++) {
-		if (bank->eint_type != EINT_TYPE_GPIO)
-			continue;
-		if ((hw >= irq_base) && (hw < (irq_base + bank->nr_pins)))
-			break;
-		irq_base += bank->nr_pins;
-		eint_offset += 4;
-	}
-
-	if (idx == nr_banks) {
-		dev_err(d->dev, "pin bank not found for ext-gpio interrupt\n");
-		return NULL;
-	}
-
-	eint_data = devm_kzalloc(d->dev, sizeof(*eint_data), GFP_KERNEL);
-	if (!eint_data) {
-		dev_err(d->dev, "no memory for eint-gpio data\n");
-		return NULL;
-	}
-
-	eint_data->bank	= bank;
-	eint_data->pin = hw - irq_base;
-	eint_data->eint_offset = eint_offset;
-	return eint_data;
-}
-
 static int exynos_gpio_irq_map(struct irq_domain *h, unsigned int virq,
 					irq_hw_number_t hw)
 {
-	struct samsung_pinctrl_drv_data *d = h->host_data;
-	struct exynos_geint_data *eint_data;
-
-	eint_data = exynos_get_eint_data(hw, d);
-	if (!eint_data)
-		return -EINVAL;
+	struct samsung_pin_bank *b = h->host_data;
 
-	irq_set_handler_data(virq, eint_data);
-	irq_set_chip_data(virq, h->host_data);
+	irq_set_chip_data(virq, b);
 	irq_set_chip_and_handler(virq, &exynos_gpio_irq_chip,
 					handle_level_irq);
 	set_irq_flags(virq, IRQF_VALID);
 	return 0;
 }
 
-static void exynos_gpio_irq_unmap(struct irq_domain *h, unsigned int virq)
-{
-	struct samsung_pinctrl_drv_data *d = h->host_data;
-	struct exynos_geint_data *eint_data;
-
-	eint_data = irq_get_handler_data(virq);
-	devm_kfree(d->dev, eint_data);
-}
-
 /*
  * irq domain callbacks for external gpio interrupt controller.
  */
 static const struct irq_domain_ops exynos_gpio_irqd_ops = {
 	.map	= exynos_gpio_irq_map,
-	.unmap	= exynos_gpio_irq_unmap,
 	.xlate	= irq_domain_xlate_twocell,
 };
 
@@ -230,7 +172,7 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
 		return IRQ_HANDLED;
 	bank += (group - 1);
 
-	virq = irq_linear_revmap(d->gpio_irqd, bank->irq_base + pin);
+	virq = irq_linear_revmap(bank->irq_domain, pin);
 	if (!virq)
 		return IRQ_NONE;
 	generic_handle_irq(virq);
@@ -243,8 +185,10 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
  */
 static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
 {
+	struct samsung_pin_bank *bank;
 	struct device *dev = d->dev;
 	unsigned int ret;
+	unsigned int i;
 
 	if (!d->irq) {
 		dev_err(dev, "irq number not available\n");
@@ -258,11 +202,16 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
 		return -ENXIO;
 	}
 
-	d->gpio_irqd = irq_domain_add_linear(dev->of_node, d->ctrl->nr_gint,
-				&exynos_gpio_irqd_ops, d);
-	if (!d->gpio_irqd) {
-		dev_err(dev, "gpio irq domain allocation failed\n");
-		return -ENXIO;
+	bank = d->ctrl->pin_banks;
+	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+		if (bank->eint_type != EINT_TYPE_GPIO)
+			continue;
+		bank->irq_domain = irq_domain_add_linear(bank->of_node,
+				bank->nr_pins, &exynos_gpio_irqd_ops, bank);
+		if (!bank->irq_domain) {
+			dev_err(dev, "gpio irq domain add failed\n");
+			return -ENXIO;
+		}
 	}
 
 	return 0;
@@ -270,48 +219,46 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
 
 static void exynos_wkup_irq_unmask(struct irq_data *irqd)
 {
-	struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
-	unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
-	unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
-	unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2);
+	struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = b->drvdata;
+	unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
 	unsigned long mask;
 
 	mask = readl(d->virt_base + reg_mask);
-	mask &= ~(1 << pin);
+	mask &= ~(1 << irqd->hwirq);
 	writel(mask, d->virt_base + reg_mask);
 }
 
 static void exynos_wkup_irq_mask(struct irq_data *irqd)
 {
-	struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
-	unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
-	unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
-	unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2);
+	struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = b->drvdata;
+	unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
 	unsigned long mask;
 
 	mask = readl(d->virt_base + reg_mask);
-	mask |= 1 << pin;
+	mask |= 1 << irqd->hwirq;
 	writel(mask, d->virt_base + reg_mask);
 }
 
 static void exynos_wkup_irq_ack(struct irq_data *irqd)
 {
-	struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
-	unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
-	unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
-	unsigned long pend = d->ctrl->weint_pend + (bank << 2);
+	struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = b->drvdata;
+	unsigned long pend = d->ctrl->weint_pend + b->eint_offset;
 
-	writel(1 << pin, d->virt_base + pend);
+	writel(1 << irqd->hwirq, d->virt_base + pend);
 }
 
 static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
 {
-	struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
-	unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
-	unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
-	unsigned long reg_con = d->ctrl->weint_con + (bank << 2);
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned int pin = irqd->hwirq;
+	unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset;
 	unsigned long shift = EXYNOS_EINT_CON_LEN * pin;
 	unsigned long con, trig_type;
+	unsigned int mask;
 
 	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
@@ -343,6 +290,16 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
 	con &= ~(EXYNOS_EINT_CON_MASK << shift);
 	con |= trig_type << shift;
 	writel(con, d->virt_base + reg_con);
+
+	reg_con = bank->pctl_offset;
+	shift = pin * bank->func_width;
+	mask = (1 << bank->func_width) - 1;
+
+	con = readl(d->virt_base + reg_con);
+	con &= ~(mask << shift);
+	con |= EXYNOS_EINT_FUNC << shift;
+	writel(con, d->virt_base + reg_con);
+
 	return 0;
 }
 
@@ -361,6 +318,7 @@ static struct irq_chip exynos_wkup_irq_chip = {
 static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
 {
 	struct exynos_weint_data *eintd = irq_get_handler_data(irq);
+	struct samsung_pin_bank *bank = eintd->bank;
 	struct irq_chip *chip = irq_get_chip(irq);
 	int eint_irq;
 
@@ -370,20 +328,20 @@ static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
 	if (chip->irq_ack)
 		chip->irq_ack(&desc->irq_data);
 
-	eint_irq = irq_linear_revmap(eintd->domain, eintd->irq);
+	eint_irq = irq_linear_revmap(bank->irq_domain, eintd->irq);
 	generic_handle_irq(eint_irq);
 	chip->irq_unmask(&desc->irq_data);
 	chained_irq_exit(chip, desc);
 }
 
-static inline void exynos_irq_demux_eint(int irq_base, unsigned long pend,
-					struct irq_domain *domain)
+static inline void exynos_irq_demux_eint(unsigned long pend,
+						struct irq_domain *domain)
 {
 	unsigned int irq;
 
 	while (pend) {
 		irq = fls(pend) - 1;
-		generic_handle_irq(irq_find_mapping(domain, irq_base + irq));
+		generic_handle_irq(irq_find_mapping(domain, irq));
 		pend &= ~(1 << irq);
 	}
 }
@@ -392,18 +350,22 @@ static inline void exynos_irq_demux_eint(int irq_base, unsigned long pend,
 static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_get_chip(irq);
-	struct exynos_weint_data *eintd = irq_get_handler_data(irq);
-	struct samsung_pinctrl_drv_data *d = eintd->domain->host_data;
+	struct exynos_muxed_weint_data *eintd = irq_get_handler_data(irq);
+	struct samsung_pinctrl_drv_data *d = eintd->banks[0]->drvdata;
+	struct samsung_pin_ctrl *ctrl = d->ctrl;
 	unsigned long pend;
 	unsigned long mask;
+	int i;
 
 	chained_irq_enter(chip, desc);
-	pend = readl(d->virt_base + d->ctrl->weint_pend + 0x8);
-	mask = readl(d->virt_base + d->ctrl->weint_mask + 0x8);
-	exynos_irq_demux_eint(16, pend & ~mask, eintd->domain);
-	pend = readl(d->virt_base + d->ctrl->weint_pend + 0xC);
-	mask = readl(d->virt_base + d->ctrl->weint_mask + 0xC);
-	exynos_irq_demux_eint(24, pend & ~mask, eintd->domain);
+
+	for (i = 0; i < eintd->nr_banks; ++i) {
+		struct samsung_pin_bank *b = eintd->banks[i];
+		pend = readl(d->virt_base + ctrl->weint_pend + b->eint_offset);
+		mask = readl(d->virt_base + ctrl->weint_mask + b->eint_offset);
+		exynos_irq_demux_eint(pend & ~mask, b->irq_domain);
+	}
+
 	chained_irq_exit(chip, desc);
 }
 
@@ -433,7 +395,11 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
 	struct device *dev = d->dev;
 	struct device_node *wkup_np = NULL;
 	struct device_node *np;
+	struct samsung_pin_bank *bank;
 	struct exynos_weint_data *weint_data;
+	struct exynos_muxed_weint_data *muxed_data;
+	unsigned int muxed_banks = 0;
+	unsigned int i;
 	int idx, irq;
 
 	for_each_child_of_node(dev->of_node, np) {
@@ -445,90 +411,124 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
 	if (!wkup_np)
 		return -ENODEV;
 
-	d->wkup_irqd = irq_domain_add_linear(wkup_np, d->ctrl->nr_wint,
-				&exynos_wkup_irqd_ops, d);
-	if (!d->wkup_irqd) {
-		dev_err(dev, "wakeup irq domain allocation failed\n");
-		return -ENXIO;
-	}
+	bank = d->ctrl->pin_banks;
+	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+		if (bank->eint_type != EINT_TYPE_WKUP)
+			continue;
 
-	weint_data = devm_kzalloc(dev, sizeof(*weint_data) * 17, GFP_KERNEL);
-	if (!weint_data) {
-		dev_err(dev, "could not allocate memory for weint_data\n");
-		return -ENOMEM;
-	}
+		bank->irq_domain = irq_domain_add_linear(bank->of_node,
+				bank->nr_pins, &exynos_wkup_irqd_ops, bank);
+		if (!bank->irq_domain) {
+			dev_err(dev, "wkup irq domain add failed\n");
+			return -ENXIO;
+		}
 
-	irq = irq_of_parse_and_map(wkup_np, 16);
-	if (irq) {
-		weint_data[16].domain = d->wkup_irqd;
-		irq_set_chained_handler(irq, exynos_irq_demux_eint16_31);
-		irq_set_handler_data(irq, &weint_data[16]);
-	} else {
-		dev_err(dev, "irq number for EINT16-32 not found\n");
-	}
+		if (!of_find_property(bank->of_node, "interrupts", NULL)) {
+			bank->eint_type = EINT_TYPE_WKUP_MUX;
+			++muxed_banks;
+			continue;
+		}
 
-	for (idx = 0; idx < 16; idx++) {
-		weint_data[idx].domain = d->wkup_irqd;
-		weint_data[idx].irq = idx;
+		weint_data = devm_kzalloc(dev, bank->nr_pins
+					* sizeof(*weint_data), GFP_KERNEL);
+		if (!weint_data) {
+			dev_err(dev, "could not allocate memory for weint_data\n");
+			return -ENOMEM;
+		}
 
-		irq = irq_of_parse_and_map(wkup_np, idx);
-		if (irq) {
+		for (idx = 0; idx < bank->nr_pins; ++idx) {
+			irq = irq_of_parse_and_map(bank->of_node, idx);
+			if (!irq) {
+				dev_err(dev, "irq number for eint-%s-%d not found\n",
+							bank->name, idx);
+				continue;
+			}
+			weint_data[idx].irq = idx;
+			weint_data[idx].bank = bank;
 			irq_set_handler_data(irq, &weint_data[idx]);
 			irq_set_chained_handler(irq, exynos_irq_eint0_15);
-		} else {
-			dev_err(dev, "irq number for eint-%x not found\n", idx);
 		}
 	}
+
+	if (!muxed_banks)
+		return 0;
+
+	irq = irq_of_parse_and_map(wkup_np, 0);
+	if (!irq) {
+		dev_err(dev, "irq number for muxed EINTs not found\n");
+		return 0;
+	}
+
+	muxed_data = devm_kzalloc(dev, sizeof(*muxed_data)
+		+ muxed_banks*sizeof(struct samsung_pin_bank *), GFP_KERNEL);
+	if (!muxed_data) {
+		dev_err(dev, "could not allocate memory for muxed_data\n");
+		return -ENOMEM;
+	}
+
+	irq_set_chained_handler(irq, exynos_irq_demux_eint16_31);
+	irq_set_handler_data(irq, muxed_data);
+
+	bank = d->ctrl->pin_banks;
+	idx = 0;
+	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+		if (bank->eint_type != EINT_TYPE_WKUP_MUX)
+			continue;
+
+		muxed_data->banks[idx++] = bank;
+	}
+	muxed_data->nr_banks = muxed_banks;
+
 	return 0;
 }
 
 /* pin banks of exynos4210 pin-controller 0 */
 static struct samsung_pin_bank exynos4210_pin_banks0[] = {
-	EXYNOS_PIN_BANK_EINTG(0x000, EXYNOS4210_GPIO_A0, "gpa0"),
-	EXYNOS_PIN_BANK_EINTG(0x020, EXYNOS4210_GPIO_A1, "gpa1"),
-	EXYNOS_PIN_BANK_EINTG(0x040, EXYNOS4210_GPIO_B, "gpb"),
-	EXYNOS_PIN_BANK_EINTG(0x060, EXYNOS4210_GPIO_C0, "gpc0"),
-	EXYNOS_PIN_BANK_EINTG(0x080, EXYNOS4210_GPIO_C1, "gpc1"),
-	EXYNOS_PIN_BANK_EINTG(0x0A0, EXYNOS4210_GPIO_D0, "gpd0"),
-	EXYNOS_PIN_BANK_EINTG(0x0C0, EXYNOS4210_GPIO_D1, "gpd1"),
-	EXYNOS_PIN_BANK_EINTG(0x0E0, EXYNOS4210_GPIO_E0, "gpe0"),
-	EXYNOS_PIN_BANK_EINTG(0x100, EXYNOS4210_GPIO_E1, "gpe1"),
-	EXYNOS_PIN_BANK_EINTG(0x120, EXYNOS4210_GPIO_E2, "gpe2"),
-	EXYNOS_PIN_BANK_EINTG(0x140, EXYNOS4210_GPIO_E3, "gpe3"),
-	EXYNOS_PIN_BANK_EINTG(0x160, EXYNOS4210_GPIO_E4, "gpe4"),
-	EXYNOS_PIN_BANK_EINTG(0x180, EXYNOS4210_GPIO_F0, "gpf0"),
-	EXYNOS_PIN_BANK_EINTG(0x1A0, EXYNOS4210_GPIO_F1, "gpf1"),
-	EXYNOS_PIN_BANK_EINTG(0x1C0, EXYNOS4210_GPIO_F2, "gpf2"),
-	EXYNOS_PIN_BANK_EINTG(0x1E0, EXYNOS4210_GPIO_F3, "gpf3"),
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
+	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1", 0x18),
+	EXYNOS_PIN_BANK_EINTG(5, 0x0E0, "gpe0", 0x1c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpe1", 0x20),
+	EXYNOS_PIN_BANK_EINTG(6, 0x120, "gpe2", 0x24),
+	EXYNOS_PIN_BANK_EINTG(8, 0x140, "gpe3", 0x28),
+	EXYNOS_PIN_BANK_EINTG(8, 0x160, "gpe4", 0x2c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0", 0x30),
+	EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1", 0x34),
+	EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2", 0x38),
+	EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3", 0x3c),
 };
 
 /* pin banks of exynos4210 pin-controller 1 */
 static struct samsung_pin_bank exynos4210_pin_banks1[] = {
-	EXYNOS_PIN_BANK_EINTG(0x000, EXYNOS4210_GPIO_J0, "gpj0"),
-	EXYNOS_PIN_BANK_EINTG(0x020, EXYNOS4210_GPIO_J1, "gpj1"),
-	EXYNOS_PIN_BANK_EINTG(0x040, EXYNOS4210_GPIO_K0, "gpk0"),
-	EXYNOS_PIN_BANK_EINTG(0x060, EXYNOS4210_GPIO_K1, "gpk1"),
-	EXYNOS_PIN_BANK_EINTG(0x080, EXYNOS4210_GPIO_K2, "gpk2"),
-	EXYNOS_PIN_BANK_EINTG(0x0A0, EXYNOS4210_GPIO_K3, "gpk3"),
-	EXYNOS_PIN_BANK_EINTG(0x0C0, EXYNOS4210_GPIO_L0, "gpl0"),
-	EXYNOS_PIN_BANK_EINTG(0x0E0, EXYNOS4210_GPIO_L1, "gpl1"),
-	EXYNOS_PIN_BANK_EINTG(0x100, EXYNOS4210_GPIO_L2, "gpl2"),
-	EXYNOS_PIN_BANK_EINTN(0x120, EXYNOS4210_GPIO_Y0, "gpy0"),
-	EXYNOS_PIN_BANK_EINTN(0x140, EXYNOS4210_GPIO_Y1, "gpy1"),
-	EXYNOS_PIN_BANK_EINTN(0x160, EXYNOS4210_GPIO_Y2, "gpy2"),
-	EXYNOS_PIN_BANK_EINTN(0x180, EXYNOS4210_GPIO_Y3, "gpy3"),
-	EXYNOS_PIN_BANK_EINTN(0x1A0, EXYNOS4210_GPIO_Y4, "gpy4"),
-	EXYNOS_PIN_BANK_EINTN(0x1C0, EXYNOS4210_GPIO_Y5, "gpy5"),
-	EXYNOS_PIN_BANK_EINTN(0x1E0, EXYNOS4210_GPIO_Y6, "gpy6"),
-	EXYNOS_PIN_BANK_EINTN(0xC00, EXYNOS4210_GPIO_X0, "gpx0"),
-	EXYNOS_PIN_BANK_EINTN(0xC20, EXYNOS4210_GPIO_X1, "gpx1"),
-	EXYNOS_PIN_BANK_EINTN(0xC40, EXYNOS4210_GPIO_X2, "gpx2"),
-	EXYNOS_PIN_BANK_EINTN(0xC60, EXYNOS4210_GPIO_X3, "gpx3"),
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpj0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(5, 0x020, "gpj1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0", 0x08),
+	EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10),
+	EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3", 0x14),
+	EXYNOS_PIN_BANK_EINTG(8, 0x0C0, "gpl0", 0x18),
+	EXYNOS_PIN_BANK_EINTG(3, 0x0E0, "gpl1", 0x1c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2", 0x20),
+	EXYNOS_PIN_BANK_EINTN(6, 0x120, "gpy0"),
+	EXYNOS_PIN_BANK_EINTN(4, 0x140, "gpy1"),
+	EXYNOS_PIN_BANK_EINTN(6, 0x160, "gpy2"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x180, "gpy3"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
 };
 
 /* pin banks of exynos4210 pin-controller 2 */
 static struct samsung_pin_bank exynos4210_pin_banks2[] = {
-	EXYNOS_PIN_BANK_EINTN(0x000, EXYNOS4210_GPIO_Z, "gpz"),
+	EXYNOS_PIN_BANK_EINTN(7, 0x000, "gpz"),
 };
 
 /*
@@ -540,9 +540,6 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
 		/* pin-controller instance 0 data */
 		.pin_banks	= exynos4210_pin_banks0,
 		.nr_banks	= ARRAY_SIZE(exynos4210_pin_banks0),
-		.base		= EXYNOS4210_GPIO_A0_START,
-		.nr_pins	= EXYNOS4210_GPIOA_NR_PINS,
-		.nr_gint	= EXYNOS4210_GPIOA_NR_GINT,
 		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
 		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
 		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
@@ -553,10 +550,6 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
 		/* pin-controller instance 1 data */
 		.pin_banks	= exynos4210_pin_banks1,
 		.nr_banks	= ARRAY_SIZE(exynos4210_pin_banks1),
-		.base		= EXYNOS4210_GPIOA_NR_PINS,
-		.nr_pins	= EXYNOS4210_GPIOB_NR_PINS,
-		.nr_gint	= EXYNOS4210_GPIOB_NR_GINT,
-		.nr_wint	= 32,
 		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
 		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
 		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
@@ -571,9 +564,116 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
 		/* pin-controller instance 2 data */
 		.pin_banks	= exynos4210_pin_banks2,
 		.nr_banks	= ARRAY_SIZE(exynos4210_pin_banks2),
-		.base		= EXYNOS4210_GPIOA_NR_PINS +
-					EXYNOS4210_GPIOB_NR_PINS,
-		.nr_pins	= EXYNOS4210_GPIOC_NR_PINS,
 		.label		= "exynos4210-gpio-ctrl2",
 	},
 };
+
+/* pin banks of exynos4x12 pin-controller 0 */
+static struct samsung_pin_bank exynos4x12_pin_banks0[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
+	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1", 0x18),
+	EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0", 0x30),
+	EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1", 0x34),
+	EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2", 0x38),
+	EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3", 0x3c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x240, "gpj0", 0x40),
+	EXYNOS_PIN_BANK_EINTG(5, 0x260, "gpj1", 0x44),
+};
+
+/* pin banks of exynos4x12 pin-controller 1 */
+static struct samsung_pin_bank exynos4x12_pin_banks1[] = {
+	EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0", 0x08),
+	EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10),
+	EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3", 0x14),
+	EXYNOS_PIN_BANK_EINTG(7, 0x0C0, "gpl0", 0x18),
+	EXYNOS_PIN_BANK_EINTG(2, 0x0E0, "gpl1", 0x1c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2", 0x20),
+	EXYNOS_PIN_BANK_EINTG(8, 0x260, "gpm0", 0x24),
+	EXYNOS_PIN_BANK_EINTG(7, 0x280, "gpm1", 0x28),
+	EXYNOS_PIN_BANK_EINTG(5, 0x2A0, "gpm2", 0x2c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x2C0, "gpm3", 0x30),
+	EXYNOS_PIN_BANK_EINTG(8, 0x2E0, "gpm4", 0x34),
+	EXYNOS_PIN_BANK_EINTN(6, 0x120, "gpy0"),
+	EXYNOS_PIN_BANK_EINTN(4, 0x140, "gpy1"),
+	EXYNOS_PIN_BANK_EINTN(6, 0x160, "gpy2"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x180, "gpy3"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"),
+	EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
+};
+
+/* pin banks of exynos4x12 pin-controller 2 */
+static struct samsung_pin_bank exynos4x12_pin_banks2[] = {
+	EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
+};
+
+/* pin banks of exynos4x12 pin-controller 3 */
+static struct samsung_pin_bank exynos4x12_pin_banks3[] = {
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpv0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpv1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpv2", 0x08),
+	EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpv3", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(2, 0x080, "gpv4", 0x10),
+};
+
+/*
+ * Samsung pinctrl driver data for Exynos4x12 SoC. Exynos4x12 SoC includes
+ * four gpio/pin-mux/pinconfig controllers.
+ */
+struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
+	{
+		/* pin-controller instance 0 data */
+		.pin_banks	= exynos4x12_pin_banks0,
+		.nr_banks	= ARRAY_SIZE(exynos4x12_pin_banks0),
+		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
+		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
+		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
+		.svc		= EXYNOS_SVC_OFFSET,
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.label		= "exynos4x12-gpio-ctrl0",
+	}, {
+		/* pin-controller instance 1 data */
+		.pin_banks	= exynos4x12_pin_banks1,
+		.nr_banks	= ARRAY_SIZE(exynos4x12_pin_banks1),
+		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
+		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
+		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
+		.weint_con	= EXYNOS_WKUP_ECON_OFFSET,
+		.weint_mask	= EXYNOS_WKUP_EMASK_OFFSET,
+		.weint_pend	= EXYNOS_WKUP_EPEND_OFFSET,
+		.svc		= EXYNOS_SVC_OFFSET,
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.eint_wkup_init = exynos_eint_wkup_init,
+		.label		= "exynos4x12-gpio-ctrl1",
+	}, {
+		/* pin-controller instance 2 data */
+		.pin_banks	= exynos4x12_pin_banks2,
+		.nr_banks	= ARRAY_SIZE(exynos4x12_pin_banks2),
+		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
+		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
+		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
+		.svc		= EXYNOS_SVC_OFFSET,
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.label		= "exynos4x12-gpio-ctrl2",
+	}, {
+		/* pin-controller instance 3 data */
+		.pin_banks	= exynos4x12_pin_banks3,
+		.nr_banks	= ARRAY_SIZE(exynos4x12_pin_banks3),
+		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
+		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
+		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
+		.svc		= EXYNOS_SVC_OFFSET,
+		.eint_gpio_init = exynos_eint_gpio_init,
+		.label		= "exynos4x12-gpio-ctrl3",
+	},
+};
diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h
index 31d0a06..0a70889 100644
--- a/drivers/pinctrl/pinctrl-exynos.h
+++ b/drivers/pinctrl/pinctrl-exynos.h
@@ -17,125 +17,6 @@
  * (at your option) any later version.
  */
 
-#define EXYNOS_GPIO_START(__gpio)	((__gpio##_START) + (__gpio##_NR))
-
-#define EXYNOS4210_GPIO_A0_NR	(8)
-#define EXYNOS4210_GPIO_A1_NR	(6)
-#define EXYNOS4210_GPIO_B_NR	(8)
-#define EXYNOS4210_GPIO_C0_NR	(5)
-#define EXYNOS4210_GPIO_C1_NR	(5)
-#define EXYNOS4210_GPIO_D0_NR	(4)
-#define EXYNOS4210_GPIO_D1_NR	(4)
-#define EXYNOS4210_GPIO_E0_NR	(5)
-#define EXYNOS4210_GPIO_E1_NR	(8)
-#define EXYNOS4210_GPIO_E2_NR	(6)
-#define EXYNOS4210_GPIO_E3_NR	(8)
-#define EXYNOS4210_GPIO_E4_NR	(8)
-#define EXYNOS4210_GPIO_F0_NR	(8)
-#define EXYNOS4210_GPIO_F1_NR	(8)
-#define EXYNOS4210_GPIO_F2_NR	(8)
-#define EXYNOS4210_GPIO_F3_NR	(6)
-#define EXYNOS4210_GPIO_J0_NR	(8)
-#define EXYNOS4210_GPIO_J1_NR	(5)
-#define EXYNOS4210_GPIO_K0_NR	(7)
-#define EXYNOS4210_GPIO_K1_NR	(7)
-#define EXYNOS4210_GPIO_K2_NR	(7)
-#define EXYNOS4210_GPIO_K3_NR	(7)
-#define EXYNOS4210_GPIO_L0_NR	(8)
-#define EXYNOS4210_GPIO_L1_NR	(3)
-#define EXYNOS4210_GPIO_L2_NR	(8)
-#define EXYNOS4210_GPIO_Y0_NR	(6)
-#define EXYNOS4210_GPIO_Y1_NR	(4)
-#define EXYNOS4210_GPIO_Y2_NR	(6)
-#define EXYNOS4210_GPIO_Y3_NR	(8)
-#define EXYNOS4210_GPIO_Y4_NR	(8)
-#define EXYNOS4210_GPIO_Y5_NR	(8)
-#define EXYNOS4210_GPIO_Y6_NR	(8)
-#define EXYNOS4210_GPIO_X0_NR	(8)
-#define EXYNOS4210_GPIO_X1_NR	(8)
-#define EXYNOS4210_GPIO_X2_NR	(8)
-#define EXYNOS4210_GPIO_X3_NR	(8)
-#define EXYNOS4210_GPIO_Z_NR	(7)
-
-enum exynos4210_gpio_xa_start {
-	EXYNOS4210_GPIO_A0_START	= 0,
-	EXYNOS4210_GPIO_A1_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_A0),
-	EXYNOS4210_GPIO_B_START		= EXYNOS_GPIO_START(EXYNOS4210_GPIO_A1),
-	EXYNOS4210_GPIO_C0_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_B),
-	EXYNOS4210_GPIO_C1_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_C0),
-	EXYNOS4210_GPIO_D0_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_C1),
-	EXYNOS4210_GPIO_D1_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_D0),
-	EXYNOS4210_GPIO_E0_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_D1),
-	EXYNOS4210_GPIO_E1_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_E0),
-	EXYNOS4210_GPIO_E2_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_E1),
-	EXYNOS4210_GPIO_E3_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_E2),
-	EXYNOS4210_GPIO_E4_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_E3),
-	EXYNOS4210_GPIO_F0_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_E4),
-	EXYNOS4210_GPIO_F1_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_F0),
-	EXYNOS4210_GPIO_F2_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_F1),
-	EXYNOS4210_GPIO_F3_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_F2),
-};
-
-enum exynos4210_gpio_xb_start {
-	EXYNOS4210_GPIO_J0_START	= 0,
-	EXYNOS4210_GPIO_J1_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_J0),
-	EXYNOS4210_GPIO_K0_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_J1),
-	EXYNOS4210_GPIO_K1_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_K0),
-	EXYNOS4210_GPIO_K2_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_K1),
-	EXYNOS4210_GPIO_K3_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_K2),
-	EXYNOS4210_GPIO_L0_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_K3),
-	EXYNOS4210_GPIO_L1_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_L0),
-	EXYNOS4210_GPIO_L2_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_L1),
-	EXYNOS4210_GPIO_Y0_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_L2),
-	EXYNOS4210_GPIO_Y1_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y0),
-	EXYNOS4210_GPIO_Y2_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y1),
-	EXYNOS4210_GPIO_Y3_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y2),
-	EXYNOS4210_GPIO_Y4_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y3),
-	EXYNOS4210_GPIO_Y5_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y4),
-	EXYNOS4210_GPIO_Y6_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y5),
-	EXYNOS4210_GPIO_X0_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y6),
-	EXYNOS4210_GPIO_X1_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_X0),
-	EXYNOS4210_GPIO_X2_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_X1),
-	EXYNOS4210_GPIO_X3_START	= EXYNOS_GPIO_START(EXYNOS4210_GPIO_X2),
-};
-
-enum exynos4210_gpio_xc_start {
-	EXYNOS4210_GPIO_Z_START		= 0,
-};
-
-#define	EXYNOS4210_GPIO_A0_IRQ		EXYNOS4210_GPIO_A0_START
-#define	EXYNOS4210_GPIO_A1_IRQ		EXYNOS4210_GPIO_A1_START
-#define	EXYNOS4210_GPIO_B_IRQ		EXYNOS4210_GPIO_B_START
-#define	EXYNOS4210_GPIO_C0_IRQ		EXYNOS4210_GPIO_C0_START
-#define	EXYNOS4210_GPIO_C1_IRQ		EXYNOS4210_GPIO_C1_START
-#define	EXYNOS4210_GPIO_D0_IRQ		EXYNOS4210_GPIO_D0_START
-#define	EXYNOS4210_GPIO_D1_IRQ		EXYNOS4210_GPIO_D1_START
-#define	EXYNOS4210_GPIO_E0_IRQ		EXYNOS4210_GPIO_E0_START
-#define	EXYNOS4210_GPIO_E1_IRQ		EXYNOS4210_GPIO_E1_START
-#define	EXYNOS4210_GPIO_E2_IRQ		EXYNOS4210_GPIO_E2_START
-#define	EXYNOS4210_GPIO_E3_IRQ		EXYNOS4210_GPIO_E3_START
-#define	EXYNOS4210_GPIO_E4_IRQ		EXYNOS4210_GPIO_E4_START
-#define	EXYNOS4210_GPIO_F0_IRQ		EXYNOS4210_GPIO_F0_START
-#define	EXYNOS4210_GPIO_F1_IRQ		EXYNOS4210_GPIO_F1_START
-#define	EXYNOS4210_GPIO_F2_IRQ		EXYNOS4210_GPIO_F2_START
-#define	EXYNOS4210_GPIO_F3_IRQ		EXYNOS4210_GPIO_F3_START
-#define	EXYNOS4210_GPIO_J0_IRQ		EXYNOS4210_GPIO_J0_START
-#define	EXYNOS4210_GPIO_J1_IRQ		EXYNOS4210_GPIO_J1_START
-#define	EXYNOS4210_GPIO_K0_IRQ		EXYNOS4210_GPIO_K0_START
-#define	EXYNOS4210_GPIO_K1_IRQ		EXYNOS4210_GPIO_K1_START
-#define	EXYNOS4210_GPIO_K2_IRQ		EXYNOS4210_GPIO_K2_START
-#define	EXYNOS4210_GPIO_K3_IRQ		EXYNOS4210_GPIO_K3_START
-#define	EXYNOS4210_GPIO_L0_IRQ		EXYNOS4210_GPIO_L0_START
-#define	EXYNOS4210_GPIO_L1_IRQ		EXYNOS4210_GPIO_L1_START
-#define	EXYNOS4210_GPIO_L2_IRQ		EXYNOS4210_GPIO_L2_START
-#define	EXYNOS4210_GPIO_Z_IRQ		EXYNOS4210_GPIO_Z_START
-
-#define EXYNOS4210_GPIOA_NR_PINS	EXYNOS_GPIO_START(EXYNOS4210_GPIO_F3)
-#define EXYNOS4210_GPIOA_NR_GINT	EXYNOS_GPIO_START(EXYNOS4210_GPIO_F3)
-#define EXYNOS4210_GPIOB_NR_PINS	EXYNOS_GPIO_START(EXYNOS4210_GPIO_X3)
-#define EXYNOS4210_GPIOB_NR_GINT	EXYNOS_GPIO_START(EXYNOS4210_GPIO_L2)
-#define EXYNOS4210_GPIOC_NR_PINS	EXYNOS_GPIO_START(EXYNOS4210_GPIO_Z)
-
 /* External GPIO and wakeup interrupt related definitions */
 #define EXYNOS_GPIO_ECON_OFFSET		0x700
 #define EXYNOS_GPIO_EMASK_OFFSET	0x900
@@ -165,11 +46,10 @@ enum exynos4210_gpio_xc_start {
 #define EXYNOS_EINT_MAX_PER_BANK	8
 #define EXYNOS_EINT_NR_WKUP_EINT
 
-#define EXYNOS_PIN_BANK_EINTN(reg, __gpio, id)		\
+#define EXYNOS_PIN_BANK_EINTN(pins, reg, id)		\
 	{						\
 		.pctl_offset	= reg,			\
-		.pin_base	= (__gpio##_START),	\
-		.nr_pins	= (__gpio##_NR),	\
+		.nr_pins	= pins,			\
 		.func_width	= 4,			\
 		.pud_width	= 2,			\
 		.drv_width	= 2,			\
@@ -179,40 +59,50 @@ enum exynos4210_gpio_xc_start {
 		.name		= id			\
 	}
 
-#define EXYNOS_PIN_BANK_EINTG(reg, __gpio, id)		\
+#define EXYNOS_PIN_BANK_EINTG(pins, reg, id, offs)	\
 	{						\
 		.pctl_offset	= reg,			\
-		.pin_base	= (__gpio##_START),	\
-		.nr_pins	= (__gpio##_NR),	\
+		.nr_pins	= pins,			\
 		.func_width	= 4,			\
 		.pud_width	= 2,			\
 		.drv_width	= 2,			\
 		.conpdn_width	= 2,			\
 		.pudpdn_width	= 2,			\
 		.eint_type	= EINT_TYPE_GPIO,	\
-		.irq_base	= (__gpio##_IRQ),	\
+		.eint_offset	= offs,			\
 		.name		= id			\
 	}
 
-/**
- * struct exynos_geint_data: gpio eint specific data for irq_chip callbacks.
- * @bank: pin bank from which this gpio interrupt originates.
- * @pin: pin number within the bank.
- * @eint_offset: offset to be added to the con/pend/mask register bank base.
- */
-struct exynos_geint_data {
-	struct samsung_pin_bank	*bank;
-	u32			pin;
-	u32			eint_offset;
-};
+#define EXYNOS_PIN_BANK_EINTW(pins, reg, id, offs)	\
+	{						\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.func_width	= 4,			\
+		.pud_width	= 2,			\
+		.drv_width	= 2,			\
+		.eint_type	= EINT_TYPE_WKUP,	\
+		.eint_offset	= offs,			\
+		.name		= id			\
+	}
 
 /**
  * struct exynos_weint_data: irq specific data for all the wakeup interrupts
  * generated by the external wakeup interrupt controller.
- * @domain: irq domain representing the external wakeup interrupts
  * @irq: interrupt number within the domain.
+ * @bank: bank responsible for this interrupt
  */
 struct exynos_weint_data {
-	struct irq_domain	*domain;
-	u32			irq;
+	unsigned int irq;
+	struct samsung_pin_bank *bank;
+};
+
+/**
+ * struct exynos_muxed_weint_data: irq specific data for muxed wakeup interrupts
+ * generated by the external wakeup interrupt controller.
+ * @nr_banks: count of banks being part of the mux
+ * @banks: array of banks being part of the mux
+ */
+struct exynos_muxed_weint_data {
+	unsigned int nr_banks;
+	struct samsung_pin_bank *banks[];
 };
diff --git a/drivers/pinctrl/pinctrl-exynos5440.c b/drivers/pinctrl/pinctrl-exynos5440.c
new file mode 100644
index 0000000..b8635f6
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-exynos5440.c
@@ -0,0 +1,919 @@
+/*
+ * pin-controller/pin-mux/pin-config/gpio-driver for Samsung's EXYNOS5440 SoC.
+ *
+ * Copyright (c) 2012 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.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include "core.h"
+
+/* EXYNOS5440 GPIO and Pinctrl register offsets */
+#define GPIO_MUX		0x00
+#define GPIO_IE			0x04
+#define GPIO_INT		0x08
+#define GPIO_TYPE		0x0C
+#define GPIO_VAL		0x10
+#define GPIO_OE			0x14
+#define GPIO_IN			0x18
+#define GPIO_PE			0x1C
+#define GPIO_PS			0x20
+#define GPIO_SR			0x24
+#define GPIO_DS0		0x28
+#define GPIO_DS1		0x2C
+
+#define EXYNOS5440_MAX_PINS		23
+#define PIN_NAME_LENGTH		10
+
+#define GROUP_SUFFIX		"-grp"
+#define GSUFFIX_LEN		sizeof(GROUP_SUFFIX)
+#define FUNCTION_SUFFIX		"-mux"
+#define FSUFFIX_LEN		sizeof(FUNCTION_SUFFIX)
+
+/*
+ * pin configuration type and its value are packed together into a 16-bits.
+ * The upper 8-bits represent the configuration type and the lower 8-bits
+ * hold the value of the configuration type.
+ */
+#define PINCFG_TYPE_MASK		0xFF
+#define PINCFG_VALUE_SHIFT		8
+#define PINCFG_VALUE_MASK		(0xFF << PINCFG_VALUE_SHIFT)
+#define PINCFG_PACK(type, value)	(((value) << PINCFG_VALUE_SHIFT) | type)
+#define PINCFG_UNPACK_TYPE(cfg)		((cfg) & PINCFG_TYPE_MASK)
+#define PINCFG_UNPACK_VALUE(cfg)	(((cfg) & PINCFG_VALUE_MASK) >> \
+						PINCFG_VALUE_SHIFT)
+
+/**
+ * enum pincfg_type - possible pin configuration types supported.
+ * @PINCFG_TYPE_PUD: Pull up/down configuration.
+ * @PINCFG_TYPE_DRV: Drive strength configuration.
+ * @PINCFG_TYPE_SKEW_RATE: Skew rate configuration.
+ * @PINCFG_TYPE_INPUT_TYPE: Pin input type configuration.
+ */
+enum pincfg_type {
+	PINCFG_TYPE_PUD,
+	PINCFG_TYPE_DRV,
+	PINCFG_TYPE_SKEW_RATE,
+	PINCFG_TYPE_INPUT_TYPE
+};
+
+/**
+ * struct exynos5440_pin_group: represent group of pins for pincfg setting.
+ * @name: name of the pin group, used to lookup the group.
+ * @pins: the pins included in this group.
+ * @num_pins: number of pins included in this group.
+ */
+struct exynos5440_pin_group {
+	const char		*name;
+	const unsigned int	*pins;
+	u8			num_pins;
+};
+
+/**
+ * struct exynos5440_pmx_func: represent a pin function.
+ * @name: name of the pin function, used to lookup the function.
+ * @groups: one or more names of pin groups that provide this function.
+ * @num_groups: number of groups included in @groups.
+ * @function: the function number to be programmed when selected.
+ */
+struct exynos5440_pmx_func {
+	const char		*name;
+	const char		**groups;
+	u8			num_groups;
+	unsigned long		function;
+};
+
+/**
+ * struct exynos5440_pinctrl_priv_data: driver's private runtime data.
+ * @reg_base: ioremapped based address of the register space.
+ * @gc: gpio chip registered with gpiolib.
+ * @pin_groups: list of pin groups parsed from device tree.
+ * @nr_groups: number of pin groups available.
+ * @pmx_functions: list of pin functions parsed from device tree.
+ * @nr_functions: number of pin functions available.
+ */
+struct exynos5440_pinctrl_priv_data {
+	void __iomem			*reg_base;
+	struct gpio_chip		*gc;
+
+	const struct exynos5440_pin_group	*pin_groups;
+	unsigned int			nr_groups;
+	const struct exynos5440_pmx_func	*pmx_functions;
+	unsigned int			nr_functions;
+};
+
+/* list of all possible config options supported */
+struct pin_config {
+	char		*prop_cfg;
+	unsigned int	cfg_type;
+} pcfgs[] = {
+	{ "samsung,exynos5440-pin-pud", PINCFG_TYPE_PUD },
+	{ "samsung,exynos5440-pin-drv", PINCFG_TYPE_DRV },
+	{ "samsung,exynos5440-pin-skew-rate", PINCFG_TYPE_SKEW_RATE },
+	{ "samsung,exynos5440-pin-input-type", PINCFG_TYPE_INPUT_TYPE },
+};
+
+/* check if the selector is a valid pin group selector */
+static int exynos5440_get_group_count(struct pinctrl_dev *pctldev)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	return priv->nr_groups;
+}
+
+/* return the name of the group selected by the group selector */
+static const char *exynos5440_get_group_name(struct pinctrl_dev *pctldev,
+						unsigned selector)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	return priv->pin_groups[selector].name;
+}
+
+/* return the pin numbers associated with the specified group */
+static int exynos5440_get_group_pins(struct pinctrl_dev *pctldev,
+		unsigned selector, const unsigned **pins, unsigned *num_pins)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	*pins = priv->pin_groups[selector].pins;
+	*num_pins = priv->pin_groups[selector].num_pins;
+	return 0;
+}
+
+/* create pinctrl_map entries by parsing device tree nodes */
+static int exynos5440_dt_node_to_map(struct pinctrl_dev *pctldev,
+			struct device_node *np, struct pinctrl_map **maps,
+			unsigned *nmaps)
+{
+	struct device *dev = pctldev->dev;
+	struct pinctrl_map *map;
+	unsigned long *cfg = NULL;
+	char *gname, *fname;
+	int cfg_cnt = 0, map_cnt = 0, idx = 0;
+
+	/* count the number of config options specfied in the node */
+	for (idx = 0; idx < ARRAY_SIZE(pcfgs); idx++)
+		if (of_find_property(np, pcfgs[idx].prop_cfg, NULL))
+			cfg_cnt++;
+
+	/*
+	 * Find out the number of map entries to create. All the config options
+	 * can be accomadated into a single config map entry.
+	 */
+	if (cfg_cnt)
+		map_cnt = 1;
+	if (of_find_property(np, "samsung,exynos5440-pin-function", NULL))
+		map_cnt++;
+	if (!map_cnt) {
+		dev_err(dev, "node %s does not have either config or function "
+				"configurations\n", np->name);
+		return -EINVAL;
+	}
+
+	/* Allocate memory for pin-map entries */
+	map = kzalloc(sizeof(*map) * map_cnt, GFP_KERNEL);
+	if (!map) {
+		dev_err(dev, "could not alloc memory for pin-maps\n");
+		return -ENOMEM;
+	}
+	*nmaps = 0;
+
+	/*
+	 * Allocate memory for pin group name. The pin group name is derived
+	 * from the node name from which these map entries are be created.
+	 */
+	gname = kzalloc(strlen(np->name) + GSUFFIX_LEN, GFP_KERNEL);
+	if (!gname) {
+		dev_err(dev, "failed to alloc memory for group name\n");
+		goto free_map;
+	}
+	sprintf(gname, "%s%s", np->name, GROUP_SUFFIX);
+
+	/*
+	 * don't have config options? then skip over to creating function
+	 * map entries.
+	 */
+	if (!cfg_cnt)
+		goto skip_cfgs;
+
+	/* Allocate memory for config entries */
+	cfg = kzalloc(sizeof(*cfg) * cfg_cnt, GFP_KERNEL);
+	if (!cfg) {
+		dev_err(dev, "failed to alloc memory for configs\n");
+		goto free_gname;
+	}
+
+	/* Prepare a list of config settings */
+	for (idx = 0, cfg_cnt = 0; idx < ARRAY_SIZE(pcfgs); idx++) {
+		u32 value;
+		if (!of_property_read_u32(np, pcfgs[idx].prop_cfg, &value))
+			cfg[cfg_cnt++] =
+				PINCFG_PACK(pcfgs[idx].cfg_type, value);
+	}
+
+	/* create the config map entry */
+	map[*nmaps].data.configs.group_or_pin = gname;
+	map[*nmaps].data.configs.configs = cfg;
+	map[*nmaps].data.configs.num_configs = cfg_cnt;
+	map[*nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
+	*nmaps += 1;
+
+skip_cfgs:
+	/* create the function map entry */
+	if (of_find_property(np, "samsung,exynos5440-pin-function", NULL)) {
+		fname = kzalloc(strlen(np->name) + FSUFFIX_LEN,	GFP_KERNEL);
+		if (!fname) {
+			dev_err(dev, "failed to alloc memory for func name\n");
+			goto free_cfg;
+		}
+		sprintf(fname, "%s%s", np->name, FUNCTION_SUFFIX);
+
+		map[*nmaps].data.mux.group = gname;
+		map[*nmaps].data.mux.function = fname;
+		map[*nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
+		*nmaps += 1;
+	}
+
+	*maps = map;
+	return 0;
+
+free_cfg:
+	kfree(cfg);
+free_gname:
+	kfree(gname);
+free_map:
+	kfree(map);
+	return -ENOMEM;
+}
+
+/* free the memory allocated to hold the pin-map table */
+static void exynos5440_dt_free_map(struct pinctrl_dev *pctldev,
+			     struct pinctrl_map *map, unsigned num_maps)
+{
+	int idx;
+
+	for (idx = 0; idx < num_maps; idx++) {
+		if (map[idx].type == PIN_MAP_TYPE_MUX_GROUP) {
+			kfree(map[idx].data.mux.function);
+			if (!idx)
+				kfree(map[idx].data.mux.group);
+		} else if (map->type == PIN_MAP_TYPE_CONFIGS_GROUP) {
+			kfree(map[idx].data.configs.configs);
+			if (!idx)
+				kfree(map[idx].data.configs.group_or_pin);
+		}
+	};
+
+	kfree(map);
+}
+
+/* list of pinctrl callbacks for the pinctrl core */
+static struct pinctrl_ops exynos5440_pctrl_ops = {
+	.get_groups_count	= exynos5440_get_group_count,
+	.get_group_name		= exynos5440_get_group_name,
+	.get_group_pins		= exynos5440_get_group_pins,
+	.dt_node_to_map		= exynos5440_dt_node_to_map,
+	.dt_free_map		= exynos5440_dt_free_map,
+};
+
+/* check if the selector is a valid pin function selector */
+static int exynos5440_get_functions_count(struct pinctrl_dev *pctldev)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	return priv->nr_functions;
+}
+
+/* return the name of the pin function specified */
+static const char *exynos5440_pinmux_get_fname(struct pinctrl_dev *pctldev,
+						unsigned selector)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	return priv->pmx_functions[selector].name;
+}
+
+/* return the groups associated for the specified function selector */
+static int exynos5440_pinmux_get_groups(struct pinctrl_dev *pctldev,
+		unsigned selector, const char * const **groups,
+		unsigned * const num_groups)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	*groups = priv->pmx_functions[selector].groups;
+	*num_groups = priv->pmx_functions[selector].num_groups;
+	return 0;
+}
+
+/* enable or disable a pinmux function */
+static void exynos5440_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
+					unsigned group, bool enable)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+	void __iomem *base;
+	u32 function;
+	u32 data;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	base = priv->reg_base;
+	function = priv->pmx_functions[selector].function;
+
+	data = readl(base + GPIO_MUX);
+	if (enable)
+		data |= (1 << function);
+	else
+		data &= ~(1 << function);
+	writel(data, base + GPIO_MUX);
+}
+
+/* enable a specified pinmux by writing to registers */
+static int exynos5440_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
+					unsigned group)
+{
+	exynos5440_pinmux_setup(pctldev, selector, group, true);
+	return 0;
+}
+
+/* disable a specified pinmux by writing to registers */
+static void exynos5440_pinmux_disable(struct pinctrl_dev *pctldev,
+					unsigned selector, unsigned group)
+{
+	exynos5440_pinmux_setup(pctldev, selector, group, false);
+}
+
+/*
+ * The calls to gpio_direction_output() and gpio_direction_input()
+ * leads to this function call (via the pinctrl_gpio_direction_{input|output}()
+ * function called from the gpiolib interface).
+ */
+static int exynos5440_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
+		struct pinctrl_gpio_range *range, unsigned offset, bool input)
+{
+	return 0;
+}
+
+/* list of pinmux callbacks for the pinmux vertical in pinctrl core */
+static struct pinmux_ops exynos5440_pinmux_ops = {
+	.get_functions_count	= exynos5440_get_functions_count,
+	.get_function_name	= exynos5440_pinmux_get_fname,
+	.get_function_groups	= exynos5440_pinmux_get_groups,
+	.enable			= exynos5440_pinmux_enable,
+	.disable		= exynos5440_pinmux_disable,
+	.gpio_set_direction	= exynos5440_pinmux_gpio_set_direction,
+};
+
+/* set the pin config settings for a specified pin */
+static int exynos5440_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+				unsigned long config)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+	void __iomem *base;
+	enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(config);
+	u32 cfg_value = PINCFG_UNPACK_VALUE(config);
+	u32 data;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	base = priv->reg_base;
+
+	switch (cfg_type) {
+	case PINCFG_TYPE_PUD:
+		/* first set pull enable/disable bit */
+		data = readl(base + GPIO_PE);
+		data &= ~(1 << pin);
+		if (cfg_value)
+			data |= (1 << pin);
+		writel(data, base + GPIO_PE);
+
+		/* then set pull up/down bit */
+		data = readl(base + GPIO_PS);
+		data &= ~(1 << pin);
+		if (cfg_value == 2)
+			data |= (1 << pin);
+		writel(data, base + GPIO_PS);
+		break;
+
+	case PINCFG_TYPE_DRV:
+		/* set the first bit of the drive strength */
+		data = readl(base + GPIO_DS0);
+		data &= ~(1 << pin);
+		data |= ((cfg_value & 1) << pin);
+		writel(data, base + GPIO_DS0);
+		cfg_value >>= 1;
+
+		/* set the second bit of the driver strength */
+		data = readl(base + GPIO_DS1);
+		data &= ~(1 << pin);
+		data |= ((cfg_value & 1) << pin);
+		writel(data, base + GPIO_DS1);
+		break;
+	case PINCFG_TYPE_SKEW_RATE:
+		data = readl(base + GPIO_SR);
+		data &= ~(1 << pin);
+		data |= ((cfg_value & 1) << pin);
+		writel(data, base + GPIO_SR);
+		break;
+	case PINCFG_TYPE_INPUT_TYPE:
+		data = readl(base + GPIO_TYPE);
+		data &= ~(1 << pin);
+		data |= ((cfg_value & 1) << pin);
+		writel(data, base + GPIO_TYPE);
+		break;
+	default:
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* get the pin config settings for a specified pin */
+static int exynos5440_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
+					unsigned long *config)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+	void __iomem *base;
+	enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config);
+	u32 data;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	base = priv->reg_base;
+
+	switch (cfg_type) {
+	case PINCFG_TYPE_PUD:
+		data = readl(base + GPIO_PE);
+		data = (data >> pin) & 1;
+		if (!data)
+			*config = 0;
+		else
+			*config = ((readl(base + GPIO_PS) >> pin) & 1) + 1;
+		break;
+	case PINCFG_TYPE_DRV:
+		data = readl(base + GPIO_DS0);
+		data = (data >> pin) & 1;
+		*config = data;
+		data = readl(base + GPIO_DS1);
+		data = (data >> pin) & 1;
+		*config |= (data << 1);
+		break;
+	case PINCFG_TYPE_SKEW_RATE:
+		data = readl(base + GPIO_SR);
+		*config = (data >> pin) & 1;
+		break;
+	case PINCFG_TYPE_INPUT_TYPE:
+		data = readl(base + GPIO_TYPE);
+		*config = (data >> pin) & 1;
+		break;
+	default:
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* set the pin config settings for a specified pin group */
+static int exynos5440_pinconf_group_set(struct pinctrl_dev *pctldev,
+			unsigned group, unsigned long config)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+	const unsigned int *pins;
+	unsigned int cnt;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	pins = priv->pin_groups[group].pins;
+
+	for (cnt = 0; cnt < priv->pin_groups[group].num_pins; cnt++)
+		exynos5440_pinconf_set(pctldev, pins[cnt], config);
+
+	return 0;
+}
+
+/* get the pin config settings for a specified pin group */
+static int exynos5440_pinconf_group_get(struct pinctrl_dev *pctldev,
+				unsigned int group, unsigned long *config)
+{
+	struct exynos5440_pinctrl_priv_data *priv;
+	const unsigned int *pins;
+
+	priv = pinctrl_dev_get_drvdata(pctldev);
+	pins = priv->pin_groups[group].pins;
+	exynos5440_pinconf_get(pctldev, pins[0], config);
+	return 0;
+}
+
+/* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */
+static struct pinconf_ops exynos5440_pinconf_ops = {
+	.pin_config_get		= exynos5440_pinconf_get,
+	.pin_config_set		= exynos5440_pinconf_set,
+	.pin_config_group_get	= exynos5440_pinconf_group_get,
+	.pin_config_group_set	= exynos5440_pinconf_group_set,
+};
+
+/* gpiolib gpio_set callback function */
+static void exynos5440_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+{
+	struct exynos5440_pinctrl_priv_data *priv = dev_get_drvdata(gc->dev);
+	void __iomem *base = priv->reg_base;
+	u32 data;
+
+	data = readl(base + GPIO_VAL);
+	data &= ~(1 << offset);
+	if (value)
+		data |= 1 << offset;
+	writel(data, base + GPIO_VAL);
+}
+
+/* gpiolib gpio_get callback function */
+static int exynos5440_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+	struct exynos5440_pinctrl_priv_data *priv = dev_get_drvdata(gc->dev);
+	void __iomem *base = priv->reg_base;
+	u32 data;
+
+	data = readl(base + GPIO_IN);
+	data >>= offset;
+	data &= 1;
+	return data;
+}
+
+/* gpiolib gpio_direction_input callback function */
+static int exynos5440_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+	struct exynos5440_pinctrl_priv_data *priv = dev_get_drvdata(gc->dev);
+	void __iomem *base = priv->reg_base;
+	u32 data;
+
+	/* first disable the data output enable on this pin */
+	data = readl(base + GPIO_OE);
+	data &= ~(1 << offset);
+	writel(data, base + GPIO_OE);
+
+	/* now enable input on this pin */
+	data =  readl(base + GPIO_IE);
+	data |= 1 << offset;
+	writel(data, base + GPIO_IE);
+	return 0;
+}
+
+/* gpiolib gpio_direction_output callback function */
+static int exynos5440_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
+							int value)
+{
+	struct exynos5440_pinctrl_priv_data *priv = dev_get_drvdata(gc->dev);
+	void __iomem *base = priv->reg_base;
+	u32 data;
+
+	exynos5440_gpio_set(gc, offset, value);
+
+	/* first disable the data input enable on this pin */
+	data = readl(base + GPIO_IE);
+	data &= ~(1 << offset);
+	writel(data, base + GPIO_IE);
+
+	/* now enable output on this pin */
+	data =  readl(base + GPIO_OE);
+	data |= 1 << offset;
+	writel(data, base + GPIO_OE);
+	return 0;
+}
+
+/* parse the pin numbers listed in the 'samsung,exynos5440-pins' property */
+static int __init exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev,
+			struct device_node *cfg_np, unsigned int **pin_list,
+			unsigned int *npins)
+{
+	struct device *dev = &pdev->dev;
+	struct property *prop;
+
+	prop = of_find_property(cfg_np, "samsung,exynos5440-pins", NULL);
+	if (!prop)
+		return -ENOENT;
+
+	*npins = prop->length / sizeof(unsigned long);
+	if (!*npins) {
+		dev_err(dev, "invalid pin list in %s node", cfg_np->name);
+		return -EINVAL;
+	}
+
+	*pin_list = devm_kzalloc(dev, *npins * sizeof(**pin_list), GFP_KERNEL);
+	if (!*pin_list) {
+		dev_err(dev, "failed to allocate memory for pin list\n");
+		return -ENOMEM;
+	}
+
+	return of_property_read_u32_array(cfg_np, "samsung,exynos5440-pins",
+			*pin_list, *npins);
+}
+
+/*
+ * Parse the information about all the available pin groups and pin functions
+ * from device node of the pin-controller.
+ */
+static int __init exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
+				struct exynos5440_pinctrl_priv_data *priv)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *dev_np = dev->of_node;
+	struct device_node *cfg_np;
+	struct exynos5440_pin_group *groups, *grp;
+	struct exynos5440_pmx_func *functions, *func;
+	unsigned *pin_list;
+	unsigned int npins, grp_cnt, func_idx = 0;
+	char *gname, *fname;
+	int ret;
+
+	grp_cnt = of_get_child_count(dev_np);
+	if (!grp_cnt)
+		return -EINVAL;
+
+	groups = devm_kzalloc(dev, grp_cnt * sizeof(*groups), GFP_KERNEL);
+	if (!groups) {
+		dev_err(dev, "failed allocate memory for ping group list\n");
+		return -EINVAL;
+	}
+	grp = groups;
+
+	functions = devm_kzalloc(dev, grp_cnt * sizeof(*functions), GFP_KERNEL);
+	if (!functions) {
+		dev_err(dev, "failed to allocate memory for function list\n");
+		return -EINVAL;
+	}
+	func = functions;
+
+	/*
+	 * Iterate over all the child nodes of the pin controller node
+	 * and create pin groups and pin function lists.
+	 */
+	for_each_child_of_node(dev_np, cfg_np) {
+		u32 function;
+
+		ret = exynos5440_pinctrl_parse_dt_pins(pdev, cfg_np,
+					&pin_list, &npins);
+		if (ret)
+			return ret;
+
+		/* derive pin group name from the node name */
+		gname = devm_kzalloc(dev, strlen(cfg_np->name) + GSUFFIX_LEN,
+					GFP_KERNEL);
+		if (!gname) {
+			dev_err(dev, "failed to alloc memory for group name\n");
+			return -ENOMEM;
+		}
+		sprintf(gname, "%s%s", cfg_np->name, GROUP_SUFFIX);
+
+		grp->name = gname;
+		grp->pins = pin_list;
+		grp->num_pins = npins;
+		grp++;
+
+		ret = of_property_read_u32(cfg_np, "samsung,exynos5440-pin-function",
+						&function);
+		if (ret)
+			continue;
+
+		/* derive function name from the node name */
+		fname = devm_kzalloc(dev, strlen(cfg_np->name) + FSUFFIX_LEN,
+					GFP_KERNEL);
+		if (!fname) {
+			dev_err(dev, "failed to alloc memory for func name\n");
+			return -ENOMEM;
+		}
+		sprintf(fname, "%s%s", cfg_np->name, FUNCTION_SUFFIX);
+
+		func->name = fname;
+		func->groups = devm_kzalloc(dev, sizeof(char *), GFP_KERNEL);
+		if (!func->groups) {
+			dev_err(dev, "failed to alloc memory for group list "
+					"in pin function");
+			return -ENOMEM;
+		}
+		func->groups[0] = gname;
+		func->num_groups = 1;
+		func->function = function;
+		func++;
+		func_idx++;
+	}
+
+	priv->pin_groups = groups;
+	priv->nr_groups = grp_cnt;
+	priv->pmx_functions = functions;
+	priv->nr_functions = func_idx;
+	return 0;
+}
+
+/* register the pinctrl interface with the pinctrl subsystem */
+static int __init exynos5440_pinctrl_register(struct platform_device *pdev,
+				struct exynos5440_pinctrl_priv_data *priv)
+{
+	struct device *dev = &pdev->dev;
+	struct pinctrl_desc *ctrldesc;
+	struct pinctrl_dev *pctl_dev;
+	struct pinctrl_pin_desc *pindesc, *pdesc;
+	struct pinctrl_gpio_range grange;
+	char *pin_names;
+	int pin, ret;
+
+	ctrldesc = devm_kzalloc(dev, sizeof(*ctrldesc), GFP_KERNEL);
+	if (!ctrldesc) {
+		dev_err(dev, "could not allocate memory for pinctrl desc\n");
+		return -ENOMEM;
+	}
+
+	ctrldesc->name = "exynos5440-pinctrl";
+	ctrldesc->owner = THIS_MODULE;
+	ctrldesc->pctlops = &exynos5440_pctrl_ops;
+	ctrldesc->pmxops = &exynos5440_pinmux_ops;
+	ctrldesc->confops = &exynos5440_pinconf_ops;
+
+	pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) *
+				EXYNOS5440_MAX_PINS, GFP_KERNEL);
+	if (!pindesc) {
+		dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n");
+		return -ENOMEM;
+	}
+	ctrldesc->pins = pindesc;
+	ctrldesc->npins = EXYNOS5440_MAX_PINS;
+
+	/* dynamically populate the pin number and pin name for pindesc */
+	for (pin = 0, pdesc = pindesc; pin < ctrldesc->npins; pin++, pdesc++)
+		pdesc->number = pin;
+
+	/*
+	 * allocate space for storing the dynamically generated names for all
+	 * the pins which belong to this pin-controller.
+	 */
+	pin_names = devm_kzalloc(&pdev->dev, sizeof(char) * PIN_NAME_LENGTH *
+					ctrldesc->npins, GFP_KERNEL);
+	if (!pin_names) {
+		dev_err(&pdev->dev, "mem alloc for pin names failed\n");
+		return -ENOMEM;
+	}
+
+	/* for each pin, set the name of the pin */
+	for (pin = 0; pin < ctrldesc->npins; pin++) {
+		sprintf(pin_names, "gpio%02d", pin);
+		pdesc = pindesc + pin;
+		pdesc->name = pin_names;
+		pin_names += PIN_NAME_LENGTH;
+	}
+
+	ret = exynos5440_pinctrl_parse_dt(pdev, priv);
+	if (ret)
+		return ret;
+
+	pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, priv);
+	if (!pctl_dev) {
+		dev_err(&pdev->dev, "could not register pinctrl driver\n");
+		return -EINVAL;
+	}
+
+	grange.name = "exynos5440-pctrl-gpio-range";
+	grange.id = 0;
+	grange.base = 0;
+	grange.npins = EXYNOS5440_MAX_PINS;
+	grange.gc = priv->gc;
+	pinctrl_add_gpio_range(pctl_dev, &grange);
+	return 0;
+}
+
+/* register the gpiolib interface with the gpiolib subsystem */
+static int __init exynos5440_gpiolib_register(struct platform_device *pdev,
+				struct exynos5440_pinctrl_priv_data *priv)
+{
+	struct gpio_chip *gc;
+	int ret;
+
+	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
+	if (!gc) {
+		dev_err(&pdev->dev, "mem alloc for gpio_chip failed\n");
+		return -ENOMEM;
+	}
+
+	priv->gc = gc;
+	gc->base = 0;
+	gc->ngpio = EXYNOS5440_MAX_PINS;
+	gc->dev = &pdev->dev;
+	gc->set = exynos5440_gpio_set;
+	gc->get = exynos5440_gpio_get;
+	gc->direction_input = exynos5440_gpio_direction_input;
+	gc->direction_output = exynos5440_gpio_direction_output;
+	gc->label = "gpiolib-exynos5440";
+	gc->owner = THIS_MODULE;
+	ret = gpiochip_add(gc);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register gpio_chip %s, error "
+					"code: %d\n", gc->label, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/* unregister the gpiolib interface with the gpiolib subsystem */
+static int __init exynos5440_gpiolib_unregister(struct platform_device *pdev,
+				struct exynos5440_pinctrl_priv_data *priv)
+{
+	int ret = gpiochip_remove(priv->gc);
+	if (ret) {
+		dev_err(&pdev->dev, "gpio chip remove failed\n");
+		return ret;
+	}
+	return 0;
+}
+
+static int __devinit exynos5440_pinctrl_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct exynos5440_pinctrl_priv_data *priv;
+	struct resource *res;
+	int ret;
+
+	if (!dev->of_node) {
+		dev_err(dev, "device tree node not found\n");
+		return -ENODEV;
+	}
+
+	priv = devm_kzalloc(dev, sizeof(priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(dev, "could not allocate memory for private data\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "cannot find IO resource\n");
+		return -ENOENT;
+	}
+
+	priv->reg_base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!priv->reg_base) {
+		dev_err(dev, "ioremap failed\n");
+		return -ENODEV;
+	}
+
+	ret = exynos5440_gpiolib_register(pdev, priv);
+	if (ret)
+		return ret;
+
+	ret = exynos5440_pinctrl_register(pdev, priv);
+	if (ret) {
+		exynos5440_gpiolib_unregister(pdev, priv);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv);
+	dev_info(dev, "EXYNOS5440 pinctrl driver registered\n");
+	return 0;
+}
+
+static const struct of_device_id exynos5440_pinctrl_dt_match[] = {
+	{ .compatible = "samsung,exynos5440-pinctrl" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, exynos5440_pinctrl_dt_match);
+
+static struct platform_driver exynos5440_pinctrl_driver = {
+	.probe		= exynos5440_pinctrl_probe,
+	.driver = {
+		.name	= "exynos5440-pinctrl",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(exynos5440_pinctrl_dt_match),
+	},
+};
+
+static int __init exynos5440_pinctrl_drv_register(void)
+{
+	return platform_driver_register(&exynos5440_pinctrl_driver);
+}
+postcore_initcall(exynos5440_pinctrl_drv_register);
+
+static void __exit exynos5440_pinctrl_drv_unregister(void)
+{
+	platform_driver_unregister(&exynos5440_pinctrl_driver);
+}
+module_exit(exynos5440_pinctrl_drv_unregister);
+
+MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>");
+MODULE_DESCRIPTION("Samsung EXYNOS5440 SoC pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-falcon.c b/drivers/pinctrl/pinctrl-falcon.c
index ee73059..8ed20e8 100644
--- a/drivers/pinctrl/pinctrl-falcon.c
+++ b/drivers/pinctrl/pinctrl-falcon.c
@@ -322,7 +322,7 @@ static void falcon_pinconf_group_dbg_show(struct pinctrl_dev *pctrldev,
 {
 }
 
-struct pinconf_ops falcon_pinconf_ops = {
+static struct pinconf_ops falcon_pinconf_ops = {
 	.pin_config_get			= falcon_pinconf_get,
 	.pin_config_set			= falcon_pinconf_set,
 	.pin_config_group_get		= falcon_pinconf_group_get,
diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c
index 63866d9..131d86d 100644
--- a/drivers/pinctrl/pinctrl-imx.c
+++ b/drivers/pinctrl/pinctrl-imx.c
@@ -71,7 +71,7 @@ static const struct imx_pin_reg *imx_find_pin_reg(
 			break;
 	}
 
-	if (!pin_reg) {
+	if (i == info->npin_regs) {
 		dev_err(info->dev, "Pin(%s): unable to find pin reg map\n",
 			info->pins[pin].name);
 		return NULL;
@@ -397,7 +397,7 @@ static void imx_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
 	}
 }
 
-struct pinconf_ops imx_pinconf_ops = {
+static struct pinconf_ops imx_pinconf_ops = {
 	.pin_config_get = imx_pinconf_get,
 	.pin_config_set = imx_pinconf_set,
 	.pin_config_dbg_show = imx_pinconf_dbg_show,
@@ -611,7 +611,7 @@ int __devinit imx_pinctrl_probe(struct platform_device *pdev,
 	return 0;
 }
 
-int __devexit imx_pinctrl_remove(struct platform_device *pdev)
+int imx_pinctrl_remove(struct platform_device *pdev)
 {
 	struct imx_pinctrl *ipctl = platform_get_drvdata(pdev);
 
diff --git a/drivers/pinctrl/pinctrl-imx23.c b/drivers/pinctrl/pinctrl-imx23.c
index 3674d87..04364f7 100644
--- a/drivers/pinctrl/pinctrl-imx23.c
+++ b/drivers/pinctrl/pinctrl-imx23.c
@@ -272,7 +272,7 @@ static int __devinit imx23_pinctrl_probe(struct platform_device *pdev)
 	return mxs_pinctrl_probe(pdev, &imx23_pinctrl_data);
 }
 
-static struct of_device_id imx23_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id imx23_pinctrl_of_match[] = {
 	{ .compatible = "fsl,imx23-pinctrl", },
 	{ /* sentinel */ }
 };
@@ -285,7 +285,7 @@ static struct platform_driver imx23_pinctrl_driver = {
 		.of_match_table = imx23_pinctrl_of_match,
 	},
 	.probe = imx23_pinctrl_probe,
-	.remove = __devexit_p(mxs_pinctrl_remove),
+	.remove = mxs_pinctrl_remove,
 };
 
 static int __init imx23_pinctrl_init(void)
diff --git a/drivers/pinctrl/pinctrl-imx28.c b/drivers/pinctrl/pinctrl-imx28.c
index 0f5b212..e1af2ba 100644
--- a/drivers/pinctrl/pinctrl-imx28.c
+++ b/drivers/pinctrl/pinctrl-imx28.c
@@ -388,7 +388,7 @@ static int __devinit imx28_pinctrl_probe(struct platform_device *pdev)
 	return mxs_pinctrl_probe(pdev, &imx28_pinctrl_data);
 }
 
-static struct of_device_id imx28_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id imx28_pinctrl_of_match[] = {
 	{ .compatible = "fsl,imx28-pinctrl", },
 	{ /* sentinel */ }
 };
@@ -401,7 +401,7 @@ static struct platform_driver imx28_pinctrl_driver = {
 		.of_match_table = imx28_pinctrl_of_match,
 	},
 	.probe = imx28_pinctrl_probe,
-	.remove = __devexit_p(mxs_pinctrl_remove),
+	.remove = mxs_pinctrl_remove,
 };
 
 static int __init imx28_pinctrl_init(void)
diff --git a/drivers/pinctrl/pinctrl-imx35.c b/drivers/pinctrl/pinctrl-imx35.c
index 82f109e..1dbf5278 100644
--- a/drivers/pinctrl/pinctrl-imx35.c
+++ b/drivers/pinctrl/pinctrl-imx35.c
@@ -1559,7 +1559,7 @@ static struct imx_pinctrl_soc_info imx35_pinctrl_info = {
 	.npin_regs = ARRAY_SIZE(imx35_pin_regs),
 };
 
-static struct of_device_id imx35_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id imx35_pinctrl_of_match[] = {
 	{ .compatible = "fsl,imx35-iomuxc", },
 	{ /* sentinel */ }
 };
@@ -1576,7 +1576,7 @@ static struct platform_driver imx35_pinctrl_driver = {
 		.of_match_table = of_match_ptr(imx35_pinctrl_of_match),
 	},
 	.probe = imx35_pinctrl_probe,
-	.remove = __devexit_p(imx_pinctrl_remove),
+	.remove = imx_pinctrl_remove,
 };
 
 static int __init imx35_pinctrl_init(void)
diff --git a/drivers/pinctrl/pinctrl-imx51.c b/drivers/pinctrl/pinctrl-imx51.c
index fb84689..1312165 100644
--- a/drivers/pinctrl/pinctrl-imx51.c
+++ b/drivers/pinctrl/pinctrl-imx51.c
@@ -1286,7 +1286,7 @@ static struct imx_pinctrl_soc_info imx51_pinctrl_info = {
 	.npin_regs = ARRAY_SIZE(imx51_pin_regs),
 };
 
-static struct of_device_id imx51_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id imx51_pinctrl_of_match[] = {
 	{ .compatible = "fsl,imx51-iomuxc", },
 	{ /* sentinel */ }
 };
@@ -1303,7 +1303,7 @@ static struct platform_driver imx51_pinctrl_driver = {
 		.of_match_table = of_match_ptr(imx51_pinctrl_of_match),
 	},
 	.probe = imx51_pinctrl_probe,
-	.remove = __devexit_p(imx_pinctrl_remove),
+	.remove = imx_pinctrl_remove,
 };
 
 static int __init imx51_pinctrl_init(void)
diff --git a/drivers/pinctrl/pinctrl-imx53.c b/drivers/pinctrl/pinctrl-imx53.c
index 783feb1..ec40486 100644
--- a/drivers/pinctrl/pinctrl-imx53.c
+++ b/drivers/pinctrl/pinctrl-imx53.c
@@ -1613,7 +1613,7 @@ static struct imx_pinctrl_soc_info imx53_pinctrl_info = {
 	.npin_regs = ARRAY_SIZE(imx53_pin_regs),
 };
 
-static struct of_device_id imx53_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id imx53_pinctrl_of_match[] = {
 	{ .compatible = "fsl,imx53-iomuxc", },
 	{ /* sentinel */ }
 };
@@ -1630,7 +1630,7 @@ static struct platform_driver imx53_pinctrl_driver = {
 		.of_match_table = of_match_ptr(imx53_pinctrl_of_match),
 	},
 	.probe = imx53_pinctrl_probe,
-	.remove = __devexit_p(imx_pinctrl_remove),
+	.remove = imx_pinctrl_remove,
 };
 
 static int __init imx53_pinctrl_init(void)
diff --git a/drivers/pinctrl/pinctrl-imx6q.c b/drivers/pinctrl/pinctrl-imx6q.c
index e9bf71f..844ab13 100644
--- a/drivers/pinctrl/pinctrl-imx6q.c
+++ b/drivers/pinctrl/pinctrl-imx6q.c
@@ -2297,7 +2297,7 @@ static struct imx_pinctrl_soc_info imx6q_pinctrl_info = {
 	.npin_regs = ARRAY_SIZE(imx6q_pin_regs),
 };
 
-static struct of_device_id imx6q_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id imx6q_pinctrl_of_match[] = {
 	{ .compatible = "fsl,imx6q-iomuxc", },
 	{ /* sentinel */ }
 };
@@ -2314,7 +2314,7 @@ static struct platform_driver imx6q_pinctrl_driver = {
 		.of_match_table = of_match_ptr(imx6q_pinctrl_of_match),
 	},
 	.probe = imx6q_pinctrl_probe,
-	.remove = __devexit_p(imx_pinctrl_remove),
+	.remove = imx_pinctrl_remove,
 };
 
 static int __init imx6q_pinctrl_init(void)
diff --git a/drivers/pinctrl/pinctrl-kirkwood.c b/drivers/pinctrl/pinctrl-kirkwood.c
deleted file mode 100644
index 9a74ef6..0000000
--- a/drivers/pinctrl/pinctrl-kirkwood.c
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * Marvell Kirkwood pinctrl driver based on mvebu pinctrl core
- *
- * Author: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/pinctrl/pinctrl.h>
-
-#include "pinctrl-mvebu.h"
-
-#define V(f6180, f6190, f6192, f6281, f6282)		\
-	((f6180 << 0) | (f6190 << 1) | (f6192 << 2) |	\
-	 (f6281 << 3) | (f6282 << 4))
-
-enum kirkwood_variant {
-	VARIANT_MV88F6180 = V(1, 0, 0, 0, 0),
-	VARIANT_MV88F6190 = V(0, 1, 0, 0, 0),
-	VARIANT_MV88F6192 = V(0, 0, 1, 0, 0),
-	VARIANT_MV88F6281 = V(0, 0, 0, 1, 0),
-	VARIANT_MV88F6282 = V(0, 0, 0, 0, 1),
-};
-
-static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
-	MPP_MODE(0,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "nand", "io2",     V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "spi", "cs",       V(1, 1, 1, 1, 1))),
-	MPP_MODE(1,
-		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "nand", "io3",     V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "spi", "mosi",     V(1, 1, 1, 1, 1))),
-	MPP_MODE(2,
-		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "nand", "io4",     V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "spi", "sck",      V(1, 1, 1, 1, 1))),
-	MPP_MODE(3,
-		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "nand", "io5",     V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "spi", "miso",     V(1, 1, 1, 1, 1))),
-	MPP_MODE(4,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "nand", "io6",     V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "uart0", "rxd",    V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "hsync",    V(0, 0, 0, 0, 1)),
-		MPP_VAR_FUNCTION(0xd, "ptp", "clk",      V(1, 1, 1, 1, 0))),
-	MPP_MODE(5,
-		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "nand", "io7",     V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "uart0", "txd",    V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "ptp", "trig",     V(1, 1, 1, 1, 0)),
-		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "vsync",    V(0, 0, 0, 0, 1))),
-	MPP_MODE(6,
-		MPP_VAR_FUNCTION(0x0, "sysrst", "out",   V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "spi", "mosi",     V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "ptp", "trig",     V(1, 1, 1, 1, 0))),
-	MPP_MODE(7,
-		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "pex", "rsto",     V(1, 1, 1, 1, 0)),
-		MPP_VAR_FUNCTION(0x2, "spi", "cs",       V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ptp", "trig",     V(1, 1, 1, 1, 0)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "pwm",      V(0, 0, 0, 0, 1))),
-	MPP_MODE(8,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "twsi0", "sda",    V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "uart0", "rts",    V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "uart1", "rts",    V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "mii-1", "rxerr",  V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x5, "sata1", "prsnt",  V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xc, "ptp", "clk",      V(1, 1, 1, 1, 0)),
-		MPP_VAR_FUNCTION(0xd, "mii", "col",      V(1, 1, 1, 1, 1))),
-	MPP_MODE(9,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "twsi0", "sck",    V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "uart0", "cts",    V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "uart1", "cts",    V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x5, "sata0", "prsnt",  V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xc, "ptp", "evreq",    V(1, 1, 1, 1, 0)),
-		MPP_VAR_FUNCTION(0xd, "mii", "crs",      V(1, 1, 1, 1, 1))),
-	MPP_MODE(10,
-		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "spi", "sck",      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0X3, "uart0", "txd",    V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xc, "ptp", "trig",     V(1, 1, 1, 1, 0))),
-	MPP_MODE(11,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "spi", "miso",     V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "uart0", "rxd",    V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "ptp-1", "evreq",  V(1, 1, 1, 1, 0)),
-		MPP_VAR_FUNCTION(0xc, "ptp-2", "trig",   V(1, 1, 1, 1, 0)),
-		MPP_VAR_FUNCTION(0xd, "ptp", "clk",      V(1, 1, 1, 1, 0)),
-		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1))),
-	MPP_MODE(12,
-		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 0, 1)),
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 0)),
-		MPP_VAR_FUNCTION(0x1, "sdio", "clk",     V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xa, "audio", "spdifo", V(0, 0, 0, 0, 1)),
-		MPP_VAR_FUNCTION(0xb, "spi", "mosi",     V(0, 0, 0, 0, 1)),
-		MPP_VAR_FUNCTION(0xd, "twsi1", "sda",    V(0, 0, 0, 0, 1))),
-	MPP_MODE(13,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "sdio", "cmd",     V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "uart1", "txd",    V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xa, "audio", "rmclk",  V(0, 0, 0, 0, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "pwm",      V(0, 0, 0, 0, 1))),
-	MPP_MODE(14,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "sdio", "d0",      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "uart1", "rxd",    V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "sata1", "prsnt",  V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xa, "audio", "spdifi", V(0, 0, 0, 0, 1)),
-		MPP_VAR_FUNCTION(0xb, "audio-1", "sdi",  V(0, 0, 0, 0, 1)),
-		MPP_VAR_FUNCTION(0xd, "mii", "col",      V(1, 1, 1, 1, 1))),
-	MPP_MODE(15,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "sdio", "d1",      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "uart0", "rts",    V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "uart1", "txd",    V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "sata0", "act",    V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "spi", "cs",       V(0, 0, 0, 0, 1))),
-	MPP_MODE(16,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "sdio", "d2",      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "uart0", "cts",    V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "uart1", "rxd",    V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "sata1", "act",    V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "extclk",   V(0, 0, 0, 0, 1)),
-		MPP_VAR_FUNCTION(0xd, "mii", "crs",      V(1, 1, 1, 1, 1))),
-	MPP_MODE(17,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "sdio", "d3",      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "sata0", "prsnt",  V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xa, "sata1", "act",    V(0, 0, 0, 0, 1)),
-		MPP_VAR_FUNCTION(0xd, "twsi1", "sck",    V(0, 0, 0, 0, 1))),
-	MPP_MODE(18,
-		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "nand", "io0",     V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "pex", "clkreq",   V(0, 0, 0, 0, 1))),
-	MPP_MODE(19,
-		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "nand", "io1",     V(1, 1, 1, 1, 1))),
-	MPP_MODE(20,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp0",       V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql",    V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ge1", "txd0",     V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d0",       V(0, 0, 0, 0, 1)),
-		MPP_VAR_FUNCTION(0xc, "mii", "rxerr",    V(1, 0, 0, 0, 0))),
-	MPP_MODE(21,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp1",       V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql",    V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ge1", "txd1",     V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(1, 0, 0, 0, 0)),
-		MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d1",       V(0, 0, 0, 0, 1))),
-	MPP_MODE(22,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp2",       V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql",    V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ge1", "txd2",     V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(1, 0, 0, 0, 0)),
-		MPP_VAR_FUNCTION(0x4, "audio", "rmclk",  V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x5, "sata1", "prsnt",  V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d2",       V(0, 0, 0, 0, 1))),
-	MPP_MODE(23,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp3",       V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql",    V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ge1", "txd3",     V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "rmclk",  V(1, 0, 0, 0, 0)),
-		MPP_VAR_FUNCTION(0x4, "audio", "bclk",   V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x5, "sata0", "prsnt",  V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d3",       V(0, 0, 0, 0, 1))),
-	MPP_MODE(24,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp4",       V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0",  V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ge1", "rxd0",     V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "bclk",   V(1, 0, 0, 0, 0)),
-		MPP_VAR_FUNCTION(0x4, "audio", "sdo",    V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d4",       V(0, 0, 0, 0, 1))),
-	MPP_MODE(25,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp5",       V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck",  V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ge1", "rxd1",     V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "sdo",    V(1, 0, 0, 0, 0)),
-		MPP_VAR_FUNCTION(0x4, "audio", "lrclk",  V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d5",       V(0, 0, 0, 0, 1))),
-	MPP_MODE(26,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp6",       V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ge1", "rxd2",     V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "lrclk",  V(1, 0, 0, 0, 0)),
-		MPP_VAR_FUNCTION(0x4, "audio", "mclk",   V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d6",       V(0, 0, 0, 0, 1))),
-	MPP_MODE(27,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp7",       V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ge1", "rxd3",     V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "mclk",   V(1, 0, 0, 0, 0)),
-		MPP_VAR_FUNCTION(0x4, "audio", "sdi",    V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d7",       V(0, 0, 0, 0, 1))),
-	MPP_MODE(28,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp8",       V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "int",      V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ge1", "col",      V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "sdi",    V(1, 0, 0, 0, 0)),
-		MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d8",       V(0, 0, 0, 0, 1))),
-	MPP_MODE(29,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp9",       V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "rst",      V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ge1", "txclk",    V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(1, 0, 0, 0, 0)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d9",       V(0, 0, 0, 0, 1))),
-	MPP_MODE(30,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp10",      V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "pclk",     V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ge1", "rxctl",    V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d10",      V(0, 0, 0, 0, 1))),
-	MPP_MODE(31,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp11",      V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "fs",       V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ge1", "rxclk",    V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d11",      V(0, 0, 0, 0, 1))),
-	MPP_MODE(32,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp12",      V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "drx",      V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ge1", "txclko",   V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d12",      V(0, 0, 0, 0, 1))),
-	MPP_MODE(33,
-		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "dtx",      V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ge1", "txctl",    V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d13",      V(0, 0, 0, 0, 1))),
-	MPP_MODE(34,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1",  V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ge1", "txen",     V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d14",      V(0, 0, 0, 0, 1))),
-	MPP_MODE(35,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql",    V(0, 0, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x3, "ge1", "rxerr",    V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d15",      V(0, 0, 0, 0, 1)),
-		MPP_VAR_FUNCTION(0xc, "mii", "rxerr",    V(0, 1, 1, 1, 1))),
-	MPP_MODE(36,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp0",       V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1",  V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "twsi1", "sda",    V(0, 0, 0, 0, 1))),
-	MPP_MODE(37,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp1",       V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql",    V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "twsi1", "sck",    V(0, 0, 0, 0, 1))),
-	MPP_MODE(38,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp2",       V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql",    V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "rmclk",  V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d18",      V(0, 0, 0, 0, 1))),
-	MPP_MODE(39,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp3",       V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0",  V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "bclk",   V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d19",      V(0, 0, 0, 0, 1))),
-	MPP_MODE(40,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp4",       V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck",  V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "sdo",    V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d20",      V(0, 0, 0, 0, 1))),
-	MPP_MODE(41,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp5",       V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "lrclk",  V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d21",      V(0, 0, 0, 0, 1))),
-	MPP_MODE(42,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp6",       V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "mclk",   V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d22",      V(0, 0, 0, 0, 1))),
-	MPP_MODE(43,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp7",       V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "int",      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "sdi",    V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d23",      V(0, 0, 0, 0, 1))),
-	MPP_MODE(44,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp8",       V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "rst",      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "clk",      V(0, 0, 0, 0, 1))),
-	MPP_MODE(45,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp9",       V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "pclk",     V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "e",        V(0, 0, 0, 0, 1))),
-	MPP_MODE(46,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp10",      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "fs",       V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "hsync",    V(0, 0, 0, 0, 1))),
-	MPP_MODE(47,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp11",      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "drx",      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "vsync",    V(0, 0, 0, 0, 1))),
-	MPP_MODE(48,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp12",      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "dtx",      V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d16",      V(0, 0, 0, 0, 1))),
-	MPP_MODE(49,
-		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 0)),
-		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(0, 0, 0, 0, 1)),
-		MPP_VAR_FUNCTION(0x1, "ts", "mp9",       V(0, 0, 0, 1, 0)),
-		MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql",    V(0, 0, 0, 1, 1)),
-		MPP_VAR_FUNCTION(0x5, "ptp", "clk",      V(0, 0, 0, 1, 0)),
-		MPP_VAR_FUNCTION(0xa, "pex", "clkreq",   V(0, 0, 0, 0, 1)),
-		MPP_VAR_FUNCTION(0xb, "lcd", "d17",      V(0, 0, 0, 0, 1))),
-};
-
-static struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
-	MPP_REG_CTRL(0, 29),
-};
-
-static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
-	MPP_GPIO_RANGE(0, 0, 0, 30),
-};
-
-static struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = {
-	MPP_REG_CTRL(0, 35),
-};
-
-static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
-	MPP_GPIO_RANGE(0,  0,  0, 32),
-	MPP_GPIO_RANGE(1, 32, 32,  4),
-};
-
-static struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = {
-	MPP_REG_CTRL(0, 49),
-};
-
-static struct pinctrl_gpio_range mv88f628x_gpio_ranges[] = {
-	MPP_GPIO_RANGE(0,  0,  0, 32),
-	MPP_GPIO_RANGE(1, 32, 32, 18),
-};
-
-static struct mvebu_pinctrl_soc_info mv88f6180_info = {
-	.variant = VARIANT_MV88F6180,
-	.controls = mv88f6180_mpp_controls,
-	.ncontrols = ARRAY_SIZE(mv88f6180_mpp_controls),
-	.modes = mv88f6xxx_mpp_modes,
-	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
-	.gpioranges = mv88f6180_gpio_ranges,
-	.ngpioranges = ARRAY_SIZE(mv88f6180_gpio_ranges),
-};
-
-static struct mvebu_pinctrl_soc_info mv88f6190_info = {
-	.variant = VARIANT_MV88F6190,
-	.controls = mv88f619x_mpp_controls,
-	.ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls),
-	.modes = mv88f6xxx_mpp_modes,
-	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
-	.gpioranges = mv88f619x_gpio_ranges,
-	.ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges),
-};
-
-static struct mvebu_pinctrl_soc_info mv88f6192_info = {
-	.variant = VARIANT_MV88F6192,
-	.controls = mv88f619x_mpp_controls,
-	.ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls),
-	.modes = mv88f6xxx_mpp_modes,
-	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
-	.gpioranges = mv88f619x_gpio_ranges,
-	.ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges),
-};
-
-static struct mvebu_pinctrl_soc_info mv88f6281_info = {
-	.variant = VARIANT_MV88F6281,
-	.controls = mv88f628x_mpp_controls,
-	.ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
-	.modes = mv88f6xxx_mpp_modes,
-	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
-	.gpioranges = mv88f628x_gpio_ranges,
-	.ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
-};
-
-static struct mvebu_pinctrl_soc_info mv88f6282_info = {
-	.variant = VARIANT_MV88F6282,
-	.controls = mv88f628x_mpp_controls,
-	.ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
-	.modes = mv88f6xxx_mpp_modes,
-	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
-	.gpioranges = mv88f628x_gpio_ranges,
-	.ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
-};
-
-static struct of_device_id kirkwood_pinctrl_of_match[] __devinitdata = {
-	{ .compatible = "marvell,88f6180-pinctrl", .data = &mv88f6180_info },
-	{ .compatible = "marvell,88f6190-pinctrl", .data = &mv88f6190_info },
-	{ .compatible = "marvell,88f6192-pinctrl", .data = &mv88f6192_info },
-	{ .compatible = "marvell,88f6281-pinctrl", .data = &mv88f6281_info },
-	{ .compatible = "marvell,88f6282-pinctrl", .data = &mv88f6282_info },
-	{ }
-};
-
-static int __devinit kirkwood_pinctrl_probe(struct platform_device *pdev)
-{
-	const struct of_device_id *match =
-		of_match_device(kirkwood_pinctrl_of_match, &pdev->dev);
-	pdev->dev.platform_data = match->data;
-	return mvebu_pinctrl_probe(pdev);
-}
-
-static int __devexit kirkwood_pinctrl_remove(struct platform_device *pdev)
-{
-	return mvebu_pinctrl_remove(pdev);
-}
-
-static struct platform_driver kirkwood_pinctrl_driver = {
-	.driver = {
-		.name = "kirkwood-pinctrl",
-		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(kirkwood_pinctrl_of_match),
-	},
-	.probe = kirkwood_pinctrl_probe,
-	.remove = __devexit_p(kirkwood_pinctrl_remove),
-};
-
-module_platform_driver(kirkwood_pinctrl_driver);
-
-MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
-MODULE_DESCRIPTION("Marvell Kirkwood pinctrl driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-lantiq.c b/drivers/pinctrl/pinctrl-lantiq.c
index 07ba768..15f501d 100644
--- a/drivers/pinctrl/pinctrl-lantiq.c
+++ b/drivers/pinctrl/pinctrl-lantiq.c
@@ -46,8 +46,8 @@ static int ltq_get_group_pins(struct pinctrl_dev *pctrldev,
 	return 0;
 }
 
-void ltq_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
-				struct pinctrl_map *map, unsigned num_maps)
+static void ltq_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+				    struct pinctrl_map *map, unsigned num_maps)
 {
 	int i;
 
@@ -128,10 +128,10 @@ static int ltq_pinctrl_dt_subnode_size(struct device_node *np)
 	return ret;
 }
 
-int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
-				struct device_node *np_config,
-				struct pinctrl_map **map,
-				unsigned *num_maps)
+static int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+				      struct device_node *np_config,
+				      struct pinctrl_map **map,
+				      unsigned *num_maps)
 {
 	struct pinctrl_map *tmp;
 	struct device_node *np;
@@ -275,16 +275,6 @@ static int ltq_pmx_enable(struct pinctrl_dev *pctrldev,
 	return 0;
 }
 
-static void ltq_pmx_disable(struct pinctrl_dev *pctrldev,
-				unsigned func,
-				unsigned group)
-{
-	/*
-	 * Nothing to do here. However, pinconf_check_ops() requires this
-	 * callback to be defined.
-	 */
-}
-
 static int ltq_pmx_gpio_request_enable(struct pinctrl_dev *pctrldev,
 				struct pinctrl_gpio_range *range,
 				unsigned pin)
@@ -312,7 +302,6 @@ static struct pinmux_ops ltq_pmx_ops = {
 	.get_function_name	= ltq_pmx_func_name,
 	.get_function_groups	= ltq_pmx_get_groups,
 	.enable			= ltq_pmx_enable,
-	.disable		= ltq_pmx_disable,
 	.gpio_request_enable	= ltq_pmx_gpio_request_enable,
 };
 
diff --git a/drivers/pinctrl/pinctrl-mmp2.c b/drivers/pinctrl/pinctrl-mmp2.c
index 2cfed55..4fbb3db 100644
--- a/drivers/pinctrl/pinctrl-mmp2.c
+++ b/drivers/pinctrl/pinctrl-mmp2.c
@@ -691,7 +691,7 @@ static int __devinit mmp2_pinmux_probe(struct platform_device *pdev)
 	return pxa3xx_pinctrl_register(pdev, &mmp2_info);
 }
 
-static int __devexit mmp2_pinmux_remove(struct platform_device *pdev)
+static int mmp2_pinmux_remove(struct platform_device *pdev)
 {
 	return pxa3xx_pinctrl_unregister(pdev);
 }
@@ -702,7 +702,7 @@ static struct platform_driver mmp2_pinmux_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe	= mmp2_pinmux_probe,
-	.remove	= __devexit_p(mmp2_pinmux_remove),
+	.remove	= mmp2_pinmux_remove,
 };
 
 static int __init mmp2_pinmux_init(void)
diff --git a/drivers/pinctrl/pinctrl-mvebu.c b/drivers/pinctrl/pinctrl-mvebu.c
deleted file mode 100644
index 8e6266c..0000000
--- a/drivers/pinctrl/pinctrl-mvebu.c
+++ /dev/null
@@ -1,754 +0,0 @@
-/*
- * Marvell MVEBU pinctrl core driver
- *
- * Authors: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
- *          Thomas Petazzoni <thomas.petazzoni@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.
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/pinctrl/machine.h>
-#include <linux/pinctrl/pinconf.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-
-#include "core.h"
-#include "pinctrl-mvebu.h"
-
-#define MPPS_PER_REG	8
-#define MPP_BITS	4
-#define MPP_MASK	0xf
-
-struct mvebu_pinctrl_function {
-	const char *name;
-	const char **groups;
-	unsigned num_groups;
-};
-
-struct mvebu_pinctrl_group {
-	const char *name;
-	struct mvebu_mpp_ctrl *ctrl;
-	struct mvebu_mpp_ctrl_setting *settings;
-	unsigned num_settings;
-	unsigned gid;
-	unsigned *pins;
-	unsigned npins;
-};
-
-struct mvebu_pinctrl {
-	struct device *dev;
-	struct pinctrl_dev *pctldev;
-	struct pinctrl_desc desc;
-	void __iomem *base;
-	struct mvebu_pinctrl_group *groups;
-	unsigned num_groups;
-	struct mvebu_pinctrl_function *functions;
-	unsigned num_functions;
-	u8 variant;
-};
-
-static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_pid(
-	struct mvebu_pinctrl *pctl, unsigned pid)
-{
-	unsigned n;
-	for (n = 0; n < pctl->num_groups; n++) {
-		if (pid >= pctl->groups[n].pins[0] &&
-		    pid < pctl->groups[n].pins[0] +
-			pctl->groups[n].npins)
-			return &pctl->groups[n];
-	}
-	return NULL;
-}
-
-static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_name(
-	struct mvebu_pinctrl *pctl, const char *name)
-{
-	unsigned n;
-	for (n = 0; n < pctl->num_groups; n++) {
-		if (strcmp(name, pctl->groups[n].name) == 0)
-			return &pctl->groups[n];
-	}
-	return NULL;
-}
-
-static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_val(
-	struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp,
-	unsigned long config)
-{
-	unsigned n;
-	for (n = 0; n < grp->num_settings; n++) {
-		if (config == grp->settings[n].val) {
-			if (!pctl->variant || (pctl->variant &
-					       grp->settings[n].variant))
-				return &grp->settings[n];
-		}
-	}
-	return NULL;
-}
-
-static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_name(
-	struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp,
-	const char *name)
-{
-	unsigned n;
-	for (n = 0; n < grp->num_settings; n++) {
-		if (strcmp(name, grp->settings[n].name) == 0) {
-			if (!pctl->variant || (pctl->variant &
-					       grp->settings[n].variant))
-				return &grp->settings[n];
-		}
-	}
-	return NULL;
-}
-
-static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_gpio_setting(
-	struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp)
-{
-	unsigned n;
-	for (n = 0; n < grp->num_settings; n++) {
-		if (grp->settings[n].flags &
-			(MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {
-			if (!pctl->variant || (pctl->variant &
-						grp->settings[n].variant))
-				return &grp->settings[n];
-		}
-	}
-	return NULL;
-}
-
-static struct mvebu_pinctrl_function *mvebu_pinctrl_find_function_by_name(
-	struct mvebu_pinctrl *pctl, const char *name)
-{
-	unsigned n;
-	for (n = 0; n < pctl->num_functions; n++) {
-		if (strcmp(name, pctl->functions[n].name) == 0)
-			return &pctl->functions[n];
-	}
-	return NULL;
-}
-
-/*
- * Common mpp pin configuration registers on MVEBU are
- * registers of eight 4-bit values for each mpp setting.
- * Register offset and bit mask are calculated accordingly below.
- */
-static int mvebu_common_mpp_get(struct mvebu_pinctrl *pctl,
-				struct mvebu_pinctrl_group *grp,
-				unsigned long *config)
-{
-	unsigned pin = grp->gid;
-	unsigned off = (pin / MPPS_PER_REG) * MPP_BITS;
-	unsigned shift = (pin % MPPS_PER_REG) * MPP_BITS;
-
-	*config = readl(pctl->base + off);
-	*config >>= shift;
-	*config &= MPP_MASK;
-
-	return 0;
-}
-
-static int mvebu_common_mpp_set(struct mvebu_pinctrl *pctl,
-				struct mvebu_pinctrl_group *grp,
-				unsigned long config)
-{
-	unsigned pin = grp->gid;
-	unsigned off = (pin / MPPS_PER_REG) * MPP_BITS;
-	unsigned shift = (pin % MPPS_PER_REG) * MPP_BITS;
-	unsigned long reg;
-
-	reg = readl(pctl->base + off);
-	reg &= ~(MPP_MASK << shift);
-	reg |= (config << shift);
-	writel(reg, pctl->base + off);
-
-	return 0;
-}
-
-static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev,
-				unsigned gid, unsigned long *config)
-{
-	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
-	struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
-
-	if (!grp->ctrl)
-		return -EINVAL;
-
-	if (grp->ctrl->mpp_get)
-		return grp->ctrl->mpp_get(grp->ctrl, config);
-
-	return mvebu_common_mpp_get(pctl, grp, config);
-}
-
-static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev,
-				unsigned gid, unsigned long config)
-{
-	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
-	struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
-
-	if (!grp->ctrl)
-		return -EINVAL;
-
-	if (grp->ctrl->mpp_set)
-		return grp->ctrl->mpp_set(grp->ctrl, config);
-
-	return mvebu_common_mpp_set(pctl, grp, config);
-}
-
-static void mvebu_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
-					struct seq_file *s, unsigned gid)
-{
-	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
-	struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
-	struct mvebu_mpp_ctrl_setting *curr;
-	unsigned long config;
-	unsigned n;
-
-	if (mvebu_pinconf_group_get(pctldev, gid, &config))
-		return;
-
-	curr = mvebu_pinctrl_find_setting_by_val(pctl, grp, config);
-
-	if (curr) {
-		seq_printf(s, "current: %s", curr->name);
-		if (curr->subname)
-			seq_printf(s, "(%s)", curr->subname);
-		if (curr->flags & (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {
-			seq_printf(s, "(");
-			if (curr->flags & MVEBU_SETTING_GPI)
-				seq_printf(s, "i");
-			if (curr->flags & MVEBU_SETTING_GPO)
-				seq_printf(s, "o");
-			seq_printf(s, ")");
-		}
-	} else
-		seq_printf(s, "current: UNKNOWN");
-
-	if (grp->num_settings > 1) {
-		seq_printf(s, ", available = [");
-		for (n = 0; n < grp->num_settings; n++) {
-			if (curr == &grp->settings[n])
-				continue;
-
-			/* skip unsupported settings for this variant */
-			if (pctl->variant &&
-			    !(pctl->variant & grp->settings[n].variant))
-				continue;
-
-			seq_printf(s, " %s", grp->settings[n].name);
-			if (grp->settings[n].subname)
-				seq_printf(s, "(%s)", grp->settings[n].subname);
-			if (grp->settings[n].flags &
-				(MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {
-				seq_printf(s, "(");
-				if (grp->settings[n].flags & MVEBU_SETTING_GPI)
-					seq_printf(s, "i");
-				if (grp->settings[n].flags & MVEBU_SETTING_GPO)
-					seq_printf(s, "o");
-				seq_printf(s, ")");
-			}
-		}
-		seq_printf(s, " ]");
-	}
-	return;
-}
-
-static struct pinconf_ops mvebu_pinconf_ops = {
-	.pin_config_group_get = mvebu_pinconf_group_get,
-	.pin_config_group_set = mvebu_pinconf_group_set,
-	.pin_config_group_dbg_show = mvebu_pinconf_group_dbg_show,
-};
-
-static int mvebu_pinmux_get_funcs_count(struct pinctrl_dev *pctldev)
-{
-	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
-
-	return pctl->num_functions;
-}
-
-static const char *mvebu_pinmux_get_func_name(struct pinctrl_dev *pctldev,
-					unsigned fid)
-{
-	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
-
-	return pctl->functions[fid].name;
-}
-
-static int mvebu_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned fid,
-				const char * const **groups,
-				unsigned * const num_groups)
-{
-	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
-
-	*groups = pctl->functions[fid].groups;
-	*num_groups = pctl->functions[fid].num_groups;
-	return 0;
-}
-
-static int mvebu_pinmux_enable(struct pinctrl_dev *pctldev, unsigned fid,
-			unsigned gid)
-{
-	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
-	struct mvebu_pinctrl_function *func = &pctl->functions[fid];
-	struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
-	struct mvebu_mpp_ctrl_setting *setting;
-	int ret;
-
-	setting = mvebu_pinctrl_find_setting_by_name(pctl, grp,
-						     func->name);
-	if (!setting) {
-		dev_err(pctl->dev,
-			"unable to find setting %s in group %s\n",
-			func->name, func->groups[gid]);
-		return -EINVAL;
-	}
-
-	ret = mvebu_pinconf_group_set(pctldev, grp->gid, setting->val);
-	if (ret) {
-		dev_err(pctl->dev, "cannot set group %s to %s\n",
-			func->groups[gid], func->name);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int mvebu_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
-			struct pinctrl_gpio_range *range, unsigned offset)
-{
-	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
-	struct mvebu_pinctrl_group *grp;
-	struct mvebu_mpp_ctrl_setting *setting;
-
-	grp = mvebu_pinctrl_find_group_by_pid(pctl, offset);
-	if (!grp)
-		return -EINVAL;
-
-	if (grp->ctrl->mpp_gpio_req)
-		return grp->ctrl->mpp_gpio_req(grp->ctrl, offset);
-
-	setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
-	if (!setting)
-		return -ENOTSUPP;
-
-	return mvebu_pinconf_group_set(pctldev, grp->gid, setting->val);
-}
-
-static int mvebu_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
-	   struct pinctrl_gpio_range *range, unsigned offset, bool input)
-{
-	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
-	struct mvebu_pinctrl_group *grp;
-	struct mvebu_mpp_ctrl_setting *setting;
-
-	grp = mvebu_pinctrl_find_group_by_pid(pctl, offset);
-	if (!grp)
-		return -EINVAL;
-
-	if (grp->ctrl->mpp_gpio_dir)
-		return grp->ctrl->mpp_gpio_dir(grp->ctrl, offset, input);
-
-	setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
-	if (!setting)
-		return -ENOTSUPP;
-
-	if ((input && (setting->flags & MVEBU_SETTING_GPI)) ||
-	    (!input && (setting->flags & MVEBU_SETTING_GPO)))
-		return 0;
-
-	return -ENOTSUPP;
-}
-
-static struct pinmux_ops mvebu_pinmux_ops = {
-	.get_functions_count = mvebu_pinmux_get_funcs_count,
-	.get_function_name = mvebu_pinmux_get_func_name,
-	.get_function_groups = mvebu_pinmux_get_groups,
-	.gpio_request_enable = mvebu_pinmux_gpio_request_enable,
-	.gpio_set_direction = mvebu_pinmux_gpio_set_direction,
-	.enable = mvebu_pinmux_enable,
-};
-
-static int mvebu_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
-{
-	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
-	return pctl->num_groups;
-}
-
-static const char *mvebu_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
-						unsigned gid)
-{
-	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
-	return pctl->groups[gid].name;
-}
-
-static int mvebu_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
-					unsigned gid, const unsigned **pins,
-					unsigned *num_pins)
-{
-	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
-	*pins = pctl->groups[gid].pins;
-	*num_pins = pctl->groups[gid].npins;
-	return 0;
-}
-
-static int mvebu_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
-					struct device_node *np,
-					struct pinctrl_map **map,
-					unsigned *num_maps)
-{
-	struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
-	struct property *prop;
-	const char *function;
-	const char *group;
-	int ret, nmaps, n;
-
-	*map = NULL;
-	*num_maps = 0;
-
-	ret = of_property_read_string(np, "marvell,function", &function);
-	if (ret) {
-		dev_err(pctl->dev,
-			"missing marvell,function in node %s\n", np->name);
-		return 0;
-	}
-
-	nmaps = of_property_count_strings(np, "marvell,pins");
-	if (nmaps < 0) {
-		dev_err(pctl->dev,
-			"missing marvell,pins in node %s\n", np->name);
-		return 0;
-	}
-
-	*map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL);
-	if (map == NULL) {
-		dev_err(pctl->dev,
-			"cannot allocate pinctrl_map memory for %s\n",
-			np->name);
-		return -ENOMEM;
-	}
-
-	n = 0;
-	of_property_for_each_string(np, "marvell,pins", prop, group) {
-		struct mvebu_pinctrl_group *grp =
-			mvebu_pinctrl_find_group_by_name(pctl, group);
-
-		if (!grp) {
-			dev_err(pctl->dev, "unknown pin %s", group);
-			continue;
-		}
-
-		if (!mvebu_pinctrl_find_setting_by_name(pctl, grp, function)) {
-			dev_err(pctl->dev, "unsupported function %s on pin %s",
-				function, group);
-			continue;
-		}
-
-		(*map)[n].type = PIN_MAP_TYPE_MUX_GROUP;
-		(*map)[n].data.mux.group = group;
-		(*map)[n].data.mux.function = function;
-		n++;
-	}
-
-	*num_maps = nmaps;
-
-	return 0;
-}
-
-static void mvebu_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
-				struct pinctrl_map *map, unsigned num_maps)
-{
-	kfree(map);
-}
-
-static struct pinctrl_ops mvebu_pinctrl_ops = {
-	.get_groups_count = mvebu_pinctrl_get_groups_count,
-	.get_group_name = mvebu_pinctrl_get_group_name,
-	.get_group_pins = mvebu_pinctrl_get_group_pins,
-	.dt_node_to_map = mvebu_pinctrl_dt_node_to_map,
-	.dt_free_map = mvebu_pinctrl_dt_free_map,
-};
-
-static int __devinit _add_function(struct mvebu_pinctrl_function *funcs,
-				   const char *name)
-{
-	while (funcs->num_groups) {
-		/* function already there */
-		if (strcmp(funcs->name, name) == 0) {
-			funcs->num_groups++;
-			return -EEXIST;
-		}
-		funcs++;
-	}
-	funcs->name = name;
-	funcs->num_groups = 1;
-	return 0;
-}
-
-static int __devinit mvebu_pinctrl_build_functions(struct platform_device *pdev,
-						   struct mvebu_pinctrl *pctl)
-{
-	struct mvebu_pinctrl_function *funcs;
-	int num = 0;
-	int n, s;
-
-	/* we allocate functions for number of pins and hope
-	 * there are less unique functions than pins available */
-	funcs = devm_kzalloc(&pdev->dev, pctl->desc.npins *
-			     sizeof(struct mvebu_pinctrl_function), GFP_KERNEL);
-	if (!funcs)
-		return -ENOMEM;
-
-	for (n = 0; n < pctl->num_groups; n++) {
-		struct mvebu_pinctrl_group *grp = &pctl->groups[n];
-		for (s = 0; s < grp->num_settings; s++) {
-			/* skip unsupported settings on this variant */
-			if (pctl->variant &&
-			    !(pctl->variant & grp->settings[s].variant))
-				continue;
-
-			/* check for unique functions and count groups */
-			if (_add_function(funcs, grp->settings[s].name))
-				continue;
-
-			num++;
-		}
-	}
-
-	/* with the number of unique functions and it's groups known,
-	   reallocate functions and assign group names */
-	funcs = krealloc(funcs, num * sizeof(struct mvebu_pinctrl_function),
-			 GFP_KERNEL);
-	if (!funcs)
-		return -ENOMEM;
-
-	pctl->num_functions = num;
-	pctl->functions = funcs;
-
-	for (n = 0; n < pctl->num_groups; n++) {
-		struct mvebu_pinctrl_group *grp = &pctl->groups[n];
-		for (s = 0; s < grp->num_settings; s++) {
-			struct mvebu_pinctrl_function *f;
-			const char **groups;
-
-			/* skip unsupported settings on this variant */
-			if (pctl->variant &&
-			    !(pctl->variant & grp->settings[s].variant))
-				continue;
-
-			f = mvebu_pinctrl_find_function_by_name(pctl,
-							grp->settings[s].name);
-
-			/* allocate group name array if not done already */
-			if (!f->groups) {
-				f->groups = devm_kzalloc(&pdev->dev,
-						 f->num_groups * sizeof(char *),
-						 GFP_KERNEL);
-				if (!f->groups)
-					return -ENOMEM;
-			}
-
-			/* find next free group name and assign current name */
-			groups = f->groups;
-			while (*groups)
-				groups++;
-			*groups = grp->name;
-		}
-	}
-
-	return 0;
-}
-
-int __devinit mvebu_pinctrl_probe(struct platform_device *pdev)
-{
-	struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev);
-	struct device_node *np = pdev->dev.of_node;
-	struct mvebu_pinctrl *pctl;
-	void __iomem *base;
-	struct pinctrl_pin_desc *pdesc;
-	unsigned gid, n, k;
-	int ret;
-
-	if (!soc || !soc->controls || !soc->modes) {
-		dev_err(&pdev->dev, "wrong pinctrl soc info\n");
-		return -EINVAL;
-	}
-
-	base = of_iomap(np, 0);
-	if (!base) {
-		dev_err(&pdev->dev, "unable to get base address\n");
-		return -ENODEV;
-	}
-
-	pctl = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pinctrl),
-			GFP_KERNEL);
-	if (!pctl) {
-		dev_err(&pdev->dev, "unable to alloc driver\n");
-		return -ENOMEM;
-	}
-
-	pctl->desc.name = dev_name(&pdev->dev);
-	pctl->desc.owner = THIS_MODULE;
-	pctl->desc.pctlops = &mvebu_pinctrl_ops;
-	pctl->desc.pmxops = &mvebu_pinmux_ops;
-	pctl->desc.confops = &mvebu_pinconf_ops;
-	pctl->variant = soc->variant;
-	pctl->base = base;
-	pctl->dev = &pdev->dev;
-	platform_set_drvdata(pdev, pctl);
-
-	/* count controls and create names for mvebu generic
-	   register controls; also does sanity checks */
-	pctl->num_groups = 0;
-	pctl->desc.npins = 0;
-	for (n = 0; n < soc->ncontrols; n++) {
-		struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
-		char *names;
-
-		pctl->desc.npins += ctrl->npins;
-		/* initial control pins */
-		for (k = 0; k < ctrl->npins; k++)
-			ctrl->pins[k] = ctrl->pid + k;
-
-		/* special soc specific control */
-		if (ctrl->mpp_get || ctrl->mpp_set) {
-			if (!ctrl->name || !ctrl->mpp_set || !ctrl->mpp_set) {
-				dev_err(&pdev->dev, "wrong soc control info\n");
-				return -EINVAL;
-			}
-			pctl->num_groups += 1;
-			continue;
-		}
-
-		/* generic mvebu register control */
-		names = devm_kzalloc(&pdev->dev, ctrl->npins * 8, GFP_KERNEL);
-		if (!names) {
-			dev_err(&pdev->dev, "failed to alloc mpp names\n");
-			return -ENOMEM;
-		}
-		for (k = 0; k < ctrl->npins; k++)
-			sprintf(names + 8*k, "mpp%d", ctrl->pid+k);
-		ctrl->name = names;
-		pctl->num_groups += ctrl->npins;
-	}
-
-	pdesc = devm_kzalloc(&pdev->dev, pctl->desc.npins *
-			     sizeof(struct pinctrl_pin_desc), GFP_KERNEL);
-	if (!pdesc) {
-		dev_err(&pdev->dev, "failed to alloc pinctrl pins\n");
-		return -ENOMEM;
-	}
-
-	for (n = 0; n < pctl->desc.npins; n++)
-		pdesc[n].number = n;
-	pctl->desc.pins = pdesc;
-
-	pctl->groups = devm_kzalloc(&pdev->dev, pctl->num_groups *
-			     sizeof(struct mvebu_pinctrl_group), GFP_KERNEL);
-	if (!pctl->groups) {
-		dev_err(&pdev->dev, "failed to alloc pinctrl groups\n");
-		return -ENOMEM;
-	}
-
-	/* assign mpp controls to groups */
-	gid = 0;
-	for (n = 0; n < soc->ncontrols; n++) {
-		struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
-		pctl->groups[gid].gid = gid;
-		pctl->groups[gid].ctrl = ctrl;
-		pctl->groups[gid].name = ctrl->name;
-		pctl->groups[gid].pins = ctrl->pins;
-		pctl->groups[gid].npins = ctrl->npins;
-
-		/* generic mvebu register control maps to a number of groups */
-		if (!ctrl->mpp_get && !ctrl->mpp_set) {
-			pctl->groups[gid].npins = 1;
-
-			for (k = 1; k < ctrl->npins; k++) {
-				gid++;
-				pctl->groups[gid].gid = gid;
-				pctl->groups[gid].ctrl = ctrl;
-				pctl->groups[gid].name = &ctrl->name[8*k];
-				pctl->groups[gid].pins = &ctrl->pins[k];
-				pctl->groups[gid].npins = 1;
-			}
-		}
-		gid++;
-	}
-
-	/* assign mpp modes to groups */
-	for (n = 0; n < soc->nmodes; n++) {
-		struct mvebu_mpp_mode *mode = &soc->modes[n];
-		struct mvebu_pinctrl_group *grp =
-			mvebu_pinctrl_find_group_by_pid(pctl, mode->pid);
-		unsigned num_settings;
-
-		if (!grp) {
-			dev_warn(&pdev->dev, "unknown pinctrl group %d\n",
-				mode->pid);
-			continue;
-		}
-
-		for (num_settings = 0; ;) {
-			struct mvebu_mpp_ctrl_setting *set =
-				&mode->settings[num_settings];
-
-			if (!set->name)
-				break;
-			num_settings++;
-
-			/* skip unsupported settings for this variant */
-			if (pctl->variant && !(pctl->variant & set->variant))
-				continue;
-
-			/* find gpio/gpo/gpi settings */
-			if (strcmp(set->name, "gpio") == 0)
-				set->flags = MVEBU_SETTING_GPI |
-					MVEBU_SETTING_GPO;
-			else if (strcmp(set->name, "gpo") == 0)
-				set->flags = MVEBU_SETTING_GPO;
-			else if (strcmp(set->name, "gpi") == 0)
-				set->flags = MVEBU_SETTING_GPI;
-		}
-
-		grp->settings = mode->settings;
-		grp->num_settings = num_settings;
-	}
-
-	ret = mvebu_pinctrl_build_functions(pdev, pctl);
-	if (ret) {
-		dev_err(&pdev->dev, "unable to build functions\n");
-		return ret;
-	}
-
-	pctl->pctldev = pinctrl_register(&pctl->desc, &pdev->dev, pctl);
-	if (!pctl->pctldev) {
-		dev_err(&pdev->dev, "unable to register pinctrl driver\n");
-		return -EINVAL;
-	}
-
-	dev_info(&pdev->dev, "registered pinctrl driver\n");
-
-	/* register gpio ranges */
-	for (n = 0; n < soc->ngpioranges; n++)
-		pinctrl_add_gpio_range(pctl->pctldev, &soc->gpioranges[n]);
-
-	return 0;
-}
-
-int __devexit mvebu_pinctrl_remove(struct platform_device *pdev)
-{
-	struct mvebu_pinctrl *pctl = platform_get_drvdata(pdev);
-	pinctrl_unregister(pctl->pctldev);
-	return 0;
-}
diff --git a/drivers/pinctrl/pinctrl-mvebu.h b/drivers/pinctrl/pinctrl-mvebu.h
deleted file mode 100644
index 90bd3be..0000000
--- a/drivers/pinctrl/pinctrl-mvebu.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Marvell MVEBU pinctrl driver
- *
- * Authors: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
- *          Thomas Petazzoni <thomas.petazzoni@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.
- */
-
-#ifndef __PINCTRL_MVEBU_H__
-#define __PINCTRL_MVEBU_H__
-
-/**
- * struct mvebu_mpp_ctrl - describe a mpp control
- * @name: name of the control group
- * @pid: first pin id handled by this control
- * @npins: number of pins controlled by this control
- * @mpp_get: (optional) special function to get mpp setting
- * @mpp_set: (optional) special function to set mpp setting
- * @mpp_gpio_req: (optional) special function to request gpio
- * @mpp_gpio_dir: (optional) special function to set gpio direction
- *
- * A mpp_ctrl describes a muxable unit, e.g. pin, group of pins, or
- * internal function, inside the SoC. Each muxable unit can be switched
- * between two or more different settings, e.g. assign mpp pin 13 to
- * uart1 or sata.
- *
- * If optional mpp_get/_set functions are set these are used to get/set
- * a specific mode. Otherwise it is assumed that the mpp control is based
- * on 4-bit groups in subsequent registers. The optional mpp_gpio_req/_dir
- * functions can be used to allow pin settings with varying gpio pins.
- */
-struct mvebu_mpp_ctrl {
-	const char *name;
-	u8 pid;
-	u8 npins;
-	unsigned *pins;
-	int (*mpp_get)(struct mvebu_mpp_ctrl *ctrl, unsigned long *config);
-	int (*mpp_set)(struct mvebu_mpp_ctrl *ctrl, unsigned long config);
-	int (*mpp_gpio_req)(struct mvebu_mpp_ctrl *ctrl, u8 pid);
-	int (*mpp_gpio_dir)(struct mvebu_mpp_ctrl *ctrl, u8 pid, bool input);
-};
-
-/**
- * struct mvebu_mpp_ctrl_setting - describe a mpp ctrl setting
- * @val: ctrl setting value
- * @name: ctrl setting name, e.g. uart2, spi0 - unique per mpp_mode
- * @subname: (optional) additional ctrl setting name, e.g. rts, cts
- * @variant: (optional) variant identifier mask
- * @flags: (private) flags to store gpi/gpo/gpio capabilities
- *
- * A ctrl_setting describes a specific internal mux function that a mpp pin
- * can be switched to. The value (val) will be written in the corresponding
- * register for common mpp pin configuration registers on MVEBU. SoC specific
- * mpp_get/_set function may use val to distinguish between different settings.
- *
- * The name will be used to switch to this setting in DT description, e.g.
- * marvell,function = "uart2". subname is only for debugging purposes.
- *
- * If name is one of "gpi", "gpo", "gpio" gpio capabilities are
- * parsed during initialization and stored in flags.
- *
- * The variant can be used to combine different revisions of one SoC to a
- * common pinctrl driver. It is matched (AND) with variant of soc_info to
- * determine if a setting is available on the current SoC revision.
- */
-struct mvebu_mpp_ctrl_setting {
-	u8 val;
-	const char *name;
-	const char *subname;
-	u8 variant;
-	u8 flags;
-#define  MVEBU_SETTING_GPO	(1 << 0)
-#define  MVEBU_SETTING_GPI	(1 << 1)
-};
-
-/**
- * struct mvebu_mpp_mode - link ctrl and settings
- * @pid: first pin id handled by this mode
- * @settings: list of settings available for this mode
- *
- * A mode connects all available settings with the corresponding mpp_ctrl
- * given by pid.
- */
-struct mvebu_mpp_mode {
-	u8 pid;
-	struct mvebu_mpp_ctrl_setting *settings;
-};
-
-/**
- * struct mvebu_pinctrl_soc_info - SoC specific info passed to pinctrl-mvebu
- * @variant: variant mask of soc_info
- * @controls: list of available mvebu_mpp_ctrls
- * @ncontrols: number of available mvebu_mpp_ctrls
- * @modes: list of available mvebu_mpp_modes
- * @nmodes: number of available mvebu_mpp_modes
- * @gpioranges: list of pinctrl_gpio_ranges
- * @ngpioranges: number of available pinctrl_gpio_ranges
- *
- * This struct describes all pinctrl related information for a specific SoC.
- * If variant is unequal 0 it will be matched (AND) with variant of each
- * setting and allows to distinguish between different revisions of one SoC.
- */
-struct mvebu_pinctrl_soc_info {
-	u8 variant;
-	struct mvebu_mpp_ctrl *controls;
-	int ncontrols;
-	struct mvebu_mpp_mode *modes;
-	int nmodes;
-	struct pinctrl_gpio_range *gpioranges;
-	int ngpioranges;
-};
-
-#define MPP_REG_CTRL(_idl, _idh)				\
-	{							\
-		.name = NULL,					\
-		.pid = _idl,					\
-		.npins = _idh - _idl + 1,			\
-		.pins = (unsigned[_idh - _idl + 1]) { },	\
-		.mpp_get = NULL,				\
-		.mpp_set = NULL,				\
-		.mpp_gpio_req = NULL,				\
-		.mpp_gpio_dir = NULL,				\
-	}
-
-#define MPP_FUNC_CTRL(_idl, _idh, _name, _func)			\
-	{							\
-		.name = _name,					\
-		.pid = _idl,					\
-		.npins = _idh - _idl + 1,			\
-		.pins = (unsigned[_idh - _idl + 1]) { },	\
-		.mpp_get = _func ## _get,			\
-		.mpp_set = _func ## _set,			\
-		.mpp_gpio_req = NULL,				\
-		.mpp_gpio_dir = NULL,				\
-	}
-
-#define MPP_FUNC_GPIO_CTRL(_idl, _idh, _name, _func)		\
-	{							\
-		.name = _name,					\
-		.pid = _idl,					\
-		.npins = _idh - _idl + 1,			\
-		.pins = (unsigned[_idh - _idl + 1]) { },	\
-		.mpp_get = _func ## _get,			\
-		.mpp_set = _func ## _set,			\
-		.mpp_gpio_req = _func ## _gpio_req,		\
-		.mpp_gpio_dir = _func ## _gpio_dir,		\
-	}
-
-#define _MPP_VAR_FUNCTION(_val, _name, _subname, _mask)		\
-	{							\
-		.val = _val,					\
-		.name = _name,					\
-		.subname = _subname,				\
-		.variant = _mask,				\
-		.flags = 0,					\
-	}
-
-#if defined(CONFIG_DEBUG_FS)
-#define MPP_VAR_FUNCTION(_val, _name, _subname, _mask)		\
-	_MPP_VAR_FUNCTION(_val, _name, _subname, _mask)
-#else
-#define MPP_VAR_FUNCTION(_val, _name, _subname, _mask)		\
-	_MPP_VAR_FUNCTION(_val, _name, NULL, _mask)
-#endif
-
-#define MPP_FUNCTION(_val, _name, _subname)			\
-	MPP_VAR_FUNCTION(_val, _name, _subname, (u8)-1)
-
-#define MPP_MODE(_id, ...)					\
-	{							\
-		.pid = _id,					\
-		.settings = (struct mvebu_mpp_ctrl_setting[]){	\
-			__VA_ARGS__, { } },			\
-	}
-
-#define MPP_GPIO_RANGE(_id, _pinbase, _gpiobase, _npins)	\
-	{							\
-		.name = "mvebu-gpio",				\
-		.id = _id,					\
-		.pin_base = _pinbase,				\
-		.base = _gpiobase,				\
-		.npins = _npins,				\
-	}
-
-int mvebu_pinctrl_probe(struct platform_device *pdev);
-int mvebu_pinctrl_remove(struct platform_device *pdev);
-
-#endif
diff --git a/drivers/pinctrl/pinctrl-mxs.c b/drivers/pinctrl/pinctrl-mxs.c
index 4ba4636..180f163 100644
--- a/drivers/pinctrl/pinctrl-mxs.c
+++ b/drivers/pinctrl/pinctrl-mxs.c
@@ -319,7 +319,7 @@ static void mxs_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
 		seq_printf(s, "0x%lx", config);
 }
 
-struct pinconf_ops mxs_pinconf_ops = {
+static struct pinconf_ops mxs_pinconf_ops = {
 	.pin_config_get = mxs_pinconf_get,
 	.pin_config_set = mxs_pinconf_set,
 	.pin_config_group_get = mxs_pinconf_group_get,
@@ -522,7 +522,7 @@ err:
 }
 EXPORT_SYMBOL_GPL(mxs_pinctrl_probe);
 
-int __devexit mxs_pinctrl_remove(struct platform_device *pdev)
+int mxs_pinctrl_remove(struct platform_device *pdev)
 {
 	struct mxs_pinctrl_data *d = platform_get_drvdata(pdev);
 
diff --git a/drivers/pinctrl/pinctrl-nomadik-db8500.c b/drivers/pinctrl/pinctrl-nomadik-db8500.c
index debaa75b..7d88ae3 100644
--- a/drivers/pinctrl/pinctrl-nomadik-db8500.c
+++ b/drivers/pinctrl/pinctrl-nomadik-db8500.c
@@ -475,8 +475,10 @@ static const unsigned hsit_a_1_pins[] = { DB8500_PIN_AJ9, DB8500_PIN_AH9,
 	DB8500_PIN_AG9, DB8500_PIN_AG8, DB8500_PIN_AF8 };
 static const unsigned hsit_a_2_pins[] = { DB8500_PIN_AJ9, DB8500_PIN_AH9,
 	DB8500_PIN_AG9, DB8500_PIN_AG8 };
-static const unsigned clkout_a_1_pins[] = { DB8500_PIN_AH7, DB8500_PIN_AJ6 };
-static const unsigned clkout_a_2_pins[] = { DB8500_PIN_AG7, DB8500_PIN_AF7 };
+static const unsigned clkout1_a_1_pins[] = { DB8500_PIN_AH7 };
+static const unsigned clkout1_a_2_pins[] = { DB8500_PIN_AG7 };
+static const unsigned clkout2_a_1_pins[] = { DB8500_PIN_AJ6 };
+static const unsigned clkout2_a_2_pins[] = { DB8500_PIN_AF7 };
 static const unsigned usb_a_1_pins[] = { DB8500_PIN_AF28, DB8500_PIN_AE29,
 	DB8500_PIN_AD29, DB8500_PIN_AC29, DB8500_PIN_AD28, DB8500_PIN_AD26,
 	DB8500_PIN_AE26, DB8500_PIN_AG29, DB8500_PIN_AE27, DB8500_PIN_AD27,
@@ -592,7 +594,8 @@ static const unsigned stmmod_c_1_pins[] = { DB8500_PIN_C20, DB8500_PIN_B21,
 	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24 };
 static const unsigned usbsim_c_1_pins[] = { DB8500_PIN_D22 };
 static const unsigned mc4rstn_c_1_pins[] = { DB8500_PIN_AF25 };
-static const unsigned clkout_c_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AH12 };
+static const unsigned clkout1_c_1_pins[] = { DB8500_PIN_AH13 };
+static const unsigned clkout2_c_1_pins[] = { DB8500_PIN_AH12 };
 static const unsigned i2c3_c_1_pins[] = { DB8500_PIN_AG12, DB8500_PIN_AH11 };
 static const unsigned spi0_c_1_pins[] = { DB8500_PIN_AH10, DB8500_PIN_AH9,
 					  DB8500_PIN_AG9, DB8500_PIN_AG8 };
@@ -600,14 +603,66 @@ static const unsigned usbsim_c_2_pins[] = { DB8500_PIN_AF8 };
 static const unsigned i2c3_c_2_pins[] = { DB8500_PIN_AG7, DB8500_PIN_AF7 };
 
 /* Other C1 column */
+static const unsigned u2rx_oc1_1_pins[] = { DB8500_PIN_AB2 };
+static const unsigned stmape_oc1_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_Y4,
+	DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
+static const unsigned remap0_oc1_1_pins[] = { DB8500_PIN_E1 };
+static const unsigned remap1_oc1_1_pins[] = { DB8500_PIN_E2 };
+static const unsigned ptma9_oc1_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
+	DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H2,
+	DB8500_PIN_J2, DB8500_PIN_H1 };
 static const unsigned kp_oc1_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3,
 	DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6,
 	DB8500_PIN_D6, DB8500_PIN_B7 };
+static const unsigned rf_oc1_1_pins[] = { DB8500_PIN_D8, DB8500_PIN_D9 };
+static const unsigned hxclk_oc1_1_pins[] = { DB8500_PIN_D16 };
+static const unsigned uartmodrx_oc1_1_pins[] = { DB8500_PIN_B17 };
+static const unsigned uartmodtx_oc1_1_pins[] = { DB8500_PIN_C16 };
+static const unsigned stmmod_oc1_1_pins[] = { DB8500_PIN_C19, DB8500_PIN_C17,
+	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19 };
+static const unsigned hxgpio_oc1_1_pins[] = { DB8500_PIN_D21, DB8500_PIN_D20,
+	DB8500_PIN_C20, DB8500_PIN_B21, DB8500_PIN_C21, DB8500_PIN_A22,
+	DB8500_PIN_B24, DB8500_PIN_C22 };
+static const unsigned rf_oc1_2_pins[] = { DB8500_PIN_C23, DB8500_PIN_D23 };
 static const unsigned spi2_oc1_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12,
 	DB8500_PIN_AH12, DB8500_PIN_AH11 };
 static const unsigned spi2_oc1_2_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AH12,
 	DB8500_PIN_AH11 };
 
+/* Other C2 column */
+static const unsigned sbag_oc2_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_AB2,
+	DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
+static const unsigned etmr4_oc2_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
+	DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H2,
+	DB8500_PIN_J2, DB8500_PIN_H1 };
+static const unsigned ptma9_oc2_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
+	DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
+	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
+	DB8500_PIN_D21, DB8500_PIN_D20,	DB8500_PIN_C20, DB8500_PIN_B21,
+	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
+
+/* Other C3 column */
+static const unsigned stmmod_oc3_1_pins[] = { DB8500_PIN_AB2, DB8500_PIN_W2,
+	DB8500_PIN_W3, DB8500_PIN_V3, DB8500_PIN_V2 };
+static const unsigned stmmod_oc3_2_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
+	DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3 };
+static const unsigned uartmodrx_oc3_1_pins[] = { DB8500_PIN_H2 };
+static const unsigned uartmodtx_oc3_1_pins[] = { DB8500_PIN_J2 };
+static const unsigned etmr4_oc3_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
+	DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
+	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
+	DB8500_PIN_D21, DB8500_PIN_D20,	DB8500_PIN_C20, DB8500_PIN_B21,
+	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
+
+/* Other C4 column */
+static const unsigned sbag_oc4_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
+	DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H1 };
+static const unsigned hwobs_oc4_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16,
+	DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17,
+	DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20,
+	DB8500_PIN_D21, DB8500_PIN_D20,	DB8500_PIN_C20, DB8500_PIN_B21,
+	DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
+
 #define DB8500_PIN_GROUP(a,b) { .name = #a, .pins = a##_pins,		\
 			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
 
@@ -639,6 +694,7 @@ static const struct nmk_pingroup nmk_db8500_groups[] = {
 	DB8500_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A),
 	DB8500_PIN_GROUP(ipgpio0_a_1, NMK_GPIO_ALT_A),
 	DB8500_PIN_GROUP(ipgpio1_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(kp_a_2, NMK_GPIO_ALT_A),
 	DB8500_PIN_GROUP(msp2sck_a_1, NMK_GPIO_ALT_A),
 	DB8500_PIN_GROUP(msp2_a_1, NMK_GPIO_ALT_A),
 	DB8500_PIN_GROUP(mc4_a_1, NMK_GPIO_ALT_A),
@@ -647,8 +703,10 @@ static const struct nmk_pingroup nmk_db8500_groups[] = {
 	DB8500_PIN_GROUP(hsir_a_1, NMK_GPIO_ALT_A),
 	DB8500_PIN_GROUP(hsit_a_1, NMK_GPIO_ALT_A),
 	DB8500_PIN_GROUP(hsit_a_2, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(clkout_a_1, NMK_GPIO_ALT_A),
-	DB8500_PIN_GROUP(clkout_a_2, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(clkout1_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(clkout1_a_2, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(clkout2_a_1, NMK_GPIO_ALT_A),
+	DB8500_PIN_GROUP(clkout2_a_2, NMK_GPIO_ALT_A),
 	DB8500_PIN_GROUP(usb_a_1, NMK_GPIO_ALT_A),
 	/* Altfunction B column */
 	DB8500_PIN_GROUP(trig_b_1, NMK_GPIO_ALT_B),
@@ -720,15 +778,41 @@ static const struct nmk_pingroup nmk_db8500_groups[] = {
 	DB8500_PIN_GROUP(stmmod_c_1, NMK_GPIO_ALT_C),
 	DB8500_PIN_GROUP(usbsim_c_1, NMK_GPIO_ALT_C),
 	DB8500_PIN_GROUP(mc4rstn_c_1, NMK_GPIO_ALT_C),
-	DB8500_PIN_GROUP(clkout_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(clkout1_c_1, NMK_GPIO_ALT_C),
+	DB8500_PIN_GROUP(clkout2_c_1, NMK_GPIO_ALT_C),
 	DB8500_PIN_GROUP(i2c3_c_1, NMK_GPIO_ALT_C),
 	DB8500_PIN_GROUP(spi0_c_1, NMK_GPIO_ALT_C),
 	DB8500_PIN_GROUP(usbsim_c_2, NMK_GPIO_ALT_C),
 	DB8500_PIN_GROUP(i2c3_c_2, NMK_GPIO_ALT_C),
 	/* Other alt C1 column */
+	DB8500_PIN_GROUP(u2rx_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(stmape_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(remap0_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(remap1_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(ptma9_oc1_1, NMK_GPIO_ALT_C1),
 	DB8500_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(rf_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(hxclk_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(uartmodrx_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(uartmodtx_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(stmmod_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(hxgpio_oc1_1, NMK_GPIO_ALT_C1),
+	DB8500_PIN_GROUP(rf_oc1_2, NMK_GPIO_ALT_C1),
 	DB8500_PIN_GROUP(spi2_oc1_1, NMK_GPIO_ALT_C1),
 	DB8500_PIN_GROUP(spi2_oc1_2, NMK_GPIO_ALT_C1),
+	/* Other alt C2 column */
+	DB8500_PIN_GROUP(sbag_oc2_1, NMK_GPIO_ALT_C2),
+	DB8500_PIN_GROUP(etmr4_oc2_1, NMK_GPIO_ALT_C2),
+	DB8500_PIN_GROUP(ptma9_oc2_1, NMK_GPIO_ALT_C2),
+	/* Other alt C3 column */
+	DB8500_PIN_GROUP(stmmod_oc3_1, NMK_GPIO_ALT_C3),
+	DB8500_PIN_GROUP(stmmod_oc3_2, NMK_GPIO_ALT_C3),
+	DB8500_PIN_GROUP(uartmodrx_oc3_1, NMK_GPIO_ALT_C3),
+	DB8500_PIN_GROUP(uartmodtx_oc3_1, NMK_GPIO_ALT_C3),
+	DB8500_PIN_GROUP(etmr4_oc3_1, NMK_GPIO_ALT_C3),
+	/* Other alt C4 column */
+	DB8500_PIN_GROUP(sbag_oc4_1, NMK_GPIO_ALT_C4),
+	DB8500_PIN_GROUP(hwobs_oc4_1, NMK_GPIO_ALT_C4),
 };
 
 /* We use this macro to define the groups applicable to a function */
@@ -742,7 +826,7 @@ DB8500_FUNC_GROUPS(u1, "u1rxtx_a_1", "u1ctsrts_a_1");
  * only available on two pins in alternative function C
  */
 DB8500_FUNC_GROUPS(u2, "u2rxtx_b_1", "u2rxtx_c_1", "u2ctsrts_c_1",
-		   "u2rxtx_c_2", "u2rxtx_c_3");
+		   "u2rxtx_c_2", "u2rxtx_c_3", "u2rx_oc1_1");
 DB8500_FUNC_GROUPS(ipi2c, "ipi2c_a_1", "ipi2c_a_2");
 /*
  * MSP0 can only be on a certain set of pins, but the TX/RX pins can be
@@ -757,7 +841,7 @@ DB8500_FUNC_GROUPS(msp1, "msp1txrx_a_1", "msp1_a_1", "msp1txrx_b_1");
 DB8500_FUNC_GROUPS(lcdb, "lcdb_a_1");
 DB8500_FUNC_GROUPS(lcd, "lcdvsi0_a_1", "lcdvsi1_a_1", "lcd_d0_d7_a_1",
 	"lcd_d8_d11_a_1", "lcd_d12_d23_a_1", "lcd_b_1");
-DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_b_1", "kp_b_2", "kp_c_1", "kp_oc1_1");
+DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_a_2", "kp_b_1", "kp_b_2", "kp_c_1", "kp_oc1_1");
 DB8500_FUNC_GROUPS(mc2, "mc2_a_1", "mc2rstn_c_1");
 DB8500_FUNC_GROUPS(ssp1, "ssp1_a_1");
 DB8500_FUNC_GROUPS(ssp0, "ssp0_a_1");
@@ -773,7 +857,8 @@ DB8500_FUNC_GROUPS(msp2, "msp2sck_a_1", "msp2_a_1");
 DB8500_FUNC_GROUPS(mc4, "mc4_a_1", "mc4rstn_c_1");
 DB8500_FUNC_GROUPS(mc1, "mc1_a_1", "mc1_a_2", "mc1dir_a_1");
 DB8500_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2");
-DB8500_FUNC_GROUPS(clkout, "clkout_a_1", "clkout_a_2", "clkout_c_1");
+DB8500_FUNC_GROUPS(clkout, "clkout1_a_1", "clkout1_a_2", "clkout1_c_1",
+		"clkout2_a_1", "clkout2_a_2", "clkout2_c_1");
 DB8500_FUNC_GROUPS(usb, "usb_a_1");
 DB8500_FUNC_GROUPS(trig, "trig_b_1");
 DB8500_FUNC_GROUPS(i2c4, "i2c4_b_1");
@@ -784,8 +869,10 @@ DB8500_FUNC_GROUPS(i2c2, "i2c2_b_1", "i2c2_b_2");
  * so select one of each.
  */
 DB8500_FUNC_GROUPS(uartmod, "uartmodtx_b_1", "uartmodrx_b_1", "uartmodrx_b_2",
-		   "uartmodrx_c_1", "uartmod_tx_c_1");
-DB8500_FUNC_GROUPS(stmmod, "stmmod_b_1", "stmmod_c_1");
+		"uartmodrx_c_1", "uartmod_tx_c_1", "uartmodrx_oc1_1",
+		"uartmodtx_oc1_1", "uartmodrx_oc3_1", "uartmodtx_oc3_1");
+DB8500_FUNC_GROUPS(stmmod, "stmmod_b_1", "stmmod_c_1", "stmmod_oc1_1",
+		"stmmod_oc3_1", "stmmod_oc3_2");
 DB8500_FUNC_GROUPS(spi3, "spi3_b_1");
 /* Select between CS0 on alt B or PS1 on alt C */
 DB8500_FUNC_GROUPS(sm, "sm_b_1", "smcs0_b_1", "smcs1_b_1", "smcleale_c_1",
@@ -799,13 +886,19 @@ DB8500_FUNC_GROUPS(ipjtag, "ipjtag_c_1");
 DB8500_FUNC_GROUPS(slim0, "slim0_c_1");
 DB8500_FUNC_GROUPS(ms, "ms_c_1");
 DB8500_FUNC_GROUPS(iptrigout, "iptrigout_c_1");
-DB8500_FUNC_GROUPS(stmape, "stmape_c_1", "stmape_c_2");
+DB8500_FUNC_GROUPS(stmape, "stmape_c_1", "stmape_c_2", "stmape_oc1_1");
 DB8500_FUNC_GROUPS(mc5, "mc5_c_1");
 DB8500_FUNC_GROUPS(usbsim, "usbsim_c_1", "usbsim_c_2");
 DB8500_FUNC_GROUPS(i2c3, "i2c3_c_1", "i2c3_c_2");
 DB8500_FUNC_GROUPS(spi0, "spi0_c_1");
 DB8500_FUNC_GROUPS(spi2, "spi2_oc1_1", "spi2_oc1_2");
-
+DB8500_FUNC_GROUPS(remap, "remap0_oc1_1", "remap1_oc1_1");
+DB8500_FUNC_GROUPS(sbag, "sbag_oc2_1", "sbag_oc4_1");
+DB8500_FUNC_GROUPS(ptm, "ptma9_oc1_1", "ptma9_oc2_1");
+DB8500_FUNC_GROUPS(rf, "rf_oc1_1", "rf_oc1_2");
+DB8500_FUNC_GROUPS(hx, "hxclk_oc1_1", "hxgpio_oc1_1");
+DB8500_FUNC_GROUPS(etm, "etmr4_oc2_1", "etmr4_oc3_1");
+DB8500_FUNC_GROUPS(hwobs, "hwobs_oc4_1");
 #define FUNCTION(fname)					\
 	{						\
 		.name = #fname,				\
@@ -858,6 +951,12 @@ static const struct nmk_function nmk_db8500_functions[] = {
 	FUNCTION(i2c3),
 	FUNCTION(spi0),
 	FUNCTION(spi2),
+	FUNCTION(remap),
+	FUNCTION(ptm),
+	FUNCTION(rf),
+	FUNCTION(hx),
+	FUNCTION(etm),
+	FUNCTION(hwobs),
 };
 
 static const struct prcm_gpiocr_altcx_pin_desc db8500_altcx_pins[] = {
diff --git a/drivers/pinctrl/pinctrl-nomadik-db8540.c b/drivers/pinctrl/pinctrl-nomadik-db8540.c
index 52fc301..bb6a4016 100644
--- a/drivers/pinctrl/pinctrl-nomadik-db8540.c
+++ b/drivers/pinctrl/pinctrl-nomadik-db8540.c
@@ -460,8 +460,10 @@ static const unsigned hsit_a_1_pins[] = { DB8540_PIN_B11, DB8540_PIN_B10,
 	DB8540_PIN_E10, DB8540_PIN_B12, DB8540_PIN_D10 };
 static const unsigned hsit_a_2_pins[] = { DB8540_PIN_B11, DB8540_PIN_B10,
 	DB8540_PIN_E10, DB8540_PIN_B12 };
-static const unsigned clkout_a_1_pins[] = { DB8540_PIN_D11, DB8540_PIN_AJ6 };
-static const unsigned clkout_a_2_pins[] = { DB8540_PIN_B13, DB8540_PIN_C12 };
+static const unsigned clkout1_a_1_pins[] = { DB8540_PIN_D11 };
+static const unsigned clkout1_a_2_pins[] = { DB8540_PIN_B13 };
+static const unsigned clkout2_a_1_pins[] = { DB8540_PIN_AJ6 };
+static const unsigned clkout2_a_2_pins[] = { DB8540_PIN_C12 };
 static const unsigned msp4_a_1_pins[] = { DB8540_PIN_B14, DB8540_PIN_E11 };
 static const unsigned usb_a_1_pins[] = { DB8540_PIN_D12, DB8540_PIN_D15,
 	DB8540_PIN_C13, DB8540_PIN_C14, DB8540_PIN_C18, DB8540_PIN_C16,
@@ -698,8 +700,10 @@ static const struct nmk_pingroup nmk_db8540_groups[] = {
 	DB8540_PIN_GROUP(hsir_a_1, NMK_GPIO_ALT_A),
 	DB8540_PIN_GROUP(hsit_a_1, NMK_GPIO_ALT_A),
 	DB8540_PIN_GROUP(hsit_a_2, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(clkout_a_1, NMK_GPIO_ALT_A),
-	DB8540_PIN_GROUP(clkout_a_2, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(clkout1_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(clkout1_a_2, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(clkout2_a_1, NMK_GPIO_ALT_A),
+	DB8540_PIN_GROUP(clkout2_a_2, NMK_GPIO_ALT_A),
 	DB8540_PIN_GROUP(msp4_a_1, NMK_GPIO_ALT_A),
 	DB8540_PIN_GROUP(usb_a_1, NMK_GPIO_ALT_A),
 	/* Altfunction B column */
@@ -822,6 +826,7 @@ static const struct nmk_pingroup nmk_db8540_groups[] = {
 	DB8540_PIN_GROUP(modaccuarttxrx_oc4_1, NMK_GPIO_ALT_C4),
 	DB8540_PIN_GROUP(modaccuartrtscts_oc4_1, NMK_GPIO_ALT_C4),
 	DB8540_PIN_GROUP(stmmod_oc4_1, NMK_GPIO_ALT_C4),
+	DB8540_PIN_GROUP(moduartstmmux_oc4_1, NMK_GPIO_ALT_C4),
 
 };
 
@@ -830,7 +835,8 @@ static const struct nmk_pingroup nmk_db8540_groups[] = {
 static const char * const a##_groups[] = { b };
 
 DB8540_FUNC_GROUPS(apetrig, "apetrig_b_1");
-DB8540_FUNC_GROUPS(clkout, "clkoutreq_a_1", "clkout_a_1", "clkout_a_2");
+DB8540_FUNC_GROUPS(clkout, "clkoutreq_a_1", "clkout1_a_1", "clkout1_a_2",
+		"clkout2_a_1", "clkout2_a_2");
 DB8540_FUNC_GROUPS(ddrtrig, "ddrtrig_b_1");
 DB8540_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2");
 DB8540_FUNC_GROUPS(hwobs, "hwobs_oc4_1");
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index cf82d9c..ef66f98 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -30,26 +30,9 @@
 #include <linux/pinctrl/pinconf.h>
 /* Since we request GPIOs from ourself */
 #include <linux/pinctrl/consumer.h>
-/*
- * For the U8500 archs, use the PRCMU register interface, for the older
- * Nomadik, provide some stubs. The functions using these will only be
- * called on the U8500 series.
- */
-#ifdef CONFIG_ARCH_U8500
-#include <linux/mfd/dbx500-prcmu.h>
-#else
-static inline u32 prcmu_read(unsigned int reg) {
-	return 0;
-}
-static inline void prcmu_write(unsigned int reg, u32 value) {}
-static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {}
-#endif
-
+#include <linux/platform_data/pinctrl-nomadik.h>
 #include <asm/mach/irq.h>
-
-#include <plat/pincfg.h>
-#include <plat/gpio-nomadik.h>
-
+#include <mach/irqs.h>
 #include "pinctrl-nomadik.h"
 
 /*
@@ -60,8 +43,6 @@ static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {}
  * Symbols in this file are called "nmk_gpio" for "nomadik gpio"
  */
 
-#define NMK_GPIO_PER_CHIP	32
-
 struct nmk_gpio_chip {
 	struct gpio_chip chip;
 	struct irq_domain *domain;
@@ -86,10 +67,18 @@ struct nmk_gpio_chip {
 	u32 lowemi;
 };
 
+/**
+ * struct nmk_pinctrl - state container for the Nomadik pin controller
+ * @dev: containing device pointer
+ * @pctl: corresponding pin controller device
+ * @soc: SoC data for this specific chip
+ * @prcm_base: PRCM register range virtual base
+ */
 struct nmk_pinctrl {
 	struct device *dev;
 	struct pinctrl_dev *pctl;
 	const struct nmk_pinctrl_soc_data *soc;
+	void __iomem *prcm_base;
 };
 
 static struct nmk_gpio_chip *
@@ -251,6 +240,15 @@ nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset)
 	dev_dbg(nmk_chip->chip.dev, "%d: clearing interrupt mask\n", gpio);
 }
 
+static void nmk_write_masked(void __iomem *reg, u32 mask, u32 value)
+{
+	u32 val;
+
+	val = readl(reg);
+	val = ((val & ~mask) | (value & mask));
+	writel(val, reg);
+}
+
 static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
 	unsigned offset, unsigned alt_num)
 {
@@ -289,8 +287,8 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
 			if (pin_desc->altcx[i].used == true) {
 				reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
 				bit = pin_desc->altcx[i].control_bit;
-				if (prcmu_read(reg) & BIT(bit)) {
-					prcmu_write_masked(reg, BIT(bit), 0);
+				if (readl(npct->prcm_base + reg) & BIT(bit)) {
+					nmk_write_masked(npct->prcm_base + reg, BIT(bit), 0);
 					dev_dbg(npct->dev,
 						"PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n",
 						offset, i+1);
@@ -318,8 +316,8 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
 		if (pin_desc->altcx[i].used == true) {
 			reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
 			bit = pin_desc->altcx[i].control_bit;
-			if (prcmu_read(reg) & BIT(bit)) {
-				prcmu_write_masked(reg, BIT(bit), 0);
+			if (readl(npct->prcm_base + reg) & BIT(bit)) {
+				nmk_write_masked(npct->prcm_base + reg, BIT(bit), 0);
 				dev_dbg(npct->dev,
 					"PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n",
 					offset, i+1);
@@ -331,7 +329,7 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
 	bit = pin_desc->altcx[alt_index].control_bit;
 	dev_dbg(npct->dev, "PRCM GPIOCR: pin %i: alternate-C%i has been selected\n",
 		offset, alt_index+1);
-	prcmu_write_masked(reg, BIT(bit), BIT(bit));
+	nmk_write_masked(npct->prcm_base + reg, BIT(bit), BIT(bit));
 }
 
 static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
@@ -536,7 +534,7 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
  * and its sleep mode based on the specified configuration.  The @cfg is
  * usually one of the SoC specific macros defined in mach/<soc>-pins.h.  These
  * are constructed using, and can be further enhanced with, the macros in
- * plat/pincfg.h.
+ * <linux/platform_data/pinctrl-nomadik.h>
  *
  * If a pin's mode is set to GPIO, it is configured as an input to avoid
  * side-effects.  The gpio can be manipulated later using standard GPIO API
@@ -675,6 +673,35 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode)
 }
 EXPORT_SYMBOL(nmk_gpio_set_mode);
 
+static int nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio)
+{
+	int i;
+	u16 reg;
+	u8 bit;
+	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+	const struct prcm_gpiocr_altcx_pin_desc *pin_desc;
+	const u16 *gpiocr_regs;
+
+	for (i = 0; i < npct->soc->npins_altcx; i++) {
+		if (npct->soc->altcx_pins[i].pin == gpio)
+			break;
+	}
+	if (i == npct->soc->npins_altcx)
+		return NMK_GPIO_ALT_C;
+
+	pin_desc = npct->soc->altcx_pins + i;
+	gpiocr_regs = npct->soc->prcm_gpiocr_registers;
+	for (i = 0; i < PRCM_IDX_GPIOCR_ALTC_MAX; i++) {
+		if (pin_desc->altcx[i].used == true) {
+			reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
+			bit = pin_desc->altcx[i].control_bit;
+			if (readl(npct->prcm_base + reg) & BIT(bit))
+				return NMK_GPIO_ALT_C+i+1;
+		}
+	}
+	return NMK_GPIO_ALT_C;
+}
+
 int nmk_gpio_get_mode(int gpio)
 {
 	struct nmk_gpio_chip *nmk_chip;
@@ -1063,8 +1090,9 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 
 #include <linux/seq_file.h>
 
-static void nmk_gpio_dbg_show_one(struct seq_file *s, struct gpio_chip *chip,
-				  unsigned offset, unsigned gpio)
+static void nmk_gpio_dbg_show_one(struct seq_file *s,
+	struct pinctrl_dev *pctldev, struct gpio_chip *chip,
+	unsigned offset, unsigned gpio)
 {
 	const char *label = gpiochip_is_requested(chip, offset);
 	struct nmk_gpio_chip *nmk_chip =
@@ -1078,12 +1106,18 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s, struct gpio_chip *chip,
 		[NMK_GPIO_ALT_A]	= "altA",
 		[NMK_GPIO_ALT_B]	= "altB",
 		[NMK_GPIO_ALT_C]	= "altC",
+		[NMK_GPIO_ALT_C+1]	= "altC1",
+		[NMK_GPIO_ALT_C+2]	= "altC2",
+		[NMK_GPIO_ALT_C+3]	= "altC3",
+		[NMK_GPIO_ALT_C+4]	= "altC4",
 	};
 
 	clk_enable(nmk_chip->clk);
 	is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & bit);
 	pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit);
 	mode = nmk_gpio_get_mode(gpio);
+	if ((mode == NMK_GPIO_ALT_C) && pctldev)
+		mode = nmk_prcm_gpiocr_get_mode(pctldev, gpio);
 
 	seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s",
 		   gpio, label ?: "(none)",
@@ -1127,13 +1161,14 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 	unsigned		gpio = chip->base;
 
 	for (i = 0; i < chip->ngpio; i++, gpio++) {
-		nmk_gpio_dbg_show_one(s, chip, i, gpio);
+		nmk_gpio_dbg_show_one(s, NULL, chip, i, gpio);
 		seq_printf(s, "\n");
 	}
 }
 
 #else
 static inline void nmk_gpio_dbg_show_one(struct seq_file *s,
+					 struct pinctrl_dev *pctldev,
 					 struct gpio_chip *chip,
 					 unsigned offset, unsigned gpio)
 {
@@ -1250,8 +1285,8 @@ void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up)
 	}
 }
 
-int nmk_gpio_irq_map(struct irq_domain *d, unsigned int irq,
-			  irq_hw_number_t hwirq)
+static int nmk_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+			    irq_hw_number_t hwirq)
 {
 	struct nmk_gpio_chip *nmk_chip = d->host_data;
 
@@ -1464,7 +1499,7 @@ static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
 		return;
 	}
 	chip = range->gc;
-	nmk_gpio_dbg_show_one(s, chip, offset - chip->base, offset);
+	nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset);
 }
 
 static struct pinctrl_ops nmk_pinctrl_ops = {
@@ -1635,9 +1670,9 @@ static void nmk_pmx_disable(struct pinctrl_dev *pctldev,
 	dev_dbg(npct->dev, "disable group %s, %u pins\n", g->name, g->npins);
 }
 
-int nmk_gpio_request_enable(struct pinctrl_dev *pctldev,
-			    struct pinctrl_gpio_range *range,
-			    unsigned offset)
+static int nmk_gpio_request_enable(struct pinctrl_dev *pctldev,
+				   struct pinctrl_gpio_range *range,
+				   unsigned offset)
 {
 	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
 	struct nmk_gpio_chip *nmk_chip;
@@ -1666,9 +1701,9 @@ int nmk_gpio_request_enable(struct pinctrl_dev *pctldev,
 	return 0;
 }
 
-void nmk_gpio_disable_free(struct pinctrl_dev *pctldev,
-			   struct pinctrl_gpio_range *range,
-			   unsigned offset)
+static void nmk_gpio_disable_free(struct pinctrl_dev *pctldev,
+				  struct pinctrl_gpio_range *range,
+				  unsigned offset)
 {
 	struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
 
@@ -1686,17 +1721,15 @@ static struct pinmux_ops nmk_pinmux_ops = {
 	.gpio_disable_free = nmk_gpio_disable_free,
 };
 
-int nmk_pin_config_get(struct pinctrl_dev *pctldev,
-		       unsigned pin,
-		       unsigned long *config)
+static int nmk_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
+			      unsigned long *config)
 {
 	/* Not implemented */
 	return -EINVAL;
 }
 
-int nmk_pin_config_set(struct pinctrl_dev *pctldev,
-		       unsigned pin,
-		       unsigned long config)
+static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
+			      unsigned long config)
 {
 	static const char *pullnames[] = {
 		[NMK_GPIO_PULL_NONE]	= "none",
@@ -1818,6 +1851,7 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev)
 	const struct platform_device_id *platid = platform_get_device_id(pdev);
 	struct device_node *np = pdev->dev.of_node;
 	struct nmk_pinctrl *npct;
+	struct resource *res;
 	unsigned int version = 0;
 	int i;
 
@@ -1827,9 +1861,14 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev)
 
 	if (platid)
 		version = platid->driver_data;
-	else if (np)
-		version = (unsigned int)
-			of_match_device(nmk_pinctrl_match, &pdev->dev)->data;
+	else if (np) {
+		const struct of_device_id *match;
+
+		match = of_match_device(nmk_pinctrl_match, &pdev->dev);
+		if (!match)
+			return -ENODEV;
+		version = (unsigned int) match->data;
+	}
 
 	/* Poke in other ASIC variants here */
 	if (version == PINCTRL_NMK_STN8815)
@@ -1839,22 +1878,37 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev)
 	if (version == PINCTRL_NMK_DB8540)
 		nmk_pinctrl_db8540_init(&npct->soc);
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res) {
+		npct->prcm_base = devm_ioremap(&pdev->dev, res->start,
+					       resource_size(res));
+		if (!npct->prcm_base) {
+			dev_err(&pdev->dev,
+				"failed to ioremap PRCM registers\n");
+			return -ENOMEM;
+		}
+	} else {
+		dev_info(&pdev->dev,
+			 "No PRCM base, assume no ALT-Cx control is available\n");
+	}
+
 	/*
 	 * We need all the GPIO drivers to probe FIRST, or we will not be able
 	 * to obtain references to the struct gpio_chip * for them, and we
 	 * need this to proceed.
 	 */
 	for (i = 0; i < npct->soc->gpio_num_ranges; i++) {
-		if (!nmk_gpio_chips[i]) {
+		if (!nmk_gpio_chips[npct->soc->gpio_ranges[i].id]) {
 			dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i);
 			return -EPROBE_DEFER;
 		}
-		npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[i]->chip;
+		npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[npct->soc->gpio_ranges[i].id]->chip;
 	}
 
 	nmk_pinctrl_desc.pins = npct->soc->pins;
 	nmk_pinctrl_desc.npins = npct->soc->npins;
 	npct->dev = &pdev->dev;
+
 	npct->pctl = pinctrl_register(&nmk_pinctrl_desc, &pdev->dev, npct);
 	if (!npct->pctl) {
 		dev_err(&pdev->dev, "could not register Nomadik pinctrl driver\n");
@@ -1889,6 +1943,7 @@ static const struct platform_device_id nmk_pinctrl_id[] = {
 	{ "pinctrl-stn8815", PINCTRL_NMK_STN8815 },
 	{ "pinctrl-db8500", PINCTRL_NMK_DB8500 },
 	{ "pinctrl-db8540", PINCTRL_NMK_DB8540 },
+	{ }
 };
 
 static struct platform_driver nmk_pinctrl_driver = {
diff --git a/drivers/pinctrl/pinctrl-nomadik.h b/drivers/pinctrl/pinctrl-nomadik.h
index eef316e..bcd4191 100644
--- a/drivers/pinctrl/pinctrl-nomadik.h
+++ b/drivers/pinctrl/pinctrl-nomadik.h
@@ -1,7 +1,7 @@
 #ifndef PINCTRL_PINCTRL_NOMADIK_H
 #define PINCTRL_PINCTRL_NOMADIK_H
 
-#include <plat/gpio-nomadik.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
 
 /* Package definitions */
 #define PINCTRL_NMK_STN8815	0
diff --git a/drivers/pinctrl/pinctrl-pxa168.c b/drivers/pinctrl/pinctrl-pxa168.c
index c1997fa..cb771e4 100644
--- a/drivers/pinctrl/pinctrl-pxa168.c
+++ b/drivers/pinctrl/pinctrl-pxa168.c
@@ -620,7 +620,7 @@ static int __devinit pxa168_pinmux_probe(struct platform_device *pdev)
 	return pxa3xx_pinctrl_register(pdev, &pxa168_info);
 }
 
-static int __devexit pxa168_pinmux_remove(struct platform_device *pdev)
+static int pxa168_pinmux_remove(struct platform_device *pdev)
 {
 	return pxa3xx_pinctrl_unregister(pdev);
 }
@@ -631,7 +631,7 @@ static struct platform_driver pxa168_pinmux_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe	= pxa168_pinmux_probe,
-	.remove	= __devexit_p(pxa168_pinmux_remove),
+	.remove	= pxa168_pinmux_remove,
 };
 
 static int __init pxa168_pinmux_init(void)
diff --git a/drivers/pinctrl/pinctrl-pxa3xx.c b/drivers/pinctrl/pinctrl-pxa3xx.c
index f14cd6b..51f8a38 100644
--- a/drivers/pinctrl/pinctrl-pxa3xx.c
+++ b/drivers/pinctrl/pinctrl-pxa3xx.c
@@ -173,7 +173,6 @@ int pxa3xx_pinctrl_register(struct platform_device *pdev,
 {
 	struct pinctrl_desc *desc;
 	struct resource *res;
-	int ret = 0;
 
 	if (!info || !info->cputype)
 		return -EINVAL;
@@ -188,23 +187,17 @@ int pxa3xx_pinctrl_register(struct platform_device *pdev,
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
 		return -ENOENT;
-	info->phy_base = res->start;
-	info->phy_size = resource_size(res);
-	info->virt_base = ioremap(info->phy_base, info->phy_size);
+	info->virt_base = devm_request_and_ioremap(&pdev->dev, res);
 	if (!info->virt_base)
 		return -ENOMEM;
 	info->pctrl = pinctrl_register(desc, &pdev->dev, info);
 	if (!info->pctrl) {
 		dev_err(&pdev->dev, "failed to register PXA pinmux driver\n");
-		ret = -EINVAL;
-		goto err;
+		return -EINVAL;
 	}
 	pinctrl_add_gpio_range(info->pctrl, &pxa3xx_pinctrl_gpio_range);
 	platform_set_drvdata(pdev, info);
 	return 0;
-err:
-	iounmap(info->virt_base);
-	return ret;
 }
 
 int pxa3xx_pinctrl_unregister(struct platform_device *pdev)
@@ -212,7 +205,6 @@ int pxa3xx_pinctrl_unregister(struct platform_device *pdev)
 	struct pxa3xx_pinmux_info *info = platform_get_drvdata(pdev);
 
 	pinctrl_unregister(info->pctrl);
-	iounmap(info->virt_base);
 	platform_set_drvdata(pdev, NULL);
 	return 0;
 }
diff --git a/drivers/pinctrl/pinctrl-pxa3xx.h b/drivers/pinctrl/pinctrl-pxa3xx.h
index 8135744..92fad08 100644
--- a/drivers/pinctrl/pinctrl-pxa3xx.h
+++ b/drivers/pinctrl/pinctrl-pxa3xx.h
@@ -60,8 +60,6 @@ struct pxa3xx_pinmux_info {
 	struct device *dev;
 	struct pinctrl_dev *pctrl;
 	enum pxa_cpu_type cputype;
-	unsigned int phy_base;
-	unsigned int phy_size;
 	void __iomem *virt_base;
 
 	struct pxa3xx_mfp_pin *mfp;
diff --git a/drivers/pinctrl/pinctrl-pxa910.c b/drivers/pinctrl/pinctrl-pxa910.c
index c72ab4b..5fecd22 100644
--- a/drivers/pinctrl/pinctrl-pxa910.c
+++ b/drivers/pinctrl/pinctrl-pxa910.c
@@ -976,7 +976,7 @@ static int __devinit pxa910_pinmux_probe(struct platform_device *pdev)
 	return pxa3xx_pinctrl_register(pdev, &pxa910_info);
 }
 
-static int __devexit pxa910_pinmux_remove(struct platform_device *pdev)
+static int pxa910_pinmux_remove(struct platform_device *pdev)
 {
 	return pxa3xx_pinctrl_unregister(pdev);
 }
@@ -987,7 +987,7 @@ static struct platform_driver pxa910_pinmux_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe	= pxa910_pinmux_probe,
-	.remove	= __devexit_p(pxa910_pinmux_remove),
+	.remove	= pxa910_pinmux_remove,
 };
 
 static int __init pxa910_pinmux_init(void)
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index 861cd5f..8f31b65 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
+#include <linux/irqdomain.h>
 
 #include "core.h"
 #include "pinctrl-samsung.h"
@@ -46,6 +47,13 @@ struct pin_config {
 	{ "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN },
 };
 
+static unsigned int pin_base;
+
+static inline struct samsung_pin_bank *gc_to_pin_bank(struct gpio_chip *gc)
+{
+	return container_of(gc, struct samsung_pin_bank, gpio_chip);
+}
+
 /* check if the selector is a valid pin group selector */
 static int samsung_get_group_count(struct pinctrl_dev *pctldev)
 {
@@ -250,14 +258,12 @@ static int samsung_pinmux_get_groups(struct pinctrl_dev *pctldev,
  * given a pin number that is local to a pin controller, find out the pin bank
  * and the register base of the pin bank.
  */
-static void pin_to_reg_bank(struct gpio_chip *gc, unsigned pin,
-			void __iomem **reg, u32 *offset,
+static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata,
+			unsigned pin, void __iomem **reg, u32 *offset,
 			struct samsung_pin_bank **bank)
 {
-	struct samsung_pinctrl_drv_data *drvdata;
 	struct samsung_pin_bank *b;
 
-	drvdata = dev_get_drvdata(gc->dev);
 	b = drvdata->ctrl->pin_banks;
 
 	while ((pin >= b->pin_base) &&
@@ -292,7 +298,7 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
 	 * pin function number in the config register.
 	 */
 	for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) {
-		pin_to_reg_bank(drvdata->gc, pins[cnt] - drvdata->ctrl->base,
+		pin_to_reg_bank(drvdata, pins[cnt] - drvdata->ctrl->base,
 				&reg, &pin_offset, &bank);
 		mask = (1 << bank->func_width) - 1;
 		shift = pin_offset * bank->func_width;
@@ -329,10 +335,16 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
 		struct pinctrl_gpio_range *range, unsigned offset, bool input)
 {
 	struct samsung_pin_bank *bank;
+	struct samsung_pinctrl_drv_data *drvdata;
 	void __iomem *reg;
 	u32 data, pin_offset, mask, shift;
 
-	pin_to_reg_bank(range->gc, offset, &reg, &pin_offset, &bank);
+	bank = gc_to_pin_bank(range->gc);
+	drvdata = pinctrl_dev_get_drvdata(pctldev);
+
+	pin_offset = offset - bank->pin_base;
+	reg = drvdata->virt_base + bank->pctl_offset;
+
 	mask = (1 << bank->func_width) - 1;
 	shift = pin_offset * bank->func_width;
 
@@ -366,7 +378,7 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
 	u32 cfg_value, cfg_reg;
 
 	drvdata = pinctrl_dev_get_drvdata(pctldev);
-	pin_to_reg_bank(drvdata->gc, pin - drvdata->ctrl->base, &reg_base,
+	pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, &reg_base,
 					&pin_offset, &bank);
 
 	switch (cfg_type) {
@@ -391,6 +403,9 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
 		return -EINVAL;
 	}
 
+	if (!width)
+		return -EINVAL;
+
 	mask = (1 << width) - 1;
 	shift = pin_offset * width;
 	data = readl(reg_base + cfg_reg);
@@ -463,14 +478,16 @@ static struct pinconf_ops samsung_pinconf_ops = {
 /* gpiolib gpio_set callback function */
 static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
 {
+	struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
 	void __iomem *reg;
-	u32 pin_offset, data;
+	u32 data;
+
+	reg = bank->drvdata->virt_base + bank->pctl_offset;
 
-	pin_to_reg_bank(gc, offset, &reg, &pin_offset, NULL);
 	data = readl(reg + DAT_REG);
-	data &= ~(1 << pin_offset);
+	data &= ~(1 << offset);
 	if (value)
-		data |= 1 << pin_offset;
+		data |= 1 << offset;
 	writel(data, reg + DAT_REG);
 }
 
@@ -478,11 +495,13 @@ static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
 static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
 {
 	void __iomem *reg;
-	u32 pin_offset, data;
+	u32 data;
+	struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
+
+	reg = bank->drvdata->virt_base + bank->pctl_offset;
 
-	pin_to_reg_bank(gc, offset, &reg, &pin_offset, NULL);
 	data = readl(reg + DAT_REG);
-	data >>= pin_offset;
+	data >>= offset;
 	data &= 1;
 	return data;
 }
@@ -510,6 +529,23 @@ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
 }
 
 /*
+ * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin
+ * and a virtual IRQ, if not already present.
+ */
+static int samsung_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+	struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
+	unsigned int virq;
+
+	if (!bank->irq_domain)
+		return -ENXIO;
+
+	virq = irq_create_mapping(bank->irq_domain, offset);
+
+	return (virq) ? : -ENXIO;
+}
+
+/*
  * Parse the pin names listed in the 'samsung,pins' property and convert it
  * into a list of gpio numbers are create a pin group from it.
  */
@@ -524,7 +560,7 @@ static int __devinit samsung_pinctrl_parse_dt_pins(struct platform_device *pdev,
 	const char *pin_name;
 
 	*npins = of_property_count_strings(cfg_np, "samsung,pins");
-	if (*npins < 0) {
+	if (IS_ERR_VALUE(*npins)) {
 		dev_err(dev, "invalid pin list in %s node", cfg_np->name);
 		return -EINVAL;
 	}
@@ -597,7 +633,7 @@ static int __devinit samsung_pinctrl_parse_dt(struct platform_device *pdev,
 	 */
 	for_each_child_of_node(dev_np, cfg_np) {
 		u32 function;
-		if (of_find_property(cfg_np, "interrupt-controller", NULL))
+		if (!of_find_property(cfg_np, "samsung,pins", NULL))
 			continue;
 
 		ret = samsung_pinctrl_parse_dt_pins(pdev, cfg_np,
@@ -712,12 +748,16 @@ static int __devinit samsung_pinctrl_register(struct platform_device *pdev,
 		return -EINVAL;
 	}
 
-	drvdata->grange.name = "samsung-pctrl-gpio-range";
-	drvdata->grange.id = 0;
-	drvdata->grange.base = drvdata->ctrl->base;
-	drvdata->grange.npins = drvdata->ctrl->nr_pins;
-	drvdata->grange.gc = drvdata->gc;
-	pinctrl_add_gpio_range(drvdata->pctl_dev, &drvdata->grange);
+	for (bank = 0; bank < drvdata->ctrl->nr_banks; ++bank) {
+		pin_bank = &drvdata->ctrl->pin_banks[bank];
+		pin_bank->grange.name = pin_bank->name;
+		pin_bank->grange.id = bank;
+		pin_bank->grange.pin_base = pin_bank->pin_base;
+		pin_bank->grange.base = pin_bank->gpio_chip.base;
+		pin_bank->grange.npins = pin_bank->gpio_chip.ngpio;
+		pin_bank->grange.gc = &pin_bank->gpio_chip;
+		pinctrl_add_gpio_range(drvdata->pctl_dev, &pin_bank->grange);
+	}
 
 	ret = samsung_pinctrl_parse_dt(pdev, drvdata);
 	if (ret) {
@@ -728,68 +768,117 @@ static int __devinit samsung_pinctrl_register(struct platform_device *pdev,
 	return 0;
 }
 
+static const struct gpio_chip samsung_gpiolib_chip = {
+	.set = samsung_gpio_set,
+	.get = samsung_gpio_get,
+	.direction_input = samsung_gpio_direction_input,
+	.direction_output = samsung_gpio_direction_output,
+	.to_irq = samsung_gpio_to_irq,
+	.owner = THIS_MODULE,
+};
+
 /* register the gpiolib interface with the gpiolib subsystem */
 static int __devinit samsung_gpiolib_register(struct platform_device *pdev,
 				struct samsung_pinctrl_drv_data *drvdata)
 {
+	struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+	struct samsung_pin_bank *bank = ctrl->pin_banks;
 	struct gpio_chip *gc;
 	int ret;
-
-	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc) {
-		dev_err(&pdev->dev, "mem alloc for gpio_chip failed\n");
-		return -ENOMEM;
-	}
-
-	drvdata->gc = gc;
-	gc->base = drvdata->ctrl->base;
-	gc->ngpio = drvdata->ctrl->nr_pins;
-	gc->dev = &pdev->dev;
-	gc->set = samsung_gpio_set;
-	gc->get = samsung_gpio_get;
-	gc->direction_input = samsung_gpio_direction_input;
-	gc->direction_output = samsung_gpio_direction_output;
-	gc->label = drvdata->ctrl->label;
-	gc->owner = THIS_MODULE;
-	ret = gpiochip_add(gc);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to register gpio_chip %s, error "
-					"code: %d\n", gc->label, ret);
-		return ret;
+	int i;
+
+	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+		bank->gpio_chip = samsung_gpiolib_chip;
+
+		gc = &bank->gpio_chip;
+		gc->base = ctrl->base + bank->pin_base;
+		gc->ngpio = bank->nr_pins;
+		gc->dev = &pdev->dev;
+		gc->of_node = bank->of_node;
+		gc->label = bank->name;
+
+		ret = gpiochip_add(gc);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to register gpio_chip %s, error code: %d\n",
+							gc->label, ret);
+			goto fail;
+		}
 	}
 
 	return 0;
+
+fail:
+	for (--i, --bank; i >= 0; --i, --bank)
+		if (gpiochip_remove(&bank->gpio_chip))
+			dev_err(&pdev->dev, "gpio chip %s remove failed\n",
+							bank->gpio_chip.label);
+	return ret;
 }
 
 /* unregister the gpiolib interface with the gpiolib subsystem */
 static int __devinit samsung_gpiolib_unregister(struct platform_device *pdev,
 				struct samsung_pinctrl_drv_data *drvdata)
 {
-	int ret = gpiochip_remove(drvdata->gc);
-	if (ret) {
+	struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+	struct samsung_pin_bank *bank = ctrl->pin_banks;
+	int ret = 0;
+	int i;
+
+	for (i = 0; !ret && i < ctrl->nr_banks; ++i, ++bank)
+		ret = gpiochip_remove(&bank->gpio_chip);
+
+	if (ret)
 		dev_err(&pdev->dev, "gpio chip remove failed\n");
-		return ret;
-	}
-	return 0;
+
+	return ret;
 }
 
 static const struct of_device_id samsung_pinctrl_dt_match[];
 
 /* retrieve the soc specific data */
 static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(
+				struct samsung_pinctrl_drv_data *d,
 				struct platform_device *pdev)
 {
 	int id;
 	const struct of_device_id *match;
-	const struct device_node *node = pdev->dev.of_node;
+	struct device_node *node = pdev->dev.of_node;
+	struct device_node *np;
+	struct samsung_pin_ctrl *ctrl;
+	struct samsung_pin_bank *bank;
+	int i;
 
-	id = of_alias_get_id(pdev->dev.of_node, "pinctrl");
+	id = of_alias_get_id(node, "pinctrl");
 	if (id < 0) {
 		dev_err(&pdev->dev, "failed to get alias id\n");
 		return NULL;
 	}
 	match = of_match_node(samsung_pinctrl_dt_match, node);
-	return (struct samsung_pin_ctrl *)match->data + id;
+	ctrl = (struct samsung_pin_ctrl *)match->data + id;
+
+	bank = ctrl->pin_banks;
+	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+		bank->drvdata = d;
+		bank->pin_base = ctrl->nr_pins;
+		ctrl->nr_pins += bank->nr_pins;
+	}
+
+	for_each_child_of_node(node, np) {
+		if (!of_find_property(np, "gpio-controller", NULL))
+			continue;
+		bank = ctrl->pin_banks;
+		for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+			if (!strcmp(bank->name, np->name)) {
+				bank->of_node = np;
+				break;
+			}
+		}
+	}
+
+	ctrl->base = pin_base;
+	pin_base += ctrl->nr_pins;
+
+	return ctrl;
 }
 
 static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
@@ -805,18 +894,18 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	ctrl = samsung_pinctrl_get_soc_data(pdev);
-	if (!ctrl) {
-		dev_err(&pdev->dev, "driver data not available\n");
-		return -EINVAL;
-	}
-
 	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
 	if (!drvdata) {
 		dev_err(dev, "failed to allocate memory for driver's "
 				"private data\n");
 		return -ENOMEM;
 	}
+
+	ctrl = samsung_pinctrl_get_soc_data(drvdata, pdev);
+	if (!ctrl) {
+		dev_err(&pdev->dev, "driver data not available\n");
+		return -EINVAL;
+	}
 	drvdata->ctrl = ctrl;
 	drvdata->dev = dev;
 
@@ -858,6 +947,8 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
 static const struct of_device_id samsung_pinctrl_dt_match[] = {
 	{ .compatible = "samsung,pinctrl-exynos4210",
 		.data = (void *)exynos4210_pin_ctrl },
+	{ .compatible = "samsung,pinctrl-exynos4x12",
+		.data = (void *)exynos4x12_pin_ctrl },
 	{},
 };
 MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match);
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
index b895693..5addfd1 100644
--- a/drivers/pinctrl/pinctrl-samsung.h
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -23,6 +23,8 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/pinctrl/machine.h>
 
+#include <linux/gpio.h>
+
 /* register offsets within a pin bank */
 #define DAT_REG		0x4
 #define PUD_REG		0x8
@@ -64,6 +66,7 @@ enum pincfg_type {
  * @EINT_TYPE_NONE: bank does not support external interrupts
  * @EINT_TYPE_GPIO: bank supportes external gpio interrupts
  * @EINT_TYPE_WKUP: bank supportes external wakeup interrupts
+ * @EINT_TYPE_WKUP_MUX: bank supports multiplexed external wakeup interrupts
  *
  * Samsung GPIO controller groups all the available pins into banks. The pins
  * in a pin bank can support external gpio interrupts or external wakeup
@@ -76,6 +79,7 @@ enum eint_type {
 	EINT_TYPE_NONE,
 	EINT_TYPE_GPIO,
 	EINT_TYPE_WKUP,
+	EINT_TYPE_WKUP_MUX,
 };
 
 /* maximum length of a pin in pin descriptor (example: "gpa0-0") */
@@ -109,8 +113,12 @@ struct samsung_pinctrl_drv_data;
  * @conpdn_width: width of the sleep mode function selector bin field.
  * @pudpdn_width: width of the sleep mode pull up/down selector bit field.
  * @eint_type: type of the external interrupt supported by the bank.
- * @irq_base: starting controller local irq number of the bank.
  * @name: name to be prefixed for each pin in this pin bank.
+ * @of_node: OF node of the bank.
+ * @drvdata: link to controller driver data
+ * @irq_domain: IRQ domain of the bank.
+ * @gpio_chip: GPIO chip of the bank.
+ * @grange: linux gpio pin range supported by this bank.
  */
 struct samsung_pin_bank {
 	u32		pctl_offset;
@@ -122,8 +130,13 @@ struct samsung_pin_bank {
 	u8		conpdn_width;
 	u8		pudpdn_width;
 	enum eint_type	eint_type;
-	u32		irq_base;
+	u32		eint_offset;
 	char		*name;
+	struct device_node *of_node;
+	struct samsung_pinctrl_drv_data *drvdata;
+	struct irq_domain *irq_domain;
+	struct gpio_chip gpio_chip;
+	struct pinctrl_gpio_range grange;
 };
 
 /**
@@ -132,8 +145,6 @@ struct samsung_pin_bank {
  * @nr_banks: number of pin banks.
  * @base: starting system wide pin number.
  * @nr_pins: number of pins supported by the controller.
- * @nr_gint: number of external gpio interrupts supported.
- * @nr_wint: number of external wakeup interrupts supported.
  * @geint_con: offset of the ext-gpio controller registers.
  * @geint_mask: offset of the ext-gpio interrupt mask registers.
  * @geint_pend: offset of the ext-gpio interrupt pending registers.
@@ -153,8 +164,6 @@ struct samsung_pin_ctrl {
 
 	u32		base;
 	u32		nr_pins;
-	u32		nr_gint;
-	u32		nr_wint;
 
 	u32		geint_con;
 	u32		geint_mask;
@@ -183,8 +192,6 @@ struct samsung_pin_ctrl {
  * @nr_groups: number of such pin groups.
  * @pmx_functions: list of pin functions available to the driver.
  * @nr_function: number of such pin functions.
- * @gc: gpio_chip instance registered with gpiolib.
- * @grange: linux gpio pin range supported by this controller.
  */
 struct samsung_pinctrl_drv_data {
 	void __iomem			*virt_base;
@@ -199,12 +206,6 @@ struct samsung_pinctrl_drv_data {
 	unsigned int			nr_groups;
 	const struct samsung_pmx_func	*pmx_functions;
 	unsigned int			nr_functions;
-
-	struct irq_domain		*gpio_irqd;
-	struct irq_domain		*wkup_irqd;
-
-	struct gpio_chip		*gc;
-	struct pinctrl_gpio_range	grange;
 };
 
 /**
@@ -235,5 +236,6 @@ struct samsung_pmx_func {
 
 /* list of all exported SoC specific data */
 extern struct samsung_pin_ctrl exynos4210_pin_ctrl[];
+extern struct samsung_pin_ctrl exynos4x12_pin_ctrl[];
 
 #endif /* __PINCTRL_SAMSUNG_H */
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 726a729..62f2747 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -30,6 +30,7 @@
 #define PCS_MUX_BITS_NAME		"pinctrl-single,bits"
 #define PCS_REG_NAME_LEN		((sizeof(unsigned long) * 2) + 1)
 #define PCS_OFF_DISABLED		~0U
+#define PCS_MAX_GPIO_VALUES		2
 
 /**
  * struct pcs_pingroup - pingroups for a function
@@ -77,6 +78,16 @@ struct pcs_function {
 };
 
 /**
+ * struct pcs_gpio_range - pinctrl gpio range
+ * @range:	subrange of the GPIO number space
+ * @gpio_func:	gpio function value in the pinmux register
+ */
+struct pcs_gpio_range {
+	struct pinctrl_gpio_range range;
+	int gpio_func;
+};
+
+/**
  * struct pcs_data - wrapper for data needed by pinctrl framework
  * @pa:		pindesc array
  * @cur:	index to current element
@@ -244,15 +255,15 @@ static int pcs_get_group_pins(struct pinctrl_dev *pctldev,
 
 static void pcs_pin_dbg_show(struct pinctrl_dev *pctldev,
 					struct seq_file *s,
-					unsigned offset)
+					unsigned pin)
 {
 	struct pcs_device *pcs;
-	unsigned val;
+	unsigned val, mux_bytes;
 
 	pcs = pinctrl_dev_get_drvdata(pctldev);
 
-	val = pcs->read(pcs->base + offset);
-	val &= pcs->fmask;
+	mux_bytes = pcs->width / BITS_PER_BYTE;
+	val = pcs->read(pcs->base + pin * mux_bytes);
 
 	seq_printf(s, "%08x %s " , val, DRIVER_NAME);
 }
@@ -403,9 +414,26 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector,
 }
 
 static int pcs_request_gpio(struct pinctrl_dev *pctldev,
-			struct pinctrl_gpio_range *range, unsigned offset)
+			    struct pinctrl_gpio_range *range, unsigned pin)
 {
-	return -ENOTSUPP;
+	struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
+	struct pcs_gpio_range *gpio = NULL;
+	int end, mux_bytes;
+	unsigned data;
+
+	gpio = container_of(range, struct pcs_gpio_range, range);
+	end = range->pin_base + range->npins - 1;
+	if (pin < range->pin_base || pin > end) {
+		dev_err(pctldev->dev,
+			"pin %d isn't in the range of %d to %d\n",
+			pin, range->pin_base, end);
+		return -EINVAL;
+	}
+	mux_bytes = pcs->width / BITS_PER_BYTE;
+	data = pcs->read(pcs->base + pin * mux_bytes) & ~pcs->fmask;
+	data |= gpio->gpio_func;
+	pcs->write(data, pcs->base + pin * mux_bytes);
+	return 0;
 }
 
 static struct pinmux_ops pcs_pinmux_ops = {
@@ -879,6 +907,50 @@ static void pcs_free_resources(struct pcs_device *pcs)
 
 static struct of_device_id pcs_of_match[];
 
+static int __devinit pcs_add_gpio_range(struct device_node *node,
+					struct pcs_device *pcs)
+{
+	struct pcs_gpio_range *gpio;
+	struct device_node *child;
+	struct resource r;
+	const char name[] = "pinctrl-single";
+	u32 gpiores[PCS_MAX_GPIO_VALUES];
+	int ret, i = 0, mux_bytes = 0;
+
+	for_each_child_of_node(node, child) {
+		ret = of_address_to_resource(child, 0, &r);
+		if (ret < 0)
+			continue;
+		memset(gpiores, 0, sizeof(u32) * PCS_MAX_GPIO_VALUES);
+		ret = of_property_read_u32_array(child, "pinctrl-single,gpio",
+						 gpiores, PCS_MAX_GPIO_VALUES);
+		if (ret < 0)
+			continue;
+		gpio = devm_kzalloc(pcs->dev, sizeof(*gpio), GFP_KERNEL);
+		if (!gpio) {
+			dev_err(pcs->dev, "failed to allocate pcs gpio\n");
+			return -ENOMEM;
+		}
+		gpio->range.name = devm_kzalloc(pcs->dev, sizeof(name),
+						GFP_KERNEL);
+		if (!gpio->range.name) {
+			dev_err(pcs->dev, "failed to allocate range name\n");
+			return -ENOMEM;
+		}
+		memcpy((char *)gpio->range.name, name, sizeof(name));
+
+		gpio->range.id = i++;
+		gpio->range.base = gpiores[0];
+		gpio->gpio_func = gpiores[1];
+		mux_bytes = pcs->width / BITS_PER_BYTE;
+		gpio->range.pin_base = (r.start - pcs->res->start) / mux_bytes;
+		gpio->range.npins = (r.end - r.start) / mux_bytes + 1;
+
+		pinctrl_add_gpio_range(pcs->pctl, &gpio->range);
+	}
+	return 0;
+}
+
 static int __devinit pcs_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -975,6 +1047,10 @@ static int __devinit pcs_probe(struct platform_device *pdev)
 		goto free;
 	}
 
+	ret = pcs_add_gpio_range(np, pcs);
+	if (ret < 0)
+		goto free;
+
 	dev_info(pcs->dev, "%i pins at pa %p size %u\n",
 		 pcs->desc.npins, pcs->base, pcs->size);
 
@@ -986,7 +1062,7 @@ free:
 	return ret;
 }
 
-static int __devexit pcs_remove(struct platform_device *pdev)
+static int pcs_remove(struct platform_device *pdev)
 {
 	struct pcs_device *pcs = platform_get_drvdata(pdev);
 
@@ -998,7 +1074,7 @@ static int __devexit pcs_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static struct of_device_id pcs_of_match[] __devinitdata = {
+static struct of_device_id pcs_of_match[] = {
 	{ .compatible = DRIVER_NAME, },
 	{ },
 };
@@ -1006,7 +1082,7 @@ MODULE_DEVICE_TABLE(of, pcs_of_match);
 
 static struct platform_driver pcs_driver = {
 	.probe		= pcs_probe,
-	.remove		= __devexit_p(pcs_remove),
+	.remove		= pcs_remove,
 	.driver = {
 		.owner		= THIS_MODULE,
 		.name		= DRIVER_NAME,
diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c
index 9ecacf3..a4f0c5e 100644
--- a/drivers/pinctrl/pinctrl-sirf.c
+++ b/drivers/pinctrl/pinctrl-sirf.c
@@ -32,10 +32,10 @@
 #define SIRFSOC_NUM_PADS    622
 #define SIRFSOC_RSC_PIN_MUX 0x4
 
-#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
+#define SIRFSOC_GPIO_PAD_EN(g)		((g)*0x100 + 0x84)
+#define SIRFSOC_GPIO_PAD_EN_CLR(g)	((g)*0x100 + 0x90)
 #define SIRFSOC_GPIO_CTRL(g, i)			((g)*0x100 + (i)*4)
 #define SIRFSOC_GPIO_DSP_EN0			(0x80)
-#define SIRFSOC_GPIO_PAD_EN(g)			((g)*0x100 + 0x84)
 #define SIRFSOC_GPIO_INT_STATUS(g)		((g)*0x100 + 0x8C)
 
 #define SIRFSOC_GPIO_CTL_INTR_LOW_MASK		0x1
@@ -60,6 +60,7 @@ struct sirfsoc_gpio_bank {
 	int id;
 	int parent_irq;
 	spinlock_t lock;
+	bool is_marco; /* for marco, some registers are different with prima2 */
 };
 
 static struct sirfsoc_gpio_bank sgpio_bank[SIRFSOC_GPIO_NO_OF_BANKS];
@@ -191,6 +192,7 @@ struct sirfsoc_pmx {
 	struct pinctrl_dev *pmx;
 	void __iomem *gpio_virtbase;
 	void __iomem *rsc_virtbase;
+	bool is_marco;
 };
 
 /* SIRFSOC_GPIO_PAD_EN set */
@@ -1088,12 +1090,21 @@ static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx, unsigned selector
 
 	for (i = 0; i < mux->muxmask_counts; i++) {
 		u32 muxval;
-		muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
-		if (enable)
-			muxval = muxval & ~mask[i].mask;
-		else
-			muxval = muxval | mask[i].mask;
-		writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
+		if (!spmx->is_marco) {
+			muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
+			if (enable)
+				muxval = muxval & ~mask[i].mask;
+			else
+				muxval = muxval | mask[i].mask;
+			writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
+		} else {
+			if (enable)
+				writel(mask[i].mask, spmx->gpio_virtbase +
+					SIRFSOC_GPIO_PAD_EN_CLR(mask[i].group));
+			else
+				writel(mask[i].mask, spmx->gpio_virtbase +
+					SIRFSOC_GPIO_PAD_EN(mask[i].group));
+		}
 	}
 
 	if (mux->funcmask && enable) {
@@ -1158,9 +1169,14 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
 
 	spmx = pinctrl_dev_get_drvdata(pmxdev);
 
-	muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
-	muxval = muxval | (1 << (offset - range->pin_base));
-	writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
+	if (!spmx->is_marco) {
+		muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
+		muxval = muxval | (1 << (offset - range->pin_base));
+		writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
+	} else {
+		writel(1 << (offset - range->pin_base), spmx->gpio_virtbase +
+			SIRFSOC_GPIO_PAD_EN(group));
+	}
 
 	return 0;
 }
@@ -1218,6 +1234,7 @@ static void __iomem *sirfsoc_rsc_of_iomap(void)
 {
 	const struct of_device_id rsc_ids[]  = {
 		{ .compatible = "sirf,prima2-rsc" },
+		{ .compatible = "sirf,marco-rsc" },
 		{}
 	};
 	struct device_node *np;
@@ -1259,6 +1276,9 @@ static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev)
 		goto out_no_rsc_remap;
 	}
 
+	if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
+		spmx->is_marco = 1;
+
 	/* Now register the pin controller and all pins it handles */
 	spmx->pmx = pinctrl_register(&sirfsoc_pinmux_desc, &pdev->dev, spmx);
 	if (!spmx->pmx) {
@@ -1285,8 +1305,9 @@ out_no_gpio_remap:
 	return ret;
 }
 
-static const struct of_device_id pinmux_ids[] __devinitconst = {
+static const struct of_device_id pinmux_ids[] = {
 	{ .compatible = "sirf,prima2-pinctrl" },
+	{ .compatible = "sirf,marco-pinctrl" },
 	{}
 };
 
@@ -1621,8 +1642,8 @@ static void sirfsoc_gpio_set_value(struct gpio_chip *chip, unsigned offset,
 	spin_unlock_irqrestore(&bank->lock, flags);
 }
 
-int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq,
-	irq_hw_number_t hwirq)
+static int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+				irq_hw_number_t hwirq)
 {
 	struct sirfsoc_gpio_bank *bank = d->host_data;
 
@@ -1648,6 +1669,7 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
 	struct sirfsoc_gpio_bank *bank;
 	void *regs;
 	struct platform_device *pdev;
+	bool is_marco = false;
 
 	pdev = of_find_device_by_node(np);
 	if (!pdev)
@@ -1657,6 +1679,9 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
 	if (!regs)
 		return -ENOMEM;
 
+	if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
+		is_marco = 1;
+
 	for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
 		bank = &sgpio_bank[i];
 		spin_lock_init(&bank->lock);
@@ -1673,6 +1698,7 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
 		bank->chip.gc.of_node = np;
 		bank->chip.regs = regs;
 		bank->id = i;
+		bank->is_marco = is_marco;
 		bank->parent_irq = platform_get_irq(pdev, i);
 		if (bank->parent_irq < 0) {
 			err = bank->parent_irq;
diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c
index 7da0b37..e356b03 100644
--- a/drivers/pinctrl/pinctrl-tegra.c
+++ b/drivers/pinctrl/pinctrl-tegra.c
@@ -178,8 +178,9 @@ static int add_config(struct device *dev, unsigned long **configs,
 	return 0;
 }
 
-void tegra_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
-			       struct pinctrl_map *map, unsigned num_maps)
+static void tegra_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+				      struct pinctrl_map *map,
+				      unsigned num_maps)
 {
 	int i;
 
@@ -209,11 +210,11 @@ static const struct cfg_param {
 	{"nvidia,slew-rate-rising",	TEGRA_PINCONF_PARAM_SLEW_RATE_RISING},
 };
 
-int tegra_pinctrl_dt_subnode_to_map(struct device *dev,
-				    struct device_node *np,
-				    struct pinctrl_map **map,
-				    unsigned *reserved_maps,
-				    unsigned *num_maps)
+static int tegra_pinctrl_dt_subnode_to_map(struct device *dev,
+					   struct device_node *np,
+					   struct pinctrl_map **map,
+					   unsigned *reserved_maps,
+					   unsigned *num_maps)
 {
 	int ret, i;
 	const char *function;
@@ -288,9 +289,10 @@ exit:
 	return ret;
 }
 
-int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
-				 struct device_node *np_config,
-				 struct pinctrl_map **map, unsigned *num_maps)
+static int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+					struct device_node *np_config,
+					struct pinctrl_map **map,
+					unsigned *num_maps)
 {
 	unsigned reserved_maps;
 	struct device_node *np;
@@ -660,7 +662,7 @@ static void tegra_pinconf_config_dbg_show(struct pinctrl_dev *pctldev,
 }
 #endif
 
-struct pinconf_ops tegra_pinconf_ops = {
+static struct pinconf_ops tegra_pinconf_ops = {
 	.pin_config_get = tegra_pinconf_get,
 	.pin_config_set = tegra_pinconf_set,
 	.pin_config_group_get = tegra_pinconf_group_get,
@@ -758,7 +760,7 @@ int __devinit tegra_pinctrl_probe(struct platform_device *pdev,
 }
 EXPORT_SYMBOL_GPL(tegra_pinctrl_probe);
 
-int __devexit tegra_pinctrl_remove(struct platform_device *pdev)
+int tegra_pinctrl_remove(struct platform_device *pdev)
 {
 	struct tegra_pmx *pmx = platform_get_drvdata(pdev);
 
diff --git a/drivers/pinctrl/pinctrl-tegra20.c b/drivers/pinctrl/pinctrl-tegra20.c
index a74f9a5..1524bfd 100644
--- a/drivers/pinctrl/pinctrl-tegra20.c
+++ b/drivers/pinctrl/pinctrl-tegra20.c
@@ -2861,7 +2861,7 @@ static int __devinit tegra20_pinctrl_probe(struct platform_device *pdev)
 	return tegra_pinctrl_probe(pdev, &tegra20_pinctrl);
 }
 
-static struct of_device_id tegra20_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id tegra20_pinctrl_of_match[] = {
 	{ .compatible = "nvidia,tegra20-pinmux", },
 	{ },
 };
@@ -2873,7 +2873,7 @@ static struct platform_driver tegra20_pinctrl_driver = {
 		.of_match_table = tegra20_pinctrl_of_match,
 	},
 	.probe = tegra20_pinctrl_probe,
-	.remove = __devexit_p(tegra_pinctrl_remove),
+	.remove = tegra_pinctrl_remove,
 };
 
 static int __init tegra20_pinctrl_init(void)
diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c
index 7894f14..cf579eb 100644
--- a/drivers/pinctrl/pinctrl-tegra30.c
+++ b/drivers/pinctrl/pinctrl-tegra30.c
@@ -3727,7 +3727,7 @@ static int __devinit tegra30_pinctrl_probe(struct platform_device *pdev)
 	return tegra_pinctrl_probe(pdev, &tegra30_pinctrl);
 }
 
-static struct of_device_id tegra30_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id tegra30_pinctrl_of_match[] = {
 	{ .compatible = "nvidia,tegra30-pinmux", },
 	{ },
 };
@@ -3739,7 +3739,7 @@ static struct platform_driver tegra30_pinctrl_driver = {
 		.of_match_table = tegra30_pinctrl_of_match,
 	},
 	.probe = tegra30_pinctrl_probe,
-	.remove = __devexit_p(tegra_pinctrl_remove),
+	.remove = tegra_pinctrl_remove,
 };
 
 static int __init tegra30_pinctrl_init(void)
diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c
index 309f5b9..8c039ad 100644
--- a/drivers/pinctrl/pinctrl-u300.c
+++ b/drivers/pinctrl/pinctrl-u300.c
@@ -663,8 +663,6 @@ static const struct pinctrl_pin_desc u300_pads[] = {
 struct u300_pmx {
 	struct device *dev;
 	struct pinctrl_dev *pctl;
-	u32 phybase;
-	u32 physize;
 	void __iomem *virtbase;
 };
 
@@ -1013,52 +1011,11 @@ static struct pinmux_ops u300_pmx_ops = {
 	.disable = u300_pmx_disable,
 };
 
-/*
- * GPIO ranges handled by the application-side COH901XXX GPIO controller
- * Very many pins can be converted into GPIO pins, but we only list those
- * that are useful in practice to cut down on tables.
- */
-#define U300_GPIO_RANGE(a, b, c) { .name = "COH901XXX", .id = a, .base= a, \
-			.pin_base = b, .npins = c }
-
-static struct pinctrl_gpio_range u300_gpio_ranges[] = {
-	U300_GPIO_RANGE(10, 426, 1),
-	U300_GPIO_RANGE(11, 180, 1),
-	U300_GPIO_RANGE(12, 165, 1), /* MS/MMC card insertion */
-	U300_GPIO_RANGE(13, 179, 1),
-	U300_GPIO_RANGE(14, 178, 1),
-	U300_GPIO_RANGE(16, 194, 1),
-	U300_GPIO_RANGE(17, 193, 1),
-	U300_GPIO_RANGE(18, 192, 1),
-	U300_GPIO_RANGE(19, 191, 1),
-	U300_GPIO_RANGE(20, 186, 1),
-	U300_GPIO_RANGE(21, 185, 1),
-	U300_GPIO_RANGE(22, 184, 1),
-	U300_GPIO_RANGE(23, 183, 1),
-	U300_GPIO_RANGE(24, 182, 1),
-	U300_GPIO_RANGE(25, 181, 1),
-};
-
-static struct pinctrl_gpio_range *u300_match_gpio_range(unsigned pin)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) {
-		struct pinctrl_gpio_range *range;
-
-		range = &u300_gpio_ranges[i];
-		if (pin >= range->pin_base &&
-		    pin <= (range->pin_base + range->npins - 1))
-			return range;
-	}
-	return NULL;
-}
-
-int u300_pin_config_get(struct pinctrl_dev *pctldev,
-			unsigned pin,
-			unsigned long *config)
+static int u300_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
+			       unsigned long *config)
 {
-	struct pinctrl_gpio_range *range = u300_match_gpio_range(pin);
+	struct pinctrl_gpio_range *range =
+		pinctrl_find_gpio_range_from_pin(pctldev, pin);
 
 	/* We get config for those pins we CAN get it for and that's it */
 	if (!range)
@@ -1069,11 +1026,11 @@ int u300_pin_config_get(struct pinctrl_dev *pctldev,
 				    config);
 }
 
-int u300_pin_config_set(struct pinctrl_dev *pctldev,
-			unsigned pin,
-			unsigned long config)
+static int u300_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
+			       unsigned long config)
 {
-	struct pinctrl_gpio_range *range = u300_match_gpio_range(pin);
+	struct pinctrl_gpio_range *range =
+		pinctrl_find_gpio_range_from_pin(pctldev, pin);
 	int ret;
 
 	if (!range)
@@ -1109,9 +1066,6 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)
 {
 	struct u300_pmx *upmx;
 	struct resource *res;
-	struct gpio_chip *gpio_chip = dev_get_platdata(&pdev->dev);
-	int ret;
-	int i;
 
 	/* Create state holders etc for this driver */
 	upmx = devm_kzalloc(&pdev->dev, sizeof(*upmx), GFP_KERNEL);
@@ -1123,32 +1077,15 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
 		return -ENOENT;
-	upmx->phybase = res->start;
-	upmx->physize = resource_size(res);
-
-	if (request_mem_region(upmx->phybase, upmx->physize,
-			       DRIVER_NAME) == NULL) {
-		ret = -ENOMEM;
-		goto out_no_memregion;
-	}
 
-	upmx->virtbase = ioremap(upmx->phybase, upmx->physize);
-	if (!upmx->virtbase) {
-		ret = -ENOMEM;
-		goto out_no_remap;
-	}
+	upmx->virtbase = devm_request_and_ioremap(&pdev->dev, res);
+	if (!upmx->virtbase)
+		return -ENOMEM;
 
 	upmx->pctl = pinctrl_register(&u300_pmx_desc, &pdev->dev, upmx);
 	if (!upmx->pctl) {
 		dev_err(&pdev->dev, "could not register U300 pinmux driver\n");
-		ret = -EINVAL;
-		goto out_no_pmx;
-	}
-
-	/* We will handle a range of GPIO pins */
-	for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) {
-		u300_gpio_ranges[i].gc = gpio_chip;
-		pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_ranges[i]);
+		return -EINVAL;
 	}
 
 	platform_set_drvdata(pdev, upmx);
@@ -1156,23 +1093,13 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)
 	dev_info(&pdev->dev, "initialized U300 pin control driver\n");
 
 	return 0;
-
-out_no_pmx:
-	iounmap(upmx->virtbase);
-out_no_remap:
-	platform_set_drvdata(pdev, NULL);
-out_no_memregion:
-	release_mem_region(upmx->phybase, upmx->physize);
-	return ret;
 }
 
-static int __devexit u300_pmx_remove(struct platform_device *pdev)
+static int u300_pmx_remove(struct platform_device *pdev)
 {
 	struct u300_pmx *upmx = platform_get_drvdata(pdev);
 
 	pinctrl_unregister(upmx->pctl);
-	iounmap(upmx->virtbase);
-	release_mem_region(upmx->phybase, upmx->physize);
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
@@ -1184,7 +1111,7 @@ static struct platform_driver u300_pmx_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = u300_pmx_probe,
-	.remove = __devexit_p(u300_pmx_remove),
+	.remove = u300_pmx_remove,
 };
 
 static int __init u300_pmx_init(void)
diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c
index b9bcaec..ad90984 100644
--- a/drivers/pinctrl/pinctrl-xway.c
+++ b/drivers/pinctrl/pinctrl-xway.c
@@ -522,7 +522,7 @@ static int xway_pinconf_set(struct pinctrl_dev *pctldev,
 	return 0;
 }
 
-struct pinconf_ops xway_pinconf_ops = {
+static struct pinconf_ops xway_pinconf_ops = {
 	.pin_config_get	= xway_pinconf_get,
 	.pin_config_set	= xway_pinconf_set,
 };
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 9301a7a..1a00658 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -314,14 +314,11 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
 {
 	struct pinctrl_dev *pctldev = setting->pctldev;
 	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
-	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
 	char const * const *groups;
 	unsigned num_groups;
 	int ret;
 	const char *group;
 	int i;
-	const unsigned *pins;
-	unsigned num_pins;
 
 	if (!pmxops) {
 		dev_err(pctldev->dev, "does not support mux function\n");
@@ -376,53 +373,12 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
 	}
 	setting->data.mux.group = ret;
 
-	ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, &pins,
-				      &num_pins);
-	if (ret) {
-		dev_err(pctldev->dev,
-			"could not get pins for device %s group selector %d\n",
-			pinctrl_dev_get_name(pctldev), setting->data.mux.group);
-			return -ENODEV;
-	}
-
-	/* Try to allocate all pins in this group, one by one */
-	for (i = 0; i < num_pins; i++) {
-		ret = pin_request(pctldev, pins[i], map->dev_name, NULL);
-		if (ret) {
-			dev_err(pctldev->dev,
-				"could not request pin %d on device %s\n",
-				pins[i], pinctrl_dev_get_name(pctldev));
-			/* On error release all taken pins */
-			i--; /* this pin just failed */
-			for (; i >= 0; i--)
-				pin_free(pctldev, pins[i], NULL);
-			return -ENODEV;
-		}
-	}
-
 	return 0;
 }
 
 void pinmux_free_setting(struct pinctrl_setting const *setting)
 {
-	struct pinctrl_dev *pctldev = setting->pctldev;
-	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
-	const unsigned *pins;
-	unsigned num_pins;
-	int ret;
-	int i;
-
-	ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
-				      &pins, &num_pins);
-	if (ret) {
-		dev_err(pctldev->dev,
-			"could not get pins for device %s group selector %d\n",
-			pinctrl_dev_get_name(pctldev), setting->data.mux.group);
-		return;
-	}
-
-	for (i = 0; i < num_pins; i++)
-		pin_free(pctldev, pins[i], NULL);
+	/* This function is currently unused */
 }
 
 int pinmux_enable_setting(struct pinctrl_setting const *setting)
@@ -446,6 +402,18 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting)
 		num_pins = 0;
 	}
 
+	/* Try to allocate all pins in this group, one by one */
+	for (i = 0; i < num_pins; i++) {
+		ret = pin_request(pctldev, pins[i], setting->dev_name, NULL);
+		if (ret) {
+			dev_err(pctldev->dev,
+				"could not request pin %d on device %s\n",
+				pins[i], pinctrl_dev_get_name(pctldev));
+			goto err_pin_request;
+		}
+	}
+
+	/* Now that we have acquired the pins, encode the mux setting */
 	for (i = 0; i < num_pins; i++) {
 		desc = pin_desc_get(pctldev, pins[i]);
 		if (desc == NULL) {
@@ -457,8 +425,26 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting)
 		desc->mux_setting = &(setting->data.mux);
 	}
 
-	return ops->enable(pctldev, setting->data.mux.func,
-			   setting->data.mux.group);
+	ret = ops->enable(pctldev, setting->data.mux.func,
+			  setting->data.mux.group);
+
+	if (ret)
+		goto err_enable;
+
+	return 0;
+
+err_enable:
+	for (i = 0; i < num_pins; i++) {
+		desc = pin_desc_get(pctldev, pins[i]);
+		if (desc)
+			desc->mux_setting = NULL;
+	}
+err_pin_request:
+	/* On error release all taken pins */
+	while (--i >= 0)
+		pin_free(pctldev, pins[i], NULL);
+
+	return ret;
 }
 
 void pinmux_disable_setting(struct pinctrl_setting const *setting)
@@ -482,6 +468,7 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
 		num_pins = 0;
 	}
 
+	/* Flag the descs that no setting is active */
 	for (i = 0; i < num_pins; i++) {
 		desc = pin_desc_get(pctldev, pins[i]);
 		if (desc == NULL) {
@@ -493,6 +480,10 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
 		desc->mux_setting = NULL;
 	}
 
+	/* And release the pins */
+	for (i = 0; i < num_pins; i++)
+		pin_free(pctldev, pins[i], NULL);
+
 	if (ops->disable)
 		ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group);
 }
diff --git a/drivers/pinctrl/spear/Kconfig b/drivers/pinctrl/spear/Kconfig
index 91558791..04d93e6 100644
--- a/drivers/pinctrl/spear/Kconfig
+++ b/drivers/pinctrl/spear/Kconfig
@@ -25,20 +25,31 @@ config PINCTRL_SPEAR310
 	bool "ST Microelectronics SPEAr310 SoC pin controller driver"
 	depends on MACH_SPEAR310
 	select PINCTRL_SPEAR3XX
+	select PINCTRL_SPEAR_PLGPIO
 
 config PINCTRL_SPEAR320
 	bool "ST Microelectronics SPEAr320 SoC pin controller driver"
 	depends on MACH_SPEAR320
 	select PINCTRL_SPEAR3XX
+	select PINCTRL_SPEAR_PLGPIO
 
 config PINCTRL_SPEAR1310
 	bool "ST Microelectronics SPEAr1310 SoC pin controller driver"
 	depends on MACH_SPEAR1310
 	select PINCTRL_SPEAR
+	select PINCTRL_SPEAR_PLGPIO
 
 config PINCTRL_SPEAR1340
 	bool "ST Microelectronics SPEAr1340 SoC pin controller driver"
 	depends on MACH_SPEAR1340
 	select PINCTRL_SPEAR
+	select PINCTRL_SPEAR_PLGPIO
+
+config PINCTRL_SPEAR_PLGPIO
+	bool "SPEAr SoC PLGPIO Controller"
+	depends on GPIOLIB && PINCTRL_SPEAR
+	help
+	  Say yes here to support PLGPIO controller on ST Microelectronics SPEAr
+	  SoCs.
 
 endif
diff --git a/drivers/pinctrl/spear/Makefile b/drivers/pinctrl/spear/Makefile
index b28a7ba..0e400eb 100644
--- a/drivers/pinctrl/spear/Makefile
+++ b/drivers/pinctrl/spear/Makefile
@@ -1,5 +1,6 @@
 # SPEAr pinmux support
 
+obj-$(CONFIG_PINCTRL_SPEAR_PLGPIO)	+= pinctrl-plgpio.o
 obj-$(CONFIG_PINCTRL_SPEAR)	+= pinctrl-spear.o
 obj-$(CONFIG_PINCTRL_SPEAR3XX)	+= pinctrl-spear3xx.o
 obj-$(CONFIG_PINCTRL_SPEAR300)	+= pinctrl-spear300.o
diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c
new file mode 100644
index 0000000..5aebbf7
--- /dev/null
+++ b/drivers/pinctrl/spear/pinctrl-plgpio.c
@@ -0,0 +1,758 @@
+/*
+ * SPEAr platform PLGPIO driver
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/spinlock.h>
+#include <asm/mach/irq.h>
+
+#define MAX_GPIO_PER_REG		32
+#define PIN_OFFSET(pin)			(pin % MAX_GPIO_PER_REG)
+#define REG_OFFSET(base, reg, pin)	(base + reg + (pin / MAX_GPIO_PER_REG) \
+							* sizeof(int *))
+
+/*
+ * plgpio pins in all machines are not one to one mapped, bitwise with registers
+ * bits. These set of macros define register masks for which below functions
+ * (pin_to_offset and offset_to_pin) are required to be called.
+ */
+#define PTO_ENB_REG		0x001
+#define PTO_WDATA_REG		0x002
+#define PTO_DIR_REG		0x004
+#define PTO_IE_REG		0x008
+#define PTO_RDATA_REG		0x010
+#define PTO_MIS_REG		0x020
+
+struct plgpio_regs {
+	u32 enb;		/* enable register */
+	u32 wdata;		/* write data register */
+	u32 dir;		/* direction set register */
+	u32 rdata;		/* read data register */
+	u32 ie;			/* interrupt enable register */
+	u32 mis;		/* mask interrupt status register */
+	u32 eit;		/* edge interrupt type */
+};
+
+/*
+ * struct plgpio: plgpio driver specific structure
+ *
+ * lock: lock for guarding gpio registers
+ * base: base address of plgpio block
+ * irq_base: irq number of plgpio0
+ * chip: gpio framework specific chip information structure
+ * p2o: function ptr for pin to offset conversion. This is required only for
+ *	machines where mapping b/w pin and offset is not 1-to-1.
+ * o2p: function ptr for offset to pin conversion. This is required only for
+ *	machines where mapping b/w pin and offset is not 1-to-1.
+ * p2o_regs: mask of registers for which p2o and o2p are applicable
+ * regs: register offsets
+ * csave_regs: context save registers for standby/sleep/hibernate cases
+ */
+struct plgpio {
+	spinlock_t		lock;
+	void __iomem		*base;
+	struct clk		*clk;
+	unsigned		irq_base;
+	struct irq_domain	*irq_domain;
+	struct gpio_chip	chip;
+	int			(*p2o)(int pin);	/* pin_to_offset */
+	int			(*o2p)(int offset);	/* offset_to_pin */
+	u32			p2o_regs;
+	struct plgpio_regs	regs;
+#ifdef CONFIG_PM
+	struct plgpio_regs	*csave_regs;
+#endif
+};
+
+/* register manipulation inline functions */
+static inline u32 is_plgpio_set(void __iomem *base, u32 pin, u32 reg)
+{
+	u32 offset = PIN_OFFSET(pin);
+	void __iomem *reg_off = REG_OFFSET(base, reg, pin);
+	u32 val = readl_relaxed(reg_off);
+
+	return !!(val & (1 << offset));
+}
+
+static inline void plgpio_reg_set(void __iomem *base, u32 pin, u32 reg)
+{
+	u32 offset = PIN_OFFSET(pin);
+	void __iomem *reg_off = REG_OFFSET(base, reg, pin);
+	u32 val = readl_relaxed(reg_off);
+
+	writel_relaxed(val | (1 << offset), reg_off);
+}
+
+static inline void plgpio_reg_reset(void __iomem *base, u32 pin, u32 reg)
+{
+	u32 offset = PIN_OFFSET(pin);
+	void __iomem *reg_off = REG_OFFSET(base, reg, pin);
+	u32 val = readl_relaxed(reg_off);
+
+	writel_relaxed(val & ~(1 << offset), reg_off);
+}
+
+/* gpio framework specific routines */
+static int plgpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+	unsigned long flags;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_DIR_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return -EINVAL;
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	plgpio_reg_set(plgpio->base, offset, plgpio->regs.dir);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+
+	return 0;
+}
+
+static int plgpio_direction_output(struct gpio_chip *chip, unsigned offset,
+		int value)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+	unsigned long flags;
+	unsigned dir_offset = offset, wdata_offset = offset, tmp;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & (PTO_DIR_REG | PTO_WDATA_REG))) {
+		tmp = plgpio->p2o(offset);
+		if (tmp == -1)
+			return -EINVAL;
+
+		if (plgpio->p2o_regs & PTO_DIR_REG)
+			dir_offset = tmp;
+		if (plgpio->p2o_regs & PTO_WDATA_REG)
+			wdata_offset = tmp;
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	if (value)
+		plgpio_reg_set(plgpio->base, wdata_offset,
+				plgpio->regs.wdata);
+	else
+		plgpio_reg_reset(plgpio->base, wdata_offset,
+				plgpio->regs.wdata);
+
+	plgpio_reg_reset(plgpio->base, dir_offset, plgpio->regs.dir);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+
+	return 0;
+}
+
+static int plgpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+
+	if (offset >= chip->ngpio)
+		return -EINVAL;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_RDATA_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return -EINVAL;
+	}
+
+	return is_plgpio_set(plgpio->base, offset, plgpio->regs.rdata);
+}
+
+static void plgpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+
+	if (offset >= chip->ngpio)
+		return;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_WDATA_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return;
+	}
+
+	if (value)
+		plgpio_reg_set(plgpio->base, offset, plgpio->regs.wdata);
+	else
+		plgpio_reg_reset(plgpio->base, offset, plgpio->regs.wdata);
+}
+
+static int plgpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+	int gpio = chip->base + offset;
+	unsigned long flags;
+	int ret = 0;
+
+	if (offset >= chip->ngpio)
+		return -EINVAL;
+
+	ret = pinctrl_request_gpio(gpio);
+	if (ret)
+		return ret;
+
+	if (!IS_ERR(plgpio->clk)) {
+		ret = clk_enable(plgpio->clk);
+		if (ret)
+			goto err0;
+	}
+
+	if (plgpio->regs.enb == -1)
+		return 0;
+
+	/*
+	 * put gpio in IN mode before enabling it. This make enabling gpio safe
+	 */
+	ret = plgpio_direction_input(chip, offset);
+	if (ret)
+		goto err1;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1) {
+			ret = -EINVAL;
+			goto err1;
+		}
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	plgpio_reg_set(plgpio->base, offset, plgpio->regs.enb);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+	return 0;
+
+err1:
+	if (!IS_ERR(plgpio->clk))
+		clk_disable(plgpio->clk);
+err0:
+	pinctrl_free_gpio(gpio);
+	return ret;
+}
+
+static void plgpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+	int gpio = chip->base + offset;
+	unsigned long flags;
+
+	if (offset >= chip->ngpio)
+		return;
+
+	if (plgpio->regs.enb == -1)
+		goto disable_clk;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return;
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	plgpio_reg_reset(plgpio->base, offset, plgpio->regs.enb);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+
+disable_clk:
+	if (!IS_ERR(plgpio->clk))
+		clk_disable(plgpio->clk);
+
+	pinctrl_free_gpio(gpio);
+}
+
+static int plgpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+
+	if (plgpio->irq_base < 0)
+		return -EINVAL;
+
+	return irq_find_mapping(plgpio->irq_domain, offset);
+}
+
+/* PLGPIO IRQ */
+static void plgpio_irq_disable(struct irq_data *d)
+{
+	struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - plgpio->irq_base;
+	unsigned long flags;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return;
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	plgpio_reg_set(plgpio->base, offset, plgpio->regs.ie);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+}
+
+static void plgpio_irq_enable(struct irq_data *d)
+{
+	struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - plgpio->irq_base;
+	unsigned long flags;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return;
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	plgpio_reg_reset(plgpio->base, offset, plgpio->regs.ie);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+}
+
+static int plgpio_irq_set_type(struct irq_data *d, unsigned trigger)
+{
+	struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - plgpio->irq_base;
+	void __iomem *reg_off;
+	unsigned int supported_type = 0, val;
+
+	if (offset >= plgpio->chip.ngpio)
+		return -EINVAL;
+
+	if (plgpio->regs.eit == -1)
+		supported_type = IRQ_TYPE_LEVEL_HIGH;
+	else
+		supported_type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+
+	if (!(trigger & supported_type))
+		return -EINVAL;
+
+	if (plgpio->regs.eit == -1)
+		return 0;
+
+	reg_off = REG_OFFSET(plgpio->base, plgpio->regs.eit, offset);
+	val = readl_relaxed(reg_off);
+
+	offset = PIN_OFFSET(offset);
+	if (trigger & IRQ_TYPE_EDGE_RISING)
+		writel_relaxed(val | (1 << offset), reg_off);
+	else
+		writel_relaxed(val & ~(1 << offset), reg_off);
+
+	return 0;
+}
+
+static struct irq_chip plgpio_irqchip = {
+	.name		= "PLGPIO",
+	.irq_enable	= plgpio_irq_enable,
+	.irq_disable	= plgpio_irq_disable,
+	.irq_set_type	= plgpio_irq_set_type,
+};
+
+static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+	struct plgpio *plgpio = irq_get_handler_data(irq);
+	struct irq_chip *irqchip = irq_desc_get_chip(desc);
+	int regs_count, count, pin, offset, i = 0;
+	unsigned long pending;
+
+	count = plgpio->chip.ngpio;
+	regs_count = DIV_ROUND_UP(count, MAX_GPIO_PER_REG);
+
+	chained_irq_enter(irqchip, desc);
+	/* check all plgpio MIS registers for a possible interrupt */
+	for (; i < regs_count; i++) {
+		pending = readl_relaxed(plgpio->base + plgpio->regs.mis +
+				i * sizeof(int *));
+		if (!pending)
+			continue;
+
+		/* clear interrupts */
+		writel_relaxed(~pending, plgpio->base + plgpio->regs.mis +
+				i * sizeof(int *));
+		/*
+		 * clear extra bits in last register having gpios < MAX/REG
+		 * ex: Suppose there are max 102 plgpios. then last register
+		 * must have only (102 - MAX_GPIO_PER_REG * 3) = 6 relevant bits
+		 * so, we must not take other 28 bits into consideration for
+		 * checking interrupt. so clear those bits.
+		 */
+		count = count - i * MAX_GPIO_PER_REG;
+		if (count < MAX_GPIO_PER_REG)
+			pending &= (1 << count) - 1;
+
+		for_each_set_bit(offset, &pending, MAX_GPIO_PER_REG) {
+			/* get correct pin for "offset" */
+			if (plgpio->o2p && (plgpio->p2o_regs & PTO_MIS_REG)) {
+				pin = plgpio->o2p(offset);
+				if (pin == -1)
+					continue;
+			} else
+				pin = offset;
+
+			/* get correct irq line number */
+			pin = i * MAX_GPIO_PER_REG + pin;
+			generic_handle_irq(plgpio_to_irq(&plgpio->chip, pin));
+		}
+	}
+	chained_irq_exit(irqchip, desc);
+}
+
+/*
+ * pin to offset and offset to pin converter functions
+ *
+ * In spear310 there is inconsistency among bit positions in plgpio regiseters,
+ * for different plgpio pins. For example: for pin 27, bit offset is 23, pin
+ * 28-33 are not supported, pin 95 has offset bit 95, bit 100 has offset bit 1
+ */
+static int spear310_p2o(int pin)
+{
+	int offset = pin;
+
+	if (pin <= 27)
+		offset += 4;
+	else if (pin <= 33)
+		offset = -1;
+	else if (pin <= 97)
+		offset -= 2;
+	else if (pin <= 101)
+		offset = 101 - pin;
+	else
+		offset = -1;
+
+	return offset;
+}
+
+int spear310_o2p(int offset)
+{
+	if (offset <= 3)
+		return 101 - offset;
+	else if (offset <= 31)
+		return offset - 4;
+	else
+		return offset + 2;
+}
+
+static int __devinit plgpio_probe_dt(struct platform_device *pdev,
+		struct plgpio *plgpio)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int ret = -EINVAL;
+	u32 val;
+
+	if (of_machine_is_compatible("st,spear310")) {
+		plgpio->p2o = spear310_p2o;
+		plgpio->o2p = spear310_o2p;
+		plgpio->p2o_regs = PTO_WDATA_REG | PTO_DIR_REG | PTO_IE_REG |
+			PTO_RDATA_REG | PTO_MIS_REG;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,ngpio", &val)) {
+		plgpio->chip.ngpio = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid ngpio field\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,enb-reg", &val))
+		plgpio->regs.enb = val;
+	else
+		plgpio->regs.enb = -1;
+
+	if (!of_property_read_u32(np, "st-plgpio,wdata-reg", &val)) {
+		plgpio->regs.wdata = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid wdata reg\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,dir-reg", &val)) {
+		plgpio->regs.dir = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid dir reg\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,ie-reg", &val)) {
+		plgpio->regs.ie = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid ie reg\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,rdata-reg", &val)) {
+		plgpio->regs.rdata = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid rdata reg\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,mis-reg", &val)) {
+		plgpio->regs.mis = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid mis reg\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,eit-reg", &val))
+		plgpio->regs.eit = val;
+	else
+		plgpio->regs.eit = -1;
+
+	return 0;
+
+end:
+	return ret;
+}
+static int __devinit plgpio_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct plgpio *plgpio;
+	struct resource *res;
+	int ret, irq, i;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n");
+		return -EBUSY;
+	}
+
+	plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL);
+	if (!plgpio) {
+		dev_err(&pdev->dev, "memory allocation fail\n");
+		return -ENOMEM;
+	}
+
+	plgpio->base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!plgpio->base) {
+		dev_err(&pdev->dev, "request and ioremap fail\n");
+		return -ENOMEM;
+	}
+
+	ret = plgpio_probe_dt(pdev, plgpio);
+	if (ret) {
+		dev_err(&pdev->dev, "DT probe failed\n");
+		return ret;
+	}
+
+	plgpio->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(plgpio->clk))
+		dev_warn(&pdev->dev, "clk_get() failed, work without it\n");
+
+#ifdef CONFIG_PM
+	plgpio->csave_regs = devm_kzalloc(&pdev->dev,
+			sizeof(*plgpio->csave_regs) *
+			DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG),
+			GFP_KERNEL);
+	if (!plgpio->csave_regs) {
+		dev_err(&pdev->dev, "csave registers memory allocation fail\n");
+		return -ENOMEM;
+	}
+#endif
+
+	platform_set_drvdata(pdev, plgpio);
+	spin_lock_init(&plgpio->lock);
+
+	plgpio->irq_base = -1;
+	plgpio->chip.base = -1;
+	plgpio->chip.request = plgpio_request;
+	plgpio->chip.free = plgpio_free;
+	plgpio->chip.direction_input = plgpio_direction_input;
+	plgpio->chip.direction_output = plgpio_direction_output;
+	plgpio->chip.get = plgpio_get_value;
+	plgpio->chip.set = plgpio_set_value;
+	plgpio->chip.to_irq = plgpio_to_irq;
+	plgpio->chip.label = dev_name(&pdev->dev);
+	plgpio->chip.dev = &pdev->dev;
+	plgpio->chip.owner = THIS_MODULE;
+
+	if (!IS_ERR(plgpio->clk)) {
+		ret = clk_prepare(plgpio->clk);
+		if (ret) {
+			dev_err(&pdev->dev, "clk prepare failed\n");
+			return ret;
+		}
+	}
+
+	ret = gpiochip_add(&plgpio->chip);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to add gpio chip\n");
+		goto unprepare_clk;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_info(&pdev->dev, "irqs not supported\n");
+		return 0;
+	}
+
+	plgpio->irq_base = irq_alloc_descs(-1, 0, plgpio->chip.ngpio, 0);
+	if (IS_ERR_VALUE(plgpio->irq_base)) {
+		/* we would not support irq for gpio */
+		dev_warn(&pdev->dev, "couldn't allocate irq base\n");
+		return 0;
+	}
+
+	plgpio->irq_domain = irq_domain_add_legacy(np, plgpio->chip.ngpio,
+			plgpio->irq_base, 0, &irq_domain_simple_ops, NULL);
+	if (WARN_ON(!plgpio->irq_domain)) {
+		dev_err(&pdev->dev, "irq domain init failed\n");
+		irq_free_descs(plgpio->irq_base, plgpio->chip.ngpio);
+		ret = -ENXIO;
+		goto remove_gpiochip;
+	}
+
+	irq_set_chained_handler(irq, plgpio_irq_handler);
+	for (i = 0; i < plgpio->chip.ngpio; i++) {
+		irq_set_chip_and_handler(i + plgpio->irq_base, &plgpio_irqchip,
+				handle_simple_irq);
+		set_irq_flags(i + plgpio->irq_base, IRQF_VALID);
+		irq_set_chip_data(i + plgpio->irq_base, plgpio);
+	}
+
+	irq_set_handler_data(irq, plgpio);
+	dev_info(&pdev->dev, "PLGPIO registered with IRQs\n");
+
+	return 0;
+
+remove_gpiochip:
+	dev_info(&pdev->dev, "Remove gpiochip\n");
+	if (gpiochip_remove(&plgpio->chip))
+		dev_err(&pdev->dev, "unable to remove gpiochip\n");
+unprepare_clk:
+	if (!IS_ERR(plgpio->clk))
+		clk_unprepare(plgpio->clk);
+
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int plgpio_suspend(struct device *dev)
+{
+	struct plgpio *plgpio = dev_get_drvdata(dev);
+	int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);
+	void __iomem *off;
+
+	for (i = 0; i < reg_count; i++) {
+		off = plgpio->base + i * sizeof(int *);
+
+		if (plgpio->regs.enb != -1)
+			plgpio->csave_regs[i].enb =
+				readl_relaxed(plgpio->regs.enb + off);
+		if (plgpio->regs.eit != -1)
+			plgpio->csave_regs[i].eit =
+				readl_relaxed(plgpio->regs.eit + off);
+		plgpio->csave_regs[i].wdata = readl_relaxed(plgpio->regs.wdata +
+				off);
+		plgpio->csave_regs[i].dir = readl_relaxed(plgpio->regs.dir +
+				off);
+		plgpio->csave_regs[i].ie = readl_relaxed(plgpio->regs.ie + off);
+	}
+
+	return 0;
+}
+
+/*
+ * This is used to correct the values in end registers. End registers contain
+ * extra bits that might be used for other purpose in platform. So, we shouldn't
+ * overwrite these bits. This macro, reads given register again, preserves other
+ * bit values (non-plgpio bits), and retain captured value (plgpio bits).
+ */
+#define plgpio_prepare_reg(__reg, _off, _mask, _tmp)		\
+{								\
+	_tmp = readl_relaxed(plgpio->regs.__reg + _off);		\
+	_tmp &= ~_mask;						\
+	plgpio->csave_regs[i].__reg =				\
+		_tmp | (plgpio->csave_regs[i].__reg & _mask);	\
+}
+
+static int plgpio_resume(struct device *dev)
+{
+	struct plgpio *plgpio = dev_get_drvdata(dev);
+	int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);
+	void __iomem *off;
+	u32 mask, tmp;
+
+	for (i = 0; i < reg_count; i++) {
+		off = plgpio->base + i * sizeof(int *);
+
+		if (i == reg_count - 1) {
+			mask = (1 << (plgpio->chip.ngpio - i *
+						MAX_GPIO_PER_REG)) - 1;
+
+			if (plgpio->regs.enb != -1)
+				plgpio_prepare_reg(enb, off, mask, tmp);
+
+			if (plgpio->regs.eit != -1)
+				plgpio_prepare_reg(eit, off, mask, tmp);
+
+			plgpio_prepare_reg(wdata, off, mask, tmp);
+			plgpio_prepare_reg(dir, off, mask, tmp);
+			plgpio_prepare_reg(ie, off, mask, tmp);
+		}
+
+		writel_relaxed(plgpio->csave_regs[i].wdata, plgpio->regs.wdata +
+				off);
+		writel_relaxed(plgpio->csave_regs[i].dir, plgpio->regs.dir +
+				off);
+
+		if (plgpio->regs.eit != -1)
+			writel_relaxed(plgpio->csave_regs[i].eit,
+					plgpio->regs.eit + off);
+
+		writel_relaxed(plgpio->csave_regs[i].ie, plgpio->regs.ie + off);
+
+		if (plgpio->regs.enb != -1)
+			writel_relaxed(plgpio->csave_regs[i].enb,
+					plgpio->regs.enb + off);
+	}
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(plgpio_dev_pm_ops, plgpio_suspend, plgpio_resume);
+
+static const struct of_device_id plgpio_of_match[] = {
+	{ .compatible = "st,spear-plgpio" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, plgpio_of_match);
+
+static struct platform_driver plgpio_driver = {
+	.probe = plgpio_probe,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "spear-plgpio",
+		.pm = &plgpio_dev_pm_ops,
+		.of_match_table = of_match_ptr(plgpio_of_match),
+	},
+};
+
+static int __init plgpio_init(void)
+{
+	return platform_driver_register(&plgpio_driver);
+}
+subsys_initcall(plgpio_init);
+
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
+MODULE_DESCRIPTION("ST Microlectronics SPEAr PLGPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
index b1fd6ee..922c057 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.c
+++ b/drivers/pinctrl/spear/pinctrl-spear.c
@@ -14,10 +14,10 @@
  */
 
 #include <linux/err.h>
-#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_gpio.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
@@ -28,14 +28,26 @@
 
 #define DRIVER_NAME "spear-pinmux"
 
-static inline u32 pmx_readl(struct spear_pmx *pmx, u32 reg)
+static void muxregs_endisable(struct spear_pmx *pmx,
+		struct spear_muxreg *muxregs, u8 count, bool enable)
 {
-	return readl_relaxed(pmx->vbase + reg);
-}
+	struct spear_muxreg *muxreg;
+	u32 val, temp, j;
 
-static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg)
-{
-	writel_relaxed(val, pmx->vbase + reg);
+	for (j = 0; j < count; j++) {
+		muxreg = &muxregs[j];
+
+		val = pmx_readl(pmx, muxreg->reg);
+		val &= ~muxreg->mask;
+
+		if (enable)
+			temp = muxreg->val;
+		else
+			temp = ~muxreg->val;
+
+		val |= muxreg->mask & temp;
+		pmx_writel(pmx, val, muxreg->reg);
+	}
 }
 
 static int set_mode(struct spear_pmx *pmx, int mode)
@@ -70,6 +82,17 @@ static int set_mode(struct spear_pmx *pmx, int mode)
 	return 0;
 }
 
+void __devinit
+pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
+		unsigned count, u16 reg)
+{
+	int i, j;
+
+	for (i = 0; i < count; i++)
+		for (j = 0; j < gpio_pingroup[i].nmuxregs; j++)
+			gpio_pingroup[i].muxregs[j].reg = reg;
+}
+
 void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg)
 {
 	struct spear_pingroup *pgroup;
@@ -121,9 +144,10 @@ static void spear_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
 	seq_printf(s, " " DRIVER_NAME);
 }
 
-int spear_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
-				 struct device_node *np_config,
-				 struct pinctrl_map **map, unsigned *num_maps)
+static int spear_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+					struct device_node *np_config,
+					struct pinctrl_map **map,
+					unsigned *num_maps)
 {
 	struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
 	struct device_node *np;
@@ -168,8 +192,9 @@ int spear_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
 	return 0;
 }
 
-void spear_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
-		struct pinctrl_map *map, unsigned num_maps)
+static void spear_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+				      struct pinctrl_map *map,
+				      unsigned num_maps)
 {
 	kfree(map);
 }
@@ -216,9 +241,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
 	struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
 	const struct spear_pingroup *pgroup;
 	const struct spear_modemux *modemux;
-	struct spear_muxreg *muxreg;
-	u32 val, temp;
-	int i, j;
+	int i;
 	bool found = false;
 
 	pgroup = pmx->machdata->groups[group];
@@ -233,20 +256,8 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
 		}
 
 		found = true;
-		for (j = 0; j < modemux->nmuxregs; j++) {
-			muxreg = &modemux->muxregs[j];
-
-			val = pmx_readl(pmx, muxreg->reg);
-			val &= ~muxreg->mask;
-
-			if (enable)
-				temp = muxreg->val;
-			else
-				temp = ~muxreg->val;
-
-			val |= muxreg->mask & temp;
-			pmx_writel(pmx, val, muxreg->reg);
-		}
+		muxregs_endisable(pmx, modemux->muxregs, modemux->nmuxregs,
+				enable);
 	}
 
 	if (!found) {
@@ -270,12 +281,74 @@ static void spear_pinctrl_disable(struct pinctrl_dev *pctldev,
 	spear_pinctrl_endisable(pctldev, function, group, false);
 }
 
+/* gpio with pinmux */
+static struct spear_gpio_pingroup *get_gpio_pingroup(struct spear_pmx *pmx,
+		unsigned pin)
+{
+	struct spear_gpio_pingroup *gpio_pingroup;
+	int i, j;
+
+	if (!pmx->machdata->gpio_pingroups)
+		return NULL;
+
+	for (i = 0; i < pmx->machdata->ngpio_pingroups; i++) {
+		gpio_pingroup = &pmx->machdata->gpio_pingroups[i];
+
+		for (j = 0; j < gpio_pingroup->npins; j++) {
+			if (gpio_pingroup->pins[j] == pin)
+				return gpio_pingroup;
+		}
+	}
+
+	return NULL;
+}
+
+static int gpio_request_endisable(struct pinctrl_dev *pctldev,
+		struct pinctrl_gpio_range *range, unsigned offset, bool enable)
+{
+	struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+	struct spear_pinctrl_machdata *machdata = pmx->machdata;
+	struct spear_gpio_pingroup *gpio_pingroup;
+
+	/*
+	 * Some SoC have configuration options applicable to group of pins,
+	 * rather than a single pin.
+	 */
+	gpio_pingroup = get_gpio_pingroup(pmx, offset);
+	if (gpio_pingroup)
+		muxregs_endisable(pmx, gpio_pingroup->muxregs,
+				gpio_pingroup->nmuxregs, enable);
+
+	/*
+	 * SoC may need some extra configurations, or configurations for single
+	 * pin
+	 */
+	if (machdata->gpio_request_endisable)
+		machdata->gpio_request_endisable(pmx, offset, enable);
+
+	return 0;
+}
+
+static int gpio_request_enable(struct pinctrl_dev *pctldev,
+		struct pinctrl_gpio_range *range, unsigned offset)
+{
+	return gpio_request_endisable(pctldev, range, offset, true);
+}
+
+static void gpio_disable_free(struct pinctrl_dev *pctldev,
+		struct pinctrl_gpio_range *range, unsigned offset)
+{
+	gpio_request_endisable(pctldev, range, offset, false);
+}
+
 static struct pinmux_ops spear_pinmux_ops = {
 	.get_functions_count = spear_pinctrl_get_funcs_count,
 	.get_function_name = spear_pinctrl_get_func_name,
 	.get_function_groups = spear_pinctrl_get_func_groups,
 	.enable = spear_pinctrl_enable,
 	.disable = spear_pinctrl_disable,
+	.gpio_request_enable = gpio_request_enable,
+	.gpio_disable_free = gpio_disable_free,
 };
 
 static struct pinctrl_desc spear_pinctrl_desc = {
@@ -344,7 +417,7 @@ int __devinit spear_pinctrl_probe(struct platform_device *pdev,
 	return 0;
 }
 
-int __devexit spear_pinctrl_remove(struct platform_device *pdev)
+int spear_pinctrl_remove(struct platform_device *pdev)
 {
 	struct spear_pmx *pmx = platform_get_drvdata(pdev);
 
diff --git a/drivers/pinctrl/spear/pinctrl-spear.h b/drivers/pinctrl/spear/pinctrl-spear.h
index d950eb7..1be46ec 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.h
+++ b/drivers/pinctrl/spear/pinctrl-spear.h
@@ -12,11 +12,14 @@
 #ifndef __PINMUX_SPEAR_H__
 #define __PINMUX_SPEAR_H__
 
+#include <linux/gpio.h>
+#include <linux/io.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/types.h>
 
 struct platform_device;
 struct device;
+struct spear_pmx;
 
 /**
  * struct spear_pmx_mode - SPEAr pmx mode
@@ -46,6 +49,44 @@ struct spear_muxreg {
 	u32 val;
 };
 
+struct spear_gpio_pingroup {
+	const unsigned *pins;
+	unsigned npins;
+	struct spear_muxreg *muxregs;
+	u8 nmuxregs;
+};
+
+/* ste: set to enable */
+#define DEFINE_MUXREG(__pins, __muxreg, __mask, __ste)		\
+static struct spear_muxreg __pins##_muxregs[] = {		\
+	{							\
+		.reg = __muxreg,				\
+		.mask = __mask,					\
+		.val = __ste ? __mask : 0,			\
+	},							\
+}
+
+#define DEFINE_2_MUXREG(__pins, __muxreg1, __muxreg2, __mask, __ste1, __ste2) \
+static struct spear_muxreg __pins##_muxregs[] = {		\
+	{							\
+		.reg = __muxreg1,				\
+		.mask = __mask,					\
+		.val = __ste1 ? __mask : 0,			\
+	}, {							\
+		.reg = __muxreg2,				\
+		.mask = __mask,					\
+		.val = __ste2 ? __mask : 0,			\
+	},							\
+}
+
+#define GPIO_PINGROUP(__pins)					\
+	{							\
+		.pins = __pins,					\
+		.npins = ARRAY_SIZE(__pins),			\
+		.muxregs = __pins##_muxregs,			\
+		.nmuxregs = ARRAY_SIZE(__pins##_muxregs),	\
+	}
+
 /**
  * struct spear_modemux - SPEAr mode mux configuration
  * @modes: mode ids supported by this group of muxregs
@@ -100,6 +141,8 @@ struct spear_function {
  * @nfunctions: The numbmer of entries in @functions.
  * @groups: An array describing all pin groups the pin SoC supports.
  * @ngroups: The numbmer of entries in @groups.
+ * @gpio_pingroups: gpio pingroups
+ * @ngpio_pingroups: gpio pingroups count
  *
  * @modes_supported: Does SoC support modes
  * @mode: mode configured from probe
@@ -113,6 +156,10 @@ struct spear_pinctrl_machdata {
 	unsigned nfunctions;
 	struct spear_pingroup **groups;
 	unsigned ngroups;
+	struct spear_gpio_pingroup *gpio_pingroups;
+	void (*gpio_request_endisable)(struct spear_pmx *pmx, int offset,
+			bool enable);
+	unsigned ngpio_pingroups;
 
 	bool modes_supported;
 	u16 mode;
@@ -135,10 +182,23 @@ struct spear_pmx {
 };
 
 /* exported routines */
+static inline u32 pmx_readl(struct spear_pmx *pmx, u32 reg)
+{
+	return readl_relaxed(pmx->vbase + reg);
+}
+
+static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg)
+{
+	writel_relaxed(val, pmx->vbase + reg);
+}
+
 void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg);
+void __devinit
+pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
+		unsigned count, u16 reg);
 int __devinit spear_pinctrl_probe(struct platform_device *pdev,
 		struct spear_pinctrl_machdata *machdata);
-int __devexit spear_pinctrl_remove(struct platform_device *pdev);
+int spear_pinctrl_remove(struct platform_device *pdev);
 
 #define SPEAR_PIN_0_TO_101		\
 	PINCTRL_PIN(0, "PLGPIO0"),	\
diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c
index 0436fc7..e40d785 100644
--- a/drivers/pinctrl/spear/pinctrl-spear1310.c
+++ b/drivers/pinctrl/spear/pinctrl-spear1310.c
@@ -2418,6 +2418,268 @@ static struct spear_function *spear1310_functions[] = {
 	&gpt64_function,
 };
 
+static const unsigned pin18[] = { 18, };
+static const unsigned pin19[] = { 19, };
+static const unsigned pin20[] = { 20, };
+static const unsigned pin21[] = { 21, };
+static const unsigned pin22[] = { 22, };
+static const unsigned pin23[] = { 23, };
+static const unsigned pin54[] = { 54, };
+static const unsigned pin55[] = { 55, };
+static const unsigned pin56[] = { 56, };
+static const unsigned pin57[] = { 57, };
+static const unsigned pin58[] = { 58, };
+static const unsigned pin59[] = { 59, };
+static const unsigned pin60[] = { 60, };
+static const unsigned pin61[] = { 61, };
+static const unsigned pin62[] = { 62, };
+static const unsigned pin63[] = { 63, };
+static const unsigned pin143[] = { 143, };
+static const unsigned pin144[] = { 144, };
+static const unsigned pin145[] = { 145, };
+static const unsigned pin146[] = { 146, };
+static const unsigned pin147[] = { 147, };
+static const unsigned pin148[] = { 148, };
+static const unsigned pin149[] = { 149, };
+static const unsigned pin150[] = { 150, };
+static const unsigned pin151[] = { 151, };
+static const unsigned pin152[] = { 152, };
+static const unsigned pin205[] = { 205, };
+static const unsigned pin206[] = { 206, };
+static const unsigned pin211[] = { 211, };
+static const unsigned pin212[] = { 212, };
+static const unsigned pin213[] = { 213, };
+static const unsigned pin214[] = { 214, };
+static const unsigned pin215[] = { 215, };
+static const unsigned pin216[] = { 216, };
+static const unsigned pin217[] = { 217, };
+static const unsigned pin218[] = { 218, };
+static const unsigned pin219[] = { 219, };
+static const unsigned pin220[] = { 220, };
+static const unsigned pin221[] = { 221, };
+static const unsigned pin222[] = { 222, };
+static const unsigned pin223[] = { 223, };
+static const unsigned pin224[] = { 224, };
+static const unsigned pin225[] = { 225, };
+static const unsigned pin226[] = { 226, };
+static const unsigned pin227[] = { 227, };
+static const unsigned pin228[] = { 228, };
+static const unsigned pin229[] = { 229, };
+static const unsigned pin230[] = { 230, };
+static const unsigned pin231[] = { 231, };
+static const unsigned pin232[] = { 232, };
+static const unsigned pin233[] = { 233, };
+static const unsigned pin234[] = { 234, };
+static const unsigned pin235[] = { 235, };
+static const unsigned pin236[] = { 236, };
+static const unsigned pin237[] = { 237, };
+static const unsigned pin238[] = { 238, };
+static const unsigned pin239[] = { 239, };
+static const unsigned pin240[] = { 240, };
+static const unsigned pin241[] = { 241, };
+static const unsigned pin242[] = { 242, };
+static const unsigned pin243[] = { 243, };
+static const unsigned pin244[] = { 244, };
+static const unsigned pin245[] = { 245, };
+
+static const unsigned pin_grp0[] = { 173, 174, };
+static const unsigned pin_grp1[] = { 175, 185, 188, 197, 198, };
+static const unsigned pin_grp2[] = { 176, 177, 178, 179, 184, 186, 187, 189,
+	190, 191, 192, };
+static const unsigned pin_grp3[] = { 180, 181, 182, 183, 193, 194, 195, 196, };
+static const unsigned pin_grp4[] = { 199, 200, };
+static const unsigned pin_grp5[] = { 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+	75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, };
+static const unsigned pin_grp6[] = { 86, 87, 88, 89, 90, 91, 92, 93, };
+static const unsigned pin_grp7[] = { 98, 99, };
+static const unsigned pin_grp8[] = { 158, 159, 160, 161, 162, 163, 164, 165,
+	166, 167, 168, 169, 170, 171, 172, };
+
+/* Define muxreg arrays */
+DEFINE_2_MUXREG(i2c0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_I2C0_MASK, 0, 1);
+DEFINE_2_MUXREG(ssp0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_SSP0_MASK, 0, 1);
+DEFINE_2_MUXREG(ssp0_cs0_pins, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_SSP0_CS0_MASK, 0, 1);
+DEFINE_2_MUXREG(ssp0_cs1_2_pins, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_SSP0_CS1_2_MASK, 0, 1);
+DEFINE_2_MUXREG(i2s0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_I2S0_MASK, 0, 1);
+DEFINE_2_MUXREG(i2s1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_I2S1_MASK, 0, 1);
+DEFINE_2_MUXREG(clcd_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_CLCD1_MASK, 0, 1);
+DEFINE_2_MUXREG(clcd_high_res_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_CLCD2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin18, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO15_MASK, 0, 1);
+DEFINE_2_MUXREG(pin19, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO14_MASK, 0, 1);
+DEFINE_2_MUXREG(pin20, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO13_MASK, 0, 1);
+DEFINE_2_MUXREG(pin21, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO12_MASK, 0, 1);
+DEFINE_2_MUXREG(pin22, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO11_MASK, 0, 1);
+DEFINE_2_MUXREG(pin23, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO10_MASK, 0, 1);
+DEFINE_2_MUXREG(pin143, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO00_MASK, 0, 1);
+DEFINE_2_MUXREG(pin144, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO01_MASK, 0, 1);
+DEFINE_2_MUXREG(pin145, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO02_MASK, 0, 1);
+DEFINE_2_MUXREG(pin146, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO03_MASK, 0, 1);
+DEFINE_2_MUXREG(pin147, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO04_MASK, 0, 1);
+DEFINE_2_MUXREG(pin148, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO05_MASK, 0, 1);
+DEFINE_2_MUXREG(pin149, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO06_MASK, 0, 1);
+DEFINE_2_MUXREG(pin150, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO07_MASK, 0, 1);
+DEFINE_2_MUXREG(pin151, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO08_MASK, 0, 1);
+DEFINE_2_MUXREG(pin152, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO09_MASK, 0, 1);
+DEFINE_2_MUXREG(smi_2_chips_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_SMI_MASK, 0, 1);
+DEFINE_2_MUXREG(pin54, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_SMINCS3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin55, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_SMINCS2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin56, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NFRSTPWDWN3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin57, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin58, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin59, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN0_MASK, 0, 1);
+DEFINE_2_MUXREG(pin60, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFWPRT3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin61, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFCE3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin62, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD25_MASK, 0, 1);
+DEFINE_2_MUXREG(pin63, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD24_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp0, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIICLK_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp1, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp2, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_RXCLK_RDV_TXEN_D03_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp3, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIID47_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp4, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_MDC_MDIO_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp5, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD23_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp6, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_MCI_DATA8_15_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp7, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NFCE2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp8, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NAND8_MASK, 0, 1);
+DEFINE_2_MUXREG(nand_16bit_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NAND16BIT_1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin205, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_COL1_MASK | PMX_NFCE1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin206, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_COL0_MASK | PMX_NFCE2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin211, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROW1_MASK | PMX_NFWPRT1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin212, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROW0_MASK | PMX_NFWPRT2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin213, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA0_MASK, 0, 1);
+DEFINE_2_MUXREG(pin214, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin215, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin216, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin217, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA4_MASK, 0, 1);
+DEFINE_2_MUXREG(pin218, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA5_MASK, 0, 1);
+DEFINE_2_MUXREG(pin219, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA6_MASK, 0, 1);
+DEFINE_2_MUXREG(pin220, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA7_MASK, 0, 1);
+DEFINE_2_MUXREG(pin221, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA1SD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin222, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA2SD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin223, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA3SD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin224, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR0ALE_MASK, 0, 1);
+DEFINE_2_MUXREG(pin225, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR1CLECLK_MASK, 0, 1);
+DEFINE_2_MUXREG(pin226, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin227, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICECF_MASK, 0, 1);
+DEFINE_2_MUXREG(pin228, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICEXD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin229, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICESDMMC_MASK, 0, 1);
+DEFINE_2_MUXREG(pin230, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDCF1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin231, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDCF2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin232, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDXD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin233, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDSDMMC_MASK, 0, 1);
+DEFINE_2_MUXREG(pin234, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATADIR_MASK, 0, 1);
+DEFINE_2_MUXREG(pin235, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDMARQWP_MASK, 0, 1);
+DEFINE_2_MUXREG(pin236, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIORDRE_MASK, 0, 1);
+DEFINE_2_MUXREG(pin237, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIOWRWE_MASK, 0, 1);
+DEFINE_2_MUXREG(pin238, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIRESETCF_MASK, 0, 1);
+DEFINE_2_MUXREG(pin239, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICS0CE_MASK, 0, 1);
+DEFINE_2_MUXREG(pin240, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICFINTR_MASK, 0, 1);
+DEFINE_2_MUXREG(pin241, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIORDY_MASK, 0, 1);
+DEFINE_2_MUXREG(pin242, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICS1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin243, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDMAACK_MASK, 0, 1);
+DEFINE_2_MUXREG(pin244, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCISDCMD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin245, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCILEDS_MASK, 0, 1);
+DEFINE_2_MUXREG(keyboard_rowcol6_8_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROWCOL68_MASK, 0, 1);
+DEFINE_2_MUXREG(uart0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_UART0_MASK, 0, 1);
+DEFINE_2_MUXREG(uart0_modem_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_UART0_MODEM_MASK, 0, 1);
+DEFINE_2_MUXREG(gpt0_tmr0_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT0_TMR0_MASK, 0, 1);
+DEFINE_2_MUXREG(gpt0_tmr1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT0_TMR1_MASK, 0, 1);
+DEFINE_2_MUXREG(gpt1_tmr0_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT1_TMR0_MASK, 0, 1);
+DEFINE_2_MUXREG(gpt1_tmr1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT1_TMR1_MASK, 0, 1);
+DEFINE_2_MUXREG(touch_xy_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_TOUCH_XY_MASK, 0, 1);
+
+static struct spear_gpio_pingroup spear1310_gpio_pingroup[] = {
+	GPIO_PINGROUP(i2c0_pins),
+	GPIO_PINGROUP(ssp0_pins),
+	GPIO_PINGROUP(ssp0_cs0_pins),
+	GPIO_PINGROUP(ssp0_cs1_2_pins),
+	GPIO_PINGROUP(i2s0_pins),
+	GPIO_PINGROUP(i2s1_pins),
+	GPIO_PINGROUP(clcd_pins),
+	GPIO_PINGROUP(clcd_high_res_pins),
+	GPIO_PINGROUP(pin18),
+	GPIO_PINGROUP(pin19),
+	GPIO_PINGROUP(pin20),
+	GPIO_PINGROUP(pin21),
+	GPIO_PINGROUP(pin22),
+	GPIO_PINGROUP(pin23),
+	GPIO_PINGROUP(pin143),
+	GPIO_PINGROUP(pin144),
+	GPIO_PINGROUP(pin145),
+	GPIO_PINGROUP(pin146),
+	GPIO_PINGROUP(pin147),
+	GPIO_PINGROUP(pin148),
+	GPIO_PINGROUP(pin149),
+	GPIO_PINGROUP(pin150),
+	GPIO_PINGROUP(pin151),
+	GPIO_PINGROUP(pin152),
+	GPIO_PINGROUP(smi_2_chips_pins),
+	GPIO_PINGROUP(pin54),
+	GPIO_PINGROUP(pin55),
+	GPIO_PINGROUP(pin56),
+	GPIO_PINGROUP(pin57),
+	GPIO_PINGROUP(pin58),
+	GPIO_PINGROUP(pin59),
+	GPIO_PINGROUP(pin60),
+	GPIO_PINGROUP(pin61),
+	GPIO_PINGROUP(pin62),
+	GPIO_PINGROUP(pin63),
+	GPIO_PINGROUP(pin_grp0),
+	GPIO_PINGROUP(pin_grp1),
+	GPIO_PINGROUP(pin_grp2),
+	GPIO_PINGROUP(pin_grp3),
+	GPIO_PINGROUP(pin_grp4),
+	GPIO_PINGROUP(pin_grp5),
+	GPIO_PINGROUP(pin_grp6),
+	GPIO_PINGROUP(pin_grp7),
+	GPIO_PINGROUP(pin_grp8),
+	GPIO_PINGROUP(nand_16bit_pins),
+	GPIO_PINGROUP(pin205),
+	GPIO_PINGROUP(pin206),
+	GPIO_PINGROUP(pin211),
+	GPIO_PINGROUP(pin212),
+	GPIO_PINGROUP(pin213),
+	GPIO_PINGROUP(pin214),
+	GPIO_PINGROUP(pin215),
+	GPIO_PINGROUP(pin216),
+	GPIO_PINGROUP(pin217),
+	GPIO_PINGROUP(pin218),
+	GPIO_PINGROUP(pin219),
+	GPIO_PINGROUP(pin220),
+	GPIO_PINGROUP(pin221),
+	GPIO_PINGROUP(pin222),
+	GPIO_PINGROUP(pin223),
+	GPIO_PINGROUP(pin224),
+	GPIO_PINGROUP(pin225),
+	GPIO_PINGROUP(pin226),
+	GPIO_PINGROUP(pin227),
+	GPIO_PINGROUP(pin228),
+	GPIO_PINGROUP(pin229),
+	GPIO_PINGROUP(pin230),
+	GPIO_PINGROUP(pin231),
+	GPIO_PINGROUP(pin232),
+	GPIO_PINGROUP(pin233),
+	GPIO_PINGROUP(pin234),
+	GPIO_PINGROUP(pin235),
+	GPIO_PINGROUP(pin236),
+	GPIO_PINGROUP(pin237),
+	GPIO_PINGROUP(pin238),
+	GPIO_PINGROUP(pin239),
+	GPIO_PINGROUP(pin240),
+	GPIO_PINGROUP(pin241),
+	GPIO_PINGROUP(pin242),
+	GPIO_PINGROUP(pin243),
+	GPIO_PINGROUP(pin244),
+	GPIO_PINGROUP(pin245),
+	GPIO_PINGROUP(keyboard_rowcol6_8_pins),
+	GPIO_PINGROUP(uart0_pins),
+	GPIO_PINGROUP(uart0_modem_pins),
+	GPIO_PINGROUP(gpt0_tmr0_pins),
+	GPIO_PINGROUP(gpt0_tmr1_pins),
+	GPIO_PINGROUP(gpt1_tmr0_pins),
+	GPIO_PINGROUP(gpt1_tmr1_pins),
+	GPIO_PINGROUP(touch_xy_pins),
+};
+
 static struct spear_pinctrl_machdata spear1310_machdata = {
 	.pins = spear1310_pins,
 	.npins = ARRAY_SIZE(spear1310_pins),
@@ -2425,10 +2687,12 @@ static struct spear_pinctrl_machdata spear1310_machdata = {
 	.ngroups = ARRAY_SIZE(spear1310_pingroups),
 	.functions = spear1310_functions,
 	.nfunctions = ARRAY_SIZE(spear1310_functions),
+	.gpio_pingroups = spear1310_gpio_pingroup,
+	.ngpio_pingroups = ARRAY_SIZE(spear1310_gpio_pingroup),
 	.modes_supported = false,
 };
 
-static struct of_device_id spear1310_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id spear1310_pinctrl_of_match[] = {
 	{
 		.compatible = "st,spear1310-pinmux",
 	},
@@ -2440,7 +2704,7 @@ static int __devinit spear1310_pinctrl_probe(struct platform_device *pdev)
 	return spear_pinctrl_probe(pdev, &spear1310_machdata);
 }
 
-static int __devexit spear1310_pinctrl_remove(struct platform_device *pdev)
+static int spear1310_pinctrl_remove(struct platform_device *pdev)
 {
 	return spear_pinctrl_remove(pdev);
 }
@@ -2452,7 +2716,7 @@ static struct platform_driver spear1310_pinctrl_driver = {
 		.of_match_table = spear1310_pinctrl_of_match,
 	},
 	.probe = spear1310_pinctrl_probe,
-	.remove = __devexit_p(spear1310_pinctrl_remove),
+	.remove = spear1310_pinctrl_remove,
 };
 
 static int __init spear1310_pinctrl_init(void)
diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c
index 0606b8c..8deaaff 100644
--- a/drivers/pinctrl/spear/pinctrl-spear1340.c
+++ b/drivers/pinctrl/spear/pinctrl-spear1340.c
@@ -1971,6 +1971,32 @@ static struct spear_function *spear1340_functions[] = {
 	&sata_function,
 };
 
+static void gpio_request_endisable(struct spear_pmx *pmx, int pin,
+		bool enable)
+{
+	unsigned int regoffset, regindex, bitoffset;
+	unsigned int val;
+
+	/* pin++ as gpio configuration starts from 2nd bit of base register */
+	pin++;
+
+	regindex = pin / 32;
+	bitoffset = pin % 32;
+
+	if (regindex <= 3)
+		regoffset = PAD_FUNCTION_EN_1 + regindex * sizeof(int *);
+	else
+		regoffset = PAD_FUNCTION_EN_5 + (regindex - 4) * sizeof(int *);
+
+	val = pmx_readl(pmx, regoffset);
+	if (enable)
+		val &= ~(0x1 << bitoffset);
+	else
+		val |= 0x1 << bitoffset;
+
+	pmx_writel(pmx, val, regoffset);
+}
+
 static struct spear_pinctrl_machdata spear1340_machdata = {
 	.pins = spear1340_pins,
 	.npins = ARRAY_SIZE(spear1340_pins),
@@ -1978,10 +2004,11 @@ static struct spear_pinctrl_machdata spear1340_machdata = {
 	.ngroups = ARRAY_SIZE(spear1340_pingroups),
 	.functions = spear1340_functions,
 	.nfunctions = ARRAY_SIZE(spear1340_functions),
+	.gpio_request_endisable = gpio_request_endisable,
 	.modes_supported = false,
 };
 
-static struct of_device_id spear1340_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id spear1340_pinctrl_of_match[] = {
 	{
 		.compatible = "st,spear1340-pinmux",
 	},
@@ -1993,7 +2020,7 @@ static int __devinit spear1340_pinctrl_probe(struct platform_device *pdev)
 	return spear_pinctrl_probe(pdev, &spear1340_machdata);
 }
 
-static int __devexit spear1340_pinctrl_remove(struct platform_device *pdev)
+static int spear1340_pinctrl_remove(struct platform_device *pdev)
 {
 	return spear_pinctrl_remove(pdev);
 }
@@ -2005,7 +2032,7 @@ static struct platform_driver spear1340_pinctrl_driver = {
 		.of_match_table = spear1340_pinctrl_of_match,
 	},
 	.probe = spear1340_pinctrl_probe,
-	.remove = __devexit_p(spear1340_pinctrl_remove),
+	.remove = spear1340_pinctrl_remove,
 };
 
 static int __init spear1340_pinctrl_init(void)
diff --git a/drivers/pinctrl/spear/pinctrl-spear300.c b/drivers/pinctrl/spear/pinctrl-spear300.c
index 4dfc284..f48e466 100644
--- a/drivers/pinctrl/spear/pinctrl-spear300.c
+++ b/drivers/pinctrl/spear/pinctrl-spear300.c
@@ -646,7 +646,7 @@ static struct spear_function *spear300_functions[] = {
 	&gpio1_function,
 };
 
-static struct of_device_id spear300_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id spear300_pinctrl_of_match[] = {
 	{
 		.compatible = "st,spear300-pinmux",
 	},
@@ -661,6 +661,8 @@ static int __devinit spear300_pinctrl_probe(struct platform_device *pdev)
 	spear3xx_machdata.ngroups = ARRAY_SIZE(spear300_pingroups);
 	spear3xx_machdata.functions = spear300_functions;
 	spear3xx_machdata.nfunctions = ARRAY_SIZE(spear300_functions);
+	spear3xx_machdata.gpio_pingroups = NULL;
+	spear3xx_machdata.ngpio_pingroups = 0;
 
 	spear3xx_machdata.modes_supported = true;
 	spear3xx_machdata.pmx_modes = spear300_pmx_modes;
@@ -675,7 +677,7 @@ static int __devinit spear300_pinctrl_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit spear300_pinctrl_remove(struct platform_device *pdev)
+static int spear300_pinctrl_remove(struct platform_device *pdev)
 {
 	return spear_pinctrl_remove(pdev);
 }
@@ -687,7 +689,7 @@ static struct platform_driver spear300_pinctrl_driver = {
 		.of_match_table = spear300_pinctrl_of_match,
 	},
 	.probe = spear300_pinctrl_probe,
-	.remove = __devexit_p(spear300_pinctrl_remove),
+	.remove = spear300_pinctrl_remove,
 };
 
 static int __init spear300_pinctrl_init(void)
diff --git a/drivers/pinctrl/spear/pinctrl-spear310.c b/drivers/pinctrl/spear/pinctrl-spear310.c
index 9688369..5b954c1 100644
--- a/drivers/pinctrl/spear/pinctrl-spear310.c
+++ b/drivers/pinctrl/spear/pinctrl-spear310.c
@@ -371,7 +371,7 @@ static struct spear_function *spear310_functions[] = {
 	&tdm_function,
 };
 
-static struct of_device_id spear310_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id spear310_pinctrl_of_match[] = {
 	{
 		.compatible = "st,spear310-pinmux",
 	},
@@ -388,6 +388,8 @@ static int __devinit spear310_pinctrl_probe(struct platform_device *pdev)
 	spear3xx_machdata.nfunctions = ARRAY_SIZE(spear310_functions);
 
 	pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
+	pmx_init_gpio_pingroup_addr(spear3xx_machdata.gpio_pingroups,
+			spear3xx_machdata.ngpio_pingroups, PMX_CONFIG_REG);
 
 	spear3xx_machdata.modes_supported = false;
 
@@ -398,7 +400,7 @@ static int __devinit spear310_pinctrl_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit spear310_pinctrl_remove(struct platform_device *pdev)
+static int spear310_pinctrl_remove(struct platform_device *pdev)
 {
 	return spear_pinctrl_remove(pdev);
 }
@@ -410,7 +412,7 @@ static struct platform_driver spear310_pinctrl_driver = {
 		.of_match_table = spear310_pinctrl_of_match,
 	},
 	.probe = spear310_pinctrl_probe,
-	.remove = __devexit_p(spear310_pinctrl_remove),
+	.remove = spear310_pinctrl_remove,
 };
 
 static int __init spear310_pinctrl_init(void)
diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c
index ca47b0e..e9a5e6d 100644
--- a/drivers/pinctrl/spear/pinctrl-spear320.c
+++ b/drivers/pinctrl/spear/pinctrl-spear320.c
@@ -3410,7 +3410,7 @@ static struct spear_function *spear320_functions[] = {
 	&i2c2_function,
 };
 
-static struct of_device_id spear320_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id spear320_pinctrl_of_match[] = {
 	{
 		.compatible = "st,spear320-pinmux",
 	},
@@ -3431,6 +3431,8 @@ static int __devinit spear320_pinctrl_probe(struct platform_device *pdev)
 	spear3xx_machdata.npmx_modes = ARRAY_SIZE(spear320_pmx_modes);
 
 	pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
+	pmx_init_gpio_pingroup_addr(spear3xx_machdata.gpio_pingroups,
+			spear3xx_machdata.ngpio_pingroups, PMX_CONFIG_REG);
 
 	ret = spear_pinctrl_probe(pdev, &spear3xx_machdata);
 	if (ret)
@@ -3439,7 +3441,7 @@ static int __devinit spear320_pinctrl_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit spear320_pinctrl_remove(struct platform_device *pdev)
+static int spear320_pinctrl_remove(struct platform_device *pdev)
 {
 	return spear_pinctrl_remove(pdev);
 }
@@ -3451,7 +3453,7 @@ static struct platform_driver spear320_pinctrl_driver = {
 		.of_match_table = spear320_pinctrl_of_match,
 	},
 	.probe = spear320_pinctrl_probe,
-	.remove = __devexit_p(spear320_pinctrl_remove),
+	.remove = spear320_pinctrl_remove,
 };
 
 static int __init spear320_pinctrl_init(void)
diff --git a/drivers/pinctrl/spear/pinctrl-spear3xx.c b/drivers/pinctrl/spear/pinctrl-spear3xx.c
index 0242378..12ee21a 100644
--- a/drivers/pinctrl/spear/pinctrl-spear3xx.c
+++ b/drivers/pinctrl/spear/pinctrl-spear3xx.c
@@ -481,7 +481,44 @@ struct spear_function spear3xx_timer_2_3_function = {
 	.ngroups = ARRAY_SIZE(timer_2_3_grps),
 };
 
+/* Define muxreg arrays */
+DEFINE_MUXREG(firda_pins, 0, PMX_FIRDA_MASK, 0);
+DEFINE_MUXREG(i2c_pins, 0, PMX_I2C_MASK, 0);
+DEFINE_MUXREG(ssp_cs_pins, 0, PMX_SSP_CS_MASK, 0);
+DEFINE_MUXREG(ssp_pins, 0, PMX_SSP_MASK, 0);
+DEFINE_MUXREG(mii_pins, 0, PMX_MII_MASK, 0);
+DEFINE_MUXREG(gpio0_pin0_pins, 0, PMX_GPIO_PIN0_MASK, 0);
+DEFINE_MUXREG(gpio0_pin1_pins, 0, PMX_GPIO_PIN1_MASK, 0);
+DEFINE_MUXREG(gpio0_pin2_pins, 0, PMX_GPIO_PIN2_MASK, 0);
+DEFINE_MUXREG(gpio0_pin3_pins, 0, PMX_GPIO_PIN3_MASK, 0);
+DEFINE_MUXREG(gpio0_pin4_pins, 0, PMX_GPIO_PIN4_MASK, 0);
+DEFINE_MUXREG(gpio0_pin5_pins, 0, PMX_GPIO_PIN5_MASK, 0);
+DEFINE_MUXREG(uart0_ext_pins, 0, PMX_UART0_MODEM_MASK, 0);
+DEFINE_MUXREG(uart0_pins, 0, PMX_UART0_MASK, 0);
+DEFINE_MUXREG(timer_0_1_pins, 0, PMX_TIMER_0_1_MASK, 0);
+DEFINE_MUXREG(timer_2_3_pins, 0, PMX_TIMER_2_3_MASK, 0);
+
+static struct spear_gpio_pingroup spear3xx_gpio_pingroup[] = {
+	GPIO_PINGROUP(firda_pins),
+	GPIO_PINGROUP(i2c_pins),
+	GPIO_PINGROUP(ssp_cs_pins),
+	GPIO_PINGROUP(ssp_pins),
+	GPIO_PINGROUP(mii_pins),
+	GPIO_PINGROUP(gpio0_pin0_pins),
+	GPIO_PINGROUP(gpio0_pin1_pins),
+	GPIO_PINGROUP(gpio0_pin2_pins),
+	GPIO_PINGROUP(gpio0_pin3_pins),
+	GPIO_PINGROUP(gpio0_pin4_pins),
+	GPIO_PINGROUP(gpio0_pin5_pins),
+	GPIO_PINGROUP(uart0_ext_pins),
+	GPIO_PINGROUP(uart0_pins),
+	GPIO_PINGROUP(timer_0_1_pins),
+	GPIO_PINGROUP(timer_2_3_pins),
+};
+
 struct spear_pinctrl_machdata spear3xx_machdata = {
 	.pins = spear3xx_pins,
 	.npins = ARRAY_SIZE(spear3xx_pins),
+	.gpio_pingroups = spear3xx_gpio_pingroup,
+	.ngpio_pingroups = ARRAY_SIZE(spear3xx_gpio_pingroup),
 };
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index 84c5688..c2e3e63 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -662,7 +662,7 @@ static int acerhdf_register_thermal(void)
 		return -EINVAL;
 
 	thz_dev = thermal_zone_device_register("acerhdf", 1, 0, NULL,
-					      &acerhdf_dev_ops, 0,
+					      &acerhdf_dev_ops, NULL, 0,
 					      (kernelmode) ? interval*1000 : 0);
 	if (IS_ERR(thz_dev))
 		return -EINVAL;
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index c0e9ff4..18f5169 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -187,6 +187,8 @@ struct asus_wmi {
 	struct device *hwmon_device;
 	struct platform_device *platform_device;
 
+	struct led_classdev wlan_led;
+	int wlan_led_wk;
 	struct led_classdev tpd_led;
 	int tpd_led_wk;
 	struct led_classdev kbd_led;
@@ -194,6 +196,7 @@ struct asus_wmi {
 	struct workqueue_struct *led_workqueue;
 	struct work_struct tpd_led_work;
 	struct work_struct kbd_led_work;
+	struct work_struct wlan_led_work;
 
 	struct asus_rfkill wlan;
 	struct asus_rfkill bluetooth;
@@ -456,12 +459,65 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
 	return value;
 }
 
+static int wlan_led_unknown_state(struct asus_wmi *asus)
+{
+	u32 result;
+
+	asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
+
+	return result & ASUS_WMI_DSTS_UNKNOWN_BIT;
+}
+
+static int wlan_led_presence(struct asus_wmi *asus)
+{
+	u32 result;
+
+	asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
+
+	return result & ASUS_WMI_DSTS_PRESENCE_BIT;
+}
+
+static void wlan_led_update(struct work_struct *work)
+{
+	int ctrl_param;
+	struct asus_wmi *asus;
+
+	asus = container_of(work, struct asus_wmi, wlan_led_work);
+
+	ctrl_param = asus->wlan_led_wk;
+	asus_wmi_set_devstate(ASUS_WMI_DEVID_WIRELESS_LED, ctrl_param, NULL);
+}
+
+static void wlan_led_set(struct led_classdev *led_cdev,
+			 enum led_brightness value)
+{
+	struct asus_wmi *asus;
+
+	asus = container_of(led_cdev, struct asus_wmi, wlan_led);
+
+	asus->wlan_led_wk = !!value;
+	queue_work(asus->led_workqueue, &asus->wlan_led_work);
+}
+
+static enum led_brightness wlan_led_get(struct led_classdev *led_cdev)
+{
+	struct asus_wmi *asus;
+	u32 result;
+
+	asus = container_of(led_cdev, struct asus_wmi, wlan_led);
+	asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);
+
+	return result & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
+}
+
 static void asus_wmi_led_exit(struct asus_wmi *asus)
 {
 	if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
 		led_classdev_unregister(&asus->kbd_led);
 	if (!IS_ERR_OR_NULL(asus->tpd_led.dev))
 		led_classdev_unregister(&asus->tpd_led);
+	if (!IS_ERR_OR_NULL(asus->wlan_led.dev))
+		led_classdev_unregister(&asus->wlan_led);
 	if (asus->led_workqueue)
 		destroy_workqueue(asus->led_workqueue);
 }
@@ -498,6 +554,23 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
 
 		rv = led_classdev_register(&asus->platform_device->dev,
 					   &asus->kbd_led);
+		if (rv)
+			goto error;
+	}
+
+	if (wlan_led_presence(asus)) {
+		INIT_WORK(&asus->wlan_led_work, wlan_led_update);
+
+		asus->wlan_led.name = "asus::wlan";
+		asus->wlan_led.brightness_set = wlan_led_set;
+		if (!wlan_led_unknown_state(asus))
+			asus->wlan_led.brightness_get = wlan_led_get;
+		asus->wlan_led.flags = LED_CORE_SUSPENDRESUME;
+		asus->wlan_led.max_brightness = 1;
+		asus->wlan_led.default_trigger = "asus-wlan";
+
+		rv = led_classdev_register(&asus->platform_device->dev,
+					   &asus->wlan_led);
 	}
 
 error:
@@ -813,6 +886,9 @@ static int asus_new_rfkill(struct asus_wmi *asus,
 	if (!*rfkill)
 		return -EINVAL;
 
+	if (dev_id == ASUS_WMI_DEVID_WLAN)
+		rfkill_set_led_trigger_name(*rfkill, "asus-wlan");
+
 	rfkill_init_sw_state(*rfkill, !result);
 	result = rfkill_register(*rfkill);
 	if (result) {
diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c
index c809761..93de090 100644
--- a/drivers/platform/x86/intel_mid_thermal.c
+++ b/drivers/platform/x86/intel_mid_thermal.c
@@ -502,7 +502,7 @@ static int mid_thermal_probe(struct platform_device *pdev)
 			goto err;
 		}
 		pinfo->tzd[i] = thermal_zone_device_register(name[i],
-				0, 0, td_info, &tzd_ops, 0, 0);
+				0, 0, td_info, &tzd_ops, NULL, 0, 0);
 		if (IS_ERR(pinfo->tzd[i])) {
 			kfree(td_info);
 			ret = PTR_ERR(pinfo->tzd[i]);
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index fa4e0a5..ffd53e3 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -159,6 +159,8 @@ struct pnp_resource {
 
 void pnp_free_resource(struct pnp_resource *pnp_res);
 
+struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
+				      struct resource *res);
 struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
 					  int flags);
 struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 26b5d4b..653d563 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -242,6 +242,10 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
 	char *pnpid;
 	struct acpi_hardware_id *id;
 
+	/* Skip devices that are already bound */
+	if (device->physical_node_count)
+		return 0;
+
 	/*
 	 * If a PnPacpi device is not present , the device
 	 * driver should not be loaded.
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 5be4a39..b8f4ea7 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -28,37 +28,6 @@
 #include "../base.h"
 #include "pnpacpi.h"
 
-#ifdef CONFIG_IA64
-#define valid_IRQ(i) (1)
-#else
-#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
-#endif
-
-/*
- * Allocated Resources
- */
-static int irq_flags(int triggering, int polarity, int shareable)
-{
-	int flags;
-
-	if (triggering == ACPI_LEVEL_SENSITIVE) {
-		if (polarity == ACPI_ACTIVE_LOW)
-			flags = IORESOURCE_IRQ_LOWLEVEL;
-		else
-			flags = IORESOURCE_IRQ_HIGHLEVEL;
-	} else {
-		if (polarity == ACPI_ACTIVE_LOW)
-			flags = IORESOURCE_IRQ_LOWEDGE;
-		else
-			flags = IORESOURCE_IRQ_HIGHEDGE;
-	}
-
-	if (shareable == ACPI_SHARED)
-		flags |= IORESOURCE_IRQ_SHAREABLE;
-
-	return flags;
-}
-
 static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
 			     int *polarity, int *shareable)
 {
@@ -94,45 +63,6 @@ static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
 		*shareable = ACPI_EXCLUSIVE;
 }
 
-static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
-						u32 gsi, int triggering,
-						int polarity, int shareable)
-{
-	int irq, flags;
-	int p, t;
-
-	if (!valid_IRQ(gsi)) {
-		pnp_add_irq_resource(dev, gsi, IORESOURCE_DISABLED);
-		return;
-	}
-
-	/*
-	 * in IO-APIC mode, use overrided attribute. Two reasons:
-	 * 1. BIOS bug in DSDT
-	 * 2. BIOS uses IO-APIC mode Interrupt Source Override
-	 */
-	if (!acpi_get_override_irq(gsi, &t, &p)) {
-		t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
-		p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
-
-		if (triggering != t || polarity != p) {
-			dev_warn(&dev->dev, "IRQ %d override to %s, %s\n",
-				gsi, t ? "edge":"level", p ? "low":"high");
-			triggering = t;
-			polarity = p;
-		}
-	}
-
-	flags = irq_flags(triggering, polarity, shareable);
-	irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
-	if (irq >= 0)
-		pcibios_penalize_isa_irq(irq, 1);
-	else
-		flags |= IORESOURCE_DISABLED;
-
-	pnp_add_irq_resource(dev, irq, flags);
-}
-
 static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
 		     int transfer)
 {
@@ -177,21 +107,16 @@ static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
 	return flags;
 }
 
-static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
-					       u64 len, int io_decode,
-					       int window)
-{
-	int flags = 0;
-	u64 end = start + len - 1;
+/*
+ * Allocated Resources
+ */
 
-	if (io_decode == ACPI_DECODE_16)
-		flags |= IORESOURCE_IO_16BIT_ADDR;
-	if (len == 0 || end >= 0x10003)
-		flags |= IORESOURCE_DISABLED;
-	if (window)
-		flags |= IORESOURCE_WINDOW;
+static void pnpacpi_add_irqresource(struct pnp_dev *dev, struct resource *r)
+{
+	if (!(r->flags & IORESOURCE_DISABLED))
+		pcibios_penalize_isa_irq(r->start, 1);
 
-	pnp_add_io_resource(dev, start, end, flags);
+	pnp_add_resource(dev, r);
 }
 
 /*
@@ -249,130 +174,49 @@ static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
 	}
 }
 
-static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
-						u64 start, u64 len,
-						int write_protect, int window)
-{
-	int flags = 0;
-	u64 end = start + len - 1;
-
-	if (len == 0)
-		flags |= IORESOURCE_DISABLED;
-	if (write_protect == ACPI_READ_WRITE_MEMORY)
-		flags |= IORESOURCE_MEM_WRITEABLE;
-	if (window)
-		flags |= IORESOURCE_WINDOW;
-
-	pnp_add_mem_resource(dev, start, end, flags);
-}
-
-static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev,
-						u64 start, u64 len)
-{
-	u64 end = start + len - 1;
-
-	pnp_add_bus_resource(dev, start, end);
-}
-
-static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
-						  struct acpi_resource *res)
-{
-	struct acpi_resource_address64 addr, *p = &addr;
-	acpi_status status;
-	int window;
-	u64 len;
-
-	status = acpi_resource_to_address64(res, p);
-	if (!ACPI_SUCCESS(status)) {
-		dev_warn(&dev->dev, "failed to convert resource type %d\n",
-			 res->type);
-		return;
-	}
-
-	/* Windows apparently computes length rather than using _LEN */
-	len = p->maximum - p->minimum + 1;
-	window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
-
-	if (p->resource_type == ACPI_MEMORY_RANGE)
-		pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
-			p->info.mem.write_protect, window);
-	else if (p->resource_type == ACPI_IO_RANGE)
-		pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
-			p->granularity == 0xfff ? ACPI_DECODE_10 :
-				ACPI_DECODE_16, window);
-	else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
-		pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
-}
-
-static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev,
-						      struct acpi_resource *res)
-{
-	struct acpi_resource_extended_address64 *p = &res->data.ext_address64;
-	int window;
-	u64 len;
-
-	/* Windows apparently computes length rather than using _LEN */
-	len = p->maximum - p->minimum + 1;
-	window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
-
-	if (p->resource_type == ACPI_MEMORY_RANGE)
-		pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
-			p->info.mem.write_protect, window);
-	else if (p->resource_type == ACPI_IO_RANGE)
-		pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
-			p->granularity == 0xfff ? ACPI_DECODE_10 :
-				ACPI_DECODE_16, window);
-	else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
-		pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
-}
-
 static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
 					      void *data)
 {
 	struct pnp_dev *dev = data;
-	struct acpi_resource_irq *irq;
 	struct acpi_resource_dma *dma;
-	struct acpi_resource_io *io;
-	struct acpi_resource_fixed_io *fixed_io;
 	struct acpi_resource_vendor_typed *vendor_typed;
-	struct acpi_resource_memory24 *memory24;
-	struct acpi_resource_memory32 *memory32;
-	struct acpi_resource_fixed_memory32 *fixed_memory32;
-	struct acpi_resource_extended_irq *extended_irq;
+	struct resource r;
 	int i, flags;
 
-	switch (res->type) {
-	case ACPI_RESOURCE_TYPE_IRQ:
-		/*
-		 * Per spec, only one interrupt per descriptor is allowed in
-		 * _CRS, but some firmware violates this, so parse them all.
-		 */
-		irq = &res->data.irq;
-		if (irq->interrupt_count == 0)
-			pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
-		else {
-			for (i = 0; i < irq->interrupt_count; i++) {
-				pnpacpi_parse_allocated_irqresource(dev,
-					irq->interrupts[i],
-					irq->triggering,
-					irq->polarity,
-				    irq->sharable);
-			}
+	if (acpi_dev_resource_memory(res, &r)
+	    || acpi_dev_resource_io(res, &r)
+	    || acpi_dev_resource_address_space(res, &r)
+	    || acpi_dev_resource_ext_address_space(res, &r)) {
+		pnp_add_resource(dev, &r);
+		return AE_OK;
+	}
 
+	r.flags = 0;
+	if (acpi_dev_resource_interrupt(res, 0, &r)) {
+		pnpacpi_add_irqresource(dev, &r);
+		for (i = 1; acpi_dev_resource_interrupt(res, i, &r); i++)
+			pnpacpi_add_irqresource(dev, &r);
+
+		if (i > 1) {
 			/*
 			 * The IRQ encoder puts a single interrupt in each
 			 * descriptor, so if a _CRS descriptor has more than
 			 * one interrupt, we won't be able to re-encode it.
 			 */
-			if (pnp_can_write(dev) && irq->interrupt_count > 1) {
+			if (pnp_can_write(dev)) {
 				dev_warn(&dev->dev, "multiple interrupts in "
 					 "_CRS descriptor; configuration can't "
 					 "be changed\n");
 				dev->capabilities &= ~PNP_WRITE;
 			}
 		}
-		break;
+		return AE_OK;
+	} else if (r.flags & IORESOURCE_DISABLED) {
+		pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
+		return AE_OK;
+	}
 
+	switch (res->type) {
 	case ACPI_RESOURCE_TYPE_DMA:
 		dma = &res->data.dma;
 		if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
@@ -383,26 +227,10 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
 		pnp_add_dma_resource(dev, dma->channels[0], flags);
 		break;
 
-	case ACPI_RESOURCE_TYPE_IO:
-		io = &res->data.io;
-		pnpacpi_parse_allocated_ioresource(dev,
-			io->minimum,
-			io->address_length,
-			io->io_decode, 0);
-		break;
-
 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
 	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
 		break;
 
-	case ACPI_RESOURCE_TYPE_FIXED_IO:
-		fixed_io = &res->data.fixed_io;
-		pnpacpi_parse_allocated_ioresource(dev,
-			fixed_io->address,
-			fixed_io->address_length,
-			ACPI_DECODE_10, 0);
-		break;
-
 	case ACPI_RESOURCE_TYPE_VENDOR:
 		vendor_typed = &res->data.vendor_typed;
 		pnpacpi_parse_allocated_vendor(dev, vendor_typed);
@@ -411,66 +239,6 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
 	case ACPI_RESOURCE_TYPE_END_TAG:
 		break;
 
-	case ACPI_RESOURCE_TYPE_MEMORY24:
-		memory24 = &res->data.memory24;
-		pnpacpi_parse_allocated_memresource(dev,
-			memory24->minimum,
-			memory24->address_length,
-			memory24->write_protect, 0);
-		break;
-	case ACPI_RESOURCE_TYPE_MEMORY32:
-		memory32 = &res->data.memory32;
-		pnpacpi_parse_allocated_memresource(dev,
-			memory32->minimum,
-			memory32->address_length,
-			memory32->write_protect, 0);
-		break;
-	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-		fixed_memory32 = &res->data.fixed_memory32;
-		pnpacpi_parse_allocated_memresource(dev,
-			fixed_memory32->address,
-			fixed_memory32->address_length,
-			fixed_memory32->write_protect, 0);
-		break;
-	case ACPI_RESOURCE_TYPE_ADDRESS16:
-	case ACPI_RESOURCE_TYPE_ADDRESS32:
-	case ACPI_RESOURCE_TYPE_ADDRESS64:
-		pnpacpi_parse_allocated_address_space(dev, res);
-		break;
-
-	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
-		pnpacpi_parse_allocated_ext_address_space(dev, res);
-		break;
-
-	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
-		extended_irq = &res->data.extended_irq;
-
-		if (extended_irq->interrupt_count == 0)
-			pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
-		else {
-			for (i = 0; i < extended_irq->interrupt_count; i++) {
-				pnpacpi_parse_allocated_irqresource(dev,
-					extended_irq->interrupts[i],
-					extended_irq->triggering,
-					extended_irq->polarity,
-					extended_irq->sharable);
-			}
-
-			/*
-			 * The IRQ encoder puts a single interrupt in each
-			 * descriptor, so if a _CRS descriptor has more than
-			 * one interrupt, we won't be able to re-encode it.
-			 */
-			if (pnp_can_write(dev) &&
-			    extended_irq->interrupt_count > 1) {
-				dev_warn(&dev->dev, "multiple interrupts in "
-					 "_CRS descriptor; configuration can't "
-					 "be changed\n");
-				dev->capabilities &= ~PNP_WRITE;
-			}
-		}
-		break;
-
 	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
 		break;
 
@@ -531,7 +299,7 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
 		if (p->interrupts[i])
 			__set_bit(p->interrupts[i], map.bits);
 
-	flags = irq_flags(p->triggering, p->polarity, p->sharable);
+	flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable);
 	pnp_register_irq_resource(dev, option_flags, &map, flags);
 }
 
@@ -555,7 +323,7 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
 		}
 	}
 
-	flags = irq_flags(p->triggering, p->polarity, p->sharable);
+	flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable);
 	pnp_register_irq_resource(dev, option_flags, &map, flags);
 }
 
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 9d42226..5d66e55 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -91,8 +91,6 @@ struct pnp_dev_node_info node_info;
  *
  */
 
-#ifdef CONFIG_HOTPLUG
-
 static struct completion unload_sem;
 
 /*
@@ -199,8 +197,6 @@ static int pnp_dock_thread(void *unused)
 	complete_and_exit(&unload_sem, 0);
 }
 
-#endif				/* CONFIG_HOTPLUG */
-
 static int pnpbios_get_resources(struct pnp_dev *dev)
 {
 	u8 nodenum = dev->number;
@@ -573,21 +569,19 @@ fs_initcall(pnpbios_init);
 
 static int __init pnpbios_thread_init(void)
 {
+	struct task_struct *task;
 #if defined(CONFIG_PPC)
 	if (check_legacy_ioport(PNPBIOS_BASE))
 		return 0;
 #endif
 	if (pnpbios_disabled)
 		return 0;
-#ifdef CONFIG_HOTPLUG
-	{
-		struct task_struct *task;
-		init_completion(&unload_sem);
-		task = kthread_run(pnp_dock_thread, NULL, "kpnpbiosd");
-		if (IS_ERR(task))
-			return PTR_ERR(task);
-	}
-#endif
+
+	init_completion(&unload_sem);
+	task = kthread_run(pnp_dock_thread, NULL, "kpnpbiosd");
+	if (IS_ERR(task))
+		return PTR_ERR(task);
+
 	return 0;
 }
 
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index b0ecacb..3e6db1c 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -503,6 +503,22 @@ static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev)
 	return pnp_res;
 }
 
+struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
+				      struct resource *res)
+{
+	struct pnp_resource *pnp_res;
+
+	pnp_res = pnp_new_resource(dev);
+	if (!pnp_res) {
+		dev_err(&dev->dev, "can't add resource %pR\n", res);
+		return NULL;
+	}
+
+	pnp_res->res = *res;
+	dev_dbg(&dev->dev, "%pR\n", res);
+	return pnp_res;
+}
+
 struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
 					  int flags)
 {
diff --git a/drivers/power/88pm860x_battery.c b/drivers/power/88pm860x_battery.c
index beed5ecf..8bc80b0 100644
--- a/drivers/power/88pm860x_battery.c
+++ b/drivers/power/88pm860x_battery.c
@@ -901,7 +901,7 @@ static enum power_supply_property pm860x_batt_props[] = {
 	POWER_SUPPLY_PROP_TEMP,
 };
 
-static __devinit int pm860x_battery_probe(struct platform_device *pdev)
+static int pm860x_battery_probe(struct platform_device *pdev)
 {
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct pm860x_battery_info *info;
@@ -989,7 +989,7 @@ out:
 	return ret;
 }
 
-static int __devexit pm860x_battery_remove(struct platform_device *pdev)
+static int pm860x_battery_remove(struct platform_device *pdev)
 {
 	struct pm860x_battery_info *info = platform_get_drvdata(pdev);
 
@@ -1033,7 +1033,7 @@ static struct platform_driver pm860x_battery_driver = {
 		   .pm = &pm860x_battery_pm_ops,
 	},
 	.probe = pm860x_battery_probe,
-	.remove = __devexit_p(pm860x_battery_remove),
+	.remove = pm860x_battery_remove,
 };
 module_platform_driver(pm860x_battery_driver);
 
diff --git a/drivers/power/88pm860x_charger.c b/drivers/power/88pm860x_charger.c
index 2dbeb14..4b37a5a 100644
--- a/drivers/power/88pm860x_charger.c
+++ b/drivers/power/88pm860x_charger.c
@@ -645,7 +645,7 @@ static struct pm860x_irq_desc {
 	{ "vchg", pm860x_vchg_handler },
 };
 
-static __devinit int pm860x_charger_probe(struct platform_device *pdev)
+static int pm860x_charger_probe(struct platform_device *pdev)
 {
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct pm860x_charger_info *info;
@@ -718,7 +718,7 @@ out:
 	return ret;
 }
 
-static int __devexit pm860x_charger_remove(struct platform_device *pdev)
+static int pm860x_charger_remove(struct platform_device *pdev)
 {
 	struct pm860x_charger_info *info = platform_get_drvdata(pdev);
 	int i;
@@ -738,7 +738,7 @@ static struct platform_driver pm860x_charger_driver = {
 		   .owner = THIS_MODULE,
 	},
 	.probe = pm860x_charger_probe,
-	.remove = __devexit_p(pm860x_charger_remove),
+	.remove = pm860x_charger_remove,
 };
 module_platform_driver(pm860x_charger_driver);
 
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 49a8939..9f45e2f 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -245,6 +245,13 @@ config BATTERY_INTEL_MID
 	  Say Y here to enable the battery driver on Intel MID
 	  platforms.
 
+config BATTERY_RX51
+	tristate "Nokia RX-51 (N900) battery driver"
+	depends on TWL4030_MADC
+	help
+	  Say Y here to enable support for battery information on Nokia
+	  RX-51, also known as N900 tablet.
+
 config CHARGER_ISP1704
 	tristate "ISP1704 USB Charger Detection"
 	depends on USB_OTG_UTILS
@@ -315,6 +322,16 @@ config CHARGER_MAX8998
 	  Say Y to enable support for the battery charger control sysfs and
 	  platform data of MAX8998/LP3974 PMICs.
 
+config CHARGER_BQ2415X
+	tristate "TI BQ2415x battery charger driver"
+	depends on I2C
+	help
+	  Say Y to enable support for the TI BQ2415x battery charger
+	  PMICs.
+
+	  You'll need this driver to charge batteries on e.g. Nokia
+	  RX-51/N900.
+
 config CHARGER_SMB347
 	tristate "Summit Microelectronics SMB347 Battery Charger"
 	depends on I2C
@@ -329,12 +346,8 @@ config AB8500_BM
 	help
 	  Say Y to include support for AB8500 battery management.
 
-config AB8500_BATTERY_THERM_ON_BATCTRL
-	bool "Thermistor connected on BATCTRL ADC"
-	depends on AB8500_BM
-	help
-	  Say Y to enable battery temperature measurements using
-	  thermistor connected on BATCTRL ADC.
+source "drivers/power/reset/Kconfig"
+
 endif # POWER_SUPPLY
 
 source "drivers/power/avs/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index b949cf8..22c8913 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -37,7 +37,8 @@ obj-$(CONFIG_CHARGER_88PM860X)	+= 88pm860x_charger.o
 obj-$(CONFIG_CHARGER_PCF50633)	+= pcf50633-charger.o
 obj-$(CONFIG_BATTERY_JZ4740)	+= jz4740-battery.o
 obj-$(CONFIG_BATTERY_INTEL_MID)	+= intel_mid_battery.o
-obj-$(CONFIG_AB8500_BM)		+= ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o
+obj-$(CONFIG_BATTERY_RX51)	+= rx51_battery.o
+obj-$(CONFIG_AB8500_BM)		+= ab8500_bmdata.o ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o
 obj-$(CONFIG_CHARGER_ISP1704)	+= isp1704_charger.o
 obj-$(CONFIG_CHARGER_MAX8903)	+= max8903_charger.o
 obj-$(CONFIG_CHARGER_TWL4030)	+= twl4030_charger.o
@@ -47,5 +48,7 @@ obj-$(CONFIG_CHARGER_GPIO)	+= gpio-charger.o
 obj-$(CONFIG_CHARGER_MANAGER)	+= charger-manager.o
 obj-$(CONFIG_CHARGER_MAX8997)	+= max8997_charger.o
 obj-$(CONFIG_CHARGER_MAX8998)	+= max8998_charger.o
+obj-$(CONFIG_CHARGER_BQ2415X)	+= bq2415x_charger.o
 obj-$(CONFIG_POWER_AVS)		+= avs/
 obj-$(CONFIG_CHARGER_SMB347)	+= smb347-charger.o
+obj-$(CONFIG_POWER_RESET)	+= reset/
diff --git a/drivers/power/ab8500_bmdata.c b/drivers/power/ab8500_bmdata.c
new file mode 100644
index 0000000..03cc528
--- /dev/null
+++ b/drivers/power/ab8500_bmdata.c
@@ -0,0 +1,521 @@
+#include <linux/export.h>
+#include <linux/power_supply.h>
+#include <linux/of.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/mfd/abx500/ab8500-bm.h>
+
+/*
+ * These are the defined batteries that uses a NTC and ID resistor placed
+ * inside of the battery pack.
+ * Note that the res_to_temp table must be strictly sorted by falling resistance
+ * values to work.
+ */
+static struct abx500_res_to_temp temp_tbl_A_thermistor[] = {
+	{-5, 53407},
+	{ 0, 48594},
+	{ 5, 43804},
+	{10, 39188},
+	{15, 34870},
+	{20, 30933},
+	{25, 27422},
+	{30, 24347},
+	{35, 21694},
+	{40, 19431},
+	{45, 17517},
+	{50, 15908},
+	{55, 14561},
+	{60, 13437},
+	{65, 12500},
+};
+
+static struct abx500_res_to_temp temp_tbl_B_thermistor[] = {
+	{-5, 200000},
+	{ 0, 159024},
+	{ 5, 151921},
+	{10, 144300},
+	{15, 136424},
+	{20, 128565},
+	{25, 120978},
+	{30, 113875},
+	{35, 107397},
+	{40, 101629},
+	{45,  96592},
+	{50,  92253},
+	{55,  88569},
+	{60,  85461},
+	{65,  82869},
+};
+
+static struct abx500_v_to_cap cap_tbl_A_thermistor[] = {
+	{4171,	100},
+	{4114,	 95},
+	{4009,	 83},
+	{3947,	 74},
+	{3907,	 67},
+	{3863,	 59},
+	{3830,	 56},
+	{3813,	 53},
+	{3791,	 46},
+	{3771,	 33},
+	{3754,	 25},
+	{3735,	 20},
+	{3717,	 17},
+	{3681,	 13},
+	{3664,	  8},
+	{3651,	  6},
+	{3635,	  5},
+	{3560,	  3},
+	{3408,    1},
+	{3247,	  0},
+};
+
+static struct abx500_v_to_cap cap_tbl_B_thermistor[] = {
+	{4161,	100},
+	{4124,	 98},
+	{4044,	 90},
+	{4003,	 85},
+	{3966,	 80},
+	{3933,	 75},
+	{3888,	 67},
+	{3849,	 60},
+	{3813,	 55},
+	{3787,	 47},
+	{3772,	 30},
+	{3751,	 25},
+	{3718,	 20},
+	{3681,	 16},
+	{3660,	 14},
+	{3589,	 10},
+	{3546,	  7},
+	{3495,	  4},
+	{3404,	  2},
+	{3250,	  0},
+};
+
+static struct abx500_v_to_cap cap_tbl[] = {
+	{4186,	100},
+	{4163,	 99},
+	{4114,	 95},
+	{4068,	 90},
+	{3990,	 80},
+	{3926,	 70},
+	{3898,	 65},
+	{3866,	 60},
+	{3833,	 55},
+	{3812,	 50},
+	{3787,	 40},
+	{3768,	 30},
+	{3747,	 25},
+	{3730,	 20},
+	{3705,	 15},
+	{3699,	 14},
+	{3684,	 12},
+	{3672,	  9},
+	{3657,	  7},
+	{3638,	  6},
+	{3556,	  4},
+	{3424,	  2},
+	{3317,	  1},
+	{3094,	  0},
+};
+
+/*
+ * Note that the res_to_temp table must be strictly sorted by falling
+ * resistance values to work.
+ */
+static struct abx500_res_to_temp temp_tbl[] = {
+	{-5, 214834},
+	{ 0, 162943},
+	{ 5, 124820},
+	{10,  96520},
+	{15,  75306},
+	{20,  59254},
+	{25,  47000},
+	{30,  37566},
+	{35,  30245},
+	{40,  24520},
+	{45,  20010},
+	{50,  16432},
+	{55,  13576},
+	{60,  11280},
+	{65,   9425},
+};
+
+/*
+ * Note that the batres_vs_temp table must be strictly sorted by falling
+ * temperature values to work.
+ */
+static struct batres_vs_temp temp_to_batres_tbl_thermistor[] = {
+	{ 40, 120},
+	{ 30, 135},
+	{ 20, 165},
+	{ 10, 230},
+	{ 00, 325},
+	{-10, 445},
+	{-20, 595},
+};
+
+/*
+ * Note that the batres_vs_temp table must be strictly sorted by falling
+ * temperature values to work.
+ */
+static struct batres_vs_temp temp_to_batres_tbl_ext_thermistor[] = {
+	{ 60, 300},
+	{ 30, 300},
+	{ 20, 300},
+	{ 10, 300},
+	{ 00, 300},
+	{-10, 300},
+	{-20, 300},
+};
+
+/* battery resistance table for LI ION 9100 battery */
+static struct batres_vs_temp temp_to_batres_tbl_9100[] = {
+	{ 60, 180},
+	{ 30, 180},
+	{ 20, 180},
+	{ 10, 180},
+	{ 00, 180},
+	{-10, 180},
+	{-20, 180},
+};
+
+static struct abx500_battery_type bat_type_thermistor[] = {
+[BATTERY_UNKNOWN] = {
+	/* First element always represent the UNKNOWN battery */
+	.name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN,
+	.resis_high = 0,
+	.resis_low = 0,
+	.battery_resistance = 300,
+	.charge_full_design = 612,
+	.nominal_voltage = 3700,
+	.termination_vol = 4050,
+	.termination_curr = 200,
+	.recharge_vol = 3990,
+	.normal_cur_lvl = 400,
+	.normal_vol_lvl = 4100,
+	.maint_a_cur_lvl = 400,
+	.maint_a_vol_lvl = 4050,
+	.maint_a_chg_timer_h = 60,
+	.maint_b_cur_lvl = 400,
+	.maint_b_vol_lvl = 4000,
+	.maint_b_chg_timer_h = 200,
+	.low_high_cur_lvl = 300,
+	.low_high_vol_lvl = 4000,
+	.n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+	.r_to_t_tbl = temp_tbl,
+	.n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+	.v_to_cap_tbl = cap_tbl,
+	.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+	.batres_tbl = temp_to_batres_tbl_thermistor,
+},
+{
+	.name = POWER_SUPPLY_TECHNOLOGY_LIPO,
+	.resis_high = 53407,
+	.resis_low = 12500,
+	.battery_resistance = 300,
+	.charge_full_design = 900,
+	.nominal_voltage = 3600,
+	.termination_vol = 4150,
+	.termination_curr = 80,
+	.recharge_vol = 4130,
+	.normal_cur_lvl = 700,
+	.normal_vol_lvl = 4200,
+	.maint_a_cur_lvl = 600,
+	.maint_a_vol_lvl = 4150,
+	.maint_a_chg_timer_h = 60,
+	.maint_b_cur_lvl = 600,
+	.maint_b_vol_lvl = 4100,
+	.maint_b_chg_timer_h = 200,
+	.low_high_cur_lvl = 300,
+	.low_high_vol_lvl = 4000,
+	.n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_A_thermistor),
+	.r_to_t_tbl = temp_tbl_A_thermistor,
+	.n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_A_thermistor),
+	.v_to_cap_tbl = cap_tbl_A_thermistor,
+	.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+	.batres_tbl = temp_to_batres_tbl_thermistor,
+
+},
+{
+	.name = POWER_SUPPLY_TECHNOLOGY_LIPO,
+	.resis_high = 200000,
+	.resis_low = 82869,
+	.battery_resistance = 300,
+	.charge_full_design = 900,
+	.nominal_voltage = 3600,
+	.termination_vol = 4150,
+	.termination_curr = 80,
+	.recharge_vol = 4130,
+	.normal_cur_lvl = 700,
+	.normal_vol_lvl = 4200,
+	.maint_a_cur_lvl = 600,
+	.maint_a_vol_lvl = 4150,
+	.maint_a_chg_timer_h = 60,
+	.maint_b_cur_lvl = 600,
+	.maint_b_vol_lvl = 4100,
+	.maint_b_chg_timer_h = 200,
+	.low_high_cur_lvl = 300,
+	.low_high_vol_lvl = 4000,
+	.n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_B_thermistor),
+	.r_to_t_tbl = temp_tbl_B_thermistor,
+	.n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B_thermistor),
+	.v_to_cap_tbl = cap_tbl_B_thermistor,
+	.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+	.batres_tbl = temp_to_batres_tbl_thermistor,
+},
+};
+
+static struct abx500_battery_type bat_type_ext_thermistor[] = {
+[BATTERY_UNKNOWN] = {
+	/* First element always represent the UNKNOWN battery */
+	.name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN,
+	.resis_high = 0,
+	.resis_low = 0,
+	.battery_resistance = 300,
+	.charge_full_design = 612,
+	.nominal_voltage = 3700,
+	.termination_vol = 4050,
+	.termination_curr = 200,
+	.recharge_vol = 3990,
+	.normal_cur_lvl = 400,
+	.normal_vol_lvl = 4100,
+	.maint_a_cur_lvl = 400,
+	.maint_a_vol_lvl = 4050,
+	.maint_a_chg_timer_h = 60,
+	.maint_b_cur_lvl = 400,
+	.maint_b_vol_lvl = 4000,
+	.maint_b_chg_timer_h = 200,
+	.low_high_cur_lvl = 300,
+	.low_high_vol_lvl = 4000,
+	.n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+	.r_to_t_tbl = temp_tbl,
+	.n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+	.v_to_cap_tbl = cap_tbl,
+	.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+	.batres_tbl = temp_to_batres_tbl_thermistor,
+},
+/*
+ * These are the batteries that doesn't have an internal NTC resistor to measure
+ * its temperature. The temperature in this case is measure with a NTC placed
+ * near the battery but on the PCB.
+ */
+{
+	.name = POWER_SUPPLY_TECHNOLOGY_LIPO,
+	.resis_high = 76000,
+	.resis_low = 53000,
+	.battery_resistance = 300,
+	.charge_full_design = 900,
+	.nominal_voltage = 3700,
+	.termination_vol = 4150,
+	.termination_curr = 100,
+	.recharge_vol = 4130,
+	.normal_cur_lvl = 700,
+	.normal_vol_lvl = 4200,
+	.maint_a_cur_lvl = 600,
+	.maint_a_vol_lvl = 4150,
+	.maint_a_chg_timer_h = 60,
+	.maint_b_cur_lvl = 600,
+	.maint_b_vol_lvl = 4100,
+	.maint_b_chg_timer_h = 200,
+	.low_high_cur_lvl = 300,
+	.low_high_vol_lvl = 4000,
+	.n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+	.r_to_t_tbl = temp_tbl,
+	.n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+	.v_to_cap_tbl = cap_tbl,
+	.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+	.batres_tbl = temp_to_batres_tbl_thermistor,
+},
+{
+	.name = POWER_SUPPLY_TECHNOLOGY_LION,
+	.resis_high = 30000,
+	.resis_low = 10000,
+	.battery_resistance = 300,
+	.charge_full_design = 950,
+	.nominal_voltage = 3700,
+	.termination_vol = 4150,
+	.termination_curr = 100,
+	.recharge_vol = 4130,
+	.normal_cur_lvl = 700,
+	.normal_vol_lvl = 4200,
+	.maint_a_cur_lvl = 600,
+	.maint_a_vol_lvl = 4150,
+	.maint_a_chg_timer_h = 60,
+	.maint_b_cur_lvl = 600,
+	.maint_b_vol_lvl = 4100,
+	.maint_b_chg_timer_h = 200,
+	.low_high_cur_lvl = 300,
+	.low_high_vol_lvl = 4000,
+	.n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+	.r_to_t_tbl = temp_tbl,
+	.n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+	.v_to_cap_tbl = cap_tbl,
+	.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+	.batres_tbl = temp_to_batres_tbl_thermistor,
+},
+{
+	.name = POWER_SUPPLY_TECHNOLOGY_LION,
+	.resis_high = 95000,
+	.resis_low = 76001,
+	.battery_resistance = 300,
+	.charge_full_design = 950,
+	.nominal_voltage = 3700,
+	.termination_vol = 4150,
+	.termination_curr = 100,
+	.recharge_vol = 4130,
+	.normal_cur_lvl = 700,
+	.normal_vol_lvl = 4200,
+	.maint_a_cur_lvl = 600,
+	.maint_a_vol_lvl = 4150,
+	.maint_a_chg_timer_h = 60,
+	.maint_b_cur_lvl = 600,
+	.maint_b_vol_lvl = 4100,
+	.maint_b_chg_timer_h = 200,
+	.low_high_cur_lvl = 300,
+	.low_high_vol_lvl = 4000,
+	.n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+	.r_to_t_tbl = temp_tbl,
+	.n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+	.v_to_cap_tbl = cap_tbl,
+	.n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor),
+	.batres_tbl = temp_to_batres_tbl_thermistor,
+},
+};
+
+static const struct abx500_bm_capacity_levels cap_levels = {
+	.critical	= 2,
+	.low		= 10,
+	.normal		= 70,
+	.high		= 95,
+	.full		= 100,
+};
+
+static const struct abx500_fg_parameters fg = {
+	.recovery_sleep_timer = 10,
+	.recovery_total_time = 100,
+	.init_timer = 1,
+	.init_discard_time = 5,
+	.init_total_time = 40,
+	.high_curr_time = 60,
+	.accu_charging = 30,
+	.accu_high_curr = 30,
+	.high_curr_threshold = 50,
+	.lowbat_threshold = 3100,
+	.battok_falling_th_sel0 = 2860,
+	.battok_raising_th_sel1 = 2860,
+	.user_cap_limit = 15,
+	.maint_thres = 97,
+};
+
+static const struct abx500_maxim_parameters maxi_params = {
+	.ena_maxi = true,
+	.chg_curr = 910,
+	.wait_cycles = 10,
+	.charger_curr_step = 100,
+};
+
+static const struct abx500_bm_charger_parameters chg = {
+	.usb_volt_max		= 5500,
+	.usb_curr_max		= 1500,
+	.ac_volt_max		= 7500,
+	.ac_curr_max		= 1500,
+};
+
+struct abx500_bm_data ab8500_bm_data = {
+	.temp_under		= 3,
+	.temp_low		= 8,
+	.temp_high		= 43,
+	.temp_over		= 48,
+	.main_safety_tmr_h	= 4,
+	.temp_interval_chg	= 20,
+	.temp_interval_nochg	= 120,
+	.usb_safety_tmr_h	= 4,
+	.bkup_bat_v		= BUP_VCH_SEL_2P6V,
+	.bkup_bat_i		= BUP_ICH_SEL_150UA,
+	.no_maintenance		= false,
+	.adc_therm		= ABx500_ADC_THERM_BATCTRL,
+	.chg_unknown_bat	= false,
+	.enable_overshoot	= false,
+	.fg_res			= 100,
+	.cap_levels		= &cap_levels,
+	.bat_type		= bat_type_thermistor,
+	.n_btypes		= 3,
+	.batt_id		= 0,
+	.interval_charging	= 5,
+	.interval_not_charging	= 120,
+	.temp_hysteresis	= 3,
+	.gnd_lift_resistance	= 34,
+	.maxi			= &maxi_params,
+	.chg_params		= &chg,
+	.fg_params		= &fg,
+};
+
+int __devinit
+bmdevs_of_probe(struct device *dev,
+		struct device_node *np,
+		struct abx500_bm_data **battery)
+{
+	struct	abx500_battery_type *btype;
+	struct  device_node *np_bat_supply;
+	struct	abx500_bm_data *bat;
+	const char *btech;
+	char bat_tech[8];
+	int i, thermistor;
+
+	*battery = &ab8500_bm_data;
+
+	/* get phandle to 'battery-info' node */
+	np_bat_supply = of_parse_phandle(np, "battery", 0);
+	if (!np_bat_supply) {
+		dev_err(dev, "missing property battery\n");
+		return -EINVAL;
+	}
+	if (of_property_read_bool(np_bat_supply,
+			"thermistor-on-batctrl"))
+		thermistor = NTC_INTERNAL;
+	else
+		thermistor = NTC_EXTERNAL;
+
+	bat = *battery;
+	if (thermistor == NTC_EXTERNAL) {
+		bat->n_btypes  = 4;
+		bat->bat_type  = bat_type_ext_thermistor;
+		bat->adc_therm = ABx500_ADC_THERM_BATTEMP;
+	}
+	btech = of_get_property(np_bat_supply,
+		"stericsson,battery-type", NULL);
+	if (!btech) {
+		dev_warn(dev, "missing property battery-name/type\n");
+		strcpy(bat_tech, "UNKNOWN");
+	} else {
+		strcpy(bat_tech, btech);
+	}
+
+	if (strncmp(bat_tech, "LION", 4) == 0) {
+		bat->no_maintenance  = true;
+		bat->chg_unknown_bat = true;
+		bat->bat_type[BATTERY_UNKNOWN].charge_full_design = 2600;
+		bat->bat_type[BATTERY_UNKNOWN].termination_vol    = 4150;
+		bat->bat_type[BATTERY_UNKNOWN].recharge_vol	  = 4130;
+		bat->bat_type[BATTERY_UNKNOWN].normal_cur_lvl	  = 520;
+		bat->bat_type[BATTERY_UNKNOWN].normal_vol_lvl	  = 4200;
+	}
+	/* select the battery resolution table */
+	for (i = 0; i < bat->n_btypes; ++i) {
+		btype = (bat->bat_type + i);
+		if (thermistor == NTC_EXTERNAL) {
+			btype->batres_tbl =
+				temp_to_batres_tbl_ext_thermistor;
+		} else if (strncmp(bat_tech, "LION", 4) == 0) {
+			btype->batres_tbl =
+				temp_to_batres_tbl_9100;
+		} else {
+			btype->batres_tbl =
+				temp_to_batres_tbl_thermistor;
+		}
+	}
+	of_node_put(np_bat_supply);
+	return 0;
+}
diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index e3b6395..20e2a7d 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -20,11 +20,13 @@
 #include <linux/power_supply.h>
 #include <linux/completion.h>
 #include <linux/workqueue.h>
-#include <linux/mfd/abx500/ab8500.h>
+#include <linux/jiffies.h>
+#include <linux/of.h>
+#include <linux/mfd/core.h>
 #include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
 #include <linux/mfd/abx500/ab8500-bm.h>
 #include <linux/mfd/abx500/ab8500-gpadc.h>
-#include <linux/jiffies.h>
 
 #define VTVOUT_V			1800
 
@@ -76,7 +78,6 @@ struct ab8500_btemp_ranges {
  * @parent:		Pointer to the struct ab8500
  * @gpadc:		Pointer to the struct gpadc
  * @fg:			Pointer to the struct fg
- * @pdata:		Pointer to the abx500_btemp platform data
  * @bat:		Pointer to the abx500_bm platform data
  * @btemp_psy:		Structure for BTEMP specific battery properties
  * @events:		Structure for information about events triggered
@@ -93,7 +94,6 @@ struct ab8500_btemp {
 	struct ab8500 *parent;
 	struct ab8500_gpadc *gpadc;
 	struct ab8500_fg *fg;
-	struct abx500_btemp_platform_data *pdata;
 	struct abx500_bm_data *bat;
 	struct power_supply btemp_psy;
 	struct ab8500_btemp_events events;
@@ -938,7 +938,7 @@ static int ab8500_btemp_suspend(struct platform_device *pdev,
 #define ab8500_btemp_resume       NULL
 #endif
 
-static int __devexit ab8500_btemp_remove(struct platform_device *pdev)
+static int ab8500_btemp_remove(struct platform_device *pdev)
 {
 	struct ab8500_btemp *di = platform_get_drvdata(pdev);
 	int i, irq;
@@ -955,56 +955,57 @@ static int __devexit ab8500_btemp_remove(struct platform_device *pdev)
 	flush_scheduled_work();
 	power_supply_unregister(&di->btemp_psy);
 	platform_set_drvdata(pdev, NULL);
-	kfree(di);
 
 	return 0;
 }
 
-static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
+static char *supply_interface[] = {
+	"ab8500_chargalg",
+	"ab8500_fg",
+};
+
+static int ab8500_btemp_probe(struct platform_device *pdev)
 {
+	struct device_node *np = pdev->dev.of_node;
+	struct ab8500_btemp *di;
 	int irq, i, ret = 0;
 	u8 val;
-	struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
-	struct ab8500_btemp *di;
-
-	if (!plat_data) {
-		dev_err(&pdev->dev, "No platform data\n");
-		return -EINVAL;
-	}
 
-	di = kzalloc(sizeof(*di), GFP_KERNEL);
-	if (!di)
+	di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+	if (!di) {
+		dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__);
 		return -ENOMEM;
+	}
+	di->bat = pdev->mfd_cell->platform_data;
+	if (!di->bat) {
+		if (np) {
+			ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
+			if (ret) {
+				dev_err(&pdev->dev,
+					"failed to get battery information\n");
+				return ret;
+			}
+		} else {
+			dev_err(&pdev->dev, "missing dt node for ab8500_btemp\n");
+			return -EINVAL;
+		}
+	} else {
+		dev_info(&pdev->dev, "falling back to legacy platform data\n");
+	}
 
 	/* get parent data */
 	di->dev = &pdev->dev;
 	di->parent = dev_get_drvdata(pdev->dev.parent);
 	di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
 
-	/* get btemp specific platform data */
-	di->pdata = plat_data->btemp;
-	if (!di->pdata) {
-		dev_err(di->dev, "no btemp platform data supplied\n");
-		ret = -EINVAL;
-		goto free_device_info;
-	}
-
-	/* get battery specific platform data */
-	di->bat = plat_data->battery;
-	if (!di->bat) {
-		dev_err(di->dev, "no battery platform data supplied\n");
-		ret = -EINVAL;
-		goto free_device_info;
-	}
-
 	/* BTEMP supply */
 	di->btemp_psy.name = "ab8500_btemp";
 	di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY;
 	di->btemp_psy.properties = ab8500_btemp_props;
 	di->btemp_psy.num_properties = ARRAY_SIZE(ab8500_btemp_props);
 	di->btemp_psy.get_property = ab8500_btemp_get_property;
-	di->btemp_psy.supplied_to = di->pdata->supplied_to;
-	di->btemp_psy.num_supplicants = di->pdata->num_supplicants;
+	di->btemp_psy.supplied_to = supply_interface;
+	di->btemp_psy.num_supplicants = ARRAY_SIZE(supply_interface);
 	di->btemp_psy.external_power_changed =
 		ab8500_btemp_external_power_changed;
 
@@ -1014,8 +1015,7 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
 		create_singlethread_workqueue("ab8500_btemp_wq");
 	if (di->btemp_wq == NULL) {
 		dev_err(di->dev, "failed to create work queue\n");
-		ret = -ENOMEM;
-		goto free_device_info;
+		return -ENOMEM;
 	}
 
 	/* Init work for measuring temperature periodically */
@@ -1093,20 +1093,23 @@ free_irq:
 	}
 free_btemp_wq:
 	destroy_workqueue(di->btemp_wq);
-free_device_info:
-	kfree(di);
-
 	return ret;
 }
 
+static const struct of_device_id ab8500_btemp_match[] = {
+	{ .compatible = "stericsson,ab8500-btemp", },
+	{ },
+};
+
 static struct platform_driver ab8500_btemp_driver = {
 	.probe = ab8500_btemp_probe,
-	.remove = __devexit_p(ab8500_btemp_remove),
+	.remove = ab8500_btemp_remove,
 	.suspend = ab8500_btemp_suspend,
 	.resume = ab8500_btemp_resume,
 	.driver = {
 		.name = "ab8500-btemp",
 		.owner = THIS_MODULE,
+		.of_match_table = ab8500_btemp_match,
 	},
 };
 
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 26ff759..3be9c0e 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -23,6 +23,8 @@
 #include <linux/err.h>
 #include <linux/workqueue.h>
 #include <linux/kobject.h>
+#include <linux/of.h>
+#include <linux/mfd/core.h>
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/mfd/abx500.h>
 #include <linux/mfd/abx500/ab8500-bm.h>
@@ -181,9 +183,9 @@ struct ab8500_charger_usb_state {
  * @vbat		Battery voltage
  * @old_vbat		Previously measured battery voltage
  * @autopower		Indicate if we should have automatic pwron after pwrloss
+ * @autopower_cfg	platform specific power config support for "pwron after pwrloss"
  * @parent:		Pointer to the struct ab8500
  * @gpadc:		Pointer to the struct gpadc
- * @pdata:		Pointer to the abx500_charger platform data
  * @bat:		Pointer to the abx500_bm platform data
  * @flags:		Structure for information about events triggered
  * @usb_state:		Structure for usb stack information
@@ -218,9 +220,9 @@ struct ab8500_charger {
 	int vbat;
 	int old_vbat;
 	bool autopower;
+	bool autopower_cfg;
 	struct ab8500 *parent;
 	struct ab8500_gpadc *gpadc;
-	struct abx500_charger_platform_data *pdata;
 	struct abx500_bm_data *bat;
 	struct ab8500_charger_event_flags flags;
 	struct ab8500_charger_usb_state usb_state;
@@ -322,7 +324,7 @@ static void ab8500_power_loss_handling(struct ab8500_charger *di)
 static void ab8500_power_supply_changed(struct ab8500_charger *di,
 					struct power_supply *psy)
 {
-	if (di->pdata->autopower_cfg) {
+	if (di->autopower_cfg) {
 		if (!di->usb.charger_connected &&
 		    !di->ac.charger_connected &&
 		    di->autopower) {
@@ -2490,7 +2492,7 @@ static int ab8500_charger_suspend(struct platform_device *pdev,
 #define ab8500_charger_resume       NULL
 #endif
 
-static int __devexit ab8500_charger_remove(struct platform_device *pdev)
+static int ab8500_charger_remove(struct platform_device *pdev)
 {
 	struct ab8500_charger *di = platform_get_drvdata(pdev);
 	int i, irq, ret;
@@ -2526,25 +2528,45 @@ static int __devexit ab8500_charger_remove(struct platform_device *pdev)
 	power_supply_unregister(&di->usb_chg.psy);
 	power_supply_unregister(&di->ac_chg.psy);
 	platform_set_drvdata(pdev, NULL);
-	kfree(di);
 
 	return 0;
 }
 
-static int __devinit ab8500_charger_probe(struct platform_device *pdev)
+static char *supply_interface[] = {
+	"ab8500_chargalg",
+	"ab8500_fg",
+	"ab8500_btemp",
+};
+
+static int ab8500_charger_probe(struct platform_device *pdev)
 {
-	int irq, i, charger_status, ret = 0;
-	struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
+	struct device_node *np = pdev->dev.of_node;
 	struct ab8500_charger *di;
+	int irq, i, charger_status, ret = 0;
 
-	if (!plat_data) {
-		dev_err(&pdev->dev, "No platform data\n");
-		return -EINVAL;
-	}
-
-	di = kzalloc(sizeof(*di), GFP_KERNEL);
-	if (!di)
+	di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+	if (!di) {
+		dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__);
 		return -ENOMEM;
+	}
+	di->bat = pdev->mfd_cell->platform_data;
+	if (!di->bat) {
+		if (np) {
+			ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
+			if (ret) {
+				dev_err(&pdev->dev,
+					"failed to get battery information\n");
+				return ret;
+			}
+			di->autopower_cfg = of_property_read_bool(np, "autopower_cfg");
+		} else {
+			dev_err(&pdev->dev, "missing dt node for ab8500_charger\n");
+			return -EINVAL;
+		}
+	} else {
+		dev_info(&pdev->dev, "falling back to legacy platform data\n");
+		di->autopower_cfg = false;
+	}
 
 	/* get parent data */
 	di->dev = &pdev->dev;
@@ -2554,22 +2576,6 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev)
 	/* initialize lock */
 	spin_lock_init(&di->usb_state.usb_lock);
 
-	/* get charger specific platform data */
-	di->pdata = plat_data->charger;
-	if (!di->pdata) {
-		dev_err(di->dev, "no charger platform data supplied\n");
-		ret = -EINVAL;
-		goto free_device_info;
-	}
-
-	/* get battery specific platform data */
-	di->bat = plat_data->battery;
-	if (!di->bat) {
-		dev_err(di->dev, "no battery platform data supplied\n");
-		ret = -EINVAL;
-		goto free_device_info;
-	}
-
 	di->autopower = false;
 
 	/* AC supply */
@@ -2579,8 +2585,8 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev)
 	di->ac_chg.psy.properties = ab8500_charger_ac_props;
 	di->ac_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_ac_props);
 	di->ac_chg.psy.get_property = ab8500_charger_ac_get_property;
-	di->ac_chg.psy.supplied_to = di->pdata->supplied_to;
-	di->ac_chg.psy.num_supplicants = di->pdata->num_supplicants;
+	di->ac_chg.psy.supplied_to = supply_interface;
+	di->ac_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface),
 	/* ux500_charger sub-class */
 	di->ac_chg.ops.enable = &ab8500_charger_ac_en;
 	di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
@@ -2597,8 +2603,8 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev)
 	di->usb_chg.psy.properties = ab8500_charger_usb_props;
 	di->usb_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_usb_props);
 	di->usb_chg.psy.get_property = ab8500_charger_usb_get_property;
-	di->usb_chg.psy.supplied_to = di->pdata->supplied_to;
-	di->usb_chg.psy.num_supplicants = di->pdata->num_supplicants;
+	di->usb_chg.psy.supplied_to = supply_interface;
+	di->usb_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface),
 	/* ux500_charger sub-class */
 	di->usb_chg.ops.enable = &ab8500_charger_usb_en;
 	di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
@@ -2614,8 +2620,7 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev)
 		create_singlethread_workqueue("ab8500_charger_wq");
 	if (di->charger_wq == NULL) {
 		dev_err(di->dev, "failed to create work queue\n");
-		ret = -ENOMEM;
-		goto free_device_info;
+		return -ENOMEM;
 	}
 
 	/* Init work for HW failure check */
@@ -2757,20 +2762,23 @@ free_regulator:
 	regulator_put(di->regu);
 free_charger_wq:
 	destroy_workqueue(di->charger_wq);
-free_device_info:
-	kfree(di);
-
 	return ret;
 }
 
+static const struct of_device_id ab8500_charger_match[] = {
+	{ .compatible = "stericsson,ab8500-charger", },
+	{ },
+};
+
 static struct platform_driver ab8500_charger_driver = {
 	.probe = ab8500_charger_probe,
-	.remove = __devexit_p(ab8500_charger_remove),
+	.remove = ab8500_charger_remove,
 	.suspend = ab8500_charger_suspend,
 	.resume = ab8500_charger_resume,
 	.driver = {
 		.name = "ab8500-charger",
 		.owner = THIS_MODULE,
+		.of_match_table = ab8500_charger_match,
 	},
 };
 
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 2db8cc2..b3bf178 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -22,15 +22,16 @@
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
 #include <linux/kobject.h>
-#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/abx500.h>
 #include <linux/slab.h>
-#include <linux/mfd/abx500/ab8500-bm.h>
 #include <linux/delay.h>
-#include <linux/mfd/abx500/ab8500-gpadc.h>
-#include <linux/mfd/abx500.h>
 #include <linux/time.h>
+#include <linux/of.h>
 #include <linux/completion.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/mfd/abx500/ab8500-bm.h>
+#include <linux/mfd/abx500/ab8500-gpadc.h>
 
 #define MILLI_TO_MICRO			1000
 #define FG_LSB_IN_MA			1627
@@ -172,7 +173,6 @@ struct inst_curr_result_list {
  * @avg_cap:		Average capacity filter
  * @parent:		Pointer to the struct ab8500
  * @gpadc:		Pointer to the struct gpadc
- * @pdata:		Pointer to the abx500_fg platform data
  * @bat:		Pointer to the abx500_bm platform data
  * @fg_psy:		Structure that holds the FG specific battery properties
  * @fg_wq:		Work queue for running the FG algorithm
@@ -212,7 +212,6 @@ struct ab8500_fg {
 	struct ab8500_fg_avg_cap avg_cap;
 	struct ab8500 *parent;
 	struct ab8500_gpadc *gpadc;
-	struct abx500_fg_platform_data *pdata;
 	struct abx500_bm_data *bat;
 	struct power_supply fg_psy;
 	struct workqueue_struct *fg_wq;
@@ -2411,7 +2410,7 @@ static int ab8500_fg_suspend(struct platform_device *pdev,
 #define ab8500_fg_resume       NULL
 #endif
 
-static int __devexit ab8500_fg_remove(struct platform_device *pdev)
+static int ab8500_fg_remove(struct platform_device *pdev)
 {
 	int ret = 0;
 	struct ab8500_fg *di = platform_get_drvdata(pdev);
@@ -2429,7 +2428,6 @@ static int __devexit ab8500_fg_remove(struct platform_device *pdev)
 	flush_scheduled_work();
 	power_supply_unregister(&di->fg_psy);
 	platform_set_drvdata(pdev, NULL);
-	kfree(di);
 	return ret;
 }
 
@@ -2442,21 +2440,39 @@ static struct ab8500_fg_interrupts ab8500_fg_irq[] = {
 	{"CCEOC", ab8500_fg_cc_data_end_handler},
 };
 
-static int __devinit ab8500_fg_probe(struct platform_device *pdev)
+static char *supply_interface[] = {
+	"ab8500_chargalg",
+	"ab8500_usb",
+};
+
+static int ab8500_fg_probe(struct platform_device *pdev)
 {
+	struct device_node *np = pdev->dev.of_node;
+	struct ab8500_fg *di;
 	int i, irq;
 	int ret = 0;
-	struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
-	struct ab8500_fg *di;
-
-	if (!plat_data) {
-		dev_err(&pdev->dev, "No platform data\n");
-		return -EINVAL;
-	}
 
-	di = kzalloc(sizeof(*di), GFP_KERNEL);
-	if (!di)
+	di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+	if (!di) {
+		dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__);
 		return -ENOMEM;
+	}
+	di->bat = pdev->mfd_cell->platform_data;
+	if (!di->bat) {
+		if (np) {
+			ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
+			if (ret) {
+				dev_err(&pdev->dev,
+					"failed to get battery information\n");
+				return ret;
+			}
+		} else {
+			dev_err(&pdev->dev, "missing dt node for ab8500_fg\n");
+			return -EINVAL;
+		}
+	} else {
+		dev_info(&pdev->dev, "falling back to legacy platform data\n");
+	}
 
 	mutex_init(&di->cc_lock);
 
@@ -2465,29 +2481,13 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev)
 	di->parent = dev_get_drvdata(pdev->dev.parent);
 	di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
 
-	/* get fg specific platform data */
-	di->pdata = plat_data->fg;
-	if (!di->pdata) {
-		dev_err(di->dev, "no fg platform data supplied\n");
-		ret = -EINVAL;
-		goto free_device_info;
-	}
-
-	/* get battery specific platform data */
-	di->bat = plat_data->battery;
-	if (!di->bat) {
-		dev_err(di->dev, "no battery platform data supplied\n");
-		ret = -EINVAL;
-		goto free_device_info;
-	}
-
 	di->fg_psy.name = "ab8500_fg";
 	di->fg_psy.type = POWER_SUPPLY_TYPE_BATTERY;
 	di->fg_psy.properties = ab8500_fg_props;
 	di->fg_psy.num_properties = ARRAY_SIZE(ab8500_fg_props);
 	di->fg_psy.get_property = ab8500_fg_get_property;
-	di->fg_psy.supplied_to = di->pdata->supplied_to;
-	di->fg_psy.num_supplicants = di->pdata->num_supplicants;
+	di->fg_psy.supplied_to = supply_interface;
+	di->fg_psy.num_supplicants = ARRAY_SIZE(supply_interface),
 	di->fg_psy.external_power_changed = ab8500_fg_external_power_changed;
 
 	di->bat_cap.max_mah_design = MILLI_TO_MICRO *
@@ -2506,8 +2506,7 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev)
 	di->fg_wq = create_singlethread_workqueue("ab8500_fg_wq");
 	if (di->fg_wq == NULL) {
 		dev_err(di->dev, "failed to create work queue\n");
-		ret = -ENOMEM;
-		goto free_device_info;
+		return -ENOMEM;
 	}
 
 	/* Init work for running the fg algorithm instantly */
@@ -2606,20 +2605,23 @@ free_irq:
 	}
 free_inst_curr_wq:
 	destroy_workqueue(di->fg_wq);
-free_device_info:
-	kfree(di);
-
 	return ret;
 }
 
+static const struct of_device_id ab8500_fg_match[] = {
+	{ .compatible = "stericsson,ab8500-fg", },
+	{ },
+};
+
 static struct platform_driver ab8500_fg_driver = {
 	.probe = ab8500_fg_probe,
-	.remove = __devexit_p(ab8500_fg_remove),
+	.remove = ab8500_fg_remove,
 	.suspend = ab8500_fg_suspend,
 	.resume = ab8500_fg_resume,
 	.driver = {
 		.name = "ab8500-fg",
 		.owner = THIS_MODULE,
+		.of_match_table = ab8500_fg_match,
 	},
 };
 
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index 4d30280..2970891 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -21,6 +21,8 @@
 #include <linux/completion.h>
 #include <linux/workqueue.h>
 #include <linux/kobject.h>
+#include <linux/of.h>
+#include <linux/mfd/core.h>
 #include <linux/mfd/abx500.h>
 #include <linux/mfd/abx500/ux500_chargalg.h>
 #include <linux/mfd/abx500/ab8500-bm.h>
@@ -205,7 +207,6 @@ enum maxim_ret {
  * @chg_info:		information about connected charger types
  * @batt_data:		data of the battery
  * @susp_status:	current charger suspension status
- * @pdata:		pointer to the abx500_chargalg platform data
  * @bat:		pointer to the abx500_bm platform data
  * @chargalg_psy:	structure that holds the battery properties exposed by
  *			the charging algorithm
@@ -231,7 +232,6 @@ struct abx500_chargalg {
 	struct abx500_chargalg_charger_info chg_info;
 	struct abx500_chargalg_battery_data batt_data;
 	struct abx500_chargalg_suspension_status susp_status;
-	struct abx500_chargalg_platform_data *pdata;
 	struct abx500_bm_data *bat;
 	struct power_supply chargalg_psy;
 	struct ux500_charger *ac_chg;
@@ -1782,7 +1782,7 @@ static int abx500_chargalg_suspend(struct platform_device *pdev,
 #define abx500_chargalg_resume       NULL
 #endif
 
-static int __devexit abx500_chargalg_remove(struct platform_device *pdev)
+static int abx500_chargalg_remove(struct platform_device *pdev)
 {
 	struct abx500_chargalg *di = platform_get_drvdata(pdev);
 
@@ -1795,36 +1795,53 @@ static int __devexit abx500_chargalg_remove(struct platform_device *pdev)
 	flush_scheduled_work();
 	power_supply_unregister(&di->chargalg_psy);
 	platform_set_drvdata(pdev, NULL);
-	kfree(di);
 
 	return 0;
 }
 
-static int __devinit abx500_chargalg_probe(struct platform_device *pdev)
+static char *supply_interface[] = {
+	"ab8500_fg",
+};
+
+static int abx500_chargalg_probe(struct platform_device *pdev)
 {
-	struct abx500_bm_plat_data *plat_data;
+	struct device_node *np = pdev->dev.of_node;
+	struct abx500_chargalg *di;
 	int ret = 0;
 
-	struct abx500_chargalg *di =
-		kzalloc(sizeof(struct abx500_chargalg), GFP_KERNEL);
-	if (!di)
+	di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+	if (!di) {
+		dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__);
 		return -ENOMEM;
+	}
+	di->bat = pdev->mfd_cell->platform_data;
+	if (!di->bat) {
+		if (np) {
+			ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
+			if (ret) {
+				dev_err(&pdev->dev,
+					"failed to get battery information\n");
+				return ret;
+			}
+		} else {
+			dev_err(&pdev->dev, "missing dt node for ab8500_chargalg\n");
+			return -EINVAL;
+		}
+	} else {
+		dev_info(&pdev->dev, "falling back to legacy platform data\n");
+	}
 
 	/* get device struct */
 	di->dev = &pdev->dev;
 
-	plat_data = pdev->dev.platform_data;
-	di->pdata = plat_data->chargalg;
-	di->bat = plat_data->battery;
-
 	/* chargalg supply */
 	di->chargalg_psy.name = "abx500_chargalg";
 	di->chargalg_psy.type = POWER_SUPPLY_TYPE_BATTERY;
 	di->chargalg_psy.properties = abx500_chargalg_props;
 	di->chargalg_psy.num_properties = ARRAY_SIZE(abx500_chargalg_props);
 	di->chargalg_psy.get_property = abx500_chargalg_get_property;
-	di->chargalg_psy.supplied_to = di->pdata->supplied_to;
-	di->chargalg_psy.num_supplicants = di->pdata->num_supplicants;
+	di->chargalg_psy.supplied_to = supply_interface;
+	di->chargalg_psy.num_supplicants = ARRAY_SIZE(supply_interface),
 	di->chargalg_psy.external_power_changed =
 		abx500_chargalg_external_power_changed;
 
@@ -1844,7 +1861,7 @@ static int __devinit abx500_chargalg_probe(struct platform_device *pdev)
 		create_singlethread_workqueue("abx500_chargalg_wq");
 	if (di->chargalg_wq == NULL) {
 		dev_err(di->dev, "failed to create work queue\n");
-		goto free_device_info;
+		return -ENOMEM;
 	}
 
 	/* Init work for chargalg */
@@ -1885,20 +1902,23 @@ free_psy:
 	power_supply_unregister(&di->chargalg_psy);
 free_chargalg_wq:
 	destroy_workqueue(di->chargalg_wq);
-free_device_info:
-	kfree(di);
-
 	return ret;
 }
 
+static const struct of_device_id ab8500_chargalg_match[] = {
+	{ .compatible = "stericsson,ab8500-chargalg", },
+	{ },
+};
+
 static struct platform_driver abx500_chargalg_driver = {
 	.probe = abx500_chargalg_probe,
-	.remove = __devexit_p(abx500_chargalg_remove),
+	.remove = abx500_chargalg_remove,
 	.suspend = abx500_chargalg_suspend,
 	.resume = abx500_chargalg_resume,
 	.driver = {
-		.name = "abx500-chargalg",
+		.name = "ab8500-chargalg",
 		.owner = THIS_MODULE,
+		.of_match_table = ab8500_chargalg_match,
 	},
 };
 
diff --git a/drivers/power/avs/smartreflex.c b/drivers/power/avs/smartreflex.c
index 24768a2..a17d084 100644
--- a/drivers/power/avs/smartreflex.c
+++ b/drivers/power/avs/smartreflex.c
@@ -130,24 +130,21 @@ static irqreturn_t sr_interrupt(int irq, void *data)
 
 static void sr_set_clk_length(struct omap_sr *sr)
 {
-	struct clk *sys_ck;
-	u32 sys_clk_speed;
+	struct clk *fck;
+	u32 fclk_speed;
 
-	if (cpu_is_omap34xx())
-		sys_ck = clk_get(NULL, "sys_ck");
-	else
-		sys_ck = clk_get(NULL, "sys_clkin_ck");
+	fck = clk_get(&sr->pdev->dev, "fck");
 
-	if (IS_ERR(sys_ck)) {
-		dev_err(&sr->pdev->dev, "%s: unable to get sys clk\n",
-			__func__);
+	if (IS_ERR(fck)) {
+		dev_err(&sr->pdev->dev, "%s: unable to get fck for device %s\n",
+				__func__, dev_name(&sr->pdev->dev));
 		return;
 	}
 
-	sys_clk_speed = clk_get_rate(sys_ck);
-	clk_put(sys_ck);
+	fclk_speed = clk_get_rate(fck);
+	clk_put(fck);
 
-	switch (sys_clk_speed) {
+	switch (fclk_speed) {
 	case 12000000:
 		sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK;
 		break;
@@ -164,34 +161,12 @@ static void sr_set_clk_length(struct omap_sr *sr)
 		sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK;
 		break;
 	default:
-		dev_err(&sr->pdev->dev, "%s: Invalid sysclk value: %d\n",
-			__func__, sys_clk_speed);
+		dev_err(&sr->pdev->dev, "%s: Invalid fclk rate: %d\n",
+			__func__, fclk_speed);
 		break;
 	}
 }
 
-static void sr_set_regfields(struct omap_sr *sr)
-{
-	/*
-	 * For time being these values are defined in smartreflex.h
-	 * and populated during init. May be they can be moved to board
-	 * file or pmic specific data structure. In that case these structure
-	 * fields will have to be populated using the pdata or pmic structure.
-	 */
-	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-		sr->err_weight = OMAP3430_SR_ERRWEIGHT;
-		sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
-		sr->accum_data = OMAP3430_SR_ACCUMDATA;
-		if (!(strcmp(sr->name, "smartreflex_mpu_iva"))) {
-			sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
-			sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
-		} else {
-			sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
-			sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
-		}
-	}
-}
-
 static void sr_start_vddautocomp(struct omap_sr *sr)
 {
 	if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
@@ -924,8 +899,14 @@ static int __init omap_sr_probe(struct platform_device *pdev)
 	sr_info->nvalue_count = pdata->nvalue_count;
 	sr_info->senn_mod = pdata->senn_mod;
 	sr_info->senp_mod = pdata->senp_mod;
+	sr_info->err_weight = pdata->err_weight;
+	sr_info->err_maxlimit = pdata->err_maxlimit;
+	sr_info->accum_data = pdata->accum_data;
+	sr_info->senn_avgweight = pdata->senn_avgweight;
+	sr_info->senp_avgweight = pdata->senp_avgweight;
 	sr_info->autocomp_active = false;
 	sr_info->ip_type = pdata->ip_type;
+
 	sr_info->base = ioremap(mem->start, resource_size(mem));
 	if (!sr_info->base) {
 		dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
@@ -937,7 +918,6 @@ static int __init omap_sr_probe(struct platform_device *pdev)
 		sr_info->irq = irq->start;
 
 	sr_set_clk_length(sr_info);
-	sr_set_regfields(sr_info);
 
 	list_add(&sr_info->node, &sr_list);
 
@@ -1026,7 +1006,7 @@ err_free_devinfo:
 	return ret;
 }
 
-static int __devexit omap_sr_remove(struct platform_device *pdev)
+static int omap_sr_remove(struct platform_device *pdev)
 {
 	struct omap_sr_data *pdata = pdev->dev.platform_data;
 	struct omap_sr *sr_info;
@@ -1059,7 +1039,7 @@ static int __devexit omap_sr_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static void __devexit omap_sr_shutdown(struct platform_device *pdev)
+static void omap_sr_shutdown(struct platform_device *pdev)
 {
 	struct omap_sr_data *pdata = pdev->dev.platform_data;
 	struct omap_sr *sr_info;
@@ -1083,8 +1063,8 @@ static void __devexit omap_sr_shutdown(struct platform_device *pdev)
 }
 
 static struct platform_driver smartreflex_driver = {
-	.remove         = __devexit_p(omap_sr_remove),
-	.shutdown	= __devexit_p(omap_sr_shutdown),
+	.remove         = omap_sr_remove,
+	.shutdown	= omap_sr_shutdown,
 	.driver		= {
 		.name	= "smartreflex",
 	},
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c
new file mode 100644
index 0000000..ee842b3
--- /dev/null
+++ b/drivers/power/bq2415x_charger.c
@@ -0,0 +1,1670 @@
+/*
+ * bq2415x charger driver
+ *
+ * Copyright (C) 2011-2012  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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have 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.
+ */
+
+/*
+ * Datasheets:
+ * http://www.ti.com/product/bq24150
+ * http://www.ti.com/product/bq24150a
+ * http://www.ti.com/product/bq24152
+ * http://www.ti.com/product/bq24153
+ * http://www.ti.com/product/bq24153a
+ * http://www.ti.com/product/bq24155
+ */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/err.h>
+#include <linux/workqueue.h>
+#include <linux/sysfs.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/idr.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+
+#include <linux/power/bq2415x_charger.h>
+
+/* timeout for resetting chip timer */
+#define BQ2415X_TIMER_TIMEOUT		10
+
+#define BQ2415X_REG_STATUS		0x00
+#define BQ2415X_REG_CONTROL		0x01
+#define BQ2415X_REG_VOLTAGE		0x02
+#define BQ2415X_REG_VENDER		0x03
+#define BQ2415X_REG_CURRENT		0x04
+
+/* reset state for all registers */
+#define BQ2415X_RESET_STATUS		BIT(6)
+#define BQ2415X_RESET_CONTROL		(BIT(4)|BIT(5))
+#define BQ2415X_RESET_VOLTAGE		(BIT(1)|BIT(3))
+#define BQ2415X_RESET_CURRENT		(BIT(0)|BIT(3)|BIT(7))
+
+/* status register */
+#define BQ2415X_BIT_TMR_RST		7
+#define BQ2415X_BIT_OTG			7
+#define BQ2415X_BIT_EN_STAT		6
+#define BQ2415X_MASK_STAT		(BIT(4)|BIT(5))
+#define BQ2415X_SHIFT_STAT		4
+#define BQ2415X_BIT_BOOST		3
+#define BQ2415X_MASK_FAULT		(BIT(0)|BIT(1)|BIT(2))
+#define BQ2415X_SHIFT_FAULT		0
+
+/* control register */
+#define BQ2415X_MASK_LIMIT		(BIT(6)|BIT(7))
+#define BQ2415X_SHIFT_LIMIT		6
+#define BQ2415X_MASK_VLOWV		(BIT(4)|BIT(5))
+#define BQ2415X_SHIFT_VLOWV		4
+#define BQ2415X_BIT_TE			3
+#define BQ2415X_BIT_CE			2
+#define BQ2415X_BIT_HZ_MODE		1
+#define BQ2415X_BIT_OPA_MODE		0
+
+/* voltage register */
+#define BQ2415X_MASK_VO		(BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7))
+#define BQ2415X_SHIFT_VO		2
+#define BQ2415X_BIT_OTG_PL		1
+#define BQ2415X_BIT_OTG_EN		0
+
+/* vender register */
+#define BQ2415X_MASK_VENDER		(BIT(5)|BIT(6)|BIT(7))
+#define BQ2415X_SHIFT_VENDER		5
+#define BQ2415X_MASK_PN			(BIT(3)|BIT(4))
+#define BQ2415X_SHIFT_PN		3
+#define BQ2415X_MASK_REVISION		(BIT(0)|BIT(1)|BIT(2))
+#define BQ2415X_SHIFT_REVISION		0
+
+/* current register */
+#define BQ2415X_MASK_RESET		BIT(7)
+#define BQ2415X_MASK_VI_CHRG		(BIT(4)|BIT(5)|BIT(6))
+#define BQ2415X_SHIFT_VI_CHRG		4
+/* N/A					BIT(3) */
+#define BQ2415X_MASK_VI_TERM		(BIT(0)|BIT(1)|BIT(2))
+#define BQ2415X_SHIFT_VI_TERM		0
+
+
+enum bq2415x_command {
+	BQ2415X_TIMER_RESET,
+	BQ2415X_OTG_STATUS,
+	BQ2415X_STAT_PIN_STATUS,
+	BQ2415X_STAT_PIN_ENABLE,
+	BQ2415X_STAT_PIN_DISABLE,
+	BQ2415X_CHARGE_STATUS,
+	BQ2415X_BOOST_STATUS,
+	BQ2415X_FAULT_STATUS,
+
+	BQ2415X_CHARGE_TERMINATION_STATUS,
+	BQ2415X_CHARGE_TERMINATION_ENABLE,
+	BQ2415X_CHARGE_TERMINATION_DISABLE,
+	BQ2415X_CHARGER_STATUS,
+	BQ2415X_CHARGER_ENABLE,
+	BQ2415X_CHARGER_DISABLE,
+	BQ2415X_HIGH_IMPEDANCE_STATUS,
+	BQ2415X_HIGH_IMPEDANCE_ENABLE,
+	BQ2415X_HIGH_IMPEDANCE_DISABLE,
+	BQ2415X_BOOST_MODE_STATUS,
+	BQ2415X_BOOST_MODE_ENABLE,
+	BQ2415X_BOOST_MODE_DISABLE,
+
+	BQ2415X_OTG_LEVEL,
+	BQ2415X_OTG_ACTIVATE_HIGH,
+	BQ2415X_OTG_ACTIVATE_LOW,
+	BQ2415X_OTG_PIN_STATUS,
+	BQ2415X_OTG_PIN_ENABLE,
+	BQ2415X_OTG_PIN_DISABLE,
+
+	BQ2415X_VENDER_CODE,
+	BQ2415X_PART_NUMBER,
+	BQ2415X_REVISION,
+};
+
+enum bq2415x_chip {
+	BQUNKNOWN,
+	BQ24150,
+	BQ24150A,
+	BQ24151,
+	BQ24151A,
+	BQ24152,
+	BQ24153,
+	BQ24153A,
+	BQ24155,
+	BQ24156,
+	BQ24156A,
+	BQ24158,
+};
+
+static char *bq2415x_chip_name[] = {
+	"unknown",
+	"bq24150",
+	"bq24150a",
+	"bq24151",
+	"bq24151a",
+	"bq24152",
+	"bq24153",
+	"bq24153a",
+	"bq24155",
+	"bq24156",
+	"bq24156a",
+	"bq24158",
+};
+
+struct bq2415x_device {
+	struct device *dev;
+	struct bq2415x_platform_data init_data;
+	struct power_supply charger;
+	struct delayed_work work;
+	enum bq2415x_mode reported_mode;/* mode reported by hook function */
+	enum bq2415x_mode mode;		/* current configured mode */
+	enum bq2415x_chip chip;
+	const char *timer_error;
+	char *model;
+	char *name;
+	int autotimer;	/* 1 - if driver automatically reset timer, 0 - not */
+	int automode;	/* 1 - enabled, 0 - disabled; -1 - not supported */
+	int id;
+};
+
+/* each registered chip must have unique id */
+static DEFINE_IDR(bq2415x_id);
+
+static DEFINE_MUTEX(bq2415x_id_mutex);
+static DEFINE_MUTEX(bq2415x_timer_mutex);
+static DEFINE_MUTEX(bq2415x_i2c_mutex);
+
+/**** i2c read functions ****/
+
+/* read value from register */
+static int bq2415x_i2c_read(struct bq2415x_device *bq, u8 reg)
+{
+	struct i2c_client *client = to_i2c_client(bq->dev);
+	struct i2c_msg msg[2];
+	u8 val;
+	int ret;
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	msg[0].addr = client->addr;
+	msg[0].flags = 0;
+	msg[0].buf = &reg;
+	msg[0].len = sizeof(reg);
+	msg[1].addr = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].buf = &val;
+	msg[1].len = sizeof(val);
+
+	mutex_lock(&bq2415x_i2c_mutex);
+	ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+	mutex_unlock(&bq2415x_i2c_mutex);
+
+	if (ret < 0)
+		return ret;
+
+	return val;
+}
+
+/* read value from register, apply mask and right shift it */
+static int bq2415x_i2c_read_mask(struct bq2415x_device *bq, u8 reg,
+				 u8 mask, u8 shift)
+{
+	int ret;
+
+	if (shift > 8)
+		return -EINVAL;
+
+	ret = bq2415x_i2c_read(bq, reg);
+	if (ret < 0)
+		return ret;
+	return (ret & mask) >> shift;
+}
+
+/* read value from register and return one specified bit */
+static int bq2415x_i2c_read_bit(struct bq2415x_device *bq, u8 reg, u8 bit)
+{
+	if (bit > 8)
+		return -EINVAL;
+	return bq2415x_i2c_read_mask(bq, reg, BIT(bit), bit);
+}
+
+/**** i2c write functions ****/
+
+/* write value to register */
+static int bq2415x_i2c_write(struct bq2415x_device *bq, u8 reg, u8 val)
+{
+	struct i2c_client *client = to_i2c_client(bq->dev);
+	struct i2c_msg msg[1];
+	u8 data[2];
+	int ret;
+
+	data[0] = reg;
+	data[1] = val;
+
+	msg[0].addr = client->addr;
+	msg[0].flags = 0;
+	msg[0].buf = data;
+	msg[0].len = ARRAY_SIZE(data);
+
+	mutex_lock(&bq2415x_i2c_mutex);
+	ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+	mutex_unlock(&bq2415x_i2c_mutex);
+
+	/* i2c_transfer returns number of messages transferred */
+	if (ret < 0)
+		return ret;
+	else if (ret != 1)
+		return -EIO;
+
+	return 0;
+}
+
+/* read value from register, change it with mask left shifted and write back */
+static int bq2415x_i2c_write_mask(struct bq2415x_device *bq, u8 reg, u8 val,
+				  u8 mask, u8 shift)
+{
+	int ret;
+
+	if (shift > 8)
+		return -EINVAL;
+
+	ret = bq2415x_i2c_read(bq, reg);
+	if (ret < 0)
+		return ret;
+
+	ret &= ~mask;
+	ret |= val << shift;
+
+	return bq2415x_i2c_write(bq, reg, ret);
+}
+
+/* change only one bit in register */
+static int bq2415x_i2c_write_bit(struct bq2415x_device *bq, u8 reg,
+				 bool val, u8 bit)
+{
+	if (bit > 8)
+		return -EINVAL;
+	return bq2415x_i2c_write_mask(bq, reg, val, BIT(bit), bit);
+}
+
+/**** global functions ****/
+
+/* exec command function */
+static int bq2415x_exec_command(struct bq2415x_device *bq,
+				enum bq2415x_command command)
+{
+	int ret;
+
+	switch (command) {
+	case BQ2415X_TIMER_RESET:
+		return bq2415x_i2c_write_bit(bq, BQ2415X_REG_STATUS,
+				1, BQ2415X_BIT_TMR_RST);
+	case BQ2415X_OTG_STATUS:
+		return bq2415x_i2c_read_bit(bq, BQ2415X_REG_STATUS,
+				BQ2415X_BIT_OTG);
+	case BQ2415X_STAT_PIN_STATUS:
+		return bq2415x_i2c_read_bit(bq, BQ2415X_REG_STATUS,
+				BQ2415X_BIT_EN_STAT);
+	case BQ2415X_STAT_PIN_ENABLE:
+		return bq2415x_i2c_write_bit(bq, BQ2415X_REG_STATUS, 1,
+				BQ2415X_BIT_EN_STAT);
+	case BQ2415X_STAT_PIN_DISABLE:
+		return bq2415x_i2c_write_bit(bq, BQ2415X_REG_STATUS, 0,
+				BQ2415X_BIT_EN_STAT);
+	case BQ2415X_CHARGE_STATUS:
+		return bq2415x_i2c_read_mask(bq, BQ2415X_REG_STATUS,
+				BQ2415X_MASK_STAT, BQ2415X_SHIFT_STAT);
+	case BQ2415X_BOOST_STATUS:
+		return bq2415x_i2c_read_bit(bq, BQ2415X_REG_STATUS,
+				BQ2415X_BIT_BOOST);
+	case BQ2415X_FAULT_STATUS:
+		return bq2415x_i2c_read_mask(bq, BQ2415X_REG_STATUS,
+			BQ2415X_MASK_FAULT, BQ2415X_SHIFT_FAULT);
+
+	case BQ2415X_CHARGE_TERMINATION_STATUS:
+		return bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL,
+				BQ2415X_BIT_TE);
+	case BQ2415X_CHARGE_TERMINATION_ENABLE:
+		return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
+				1, BQ2415X_BIT_TE);
+	case BQ2415X_CHARGE_TERMINATION_DISABLE:
+		return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
+				0, BQ2415X_BIT_TE);
+	case BQ2415X_CHARGER_STATUS:
+		ret = bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL,
+			BQ2415X_BIT_CE);
+		if (ret < 0)
+			return ret;
+		else
+			return ret > 0 ? 0 : 1;
+	case BQ2415X_CHARGER_ENABLE:
+		return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
+				0, BQ2415X_BIT_CE);
+	case BQ2415X_CHARGER_DISABLE:
+		return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
+				1, BQ2415X_BIT_CE);
+	case BQ2415X_HIGH_IMPEDANCE_STATUS:
+		return bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL,
+				BQ2415X_BIT_HZ_MODE);
+	case BQ2415X_HIGH_IMPEDANCE_ENABLE:
+		return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
+				1, BQ2415X_BIT_HZ_MODE);
+	case BQ2415X_HIGH_IMPEDANCE_DISABLE:
+		return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
+				0, BQ2415X_BIT_HZ_MODE);
+	case BQ2415X_BOOST_MODE_STATUS:
+		return bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL,
+				BQ2415X_BIT_OPA_MODE);
+	case BQ2415X_BOOST_MODE_ENABLE:
+		return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
+				1, BQ2415X_BIT_OPA_MODE);
+	case BQ2415X_BOOST_MODE_DISABLE:
+		return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
+				0, BQ2415X_BIT_OPA_MODE);
+
+	case BQ2415X_OTG_LEVEL:
+		return bq2415x_i2c_read_bit(bq, BQ2415X_REG_VOLTAGE,
+				BQ2415X_BIT_OTG_PL);
+	case BQ2415X_OTG_ACTIVATE_HIGH:
+		return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE,
+				1, BQ2415X_BIT_OTG_PL);
+	case BQ2415X_OTG_ACTIVATE_LOW:
+		return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE,
+				0, BQ2415X_BIT_OTG_PL);
+	case BQ2415X_OTG_PIN_STATUS:
+		return bq2415x_i2c_read_bit(bq, BQ2415X_REG_VOLTAGE,
+				BQ2415X_BIT_OTG_EN);
+	case BQ2415X_OTG_PIN_ENABLE:
+		return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE,
+				1, BQ2415X_BIT_OTG_EN);
+	case BQ2415X_OTG_PIN_DISABLE:
+		return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE,
+				0, BQ2415X_BIT_OTG_EN);
+
+	case BQ2415X_VENDER_CODE:
+		return bq2415x_i2c_read_mask(bq, BQ2415X_REG_VENDER,
+			BQ2415X_MASK_VENDER, BQ2415X_SHIFT_VENDER);
+	case BQ2415X_PART_NUMBER:
+		return bq2415x_i2c_read_mask(bq, BQ2415X_REG_VENDER,
+				BQ2415X_MASK_PN, BQ2415X_SHIFT_PN);
+	case BQ2415X_REVISION:
+		return bq2415x_i2c_read_mask(bq, BQ2415X_REG_VENDER,
+			BQ2415X_MASK_REVISION, BQ2415X_SHIFT_REVISION);
+	}
+	return -EINVAL;
+}
+
+/* detect chip type */
+static enum bq2415x_chip bq2415x_detect_chip(struct bq2415x_device *bq)
+{
+	struct i2c_client *client = to_i2c_client(bq->dev);
+	int ret = bq2415x_exec_command(bq, BQ2415X_PART_NUMBER);
+
+	if (ret < 0)
+		return ret;
+
+	switch (client->addr) {
+	case 0x6b:
+		switch (ret) {
+		case 0:
+			if (bq->chip == BQ24151A)
+				return bq->chip;
+			else
+				return BQ24151;
+		case 1:
+			if (bq->chip == BQ24150A ||
+				bq->chip == BQ24152 ||
+				bq->chip == BQ24155)
+				return bq->chip;
+			else
+				return BQ24150;
+		case 2:
+			if (bq->chip == BQ24153A)
+				return bq->chip;
+			else
+				return BQ24153;
+		default:
+			return BQUNKNOWN;
+		}
+		break;
+
+	case 0x6a:
+		switch (ret) {
+		case 0:
+			if (bq->chip == BQ24156A)
+				return bq->chip;
+			else
+				return BQ24156;
+		case 2:
+			return BQ24158;
+		default:
+			return BQUNKNOWN;
+		}
+		break;
+	}
+
+	return BQUNKNOWN;
+}
+
+/* detect chip revision */
+static int bq2415x_detect_revision(struct bq2415x_device *bq)
+{
+	int ret = bq2415x_exec_command(bq, BQ2415X_REVISION);
+	int chip = bq2415x_detect_chip(bq);
+
+	if (ret < 0 || chip < 0)
+		return -1;
+
+	switch (chip) {
+	case BQ24150:
+	case BQ24150A:
+	case BQ24151:
+	case BQ24151A:
+	case BQ24152:
+		if (ret >= 0 && ret <= 3)
+			return ret;
+		else
+			return -1;
+	case BQ24153:
+	case BQ24153A:
+	case BQ24156:
+	case BQ24156A:
+	case BQ24158:
+		if (ret == 3)
+			return 0;
+		else if (ret == 1)
+			return 1;
+		else
+			return -1;
+	case BQ24155:
+		if (ret == 3)
+			return 3;
+		else
+			return -1;
+	case BQUNKNOWN:
+		return -1;
+	}
+
+	return -1;
+}
+
+/* return chip vender code */
+static int bq2415x_get_vender_code(struct bq2415x_device *bq)
+{
+	int ret;
+
+	ret = bq2415x_exec_command(bq, BQ2415X_VENDER_CODE);
+	if (ret < 0)
+		return 0;
+
+	/* convert to binary */
+	return (ret & 0x1) +
+	       ((ret >> 1) & 0x1) * 10 +
+	       ((ret >> 2) & 0x1) * 100;
+}
+
+/* reset all chip registers to default state */
+static void bq2415x_reset_chip(struct bq2415x_device *bq)
+{
+	bq2415x_i2c_write(bq, BQ2415X_REG_CURRENT, BQ2415X_RESET_CURRENT);
+	bq2415x_i2c_write(bq, BQ2415X_REG_VOLTAGE, BQ2415X_RESET_VOLTAGE);
+	bq2415x_i2c_write(bq, BQ2415X_REG_CONTROL, BQ2415X_RESET_CONTROL);
+	bq2415x_i2c_write(bq, BQ2415X_REG_STATUS, BQ2415X_RESET_STATUS);
+	bq->timer_error = NULL;
+}
+
+/**** properties functions ****/
+
+/* set current limit in mA */
+static int bq2415x_set_current_limit(struct bq2415x_device *bq, int mA)
+{
+	int val;
+
+	if (mA <= 100)
+		val = 0;
+	else if (mA <= 500)
+		val = 1;
+	else if (mA <= 800)
+		val = 2;
+	else
+		val = 3;
+
+	return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CONTROL, val,
+			BQ2415X_MASK_LIMIT, BQ2415X_SHIFT_LIMIT);
+}
+
+/* get current limit in mA */
+static int bq2415x_get_current_limit(struct bq2415x_device *bq)
+{
+	int ret;
+
+	ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CONTROL,
+			BQ2415X_MASK_LIMIT, BQ2415X_SHIFT_LIMIT);
+	if (ret < 0)
+		return ret;
+	else if (ret == 0)
+		return 100;
+	else if (ret == 1)
+		return 500;
+	else if (ret == 2)
+		return 800;
+	else if (ret == 3)
+		return 1800;
+	return -EINVAL;
+}
+
+/* set weak battery voltage in mV */
+static int bq2415x_set_weak_battery_voltage(struct bq2415x_device *bq, int mV)
+{
+	int val;
+
+	/* round to 100mV */
+	if (mV <= 3400 + 50)
+		val = 0;
+	else if (mV <= 3500 + 50)
+		val = 1;
+	else if (mV <= 3600 + 50)
+		val = 2;
+	else
+		val = 3;
+
+	return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CONTROL, val,
+			BQ2415X_MASK_VLOWV, BQ2415X_SHIFT_VLOWV);
+}
+
+/* get weak battery voltage in mV */
+static int bq2415x_get_weak_battery_voltage(struct bq2415x_device *bq)
+{
+	int ret;
+
+	ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CONTROL,
+			BQ2415X_MASK_VLOWV, BQ2415X_SHIFT_VLOWV);
+	if (ret < 0)
+		return ret;
+	return 100 * (34 + ret);
+}
+
+/* set battery regulation voltage in mV */
+static int bq2415x_set_battery_regulation_voltage(struct bq2415x_device *bq,
+						  int mV)
+{
+	int val = (mV/10 - 350) / 2;
+
+	if (val < 0)
+		val = 0;
+	else if (val > 94) /* FIXME: Max is 94 or 122 ? Set max value ? */
+		return -EINVAL;
+
+	return bq2415x_i2c_write_mask(bq, BQ2415X_REG_VOLTAGE, val,
+			BQ2415X_MASK_VO, BQ2415X_SHIFT_VO);
+}
+
+/* get battery regulation voltage in mV */
+static int bq2415x_get_battery_regulation_voltage(struct bq2415x_device *bq)
+{
+	int ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_VOLTAGE,
+			BQ2415X_MASK_VO, BQ2415X_SHIFT_VO);
+
+	if (ret < 0)
+		return ret;
+	return 10 * (350 + 2*ret);
+}
+
+/* set charge current in mA (platform data must provide resistor sense) */
+static int bq2415x_set_charge_current(struct bq2415x_device *bq, int mA)
+{
+	int val;
+
+	if (bq->init_data.resistor_sense <= 0)
+		return -ENOSYS;
+
+	val = (mA * bq->init_data.resistor_sense - 37400) / 6800;
+	if (val < 0)
+		val = 0;
+	else if (val > 7)
+		val = 7;
+
+	return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CURRENT, val,
+			BQ2415X_MASK_VI_CHRG | BQ2415X_MASK_RESET,
+			BQ2415X_SHIFT_VI_CHRG);
+}
+
+/* get charge current in mA (platform data must provide resistor sense) */
+static int bq2415x_get_charge_current(struct bq2415x_device *bq)
+{
+	int ret;
+
+	if (bq->init_data.resistor_sense <= 0)
+		return -ENOSYS;
+
+	ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CURRENT,
+			BQ2415X_MASK_VI_CHRG, BQ2415X_SHIFT_VI_CHRG);
+	if (ret < 0)
+		return ret;
+	return (37400 + 6800*ret) / bq->init_data.resistor_sense;
+}
+
+/* set termination current in mA (platform data must provide resistor sense) */
+static int bq2415x_set_termination_current(struct bq2415x_device *bq, int mA)
+{
+	int val;
+
+	if (bq->init_data.resistor_sense <= 0)
+		return -ENOSYS;
+
+	val = (mA * bq->init_data.resistor_sense - 3400) / 3400;
+	if (val < 0)
+		val = 0;
+	else if (val > 7)
+		val = 7;
+
+	return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CURRENT, val,
+			BQ2415X_MASK_VI_TERM | BQ2415X_MASK_RESET,
+			BQ2415X_SHIFT_VI_TERM);
+}
+
+/* get termination current in mA (platform data must provide resistor sense) */
+static int bq2415x_get_termination_current(struct bq2415x_device *bq)
+{
+	int ret;
+
+	if (bq->init_data.resistor_sense <= 0)
+		return -ENOSYS;
+
+	ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CURRENT,
+			BQ2415X_MASK_VI_TERM, BQ2415X_SHIFT_VI_TERM);
+	if (ret < 0)
+		return ret;
+	return (3400 + 3400*ret) / bq->init_data.resistor_sense;
+}
+
+/* set default value of property */
+#define bq2415x_set_default_value(bq, prop) \
+	do { \
+		int ret = 0; \
+		if (bq->init_data.prop != -1) \
+			ret = bq2415x_set_##prop(bq, bq->init_data.prop); \
+		if (ret < 0) \
+			return ret; \
+	} while (0)
+
+/* set default values of all properties */
+static int bq2415x_set_defaults(struct bq2415x_device *bq)
+{
+	bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_DISABLE);
+	bq2415x_exec_command(bq, BQ2415X_CHARGER_DISABLE);
+	bq2415x_exec_command(bq, BQ2415X_CHARGE_TERMINATION_DISABLE);
+
+	bq2415x_set_default_value(bq, current_limit);
+	bq2415x_set_default_value(bq, weak_battery_voltage);
+	bq2415x_set_default_value(bq, battery_regulation_voltage);
+
+	if (bq->init_data.resistor_sense > 0) {
+		bq2415x_set_default_value(bq, charge_current);
+		bq2415x_set_default_value(bq, termination_current);
+		bq2415x_exec_command(bq, BQ2415X_CHARGE_TERMINATION_ENABLE);
+	}
+
+	bq2415x_exec_command(bq, BQ2415X_CHARGER_ENABLE);
+	return 0;
+}
+
+/**** charger mode functions ****/
+
+/* set charger mode */
+static int bq2415x_set_mode(struct bq2415x_device *bq, enum bq2415x_mode mode)
+{
+	int ret = 0;
+	int charger = 0;
+	int boost = 0;
+
+	if (mode == BQ2415X_MODE_HOST_CHARGER ||
+		mode == BQ2415X_MODE_DEDICATED_CHARGER)
+			charger = 1;
+
+	if (mode == BQ2415X_MODE_BOOST)
+		boost = 1;
+
+	if (!charger)
+		ret = bq2415x_exec_command(bq, BQ2415X_CHARGER_DISABLE);
+
+	if (!boost)
+		ret = bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_DISABLE);
+
+	if (ret < 0)
+		return ret;
+
+	switch (mode) {
+	case BQ2415X_MODE_NONE:
+		dev_dbg(bq->dev, "changing mode to: N/A\n");
+		ret = bq2415x_set_current_limit(bq, 100);
+		break;
+	case BQ2415X_MODE_HOST_CHARGER:
+		dev_dbg(bq->dev, "changing mode to: Host/HUB charger\n");
+		ret = bq2415x_set_current_limit(bq, 500);
+		break;
+	case BQ2415X_MODE_DEDICATED_CHARGER:
+		dev_dbg(bq->dev, "changing mode to: Dedicated charger\n");
+		ret = bq2415x_set_current_limit(bq, 1800);
+		break;
+	case BQ2415X_MODE_BOOST: /* Boost mode */
+		dev_dbg(bq->dev, "changing mode to: Boost\n");
+		ret = bq2415x_set_current_limit(bq, 100);
+		break;
+	}
+
+	if (ret < 0)
+		return ret;
+
+	if (charger)
+		ret = bq2415x_exec_command(bq, BQ2415X_CHARGER_ENABLE);
+	else if (boost)
+		ret = bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_ENABLE);
+
+	if (ret < 0)
+		return ret;
+
+	bq2415x_set_default_value(bq, weak_battery_voltage);
+	bq2415x_set_default_value(bq, battery_regulation_voltage);
+
+	bq->mode = mode;
+	sysfs_notify(&bq->charger.dev->kobj, NULL, "mode");
+
+	return 0;
+
+}
+
+/* hook function called by other driver which set reported mode */
+static void bq2415x_hook_function(enum bq2415x_mode mode, void *data)
+{
+	struct bq2415x_device *bq = data;
+
+	if (!bq)
+		return;
+
+	dev_dbg(bq->dev, "hook function was called\n");
+	bq->reported_mode = mode;
+
+	/* if automode is not enabled do not tell about reported_mode */
+	if (bq->automode < 1)
+		return;
+
+	sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode");
+	bq2415x_set_mode(bq, bq->reported_mode);
+
+}
+
+/**** timer functions ****/
+
+/* enable/disable auto resetting chip timer */
+static void bq2415x_set_autotimer(struct bq2415x_device *bq, int state)
+{
+	mutex_lock(&bq2415x_timer_mutex);
+
+	if (bq->autotimer == state) {
+		mutex_unlock(&bq2415x_timer_mutex);
+		return;
+	}
+
+	bq->autotimer = state;
+
+	if (state) {
+		schedule_delayed_work(&bq->work, BQ2415X_TIMER_TIMEOUT * HZ);
+		bq2415x_exec_command(bq, BQ2415X_TIMER_RESET);
+		bq->timer_error = NULL;
+	} else {
+		cancel_delayed_work_sync(&bq->work);
+	}
+
+	mutex_unlock(&bq2415x_timer_mutex);
+}
+
+/* called by bq2415x_timer_work on timer error */
+static void bq2415x_timer_error(struct bq2415x_device *bq, const char *msg)
+{
+	bq->timer_error = msg;
+	sysfs_notify(&bq->charger.dev->kobj, NULL, "timer");
+	dev_err(bq->dev, "%s\n", msg);
+	if (bq->automode > 0)
+		bq->automode = 0;
+	bq2415x_set_mode(bq, BQ2415X_MODE_NONE);
+	bq2415x_set_autotimer(bq, 0);
+}
+
+/* delayed work function for auto resetting chip timer */
+static void bq2415x_timer_work(struct work_struct *work)
+{
+	struct bq2415x_device *bq = container_of(work, struct bq2415x_device,
+						 work.work);
+	int ret;
+	int error;
+	int boost;
+
+	if (!bq->autotimer)
+		return;
+
+	ret = bq2415x_exec_command(bq, BQ2415X_TIMER_RESET);
+	if (ret < 0) {
+		bq2415x_timer_error(bq, "Resetting timer failed");
+		return;
+	}
+
+	boost = bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_STATUS);
+	if (boost < 0) {
+		bq2415x_timer_error(bq, "Unknown error");
+		return;
+	}
+
+	error = bq2415x_exec_command(bq, BQ2415X_FAULT_STATUS);
+	if (error < 0) {
+		bq2415x_timer_error(bq, "Unknown error");
+		return;
+	}
+
+	if (boost) {
+		switch (error) {
+		/* Non fatal errors, chip is OK */
+		case 0: /* No error */
+			break;
+		case 6: /* Timer expired */
+			dev_err(bq->dev, "Timer expired\n");
+			break;
+		case 3: /* Battery voltage too low */
+			dev_err(bq->dev, "Battery voltage to low\n");
+			break;
+
+		/* Fatal errors, disable and reset chip */
+		case 1: /* Overvoltage protection (chip fried) */
+			bq2415x_timer_error(bq,
+				"Overvoltage protection (chip fried)");
+			return;
+		case 2: /* Overload */
+			bq2415x_timer_error(bq, "Overload");
+			return;
+		case 4: /* Battery overvoltage protection */
+			bq2415x_timer_error(bq,
+				"Battery overvoltage protection");
+			return;
+		case 5: /* Thermal shutdown (too hot) */
+			bq2415x_timer_error(bq,
+					"Thermal shutdown (too hot)");
+			return;
+		case 7: /* N/A */
+			bq2415x_timer_error(bq, "Unknown error");
+			return;
+		}
+	} else {
+		switch (error) {
+		/* Non fatal errors, chip is OK */
+		case 0: /* No error */
+			break;
+		case 2: /* Sleep mode */
+			dev_err(bq->dev, "Sleep mode\n");
+			break;
+		case 3: /* Poor input source */
+			dev_err(bq->dev, "Poor input source\n");
+			break;
+		case 6: /* Timer expired */
+			dev_err(bq->dev, "Timer expired\n");
+			break;
+		case 7: /* No battery */
+			dev_err(bq->dev, "No battery\n");
+			break;
+
+		/* Fatal errors, disable and reset chip */
+		case 1: /* Overvoltage protection (chip fried) */
+			bq2415x_timer_error(bq,
+				"Overvoltage protection (chip fried)");
+			return;
+		case 4: /* Battery overvoltage protection */
+			bq2415x_timer_error(bq,
+				"Battery overvoltage protection");
+			return;
+		case 5: /* Thermal shutdown (too hot) */
+			bq2415x_timer_error(bq,
+				"Thermal shutdown (too hot)");
+			return;
+		}
+	}
+
+	schedule_delayed_work(&bq->work, BQ2415X_TIMER_TIMEOUT * HZ);
+}
+
+/**** power supply interface code ****/
+
+static enum power_supply_property bq2415x_power_supply_props[] = {
+	/* TODO: maybe add more power supply properties */
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_MODEL_NAME,
+};
+
+static int bq2415x_power_supply_get_property(struct power_supply *psy,
+					     enum power_supply_property psp,
+					     union power_supply_propval *val)
+{
+	struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+						 charger);
+	int ret;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_STATUS:
+		ret = bq2415x_exec_command(bq, BQ2415X_CHARGE_STATUS);
+		if (ret < 0)
+			return ret;
+		else if (ret == 0) /* Ready */
+			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+		else if (ret == 1) /* Charge in progress */
+			val->intval = POWER_SUPPLY_STATUS_CHARGING;
+		else if (ret == 2) /* Charge done */
+			val->intval = POWER_SUPPLY_STATUS_FULL;
+		else
+			val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+		break;
+	case POWER_SUPPLY_PROP_MODEL_NAME:
+		val->strval = bq->model;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int bq2415x_power_supply_init(struct bq2415x_device *bq)
+{
+	int ret;
+	int chip;
+	char revstr[8];
+
+	bq->charger.name = bq->name;
+	bq->charger.type = POWER_SUPPLY_TYPE_USB;
+	bq->charger.properties = bq2415x_power_supply_props;
+	bq->charger.num_properties = ARRAY_SIZE(bq2415x_power_supply_props);
+	bq->charger.get_property = bq2415x_power_supply_get_property;
+
+	ret = bq2415x_detect_chip(bq);
+	if (ret < 0)
+		chip = BQUNKNOWN;
+	else
+		chip = ret;
+
+	ret = bq2415x_detect_revision(bq);
+	if (ret < 0)
+		strcpy(revstr, "unknown");
+	else
+		sprintf(revstr, "1.%d", ret);
+
+	bq->model = kasprintf(GFP_KERNEL,
+				"chip %s, revision %s, vender code %.3d",
+				bq2415x_chip_name[chip], revstr,
+				bq2415x_get_vender_code(bq));
+	if (!bq->model) {
+		dev_err(bq->dev, "failed to allocate model name\n");
+		return -ENOMEM;
+	}
+
+	ret = power_supply_register(bq->dev, &bq->charger);
+	if (ret) {
+		kfree(bq->model);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void bq2415x_power_supply_exit(struct bq2415x_device *bq)
+{
+	bq->autotimer = 0;
+	if (bq->automode > 0)
+		bq->automode = 0;
+	cancel_delayed_work_sync(&bq->work);
+	power_supply_unregister(&bq->charger);
+	kfree(bq->model);
+}
+
+/**** additional sysfs entries for power supply interface ****/
+
+/* show *_status entries */
+static ssize_t bq2415x_sysfs_show_status(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+						charger);
+	enum bq2415x_command command;
+	int ret;
+
+	if (strcmp(attr->attr.name, "otg_status") == 0)
+		command = BQ2415X_OTG_STATUS;
+	else if (strcmp(attr->attr.name, "charge_status") == 0)
+		command = BQ2415X_CHARGE_STATUS;
+	else if (strcmp(attr->attr.name, "boost_status") == 0)
+		command = BQ2415X_BOOST_STATUS;
+	else if (strcmp(attr->attr.name, "fault_status") == 0)
+		command = BQ2415X_FAULT_STATUS;
+	else
+		return -EINVAL;
+
+	ret = bq2415x_exec_command(bq, command);
+	if (ret < 0)
+		return ret;
+	return sprintf(buf, "%d\n", ret);
+}
+
+/*
+ * set timer entry:
+ *    auto - enable auto mode
+ *    off - disable auto mode
+ *    (other values) - reset chip timer
+ */
+static ssize_t bq2415x_sysfs_set_timer(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf,
+				       size_t count)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+						charger);
+	int ret = 0;
+
+	if (strncmp(buf, "auto", 4) == 0)
+		bq2415x_set_autotimer(bq, 1);
+	else if (strncmp(buf, "off", 3) == 0)
+		bq2415x_set_autotimer(bq, 0);
+	else
+		ret = bq2415x_exec_command(bq, BQ2415X_TIMER_RESET);
+
+	if (ret < 0)
+		return ret;
+	return count;
+}
+
+/* show timer entry (auto or off) */
+static ssize_t bq2415x_sysfs_show_timer(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+						 charger);
+
+	if (bq->timer_error)
+		return sprintf(buf, "%s\n", bq->timer_error);
+
+	if (bq->autotimer)
+		return sprintf(buf, "auto\n");
+	return sprintf(buf, "off\n");
+}
+
+/*
+ * set mode entry:
+ *    auto - if automode is supported, enable it and set mode to reported
+ *    none - disable charger and boost mode
+ *    host - charging mode for host/hub chargers (current limit 500mA)
+ *    dedicated - charging mode for dedicated chargers (unlimited current limit)
+ *    boost - disable charger and enable boost mode
+ */
+static ssize_t bq2415x_sysfs_set_mode(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf,
+				      size_t count)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+						 charger);
+	enum bq2415x_mode mode;
+	int ret = 0;
+
+	if (strncmp(buf, "auto", 4) == 0) {
+		if (bq->automode < 0)
+			return -ENOSYS;
+		bq->automode = 1;
+		mode = bq->reported_mode;
+	} else if (strncmp(buf, "none", 4) == 0) {
+		if (bq->automode > 0)
+			bq->automode = 0;
+		mode = BQ2415X_MODE_NONE;
+	} else if (strncmp(buf, "host", 4) == 0) {
+		if (bq->automode > 0)
+			bq->automode = 0;
+		mode = BQ2415X_MODE_HOST_CHARGER;
+	} else if (strncmp(buf, "dedicated", 9) == 0) {
+		if (bq->automode > 0)
+			bq->automode = 0;
+		mode = BQ2415X_MODE_DEDICATED_CHARGER;
+	} else if (strncmp(buf, "boost", 5) == 0) {
+		if (bq->automode > 0)
+			bq->automode = 0;
+		mode = BQ2415X_MODE_BOOST;
+	} else if (strncmp(buf, "reset", 5) == 0) {
+		bq2415x_reset_chip(bq);
+		bq2415x_set_defaults(bq);
+		if (bq->automode <= 0)
+			return count;
+		bq->automode = 1;
+		mode = bq->reported_mode;
+	} else {
+		return -EINVAL;
+	}
+
+	ret = bq2415x_set_mode(bq, mode);
+	if (ret < 0)
+		return ret;
+	return count;
+}
+
+/* show mode entry (auto, none, host, dedicated or boost) */
+static ssize_t bq2415x_sysfs_show_mode(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+						charger);
+	ssize_t ret = 0;
+
+	if (bq->automode > 0)
+		ret += sprintf(buf+ret, "auto (");
+
+	switch (bq->mode) {
+	case BQ2415X_MODE_NONE:
+		ret += sprintf(buf+ret, "none");
+		break;
+	case BQ2415X_MODE_HOST_CHARGER:
+		ret += sprintf(buf+ret, "host");
+		break;
+	case BQ2415X_MODE_DEDICATED_CHARGER:
+		ret += sprintf(buf+ret, "dedicated");
+		break;
+	case BQ2415X_MODE_BOOST:
+		ret += sprintf(buf+ret, "boost");
+		break;
+	}
+
+	if (bq->automode > 0)
+		ret += sprintf(buf+ret, ")");
+
+	ret += sprintf(buf+ret, "\n");
+	return ret;
+}
+
+/* show reported_mode entry (none, host, dedicated or boost) */
+static ssize_t bq2415x_sysfs_show_reported_mode(struct device *dev,
+						struct device_attribute *attr,
+						char *buf)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+						 charger);
+
+	if (bq->automode < 0)
+		return -EINVAL;
+
+	switch (bq->reported_mode) {
+	case BQ2415X_MODE_NONE:
+		return sprintf(buf, "none\n");
+	case BQ2415X_MODE_HOST_CHARGER:
+		return sprintf(buf, "host\n");
+	case BQ2415X_MODE_DEDICATED_CHARGER:
+		return sprintf(buf, "dedicated\n");
+	case BQ2415X_MODE_BOOST:
+		return sprintf(buf, "boost\n");
+	}
+
+	return -EINVAL;
+}
+
+/* directly set raw value to chip register, format: 'register value' */
+static ssize_t bq2415x_sysfs_set_registers(struct device *dev,
+					   struct device_attribute *attr,
+					   const char *buf,
+					   size_t count)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+						 charger);
+	ssize_t ret = 0;
+	unsigned int reg;
+	unsigned int val;
+
+	if (sscanf(buf, "%x %x", &reg, &val) != 2)
+		return -EINVAL;
+
+	if (reg > 4 || val > 255)
+		return -EINVAL;
+
+	ret = bq2415x_i2c_write(bq, reg, val);
+	if (ret < 0)
+		return ret;
+	return count;
+}
+
+/* print value of chip register, format: 'register=value' */
+static ssize_t bq2415x_sysfs_print_reg(struct bq2415x_device *bq,
+				       u8 reg,
+				       char *buf)
+{
+	int ret = bq2415x_i2c_read(bq, reg);
+
+	if (ret < 0)
+		return sprintf(buf, "%#.2x=error %d\n", reg, ret);
+	return sprintf(buf, "%#.2x=%#.2x\n", reg, ret);
+}
+
+/* show all raw values of chip register, format per line: 'register=value' */
+static ssize_t bq2415x_sysfs_show_registers(struct device *dev,
+					    struct device_attribute *attr,
+					    char *buf)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+						 charger);
+	ssize_t ret = 0;
+
+	ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_STATUS, buf+ret);
+	ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_CONTROL, buf+ret);
+	ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_VOLTAGE, buf+ret);
+	ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_VENDER, buf+ret);
+	ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_CURRENT, buf+ret);
+	return ret;
+}
+
+/* set current and voltage limit entries (in mA or mV) */
+static ssize_t bq2415x_sysfs_set_limit(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf,
+				       size_t count)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+						 charger);
+	long val;
+	int ret;
+
+	if (kstrtol(buf, 10, &val) < 0)
+		return -EINVAL;
+
+	if (strcmp(attr->attr.name, "current_limit") == 0)
+		ret = bq2415x_set_current_limit(bq, val);
+	else if (strcmp(attr->attr.name, "weak_battery_voltage") == 0)
+		ret = bq2415x_set_weak_battery_voltage(bq, val);
+	else if (strcmp(attr->attr.name, "battery_regulation_voltage") == 0)
+		ret = bq2415x_set_battery_regulation_voltage(bq, val);
+	else if (strcmp(attr->attr.name, "charge_current") == 0)
+		ret = bq2415x_set_charge_current(bq, val);
+	else if (strcmp(attr->attr.name, "termination_current") == 0)
+		ret = bq2415x_set_termination_current(bq, val);
+	else
+		return -EINVAL;
+
+	if (ret < 0)
+		return ret;
+	return count;
+}
+
+/* show current and voltage limit entries (in mA or mV) */
+static ssize_t bq2415x_sysfs_show_limit(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+						 charger);
+	int ret;
+
+	if (strcmp(attr->attr.name, "current_limit") == 0)
+		ret = bq2415x_get_current_limit(bq);
+	else if (strcmp(attr->attr.name, "weak_battery_voltage") == 0)
+		ret = bq2415x_get_weak_battery_voltage(bq);
+	else if (strcmp(attr->attr.name, "battery_regulation_voltage") == 0)
+		ret = bq2415x_get_battery_regulation_voltage(bq);
+	else if (strcmp(attr->attr.name, "charge_current") == 0)
+		ret = bq2415x_get_charge_current(bq);
+	else if (strcmp(attr->attr.name, "termination_current") == 0)
+		ret = bq2415x_get_termination_current(bq);
+	else
+		return -EINVAL;
+
+	if (ret < 0)
+		return ret;
+	return sprintf(buf, "%d\n", ret);
+}
+
+/* set *_enable entries */
+static ssize_t bq2415x_sysfs_set_enable(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf,
+					size_t count)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+						 charger);
+	enum bq2415x_command command;
+	long val;
+	int ret;
+
+	if (kstrtol(buf, 10, &val) < 0)
+		return -EINVAL;
+
+	if (strcmp(attr->attr.name, "charge_termination_enable") == 0)
+		command = val ? BQ2415X_CHARGE_TERMINATION_ENABLE :
+			BQ2415X_CHARGE_TERMINATION_DISABLE;
+	else if (strcmp(attr->attr.name, "high_impedance_enable") == 0)
+		command = val ? BQ2415X_HIGH_IMPEDANCE_ENABLE :
+			BQ2415X_HIGH_IMPEDANCE_DISABLE;
+	else if (strcmp(attr->attr.name, "otg_pin_enable") == 0)
+		command = val ? BQ2415X_OTG_PIN_ENABLE :
+			BQ2415X_OTG_PIN_DISABLE;
+	else if (strcmp(attr->attr.name, "stat_pin_enable") == 0)
+		command = val ? BQ2415X_STAT_PIN_ENABLE :
+			BQ2415X_STAT_PIN_DISABLE;
+	else
+		return -EINVAL;
+
+	ret = bq2415x_exec_command(bq, command);
+	if (ret < 0)
+		return ret;
+	return count;
+}
+
+/* show *_enable entries */
+static ssize_t bq2415x_sysfs_show_enable(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq2415x_device *bq = container_of(psy, struct bq2415x_device,
+						 charger);
+	enum bq2415x_command command;
+	int ret;
+
+	if (strcmp(attr->attr.name, "charge_termination_enable") == 0)
+		command = BQ2415X_CHARGE_TERMINATION_STATUS;
+	else if (strcmp(attr->attr.name, "high_impedance_enable") == 0)
+		command = BQ2415X_HIGH_IMPEDANCE_STATUS;
+	else if (strcmp(attr->attr.name, "otg_pin_enable") == 0)
+		command = BQ2415X_OTG_PIN_STATUS;
+	else if (strcmp(attr->attr.name, "stat_pin_enable") == 0)
+		command = BQ2415X_STAT_PIN_STATUS;
+	else
+		return -EINVAL;
+
+	ret = bq2415x_exec_command(bq, command);
+	if (ret < 0)
+		return ret;
+	return sprintf(buf, "%d\n", ret);
+}
+
+static DEVICE_ATTR(current_limit, S_IWUSR | S_IRUGO,
+		bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit);
+static DEVICE_ATTR(weak_battery_voltage, S_IWUSR | S_IRUGO,
+		bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit);
+static DEVICE_ATTR(battery_regulation_voltage, S_IWUSR | S_IRUGO,
+		bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit);
+static DEVICE_ATTR(charge_current, S_IWUSR | S_IRUGO,
+		bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit);
+static DEVICE_ATTR(termination_current, S_IWUSR | S_IRUGO,
+		bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit);
+
+static DEVICE_ATTR(charge_termination_enable, S_IWUSR | S_IRUGO,
+		bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable);
+static DEVICE_ATTR(high_impedance_enable, S_IWUSR | S_IRUGO,
+		bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable);
+static DEVICE_ATTR(otg_pin_enable, S_IWUSR | S_IRUGO,
+		bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable);
+static DEVICE_ATTR(stat_pin_enable, S_IWUSR | S_IRUGO,
+		bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable);
+
+static DEVICE_ATTR(reported_mode, S_IRUGO,
+		bq2415x_sysfs_show_reported_mode, NULL);
+static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO,
+		bq2415x_sysfs_show_mode, bq2415x_sysfs_set_mode);
+static DEVICE_ATTR(timer, S_IWUSR | S_IRUGO,
+		bq2415x_sysfs_show_timer, bq2415x_sysfs_set_timer);
+
+static DEVICE_ATTR(registers, S_IWUSR | S_IRUGO,
+		bq2415x_sysfs_show_registers, bq2415x_sysfs_set_registers);
+
+static DEVICE_ATTR(otg_status, S_IRUGO, bq2415x_sysfs_show_status, NULL);
+static DEVICE_ATTR(charge_status, S_IRUGO, bq2415x_sysfs_show_status, NULL);
+static DEVICE_ATTR(boost_status, S_IRUGO, bq2415x_sysfs_show_status, NULL);
+static DEVICE_ATTR(fault_status, S_IRUGO, bq2415x_sysfs_show_status, NULL);
+
+static struct attribute *bq2415x_sysfs_attributes[] = {
+	/*
+	 * TODO: some (appropriate) of these attrs should be switched to
+	 * use power supply class props.
+	 */
+	&dev_attr_current_limit.attr,
+	&dev_attr_weak_battery_voltage.attr,
+	&dev_attr_battery_regulation_voltage.attr,
+	&dev_attr_charge_current.attr,
+	&dev_attr_termination_current.attr,
+
+	&dev_attr_charge_termination_enable.attr,
+	&dev_attr_high_impedance_enable.attr,
+	&dev_attr_otg_pin_enable.attr,
+	&dev_attr_stat_pin_enable.attr,
+
+	&dev_attr_reported_mode.attr,
+	&dev_attr_mode.attr,
+	&dev_attr_timer.attr,
+
+	&dev_attr_registers.attr,
+
+	&dev_attr_otg_status.attr,
+	&dev_attr_charge_status.attr,
+	&dev_attr_boost_status.attr,
+	&dev_attr_fault_status.attr,
+	NULL,
+};
+
+static const struct attribute_group bq2415x_sysfs_attr_group = {
+	.attrs = bq2415x_sysfs_attributes,
+};
+
+static int bq2415x_sysfs_init(struct bq2415x_device *bq)
+{
+	return sysfs_create_group(&bq->charger.dev->kobj,
+			&bq2415x_sysfs_attr_group);
+}
+
+static void bq2415x_sysfs_exit(struct bq2415x_device *bq)
+{
+	sysfs_remove_group(&bq->charger.dev->kobj, &bq2415x_sysfs_attr_group);
+}
+
+/* main bq2415x probe function */
+static int bq2415x_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	int ret;
+	int num;
+	char *name;
+	struct bq2415x_device *bq;
+
+	if (!client->dev.platform_data) {
+		dev_err(&client->dev, "platform data not set\n");
+		return -ENODEV;
+	}
+
+	/* Get new ID for the new device */
+	ret = idr_pre_get(&bq2415x_id, GFP_KERNEL);
+	if (ret == 0)
+		return -ENOMEM;
+
+	mutex_lock(&bq2415x_id_mutex);
+	ret = idr_get_new(&bq2415x_id, client, &num);
+	mutex_unlock(&bq2415x_id_mutex);
+
+	if (ret < 0)
+		return ret;
+
+	name = kasprintf(GFP_KERNEL, "%s-%d", id->name, num);
+	if (!name) {
+		dev_err(&client->dev, "failed to allocate device name\n");
+		ret = -ENOMEM;
+		goto error_1;
+	}
+
+	bq = kzalloc(sizeof(*bq), GFP_KERNEL);
+	if (!bq) {
+		dev_err(&client->dev, "failed to allocate device data\n");
+		ret = -ENOMEM;
+		goto error_2;
+	}
+
+	i2c_set_clientdata(client, bq);
+
+	bq->id = num;
+	bq->dev = &client->dev;
+	bq->chip = id->driver_data;
+	bq->name = name;
+	bq->mode = BQ2415X_MODE_NONE;
+	bq->reported_mode = BQ2415X_MODE_NONE;
+	bq->autotimer = 0;
+	bq->automode = 0;
+
+	memcpy(&bq->init_data, client->dev.platform_data,
+			sizeof(bq->init_data));
+
+	bq2415x_reset_chip(bq);
+
+	ret = bq2415x_power_supply_init(bq);
+	if (ret) {
+		dev_err(bq->dev, "failed to register power supply: %d\n", ret);
+		goto error_3;
+	}
+
+	ret = bq2415x_sysfs_init(bq);
+	if (ret) {
+		dev_err(bq->dev, "failed to create sysfs entries: %d\n", ret);
+		goto error_4;
+	}
+
+	ret = bq2415x_set_defaults(bq);
+	if (ret) {
+		dev_err(bq->dev, "failed to set default values: %d\n", ret);
+		goto error_5;
+	}
+
+	if (bq->init_data.set_mode_hook) {
+		if (bq->init_data.set_mode_hook(
+				bq2415x_hook_function, bq)) {
+			bq->automode = 1;
+			bq2415x_set_mode(bq, bq->reported_mode);
+			dev_info(bq->dev, "automode enabled\n");
+		} else {
+			bq->automode = -1;
+			dev_info(bq->dev, "automode failed\n");
+		}
+	} else {
+		bq->automode = -1;
+		dev_info(bq->dev, "automode not supported\n");
+	}
+
+	INIT_DELAYED_WORK(&bq->work, bq2415x_timer_work);
+	bq2415x_set_autotimer(bq, 1);
+
+	dev_info(bq->dev, "driver registered\n");
+	return 0;
+
+error_5:
+	bq2415x_sysfs_exit(bq);
+error_4:
+	bq2415x_power_supply_exit(bq);
+error_3:
+	kfree(bq);
+error_2:
+	kfree(name);
+error_1:
+	mutex_lock(&bq2415x_id_mutex);
+	idr_remove(&bq2415x_id, num);
+	mutex_unlock(&bq2415x_id_mutex);
+
+	return ret;
+}
+
+/* main bq2415x remove function */
+
+static int bq2415x_remove(struct i2c_client *client)
+{
+	struct bq2415x_device *bq = i2c_get_clientdata(client);
+
+	if (bq->init_data.set_mode_hook)
+		bq->init_data.set_mode_hook(NULL, NULL);
+
+	bq2415x_sysfs_exit(bq);
+	bq2415x_power_supply_exit(bq);
+
+	bq2415x_reset_chip(bq);
+
+	mutex_lock(&bq2415x_id_mutex);
+	idr_remove(&bq2415x_id, bq->id);
+	mutex_unlock(&bq2415x_id_mutex);
+
+	dev_info(bq->dev, "driver unregistered\n");
+
+	kfree(bq->name);
+	kfree(bq);
+
+	return 0;
+}
+
+static const struct i2c_device_id bq2415x_i2c_id_table[] = {
+	{ "bq2415x", BQUNKNOWN },
+	{ "bq24150", BQ24150 },
+	{ "bq24150a", BQ24150A },
+	{ "bq24151", BQ24151 },
+	{ "bq24151a", BQ24151A },
+	{ "bq24152", BQ24152 },
+	{ "bq24153", BQ24153 },
+	{ "bq24153a", BQ24153A },
+	{ "bq24155", BQ24155 },
+	{ "bq24156", BQ24156 },
+	{ "bq24156a", BQ24156A },
+	{ "bq24158", BQ24158 },
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, bq2415x_i2c_id_table);
+
+static struct i2c_driver bq2415x_driver = {
+	.driver = {
+		.name = "bq2415x-charger",
+	},
+	.probe = bq2415x_probe,
+	.remove = bq2415x_remove,
+	.id_table = bq2415x_i2c_id_table,
+};
+
+static int __init bq2415x_init(void)
+{
+	return i2c_add_driver(&bq2415x_driver);
+}
+module_init(bq2415x_init);
+
+static void __exit bq2415x_exit(void)
+{
+	i2c_del_driver(&bq2415x_driver);
+}
+module_exit(bq2415x_exit);
+
+MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
+MODULE_DESCRIPTION("bq2415x charger driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index 5860d4d..36b34ef 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -230,6 +230,14 @@ static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg)
  */
 static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di)
 {
+	int flags;
+	bool is_bq27500 = di->chip == BQ27500;
+	bool is_higher = bq27xxx_is_chip_version_higher(di);
+
+	flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500);
+	if (flags >= 0 && !is_higher && (flags & BQ27000_FLAG_CI))
+		return -ENODATA;
+
 	return bq27x00_battery_read_charge(di, BQ27x00_REG_NAC);
 }
 
@@ -926,7 +934,7 @@ static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg,
 	return pdata->read(dev, reg);
 }
 
-static int __devinit bq27000_battery_probe(struct platform_device *pdev)
+static int bq27000_battery_probe(struct platform_device *pdev)
 {
 	struct bq27x00_device_info *di;
 	struct bq27000_platform_data *pdata = pdev->dev.platform_data;
@@ -969,7 +977,7 @@ err_free:
 	return ret;
 }
 
-static int __devexit bq27000_battery_remove(struct platform_device *pdev)
+static int bq27000_battery_remove(struct platform_device *pdev)
 {
 	struct bq27x00_device_info *di = platform_get_drvdata(pdev);
 
@@ -983,7 +991,7 @@ static int __devexit bq27000_battery_remove(struct platform_device *pdev)
 
 static struct platform_driver bq27000_battery_driver = {
 	.probe	= bq27000_battery_probe,
-	.remove = __devexit_p(bq27000_battery_remove),
+	.remove = bq27000_battery_remove,
 	.driver = {
 		.name = "bq27000-battery",
 		.owner = THIS_MODULE,
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 8a0aca6..adb3a4b 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -1655,7 +1655,7 @@ err_alloc:
 	return ret;
 }
 
-static int __devexit charger_manager_remove(struct platform_device *pdev)
+static int charger_manager_remove(struct platform_device *pdev)
 {
 	struct charger_manager *cm = platform_get_drvdata(pdev);
 	struct charger_desc *desc = cm->desc;
@@ -1812,7 +1812,7 @@ static struct platform_driver charger_manager_driver = {
 		.pm = &charger_manager_pm,
 	},
 	.probe = charger_manager_probe,
-	.remove = __devexit_p(charger_manager_remove),
+	.remove = charger_manager_remove,
 	.id_table = charger_manager_id,
 };
 
diff --git a/drivers/power/collie_battery.c b/drivers/power/collie_battery.c
index b19bfe4..c58d0e3 100644
--- a/drivers/power/collie_battery.c
+++ b/drivers/power/collie_battery.c
@@ -305,7 +305,7 @@ static int collie_bat_resume(struct ucb1x00_dev *dev)
 #define collie_bat_resume NULL
 #endif
 
-static int __devinit collie_bat_probe(struct ucb1x00_dev *dev)
+static int collie_bat_probe(struct ucb1x00_dev *dev)
 {
 	int ret;
 
@@ -349,7 +349,7 @@ err_psy_reg_main:
 	return ret;
 }
 
-static void __devexit collie_bat_remove(struct ucb1x00_dev *dev)
+static void collie_bat_remove(struct ucb1x00_dev *dev)
 {
 	free_irq(gpio_to_irq(COLLIE_GPIO_CO), &collie_bat_main);
 
@@ -367,7 +367,7 @@ static void __devexit collie_bat_remove(struct ucb1x00_dev *dev)
 
 static struct ucb1x00_driver collie_bat_driver = {
 	.add		= collie_bat_probe,
-	.remove		= __devexit_p(collie_bat_remove),
+	.remove		= collie_bat_remove,
 	.suspend	= collie_bat_suspend,
 	.resume		= collie_bat_resume,
 };
diff --git a/drivers/power/da9052-battery.c b/drivers/power/da9052-battery.c
index d9d034d..3c5c2e4 100644
--- a/drivers/power/da9052-battery.c
+++ b/drivers/power/da9052-battery.c
@@ -440,8 +440,10 @@ static int da9052_bat_check_health(struct da9052_battery *bat, int *health)
 static irqreturn_t da9052_bat_irq(int irq, void *data)
 {
 	struct da9052_battery *bat = data;
+	int virq;
 
-	irq -= bat->da9052->irq_base;
+	virq = regmap_irq_get_virq(bat->da9052->irq_data, irq);
+	irq -= virq;
 
 	if (irq == DA9052_IRQ_CHGEND)
 		bat->status = POWER_SUPPLY_STATUS_FULL;
@@ -567,7 +569,7 @@ static struct power_supply template_battery = {
 	.get_property	= da9052_bat_get_property,
 };
 
-static const char *const da9052_bat_irqs[] = {
+static char *da9052_bat_irqs[] = {
 	"BATT TEMP",
 	"DCIN DET",
 	"DCIN REM",
@@ -576,12 +578,20 @@ static const char *const da9052_bat_irqs[] = {
 	"CHG END",
 };
 
-static s32 __devinit da9052_bat_probe(struct platform_device *pdev)
+static int da9052_bat_irq_bits[] = {
+	DA9052_IRQ_TBAT,
+	DA9052_IRQ_DCIN,
+	DA9052_IRQ_DCINREM,
+	DA9052_IRQ_VBUS,
+	DA9052_IRQ_VBUSREM,
+	DA9052_IRQ_CHGEND,
+};
+
+static s32 da9052_bat_probe(struct platform_device *pdev)
 {
 	struct da9052_pdata *pdata;
 	struct da9052_battery *bat;
 	int ret;
-	int irq;
 	int i;
 
 	bat = kzalloc(sizeof(struct da9052_battery), GFP_KERNEL);
@@ -602,15 +612,14 @@ static s32 __devinit da9052_bat_probe(struct platform_device *pdev)
 		bat->psy.use_for_apm = 1;
 
 	for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++) {
-		irq = platform_get_irq_byname(pdev, da9052_bat_irqs[i]);
-		ret = request_threaded_irq(bat->da9052->irq_base + irq,
-					   NULL, da9052_bat_irq,
-					   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-					   da9052_bat_irqs[i], bat);
+		ret = da9052_request_irq(bat->da9052,
+				da9052_bat_irq_bits[i], da9052_bat_irqs[i],
+				da9052_bat_irq, bat);
+
 		if (ret != 0) {
 			dev_err(bat->da9052->dev,
-				"DA9052 failed to request %s IRQ %d: %d\n",
-				da9052_bat_irqs[i], irq, ret);
+				"DA9052 failed to request %s IRQ: %d\n",
+				da9052_bat_irqs[i], ret);
 			goto err;
 		}
 	}
@@ -623,23 +632,20 @@ static s32 __devinit da9052_bat_probe(struct platform_device *pdev)
 	return 0;
 
 err:
-	while (--i >= 0) {
-		irq = platform_get_irq_byname(pdev, da9052_bat_irqs[i]);
-		free_irq(bat->da9052->irq_base + irq, bat);
-	}
+	while (--i >= 0)
+		da9052_free_irq(bat->da9052, da9052_bat_irq_bits[i], bat);
+
 	kfree(bat);
 	return ret;
 }
-static int __devexit da9052_bat_remove(struct platform_device *pdev)
+static int da9052_bat_remove(struct platform_device *pdev)
 {
 	int i;
-	int irq;
 	struct da9052_battery *bat = platform_get_drvdata(pdev);
 
-	for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++) {
-		irq = platform_get_irq_byname(pdev, da9052_bat_irqs[i]);
-		free_irq(bat->da9052->irq_base + irq, bat);
-	}
+	for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++)
+		da9052_free_irq(bat->da9052, da9052_bat_irq_bits[i], bat);
+
 	power_supply_unregister(&bat->psy);
 	kfree(bat);
 
@@ -648,7 +654,7 @@ static int __devexit da9052_bat_remove(struct platform_device *pdev)
 
 static struct platform_driver da9052_bat_driver = {
 	.probe = da9052_bat_probe,
-	.remove = __devexit_p(da9052_bat_remove),
+	.remove = da9052_bat_remove,
 	.driver = {
 		.name = "da9052-bat",
 		.owner = THIS_MODULE,
diff --git a/drivers/power/ds2780_battery.c b/drivers/power/ds2780_battery.c
index 74fad94..8b6c453 100644
--- a/drivers/power/ds2780_battery.c
+++ b/drivers/power/ds2780_battery.c
@@ -755,7 +755,7 @@ static const struct attribute_group ds2780_attr_group = {
 	.attrs = ds2780_attributes,
 };
 
-static int __devinit ds2780_battery_probe(struct platform_device *pdev)
+static int ds2780_battery_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 	struct ds2780_device_info *dev_info;
@@ -819,7 +819,7 @@ fail:
 	return ret;
 }
 
-static int __devexit ds2780_battery_remove(struct platform_device *pdev)
+static int ds2780_battery_remove(struct platform_device *pdev)
 {
 	struct ds2780_device_info *dev_info = platform_get_drvdata(pdev);
 
@@ -837,7 +837,7 @@ static struct platform_driver ds2780_battery_driver = {
 		.name = "ds2780-battery",
 	},
 	.probe	  = ds2780_battery_probe,
-	.remove   = __devexit_p(ds2780_battery_remove),
+	.remove   = ds2780_battery_remove,
 };
 
 module_platform_driver(ds2780_battery_driver);
diff --git a/drivers/power/ds2781_battery.c b/drivers/power/ds2781_battery.c
index 22b3c8c..0a5acc6 100644
--- a/drivers/power/ds2781_battery.c
+++ b/drivers/power/ds2781_battery.c
@@ -750,7 +750,7 @@ static const struct attribute_group ds2781_attr_group = {
 	.attrs = ds2781_attributes,
 };
 
-static int __devinit ds2781_battery_probe(struct platform_device *pdev)
+static int ds2781_battery_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 	struct ds2781_device_info *dev_info;
@@ -810,7 +810,7 @@ fail:
 	return ret;
 }
 
-static int __devexit ds2781_battery_remove(struct platform_device *pdev)
+static int ds2781_battery_remove(struct platform_device *pdev)
 {
 	struct ds2781_device_info *dev_info = platform_get_drvdata(pdev);
 
@@ -827,7 +827,7 @@ static struct platform_driver ds2781_battery_driver = {
 		.name = "ds2781-battery",
 	},
 	.probe	  = ds2781_battery_probe,
-	.remove   = __devexit_p(ds2781_battery_remove),
+	.remove   = ds2781_battery_remove,
 };
 module_platform_driver(ds2781_battery_driver);
 
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c
index 6bb6e2f..2fa9b6b 100644
--- a/drivers/power/ds2782_battery.c
+++ b/drivers/power/ds2782_battery.c
@@ -80,13 +80,13 @@ static inline int ds278x_read_reg16(struct ds278x_info *info, int reg_msb,
 {
 	int ret;
 
-	ret = swab16(i2c_smbus_read_word_data(info->client, reg_msb));
+	ret = i2c_smbus_read_word_data(info->client, reg_msb);
 	if (ret < 0) {
 		dev_err(&info->client->dev, "register read failed\n");
 		return ret;
 	}
 
-	*val = ret;
+	*val = swab16(ret);
 	return 0;
 }
 
diff --git a/drivers/power/generic-adc-battery.c b/drivers/power/generic-adc-battery.c
index 9bdf444..32ce17e 100644
--- a/drivers/power/generic-adc-battery.c
+++ b/drivers/power/generic-adc-battery.c
@@ -236,7 +236,7 @@ static irqreturn_t gab_charged(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit gab_probe(struct platform_device *pdev)
+static int gab_probe(struct platform_device *pdev)
 {
 	struct gab *adc_bat;
 	struct power_supply *psy;
@@ -279,7 +279,8 @@ static int __devinit gab_probe(struct platform_device *pdev)
 	}
 
 	memcpy(psy->properties, gab_props, sizeof(gab_props));
-	properties = psy->properties + sizeof(gab_props);
+	properties = (enum power_supply_property *)
+				((char *)psy->properties + sizeof(gab_props));
 
 	/*
 	 * getting channel from iio and copying the battery properties
@@ -327,7 +328,7 @@ static int __devinit gab_probe(struct platform_device *pdev)
 		ret = request_any_context_irq(irq, gab_charged,
 				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 				"battery charged", adc_bat);
-		if (ret)
+		if (ret < 0)
 			goto err_gpio;
 	}
 
@@ -351,7 +352,7 @@ first_mem_fail:
 	return ret;
 }
 
-static int __devexit gab_remove(struct platform_device *pdev)
+static int gab_remove(struct platform_device *pdev)
 {
 	int chan;
 	struct gab *adc_bat = platform_get_drvdata(pdev);
@@ -413,7 +414,7 @@ static struct platform_driver gab_driver = {
 		.pm	= GAB_PM_OPS
 	},
 	.probe		= gab_probe,
-	.remove		= __devexit_p(gab_remove),
+	.remove		= gab_remove,
 };
 module_platform_driver(gab_driver);
 
diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c
index cb2aa31..e3e40a9 100644
--- a/drivers/power/gpio-charger.c
+++ b/drivers/power/gpio-charger.c
@@ -68,7 +68,7 @@ static enum power_supply_property gpio_charger_properties[] = {
 	POWER_SUPPLY_PROP_ONLINE,
 };
 
-static int __devinit gpio_charger_probe(struct platform_device *pdev)
+static int gpio_charger_probe(struct platform_device *pdev)
 {
 	const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data;
 	struct gpio_charger *gpio_charger;
@@ -144,7 +144,7 @@ err_free:
 	return ret;
 }
 
-static int __devexit gpio_charger_remove(struct platform_device *pdev)
+static int gpio_charger_remove(struct platform_device *pdev)
 {
 	struct gpio_charger *gpio_charger = platform_get_drvdata(pdev);
 
@@ -177,7 +177,7 @@ static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, NULL, gpio_charger_resume);
 
 static struct platform_driver gpio_charger_driver = {
 	.probe = gpio_charger_probe,
-	.remove = __devexit_p(gpio_charger_remove),
+	.remove = gpio_charger_remove,
 	.driver = {
 		.name = "gpio-charger",
 		.owner = THIS_MODULE,
diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c
index d096497..18d136b 100644
--- a/drivers/power/intel_mid_battery.c
+++ b/drivers/power/intel_mid_battery.c
@@ -649,7 +649,7 @@ static void pmic_battery_handle_intrpt(struct work_struct *work)
  * PMIC battery initializes its internal data structue and other
  * infrastructure components for it to work as expected.
  */
-static __devinit int probe(int irq, struct device *dev)
+static int probe(int irq, struct device *dev)
 {
 	int retval = 0;
 	struct pmic_power_module_info *pbi;
@@ -739,7 +739,7 @@ wqueue_failed:
 	return retval;
 }
 
-static int __devinit platform_pmic_battery_probe(struct platform_device *pdev)
+static int platform_pmic_battery_probe(struct platform_device *pdev)
 {
 	return probe(pdev->id, &pdev->dev);
 }
@@ -754,7 +754,7 @@ static int __devinit platform_pmic_battery_probe(struct platform_device *pdev)
  * pmic_battery_probe.
  */
 
-static int __devexit platform_pmic_battery_remove(struct platform_device *pdev)
+static int platform_pmic_battery_remove(struct platform_device *pdev)
 {
 	struct pmic_power_module_info *pbi = dev_get_drvdata(&pdev->dev);
 
@@ -776,7 +776,7 @@ static struct platform_driver platform_pmic_battery_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = platform_pmic_battery_probe,
-	.remove = __devexit_p(platform_pmic_battery_remove),
+	.remove = platform_pmic_battery_remove,
 };
 
 module_platform_driver(platform_pmic_battery_driver);
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
index 1229119..176ad59 100644
--- a/drivers/power/isp1704_charger.c
+++ b/drivers/power/isp1704_charger.c
@@ -406,7 +406,7 @@ static inline int isp1704_test_ulpi(struct isp1704_charger *isp)
 	return -ENODEV;
 }
 
-static int __devinit isp1704_charger_probe(struct platform_device *pdev)
+static int isp1704_charger_probe(struct platform_device *pdev)
 {
 	struct isp1704_charger	*isp;
 	int			ret = -ENODEV;
@@ -484,7 +484,7 @@ fail0:
 	return ret;
 }
 
-static int __devexit isp1704_charger_remove(struct platform_device *pdev)
+static int isp1704_charger_remove(struct platform_device *pdev)
 {
 	struct isp1704_charger *isp = platform_get_drvdata(pdev);
 
@@ -502,7 +502,7 @@ static struct platform_driver isp1704_charger_driver = {
 		.name = "isp1704_charger",
 	},
 	.probe = isp1704_charger_probe,
-	.remove = __devexit_p(isp1704_charger_remove),
+	.remove = isp1704_charger_remove,
 };
 
 module_platform_driver(isp1704_charger_driver);
diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c
index ffbed5e..bf91489 100644
--- a/drivers/power/jz4740-battery.c
+++ b/drivers/power/jz4740-battery.c
@@ -33,7 +33,6 @@ struct jz_battery {
 	struct jz_battery_platform_data *pdata;
 	struct platform_device *pdev;
 
-	struct resource *mem;
 	void __iomem *base;
 
 	int irq;
@@ -238,19 +237,20 @@ static void jz_battery_work(struct work_struct *work)
 	schedule_delayed_work(&jz_battery->work, interval);
 }
 
-static int __devinit jz_battery_probe(struct platform_device *pdev)
+static int jz_battery_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 	struct jz_battery_platform_data *pdata = pdev->dev.parent->platform_data;
 	struct jz_battery *jz_battery;
 	struct power_supply *battery;
+	struct resource *mem;
 
 	if (!pdata) {
 		dev_err(&pdev->dev, "No platform_data supplied\n");
 		return -ENXIO;
 	}
 
-	jz_battery = kzalloc(sizeof(*jz_battery), GFP_KERNEL);
+	jz_battery = devm_kzalloc(&pdev->dev, sizeof(*jz_battery), GFP_KERNEL);
 	if (!jz_battery) {
 		dev_err(&pdev->dev, "Failed to allocate driver structure\n");
 		return -ENOMEM;
@@ -260,33 +260,15 @@ static int __devinit jz_battery_probe(struct platform_device *pdev)
 
 	jz_battery->irq = platform_get_irq(pdev, 0);
 	if (jz_battery->irq < 0) {
-		ret = jz_battery->irq;
 		dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
-		goto err_free;
+		return jz_battery->irq;
 	}
 
-	jz_battery->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!jz_battery->mem) {
-		ret = -ENOENT;
-		dev_err(&pdev->dev, "Failed to get platform mmio resource\n");
-		goto err_free;
-	}
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	jz_battery->mem = request_mem_region(jz_battery->mem->start,
-				resource_size(jz_battery->mem),	pdev->name);
-	if (!jz_battery->mem) {
-		ret = -EBUSY;
-		dev_err(&pdev->dev, "Failed to request mmio memory region\n");
-		goto err_free;
-	}
-
-	jz_battery->base = ioremap_nocache(jz_battery->mem->start,
-				resource_size(jz_battery->mem));
-	if (!jz_battery->base) {
-		ret = -EBUSY;
-		dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
-		goto err_release_mem_region;
-	}
+	jz_battery->base = devm_request_and_ioremap(&pdev->dev, mem);
+	if (!jz_battery->base)
+		return -EBUSY;
 
 	battery = &jz_battery->battery;
 	battery->name = pdata->info.name;
@@ -309,7 +291,7 @@ static int __devinit jz_battery_probe(struct platform_device *pdev)
 			jz_battery);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to request irq %d\n", ret);
-		goto err_iounmap;
+		goto err;
 	}
 	disable_irq(jz_battery->irq);
 
@@ -366,17 +348,12 @@ err_free_gpio:
 		gpio_free(jz_battery->pdata->gpio_charge);
 err_free_irq:
 	free_irq(jz_battery->irq, jz_battery);
-err_iounmap:
+err:
 	platform_set_drvdata(pdev, NULL);
-	iounmap(jz_battery->base);
-err_release_mem_region:
-	release_mem_region(jz_battery->mem->start, resource_size(jz_battery->mem));
-err_free:
-	kfree(jz_battery);
 	return ret;
 }
 
-static int __devexit jz_battery_remove(struct platform_device *pdev)
+static int jz_battery_remove(struct platform_device *pdev)
 {
 	struct jz_battery *jz_battery = platform_get_drvdata(pdev);
 
@@ -392,10 +369,6 @@ static int __devexit jz_battery_remove(struct platform_device *pdev)
 
 	free_irq(jz_battery->irq, jz_battery);
 
-	iounmap(jz_battery->base);
-	release_mem_region(jz_battery->mem->start, resource_size(jz_battery->mem));
-	kfree(jz_battery);
-
 	return 0;
 }
 
@@ -431,7 +404,7 @@ static const struct dev_pm_ops jz_battery_pm_ops = {
 
 static struct platform_driver jz_battery_driver = {
 	.probe		= jz_battery_probe,
-	.remove		= __devexit_p(jz_battery_remove),
+	.remove		= jz_battery_remove,
 	.driver = {
 		.name = "jz4740-battery",
 		.owner = THIS_MODULE,
diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c
index c628224..4ee71a9 100644
--- a/drivers/power/lp8727_charger.c
+++ b/drivers/power/lp8727_charger.c
@@ -522,7 +522,7 @@ static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 	return 0;
 }
 
-static int __devexit lp8727_remove(struct i2c_client *cl)
+static int lp8727_remove(struct i2c_client *cl)
 {
 	struct lp8727_chg *pchg = i2c_get_clientdata(cl);
 
@@ -542,7 +542,7 @@ static struct i2c_driver lp8727_driver = {
 		   .name = "lp8727",
 		   },
 	.probe = lp8727_probe,
-	.remove = __devexit_p(lp8727_remove),
+	.remove = lp8727_remove,
 	.id_table = lp8727_ids,
 };
 module_i2c_driver(lp8727_driver);
diff --git a/drivers/power/lp8788-charger.c b/drivers/power/lp8788-charger.c
index e852d12..22b6407c 100644
--- a/drivers/power/lp8788-charger.c
+++ b/drivers/power/lp8788-charger.c
@@ -235,25 +235,14 @@ static int lp8788_get_battery_present(struct lp8788_charger *pchg,
 	return 0;
 }
 
-static int lp8788_get_vbatt_adc(struct lp8788_charger *pchg,
-				unsigned int *result)
+static int lp8788_get_vbatt_adc(struct lp8788_charger *pchg, int *result)
 {
 	struct iio_channel *channel = pchg->chan[LP8788_VBATT];
-	int scaleint;
-	int scalepart;
-	int ret;
 
 	if (!channel)
 		return -EINVAL;
 
-	ret = iio_read_channel_scale(channel, &scaleint, &scalepart);
-	if (ret != IIO_VAL_INT_PLUS_MICRO)
-		return -EINVAL;
-
-	/* unit: mV */
-	*result = (scaleint + scalepart * 1000000) / 1000;
-
-	return 0;
+	return iio_read_channel_processed(channel, result);
 }
 
 static int lp8788_get_battery_voltage(struct lp8788_charger *pchg,
@@ -268,7 +257,7 @@ static int lp8788_get_battery_capacity(struct lp8788_charger *pchg,
 	struct lp8788 *lp = pchg->lp;
 	struct lp8788_charger_platform_data *pdata = pchg->pdata;
 	unsigned int max_vbatt;
-	unsigned int vbatt;
+	int vbatt;
 	enum lp8788_charging_state state;
 	u8 data;
 	int ret;
@@ -304,19 +293,18 @@ static int lp8788_get_battery_temperature(struct lp8788_charger *pchg,
 				union power_supply_propval *val)
 {
 	struct iio_channel *channel = pchg->chan[LP8788_BATT_TEMP];
-	int scaleint;
-	int scalepart;
+	int result;
 	int ret;
 
 	if (!channel)
 		return -EINVAL;
 
-	ret = iio_read_channel_scale(channel, &scaleint, &scalepart);
-	if (ret != IIO_VAL_INT_PLUS_MICRO)
+	ret = iio_read_channel_processed(channel, &result);
+	if (ret < 0)
 		return -EINVAL;
 
 	/* unit: 0.1 'C */
-	val->intval = (scaleint + scalepart * 1000000) / 100;
+	val->intval = result * 10;
 
 	return 0;
 }
@@ -592,53 +580,22 @@ static void lp8788_irq_unregister(struct platform_device *pdev,
 	}
 }
 
-static void lp8788_setup_adc_channel(struct lp8788_charger *pchg)
+static void lp8788_setup_adc_channel(const char *consumer_name,
+				struct lp8788_charger *pchg)
 {
 	struct lp8788_charger_platform_data *pdata = pchg->pdata;
-	struct device *dev = pchg->lp->dev;
 	struct iio_channel *chan;
-	enum lp8788_adc_id id;
-	const char *chan_name[LPADC_MAX] = {
-		[LPADC_VBATT_5P5] = "vbatt-5p5",
-		[LPADC_VBATT_6P0] = "vbatt-6p0",
-		[LPADC_VBATT_5P0] = "vbatt-5p0",
-		[LPADC_ADC1]      = "adc1",
-		[LPADC_ADC2]      = "adc2",
-		[LPADC_ADC3]      = "adc3",
-		[LPADC_ADC4]      = "adc4",
-	};
 
 	if (!pdata)
 		return;
 
-	id = pdata->vbatt_adc;
-	switch (id) {
-	case LPADC_VBATT_5P5:
-	case LPADC_VBATT_6P0:
-	case LPADC_VBATT_5P0:
-		chan = iio_channel_get(NULL, chan_name[id]);
-		pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan;
-		break;
-	default:
-		dev_err(dev, "invalid ADC id for VBATT: %d\n", id);
-		pchg->chan[LP8788_VBATT] = NULL;
-		break;
-	}
+	/* ADC channel for battery voltage */
+	chan = iio_channel_get(consumer_name, pdata->adc_vbatt);
+	pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan;
 
-	id = pdata->batt_temp_adc;
-	switch (id) {
-	case LPADC_ADC1:
-	case LPADC_ADC2:
-	case LPADC_ADC3:
-	case LPADC_ADC4:
-		chan = iio_channel_get(NULL, chan_name[id]);
-		pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan;
-		break;
-	default:
-		dev_err(dev, "invalid ADC id for BATT_TEMP : %d\n", id);
-		pchg->chan[LP8788_BATT_TEMP] = NULL;
-		break;
-	}
+	/* ADC channel for battery temperature */
+	chan = iio_channel_get(consumer_name, pdata->adc_batt_temp);
+	pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan;
 }
 
 static void lp8788_release_adc_channel(struct lp8788_charger *pchg)
@@ -729,7 +686,7 @@ static const struct attribute_group lp8788_attr_group = {
 	.attrs = lp8788_charger_attr,
 };
 
-static __devinit int lp8788_charger_probe(struct platform_device *pdev)
+static int lp8788_charger_probe(struct platform_device *pdev)
 {
 	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
 	struct lp8788_charger *pchg;
@@ -747,7 +704,7 @@ static __devinit int lp8788_charger_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	lp8788_setup_adc_channel(pchg);
+	lp8788_setup_adc_channel(pdev->name, pchg);
 
 	ret = lp8788_psy_register(pdev, pchg);
 	if (ret)
@@ -766,7 +723,7 @@ static __devinit int lp8788_charger_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit lp8788_charger_remove(struct platform_device *pdev)
+static int lp8788_charger_remove(struct platform_device *pdev)
 {
 	struct lp8788_charger *pchg = platform_get_drvdata(pdev);
 
@@ -781,7 +738,7 @@ static int __devexit lp8788_charger_remove(struct platform_device *pdev)
 
 static struct platform_driver lp8788_charger_driver = {
 	.probe = lp8788_charger_probe,
-	.remove = __devexit_p(lp8788_charger_remove),
+	.remove = lp8788_charger_remove,
 	.driver = {
 		.name = LP8788_DEV_CHARGER,
 		.owner = THIS_MODULE,
diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c
index 58e6783..22cfe9c 100644
--- a/drivers/power/max17040_battery.c
+++ b/drivers/power/max17040_battery.c
@@ -197,7 +197,7 @@ static enum power_supply_property max17040_battery_props[] = {
 	POWER_SUPPLY_PROP_CAPACITY,
 };
 
-static int __devinit max17040_probe(struct i2c_client *client,
+static int max17040_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@@ -238,7 +238,7 @@ static int __devinit max17040_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int __devexit max17040_remove(struct i2c_client *client)
+static int max17040_remove(struct i2c_client *client)
 {
 	struct max17040_chip *chip = i2c_get_clientdata(client);
 
@@ -285,7 +285,7 @@ static struct i2c_driver max17040_i2c_driver = {
 		.name	= "max17040",
 	},
 	.probe		= max17040_probe,
-	.remove		= __devexit_p(max17040_remove),
+	.remove		= max17040_remove,
 	.suspend	= max17040_suspend,
 	.resume		= max17040_resume,
 	.id_table	= max17040_id,
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c
index 74abc6c..d664ef5 100644
--- a/drivers/power/max17042_battery.c
+++ b/drivers/power/max17042_battery.c
@@ -572,7 +572,8 @@ static int max17042_init_chip(struct max17042_chip *chip)
 			__func__);
 		return -EIO;
 	}
-	max17042_verify_model_lock(chip);
+
+	ret = max17042_verify_model_lock(chip);
 	if (ret) {
 		dev_err(&chip->client->dev, "%s lock verify failed\n",
 			__func__);
@@ -681,7 +682,7 @@ max17042_get_pdata(struct device *dev)
 }
 #endif
 
-static int __devinit max17042_probe(struct i2c_client *client,
+static int max17042_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@@ -775,7 +776,7 @@ static int __devinit max17042_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int __devexit max17042_remove(struct i2c_client *client)
+static int max17042_remove(struct i2c_client *client)
 {
 	struct max17042_chip *chip = i2c_get_clientdata(client);
 
@@ -851,7 +852,7 @@ static struct i2c_driver max17042_i2c_driver = {
 		.pm	= MAX17042_PM_OPS,
 	},
 	.probe		= max17042_probe,
-	.remove		= __devexit_p(max17042_remove),
+	.remove		= max17042_remove,
 	.id_table	= max17042_id,
 };
 module_i2c_driver(max17042_i2c_driver);
diff --git a/drivers/power/max8903_charger.c b/drivers/power/max8903_charger.c
index 3e23f43..14e2b96 100644
--- a/drivers/power/max8903_charger.c
+++ b/drivers/power/max8903_charger.c
@@ -179,7 +179,7 @@ static irqreturn_t max8903_fault(int irq, void *_data)
 	return IRQ_HANDLED;
 }
 
-static __devinit int max8903_probe(struct platform_device *pdev)
+static int max8903_probe(struct platform_device *pdev)
 {
 	struct max8903_data *data;
 	struct device *dev = &pdev->dev;
@@ -345,7 +345,7 @@ err:
 	return ret;
 }
 
-static __devexit int max8903_remove(struct platform_device *pdev)
+static int max8903_remove(struct platform_device *pdev)
 {
 	struct max8903_data *data = platform_get_drvdata(pdev);
 
@@ -367,7 +367,7 @@ static __devexit int max8903_remove(struct platform_device *pdev)
 
 static struct platform_driver max8903_driver = {
 	.probe	= max8903_probe,
-	.remove	= __devexit_p(max8903_remove),
+	.remove	= max8903_remove,
 	.driver = {
 		.name	= "max8903-charger",
 		.owner	= THIS_MODULE,
diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c
index daa333b..665cdc7 100644
--- a/drivers/power/max8925_power.c
+++ b/drivers/power/max8925_power.c
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
@@ -356,7 +357,7 @@ do {									\
 			_irq, ret);					\
 } while (0)
 
-static __devinit int max8925_init_charger(struct max8925_chip *chip,
+static int max8925_init_charger(struct max8925_chip *chip,
 					  struct max8925_power_info *info)
 {
 	int ret;
@@ -414,7 +415,7 @@ static __devinit int max8925_init_charger(struct max8925_chip *chip,
 	return 0;
 }
 
-static __devexit int max8925_deinit_charger(struct max8925_power_info *info)
+static int max8925_deinit_charger(struct max8925_power_info *info)
 {
 	struct max8925_chip *chip = info->chip;
 	int irq;
@@ -426,14 +427,62 @@ static __devexit int max8925_deinit_charger(struct max8925_power_info *info)
 	return 0;
 }
 
-static __devinit int max8925_power_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static struct max8925_power_pdata *
+max8925_power_dt_init(struct platform_device *pdev)
+{
+	struct device_node *nproot = pdev->dev.parent->of_node;
+	struct device_node *np;
+	int batt_detect;
+	int topoff_threshold;
+	int fast_charge;
+	int no_temp_support;
+	int no_insert_detect;
+	struct max8925_power_pdata *pdata;
+
+	if (!nproot)
+		return pdev->dev.platform_data;
+
+	np = of_find_node_by_name(nproot, "charger");
+	if (!np) {
+		dev_err(&pdev->dev, "failed to find charger node\n");
+		return NULL;
+	}
+
+	pdata = devm_kzalloc(&pdev->dev,
+			sizeof(struct max8925_power_pdata),
+			GFP_KERNEL);
+
+	of_property_read_u32(np, "topoff-threshold", &topoff_threshold);
+	of_property_read_u32(np, "batt-detect", &batt_detect);
+	of_property_read_u32(np, "fast-charge", &fast_charge);
+	of_property_read_u32(np, "no-insert-detect", &no_insert_detect);
+	of_property_read_u32(np, "no-temp-support", &no_temp_support);
+
+	pdata->batt_detect = batt_detect;
+	pdata->fast_charge = fast_charge;
+	pdata->topoff_threshold = topoff_threshold;
+	pdata->no_insert_detect = no_insert_detect;
+	pdata->no_temp_support = no_temp_support;
+
+	return pdata;
+}
+#else
+static struct max8925_power_pdata *
+max8925_power_dt_init(struct platform_device *pdev)
+{
+	return pdev->dev.platform_data;
+}
+#endif
+
+static int max8925_power_probe(struct platform_device *pdev)
 {
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct max8925_power_pdata *pdata = NULL;
 	struct max8925_power_info *info;
 	int ret;
 
-	pdata = pdev->dev.platform_data;
+	pdata = max8925_power_dt_init(pdev);
 	if (!pdata) {
 		dev_err(&pdev->dev, "platform data isn't assigned to "
 			"power supply\n");
@@ -501,7 +550,7 @@ out:
 	return ret;
 }
 
-static __devexit int max8925_power_remove(struct platform_device *pdev)
+static int max8925_power_remove(struct platform_device *pdev)
 {
 	struct max8925_power_info *info = platform_get_drvdata(pdev);
 
@@ -517,7 +566,7 @@ static __devexit int max8925_power_remove(struct platform_device *pdev)
 
 static struct platform_driver max8925_power_driver = {
 	.probe	= max8925_power_probe,
-	.remove	= __devexit_p(max8925_power_remove),
+	.remove	= max8925_power_remove,
 	.driver	= {
 		.name	= "max8925-power",
 	},
diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c
index 6e88c5d..e757885 100644
--- a/drivers/power/max8997_charger.c
+++ b/drivers/power/max8997_charger.c
@@ -86,7 +86,7 @@ static int max8997_battery_get_property(struct power_supply *psy,
 	return 0;
 }
 
-static __devinit int max8997_battery_probe(struct platform_device *pdev)
+static int max8997_battery_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 	struct charger_data *charger;
@@ -167,7 +167,7 @@ err:
 	return ret;
 }
 
-static int __devexit max8997_battery_remove(struct platform_device *pdev)
+static int max8997_battery_remove(struct platform_device *pdev)
 {
 	struct charger_data *charger = platform_get_drvdata(pdev);
 
@@ -187,7 +187,7 @@ static struct platform_driver max8997_battery_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = max8997_battery_probe,
-	.remove = __devexit_p(max8997_battery_remove),
+	.remove = max8997_battery_remove,
 	.id_table = max8997_battery_id,
 };
 
diff --git a/drivers/power/max8998_charger.c b/drivers/power/max8998_charger.c
index 6dc01c2..bf677e3 100644
--- a/drivers/power/max8998_charger.c
+++ b/drivers/power/max8998_charger.c
@@ -75,7 +75,7 @@ static int max8998_battery_get_property(struct power_supply *psy,
 	return 0;
 }
 
-static __devinit int max8998_battery_probe(struct platform_device *pdev)
+static int max8998_battery_probe(struct platform_device *pdev)
 {
 	struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 	struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -178,7 +178,7 @@ err:
 	return ret;
 }
 
-static int __devexit max8998_battery_remove(struct platform_device *pdev)
+static int max8998_battery_remove(struct platform_device *pdev)
 {
 	struct max8998_battery_data *max8998 = platform_get_drvdata(pdev);
 
@@ -199,7 +199,7 @@ static struct platform_driver max8998_battery_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = max8998_battery_probe,
-	.remove = __devexit_p(max8998_battery_remove),
+	.remove = max8998_battery_remove,
 	.id_table = max8998_battery_id,
 };
 
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
index a89a41a..298c47d 100644
--- a/drivers/power/olpc_battery.c
+++ b/drivers/power/olpc_battery.c
@@ -598,7 +598,7 @@ static int olpc_battery_suspend(struct platform_device *pdev,
 	return 0;
 }
 
-static int __devinit olpc_battery_probe(struct platform_device *pdev)
+static int olpc_battery_probe(struct platform_device *pdev)
 {
 	int ret;
 	uint8_t status;
@@ -659,7 +659,7 @@ battery_failed:
 	return ret;
 }
 
-static int __devexit olpc_battery_remove(struct platform_device *pdev)
+static int olpc_battery_remove(struct platform_device *pdev)
 {
 	device_remove_file(olpc_bat.dev, &olpc_bat_error);
 	device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom);
@@ -681,7 +681,7 @@ static struct platform_driver olpc_battery_driver = {
 		.of_match_table = olpc_battery_ids,
 	},
 	.probe = olpc_battery_probe,
-	.remove = __devexit_p(olpc_battery_remove),
+	.remove = olpc_battery_remove,
 	.suspend = olpc_battery_suspend,
 };
 
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
index 3d1e9ef..c2122a7 100644
--- a/drivers/power/pcf50633-charger.c
+++ b/drivers/power/pcf50633-charger.c
@@ -366,7 +366,7 @@ static const u8 mbc_irq_handlers[] = {
 	PCF50633_IRQ_LOWBAT,
 };
 
-static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
+static int pcf50633_mbc_probe(struct platform_device *pdev)
 {
 	struct pcf50633_mbc *mbc;
 	int ret;
@@ -447,7 +447,7 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit pcf50633_mbc_remove(struct platform_device *pdev)
+static int pcf50633_mbc_remove(struct platform_device *pdev)
 {
 	struct pcf50633_mbc *mbc = platform_get_drvdata(pdev);
 	int i;
@@ -471,7 +471,7 @@ static struct platform_driver pcf50633_mbc_driver = {
 		.name = "pcf50633-mbc",
 	},
 	.probe = pcf50633_mbc_probe,
-	.remove = __devexit_p(pcf50633_mbc_remove),
+	.remove = pcf50633_mbc_remove,
 };
 
 module_platform_driver(pcf50633_mbc_driver);
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 2436f13..8a7cfb3 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -201,7 +201,7 @@ static int psy_register_thermal(struct power_supply *psy)
 	for (i = 0; i < psy->num_properties; i++) {
 		if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) {
 			psy->tzd = thermal_zone_device_register(psy->name, 0, 0,
-					psy, &psy_tzd_ops, 0, 0);
+					psy, &psy_tzd_ops, NULL, 0, 0);
 			if (IS_ERR(psy->tzd))
 				return PTR_ERR(psy->tzd);
 			break;
@@ -216,6 +216,86 @@ static void psy_unregister_thermal(struct power_supply *psy)
 		return;
 	thermal_zone_device_unregister(psy->tzd);
 }
+
+/* thermal cooling device callbacks */
+static int ps_get_max_charge_cntl_limit(struct thermal_cooling_device *tcd,
+					unsigned long *state)
+{
+	struct power_supply *psy;
+	union power_supply_propval val;
+	int ret;
+
+	psy = tcd->devdata;
+	ret = psy->get_property(psy,
+		POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, &val);
+	if (!ret)
+		*state = val.intval;
+
+	return ret;
+}
+
+static int ps_get_cur_chrage_cntl_limit(struct thermal_cooling_device *tcd,
+					unsigned long *state)
+{
+	struct power_supply *psy;
+	union power_supply_propval val;
+	int ret;
+
+	psy = tcd->devdata;
+	ret = psy->get_property(psy,
+		POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val);
+	if (!ret)
+		*state = val.intval;
+
+	return ret;
+}
+
+static int ps_set_cur_charge_cntl_limit(struct thermal_cooling_device *tcd,
+					unsigned long state)
+{
+	struct power_supply *psy;
+	union power_supply_propval val;
+	int ret;
+
+	psy = tcd->devdata;
+	val.intval = state;
+	ret = psy->set_property(psy,
+		POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val);
+
+	return ret;
+}
+
+static struct thermal_cooling_device_ops psy_tcd_ops = {
+	.get_max_state = ps_get_max_charge_cntl_limit,
+	.get_cur_state = ps_get_cur_chrage_cntl_limit,
+	.set_cur_state = ps_set_cur_charge_cntl_limit,
+};
+
+static int psy_register_cooler(struct power_supply *psy)
+{
+	int i;
+
+	/* Register for cooling device if psy can control charging */
+	for (i = 0; i < psy->num_properties; i++) {
+		if (psy->properties[i] ==
+				POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT) {
+			psy->tcd = thermal_cooling_device_register(
+							(char *)psy->name,
+							psy, &psy_tcd_ops);
+			if (IS_ERR(psy->tcd))
+				return PTR_ERR(psy->tcd);
+			break;
+		}
+	}
+	return 0;
+}
+
+static void psy_unregister_cooler(struct power_supply *psy)
+{
+	if (IS_ERR_OR_NULL(psy->tcd))
+		return;
+	thermal_cooling_device_unregister(psy->tcd);
+}
 #else
 static int psy_register_thermal(struct power_supply *psy)
 {
@@ -225,6 +305,15 @@ static int psy_register_thermal(struct power_supply *psy)
 static void psy_unregister_thermal(struct power_supply *psy)
 {
 }
+
+static int psy_register_cooler(struct power_supply *psy)
+{
+	return 0;
+}
+
+static void psy_unregister_cooler(struct power_supply *psy)
+{
+}
 #endif
 
 int power_supply_register(struct device *parent, struct power_supply *psy)
@@ -259,6 +348,10 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
 	if (rc)
 		goto register_thermal_failed;
 
+	rc = psy_register_cooler(psy);
+	if (rc)
+		goto register_cooler_failed;
+
 	rc = power_supply_create_triggers(psy);
 	if (rc)
 		goto create_triggers_failed;
@@ -268,6 +361,8 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
 	goto success;
 
 create_triggers_failed:
+	psy_unregister_cooler(psy);
+register_cooler_failed:
 	psy_unregister_thermal(psy);
 register_thermal_failed:
 	device_del(dev);
@@ -284,6 +379,7 @@ void power_supply_unregister(struct power_supply *psy)
 	cancel_work_sync(&psy->changed_work);
 	sysfs_remove_link(&psy->dev->kobj, "powers");
 	power_supply_remove_triggers(psy);
+	psy_unregister_cooler(psy);
 	psy_unregister_thermal(psy);
 	device_unregister(psy->dev);
 }
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 395c2cf..40fa3b7 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -164,6 +164,8 @@ static struct device_attribute power_supply_attrs[] = {
 	POWER_SUPPLY_ATTR(constant_charge_current_max),
 	POWER_SUPPLY_ATTR(constant_charge_voltage),
 	POWER_SUPPLY_ATTR(constant_charge_voltage_max),
+	POWER_SUPPLY_ATTR(charge_control_limit),
+	POWER_SUPPLY_ATTR(charge_control_limit_max),
 	POWER_SUPPLY_ATTR(energy_full_design),
 	POWER_SUPPLY_ATTR(energy_empty_design),
 	POWER_SUPPLY_ATTR(energy_full),
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
new file mode 100644
index 0000000..6461b48
--- /dev/null
+++ b/drivers/power/reset/Kconfig
@@ -0,0 +1,15 @@
+menuconfig POWER_RESET
+	bool "Board level reset or power off"
+	help
+	  Provides a number of drivers which either reset a complete board
+	  or shut it down, by manipulating the main power supply on the board.
+
+	  Say Y here to enable board reset and power off
+
+config POWER_RESET_GPIO
+	bool "GPIO power-off driver"
+	depends on OF_GPIO && POWER_RESET
+	help
+	  This driver supports turning off your board via a GPIO line.
+	  If your board needs a GPIO high/low to power down, say Y and
+	  create a binding in your devicetree.
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
new file mode 100644
index 0000000..751488a
--- /dev/null
+++ b/drivers/power/reset/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c
new file mode 100644
index 0000000..0491e53
--- /dev/null
+++ b/drivers/power/reset/gpio-poweroff.c
@@ -0,0 +1,129 @@
+/*
+ * Toggles a GPIO pin to power down a device
+ *
+ * Jamie Lentin <jm@lentin.co.uk>
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * Copyright (C) 2012 Jamie Lentin
+ *
+ * This program is free software; you can redistribute 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/delay.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/module.h>
+
+/*
+ * Hold configuration here, cannot be more than one instance of the driver
+ * since pm_power_off itself is global.
+ */
+static int gpio_num = -1;
+static int gpio_active_low;
+
+static void gpio_poweroff_do_poweroff(void)
+{
+	BUG_ON(gpio_num == -1);
+
+	/* drive it active */
+	gpio_direction_output(gpio_num, !gpio_active_low);
+	mdelay(100);
+	/* rising edge or drive inactive */
+	gpio_set_value(gpio_num, gpio_active_low);
+	mdelay(100);
+	/* falling edge */
+	gpio_set_value(gpio_num, !gpio_active_low);
+
+	/* give it some time */
+	mdelay(3000);
+
+	WARN_ON(1);
+}
+
+static int __devinit gpio_poweroff_probe(struct platform_device *pdev)
+{
+	enum of_gpio_flags flags;
+	bool input = false;
+	int ret;
+
+	/* If a pm_power_off function has already been added, leave it alone */
+	if (pm_power_off != NULL) {
+		pr_err("%s: pm_power_off function already registered",
+		       __func__);
+		return -EBUSY;
+	}
+
+	gpio_num = of_get_gpio_flags(pdev->dev.of_node, 0, &flags);
+	if (gpio_num < 0) {
+		pr_err("%s: Could not get GPIO configuration: %d",
+		       __func__, gpio_num);
+		return -ENODEV;
+	}
+	gpio_active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+	if (of_get_property(pdev->dev.of_node, "input", NULL))
+		input = true;
+
+	ret = gpio_request(gpio_num, "poweroff-gpio");
+	if (ret) {
+		pr_err("%s: Could not get GPIO %d", __func__, gpio_num);
+		return ret;
+	}
+	if (input) {
+		if (gpio_direction_input(gpio_num)) {
+			pr_err("Could not set direction of GPIO %d to input",
+			       gpio_num);
+			goto err;
+		}
+	} else {
+		if (gpio_direction_output(gpio_num, gpio_active_low)) {
+			pr_err("Could not set direction of GPIO %d", gpio_num);
+			goto err;
+		}
+	}
+
+	pm_power_off = &gpio_poweroff_do_poweroff;
+	return 0;
+
+err:
+	gpio_free(gpio_num);
+	return -ENODEV;
+}
+
+static int __devexit gpio_poweroff_remove(struct platform_device *pdev)
+{
+	if (gpio_num != -1)
+		gpio_free(gpio_num);
+	if (pm_power_off == &gpio_poweroff_do_poweroff)
+		pm_power_off = NULL;
+
+	return 0;
+}
+
+static const struct of_device_id of_gpio_poweroff_match[] = {
+	{ .compatible = "gpio-poweroff", },
+	{},
+};
+
+static struct platform_driver gpio_poweroff_driver = {
+	.probe = gpio_poweroff_probe,
+	.remove = __devexit_p(gpio_poweroff_remove),
+	.driver = {
+		   .name = "poweroff-gpio",
+		   .owner = THIS_MODULE,
+		   .of_match_table = of_gpio_poweroff_match,
+		   },
+};
+
+module_platform_driver(gpio_poweroff_driver);
+
+MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>");
+MODULE_DESCRIPTION("GPIO poweroff driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:poweroff-gpio");
diff --git a/drivers/power/rx51_battery.c b/drivers/power/rx51_battery.c
new file mode 100644
index 0000000..ca49d6c
--- /dev/null
+++ b/drivers/power/rx51_battery.c
@@ -0,0 +1,251 @@
+/*
+ * Nokia RX-51 battery driver
+ *
+ * Copyright (C) 2012  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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/i2c/twl4030-madc.h>
+
+struct rx51_device_info {
+	struct device *dev;
+	struct power_supply bat;
+};
+
+/*
+ * Read ADCIN channel value, code copied from maemo kernel
+ */
+static int rx51_battery_read_adc(int channel)
+{
+	struct twl4030_madc_request req;
+
+	req.channels = 1 << channel;
+	req.do_avg = 1;
+	req.method = TWL4030_MADC_SW1;
+	req.func_cb = NULL;
+	req.type = TWL4030_MADC_WAIT;
+
+	if (twl4030_madc_conversion(&req) <= 0)
+		return -ENODATA;
+
+	return req.rbuf[channel];
+}
+
+/*
+ * Read ADCIN channel 12 (voltage) and convert RAW value to micro voltage
+ * This conversion formula was extracted from maemo program bsi-read
+ */
+static int rx51_battery_read_voltage(struct rx51_device_info *di)
+{
+	int voltage = rx51_battery_read_adc(12);
+
+	if (voltage < 0)
+		return voltage;
+
+	return 1000 * (10000 * voltage / 1705);
+}
+
+/*
+ * Temperature look-up tables
+ * TEMP = (1/(t1 + 1/298) - 273.15)
+ * Where t1 = (1/B) * ln((RAW_ADC_U * 2.5)/(R * I * 255))
+ * Formula is based on experimental data, RX-51 CAL data, maemo program bme
+ * and formula from da9052 driver with values R = 100, B = 3380, I = 0.00671
+ */
+
+/*
+ * Table1 (temperature for first 25 RAW values)
+ * Usage: TEMP = rx51_temp_table1[RAW]
+ *   RAW is between 1 and 24
+ *   TEMP is between 201 C and 55 C
+ */
+static u8 rx51_temp_table1[] = {
+	255, 201, 159, 138, 124, 114, 106,  99,  94,  89,  85,  82,  78,  75,
+	 73,  70,  68,  66,  64,  62,  61,  59,  57,  56,  55
+};
+
+/*
+ * Table2 (lowest RAW value for temperature)
+ * Usage: RAW = rx51_temp_table2[TEMP-rx51_temp_table2_first]
+ *   TEMP is between 53 C and -32 C
+ *   RAW is between 25 and 993
+ */
+#define rx51_temp_table2_first 53
+static u16 rx51_temp_table2[] = {
+	 25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  39,
+	 40,  41,  43,  44,  46,  48,  49,  51,  53,  55,  57,  59,  61,  64,
+	 66,  69,  71,  74,  77,  80,  83,  86,  90,  94,  97, 101, 106, 110,
+	115, 119, 125, 130, 136, 141, 148, 154, 161, 168, 176, 184, 202, 211,
+	221, 231, 242, 254, 266, 279, 293, 308, 323, 340, 357, 375, 395, 415,
+	437, 460, 485, 511, 539, 568, 600, 633, 669, 706, 747, 790, 836, 885,
+	937, 993, 1024
+};
+
+/*
+ * Read ADCIN channel 0 (battery temp) and convert value to tenths of Celsius
+ * Use Temperature look-up tables for conversation
+ */
+static int rx51_battery_read_temperature(struct rx51_device_info *di)
+{
+	int min = 0;
+	int max = ARRAY_SIZE(rx51_temp_table2) - 1;
+	int raw = rx51_battery_read_adc(0);
+
+	/* Zero and negative values are undefined */
+	if (raw <= 0)
+		return INT_MAX;
+
+	/* ADC channels are 10 bit, higher value are undefined */
+	if (raw >= (1 << 10))
+		return INT_MIN;
+
+	/* First check for temperature in first direct table */
+	if (raw < ARRAY_SIZE(rx51_temp_table1))
+		return rx51_temp_table1[raw] * 100;
+
+	/* Binary search RAW value in second inverse table */
+	while (max - min > 1) {
+		int mid = (max + min) / 2;
+		if (rx51_temp_table2[mid] <= raw)
+			min = mid;
+		else if (rx51_temp_table2[mid] > raw)
+			max = mid;
+		if (rx51_temp_table2[mid] == raw)
+			break;
+	}
+
+	return (rx51_temp_table2_first - min) * 100;
+}
+
+/*
+ * Read ADCIN channel 4 (BSI) and convert RAW value to micro Ah
+ * This conversion formula was extracted from maemo program bsi-read
+ */
+static int rx51_battery_read_capacity(struct rx51_device_info *di)
+{
+	int capacity = rx51_battery_read_adc(4);
+
+	if (capacity < 0)
+		return capacity;
+
+	return 1280 * (1200 * capacity)/(1024 - capacity);
+}
+
+/*
+ * Return power_supply property
+ */
+static int rx51_battery_get_property(struct power_supply *psy,
+					enum power_supply_property psp,
+					union power_supply_propval *val)
+{
+	struct rx51_device_info *di = container_of((psy),
+				struct rx51_device_info, bat);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_TECHNOLOGY:
+		val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+		val->intval = 4200000;
+		break;
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = rx51_battery_read_voltage(di) ? 1 : 0;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		val->intval = rx51_battery_read_voltage(di);
+		break;
+	case POWER_SUPPLY_PROP_TEMP:
+		val->intval = rx51_battery_read_temperature(di);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+		val->intval = rx51_battery_read_capacity(di);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (val->intval == INT_MAX || val->intval == INT_MIN)
+		return -EINVAL;
+
+	return 0;
+}
+
+static enum power_supply_property rx51_battery_props[] = {
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+};
+
+static int __devinit rx51_battery_probe(struct platform_device *pdev)
+{
+	struct rx51_device_info *di;
+	int ret;
+
+	di = kzalloc(sizeof(*di), GFP_KERNEL);
+	if (!di)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, di);
+
+	di->bat.name = dev_name(&pdev->dev);
+	di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
+	di->bat.properties = rx51_battery_props;
+	di->bat.num_properties = ARRAY_SIZE(rx51_battery_props);
+	di->bat.get_property = rx51_battery_get_property;
+
+	ret = power_supply_register(di->dev, &di->bat);
+	if (ret) {
+		platform_set_drvdata(pdev, NULL);
+		kfree(di);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __devexit rx51_battery_remove(struct platform_device *pdev)
+{
+	struct rx51_device_info *di = platform_get_drvdata(pdev);
+
+	power_supply_unregister(&di->bat);
+	platform_set_drvdata(pdev, NULL);
+	kfree(di);
+
+	return 0;
+}
+
+static struct platform_driver rx51_battery_driver = {
+	.probe = rx51_battery_probe,
+	.remove = __devexit_p(rx51_battery_remove),
+	.driver = {
+		.name = "rx51-battery",
+		.owner = THIS_MODULE,
+	},
+};
+module_platform_driver(rx51_battery_driver);
+
+MODULE_ALIAS("platform:rx51-battery");
+MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
+MODULE_DESCRIPTION("Nokia RX-51 battery driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/s3c_adc_battery.c b/drivers/power/s3c_adc_battery.c
index 8b804a5..d2ca989 100644
--- a/drivers/power/s3c_adc_battery.c
+++ b/drivers/power/s3c_adc_battery.c
@@ -286,7 +286,7 @@ static irqreturn_t s3c_adc_bat_charged(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit s3c_adc_bat_probe(struct platform_device *pdev)
+static int s3c_adc_bat_probe(struct platform_device *pdev)
 {
 	struct s3c_adc_client	*client;
 	struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data;
diff --git a/drivers/power/sbs-battery.c b/drivers/power/sbs-battery.c
index 4146596..3960f0b 100644
--- a/drivers/power/sbs-battery.c
+++ b/drivers/power/sbs-battery.c
@@ -675,7 +675,7 @@ static struct sbs_platform_data *sbs_of_populate_pdata(
 }
 #endif
 
-static int __devinit sbs_probe(struct i2c_client *client,
+static int sbs_probe(struct i2c_client *client,
 	const struct i2c_device_id *id)
 {
 	struct sbs_info *chip;
@@ -800,7 +800,7 @@ exit_free_name:
 	return rc;
 }
 
-static int __devexit sbs_remove(struct i2c_client *client)
+static int sbs_remove(struct i2c_client *client)
 {
 	struct sbs_info *chip = i2c_get_clientdata(client);
 
@@ -853,7 +853,7 @@ MODULE_DEVICE_TABLE(i2c, sbs_id);
 
 static struct i2c_driver sbs_battery_driver = {
 	.probe		= sbs_probe,
-	.remove		= __devexit_p(sbs_remove),
+	.remove		= sbs_remove,
 	.suspend	= sbs_suspend,
 	.resume		= sbs_resume,
 	.id_table	= sbs_id,
diff --git a/drivers/power/smb347-charger.c b/drivers/power/smb347-charger.c
index a9707c1..acf84e8 100644
--- a/drivers/power/smb347-charger.c
+++ b/drivers/power/smb347-charger.c
@@ -1313,7 +1313,7 @@ static struct i2c_driver smb347_driver = {
 		.name = "smb347",
 	},
 	.probe        = smb347_probe,
-	.remove       = __devexit_p(smb347_remove),
+	.remove       = smb347_remove,
 	.id_table     = smb347_id,
 };
 
diff --git a/drivers/power/tosa_battery.c b/drivers/power/tosa_battery.c
index 51199b5..0224de5 100644
--- a/drivers/power/tosa_battery.c
+++ b/drivers/power/tosa_battery.c
@@ -342,7 +342,7 @@ static int tosa_bat_resume(struct platform_device *dev)
 #define tosa_bat_resume NULL
 #endif
 
-static int __devinit tosa_bat_probe(struct platform_device *dev)
+static int tosa_bat_probe(struct platform_device *dev)
 {
 	int ret;
 
@@ -409,7 +409,7 @@ err_psy_reg_main:
 	return ret;
 }
 
-static int __devexit tosa_bat_remove(struct platform_device *dev)
+static int tosa_bat_remove(struct platform_device *dev)
 {
 	free_irq(gpio_to_irq(TOSA_GPIO_JACKET_DETECT), &tosa_bat_jacket);
 	free_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG), &tosa_bat_jacket);
@@ -433,7 +433,7 @@ static struct platform_driver tosa_bat_driver = {
 	.driver.name	= "wm97xx-battery",
 	.driver.owner	= THIS_MODULE,
 	.probe		= tosa_bat_probe,
-	.remove		= __devexit_p(tosa_bat_remove),
+	.remove		= tosa_bat_remove,
 	.suspend	= tosa_bat_suspend,
 	.resume		= tosa_bat_resume,
 };
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index f9e70cf..a69d0d1 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -114,12 +114,12 @@ static int twl4030_clear_set(u8 mod_no, u8 clear, u8 set, u8 reg)
 
 static int twl4030_bci_read(u8 reg, u8 *val)
 {
-	return twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, val, reg);
+	return twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, val, reg);
 }
 
 static int twl4030_clear_set_boot_bci(u8 clear, u8 set)
 {
-	return twl4030_clear_set(TWL4030_MODULE_PM_MASTER, clear,
+	return twl4030_clear_set(TWL_MODULE_PM_MASTER, clear,
 			TWL4030_CONFIG_DONE | TWL4030_BCIAUTOWEN | set,
 			TWL4030_PM_MASTER_BOOT_BCI);
 }
@@ -152,7 +152,7 @@ static int twl4030_bci_have_vbus(struct twl4030_bci *bci)
 	int ret;
 	u8 hwsts;
 
-	ret = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &hwsts,
+	ret = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &hwsts,
 			      TWL4030_PM_MASTER_STS_HW_CONDITIONS);
 	if (ret < 0)
 		return 0;
@@ -199,7 +199,7 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
 			return ret;
 
 		/* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */
-		ret = twl4030_clear_set(TWL4030_MODULE_MAIN_CHARGE, 0,
+		ret = twl4030_clear_set(TWL_MODULE_MAIN_CHARGE, 0,
 			TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4);
 	} else {
 		ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0);
@@ -238,7 +238,7 @@ static int twl4030_charger_enable_backup(int uvolt, int uamp)
 	if (uvolt < 2500000 ||
 	    uamp < 25) {
 		/* disable charging of backup battery */
-		ret = twl4030_clear_set(TWL4030_MODULE_PM_RECEIVER,
+		ret = twl4030_clear_set(TWL_MODULE_PM_RECEIVER,
 					TWL4030_BBCHEN, 0, TWL4030_BB_CFG);
 		return ret;
 	}
@@ -262,7 +262,7 @@ static int twl4030_charger_enable_backup(int uvolt, int uamp)
 	else
 		flags |= TWL4030_BBISEL_25uA;
 
-	ret = twl4030_clear_set(TWL4030_MODULE_PM_RECEIVER,
+	ret = twl4030_clear_set(TWL_MODULE_PM_RECEIVER,
 				TWL4030_BBSEL_MASK | TWL4030_BBISEL_MASK,
 				flags,
 				TWL4030_BB_CFG);
diff --git a/drivers/power/wm831x_backup.c b/drivers/power/wm831x_backup.c
index 6243e69..d9cc169 100644
--- a/drivers/power/wm831x_backup.c
+++ b/drivers/power/wm831x_backup.c
@@ -161,7 +161,7 @@ static enum power_supply_property wm831x_backup_props[] = {
  *		Initialisation
  *********************************************************************/
 
-static __devinit int wm831x_backup_probe(struct platform_device *pdev)
+static int wm831x_backup_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 	struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
@@ -207,7 +207,7 @@ err_kmalloc:
 	return ret;
 }
 
-static __devexit int wm831x_backup_remove(struct platform_device *pdev)
+static int wm831x_backup_remove(struct platform_device *pdev)
 {
 	struct wm831x_backup *devdata = platform_get_drvdata(pdev);
 
@@ -220,7 +220,7 @@ static __devexit int wm831x_backup_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_backup_driver = {
 	.probe = wm831x_backup_probe,
-	.remove = __devexit_p(wm831x_backup_remove),
+	.remove = wm831x_backup_remove,
 	.driver = {
 		.name = "wm831x-backup",
 	},
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index fc1ad95..3bed2f5 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -489,7 +489,7 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static __devinit int wm831x_power_probe(struct platform_device *pdev)
+static int wm831x_power_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 	struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
@@ -625,7 +625,7 @@ err_kmalloc:
 	return ret;
 }
 
-static __devexit int wm831x_power_remove(struct platform_device *pdev)
+static int wm831x_power_remove(struct platform_device *pdev)
 {
 	struct wm831x_power *wm831x_power = platform_get_drvdata(pdev);
 	struct wm831x *wm831x = wm831x_power->wm831x;
@@ -654,7 +654,7 @@ static __devexit int wm831x_power_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_power_driver = {
 	.probe = wm831x_power_probe,
-	.remove = __devexit_p(wm831x_power_remove),
+	.remove = wm831x_power_remove,
 	.driver = {
 		.name = "wm831x-power",
 	},
diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c
index fae04d3..b3607e2 100644
--- a/drivers/power/wm8350_power.c
+++ b/drivers/power/wm8350_power.c
@@ -442,7 +442,7 @@ static void free_charger_irq(struct wm8350 *wm8350)
 	wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, wm8350);
 }
 
-static __devinit int wm8350_power_probe(struct platform_device *pdev)
+static int wm8350_power_probe(struct platform_device *pdev)
 {
 	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
 	struct wm8350_power *power = &wm8350->power;
@@ -501,7 +501,7 @@ battery_failed:
 	return ret;
 }
 
-static __devexit int wm8350_power_remove(struct platform_device *pdev)
+static int wm8350_power_remove(struct platform_device *pdev)
 {
 	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
 	struct wm8350_power *power = &wm8350->power;
@@ -516,7 +516,7 @@ static __devexit int wm8350_power_remove(struct platform_device *pdev)
 
 static struct platform_driver wm8350_power_driver = {
 	.probe = wm8350_power_probe,
-	.remove = __devexit_p(wm8350_power_remove),
+	.remove = wm8350_power_remove,
 	.driver = {
 		.name = "wm8350-power",
 	},
diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c
index e128a81..58f7348 100644
--- a/drivers/power/wm97xx_battery.c
+++ b/drivers/power/wm97xx_battery.c
@@ -162,7 +162,7 @@ static const struct dev_pm_ops wm97xx_bat_pm_ops = {
 };
 #endif
 
-static int __devinit wm97xx_bat_probe(struct platform_device *dev)
+static int wm97xx_bat_probe(struct platform_device *dev)
 {
 	int ret = 0;
 	int props = 1;	/* POWER_SUPPLY_PROP_PRESENT */
@@ -263,7 +263,7 @@ err:
 	return ret;
 }
 
-static int __devexit wm97xx_bat_remove(struct platform_device *dev)
+static int wm97xx_bat_remove(struct platform_device *dev)
 {
 	struct wm97xx_pdata *wmdata = dev->dev.platform_data;
 	struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata;
@@ -287,7 +287,7 @@ static struct platform_driver wm97xx_bat_driver = {
 #endif
 	},
 	.probe		= wm97xx_bat_probe,
-	.remove		= __devexit_p(wm97xx_bat_remove),
+	.remove		= wm97xx_bat_remove,
 };
 
 module_platform_driver(wm97xx_bat_driver);
diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c
index 5757d0d..814d2e3 100644
--- a/drivers/power/z2_battery.c
+++ b/drivers/power/z2_battery.c
@@ -180,7 +180,7 @@ static int z2_batt_ps_init(struct z2_charger *charger, int props)
 	return 0;
 }
 
-static int __devinit z2_batt_probe(struct i2c_client *client,
+static int z2_batt_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
 	int ret = 0;
@@ -251,7 +251,7 @@ err:
 	return ret;
 }
 
-static int __devexit z2_batt_remove(struct i2c_client *client)
+static int z2_batt_remove(struct i2c_client *client)
 {
 	struct z2_charger *charger = i2c_get_clientdata(client);
 	struct z2_battery_info *info = charger->info;
@@ -313,7 +313,7 @@ static struct i2c_driver z2_batt_driver = {
 		.pm	= Z2_BATTERY_PM_OPS
 	},
 	.probe		= z2_batt_probe,
-	.remove		= __devexit_p(z2_batt_remove),
+	.remove		= z2_batt_remove,
 	.id_table	= z2_batt_id,
 };
 module_i2c_driver(z2_batt_driver);
diff --git a/drivers/pps/Kconfig b/drivers/pps/Kconfig
index 258ca59..982d16b 100644
--- a/drivers/pps/Kconfig
+++ b/drivers/pps/Kconfig
@@ -6,7 +6,6 @@ menu "PPS support"
 
 config PPS
 	tristate "PPS support"
-	depends on EXPERIMENTAL
 	---help---
 	  PPS (Pulse Per Second) is a special pulse provided by some GPS
 	  antennae. Userland can use it to get a high-precision time
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index ffdf712..1ea6f1d 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -4,13 +4,9 @@
 
 menu "PTP clock support"
 
-comment "Enable Device Drivers -> PPS to see the PTP clock options."
-	depends on PPS=n
-
 config PTP_1588_CLOCK
 	tristate "PTP clock support"
-	depends on EXPERIMENTAL
-	depends on PPS
+	select PPS
 	help
 	  The IEEE 1588 standard defines a method to precisely
 	  synchronize distributed clocks over Ethernet networks. The
@@ -29,8 +25,9 @@ config PTP_1588_CLOCK
 
 config PTP_1588_CLOCK_GIANFAR
 	tristate "Freescale eTSEC as PTP clock"
-	depends on PTP_1588_CLOCK
 	depends on GIANFAR
+	select PTP_1588_CLOCK
+	default y
 	help
 	  This driver adds support for using the eTSEC as a PTP
 	  clock. This clock is only useful if your PTP programs are
@@ -42,8 +39,9 @@ config PTP_1588_CLOCK_GIANFAR
 
 config PTP_1588_CLOCK_IXP46X
 	tristate "Intel IXP46x as PTP clock"
-	depends on PTP_1588_CLOCK
 	depends on IXP4XX_ETH
+	select PTP_1588_CLOCK
+	default y
 	help
 	  This driver adds support for using the IXP46X as a PTP
 	  clock. This clock is only useful if your PTP programs are
@@ -54,13 +52,13 @@ config PTP_1588_CLOCK_IXP46X
 	  will be called ptp_ixp46x.
 
 comment "Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks."
-	depends on PTP_1588_CLOCK && (PHYLIB=n || NETWORK_PHY_TIMESTAMPING=n)
+	depends on PHYLIB=n || NETWORK_PHY_TIMESTAMPING=n
 
 config DP83640_PHY
 	tristate "Driver for the National Semiconductor DP83640 PHYTER"
-	depends on PTP_1588_CLOCK
 	depends on NETWORK_PHY_TIMESTAMPING
 	depends on PHYLIB
+	select PTP_1588_CLOCK
 	---help---
 	  Supports the DP83640 PHYTER with IEEE 1588 features.
 
@@ -74,8 +72,7 @@ config DP83640_PHY
 
 config PTP_1588_CLOCK_PCH
 	tristate "Intel PCH EG20T as PTP clock"
-	depends on PTP_1588_CLOCK
-	depends on PCH_GBE
+	select PTP_1588_CLOCK
 	help
 	  This driver adds support for using the PCH EG20T as a PTP
 	  clock. The hardware supports time stamping of PTP packets
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
index e7f301da2..34a0c60 100644
--- a/drivers/ptp/ptp_chardev.c
+++ b/drivers/ptp/ptp_chardev.c
@@ -21,6 +21,7 @@
 #include <linux/posix-clock.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
 
 #include "ptp_private.h"
 
@@ -33,9 +34,13 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
 {
 	struct ptp_clock_caps caps;
 	struct ptp_clock_request req;
+	struct ptp_sys_offset *sysoff = NULL;
 	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
 	struct ptp_clock_info *ops = ptp->info;
+	struct ptp_clock_time *pct;
+	struct timespec ts;
 	int enable, err = 0;
+	unsigned int i;
 
 	switch (cmd) {
 
@@ -88,10 +93,45 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
 		err = ops->enable(ops, &req, enable);
 		break;
 
+	case PTP_SYS_OFFSET:
+		sysoff = kmalloc(sizeof(*sysoff), GFP_KERNEL);
+		if (!sysoff) {
+			err = -ENOMEM;
+			break;
+		}
+		if (copy_from_user(sysoff, (void __user *)arg,
+				   sizeof(*sysoff))) {
+			err = -EFAULT;
+			break;
+		}
+		if (sysoff->n_samples > PTP_MAX_SAMPLES) {
+			err = -EINVAL;
+			break;
+		}
+		pct = &sysoff->ts[0];
+		for (i = 0; i < sysoff->n_samples; i++) {
+			getnstimeofday(&ts);
+			pct->sec = ts.tv_sec;
+			pct->nsec = ts.tv_nsec;
+			pct++;
+			ptp->info->gettime(ptp->info, &ts);
+			pct->sec = ts.tv_sec;
+			pct->nsec = ts.tv_nsec;
+			pct++;
+		}
+		getnstimeofday(&ts);
+		pct->sec = ts.tv_sec;
+		pct->nsec = ts.tv_nsec;
+		if (copy_to_user((void __user *)arg, sysoff, sizeof(*sysoff)))
+			err = -EFAULT;
+		break;
+
 	default:
 		err = -ENOTTY;
 		break;
 	}
+
+	kfree(sysoff);
 	return err;
 }
 
@@ -104,20 +144,23 @@ unsigned int ptp_poll(struct posix_clock *pc, struct file *fp, poll_table *wait)
 	return queue_cnt(&ptp->tsevq) ? POLLIN : 0;
 }
 
+#define EXTTS_BUFSIZE (PTP_BUF_TIMESTAMPS * sizeof(struct ptp_extts_event))
+
 ssize_t ptp_read(struct posix_clock *pc,
 		 uint rdflags, char __user *buf, size_t cnt)
 {
 	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
 	struct timestamp_event_queue *queue = &ptp->tsevq;
-	struct ptp_extts_event event[PTP_BUF_TIMESTAMPS];
+	struct ptp_extts_event *event;
 	unsigned long flags;
 	size_t qcnt, i;
+	int result;
 
 	if (cnt % sizeof(struct ptp_extts_event) != 0)
 		return -EINVAL;
 
-	if (cnt > sizeof(event))
-		cnt = sizeof(event);
+	if (cnt > EXTTS_BUFSIZE)
+		cnt = EXTTS_BUFSIZE;
 
 	cnt = cnt / sizeof(struct ptp_extts_event);
 
@@ -135,6 +178,12 @@ ssize_t ptp_read(struct posix_clock *pc,
 		return -ENODEV;
 	}
 
+	event = kmalloc(EXTTS_BUFSIZE, GFP_KERNEL);
+	if (!event) {
+		mutex_unlock(&ptp->tsevq_mux);
+		return -ENOMEM;
+	}
+
 	spin_lock_irqsave(&queue->lock, flags);
 
 	qcnt = queue_cnt(queue);
@@ -153,8 +202,10 @@ ssize_t ptp_read(struct posix_clock *pc,
 
 	mutex_unlock(&ptp->tsevq_mux);
 
+	result = cnt;
 	if (copy_to_user(buf, event, cnt))
-		return -EFAULT;
+		result = -EFAULT;
 
-	return cnt;
+	kfree(event);
+	return result;
 }
diff --git a/drivers/ptp/ptp_pch.c b/drivers/ptp/ptp_pch.c
index e624e4d..1367655 100644
--- a/drivers/ptp/ptp_pch.c
+++ b/drivers/ptp/ptp_pch.c
@@ -557,7 +557,7 @@ static s32 pch_resume(struct pci_dev *pdev)
 #define pch_resume NULL
 #endif
 
-static void __devexit pch_remove(struct pci_dev *pdev)
+static void pch_remove(struct pci_dev *pdev)
 {
 	struct pch_dev *chip = pci_get_drvdata(pdev);
 
@@ -581,7 +581,7 @@ static void __devexit pch_remove(struct pci_dev *pdev)
 	dev_info(&pdev->dev, "complete\n");
 }
 
-static s32 __devinit
+static s32
 pch_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	s32 ret;
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index ed81720..e513cd9 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -112,6 +112,17 @@ config PWM_SAMSUNG
 	  To compile this driver as a module, choose M here: the module
 	  will be called pwm-samsung.
 
+config PWM_SPEAR
+	tristate "STMicroelectronics SPEAr PWM support"
+	depends on PLAT_SPEAR
+	depends on OF
+	help
+	  Generic PWM framework driver for the PWM controller on ST
+	  SPEAr SoCs.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pwm-spear.
+
 config PWM_TEGRA
 	tristate "NVIDIA Tegra PWM support"
 	depends on ARCH_TEGRA
@@ -125,6 +136,7 @@ config PWM_TEGRA
 config  PWM_TIECAP
 	tristate "ECAP PWM support"
 	depends on SOC_AM33XX
+	select PWM_TIPWMSS
 	help
 	  PWM driver support for the ECAP APWM controller found on AM33XX
 	  TI SOC
@@ -135,6 +147,7 @@ config  PWM_TIECAP
 config  PWM_TIEHRPWM
 	tristate "EHRPWM PWM support"
 	depends on SOC_AM33XX
+	select PWM_TIPWMSS
 	help
 	  PWM driver support for the EHRPWM controller found on AM33XX
 	  TI SOC
@@ -142,14 +155,32 @@ config  PWM_TIEHRPWM
 	  To compile this driver as a module, choose M here: the module
 	  will be called pwm-tiehrpwm.
 
-config PWM_TWL6030
-	tristate "TWL6030 PWM support"
+config  PWM_TIPWMSS
+	bool
+	depends on SOC_AM33XX && (PWM_TIEHRPWM || PWM_TIECAP)
+	help
+	  PWM Subsystem driver support for AM33xx SOC.
+
+	  PWM submodules require PWM config space access from submodule
+	  drivers and require common parent driver support.
+
+config PWM_TWL
+	tristate "TWL4030/6030 PWM support"
+	depends on TWL4030_CORE
+	help
+	  Generic PWM framework driver for TWL4030/6030.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pwm-twl.
+
+config PWM_TWL_LED
+	tristate "TWL4030/6030 PWM support for LED drivers"
 	depends on TWL4030_CORE
 	help
-	  Generic PWM framework driver for TWL6030.
+	  Generic PWM framework driver for TWL4030/6030 LED terminals.
 
 	  To compile this driver as a module, choose M here: the module
-	  will be called pwm-twl6030.
+	  will be called pwm-twl-led.
 
 config PWM_VT8500
 	tristate "vt8500 pwm support"
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index acfe482..62a2963 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -8,8 +8,11 @@ obj-$(CONFIG_PWM_MXS)		+= pwm-mxs.o
 obj-$(CONFIG_PWM_PUV3)		+= pwm-puv3.o
 obj-$(CONFIG_PWM_PXA)		+= pwm-pxa.o
 obj-$(CONFIG_PWM_SAMSUNG)	+= pwm-samsung.o
+obj-$(CONFIG_PWM_SPEAR)		+= pwm-spear.o
 obj-$(CONFIG_PWM_TEGRA)		+= pwm-tegra.o
 obj-$(CONFIG_PWM_TIECAP)	+= pwm-tiecap.o
 obj-$(CONFIG_PWM_TIEHRPWM)	+= pwm-tiehrpwm.o
-obj-$(CONFIG_PWM_TWL6030)	+= pwm-twl6030.o
+obj-$(CONFIG_PWM_TIPWMSS)	+= pwm-tipwmss.o
+obj-$(CONFIG_PWM_TWL)		+= pwm-twl.o
+obj-$(CONFIG_PWM_TWL_LED)	+= pwm-twl-led.o
 obj-$(CONFIG_PWM_VT8500)	+= pwm-vt8500.o
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index f5acdaa..903138b 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -32,6 +32,9 @@
 
 #define MAX_PWMS 1024
 
+/* flags in the third cell of the DT PWM specifier */
+#define PWM_SPEC_POLARITY	(1 << 0)
+
 static DEFINE_MUTEX(pwm_lookup_lock);
 static LIST_HEAD(pwm_lookup_list);
 static DEFINE_MUTEX(pwm_lock);
@@ -129,6 +132,32 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label)
 	return 0;
 }
 
+struct pwm_device *
+of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
+{
+	struct pwm_device *pwm;
+
+	if (pc->of_pwm_n_cells < 3)
+		return ERR_PTR(-EINVAL);
+
+	if (args->args[0] >= pc->npwm)
+		return ERR_PTR(-EINVAL);
+
+	pwm = pwm_request_from_chip(pc, args->args[0], NULL);
+	if (IS_ERR(pwm))
+		return pwm;
+
+	pwm_set_period(pwm, args->args[1]);
+
+	if (args->args[2] & PWM_SPEC_POLARITY)
+		pwm_set_polarity(pwm, PWM_POLARITY_INVERSED);
+	else
+		pwm_set_polarity(pwm, PWM_POLARITY_NORMAL);
+
+	return pwm;
+}
+EXPORT_SYMBOL_GPL(of_pwm_xlate_with_flags);
+
 static struct pwm_device *
 of_pwm_simple_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
 {
diff --git a/drivers/pwm/pwm-ab8500.c b/drivers/pwm/pwm-ab8500.c
index cfb72ca..4248d04 100644
--- a/drivers/pwm/pwm-ab8500.c
+++ b/drivers/pwm/pwm-ab8500.c
@@ -90,7 +90,7 @@ static const struct pwm_ops ab8500_pwm_ops = {
 	.disable = ab8500_pwm_disable,
 };
 
-static int __devinit ab8500_pwm_probe(struct platform_device *pdev)
+static int ab8500_pwm_probe(struct platform_device *pdev)
 {
 	struct ab8500_pwm_chip *ab8500;
 	int err;
@@ -122,7 +122,7 @@ static int __devinit ab8500_pwm_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit ab8500_pwm_remove(struct platform_device *pdev)
+static int ab8500_pwm_remove(struct platform_device *pdev)
 {
 	struct ab8500_pwm_chip *ab8500 = platform_get_drvdata(pdev);
 	int err;
@@ -143,7 +143,7 @@ static struct platform_driver ab8500_pwm_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ab8500_pwm_probe,
-	.remove = __devexit_p(ab8500_pwm_remove),
+	.remove = ab8500_pwm_remove,
 };
 module_platform_driver(ab8500_pwm_driver);
 
diff --git a/drivers/pwm/pwm-bfin.c b/drivers/pwm/pwm-bfin.c
index 5da8e18..7631ef1 100644
--- a/drivers/pwm/pwm-bfin.c
+++ b/drivers/pwm/pwm-bfin.c
@@ -139,7 +139,7 @@ static int bfin_pwm_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit bfin_pwm_remove(struct platform_device *pdev)
+static int bfin_pwm_remove(struct platform_device *pdev)
 {
 	struct bfin_pwm_chip *pwm = platform_get_drvdata(pdev);
 
@@ -151,7 +151,7 @@ static struct platform_driver bfin_pwm_driver = {
 		.name = "bfin-pwm",
 	},
 	.probe = bfin_pwm_probe,
-	.remove = __devexit_p(bfin_pwm_remove),
+	.remove = bfin_pwm_remove,
 };
 
 module_platform_driver(bfin_pwm_driver);
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 8a5d3ae..8f26e9f 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -231,7 +231,7 @@ static const struct of_device_id imx_pwm_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, imx_pwm_dt_ids);
 
-static int __devinit imx_pwm_probe(struct platform_device *pdev)
+static int imx_pwm_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id =
 			of_match_device(imx_pwm_dt_ids, &pdev->dev);
@@ -290,7 +290,7 @@ static int __devinit imx_pwm_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit imx_pwm_remove(struct platform_device *pdev)
+static int imx_pwm_remove(struct platform_device *pdev)
 {
 	struct imx_chip *imx;
 
@@ -307,7 +307,7 @@ static struct platform_driver imx_pwm_driver = {
 		.of_match_table = of_match_ptr(imx_pwm_dt_ids),
 	},
 	.probe		= imx_pwm_probe,
-	.remove		= __devexit_p(imx_pwm_remove),
+	.remove		= imx_pwm_remove,
 };
 
 module_platform_driver(imx_pwm_driver);
diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
index 10250fc..0a2ede3 100644
--- a/drivers/pwm/pwm-jz4740.c
+++ b/drivers/pwm/pwm-jz4740.c
@@ -162,7 +162,7 @@ static const struct pwm_ops jz4740_pwm_ops = {
 	.owner = THIS_MODULE,
 };
 
-static int __devinit jz4740_pwm_probe(struct platform_device *pdev)
+static int jz4740_pwm_probe(struct platform_device *pdev)
 {
 	struct jz4740_pwm_chip *jz4740;
 	int ret;
@@ -191,7 +191,7 @@ static int __devinit jz4740_pwm_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit jz4740_pwm_remove(struct platform_device *pdev)
+static int jz4740_pwm_remove(struct platform_device *pdev)
 {
 	struct jz4740_pwm_chip *jz4740 = platform_get_drvdata(pdev);
 	int ret;
@@ -211,7 +211,7 @@ static struct platform_driver jz4740_pwm_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = jz4740_pwm_probe,
-	.remove = __devexit_p(jz4740_pwm_remove),
+	.remove = jz4740_pwm_remove,
 };
 module_platform_driver(jz4740_pwm_driver);
 
diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c
index adb87f0..015a822 100644
--- a/drivers/pwm/pwm-lpc32xx.c
+++ b/drivers/pwm/pwm-lpc32xx.c
@@ -118,7 +118,7 @@ static int lpc32xx_pwm_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit lpc32xx_pwm_remove(struct platform_device *pdev)
+static int lpc32xx_pwm_remove(struct platform_device *pdev)
 {
 	struct lpc32xx_pwm_chip *lpc32xx = platform_get_drvdata(pdev);
 
@@ -138,7 +138,7 @@ static struct platform_driver lpc32xx_pwm_driver = {
 		.of_match_table = of_match_ptr(lpc32xx_pwm_dt_ids),
 	},
 	.probe = lpc32xx_pwm_probe,
-	.remove = __devexit_p(lpc32xx_pwm_remove),
+	.remove = lpc32xx_pwm_remove,
 };
 module_platform_driver(lpc32xx_pwm_driver);
 
diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c
index e585264..7ec345f 100644
--- a/drivers/pwm/pwm-mxs.c
+++ b/drivers/pwm/pwm-mxs.c
@@ -174,7 +174,7 @@ static int mxs_pwm_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit mxs_pwm_remove(struct platform_device *pdev)
+static int mxs_pwm_remove(struct platform_device *pdev)
 {
 	struct mxs_pwm_chip *mxs = platform_get_drvdata(pdev);
 
@@ -193,7 +193,7 @@ static struct platform_driver mxs_pwm_driver = {
 		.of_match_table = of_match_ptr(mxs_pwm_dt_ids),
 	},
 	.probe = mxs_pwm_probe,
-	.remove = __devexit_p(mxs_pwm_remove),
+	.remove = mxs_pwm_remove,
 };
 module_platform_driver(mxs_pwm_driver);
 
diff --git a/drivers/pwm/pwm-puv3.c b/drivers/pwm/pwm-puv3.c
index 2a93f37..b882f60 100644
--- a/drivers/pwm/pwm-puv3.c
+++ b/drivers/pwm/pwm-puv3.c
@@ -101,7 +101,7 @@ static const struct pwm_ops puv3_pwm_ops = {
 	.owner = THIS_MODULE,
 };
 
-static int __devinit pwm_probe(struct platform_device *pdev)
+static int pwm_probe(struct platform_device *pdev)
 {
 	struct puv3_pwm_chip *puv3;
 	struct resource *r;
@@ -142,7 +142,7 @@ static int __devinit pwm_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit pwm_remove(struct platform_device *pdev)
+static int pwm_remove(struct platform_device *pdev)
 {
 	struct puv3_pwm_chip *puv3 = platform_get_drvdata(pdev);
 
@@ -154,7 +154,7 @@ static struct platform_driver puv3_pwm_driver = {
 		.name = "PKUnity-v3-PWM",
 	},
 	.probe = pwm_probe,
-	.remove = __devexit_p(pwm_remove),
+	.remove = pwm_remove,
 };
 module_platform_driver(puv3_pwm_driver);
 
diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
index 260c3a8..f32fc4e 100644
--- a/drivers/pwm/pwm-pxa.c
+++ b/drivers/pwm/pwm-pxa.c
@@ -135,7 +135,7 @@ static struct pwm_ops pxa_pwm_ops = {
 	.owner = THIS_MODULE,
 };
 
-static int __devinit pwm_probe(struct platform_device *pdev)
+static int pwm_probe(struct platform_device *pdev)
 {
 	const struct platform_device_id *id = platform_get_device_id(pdev);
 	struct pxa_pwm_chip *pwm;
@@ -179,7 +179,7 @@ static int __devinit pwm_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit pwm_remove(struct platform_device *pdev)
+static int pwm_remove(struct platform_device *pdev)
 {
 	struct pxa_pwm_chip *chip;
 
@@ -196,7 +196,7 @@ static struct platform_driver pwm_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= pwm_probe,
-	.remove		= __devexit_p(pwm_remove),
+	.remove		= pwm_remove,
 	.id_table	= pwm_id_table,
 };
 
diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
index 023a3be..e9b15d0 100644
--- a/drivers/pwm/pwm-samsung.c
+++ b/drivers/pwm/pwm-samsung.c
@@ -273,7 +273,7 @@ static int s3c_pwm_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit s3c_pwm_remove(struct platform_device *pdev)
+static int s3c_pwm_remove(struct platform_device *pdev)
 {
 	struct s3c_chip *s3c = platform_get_drvdata(pdev);
 	int err;
@@ -327,7 +327,7 @@ static struct platform_driver s3c_pwm_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= s3c_pwm_probe,
-	.remove		= __devexit_p(s3c_pwm_remove),
+	.remove		= s3c_pwm_remove,
 	.suspend	= s3c_pwm_suspend,
 	.resume		= s3c_pwm_resume,
 };
diff --git a/drivers/pwm/pwm-spear.c b/drivers/pwm/pwm-spear.c
new file mode 100644
index 0000000..83b21d9
--- /dev/null
+++ b/drivers/pwm/pwm-spear.c
@@ -0,0 +1,276 @@
+/*
+ * ST Microelectronics SPEAr Pulse Width Modulator driver
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Shiraz Hashim <shiraz.hashim@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define NUM_PWM		4
+
+/* PWM registers and bits definitions */
+#define PWMCR			0x00	/* Control Register */
+#define PWMCR_PWM_ENABLE	0x1
+#define PWMCR_PRESCALE_SHIFT	2
+#define PWMCR_MIN_PRESCALE	0x00
+#define PWMCR_MAX_PRESCALE	0x3FFF
+
+#define PWMDCR			0x04	/* Duty Cycle Register */
+#define PWMDCR_MIN_DUTY		0x0001
+#define PWMDCR_MAX_DUTY		0xFFFF
+
+#define PWMPCR			0x08	/* Period Register */
+#define PWMPCR_MIN_PERIOD	0x0001
+#define PWMPCR_MAX_PERIOD	0xFFFF
+
+/* Following only available on 13xx SoCs */
+#define PWMMCR			0x3C	/* Master Control Register */
+#define PWMMCR_PWM_ENABLE	0x1
+
+/**
+ * struct spear_pwm_chip - struct representing pwm chip
+ *
+ * @mmio_base: base address of pwm chip
+ * @clk: pointer to clk structure of pwm chip
+ * @chip: linux pwm chip representation
+ * @dev: pointer to device structure of pwm chip
+ */
+struct spear_pwm_chip {
+	void __iomem *mmio_base;
+	struct clk *clk;
+	struct pwm_chip chip;
+	struct device *dev;
+};
+
+static inline struct spear_pwm_chip *to_spear_pwm_chip(struct pwm_chip *chip)
+{
+	return container_of(chip, struct spear_pwm_chip, chip);
+}
+
+static inline u32 spear_pwm_readl(struct spear_pwm_chip *chip, unsigned int num,
+				  unsigned long offset)
+{
+	return readl_relaxed(chip->mmio_base + (num << 4) + offset);
+}
+
+static inline void spear_pwm_writel(struct spear_pwm_chip *chip,
+				    unsigned int num, unsigned long offset,
+				    unsigned long val)
+{
+	writel_relaxed(val, chip->mmio_base + (num << 4) + offset);
+}
+
+static int spear_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+			    int duty_ns, int period_ns)
+{
+	struct spear_pwm_chip *pc = to_spear_pwm_chip(chip);
+	u64 val, div, clk_rate;
+	unsigned long prescale = PWMCR_MIN_PRESCALE, pv, dc;
+	int ret;
+
+	/*
+	 * Find pv, dc and prescale to suit duty_ns and period_ns. This is done
+	 * according to formulas described below:
+	 *
+	 * period_ns = 10^9 * (PRESCALE + 1) * PV / PWM_CLK_RATE
+	 * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
+	 *
+	 * PV = (PWM_CLK_RATE * period_ns) / (10^9 * (PRESCALE + 1))
+	 * DC = (PWM_CLK_RATE * duty_ns) / (10^9 * (PRESCALE + 1))
+	 */
+	clk_rate = clk_get_rate(pc->clk);
+	while (1) {
+		div = 1000000000;
+		div *= 1 + prescale;
+		val = clk_rate * period_ns;
+		pv = div64_u64(val, div);
+		val = clk_rate * duty_ns;
+		dc = div64_u64(val, div);
+
+		/* if duty_ns and period_ns are not achievable then return */
+		if (pv < PWMPCR_MIN_PERIOD || dc < PWMDCR_MIN_DUTY)
+			return -EINVAL;
+
+		/*
+		 * if pv and dc have crossed their upper limit, then increase
+		 * prescale and recalculate pv and dc.
+		 */
+		if (pv > PWMPCR_MAX_PERIOD || dc > PWMDCR_MAX_DUTY) {
+			if (++prescale > PWMCR_MAX_PRESCALE)
+				return -EINVAL;
+			continue;
+		}
+		break;
+	}
+
+	/*
+	 * NOTE: the clock to PWM has to be enabled first before writing to the
+	 * registers.
+	 */
+	ret = clk_enable(pc->clk);
+	if (ret)
+		return ret;
+
+	spear_pwm_writel(pc, pwm->hwpwm, PWMCR,
+			prescale << PWMCR_PRESCALE_SHIFT);
+	spear_pwm_writel(pc, pwm->hwpwm, PWMDCR, dc);
+	spear_pwm_writel(pc, pwm->hwpwm, PWMPCR, pv);
+	clk_disable(pc->clk);
+
+	return 0;
+}
+
+static int spear_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct spear_pwm_chip *pc = to_spear_pwm_chip(chip);
+	int rc = 0;
+	u32 val;
+
+	rc = clk_enable(pc->clk);
+	if (!rc)
+		return rc;
+
+	val = spear_pwm_readl(pc, pwm->hwpwm, PWMCR);
+	val |= PWMCR_PWM_ENABLE;
+	spear_pwm_writel(pc, pwm->hwpwm, PWMCR, val);
+
+	return 0;
+}
+
+static void spear_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct spear_pwm_chip *pc = to_spear_pwm_chip(chip);
+	u32 val;
+
+	val = spear_pwm_readl(pc, pwm->hwpwm, PWMCR);
+	val &= ~PWMCR_PWM_ENABLE;
+	spear_pwm_writel(pc, pwm->hwpwm, PWMCR, val);
+
+	clk_disable(pc->clk);
+}
+
+static const struct pwm_ops spear_pwm_ops = {
+	.config = spear_pwm_config,
+	.enable = spear_pwm_enable,
+	.disable = spear_pwm_disable,
+	.owner = THIS_MODULE,
+};
+
+static int spear_pwm_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct spear_pwm_chip *pc;
+	struct resource *r;
+	int ret;
+	u32 val;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "no memory resources defined\n");
+		return -ENODEV;
+	}
+
+	pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
+	if (!pc) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	pc->mmio_base = devm_request_and_ioremap(&pdev->dev, r);
+	if (!pc->mmio_base)
+		return -EADDRNOTAVAIL;
+
+	pc->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(pc->clk))
+		return PTR_ERR(pc->clk);
+
+	pc->dev = &pdev->dev;
+	platform_set_drvdata(pdev, pc);
+
+	pc->chip.dev = &pdev->dev;
+	pc->chip.ops = &spear_pwm_ops;
+	pc->chip.base = -1;
+	pc->chip.npwm = NUM_PWM;
+
+	ret = clk_prepare(pc->clk);
+	if (!ret)
+		return ret;
+
+	if (of_device_is_compatible(np, "st,spear1340-pwm")) {
+		ret = clk_enable(pc->clk);
+		if (!ret) {
+			clk_unprepare(pc->clk);
+			return ret;
+		}
+		/*
+		 * Following enables PWM chip, channels would still be
+		 * enabled individually through their control register
+		 */
+		val = readl_relaxed(pc->mmio_base + PWMMCR);
+		val |= PWMMCR_PWM_ENABLE;
+		writel_relaxed(val, pc->mmio_base + PWMMCR);
+
+		clk_disable(pc->clk);
+	}
+
+	ret = pwmchip_add(&pc->chip);
+	if (!ret) {
+		clk_unprepare(pc->clk);
+		dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
+	}
+
+	return ret;
+}
+
+static int spear_pwm_remove(struct platform_device *pdev)
+{
+	struct spear_pwm_chip *pc = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < NUM_PWM; i++)
+		pwm_disable(&pc->chip.pwms[i]);
+
+	/* clk was prepared in probe, hence unprepare it here */
+	clk_unprepare(pc->clk);
+	return pwmchip_remove(&pc->chip);
+}
+
+static struct of_device_id spear_pwm_of_match[] = {
+	{ .compatible = "st,spear320-pwm" },
+	{ .compatible = "st,spear1340-pwm" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, spear_pwm_of_match);
+
+static struct platform_driver spear_pwm_driver = {
+	.driver = {
+		.name = "spear-pwm",
+		.of_match_table = spear_pwm_of_match,
+	},
+	.probe = spear_pwm_probe,
+	.remove = spear_pwm_remove,
+};
+
+module_platform_driver(spear_pwm_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Shiraz Hashim <shiraz.hashim@st.com>");
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.com>");
+MODULE_ALIAS("platform:spear-pwm");
diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index 057465e..30c0e2b 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -210,7 +210,7 @@ static int tegra_pwm_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit tegra_pwm_remove(struct platform_device *pdev)
+static int tegra_pwm_remove(struct platform_device *pdev)
 {
 	struct tegra_pwm_chip *pc = platform_get_drvdata(pdev);
 	int i;
@@ -249,7 +249,7 @@ static struct platform_driver tegra_pwm_driver = {
 		.of_match_table = of_match_ptr(tegra_pwm_of_match),
 	},
 	.probe = tegra_pwm_probe,
-	.remove = __devexit_p(tegra_pwm_remove),
+	.remove = tegra_pwm_remove,
 };
 
 module_platform_driver(tegra_pwm_driver);
diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
index d6d4cf0..5cf016d 100644
--- a/drivers/pwm/pwm-tiecap.c
+++ b/drivers/pwm/pwm-tiecap.c
@@ -25,6 +25,10 @@
 #include <linux/clk.h>
 #include <linux/pm_runtime.h>
 #include <linux/pwm.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+
+#include "pwm-tipwmss.h"
 
 /* ECAP registers and bits definitions */
 #define CAP1			0x08
@@ -184,12 +188,24 @@ static const struct pwm_ops ecap_pwm_ops = {
 	.owner		= THIS_MODULE,
 };
 
-static int __devinit ecap_pwm_probe(struct platform_device *pdev)
+static const struct of_device_id ecap_of_match[] = {
+	{ .compatible	= "ti,am33xx-ecap" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ecap_of_match);
+
+static int ecap_pwm_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct resource *r;
 	struct clk *clk;
 	struct ecap_pwm_chip *pc;
+	u16 status;
+	struct pinctrl *pinctrl;
+
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev, "unable to select pin group\n");
 
 	pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
 	if (!pc) {
@@ -211,6 +227,8 @@ static int __devinit ecap_pwm_probe(struct platform_device *pdev)
 
 	pc->chip.dev = &pdev->dev;
 	pc->chip.ops = &ecap_pwm_ops;
+	pc->chip.of_xlate = of_pwm_xlate_with_flags;
+	pc->chip.of_pwm_n_cells = 3;
 	pc->chip.base = -1;
 	pc->chip.npwm = 1;
 
@@ -231,14 +249,40 @@ static int __devinit ecap_pwm_probe(struct platform_device *pdev)
 	}
 
 	pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_sync(&pdev->dev);
+
+	status = pwmss_submodule_state_change(pdev->dev.parent,
+			PWMSS_ECAPCLK_EN);
+	if (!(status & PWMSS_ECAPCLK_EN_ACK)) {
+		dev_err(&pdev->dev, "PWMSS config space clock enable failed\n");
+		ret = -EINVAL;
+		goto pwmss_clk_failure;
+	}
+
+	pm_runtime_put_sync(&pdev->dev);
+
 	platform_set_drvdata(pdev, pc);
 	return 0;
+
+pwmss_clk_failure:
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	pwmchip_remove(&pc->chip);
+	return ret;
 }
 
-static int __devexit ecap_pwm_remove(struct platform_device *pdev)
+static int ecap_pwm_remove(struct platform_device *pdev)
 {
 	struct ecap_pwm_chip *pc = platform_get_drvdata(pdev);
 
+	pm_runtime_get_sync(&pdev->dev);
+	/*
+	 * Due to hardware misbehaviour, acknowledge of the stop_req
+	 * is missing. Hence checking of the status bit skipped.
+	 */
+	pwmss_submodule_state_change(pdev->dev.parent, PWMSS_ECAPCLK_STOP_REQ);
+	pm_runtime_put_sync(&pdev->dev);
+
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	return pwmchip_remove(&pc->chip);
@@ -246,10 +290,12 @@ static int __devexit ecap_pwm_remove(struct platform_device *pdev)
 
 static struct platform_driver ecap_pwm_driver = {
 	.driver = {
-		.name = "ecap",
+		.name	= "ecap",
+		.owner	= THIS_MODULE,
+		.of_match_table = ecap_of_match,
 	},
 	.probe = ecap_pwm_probe,
-	.remove = __devexit_p(ecap_pwm_remove),
+	.remove = ecap_pwm_remove,
 };
 
 module_platform_driver(ecap_pwm_driver);
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index d3c1dff..72a6dd4 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -25,6 +25,10 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/pm_runtime.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+
+#include "pwm-tipwmss.h"
 
 /* EHRPWM registers and bits definitions */
 
@@ -115,6 +119,7 @@ struct ehrpwm_pwm_chip {
 	void __iomem	*mmio_base;
 	unsigned long period_cycles[NUM_PWM_CHANNEL];
 	enum pwm_polarity polarity[NUM_PWM_CHANNEL];
+	struct	clk	*tbclk;
 };
 
 static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
@@ -335,6 +340,9 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 	/* Channels polarity can be configured from action qualifier module */
 	configure_polarity(pc, pwm->hwpwm);
 
+	/* Enable TBCLK before enabling PWM device */
+	clk_enable(pc->tbclk);
+
 	/* Enable time counter for free_run */
 	ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN);
 	return 0;
@@ -363,6 +371,9 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 
 	ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
 
+	/* Disabling TBCLK on PWM disable */
+	clk_disable(pc->tbclk);
+
 	/* Stop Time base counter */
 	ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT);
 
@@ -392,12 +403,24 @@ static const struct pwm_ops ehrpwm_pwm_ops = {
 	.owner		= THIS_MODULE,
 };
 
-static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev)
+static const struct of_device_id ehrpwm_of_match[] = {
+	{ .compatible	= "ti,am33xx-ehrpwm" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ehrpwm_of_match);
+
+static int ehrpwm_pwm_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct resource *r;
 	struct clk *clk;
 	struct ehrpwm_pwm_chip *pc;
+	u16 status;
+	struct pinctrl *pinctrl;
+
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev, "unable to select pin group\n");
 
 	pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
 	if (!pc) {
@@ -419,6 +442,8 @@ static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev)
 
 	pc->chip.dev = &pdev->dev;
 	pc->chip.ops = &ehrpwm_pwm_ops;
+	pc->chip.of_xlate = of_pwm_xlate_with_flags;
+	pc->chip.of_pwm_n_cells = 3;
 	pc->chip.base = -1;
 	pc->chip.npwm = NUM_PWM_CHANNEL;
 
@@ -432,6 +457,13 @@ static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev)
 	if (!pc->mmio_base)
 		return  -EADDRNOTAVAIL;
 
+	/* Acquire tbclk for Time Base EHRPWM submodule */
+	pc->tbclk = devm_clk_get(&pdev->dev, "tbclk");
+	if (IS_ERR(pc->tbclk)) {
+		dev_err(&pdev->dev, "Failed to get tbclk\n");
+		return PTR_ERR(pc->tbclk);
+	}
+
 	ret = pwmchip_add(&pc->chip);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
@@ -439,14 +471,40 @@ static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev)
 	}
 
 	pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_sync(&pdev->dev);
+
+	status = pwmss_submodule_state_change(pdev->dev.parent,
+			PWMSS_EPWMCLK_EN);
+	if (!(status & PWMSS_EPWMCLK_EN_ACK)) {
+		dev_err(&pdev->dev, "PWMSS config space clock enable failed\n");
+		ret = -EINVAL;
+		goto pwmss_clk_failure;
+	}
+
+	pm_runtime_put_sync(&pdev->dev);
+
 	platform_set_drvdata(pdev, pc);
 	return 0;
+
+pwmss_clk_failure:
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	pwmchip_remove(&pc->chip);
+	return ret;
 }
 
-static int __devexit ehrpwm_pwm_remove(struct platform_device *pdev)
+static int ehrpwm_pwm_remove(struct platform_device *pdev)
 {
 	struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev);
 
+	pm_runtime_get_sync(&pdev->dev);
+	/*
+	 * Due to hardware misbehaviour, acknowledge of the stop_req
+	 * is missing. Hence checking of the status bit skipped.
+	 */
+	pwmss_submodule_state_change(pdev->dev.parent, PWMSS_EPWMCLK_STOP_REQ);
+	pm_runtime_put_sync(&pdev->dev);
+
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	return pwmchip_remove(&pc->chip);
@@ -454,10 +512,12 @@ static int __devexit ehrpwm_pwm_remove(struct platform_device *pdev)
 
 static struct platform_driver ehrpwm_pwm_driver = {
 	.driver = {
-		.name = "ehrpwm",
+		.name	= "ehrpwm",
+		.owner	= THIS_MODULE,
+		.of_match_table = ehrpwm_of_match,
 	},
 	.probe = ehrpwm_pwm_probe,
-	.remove = __devexit_p(ehrpwm_pwm_remove),
+	.remove = ehrpwm_pwm_remove,
 };
 
 module_platform_driver(ehrpwm_pwm_driver);
diff --git a/drivers/pwm/pwm-tipwmss.c b/drivers/pwm/pwm-tipwmss.c
new file mode 100644
index 0000000..3448a1c
--- /dev/null
+++ b/drivers/pwm/pwm-tipwmss.c
@@ -0,0 +1,139 @@
+/*
+ * TI PWM Subsystem driver
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+#include <linux/of_device.h>
+
+#include "pwm-tipwmss.h"
+
+#define PWMSS_CLKCONFIG		0x8	/* Clock gating reg */
+#define PWMSS_CLKSTATUS		0xc	/* Clock gating status reg */
+
+struct pwmss_info {
+	void __iomem	*mmio_base;
+	struct mutex	pwmss_lock;
+	u16		pwmss_clkconfig;
+};
+
+u16 pwmss_submodule_state_change(struct device *dev, int set)
+{
+	struct pwmss_info *info = dev_get_drvdata(dev);
+	u16 val;
+
+	mutex_lock(&info->pwmss_lock);
+	val = readw(info->mmio_base + PWMSS_CLKCONFIG);
+	val |= set;
+	writew(val , info->mmio_base + PWMSS_CLKCONFIG);
+	mutex_unlock(&info->pwmss_lock);
+
+	return readw(info->mmio_base + PWMSS_CLKSTATUS);
+}
+EXPORT_SYMBOL(pwmss_submodule_state_change);
+
+static const struct of_device_id pwmss_of_match[] = {
+	{ .compatible	= "ti,am33xx-pwmss" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, pwmss_of_match);
+
+static int pwmss_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct resource *r;
+	struct pwmss_info *info;
+	struct device_node *node = pdev->dev.of_node;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	mutex_init(&info->pwmss_lock);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "no memory resource defined\n");
+		return -ENODEV;
+	}
+
+	info->mmio_base = devm_request_and_ioremap(&pdev->dev, r);
+	if (!info->mmio_base)
+		return -EADDRNOTAVAIL;
+
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_sync(&pdev->dev);
+	platform_set_drvdata(pdev, info);
+
+	/* Populate all the child nodes here... */
+	ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
+	if (ret)
+		dev_err(&pdev->dev, "no child node found\n");
+
+	return ret;
+}
+
+static int pwmss_remove(struct platform_device *pdev)
+{
+	struct pwmss_info *info = platform_get_drvdata(pdev);
+
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	mutex_destroy(&info->pwmss_lock);
+	return 0;
+}
+
+static int pwmss_suspend(struct device *dev)
+{
+	struct pwmss_info *info = dev_get_drvdata(dev);
+
+	info->pwmss_clkconfig = readw(info->mmio_base + PWMSS_CLKCONFIG);
+	pm_runtime_put_sync(dev);
+	return 0;
+}
+
+static int pwmss_resume(struct device *dev)
+{
+	struct pwmss_info *info = dev_get_drvdata(dev);
+
+	pm_runtime_get_sync(dev);
+	writew(info->pwmss_clkconfig, info->mmio_base + PWMSS_CLKCONFIG);
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(pwmss_pm_ops, pwmss_suspend, pwmss_resume);
+
+static struct platform_driver pwmss_driver = {
+	.driver	= {
+		.name	= "pwmss",
+		.owner	= THIS_MODULE,
+		.pm	= &pwmss_pm_ops,
+		.of_match_table	= pwmss_of_match,
+	},
+	.probe	= pwmss_probe,
+	.remove	= pwmss_remove,
+};
+
+module_platform_driver(pwmss_driver);
+
+MODULE_DESCRIPTION("PWM Subsystem driver");
+MODULE_AUTHOR("Texas Instruments");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/pwm-tipwmss.h b/drivers/pwm/pwm-tipwmss.h
new file mode 100644
index 0000000..11f76a1
--- /dev/null
+++ b/drivers/pwm/pwm-tipwmss.h
@@ -0,0 +1,39 @@
+/*
+ * TI PWM Subsystem driver
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 __TIPWMSS_H
+#define __TIPWMSS_H
+
+#ifdef CONFIG_PWM_TIPWMSS
+/* PWM substem clock gating */
+#define PWMSS_ECAPCLK_EN	BIT(0)
+#define PWMSS_ECAPCLK_STOP_REQ	BIT(1)
+#define PWMSS_EPWMCLK_EN	BIT(8)
+#define PWMSS_EPWMCLK_STOP_REQ	BIT(9)
+
+#define PWMSS_ECAPCLK_EN_ACK	BIT(0)
+#define PWMSS_EPWMCLK_EN_ACK	BIT(8)
+
+extern u16 pwmss_submodule_state_change(struct device *dev, int set);
+#else
+static inline u16 pwmss_submodule_state_change(struct device *dev, int set)
+{
+	/* return success status value */
+	return 0xFFFF;
+}
+#endif
+#endif	/* __TIPWMSS_H */
diff --git a/drivers/pwm/pwm-twl-led.c b/drivers/pwm/pwm-twl-led.c
new file mode 100644
index 0000000..9dfa0f3
--- /dev/null
+++ b/drivers/pwm/pwm-twl-led.c
@@ -0,0 +1,344 @@
+/*
+ * Driver for TWL4030/6030 Pulse Width Modulator used as LED driver
+ *
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * This driver is a complete rewrite of the former pwm-twl6030.c authorded by:
+ * Hemanth V <hemanthv@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/i2c/twl.h>
+#include <linux/slab.h>
+
+/*
+ * This driver handles the PWM driven LED terminals of TWL4030 and TWL6030.
+ * To generate the signal on TWL4030:
+ *  - LEDA uses PWMA
+ *  - LEDB uses PWMB
+ * TWL6030 has one LED pin with dedicated LEDPWM
+ */
+
+#define TWL4030_LED_MAX		0x7f
+#define TWL6030_LED_MAX		0xff
+
+/* Registers, bits and macro for TWL4030 */
+#define TWL4030_LEDEN_REG	0x00
+#define TWL4030_PWMA_REG	0x01
+
+#define TWL4030_LEDXON		(1 << 0)
+#define TWL4030_LEDXPWM		(1 << 4)
+#define TWL4030_LED_PINS	(TWL4030_LEDXON | TWL4030_LEDXPWM)
+#define TWL4030_LED_TOGGLE(led, x)	((x) << (led))
+
+/* Register, bits and macro for TWL6030 */
+#define TWL6030_LED_PWM_CTRL1	0xf4
+#define TWL6030_LED_PWM_CTRL2	0xf5
+
+#define TWL6040_LED_MODE_HW	0x00
+#define TWL6040_LED_MODE_ON	0x01
+#define TWL6040_LED_MODE_OFF	0x02
+#define TWL6040_LED_MODE_MASK	0x03
+
+struct twl_pwmled_chip {
+	struct pwm_chip chip;
+	struct mutex mutex;
+};
+
+static inline struct twl_pwmled_chip *to_twl(struct pwm_chip *chip)
+{
+	return container_of(chip, struct twl_pwmled_chip, chip);
+}
+
+static int twl4030_pwmled_config(struct pwm_chip *chip, struct pwm_device *pwm,
+			      int duty_ns, int period_ns)
+{
+	int duty_cycle = DIV_ROUND_UP(duty_ns * TWL4030_LED_MAX, period_ns) + 1;
+	u8 pwm_config[2] = { 1, 0 };
+	int base, ret;
+
+	/*
+	 * To configure the duty period:
+	 * On-cycle is set to 1 (the minimum allowed value)
+	 * The off time of 0 is not configurable, so the mapping is:
+	 * 0 -> off cycle = 2,
+	 * 1 -> off cycle = 2,
+	 * 2 -> off cycle = 3,
+	 * 126 - > off cycle 127,
+	 * 127 - > off cycle 1
+	 * When on cycle == off cycle the PWM will be always on
+	 */
+	if (duty_cycle == 1)
+		duty_cycle = 2;
+	else if (duty_cycle > TWL4030_LED_MAX)
+		duty_cycle = 1;
+
+	base = pwm->hwpwm * 2 + TWL4030_PWMA_REG;
+
+	pwm_config[1] = duty_cycle;
+
+	ret = twl_i2c_write(TWL4030_MODULE_LED, pwm_config, base, 2);
+	if (ret < 0)
+		dev_err(chip->dev, "%s: Failed to configure PWM\n", pwm->label);
+
+	return ret;
+}
+
+static int twl4030_pwmled_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct twl_pwmled_chip *twl = to_twl(chip);
+	int ret;
+	u8 val;
+
+	mutex_lock(&twl->mutex);
+	ret = twl_i2c_read_u8(TWL4030_MODULE_LED, &val, TWL4030_LEDEN_REG);
+	if (ret < 0) {
+		dev_err(chip->dev, "%s: Failed to read LEDEN\n", pwm->label);
+		goto out;
+	}
+
+	val |= TWL4030_LED_TOGGLE(pwm->hwpwm, TWL4030_LED_PINS);
+
+	ret = twl_i2c_write_u8(TWL4030_MODULE_LED, val, TWL4030_LEDEN_REG);
+	if (ret < 0)
+		dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label);
+
+out:
+	mutex_unlock(&twl->mutex);
+	return ret;
+}
+
+static void twl4030_pwmled_disable(struct pwm_chip *chip,
+				   struct pwm_device *pwm)
+{
+	struct twl_pwmled_chip *twl = to_twl(chip);
+	int ret;
+	u8 val;
+
+	mutex_lock(&twl->mutex);
+	ret = twl_i2c_read_u8(TWL4030_MODULE_LED, &val, TWL4030_LEDEN_REG);
+	if (ret < 0) {
+		dev_err(chip->dev, "%s: Failed to read LEDEN\n", pwm->label);
+		goto out;
+	}
+
+	val &= ~TWL4030_LED_TOGGLE(pwm->hwpwm, TWL4030_LED_PINS);
+
+	ret = twl_i2c_write_u8(TWL4030_MODULE_LED, val, TWL4030_LEDEN_REG);
+	if (ret < 0)
+		dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label);
+
+out:
+	mutex_unlock(&twl->mutex);
+}
+
+static int twl6030_pwmled_config(struct pwm_chip *chip, struct pwm_device *pwm,
+			      int duty_ns, int period_ns)
+{
+	int duty_cycle = (duty_ns * TWL6030_LED_MAX) / period_ns;
+	u8 on_time;
+	int ret;
+
+	on_time = duty_cycle & 0xff;
+
+	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, on_time,
+			       TWL6030_LED_PWM_CTRL1);
+	if (ret < 0)
+		dev_err(chip->dev, "%s: Failed to configure PWM\n", pwm->label);
+
+	return ret;
+}
+
+static int twl6030_pwmled_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct twl_pwmled_chip *twl = to_twl(chip);
+	int ret;
+	u8 val;
+
+	mutex_lock(&twl->mutex);
+	ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2);
+	if (ret < 0) {
+		dev_err(chip->dev, "%s: Failed to read PWM_CTRL2\n",
+			pwm->label);
+		goto out;
+	}
+
+	val &= ~TWL6040_LED_MODE_MASK;
+	val |= TWL6040_LED_MODE_ON;
+
+	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2);
+	if (ret < 0)
+		dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label);
+
+out:
+	mutex_unlock(&twl->mutex);
+	return ret;
+}
+
+static void twl6030_pwmled_disable(struct pwm_chip *chip,
+				   struct pwm_device *pwm)
+{
+	struct twl_pwmled_chip *twl = to_twl(chip);
+	int ret;
+	u8 val;
+
+	mutex_lock(&twl->mutex);
+	ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2);
+	if (ret < 0) {
+		dev_err(chip->dev, "%s: Failed to read PWM_CTRL2\n",
+			pwm->label);
+		goto out;
+	}
+
+	val &= ~TWL6040_LED_MODE_MASK;
+	val |= TWL6040_LED_MODE_OFF;
+
+	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2);
+	if (ret < 0)
+		dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label);
+
+out:
+	mutex_unlock(&twl->mutex);
+}
+
+static int twl6030_pwmled_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct twl_pwmled_chip *twl = to_twl(chip);
+	int ret;
+	u8 val;
+
+	mutex_lock(&twl->mutex);
+	ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2);
+	if (ret < 0) {
+		dev_err(chip->dev, "%s: Failed to read PWM_CTRL2\n",
+			pwm->label);
+		goto out;
+	}
+
+	val &= ~TWL6040_LED_MODE_MASK;
+	val |= TWL6040_LED_MODE_OFF;
+
+	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2);
+	if (ret < 0)
+		dev_err(chip->dev, "%s: Failed to request PWM\n", pwm->label);
+
+out:
+	mutex_unlock(&twl->mutex);
+	return ret;
+}
+
+static void twl6030_pwmled_free(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct twl_pwmled_chip *twl = to_twl(chip);
+	int ret;
+	u8 val;
+
+	mutex_lock(&twl->mutex);
+	ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2);
+	if (ret < 0) {
+		dev_err(chip->dev, "%s: Failed to read PWM_CTRL2\n",
+			pwm->label);
+		goto out;
+	}
+
+	val &= ~TWL6040_LED_MODE_MASK;
+	val |= TWL6040_LED_MODE_HW;
+
+	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2);
+	if (ret < 0)
+		dev_err(chip->dev, "%s: Failed to free PWM\n", pwm->label);
+
+out:
+	mutex_unlock(&twl->mutex);
+}
+
+static const struct pwm_ops twl4030_pwmled_ops = {
+	.enable = twl4030_pwmled_enable,
+	.disable = twl4030_pwmled_disable,
+	.config = twl4030_pwmled_config,
+};
+
+static const struct pwm_ops twl6030_pwmled_ops = {
+	.enable = twl6030_pwmled_enable,
+	.disable = twl6030_pwmled_disable,
+	.config = twl6030_pwmled_config,
+	.request = twl6030_pwmled_request,
+	.free = twl6030_pwmled_free,
+};
+
+static int twl_pwmled_probe(struct platform_device *pdev)
+{
+	struct twl_pwmled_chip *twl;
+	int ret;
+
+	twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL);
+	if (!twl)
+		return -ENOMEM;
+
+	if (twl_class_is_4030()) {
+		twl->chip.ops = &twl4030_pwmled_ops;
+		twl->chip.npwm = 2;
+	} else {
+		twl->chip.ops = &twl6030_pwmled_ops;
+		twl->chip.npwm = 1;
+	}
+
+	twl->chip.dev = &pdev->dev;
+	twl->chip.base = -1;
+
+	mutex_init(&twl->mutex);
+
+	ret = pwmchip_add(&twl->chip);
+	if (ret < 0)
+		return ret;
+
+	platform_set_drvdata(pdev, twl);
+
+	return 0;
+}
+
+static int twl_pwmled_remove(struct platform_device *pdev)
+{
+	struct twl_pwmled_chip *twl = platform_get_drvdata(pdev);
+
+	return pwmchip_remove(&twl->chip);
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id twl_pwmled_of_match[] = {
+	{ .compatible = "ti,twl4030-pwmled" },
+	{ .compatible = "ti,twl6030-pwmled" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, twl_pwmled_of_match);
+#endif
+
+static struct platform_driver twl_pwmled_driver = {
+	.driver = {
+		.name = "twl-pwmled",
+		.of_match_table = of_match_ptr(twl_pwmled_of_match),
+	},
+	.probe = twl_pwmled_probe,
+	.remove = twl_pwmled_remove,
+};
+module_platform_driver(twl_pwmled_driver);
+
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_DESCRIPTION("PWM driver for TWL4030 and TWL6030 LED outputs");
+MODULE_ALIAS("platform:twl-pwmled");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/pwm-twl.c b/drivers/pwm/pwm-twl.c
new file mode 100644
index 0000000..e65db95
--- /dev/null
+++ b/drivers/pwm/pwm-twl.c
@@ -0,0 +1,359 @@
+/*
+ * Driver for TWL4030/6030 Generic Pulse Width Modulator
+ *
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/i2c/twl.h>
+#include <linux/slab.h>
+
+/*
+ * This driver handles the PWMs of TWL4030 and TWL6030.
+ * The TRM names for the PWMs on TWL4030 are: PWM0, PWM1
+ * TWL6030 also have two PWMs named in the TRM as PWM1, PWM2
+ */
+
+#define TWL_PWM_MAX		0x7f
+
+/* Registers, bits and macro for TWL4030 */
+#define TWL4030_GPBR1_REG	0x0c
+#define TWL4030_PMBR1_REG	0x0d
+
+/* GPBR1 register bits */
+#define TWL4030_PWMXCLK_ENABLE	(1 << 0)
+#define TWL4030_PWMX_ENABLE	(1 << 2)
+#define TWL4030_PWMX_BITS	(TWL4030_PWMX_ENABLE | TWL4030_PWMXCLK_ENABLE)
+#define TWL4030_PWM_TOGGLE(pwm, x)	((x) << (pwm))
+
+/* PMBR1 register bits */
+#define TWL4030_GPIO6_PWM0_MUTE_MASK		(0x03 << 2)
+#define TWL4030_GPIO6_PWM0_MUTE_PWM0		(0x01 << 2)
+#define TWL4030_GPIO7_VIBRASYNC_PWM1_MASK	(0x03 << 4)
+#define TWL4030_GPIO7_VIBRASYNC_PWM1_PWM1	(0x03 << 4)
+
+/* Register, bits and macro for TWL6030 */
+#define TWL6030_TOGGLE3_REG	0x92
+
+#define TWL6030_PWMXR		(1 << 0)
+#define TWL6030_PWMXS		(1 << 1)
+#define TWL6030_PWMXEN		(1 << 2)
+#define TWL6030_PWM_TOGGLE(pwm, x)	((x) << (pwm * 3))
+
+struct twl_pwm_chip {
+	struct pwm_chip chip;
+	struct mutex mutex;
+	u8 twl6030_toggle3;
+	u8 twl4030_pwm_mux;
+};
+
+static inline struct twl_pwm_chip *to_twl(struct pwm_chip *chip)
+{
+	return container_of(chip, struct twl_pwm_chip, chip);
+}
+
+static int twl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+			      int duty_ns, int period_ns)
+{
+	int duty_cycle = DIV_ROUND_UP(duty_ns * TWL_PWM_MAX, period_ns) + 1;
+	u8 pwm_config[2] = { 1, 0 };
+	int base, ret;
+
+	/*
+	 * To configure the duty period:
+	 * On-cycle is set to 1 (the minimum allowed value)
+	 * The off time of 0 is not configurable, so the mapping is:
+	 * 0 -> off cycle = 2,
+	 * 1 -> off cycle = 2,
+	 * 2 -> off cycle = 3,
+	 * 126 - > off cycle 127,
+	 * 127 - > off cycle 1
+	 * When on cycle == off cycle the PWM will be always on
+	 */
+	if (duty_cycle == 1)
+		duty_cycle = 2;
+	else if (duty_cycle > TWL_PWM_MAX)
+		duty_cycle = 1;
+
+	base = pwm->hwpwm * 3;
+
+	pwm_config[1] = duty_cycle;
+
+	ret = twl_i2c_write(TWL_MODULE_PWM, pwm_config, base, 2);
+	if (ret < 0)
+		dev_err(chip->dev, "%s: Failed to configure PWM\n", pwm->label);
+
+	return ret;
+}
+
+static int twl4030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct twl_pwm_chip *twl = to_twl(chip);
+	int ret;
+	u8 val;
+
+	mutex_lock(&twl->mutex);
+	ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &val, TWL4030_GPBR1_REG);
+	if (ret < 0) {
+		dev_err(chip->dev, "%s: Failed to read GPBR1\n", pwm->label);
+		goto out;
+	}
+
+	val |= TWL4030_PWM_TOGGLE(pwm->hwpwm, TWL4030_PWMXCLK_ENABLE);
+
+	ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_GPBR1_REG);
+	if (ret < 0)
+		dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label);
+
+	val |= TWL4030_PWM_TOGGLE(pwm->hwpwm, TWL4030_PWMX_ENABLE);
+
+	ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_GPBR1_REG);
+	if (ret < 0)
+		dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label);
+
+out:
+	mutex_unlock(&twl->mutex);
+	return ret;
+}
+
+static void twl4030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct twl_pwm_chip *twl = to_twl(chip);
+	int ret;
+	u8 val;
+
+	mutex_lock(&twl->mutex);
+	ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &val, TWL4030_GPBR1_REG);
+	if (ret < 0) {
+		dev_err(chip->dev, "%s: Failed to read GPBR1\n", pwm->label);
+		goto out;
+	}
+
+	val &= ~TWL4030_PWM_TOGGLE(pwm->hwpwm, TWL4030_PWMX_ENABLE);
+
+	ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_GPBR1_REG);
+	if (ret < 0)
+		dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label);
+
+	val &= ~TWL4030_PWM_TOGGLE(pwm->hwpwm, TWL4030_PWMXCLK_ENABLE);
+
+	ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_GPBR1_REG);
+	if (ret < 0)
+		dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label);
+
+out:
+	mutex_unlock(&twl->mutex);
+}
+
+static int twl4030_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct twl_pwm_chip *twl = to_twl(chip);
+	int ret;
+	u8 val, mask, bits;
+
+	if (pwm->hwpwm == 1) {
+		mask = TWL4030_GPIO7_VIBRASYNC_PWM1_MASK;
+		bits = TWL4030_GPIO7_VIBRASYNC_PWM1_PWM1;
+	} else {
+		mask = TWL4030_GPIO6_PWM0_MUTE_MASK;
+		bits = TWL4030_GPIO6_PWM0_MUTE_PWM0;
+	}
+
+	mutex_lock(&twl->mutex);
+	ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &val, TWL4030_PMBR1_REG);
+	if (ret < 0) {
+		dev_err(chip->dev, "%s: Failed to read PMBR1\n", pwm->label);
+		goto out;
+	}
+
+	/* Save the current MUX configuration for the PWM */
+	twl->twl4030_pwm_mux &= ~mask;
+	twl->twl4030_pwm_mux |= (val & mask);
+
+	/* Select PWM functionality */
+	val &= ~mask;
+	val |= bits;
+
+	ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_PMBR1_REG);
+	if (ret < 0)
+		dev_err(chip->dev, "%s: Failed to request PWM\n", pwm->label);
+
+out:
+	mutex_unlock(&twl->mutex);
+	return ret;
+}
+
+static void twl4030_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct twl_pwm_chip *twl = container_of(chip, struct twl_pwm_chip,
+						chip);
+	int ret;
+	u8 val, mask;
+
+	if (pwm->hwpwm == 1)
+		mask = TWL4030_GPIO7_VIBRASYNC_PWM1_MASK;
+	else
+		mask = TWL4030_GPIO6_PWM0_MUTE_MASK;
+
+	mutex_lock(&twl->mutex);
+	ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &val, TWL4030_PMBR1_REG);
+	if (ret < 0) {
+		dev_err(chip->dev, "%s: Failed to read PMBR1\n", pwm->label);
+		goto out;
+	}
+
+	/* Restore the MUX configuration for the PWM */
+	val &= ~mask;
+	val |= (twl->twl4030_pwm_mux & mask);
+
+	ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_PMBR1_REG);
+	if (ret < 0)
+		dev_err(chip->dev, "%s: Failed to free PWM\n", pwm->label);
+
+out:
+	mutex_unlock(&twl->mutex);
+}
+
+static int twl6030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct twl_pwm_chip *twl = container_of(chip, struct twl_pwm_chip,
+						chip);
+	int ret;
+	u8 val;
+
+	mutex_lock(&twl->mutex);
+	val = twl->twl6030_toggle3;
+	val |= TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXS | TWL6030_PWMXEN);
+	val &= ~TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXR);
+
+	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_TOGGLE3_REG);
+	if (ret < 0) {
+		dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label);
+		goto out;
+	}
+
+	twl->twl6030_toggle3 = val;
+out:
+	mutex_unlock(&twl->mutex);
+	return 0;
+}
+
+static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct twl_pwm_chip *twl = container_of(chip, struct twl_pwm_chip,
+						chip);
+	int ret;
+	u8 val;
+
+	mutex_lock(&twl->mutex);
+	val = twl->twl6030_toggle3;
+	val |= TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXR);
+	val &= ~TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXS | TWL6030_PWMXEN);
+
+	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_TOGGLE3_REG);
+	if (ret < 0) {
+		dev_err(chip->dev, "%s: Failed to read TOGGLE3\n", pwm->label);
+		goto out;
+	}
+
+	val |= TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXS | TWL6030_PWMXEN);
+
+	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_TOGGLE3_REG);
+	if (ret < 0) {
+		dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label);
+		goto out;
+	}
+
+	twl->twl6030_toggle3 = val;
+out:
+	mutex_unlock(&twl->mutex);
+}
+
+static const struct pwm_ops twl4030_pwm_ops = {
+	.config = twl_pwm_config,
+	.enable = twl4030_pwm_enable,
+	.disable = twl4030_pwm_disable,
+	.request = twl4030_pwm_request,
+	.free = twl4030_pwm_free,
+};
+
+static const struct pwm_ops twl6030_pwm_ops = {
+	.config = twl_pwm_config,
+	.enable = twl6030_pwm_enable,
+	.disable = twl6030_pwm_disable,
+};
+
+static int twl_pwm_probe(struct platform_device *pdev)
+{
+	struct twl_pwm_chip *twl;
+	int ret;
+
+	twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL);
+	if (!twl)
+		return -ENOMEM;
+
+	if (twl_class_is_4030())
+		twl->chip.ops = &twl4030_pwm_ops;
+	else
+		twl->chip.ops = &twl6030_pwm_ops;
+
+	twl->chip.dev = &pdev->dev;
+	twl->chip.base = -1;
+	twl->chip.npwm = 2;
+
+	mutex_init(&twl->mutex);
+
+	ret = pwmchip_add(&twl->chip);
+	if (ret < 0)
+		return ret;
+
+	platform_set_drvdata(pdev, twl);
+
+	return 0;
+}
+
+static int twl_pwm_remove(struct platform_device *pdev)
+{
+	struct twl_pwm_chip *twl = platform_get_drvdata(pdev);
+
+	return pwmchip_remove(&twl->chip);
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id twl_pwm_of_match[] = {
+	{ .compatible = "ti,twl4030-pwm" },
+	{ .compatible = "ti,twl6030-pwm" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, twl_pwm_of_match);
+#endif
+
+static struct platform_driver twl_pwm_driver = {
+	.driver = {
+		.name = "twl-pwm",
+		.of_match_table = of_match_ptr(twl_pwm_of_match),
+	},
+	.probe = twl_pwm_probe,
+	.remove = twl_pwm_remove,
+};
+module_platform_driver(twl_pwm_driver);
+
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_DESCRIPTION("PWM driver for TWL4030 and TWL6030");
+MODULE_ALIAS("platform:twl-pwm");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/pwm-twl6030.c b/drivers/pwm/pwm-twl6030.c
deleted file mode 100644
index 8e63878..0000000
--- a/drivers/pwm/pwm-twl6030.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * twl6030_pwm.c
- * Driver for PHOENIX (TWL6030) Pulse Width Modulator
- *
- * Copyright (C) 2010 Texas Instruments
- * Author: Hemanth V <hemanthv@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pwm.h>
-#include <linux/i2c/twl.h>
-#include <linux/slab.h>
-
-#define LED_PWM_CTRL1	0xF4
-#define LED_PWM_CTRL2	0xF5
-
-/* Max value for CTRL1 register */
-#define PWM_CTRL1_MAX	255
-
-/* Pull down disable */
-#define PWM_CTRL2_DIS_PD	(1 << 6)
-
-/* Current control 2.5 milli Amps */
-#define PWM_CTRL2_CURR_02	(2 << 4)
-
-/* LED supply source */
-#define PWM_CTRL2_SRC_VAC	(1 << 2)
-
-/* LED modes */
-#define PWM_CTRL2_MODE_HW	(0 << 0)
-#define PWM_CTRL2_MODE_SW	(1 << 0)
-#define PWM_CTRL2_MODE_DIS	(2 << 0)
-
-#define PWM_CTRL2_MODE_MASK	0x3
-
-struct twl6030_pwm_chip {
-	struct pwm_chip chip;
-};
-
-static int twl6030_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
-{
-	int ret;
-	u8 val;
-
-	/* Configure PWM */
-	val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VAC |
-	      PWM_CTRL2_MODE_HW;
-
-	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
-	if (ret < 0) {
-		dev_err(chip->dev, "%s: Failed to configure PWM, Error %d\n",
-			pwm->label, ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int twl6030_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
-			      int duty_ns, int period_ns)
-{
-	u8 duty_cycle = (duty_ns * PWM_CTRL1_MAX) / period_ns;
-	int ret;
-
-	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, duty_cycle, LED_PWM_CTRL1);
-	if (ret < 0) {
-		pr_err("%s: Failed to configure PWM, Error %d\n",
-			pwm->label, ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int twl6030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
-{
-	int ret;
-	u8 val;
-
-	ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
-	if (ret < 0) {
-		dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
-			pwm->label, ret);
-		return ret;
-	}
-
-	/* Change mode to software control */
-	val &= ~PWM_CTRL2_MODE_MASK;
-	val |= PWM_CTRL2_MODE_SW;
-
-	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
-	if (ret < 0) {
-		dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
-			pwm->label, ret);
-		return ret;
-	}
-
-	twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
-	return 0;
-}
-
-static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
-{
-	int ret;
-	u8 val;
-
-	ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
-	if (ret < 0) {
-		dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
-			pwm->label, ret);
-		return;
-	}
-
-	val &= ~PWM_CTRL2_MODE_MASK;
-	val |= PWM_CTRL2_MODE_HW;
-
-	ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
-	if (ret < 0) {
-		dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
-			pwm->label, ret);
-	}
-}
-
-static const struct pwm_ops twl6030_pwm_ops = {
-	.request = twl6030_pwm_request,
-	.config = twl6030_pwm_config,
-	.enable = twl6030_pwm_enable,
-	.disable = twl6030_pwm_disable,
-};
-
-static int twl6030_pwm_probe(struct platform_device *pdev)
-{
-	struct twl6030_pwm_chip *twl6030;
-	int ret;
-
-	twl6030 = devm_kzalloc(&pdev->dev, sizeof(*twl6030), GFP_KERNEL);
-	if (!twl6030)
-		return -ENOMEM;
-
-	twl6030->chip.dev = &pdev->dev;
-	twl6030->chip.ops = &twl6030_pwm_ops;
-	twl6030->chip.base = -1;
-	twl6030->chip.npwm = 1;
-
-	ret = pwmchip_add(&twl6030->chip);
-	if (ret < 0)
-		return ret;
-
-	platform_set_drvdata(pdev, twl6030);
-
-	return 0;
-}
-
-static int twl6030_pwm_remove(struct platform_device *pdev)
-{
-	struct twl6030_pwm_chip *twl6030 = platform_get_drvdata(pdev);
-
-	return pwmchip_remove(&twl6030->chip);
-}
-
-static struct platform_driver twl6030_pwm_driver = {
-	.driver = {
-		.name = "twl6030-pwm",
-	},
-	.probe = twl6030_pwm_probe,
-	.remove = __devexit_p(twl6030_pwm_remove),
-};
-module_platform_driver(twl6030_pwm_driver);
-
-MODULE_ALIAS("platform:twl6030-pwm");
-MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/pwm-vt8500.c b/drivers/pwm/pwm-vt8500.c
index ad14389..b0ba2d4 100644
--- a/drivers/pwm/pwm-vt8500.c
+++ b/drivers/pwm/pwm-vt8500.c
@@ -1,7 +1,8 @@
 /*
  * drivers/pwm/pwm-vt8500.c
  *
- *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -21,14 +22,24 @@
 #include <linux/io.h>
 #include <linux/pwm.h>
 #include <linux/delay.h>
+#include <linux/clk.h>
 
 #include <asm/div64.h>
 
-#define VT8500_NR_PWMS 4
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+
+/*
+ * SoC architecture allocates register space for 4 PWMs but only
+ * 2 are currently implemented.
+ */
+#define VT8500_NR_PWMS	2
 
 struct vt8500_chip {
 	struct pwm_chip chip;
 	void __iomem *base;
+	struct clk *clk;
 };
 
 #define to_vt8500_chip(chip)	container_of(chip, struct vt8500_chip, chip)
@@ -51,8 +62,15 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 	struct vt8500_chip *vt8500 = to_vt8500_chip(chip);
 	unsigned long long c;
 	unsigned long period_cycles, prescale, pv, dc;
+	int err;
 
-	c = 25000000/2; /* wild guess --- need to implement clocks */
+	err = clk_enable(vt8500->clk);
+	if (err < 0) {
+		dev_err(chip->dev, "failed to enable clock\n");
+		return err;
+	}
+
+	c = clk_get_rate(vt8500->clk);
 	c = c * period_ns;
 	do_div(c, 1000000000);
 	period_cycles = c;
@@ -64,8 +82,10 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 	if (pv > 4095)
 		pv = 4095;
 
-	if (prescale > 1023)
+	if (prescale > 1023) {
+		clk_disable(vt8500->clk);
 		return -EINVAL;
+	}
 
 	c = (unsigned long long)pv * duty_ns;
 	do_div(c, period_ns);
@@ -80,13 +100,21 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 	pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 3));
 	writel(dc, vt8500->base + 0xc + (pwm->hwpwm << 4));
 
+	clk_disable(vt8500->clk);
 	return 0;
 }
 
 static int vt8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
+	int err;
 	struct vt8500_chip *vt8500 = to_vt8500_chip(chip);
 
+	err = clk_enable(vt8500->clk);
+	if (err < 0) {
+		dev_err(chip->dev, "failed to enable clock\n");
+		return err;
+	}
+
 	pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 0));
 	writel(5, vt8500->base + (pwm->hwpwm << 4));
 	return 0;
@@ -98,6 +126,8 @@ static void vt8500_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 
 	pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 0));
 	writel(0, vt8500->base + (pwm->hwpwm << 4));
+
+	clk_disable(vt8500->clk);
 }
 
 static struct pwm_ops vt8500_pwm_ops = {
@@ -107,12 +137,24 @@ static struct pwm_ops vt8500_pwm_ops = {
 	.owner = THIS_MODULE,
 };
 
-static int __devinit pwm_probe(struct platform_device *pdev)
+static const struct of_device_id vt8500_pwm_dt_ids[] = {
+	{ .compatible = "via,vt8500-pwm", },
+	{ /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, vt8500_pwm_dt_ids);
+
+static int vt8500_pwm_probe(struct platform_device *pdev)
 {
 	struct vt8500_chip *chip;
 	struct resource *r;
+	struct device_node *np = pdev->dev.of_node;
 	int ret;
 
+	if (!np) {
+		dev_err(&pdev->dev, "invalid devicetree node\n");
+		return -EINVAL;
+	}
+
 	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		dev_err(&pdev->dev, "failed to allocate memory\n");
@@ -124,6 +166,12 @@ static int __devinit pwm_probe(struct platform_device *pdev)
 	chip->chip.base = -1;
 	chip->chip.npwm = VT8500_NR_PWMS;
 
+	chip->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(chip->clk)) {
+		dev_err(&pdev->dev, "clock source not specified\n");
+		return PTR_ERR(chip->clk);
+	}
+
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (r == NULL) {
 		dev_err(&pdev->dev, "no memory resource defined\n");
@@ -131,18 +179,26 @@ static int __devinit pwm_probe(struct platform_device *pdev)
 	}
 
 	chip->base = devm_request_and_ioremap(&pdev->dev, r);
-	if (chip->base == NULL)
+	if (!chip->base)
 		return -EADDRNOTAVAIL;
 
+	ret = clk_prepare(chip->clk);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to prepare clock\n");
+		return ret;
+	}
+
 	ret = pwmchip_add(&chip->chip);
-	if (ret < 0)
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to add PWM chip\n");
 		return ret;
+	}
 
 	platform_set_drvdata(pdev, chip);
 	return ret;
 }
 
-static int __devexit pwm_remove(struct platform_device *pdev)
+static int vt8500_pwm_remove(struct platform_device *pdev)
 {
 	struct vt8500_chip *chip;
 
@@ -150,28 +206,22 @@ static int __devexit pwm_remove(struct platform_device *pdev)
 	if (chip == NULL)
 		return -ENODEV;
 
+	clk_unprepare(chip->clk);
+
 	return pwmchip_remove(&chip->chip);
 }
 
-static struct platform_driver pwm_driver = {
+static struct platform_driver vt8500_pwm_driver = {
+	.probe		= vt8500_pwm_probe,
+	.remove		= vt8500_pwm_remove,
 	.driver		= {
 		.name	= "vt8500-pwm",
 		.owner	= THIS_MODULE,
+		.of_match_table = vt8500_pwm_dt_ids,
 	},
-	.probe		= pwm_probe,
-	.remove		= __devexit_p(pwm_remove),
 };
+module_platform_driver(vt8500_pwm_driver);
 
-static int __init pwm_init(void)
-{
-	return platform_driver_register(&pwm_driver);
-}
-arch_initcall(pwm_init);
-
-static void __exit pwm_exit(void)
-{
-	platform_driver_unregister(&pwm_driver);
-}
-module_exit(pwm_exit);
-
-MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("VT8500 PWM Driver");
+MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c
index 38ecd8f..6faba40 100644
--- a/drivers/rapidio/devices/tsi721.c
+++ b/drivers/rapidio/devices/tsi721.c
@@ -2202,7 +2202,7 @@ static void tsi721_disable_ints(struct tsi721_device *priv)
  *
  * Configures Tsi721 as RapidIO master port.
  */
-static int __devinit tsi721_setup_mport(struct tsi721_device *priv)
+static int tsi721_setup_mport(struct tsi721_device *priv)
 {
 	struct pci_dev *pdev = priv->pdev;
 	int err = 0;
@@ -2302,7 +2302,7 @@ err_exit:
 	return err;
 }
 
-static int __devinit tsi721_probe(struct pci_dev *pdev,
+static int tsi721_probe(struct pci_dev *pdev,
 				  const struct pci_device_id *id)
 {
 	struct tsi721_device *priv;
diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h
index 7d5b13b..b4b0d83 100644
--- a/drivers/rapidio/devices/tsi721.h
+++ b/drivers/rapidio/devices/tsi721.h
@@ -846,7 +846,7 @@ struct tsi721_device {
 
 #ifdef CONFIG_RAPIDIO_DMA_ENGINE
 extern void tsi721_bdma_handler(struct tsi721_bdma_chan *bdma_chan);
-extern int __devinit tsi721_register_dma(struct tsi721_device *priv);
+extern int tsi721_register_dma(struct tsi721_device *priv);
 #endif
 
 #endif
diff --git a/drivers/rapidio/devices/tsi721_dma.c b/drivers/rapidio/devices/tsi721_dma.c
index 92e06a5..502663f 100644
--- a/drivers/rapidio/devices/tsi721_dma.c
+++ b/drivers/rapidio/devices/tsi721_dma.c
@@ -765,7 +765,7 @@ static int tsi721_device_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,
 	return 0;
 }
 
-int __devinit tsi721_register_dma(struct tsi721_device *priv)
+int tsi721_register_dma(struct tsi721_device *priv)
 {
 	int i;
 	int nr_channels = TSI721_DMA_MAXCH;
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 07da58b..a965acd 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -371,7 +371,7 @@ static void rio_switch_init(struct rio_dev *rdev, int do_enum)
  * device to the RIO device list.  Creates the generic sysfs nodes
  * for an RIO device.
  */
-static int __devinit rio_add_device(struct rio_dev *rdev)
+static int rio_add_device(struct rio_dev *rdev)
 {
 	int err;
 
@@ -463,7 +463,7 @@ inline int rio_enable_rx_tx_port(struct rio_mport *port,
  * to a RIO device on success or NULL on failure.
  *
  */
-static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
+static struct rio_dev *rio_setup_device(struct rio_net *net,
 					struct rio_mport *port, u16 destid,
 					u8 hopcount, int do_enum)
 {
@@ -837,7 +837,7 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount)
  * Recursively enumerates a RIO network.  Transactions are sent via the
  * master port passed in @port.
  */
-static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
+static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
 			 u8 hopcount, struct rio_dev *prev, int prev_port)
 {
 	struct rio_dev *rdev;
@@ -1044,7 +1044,7 @@ static int rio_enum_complete(struct rio_mport *port)
  * Recursively discovers a RIO network.  Transactions are sent via the
  * master port passed in @port.
  */
-static int __devinit
+static int
 rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
 	      u8 hopcount, struct rio_dev *prev, int prev_port)
 {
@@ -1151,7 +1151,7 @@ static int rio_mport_is_active(struct rio_mport *port)
  * network list of associated master ports. Returns a
  * RIO network pointer on success or %NULL on failure.
  */
-static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port,
+static struct rio_net *rio_alloc_net(struct rio_mport *port,
 					       int do_enum, u16 start)
 {
 	struct rio_net *net;
@@ -1266,7 +1266,7 @@ static void rio_pw_enable(struct rio_mport *port, int enable)
  * link, then start recursive peer enumeration. Returns %0 if
  * enumeration succeeds or %-EBUSY if enumeration fails.
  */
-int __devinit rio_enum_mport(struct rio_mport *mport)
+int rio_enum_mport(struct rio_mport *mport)
 {
 	struct rio_net *net = NULL;
 	int rc = 0;
@@ -1369,7 +1369,7 @@ static void rio_build_route_tables(struct rio_net *net)
  * peer discovery. Returns %0 if discovery succeeds or %-EBUSY
  * on failure.
  */
-int __devinit rio_disc_mport(struct rio_mport *mport)
+int rio_disc_mport(struct rio_mport *mport)
 {
 	struct rio_net *net = NULL;
 	unsigned long to_end;
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index 0c6fcb4..d553b5d 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -1250,7 +1250,7 @@ static void rio_fixup_device(struct rio_dev *dev)
 {
 }
 
-static int __devinit rio_init(void)
+static int rio_init(void)
 {
 	struct rio_dev *dev = NULL;
 
@@ -1267,7 +1267,7 @@ struct rio_disc_work {
 	struct rio_mport	*mport;
 };
 
-static void __devinit disc_work_handler(struct work_struct *_work)
+static void disc_work_handler(struct work_struct *_work)
 {
 	struct rio_disc_work *work;
 
@@ -1277,7 +1277,7 @@ static void __devinit disc_work_handler(struct work_struct *_work)
 	rio_disc_mport(work->mport);
 }
 
-int __devinit rio_init_mports(void)
+int rio_init_mports(void)
 {
 	struct rio_mport *port;
 	struct rio_disc_work *work;
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index 1c5ab01..2b55711 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -394,7 +394,7 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev,
 #define pm8607_regulator_dt_init(x, y, z)	(-1)
 #endif
 
-static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
+static int pm8607_regulator_probe(struct platform_device *pdev)
 {
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct pm8607_regulator_info *info = NULL;
@@ -454,7 +454,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit pm8607_regulator_remove(struct platform_device *pdev)
+static int pm8607_regulator_remove(struct platform_device *pdev)
 {
 	struct pm8607_regulator_info *info = platform_get_drvdata(pdev);
 
@@ -481,7 +481,7 @@ static struct platform_driver pm8607_regulator_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= pm8607_regulator_probe,
-	.remove		= __devexit_p(pm8607_regulator_remove),
+	.remove		= pm8607_regulator_remove,
 	.id_table	= pm8607_regulator_driver_ids,
 };
 
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 67d47b59..551a22b 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -109,6 +109,16 @@ config REGULATOR_DA9052
 	  This driver supports the voltage regulators of DA9052-BC and
 	  DA9053-AA/Bx PMIC.
 
+config REGULATOR_DA9055
+	tristate "Dialog Semiconductor DA9055 regulators"
+	depends on MFD_DA9055
+	help
+	  Say y here to support the BUCKs and LDOs regulators found on
+	  Dialog Semiconductor DA9055 PMIC.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called da9055-regulator.
+
 config REGULATOR_FAN53555
 	tristate "Fairchild FAN53555 Regulator"
 	depends on I2C
@@ -204,6 +214,16 @@ config REGULATOR_MAX8952
 	  via I2C bus. Maxim 8952 has one voltage output and supports 4 DVS
 	  modes ranging from 0.77V to 1.40V by 0.01V steps.
 
+config REGULATOR_MAX8973
+	tristate "Maxim MAX8973 voltage regulator "
+	depends on I2C
+	select REGMAP_I2C
+	help
+	  The MAXIM MAX8973 high-efficiency. three phase, DC-DC step-down
+	  switching regulator delievers up to 9A of output current. Each
+	  phase operates at a 2MHz fixed frequency with a 120 deg shift
+	  from the adjacent phase, allowing the use of small magnetic component.
+
 config REGULATOR_MAX8997
 	tristate "Maxim 8997/8966 regulator"
 	depends on MFD_MAX8997
@@ -335,6 +355,17 @@ config REGULATOR_PALMAS
 	  on the muxing. This is handled automatically in the driver by
 	  reading the mux info from OTP.
 
+config REGULATOR_TPS51632
+	tristate "TI TPS51632 Power Regulator"
+	depends on I2C
+	select REGMAP_I2C
+	help
+	  This driver supports TPS51632 voltage regulator chip.
+	  The TPS51632 is 3-2-1 Phase D-Cap+ Step Down Driverless Controller
+	  with Serial VID control and DVFS.
+	  The voltage output can be configure through I2C interface or PWM
+	  interface.
+
 config REGULATOR_TPS6105X
 	tristate "TI TPS6105X Power regulators"
 	depends on TPS6105X
@@ -415,6 +446,15 @@ config REGULATOR_TPS65912
 	help
 	    This driver supports TPS65912 voltage regulator chip.
 
+config REGULATOR_TPS80031
+	tristate "TI TPS80031/TPS80032 power regualtor driver"
+	depends on MFD_TPS80031
+	help
+	  TPS80031/ TPS80032 Fully Integrated Power Management with Power
+	  Path and Battery Charger. It has 5 configurable step-down
+	  converters, 11 general purpose LDOs, VBUS generator and digital
+	  output to control regulators.
+
 config REGULATOR_TWL4030
 	bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 PMIC"
 	depends on TWL4030_CORE
@@ -422,6 +462,13 @@ config REGULATOR_TWL4030
 	  This driver supports the voltage regulators provided by
 	  this family of companion chips.
 
+config REGULATOR_VEXPRESS
+	tristate "Versatile Express regulators"
+	depends on VEXPRESS_CONFIG
+	help
+	  This driver provides support for voltage regulators available
+	  on the ARM Ltd's Versatile Express platform.
+
 config REGULATOR_WM831X
 	tristate "Wolfson Microelectronics WM831x PMIC regulators"
 	depends on MFD_WM831X
@@ -450,5 +497,12 @@ config REGULATOR_WM8994
 	  This driver provides support for the voltage regulators on the
 	  WM8994 CODEC.
 
+config REGULATOR_AS3711
+	tristate "AS3711 PMIC"
+	depends on MFD_AS3711
+	help
+	  This driver provides support for the voltage regulators on the
+	  AS3711 PMIC
+
 endif
 
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index e431eed..b802b0c 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -16,8 +16,10 @@ obj-$(CONFIG_REGULATOR_AB8500)	+= ab8500.o
 obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
 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_DA903X)	+= da903x.o
 obj-$(CONFIG_REGULATOR_DA9052)	+= da9052-regulator.o
+obj-$(CONFIG_REGULATOR_DA9055)	+= da9055-regulator.o
 obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
 obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
 obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
@@ -34,6 +36,7 @@ obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
 obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o
 obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
 obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
+obj-$(CONFIG_REGULATOR_MAX8973) += max8973-regulator.o
 obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
 obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
 obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o
@@ -41,6 +44,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
 obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
 obj-$(CONFIG_REGULATOR_MC13XXX_CORE) +=  mc13xxx-regulator-core.o
 obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
+obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
 obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
 obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
 obj-$(CONFIG_REGULATOR_RC5T583)  += rc5t583-regulator.o
@@ -56,7 +60,9 @@ obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
+obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
+obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c
index 167c93f..8b58763 100644
--- a/drivers/regulator/aat2870-regulator.c
+++ b/drivers/regulator/aat2870-regulator.c
@@ -187,7 +187,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit aat2870_regulator_remove(struct platform_device *pdev)
+static int aat2870_regulator_remove(struct platform_device *pdev)
 {
 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -201,7 +201,7 @@ static struct platform_driver aat2870_regulator_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe	= aat2870_regulator_probe,
-	.remove	= __devexit_p(aat2870_regulator_remove),
+	.remove	= aat2870_regulator_remove,
 };
 
 static int __init aat2870_regulator_init(void)
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c
index df4ad89..111ec69 100644
--- a/drivers/regulator/ab3100.c
+++ b/drivers/regulator/ab3100.c
@@ -494,7 +494,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
  * for all the different regulators.
  */
 
-static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
+static int ab3100_regulators_probe(struct platform_device *pdev)
 {
 	struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
 	struct regulator_config config = { };
@@ -571,7 +571,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit ab3100_regulators_remove(struct platform_device *pdev)
+static int ab3100_regulators_remove(struct platform_device *pdev)
 {
 	int i;
 
@@ -589,7 +589,7 @@ static struct platform_driver ab3100_regulators_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ab3100_regulators_probe,
-	.remove = __devexit_p(ab3100_regulators_remove),
+	.remove = ab3100_regulators_remove,
 };
 
 static __init int ab3100_regulators_init(void)
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c
index e3d1d06..09014f3 100644
--- a/drivers/regulator/ab8500.c
+++ b/drivers/regulator/ab8500.c
@@ -641,7 +641,7 @@ static struct ab8500_reg_init ab8500_reg_init[] = {
 	REG_INIT(AB8500_REGUCTRLDISCH2,		0x04, 0x44, 0x16),
 };
 
-static __devinit int
+static int
 ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
 {
 	int err;
@@ -676,7 +676,7 @@ ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
 	return 0;
 }
 
-static __devinit int ab8500_regulator_register(struct platform_device *pdev,
+static int ab8500_regulator_register(struct platform_device *pdev,
 					struct regulator_init_data *init_data,
 					int id,
 					struct device_node *np)
@@ -735,7 +735,7 @@ static struct of_regulator_match ab8500_regulator_matches[] = {
 	{ .name	= "ab8500_ldo_ana",     .driver_data = (void *) AB8500_LDO_ANA, },
 };
 
-static __devinit int
+static int
 ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
 {
 	int err, i;
@@ -751,7 +751,7 @@ ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
 	return 0;
 }
 
-static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
+static int ab8500_regulator_probe(struct platform_device *pdev)
 {
 	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
 	struct ab8500_platform_data *pdata;
@@ -817,7 +817,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
+static int ab8500_regulator_remove(struct platform_device *pdev)
 {
 	int i;
 
@@ -836,7 +836,7 @@ static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
 
 static struct platform_driver ab8500_regulator_driver = {
 	.probe = ab8500_regulator_probe,
-	.remove = __devexit_p(ab8500_regulator_remove),
+	.remove = ab8500_regulator_remove,
 	.driver         = {
 		.name   = "ab8500-regulator",
 		.owner  = THIS_MODULE,
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
index f123f7e..6b981b5 100644
--- a/drivers/regulator/ad5398.c
+++ b/drivers/regulator/ad5398.c
@@ -211,7 +211,7 @@ static const struct i2c_device_id ad5398_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, ad5398_id);
 
-static int __devinit ad5398_probe(struct i2c_client *client,
+static int ad5398_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
 	struct regulator_init_data *init_data = client->dev.platform_data;
@@ -256,7 +256,7 @@ err:
 	return ret;
 }
 
-static int __devexit ad5398_remove(struct i2c_client *client)
+static int ad5398_remove(struct i2c_client *client)
 {
 	struct ad5398_chip_info *chip = i2c_get_clientdata(client);
 
@@ -266,7 +266,7 @@ static int __devexit ad5398_remove(struct i2c_client *client)
 
 static struct i2c_driver ad5398_driver = {
 	.probe = ad5398_probe,
-	.remove = __devexit_p(ad5398_remove),
+	.remove = ad5398_remove,
 	.driver		= {
 		.name	= "ad5398",
 	},
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
index 1af9768..1aa5246 100644
--- a/drivers/regulator/anatop-regulator.c
+++ b/drivers/regulator/anatop-regulator.c
@@ -87,7 +87,7 @@ static struct regulator_ops anatop_rops = {
 	.map_voltage = regulator_map_voltage_linear,
 };
 
-static int __devinit anatop_regulator_probe(struct platform_device *pdev)
+static int anatop_regulator_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
@@ -186,7 +186,7 @@ anatop_probe_end:
 	return ret;
 }
 
-static int __devexit anatop_regulator_remove(struct platform_device *pdev)
+static int anatop_regulator_remove(struct platform_device *pdev)
 {
 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
 	struct anatop_regulator *sreg = rdev_get_drvdata(rdev);
@@ -210,7 +210,7 @@ static struct platform_driver anatop_regulator_driver = {
 		.of_match_table = of_anatop_regulator_match_tbl,
 	},
 	.probe	= anatop_regulator_probe,
-	.remove	= __devexit_p(anatop_regulator_remove),
+	.remove	= anatop_regulator_remove,
 };
 
 static int __init anatop_regulator_init(void)
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
index d184aa3..ed7beec 100644
--- a/drivers/regulator/arizona-ldo1.c
+++ b/drivers/regulator/arizona-ldo1.c
@@ -34,6 +34,108 @@ struct arizona_ldo1 {
 	struct regulator_init_data init_data;
 };
 
+static int arizona_ldo1_hc_list_voltage(struct regulator_dev *rdev,
+					unsigned int selector)
+{
+	if (selector >= rdev->desc->n_voltages)
+		return -EINVAL;
+
+	if (selector == rdev->desc->n_voltages - 1)
+		return 1800000;
+	else
+		return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
+}
+
+static int arizona_ldo1_hc_map_voltage(struct regulator_dev *rdev,
+				       int min_uV, int max_uV)
+{
+	int sel;
+
+	sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
+	if (sel >= rdev->desc->n_voltages)
+		sel = rdev->desc->n_voltages - 1;
+
+	return sel;
+}
+
+static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev,
+					   unsigned sel)
+{
+	struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev);
+	struct regmap *regmap = ldo->arizona->regmap;
+	unsigned int val;
+	int ret;
+
+	if (sel == rdev->desc->n_voltages - 1)
+		val = ARIZONA_LDO1_HI_PWR;
+	else
+		val = 0;
+
+	ret = regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_2,
+				 ARIZONA_LDO1_HI_PWR, val);
+	if (ret != 0)
+		return ret;
+
+	ret = regmap_update_bits(regmap, ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
+				 ARIZONA_SUBSYS_MAX_FREQ, val);
+	if (ret != 0)
+		return ret;
+
+	if (val)
+		return 0;
+
+	val = sel << ARIZONA_LDO1_VSEL_SHIFT;
+
+	return regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_1,
+				  ARIZONA_LDO1_VSEL_MASK, val);
+}
+
+static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev)
+{
+	struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev);
+	struct regmap *regmap = ldo->arizona->regmap;
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_2, &val);
+	if (ret != 0)
+		return ret;
+
+	if (val & ARIZONA_LDO1_HI_PWR)
+		return rdev->desc->n_voltages - 1;
+
+	ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_1, &val);
+	if (ret != 0)
+		return ret;
+
+	return (val & ARIZONA_LDO1_VSEL_MASK) >> ARIZONA_LDO1_VSEL_SHIFT;
+}
+
+static struct regulator_ops arizona_ldo1_hc_ops = {
+	.list_voltage = arizona_ldo1_hc_list_voltage,
+	.map_voltage = arizona_ldo1_hc_map_voltage,
+	.get_voltage_sel = arizona_ldo1_hc_get_voltage_sel,
+	.set_voltage_sel = arizona_ldo1_hc_set_voltage_sel,
+	.get_bypass = regulator_get_bypass_regmap,
+	.set_bypass = regulator_set_bypass_regmap,
+};
+
+static const struct regulator_desc arizona_ldo1_hc = {
+	.name = "LDO1",
+	.supply_name = "LDOVDD",
+	.type = REGULATOR_VOLTAGE,
+	.ops = &arizona_ldo1_hc_ops,
+
+	.bypass_reg = ARIZONA_LDO1_CONTROL_1,
+	.bypass_mask = ARIZONA_LDO1_BYPASS,
+	.min_uV = 900000,
+	.uV_step = 50000,
+	.n_voltages = 8,
+	.enable_time = 500,
+
+	.owner = THIS_MODULE,
+};
+
 static struct regulator_ops arizona_ldo1_ops = {
 	.list_voltage = regulator_list_voltage_linear,
 	.map_voltage = regulator_map_voltage_linear,
@@ -55,11 +157,22 @@ static const struct regulator_desc arizona_ldo1 = {
 	.bypass_mask = ARIZONA_LDO1_BYPASS,
 	.min_uV = 900000,
 	.uV_step = 50000,
-	.n_voltages = 6,
+	.n_voltages = 7,
+	.enable_time = 500,
 
 	.owner = THIS_MODULE,
 };
 
+static const struct regulator_init_data arizona_ldo1_dvfs = {
+	.constraints = {
+		.min_uV = 1200000,
+		.max_uV = 1800000,
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS |
+				  REGULATOR_CHANGE_VOLTAGE,
+	},
+	.num_consumer_supplies = 1,
+};
+
 static const struct regulator_init_data arizona_ldo1_default = {
 	.constraints = {
 		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -67,9 +180,10 @@ static const struct regulator_init_data arizona_ldo1_default = {
 	.num_consumer_supplies = 1,
 };
 
-static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
+static int arizona_ldo1_probe(struct platform_device *pdev)
 {
 	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+	const struct regulator_desc *desc;
 	struct regulator_config config = { };
 	struct arizona_ldo1 *ldo1;
 	int ret;
@@ -87,7 +201,17 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
 	 * default init_data for it.  This will be overridden with
 	 * platform data if provided.
 	 */
-	ldo1->init_data = arizona_ldo1_default;
+	switch (arizona->type) {
+	case WM5102:
+		desc = &arizona_ldo1_hc;
+		ldo1->init_data = arizona_ldo1_dvfs;
+		break;
+	default:
+		desc = &arizona_ldo1;
+		ldo1->init_data = arizona_ldo1_default;
+		break;
+	}
+
 	ldo1->init_data.consumer_supplies = &ldo1->supply;
 	ldo1->supply.supply = "DCVDD";
 	ldo1->supply.dev_name = dev_name(arizona->dev);
@@ -102,7 +226,7 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
 	else
 		config.init_data = &ldo1->init_data;
 
-	ldo1->regulator = regulator_register(&arizona_ldo1, &config);
+	ldo1->regulator = regulator_register(desc, &config);
 	if (IS_ERR(ldo1->regulator)) {
 		ret = PTR_ERR(ldo1->regulator);
 		dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n",
@@ -115,7 +239,7 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
+static int arizona_ldo1_remove(struct platform_device *pdev)
 {
 	struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev);
 
@@ -126,7 +250,7 @@ static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
 
 static struct platform_driver arizona_ldo1_driver = {
 	.probe = arizona_ldo1_probe,
-	.remove = __devexit_p(arizona_ldo1_remove),
+	.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 d9b1f82..a6d040c 100644
--- a/drivers/regulator/arizona-micsupp.c
+++ b/drivers/regulator/arizona-micsupp.c
@@ -101,6 +101,8 @@ static const struct regulator_desc arizona_micsupp = {
 	.bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1,
 	.bypass_mask = ARIZONA_CPMIC_BYPASS,
 
+	.enable_time = 3000,
+
 	.owner = THIS_MODULE,
 };
 
@@ -115,7 +117,7 @@ static const struct regulator_init_data arizona_micsupp_default = {
 	.num_consumer_supplies = 1,
 };
 
-static __devinit int arizona_micsupp_probe(struct platform_device *pdev)
+static int arizona_micsupp_probe(struct platform_device *pdev)
 {
 	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
 	struct regulator_config config = { };
@@ -166,7 +168,7 @@ static __devinit int arizona_micsupp_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
+static int arizona_micsupp_remove(struct platform_device *pdev)
 {
 	struct arizona_micsupp *micsupp = platform_get_drvdata(pdev);
 
@@ -177,7 +179,7 @@ static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
 
 static struct platform_driver arizona_micsupp_driver = {
 	.probe = arizona_micsupp_probe,
-	.remove = __devexit_p(arizona_micsupp_remove),
+	.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
new file mode 100644
index 0000000..2f1341d
--- /dev/null
+++ b/drivers/regulator/as3711-regulator.c
@@ -0,0 +1,369 @@
+/*
+ * AS3711 PMIC regulator driver, using DCDC Step Down and LDO supplies
+ *
+ * Copyright (C) 2012 Renesas Electronics Corporation
+ * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License as
+ * published by the Free Software Foundation
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/mfd/as3711.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/slab.h>
+
+struct as3711_regulator_info {
+	struct regulator_desc	desc;
+	unsigned int		max_uV;
+};
+
+struct as3711_regulator {
+	struct as3711_regulator_info *reg_info;
+	struct regulator_dev *rdev;
+};
+
+static int as3711_list_voltage_sd(struct regulator_dev *rdev,
+				  unsigned int selector)
+{
+	if (selector >= rdev->desc->n_voltages)
+		return -EINVAL;
+
+	if (!selector)
+		return 0;
+	if (selector < 0x41)
+		return 600000 + selector * 12500;
+	if (selector < 0x71)
+		return 1400000 + (selector - 0x40) * 25000;
+	return 2600000 + (selector - 0x70) * 50000;
+}
+
+static int as3711_list_voltage_aldo(struct regulator_dev *rdev,
+				    unsigned int selector)
+{
+	if (selector >= rdev->desc->n_voltages)
+		return -EINVAL;
+
+	if (selector < 0x10)
+		return 1200000 + selector * 50000;
+	return 1800000 + (selector - 0x10) * 100000;
+}
+
+static int as3711_list_voltage_dldo(struct regulator_dev *rdev,
+				    unsigned int selector)
+{
+	if (selector >= rdev->desc->n_voltages ||
+	    (selector > 0x10 && selector < 0x20))
+		return -EINVAL;
+
+	if (selector < 0x11)
+		return 900000 + selector * 50000;
+	return 1750000 + (selector - 0x20) * 50000;
+}
+
+static int as3711_bound_check(struct regulator_dev *rdev,
+			      int *min_uV, int *max_uV)
+{
+	struct as3711_regulator *reg = rdev_get_drvdata(rdev);
+	struct as3711_regulator_info *info = reg->reg_info;
+
+	dev_dbg(&rdev->dev, "%s(), %d, %d, %d\n", __func__,
+		*min_uV, rdev->desc->min_uV, info->max_uV);
+
+	if (*max_uV < *min_uV ||
+	    *min_uV > info->max_uV || rdev->desc->min_uV > *max_uV)
+		return -EINVAL;
+
+	if (rdev->desc->n_voltages == 1)
+		return 0;
+
+	if (*max_uV > info->max_uV)
+		*max_uV = info->max_uV;
+
+	if (*min_uV < rdev->desc->min_uV)
+		*min_uV = rdev->desc->min_uV;
+
+	return *min_uV;
+}
+
+static int as3711_sel_check(int min, int max, int bottom, int step)
+{
+	int sel, voltage;
+
+	/* Round up min, when dividing: keeps us within the range */
+	sel = DIV_ROUND_UP(min - bottom, step);
+	voltage = sel * step + bottom;
+	pr_debug("%s(): select %d..%d in %d+N*%d: %d\n", __func__,
+	       min, max, bottom, step, sel);
+	if (voltage > max)
+		return -EINVAL;
+
+	return sel;
+}
+
+static int as3711_map_voltage_sd(struct regulator_dev *rdev,
+				 int min_uV, int max_uV)
+{
+	int ret;
+
+	ret = as3711_bound_check(rdev, &min_uV, &max_uV);
+	if (ret <= 0)
+		return ret;
+
+	if (min_uV <= 1400000)
+		return as3711_sel_check(min_uV, max_uV, 600000, 12500);
+
+	if (min_uV <= 2600000)
+		return as3711_sel_check(min_uV, max_uV, 1400000, 25000) + 0x40;
+
+	return as3711_sel_check(min_uV, max_uV, 2600000, 50000) + 0x70;
+}
+
+/*
+ * The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and
+ * STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes:
+ * FAST:	sdX_fast=1
+ * NORMAL:	low_noise=1
+ * IDLE:	low_noise=0
+ */
+
+static int as3711_set_mode_sd(struct regulator_dev *rdev, unsigned int mode)
+{
+	unsigned int fast_bit = rdev->desc->enable_mask,
+		low_noise_bit = fast_bit << 4;
+	u8 val;
+
+	switch (mode) {
+	case REGULATOR_MODE_FAST:
+		val = fast_bit | low_noise_bit;
+		break;
+	case REGULATOR_MODE_NORMAL:
+		val = low_noise_bit;
+		break;
+	case REGULATOR_MODE_IDLE:
+		val = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return regmap_update_bits(rdev->regmap, AS3711_SD_CONTROL_1,
+				  low_noise_bit | fast_bit, val);
+}
+
+static unsigned int as3711_get_mode_sd(struct regulator_dev *rdev)
+{
+	unsigned int fast_bit = rdev->desc->enable_mask,
+		low_noise_bit = fast_bit << 4, mask = fast_bit | low_noise_bit;
+	unsigned int val;
+	int ret = regmap_read(rdev->regmap, AS3711_SD_CONTROL_1, &val);
+
+	if (ret < 0)
+		return ret;
+
+	if ((val & mask) == mask)
+		return REGULATOR_MODE_FAST;
+
+	if ((val & mask) == low_noise_bit)
+		return REGULATOR_MODE_NORMAL;
+
+	if (!(val & mask))
+		return REGULATOR_MODE_IDLE;
+
+	return -EINVAL;
+}
+
+static int as3711_map_voltage_aldo(struct regulator_dev *rdev,
+				  int min_uV, int max_uV)
+{
+	int ret;
+
+	ret = as3711_bound_check(rdev, &min_uV, &max_uV);
+	if (ret <= 0)
+		return ret;
+
+	if (min_uV <= 1800000)
+		return as3711_sel_check(min_uV, max_uV, 1200000, 50000);
+
+	return as3711_sel_check(min_uV, max_uV, 1800000, 100000) + 0x10;
+}
+
+static int as3711_map_voltage_dldo(struct regulator_dev *rdev,
+				  int min_uV, int max_uV)
+{
+	int ret;
+
+	ret = as3711_bound_check(rdev, &min_uV, &max_uV);
+	if (ret <= 0)
+		return ret;
+
+	if (min_uV <= 1700000)
+		return as3711_sel_check(min_uV, max_uV, 900000, 50000);
+
+	return as3711_sel_check(min_uV, max_uV, 1750000, 50000) + 0x20;
+}
+
+static struct regulator_ops as3711_sd_ops = {
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.list_voltage		= as3711_list_voltage_sd,
+	.map_voltage		= as3711_map_voltage_sd,
+	.get_mode		= as3711_get_mode_sd,
+	.set_mode		= as3711_set_mode_sd,
+};
+
+static struct regulator_ops as3711_aldo_ops = {
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.list_voltage		= as3711_list_voltage_aldo,
+	.map_voltage		= as3711_map_voltage_aldo,
+};
+
+static struct regulator_ops as3711_dldo_ops = {
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.list_voltage		= as3711_list_voltage_dldo,
+	.map_voltage		= as3711_map_voltage_dldo,
+};
+
+#define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx)	\
+	[AS3711_REGULATOR_ ## _id] = {							\
+	.desc = {									\
+		.name = "as3711-regulator-" # _id,					\
+		.id = AS3711_REGULATOR_ ## _id,						\
+		.n_voltages = (_vmask + 1),						\
+		.ops = &as3711_ ## _sfx ## _ops,					\
+		.type = REGULATOR_VOLTAGE,						\
+		.owner = THIS_MODULE,							\
+		.vsel_reg = AS3711_ ## _id ## _VOLTAGE,					\
+		.vsel_mask = _vmask << _vshift,						\
+		.enable_reg = AS3711_ ## _en_reg,					\
+		.enable_mask = BIT(_en_bit),						\
+		.min_uV	= _min_uV,							\
+	},										\
+	.max_uV = _max_uV,								\
+}
+
+static struct as3711_regulator_info as3711_reg_info[] = {
+	AS3711_REG(SD_1, SD_CONTROL, 0, 0x7f, 0, 612500, 3350000, sd),
+	AS3711_REG(SD_2, SD_CONTROL, 1, 0x7f, 0, 612500, 3350000, sd),
+	AS3711_REG(SD_3, SD_CONTROL, 2, 0x7f, 0, 612500, 3350000, sd),
+	AS3711_REG(SD_4, SD_CONTROL, 3, 0x7f, 0, 612500, 3350000, sd),
+	AS3711_REG(LDO_1, LDO_1_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo),
+	AS3711_REG(LDO_2, LDO_2_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo),
+	AS3711_REG(LDO_3, LDO_3_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+	AS3711_REG(LDO_4, LDO_4_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+	AS3711_REG(LDO_5, LDO_5_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+	AS3711_REG(LDO_6, LDO_6_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+	AS3711_REG(LDO_7, LDO_7_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+	AS3711_REG(LDO_8, LDO_8_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+	/* StepUp output voltage depends on supplying regulator */
+};
+
+#define AS3711_REGULATOR_NUM ARRAY_SIZE(as3711_reg_info)
+
+static int as3711_regulator_probe(struct platform_device *pdev)
+{
+	struct as3711_regulator_pdata *pdata = dev_get_platdata(&pdev->dev);
+	struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent);
+	struct regulator_init_data *reg_data;
+	struct regulator_config config = {.dev = &pdev->dev,};
+	struct as3711_regulator *reg = NULL;
+	struct as3711_regulator *regs;
+	struct regulator_dev *rdev;
+	struct as3711_regulator_info *ri;
+	int ret;
+	int id;
+
+	if (!pdata)
+		dev_dbg(&pdev->dev, "No platform data...\n");
+
+	regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM *
+			sizeof(struct as3711_regulator), GFP_KERNEL);
+	if (!regs) {
+		dev_err(&pdev->dev, "Memory allocation failed exiting..\n");
+		return -ENOMEM;
+	}
+
+	for (id = 0, ri = as3711_reg_info; id < AS3711_REGULATOR_NUM; ++id, ri++) {
+		reg_data = pdata ? pdata->init_data[id] : NULL;
+
+		/* No need to register if there is no regulator data */
+		if (!ri->desc.name)
+			continue;
+
+		reg = &regs[id];
+		reg->reg_info = ri;
+
+		config.init_data = reg_data;
+		config.driver_data = reg;
+		config.regmap = as3711->regmap;
+
+		rdev = regulator_register(&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;
+		}
+		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 = {
+	.driver	= {
+		.name	= "as3711-regulator",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= as3711_regulator_probe,
+	.remove		= as3711_regulator_remove,
+};
+
+static int __init as3711_regulator_init(void)
+{
+	return platform_driver_register(&as3711_regulator_driver);
+}
+subsys_initcall(as3711_regulator_init);
+
+static void __exit as3711_regulator_exit(void)
+{
+	platform_driver_unregister(&as3711_regulator_driver);
+}
+module_exit(as3711_regulator_exit);
+
+MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
+MODULE_DESCRIPTION("AS3711 regulator driver");
+MODULE_ALIAS("platform:as3711-regulator");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index e872c8b..af97b62 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -199,8 +199,11 @@ static int regulator_check_consumers(struct regulator_dev *rdev,
 			*min_uV = regulator->min_uV;
 	}
 
-	if (*min_uV > *max_uV)
+	if (*min_uV > *max_uV) {
+		dev_err(regulator->dev, "Restricting voltage, %u-%uuV\n",
+			regulator->min_uV, regulator->max_uV);
 		return -EINVAL;
+	}
 
 	return 0;
 }
@@ -880,7 +883,9 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
 
 		/* final: [min_uV..max_uV] valid iff constraints valid */
 		if (max_uV < min_uV) {
-			rdev_err(rdev, "unsupportable voltage constraints\n");
+			rdev_err(rdev,
+				 "unsupportable voltage constraints %u-%uuV\n",
+				 min_uV, max_uV);
 			return -EINVAL;
 		}
 
@@ -1897,6 +1902,10 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev,
 {
 	if (selector >= rdev->desc->n_voltages)
 		return -EINVAL;
+	if (selector < rdev->desc->linear_min_sel)
+		return 0;
+
+	selector -= rdev->desc->linear_min_sel;
 
 	return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
 }
@@ -1985,6 +1994,11 @@ int regulator_is_supported_voltage(struct regulator *regulator,
 			return ret;
 	}
 
+	/* Any voltage within constrains range is fine? */
+	if (rdev->desc->continuous_voltage_range)
+		return min_uV >= rdev->constraints->min_uV &&
+				max_uV <= rdev->constraints->max_uV;
+
 	ret = regulator_count_voltages(regulator);
 	if (ret < 0)
 		return ret;
@@ -2120,6 +2134,8 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev,
 	if (ret < 0)
 		return ret;
 
+	ret += rdev->desc->linear_min_sel;
+
 	/* Map back into a voltage to verify we're still in bounds */
 	voltage = rdev->desc->ops->list_voltage(rdev, ret);
 	if (voltage < min_uV || voltage > max_uV)
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
index 36c5b92..2afa573 100644
--- a/drivers/regulator/da903x.c
+++ b/drivers/regulator/da903x.c
@@ -460,7 +460,7 @@ static inline struct da903x_regulator_info *find_regulator_info(int id)
 	return NULL;
 }
 
-static int __devinit da903x_regulator_probe(struct platform_device *pdev)
+static int da903x_regulator_probe(struct platform_device *pdev)
 {
 	struct da903x_regulator_info *ri = NULL;
 	struct regulator_dev *rdev;
@@ -499,7 +499,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit da903x_regulator_remove(struct platform_device *pdev)
+static int da903x_regulator_remove(struct platform_device *pdev)
 {
 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -513,7 +513,7 @@ static struct platform_driver da903x_regulator_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= da903x_regulator_probe,
-	.remove		= __devexit_p(da903x_regulator_remove),
+	.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 27355b1..d096309 100644
--- a/drivers/regulator/da9052-regulator.c
+++ b/drivers/regulator/da9052-regulator.c
@@ -129,17 +129,17 @@ static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA,
 	else if (offset == 0)
 		row = 1;
 
-	if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] ||
-	    max_uA < da9052_current_limits[row][DA9052_MIN_UA])
-		return -EINVAL;
-
 	for (i = DA9052_CURRENT_RANGE - 1; i >= 0; i--) {
-		if (da9052_current_limits[row][i] <= max_uA) {
+		if ((min_uA <= da9052_current_limits[row][i]) &&
+		    (da9052_current_limits[row][i] <= max_uA)) {
 			reg_val = i;
 			break;
 		}
 	}
 
+	if (i < 0)
+		return -EINVAL;
+
 	/* Determine the even or odd position of the buck current limit
 	 * register field
 	*/
@@ -365,7 +365,7 @@ static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
 	return NULL;
 }
 
-static int __devinit da9052_regulator_probe(struct platform_device *pdev)
+static int da9052_regulator_probe(struct platform_device *pdev)
 {
 	struct regulator_config config = { };
 	struct da9052_regulator *regulator;
@@ -430,7 +430,7 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit da9052_regulator_remove(struct platform_device *pdev)
+static int da9052_regulator_remove(struct platform_device *pdev)
 {
 	struct da9052_regulator *regulator = platform_get_drvdata(pdev);
 
@@ -440,7 +440,7 @@ static int __devexit da9052_regulator_remove(struct platform_device *pdev)
 
 static struct platform_driver da9052_regulator_driver = {
 	.probe = da9052_regulator_probe,
-	.remove = __devexit_p(da9052_regulator_remove),
+	.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
new file mode 100644
index 0000000..a4b9cb8
--- /dev/null
+++ b/drivers/regulator/da9055-regulator.c
@@ -0,0 +1,641 @@
+/*
+* Regulator driver for DA9055 PMIC
+*
+* Copyright(c) 2012 Dialog Semiconductor Ltd.
+*
+* Author: David Dajun Chen <dchen@diasemi.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the 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/init.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/reg.h>
+#include <linux/mfd/da9055/pdata.h>
+
+#define DA9055_MIN_UA		0
+#define DA9055_MAX_UA		3
+
+#define DA9055_LDO_MODE_SYNC	0
+#define DA9055_LDO_MODE_SLEEP	1
+
+#define DA9055_BUCK_MODE_SLEEP	1
+#define DA9055_BUCK_MODE_SYNC	2
+#define DA9055_BUCK_MODE_AUTO	3
+
+/* DA9055 REGULATOR IDs */
+#define DA9055_ID_BUCK1	0
+#define DA9055_ID_BUCK2	1
+#define DA9055_ID_LDO1		2
+#define DA9055_ID_LDO2		3
+#define DA9055_ID_LDO3		4
+#define DA9055_ID_LDO4		5
+#define DA9055_ID_LDO5		6
+#define DA9055_ID_LDO6		7
+
+/* DA9055 BUCK current limit */
+static const int da9055_current_limits[] = { 500000, 600000, 700000, 800000 };
+
+struct da9055_conf_reg {
+	int reg;
+	int sel_mask;
+	int en_mask;
+};
+
+struct da9055_volt_reg {
+	int reg_a;
+	int reg_b;
+	int sl_shift;
+	int v_mask;
+	int v_shift;
+};
+
+struct da9055_mode_reg {
+	int reg;
+	int mask;
+	int shift;
+};
+
+struct da9055_regulator_info {
+	struct regulator_desc reg_desc;
+	struct da9055_conf_reg conf;
+	struct da9055_volt_reg volt;
+	struct da9055_mode_reg mode;
+};
+
+struct da9055_regulator {
+	struct da9055 *da9055;
+	struct da9055_regulator_info *info;
+	struct regulator_dev *rdev;
+	enum gpio_select reg_rselect;
+};
+
+static unsigned int da9055_buck_get_mode(struct regulator_dev *rdev)
+{
+	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+	struct da9055_regulator_info *info = regulator->info;
+	int ret, mode = 0;
+
+	ret = da9055_reg_read(regulator->da9055, info->mode.reg);
+	if (ret < 0)
+		return ret;
+
+	switch ((ret & info->mode.mask) >> info->mode.shift) {
+	case DA9055_BUCK_MODE_SYNC:
+		mode = REGULATOR_MODE_FAST;
+		break;
+	case DA9055_BUCK_MODE_AUTO:
+		mode = REGULATOR_MODE_NORMAL;
+		break;
+	case DA9055_BUCK_MODE_SLEEP:
+		mode = REGULATOR_MODE_STANDBY;
+		break;
+	}
+
+	return mode;
+}
+
+static int da9055_buck_set_mode(struct regulator_dev *rdev,
+					unsigned int mode)
+{
+	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+	struct da9055_regulator_info *info = regulator->info;
+	int val = 0;
+
+	switch (mode) {
+	case REGULATOR_MODE_FAST:
+		val = DA9055_BUCK_MODE_SYNC << info->mode.shift;
+		break;
+	case REGULATOR_MODE_NORMAL:
+		val = DA9055_BUCK_MODE_AUTO << info->mode.shift;
+		break;
+	case REGULATOR_MODE_STANDBY:
+		val = DA9055_BUCK_MODE_SLEEP << info->mode.shift;
+		break;
+	}
+
+	return da9055_reg_update(regulator->da9055, info->mode.reg,
+				 info->mode.mask, val);
+}
+
+static unsigned int da9055_ldo_get_mode(struct regulator_dev *rdev)
+{
+	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+	struct da9055_regulator_info *info = regulator->info;
+	int ret;
+
+	ret = da9055_reg_read(regulator->da9055, info->volt.reg_b);
+	if (ret < 0)
+		return ret;
+
+	if (ret >> info->volt.sl_shift)
+		return REGULATOR_MODE_STANDBY;
+	else
+		return REGULATOR_MODE_NORMAL;
+}
+
+static int da9055_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+	struct da9055_regulator_info *info = regulator->info;
+	struct da9055_volt_reg volt = info->volt;
+	int val = 0;
+
+	switch (mode) {
+	case REGULATOR_MODE_NORMAL:
+	case REGULATOR_MODE_FAST:
+		val = DA9055_LDO_MODE_SYNC;
+		break;
+	case REGULATOR_MODE_STANDBY:
+		val = DA9055_LDO_MODE_SLEEP;
+		break;
+	}
+
+	return da9055_reg_update(regulator->da9055, volt.reg_b,
+				 1 << volt.sl_shift,
+				 val << volt.sl_shift);
+}
+
+static int da9055_buck_get_current_limit(struct regulator_dev *rdev)
+{
+	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+	struct da9055_regulator_info *info = regulator->info;
+	int ret;
+
+	ret = da9055_reg_read(regulator->da9055, DA9055_REG_BUCK_LIM);
+	if (ret < 0)
+		return ret;
+
+	ret &= info->mode.mask;
+	return da9055_current_limits[ret >> info->mode.shift];
+}
+
+static int da9055_buck_set_current_limit(struct regulator_dev *rdev, int min_uA,
+					 int max_uA)
+{
+	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+	struct da9055_regulator_info *info = regulator->info;
+	int i;
+
+	for (i = ARRAY_SIZE(da9055_current_limits) - 1; i >= 0; i--) {
+		if ((min_uA <= da9055_current_limits[i]) &&
+		    (da9055_current_limits[i] <= max_uA))
+			return da9055_reg_update(regulator->da9055,
+						 DA9055_REG_BUCK_LIM,
+						 info->mode.mask,
+						 i << info->mode.shift);
+	}
+
+	return -EINVAL;
+}
+
+static int da9055_regulator_get_voltage_sel(struct regulator_dev *rdev)
+{
+	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+	struct da9055_regulator_info *info = regulator->info;
+	struct da9055_volt_reg volt = info->volt;
+	int ret, sel;
+
+	/*
+	 * There are two voltage register set A & B for voltage ramping but
+	 * either one of then can be active therefore we first determine
+	 * the active register set.
+	 */
+	ret = da9055_reg_read(regulator->da9055, info->conf.reg);
+	if (ret < 0)
+		return ret;
+
+	ret &= info->conf.sel_mask;
+
+	/* Get the voltage for the active register set A/B */
+	if (ret == DA9055_REGUALTOR_SET_A)
+		ret = da9055_reg_read(regulator->da9055, volt.reg_a);
+	else
+		ret = da9055_reg_read(regulator->da9055, volt.reg_b);
+
+	if (ret < 0)
+		return ret;
+
+	sel = (ret & volt.v_mask);
+	return sel;
+}
+
+static int da9055_regulator_set_voltage_sel(struct regulator_dev *rdev,
+					    unsigned int selector)
+{
+	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+	struct da9055_regulator_info *info = regulator->info;
+	int ret;
+
+	/*
+	 * Regulator register set A/B is not selected through GPIO therefore
+	 * we use default register set A for voltage ramping.
+	 */
+	if (regulator->reg_rselect == NO_GPIO) {
+		/* Select register set A */
+		ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+					info->conf.sel_mask, DA9055_SEL_REG_A);
+		if (ret < 0)
+			return ret;
+
+		/* Set the voltage */
+		return da9055_reg_update(regulator->da9055, info->volt.reg_a,
+					 info->volt.v_mask, selector);
+	}
+
+	/*
+	 * Here regulator register set A/B is selected through GPIO.
+	 * Therefore we first determine the selected register set A/B and
+	 * then set the desired voltage for that register set A/B.
+	 */
+	ret = da9055_reg_read(regulator->da9055, info->conf.reg);
+	if (ret < 0)
+		return ret;
+
+	ret &= info->conf.sel_mask;
+
+	/* Set the voltage */
+	if (ret == DA9055_REGUALTOR_SET_A)
+		return da9055_reg_update(regulator->da9055, info->volt.reg_a,
+					 info->volt.v_mask, selector);
+	else
+		return da9055_reg_update(regulator->da9055, info->volt.reg_b,
+					 info->volt.v_mask, selector);
+}
+
+static int da9055_regulator_set_suspend_voltage(struct regulator_dev *rdev,
+						int uV)
+{
+	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+	struct da9055_regulator_info *info = regulator->info;
+	int ret;
+
+	/* Select register set B for suspend voltage ramping. */
+	if (regulator->reg_rselect == NO_GPIO) {
+		ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+					info->conf.sel_mask, DA9055_SEL_REG_B);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = regulator_map_voltage_linear(rdev, uV, uV);
+	if (ret < 0)
+		return ret;
+
+	return da9055_reg_update(regulator->da9055, info->volt.reg_b,
+				 info->volt.v_mask, ret);
+}
+
+static int da9055_suspend_enable(struct regulator_dev *rdev)
+{
+	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+	struct da9055_regulator_info *info = regulator->info;
+
+	/* Select register set B for voltage ramping. */
+	if (regulator->reg_rselect == NO_GPIO)
+		return da9055_reg_update(regulator->da9055, info->conf.reg,
+					info->conf.sel_mask, DA9055_SEL_REG_B);
+	else
+		return 0;
+}
+
+static int da9055_suspend_disable(struct regulator_dev *rdev)
+{
+	struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+	struct da9055_regulator_info *info = regulator->info;
+
+	/* Diselect register set B. */
+	if (regulator->reg_rselect == NO_GPIO)
+		return da9055_reg_update(regulator->da9055, info->conf.reg,
+					info->conf.sel_mask, DA9055_SEL_REG_A);
+	else
+		return 0;
+}
+
+static struct regulator_ops da9055_buck_ops = {
+	.get_mode = da9055_buck_get_mode,
+	.set_mode = da9055_buck_set_mode,
+
+	.get_current_limit = da9055_buck_get_current_limit,
+	.set_current_limit = da9055_buck_set_current_limit,
+
+	.get_voltage_sel = da9055_regulator_get_voltage_sel,
+	.set_voltage_sel = da9055_regulator_set_voltage_sel,
+	.list_voltage = regulator_list_voltage_linear,
+	.map_voltage = regulator_map_voltage_linear,
+	.is_enabled = regulator_is_enabled_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+
+	.set_suspend_voltage = da9055_regulator_set_suspend_voltage,
+	.set_suspend_enable = da9055_suspend_enable,
+	.set_suspend_disable = da9055_suspend_disable,
+	.set_suspend_mode = da9055_buck_set_mode,
+};
+
+static struct regulator_ops da9055_ldo_ops = {
+	.get_mode = da9055_ldo_get_mode,
+	.set_mode = da9055_ldo_set_mode,
+
+	.get_voltage_sel = da9055_regulator_get_voltage_sel,
+	.set_voltage_sel = da9055_regulator_set_voltage_sel,
+	.list_voltage = regulator_list_voltage_linear,
+	.map_voltage = regulator_map_voltage_linear,
+	.is_enabled = regulator_is_enabled_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+
+	.set_suspend_voltage = da9055_regulator_set_suspend_voltage,
+	.set_suspend_enable = da9055_suspend_enable,
+	.set_suspend_disable = da9055_suspend_disable,
+	.set_suspend_mode = da9055_ldo_set_mode,
+
+};
+
+#define DA9055_LDO(_id, step, min, max, vbits, voffset) \
+{\
+	.reg_desc = {\
+		.name = #_id,\
+		.ops = &da9055_ldo_ops,\
+		.type = REGULATOR_VOLTAGE,\
+		.id = DA9055_ID_##_id,\
+		.n_voltages = (max - min) / step + 1 + (voffset), \
+		.enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+		.enable_mask = 1, \
+		.min_uV = (min) * 1000,\
+		.uV_step = (step) * 1000,\
+		.linear_min_sel = (voffset),\
+		.owner = THIS_MODULE,\
+	},\
+	.conf = {\
+		.reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+		.sel_mask = (1 << 4),\
+		.en_mask = 1,\
+	},\
+	.volt = {\
+		.reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \
+		.reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \
+		.sl_shift = 7,\
+		.v_mask = (1 << (vbits)) - 1,\
+		.v_shift = (vbits),\
+	},\
+}
+
+#define DA9055_BUCK(_id, step, min, max, vbits, voffset, mbits, sbits) \
+{\
+	.reg_desc = {\
+		.name = #_id,\
+		.ops = &da9055_buck_ops,\
+		.type = REGULATOR_VOLTAGE,\
+		.id = DA9055_ID_##_id,\
+		.n_voltages = (max - min) / step + 1 + (voffset), \
+		.enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+		.enable_mask = 1,\
+		.min_uV = (min) * 1000,\
+		.uV_step = (step) * 1000,\
+		.linear_min_sel = (voffset),\
+		.owner = THIS_MODULE,\
+	},\
+	.conf = {\
+		.reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+		.sel_mask = (1 << 4),\
+		.en_mask = 1,\
+	},\
+	.volt = {\
+		.reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \
+		.reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \
+		.sl_shift = 7,\
+		.v_mask = (1 << (vbits)) - 1,\
+		.v_shift = (vbits),\
+	},\
+	.mode = {\
+		.reg = DA9055_REG_BCORE_MODE,\
+		.mask = (mbits),\
+		.shift = (sbits),\
+	},\
+}
+
+static struct da9055_regulator_info da9055_regulator_info[] = {
+	DA9055_BUCK(BUCK1, 25, 725, 2075, 6, 9, 0xc, 2),
+	DA9055_BUCK(BUCK2, 25, 925, 2500, 6, 0, 3, 0),
+	DA9055_LDO(LDO1, 50, 900, 3300, 6, 2),
+	DA9055_LDO(LDO2, 50, 900, 3300, 6, 3),
+	DA9055_LDO(LDO3, 50, 900, 3300, 6, 2),
+	DA9055_LDO(LDO4, 50, 900, 3300, 6, 2),
+	DA9055_LDO(LDO5, 50, 900, 2750, 6, 2),
+	DA9055_LDO(LDO6, 20, 900, 3300, 7, 0),
+};
+
+/*
+ * Configures regulator to be controlled either through GPIO 1 or 2.
+ * GPIO can control regulator state and/or select the regulator register
+ * set A/B for voltage ramping.
+ */
+static __devinit int da9055_gpio_init(struct da9055_regulator *regulator,
+				      struct regulator_config *config,
+				      struct da9055_pdata *pdata, int id)
+{
+	struct da9055_regulator_info *info = regulator->info;
+	int ret = 0;
+
+	if (pdata->gpio_ren && pdata->gpio_ren[id]) {
+		char name[18];
+		int gpio_mux = pdata->gpio_ren[id];
+
+		config->ena_gpio = pdata->ena_gpio[id];
+		config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
+		config->ena_gpio_invert = 1;
+
+		/*
+		 * GPI pin is muxed with regulator to control the
+		 * regulator state.
+		 */
+		sprintf(name, "DA9055 GPI %d", gpio_mux);
+		ret = devm_gpio_request_one(config->dev, gpio_mux, GPIOF_DIR_IN,
+					    name);
+		if (ret < 0)
+			goto err;
+
+		/*
+		 * Let the regulator know that its state is controlled
+		 * through GPI.
+		 */
+		ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+					DA9055_E_GPI_MASK,
+					pdata->reg_ren[id]
+					<< DA9055_E_GPI_SHIFT);
+		if (ret < 0)
+			goto err;
+	}
+
+	if (pdata->gpio_rsel && pdata->gpio_rsel[id]) {
+		char name[18];
+		int gpio_mux = pdata->gpio_rsel[id];
+
+		regulator->reg_rselect = pdata->reg_rsel[id];
+
+		/*
+		 * GPI pin is muxed with regulator to select the
+		 * regulator register set A/B for voltage ramping.
+		 */
+		sprintf(name, "DA9055 GPI %d", gpio_mux);
+		ret = devm_gpio_request_one(config->dev, gpio_mux, GPIOF_DIR_IN,
+					    name);
+		if (ret < 0)
+			goto err;
+
+		/*
+		 * Let the regulator know that its register set A/B
+		 * will be selected through GPI for voltage ramping.
+		 */
+		ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+					DA9055_V_GPI_MASK,
+					pdata->reg_rsel[id]
+					<< DA9055_V_GPI_SHIFT);
+	}
+
+err:
+	return ret;
+}
+
+static irqreturn_t da9055_ldo5_6_oc_irq(int irq, void *data)
+{
+	struct da9055_regulator *regulator = data;
+
+	regulator_notifier_call_chain(regulator->rdev,
+				      REGULATOR_EVENT_OVER_CURRENT, NULL);
+
+	return IRQ_HANDLED;
+}
+
+static inline struct da9055_regulator_info *find_regulator_info(int id)
+{
+	struct da9055_regulator_info *info;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(da9055_regulator_info); i++) {
+		info = &da9055_regulator_info[i];
+		if (info->reg_desc.id == id)
+			return info;
+	}
+
+	return NULL;
+}
+
+static int __devinit da9055_regulator_probe(struct platform_device *pdev)
+{
+	struct regulator_config config = { };
+	struct da9055_regulator *regulator;
+	struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent);
+	struct da9055_pdata *pdata = da9055->dev->platform_data;
+	int ret, irq;
+
+	if (pdata == NULL || pdata->regulators[pdev->id] == NULL)
+		return -ENODEV;
+
+	regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9055_regulator),
+				 GFP_KERNEL);
+	if (!regulator)
+		return -ENOMEM;
+
+	regulator->info = find_regulator_info(pdev->id);
+	if (regulator->info == NULL) {
+		dev_err(&pdev->dev, "invalid regulator ID specified\n");
+		return -EINVAL;
+	}
+
+	regulator->da9055 = da9055;
+	config.dev = &pdev->dev;
+	config.driver_data = regulator;
+	config.regmap = da9055->regmap;
+
+	if (pdata && pdata->regulators)
+		config.init_data = pdata->regulators[pdev->id];
+
+	ret = da9055_gpio_init(regulator, &config, pdata, pdev->id);
+	if (ret < 0)
+		return ret;
+
+	regulator->rdev = regulator_register(&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;
+	}
+
+	/* Only LDO 5 and 6 has got the over current interrupt */
+	if (pdev->id == DA9055_ID_LDO5 || pdev->id ==  DA9055_ID_LDO6) {
+		irq = platform_get_irq_byname(pdev, "REGULATOR");
+		irq = regmap_irq_get_virq(da9055->irq_data, irq);
+		ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+						da9055_ldo5_6_oc_irq,
+						IRQF_TRIGGER_HIGH |
+						IRQF_ONESHOT |
+						IRQF_PROBE_SHARED,
+						pdev->name, regulator);
+		if (ret != 0) {
+			if (ret != -EBUSY) {
+				dev_err(&pdev->dev,
+				"Failed to request Regulator IRQ %d: %d\n",
+				irq, ret);
+				goto err_regulator;
+			}
+		}
+	}
+
+	platform_set_drvdata(pdev, regulator);
+
+	return 0;
+
+err_regulator:
+	regulator_unregister(regulator->rdev);
+	return ret;
+}
+
+static int __devexit 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 = __devexit_p(da9055_regulator_remove),
+	.driver = {
+		.name = "da9055-regulator",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init da9055_regulator_init(void)
+{
+	return platform_driver_register(&da9055_regulator_driver);
+}
+subsys_initcall(da9055_regulator_init);
+
+static void __exit da9055_regulator_exit(void)
+{
+	platform_driver_unregister(&da9055_regulator_driver);
+}
+module_exit(da9055_regulator_exit);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9055 PMIC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9055-regulator");
diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c
index 359f8d1..219d162 100644
--- a/drivers/regulator/db8500-prcmu.c
+++ b/drivers/regulator/db8500-prcmu.c
@@ -412,7 +412,7 @@ dbx500_regulator_info[DB8500_NUM_REGULATORS] = {
 	},
 };
 
-static __devinit int db8500_regulator_register(struct platform_device *pdev,
+static int db8500_regulator_register(struct platform_device *pdev,
 					struct regulator_init_data *init_data,
 					int id,
 					struct device_node *np)
@@ -474,7 +474,7 @@ static struct of_regulator_match db8500_regulator_matches[] = {
 	{ .name	= "db8500_esram34_ret",   .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM34RET, },
 };
 
-static __devinit int
+static int
 db8500_regulator_of_probe(struct platform_device *pdev,
 			struct device_node *np)
 {
@@ -491,7 +491,7 @@ db8500_regulator_of_probe(struct platform_device *pdev,
 	return 0;
 }
 
-static int __devinit db8500_regulator_probe(struct platform_device *pdev)
+static int db8500_regulator_probe(struct platform_device *pdev)
 {
 	struct regulator_init_data *db8500_init_data =
 					dev_get_platdata(&pdev->dev);
diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c
index f2e5ecd..261f3d2 100644
--- a/drivers/regulator/dbx500-prcmu.c
+++ b/drivers/regulator/dbx500-prcmu.c
@@ -173,7 +173,7 @@ int __attribute__((weak)) dbx500_regulator_testcase(
 	return 0;
 }
 
-int __devinit
+int
 ux500_regulator_debug_init(struct platform_device *pdev,
 	struct dbx500_regulator_info *regulator_info,
 	int num_regulators)
@@ -230,7 +230,7 @@ exit_no_debugfs:
 	return -ENOMEM;
 }
 
-int __devexit ux500_regulator_debug_exit(void)
+int ux500_regulator_debug_exit(void)
 {
 	debugfs_remove_recursive(rdebug.dir);
 	kfree(rdebug.state_after_suspend);
diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c
index 03a1d7c..df9f425 100644
--- a/drivers/regulator/dummy.c
+++ b/drivers/regulator/dummy.c
@@ -37,7 +37,7 @@ static struct regulator_desc dummy_desc = {
 	.ops = &dummy_ops,
 };
 
-static int __devinit dummy_regulator_probe(struct platform_device *pdev)
+static int dummy_regulator_probe(struct platform_device *pdev)
 {
 	struct regulator_config config = { };
 	int ret;
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
index 339f4d7..9165b0c 100644
--- a/drivers/regulator/fan53555.c
+++ b/drivers/regulator/fan53555.c
@@ -230,7 +230,7 @@ static struct regmap_config fan53555_regmap_config = {
 	.val_bits = 8,
 };
 
-static int __devinit fan53555_regulator_probe(struct i2c_client *client,
+static int fan53555_regulator_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
 	struct fan53555_device_info *di;
@@ -293,7 +293,7 @@ static int __devinit fan53555_regulator_probe(struct i2c_client *client,
 
 }
 
-static int __devexit fan53555_regulator_remove(struct i2c_client *client)
+static int fan53555_regulator_remove(struct i2c_client *client)
 {
 	struct fan53555_device_info *di = i2c_get_clientdata(client);
 
@@ -311,7 +311,7 @@ static struct i2c_driver fan53555_regulator_driver = {
 		.name = "fan53555-regulator",
 	},
 	.probe = fan53555_regulator_probe,
-	.remove = __devexit_p(fan53555_regulator_remove),
+	.remove = fan53555_regulator_remove,
 	.id_table = fan53555_id,
 };
 
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index 185468c..48d5b76 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -134,7 +134,7 @@ static struct regulator_ops fixed_voltage_ops = {
 	.list_voltage = fixed_voltage_list_voltage,
 };
 
-static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
+static int reg_fixed_voltage_probe(struct platform_device *pdev)
 {
 	struct fixed_voltage_config *config;
 	struct fixed_voltage_data *drvdata;
@@ -234,7 +234,7 @@ err:
 	return ret;
 }
 
-static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev)
+static int reg_fixed_voltage_remove(struct platform_device *pdev)
 {
 	struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev);
 
@@ -255,7 +255,7 @@ MODULE_DEVICE_TABLE(of, fixed_of_match);
 
 static struct platform_driver regulator_fixed_voltage_driver = {
 	.probe		= reg_fixed_voltage_probe,
-	.remove		= __devexit_p(reg_fixed_voltage_remove),
+	.remove		= reg_fixed_voltage_remove,
 	.driver		= {
 		.name		= "reg-fixed-voltage",
 		.owner		= THIS_MODULE,
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
index 8b5944f..3ee79c8 100644
--- a/drivers/regulator/gpio-regulator.c
+++ b/drivers/regulator/gpio-regulator.c
@@ -28,9 +28,12 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
 #include <linux/regulator/gpio-regulator.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 
 struct gpio_regulator_data {
 	struct regulator_desc desc;
@@ -129,18 +132,108 @@ static struct regulator_ops gpio_regulator_voltage_ops = {
 	.list_voltage = gpio_regulator_list_voltage,
 };
 
+struct gpio_regulator_config *
+of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
+{
+	struct gpio_regulator_config *config;
+	struct property *prop;
+	const char *regtype;
+	int proplen, gpio, i;
+
+	config = devm_kzalloc(dev,
+			sizeof(struct gpio_regulator_config),
+			GFP_KERNEL);
+	if (!config)
+		return ERR_PTR(-ENOMEM);
+
+	config->init_data = of_get_regulator_init_data(dev, np);
+	if (!config->init_data)
+		return ERR_PTR(-EINVAL);
+
+	config->supply_name = config->init_data->constraints.name;
+
+	if (of_property_read_bool(np, "enable-active-high"))
+		config->enable_high = true;
+
+	if (of_property_read_bool(np, "enable-at-boot"))
+		config->enabled_at_boot = true;
+
+	of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
+
+	config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
+
+	/* Fetch GPIOs. */
+	for (i = 0; ; i++)
+		if (of_get_named_gpio(np, "gpios", i) < 0)
+			break;
+	config->nr_gpios = i;
+
+	config->gpios = devm_kzalloc(dev,
+				sizeof(struct gpio) * config->nr_gpios,
+				GFP_KERNEL);
+	if (!config->gpios)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; config->nr_gpios; i++) {
+		gpio = of_get_named_gpio(np, "gpios", i);
+		if (gpio < 0)
+			break;
+		config->gpios[i].gpio = gpio;
+	}
+
+	/* Fetch states. */
+	prop = of_find_property(np, "states", NULL);
+	if (!prop) {
+		dev_err(dev, "No 'states' property found\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	proplen = prop->length / sizeof(int);
+
+	config->states = devm_kzalloc(dev,
+				sizeof(struct gpio_regulator_state)
+				* (proplen / 2),
+				GFP_KERNEL);
+	if (!config->states)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < proplen / 2; i++) {
+		config->states[i].value =
+			be32_to_cpup((int *)prop->value + (i * 2));
+		config->states[i].gpios =
+			be32_to_cpup((int *)prop->value + (i * 2 + 1));
+	}
+	config->nr_states = i;
+
+	of_property_read_string(np, "regulator-type", &regtype);
+
+	if (!strncmp("voltage", regtype, 7))
+		config->type = REGULATOR_VOLTAGE;
+	else if (!strncmp("current", regtype, 7))
+		config->type = REGULATOR_CURRENT;
+
+	return config;
+}
+
 static struct regulator_ops gpio_regulator_current_ops = {
 	.get_current_limit = gpio_regulator_get_value,
 	.set_current_limit = gpio_regulator_set_current_limit,
 };
 
-static int __devinit gpio_regulator_probe(struct platform_device *pdev)
+static int gpio_regulator_probe(struct platform_device *pdev)
 {
 	struct gpio_regulator_config *config = pdev->dev.platform_data;
+	struct device_node *np = pdev->dev.of_node;
 	struct gpio_regulator_data *drvdata;
 	struct regulator_config cfg = { };
 	int ptr, ret, state;
 
+	if (np) {
+		config = of_get_gpio_regulator_config(&pdev->dev, np);
+		if (IS_ERR(config))
+			return PTR_ERR(config);
+	}
+
 	drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data),
 			       GFP_KERNEL);
 	if (drvdata == NULL) {
@@ -215,6 +308,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
 	cfg.dev = &pdev->dev;
 	cfg.init_data = config->init_data;
 	cfg.driver_data = drvdata;
+	cfg.of_node = np;
 
 	if (config->enable_gpio >= 0)
 		cfg.ena_gpio = config->enable_gpio;
@@ -254,7 +348,7 @@ err:
 	return ret;
 }
 
-static int __devexit gpio_regulator_remove(struct platform_device *pdev)
+static int gpio_regulator_remove(struct platform_device *pdev)
 {
 	struct gpio_regulator_data *drvdata = platform_get_drvdata(pdev);
 
@@ -270,12 +364,18 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct of_device_id regulator_gpio_of_match[] __devinitconst = {
+	{ .compatible = "regulator-gpio", },
+	{},
+};
+
 static struct platform_driver gpio_regulator_driver = {
 	.probe		= gpio_regulator_probe,
-	.remove		= __devexit_p(gpio_regulator_remove),
+	.remove		= gpio_regulator_remove,
 	.driver		= {
 		.name		= "gpio-regulator",
 		.owner		= THIS_MODULE,
+		.of_match_table = regulator_gpio_of_match,
 	},
 };
 
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c
index d8ecf49..d1e5bee 100644
--- a/drivers/regulator/isl6271a-regulator.c
+++ b/drivers/regulator/isl6271a-regulator.c
@@ -106,7 +106,7 @@ static const struct regulator_desc isl_rd[] = {
 	},
 };
 
-static int __devinit isl6271a_probe(struct i2c_client *i2c,
+static int isl6271a_probe(struct i2c_client *i2c,
 				     const struct i2c_device_id *id)
 {
 	struct regulator_config config = { };
@@ -151,7 +151,7 @@ error:
 	return err;
 }
 
-static int __devexit isl6271a_remove(struct i2c_client *i2c)
+static int isl6271a_remove(struct i2c_client *i2c)
 {
 	struct isl_pmic *pmic = i2c_get_clientdata(i2c);
 	int i;
@@ -174,7 +174,7 @@ static struct i2c_driver isl6271a_i2c_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = isl6271a_probe,
-	.remove = __devexit_p(isl6271a_remove),
+	.remove = isl6271a_remove,
 	.id_table = isl6271a_id,
 };
 
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index 7c6e3b8..5f68ff1 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -386,7 +386,7 @@ static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val)
 	return ret;
 }
 
-static int __devinit setup_regulators(struct lp3971 *lp3971,
+static int setup_regulators(struct lp3971 *lp3971,
 				      struct lp3971_platform_data *pdata)
 {
 	int i, err;
@@ -429,7 +429,7 @@ err_nomem:
 	return err;
 }
 
-static int __devinit lp3971_i2c_probe(struct i2c_client *i2c,
+static int lp3971_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
 	struct lp3971 *lp3971;
@@ -472,7 +472,7 @@ err_detect:
 	return ret;
 }
 
-static int __devexit lp3971_i2c_remove(struct i2c_client *i2c)
+static int lp3971_i2c_remove(struct i2c_client *i2c)
 {
 	struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
 	int i;
@@ -498,7 +498,7 @@ static struct i2c_driver lp3971_i2c_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe    = lp3971_i2c_probe,
-	.remove   = __devexit_p(lp3971_i2c_remove),
+	.remove   = lp3971_i2c_remove,
 	.id_table = lp3971_i2c_id,
 };
 
diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c
index 3cdc755..69c42c3 100644
--- a/drivers/regulator/lp3972.c
+++ b/drivers/regulator/lp3972.c
@@ -481,7 +481,7 @@ static const struct regulator_desc regulators[] = {
 	},
 };
 
-static int __devinit setup_regulators(struct lp3972 *lp3972,
+static int setup_regulators(struct lp3972 *lp3972,
 	struct lp3972_platform_data *pdata)
 {
 	int i, err;
@@ -523,7 +523,7 @@ err_nomem:
 	return err;
 }
 
-static int __devinit lp3972_i2c_probe(struct i2c_client *i2c,
+static int lp3972_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 {
 	struct lp3972 *lp3972;
@@ -569,7 +569,7 @@ err_detect:
 	return ret;
 }
 
-static int __devexit lp3972_i2c_remove(struct i2c_client *i2c)
+static int lp3972_i2c_remove(struct i2c_client *i2c)
 {
 	struct lp3972 *lp3972 = i2c_get_clientdata(i2c);
 	int i;
@@ -594,7 +594,7 @@ static struct i2c_driver lp3972_i2c_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe    = lp3972_i2c_probe,
-	.remove   = __devexit_p(lp3972_i2c_remove),
+	.remove   = lp3972_i2c_remove,
 	.id_table = lp3972_i2c_id,
 };
 
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index 708f4b6..9289ead 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -893,7 +893,7 @@ err_dev:
 	return ret;
 }
 
-static int __devexit lp872x_remove(struct i2c_client *cl)
+static int lp872x_remove(struct i2c_client *cl)
 {
 	struct lp872x *lp = i2c_get_clientdata(cl);
 
@@ -914,7 +914,7 @@ static struct i2c_driver lp872x_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = lp872x_probe,
-	.remove = __devexit_p(lp872x_remove),
+	.remove = lp872x_remove,
 	.id_table = lp872x_ids,
 };
 
diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c
index ba3e0aa..6cc02c3 100644
--- a/drivers/regulator/lp8788-buck.c
+++ b/drivers/regulator/lp8788-buck.c
@@ -504,7 +504,7 @@ set_default_dvs_mode:
 				  default_dvs_mode[id]);
 }
 
-static __devinit int lp8788_buck_probe(struct platform_device *pdev)
+static int lp8788_buck_probe(struct platform_device *pdev)
 {
 	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
 	int id = pdev->id;
@@ -542,7 +542,7 @@ static __devinit int lp8788_buck_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit lp8788_buck_remove(struct platform_device *pdev)
+static int lp8788_buck_remove(struct platform_device *pdev)
 {
 	struct lp8788_buck *buck = platform_get_drvdata(pdev);
 
@@ -554,7 +554,7 @@ static int __devexit lp8788_buck_remove(struct platform_device *pdev)
 
 static struct platform_driver lp8788_buck_driver = {
 	.probe = lp8788_buck_probe,
-	.remove = __devexit_p(lp8788_buck_remove),
+	.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 6796eeb..9c1c253 100644
--- a/drivers/regulator/lp8788-ldo.c
+++ b/drivers/regulator/lp8788-ldo.c
@@ -126,7 +126,7 @@ struct lp8788_ldo {
 };
 
 /* DLDO 1, 2, 3, 9 voltage table */
-const int lp8788_dldo1239_vtbl[] = {
+static const int lp8788_dldo1239_vtbl[] = {
 	1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
 	2600000, 2700000, 2800000, 2900000, 3000000, 2850000, 2850000, 2850000,
 	2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
@@ -712,7 +712,7 @@ set_default_ldo_enable_mode:
 				val[enable_id]);
 }
 
-static __devinit int lp8788_dldo_probe(struct platform_device *pdev)
+static int lp8788_dldo_probe(struct platform_device *pdev)
 {
 	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
 	int id = pdev->id;
@@ -749,7 +749,7 @@ static __devinit int lp8788_dldo_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
+static int lp8788_dldo_remove(struct platform_device *pdev)
 {
 	struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -761,14 +761,14 @@ static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
 
 static struct platform_driver lp8788_dldo_driver = {
 	.probe = lp8788_dldo_probe,
-	.remove = __devexit_p(lp8788_dldo_remove),
+	.remove = lp8788_dldo_remove,
 	.driver = {
 		.name = LP8788_DEV_DLDO,
 		.owner = THIS_MODULE,
 	},
 };
 
-static __devinit int lp8788_aldo_probe(struct platform_device *pdev)
+static int lp8788_aldo_probe(struct platform_device *pdev)
 {
 	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
 	int id = pdev->id;
@@ -805,7 +805,7 @@ static __devinit int lp8788_aldo_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
+static int lp8788_aldo_remove(struct platform_device *pdev)
 {
 	struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -817,7 +817,7 @@ static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
 
 static struct platform_driver lp8788_aldo_driver = {
 	.probe = lp8788_aldo_probe,
-	.remove = __devexit_p(lp8788_aldo_remove),
+	.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 f67af3c..3a035ec 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -125,7 +125,7 @@ static struct regulator_desc max1586_reg[] = {
 	},
 };
 
-static int __devinit max1586_pmic_probe(struct i2c_client *client,
+static int max1586_pmic_probe(struct i2c_client *client,
 					const struct i2c_device_id *i2c_id)
 {
 	struct regulator_dev **rdev;
@@ -188,7 +188,7 @@ err:
 	return ret;
 }
 
-static int __devexit max1586_pmic_remove(struct i2c_client *client)
+static int max1586_pmic_remove(struct i2c_client *client)
 {
 	struct max1586_data *max1586 = i2c_get_clientdata(client);
 	int i;
@@ -207,7 +207,7 @@ MODULE_DEVICE_TABLE(i2c, max1586_id);
 
 static struct i2c_driver max1586_pmic_driver = {
 	.probe = max1586_pmic_probe,
-	.remove = __devexit_p(max1586_pmic_remove),
+	.remove = max1586_pmic_remove,
 	.driver		= {
 		.name	= "max1586",
 		.owner	= THIS_MODULE,
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c
index 2a67d08..b85040c 100644
--- a/drivers/regulator/max77686.c
+++ b/drivers/regulator/max77686.c
@@ -67,8 +67,94 @@ enum max77686_ramp_rate {
 
 struct max77686_data {
 	struct regulator_dev *rdev[MAX77686_REGULATORS];
+	unsigned int opmode[MAX77686_REGULATORS];
 };
 
+/* Some BUCKS supports Normal[ON/OFF] mode during suspend */
+static int max77686_buck_set_suspend_disable(struct regulator_dev *rdev)
+{
+	unsigned int val;
+	struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+
+	if (rdev->desc->id == MAX77686_BUCK1)
+		val = 0x1;
+	else
+		val = 0x1 << MAX77686_OPMODE_BUCK234_SHIFT;
+
+	max77686->opmode[rdev->desc->id] = val;
+	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+				  rdev->desc->enable_mask,
+				  val);
+}
+
+/* Some LDOs supports [LPM/Normal]ON mode during suspend state */
+static int max77686_set_suspend_mode(struct regulator_dev *rdev,
+				     unsigned int mode)
+{
+	struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+	unsigned int val;
+
+	/* BUCK[5-9] doesn't support this feature */
+	if (rdev->desc->id >= MAX77686_BUCK5)
+		return 0;
+
+	switch (mode) {
+	case REGULATOR_MODE_IDLE:			/* ON in LP Mode */
+		val = 0x2 << MAX77686_OPMODE_SHIFT;
+		break;
+	case REGULATOR_MODE_NORMAL:			/* ON in Normal Mode */
+		val = 0x3 << MAX77686_OPMODE_SHIFT;
+		break;
+	default:
+		pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
+			rdev->desc->name, mode);
+		return -EINVAL;
+	}
+
+	max77686->opmode[rdev->desc->id] = val;
+	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+				  rdev->desc->enable_mask,
+				  val);
+}
+
+/* Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state */
+static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
+				     unsigned int mode)
+{
+	unsigned int val;
+	struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+
+	switch (mode) {
+	case REGULATOR_MODE_STANDBY:			/* switch off */
+		val = 0x1 << MAX77686_OPMODE_SHIFT;
+		break;
+	case REGULATOR_MODE_IDLE:			/* ON in LP Mode */
+		val = 0x2 << MAX77686_OPMODE_SHIFT;
+		break;
+	case REGULATOR_MODE_NORMAL:			/* ON in Normal Mode */
+		val = 0x3 << MAX77686_OPMODE_SHIFT;
+		break;
+	default:
+		pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
+			rdev->desc->name, mode);
+		return -EINVAL;
+	}
+
+	max77686->opmode[rdev->desc->id] = val;
+	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+				  rdev->desc->enable_mask,
+				  val);
+}
+
+static int max77686_enable(struct regulator_dev *rdev)
+{
+	struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+
+	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+				  rdev->desc->enable_mask,
+				  max77686->opmode[rdev->desc->id]);
+}
+
 static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
 {
 	unsigned int ramp_value = RAMP_RATE_NO_CTRL;
@@ -98,23 +184,49 @@ static struct regulator_ops max77686_ops = {
 	.list_voltage		= regulator_list_voltage_linear,
 	.map_voltage		= regulator_map_voltage_linear,
 	.is_enabled		= regulator_is_enabled_regmap,
-	.enable			= regulator_enable_regmap,
+	.enable			= max77686_enable,
+	.disable		= regulator_disable_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+	.set_suspend_mode	= max77686_set_suspend_mode,
+};
+
+static struct regulator_ops max77686_ldo_ops = {
+	.list_voltage		= regulator_list_voltage_linear,
+	.map_voltage		= regulator_map_voltage_linear,
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= max77686_enable,
 	.disable		= regulator_disable_regmap,
 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
 	.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+	.set_suspend_mode	= max77686_ldo_set_suspend_mode,
+};
+
+static struct regulator_ops max77686_buck1_ops = {
+	.list_voltage		= regulator_list_voltage_linear,
+	.map_voltage		= regulator_map_voltage_linear,
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= max77686_enable,
+	.disable		= regulator_disable_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+	.set_suspend_disable	= max77686_buck_set_suspend_disable,
 };
 
 static struct regulator_ops max77686_buck_dvs_ops = {
 	.list_voltage		= regulator_list_voltage_linear,
 	.map_voltage		= regulator_map_voltage_linear,
 	.is_enabled		= regulator_is_enabled_regmap,
-	.enable			= regulator_enable_regmap,
+	.enable			= max77686_enable,
 	.disable		= regulator_disable_regmap,
 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
 	.set_voltage_time_sel	= regulator_set_voltage_time_sel,
 	.set_ramp_delay		= max77686_set_ramp_delay,
+	.set_suspend_disable	= max77686_buck_set_suspend_disable,
 };
 
 #define regulator_desc_ldo(num)		{				\
@@ -133,9 +245,41 @@ static struct regulator_ops max77686_buck_dvs_ops = {
 	.enable_mask	= MAX77686_OPMODE_MASK				\
 			<< MAX77686_OPMODE_SHIFT,			\
 }
+#define regulator_desc_lpm_ldo(num)	{				\
+	.name		= "LDO"#num,					\
+	.id		= MAX77686_LDO##num,				\
+	.ops		= &max77686_ldo_ops,				\
+	.type		= REGULATOR_VOLTAGE,				\
+	.owner		= THIS_MODULE,					\
+	.min_uV		= MAX77686_LDO_MINUV,				\
+	.uV_step	= MAX77686_LDO_UVSTEP,				\
+	.ramp_delay	= MAX77686_RAMP_DELAY,				\
+	.n_voltages	= MAX77686_VSEL_MASK + 1,			\
+	.vsel_reg	= MAX77686_REG_LDO1CTRL1 + num - 1,		\
+	.vsel_mask	= MAX77686_VSEL_MASK,				\
+	.enable_reg	= MAX77686_REG_LDO1CTRL1 + num - 1,		\
+	.enable_mask	= MAX77686_OPMODE_MASK				\
+			<< MAX77686_OPMODE_SHIFT,			\
+}
 #define regulator_desc_ldo_low(num)		{			\
 	.name		= "LDO"#num,					\
 	.id		= MAX77686_LDO##num,				\
+	.ops		= &max77686_ldo_ops,				\
+	.type		= REGULATOR_VOLTAGE,				\
+	.owner		= THIS_MODULE,					\
+	.min_uV		= MAX77686_LDO_LOW_MINUV,			\
+	.uV_step	= MAX77686_LDO_LOW_UVSTEP,			\
+	.ramp_delay	= MAX77686_RAMP_DELAY,				\
+	.n_voltages	= MAX77686_VSEL_MASK + 1,			\
+	.vsel_reg	= MAX77686_REG_LDO1CTRL1 + num - 1,		\
+	.vsel_mask	= MAX77686_VSEL_MASK,				\
+	.enable_reg	= MAX77686_REG_LDO1CTRL1 + num - 1,		\
+	.enable_mask	= MAX77686_OPMODE_MASK				\
+			<< MAX77686_OPMODE_SHIFT,			\
+}
+#define regulator_desc_ldo1_low(num)		{			\
+	.name		= "LDO"#num,					\
+	.id		= MAX77686_LDO##num,				\
 	.ops		= &max77686_ops,				\
 	.type		= REGULATOR_VOLTAGE,				\
 	.owner		= THIS_MODULE,					\
@@ -167,7 +311,7 @@ static struct regulator_ops max77686_buck_dvs_ops = {
 #define regulator_desc_buck1(num)		{			\
 	.name		= "BUCK"#num,					\
 	.id		= MAX77686_BUCK##num,				\
-	.ops		= &max77686_ops,				\
+	.ops		= &max77686_buck1_ops,				\
 	.type		= REGULATOR_VOLTAGE,				\
 	.owner		= THIS_MODULE,					\
 	.min_uV		= MAX77686_BUCK_MINUV,				\
@@ -197,7 +341,7 @@ static struct regulator_ops max77686_buck_dvs_ops = {
 }
 
 static struct regulator_desc regulators[] = {
-	regulator_desc_ldo_low(1),
+	regulator_desc_ldo1_low(1),
 	regulator_desc_ldo_low(2),
 	regulator_desc_ldo(3),
 	regulator_desc_ldo(4),
@@ -206,13 +350,13 @@ static struct regulator_desc regulators[] = {
 	regulator_desc_ldo_low(7),
 	regulator_desc_ldo_low(8),
 	regulator_desc_ldo(9),
-	regulator_desc_ldo(10),
-	regulator_desc_ldo(11),
-	regulator_desc_ldo(12),
+	regulator_desc_lpm_ldo(10),
+	regulator_desc_lpm_ldo(11),
+	regulator_desc_lpm_ldo(12),
 	regulator_desc_ldo(13),
-	regulator_desc_ldo(14),
+	regulator_desc_lpm_ldo(14),
 	regulator_desc_ldo_low(15),
-	regulator_desc_ldo(16),
+	regulator_desc_lpm_ldo(16),
 	regulator_desc_ldo(17),
 	regulator_desc_ldo(18),
 	regulator_desc_ldo(19),
@@ -280,7 +424,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
 }
 #endif /* CONFIG_OF */
 
-static __devinit int max77686_pmic_probe(struct platform_device *pdev)
+static int max77686_pmic_probe(struct platform_device *pdev)
 {
 	struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 	struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -314,12 +458,14 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev)
 
 	config.dev = &pdev->dev;
 	config.regmap = iodev->regmap;
+	config.driver_data = max77686;
 	platform_set_drvdata(pdev, max77686);
 
 	for (i = 0; i < MAX77686_REGULATORS; i++) {
 		config.init_data = pdata->regulators[i].initdata;
 		config.of_node = pdata->regulators[i].of_node;
 
+		max77686->opmode[i] = regulators[i].enable_mask;
 		max77686->rdev[i] = regulator_register(&regulators[i], &config);
 		if (IS_ERR(max77686->rdev[i])) {
 			ret = PTR_ERR(max77686->rdev[i]);
@@ -337,7 +483,7 @@ err:
 	return ret;
 }
 
-static int __devexit max77686_pmic_remove(struct platform_device *pdev)
+static int max77686_pmic_remove(struct platform_device *pdev)
 {
 	struct max77686_data *max77686 = platform_get_drvdata(pdev);
 	int i;
@@ -360,7 +506,7 @@ static struct platform_driver max77686_pmic_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = max77686_pmic_probe,
-	.remove = __devexit_p(max77686_pmic_remove),
+	.remove = max77686_pmic_remove,
 	.id_table = max77686_pmic_id,
 };
 
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index 9d540cd..3ca1438 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -176,7 +176,7 @@ static struct regmap_config max8649_regmap_config = {
 	.val_bits = 8,
 };
 
-static int __devinit max8649_regulator_probe(struct i2c_client *client,
+static int max8649_regulator_probe(struct i2c_client *client,
 					     const struct i2c_device_id *id)
 {
 	struct max8649_platform_data *pdata = client->dev.platform_data;
@@ -271,7 +271,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int __devexit max8649_regulator_remove(struct i2c_client *client)
+static int max8649_regulator_remove(struct i2c_client *client)
 {
 	struct max8649_regulator_info *info = i2c_get_clientdata(client);
 
@@ -291,7 +291,7 @@ MODULE_DEVICE_TABLE(i2c, max8649_id);
 
 static struct i2c_driver max8649_driver = {
 	.probe		= max8649_regulator_probe,
-	.remove		= __devexit_p(max8649_regulator_remove),
+	.remove		= max8649_regulator_remove,
 	.driver		= {
 		.name	= "max8649",
 	},
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
index 8d53174..4d7c635 100644
--- a/drivers/regulator/max8660.c
+++ b/drivers/regulator/max8660.c
@@ -305,7 +305,7 @@ static const struct regulator_desc max8660_reg[] = {
 	},
 };
 
-static int __devinit max8660_probe(struct i2c_client *client,
+static int max8660_probe(struct i2c_client *client,
 				   const struct i2c_device_id *i2c_id)
 {
 	struct regulator_dev **rdev;
@@ -420,7 +420,7 @@ err_out:
 	return ret;
 }
 
-static int __devexit max8660_remove(struct i2c_client *client)
+static int max8660_remove(struct i2c_client *client)
 {
 	struct max8660 *max8660 = i2c_get_clientdata(client);
 	int i;
@@ -440,7 +440,7 @@ MODULE_DEVICE_TABLE(i2c, max8660_id);
 
 static struct i2c_driver max8660_driver = {
 	.probe = max8660_probe,
-	.remove = __devexit_p(max8660_remove),
+	.remove = max8660_remove,
 	.driver		= {
 		.name	= "max8660",
 		.owner	= THIS_MODULE,
diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c
index af76075..d1a7751 100644
--- a/drivers/regulator/max8907-regulator.c
+++ b/drivers/regulator/max8907-regulator.c
@@ -275,7 +275,7 @@ static inline struct device_node *match_of_node(int index)
 }
 #endif
 
-static __devinit int max8907_regulator_probe(struct platform_device *pdev)
+static int max8907_regulator_probe(struct platform_device *pdev)
 {
 	struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
 	struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev);
@@ -368,7 +368,7 @@ err_unregister_regulator:
 	return ret;
 }
 
-static __devexit int max8907_regulator_remove(struct platform_device *pdev)
+static int max8907_regulator_remove(struct platform_device *pdev)
 {
 	struct max8907_regulator *pmic = platform_get_drvdata(pdev);
 	int i;
@@ -385,7 +385,7 @@ static struct platform_driver max8907_regulator_driver = {
 		   .owner = THIS_MODULE,
 		   },
 	.probe = max8907_regulator_probe,
-	.remove = __devexit_p(max8907_regulator_remove),
+	.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 9bb0be3..446a854 100644
--- a/drivers/regulator/max8925-regulator.c
+++ b/drivers/regulator/max8925-regulator.c
@@ -17,6 +17,8 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/max8925.h>
+#include <linux/of.h>
+#include <linux/regulator/of_regulator.h>
 
 #define SD1_DVM_VMIN		850000
 #define SD1_DVM_VMAX		1000000
@@ -187,6 +189,34 @@ static struct regulator_ops max8925_regulator_ldo_ops = {
 	.enable_reg	= MAX8925_LDOCTL##_id,			\
 }
 
+#ifdef CONFIG_OF
+static struct of_regulator_match max8925_regulator_matches[] = {
+	{ .name	= "SDV1",},
+	{ .name = "SDV2",},
+	{ .name = "SDV3",},
+	{ .name = "LDO1",},
+	{ .name = "LDO2",},
+	{ .name = "LDO3",},
+	{ .name = "LDO4",},
+	{ .name = "LDO5",},
+	{ .name = "LDO6",},
+	{ .name = "LDO7",},
+	{ .name = "LDO8",},
+	{ .name = "LDO9",},
+	{ .name = "LDO10",},
+	{ .name = "LDO11",},
+	{ .name = "LDO12",},
+	{ .name = "LDO13",},
+	{ .name = "LDO14",},
+	{ .name = "LDO15",},
+	{ .name = "LDO16",},
+	{ .name = "LDO17",},
+	{ .name = "LDO18",},
+	{ .name = "LDO19",},
+	{ .name = "LDO20",},
+};
+#endif
+
 static struct max8925_regulator_info max8925_regulator_info[] = {
 	MAX8925_SDV(1, 637.5, 1425, 12.5),
 	MAX8925_SDV(2,   650, 2225,   25),
@@ -214,7 +244,37 @@ static struct max8925_regulator_info max8925_regulator_info[] = {
 	MAX8925_LDO(20, 750, 3900, 50),
 };
 
-static int __devinit max8925_regulator_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static int max8925_regulator_dt_init(struct platform_device *pdev,
+				    struct max8925_regulator_info *info,
+				    struct regulator_config *config,
+				    int ridx)
+{
+	struct device_node *nproot, *np;
+	int rcount;
+	nproot = pdev->dev.parent->of_node;
+	if (!nproot)
+		return -ENODEV;
+	np = of_find_node_by_name(nproot, "regulators");
+	if (!np) {
+		dev_err(&pdev->dev, "failed to find regulators node\n");
+		return -ENODEV;
+	}
+
+	rcount = of_regulator_match(&pdev->dev, np,
+				&max8925_regulator_matches[ridx], 1);
+	if (rcount < 0)
+		return -ENODEV;
+	config->init_data =	max8925_regulator_matches[ridx].init_data;
+	config->of_node = max8925_regulator_matches[ridx].of_node;
+
+	return 0;
+}
+#else
+#define max8925_regulator_dt_init(w, x, y, z)	(-1)
+#endif
+
+static int max8925_regulator_probe(struct platform_device *pdev)
 {
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct regulator_init_data *pdata = pdev->dev.platform_data;
@@ -222,7 +282,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
 	struct max8925_regulator_info *ri;
 	struct resource *res;
 	struct regulator_dev *rdev;
-	int i;
+	int i, regulator_idx;
 
 	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
 	if (!res) {
@@ -231,9 +291,12 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
 	}
 	for (i = 0; i < ARRAY_SIZE(max8925_regulator_info); i++) {
 		ri = &max8925_regulator_info[i];
-		if (ri->vol_reg == res->start)
+		if (ri->vol_reg == res->start) {
+			regulator_idx = i;
 			break;
+		}
 	}
+
 	if (i == ARRAY_SIZE(max8925_regulator_info)) {
 		dev_err(&pdev->dev, "Failed to find regulator %llu\n",
 			(unsigned long long)res->start);
@@ -243,9 +306,12 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
 	ri->chip = chip;
 
 	config.dev = &pdev->dev;
-	config.init_data = pdata;
 	config.driver_data = ri;
 
+	if (max8925_regulator_dt_init(pdev, ri, &config, regulator_idx))
+		if (pdata)
+			config.init_data = pdata;
+
 	rdev = regulator_register(&ri->desc, &config);
 	if (IS_ERR(rdev)) {
 		dev_err(&pdev->dev, "failed to register regulator %s\n",
@@ -257,7 +323,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit max8925_regulator_remove(struct platform_device *pdev)
+static int max8925_regulator_remove(struct platform_device *pdev)
 {
 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -273,7 +339,7 @@ static struct platform_driver max8925_regulator_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= max8925_regulator_probe,
-	.remove		= __devexit_p(max8925_regulator_remove),
+	.remove		= max8925_regulator_remove,
 };
 
 static int __init max8925_regulator_init(void)
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
index 355ca7b..fc7935a 100644
--- a/drivers/regulator/max8952.c
+++ b/drivers/regulator/max8952.c
@@ -126,7 +126,7 @@ static const struct regulator_desc regulator = {
 	.owner		= THIS_MODULE,
 };
 
-static int __devinit max8952_pmic_probe(struct i2c_client *client,
+static int max8952_pmic_probe(struct i2c_client *client,
 		const struct i2c_device_id *i2c_id)
 {
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@@ -247,7 +247,7 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int __devexit max8952_pmic_remove(struct i2c_client *client)
+static int max8952_pmic_remove(struct i2c_client *client)
 {
 	struct max8952_data *max8952 = i2c_get_clientdata(client);
 	struct max8952_platform_data *pdata = max8952->pdata;
@@ -268,7 +268,7 @@ MODULE_DEVICE_TABLE(i2c, max8952_ids);
 
 static struct i2c_driver max8952_pmic_driver = {
 	.probe		= max8952_pmic_probe,
-	.remove		= __devexit_p(max8952_pmic_remove),
+	.remove		= max8952_pmic_remove,
 	.driver		= {
 		.name	= "max8952",
 	},
diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c
new file mode 100644
index 0000000..3ee2638
--- /dev/null
+++ b/drivers/regulator/max8973-regulator.c
@@ -0,0 +1,505 @@
+/*
+ * max8973-regulator.c -- Maxim max8973
+ *
+ * Regulator driver for MAXIM 8973 DC-DC step-down switching regulator.
+ *
+ * Copyright (c) 2012, 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/max8973-regulator.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+
+/* Register definitions */
+#define MAX8973_VOUT					0x0
+#define MAX8973_VOUT_DVS				0x1
+#define MAX8973_CONTROL1				0x2
+#define MAX8973_CONTROL2				0x3
+#define MAX8973_CHIPID1					0x4
+#define MAX8973_CHIPID2					0x5
+
+#define MAX8973_MAX_VOUT_REG				2
+
+/* MAX8973_VOUT */
+#define MAX8973_VOUT_ENABLE				BIT(7)
+#define MAX8973_VOUT_MASK				0x7F
+
+/* MAX8973_VOUT_DVS */
+#define MAX8973_DVS_VOUT_MASK				0x7F
+
+/* MAX8973_CONTROL1 */
+#define MAX8973_SNS_ENABLE				BIT(7)
+#define MAX8973_FPWM_EN_M				BIT(6)
+#define MAX8973_NFSR_ENABLE				BIT(5)
+#define MAX8973_AD_ENABLE				BIT(4)
+#define MAX8973_BIAS_ENABLE				BIT(3)
+#define MAX8973_FREQSHIFT_9PER				BIT(2)
+
+#define MAX8973_RAMP_12mV_PER_US			0x0
+#define MAX8973_RAMP_25mV_PER_US			0x1
+#define MAX8973_RAMP_50mV_PER_US			0x2
+#define MAX8973_RAMP_200mV_PER_US			0x3
+
+/* MAX8973_CONTROL2 */
+#define MAX8973_WDTMR_ENABLE				BIT(6)
+#define MAX8973_DISCH_ENBABLE				BIT(5)
+#define MAX8973_FT_ENABLE				BIT(4)
+
+#define MAX8973_CKKADV_TRIP_DISABLE			0xC
+#define MAX8973_CKKADV_TRIP_75mV_PER_US			0x0
+#define MAX8973_CKKADV_TRIP_150mV_PER_US		0x4
+#define MAX8973_CKKADV_TRIP_75mV_PER_US_HIST_DIS	0x8
+#define MAX8973_CONTROL_CLKADV_TRIP_MASK		0x00030000
+
+#define MAX8973_INDUCTOR_MIN_30_PER			0x0
+#define MAX8973_INDUCTOR_NOMINAL			0x1
+#define MAX8973_INDUCTOR_PLUS_30_PER			0x2
+#define MAX8973_INDUCTOR_PLUS_60_PER			0x3
+#define MAX8973_CONTROL_INDUCTOR_VALUE_MASK		0x00300000
+
+#define MAX8973_MIN_VOLATGE				606250
+#define MAX8973_MAX_VOLATGE				1400000
+#define MAX8973_VOLATGE_STEP				6250
+#define MAX8973_BUCK_N_VOLTAGE				0x80
+
+/* Maxim 8973 chip information */
+struct max8973_chip {
+	struct device *dev;
+	struct regulator_desc desc;
+	struct regulator_dev *rdev;
+	struct regmap *regmap;
+	bool enable_external_control;
+	int dvs_gpio;
+	int lru_index[MAX8973_MAX_VOUT_REG];
+	int curr_vout_val[MAX8973_MAX_VOUT_REG];
+	int curr_vout_reg;
+	int curr_gpio_val;
+	bool valid_dvs_gpio;
+};
+
+/*
+ * find_voltage_set_register: Find new voltage configuration register (VOUT).
+ * The finding of the new VOUT register will be based on the LRU mechanism.
+ * Each VOUT register will have different voltage configured . This
+ * Function will look if any of the VOUT register have requested voltage set
+ * or not.
+ *     - If it is already there then it will make that register as most
+ *       recently used and return as found so that caller need not to set
+ *       the VOUT register but need to set the proper gpios to select this
+ *       VOUT register.
+ *     - If requested voltage is not found then it will use the least
+ *       recently mechanism to get new VOUT register for new configuration
+ *       and will return not_found so that caller need to set new VOUT
+ *       register and then gpios (both).
+ */
+static bool find_voltage_set_register(struct max8973_chip *tps,
+		int req_vsel, int *vout_reg, int *gpio_val)
+{
+	int i;
+	bool found = false;
+	int new_vout_reg = tps->lru_index[MAX8973_MAX_VOUT_REG - 1];
+	int found_index = MAX8973_MAX_VOUT_REG - 1;
+
+	for (i = 0; i < MAX8973_MAX_VOUT_REG; ++i) {
+		if (tps->curr_vout_val[tps->lru_index[i]] == req_vsel) {
+			new_vout_reg = tps->lru_index[i];
+			found_index = i;
+			found = true;
+			goto update_lru_index;
+		}
+	}
+
+update_lru_index:
+	for (i = found_index; i > 0; i--)
+		tps->lru_index[i] = tps->lru_index[i - 1];
+
+	tps->lru_index[0] = new_vout_reg;
+	*gpio_val = new_vout_reg;
+	*vout_reg = MAX8973_VOUT + new_vout_reg;
+	return found;
+}
+
+static int max8973_dcdc_get_voltage_sel(struct regulator_dev *rdev)
+{
+	struct max8973_chip *max = rdev_get_drvdata(rdev);
+	unsigned int data;
+	int ret;
+
+	ret = regmap_read(max->regmap, max->curr_vout_reg, &data);
+	if (ret < 0) {
+		dev_err(max->dev, "register %d read failed, err = %d\n",
+			max->curr_vout_reg, ret);
+		return ret;
+	}
+	return data & MAX8973_VOUT_MASK;
+}
+
+static int max8973_dcdc_set_voltage_sel(struct regulator_dev *rdev,
+	     unsigned vsel)
+{
+	struct max8973_chip *max = rdev_get_drvdata(rdev);
+	int ret;
+	bool found = false;
+	int vout_reg = max->curr_vout_reg;
+	int gpio_val = max->curr_gpio_val;
+
+	/*
+	 * If gpios are available to select the VOUT register then least
+	 * recently used register for new configuration.
+	 */
+	if (max->valid_dvs_gpio)
+		found = find_voltage_set_register(max, vsel,
+					&vout_reg, &gpio_val);
+
+	if (!found) {
+		ret = regmap_update_bits(max->regmap, vout_reg,
+					MAX8973_VOUT_MASK, vsel);
+		if (ret < 0) {
+			dev_err(max->dev, "register %d update failed, err %d\n",
+				 vout_reg, ret);
+			return ret;
+		}
+		max->curr_vout_reg = vout_reg;
+		max->curr_vout_val[gpio_val] = vsel;
+	}
+
+	/* Select proper VOUT register vio gpios */
+	if (max->valid_dvs_gpio) {
+		gpio_set_value_cansleep(max->dvs_gpio, gpio_val & 0x1);
+		max->curr_gpio_val = gpio_val;
+	}
+	return 0;
+}
+
+static int max8973_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+	struct max8973_chip *max = rdev_get_drvdata(rdev);
+	int ret;
+	int pwm;
+
+	/* Enable force PWM mode in FAST mode only. */
+	switch (mode) {
+	case REGULATOR_MODE_FAST:
+		pwm = MAX8973_FPWM_EN_M;
+		break;
+
+	case REGULATOR_MODE_NORMAL:
+		pwm = 0;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	ret = regmap_update_bits(max->regmap, MAX8973_CONTROL1,
+				MAX8973_FPWM_EN_M, pwm);
+	if (ret < 0)
+		dev_err(max->dev, "register %d update failed, err %d\n",
+				MAX8973_CONTROL1, ret);
+	return ret;
+}
+
+static unsigned int max8973_dcdc_get_mode(struct regulator_dev *rdev)
+{
+	struct max8973_chip *max = rdev_get_drvdata(rdev);
+	unsigned int data;
+	int ret;
+
+	ret = regmap_read(max->regmap, MAX8973_CONTROL1, &data);
+	if (ret < 0) {
+		dev_err(max->dev, "register %d read failed, err %d\n",
+				MAX8973_CONTROL1, ret);
+		return ret;
+	}
+	return (data & MAX8973_FPWM_EN_M) ?
+		REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
+}
+
+static struct regulator_ops max8973_dcdc_ops = {
+	.get_voltage_sel	= max8973_dcdc_get_voltage_sel,
+	.set_voltage_sel	= max8973_dcdc_set_voltage_sel,
+	.list_voltage		= regulator_list_voltage_linear,
+	.set_mode		= max8973_dcdc_set_mode,
+	.get_mode		= max8973_dcdc_get_mode,
+};
+
+static int __devinit max8973_init_dcdc(struct max8973_chip *max,
+		struct max8973_regulator_platform_data *pdata)
+{
+	int ret;
+	uint8_t	control1 = 0;
+	uint8_t control2 = 0;
+
+	if (pdata->control_flags & MAX8973_CONTROL_REMOTE_SENSE_ENABLE)
+		control1 |= MAX8973_SNS_ENABLE;
+
+	if (!(pdata->control_flags & MAX8973_CONTROL_FALLING_SLEW_RATE_ENABLE))
+		control1 |= MAX8973_NFSR_ENABLE;
+
+	if (pdata->control_flags & MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE)
+		control1 |= MAX8973_AD_ENABLE;
+
+	if (pdata->control_flags & MAX8973_CONTROL_BIAS_ENABLE)
+		control1 |= MAX8973_BIAS_ENABLE;
+
+	if (pdata->control_flags & MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE)
+		control1 |= MAX8973_FREQSHIFT_9PER;
+
+	/* Set ramp delay */
+	if (pdata->reg_init_data &&
+			pdata->reg_init_data->constraints.ramp_delay) {
+		if (pdata->reg_init_data->constraints.ramp_delay < 25000)
+			control1 = MAX8973_RAMP_12mV_PER_US;
+		else if (pdata->reg_init_data->constraints.ramp_delay < 50000)
+			control1 = MAX8973_RAMP_25mV_PER_US;
+		else if (pdata->reg_init_data->constraints.ramp_delay < 200000)
+			control1 = MAX8973_RAMP_50mV_PER_US;
+		else
+			control1 = MAX8973_RAMP_200mV_PER_US;
+	} else {
+		control1 = MAX8973_RAMP_12mV_PER_US;
+		max->desc.ramp_delay = 12500;
+	}
+
+	if (!(pdata->control_flags & MAX8973_CONTROL_PULL_DOWN_ENABLE))
+		control2 |= MAX8973_DISCH_ENBABLE;
+
+	/*  Clock advance trip configuration */
+	switch (pdata->control_flags & MAX8973_CONTROL_CLKADV_TRIP_MASK) {
+	case MAX8973_CONTROL_CLKADV_TRIP_DISABLED:
+		control2 |= MAX8973_CKKADV_TRIP_DISABLE;
+		break;
+
+	case MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US:
+		control2 |= MAX8973_CKKADV_TRIP_75mV_PER_US;
+		break;
+
+	case MAX8973_CONTROL_CLKADV_TRIP_150mV_PER_US:
+		control2 |= MAX8973_CKKADV_TRIP_150mV_PER_US;
+		break;
+
+	case MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US_HIST_DIS:
+		control2 |= MAX8973_CKKADV_TRIP_75mV_PER_US_HIST_DIS;
+		break;
+	}
+
+	/* Configure inductor value */
+	switch (pdata->control_flags & MAX8973_CONTROL_INDUCTOR_VALUE_MASK) {
+	case MAX8973_CONTROL_INDUCTOR_VALUE_NOMINAL:
+		control2 |= MAX8973_INDUCTOR_NOMINAL;
+		break;
+
+	case MAX8973_CONTROL_INDUCTOR_VALUE_MINUS_30_PER:
+		control2 |= MAX8973_INDUCTOR_MIN_30_PER;
+		break;
+
+	case MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_30_PER:
+		control2 |= MAX8973_INDUCTOR_PLUS_30_PER;
+		break;
+
+	case MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_60_PER:
+		control2 |= MAX8973_INDUCTOR_PLUS_60_PER;
+		break;
+	}
+
+	ret = regmap_write(max->regmap, MAX8973_CONTROL1, control1);
+	if (ret < 0) {
+		dev_err(max->dev, "register %d write failed, err = %d",
+				MAX8973_CONTROL1, ret);
+		return ret;
+	}
+
+	ret = regmap_write(max->regmap, MAX8973_CONTROL2, control2);
+	if (ret < 0) {
+		dev_err(max->dev, "register %d write failed, err = %d",
+				MAX8973_CONTROL2, ret);
+		return ret;
+	}
+
+	/* If external control is enabled then disable EN bit */
+	if (max->enable_external_control) {
+		ret = regmap_update_bits(max->regmap, MAX8973_VOUT,
+						MAX8973_VOUT_ENABLE, 0);
+		if (ret < 0)
+			dev_err(max->dev, "register %d update failed, err = %d",
+				MAX8973_VOUT, ret);
+	}
+	return ret;
+}
+
+static const struct regmap_config max8973_regmap_config = {
+	.reg_bits		= 8,
+	.val_bits		= 8,
+	.max_register		= MAX8973_CHIPID2,
+	.cache_type		= REGCACHE_RBTREE,
+};
+
+static int __devinit max8973_probe(struct i2c_client *client,
+				     const struct i2c_device_id *id)
+{
+	struct max8973_regulator_platform_data *pdata;
+	struct regulator_config config = { };
+	struct regulator_dev *rdev;
+	struct max8973_chip *max;
+	int ret;
+
+	pdata = client->dev.platform_data;
+	if (!pdata) {
+		dev_err(&client->dev, "No Platform data");
+		return -EIO;
+	}
+
+	max = devm_kzalloc(&client->dev, sizeof(*max), GFP_KERNEL);
+	if (!max) {
+		dev_err(&client->dev, "Memory allocation for max failed\n");
+		return -ENOMEM;
+	}
+
+	max->regmap = devm_regmap_init_i2c(client, &max8973_regmap_config);
+	if (IS_ERR(max->regmap)) {
+		ret = PTR_ERR(max->regmap);
+		dev_err(&client->dev, "regmap init failed, err %d\n", ret);
+		return ret;
+	}
+
+	i2c_set_clientdata(client, max);
+	max->dev = &client->dev;
+	max->desc.name = id->name;
+	max->desc.id = 0;
+	max->desc.ops = &max8973_dcdc_ops;
+	max->desc.type = REGULATOR_VOLTAGE;
+	max->desc.owner = THIS_MODULE;
+	max->desc.min_uV = MAX8973_MIN_VOLATGE;
+	max->desc.uV_step = MAX8973_VOLATGE_STEP;
+	max->desc.n_voltages = MAX8973_BUCK_N_VOLTAGE;
+
+	if (!pdata->enable_ext_control) {
+		max->desc.enable_reg = MAX8973_VOUT;
+		max->desc.enable_mask = MAX8973_VOUT_ENABLE;
+		max8973_dcdc_ops.enable = regulator_enable_regmap;
+		max8973_dcdc_ops.disable = regulator_disable_regmap;
+		max8973_dcdc_ops.is_enabled = regulator_is_enabled_regmap;
+	}
+
+	max->enable_external_control = pdata->enable_ext_control;
+	max->dvs_gpio = pdata->dvs_gpio;
+	max->curr_gpio_val = pdata->dvs_def_state;
+	max->curr_vout_reg = MAX8973_VOUT + pdata->dvs_def_state;
+	max->lru_index[0] = max->curr_vout_reg;
+	max->valid_dvs_gpio = false;
+
+	if (gpio_is_valid(max->dvs_gpio)) {
+		int gpio_flags;
+		int i;
+
+		gpio_flags = (pdata->dvs_def_state) ?
+				GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+		ret = devm_gpio_request_one(&client->dev, max->dvs_gpio,
+				gpio_flags, "max8973-dvs");
+		if (ret) {
+			dev_err(&client->dev,
+				"gpio_request for gpio %d failed, err = %d\n",
+				max->dvs_gpio, ret);
+			return ret;
+		}
+		max->valid_dvs_gpio = true;
+
+		/*
+		 * Initialize the lru index with vout_reg id
+		 * The index 0 will be most recently used and
+		 * set with the max->curr_vout_reg */
+		for (i = 0; i < MAX8973_MAX_VOUT_REG; ++i)
+			max->lru_index[i] = i;
+		max->lru_index[0] = max->curr_vout_reg;
+		max->lru_index[max->curr_vout_reg] = 0;
+	}
+
+	ret = max8973_init_dcdc(max, pdata);
+	if (ret < 0) {
+		dev_err(max->dev, "Max8973 Init failed, err = %d\n", ret);
+		return ret;
+	}
+
+	config.dev = &client->dev;
+	config.init_data = pdata->reg_init_data;
+	config.driver_data = max;
+	config.of_node = client->dev.of_node;
+	config.regmap = max->regmap;
+
+	/* Register the regulators */
+	rdev = regulator_register(&max->desc, &config);
+	if (IS_ERR(rdev)) {
+		ret = PTR_ERR(rdev);
+		dev_err(max->dev, "regulator register failed, err %d\n", ret);
+		return ret;
+	}
+
+	max->rdev = rdev;
+	return 0;
+}
+
+static int __devexit 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",},
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, max8973_id);
+
+static struct i2c_driver max8973_i2c_driver = {
+	.driver = {
+		.name = "max8973",
+		.owner = THIS_MODULE,
+	},
+	.probe = max8973_probe,
+	.remove = __devexit_p(max8973_remove),
+	.id_table = max8973_id,
+};
+
+static int __init max8973_init(void)
+{
+	return i2c_add_driver(&max8973_i2c_driver);
+}
+subsys_initcall(max8973_init);
+
+static void __exit max8973_cleanup(void)
+{
+	i2c_del_driver(&max8973_i2c_driver);
+}
+module_exit(max8973_cleanup);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("MAX8973 voltage regulator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
index e39a0c7..df0eafb 100644
--- a/drivers/regulator/max8997.c
+++ b/drivers/regulator/max8997.c
@@ -24,6 +24,7 @@
 #include <linux/bug.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
+#include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -31,6 +32,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/mfd/max8997.h>
 #include <linux/mfd/max8997-private.h>
+#include <linux/regulator/of_regulator.h>
 
 struct max8997_data {
 	struct device *dev;
@@ -933,22 +935,163 @@ static struct regulator_desc regulators[] = {
 				  max8997_charger_fixedstate_ops),
 };
 
-static __devinit int max8997_pmic_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev,
+			struct max8997_platform_data *pdata,
+			struct device_node *pmic_np)
+{
+	int i, gpio;
+
+	for (i = 0; i < 3; i++) {
+		gpio = of_get_named_gpio(pmic_np,
+					"max8997,pmic-buck125-dvs-gpios", i);
+		if (!gpio_is_valid(gpio)) {
+			dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio);
+			return -EINVAL;
+		}
+		pdata->buck125_gpios[i] = gpio;
+	}
+	return 0;
+}
+
+static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
+					struct max8997_platform_data *pdata)
+{
+	struct device_node *pmic_np, *regulators_np, *reg_np;
+	struct max8997_regulator_data *rdata;
+	unsigned int i, dvs_voltage_nr = 1, ret;
+
+	pmic_np = iodev->dev->of_node;
+	if (!pmic_np) {
+		dev_err(iodev->dev, "could not find pmic sub-node\n");
+		return -ENODEV;
+	}
+
+	regulators_np = of_find_node_by_name(pmic_np, "regulators");
+	if (!regulators_np) {
+		dev_err(iodev->dev, "could not find regulators sub-node\n");
+		return -EINVAL;
+	}
+
+	/* count the number of regulators to be supported in pmic */
+	pdata->num_regulators = 0;
+	for_each_child_of_node(regulators_np, reg_np)
+		pdata->num_regulators++;
+
+	rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
+				pdata->num_regulators, GFP_KERNEL);
+	if (!rdata) {
+		dev_err(iodev->dev, "could not allocate memory for "
+						"regulator data\n");
+		return -ENOMEM;
+	}
+
+	pdata->regulators = rdata;
+	for_each_child_of_node(regulators_np, reg_np) {
+		for (i = 0; i < ARRAY_SIZE(regulators); i++)
+			if (!of_node_cmp(reg_np->name, regulators[i].name))
+				break;
+
+		if (i == ARRAY_SIZE(regulators)) {
+			dev_warn(iodev->dev, "don't know how to configure "
+				"regulator %s\n", reg_np->name);
+			continue;
+		}
+
+		rdata->id = i;
+		rdata->initdata = of_get_regulator_init_data(
+						iodev->dev, reg_np);
+		rdata->reg_node = reg_np;
+		rdata++;
+	}
+
+	if (of_get_property(pmic_np, "max8997,pmic-buck1-uses-gpio-dvs", NULL))
+		pdata->buck1_gpiodvs = true;
+
+	if (of_get_property(pmic_np, "max8997,pmic-buck2-uses-gpio-dvs", NULL))
+		pdata->buck2_gpiodvs = true;
+
+	if (of_get_property(pmic_np, "max8997,pmic-buck5-uses-gpio-dvs", NULL))
+		pdata->buck5_gpiodvs = true;
+
+	if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
+						pdata->buck5_gpiodvs) {
+		ret = max8997_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
+		if (ret)
+			return -EINVAL;
+
+		if (of_property_read_u32(pmic_np,
+				"max8997,pmic-buck125-default-dvs-idx",
+				&pdata->buck125_default_idx)) {
+			pdata->buck125_default_idx = 0;
+		} else {
+			if (pdata->buck125_default_idx >= 8) {
+				pdata->buck125_default_idx = 0;
+				dev_info(iodev->dev, "invalid value for "
+				"default dvs index, using 0 instead\n");
+			}
+		}
+
+		if (of_get_property(pmic_np,
+			"max8997,pmic-ignore-gpiodvs-side-effect", NULL))
+			pdata->ignore_gpiodvs_side_effect = true;
+
+		dvs_voltage_nr = 8;
+	}
+
+	if (of_property_read_u32_array(pmic_np,
+				"max8997,pmic-buck1-dvs-voltage",
+				pdata->buck1_voltage, dvs_voltage_nr)) {
+		dev_err(iodev->dev, "buck1 voltages not specified\n");
+		return -EINVAL;
+	}
+
+	if (of_property_read_u32_array(pmic_np,
+				"max8997,pmic-buck2-dvs-voltage",
+				pdata->buck2_voltage, dvs_voltage_nr)) {
+		dev_err(iodev->dev, "buck2 voltages not specified\n");
+		return -EINVAL;
+	}
+
+	if (of_property_read_u32_array(pmic_np,
+				"max8997,pmic-buck5-dvs-voltage",
+				pdata->buck5_voltage, dvs_voltage_nr)) {
+		dev_err(iodev->dev, "buck5 voltages not specified\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+#else
+static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
+					struct max8997_platform_data *pdata)
+{
+	return 0;
+}
+#endif /* CONFIG_OF */
+
+static int max8997_pmic_probe(struct platform_device *pdev)
 {
 	struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
-	struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
+	struct max8997_platform_data *pdata = iodev->pdata;
 	struct regulator_config config = { };
 	struct regulator_dev **rdev;
 	struct max8997_data *max8997;
 	struct i2c_client *i2c;
-	int i, ret, size;
+	int i, ret, size, nr_dvs;
 	u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0;
 
-	if (!pdata) {
+	if (IS_ERR_OR_NULL(pdata)) {
 		dev_err(pdev->dev.parent, "No platform init data supplied.\n");
 		return -ENODEV;
 	}
 
+	if (iodev->dev->of_node) {
+		ret = max8997_pmic_dt_parse_pdata(iodev, pdata);
+		if (ret)
+			return ret;
+	}
+
 	max8997 = devm_kzalloc(&pdev->dev, sizeof(struct max8997_data),
 			       GFP_KERNEL);
 	if (!max8997)
@@ -973,7 +1116,10 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
 	memcpy(max8997->buck125_gpios, pdata->buck125_gpios, sizeof(int) * 3);
 	max8997->ignore_gpiodvs_side_effect = pdata->ignore_gpiodvs_side_effect;
 
-	for (i = 0; i < 8; i++) {
+	nr_dvs = (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
+			pdata->buck5_gpiodvs) ? 8 : 1;
+
+	for (i = 0; i < nr_dvs; i++) {
 		max8997->buck1_vol[i] = ret =
 			max8997_get_voltage_proper_val(
 					&buck1245_voltage_map_desc,
@@ -1019,6 +1165,19 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
 				max_buck5, 0x3f);
 	}
 
+	/* Initialize all the DVS related BUCK registers */
+	for (i = 0; i < nr_dvs; i++) {
+		max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
+				max8997->buck1_vol[i],
+				0x3f);
+		max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
+				max8997->buck2_vol[i],
+				0x3f);
+		max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
+				max8997->buck5_vol[i],
+				0x3f);
+	}
+
 	/*
 	 * If buck 1, 2, and 5 do not care DVS GPIO settings, ignore them.
 	 * If at least one of them cares, set gpios.
@@ -1068,19 +1227,6 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
 	max8997_update_reg(i2c, MAX8997_REG_BUCK5CTRL, (pdata->buck5_gpiodvs) ?
 			(1 << 1) : (0 << 1), 1 << 1);
 
-	/* Initialize all the DVS related BUCK registers */
-	for (i = 0; i < 8; i++) {
-		max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
-				max8997->buck1_vol[i],
-				0x3f);
-		max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
-				max8997->buck2_vol[i],
-				0x3f);
-		max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
-				max8997->buck5_vol[i],
-				0x3f);
-	}
-
 	/* Misc Settings */
 	max8997->ramp_delay = 10; /* set 10mV/us, which is the default */
 	max8997_write_reg(i2c, MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9);
@@ -1101,6 +1247,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
 		config.dev = max8997->dev;
 		config.init_data = pdata->regulators[i].initdata;
 		config.driver_data = max8997;
+		config.of_node = pdata->regulators[i].reg_node;
 
 		rdev[i] = regulator_register(&regulators[id], &config);
 		if (IS_ERR(rdev[i])) {
@@ -1120,7 +1267,7 @@ err_out:
 	return ret;
 }
 
-static int __devexit max8997_pmic_remove(struct platform_device *pdev)
+static int max8997_pmic_remove(struct platform_device *pdev)
 {
 	struct max8997_data *max8997 = platform_get_drvdata(pdev);
 	struct regulator_dev **rdev = max8997->rdev;
@@ -1143,7 +1290,7 @@ static struct platform_driver max8997_pmic_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = max8997_pmic_probe,
-	.remove = __devexit_p(max8997_pmic_remove),
+	.remove = max8997_pmic_remove,
 	.id_table = max8997_pmic_id,
 };
 
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c
index 5dfa920..b821d08 100644
--- a/drivers/regulator/max8998.c
+++ b/drivers/regulator/max8998.c
@@ -633,7 +633,7 @@ static struct regulator_desc regulators[] = {
 	}
 };
 
-static __devinit int max8998_pmic_probe(struct platform_device *pdev)
+static int max8998_pmic_probe(struct platform_device *pdev)
 {
 	struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 	struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -818,7 +818,7 @@ err_out:
 	return ret;
 }
 
-static int __devexit max8998_pmic_remove(struct platform_device *pdev)
+static int max8998_pmic_remove(struct platform_device *pdev)
 {
 	struct max8998_data *max8998 = platform_get_drvdata(pdev);
 	struct regulator_dev **rdev = max8998->rdev;
@@ -842,7 +842,7 @@ static struct platform_driver max8998_pmic_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = max8998_pmic_probe,
-	.remove = __devexit_p(max8998_pmic_remove),
+	.remove = max8998_pmic_remove,
 	.id_table = max8998_pmic_id,
 };
 
diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c
index 0801a6d..c46c670 100644
--- a/drivers/regulator/mc13783-regulator.c
+++ b/drivers/regulator/mc13783-regulator.c
@@ -392,7 +392,7 @@ static struct regulator_ops mc13783_gpo_regulator_ops = {
 	.set_voltage = mc13xxx_fixed_regulator_set_voltage,
 };
 
-static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
+static int mc13783_regulator_probe(struct platform_device *pdev)
 {
 	struct mc13xxx_regulator_priv *priv;
 	struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
@@ -445,7 +445,7 @@ err:
 	return ret;
 }
 
-static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
+static int mc13783_regulator_remove(struct platform_device *pdev)
 {
 	struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
 	struct mc13xxx_regulator_platform_data *pdata =
@@ -465,7 +465,7 @@ static struct platform_driver mc13783_regulator_driver = {
 		.name	= "mc13783-regulator",
 		.owner	= THIS_MODULE,
 	},
-	.remove		= __devexit_p(mc13783_regulator_remove),
+	.remove		= mc13783_regulator_remove,
 	.probe		= mc13783_regulator_probe,
 };
 
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c
index 1fa6381..0d84b1f 100644
--- a/drivers/regulator/mc13892-regulator.c
+++ b/drivers/regulator/mc13892-regulator.c
@@ -486,7 +486,7 @@ static unsigned int mc13892_vcam_get_mode(struct regulator_dev *rdev)
 }
 
 
-static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
+static int mc13892_regulator_probe(struct platform_device *pdev)
 {
 	struct mc13xxx_regulator_priv *priv;
 	struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent);
@@ -588,7 +588,7 @@ err_unlock:
 	return ret;
 }
 
-static int __devexit mc13892_regulator_remove(struct platform_device *pdev)
+static int mc13892_regulator_remove(struct platform_device *pdev)
 {
 	struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
 	int i;
@@ -606,7 +606,7 @@ static struct platform_driver mc13892_regulator_driver = {
 		.name	= "mc13892-regulator",
 		.owner	= THIS_MODULE,
 	},
-	.remove	= __devexit_p(mc13892_regulator_remove),
+	.remove	= mc13892_regulator_remove,
 	.probe	= mc13892_regulator_probe,
 };
 
diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c
index 88cbb83..4ed89c6 100644
--- a/drivers/regulator/mc13xxx-regulator-core.c
+++ b/drivers/regulator/mc13xxx-regulator-core.c
@@ -162,7 +162,7 @@ struct regulator_ops mc13xxx_fixed_regulator_ops = {
 EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops);
 
 #ifdef CONFIG_OF
-int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
+int mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
 {
 	struct device_node *parent, *child;
 	int num = 0;
@@ -179,7 +179,7 @@ int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
 }
 EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt);
 
-struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt(
+struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
 	struct platform_device *pdev, struct mc13xxx_regulator *regulators,
 	int num_regulators)
 {
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
index 07aee69..9d50bbb 100644
--- a/drivers/regulator/palmas-regulator.c
+++ b/drivers/regulator/palmas-regulator.c
@@ -436,44 +436,14 @@ static int palmas_is_enabled_ldo(struct regulator_dev *dev)
 	return !!(reg);
 }
 
-static int palmas_list_voltage_ldo(struct regulator_dev *dev,
-					unsigned selector)
-{
-	if (!selector)
-		return 0;
-
-	/* voltage is 0.85V + (selector * 0.05v) */
-	return  850000 + (selector * 50000);
-}
-
-static int palmas_map_voltage_ldo(struct regulator_dev *rdev,
-		int min_uV, int max_uV)
-{
-	int ret, voltage;
-
-	if (min_uV == 0)
-		return 0;
-
-	if (min_uV < 900000)
-		min_uV = 900000;
-	ret = DIV_ROUND_UP(min_uV - 900000, 50000) + 1;
-
-	/* Map back into a voltage to verify we're still in bounds */
-	voltage = palmas_list_voltage_ldo(rdev, ret);
-	if (voltage < min_uV || voltage > max_uV)
-		return -EINVAL;
-
-	return ret;
-}
-
 static struct regulator_ops palmas_ops_ldo = {
 	.is_enabled		= palmas_is_enabled_ldo,
 	.enable			= regulator_enable_regmap,
 	.disable		= regulator_disable_regmap,
 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
-	.list_voltage		= palmas_list_voltage_ldo,
-	.map_voltage		= palmas_map_voltage_ldo,
+	.list_voltage		= regulator_list_voltage_linear,
+	.map_voltage		= regulator_map_voltage_linear,
 };
 
 /*
@@ -595,7 +565,7 @@ static struct of_regulator_match palmas_matches[] = {
 	{ .name = "ldousb", },
 };
 
-static void __devinit palmas_dt_to_pdata(struct device *dev,
+static void palmas_dt_to_pdata(struct device *dev,
 		struct device_node *node,
 		struct palmas_pmic_platform_data *pdata)
 {
@@ -663,7 +633,7 @@ static void __devinit palmas_dt_to_pdata(struct device *dev,
 }
 
 
-static __devinit int palmas_probe(struct platform_device *pdev)
+static int palmas_probe(struct platform_device *pdev)
 {
 	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
 	struct palmas_pmic_platform_data *pdata = pdev->dev.platform_data;
@@ -773,7 +743,7 @@ static __devinit int palmas_probe(struct platform_device *pdev)
 		/*
 		 * read and store the RANGE bit for later use
 		 * This must be done before regulator is probed otherwise
-		 * we error in probe with unsuportable ranges.
+		 * we error in probe with unsupportable ranges.
 		 */
 		if (id != PALMAS_REG_SMPS10) {
 			addr = palmas_regs_info[id].vsel_addr;
@@ -821,6 +791,9 @@ static __devinit int palmas_probe(struct platform_device *pdev)
 
 		pmic->desc[id].type = REGULATOR_VOLTAGE;
 		pmic->desc[id].owner = THIS_MODULE;
+		pmic->desc[id].min_uV = 900000;
+		pmic->desc[id].uV_step = 50000;
+		pmic->desc[id].linear_min_sel = 1;
 		pmic->desc[id].vsel_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
 						palmas_regs_info[id].vsel_addr);
 		pmic->desc[id].vsel_mask = PALMAS_LDO1_VOLTAGE_VSEL_MASK;
@@ -868,7 +841,7 @@ err_unregister_regulator:
 	return ret;
 }
 
-static int __devexit palmas_remove(struct platform_device *pdev)
+static int palmas_remove(struct platform_device *pdev)
 {
 	struct palmas_pmic *pmic = platform_get_drvdata(pdev);
 	int id;
@@ -890,7 +863,7 @@ static struct platform_driver palmas_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = palmas_probe,
-	.remove = __devexit_p(palmas_remove),
+	.remove = palmas_remove,
 };
 
 static int __init palmas_init(void)
diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c
index 68777ac..4899342 100644
--- a/drivers/regulator/pcap-regulator.c
+++ b/drivers/regulator/pcap-regulator.c
@@ -236,7 +236,7 @@ static const struct regulator_desc pcap_regulators[] = {
 	VREG(VAUX4), VREG(VSIM), VREG(VSIM2), VREG(VVIB), VREG(SW1), VREG(SW2),
 };
 
-static int __devinit pcap_regulator_probe(struct platform_device *pdev)
+static int pcap_regulator_probe(struct platform_device *pdev)
 {
 	struct regulator_dev *rdev;
 	void *pcap = dev_get_drvdata(pdev->dev.parent);
@@ -255,7 +255,7 @@ static int __devinit pcap_regulator_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit pcap_regulator_remove(struct platform_device *pdev)
+static int pcap_regulator_remove(struct platform_device *pdev)
 {
 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -271,7 +271,7 @@ static struct platform_driver pcap_regulator_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe	= pcap_regulator_probe,
-	.remove	= __devexit_p(pcap_regulator_remove),
+	.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 092e5cb..534075e 100644
--- a/drivers/regulator/pcf50633-regulator.c
+++ b/drivers/regulator/pcf50633-regulator.c
@@ -24,12 +24,15 @@
 #include <linux/mfd/pcf50633/core.h>
 #include <linux/mfd/pcf50633/pmic.h>
 
-#define PCF50633_REGULATOR(_name, _id, _n)			\
+#define PCF50633_REGULATOR(_name, _id, _min_uV, _uV_step, _min_sel, _n) \
 	{							\
 		.name = _name,					\
 		.id = PCF50633_REGULATOR_##_id,			\
 		.ops = &pcf50633_regulator_ops,			\
 		.n_voltages = _n,				\
+		.min_uV = _min_uV,				\
+		.uV_step = _uV_step,				\
+		.linear_min_sel = _min_sel,			\
 		.type = REGULATOR_VOLTAGE,			\
 		.owner = THIS_MODULE,				\
 		.vsel_reg = PCF50633_REG_##_id##OUT,		\
@@ -38,165 +41,42 @@
 		.enable_mask = PCF50633_REGULATOR_ON,		\
 	}
 
-/* Bits from voltage value */
-static u8 auto_voltage_bits(unsigned int millivolts)
-{
-	if (millivolts < 1800)
-		return 0x2f;
-	if (millivolts > 3800)
-		return 0xff;
-
-	millivolts -= 625;
-
-	return millivolts / 25;
-}
-
-static u8 down_voltage_bits(unsigned int millivolts)
-{
-	if (millivolts < 625)
-		return 0;
-	else if (millivolts > 3000)
-		return 0xff;
-
-	millivolts -= 625;
-
-	return millivolts / 25;
-}
-
-static u8 ldo_voltage_bits(unsigned int millivolts)
-{
-	if (millivolts < 900)
-		return 0;
-	else if (millivolts > 3600)
-		return 0x1f;
-
-	millivolts -= 900;
-	return millivolts / 100;
-}
-
-/* Obtain voltage value from bits */
-static unsigned int auto_voltage_value(u8 bits)
-{
-	/* AUTOOUT: 00000000 to 00101110 are reserved.
-	 * Return 0 for bits in reserved range, which means this selector code
-	 * can't be used on this system */
-	if (bits < 0x2f)
-		return 0;
-
-	return 625 + (bits * 25);
-}
-
-
-static unsigned int down_voltage_value(u8 bits)
-{
-	return 625 + (bits * 25);
-}
-
-
-static unsigned int ldo_voltage_value(u8 bits)
-{
-	bits &= 0x1f;
-
-	return 900 + (bits * 100);
-}
-
-static int pcf50633_regulator_map_voltage(struct regulator_dev *rdev,
-					  int min_uV, int max_uV)
-{
-	struct pcf50633 *pcf;
-	int regulator_id, millivolts;
-	u8 volt_bits;
-
-	pcf = rdev_get_drvdata(rdev);
-
-	regulator_id = rdev_get_id(rdev);
-	if (regulator_id >= PCF50633_NUM_REGULATORS)
-		return -EINVAL;
-
-	millivolts = min_uV / 1000;
-
-	switch (regulator_id) {
-	case PCF50633_REGULATOR_AUTO:
-		volt_bits = auto_voltage_bits(millivolts);
-		break;
-	case PCF50633_REGULATOR_DOWN1:
-	case PCF50633_REGULATOR_DOWN2:
-		volt_bits = down_voltage_bits(millivolts);
-		break;
-	case PCF50633_REGULATOR_LDO1:
-	case PCF50633_REGULATOR_LDO2:
-	case PCF50633_REGULATOR_LDO3:
-	case PCF50633_REGULATOR_LDO4:
-	case PCF50633_REGULATOR_LDO5:
-	case PCF50633_REGULATOR_LDO6:
-	case PCF50633_REGULATOR_HCLDO:
-	case PCF50633_REGULATOR_MEMLDO:
-		volt_bits = ldo_voltage_bits(millivolts);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return volt_bits;
-}
-
-static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
-						unsigned int index)
-{
-	int regulator_id = rdev_get_id(rdev);
-
-	int millivolts;
-
-	switch (regulator_id) {
-	case PCF50633_REGULATOR_AUTO:
-		millivolts = auto_voltage_value(index);
-		break;
-	case PCF50633_REGULATOR_DOWN1:
-	case PCF50633_REGULATOR_DOWN2:
-		millivolts = down_voltage_value(index);
-		break;
-	case PCF50633_REGULATOR_LDO1:
-	case PCF50633_REGULATOR_LDO2:
-	case PCF50633_REGULATOR_LDO3:
-	case PCF50633_REGULATOR_LDO4:
-	case PCF50633_REGULATOR_LDO5:
-	case PCF50633_REGULATOR_LDO6:
-	case PCF50633_REGULATOR_HCLDO:
-	case PCF50633_REGULATOR_MEMLDO:
-		millivolts = ldo_voltage_value(index);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return millivolts * 1000;
-}
-
 static struct regulator_ops pcf50633_regulator_ops = {
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
-	.list_voltage = pcf50633_regulator_list_voltage,
-	.map_voltage = pcf50633_regulator_map_voltage,
+	.list_voltage = regulator_list_voltage_linear,
+	.map_voltage = regulator_map_voltage_linear,
 	.enable = regulator_enable_regmap,
 	.disable = regulator_disable_regmap,
 	.is_enabled = regulator_is_enabled_regmap,
 };
 
 static const struct regulator_desc regulators[] = {
-	[PCF50633_REGULATOR_AUTO] = PCF50633_REGULATOR("auto", AUTO, 128),
-	[PCF50633_REGULATOR_DOWN1] = PCF50633_REGULATOR("down1", DOWN1, 96),
-	[PCF50633_REGULATOR_DOWN2] = PCF50633_REGULATOR("down2", DOWN2, 96),
-	[PCF50633_REGULATOR_LDO1] = PCF50633_REGULATOR("ldo1", LDO1, 28),
-	[PCF50633_REGULATOR_LDO2] = PCF50633_REGULATOR("ldo2", LDO2, 28),
-	[PCF50633_REGULATOR_LDO3] = PCF50633_REGULATOR("ldo3", LDO3, 28),
-	[PCF50633_REGULATOR_LDO4] = PCF50633_REGULATOR("ldo4", LDO4, 28),
-	[PCF50633_REGULATOR_LDO5] = PCF50633_REGULATOR("ldo5", LDO5, 28),
-	[PCF50633_REGULATOR_LDO6] = PCF50633_REGULATOR("ldo6", LDO6, 28),
-	[PCF50633_REGULATOR_HCLDO] = PCF50633_REGULATOR("hcldo", HCLDO, 28),
-	[PCF50633_REGULATOR_MEMLDO] = PCF50633_REGULATOR("memldo", MEMLDO, 28),
+	[PCF50633_REGULATOR_AUTO] =
+		PCF50633_REGULATOR("auto", AUTO, 1800000, 25000, 0x2f, 128),
+	[PCF50633_REGULATOR_DOWN1] =
+		PCF50633_REGULATOR("down1", DOWN1, 625000, 25000, 0, 96),
+	[PCF50633_REGULATOR_DOWN2] =
+		PCF50633_REGULATOR("down2", DOWN2, 625000, 25000, 0, 96),
+	[PCF50633_REGULATOR_LDO1] =
+		PCF50633_REGULATOR("ldo1", LDO1, 900000, 100000, 0, 28),
+	[PCF50633_REGULATOR_LDO2] =
+		PCF50633_REGULATOR("ldo2", LDO2, 900000, 100000, 0, 28),
+	[PCF50633_REGULATOR_LDO3] =
+		PCF50633_REGULATOR("ldo3", LDO3, 900000, 100000, 0, 28),
+	[PCF50633_REGULATOR_LDO4] =
+		PCF50633_REGULATOR("ldo4", LDO4, 900000, 100000, 0, 28),
+	[PCF50633_REGULATOR_LDO5] =
+		PCF50633_REGULATOR("ldo5", LDO5, 900000, 100000, 0, 28),
+	[PCF50633_REGULATOR_LDO6] =
+		PCF50633_REGULATOR("ldo6", LDO6, 900000, 100000, 0, 28),
+	[PCF50633_REGULATOR_HCLDO] =
+		PCF50633_REGULATOR("hcldo", HCLDO, 900000, 100000, 0, 28),
+	[PCF50633_REGULATOR_MEMLDO] =
+		PCF50633_REGULATOR("memldo", MEMLDO, 900000, 100000, 0, 28),
 };
 
-static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
+static int pcf50633_regulator_probe(struct platform_device *pdev)
 {
 	struct regulator_dev *rdev;
 	struct pcf50633 *pcf;
@@ -222,7 +102,7 @@ static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit pcf50633_regulator_remove(struct platform_device *pdev)
+static int pcf50633_regulator_remove(struct platform_device *pdev)
 {
 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -237,7 +117,7 @@ static struct platform_driver pcf50633_regulator_driver = {
 		.name = "pcf50633-regltr",
 	},
 	.probe = pcf50633_regulator_probe,
-	.remove = __devexit_p(pcf50633_regulator_remove),
+	.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 8bf4e8c..9e6f786 100644
--- a/drivers/regulator/rc5t583-regulator.c
+++ b/drivers/regulator/rc5t583-regulator.c
@@ -119,7 +119,7 @@ static struct rc5t583_regulator_info rc5t583_reg_info[RC5T583_REGULATOR_MAX] = {
 	RC5T583_REG(LDO9, LDOEN1, 1, LDODIS1, 1, 0x7F, 900, 3400, 25000, 133),
 };
 
-static int __devinit rc5t583_regulator_probe(struct platform_device *pdev)
+static int rc5t583_regulator_probe(struct platform_device *pdev)
 {
 	struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
 	struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
@@ -198,7 +198,7 @@ clean_exit:
 	return ret;
 }
 
-static int __devexit rc5t583_regulator_remove(struct platform_device *pdev)
+static int rc5t583_regulator_remove(struct platform_device *pdev)
 {
 	struct rc5t583_regulator *regs = platform_get_drvdata(pdev);
 	int id;
@@ -214,7 +214,7 @@ static struct platform_driver rc5t583_regulator_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= rc5t583_regulator_probe,
-	.remove		= __devexit_p(rc5t583_regulator_remove),
+	.remove		= rc5t583_regulator_remove,
 };
 
 static int __init rc5t583_regulator_init(void)
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 926f9c8..bd062a2 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -231,7 +231,7 @@ static struct regulator_desc regulators[] = {
 	regulator_desc_buck10,
 };
 
-static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
+static int s2mps11_pmic_probe(struct platform_device *pdev)
 {
 	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 	struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -269,16 +269,16 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
 
 	if (ramp_enable) {
 		if (s2mps11->buck2_ramp)
-			ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) >> 6;
+			ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) << 6;
 		if (s2mps11->buck3_ramp || s2mps11->buck4_ramp)
-			ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) >> 4;
+			ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) << 4;
 		sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable);
 	}
 
 	ramp_reg &= 0x00;
-	ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) >> 6;
-	ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) >> 4;
-	ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) >> 2;
+	ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) << 6;
+	ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) << 4;
+	ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) << 2;
 	ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9);
 	sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg);
 
@@ -307,7 +307,7 @@ err:
 	return ret;
 }
 
-static int __devexit s2mps11_pmic_remove(struct platform_device *pdev)
+static int s2mps11_pmic_remove(struct platform_device *pdev)
 {
 	struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev);
 	int i;
@@ -330,7 +330,7 @@ static struct platform_driver s2mps11_pmic_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = s2mps11_pmic_probe,
-	.remove = __devexit_p(s2mps11_pmic_remove),
+	.remove = s2mps11_pmic_remove,
 	.id_table = s2mps11_pmic_id,
 };
 
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index abe64a3..2b822be 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -499,7 +499,7 @@ static struct regulator_desc regulators[] = {
 	s5m8767_regulator_desc(BUCK9),
 };
 
-static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
+static int s5m8767_pmic_probe(struct platform_device *pdev)
 {
 	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 	struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -773,7 +773,7 @@ err:
 	return ret;
 }
 
-static int __devexit s5m8767_pmic_remove(struct platform_device *pdev)
+static int s5m8767_pmic_remove(struct platform_device *pdev)
 {
 	struct s5m8767_info *s5m8767 = platform_get_drvdata(pdev);
 	struct regulator_dev **rdev = s5m8767->rdev;
@@ -798,7 +798,7 @@ static struct platform_driver s5m8767_pmic_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = s5m8767_pmic_probe,
-	.remove = __devexit_p(s5m8767_pmic_remove),
+	.remove = s5m8767_pmic_remove,
 	.id_table = s5m8767_pmic_id,
 };
 
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
new file mode 100644
index 0000000..523b1e5
--- /dev/null
+++ b/drivers/regulator/tps51632-regulator.c
@@ -0,0 +1,327 @@
+/*
+ * tps51632-regulator.c -- TI TPS51632
+ *
+ * Regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down Driverless
+ * Controller with serial VID control and DVFS.
+ *
+ * Copyright (c) 2012, 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/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/tps51632-regulator.h>
+#include <linux/slab.h>
+
+/* Register definitions */
+#define TPS51632_VOLTAGE_SELECT_REG		0x0
+#define TPS51632_VOLTAGE_BASE_REG		0x1
+#define TPS51632_OFFSET_REG			0x2
+#define TPS51632_IMON_REG			0x3
+#define TPS51632_VMAX_REG			0x4
+#define TPS51632_DVFS_CONTROL_REG		0x5
+#define TPS51632_POWER_STATE_REG		0x6
+#define TPS51632_SLEW_REGS			0x7
+#define TPS51632_FAULT_REG			0x14
+
+#define TPS51632_MAX_REG			0x15
+
+#define TPS51632_VOUT_MASK			0x7F
+#define TPS51632_VOUT_OFFSET_MASK		0x1F
+#define TPS51632_VMAX_MASK			0x7F
+#define TPS51632_VMAX_LOCK			0x80
+
+/* TPS51632_DVFS_CONTROL_REG */
+#define TPS51632_DVFS_PWMEN			0x1
+#define TPS51632_DVFS_STEP_20			0x2
+#define TPS51632_DVFS_VMAX_PG			0x4
+#define TPS51632_DVFS_PWMRST			0x8
+#define TPS51632_DVFS_OCA_EN			0x10
+#define TPS51632_DVFS_FCCM			0x20
+
+/* TPS51632_POWER_STATE_REG */
+#define TPS51632_POWER_STATE_MASK		0x03
+#define TPS51632_POWER_STATE_MULTI_PHASE_CCM	0x0
+#define TPS51632_POWER_STATE_SINGLE_PHASE_CCM	0x1
+#define TPS51632_POWER_STATE_SINGLE_PHASE_DCM	0x2
+
+#define TPS51632_MIN_VOLATGE			500000
+#define TPS51632_MAX_VOLATGE			1520000
+#define TPS51632_VOLATGE_STEP_10mV		10000
+#define TPS51632_VOLATGE_STEP_20mV		20000
+#define TPS51632_MAX_VSEL			0x7F
+#define TPS51632_MIN_VSEL			0x19
+#define TPS51632_DEFAULT_RAMP_DELAY		6000
+#define TPS51632_VOLT_VSEL(uV)					\
+		(DIV_ROUND_UP(uV - TPS51632_MIN_VOLATGE,	\
+			TPS51632_VOLATGE_STEP_10mV) +		\
+			TPS51632_MIN_VSEL)
+
+/* TPS51632 chip information */
+struct tps51632_chip {
+	struct device *dev;
+	struct regulator_desc desc;
+	struct regulator_dev *rdev;
+	struct regmap *regmap;
+	bool enable_pwm_dvfs;
+};
+
+static int tps51632_dcdc_get_voltage_sel(struct regulator_dev *rdev)
+{
+	struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+	unsigned int data;
+	int ret;
+	unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
+	int vsel;
+
+	if (tps->enable_pwm_dvfs)
+		reg = TPS51632_VOLTAGE_BASE_REG;
+
+	ret = regmap_read(tps->regmap, reg, &data);
+	if (ret < 0) {
+		dev_err(tps->dev, "reg read failed, err %d\n", ret);
+		return ret;
+	}
+
+	vsel = data & TPS51632_VOUT_MASK;
+	return vsel;
+}
+
+static int tps51632_dcdc_set_voltage_sel(struct regulator_dev *rdev,
+		unsigned selector)
+{
+	struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+	int ret;
+	unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
+
+	if (tps->enable_pwm_dvfs)
+		reg = TPS51632_VOLTAGE_BASE_REG;
+
+	if (selector > TPS51632_MAX_VSEL)
+		return -EINVAL;
+
+	ret = regmap_write(tps->regmap, reg, selector);
+	if (ret < 0)
+		dev_err(tps->dev, "reg write failed, err %d\n", ret);
+	return ret;
+}
+
+static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev,
+		int ramp_delay)
+{
+	struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+	int bit = ramp_delay/6000;
+	int ret;
+
+	if (bit)
+		bit--;
+	ret = regmap_write(tps->regmap, TPS51632_SLEW_REGS, BIT(bit));
+	if (ret < 0)
+		dev_err(tps->dev, "SLEW reg write failed, err %d\n", ret);
+	return ret;
+}
+
+static struct regulator_ops tps51632_dcdc_ops = {
+	.get_voltage_sel	= tps51632_dcdc_get_voltage_sel,
+	.set_voltage_sel	= tps51632_dcdc_set_voltage_sel,
+	.list_voltage		= regulator_list_voltage_linear,
+	.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+	.set_ramp_delay		= tps51632_dcdc_set_ramp_delay,
+};
+
+static int tps51632_init_dcdc(struct tps51632_chip *tps,
+		struct tps51632_regulator_platform_data *pdata)
+{
+	int ret;
+	uint8_t	control = 0;
+	int vsel;
+
+	if (!pdata->enable_pwm_dvfs)
+		goto skip_pwm_config;
+
+	control |= TPS51632_DVFS_PWMEN;
+	tps->enable_pwm_dvfs = pdata->enable_pwm_dvfs;
+	vsel = TPS51632_VOLT_VSEL(pdata->base_voltage_uV);
+	ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_BASE_REG, vsel);
+	if (ret < 0) {
+		dev_err(tps->dev, "BASE reg write failed, err %d\n", ret);
+		return ret;
+	}
+
+	if (pdata->dvfs_step_20mV)
+		control |= TPS51632_DVFS_STEP_20;
+
+	if (pdata->max_voltage_uV) {
+		unsigned int vmax;
+		/**
+		 * TPS51632 hw behavior: VMAX register can be write only
+		 * once as it get locked after first write. The lock get
+		 * reset only when device is power-reset.
+		 * Write register only when lock bit is not enabled.
+		 */
+		ret = regmap_read(tps->regmap, TPS51632_VMAX_REG, &vmax);
+		if (ret < 0) {
+			dev_err(tps->dev, "VMAX read failed, err %d\n", ret);
+			return ret;
+		}
+		if (!(vmax & TPS51632_VMAX_LOCK)) {
+			vsel = TPS51632_VOLT_VSEL(pdata->max_voltage_uV);
+			ret = regmap_write(tps->regmap, TPS51632_VMAX_REG,
+					vsel);
+			if (ret < 0) {
+				dev_err(tps->dev,
+					"VMAX write failed, err %d\n", ret);
+				return ret;
+			}
+		}
+	}
+
+skip_pwm_config:
+	ret = regmap_write(tps->regmap, TPS51632_DVFS_CONTROL_REG, control);
+	if (ret < 0)
+		dev_err(tps->dev, "DVFS reg write failed, err %d\n", ret);
+	return ret;
+}
+
+static bool rd_wr_reg(struct device *dev, unsigned int reg)
+{
+	if ((reg >= 0x8) && (reg <= 0x10))
+		return false;
+	return true;
+}
+
+static const struct regmap_config tps51632_regmap_config = {
+	.reg_bits		= 8,
+	.val_bits		= 8,
+	.writeable_reg		= rd_wr_reg,
+	.readable_reg		= rd_wr_reg,
+	.max_register		= TPS51632_MAX_REG - 1,
+	.cache_type		= REGCACHE_RBTREE,
+};
+
+static int tps51632_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct tps51632_regulator_platform_data *pdata;
+	struct regulator_dev *rdev;
+	struct tps51632_chip *tps;
+	int ret;
+	struct regulator_config config = { };
+
+	pdata = client->dev.platform_data;
+	if (!pdata) {
+		dev_err(&client->dev, "No Platform data\n");
+		return -EINVAL;
+	}
+
+	tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+	if (!tps) {
+		dev_err(&client->dev, "Memory allocation failed\n");
+		return -ENOMEM;
+	}
+
+	tps->dev = &client->dev;
+	tps->desc.name = id->name;
+	tps->desc.id = 0;
+	tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY;
+	tps->desc.min_uV = TPS51632_MIN_VOLATGE;
+	tps->desc.uV_step = TPS51632_VOLATGE_STEP_10mV;
+	tps->desc.linear_min_sel = TPS51632_MIN_VSEL;
+	tps->desc.n_voltages = TPS51632_MAX_VSEL + 1;
+	tps->desc.ops = &tps51632_dcdc_ops;
+	tps->desc.type = REGULATOR_VOLTAGE;
+	tps->desc.owner = THIS_MODULE;
+
+	tps->regmap = devm_regmap_init_i2c(client, &tps51632_regmap_config);
+	if (IS_ERR(tps->regmap)) {
+		ret = PTR_ERR(tps->regmap);
+		dev_err(&client->dev, "regmap init failed, err %d\n", ret);
+		return ret;
+	}
+	i2c_set_clientdata(client, tps);
+
+	ret = tps51632_init_dcdc(tps, pdata);
+	if (ret < 0) {
+		dev_err(tps->dev, "Init failed, err = %d\n", ret);
+		return ret;
+	}
+
+	/* Register the regulators */
+	config.dev = &client->dev;
+	config.init_data = pdata->reg_init_data;
+	config.driver_data = tps;
+	config.regmap = tps->regmap;
+	config.of_node = client->dev.of_node;
+
+	rdev = regulator_register(&tps->desc, &config);
+	if (IS_ERR(rdev)) {
+		dev_err(tps->dev, "regulator register failed\n");
+		return PTR_ERR(rdev);
+	}
+
+	tps->rdev = rdev;
+	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",},
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, tps51632_id);
+
+static struct i2c_driver tps51632_i2c_driver = {
+	.driver = {
+		.name = "tps51632",
+		.owner = THIS_MODULE,
+	},
+	.probe = tps51632_probe,
+	.remove = tps51632_remove,
+	.id_table = tps51632_id,
+};
+
+static int __init tps51632_init(void)
+{
+	return i2c_add_driver(&tps51632_i2c_driver);
+}
+subsys_initcall(tps51632_init);
+
+static void __exit tps51632_cleanup(void)
+{
+	i2c_del_driver(&tps51632_i2c_driver);
+}
+module_exit(tps51632_cleanup);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("TPS51632 voltage regulator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c
index 1378409..ec9453f 100644
--- a/drivers/regulator/tps6105x-regulator.c
+++ b/drivers/regulator/tps6105x-regulator.c
@@ -127,7 +127,7 @@ static const struct regulator_desc tps6105x_regulator_desc = {
 /*
  * Registers the chip as a voltage regulator
  */
-static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
+static int tps6105x_regulator_probe(struct platform_device *pdev)
 {
 	struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
 	struct tps6105x_platform_data *pdata = tps6105x->pdata;
@@ -159,7 +159,7 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit tps6105x_regulator_remove(struct platform_device *pdev)
+static int tps6105x_regulator_remove(struct platform_device *pdev)
 {
 	struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
 	regulator_unregister(tps6105x->regulator);
@@ -172,7 +172,7 @@ static struct platform_driver tps6105x_regulator_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = tps6105x_regulator_probe,
-	.remove = __devexit_p(tps6105x_regulator_remove),
+	.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 68729a7..acbd63f 100644
--- a/drivers/regulator/tps62360-regulator.c
+++ b/drivers/regulator/tps62360-regulator.c
@@ -243,7 +243,7 @@ static struct regulator_ops tps62360_dcdc_ops = {
 	.get_mode		= tps62360_get_mode,
 };
 
-static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps,
+static int tps62360_init_dcdc(struct tps62360_chip *tps,
 		struct tps62360_regulator_platform_data *pdata)
 {
 	int ret;
@@ -339,7 +339,7 @@ static const struct of_device_id tps62360_of_match[] = {
 MODULE_DEVICE_TABLE(of, tps62360_of_match);
 #endif
 
-static int __devinit tps62360_probe(struct i2c_client *client,
+static int tps62360_probe(struct i2c_client *client,
 				     const struct i2c_device_id *id)
 {
 	struct regulator_config config = { };
@@ -490,7 +490,7 @@ static int __devinit tps62360_probe(struct i2c_client *client,
  *
  * Unregister TPS driver as an i2c client device driver
  */
-static int __devexit tps62360_remove(struct i2c_client *client)
+static int tps62360_remove(struct i2c_client *client)
 {
 	struct tps62360_chip *tps = i2c_get_clientdata(client);
 
@@ -531,7 +531,7 @@ static struct i2c_driver tps62360_i2c_driver = {
 		.of_match_table = of_match_ptr(tps62360_of_match),
 	},
 	.probe = tps62360_probe,
-	.remove = __devexit_p(tps62360_remove),
+	.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 6998d57..9b9af6d 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -219,7 +219,7 @@ static struct regmap_config tps65023_regmap_config = {
 	.val_bits = 8,
 };
 
-static int __devinit tps_65023_probe(struct i2c_client *client,
+static int tps_65023_probe(struct i2c_client *client,
 				     const struct i2c_device_id *id)
 {
 	const struct tps_driver_data *drv_data = (void *)id->driver_data;
@@ -319,7 +319,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
 	return error;
 }
 
-static int __devexit tps_65023_remove(struct i2c_client *client)
+static int tps_65023_remove(struct i2c_client *client)
 {
 	struct tps_pmic *tps = i2c_get_clientdata(client);
 	int i;
@@ -446,7 +446,7 @@ static struct i2c_driver tps_65023_i2c_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = tps_65023_probe,
-	.remove = __devexit_p(tps_65023_remove),
+	.remove = tps_65023_remove,
 	.id_table = tps_65023_id,
 };
 
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
index 07d01cc..0233cfb 100644
--- a/drivers/regulator/tps6507x-regulator.c
+++ b/drivers/regulator/tps6507x-regulator.c
@@ -356,7 +356,7 @@ static struct regulator_ops tps6507x_pmic_ops = {
 	.list_voltage = regulator_list_voltage_table,
 };
 
-static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
+static int tps6507x_pmic_probe(struct platform_device *pdev)
 {
 	struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
 	struct tps_info *info = &tps6507x_pmic_regs[0];
@@ -439,7 +439,7 @@ fail:
 	return error;
 }
 
-static int __devexit tps6507x_pmic_remove(struct platform_device *pdev)
+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;
@@ -456,7 +456,7 @@ static struct platform_driver tps6507x_pmic_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = tps6507x_pmic_probe,
-	.remove = __devexit_p(tps6507x_pmic_remove),
+	.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 001ad55..41c3917 100644
--- a/drivers/regulator/tps65090-regulator.c
+++ b/drivers/regulator/tps65090-regulator.c
@@ -18,119 +18,240 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/tps65090.h>
-#include <linux/regulator/tps65090-regulator.h>
 
 struct tps65090_regulator {
-	int		id;
-	/* used by regulator core */
-	struct regulator_desc	desc;
-
-	/* Device */
 	struct device		*dev;
+	struct regulator_desc	*desc;
+	struct regulator_dev	*rdev;
+};
+
+static struct regulator_ops tps65090_ext_control_ops = {
+};
+
+static struct regulator_ops tps65090_reg_contol_ops = {
+	.enable		= regulator_enable_regmap,
+	.disable	= regulator_disable_regmap,
+	.is_enabled	= regulator_is_enabled_regmap,
 };
 
-static struct regulator_ops tps65090_ops = {
-	.enable = regulator_enable_regmap,
-	.disable = regulator_disable_regmap,
-	.is_enabled = regulator_is_enabled_regmap,
+static struct regulator_ops tps65090_ldo_ops = {
 };
 
-#define tps65090_REG(_id)				\
+#define tps65090_REG_DESC(_id, _sname, _en_reg, _ops)	\
 {							\
-	.id		= TPS65090_ID_##_id,		\
-	.desc = {					\
-		.name = tps65090_rails(_id),		\
-		.id = TPS65090_ID_##_id,		\
-		.ops = &tps65090_ops,			\
-		.type = REGULATOR_VOLTAGE,		\
-		.owner = THIS_MODULE,			\
-		.enable_reg = (TPS65090_ID_##_id) + 12,	\
-		.enable_mask = BIT(0),			\
-	},						\
+	.name = "TPS65090_RAILS"#_id,			\
+	.supply_name = _sname,				\
+	.id = TPS65090_REGULATOR_##_id,			\
+	.ops = &_ops,					\
+	.enable_reg = _en_reg,				\
+	.enable_mask = BIT(0),				\
+	.type = REGULATOR_VOLTAGE,			\
+	.owner = THIS_MODULE,				\
 }
 
-static struct tps65090_regulator TPS65090_regulator[] = {
-	tps65090_REG(DCDC1),
-	tps65090_REG(DCDC2),
-	tps65090_REG(DCDC3),
-	tps65090_REG(FET1),
-	tps65090_REG(FET2),
-	tps65090_REG(FET3),
-	tps65090_REG(FET4),
-	tps65090_REG(FET5),
-	tps65090_REG(FET6),
-	tps65090_REG(FET7),
+static struct regulator_desc tps65090_regulator_desc[] = {
+	tps65090_REG_DESC(DCDC1, "vsys1",   0x0C, tps65090_reg_contol_ops),
+	tps65090_REG_DESC(DCDC2, "vsys2",   0x0D, tps65090_reg_contol_ops),
+	tps65090_REG_DESC(DCDC3, "vsys3",   0x0E, tps65090_reg_contol_ops),
+	tps65090_REG_DESC(FET1,  "infet1",  0x0F, tps65090_reg_contol_ops),
+	tps65090_REG_DESC(FET2,  "infet2",  0x10, tps65090_reg_contol_ops),
+	tps65090_REG_DESC(FET3,  "infet3",  0x11, tps65090_reg_contol_ops),
+	tps65090_REG_DESC(FET4,  "infet4",  0x12, tps65090_reg_contol_ops),
+	tps65090_REG_DESC(FET5,  "infet5",  0x13, tps65090_reg_contol_ops),
+	tps65090_REG_DESC(FET6,  "infet6",  0x14, tps65090_reg_contol_ops),
+	tps65090_REG_DESC(FET7,  "infet7",  0x15, tps65090_reg_contol_ops),
+	tps65090_REG_DESC(LDO1,  "vsys_l1", 0,    tps65090_ldo_ops),
+	tps65090_REG_DESC(LDO2,  "vsys_l2", 0,    tps65090_ldo_ops),
 };
 
-static inline struct tps65090_regulator *find_regulator_info(int id)
+static inline bool is_dcdc(int id)
 {
-	struct tps65090_regulator *ri;
-	int i;
+	switch (id) {
+	case TPS65090_REGULATOR_DCDC1:
+	case TPS65090_REGULATOR_DCDC2:
+	case TPS65090_REGULATOR_DCDC3:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int tps65090_config_ext_control(
+	struct tps65090_regulator *ri, bool enable)
+{
+	int ret;
+	struct device *parent = ri->dev->parent;
+	unsigned int reg_en_reg = ri->desc->enable_reg;
+
+	if (enable)
+		ret = tps65090_set_bits(parent, reg_en_reg, 1);
+	else
+		ret =  tps65090_clr_bits(parent, reg_en_reg, 1);
+	if (ret < 0)
+		dev_err(ri->dev, "Error in updating reg 0x%x\n", reg_en_reg);
+	return ret;
+}
+
+static int tps65090_regulator_disable_ext_control(
+		struct tps65090_regulator *ri,
+		struct tps65090_regulator_plat_data *tps_pdata)
+{
+	int ret = 0;
+	struct device *parent = ri->dev->parent;
+	unsigned int reg_en_reg = ri->desc->enable_reg;
+
+	/*
+	 * First enable output for internal control if require.
+	 * And then disable external control.
+	 */
+	if (tps_pdata->reg_init_data->constraints.always_on ||
+			tps_pdata->reg_init_data->constraints.boot_on) {
+		ret =  tps65090_set_bits(parent, reg_en_reg, 0);
+		if (ret < 0) {
+			dev_err(ri->dev, "Error in set reg 0x%x\n", reg_en_reg);
+			return ret;
+		}
+	}
+	return tps65090_config_ext_control(ri, false);
+}
+
+static void tps65090_configure_regulator_config(
+		struct tps65090_regulator_plat_data *tps_pdata,
+		struct regulator_config *config)
+{
+	if (gpio_is_valid(tps_pdata->gpio)) {
+		int gpio_flag = GPIOF_OUT_INIT_LOW;
+
+		if (tps_pdata->reg_init_data->constraints.always_on ||
+				tps_pdata->reg_init_data->constraints.boot_on)
+			gpio_flag = GPIOF_OUT_INIT_HIGH;
 
-	for (i = 0; i < ARRAY_SIZE(TPS65090_regulator); i++) {
-		ri = &TPS65090_regulator[i];
-		if (ri->desc.id == id)
-			return ri;
+		config->ena_gpio = tps_pdata->gpio;
+		config->ena_gpio_flags = gpio_flag;
 	}
-	return NULL;
 }
 
-static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
+static int tps65090_regulator_probe(struct platform_device *pdev)
 {
 	struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent);
 	struct tps65090_regulator *ri = NULL;
 	struct regulator_config config = { };
 	struct regulator_dev *rdev;
-	struct tps65090_regulator_platform_data *tps_pdata;
-	int id = pdev->id;
+	struct tps65090_regulator_plat_data *tps_pdata;
+	struct tps65090_regulator *pmic;
+	struct tps65090_platform_data *tps65090_pdata;
+	int num;
+	int ret;
 
-	dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
+	dev_dbg(&pdev->dev, "Probing regulator\n");
 
-	ri = find_regulator_info(id);
-	if (ri == NULL) {
-		dev_err(&pdev->dev, "invalid regulator ID specified\n");
+	tps65090_pdata = dev_get_platdata(pdev->dev.parent);
+	if (!tps65090_pdata) {
+		dev_err(&pdev->dev, "Platform data missing\n");
 		return -EINVAL;
 	}
-	tps_pdata = pdev->dev.platform_data;
-	ri->dev = &pdev->dev;
-
-	config.dev = &pdev->dev;
-	config.init_data = &tps_pdata->regulator;
-	config.driver_data = ri;
-	config.regmap = tps65090_mfd->rmap;
-
-	rdev = regulator_register(&ri->desc, &config);
-	if (IS_ERR(rdev)) {
-		dev_err(&pdev->dev, "failed to register regulator %s\n",
-				ri->desc.name);
-		return PTR_ERR(rdev);
+
+	pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic),
+			GFP_KERNEL);
+	if (!pmic) {
+		dev_err(&pdev->dev, "mem alloc for pmic failed\n");
+		return -ENOMEM;
+	}
+
+	for (num = 0; num < TPS65090_REGULATOR_MAX; num++) {
+		tps_pdata = tps65090_pdata->reg_pdata[num];
+
+		ri = &pmic[num];
+		ri->dev = &pdev->dev;
+		ri->desc = &tps65090_regulator_desc[num];
+
+		/*
+		 * TPS5090 DCDC support the control from external digital input.
+		 * Configure it as per platform data.
+		 */
+		if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data) {
+			if (tps_pdata->enable_ext_control) {
+				tps65090_configure_regulator_config(
+						tps_pdata, &config);
+				ri->desc->ops = &tps65090_ext_control_ops;
+			} else {
+				ret = tps65090_regulator_disable_ext_control(
+						ri, tps_pdata);
+				if (ret < 0) {
+					dev_err(&pdev->dev,
+						"failed disable ext control\n");
+					goto scrub;
+				}
+			}
+		}
+
+		config.dev = &pdev->dev;
+		config.driver_data = ri;
+		config.regmap = tps65090_mfd->rmap;
+		if (tps_pdata)
+			config.init_data = tps_pdata->reg_init_data;
+		else
+			config.init_data = NULL;
+
+		rdev = regulator_register(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;
+		}
+		ri->rdev = rdev;
+
+		/* Enable external control if it is require */
+		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;
+			}
+		}
 	}
 
-	platform_set_drvdata(pdev, rdev);
+	platform_set_drvdata(pdev, pmic);
 	return 0;
+
+scrub:
+	while (--num >= 0) {
+		ri = &pmic[num];
+		regulator_unregister(ri->rdev);
+	}
+	return ret;
 }
 
-static int __devexit tps65090_regulator_remove(struct platform_device *pdev)
+static int tps65090_regulator_remove(struct platform_device *pdev)
 {
-	struct regulator_dev *rdev = platform_get_drvdata(pdev);
+	struct tps65090_regulator *pmic = platform_get_drvdata(pdev);
+	struct tps65090_regulator *ri;
+	int num;
 
-	regulator_unregister(rdev);
+	for (num = 0; num < TPS65090_REGULATOR_MAX; ++num) {
+		ri = &pmic[num];
+		regulator_unregister(ri->rdev);
+	}
 	return 0;
 }
 
 static struct platform_driver tps65090_regulator_driver = {
 	.driver	= {
-		.name	= "tps65090-regulator",
+		.name	= "tps65090-pmic",
 		.owner	= THIS_MODULE,
 	},
 	.probe		= tps65090_regulator_probe,
-	.remove		= __devexit_p(tps65090_regulator_remove),
+	.remove		= tps65090_regulator_remove,
 };
 
 static int __init tps65090_regulator_init(void)
@@ -148,3 +269,4 @@ module_exit(tps65090_regulator_exit);
 MODULE_DESCRIPTION("tps65090 regulator driver");
 MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:tps65090-pmic");
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c
index ab00cab..73dce76 100644
--- a/drivers/regulator/tps65217-regulator.c
+++ b/drivers/regulator/tps65217-regulator.c
@@ -332,7 +332,7 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev)
 }
 #endif
 
-static int __devinit tps65217_regulator_probe(struct platform_device *pdev)
+static int tps65217_regulator_probe(struct platform_device *pdev)
 {
 	struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
 	struct tps65217_board *pdata = dev_get_platdata(tps->dev);
@@ -397,7 +397,7 @@ err_unregister_regulator:
 	return ret;
 }
 
-static int __devexit tps65217_regulator_remove(struct platform_device *pdev)
+static int tps65217_regulator_remove(struct platform_device *pdev)
 {
 	struct tps65217 *tps = platform_get_drvdata(pdev);
 	unsigned int i;
@@ -415,7 +415,7 @@ static struct platform_driver tps65217_regulator_driver = {
 		.name = "tps65217-pmic",
 	},
 	.probe = tps65217_regulator_probe,
-	.remove = __devexit_p(tps65217_regulator_remove),
+	.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 058d2f2..843ee0a 100644
--- a/drivers/regulator/tps6524x-regulator.c
+++ b/drivers/regulator/tps6524x-regulator.c
@@ -592,7 +592,7 @@ static int pmic_remove(struct spi_device *spi)
 	return 0;
 }
 
-static int __devinit pmic_probe(struct spi_device *spi)
+static int pmic_probe(struct spi_device *spi)
 {
 	struct tps6524x *hw;
 	struct device *dev = &spi->dev;
@@ -649,7 +649,7 @@ fail:
 
 static struct spi_driver pmic_driver = {
 	.probe		= pmic_probe,
-	.remove		= __devexit_p(pmic_remove),
+	.remove		= pmic_remove,
 	.driver		= {
 		.name	= "tps6524x",
 		.owner	= THIS_MODULE,
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index ce1e7cb..f86da67 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -17,10 +17,12 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
 #include <linux/mfd/tps6586x.h>
 
 /* supply control and voltage setting  */
@@ -255,10 +257,10 @@ static inline int tps6586x_regulator_preinit(struct device *parent,
 				 1 << ri->enable_bit[1]);
 }
 
-static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev)
+static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev,
+			int id, struct regulator_init_data *p)
 {
 	struct device *parent = pdev->dev.parent;
-	struct regulator_init_data *p = pdev->dev.platform_data;
 	struct tps6586x_settings *setting = p->driver_data;
 	uint8_t reg;
 
@@ -269,7 +271,7 @@ static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev)
 		return 0;
 
 	/* only SM0 and SM1 can have the slew rate settings */
-	switch (pdev->id) {
+	switch (id) {
 	case TPS6586X_ID_SM_0:
 		reg = TPS6586X_SM0SL;
 		break;
@@ -298,58 +300,185 @@ static inline struct tps6586x_regulator *find_regulator_info(int id)
 	return NULL;
 }
 
-static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static struct of_regulator_match tps6586x_matches[] = {
+	{ .name = "sys",     .driver_data = (void *)TPS6586X_ID_SYS     },
+	{ .name = "sm0",     .driver_data = (void *)TPS6586X_ID_SM_0    },
+	{ .name = "sm1",     .driver_data = (void *)TPS6586X_ID_SM_1    },
+	{ .name = "sm2",     .driver_data = (void *)TPS6586X_ID_SM_2    },
+	{ .name = "ldo0",    .driver_data = (void *)TPS6586X_ID_LDO_0   },
+	{ .name = "ldo1",    .driver_data = (void *)TPS6586X_ID_LDO_1   },
+	{ .name = "ldo2",    .driver_data = (void *)TPS6586X_ID_LDO_2   },
+	{ .name = "ldo3",    .driver_data = (void *)TPS6586X_ID_LDO_3   },
+	{ .name = "ldo4",    .driver_data = (void *)TPS6586X_ID_LDO_4   },
+	{ .name = "ldo5",    .driver_data = (void *)TPS6586X_ID_LDO_5   },
+	{ .name = "ldo6",    .driver_data = (void *)TPS6586X_ID_LDO_6   },
+	{ .name = "ldo7",    .driver_data = (void *)TPS6586X_ID_LDO_7   },
+	{ .name = "ldo8",    .driver_data = (void *)TPS6586X_ID_LDO_8   },
+	{ .name = "ldo9",    .driver_data = (void *)TPS6586X_ID_LDO_9   },
+	{ .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC },
+};
+
+static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
+		struct platform_device *pdev,
+		struct of_regulator_match **tps6586x_reg_matches)
+{
+	const unsigned int num = ARRAY_SIZE(tps6586x_matches);
+	struct device_node *np = pdev->dev.parent->of_node;
+	struct device_node *regs;
+	const char *sys_rail = NULL;
+	unsigned int i;
+	struct tps6586x_platform_data *pdata;
+	int err;
+
+	regs = of_find_node_by_name(np, "regulators");
+	if (!regs) {
+		dev_err(&pdev->dev, "regulator node not found\n");
+		return NULL;
+	}
+
+	err = of_regulator_match(&pdev->dev, regs, tps6586x_matches, num);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Regulator match failed, e %d\n", err);
+		of_node_put(regs);
+		return NULL;
+	}
+
+	of_node_put(regs);
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		dev_err(&pdev->dev, "Memory alloction failed\n");
+		return NULL;
+	}
+
+	for (i = 0; i < num; i++) {
+		int id;
+		if (!tps6586x_matches[i].init_data)
+			continue;
+
+		pdata->reg_init_data[i] = tps6586x_matches[i].init_data;
+		id = (int)tps6586x_matches[i].driver_data;
+		if (id == TPS6586X_ID_SYS)
+			sys_rail = pdata->reg_init_data[i]->constraints.name;
+
+		if ((id == TPS6586X_ID_LDO_5) || (id == TPS6586X_ID_LDO_RTC))
+			pdata->reg_init_data[i]->supply_regulator = sys_rail;
+	}
+	*tps6586x_reg_matches = tps6586x_matches;
+	return pdata;
+}
+#else
+static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
+		struct platform_device *pdev,
+		struct of_regulator_match **tps6586x_reg_matches)
+{
+	*tps6586x_reg_matches = NULL;
+	return NULL;
+}
+#endif
+
+static int tps6586x_regulator_probe(struct platform_device *pdev)
 {
 	struct tps6586x_regulator *ri = NULL;
 	struct regulator_config config = { };
-	struct regulator_dev *rdev;
-	int id = pdev->id;
+	struct regulator_dev **rdev;
+	struct regulator_init_data *reg_data;
+	struct tps6586x_platform_data *pdata;
+	struct of_regulator_match *tps6586x_reg_matches = NULL;
+	int id;
 	int err;
 
-	dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
+	dev_dbg(&pdev->dev, "Probing regulator\n");
 
-	ri = find_regulator_info(id);
-	if (ri == NULL) {
-		dev_err(&pdev->dev, "invalid regulator ID specified\n");
-		return -EINVAL;
-	}
+	pdata = dev_get_platdata(pdev->dev.parent);
+	if ((!pdata) && (pdev->dev.parent->of_node))
+		pdata = tps6586x_parse_regulator_dt(pdev,
+					&tps6586x_reg_matches);
 
-	err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
-	if (err)
-		return err;
+	if (!pdata) {
+		dev_err(&pdev->dev, "Platform data not available, exiting\n");
+		return -ENODEV;
+	}
 
-	config.dev = pdev->dev.parent;
-	config.of_node = pdev->dev.of_node;
-	config.init_data = pdev->dev.platform_data;
-	config.driver_data = ri;
+	rdev = devm_kzalloc(&pdev->dev, TPS6586X_ID_MAX_REGULATOR *
+				sizeof(*rdev), GFP_KERNEL);
+	if (!rdev) {
+		dev_err(&pdev->dev, "Mmemory alloc failed\n");
+		return -ENOMEM;
+	}
 
-	rdev = regulator_register(&ri->desc, &config);
-	if (IS_ERR(rdev)) {
-		dev_err(&pdev->dev, "failed to register regulator %s\n",
-				ri->desc.name);
-		return PTR_ERR(rdev);
+	for (id = 0; id < TPS6586X_ID_MAX_REGULATOR; ++id) {
+		reg_data = pdata->reg_init_data[id];
+
+		ri = find_regulator_info(id);
+		if (!ri) {
+			dev_err(&pdev->dev, "invalid regulator ID specified\n");
+			err = -EINVAL;
+			goto fail;
+		}
+
+		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;
+		}
+
+		config.dev = pdev->dev.parent;
+		config.init_data = reg_data;
+		config.driver_data = ri;
+
+		if (tps6586x_reg_matches)
+			config.of_node = tps6586x_reg_matches[id].of_node;
+
+		rdev[id] = regulator_register(&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;
+		}
+
+		if (reg_data) {
+			err = tps6586x_regulator_set_slew_rate(pdev, id,
+					reg_data);
+			if (err < 0) {
+				dev_err(&pdev->dev,
+					"Slew rate config failed, e %d\n", err);
+				regulator_unregister(rdev[id]);
+				goto fail;
+			}
+		}
 	}
 
 	platform_set_drvdata(pdev, rdev);
+	return 0;
 
-	return tps6586x_regulator_set_slew_rate(pdev);
+fail:
+	while (--id >= 0)
+		regulator_unregister(rdev[id]);
+	return err;
 }
 
-static int __devexit tps6586x_regulator_remove(struct platform_device *pdev)
+static int tps6586x_regulator_remove(struct platform_device *pdev)
 {
-	struct regulator_dev *rdev = platform_get_drvdata(pdev);
+	struct regulator_dev **rdev = platform_get_drvdata(pdev);
+	int id = TPS6586X_ID_MAX_REGULATOR;
+
+	while (--id >= 0)
+		regulator_unregister(rdev[id]);
 
-	regulator_unregister(rdev);
 	return 0;
 }
 
 static struct platform_driver tps6586x_regulator_driver = {
 	.driver	= {
-		.name	= "tps6586x-regulator",
+		.name	= "tps6586x-pmic",
 		.owner	= THIS_MODULE,
 	},
 	.probe		= tps6586x_regulator_probe,
-	.remove		= __devexit_p(tps6586x_regulator_remove),
+	.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 793adda..59c3770 100644
--- a/drivers/regulator/tps65910-regulator.c
+++ b/drivers/regulator/tps65910-regulator.c
@@ -38,6 +38,11 @@ static const unsigned int VIO_VSEL_table[] = {
 
 /* VSEL tables for TPS65910 specific LDOs and dcdc's */
 
+/* supported VRTC voltages in microvolts */
+static const unsigned int VRTC_VSEL_table[] = {
+	1800000,
+};
+
 /* supported VDD3 voltages in microvolts */
 static const unsigned int VDD3_VSEL_table[] = {
 	5000000,
@@ -95,6 +100,8 @@ static struct tps_info tps65910_regs[] = {
 	{
 		.name = "vrtc",
 		.vin_name = "vcc7",
+		.n_voltages = ARRAY_SIZE(VRTC_VSEL_table),
+		.voltage_table = VRTC_VSEL_table,
 		.enable_time_us = 2200,
 	},
 	{
@@ -1026,7 +1033,7 @@ static inline struct tps65910_board *tps65910_parse_dt_reg_data(
 }
 #endif
 
-static __devinit int tps65910_probe(struct platform_device *pdev)
+static int tps65910_probe(struct platform_device *pdev)
 {
 	struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
 	struct regulator_config config = { };
@@ -1184,7 +1191,7 @@ err_unregister_regulator:
 	return err;
 }
 
-static int __devexit tps65910_remove(struct platform_device *pdev)
+static int tps65910_remove(struct platform_device *pdev)
 {
 	struct tps65910_reg *pmic = platform_get_drvdata(pdev);
 	int i;
@@ -1231,7 +1238,7 @@ static struct platform_driver tps65910_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = tps65910_probe,
-	.remove = __devexit_p(tps65910_remove),
+	.remove = tps65910_remove,
 	.shutdown = tps65910_shutdown,
 };
 
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
index 18b2a1d..17e994e 100644
--- a/drivers/regulator/tps65912-regulator.c
+++ b/drivers/regulator/tps65912-regulator.c
@@ -459,7 +459,7 @@ static struct regulator_ops tps65912_ops_ldo = {
 	.list_voltage = tps65912_list_voltage,
 };
 
-static __devinit int tps65912_probe(struct platform_device *pdev)
+static int tps65912_probe(struct platform_device *pdev)
 {
 	struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
 	struct regulator_config config = { };
@@ -525,7 +525,7 @@ err:
 	return err;
 }
 
-static int __devexit tps65912_remove(struct platform_device *pdev)
+static int tps65912_remove(struct platform_device *pdev)
 {
 	struct tps65912_reg *tps65912_reg = platform_get_drvdata(pdev);
 	int i;
@@ -541,7 +541,7 @@ static struct platform_driver tps65912_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = tps65912_probe,
-	.remove = __devexit_p(tps65912_remove),
+	.remove = tps65912_remove,
 };
 
 static int __init tps65912_init(void)
diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c
new file mode 100644
index 0000000..50f89b0
--- /dev/null
+++ b/drivers/regulator/tps80031-regulator.c
@@ -0,0 +1,795 @@
+/*
+ * tps80031-regulator.c -- TI TPS80031 regulator driver.
+ *
+ * Regulator driver for TI TPS80031/TPS80032 Fully Integrated Power
+ * Management with Power Path and Battery Charger.
+ *
+ * Copyright (c) 2012, 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/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mfd/tps80031.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/slab.h>
+
+/* Flags for DCDC Voltage reading */
+#define DCDC_OFFSET_EN		BIT(0)
+#define DCDC_EXTENDED_EN	BIT(1)
+#define TRACK_MODE_ENABLE	BIT(2)
+
+#define SMPS_MULTOFFSET_VIO	BIT(1)
+#define SMPS_MULTOFFSET_SMPS1	BIT(3)
+#define SMPS_MULTOFFSET_SMPS2	BIT(4)
+#define SMPS_MULTOFFSET_SMPS3	BIT(6)
+#define SMPS_MULTOFFSET_SMPS4	BIT(0)
+
+#define SMPS_CMD_MASK		0xC0
+#define SMPS_VSEL_MASK		0x3F
+#define LDO_VSEL_MASK		0x1F
+#define LDO_TRACK_VSEL_MASK	0x3F
+
+#define MISC2_LDOUSB_IN_VSYS	BIT(4)
+#define MISC2_LDOUSB_IN_PMID	BIT(3)
+#define MISC2_LDOUSB_IN_MASK	0x18
+
+#define MISC2_LDO3_SEL_VIB_VAL	BIT(0)
+#define MISC2_LDO3_SEL_VIB_MASK	0x1
+
+#define BOOST_HW_PWR_EN		BIT(5)
+#define BOOST_HW_PWR_EN_MASK	BIT(5)
+
+#define OPA_MODE_EN		BIT(6)
+#define OPA_MODE_EN_MASK	BIT(6)
+
+#define USB_VBUS_CTRL_SET	0x04
+#define USB_VBUS_CTRL_CLR	0x05
+#define VBUS_DISCHRG		0x20
+
+struct tps80031_regulator_info {
+	/* Regulator register address.*/
+	u8		trans_reg;
+	u8		state_reg;
+	u8		force_reg;
+	u8		volt_reg;
+	u8		volt_id;
+
+	/*Power request bits */
+	int		preq_bit;
+
+	/* used by regulator core */
+	struct regulator_desc	desc;
+
+};
+
+struct tps80031_regulator {
+	struct device			*dev;
+	struct regulator_dev		*rdev;
+	struct tps80031_regulator_info	*rinfo;
+
+	u8				device_flags;
+	unsigned int			config_flags;
+	unsigned int			ext_ctrl_flag;
+};
+
+static inline struct device *to_tps80031_dev(struct regulator_dev *rdev)
+{
+	return rdev_get_dev(rdev)->parent->parent;
+}
+
+static int tps80031_reg_is_enabled(struct regulator_dev *rdev)
+{
+	struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+	struct device *parent = to_tps80031_dev(rdev);
+	u8 reg_val;
+	int ret;
+
+	if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
+		return true;
+
+	ret = tps80031_read(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
+				&reg_val);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "Reg 0x%02x read failed, err = %d\n",
+			ri->rinfo->state_reg, ret);
+		return ret;
+	}
+	return ((reg_val & TPS80031_STATE_MASK) == TPS80031_STATE_ON);
+}
+
+static int tps80031_reg_enable(struct regulator_dev *rdev)
+{
+	struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+	struct device *parent = to_tps80031_dev(rdev);
+	int ret;
+
+	if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
+		return 0;
+
+	ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
+			TPS80031_STATE_ON, TPS80031_STATE_MASK);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "Reg 0x%02x update failed, err = %d\n",
+			ri->rinfo->state_reg, ret);
+		return ret;
+	}
+	return ret;
+}
+
+static int tps80031_reg_disable(struct regulator_dev *rdev)
+{
+	struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+	struct device *parent = to_tps80031_dev(rdev);
+	int ret;
+
+	if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
+		return 0;
+
+	ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
+			TPS80031_STATE_OFF, TPS80031_STATE_MASK);
+	if (ret < 0)
+		dev_err(&rdev->dev, "Reg 0x%02x update failed, err = %d\n",
+			ri->rinfo->state_reg, ret);
+	return ret;
+}
+
+/* DCDC voltages for the selector of 58 to 63 */
+static int tps80031_dcdc_voltages[4][5] = {
+	{ 1350, 1500, 1800, 1900, 2100},
+	{ 1350, 1500, 1800, 1900, 2100},
+	{ 2084, 2315, 2778, 2932, 3241},
+	{ 4167, 2315, 2778, 2932, 3241},
+};
+
+static int tps80031_dcdc_list_voltage(struct regulator_dev *rdev, unsigned sel)
+{
+	struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+	int volt_index = ri->device_flags & 0x3;
+
+	if (sel == 0)
+		return 0;
+	else if (sel < 58)
+		return regulator_list_voltage_linear(rdev, sel - 1);
+	else
+		return tps80031_dcdc_voltages[volt_index][sel - 58] * 1000;
+}
+
+static int tps80031_dcdc_set_voltage_sel(struct regulator_dev *rdev,
+		unsigned vsel)
+{
+	struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+	struct device *parent = to_tps80031_dev(rdev);
+	int ret;
+	u8 reg_val;
+
+	if (ri->rinfo->force_reg) {
+		ret = tps80031_read(parent, ri->rinfo->volt_id,
+						ri->rinfo->force_reg, &reg_val);
+		if (ret < 0) {
+			dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+				ri->rinfo->force_reg, ret);
+			return ret;
+		}
+		if (!(reg_val & SMPS_CMD_MASK)) {
+			ret = tps80031_update(parent, ri->rinfo->volt_id,
+				ri->rinfo->force_reg, vsel, SMPS_VSEL_MASK);
+			if (ret < 0)
+				dev_err(ri->dev,
+					"reg 0x%02x update failed, e = %d\n",
+					ri->rinfo->force_reg, ret);
+			return ret;
+		}
+	}
+	ret = tps80031_update(parent, ri->rinfo->volt_id,
+			ri->rinfo->volt_reg, vsel, SMPS_VSEL_MASK);
+	if (ret < 0)
+		dev_err(ri->dev, "reg 0x%02x update failed, e = %d\n",
+			ri->rinfo->volt_reg, ret);
+	return ret;
+}
+
+static int tps80031_dcdc_get_voltage_sel(struct regulator_dev *rdev)
+{
+	struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+	struct device *parent = to_tps80031_dev(rdev);
+	uint8_t vsel = 0;
+	int ret;
+
+	if (ri->rinfo->force_reg) {
+		ret = tps80031_read(parent, ri->rinfo->volt_id,
+						ri->rinfo->force_reg, &vsel);
+		if (ret < 0) {
+			dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+					ri->rinfo->force_reg, ret);
+			return ret;
+		}
+
+		if (!(vsel & SMPS_CMD_MASK))
+			return vsel & SMPS_VSEL_MASK;
+	}
+	ret = tps80031_read(parent, ri->rinfo->volt_id,
+				ri->rinfo->volt_reg, &vsel);
+	if (ret < 0) {
+		dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+			ri->rinfo->volt_reg, ret);
+		return ret;
+	}
+	return vsel & SMPS_VSEL_MASK;
+}
+
+static int tps80031_ldo_set_voltage_sel(struct regulator_dev *rdev,
+		unsigned sel)
+{
+	struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+	struct device *parent = to_tps80031_dev(rdev);
+	int ret;
+
+	/* Check for valid setting for TPS80031 or TPS80032-ES1.0 */
+	if ((ri->rinfo->desc.id == TPS80031_REGULATOR_LDO2) &&
+			(ri->device_flags & TRACK_MODE_ENABLE)) {
+		unsigned nvsel = (sel) & 0x1F;
+		if (((tps80031_get_chip_info(parent) == TPS80031) ||
+			((tps80031_get_chip_info(parent) == TPS80032) &&
+			(tps80031_get_pmu_version(parent) == 0x0))) &&
+			((nvsel == 0x0) || (nvsel >= 0x19 && nvsel <= 0x1F))) {
+				dev_err(ri->dev,
+					"Invalid sel %d in track mode LDO2\n",
+					nvsel);
+				return -EINVAL;
+		}
+	}
+
+	ret = tps80031_write(parent, ri->rinfo->volt_id,
+			ri->rinfo->volt_reg, sel);
+	if (ret < 0)
+		dev_err(ri->dev, "Error in writing reg 0x%02x, e = %d\n",
+			ri->rinfo->volt_reg, ret);
+	return ret;
+}
+
+static int tps80031_ldo_get_voltage_sel(struct regulator_dev *rdev)
+{
+	struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+	struct device *parent = to_tps80031_dev(rdev);
+	uint8_t vsel;
+	int ret;
+
+	ret = tps80031_read(parent, ri->rinfo->volt_id,
+				ri->rinfo->volt_reg, &vsel);
+	if (ret < 0) {
+		dev_err(ri->dev, "Error in writing the Voltage register\n");
+		return ret;
+	}
+	return vsel & rdev->desc->vsel_mask;
+}
+
+static int tps80031_ldo_list_voltage(struct regulator_dev *rdev, unsigned sel)
+{
+	if (sel == 0)
+		return 0;
+	else
+		return regulator_list_voltage_linear(rdev, sel - 1);
+}
+
+static int tps80031_vbus_is_enabled(struct regulator_dev *rdev)
+{
+	struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+	struct device *parent = to_tps80031_dev(rdev);
+	int ret = -EIO;
+	uint8_t ctrl1 = 0;
+	uint8_t ctrl3 = 0;
+
+	ret = tps80031_read(parent, TPS80031_SLAVE_ID2,
+			TPS80031_CHARGERUSB_CTRL1, &ctrl1);
+	if (ret < 0) {
+		dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+			TPS80031_CHARGERUSB_CTRL1, ret);
+		return ret;
+	}
+	ret = tps80031_read(parent, TPS80031_SLAVE_ID2,
+				TPS80031_CHARGERUSB_CTRL3, &ctrl3);
+	if (ret < 0) {
+		dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+			TPS80031_CHARGERUSB_CTRL3, ret);
+		return ret;
+	}
+	if ((ctrl1 & OPA_MODE_EN) && (ctrl3 & BOOST_HW_PWR_EN))
+		return 1;
+	return ret;
+}
+
+static int tps80031_vbus_enable(struct regulator_dev *rdev)
+{
+	struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+	struct device *parent = to_tps80031_dev(rdev);
+	int ret;
+
+	ret = tps80031_set_bits(parent, TPS80031_SLAVE_ID2,
+				TPS80031_CHARGERUSB_CTRL1, OPA_MODE_EN);
+	if (ret < 0) {
+		dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+					TPS80031_CHARGERUSB_CTRL1, ret);
+		return ret;
+	}
+
+	ret = tps80031_set_bits(parent, TPS80031_SLAVE_ID2,
+				TPS80031_CHARGERUSB_CTRL3, BOOST_HW_PWR_EN);
+	if (ret < 0) {
+		dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+			TPS80031_CHARGERUSB_CTRL3, ret);
+		return ret;
+	}
+	return ret;
+}
+
+static int tps80031_vbus_disable(struct regulator_dev *rdev)
+{
+	struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+	struct device *parent = to_tps80031_dev(rdev);
+	int ret = 0;
+
+	if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) {
+		ret = tps80031_write(parent, TPS80031_SLAVE_ID2,
+			USB_VBUS_CTRL_SET, VBUS_DISCHRG);
+		if (ret < 0) {
+			dev_err(ri->dev, "reg 0x%02x write failed, e = %d\n",
+				USB_VBUS_CTRL_SET, ret);
+			return ret;
+		}
+	}
+
+	ret = tps80031_clr_bits(parent, TPS80031_SLAVE_ID2,
+			TPS80031_CHARGERUSB_CTRL1,  OPA_MODE_EN);
+	if (ret < 0) {
+		dev_err(ri->dev, "reg 0x%02x clearbit failed, e = %d\n",
+				TPS80031_CHARGERUSB_CTRL1, ret);
+		return ret;
+	}
+
+	ret = tps80031_clr_bits(parent, TPS80031_SLAVE_ID2,
+				TPS80031_CHARGERUSB_CTRL3, BOOST_HW_PWR_EN);
+	if (ret < 0) {
+		dev_err(ri->dev, "reg 0x%02x clearbit failed, e = %d\n",
+				TPS80031_CHARGERUSB_CTRL3, ret);
+		return ret;
+	}
+
+	mdelay(DIV_ROUND_UP(ri->rinfo->desc.enable_time, 1000));
+	if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) {
+		ret = tps80031_write(parent, TPS80031_SLAVE_ID2,
+			USB_VBUS_CTRL_CLR, VBUS_DISCHRG);
+		if (ret < 0) {
+			dev_err(ri->dev, "reg 0x%02x write failed, e = %d\n",
+					USB_VBUS_CTRL_CLR, ret);
+			return ret;
+		}
+	}
+	return ret;
+}
+
+static struct regulator_ops tps80031_dcdc_ops = {
+	.list_voltage		= tps80031_dcdc_list_voltage,
+	.set_voltage_sel	= tps80031_dcdc_set_voltage_sel,
+	.get_voltage_sel	= tps80031_dcdc_get_voltage_sel,
+	.enable		= tps80031_reg_enable,
+	.disable	= tps80031_reg_disable,
+	.is_enabled	= tps80031_reg_is_enabled,
+};
+
+static struct regulator_ops tps80031_ldo_ops = {
+	.list_voltage		= tps80031_ldo_list_voltage,
+	.set_voltage_sel	= tps80031_ldo_set_voltage_sel,
+	.get_voltage_sel	= tps80031_ldo_get_voltage_sel,
+	.enable			= tps80031_reg_enable,
+	.disable		= tps80031_reg_disable,
+	.is_enabled		= tps80031_reg_is_enabled,
+};
+
+static struct regulator_ops tps80031_vbus_sw_ops = {
+	.list_voltage	= regulator_list_voltage_linear,
+	.enable		= tps80031_vbus_enable,
+	.disable	= tps80031_vbus_disable,
+	.is_enabled	= tps80031_vbus_is_enabled,
+};
+
+static struct regulator_ops tps80031_vbus_hw_ops = {
+	.list_voltage	= regulator_list_voltage_linear,
+};
+
+static struct regulator_ops tps80031_ext_reg_ops = {
+	.list_voltage	= regulator_list_voltage_linear,
+	.enable		= tps80031_reg_enable,
+	.disable	= tps80031_reg_disable,
+	.is_enabled	= tps80031_reg_is_enabled,
+};
+
+/* Non-exiting default definition for some register */
+#define TPS80031_SMPS3_CFG_FORCE	0
+#define TPS80031_SMPS4_CFG_FORCE	0
+
+#define TPS80031_VBUS_CFG_TRANS		0
+#define TPS80031_VBUS_CFG_STATE		0
+
+#define TPS80031_REG_SMPS(_id, _volt_id, _pbit)	\
+{								\
+	.trans_reg = TPS80031_##_id##_CFG_TRANS,		\
+	.state_reg = TPS80031_##_id##_CFG_STATE,		\
+	.force_reg = TPS80031_##_id##_CFG_FORCE,		\
+	.volt_reg = TPS80031_##_id##_CFG_VOLTAGE,		\
+	.volt_id = TPS80031_SLAVE_##_volt_id,			\
+	.preq_bit = _pbit,					\
+	.desc = {						\
+		.name = "tps80031_"#_id,			\
+		.id = TPS80031_REGULATOR_##_id,			\
+		.n_voltages = 63,				\
+		.ops = &tps80031_dcdc_ops,			\
+		.type = REGULATOR_VOLTAGE,			\
+		.owner = THIS_MODULE,				\
+		.enable_time = 500,				\
+	},							\
+}
+
+#define TPS80031_REG_LDO(_id, _preq_bit)			\
+{								\
+	.trans_reg = TPS80031_##_id##_CFG_TRANS,		\
+	.state_reg = TPS80031_##_id##_CFG_STATE,		\
+	.volt_reg = TPS80031_##_id##_CFG_VOLTAGE,		\
+	.volt_id = TPS80031_SLAVE_ID1,				\
+	.preq_bit = _preq_bit,					\
+	.desc = {						\
+		.owner = THIS_MODULE,				\
+		.name = "tps80031_"#_id,			\
+		.id = TPS80031_REGULATOR_##_id,			\
+		.ops = &tps80031_ldo_ops,			\
+		.type = REGULATOR_VOLTAGE,			\
+		.min_uV = 1000000,				\
+		.uV_step = 100000,				\
+		.n_voltages = 25,				\
+		.vsel_mask = LDO_VSEL_MASK,			\
+		.enable_time = 500,				\
+	},							\
+}
+
+#define TPS80031_REG_FIXED(_id, max_mV, _ops, _delay, _pbit)	\
+{								\
+	.trans_reg = TPS80031_##_id##_CFG_TRANS,		\
+	.state_reg = TPS80031_##_id##_CFG_STATE,		\
+	.volt_id = TPS80031_SLAVE_ID1,				\
+	.preq_bit = _pbit,					\
+	.desc = {						\
+		.name = "tps80031_"#_id,			\
+		.id = TPS80031_REGULATOR_##_id,			\
+		.min_uV = max_mV * 1000,			\
+		.n_voltages = 1,				\
+		.ops = &_ops,					\
+		.type = REGULATOR_VOLTAGE,			\
+		.owner = THIS_MODULE,				\
+		.enable_time = _delay,				\
+	},							\
+}
+
+static struct tps80031_regulator_info tps80031_rinfo[TPS80031_REGULATOR_MAX] = {
+	TPS80031_REG_SMPS(VIO,   ID0, 4),
+	TPS80031_REG_SMPS(SMPS1, ID0, 0),
+	TPS80031_REG_SMPS(SMPS2, ID0, 1),
+	TPS80031_REG_SMPS(SMPS3, ID1, 2),
+	TPS80031_REG_SMPS(SMPS4, ID1, 3),
+	TPS80031_REG_LDO(VANA,   -1),
+	TPS80031_REG_LDO(LDO1,   8),
+	TPS80031_REG_LDO(LDO2,   9),
+	TPS80031_REG_LDO(LDO3,   10),
+	TPS80031_REG_LDO(LDO4,   11),
+	TPS80031_REG_LDO(LDO5,   12),
+	TPS80031_REG_LDO(LDO6,   13),
+	TPS80031_REG_LDO(LDO7,   14),
+	TPS80031_REG_LDO(LDOLN,  15),
+	TPS80031_REG_LDO(LDOUSB, 5),
+	TPS80031_REG_FIXED(VBUS,   5000, tps80031_vbus_hw_ops, 100000, -1),
+	TPS80031_REG_FIXED(REGEN1, 3300, tps80031_ext_reg_ops, 0, 16),
+	TPS80031_REG_FIXED(REGEN2, 3300, tps80031_ext_reg_ops, 0, 17),
+	TPS80031_REG_FIXED(SYSEN,  3300, tps80031_ext_reg_ops, 0, 18),
+};
+
+static int tps80031_power_req_config(struct device *parent,
+		struct tps80031_regulator *ri,
+		struct tps80031_regulator_platform_data *tps80031_pdata)
+{
+	int ret = 0;
+
+	if (ri->rinfo->preq_bit < 0)
+		goto skip_pwr_req_config;
+
+	ret = tps80031_ext_power_req_config(parent, ri->ext_ctrl_flag,
+			ri->rinfo->preq_bit, ri->rinfo->state_reg,
+			ri->rinfo->trans_reg);
+	if (ret < 0) {
+		dev_err(ri->dev, "ext powerreq config failed, err = %d\n", ret);
+		return ret;
+	}
+
+skip_pwr_req_config:
+	if (tps80031_pdata->ext_ctrl_flag & TPS80031_PWR_ON_ON_SLEEP) {
+		ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
+				ri->rinfo->trans_reg, TPS80031_TRANS_SLEEP_ON,
+				TPS80031_TRANS_SLEEP_MASK);
+		if (ret < 0) {
+			dev_err(ri->dev, "Reg 0x%02x update failed, e %d\n",
+					ri->rinfo->trans_reg, ret);
+			return ret;
+		}
+	}
+	return ret;
+}
+
+static int tps80031_regulator_config(struct device *parent,
+		struct tps80031_regulator *ri,
+		struct tps80031_regulator_platform_data *tps80031_pdata)
+{
+	int ret = 0;
+
+	switch (ri->rinfo->desc.id) {
+	case TPS80031_REGULATOR_LDOUSB:
+		if (ri->config_flags & (TPS80031_USBLDO_INPUT_VSYS |
+			TPS80031_USBLDO_INPUT_PMID)) {
+			unsigned val = 0;
+			if (ri->config_flags & TPS80031_USBLDO_INPUT_VSYS)
+				val = MISC2_LDOUSB_IN_VSYS;
+			else
+				val = MISC2_LDOUSB_IN_PMID;
+
+			ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
+				TPS80031_MISC2, val,
+				MISC2_LDOUSB_IN_MASK);
+			if (ret < 0) {
+				dev_err(ri->dev,
+					"LDOUSB config failed, e= %d\n", ret);
+				return ret;
+			}
+		}
+		break;
+
+	case TPS80031_REGULATOR_LDO3:
+		if (ri->config_flags & TPS80031_LDO3_OUTPUT_VIB) {
+			ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
+				TPS80031_MISC2, MISC2_LDO3_SEL_VIB_VAL,
+				MISC2_LDO3_SEL_VIB_MASK);
+			if (ret < 0) {
+				dev_err(ri->dev,
+					"LDO3 config failed, e = %d\n", ret);
+				return ret;
+			}
+		}
+		break;
+
+	case TPS80031_REGULATOR_VBUS:
+		/* Provide SW control Ops if VBUS is SW control */
+		if (!(ri->config_flags & TPS80031_VBUS_SW_ONLY))
+			ri->rinfo->desc.ops = &tps80031_vbus_sw_ops;
+		break;
+	default:
+		break;
+	}
+
+	/* Configure Active state to ON, SLEEP to OFF and OFF_state to OFF */
+	ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->trans_reg,
+		TPS80031_TRANS_ACTIVE_ON | TPS80031_TRANS_SLEEP_OFF |
+		TPS80031_TRANS_OFF_OFF, TPS80031_TRANS_ACTIVE_MASK |
+		TPS80031_TRANS_SLEEP_MASK | TPS80031_TRANS_OFF_MASK);
+	if (ret < 0) {
+		dev_err(ri->dev, "trans reg update failed, e %d\n", ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int check_smps_mode_mult(struct device *parent,
+	struct tps80031_regulator *ri)
+{
+	int mult_offset;
+	int ret;
+	u8 smps_offset;
+	u8 smps_mult;
+
+	ret = tps80031_read(parent, TPS80031_SLAVE_ID1,
+			TPS80031_SMPS_OFFSET, &smps_offset);
+	if (ret < 0) {
+		dev_err(parent, "Error in reading smps offset register\n");
+		return ret;
+	}
+
+	ret = tps80031_read(parent, TPS80031_SLAVE_ID1,
+			TPS80031_SMPS_MULT, &smps_mult);
+	if (ret < 0) {
+		dev_err(parent, "Error in reading smps mult register\n");
+		return ret;
+	}
+
+	switch (ri->rinfo->desc.id) {
+	case TPS80031_REGULATOR_VIO:
+		mult_offset = SMPS_MULTOFFSET_VIO;
+		break;
+	case TPS80031_REGULATOR_SMPS1:
+		mult_offset = SMPS_MULTOFFSET_SMPS1;
+		break;
+	case TPS80031_REGULATOR_SMPS2:
+		mult_offset = SMPS_MULTOFFSET_SMPS2;
+		break;
+	case TPS80031_REGULATOR_SMPS3:
+		mult_offset = SMPS_MULTOFFSET_SMPS3;
+		break;
+	case TPS80031_REGULATOR_SMPS4:
+		mult_offset = SMPS_MULTOFFSET_SMPS4;
+		break;
+	case TPS80031_REGULATOR_LDO2:
+		ri->device_flags = smps_mult & BIT(5) ? TRACK_MODE_ENABLE : 0;
+		/* TRACK mode the ldo2 varies from 600mV to 1300mV */
+		if (ri->device_flags & TRACK_MODE_ENABLE) {
+			ri->rinfo->desc.min_uV = 600000;
+			ri->rinfo->desc.uV_step = 12500;
+			ri->rinfo->desc.n_voltages = 57;
+			ri->rinfo->desc.vsel_mask = LDO_TRACK_VSEL_MASK;
+		}
+		return 0;
+	default:
+		return 0;
+	}
+
+	ri->device_flags = (smps_offset & mult_offset) ? DCDC_OFFSET_EN : 0;
+	ri->device_flags |= (smps_mult & mult_offset) ? DCDC_EXTENDED_EN : 0;
+	switch (ri->device_flags) {
+	case 0:
+		ri->rinfo->desc.min_uV = 607700;
+		ri->rinfo->desc.uV_step = 12660;
+		break;
+	case DCDC_OFFSET_EN:
+		ri->rinfo->desc.min_uV = 700000;
+		ri->rinfo->desc.uV_step = 12500;
+		break;
+	case DCDC_EXTENDED_EN:
+		ri->rinfo->desc.min_uV = 1852000;
+		ri->rinfo->desc.uV_step = 38600;
+		break;
+	case DCDC_OFFSET_EN | DCDC_EXTENDED_EN:
+		ri->rinfo->desc.min_uV = 2161000;
+		ri->rinfo->desc.uV_step = 38600;
+		break;
+	}
+	return 0;
+}
+
+static int tps80031_regulator_probe(struct platform_device *pdev)
+{
+	struct tps80031_platform_data *pdata;
+	struct tps80031_regulator_platform_data *tps_pdata;
+	struct tps80031_regulator *ri;
+	struct tps80031_regulator *pmic;
+	struct regulator_dev *rdev;
+	struct regulator_config config = { };
+	int ret;
+	int num;
+
+	pdata = dev_get_platdata(pdev->dev.parent);
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "No platform data\n");
+		return -EINVAL;
+	}
+
+	pmic = devm_kzalloc(&pdev->dev,
+			TPS80031_REGULATOR_MAX * sizeof(*pmic), GFP_KERNEL);
+	if (!pmic) {
+		dev_err(&pdev->dev, "mem alloc for pmic failed\n");
+		return -ENOMEM;
+	}
+
+	for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) {
+		tps_pdata = pdata->regulator_pdata[num];
+		ri = &pmic[num];
+		ri->rinfo = &tps80031_rinfo[num];
+		ri->dev = &pdev->dev;
+
+		check_smps_mode_mult(pdev->dev.parent, ri);
+		config.dev = &pdev->dev;
+		config.init_data = NULL;
+		config.driver_data = ri;
+		if (tps_pdata) {
+			config.init_data = tps_pdata->reg_init_data;
+			ri->config_flags = tps_pdata->config_flags;
+			ri->ext_ctrl_flag = tps_pdata->ext_ctrl_flag;
+			ret = tps80031_regulator_config(pdev->dev.parent,
+					ri, tps_pdata);
+			if (ret < 0) {
+				dev_err(&pdev->dev,
+					"regulator config failed, e %d\n", ret);
+				goto fail;
+			}
+
+			ret = tps80031_power_req_config(pdev->dev.parent,
+					ri, tps_pdata);
+			if (ret < 0) {
+				dev_err(&pdev->dev,
+					"pwr_req config failed, err %d\n", ret);
+				goto fail;
+			}
+		}
+		rdev = regulator_register(&ri->rinfo->desc, &config);
+		if (IS_ERR_OR_NULL(rdev)) {
+			dev_err(&pdev->dev,
+				"register regulator failed %s\n",
+					ri->rinfo->desc.name);
+			ret = PTR_ERR(rdev);
+			goto fail;
+		}
+		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 = {
+	.driver	= {
+		.name	= "tps80031-pmic",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= tps80031_regulator_probe,
+	.remove		= tps80031_regulator_remove,
+};
+
+static int __init tps80031_regulator_init(void)
+{
+	return platform_driver_register(&tps80031_regulator_driver);
+}
+subsys_initcall(tps80031_regulator_init);
+
+static void __exit tps80031_regulator_exit(void)
+{
+	platform_driver_unregister(&tps80031_regulator_driver);
+}
+module_exit(tps80031_regulator_exit);
+
+MODULE_ALIAS("platform:tps80031-regulator");
+MODULE_DESCRIPTION("Regulator Driver for TI TPS80031/TPS80032 PMIC");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 7eb986a..493c8c6 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -1116,7 +1116,7 @@ static const struct of_device_id twl_of_match[] __devinitconst = {
 };
 MODULE_DEVICE_TABLE(of, twl_of_match);
 
-static int __devinit twlreg_probe(struct platform_device *pdev)
+static int twlreg_probe(struct platform_device *pdev)
 {
 	int				i, id;
 	struct twlreg_info		*info;
@@ -1241,7 +1241,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit twlreg_remove(struct platform_device *pdev)
+static int twlreg_remove(struct platform_device *pdev)
 {
 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
 	struct twlreg_info *info = rdev->reg_data;
@@ -1255,7 +1255,7 @@ MODULE_ALIAS("platform:twl_reg");
 
 static struct platform_driver twlreg_driver = {
 	.probe		= twlreg_probe,
-	.remove		= __devexit_p(twlreg_remove),
+	.remove		= twlreg_remove,
 	/* NOTE: short name, to work around driver model truncation of
 	 * "twl_regulator.12" (and friends) to "twl_regulator.1".
 	 */
diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c
new file mode 100644
index 0000000..4668c7f
--- /dev/null
+++ b/drivers/regulator/vexpress.c
@@ -0,0 +1,147 @@
+/*
+ * This program is free software; you can 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#define DRVNAME "vexpress-regulator"
+#define pr_fmt(fmt) DRVNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/vexpress.h>
+
+struct vexpress_regulator {
+	struct regulator_desc desc;
+	struct regulator_dev *regdev;
+	struct vexpress_config_func *func;
+};
+
+static int vexpress_regulator_get_voltage(struct regulator_dev *regdev)
+{
+	struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
+	u32 uV;
+	int err = vexpress_config_read(reg->func, 0, &uV);
+
+	return err ? err : uV;
+}
+
+static int vexpress_regulator_set_voltage(struct regulator_dev *regdev,
+		int min_uV, int max_uV, unsigned *selector)
+{
+	struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
+
+	return vexpress_config_write(reg->func, 0, min_uV);
+}
+
+static struct regulator_ops vexpress_regulator_ops_ro = {
+	.get_voltage = vexpress_regulator_get_voltage,
+};
+
+static struct regulator_ops vexpress_regulator_ops = {
+	.get_voltage = vexpress_regulator_get_voltage,
+	.set_voltage = vexpress_regulator_set_voltage,
+};
+
+static int vexpress_regulator_probe(struct platform_device *pdev)
+{
+	int err;
+	struct vexpress_regulator *reg;
+	struct regulator_init_data *init_data;
+	struct regulator_config config = { };
+
+	reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL);
+	if (!reg) {
+		err = -ENOMEM;
+		goto error_kzalloc;
+	}
+
+	reg->func = vexpress_config_func_get_by_dev(&pdev->dev);
+	if (!reg->func) {
+		err = -ENXIO;
+		goto error_get_func;
+	}
+
+	reg->desc.name = dev_name(&pdev->dev);
+	reg->desc.type = REGULATOR_VOLTAGE;
+	reg->desc.owner = THIS_MODULE;
+	reg->desc.continuous_voltage_range = true;
+
+	init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
+	if (!init_data) {
+		err = -EINVAL;
+		goto error_get_regulator_init_data;
+	}
+
+	init_data->constraints.apply_uV = 0;
+	if (init_data->constraints.min_uV && init_data->constraints.max_uV)
+		reg->desc.ops = &vexpress_regulator_ops;
+	else
+		reg->desc.ops = &vexpress_regulator_ops_ro;
+
+	config.dev = &pdev->dev;
+	config.init_data = init_data;
+	config.driver_data = reg;
+	config.of_node = pdev->dev.of_node;
+
+	reg->regdev = regulator_register(&reg->desc, &config);
+	if (IS_ERR(reg->regdev)) {
+		err = PTR_ERR(reg->regdev);
+		goto error_regulator_register;
+	}
+
+	platform_set_drvdata(pdev, reg);
+
+	return 0;
+
+error_regulator_register:
+error_get_regulator_init_data:
+	vexpress_config_func_put(reg->func);
+error_get_func:
+error_kzalloc:
+	return err;
+}
+
+static int vexpress_regulator_remove(struct platform_device *pdev)
+{
+	struct vexpress_regulator *reg = platform_get_drvdata(pdev);
+
+	vexpress_config_func_put(reg->func);
+	regulator_unregister(reg->regdev);
+
+	return 0;
+}
+
+static struct of_device_id vexpress_regulator_of_match[] = {
+	{ .compatible = "arm,vexpress-volt", },
+	{ }
+};
+
+static struct platform_driver vexpress_regulator_driver = {
+	.probe = vexpress_regulator_probe,
+	.remove = vexpress_regulator_remove,
+	.driver	= {
+		.name = DRVNAME,
+		.owner = THIS_MODULE,
+		.of_match_table = vexpress_regulator_of_match,
+	},
+};
+
+module_platform_driver(vexpress_regulator_driver);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_DESCRIPTION("Versatile Express regulator");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:vexpress-regulator");
diff --git a/drivers/regulator/virtual.c b/drivers/regulator/virtual.c
index c038e74..01c66e9 100644
--- a/drivers/regulator/virtual.c
+++ b/drivers/regulator/virtual.c
@@ -285,7 +285,7 @@ static const struct attribute_group regulator_virtual_attr_group = {
 	.attrs	= regulator_virtual_attributes,
 };
 
-static int __devinit regulator_virtual_probe(struct platform_device *pdev)
+static int regulator_virtual_probe(struct platform_device *pdev)
 {
 	char *reg_id = pdev->dev.platform_data;
 	struct virtual_consumer_data *drvdata;
@@ -321,7 +321,7 @@ static int __devinit regulator_virtual_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit regulator_virtual_remove(struct platform_device *pdev)
+static int regulator_virtual_remove(struct platform_device *pdev)
 {
 	struct virtual_consumer_data *drvdata = platform_get_drvdata(pdev);
 
@@ -337,7 +337,7 @@ static int __devexit regulator_virtual_remove(struct platform_device *pdev)
 
 static struct platform_driver regulator_virtual_consumer_driver = {
 	.probe		= regulator_virtual_probe,
-	.remove		= __devexit_p(regulator_virtual_remove),
+	.remove		= regulator_virtual_remove,
 	.driver		= {
 		.name		= "reg-virt-consumer",
 		.owner		= THIS_MODULE,
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index 782c228..bce2565 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -290,7 +290,7 @@ static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev,
 	if (vsel > dcdc->dvs_vsel) {
 		ret = wm831x_set_bits(wm831x, dvs_reg,
 				      WM831X_DC1_DVS_VSEL_MASK,
-				      dcdc->dvs_vsel);
+				      vsel);
 		if (ret == 0)
 			dcdc->dvs_vsel = vsel;
 		else
@@ -387,7 +387,7 @@ static struct regulator_ops wm831x_buckv_ops = {
  * Set up DVS control.  We just log errors since we can still run
  * (with reduced performance) if we fail.
  */
-static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
+static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
 					    struct wm831x_buckv_pdata *pdata)
 {
 	struct wm831x *wm831x = dcdc->wm831x;
@@ -448,7 +448,7 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
 	}
 }
 
-static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
+static int wm831x_buckv_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -562,7 +562,7 @@ err:
 	return ret;
 }
 
-static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
+static int wm831x_buckv_remove(struct platform_device *pdev)
 {
 	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 	struct wm831x *wm831x = dcdc->wm831x;
@@ -582,7 +582,7 @@ static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_buckv_driver = {
 	.probe = wm831x_buckv_probe,
-	.remove = __devexit_p(wm831x_buckv_remove),
+	.remove = wm831x_buckv_remove,
 	.driver		= {
 		.name	= "wm831x-buckv",
 		.owner	= THIS_MODULE,
@@ -623,7 +623,7 @@ static struct regulator_ops wm831x_buckp_ops = {
 	.set_suspend_mode = wm831x_dcdc_set_suspend_mode,
 };
 
-static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
+static int wm831x_buckp_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -710,7 +710,7 @@ err:
 	return ret;
 }
 
-static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
+static int wm831x_buckp_remove(struct platform_device *pdev)
 {
 	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 
@@ -725,7 +725,7 @@ static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_buckp_driver = {
 	.probe = wm831x_buckp_probe,
-	.remove = __devexit_p(wm831x_buckp_remove),
+	.remove = wm831x_buckp_remove,
 	.driver		= {
 		.name	= "wm831x-buckp",
 		.owner	= THIS_MODULE,
@@ -771,7 +771,7 @@ static struct regulator_ops wm831x_boostp_ops = {
 	.disable = regulator_disable_regmap,
 };
 
-static __devinit int wm831x_boostp_probe(struct platform_device *pdev)
+static int wm831x_boostp_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -845,7 +845,7 @@ err:
 	return ret;
 }
 
-static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
+static int wm831x_boostp_remove(struct platform_device *pdev)
 {
 	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 
@@ -860,7 +860,7 @@ static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_boostp_driver = {
 	.probe = wm831x_boostp_probe,
-	.remove = __devexit_p(wm831x_boostp_remove),
+	.remove = wm831x_boostp_remove,
 	.driver		= {
 		.name	= "wm831x-boostp",
 		.owner	= THIS_MODULE,
@@ -883,7 +883,7 @@ static struct regulator_ops wm831x_epe_ops = {
 	.get_status = wm831x_dcdc_get_status,
 };
 
-static __devinit int wm831x_epe_probe(struct platform_device *pdev)
+static int wm831x_epe_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -936,7 +936,7 @@ err:
 	return ret;
 }
 
-static __devexit int wm831x_epe_remove(struct platform_device *pdev)
+static int wm831x_epe_remove(struct platform_device *pdev)
 {
 	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 
@@ -948,7 +948,7 @@ static __devexit int wm831x_epe_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_epe_driver = {
 	.probe = wm831x_epe_probe,
-	.remove = __devexit_p(wm831x_epe_remove),
+	.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 2646a19..68586ee 100644
--- a/drivers/regulator/wm831x-isink.c
+++ b/drivers/regulator/wm831x-isink.c
@@ -148,7 +148,7 @@ static irqreturn_t wm831x_isink_irq(int irq, void *data)
 }
 
 
-static __devinit int wm831x_isink_probe(struct platform_device *pdev)
+static int wm831x_isink_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -221,7 +221,7 @@ err:
 	return ret;
 }
 
-static __devexit int wm831x_isink_remove(struct platform_device *pdev)
+static int wm831x_isink_remove(struct platform_device *pdev)
 {
 	struct wm831x_isink *isink = platform_get_drvdata(pdev);
 
@@ -236,7 +236,7 @@ static __devexit int wm831x_isink_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_isink_driver = {
 	.probe = wm831x_isink_probe,
-	.remove = __devexit_p(wm831x_isink_remove),
+	.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 c2dc039..1ec379a 100644
--- a/drivers/regulator/wm831x-ldo.c
+++ b/drivers/regulator/wm831x-ldo.c
@@ -247,7 +247,7 @@ static struct regulator_ops wm831x_gp_ldo_ops = {
 	.disable = regulator_disable_regmap,
 };
 
-static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
+static int wm831x_gp_ldo_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -334,7 +334,7 @@ err:
 	return ret;
 }
 
-static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
+static int wm831x_gp_ldo_remove(struct platform_device *pdev)
 {
 	struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -349,7 +349,7 @@ static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_gp_ldo_driver = {
 	.probe = wm831x_gp_ldo_probe,
-	.remove = __devexit_p(wm831x_gp_ldo_remove),
+	.remove = wm831x_gp_ldo_remove,
 	.driver		= {
 		.name	= "wm831x-ldo",
 		.owner	= THIS_MODULE,
@@ -504,7 +504,7 @@ static struct regulator_ops wm831x_aldo_ops = {
 	.disable = regulator_disable_regmap,
 };
 
-static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
+static int wm831x_aldo_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -590,7 +590,7 @@ err:
 	return ret;
 }
 
-static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
+static int wm831x_aldo_remove(struct platform_device *pdev)
 {
 	struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -603,7 +603,7 @@ static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_aldo_driver = {
 	.probe = wm831x_aldo_probe,
-	.remove = __devexit_p(wm831x_aldo_remove),
+	.remove = wm831x_aldo_remove,
 	.driver		= {
 		.name	= "wm831x-aldo",
 		.owner	= THIS_MODULE,
@@ -660,7 +660,7 @@ static struct regulator_ops wm831x_alive_ldo_ops = {
 	.disable = regulator_disable_regmap,
 };
 
-static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
+static int wm831x_alive_ldo_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -737,7 +737,7 @@ err:
 	return ret;
 }
 
-static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
+static int wm831x_alive_ldo_remove(struct platform_device *pdev)
 {
 	struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -748,7 +748,7 @@ static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_alive_ldo_driver = {
 	.probe = wm831x_alive_ldo_probe,
-	.remove = __devexit_p(wm831x_alive_ldo_remove),
+	.remove = wm831x_alive_ldo_remove,
 	.driver		= {
 		.name	= "wm831x-alive-ldo",
 		.owner	= THIS_MODULE,
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
index 27c746e..c6a32ea 100644
--- a/drivers/regulator/wm8400-regulator.c
+++ b/drivers/regulator/wm8400-regulator.c
@@ -226,7 +226,7 @@ static struct regulator_desc regulators[] = {
 	},
 };
 
-static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
+static int wm8400_regulator_probe(struct platform_device *pdev)
 {
 	struct wm8400 *wm8400 = container_of(pdev, struct wm8400, regulators[pdev->id]);
 	struct regulator_config config = { };
@@ -246,7 +246,7 @@ static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit wm8400_regulator_remove(struct platform_device *pdev)
+static int wm8400_regulator_remove(struct platform_device *pdev)
 {
 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -261,7 +261,7 @@ static struct platform_driver wm8400_regulator_driver = {
 		.name = "wm8400-regulator",
 	},
 	.probe = wm8400_regulator_probe,
-	.remove = __devexit_p(wm8400_regulator_remove),
+	.remove = wm8400_regulator_remove,
 };
 
 /**
diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
index 86bb48d..6ff8723 100644
--- a/drivers/regulator/wm8994-regulator.c
+++ b/drivers/regulator/wm8994-regulator.c
@@ -99,7 +99,7 @@ static const struct regulator_desc wm8994_ldo_desc[] = {
 	},
 };
 
-static __devinit int wm8994_ldo_probe(struct platform_device *pdev)
+static int wm8994_ldo_probe(struct platform_device *pdev)
 {
 	struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
 	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
@@ -142,7 +142,7 @@ err:
 	return ret;
 }
 
-static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
+static int wm8994_ldo_remove(struct platform_device *pdev)
 {
 	struct wm8994_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -155,7 +155,7 @@ static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
 
 static struct platform_driver wm8994_ldo_driver = {
 	.probe = wm8994_ldo_probe,
-	.remove = __devexit_p(wm8994_ldo_remove),
+	.remove = wm8994_ldo_remove,
 	.driver		= {
 		.name	= "wm8994-ldo",
 		.owner	= THIS_MODULE,
diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index 2bd911f..f6e0ea6 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -1,9 +1,8 @@
-menu "Rpmsg drivers (EXPERIMENTAL)"
+menu "Rpmsg drivers"
 
 # RPMSG always gets selected by whoever wants it
 config RPMSG
 	tristate
 	select VIRTIO
-	depends on EXPERIMENTAL
 
 endmenu
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 1859f71..027096f 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -764,7 +764,7 @@ int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst,
 
 	/* add message to the remote processor's virtqueue */
 	err = virtqueue_add_buf(vrp->svq, &sg, 1, 0, msg, GFP_KERNEL);
-	if (err < 0) {
+	if (err) {
 		/*
 		 * need to reclaim the buffer here, otherwise it's lost
 		 * (memory won't leak, but rpmsg won't use it again for TX).
@@ -776,8 +776,6 @@ int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst,
 
 	/* tell the remote processor it has a pending message to read */
 	virtqueue_kick(vrp->svq);
-
-	err = 0;
 out:
 	mutex_unlock(&vrp->tx_lock);
 	return err;
@@ -980,7 +978,7 @@ static int rpmsg_probe(struct virtio_device *vdev)
 
 		err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, cpu_addr,
 								GFP_KERNEL);
-		WARN_ON(err < 0); /* sanity check; this can't really happen */
+		WARN_ON(err); /* sanity check; this can't really happen */
 	}
 
 	/* suppress "tx-complete" interrupts */
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 19c03ab..5bb0314 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -269,6 +269,15 @@ config RTC_DRV_X1205
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-x1205.
 
+config RTC_DRV_PCF8523
+	tristate "NXP PCF8523"
+	help
+	  If you say yes here you get support for the NXP PCF8523 RTC
+	  chips.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-pcf8523.
+
 config RTC_DRV_PCF8563
 	tristate "Philips PCF8563/Epson RTC8564"
 	help
@@ -768,7 +777,7 @@ config RTC_DRV_DAVINCI
 
 config RTC_DRV_IMXDI
 	tristate "Freescale IMX DryIce Real Time Clock"
-	depends on SOC_IMX25
+	depends on ARCH_MXC
 	help
 	   Support for Freescale IMX DryIce RTC
 
@@ -777,11 +786,13 @@ config RTC_DRV_IMXDI
 
 config RTC_DRV_OMAP
 	tristate "TI OMAP1"
-	depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX
+	depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX || SOC_AM33XX
 	help
-	  Say "yes" here to support the real time clock on TI OMAP1 and
-	  DA8xx/OMAP-L13x chips.  This driver can also be built as a
-	  module called rtc-omap.
+	  Say "yes" here to support the on chip real time clock
+	  present on TI OMAP1, AM33xx and DA8xx/OMAP-L13x.
+
+	  This driver can also be built as a module, if so, module
+	  will be called rtc-omap.
 
 config HAVE_S3C_RTC
 	bool
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 56297f0..59e2132 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_RTC_DRV_MV)	+= rtc-mv.o
 obj-$(CONFIG_RTC_DRV_NUC900)	+= rtc-nuc900.o
 obj-$(CONFIG_RTC_DRV_OMAP)	+= rtc-omap.o
 obj-$(CONFIG_RTC_DRV_PCAP)	+= rtc-pcap.o
+obj-$(CONFIG_RTC_DRV_PCF8523)	+= rtc-pcf8523.o
 obj-$(CONFIG_RTC_DRV_PCF8563)	+= rtc-pcf8563.o
 obj-$(CONFIG_RTC_DRV_PCF8583)	+= rtc-pcf8583.o
 obj-$(CONFIG_RTC_DRV_PCF2123)	+= rtc-pcf2123.o
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index fca9790..b6469e2 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -31,7 +31,7 @@
 
 #include <asm/uaccess.h>
 
-#include <mach/at91_rtc.h>
+#include "rtc-at91rm9200.h"
 
 #define at91_rtc_read(field) \
 	__raw_readl(at91_rtc_regs + field)
diff --git a/drivers/rtc/rtc-at91rm9200.h b/drivers/rtc/rtc-at91rm9200.h
new file mode 100644
index 0000000..da1945e
--- /dev/null
+++ b/drivers/rtc/rtc-at91rm9200.h
@@ -0,0 +1,75 @@
+/*
+ * arch/arm/mach-at91/include/mach/at91_rtc.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Real Time Clock (RTC) - System peripheral registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 AT91_RTC_H
+#define AT91_RTC_H
+
+#define	AT91_RTC_CR		0x00			/* Control Register */
+#define		AT91_RTC_UPDTIM		(1 <<  0)		/* Update Request Time Register */
+#define		AT91_RTC_UPDCAL		(1 <<  1)		/* Update Request Calendar Register */
+#define		AT91_RTC_TIMEVSEL	(3 <<  8)		/* Time Event Selection */
+#define			AT91_RTC_TIMEVSEL_MINUTE	(0 << 8)
+#define			AT91_RTC_TIMEVSEL_HOUR		(1 << 8)
+#define			AT91_RTC_TIMEVSEL_DAY24		(2 << 8)
+#define			AT91_RTC_TIMEVSEL_DAY12		(3 << 8)
+#define		AT91_RTC_CALEVSEL	(3 << 16)		/* Calendar Event Selection */
+#define			AT91_RTC_CALEVSEL_WEEK		(0 << 16)
+#define			AT91_RTC_CALEVSEL_MONTH		(1 << 16)
+#define			AT91_RTC_CALEVSEL_YEAR		(2 << 16)
+
+#define	AT91_RTC_MR		0x04			/* Mode Register */
+#define			AT91_RTC_HRMOD		(1 <<  0)		/* 12/24 Hour Mode */
+
+#define	AT91_RTC_TIMR		0x08			/* Time Register */
+#define		AT91_RTC_SEC		(0x7f <<  0)		/* Current Second */
+#define		AT91_RTC_MIN		(0x7f <<  8)		/* Current Minute */
+#define		AT91_RTC_HOUR		(0x3f << 16)		/* Current Hour */
+#define		AT91_RTC_AMPM		(1    << 22)		/* Ante Meridiem Post Meridiem Indicator */
+
+#define	AT91_RTC_CALR		0x0c			/* Calendar Register */
+#define		AT91_RTC_CENT		(0x7f <<  0)		/* Current Century */
+#define		AT91_RTC_YEAR		(0xff <<  8)		/* Current Year */
+#define		AT91_RTC_MONTH		(0x1f << 16)		/* Current Month */
+#define		AT91_RTC_DAY		(7    << 21)		/* Current Day */
+#define		AT91_RTC_DATE		(0x3f << 24)		/* Current Date */
+
+#define	AT91_RTC_TIMALR		0x10			/* Time Alarm Register */
+#define		AT91_RTC_SECEN		(1 <<  7)		/* Second Alarm Enable */
+#define		AT91_RTC_MINEN		(1 << 15)		/* Minute Alarm Enable */
+#define		AT91_RTC_HOUREN		(1 << 23)		/* Hour Alarm Enable */
+
+#define	AT91_RTC_CALALR		0x14			/* Calendar Alarm Register */
+#define		AT91_RTC_MTHEN		(1 << 23)		/* Month Alarm Enable */
+#define		AT91_RTC_DATEEN		(1 << 31)		/* Date Alarm Enable */
+
+#define	AT91_RTC_SR		0x18			/* Status Register */
+#define		AT91_RTC_ACKUPD		(1 <<  0)		/* Acknowledge for Update */
+#define		AT91_RTC_ALARM		(1 <<  1)		/* Alarm Flag */
+#define		AT91_RTC_SECEV		(1 <<  2)		/* Second Event */
+#define		AT91_RTC_TIMEV		(1 <<  3)		/* Time Event */
+#define		AT91_RTC_CALEV		(1 <<  4)		/* Calendar Event */
+
+#define	AT91_RTC_SCCR		0x1c			/* Status Clear Command Register */
+#define	AT91_RTC_IER		0x20			/* Interrupt Enable Register */
+#define	AT91_RTC_IDR		0x24			/* Interrupt Disable Register */
+#define	AT91_RTC_IMR		0x28			/* Interrupt Mask Register */
+
+#define	AT91_RTC_VER		0x2c			/* Valid Entry Register */
+#define		AT91_RTC_NVTIM		(1 <<  0)		/* Non valid Time */
+#define		AT91_RTC_NVCAL		(1 <<  1)		/* Non valid Calendar */
+#define		AT91_RTC_NVTIMALR	(1 <<  2)		/* Non valid Time Alarm */
+#define		AT91_RTC_NVCALALR	(1 <<  3)		/* Non valid Calendar Alarm */
+
+#endif
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 2dfe7a2..e981798 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -19,8 +19,8 @@
 #include <linux/interrupt.h>
 #include <linux/ioctl.h>
 #include <linux/slab.h>
+#include <linux/platform_data/atmel.h>
 
-#include <mach/board.h>
 #include <mach/at91_rtt.h>
 #include <mach/cpu.h>
 
diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c
index 14c2109..07cd03e 100644
--- a/drivers/rtc/rtc-davinci.c
+++ b/drivers/rtc/rtc-davinci.c
@@ -485,7 +485,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
 	struct resource *res, *mem;
 	int ret = 0;
 
-	davinci_rtc = kzalloc(sizeof(struct davinci_rtc), GFP_KERNEL);
+	davinci_rtc = devm_kzalloc(&pdev->dev, sizeof(struct davinci_rtc), GFP_KERNEL);
 	if (!davinci_rtc) {
 		dev_dbg(dev, "could not allocate memory for private data\n");
 		return -ENOMEM;
@@ -494,15 +494,13 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
 	davinci_rtc->irq = platform_get_irq(pdev, 0);
 	if (davinci_rtc->irq < 0) {
 		dev_err(dev, "no RTC irq\n");
-		ret = davinci_rtc->irq;
-		goto fail1;
+		return davinci_rtc->irq;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(dev, "no mem resource\n");
-		ret = -EINVAL;
-		goto fail1;
+		return -EINVAL;
 	}
 
 	davinci_rtc->pbase = res->start;
@@ -513,8 +511,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
 	if (!mem) {
 		dev_err(dev, "RTC registers at %08x are not free\n",
 			davinci_rtc->pbase);
-		ret = -EBUSY;
-		goto fail1;
+		return -EBUSY;
 	}
 
 	davinci_rtc->base = ioremap(davinci_rtc->pbase, davinci_rtc->base_size);
@@ -529,8 +526,9 @@ static int __init davinci_rtc_probe(struct platform_device *pdev)
 	davinci_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
 				    &davinci_rtc_ops, THIS_MODULE);
 	if (IS_ERR(davinci_rtc->rtc)) {
-		dev_err(dev, "unable to register RTC device, err %ld\n",
-				PTR_ERR(davinci_rtc->rtc));
+		ret = PTR_ERR(davinci_rtc->rtc);
+		dev_err(dev, "unable to register RTC device, err %d\n",
+				ret);
 		goto fail3;
 	}
 
@@ -566,9 +564,6 @@ fail3:
 	iounmap(davinci_rtc->base);
 fail2:
 	release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size);
-fail1:
-	kfree(davinci_rtc);
-
 	return ret;
 }
 
@@ -589,8 +584,6 @@ static int __devexit davinci_rtc_remove(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, NULL);
 
-	kfree(davinci_rtc);
-
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index cace6d3..9a86b4b 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -379,25 +379,6 @@ static long rtc_dev_ioctl(struct file *file,
 		err = put_user(rtc->irq_freq, (unsigned long __user *)uarg);
 		break;
 
-#if 0
-	case RTC_EPOCH_SET:
-#ifndef rtc_epoch
-		/*
-		 * There were no RTC clocks before 1900.
-		 */
-		if (arg < 1900) {
-			err = -EINVAL;
-			break;
-		}
-		rtc_epoch = arg;
-		err = 0;
-#endif
-		break;
-
-	case RTC_EPOCH_READ:
-		err = put_user(rtc_epoch, (unsigned long __user *)uarg);
-		break;
-#endif
 	case RTC_WKALM_SET:
 		mutex_unlock(&rtc->ops_lock);
 		if (copy_from_user(&alarm, uarg, sizeof(alarm)))
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c
index 4eed510..18a4f0d 100644
--- a/drivers/rtc/rtc-imxdi.c
+++ b/drivers/rtc/rtc-imxdi.c
@@ -37,6 +37,7 @@
 #include <linux/rtc.h>
 #include <linux/sched.h>
 #include <linux/workqueue.h>
+#include <linux/of.h>
 
 /* DryIce Register Definitions */
 
@@ -495,10 +496,20 @@ static int __devexit dryice_rtc_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id dryice_dt_ids[] = {
+	{ .compatible = "fsl,imx25-rtc" },
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, dryice_dt_ids);
+#endif
+
 static struct platform_driver dryice_rtc_driver = {
 	.driver = {
 		   .name = "imxdi_rtc",
 		   .owner = THIS_MODULE,
+		   .of_match_table = of_match_ptr(dryice_dt_ids),
 		   },
 	.remove = __devexit_p(dryice_rtc_remove),
 };
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c
index 26c81f2..afb7cfa 100644
--- a/drivers/rtc/rtc-isl1208.c
+++ b/drivers/rtc/rtc-isl1208.c
@@ -118,7 +118,7 @@ isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[],
 	return ret;
 }
 
-/* simple check to see wether we have a isl1208 */
+/* simple check to see whether we have a isl1208 */
 static int
 isl1208_i2c_validate_client(struct i2c_client *client)
 {
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c
index cd01062..7304139 100644
--- a/drivers/rtc/rtc-mxc.c
+++ b/drivers/rtc/rtc-mxc.c
@@ -17,8 +17,6 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 
-#include <mach/hardware.h>
-
 #define RTC_INPUT_CLK_32768HZ	(0x00 << 5)
 #define RTC_INPUT_CLK_32000HZ	(0x01 << 5)
 #define RTC_INPUT_CLK_38400HZ	(0x02 << 5)
@@ -72,14 +70,38 @@ static const u32 PIE_BIT_DEF[MAX_PIE_NUM][2] = {
 #define RTC_TEST2	0x2C	/*  32bit rtc test reg 2 */
 #define RTC_TEST3	0x30	/*  32bit rtc test reg 3 */
 
+enum imx_rtc_type {
+	IMX1_RTC,
+	IMX21_RTC,
+};
+
 struct rtc_plat_data {
 	struct rtc_device *rtc;
 	void __iomem *ioaddr;
 	int irq;
 	struct clk *clk;
 	struct rtc_time g_rtc_alarm;
+	enum imx_rtc_type devtype;
 };
 
+static struct platform_device_id imx_rtc_devtype[] = {
+	{
+		.name = "imx1-rtc",
+		.driver_data = IMX1_RTC,
+	}, {
+		.name = "imx21-rtc",
+		.driver_data = IMX21_RTC,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, imx_rtc_devtype);
+
+static inline int is_imx1_rtc(struct rtc_plat_data *data)
+{
+	return data->devtype == IMX1_RTC;
+}
+
 /*
  * This function is used to obtain the RTC time or the alarm value in
  * second.
@@ -278,10 +300,13 @@ static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
  */
 static int mxc_rtc_set_mmss(struct device *dev, unsigned long time)
 {
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
 	/*
 	 * TTC_DAYR register is 9-bit in MX1 SoC, save time and day of year only
 	 */
-	if (cpu_is_mx1()) {
+	if (is_imx1_rtc(pdata)) {
 		struct rtc_time tm;
 
 		rtc_time_to_tm(time, &tm);
@@ -360,6 +385,8 @@ static int __devinit mxc_rtc_probe(struct platform_device *pdev)
 	if (!pdata)
 		return -ENOMEM;
 
+	pdata->devtype = pdev->id_entry->driver_data;
+
 	if (!devm_request_mem_region(&pdev->dev, res->start,
 				     resource_size(res), pdev->name))
 		return -EBUSY;
@@ -480,6 +507,7 @@ static struct platform_driver mxc_rtc_driver = {
 #endif
 		   .owner	= THIS_MODULE,
 	},
+	.id_table = imx_rtc_devtype,
 	.probe = mxc_rtc_probe,
 	.remove = __devexit_p(mxc_rtc_remove),
 };
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index 0b614e3..6009714 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -20,6 +20,9 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
 
 #include <asm/io.h>
 
@@ -38,6 +41,8 @@
  * the SoC). See the BOARD-SPECIFIC CUSTOMIZATION comment.
  */
 
+#define	DRIVER_NAME			"omap_rtc"
+
 #define OMAP_RTC_BASE			0xfffb4800
 
 /* RTC registers */
@@ -64,6 +69,9 @@
 #define OMAP_RTC_COMP_MSB_REG		0x50
 #define OMAP_RTC_OSC_REG		0x54
 
+#define OMAP_RTC_KICK0_REG		0x6c
+#define OMAP_RTC_KICK1_REG		0x70
+
 /* OMAP_RTC_CTRL_REG bit fields: */
 #define OMAP_RTC_CTRL_SPLIT		(1<<7)
 #define OMAP_RTC_CTRL_DISABLE		(1<<6)
@@ -88,10 +96,18 @@
 #define OMAP_RTC_INTERRUPTS_IT_ALARM    (1<<3)
 #define OMAP_RTC_INTERRUPTS_IT_TIMER    (1<<2)
 
+/* OMAP_RTC_KICKER values */
+#define	KICK0_VALUE			0x83e70b13
+#define	KICK1_VALUE			0x95a4f1e0
+
+#define	OMAP_RTC_HAS_KICKER		0x1
+
 static void __iomem	*rtc_base;
 
-#define rtc_read(addr)		__raw_readb(rtc_base + (addr))
-#define rtc_write(val, addr)	__raw_writeb(val, rtc_base + (addr))
+#define rtc_read(addr)		readb(rtc_base + (addr))
+#define rtc_write(val, addr)	writeb(val, rtc_base + (addr))
+
+#define rtc_writel(val, addr)	writel(val, rtc_base + (addr))
 
 
 /* we rely on the rtc framework to handle locking (rtc->ops_lock),
@@ -285,11 +301,38 @@ static struct rtc_class_ops omap_rtc_ops = {
 static int omap_rtc_alarm;
 static int omap_rtc_timer;
 
+#define	OMAP_RTC_DATA_DA830_IDX	1
+
+static struct platform_device_id omap_rtc_devtype[] = {
+	{
+		.name	= DRIVER_NAME,
+	}, {
+		.name	= "da830-rtc",
+		.driver_data = OMAP_RTC_HAS_KICKER,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(platform, omap_rtc_devtype);
+
+static const struct of_device_id omap_rtc_of_match[] = {
+	{	.compatible	= "ti,da830-rtc",
+		.data		= &omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX],
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
+
 static int __init omap_rtc_probe(struct platform_device *pdev)
 {
 	struct resource		*res, *mem;
 	struct rtc_device	*rtc;
 	u8			reg, new_ctrl;
+	const struct platform_device_id *id_entry;
+	const struct of_device_id *of_id;
+
+	of_id = of_match_device(omap_rtc_of_match, &pdev->dev);
+	if (of_id)
+		pdev->id_entry = of_id->data;
 
 	omap_rtc_timer = platform_get_irq(pdev, 0);
 	if (omap_rtc_timer <= 0) {
@@ -322,6 +365,16 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
 		goto fail;
 	}
 
+	/* Enable the clock/module so that we can access the registers */
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_sync(&pdev->dev);
+
+	id_entry = platform_get_device_id(pdev);
+	if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) {
+		rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG);
+		rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG);
+	}
+
 	rtc = rtc_device_register(pdev->name, &pdev->dev,
 			&omap_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc)) {
@@ -398,6 +451,10 @@ fail2:
 fail1:
 	rtc_device_unregister(rtc);
 fail0:
+	if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER))
+		rtc_writel(0, OMAP_RTC_KICK0_REG);
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
 	iounmap(rtc_base);
 fail:
 	release_mem_region(mem->start, resource_size(mem));
@@ -408,6 +465,8 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
 {
 	struct rtc_device	*rtc = platform_get_drvdata(pdev);
 	struct resource		*mem = dev_get_drvdata(&rtc->dev);
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(pdev);
 
 	device_init_wakeup(&pdev->dev, 0);
 
@@ -420,6 +479,13 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
 		free_irq(omap_rtc_alarm, rtc);
 
 	rtc_device_unregister(rtc);
+	if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER))
+		rtc_writel(0, OMAP_RTC_KICK0_REG);
+
+	/* Disable the clock/module */
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
 	iounmap(rtc_base);
 	release_mem_region(mem->start, resource_size(mem));
 	return 0;
@@ -442,11 +508,17 @@ static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state)
 	else
 		rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
 
+	/* Disable the clock/module */
+	pm_runtime_put_sync(&pdev->dev);
+
 	return 0;
 }
 
 static int omap_rtc_resume(struct platform_device *pdev)
 {
+	/* Enable the clock/module so that we can access the registers */
+	pm_runtime_get_sync(&pdev->dev);
+
 	if (device_may_wakeup(&pdev->dev))
 		disable_irq_wake(omap_rtc_alarm);
 	else
@@ -471,9 +543,11 @@ static struct platform_driver omap_rtc_driver = {
 	.resume		= omap_rtc_resume,
 	.shutdown	= omap_rtc_shutdown,
 	.driver		= {
-		.name	= "omap_rtc",
+		.name	= DRIVER_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(omap_rtc_of_match),
 	},
+	.id_table	= omap_rtc_devtype,
 };
 
 static int __init rtc_init(void)
diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c
new file mode 100644
index 0000000..be05a64
--- /dev/null
+++ b/drivers/rtc/rtc-pcf8523.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ *
+ * This program is free software; you can redistribute 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/bcd.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/of.h>
+
+#define DRIVER_NAME "rtc-pcf8523"
+
+#define REG_CONTROL1 0x00
+#define REG_CONTROL1_CAP_SEL (1 << 7)
+#define REG_CONTROL1_STOP    (1 << 5)
+
+#define REG_CONTROL3 0x02
+#define REG_CONTROL3_PM_BLD (1 << 7) /* battery low detection disabled */
+#define REG_CONTROL3_PM_VDD (1 << 6) /* switch-over disabled */
+#define REG_CONTROL3_PM_DSM (1 << 5) /* direct switching mode */
+#define REG_CONTROL3_PM_MASK 0xe0
+
+#define REG_SECONDS  0x03
+#define REG_SECONDS_OS (1 << 7)
+
+#define REG_MINUTES  0x04
+#define REG_HOURS    0x05
+#define REG_DAYS     0x06
+#define REG_WEEKDAYS 0x07
+#define REG_MONTHS   0x08
+#define REG_YEARS    0x09
+
+struct pcf8523 {
+	struct rtc_device *rtc;
+};
+
+static int pcf8523_read(struct i2c_client *client, u8 reg, u8 *valuep)
+{
+	struct i2c_msg msgs[2];
+	u8 value = 0;
+	int err;
+
+	msgs[0].addr = client->addr;
+	msgs[0].flags = 0;
+	msgs[0].len = sizeof(reg);
+	msgs[0].buf = &reg;
+
+	msgs[1].addr = client->addr;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].len = sizeof(value);
+	msgs[1].buf = &value;
+
+	err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+	if (err < 0)
+		return err;
+
+	*valuep = value;
+
+	return 0;
+}
+
+static int pcf8523_write(struct i2c_client *client, u8 reg, u8 value)
+{
+	u8 buffer[2] = { reg, value };
+	struct i2c_msg msg;
+	int err;
+
+	msg.addr = client->addr;
+	msg.flags = 0;
+	msg.len = sizeof(buffer);
+	msg.buf = buffer;
+
+	err = i2c_transfer(client->adapter, &msg, 1);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int pcf8523_select_capacitance(struct i2c_client *client, bool high)
+{
+	u8 value;
+	int err;
+
+	err = pcf8523_read(client, REG_CONTROL1, &value);
+	if (err < 0)
+		return err;
+
+	if (!high)
+		value &= ~REG_CONTROL1_CAP_SEL;
+	else
+		value |= REG_CONTROL1_CAP_SEL;
+
+	err = pcf8523_write(client, REG_CONTROL1, value);
+	if (err < 0)
+		return err;
+
+	return err;
+}
+
+static int pcf8523_set_pm(struct i2c_client *client, u8 pm)
+{
+	u8 value;
+	int err;
+
+	err = pcf8523_read(client, REG_CONTROL3, &value);
+	if (err < 0)
+		return err;
+
+	value = (value & ~REG_CONTROL3_PM_MASK) | pm;
+
+	err = pcf8523_write(client, REG_CONTROL3, value);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int pcf8523_stop_rtc(struct i2c_client *client)
+{
+	u8 value;
+	int err;
+
+	err = pcf8523_read(client, REG_CONTROL1, &value);
+	if (err < 0)
+		return err;
+
+	value |= REG_CONTROL1_STOP;
+
+	err = pcf8523_write(client, REG_CONTROL1, value);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int pcf8523_start_rtc(struct i2c_client *client)
+{
+	u8 value;
+	int err;
+
+	err = pcf8523_read(client, REG_CONTROL1, &value);
+	if (err < 0)
+		return err;
+
+	value &= ~REG_CONTROL1_STOP;
+
+	err = pcf8523_write(client, REG_CONTROL1, value);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	u8 start = REG_SECONDS, regs[7];
+	struct i2c_msg msgs[2];
+	int err;
+
+	msgs[0].addr = client->addr;
+	msgs[0].flags = 0;
+	msgs[0].len = 1;
+	msgs[0].buf = &start;
+
+	msgs[1].addr = client->addr;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].len = sizeof(regs);
+	msgs[1].buf = regs;
+
+	err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+	if (err < 0)
+		return err;
+
+	if (regs[0] & REG_SECONDS_OS) {
+		/*
+		 * If the oscillator was stopped, try to clear the flag. Upon
+		 * power-up the flag is always set, but if we cannot clear it
+		 * the oscillator isn't running properly for some reason. The
+		 * sensible thing therefore is to return an error, signalling
+		 * that the clock cannot be assumed to be correct.
+		 */
+
+		regs[0] &= ~REG_SECONDS_OS;
+
+		err = pcf8523_write(client, REG_SECONDS, regs[0]);
+		if (err < 0)
+			return err;
+
+		err = pcf8523_read(client, REG_SECONDS, &regs[0]);
+		if (err < 0)
+			return err;
+
+		if (regs[0] & REG_SECONDS_OS)
+			return -EAGAIN;
+	}
+
+	tm->tm_sec = bcd2bin(regs[0] & 0x7f);
+	tm->tm_min = bcd2bin(regs[1] & 0x7f);
+	tm->tm_hour = bcd2bin(regs[2] & 0x3f);
+	tm->tm_mday = bcd2bin(regs[3] & 0x3f);
+	tm->tm_wday = regs[4] & 0x7;
+	tm->tm_mon = bcd2bin(regs[5] & 0x1f);
+	tm->tm_year = bcd2bin(regs[6]) + 100;
+
+	return rtc_valid_tm(tm);
+}
+
+static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_msg msg;
+	u8 regs[8];
+	int err;
+
+	err = pcf8523_stop_rtc(client);
+	if (err < 0)
+		return err;
+
+	regs[0] = REG_SECONDS;
+	regs[1] = bin2bcd(tm->tm_sec);
+	regs[2] = bin2bcd(tm->tm_min);
+	regs[3] = bin2bcd(tm->tm_hour);
+	regs[4] = bin2bcd(tm->tm_mday);
+	regs[5] = tm->tm_wday;
+	regs[6] = bin2bcd(tm->tm_mon);
+	regs[7] = bin2bcd(tm->tm_year - 100);
+
+	msg.addr = client->addr;
+	msg.flags = 0;
+	msg.len = sizeof(regs);
+	msg.buf = regs;
+
+	err = i2c_transfer(client->adapter, &msg, 1);
+	if (err < 0) {
+		/*
+		 * If the time cannot be set, restart the RTC anyway. Note
+		 * that errors are ignored if the RTC cannot be started so
+		 * that we have a chance to propagate the original error.
+		 */
+		pcf8523_start_rtc(client);
+		return err;
+	}
+
+	return pcf8523_start_rtc(client);
+}
+
+static const struct rtc_class_ops pcf8523_rtc_ops = {
+	.read_time = pcf8523_rtc_read_time,
+	.set_time = pcf8523_rtc_set_time,
+};
+
+static int pcf8523_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct pcf8523 *pcf;
+	int err;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+		return -ENODEV;
+
+	pcf = devm_kzalloc(&client->dev, sizeof(*pcf), GFP_KERNEL);
+	if (!pcf)
+		return -ENOMEM;
+
+	err = pcf8523_select_capacitance(client, true);
+	if (err < 0)
+		return err;
+
+	err = pcf8523_set_pm(client, 0);
+	if (err < 0)
+		return err;
+
+	pcf->rtc = rtc_device_register(DRIVER_NAME, &client->dev,
+				       &pcf8523_rtc_ops, THIS_MODULE);
+	if (IS_ERR(pcf->rtc))
+		return PTR_ERR(pcf->rtc);
+
+	i2c_set_clientdata(client, pcf);
+
+	return 0;
+}
+
+static int pcf8523_remove(struct i2c_client *client)
+{
+	struct pcf8523 *pcf = i2c_get_clientdata(client);
+
+	rtc_device_unregister(pcf->rtc);
+
+	return 0;
+}
+
+static const struct i2c_device_id pcf8523_id[] = {
+	{ "pcf8523", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, pcf8523_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id pcf8523_of_match[] = {
+	{ .compatible = "nxp,pcf8523" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, pcf8523_of_match);
+#endif
+
+static struct i2c_driver pcf8523_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(pcf8523_of_match),
+	},
+	.probe = pcf8523_probe,
+	.remove = pcf8523_remove,
+	.id_table = pcf8523_id,
+};
+module_i2c_driver(pcf8523_driver);
+
+MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
+MODULE_DESCRIPTION("NXP PCF8523 RTC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 77823d2..e33df1b 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -47,8 +47,6 @@ struct s3c_rtc_drv_data {
 /* I have yet to find an S3C implementation with more than one
  * of these rtc blocks in */
 
-static struct resource *s3c_rtc_mem;
-
 static struct clk *rtc_clk;
 static void __iomem *s3c_rtc_base;
 static int s3c_rtc_alarmno = NO_IRQ;
@@ -186,7 +184,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
 	rtc_tm->tm_year = readb(base + S3C2410_RTCYEAR);
 	rtc_tm->tm_sec  = readb(base + S3C2410_RTCSEC);
 
-	/* the only way to work out wether the system was mid-update
+	/* the only way to work out whether the system was mid-update
 	 * when we read it is to check the second counter, and if it
 	 * is zero, then we re-try the entire read
 	 */
@@ -427,21 +425,13 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)
 {
 	struct rtc_device *rtc = platform_get_drvdata(dev);
 
-	free_irq(s3c_rtc_alarmno, rtc);
-	free_irq(s3c_rtc_tickno, rtc);
-
 	platform_set_drvdata(dev, NULL);
 	rtc_device_unregister(rtc);
 
 	s3c_rtc_setaie(&dev->dev, 0);
 
-	clk_put(rtc_clk);
 	rtc_clk = NULL;
 
-	iounmap(s3c_rtc_base);
-	release_resource(s3c_rtc_mem);
-	kfree(s3c_rtc_mem);
-
 	return 0;
 }
 
@@ -496,28 +486,18 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
 		return -ENOENT;
 	}
 
-	s3c_rtc_mem = request_mem_region(res->start, resource_size(res),
-					 pdev->name);
-
-	if (s3c_rtc_mem == NULL) {
-		dev_err(&pdev->dev, "failed to reserve memory region\n");
-		ret = -ENOENT;
-		goto err_nores;
-	}
-
-	s3c_rtc_base = ioremap(res->start, resource_size(res));
+	s3c_rtc_base = devm_request_and_ioremap(&pdev->dev, res);
 	if (s3c_rtc_base == NULL) {
-		dev_err(&pdev->dev, "failed ioremap()\n");
-		ret = -EINVAL;
-		goto err_nomap;
+		dev_err(&pdev->dev, "failed to ioremap memory region\n");
+		return -EINVAL;
 	}
 
-	rtc_clk = clk_get(&pdev->dev, "rtc");
+	rtc_clk = devm_clk_get(&pdev->dev, "rtc");
 	if (IS_ERR(rtc_clk)) {
 		dev_err(&pdev->dev, "failed to find rtc clock source\n");
 		ret = PTR_ERR(rtc_clk);
 		rtc_clk = NULL;
-		goto err_clk;
+		return ret;
 	}
 
 	clk_enable(rtc_clk);
@@ -576,28 +556,24 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
 
 	s3c_rtc_setfreq(&pdev->dev, 1);
 
-	ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq,
+	ret = devm_request_irq(&pdev->dev, s3c_rtc_alarmno, s3c_rtc_alarmirq,
 			  0,  "s3c2410-rtc alarm", rtc);
 	if (ret) {
 		dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret);
 		goto err_alarm_irq;
 	}
 
-	ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq,
+	ret = devm_request_irq(&pdev->dev, s3c_rtc_tickno, s3c_rtc_tickirq,
 			  0,  "s3c2410-rtc tick", rtc);
 	if (ret) {
 		dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret);
-		free_irq(s3c_rtc_alarmno, rtc);
-		goto err_tick_irq;
+		goto err_alarm_irq;
 	}
 
 	clk_disable(rtc_clk);
 
 	return 0;
 
- err_tick_irq:
-	free_irq(s3c_rtc_alarmno, rtc);
-
  err_alarm_irq:
 	platform_set_drvdata(pdev, NULL);
 	rtc_device_unregister(rtc);
@@ -605,15 +581,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
  err_nortc:
 	s3c_rtc_enable(pdev, 0);
 	clk_disable(rtc_clk);
-	clk_put(rtc_clk);
-
- err_clk:
-	iounmap(s3c_rtc_base);
-
- err_nomap:
-	release_resource(s3c_rtc_mem);
 
- err_nores:
 	return ret;
 }
 
diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c
index bb507d2..141fc94 100644
--- a/drivers/rtc/rtc-spear.c
+++ b/drivers/rtc/rtc-spear.c
@@ -363,35 +363,42 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "no resource defined\n");
 		return -EBUSY;
 	}
-	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
-		dev_err(&pdev->dev, "rtc region already claimed\n");
-		return -EBUSY;
-	}
 
-	config = kzalloc(sizeof(*config), GFP_KERNEL);
+	config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
 	if (!config) {
 		dev_err(&pdev->dev, "out of memory\n");
-		status = -ENOMEM;
-		goto err_release_region;
+		return -ENOMEM;
 	}
 
-	config->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(config->clk)) {
-		status = PTR_ERR(config->clk);
-		goto err_kfree;
+	/* alarm irqs */
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no update irq?\n");
+		return irq;
 	}
 
-	status = clk_enable(config->clk);
-	if (status < 0)
-		goto err_clk_put;
+	status = devm_request_irq(&pdev->dev, irq, spear_rtc_irq, 0, pdev->name,
+			config);
+	if (status) {
+		dev_err(&pdev->dev, "Alarm interrupt IRQ%d already claimed\n",
+				irq);
+		return status;
+	}
 
-	config->ioaddr = ioremap(res->start, resource_size(res));
+	config->ioaddr = devm_request_and_ioremap(&pdev->dev, res);
 	if (!config->ioaddr) {
-		dev_err(&pdev->dev, "ioremap fail\n");
-		status = -ENOMEM;
-		goto err_disable_clock;
+		dev_err(&pdev->dev, "request-ioremap fail\n");
+		return -ENOMEM;
 	}
 
+	config->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(config->clk))
+		return PTR_ERR(config->clk);
+
+	status = clk_prepare_enable(config->clk);
+	if (status < 0)
+		return status;
+
 	spin_lock_init(&config->lock);
 	platform_set_drvdata(pdev, config);
 
@@ -401,42 +408,19 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
 				PTR_ERR(config->rtc));
 		status = PTR_ERR(config->rtc);
-		goto err_iounmap;
-	}
-
-	/* alarm irqs */
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "no update irq?\n");
-		status = irq;
-		goto err_clear_platdata;
+		goto err_disable_clock;
 	}
 
-	status = request_irq(irq, spear_rtc_irq, 0, pdev->name, config);
-	if (status) {
-		dev_err(&pdev->dev, "Alarm interrupt IRQ%d already \
-				claimed\n", irq);
-		goto err_clear_platdata;
-	}
+	config->rtc->uie_unsupported = 1;
 
 	if (!device_can_wakeup(&pdev->dev))
 		device_init_wakeup(&pdev->dev, 1);
 
 	return 0;
 
-err_clear_platdata:
-	platform_set_drvdata(pdev, NULL);
-	rtc_device_unregister(config->rtc);
-err_iounmap:
-	iounmap(config->ioaddr);
 err_disable_clock:
-	clk_disable(config->clk);
-err_clk_put:
-	clk_put(config->clk);
-err_kfree:
-	kfree(config);
-err_release_region:
-	release_mem_region(res->start, resource_size(res));
+	platform_set_drvdata(pdev, NULL);
+	clk_disable_unprepare(config->clk);
 
 	return status;
 }
@@ -444,24 +428,11 @@ err_release_region:
 static int __devexit spear_rtc_remove(struct platform_device *pdev)
 {
 	struct spear_rtc_config *config = platform_get_drvdata(pdev);
-	int irq;
-	struct resource *res;
 
-	/* leave rtc running, but disable irqs */
+	rtc_device_unregister(config->rtc);
 	spear_rtc_disable_interrupt(config);
+	clk_disable_unprepare(config->clk);
 	device_init_wakeup(&pdev->dev, 0);
-	irq = platform_get_irq(pdev, 0);
-	if (irq)
-		free_irq(irq, pdev);
-	clk_disable(config->clk);
-	clk_put(config->clk);
-	iounmap(config->ioaddr);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res)
-		release_mem_region(res->start, resource_size(res));
-	platform_set_drvdata(pdev, NULL);
-	rtc_device_unregister(config->rtc);
-	kfree(config);
 
 	return 0;
 }
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c
index 7e96254..974b9ae 100644
--- a/drivers/rtc/rtc-test.c
+++ b/drivers/rtc/rtc-test.c
@@ -152,24 +152,24 @@ static int __init test_init(void)
 
 	if ((test1 = platform_device_alloc("rtc-test", 1)) == NULL) {
 		err = -ENOMEM;
-		goto exit_free_test0;
+		goto exit_put_test0;
 	}
 
 	if ((err = platform_device_add(test0)))
-		goto exit_free_test1;
+		goto exit_put_test1;
 
 	if ((err = platform_device_add(test1)))
-		goto exit_device_unregister;
+		goto exit_del_test0;
 
 	return 0;
 
-exit_device_unregister:
-	platform_device_unregister(test0);
+exit_del_test0:
+	platform_device_del(test0);
 
-exit_free_test1:
+exit_put_test1:
 	platform_device_put(test1);
 
-exit_free_test0:
+exit_put_test0:
 	platform_device_put(test0);
 
 exit_driver_unregister:
diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c
index 7a82337..687006f 100644
--- a/drivers/rtc/rtc-tps65910.c
+++ b/drivers/rtc/rtc-tps65910.c
@@ -261,7 +261,7 @@ static int __devinit tps65910_rtc_probe(struct platform_device *pdev)
 
 	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
 		tps65910_rtc_interrupt, IRQF_TRIGGER_LOW,
-		"rtc-tps65910", &pdev->dev);
+		dev_name(&pdev->dev), &pdev->dev);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "IRQ is not free.\n");
 		return ret;
@@ -288,11 +288,11 @@ static int __devinit tps65910_rtc_probe(struct platform_device *pdev)
 static int __devexit tps65910_rtc_remove(struct platform_device *pdev)
 {
 	/* leave rtc running, but disable irqs */
-	struct rtc_device *rtc = platform_get_drvdata(pdev);
+	struct tps65910_rtc *tps_rtc = platform_get_drvdata(pdev);
 
-	tps65910_rtc_alarm_irq_enable(&rtc->dev, 0);
+	tps65910_rtc_alarm_irq_enable(&pdev->dev, 0);
 
-	rtc_device_unregister(rtc);
+	rtc_device_unregister(tps_rtc->rtc);
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index 9277d94..8b7464c 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -233,7 +233,7 @@ static int twl_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
  */
 static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-	unsigned char rtc_data[ALL_TIME_REGS + 1];
+	unsigned char rtc_data[ALL_TIME_REGS];
 	int ret;
 	u8 save_control;
 	u8 rtc_control;
@@ -300,15 +300,15 @@ static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm)
 static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
 	unsigned char save_control;
-	unsigned char rtc_data[ALL_TIME_REGS + 1];
+	unsigned char rtc_data[ALL_TIME_REGS];
 	int ret;
 
-	rtc_data[1] = bin2bcd(tm->tm_sec);
-	rtc_data[2] = bin2bcd(tm->tm_min);
-	rtc_data[3] = bin2bcd(tm->tm_hour);
-	rtc_data[4] = bin2bcd(tm->tm_mday);
-	rtc_data[5] = bin2bcd(tm->tm_mon + 1);
-	rtc_data[6] = bin2bcd(tm->tm_year - 100);
+	rtc_data[0] = bin2bcd(tm->tm_sec);
+	rtc_data[1] = bin2bcd(tm->tm_min);
+	rtc_data[2] = bin2bcd(tm->tm_hour);
+	rtc_data[3] = bin2bcd(tm->tm_mday);
+	rtc_data[4] = bin2bcd(tm->tm_mon + 1);
+	rtc_data[5] = bin2bcd(tm->tm_year - 100);
 
 	/* Stop RTC while updating the TC registers */
 	ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
@@ -341,7 +341,7 @@ out:
  */
 static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
-	unsigned char rtc_data[ALL_TIME_REGS + 1];
+	unsigned char rtc_data[ALL_TIME_REGS];
 	int ret;
 
 	ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data,
@@ -368,19 +368,19 @@ static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 
 static int twl_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
-	unsigned char alarm_data[ALL_TIME_REGS + 1];
+	unsigned char alarm_data[ALL_TIME_REGS];
 	int ret;
 
 	ret = twl_rtc_alarm_irq_enable(dev, 0);
 	if (ret)
 		goto out;
 
-	alarm_data[1] = bin2bcd(alm->time.tm_sec);
-	alarm_data[2] = bin2bcd(alm->time.tm_min);
-	alarm_data[3] = bin2bcd(alm->time.tm_hour);
-	alarm_data[4] = bin2bcd(alm->time.tm_mday);
-	alarm_data[5] = bin2bcd(alm->time.tm_mon + 1);
-	alarm_data[6] = bin2bcd(alm->time.tm_year - 100);
+	alarm_data[0] = bin2bcd(alm->time.tm_sec);
+	alarm_data[1] = bin2bcd(alm->time.tm_min);
+	alarm_data[2] = bin2bcd(alm->time.tm_hour);
+	alarm_data[3] = bin2bcd(alm->time.tm_mday);
+	alarm_data[4] = bin2bcd(alm->time.tm_mon + 1);
+	alarm_data[5] = bin2bcd(alm->time.tm_year - 100);
 
 	/* update all the alarm registers in one shot */
 	ret = twl_i2c_write(TWL_MODULE_RTC, alarm_data,
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c
index 07bf193..14e2d8c 100644
--- a/drivers/rtc/rtc-vt8500.c
+++ b/drivers/rtc/rtc-vt8500.c
@@ -210,7 +210,8 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev)
 	struct vt8500_rtc *vt8500_rtc;
 	int ret;
 
-	vt8500_rtc = kzalloc(sizeof(struct vt8500_rtc), GFP_KERNEL);
+	vt8500_rtc = devm_kzalloc(&pdev->dev,
+			   sizeof(struct vt8500_rtc), GFP_KERNEL);
 	if (!vt8500_rtc)
 		return -ENOMEM;
 
@@ -220,15 +221,13 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev)
 	vt8500_rtc->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!vt8500_rtc->res) {
 		dev_err(&pdev->dev, "No I/O memory resource defined\n");
-		ret = -ENXIO;
-		goto err_free;
+		return -ENXIO;
 	}
 
 	vt8500_rtc->irq_alarm = platform_get_irq(pdev, 0);
 	if (vt8500_rtc->irq_alarm < 0) {
 		dev_err(&pdev->dev, "No alarm IRQ resource defined\n");
-		ret = -ENXIO;
-		goto err_free;
+		return -ENXIO;
 	}
 
 	vt8500_rtc->res = request_mem_region(vt8500_rtc->res->start,
@@ -236,8 +235,7 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev)
 					     "vt8500-rtc");
 	if (vt8500_rtc->res == NULL) {
 		dev_err(&pdev->dev, "failed to request I/O memory\n");
-		ret = -EBUSY;
-		goto err_free;
+		return -EBUSY;
 	}
 
 	vt8500_rtc->regbase = ioremap(vt8500_rtc->res->start,
@@ -278,8 +276,6 @@ err_unmap:
 err_release:
 	release_mem_region(vt8500_rtc->res->start,
 			   resource_size(vt8500_rtc->res));
-err_free:
-	kfree(vt8500_rtc);
 	return ret;
 }
 
@@ -297,7 +293,6 @@ static int __devexit vt8500_rtc_remove(struct platform_device *pdev)
 	release_mem_region(vt8500_rtc->res->start,
 			   resource_size(vt8500_rtc->res));
 
-	kfree(vt8500_rtc);
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index b2b8c18..20cfd02 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -1344,7 +1344,7 @@ dasd_get_feature(struct ccw_device *cdev, int feature)
 
 /*
  * Set / reset given feature.
- * Flag indicates wether to set (!=0) or the reset (=0) the feature.
+ * Flag indicates whether to set (!=0) or the reset (=0) the feature.
  */
 int
 dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 108332b..705b182 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -3847,7 +3847,7 @@ dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page)
 
 	len = 0;
 	while (from <= to) {
-		len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+		len += sprintf(page + len, PRINTK_HEADER
 			       " CCW %p: %08X %08X DAT:",
 			       from, ((int *) from)[0], ((int *) from)[1]);
 
@@ -3908,23 +3908,23 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device,
 		return;
 	}
 	/* dump the sense data */
-	len = sprintf(page,  KERN_ERR PRINTK_HEADER
+	len = sprintf(page, PRINTK_HEADER
 		      " I/O status report for device %s:\n",
 		      dev_name(&device->cdev->dev));
-	len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+	len += sprintf(page + len, PRINTK_HEADER
 		       " in req: %p CC:%02X FC:%02X AC:%02X SC:%02X DS:%02X "
 		       "CS:%02X RC:%d\n",
 		       req, scsw_cc(&irb->scsw), scsw_fctl(&irb->scsw),
 		       scsw_actl(&irb->scsw), scsw_stctl(&irb->scsw),
 		       scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw),
 		       req ? req->intrc : 0);
-	len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+	len += sprintf(page + len, PRINTK_HEADER
 		       " device %s: Failing CCW: %p\n",
 		       dev_name(&device->cdev->dev),
 		       (void *) (addr_t) irb->scsw.cmd.cpa);
 	if (irb->esw.esw0.erw.cons) {
 		for (sl = 0; sl < 4; sl++) {
-			len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+			len += sprintf(page + len, PRINTK_HEADER
 				       " Sense(hex) %2d-%2d:",
 				       (8 * sl), ((8 * sl) + 7));
 
@@ -3937,23 +3937,23 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device,
 
 		if (irb->ecw[27] & DASD_SENSE_BIT_0) {
 			/* 24 Byte Sense Data */
-			sprintf(page + len, KERN_ERR PRINTK_HEADER
+			sprintf(page + len, PRINTK_HEADER
 				" 24 Byte: %x MSG %x, "
 				"%s MSGb to SYSOP\n",
 				irb->ecw[7] >> 4, irb->ecw[7] & 0x0f,
 				irb->ecw[1] & 0x10 ? "" : "no");
 		} else {
 			/* 32 Byte Sense Data */
-			sprintf(page + len, KERN_ERR PRINTK_HEADER
+			sprintf(page + len, PRINTK_HEADER
 				" 32 Byte: Format: %x "
 				"Exception class %x\n",
 				irb->ecw[6] & 0x0f, irb->ecw[22] >> 4);
 		}
 	} else {
-		sprintf(page + len, KERN_ERR PRINTK_HEADER
+		sprintf(page + len, PRINTK_HEADER
 			" SORRY - NO VALID SENSE AVAILABLE\n");
 	}
-	printk("%s", page);
+	printk(KERN_ERR "%s", page);
 
 	if (req) {
 		/* req == NULL for unsolicited interrupts */
@@ -3962,10 +3962,10 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device,
 		first = req->cpaddr;
 		for (last = first; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++);
 		to = min(first + 6, last);
-		len = sprintf(page,  KERN_ERR PRINTK_HEADER
+		len = sprintf(page, PRINTK_HEADER
 			      " Related CP in req: %p\n", req);
 		dasd_eckd_dump_ccw_range(first, to, page + len);
-		printk("%s", page);
+		printk(KERN_ERR "%s", page);
 
 		/* print failing CCW area (maximum 4) */
 		/* scsw->cda is either valid or zero  */
@@ -3975,7 +3975,7 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device,
 				irb->scsw.cmd.cpa; /* failing CCW */
 		if (from <  fail - 2) {
 			from = fail - 2;     /* there is a gap - print header */
-			len += sprintf(page, KERN_ERR PRINTK_HEADER "......\n");
+			len += sprintf(page, PRINTK_HEADER "......\n");
 		}
 		to = min(fail + 1, last);
 		len += dasd_eckd_dump_ccw_range(from, to, page + len);
@@ -3984,11 +3984,11 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device,
 		from = max(from, ++to);
 		if (from < last - 1) {
 			from = last - 1;     /* there is a gap - print header */
-			len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n");
+			len += sprintf(page + len, PRINTK_HEADER "......\n");
 		}
 		len += dasd_eckd_dump_ccw_range(from, last, page + len);
 		if (len > 0)
-			printk("%s", page);
+			printk(KERN_ERR "%s", page);
 	}
 	free_page((unsigned long) page);
 }
@@ -4012,10 +4012,10 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
 		return;
 	}
 	/* dump the sense data */
-	len = sprintf(page,  KERN_ERR PRINTK_HEADER
+	len = sprintf(page, PRINTK_HEADER
 		      " I/O status report for device %s:\n",
 		      dev_name(&device->cdev->dev));
-	len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+	len += sprintf(page + len, PRINTK_HEADER
 		       " in req: %p CC:%02X FC:%02X AC:%02X SC:%02X DS:%02X "
 		       "CS:%02X fcxs:%02X schxs:%02X RC:%d\n",
 		       req, scsw_cc(&irb->scsw), scsw_fctl(&irb->scsw),
@@ -4023,7 +4023,7 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
 		       scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw),
 		       irb->scsw.tm.fcxs, irb->scsw.tm.schxs,
 		       req ? req->intrc : 0);
-	len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+	len += sprintf(page + len, PRINTK_HEADER
 		       " device %s: Failing TCW: %p\n",
 		       dev_name(&device->cdev->dev),
 		       (void *) (addr_t) irb->scsw.tm.tcw);
@@ -4035,43 +4035,42 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
 			(struct tcw *)(unsigned long)irb->scsw.tm.tcw);
 
 	if (tsb) {
-		len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+		len += sprintf(page + len, PRINTK_HEADER
 			       " tsb->length %d\n", tsb->length);
-		len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+		len += sprintf(page + len, PRINTK_HEADER
 			       " tsb->flags %x\n", tsb->flags);
-		len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+		len += sprintf(page + len, PRINTK_HEADER
 			       " tsb->dcw_offset %d\n", tsb->dcw_offset);
-		len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+		len += sprintf(page + len, PRINTK_HEADER
 			       " tsb->count %d\n", tsb->count);
 		residual = tsb->count - 28;
-		len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+		len += sprintf(page + len, PRINTK_HEADER
 			       " residual %d\n", residual);
 
 		switch (tsb->flags & 0x07) {
 		case 1:	/* tsa_iostat */
-			len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+			len += sprintf(page + len, PRINTK_HEADER
 			       " tsb->tsa.iostat.dev_time %d\n",
 				       tsb->tsa.iostat.dev_time);
-			len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+			len += sprintf(page + len, PRINTK_HEADER
 			       " tsb->tsa.iostat.def_time %d\n",
 				       tsb->tsa.iostat.def_time);
-			len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+			len += sprintf(page + len, PRINTK_HEADER
 			       " tsb->tsa.iostat.queue_time %d\n",
 				       tsb->tsa.iostat.queue_time);
-			len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+			len += sprintf(page + len, PRINTK_HEADER
 			       " tsb->tsa.iostat.dev_busy_time %d\n",
 				       tsb->tsa.iostat.dev_busy_time);
-			len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+			len += sprintf(page + len, PRINTK_HEADER
 			       " tsb->tsa.iostat.dev_act_time %d\n",
 				       tsb->tsa.iostat.dev_act_time);
 			sense = tsb->tsa.iostat.sense;
 			break;
 		case 2: /* ts_ddpc */
-			len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+			len += sprintf(page + len, PRINTK_HEADER
 			       " tsb->tsa.ddpc.rc %d\n", tsb->tsa.ddpc.rc);
 			for (sl = 0; sl < 2; sl++) {
-				len += sprintf(page + len,
-					       KERN_ERR PRINTK_HEADER
+				len += sprintf(page + len, PRINTK_HEADER
 					       " tsb->tsa.ddpc.rcq %2d-%2d: ",
 					       (8 * sl), ((8 * sl) + 7));
 				rcq = tsb->tsa.ddpc.rcq;
@@ -4084,15 +4083,14 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
 			sense = tsb->tsa.ddpc.sense;
 			break;
 		case 3: /* tsa_intrg */
-			len += sprintf(page + len, KERN_ERR PRINTK_HEADER
-				      " tsb->tsa.intrg.: not supportet yet \n");
+			len += sprintf(page + len, PRINTK_HEADER
+				      " tsb->tsa.intrg.: not supportet yet\n");
 			break;
 		}
 
 		if (sense) {
 			for (sl = 0; sl < 4; sl++) {
-				len += sprintf(page + len,
-					       KERN_ERR PRINTK_HEADER
+				len += sprintf(page + len, PRINTK_HEADER
 					       " Sense(hex) %2d-%2d:",
 					       (8 * sl), ((8 * sl) + 7));
 				for (sct = 0; sct < 8; sct++) {
@@ -4104,27 +4102,27 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
 
 			if (sense[27] & DASD_SENSE_BIT_0) {
 				/* 24 Byte Sense Data */
-				sprintf(page + len, KERN_ERR PRINTK_HEADER
+				sprintf(page + len, PRINTK_HEADER
 					" 24 Byte: %x MSG %x, "
 					"%s MSGb to SYSOP\n",
 					sense[7] >> 4, sense[7] & 0x0f,
 					sense[1] & 0x10 ? "" : "no");
 			} else {
 				/* 32 Byte Sense Data */
-				sprintf(page + len, KERN_ERR PRINTK_HEADER
+				sprintf(page + len, PRINTK_HEADER
 					" 32 Byte: Format: %x "
 					"Exception class %x\n",
 					sense[6] & 0x0f, sense[22] >> 4);
 			}
 		} else {
-			sprintf(page + len, KERN_ERR PRINTK_HEADER
+			sprintf(page + len, PRINTK_HEADER
 				" SORRY - NO VALID SENSE AVAILABLE\n");
 		}
 	} else {
-		sprintf(page + len, KERN_ERR PRINTK_HEADER
+		sprintf(page + len, PRINTK_HEADER
 			" SORRY - NO TSB DATA AVAILABLE\n");
 	}
-	printk("%s", page);
+	printk(KERN_ERR "%s", page);
 	free_page((unsigned long) page);
 }
 
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index fb7f3bd..eb74850 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -479,19 +479,19 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
 			    "No memory to dump sense data");
 		return;
 	}
-	len = sprintf(page, KERN_ERR PRINTK_HEADER
+	len = sprintf(page, PRINTK_HEADER
 		      " I/O status report for device %s:\n",
 		      dev_name(&device->cdev->dev));
-	len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+	len += sprintf(page + len, PRINTK_HEADER
 		       " in req: %p CS: 0x%02X DS: 0x%02X\n", req,
 		       irb->scsw.cmd.cstat, irb->scsw.cmd.dstat);
-	len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+	len += sprintf(page + len, PRINTK_HEADER
 		       " device %s: Failing CCW: %p\n",
 		       dev_name(&device->cdev->dev),
 		       (void *) (addr_t) irb->scsw.cmd.cpa);
 	if (irb->esw.esw0.erw.cons) {
 		for (sl = 0; sl < 4; sl++) {
-			len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+			len += sprintf(page + len, PRINTK_HEADER
 				       " Sense(hex) %2d-%2d:",
 				       (8 * sl), ((8 * sl) + 7));
 
@@ -502,7 +502,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
 			len += sprintf(page + len, "\n");
 		}
 	} else {
-	        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+		len += sprintf(page + len, PRINTK_HEADER
 			       " SORRY - NO VALID SENSE AVAILABLE\n");
 	}
 	printk(KERN_ERR "%s", page);
@@ -512,10 +512,9 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
 	act = req->cpaddr;
         for (last = act; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++);
 	end = min(act + 8, last);
-	len = sprintf(page, KERN_ERR PRINTK_HEADER
-		      " Related CP in req: %p\n", req);
+	len = sprintf(page, PRINTK_HEADER " Related CP in req: %p\n", req);
 	while (act <= end) {
-		len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+		len += sprintf(page + len, PRINTK_HEADER
 			       " CCW %p: %08X %08X DAT:",
 			       act, ((int *) act)[0], ((int *) act)[1]);
 		for (count = 0; count < 32 && count < act->count;
@@ -533,11 +532,11 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
 	len = 0;
 	if (act <  ((struct ccw1 *)(addr_t) irb->scsw.cmd.cpa) - 2) {
 		act = ((struct ccw1 *)(addr_t) irb->scsw.cmd.cpa) - 2;
-		len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n");
+		len += sprintf(page + len, PRINTK_HEADER "......\n");
 	}
 	end = min((struct ccw1 *)(addr_t) irb->scsw.cmd.cpa + 2, last);
 	while (act <= end) {
-		len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+		len += sprintf(page + len, PRINTK_HEADER
 			       " CCW %p: %08X %08X DAT:",
 			       act, ((int *) act)[0], ((int *) act)[1]);
 		for (count = 0; count < 32 && count < act->count;
@@ -552,10 +551,10 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
 	/* print last CCWs */
 	if (act <  last - 2) {
 		act = last - 2;
-		len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n");
+		len += sprintf(page + len, PRINTK_HEADER "......\n");
 	}
 	while (act <= last) {
-		len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+		len += sprintf(page + len, PRINTK_HEADER
 			       " CCW %p: %08X %08X DAT:",
 			       act, ((int *) act)[0], ((int *) act)[1]);
 		for (count = 0; count < 32 && count < act->count;
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 8252f37..03c0e04 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <asm/compat.h>
 #include <asm/ccwdev.h>
+#include <asm/schid.h>
 #include <asm/cmb.h>
 #include <asm/uaccess.h>
 
@@ -308,11 +309,12 @@ static int dasd_ioctl_information(struct dasd_block *block,
 				  unsigned int cmd, void __user *argp)
 {
 	struct dasd_information2_t *dasd_info;
-	unsigned long flags;
-	int rc;
+	struct subchannel_id sch_id;
+	struct ccw_dev_id dev_id;
 	struct dasd_device *base;
 	struct ccw_device *cdev;
-	struct ccw_dev_id dev_id;
+	unsigned long flags;
+	int rc;
 
 	base = block->base;
 	if (!base->discipline || !base->discipline->fill_info)
@@ -330,9 +332,10 @@ static int dasd_ioctl_information(struct dasd_block *block,
 
 	cdev = base->cdev;
 	ccw_device_get_id(cdev, &dev_id);
+	ccw_device_get_schid(cdev, &sch_id);
 
 	dasd_info->devno = dev_id.devno;
-	dasd_info->schid = _ccw_device_get_subchannel_number(base->cdev);
+	dasd_info->schid = sch_id.sch_no;
 	dasd_info->cu_type = cdev->id.cu_type;
 	dasd_info->cu_model = cdev->id.cu_model;
 	dasd_info->dev_type = cdev->id.dev_type;
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 4ed343e..4008450 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -677,6 +677,7 @@ static void raw3215_free_info(struct raw3215_info *raw)
 {
 	kfree(raw->inbuf);
 	kfree(raw->buffer);
+	tty_port_destroy(&raw->port);
 	kfree(raw);
 }
 
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index 71ea923c..0dfa88a 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -19,10 +19,11 @@
 #include <linux/memory.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <asm/ctl_reg.h>
 #include <asm/chpid.h>
-#include <asm/sclp.h>
 #include <asm/setup.h>
-#include <asm/ctl_reg.h>
+#include <asm/page.h>
+#include <asm/sclp.h>
 
 #include "sclp.h"
 
@@ -400,17 +401,15 @@ out:
 
 static int sclp_assign_storage(u16 rn)
 {
-	unsigned long long start, address;
+	unsigned long long start;
 	int rc;
 
 	rc = do_assign_storage(0x000d0001, rn);
 	if (rc)
-		goto out;
-	start = address = rn2addr(rn);
-	for (; address < start + rzm; address += PAGE_SIZE)
-		page_set_storage_key(address, PAGE_DEFAULT_KEY, 0);
-out:
-	return rc;
+		return rc;
+	start = rn2addr(rn);
+	storage_key_init_range(start, start + rzm);
+	return 0;
 }
 
 static int sclp_unassign_storage(u16 rn)
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 30ec09e..877fbc3 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -547,7 +547,6 @@ sclp_tty_init(void)
 		sclp_tty_tolower = 1;
 	}
 	sclp_tty_chars_count = 0;
-	tty_port_init(&sclp_port);
 
 	rc = sclp_register(&sclp_input_event);
 	if (rc) {
@@ -555,6 +554,8 @@ sclp_tty_init(void)
 		return rc;
 	}
 
+	tty_port_init(&sclp_port);
+
 	driver->driver_name = "sclp_line";
 	driver->name = "sclp_line";
 	driver->major = TTY_MAJOR;
@@ -571,6 +572,7 @@ sclp_tty_init(void)
 	rc = tty_register_driver(driver);
 	if (rc) {
 		put_tty_driver(driver);
+		tty_port_destroy(&sclp_port);
 		return rc;
 	}
 	sclp_tty_driver = driver;
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 7e60f3d..effcc87 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -615,6 +615,7 @@ static void __init __sclp_vt220_cleanup(void)
 		return;
 	sclp_unregister(&sclp_vt220_register);
 	__sclp_vt220_free_pages();
+	tty_port_destroy(&sclp_vt220_port);
 }
 
 /* Allocate buffer pages and register with sclp core. Controlled by init
@@ -650,6 +651,7 @@ out:
 	if (rc) {
 		__sclp_vt220_free_pages();
 		sclp_vt220_init_count--;
+		tty_port_destroy(&sclp_vt220_port);
 	}
 	return rc;
 }
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 482ee02..43ea059 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -722,6 +722,7 @@ out_pages:
 	while (pages--)
 		free_pages((unsigned long) tp->freemem_pages[pages], 0);
 	kfree(tp->freemem_pages);
+	tty_port_destroy(&tp->port);
 out_tp:
 	kfree(tp);
 out_err:
@@ -744,6 +745,7 @@ tty3270_free_view(struct tty3270 *tp)
 	for (pages = 0; pages < TTY3270_STRING_PAGES; pages++)
 		free_pages((unsigned long) tp->freemem_pages[pages], 0);
 	kfree(tp->freemem_pages);
+	tty_port_destroy(&tp->port);
 	kfree(tp);
 }
 
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 731470e..84846c2 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -65,10 +65,18 @@ static void __ccwgroup_remove_cdev_refs(struct ccwgroup_device *gdev)
 	}
 }
 
-static int ccwgroup_set_online(struct ccwgroup_device *gdev)
+/**
+ * ccwgroup_set_online() - enable a ccwgroup device
+ * @gdev: target ccwgroup device
+ *
+ * This function attempts to put the ccwgroup device into the online state.
+ * Returns:
+ *  %0 on success and a negative error value on failure.
+ */
+int ccwgroup_set_online(struct ccwgroup_device *gdev)
 {
 	struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver);
-	int ret = 0;
+	int ret = -EINVAL;
 
 	if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
 		return -EAGAIN;
@@ -84,11 +92,20 @@ out:
 	atomic_set(&gdev->onoff, 0);
 	return ret;
 }
+EXPORT_SYMBOL(ccwgroup_set_online);
 
-static int ccwgroup_set_offline(struct ccwgroup_device *gdev)
+/**
+ * ccwgroup_set_offline() - disable a ccwgroup device
+ * @gdev: target ccwgroup device
+ *
+ * This function attempts to put the ccwgroup device into the offline state.
+ * Returns:
+ *  %0 on success and a negative error value on failure.
+ */
+int ccwgroup_set_offline(struct ccwgroup_device *gdev)
 {
 	struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver);
-	int ret = 0;
+	int ret = -EINVAL;
 
 	if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
 		return -EAGAIN;
@@ -104,6 +121,7 @@ out:
 	atomic_set(&gdev->onoff, 0);
 	return ret;
 }
+EXPORT_SYMBOL(ccwgroup_set_offline);
 
 static ssize_t ccwgroup_online_store(struct device *dev,
 				     struct device_attribute *attr,
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index fd3143c..6995cff 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -2036,16 +2036,6 @@ void ccw_driver_unregister(struct ccw_driver *cdriver)
 	driver_unregister(&cdriver->driver);
 }
 
-/* Helper func for qdio. */
-struct subchannel_id
-ccw_device_get_subchannel_id(struct ccw_device *cdev)
-{
-	struct subchannel *sch;
-
-	sch = to_subchannel(cdev->dev.parent);
-	return sch->schid;
-}
-
 static void ccw_device_todo(struct work_struct *work)
 {
 	struct ccw_device_private *priv;
@@ -2138,4 +2128,3 @@ EXPORT_SYMBOL(ccw_device_set_offline);
 EXPORT_SYMBOL(ccw_driver_register);
 EXPORT_SYMBOL(ccw_driver_unregister);
 EXPORT_SYMBOL(get_ccwdev_by_busid);
-EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id);
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 6bace69..2e575cf 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -142,9 +142,7 @@ int ccw_device_notify(struct ccw_device *, int);
 void ccw_device_set_disconnected(struct ccw_device *cdev);
 void ccw_device_set_notoper(struct ccw_device *cdev);
 
-/* qdio needs this. */
 void ccw_device_set_timeout(struct ccw_device *, int);
-extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *);
 
 /* Channel measurement facility related */
 void retry_set_schib(struct ccw_device *cdev);
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index ec7fb6d..c77b6e0 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -755,14 +755,18 @@ int ccw_device_tm_intrg(struct ccw_device *cdev)
 }
 EXPORT_SYMBOL(ccw_device_tm_intrg);
 
-// FIXME: these have to go:
-
-int
-_ccw_device_get_subchannel_number(struct ccw_device *cdev)
+/**
+ * ccw_device_get_schid - obtain a subchannel id
+ * @cdev: device to obtain the id for
+ * @schid: where to fill in the values
+ */
+void ccw_device_get_schid(struct ccw_device *cdev, struct subchannel_id *schid)
 {
-	return cdev->private->schid.sch_no;
-}
+	struct subchannel *sch = to_subchannel(cdev->dev.parent);
 
+	*schid = sch->schid;
+}
+EXPORT_SYMBOL_GPL(ccw_device_get_schid);
 
 MODULE_LICENSE("GPL");
 EXPORT_SYMBOL(ccw_device_set_options_mask);
@@ -777,5 +781,4 @@ EXPORT_SYMBOL(ccw_device_start_timeout_key);
 EXPORT_SYMBOL(ccw_device_start_key);
 EXPORT_SYMBOL(ccw_device_get_ciw);
 EXPORT_SYMBOL(ccw_device_get_path_mask);
-EXPORT_SYMBOL(_ccw_device_get_subchannel_number);
 EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc);
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index e06fa03..1671d34 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -129,7 +129,6 @@ static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
 	int rc, tmp_count = count, tmp_start = start, nr = q->nr, retried = 0;
 	unsigned int ccq = 0;
 
-	BUG_ON(!q->irq_ptr->sch_token);
 	qperf_inc(q, eqbs);
 
 	if (!q->is_input_q)
@@ -147,7 +146,6 @@ again:
 	}
 
 	if (rc == 2) {
-		BUG_ON(tmp_count == count);
 		qperf_inc(q, eqbs_partial);
 		DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "EQBS part:%02x",
 			tmp_count);
@@ -189,8 +187,6 @@ static int qdio_do_sqbs(struct qdio_q *q, unsigned char state, int start,
 
 	if (!count)
 		return 0;
-
-	BUG_ON(!q->irq_ptr->sch_token);
 	qperf_inc(q, sqbs);
 
 	if (!q->is_input_q)
@@ -199,7 +195,7 @@ again:
 	ccq = do_sqbs(q->irq_ptr->sch_token, state, nr, &tmp_start, &tmp_count);
 	rc = qdio_check_ccq(q, ccq);
 	if (!rc) {
-		WARN_ON(tmp_count);
+		WARN_ON_ONCE(tmp_count);
 		return count - tmp_count;
 	}
 
@@ -224,9 +220,6 @@ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr,
 	unsigned char __state = 0;
 	int i;
 
-	BUG_ON(bufnr > QDIO_MAX_BUFFERS_MASK);
-	BUG_ON(count > QDIO_MAX_BUFFERS_PER_Q);
-
 	if (is_qebsm(q))
 		return qdio_do_eqbs(q, state, bufnr, count, auto_ack);
 
@@ -258,9 +251,6 @@ static inline int set_buf_states(struct qdio_q *q, int bufnr,
 {
 	int i;
 
-	BUG_ON(bufnr > QDIO_MAX_BUFFERS_MASK);
-	BUG_ON(count > QDIO_MAX_BUFFERS_PER_Q);
-
 	if (is_qebsm(q))
 		return qdio_do_sqbs(q, state, bufnr, count);
 
@@ -345,7 +335,6 @@ again:
 
 	/* hipersocket busy condition */
 	if (unlikely(*busy_bit)) {
-		WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2);
 		retries++;
 
 		if (!start_time) {
@@ -559,7 +548,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
 		DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in nop");
 		break;
 	default:
-		BUG();
+		WARN_ON_ONCE(1);
 	}
 out:
 	return q->first_to_check;
@@ -678,12 +667,10 @@ static inline void qdio_handle_aobs(struct qdio_q *q, int start, int count)
 			if (aob == NULL)
 				continue;
 
-			BUG_ON(q->u.out.sbal_state == NULL);
 			q->u.out.sbal_state[b].flags |=
 				QDIO_OUTBUF_STATE_FLAG_PENDING;
 			q->u.out.aobs[b] = NULL;
 		} else if (state == SLSB_P_OUTPUT_EMPTY) {
-			BUG_ON(q->u.out.sbal_state == NULL);
 			q->u.out.sbal_state[b].aob = NULL;
 		}
 		b = next_buf(b);
@@ -703,12 +690,11 @@ static inline unsigned long qdio_aob_for_buffer(struct qdio_output_q *q,
 		q->aobs[bufnr] = aob;
 	}
 	if (q->aobs[bufnr]) {
-		BUG_ON(q->sbal_state == NULL);
 		q->sbal_state[bufnr].flags = QDIO_OUTBUF_STATE_FLAG_NONE;
 		q->sbal_state[bufnr].aob = q->aobs[bufnr];
 		q->aobs[bufnr]->user1 = (u64) q->sbal_state[bufnr].user;
 		phys_aob = virt_to_phys(q->aobs[bufnr]);
-		BUG_ON(phys_aob & 0xFF);
+		WARN_ON_ONCE(phys_aob & 0xFF);
 	}
 
 out:
@@ -809,8 +795,6 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
 		goto out;
 
 	switch (state) {
-	case SLSB_P_OUTPUT_PENDING:
-		BUG();
 	case SLSB_P_OUTPUT_EMPTY:
 		/* the adapter got it */
 		DBF_DEV_EVENT(DBF_INFO, q->irq_ptr,
@@ -840,7 +824,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
 	case SLSB_P_OUTPUT_HALTED:
 		break;
 	default:
-		BUG();
+		WARN_ON_ONCE(1);
 	}
 
 out:
@@ -912,7 +896,7 @@ retry:
 static void __qdio_outbound_processing(struct qdio_q *q)
 {
 	qperf_inc(q, tasklet_outbound);
-	BUG_ON(atomic_read(&q->nr_buf_used) < 0);
+	WARN_ON_ONCE(atomic_read(&q->nr_buf_used) < 0);
 
 	if (qdio_outbound_q_moved(q))
 		qdio_kick_handler(q);
@@ -1138,16 +1122,10 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
 		irq_ptr->perf_stat.qdio_int++;
 
 	if (IS_ERR(irb)) {
-		switch (PTR_ERR(irb)) {
-		case -EIO:
-			DBF_ERROR("%4x IO error", irq_ptr->schid.sch_no);
-			qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
-			wake_up(&cdev->private->wait_q);
-			return;
-		default:
-			WARN_ON(1);
-			return;
-		}
+		DBF_ERROR("%4x IO error", irq_ptr->schid.sch_no);
+		qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
+		wake_up(&cdev->private->wait_q);
+		return;
 	}
 	qdio_irq_check_sense(irq_ptr, irb);
 	cstat = irb->scsw.cmd.cstat;
@@ -1173,7 +1151,7 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
 	case QDIO_IRQ_STATE_STOPPED:
 		break;
 	default:
-		WARN_ON(1);
+		WARN_ON_ONCE(1);
 	}
 	wake_up(&cdev->private->wait_q);
 }
@@ -1227,7 +1205,7 @@ int qdio_shutdown(struct ccw_device *cdev, int how)
 	if (!irq_ptr)
 		return -ENODEV;
 
-	BUG_ON(irqs_disabled());
+	WARN_ON_ONCE(irqs_disabled());
 	DBF_EVENT("qshutdown:%4x", cdev->private->schid.sch_no);
 
 	mutex_lock(&irq_ptr->setup_mutex);
@@ -1358,7 +1336,6 @@ int qdio_allocate(struct qdio_initialize *init_data)
 	irq_ptr->qdr = (struct qdr *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!irq_ptr->qdr)
 		goto out_rel;
-	WARN_ON((unsigned long)irq_ptr->qdr & 0xfff);
 
 	if (qdio_allocate_qs(irq_ptr, init_data->no_input_qs,
 			     init_data->no_output_qs))
@@ -1597,9 +1574,7 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags,
 
 set:
 	count = set_buf_states(q, bufnr, SLSB_CU_INPUT_EMPTY, count);
-
 	used = atomic_add_return(count, &q->nr_buf_used) - count;
-	BUG_ON(used + count > QDIO_MAX_BUFFERS_PER_Q);
 
 	if (need_siga_in(q))
 		return qdio_siga_input(q);
@@ -1624,7 +1599,6 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
 
 	count = set_buf_states(q, bufnr, SLSB_CU_OUTPUT_PRIMED, count);
 	used = atomic_add_return(count, &q->nr_buf_used);
-	BUG_ON(used > QDIO_MAX_BUFFERS_PER_Q);
 
 	if (used == QDIO_MAX_BUFFERS_PER_Q)
 		qperf_inc(q, outbound_queue_full);
@@ -1678,7 +1652,6 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
 {
 	struct qdio_irq *irq_ptr;
 
-
 	if (bufnr >= QDIO_MAX_BUFFERS_PER_Q || count > QDIO_MAX_BUFFERS_PER_Q)
 		return -EINVAL;
 
@@ -1721,8 +1694,6 @@ int qdio_start_irq(struct ccw_device *cdev, int nr)
 		return -ENODEV;
 	q = irq_ptr->input_qs[nr];
 
-	WARN_ON(queue_irqs_enabled(q));
-
 	clear_nonshared_ind(irq_ptr);
 	qdio_stop_polling(q);
 	clear_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state);
@@ -1769,7 +1740,6 @@ int qdio_get_next_buffers(struct ccw_device *cdev, int nr, int *bufnr,
 	if (!irq_ptr)
 		return -ENODEV;
 	q = irq_ptr->input_qs[nr];
-	WARN_ON(queue_irqs_enabled(q));
 
 	/*
 	 * Cannot rely on automatic sync after interrupt since queues may
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index 6c973db..31ddb96 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -140,10 +140,8 @@ static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr,
 	q->sl = (struct sl *)((char *)q->slib + PAGE_SIZE / 2);
 
 	/* fill in sbal */
-	for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) {
+	for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++)
 		q->sbal[j] = *sbals_array++;
-		BUG_ON((unsigned long)q->sbal[j] & 0xff);
-	}
 
 	/* fill in slib */
 	if (i > 0) {
@@ -434,9 +432,8 @@ int qdio_setup_irq(struct qdio_initialize *init_data)
 	irq_ptr->int_parm = init_data->int_parm;
 	irq_ptr->nr_input_qs = init_data->no_input_qs;
 	irq_ptr->nr_output_qs = init_data->no_output_qs;
-
-	irq_ptr->schid = ccw_device_get_subchannel_id(init_data->cdev);
 	irq_ptr->cdev = init_data->cdev;
+	ccw_device_get_schid(irq_ptr->cdev, &irq_ptr->schid);
 	setup_queues(irq_ptr, init_data);
 
 	setup_qib(irq_ptr, init_data);
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index 2e06008..bdb394b 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -73,7 +73,6 @@ static void put_indicator(u32 *addr)
 void tiqdio_add_input_queues(struct qdio_irq *irq_ptr)
 {
 	mutex_lock(&tiq_list_lock);
-	BUG_ON(irq_ptr->nr_input_qs < 1);
 	list_add_rcu(&irq_ptr->input_qs[0]->entry, &tiq_list);
 	mutex_unlock(&tiq_list_lock);
 	xchg(irq_ptr->dsci, 1 << 7);
@@ -83,7 +82,6 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
 {
 	struct qdio_q *q;
 
-	BUG_ON(irq_ptr->nr_input_qs < 1);
 	q = irq_ptr->input_qs[0];
 	/* if establish triggered an error */
 	if (!q || !q->entry.prev || !q->entry.next)
diff --git a/drivers/s390/crypto/zcrypt_msgtype50.c b/drivers/s390/crypto/zcrypt_msgtype50.c
index 035b6dc..7c522f3 100644
--- a/drivers/s390/crypto/zcrypt_msgtype50.c
+++ b/drivers/s390/crypto/zcrypt_msgtype50.c
@@ -241,84 +241,70 @@ static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_device *zdev,
 				       struct ap_message *ap_msg,
 				       struct ica_rsa_modexpo_crt *crt)
 {
-	int mod_len, short_len, long_len, long_offset, limit;
+	int mod_len, short_len;
 	unsigned char *p, *q, *dp, *dq, *u, *inp;
 
 	mod_len = crt->inputdatalength;
 	short_len = mod_len / 2;
-	long_len = mod_len / 2 + 8;
 
 	/*
-	 * CEX2A cannot handle p, dp, or U > 128 bytes.
-	 * If we have one of these, we need to do extra checking.
-	 * For CEX3A the limit is 256 bytes.
+	 * CEX2A and CEX3A w/o FW update can handle requests up to
+	 * 256 byte modulus (2k keys).
+	 * CEX3A with FW update and CEX4A cards are able to handle
+	 * 512 byte modulus (4k keys).
 	 */
-	if (zdev->max_mod_size == CEX3A_MAX_MOD_SIZE)
-		limit = 256;
-	else
-		limit = 128;
-
-	if (long_len > limit) {
-		/*
-		 * zcrypt_rsa_crt already checked for the leading
-		 * zeroes of np_prime, bp_key and u_mult_inc.
-		 */
-		long_offset = long_len - limit;
-		long_len = limit;
-	} else
-		long_offset = 0;
-
-	/*
-	 * Instead of doing extra work for p, dp, U > 64 bytes, we'll just use
-	 * the larger message structure.
-	 */
-	if (long_len <= 64) {
+	if (mod_len <= 128) {		/* up to 1024 bit key size */
 		struct type50_crb1_msg *crb1 = ap_msg->message;
 		memset(crb1, 0, sizeof(*crb1));
 		ap_msg->length = sizeof(*crb1);
 		crb1->header.msg_type_code = TYPE50_TYPE_CODE;
 		crb1->header.msg_len = sizeof(*crb1);
 		crb1->keyblock_type = TYPE50_CRB1_FMT;
-		p = crb1->p + sizeof(crb1->p) - long_len;
+		p = crb1->p + sizeof(crb1->p) - short_len;
 		q = crb1->q + sizeof(crb1->q) - short_len;
-		dp = crb1->dp + sizeof(crb1->dp) - long_len;
+		dp = crb1->dp + sizeof(crb1->dp) - short_len;
 		dq = crb1->dq + sizeof(crb1->dq) - short_len;
-		u = crb1->u + sizeof(crb1->u) - long_len;
+		u = crb1->u + sizeof(crb1->u) - short_len;
 		inp = crb1->message + sizeof(crb1->message) - mod_len;
-	} else if (long_len <= 128) {
+	} else if (mod_len <= 256) {	/* up to 2048 bit key size */
 		struct type50_crb2_msg *crb2 = ap_msg->message;
 		memset(crb2, 0, sizeof(*crb2));
 		ap_msg->length = sizeof(*crb2);
 		crb2->header.msg_type_code = TYPE50_TYPE_CODE;
 		crb2->header.msg_len = sizeof(*crb2);
 		crb2->keyblock_type = TYPE50_CRB2_FMT;
-		p = crb2->p + sizeof(crb2->p) - long_len;
+		p = crb2->p + sizeof(crb2->p) - short_len;
 		q = crb2->q + sizeof(crb2->q) - short_len;
-		dp = crb2->dp + sizeof(crb2->dp) - long_len;
+		dp = crb2->dp + sizeof(crb2->dp) - short_len;
 		dq = crb2->dq + sizeof(crb2->dq) - short_len;
-		u = crb2->u + sizeof(crb2->u) - long_len;
+		u = crb2->u + sizeof(crb2->u) - short_len;
 		inp = crb2->message + sizeof(crb2->message) - mod_len;
-	} else {
-		/* long_len >= 256 */
+	} else if ((mod_len <= 512) &&	/* up to 4096 bit key size */
+		   (zdev->max_mod_size == CEX3A_MAX_MOD_SIZE)) { /* >= CEX3A */
 		struct type50_crb3_msg *crb3 = ap_msg->message;
 		memset(crb3, 0, sizeof(*crb3));
 		ap_msg->length = sizeof(*crb3);
 		crb3->header.msg_type_code = TYPE50_TYPE_CODE;
 		crb3->header.msg_len = sizeof(*crb3);
 		crb3->keyblock_type = TYPE50_CRB3_FMT;
-		p = crb3->p + sizeof(crb3->p) - long_len;
+		p = crb3->p + sizeof(crb3->p) - short_len;
 		q = crb3->q + sizeof(crb3->q) - short_len;
-		dp = crb3->dp + sizeof(crb3->dp) - long_len;
+		dp = crb3->dp + sizeof(crb3->dp) - short_len;
 		dq = crb3->dq + sizeof(crb3->dq) - short_len;
-		u = crb3->u + sizeof(crb3->u) - long_len;
+		u = crb3->u + sizeof(crb3->u) - short_len;
 		inp = crb3->message + sizeof(crb3->message) - mod_len;
-	}
+	} else
+		return -EINVAL;
 
-	if (copy_from_user(p, crt->np_prime + long_offset, long_len) ||
+	/*
+	 * correct the offset of p, bp and mult_inv according zcrypt.h
+	 * block size right aligned (skip the first byte)
+	 */
+	if (copy_from_user(p, crt->np_prime + MSGTYPE_ADJUSTMENT, short_len) ||
 	    copy_from_user(q, crt->nq_prime, short_len) ||
-	    copy_from_user(dp, crt->bp_key + long_offset, long_len) ||
+	    copy_from_user(dp, crt->bp_key + MSGTYPE_ADJUSTMENT, short_len) ||
 	    copy_from_user(dq, crt->bq_key, short_len) ||
-	    copy_from_user(u, crt->u_mult_inv + long_offset, long_len) ||
+	    copy_from_user(u, crt->u_mult_inv + MSGTYPE_ADJUSTMENT, short_len) ||
 	    copy_from_user(inp, crt->inputdata, mod_len))
 		return -EFAULT;
 
diff --git a/drivers/s390/crypto/zcrypt_msgtype50.h b/drivers/s390/crypto/zcrypt_msgtype50.h
index e56dc72..0a66e4a 100644
--- a/drivers/s390/crypto/zcrypt_msgtype50.h
+++ b/drivers/s390/crypto/zcrypt_msgtype50.h
@@ -33,6 +33,8 @@
 #define MSGTYPE50_CRB2_MAX_MSG_SIZE	0x390 /*sizeof(struct type50_crb2_msg)*/
 #define MSGTYPE50_CRB3_MAX_MSG_SIZE	0x710 /*sizeof(struct type50_crb3_msg)*/
 
+#define MSGTYPE_ADJUSTMENT		0x08  /*type04 extension (not needed in type50)*/
+
 int zcrypt_msgtype50_init(void);
 void zcrypt_msgtype50_exit(void);
 
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index a0a4afe..5c70a65 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -3018,10 +3018,8 @@ claw_remove_device(struct ccwgroup_device *cgdev)
 {
 	struct claw_privbk *priv;
 
-	BUG_ON(!cgdev);
 	CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev));
 	priv = dev_get_drvdata(&cgdev->dev);
-	BUG_ON(!priv);
 	dev_info(&cgdev->dev, " will be removed.\n");
 	if (cgdev->state == CCWGROUP_ONLINE)
 		claw_shutdown_device(cgdev);
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 98ea9cc..817b689 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -1691,8 +1691,6 @@ static void ctcm_remove_device(struct ccwgroup_device *cgdev)
 {
 	struct ctcm_priv *priv = dev_get_drvdata(&cgdev->dev);
 
-	BUG_ON(priv == NULL);
-
 	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
 			"removing device %p, proto : %d",
 			cgdev, priv->protocol);
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
index 05b734a..2dbc77b 100644
--- a/drivers/s390/net/ctcm_mpc.c
+++ b/drivers/s390/net/ctcm_mpc.c
@@ -1367,7 +1367,6 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg)
 	struct mpc_group *grp;
 	struct channel *wch;
 
-	BUG_ON(dev == NULL);
 	CTCM_PR_DEBUG("Enter %s: %s\n",	__func__, dev->name);
 
 	priv  = dev->ml_priv;
@@ -1472,8 +1471,6 @@ static void mpc_action_timeout(fsm_instance *fi, int event, void *arg)
 	struct channel *wch;
 	struct channel *rch;
 
-	BUG_ON(dev == NULL);
-
 	priv = dev->ml_priv;
 	grp = priv->mpcg;
 	wch = priv->channel[CTCM_WRITE];
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index fa7adad..480fbea 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -933,6 +933,7 @@ int qeth_hdr_chk_and_bounce(struct sk_buff *, int);
 int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
 int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
 int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot);
+void qeth_trace_features(struct qeth_card *);
 
 /* exports for OSN */
 int qeth_osn_assist(struct net_device *, void *, int);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 4d6ba00..638a57f 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -73,13 +73,13 @@ static inline const char *qeth_get_cardname(struct qeth_card *card)
 	if (card->info.guestlan) {
 		switch (card->info.type) {
 		case QETH_CARD_TYPE_OSD:
-			return " Guest LAN QDIO";
+			return " Virtual NIC QDIO";
 		case QETH_CARD_TYPE_IQD:
-			return " Guest LAN Hiper";
+			return " Virtual NIC Hiper";
 		case QETH_CARD_TYPE_OSM:
-			return " Guest LAN QDIO - OSM";
+			return " Virtual NIC QDIO - OSM";
 		case QETH_CARD_TYPE_OSX:
-			return " Guest LAN QDIO - OSX";
+			return " Virtual NIC QDIO - OSX";
 		default:
 			return " unknown";
 		}
@@ -108,13 +108,13 @@ const char *qeth_get_cardname_short(struct qeth_card *card)
 	if (card->info.guestlan) {
 		switch (card->info.type) {
 		case QETH_CARD_TYPE_OSD:
-			return "GuestLAN QDIO";
+			return "Virt.NIC QDIO";
 		case QETH_CARD_TYPE_IQD:
-			return "GuestLAN Hiper";
+			return "Virt.NIC Hiper";
 		case QETH_CARD_TYPE_OSM:
-			return "GuestLAN OSM";
+			return "Virt.NIC OSM";
 		case QETH_CARD_TYPE_OSX:
-			return "GuestLAN OSX";
+			return "Virt.NIC OSX";
 		default:
 			return "unknown";
 		}
@@ -383,7 +383,7 @@ static inline void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q,
 				qeth_release_skbs(c);
 
 				c = f->next_pending;
-				BUG_ON(head->next_pending != f);
+				WARN_ON_ONCE(head->next_pending != f);
 				head->next_pending = c;
 				kmem_cache_free(qeth_qdio_outbuf_cache, f);
 			} else {
@@ -415,13 +415,12 @@ static inline void qeth_qdio_handle_aob(struct qeth_card *card,
 	buffer = (struct qeth_qdio_out_buffer *) aob->user1;
 	QETH_CARD_TEXT_(card, 5, "%lx", aob->user1);
 
-	BUG_ON(buffer == NULL);
-
 	if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED,
 			   QETH_QDIO_BUF_IN_CQ) == QETH_QDIO_BUF_PRIMED) {
 		notification = TX_NOTIFY_OK;
 	} else {
-		BUG_ON(atomic_read(&buffer->state) != QETH_QDIO_BUF_PENDING);
+		WARN_ON_ONCE(atomic_read(&buffer->state) !=
+							QETH_QDIO_BUF_PENDING);
 		atomic_set(&buffer->state, QETH_QDIO_BUF_IN_CQ);
 		notification = TX_NOTIFY_DELAYED_OK;
 	}
@@ -1131,7 +1130,7 @@ static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf)
 		notify_general_error = 1;
 
 	/* release may never happen from within CQ tasklet scope */
-	BUG_ON(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ);
+	WARN_ON_ONCE(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ);
 
 	skb = skb_dequeue(&buf->skb_list);
 	while (skb) {
@@ -2280,7 +2279,6 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
 		unsigned long data)
 {
 	struct qeth_cmd_buffer *iob;
-	int rc = 0;
 
 	QETH_DBF_TEXT(SETUP, 2, "ulpstpcb");
 
@@ -2296,7 +2294,7 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
 		iob->rc = -EMLINK;
 	}
 	QETH_DBF_TEXT_(SETUP, 2, "  rc%d", iob->rc);
-	return rc;
+	return 0;
 }
 
 static int qeth_ulp_setup(struct qeth_card *card)
@@ -2401,7 +2399,7 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
 		card->qdio.out_qs[i]->queue_no = i;
 		/* give outbound qeth_qdio_buffers their qdio_buffers */
 		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
-			BUG_ON(card->qdio.out_qs[i]->bufs[j] != NULL);
+			WARN_ON(card->qdio.out_qs[i]->bufs[j] != NULL);
 			if (qeth_init_qdio_out_buf(card->qdio.out_qs[i], j))
 				goto out_freeoutqbufs;
 		}
@@ -2969,9 +2967,6 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,
 	} else
 		QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Flawed LIC detected"
 					"\n", dev_name(&card->gdev->dev));
-	QETH_DBF_TEXT(SETUP, 2, "suppenbl");
-	QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_supported);
-	QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_enabled);
 	return 0;
 }
 
@@ -3569,7 +3564,7 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
 		if (queue->bufstates &&
 		    (queue->bufstates[bidx].flags &
 		     QDIO_OUTBUF_STATE_FLAG_PENDING) != 0) {
-			BUG_ON(card->options.cq != QETH_CQ_ENABLED);
+			WARN_ON_ONCE(card->options.cq != QETH_CQ_ENABLED);
 
 			if (atomic_cmpxchg(&buffer->state,
 					   QETH_QDIO_BUF_PRIMED,
@@ -3583,7 +3578,6 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
 			QETH_CARD_TEXT(queue->card, 5, "aob");
 			QETH_CARD_TEXT_(queue->card, 5, "%lx",
 					virt_to_phys(buffer->aob));
-			BUG_ON(bidx < 0 || bidx >= QDIO_MAX_BUFFERS_PER_Q);
 			if (qeth_init_qdio_out_buf(queue, bidx)) {
 				QETH_CARD_TEXT(card, 2, "outofbuf");
 				qeth_schedule_recovery(card);
@@ -4731,6 +4725,19 @@ static void qeth_core_free_card(struct qeth_card *card)
 	kfree(card);
 }
 
+void qeth_trace_features(struct qeth_card *card)
+{
+	QETH_CARD_TEXT(card, 2, "features");
+	QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa4.supported_funcs);
+	QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa4.enabled_funcs);
+	QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa6.supported_funcs);
+	QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa6.enabled_funcs);
+	QETH_CARD_TEXT_(card, 2, "%x", card->options.adp.supported_funcs);
+	QETH_CARD_TEXT_(card, 2, "%x", card->options.adp.enabled_funcs);
+	QETH_CARD_TEXT_(card, 2, "%x", card->info.diagass_support);
+}
+EXPORT_SYMBOL_GPL(qeth_trace_features);
+
 static struct ccw_device_id qeth_ids[] = {
 	{CCW_DEVICE_DEVTYPE(0x1731, 0x01, 0x1732, 0x01),
 					.driver_info = QETH_CARD_TYPE_OSD},
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index fddb626..7319555 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -411,7 +411,7 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
 	unsigned int len;
 
 	*done = 0;
-	BUG_ON(!budget);
+	WARN_ON_ONCE(!budget);
 	while (budget) {
 		skb = qeth_core_get_next_skb(card,
 			&card->qdio.in_q->bufs[card->rx.b_index],
@@ -973,7 +973,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
 	int rc = 0;
 	enum qeth_card_states recover_flag;
 
-	BUG_ON(!card);
 	mutex_lock(&card->discipline_mutex);
 	mutex_lock(&card->conf_mutex);
 	QETH_DBF_TEXT(SETUP, 2, "setonlin");
@@ -986,6 +985,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
 		rc = -ENODEV;
 		goto out_remove;
 	}
+	qeth_trace_features(card);
 
 	if (!card->dev && qeth_l2_setup_netdev(card)) {
 		rc = -ENODEV;
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 5ba3906..6e5eef0 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1939,7 +1939,7 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
 	__u16 magic;
 
 	*done = 0;
-	BUG_ON(!budget);
+	WARN_ON_ONCE(!budget);
 	while (budget) {
 		skb = qeth_core_get_next_skb(card,
 			&card->qdio.in_q->bufs[card->rx.b_index],
@@ -3334,7 +3334,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
 	int rc = 0;
 	enum qeth_card_states recover_flag;
 
-	BUG_ON(!card);
 	mutex_lock(&card->discipline_mutex);
 	mutex_lock(&card->conf_mutex);
 	QETH_DBF_TEXT(SETUP, 2, "setonlin");
@@ -3347,6 +3346,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
 		rc = -ENODEV;
 		goto out_remove;
 	}
+	qeth_trace_features(card);
 
 	if (!card->dev && qeth_l3_setup_netdev(card)) {
 		rc = -ENODEV;
@@ -3714,9 +3714,9 @@ static void qeth_l3_unregister_notifiers(void)
 {
 
 	QETH_DBF_TEXT(SETUP, 5, "unregnot");
-	BUG_ON(unregister_inetaddr_notifier(&qeth_l3_ip_notifier));
+	WARN_ON(unregister_inetaddr_notifier(&qeth_l3_ip_notifier));
 #ifdef CONFIG_QETH_IPV6
-	BUG_ON(unregister_inet6addr_notifier(&qeth_l3_ip6_notifier));
+	WARN_ON(unregister_inet6addr_notifier(&qeth_l3_ip6_notifier));
 #endif /* QETH_IPV6 */
 }
 
diff --git a/drivers/sbus/char/Kconfig b/drivers/sbus/char/Kconfig
index 73cde85..5ba684f 100644
--- a/drivers/sbus/char/Kconfig
+++ b/drivers/sbus/char/Kconfig
@@ -21,8 +21,7 @@ config OBP_FLASH
 	  able to upgrade the OBP firmware, say Y here.
 
 config TADPOLE_TS102_UCTRL
-	tristate "Tadpole TS102 Microcontroller support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	tristate "Tadpole TS102 Microcontroller support"
 	help
 	  Say Y here to directly support the TS102 Microcontroller interface
 	  on the Tadpole Sparcbook 3.  This device handles power-management
@@ -30,8 +29,8 @@ config TADPOLE_TS102_UCTRL
 	  monitors and mice.
 
 config SUN_JSFLASH
-	tristate "JavaStation OS Flash SIMM (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && SPARC32
+	tristate "JavaStation OS Flash SIMM"
+	depends on SPARC32
 	help
 	  If you say Y here, you will be able to boot from your JavaStation's
 	  Flash memory.
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 74bf1aa..af7a3e7 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1812,6 +1812,7 @@ config SCSI_VIRTIO
           This is the virtual HBA driver for virtio.  If the kernel will
           be used in a virtual machine, say Y or M.
 
+source "drivers/scsi/csiostor/Kconfig"
 
 endif # SCSI_LOWLEVEL
 
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 888f73a..8739aa7 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -90,6 +90,7 @@ obj-$(CONFIG_SCSI_QLA_FC)	+= qla2xxx/
 obj-$(CONFIG_SCSI_QLA_ISCSI)	+= libiscsi.o qla4xxx/
 obj-$(CONFIG_SCSI_LPFC)		+= lpfc/
 obj-$(CONFIG_SCSI_BFA_FC)	+= bfa/
+obj-$(CONFIG_SCSI_CHELSIO_FCOE)	+= csiostor/
 obj-$(CONFIG_SCSI_PAS16)	+= pas16.o
 obj-$(CONFIG_SCSI_T128)		+= t128.o
 obj-$(CONFIG_SCSI_DMX3191D)	+= dmx3191d.o
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index d79457a..681434e 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -132,11 +132,13 @@ struct inquiry_data {
  *              M O D U L E   G L O B A L S
  */
 
-static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap);
-static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg);
-static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg);
-static unsigned long aac_build_sgraw2(struct scsi_cmnd *scsicmd, struct aac_raw_io2 *rio2, int sg_max);
-static int aac_convert_sgraw2(struct aac_raw_io2 *rio2, int pages, int nseg, int nseg_new);
+static long aac_build_sg(struct scsi_cmnd *scsicmd, struct sgmap *sgmap);
+static long aac_build_sg64(struct scsi_cmnd *scsicmd, struct sgmap64 *psg);
+static long aac_build_sgraw(struct scsi_cmnd *scsicmd, struct sgmapraw *psg);
+static long aac_build_sgraw2(struct scsi_cmnd *scsicmd,
+				struct aac_raw_io2 *rio2, int sg_max);
+static int aac_convert_sgraw2(struct aac_raw_io2 *rio2,
+				int pages, int nseg, int nseg_new);
 static int aac_send_srb_fib(struct scsi_cmnd* scsicmd);
 #ifdef AAC_DETAILED_STATUS_INFO
 static char *aac_get_status_string(u32 status);
@@ -971,6 +973,7 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
 {
 	struct aac_dev *dev = fib->dev;
 	u16 fibsize, command;
+	long ret;
 
 	aac_fib_init(fib);
 	if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 && !dev->sync_mode) {
@@ -982,7 +985,10 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
 		readcmd2->byteCount = cpu_to_le32(count<<9);
 		readcmd2->cid = cpu_to_le16(scmd_id(cmd));
 		readcmd2->flags = cpu_to_le16(RIO2_IO_TYPE_READ);
-		aac_build_sgraw2(cmd, readcmd2, dev->scsi_host_ptr->sg_tablesize);
+		ret = aac_build_sgraw2(cmd, readcmd2,
+				dev->scsi_host_ptr->sg_tablesize);
+		if (ret < 0)
+			return ret;
 		command = ContainerRawIo2;
 		fibsize = sizeof(struct aac_raw_io2) +
 			((le32_to_cpu(readcmd2->sgeCnt)-1) * sizeof(struct sge_ieee1212));
@@ -996,7 +1002,9 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
 		readcmd->flags = cpu_to_le16(RIO_TYPE_READ);
 		readcmd->bpTotal = 0;
 		readcmd->bpComplete = 0;
-		aac_build_sgraw(cmd, &readcmd->sg);
+		ret = aac_build_sgraw(cmd, &readcmd->sg);
+		if (ret < 0)
+			return ret;
 		command = ContainerRawIo;
 		fibsize = sizeof(struct aac_raw_io) +
 			((le32_to_cpu(readcmd->sg.count)-1) * sizeof(struct sgentryraw));
@@ -1019,6 +1027,8 @@ static int aac_read_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u
 {
 	u16 fibsize;
 	struct aac_read64 *readcmd;
+	long ret;
+
 	aac_fib_init(fib);
 	readcmd = (struct aac_read64 *) fib_data(fib);
 	readcmd->command = cpu_to_le32(VM_CtHostRead64);
@@ -1028,7 +1038,9 @@ static int aac_read_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u
 	readcmd->pad   = 0;
 	readcmd->flags = 0;
 
-	aac_build_sg64(cmd, &readcmd->sg);
+	ret = aac_build_sg64(cmd, &readcmd->sg);
+	if (ret < 0)
+		return ret;
 	fibsize = sizeof(struct aac_read64) +
 		((le32_to_cpu(readcmd->sg.count) - 1) *
 		 sizeof (struct sgentry64));
@@ -1050,6 +1062,8 @@ static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32
 {
 	u16 fibsize;
 	struct aac_read *readcmd;
+	long ret;
+
 	aac_fib_init(fib);
 	readcmd = (struct aac_read *) fib_data(fib);
 	readcmd->command = cpu_to_le32(VM_CtBlockRead);
@@ -1057,7 +1071,9 @@ static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32
 	readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
 	readcmd->count = cpu_to_le32(count * 512);
 
-	aac_build_sg(cmd, &readcmd->sg);
+	ret = aac_build_sg(cmd, &readcmd->sg);
+	if (ret < 0)
+		return ret;
 	fibsize = sizeof(struct aac_read) +
 			((le32_to_cpu(readcmd->sg.count) - 1) *
 			 sizeof (struct sgentry));
@@ -1079,6 +1095,7 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u
 {
 	struct aac_dev *dev = fib->dev;
 	u16 fibsize, command;
+	long ret;
 
 	aac_fib_init(fib);
 	if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 && !dev->sync_mode) {
@@ -1093,7 +1110,10 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u
 						   (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ?
 			cpu_to_le16(RIO2_IO_TYPE_WRITE|RIO2_IO_SUREWRITE) :
 			cpu_to_le16(RIO2_IO_TYPE_WRITE);
-		aac_build_sgraw2(cmd, writecmd2, dev->scsi_host_ptr->sg_tablesize);
+		ret = aac_build_sgraw2(cmd, writecmd2,
+				dev->scsi_host_ptr->sg_tablesize);
+		if (ret < 0)
+			return ret;
 		command = ContainerRawIo2;
 		fibsize = sizeof(struct aac_raw_io2) +
 			((le32_to_cpu(writecmd2->sgeCnt)-1) * sizeof(struct sge_ieee1212));
@@ -1110,7 +1130,9 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u
 			cpu_to_le16(RIO_TYPE_WRITE);
 		writecmd->bpTotal = 0;
 		writecmd->bpComplete = 0;
-		aac_build_sgraw(cmd, &writecmd->sg);
+		ret = aac_build_sgraw(cmd, &writecmd->sg);
+		if (ret < 0)
+			return ret;
 		command = ContainerRawIo;
 		fibsize = sizeof(struct aac_raw_io) +
 			((le32_to_cpu(writecmd->sg.count)-1) * sizeof (struct sgentryraw));
@@ -1133,6 +1155,8 @@ static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba,
 {
 	u16 fibsize;
 	struct aac_write64 *writecmd;
+	long ret;
+
 	aac_fib_init(fib);
 	writecmd = (struct aac_write64 *) fib_data(fib);
 	writecmd->command = cpu_to_le32(VM_CtHostWrite64);
@@ -1142,7 +1166,9 @@ static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba,
 	writecmd->pad	= 0;
 	writecmd->flags	= 0;
 
-	aac_build_sg64(cmd, &writecmd->sg);
+	ret = aac_build_sg64(cmd, &writecmd->sg);
+	if (ret < 0)
+		return ret;
 	fibsize = sizeof(struct aac_write64) +
 		((le32_to_cpu(writecmd->sg.count) - 1) *
 		 sizeof (struct sgentry64));
@@ -1164,6 +1190,8 @@ static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
 {
 	u16 fibsize;
 	struct aac_write *writecmd;
+	long ret;
+
 	aac_fib_init(fib);
 	writecmd = (struct aac_write *) fib_data(fib);
 	writecmd->command = cpu_to_le32(VM_CtBlockWrite);
@@ -1173,7 +1201,9 @@ static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
 	writecmd->sg.count = cpu_to_le32(1);
 	/* ->stable is not used - it did mean which type of write */
 
-	aac_build_sg(cmd, &writecmd->sg);
+	ret = aac_build_sg(cmd, &writecmd->sg);
+	if (ret < 0)
+		return ret;
 	fibsize = sizeof(struct aac_write) +
 		((le32_to_cpu(writecmd->sg.count) - 1) *
 		 sizeof (struct sgentry));
@@ -1235,8 +1265,11 @@ static int aac_scsi_64(struct fib * fib, struct scsi_cmnd * cmd)
 {
 	u16 fibsize;
 	struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
+	long ret;
 
-	aac_build_sg64(cmd, (struct sgmap64*) &srbcmd->sg);
+	ret = aac_build_sg64(cmd, (struct sgmap64 *) &srbcmd->sg);
+	if (ret < 0)
+		return ret;
 	srbcmd->count = cpu_to_le32(scsi_bufflen(cmd));
 
 	memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
@@ -1263,8 +1296,11 @@ static int aac_scsi_32(struct fib * fib, struct scsi_cmnd * cmd)
 {
 	u16 fibsize;
 	struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
+	long ret;
 
-	aac_build_sg(cmd, (struct sgmap*)&srbcmd->sg);
+	ret = aac_build_sg(cmd, (struct sgmap *)&srbcmd->sg);
+	if (ret < 0)
+		return ret;
 	srbcmd->count = cpu_to_le32(scsi_bufflen(cmd));
 
 	memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
@@ -2870,7 +2906,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
 	return -1;
 }
 
-static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
+static long aac_build_sg(struct scsi_cmnd *scsicmd, struct sgmap *psg)
 {
 	struct aac_dev *dev;
 	unsigned long byte_count = 0;
@@ -2883,7 +2919,8 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
 	psg->sg[0].count = 0;
 
 	nseg = scsi_dma_map(scsicmd);
-	BUG_ON(nseg < 0);
+	if (nseg < 0)
+		return nseg;
 	if (nseg) {
 		struct scatterlist *sg;
 		int i;
@@ -2912,7 +2949,7 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
 }
 
 
-static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg)
+static long aac_build_sg64(struct scsi_cmnd *scsicmd, struct sgmap64 *psg)
 {
 	struct aac_dev *dev;
 	unsigned long byte_count = 0;
@@ -2927,7 +2964,8 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
 	psg->sg[0].count = 0;
 
 	nseg = scsi_dma_map(scsicmd);
-	BUG_ON(nseg < 0);
+	if (nseg < 0)
+		return nseg;
 	if (nseg) {
 		struct scatterlist *sg;
 		int i;
@@ -2957,7 +2995,7 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
 	return byte_count;
 }
 
-static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg)
+static long aac_build_sgraw(struct scsi_cmnd *scsicmd, struct sgmapraw *psg)
 {
 	unsigned long byte_count = 0;
 	int nseg;
@@ -2972,7 +3010,8 @@ static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw*
 	psg->sg[0].flags = 0;
 
 	nseg = scsi_dma_map(scsicmd);
-	BUG_ON(nseg < 0);
+	if (nseg < 0)
+		return nseg;
 	if (nseg) {
 		struct scatterlist *sg;
 		int i;
@@ -3005,13 +3044,15 @@ static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw*
 	return byte_count;
 }
 
-static unsigned long aac_build_sgraw2(struct scsi_cmnd *scsicmd, struct aac_raw_io2 *rio2, int sg_max)
+static long aac_build_sgraw2(struct scsi_cmnd *scsicmd,
+				struct aac_raw_io2 *rio2, int sg_max)
 {
 	unsigned long byte_count = 0;
 	int nseg;
 
 	nseg = scsi_dma_map(scsicmd);
-	BUG_ON(nseg < 0);
+	if (nseg < 0)
+		return nseg;
 	if (nseg) {
 		struct scatterlist *sg;
 		int i, conformable = 0;
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 9e933a8..742f5d7 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -12,7 +12,7 @@
  *----------------------------------------------------------------------------*/
 
 #ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 29800
+# define AAC_DRIVER_BUILD 29801
 # define AAC_DRIVER_BRANCH "-ms"
 #endif
 #define MAXIMUM_NUM_CONTAINERS	32
diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h
index a50b6a9..f1733df 100644
--- a/drivers/scsi/be2iscsi/be.h
+++ b/drivers/scsi/be2iscsi/be.h
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -28,7 +28,7 @@
 /* BladeEngine Generation numbers */
 #define BE_GEN2 2
 #define BE_GEN3 3
-
+#define BE_GEN4	4
 struct be_dma_mem {
 	void *va;
 	dma_addr_t dma;
@@ -84,9 +84,12 @@ static inline void queue_tail_inc(struct be_queue_info *q)
 /*ISCSI */
 
 struct be_eq_obj {
+	bool todo_mcc_cq;
+	bool todo_cq;
 	struct be_queue_info q;
 	struct beiscsi_hba *phba;
 	struct be_queue_info *cq;
+	struct work_struct work_cqs; /* Work Item */
 	struct blk_iopoll	iopoll;
 };
 
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
index 07d2cb1..5c87768 100644
--- a/drivers/scsi/be2iscsi/be_cmds.c
+++ b/drivers/scsi/be2iscsi/be_cmds.c
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -56,7 +56,7 @@ int beiscsi_pci_soft_reset(struct beiscsi_hba *phba)
 	writel(pconline0, (void *)pci_online0_offset);
 	writel(pconline1, (void *)pci_online1_offset);
 
-	sreset = BE2_SET_RESET;
+	sreset |= BE2_SET_RESET;
 	writel(sreset, (void *)pci_reset_offset);
 
 	i = 0;
@@ -133,6 +133,87 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba)
 	return tag;
 }
 
+/*
+ * beiscsi_mccq_compl()- Wait for completion of MBX
+ * @phba: Driver private structure
+ * @tag: Tag for the MBX Command
+ * @wrb: the WRB used for the MBX Command
+ * @cmd_hdr: IOCTL Hdr for the MBX Cmd
+ *
+ * Waits for MBX completion with the passed TAG.
+ *
+ * return
+ * Success: 0
+ * Failure: Non-Zero
+ **/
+int beiscsi_mccq_compl(struct beiscsi_hba *phba,
+		uint32_t tag, struct be_mcc_wrb **wrb,
+		void *cmd_hdr)
+{
+	int rc = 0;
+	uint32_t mcc_tag_response;
+	uint16_t status = 0, addl_status = 0, wrb_num = 0;
+	struct be_mcc_wrb *temp_wrb;
+	struct be_cmd_req_hdr *ioctl_hdr;
+	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+
+	if (beiscsi_error(phba))
+		return -EIO;
+
+	/* wait for the mccq completion */
+	rc = wait_event_interruptible_timeout(
+				phba->ctrl.mcc_wait[tag],
+				phba->ctrl.mcc_numtag[tag],
+				msecs_to_jiffies(
+				BEISCSI_HOST_MBX_TIMEOUT));
+
+	if (rc <= 0) {
+		beiscsi_log(phba, KERN_ERR,
+			    BEISCSI_LOG_INIT | BEISCSI_LOG_EH |
+			    BEISCSI_LOG_CONFIG,
+			    "BC_%d : MBX Cmd Completion timed out\n");
+		rc = -EAGAIN;
+		goto release_mcc_tag;
+	} else
+		rc = 0;
+
+	mcc_tag_response = phba->ctrl.mcc_numtag[tag];
+	status = (mcc_tag_response & CQE_STATUS_MASK);
+	addl_status = ((mcc_tag_response & CQE_STATUS_ADDL_MASK) >>
+			CQE_STATUS_ADDL_SHIFT);
+
+	if (cmd_hdr) {
+		ioctl_hdr = (struct be_cmd_req_hdr *)cmd_hdr;
+	} else {
+		wrb_num = (mcc_tag_response & CQE_STATUS_WRB_MASK) >>
+			   CQE_STATUS_WRB_SHIFT;
+		temp_wrb = (struct be_mcc_wrb *)queue_get_wrb(mccq, wrb_num);
+		ioctl_hdr = embedded_payload(temp_wrb);
+
+		if (wrb)
+			*wrb = temp_wrb;
+	}
+
+	if (status || addl_status) {
+		beiscsi_log(phba, KERN_ERR,
+			    BEISCSI_LOG_INIT | BEISCSI_LOG_EH |
+			    BEISCSI_LOG_CONFIG,
+			    "BC_%d : MBX Cmd Failed for "
+			    "Subsys : %d Opcode : %d with "
+			    "Status : %d and Extd_Status : %d\n",
+			    ioctl_hdr->subsystem,
+			    ioctl_hdr->opcode,
+			    status, addl_status);
+		rc = -EAGAIN;
+	}
+
+release_mcc_tag:
+	/* Release the MCC entry */
+	free_mcc_tag(&phba->ctrl, tag);
+
+	return rc;
+}
+
 void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag)
 {
 	spin_lock(&ctrl->mbox_lock);
@@ -168,11 +249,24 @@ static inline void be_mcc_compl_use(struct be_mcc_compl *compl)
 	compl->flags = 0;
 }
 
+/*
+ * be_mcc_compl_process()- Check the MBX comapletion status
+ * @ctrl: Function specific MBX data structure
+ * @compl: Completion status of MBX Command
+ *
+ * Check for the MBX completion status when BMBX method used
+ *
+ * return
+ * Success: Zero
+ * Failure: Non-Zero
+ **/
 static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
 				struct be_mcc_compl *compl)
 {
 	u16 compl_status, extd_status;
+	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
 	struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
+	struct be_cmd_req_hdr *hdr = embedded_payload(wrb);
 
 	be_dws_le_to_cpu(compl, 4);
 
@@ -184,7 +278,10 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
 
 		beiscsi_log(phba, KERN_ERR,
 			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-			    "BC_%d : error in cmd completion: status(compl/extd)=%d/%d\n",
+			    "BC_%d : error in cmd completion: "
+			    "Subsystem : %d Opcode : %d "
+			    "status(compl/extd)=%d/%d\n",
+			    hdr->subsystem, hdr->opcode,
 			    compl_status, extd_status);
 
 		return -EBUSY;
@@ -314,11 +411,24 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba)
 	return status;
 }
 
-/* Wait till no more pending mcc requests are present */
+/*
+ * be_mcc_wait_compl()- Wait for MBX completion
+ * @phba: driver private structure
+ *
+ * Wait till no more pending mcc requests are present
+ *
+ * return
+ * Success: 0
+ * Failure: Non-Zero
+ *
+ **/
 static int be_mcc_wait_compl(struct beiscsi_hba *phba)
 {
 	int i, status;
 	for (i = 0; i < mcc_timeout; i++) {
+		if (beiscsi_error(phba))
+			return -EIO;
+
 		status = beiscsi_process_mcc(phba);
 		if (status)
 			return status;
@@ -330,51 +440,83 @@ static int be_mcc_wait_compl(struct beiscsi_hba *phba)
 	if (i == mcc_timeout) {
 		beiscsi_log(phba, KERN_ERR,
 			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-			    "BC_%d : mccq poll timed out\n");
-
+			    "BC_%d : FW Timed Out\n");
+		phba->fw_timeout = true;
+		beiscsi_ue_detect(phba);
 		return -EBUSY;
 	}
 	return 0;
 }
 
-/* Notify MCC requests and wait for completion */
+/*
+ * be_mcc_notify_wait()- Notify and wait for Compl
+ * @phba: driver private structure
+ *
+ * Notify MCC requests and wait for completion
+ *
+ * return
+ * Success: 0
+ * Failure: Non-Zero
+ **/
 int be_mcc_notify_wait(struct beiscsi_hba *phba)
 {
 	be_mcc_notify(phba);
 	return be_mcc_wait_compl(phba);
 }
 
+/*
+ * be_mbox_db_ready_wait()- Check ready status
+ * @ctrl: Function specific MBX data structure
+ *
+ * Check for the ready status of FW to send BMBX
+ * commands to adapter.
+ *
+ * return
+ * Success: 0
+ * Failure: Non-Zero
+ **/
 static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
 {
-#define long_delay 2000
 	void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
-	int cnt = 0, wait = 5;	/* in usecs */
+	struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
+	int wait = 0;
 	u32 ready;
 
 	do {
+
+		if (beiscsi_error(phba))
+			return -EIO;
+
 		ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK;
 		if (ready)
 			break;
 
-		if (cnt > 12000000) {
-			struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
+		if (wait > BEISCSI_HOST_MBX_TIMEOUT) {
 			beiscsi_log(phba, KERN_ERR,
 				    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-				    "BC_%d : mbox_db poll timed out\n");
-
+				    "BC_%d : FW Timed Out\n");
+			phba->fw_timeout = true;
+			beiscsi_ue_detect(phba);
 			return -EBUSY;
 		}
 
-		if (cnt > 50) {
-			wait = long_delay;
-			mdelay(long_delay / 1000);
-		} else
-			udelay(wait);
-		cnt += wait;
+		mdelay(1);
+		wait++;
 	} while (true);
 	return 0;
 }
 
+/*
+ * be_mbox_notify: Notify adapter of new BMBX command
+ * @ctrl: Function specific MBX data structure
+ *
+ * Ring doorbell to inform adapter of a BMBX command
+ * to process
+ *
+ * return
+ * Success: 0
+ * Failure: Non-Zero
+ **/
 int be_mbox_notify(struct be_ctrl_info *ctrl)
 {
 	int status;
@@ -391,13 +533,9 @@ int be_mbox_notify(struct be_ctrl_info *ctrl)
 	iowrite32(val, db);
 
 	status = be_mbox_db_ready_wait(ctrl);
-	if (status != 0) {
-		beiscsi_log(phba, KERN_ERR,
-			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-			    "BC_%d : be_mbox_db_ready_wait failed\n");
-
+	if (status)
 		return status;
-	}
+
 	val = 0;
 	val &= ~MPU_MAILBOX_DB_RDY_MASK;
 	val &= ~MPU_MAILBOX_DB_HI_MASK;
@@ -405,13 +543,9 @@ int be_mbox_notify(struct be_ctrl_info *ctrl)
 	iowrite32(val, db);
 
 	status = be_mbox_db_ready_wait(ctrl);
-	if (status != 0) {
-		beiscsi_log(phba, KERN_ERR,
-			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-			    "BC_%d : be_mbox_db_ready_wait failed\n");
-
+	if (status)
 		return status;
-	}
+
 	if (be_mcc_compl_is_new(compl)) {
 		status = be_mcc_compl_process(ctrl, &mbox->compl);
 		be_mcc_compl_use(compl);
@@ -499,7 +633,7 @@ void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
 	req_hdr->opcode = opcode;
 	req_hdr->subsystem = subsystem;
 	req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
-	req_hdr->timeout = 120;
+	req_hdr->timeout = BEISCSI_FW_MBX_TIMEOUT;
 }
 
 static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages,
@@ -649,18 +783,34 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
 			OPCODE_COMMON_CQ_CREATE, sizeof(*req));
 
 	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
+	if (chip_skh_r(ctrl->pdev)) {
+		req->hdr.version = MBX_CMD_VER2;
+		req->page_size = 1;
+		AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm,
+			      ctxt, coalesce_wm);
+		AMAP_SET_BITS(struct amap_cq_context_v2, nodelay,
+			      ctxt, no_delay);
+		AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt,
+			      __ilog2_u32(cq->len / 256));
+		AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1);
+		AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1);
+		AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id);
+		AMAP_SET_BITS(struct amap_cq_context_v2, armed, ctxt, 1);
+	} else {
+		AMAP_SET_BITS(struct amap_cq_context, coalescwm,
+			      ctxt, coalesce_wm);
+		AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay);
+		AMAP_SET_BITS(struct amap_cq_context, count, ctxt,
+			      __ilog2_u32(cq->len / 256));
+		AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1);
+		AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts);
+		AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1);
+		AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id);
+		AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1);
+		AMAP_SET_BITS(struct amap_cq_context, func, ctxt,
+			      PCI_FUNC(ctrl->pdev->devfn));
+	}
 
-	AMAP_SET_BITS(struct amap_cq_context, coalescwm, ctxt, coalesce_wm);
-	AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay);
-	AMAP_SET_BITS(struct amap_cq_context, count, ctxt,
-		      __ilog2_u32(cq->len / 256));
-	AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1);
-	AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts);
-	AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1);
-	AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id);
-	AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1);
-	AMAP_SET_BITS(struct amap_cq_context, func, ctxt,
-		      PCI_FUNC(ctrl->pdev->devfn));
 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
 
 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h
index 2c8f98d..23397d5 100644
--- a/drivers/scsi/be2iscsi/be_cmds.h
+++ b/drivers/scsi/be2iscsi/be_cmds.h
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -57,6 +57,16 @@ struct be_mcc_wrb {
 #define CQE_STATUS_COMPL_SHIFT 0	/* bits 0 - 15 */
 #define CQE_STATUS_EXTD_MASK 0xFFFF
 #define CQE_STATUS_EXTD_SHIFT 16		/* bits 0 - 15 */
+#define CQE_STATUS_ADDL_MASK	0xFF00
+#define CQE_STATUS_MASK	0xFF
+#define CQE_STATUS_ADDL_SHIFT	0x08
+#define CQE_STATUS_WRB_MASK	0xFF0000
+#define CQE_STATUS_WRB_SHIFT	16
+#define BEISCSI_HOST_MBX_TIMEOUT (110 * 1000)
+#define BEISCSI_FW_MBX_TIMEOUT	100
+
+/* MBOX Command VER */
+#define MBX_CMD_VER2	0x02
 
 struct be_mcc_compl {
 	u32 status;		/* dword 0 */
@@ -183,7 +193,8 @@ struct be_cmd_req_hdr {
 	u8 domain;		/* dword 0 */
 	u32 timeout;		/* dword 1 */
 	u32 request_length;	/* dword 2 */
-	u32 rsvd0;		/* dword 3 */
+	u8 version;		/* dword 3 */
+	u8 rsvd0[3];		/* dword 3 */
 };
 
 struct be_cmd_resp_hdr {
@@ -483,10 +494,28 @@ struct amap_cq_context {
 	u8 rsvd5[32];		/* dword 3 */
 } __packed;
 
+struct amap_cq_context_v2 {
+	u8 rsvd0[12];   /* dword 0 */
+	u8 coalescwm[2];    /* dword 0 */
+	u8 nodelay;     /* dword 0 */
+	u8 rsvd1[12];   /* dword 0 */
+	u8 count[2];    /* dword 0 */
+	u8 valid;       /* dword 0 */
+	u8 rsvd2;       /* dword 0 */
+	u8 eventable;   /* dword 0 */
+	u8 eqid[16];    /* dword 1 */
+	u8 rsvd3[15];   /* dword 1 */
+	u8 armed;       /* dword 1 */
+	u8 cqecount[16];/* dword 2 */
+	u8 rsvd4[16];   /* dword 2 */
+	u8 rsvd5[32];   /* dword 3 */
+};
+
 struct be_cmd_req_cq_create {
 	struct be_cmd_req_hdr hdr;
 	u16 num_pages;
-	u16 rsvd0;
+	u8 page_size;
+	u8 rsvd0;
 	u8 context[sizeof(struct amap_cq_context) / 8];
 	struct phys_addr pages[4];
 } __packed;
@@ -663,6 +692,9 @@ unsigned int be_cmd_get_initname(struct beiscsi_hba *phba);
 unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba);
 
 void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag);
+
+int beiscsi_mccq_compl(struct beiscsi_hba *phba,
+			uint32_t tag, struct be_mcc_wrb **wrb, void *cmd_va);
 /*ISCSI Functuions */
 int be_cmd_fw_initialize(struct be_ctrl_info *ctrl);
 
@@ -804,6 +836,59 @@ struct amap_sol_cqe_ring {
 	u8 valid;		/* dword 3 */
 } __packed;
 
+struct amap_sol_cqe_v2 {
+	u8 hw_sts[8];   /* dword 0 */
+	u8 i_sts[8];    /* dword 0 */
+	u8 wrb_index[16];   /* dword 0 */
+	u8 i_exp_cmd_sn[32];    /* dword 1 */
+	u8 code[6]; /* dword 2 */
+	u8 cmd_cmpl;    /* dword 2 */
+	u8 rsvd0;   /* dword 2 */
+	u8 i_cmd_wnd[8];    /* dword 2 */
+	u8 cid[13]; /* dword 2 */
+	u8 u;   /* dword 2 */
+	u8 o;   /* dword 2 */
+	u8 s;   /* dword 2 */
+	u8 i_res_cnt[31];   /* dword 3 */
+	u8 valid;   /* dword 3 */
+} __packed;
+
+struct common_sol_cqe {
+	u32 exp_cmdsn;
+	u32 res_cnt;
+	u16 wrb_index;
+	u16 cid;
+	u8 hw_sts;
+	u8 cmd_wnd;
+	u8 res_flag; /* the s feild of structure */
+	u8 i_resp; /* for skh if cmd_complete is set then i_sts is response */
+	u8 i_flags; /* for skh or the u and o feilds */
+	u8 i_sts; /* for skh if cmd_complete is not-set then i_sts is status */
+};
+
+/*** iSCSI ack/driver message completions ***/
+struct amap_it_dmsg_cqe {
+	u8 ack_num[32]; /* DWORD 0 */
+	u8 pdu_bytes_rcvd[32];  /* DWORD 1 */
+	u8 code[6]; /* DWORD 2 */
+	u8 cid[10]; /* DWORD 2 */
+	u8 wrb_idx[8];  /* DWORD 2 */
+	u8 rsvd0[8];    /* DWORD 2*/
+	u8 rsvd1[31];   /* DWORD 3*/
+	u8 valid;   /* DWORD 3 */
+} __packed;
+
+struct amap_it_dmsg_cqe_v2 {
+	u8 ack_num[32]; /* DWORD 0 */
+	u8 pdu_bytes_rcvd[32];  /* DWORD 1 */
+	u8 code[6]; /* DWORD 2 */
+	u8 rsvd0[10];   /* DWORD 2 */
+	u8 wrb_idx[16]; /* DWORD 2 */
+	u8 rsvd1[16];   /* DWORD 3 */
+	u8 cid[13]; /* DWORD 3 */
+	u8 rsvd2[2];    /* DWORD 3 */
+	u8 valid;   /* DWORD 3 */
+} __packed;
 
 
 /**
@@ -992,8 +1077,6 @@ struct be_cmd_get_all_if_id_req {
 #define CONNECTION_UPLOAD_ABORT_WITH_SEQ 4	/* Abortive upload with reset,
 						 * sequence number by driver  */
 
-/* Returns byte size of given field with a structure. */
-
 /* Returns the number of items in the field array. */
 #define BE_NUMBER_OF_FIELD(_type_, _field_)	\
 	(FIELD_SIZEOF(_type_, _field_)/sizeof((((_type_ *)0)->_field_[0])))\
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index aedb0d9..214d691 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -531,9 +531,9 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba,
 		break;
 	case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
 		if (!if_info.dhcp_state)
-			len = sprintf(buf, "static");
+			len = sprintf(buf, "static\n");
 		else
-			len = sprintf(buf, "dhcp");
+			len = sprintf(buf, "dhcp\n");
 		break;
 	case ISCSI_NET_PARAM_IPV4_SUBNET:
 		len = sprintf(buf, "%pI4\n", &if_info.ip_addr.subnet_mask);
@@ -541,7 +541,7 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba,
 	case ISCSI_NET_PARAM_VLAN_ENABLED:
 		len = sprintf(buf, "%s\n",
 			     (if_info.vlan_priority == BEISCSI_VLAN_DISABLE)
-			     ? "Disabled" : "Enabled");
+			     ? "Disabled\n" : "Enabled\n");
 		break;
 	case ISCSI_NET_PARAM_VLAN_ID:
 		if (if_info.vlan_priority == BEISCSI_VLAN_DISABLE)
@@ -586,7 +586,7 @@ int be2iscsi_iface_get_param(struct iscsi_iface *iface,
 		len = be2iscsi_get_if_param(phba, iface, param, buf);
 		break;
 	case ISCSI_NET_PARAM_IFACE_ENABLE:
-		len = sprintf(buf, "enabled");
+		len = sprintf(buf, "enabled\n");
 		break;
 	case ISCSI_NET_PARAM_IPV4_GW:
 		memset(&gateway, 0, sizeof(gateway));
@@ -690,11 +690,9 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
 static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba)
 {
 	int rc;
-	unsigned int tag, wrb_num;
-	unsigned short status, extd_status;
+	unsigned int tag;
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_hba_name *resp;
-	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
 
 	tag = be_cmd_get_initname(phba);
 	if (!tag) {
@@ -702,26 +700,16 @@ static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba)
 			    "BS_%d : Getting Initiator Name Failed\n");
 
 		return -EBUSY;
-	} else
-		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-				phba->ctrl.mcc_numtag[tag]);
-
-	wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
-	extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-	status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
+	}
 
-	if (status || extd_status) {
+	rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
+	if (rc) {
 		beiscsi_log(phba, KERN_ERR,
 			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-			    "BS_%d : MailBox Command Failed with "
-			    "status = %d extd_status = %d\n",
-			    status, extd_status);
-
-		free_mcc_tag(&phba->ctrl, tag);
-		return -EAGAIN;
+			    "BS_%d : Initiator Name MBX Failed\n");
+		return rc;
 	}
-	wrb = queue_get_wrb(mccq, wrb_num);
-	free_mcc_tag(&phba->ctrl, tag);
+
 	resp = embedded_payload(wrb);
 	rc = sprintf(buf, "%s\n", resp->initiator_name);
 	return rc;
@@ -731,7 +719,6 @@ static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba)
  * beiscsi_get_port_state - Get the Port State
  * @shost : pointer to scsi_host structure
  *
- * returns number of bytes
  */
 static void beiscsi_get_port_state(struct Scsi_Host *shost)
 {
@@ -750,13 +737,12 @@ static void beiscsi_get_port_state(struct Scsi_Host *shost)
  */
 static int beiscsi_get_port_speed(struct Scsi_Host *shost)
 {
-	unsigned int tag, wrb_num;
-	unsigned short status, extd_status;
+	int rc;
+	unsigned int tag;
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_ntwk_link_status_resp *resp;
 	struct beiscsi_hba *phba = iscsi_host_priv(shost);
 	struct iscsi_cls_host *ihost = shost->shost_data;
-	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
 
 	tag = be_cmd_get_port_speed(phba);
 	if (!tag) {
@@ -764,26 +750,14 @@ static int beiscsi_get_port_speed(struct Scsi_Host *shost)
 			    "BS_%d : Getting Port Speed Failed\n");
 
 		 return -EBUSY;
-	 } else
-		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-				phba->ctrl.mcc_numtag[tag]);
-
-	wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
-	extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-	status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
-
-	if (status || extd_status) {
+	}
+	rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
+	if (rc) {
 		beiscsi_log(phba, KERN_ERR,
 			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-			    "BS_%d : MailBox Command Failed with "
-			    "status = %d extd_status = %d\n",
-			    status, extd_status);
-
-		free_mcc_tag(&phba->ctrl, tag);
-		return -EAGAIN;
+			    "BS_%d : Port Speed MBX Failed\n");
+		return rc;
 	}
-	wrb = queue_get_wrb(mccq, wrb_num);
-	free_mcc_tag(&phba->ctrl, tag);
 	resp = embedded_payload(wrb);
 
 	switch (resp->mac_speed) {
@@ -937,6 +911,14 @@ static void  beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn,
 		      session->initial_r2t_en);
 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, imd, params,
 		      session->imm_data_en);
+	AMAP_SET_BITS(struct amap_beiscsi_offload_params,
+		      data_seq_inorder, params,
+		      session->dataseq_inorder_en);
+	AMAP_SET_BITS(struct amap_beiscsi_offload_params,
+		      pdu_seq_inorder, params,
+		      session->pdu_inorder_en);
+	AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_r2t, params,
+		      session->max_r2t);
 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params,
 		      (conn->exp_statsn - 1));
 }
@@ -1027,12 +1009,10 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
 {
 	struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
 	struct beiscsi_hba *phba = beiscsi_ep->phba;
-	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
 	struct be_mcc_wrb *wrb;
 	struct tcp_connect_and_offload_out *ptcpcnct_out;
-	unsigned short status, extd_status;
 	struct be_dma_mem nonemb_cmd;
-	unsigned int tag, wrb_num;
+	unsigned int tag;
 	int ret = -ENOMEM;
 
 	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
@@ -1084,35 +1064,26 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
 		pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
 				    nonemb_cmd.va, nonemb_cmd.dma);
 		return -EAGAIN;
-	} else {
-		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-					 phba->ctrl.mcc_numtag[tag]);
 	}
-	wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
-	extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-	status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
-	if (status || extd_status) {
+
+	ret = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
+	if (ret) {
 		beiscsi_log(phba, KERN_ERR,
 			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-			    "BS_%d : mgmt_open_connection Failed"
-			    " status = %d extd_status = %d\n",
-			    status, extd_status);
+			    "BS_%d : mgmt_open_connection Failed");
 
-		free_mcc_tag(&phba->ctrl, tag);
 		pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
 			    nonemb_cmd.va, nonemb_cmd.dma);
 		goto free_ep;
-	} else {
-		wrb = queue_get_wrb(mccq, wrb_num);
-		free_mcc_tag(&phba->ctrl, tag);
-
-		ptcpcnct_out = embedded_payload(wrb);
-		beiscsi_ep = ep->dd_data;
-		beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle;
-		beiscsi_ep->cid_vld = 1;
-		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
-			    "BS_%d : mgmt_open_connection Success\n");
 	}
+
+	ptcpcnct_out = embedded_payload(wrb);
+	beiscsi_ep = ep->dd_data;
+	beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle;
+	beiscsi_ep->cid_vld = 1;
+	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
+		    "BS_%d : mgmt_open_connection Success\n");
+
 	pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
 			    nonemb_cmd.va, nonemb_cmd.dma);
 	return 0;
@@ -1150,8 +1121,8 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
 
 	if (phba->state != BE_ADAPTER_UP) {
 		ret = -EBUSY;
-		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
-			    "BS_%d : The Adapter state is Not UP\n");
+		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
+			    "BS_%d : The Adapter Port state is Down!!!\n");
 		return ERR_PTR(ret);
 	}
 
@@ -1216,11 +1187,9 @@ static int beiscsi_close_conn(struct  beiscsi_endpoint *beiscsi_ep, int flag)
 			    beiscsi_ep->ep_cid);
 
 		ret = -EAGAIN;
-	} else {
-		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-					 phba->ctrl.mcc_numtag[tag]);
-		free_mcc_tag(&phba->ctrl, tag);
 	}
+
+	ret = beiscsi_mccq_compl(phba, tag, NULL, NULL);
 	return ret;
 }
 
@@ -1281,12 +1250,9 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
 			    "BS_%d : mgmt_invalidate_connection Failed for cid=%d\n",
 			    beiscsi_ep->ep_cid);
-	} else {
-		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-					 phba->ctrl.mcc_numtag[tag]);
-		free_mcc_tag(&phba->ctrl, tag);
 	}
 
+	beiscsi_mccq_compl(phba, tag, NULL, NULL);
 	beiscsi_close_conn(beiscsi_ep, tcp_upload_flag);
 	beiscsi_free_ep(beiscsi_ep);
 	beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h
index 8b826fc..38eab72 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.h
+++ b/drivers/scsi/be2iscsi/be_iscsi.h
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index ff73f95..48d37dd 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -47,8 +47,6 @@
 static unsigned int be_iopoll_budget = 10;
 static unsigned int be_max_phys_size = 64;
 static unsigned int enable_msix = 1;
-static unsigned int gcrashmode = 0;
-static unsigned int num_hba = 0;
 
 MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
 MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR);
@@ -153,11 +151,54 @@ BEISCSI_RW_ATTR(log_enable, 0x00,
 		"\t\t\t\tIO Path Events		: 0x10\n"
 		"\t\t\t\tConfiguration Path	: 0x20\n");
 
+DEVICE_ATTR(beiscsi_drvr_ver, S_IRUGO, beiscsi_drvr_ver_disp, NULL);
+DEVICE_ATTR(beiscsi_adapter_family, S_IRUGO, beiscsi_adap_family_disp, NULL);
 struct device_attribute *beiscsi_attrs[] = {
 	&dev_attr_beiscsi_log_enable,
+	&dev_attr_beiscsi_drvr_ver,
+	&dev_attr_beiscsi_adapter_family,
 	NULL,
 };
 
+static char const *cqe_desc[] = {
+	"RESERVED_DESC",
+	"SOL_CMD_COMPLETE",
+	"SOL_CMD_KILLED_DATA_DIGEST_ERR",
+	"CXN_KILLED_PDU_SIZE_EXCEEDS_DSL",
+	"CXN_KILLED_BURST_LEN_MISMATCH",
+	"CXN_KILLED_AHS_RCVD",
+	"CXN_KILLED_HDR_DIGEST_ERR",
+	"CXN_KILLED_UNKNOWN_HDR",
+	"CXN_KILLED_STALE_ITT_TTT_RCVD",
+	"CXN_KILLED_INVALID_ITT_TTT_RCVD",
+	"CXN_KILLED_RST_RCVD",
+	"CXN_KILLED_TIMED_OUT",
+	"CXN_KILLED_RST_SENT",
+	"CXN_KILLED_FIN_RCVD",
+	"CXN_KILLED_BAD_UNSOL_PDU_RCVD",
+	"CXN_KILLED_BAD_WRB_INDEX_ERROR",
+	"CXN_KILLED_OVER_RUN_RESIDUAL",
+	"CXN_KILLED_UNDER_RUN_RESIDUAL",
+	"CMD_KILLED_INVALID_STATSN_RCVD",
+	"CMD_KILLED_INVALID_R2T_RCVD",
+	"CMD_CXN_KILLED_LUN_INVALID",
+	"CMD_CXN_KILLED_ICD_INVALID",
+	"CMD_CXN_KILLED_ITT_INVALID",
+	"CMD_CXN_KILLED_SEQ_OUTOFORDER",
+	"CMD_CXN_KILLED_INVALID_DATASN_RCVD",
+	"CXN_INVALIDATE_NOTIFY",
+	"CXN_INVALIDATE_INDEX_NOTIFY",
+	"CMD_INVALIDATED_NOTIFY",
+	"UNSOL_HDR_NOTIFY",
+	"UNSOL_DATA_NOTIFY",
+	"UNSOL_DATA_DIGEST_ERROR_NOTIFY",
+	"DRIVERMSG_NOTIFY",
+	"CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN",
+	"SOL_CMD_KILLED_DIF_ERR",
+	"CXN_KILLED_SYN_RCVD",
+	"CXN_KILLED_IMM_DATA_RCVD"
+};
+
 static int beiscsi_slave_configure(struct scsi_device *sdev)
 {
 	blk_queue_max_segment_size(sdev->request_queue, 65536);
@@ -226,11 +267,9 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)
 				    nonemb_cmd.va, nonemb_cmd.dma);
 
 		return FAILED;
-	} else {
-		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-					 phba->ctrl.mcc_numtag[tag]);
-		free_mcc_tag(&phba->ctrl, tag);
 	}
+
+	beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va);
 	pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
 			    nonemb_cmd.va, nonemb_cmd.dma);
 	return iscsi_eh_abort(sc);
@@ -301,11 +340,9 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
 		pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
 				    nonemb_cmd.va, nonemb_cmd.dma);
 		return FAILED;
-	} else {
-		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-					 phba->ctrl.mcc_numtag[tag]);
-		free_mcc_tag(&phba->ctrl, tag);
 	}
+
+	beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va);
 	pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
 			    nonemb_cmd.va, nonemb_cmd.dma);
 	return iscsi_eh_device_reset(sc);
@@ -482,6 +519,7 @@ static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
 	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
 	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) },
 	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID3) },
+	{ PCI_DEVICE(ELX_VENDOR_ID, OC_SKH_ID1) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
@@ -730,7 +768,7 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id)
 		     resource_id) / 32] &
 		     EQE_RESID_MASK) >> 16) == mcc->id) {
 			spin_lock_irqsave(&phba->isr_lock, flags);
-			phba->todo_mcc_cq = 1;
+			pbe_eq->todo_mcc_cq = true;
 			spin_unlock_irqrestore(&phba->isr_lock, flags);
 		}
 		AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
@@ -738,8 +776,8 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id)
 		eqe = queue_tail_node(eq);
 		num_eq_processed++;
 	}
-	if (phba->todo_mcc_cq)
-		queue_work(phba->wq, &phba->work_cqs);
+	if (pbe_eq->todo_mcc_cq)
+		queue_work(phba->wq, &pbe_eq->work_cqs);
 	if (num_eq_processed)
 		hwi_ring_eq_db(phba, eq->id, 1,	num_eq_processed, 1, 1);
 
@@ -779,29 +817,26 @@ static irqreturn_t be_isr_msix(int irq, void *dev_id)
 			eqe = queue_tail_node(eq);
 			num_eq_processed++;
 		}
-		if (num_eq_processed)
-			hwi_ring_eq_db(phba, eq->id, 1,	num_eq_processed, 0, 1);
-
-		return IRQ_HANDLED;
 	} else {
 		while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
 						& EQE_VALID_MASK) {
 			spin_lock_irqsave(&phba->isr_lock, flags);
-			phba->todo_cq = 1;
+			pbe_eq->todo_cq = true;
 			spin_unlock_irqrestore(&phba->isr_lock, flags);
 			AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
 			queue_tail_inc(eq);
 			eqe = queue_tail_node(eq);
 			num_eq_processed++;
 		}
-		if (phba->todo_cq)
-			queue_work(phba->wq, &phba->work_cqs);
 
-		if (num_eq_processed)
-			hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1);
-
-		return IRQ_HANDLED;
+		if (pbe_eq->todo_cq)
+			queue_work(phba->wq, &pbe_eq->work_cqs);
 	}
+
+	if (num_eq_processed)
+		hwi_ring_eq_db(phba, eq->id, 1,	num_eq_processed, 0, 1);
+
+	return IRQ_HANDLED;
 }
 
 /**
@@ -849,7 +884,7 @@ static irqreturn_t be_isr(int irq, void *dev_id)
 			     resource_id) / 32] &
 			     EQE_RESID_MASK) >> 16) == mcc->id) {
 				spin_lock_irqsave(&phba->isr_lock, flags);
-				phba->todo_mcc_cq = 1;
+				pbe_eq->todo_mcc_cq = true;
 				spin_unlock_irqrestore(&phba->isr_lock, flags);
 				num_mcceq_processed++;
 			} else {
@@ -862,8 +897,8 @@ static irqreturn_t be_isr(int irq, void *dev_id)
 			eqe = queue_tail_node(eq);
 		}
 		if (num_ioeq_processed || num_mcceq_processed) {
-			if (phba->todo_mcc_cq)
-				queue_work(phba->wq, &phba->work_cqs);
+			if (pbe_eq->todo_mcc_cq)
+				queue_work(phba->wq, &pbe_eq->work_cqs);
 
 			if ((num_mcceq_processed) && (!num_ioeq_processed))
 				hwi_ring_eq_db(phba, eq->id, 0,
@@ -886,11 +921,11 @@ static irqreturn_t be_isr(int irq, void *dev_id)
 			     resource_id) / 32] &
 			     EQE_RESID_MASK) >> 16) != cq->id) {
 				spin_lock_irqsave(&phba->isr_lock, flags);
-				phba->todo_mcc_cq = 1;
+				pbe_eq->todo_mcc_cq = true;
 				spin_unlock_irqrestore(&phba->isr_lock, flags);
 			} else {
 				spin_lock_irqsave(&phba->isr_lock, flags);
-				phba->todo_cq = 1;
+				pbe_eq->todo_cq = true;
 				spin_unlock_irqrestore(&phba->isr_lock, flags);
 			}
 			AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
@@ -898,8 +933,8 @@ static irqreturn_t be_isr(int irq, void *dev_id)
 			eqe = queue_tail_node(eq);
 			num_ioeq_processed++;
 		}
-		if (phba->todo_cq || phba->todo_mcc_cq)
-			queue_work(phba->wq, &phba->work_cqs);
+		if (pbe_eq->todo_cq || pbe_eq->todo_mcc_cq)
+			queue_work(phba->wq, &pbe_eq->work_cqs);
 
 		if (num_ioeq_processed) {
 			hwi_ring_eq_db(phba, eq->id, 0,
@@ -1211,7 +1246,8 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
 
 static void
 be_complete_io(struct beiscsi_conn *beiscsi_conn,
-	       struct iscsi_task *task, struct sol_cqe *psol)
+		struct iscsi_task *task,
+		struct common_sol_cqe *csol_cqe)
 {
 	struct beiscsi_io_task *io_task = task->dd_data;
 	struct be_status_bhs *sts_bhs =
@@ -1221,20 +1257,14 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,
 	u32 resid = 0, exp_cmdsn, max_cmdsn;
 	u8 rsp, status, flags;
 
-	exp_cmdsn = (psol->
-			dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
-			& SOL_EXP_CMD_SN_MASK);
-	max_cmdsn = ((psol->
-			dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
-			& SOL_EXP_CMD_SN_MASK) +
-			((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
-				/ 32] & SOL_CMD_WND_MASK) >> 24) - 1);
-	rsp = ((psol->dw[offsetof(struct amap_sol_cqe, i_resp) / 32]
-						& SOL_RESP_MASK) >> 16);
-	status = ((psol->dw[offsetof(struct amap_sol_cqe, i_sts) / 32]
-						& SOL_STS_MASK) >> 8);
-	flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
-					& SOL_FLAGS_MASK) >> 24) | 0x80;
+	exp_cmdsn = csol_cqe->exp_cmdsn;
+	max_cmdsn = (csol_cqe->exp_cmdsn +
+		     csol_cqe->cmd_wnd - 1);
+	rsp = csol_cqe->i_resp;
+	status = csol_cqe->i_sts;
+	flags = csol_cqe->i_flags;
+	resid = csol_cqe->res_cnt;
+
 	if (!task->sc) {
 		if (io_task->scsi_cmnd)
 			scsi_dma_unmap(io_task->scsi_cmnd);
@@ -1249,9 +1279,6 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,
 
 	/* bidi not initially supported */
 	if (flags & (ISCSI_FLAG_CMD_UNDERFLOW | ISCSI_FLAG_CMD_OVERFLOW)) {
-		resid = (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) /
-				32] & SOL_RES_CNT_MASK);
-
 		if (!status && (flags & ISCSI_FLAG_CMD_OVERFLOW))
 			task->sc->result = DID_ERROR << 16;
 
@@ -1273,13 +1300,8 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,
 		       min_t(u16, sense_len, SCSI_SENSE_BUFFERSIZE));
 	}
 
-	if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ) {
-		if (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32]
-							& SOL_RES_CNT_MASK)
-			 conn->rxdata_octets += (psol->
-			     dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32]
-			     & SOL_RES_CNT_MASK);
-	}
+	if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ)
+		conn->rxdata_octets += resid;
 unmap:
 	scsi_dma_unmap(io_task->scsi_cmnd);
 	iscsi_complete_scsi_task(task, exp_cmdsn, max_cmdsn);
@@ -1287,7 +1309,8 @@ unmap:
 
 static void
 be_complete_logout(struct beiscsi_conn *beiscsi_conn,
-		   struct iscsi_task *task, struct sol_cqe *psol)
+		    struct iscsi_task *task,
+		    struct common_sol_cqe *csol_cqe)
 {
 	struct iscsi_logout_rsp *hdr;
 	struct beiscsi_io_task *io_task = task->dd_data;
@@ -1297,18 +1320,11 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn,
 	hdr->opcode = ISCSI_OP_LOGOUT_RSP;
 	hdr->t2wait = 5;
 	hdr->t2retain = 0;
-	hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
-					& SOL_FLAGS_MASK) >> 24) | 0x80;
-	hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) /
-					32] & SOL_RESP_MASK);
-	hdr->exp_cmdsn = cpu_to_be32(psol->
-			dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
-					& SOL_EXP_CMD_SN_MASK);
-	hdr->max_cmdsn = be32_to_cpu((psol->
-			 dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
-					& SOL_EXP_CMD_SN_MASK) +
-			((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
-					/ 32] & SOL_CMD_WND_MASK) >> 24) - 1);
+	hdr->flags = csol_cqe->i_flags;
+	hdr->response = csol_cqe->i_resp;
+	hdr->exp_cmdsn = csol_cqe->exp_cmdsn;
+	hdr->max_cmdsn = (csol_cqe->exp_cmdsn + csol_cqe->cmd_wnd - 1);
+
 	hdr->dlength[0] = 0;
 	hdr->dlength[1] = 0;
 	hdr->dlength[2] = 0;
@@ -1319,7 +1335,8 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn,
 
 static void
 be_complete_tmf(struct beiscsi_conn *beiscsi_conn,
-		struct iscsi_task *task, struct sol_cqe *psol)
+		 struct iscsi_task *task,
+		 struct common_sol_cqe *csol_cqe)
 {
 	struct iscsi_tm_rsp *hdr;
 	struct iscsi_conn *conn = beiscsi_conn->conn;
@@ -1327,16 +1344,12 @@ be_complete_tmf(struct beiscsi_conn *beiscsi_conn,
 
 	hdr = (struct iscsi_tm_rsp *)task->hdr;
 	hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP;
-	hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
-					& SOL_FLAGS_MASK) >> 24) | 0x80;
-	hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) /
-					32] & SOL_RESP_MASK);
-	hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe,
-				    i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK);
-	hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe,
-			i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) +
-			((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
-			/ 32] & SOL_CMD_WND_MASK) >> 24) - 1);
+	hdr->flags = csol_cqe->i_flags;
+	hdr->response = csol_cqe->i_resp;
+	hdr->exp_cmdsn = csol_cqe->exp_cmdsn;
+	hdr->max_cmdsn = (csol_cqe->exp_cmdsn +
+			  csol_cqe->cmd_wnd - 1);
+
 	hdr->itt = io_task->libiscsi_itt;
 	__iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
 }
@@ -1352,15 +1365,24 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
 	struct beiscsi_io_task *io_task;
 	struct iscsi_conn *conn = beiscsi_conn->conn;
 	struct iscsi_session *session = conn->session;
+	uint16_t wrb_index, cid;
 
 	phwi_ctrlr = phba->phwi_ctrlr;
-	pwrb_context = &phwi_ctrlr->wrb_context[((psol->
-				dw[offsetof(struct amap_sol_cqe, cid) / 32] &
-				SOL_CID_MASK) >> 6) -
-				phba->fw_config.iscsi_cid_start];
-	pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol->
-				dw[offsetof(struct amap_sol_cqe, wrb_index) /
-				32] & SOL_WRB_INDEX_MASK) >> 16)];
+	if (chip_skh_r(phba->pcidev)) {
+		wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2,
+					  wrb_idx, psol);
+		cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2,
+				    cid, psol);
+	} else {
+		wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe,
+					  wrb_idx, psol);
+		cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe,
+				    cid, psol);
+	}
+
+	pwrb_context = &phwi_ctrlr->wrb_context[
+			cid - phba->fw_config.iscsi_cid_start];
+	pwrb_handle = pwrb_context->pwrb_handle_basestd[wrb_index];
 	task = pwrb_handle->pio_handle;
 
 	io_task = task->dd_data;
@@ -1374,26 +1396,78 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
 
 static void
 be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn,
-		       struct iscsi_task *task, struct sol_cqe *psol)
+			struct iscsi_task *task,
+			struct common_sol_cqe *csol_cqe)
 {
 	struct iscsi_nopin *hdr;
 	struct iscsi_conn *conn = beiscsi_conn->conn;
 	struct beiscsi_io_task *io_task = task->dd_data;
 
 	hdr = (struct iscsi_nopin *)task->hdr;
-	hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
-			& SOL_FLAGS_MASK) >> 24) | 0x80;
-	hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe,
-				     i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK);
-	hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe,
-			i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) +
-			((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
-			/ 32] & SOL_CMD_WND_MASK) >> 24) - 1);
+	hdr->flags = csol_cqe->i_flags;
+	hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn);
+	hdr->max_cmdsn = be32_to_cpu(hdr->exp_cmdsn +
+			 csol_cqe->cmd_wnd - 1);
+
 	hdr->opcode = ISCSI_OP_NOOP_IN;
 	hdr->itt = io_task->libiscsi_itt;
 	__iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
 }
 
+static void adapter_get_sol_cqe(struct beiscsi_hba *phba,
+		struct sol_cqe *psol,
+		struct common_sol_cqe *csol_cqe)
+{
+	if (chip_skh_r(phba->pcidev)) {
+		csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+						    i_exp_cmd_sn, psol);
+		csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+						  i_res_cnt, psol);
+		csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+						    wrb_index, psol);
+		csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+					      cid, psol);
+		csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+						 hw_sts, psol);
+		csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe,
+						  i_cmd_wnd, psol);
+		if (AMAP_GET_BITS(struct amap_sol_cqe_v2,
+				  cmd_cmpl, psol))
+			csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+							i_sts, psol);
+		else
+			csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+							 i_sts, psol);
+		if (AMAP_GET_BITS(struct amap_sol_cqe_v2,
+				  u, psol))
+			csol_cqe->i_flags = ISCSI_FLAG_CMD_UNDERFLOW;
+
+		if (AMAP_GET_BITS(struct amap_sol_cqe_v2,
+				  o, psol))
+			csol_cqe->i_flags |= ISCSI_FLAG_CMD_OVERFLOW;
+	} else {
+		csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe,
+						    i_exp_cmd_sn, psol);
+		csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe,
+						  i_res_cnt, psol);
+		csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe,
+						  i_cmd_wnd, psol);
+		csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe,
+						    wrb_index, psol);
+		csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe,
+					      cid, psol);
+		csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe,
+						 hw_sts, psol);
+		csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe,
+						 i_resp, psol);
+		csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe,
+						i_sts, psol);
+		csol_cqe->i_flags = AMAP_GET_BITS(struct amap_sol_cqe,
+						  i_flags, psol);
+	}
+}
+
+
 static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
 			     struct beiscsi_hba *phba, struct sol_cqe *psol)
 {
@@ -1405,19 +1479,22 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
 	unsigned int type;
 	struct iscsi_conn *conn = beiscsi_conn->conn;
 	struct iscsi_session *session = conn->session;
+	struct common_sol_cqe csol_cqe = {0};
 
 	phwi_ctrlr = phba->phwi_ctrlr;
-	pwrb_context = &phwi_ctrlr->wrb_context[((psol->dw[offsetof
-				(struct amap_sol_cqe, cid) / 32]
-				& SOL_CID_MASK) >> 6) -
-				phba->fw_config.iscsi_cid_start];
-	pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol->
-				dw[offsetof(struct amap_sol_cqe, wrb_index) /
-				32] & SOL_WRB_INDEX_MASK) >> 16)];
+
+	/* Copy the elements to a common structure */
+	adapter_get_sol_cqe(phba, psol, &csol_cqe);
+
+	pwrb_context = &phwi_ctrlr->wrb_context[
+			csol_cqe.cid - phba->fw_config.iscsi_cid_start];
+
+	pwrb_handle = pwrb_context->pwrb_handle_basestd[
+		      csol_cqe.wrb_index];
+
 	task = pwrb_handle->pio_handle;
 	pwrb = pwrb_handle->pwrb;
-	type = (pwrb->dw[offsetof(struct amap_iscsi_wrb, type) / 32] &
-				 WRB_TYPE_MASK) >> 28;
+	type = ((struct beiscsi_io_task *)task->dd_data)->wrb_type;
 
 	spin_lock_bh(&session->lock);
 	switch (type) {
@@ -1425,17 +1502,16 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
 	case HWH_TYPE_IO_RD:
 		if ((task->hdr->opcode & ISCSI_OPCODE_MASK) ==
 		     ISCSI_OP_NOOP_OUT)
-			be_complete_nopin_resp(beiscsi_conn, task, psol);
+			be_complete_nopin_resp(beiscsi_conn, task, &csol_cqe);
 		else
-			be_complete_io(beiscsi_conn, task, psol);
+			be_complete_io(beiscsi_conn, task, &csol_cqe);
 		break;
 
 	case HWH_TYPE_LOGOUT:
 		if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT)
-			be_complete_logout(beiscsi_conn, task, psol);
+			be_complete_logout(beiscsi_conn, task, &csol_cqe);
 		else
-			be_complete_tmf(beiscsi_conn, task, psol);
-
+			be_complete_tmf(beiscsi_conn, task, &csol_cqe);
 		break;
 
 	case HWH_TYPE_LOGIN:
@@ -1446,7 +1522,7 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
 		break;
 
 	case HWH_TYPE_NOP:
-		be_complete_nopin_resp(beiscsi_conn, task, psol);
+		be_complete_nopin_resp(beiscsi_conn, task, &csol_cqe);
 		break;
 
 	default:
@@ -1454,10 +1530,8 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
 			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
 			    "BM_%d : In hwi_complete_cmd, unknown type = %d"
 			    "wrb_index 0x%x CID 0x%x\n", type,
-			    ((psol->dw[offsetof(struct amap_iscsi_wrb,
-			    type) / 32] & SOL_WRB_INDEX_MASK) >> 16),
-			    ((psol->dw[offsetof(struct amap_sol_cqe,
-			    cid) / 32] & SOL_CID_MASK) >> 6));
+			    csol_cqe.wrb_index,
+			    csol_cqe.cid);
 		break;
 	}
 
@@ -1485,13 +1559,26 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
 	struct list_head *pbusy_list;
 	struct async_pdu_handle *pasync_handle = NULL;
 	unsigned char is_header = 0;
+	unsigned int index, dpl;
+
+	if (chip_skh_r(phba->pcidev)) {
+		dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2,
+				    dpl, pdpdu_cqe);
+		index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2,
+				      index, pdpdu_cqe);
+	} else {
+		dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe,
+				    dpl, pdpdu_cqe);
+		index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe,
+				      index, pdpdu_cqe);
+	}
 
 	phys_addr.u.a32.address_lo =
-	    pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_lo) / 32] -
-	    ((pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32]
-						& PDUCQE_DPL_MASK) >> 16);
+		(pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
+					db_addr_lo) / 32] - dpl);
 	phys_addr.u.a32.address_hi =
-	    pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_hi) / 32];
+		pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
+				       db_addr_hi) / 32];
 
 	phys_addr.u.a64.address =
 			*((unsigned long long *)(&phys_addr.u.a64.address));
@@ -1501,14 +1588,12 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
 	case UNSOL_HDR_NOTIFY:
 		is_header = 1;
 
-		pbusy_list = hwi_get_async_busy_list(pasync_ctx, 1,
-			(pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
-			index) / 32] & PDUCQE_INDEX_MASK));
+		 pbusy_list = hwi_get_async_busy_list(pasync_ctx,
+						      is_header, index);
 		break;
 	case UNSOL_DATA_NOTIFY:
-		pbusy_list = hwi_get_async_busy_list(pasync_ctx, 0, (pdpdu_cqe->
-					dw[offsetof(struct amap_i_t_dpdu_cqe,
-					index) / 32] & PDUCQE_INDEX_MASK));
+		 pbusy_list = hwi_get_async_busy_list(pasync_ctx,
+						      is_header, index);
 		break;
 	default:
 		pbusy_list = NULL;
@@ -1531,12 +1616,9 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
 	pasync_handle->cri = (unsigned short)beiscsi_conn->beiscsi_conn_cid -
 					     phba->fw_config.iscsi_cid_start;
 	pasync_handle->is_header = is_header;
-	pasync_handle->buffer_len = ((pdpdu_cqe->
-			dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32]
-			& PDUCQE_DPL_MASK) >> 16);
+	pasync_handle->buffer_len = dpl;
+	*pcq_index = index;
 
-	*pcq_index = (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
-			index) / 32] & PDUCQE_INDEX_MASK);
 	return pasync_handle;
 }
 
@@ -1914,6 +1996,13 @@ static void  beiscsi_process_mcc_isr(struct beiscsi_hba *phba)
 
 }
 
+/**
+ * beiscsi_process_cq()- Process the Completion Queue
+ * @pbe_eq: Event Q on which the Completion has come
+ *
+ * return
+ *     Number of Completion Entries processed.
+ **/
 static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
 {
 	struct be_queue_info *cq;
@@ -1935,12 +2024,24 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
 	       CQE_VALID_MASK) {
 		be_dws_le_to_cpu(sol, sizeof(struct sol_cqe));
 
-		cid = ((sol->dw[offsetof(struct amap_sol_cqe, cid)/32] &
-		      CQE_CID_MASK) >> 6);
-		code = (sol->dw[offsetof(struct amap_sol_cqe, code)/32] &
-		       CQE_CODE_MASK);
-		ep = phba->ep_array[cid - phba->fw_config.iscsi_cid_start];
+		 code = (sol->dw[offsetof(struct amap_sol_cqe, code) /
+			 32] & CQE_CODE_MASK);
+
+		 /* Get the CID */
+		if (chip_skh_r(phba->pcidev)) {
+			if ((code == DRIVERMSG_NOTIFY) ||
+			    (code == UNSOL_HDR_NOTIFY) ||
+			    (code == UNSOL_DATA_NOTIFY))
+				cid = AMAP_GET_BITS(
+						    struct amap_i_t_dpdu_cqe_v2,
+						    cid, sol);
+			 else
+				 cid = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+						     cid, sol);
+		   } else
+			 cid = AMAP_GET_BITS(struct amap_sol_cqe, cid, sol);
 
+		ep = phba->ep_array[cid - phba->fw_config.iscsi_cid_start];
 		beiscsi_ep = ep->dd_data;
 		beiscsi_conn = beiscsi_ep->conn;
 
@@ -1958,7 +2059,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
 		case DRIVERMSG_NOTIFY:
 			beiscsi_log(phba, KERN_INFO,
 				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
-				    "BM_%d : Received DRIVERMSG_NOTIFY\n");
+				    "BM_%d : Received %s[%d] on CID : %d\n",
+				    cqe_desc[code], code, cid);
 
 			dmsg = (struct dmsg_cqe *)sol;
 			hwi_complete_drvr_msgs(beiscsi_conn, phba, sol);
@@ -1966,7 +2068,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
 		case UNSOL_HDR_NOTIFY:
 			beiscsi_log(phba, KERN_INFO,
 				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
-				    "BM_%d : Received UNSOL_HDR_ NOTIFY\n");
+				    "BM_%d : Received %s[%d] on CID : %d\n",
+				    cqe_desc[code], code, cid);
 
 			hwi_process_default_pdu_ring(beiscsi_conn, phba,
 					     (struct i_t_dpdu_cqe *)sol);
@@ -1974,7 +2077,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
 		case UNSOL_DATA_NOTIFY:
 			beiscsi_log(phba, KERN_INFO,
 				    BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
-				    "BM_%d : Received UNSOL_DATA_NOTIFY\n");
+				    "BM_%d : Received %s[%d] on CID : %d\n",
+				    cqe_desc[code], code, cid);
 
 			hwi_process_default_pdu_ring(beiscsi_conn, phba,
 					     (struct i_t_dpdu_cqe *)sol);
@@ -1984,8 +2088,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
 		case CXN_INVALIDATE_NOTIFY:
 			beiscsi_log(phba, KERN_ERR,
 				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
-				    "BM_%d : Ignoring CQ Error notification for"
-				    " cmd/cxn invalidate\n");
+				    "BM_%d : Ignoring %s[%d] on CID : %d\n",
+				    cqe_desc[code], code, cid);
 			break;
 		case SOL_CMD_KILLED_DATA_DIGEST_ERR:
 		case CMD_KILLED_INVALID_STATSN_RCVD:
@@ -1997,14 +2101,14 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
 		case CMD_CXN_KILLED_INVALID_DATASN_RCVD:
 			beiscsi_log(phba, KERN_ERR,
 				    BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
-				    "BM_%d : CQ Error notification for cmd.. "
-				    "code %d cid 0x%x\n", code, cid);
+				    "BM_%d : Cmd Notification %s[%d] on CID : %d\n",
+				    cqe_desc[code], code,  cid);
 			break;
 		case UNSOL_DATA_DIGEST_ERROR_NOTIFY:
 			beiscsi_log(phba, KERN_ERR,
 				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
-				    "BM_%d : Digest error on def pdu ring,"
-				    " dropping..\n");
+				    "BM_%d :  Dropping %s[%d] on DPDU ring on CID : %d\n",
+				    cqe_desc[code], code, cid);
 			hwi_flush_default_pdu_buffer(phba, beiscsi_conn,
 					     (struct i_t_dpdu_cqe *) sol);
 			break;
@@ -2017,6 +2121,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
 		case CXN_KILLED_INVALID_ITT_TTT_RCVD:
 		case CXN_KILLED_TIMED_OUT:
 		case CXN_KILLED_FIN_RCVD:
+		case CXN_KILLED_RST_SENT:
+		case CXN_KILLED_RST_RCVD:
 		case CXN_KILLED_BAD_UNSOL_PDU_RCVD:
 		case CXN_KILLED_BAD_WRB_INDEX_ERROR:
 		case CXN_KILLED_OVER_RUN_RESIDUAL:
@@ -2024,19 +2130,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
 		case CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN:
 			beiscsi_log(phba, KERN_ERR,
 				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
-				    "BM_%d : CQ Error %d, reset CID 0x%x...\n",
-				    code, cid);
-			if (beiscsi_conn)
-				iscsi_conn_failure(beiscsi_conn->conn,
-						   ISCSI_ERR_CONN_FAILED);
-			break;
-		case CXN_KILLED_RST_SENT:
-		case CXN_KILLED_RST_RCVD:
-			beiscsi_log(phba, KERN_ERR,
-				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
-				    "BM_%d : CQ Error %d, reset"
-				    "received/sent on CID 0x%x...\n",
-				    code, cid);
+				    "BM_%d : Event %s[%d] received on CID : %d\n",
+				    cqe_desc[code], code, cid);
 			if (beiscsi_conn)
 				iscsi_conn_failure(beiscsi_conn->conn,
 						   ISCSI_ERR_CONN_FAILED);
@@ -2044,8 +2139,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
 		default:
 			beiscsi_log(phba, KERN_ERR,
 				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
-				    "BM_%d : CQ Error Invalid code= %d "
-				    "received on CID 0x%x...\n",
+				    "BM_%d : Invalid CQE Event Received Code : %d"
+				    "CID 0x%x...\n",
 				    code, cid);
 			break;
 		}
@@ -2068,30 +2163,30 @@ void beiscsi_process_all_cqs(struct work_struct *work)
 	unsigned long flags;
 	struct hwi_controller *phwi_ctrlr;
 	struct hwi_context_memory *phwi_context;
-	struct be_eq_obj *pbe_eq;
-	struct beiscsi_hba *phba =
-	    container_of(work, struct beiscsi_hba, work_cqs);
+	struct beiscsi_hba *phba;
+	struct be_eq_obj *pbe_eq =
+	    container_of(work, struct be_eq_obj, work_cqs);
 
+	phba = pbe_eq->phba;
 	phwi_ctrlr = phba->phwi_ctrlr;
 	phwi_context = phwi_ctrlr->phwi_ctxt;
-	if (phba->msix_enabled)
-		pbe_eq = &phwi_context->be_eq[phba->num_cpus];
-	else
-		pbe_eq = &phwi_context->be_eq[0];
 
-	if (phba->todo_mcc_cq) {
+	if (pbe_eq->todo_mcc_cq) {
 		spin_lock_irqsave(&phba->isr_lock, flags);
-		phba->todo_mcc_cq = 0;
+		pbe_eq->todo_mcc_cq = false;
 		spin_unlock_irqrestore(&phba->isr_lock, flags);
 		beiscsi_process_mcc_isr(phba);
 	}
 
-	if (phba->todo_cq) {
+	if (pbe_eq->todo_cq) {
 		spin_lock_irqsave(&phba->isr_lock, flags);
-		phba->todo_cq = 0;
+		pbe_eq->todo_cq = false;
 		spin_unlock_irqrestore(&phba->isr_lock, flags);
 		beiscsi_process_cq(pbe_eq);
 	}
+
+	/* rearm EQ for further interrupts */
+	hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1);
 }
 
 static int be_iopoll(struct blk_iopoll *iop, int budget)
@@ -2115,6 +2210,101 @@ static int be_iopoll(struct blk_iopoll *iop, int budget)
 }
 
 static void
+hwi_write_sgl_v2(struct iscsi_wrb *pwrb, struct scatterlist *sg,
+		  unsigned int num_sg, struct beiscsi_io_task *io_task)
+{
+	struct iscsi_sge *psgl;
+	unsigned int sg_len, index;
+	unsigned int sge_len = 0;
+	unsigned long long addr;
+	struct scatterlist *l_sg;
+	unsigned int offset;
+
+	AMAP_SET_BITS(struct amap_iscsi_wrb_v2, iscsi_bhs_addr_lo, pwrb,
+		      io_task->bhs_pa.u.a32.address_lo);
+	AMAP_SET_BITS(struct amap_iscsi_wrb_v2, iscsi_bhs_addr_hi, pwrb,
+		      io_task->bhs_pa.u.a32.address_hi);
+
+	l_sg = sg;
+	for (index = 0; (index < num_sg) && (index < 2); index++,
+			sg = sg_next(sg)) {
+		if (index == 0) {
+			sg_len = sg_dma_len(sg);
+			addr = (u64) sg_dma_address(sg);
+			AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+				      sge0_addr_lo, pwrb,
+				      lower_32_bits(addr));
+			AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+				      sge0_addr_hi, pwrb,
+				      upper_32_bits(addr));
+			AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+				      sge0_len, pwrb,
+				      sg_len);
+			sge_len = sg_len;
+		} else {
+			AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_r2t_offset,
+				      pwrb, sge_len);
+			sg_len = sg_dma_len(sg);
+			addr = (u64) sg_dma_address(sg);
+			AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+				      sge1_addr_lo, pwrb,
+				      lower_32_bits(addr));
+			AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+				      sge1_addr_hi, pwrb,
+				      upper_32_bits(addr));
+			AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+				      sge1_len, pwrb,
+				      sg_len);
+		}
+	}
+	psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag;
+	memset(psgl, 0, sizeof(*psgl) * BE2_SGE);
+
+	AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, io_task->bhs_len - 2);
+
+	AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
+		      io_task->bhs_pa.u.a32.address_hi);
+	AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
+		      io_task->bhs_pa.u.a32.address_lo);
+
+	if (num_sg == 1) {
+		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge0_last, pwrb,
+			      1);
+		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_last, pwrb,
+			      0);
+	} else if (num_sg == 2) {
+		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge0_last, pwrb,
+			      0);
+		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_last, pwrb,
+			      1);
+	} else {
+		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge0_last, pwrb,
+			      0);
+		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_last, pwrb,
+			      0);
+	}
+
+	sg = l_sg;
+	psgl++;
+	psgl++;
+	offset = 0;
+	for (index = 0; index < num_sg; index++, sg = sg_next(sg), psgl++) {
+		sg_len = sg_dma_len(sg);
+		addr = (u64) sg_dma_address(sg);
+		AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
+			      lower_32_bits(addr));
+		AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
+			      upper_32_bits(addr));
+		AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, sg_len);
+		AMAP_SET_BITS(struct amap_iscsi_sge, sge_offset, psgl, offset);
+		AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 0);
+		offset += sg_len;
+	}
+	psgl--;
+	AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1);
+}
+
+static void
 hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg,
 	      unsigned int num_sg, struct beiscsi_io_task *io_task)
 {
@@ -2202,13 +2392,18 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg,
 	AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1);
 }
 
+/**
+ * hwi_write_buffer()- Populate the WRB with task info
+ * @pwrb: ptr to the WRB entry
+ * @task: iscsi task which is to be executed
+ **/
 static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
 {
 	struct iscsi_sge *psgl;
-	unsigned long long addr;
 	struct beiscsi_io_task *io_task = task->dd_data;
 	struct beiscsi_conn *beiscsi_conn = io_task->conn;
 	struct beiscsi_hba *phba = beiscsi_conn->phba;
+	uint8_t dsp_value = 0;
 
 	io_task->bhs_len = sizeof(struct be_nonio_bhs) - 2;
 	AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_lo, pwrb,
@@ -2217,26 +2412,38 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
 				io_task->bhs_pa.u.a32.address_hi);
 
 	if (task->data) {
-		if (task->data_count) {
-			AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1);
-			addr = (u64) pci_map_single(phba->pcidev,
-						    task->data,
-						    task->data_count, 1);
-		} else {
-			AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);
-			addr = 0;
-		}
+
+		/* Check for the data_count */
+		dsp_value = (task->data_count) ? 1 : 0;
+
+		if (chip_skh_r(phba->pcidev))
+			AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp,
+				      pwrb, dsp_value);
+		else
+			AMAP_SET_BITS(struct amap_iscsi_wrb, dsp,
+				      pwrb, dsp_value);
+
+		/* Map addr only if there is data_count */
+		if (dsp_value) {
+			io_task->mtask_addr = pci_map_single(phba->pcidev,
+							     task->data,
+							     task->data_count,
+							     PCI_DMA_TODEVICE);
+			io_task->mtask_data_count = task->data_count;
+		} else
+			io_task->mtask_addr = 0;
+
 		AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb,
-						((u32)(addr & 0xFFFFFFFF)));
+			      lower_32_bits(io_task->mtask_addr));
 		AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb,
-						((u32)(addr >> 32)));
+			      upper_32_bits(io_task->mtask_addr));
 		AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb,
 						task->data_count);
 
 		AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, 1);
 	} else {
 		AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);
-		addr = 0;
+		io_task->mtask_addr = 0;
 	}
 
 	psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag;
@@ -2259,9 +2466,9 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
 		psgl++;
 		if (task->data) {
 			AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
-						((u32)(addr & 0xFFFFFFFF)));
+				      lower_32_bits(io_task->mtask_addr));
 			AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
-						((u32)(addr >> 32)));
+				      upper_32_bits(io_task->mtask_addr));
 		}
 		AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0x106);
 	}
@@ -2843,7 +3050,7 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba,
 	}
 	return 0;
 create_eq_error:
-	for (i = 0; i < (phba->num_cpus + 1); i++) {
+	for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) {
 		eq = &phwi_context->be_eq[i].q;
 		mem = &eq->dma_mem;
 		if (mem->va)
@@ -3268,15 +3475,31 @@ err:
 	return -ENOMEM;
 }
 
-static int find_num_cpus(void)
+/**
+ * find_num_cpus()- Get the CPU online count
+ * @phba: ptr to priv structure
+ *
+ * CPU count is used for creating EQ.
+ **/
+static void find_num_cpus(struct beiscsi_hba *phba)
 {
 	int  num_cpus = 0;
 
 	num_cpus = num_online_cpus();
-	if (num_cpus >= MAX_CPUS)
-		num_cpus = MAX_CPUS - 1;
 
-	return num_cpus;
+	switch (phba->generation) {
+	case BE_GEN2:
+	case BE_GEN3:
+		phba->num_cpus = (num_cpus > BEISCSI_MAX_NUM_CPUS) ?
+				  BEISCSI_MAX_NUM_CPUS : num_cpus;
+		break;
+	case BE_GEN4:
+		phba->num_cpus = (num_cpus > OC_SKH_MAX_NUM_CPUS) ?
+				  OC_SKH_MAX_NUM_CPUS : num_cpus;
+		break;
+	default:
+		phba->num_cpus = 1;
+	}
 }
 
 static int hwi_init_port(struct beiscsi_hba *phba)
@@ -3644,12 +3867,9 @@ static void hwi_disable_intr(struct beiscsi_hba *phba)
 static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
 {
 	struct be_cmd_get_session_resp *session_resp;
-	struct be_mcc_wrb *wrb;
 	struct be_dma_mem nonemb_cmd;
-	unsigned int tag, wrb_num;
-	unsigned short status, extd_status;
+	unsigned int tag;
 	unsigned int s_handle;
-	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
 	int ret = -ENOMEM;
 
 	/* Get the session handle of the boot target */
@@ -3682,25 +3902,16 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
 			    " Failed\n");
 
 		goto boot_freemem;
-	} else
-		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-					 phba->ctrl.mcc_numtag[tag]);
+	}
 
-	wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
-	extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-	status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
-	if (status || extd_status) {
+	ret = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va);
+	if (ret) {
 		beiscsi_log(phba, KERN_ERR,
 			    BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
-			    "BM_%d : beiscsi_get_session_info Failed"
-			    " status = %d extd_status = %d\n",
-			    status, extd_status);
-
-		free_mcc_tag(&phba->ctrl, tag);
+			    "BM_%d : beiscsi_get_session_info Failed");
 		goto boot_freemem;
 	}
-	wrb = queue_get_wrb(mccq, wrb_num);
-	free_mcc_tag(&phba->ctrl, tag);
+
 	session_resp = nonemb_cmd.va ;
 
 	memcpy(&phba->boot_sess, &session_resp->session_info,
@@ -3853,6 +4064,11 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba)
 	kfree(phba->ep_array);
 }
 
+/**
+ * beiscsi_cleanup_task()- Free driver resources of the task
+ * @task: ptr to the iscsi task
+ *
+ **/
 static void beiscsi_cleanup_task(struct iscsi_task *task)
 {
 	struct beiscsi_io_task *io_task = task->dd_data;
@@ -3900,6 +4116,13 @@ static void beiscsi_cleanup_task(struct iscsi_task *task)
 				spin_unlock(&phba->mgmt_sgl_lock);
 				io_task->psgl_handle = NULL;
 			}
+			if (io_task->mtask_addr) {
+				pci_unmap_single(phba->pcidev,
+						 io_task->mtask_addr,
+						 io_task->mtask_data_count,
+						 PCI_DMA_TODEVICE);
+				io_task->mtask_addr = 0;
+			}
 		}
 	}
 }
@@ -3909,8 +4132,6 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
 			   struct beiscsi_offload_params *params)
 {
 	struct wrb_handle *pwrb_handle;
-	struct iscsi_target_context_update_wrb *pwrb = NULL;
-	struct be_mem_descriptor *mem_descr;
 	struct beiscsi_hba *phba = beiscsi_conn->phba;
 	struct iscsi_task *task = beiscsi_conn->task;
 	struct iscsi_session *session = task->conn->session;
@@ -3927,67 +4148,16 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
 
 	pwrb_handle = alloc_wrb_handle(phba, (beiscsi_conn->beiscsi_conn_cid -
 				       phba->fw_config.iscsi_cid_start));
-	pwrb = (struct iscsi_target_context_update_wrb *)pwrb_handle->pwrb;
-	memset(pwrb, 0, sizeof(*pwrb));
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
-		      max_burst_length, pwrb, params->dw[offsetof
-		      (struct amap_beiscsi_offload_params,
-		      max_burst_length) / 32]);
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
-		      max_send_data_segment_length, pwrb,
-		      params->dw[offsetof(struct amap_beiscsi_offload_params,
-		      max_send_data_segment_length) / 32]);
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
-		      first_burst_length,
-		      pwrb,
-		      params->dw[offsetof(struct amap_beiscsi_offload_params,
-		      first_burst_length) / 32]);
-
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, erl, pwrb,
-		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
-		      erl) / 32] & OFFLD_PARAMS_ERL));
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, dde, pwrb,
-		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
-		      dde) / 32] & OFFLD_PARAMS_DDE) >> 2);
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, hde, pwrb,
-		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
-		      hde) / 32] & OFFLD_PARAMS_HDE) >> 3);
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ir2t, pwrb,
-		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
-		      ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4);
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, imd, pwrb,
-		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
-		       imd) / 32] & OFFLD_PARAMS_IMD) >> 5);
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, stat_sn,
-		      pwrb,
-		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
-		      exp_statsn) / 32] + 1));
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, type, pwrb,
-		      0x7);
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, wrb_idx,
-		      pwrb, pwrb_handle->wrb_index);
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb,
-		      pwrb, pwrb_handle->nxt_wrb_index);
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
-			session_state, pwrb, 0);
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack,
-		      pwrb, 1);
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, notpredblq,
-		      pwrb, 0);
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, mode, pwrb,
-		      0);
 
-	mem_descr = phba->init_mem;
-	mem_descr += ISCSI_MEM_GLOBAL_HEADER;
-
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
-			pad_buffer_addr_hi, pwrb,
-		      mem_descr->mem_array[0].bus_address.u.a32.address_hi);
-	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
-			pad_buffer_addr_lo, pwrb,
-		      mem_descr->mem_array[0].bus_address.u.a32.address_lo);
+	/* Check for the adapter family */
+	if (chip_skh_r(phba->pcidev))
+		beiscsi_offload_cxn_v2(params, pwrb_handle);
+	else
+		beiscsi_offload_cxn_v0(params, pwrb_handle,
+				       phba->init_mem);
 
-	be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_target_context_update_wrb));
+	be_dws_le_to_cpu(pwrb_handle->pwrb,
+			 sizeof(struct iscsi_target_context_update_wrb));
 
 	doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
 	doorbell |= (pwrb_handle->wrb_index & DB_DEF_PDU_WRB_INDEX_MASK)
@@ -4044,13 +4214,25 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
 		spin_lock(&phba->io_sgl_lock);
 		io_task->psgl_handle = alloc_io_sgl_handle(phba);
 		spin_unlock(&phba->io_sgl_lock);
-		if (!io_task->psgl_handle)
+		if (!io_task->psgl_handle) {
+			beiscsi_log(phba, KERN_ERR,
+				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
+				    "BM_%d : Alloc of IO_SGL_ICD Failed"
+				    "for the CID : %d\n",
+				    beiscsi_conn->beiscsi_conn_cid);
 			goto free_hndls;
+		}
 		io_task->pwrb_handle = alloc_wrb_handle(phba,
 					beiscsi_conn->beiscsi_conn_cid -
 					phba->fw_config.iscsi_cid_start);
-		if (!io_task->pwrb_handle)
+		if (!io_task->pwrb_handle) {
+			beiscsi_log(phba, KERN_ERR,
+				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
+				    "BM_%d : Alloc of WRB_HANDLE Failed"
+				    "for the CID : %d\n",
+				    beiscsi_conn->beiscsi_conn_cid);
 			goto free_io_hndls;
+		}
 	} else {
 		io_task->scsi_cmnd = NULL;
 		if ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) {
@@ -4059,8 +4241,16 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
 				io_task->psgl_handle = (struct sgl_handle *)
 						alloc_mgmt_sgl_handle(phba);
 				spin_unlock(&phba->mgmt_sgl_lock);
-				if (!io_task->psgl_handle)
+				if (!io_task->psgl_handle) {
+					beiscsi_log(phba, KERN_ERR,
+						    BEISCSI_LOG_IO |
+						    BEISCSI_LOG_CONFIG,
+						    "BM_%d : Alloc of MGMT_SGL_ICD Failed"
+						    "for the CID : %d\n",
+						    beiscsi_conn->
+						    beiscsi_conn_cid);
 					goto free_hndls;
+				}
 
 				beiscsi_conn->login_in_progress = 1;
 				beiscsi_conn->plogin_sgl_handle =
@@ -4069,8 +4259,16 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
 					alloc_wrb_handle(phba,
 					beiscsi_conn->beiscsi_conn_cid -
 					phba->fw_config.iscsi_cid_start);
-				if (!io_task->pwrb_handle)
-					goto free_io_hndls;
+				if (!io_task->pwrb_handle) {
+					beiscsi_log(phba, KERN_ERR,
+						    BEISCSI_LOG_IO |
+						    BEISCSI_LOG_CONFIG,
+						    "BM_%d : Alloc of WRB_HANDLE Failed"
+						    "for the CID : %d\n",
+						    beiscsi_conn->
+						    beiscsi_conn_cid);
+					goto free_mgmt_hndls;
+				}
 				beiscsi_conn->plogin_wrb_handle =
 							io_task->pwrb_handle;
 
@@ -4085,14 +4283,28 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
 			spin_lock(&phba->mgmt_sgl_lock);
 			io_task->psgl_handle = alloc_mgmt_sgl_handle(phba);
 			spin_unlock(&phba->mgmt_sgl_lock);
-			if (!io_task->psgl_handle)
+			if (!io_task->psgl_handle) {
+				beiscsi_log(phba, KERN_ERR,
+					    BEISCSI_LOG_IO |
+					    BEISCSI_LOG_CONFIG,
+					    "BM_%d : Alloc of MGMT_SGL_ICD Failed"
+					    "for the CID : %d\n",
+					    beiscsi_conn->
+					    beiscsi_conn_cid);
 				goto free_hndls;
+			}
 			io_task->pwrb_handle =
 					alloc_wrb_handle(phba,
 					beiscsi_conn->beiscsi_conn_cid -
 					phba->fw_config.iscsi_cid_start);
-			if (!io_task->pwrb_handle)
+			if (!io_task->pwrb_handle) {
+				beiscsi_log(phba, KERN_ERR,
+					    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
+					    "BM_%d : Alloc of WRB_HANDLE Failed"
+					    "for the CID : %d\n",
+					    beiscsi_conn->beiscsi_conn_cid);
 				goto free_mgmt_hndls;
+			}
 
 		}
 	}
@@ -4124,11 +4336,64 @@ free_hndls:
 	pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
 		      io_task->bhs_pa.u.a64.address);
 	io_task->cmd_bhs = NULL;
-	beiscsi_log(phba, KERN_ERR,
-		    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
-		    "BM_%d : Alloc of SGL_ICD Failed\n");
 	return -ENOMEM;
 }
+int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg,
+		       unsigned int num_sg, unsigned int xferlen,
+		       unsigned int writedir)
+{
+
+	struct beiscsi_io_task *io_task = task->dd_data;
+	struct iscsi_conn *conn = task->conn;
+	struct beiscsi_conn *beiscsi_conn = conn->dd_data;
+	struct beiscsi_hba *phba = beiscsi_conn->phba;
+	struct iscsi_wrb *pwrb = NULL;
+	unsigned int doorbell = 0;
+
+	pwrb = io_task->pwrb_handle->pwrb;
+	memset(pwrb, 0, sizeof(*pwrb));
+
+	io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0;
+	io_task->bhs_len = sizeof(struct be_cmd_bhs);
+
+	if (writedir) {
+		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, type, pwrb,
+			      INI_WR_CMD);
+		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp, pwrb, 1);
+	} else {
+		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, type, pwrb,
+			      INI_RD_CMD);
+		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp, pwrb, 0);
+	}
+
+	io_task->wrb_type = AMAP_GET_BITS(struct amap_iscsi_wrb_v2,
+					  type, pwrb);
+
+	AMAP_SET_BITS(struct amap_iscsi_wrb_v2, lun, pwrb,
+		      cpu_to_be16(*(unsigned short *)
+		      &io_task->cmd_bhs->iscsi_hdr.lun));
+	AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb, xferlen);
+	AMAP_SET_BITS(struct amap_iscsi_wrb_v2, wrb_idx, pwrb,
+		      io_task->pwrb_handle->wrb_index);
+	AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb,
+		      be32_to_cpu(task->cmdsn));
+	AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sgl_idx, pwrb,
+		      io_task->psgl_handle->sgl_index);
+
+	hwi_write_sgl_v2(pwrb, sg, num_sg, io_task);
+	AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb,
+		      io_task->pwrb_handle->nxt_wrb_index);
+
+	be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
+
+	doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
+	doorbell |= (io_task->pwrb_handle->wrb_index &
+		     DB_DEF_PDU_WRB_INDEX_MASK) <<
+		     DB_DEF_PDU_WRB_INDEX_SHIFT;
+	doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT;
+	iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET);
+	return 0;
+}
 
 static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
 			  unsigned int num_sg, unsigned int xferlen,
@@ -4156,6 +4421,9 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
 		AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);
 	}
 
+	io_task->wrb_type = AMAP_GET_BITS(struct amap_iscsi_wrb,
+					  type, pwrb);
+
 	AMAP_SET_BITS(struct amap_iscsi_wrb, lun, pwrb,
 		      cpu_to_be16(*(unsigned short *)
 				  &io_task->cmd_bhs->iscsi_hdr.lun));
@@ -4191,55 +4459,75 @@ static int beiscsi_mtask(struct iscsi_task *task)
 	struct iscsi_wrb *pwrb = NULL;
 	unsigned int doorbell = 0;
 	unsigned int cid;
+	unsigned int pwrb_typeoffset = 0;
 
 	cid = beiscsi_conn->beiscsi_conn_cid;
 	pwrb = io_task->pwrb_handle->pwrb;
 	memset(pwrb, 0, sizeof(*pwrb));
-	AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb,
-		      be32_to_cpu(task->cmdsn));
-	AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
-		      io_task->pwrb_handle->wrb_index);
-	AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb,
-		      io_task->psgl_handle->sgl_index);
+
+	if (chip_skh_r(phba->pcidev)) {
+		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb,
+			      be32_to_cpu(task->cmdsn));
+		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, wrb_idx, pwrb,
+			      io_task->pwrb_handle->wrb_index);
+		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sgl_idx, pwrb,
+			      io_task->psgl_handle->sgl_index);
+		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb,
+			      task->data_count);
+		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb,
+			      io_task->pwrb_handle->nxt_wrb_index);
+		pwrb_typeoffset = SKH_WRB_TYPE_OFFSET;
+	} else {
+		AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb,
+			      be32_to_cpu(task->cmdsn));
+		AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
+			      io_task->pwrb_handle->wrb_index);
+		AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb,
+			      io_task->psgl_handle->sgl_index);
+		AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb,
+			      task->data_count);
+		AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
+			      io_task->pwrb_handle->nxt_wrb_index);
+		pwrb_typeoffset = BE_WRB_TYPE_OFFSET;
+	}
+
 
 	switch (task->hdr->opcode & ISCSI_OPCODE_MASK) {
 	case ISCSI_OP_LOGIN:
-		AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
-			      TGT_DM_CMD);
-		AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
 		AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, 1);
+		ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset);
 		hwi_write_buffer(pwrb, task);
 		break;
 	case ISCSI_OP_NOOP_OUT:
 		if (task->hdr->ttt != ISCSI_RESERVED_TAG) {
-			AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
-				      TGT_DM_CMD);
-			AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt,
-				      pwrb, 0);
-			AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1);
+			ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset);
+			if (chip_skh_r(phba->pcidev))
+				AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+					      dmsg, pwrb, 1);
+			else
+				AMAP_SET_BITS(struct amap_iscsi_wrb,
+					      dmsg, pwrb, 1);
 		} else {
-			AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
-				      INI_RD_CMD);
-			AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
+			ADAPTER_SET_WRB_TYPE(pwrb, INI_RD_CMD, pwrb_typeoffset);
+			if (chip_skh_r(phba->pcidev))
+				AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+					      dmsg, pwrb, 0);
+			else
+				AMAP_SET_BITS(struct amap_iscsi_wrb,
+					      dmsg, pwrb, 0);
 		}
 		hwi_write_buffer(pwrb, task);
 		break;
 	case ISCSI_OP_TEXT:
-		AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
-			      TGT_DM_CMD);
-		AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
+		ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset);
 		hwi_write_buffer(pwrb, task);
 		break;
 	case ISCSI_OP_SCSI_TMFUNC:
-		AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
-			      INI_TMF_CMD);
-		AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
+		ADAPTER_SET_WRB_TYPE(pwrb, INI_TMF_CMD, pwrb_typeoffset);
 		hwi_write_buffer(pwrb, task);
 		break;
 	case ISCSI_OP_LOGOUT:
-		AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
-		AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
-			      HWH_TYPE_LOGOUT);
+		ADAPTER_SET_WRB_TYPE(pwrb, HWH_TYPE_LOGOUT, pwrb_typeoffset);
 		hwi_write_buffer(pwrb, task);
 		break;
 
@@ -4251,11 +4539,10 @@ static int beiscsi_mtask(struct iscsi_task *task)
 		return -EINVAL;
 	}
 
-	AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb,
-		      task->data_count);
-	AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
-		      io_task->pwrb_handle->nxt_wrb_index);
-	be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
+	/* Set the task type */
+	io_task->wrb_type = (chip_skh_r(phba->pcidev)) ?
+		AMAP_GET_BITS(struct amap_iscsi_wrb_v2, type, pwrb) :
+		AMAP_GET_BITS(struct amap_iscsi_wrb, type, pwrb);
 
 	doorbell |= cid & DB_WRB_POST_CID_MASK;
 	doorbell |= (io_task->pwrb_handle->wrb_index &
@@ -4269,10 +4556,13 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
 {
 	struct beiscsi_io_task *io_task = task->dd_data;
 	struct scsi_cmnd *sc = task->sc;
+	struct beiscsi_hba *phba = NULL;
 	struct scatterlist *sg;
 	int num_sg;
 	unsigned int  writedir = 0, xferlen = 0;
 
+	phba = ((struct beiscsi_conn *)task->conn->dd_data)->phba;
+
 	if (!sc)
 		return beiscsi_mtask(task);
 
@@ -4295,7 +4585,7 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
 	 else
 		writedir = 0;
 
-	return beiscsi_iotask(task, sg, num_sg, xferlen, writedir);
+	 return phba->iotask_fn(task, sg, num_sg, xferlen, writedir);
 }
 
 /**
@@ -4326,20 +4616,24 @@ static int beiscsi_bsg_request(struct bsg_job *job)
 			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
 				    "BM_%d : Failed to allocate memory for "
 				    "beiscsi_bsg_request\n");
-			return -EIO;
+			return -ENOMEM;
 		}
 		tag = mgmt_vendor_specific_fw_cmd(&phba->ctrl, phba, job,
 						  &nonemb_cmd);
 		if (!tag) {
 			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
-				    "BM_%d : be_cmd_get_mac_addr Failed\n");
+				    "BM_%d : MBX Tag Allocation Failed\n");
 
 			pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
 					    nonemb_cmd.va, nonemb_cmd.dma);
 			return -EAGAIN;
-		} else
-			wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-						 phba->ctrl.mcc_numtag[tag]);
+		}
+
+		rc = wait_event_interruptible_timeout(
+					phba->ctrl.mcc_wait[tag],
+					phba->ctrl.mcc_numtag[tag],
+					msecs_to_jiffies(
+					BEISCSI_HOST_MBX_TIMEOUT));
 		extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
 		status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
 		free_mcc_tag(&phba->ctrl, tag);
@@ -4356,11 +4650,13 @@ static int beiscsi_bsg_request(struct bsg_job *job)
 				    nonemb_cmd.va, nonemb_cmd.dma);
 		if (status || extd_status) {
 			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
-				    "BM_%d : be_cmd_get_mac_addr Failed"
+				    "BM_%d : MBX Cmd Failed"
 				    " status = %d extd_status = %d\n",
 				    status, extd_status);
 
 			return -EIO;
+		} else {
+			rc = 0;
 		}
 		break;
 
@@ -4380,14 +4676,18 @@ void beiscsi_hba_attrs_init(struct beiscsi_hba *phba)
 	beiscsi_log_enable_init(phba, beiscsi_log_enable);
 }
 
+/*
+ * beiscsi_quiesce()- Cleanup Driver resources
+ * @phba: Instance Priv structure
+ *
+ * Free the OS and HW resources held by the driver
+ **/
 static void beiscsi_quiesce(struct beiscsi_hba *phba)
 {
 	struct hwi_controller *phwi_ctrlr;
 	struct hwi_context_memory *phwi_context;
 	struct be_eq_obj *pbe_eq;
 	unsigned int i, msix_vec;
-	u8 *real_offset = 0;
-	u32 value = 0;
 
 	phwi_ctrlr = phba->phwi_ctrlr;
 	phwi_context = phwi_ctrlr->phwi_ctxt;
@@ -4411,19 +4711,14 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba)
 
 	beiscsi_clean_port(phba);
 	beiscsi_free_mem(phba);
-	real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
 
-	value = readl((void *)real_offset);
-
-	if (value & 0x00010000) {
-		value &= 0xfffeffff;
-		writel(value, (void *)real_offset);
-	}
 	beiscsi_unmap_pci_function(phba);
 	pci_free_consistent(phba->pcidev,
 			    phba->ctrl.mbox_mem_alloced.size,
 			    phba->ctrl.mbox_mem_alloced.va,
 			    phba->ctrl.mbox_mem_alloced.dma);
+
+	cancel_delayed_work_sync(&phba->beiscsi_hw_check_task);
 }
 
 static void beiscsi_remove(struct pci_dev *pcidev)
@@ -4476,6 +4771,25 @@ static void beiscsi_msix_enable(struct beiscsi_hba *phba)
 	return;
 }
 
+/*
+ * beiscsi_hw_health_check()- Check adapter health
+ * @work: work item to check HW health
+ *
+ * Check if adapter in an unrecoverable state or not.
+ **/
+static void
+beiscsi_hw_health_check(struct work_struct *work)
+{
+	struct beiscsi_hba *phba =
+		container_of(work, struct beiscsi_hba,
+			     beiscsi_hw_check_task.work);
+
+	beiscsi_ue_detect(phba);
+
+	schedule_delayed_work(&phba->beiscsi_hw_check_task,
+			      msecs_to_jiffies(1000));
+}
+
 static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
 				const struct pci_device_id *id)
 {
@@ -4483,9 +4797,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
 	struct hwi_controller *phwi_ctrlr;
 	struct hwi_context_memory *phwi_context;
 	struct be_eq_obj *pbe_eq;
-	int ret, num_cpus, i;
-	u8 *real_offset = 0;
-	u32 value = 0;
+	int ret, i;
 
 	ret = beiscsi_enable_pci(pcidev);
 	if (ret < 0) {
@@ -4504,25 +4816,33 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
 	/* Initialize Driver configuration Paramters */
 	beiscsi_hba_attrs_init(phba);
 
+	phba->fw_timeout = false;
+
+
 	switch (pcidev->device) {
 	case BE_DEVICE_ID1:
 	case OC_DEVICE_ID1:
 	case OC_DEVICE_ID2:
 		phba->generation = BE_GEN2;
+		phba->iotask_fn = beiscsi_iotask;
 		break;
 	case BE_DEVICE_ID2:
 	case OC_DEVICE_ID3:
 		phba->generation = BE_GEN3;
+		phba->iotask_fn = beiscsi_iotask;
 		break;
+	case OC_SKH_ID1:
+		phba->generation = BE_GEN4;
+		phba->iotask_fn = beiscsi_iotask_v2;
 	default:
 		phba->generation = 0;
 	}
 
 	if (enable_msix)
-		num_cpus = find_num_cpus();
+		find_num_cpus(phba);
 	else
-		num_cpus = 1;
-	phba->num_cpus = num_cpus;
+		phba->num_cpus = 1;
+
 	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
 		    "BM_%d : num_cpus = %d\n",
 		    phba->num_cpus);
@@ -4540,31 +4860,18 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
 		goto hba_free;
 	}
 
-	if (!num_hba) {
-		real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
-		value = readl((void *)real_offset);
-		if (value & 0x00010000) {
-			gcrashmode++;
-			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
-				    "BM_%d : Loading Driver in crashdump mode\n");
-			ret = beiscsi_cmd_reset_function(phba);
-			if (ret) {
-				beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
-					    "BM_%d : Reset Failed. Aborting Crashdump\n");
-				goto hba_free;
-			}
-			ret = be_chk_reset_complete(phba);
-			if (ret) {
-				beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
-					    "BM_%d : Failed to get out of reset."
-					    "Aborting Crashdump\n");
-				goto hba_free;
-			}
-		} else {
-			value |= 0x00010000;
-			writel(value, (void *)real_offset);
-			num_hba++;
-		}
+	ret = beiscsi_cmd_reset_function(phba);
+	if (ret) {
+		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
+			    "BM_%d : Reset Failed. Aborting Crashdump\n");
+		goto hba_free;
+	}
+	ret = be_chk_reset_complete(phba);
+	if (ret) {
+		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
+			    "BM_%d : Failed to get out of reset."
+			    "Aborting Crashdump\n");
+		goto hba_free;
 	}
 
 	spin_lock_init(&phba->io_sgl_lock);
@@ -4596,7 +4903,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
 
 	phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0;
 
-	snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u",
+	snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_%02x_wq",
 		 phba->shost->host_no);
 	phba->wq = alloc_workqueue(phba->wq_name, WQ_MEM_RECLAIM, 1);
 	if (!phba->wq) {
@@ -4606,10 +4913,12 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
 		goto free_twq;
 	}
 
-	INIT_WORK(&phba->work_cqs, beiscsi_process_all_cqs);
+	INIT_DELAYED_WORK(&phba->beiscsi_hw_check_task,
+			  beiscsi_hw_health_check);
 
 	phwi_ctrlr = phba->phwi_ctrlr;
 	phwi_context = phwi_ctrlr->phwi_ctxt;
+
 	if (blk_iopoll_enabled) {
 		for (i = 0; i < phba->num_cpus; i++) {
 			pbe_eq = &phwi_context->be_eq[i];
@@ -4617,7 +4926,25 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
 					be_iopoll);
 			blk_iopoll_enable(&pbe_eq->iopoll);
 		}
+
+		i = (phba->msix_enabled) ? i : 0;
+		/* Work item for MCC handling */
+		pbe_eq = &phwi_context->be_eq[i];
+		INIT_WORK(&pbe_eq->work_cqs, beiscsi_process_all_cqs);
+	} else {
+		if (phba->msix_enabled) {
+			for (i = 0; i <= phba->num_cpus; i++) {
+				pbe_eq = &phwi_context->be_eq[i];
+				INIT_WORK(&pbe_eq->work_cqs,
+					  beiscsi_process_all_cqs);
+			}
+		} else {
+				pbe_eq = &phwi_context->be_eq[0];
+				INIT_WORK(&pbe_eq->work_cqs,
+					  beiscsi_process_all_cqs);
+			}
 	}
+
 	ret = beiscsi_init_irqs(phba);
 	if (ret < 0) {
 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
@@ -4637,6 +4964,9 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
 			    "iSCSI boot info.\n");
 
 	beiscsi_create_def_ifaces(phba);
+	schedule_delayed_work(&phba->beiscsi_hw_check_task,
+			      msecs_to_jiffies(1000));
+
 	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
 		    "\n\n\n BM_%d : SUCCESS - DRIVER LOADED\n\n\n");
 	return 0;
@@ -4652,15 +4982,6 @@ free_twq:
 	beiscsi_clean_port(phba);
 	beiscsi_free_mem(phba);
 free_port:
-	real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
-
-	value = readl((void *)real_offset);
-
-	if (value & 0x00010000) {
-		value &= 0xfffeffff;
-		writel(value, (void *)real_offset);
-	}
-
 	pci_free_consistent(phba->pcidev,
 			    phba->ctrl.mbox_mem_alloced.size,
 			    phba->ctrl.mbox_mem_alloced.va,
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h
index b891226..5946577 100644
--- a/drivers/scsi/be2iscsi/be_main.h
+++ b/drivers/scsi/be2iscsi/be_main.h
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -36,12 +36,13 @@
 
 #include "be.h"
 #define DRV_NAME		"be2iscsi"
-#define BUILD_STR		"4.4.58.0"
+#define BUILD_STR		"10.0.272.0"
 #define BE_NAME			"Emulex OneConnect" \
 				"Open-iSCSI Driver version" BUILD_STR
 #define DRV_DESC		BE_NAME " " "Driver"
 
 #define BE_VENDOR_ID		0x19A2
+#define ELX_VENDOR_ID		0x10DF
 /* DEVICE ID's for BE2 */
 #define BE_DEVICE_ID1		0x212
 #define OC_DEVICE_ID1		0x702
@@ -51,6 +52,9 @@
 #define BE_DEVICE_ID2		0x222
 #define OC_DEVICE_ID3		0x712
 
+/* DEVICE ID for SKH */
+#define OC_SKH_ID1		0x722
+
 #define BE2_IO_DEPTH		1024
 #define BE2_MAX_SESSIONS	256
 #define BE2_CMDS_PER_CXN	128
@@ -60,7 +64,11 @@
 #define BE2_DEFPDU_HDR_SZ	64
 #define BE2_DEFPDU_DATA_SZ	8192
 
-#define MAX_CPUS		31
+#define MAX_CPUS		64
+#define BEISCSI_MAX_NUM_CPUS	7
+#define OC_SKH_MAX_NUM_CPUS	63
+
+
 #define BEISCSI_SGLIST_ELEMENTS	30
 
 #define BEISCSI_CMD_PER_LUN	128	/* scsi_host->cmd_per_lun */
@@ -257,6 +265,7 @@ struct invalidate_command_table {
 	unsigned short cid;
 } __packed;
 
+#define chip_skh_r(pdev)	(pdev->device == OC_SKH_ID1)
 struct beiscsi_hba {
 	struct hba_parameters params;
 	struct hwi_controller *phwi_ctrlr;
@@ -270,12 +279,11 @@ struct beiscsi_hba {
 	struct be_bus_address pci_pa;	/* CSR */
 	/* PCI representation of our HBA */
 	struct pci_dev *pcidev;
-	unsigned int state;
 	unsigned short asic_revision;
 	unsigned int num_cpus;
 	unsigned int nxt_cqid;
-	struct msix_entry msix_entries[MAX_CPUS + 1];
-	char *msi_name[MAX_CPUS + 1];
+	struct msix_entry msix_entries[MAX_CPUS];
+	char *msi_name[MAX_CPUS];
 	bool msix_enabled;
 	struct be_mem_descriptor *init_mem;
 
@@ -325,12 +333,14 @@ struct beiscsi_hba {
 		spinlock_t cid_lock;
 	} fw_config;
 
+	unsigned int state;
+	bool fw_timeout;
+	bool ue_detected;
+	struct delayed_work beiscsi_hw_check_task;
+
 	u8 mac_address[ETH_ALEN];
-	unsigned short todo_cq;
-	unsigned short todo_mcc_cq;
 	char wq_name[20];
 	struct workqueue_struct *wq;	/* The actuak work queue */
-	struct work_struct work_cqs;	/* The work being queued */
 	struct be_ctrl_info ctrl;
 	unsigned int generation;
 	unsigned int interface_handle;
@@ -338,7 +348,10 @@ struct beiscsi_hba {
 	struct invalidate_command_table inv_tbl[128];
 
 	unsigned int attr_log_enable;
-
+	int (*iotask_fn)(struct iscsi_task *,
+			struct scatterlist *sg,
+			uint32_t num_sg, uint32_t xferlen,
+			uint32_t writedir);
 };
 
 struct beiscsi_session {
@@ -410,6 +423,9 @@ struct beiscsi_io_task {
 	struct be_cmd_bhs *cmd_bhs;
 	struct be_bus_address bhs_pa;
 	unsigned short bhs_len;
+	dma_addr_t mtask_addr;
+	uint32_t mtask_data_count;
+	uint8_t wrb_type;
 };
 
 struct be_nonio_bhs {
@@ -457,6 +473,9 @@ struct beiscsi_offload_params {
 #define OFFLD_PARAMS_HDE	0x00000008
 #define OFFLD_PARAMS_IR2T	0x00000010
 #define OFFLD_PARAMS_IMD	0x00000020
+#define OFFLD_PARAMS_DATA_SEQ_INORDER   0x00000040
+#define OFFLD_PARAMS_PDU_SEQ_INORDER    0x00000080
+#define OFFLD_PARAMS_MAX_R2T 0x00FFFF00
 
 /**
  * Pseudo amap definition in which each bit of the actual structure is defined
@@ -471,7 +490,10 @@ struct amap_beiscsi_offload_params {
 	u8 hde[1];
 	u8 ir2t[1];
 	u8 imd[1];
-	u8 pad[26];
+	u8 data_seq_inorder[1];
+	u8 pdu_seq_inorder[1];
+	u8 max_r2t[16];
+	u8 pad[8];
 	u8 exp_statsn[32];
 };
 
@@ -569,6 +591,20 @@ struct amap_i_t_dpdu_cqe {
 	u8 valid;
 } __packed;
 
+struct amap_i_t_dpdu_cqe_v2 {
+	u8 db_addr_hi[32];  /* DWORD 0 */
+	u8 db_addr_lo[32];  /* DWORD 1 */
+	u8 code[6]; /* DWORD 2 */
+	u8 num_cons; /* DWORD 2*/
+	u8 rsvd0[8]; /* DWORD 2 */
+	u8 dpl[17]; /* DWORD 2 */
+	u8 index[16]; /* DWORD 3 */
+	u8 cid[13]; /* DWORD 3 */
+	u8 rsvd1; /* DWORD 3 */
+	u8 final; /* DWORD 3 */
+	u8 valid; /* DWORD 3 */
+} __packed;
+
 #define CQE_VALID_MASK	0x80000000
 #define CQE_CODE_MASK	0x0000003F
 #define CQE_CID_MASK	0x0000FFC0
@@ -617,6 +653,11 @@ struct iscsi_wrb {
 } __packed;
 
 #define WRB_TYPE_MASK 0xF0000000
+#define SKH_WRB_TYPE_OFFSET 27
+#define BE_WRB_TYPE_OFFSET  28
+
+#define ADAPTER_SET_WRB_TYPE(pwrb, wrb_type, type_offset) \
+		(pwrb->dw[0] |= (wrb_type << type_offset))
 
 /**
  * Pseudo amap definition in which each bit of the actual structure is defined
@@ -663,12 +704,57 @@ struct amap_iscsi_wrb {
 
 } __packed;
 
+struct amap_iscsi_wrb_v2 {
+	u8 r2t_exp_dtl[25]; /* DWORD 0 */
+	u8 rsvd0[2];    /* DWORD 0*/
+	u8 type[5];     /* DWORD 0 */
+	u8 ptr2nextwrb[8];  /* DWORD 1 */
+	u8 wrb_idx[8];      /* DWORD 1 */
+	u8 lun[16];     /* DWORD 1 */
+	u8 sgl_idx[16]; /* DWORD 2 */
+	u8 ref_sgl_icd_idx[16]; /* DWORD 2 */
+	u8 exp_data_sn[32]; /* DWORD 3 */
+	u8 iscsi_bhs_addr_hi[32];   /* DWORD 4 */
+	u8 iscsi_bhs_addr_lo[32];   /* DWORD 5 */
+	u8 cq_id[16];   /* DWORD 6 */
+	u8 rsvd1[16];   /* DWORD 6 */
+	u8 cmdsn_itt[32];   /* DWORD 7 */
+	u8 sge0_addr_hi[32];    /* DWORD 8 */
+	u8 sge0_addr_lo[32];    /* DWORD 9 */
+	u8 sge0_offset[24]; /* DWORD 10 */
+	u8 rsvd2[7];    /* DWORD 10 */
+	u8 sge0_last;   /* DWORD 10 */
+	u8 sge0_len[17];    /* DWORD 11 */
+	u8 rsvd3[7];    /* DWORD 11 */
+	u8 diff_enbl;   /* DWORD 11 */
+	u8 u_run;       /* DWORD 11 */
+	u8 o_run;       /* DWORD 11 */
+	u8 invalid;     /* DWORD 11 */
+	u8 dsp;         /* DWORD 11 */
+	u8 dmsg;        /* DWORD 11 */
+	u8 rsvd4;       /* DWORD 11 */
+	u8 lt;          /* DWORD 11 */
+	u8 sge1_addr_hi[32];    /* DWORD 12 */
+	u8 sge1_addr_lo[32];    /* DWORD 13 */
+	u8 sge1_r2t_offset[24]; /* DWORD 14 */
+	u8 rsvd5[7];    /* DWORD 14 */
+	u8 sge1_last;   /* DWORD 14 */
+	u8 sge1_len[17];    /* DWORD 15 */
+	u8 rsvd6[15];   /* DWORD 15 */
+} __packed;
+
+
 struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid);
 void
 free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle);
 
 void beiscsi_process_all_cqs(struct work_struct *work);
 
+static inline bool beiscsi_error(struct beiscsi_hba *phba)
+{
+	return phba->ue_detected || phba->fw_timeout;
+}
+
 struct pdu_nop_out {
 	u32 dw[12];
 };
@@ -728,6 +814,7 @@ struct iscsi_target_context_update_wrb {
  * Pseudo amap definition in which each bit of the actual structure is defined
  * as a byte: used to calculate offset/shift/mask of each field
  */
+#define BE_TGT_CTX_UPDT_CMD 0x07
 struct amap_iscsi_target_context_update_wrb {
 	u8 lun[14];		/* DWORD 0 */
 	u8 lt;			/* DWORD 0 */
@@ -773,6 +860,47 @@ struct amap_iscsi_target_context_update_wrb {
 
 } __packed;
 
+#define BEISCSI_MAX_RECV_DATASEG_LEN    (64 * 1024)
+#define BEISCSI_MAX_CXNS    1
+struct amap_iscsi_target_context_update_wrb_v2 {
+	u8 max_burst_length[24];    /* DWORD 0 */
+	u8 rsvd0[3];    /* DWORD 0 */
+	u8 type[5];     /* DWORD 0 */
+	u8 ptr2nextwrb[8];  /* DWORD 1 */
+	u8 wrb_idx[8];      /* DWORD 1 */
+	u8 rsvd1[16];       /* DWORD 1 */
+	u8 max_send_data_segment_length[24];    /* DWORD 2 */
+	u8 rsvd2[8];    /* DWORD 2 */
+	u8 first_burst_length[24]; /* DWORD 3 */
+	u8 rsvd3[8]; /* DOWRD 3 */
+	u8 max_r2t[16]; /* DWORD 4 */
+	u8 rsvd4[10];   /* DWORD 4 */
+	u8 hde;         /* DWORD 4 */
+	u8 dde;         /* DWORD 4 */
+	u8 erl[2];      /* DWORD 4 */
+	u8 imd;         /* DWORD 4 */
+	u8 ir2t;        /* DWORD 4 */
+	u8 stat_sn[32];     /* DWORD 5 */
+	u8 rsvd5[32];   /* DWORD 6 */
+	u8 rsvd6[32];   /* DWORD 7 */
+	u8 max_recv_dataseg_len[24];    /* DWORD 8 */
+	u8 rsvd7[8]; /* DWORD 8 */
+	u8 rsvd8[32];   /* DWORD 9 */
+	u8 rsvd9[32];   /* DWORD 10 */
+	u8 max_cxns[16]; /* DWORD 11 */
+	u8 rsvd10[11]; /* DWORD  11*/
+	u8 invld; /* DWORD 11 */
+	u8 rsvd11;/* DWORD 11*/
+	u8 dmsg; /* DWORD 11 */
+	u8 data_seq_inorder; /* DWORD 11 */
+	u8 pdu_seq_inorder; /* DWORD 11 */
+	u8 rsvd12[32]; /*DWORD 12 */
+	u8 rsvd13[32]; /* DWORD 13 */
+	u8 rsvd14[32]; /* DWORD 14 */
+	u8 rsvd15[32]; /* DWORD 15 */
+} __packed;
+
+
 struct be_ring {
 	u32 pages;		/* queue size in pages */
 	u32 id;			/* queue id assigned by beklib */
@@ -837,7 +965,7 @@ struct hwi_context_memory {
 	u16 max_eqd;		/* in usecs */
 	u16 cur_eqd;		/* in usecs */
 	struct be_eq_obj be_eq[MAX_CPUS];
-	struct be_queue_info be_cq[MAX_CPUS];
+	struct be_queue_info be_cq[MAX_CPUS - 1];
 
 	struct be_queue_info be_def_hdrq;
 	struct be_queue_info be_def_dataq;
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index aab5dd3..a6c2fe4 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -22,6 +22,138 @@
 #include <scsi/scsi_bsg_iscsi.h>
 #include "be_mgmt.h"
 #include "be_iscsi.h"
+#include "be_main.h"
+
+/* UE Status Low CSR */
+static const char * const desc_ue_status_low[] = {
+	"CEV",
+	"CTX",
+	"DBUF",
+	"ERX",
+	"Host",
+	"MPU",
+	"NDMA",
+	"PTC ",
+	"RDMA ",
+	"RXF ",
+	"RXIPS ",
+	"RXULP0 ",
+	"RXULP1 ",
+	"RXULP2 ",
+	"TIM ",
+	"TPOST ",
+	"TPRE ",
+	"TXIPS ",
+	"TXULP0 ",
+	"TXULP1 ",
+	"UC ",
+	"WDMA ",
+	"TXULP2 ",
+	"HOST1 ",
+	"P0_OB_LINK ",
+	"P1_OB_LINK ",
+	"HOST_GPIO ",
+	"MBOX ",
+	"AXGMAC0",
+	"AXGMAC1",
+	"JTAG",
+	"MPU_INTPEND"
+};
+
+/* UE Status High CSR */
+static const char * const desc_ue_status_hi[] = {
+	"LPCMEMHOST",
+	"MGMT_MAC",
+	"PCS0ONLINE",
+	"MPU_IRAM",
+	"PCS1ONLINE",
+	"PCTL0",
+	"PCTL1",
+	"PMEM",
+	"RR",
+	"TXPB",
+	"RXPP",
+	"XAUI",
+	"TXP",
+	"ARM",
+	"IPC",
+	"HOST2",
+	"HOST3",
+	"HOST4",
+	"HOST5",
+	"HOST6",
+	"HOST7",
+	"HOST8",
+	"HOST9",
+	"NETC",
+	"Unknown",
+	"Unknown",
+	"Unknown",
+	"Unknown",
+	"Unknown",
+	"Unknown",
+	"Unknown",
+	"Unknown"
+};
+
+/*
+ * beiscsi_ue_detec()- Detect Unrecoverable Error on adapter
+ * @phba: Driver priv structure
+ *
+ * Read registers linked to UE and check for the UE status
+ **/
+void beiscsi_ue_detect(struct beiscsi_hba *phba)
+{
+	uint32_t ue_hi = 0, ue_lo = 0;
+	uint32_t ue_mask_hi = 0, ue_mask_lo = 0;
+	uint8_t i = 0;
+
+	if (phba->ue_detected)
+		return;
+
+	pci_read_config_dword(phba->pcidev,
+			      PCICFG_UE_STATUS_LOW, &ue_lo);
+	pci_read_config_dword(phba->pcidev,
+			      PCICFG_UE_STATUS_MASK_LOW,
+			      &ue_mask_lo);
+	pci_read_config_dword(phba->pcidev,
+			      PCICFG_UE_STATUS_HIGH,
+			      &ue_hi);
+	pci_read_config_dword(phba->pcidev,
+			      PCICFG_UE_STATUS_MASK_HI,
+			      &ue_mask_hi);
+
+	ue_lo = (ue_lo & ~ue_mask_lo);
+	ue_hi = (ue_hi & ~ue_mask_hi);
+
+
+	if (ue_lo || ue_hi) {
+		phba->ue_detected = true;
+		beiscsi_log(phba, KERN_ERR,
+			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
+			    "BG_%d : Error detected on the adapter\n");
+	}
+
+	if (ue_lo) {
+		for (i = 0; ue_lo; ue_lo >>= 1, i++) {
+			if (ue_lo & 1)
+				beiscsi_log(phba, KERN_ERR,
+					    BEISCSI_LOG_CONFIG,
+					    "BG_%d : UE_LOW %s bit set\n",
+					    desc_ue_status_low[i]);
+		}
+	}
+
+	if (ue_hi) {
+		for (i = 0; ue_hi; ue_hi >>= 1, i++) {
+			if (ue_hi & 1)
+				beiscsi_log(phba, KERN_ERR,
+					    BEISCSI_LOG_CONFIG,
+					    "BG_%d : UE_HIGH %s bit set\n",
+					    desc_ue_status_hi[i]);
+		}
+	}
+}
 
 /**
  * mgmt_reopen_session()- Reopen a session based on reopen_type
@@ -575,13 +707,20 @@ unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba)
 	return status;
 }
 
+/*
+ * mgmt_exec_nonemb_cmd()- Execute Non Embedded MBX Cmd
+ * @phba: Driver priv structure
+ * @nonemb_cmd: Address of the MBX command issued
+ * @resp_buf: Buffer to copy the MBX cmd response
+ * @resp_buf_len: respone lenght to be copied
+ *
+ **/
 static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba,
 				struct be_dma_mem *nonemb_cmd, void *resp_buf,
 				int resp_buf_len)
 {
 	struct be_ctrl_info *ctrl = &phba->ctrl;
 	struct be_mcc_wrb *wrb = wrb_from_mccq(phba);
-	unsigned short status, extd_status;
 	struct be_sge *sge;
 	unsigned int tag;
 	int rc = 0;
@@ -599,31 +738,25 @@ static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba,
 
 	be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1);
 	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
-	sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
+	sge->pa_lo = cpu_to_le32(lower_32_bits(nonemb_cmd->dma));
 	sge->len = cpu_to_le32(nonemb_cmd->size);
 
 	be_mcc_notify(phba);
 	spin_unlock(&ctrl->mbox_lock);
 
-	wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-				 phba->ctrl.mcc_numtag[tag]);
-
-	extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-	status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
-	if (status || extd_status) {
+	rc = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd->va);
+	if (rc) {
 		beiscsi_log(phba, KERN_ERR,
 			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-			    "BG_%d : mgmt_exec_nonemb_cmd Failed status = %d"
-			    "extd_status = %d\n", status, extd_status);
+			    "BG_%d : mgmt_exec_nonemb_cmd Failed status\n");
+
 		rc = -EIO;
-		goto free_tag;
+		goto free_cmd;
 	}
 
 	if (resp_buf)
 		memcpy(resp_buf, nonemb_cmd->va, resp_buf_len);
 
-free_tag:
-	free_mcc_tag(&phba->ctrl, tag);
 free_cmd:
 	pci_free_consistent(ctrl->pdev, nonemb_cmd->size,
 			    nonemb_cmd->va, nonemb_cmd->dma);
@@ -1009,10 +1142,9 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba,
 {
 	struct be_cmd_get_boot_target_resp *boot_resp;
 	struct be_mcc_wrb *wrb;
-	unsigned int tag, wrb_num;
+	unsigned int tag;
 	uint8_t boot_retry = 3;
-	unsigned short status, extd_status;
-	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+	int rc;
 
 	do {
 		/* Get the Boot Target Session Handle and Count*/
@@ -1022,24 +1154,16 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba,
 				    BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT,
 				    "BG_%d : Getting Boot Target Info Failed\n");
 			return -EAGAIN;
-		} else
-			wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-						 phba->ctrl.mcc_numtag[tag]);
-
-		wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
-		extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-		status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
-		if (status || extd_status) {
+		}
+
+		rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
+		if (rc) {
 			beiscsi_log(phba, KERN_ERR,
 				    BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
-				    "BG_%d : mgmt_get_boot_target Failed"
-				    " status = %d extd_status = %d\n",
-				    status, extd_status);
-			free_mcc_tag(&phba->ctrl, tag);
+				    "BG_%d : MBX CMD get_boot_target Failed\n");
 			return -EBUSY;
 		}
-		wrb = queue_get_wrb(mccq, wrb_num);
-		free_mcc_tag(&phba->ctrl, tag);
+
 		boot_resp = embedded_payload(wrb);
 
 		/* Check if the there are any Boot targets configured */
@@ -1064,24 +1188,15 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba,
 				    BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
 				    "BG_%d : mgmt_reopen_session Failed\n");
 			return -EAGAIN;
-		} else
-			wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-						 phba->ctrl.mcc_numtag[tag]);
-
-		wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
-		extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-		status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
-		if (status || extd_status) {
+		}
+
+		rc = beiscsi_mccq_compl(phba, tag, NULL, NULL);
+		if (rc) {
 			beiscsi_log(phba, KERN_ERR,
 				    BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
-				    "BG_%d : mgmt_reopen_session Failed"
-				    " status = %d extd_status = %d\n",
-				    status, extd_status);
-			free_mcc_tag(&phba->ctrl, tag);
-			return -EBUSY;
+				    "BG_%d : mgmt_reopen_session Failed");
+			return rc;
 		}
-		free_mcc_tag(&phba->ctrl, tag);
-
 	} while (--boot_retry);
 
 	/* Couldn't log into the boot target */
@@ -1106,8 +1221,9 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba,
 int mgmt_set_vlan(struct beiscsi_hba *phba,
 		   uint16_t vlan_tag)
 {
-	unsigned int tag, wrb_num;
-	unsigned short status, extd_status;
+	int rc;
+	unsigned int tag;
+	struct be_mcc_wrb *wrb = NULL;
 
 	tag = be_cmd_set_vlan(phba, vlan_tag);
 	if (!tag) {
@@ -1115,24 +1231,208 @@ int mgmt_set_vlan(struct beiscsi_hba *phba,
 			    (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX),
 			    "BG_%d : VLAN Setting Failed\n");
 		return -EBUSY;
-	} else
-		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-					 phba->ctrl.mcc_numtag[tag]);
-
-	wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
-	extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-	status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
+	}
 
-	if (status || extd_status) {
+	rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
+	if (rc) {
 		beiscsi_log(phba, KERN_ERR,
 			    (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX),
-			    "BS_%d : status : %d extd_status : %d\n",
-			    status, extd_status);
+			    "BS_%d : VLAN MBX Cmd Failed\n");
+		return rc;
+	}
+	return rc;
+}
 
-		free_mcc_tag(&phba->ctrl, tag);
-		return -EAGAIN;
+/**
+ * beiscsi_drvr_ver_disp()- Display the driver Name and Version
+ * @dev: ptr to device not used.
+ * @attr: device attribute, not used.
+ * @buf: contains formatted text driver name and version
+ *
+ * return
+ * size of the formatted string
+ **/
+ssize_t
+beiscsi_drvr_ver_disp(struct device *dev, struct device_attribute *attr,
+		       char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, BE_NAME "\n");
+}
+
+/**
+ * beiscsi_adap_family_disp()- Display adapter family.
+ * @dev: ptr to device to get priv structure
+ * @attr: device attribute, not used.
+ * @buf: contains formatted text driver name and version
+ *
+ * return
+ * size of the formatted string
+ **/
+ssize_t
+beiscsi_adap_family_disp(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	uint16_t dev_id = 0;
+	struct Scsi_Host *shost = class_to_shost(dev);
+	struct beiscsi_hba *phba = iscsi_host_priv(shost);
+
+	dev_id = phba->pcidev->device;
+	switch (dev_id) {
+	case BE_DEVICE_ID1:
+	case OC_DEVICE_ID1:
+	case OC_DEVICE_ID2:
+		return snprintf(buf, PAGE_SIZE, "BE2 Adapter Family\n");
+		break;
+	case BE_DEVICE_ID2:
+	case OC_DEVICE_ID3:
+		return snprintf(buf, PAGE_SIZE, "BE3-R Adapter Family\n");
+		break;
+	case OC_SKH_ID1:
+		return snprintf(buf, PAGE_SIZE, "Skyhawk-R Adapter Family\n");
+		break;
+	default:
+		return snprintf(buf, PAGE_SIZE,
+				"Unkown Adapter Family: 0x%x\n", dev_id);
+		break;
 	}
+}
 
-	free_mcc_tag(&phba->ctrl, tag);
-	return 0;
+
+void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
+			     struct wrb_handle *pwrb_handle,
+			     struct be_mem_descriptor *mem_descr)
+{
+	struct iscsi_wrb *pwrb = pwrb_handle->pwrb;
+
+	memset(pwrb, 0, sizeof(*pwrb));
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+		      max_send_data_segment_length, pwrb,
+		      params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      max_send_data_segment_length) / 32]);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, type, pwrb,
+		      BE_TGT_CTX_UPDT_CMD);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+		      first_burst_length,
+		      pwrb,
+		      params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      first_burst_length) / 32]);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, erl, pwrb,
+		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      erl) / 32] & OFFLD_PARAMS_ERL));
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, dde, pwrb,
+		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
+		       dde) / 32] & OFFLD_PARAMS_DDE) >> 2);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, hde, pwrb,
+		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      hde) / 32] & OFFLD_PARAMS_HDE) >> 3);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ir2t, pwrb,
+		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, imd, pwrb,
+		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      imd) / 32] & OFFLD_PARAMS_IMD) >> 5);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, stat_sn,
+		      pwrb,
+		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      exp_statsn) / 32] + 1));
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, wrb_idx,
+		      pwrb, pwrb_handle->wrb_index);
+
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+		      max_burst_length, pwrb, params->dw[offsetof
+		      (struct amap_beiscsi_offload_params,
+		      max_burst_length) / 32]);
+
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb,
+		      pwrb, pwrb_handle->nxt_wrb_index);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+		      session_state, pwrb, 0);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack,
+		      pwrb, 1);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, notpredblq,
+		      pwrb, 0);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, mode, pwrb,
+		      0);
+
+	mem_descr += ISCSI_MEM_GLOBAL_HEADER;
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+		      pad_buffer_addr_hi, pwrb,
+		      mem_descr->mem_array[0].bus_address.u.a32.address_hi);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+		      pad_buffer_addr_lo, pwrb,
+		      mem_descr->mem_array[0].bus_address.u.a32.address_lo);
+}
+
+void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
+			     struct wrb_handle *pwrb_handle)
+{
+	struct iscsi_wrb *pwrb = pwrb_handle->pwrb;
+
+	memset(pwrb, 0, sizeof(*pwrb));
+
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+		      max_burst_length, pwrb, params->dw[offsetof
+		      (struct amap_beiscsi_offload_params,
+		      max_burst_length) / 32]);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+		      max_burst_length, pwrb, params->dw[offsetof
+		      (struct amap_beiscsi_offload_params,
+		      max_burst_length) / 32]);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+		      type, pwrb,
+		      BE_TGT_CTX_UPDT_CMD);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+		      ptr2nextwrb,
+		      pwrb, pwrb_handle->nxt_wrb_index);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, wrb_idx,
+		      pwrb, pwrb_handle->wrb_index);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+		      max_send_data_segment_length, pwrb,
+		      params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      max_send_data_segment_length) / 32]);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+		      first_burst_length, pwrb,
+		      params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      first_burst_length) / 32]);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+		      max_recv_dataseg_len, pwrb, BEISCSI_MAX_RECV_DATASEG_LEN);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+		      max_cxns, pwrb, BEISCSI_MAX_CXNS);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, erl, pwrb,
+		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      erl) / 32] & OFFLD_PARAMS_ERL));
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, dde, pwrb,
+		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      dde) / 32] & OFFLD_PARAMS_DDE) >> 2);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, hde, pwrb,
+		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      hde) / 32] & OFFLD_PARAMS_HDE) >> 3);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+		      ir2t, pwrb,
+		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, imd, pwrb,
+		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      imd) / 32] & OFFLD_PARAMS_IMD) >> 5);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+		      data_seq_inorder,
+		      pwrb,
+		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      data_seq_inorder) / 32] &
+		      OFFLD_PARAMS_DATA_SEQ_INORDER) >> 6);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+		      pdu_seq_inorder,
+		      pwrb,
+		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      pdu_seq_inorder) / 32] &
+		      OFFLD_PARAMS_PDU_SEQ_INORDER) >> 7);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, max_r2t,
+		      pwrb,
+		      (params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      max_r2t) / 32] &
+		      OFFLD_PARAMS_MAX_R2T) >> 8);
+	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, stat_sn,
+		      pwrb,
+		     (params->dw[offsetof(struct amap_beiscsi_offload_params,
+		      exp_statsn) / 32] + 1));
 }
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h
index c50cef6..2e4968a 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.h
+++ b/drivers/scsi/be2iscsi/be_mgmt.h
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -30,6 +30,12 @@
 #define IP_V6_LEN	16
 #define IP_V4_LEN	4
 
+/* UE Status and Mask register */
+#define PCICFG_UE_STATUS_LOW            0xA0
+#define PCICFG_UE_STATUS_HIGH           0xA4
+#define PCICFG_UE_STATUS_MASK_LOW       0xA8
+#define PCICFG_UE_STATUS_MASK_HI        0xAC
+
 /**
  * Pseudo amap definition in which each bit of the actual structure is defined
  * as a byte: used to calculate offset/shift/mask of each field
@@ -301,4 +307,19 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba,
 unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba);
 
 int mgmt_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag);
+
+ssize_t beiscsi_drvr_ver_disp(struct device *dev,
+			       struct device_attribute *attr, char *buf);
+
+ssize_t beiscsi_adap_family_disp(struct device *dev,
+				  struct device_attribute *attr, char *buf);
+
+void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
+			     struct wrb_handle *pwrb_handle,
+			     struct be_mem_descriptor *mem_descr);
+
+void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
+			     struct wrb_handle *pwrb_handle);
+void beiscsi_ue_detect(struct beiscsi_hba *phba);
+
 #endif
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
index 6d6eee4..ef60afa 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -296,7 +296,7 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
 	ofld_req3.flags |= (interface->vlan_enabled <<
 			    FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT);
 
-	/* C2_VALID and ACK flags are not set as they are not suppported */
+	/* C2_VALID and ACK flags are not set as they are not supported */
 
 
 	/* Initialize offload request 4 structure */
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index 3f9e706..b44d04e 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -800,7 +800,7 @@ extern struct device_attribute *bnx2i_dev_attributes[];
 /*
  * Function Prototypes
  */
-extern void bnx2i_identify_device(struct bnx2i_hba *hba);
+extern void bnx2i_identify_device(struct bnx2i_hba *hba, struct cnic_dev *dev);
 
 extern void bnx2i_ulp_init(struct cnic_dev *dev);
 extern void bnx2i_ulp_exit(struct cnic_dev *dev);
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index b17637a..ee009e4ad 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -79,42 +79,33 @@ static struct notifier_block bnx2i_cpu_notifier = {
 /**
  * bnx2i_identify_device - identifies NetXtreme II device type
  * @hba: 		Adapter structure pointer
+ * @cnic:		Corresponding cnic device
  *
  * This function identifies the NX2 device type and sets appropriate
  *	queue mailbox register access method, 5709 requires driver to
  *	access MBOX regs using *bin* mode
  */
-void bnx2i_identify_device(struct bnx2i_hba *hba)
+void bnx2i_identify_device(struct bnx2i_hba *hba, struct cnic_dev *dev)
 {
 	hba->cnic_dev_type = 0;
-	if ((hba->pci_did == PCI_DEVICE_ID_NX2_5706) ||
-	    (hba->pci_did == PCI_DEVICE_ID_NX2_5706S))
-		set_bit(BNX2I_NX2_DEV_5706, &hba->cnic_dev_type);
-	else if ((hba->pci_did == PCI_DEVICE_ID_NX2_5708) ||
-	    (hba->pci_did == PCI_DEVICE_ID_NX2_5708S))
-		set_bit(BNX2I_NX2_DEV_5708, &hba->cnic_dev_type);
-	else if ((hba->pci_did == PCI_DEVICE_ID_NX2_5709) ||
-	    (hba->pci_did == PCI_DEVICE_ID_NX2_5709S)) {
-		set_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type);
-		hba->mail_queue_access = BNX2I_MQ_BIN_MODE;
-	} else if (hba->pci_did == PCI_DEVICE_ID_NX2_57710    ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57711    ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57711E   ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57712    ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57712E   ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57800    ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57800_MF ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57800_VF ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57810    ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57810_MF ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57810_VF ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57840    ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57840_MF ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57840_VF)
+	if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) {
+		if (hba->pci_did == PCI_DEVICE_ID_NX2_5706 ||
+		    hba->pci_did == PCI_DEVICE_ID_NX2_5706S) {
+			set_bit(BNX2I_NX2_DEV_5706, &hba->cnic_dev_type);
+		} else if (hba->pci_did == PCI_DEVICE_ID_NX2_5708 ||
+		    hba->pci_did == PCI_DEVICE_ID_NX2_5708S) {
+			set_bit(BNX2I_NX2_DEV_5708, &hba->cnic_dev_type);
+		} else if (hba->pci_did == PCI_DEVICE_ID_NX2_5709 ||
+		    hba->pci_did == PCI_DEVICE_ID_NX2_5709S) {
+			set_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type);
+			hba->mail_queue_access = BNX2I_MQ_BIN_MODE;
+		}
+	} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
 		set_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type);
-	else
+	} else {
 		printk(KERN_ALERT "bnx2i: unknown device, 0x%x\n",
 				  hba->pci_did);
+	}
 }
 
 
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index 3b34c13..0056e47 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -808,7 +808,7 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic)
 	hba->pci_func = PCI_FUNC(hba->pcidev->devfn);
 	hba->pci_devno = PCI_SLOT(hba->pcidev->devfn);
 
-	bnx2i_identify_device(hba);
+	bnx2i_identify_device(hba, cnic);
 	bnx2i_setup_host_queue_size(hba, shost);
 
 	hba->reg_base = pci_resource_start(hba->pcidev, 0);
diff --git a/drivers/scsi/csiostor/Kconfig b/drivers/scsi/csiostor/Kconfig
new file mode 100644
index 0000000..4d03b03
--- /dev/null
+++ b/drivers/scsi/csiostor/Kconfig
@@ -0,0 +1,19 @@
+config SCSI_CHELSIO_FCOE
+	tristate "Chelsio Communications FCoE support"
+	depends on PCI && SCSI
+	select SCSI_FC_ATTRS
+	select FW_LOADER
+	help
+	  This driver supports FCoE Offload functionality over
+	  Chelsio T4-based 10Gb Converged Network Adapters.
+
+	  For general information about Chelsio and our products, visit
+	  our website at <http://www.chelsio.com>.
+
+	  For customer support, please visit our customer support page at
+	  <http://www.chelsio.com/support.html>.
+
+	  Please send feedback to <linux-bugs@chelsio.com>.
+
+	  To compile this driver as a module choose M here; the module
+	  will be called csiostor.
diff --git a/drivers/scsi/csiostor/Makefile b/drivers/scsi/csiostor/Makefile
new file mode 100644
index 0000000..b581966
--- /dev/null
+++ b/drivers/scsi/csiostor/Makefile
@@ -0,0 +1,11 @@
+#
+## Chelsio FCoE driver
+#
+##
+
+ccflags-y += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb4
+
+obj-$(CONFIG_SCSI_CHELSIO_FCOE) += csiostor.o
+
+csiostor-objs := csio_attr.o csio_init.o csio_lnode.o csio_scsi.o \
+		csio_hw.o csio_isr.o csio_mb.o csio_rnode.o csio_wr.o
diff --git a/drivers/scsi/csiostor/csio_attr.c b/drivers/scsi/csiostor/csio_attr.c
new file mode 100644
index 0000000..c8cf857
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_attr.c
@@ -0,0 +1,796 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/mm.h>
+#include <linux/jiffies.h>
+#include <scsi/fc/fc_fs.h>
+
+#include "csio_init.h"
+
+static void
+csio_vport_set_state(struct csio_lnode *ln);
+
+/*
+ * csio_reg_rnode - Register a remote port with FC transport.
+ * @rn: Rnode representing remote port.
+ *
+ * Call fc_remote_port_add() to register this remote port with FC transport.
+ * If remote port is Initiator OR Target OR both, change the role appropriately.
+ *
+ */
+void
+csio_reg_rnode(struct csio_rnode *rn)
+{
+	struct csio_lnode *ln		= csio_rnode_to_lnode(rn);
+	struct Scsi_Host *shost		= csio_ln_to_shost(ln);
+	struct fc_rport_identifiers ids;
+	struct fc_rport  *rport;
+	struct csio_service_parms *sp;
+
+	ids.node_name	= wwn_to_u64(csio_rn_wwnn(rn));
+	ids.port_name	= wwn_to_u64(csio_rn_wwpn(rn));
+	ids.port_id	= rn->nport_id;
+	ids.roles	= FC_RPORT_ROLE_UNKNOWN;
+
+	if (rn->role & CSIO_RNFR_INITIATOR || rn->role & CSIO_RNFR_TARGET) {
+		rport = rn->rport;
+		CSIO_ASSERT(rport != NULL);
+		goto update_role;
+	}
+
+	rn->rport = fc_remote_port_add(shost, 0, &ids);
+	if (!rn->rport) {
+		csio_ln_err(ln, "Failed to register rport = 0x%x.\n",
+					rn->nport_id);
+		return;
+	}
+
+	ln->num_reg_rnodes++;
+	rport = rn->rport;
+	spin_lock_irq(shost->host_lock);
+	*((struct csio_rnode **)rport->dd_data) = rn;
+	spin_unlock_irq(shost->host_lock);
+
+	sp = &rn->rn_sparm;
+	rport->maxframe_size		= sp->csp.sp_bb_data;
+	if (ntohs(sp->clsp[2].cp_class) & FC_CPC_VALID)
+		rport->supported_classes = FC_COS_CLASS3;
+	else
+		rport->supported_classes = FC_COS_UNSPECIFIED;
+update_role:
+	if (rn->role & CSIO_RNFR_INITIATOR)
+		ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+	if (rn->role & CSIO_RNFR_TARGET)
+		ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
+
+	if (ids.roles != FC_RPORT_ROLE_UNKNOWN)
+		fc_remote_port_rolechg(rport, ids.roles);
+
+	rn->scsi_id = rport->scsi_target_id;
+
+	csio_ln_dbg(ln, "Remote port x%x role 0x%x registered\n",
+		rn->nport_id, ids.roles);
+}
+
+/*
+ * csio_unreg_rnode - Unregister a remote port with FC transport.
+ * @rn: Rnode representing remote port.
+ *
+ * Call fc_remote_port_delete() to unregister this remote port with FC
+ * transport.
+ *
+ */
+void
+csio_unreg_rnode(struct csio_rnode *rn)
+{
+	struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+	struct fc_rport *rport = rn->rport;
+
+	rn->role &= ~(CSIO_RNFR_INITIATOR | CSIO_RNFR_TARGET);
+	fc_remote_port_delete(rport);
+	ln->num_reg_rnodes--;
+
+	csio_ln_dbg(ln, "Remote port x%x un-registered\n", rn->nport_id);
+}
+
+/*
+ * csio_lnode_async_event - Async events from local port.
+ * @ln: lnode representing local port.
+ *
+ * Async events from local node that FC transport/SCSI ML
+ * should be made aware of (Eg: RSCN).
+ */
+void
+csio_lnode_async_event(struct csio_lnode *ln, enum csio_ln_fc_evt fc_evt)
+{
+	switch (fc_evt) {
+	case CSIO_LN_FC_RSCN:
+		/* Get payload of rscn from ln */
+		/* For each RSCN entry */
+			/*
+			 * fc_host_post_event(shost,
+			 *		      fc_get_event_number(),
+			 *		      FCH_EVT_RSCN,
+			 *		      rscn_entry);
+			 */
+		break;
+	case CSIO_LN_FC_LINKUP:
+		/* send fc_host_post_event */
+		/* set vport state */
+		if (csio_is_npiv_ln(ln))
+			csio_vport_set_state(ln);
+
+		break;
+	case CSIO_LN_FC_LINKDOWN:
+		/* send fc_host_post_event */
+		/* set vport state */
+		if (csio_is_npiv_ln(ln))
+			csio_vport_set_state(ln);
+
+		break;
+	case CSIO_LN_FC_ATTRIB_UPDATE:
+		csio_fchost_attr_init(ln);
+		break;
+	default:
+		break;
+	}
+}
+
+/*
+ * csio_fchost_attr_init - Initialize FC transport attributes
+ * @ln: Lnode.
+ *
+ */
+void
+csio_fchost_attr_init(struct csio_lnode *ln)
+{
+	struct Scsi_Host  *shost = csio_ln_to_shost(ln);
+
+	fc_host_node_name(shost) = wwn_to_u64(csio_ln_wwnn(ln));
+	fc_host_port_name(shost) = wwn_to_u64(csio_ln_wwpn(ln));
+
+	fc_host_supported_classes(shost) = FC_COS_CLASS3;
+	fc_host_max_npiv_vports(shost) =
+			(csio_lnode_to_hw(ln))->fres_info.max_vnps;
+	fc_host_supported_speeds(shost) = FC_PORTSPEED_10GBIT |
+		FC_PORTSPEED_1GBIT;
+
+	fc_host_maxframe_size(shost) = ln->ln_sparm.csp.sp_bb_data;
+	memset(fc_host_supported_fc4s(shost), 0,
+		sizeof(fc_host_supported_fc4s(shost)));
+	fc_host_supported_fc4s(shost)[7] = 1;
+
+	memset(fc_host_active_fc4s(shost), 0,
+		sizeof(fc_host_active_fc4s(shost)));
+	fc_host_active_fc4s(shost)[7] = 1;
+}
+
+/*
+ * csio_get_host_port_id - sysfs entries for nport_id is
+ * populated/cached from this function
+ */
+static void
+csio_get_host_port_id(struct Scsi_Host *shost)
+{
+	struct csio_lnode *ln	= shost_priv(shost);
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+	spin_lock_irq(&hw->lock);
+	fc_host_port_id(shost) = ln->nport_id;
+	spin_unlock_irq(&hw->lock);
+}
+
+/*
+ * csio_get_port_type - Return FC local port type.
+ * @shost: scsi host.
+ *
+ */
+static void
+csio_get_host_port_type(struct Scsi_Host *shost)
+{
+	struct csio_lnode *ln = shost_priv(shost);
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+	spin_lock_irq(&hw->lock);
+	if (csio_is_npiv_ln(ln))
+		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
+	else
+		fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
+	spin_unlock_irq(&hw->lock);
+}
+
+/*
+ * csio_get_port_state - Return FC local port state.
+ * @shost: scsi host.
+ *
+ */
+static void
+csio_get_host_port_state(struct Scsi_Host *shost)
+{
+	struct csio_lnode *ln = shost_priv(shost);
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+	char state[16];
+
+	spin_lock_irq(&hw->lock);
+
+	csio_lnode_state_to_str(ln, state);
+	if (!strcmp(state, "READY"))
+		fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
+	else if (!strcmp(state, "OFFLINE"))
+		fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
+	else
+		fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
+
+	spin_unlock_irq(&hw->lock);
+}
+
+/*
+ * csio_get_host_speed - Return link speed to FC transport.
+ * @shost: scsi host.
+ *
+ */
+static void
+csio_get_host_speed(struct Scsi_Host *shost)
+{
+	struct csio_lnode *ln = shost_priv(shost);
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+	spin_lock_irq(&hw->lock);
+	switch (hw->pport[ln->portid].link_speed) {
+	case FW_PORT_CAP_SPEED_1G:
+		fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
+		break;
+	case FW_PORT_CAP_SPEED_10G:
+		fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
+		break;
+	default:
+		fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
+		break;
+	}
+	spin_unlock_irq(&hw->lock);
+}
+
+/*
+ * csio_get_host_fabric_name - Return fabric name
+ * @shost: scsi host.
+ *
+ */
+static void
+csio_get_host_fabric_name(struct Scsi_Host *shost)
+{
+	struct csio_lnode *ln = shost_priv(shost);
+	struct csio_rnode *rn = NULL;
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+	spin_lock_irq(&hw->lock);
+	rn = csio_rnode_lookup_portid(ln, FC_FID_FLOGI);
+	if (rn)
+		fc_host_fabric_name(shost) = wwn_to_u64(csio_rn_wwnn(rn));
+	else
+		fc_host_fabric_name(shost) = 0;
+	spin_unlock_irq(&hw->lock);
+}
+
+/*
+ * csio_get_host_speed - Return FC transport statistics.
+ * @ln: Lnode.
+ *
+ */
+static struct fc_host_statistics *
+csio_get_stats(struct Scsi_Host *shost)
+{
+	struct csio_lnode *ln = shost_priv(shost);
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+	struct fc_host_statistics *fhs = &ln->fch_stats;
+	struct fw_fcoe_port_stats fcoe_port_stats;
+	uint64_t seconds;
+
+	memset(&fcoe_port_stats, 0, sizeof(struct fw_fcoe_port_stats));
+	csio_get_phy_port_stats(hw, ln->portid, &fcoe_port_stats);
+
+	fhs->tx_frames  += (fcoe_port_stats.tx_bcast_frames +
+				fcoe_port_stats.tx_mcast_frames +
+				fcoe_port_stats.tx_ucast_frames +
+				fcoe_port_stats.tx_offload_frames);
+	fhs->tx_words  += (fcoe_port_stats.tx_bcast_bytes +
+			   fcoe_port_stats.tx_mcast_bytes +
+			   fcoe_port_stats.tx_ucast_bytes +
+			   fcoe_port_stats.tx_offload_bytes) /
+							CSIO_WORD_TO_BYTE;
+	fhs->rx_frames += (fcoe_port_stats.rx_bcast_frames +
+				fcoe_port_stats.rx_mcast_frames +
+				fcoe_port_stats.rx_ucast_frames);
+	fhs->rx_words += (fcoe_port_stats.rx_bcast_bytes +
+				fcoe_port_stats.rx_mcast_bytes +
+				fcoe_port_stats.rx_ucast_bytes) /
+							CSIO_WORD_TO_BYTE;
+	fhs->error_frames += fcoe_port_stats.rx_err_frames;
+	fhs->fcp_input_requests +=  ln->stats.n_input_requests;
+	fhs->fcp_output_requests +=  ln->stats.n_output_requests;
+	fhs->fcp_control_requests +=  ln->stats.n_control_requests;
+	fhs->fcp_input_megabytes +=  ln->stats.n_input_bytes >> 20;
+	fhs->fcp_output_megabytes +=  ln->stats.n_output_bytes >> 20;
+	fhs->link_failure_count = ln->stats.n_link_down;
+	/* Reset stats for the device */
+	seconds = jiffies_to_msecs(jiffies) - hw->stats.n_reset_start;
+	do_div(seconds, 1000);
+	fhs->seconds_since_last_reset = seconds;
+
+	return fhs;
+}
+
+/*
+ * csio_set_rport_loss_tmo - Set the rport dev loss timeout
+ * @rport: fc rport.
+ * @timeout: new value for dev loss tmo.
+ *
+ * If timeout is non zero set the dev_loss_tmo to timeout, else set
+ * dev_loss_tmo to one.
+ */
+static void
+csio_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
+{
+	if (timeout)
+		rport->dev_loss_tmo = timeout;
+	else
+		rport->dev_loss_tmo = 1;
+}
+
+static void
+csio_vport_set_state(struct csio_lnode *ln)
+{
+	struct fc_vport *fc_vport = ln->fc_vport;
+	struct csio_lnode  *pln = ln->pln;
+	char state[16];
+
+	/* Set fc vport state based on phyiscal lnode */
+	csio_lnode_state_to_str(pln, state);
+	if (strcmp(state, "READY")) {
+		fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
+		return;
+	}
+
+	if (!(pln->flags & CSIO_LNF_NPIVSUPP)) {
+		fc_vport_set_state(fc_vport, FC_VPORT_NO_FABRIC_SUPP);
+		return;
+	}
+
+	/* Set fc vport state based on virtual lnode */
+	csio_lnode_state_to_str(ln, state);
+	if (strcmp(state, "READY")) {
+		fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
+		return;
+	}
+	fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE);
+}
+
+static int
+csio_fcoe_alloc_vnp(struct csio_hw *hw, struct csio_lnode *ln)
+{
+	struct csio_lnode *pln;
+	struct csio_mb  *mbp;
+	struct fw_fcoe_vnp_cmd *rsp;
+	int ret = 0;
+	int retry = 0;
+
+	/* Issue VNP cmd to alloc vport */
+	/* Allocate Mbox request */
+	spin_lock_irq(&hw->lock);
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	pln = ln->pln;
+	ln->fcf_flowid = pln->fcf_flowid;
+	ln->portid = pln->portid;
+
+	csio_fcoe_vnp_alloc_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
+				    pln->fcf_flowid, pln->vnp_flowid, 0,
+				    csio_ln_wwnn(ln), csio_ln_wwpn(ln), NULL);
+
+	for (retry = 0; retry < 3; retry++) {
+		/* FW is expected to complete vnp cmd in immediate mode
+		 * without much delay.
+		 * Otherwise, there will be increase in IO latency since HW
+		 * lock is held till completion of vnp mbox cmd.
+		 */
+		ret = csio_mb_issue(hw, mbp);
+		if (ret != -EBUSY)
+			break;
+
+		/* Retry if mbox returns busy */
+		spin_unlock_irq(&hw->lock);
+		msleep(2000);
+		spin_lock_irq(&hw->lock);
+	}
+
+	if (ret) {
+		csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n");
+		goto out_free;
+	}
+
+	/* Process Mbox response of VNP command */
+	rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);
+	if (FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) {
+		csio_ln_err(ln, "FCOE VNP ALLOC cmd returned 0x%x!\n",
+			    FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16)));
+		ret = -EINVAL;
+		goto out_free;
+	}
+
+	ln->vnp_flowid = FW_FCOE_VNP_CMD_VNPI_GET(
+				ntohl(rsp->gen_wwn_to_vnpi));
+	memcpy(csio_ln_wwnn(ln), rsp->vnport_wwnn, 8);
+	memcpy(csio_ln_wwpn(ln), rsp->vnport_wwpn, 8);
+
+	csio_ln_dbg(ln, "FCOE VNPI: 0x%x\n", ln->vnp_flowid);
+	csio_ln_dbg(ln, "\tWWNN: %x%x%x%x%x%x%x%x\n",
+		    ln->ln_sparm.wwnn[0], ln->ln_sparm.wwnn[1],
+		    ln->ln_sparm.wwnn[2], ln->ln_sparm.wwnn[3],
+		    ln->ln_sparm.wwnn[4], ln->ln_sparm.wwnn[5],
+		    ln->ln_sparm.wwnn[6], ln->ln_sparm.wwnn[7]);
+	csio_ln_dbg(ln, "\tWWPN: %x%x%x%x%x%x%x%x\n",
+		    ln->ln_sparm.wwpn[0], ln->ln_sparm.wwpn[1],
+		    ln->ln_sparm.wwpn[2], ln->ln_sparm.wwpn[3],
+		    ln->ln_sparm.wwpn[4], ln->ln_sparm.wwpn[5],
+		    ln->ln_sparm.wwpn[6], ln->ln_sparm.wwpn[7]);
+
+out_free:
+	mempool_free(mbp, hw->mb_mempool);
+out:
+	spin_unlock_irq(&hw->lock);
+	return ret;
+}
+
+static int
+csio_fcoe_free_vnp(struct csio_hw *hw, struct csio_lnode *ln)
+{
+	struct csio_lnode *pln;
+	struct csio_mb  *mbp;
+	struct fw_fcoe_vnp_cmd *rsp;
+	int ret = 0;
+	int retry = 0;
+
+	/* Issue VNP cmd to free vport */
+	/* Allocate Mbox request */
+
+	spin_lock_irq(&hw->lock);
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	pln = ln->pln;
+
+	csio_fcoe_vnp_free_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
+				   ln->fcf_flowid, ln->vnp_flowid,
+				   NULL);
+
+	for (retry = 0; retry < 3; retry++) {
+		ret = csio_mb_issue(hw, mbp);
+		if (ret != -EBUSY)
+			break;
+
+		/* Retry if mbox returns busy */
+		spin_unlock_irq(&hw->lock);
+		msleep(2000);
+		spin_lock_irq(&hw->lock);
+	}
+
+	if (ret) {
+		csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n");
+		goto out_free;
+	}
+
+	/* Process Mbox response of VNP command */
+	rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);
+	if (FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) {
+		csio_ln_err(ln, "FCOE VNP FREE cmd returned 0x%x!\n",
+			    FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16)));
+		ret = -EINVAL;
+	}
+
+out_free:
+	mempool_free(mbp, hw->mb_mempool);
+out:
+	spin_unlock_irq(&hw->lock);
+	return ret;
+}
+
+static int
+csio_vport_create(struct fc_vport *fc_vport, bool disable)
+{
+	struct Scsi_Host *shost = fc_vport->shost;
+	struct csio_lnode *pln = shost_priv(shost);
+	struct csio_lnode *ln = NULL;
+	struct csio_hw *hw = csio_lnode_to_hw(pln);
+	uint8_t wwn[8];
+	int ret = -1;
+
+	ln = csio_shost_init(hw, &fc_vport->dev, false, pln);
+	if (!ln)
+		goto error;
+
+	if (fc_vport->node_name != 0) {
+		u64_to_wwn(fc_vport->node_name, wwn);
+
+		if (!CSIO_VALID_WWN(wwn)) {
+			csio_ln_err(ln,
+				    "vport create failed. Invalid wwnn\n");
+			goto error;
+		}
+		memcpy(csio_ln_wwnn(ln), wwn, 8);
+	}
+
+	if (fc_vport->port_name != 0) {
+		u64_to_wwn(fc_vport->port_name, wwn);
+
+		if (!CSIO_VALID_WWN(wwn)) {
+			csio_ln_err(ln,
+				    "vport create failed. Invalid wwpn\n");
+			goto error;
+		}
+
+		if (csio_lnode_lookup_by_wwpn(hw, wwn)) {
+			csio_ln_err(ln,
+			    "vport create failed. wwpn already exists\n");
+			goto error;
+		}
+		memcpy(csio_ln_wwpn(ln), wwn, 8);
+	}
+
+	fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
+
+	if (csio_fcoe_alloc_vnp(hw, ln))
+		goto error;
+
+	*(struct csio_lnode **)fc_vport->dd_data = ln;
+	ln->fc_vport = fc_vport;
+	if (!fc_vport->node_name)
+		fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln));
+	if (!fc_vport->port_name)
+		fc_vport->port_name = wwn_to_u64(csio_ln_wwpn(ln));
+	csio_fchost_attr_init(ln);
+	return 0;
+error:
+	if (ln)
+		csio_shost_exit(ln);
+
+	return ret;
+}
+
+static int
+csio_vport_delete(struct fc_vport *fc_vport)
+{
+	struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data;
+	struct Scsi_Host *shost = csio_ln_to_shost(ln);
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+	int rmv;
+
+	spin_lock_irq(&hw->lock);
+	rmv = csio_is_hw_removing(hw);
+	spin_unlock_irq(&hw->lock);
+
+	if (rmv) {
+		csio_shost_exit(ln);
+		return 0;
+	}
+
+	/* Quiesce ios and send remove event to lnode */
+	scsi_block_requests(shost);
+	spin_lock_irq(&hw->lock);
+	csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln);
+	csio_lnode_close(ln);
+	spin_unlock_irq(&hw->lock);
+	scsi_unblock_requests(shost);
+
+	/* Free vnp */
+	if (fc_vport->vport_state !=  FC_VPORT_DISABLED)
+		csio_fcoe_free_vnp(hw, ln);
+
+	csio_shost_exit(ln);
+	return 0;
+}
+
+static int
+csio_vport_disable(struct fc_vport *fc_vport, bool disable)
+{
+	struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data;
+	struct Scsi_Host *shost = csio_ln_to_shost(ln);
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+	/* disable vport */
+	if (disable) {
+		/* Quiesce ios and send stop event to lnode */
+		scsi_block_requests(shost);
+		spin_lock_irq(&hw->lock);
+		csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln);
+		csio_lnode_stop(ln);
+		spin_unlock_irq(&hw->lock);
+		scsi_unblock_requests(shost);
+
+		/* Free vnp */
+		csio_fcoe_free_vnp(hw, ln);
+		fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
+		csio_ln_err(ln, "vport disabled\n");
+		return 0;
+	} else {
+		/* enable vport */
+		fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
+		if (csio_fcoe_alloc_vnp(hw, ln)) {
+			csio_ln_err(ln, "vport enabled failed.\n");
+			return -1;
+		}
+		csio_ln_err(ln, "vport enabled\n");
+		return 0;
+	}
+}
+
+static void
+csio_dev_loss_tmo_callbk(struct fc_rport *rport)
+{
+	struct csio_rnode *rn;
+	struct csio_hw *hw;
+	struct csio_lnode *ln;
+
+	rn = *((struct csio_rnode **)rport->dd_data);
+	ln = csio_rnode_to_lnode(rn);
+	hw = csio_lnode_to_hw(ln);
+
+	spin_lock_irq(&hw->lock);
+
+	/* return if driver is being removed or same rnode comes back online */
+	if (csio_is_hw_removing(hw) || csio_is_rnode_ready(rn))
+		goto out;
+
+	csio_ln_dbg(ln, "devloss timeout on rnode:%p portid:x%x flowid:x%x\n",
+		    rn, rn->nport_id, csio_rn_flowid(rn));
+
+	CSIO_INC_STATS(ln, n_dev_loss_tmo);
+
+	/*
+	 * enqueue devloss event to event worker thread to serialize all
+	 * rnode events.
+	 */
+	if (csio_enqueue_evt(hw, CSIO_EVT_DEV_LOSS, &rn, sizeof(rn))) {
+		CSIO_INC_STATS(hw, n_evt_drop);
+		goto out;
+	}
+
+	if (!(hw->flags & CSIO_HWF_FWEVT_PENDING)) {
+		hw->flags |= CSIO_HWF_FWEVT_PENDING;
+		spin_unlock_irq(&hw->lock);
+		schedule_work(&hw->evtq_work);
+		return;
+	}
+
+out:
+	spin_unlock_irq(&hw->lock);
+}
+
+/* FC transport functions template - Physical port */
+struct fc_function_template csio_fc_transport_funcs = {
+	.show_host_node_name = 1,
+	.show_host_port_name = 1,
+	.show_host_supported_classes = 1,
+	.show_host_supported_fc4s = 1,
+	.show_host_maxframe_size = 1,
+
+	.get_host_port_id = csio_get_host_port_id,
+	.show_host_port_id = 1,
+
+	.get_host_port_type = csio_get_host_port_type,
+	.show_host_port_type = 1,
+
+	.get_host_port_state = csio_get_host_port_state,
+	.show_host_port_state = 1,
+
+	.show_host_active_fc4s = 1,
+	.get_host_speed = csio_get_host_speed,
+	.show_host_speed = 1,
+	.get_host_fabric_name = csio_get_host_fabric_name,
+	.show_host_fabric_name = 1,
+
+	.get_fc_host_stats = csio_get_stats,
+
+	.dd_fcrport_size = sizeof(struct csio_rnode *),
+	.show_rport_maxframe_size = 1,
+	.show_rport_supported_classes = 1,
+
+	.set_rport_dev_loss_tmo = csio_set_rport_loss_tmo,
+	.show_rport_dev_loss_tmo = 1,
+
+	.show_starget_port_id = 1,
+	.show_starget_node_name = 1,
+	.show_starget_port_name = 1,
+
+	.dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk,
+	.dd_fcvport_size = sizeof(struct csio_lnode *),
+
+	.vport_create = csio_vport_create,
+	.vport_disable = csio_vport_disable,
+	.vport_delete = csio_vport_delete,
+};
+
+/* FC transport functions template - Virtual  port */
+struct fc_function_template csio_fc_transport_vport_funcs = {
+	.show_host_node_name = 1,
+	.show_host_port_name = 1,
+	.show_host_supported_classes = 1,
+	.show_host_supported_fc4s = 1,
+	.show_host_maxframe_size = 1,
+
+	.get_host_port_id = csio_get_host_port_id,
+	.show_host_port_id = 1,
+
+	.get_host_port_type = csio_get_host_port_type,
+	.show_host_port_type = 1,
+
+	.get_host_port_state = csio_get_host_port_state,
+	.show_host_port_state = 1,
+	.show_host_active_fc4s = 1,
+
+	.get_host_speed = csio_get_host_speed,
+	.show_host_speed = 1,
+
+	.get_host_fabric_name = csio_get_host_fabric_name,
+	.show_host_fabric_name = 1,
+
+	.get_fc_host_stats = csio_get_stats,
+
+	.dd_fcrport_size = sizeof(struct csio_rnode *),
+	.show_rport_maxframe_size = 1,
+	.show_rport_supported_classes = 1,
+
+	.set_rport_dev_loss_tmo = csio_set_rport_loss_tmo,
+	.show_rport_dev_loss_tmo = 1,
+
+	.show_starget_port_id = 1,
+	.show_starget_node_name = 1,
+	.show_starget_port_name = 1,
+
+	.dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk,
+
+};
diff --git a/drivers/scsi/csiostor/csio_defs.h b/drivers/scsi/csiostor/csio_defs.h
new file mode 100644
index 0000000..c38017b
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_defs.h
@@ -0,0 +1,121 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_DEFS_H__
+#define __CSIO_DEFS_H__
+
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/bug.h>
+#include <linux/pci.h>
+#include <linux/jiffies.h>
+
+#define CSIO_INVALID_IDX		0xFFFFFFFF
+#define CSIO_INC_STATS(elem, val)	((elem)->stats.val++)
+#define CSIO_DEC_STATS(elem, val)	((elem)->stats.val--)
+#define CSIO_VALID_WWN(__n)		((*__n >> 4) == 0x5 ? true : false)
+#define CSIO_DID_MASK			0xFFFFFF
+#define CSIO_WORD_TO_BYTE		4
+
+#ifndef readq
+static inline u64 readq(void __iomem *addr)
+{
+	return readl(addr) + ((u64)readl(addr + 4) << 32);
+}
+
+static inline void writeq(u64 val, void __iomem *addr)
+{
+	writel(val, addr);
+	writel(val >> 32, addr + 4);
+}
+#endif
+
+static inline int
+csio_list_deleted(struct list_head *list)
+{
+	return ((list->next == list) && (list->prev == list));
+}
+
+#define csio_list_next(elem)	(((struct list_head *)(elem))->next)
+#define csio_list_prev(elem)	(((struct list_head *)(elem))->prev)
+
+/* State machine */
+typedef void (*csio_sm_state_t)(void *, uint32_t);
+
+struct csio_sm {
+	struct list_head	sm_list;
+	csio_sm_state_t		sm_state;
+};
+
+static inline void
+csio_set_state(void *smp, void *state)
+{
+	((struct csio_sm *)smp)->sm_state = (csio_sm_state_t)state;
+}
+
+static inline void
+csio_init_state(struct csio_sm *smp, void *state)
+{
+	csio_set_state(smp, state);
+}
+
+static inline void
+csio_post_event(void *smp, uint32_t evt)
+{
+	((struct csio_sm *)smp)->sm_state(smp, evt);
+}
+
+static inline csio_sm_state_t
+csio_get_state(void *smp)
+{
+	return ((struct csio_sm *)smp)->sm_state;
+}
+
+static inline bool
+csio_match_state(void *smp, void *state)
+{
+	return (csio_get_state(smp) == (csio_sm_state_t)state);
+}
+
+#define	CSIO_ASSERT(cond)		BUG_ON(!(cond))
+
+#ifdef __CSIO_DEBUG__
+#define CSIO_DB_ASSERT(__c)		CSIO_ASSERT((__c))
+#else
+#define CSIO_DB_ASSERT(__c)
+#endif
+
+#endif /* ifndef __CSIO_DEFS_H__ */
diff --git a/drivers/scsi/csiostor/csio_hw.c b/drivers/scsi/csiostor/csio_hw.c
new file mode 100644
index 0000000..963c6c1
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_hw.c
@@ -0,0 +1,4395 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/firmware.h>
+#include <linux/stddef.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/compiler.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/log2.h>
+
+#include "csio_hw.h"
+#include "csio_lnode.h"
+#include "csio_rnode.h"
+
+int csio_force_master;
+int csio_dbg_level = 0xFEFF;
+unsigned int csio_port_mask = 0xf;
+
+/* Default FW event queue entries. */
+static uint32_t csio_evtq_sz = CSIO_EVTQ_SIZE;
+
+/* Default MSI param level */
+int csio_msi = 2;
+
+/* FCoE function instances */
+static int dev_num;
+
+/* FCoE Adapter types & its description */
+static const struct csio_adap_desc csio_fcoe_adapters[] = {
+	{"T440-Dbg 10G", "Chelsio T440-Dbg 10G [FCoE]"},
+	{"T420-CR 10G", "Chelsio T420-CR 10G [FCoE]"},
+	{"T422-CR 10G/1G", "Chelsio T422-CR 10G/1G [FCoE]"},
+	{"T440-CR 10G", "Chelsio T440-CR 10G [FCoE]"},
+	{"T420-BCH 10G", "Chelsio T420-BCH 10G [FCoE]"},
+	{"T440-BCH 10G", "Chelsio T440-BCH 10G [FCoE]"},
+	{"T440-CH 10G", "Chelsio T440-CH 10G [FCoE]"},
+	{"T420-SO 10G", "Chelsio T420-SO 10G [FCoE]"},
+	{"T420-CX4 10G", "Chelsio T420-CX4 10G [FCoE]"},
+	{"T420-BT 10G", "Chelsio T420-BT 10G [FCoE]"},
+	{"T404-BT 1G", "Chelsio T404-BT 1G [FCoE]"},
+	{"B420-SR 10G", "Chelsio B420-SR 10G [FCoE]"},
+	{"B404-BT 1G", "Chelsio B404-BT 1G [FCoE]"},
+	{"T480-CR 10G", "Chelsio T480-CR 10G [FCoE]"},
+	{"T440-LP-CR 10G", "Chelsio T440-LP-CR 10G [FCoE]"},
+	{"T4 FPGA", "Chelsio T4 FPGA [FCoE]"}
+};
+
+static void csio_mgmtm_cleanup(struct csio_mgmtm *);
+static void csio_hw_mbm_cleanup(struct csio_hw *);
+
+/* State machine forward declarations */
+static void csio_hws_uninit(struct csio_hw *, enum csio_hw_ev);
+static void csio_hws_configuring(struct csio_hw *, enum csio_hw_ev);
+static void csio_hws_initializing(struct csio_hw *, enum csio_hw_ev);
+static void csio_hws_ready(struct csio_hw *, enum csio_hw_ev);
+static void csio_hws_quiescing(struct csio_hw *, enum csio_hw_ev);
+static void csio_hws_quiesced(struct csio_hw *, enum csio_hw_ev);
+static void csio_hws_resetting(struct csio_hw *, enum csio_hw_ev);
+static void csio_hws_removing(struct csio_hw *, enum csio_hw_ev);
+static void csio_hws_pcierr(struct csio_hw *, enum csio_hw_ev);
+
+static void csio_hw_initialize(struct csio_hw *hw);
+static void csio_evtq_stop(struct csio_hw *hw);
+static void csio_evtq_start(struct csio_hw *hw);
+
+int csio_is_hw_ready(struct csio_hw *hw)
+{
+	return csio_match_state(hw, csio_hws_ready);
+}
+
+int csio_is_hw_removing(struct csio_hw *hw)
+{
+	return csio_match_state(hw, csio_hws_removing);
+}
+
+
+/*
+ *	csio_hw_wait_op_done_val - wait until an operation is completed
+ *	@hw: the HW module
+ *	@reg: the register to check for completion
+ *	@mask: a single-bit field within @reg that indicates completion
+ *	@polarity: the value of the field when the operation is completed
+ *	@attempts: number of check iterations
+ *	@delay: delay in usecs between iterations
+ *	@valp: where to store the value of the register at completion time
+ *
+ *	Wait until an operation is completed by checking a bit in a register
+ *	up to @attempts times.  If @valp is not NULL the value of the register
+ *	at the time it indicated completion is stored there.  Returns 0 if the
+ *	operation completes and	-EAGAIN	otherwise.
+ */
+static int
+csio_hw_wait_op_done_val(struct csio_hw *hw, int reg, uint32_t mask,
+			 int polarity, int attempts, int delay, uint32_t *valp)
+{
+	uint32_t val;
+	while (1) {
+		val = csio_rd_reg32(hw, reg);
+
+		if (!!(val & mask) == polarity) {
+			if (valp)
+				*valp = val;
+			return 0;
+		}
+
+		if (--attempts == 0)
+			return -EAGAIN;
+		if (delay)
+			udelay(delay);
+	}
+}
+
+void
+csio_set_reg_field(struct csio_hw *hw, uint32_t reg, uint32_t mask,
+		   uint32_t value)
+{
+	uint32_t val = csio_rd_reg32(hw, reg) & ~mask;
+
+	csio_wr_reg32(hw, val | value, reg);
+	/* Flush */
+	csio_rd_reg32(hw, reg);
+
+}
+
+/*
+ *	csio_hw_mc_read - read from MC through backdoor accesses
+ *	@hw: the hw module
+ *	@addr: address of first byte requested
+ *	@data: 64 bytes of data containing the requested address
+ *	@ecc: where to store the corresponding 64-bit ECC word
+ *
+ *	Read 64 bytes of data from MC starting at a 64-byte-aligned address
+ *	that covers the requested address @addr.  If @parity is not %NULL it
+ *	is assigned the 64-bit ECC word for the read data.
+ */
+int
+csio_hw_mc_read(struct csio_hw *hw, uint32_t addr, uint32_t *data,
+		uint64_t *ecc)
+{
+	int i;
+
+	if (csio_rd_reg32(hw, MC_BIST_CMD) & START_BIST)
+		return -EBUSY;
+	csio_wr_reg32(hw, addr & ~0x3fU, MC_BIST_CMD_ADDR);
+	csio_wr_reg32(hw, 64, MC_BIST_CMD_LEN);
+	csio_wr_reg32(hw, 0xc, MC_BIST_DATA_PATTERN);
+	csio_wr_reg32(hw, BIST_OPCODE(1) | START_BIST |  BIST_CMD_GAP(1),
+		      MC_BIST_CMD);
+	i = csio_hw_wait_op_done_val(hw, MC_BIST_CMD, START_BIST,
+		 0, 10, 1, NULL);
+	if (i)
+		return i;
+
+#define MC_DATA(i) MC_BIST_STATUS_REG(MC_BIST_STATUS_RDATA, i)
+
+	for (i = 15; i >= 0; i--)
+		*data++ = htonl(csio_rd_reg32(hw, MC_DATA(i)));
+	if (ecc)
+		*ecc = csio_rd_reg64(hw, MC_DATA(16));
+#undef MC_DATA
+	return 0;
+}
+
+/*
+ *	csio_hw_edc_read - read from EDC through backdoor accesses
+ *	@hw: the hw module
+ *	@idx: which EDC to access
+ *	@addr: address of first byte requested
+ *	@data: 64 bytes of data containing the requested address
+ *	@ecc: where to store the corresponding 64-bit ECC word
+ *
+ *	Read 64 bytes of data from EDC starting at a 64-byte-aligned address
+ *	that covers the requested address @addr.  If @parity is not %NULL it
+ *	is assigned the 64-bit ECC word for the read data.
+ */
+int
+csio_hw_edc_read(struct csio_hw *hw, int idx, uint32_t addr, uint32_t *data,
+		uint64_t *ecc)
+{
+	int i;
+
+	idx *= EDC_STRIDE;
+	if (csio_rd_reg32(hw, EDC_BIST_CMD + idx) & START_BIST)
+		return -EBUSY;
+	csio_wr_reg32(hw, addr & ~0x3fU, EDC_BIST_CMD_ADDR + idx);
+	csio_wr_reg32(hw, 64, EDC_BIST_CMD_LEN + idx);
+	csio_wr_reg32(hw, 0xc, EDC_BIST_DATA_PATTERN + idx);
+	csio_wr_reg32(hw, BIST_OPCODE(1) | BIST_CMD_GAP(1) | START_BIST,
+		     EDC_BIST_CMD + idx);
+	i = csio_hw_wait_op_done_val(hw, EDC_BIST_CMD + idx, START_BIST,
+		 0, 10, 1, NULL);
+	if (i)
+		return i;
+
+#define EDC_DATA(i) (EDC_BIST_STATUS_REG(EDC_BIST_STATUS_RDATA, i) + idx)
+
+	for (i = 15; i >= 0; i--)
+		*data++ = htonl(csio_rd_reg32(hw, EDC_DATA(i)));
+	if (ecc)
+		*ecc = csio_rd_reg64(hw, EDC_DATA(16));
+#undef EDC_DATA
+	return 0;
+}
+
+/*
+ *      csio_mem_win_rw - read/write memory through PCIE memory window
+ *      @hw: the adapter
+ *      @addr: address of first byte requested
+ *      @data: MEMWIN0_APERTURE bytes of data containing the requested address
+ *      @dir: direction of transfer 1 => read, 0 => write
+ *
+ *      Read/write MEMWIN0_APERTURE bytes of data from MC starting at a
+ *      MEMWIN0_APERTURE-byte-aligned address that covers the requested
+ *      address @addr.
+ */
+static int
+csio_mem_win_rw(struct csio_hw *hw, u32 addr, __be32 *data, int dir)
+{
+	int i;
+
+	/*
+	 * Setup offset into PCIE memory window.  Address must be a
+	 * MEMWIN0_APERTURE-byte-aligned address.  (Read back MA register to
+	 * ensure that changes propagate before we attempt to use the new
+	 * values.)
+	 */
+	csio_wr_reg32(hw, addr & ~(MEMWIN0_APERTURE - 1),
+			PCIE_MEM_ACCESS_OFFSET);
+	csio_rd_reg32(hw, PCIE_MEM_ACCESS_OFFSET);
+
+	/* Collecting data 4 bytes at a time upto MEMWIN0_APERTURE */
+	for (i = 0; i < MEMWIN0_APERTURE; i = i + sizeof(__be32)) {
+		if (dir)
+			*data++ = csio_rd_reg32(hw, (MEMWIN0_BASE + i));
+		else
+			csio_wr_reg32(hw, *data++, (MEMWIN0_BASE + i));
+	}
+
+	return 0;
+}
+
+/*
+ *      csio_memory_rw - read/write EDC 0, EDC 1 or MC via PCIE memory window
+ *      @hw: the csio_hw
+ *      @mtype: memory type: MEM_EDC0, MEM_EDC1 or MEM_MC
+ *      @addr: address within indicated memory type
+ *      @len: amount of memory to transfer
+ *      @buf: host memory buffer
+ *      @dir: direction of transfer 1 => read, 0 => write
+ *
+ *      Reads/writes an [almost] arbitrary memory region in the firmware: the
+ *      firmware memory address, length and host buffer must be aligned on
+ *      32-bit boudaries.  The memory is transferred as a raw byte sequence
+ *      from/to the firmware's memory.  If this memory contains data
+ *      structures which contain multi-byte integers, it's the callers
+ *      responsibility to perform appropriate byte order conversions.
+ */
+static int
+csio_memory_rw(struct csio_hw *hw, int mtype, u32 addr, u32 len,
+		uint32_t *buf, int dir)
+{
+	uint32_t pos, start, end, offset, memoffset;
+	int ret;
+	__be32 *data;
+
+	/*
+	 * Argument sanity checks ...
+	 */
+	if ((addr & 0x3) || (len & 0x3))
+		return -EINVAL;
+
+	data = kzalloc(MEMWIN0_APERTURE, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	/* Offset into the region of memory which is being accessed
+	 * MEM_EDC0 = 0
+	 * MEM_EDC1 = 1
+	 * MEM_MC   = 2
+	 */
+	memoffset = (mtype * (5 * 1024 * 1024));
+
+	/* Determine the PCIE_MEM_ACCESS_OFFSET */
+	addr = addr + memoffset;
+
+	/*
+	 * The underlaying EDC/MC read routines read MEMWIN0_APERTURE bytes
+	 * at a time so we need to round down the start and round up the end.
+	 * We'll start copying out of the first line at (addr - start) a word
+	 * at a time.
+	 */
+	start = addr & ~(MEMWIN0_APERTURE-1);
+	end = (addr + len + MEMWIN0_APERTURE-1) & ~(MEMWIN0_APERTURE-1);
+	offset = (addr - start)/sizeof(__be32);
+
+	for (pos = start; pos < end; pos += MEMWIN0_APERTURE, offset = 0) {
+		/*
+		 * If we're writing, copy the data from the caller's memory
+		 * buffer
+		 */
+		if (!dir) {
+			/*
+			 * If we're doing a partial write, then we need to do
+			 * a read-modify-write ...
+			 */
+			if (offset || len < MEMWIN0_APERTURE) {
+				ret = csio_mem_win_rw(hw, pos, data, 1);
+				if (ret) {
+					kfree(data);
+					return ret;
+				}
+			}
+			while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) &&
+								len > 0) {
+				data[offset++] = *buf++;
+				len -= sizeof(__be32);
+			}
+		}
+
+		/*
+		 * Transfer a block of memory and bail if there's an error.
+		 */
+		ret = csio_mem_win_rw(hw, pos, data, dir);
+		if (ret) {
+			kfree(data);
+			return ret;
+		}
+
+		/*
+		 * If we're reading, copy the data into the caller's memory
+		 * buffer.
+		 */
+		if (dir)
+			while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) &&
+								len > 0) {
+				*buf++ = data[offset++];
+				len -= sizeof(__be32);
+			}
+	}
+
+	kfree(data);
+
+	return 0;
+}
+
+static int
+csio_memory_write(struct csio_hw *hw, int mtype, u32 addr, u32 len, __be32 *buf)
+{
+	return csio_memory_rw(hw, mtype, addr, len, buf, 0);
+}
+
+/*
+ * EEPROM reads take a few tens of us while writes can take a bit over 5 ms.
+ */
+#define EEPROM_MAX_RD_POLL 40
+#define EEPROM_MAX_WR_POLL 6
+#define EEPROM_STAT_ADDR   0x7bfc
+#define VPD_BASE           0x400
+#define VPD_BASE_OLD	   0
+#define VPD_LEN            512
+#define VPD_INFO_FLD_HDR_SIZE	3
+
+/*
+ *	csio_hw_seeprom_read - read a serial EEPROM location
+ *	@hw: hw to read
+ *	@addr: EEPROM virtual address
+ *	@data: where to store the read data
+ *
+ *	Read a 32-bit word from a location in serial EEPROM using the card's PCI
+ *	VPD capability.  Note that this function must be called with a virtual
+ *	address.
+ */
+static int
+csio_hw_seeprom_read(struct csio_hw *hw, uint32_t addr, uint32_t *data)
+{
+	uint16_t val = 0;
+	int attempts = EEPROM_MAX_RD_POLL;
+	uint32_t base = hw->params.pci.vpd_cap_addr;
+
+	if (addr >= EEPROMVSIZE || (addr & 3))
+		return -EINVAL;
+
+	pci_write_config_word(hw->pdev, base + PCI_VPD_ADDR, (uint16_t)addr);
+
+	do {
+		udelay(10);
+		pci_read_config_word(hw->pdev, base + PCI_VPD_ADDR, &val);
+	} while (!(val & PCI_VPD_ADDR_F) && --attempts);
+
+	if (!(val & PCI_VPD_ADDR_F)) {
+		csio_err(hw, "reading EEPROM address 0x%x failed\n", addr);
+		return -EINVAL;
+	}
+
+	pci_read_config_dword(hw->pdev, base + PCI_VPD_DATA, data);
+	*data = le32_to_cpu(*data);
+	return 0;
+}
+
+/*
+ * Partial EEPROM Vital Product Data structure.  Includes only the ID and
+ * VPD-R sections.
+ */
+struct t4_vpd_hdr {
+	u8  id_tag;
+	u8  id_len[2];
+	u8  id_data[ID_LEN];
+	u8  vpdr_tag;
+	u8  vpdr_len[2];
+};
+
+/*
+ *	csio_hw_get_vpd_keyword_val - Locates an information field keyword in
+ *				      the VPD
+ *	@v: Pointer to buffered vpd data structure
+ *	@kw: The keyword to search for
+ *
+ *	Returns the value of the information field keyword or
+ *	-EINVAL otherwise.
+ */
+static int
+csio_hw_get_vpd_keyword_val(const struct t4_vpd_hdr *v, const char *kw)
+{
+	int32_t i;
+	int32_t offset , len;
+	const uint8_t *buf = &v->id_tag;
+	const uint8_t *vpdr_len = &v->vpdr_tag;
+	offset = sizeof(struct t4_vpd_hdr);
+	len =  (uint16_t)vpdr_len[1] + ((uint16_t)vpdr_len[2] << 8);
+
+	if (len + sizeof(struct t4_vpd_hdr) > VPD_LEN)
+		return -EINVAL;
+
+	for (i = offset; (i + VPD_INFO_FLD_HDR_SIZE) <= (offset + len);) {
+		if (memcmp(buf + i , kw, 2) == 0) {
+			i += VPD_INFO_FLD_HDR_SIZE;
+			return i;
+		}
+
+		i += VPD_INFO_FLD_HDR_SIZE + buf[i+2];
+	}
+
+	return -EINVAL;
+}
+
+static int
+csio_pci_capability(struct pci_dev *pdev, int cap, int *pos)
+{
+	*pos = pci_find_capability(pdev, cap);
+	if (*pos)
+		return 0;
+
+	return -1;
+}
+
+/*
+ *	csio_hw_get_vpd_params - read VPD parameters from VPD EEPROM
+ *	@hw: HW module
+ *	@p: where to store the parameters
+ *
+ *	Reads card parameters stored in VPD EEPROM.
+ */
+static int
+csio_hw_get_vpd_params(struct csio_hw *hw, struct csio_vpd *p)
+{
+	int i, ret, ec, sn, addr;
+	uint8_t *vpd, csum;
+	const struct t4_vpd_hdr *v;
+	/* To get around compilation warning from strstrip */
+	char *s;
+
+	if (csio_is_valid_vpd(hw))
+		return 0;
+
+	ret = csio_pci_capability(hw->pdev, PCI_CAP_ID_VPD,
+				  &hw->params.pci.vpd_cap_addr);
+	if (ret)
+		return -EINVAL;
+
+	vpd = kzalloc(VPD_LEN, GFP_ATOMIC);
+	if (vpd == NULL)
+		return -ENOMEM;
+
+	/*
+	 * Card information normally starts at VPD_BASE but early cards had
+	 * it at 0.
+	 */
+	ret = csio_hw_seeprom_read(hw, VPD_BASE, (uint32_t *)(vpd));
+	addr = *vpd == 0x82 ? VPD_BASE : VPD_BASE_OLD;
+
+	for (i = 0; i < VPD_LEN; i += 4) {
+		ret = csio_hw_seeprom_read(hw, addr + i, (uint32_t *)(vpd + i));
+		if (ret) {
+			kfree(vpd);
+			return ret;
+		}
+	}
+
+	/* Reset the VPD flag! */
+	hw->flags &= (~CSIO_HWF_VPD_VALID);
+
+	v = (const struct t4_vpd_hdr *)vpd;
+
+#define FIND_VPD_KW(var, name) do { \
+	var = csio_hw_get_vpd_keyword_val(v, name); \
+	if (var < 0) { \
+		csio_err(hw, "missing VPD keyword " name "\n"); \
+		kfree(vpd); \
+		return -EINVAL; \
+	} \
+} while (0)
+
+	FIND_VPD_KW(i, "RV");
+	for (csum = 0; i >= 0; i--)
+		csum += vpd[i];
+
+	if (csum) {
+		csio_err(hw, "corrupted VPD EEPROM, actual csum %u\n", csum);
+		kfree(vpd);
+		return -EINVAL;
+	}
+	FIND_VPD_KW(ec, "EC");
+	FIND_VPD_KW(sn, "SN");
+#undef FIND_VPD_KW
+
+	memcpy(p->id, v->id_data, ID_LEN);
+	s = strstrip(p->id);
+	memcpy(p->ec, vpd + ec, EC_LEN);
+	s = strstrip(p->ec);
+	i = vpd[sn - VPD_INFO_FLD_HDR_SIZE + 2];
+	memcpy(p->sn, vpd + sn, min(i, SERNUM_LEN));
+	s = strstrip(p->sn);
+
+	csio_valid_vpd_copied(hw);
+
+	kfree(vpd);
+	return 0;
+}
+
+/*
+ *	csio_hw_sf1_read - read data from the serial flash
+ *	@hw: the HW module
+ *	@byte_cnt: number of bytes to read
+ *	@cont: whether another operation will be chained
+ *      @lock: whether to lock SF for PL access only
+ *	@valp: where to store the read data
+ *
+ *	Reads up to 4 bytes of data from the serial flash.  The location of
+ *	the read needs to be specified prior to calling this by issuing the
+ *	appropriate commands to the serial flash.
+ */
+static int
+csio_hw_sf1_read(struct csio_hw *hw, uint32_t byte_cnt, int32_t cont,
+		 int32_t lock, uint32_t *valp)
+{
+	int ret;
+
+	if (!byte_cnt || byte_cnt > 4)
+		return -EINVAL;
+	if (csio_rd_reg32(hw, SF_OP) & SF_BUSY)
+		return -EBUSY;
+
+	cont = cont ? SF_CONT : 0;
+	lock = lock ? SF_LOCK : 0;
+
+	csio_wr_reg32(hw, lock | cont | BYTECNT(byte_cnt - 1), SF_OP);
+	ret = csio_hw_wait_op_done_val(hw, SF_OP, SF_BUSY, 0, SF_ATTEMPTS,
+					 10, NULL);
+	if (!ret)
+		*valp = csio_rd_reg32(hw, SF_DATA);
+	return ret;
+}
+
+/*
+ *	csio_hw_sf1_write - write data to the serial flash
+ *	@hw: the HW module
+ *	@byte_cnt: number of bytes to write
+ *	@cont: whether another operation will be chained
+ *      @lock: whether to lock SF for PL access only
+ *	@val: value to write
+ *
+ *	Writes up to 4 bytes of data to the serial flash.  The location of
+ *	the write needs to be specified prior to calling this by issuing the
+ *	appropriate commands to the serial flash.
+ */
+static int
+csio_hw_sf1_write(struct csio_hw *hw, uint32_t byte_cnt, uint32_t cont,
+		  int32_t lock, uint32_t val)
+{
+	if (!byte_cnt || byte_cnt > 4)
+		return -EINVAL;
+	if (csio_rd_reg32(hw, SF_OP) & SF_BUSY)
+		return -EBUSY;
+
+	cont = cont ? SF_CONT : 0;
+	lock = lock ? SF_LOCK : 0;
+
+	csio_wr_reg32(hw, val, SF_DATA);
+	csio_wr_reg32(hw, cont | BYTECNT(byte_cnt - 1) | OP_WR | lock, SF_OP);
+
+	return csio_hw_wait_op_done_val(hw, SF_OP, SF_BUSY, 0, SF_ATTEMPTS,
+					10, NULL);
+}
+
+/*
+ *	csio_hw_flash_wait_op - wait for a flash operation to complete
+ *	@hw: the HW module
+ *	@attempts: max number of polls of the status register
+ *	@delay: delay between polls in ms
+ *
+ *	Wait for a flash operation to complete by polling the status register.
+ */
+static int
+csio_hw_flash_wait_op(struct csio_hw *hw, int32_t attempts, int32_t delay)
+{
+	int ret;
+	uint32_t status;
+
+	while (1) {
+		ret = csio_hw_sf1_write(hw, 1, 1, 1, SF_RD_STATUS);
+		if (ret != 0)
+			return ret;
+
+		ret = csio_hw_sf1_read(hw, 1, 0, 1, &status);
+		if (ret != 0)
+			return ret;
+
+		if (!(status & 1))
+			return 0;
+		if (--attempts == 0)
+			return -EAGAIN;
+		if (delay)
+			msleep(delay);
+	}
+}
+
+/*
+ *	csio_hw_read_flash - read words from serial flash
+ *	@hw: the HW module
+ *	@addr: the start address for the read
+ *	@nwords: how many 32-bit words to read
+ *	@data: where to store the read data
+ *	@byte_oriented: whether to store data as bytes or as words
+ *
+ *	Read the specified number of 32-bit words from the serial flash.
+ *	If @byte_oriented is set the read data is stored as a byte array
+ *	(i.e., big-endian), otherwise as 32-bit words in the platform's
+ *	natural endianess.
+ */
+static int
+csio_hw_read_flash(struct csio_hw *hw, uint32_t addr, uint32_t nwords,
+		  uint32_t *data, int32_t byte_oriented)
+{
+	int ret;
+
+	if (addr + nwords * sizeof(uint32_t) > hw->params.sf_size || (addr & 3))
+		return -EINVAL;
+
+	addr = swab32(addr) | SF_RD_DATA_FAST;
+
+	ret = csio_hw_sf1_write(hw, 4, 1, 0, addr);
+	if (ret != 0)
+		return ret;
+
+	ret = csio_hw_sf1_read(hw, 1, 1, 0, data);
+	if (ret != 0)
+		return ret;
+
+	for ( ; nwords; nwords--, data++) {
+		ret = csio_hw_sf1_read(hw, 4, nwords > 1, nwords == 1, data);
+		if (nwords == 1)
+			csio_wr_reg32(hw, 0, SF_OP);    /* unlock SF */
+		if (ret)
+			return ret;
+		if (byte_oriented)
+			*data = htonl(*data);
+	}
+	return 0;
+}
+
+/*
+ *	csio_hw_write_flash - write up to a page of data to the serial flash
+ *	@hw: the hw
+ *	@addr: the start address to write
+ *	@n: length of data to write in bytes
+ *	@data: the data to write
+ *
+ *	Writes up to a page of data (256 bytes) to the serial flash starting
+ *	at the given address.  All the data must be written to the same page.
+ */
+static int
+csio_hw_write_flash(struct csio_hw *hw, uint32_t addr,
+		    uint32_t n, const uint8_t *data)
+{
+	int ret = -EINVAL;
+	uint32_t buf[64];
+	uint32_t i, c, left, val, offset = addr & 0xff;
+
+	if (addr >= hw->params.sf_size || offset + n > SF_PAGE_SIZE)
+		return -EINVAL;
+
+	val = swab32(addr) | SF_PROG_PAGE;
+
+	ret = csio_hw_sf1_write(hw, 1, 0, 1, SF_WR_ENABLE);
+	if (ret != 0)
+		goto unlock;
+
+	ret = csio_hw_sf1_write(hw, 4, 1, 1, val);
+	if (ret != 0)
+		goto unlock;
+
+	for (left = n; left; left -= c) {
+		c = min(left, 4U);
+		for (val = 0, i = 0; i < c; ++i)
+			val = (val << 8) + *data++;
+
+		ret = csio_hw_sf1_write(hw, c, c != left, 1, val);
+		if (ret)
+			goto unlock;
+	}
+	ret = csio_hw_flash_wait_op(hw, 8, 1);
+	if (ret)
+		goto unlock;
+
+	csio_wr_reg32(hw, 0, SF_OP);    /* unlock SF */
+
+	/* Read the page to verify the write succeeded */
+	ret = csio_hw_read_flash(hw, addr & ~0xff, ARRAY_SIZE(buf), buf, 1);
+	if (ret)
+		return ret;
+
+	if (memcmp(data - n, (uint8_t *)buf + offset, n)) {
+		csio_err(hw,
+			 "failed to correctly write the flash page at %#x\n",
+			 addr);
+		return -EINVAL;
+	}
+
+	return 0;
+
+unlock:
+	csio_wr_reg32(hw, 0, SF_OP);    /* unlock SF */
+	return ret;
+}
+
+/*
+ *	csio_hw_flash_erase_sectors - erase a range of flash sectors
+ *	@hw: the HW module
+ *	@start: the first sector to erase
+ *	@end: the last sector to erase
+ *
+ *	Erases the sectors in the given inclusive range.
+ */
+static int
+csio_hw_flash_erase_sectors(struct csio_hw *hw, int32_t start, int32_t end)
+{
+	int ret = 0;
+
+	while (start <= end) {
+
+		ret = csio_hw_sf1_write(hw, 1, 0, 1, SF_WR_ENABLE);
+		if (ret != 0)
+			goto out;
+
+		ret = csio_hw_sf1_write(hw, 4, 0, 1,
+					SF_ERASE_SECTOR | (start << 8));
+		if (ret != 0)
+			goto out;
+
+		ret = csio_hw_flash_wait_op(hw, 14, 500);
+		if (ret != 0)
+			goto out;
+
+		start++;
+	}
+out:
+	if (ret)
+		csio_err(hw, "erase of flash sector %d failed, error %d\n",
+			 start, ret);
+	csio_wr_reg32(hw, 0, SF_OP);    /* unlock SF */
+	return 0;
+}
+
+/*
+ *	csio_hw_flash_cfg_addr - return the address of the flash
+ *				configuration file
+ *	@hw: the HW module
+ *
+ *	Return the address within the flash where the Firmware Configuration
+ *	File is stored.
+ */
+static unsigned int
+csio_hw_flash_cfg_addr(struct csio_hw *hw)
+{
+	if (hw->params.sf_size == 0x100000)
+		return FPGA_FLASH_CFG_OFFSET;
+	else
+		return FLASH_CFG_OFFSET;
+}
+
+static void
+csio_hw_print_fw_version(struct csio_hw *hw, char *str)
+{
+	csio_info(hw, "%s: %u.%u.%u.%u\n", str,
+		    FW_HDR_FW_VER_MAJOR_GET(hw->fwrev),
+		    FW_HDR_FW_VER_MINOR_GET(hw->fwrev),
+		    FW_HDR_FW_VER_MICRO_GET(hw->fwrev),
+		    FW_HDR_FW_VER_BUILD_GET(hw->fwrev));
+}
+
+/*
+ * csio_hw_get_fw_version - read the firmware version
+ * @hw: HW module
+ * @vers: where to place the version
+ *
+ * Reads the FW version from flash.
+ */
+static int
+csio_hw_get_fw_version(struct csio_hw *hw, uint32_t *vers)
+{
+	return csio_hw_read_flash(hw, FW_IMG_START +
+				  offsetof(struct fw_hdr, fw_ver), 1,
+				  vers, 0);
+}
+
+/*
+ *	csio_hw_get_tp_version - read the TP microcode version
+ *	@hw: HW module
+ *	@vers: where to place the version
+ *
+ *	Reads the TP microcode version from flash.
+ */
+static int
+csio_hw_get_tp_version(struct csio_hw *hw, u32 *vers)
+{
+	return csio_hw_read_flash(hw, FLASH_FW_START +
+			offsetof(struct fw_hdr, tp_microcode_ver), 1,
+			vers, 0);
+}
+
+/*
+ *	csio_hw_check_fw_version - check if the FW is compatible with
+ *				   this driver
+ *	@hw: HW module
+ *
+ *	Checks if an adapter's FW is compatible with the driver.  Returns 0
+ *	if there's exact match, a negative error if the version could not be
+ *	read or there's a major/minor version mismatch/minor.
+ */
+static int
+csio_hw_check_fw_version(struct csio_hw *hw)
+{
+	int ret, major, minor, micro;
+
+	ret = csio_hw_get_fw_version(hw, &hw->fwrev);
+	if (!ret)
+		ret = csio_hw_get_tp_version(hw, &hw->tp_vers);
+	if (ret)
+		return ret;
+
+	major = FW_HDR_FW_VER_MAJOR_GET(hw->fwrev);
+	minor = FW_HDR_FW_VER_MINOR_GET(hw->fwrev);
+	micro = FW_HDR_FW_VER_MICRO_GET(hw->fwrev);
+
+	if (major != FW_VERSION_MAJOR) {            /* major mismatch - fail */
+		csio_err(hw, "card FW has major version %u, driver wants %u\n",
+			 major, FW_VERSION_MAJOR);
+		return -EINVAL;
+	}
+
+	if (minor == FW_VERSION_MINOR && micro == FW_VERSION_MICRO)
+		return 0;        /* perfect match */
+
+	/* Minor/micro version mismatch */
+	return -EINVAL;
+}
+
+/*
+ * csio_hw_fw_dload - download firmware.
+ * @hw: HW module
+ * @fw_data: firmware image to write.
+ * @size: image size
+ *
+ * Write the supplied firmware image to the card's serial flash.
+ */
+static int
+csio_hw_fw_dload(struct csio_hw *hw, uint8_t *fw_data, uint32_t size)
+{
+	uint32_t csum;
+	int32_t addr;
+	int ret;
+	uint32_t i;
+	uint8_t first_page[SF_PAGE_SIZE];
+	const uint32_t *p = (const uint32_t *)fw_data;
+	struct fw_hdr *hdr = (struct fw_hdr *)fw_data;
+	uint32_t sf_sec_size;
+
+	if ((!hw->params.sf_size) || (!hw->params.sf_nsec)) {
+		csio_err(hw, "Serial Flash data invalid\n");
+		return -EINVAL;
+	}
+
+	if (!size) {
+		csio_err(hw, "FW image has no data\n");
+		return -EINVAL;
+	}
+
+	if (size & 511) {
+		csio_err(hw, "FW image size not multiple of 512 bytes\n");
+		return -EINVAL;
+	}
+
+	if (ntohs(hdr->len512) * 512 != size) {
+		csio_err(hw, "FW image size differs from size in FW header\n");
+		return -EINVAL;
+	}
+
+	if (size > FW_MAX_SIZE) {
+		csio_err(hw, "FW image too large, max is %u bytes\n",
+			    FW_MAX_SIZE);
+		return -EINVAL;
+	}
+
+	for (csum = 0, i = 0; i < size / sizeof(csum); i++)
+		csum += ntohl(p[i]);
+
+	if (csum != 0xffffffff) {
+		csio_err(hw, "corrupted firmware image, checksum %#x\n", csum);
+		return -EINVAL;
+	}
+
+	sf_sec_size = hw->params.sf_size / hw->params.sf_nsec;
+	i = DIV_ROUND_UP(size, sf_sec_size);        /* # of sectors spanned */
+
+	csio_dbg(hw, "Erasing sectors... start:%d end:%d\n",
+			  FW_START_SEC, FW_START_SEC + i - 1);
+
+	ret = csio_hw_flash_erase_sectors(hw, FW_START_SEC,
+					  FW_START_SEC + i - 1);
+	if (ret) {
+		csio_err(hw, "Flash Erase failed\n");
+		goto out;
+	}
+
+	/*
+	 * We write the correct version at the end so the driver can see a bad
+	 * version if the FW write fails.  Start by writing a copy of the
+	 * first page with a bad version.
+	 */
+	memcpy(first_page, fw_data, SF_PAGE_SIZE);
+	((struct fw_hdr *)first_page)->fw_ver = htonl(0xffffffff);
+	ret = csio_hw_write_flash(hw, FW_IMG_START, SF_PAGE_SIZE, first_page);
+	if (ret)
+		goto out;
+
+	csio_dbg(hw, "Writing Flash .. start:%d end:%d\n",
+		    FW_IMG_START, FW_IMG_START + size);
+
+	addr = FW_IMG_START;
+	for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) {
+		addr += SF_PAGE_SIZE;
+		fw_data += SF_PAGE_SIZE;
+		ret = csio_hw_write_flash(hw, addr, SF_PAGE_SIZE, fw_data);
+		if (ret)
+			goto out;
+	}
+
+	ret = csio_hw_write_flash(hw,
+				  FW_IMG_START +
+					offsetof(struct fw_hdr, fw_ver),
+				  sizeof(hdr->fw_ver),
+				  (const uint8_t *)&hdr->fw_ver);
+
+out:
+	if (ret)
+		csio_err(hw, "firmware download failed, error %d\n", ret);
+	return ret;
+}
+
+static int
+csio_hw_get_flash_params(struct csio_hw *hw)
+{
+	int ret;
+	uint32_t info = 0;
+
+	ret = csio_hw_sf1_write(hw, 1, 1, 0, SF_RD_ID);
+	if (!ret)
+		ret = csio_hw_sf1_read(hw, 3, 0, 1, &info);
+	csio_wr_reg32(hw, 0, SF_OP);    /* unlock SF */
+	if (ret != 0)
+		return ret;
+
+	if ((info & 0xff) != 0x20)		/* not a Numonix flash */
+		return -EINVAL;
+	info >>= 16;				/* log2 of size */
+	if (info >= 0x14 && info < 0x18)
+		hw->params.sf_nsec = 1 << (info - 16);
+	else if (info == 0x18)
+		hw->params.sf_nsec = 64;
+	else
+		return -EINVAL;
+	hw->params.sf_size = 1 << info;
+
+	return 0;
+}
+
+static void
+csio_set_pcie_completion_timeout(struct csio_hw *hw, u8 range)
+{
+	uint16_t val;
+	uint32_t pcie_cap;
+
+	if (!csio_pci_capability(hw->pdev, PCI_CAP_ID_EXP, &pcie_cap)) {
+		pci_read_config_word(hw->pdev,
+				     pcie_cap + PCI_EXP_DEVCTL2, &val);
+		val &= 0xfff0;
+		val |= range ;
+		pci_write_config_word(hw->pdev,
+				      pcie_cap + PCI_EXP_DEVCTL2, val);
+	}
+}
+
+
+/*
+ * Return the specified PCI-E Configuration Space register from our Physical
+ * Function.  We try first via a Firmware LDST Command since we prefer to let
+ * the firmware own all of these registers, but if that fails we go for it
+ * directly ourselves.
+ */
+static uint32_t
+csio_read_pcie_cfg4(struct csio_hw *hw, int reg)
+{
+	u32 val = 0;
+	struct csio_mb *mbp;
+	int rv;
+	struct fw_ldst_cmd *ldst_cmd;
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		pci_read_config_dword(hw->pdev, reg, &val);
+		return val;
+	}
+
+	csio_mb_ldst(hw, mbp, CSIO_MB_DEFAULT_TMO, reg);
+
+	rv = csio_mb_issue(hw, mbp);
+
+	/*
+	 * If the LDST Command suucceeded, exctract the returned register
+	 * value.  Otherwise read it directly ourself.
+	 */
+	if (rv == 0) {
+		ldst_cmd = (struct fw_ldst_cmd *)(mbp->mb);
+		val = ntohl(ldst_cmd->u.pcie.data[0]);
+	} else
+		pci_read_config_dword(hw->pdev, reg, &val);
+
+	mempool_free(mbp, hw->mb_mempool);
+
+	return val;
+} /* csio_read_pcie_cfg4 */
+
+static int
+csio_hw_set_mem_win(struct csio_hw *hw)
+{
+	u32 bar0;
+
+	/*
+	 * Truncation intentional: we only read the bottom 32-bits of the
+	 * 64-bit BAR0/BAR1 ...  We use the hardware backdoor mechanism to
+	 * read BAR0 instead of using pci_resource_start() because we could be
+	 * operating from within a Virtual Machine which is trapping our
+	 * accesses to our Configuration Space and we need to set up the PCI-E
+	 * Memory Window decoders with the actual addresses which will be
+	 * coming across the PCI-E link.
+	 */
+	bar0 = csio_read_pcie_cfg4(hw, PCI_BASE_ADDRESS_0);
+	bar0 &= PCI_BASE_ADDRESS_MEM_MASK;
+
+	/*
+	 * Set up memory window for accessing adapter memory ranges.  (Read
+	 * back MA register to ensure that changes propagate before we attempt
+	 * to use the new values.)
+	 */
+	csio_wr_reg32(hw, (bar0 + MEMWIN0_BASE) | BIR(0) |
+		WINDOW(ilog2(MEMWIN0_APERTURE) - 10),
+		PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 0));
+	csio_wr_reg32(hw, (bar0 + MEMWIN1_BASE) | BIR(0) |
+		WINDOW(ilog2(MEMWIN1_APERTURE) - 10),
+		PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 1));
+	csio_wr_reg32(hw, (bar0 + MEMWIN2_BASE) | BIR(0) |
+		WINDOW(ilog2(MEMWIN2_APERTURE) - 10),
+		PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2));
+	csio_rd_reg32(hw, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2));
+	return 0;
+} /* csio_hw_set_mem_win */
+
+
+
+/*****************************************************************************/
+/* HW State machine assists                                                  */
+/*****************************************************************************/
+
+static int
+csio_hw_dev_ready(struct csio_hw *hw)
+{
+	uint32_t reg;
+	int cnt = 6;
+
+	while (((reg = csio_rd_reg32(hw, PL_WHOAMI)) == 0xFFFFFFFF) &&
+								(--cnt != 0))
+		mdelay(100);
+
+	if ((cnt == 0) && (((int32_t)(SOURCEPF_GET(reg)) < 0) ||
+			    (SOURCEPF_GET(reg) >= CSIO_MAX_PFN))) {
+		csio_err(hw, "PL_WHOAMI returned 0x%x, cnt:%d\n", reg, cnt);
+		return -EIO;
+	}
+
+	hw->pfn = SOURCEPF_GET(reg);
+
+	return 0;
+}
+
+/*
+ * csio_do_hello - Perform the HELLO FW Mailbox command and process response.
+ * @hw: HW module
+ * @state: Device state
+ *
+ * FW_HELLO_CMD has to be polled for completion.
+ */
+static int
+csio_do_hello(struct csio_hw *hw, enum csio_dev_state *state)
+{
+	struct csio_mb	*mbp;
+	int	rv = 0;
+	enum csio_dev_master master;
+	enum fw_retval retval;
+	uint8_t mpfn;
+	char state_str[16];
+	int retries = FW_CMD_HELLO_RETRIES;
+
+	memset(state_str, 0, sizeof(state_str));
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		rv = -ENOMEM;
+		CSIO_INC_STATS(hw, n_err_nomem);
+		goto out;
+	}
+
+	master = csio_force_master ? CSIO_MASTER_MUST : CSIO_MASTER_MAY;
+
+retry:
+	csio_mb_hello(hw, mbp, CSIO_MB_DEFAULT_TMO, hw->pfn,
+		      hw->pfn, master, NULL);
+
+	rv = csio_mb_issue(hw, mbp);
+	if (rv) {
+		csio_err(hw, "failed to issue HELLO cmd. ret:%d.\n", rv);
+		goto out_free_mb;
+	}
+
+	csio_mb_process_hello_rsp(hw, mbp, &retval, state, &mpfn);
+	if (retval != FW_SUCCESS) {
+		csio_err(hw, "HELLO cmd failed with ret: %d\n", retval);
+		rv = -EINVAL;
+		goto out_free_mb;
+	}
+
+	/* Firmware has designated us to be master */
+	if (hw->pfn == mpfn) {
+		hw->flags |= CSIO_HWF_MASTER;
+	} else if (*state == CSIO_DEV_STATE_UNINIT) {
+		/*
+		 * If we're not the Master PF then we need to wait around for
+		 * the Master PF Driver to finish setting up the adapter.
+		 *
+		 * Note that we also do this wait if we're a non-Master-capable
+		 * PF and there is no current Master PF; a Master PF may show up
+		 * momentarily and we wouldn't want to fail pointlessly.  (This
+		 * can happen when an OS loads lots of different drivers rapidly
+		 * at the same time). In this case, the Master PF returned by
+		 * the firmware will be PCIE_FW_MASTER_MASK so the test below
+		 * will work ...
+		 */
+
+		int waiting = FW_CMD_HELLO_TIMEOUT;
+
+		/*
+		 * Wait for the firmware to either indicate an error or
+		 * initialized state.  If we see either of these we bail out
+		 * and report the issue to the caller.  If we exhaust the
+		 * "hello timeout" and we haven't exhausted our retries, try
+		 * again.  Otherwise bail with a timeout error.
+		 */
+		for (;;) {
+			uint32_t pcie_fw;
+
+			msleep(50);
+			waiting -= 50;
+
+			/*
+			 * If neither Error nor Initialialized are indicated
+			 * by the firmware keep waiting till we exaust our
+			 * timeout ... and then retry if we haven't exhausted
+			 * our retries ...
+			 */
+			pcie_fw = csio_rd_reg32(hw, PCIE_FW);
+			if (!(pcie_fw & (PCIE_FW_ERR|PCIE_FW_INIT))) {
+				if (waiting <= 0) {
+					if (retries-- > 0)
+						goto retry;
+
+					rv = -ETIMEDOUT;
+					break;
+				}
+				continue;
+			}
+
+			/*
+			 * We either have an Error or Initialized condition
+			 * report errors preferentially.
+			 */
+			if (state) {
+				if (pcie_fw & PCIE_FW_ERR) {
+					*state = CSIO_DEV_STATE_ERR;
+					rv = -ETIMEDOUT;
+				} else if (pcie_fw & PCIE_FW_INIT)
+					*state = CSIO_DEV_STATE_INIT;
+			}
+
+			/*
+			 * If we arrived before a Master PF was selected and
+			 * there's not a valid Master PF, grab its identity
+			 * for our caller.
+			 */
+			if (mpfn == PCIE_FW_MASTER_MASK &&
+			    (pcie_fw & PCIE_FW_MASTER_VLD))
+				mpfn = PCIE_FW_MASTER_GET(pcie_fw);
+			break;
+		}
+		hw->flags &= ~CSIO_HWF_MASTER;
+	}
+
+	switch (*state) {
+	case CSIO_DEV_STATE_UNINIT:
+		strcpy(state_str, "Initializing");
+		break;
+	case CSIO_DEV_STATE_INIT:
+		strcpy(state_str, "Initialized");
+		break;
+	case CSIO_DEV_STATE_ERR:
+		strcpy(state_str, "Error");
+		break;
+	default:
+		strcpy(state_str, "Unknown");
+		break;
+	}
+
+	if (hw->pfn == mpfn)
+		csio_info(hw, "PF: %d, Coming up as MASTER, HW state: %s\n",
+			hw->pfn, state_str);
+	else
+		csio_info(hw,
+		    "PF: %d, Coming up as SLAVE, Master PF: %d, HW state: %s\n",
+		    hw->pfn, mpfn, state_str);
+
+out_free_mb:
+	mempool_free(mbp, hw->mb_mempool);
+out:
+	return rv;
+}
+
+/*
+ * csio_do_bye - Perform the BYE FW Mailbox command and process response.
+ * @hw: HW module
+ *
+ */
+static int
+csio_do_bye(struct csio_hw *hw)
+{
+	struct csio_mb	*mbp;
+	enum fw_retval retval;
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		return -ENOMEM;
+	}
+
+	csio_mb_bye(hw, mbp, CSIO_MB_DEFAULT_TMO, NULL);
+
+	if (csio_mb_issue(hw, mbp)) {
+		csio_err(hw, "Issue of BYE command failed\n");
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	retval = csio_mb_fw_retval(mbp);
+	if (retval != FW_SUCCESS) {
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	mempool_free(mbp, hw->mb_mempool);
+
+	return 0;
+}
+
+/*
+ * csio_do_reset- Perform the device reset.
+ * @hw: HW module
+ * @fw_rst: FW reset
+ *
+ * If fw_rst is set, issues FW reset mbox cmd otherwise
+ * does PIO reset.
+ * Performs reset of the function.
+ */
+static int
+csio_do_reset(struct csio_hw *hw, bool fw_rst)
+{
+	struct csio_mb	*mbp;
+	enum fw_retval retval;
+
+	if (!fw_rst) {
+		/* PIO reset */
+		csio_wr_reg32(hw, PIORSTMODE | PIORST, PL_RST);
+		mdelay(2000);
+		return 0;
+	}
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		return -ENOMEM;
+	}
+
+	csio_mb_reset(hw, mbp, CSIO_MB_DEFAULT_TMO,
+		      PIORSTMODE | PIORST, 0, NULL);
+
+	if (csio_mb_issue(hw, mbp)) {
+		csio_err(hw, "Issue of RESET command failed.n");
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	retval = csio_mb_fw_retval(mbp);
+	if (retval != FW_SUCCESS) {
+		csio_err(hw, "RESET cmd failed with ret:0x%x.\n", retval);
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	mempool_free(mbp, hw->mb_mempool);
+
+	return 0;
+}
+
+static int
+csio_hw_validate_caps(struct csio_hw *hw, struct csio_mb *mbp)
+{
+	struct fw_caps_config_cmd *rsp = (struct fw_caps_config_cmd *)mbp->mb;
+	uint16_t caps;
+
+	caps = ntohs(rsp->fcoecaps);
+
+	if (!(caps & FW_CAPS_CONFIG_FCOE_INITIATOR)) {
+		csio_err(hw, "No FCoE Initiator capability in the firmware.\n");
+		return -EINVAL;
+	}
+
+	if (!(caps & FW_CAPS_CONFIG_FCOE_CTRL_OFLD)) {
+		csio_err(hw, "No FCoE Control Offload capability\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ *	csio_hw_fw_halt - issue a reset/halt to FW and put uP into RESET
+ *	@hw: the HW module
+ *	@mbox: mailbox to use for the FW RESET command (if desired)
+ *	@force: force uP into RESET even if FW RESET command fails
+ *
+ *	Issues a RESET command to firmware (if desired) with a HALT indication
+ *	and then puts the microprocessor into RESET state.  The RESET command
+ *	will only be issued if a legitimate mailbox is provided (mbox <=
+ *	PCIE_FW_MASTER_MASK).
+ *
+ *	This is generally used in order for the host to safely manipulate the
+ *	adapter without fear of conflicting with whatever the firmware might
+ *	be doing.  The only way out of this state is to RESTART the firmware
+ *	...
+ */
+static int
+csio_hw_fw_halt(struct csio_hw *hw, uint32_t mbox, int32_t force)
+{
+	enum fw_retval retval = 0;
+
+	/*
+	 * If a legitimate mailbox is provided, issue a RESET command
+	 * with a HALT indication.
+	 */
+	if (mbox <= PCIE_FW_MASTER_MASK) {
+		struct csio_mb	*mbp;
+
+		mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+		if (!mbp) {
+			CSIO_INC_STATS(hw, n_err_nomem);
+			return -ENOMEM;
+		}
+
+		csio_mb_reset(hw, mbp, CSIO_MB_DEFAULT_TMO,
+			      PIORSTMODE | PIORST, FW_RESET_CMD_HALT(1),
+			      NULL);
+
+		if (csio_mb_issue(hw, mbp)) {
+			csio_err(hw, "Issue of RESET command failed!\n");
+			mempool_free(mbp, hw->mb_mempool);
+			return -EINVAL;
+		}
+
+		retval = csio_mb_fw_retval(mbp);
+		mempool_free(mbp, hw->mb_mempool);
+	}
+
+	/*
+	 * Normally we won't complete the operation if the firmware RESET
+	 * command fails but if our caller insists we'll go ahead and put the
+	 * uP into RESET.  This can be useful if the firmware is hung or even
+	 * missing ...  We'll have to take the risk of putting the uP into
+	 * RESET without the cooperation of firmware in that case.
+	 *
+	 * We also force the firmware's HALT flag to be on in case we bypassed
+	 * the firmware RESET command above or we're dealing with old firmware
+	 * which doesn't have the HALT capability.  This will serve as a flag
+	 * for the incoming firmware to know that it's coming out of a HALT
+	 * rather than a RESET ... if it's new enough to understand that ...
+	 */
+	if (retval == 0 || force) {
+		csio_set_reg_field(hw, CIM_BOOT_CFG, UPCRST, UPCRST);
+		csio_set_reg_field(hw, PCIE_FW, PCIE_FW_HALT, PCIE_FW_HALT);
+	}
+
+	/*
+	 * And we always return the result of the firmware RESET command
+	 * even when we force the uP into RESET ...
+	 */
+	return retval ? -EINVAL : 0;
+}
+
+/*
+ *	csio_hw_fw_restart - restart the firmware by taking the uP out of RESET
+ *	@hw: the HW module
+ *	@reset: if we want to do a RESET to restart things
+ *
+ *	Restart firmware previously halted by csio_hw_fw_halt().  On successful
+ *	return the previous PF Master remains as the new PF Master and there
+ *	is no need to issue a new HELLO command, etc.
+ *
+ *	We do this in two ways:
+ *
+ *	 1. If we're dealing with newer firmware we'll simply want to take
+ *	    the chip's microprocessor out of RESET.  This will cause the
+ *	    firmware to start up from its start vector.  And then we'll loop
+ *	    until the firmware indicates it's started again (PCIE_FW.HALT
+ *	    reset to 0) or we timeout.
+ *
+ *	 2. If we're dealing with older firmware then we'll need to RESET
+ *	    the chip since older firmware won't recognize the PCIE_FW.HALT
+ *	    flag and automatically RESET itself on startup.
+ */
+static int
+csio_hw_fw_restart(struct csio_hw *hw, uint32_t mbox, int32_t reset)
+{
+	if (reset) {
+		/*
+		 * Since we're directing the RESET instead of the firmware
+		 * doing it automatically, we need to clear the PCIE_FW.HALT
+		 * bit.
+		 */
+		csio_set_reg_field(hw, PCIE_FW, PCIE_FW_HALT, 0);
+
+		/*
+		 * If we've been given a valid mailbox, first try to get the
+		 * firmware to do the RESET.  If that works, great and we can
+		 * return success.  Otherwise, if we haven't been given a
+		 * valid mailbox or the RESET command failed, fall back to
+		 * hitting the chip with a hammer.
+		 */
+		if (mbox <= PCIE_FW_MASTER_MASK) {
+			csio_set_reg_field(hw, CIM_BOOT_CFG, UPCRST, 0);
+			msleep(100);
+			if (csio_do_reset(hw, true) == 0)
+				return 0;
+		}
+
+		csio_wr_reg32(hw, PIORSTMODE | PIORST, PL_RST);
+		msleep(2000);
+	} else {
+		int ms;
+
+		csio_set_reg_field(hw, CIM_BOOT_CFG, UPCRST, 0);
+		for (ms = 0; ms < FW_CMD_MAX_TIMEOUT; ) {
+			if (!(csio_rd_reg32(hw, PCIE_FW) & PCIE_FW_HALT))
+				return 0;
+			msleep(100);
+			ms += 100;
+		}
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+/*
+ *	csio_hw_fw_upgrade - perform all of the steps necessary to upgrade FW
+ *	@hw: the HW module
+ *	@mbox: mailbox to use for the FW RESET command (if desired)
+ *	@fw_data: the firmware image to write
+ *	@size: image size
+ *	@force: force upgrade even if firmware doesn't cooperate
+ *
+ *	Perform all of the steps necessary for upgrading an adapter's
+ *	firmware image.  Normally this requires the cooperation of the
+ *	existing firmware in order to halt all existing activities
+ *	but if an invalid mailbox token is passed in we skip that step
+ *	(though we'll still put the adapter microprocessor into RESET in
+ *	that case).
+ *
+ *	On successful return the new firmware will have been loaded and
+ *	the adapter will have been fully RESET losing all previous setup
+ *	state.  On unsuccessful return the adapter may be completely hosed ...
+ *	positive errno indicates that the adapter is ~probably~ intact, a
+ *	negative errno indicates that things are looking bad ...
+ */
+static int
+csio_hw_fw_upgrade(struct csio_hw *hw, uint32_t mbox,
+		  const u8 *fw_data, uint32_t size, int32_t force)
+{
+	const struct fw_hdr *fw_hdr = (const struct fw_hdr *)fw_data;
+	int reset, ret;
+
+	ret = csio_hw_fw_halt(hw, mbox, force);
+	if (ret != 0 && !force)
+		return ret;
+
+	ret = csio_hw_fw_dload(hw, (uint8_t *) fw_data, size);
+	if (ret != 0)
+		return ret;
+
+	/*
+	 * Older versions of the firmware don't understand the new
+	 * PCIE_FW.HALT flag and so won't know to perform a RESET when they
+	 * restart.  So for newly loaded older firmware we'll have to do the
+	 * RESET for it so it starts up on a clean slate.  We can tell if
+	 * the newly loaded firmware will handle this right by checking
+	 * its header flags to see if it advertises the capability.
+	 */
+	reset = ((ntohl(fw_hdr->flags) & FW_HDR_FLAGS_RESET_HALT) == 0);
+	return csio_hw_fw_restart(hw, mbox, reset);
+}
+
+
+/*
+ *	csio_hw_fw_config_file - setup an adapter via a Configuration File
+ *	@hw: the HW module
+ *	@mbox: mailbox to use for the FW command
+ *	@mtype: the memory type where the Configuration File is located
+ *	@maddr: the memory address where the Configuration File is located
+ *	@finiver: return value for CF [fini] version
+ *	@finicsum: return value for CF [fini] checksum
+ *	@cfcsum: return value for CF computed checksum
+ *
+ *	Issue a command to get the firmware to process the Configuration
+ *	File located at the specified mtype/maddress.  If the Configuration
+ *	File is processed successfully and return value pointers are
+ *	provided, the Configuration File "[fini] section version and
+ *	checksum values will be returned along with the computed checksum.
+ *	It's up to the caller to decide how it wants to respond to the
+ *	checksums not matching but it recommended that a prominant warning
+ *	be emitted in order to help people rapidly identify changed or
+ *	corrupted Configuration Files.
+ *
+ *	Also note that it's possible to modify things like "niccaps",
+ *	"toecaps",etc. between processing the Configuration File and telling
+ *	the firmware to use the new configuration.  Callers which want to
+ *	do this will need to "hand-roll" their own CAPS_CONFIGS commands for
+ *	Configuration Files if they want to do this.
+ */
+static int
+csio_hw_fw_config_file(struct csio_hw *hw,
+		      unsigned int mtype, unsigned int maddr,
+		      uint32_t *finiver, uint32_t *finicsum, uint32_t *cfcsum)
+{
+	struct csio_mb	*mbp;
+	struct fw_caps_config_cmd *caps_cmd;
+	int rv = -EINVAL;
+	enum fw_retval ret;
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		return -ENOMEM;
+	}
+	/*
+	 * Tell the firmware to process the indicated Configuration File.
+	 * If there are no errors and the caller has provided return value
+	 * pointers for the [fini] section version, checksum and computed
+	 * checksum, pass those back to the caller.
+	 */
+	caps_cmd = (struct fw_caps_config_cmd *)(mbp->mb);
+	CSIO_INIT_MBP(mbp, caps_cmd, CSIO_MB_DEFAULT_TMO, hw, NULL, 1);
+	caps_cmd->op_to_write =
+		htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
+		      FW_CMD_REQUEST |
+		      FW_CMD_READ);
+	caps_cmd->cfvalid_to_len16 =
+		htonl(FW_CAPS_CONFIG_CMD_CFVALID |
+		      FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) |
+		      FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(maddr >> 16) |
+		      FW_LEN16(*caps_cmd));
+
+	if (csio_mb_issue(hw, mbp)) {
+		csio_err(hw, "Issue of FW_CAPS_CONFIG_CMD failed!\n");
+		goto out;
+	}
+
+	ret = csio_mb_fw_retval(mbp);
+	if (ret != FW_SUCCESS) {
+		csio_dbg(hw, "FW_CAPS_CONFIG_CMD returned %d!\n", rv);
+		goto out;
+	}
+
+	if (finiver)
+		*finiver = ntohl(caps_cmd->finiver);
+	if (finicsum)
+		*finicsum = ntohl(caps_cmd->finicsum);
+	if (cfcsum)
+		*cfcsum = ntohl(caps_cmd->cfcsum);
+
+	/* Validate device capabilities */
+	if (csio_hw_validate_caps(hw, mbp)) {
+		rv = -ENOENT;
+		goto out;
+	}
+
+	/*
+	 * And now tell the firmware to use the configuration we just loaded.
+	 */
+	caps_cmd->op_to_write =
+		htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
+		      FW_CMD_REQUEST |
+		      FW_CMD_WRITE);
+	caps_cmd->cfvalid_to_len16 = htonl(FW_LEN16(*caps_cmd));
+
+	if (csio_mb_issue(hw, mbp)) {
+		csio_err(hw, "Issue of FW_CAPS_CONFIG_CMD failed!\n");
+		goto out;
+	}
+
+	ret = csio_mb_fw_retval(mbp);
+	if (ret != FW_SUCCESS) {
+		csio_dbg(hw, "FW_CAPS_CONFIG_CMD returned %d!\n", rv);
+		goto out;
+	}
+
+	rv = 0;
+out:
+	mempool_free(mbp, hw->mb_mempool);
+	return rv;
+}
+
+/*
+ * csio_get_device_params - Get device parameters.
+ * @hw: HW module
+ *
+ */
+static int
+csio_get_device_params(struct csio_hw *hw)
+{
+	struct csio_wrm *wrm	= csio_hw_to_wrm(hw);
+	struct csio_mb	*mbp;
+	enum fw_retval retval;
+	u32 param[6];
+	int i, j = 0;
+
+	/* Initialize portids to -1 */
+	for (i = 0; i < CSIO_MAX_PPORTS; i++)
+		hw->pport[i].portid = -1;
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		return -ENOMEM;
+	}
+
+	/* Get port vec information. */
+	param[0] = FW_PARAM_DEV(PORTVEC);
+
+	/* Get Core clock. */
+	param[1] = FW_PARAM_DEV(CCLK);
+
+	/* Get EQ id start and end. */
+	param[2] = FW_PARAM_PFVF(EQ_START);
+	param[3] = FW_PARAM_PFVF(EQ_END);
+
+	/* Get IQ id start and end. */
+	param[4] = FW_PARAM_PFVF(IQFLINT_START);
+	param[5] = FW_PARAM_PFVF(IQFLINT_END);
+
+	csio_mb_params(hw, mbp, CSIO_MB_DEFAULT_TMO, hw->pfn, 0,
+		       ARRAY_SIZE(param), param, NULL, false, NULL);
+	if (csio_mb_issue(hw, mbp)) {
+		csio_err(hw, "Issue of FW_PARAMS_CMD(read) failed!\n");
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	csio_mb_process_read_params_rsp(hw, mbp, &retval,
+			ARRAY_SIZE(param), param);
+	if (retval != FW_SUCCESS) {
+		csio_err(hw, "FW_PARAMS_CMD(read) failed with ret:0x%x!\n",
+				retval);
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	/* cache the information. */
+	hw->port_vec = param[0];
+	hw->vpd.cclk = param[1];
+	wrm->fw_eq_start = param[2];
+	wrm->fw_iq_start = param[4];
+
+	/* Using FW configured max iqs & eqs */
+	if ((hw->flags & CSIO_HWF_USING_SOFT_PARAMS) ||
+		!csio_is_hw_master(hw)) {
+		hw->cfg_niq = param[5] - param[4] + 1;
+		hw->cfg_neq = param[3] - param[2] + 1;
+		csio_dbg(hw, "Using fwconfig max niqs %d neqs %d\n",
+			hw->cfg_niq, hw->cfg_neq);
+	}
+
+	hw->port_vec &= csio_port_mask;
+
+	hw->num_pports	= hweight32(hw->port_vec);
+
+	csio_dbg(hw, "Port vector: 0x%x, #ports: %d\n",
+		    hw->port_vec, hw->num_pports);
+
+	for (i = 0; i < hw->num_pports; i++) {
+		while ((hw->port_vec & (1 << j)) == 0)
+			j++;
+		hw->pport[i].portid = j++;
+		csio_dbg(hw, "Found Port:%d\n", hw->pport[i].portid);
+	}
+	mempool_free(mbp, hw->mb_mempool);
+
+	return 0;
+}
+
+
+/*
+ * csio_config_device_caps - Get and set device capabilities.
+ * @hw: HW module
+ *
+ */
+static int
+csio_config_device_caps(struct csio_hw *hw)
+{
+	struct csio_mb	*mbp;
+	enum fw_retval retval;
+	int rv = -EINVAL;
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		return -ENOMEM;
+	}
+
+	/* Get device capabilities */
+	csio_mb_caps_config(hw, mbp, CSIO_MB_DEFAULT_TMO, 0, 0, 0, 0, NULL);
+
+	if (csio_mb_issue(hw, mbp)) {
+		csio_err(hw, "Issue of FW_CAPS_CONFIG_CMD(r) failed!\n");
+		goto out;
+	}
+
+	retval = csio_mb_fw_retval(mbp);
+	if (retval != FW_SUCCESS) {
+		csio_err(hw, "FW_CAPS_CONFIG_CMD(r) returned %d!\n", retval);
+		goto out;
+	}
+
+	/* Validate device capabilities */
+	if (csio_hw_validate_caps(hw, mbp))
+		goto out;
+
+	/* Don't config device capabilities if already configured */
+	if (hw->fw_state == CSIO_DEV_STATE_INIT) {
+		rv = 0;
+		goto out;
+	}
+
+	/* Write back desired device capabilities */
+	csio_mb_caps_config(hw, mbp, CSIO_MB_DEFAULT_TMO, true, true,
+			    false, true, NULL);
+
+	if (csio_mb_issue(hw, mbp)) {
+		csio_err(hw, "Issue of FW_CAPS_CONFIG_CMD(w) failed!\n");
+		goto out;
+	}
+
+	retval = csio_mb_fw_retval(mbp);
+	if (retval != FW_SUCCESS) {
+		csio_err(hw, "FW_CAPS_CONFIG_CMD(w) returned %d!\n", retval);
+		goto out;
+	}
+
+	rv = 0;
+out:
+	mempool_free(mbp, hw->mb_mempool);
+	return rv;
+}
+
+static int
+csio_config_global_rss(struct csio_hw *hw)
+{
+	struct csio_mb	*mbp;
+	enum fw_retval retval;
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		return -ENOMEM;
+	}
+
+	csio_rss_glb_config(hw, mbp, CSIO_MB_DEFAULT_TMO,
+			    FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL,
+			    FW_RSS_GLB_CONFIG_CMD_TNLMAPEN |
+			    FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ |
+			    FW_RSS_GLB_CONFIG_CMD_TNLALLLKP,
+			    NULL);
+
+	if (csio_mb_issue(hw, mbp)) {
+		csio_err(hw, "Issue of FW_RSS_GLB_CONFIG_CMD failed!\n");
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	retval = csio_mb_fw_retval(mbp);
+	if (retval != FW_SUCCESS) {
+		csio_err(hw, "FW_RSS_GLB_CONFIG_CMD returned 0x%x!\n", retval);
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	mempool_free(mbp, hw->mb_mempool);
+
+	return 0;
+}
+
+/*
+ * csio_config_pfvf - Configure Physical/Virtual functions settings.
+ * @hw: HW module
+ *
+ */
+static int
+csio_config_pfvf(struct csio_hw *hw)
+{
+	struct csio_mb	*mbp;
+	enum fw_retval retval;
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		return -ENOMEM;
+	}
+
+	/*
+	 * For now, allow all PFs to access to all ports using a pmask
+	 * value of 0xF (M_FW_PFVF_CMD_PMASK). Once we have VFs, we will
+	 * need to provide access based on some rule.
+	 */
+	csio_mb_pfvf(hw, mbp, CSIO_MB_DEFAULT_TMO, hw->pfn, 0, CSIO_NEQ,
+		     CSIO_NETH_CTRL, CSIO_NIQ_FLINT, 0, 0, CSIO_NVI, CSIO_CMASK,
+		     CSIO_PMASK, CSIO_NEXACTF, CSIO_R_CAPS, CSIO_WX_CAPS, NULL);
+
+	if (csio_mb_issue(hw, mbp)) {
+		csio_err(hw, "Issue of FW_PFVF_CMD failed!\n");
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	retval = csio_mb_fw_retval(mbp);
+	if (retval != FW_SUCCESS) {
+		csio_err(hw, "FW_PFVF_CMD returned 0x%x!\n", retval);
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	mempool_free(mbp, hw->mb_mempool);
+
+	return 0;
+}
+
+/*
+ * csio_enable_ports - Bring up all available ports.
+ * @hw: HW module.
+ *
+ */
+static int
+csio_enable_ports(struct csio_hw *hw)
+{
+	struct csio_mb  *mbp;
+	enum fw_retval retval;
+	uint8_t portid;
+	int i;
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < hw->num_pports; i++) {
+		portid = hw->pport[i].portid;
+
+		/* Read PORT information */
+		csio_mb_port(hw, mbp, CSIO_MB_DEFAULT_TMO, portid,
+			     false, 0, 0, NULL);
+
+		if (csio_mb_issue(hw, mbp)) {
+			csio_err(hw, "failed to issue FW_PORT_CMD(r) port:%d\n",
+				 portid);
+			mempool_free(mbp, hw->mb_mempool);
+			return -EINVAL;
+		}
+
+		csio_mb_process_read_port_rsp(hw, mbp, &retval,
+					      &hw->pport[i].pcap);
+		if (retval != FW_SUCCESS) {
+			csio_err(hw, "FW_PORT_CMD(r) port:%d failed: 0x%x\n",
+				 portid, retval);
+			mempool_free(mbp, hw->mb_mempool);
+			return -EINVAL;
+		}
+
+		/* Write back PORT information */
+		csio_mb_port(hw, mbp, CSIO_MB_DEFAULT_TMO, portid, true,
+			     (PAUSE_RX | PAUSE_TX), hw->pport[i].pcap, NULL);
+
+		if (csio_mb_issue(hw, mbp)) {
+			csio_err(hw, "failed to issue FW_PORT_CMD(w) port:%d\n",
+				 portid);
+			mempool_free(mbp, hw->mb_mempool);
+			return -EINVAL;
+		}
+
+		retval = csio_mb_fw_retval(mbp);
+		if (retval != FW_SUCCESS) {
+			csio_err(hw, "FW_PORT_CMD(w) port:%d failed :0x%x\n",
+				 portid, retval);
+			mempool_free(mbp, hw->mb_mempool);
+			return -EINVAL;
+		}
+
+	} /* For all ports */
+
+	mempool_free(mbp, hw->mb_mempool);
+
+	return 0;
+}
+
+/*
+ * csio_get_fcoe_resinfo - Read fcoe fw resource info.
+ * @hw: HW module
+ * Issued with lock held.
+ */
+static int
+csio_get_fcoe_resinfo(struct csio_hw *hw)
+{
+	struct csio_fcoe_res_info *res_info = &hw->fres_info;
+	struct fw_fcoe_res_info_cmd *rsp;
+	struct csio_mb  *mbp;
+	enum fw_retval retval;
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		return -ENOMEM;
+	}
+
+	/* Get FCoE FW resource information */
+	csio_fcoe_read_res_info_init_mb(hw, mbp, CSIO_MB_DEFAULT_TMO, NULL);
+
+	if (csio_mb_issue(hw, mbp)) {
+		csio_err(hw, "failed to issue FW_FCOE_RES_INFO_CMD\n");
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	rsp = (struct fw_fcoe_res_info_cmd *)(mbp->mb);
+	retval = FW_CMD_RETVAL_GET(ntohl(rsp->retval_len16));
+	if (retval != FW_SUCCESS) {
+		csio_err(hw, "FW_FCOE_RES_INFO_CMD failed with ret x%x\n",
+			 retval);
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	res_info->e_d_tov = ntohs(rsp->e_d_tov);
+	res_info->r_a_tov_seq = ntohs(rsp->r_a_tov_seq);
+	res_info->r_a_tov_els = ntohs(rsp->r_a_tov_els);
+	res_info->r_r_tov = ntohs(rsp->r_r_tov);
+	res_info->max_xchgs = ntohl(rsp->max_xchgs);
+	res_info->max_ssns = ntohl(rsp->max_ssns);
+	res_info->used_xchgs = ntohl(rsp->used_xchgs);
+	res_info->used_ssns = ntohl(rsp->used_ssns);
+	res_info->max_fcfs = ntohl(rsp->max_fcfs);
+	res_info->max_vnps = ntohl(rsp->max_vnps);
+	res_info->used_fcfs = ntohl(rsp->used_fcfs);
+	res_info->used_vnps = ntohl(rsp->used_vnps);
+
+	csio_dbg(hw, "max ssns:%d max xchgs:%d\n", res_info->max_ssns,
+						  res_info->max_xchgs);
+	mempool_free(mbp, hw->mb_mempool);
+
+	return 0;
+}
+
+static int
+csio_hw_check_fwconfig(struct csio_hw *hw, u32 *param)
+{
+	struct csio_mb	*mbp;
+	enum fw_retval retval;
+	u32 _param[1];
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		return -ENOMEM;
+	}
+
+	/*
+	 * Find out whether we're dealing with a version of
+	 * the firmware which has configuration file support.
+	 */
+	_param[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
+		     FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CF));
+
+	csio_mb_params(hw, mbp, CSIO_MB_DEFAULT_TMO, hw->pfn, 0,
+		       ARRAY_SIZE(_param), _param, NULL, false, NULL);
+	if (csio_mb_issue(hw, mbp)) {
+		csio_err(hw, "Issue of FW_PARAMS_CMD(read) failed!\n");
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	csio_mb_process_read_params_rsp(hw, mbp, &retval,
+			ARRAY_SIZE(_param), _param);
+	if (retval != FW_SUCCESS) {
+		csio_err(hw, "FW_PARAMS_CMD(read) failed with ret:0x%x!\n",
+				retval);
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	mempool_free(mbp, hw->mb_mempool);
+	*param = _param[0];
+
+	return 0;
+}
+
+static int
+csio_hw_flash_config(struct csio_hw *hw, u32 *fw_cfg_param, char *path)
+{
+	int ret = 0;
+	const struct firmware *cf;
+	struct pci_dev *pci_dev = hw->pdev;
+	struct device *dev = &pci_dev->dev;
+
+	unsigned int mtype = 0, maddr = 0;
+	uint32_t *cfg_data;
+	int value_to_add = 0;
+
+	if (request_firmware(&cf, CSIO_CF_FNAME, dev) < 0) {
+		csio_err(hw, "could not find config file " CSIO_CF_FNAME
+			 ",err: %d\n", ret);
+		return -ENOENT;
+	}
+
+	if (cf->size%4 != 0)
+		value_to_add = 4 - (cf->size % 4);
+
+	cfg_data = kzalloc(cf->size+value_to_add, GFP_KERNEL);
+	if (cfg_data == NULL)
+		return -ENOMEM;
+
+	memcpy((void *)cfg_data, (const void *)cf->data, cf->size);
+
+	if (csio_hw_check_fwconfig(hw, fw_cfg_param) != 0)
+		return -EINVAL;
+
+	mtype = FW_PARAMS_PARAM_Y_GET(*fw_cfg_param);
+	maddr = FW_PARAMS_PARAM_Z_GET(*fw_cfg_param) << 16;
+
+	ret = csio_memory_write(hw, mtype, maddr,
+				cf->size + value_to_add, cfg_data);
+	if (ret == 0) {
+		csio_info(hw, "config file upgraded to " CSIO_CF_FNAME "\n");
+		strncpy(path, "/lib/firmware/" CSIO_CF_FNAME, 64);
+	}
+
+	kfree(cfg_data);
+	release_firmware(cf);
+
+	return ret;
+}
+
+/*
+ * HW initialization: contact FW, obtain config, perform basic init.
+ *
+ * If the firmware we're dealing with has Configuration File support, then
+ * we use that to perform all configuration -- either using the configuration
+ * file stored in flash on the adapter or using a filesystem-local file
+ * if available.
+ *
+ * If we don't have configuration file support in the firmware, then we'll
+ * have to set things up the old fashioned way with hard-coded register
+ * writes and firmware commands ...
+ */
+
+/*
+ * Attempt to initialize the HW via a Firmware Configuration File.
+ */
+static int
+csio_hw_use_fwconfig(struct csio_hw *hw, int reset, u32 *fw_cfg_param)
+{
+	unsigned int mtype, maddr;
+	int rv;
+	uint32_t finiver, finicsum, cfcsum;
+	int using_flash;
+	char path[64];
+
+	/*
+	 * Reset device if necessary
+	 */
+	if (reset) {
+		rv = csio_do_reset(hw, true);
+		if (rv != 0)
+			goto bye;
+	}
+
+	/*
+	 * If we have a configuration file in host ,
+	 * then use that.  Otherwise, use the configuration file stored
+	 * in the HW flash ...
+	 */
+	spin_unlock_irq(&hw->lock);
+	rv = csio_hw_flash_config(hw, fw_cfg_param, path);
+	spin_lock_irq(&hw->lock);
+	if (rv != 0) {
+		if (rv == -ENOENT) {
+			/*
+			 * config file was not found. Use default
+			 * config file from flash.
+			 */
+			mtype = FW_MEMTYPE_CF_FLASH;
+			maddr = csio_hw_flash_cfg_addr(hw);
+			using_flash = 1;
+		} else {
+			/*
+			 * we revert back to the hardwired config if
+			 * flashing failed.
+			 */
+			goto bye;
+		}
+	} else {
+		mtype = FW_PARAMS_PARAM_Y_GET(*fw_cfg_param);
+		maddr = FW_PARAMS_PARAM_Z_GET(*fw_cfg_param) << 16;
+		using_flash = 0;
+	}
+
+	hw->cfg_store = (uint8_t)mtype;
+
+	/*
+	 * Issue a Capability Configuration command to the firmware to get it
+	 * to parse the Configuration File.
+	 */
+	rv = csio_hw_fw_config_file(hw, mtype, maddr, &finiver,
+		&finicsum, &cfcsum);
+	if (rv != 0)
+		goto bye;
+
+	hw->cfg_finiver		= finiver;
+	hw->cfg_finicsum	= finicsum;
+	hw->cfg_cfcsum		= cfcsum;
+	hw->cfg_csum_status	= true;
+
+	if (finicsum != cfcsum) {
+		csio_warn(hw,
+		      "Config File checksum mismatch: csum=%#x, computed=%#x\n",
+		      finicsum, cfcsum);
+
+		hw->cfg_csum_status = false;
+	}
+
+	/*
+	 * Note that we're operating with parameters
+	 * not supplied by the driver, rather than from hard-wired
+	 * initialization constants buried in the driver.
+	 */
+	hw->flags |= CSIO_HWF_USING_SOFT_PARAMS;
+
+	/* device parameters */
+	rv = csio_get_device_params(hw);
+	if (rv != 0)
+		goto bye;
+
+	/* Configure SGE */
+	csio_wr_sge_init(hw);
+
+	/*
+	 * And finally tell the firmware to initialize itself using the
+	 * parameters from the Configuration File.
+	 */
+	/* Post event to notify completion of configuration */
+	csio_post_event(&hw->sm, CSIO_HWE_INIT);
+
+	csio_info(hw,
+	 "Firmware Configuration File %s, version %#x, computed checksum %#x\n",
+		  (using_flash ? "in device FLASH" : path), finiver, cfcsum);
+
+	return 0;
+
+	/*
+	 * Something bad happened.  Return the error ...
+	 */
+bye:
+	hw->flags &= ~CSIO_HWF_USING_SOFT_PARAMS;
+	csio_dbg(hw, "Configuration file error %d\n", rv);
+	return rv;
+}
+
+/*
+ * Attempt to initialize the adapter via hard-coded, driver supplied
+ * parameters ...
+ */
+static int
+csio_hw_no_fwconfig(struct csio_hw *hw, int reset)
+{
+	int		rv;
+	/*
+	 * Reset device if necessary
+	 */
+	if (reset) {
+		rv = csio_do_reset(hw, true);
+		if (rv != 0)
+			goto out;
+	}
+
+	/* Get and set device capabilities */
+	rv = csio_config_device_caps(hw);
+	if (rv != 0)
+		goto out;
+
+	/* Config Global RSS command */
+	rv = csio_config_global_rss(hw);
+	if (rv != 0)
+		goto out;
+
+	/* Configure PF/VF capabilities of device */
+	rv = csio_config_pfvf(hw);
+	if (rv != 0)
+		goto out;
+
+	/* device parameters */
+	rv = csio_get_device_params(hw);
+	if (rv != 0)
+		goto out;
+
+	/* Configure SGE */
+	csio_wr_sge_init(hw);
+
+	/* Post event to notify completion of configuration */
+	csio_post_event(&hw->sm, CSIO_HWE_INIT);
+
+out:
+	return rv;
+}
+
+/*
+ * Returns -EINVAL if attempts to flash the firmware failed
+ * else returns 0,
+ * if flashing was not attempted because the card had the
+ * latest firmware ECANCELED is returned
+ */
+static int
+csio_hw_flash_fw(struct csio_hw *hw)
+{
+	int ret = -ECANCELED;
+	const struct firmware *fw;
+	const struct fw_hdr *hdr;
+	u32 fw_ver;
+	struct pci_dev *pci_dev = hw->pdev;
+	struct device *dev = &pci_dev->dev ;
+
+	if (request_firmware(&fw, CSIO_FW_FNAME, dev) < 0) {
+		csio_err(hw, "could not find firmware image " CSIO_FW_FNAME
+		",err: %d\n", ret);
+		return -EINVAL;
+	}
+
+	hdr = (const struct fw_hdr *)fw->data;
+	fw_ver = ntohl(hdr->fw_ver);
+	if (FW_HDR_FW_VER_MAJOR_GET(fw_ver) != FW_VERSION_MAJOR)
+		return -EINVAL;      /* wrong major version, won't do */
+
+	/*
+	 * If the flash FW is unusable or we found something newer, load it.
+	 */
+	if (FW_HDR_FW_VER_MAJOR_GET(hw->fwrev) != FW_VERSION_MAJOR ||
+	    fw_ver > hw->fwrev) {
+		ret = csio_hw_fw_upgrade(hw, hw->pfn, fw->data, fw->size,
+				    /*force=*/false);
+		if (!ret)
+			csio_info(hw, "firmware upgraded to version %pI4 from "
+				  CSIO_FW_FNAME "\n", &hdr->fw_ver);
+		else
+			csio_err(hw, "firmware upgrade failed! err=%d\n", ret);
+	}
+
+	release_firmware(fw);
+
+	return ret;
+}
+
+
+/*
+ * csio_hw_configure - Configure HW
+ * @hw - HW module
+ *
+ */
+static void
+csio_hw_configure(struct csio_hw *hw)
+{
+	int reset = 1;
+	int rv;
+	u32 param[1];
+
+	rv = csio_hw_dev_ready(hw);
+	if (rv != 0) {
+		CSIO_INC_STATS(hw, n_err_fatal);
+		csio_post_event(&hw->sm, CSIO_HWE_FATAL);
+		goto out;
+	}
+
+	/* HW version */
+	hw->chip_ver = (char)csio_rd_reg32(hw, PL_REV);
+
+	/* Needed for FW download */
+	rv = csio_hw_get_flash_params(hw);
+	if (rv != 0) {
+		csio_err(hw, "Failed to get serial flash params rv:%d\n", rv);
+		csio_post_event(&hw->sm, CSIO_HWE_FATAL);
+		goto out;
+	}
+
+	/* Set pci completion timeout value to 4 seconds. */
+	csio_set_pcie_completion_timeout(hw, 0xd);
+
+	csio_hw_set_mem_win(hw);
+
+	rv = csio_hw_get_fw_version(hw, &hw->fwrev);
+	if (rv != 0)
+		goto out;
+
+	csio_hw_print_fw_version(hw, "Firmware revision");
+
+	rv = csio_do_hello(hw, &hw->fw_state);
+	if (rv != 0) {
+		CSIO_INC_STATS(hw, n_err_fatal);
+		csio_post_event(&hw->sm, CSIO_HWE_FATAL);
+		goto out;
+	}
+
+	/* Read vpd */
+	rv = csio_hw_get_vpd_params(hw, &hw->vpd);
+	if (rv != 0)
+		goto out;
+
+	if (csio_is_hw_master(hw) && hw->fw_state != CSIO_DEV_STATE_INIT) {
+		rv = csio_hw_check_fw_version(hw);
+		if (rv == -EINVAL) {
+
+			/* Do firmware update */
+			spin_unlock_irq(&hw->lock);
+			rv = csio_hw_flash_fw(hw);
+			spin_lock_irq(&hw->lock);
+
+			if (rv == 0) {
+				reset = 0;
+				/*
+				 * Note that the chip was reset as part of the
+				 * firmware upgrade so we don't reset it again
+				 * below and grab the new firmware version.
+				 */
+				rv = csio_hw_check_fw_version(hw);
+			}
+		}
+		/*
+		 * If the firmware doesn't support Configuration
+		 * Files, use the old Driver-based, hard-wired
+		 * initialization.  Otherwise, try using the
+		 * Configuration File support and fall back to the
+		 * Driver-based initialization if there's no
+		 * Configuration File found.
+		 */
+		if (csio_hw_check_fwconfig(hw, param) == 0) {
+			rv = csio_hw_use_fwconfig(hw, reset, param);
+			if (rv == -ENOENT)
+				goto out;
+			if (rv != 0) {
+				csio_info(hw,
+				    "No Configuration File present "
+				    "on adapter.  Using hard-wired "
+				    "configuration parameters.\n");
+				rv = csio_hw_no_fwconfig(hw, reset);
+			}
+		} else {
+			rv = csio_hw_no_fwconfig(hw, reset);
+		}
+
+		if (rv != 0)
+			goto out;
+
+	} else {
+		if (hw->fw_state == CSIO_DEV_STATE_INIT) {
+
+			/* device parameters */
+			rv = csio_get_device_params(hw);
+			if (rv != 0)
+				goto out;
+
+			/* Get device capabilities */
+			rv = csio_config_device_caps(hw);
+			if (rv != 0)
+				goto out;
+
+			/* Configure SGE */
+			csio_wr_sge_init(hw);
+
+			/* Post event to notify completion of configuration */
+			csio_post_event(&hw->sm, CSIO_HWE_INIT);
+			goto out;
+		}
+	} /* if not master */
+
+out:
+	return;
+}
+
+/*
+ * csio_hw_initialize - Initialize HW
+ * @hw - HW module
+ *
+ */
+static void
+csio_hw_initialize(struct csio_hw *hw)
+{
+	struct csio_mb	*mbp;
+	enum fw_retval retval;
+	int rv;
+	int i;
+
+	if (csio_is_hw_master(hw) && hw->fw_state != CSIO_DEV_STATE_INIT) {
+		mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+		if (!mbp)
+			goto out;
+
+		csio_mb_initialize(hw, mbp, CSIO_MB_DEFAULT_TMO, NULL);
+
+		if (csio_mb_issue(hw, mbp)) {
+			csio_err(hw, "Issue of FW_INITIALIZE_CMD failed!\n");
+			goto free_and_out;
+		}
+
+		retval = csio_mb_fw_retval(mbp);
+		if (retval != FW_SUCCESS) {
+			csio_err(hw, "FW_INITIALIZE_CMD returned 0x%x!\n",
+				 retval);
+			goto free_and_out;
+		}
+
+		mempool_free(mbp, hw->mb_mempool);
+	}
+
+	rv = csio_get_fcoe_resinfo(hw);
+	if (rv != 0) {
+		csio_err(hw, "Failed to read fcoe resource info: %d\n", rv);
+		goto out;
+	}
+
+	spin_unlock_irq(&hw->lock);
+	rv = csio_config_queues(hw);
+	spin_lock_irq(&hw->lock);
+
+	if (rv != 0) {
+		csio_err(hw, "Config of queues failed!: %d\n", rv);
+		goto out;
+	}
+
+	for (i = 0; i < hw->num_pports; i++)
+		hw->pport[i].mod_type = FW_PORT_MOD_TYPE_NA;
+
+	if (csio_is_hw_master(hw) && hw->fw_state != CSIO_DEV_STATE_INIT) {
+		rv = csio_enable_ports(hw);
+		if (rv != 0) {
+			csio_err(hw, "Failed to enable ports: %d\n", rv);
+			goto out;
+		}
+	}
+
+	csio_post_event(&hw->sm, CSIO_HWE_INIT_DONE);
+	return;
+
+free_and_out:
+	mempool_free(mbp, hw->mb_mempool);
+out:
+	return;
+}
+
+#define PF_INTR_MASK (PFSW | PFCIM)
+
+/*
+ * csio_hw_intr_enable - Enable HW interrupts
+ * @hw: Pointer to HW module.
+ *
+ * Enable interrupts in HW registers.
+ */
+static void
+csio_hw_intr_enable(struct csio_hw *hw)
+{
+	uint16_t vec = (uint16_t)csio_get_mb_intr_idx(csio_hw_to_mbm(hw));
+	uint32_t pf = SOURCEPF_GET(csio_rd_reg32(hw, PL_WHOAMI));
+	uint32_t pl = csio_rd_reg32(hw, PL_INT_ENABLE);
+
+	/*
+	 * Set aivec for MSI/MSIX. PCIE_PF_CFG.INTXType is set up
+	 * by FW, so do nothing for INTX.
+	 */
+	if (hw->intr_mode == CSIO_IM_MSIX)
+		csio_set_reg_field(hw, MYPF_REG(PCIE_PF_CFG),
+				   AIVEC(AIVEC_MASK), vec);
+	else if (hw->intr_mode == CSIO_IM_MSI)
+		csio_set_reg_field(hw, MYPF_REG(PCIE_PF_CFG),
+				   AIVEC(AIVEC_MASK), 0);
+
+	csio_wr_reg32(hw, PF_INTR_MASK, MYPF_REG(PL_PF_INT_ENABLE));
+
+	/* Turn on MB interrupts - this will internally flush PIO as well */
+	csio_mb_intr_enable(hw);
+
+	/* These are common registers - only a master can modify them */
+	if (csio_is_hw_master(hw)) {
+		/*
+		 * Disable the Serial FLASH interrupt, if enabled!
+		 */
+		pl &= (~SF);
+		csio_wr_reg32(hw, pl, PL_INT_ENABLE);
+
+		csio_wr_reg32(hw, ERR_CPL_EXCEED_IQE_SIZE |
+			      EGRESS_SIZE_ERR | ERR_INVALID_CIDX_INC |
+			      ERR_CPL_OPCODE_0 | ERR_DROPPED_DB |
+			      ERR_DATA_CPL_ON_HIGH_QID1 |
+			      ERR_DATA_CPL_ON_HIGH_QID0 | ERR_BAD_DB_PIDX3 |
+			      ERR_BAD_DB_PIDX2 | ERR_BAD_DB_PIDX1 |
+			      ERR_BAD_DB_PIDX0 | ERR_ING_CTXT_PRIO |
+			      ERR_EGR_CTXT_PRIO | INGRESS_SIZE_ERR,
+			      SGE_INT_ENABLE3);
+		csio_set_reg_field(hw, PL_INT_MAP0, 0, 1 << pf);
+	}
+
+	hw->flags |= CSIO_HWF_HW_INTR_ENABLED;
+
+}
+
+/*
+ * csio_hw_intr_disable - Disable HW interrupts
+ * @hw: Pointer to HW module.
+ *
+ * Turn off Mailbox and PCI_PF_CFG interrupts.
+ */
+void
+csio_hw_intr_disable(struct csio_hw *hw)
+{
+	uint32_t pf = SOURCEPF_GET(csio_rd_reg32(hw, PL_WHOAMI));
+
+	if (!(hw->flags & CSIO_HWF_HW_INTR_ENABLED))
+		return;
+
+	hw->flags &= ~CSIO_HWF_HW_INTR_ENABLED;
+
+	csio_wr_reg32(hw, 0, MYPF_REG(PL_PF_INT_ENABLE));
+	if (csio_is_hw_master(hw))
+		csio_set_reg_field(hw, PL_INT_MAP0, 1 << pf, 0);
+
+	/* Turn off MB interrupts */
+	csio_mb_intr_disable(hw);
+
+}
+
+static void
+csio_hw_fatal_err(struct csio_hw *hw)
+{
+	csio_set_reg_field(hw, SGE_CONTROL, GLOBALENABLE, 0);
+	csio_hw_intr_disable(hw);
+
+	/* Do not reset HW, we may need FW state for debugging */
+	csio_fatal(hw, "HW Fatal error encountered!\n");
+}
+
+/*****************************************************************************/
+/* START: HW SM                                                              */
+/*****************************************************************************/
+/*
+ * csio_hws_uninit - Uninit state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_uninit(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+	hw->prev_evt = hw->cur_evt;
+	hw->cur_evt = evt;
+	CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+	switch (evt) {
+	case CSIO_HWE_CFG:
+		csio_set_state(&hw->sm, csio_hws_configuring);
+		csio_hw_configure(hw);
+		break;
+
+	default:
+		CSIO_INC_STATS(hw, n_evt_unexp);
+		break;
+	}
+}
+
+/*
+ * csio_hws_configuring - Configuring state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_configuring(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+	hw->prev_evt = hw->cur_evt;
+	hw->cur_evt = evt;
+	CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+	switch (evt) {
+	case CSIO_HWE_INIT:
+		csio_set_state(&hw->sm, csio_hws_initializing);
+		csio_hw_initialize(hw);
+		break;
+
+	case CSIO_HWE_INIT_DONE:
+		csio_set_state(&hw->sm, csio_hws_ready);
+		/* Fan out event to all lnode SMs */
+		csio_notify_lnodes(hw, CSIO_LN_NOTIFY_HWREADY);
+		break;
+
+	case CSIO_HWE_FATAL:
+		csio_set_state(&hw->sm, csio_hws_uninit);
+		break;
+
+	case CSIO_HWE_PCI_REMOVE:
+		csio_do_bye(hw);
+		break;
+	default:
+		CSIO_INC_STATS(hw, n_evt_unexp);
+		break;
+	}
+}
+
+/*
+ * csio_hws_initializing - Initialiazing state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_initializing(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+	hw->prev_evt = hw->cur_evt;
+	hw->cur_evt = evt;
+	CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+	switch (evt) {
+	case CSIO_HWE_INIT_DONE:
+		csio_set_state(&hw->sm, csio_hws_ready);
+
+		/* Fan out event to all lnode SMs */
+		csio_notify_lnodes(hw, CSIO_LN_NOTIFY_HWREADY);
+
+		/* Enable interrupts */
+		csio_hw_intr_enable(hw);
+		break;
+
+	case CSIO_HWE_FATAL:
+		csio_set_state(&hw->sm, csio_hws_uninit);
+		break;
+
+	case CSIO_HWE_PCI_REMOVE:
+		csio_do_bye(hw);
+		break;
+
+	default:
+		CSIO_INC_STATS(hw, n_evt_unexp);
+		break;
+	}
+}
+
+/*
+ * csio_hws_ready - Ready state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_ready(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+	/* Remember the event */
+	hw->evtflag = evt;
+
+	hw->prev_evt = hw->cur_evt;
+	hw->cur_evt = evt;
+	CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+	switch (evt) {
+	case CSIO_HWE_HBA_RESET:
+	case CSIO_HWE_FW_DLOAD:
+	case CSIO_HWE_SUSPEND:
+	case CSIO_HWE_PCI_REMOVE:
+	case CSIO_HWE_PCIERR_DETECTED:
+		csio_set_state(&hw->sm, csio_hws_quiescing);
+		/* cleanup all outstanding cmds */
+		if (evt == CSIO_HWE_HBA_RESET ||
+		    evt == CSIO_HWE_PCIERR_DETECTED)
+			csio_scsim_cleanup_io(csio_hw_to_scsim(hw), false);
+		else
+			csio_scsim_cleanup_io(csio_hw_to_scsim(hw), true);
+
+		csio_hw_intr_disable(hw);
+		csio_hw_mbm_cleanup(hw);
+		csio_evtq_stop(hw);
+		csio_notify_lnodes(hw, CSIO_LN_NOTIFY_HWSTOP);
+		csio_evtq_flush(hw);
+		csio_mgmtm_cleanup(csio_hw_to_mgmtm(hw));
+		csio_post_event(&hw->sm, CSIO_HWE_QUIESCED);
+		break;
+
+	case CSIO_HWE_FATAL:
+		csio_set_state(&hw->sm, csio_hws_uninit);
+		break;
+
+	default:
+		CSIO_INC_STATS(hw, n_evt_unexp);
+		break;
+	}
+}
+
+/*
+ * csio_hws_quiescing - Quiescing state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_quiescing(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+	hw->prev_evt = hw->cur_evt;
+	hw->cur_evt = evt;
+	CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+	switch (evt) {
+	case CSIO_HWE_QUIESCED:
+		switch (hw->evtflag) {
+		case CSIO_HWE_FW_DLOAD:
+			csio_set_state(&hw->sm, csio_hws_resetting);
+			/* Download firmware */
+			/* Fall through */
+
+		case CSIO_HWE_HBA_RESET:
+			csio_set_state(&hw->sm, csio_hws_resetting);
+			/* Start reset of the HBA */
+			csio_notify_lnodes(hw, CSIO_LN_NOTIFY_HWRESET);
+			csio_wr_destroy_queues(hw, false);
+			csio_do_reset(hw, false);
+			csio_post_event(&hw->sm, CSIO_HWE_HBA_RESET_DONE);
+			break;
+
+		case CSIO_HWE_PCI_REMOVE:
+			csio_set_state(&hw->sm, csio_hws_removing);
+			csio_notify_lnodes(hw, CSIO_LN_NOTIFY_HWREMOVE);
+			csio_wr_destroy_queues(hw, true);
+			/* Now send the bye command */
+			csio_do_bye(hw);
+			break;
+
+		case CSIO_HWE_SUSPEND:
+			csio_set_state(&hw->sm, csio_hws_quiesced);
+			break;
+
+		case CSIO_HWE_PCIERR_DETECTED:
+			csio_set_state(&hw->sm, csio_hws_pcierr);
+			csio_wr_destroy_queues(hw, false);
+			break;
+
+		default:
+			CSIO_INC_STATS(hw, n_evt_unexp);
+			break;
+
+		}
+		break;
+
+	default:
+		CSIO_INC_STATS(hw, n_evt_unexp);
+		break;
+	}
+}
+
+/*
+ * csio_hws_quiesced - Quiesced state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_quiesced(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+	hw->prev_evt = hw->cur_evt;
+	hw->cur_evt = evt;
+	CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+	switch (evt) {
+	case CSIO_HWE_RESUME:
+		csio_set_state(&hw->sm, csio_hws_configuring);
+		csio_hw_configure(hw);
+		break;
+
+	default:
+		CSIO_INC_STATS(hw, n_evt_unexp);
+		break;
+	}
+}
+
+/*
+ * csio_hws_resetting - HW Resetting state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_resetting(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+	hw->prev_evt = hw->cur_evt;
+	hw->cur_evt = evt;
+	CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+	switch (evt) {
+	case CSIO_HWE_HBA_RESET_DONE:
+		csio_evtq_start(hw);
+		csio_set_state(&hw->sm, csio_hws_configuring);
+		csio_hw_configure(hw);
+		break;
+
+	default:
+		CSIO_INC_STATS(hw, n_evt_unexp);
+		break;
+	}
+}
+
+/*
+ * csio_hws_removing - PCI Hotplug removing state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_removing(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+	hw->prev_evt = hw->cur_evt;
+	hw->cur_evt = evt;
+	CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+	switch (evt) {
+	case CSIO_HWE_HBA_RESET:
+		if (!csio_is_hw_master(hw))
+			break;
+		/*
+		 * The BYE should have alerady been issued, so we cant
+		 * use the mailbox interface. Hence we use the PL_RST
+		 * register directly.
+		 */
+		csio_err(hw, "Resetting HW and waiting 2 seconds...\n");
+		csio_wr_reg32(hw, PIORSTMODE | PIORST, PL_RST);
+		mdelay(2000);
+		break;
+
+	/* Should never receive any new events */
+	default:
+		CSIO_INC_STATS(hw, n_evt_unexp);
+		break;
+
+	}
+}
+
+/*
+ * csio_hws_pcierr - PCI Error state
+ * @hw - HW module
+ * @evt - Event
+ *
+ */
+static void
+csio_hws_pcierr(struct csio_hw *hw, enum csio_hw_ev evt)
+{
+	hw->prev_evt = hw->cur_evt;
+	hw->cur_evt = evt;
+	CSIO_INC_STATS(hw, n_evt_sm[evt]);
+
+	switch (evt) {
+	case CSIO_HWE_PCIERR_SLOT_RESET:
+		csio_evtq_start(hw);
+		csio_set_state(&hw->sm, csio_hws_configuring);
+		csio_hw_configure(hw);
+		break;
+
+	default:
+		CSIO_INC_STATS(hw, n_evt_unexp);
+		break;
+	}
+}
+
+/*****************************************************************************/
+/* END: HW SM                                                                */
+/*****************************************************************************/
+
+/* Slow path handlers */
+struct intr_info {
+	unsigned int mask;       /* bits to check in interrupt status */
+	const char *msg;         /* message to print or NULL */
+	short stat_idx;          /* stat counter to increment or -1 */
+	unsigned short fatal;    /* whether the condition reported is fatal */
+};
+
+/*
+ *	csio_handle_intr_status - table driven interrupt handler
+ *	@hw: HW instance
+ *	@reg: the interrupt status register to process
+ *	@acts: table of interrupt actions
+ *
+ *	A table driven interrupt handler that applies a set of masks to an
+ *	interrupt status word and performs the corresponding actions if the
+ *	interrupts described by the mask have occured.  The actions include
+ *	optionally emitting a warning or alert message. The table is terminated
+ *	by an entry specifying mask 0.  Returns the number of fatal interrupt
+ *	conditions.
+ */
+static int
+csio_handle_intr_status(struct csio_hw *hw, unsigned int reg,
+				 const struct intr_info *acts)
+{
+	int fatal = 0;
+	unsigned int mask = 0;
+	unsigned int status = csio_rd_reg32(hw, reg);
+
+	for ( ; acts->mask; ++acts) {
+		if (!(status & acts->mask))
+			continue;
+		if (acts->fatal) {
+			fatal++;
+			csio_fatal(hw, "Fatal %s (0x%x)\n",
+				    acts->msg, status & acts->mask);
+		} else if (acts->msg)
+			csio_info(hw, "%s (0x%x)\n",
+				    acts->msg, status & acts->mask);
+		mask |= acts->mask;
+	}
+	status &= mask;
+	if (status)                           /* clear processed interrupts */
+		csio_wr_reg32(hw, status, reg);
+	return fatal;
+}
+
+/*
+ * Interrupt handler for the PCIE module.
+ */
+static void
+csio_pcie_intr_handler(struct csio_hw *hw)
+{
+	static struct intr_info sysbus_intr_info[] = {
+		{ RNPP, "RXNP array parity error", -1, 1 },
+		{ RPCP, "RXPC array parity error", -1, 1 },
+		{ RCIP, "RXCIF array parity error", -1, 1 },
+		{ RCCP, "Rx completions control array parity error", -1, 1 },
+		{ RFTP, "RXFT array parity error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+	static struct intr_info pcie_port_intr_info[] = {
+		{ TPCP, "TXPC array parity error", -1, 1 },
+		{ TNPP, "TXNP array parity error", -1, 1 },
+		{ TFTP, "TXFT array parity error", -1, 1 },
+		{ TCAP, "TXCA array parity error", -1, 1 },
+		{ TCIP, "TXCIF array parity error", -1, 1 },
+		{ RCAP, "RXCA array parity error", -1, 1 },
+		{ OTDD, "outbound request TLP discarded", -1, 1 },
+		{ RDPE, "Rx data parity error", -1, 1 },
+		{ TDUE, "Tx uncorrectable data error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+	static struct intr_info pcie_intr_info[] = {
+		{ MSIADDRLPERR, "MSI AddrL parity error", -1, 1 },
+		{ MSIADDRHPERR, "MSI AddrH parity error", -1, 1 },
+		{ MSIDATAPERR, "MSI data parity error", -1, 1 },
+		{ MSIXADDRLPERR, "MSI-X AddrL parity error", -1, 1 },
+		{ MSIXADDRHPERR, "MSI-X AddrH parity error", -1, 1 },
+		{ MSIXDATAPERR, "MSI-X data parity error", -1, 1 },
+		{ MSIXDIPERR, "MSI-X DI parity error", -1, 1 },
+		{ PIOCPLPERR, "PCI PIO completion FIFO parity error", -1, 1 },
+		{ PIOREQPERR, "PCI PIO request FIFO parity error", -1, 1 },
+		{ TARTAGPERR, "PCI PCI target tag FIFO parity error", -1, 1 },
+		{ CCNTPERR, "PCI CMD channel count parity error", -1, 1 },
+		{ CREQPERR, "PCI CMD channel request parity error", -1, 1 },
+		{ CRSPPERR, "PCI CMD channel response parity error", -1, 1 },
+		{ DCNTPERR, "PCI DMA channel count parity error", -1, 1 },
+		{ DREQPERR, "PCI DMA channel request parity error", -1, 1 },
+		{ DRSPPERR, "PCI DMA channel response parity error", -1, 1 },
+		{ HCNTPERR, "PCI HMA channel count parity error", -1, 1 },
+		{ HREQPERR, "PCI HMA channel request parity error", -1, 1 },
+		{ HRSPPERR, "PCI HMA channel response parity error", -1, 1 },
+		{ CFGSNPPERR, "PCI config snoop FIFO parity error", -1, 1 },
+		{ FIDPERR, "PCI FID parity error", -1, 1 },
+		{ INTXCLRPERR, "PCI INTx clear parity error", -1, 1 },
+		{ MATAGPERR, "PCI MA tag parity error", -1, 1 },
+		{ PIOTAGPERR, "PCI PIO tag parity error", -1, 1 },
+		{ RXCPLPERR, "PCI Rx completion parity error", -1, 1 },
+		{ RXWRPERR, "PCI Rx write parity error", -1, 1 },
+		{ RPLPERR, "PCI replay buffer parity error", -1, 1 },
+		{ PCIESINT, "PCI core secondary fault", -1, 1 },
+		{ PCIEPINT, "PCI core primary fault", -1, 1 },
+		{ UNXSPLCPLERR, "PCI unexpected split completion error", -1,
+		  0 },
+		{ 0, NULL, 0, 0 }
+	};
+
+	int fat;
+
+	fat = csio_handle_intr_status(hw,
+				    PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
+				    sysbus_intr_info) +
+	      csio_handle_intr_status(hw,
+				    PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
+				    pcie_port_intr_info) +
+	      csio_handle_intr_status(hw, PCIE_INT_CAUSE, pcie_intr_info);
+	if (fat)
+		csio_hw_fatal_err(hw);
+}
+
+/*
+ * TP interrupt handler.
+ */
+static void csio_tp_intr_handler(struct csio_hw *hw)
+{
+	static struct intr_info tp_intr_info[] = {
+		{ 0x3fffffff, "TP parity error", -1, 1 },
+		{ FLMTXFLSTEMPTY, "TP out of Tx pages", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+
+	if (csio_handle_intr_status(hw, TP_INT_CAUSE, tp_intr_info))
+		csio_hw_fatal_err(hw);
+}
+
+/*
+ * SGE interrupt handler.
+ */
+static void csio_sge_intr_handler(struct csio_hw *hw)
+{
+	uint64_t v;
+
+	static struct intr_info sge_intr_info[] = {
+		{ ERR_CPL_EXCEED_IQE_SIZE,
+		  "SGE received CPL exceeding IQE size", -1, 1 },
+		{ ERR_INVALID_CIDX_INC,
+		  "SGE GTS CIDX increment too large", -1, 0 },
+		{ ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 },
+		{ ERR_DROPPED_DB, "SGE doorbell dropped", -1, 0 },
+		{ ERR_DATA_CPL_ON_HIGH_QID1 | ERR_DATA_CPL_ON_HIGH_QID0,
+		  "SGE IQID > 1023 received CPL for FL", -1, 0 },
+		{ ERR_BAD_DB_PIDX3, "SGE DBP 3 pidx increment too large", -1,
+		  0 },
+		{ ERR_BAD_DB_PIDX2, "SGE DBP 2 pidx increment too large", -1,
+		  0 },
+		{ ERR_BAD_DB_PIDX1, "SGE DBP 1 pidx increment too large", -1,
+		  0 },
+		{ ERR_BAD_DB_PIDX0, "SGE DBP 0 pidx increment too large", -1,
+		  0 },
+		{ ERR_ING_CTXT_PRIO,
+		  "SGE too many priority ingress contexts", -1, 0 },
+		{ ERR_EGR_CTXT_PRIO,
+		  "SGE too many priority egress contexts", -1, 0 },
+		{ INGRESS_SIZE_ERR, "SGE illegal ingress QID", -1, 0 },
+		{ EGRESS_SIZE_ERR, "SGE illegal egress QID", -1, 0 },
+		{ 0, NULL, 0, 0 }
+	};
+
+	v = (uint64_t)csio_rd_reg32(hw, SGE_INT_CAUSE1) |
+	    ((uint64_t)csio_rd_reg32(hw, SGE_INT_CAUSE2) << 32);
+	if (v) {
+		csio_fatal(hw, "SGE parity error (%#llx)\n",
+			    (unsigned long long)v);
+		csio_wr_reg32(hw, (uint32_t)(v & 0xFFFFFFFF),
+						SGE_INT_CAUSE1);
+		csio_wr_reg32(hw, (uint32_t)(v >> 32), SGE_INT_CAUSE2);
+	}
+
+	v |= csio_handle_intr_status(hw, SGE_INT_CAUSE3, sge_intr_info);
+
+	if (csio_handle_intr_status(hw, SGE_INT_CAUSE3, sge_intr_info) ||
+	    v != 0)
+		csio_hw_fatal_err(hw);
+}
+
+#define CIM_OBQ_INTR (OBQULP0PARERR | OBQULP1PARERR | OBQULP2PARERR |\
+		      OBQULP3PARERR | OBQSGEPARERR | OBQNCSIPARERR)
+#define CIM_IBQ_INTR (IBQTP0PARERR | IBQTP1PARERR | IBQULPPARERR |\
+		      IBQSGEHIPARERR | IBQSGELOPARERR | IBQNCSIPARERR)
+
+/*
+ * CIM interrupt handler.
+ */
+static void csio_cim_intr_handler(struct csio_hw *hw)
+{
+	static struct intr_info cim_intr_info[] = {
+		{ PREFDROPINT, "CIM control register prefetch drop", -1, 1 },
+		{ CIM_OBQ_INTR, "CIM OBQ parity error", -1, 1 },
+		{ CIM_IBQ_INTR, "CIM IBQ parity error", -1, 1 },
+		{ MBUPPARERR, "CIM mailbox uP parity error", -1, 1 },
+		{ MBHOSTPARERR, "CIM mailbox host parity error", -1, 1 },
+		{ TIEQINPARERRINT, "CIM TIEQ outgoing parity error", -1, 1 },
+		{ TIEQOUTPARERRINT, "CIM TIEQ incoming parity error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+	static struct intr_info cim_upintr_info[] = {
+		{ RSVDSPACEINT, "CIM reserved space access", -1, 1 },
+		{ ILLTRANSINT, "CIM illegal transaction", -1, 1 },
+		{ ILLWRINT, "CIM illegal write", -1, 1 },
+		{ ILLRDINT, "CIM illegal read", -1, 1 },
+		{ ILLRDBEINT, "CIM illegal read BE", -1, 1 },
+		{ ILLWRBEINT, "CIM illegal write BE", -1, 1 },
+		{ SGLRDBOOTINT, "CIM single read from boot space", -1, 1 },
+		{ SGLWRBOOTINT, "CIM single write to boot space", -1, 1 },
+		{ BLKWRBOOTINT, "CIM block write to boot space", -1, 1 },
+		{ SGLRDFLASHINT, "CIM single read from flash space", -1, 1 },
+		{ SGLWRFLASHINT, "CIM single write to flash space", -1, 1 },
+		{ BLKWRFLASHINT, "CIM block write to flash space", -1, 1 },
+		{ SGLRDEEPROMINT, "CIM single EEPROM read", -1, 1 },
+		{ SGLWREEPROMINT, "CIM single EEPROM write", -1, 1 },
+		{ BLKRDEEPROMINT, "CIM block EEPROM read", -1, 1 },
+		{ BLKWREEPROMINT, "CIM block EEPROM write", -1, 1 },
+		{ SGLRDCTLINT , "CIM single read from CTL space", -1, 1 },
+		{ SGLWRCTLINT , "CIM single write to CTL space", -1, 1 },
+		{ BLKRDCTLINT , "CIM block read from CTL space", -1, 1 },
+		{ BLKWRCTLINT , "CIM block write to CTL space", -1, 1 },
+		{ SGLRDPLINT , "CIM single read from PL space", -1, 1 },
+		{ SGLWRPLINT , "CIM single write to PL space", -1, 1 },
+		{ BLKRDPLINT , "CIM block read from PL space", -1, 1 },
+		{ BLKWRPLINT , "CIM block write to PL space", -1, 1 },
+		{ REQOVRLOOKUPINT , "CIM request FIFO overwrite", -1, 1 },
+		{ RSPOVRLOOKUPINT , "CIM response FIFO overwrite", -1, 1 },
+		{ TIMEOUTINT , "CIM PIF timeout", -1, 1 },
+		{ TIMEOUTMAINT , "CIM PIF MA timeout", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+
+	int fat;
+
+	fat = csio_handle_intr_status(hw, CIM_HOST_INT_CAUSE,
+				    cim_intr_info) +
+	      csio_handle_intr_status(hw, CIM_HOST_UPACC_INT_CAUSE,
+				    cim_upintr_info);
+	if (fat)
+		csio_hw_fatal_err(hw);
+}
+
+/*
+ * ULP RX interrupt handler.
+ */
+static void csio_ulprx_intr_handler(struct csio_hw *hw)
+{
+	static struct intr_info ulprx_intr_info[] = {
+		{ 0x1800000, "ULPRX context error", -1, 1 },
+		{ 0x7fffff, "ULPRX parity error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+
+	if (csio_handle_intr_status(hw, ULP_RX_INT_CAUSE, ulprx_intr_info))
+		csio_hw_fatal_err(hw);
+}
+
+/*
+ * ULP TX interrupt handler.
+ */
+static void csio_ulptx_intr_handler(struct csio_hw *hw)
+{
+	static struct intr_info ulptx_intr_info[] = {
+		{ PBL_BOUND_ERR_CH3, "ULPTX channel 3 PBL out of bounds", -1,
+		  0 },
+		{ PBL_BOUND_ERR_CH2, "ULPTX channel 2 PBL out of bounds", -1,
+		  0 },
+		{ PBL_BOUND_ERR_CH1, "ULPTX channel 1 PBL out of bounds", -1,
+		  0 },
+		{ PBL_BOUND_ERR_CH0, "ULPTX channel 0 PBL out of bounds", -1,
+		  0 },
+		{ 0xfffffff, "ULPTX parity error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+
+	if (csio_handle_intr_status(hw, ULP_TX_INT_CAUSE, ulptx_intr_info))
+		csio_hw_fatal_err(hw);
+}
+
+/*
+ * PM TX interrupt handler.
+ */
+static void csio_pmtx_intr_handler(struct csio_hw *hw)
+{
+	static struct intr_info pmtx_intr_info[] = {
+		{ PCMD_LEN_OVFL0, "PMTX channel 0 pcmd too large", -1, 1 },
+		{ PCMD_LEN_OVFL1, "PMTX channel 1 pcmd too large", -1, 1 },
+		{ PCMD_LEN_OVFL2, "PMTX channel 2 pcmd too large", -1, 1 },
+		{ ZERO_C_CMD_ERROR, "PMTX 0-length pcmd", -1, 1 },
+		{ 0xffffff0, "PMTX framing error", -1, 1 },
+		{ OESPI_PAR_ERROR, "PMTX oespi parity error", -1, 1 },
+		{ DB_OPTIONS_PAR_ERROR, "PMTX db_options parity error", -1,
+		  1 },
+		{ ICSPI_PAR_ERROR, "PMTX icspi parity error", -1, 1 },
+		{ C_PCMD_PAR_ERROR, "PMTX c_pcmd parity error", -1, 1},
+		{ 0, NULL, 0, 0 }
+	};
+
+	if (csio_handle_intr_status(hw, PM_TX_INT_CAUSE, pmtx_intr_info))
+		csio_hw_fatal_err(hw);
+}
+
+/*
+ * PM RX interrupt handler.
+ */
+static void csio_pmrx_intr_handler(struct csio_hw *hw)
+{
+	static struct intr_info pmrx_intr_info[] = {
+		{ ZERO_E_CMD_ERROR, "PMRX 0-length pcmd", -1, 1 },
+		{ 0x3ffff0, "PMRX framing error", -1, 1 },
+		{ OCSPI_PAR_ERROR, "PMRX ocspi parity error", -1, 1 },
+		{ DB_OPTIONS_PAR_ERROR, "PMRX db_options parity error", -1,
+		  1 },
+		{ IESPI_PAR_ERROR, "PMRX iespi parity error", -1, 1 },
+		{ E_PCMD_PAR_ERROR, "PMRX e_pcmd parity error", -1, 1},
+		{ 0, NULL, 0, 0 }
+	};
+
+	if (csio_handle_intr_status(hw, PM_RX_INT_CAUSE, pmrx_intr_info))
+		csio_hw_fatal_err(hw);
+}
+
+/*
+ * CPL switch interrupt handler.
+ */
+static void csio_cplsw_intr_handler(struct csio_hw *hw)
+{
+	static struct intr_info cplsw_intr_info[] = {
+		{ CIM_OP_MAP_PERR, "CPLSW CIM op_map parity error", -1, 1 },
+		{ CIM_OVFL_ERROR, "CPLSW CIM overflow", -1, 1 },
+		{ TP_FRAMING_ERROR, "CPLSW TP framing error", -1, 1 },
+		{ SGE_FRAMING_ERROR, "CPLSW SGE framing error", -1, 1 },
+		{ CIM_FRAMING_ERROR, "CPLSW CIM framing error", -1, 1 },
+		{ ZERO_SWITCH_ERROR, "CPLSW no-switch error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+
+	if (csio_handle_intr_status(hw, CPL_INTR_CAUSE, cplsw_intr_info))
+		csio_hw_fatal_err(hw);
+}
+
+/*
+ * LE interrupt handler.
+ */
+static void csio_le_intr_handler(struct csio_hw *hw)
+{
+	static struct intr_info le_intr_info[] = {
+		{ LIPMISS, "LE LIP miss", -1, 0 },
+		{ LIP0, "LE 0 LIP error", -1, 0 },
+		{ PARITYERR, "LE parity error", -1, 1 },
+		{ UNKNOWNCMD, "LE unknown command", -1, 1 },
+		{ REQQPARERR, "LE request queue parity error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+
+	if (csio_handle_intr_status(hw, LE_DB_INT_CAUSE, le_intr_info))
+		csio_hw_fatal_err(hw);
+}
+
+/*
+ * MPS interrupt handler.
+ */
+static void csio_mps_intr_handler(struct csio_hw *hw)
+{
+	static struct intr_info mps_rx_intr_info[] = {
+		{ 0xffffff, "MPS Rx parity error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+	static struct intr_info mps_tx_intr_info[] = {
+		{ TPFIFO, "MPS Tx TP FIFO parity error", -1, 1 },
+		{ NCSIFIFO, "MPS Tx NC-SI FIFO parity error", -1, 1 },
+		{ TXDATAFIFO, "MPS Tx data FIFO parity error", -1, 1 },
+		{ TXDESCFIFO, "MPS Tx desc FIFO parity error", -1, 1 },
+		{ BUBBLE, "MPS Tx underflow", -1, 1 },
+		{ SECNTERR, "MPS Tx SOP/EOP error", -1, 1 },
+		{ FRMERR, "MPS Tx framing error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+	static struct intr_info mps_trc_intr_info[] = {
+		{ FILTMEM, "MPS TRC filter parity error", -1, 1 },
+		{ PKTFIFO, "MPS TRC packet FIFO parity error", -1, 1 },
+		{ MISCPERR, "MPS TRC misc parity error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+	static struct intr_info mps_stat_sram_intr_info[] = {
+		{ 0x1fffff, "MPS statistics SRAM parity error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+	static struct intr_info mps_stat_tx_intr_info[] = {
+		{ 0xfffff, "MPS statistics Tx FIFO parity error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+	static struct intr_info mps_stat_rx_intr_info[] = {
+		{ 0xffffff, "MPS statistics Rx FIFO parity error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+	static struct intr_info mps_cls_intr_info[] = {
+		{ MATCHSRAM, "MPS match SRAM parity error", -1, 1 },
+		{ MATCHTCAM, "MPS match TCAM parity error", -1, 1 },
+		{ HASHSRAM, "MPS hash SRAM parity error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+
+	int fat;
+
+	fat = csio_handle_intr_status(hw, MPS_RX_PERR_INT_CAUSE,
+				    mps_rx_intr_info) +
+	      csio_handle_intr_status(hw, MPS_TX_INT_CAUSE,
+				    mps_tx_intr_info) +
+	      csio_handle_intr_status(hw, MPS_TRC_INT_CAUSE,
+				    mps_trc_intr_info) +
+	      csio_handle_intr_status(hw, MPS_STAT_PERR_INT_CAUSE_SRAM,
+				    mps_stat_sram_intr_info) +
+	      csio_handle_intr_status(hw, MPS_STAT_PERR_INT_CAUSE_TX_FIFO,
+				    mps_stat_tx_intr_info) +
+	      csio_handle_intr_status(hw, MPS_STAT_PERR_INT_CAUSE_RX_FIFO,
+				    mps_stat_rx_intr_info) +
+	      csio_handle_intr_status(hw, MPS_CLS_INT_CAUSE,
+				    mps_cls_intr_info);
+
+	csio_wr_reg32(hw, 0, MPS_INT_CAUSE);
+	csio_rd_reg32(hw, MPS_INT_CAUSE);                    /* flush */
+	if (fat)
+		csio_hw_fatal_err(hw);
+}
+
+#define MEM_INT_MASK (PERR_INT_CAUSE | ECC_CE_INT_CAUSE | ECC_UE_INT_CAUSE)
+
+/*
+ * EDC/MC interrupt handler.
+ */
+static void csio_mem_intr_handler(struct csio_hw *hw, int idx)
+{
+	static const char name[3][5] = { "EDC0", "EDC1", "MC" };
+
+	unsigned int addr, cnt_addr, v;
+
+	if (idx <= MEM_EDC1) {
+		addr = EDC_REG(EDC_INT_CAUSE, idx);
+		cnt_addr = EDC_REG(EDC_ECC_STATUS, idx);
+	} else {
+		addr = MC_INT_CAUSE;
+		cnt_addr = MC_ECC_STATUS;
+	}
+
+	v = csio_rd_reg32(hw, addr) & MEM_INT_MASK;
+	if (v & PERR_INT_CAUSE)
+		csio_fatal(hw, "%s FIFO parity error\n", name[idx]);
+	if (v & ECC_CE_INT_CAUSE) {
+		uint32_t cnt = ECC_CECNT_GET(csio_rd_reg32(hw, cnt_addr));
+
+		csio_wr_reg32(hw, ECC_CECNT_MASK, cnt_addr);
+		csio_warn(hw, "%u %s correctable ECC data error%s\n",
+			    cnt, name[idx], cnt > 1 ? "s" : "");
+	}
+	if (v & ECC_UE_INT_CAUSE)
+		csio_fatal(hw, "%s uncorrectable ECC data error\n", name[idx]);
+
+	csio_wr_reg32(hw, v, addr);
+	if (v & (PERR_INT_CAUSE | ECC_UE_INT_CAUSE))
+		csio_hw_fatal_err(hw);
+}
+
+/*
+ * MA interrupt handler.
+ */
+static void csio_ma_intr_handler(struct csio_hw *hw)
+{
+	uint32_t v, status = csio_rd_reg32(hw, MA_INT_CAUSE);
+
+	if (status & MEM_PERR_INT_CAUSE)
+		csio_fatal(hw, "MA parity error, parity status %#x\n",
+			    csio_rd_reg32(hw, MA_PARITY_ERROR_STATUS));
+	if (status & MEM_WRAP_INT_CAUSE) {
+		v = csio_rd_reg32(hw, MA_INT_WRAP_STATUS);
+		csio_fatal(hw,
+		   "MA address wrap-around error by client %u to address %#x\n",
+		   MEM_WRAP_CLIENT_NUM_GET(v), MEM_WRAP_ADDRESS_GET(v) << 4);
+	}
+	csio_wr_reg32(hw, status, MA_INT_CAUSE);
+	csio_hw_fatal_err(hw);
+}
+
+/*
+ * SMB interrupt handler.
+ */
+static void csio_smb_intr_handler(struct csio_hw *hw)
+{
+	static struct intr_info smb_intr_info[] = {
+		{ MSTTXFIFOPARINT, "SMB master Tx FIFO parity error", -1, 1 },
+		{ MSTRXFIFOPARINT, "SMB master Rx FIFO parity error", -1, 1 },
+		{ SLVFIFOPARINT, "SMB slave FIFO parity error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+
+	if (csio_handle_intr_status(hw, SMB_INT_CAUSE, smb_intr_info))
+		csio_hw_fatal_err(hw);
+}
+
+/*
+ * NC-SI interrupt handler.
+ */
+static void csio_ncsi_intr_handler(struct csio_hw *hw)
+{
+	static struct intr_info ncsi_intr_info[] = {
+		{ CIM_DM_PRTY_ERR, "NC-SI CIM parity error", -1, 1 },
+		{ MPS_DM_PRTY_ERR, "NC-SI MPS parity error", -1, 1 },
+		{ TXFIFO_PRTY_ERR, "NC-SI Tx FIFO parity error", -1, 1 },
+		{ RXFIFO_PRTY_ERR, "NC-SI Rx FIFO parity error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+
+	if (csio_handle_intr_status(hw, NCSI_INT_CAUSE, ncsi_intr_info))
+		csio_hw_fatal_err(hw);
+}
+
+/*
+ * XGMAC interrupt handler.
+ */
+static void csio_xgmac_intr_handler(struct csio_hw *hw, int port)
+{
+	uint32_t v = csio_rd_reg32(hw, PORT_REG(port, XGMAC_PORT_INT_CAUSE));
+
+	v &= TXFIFO_PRTY_ERR | RXFIFO_PRTY_ERR;
+	if (!v)
+		return;
+
+	if (v & TXFIFO_PRTY_ERR)
+		csio_fatal(hw, "XGMAC %d Tx FIFO parity error\n", port);
+	if (v & RXFIFO_PRTY_ERR)
+		csio_fatal(hw, "XGMAC %d Rx FIFO parity error\n", port);
+	csio_wr_reg32(hw, v, PORT_REG(port, XGMAC_PORT_INT_CAUSE));
+	csio_hw_fatal_err(hw);
+}
+
+/*
+ * PL interrupt handler.
+ */
+static void csio_pl_intr_handler(struct csio_hw *hw)
+{
+	static struct intr_info pl_intr_info[] = {
+		{ FATALPERR, "T4 fatal parity error", -1, 1 },
+		{ PERRVFID, "PL VFID_MAP parity error", -1, 1 },
+		{ 0, NULL, 0, 0 }
+	};
+
+	if (csio_handle_intr_status(hw, PL_PL_INT_CAUSE, pl_intr_info))
+		csio_hw_fatal_err(hw);
+}
+
+/*
+ *	csio_hw_slow_intr_handler - control path interrupt handler
+ *	@hw: HW module
+ *
+ *	Interrupt handler for non-data global interrupt events, e.g., errors.
+ *	The designation 'slow' is because it involves register reads, while
+ *	data interrupts typically don't involve any MMIOs.
+ */
+int
+csio_hw_slow_intr_handler(struct csio_hw *hw)
+{
+	uint32_t cause = csio_rd_reg32(hw, PL_INT_CAUSE);
+
+	if (!(cause & CSIO_GLBL_INTR_MASK)) {
+		CSIO_INC_STATS(hw, n_plint_unexp);
+		return 0;
+	}
+
+	csio_dbg(hw, "Slow interrupt! cause: 0x%x\n", cause);
+
+	CSIO_INC_STATS(hw, n_plint_cnt);
+
+	if (cause & CIM)
+		csio_cim_intr_handler(hw);
+
+	if (cause & MPS)
+		csio_mps_intr_handler(hw);
+
+	if (cause & NCSI)
+		csio_ncsi_intr_handler(hw);
+
+	if (cause & PL)
+		csio_pl_intr_handler(hw);
+
+	if (cause & SMB)
+		csio_smb_intr_handler(hw);
+
+	if (cause & XGMAC0)
+		csio_xgmac_intr_handler(hw, 0);
+
+	if (cause & XGMAC1)
+		csio_xgmac_intr_handler(hw, 1);
+
+	if (cause & XGMAC_KR0)
+		csio_xgmac_intr_handler(hw, 2);
+
+	if (cause & XGMAC_KR1)
+		csio_xgmac_intr_handler(hw, 3);
+
+	if (cause & PCIE)
+		csio_pcie_intr_handler(hw);
+
+	if (cause & MC)
+		csio_mem_intr_handler(hw, MEM_MC);
+
+	if (cause & EDC0)
+		csio_mem_intr_handler(hw, MEM_EDC0);
+
+	if (cause & EDC1)
+		csio_mem_intr_handler(hw, MEM_EDC1);
+
+	if (cause & LE)
+		csio_le_intr_handler(hw);
+
+	if (cause & TP)
+		csio_tp_intr_handler(hw);
+
+	if (cause & MA)
+		csio_ma_intr_handler(hw);
+
+	if (cause & PM_TX)
+		csio_pmtx_intr_handler(hw);
+
+	if (cause & PM_RX)
+		csio_pmrx_intr_handler(hw);
+
+	if (cause & ULP_RX)
+		csio_ulprx_intr_handler(hw);
+
+	if (cause & CPL_SWITCH)
+		csio_cplsw_intr_handler(hw);
+
+	if (cause & SGE)
+		csio_sge_intr_handler(hw);
+
+	if (cause & ULP_TX)
+		csio_ulptx_intr_handler(hw);
+
+	/* Clear the interrupts just processed for which we are the master. */
+	csio_wr_reg32(hw, cause & CSIO_GLBL_INTR_MASK, PL_INT_CAUSE);
+	csio_rd_reg32(hw, PL_INT_CAUSE); /* flush */
+
+	return 1;
+}
+
+/*****************************************************************************
+ * HW <--> mailbox interfacing routines.
+ ****************************************************************************/
+/*
+ * csio_mberr_worker - Worker thread (dpc) for mailbox/error completions
+ *
+ * @data: Private data pointer.
+ *
+ * Called from worker thread context.
+ */
+static void
+csio_mberr_worker(void *data)
+{
+	struct csio_hw *hw = (struct csio_hw *)data;
+	struct csio_mbm *mbm = &hw->mbm;
+	LIST_HEAD(cbfn_q);
+	struct csio_mb *mbp_next;
+	int rv;
+
+	del_timer_sync(&mbm->timer);
+
+	spin_lock_irq(&hw->lock);
+	if (list_empty(&mbm->cbfn_q)) {
+		spin_unlock_irq(&hw->lock);
+		return;
+	}
+
+	list_splice_tail_init(&mbm->cbfn_q, &cbfn_q);
+	mbm->stats.n_cbfnq = 0;
+
+	/* Try to start waiting mailboxes */
+	if (!list_empty(&mbm->req_q)) {
+		mbp_next = list_first_entry(&mbm->req_q, struct csio_mb, list);
+		list_del_init(&mbp_next->list);
+
+		rv = csio_mb_issue(hw, mbp_next);
+		if (rv != 0)
+			list_add_tail(&mbp_next->list, &mbm->req_q);
+		else
+			CSIO_DEC_STATS(mbm, n_activeq);
+	}
+	spin_unlock_irq(&hw->lock);
+
+	/* Now callback completions */
+	csio_mb_completions(hw, &cbfn_q);
+}
+
+/*
+ * csio_hw_mb_timer - Top-level Mailbox timeout handler.
+ *
+ * @data: private data pointer
+ *
+ **/
+static void
+csio_hw_mb_timer(uintptr_t data)
+{
+	struct csio_hw *hw = (struct csio_hw *)data;
+	struct csio_mb *mbp = NULL;
+
+	spin_lock_irq(&hw->lock);
+	mbp = csio_mb_tmo_handler(hw);
+	spin_unlock_irq(&hw->lock);
+
+	/* Call back the function for the timed-out Mailbox */
+	if (mbp)
+		mbp->mb_cbfn(hw, mbp);
+
+}
+
+/*
+ * csio_hw_mbm_cleanup - Cleanup Mailbox module.
+ * @hw: HW module
+ *
+ * Called with lock held, should exit with lock held.
+ * Cancels outstanding mailboxes (waiting, in-flight) and gathers them
+ * into a local queue. Drops lock and calls the completions. Holds
+ * lock and returns.
+ */
+static void
+csio_hw_mbm_cleanup(struct csio_hw *hw)
+{
+	LIST_HEAD(cbfn_q);
+
+	csio_mb_cancel_all(hw, &cbfn_q);
+
+	spin_unlock_irq(&hw->lock);
+	csio_mb_completions(hw, &cbfn_q);
+	spin_lock_irq(&hw->lock);
+}
+
+/*****************************************************************************
+ * Event handling
+ ****************************************************************************/
+int
+csio_enqueue_evt(struct csio_hw *hw, enum csio_evt type, void *evt_msg,
+			uint16_t len)
+{
+	struct csio_evt_msg *evt_entry = NULL;
+
+	if (type >= CSIO_EVT_MAX)
+		return -EINVAL;
+
+	if (len > CSIO_EVT_MSG_SIZE)
+		return -EINVAL;
+
+	if (hw->flags & CSIO_HWF_FWEVT_STOP)
+		return -EINVAL;
+
+	if (list_empty(&hw->evt_free_q)) {
+		csio_err(hw, "Failed to alloc evt entry, msg type %d len %d\n",
+			 type, len);
+		return -ENOMEM;
+	}
+
+	evt_entry = list_first_entry(&hw->evt_free_q,
+				     struct csio_evt_msg, list);
+	list_del_init(&evt_entry->list);
+
+	/* copy event msg and queue the event */
+	evt_entry->type = type;
+	memcpy((void *)evt_entry->data, evt_msg, len);
+	list_add_tail(&evt_entry->list, &hw->evt_active_q);
+
+	CSIO_DEC_STATS(hw, n_evt_freeq);
+	CSIO_INC_STATS(hw, n_evt_activeq);
+
+	return 0;
+}
+
+static int
+csio_enqueue_evt_lock(struct csio_hw *hw, enum csio_evt type, void *evt_msg,
+			uint16_t len, bool msg_sg)
+{
+	struct csio_evt_msg *evt_entry = NULL;
+	struct csio_fl_dma_buf *fl_sg;
+	uint32_t off = 0;
+	unsigned long flags;
+	int n, ret = 0;
+
+	if (type >= CSIO_EVT_MAX)
+		return -EINVAL;
+
+	if (len > CSIO_EVT_MSG_SIZE)
+		return -EINVAL;
+
+	spin_lock_irqsave(&hw->lock, flags);
+	if (hw->flags & CSIO_HWF_FWEVT_STOP) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (list_empty(&hw->evt_free_q)) {
+		csio_err(hw, "Failed to alloc evt entry, msg type %d len %d\n",
+			 type, len);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	evt_entry = list_first_entry(&hw->evt_free_q,
+				     struct csio_evt_msg, list);
+	list_del_init(&evt_entry->list);
+
+	/* copy event msg and queue the event */
+	evt_entry->type = type;
+
+	/* If Payload in SG list*/
+	if (msg_sg) {
+		fl_sg = (struct csio_fl_dma_buf *) evt_msg;
+		for (n = 0; (n < CSIO_MAX_FLBUF_PER_IQWR && off < len); n++) {
+			memcpy((void *)((uintptr_t)evt_entry->data + off),
+				fl_sg->flbufs[n].vaddr,
+				fl_sg->flbufs[n].len);
+			off += fl_sg->flbufs[n].len;
+		}
+	} else
+		memcpy((void *)evt_entry->data, evt_msg, len);
+
+	list_add_tail(&evt_entry->list, &hw->evt_active_q);
+	CSIO_DEC_STATS(hw, n_evt_freeq);
+	CSIO_INC_STATS(hw, n_evt_activeq);
+out:
+	spin_unlock_irqrestore(&hw->lock, flags);
+	return ret;
+}
+
+static void
+csio_free_evt(struct csio_hw *hw, struct csio_evt_msg *evt_entry)
+{
+	if (evt_entry) {
+		spin_lock_irq(&hw->lock);
+		list_del_init(&evt_entry->list);
+		list_add_tail(&evt_entry->list, &hw->evt_free_q);
+		CSIO_DEC_STATS(hw, n_evt_activeq);
+		CSIO_INC_STATS(hw, n_evt_freeq);
+		spin_unlock_irq(&hw->lock);
+	}
+}
+
+void
+csio_evtq_flush(struct csio_hw *hw)
+{
+	uint32_t count;
+	count = 30;
+	while (hw->flags & CSIO_HWF_FWEVT_PENDING && count--) {
+		spin_unlock_irq(&hw->lock);
+		msleep(2000);
+		spin_lock_irq(&hw->lock);
+	}
+
+	CSIO_DB_ASSERT(!(hw->flags & CSIO_HWF_FWEVT_PENDING));
+}
+
+static void
+csio_evtq_stop(struct csio_hw *hw)
+{
+	hw->flags |= CSIO_HWF_FWEVT_STOP;
+}
+
+static void
+csio_evtq_start(struct csio_hw *hw)
+{
+	hw->flags &= ~CSIO_HWF_FWEVT_STOP;
+}
+
+static void
+csio_evtq_cleanup(struct csio_hw *hw)
+{
+	struct list_head *evt_entry, *next_entry;
+
+	/* Release outstanding events from activeq to freeq*/
+	if (!list_empty(&hw->evt_active_q))
+		list_splice_tail_init(&hw->evt_active_q, &hw->evt_free_q);
+
+	hw->stats.n_evt_activeq = 0;
+	hw->flags &= ~CSIO_HWF_FWEVT_PENDING;
+
+	/* Freeup event entry */
+	list_for_each_safe(evt_entry, next_entry, &hw->evt_free_q) {
+		kfree(evt_entry);
+		CSIO_DEC_STATS(hw, n_evt_freeq);
+	}
+
+	hw->stats.n_evt_freeq = 0;
+}
+
+
+static void
+csio_process_fwevtq_entry(struct csio_hw *hw, void *wr, uint32_t len,
+			  struct csio_fl_dma_buf *flb, void *priv)
+{
+	__u8 op;
+	__be64 *data;
+	void *msg = NULL;
+	uint32_t msg_len = 0;
+	bool msg_sg = 0;
+
+	op = ((struct rss_header *) wr)->opcode;
+	if (op == CPL_FW6_PLD) {
+		CSIO_INC_STATS(hw, n_cpl_fw6_pld);
+		if (!flb || !flb->totlen) {
+			CSIO_INC_STATS(hw, n_cpl_unexp);
+			return;
+		}
+
+		msg = (void *) flb;
+		msg_len = flb->totlen;
+		msg_sg = 1;
+
+		data = (__be64 *) msg;
+	} else if (op == CPL_FW6_MSG || op == CPL_FW4_MSG) {
+
+		CSIO_INC_STATS(hw, n_cpl_fw6_msg);
+		/* skip RSS header */
+		msg = (void *)((uintptr_t)wr + sizeof(__be64));
+		msg_len = (op == CPL_FW6_MSG) ? sizeof(struct cpl_fw6_msg) :
+			   sizeof(struct cpl_fw4_msg);
+
+		data = (__be64 *) msg;
+	} else {
+		csio_warn(hw, "unexpected CPL %#x on FW event queue\n", op);
+		CSIO_INC_STATS(hw, n_cpl_unexp);
+		return;
+	}
+
+	/*
+	 * Enqueue event to EventQ. Events processing happens
+	 * in Event worker thread context
+	 */
+	if (csio_enqueue_evt_lock(hw, CSIO_EVT_FW, msg,
+				  (uint16_t)msg_len, msg_sg))
+		CSIO_INC_STATS(hw, n_evt_drop);
+}
+
+void
+csio_evtq_worker(struct work_struct *work)
+{
+	struct csio_hw *hw = container_of(work, struct csio_hw, evtq_work);
+	struct list_head *evt_entry, *next_entry;
+	LIST_HEAD(evt_q);
+	struct csio_evt_msg	*evt_msg;
+	struct cpl_fw6_msg *msg;
+	struct csio_rnode *rn;
+	int rv = 0;
+	uint8_t evtq_stop = 0;
+
+	csio_dbg(hw, "event worker thread active evts#%d\n",
+		 hw->stats.n_evt_activeq);
+
+	spin_lock_irq(&hw->lock);
+	while (!list_empty(&hw->evt_active_q)) {
+		list_splice_tail_init(&hw->evt_active_q, &evt_q);
+		spin_unlock_irq(&hw->lock);
+
+		list_for_each_safe(evt_entry, next_entry, &evt_q) {
+			evt_msg = (struct csio_evt_msg *) evt_entry;
+
+			/* Drop events if queue is STOPPED */
+			spin_lock_irq(&hw->lock);
+			if (hw->flags & CSIO_HWF_FWEVT_STOP)
+				evtq_stop = 1;
+			spin_unlock_irq(&hw->lock);
+			if (evtq_stop) {
+				CSIO_INC_STATS(hw, n_evt_drop);
+				goto free_evt;
+			}
+
+			switch (evt_msg->type) {
+			case CSIO_EVT_FW:
+				msg = (struct cpl_fw6_msg *)(evt_msg->data);
+
+				if ((msg->opcode == CPL_FW6_MSG ||
+				     msg->opcode == CPL_FW4_MSG) &&
+				    !msg->type) {
+					rv = csio_mb_fwevt_handler(hw,
+								msg->data);
+					if (!rv)
+						break;
+					/* Handle any remaining fw events */
+					csio_fcoe_fwevt_handler(hw,
+							msg->opcode, msg->data);
+				} else if (msg->opcode == CPL_FW6_PLD) {
+
+					csio_fcoe_fwevt_handler(hw,
+							msg->opcode, msg->data);
+				} else {
+					csio_warn(hw,
+					     "Unhandled FW msg op %x type %x\n",
+						  msg->opcode, msg->type);
+					CSIO_INC_STATS(hw, n_evt_drop);
+				}
+				break;
+
+			case CSIO_EVT_MBX:
+				csio_mberr_worker(hw);
+				break;
+
+			case CSIO_EVT_DEV_LOSS:
+				memcpy(&rn, evt_msg->data, sizeof(rn));
+				csio_rnode_devloss_handler(rn);
+				break;
+
+			default:
+				csio_warn(hw, "Unhandled event %x on evtq\n",
+					  evt_msg->type);
+				CSIO_INC_STATS(hw, n_evt_unexp);
+				break;
+			}
+free_evt:
+			csio_free_evt(hw, evt_msg);
+		}
+
+		spin_lock_irq(&hw->lock);
+	}
+	hw->flags &= ~CSIO_HWF_FWEVT_PENDING;
+	spin_unlock_irq(&hw->lock);
+}
+
+int
+csio_fwevtq_handler(struct csio_hw *hw)
+{
+	int rv;
+
+	if (csio_q_iqid(hw, hw->fwevt_iq_idx) == CSIO_MAX_QID) {
+		CSIO_INC_STATS(hw, n_int_stray);
+		return -EINVAL;
+	}
+
+	rv = csio_wr_process_iq_idx(hw, hw->fwevt_iq_idx,
+			   csio_process_fwevtq_entry, NULL);
+	return rv;
+}
+
+/****************************************************************************
+ * Entry points
+ ****************************************************************************/
+
+/* Management module */
+/*
+ * csio_mgmt_req_lookup - Lookup the given IO req exist in Active Q.
+ * mgmt - mgmt module
+ * @io_req - io request
+ *
+ * Return - 0:if given IO Req exists in active Q.
+ *          -EINVAL  :if lookup fails.
+ */
+int
+csio_mgmt_req_lookup(struct csio_mgmtm *mgmtm, struct csio_ioreq *io_req)
+{
+	struct list_head *tmp;
+
+	/* Lookup ioreq in the ACTIVEQ */
+	list_for_each(tmp, &mgmtm->active_q) {
+		if (io_req == (struct csio_ioreq *)tmp)
+			return 0;
+	}
+	return -EINVAL;
+}
+
+#define	ECM_MIN_TMO	1000	/* Minimum timeout value for req */
+
+/*
+ * csio_mgmts_tmo_handler - MGMT IO Timeout handler.
+ * @data - Event data.
+ *
+ * Return - none.
+ */
+static void
+csio_mgmt_tmo_handler(uintptr_t data)
+{
+	struct csio_mgmtm *mgmtm = (struct csio_mgmtm *) data;
+	struct list_head *tmp;
+	struct csio_ioreq *io_req;
+
+	csio_dbg(mgmtm->hw, "Mgmt timer invoked!\n");
+
+	spin_lock_irq(&mgmtm->hw->lock);
+
+	list_for_each(tmp, &mgmtm->active_q) {
+		io_req = (struct csio_ioreq *) tmp;
+		io_req->tmo -= min_t(uint32_t, io_req->tmo, ECM_MIN_TMO);
+
+		if (!io_req->tmo) {
+			/* Dequeue the request from retry Q. */
+			tmp = csio_list_prev(tmp);
+			list_del_init(&io_req->sm.sm_list);
+			if (io_req->io_cbfn) {
+				/* io_req will be freed by completion handler */
+				io_req->wr_status = -ETIMEDOUT;
+				io_req->io_cbfn(mgmtm->hw, io_req);
+			} else {
+				CSIO_DB_ASSERT(0);
+			}
+		}
+	}
+
+	/* If retry queue is not empty, re-arm timer */
+	if (!list_empty(&mgmtm->active_q))
+		mod_timer(&mgmtm->mgmt_timer,
+			  jiffies + msecs_to_jiffies(ECM_MIN_TMO));
+	spin_unlock_irq(&mgmtm->hw->lock);
+}
+
+static void
+csio_mgmtm_cleanup(struct csio_mgmtm *mgmtm)
+{
+	struct csio_hw *hw = mgmtm->hw;
+	struct csio_ioreq *io_req;
+	struct list_head *tmp;
+	uint32_t count;
+
+	count = 30;
+	/* Wait for all outstanding req to complete gracefully */
+	while ((!list_empty(&mgmtm->active_q)) && count--) {
+		spin_unlock_irq(&hw->lock);
+		msleep(2000);
+		spin_lock_irq(&hw->lock);
+	}
+
+	/* release outstanding req from ACTIVEQ */
+	list_for_each(tmp, &mgmtm->active_q) {
+		io_req = (struct csio_ioreq *) tmp;
+		tmp = csio_list_prev(tmp);
+		list_del_init(&io_req->sm.sm_list);
+		mgmtm->stats.n_active--;
+		if (io_req->io_cbfn) {
+			/* io_req will be freed by completion handler */
+			io_req->wr_status = -ETIMEDOUT;
+			io_req->io_cbfn(mgmtm->hw, io_req);
+		}
+	}
+}
+
+/*
+ * csio_mgmt_init - Mgmt module init entry point
+ * @mgmtsm - mgmt module
+ * @hw	 - HW module
+ *
+ * Initialize mgmt timer, resource wait queue, active queue,
+ * completion q. Allocate Egress and Ingress
+ * WR queues and save off the queue index returned by the WR
+ * module for future use. Allocate and save off mgmt reqs in the
+ * mgmt_req_freelist for future use. Make sure their SM is initialized
+ * to uninit state.
+ * Returns: 0 - on success
+ *          -ENOMEM   - on error.
+ */
+static int
+csio_mgmtm_init(struct csio_mgmtm *mgmtm, struct csio_hw *hw)
+{
+	struct timer_list *timer = &mgmtm->mgmt_timer;
+
+	init_timer(timer);
+	timer->function = csio_mgmt_tmo_handler;
+	timer->data = (unsigned long)mgmtm;
+
+	INIT_LIST_HEAD(&mgmtm->active_q);
+	INIT_LIST_HEAD(&mgmtm->cbfn_q);
+
+	mgmtm->hw = hw;
+	/*mgmtm->iq_idx = hw->fwevt_iq_idx;*/
+
+	return 0;
+}
+
+/*
+ * csio_mgmtm_exit - MGMT module exit entry point
+ * @mgmtsm - mgmt module
+ *
+ * This function called during MGMT module uninit.
+ * Stop timers, free ioreqs allocated.
+ * Returns: None
+ *
+ */
+static void
+csio_mgmtm_exit(struct csio_mgmtm *mgmtm)
+{
+	del_timer_sync(&mgmtm->mgmt_timer);
+}
+
+
+/**
+ * csio_hw_start - Kicks off the HW State machine
+ * @hw:		Pointer to HW module.
+ *
+ * It is assumed that the initialization is a synchronous operation.
+ * So when we return afer posting the event, the HW SM should be in
+ * the ready state, if there were no errors during init.
+ */
+int
+csio_hw_start(struct csio_hw *hw)
+{
+	spin_lock_irq(&hw->lock);
+	csio_post_event(&hw->sm, CSIO_HWE_CFG);
+	spin_unlock_irq(&hw->lock);
+
+	if (csio_is_hw_ready(hw))
+		return 0;
+	else
+		return -EINVAL;
+}
+
+int
+csio_hw_stop(struct csio_hw *hw)
+{
+	csio_post_event(&hw->sm, CSIO_HWE_PCI_REMOVE);
+
+	if (csio_is_hw_removing(hw))
+		return 0;
+	else
+		return -EINVAL;
+}
+
+/* Max reset retries */
+#define CSIO_MAX_RESET_RETRIES	3
+
+/**
+ * csio_hw_reset - Reset the hardware
+ * @hw:		HW module.
+ *
+ * Caller should hold lock across this function.
+ */
+int
+csio_hw_reset(struct csio_hw *hw)
+{
+	if (!csio_is_hw_master(hw))
+		return -EPERM;
+
+	if (hw->rst_retries >= CSIO_MAX_RESET_RETRIES) {
+		csio_dbg(hw, "Max hw reset attempts reached..");
+		return -EINVAL;
+	}
+
+	hw->rst_retries++;
+	csio_post_event(&hw->sm, CSIO_HWE_HBA_RESET);
+
+	if (csio_is_hw_ready(hw)) {
+		hw->rst_retries = 0;
+		hw->stats.n_reset_start = jiffies_to_msecs(jiffies);
+		return 0;
+	} else
+		return -EINVAL;
+}
+
+/*
+ * csio_hw_get_device_id - Caches the Adapter's vendor & device id.
+ * @hw: HW module.
+ */
+static void
+csio_hw_get_device_id(struct csio_hw *hw)
+{
+	/* Is the adapter device id cached already ?*/
+	if (csio_is_dev_id_cached(hw))
+		return;
+
+	/* Get the PCI vendor & device id */
+	pci_read_config_word(hw->pdev, PCI_VENDOR_ID,
+			     &hw->params.pci.vendor_id);
+	pci_read_config_word(hw->pdev, PCI_DEVICE_ID,
+			     &hw->params.pci.device_id);
+
+	csio_dev_id_cached(hw);
+
+} /* csio_hw_get_device_id */
+
+/*
+ * csio_hw_set_description - Set the model, description of the hw.
+ * @hw: HW module.
+ * @ven_id: PCI Vendor ID
+ * @dev_id: PCI Device ID
+ */
+static void
+csio_hw_set_description(struct csio_hw *hw, uint16_t ven_id, uint16_t dev_id)
+{
+	uint32_t adap_type, prot_type;
+
+	if (ven_id == CSIO_VENDOR_ID) {
+		prot_type = (dev_id & CSIO_ASIC_DEVID_PROTO_MASK);
+		adap_type = (dev_id & CSIO_ASIC_DEVID_TYPE_MASK);
+
+		if (prot_type == CSIO_FPGA) {
+			memcpy(hw->model_desc,
+				csio_fcoe_adapters[13].description, 32);
+		} else if (prot_type == CSIO_T4_FCOE_ASIC) {
+			memcpy(hw->hw_ver,
+			       csio_fcoe_adapters[adap_type].model_no, 16);
+			memcpy(hw->model_desc,
+				csio_fcoe_adapters[adap_type].description, 32);
+		} else {
+			char tempName[32] = "Chelsio FCoE Controller";
+			memcpy(hw->model_desc, tempName, 32);
+
+			CSIO_DB_ASSERT(0);
+		}
+	}
+} /* csio_hw_set_description */
+
+/**
+ * csio_hw_init - Initialize HW module.
+ * @hw:		Pointer to HW module.
+ *
+ * Initialize the members of the HW module.
+ */
+int
+csio_hw_init(struct csio_hw *hw)
+{
+	int rv = -EINVAL;
+	uint32_t i;
+	uint16_t ven_id, dev_id;
+	struct csio_evt_msg	*evt_entry;
+
+	INIT_LIST_HEAD(&hw->sm.sm_list);
+	csio_init_state(&hw->sm, csio_hws_uninit);
+	spin_lock_init(&hw->lock);
+	INIT_LIST_HEAD(&hw->sln_head);
+
+	/* Get the PCI vendor & device id */
+	csio_hw_get_device_id(hw);
+
+	strcpy(hw->name, CSIO_HW_NAME);
+
+	/* Set the model & its description */
+
+	ven_id = hw->params.pci.vendor_id;
+	dev_id = hw->params.pci.device_id;
+
+	csio_hw_set_description(hw, ven_id, dev_id);
+
+	/* Initialize default log level */
+	hw->params.log_level = (uint32_t) csio_dbg_level;
+
+	csio_set_fwevt_intr_idx(hw, -1);
+	csio_set_nondata_intr_idx(hw, -1);
+
+	/* Init all the modules: Mailbox, WorkRequest and Transport */
+	if (csio_mbm_init(csio_hw_to_mbm(hw), hw, csio_hw_mb_timer))
+		goto err;
+
+	rv = csio_wrm_init(csio_hw_to_wrm(hw), hw);
+	if (rv)
+		goto err_mbm_exit;
+
+	rv = csio_scsim_init(csio_hw_to_scsim(hw), hw);
+	if (rv)
+		goto err_wrm_exit;
+
+	rv = csio_mgmtm_init(csio_hw_to_mgmtm(hw), hw);
+	if (rv)
+		goto err_scsim_exit;
+	/* Pre-allocate evtq and initialize them */
+	INIT_LIST_HEAD(&hw->evt_active_q);
+	INIT_LIST_HEAD(&hw->evt_free_q);
+	for (i = 0; i < csio_evtq_sz; i++) {
+
+		evt_entry = kzalloc(sizeof(struct csio_evt_msg), GFP_KERNEL);
+		if (!evt_entry) {
+			csio_err(hw, "Failed to initialize eventq");
+			goto err_evtq_cleanup;
+		}
+
+		list_add_tail(&evt_entry->list, &hw->evt_free_q);
+		CSIO_INC_STATS(hw, n_evt_freeq);
+	}
+
+	hw->dev_num = dev_num;
+	dev_num++;
+
+	return 0;
+
+err_evtq_cleanup:
+	csio_evtq_cleanup(hw);
+	csio_mgmtm_exit(csio_hw_to_mgmtm(hw));
+err_scsim_exit:
+	csio_scsim_exit(csio_hw_to_scsim(hw));
+err_wrm_exit:
+	csio_wrm_exit(csio_hw_to_wrm(hw), hw);
+err_mbm_exit:
+	csio_mbm_exit(csio_hw_to_mbm(hw));
+err:
+	return rv;
+}
+
+/**
+ * csio_hw_exit - Un-initialize HW module.
+ * @hw:		Pointer to HW module.
+ *
+ */
+void
+csio_hw_exit(struct csio_hw *hw)
+{
+	csio_evtq_cleanup(hw);
+	csio_mgmtm_exit(csio_hw_to_mgmtm(hw));
+	csio_scsim_exit(csio_hw_to_scsim(hw));
+	csio_wrm_exit(csio_hw_to_wrm(hw), hw);
+	csio_mbm_exit(csio_hw_to_mbm(hw));
+}
diff --git a/drivers/scsi/csiostor/csio_hw.h b/drivers/scsi/csiostor/csio_hw.h
new file mode 100644
index 0000000..2a9b052
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_hw.h
@@ -0,0 +1,667 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_HW_H__
+#define __CSIO_HW_H__
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/compiler.h>
+#include <linux/cdev.h>
+#include <linux/list.h>
+#include <linux/mempool.h>
+#include <linux/io.h>
+#include <linux/spinlock_types.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include "csio_wr.h"
+#include "csio_mb.h"
+#include "csio_scsi.h"
+#include "csio_defs.h"
+#include "t4_regs.h"
+#include "t4_msg.h"
+
+/*
+ * An error value used by host. Should not clash with FW defined return values.
+ */
+#define	FW_HOSTERROR			255
+
+#define CSIO_FW_FNAME		"cxgb4/t4fw.bin"
+#define CSIO_CF_FNAME		"cxgb4/t4-config.txt"
+
+#define FW_VERSION_MAJOR	1
+#define FW_VERSION_MINOR	2
+#define FW_VERSION_MICRO	8
+
+#define CSIO_HW_NAME		"Chelsio FCoE Adapter"
+#define CSIO_MAX_PFN		8
+#define CSIO_MAX_PPORTS		4
+
+#define CSIO_MAX_LUN		0xFFFF
+#define CSIO_MAX_QUEUE		2048
+#define CSIO_MAX_CMD_PER_LUN	32
+#define CSIO_MAX_DDP_BUF_SIZE	(1024 * 1024)
+#define CSIO_MAX_SECTOR_SIZE	128
+
+/* Interrupts */
+#define CSIO_EXTRA_MSI_IQS	2	/* Extra iqs for INTX/MSI mode
+					 * (Forward intr iq + fw iq) */
+#define CSIO_EXTRA_VECS		2	/* non-data + FW evt */
+#define CSIO_MAX_SCSI_CPU	128
+#define CSIO_MAX_SCSI_QSETS	(CSIO_MAX_SCSI_CPU * CSIO_MAX_PPORTS)
+#define CSIO_MAX_MSIX_VECS	(CSIO_MAX_SCSI_QSETS + CSIO_EXTRA_VECS)
+
+/* Queues */
+enum {
+	CSIO_INTR_WRSIZE = 128,
+	CSIO_INTR_IQSIZE = ((CSIO_MAX_MSIX_VECS + 1) * CSIO_INTR_WRSIZE),
+	CSIO_FWEVT_WRSIZE = 128,
+	CSIO_FWEVT_IQLEN = 128,
+	CSIO_FWEVT_FLBUFS = 64,
+	CSIO_FWEVT_IQSIZE = (CSIO_FWEVT_WRSIZE * CSIO_FWEVT_IQLEN),
+	CSIO_HW_NIQ = 1,
+	CSIO_HW_NFLQ = 1,
+	CSIO_HW_NEQ = 1,
+	CSIO_HW_NINTXQ = 1,
+};
+
+struct csio_msix_entries {
+	unsigned short	vector;		/* Vector assigned by pci_enable_msix */
+	void		*dev_id;	/* Priv object associated w/ this msix*/
+	char		desc[24];	/* Description of this vector */
+};
+
+struct csio_scsi_qset {
+	int		iq_idx;		/* Ingress index */
+	int		eq_idx;		/* Egress index */
+	uint32_t	intr_idx;	/* MSIX Vector index */
+};
+
+struct csio_scsi_cpu_info {
+	int16_t	max_cpus;
+};
+
+extern int csio_dbg_level;
+extern int csio_force_master;
+extern unsigned int csio_port_mask;
+extern int csio_msi;
+
+#define CSIO_VENDOR_ID				0x1425
+#define CSIO_ASIC_DEVID_PROTO_MASK		0xFF00
+#define CSIO_ASIC_DEVID_TYPE_MASK		0x00FF
+#define CSIO_FPGA				0xA000
+#define CSIO_T4_FCOE_ASIC			0x4600
+
+#define CSIO_GLBL_INTR_MASK		(CIM | MPS | PL | PCIE | MC | EDC0 | \
+					 EDC1 | LE | TP | MA | PM_TX | PM_RX | \
+					 ULP_RX | CPL_SWITCH | SGE | \
+					 ULP_TX | SF)
+
+/*
+ * Hard parameters used to initialize the card in the absence of a
+ * configuration file.
+ */
+enum {
+	/* General */
+	CSIO_SGE_DBFIFO_INT_THRESH	= 10,
+
+	CSIO_SGE_RX_DMA_OFFSET		= 2,
+
+	CSIO_SGE_FLBUF_SIZE1		= 65536,
+	CSIO_SGE_FLBUF_SIZE2		= 1536,
+	CSIO_SGE_FLBUF_SIZE3		= 9024,
+	CSIO_SGE_FLBUF_SIZE4		= 9216,
+	CSIO_SGE_FLBUF_SIZE5		= 2048,
+	CSIO_SGE_FLBUF_SIZE6		= 128,
+	CSIO_SGE_FLBUF_SIZE7		= 8192,
+	CSIO_SGE_FLBUF_SIZE8		= 16384,
+
+	CSIO_SGE_TIMER_VAL_0		= 5,
+	CSIO_SGE_TIMER_VAL_1		= 10,
+	CSIO_SGE_TIMER_VAL_2		= 20,
+	CSIO_SGE_TIMER_VAL_3		= 50,
+	CSIO_SGE_TIMER_VAL_4		= 100,
+	CSIO_SGE_TIMER_VAL_5		= 200,
+
+	CSIO_SGE_INT_CNT_VAL_0		= 1,
+	CSIO_SGE_INT_CNT_VAL_1		= 4,
+	CSIO_SGE_INT_CNT_VAL_2		= 8,
+	CSIO_SGE_INT_CNT_VAL_3		= 16,
+
+	/* Storage specific - used by FW_PFVF_CMD */
+	CSIO_WX_CAPS			= FW_CMD_CAP_PF, /* w/x all */
+	CSIO_R_CAPS			= FW_CMD_CAP_PF, /* r all */
+	CSIO_NVI			= 4,
+	CSIO_NIQ_FLINT			= 34,
+	CSIO_NETH_CTRL			= 32,
+	CSIO_NEQ			= 66,
+	CSIO_NEXACTF			= 32,
+	CSIO_CMASK			= FW_PFVF_CMD_CMASK_MASK,
+	CSIO_PMASK			= FW_PFVF_CMD_PMASK_MASK,
+};
+
+/* Slowpath events */
+enum csio_evt {
+	CSIO_EVT_FW  = 0,	/* FW event */
+	CSIO_EVT_MBX,		/* MBX event */
+	CSIO_EVT_SCN,		/* State change notification */
+	CSIO_EVT_DEV_LOSS,	/* Device loss event */
+	CSIO_EVT_MAX,		/* Max supported event */
+};
+
+#define CSIO_EVT_MSG_SIZE	512
+#define CSIO_EVTQ_SIZE		512
+
+/* Event msg  */
+struct csio_evt_msg {
+	struct list_head	list;	/* evt queue*/
+	enum csio_evt		type;
+	uint8_t			data[CSIO_EVT_MSG_SIZE];
+};
+
+enum {
+	EEPROMVSIZE    = 32768, /* Serial EEPROM virtual address space size */
+	SERNUM_LEN     = 16,    /* Serial # length */
+	EC_LEN         = 16,    /* E/C length */
+	ID_LEN         = 16,    /* ID length */
+	TRACE_LEN      = 112,   /* length of trace data and mask */
+};
+
+enum {
+	SF_PAGE_SIZE = 256,           /* serial flash page size */
+	SF_SEC_SIZE = 64 * 1024,      /* serial flash sector size */
+	SF_SIZE = SF_SEC_SIZE * 16,   /* serial flash size */
+};
+
+enum { MEM_EDC0, MEM_EDC1, MEM_MC };
+
+enum {
+	MEMWIN0_APERTURE = 2048,
+	MEMWIN0_BASE     = 0x1b800,
+	MEMWIN1_APERTURE = 32768,
+	MEMWIN1_BASE     = 0x28000,
+	MEMWIN2_APERTURE = 65536,
+	MEMWIN2_BASE     = 0x30000,
+};
+
+/* serial flash and firmware constants */
+enum {
+	SF_ATTEMPTS = 10,             /* max retries for SF operations */
+
+	/* flash command opcodes */
+	SF_PROG_PAGE    = 2,          /* program page */
+	SF_WR_DISABLE   = 4,          /* disable writes */
+	SF_RD_STATUS    = 5,          /* read status register */
+	SF_WR_ENABLE    = 6,          /* enable writes */
+	SF_RD_DATA_FAST = 0xb,        /* read flash */
+	SF_RD_ID	= 0x9f,	      /* read ID */
+	SF_ERASE_SECTOR = 0xd8,       /* erase sector */
+
+	FW_START_SEC = 8,             /* first flash sector for FW */
+	FW_END_SEC = 15,              /* last flash sector for FW */
+	FW_IMG_START = FW_START_SEC * SF_SEC_SIZE,
+	FW_MAX_SIZE = (FW_END_SEC - FW_START_SEC + 1) * SF_SEC_SIZE,
+
+	FLASH_CFG_MAX_SIZE    = 0x10000 , /* max size of the flash config file*/
+	FLASH_CFG_OFFSET      = 0x1f0000,
+	FLASH_CFG_START_SEC   = FLASH_CFG_OFFSET / SF_SEC_SIZE,
+	FPGA_FLASH_CFG_OFFSET = 0xf0000 , /* if FPGA mode, then cfg file is
+					   * at 1MB - 64KB */
+	FPGA_FLASH_CFG_START_SEC  = FPGA_FLASH_CFG_OFFSET / SF_SEC_SIZE,
+};
+
+/*
+ * Flash layout.
+ */
+#define FLASH_START(start)	((start) * SF_SEC_SIZE)
+#define FLASH_MAX_SIZE(nsecs)	((nsecs) * SF_SEC_SIZE)
+
+enum {
+	/*
+	 * Location of firmware image in FLASH.
+	 */
+	FLASH_FW_START_SEC = 8,
+	FLASH_FW_NSECS = 8,
+	FLASH_FW_START = FLASH_START(FLASH_FW_START_SEC),
+	FLASH_FW_MAX_SIZE = FLASH_MAX_SIZE(FLASH_FW_NSECS),
+
+};
+
+#undef FLASH_START
+#undef FLASH_MAX_SIZE
+
+/* Management module */
+enum {
+	CSIO_MGMT_EQ_WRSIZE = 512,
+	CSIO_MGMT_IQ_WRSIZE = 128,
+	CSIO_MGMT_EQLEN = 64,
+	CSIO_MGMT_IQLEN = 64,
+};
+
+#define CSIO_MGMT_EQSIZE	(CSIO_MGMT_EQLEN * CSIO_MGMT_EQ_WRSIZE)
+#define CSIO_MGMT_IQSIZE	(CSIO_MGMT_IQLEN * CSIO_MGMT_IQ_WRSIZE)
+
+/* mgmt module stats */
+struct csio_mgmtm_stats {
+	uint32_t	n_abort_req;		/* Total abort request */
+	uint32_t	n_abort_rsp;		/* Total abort response */
+	uint32_t	n_close_req;		/* Total close request */
+	uint32_t	n_close_rsp;		/* Total close response */
+	uint32_t	n_err;			/* Total Errors */
+	uint32_t	n_drop;			/* Total request dropped */
+	uint32_t	n_active;		/* Count of active_q */
+	uint32_t	n_cbfn;			/* Count of cbfn_q */
+};
+
+/* MGMT module */
+struct csio_mgmtm {
+	struct	csio_hw		*hw;		/* Pointer to HW moduel */
+	int			eq_idx;		/* Egress queue index */
+	int			iq_idx;		/* Ingress queue index */
+	int			msi_vec;	/* MSI vector */
+	struct list_head	active_q;	/* Outstanding ELS/CT */
+	struct list_head	abort_q;	/* Outstanding abort req */
+	struct list_head	cbfn_q;		/* Completion queue */
+	struct list_head	mgmt_req_freelist; /* Free poll of reqs */
+						/* ELSCT request freelist*/
+	struct timer_list	mgmt_timer;	/* MGMT timer */
+	struct csio_mgmtm_stats stats;		/* ELS/CT stats */
+};
+
+struct csio_adap_desc {
+	char model_no[16];
+	char description[32];
+};
+
+struct pci_params {
+	uint16_t   vendor_id;
+	uint16_t   device_id;
+	uint32_t   vpd_cap_addr;
+	uint16_t   speed;
+	uint8_t    width;
+};
+
+/* User configurable hw parameters */
+struct csio_hw_params {
+	uint32_t		sf_size;		/* serial flash
+							 * size in bytes
+							 */
+	uint32_t		sf_nsec;		/* # of flash sectors */
+	struct pci_params	pci;
+	uint32_t		log_level;		/* Module-level for
+							 * debug log.
+							 */
+};
+
+struct csio_vpd {
+	uint32_t cclk;
+	uint8_t ec[EC_LEN + 1];
+	uint8_t sn[SERNUM_LEN + 1];
+	uint8_t id[ID_LEN + 1];
+};
+
+struct csio_pport {
+	uint16_t	pcap;
+	uint8_t		portid;
+	uint8_t		link_status;
+	uint16_t	link_speed;
+	uint8_t		mac[6];
+	uint8_t		mod_type;
+	uint8_t		rsvd1;
+	uint8_t		rsvd2;
+	uint8_t		rsvd3;
+};
+
+/* fcoe resource information */
+struct csio_fcoe_res_info {
+	uint16_t	e_d_tov;
+	uint16_t	r_a_tov_seq;
+	uint16_t	r_a_tov_els;
+	uint16_t	r_r_tov;
+	uint32_t	max_xchgs;
+	uint32_t	max_ssns;
+	uint32_t	used_xchgs;
+	uint32_t	used_ssns;
+	uint32_t	max_fcfs;
+	uint32_t	max_vnps;
+	uint32_t	used_fcfs;
+	uint32_t	used_vnps;
+};
+
+/* HW State machine Events */
+enum csio_hw_ev {
+	CSIO_HWE_CFG = (uint32_t)1, /* Starts off the State machine */
+	CSIO_HWE_INIT,	         /* Config done, start Init      */
+	CSIO_HWE_INIT_DONE,      /* Init Mailboxes sent, HW ready */
+	CSIO_HWE_FATAL,		 /* Fatal error during initialization */
+	CSIO_HWE_PCIERR_DETECTED,/* PCI error recovery detetced */
+	CSIO_HWE_PCIERR_SLOT_RESET, /* Slot reset after PCI recoviery */
+	CSIO_HWE_PCIERR_RESUME,  /* Resume after PCI error recovery */
+	CSIO_HWE_QUIESCED,	 /* HBA quiesced */
+	CSIO_HWE_HBA_RESET,      /* HBA reset requested */
+	CSIO_HWE_HBA_RESET_DONE, /* HBA reset completed */
+	CSIO_HWE_FW_DLOAD,       /* FW download requested */
+	CSIO_HWE_PCI_REMOVE,     /* PCI de-instantiation */
+	CSIO_HWE_SUSPEND,        /* HW suspend for Online(hot) replacement */
+	CSIO_HWE_RESUME,         /* HW resume for Online(hot) replacement */
+	CSIO_HWE_MAX,		 /* Max HW event */
+};
+
+/* hw stats */
+struct csio_hw_stats {
+	uint32_t	n_evt_activeq;	/* Number of event in active Q */
+	uint32_t	n_evt_freeq;	/* Number of event in free Q */
+	uint32_t	n_evt_drop;	/* Number of event droped */
+	uint32_t	n_evt_unexp;	/* Number of unexpected events */
+	uint32_t	n_pcich_offline;/* Number of pci channel offline */
+	uint32_t	n_lnlkup_miss;  /* Number of lnode lookup miss */
+	uint32_t	n_cpl_fw6_msg;	/* Number of cpl fw6 message*/
+	uint32_t	n_cpl_fw6_pld;	/* Number of cpl fw6 payload*/
+	uint32_t	n_cpl_unexp;	/* Number of unexpected cpl */
+	uint32_t	n_mbint_unexp;	/* Number of unexpected mbox */
+					/* interrupt */
+	uint32_t	n_plint_unexp;	/* Number of unexpected PL */
+					/* interrupt */
+	uint32_t	n_plint_cnt;	/* Number of PL interrupt */
+	uint32_t	n_int_stray;	/* Number of stray interrupt */
+	uint32_t	n_err;		/* Number of hw errors */
+	uint32_t	n_err_fatal;	/* Number of fatal errors */
+	uint32_t	n_err_nomem;	/* Number of memory alloc failure */
+	uint32_t	n_err_io;	/* Number of IO failure */
+	enum csio_hw_ev	n_evt_sm[CSIO_HWE_MAX];	/* Number of sm events */
+	uint64_t	n_reset_start;  /* Start time after the reset */
+	uint32_t	rsvd1;
+};
+
+/* Defines for hw->flags */
+#define CSIO_HWF_MASTER			0x00000001	/* This is the Master
+							 * function for the
+							 * card.
+							 */
+#define	CSIO_HWF_HW_INTR_ENABLED	0x00000002	/* Are HW Interrupt
+							 * enable bit set?
+							 */
+#define	CSIO_HWF_FWEVT_PENDING		0x00000004	/* FW events pending */
+#define	CSIO_HWF_Q_MEM_ALLOCED		0x00000008	/* Queues have been
+							 * allocated memory.
+							 */
+#define	CSIO_HWF_Q_FW_ALLOCED		0x00000010	/* Queues have been
+							 * allocated in FW.
+							 */
+#define CSIO_HWF_VPD_VALID		0x00000020	/* Valid VPD copied */
+#define CSIO_HWF_DEVID_CACHED		0X00000040	/* PCI vendor & device
+							 * id cached */
+#define	CSIO_HWF_FWEVT_STOP		0x00000080	/* Stop processing
+							 * FW events
+							 */
+#define CSIO_HWF_USING_SOFT_PARAMS	0x00000100      /* Using FW config
+							 * params
+							 */
+#define	CSIO_HWF_HOST_INTR_ENABLED	0x00000200	/* Are host interrupts
+							 * enabled?
+							 */
+
+#define csio_is_hw_intr_enabled(__hw)	\
+				((__hw)->flags & CSIO_HWF_HW_INTR_ENABLED)
+#define csio_is_host_intr_enabled(__hw)	\
+				((__hw)->flags & CSIO_HWF_HOST_INTR_ENABLED)
+#define csio_is_hw_master(__hw)		((__hw)->flags & CSIO_HWF_MASTER)
+#define csio_is_valid_vpd(__hw)		((__hw)->flags & CSIO_HWF_VPD_VALID)
+#define csio_is_dev_id_cached(__hw)	((__hw)->flags & CSIO_HWF_DEVID_CACHED)
+#define csio_valid_vpd_copied(__hw)	((__hw)->flags |= CSIO_HWF_VPD_VALID)
+#define csio_dev_id_cached(__hw)	((__hw)->flags |= CSIO_HWF_DEVID_CACHED)
+
+/* Defines for intr_mode */
+enum csio_intr_mode {
+	CSIO_IM_NONE = 0,
+	CSIO_IM_INTX = 1,
+	CSIO_IM_MSI  = 2,
+	CSIO_IM_MSIX = 3,
+};
+
+/* Master HW structure: One per function */
+struct csio_hw {
+	struct csio_sm		sm;			/* State machine: should
+							 * be the 1st member.
+							 */
+	spinlock_t		lock;			/* Lock for hw */
+
+	struct csio_scsim	scsim;			/* SCSI module*/
+	struct csio_wrm		wrm;			/* Work request module*/
+	struct pci_dev		*pdev;			/* PCI device */
+
+	void __iomem		*regstart;		/* Virtual address of
+							 * register map
+							 */
+	/* SCSI queue sets */
+	uint32_t		num_sqsets;		/* Number of SCSI
+							 * queue sets */
+	uint32_t		num_scsi_msix_cpus;	/* Number of CPUs that
+							 * will be used
+							 * for ingress
+							 * processing.
+							 */
+
+	struct csio_scsi_qset	sqset[CSIO_MAX_PPORTS][CSIO_MAX_SCSI_CPU];
+	struct csio_scsi_cpu_info scsi_cpu_info[CSIO_MAX_PPORTS];
+
+	uint32_t		evtflag;		/* Event flag  */
+	uint32_t		flags;			/* HW flags */
+
+	struct csio_mgmtm	mgmtm;			/* management module */
+	struct csio_mbm		mbm;			/* Mailbox module */
+
+	/* Lnodes */
+	uint32_t		num_lns;		/* Number of lnodes */
+	struct csio_lnode	*rln;			/* Root lnode */
+	struct list_head	sln_head;		/* Sibling node list
+							 * list
+							 */
+	int			intr_iq_idx;		/* Forward interrupt
+							 * queue.
+							 */
+	int			fwevt_iq_idx;		/* FW evt queue */
+	struct work_struct	evtq_work;		/* Worker thread for
+							 * HW events.
+							 */
+	struct list_head	evt_free_q;		/* freelist of evt
+							 * elements
+							 */
+	struct list_head	evt_active_q;		/* active evt queue*/
+
+	/* board related info */
+	char			name[32];
+	char			hw_ver[16];
+	char			model_desc[32];
+	char			drv_version[32];
+	char			fwrev_str[32];
+	uint32_t		optrom_ver;
+	uint32_t		fwrev;
+	uint32_t		tp_vers;
+	char			chip_ver;
+	uint32_t		cfg_finiver;
+	uint32_t		cfg_finicsum;
+	uint32_t		cfg_cfcsum;
+	uint8_t			cfg_csum_status;
+	uint8_t			cfg_store;
+	enum csio_dev_state	fw_state;
+	struct csio_vpd		vpd;
+
+	uint8_t			pfn;			/* Physical Function
+							 * number
+							 */
+	uint32_t		port_vec;		/* Port vector */
+	uint8_t			num_pports;		/* Number of physical
+							 * ports.
+							 */
+	uint8_t			rst_retries;		/* Reset retries */
+	uint8_t			cur_evt;		/* current s/m evt */
+	uint8_t			prev_evt;		/* Previous s/m evt */
+	uint32_t		dev_num;		/* device number */
+	struct csio_pport	pport[CSIO_MAX_PPORTS];	/* Ports (XGMACs) */
+	struct csio_hw_params	params;			/* Hw parameters */
+
+	struct pci_pool		*scsi_pci_pool;		/* PCI pool for SCSI */
+	mempool_t		*mb_mempool;		/* Mailbox memory pool*/
+	mempool_t		*rnode_mempool;		/* rnode memory pool */
+
+	/* Interrupt */
+	enum csio_intr_mode	intr_mode;		/* INTx, MSI, MSIX */
+	uint32_t		fwevt_intr_idx;		/* FW evt MSIX/interrupt
+							 * index
+							 */
+	uint32_t		nondata_intr_idx;	/* nondata MSIX/intr
+							 * idx
+							 */
+
+	uint8_t			cfg_neq;		/* FW configured no of
+							 * egress queues
+							 */
+	uint8_t			cfg_niq;		/* FW configured no of
+							 * iq queues.
+							 */
+
+	struct csio_fcoe_res_info  fres_info;		/* Fcoe resource info */
+
+	/* MSIX vectors */
+	struct csio_msix_entries msix_entries[CSIO_MAX_MSIX_VECS];
+
+	struct dentry		*debugfs_root;		/* Debug FS */
+	struct csio_hw_stats	stats;			/* Hw statistics */
+};
+
+/* Register access macros */
+#define csio_reg(_b, _r)		((_b) + (_r))
+
+#define	csio_rd_reg8(_h, _r)		readb(csio_reg((_h)->regstart, (_r)))
+#define	csio_rd_reg16(_h, _r)		readw(csio_reg((_h)->regstart, (_r)))
+#define	csio_rd_reg32(_h, _r)		readl(csio_reg((_h)->regstart, (_r)))
+#define	csio_rd_reg64(_h, _r)		readq(csio_reg((_h)->regstart, (_r)))
+
+#define	csio_wr_reg8(_h, _v, _r)	writeb((_v), \
+						csio_reg((_h)->regstart, (_r)))
+#define	csio_wr_reg16(_h, _v, _r)	writew((_v), \
+						csio_reg((_h)->regstart, (_r)))
+#define	csio_wr_reg32(_h, _v, _r)	writel((_v), \
+						csio_reg((_h)->regstart, (_r)))
+#define	csio_wr_reg64(_h, _v, _r)	writeq((_v), \
+						csio_reg((_h)->regstart, (_r)))
+
+void csio_set_reg_field(struct csio_hw *, uint32_t, uint32_t, uint32_t);
+
+/* Core clocks <==> uSecs */
+static inline uint32_t
+csio_core_ticks_to_us(struct csio_hw *hw, uint32_t ticks)
+{
+	/* add Core Clock / 2 to round ticks to nearest uS */
+	return (ticks * 1000 + hw->vpd.cclk/2) / hw->vpd.cclk;
+}
+
+static inline uint32_t
+csio_us_to_core_ticks(struct csio_hw *hw, uint32_t us)
+{
+	return (us * hw->vpd.cclk) / 1000;
+}
+
+/* Easy access macros */
+#define csio_hw_to_wrm(hw)		((struct csio_wrm *)(&(hw)->wrm))
+#define csio_hw_to_mbm(hw)		((struct csio_mbm *)(&(hw)->mbm))
+#define csio_hw_to_scsim(hw)		((struct csio_scsim *)(&(hw)->scsim))
+#define csio_hw_to_mgmtm(hw)		((struct csio_mgmtm *)(&(hw)->mgmtm))
+
+#define CSIO_PCI_BUS(hw)		((hw)->pdev->bus->number)
+#define CSIO_PCI_DEV(hw)		(PCI_SLOT((hw)->pdev->devfn))
+#define CSIO_PCI_FUNC(hw)		(PCI_FUNC((hw)->pdev->devfn))
+
+#define csio_set_fwevt_intr_idx(_h, _i)		((_h)->fwevt_intr_idx = (_i))
+#define csio_get_fwevt_intr_idx(_h)		((_h)->fwevt_intr_idx)
+#define csio_set_nondata_intr_idx(_h, _i)	((_h)->nondata_intr_idx = (_i))
+#define csio_get_nondata_intr_idx(_h)		((_h)->nondata_intr_idx)
+
+/* Printing/logging */
+#define CSIO_DEVID(__dev)		((__dev)->dev_num)
+#define CSIO_DEVID_LO(__dev)		(CSIO_DEVID((__dev)) & 0xFFFF)
+#define CSIO_DEVID_HI(__dev)		((CSIO_DEVID((__dev)) >> 16) & 0xFFFF)
+
+#define csio_info(__hw, __fmt, ...)					\
+			dev_info(&(__hw)->pdev->dev, __fmt, ##__VA_ARGS__)
+
+#define csio_fatal(__hw, __fmt, ...)					\
+			dev_crit(&(__hw)->pdev->dev, __fmt, ##__VA_ARGS__)
+
+#define csio_err(__hw, __fmt, ...)					\
+			dev_err(&(__hw)->pdev->dev, __fmt, ##__VA_ARGS__)
+
+#define csio_warn(__hw, __fmt, ...)					\
+			dev_warn(&(__hw)->pdev->dev, __fmt, ##__VA_ARGS__)
+
+#ifdef __CSIO_DEBUG__
+#define csio_dbg(__hw, __fmt, ...)					\
+			csio_info((__hw), __fmt, ##__VA_ARGS__);
+#else
+#define csio_dbg(__hw, __fmt, ...)
+#endif
+
+int csio_mgmt_req_lookup(struct csio_mgmtm *, struct csio_ioreq *);
+void csio_hw_intr_disable(struct csio_hw *);
+int csio_hw_slow_intr_handler(struct csio_hw *hw);
+int csio_hw_start(struct csio_hw *);
+int csio_hw_stop(struct csio_hw *);
+int csio_hw_reset(struct csio_hw *);
+int csio_is_hw_ready(struct csio_hw *);
+int csio_is_hw_removing(struct csio_hw *);
+
+int csio_fwevtq_handler(struct csio_hw *);
+void csio_evtq_worker(struct work_struct *);
+int csio_enqueue_evt(struct csio_hw *hw, enum csio_evt type,
+				void *evt_msg, uint16_t len);
+void csio_evtq_flush(struct csio_hw *hw);
+
+int csio_request_irqs(struct csio_hw *);
+void csio_intr_enable(struct csio_hw *);
+void csio_intr_disable(struct csio_hw *, bool);
+
+struct csio_lnode *csio_lnode_alloc(struct csio_hw *);
+int csio_config_queues(struct csio_hw *);
+
+int csio_hw_mc_read(struct csio_hw *, uint32_t,
+			      uint32_t *, uint64_t *);
+int csio_hw_edc_read(struct csio_hw *, int, uint32_t, uint32_t *,
+			       uint64_t *);
+int csio_hw_init(struct csio_hw *);
+void csio_hw_exit(struct csio_hw *);
+#endif /* ifndef __CSIO_HW_H__ */
diff --git a/drivers/scsi/csiostor/csio_init.c b/drivers/scsi/csiostor/csio_init.c
new file mode 100644
index 0000000..fdd408f
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_init.c
@@ -0,0 +1,1274 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/aer.h>
+#include <linux/mm.h>
+#include <linux/notifier.h>
+#include <linux/kdebug.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/string.h>
+#include <linux/export.h>
+
+#include "csio_init.h"
+#include "csio_defs.h"
+
+#define CSIO_MIN_MEMPOOL_SZ	64
+
+static struct dentry *csio_debugfs_root;
+
+static struct scsi_transport_template *csio_fcoe_transport;
+static struct scsi_transport_template *csio_fcoe_transport_vport;
+
+/*
+ * debugfs support
+ */
+static int
+csio_mem_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t
+csio_mem_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+	loff_t pos = *ppos;
+	loff_t avail = file->f_path.dentry->d_inode->i_size;
+	unsigned int mem = (uintptr_t)file->private_data & 3;
+	struct csio_hw *hw = file->private_data - mem;
+
+	if (pos < 0)
+		return -EINVAL;
+	if (pos >= avail)
+		return 0;
+	if (count > avail - pos)
+		count = avail - pos;
+
+	while (count) {
+		size_t len;
+		int ret, ofst;
+		__be32 data[16];
+
+		if (mem == MEM_MC)
+			ret = csio_hw_mc_read(hw, pos, data, NULL);
+		else
+			ret = csio_hw_edc_read(hw, mem, pos, data, NULL);
+		if (ret)
+			return ret;
+
+		ofst = pos % sizeof(data);
+		len = min(count, sizeof(data) - ofst);
+		if (copy_to_user(buf, (u8 *)data + ofst, len))
+			return -EFAULT;
+
+		buf += len;
+		pos += len;
+		count -= len;
+	}
+	count = pos - *ppos;
+	*ppos = pos;
+	return count;
+}
+
+static const struct file_operations csio_mem_debugfs_fops = {
+	.owner   = THIS_MODULE,
+	.open    = csio_mem_open,
+	.read    = csio_mem_read,
+	.llseek  = default_llseek,
+};
+
+static void __devinit
+csio_add_debugfs_mem(struct csio_hw *hw, const char *name,
+		     unsigned int idx, unsigned int size_mb)
+{
+	struct dentry *de;
+
+	de = debugfs_create_file(name, S_IRUSR, hw->debugfs_root,
+				 (void *)hw + idx, &csio_mem_debugfs_fops);
+	if (de && de->d_inode)
+		de->d_inode->i_size = size_mb << 20;
+}
+
+static int __devinit
+csio_setup_debugfs(struct csio_hw *hw)
+{
+	int i;
+
+	if (IS_ERR_OR_NULL(hw->debugfs_root))
+		return -1;
+
+	i = csio_rd_reg32(hw, MA_TARGET_MEM_ENABLE);
+	if (i & EDRAM0_ENABLE)
+		csio_add_debugfs_mem(hw, "edc0", MEM_EDC0, 5);
+	if (i & EDRAM1_ENABLE)
+		csio_add_debugfs_mem(hw, "edc1", MEM_EDC1, 5);
+	if (i & EXT_MEM_ENABLE)
+		csio_add_debugfs_mem(hw, "mc", MEM_MC,
+		      EXT_MEM_SIZE_GET(csio_rd_reg32(hw, MA_EXT_MEMORY_BAR)));
+	return 0;
+}
+
+/*
+ * csio_dfs_create - Creates and sets up per-hw debugfs.
+ *
+ */
+static int
+csio_dfs_create(struct csio_hw *hw)
+{
+	if (csio_debugfs_root) {
+		hw->debugfs_root = debugfs_create_dir(pci_name(hw->pdev),
+							csio_debugfs_root);
+		csio_setup_debugfs(hw);
+	}
+
+	return 0;
+}
+
+/*
+ * csio_dfs_destroy - Destroys per-hw debugfs.
+ */
+static int
+csio_dfs_destroy(struct csio_hw *hw)
+{
+	if (hw->debugfs_root)
+		debugfs_remove_recursive(hw->debugfs_root);
+
+	return 0;
+}
+
+/*
+ * csio_dfs_init - Debug filesystem initialization for the module.
+ *
+ */
+static int
+csio_dfs_init(void)
+{
+	csio_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
+	if (!csio_debugfs_root)
+		pr_warn("Could not create debugfs entry, continuing\n");
+
+	return 0;
+}
+
+/*
+ * csio_dfs_exit - debugfs cleanup for the module.
+ */
+static void
+csio_dfs_exit(void)
+{
+	debugfs_remove(csio_debugfs_root);
+}
+
+/*
+ * csio_pci_init - PCI initialization.
+ * @pdev: PCI device.
+ * @bars: Bitmask of bars to be requested.
+ *
+ * Initializes the PCI function by enabling MMIO, setting bus
+ * mastership and setting DMA mask.
+ */
+static int
+csio_pci_init(struct pci_dev *pdev, int *bars)
+{
+	int rv = -ENODEV;
+
+	*bars = pci_select_bars(pdev, IORESOURCE_MEM);
+
+	if (pci_enable_device_mem(pdev))
+		goto err;
+
+	if (pci_request_selected_regions(pdev, *bars, KBUILD_MODNAME))
+		goto err_disable_device;
+
+	pci_set_master(pdev);
+	pci_try_set_mwi(pdev);
+
+	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+	} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+	} else {
+		dev_err(&pdev->dev, "No suitable DMA available.\n");
+		goto err_release_regions;
+	}
+
+	return 0;
+
+err_release_regions:
+	pci_release_selected_regions(pdev, *bars);
+err_disable_device:
+	pci_disable_device(pdev);
+err:
+	return rv;
+
+}
+
+/*
+ * csio_pci_exit - PCI unitialization.
+ * @pdev: PCI device.
+ * @bars: Bars to be released.
+ *
+ */
+static void
+csio_pci_exit(struct pci_dev *pdev, int *bars)
+{
+	pci_release_selected_regions(pdev, *bars);
+	pci_disable_device(pdev);
+}
+
+/*
+ * csio_hw_init_workers - Initialize the HW module's worker threads.
+ * @hw: HW module.
+ *
+ */
+static void
+csio_hw_init_workers(struct csio_hw *hw)
+{
+	INIT_WORK(&hw->evtq_work, csio_evtq_worker);
+}
+
+static void
+csio_hw_exit_workers(struct csio_hw *hw)
+{
+	cancel_work_sync(&hw->evtq_work);
+	flush_scheduled_work();
+}
+
+static int
+csio_create_queues(struct csio_hw *hw)
+{
+	int i, j;
+	struct csio_mgmtm *mgmtm = csio_hw_to_mgmtm(hw);
+	int rv;
+	struct csio_scsi_cpu_info *info;
+
+	if (hw->flags & CSIO_HWF_Q_FW_ALLOCED)
+		return 0;
+
+	if (hw->intr_mode != CSIO_IM_MSIX) {
+		rv = csio_wr_iq_create(hw, NULL, hw->intr_iq_idx,
+					0, hw->pport[0].portid, false, NULL);
+		if (rv != 0) {
+			csio_err(hw, " Forward Interrupt IQ failed!: %d\n", rv);
+			return rv;
+		}
+	}
+
+	/* FW event queue */
+	rv = csio_wr_iq_create(hw, NULL, hw->fwevt_iq_idx,
+			       csio_get_fwevt_intr_idx(hw),
+			       hw->pport[0].portid, true, NULL);
+	if (rv != 0) {
+		csio_err(hw, "FW event IQ config failed!: %d\n", rv);
+		return rv;
+	}
+
+	/* Create mgmt queue */
+	rv = csio_wr_eq_create(hw, NULL, mgmtm->eq_idx,
+			mgmtm->iq_idx, hw->pport[0].portid, NULL);
+
+	if (rv != 0) {
+		csio_err(hw, "Mgmt EQ create failed!: %d\n", rv);
+		goto err;
+	}
+
+	/* Create SCSI queues */
+	for (i = 0; i < hw->num_pports; i++) {
+		info = &hw->scsi_cpu_info[i];
+
+		for (j = 0; j < info->max_cpus; j++) {
+			struct csio_scsi_qset *sqset = &hw->sqset[i][j];
+
+			rv = csio_wr_iq_create(hw, NULL, sqset->iq_idx,
+					       sqset->intr_idx, i, false, NULL);
+			if (rv != 0) {
+				csio_err(hw,
+				   "SCSI module IQ config failed [%d][%d]:%d\n",
+				   i, j, rv);
+				goto err;
+			}
+			rv = csio_wr_eq_create(hw, NULL, sqset->eq_idx,
+					       sqset->iq_idx, i, NULL);
+			if (rv != 0) {
+				csio_err(hw,
+				   "SCSI module EQ config failed [%d][%d]:%d\n",
+				   i, j, rv);
+				goto err;
+			}
+		} /* for all CPUs */
+	} /* For all ports */
+
+	hw->flags |= CSIO_HWF_Q_FW_ALLOCED;
+	return 0;
+err:
+	csio_wr_destroy_queues(hw, true);
+	return -EINVAL;
+}
+
+/*
+ * csio_config_queues - Configure the DMA queues.
+ * @hw: HW module.
+ *
+ * Allocates memory for queues are registers them with FW.
+ */
+int
+csio_config_queues(struct csio_hw *hw)
+{
+	int i, j, idx, k = 0;
+	int rv;
+	struct csio_scsi_qset *sqset;
+	struct csio_mgmtm *mgmtm = csio_hw_to_mgmtm(hw);
+	struct csio_scsi_qset *orig;
+	struct csio_scsi_cpu_info *info;
+
+	if (hw->flags & CSIO_HWF_Q_MEM_ALLOCED)
+		return csio_create_queues(hw);
+
+	/* Calculate number of SCSI queues for MSIX we would like */
+	hw->num_scsi_msix_cpus = num_online_cpus();
+	hw->num_sqsets = num_online_cpus() * hw->num_pports;
+
+	if (hw->num_sqsets > CSIO_MAX_SCSI_QSETS) {
+		hw->num_sqsets = CSIO_MAX_SCSI_QSETS;
+		hw->num_scsi_msix_cpus = CSIO_MAX_SCSI_CPU;
+	}
+
+	/* Initialize max_cpus, may get reduced during msix allocations */
+	for (i = 0; i < hw->num_pports; i++)
+		hw->scsi_cpu_info[i].max_cpus = hw->num_scsi_msix_cpus;
+
+	csio_dbg(hw, "nsqsets:%d scpus:%d\n",
+		    hw->num_sqsets, hw->num_scsi_msix_cpus);
+
+	csio_intr_enable(hw);
+
+	if (hw->intr_mode != CSIO_IM_MSIX) {
+
+		/* Allocate Forward interrupt iq. */
+		hw->intr_iq_idx = csio_wr_alloc_q(hw, CSIO_INTR_IQSIZE,
+						CSIO_INTR_WRSIZE, CSIO_INGRESS,
+						(void *)hw, 0, 0, NULL);
+		if (hw->intr_iq_idx == -1) {
+			csio_err(hw,
+				 "Forward interrupt queue creation failed\n");
+			goto intr_disable;
+		}
+	}
+
+	/* Allocate the FW evt queue */
+	hw->fwevt_iq_idx = csio_wr_alloc_q(hw, CSIO_FWEVT_IQSIZE,
+					   CSIO_FWEVT_WRSIZE,
+					   CSIO_INGRESS, (void *)hw,
+					   CSIO_FWEVT_FLBUFS, 0,
+					   csio_fwevt_intx_handler);
+	if (hw->fwevt_iq_idx == -1) {
+		csio_err(hw, "FW evt queue creation failed\n");
+		goto intr_disable;
+	}
+
+	/* Allocate the mgmt queue */
+	mgmtm->eq_idx = csio_wr_alloc_q(hw, CSIO_MGMT_EQSIZE,
+				      CSIO_MGMT_EQ_WRSIZE,
+				      CSIO_EGRESS, (void *)hw, 0, 0, NULL);
+	if (mgmtm->eq_idx == -1) {
+		csio_err(hw, "Failed to alloc egress queue for mgmt module\n");
+		goto intr_disable;
+	}
+
+	/* Use FW IQ for MGMT req completion */
+	mgmtm->iq_idx = hw->fwevt_iq_idx;
+
+	/* Allocate SCSI queues */
+	for (i = 0; i < hw->num_pports; i++) {
+		info = &hw->scsi_cpu_info[i];
+
+		for (j = 0; j < hw->num_scsi_msix_cpus; j++) {
+			sqset = &hw->sqset[i][j];
+
+			if (j >= info->max_cpus) {
+				k = j % info->max_cpus;
+				orig = &hw->sqset[i][k];
+				sqset->eq_idx = orig->eq_idx;
+				sqset->iq_idx = orig->iq_idx;
+				continue;
+			}
+
+			idx = csio_wr_alloc_q(hw, csio_scsi_eqsize, 0,
+					      CSIO_EGRESS, (void *)hw, 0, 0,
+					      NULL);
+			if (idx == -1) {
+				csio_err(hw, "EQ creation failed for idx:%d\n",
+					    idx);
+				goto intr_disable;
+			}
+
+			sqset->eq_idx = idx;
+
+			idx = csio_wr_alloc_q(hw, CSIO_SCSI_IQSIZE,
+					     CSIO_SCSI_IQ_WRSZ, CSIO_INGRESS,
+					     (void *)hw, 0, 0,
+					     csio_scsi_intx_handler);
+			if (idx == -1) {
+				csio_err(hw, "IQ creation failed for idx:%d\n",
+					    idx);
+				goto intr_disable;
+			}
+			sqset->iq_idx = idx;
+		} /* for all CPUs */
+	} /* For all ports */
+
+	hw->flags |= CSIO_HWF_Q_MEM_ALLOCED;
+
+	rv = csio_create_queues(hw);
+	if (rv != 0)
+		goto intr_disable;
+
+	/*
+	 * Now request IRQs for the vectors. In the event of a failure,
+	 * cleanup is handled internally by this function.
+	 */
+	rv = csio_request_irqs(hw);
+	if (rv != 0)
+		return -EINVAL;
+
+	return 0;
+
+intr_disable:
+	csio_intr_disable(hw, false);
+
+	return -EINVAL;
+}
+
+static int
+csio_resource_alloc(struct csio_hw *hw)
+{
+	struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+	int rv = -ENOMEM;
+
+	wrm->num_q = ((CSIO_MAX_SCSI_QSETS * 2) + CSIO_HW_NIQ +
+		       CSIO_HW_NEQ + CSIO_HW_NFLQ + CSIO_HW_NINTXQ);
+
+	hw->mb_mempool = mempool_create_kmalloc_pool(CSIO_MIN_MEMPOOL_SZ,
+						  sizeof(struct csio_mb));
+	if (!hw->mb_mempool)
+		goto err;
+
+	hw->rnode_mempool = mempool_create_kmalloc_pool(CSIO_MIN_MEMPOOL_SZ,
+						     sizeof(struct csio_rnode));
+	if (!hw->rnode_mempool)
+		goto err_free_mb_mempool;
+
+	hw->scsi_pci_pool = pci_pool_create("csio_scsi_pci_pool", hw->pdev,
+					    CSIO_SCSI_RSP_LEN, 8, 0);
+	if (!hw->scsi_pci_pool)
+		goto err_free_rn_pool;
+
+	return 0;
+
+err_free_rn_pool:
+	mempool_destroy(hw->rnode_mempool);
+	hw->rnode_mempool = NULL;
+err_free_mb_mempool:
+	mempool_destroy(hw->mb_mempool);
+	hw->mb_mempool = NULL;
+err:
+	return rv;
+}
+
+static void
+csio_resource_free(struct csio_hw *hw)
+{
+	pci_pool_destroy(hw->scsi_pci_pool);
+	hw->scsi_pci_pool = NULL;
+	mempool_destroy(hw->rnode_mempool);
+	hw->rnode_mempool = NULL;
+	mempool_destroy(hw->mb_mempool);
+	hw->mb_mempool = NULL;
+}
+
+/*
+ * csio_hw_alloc - Allocate and initialize the HW module.
+ * @pdev: PCI device.
+ *
+ * Allocates HW structure, DMA, memory resources, maps BARS to
+ * host memory and initializes HW module.
+ */
+static struct csio_hw * __devinit
+csio_hw_alloc(struct pci_dev *pdev)
+{
+	struct csio_hw *hw;
+
+	hw = kzalloc(sizeof(struct csio_hw), GFP_KERNEL);
+	if (!hw)
+		goto err;
+
+	hw->pdev = pdev;
+	strncpy(hw->drv_version, CSIO_DRV_VERSION, 32);
+
+	/* memory pool/DMA pool allocation */
+	if (csio_resource_alloc(hw))
+		goto err_free_hw;
+
+	/* Get the start address of registers from BAR 0 */
+	hw->regstart = ioremap_nocache(pci_resource_start(pdev, 0),
+				       pci_resource_len(pdev, 0));
+	if (!hw->regstart) {
+		csio_err(hw, "Could not map BAR 0, regstart = %p\n",
+			 hw->regstart);
+		goto err_resource_free;
+	}
+
+	csio_hw_init_workers(hw);
+
+	if (csio_hw_init(hw))
+		goto err_unmap_bar;
+
+	csio_dfs_create(hw);
+
+	csio_dbg(hw, "hw:%p\n", hw);
+
+	return hw;
+
+err_unmap_bar:
+	csio_hw_exit_workers(hw);
+	iounmap(hw->regstart);
+err_resource_free:
+	csio_resource_free(hw);
+err_free_hw:
+	kfree(hw);
+err:
+	return NULL;
+}
+
+/*
+ * csio_hw_free - Uninitialize and free the HW module.
+ * @hw: The HW module
+ *
+ * Disable interrupts, uninit the HW module, free resources, free hw.
+ */
+static void
+csio_hw_free(struct csio_hw *hw)
+{
+	csio_intr_disable(hw, true);
+	csio_hw_exit_workers(hw);
+	csio_hw_exit(hw);
+	iounmap(hw->regstart);
+	csio_dfs_destroy(hw);
+	csio_resource_free(hw);
+	kfree(hw);
+}
+
+/**
+ * csio_shost_init - Create and initialize the lnode module.
+ * @hw:		The HW module.
+ * @dev:	The device associated with this invocation.
+ * @probe:	Called from probe context or not?
+ * @os_pln:	Parent lnode if any.
+ *
+ * Allocates lnode structure via scsi_host_alloc, initializes
+ * shost, initializes lnode module and registers with SCSI ML
+ * via scsi_host_add. This function is shared between physical and
+ * virtual node ports.
+ */
+struct csio_lnode *
+csio_shost_init(struct csio_hw *hw, struct device *dev,
+		  bool probe, struct csio_lnode *pln)
+{
+	struct Scsi_Host  *shost = NULL;
+	struct csio_lnode *ln;
+
+	csio_fcoe_shost_template.cmd_per_lun = csio_lun_qdepth;
+	csio_fcoe_shost_vport_template.cmd_per_lun = csio_lun_qdepth;
+
+	/*
+	 * hw->pdev is the physical port's PCI dev structure,
+	 * which will be different from the NPIV dev structure.
+	 */
+	if (dev == &hw->pdev->dev)
+		shost = scsi_host_alloc(
+				&csio_fcoe_shost_template,
+				sizeof(struct csio_lnode));
+	else
+		shost = scsi_host_alloc(
+				&csio_fcoe_shost_vport_template,
+				sizeof(struct csio_lnode));
+
+	if (!shost)
+		goto err;
+
+	ln = shost_priv(shost);
+	memset(ln, 0, sizeof(struct csio_lnode));
+
+	/* Link common lnode to this lnode */
+	ln->dev_num = (shost->host_no << 16);
+
+	shost->can_queue = CSIO_MAX_QUEUE;
+	shost->this_id = -1;
+	shost->unique_id = shost->host_no;
+	shost->max_cmd_len = 16; /* Max CDB length supported */
+	shost->max_id = min_t(uint32_t, csio_fcoe_rnodes,
+			      hw->fres_info.max_ssns);
+	shost->max_lun = CSIO_MAX_LUN;
+	if (dev == &hw->pdev->dev)
+		shost->transportt = csio_fcoe_transport;
+	else
+		shost->transportt = csio_fcoe_transport_vport;
+
+	/* root lnode */
+	if (!hw->rln)
+		hw->rln = ln;
+
+	/* Other initialization here: Common, Transport specific */
+	if (csio_lnode_init(ln, hw, pln))
+		goto err_shost_put;
+
+	if (scsi_add_host(shost, dev))
+		goto err_lnode_exit;
+
+	return ln;
+
+err_lnode_exit:
+	csio_lnode_exit(ln);
+err_shost_put:
+	scsi_host_put(shost);
+err:
+	return NULL;
+}
+
+/**
+ * csio_shost_exit - De-instantiate the shost.
+ * @ln:		The lnode module corresponding to the shost.
+ *
+ */
+void
+csio_shost_exit(struct csio_lnode *ln)
+{
+	struct Scsi_Host *shost = csio_ln_to_shost(ln);
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+	/* Inform transport */
+	fc_remove_host(shost);
+
+	/* Inform SCSI ML */
+	scsi_remove_host(shost);
+
+	/* Flush all the events, so that any rnode removal events
+	 * already queued are all handled, before we remove the lnode.
+	 */
+	spin_lock_irq(&hw->lock);
+	csio_evtq_flush(hw);
+	spin_unlock_irq(&hw->lock);
+
+	csio_lnode_exit(ln);
+	scsi_host_put(shost);
+}
+
+struct csio_lnode *
+csio_lnode_alloc(struct csio_hw *hw)
+{
+	return csio_shost_init(hw, &hw->pdev->dev, false, NULL);
+}
+
+void
+csio_lnodes_block_request(struct csio_hw *hw)
+{
+	struct Scsi_Host  *shost;
+	struct csio_lnode *sln;
+	struct csio_lnode *ln;
+	struct list_head *cur_ln, *cur_cln;
+	struct csio_lnode **lnode_list;
+	int cur_cnt = 0, ii;
+
+	lnode_list = kzalloc((sizeof(struct csio_lnode *) * hw->num_lns),
+			GFP_KERNEL);
+	if (!lnode_list) {
+		csio_err(hw, "Failed to allocate lnodes_list");
+		return;
+	}
+
+	spin_lock_irq(&hw->lock);
+	/* Traverse sibling lnodes */
+	list_for_each(cur_ln, &hw->sln_head) {
+		sln = (struct csio_lnode *) cur_ln;
+		lnode_list[cur_cnt++] = sln;
+
+		/* Traverse children lnodes */
+		list_for_each(cur_cln, &sln->cln_head)
+			lnode_list[cur_cnt++] = (struct csio_lnode *) cur_cln;
+	}
+	spin_unlock_irq(&hw->lock);
+
+	for (ii = 0; ii < cur_cnt; ii++) {
+		csio_dbg(hw, "Blocking IOs on lnode: %p\n", lnode_list[ii]);
+		ln = lnode_list[ii];
+		shost = csio_ln_to_shost(ln);
+		scsi_block_requests(shost);
+
+	}
+	kfree(lnode_list);
+}
+
+void
+csio_lnodes_unblock_request(struct csio_hw *hw)
+{
+	struct csio_lnode *ln;
+	struct Scsi_Host  *shost;
+	struct csio_lnode *sln;
+	struct list_head *cur_ln, *cur_cln;
+	struct csio_lnode **lnode_list;
+	int cur_cnt = 0, ii;
+
+	lnode_list = kzalloc((sizeof(struct csio_lnode *) * hw->num_lns),
+			GFP_KERNEL);
+	if (!lnode_list) {
+		csio_err(hw, "Failed to allocate lnodes_list");
+		return;
+	}
+
+	spin_lock_irq(&hw->lock);
+	/* Traverse sibling lnodes */
+	list_for_each(cur_ln, &hw->sln_head) {
+		sln = (struct csio_lnode *) cur_ln;
+		lnode_list[cur_cnt++] = sln;
+
+		/* Traverse children lnodes */
+		list_for_each(cur_cln, &sln->cln_head)
+			lnode_list[cur_cnt++] = (struct csio_lnode *) cur_cln;
+	}
+	spin_unlock_irq(&hw->lock);
+
+	for (ii = 0; ii < cur_cnt; ii++) {
+		csio_dbg(hw, "unblocking IOs on lnode: %p\n", lnode_list[ii]);
+		ln = lnode_list[ii];
+		shost = csio_ln_to_shost(ln);
+		scsi_unblock_requests(shost);
+	}
+	kfree(lnode_list);
+}
+
+void
+csio_lnodes_block_by_port(struct csio_hw *hw, uint8_t portid)
+{
+	struct csio_lnode *ln;
+	struct Scsi_Host  *shost;
+	struct csio_lnode *sln;
+	struct list_head *cur_ln, *cur_cln;
+	struct csio_lnode **lnode_list;
+	int cur_cnt = 0, ii;
+
+	lnode_list = kzalloc((sizeof(struct csio_lnode *) * hw->num_lns),
+			GFP_KERNEL);
+	if (!lnode_list) {
+		csio_err(hw, "Failed to allocate lnodes_list");
+		return;
+	}
+
+	spin_lock_irq(&hw->lock);
+	/* Traverse sibling lnodes */
+	list_for_each(cur_ln, &hw->sln_head) {
+		sln = (struct csio_lnode *) cur_ln;
+		if (sln->portid != portid)
+			continue;
+
+		lnode_list[cur_cnt++] = sln;
+
+		/* Traverse children lnodes */
+		list_for_each(cur_cln, &sln->cln_head)
+			lnode_list[cur_cnt++] = (struct csio_lnode *) cur_cln;
+	}
+	spin_unlock_irq(&hw->lock);
+
+	for (ii = 0; ii < cur_cnt; ii++) {
+		csio_dbg(hw, "Blocking IOs on lnode: %p\n", lnode_list[ii]);
+		ln = lnode_list[ii];
+		shost = csio_ln_to_shost(ln);
+		scsi_block_requests(shost);
+	}
+	kfree(lnode_list);
+}
+
+void
+csio_lnodes_unblock_by_port(struct csio_hw *hw, uint8_t portid)
+{
+	struct csio_lnode *ln;
+	struct Scsi_Host  *shost;
+	struct csio_lnode *sln;
+	struct list_head *cur_ln, *cur_cln;
+	struct csio_lnode **lnode_list;
+	int cur_cnt = 0, ii;
+
+	lnode_list = kzalloc((sizeof(struct csio_lnode *) * hw->num_lns),
+			GFP_KERNEL);
+	if (!lnode_list) {
+		csio_err(hw, "Failed to allocate lnodes_list");
+		return;
+	}
+
+	spin_lock_irq(&hw->lock);
+	/* Traverse sibling lnodes */
+	list_for_each(cur_ln, &hw->sln_head) {
+		sln = (struct csio_lnode *) cur_ln;
+		if (sln->portid != portid)
+			continue;
+		lnode_list[cur_cnt++] = sln;
+
+		/* Traverse children lnodes */
+		list_for_each(cur_cln, &sln->cln_head)
+			lnode_list[cur_cnt++] = (struct csio_lnode *) cur_cln;
+	}
+	spin_unlock_irq(&hw->lock);
+
+	for (ii = 0; ii < cur_cnt; ii++) {
+		csio_dbg(hw, "unblocking IOs on lnode: %p\n", lnode_list[ii]);
+		ln = lnode_list[ii];
+		shost = csio_ln_to_shost(ln);
+		scsi_unblock_requests(shost);
+	}
+	kfree(lnode_list);
+}
+
+void
+csio_lnodes_exit(struct csio_hw *hw, bool npiv)
+{
+	struct csio_lnode *sln;
+	struct csio_lnode *ln;
+	struct list_head *cur_ln, *cur_cln;
+	struct csio_lnode **lnode_list;
+	int cur_cnt = 0, ii;
+
+	lnode_list = kzalloc((sizeof(struct csio_lnode *) * hw->num_lns),
+			GFP_KERNEL);
+	if (!lnode_list) {
+		csio_err(hw, "lnodes_exit: Failed to allocate lnodes_list.\n");
+		return;
+	}
+
+	/* Get all child lnodes(NPIV ports) */
+	spin_lock_irq(&hw->lock);
+	list_for_each(cur_ln, &hw->sln_head) {
+		sln = (struct csio_lnode *) cur_ln;
+
+		/* Traverse children lnodes */
+		list_for_each(cur_cln, &sln->cln_head)
+			lnode_list[cur_cnt++] = (struct csio_lnode *) cur_cln;
+	}
+	spin_unlock_irq(&hw->lock);
+
+	/* Delete NPIV lnodes */
+	for (ii = 0; ii < cur_cnt; ii++) {
+		csio_dbg(hw, "Deleting child lnode: %p\n", lnode_list[ii]);
+		ln = lnode_list[ii];
+		fc_vport_terminate(ln->fc_vport);
+	}
+
+	/* Delete only npiv lnodes */
+	if (npiv)
+		goto free_lnodes;
+
+	cur_cnt = 0;
+	/* Get all physical lnodes */
+	spin_lock_irq(&hw->lock);
+	/* Traverse sibling lnodes */
+	list_for_each(cur_ln, &hw->sln_head) {
+		sln = (struct csio_lnode *) cur_ln;
+		lnode_list[cur_cnt++] = sln;
+	}
+	spin_unlock_irq(&hw->lock);
+
+	/* Delete physical lnodes */
+	for (ii = 0; ii < cur_cnt; ii++) {
+		csio_dbg(hw, "Deleting parent lnode: %p\n", lnode_list[ii]);
+		csio_shost_exit(lnode_list[ii]);
+	}
+
+free_lnodes:
+	kfree(lnode_list);
+}
+
+/*
+ * csio_lnode_init_post: Set lnode attributes after starting HW.
+ * @ln: lnode.
+ *
+ */
+static void
+csio_lnode_init_post(struct csio_lnode *ln)
+{
+	struct Scsi_Host  *shost = csio_ln_to_shost(ln);
+
+	csio_fchost_attr_init(ln);
+
+	scsi_scan_host(shost);
+}
+
+/*
+ * csio_probe_one - Instantiate this function.
+ * @pdev: PCI device
+ * @id: Device ID
+ *
+ * This is the .probe() callback of the driver. This function:
+ * - Initializes the PCI function by enabling MMIO, setting bus
+ *   mastership and setting DMA mask.
+ * - Allocates HW structure, DMA, memory resources, maps BARS to
+ *   host memory and initializes HW module.
+ * - Allocates lnode structure via scsi_host_alloc, initializes
+ *   shost, initialized lnode module and registers with SCSI ML
+ *   via scsi_host_add.
+ * - Enables interrupts, and starts the chip by kicking off the
+ *   HW state machine.
+ * - Once hardware is ready, initiated scan of the host via
+ *   scsi_scan_host.
+ */
+static int __devinit
+csio_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	int rv;
+	int bars;
+	int i;
+	struct csio_hw *hw;
+	struct csio_lnode *ln;
+
+	rv = csio_pci_init(pdev, &bars);
+	if (rv)
+		goto err;
+
+	hw = csio_hw_alloc(pdev);
+	if (!hw) {
+		rv = -ENODEV;
+		goto err_pci_exit;
+	}
+
+	pci_set_drvdata(pdev, hw);
+
+	if (csio_hw_start(hw) != 0) {
+		dev_err(&pdev->dev,
+			"Failed to start FW, continuing in debug mode.\n");
+		return 0;
+	}
+
+	sprintf(hw->fwrev_str, "%u.%u.%u.%u\n",
+		    FW_HDR_FW_VER_MAJOR_GET(hw->fwrev),
+		    FW_HDR_FW_VER_MINOR_GET(hw->fwrev),
+		    FW_HDR_FW_VER_MICRO_GET(hw->fwrev),
+		    FW_HDR_FW_VER_BUILD_GET(hw->fwrev));
+
+	for (i = 0; i < hw->num_pports; i++) {
+		ln = csio_shost_init(hw, &pdev->dev, true, NULL);
+		if (!ln) {
+			rv = -ENODEV;
+			break;
+		}
+		/* Initialize portid */
+		ln->portid = hw->pport[i].portid;
+
+		spin_lock_irq(&hw->lock);
+		if (csio_lnode_start(ln) != 0)
+			rv = -ENODEV;
+		spin_unlock_irq(&hw->lock);
+
+		if (rv)
+			break;
+
+		csio_lnode_init_post(ln);
+	}
+
+	if (rv)
+		goto err_lnode_exit;
+
+	return 0;
+
+err_lnode_exit:
+	csio_lnodes_block_request(hw);
+	spin_lock_irq(&hw->lock);
+	csio_hw_stop(hw);
+	spin_unlock_irq(&hw->lock);
+	csio_lnodes_unblock_request(hw);
+	pci_set_drvdata(hw->pdev, NULL);
+	csio_lnodes_exit(hw, 0);
+	csio_hw_free(hw);
+err_pci_exit:
+	csio_pci_exit(pdev, &bars);
+err:
+	dev_err(&pdev->dev, "probe of device failed: %d\n", rv);
+	return rv;
+}
+
+/*
+ * csio_remove_one - Remove one instance of the driver at this PCI function.
+ * @pdev: PCI device
+ *
+ * Used during hotplug operation.
+ */
+static void __devexit
+csio_remove_one(struct pci_dev *pdev)
+{
+	struct csio_hw *hw = pci_get_drvdata(pdev);
+	int bars = pci_select_bars(pdev, IORESOURCE_MEM);
+
+	csio_lnodes_block_request(hw);
+	spin_lock_irq(&hw->lock);
+
+	/* Stops lnode, Rnode s/m
+	 * Quiesce IOs.
+	 * All sessions with remote ports are unregistered.
+	 */
+	csio_hw_stop(hw);
+	spin_unlock_irq(&hw->lock);
+	csio_lnodes_unblock_request(hw);
+
+	csio_lnodes_exit(hw, 0);
+	csio_hw_free(hw);
+	pci_set_drvdata(pdev, NULL);
+	csio_pci_exit(pdev, &bars);
+}
+
+/*
+ * csio_pci_error_detected - PCI error was detected
+ * @pdev: PCI device
+ *
+ */
+static pci_ers_result_t
+csio_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+{
+	struct csio_hw *hw = pci_get_drvdata(pdev);
+
+	csio_lnodes_block_request(hw);
+	spin_lock_irq(&hw->lock);
+
+	/* Post PCI error detected evt to HW s/m
+	 * HW s/m handles this evt by quiescing IOs, unregisters rports
+	 * and finally takes the device to offline.
+	 */
+	csio_post_event(&hw->sm, CSIO_HWE_PCIERR_DETECTED);
+	spin_unlock_irq(&hw->lock);
+	csio_lnodes_unblock_request(hw);
+	csio_lnodes_exit(hw, 0);
+	csio_intr_disable(hw, true);
+	pci_disable_device(pdev);
+	return state == pci_channel_io_perm_failure ?
+		PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET;
+}
+
+/*
+ * csio_pci_slot_reset - PCI slot has been reset.
+ * @pdev: PCI device
+ *
+ */
+static pci_ers_result_t
+csio_pci_slot_reset(struct pci_dev *pdev)
+{
+	struct csio_hw *hw = pci_get_drvdata(pdev);
+	int ready;
+
+	if (pci_enable_device(pdev)) {
+		dev_err(&pdev->dev, "cannot re-enable device in slot reset\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+
+	pci_set_master(pdev);
+	pci_restore_state(pdev);
+	pci_save_state(pdev);
+	pci_cleanup_aer_uncorrect_error_status(pdev);
+
+	/* Bring HW s/m to ready state.
+	 * but don't resume IOs.
+	 */
+	spin_lock_irq(&hw->lock);
+	csio_post_event(&hw->sm, CSIO_HWE_PCIERR_SLOT_RESET);
+	ready = csio_is_hw_ready(hw);
+	spin_unlock_irq(&hw->lock);
+
+	if (ready) {
+		return PCI_ERS_RESULT_RECOVERED;
+	} else {
+		dev_err(&pdev->dev, "Can't initialize HW when in slot reset\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+}
+
+/*
+ * csio_pci_resume - Resume normal operations
+ * @pdev: PCI device
+ *
+ */
+static void
+csio_pci_resume(struct pci_dev *pdev)
+{
+	struct csio_hw *hw = pci_get_drvdata(pdev);
+	struct csio_lnode *ln;
+	int rv = 0;
+	int i;
+
+	/* Bring the LINK UP and Resume IO */
+
+	for (i = 0; i < hw->num_pports; i++) {
+		ln = csio_shost_init(hw, &pdev->dev, true, NULL);
+		if (!ln) {
+			rv = -ENODEV;
+			break;
+		}
+		/* Initialize portid */
+		ln->portid = hw->pport[i].portid;
+
+		spin_lock_irq(&hw->lock);
+		if (csio_lnode_start(ln) != 0)
+			rv = -ENODEV;
+		spin_unlock_irq(&hw->lock);
+
+		if (rv)
+			break;
+
+		csio_lnode_init_post(ln);
+	}
+
+	if (rv)
+		goto err_resume_exit;
+
+	return;
+
+err_resume_exit:
+	csio_lnodes_block_request(hw);
+	spin_lock_irq(&hw->lock);
+	csio_hw_stop(hw);
+	spin_unlock_irq(&hw->lock);
+	csio_lnodes_unblock_request(hw);
+	csio_lnodes_exit(hw, 0);
+	csio_hw_free(hw);
+	dev_err(&pdev->dev, "resume of device failed: %d\n", rv);
+}
+
+static struct pci_error_handlers csio_err_handler = {
+	.error_detected = csio_pci_error_detected,
+	.slot_reset	= csio_pci_slot_reset,
+	.resume		= csio_pci_resume,
+};
+
+static DEFINE_PCI_DEVICE_TABLE(csio_pci_tbl) = {
+	CSIO_DEVICE(CSIO_DEVID_T440DBG_FCOE, 0),	/* T440DBG FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T420CR_FCOE, 0),		/* T420CR FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T422CR_FCOE, 0),		/* T422CR FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T440CR_FCOE, 0),		/* T440CR FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T420BCH_FCOE, 0),	/* T420BCH FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T440BCH_FCOE, 0),	/* T440BCH FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T440CH_FCOE, 0),		/* T440CH FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T420SO_FCOE, 0),		/* T420SO FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T420CX_FCOE, 0),		/* T420CX FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T420BT_FCOE, 0),		/* T420BT FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T404BT_FCOE, 0),		/* T404BT FCOE */
+	CSIO_DEVICE(CSIO_DEVID_B420_FCOE, 0),		/* B420 FCOE */
+	CSIO_DEVICE(CSIO_DEVID_B404_FCOE, 0),		/* B404 FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T480CR_FCOE, 0),		/* T480 CR FCOE */
+	CSIO_DEVICE(CSIO_DEVID_T440LPCR_FCOE, 0),	/* T440 LP-CR FCOE */
+	CSIO_DEVICE(CSIO_DEVID_PE10K, 0),		/* PE10K FCOE */
+	CSIO_DEVICE(CSIO_DEVID_PE10K_PF1, 0),	/* PE10K FCOE on PF1 */
+	{ 0, 0, 0, 0, 0, 0, 0 }
+};
+
+
+static struct pci_driver csio_pci_driver = {
+	.name		= KBUILD_MODNAME,
+	.driver		= {
+		.owner	= THIS_MODULE,
+	},
+	.id_table	= csio_pci_tbl,
+	.probe		= csio_probe_one,
+	.remove		= csio_remove_one,
+	.err_handler	= &csio_err_handler,
+};
+
+/*
+ * csio_init - Chelsio storage driver initialization function.
+ *
+ */
+static int __init
+csio_init(void)
+{
+	int rv = -ENOMEM;
+
+	pr_info("%s %s\n", CSIO_DRV_DESC, CSIO_DRV_VERSION);
+
+	csio_dfs_init();
+
+	csio_fcoe_transport = fc_attach_transport(&csio_fc_transport_funcs);
+	if (!csio_fcoe_transport)
+		goto err;
+
+	csio_fcoe_transport_vport =
+			fc_attach_transport(&csio_fc_transport_vport_funcs);
+	if (!csio_fcoe_transport_vport)
+		goto err_vport;
+
+	rv = pci_register_driver(&csio_pci_driver);
+	if (rv)
+		goto err_pci;
+
+	return 0;
+
+err_pci:
+	fc_release_transport(csio_fcoe_transport_vport);
+err_vport:
+	fc_release_transport(csio_fcoe_transport);
+err:
+	csio_dfs_exit();
+	return rv;
+}
+
+/*
+ * csio_exit - Chelsio storage driver uninitialization .
+ *
+ * Function that gets called in the unload path.
+ */
+static void __exit
+csio_exit(void)
+{
+	pci_unregister_driver(&csio_pci_driver);
+	csio_dfs_exit();
+	fc_release_transport(csio_fcoe_transport_vport);
+	fc_release_transport(csio_fcoe_transport);
+}
+
+module_init(csio_init);
+module_exit(csio_exit);
+MODULE_AUTHOR(CSIO_DRV_AUTHOR);
+MODULE_DESCRIPTION(CSIO_DRV_DESC);
+MODULE_LICENSE(CSIO_DRV_LICENSE);
+MODULE_DEVICE_TABLE(pci, csio_pci_tbl);
+MODULE_VERSION(CSIO_DRV_VERSION);
+MODULE_FIRMWARE(CSIO_FW_FNAME);
diff --git a/drivers/scsi/csiostor/csio_init.h b/drivers/scsi/csiostor/csio_init.h
new file mode 100644
index 0000000..0838fd7
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_init.h
@@ -0,0 +1,158 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_INIT_H__
+#define __CSIO_INIT_H__
+
+#include <linux/pci.h>
+#include <linux/if_ether.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include "csio_scsi.h"
+#include "csio_lnode.h"
+#include "csio_rnode.h"
+#include "csio_hw.h"
+
+#define CSIO_DRV_AUTHOR			"Chelsio Communications"
+#define CSIO_DRV_LICENSE		"Dual BSD/GPL"
+#define CSIO_DRV_DESC			"Chelsio FCoE driver"
+#define CSIO_DRV_VERSION		"1.0.0"
+
+#define CSIO_DEVICE(devid, idx)					\
+{ PCI_VENDOR_ID_CHELSIO, (devid), PCI_ANY_ID, PCI_ANY_ID, 0, 0, (idx) }
+
+#define CSIO_IS_T4_FPGA(_dev)		(((_dev) == CSIO_DEVID_PE10K) ||\
+					 ((_dev) == CSIO_DEVID_PE10K_PF1))
+
+/* FCoE device IDs */
+#define CSIO_DEVID_PE10K		0xA000
+#define CSIO_DEVID_PE10K_PF1		0xA001
+#define CSIO_DEVID_T440DBG_FCOE		0x4600
+#define CSIO_DEVID_T420CR_FCOE		0x4601
+#define CSIO_DEVID_T422CR_FCOE		0x4602
+#define CSIO_DEVID_T440CR_FCOE		0x4603
+#define CSIO_DEVID_T420BCH_FCOE		0x4604
+#define CSIO_DEVID_T440BCH_FCOE		0x4605
+#define CSIO_DEVID_T440CH_FCOE		0x4606
+#define CSIO_DEVID_T420SO_FCOE		0x4607
+#define CSIO_DEVID_T420CX_FCOE		0x4608
+#define CSIO_DEVID_T420BT_FCOE		0x4609
+#define CSIO_DEVID_T404BT_FCOE		0x460A
+#define CSIO_DEVID_B420_FCOE		0x460B
+#define CSIO_DEVID_B404_FCOE		0x460C
+#define CSIO_DEVID_T480CR_FCOE		0x460D
+#define CSIO_DEVID_T440LPCR_FCOE	0x460E
+
+extern struct fc_function_template csio_fc_transport_funcs;
+extern struct fc_function_template csio_fc_transport_vport_funcs;
+
+void csio_fchost_attr_init(struct csio_lnode *);
+
+/* INTx handlers */
+void csio_scsi_intx_handler(struct csio_hw *, void *, uint32_t,
+			       struct csio_fl_dma_buf *, void *);
+
+void csio_fwevt_intx_handler(struct csio_hw *, void *, uint32_t,
+				struct csio_fl_dma_buf *, void *);
+
+/* Common os lnode APIs */
+void csio_lnodes_block_request(struct csio_hw *);
+void csio_lnodes_unblock_request(struct csio_hw *);
+void csio_lnodes_block_by_port(struct csio_hw *, uint8_t);
+void csio_lnodes_unblock_by_port(struct csio_hw *, uint8_t);
+
+struct csio_lnode *csio_shost_init(struct csio_hw *, struct device *, bool,
+					struct csio_lnode *);
+void csio_shost_exit(struct csio_lnode *);
+void csio_lnodes_exit(struct csio_hw *, bool);
+
+static inline struct Scsi_Host *
+csio_ln_to_shost(struct csio_lnode *ln)
+{
+	return container_of((void *)ln, struct Scsi_Host, hostdata[0]);
+}
+
+/* SCSI -- locking version of get/put ioreqs  */
+static inline struct csio_ioreq *
+csio_get_scsi_ioreq_lock(struct csio_hw *hw, struct csio_scsim *scsim)
+{
+	struct csio_ioreq *ioreq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&scsim->freelist_lock, flags);
+	ioreq = csio_get_scsi_ioreq(scsim);
+	spin_unlock_irqrestore(&scsim->freelist_lock, flags);
+
+	return ioreq;
+}
+
+static inline void
+csio_put_scsi_ioreq_lock(struct csio_hw *hw, struct csio_scsim *scsim,
+			 struct csio_ioreq *ioreq)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&scsim->freelist_lock, flags);
+	csio_put_scsi_ioreq(scsim, ioreq);
+	spin_unlock_irqrestore(&scsim->freelist_lock, flags);
+}
+
+/* Called in interrupt context */
+static inline void
+csio_put_scsi_ioreq_list_lock(struct csio_hw *hw, struct csio_scsim *scsim,
+			      struct list_head *reqlist, int n)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&scsim->freelist_lock, flags);
+	csio_put_scsi_ioreq_list(scsim, reqlist, n);
+	spin_unlock_irqrestore(&scsim->freelist_lock, flags);
+}
+
+/* Called in interrupt context */
+static inline void
+csio_put_scsi_ddp_list_lock(struct csio_hw *hw, struct csio_scsim *scsim,
+			      struct list_head *reqlist, int n)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+	csio_put_scsi_ddp_list(scsim, reqlist, n);
+	spin_unlock_irqrestore(&hw->lock, flags);
+}
+
+#endif /* ifndef __CSIO_INIT_H__ */
diff --git a/drivers/scsi/csiostor/csio_isr.c b/drivers/scsi/csiostor/csio_isr.c
new file mode 100644
index 0000000..7ee9777
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_isr.c
@@ -0,0 +1,624 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/cpumask.h>
+#include <linux/string.h>
+
+#include "csio_init.h"
+#include "csio_hw.h"
+
+static irqreturn_t
+csio_nondata_isr(int irq, void *dev_id)
+{
+	struct csio_hw *hw = (struct csio_hw *) dev_id;
+	int rv;
+	unsigned long flags;
+
+	if (unlikely(!hw))
+		return IRQ_NONE;
+
+	if (unlikely(pci_channel_offline(hw->pdev))) {
+		CSIO_INC_STATS(hw, n_pcich_offline);
+		return IRQ_NONE;
+	}
+
+	spin_lock_irqsave(&hw->lock, flags);
+	csio_hw_slow_intr_handler(hw);
+	rv = csio_mb_isr_handler(hw);
+
+	if (rv == 0 && !(hw->flags & CSIO_HWF_FWEVT_PENDING)) {
+		hw->flags |= CSIO_HWF_FWEVT_PENDING;
+		spin_unlock_irqrestore(&hw->lock, flags);
+		schedule_work(&hw->evtq_work);
+		return IRQ_HANDLED;
+	}
+	spin_unlock_irqrestore(&hw->lock, flags);
+	return IRQ_HANDLED;
+}
+
+/*
+ * csio_fwevt_handler - Common FW event handler routine.
+ * @hw: HW module.
+ *
+ * This is the ISR for FW events. It is shared b/w MSIX
+ * and INTx handlers.
+ */
+static void
+csio_fwevt_handler(struct csio_hw *hw)
+{
+	int rv;
+	unsigned long flags;
+
+	rv = csio_fwevtq_handler(hw);
+
+	spin_lock_irqsave(&hw->lock, flags);
+	if (rv == 0 && !(hw->flags & CSIO_HWF_FWEVT_PENDING)) {
+		hw->flags |= CSIO_HWF_FWEVT_PENDING;
+		spin_unlock_irqrestore(&hw->lock, flags);
+		schedule_work(&hw->evtq_work);
+		return;
+	}
+	spin_unlock_irqrestore(&hw->lock, flags);
+
+} /* csio_fwevt_handler */
+
+/*
+ * csio_fwevt_isr() - FW events MSIX ISR
+ * @irq:
+ * @dev_id:
+ *
+ * Process WRs on the FW event queue.
+ *
+ */
+static irqreturn_t
+csio_fwevt_isr(int irq, void *dev_id)
+{
+	struct csio_hw *hw = (struct csio_hw *) dev_id;
+
+	if (unlikely(!hw))
+		return IRQ_NONE;
+
+	if (unlikely(pci_channel_offline(hw->pdev))) {
+		CSIO_INC_STATS(hw, n_pcich_offline);
+		return IRQ_NONE;
+	}
+
+	csio_fwevt_handler(hw);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * csio_fwevt_isr() - INTx wrapper for handling FW events.
+ * @irq:
+ * @dev_id:
+ */
+void
+csio_fwevt_intx_handler(struct csio_hw *hw, void *wr, uint32_t len,
+			   struct csio_fl_dma_buf *flb, void *priv)
+{
+	csio_fwevt_handler(hw);
+} /* csio_fwevt_intx_handler */
+
+/*
+ * csio_process_scsi_cmpl - Process a SCSI WR completion.
+ * @hw: HW module.
+ * @wr: The completed WR from the ingress queue.
+ * @len: Length of the WR.
+ * @flb: Freelist buffer array.
+ *
+ */
+static void
+csio_process_scsi_cmpl(struct csio_hw *hw, void *wr, uint32_t len,
+			struct csio_fl_dma_buf *flb, void *cbfn_q)
+{
+	struct csio_ioreq *ioreq;
+	uint8_t *scsiwr;
+	uint8_t subop;
+	void *cmnd;
+	unsigned long flags;
+
+	ioreq = csio_scsi_cmpl_handler(hw, wr, len, flb, NULL, &scsiwr);
+	if (likely(ioreq)) {
+		if (unlikely(*scsiwr == FW_SCSI_ABRT_CLS_WR)) {
+			subop = FW_SCSI_ABRT_CLS_WR_SUB_OPCODE_GET(
+					((struct fw_scsi_abrt_cls_wr *)
+					    scsiwr)->sub_opcode_to_chk_all_io);
+
+			csio_dbg(hw, "%s cmpl recvd ioreq:%p status:%d\n",
+				    subop ? "Close" : "Abort",
+				    ioreq, ioreq->wr_status);
+
+			spin_lock_irqsave(&hw->lock, flags);
+			if (subop)
+				csio_scsi_closed(ioreq,
+						 (struct list_head *)cbfn_q);
+			else
+				csio_scsi_aborted(ioreq,
+						  (struct list_head *)cbfn_q);
+			/*
+			 * We call scsi_done for I/Os that driver thinks aborts
+			 * have timed out. If there is a race caused by FW
+			 * completing abort at the exact same time that the
+			 * driver has deteced the abort timeout, the following
+			 * check prevents calling of scsi_done twice for the
+			 * same command: once from the eh_abort_handler, another
+			 * from csio_scsi_isr_handler(). This also avoids the
+			 * need to check if csio_scsi_cmnd(req) is NULL in the
+			 * fast path.
+			 */
+			cmnd = csio_scsi_cmnd(ioreq);
+			if (unlikely(cmnd == NULL))
+				list_del_init(&ioreq->sm.sm_list);
+
+			spin_unlock_irqrestore(&hw->lock, flags);
+
+			if (unlikely(cmnd == NULL))
+				csio_put_scsi_ioreq_lock(hw,
+						csio_hw_to_scsim(hw), ioreq);
+		} else {
+			spin_lock_irqsave(&hw->lock, flags);
+			csio_scsi_completed(ioreq, (struct list_head *)cbfn_q);
+			spin_unlock_irqrestore(&hw->lock, flags);
+		}
+	}
+}
+
+/*
+ * csio_scsi_isr_handler() - Common SCSI ISR handler.
+ * @iq: Ingress queue pointer.
+ *
+ * Processes SCSI completions on the SCSI IQ indicated by scm->iq_idx
+ * by calling csio_wr_process_iq_idx. If there are completions on the
+ * isr_cbfn_q, yank them out into a local queue and call their io_cbfns.
+ * Once done, add these completions onto the freelist.
+ * This routine is shared b/w MSIX and INTx.
+ */
+static inline irqreturn_t
+csio_scsi_isr_handler(struct csio_q *iq)
+{
+	struct csio_hw *hw = (struct csio_hw *)iq->owner;
+	LIST_HEAD(cbfn_q);
+	struct list_head *tmp;
+	struct csio_scsim *scm;
+	struct csio_ioreq *ioreq;
+	int isr_completions = 0;
+
+	scm = csio_hw_to_scsim(hw);
+
+	if (unlikely(csio_wr_process_iq(hw, iq, csio_process_scsi_cmpl,
+					&cbfn_q) != 0))
+		return IRQ_NONE;
+
+	/* Call back the completion routines */
+	list_for_each(tmp, &cbfn_q) {
+		ioreq = (struct csio_ioreq *)tmp;
+		isr_completions++;
+		ioreq->io_cbfn(hw, ioreq);
+		/* Release ddp buffer if used for this req */
+		if (unlikely(ioreq->dcopy))
+			csio_put_scsi_ddp_list_lock(hw, scm, &ioreq->gen_list,
+						    ioreq->nsge);
+	}
+
+	if (isr_completions) {
+		/* Return the ioreqs back to ioreq->freelist */
+		csio_put_scsi_ioreq_list_lock(hw, scm, &cbfn_q,
+					      isr_completions);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * csio_scsi_isr() - SCSI MSIX handler
+ * @irq:
+ * @dev_id:
+ *
+ * This is the top level SCSI MSIX handler. Calls csio_scsi_isr_handler()
+ * for handling SCSI completions.
+ */
+static irqreturn_t
+csio_scsi_isr(int irq, void *dev_id)
+{
+	struct csio_q *iq = (struct csio_q *) dev_id;
+	struct csio_hw *hw;
+
+	if (unlikely(!iq))
+		return IRQ_NONE;
+
+	hw = (struct csio_hw *)iq->owner;
+
+	if (unlikely(pci_channel_offline(hw->pdev))) {
+		CSIO_INC_STATS(hw, n_pcich_offline);
+		return IRQ_NONE;
+	}
+
+	csio_scsi_isr_handler(iq);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * csio_scsi_intx_handler() - SCSI INTx handler
+ * @irq:
+ * @dev_id:
+ *
+ * This is the top level SCSI INTx handler. Calls csio_scsi_isr_handler()
+ * for handling SCSI completions.
+ */
+void
+csio_scsi_intx_handler(struct csio_hw *hw, void *wr, uint32_t len,
+			struct csio_fl_dma_buf *flb, void *priv)
+{
+	struct csio_q *iq = priv;
+
+	csio_scsi_isr_handler(iq);
+
+} /* csio_scsi_intx_handler */
+
+/*
+ * csio_fcoe_isr() - INTx/MSI interrupt service routine for FCoE.
+ * @irq:
+ * @dev_id:
+ *
+ *
+ */
+static irqreturn_t
+csio_fcoe_isr(int irq, void *dev_id)
+{
+	struct csio_hw *hw = (struct csio_hw *) dev_id;
+	struct csio_q *intx_q = NULL;
+	int rv;
+	irqreturn_t ret = IRQ_NONE;
+	unsigned long flags;
+
+	if (unlikely(!hw))
+		return IRQ_NONE;
+
+	if (unlikely(pci_channel_offline(hw->pdev))) {
+		CSIO_INC_STATS(hw, n_pcich_offline);
+		return IRQ_NONE;
+	}
+
+	/* Disable the interrupt for this PCI function. */
+	if (hw->intr_mode == CSIO_IM_INTX)
+		csio_wr_reg32(hw, 0, MYPF_REG(PCIE_PF_CLI));
+
+	/*
+	 * The read in the following function will flush the
+	 * above write.
+	 */
+	if (csio_hw_slow_intr_handler(hw))
+		ret = IRQ_HANDLED;
+
+	/* Get the INTx Forward interrupt IQ. */
+	intx_q = csio_get_q(hw, hw->intr_iq_idx);
+
+	CSIO_DB_ASSERT(intx_q);
+
+	/* IQ handler is not possible for intx_q, hence pass in NULL */
+	if (likely(csio_wr_process_iq(hw, intx_q, NULL, NULL) == 0))
+		ret = IRQ_HANDLED;
+
+	spin_lock_irqsave(&hw->lock, flags);
+	rv = csio_mb_isr_handler(hw);
+	if (rv == 0 && !(hw->flags & CSIO_HWF_FWEVT_PENDING)) {
+		hw->flags |= CSIO_HWF_FWEVT_PENDING;
+		spin_unlock_irqrestore(&hw->lock, flags);
+		schedule_work(&hw->evtq_work);
+		return IRQ_HANDLED;
+	}
+	spin_unlock_irqrestore(&hw->lock, flags);
+
+	return ret;
+}
+
+static void
+csio_add_msix_desc(struct csio_hw *hw)
+{
+	int i;
+	struct csio_msix_entries *entryp = &hw->msix_entries[0];
+	int k = CSIO_EXTRA_VECS;
+	int len = sizeof(entryp->desc) - 1;
+	int cnt = hw->num_sqsets + k;
+
+	/* Non-data vector */
+	memset(entryp->desc, 0, len + 1);
+	snprintf(entryp->desc, len, "csio-%02x:%02x:%x-nondata",
+		 CSIO_PCI_BUS(hw), CSIO_PCI_DEV(hw), CSIO_PCI_FUNC(hw));
+
+	entryp++;
+	memset(entryp->desc, 0, len + 1);
+	snprintf(entryp->desc, len, "csio-%02x:%02x:%x-fwevt",
+		 CSIO_PCI_BUS(hw), CSIO_PCI_DEV(hw), CSIO_PCI_FUNC(hw));
+	entryp++;
+
+	/* Name SCSI vecs */
+	for (i = k; i < cnt; i++, entryp++) {
+		memset(entryp->desc, 0, len + 1);
+		snprintf(entryp->desc, len, "csio-%02x:%02x:%x-scsi%d",
+			 CSIO_PCI_BUS(hw), CSIO_PCI_DEV(hw),
+			 CSIO_PCI_FUNC(hw), i - CSIO_EXTRA_VECS);
+	}
+}
+
+int
+csio_request_irqs(struct csio_hw *hw)
+{
+	int rv, i, j, k = 0;
+	struct csio_msix_entries *entryp = &hw->msix_entries[0];
+	struct csio_scsi_cpu_info *info;
+
+	if (hw->intr_mode != CSIO_IM_MSIX) {
+		rv = request_irq(hw->pdev->irq, csio_fcoe_isr,
+					(hw->intr_mode == CSIO_IM_MSI) ?
+							0 : IRQF_SHARED,
+					KBUILD_MODNAME, hw);
+		if (rv) {
+			if (hw->intr_mode == CSIO_IM_MSI)
+				pci_disable_msi(hw->pdev);
+			csio_err(hw, "Failed to allocate interrupt line.\n");
+			return -EINVAL;
+		}
+
+		goto out;
+	}
+
+	/* Add the MSIX vector descriptions */
+	csio_add_msix_desc(hw);
+
+	rv = request_irq(entryp[k].vector, csio_nondata_isr, 0,
+			 entryp[k].desc, hw);
+	if (rv) {
+		csio_err(hw, "IRQ request failed for vec %d err:%d\n",
+			 entryp[k].vector, rv);
+		goto err;
+	}
+
+	entryp[k++].dev_id = (void *)hw;
+
+	rv = request_irq(entryp[k].vector, csio_fwevt_isr, 0,
+			 entryp[k].desc, hw);
+	if (rv) {
+		csio_err(hw, "IRQ request failed for vec %d err:%d\n",
+			 entryp[k].vector, rv);
+		goto err;
+	}
+
+	entryp[k++].dev_id = (void *)hw;
+
+	/* Allocate IRQs for SCSI */
+	for (i = 0; i < hw->num_pports; i++) {
+		info = &hw->scsi_cpu_info[i];
+		for (j = 0; j < info->max_cpus; j++, k++) {
+			struct csio_scsi_qset *sqset = &hw->sqset[i][j];
+			struct csio_q *q = hw->wrm.q_arr[sqset->iq_idx];
+
+			rv = request_irq(entryp[k].vector, csio_scsi_isr, 0,
+					 entryp[k].desc, q);
+			if (rv) {
+				csio_err(hw,
+				       "IRQ request failed for vec %d err:%d\n",
+				       entryp[k].vector, rv);
+				goto err;
+			}
+
+			entryp[k].dev_id = (void *)q;
+
+		} /* for all scsi cpus */
+	} /* for all ports */
+
+out:
+	hw->flags |= CSIO_HWF_HOST_INTR_ENABLED;
+
+	return 0;
+
+err:
+	for (i = 0; i < k; i++) {
+		entryp = &hw->msix_entries[i];
+		free_irq(entryp->vector, entryp->dev_id);
+	}
+	pci_disable_msix(hw->pdev);
+
+	return -EINVAL;
+}
+
+static void
+csio_disable_msix(struct csio_hw *hw, bool free)
+{
+	int i;
+	struct csio_msix_entries *entryp;
+	int cnt = hw->num_sqsets + CSIO_EXTRA_VECS;
+
+	if (free) {
+		for (i = 0; i < cnt; i++) {
+			entryp = &hw->msix_entries[i];
+			free_irq(entryp->vector, entryp->dev_id);
+		}
+	}
+	pci_disable_msix(hw->pdev);
+}
+
+/* Reduce per-port max possible CPUs */
+static void
+csio_reduce_sqsets(struct csio_hw *hw, int cnt)
+{
+	int i;
+	struct csio_scsi_cpu_info *info;
+
+	while (cnt < hw->num_sqsets) {
+		for (i = 0; i < hw->num_pports; i++) {
+			info = &hw->scsi_cpu_info[i];
+			if (info->max_cpus > 1) {
+				info->max_cpus--;
+				hw->num_sqsets--;
+				if (hw->num_sqsets <= cnt)
+					break;
+			}
+		}
+	}
+
+	csio_dbg(hw, "Reduced sqsets to %d\n", hw->num_sqsets);
+}
+
+static int
+csio_enable_msix(struct csio_hw *hw)
+{
+	int rv, i, j, k, n, min, cnt;
+	struct csio_msix_entries *entryp;
+	struct msix_entry *entries;
+	int extra = CSIO_EXTRA_VECS;
+	struct csio_scsi_cpu_info *info;
+
+	min = hw->num_pports + extra;
+	cnt = hw->num_sqsets + extra;
+
+	/* Max vectors required based on #niqs configured in fw */
+	if (hw->flags & CSIO_HWF_USING_SOFT_PARAMS || !csio_is_hw_master(hw))
+		cnt = min_t(uint8_t, hw->cfg_niq, cnt);
+
+	entries = kzalloc(sizeof(struct msix_entry) * cnt, GFP_KERNEL);
+	if (!entries)
+		return -ENOMEM;
+
+	for (i = 0; i < cnt; i++)
+		entries[i].entry = (uint16_t)i;
+
+	csio_dbg(hw, "FW supp #niq:%d, trying %d msix's\n", hw->cfg_niq, cnt);
+
+	while ((rv = pci_enable_msix(hw->pdev, entries, cnt)) >= min)
+		cnt = rv;
+	if (!rv) {
+		if (cnt < (hw->num_sqsets + extra)) {
+			csio_dbg(hw, "Reducing sqsets to %d\n", cnt - extra);
+			csio_reduce_sqsets(hw, cnt - extra);
+		}
+	} else {
+		if (rv > 0) {
+			pci_disable_msix(hw->pdev);
+			csio_info(hw, "Not using MSI-X, remainder:%d\n", rv);
+		}
+
+		kfree(entries);
+		return -ENOMEM;
+	}
+
+	/* Save off vectors */
+	for (i = 0; i < cnt; i++) {
+		entryp = &hw->msix_entries[i];
+		entryp->vector = entries[i].vector;
+	}
+
+	/* Distribute vectors */
+	k = 0;
+	csio_set_nondata_intr_idx(hw, entries[k].entry);
+	csio_set_mb_intr_idx(csio_hw_to_mbm(hw), entries[k++].entry);
+	csio_set_fwevt_intr_idx(hw, entries[k++].entry);
+
+	for (i = 0; i < hw->num_pports; i++) {
+		info = &hw->scsi_cpu_info[i];
+
+		for (j = 0; j < hw->num_scsi_msix_cpus; j++) {
+			n = (j % info->max_cpus) +  k;
+			hw->sqset[i][j].intr_idx = entries[n].entry;
+		}
+
+		k += info->max_cpus;
+	}
+
+	kfree(entries);
+	return 0;
+}
+
+void
+csio_intr_enable(struct csio_hw *hw)
+{
+	hw->intr_mode = CSIO_IM_NONE;
+	hw->flags &= ~CSIO_HWF_HOST_INTR_ENABLED;
+
+	/* Try MSIX, then MSI or fall back to INTx */
+	if ((csio_msi == 2) && !csio_enable_msix(hw))
+		hw->intr_mode = CSIO_IM_MSIX;
+	else {
+		/* Max iqs required based on #niqs configured in fw */
+		if (hw->flags & CSIO_HWF_USING_SOFT_PARAMS ||
+			!csio_is_hw_master(hw)) {
+			int extra = CSIO_EXTRA_MSI_IQS;
+
+			if (hw->cfg_niq < (hw->num_sqsets + extra)) {
+				csio_dbg(hw, "Reducing sqsets to %d\n",
+					 hw->cfg_niq - extra);
+				csio_reduce_sqsets(hw, hw->cfg_niq - extra);
+			}
+		}
+
+		if ((csio_msi == 1) && !pci_enable_msi(hw->pdev))
+			hw->intr_mode = CSIO_IM_MSI;
+		else
+			hw->intr_mode = CSIO_IM_INTX;
+	}
+
+	csio_dbg(hw, "Using %s interrupt mode.\n",
+		(hw->intr_mode == CSIO_IM_MSIX) ? "MSIX" :
+		((hw->intr_mode == CSIO_IM_MSI) ? "MSI" : "INTx"));
+}
+
+void
+csio_intr_disable(struct csio_hw *hw, bool free)
+{
+	csio_hw_intr_disable(hw);
+
+	switch (hw->intr_mode) {
+	case CSIO_IM_MSIX:
+		csio_disable_msix(hw, free);
+		break;
+	case CSIO_IM_MSI:
+		if (free)
+			free_irq(hw->pdev->irq, hw);
+		pci_disable_msi(hw->pdev);
+		break;
+	case CSIO_IM_INTX:
+		if (free)
+			free_irq(hw->pdev->irq, hw);
+		break;
+	default:
+		break;
+	}
+	hw->intr_mode = CSIO_IM_NONE;
+	hw->flags &= ~CSIO_HWF_HOST_INTR_ENABLED;
+}
diff --git a/drivers/scsi/csiostor/csio_lnode.c b/drivers/scsi/csiostor/csio_lnode.c
new file mode 100644
index 0000000..551959e
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_lnode.c
@@ -0,0 +1,2133 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/utsname.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_fc.h>
+#include <asm/unaligned.h>
+#include <scsi/fc/fc_els.h>
+#include <scsi/fc/fc_fs.h>
+#include <scsi/fc/fc_gs.h>
+#include <scsi/fc/fc_ms.h>
+
+#include "csio_hw.h"
+#include "csio_mb.h"
+#include "csio_lnode.h"
+#include "csio_rnode.h"
+
+int csio_fcoe_rnodes = 1024;
+int csio_fdmi_enable = 1;
+
+#define PORT_ID_PTR(_x)         ((uint8_t *)(&_x) + 1)
+
+/* Lnode SM declarations */
+static void csio_lns_uninit(struct csio_lnode *, enum csio_ln_ev);
+static void csio_lns_online(struct csio_lnode *, enum csio_ln_ev);
+static void csio_lns_ready(struct csio_lnode *, enum csio_ln_ev);
+static void csio_lns_offline(struct csio_lnode *, enum csio_ln_ev);
+
+static int csio_ln_mgmt_submit_req(struct csio_ioreq *,
+		void (*io_cbfn) (struct csio_hw *, struct csio_ioreq *),
+		enum fcoe_cmn_type, struct csio_dma_buf *, uint32_t);
+
+/* LN event mapping */
+static enum csio_ln_ev fwevt_to_lnevt[] = {
+	CSIO_LNE_NONE,		/* None */
+	CSIO_LNE_NONE,		/* PLOGI_ACC_RCVD  */
+	CSIO_LNE_NONE,		/* PLOGI_RJT_RCVD  */
+	CSIO_LNE_NONE,		/* PLOGI_RCVD	   */
+	CSIO_LNE_NONE,		/* PLOGO_RCVD	   */
+	CSIO_LNE_NONE,		/* PRLI_ACC_RCVD   */
+	CSIO_LNE_NONE,		/* PRLI_RJT_RCVD   */
+	CSIO_LNE_NONE,		/* PRLI_RCVD	   */
+	CSIO_LNE_NONE,		/* PRLO_RCVD	   */
+	CSIO_LNE_NONE,		/* NPORT_ID_CHGD   */
+	CSIO_LNE_LOGO,		/* FLOGO_RCVD	   */
+	CSIO_LNE_LOGO,		/* CLR_VIRT_LNK_RCVD */
+	CSIO_LNE_FAB_INIT_DONE,/* FLOGI_ACC_RCVD   */
+	CSIO_LNE_NONE,		/* FLOGI_RJT_RCVD   */
+	CSIO_LNE_FAB_INIT_DONE,/* FDISC_ACC_RCVD   */
+	CSIO_LNE_NONE,		/* FDISC_RJT_RCVD   */
+	CSIO_LNE_NONE,		/* FLOGI_TMO_MAX_RETRY */
+	CSIO_LNE_NONE,		/* IMPL_LOGO_ADISC_ACC */
+	CSIO_LNE_NONE,		/* IMPL_LOGO_ADISC_RJT */
+	CSIO_LNE_NONE,		/* IMPL_LOGO_ADISC_CNFLT */
+	CSIO_LNE_NONE,		/* PRLI_TMO		*/
+	CSIO_LNE_NONE,		/* ADISC_TMO		*/
+	CSIO_LNE_NONE,		/* RSCN_DEV_LOST */
+	CSIO_LNE_NONE,		/* SCR_ACC_RCVD */
+	CSIO_LNE_NONE,		/* ADISC_RJT_RCVD */
+	CSIO_LNE_NONE,		/* LOGO_SNT */
+	CSIO_LNE_NONE,		/* PROTO_ERR_IMPL_LOGO */
+};
+
+#define CSIO_FWE_TO_LNE(_evt)	((_evt > PROTO_ERR_IMPL_LOGO) ?		\
+						CSIO_LNE_NONE :	\
+						fwevt_to_lnevt[_evt])
+
+#define csio_ct_rsp(cp)		(((struct fc_ct_hdr *)cp)->ct_cmd)
+#define csio_ct_reason(cp)	(((struct fc_ct_hdr *)cp)->ct_reason)
+#define csio_ct_expl(cp)	(((struct fc_ct_hdr *)cp)->ct_explan)
+#define csio_ct_get_pld(cp)	((void *)(((uint8_t *)cp) + FC_CT_HDR_LEN))
+
+/*
+ * csio_ln_match_by_portid - lookup lnode using given portid.
+ * @hw: HW module
+ * @portid: port-id.
+ *
+ * If found, returns lnode matching given portid otherwise returns NULL.
+ */
+static struct csio_lnode *
+csio_ln_lookup_by_portid(struct csio_hw *hw, uint8_t portid)
+{
+	struct csio_lnode *ln = hw->rln;
+	struct list_head *tmp;
+
+	/* Match siblings lnode with portid */
+	list_for_each(tmp, &hw->sln_head) {
+		ln = (struct csio_lnode *) tmp;
+		if (ln->portid == portid)
+			return ln;
+	}
+
+	return NULL;
+}
+
+/*
+ * csio_ln_lookup_by_vnpi - Lookup lnode using given vnp id.
+ * @hw - HW module
+ * @vnpi - vnp index.
+ * Returns - If found, returns lnode matching given vnp id
+ * otherwise returns NULL.
+ */
+static struct csio_lnode *
+csio_ln_lookup_by_vnpi(struct csio_hw *hw, uint32_t vnp_id)
+{
+	struct list_head *tmp1, *tmp2;
+	struct csio_lnode *sln = NULL, *cln = NULL;
+
+	if (list_empty(&hw->sln_head)) {
+		CSIO_INC_STATS(hw, n_lnlkup_miss);
+		return NULL;
+	}
+	/* Traverse sibling lnodes */
+	list_for_each(tmp1, &hw->sln_head) {
+		sln = (struct csio_lnode *) tmp1;
+
+		/* Match sibling lnode */
+		if (sln->vnp_flowid == vnp_id)
+			return sln;
+
+		if (list_empty(&sln->cln_head))
+			continue;
+
+		/* Traverse children lnodes */
+		list_for_each(tmp2, &sln->cln_head) {
+			cln = (struct csio_lnode *) tmp2;
+
+			if (cln->vnp_flowid == vnp_id)
+				return cln;
+		}
+	}
+	CSIO_INC_STATS(hw, n_lnlkup_miss);
+	return NULL;
+}
+
+/**
+ * csio_lnode_lookup_by_wwpn - Lookup lnode using given wwpn.
+ * @hw:		HW module.
+ * @wwpn:	WWPN.
+ *
+ * If found, returns lnode matching given wwpn, returns NULL otherwise.
+ */
+struct csio_lnode *
+csio_lnode_lookup_by_wwpn(struct csio_hw *hw, uint8_t *wwpn)
+{
+	struct list_head *tmp1, *tmp2;
+	struct csio_lnode *sln = NULL, *cln = NULL;
+
+	if (list_empty(&hw->sln_head)) {
+		CSIO_INC_STATS(hw, n_lnlkup_miss);
+		return NULL;
+	}
+	/* Traverse sibling lnodes */
+	list_for_each(tmp1, &hw->sln_head) {
+		sln = (struct csio_lnode *) tmp1;
+
+		/* Match sibling lnode */
+		if (!memcmp(csio_ln_wwpn(sln), wwpn, 8))
+			return sln;
+
+		if (list_empty(&sln->cln_head))
+			continue;
+
+		/* Traverse children lnodes */
+		list_for_each(tmp2, &sln->cln_head) {
+			cln = (struct csio_lnode *) tmp2;
+
+			if (!memcmp(csio_ln_wwpn(cln), wwpn, 8))
+				return cln;
+		}
+	}
+	return NULL;
+}
+
+/* FDMI */
+static void
+csio_fill_ct_iu(void *buf, uint8_t type, uint8_t sub_type, uint16_t op)
+{
+	struct fc_ct_hdr *cmd = (struct fc_ct_hdr *)buf;
+	cmd->ct_rev = FC_CT_REV;
+	cmd->ct_fs_type = type;
+	cmd->ct_fs_subtype = sub_type;
+	cmd->ct_cmd = op;
+}
+
+static int
+csio_hostname(uint8_t *buf, size_t buf_len)
+{
+	if (snprintf(buf, buf_len, "%s", init_utsname()->nodename) > 0)
+		return 0;
+	return -1;
+}
+
+static int
+csio_osname(uint8_t *buf, size_t buf_len)
+{
+	if (snprintf(buf, buf_len, "%s %s %s",
+		     init_utsname()->sysname,
+		     init_utsname()->release,
+		     init_utsname()->version) > 0)
+		return 0;
+
+	return -1;
+}
+
+static inline void
+csio_append_attrib(uint8_t **ptr, uint16_t type, uint8_t *val, uint16_t len)
+{
+	struct fc_fdmi_attr_entry *ae = (struct fc_fdmi_attr_entry *)*ptr;
+	ae->type = htons(type);
+	len += 4;		/* includes attribute type and length */
+	len = (len + 3) & ~3;	/* should be multiple of 4 bytes */
+	ae->len = htons(len);
+	memset(ae->value, 0, len - 4);
+	memcpy(ae->value, val, len);
+	*ptr += len;
+}
+
+/*
+ * csio_ln_fdmi_done - FDMI registeration completion
+ * @hw: HW context
+ * @fdmi_req: fdmi request
+ */
+static void
+csio_ln_fdmi_done(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
+{
+	void *cmd;
+	struct csio_lnode *ln = fdmi_req->lnode;
+
+	if (fdmi_req->wr_status != FW_SUCCESS) {
+		csio_ln_dbg(ln, "WR error:%x in processing fdmi rpa cmd\n",
+			    fdmi_req->wr_status);
+		CSIO_INC_STATS(ln, n_fdmi_err);
+	}
+
+	cmd = fdmi_req->dma_buf.vaddr;
+	if (ntohs(csio_ct_rsp(cmd)) != FC_FS_ACC) {
+		csio_ln_dbg(ln, "fdmi rpa cmd rejected reason %x expl %x\n",
+			    csio_ct_reason(cmd), csio_ct_expl(cmd));
+	}
+}
+
+/*
+ * csio_ln_fdmi_rhba_cbfn - RHBA completion
+ * @hw: HW context
+ * @fdmi_req: fdmi request
+ */
+static void
+csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
+{
+	void *cmd;
+	uint8_t *pld;
+	uint32_t len = 0;
+	struct csio_lnode *ln = fdmi_req->lnode;
+	struct fs_fdmi_attrs *attrib_blk;
+	struct fc_fdmi_port_name *port_name;
+	uint8_t buf[64];
+	uint32_t val;
+	uint8_t *fc4_type;
+
+	if (fdmi_req->wr_status != FW_SUCCESS) {
+		csio_ln_dbg(ln, "WR error:%x in processing fdmi rhba cmd\n",
+			    fdmi_req->wr_status);
+		CSIO_INC_STATS(ln, n_fdmi_err);
+	}
+
+	cmd = fdmi_req->dma_buf.vaddr;
+	if (ntohs(csio_ct_rsp(cmd)) != FC_FS_ACC) {
+		csio_ln_dbg(ln, "fdmi rhba cmd rejected reason %x expl %x\n",
+			    csio_ct_reason(cmd), csio_ct_expl(cmd));
+	}
+
+	if (!csio_is_rnode_ready(fdmi_req->rnode)) {
+		CSIO_INC_STATS(ln, n_fdmi_err);
+		return;
+	}
+
+	/* Prepare CT hdr for RPA cmd */
+	memset(cmd, 0, FC_CT_HDR_LEN);
+	csio_fill_ct_iu(cmd, FC_FST_MGMT, FC_FDMI_SUBTYPE, htons(FC_FDMI_RPA));
+
+	/* Prepare RPA payload */
+	pld = (uint8_t *)csio_ct_get_pld(cmd);
+	port_name = (struct fc_fdmi_port_name *)pld;
+	memcpy(&port_name->portname, csio_ln_wwpn(ln), 8);
+	pld += sizeof(*port_name);
+
+	/* Start appending Port attributes */
+	attrib_blk = (struct fs_fdmi_attrs *)pld;
+	attrib_blk->numattrs = 0;
+	len += sizeof(attrib_blk->numattrs);
+	pld += sizeof(attrib_blk->numattrs);
+
+	fc4_type = &buf[0];
+	memset(fc4_type, 0, FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
+	fc4_type[2] = 1;
+	fc4_type[7] = 1;
+	csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_FC4TYPES,
+			   fc4_type, FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
+	attrib_blk->numattrs++;
+	val = htonl(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
+	csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_SUPPORTEDSPEED,
+			   (uint8_t *)&val,
+			   FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN);
+	attrib_blk->numattrs++;
+
+	if (hw->pport[ln->portid].link_speed == FW_PORT_CAP_SPEED_1G)
+		val = htonl(FC_PORTSPEED_1GBIT);
+	else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP_SPEED_10G)
+		val = htonl(FC_PORTSPEED_10GBIT);
+	else
+		val = htonl(CSIO_HBA_PORTSPEED_UNKNOWN);
+	csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_CURRENTPORTSPEED,
+			   (uint8_t *)&val,
+			   FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN);
+	attrib_blk->numattrs++;
+
+	val = htonl(ln->ln_sparm.csp.sp_bb_data);
+	csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_MAXFRAMESIZE,
+			   (uint8_t *)&val, FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN);
+	attrib_blk->numattrs++;
+
+	strcpy(buf, "csiostor");
+	csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_OSDEVICENAME, buf,
+			   (uint16_t)strlen(buf));
+	attrib_blk->numattrs++;
+
+	if (!csio_hostname(buf, sizeof(buf))) {
+		csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_HOSTNAME,
+				   buf, (uint16_t)strlen(buf));
+		attrib_blk->numattrs++;
+	}
+	attrib_blk->numattrs = ntohl(attrib_blk->numattrs);
+	len = (uint32_t)(pld - (uint8_t *)cmd);
+
+	/* Submit FDMI RPA request */
+	spin_lock_irq(&hw->lock);
+	if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_done,
+				FCOE_CT, &fdmi_req->dma_buf, len)) {
+		CSIO_INC_STATS(ln, n_fdmi_err);
+		csio_ln_dbg(ln, "Failed to issue fdmi rpa req\n");
+	}
+	spin_unlock_irq(&hw->lock);
+}
+
+/*
+ * csio_ln_fdmi_dprt_cbfn - DPRT completion
+ * @hw: HW context
+ * @fdmi_req: fdmi request
+ */
+static void
+csio_ln_fdmi_dprt_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
+{
+	void *cmd;
+	uint8_t *pld;
+	uint32_t len = 0;
+	uint32_t maxpayload = htonl(65536);
+	struct fc_fdmi_hba_identifier *hbaid;
+	struct csio_lnode *ln = fdmi_req->lnode;
+	struct fc_fdmi_rpl *reg_pl;
+	struct fs_fdmi_attrs *attrib_blk;
+	uint8_t buf[64];
+
+	if (fdmi_req->wr_status != FW_SUCCESS) {
+		csio_ln_dbg(ln, "WR error:%x in processing fdmi dprt cmd\n",
+			    fdmi_req->wr_status);
+		CSIO_INC_STATS(ln, n_fdmi_err);
+	}
+
+	if (!csio_is_rnode_ready(fdmi_req->rnode)) {
+		CSIO_INC_STATS(ln, n_fdmi_err);
+		return;
+	}
+	cmd = fdmi_req->dma_buf.vaddr;
+	if (ntohs(csio_ct_rsp(cmd)) != FC_FS_ACC) {
+		csio_ln_dbg(ln, "fdmi dprt cmd rejected reason %x expl %x\n",
+			    csio_ct_reason(cmd), csio_ct_expl(cmd));
+	}
+
+	/* Prepare CT hdr for RHBA cmd */
+	memset(cmd, 0, FC_CT_HDR_LEN);
+	csio_fill_ct_iu(cmd, FC_FST_MGMT, FC_FDMI_SUBTYPE, htons(FC_FDMI_RHBA));
+	len = FC_CT_HDR_LEN;
+
+	/* Prepare RHBA payload */
+	pld = (uint8_t *)csio_ct_get_pld(cmd);
+	hbaid = (struct fc_fdmi_hba_identifier *)pld;
+	memcpy(&hbaid->id, csio_ln_wwpn(ln), 8); /* HBA identifer */
+	pld += sizeof(*hbaid);
+
+	/* Register one port per hba */
+	reg_pl = (struct fc_fdmi_rpl *)pld;
+	reg_pl->numport = ntohl(1);
+	memcpy(&reg_pl->port[0].portname, csio_ln_wwpn(ln), 8);
+	pld += sizeof(*reg_pl);
+
+	/* Start appending HBA attributes hba */
+	attrib_blk = (struct fs_fdmi_attrs *)pld;
+	attrib_blk->numattrs = 0;
+	len += sizeof(attrib_blk->numattrs);
+	pld += sizeof(attrib_blk->numattrs);
+
+	csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_NODENAME, csio_ln_wwnn(ln),
+			   FC_FDMI_HBA_ATTR_NODENAME_LEN);
+	attrib_blk->numattrs++;
+
+	memset(buf, 0, sizeof(buf));
+
+	strcpy(buf, "Chelsio Communications");
+	csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MANUFACTURER, buf,
+			   (uint16_t)strlen(buf));
+	attrib_blk->numattrs++;
+	csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_SERIALNUMBER,
+			   hw->vpd.sn, (uint16_t)sizeof(hw->vpd.sn));
+	attrib_blk->numattrs++;
+	csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MODEL, hw->vpd.id,
+			   (uint16_t)sizeof(hw->vpd.id));
+	attrib_blk->numattrs++;
+	csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MODELDESCRIPTION,
+			   hw->model_desc, (uint16_t)strlen(hw->model_desc));
+	attrib_blk->numattrs++;
+	csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_HARDWAREVERSION,
+			   hw->hw_ver, (uint16_t)sizeof(hw->hw_ver));
+	attrib_blk->numattrs++;
+	csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_FIRMWAREVERSION,
+			   hw->fwrev_str, (uint16_t)strlen(hw->fwrev_str));
+	attrib_blk->numattrs++;
+
+	if (!csio_osname(buf, sizeof(buf))) {
+		csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_OSNAMEVERSION,
+				   buf, (uint16_t)strlen(buf));
+		attrib_blk->numattrs++;
+	}
+
+	csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MAXCTPAYLOAD,
+			   (uint8_t *)&maxpayload,
+			   FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN);
+	len = (uint32_t)(pld - (uint8_t *)cmd);
+	attrib_blk->numattrs++;
+	attrib_blk->numattrs = ntohl(attrib_blk->numattrs);
+
+	/* Submit FDMI RHBA request */
+	spin_lock_irq(&hw->lock);
+	if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_rhba_cbfn,
+				FCOE_CT, &fdmi_req->dma_buf, len)) {
+		CSIO_INC_STATS(ln, n_fdmi_err);
+		csio_ln_dbg(ln, "Failed to issue fdmi rhba req\n");
+	}
+	spin_unlock_irq(&hw->lock);
+}
+
+/*
+ * csio_ln_fdmi_dhba_cbfn - DHBA completion
+ * @hw: HW context
+ * @fdmi_req: fdmi request
+ */
+static void
+csio_ln_fdmi_dhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
+{
+	struct csio_lnode *ln = fdmi_req->lnode;
+	void *cmd;
+	struct fc_fdmi_port_name *port_name;
+	uint32_t len;
+
+	if (fdmi_req->wr_status != FW_SUCCESS) {
+		csio_ln_dbg(ln, "WR error:%x in processing fdmi dhba cmd\n",
+			    fdmi_req->wr_status);
+		CSIO_INC_STATS(ln, n_fdmi_err);
+	}
+
+	if (!csio_is_rnode_ready(fdmi_req->rnode)) {
+		CSIO_INC_STATS(ln, n_fdmi_err);
+		return;
+	}
+	cmd = fdmi_req->dma_buf.vaddr;
+	if (ntohs(csio_ct_rsp(cmd)) != FC_FS_ACC) {
+		csio_ln_dbg(ln, "fdmi dhba cmd rejected reason %x expl %x\n",
+			    csio_ct_reason(cmd), csio_ct_expl(cmd));
+	}
+
+	/* Send FDMI cmd to de-register any Port attributes if registered
+	 * before
+	 */
+
+	/* Prepare FDMI DPRT cmd */
+	memset(cmd, 0, FC_CT_HDR_LEN);
+	csio_fill_ct_iu(cmd, FC_FST_MGMT, FC_FDMI_SUBTYPE, htons(FC_FDMI_DPRT));
+	len = FC_CT_HDR_LEN;
+	port_name = (struct fc_fdmi_port_name *)csio_ct_get_pld(cmd);
+	memcpy(&port_name->portname, csio_ln_wwpn(ln), 8);
+	len += sizeof(*port_name);
+
+	/* Submit FDMI request */
+	spin_lock_irq(&hw->lock);
+	if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_dprt_cbfn,
+				FCOE_CT, &fdmi_req->dma_buf, len)) {
+		CSIO_INC_STATS(ln, n_fdmi_err);
+		csio_ln_dbg(ln, "Failed to issue fdmi dprt req\n");
+	}
+	spin_unlock_irq(&hw->lock);
+}
+
+/**
+ * csio_ln_fdmi_start - Start an FDMI request.
+ * @ln:		lnode
+ * @context:	session context
+ *
+ * Issued with lock held.
+ */
+int
+csio_ln_fdmi_start(struct csio_lnode *ln, void *context)
+{
+	struct csio_ioreq *fdmi_req;
+	struct csio_rnode *fdmi_rn = (struct csio_rnode *)context;
+	void *cmd;
+	struct fc_fdmi_hba_identifier *hbaid;
+	uint32_t len;
+
+	if (!(ln->flags & CSIO_LNF_FDMI_ENABLE))
+		return -EPROTONOSUPPORT;
+
+	if (!csio_is_rnode_ready(fdmi_rn))
+		CSIO_INC_STATS(ln, n_fdmi_err);
+
+	/* Send FDMI cmd to de-register any HBA attributes if registered
+	 * before
+	 */
+
+	fdmi_req = ln->mgmt_req;
+	fdmi_req->lnode = ln;
+	fdmi_req->rnode = fdmi_rn;
+
+	/* Prepare FDMI DHBA cmd */
+	cmd = fdmi_req->dma_buf.vaddr;
+	memset(cmd, 0, FC_CT_HDR_LEN);
+	csio_fill_ct_iu(cmd, FC_FST_MGMT, FC_FDMI_SUBTYPE, htons(FC_FDMI_DHBA));
+	len = FC_CT_HDR_LEN;
+
+	hbaid = (struct fc_fdmi_hba_identifier *)csio_ct_get_pld(cmd);
+	memcpy(&hbaid->id, csio_ln_wwpn(ln), 8);
+	len += sizeof(*hbaid);
+
+	/* Submit FDMI request */
+	if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_dhba_cbfn,
+					FCOE_CT, &fdmi_req->dma_buf, len)) {
+		CSIO_INC_STATS(ln, n_fdmi_err);
+		csio_ln_dbg(ln, "Failed to issue fdmi dhba req\n");
+	}
+
+	return 0;
+}
+
+/*
+ * csio_ln_vnp_read_cbfn - vnp read completion handler.
+ * @hw: HW lnode
+ * @cbfn: Completion handler.
+ *
+ * Reads vnp response and updates ln parameters.
+ */
+static void
+csio_ln_vnp_read_cbfn(struct csio_hw *hw, struct csio_mb *mbp)
+{
+	struct csio_lnode *ln = ((struct csio_lnode *)mbp->priv);
+	struct fw_fcoe_vnp_cmd *rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);
+	struct fc_els_csp *csp;
+	struct fc_els_cssp *clsp;
+	enum fw_retval retval;
+
+	retval = FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16));
+	if (retval != FW_SUCCESS) {
+		csio_err(hw, "FCOE VNP read cmd returned error:0x%x\n", retval);
+		mempool_free(mbp, hw->mb_mempool);
+		return;
+	}
+
+	spin_lock_irq(&hw->lock);
+
+	memcpy(ln->mac, rsp->vnport_mac, sizeof(ln->mac));
+	memcpy(&ln->nport_id, &rsp->vnport_mac[3],
+			sizeof(uint8_t)*3);
+	ln->nport_id = ntohl(ln->nport_id);
+	ln->nport_id = ln->nport_id>>8;
+
+	/* Update WWNs */
+	/*
+	 * This may look like a duplication of what csio_fcoe_enable_link()
+	 * does, but is absolutely necessary if the vnpi changes between
+	 * a FCOE LINK UP and FCOE LINK DOWN.
+	 */
+	memcpy(csio_ln_wwnn(ln), rsp->vnport_wwnn, 8);
+	memcpy(csio_ln_wwpn(ln), rsp->vnport_wwpn, 8);
+
+	/* Copy common sparam */
+	csp = (struct fc_els_csp *)rsp->cmn_srv_parms;
+	ln->ln_sparm.csp.sp_hi_ver = csp->sp_hi_ver;
+	ln->ln_sparm.csp.sp_lo_ver = csp->sp_lo_ver;
+	ln->ln_sparm.csp.sp_bb_cred = ntohs(csp->sp_bb_cred);
+	ln->ln_sparm.csp.sp_features = ntohs(csp->sp_features);
+	ln->ln_sparm.csp.sp_bb_data = ntohs(csp->sp_bb_data);
+	ln->ln_sparm.csp.sp_r_a_tov = ntohl(csp->sp_r_a_tov);
+	ln->ln_sparm.csp.sp_e_d_tov = ntohl(csp->sp_e_d_tov);
+
+	/* Copy word 0 & word 1 of class sparam */
+	clsp = (struct fc_els_cssp *)rsp->clsp_word_0_1;
+	ln->ln_sparm.clsp[2].cp_class = ntohs(clsp->cp_class);
+	ln->ln_sparm.clsp[2].cp_init = ntohs(clsp->cp_init);
+	ln->ln_sparm.clsp[2].cp_recip = ntohs(clsp->cp_recip);
+	ln->ln_sparm.clsp[2].cp_rdfs = ntohs(clsp->cp_rdfs);
+
+	spin_unlock_irq(&hw->lock);
+
+	mempool_free(mbp, hw->mb_mempool);
+
+	/* Send an event to update local attribs */
+	csio_lnode_async_event(ln, CSIO_LN_FC_ATTRIB_UPDATE);
+}
+
+/*
+ * csio_ln_vnp_read - Read vnp params.
+ * @ln: lnode
+ * @cbfn: Completion handler.
+ *
+ * Issued with lock held.
+ */
+static int
+csio_ln_vnp_read(struct csio_lnode *ln,
+		void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct csio_hw *hw = ln->hwp;
+	struct csio_mb  *mbp;
+
+	/* Allocate Mbox request */
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		return -ENOMEM;
+	}
+
+	/* Prepare VNP Command */
+	csio_fcoe_vnp_read_init_mb(ln, mbp,
+				    CSIO_MB_DEFAULT_TMO,
+				    ln->fcf_flowid,
+				    ln->vnp_flowid,
+				    cbfn);
+
+	/* Issue MBOX cmd */
+	if (csio_mb_issue(hw, mbp)) {
+		csio_err(hw, "Failed to issue mbox FCoE VNP command\n");
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * csio_fcoe_enable_link - Enable fcoe link.
+ * @ln: lnode
+ * @enable: enable/disable
+ * Issued with lock held.
+ * Issues mbox cmd to bring up FCOE link on port associated with given ln.
+ */
+static int
+csio_fcoe_enable_link(struct csio_lnode *ln, bool enable)
+{
+	struct csio_hw *hw = ln->hwp;
+	struct csio_mb  *mbp;
+	enum fw_retval retval;
+	uint8_t portid;
+	uint8_t sub_op;
+	struct fw_fcoe_link_cmd *lcmd;
+	int i;
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		return -ENOMEM;
+	}
+
+	portid = ln->portid;
+	sub_op = enable ? FCOE_LINK_UP : FCOE_LINK_DOWN;
+
+	csio_dbg(hw, "bringing FCOE LINK %s on Port:%d\n",
+		 sub_op ? "UP" : "DOWN", portid);
+
+	csio_write_fcoe_link_cond_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
+					  portid, sub_op, 0, 0, 0, NULL);
+
+	if (csio_mb_issue(hw, mbp)) {
+		csio_err(hw, "failed to issue FCOE LINK cmd on port[%d]\n",
+			portid);
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	retval = csio_mb_fw_retval(mbp);
+	if (retval != FW_SUCCESS) {
+		csio_err(hw,
+			 "FCOE LINK %s cmd on port[%d] failed with "
+			 "ret:x%x\n", sub_op ? "UP" : "DOWN", portid, retval);
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	if (!enable)
+		goto out;
+
+	lcmd = (struct fw_fcoe_link_cmd *)mbp->mb;
+
+	memcpy(csio_ln_wwnn(ln), lcmd->vnport_wwnn, 8);
+	memcpy(csio_ln_wwpn(ln), lcmd->vnport_wwpn, 8);
+
+	for (i = 0; i < CSIO_MAX_PPORTS; i++)
+		if (hw->pport[i].portid == portid)
+			memcpy(hw->pport[i].mac, lcmd->phy_mac, 6);
+
+out:
+	mempool_free(mbp, hw->mb_mempool);
+	return 0;
+}
+
+/*
+ * csio_ln_read_fcf_cbfn - Read fcf parameters
+ * @ln: lnode
+ *
+ * read fcf response and Update ln fcf information.
+ */
+static void
+csio_ln_read_fcf_cbfn(struct csio_hw *hw, struct csio_mb *mbp)
+{
+	struct csio_lnode *ln = (struct csio_lnode *)mbp->priv;
+	struct csio_fcf_info	*fcf_info;
+	struct fw_fcoe_fcf_cmd *rsp =
+				(struct fw_fcoe_fcf_cmd *)(mbp->mb);
+	enum fw_retval retval;
+
+	retval = FW_CMD_RETVAL_GET(ntohl(rsp->retval_len16));
+	if (retval != FW_SUCCESS) {
+		csio_ln_err(ln, "FCOE FCF cmd failed with ret x%x\n",
+				retval);
+		mempool_free(mbp, hw->mb_mempool);
+		return;
+	}
+
+	spin_lock_irq(&hw->lock);
+	fcf_info = ln->fcfinfo;
+	fcf_info->priority = FW_FCOE_FCF_CMD_PRIORITY_GET(
+					ntohs(rsp->priority_pkd));
+	fcf_info->vf_id = ntohs(rsp->vf_id);
+	fcf_info->vlan_id = rsp->vlan_id;
+	fcf_info->max_fcoe_size = ntohs(rsp->max_fcoe_size);
+	fcf_info->fka_adv = be32_to_cpu(rsp->fka_adv);
+	fcf_info->fcfi = FW_FCOE_FCF_CMD_FCFI_GET(ntohl(rsp->op_to_fcfi));
+	fcf_info->fpma = FW_FCOE_FCF_CMD_FPMA_GET(rsp->fpma_to_portid);
+	fcf_info->spma = FW_FCOE_FCF_CMD_SPMA_GET(rsp->fpma_to_portid);
+	fcf_info->login = FW_FCOE_FCF_CMD_LOGIN_GET(rsp->fpma_to_portid);
+	fcf_info->portid = FW_FCOE_FCF_CMD_PORTID_GET(rsp->fpma_to_portid);
+	memcpy(fcf_info->fc_map, rsp->fc_map, sizeof(fcf_info->fc_map));
+	memcpy(fcf_info->mac, rsp->mac, sizeof(fcf_info->mac));
+	memcpy(fcf_info->name_id, rsp->name_id, sizeof(fcf_info->name_id));
+	memcpy(fcf_info->fabric, rsp->fabric, sizeof(fcf_info->fabric));
+	memcpy(fcf_info->spma_mac, rsp->spma_mac, sizeof(fcf_info->spma_mac));
+
+	spin_unlock_irq(&hw->lock);
+
+	mempool_free(mbp, hw->mb_mempool);
+}
+
+/*
+ * csio_ln_read_fcf_entry - Read fcf entry.
+ * @ln: lnode
+ * @cbfn: Completion handler.
+ *
+ * Issued with lock held.
+ */
+static int
+csio_ln_read_fcf_entry(struct csio_lnode *ln,
+			void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct csio_hw *hw = ln->hwp;
+	struct csio_mb  *mbp;
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		CSIO_INC_STATS(hw, n_err_nomem);
+		return -ENOMEM;
+	}
+
+	/* Get FCoE FCF information */
+	csio_fcoe_read_fcf_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
+				      ln->portid, ln->fcf_flowid, cbfn);
+
+	if (csio_mb_issue(hw, mbp)) {
+		csio_err(hw, "failed to issue FCOE FCF cmd\n");
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * csio_handle_link_up - Logical Linkup event.
+ * @hw - HW module.
+ * @portid - Physical port number
+ * @fcfi - FCF index.
+ * @vnpi - VNP index.
+ * Returns - none.
+ *
+ * This event is received from FW, when virtual link is established between
+ * Physical port[ENode] and FCF. If its new vnpi, then local node object is
+ * created on this FCF and set to [ONLINE] state.
+ * Lnode waits for FW_RDEV_CMD event to be received indicating that
+ * Fabric login is completed and lnode moves to [READY] state.
+ *
+ * This called with hw lock held
+ */
+static void
+csio_handle_link_up(struct csio_hw *hw, uint8_t portid, uint32_t fcfi,
+		    uint32_t vnpi)
+{
+	struct csio_lnode *ln = NULL;
+
+	/* Lookup lnode based on vnpi */
+	ln = csio_ln_lookup_by_vnpi(hw, vnpi);
+	if (!ln) {
+		/* Pick lnode based on portid */
+		ln = csio_ln_lookup_by_portid(hw, portid);
+		if (!ln) {
+			csio_err(hw, "failed to lookup fcoe lnode on port:%d\n",
+				portid);
+			CSIO_DB_ASSERT(0);
+			return;
+		}
+
+		/* Check if lnode has valid vnp flowid */
+		if (ln->vnp_flowid != CSIO_INVALID_IDX) {
+			/* New VN-Port */
+			spin_unlock_irq(&hw->lock);
+			csio_lnode_alloc(hw);
+			spin_lock_irq(&hw->lock);
+			if (!ln) {
+				csio_err(hw,
+					 "failed to allocate fcoe lnode"
+					 "for port:%d vnpi:x%x\n",
+					 portid, vnpi);
+				CSIO_DB_ASSERT(0);
+				return;
+			}
+			ln->portid = portid;
+		}
+		ln->vnp_flowid = vnpi;
+		ln->dev_num &= ~0xFFFF;
+		ln->dev_num |= vnpi;
+	}
+
+	/*Initialize fcfi */
+	ln->fcf_flowid = fcfi;
+
+	csio_info(hw, "Port:%d - FCOE LINK UP\n", portid);
+
+	CSIO_INC_STATS(ln, n_link_up);
+
+	/* Send LINKUP event to SM */
+	csio_post_event(&ln->sm, CSIO_LNE_LINKUP);
+}
+
+/*
+ * csio_post_event_rns
+ * @ln - FCOE lnode
+ * @evt - Given rnode event
+ * Returns - none
+ *
+ * Posts given rnode event to all FCOE rnodes connected with given Lnode.
+ * This routine is invoked when lnode receives LINK_DOWN/DOWN_LINK/CLOSE
+ * event.
+ *
+ * This called with hw lock held
+ */
+static void
+csio_post_event_rns(struct csio_lnode *ln, enum csio_rn_ev evt)
+{
+	struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
+	struct list_head *tmp, *next;
+	struct csio_rnode *rn;
+
+	list_for_each_safe(tmp, next, &rnhead->sm.sm_list) {
+		rn = (struct csio_rnode *) tmp;
+		csio_post_event(&rn->sm, evt);
+	}
+}
+
+/*
+ * csio_cleanup_rns
+ * @ln - FCOE lnode
+ * Returns - none
+ *
+ * Frees all FCOE rnodes connected with given Lnode.
+ *
+ * This called with hw lock held
+ */
+static void
+csio_cleanup_rns(struct csio_lnode *ln)
+{
+	struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
+	struct list_head *tmp, *next_rn;
+	struct csio_rnode *rn;
+
+	list_for_each_safe(tmp, next_rn, &rnhead->sm.sm_list) {
+		rn = (struct csio_rnode *) tmp;
+		csio_put_rnode(ln, rn);
+	}
+
+}
+
+/*
+ * csio_post_event_lns
+ * @ln - FCOE lnode
+ * @evt - Given lnode event
+ * Returns - none
+ *
+ * Posts given lnode event to all FCOE lnodes connected with given Lnode.
+ * This routine is invoked when lnode receives LINK_DOWN/DOWN_LINK/CLOSE
+ * event.
+ *
+ * This called with hw lock held
+ */
+static void
+csio_post_event_lns(struct csio_lnode *ln, enum csio_ln_ev evt)
+{
+	struct list_head *tmp;
+	struct csio_lnode *cln, *sln;
+
+	/* If NPIV lnode, send evt only to that and return */
+	if (csio_is_npiv_ln(ln)) {
+		csio_post_event(&ln->sm, evt);
+		return;
+	}
+
+	sln = ln;
+	/* Traverse children lnodes list and send evt */
+	list_for_each(tmp, &sln->cln_head) {
+		cln = (struct csio_lnode *) tmp;
+		csio_post_event(&cln->sm, evt);
+	}
+
+	/* Send evt to parent lnode */
+	csio_post_event(&ln->sm, evt);
+}
+
+/*
+ * csio_ln_down - Lcoal nport is down
+ * @ln - FCOE Lnode
+ * Returns - none
+ *
+ * Sends LINK_DOWN events to Lnode and its associated NPIVs lnodes.
+ *
+ * This called with hw lock held
+ */
+static void
+csio_ln_down(struct csio_lnode *ln)
+{
+	csio_post_event_lns(ln, CSIO_LNE_LINK_DOWN);
+}
+
+/*
+ * csio_handle_link_down - Logical Linkdown event.
+ * @hw - HW module.
+ * @portid - Physical port number
+ * @fcfi - FCF index.
+ * @vnpi - VNP index.
+ * Returns - none
+ *
+ * This event is received from FW, when virtual link goes down between
+ * Physical port[ENode] and FCF. Lnode and its associated NPIVs lnode hosted on
+ * this vnpi[VN-Port] will be de-instantiated.
+ *
+ * This called with hw lock held
+ */
+static void
+csio_handle_link_down(struct csio_hw *hw, uint8_t portid, uint32_t fcfi,
+		      uint32_t vnpi)
+{
+	struct csio_fcf_info *fp;
+	struct csio_lnode *ln;
+
+	/* Lookup lnode based on vnpi */
+	ln = csio_ln_lookup_by_vnpi(hw, vnpi);
+	if (ln) {
+		fp = ln->fcfinfo;
+		CSIO_INC_STATS(ln, n_link_down);
+
+		/*Warn if linkdown received if lnode is not in ready state */
+		if (!csio_is_lnode_ready(ln)) {
+			csio_ln_warn(ln,
+				"warn: FCOE link is already in offline "
+				"Ignoring Fcoe linkdown event on portid %d\n",
+				 portid);
+			CSIO_INC_STATS(ln, n_evt_drop);
+			return;
+		}
+
+		/* Verify portid */
+		if (fp->portid != portid) {
+			csio_ln_warn(ln,
+				"warn: FCOE linkdown recv with "
+				"invalid port %d\n", portid);
+			CSIO_INC_STATS(ln, n_evt_drop);
+			return;
+		}
+
+		/* verify fcfi */
+		if (ln->fcf_flowid != fcfi) {
+			csio_ln_warn(ln,
+				"warn: FCOE linkdown recv with "
+				"invalid fcfi x%x\n", fcfi);
+			CSIO_INC_STATS(ln, n_evt_drop);
+			return;
+		}
+
+		csio_info(hw, "Port:%d - FCOE LINK DOWN\n", portid);
+
+		/* Send LINK_DOWN event to lnode s/m */
+		csio_ln_down(ln);
+
+		return;
+	} else {
+		csio_warn(hw,
+			  "warn: FCOE linkdown recv with invalid vnpi x%x\n",
+			  vnpi);
+		CSIO_INC_STATS(hw, n_evt_drop);
+	}
+}
+
+/*
+ * csio_is_lnode_ready - Checks FCOE lnode is in ready state.
+ * @ln: Lnode module
+ *
+ * Returns True if FCOE lnode is in ready state.
+ */
+int
+csio_is_lnode_ready(struct csio_lnode *ln)
+{
+	return (csio_get_state(ln) == ((csio_sm_state_t)csio_lns_ready));
+}
+
+/*****************************************************************************/
+/* START: Lnode SM                                                           */
+/*****************************************************************************/
+/*
+ * csio_lns_uninit - The request in uninit state.
+ * @ln - FCOE lnode.
+ * @evt - Event to be processed.
+ *
+ * Process the given lnode event which is currently in "uninit" state.
+ * Invoked with HW lock held.
+ * Return - none.
+ */
+static void
+csio_lns_uninit(struct csio_lnode *ln, enum csio_ln_ev evt)
+{
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+	struct csio_lnode *rln = hw->rln;
+	int rv;
+
+	CSIO_INC_STATS(ln, n_evt_sm[evt]);
+	switch (evt) {
+	case CSIO_LNE_LINKUP:
+		csio_set_state(&ln->sm, csio_lns_online);
+		/* Read FCF only for physical lnode */
+		if (csio_is_phys_ln(ln)) {
+			rv = csio_ln_read_fcf_entry(ln,
+					csio_ln_read_fcf_cbfn);
+			if (rv != 0) {
+				/* TODO: Send HW RESET event */
+				CSIO_INC_STATS(ln, n_err);
+				break;
+			}
+
+			/* Add FCF record */
+			list_add_tail(&ln->fcfinfo->list, &rln->fcf_lsthead);
+		}
+
+		rv = csio_ln_vnp_read(ln, csio_ln_vnp_read_cbfn);
+		if (rv != 0) {
+			/* TODO: Send HW RESET event */
+			CSIO_INC_STATS(ln, n_err);
+		}
+		break;
+
+	case CSIO_LNE_DOWN_LINK:
+		break;
+
+	default:
+		csio_ln_dbg(ln,
+			    "unexp ln event %d recv from did:x%x in "
+			    "ln state[uninit].\n", evt, ln->nport_id);
+		CSIO_INC_STATS(ln, n_evt_unexp);
+		break;
+	} /* switch event */
+}
+
+/*
+ * csio_lns_online - The request in online state.
+ * @ln - FCOE lnode.
+ * @evt - Event to be processed.
+ *
+ * Process the given lnode event which is currently in "online" state.
+ * Invoked with HW lock held.
+ * Return - none.
+ */
+static void
+csio_lns_online(struct csio_lnode *ln, enum csio_ln_ev evt)
+{
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+	CSIO_INC_STATS(ln, n_evt_sm[evt]);
+	switch (evt) {
+	case CSIO_LNE_LINKUP:
+		csio_ln_warn(ln,
+			     "warn: FCOE link is up already "
+			     "Ignoring linkup on port:%d\n", ln->portid);
+		CSIO_INC_STATS(ln, n_evt_drop);
+		break;
+
+	case CSIO_LNE_FAB_INIT_DONE:
+		csio_set_state(&ln->sm, csio_lns_ready);
+
+		spin_unlock_irq(&hw->lock);
+		csio_lnode_async_event(ln, CSIO_LN_FC_LINKUP);
+		spin_lock_irq(&hw->lock);
+
+		break;
+
+	case CSIO_LNE_LINK_DOWN:
+		/* Fall through */
+	case CSIO_LNE_DOWN_LINK:
+		csio_set_state(&ln->sm, csio_lns_uninit);
+		if (csio_is_phys_ln(ln)) {
+			/* Remove FCF entry */
+			list_del_init(&ln->fcfinfo->list);
+		}
+		break;
+
+	default:
+		csio_ln_dbg(ln,
+			    "unexp ln event %d recv from did:x%x in "
+			    "ln state[uninit].\n", evt, ln->nport_id);
+		CSIO_INC_STATS(ln, n_evt_unexp);
+
+		break;
+	} /* switch event */
+}
+
+/*
+ * csio_lns_ready - The request in ready state.
+ * @ln - FCOE lnode.
+ * @evt - Event to be processed.
+ *
+ * Process the given lnode event which is currently in "ready" state.
+ * Invoked with HW lock held.
+ * Return - none.
+ */
+static void
+csio_lns_ready(struct csio_lnode *ln, enum csio_ln_ev evt)
+{
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+	CSIO_INC_STATS(ln, n_evt_sm[evt]);
+	switch (evt) {
+	case CSIO_LNE_FAB_INIT_DONE:
+		csio_ln_dbg(ln,
+			    "ignoring event %d recv from did x%x"
+			    "in ln state[ready].\n", evt, ln->nport_id);
+		CSIO_INC_STATS(ln, n_evt_drop);
+		break;
+
+	case CSIO_LNE_LINK_DOWN:
+		csio_set_state(&ln->sm, csio_lns_offline);
+		csio_post_event_rns(ln, CSIO_RNFE_DOWN);
+
+		spin_unlock_irq(&hw->lock);
+		csio_lnode_async_event(ln, CSIO_LN_FC_LINKDOWN);
+		spin_lock_irq(&hw->lock);
+
+		if (csio_is_phys_ln(ln)) {
+			/* Remove FCF entry */
+			list_del_init(&ln->fcfinfo->list);
+		}
+		break;
+
+	case CSIO_LNE_DOWN_LINK:
+		csio_set_state(&ln->sm, csio_lns_offline);
+		csio_post_event_rns(ln, CSIO_RNFE_DOWN);
+
+		/* Host need to issue aborts in case if FW has not returned
+		 * WRs with status "ABORTED"
+		 */
+		spin_unlock_irq(&hw->lock);
+		csio_lnode_async_event(ln, CSIO_LN_FC_LINKDOWN);
+		spin_lock_irq(&hw->lock);
+
+		if (csio_is_phys_ln(ln)) {
+			/* Remove FCF entry */
+			list_del_init(&ln->fcfinfo->list);
+		}
+		break;
+
+	case CSIO_LNE_CLOSE:
+		csio_set_state(&ln->sm, csio_lns_uninit);
+		csio_post_event_rns(ln, CSIO_RNFE_CLOSE);
+		break;
+
+	case CSIO_LNE_LOGO:
+		csio_set_state(&ln->sm, csio_lns_offline);
+		csio_post_event_rns(ln, CSIO_RNFE_DOWN);
+		break;
+
+	default:
+		csio_ln_dbg(ln,
+			    "unexp ln event %d recv from did:x%x in "
+			    "ln state[uninit].\n", evt, ln->nport_id);
+		CSIO_INC_STATS(ln, n_evt_unexp);
+		CSIO_DB_ASSERT(0);
+		break;
+	} /* switch event */
+}
+
+/*
+ * csio_lns_offline - The request in offline state.
+ * @ln - FCOE lnode.
+ * @evt - Event to be processed.
+ *
+ * Process the given lnode event which is currently in "offline" state.
+ * Invoked with HW lock held.
+ * Return - none.
+ */
+static void
+csio_lns_offline(struct csio_lnode *ln, enum csio_ln_ev evt)
+{
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+	struct csio_lnode *rln = hw->rln;
+	int rv;
+
+	CSIO_INC_STATS(ln, n_evt_sm[evt]);
+	switch (evt) {
+	case CSIO_LNE_LINKUP:
+		csio_set_state(&ln->sm, csio_lns_online);
+		/* Read FCF only for physical lnode */
+		if (csio_is_phys_ln(ln)) {
+			rv = csio_ln_read_fcf_entry(ln,
+					csio_ln_read_fcf_cbfn);
+			if (rv != 0) {
+				/* TODO: Send HW RESET event */
+				CSIO_INC_STATS(ln, n_err);
+				break;
+			}
+
+			/* Add FCF record */
+			list_add_tail(&ln->fcfinfo->list, &rln->fcf_lsthead);
+		}
+
+		rv = csio_ln_vnp_read(ln, csio_ln_vnp_read_cbfn);
+		if (rv != 0) {
+			/* TODO: Send HW RESET event */
+			CSIO_INC_STATS(ln, n_err);
+		}
+		break;
+
+	case CSIO_LNE_LINK_DOWN:
+	case CSIO_LNE_DOWN_LINK:
+	case CSIO_LNE_LOGO:
+		csio_ln_dbg(ln,
+			    "ignoring event %d recv from did x%x"
+			    "in ln state[offline].\n", evt, ln->nport_id);
+		CSIO_INC_STATS(ln, n_evt_drop);
+		break;
+
+	case CSIO_LNE_CLOSE:
+		csio_set_state(&ln->sm, csio_lns_uninit);
+		csio_post_event_rns(ln, CSIO_RNFE_CLOSE);
+		break;
+
+	default:
+		csio_ln_dbg(ln,
+			    "unexp ln event %d recv from did:x%x in "
+			    "ln state[offline]\n", evt, ln->nport_id);
+		CSIO_INC_STATS(ln, n_evt_unexp);
+		CSIO_DB_ASSERT(0);
+		break;
+	} /* switch event */
+}
+
+/*****************************************************************************/
+/* END: Lnode SM                                                             */
+/*****************************************************************************/
+
+static void
+csio_free_fcfinfo(struct kref *kref)
+{
+	struct csio_fcf_info *fcfinfo = container_of(kref,
+						struct csio_fcf_info, kref);
+	kfree(fcfinfo);
+}
+
+/* Helper routines for attributes  */
+/*
+ * csio_lnode_state_to_str - Get current state of FCOE lnode.
+ * @ln - lnode
+ * @str - state of lnode.
+ *
+ */
+void
+csio_lnode_state_to_str(struct csio_lnode *ln, int8_t *str)
+{
+	if (csio_get_state(ln) == ((csio_sm_state_t)csio_lns_uninit)) {
+		strcpy(str, "UNINIT");
+		return;
+	}
+	if (csio_get_state(ln) == ((csio_sm_state_t)csio_lns_ready)) {
+		strcpy(str, "READY");
+		return;
+	}
+	if (csio_get_state(ln) == ((csio_sm_state_t)csio_lns_offline)) {
+		strcpy(str, "OFFLINE");
+		return;
+	}
+	strcpy(str, "UNKNOWN");
+} /* csio_lnode_state_to_str */
+
+
+int
+csio_get_phy_port_stats(struct csio_hw *hw, uint8_t portid,
+			struct fw_fcoe_port_stats *port_stats)
+{
+	struct csio_mb  *mbp;
+	struct fw_fcoe_port_cmd_params portparams;
+	enum fw_retval retval;
+	int idx;
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		csio_err(hw, "FCoE FCF PARAMS command out of memory!\n");
+		return -EINVAL;
+	}
+	portparams.portid = portid;
+
+	for (idx = 1; idx <= 3; idx++) {
+		portparams.idx = (idx-1)*6 + 1;
+		portparams.nstats = 6;
+		if (idx == 3)
+			portparams.nstats = 4;
+		csio_fcoe_read_portparams_init_mb(hw, mbp, CSIO_MB_DEFAULT_TMO,
+							&portparams, NULL);
+		if (csio_mb_issue(hw, mbp)) {
+			csio_err(hw, "Issue of FCoE port params failed!\n");
+			mempool_free(mbp, hw->mb_mempool);
+			return -EINVAL;
+		}
+		csio_mb_process_portparams_rsp(hw, mbp, &retval,
+						&portparams, port_stats);
+	}
+
+	mempool_free(mbp, hw->mb_mempool);
+	return 0;
+}
+
+/*
+ * csio_ln_mgmt_wr_handler -Mgmt Work Request handler.
+ * @wr - WR.
+ * @len - WR len.
+ * This handler is invoked when an outstanding mgmt WR is completed.
+ * Its invoked in the context of FW event worker thread for every
+ * mgmt event received.
+ * Return - none.
+ */
+
+static void
+csio_ln_mgmt_wr_handler(struct csio_hw *hw, void *wr, uint32_t len)
+{
+	struct csio_mgmtm *mgmtm = csio_hw_to_mgmtm(hw);
+	struct csio_ioreq *io_req = NULL;
+	struct fw_fcoe_els_ct_wr *wr_cmd;
+
+
+	wr_cmd = (struct fw_fcoe_els_ct_wr *) wr;
+
+	if (len < sizeof(struct fw_fcoe_els_ct_wr)) {
+		csio_err(mgmtm->hw,
+			 "Invalid ELS CT WR length recvd, len:%x\n", len);
+		mgmtm->stats.n_err++;
+		return;
+	}
+
+	io_req = (struct csio_ioreq *) ((uintptr_t) wr_cmd->cookie);
+	io_req->wr_status = csio_wr_status(wr_cmd);
+
+	/* lookup ioreq exists in our active Q */
+	spin_lock_irq(&hw->lock);
+	if (csio_mgmt_req_lookup(mgmtm, io_req) != 0) {
+		csio_err(mgmtm->hw,
+			"Error- Invalid IO handle recv in WR. handle: %p\n",
+			io_req);
+		mgmtm->stats.n_err++;
+		spin_unlock_irq(&hw->lock);
+		return;
+	}
+
+	mgmtm = csio_hw_to_mgmtm(hw);
+
+	/* Dequeue from active queue */
+	list_del_init(&io_req->sm.sm_list);
+	mgmtm->stats.n_active--;
+	spin_unlock_irq(&hw->lock);
+
+	/* io_req will be freed by completion handler */
+	if (io_req->io_cbfn)
+		io_req->io_cbfn(hw, io_req);
+}
+
+/**
+ * csio_fcoe_fwevt_handler - Event handler for Firmware FCoE events.
+ * @hw:		HW module
+ * @cpl_op:	CPL opcode
+ * @cmd:	FW cmd/WR.
+ *
+ * Process received FCoE cmd/WR event from FW.
+ */
+void
+csio_fcoe_fwevt_handler(struct csio_hw *hw, __u8 cpl_op, __be64 *cmd)
+{
+	struct csio_lnode *ln;
+	struct csio_rnode *rn;
+	uint8_t portid, opcode = *(uint8_t *)cmd;
+	struct fw_fcoe_link_cmd *lcmd;
+	struct fw_wr_hdr *wr;
+	struct fw_rdev_wr *rdev_wr;
+	enum fw_fcoe_link_status lstatus;
+	uint32_t fcfi, rdev_flowid, vnpi;
+	enum csio_ln_ev evt;
+
+	if (cpl_op == CPL_FW6_MSG && opcode == FW_FCOE_LINK_CMD) {
+
+		lcmd = (struct fw_fcoe_link_cmd *)cmd;
+		lstatus = lcmd->lstatus;
+		portid = FW_FCOE_LINK_CMD_PORTID_GET(
+					ntohl(lcmd->op_to_portid));
+		fcfi = FW_FCOE_LINK_CMD_FCFI_GET(ntohl(lcmd->sub_opcode_fcfi));
+		vnpi = FW_FCOE_LINK_CMD_VNPI_GET(ntohl(lcmd->vnpi_pkd));
+
+		if (lstatus == FCOE_LINKUP) {
+
+			/* HW lock here */
+			spin_lock_irq(&hw->lock);
+			csio_handle_link_up(hw, portid, fcfi, vnpi);
+			spin_unlock_irq(&hw->lock);
+			/* HW un lock here */
+
+		} else if (lstatus == FCOE_LINKDOWN) {
+
+			/* HW lock here */
+			spin_lock_irq(&hw->lock);
+			csio_handle_link_down(hw, portid, fcfi, vnpi);
+			spin_unlock_irq(&hw->lock);
+			/* HW un lock here */
+		} else {
+			csio_warn(hw, "Unexpected FCOE LINK status:0x%x\n",
+				    ntohl(lcmd->lstatus));
+			CSIO_INC_STATS(hw, n_cpl_unexp);
+		}
+	} else if (cpl_op == CPL_FW6_PLD) {
+		wr = (struct fw_wr_hdr *) (cmd + 4);
+		if (FW_WR_OP_GET(be32_to_cpu(wr->hi))
+			== FW_RDEV_WR) {
+
+			rdev_wr = (struct fw_rdev_wr *) (cmd + 4);
+
+			rdev_flowid = FW_RDEV_WR_FLOWID_GET(
+					ntohl(rdev_wr->alloc_to_len16));
+			vnpi = FW_RDEV_WR_ASSOC_FLOWID_GET(
+				    ntohl(rdev_wr->flags_to_assoc_flowid));
+
+			csio_dbg(hw,
+				"FW_RDEV_WR: flowid:x%x ev_cause:x%x "
+				"vnpi:0x%x\n", rdev_flowid,
+				rdev_wr->event_cause, vnpi);
+
+			if (rdev_wr->protocol != PROT_FCOE) {
+				csio_err(hw,
+					"FW_RDEV_WR: invalid proto:x%x "
+					"received with flowid:x%x\n",
+					rdev_wr->protocol,
+					rdev_flowid);
+				CSIO_INC_STATS(hw, n_evt_drop);
+				return;
+			}
+
+			/* HW lock here */
+			spin_lock_irq(&hw->lock);
+			ln = csio_ln_lookup_by_vnpi(hw, vnpi);
+			if (!ln) {
+				csio_err(hw,
+					"FW_DEV_WR: invalid vnpi:x%x received "
+					"with flowid:x%x\n", vnpi, rdev_flowid);
+				CSIO_INC_STATS(hw, n_evt_drop);
+				goto out_pld;
+			}
+
+			rn = csio_confirm_rnode(ln, rdev_flowid,
+					&rdev_wr->u.fcoe_rdev);
+			if (!rn) {
+				csio_ln_dbg(ln,
+					"Failed to confirm rnode "
+					"for flowid:x%x\n", rdev_flowid);
+				CSIO_INC_STATS(hw, n_evt_drop);
+				goto out_pld;
+			}
+
+			/* save previous event for debugging */
+			ln->prev_evt = ln->cur_evt;
+			ln->cur_evt = rdev_wr->event_cause;
+			CSIO_INC_STATS(ln, n_evt_fw[rdev_wr->event_cause]);
+
+			/* Translate all the fabric events to lnode SM events */
+			evt = CSIO_FWE_TO_LNE(rdev_wr->event_cause);
+			if (evt) {
+				csio_ln_dbg(ln,
+					"Posting event to lnode event:%d "
+					"cause:%d flowid:x%x\n", evt,
+					rdev_wr->event_cause, rdev_flowid);
+				csio_post_event(&ln->sm, evt);
+			}
+
+			/* Handover event to rn SM here. */
+			csio_rnode_fwevt_handler(rn, rdev_wr->event_cause);
+out_pld:
+			spin_unlock_irq(&hw->lock);
+			return;
+		} else {
+			csio_warn(hw, "unexpected WR op(0x%x) recv\n",
+				FW_WR_OP_GET(be32_to_cpu((wr->hi))));
+			CSIO_INC_STATS(hw, n_cpl_unexp);
+		}
+	} else if (cpl_op == CPL_FW6_MSG) {
+		wr = (struct fw_wr_hdr *) (cmd);
+		if (FW_WR_OP_GET(be32_to_cpu(wr->hi)) == FW_FCOE_ELS_CT_WR) {
+			csio_ln_mgmt_wr_handler(hw, wr,
+					sizeof(struct fw_fcoe_els_ct_wr));
+		} else {
+			csio_warn(hw, "unexpected WR op(0x%x) recv\n",
+				FW_WR_OP_GET(be32_to_cpu((wr->hi))));
+			CSIO_INC_STATS(hw, n_cpl_unexp);
+		}
+	} else {
+		csio_warn(hw, "unexpected CPL op(0x%x) recv\n", opcode);
+		CSIO_INC_STATS(hw, n_cpl_unexp);
+	}
+}
+
+/**
+ * csio_lnode_start - Kickstart lnode discovery.
+ * @ln:		lnode
+ *
+ * This routine kickstarts the discovery by issuing an FCOE_LINK (up) command.
+ */
+int
+csio_lnode_start(struct csio_lnode *ln)
+{
+	int rv = 0;
+	if (csio_is_phys_ln(ln) && !(ln->flags & CSIO_LNF_LINK_ENABLE)) {
+		rv = csio_fcoe_enable_link(ln, 1);
+		ln->flags |= CSIO_LNF_LINK_ENABLE;
+	}
+
+	return rv;
+}
+
+/**
+ * csio_lnode_stop - Stop the lnode.
+ * @ln:		lnode
+ *
+ * This routine is invoked by HW module to stop lnode and its associated NPIV
+ * lnodes.
+ */
+void
+csio_lnode_stop(struct csio_lnode *ln)
+{
+	csio_post_event_lns(ln, CSIO_LNE_DOWN_LINK);
+	if (csio_is_phys_ln(ln) && (ln->flags & CSIO_LNF_LINK_ENABLE)) {
+		csio_fcoe_enable_link(ln, 0);
+		ln->flags &= ~CSIO_LNF_LINK_ENABLE;
+	}
+	csio_ln_dbg(ln, "stopping ln :%p\n", ln);
+}
+
+/**
+ * csio_lnode_close - Close an lnode.
+ * @ln:		lnode
+ *
+ * This routine is invoked by HW module to close an lnode and its
+ * associated NPIV lnodes. Lnode and its associated NPIV lnodes are
+ * set to uninitialized state.
+ */
+void
+csio_lnode_close(struct csio_lnode *ln)
+{
+	csio_post_event_lns(ln, CSIO_LNE_CLOSE);
+	if (csio_is_phys_ln(ln))
+		ln->vnp_flowid = CSIO_INVALID_IDX;
+
+	csio_ln_dbg(ln, "closed ln :%p\n", ln);
+}
+
+/*
+ * csio_ln_prep_ecwr - Prepare ELS/CT WR.
+ * @io_req - IO request.
+ * @wr_len - WR len
+ * @immd_len - WR immediate data
+ * @sub_op - Sub opcode
+ * @sid - source portid.
+ * @did - destination portid
+ * @flow_id - flowid
+ * @fw_wr - ELS/CT WR to be prepared.
+ * Returns: 0 - on success
+ */
+static int
+csio_ln_prep_ecwr(struct csio_ioreq *io_req, uint32_t wr_len,
+		      uint32_t immd_len, uint8_t sub_op, uint32_t sid,
+		      uint32_t did, uint32_t flow_id, uint8_t *fw_wr)
+{
+	struct fw_fcoe_els_ct_wr *wr;
+	uint32_t port_id;
+
+	wr  = (struct fw_fcoe_els_ct_wr *)fw_wr;
+	wr->op_immdlen = cpu_to_be32(FW_WR_OP(FW_FCOE_ELS_CT_WR) |
+				     FW_FCOE_ELS_CT_WR_IMMDLEN(immd_len));
+
+	wr_len =  DIV_ROUND_UP(wr_len, 16);
+	wr->flowid_len16 = cpu_to_be32(FW_WR_FLOWID(flow_id) |
+					  FW_WR_LEN16(wr_len));
+	wr->els_ct_type = sub_op;
+	wr->ctl_pri = 0;
+	wr->cp_en_class = 0;
+	wr->cookie = io_req->fw_handle;
+	wr->iqid = (uint16_t)cpu_to_be16(csio_q_physiqid(
+			io_req->lnode->hwp, io_req->iq_idx));
+	wr->fl_to_sp =  FW_FCOE_ELS_CT_WR_SP(1);
+	wr->tmo_val = (uint8_t) io_req->tmo;
+	port_id = htonl(sid);
+	memcpy(wr->l_id, PORT_ID_PTR(port_id), 3);
+	port_id = htonl(did);
+	memcpy(wr->r_id, PORT_ID_PTR(port_id), 3);
+
+	/* Prepare RSP SGL */
+	wr->rsp_dmalen = cpu_to_be32(io_req->dma_buf.len);
+	wr->rsp_dmaaddr = cpu_to_be64(io_req->dma_buf.paddr);
+	return 0;
+}
+
+/*
+ * csio_ln_mgmt_submit_wr - Post elsct work request.
+ * @mgmtm - mgmtm
+ * @io_req - io request.
+ * @sub_op - ELS or CT request type
+ * @pld - Dma Payload buffer
+ * @pld_len - Payload len
+ * Prepares ELSCT Work request and sents it to FW.
+ * Returns: 0 - on success
+ */
+static int
+csio_ln_mgmt_submit_wr(struct csio_mgmtm *mgmtm, struct csio_ioreq *io_req,
+		uint8_t sub_op, struct csio_dma_buf *pld,
+		uint32_t pld_len)
+{
+	struct csio_wr_pair wrp;
+	struct csio_lnode *ln = io_req->lnode;
+	struct csio_rnode *rn = io_req->rnode;
+	struct	csio_hw	*hw = mgmtm->hw;
+	uint8_t fw_wr[64];
+	struct ulptx_sgl dsgl;
+	uint32_t wr_size = 0;
+	uint8_t im_len = 0;
+	uint32_t wr_off = 0;
+
+	int ret = 0;
+
+	/* Calculate WR Size for this ELS REQ */
+	wr_size = sizeof(struct fw_fcoe_els_ct_wr);
+
+	/* Send as immediate data if pld < 256 */
+	if (pld_len < 256) {
+		wr_size += ALIGN(pld_len, 8);
+		im_len = (uint8_t)pld_len;
+	} else
+		wr_size += sizeof(struct ulptx_sgl);
+
+	/* Roundup WR size in units of 16 bytes */
+	wr_size = ALIGN(wr_size, 16);
+
+	/* Get WR to send ELS REQ */
+	ret = csio_wr_get(hw, mgmtm->eq_idx, wr_size, &wrp);
+	if (ret != 0) {
+		csio_err(hw, "Failed to get WR for ec_req %p ret:%d\n",
+			io_req, ret);
+		return ret;
+	}
+
+	/* Prepare Generic WR used by all ELS/CT cmd */
+	csio_ln_prep_ecwr(io_req, wr_size, im_len, sub_op,
+				ln->nport_id, rn->nport_id,
+				csio_rn_flowid(rn),
+				&fw_wr[0]);
+
+	/* Copy ELS/CT WR CMD */
+	csio_wr_copy_to_wrp(&fw_wr[0], &wrp, wr_off,
+			sizeof(struct fw_fcoe_els_ct_wr));
+	wr_off += sizeof(struct fw_fcoe_els_ct_wr);
+
+	/* Copy payload to Immediate section of WR */
+	if (im_len)
+		csio_wr_copy_to_wrp(pld->vaddr, &wrp, wr_off, im_len);
+	else {
+		/* Program DSGL to dma payload */
+		dsgl.cmd_nsge = htonl(ULPTX_CMD(ULP_TX_SC_DSGL) |
+					ULPTX_MORE | ULPTX_NSGE(1));
+		dsgl.len0 = cpu_to_be32(pld_len);
+		dsgl.addr0 = cpu_to_be64(pld->paddr);
+		csio_wr_copy_to_wrp(&dsgl, &wrp, ALIGN(wr_off, 8),
+				   sizeof(struct ulptx_sgl));
+	}
+
+	/* Issue work request to xmit ELS/CT req to FW */
+	csio_wr_issue(mgmtm->hw, mgmtm->eq_idx, false);
+	return ret;
+}
+
+/*
+ * csio_ln_mgmt_submit_req - Submit FCOE Mgmt request.
+ * @io_req - IO Request
+ * @io_cbfn - Completion handler.
+ * @req_type - ELS or CT request type
+ * @pld - Dma Payload buffer
+ * @pld_len - Payload len
+ *
+ *
+ * This API used submit managment ELS/CT request.
+ * This called with hw lock held
+ * Returns: 0 - on success
+ *	    -ENOMEM	- on error.
+ */
+static int
+csio_ln_mgmt_submit_req(struct csio_ioreq *io_req,
+		void (*io_cbfn) (struct csio_hw *, struct csio_ioreq *),
+		enum fcoe_cmn_type req_type, struct csio_dma_buf *pld,
+		uint32_t pld_len)
+{
+	struct csio_hw *hw = csio_lnode_to_hw(io_req->lnode);
+	struct csio_mgmtm *mgmtm = csio_hw_to_mgmtm(hw);
+	int rv;
+
+	io_req->io_cbfn = io_cbfn;	/* Upper layer callback handler */
+	io_req->fw_handle = (uintptr_t) (io_req);
+	io_req->eq_idx = mgmtm->eq_idx;
+	io_req->iq_idx = mgmtm->iq_idx;
+
+	rv = csio_ln_mgmt_submit_wr(mgmtm, io_req, req_type, pld, pld_len);
+	if (rv == 0) {
+		list_add_tail(&io_req->sm.sm_list, &mgmtm->active_q);
+		mgmtm->stats.n_active++;
+	}
+	return rv;
+}
+
+/*
+ * csio_ln_fdmi_init - FDMI Init entry point.
+ * @ln: lnode
+ */
+static int
+csio_ln_fdmi_init(struct csio_lnode *ln)
+{
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+	struct csio_dma_buf	*dma_buf;
+
+	/* Allocate MGMT request required for FDMI */
+	ln->mgmt_req = kzalloc(sizeof(struct csio_ioreq), GFP_KERNEL);
+	if (!ln->mgmt_req) {
+		csio_ln_err(ln, "Failed to alloc ioreq for FDMI\n");
+		CSIO_INC_STATS(hw, n_err_nomem);
+		return -ENOMEM;
+	}
+
+	/* Allocate Dma buffers for FDMI response Payload */
+	dma_buf = &ln->mgmt_req->dma_buf;
+	dma_buf->len = 2048;
+	dma_buf->vaddr = pci_alloc_consistent(hw->pdev, dma_buf->len,
+						&dma_buf->paddr);
+	if (!dma_buf->vaddr) {
+		csio_err(hw, "Failed to alloc DMA buffer for FDMI!\n");
+		kfree(ln->mgmt_req);
+		ln->mgmt_req = NULL;
+		return -ENOMEM;
+	}
+
+	ln->flags |= CSIO_LNF_FDMI_ENABLE;
+	return 0;
+}
+
+/*
+ * csio_ln_fdmi_exit - FDMI exit entry point.
+ * @ln: lnode
+ */
+static int
+csio_ln_fdmi_exit(struct csio_lnode *ln)
+{
+	struct csio_dma_buf *dma_buf;
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+	if (!ln->mgmt_req)
+		return 0;
+
+	dma_buf = &ln->mgmt_req->dma_buf;
+	if (dma_buf->vaddr)
+		pci_free_consistent(hw->pdev, dma_buf->len, dma_buf->vaddr,
+				    dma_buf->paddr);
+
+	kfree(ln->mgmt_req);
+	return 0;
+}
+
+int
+csio_scan_done(struct csio_lnode *ln, unsigned long ticks,
+		unsigned long time, unsigned long max_scan_ticks,
+		unsigned long delta_scan_ticks)
+{
+	int rv = 0;
+
+	if (time >= max_scan_ticks)
+		return 1;
+
+	if (!ln->tgt_scan_tick)
+		ln->tgt_scan_tick = ticks;
+
+	if (((ticks - ln->tgt_scan_tick) >= delta_scan_ticks)) {
+		if (!ln->last_scan_ntgts)
+			ln->last_scan_ntgts = ln->n_scsi_tgts;
+		else {
+			if (ln->last_scan_ntgts == ln->n_scsi_tgts)
+				return 1;
+
+			ln->last_scan_ntgts = ln->n_scsi_tgts;
+		}
+		ln->tgt_scan_tick = ticks;
+	}
+	return rv;
+}
+
+/*
+ * csio_notify_lnodes:
+ * @hw: HW module
+ * @note: Notification
+ *
+ * Called from the HW SM to fan out notifications to the
+ * Lnode SM. Since the HW SM is entered with lock held,
+ * there is no need to hold locks here.
+ *
+ */
+void
+csio_notify_lnodes(struct csio_hw *hw, enum csio_ln_notify note)
+{
+	struct list_head *tmp;
+	struct csio_lnode *ln;
+
+	csio_dbg(hw, "Notifying all nodes of event %d\n", note);
+
+	/* Traverse children lnodes list and send evt */
+	list_for_each(tmp, &hw->sln_head) {
+		ln = (struct csio_lnode *) tmp;
+
+		switch (note) {
+		case CSIO_LN_NOTIFY_HWREADY:
+			csio_lnode_start(ln);
+			break;
+
+		case CSIO_LN_NOTIFY_HWRESET:
+		case CSIO_LN_NOTIFY_HWREMOVE:
+			csio_lnode_close(ln);
+			break;
+
+		case CSIO_LN_NOTIFY_HWSTOP:
+			csio_lnode_stop(ln);
+			break;
+
+		default:
+			break;
+
+		}
+	}
+}
+
+/*
+ * csio_disable_lnodes:
+ * @hw: HW module
+ * @portid:port id
+ * @disable: disable/enable flag.
+ * If disable=1, disables all lnode hosted on given physical port.
+ * otherwise enables all the lnodes on given phsysical port.
+ * This routine need to called with hw lock held.
+ */
+void
+csio_disable_lnodes(struct csio_hw *hw, uint8_t portid, bool disable)
+{
+	struct list_head *tmp;
+	struct csio_lnode *ln;
+
+	csio_dbg(hw, "Notifying event to all nodes of port:%d\n", portid);
+
+	/* Traverse sibling lnodes list and send evt */
+	list_for_each(tmp, &hw->sln_head) {
+		ln = (struct csio_lnode *) tmp;
+		if (ln->portid != portid)
+			continue;
+
+		if (disable)
+			csio_lnode_stop(ln);
+		else
+			csio_lnode_start(ln);
+	}
+}
+
+/*
+ * csio_ln_init - Initialize an lnode.
+ * @ln:		lnode
+ *
+ */
+static int
+csio_ln_init(struct csio_lnode *ln)
+{
+	int rv = -EINVAL;
+	struct csio_lnode *rln, *pln;
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+	csio_init_state(&ln->sm, csio_lns_uninit);
+	ln->vnp_flowid = CSIO_INVALID_IDX;
+	ln->fcf_flowid = CSIO_INVALID_IDX;
+
+	if (csio_is_root_ln(ln)) {
+
+		/* This is the lnode used during initialization */
+
+		ln->fcfinfo = kzalloc(sizeof(struct csio_fcf_info), GFP_KERNEL);
+		if (!ln->fcfinfo) {
+			csio_ln_err(ln, "Failed to alloc FCF record\n");
+			CSIO_INC_STATS(hw, n_err_nomem);
+			goto err;
+		}
+
+		INIT_LIST_HEAD(&ln->fcf_lsthead);
+		kref_init(&ln->fcfinfo->kref);
+
+		if (csio_fdmi_enable && csio_ln_fdmi_init(ln))
+			goto err;
+
+	} else { /* Either a non-root physical or a virtual lnode */
+
+		/*
+		 * THe rest is common for non-root physical and NPIV lnodes.
+		 * Just get references to all other modules
+		 */
+		rln = csio_root_lnode(ln);
+
+		if (csio_is_npiv_ln(ln)) {
+			/* NPIV */
+			pln = csio_parent_lnode(ln);
+			kref_get(&pln->fcfinfo->kref);
+			ln->fcfinfo = pln->fcfinfo;
+		} else {
+			/* Another non-root physical lnode (FCF) */
+			ln->fcfinfo = kzalloc(sizeof(struct csio_fcf_info),
+								GFP_KERNEL);
+			if (!ln->fcfinfo) {
+				csio_ln_err(ln, "Failed to alloc FCF info\n");
+				CSIO_INC_STATS(hw, n_err_nomem);
+				goto err;
+			}
+
+			kref_init(&ln->fcfinfo->kref);
+
+			if (csio_fdmi_enable && csio_ln_fdmi_init(ln))
+				goto err;
+		}
+
+	} /* if (!csio_is_root_ln(ln)) */
+
+	return 0;
+err:
+	return rv;
+}
+
+static void
+csio_ln_exit(struct csio_lnode *ln)
+{
+	struct csio_lnode *pln;
+
+	csio_cleanup_rns(ln);
+	if (csio_is_npiv_ln(ln)) {
+		pln = csio_parent_lnode(ln);
+		kref_put(&pln->fcfinfo->kref, csio_free_fcfinfo);
+	} else {
+		kref_put(&ln->fcfinfo->kref, csio_free_fcfinfo);
+		if (csio_fdmi_enable)
+			csio_ln_fdmi_exit(ln);
+	}
+	ln->fcfinfo = NULL;
+}
+
+/**
+ * csio_lnode_init - Initialize the members of an lnode.
+ * @ln:		lnode
+ *
+ */
+int
+csio_lnode_init(struct csio_lnode *ln, struct csio_hw *hw,
+		struct csio_lnode *pln)
+{
+	int rv = -EINVAL;
+
+	/* Link this lnode to hw */
+	csio_lnode_to_hw(ln)	= hw;
+
+	/* Link child to parent if child lnode */
+	if (pln)
+		ln->pln = pln;
+	else
+		ln->pln = NULL;
+
+	/* Initialize scsi_tgt and timers to zero */
+	ln->n_scsi_tgts = 0;
+	ln->last_scan_ntgts = 0;
+	ln->tgt_scan_tick = 0;
+
+	/* Initialize rnode list */
+	INIT_LIST_HEAD(&ln->rnhead);
+	INIT_LIST_HEAD(&ln->cln_head);
+
+	/* Initialize log level for debug */
+	ln->params.log_level	= hw->params.log_level;
+
+	if (csio_ln_init(ln))
+		goto err;
+
+	/* Add lnode to list of sibling or children lnodes */
+	spin_lock_irq(&hw->lock);
+	list_add_tail(&ln->sm.sm_list, pln ? &pln->cln_head : &hw->sln_head);
+	if (pln)
+		pln->num_vports++;
+	spin_unlock_irq(&hw->lock);
+
+	hw->num_lns++;
+
+	return 0;
+err:
+	csio_lnode_to_hw(ln) = NULL;
+	return rv;
+}
+
+/**
+ * csio_lnode_exit - De-instantiate an lnode.
+ * @ln:		lnode
+ *
+ */
+void
+csio_lnode_exit(struct csio_lnode *ln)
+{
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+	csio_ln_exit(ln);
+
+	/* Remove this lnode from hw->sln_head */
+	spin_lock_irq(&hw->lock);
+
+	list_del_init(&ln->sm.sm_list);
+
+	/* If it is children lnode, decrement the
+	 * counter in its parent lnode
+	 */
+	if (ln->pln)
+		ln->pln->num_vports--;
+
+	/* Update root lnode pointer */
+	if (list_empty(&hw->sln_head))
+		hw->rln = NULL;
+	else
+		hw->rln = (struct csio_lnode *)csio_list_next(&hw->sln_head);
+
+	spin_unlock_irq(&hw->lock);
+
+	csio_lnode_to_hw(ln)	= NULL;
+	hw->num_lns--;
+}
diff --git a/drivers/scsi/csiostor/csio_lnode.h b/drivers/scsi/csiostor/csio_lnode.h
new file mode 100644
index 0000000..8d84988
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_lnode.h
@@ -0,0 +1,255 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_LNODE_H__
+#define __CSIO_LNODE_H__
+
+#include <linux/kref.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <scsi/fc/fc_els.h>
+
+
+#include "csio_defs.h"
+#include "csio_hw.h"
+
+#define CSIO_FCOE_MAX_NPIV	128
+#define CSIO_FCOE_MAX_RNODES	2048
+
+/* FDMI port attribute unknown speed */
+#define CSIO_HBA_PORTSPEED_UNKNOWN	0x8000
+
+extern int csio_fcoe_rnodes;
+extern int csio_fdmi_enable;
+
+/* State machine evets */
+enum csio_ln_ev {
+	CSIO_LNE_NONE = (uint32_t)0,
+	CSIO_LNE_LINKUP,
+	CSIO_LNE_FAB_INIT_DONE,
+	CSIO_LNE_LINK_DOWN,
+	CSIO_LNE_DOWN_LINK,
+	CSIO_LNE_LOGO,
+	CSIO_LNE_CLOSE,
+	CSIO_LNE_MAX_EVENT,
+};
+
+
+struct csio_fcf_info {
+	struct list_head	list;
+	uint8_t			priority;
+	uint8_t			mac[6];
+	uint8_t			name_id[8];
+	uint8_t			fabric[8];
+	uint16_t		vf_id;
+	uint8_t			vlan_id;
+	uint16_t		max_fcoe_size;
+	uint8_t			fc_map[3];
+	uint32_t		fka_adv;
+	uint32_t		fcfi;
+	uint8_t			get_next:1;
+	uint8_t			link_aff:1;
+	uint8_t			fpma:1;
+	uint8_t			spma:1;
+	uint8_t			login:1;
+	uint8_t			portid;
+	uint8_t			spma_mac[6];
+	struct kref		kref;
+};
+
+/* Defines for flags */
+#define	CSIO_LNF_FIPSUPP		0x00000001	/* Fip Supported */
+#define	CSIO_LNF_NPIVSUPP		0x00000002	/* NPIV supported */
+#define CSIO_LNF_LINK_ENABLE		0x00000004	/* Link enabled */
+#define	CSIO_LNF_FDMI_ENABLE		0x00000008	/* FDMI support */
+
+/* Transport events */
+enum csio_ln_fc_evt {
+	CSIO_LN_FC_LINKUP = 1,
+	CSIO_LN_FC_LINKDOWN,
+	CSIO_LN_FC_RSCN,
+	CSIO_LN_FC_ATTRIB_UPDATE,
+};
+
+/* Lnode stats */
+struct csio_lnode_stats {
+	uint32_t	n_link_up;	/* Link down */
+	uint32_t	n_link_down;	/* Link up */
+	uint32_t	n_err;		/* error */
+	uint32_t	n_err_nomem;	/* memory not available */
+	uint32_t	n_inval_parm;   /* Invalid parameters */
+	uint32_t	n_evt_unexp;	/* unexpected event */
+	uint32_t	n_evt_drop;	/* dropped event */
+	uint32_t	n_rnode_match;  /* matched rnode */
+	uint32_t	n_dev_loss_tmo; /* Device loss timeout */
+	uint32_t	n_fdmi_err;	/* fdmi err */
+	uint32_t	n_evt_fw[RSCN_DEV_LOST];	/* fw events */
+	enum csio_ln_ev	n_evt_sm[CSIO_LNE_MAX_EVENT];	/* State m/c events */
+	uint32_t	n_rnode_alloc;	/* rnode allocated */
+	uint32_t	n_rnode_free;	/* rnode freed */
+	uint32_t	n_rnode_nomem;	/* rnode alloc failure */
+	uint32_t        n_input_requests; /* Input Requests */
+	uint32_t        n_output_requests; /* Output Requests */
+	uint32_t        n_control_requests; /* Control Requests */
+	uint32_t        n_input_bytes; /* Input Bytes */
+	uint32_t        n_output_bytes; /* Output Bytes */
+	uint32_t	rsvd1;
+};
+
+/* Common Lnode params */
+struct csio_lnode_params {
+	uint32_t	ra_tov;
+	uint32_t	fcfi;
+	uint32_t	log_level;	/* Module level for debugging */
+};
+
+struct csio_service_parms {
+	struct fc_els_csp	csp;		/* Common service parms */
+	uint8_t			wwpn[8];	/* WWPN */
+	uint8_t			wwnn[8];	/* WWNN */
+	struct fc_els_cssp	clsp[4];	/* Class service params */
+	uint8_t			vvl[16];	/* Vendor version level */
+};
+
+/* Lnode */
+struct csio_lnode {
+	struct csio_sm		sm;		/* State machine + sibling
+						 * lnode list.
+						 */
+	struct csio_hw		*hwp;		/* Pointer to the HW module */
+	uint8_t			portid;		/* Port ID */
+	uint8_t			rsvd1;
+	uint16_t		rsvd2;
+	uint32_t		dev_num;	/* Device number */
+	uint32_t		flags;		/* Flags */
+	struct list_head	fcf_lsthead;	/* FCF entries */
+	struct csio_fcf_info	*fcfinfo;	/* FCF in use */
+	struct csio_ioreq	*mgmt_req;	/* MGMT request */
+
+	/* FCoE identifiers */
+	uint8_t			mac[6];
+	uint32_t		nport_id;
+	struct csio_service_parms ln_sparm;	/* Service parms */
+
+	/* Firmware identifiers */
+	uint32_t		fcf_flowid;	/*fcf flowid */
+	uint32_t		vnp_flowid;
+	uint16_t		ssn_cnt;	/* Registered Session */
+	uint8_t			cur_evt;	/* Current event */
+	uint8_t			prev_evt;	/* Previous event */
+
+	/* Children */
+	struct list_head	cln_head;	/* Head of the children lnode
+						 * list.
+						 */
+	uint32_t		num_vports;	/* Total NPIV/children LNodes*/
+	struct csio_lnode	*pln;		/* Parent lnode of child
+						 * lnodes.
+						 */
+	struct list_head	cmpl_q;		/* Pending I/Os on this lnode */
+
+	/* Remote node information */
+	struct list_head	rnhead;		/* Head of rnode list */
+	uint32_t		num_reg_rnodes;	/* Number of rnodes registered
+						 * with the host.
+						 */
+	uint32_t		n_scsi_tgts;	/* Number of scsi targets
+						 * found
+						 */
+	uint32_t		last_scan_ntgts;/* Number of scsi targets
+						 * found per last scan.
+						 */
+	uint32_t		tgt_scan_tick;	/* timer started after
+						 * new tgt found
+						 */
+	/* FC transport data */
+	struct fc_vport		*fc_vport;
+	struct fc_host_statistics fch_stats;
+
+	struct csio_lnode_stats stats;		/* Common lnode stats */
+	struct csio_lnode_params params;	/* Common lnode params */
+};
+
+#define	csio_lnode_to_hw(ln)	((ln)->hwp)
+#define csio_root_lnode(ln)	(csio_lnode_to_hw((ln))->rln)
+#define csio_parent_lnode(ln)	((ln)->pln)
+#define	csio_ln_flowid(ln)	((ln)->vnp_flowid)
+#define csio_ln_wwpn(ln)	((ln)->ln_sparm.wwpn)
+#define csio_ln_wwnn(ln)	((ln)->ln_sparm.wwnn)
+
+#define csio_is_root_ln(ln)	(((ln) == csio_root_lnode((ln))) ? 1 : 0)
+#define csio_is_phys_ln(ln)	(((ln)->pln == NULL) ? 1 : 0)
+#define csio_is_npiv_ln(ln)	(((ln)->pln != NULL) ? 1 : 0)
+
+
+#define csio_ln_dbg(_ln, _fmt, ...)	\
+	csio_dbg(_ln->hwp, "%x:%x "_fmt, CSIO_DEVID_HI(_ln), \
+		 CSIO_DEVID_LO(_ln), ##__VA_ARGS__);
+
+#define csio_ln_err(_ln, _fmt, ...)	\
+	csio_err(_ln->hwp, "%x:%x "_fmt, CSIO_DEVID_HI(_ln), \
+		 CSIO_DEVID_LO(_ln), ##__VA_ARGS__);
+
+#define csio_ln_warn(_ln, _fmt, ...)	\
+	csio_warn(_ln->hwp, "%x:%x "_fmt, CSIO_DEVID_HI(_ln), \
+		 CSIO_DEVID_LO(_ln), ##__VA_ARGS__);
+
+/* HW->Lnode notifications */
+enum csio_ln_notify {
+	CSIO_LN_NOTIFY_HWREADY = 1,
+	CSIO_LN_NOTIFY_HWSTOP,
+	CSIO_LN_NOTIFY_HWREMOVE,
+	CSIO_LN_NOTIFY_HWRESET,
+};
+
+void csio_fcoe_fwevt_handler(struct csio_hw *,  __u8 cpl_op, __be64 *);
+int csio_is_lnode_ready(struct csio_lnode *);
+void csio_lnode_state_to_str(struct csio_lnode *ln, int8_t *str);
+struct csio_lnode *csio_lnode_lookup_by_wwpn(struct csio_hw *, uint8_t *);
+int csio_get_phy_port_stats(struct csio_hw *, uint8_t ,
+				      struct fw_fcoe_port_stats *);
+int csio_scan_done(struct csio_lnode *, unsigned long, unsigned long,
+		   unsigned long, unsigned long);
+void csio_notify_lnodes(struct csio_hw *, enum csio_ln_notify);
+void csio_disable_lnodes(struct csio_hw *, uint8_t, bool);
+void csio_lnode_async_event(struct csio_lnode *, enum csio_ln_fc_evt);
+int csio_ln_fdmi_start(struct csio_lnode *, void *);
+int csio_lnode_start(struct csio_lnode *);
+void csio_lnode_stop(struct csio_lnode *);
+void csio_lnode_close(struct csio_lnode *);
+int csio_lnode_init(struct csio_lnode *, struct csio_hw *,
+			      struct csio_lnode *);
+void csio_lnode_exit(struct csio_lnode *);
+
+#endif /* ifndef __CSIO_LNODE_H__ */
diff --git a/drivers/scsi/csiostor/csio_mb.c b/drivers/scsi/csiostor/csio_mb.c
new file mode 100644
index 0000000..7aaf102
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_mb.c
@@ -0,0 +1,1770 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include "csio_hw.h"
+#include "csio_lnode.h"
+#include "csio_rnode.h"
+#include "csio_mb.h"
+#include "csio_wr.h"
+
+#define csio_mb_is_host_owner(__owner)		((__owner) == CSIO_MBOWNER_PL)
+
+/* MB Command/Response Helpers */
+/*
+ * csio_mb_fw_retval - FW return value from a mailbox response.
+ * @mbp: Mailbox structure
+ *
+ */
+enum fw_retval
+csio_mb_fw_retval(struct csio_mb *mbp)
+{
+	struct fw_cmd_hdr *hdr;
+
+	hdr = (struct fw_cmd_hdr *)(mbp->mb);
+
+	return FW_CMD_RETVAL_GET(ntohl(hdr->lo));
+}
+
+/*
+ * csio_mb_hello - FW HELLO command helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @m_mbox: Master mailbox number, if any.
+ * @a_mbox: Mailbox number for asycn notifications.
+ * @master: Device mastership.
+ * @cbfn: Callback, if any.
+ *
+ */
+void
+csio_mb_hello(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+	      uint32_t m_mbox, uint32_t a_mbox, enum csio_dev_master master,
+	      void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_hello_cmd *cmdp = (struct fw_hello_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
+
+	cmdp->op_to_write = htonl(FW_CMD_OP(FW_HELLO_CMD) |
+				       FW_CMD_REQUEST | FW_CMD_WRITE);
+	cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+	cmdp->err_to_clearinit = htonl(
+		FW_HELLO_CMD_MASTERDIS(master == CSIO_MASTER_CANT)	|
+		FW_HELLO_CMD_MASTERFORCE(master == CSIO_MASTER_MUST)	|
+		FW_HELLO_CMD_MBMASTER(master == CSIO_MASTER_MUST ?
+				m_mbox : FW_HELLO_CMD_MBMASTER_MASK)	|
+		FW_HELLO_CMD_MBASYNCNOT(a_mbox) |
+		FW_HELLO_CMD_STAGE(fw_hello_cmd_stage_os) |
+		FW_HELLO_CMD_CLEARINIT);
+
+}
+
+/*
+ * csio_mb_process_hello_rsp - FW HELLO response processing helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @retval: Mailbox return value from Firmware
+ * @state: State that the function is in.
+ * @mpfn: Master pfn
+ *
+ */
+void
+csio_mb_process_hello_rsp(struct csio_hw *hw, struct csio_mb *mbp,
+			  enum fw_retval *retval, enum csio_dev_state *state,
+			  uint8_t *mpfn)
+{
+	struct fw_hello_cmd *rsp = (struct fw_hello_cmd *)(mbp->mb);
+	uint32_t value;
+
+	*retval = FW_CMD_RETVAL_GET(ntohl(rsp->retval_len16));
+
+	if (*retval == FW_SUCCESS) {
+		hw->fwrev = ntohl(rsp->fwrev);
+
+		value = ntohl(rsp->err_to_clearinit);
+		*mpfn = FW_HELLO_CMD_MBMASTER_GET(value);
+
+		if (value & FW_HELLO_CMD_INIT)
+			*state = CSIO_DEV_STATE_INIT;
+		else if (value & FW_HELLO_CMD_ERR)
+			*state = CSIO_DEV_STATE_ERR;
+		else
+			*state = CSIO_DEV_STATE_UNINIT;
+	}
+}
+
+/*
+ * csio_mb_bye - FW BYE command helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @cbfn: Callback, if any.
+ *
+ */
+void
+csio_mb_bye(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+	    void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_bye_cmd *cmdp = (struct fw_bye_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
+
+	cmdp->op_to_write = htonl(FW_CMD_OP(FW_BYE_CMD) |
+				       FW_CMD_REQUEST | FW_CMD_WRITE);
+	cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+}
+
+/*
+ * csio_mb_reset - FW RESET command helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @reset: Type of reset.
+ * @cbfn: Callback, if any.
+ *
+ */
+void
+csio_mb_reset(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+	      int reset, int halt,
+	      void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_reset_cmd *cmdp = (struct fw_reset_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
+
+	cmdp->op_to_write = htonl(FW_CMD_OP(FW_RESET_CMD) |
+				  FW_CMD_REQUEST | FW_CMD_WRITE);
+	cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+	cmdp->val = htonl(reset);
+	cmdp->halt_pkd = htonl(halt);
+
+}
+
+/*
+ * csio_mb_params - FW PARAMS command helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @tmo: Command timeout.
+ * @pf: PF number.
+ * @vf: VF number.
+ * @nparams: Number of paramters
+ * @params: Parameter mnemonic array.
+ * @val: Parameter value array.
+ * @wr: Write/Read PARAMS.
+ * @cbfn: Callback, if any.
+ *
+ */
+void
+csio_mb_params(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+	       unsigned int pf, unsigned int vf, unsigned int nparams,
+	       const u32 *params, u32 *val, bool wr,
+	       void (*cbfn)(struct csio_hw *, struct csio_mb *))
+{
+	uint32_t i;
+	uint32_t temp_params = 0, temp_val = 0;
+	struct fw_params_cmd *cmdp = (struct fw_params_cmd *)(mbp->mb);
+	__be32 *p = &cmdp->param[0].mnem;
+
+	CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
+
+	cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_PARAMS_CMD)		|
+				FW_CMD_REQUEST				|
+				(wr ? FW_CMD_WRITE : FW_CMD_READ)	|
+				FW_PARAMS_CMD_PFN(pf)			|
+				FW_PARAMS_CMD_VFN(vf));
+	cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+	/* Write Params */
+	if (wr) {
+		while (nparams--) {
+			temp_params = *params++;
+			temp_val = *val++;
+
+			*p++ = htonl(temp_params);
+			*p++ = htonl(temp_val);
+		}
+	} else {
+		for (i = 0; i < nparams; i++, p += 2) {
+			temp_params = *params++;
+			*p = htonl(temp_params);
+		}
+	}
+
+}
+
+/*
+ * csio_mb_process_read_params_rsp - FW PARAMS response processing helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @retval: Mailbox return value from Firmware
+ * @nparams: Number of parameters
+ * @val: Parameter value array.
+ *
+ */
+void
+csio_mb_process_read_params_rsp(struct csio_hw *hw, struct csio_mb *mbp,
+			   enum fw_retval *retval, unsigned int nparams,
+			   u32 *val)
+{
+	struct fw_params_cmd *rsp = (struct fw_params_cmd *)(mbp->mb);
+	uint32_t i;
+	__be32 *p = &rsp->param[0].val;
+
+	*retval = FW_CMD_RETVAL_GET(ntohl(rsp->retval_len16));
+
+	if (*retval == FW_SUCCESS)
+		for (i = 0; i < nparams; i++, p += 2)
+			*val++ = ntohl(*p);
+}
+
+/*
+ * csio_mb_ldst - FW LDST command
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @tmo: timeout
+ * @reg: register
+ *
+ */
+void
+csio_mb_ldst(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, int reg)
+{
+	struct fw_ldst_cmd *ldst_cmd = (struct fw_ldst_cmd *)(mbp->mb);
+	CSIO_INIT_MBP(mbp, ldst_cmd, tmo, hw, NULL, 1);
+
+	/*
+	 * Construct and send the Firmware LDST Command to retrieve the
+	 * specified PCI-E Configuration Space register.
+	 */
+	ldst_cmd->op_to_addrspace =
+			htonl(FW_CMD_OP(FW_LDST_CMD)	|
+			FW_CMD_REQUEST			|
+			FW_CMD_READ			|
+			FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FUNC_PCIE));
+	ldst_cmd->cycles_to_len16 = htonl(FW_LEN16(struct fw_ldst_cmd));
+	ldst_cmd->u.pcie.select_naccess = FW_LDST_CMD_NACCESS(1);
+	ldst_cmd->u.pcie.ctrl_to_fn =
+		(FW_LDST_CMD_LC | FW_LDST_CMD_FN(hw->pfn));
+	ldst_cmd->u.pcie.r = (uint8_t)reg;
+}
+
+/*
+ *
+ * csio_mb_caps_config - FW Read/Write Capabilities command helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @wr: Write if 1, Read if 0
+ * @init: Turn on initiator mode.
+ * @tgt: Turn on target mode.
+ * @cofld:  If 1, Control Offload for FCoE
+ * @cbfn: Callback, if any.
+ *
+ * This helper assumes that cmdp has MB payload from a previous CAPS
+ * read command.
+ */
+void
+csio_mb_caps_config(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+		    bool wr, bool init, bool tgt, bool cofld,
+		    void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_caps_config_cmd *cmdp =
+				(struct fw_caps_config_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, wr ? 0 : 1);
+
+	cmdp->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
+				  FW_CMD_REQUEST		|
+				  (wr ? FW_CMD_WRITE : FW_CMD_READ));
+	cmdp->cfvalid_to_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+	/* Read config */
+	if (!wr)
+		return;
+
+	/* Write config */
+	cmdp->fcoecaps = 0;
+
+	if (cofld)
+		cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_CTRL_OFLD);
+	if (init)
+		cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_INITIATOR);
+	if (tgt)
+		cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_TARGET);
+}
+
+void
+csio_rss_glb_config(struct csio_hw *hw, struct csio_mb *mbp,
+		    uint32_t tmo, uint8_t mode, unsigned int flags,
+		    void (*cbfn)(struct csio_hw *, struct csio_mb *))
+{
+	struct fw_rss_glb_config_cmd *cmdp =
+				(struct fw_rss_glb_config_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
+
+	cmdp->op_to_write = htonl(FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) |
+				  FW_CMD_REQUEST | FW_CMD_WRITE);
+	cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+	if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_MANUAL) {
+		cmdp->u.manual.mode_pkd =
+			htonl(FW_RSS_GLB_CONFIG_CMD_MODE(mode));
+	} else if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL) {
+		cmdp->u.basicvirtual.mode_pkd =
+			htonl(FW_RSS_GLB_CONFIG_CMD_MODE(mode));
+		cmdp->u.basicvirtual.synmapen_to_hashtoeplitz = htonl(flags);
+	}
+}
+
+
+/*
+ * csio_mb_pfvf - FW Write PF/VF capabilities command helper.
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @pf:
+ * @vf:
+ * @txq:
+ * @txq_eht_ctrl:
+ * @rxqi:
+ * @rxq:
+ * @tc:
+ * @vi:
+ * @pmask:
+ * @rcaps:
+ * @wxcaps:
+ * @cbfn: Callback, if any.
+ *
+ */
+void
+csio_mb_pfvf(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+	     unsigned int pf, unsigned int vf, unsigned int txq,
+	     unsigned int txq_eth_ctrl, unsigned int rxqi,
+	     unsigned int rxq, unsigned int tc, unsigned int vi,
+	     unsigned int cmask, unsigned int pmask, unsigned int nexactf,
+	     unsigned int rcaps, unsigned int wxcaps,
+	     void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_pfvf_cmd *cmdp = (struct fw_pfvf_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
+
+	cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_PFVF_CMD)			|
+				FW_CMD_REQUEST				|
+				FW_CMD_WRITE				|
+				FW_PFVF_CMD_PFN(pf)			|
+				FW_PFVF_CMD_VFN(vf));
+	cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+	cmdp->niqflint_niq = htonl(FW_PFVF_CMD_NIQFLINT(rxqi)		|
+					     FW_PFVF_CMD_NIQ(rxq));
+
+	cmdp->type_to_neq = htonl(FW_PFVF_CMD_TYPE			|
+				  FW_PFVF_CMD_CMASK(cmask)		|
+				  FW_PFVF_CMD_PMASK(pmask)		|
+				  FW_PFVF_CMD_NEQ(txq));
+	cmdp->tc_to_nexactf = htonl(FW_PFVF_CMD_TC(tc)			|
+				    FW_PFVF_CMD_NVI(vi)			|
+				    FW_PFVF_CMD_NEXACTF(nexactf));
+	cmdp->r_caps_to_nethctrl = htonl(FW_PFVF_CMD_R_CAPS(rcaps)	|
+					 FW_PFVF_CMD_WX_CAPS(wxcaps)	|
+					 FW_PFVF_CMD_NETHCTRL(txq_eth_ctrl));
+}
+
+#define CSIO_ADVERT_MASK     (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\
+			      FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_ANEG)
+
+/*
+ * csio_mb_port- FW PORT command helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @tmo: COmmand timeout
+ * @portid: Port ID to get/set info
+ * @wr: Write/Read PORT information.
+ * @fc: Flow control
+ * @caps: Port capabilites to set.
+ * @cbfn: Callback, if any.
+ *
+ */
+void
+csio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+	     uint8_t portid, bool wr, uint32_t fc, uint16_t caps,
+	     void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_port_cmd *cmdp = (struct fw_port_cmd *)(mbp->mb);
+	unsigned int lfc = 0, mdi = FW_PORT_MDI(FW_PORT_MDI_AUTO);
+
+	CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn,  1);
+
+	cmdp->op_to_portid = htonl(FW_CMD_OP(FW_PORT_CMD)		|
+				   FW_CMD_REQUEST			|
+				   (wr ? FW_CMD_EXEC : FW_CMD_READ)	|
+				   FW_PORT_CMD_PORTID(portid));
+	if (!wr) {
+		cmdp->action_to_len16 = htonl(
+			FW_PORT_CMD_ACTION(FW_PORT_ACTION_GET_PORT_INFO) |
+			FW_CMD_LEN16(sizeof(*cmdp) / 16));
+		return;
+	}
+
+	/* Set port */
+	cmdp->action_to_len16 = htonl(
+			FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) |
+			FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+	if (fc & PAUSE_RX)
+		lfc |= FW_PORT_CAP_FC_RX;
+	if (fc & PAUSE_TX)
+		lfc |= FW_PORT_CAP_FC_TX;
+
+	if (!(caps & FW_PORT_CAP_ANEG))
+		cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) | lfc);
+	else
+		cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) |
+								lfc | mdi);
+}
+
+/*
+ * csio_mb_process_read_port_rsp - FW PORT command response processing helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @retval: Mailbox return value from Firmware
+ * @caps: port capabilities
+ *
+ */
+void
+csio_mb_process_read_port_rsp(struct csio_hw *hw, struct csio_mb *mbp,
+			 enum fw_retval *retval, uint16_t *caps)
+{
+	struct fw_port_cmd *rsp = (struct fw_port_cmd *)(mbp->mb);
+
+	*retval = FW_CMD_RETVAL_GET(ntohl(rsp->action_to_len16));
+
+	if (*retval == FW_SUCCESS)
+		*caps = ntohs(rsp->u.info.pcap);
+}
+
+/*
+ * csio_mb_initialize - FW INITIALIZE command helper
+ * @hw: The HW structure
+ * @mbp: Mailbox structure
+ * @tmo: COmmand timeout
+ * @cbfn: Callback, if any.
+ *
+ */
+void
+csio_mb_initialize(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+		   void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_initialize_cmd *cmdp = (struct fw_initialize_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
+
+	cmdp->op_to_write = htonl(FW_CMD_OP(FW_INITIALIZE_CMD)	|
+				  FW_CMD_REQUEST | FW_CMD_WRITE);
+	cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+}
+
+/*
+ * csio_mb_iq_alloc - Initializes the mailbox to allocate an
+ *				Ingress DMA queue in the firmware.
+ *
+ * @hw: The hw structure
+ * @mbp: Mailbox structure to initialize
+ * @priv: Private object
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @iq_params: Ingress queue params needed for allocation.
+ * @cbfn: The call-back function
+ *
+ *
+ */
+static void
+csio_mb_iq_alloc(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
+		 uint32_t mb_tmo, struct csio_iq_params *iq_params,
+		 void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
+
+	cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_IQ_CMD)		|
+				FW_CMD_REQUEST | FW_CMD_EXEC	|
+				FW_IQ_CMD_PFN(iq_params->pfn)	|
+				FW_IQ_CMD_VFN(iq_params->vfn));
+
+	cmdp->alloc_to_len16 = htonl(FW_IQ_CMD_ALLOC		|
+				FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+	cmdp->type_to_iqandstindex = htonl(
+				FW_IQ_CMD_VIID(iq_params->viid)	|
+				FW_IQ_CMD_TYPE(iq_params->type)	|
+				FW_IQ_CMD_IQASYNCH(iq_params->iqasynch));
+
+	cmdp->fl0size = htons(iq_params->fl0size);
+	cmdp->fl0size = htons(iq_params->fl1size);
+
+} /* csio_mb_iq_alloc */
+
+/*
+ * csio_mb_iq_write - Initializes the mailbox for writing into an
+ *				Ingress DMA Queue.
+ *
+ * @hw: The HW structure
+ * @mbp: Mailbox structure to initialize
+ * @priv: Private object
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @cascaded_req: TRUE - if this request is cascased with iq-alloc request.
+ * @iq_params: Ingress queue params needed for writing.
+ * @cbfn: The call-back function
+ *
+ * NOTE: We OR relevant bits with cmdp->XXX, instead of just equating,
+ * because this IQ write request can be cascaded with a previous
+ * IQ alloc request, and we dont want to over-write the bits set by
+ * that request. This logic will work even in a non-cascaded case, since the
+ * cmdp structure is zeroed out by CSIO_INIT_MBP.
+ */
+static void
+csio_mb_iq_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
+		 uint32_t mb_tmo, bool cascaded_req,
+		 struct csio_iq_params *iq_params,
+		 void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb);
+
+	uint32_t iq_start_stop = (iq_params->iq_start)	?
+					FW_IQ_CMD_IQSTART(1) :
+					FW_IQ_CMD_IQSTOP(1);
+
+	/*
+	 * If this IQ write is cascaded with IQ alloc request, do not
+	 * re-initialize with 0's.
+	 *
+	 */
+	if (!cascaded_req)
+		CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
+
+	cmdp->op_to_vfn |= htonl(FW_CMD_OP(FW_IQ_CMD)		|
+				FW_CMD_REQUEST | FW_CMD_WRITE	|
+				FW_IQ_CMD_PFN(iq_params->pfn)	|
+				FW_IQ_CMD_VFN(iq_params->vfn));
+	cmdp->alloc_to_len16 |= htonl(iq_start_stop |
+				FW_CMD_LEN16(sizeof(*cmdp) / 16));
+	cmdp->iqid |= htons(iq_params->iqid);
+	cmdp->fl0id |= htons(iq_params->fl0id);
+	cmdp->fl1id |= htons(iq_params->fl1id);
+	cmdp->type_to_iqandstindex |= htonl(
+			FW_IQ_CMD_IQANDST(iq_params->iqandst)	|
+			FW_IQ_CMD_IQANUS(iq_params->iqanus)	|
+			FW_IQ_CMD_IQANUD(iq_params->iqanud)	|
+			FW_IQ_CMD_IQANDSTINDEX(iq_params->iqandstindex));
+	cmdp->iqdroprss_to_iqesize |= htons(
+			FW_IQ_CMD_IQPCIECH(iq_params->iqpciech)		|
+			FW_IQ_CMD_IQDCAEN(iq_params->iqdcaen)		|
+			FW_IQ_CMD_IQDCACPU(iq_params->iqdcacpu)		|
+			FW_IQ_CMD_IQINTCNTTHRESH(iq_params->iqintcntthresh) |
+			FW_IQ_CMD_IQCPRIO(iq_params->iqcprio)		|
+			FW_IQ_CMD_IQESIZE(iq_params->iqesize));
+
+	cmdp->iqsize |= htons(iq_params->iqsize);
+	cmdp->iqaddr |= cpu_to_be64(iq_params->iqaddr);
+
+	if (iq_params->type == 0) {
+		cmdp->iqns_to_fl0congen |= htonl(
+			FW_IQ_CMD_IQFLINTIQHSEN(iq_params->iqflintiqhsen)|
+			FW_IQ_CMD_IQFLINTCONGEN(iq_params->iqflintcongen));
+	}
+
+	if (iq_params->fl0size && iq_params->fl0addr &&
+	    (iq_params->fl0id != 0xFFFF)) {
+
+		cmdp->iqns_to_fl0congen |= htonl(
+			FW_IQ_CMD_FL0HOSTFCMODE(iq_params->fl0hostfcmode)|
+			FW_IQ_CMD_FL0CPRIO(iq_params->fl0cprio)		|
+			FW_IQ_CMD_FL0PADEN(iq_params->fl0paden)		|
+			FW_IQ_CMD_FL0PACKEN(iq_params->fl0packen));
+		cmdp->fl0dcaen_to_fl0cidxfthresh |= htons(
+			FW_IQ_CMD_FL0DCAEN(iq_params->fl0dcaen)		|
+			FW_IQ_CMD_FL0DCACPU(iq_params->fl0dcacpu)	|
+			FW_IQ_CMD_FL0FBMIN(iq_params->fl0fbmin)		|
+			FW_IQ_CMD_FL0FBMAX(iq_params->fl0fbmax)		|
+			FW_IQ_CMD_FL0CIDXFTHRESH(iq_params->fl0cidxfthresh));
+		cmdp->fl0size |= htons(iq_params->fl0size);
+		cmdp->fl0addr |= cpu_to_be64(iq_params->fl0addr);
+	}
+} /* csio_mb_iq_write */
+
+/*
+ * csio_mb_iq_alloc_write - Initializes the mailbox for allocating an
+ *				Ingress DMA Queue.
+ *
+ * @hw: The HW structure
+ * @mbp: Mailbox structure to initialize
+ * @priv: Private data.
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @iq_params: Ingress queue params needed for allocation & writing.
+ * @cbfn: The call-back function
+ *
+ *
+ */
+void
+csio_mb_iq_alloc_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
+		       uint32_t mb_tmo, struct csio_iq_params *iq_params,
+		       void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	csio_mb_iq_alloc(hw, mbp, priv, mb_tmo, iq_params, cbfn);
+	csio_mb_iq_write(hw, mbp, priv, mb_tmo, true, iq_params, cbfn);
+} /* csio_mb_iq_alloc_write */
+
+/*
+ * csio_mb_iq_alloc_write_rsp - Process the allocation & writing
+ *				of ingress DMA queue mailbox's response.
+ *
+ * @hw: The HW structure.
+ * @mbp: Mailbox structure to initialize.
+ * @retval: Firmware return value.
+ * @iq_params: Ingress queue parameters, after allocation and write.
+ *
+ */
+void
+csio_mb_iq_alloc_write_rsp(struct csio_hw *hw, struct csio_mb *mbp,
+			   enum fw_retval *ret_val,
+			   struct csio_iq_params *iq_params)
+{
+	struct fw_iq_cmd *rsp = (struct fw_iq_cmd *)(mbp->mb);
+
+	*ret_val = FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16));
+	if (*ret_val == FW_SUCCESS) {
+		iq_params->physiqid = ntohs(rsp->physiqid);
+		iq_params->iqid = ntohs(rsp->iqid);
+		iq_params->fl0id = ntohs(rsp->fl0id);
+		iq_params->fl1id = ntohs(rsp->fl1id);
+	} else {
+		iq_params->physiqid = iq_params->iqid =
+		iq_params->fl0id = iq_params->fl1id = 0;
+	}
+} /* csio_mb_iq_alloc_write_rsp */
+
+/*
+ * csio_mb_iq_free - Initializes the mailbox for freeing a
+ *				specified Ingress DMA Queue.
+ *
+ * @hw: The HW structure
+ * @mbp: Mailbox structure to initialize
+ * @priv: Private data
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @iq_params: Parameters of ingress queue, that is to be freed.
+ * @cbfn: The call-back function
+ *
+ *
+ */
+void
+csio_mb_iq_free(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
+		uint32_t mb_tmo, struct csio_iq_params *iq_params,
+		void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
+
+	cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_IQ_CMD)		|
+				FW_CMD_REQUEST | FW_CMD_EXEC	|
+				FW_IQ_CMD_PFN(iq_params->pfn)	|
+				FW_IQ_CMD_VFN(iq_params->vfn));
+	cmdp->alloc_to_len16 = htonl(FW_IQ_CMD_FREE		|
+				FW_CMD_LEN16(sizeof(*cmdp) / 16));
+	cmdp->type_to_iqandstindex = htonl(FW_IQ_CMD_TYPE(iq_params->type));
+
+	cmdp->iqid = htons(iq_params->iqid);
+	cmdp->fl0id = htons(iq_params->fl0id);
+	cmdp->fl1id = htons(iq_params->fl1id);
+
+} /* csio_mb_iq_free */
+
+/*
+ * csio_mb_eq_ofld_alloc - Initializes the mailbox for allocating
+ *				an offload-egress queue.
+ *
+ * @hw: The HW  structure
+ * @mbp: Mailbox structure to initialize
+ * @priv: Private data
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @eq_ofld_params: (Offload) Egress queue paramters.
+ * @cbfn: The call-back function
+ *
+ *
+ */
+static void
+csio_mb_eq_ofld_alloc(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
+		uint32_t mb_tmo, struct csio_eq_params *eq_ofld_params,
+		void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
+	cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_EQ_OFLD_CMD)		|
+				FW_CMD_REQUEST | FW_CMD_EXEC		|
+				FW_EQ_OFLD_CMD_PFN(eq_ofld_params->pfn) |
+				FW_EQ_OFLD_CMD_VFN(eq_ofld_params->vfn));
+	cmdp->alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_ALLOC	|
+				FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+} /* csio_mb_eq_ofld_alloc */
+
+/*
+ * csio_mb_eq_ofld_write - Initializes the mailbox for writing
+ *				an alloacted offload-egress queue.
+ *
+ * @hw: The HW structure
+ * @mbp: Mailbox structure to initialize
+ * @priv: Private data
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @cascaded_req: TRUE - if this request is cascased with Eq-alloc request.
+ * @eq_ofld_params: (Offload) Egress queue paramters.
+ * @cbfn: The call-back function
+ *
+ *
+ * NOTE: We OR relevant bits with cmdp->XXX, instead of just equating,
+ * because this EQ write request can be cascaded with a previous
+ * EQ alloc request, and we dont want to over-write the bits set by
+ * that request. This logic will work even in a non-cascaded case, since the
+ * cmdp structure is zeroed out by CSIO_INIT_MBP.
+ */
+static void
+csio_mb_eq_ofld_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
+		      uint32_t mb_tmo, bool cascaded_req,
+		      struct csio_eq_params *eq_ofld_params,
+		      void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb);
+
+	uint32_t eq_start_stop = (eq_ofld_params->eqstart)	?
+				FW_EQ_OFLD_CMD_EQSTART	: FW_EQ_OFLD_CMD_EQSTOP;
+
+	/*
+	 * If this EQ write is cascaded with EQ alloc request, do not
+	 * re-initialize with 0's.
+	 *
+	 */
+	if (!cascaded_req)
+		CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
+
+	cmdp->op_to_vfn |= htonl(FW_CMD_OP(FW_EQ_OFLD_CMD)	|
+				FW_CMD_REQUEST | FW_CMD_WRITE	|
+				FW_EQ_OFLD_CMD_PFN(eq_ofld_params->pfn) |
+				FW_EQ_OFLD_CMD_VFN(eq_ofld_params->vfn));
+	cmdp->alloc_to_len16 |= htonl(eq_start_stop		|
+				      FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+	cmdp->eqid_pkd |= htonl(FW_EQ_OFLD_CMD_EQID(eq_ofld_params->eqid));
+
+	cmdp->fetchszm_to_iqid |= htonl(
+		FW_EQ_OFLD_CMD_HOSTFCMODE(eq_ofld_params->hostfcmode)	|
+		FW_EQ_OFLD_CMD_CPRIO(eq_ofld_params->cprio)		|
+		FW_EQ_OFLD_CMD_PCIECHN(eq_ofld_params->pciechn)		|
+		FW_EQ_OFLD_CMD_IQID(eq_ofld_params->iqid));
+
+	cmdp->dcaen_to_eqsize |= htonl(
+		FW_EQ_OFLD_CMD_DCAEN(eq_ofld_params->dcaen)		|
+		FW_EQ_OFLD_CMD_DCACPU(eq_ofld_params->dcacpu)		|
+		FW_EQ_OFLD_CMD_FBMIN(eq_ofld_params->fbmin)		|
+		FW_EQ_OFLD_CMD_FBMAX(eq_ofld_params->fbmax)		|
+		FW_EQ_OFLD_CMD_CIDXFTHRESHO(eq_ofld_params->cidxfthresho) |
+		FW_EQ_OFLD_CMD_CIDXFTHRESH(eq_ofld_params->cidxfthresh) |
+		FW_EQ_OFLD_CMD_EQSIZE(eq_ofld_params->eqsize));
+
+	cmdp->eqaddr |= cpu_to_be64(eq_ofld_params->eqaddr);
+
+} /* csio_mb_eq_ofld_write */
+
+/*
+ * csio_mb_eq_ofld_alloc_write - Initializes the mailbox for allocation
+ *				writing into an Engress DMA Queue.
+ *
+ * @hw: The HW structure
+ * @mbp: Mailbox structure to initialize
+ * @priv: Private data.
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @eq_ofld_params: (Offload) Egress queue paramters.
+ * @cbfn: The call-back function
+ *
+ *
+ */
+void
+csio_mb_eq_ofld_alloc_write(struct csio_hw *hw, struct csio_mb *mbp,
+			    void *priv, uint32_t mb_tmo,
+			    struct csio_eq_params *eq_ofld_params,
+			    void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	csio_mb_eq_ofld_alloc(hw, mbp, priv, mb_tmo, eq_ofld_params, cbfn);
+	csio_mb_eq_ofld_write(hw, mbp, priv, mb_tmo, true,
+			      eq_ofld_params, cbfn);
+} /* csio_mb_eq_ofld_alloc_write */
+
+/*
+ * csio_mb_eq_ofld_alloc_write_rsp - Process the allocation
+ *				& write egress DMA queue mailbox's response.
+ *
+ * @hw: The HW structure.
+ * @mbp: Mailbox structure to initialize.
+ * @retval: Firmware return value.
+ * @eq_ofld_params: (Offload) Egress queue paramters.
+ *
+ */
+void
+csio_mb_eq_ofld_alloc_write_rsp(struct csio_hw *hw,
+				struct csio_mb *mbp, enum fw_retval *ret_val,
+				struct csio_eq_params *eq_ofld_params)
+{
+	struct fw_eq_ofld_cmd *rsp = (struct fw_eq_ofld_cmd *)(mbp->mb);
+
+	*ret_val = FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16));
+
+	if (*ret_val == FW_SUCCESS) {
+		eq_ofld_params->eqid = FW_EQ_OFLD_CMD_EQID_GET(
+						ntohl(rsp->eqid_pkd));
+		eq_ofld_params->physeqid = FW_EQ_OFLD_CMD_PHYSEQID_GET(
+						ntohl(rsp->physeqid_pkd));
+	} else
+		eq_ofld_params->eqid = 0;
+
+} /* csio_mb_eq_ofld_alloc_write_rsp */
+
+/*
+ * csio_mb_eq_ofld_free - Initializes the mailbox for freeing a
+ *				specified Engress DMA Queue.
+ *
+ * @hw: The HW structure
+ * @mbp: Mailbox structure to initialize
+ * @priv: Private data area.
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @eq_ofld_params: (Offload) Egress queue paramters, that is to be freed.
+ * @cbfn: The call-back function
+ *
+ *
+ */
+void
+csio_mb_eq_ofld_free(struct csio_hw *hw, struct csio_mb *mbp, void *priv,
+		     uint32_t mb_tmo, struct csio_eq_params *eq_ofld_params,
+		     void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
+
+	cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_EQ_OFLD_CMD)	|
+				FW_CMD_REQUEST | FW_CMD_EXEC	|
+				FW_EQ_OFLD_CMD_PFN(eq_ofld_params->pfn) |
+				FW_EQ_OFLD_CMD_VFN(eq_ofld_params->vfn));
+	cmdp->alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_FREE |
+				FW_CMD_LEN16(sizeof(*cmdp) / 16));
+	cmdp->eqid_pkd = htonl(FW_EQ_OFLD_CMD_EQID(eq_ofld_params->eqid));
+
+} /* csio_mb_eq_ofld_free */
+
+/*
+ * csio_write_fcoe_link_cond_init_mb - Initialize Mailbox to write FCoE link
+ *				 condition.
+ *
+ * @ln: The Lnode structure
+ * @mbp: Mailbox structure to initialize
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @cbfn: The call back function.
+ *
+ *
+ */
+void
+csio_write_fcoe_link_cond_init_mb(struct csio_lnode *ln, struct csio_mb *mbp,
+			uint32_t mb_tmo, uint8_t port_id, uint32_t sub_opcode,
+			uint8_t cos, bool link_status, uint32_t fcfi,
+			void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_fcoe_link_cmd *cmdp =
+				(struct fw_fcoe_link_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
+
+	cmdp->op_to_portid = htonl((
+			FW_CMD_OP(FW_FCOE_LINK_CMD)		|
+			FW_CMD_REQUEST				|
+			FW_CMD_WRITE				|
+			FW_FCOE_LINK_CMD_PORTID(port_id)));
+	cmdp->sub_opcode_fcfi = htonl(
+			FW_FCOE_LINK_CMD_SUB_OPCODE(sub_opcode)	|
+			FW_FCOE_LINK_CMD_FCFI(fcfi));
+	cmdp->lstatus = link_status;
+	cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+} /* csio_write_fcoe_link_cond_init_mb */
+
+/*
+ * csio_fcoe_read_res_info_init_mb - Initializes the mailbox for reading FCoE
+ *				resource information(FW_GET_RES_INFO_CMD).
+ *
+ * @hw: The HW structure
+ * @mbp: Mailbox structure to initialize
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @cbfn: The call-back function
+ *
+ *
+ */
+void
+csio_fcoe_read_res_info_init_mb(struct csio_hw *hw, struct csio_mb *mbp,
+			uint32_t mb_tmo,
+			void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_fcoe_res_info_cmd *cmdp =
+			(struct fw_fcoe_res_info_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, hw, cbfn, 1);
+
+	cmdp->op_to_read = htonl((FW_CMD_OP(FW_FCOE_RES_INFO_CMD)	|
+				  FW_CMD_REQUEST			|
+				  FW_CMD_READ));
+
+	cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+} /* csio_fcoe_read_res_info_init_mb */
+
+/*
+ * csio_fcoe_vnp_alloc_init_mb - Initializes the mailbox for allocating VNP
+ *				in the firmware (FW_FCOE_VNP_CMD).
+ *
+ * @ln: The Lnode structure.
+ * @mbp: Mailbox structure to initialize.
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @fcfi: FCF Index.
+ * @vnpi: vnpi
+ * @iqid: iqid
+ * @vnport_wwnn: vnport WWNN
+ * @vnport_wwpn: vnport WWPN
+ * @cbfn: The call-back function.
+ *
+ *
+ */
+void
+csio_fcoe_vnp_alloc_init_mb(struct csio_lnode *ln, struct csio_mb *mbp,
+		uint32_t mb_tmo, uint32_t fcfi, uint32_t vnpi, uint16_t iqid,
+		uint8_t vnport_wwnn[8],	uint8_t vnport_wwpn[8],
+		void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_fcoe_vnp_cmd *cmdp =
+			(struct fw_fcoe_vnp_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
+
+	cmdp->op_to_fcfi = htonl((FW_CMD_OP(FW_FCOE_VNP_CMD)		|
+				  FW_CMD_REQUEST			|
+				  FW_CMD_EXEC				|
+				  FW_FCOE_VNP_CMD_FCFI(fcfi)));
+
+	cmdp->alloc_to_len16 = htonl(FW_FCOE_VNP_CMD_ALLOC		|
+				     FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+	cmdp->gen_wwn_to_vnpi = htonl(FW_FCOE_VNP_CMD_VNPI(vnpi));
+
+	cmdp->iqid = htons(iqid);
+
+	if (!wwn_to_u64(vnport_wwnn) && !wwn_to_u64(vnport_wwpn))
+		cmdp->gen_wwn_to_vnpi |= htonl(FW_FCOE_VNP_CMD_GEN_WWN);
+
+	if (vnport_wwnn)
+		memcpy(cmdp->vnport_wwnn, vnport_wwnn, 8);
+	if (vnport_wwpn)
+		memcpy(cmdp->vnport_wwpn, vnport_wwpn, 8);
+
+} /* csio_fcoe_vnp_alloc_init_mb */
+
+/*
+ * csio_fcoe_vnp_read_init_mb - Prepares VNP read cmd.
+ * @ln: The Lnode structure.
+ * @mbp: Mailbox structure to initialize.
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @fcfi: FCF Index.
+ * @vnpi: vnpi
+ * @cbfn: The call-back handler.
+ */
+void
+csio_fcoe_vnp_read_init_mb(struct csio_lnode *ln, struct csio_mb *mbp,
+		uint32_t mb_tmo, uint32_t fcfi, uint32_t vnpi,
+		void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_fcoe_vnp_cmd *cmdp =
+			(struct fw_fcoe_vnp_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
+	cmdp->op_to_fcfi = htonl(FW_CMD_OP(FW_FCOE_VNP_CMD)	|
+				 FW_CMD_REQUEST			|
+				 FW_CMD_READ			|
+				 FW_FCOE_VNP_CMD_FCFI(fcfi));
+	cmdp->alloc_to_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+	cmdp->gen_wwn_to_vnpi = htonl(FW_FCOE_VNP_CMD_VNPI(vnpi));
+}
+
+/*
+ * csio_fcoe_vnp_free_init_mb - Initializes the mailbox for freeing an
+ *			alloacted VNP in the firmware (FW_FCOE_VNP_CMD).
+ *
+ * @ln: The Lnode structure.
+ * @mbp: Mailbox structure to initialize.
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @fcfi: FCF flow id
+ * @vnpi: VNP flow id
+ * @cbfn: The call-back function.
+ * Return: None
+ */
+void
+csio_fcoe_vnp_free_init_mb(struct csio_lnode *ln, struct csio_mb *mbp,
+		uint32_t mb_tmo, uint32_t fcfi, uint32_t vnpi,
+		void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_fcoe_vnp_cmd *cmdp =
+			(struct fw_fcoe_vnp_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
+
+	cmdp->op_to_fcfi = htonl(FW_CMD_OP(FW_FCOE_VNP_CMD)	|
+				 FW_CMD_REQUEST			|
+				 FW_CMD_EXEC			|
+				 FW_FCOE_VNP_CMD_FCFI(fcfi));
+	cmdp->alloc_to_len16 = htonl(FW_FCOE_VNP_CMD_FREE	|
+				     FW_CMD_LEN16(sizeof(*cmdp) / 16));
+	cmdp->gen_wwn_to_vnpi = htonl(FW_FCOE_VNP_CMD_VNPI(vnpi));
+}
+
+/*
+ * csio_fcoe_read_fcf_init_mb - Initializes the mailbox to read the
+ *				FCF records.
+ *
+ * @ln: The Lnode structure
+ * @mbp: Mailbox structure to initialize
+ * @mb_tmo: Mailbox time-out period (in ms).
+ * @fcf_params: FC-Forwarder parameters.
+ * @cbfn: The call-back function
+ *
+ *
+ */
+void
+csio_fcoe_read_fcf_init_mb(struct csio_lnode *ln, struct csio_mb *mbp,
+		uint32_t mb_tmo, uint32_t portid, uint32_t fcfi,
+		void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct fw_fcoe_fcf_cmd *cmdp =
+			(struct fw_fcoe_fcf_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
+
+	cmdp->op_to_fcfi = htonl(FW_CMD_OP(FW_FCOE_FCF_CMD)	|
+				 FW_CMD_REQUEST			|
+				 FW_CMD_READ			|
+				 FW_FCOE_FCF_CMD_FCFI(fcfi));
+	cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
+
+} /* csio_fcoe_read_fcf_init_mb */
+
+void
+csio_fcoe_read_portparams_init_mb(struct csio_hw *hw, struct csio_mb *mbp,
+				uint32_t mb_tmo,
+				struct fw_fcoe_port_cmd_params *portparams,
+				void (*cbfn)(struct csio_hw *,
+					     struct csio_mb *))
+{
+	struct fw_fcoe_stats_cmd *cmdp = (struct fw_fcoe_stats_cmd *)(mbp->mb);
+
+	CSIO_INIT_MBP(mbp, cmdp, mb_tmo, hw, cbfn, 1);
+	mbp->mb_size = 64;
+
+	cmdp->op_to_flowid = htonl(FW_CMD_OP(FW_FCOE_STATS_CMD)         |
+				   FW_CMD_REQUEST | FW_CMD_READ);
+	cmdp->free_to_len16 = htonl(FW_CMD_LEN16(CSIO_MAX_MB_SIZE/16));
+
+	cmdp->u.ctl.nstats_port = FW_FCOE_STATS_CMD_NSTATS(portparams->nstats) |
+				  FW_FCOE_STATS_CMD_PORT(portparams->portid);
+
+	cmdp->u.ctl.port_valid_ix = FW_FCOE_STATS_CMD_IX(portparams->idx)    |
+				    FW_FCOE_STATS_CMD_PORT_VALID;
+
+} /* csio_fcoe_read_portparams_init_mb */
+
+void
+csio_mb_process_portparams_rsp(
+				struct csio_hw *hw,
+				struct csio_mb *mbp,
+				enum fw_retval *retval,
+				struct fw_fcoe_port_cmd_params *portparams,
+				struct fw_fcoe_port_stats  *portstats
+			     )
+{
+	struct fw_fcoe_stats_cmd *rsp = (struct fw_fcoe_stats_cmd *)(mbp->mb);
+	struct fw_fcoe_port_stats stats;
+	uint8_t *src;
+	uint8_t *dst;
+
+	*retval = FW_CMD_RETVAL_GET(ntohl(rsp->free_to_len16));
+
+	memset(&stats, 0, sizeof(struct fw_fcoe_port_stats));
+
+	if (*retval == FW_SUCCESS) {
+		dst = (uint8_t *)(&stats) + ((portparams->idx - 1) * 8);
+		src = (uint8_t *)rsp + (CSIO_STATS_OFFSET * 8);
+		memcpy(dst, src, (portparams->nstats * 8));
+		if (portparams->idx == 1) {
+			/* Get the first 6 flits from the Mailbox */
+			portstats->tx_bcast_bytes	=
+					be64_to_cpu(stats.tx_bcast_bytes);
+			portstats->tx_bcast_frames	=
+					be64_to_cpu(stats.tx_bcast_frames);
+			portstats->tx_mcast_bytes	=
+					be64_to_cpu(stats.tx_mcast_bytes);
+			portstats->tx_mcast_frames	=
+					be64_to_cpu(stats.tx_mcast_frames);
+			portstats->tx_ucast_bytes	=
+					be64_to_cpu(stats.tx_ucast_bytes);
+			portstats->tx_ucast_frames	=
+					be64_to_cpu(stats.tx_ucast_frames);
+		}
+		if (portparams->idx == 7) {
+			/* Get the second 6 flits from the Mailbox */
+			portstats->tx_drop_frames	=
+				be64_to_cpu(stats.tx_drop_frames);
+			portstats->tx_offload_bytes	=
+				be64_to_cpu(stats.tx_offload_bytes);
+			portstats->tx_offload_frames	=
+				be64_to_cpu(stats.tx_offload_frames);
+#if 0
+			portstats->rx_pf_bytes		=
+					be64_to_cpu(stats.rx_pf_bytes);
+			portstats->rx_pf_frames		=
+					be64_to_cpu(stats.rx_pf_frames);
+#endif
+			portstats->rx_bcast_bytes	=
+					be64_to_cpu(stats.rx_bcast_bytes);
+			portstats->rx_bcast_frames	=
+					be64_to_cpu(stats.rx_bcast_frames);
+			portstats->rx_mcast_bytes	=
+					be64_to_cpu(stats.rx_mcast_bytes);
+		}
+		if (portparams->idx == 13) {
+			/* Get the last 4 flits from the Mailbox */
+			portstats->rx_mcast_frames	=
+					be64_to_cpu(stats.rx_mcast_frames);
+			portstats->rx_ucast_bytes	=
+					be64_to_cpu(stats.rx_ucast_bytes);
+			portstats->rx_ucast_frames	=
+					be64_to_cpu(stats.rx_ucast_frames);
+			portstats->rx_err_frames	=
+					be64_to_cpu(stats.rx_err_frames);
+		}
+	}
+}
+
+/* Entry points/APIs for MB module					     */
+/*
+ * csio_mb_intr_enable - Enable Interrupts from mailboxes.
+ * @hw: The HW structure
+ *
+ * Enables CIM interrupt bit in appropriate INT_ENABLE registers.
+ */
+void
+csio_mb_intr_enable(struct csio_hw *hw)
+{
+	csio_wr_reg32(hw, MBMSGRDYINTEN(1), MYPF_REG(CIM_PF_HOST_INT_ENABLE));
+	csio_rd_reg32(hw, MYPF_REG(CIM_PF_HOST_INT_ENABLE));
+}
+
+/*
+ * csio_mb_intr_disable - Disable Interrupts from mailboxes.
+ * @hw: The HW structure
+ *
+ * Disable bit in HostInterruptEnable CIM register.
+ */
+void
+csio_mb_intr_disable(struct csio_hw *hw)
+{
+	csio_wr_reg32(hw, MBMSGRDYINTEN(0), MYPF_REG(CIM_PF_HOST_INT_ENABLE));
+	csio_rd_reg32(hw, MYPF_REG(CIM_PF_HOST_INT_ENABLE));
+}
+
+static void
+csio_mb_dump_fw_dbg(struct csio_hw *hw, __be64 *cmd)
+{
+	struct fw_debug_cmd *dbg = (struct fw_debug_cmd *)cmd;
+
+	if ((FW_DEBUG_CMD_TYPE_GET(ntohl(dbg->op_type))) == 1) {
+		csio_info(hw, "FW print message:\n");
+		csio_info(hw, "\tdebug->dprtstridx = %d\n",
+			    ntohs(dbg->u.prt.dprtstridx));
+		csio_info(hw, "\tdebug->dprtstrparam0 = 0x%x\n",
+			    ntohl(dbg->u.prt.dprtstrparam0));
+		csio_info(hw, "\tdebug->dprtstrparam1 = 0x%x\n",
+			    ntohl(dbg->u.prt.dprtstrparam1));
+		csio_info(hw, "\tdebug->dprtstrparam2 = 0x%x\n",
+			    ntohl(dbg->u.prt.dprtstrparam2));
+		csio_info(hw, "\tdebug->dprtstrparam3 = 0x%x\n",
+			    ntohl(dbg->u.prt.dprtstrparam3));
+	} else {
+		/* This is a FW assertion */
+		csio_fatal(hw, "FW assertion at %.16s:%u, val0 %#x, val1 %#x\n",
+			    dbg->u.assert.filename_0_7,
+			    ntohl(dbg->u.assert.line),
+			    ntohl(dbg->u.assert.x),
+			    ntohl(dbg->u.assert.y));
+	}
+}
+
+static void
+csio_mb_debug_cmd_handler(struct csio_hw *hw)
+{
+	int i;
+	__be64 cmd[CSIO_MB_MAX_REGS];
+	uint32_t ctl_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_CTRL);
+	uint32_t data_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_DATA);
+	int size = sizeof(struct fw_debug_cmd);
+
+	/* Copy mailbox data */
+	for (i = 0; i < size; i += 8)
+		cmd[i / 8] = cpu_to_be64(csio_rd_reg64(hw, data_reg + i));
+
+	csio_mb_dump_fw_dbg(hw, cmd);
+
+	/* Notify FW of mailbox by setting owner as UP */
+	csio_wr_reg32(hw, MBMSGVALID | MBINTREQ | MBOWNER(CSIO_MBOWNER_FW),
+		      ctl_reg);
+
+	csio_rd_reg32(hw, ctl_reg);
+	wmb();
+}
+
+/*
+ * csio_mb_issue - generic routine for issuing Mailbox commands.
+ * @hw: The HW structure
+ * @mbp: Mailbox command to issue
+ *
+ *  Caller should hold hw lock across this call.
+ */
+int
+csio_mb_issue(struct csio_hw *hw, struct csio_mb *mbp)
+{
+	uint32_t owner, ctl;
+	int i;
+	uint32_t ii;
+	__be64 *cmd = mbp->mb;
+	__be64 hdr;
+	struct csio_mbm	*mbm = &hw->mbm;
+	uint32_t ctl_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_CTRL);
+	uint32_t data_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_DATA);
+	int size = mbp->mb_size;
+	int rv = -EINVAL;
+	struct fw_cmd_hdr *fw_hdr;
+
+	/* Determine mode */
+	if (mbp->mb_cbfn == NULL) {
+		/* Need to issue/get results in the same context */
+		if (mbp->tmo < CSIO_MB_POLL_FREQ) {
+			csio_err(hw, "Invalid tmo: 0x%x\n", mbp->tmo);
+			goto error_out;
+		}
+	} else if (!csio_is_host_intr_enabled(hw) ||
+		   !csio_is_hw_intr_enabled(hw)) {
+		csio_err(hw, "Cannot issue mailbox in interrupt mode 0x%x\n",
+			 *((uint8_t *)mbp->mb));
+			goto error_out;
+	}
+
+	if (mbm->mcurrent != NULL) {
+		/* Queue mbox cmd, if another mbox cmd is active */
+		if (mbp->mb_cbfn == NULL) {
+			rv = -EBUSY;
+			csio_dbg(hw, "Couldnt own Mailbox %x op:0x%x\n",
+				    hw->pfn, *((uint8_t *)mbp->mb));
+
+			goto error_out;
+		} else {
+			list_add_tail(&mbp->list, &mbm->req_q);
+			CSIO_INC_STATS(mbm, n_activeq);
+
+			return 0;
+		}
+	}
+
+	/* Now get ownership of mailbox */
+	owner = MBOWNER_GET(csio_rd_reg32(hw, ctl_reg));
+
+	if (!csio_mb_is_host_owner(owner)) {
+
+		for (i = 0; (owner == CSIO_MBOWNER_NONE) && (i < 3); i++)
+			owner = MBOWNER_GET(csio_rd_reg32(hw, ctl_reg));
+		/*
+		 * Mailbox unavailable. In immediate mode, fail the command.
+		 * In other modes, enqueue the request.
+		 */
+		if (!csio_mb_is_host_owner(owner)) {
+			if (mbp->mb_cbfn == NULL) {
+				rv = owner ? -EBUSY : -ETIMEDOUT;
+
+				csio_dbg(hw,
+					 "Couldnt own Mailbox %x op:0x%x "
+					 "owner:%x\n",
+					 hw->pfn, *((uint8_t *)mbp->mb), owner);
+				goto error_out;
+			} else {
+				if (mbm->mcurrent == NULL) {
+					csio_err(hw,
+						 "Couldnt own Mailbox %x "
+						 "op:0x%x owner:%x\n",
+						 hw->pfn, *((uint8_t *)mbp->mb),
+						 owner);
+					csio_err(hw,
+						 "No outstanding driver"
+						 " mailbox as well\n");
+					goto error_out;
+				}
+			}
+		}
+	}
+
+	/* Mailbox is available, copy mailbox data into it */
+	for (i = 0; i < size; i += 8) {
+		csio_wr_reg64(hw, be64_to_cpu(*cmd), data_reg + i);
+		cmd++;
+	}
+
+	CSIO_DUMP_MB(hw, hw->pfn, data_reg);
+
+	/* Start completion timers in non-immediate modes and notify FW */
+	if (mbp->mb_cbfn != NULL) {
+		mbm->mcurrent = mbp;
+		mod_timer(&mbm->timer, jiffies + msecs_to_jiffies(mbp->tmo));
+		csio_wr_reg32(hw, MBMSGVALID | MBINTREQ |
+			      MBOWNER(CSIO_MBOWNER_FW), ctl_reg);
+	} else
+		csio_wr_reg32(hw, MBMSGVALID | MBOWNER(CSIO_MBOWNER_FW),
+			      ctl_reg);
+
+	/* Flush posted writes */
+	csio_rd_reg32(hw, ctl_reg);
+	wmb();
+
+	CSIO_INC_STATS(mbm, n_req);
+
+	if (mbp->mb_cbfn)
+		return 0;
+
+	/* Poll for completion in immediate mode */
+	cmd = mbp->mb;
+
+	for (ii = 0; ii < mbp->tmo; ii += CSIO_MB_POLL_FREQ) {
+		mdelay(CSIO_MB_POLL_FREQ);
+
+		/* Check for response */
+		ctl = csio_rd_reg32(hw, ctl_reg);
+		if (csio_mb_is_host_owner(MBOWNER_GET(ctl))) {
+
+			if (!(ctl & MBMSGVALID)) {
+				csio_wr_reg32(hw, 0, ctl_reg);
+				continue;
+			}
+
+			CSIO_DUMP_MB(hw, hw->pfn, data_reg);
+
+			hdr = cpu_to_be64(csio_rd_reg64(hw, data_reg));
+			fw_hdr = (struct fw_cmd_hdr *)&hdr;
+
+			switch (FW_CMD_OP_GET(ntohl(fw_hdr->hi))) {
+			case FW_DEBUG_CMD:
+				csio_mb_debug_cmd_handler(hw);
+				continue;
+			}
+
+			/* Copy response */
+			for (i = 0; i < size; i += 8)
+				*cmd++ = cpu_to_be64(csio_rd_reg64
+							  (hw, data_reg + i));
+			csio_wr_reg32(hw, 0, ctl_reg);
+
+			if (FW_CMD_RETVAL_GET(*(mbp->mb)))
+				CSIO_INC_STATS(mbm, n_err);
+
+			CSIO_INC_STATS(mbm, n_rsp);
+			return 0;
+		}
+	}
+
+	CSIO_INC_STATS(mbm, n_tmo);
+
+	csio_err(hw, "Mailbox %x op:0x%x timed out!\n",
+		 hw->pfn, *((uint8_t *)cmd));
+
+	return -ETIMEDOUT;
+
+error_out:
+	CSIO_INC_STATS(mbm, n_err);
+	return rv;
+}
+
+/*
+ * csio_mb_completions - Completion handler for Mailbox commands
+ * @hw: The HW structure
+ * @cbfn_q: Completion queue.
+ *
+ */
+void
+csio_mb_completions(struct csio_hw *hw, struct list_head *cbfn_q)
+{
+	struct csio_mb *mbp;
+	struct csio_mbm *mbm = &hw->mbm;
+	enum fw_retval rv;
+
+	while (!list_empty(cbfn_q)) {
+		mbp = list_first_entry(cbfn_q, struct csio_mb, list);
+		list_del_init(&mbp->list);
+
+		rv = csio_mb_fw_retval(mbp);
+		if ((rv != FW_SUCCESS) && (rv != FW_HOSTERROR))
+			CSIO_INC_STATS(mbm, n_err);
+		else if (rv != FW_HOSTERROR)
+			CSIO_INC_STATS(mbm, n_rsp);
+
+		if (mbp->mb_cbfn)
+			mbp->mb_cbfn(hw, mbp);
+	}
+}
+
+static void
+csio_mb_portmod_changed(struct csio_hw *hw, uint8_t port_id)
+{
+	static char *mod_str[] = {
+		NULL, "LR", "SR", "ER", "TWINAX", "active TWINAX", "LRM"
+	};
+
+	struct csio_pport *port = &hw->pport[port_id];
+
+	if (port->mod_type == FW_PORT_MOD_TYPE_NONE)
+		csio_info(hw, "Port:%d - port module unplugged\n", port_id);
+	else if (port->mod_type < ARRAY_SIZE(mod_str))
+		csio_info(hw, "Port:%d - %s port module inserted\n", port_id,
+			  mod_str[port->mod_type]);
+	else if (port->mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED)
+		csio_info(hw,
+			  "Port:%d - unsupported optical port module "
+			  "inserted\n", port_id);
+	else if (port->mod_type == FW_PORT_MOD_TYPE_UNKNOWN)
+		csio_info(hw,
+			  "Port:%d - unknown port module inserted, forcing "
+			  "TWINAX\n", port_id);
+	else if (port->mod_type == FW_PORT_MOD_TYPE_ERROR)
+		csio_info(hw, "Port:%d - transceiver module error\n", port_id);
+	else
+		csio_info(hw, "Port:%d - unknown module type %d inserted\n",
+			  port_id, port->mod_type);
+}
+
+int
+csio_mb_fwevt_handler(struct csio_hw *hw, __be64 *cmd)
+{
+	uint8_t opcode = *(uint8_t *)cmd;
+	struct fw_port_cmd *pcmd;
+	uint8_t port_id;
+	uint32_t link_status;
+	uint16_t action;
+	uint8_t mod_type;
+
+	if (opcode == FW_PORT_CMD) {
+		pcmd = (struct fw_port_cmd *)cmd;
+		port_id = FW_PORT_CMD_PORTID_GET(
+				ntohl(pcmd->op_to_portid));
+		action = FW_PORT_CMD_ACTION_GET(
+				ntohl(pcmd->action_to_len16));
+		if (action != FW_PORT_ACTION_GET_PORT_INFO) {
+			csio_err(hw, "Unhandled FW_PORT_CMD action: %u\n",
+				action);
+			return -EINVAL;
+		}
+
+		link_status = ntohl(pcmd->u.info.lstatus_to_modtype);
+		mod_type = FW_PORT_CMD_MODTYPE_GET(link_status);
+
+		hw->pport[port_id].link_status =
+			FW_PORT_CMD_LSTATUS_GET(link_status);
+		hw->pport[port_id].link_speed =
+			FW_PORT_CMD_LSPEED_GET(link_status);
+
+		csio_info(hw, "Port:%x - LINK %s\n", port_id,
+			FW_PORT_CMD_LSTATUS_GET(link_status) ? "UP" : "DOWN");
+
+		if (mod_type != hw->pport[port_id].mod_type) {
+			hw->pport[port_id].mod_type = mod_type;
+			csio_mb_portmod_changed(hw, port_id);
+		}
+	} else if (opcode == FW_DEBUG_CMD) {
+		csio_mb_dump_fw_dbg(hw, cmd);
+	} else {
+		csio_dbg(hw, "Gen MB can't handle op:0x%x on evtq.\n", opcode);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * csio_mb_isr_handler - Handle mailboxes related interrupts.
+ * @hw: The HW structure
+ *
+ * Called from the ISR to handle Mailbox related interrupts.
+ * HW Lock should be held across this call.
+ */
+int
+csio_mb_isr_handler(struct csio_hw *hw)
+{
+	struct csio_mbm		*mbm = &hw->mbm;
+	struct csio_mb		*mbp =  mbm->mcurrent;
+	__be64			*cmd;
+	uint32_t		ctl, cim_cause, pl_cause;
+	int			i;
+	uint32_t		ctl_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_CTRL);
+	uint32_t		data_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_DATA);
+	int			size;
+	__be64			hdr;
+	struct fw_cmd_hdr	*fw_hdr;
+
+	pl_cause = csio_rd_reg32(hw, MYPF_REG(PL_PF_INT_CAUSE));
+	cim_cause = csio_rd_reg32(hw, MYPF_REG(CIM_PF_HOST_INT_CAUSE));
+
+	if (!(pl_cause & PFCIM) || !(cim_cause & MBMSGRDYINT)) {
+		CSIO_INC_STATS(hw, n_mbint_unexp);
+		return -EINVAL;
+	}
+
+	/*
+	 * The cause registers below HAVE to be cleared in the SAME
+	 * order as below: The low level cause register followed by
+	 * the upper level cause register. In other words, CIM-cause
+	 * first followed by PL-Cause next.
+	 */
+	csio_wr_reg32(hw, MBMSGRDYINT, MYPF_REG(CIM_PF_HOST_INT_CAUSE));
+	csio_wr_reg32(hw, PFCIM, MYPF_REG(PL_PF_INT_CAUSE));
+
+	ctl = csio_rd_reg32(hw, ctl_reg);
+
+	if (csio_mb_is_host_owner(MBOWNER_GET(ctl))) {
+
+		CSIO_DUMP_MB(hw, hw->pfn, data_reg);
+
+		if (!(ctl & MBMSGVALID)) {
+			csio_warn(hw,
+				  "Stray mailbox interrupt recvd,"
+				  " mailbox data not valid\n");
+			csio_wr_reg32(hw, 0, ctl_reg);
+			/* Flush */
+			csio_rd_reg32(hw, ctl_reg);
+			return -EINVAL;
+		}
+
+		hdr = cpu_to_be64(csio_rd_reg64(hw, data_reg));
+		fw_hdr = (struct fw_cmd_hdr *)&hdr;
+
+		switch (FW_CMD_OP_GET(ntohl(fw_hdr->hi))) {
+		case FW_DEBUG_CMD:
+			csio_mb_debug_cmd_handler(hw);
+			return -EINVAL;
+#if 0
+		case FW_ERROR_CMD:
+		case FW_INITIALIZE_CMD: /* When we are not master */
+#endif
+		}
+
+		CSIO_ASSERT(mbp != NULL);
+
+		cmd = mbp->mb;
+		size = mbp->mb_size;
+		/* Get response */
+		for (i = 0; i < size; i += 8)
+			*cmd++ = cpu_to_be64(csio_rd_reg64
+						  (hw, data_reg + i));
+
+		csio_wr_reg32(hw, 0, ctl_reg);
+		/* Flush */
+		csio_rd_reg32(hw, ctl_reg);
+
+		mbm->mcurrent = NULL;
+
+		/* Add completion to tail of cbfn queue */
+		list_add_tail(&mbp->list, &mbm->cbfn_q);
+		CSIO_INC_STATS(mbm, n_cbfnq);
+
+		/*
+		 * Enqueue event to EventQ. Events processing happens
+		 * in Event worker thread context
+		 */
+		if (csio_enqueue_evt(hw, CSIO_EVT_MBX, mbp, sizeof(mbp)))
+			CSIO_INC_STATS(hw, n_evt_drop);
+
+		return 0;
+
+	} else {
+		/*
+		 * We can get here if mailbox MSIX vector is shared,
+		 * or in INTx case. Or a stray interrupt.
+		 */
+		csio_dbg(hw, "Host not owner, no mailbox interrupt\n");
+		CSIO_INC_STATS(hw, n_int_stray);
+		return -EINVAL;
+	}
+}
+
+/*
+ * csio_mb_tmo_handler - Timeout handler
+ * @hw: The HW structure
+ *
+ */
+struct csio_mb *
+csio_mb_tmo_handler(struct csio_hw *hw)
+{
+	struct csio_mbm *mbm = &hw->mbm;
+	struct csio_mb *mbp =  mbm->mcurrent;
+	struct fw_cmd_hdr *fw_hdr;
+
+	/*
+	 * Could be a race b/w the completion handler and the timer
+	 * and the completion handler won that race.
+	 */
+	if (mbp == NULL) {
+		CSIO_DB_ASSERT(0);
+		return NULL;
+	}
+
+	fw_hdr = (struct fw_cmd_hdr *)(mbp->mb);
+
+	csio_dbg(hw, "Mailbox num:%x op:0x%x timed out\n", hw->pfn,
+		    FW_CMD_OP_GET(ntohl(fw_hdr->hi)));
+
+	mbm->mcurrent = NULL;
+	CSIO_INC_STATS(mbm, n_tmo);
+	fw_hdr->lo = htonl(FW_CMD_RETVAL(FW_ETIMEDOUT));
+
+	return mbp;
+}
+
+/*
+ * csio_mb_cancel_all - Cancel all waiting commands.
+ * @hw: The HW structure
+ * @cbfn_q: The callback queue.
+ *
+ * Caller should hold hw lock across this call.
+ */
+void
+csio_mb_cancel_all(struct csio_hw *hw, struct list_head *cbfn_q)
+{
+	struct csio_mb *mbp;
+	struct csio_mbm *mbm = &hw->mbm;
+	struct fw_cmd_hdr *hdr;
+	struct list_head *tmp;
+
+	if (mbm->mcurrent) {
+		mbp = mbm->mcurrent;
+
+		/* Stop mailbox completion timer */
+		del_timer_sync(&mbm->timer);
+
+		/* Add completion to tail of cbfn queue */
+		list_add_tail(&mbp->list, cbfn_q);
+		mbm->mcurrent = NULL;
+	}
+
+	if (!list_empty(&mbm->req_q)) {
+		list_splice_tail_init(&mbm->req_q, cbfn_q);
+		mbm->stats.n_activeq = 0;
+	}
+
+	if (!list_empty(&mbm->cbfn_q)) {
+		list_splice_tail_init(&mbm->cbfn_q, cbfn_q);
+		mbm->stats.n_cbfnq = 0;
+	}
+
+	if (list_empty(cbfn_q))
+		return;
+
+	list_for_each(tmp, cbfn_q) {
+		mbp = (struct csio_mb *)tmp;
+		hdr = (struct fw_cmd_hdr *)(mbp->mb);
+
+		csio_dbg(hw, "Cancelling pending mailbox num %x op:%x\n",
+			    hw->pfn, FW_CMD_OP_GET(ntohl(hdr->hi)));
+
+		CSIO_INC_STATS(mbm, n_cancel);
+		hdr->lo = htonl(FW_CMD_RETVAL(FW_HOSTERROR));
+	}
+}
+
+/*
+ * csio_mbm_init - Initialize Mailbox module
+ * @mbm: Mailbox module
+ * @hw: The HW structure
+ * @timer: Timing function for interrupting mailboxes
+ *
+ * Initialize timer and the request/response queues.
+ */
+int
+csio_mbm_init(struct csio_mbm *mbm, struct csio_hw *hw,
+	      void (*timer_fn)(uintptr_t))
+{
+	struct timer_list *timer = &mbm->timer;
+
+	init_timer(timer);
+	timer->function = timer_fn;
+	timer->data = (unsigned long)hw;
+
+	INIT_LIST_HEAD(&mbm->req_q);
+	INIT_LIST_HEAD(&mbm->cbfn_q);
+	csio_set_mb_intr_idx(mbm, -1);
+
+	return 0;
+}
+
+/*
+ * csio_mbm_exit - Uninitialize mailbox module
+ * @mbm: Mailbox module
+ *
+ * Stop timer.
+ */
+void
+csio_mbm_exit(struct csio_mbm *mbm)
+{
+	del_timer_sync(&mbm->timer);
+
+	CSIO_DB_ASSERT(mbm->mcurrent == NULL);
+	CSIO_DB_ASSERT(list_empty(&mbm->req_q));
+	CSIO_DB_ASSERT(list_empty(&mbm->cbfn_q));
+}
diff --git a/drivers/scsi/csiostor/csio_mb.h b/drivers/scsi/csiostor/csio_mb.h
new file mode 100644
index 0000000..1788ea5
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_mb.h
@@ -0,0 +1,278 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_MB_H__
+#define __CSIO_MB_H__
+
+#include <linux/timer.h>
+#include <linux/completion.h>
+
+#include "t4fw_api.h"
+#include "t4fw_api_stor.h"
+#include "csio_defs.h"
+
+#define CSIO_STATS_OFFSET (2)
+#define CSIO_NUM_STATS_PER_MB (6)
+
+struct fw_fcoe_port_cmd_params {
+	uint8_t		portid;
+	uint8_t		idx;
+	uint8_t		nstats;
+};
+
+#define CSIO_DUMP_MB(__hw, __num, __mb)					\
+	csio_dbg(__hw, "\t%llx %llx %llx %llx %llx %llx %llx %llx\n",	\
+		(unsigned long long)csio_rd_reg64(__hw, __mb),		\
+		(unsigned long long)csio_rd_reg64(__hw, __mb + 8),	\
+		(unsigned long long)csio_rd_reg64(__hw, __mb + 16),	\
+		(unsigned long long)csio_rd_reg64(__hw, __mb + 24),	\
+		(unsigned long long)csio_rd_reg64(__hw, __mb + 32),	\
+		(unsigned long long)csio_rd_reg64(__hw, __mb + 40),	\
+		(unsigned long long)csio_rd_reg64(__hw, __mb + 48),	\
+		(unsigned long long)csio_rd_reg64(__hw, __mb + 56))
+
+#define CSIO_MB_MAX_REGS	8
+#define CSIO_MAX_MB_SIZE	64
+#define CSIO_MB_POLL_FREQ	5		/*  5 ms */
+#define CSIO_MB_DEFAULT_TMO	FW_CMD_MAX_TIMEOUT
+
+/* Device master in HELLO command */
+enum csio_dev_master { CSIO_MASTER_CANT, CSIO_MASTER_MAY, CSIO_MASTER_MUST };
+
+enum csio_mb_owner { CSIO_MBOWNER_NONE, CSIO_MBOWNER_FW, CSIO_MBOWNER_PL };
+
+enum csio_dev_state {
+	CSIO_DEV_STATE_UNINIT,
+	CSIO_DEV_STATE_INIT,
+	CSIO_DEV_STATE_ERR
+};
+
+#define FW_PARAM_DEV(param) \
+	(FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \
+	 FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param))
+
+#define FW_PARAM_PFVF(param) \
+	(FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \
+	 FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param)|  \
+	 FW_PARAMS_PARAM_Y(0) | \
+	 FW_PARAMS_PARAM_Z(0))
+
+enum {
+	PAUSE_RX      = 1 << 0,
+	PAUSE_TX      = 1 << 1,
+	PAUSE_AUTONEG = 1 << 2
+};
+
+#define CSIO_INIT_MBP(__mbp, __cp,  __tmo, __priv, __fn, __clear)	\
+do {									\
+	if (__clear)							\
+		memset((__cp), 0,					\
+			    CSIO_MB_MAX_REGS * sizeof(__be64));		\
+	INIT_LIST_HEAD(&(__mbp)->list);					\
+	(__mbp)->tmo		= (__tmo);				\
+	(__mbp)->priv		= (void *)(__priv);			\
+	(__mbp)->mb_cbfn	= (__fn);				\
+	(__mbp)->mb_size	= sizeof(*(__cp));			\
+} while (0)
+
+struct csio_mbm_stats {
+	uint32_t	n_req;		/* number of mbox req */
+	uint32_t	n_rsp;		/* number of mbox rsp */
+	uint32_t	n_activeq;	/* number of mbox req active Q */
+	uint32_t	n_cbfnq;	/* number of mbox req cbfn Q */
+	uint32_t	n_tmo;		/* number of mbox timeout */
+	uint32_t	n_cancel;	/* number of mbox cancel */
+	uint32_t	n_err;		/* number of mbox error */
+};
+
+/* Driver version of Mailbox */
+struct csio_mb {
+	struct list_head	list;			/* for req/resp */
+							/* queue in driver */
+	__be64			mb[CSIO_MB_MAX_REGS];	/* MB in HW format */
+	int			mb_size;		/* Size of this
+							 * mailbox.
+							 */
+	uint32_t		tmo;			/* Timeout */
+	struct completion	cmplobj;		/* MB Completion
+							 * object
+							 */
+	void			(*mb_cbfn) (struct csio_hw *, struct csio_mb *);
+							/* Callback fn */
+	void			*priv;			/* Owner private ptr */
+};
+
+struct csio_mbm {
+	uint32_t		a_mbox;			/* Async mbox num */
+	uint32_t		intr_idx;		/* Interrupt index */
+	struct timer_list	timer;			/* Mbox timer */
+	struct list_head	req_q;			/* Mbox request queue */
+	struct list_head	cbfn_q;			/* Mbox completion q */
+	struct csio_mb		*mcurrent;		/* Current mailbox */
+	uint32_t		req_q_cnt;		/* Outstanding mbox
+							 * cmds
+							 */
+	struct csio_mbm_stats	stats;			/* Statistics */
+};
+
+#define csio_set_mb_intr_idx(_m, _i)	((_m)->intr_idx = (_i))
+#define csio_get_mb_intr_idx(_m)	((_m)->intr_idx)
+
+struct csio_iq_params;
+struct csio_eq_params;
+
+enum fw_retval csio_mb_fw_retval(struct csio_mb *);
+
+/* MB helpers */
+void csio_mb_hello(struct csio_hw *, struct csio_mb *, uint32_t,
+		   uint32_t, uint32_t, enum csio_dev_master,
+		   void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_process_hello_rsp(struct csio_hw *, struct csio_mb *,
+			       enum fw_retval *, enum csio_dev_state *,
+			       uint8_t *);
+
+void csio_mb_bye(struct csio_hw *, struct csio_mb *, uint32_t,
+		 void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_reset(struct csio_hw *, struct csio_mb *, uint32_t, int, int,
+		   void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_params(struct csio_hw *, struct csio_mb *, uint32_t, unsigned int,
+		    unsigned int, unsigned int, const u32 *, u32 *, bool,
+		    void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_process_read_params_rsp(struct csio_hw *, struct csio_mb *,
+				enum fw_retval *, unsigned int , u32 *);
+
+void csio_mb_ldst(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+		  int reg);
+
+void csio_mb_caps_config(struct csio_hw *, struct csio_mb *, uint32_t,
+			    bool, bool, bool, bool,
+			    void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_rss_glb_config(struct csio_hw *, struct csio_mb *,
+			 uint32_t, uint8_t, unsigned int,
+			 void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_pfvf(struct csio_hw *, struct csio_mb *, uint32_t,
+		  unsigned int, unsigned int, unsigned int,
+		  unsigned int, unsigned int, unsigned int,
+		  unsigned int, unsigned int, unsigned int,
+		  unsigned int, unsigned int, unsigned int,
+		  unsigned int, void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_mb_port(struct csio_hw *, struct csio_mb *, uint32_t,
+		  uint8_t, bool, uint32_t, uint16_t,
+		  void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_mb_process_read_port_rsp(struct csio_hw *, struct csio_mb *,
+				   enum fw_retval *, uint16_t *);
+
+void csio_mb_initialize(struct csio_hw *, struct csio_mb *, uint32_t,
+			void (*)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_iq_alloc_write(struct csio_hw *, struct csio_mb *, void *,
+			uint32_t, struct csio_iq_params *,
+			void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_mb_iq_alloc_write_rsp(struct csio_hw *, struct csio_mb *,
+				enum fw_retval *, struct csio_iq_params *);
+
+void csio_mb_iq_free(struct csio_hw *, struct csio_mb *, void *,
+		     uint32_t, struct csio_iq_params *,
+		     void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_mb_eq_ofld_alloc_write(struct csio_hw *, struct csio_mb *, void *,
+				 uint32_t, struct csio_eq_params *,
+				 void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_mb_eq_ofld_alloc_write_rsp(struct csio_hw *, struct csio_mb *,
+				     enum fw_retval *, struct csio_eq_params *);
+
+void csio_mb_eq_ofld_free(struct csio_hw *, struct csio_mb *, void *,
+			  uint32_t , struct csio_eq_params *,
+			  void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_read_res_info_init_mb(struct csio_hw *, struct csio_mb *,
+			uint32_t,
+			void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_write_fcoe_link_cond_init_mb(struct csio_lnode *, struct csio_mb *,
+			uint32_t, uint8_t, uint32_t, uint8_t, bool, uint32_t,
+			void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_vnp_alloc_init_mb(struct csio_lnode *, struct csio_mb *,
+			uint32_t, uint32_t , uint32_t , uint16_t,
+			uint8_t [8], uint8_t [8],
+			void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_vnp_read_init_mb(struct csio_lnode *, struct csio_mb *,
+			uint32_t, uint32_t , uint32_t ,
+			void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_vnp_free_init_mb(struct csio_lnode *, struct csio_mb *,
+			uint32_t , uint32_t, uint32_t ,
+			void (*) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_read_fcf_init_mb(struct csio_lnode *, struct csio_mb *,
+			uint32_t, uint32_t, uint32_t,
+			void (*cbfn) (struct csio_hw *, struct csio_mb *));
+
+void csio_fcoe_read_portparams_init_mb(struct csio_hw *hw,
+			struct csio_mb *mbp, uint32_t mb_tmo,
+			struct fw_fcoe_port_cmd_params *portparams,
+			void (*cbfn)(struct csio_hw *, struct csio_mb *));
+
+void csio_mb_process_portparams_rsp(struct csio_hw *hw, struct csio_mb *mbp,
+				enum fw_retval *retval,
+				struct fw_fcoe_port_cmd_params *portparams,
+				struct fw_fcoe_port_stats *portstats);
+
+/* MB module functions */
+int csio_mbm_init(struct csio_mbm *, struct csio_hw *,
+			    void (*)(uintptr_t));
+void csio_mbm_exit(struct csio_mbm *);
+void csio_mb_intr_enable(struct csio_hw *);
+void csio_mb_intr_disable(struct csio_hw *);
+
+int csio_mb_issue(struct csio_hw *, struct csio_mb *);
+void csio_mb_completions(struct csio_hw *, struct list_head *);
+int csio_mb_fwevt_handler(struct csio_hw *, __be64 *);
+int csio_mb_isr_handler(struct csio_hw *);
+struct csio_mb *csio_mb_tmo_handler(struct csio_hw *);
+void csio_mb_cancel_all(struct csio_hw *, struct list_head *);
+
+#endif /* ifndef __CSIO_MB_H__ */
diff --git a/drivers/scsi/csiostor/csio_rnode.c b/drivers/scsi/csiostor/csio_rnode.c
new file mode 100644
index 0000000..b0ae430
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_rnode.c
@@ -0,0 +1,912 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/string.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_fc.h>
+#include <scsi/fc/fc_els.h>
+#include <scsi/fc/fc_fs.h>
+
+#include "csio_hw.h"
+#include "csio_lnode.h"
+#include "csio_rnode.h"
+
+static int csio_rnode_init(struct csio_rnode *, struct csio_lnode *);
+static void csio_rnode_exit(struct csio_rnode *);
+
+/* Static machine forward declarations */
+static void csio_rns_uninit(struct csio_rnode *, enum csio_rn_ev);
+static void csio_rns_ready(struct csio_rnode *, enum csio_rn_ev);
+static void csio_rns_offline(struct csio_rnode *, enum csio_rn_ev);
+static void csio_rns_disappeared(struct csio_rnode *, enum csio_rn_ev);
+
+/* RNF event mapping */
+static enum csio_rn_ev fwevt_to_rnevt[] = {
+	CSIO_RNFE_NONE,		/* None */
+	CSIO_RNFE_LOGGED_IN,	/* PLOGI_ACC_RCVD  */
+	CSIO_RNFE_NONE,		/* PLOGI_RJT_RCVD  */
+	CSIO_RNFE_PLOGI_RECV,	/* PLOGI_RCVD	   */
+	CSIO_RNFE_LOGO_RECV,	/* PLOGO_RCVD	   */
+	CSIO_RNFE_PRLI_DONE,	/* PRLI_ACC_RCVD   */
+	CSIO_RNFE_NONE,		/* PRLI_RJT_RCVD   */
+	CSIO_RNFE_PRLI_RECV,	/* PRLI_RCVD	   */
+	CSIO_RNFE_PRLO_RECV,	/* PRLO_RCVD	   */
+	CSIO_RNFE_NONE,		/* NPORT_ID_CHGD   */
+	CSIO_RNFE_LOGO_RECV,	/* FLOGO_RCVD	   */
+	CSIO_RNFE_NONE,		/* CLR_VIRT_LNK_RCVD */
+	CSIO_RNFE_LOGGED_IN,	/* FLOGI_ACC_RCVD   */
+	CSIO_RNFE_NONE,		/* FLOGI_RJT_RCVD   */
+	CSIO_RNFE_LOGGED_IN,	/* FDISC_ACC_RCVD   */
+	CSIO_RNFE_NONE,		/* FDISC_RJT_RCVD   */
+	CSIO_RNFE_NONE,		/* FLOGI_TMO_MAX_RETRY */
+	CSIO_RNFE_NONE,		/* IMPL_LOGO_ADISC_ACC */
+	CSIO_RNFE_NONE,		/* IMPL_LOGO_ADISC_RJT */
+	CSIO_RNFE_NONE,		/* IMPL_LOGO_ADISC_CNFLT */
+	CSIO_RNFE_NONE,		/* PRLI_TMO		*/
+	CSIO_RNFE_NONE,		/* ADISC_TMO		*/
+	CSIO_RNFE_NAME_MISSING,	/* RSCN_DEV_LOST  */
+	CSIO_RNFE_NONE,		/* SCR_ACC_RCVD	*/
+	CSIO_RNFE_NONE,		/* ADISC_RJT_RCVD */
+	CSIO_RNFE_NONE,		/* LOGO_SNT */
+	CSIO_RNFE_LOGO_RECV,	/* PROTO_ERR_IMPL_LOGO */
+};
+
+#define CSIO_FWE_TO_RNFE(_evt)	((_evt > PROTO_ERR_IMPL_LOGO) ?		\
+						CSIO_RNFE_NONE :	\
+						fwevt_to_rnevt[_evt])
+int
+csio_is_rnode_ready(struct csio_rnode *rn)
+{
+	return csio_match_state(rn, csio_rns_ready);
+}
+
+static int
+csio_is_rnode_uninit(struct csio_rnode *rn)
+{
+	return csio_match_state(rn, csio_rns_uninit);
+}
+
+static int
+csio_is_rnode_wka(uint8_t rport_type)
+{
+	if ((rport_type == FLOGI_VFPORT) ||
+	    (rport_type == FDISC_VFPORT) ||
+	    (rport_type == NS_VNPORT) ||
+	    (rport_type == FDMI_VNPORT))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * csio_rn_lookup - Finds the rnode with the given flowid
+ * @ln - lnode
+ * @flowid - flowid.
+ *
+ * Does the rnode lookup on the given lnode and flowid.If no matching entry
+ * found, NULL is returned.
+ */
+static struct csio_rnode *
+csio_rn_lookup(struct csio_lnode *ln, uint32_t flowid)
+{
+	struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
+	struct list_head *tmp;
+	struct csio_rnode *rn;
+
+	list_for_each(tmp, &rnhead->sm.sm_list) {
+		rn = (struct csio_rnode *) tmp;
+		if (rn->flowid == flowid)
+			return rn;
+	}
+
+	return NULL;
+}
+
+/*
+ * csio_rn_lookup_wwpn - Finds the rnode with the given wwpn
+ * @ln: lnode
+ * @wwpn: wwpn
+ *
+ * Does the rnode lookup on the given lnode and wwpn. If no matching entry
+ * found, NULL is returned.
+ */
+static struct csio_rnode *
+csio_rn_lookup_wwpn(struct csio_lnode *ln, uint8_t *wwpn)
+{
+	struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
+	struct list_head *tmp;
+	struct csio_rnode *rn;
+
+	list_for_each(tmp, &rnhead->sm.sm_list) {
+		rn = (struct csio_rnode *) tmp;
+		if (!memcmp(csio_rn_wwpn(rn), wwpn, 8))
+			return rn;
+	}
+
+	return NULL;
+}
+
+/**
+ * csio_rnode_lookup_portid - Finds the rnode with the given portid
+ * @ln:		lnode
+ * @portid:	port id
+ *
+ * Lookup the rnode list for a given portid. If no matching entry
+ * found, NULL is returned.
+ */
+struct csio_rnode *
+csio_rnode_lookup_portid(struct csio_lnode *ln, uint32_t portid)
+{
+	struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
+	struct list_head *tmp;
+	struct csio_rnode *rn;
+
+	list_for_each(tmp, &rnhead->sm.sm_list) {
+		rn = (struct csio_rnode *) tmp;
+		if (rn->nport_id == portid)
+			return rn;
+	}
+
+	return NULL;
+}
+
+static int
+csio_rn_dup_flowid(struct csio_lnode *ln, uint32_t rdev_flowid,
+		    uint32_t *vnp_flowid)
+{
+	struct csio_rnode *rnhead;
+	struct list_head *tmp, *tmp1;
+	struct csio_rnode *rn;
+	struct csio_lnode *ln_tmp;
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+	list_for_each(tmp1, &hw->sln_head) {
+		ln_tmp = (struct csio_lnode *) tmp1;
+		if (ln_tmp == ln)
+			continue;
+
+		rnhead = (struct csio_rnode *)&ln_tmp->rnhead;
+		list_for_each(tmp, &rnhead->sm.sm_list) {
+
+			rn = (struct csio_rnode *) tmp;
+			if (csio_is_rnode_ready(rn)) {
+				if (rn->flowid == rdev_flowid) {
+					*vnp_flowid = csio_ln_flowid(ln_tmp);
+					return 1;
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+
+static struct csio_rnode *
+csio_alloc_rnode(struct csio_lnode *ln)
+{
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+	struct csio_rnode *rn = mempool_alloc(hw->rnode_mempool, GFP_ATOMIC);
+	if (!rn)
+		goto err;
+
+	memset(rn, 0, sizeof(struct csio_rnode));
+	if (csio_rnode_init(rn, ln))
+		goto err_free;
+
+	CSIO_INC_STATS(ln, n_rnode_alloc);
+
+	return rn;
+
+err_free:
+	mempool_free(rn, hw->rnode_mempool);
+err:
+	CSIO_INC_STATS(ln, n_rnode_nomem);
+	return NULL;
+}
+
+static void
+csio_free_rnode(struct csio_rnode *rn)
+{
+	struct csio_hw *hw = csio_lnode_to_hw(csio_rnode_to_lnode(rn));
+
+	csio_rnode_exit(rn);
+	CSIO_INC_STATS(rn->lnp, n_rnode_free);
+	mempool_free(rn, hw->rnode_mempool);
+}
+
+/*
+ * csio_get_rnode - Gets rnode with the given flowid
+ * @ln - lnode
+ * @flowid - flow id.
+ *
+ * Does the rnode lookup on the given lnode and flowid. If no matching
+ * rnode found, then new rnode with given npid is allocated and returned.
+ */
+static struct csio_rnode *
+csio_get_rnode(struct csio_lnode *ln, uint32_t flowid)
+{
+	struct csio_rnode *rn;
+
+	rn = csio_rn_lookup(ln, flowid);
+	if (!rn) {
+		rn = csio_alloc_rnode(ln);
+		if (!rn)
+			return NULL;
+
+		rn->flowid = flowid;
+	}
+
+	return rn;
+}
+
+/*
+ * csio_put_rnode - Frees the given rnode
+ * @ln - lnode
+ * @flowid - flow id.
+ *
+ * Does the rnode lookup on the given lnode and flowid. If no matching
+ * rnode found, then new rnode with given npid is allocated and returned.
+ */
+void
+csio_put_rnode(struct csio_lnode *ln, struct csio_rnode *rn)
+{
+	CSIO_DB_ASSERT(csio_is_rnode_uninit(rn) != 0);
+	csio_free_rnode(rn);
+}
+
+/*
+ * csio_confirm_rnode - confirms rnode based on wwpn.
+ * @ln: lnode
+ * @rdev_flowid: remote device flowid
+ * @rdevp: remote device params
+ * This routines searches other rnode in list having same wwpn of new rnode.
+ * If there is a match, then matched rnode is returned and otherwise new rnode
+ * is returned.
+ * returns rnode.
+ */
+struct csio_rnode *
+csio_confirm_rnode(struct csio_lnode *ln, uint32_t rdev_flowid,
+		   struct fcoe_rdev_entry *rdevp)
+{
+	uint8_t rport_type;
+	struct csio_rnode *rn, *match_rn;
+	uint32_t vnp_flowid;
+	uint32_t *port_id;
+
+	port_id = (uint32_t *)&rdevp->r_id[0];
+	rport_type =
+		FW_RDEV_WR_RPORT_TYPE_GET(rdevp->rd_xfer_rdy_to_rport_type);
+
+	/* Drop rdev event for cntrl port */
+	if (rport_type == FAB_CTLR_VNPORT) {
+		csio_ln_dbg(ln,
+			    "Unhandled rport_type:%d recv in rdev evt "
+			    "ssni:x%x\n", rport_type, rdev_flowid);
+		return NULL;
+	}
+
+	/* Lookup on flowid */
+	rn = csio_rn_lookup(ln, rdev_flowid);
+	if (!rn) {
+
+		/* Drop events with duplicate flowid */
+		if (csio_rn_dup_flowid(ln, rdev_flowid, &vnp_flowid)) {
+			csio_ln_warn(ln,
+				     "ssni:%x already active on vnpi:%x",
+				     rdev_flowid, vnp_flowid);
+			return NULL;
+		}
+
+		/* Lookup on wwpn for NPORTs */
+		rn = csio_rn_lookup_wwpn(ln, rdevp->wwpn);
+		if (!rn)
+			goto alloc_rnode;
+
+	} else {
+		/* Lookup well-known ports with nport id */
+		if (csio_is_rnode_wka(rport_type)) {
+			match_rn = csio_rnode_lookup_portid(ln,
+				      ((ntohl(*port_id) >> 8) & CSIO_DID_MASK));
+			if (match_rn == NULL) {
+				csio_rn_flowid(rn) = CSIO_INVALID_IDX;
+				goto alloc_rnode;
+			}
+
+			/*
+			 * Now compare the wwpn to confirm that
+			 * same port relogged in. If so update the matched rn.
+			 * Else, go ahead and alloc a new rnode.
+			 */
+			if (!memcmp(csio_rn_wwpn(match_rn), rdevp->wwpn, 8)) {
+				if (csio_is_rnode_ready(rn)) {
+					csio_ln_warn(ln,
+						     "rnode is already"
+						     "active ssni:x%x\n",
+						     rdev_flowid);
+					CSIO_ASSERT(0);
+				}
+				csio_rn_flowid(rn) = CSIO_INVALID_IDX;
+				rn = match_rn;
+
+				/* Update rn */
+				goto found_rnode;
+			}
+			csio_rn_flowid(rn) = CSIO_INVALID_IDX;
+			goto alloc_rnode;
+		}
+
+		/* wwpn match */
+		if (!memcmp(csio_rn_wwpn(rn), rdevp->wwpn, 8))
+			goto found_rnode;
+
+		/* Search for rnode that have same wwpn */
+		match_rn = csio_rn_lookup_wwpn(ln, rdevp->wwpn);
+		if (match_rn != NULL) {
+			csio_ln_dbg(ln,
+				"ssni:x%x changed for rport name(wwpn):%llx "
+				"did:x%x\n", rdev_flowid,
+				wwn_to_u64(rdevp->wwpn),
+				match_rn->nport_id);
+			csio_rn_flowid(rn) = CSIO_INVALID_IDX;
+			rn = match_rn;
+		} else {
+			csio_ln_dbg(ln,
+				"rnode wwpn mismatch found ssni:x%x "
+				"name(wwpn):%llx\n",
+				rdev_flowid,
+				wwn_to_u64(csio_rn_wwpn(rn)));
+			if (csio_is_rnode_ready(rn)) {
+				csio_ln_warn(ln,
+					     "rnode is already active "
+					     "wwpn:%llx ssni:x%x\n",
+					     wwn_to_u64(csio_rn_wwpn(rn)),
+					     rdev_flowid);
+				CSIO_ASSERT(0);
+			}
+			csio_rn_flowid(rn) = CSIO_INVALID_IDX;
+			goto alloc_rnode;
+		}
+	}
+
+found_rnode:
+	csio_ln_dbg(ln, "found rnode:%p ssni:x%x name(wwpn):%llx\n",
+		rn, rdev_flowid, wwn_to_u64(rdevp->wwpn));
+
+	/* Update flowid */
+	csio_rn_flowid(rn) = rdev_flowid;
+
+	/* update rdev entry */
+	rn->rdev_entry = rdevp;
+	CSIO_INC_STATS(ln, n_rnode_match);
+	return rn;
+
+alloc_rnode:
+	rn = csio_get_rnode(ln, rdev_flowid);
+	if (!rn)
+		return NULL;
+
+	csio_ln_dbg(ln, "alloc rnode:%p ssni:x%x name(wwpn):%llx\n",
+		rn, rdev_flowid, wwn_to_u64(rdevp->wwpn));
+
+	/* update rdev entry */
+	rn->rdev_entry = rdevp;
+	return rn;
+}
+
+/*
+ * csio_rn_verify_rparams - verify rparams.
+ * @ln: lnode
+ * @rn: rnode
+ * @rdevp: remote device params
+ * returns success if rparams are verified.
+ */
+static int
+csio_rn_verify_rparams(struct csio_lnode *ln, struct csio_rnode *rn,
+			struct fcoe_rdev_entry *rdevp)
+{
+	uint8_t null[8];
+	uint8_t rport_type;
+	uint8_t fc_class;
+	uint32_t *did;
+
+	did = (uint32_t *) &rdevp->r_id[0];
+	rport_type =
+		FW_RDEV_WR_RPORT_TYPE_GET(rdevp->rd_xfer_rdy_to_rport_type);
+	switch (rport_type) {
+	case FLOGI_VFPORT:
+		rn->role = CSIO_RNFR_FABRIC;
+		if (((ntohl(*did) >> 8) & CSIO_DID_MASK) != FC_FID_FLOGI) {
+			csio_ln_err(ln, "ssni:x%x invalid fabric portid\n",
+				csio_rn_flowid(rn));
+			return -EINVAL;
+		}
+		/* NPIV support */
+		if (FW_RDEV_WR_NPIV_GET(rdevp->vft_to_qos))
+			ln->flags |= CSIO_LNF_NPIVSUPP;
+
+		break;
+
+	case NS_VNPORT:
+		rn->role = CSIO_RNFR_NS;
+		if (((ntohl(*did) >> 8) & CSIO_DID_MASK) != FC_FID_DIR_SERV) {
+			csio_ln_err(ln, "ssni:x%x invalid fabric portid\n",
+				csio_rn_flowid(rn));
+			return -EINVAL;
+		}
+		break;
+
+	case REG_FC4_VNPORT:
+	case REG_VNPORT:
+		rn->role = CSIO_RNFR_NPORT;
+		if (rdevp->event_cause == PRLI_ACC_RCVD ||
+			rdevp->event_cause == PRLI_RCVD) {
+			if (FW_RDEV_WR_TASK_RETRY_ID_GET(
+							rdevp->enh_disc_to_tgt))
+				rn->fcp_flags |= FCP_SPPF_OVLY_ALLOW;
+
+			if (FW_RDEV_WR_RETRY_GET(rdevp->enh_disc_to_tgt))
+				rn->fcp_flags |= FCP_SPPF_RETRY;
+
+			if (FW_RDEV_WR_CONF_CMPL_GET(rdevp->enh_disc_to_tgt))
+				rn->fcp_flags |= FCP_SPPF_CONF_COMPL;
+
+			if (FW_RDEV_WR_TGT_GET(rdevp->enh_disc_to_tgt))
+				rn->role |= CSIO_RNFR_TARGET;
+
+			if (FW_RDEV_WR_INI_GET(rdevp->enh_disc_to_tgt))
+				rn->role |= CSIO_RNFR_INITIATOR;
+		}
+
+		break;
+
+	case FDMI_VNPORT:
+	case FAB_CTLR_VNPORT:
+		rn->role = 0;
+		break;
+
+	default:
+		csio_ln_err(ln, "ssni:x%x invalid rport type recv x%x\n",
+			csio_rn_flowid(rn), rport_type);
+		return -EINVAL;
+	}
+
+	/* validate wwpn/wwnn for Name server/remote port */
+	if (rport_type == REG_VNPORT || rport_type == NS_VNPORT) {
+		memset(null, 0, 8);
+		if (!memcmp(rdevp->wwnn, null, 8)) {
+			csio_ln_err(ln,
+				    "ssni:x%x invalid wwnn received from"
+				    " rport did:x%x\n",
+				    csio_rn_flowid(rn),
+				    (ntohl(*did) & CSIO_DID_MASK));
+			return -EINVAL;
+		}
+
+		if (!memcmp(rdevp->wwpn, null, 8)) {
+			csio_ln_err(ln,
+				    "ssni:x%x invalid wwpn received from"
+				    " rport did:x%x\n",
+				    csio_rn_flowid(rn),
+				    (ntohl(*did) & CSIO_DID_MASK));
+			return -EINVAL;
+		}
+
+	}
+
+	/* Copy wwnn, wwpn and nport id */
+	rn->nport_id = (ntohl(*did) >> 8) & CSIO_DID_MASK;
+	memcpy(csio_rn_wwnn(rn), rdevp->wwnn, 8);
+	memcpy(csio_rn_wwpn(rn), rdevp->wwpn, 8);
+	rn->rn_sparm.csp.sp_bb_data = ntohs(rdevp->rcv_fr_sz);
+	fc_class = FW_RDEV_WR_CLASS_GET(rdevp->vft_to_qos);
+	rn->rn_sparm.clsp[fc_class - 1].cp_class = htons(FC_CPC_VALID);
+	return 0;
+}
+
+static void
+__csio_reg_rnode(struct csio_rnode *rn)
+{
+	struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+	spin_unlock_irq(&hw->lock);
+	csio_reg_rnode(rn);
+	spin_lock_irq(&hw->lock);
+
+	if (rn->role & CSIO_RNFR_TARGET)
+		ln->n_scsi_tgts++;
+
+	if (rn->nport_id == FC_FID_MGMT_SERV)
+		csio_ln_fdmi_start(ln, (void *) rn);
+}
+
+static void
+__csio_unreg_rnode(struct csio_rnode *rn)
+{
+	struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+	LIST_HEAD(tmp_q);
+	int cmpl = 0;
+
+	if (!list_empty(&rn->host_cmpl_q)) {
+		csio_dbg(hw, "Returning completion queue I/Os\n");
+		list_splice_tail_init(&rn->host_cmpl_q, &tmp_q);
+		cmpl = 1;
+	}
+
+	if (rn->role & CSIO_RNFR_TARGET) {
+		ln->n_scsi_tgts--;
+		ln->last_scan_ntgts--;
+	}
+
+	spin_unlock_irq(&hw->lock);
+	csio_unreg_rnode(rn);
+	spin_lock_irq(&hw->lock);
+
+	/* Cleanup I/Os that were waiting for rnode to unregister */
+	if (cmpl)
+		csio_scsi_cleanup_io_q(csio_hw_to_scsim(hw), &tmp_q);
+
+}
+
+/*****************************************************************************/
+/* START: Rnode SM                                                           */
+/*****************************************************************************/
+
+/*
+ * csio_rns_uninit -
+ * @rn - rnode
+ * @evt - SM event.
+ *
+ */
+static void
+csio_rns_uninit(struct csio_rnode *rn, enum csio_rn_ev evt)
+{
+	struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+	int ret = 0;
+
+	CSIO_INC_STATS(rn, n_evt_sm[evt]);
+
+	switch (evt) {
+	case CSIO_RNFE_LOGGED_IN:
+	case CSIO_RNFE_PLOGI_RECV:
+		ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
+		if (!ret) {
+			csio_set_state(&rn->sm, csio_rns_ready);
+			__csio_reg_rnode(rn);
+		} else {
+			CSIO_INC_STATS(rn, n_err_inval);
+		}
+		break;
+	case CSIO_RNFE_LOGO_RECV:
+		csio_ln_dbg(ln,
+			    "ssni:x%x Ignoring event %d recv "
+			    "in rn state[uninit]\n", csio_rn_flowid(rn), evt);
+		CSIO_INC_STATS(rn, n_evt_drop);
+		break;
+	default:
+		csio_ln_dbg(ln,
+			    "ssni:x%x unexp event %d recv "
+			    "in rn state[uninit]\n", csio_rn_flowid(rn), evt);
+		CSIO_INC_STATS(rn, n_evt_unexp);
+		break;
+	}
+}
+
+/*
+ * csio_rns_ready -
+ * @rn - rnode
+ * @evt - SM event.
+ *
+ */
+static void
+csio_rns_ready(struct csio_rnode *rn, enum csio_rn_ev evt)
+{
+	struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+	int ret = 0;
+
+	CSIO_INC_STATS(rn, n_evt_sm[evt]);
+
+	switch (evt) {
+	case CSIO_RNFE_LOGGED_IN:
+	case CSIO_RNFE_PLOGI_RECV:
+		csio_ln_dbg(ln,
+			"ssni:x%x Ignoring event %d recv from did:x%x "
+			"in rn state[ready]\n", csio_rn_flowid(rn), evt,
+			rn->nport_id);
+		CSIO_INC_STATS(rn, n_evt_drop);
+		break;
+
+	case CSIO_RNFE_PRLI_DONE:
+	case CSIO_RNFE_PRLI_RECV:
+		ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
+		if (!ret)
+			__csio_reg_rnode(rn);
+		else
+			CSIO_INC_STATS(rn, n_err_inval);
+
+		break;
+	case CSIO_RNFE_DOWN:
+		csio_set_state(&rn->sm, csio_rns_offline);
+		__csio_unreg_rnode(rn);
+
+		/* FW expected to internally aborted outstanding SCSI WRs
+		 * and return all SCSI WRs to host with status "ABORTED".
+		 */
+		break;
+
+	case CSIO_RNFE_LOGO_RECV:
+		csio_set_state(&rn->sm, csio_rns_offline);
+
+		__csio_unreg_rnode(rn);
+
+		/* FW expected to internally aborted outstanding SCSI WRs
+		 * and return all SCSI WRs to host with status "ABORTED".
+		 */
+		break;
+
+	case CSIO_RNFE_CLOSE:
+		/*
+		 * Each rnode receives CLOSE event when driver is removed or
+		 * device is reset
+		 * Note: All outstanding IOs on remote port need to returned
+		 * to uppper layer with appropriate error before sending
+		 * CLOSE event
+		 */
+		csio_set_state(&rn->sm, csio_rns_uninit);
+		__csio_unreg_rnode(rn);
+		break;
+
+	case CSIO_RNFE_NAME_MISSING:
+		csio_set_state(&rn->sm, csio_rns_disappeared);
+		__csio_unreg_rnode(rn);
+
+		/*
+		 * FW expected to internally aborted outstanding SCSI WRs
+		 * and return all SCSI WRs to host with status "ABORTED".
+		 */
+
+		break;
+
+	default:
+		csio_ln_dbg(ln,
+			"ssni:x%x unexp event %d recv from did:x%x "
+			"in rn state[uninit]\n", csio_rn_flowid(rn), evt,
+			rn->nport_id);
+		CSIO_INC_STATS(rn, n_evt_unexp);
+		break;
+	}
+}
+
+/*
+ * csio_rns_offline -
+ * @rn - rnode
+ * @evt - SM event.
+ *
+ */
+static void
+csio_rns_offline(struct csio_rnode *rn, enum csio_rn_ev evt)
+{
+	struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+	int ret = 0;
+
+	CSIO_INC_STATS(rn, n_evt_sm[evt]);
+
+	switch (evt) {
+	case CSIO_RNFE_LOGGED_IN:
+	case CSIO_RNFE_PLOGI_RECV:
+		ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
+		if (!ret) {
+			csio_set_state(&rn->sm, csio_rns_ready);
+			__csio_reg_rnode(rn);
+		} else {
+			CSIO_INC_STATS(rn, n_err_inval);
+			csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
+		}
+		break;
+
+	case CSIO_RNFE_DOWN:
+		csio_ln_dbg(ln,
+			"ssni:x%x Ignoring event %d recv from did:x%x "
+			"in rn state[offline]\n", csio_rn_flowid(rn), evt,
+			rn->nport_id);
+		CSIO_INC_STATS(rn, n_evt_drop);
+		break;
+
+	case CSIO_RNFE_CLOSE:
+		/* Each rnode receives CLOSE event when driver is removed or
+		 * device is reset
+		 * Note: All outstanding IOs on remote port need to returned
+		 * to uppper layer with appropriate error before sending
+		 * CLOSE event
+		 */
+		csio_set_state(&rn->sm, csio_rns_uninit);
+		break;
+
+	case CSIO_RNFE_NAME_MISSING:
+		csio_set_state(&rn->sm, csio_rns_disappeared);
+		break;
+
+	default:
+		csio_ln_dbg(ln,
+			"ssni:x%x unexp event %d recv from did:x%x "
+			"in rn state[offline]\n", csio_rn_flowid(rn), evt,
+			rn->nport_id);
+		CSIO_INC_STATS(rn, n_evt_unexp);
+		break;
+	}
+}
+
+/*
+ * csio_rns_disappeared -
+ * @rn - rnode
+ * @evt - SM event.
+ *
+ */
+static void
+csio_rns_disappeared(struct csio_rnode *rn, enum csio_rn_ev evt)
+{
+	struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+	int ret = 0;
+
+	CSIO_INC_STATS(rn, n_evt_sm[evt]);
+
+	switch (evt) {
+	case CSIO_RNFE_LOGGED_IN:
+	case CSIO_RNFE_PLOGI_RECV:
+		ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
+		if (!ret) {
+			csio_set_state(&rn->sm, csio_rns_ready);
+			__csio_reg_rnode(rn);
+		} else {
+			CSIO_INC_STATS(rn, n_err_inval);
+			csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
+		}
+		break;
+
+	case CSIO_RNFE_CLOSE:
+		/* Each rnode receives CLOSE event when driver is removed or
+		 * device is reset.
+		 * Note: All outstanding IOs on remote port need to returned
+		 * to uppper layer with appropriate error before sending
+		 * CLOSE event
+		 */
+		csio_set_state(&rn->sm, csio_rns_uninit);
+		break;
+
+	case CSIO_RNFE_DOWN:
+	case CSIO_RNFE_NAME_MISSING:
+		csio_ln_dbg(ln,
+			"ssni:x%x Ignoring event %d recv from did x%x"
+			"in rn state[disappeared]\n", csio_rn_flowid(rn),
+			evt, rn->nport_id);
+		break;
+
+	default:
+		csio_ln_dbg(ln,
+			"ssni:x%x unexp event %d recv from did x%x"
+			"in rn state[disappeared]\n", csio_rn_flowid(rn),
+			evt, rn->nport_id);
+		CSIO_INC_STATS(rn, n_evt_unexp);
+		break;
+	}
+}
+
+/*****************************************************************************/
+/* END: Rnode SM                                                             */
+/*****************************************************************************/
+
+/*
+ * csio_rnode_devloss_handler - Device loss event handler
+ * @rn: rnode
+ *
+ * Post event to close rnode SM and free rnode.
+ */
+void
+csio_rnode_devloss_handler(struct csio_rnode *rn)
+{
+	struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+
+	/* ignore if same rnode came back as online */
+	if (csio_is_rnode_ready(rn))
+		return;
+
+	csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
+
+	/* Free rn if in uninit state */
+	if (csio_is_rnode_uninit(rn))
+		csio_put_rnode(ln, rn);
+}
+
+/**
+ * csio_rnode_fwevt_handler - Event handler for firmware rnode events.
+ * @rn:		rnode
+ *
+ */
+void
+csio_rnode_fwevt_handler(struct csio_rnode *rn, uint8_t fwevt)
+{
+	struct csio_lnode *ln = csio_rnode_to_lnode(rn);
+	enum csio_rn_ev evt;
+
+	evt = CSIO_FWE_TO_RNFE(fwevt);
+	if (!evt) {
+		csio_ln_err(ln, "ssni:x%x Unhandled FW Rdev event: %d\n",
+			    csio_rn_flowid(rn), fwevt);
+		CSIO_INC_STATS(rn, n_evt_unexp);
+		return;
+	}
+	CSIO_INC_STATS(rn, n_evt_fw[fwevt]);
+
+	/* Track previous & current events for debugging */
+	rn->prev_evt = rn->cur_evt;
+	rn->cur_evt = fwevt;
+
+	/* Post event to rnode SM */
+	csio_post_event(&rn->sm, evt);
+
+	/* Free rn if in uninit state */
+	if (csio_is_rnode_uninit(rn))
+		csio_put_rnode(ln, rn);
+}
+
+/*
+ * csio_rnode_init - Initialize rnode.
+ * @rn: RNode
+ * @ln: Associated lnode
+ *
+ * Caller is responsible for holding the lock. The lock is required
+ * to be held for inserting the rnode in ln->rnhead list.
+ */
+static int
+csio_rnode_init(struct csio_rnode *rn, struct csio_lnode *ln)
+{
+	csio_rnode_to_lnode(rn) = ln;
+	csio_init_state(&rn->sm, csio_rns_uninit);
+	INIT_LIST_HEAD(&rn->host_cmpl_q);
+	csio_rn_flowid(rn) = CSIO_INVALID_IDX;
+
+	/* Add rnode to list of lnodes->rnhead */
+	list_add_tail(&rn->sm.sm_list, &ln->rnhead);
+
+	return 0;
+}
+
+static void
+csio_rnode_exit(struct csio_rnode *rn)
+{
+	list_del_init(&rn->sm.sm_list);
+	CSIO_DB_ASSERT(list_empty(&rn->host_cmpl_q));
+}
diff --git a/drivers/scsi/csiostor/csio_rnode.h b/drivers/scsi/csiostor/csio_rnode.h
new file mode 100644
index 0000000..a3b434c
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_rnode.h
@@ -0,0 +1,141 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_RNODE_H__
+#define __CSIO_RNODE_H__
+
+#include "csio_defs.h"
+
+/* State machine evets */
+enum csio_rn_ev {
+	CSIO_RNFE_NONE = (uint32_t)0,			/* None */
+	CSIO_RNFE_LOGGED_IN,				/* [N/F]Port login
+							 * complete.
+							 */
+	CSIO_RNFE_PRLI_DONE,				/* PRLI completed */
+	CSIO_RNFE_PLOGI_RECV,				/* Received PLOGI */
+	CSIO_RNFE_PRLI_RECV,				/* Received PLOGI */
+	CSIO_RNFE_LOGO_RECV,				/* Received LOGO */
+	CSIO_RNFE_PRLO_RECV,				/* Received PRLO */
+	CSIO_RNFE_DOWN,					/* Rnode is down */
+	CSIO_RNFE_CLOSE,				/* Close rnode */
+	CSIO_RNFE_NAME_MISSING,				/* Rnode name missing
+							 * in name server.
+							 */
+	CSIO_RNFE_MAX_EVENT,
+};
+
+/* rnode stats */
+struct csio_rnode_stats {
+	uint32_t	n_err;		/* error */
+	uint32_t	n_err_inval;	/* invalid parameter */
+	uint32_t	n_err_nomem;	/* error nomem */
+	uint32_t	n_evt_unexp;	/* unexpected event */
+	uint32_t	n_evt_drop;	/* unexpected event */
+	uint32_t	n_evt_fw[RSCN_DEV_LOST];	/* fw events */
+	enum csio_rn_ev	n_evt_sm[CSIO_RNFE_MAX_EVENT];	/* State m/c events */
+	uint32_t	n_lun_rst;	/* Number of resets of
+					 * of LUNs under this
+					 * target
+					 */
+	uint32_t	n_lun_rst_fail;	/* Number of LUN reset
+					 * failures.
+					 */
+	uint32_t	n_tgt_rst;	/* Number of target resets */
+	uint32_t	n_tgt_rst_fail;	/* Number of target reset
+					 * failures.
+					 */
+};
+
+/* Defines for rnode role */
+#define	CSIO_RNFR_INITIATOR	0x1
+#define	CSIO_RNFR_TARGET	0x2
+#define CSIO_RNFR_FABRIC	0x4
+#define	CSIO_RNFR_NS		0x8
+#define CSIO_RNFR_NPORT		0x10
+
+struct csio_rnode {
+	struct csio_sm		sm;			/* State machine -
+							 * should be the
+							 * 1st member
+							 */
+	struct csio_lnode	*lnp;			/* Pointer to owning
+							 * Lnode */
+	uint32_t		flowid;			/* Firmware ID */
+	struct list_head	host_cmpl_q;		/* SCSI IOs
+							 * pending to completed
+							 * to Mid-layer.
+							 */
+	/* FC identifiers for remote node */
+	uint32_t		nport_id;
+	uint16_t		fcp_flags;		/* FCP Flags */
+	uint8_t			cur_evt;		/* Current event */
+	uint8_t			prev_evt;		/* Previous event */
+	uint32_t		role;			/* Fabric/Target/
+							 * Initiator/NS
+							 */
+	struct fcoe_rdev_entry		*rdev_entry;	/* Rdev entry */
+	struct csio_service_parms	rn_sparm;
+
+	/* FC transport attributes */
+	struct fc_rport		*rport;		/* FC transport rport */
+	uint32_t		supp_classes;	/* Supported FC classes */
+	uint32_t		maxframe_size;	/* Max Frame size */
+	uint32_t		scsi_id;	/* Transport given SCSI id */
+
+	struct csio_rnode_stats	stats;		/* Common rnode stats */
+};
+
+#define csio_rn_flowid(rn)			((rn)->flowid)
+#define csio_rn_wwpn(rn)			((rn)->rn_sparm.wwpn)
+#define csio_rn_wwnn(rn)			((rn)->rn_sparm.wwnn)
+#define csio_rnode_to_lnode(rn)			((rn)->lnp)
+
+int csio_is_rnode_ready(struct csio_rnode *rn);
+void csio_rnode_state_to_str(struct csio_rnode *rn, int8_t *str);
+
+struct csio_rnode *csio_rnode_lookup_portid(struct csio_lnode *, uint32_t);
+struct csio_rnode *csio_confirm_rnode(struct csio_lnode *,
+					  uint32_t, struct fcoe_rdev_entry *);
+
+void csio_rnode_fwevt_handler(struct csio_rnode *rn, uint8_t fwevt);
+
+void csio_put_rnode(struct csio_lnode *ln, struct csio_rnode *rn);
+
+void csio_reg_rnode(struct csio_rnode *);
+void csio_unreg_rnode(struct csio_rnode *);
+
+void csio_rnode_devloss_handler(struct csio_rnode *);
+
+#endif /* ifndef __CSIO_RNODE_H__ */
diff --git a/drivers/scsi/csiostor/csio_scsi.c b/drivers/scsi/csiostor/csio_scsi.c
new file mode 100644
index 0000000..fdbd7da
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_scsi.c
@@ -0,0 +1,2555 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/compiler.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <asm/unaligned.h>
+#include <asm/page.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_fc.h>
+
+#include "csio_hw.h"
+#include "csio_lnode.h"
+#include "csio_rnode.h"
+#include "csio_scsi.h"
+#include "csio_init.h"
+
+int csio_scsi_eqsize = 65536;
+int csio_scsi_iqlen = 128;
+int csio_scsi_ioreqs = 2048;
+uint32_t csio_max_scan_tmo;
+uint32_t csio_delta_scan_tmo = 5;
+int csio_lun_qdepth = 32;
+
+static int csio_ddp_descs = 128;
+
+static int csio_do_abrt_cls(struct csio_hw *,
+				      struct csio_ioreq *, bool);
+
+static void csio_scsis_uninit(struct csio_ioreq *, enum csio_scsi_ev);
+static void csio_scsis_io_active(struct csio_ioreq *, enum csio_scsi_ev);
+static void csio_scsis_tm_active(struct csio_ioreq *, enum csio_scsi_ev);
+static void csio_scsis_aborting(struct csio_ioreq *, enum csio_scsi_ev);
+static void csio_scsis_closing(struct csio_ioreq *, enum csio_scsi_ev);
+static void csio_scsis_shost_cmpl_await(struct csio_ioreq *, enum csio_scsi_ev);
+
+/*
+ * csio_scsi_match_io - Match an ioreq with the given SCSI level data.
+ * @ioreq: The I/O request
+ * @sld: Level information
+ *
+ * Should be called with lock held.
+ *
+ */
+static bool
+csio_scsi_match_io(struct csio_ioreq *ioreq, struct csio_scsi_level_data *sld)
+{
+	struct scsi_cmnd *scmnd = csio_scsi_cmnd(ioreq);
+
+	switch (sld->level) {
+	case CSIO_LEV_LUN:
+		if (scmnd == NULL)
+			return false;
+
+		return ((ioreq->lnode == sld->lnode) &&
+			(ioreq->rnode == sld->rnode) &&
+			((uint64_t)scmnd->device->lun == sld->oslun));
+
+	case CSIO_LEV_RNODE:
+		return ((ioreq->lnode == sld->lnode) &&
+				(ioreq->rnode == sld->rnode));
+	case CSIO_LEV_LNODE:
+		return (ioreq->lnode == sld->lnode);
+	case CSIO_LEV_ALL:
+		return true;
+	default:
+		return false;
+	}
+}
+
+/*
+ * csio_scsi_gather_active_ios - Gather active I/Os based on level
+ * @scm: SCSI module
+ * @sld: Level information
+ * @dest: The queue where these I/Os have to be gathered.
+ *
+ * Should be called with lock held.
+ */
+static void
+csio_scsi_gather_active_ios(struct csio_scsim *scm,
+			    struct csio_scsi_level_data *sld,
+			    struct list_head *dest)
+{
+	struct list_head *tmp, *next;
+
+	if (list_empty(&scm->active_q))
+		return;
+
+	/* Just splice the entire active_q into dest */
+	if (sld->level == CSIO_LEV_ALL) {
+		list_splice_tail_init(&scm->active_q, dest);
+		return;
+	}
+
+	list_for_each_safe(tmp, next, &scm->active_q) {
+		if (csio_scsi_match_io((struct csio_ioreq *)tmp, sld)) {
+			list_del_init(tmp);
+			list_add_tail(tmp, dest);
+		}
+	}
+}
+
+static inline bool
+csio_scsi_itnexus_loss_error(uint16_t error)
+{
+	switch (error) {
+	case FW_ERR_LINK_DOWN:
+	case FW_RDEV_NOT_READY:
+	case FW_ERR_RDEV_LOST:
+	case FW_ERR_RDEV_LOGO:
+	case FW_ERR_RDEV_IMPL_LOGO:
+		return 1;
+	}
+	return 0;
+}
+
+static inline void
+csio_scsi_tag(struct scsi_cmnd *scmnd, uint8_t *tag, uint8_t hq,
+	      uint8_t oq, uint8_t sq)
+{
+	char stag[2];
+
+	if (scsi_populate_tag_msg(scmnd, stag)) {
+		switch (stag[0]) {
+		case HEAD_OF_QUEUE_TAG:
+			*tag = hq;
+			break;
+		case ORDERED_QUEUE_TAG:
+			*tag = oq;
+			break;
+		default:
+			*tag = sq;
+			break;
+		}
+	} else
+		*tag = 0;
+}
+
+/*
+ * csio_scsi_fcp_cmnd - Frame the SCSI FCP command paylod.
+ * @req: IO req structure.
+ * @addr: DMA location to place the payload.
+ *
+ * This routine is shared between FCP_WRITE, FCP_READ and FCP_CMD requests.
+ */
+static inline void
+csio_scsi_fcp_cmnd(struct csio_ioreq *req, void *addr)
+{
+	struct fcp_cmnd *fcp_cmnd = (struct fcp_cmnd *)addr;
+	struct scsi_cmnd *scmnd = csio_scsi_cmnd(req);
+
+	/* Check for Task Management */
+	if (likely(scmnd->SCp.Message == 0)) {
+		int_to_scsilun(scmnd->device->lun, &fcp_cmnd->fc_lun);
+		fcp_cmnd->fc_tm_flags = 0;
+		fcp_cmnd->fc_cmdref = 0;
+		fcp_cmnd->fc_pri_ta = 0;
+
+		memcpy(fcp_cmnd->fc_cdb, scmnd->cmnd, 16);
+		csio_scsi_tag(scmnd, &fcp_cmnd->fc_pri_ta,
+			      FCP_PTA_HEADQ, FCP_PTA_ORDERED, FCP_PTA_SIMPLE);
+		fcp_cmnd->fc_dl = cpu_to_be32(scsi_bufflen(scmnd));
+
+		if (req->nsge)
+			if (req->datadir == DMA_TO_DEVICE)
+				fcp_cmnd->fc_flags = FCP_CFL_WRDATA;
+			else
+				fcp_cmnd->fc_flags = FCP_CFL_RDDATA;
+		else
+			fcp_cmnd->fc_flags = 0;
+	} else {
+		memset(fcp_cmnd, 0, sizeof(*fcp_cmnd));
+		int_to_scsilun(scmnd->device->lun, &fcp_cmnd->fc_lun);
+		fcp_cmnd->fc_tm_flags = (uint8_t)scmnd->SCp.Message;
+	}
+}
+
+/*
+ * csio_scsi_init_cmd_wr - Initialize the SCSI CMD WR.
+ * @req: IO req structure.
+ * @addr: DMA location to place the payload.
+ * @size: Size of WR (including FW WR + immed data + rsp SG entry
+ *
+ * Wrapper for populating fw_scsi_cmd_wr.
+ */
+static inline void
+csio_scsi_init_cmd_wr(struct csio_ioreq *req, void *addr, uint32_t size)
+{
+	struct csio_hw *hw = req->lnode->hwp;
+	struct csio_rnode *rn = req->rnode;
+	struct fw_scsi_cmd_wr *wr = (struct fw_scsi_cmd_wr *)addr;
+	struct csio_dma_buf *dma_buf;
+	uint8_t imm = csio_hw_to_scsim(hw)->proto_cmd_len;
+
+	wr->op_immdlen = cpu_to_be32(FW_WR_OP(FW_SCSI_CMD_WR) |
+					  FW_SCSI_CMD_WR_IMMDLEN(imm));
+	wr->flowid_len16 = cpu_to_be32(FW_WR_FLOWID(rn->flowid) |
+					    FW_WR_LEN16(
+						DIV_ROUND_UP(size, 16)));
+
+	wr->cookie = (uintptr_t) req;
+	wr->iqid = (uint16_t)cpu_to_be16(csio_q_physiqid(hw, req->iq_idx));
+	wr->tmo_val = (uint8_t) req->tmo;
+	wr->r3 = 0;
+	memset(&wr->r5, 0, 8);
+
+	/* Get RSP DMA buffer */
+	dma_buf = &req->dma_buf;
+
+	/* Prepare RSP SGL */
+	wr->rsp_dmalen = cpu_to_be32(dma_buf->len);
+	wr->rsp_dmaaddr = cpu_to_be64(dma_buf->paddr);
+
+	wr->r6 = 0;
+
+	wr->u.fcoe.ctl_pri = 0;
+	wr->u.fcoe.cp_en_class = 0;
+	wr->u.fcoe.r4_lo[0] = 0;
+	wr->u.fcoe.r4_lo[1] = 0;
+
+	/* Frame a FCP command */
+	csio_scsi_fcp_cmnd(req, (void *)((uintptr_t)addr +
+				    sizeof(struct fw_scsi_cmd_wr)));
+}
+
+#define CSIO_SCSI_CMD_WR_SZ(_imm)					\
+	(sizeof(struct fw_scsi_cmd_wr) +		/* WR size */	\
+	 ALIGN((_imm), 16))				/* Immed data */
+
+#define CSIO_SCSI_CMD_WR_SZ_16(_imm)					\
+			(ALIGN(CSIO_SCSI_CMD_WR_SZ((_imm)), 16))
+
+/*
+ * csio_scsi_cmd - Create a SCSI CMD WR.
+ * @req: IO req structure.
+ *
+ * Gets a WR slot in the ingress queue and initializes it with SCSI CMD WR.
+ *
+ */
+static inline void
+csio_scsi_cmd(struct csio_ioreq *req)
+{
+	struct csio_wr_pair wrp;
+	struct csio_hw *hw = req->lnode->hwp;
+	struct csio_scsim *scsim = csio_hw_to_scsim(hw);
+	uint32_t size = CSIO_SCSI_CMD_WR_SZ_16(scsim->proto_cmd_len);
+
+	req->drv_status = csio_wr_get(hw, req->eq_idx, size, &wrp);
+	if (unlikely(req->drv_status != 0))
+		return;
+
+	if (wrp.size1 >= size) {
+		/* Initialize WR in one shot */
+		csio_scsi_init_cmd_wr(req, wrp.addr1, size);
+	} else {
+		uint8_t *tmpwr = csio_q_eq_wrap(hw, req->eq_idx);
+
+		/*
+		 * Make a temporary copy of the WR and write back
+		 * the copy into the WR pair.
+		 */
+		csio_scsi_init_cmd_wr(req, (void *)tmpwr, size);
+		memcpy(wrp.addr1, tmpwr, wrp.size1);
+		memcpy(wrp.addr2, tmpwr + wrp.size1, size - wrp.size1);
+	}
+}
+
+/*
+ * csio_scsi_init_ulptx_dsgl - Fill in a ULP_TX_SC_DSGL
+ * @hw: HW module
+ * @req: IO request
+ * @sgl: ULP TX SGL pointer.
+ *
+ */
+static inline void
+csio_scsi_init_ultptx_dsgl(struct csio_hw *hw, struct csio_ioreq *req,
+			   struct ulptx_sgl *sgl)
+{
+	struct ulptx_sge_pair *sge_pair = NULL;
+	struct scatterlist *sgel;
+	uint32_t i = 0;
+	uint32_t xfer_len;
+	struct list_head *tmp;
+	struct csio_dma_buf *dma_buf;
+	struct scsi_cmnd *scmnd = csio_scsi_cmnd(req);
+
+	sgl->cmd_nsge = htonl(ULPTX_CMD(ULP_TX_SC_DSGL) | ULPTX_MORE |
+				     ULPTX_NSGE(req->nsge));
+	/* Now add the data SGLs */
+	if (likely(!req->dcopy)) {
+		scsi_for_each_sg(scmnd, sgel, req->nsge, i) {
+			if (i == 0) {
+				sgl->addr0 = cpu_to_be64(sg_dma_address(sgel));
+				sgl->len0 = cpu_to_be32(sg_dma_len(sgel));
+				sge_pair = (struct ulptx_sge_pair *)(sgl + 1);
+				continue;
+			}
+			if ((i - 1) & 0x1) {
+				sge_pair->addr[1] = cpu_to_be64(
+							sg_dma_address(sgel));
+				sge_pair->len[1] = cpu_to_be32(
+							sg_dma_len(sgel));
+				sge_pair++;
+			} else {
+				sge_pair->addr[0] = cpu_to_be64(
+							sg_dma_address(sgel));
+				sge_pair->len[0] = cpu_to_be32(
+							sg_dma_len(sgel));
+			}
+		}
+	} else {
+		/* Program sg elements with driver's DDP buffer */
+		xfer_len = scsi_bufflen(scmnd);
+		list_for_each(tmp, &req->gen_list) {
+			dma_buf = (struct csio_dma_buf *)tmp;
+			if (i == 0) {
+				sgl->addr0 = cpu_to_be64(dma_buf->paddr);
+				sgl->len0 = cpu_to_be32(
+						min(xfer_len, dma_buf->len));
+				sge_pair = (struct ulptx_sge_pair *)(sgl + 1);
+			} else if ((i - 1) & 0x1) {
+				sge_pair->addr[1] = cpu_to_be64(dma_buf->paddr);
+				sge_pair->len[1] = cpu_to_be32(
+						min(xfer_len, dma_buf->len));
+				sge_pair++;
+			} else {
+				sge_pair->addr[0] = cpu_to_be64(dma_buf->paddr);
+				sge_pair->len[0] = cpu_to_be32(
+						min(xfer_len, dma_buf->len));
+			}
+			xfer_len -= min(xfer_len, dma_buf->len);
+			i++;
+		}
+	}
+}
+
+/*
+ * csio_scsi_init_read_wr - Initialize the READ SCSI WR.
+ * @req: IO req structure.
+ * @wrp: DMA location to place the payload.
+ * @size: Size of WR (including FW WR + immed data + rsp SG entry + data SGL
+ *
+ * Wrapper for populating fw_scsi_read_wr.
+ */
+static inline void
+csio_scsi_init_read_wr(struct csio_ioreq *req, void *wrp, uint32_t size)
+{
+	struct csio_hw *hw = req->lnode->hwp;
+	struct csio_rnode *rn = req->rnode;
+	struct fw_scsi_read_wr *wr = (struct fw_scsi_read_wr *)wrp;
+	struct ulptx_sgl *sgl;
+	struct csio_dma_buf *dma_buf;
+	uint8_t imm = csio_hw_to_scsim(hw)->proto_cmd_len;
+	struct scsi_cmnd *scmnd = csio_scsi_cmnd(req);
+
+	wr->op_immdlen = cpu_to_be32(FW_WR_OP(FW_SCSI_READ_WR) |
+				     FW_SCSI_READ_WR_IMMDLEN(imm));
+	wr->flowid_len16 = cpu_to_be32(FW_WR_FLOWID(rn->flowid) |
+				       FW_WR_LEN16(DIV_ROUND_UP(size, 16)));
+	wr->cookie = (uintptr_t)req;
+	wr->iqid = (uint16_t)cpu_to_be16(csio_q_physiqid(hw, req->iq_idx));
+	wr->tmo_val = (uint8_t)(req->tmo);
+	wr->use_xfer_cnt = 1;
+	wr->xfer_cnt = cpu_to_be32(scsi_bufflen(scmnd));
+	wr->ini_xfer_cnt = cpu_to_be32(scsi_bufflen(scmnd));
+	/* Get RSP DMA buffer */
+	dma_buf = &req->dma_buf;
+
+	/* Prepare RSP SGL */
+	wr->rsp_dmalen = cpu_to_be32(dma_buf->len);
+	wr->rsp_dmaaddr = cpu_to_be64(dma_buf->paddr);
+
+	wr->r4 = 0;
+
+	wr->u.fcoe.ctl_pri = 0;
+	wr->u.fcoe.cp_en_class = 0;
+	wr->u.fcoe.r3_lo[0] = 0;
+	wr->u.fcoe.r3_lo[1] = 0;
+	csio_scsi_fcp_cmnd(req, (void *)((uintptr_t)wrp +
+					sizeof(struct fw_scsi_read_wr)));
+
+	/* Move WR pointer past command and immediate data */
+	sgl = (struct ulptx_sgl *)((uintptr_t)wrp +
+			      sizeof(struct fw_scsi_read_wr) + ALIGN(imm, 16));
+
+	/* Fill in the DSGL */
+	csio_scsi_init_ultptx_dsgl(hw, req, sgl);
+}
+
+/*
+ * csio_scsi_init_write_wr - Initialize the WRITE SCSI WR.
+ * @req: IO req structure.
+ * @wrp: DMA location to place the payload.
+ * @size: Size of WR (including FW WR + immed data + rsp SG entry + data SGL
+ *
+ * Wrapper for populating fw_scsi_write_wr.
+ */
+static inline void
+csio_scsi_init_write_wr(struct csio_ioreq *req, void *wrp, uint32_t size)
+{
+	struct csio_hw *hw = req->lnode->hwp;
+	struct csio_rnode *rn = req->rnode;
+	struct fw_scsi_write_wr *wr = (struct fw_scsi_write_wr *)wrp;
+	struct ulptx_sgl *sgl;
+	struct csio_dma_buf *dma_buf;
+	uint8_t imm = csio_hw_to_scsim(hw)->proto_cmd_len;
+	struct scsi_cmnd *scmnd = csio_scsi_cmnd(req);
+
+	wr->op_immdlen = cpu_to_be32(FW_WR_OP(FW_SCSI_WRITE_WR) |
+				     FW_SCSI_WRITE_WR_IMMDLEN(imm));
+	wr->flowid_len16 = cpu_to_be32(FW_WR_FLOWID(rn->flowid) |
+				       FW_WR_LEN16(DIV_ROUND_UP(size, 16)));
+	wr->cookie = (uintptr_t)req;
+	wr->iqid = (uint16_t)cpu_to_be16(csio_q_physiqid(hw, req->iq_idx));
+	wr->tmo_val = (uint8_t)(req->tmo);
+	wr->use_xfer_cnt = 1;
+	wr->xfer_cnt = cpu_to_be32(scsi_bufflen(scmnd));
+	wr->ini_xfer_cnt = cpu_to_be32(scsi_bufflen(scmnd));
+	/* Get RSP DMA buffer */
+	dma_buf = &req->dma_buf;
+
+	/* Prepare RSP SGL */
+	wr->rsp_dmalen = cpu_to_be32(dma_buf->len);
+	wr->rsp_dmaaddr = cpu_to_be64(dma_buf->paddr);
+
+	wr->r4 = 0;
+
+	wr->u.fcoe.ctl_pri = 0;
+	wr->u.fcoe.cp_en_class = 0;
+	wr->u.fcoe.r3_lo[0] = 0;
+	wr->u.fcoe.r3_lo[1] = 0;
+	csio_scsi_fcp_cmnd(req, (void *)((uintptr_t)wrp +
+					sizeof(struct fw_scsi_write_wr)));
+
+	/* Move WR pointer past command and immediate data */
+	sgl = (struct ulptx_sgl *)((uintptr_t)wrp +
+			      sizeof(struct fw_scsi_write_wr) + ALIGN(imm, 16));
+
+	/* Fill in the DSGL */
+	csio_scsi_init_ultptx_dsgl(hw, req, sgl);
+}
+
+/* Calculate WR size needed for fw_scsi_read_wr/fw_scsi_write_wr */
+#define CSIO_SCSI_DATA_WRSZ(req, oper, sz, imm)				       \
+do {									       \
+	(sz) = sizeof(struct fw_scsi_##oper##_wr) +	/* WR size */          \
+	       ALIGN((imm), 16) +			/* Immed data */       \
+	       sizeof(struct ulptx_sgl);		/* ulptx_sgl */	       \
+									       \
+	if (unlikely((req)->nsge > 1))				               \
+		(sz) += (sizeof(struct ulptx_sge_pair) *		       \
+				(ALIGN(((req)->nsge - 1), 2) / 2));            \
+							/* Data SGE */	       \
+} while (0)
+
+/*
+ * csio_scsi_read - Create a SCSI READ WR.
+ * @req: IO req structure.
+ *
+ * Gets a WR slot in the ingress queue and initializes it with
+ * SCSI READ WR.
+ *
+ */
+static inline void
+csio_scsi_read(struct csio_ioreq *req)
+{
+	struct csio_wr_pair wrp;
+	uint32_t size;
+	struct csio_hw *hw = req->lnode->hwp;
+	struct csio_scsim *scsim = csio_hw_to_scsim(hw);
+
+	CSIO_SCSI_DATA_WRSZ(req, read, size, scsim->proto_cmd_len);
+	size = ALIGN(size, 16);
+
+	req->drv_status = csio_wr_get(hw, req->eq_idx, size, &wrp);
+	if (likely(req->drv_status == 0)) {
+		if (likely(wrp.size1 >= size)) {
+			/* Initialize WR in one shot */
+			csio_scsi_init_read_wr(req, wrp.addr1, size);
+		} else {
+			uint8_t *tmpwr = csio_q_eq_wrap(hw, req->eq_idx);
+			/*
+			 * Make a temporary copy of the WR and write back
+			 * the copy into the WR pair.
+			 */
+			csio_scsi_init_read_wr(req, (void *)tmpwr, size);
+			memcpy(wrp.addr1, tmpwr, wrp.size1);
+			memcpy(wrp.addr2, tmpwr + wrp.size1, size - wrp.size1);
+		}
+	}
+}
+
+/*
+ * csio_scsi_write - Create a SCSI WRITE WR.
+ * @req: IO req structure.
+ *
+ * Gets a WR slot in the ingress queue and initializes it with
+ * SCSI WRITE WR.
+ *
+ */
+static inline void
+csio_scsi_write(struct csio_ioreq *req)
+{
+	struct csio_wr_pair wrp;
+	uint32_t size;
+	struct csio_hw *hw = req->lnode->hwp;
+	struct csio_scsim *scsim = csio_hw_to_scsim(hw);
+
+	CSIO_SCSI_DATA_WRSZ(req, write, size, scsim->proto_cmd_len);
+	size = ALIGN(size, 16);
+
+	req->drv_status = csio_wr_get(hw, req->eq_idx, size, &wrp);
+	if (likely(req->drv_status == 0)) {
+		if (likely(wrp.size1 >= size)) {
+			/* Initialize WR in one shot */
+			csio_scsi_init_write_wr(req, wrp.addr1, size);
+		} else {
+			uint8_t *tmpwr = csio_q_eq_wrap(hw, req->eq_idx);
+			/*
+			 * Make a temporary copy of the WR and write back
+			 * the copy into the WR pair.
+			 */
+			csio_scsi_init_write_wr(req, (void *)tmpwr, size);
+			memcpy(wrp.addr1, tmpwr, wrp.size1);
+			memcpy(wrp.addr2, tmpwr + wrp.size1, size - wrp.size1);
+		}
+	}
+}
+
+/*
+ * csio_setup_ddp - Setup DDP buffers for Read request.
+ * @req: IO req structure.
+ *
+ * Checks SGLs/Data buffers are virtually contiguous required for DDP.
+ * If contiguous,driver posts SGLs in the WR otherwise post internal
+ * buffers for such request for DDP.
+ */
+static inline void
+csio_setup_ddp(struct csio_scsim *scsim, struct csio_ioreq *req)
+{
+#ifdef __CSIO_DEBUG__
+	struct csio_hw *hw = req->lnode->hwp;
+#endif
+	struct scatterlist *sgel = NULL;
+	struct scsi_cmnd *scmnd = csio_scsi_cmnd(req);
+	uint64_t sg_addr = 0;
+	uint32_t ddp_pagesz = 4096;
+	uint32_t buf_off;
+	struct csio_dma_buf *dma_buf = NULL;
+	uint32_t alloc_len = 0;
+	uint32_t xfer_len = 0;
+	uint32_t sg_len = 0;
+	uint32_t i;
+
+	scsi_for_each_sg(scmnd, sgel, req->nsge, i) {
+		sg_addr = sg_dma_address(sgel);
+		sg_len	= sg_dma_len(sgel);
+
+		buf_off = sg_addr & (ddp_pagesz - 1);
+
+		/* Except 1st buffer,all buffer addr have to be Page aligned */
+		if (i != 0 && buf_off) {
+			csio_dbg(hw, "SGL addr not DDP aligned (%llx:%d)\n",
+				 sg_addr, sg_len);
+			goto unaligned;
+		}
+
+		/* Except last buffer,all buffer must end on page boundary */
+		if ((i != (req->nsge - 1)) &&
+			((buf_off + sg_len) & (ddp_pagesz - 1))) {
+			csio_dbg(hw,
+				 "SGL addr not ending on page boundary"
+				 "(%llx:%d)\n", sg_addr, sg_len);
+			goto unaligned;
+		}
+	}
+
+	/* SGL's are virtually contiguous. HW will DDP to SGLs */
+	req->dcopy = 0;
+	csio_scsi_read(req);
+
+	return;
+
+unaligned:
+	CSIO_INC_STATS(scsim, n_unaligned);
+	/*
+	 * For unaligned SGLs, driver will allocate internal DDP buffer.
+	 * Once command is completed data from DDP buffer copied to SGLs
+	 */
+	req->dcopy = 1;
+
+	/* Use gen_list to store the DDP buffers */
+	INIT_LIST_HEAD(&req->gen_list);
+	xfer_len = scsi_bufflen(scmnd);
+
+	i = 0;
+	/* Allocate ddp buffers for this request */
+	while (alloc_len < xfer_len) {
+		dma_buf = csio_get_scsi_ddp(scsim);
+		if (dma_buf == NULL || i > scsim->max_sge) {
+			req->drv_status = -EBUSY;
+			break;
+		}
+		alloc_len += dma_buf->len;
+		/* Added to IO req */
+		list_add_tail(&dma_buf->list, &req->gen_list);
+		i++;
+	}
+
+	if (!req->drv_status) {
+		/* set number of ddp bufs used */
+		req->nsge = i;
+		csio_scsi_read(req);
+		return;
+	}
+
+	 /* release dma descs */
+	if (i > 0)
+		csio_put_scsi_ddp_list(scsim, &req->gen_list, i);
+}
+
+/*
+ * csio_scsi_init_abrt_cls_wr - Initialize an ABORT/CLOSE WR.
+ * @req: IO req structure.
+ * @addr: DMA location to place the payload.
+ * @size: Size of WR
+ * @abort: abort OR close
+ *
+ * Wrapper for populating fw_scsi_cmd_wr.
+ */
+static inline void
+csio_scsi_init_abrt_cls_wr(struct csio_ioreq *req, void *addr, uint32_t size,
+			   bool abort)
+{
+	struct csio_hw *hw = req->lnode->hwp;
+	struct csio_rnode *rn = req->rnode;
+	struct fw_scsi_abrt_cls_wr *wr = (struct fw_scsi_abrt_cls_wr *)addr;
+
+	wr->op_immdlen = cpu_to_be32(FW_WR_OP(FW_SCSI_ABRT_CLS_WR));
+	wr->flowid_len16 = cpu_to_be32(FW_WR_FLOWID(rn->flowid) |
+					    FW_WR_LEN16(
+						DIV_ROUND_UP(size, 16)));
+
+	wr->cookie = (uintptr_t) req;
+	wr->iqid = (uint16_t)cpu_to_be16(csio_q_physiqid(hw, req->iq_idx));
+	wr->tmo_val = (uint8_t) req->tmo;
+	/* 0 for CHK_ALL_IO tells FW to look up t_cookie */
+	wr->sub_opcode_to_chk_all_io =
+				(FW_SCSI_ABRT_CLS_WR_SUB_OPCODE(abort) |
+				 FW_SCSI_ABRT_CLS_WR_CHK_ALL_IO(0));
+	wr->r3[0] = 0;
+	wr->r3[1] = 0;
+	wr->r3[2] = 0;
+	wr->r3[3] = 0;
+	/* Since we re-use the same ioreq for abort as well */
+	wr->t_cookie = (uintptr_t) req;
+}
+
+static inline void
+csio_scsi_abrt_cls(struct csio_ioreq *req, bool abort)
+{
+	struct csio_wr_pair wrp;
+	struct csio_hw *hw = req->lnode->hwp;
+	uint32_t size = ALIGN(sizeof(struct fw_scsi_abrt_cls_wr), 16);
+
+	req->drv_status = csio_wr_get(hw, req->eq_idx, size, &wrp);
+	if (req->drv_status != 0)
+		return;
+
+	if (wrp.size1 >= size) {
+		/* Initialize WR in one shot */
+		csio_scsi_init_abrt_cls_wr(req, wrp.addr1, size, abort);
+	} else {
+		uint8_t *tmpwr = csio_q_eq_wrap(hw, req->eq_idx);
+		/*
+		 * Make a temporary copy of the WR and write back
+		 * the copy into the WR pair.
+		 */
+		csio_scsi_init_abrt_cls_wr(req, (void *)tmpwr, size, abort);
+		memcpy(wrp.addr1, tmpwr, wrp.size1);
+		memcpy(wrp.addr2, tmpwr + wrp.size1, size - wrp.size1);
+	}
+}
+
+/*****************************************************************************/
+/* START: SCSI SM                                                            */
+/*****************************************************************************/
+static void
+csio_scsis_uninit(struct csio_ioreq *req, enum csio_scsi_ev evt)
+{
+	struct csio_hw *hw = req->lnode->hwp;
+	struct csio_scsim *scsim = csio_hw_to_scsim(hw);
+
+	switch (evt) {
+	case CSIO_SCSIE_START_IO:
+
+		if (req->nsge) {
+			if (req->datadir == DMA_TO_DEVICE) {
+				req->dcopy = 0;
+				csio_scsi_write(req);
+			} else
+				csio_setup_ddp(scsim, req);
+		} else {
+			csio_scsi_cmd(req);
+		}
+
+		if (likely(req->drv_status == 0)) {
+			/* change state and enqueue on active_q */
+			csio_set_state(&req->sm, csio_scsis_io_active);
+			list_add_tail(&req->sm.sm_list, &scsim->active_q);
+			csio_wr_issue(hw, req->eq_idx, false);
+			CSIO_INC_STATS(scsim, n_active);
+
+			return;
+		}
+		break;
+
+	case CSIO_SCSIE_START_TM:
+		csio_scsi_cmd(req);
+		if (req->drv_status == 0) {
+			/*
+			 * NOTE: We collect the affected I/Os prior to issuing
+			 * LUN reset, and not after it. This is to prevent
+			 * aborting I/Os that get issued after the LUN reset,
+			 * but prior to LUN reset completion (in the event that
+			 * the host stack has not blocked I/Os to a LUN that is
+			 * being reset.
+			 */
+			csio_set_state(&req->sm, csio_scsis_tm_active);
+			list_add_tail(&req->sm.sm_list, &scsim->active_q);
+			csio_wr_issue(hw, req->eq_idx, false);
+			CSIO_INC_STATS(scsim, n_tm_active);
+		}
+		return;
+
+	case CSIO_SCSIE_ABORT:
+	case CSIO_SCSIE_CLOSE:
+		/*
+		 * NOTE:
+		 * We could get here due to  :
+		 * - a window in the cleanup path of the SCSI module
+		 *   (csio_scsi_abort_io()). Please see NOTE in this function.
+		 * - a window in the time we tried to issue an abort/close
+		 *   of a request to FW, and the FW completed the request
+		 *   itself.
+		 *   Print a message for now, and return INVAL either way.
+		 */
+		req->drv_status = -EINVAL;
+		csio_warn(hw, "Trying to abort/close completed IO:%p!\n", req);
+		break;
+
+	default:
+		csio_dbg(hw, "Unhandled event:%d sent to req:%p\n", evt, req);
+		CSIO_DB_ASSERT(0);
+	}
+}
+
+static void
+csio_scsis_io_active(struct csio_ioreq *req, enum csio_scsi_ev evt)
+{
+	struct csio_hw *hw = req->lnode->hwp;
+	struct csio_scsim *scm = csio_hw_to_scsim(hw);
+	struct csio_rnode *rn;
+
+	switch (evt) {
+	case CSIO_SCSIE_COMPLETED:
+		CSIO_DEC_STATS(scm, n_active);
+		list_del_init(&req->sm.sm_list);
+		csio_set_state(&req->sm, csio_scsis_uninit);
+		/*
+		 * In MSIX mode, with multiple queues, the SCSI compeltions
+		 * could reach us sooner than the FW events sent to indicate
+		 * I-T nexus loss (link down, remote device logo etc). We
+		 * dont want to be returning such I/Os to the upper layer
+		 * immediately, since we wouldnt have reported the I-T nexus
+		 * loss itself. This forces us to serialize such completions
+		 * with the reporting of the I-T nexus loss. Therefore, we
+		 * internally queue up such up such completions in the rnode.
+		 * The reporting of I-T nexus loss to the upper layer is then
+		 * followed by the returning of I/Os in this internal queue.
+		 * Having another state alongwith another queue helps us take
+		 * actions for events such as ABORT received while we are
+		 * in this rnode queue.
+		 */
+		if (unlikely(req->wr_status != FW_SUCCESS)) {
+			rn = req->rnode;
+			/*
+			 * FW says remote device is lost, but rnode
+			 * doesnt reflect it.
+			 */
+			if (csio_scsi_itnexus_loss_error(req->wr_status) &&
+						csio_is_rnode_ready(rn)) {
+				csio_set_state(&req->sm,
+						csio_scsis_shost_cmpl_await);
+				list_add_tail(&req->sm.sm_list,
+					      &rn->host_cmpl_q);
+			}
+		}
+
+		break;
+
+	case CSIO_SCSIE_ABORT:
+		csio_scsi_abrt_cls(req, SCSI_ABORT);
+		if (req->drv_status == 0) {
+			csio_wr_issue(hw, req->eq_idx, false);
+			csio_set_state(&req->sm, csio_scsis_aborting);
+		}
+		break;
+
+	case CSIO_SCSIE_CLOSE:
+		csio_scsi_abrt_cls(req, SCSI_CLOSE);
+		if (req->drv_status == 0) {
+			csio_wr_issue(hw, req->eq_idx, false);
+			csio_set_state(&req->sm, csio_scsis_closing);
+		}
+		break;
+
+	case CSIO_SCSIE_DRVCLEANUP:
+		req->wr_status = FW_HOSTERROR;
+		CSIO_DEC_STATS(scm, n_active);
+		csio_set_state(&req->sm, csio_scsis_uninit);
+		break;
+
+	default:
+		csio_dbg(hw, "Unhandled event:%d sent to req:%p\n", evt, req);
+		CSIO_DB_ASSERT(0);
+	}
+}
+
+static void
+csio_scsis_tm_active(struct csio_ioreq *req, enum csio_scsi_ev evt)
+{
+	struct csio_hw *hw = req->lnode->hwp;
+	struct csio_scsim *scm = csio_hw_to_scsim(hw);
+
+	switch (evt) {
+	case CSIO_SCSIE_COMPLETED:
+		CSIO_DEC_STATS(scm, n_tm_active);
+		list_del_init(&req->sm.sm_list);
+		csio_set_state(&req->sm, csio_scsis_uninit);
+
+		break;
+
+	case CSIO_SCSIE_ABORT:
+		csio_scsi_abrt_cls(req, SCSI_ABORT);
+		if (req->drv_status == 0) {
+			csio_wr_issue(hw, req->eq_idx, false);
+			csio_set_state(&req->sm, csio_scsis_aborting);
+		}
+		break;
+
+
+	case CSIO_SCSIE_CLOSE:
+		csio_scsi_abrt_cls(req, SCSI_CLOSE);
+		if (req->drv_status == 0) {
+			csio_wr_issue(hw, req->eq_idx, false);
+			csio_set_state(&req->sm, csio_scsis_closing);
+		}
+		break;
+
+	case CSIO_SCSIE_DRVCLEANUP:
+		req->wr_status = FW_HOSTERROR;
+		CSIO_DEC_STATS(scm, n_tm_active);
+		csio_set_state(&req->sm, csio_scsis_uninit);
+		break;
+
+	default:
+		csio_dbg(hw, "Unhandled event:%d sent to req:%p\n", evt, req);
+		CSIO_DB_ASSERT(0);
+	}
+}
+
+static void
+csio_scsis_aborting(struct csio_ioreq *req, enum csio_scsi_ev evt)
+{
+	struct csio_hw *hw = req->lnode->hwp;
+	struct csio_scsim *scm = csio_hw_to_scsim(hw);
+
+	switch (evt) {
+	case CSIO_SCSIE_COMPLETED:
+		csio_dbg(hw,
+			 "ioreq %p recvd cmpltd (wr_status:%d) "
+			 "in aborting st\n", req, req->wr_status);
+		/*
+		 * Use -ECANCELED to explicitly tell the ABORTED event that
+		 * the original I/O was returned to driver by FW.
+		 * We dont really care if the I/O was returned with success by
+		 * FW (because the ABORT and completion of the I/O crossed each
+		 * other), or any other return value. Once we are in aborting
+		 * state, the success or failure of the I/O is unimportant to
+		 * us.
+		 */
+		req->drv_status = -ECANCELED;
+		break;
+
+	case CSIO_SCSIE_ABORT:
+		CSIO_INC_STATS(scm, n_abrt_dups);
+		break;
+
+	case CSIO_SCSIE_ABORTED:
+
+		csio_dbg(hw, "abort of %p return status:0x%x drv_status:%x\n",
+			 req, req->wr_status, req->drv_status);
+		/*
+		 * Check if original I/O WR completed before the Abort
+		 * completion.
+		 */
+		if (req->drv_status != -ECANCELED) {
+			csio_warn(hw,
+				  "Abort completed before original I/O,"
+				   " req:%p\n", req);
+			CSIO_DB_ASSERT(0);
+		}
+
+		/*
+		 * There are the following possible scenarios:
+		 * 1. The abort completed successfully, FW returned FW_SUCCESS.
+		 * 2. The completion of an I/O and the receipt of
+		 *    abort for that I/O by the FW crossed each other.
+		 *    The FW returned FW_EINVAL. The original I/O would have
+		 *    returned with FW_SUCCESS or any other SCSI error.
+		 * 3. The FW couldnt sent the abort out on the wire, as there
+		 *    was an I-T nexus loss (link down, remote device logged
+		 *    out etc). FW sent back an appropriate IT nexus loss status
+		 *    for the abort.
+		 * 4. FW sent an abort, but abort timed out (remote device
+		 *    didnt respond). FW replied back with
+		 *    FW_SCSI_ABORT_TIMEDOUT.
+		 * 5. FW couldnt genuinely abort the request for some reason,
+		 *    and sent us an error.
+		 *
+		 * The first 3 scenarios are treated as  succesful abort
+		 * operations by the host, while the last 2 are failed attempts
+		 * to abort. Manipulate the return value of the request
+		 * appropriately, so that host can convey these results
+		 * back to the upper layer.
+		 */
+		if ((req->wr_status == FW_SUCCESS) ||
+		    (req->wr_status == FW_EINVAL) ||
+		    csio_scsi_itnexus_loss_error(req->wr_status))
+			req->wr_status = FW_SCSI_ABORT_REQUESTED;
+
+		CSIO_DEC_STATS(scm, n_active);
+		list_del_init(&req->sm.sm_list);
+		csio_set_state(&req->sm, csio_scsis_uninit);
+		break;
+
+	case CSIO_SCSIE_DRVCLEANUP:
+		req->wr_status = FW_HOSTERROR;
+		CSIO_DEC_STATS(scm, n_active);
+		csio_set_state(&req->sm, csio_scsis_uninit);
+		break;
+
+	case CSIO_SCSIE_CLOSE:
+		/*
+		 * We can receive this event from the module
+		 * cleanup paths, if the FW forgot to reply to the ABORT WR
+		 * and left this ioreq in this state. For now, just ignore
+		 * the event. The CLOSE event is sent to this state, as
+		 * the LINK may have already gone down.
+		 */
+		break;
+
+	default:
+		csio_dbg(hw, "Unhandled event:%d sent to req:%p\n", evt, req);
+		CSIO_DB_ASSERT(0);
+	}
+}
+
+static void
+csio_scsis_closing(struct csio_ioreq *req, enum csio_scsi_ev evt)
+{
+	struct csio_hw *hw = req->lnode->hwp;
+	struct csio_scsim *scm = csio_hw_to_scsim(hw);
+
+	switch (evt) {
+	case CSIO_SCSIE_COMPLETED:
+		csio_dbg(hw,
+			 "ioreq %p recvd cmpltd (wr_status:%d) "
+			 "in closing st\n", req, req->wr_status);
+		/*
+		 * Use -ECANCELED to explicitly tell the CLOSED event that
+		 * the original I/O was returned to driver by FW.
+		 * We dont really care if the I/O was returned with success by
+		 * FW (because the CLOSE and completion of the I/O crossed each
+		 * other), or any other return value. Once we are in aborting
+		 * state, the success or failure of the I/O is unimportant to
+		 * us.
+		 */
+		req->drv_status = -ECANCELED;
+		break;
+
+	case CSIO_SCSIE_CLOSED:
+		/*
+		 * Check if original I/O WR completed before the Close
+		 * completion.
+		 */
+		if (req->drv_status != -ECANCELED) {
+			csio_fatal(hw,
+				   "Close completed before original I/O,"
+				   " req:%p\n", req);
+			CSIO_DB_ASSERT(0);
+		}
+
+		/*
+		 * Either close succeeded, or we issued close to FW at the
+		 * same time FW compelted it to us. Either way, the I/O
+		 * is closed.
+		 */
+		CSIO_DB_ASSERT((req->wr_status == FW_SUCCESS) ||
+					(req->wr_status == FW_EINVAL));
+		req->wr_status = FW_SCSI_CLOSE_REQUESTED;
+
+		CSIO_DEC_STATS(scm, n_active);
+		list_del_init(&req->sm.sm_list);
+		csio_set_state(&req->sm, csio_scsis_uninit);
+		break;
+
+	case CSIO_SCSIE_CLOSE:
+		break;
+
+	case CSIO_SCSIE_DRVCLEANUP:
+		req->wr_status = FW_HOSTERROR;
+		CSIO_DEC_STATS(scm, n_active);
+		csio_set_state(&req->sm, csio_scsis_uninit);
+		break;
+
+	default:
+		csio_dbg(hw, "Unhandled event:%d sent to req:%p\n", evt, req);
+		CSIO_DB_ASSERT(0);
+	}
+}
+
+static void
+csio_scsis_shost_cmpl_await(struct csio_ioreq *req, enum csio_scsi_ev evt)
+{
+	switch (evt) {
+	case CSIO_SCSIE_ABORT:
+	case CSIO_SCSIE_CLOSE:
+		/*
+		 * Just succeed the abort request, and hope that
+		 * the remote device unregister path will cleanup
+		 * this I/O to the upper layer within a sane
+		 * amount of time.
+		 */
+		/*
+		 * A close can come in during a LINK DOWN. The FW would have
+		 * returned us the I/O back, but not the remote device lost
+		 * FW event. In this interval, if the I/O times out at the upper
+		 * layer, a close can come in. Take the same action as abort:
+		 * return success, and hope that the remote device unregister
+		 * path will cleanup this I/O. If the FW still doesnt send
+		 * the msg, the close times out, and the upper layer resorts
+		 * to the next level of error recovery.
+		 */
+		req->drv_status = 0;
+		break;
+	case CSIO_SCSIE_DRVCLEANUP:
+		csio_set_state(&req->sm, csio_scsis_uninit);
+		break;
+	default:
+		csio_dbg(req->lnode->hwp, "Unhandled event:%d sent to req:%p\n",
+			 evt, req);
+		CSIO_DB_ASSERT(0);
+	}
+}
+
+/*
+ * csio_scsi_cmpl_handler - WR completion handler for SCSI.
+ * @hw: HW module.
+ * @wr: The completed WR from the ingress queue.
+ * @len: Length of the WR.
+ * @flb: Freelist buffer array.
+ * @priv: Private object
+ * @scsiwr: Pointer to SCSI WR.
+ *
+ * This is the WR completion handler called per completion from the
+ * ISR. It is called with lock held. It walks past the RSS and CPL message
+ * header where the actual WR is present.
+ * It then gets the status, WR handle (ioreq pointer) and the len of
+ * the WR, based on WR opcode. Only on a non-good status is the entire
+ * WR copied into the WR cache (ioreq->fw_wr).
+ * The ioreq corresponding to the WR is returned to the caller.
+ * NOTE: The SCSI queue doesnt allocate a freelist today, hence
+ * no freelist buffer is expected.
+ */
+struct csio_ioreq *
+csio_scsi_cmpl_handler(struct csio_hw *hw, void *wr, uint32_t len,
+		     struct csio_fl_dma_buf *flb, void *priv, uint8_t **scsiwr)
+{
+	struct csio_ioreq *ioreq = NULL;
+	struct cpl_fw6_msg *cpl;
+	uint8_t *tempwr;
+	uint8_t	status;
+	struct csio_scsim *scm = csio_hw_to_scsim(hw);
+
+	/* skip RSS header */
+	cpl = (struct cpl_fw6_msg *)((uintptr_t)wr + sizeof(__be64));
+
+	if (unlikely(cpl->opcode != CPL_FW6_MSG)) {
+		csio_warn(hw, "Error: Invalid CPL msg %x recvd on SCSI q\n",
+			  cpl->opcode);
+		CSIO_INC_STATS(scm, n_inval_cplop);
+		return NULL;
+	}
+
+	tempwr = (uint8_t *)(cpl->data);
+	status = csio_wr_status(tempwr);
+	*scsiwr = tempwr;
+
+	if (likely((*tempwr == FW_SCSI_READ_WR) ||
+			(*tempwr == FW_SCSI_WRITE_WR) ||
+			(*tempwr == FW_SCSI_CMD_WR))) {
+		ioreq = (struct csio_ioreq *)((uintptr_t)
+				 (((struct fw_scsi_read_wr *)tempwr)->cookie));
+		CSIO_DB_ASSERT(virt_addr_valid(ioreq));
+
+		ioreq->wr_status = status;
+
+		return ioreq;
+	}
+
+	if (*tempwr == FW_SCSI_ABRT_CLS_WR) {
+		ioreq = (struct csio_ioreq *)((uintptr_t)
+			 (((struct fw_scsi_abrt_cls_wr *)tempwr)->cookie));
+		CSIO_DB_ASSERT(virt_addr_valid(ioreq));
+
+		ioreq->wr_status = status;
+		return ioreq;
+	}
+
+	csio_warn(hw, "WR with invalid opcode in SCSI IQ: %x\n", *tempwr);
+	CSIO_INC_STATS(scm, n_inval_scsiop);
+	return NULL;
+}
+
+/*
+ * csio_scsi_cleanup_io_q - Cleanup the given queue.
+ * @scm: SCSI module.
+ * @q: Queue to be cleaned up.
+ *
+ * Called with lock held. Has to exit with lock held.
+ */
+void
+csio_scsi_cleanup_io_q(struct csio_scsim *scm, struct list_head *q)
+{
+	struct csio_hw *hw = scm->hw;
+	struct csio_ioreq *ioreq;
+	struct list_head *tmp, *next;
+	struct scsi_cmnd *scmnd;
+
+	/* Call back the completion routines of the active_q */
+	list_for_each_safe(tmp, next, q) {
+		ioreq = (struct csio_ioreq *)tmp;
+		csio_scsi_drvcleanup(ioreq);
+		list_del_init(&ioreq->sm.sm_list);
+		scmnd = csio_scsi_cmnd(ioreq);
+		spin_unlock_irq(&hw->lock);
+
+		/*
+		 * Upper layers may have cleared this command, hence this
+		 * check to avoid accessing stale references.
+		 */
+		if (scmnd != NULL)
+			ioreq->io_cbfn(hw, ioreq);
+
+		spin_lock_irq(&scm->freelist_lock);
+		csio_put_scsi_ioreq(scm, ioreq);
+		spin_unlock_irq(&scm->freelist_lock);
+
+		spin_lock_irq(&hw->lock);
+	}
+}
+
+#define CSIO_SCSI_ABORT_Q_POLL_MS		2000
+
+static void
+csio_abrt_cls(struct csio_ioreq *ioreq, struct scsi_cmnd *scmnd)
+{
+	struct csio_lnode *ln = ioreq->lnode;
+	struct csio_hw *hw = ln->hwp;
+	int ready = 0;
+	struct csio_scsim *scsim = csio_hw_to_scsim(hw);
+	int rv;
+
+	if (csio_scsi_cmnd(ioreq) != scmnd) {
+		CSIO_INC_STATS(scsim, n_abrt_race_comp);
+		return;
+	}
+
+	ready = csio_is_lnode_ready(ln);
+
+	rv = csio_do_abrt_cls(hw, ioreq, (ready ? SCSI_ABORT : SCSI_CLOSE));
+	if (rv != 0) {
+		if (ready)
+			CSIO_INC_STATS(scsim, n_abrt_busy_error);
+		else
+			CSIO_INC_STATS(scsim, n_cls_busy_error);
+	}
+}
+
+/*
+ * csio_scsi_abort_io_q - Abort all I/Os on given queue
+ * @scm: SCSI module.
+ * @q: Queue to abort.
+ * @tmo: Timeout in ms
+ *
+ * Attempt to abort all I/Os on given queue, and wait for a max
+ * of tmo milliseconds for them to complete. Returns success
+ * if all I/Os are aborted. Else returns -ETIMEDOUT.
+ * Should be entered with lock held. Exits with lock held.
+ * NOTE:
+ * Lock has to be held across the loop that aborts I/Os, since dropping the lock
+ * in between can cause the list to be corrupted. As a result, the caller
+ * of this function has to ensure that the number of I/os to be aborted
+ * is finite enough to not cause lock-held-for-too-long issues.
+ */
+static int
+csio_scsi_abort_io_q(struct csio_scsim *scm, struct list_head *q, uint32_t tmo)
+{
+	struct csio_hw *hw = scm->hw;
+	struct list_head *tmp, *next;
+	int count = DIV_ROUND_UP(tmo, CSIO_SCSI_ABORT_Q_POLL_MS);
+	struct scsi_cmnd *scmnd;
+
+	if (list_empty(q))
+		return 0;
+
+	csio_dbg(hw, "Aborting SCSI I/Os\n");
+
+	/* Now abort/close I/Os in the queue passed */
+	list_for_each_safe(tmp, next, q) {
+		scmnd = csio_scsi_cmnd((struct csio_ioreq *)tmp);
+		csio_abrt_cls((struct csio_ioreq *)tmp, scmnd);
+	}
+
+	/* Wait till all active I/Os are completed/aborted/closed */
+	while (!list_empty(q) && count--) {
+		spin_unlock_irq(&hw->lock);
+		msleep(CSIO_SCSI_ABORT_Q_POLL_MS);
+		spin_lock_irq(&hw->lock);
+	}
+
+	/* all aborts completed */
+	if (list_empty(q))
+		return 0;
+
+	return -ETIMEDOUT;
+}
+
+/*
+ * csio_scsim_cleanup_io - Cleanup all I/Os in SCSI module.
+ * @scm: SCSI module.
+ * @abort: abort required.
+ * Called with lock held, should exit with lock held.
+ * Can sleep when waiting for I/Os to complete.
+ */
+int
+csio_scsim_cleanup_io(struct csio_scsim *scm, bool abort)
+{
+	struct csio_hw *hw = scm->hw;
+	int rv = 0;
+	int count = DIV_ROUND_UP(60 * 1000, CSIO_SCSI_ABORT_Q_POLL_MS);
+
+	/* No I/Os pending */
+	if (list_empty(&scm->active_q))
+		return 0;
+
+	/* Wait until all active I/Os are completed */
+	while (!list_empty(&scm->active_q) && count--) {
+		spin_unlock_irq(&hw->lock);
+		msleep(CSIO_SCSI_ABORT_Q_POLL_MS);
+		spin_lock_irq(&hw->lock);
+	}
+
+	/* all I/Os completed */
+	if (list_empty(&scm->active_q))
+		return 0;
+
+	/* Else abort */
+	if (abort) {
+		rv = csio_scsi_abort_io_q(scm, &scm->active_q, 30000);
+		if (rv == 0)
+			return rv;
+		csio_dbg(hw, "Some I/O aborts timed out, cleaning up..\n");
+	}
+
+	csio_scsi_cleanup_io_q(scm, &scm->active_q);
+
+	CSIO_DB_ASSERT(list_empty(&scm->active_q));
+
+	return rv;
+}
+
+/*
+ * csio_scsim_cleanup_io_lnode - Cleanup all I/Os of given lnode.
+ * @scm: SCSI module.
+ * @lnode: lnode
+ *
+ * Called with lock held, should exit with lock held.
+ * Can sleep (with dropped lock) when waiting for I/Os to complete.
+ */
+int
+csio_scsim_cleanup_io_lnode(struct csio_scsim *scm, struct csio_lnode *ln)
+{
+	struct csio_hw *hw = scm->hw;
+	struct csio_scsi_level_data sld;
+	int rv;
+	int count = DIV_ROUND_UP(60 * 1000, CSIO_SCSI_ABORT_Q_POLL_MS);
+
+	csio_dbg(hw, "Gathering all SCSI I/Os on lnode %p\n", ln);
+
+	sld.level = CSIO_LEV_LNODE;
+	sld.lnode = ln;
+	INIT_LIST_HEAD(&ln->cmpl_q);
+	csio_scsi_gather_active_ios(scm, &sld, &ln->cmpl_q);
+
+	/* No I/Os pending on this lnode  */
+	if (list_empty(&ln->cmpl_q))
+		return 0;
+
+	/* Wait until all active I/Os on this lnode are completed */
+	while (!list_empty(&ln->cmpl_q) && count--) {
+		spin_unlock_irq(&hw->lock);
+		msleep(CSIO_SCSI_ABORT_Q_POLL_MS);
+		spin_lock_irq(&hw->lock);
+	}
+
+	/* all I/Os completed */
+	if (list_empty(&ln->cmpl_q))
+		return 0;
+
+	csio_dbg(hw, "Some I/Os pending on ln:%p, aborting them..\n", ln);
+
+	/* I/Os are pending, abort them */
+	rv = csio_scsi_abort_io_q(scm, &ln->cmpl_q, 30000);
+	if (rv != 0) {
+		csio_dbg(hw, "Some I/O aborts timed out, cleaning up..\n");
+		csio_scsi_cleanup_io_q(scm, &ln->cmpl_q);
+	}
+
+	CSIO_DB_ASSERT(list_empty(&ln->cmpl_q));
+
+	return rv;
+}
+
+static ssize_t
+csio_show_hw_state(struct device *dev,
+		   struct device_attribute *attr, char *buf)
+{
+	struct csio_lnode *ln = shost_priv(class_to_shost(dev));
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+	if (csio_is_hw_ready(hw))
+		return snprintf(buf, PAGE_SIZE, "ready\n");
+	else
+		return snprintf(buf, PAGE_SIZE, "not ready\n");
+}
+
+/* Device reset */
+static ssize_t
+csio_device_reset(struct device *dev,
+		   struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct csio_lnode *ln = shost_priv(class_to_shost(dev));
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+
+	if (*buf != '1')
+		return -EINVAL;
+
+	/* Delete NPIV lnodes */
+	 csio_lnodes_exit(hw, 1);
+
+	/* Block upper IOs */
+	csio_lnodes_block_request(hw);
+
+	spin_lock_irq(&hw->lock);
+	csio_hw_reset(hw);
+	spin_unlock_irq(&hw->lock);
+
+	/* Unblock upper IOs */
+	csio_lnodes_unblock_request(hw);
+	return count;
+}
+
+/* disable port */
+static ssize_t
+csio_disable_port(struct device *dev,
+		   struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct csio_lnode *ln = shost_priv(class_to_shost(dev));
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+	bool disable;
+
+	if (*buf == '1' || *buf == '0')
+		disable = (*buf == '1') ? true : false;
+	else
+		return -EINVAL;
+
+	/* Block upper IOs */
+	csio_lnodes_block_by_port(hw, ln->portid);
+
+	spin_lock_irq(&hw->lock);
+	csio_disable_lnodes(hw, ln->portid, disable);
+	spin_unlock_irq(&hw->lock);
+
+	/* Unblock upper IOs */
+	csio_lnodes_unblock_by_port(hw, ln->portid);
+	return count;
+}
+
+/* Show debug level */
+static ssize_t
+csio_show_dbg_level(struct device *dev,
+		   struct device_attribute *attr, char *buf)
+{
+	struct csio_lnode *ln = shost_priv(class_to_shost(dev));
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", ln->params.log_level);
+}
+
+/* Store debug level */
+static ssize_t
+csio_store_dbg_level(struct device *dev,
+		   struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct csio_lnode *ln = shost_priv(class_to_shost(dev));
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+	uint32_t dbg_level = 0;
+
+	if (!isdigit(buf[0]))
+		return -EINVAL;
+
+	if (sscanf(buf, "%i", &dbg_level))
+		return -EINVAL;
+
+	ln->params.log_level = dbg_level;
+	hw->params.log_level = dbg_level;
+
+	return 0;
+}
+
+static DEVICE_ATTR(hw_state, S_IRUGO, csio_show_hw_state, NULL);
+static DEVICE_ATTR(device_reset, S_IRUGO | S_IWUSR, NULL, csio_device_reset);
+static DEVICE_ATTR(disable_port, S_IRUGO | S_IWUSR, NULL, csio_disable_port);
+static DEVICE_ATTR(dbg_level, S_IRUGO | S_IWUSR, csio_show_dbg_level,
+		  csio_store_dbg_level);
+
+static struct device_attribute *csio_fcoe_lport_attrs[] = {
+	&dev_attr_hw_state,
+	&dev_attr_device_reset,
+	&dev_attr_disable_port,
+	&dev_attr_dbg_level,
+	NULL,
+};
+
+static ssize_t
+csio_show_num_reg_rnodes(struct device *dev,
+		     struct device_attribute *attr, char *buf)
+{
+	struct csio_lnode *ln = shost_priv(class_to_shost(dev));
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", ln->num_reg_rnodes);
+}
+
+static DEVICE_ATTR(num_reg_rnodes, S_IRUGO, csio_show_num_reg_rnodes, NULL);
+
+static struct device_attribute *csio_fcoe_vport_attrs[] = {
+	&dev_attr_num_reg_rnodes,
+	&dev_attr_dbg_level,
+	NULL,
+};
+
+static inline uint32_t
+csio_scsi_copy_to_sgl(struct csio_hw *hw, struct csio_ioreq *req)
+{
+	struct scsi_cmnd *scmnd  = (struct scsi_cmnd *)csio_scsi_cmnd(req);
+	struct scatterlist *sg;
+	uint32_t bytes_left;
+	uint32_t bytes_copy;
+	uint32_t buf_off = 0;
+	uint32_t start_off = 0;
+	uint32_t sg_off = 0;
+	void *sg_addr;
+	void *buf_addr;
+	struct csio_dma_buf *dma_buf;
+
+	bytes_left = scsi_bufflen(scmnd);
+	sg = scsi_sglist(scmnd);
+	dma_buf = (struct csio_dma_buf *)csio_list_next(&req->gen_list);
+
+	/* Copy data from driver buffer to SGs of SCSI CMD */
+	while (bytes_left > 0 && sg && dma_buf) {
+		if (buf_off >= dma_buf->len) {
+			buf_off = 0;
+			dma_buf = (struct csio_dma_buf *)
+					csio_list_next(dma_buf);
+			continue;
+		}
+
+		if (start_off >= sg->length) {
+			start_off -= sg->length;
+			sg = sg_next(sg);
+			continue;
+		}
+
+		buf_addr = dma_buf->vaddr + buf_off;
+		sg_off = sg->offset + start_off;
+		bytes_copy = min((dma_buf->len - buf_off),
+				sg->length - start_off);
+		bytes_copy = min((uint32_t)(PAGE_SIZE - (sg_off & ~PAGE_MASK)),
+				 bytes_copy);
+
+		sg_addr = kmap_atomic(sg_page(sg) + (sg_off >> PAGE_SHIFT));
+		if (!sg_addr) {
+			csio_err(hw, "failed to kmap sg:%p of ioreq:%p\n",
+				sg, req);
+			break;
+		}
+
+		csio_dbg(hw, "copy_to_sgl:sg_addr %p sg_off %d buf %p len %d\n",
+				sg_addr, sg_off, buf_addr, bytes_copy);
+		memcpy(sg_addr + (sg_off & ~PAGE_MASK), buf_addr, bytes_copy);
+		kunmap_atomic(sg_addr);
+
+		start_off +=  bytes_copy;
+		buf_off += bytes_copy;
+		bytes_left -= bytes_copy;
+	}
+
+	if (bytes_left > 0)
+		return DID_ERROR;
+	else
+		return DID_OK;
+}
+
+/*
+ * csio_scsi_err_handler - SCSI error handler.
+ * @hw: HW module.
+ * @req: IO request.
+ *
+ */
+static inline void
+csio_scsi_err_handler(struct csio_hw *hw, struct csio_ioreq *req)
+{
+	struct scsi_cmnd *cmnd  = (struct scsi_cmnd *)csio_scsi_cmnd(req);
+	struct csio_scsim *scm = csio_hw_to_scsim(hw);
+	struct fcp_resp_with_ext *fcp_resp;
+	struct fcp_resp_rsp_info *rsp_info;
+	struct csio_dma_buf *dma_buf;
+	uint8_t flags, scsi_status = 0;
+	uint32_t host_status = DID_OK;
+	uint32_t rsp_len = 0, sns_len = 0;
+	struct csio_rnode *rn = (struct csio_rnode *)(cmnd->device->hostdata);
+
+
+	switch (req->wr_status) {
+	case FW_HOSTERROR:
+		if (unlikely(!csio_is_hw_ready(hw)))
+			return;
+
+		host_status = DID_ERROR;
+		CSIO_INC_STATS(scm, n_hosterror);
+
+		break;
+	case FW_SCSI_RSP_ERR:
+		dma_buf = &req->dma_buf;
+		fcp_resp = (struct fcp_resp_with_ext *)dma_buf->vaddr;
+		rsp_info = (struct fcp_resp_rsp_info *)(fcp_resp + 1);
+		flags = fcp_resp->resp.fr_flags;
+		scsi_status = fcp_resp->resp.fr_status;
+
+		if (flags & FCP_RSP_LEN_VAL) {
+			rsp_len = be32_to_cpu(fcp_resp->ext.fr_rsp_len);
+			if ((rsp_len != 0 && rsp_len != 4 && rsp_len != 8) ||
+				(rsp_info->rsp_code != FCP_TMF_CMPL)) {
+				host_status = DID_ERROR;
+				goto out;
+			}
+		}
+
+		if ((flags & FCP_SNS_LEN_VAL) && fcp_resp->ext.fr_sns_len) {
+			sns_len = be32_to_cpu(fcp_resp->ext.fr_sns_len);
+			if (sns_len > SCSI_SENSE_BUFFERSIZE)
+				sns_len = SCSI_SENSE_BUFFERSIZE;
+
+			memcpy(cmnd->sense_buffer,
+			       &rsp_info->_fr_resvd[0] + rsp_len, sns_len);
+			CSIO_INC_STATS(scm, n_autosense);
+		}
+
+		scsi_set_resid(cmnd, 0);
+
+		/* Under run */
+		if (flags & FCP_RESID_UNDER) {
+			scsi_set_resid(cmnd,
+				       be32_to_cpu(fcp_resp->ext.fr_resid));
+
+			if (!(flags & FCP_SNS_LEN_VAL) &&
+			    (scsi_status == SAM_STAT_GOOD) &&
+			    ((scsi_bufflen(cmnd) - scsi_get_resid(cmnd))
+							< cmnd->underflow))
+				host_status = DID_ERROR;
+		} else if (flags & FCP_RESID_OVER)
+			host_status = DID_ERROR;
+
+		CSIO_INC_STATS(scm, n_rsperror);
+		break;
+
+	case FW_SCSI_OVER_FLOW_ERR:
+		csio_warn(hw,
+			  "Over-flow error,cmnd:0x%x expected len:0x%x"
+			  " resid:0x%x\n", cmnd->cmnd[0],
+			  scsi_bufflen(cmnd), scsi_get_resid(cmnd));
+		host_status = DID_ERROR;
+		CSIO_INC_STATS(scm, n_ovflerror);
+		break;
+
+	case FW_SCSI_UNDER_FLOW_ERR:
+		csio_warn(hw,
+			  "Under-flow error,cmnd:0x%x expected"
+			  " len:0x%x resid:0x%x lun:0x%x ssn:0x%x\n",
+			  cmnd->cmnd[0], scsi_bufflen(cmnd),
+			  scsi_get_resid(cmnd), cmnd->device->lun,
+			  rn->flowid);
+		host_status = DID_ERROR;
+		CSIO_INC_STATS(scm, n_unflerror);
+		break;
+
+	case FW_SCSI_ABORT_REQUESTED:
+	case FW_SCSI_ABORTED:
+	case FW_SCSI_CLOSE_REQUESTED:
+		csio_dbg(hw, "Req %p cmd:%p op:%x %s\n", req, cmnd,
+			     cmnd->cmnd[0],
+			    (req->wr_status == FW_SCSI_CLOSE_REQUESTED) ?
+			    "closed" : "aborted");
+		/*
+		 * csio_eh_abort_handler checks this value to
+		 * succeed or fail the abort request.
+		 */
+		host_status = DID_REQUEUE;
+		if (req->wr_status == FW_SCSI_CLOSE_REQUESTED)
+			CSIO_INC_STATS(scm, n_closed);
+		else
+			CSIO_INC_STATS(scm, n_aborted);
+		break;
+
+	case FW_SCSI_ABORT_TIMEDOUT:
+		/* FW timed out the abort itself */
+		csio_dbg(hw, "FW timed out abort req:%p cmnd:%p status:%x\n",
+			 req, cmnd, req->wr_status);
+		host_status = DID_ERROR;
+		CSIO_INC_STATS(scm, n_abrt_timedout);
+		break;
+
+	case FW_RDEV_NOT_READY:
+		/*
+		 * In firmware, a RDEV can get into this state
+		 * temporarily, before moving into dissapeared/lost
+		 * state. So, the driver should complete the request equivalent
+		 * to device-disappeared!
+		 */
+		CSIO_INC_STATS(scm, n_rdev_nr_error);
+		host_status = DID_ERROR;
+		break;
+
+	case FW_ERR_RDEV_LOST:
+		CSIO_INC_STATS(scm, n_rdev_lost_error);
+		host_status = DID_ERROR;
+		break;
+
+	case FW_ERR_RDEV_LOGO:
+		CSIO_INC_STATS(scm, n_rdev_logo_error);
+		host_status = DID_ERROR;
+		break;
+
+	case FW_ERR_RDEV_IMPL_LOGO:
+		host_status = DID_ERROR;
+		break;
+
+	case FW_ERR_LINK_DOWN:
+		CSIO_INC_STATS(scm, n_link_down_error);
+		host_status = DID_ERROR;
+		break;
+
+	case FW_FCOE_NO_XCHG:
+		CSIO_INC_STATS(scm, n_no_xchg_error);
+		host_status = DID_ERROR;
+		break;
+
+	default:
+		csio_err(hw, "Unknown SCSI FW WR status:%d req:%p cmnd:%p\n",
+			    req->wr_status, req, cmnd);
+		CSIO_DB_ASSERT(0);
+
+		CSIO_INC_STATS(scm, n_unknown_error);
+		host_status = DID_ERROR;
+		break;
+	}
+
+out:
+	if (req->nsge > 0)
+		scsi_dma_unmap(cmnd);
+
+	cmnd->result = (((host_status) << 16) | scsi_status);
+	cmnd->scsi_done(cmnd);
+
+	/* Wake up waiting threads */
+	csio_scsi_cmnd(req) = NULL;
+	complete_all(&req->cmplobj);
+}
+
+/*
+ * csio_scsi_cbfn - SCSI callback function.
+ * @hw: HW module.
+ * @req: IO request.
+ *
+ */
+static void
+csio_scsi_cbfn(struct csio_hw *hw, struct csio_ioreq *req)
+{
+	struct scsi_cmnd *cmnd  = (struct scsi_cmnd *)csio_scsi_cmnd(req);
+	uint8_t scsi_status = SAM_STAT_GOOD;
+	uint32_t host_status = DID_OK;
+
+	if (likely(req->wr_status == FW_SUCCESS)) {
+		if (req->nsge > 0) {
+			scsi_dma_unmap(cmnd);
+			if (req->dcopy)
+				host_status = csio_scsi_copy_to_sgl(hw, req);
+		}
+
+		cmnd->result = (((host_status) << 16) | scsi_status);
+		cmnd->scsi_done(cmnd);
+		csio_scsi_cmnd(req) = NULL;
+		CSIO_INC_STATS(csio_hw_to_scsim(hw), n_tot_success);
+	} else {
+		/* Error handling */
+		csio_scsi_err_handler(hw, req);
+	}
+}
+
+/**
+ * csio_queuecommand - Entry point to kickstart an I/O request.
+ * @host:	The scsi_host pointer.
+ * @cmnd:	The I/O request from ML.
+ *
+ * This routine does the following:
+ *	- Checks for HW and Rnode module readiness.
+ *	- Gets a free ioreq structure (which is already initialized
+ *	  to uninit during its allocation).
+ *	- Maps SG elements.
+ *	- Initializes ioreq members.
+ *	- Kicks off the SCSI state machine for this IO.
+ *	- Returns busy status on error.
+ */
+static int
+csio_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmnd)
+{
+	struct csio_lnode *ln = shost_priv(host);
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+	struct csio_scsim *scsim = csio_hw_to_scsim(hw);
+	struct csio_rnode *rn = (struct csio_rnode *)(cmnd->device->hostdata);
+	struct csio_ioreq *ioreq = NULL;
+	unsigned long flags;
+	int nsge = 0;
+	int rv = SCSI_MLQUEUE_HOST_BUSY, nr;
+	int retval;
+	int cpu;
+	struct csio_scsi_qset *sqset;
+	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
+
+	if (!blk_rq_cpu_valid(cmnd->request))
+		cpu = smp_processor_id();
+	else
+		cpu = cmnd->request->cpu;
+
+	sqset = &hw->sqset[ln->portid][cpu];
+
+	nr = fc_remote_port_chkready(rport);
+	if (nr) {
+		cmnd->result = nr;
+		CSIO_INC_STATS(scsim, n_rn_nr_error);
+		goto err_done;
+	}
+
+	if (unlikely(!csio_is_hw_ready(hw))) {
+		cmnd->result = (DID_REQUEUE << 16);
+		CSIO_INC_STATS(scsim, n_hw_nr_error);
+		goto err_done;
+	}
+
+	/* Get req->nsge, if there are SG elements to be mapped  */
+	nsge = scsi_dma_map(cmnd);
+	if (unlikely(nsge < 0)) {
+		CSIO_INC_STATS(scsim, n_dmamap_error);
+		goto err;
+	}
+
+	/* Do we support so many mappings? */
+	if (unlikely(nsge > scsim->max_sge)) {
+		csio_warn(hw,
+			  "More SGEs than can be supported."
+			  " SGEs: %d, Max SGEs: %d\n", nsge, scsim->max_sge);
+		CSIO_INC_STATS(scsim, n_unsupp_sge_error);
+		goto err_dma_unmap;
+	}
+
+	/* Get a free ioreq structure - SM is already set to uninit */
+	ioreq = csio_get_scsi_ioreq_lock(hw, scsim);
+	if (!ioreq) {
+		csio_err(hw, "Out of I/O request elements. Active #:%d\n",
+			 scsim->stats.n_active);
+		CSIO_INC_STATS(scsim, n_no_req_error);
+		goto err_dma_unmap;
+	}
+
+	ioreq->nsge		= nsge;
+	ioreq->lnode		= ln;
+	ioreq->rnode		= rn;
+	ioreq->iq_idx		= sqset->iq_idx;
+	ioreq->eq_idx		= sqset->eq_idx;
+	ioreq->wr_status	= 0;
+	ioreq->drv_status	= 0;
+	csio_scsi_cmnd(ioreq)	= (void *)cmnd;
+	ioreq->tmo		= 0;
+	ioreq->datadir		= cmnd->sc_data_direction;
+
+	if (cmnd->sc_data_direction == DMA_TO_DEVICE) {
+		CSIO_INC_STATS(ln, n_output_requests);
+		ln->stats.n_output_bytes += scsi_bufflen(cmnd);
+	} else if (cmnd->sc_data_direction == DMA_FROM_DEVICE) {
+		CSIO_INC_STATS(ln, n_input_requests);
+		ln->stats.n_input_bytes += scsi_bufflen(cmnd);
+	} else
+		CSIO_INC_STATS(ln, n_control_requests);
+
+	/* Set cbfn */
+	ioreq->io_cbfn = csio_scsi_cbfn;
+
+	/* Needed during abort */
+	cmnd->host_scribble = (unsigned char *)ioreq;
+	cmnd->SCp.Message = 0;
+
+	/* Kick off SCSI IO SM on the ioreq */
+	spin_lock_irqsave(&hw->lock, flags);
+	retval = csio_scsi_start_io(ioreq);
+	spin_unlock_irqrestore(&hw->lock, flags);
+
+	if (retval != 0) {
+		csio_err(hw, "ioreq: %p couldnt be started, status:%d\n",
+			 ioreq, retval);
+		CSIO_INC_STATS(scsim, n_busy_error);
+		goto err_put_req;
+	}
+
+	return 0;
+
+err_put_req:
+	csio_put_scsi_ioreq_lock(hw, scsim, ioreq);
+err_dma_unmap:
+	if (nsge > 0)
+		scsi_dma_unmap(cmnd);
+err:
+	return rv;
+
+err_done:
+	cmnd->scsi_done(cmnd);
+	return 0;
+}
+
+static int
+csio_do_abrt_cls(struct csio_hw *hw, struct csio_ioreq *ioreq, bool abort)
+{
+	int rv;
+	int cpu = smp_processor_id();
+	struct csio_lnode *ln = ioreq->lnode;
+	struct csio_scsi_qset *sqset = &hw->sqset[ln->portid][cpu];
+
+	ioreq->tmo = CSIO_SCSI_ABRT_TMO_MS;
+	/*
+	 * Use current processor queue for posting the abort/close, but retain
+	 * the ingress queue ID of the original I/O being aborted/closed - we
+	 * need the abort/close completion to be received on the same queue
+	 * as the original I/O.
+	 */
+	ioreq->eq_idx = sqset->eq_idx;
+
+	if (abort == SCSI_ABORT)
+		rv = csio_scsi_abort(ioreq);
+	else
+		rv = csio_scsi_close(ioreq);
+
+	return rv;
+}
+
+static int
+csio_eh_abort_handler(struct scsi_cmnd *cmnd)
+{
+	struct csio_ioreq *ioreq;
+	struct csio_lnode *ln = shost_priv(cmnd->device->host);
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+	struct csio_scsim *scsim = csio_hw_to_scsim(hw);
+	int ready = 0, ret;
+	unsigned long tmo = 0;
+	int rv;
+	struct csio_rnode *rn = (struct csio_rnode *)(cmnd->device->hostdata);
+
+	ret = fc_block_scsi_eh(cmnd);
+	if (ret)
+		return ret;
+
+	ioreq = (struct csio_ioreq *)cmnd->host_scribble;
+	if (!ioreq)
+		return SUCCESS;
+
+	if (!rn)
+		return FAILED;
+
+	csio_dbg(hw,
+		 "Request to abort ioreq:%p cmd:%p cdb:%08llx"
+		 " ssni:0x%x lun:%d iq:0x%x\n",
+		ioreq, cmnd, *((uint64_t *)cmnd->cmnd), rn->flowid,
+		cmnd->device->lun, csio_q_physiqid(hw, ioreq->iq_idx));
+
+	if (((struct scsi_cmnd *)csio_scsi_cmnd(ioreq)) != cmnd) {
+		CSIO_INC_STATS(scsim, n_abrt_race_comp);
+		return SUCCESS;
+	}
+
+	ready = csio_is_lnode_ready(ln);
+	tmo = CSIO_SCSI_ABRT_TMO_MS;
+
+	spin_lock_irq(&hw->lock);
+	rv = csio_do_abrt_cls(hw, ioreq, (ready ? SCSI_ABORT : SCSI_CLOSE));
+	spin_unlock_irq(&hw->lock);
+
+	if (rv != 0) {
+		if (rv == -EINVAL) {
+			/* Return success, if abort/close request issued on
+			 * already completed IO
+			 */
+			return SUCCESS;
+		}
+		if (ready)
+			CSIO_INC_STATS(scsim, n_abrt_busy_error);
+		else
+			CSIO_INC_STATS(scsim, n_cls_busy_error);
+
+		goto inval_scmnd;
+	}
+
+	/* Wait for completion */
+	init_completion(&ioreq->cmplobj);
+	wait_for_completion_timeout(&ioreq->cmplobj, msecs_to_jiffies(tmo));
+
+	/* FW didnt respond to abort within our timeout */
+	if (((struct scsi_cmnd *)csio_scsi_cmnd(ioreq)) == cmnd) {
+
+		csio_err(hw, "Abort timed out -- req: %p\n", ioreq);
+		CSIO_INC_STATS(scsim, n_abrt_timedout);
+
+inval_scmnd:
+		if (ioreq->nsge > 0)
+			scsi_dma_unmap(cmnd);
+
+		spin_lock_irq(&hw->lock);
+		csio_scsi_cmnd(ioreq) = NULL;
+		spin_unlock_irq(&hw->lock);
+
+		cmnd->result = (DID_ERROR << 16);
+		cmnd->scsi_done(cmnd);
+
+		return FAILED;
+	}
+
+	/* FW successfully aborted the request */
+	if (host_byte(cmnd->result) == DID_REQUEUE) {
+		csio_info(hw,
+			"Aborted SCSI command to (%d:%d) serial#:0x%lx\n",
+			cmnd->device->id, cmnd->device->lun,
+			cmnd->serial_number);
+		return SUCCESS;
+	} else {
+		csio_info(hw,
+			"Failed to abort SCSI command, (%d:%d) serial#:0x%lx\n",
+			cmnd->device->id, cmnd->device->lun,
+			cmnd->serial_number);
+		return FAILED;
+	}
+}
+
+/*
+ * csio_tm_cbfn - TM callback function.
+ * @hw: HW module.
+ * @req: IO request.
+ *
+ * Cache the result in 'cmnd', since ioreq will be freed soon
+ * after we return from here, and the waiting thread shouldnt trust
+ * the ioreq contents.
+ */
+static void
+csio_tm_cbfn(struct csio_hw *hw, struct csio_ioreq *req)
+{
+	struct scsi_cmnd *cmnd  = (struct scsi_cmnd *)csio_scsi_cmnd(req);
+	struct csio_dma_buf *dma_buf;
+	uint8_t flags = 0;
+	struct fcp_resp_with_ext *fcp_resp;
+	struct fcp_resp_rsp_info *rsp_info;
+
+	csio_dbg(hw, "req: %p in csio_tm_cbfn status: %d\n",
+		      req, req->wr_status);
+
+	/* Cache FW return status */
+	cmnd->SCp.Status = req->wr_status;
+
+	/* Special handling based on FCP response */
+
+	/*
+	 * FW returns us this error, if flags were set. FCP4 says
+	 * FCP_RSP_LEN_VAL in flags shall be set for TM completions.
+	 * So if a target were to set this bit, we expect that the
+	 * rsp_code is set to FCP_TMF_CMPL for a successful TM
+	 * completion. Any other rsp_code means TM operation failed.
+	 * If a target were to just ignore setting flags, we treat
+	 * the TM operation as success, and FW returns FW_SUCCESS.
+	 */
+	if (req->wr_status == FW_SCSI_RSP_ERR) {
+		dma_buf = &req->dma_buf;
+		fcp_resp = (struct fcp_resp_with_ext *)dma_buf->vaddr;
+		rsp_info = (struct fcp_resp_rsp_info *)(fcp_resp + 1);
+
+		flags = fcp_resp->resp.fr_flags;
+
+		/* Modify return status if flags indicate success */
+		if (flags & FCP_RSP_LEN_VAL)
+			if (rsp_info->rsp_code == FCP_TMF_CMPL)
+				cmnd->SCp.Status = FW_SUCCESS;
+
+		csio_dbg(hw, "TM FCP rsp code: %d\n", rsp_info->rsp_code);
+	}
+
+	/* Wake up the TM handler thread */
+	csio_scsi_cmnd(req) = NULL;
+}
+
+static int
+csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd)
+{
+	struct csio_lnode *ln = shost_priv(cmnd->device->host);
+	struct csio_hw *hw = csio_lnode_to_hw(ln);
+	struct csio_scsim *scsim = csio_hw_to_scsim(hw);
+	struct csio_rnode *rn = (struct csio_rnode *)(cmnd->device->hostdata);
+	struct csio_ioreq *ioreq = NULL;
+	struct csio_scsi_qset *sqset;
+	unsigned long flags;
+	int retval;
+	int count, ret;
+	LIST_HEAD(local_q);
+	struct csio_scsi_level_data sld;
+
+	if (!rn)
+		goto fail;
+
+	csio_dbg(hw, "Request to reset LUN:%d (ssni:0x%x tgtid:%d)\n",
+		      cmnd->device->lun, rn->flowid, rn->scsi_id);
+
+	if (!csio_is_lnode_ready(ln)) {
+		csio_err(hw,
+			 "LUN reset cannot be issued on non-ready"
+			 " local node vnpi:0x%x (LUN:%d)\n",
+			 ln->vnp_flowid, cmnd->device->lun);
+		goto fail;
+	}
+
+	/* Lnode is ready, now wait on rport node readiness */
+	ret = fc_block_scsi_eh(cmnd);
+	if (ret)
+		return ret;
+
+	/*
+	 * If we have blocked in the previous call, at this point, either the
+	 * remote node has come back online, or device loss timer has fired
+	 * and the remote node is destroyed. Allow the LUN reset only for
+	 * the former case, since LUN reset is a TMF I/O on the wire, and we
+	 * need a valid session to issue it.
+	 */
+	if (fc_remote_port_chkready(rn->rport)) {
+		csio_err(hw,
+			 "LUN reset cannot be issued on non-ready"
+			 " remote node ssni:0x%x (LUN:%d)\n",
+			 rn->flowid, cmnd->device->lun);
+		goto fail;
+	}
+
+	/* Get a free ioreq structure - SM is already set to uninit */
+	ioreq = csio_get_scsi_ioreq_lock(hw, scsim);
+
+	if (!ioreq) {
+		csio_err(hw, "Out of IO request elements. Active # :%d\n",
+			 scsim->stats.n_active);
+		goto fail;
+	}
+
+	sqset			= &hw->sqset[ln->portid][smp_processor_id()];
+	ioreq->nsge		= 0;
+	ioreq->lnode		= ln;
+	ioreq->rnode		= rn;
+	ioreq->iq_idx		= sqset->iq_idx;
+	ioreq->eq_idx		= sqset->eq_idx;
+
+	csio_scsi_cmnd(ioreq)	= cmnd;
+	cmnd->host_scribble	= (unsigned char *)ioreq;
+	cmnd->SCp.Status	= 0;
+
+	cmnd->SCp.Message	= FCP_TMF_LUN_RESET;
+	ioreq->tmo		= CSIO_SCSI_LUNRST_TMO_MS / 1000;
+
+	/*
+	 * FW times the LUN reset for ioreq->tmo, so we got to wait a little
+	 * longer (10s for now) than that to allow FW to return the timed
+	 * out command.
+	 */
+	count = DIV_ROUND_UP((ioreq->tmo + 10) * 1000, CSIO_SCSI_TM_POLL_MS);
+
+	/* Set cbfn */
+	ioreq->io_cbfn = csio_tm_cbfn;
+
+	/* Save of the ioreq info for later use */
+	sld.level = CSIO_LEV_LUN;
+	sld.lnode = ioreq->lnode;
+	sld.rnode = ioreq->rnode;
+	sld.oslun = (uint64_t)cmnd->device->lun;
+
+	spin_lock_irqsave(&hw->lock, flags);
+	/* Kick off TM SM on the ioreq */
+	retval = csio_scsi_start_tm(ioreq);
+	spin_unlock_irqrestore(&hw->lock, flags);
+
+	if (retval != 0) {
+		csio_err(hw, "Failed to issue LUN reset, req:%p, status:%d\n",
+			    ioreq, retval);
+		goto fail_ret_ioreq;
+	}
+
+	csio_dbg(hw, "Waiting max %d secs for LUN reset completion\n",
+		    count * (CSIO_SCSI_TM_POLL_MS / 1000));
+	/* Wait for completion */
+	while ((((struct scsi_cmnd *)csio_scsi_cmnd(ioreq)) == cmnd)
+								&& count--)
+		msleep(CSIO_SCSI_TM_POLL_MS);
+
+	/* LUN reset timed-out */
+	if (((struct scsi_cmnd *)csio_scsi_cmnd(ioreq)) == cmnd) {
+		csio_err(hw, "LUN reset (%d:%d) timed out\n",
+			 cmnd->device->id, cmnd->device->lun);
+
+		spin_lock_irq(&hw->lock);
+		csio_scsi_drvcleanup(ioreq);
+		list_del_init(&ioreq->sm.sm_list);
+		spin_unlock_irq(&hw->lock);
+
+		goto fail_ret_ioreq;
+	}
+
+	/* LUN reset returned, check cached status */
+	if (cmnd->SCp.Status != FW_SUCCESS) {
+		csio_err(hw, "LUN reset failed (%d:%d), status: %d\n",
+			 cmnd->device->id, cmnd->device->lun, cmnd->SCp.Status);
+		goto fail;
+	}
+
+	/* LUN reset succeeded, Start aborting affected I/Os */
+	/*
+	 * Since the host guarantees during LUN reset that there
+	 * will not be any more I/Os to that LUN, until the LUN reset
+	 * completes, we gather pending I/Os after the LUN reset.
+	 */
+	spin_lock_irq(&hw->lock);
+	csio_scsi_gather_active_ios(scsim, &sld, &local_q);
+
+	retval = csio_scsi_abort_io_q(scsim, &local_q, 30000);
+	spin_unlock_irq(&hw->lock);
+
+	/* Aborts may have timed out */
+	if (retval != 0) {
+		csio_err(hw,
+			 "Attempt to abort I/Os during LUN reset of %d"
+			 " returned %d\n", cmnd->device->lun, retval);
+		/* Return I/Os back to active_q */
+		spin_lock_irq(&hw->lock);
+		list_splice_tail_init(&local_q, &scsim->active_q);
+		spin_unlock_irq(&hw->lock);
+		goto fail;
+	}
+
+	CSIO_INC_STATS(rn, n_lun_rst);
+
+	csio_info(hw, "LUN reset occurred (%d:%d)\n",
+		  cmnd->device->id, cmnd->device->lun);
+
+	return SUCCESS;
+
+fail_ret_ioreq:
+	csio_put_scsi_ioreq_lock(hw, scsim, ioreq);
+fail:
+	CSIO_INC_STATS(rn, n_lun_rst_fail);
+	return FAILED;
+}
+
+static int
+csio_slave_alloc(struct scsi_device *sdev)
+{
+	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
+
+	if (!rport || fc_remote_port_chkready(rport))
+		return -ENXIO;
+
+	sdev->hostdata = *((struct csio_lnode **)(rport->dd_data));
+
+	return 0;
+}
+
+static int
+csio_slave_configure(struct scsi_device *sdev)
+{
+	if (sdev->tagged_supported)
+		scsi_activate_tcq(sdev, csio_lun_qdepth);
+	else
+		scsi_deactivate_tcq(sdev, csio_lun_qdepth);
+
+	return 0;
+}
+
+static void
+csio_slave_destroy(struct scsi_device *sdev)
+{
+	sdev->hostdata = NULL;
+}
+
+static int
+csio_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+	struct csio_lnode *ln = shost_priv(shost);
+	int rv = 1;
+
+	spin_lock_irq(shost->host_lock);
+	if (!ln->hwp || csio_list_deleted(&ln->sm.sm_list))
+		goto out;
+
+	rv = csio_scan_done(ln, jiffies, time, csio_max_scan_tmo * HZ,
+			    csio_delta_scan_tmo * HZ);
+out:
+	spin_unlock_irq(shost->host_lock);
+
+	return rv;
+}
+
+struct scsi_host_template csio_fcoe_shost_template = {
+	.module			= THIS_MODULE,
+	.name			= CSIO_DRV_DESC,
+	.proc_name		= KBUILD_MODNAME,
+	.queuecommand		= csio_queuecommand,
+	.eh_abort_handler	= csio_eh_abort_handler,
+	.eh_device_reset_handler = csio_eh_lun_reset_handler,
+	.slave_alloc		= csio_slave_alloc,
+	.slave_configure	= csio_slave_configure,
+	.slave_destroy		= csio_slave_destroy,
+	.scan_finished		= csio_scan_finished,
+	.this_id		= -1,
+	.sg_tablesize		= CSIO_SCSI_MAX_SGE,
+	.cmd_per_lun		= CSIO_MAX_CMD_PER_LUN,
+	.use_clustering		= ENABLE_CLUSTERING,
+	.shost_attrs		= csio_fcoe_lport_attrs,
+	.max_sectors		= CSIO_MAX_SECTOR_SIZE,
+};
+
+struct scsi_host_template csio_fcoe_shost_vport_template = {
+	.module			= THIS_MODULE,
+	.name			= CSIO_DRV_DESC,
+	.proc_name		= KBUILD_MODNAME,
+	.queuecommand		= csio_queuecommand,
+	.eh_abort_handler	= csio_eh_abort_handler,
+	.eh_device_reset_handler = csio_eh_lun_reset_handler,
+	.slave_alloc		= csio_slave_alloc,
+	.slave_configure	= csio_slave_configure,
+	.slave_destroy		= csio_slave_destroy,
+	.scan_finished		= csio_scan_finished,
+	.this_id		= -1,
+	.sg_tablesize		= CSIO_SCSI_MAX_SGE,
+	.cmd_per_lun		= CSIO_MAX_CMD_PER_LUN,
+	.use_clustering		= ENABLE_CLUSTERING,
+	.shost_attrs		= csio_fcoe_vport_attrs,
+	.max_sectors		= CSIO_MAX_SECTOR_SIZE,
+};
+
+/*
+ * csio_scsi_alloc_ddp_bufs - Allocate buffers for DDP of unaligned SGLs.
+ * @scm: SCSI Module
+ * @hw: HW device.
+ * @buf_size: buffer size
+ * @num_buf : Number of buffers.
+ *
+ * This routine allocates DMA buffers required for SCSI Data xfer, if
+ * each SGL buffer for a SCSI Read request posted by SCSI midlayer are
+ * not virtually contiguous.
+ */
+static int
+csio_scsi_alloc_ddp_bufs(struct csio_scsim *scm, struct csio_hw *hw,
+			 int buf_size, int num_buf)
+{
+	int n = 0;
+	struct list_head *tmp;
+	struct csio_dma_buf *ddp_desc = NULL;
+	uint32_t unit_size = 0;
+
+	if (!num_buf)
+		return 0;
+
+	if (!buf_size)
+		return -EINVAL;
+
+	INIT_LIST_HEAD(&scm->ddp_freelist);
+
+	/* Align buf size to page size */
+	buf_size = (buf_size + PAGE_SIZE - 1) & PAGE_MASK;
+	/* Initialize dma descriptors */
+	for (n = 0; n < num_buf; n++) {
+		/* Set unit size to request size */
+		unit_size = buf_size;
+		ddp_desc = kzalloc(sizeof(struct csio_dma_buf), GFP_KERNEL);
+		if (!ddp_desc) {
+			csio_err(hw,
+				 "Failed to allocate ddp descriptors,"
+				 " Num allocated = %d.\n",
+				 scm->stats.n_free_ddp);
+			goto no_mem;
+		}
+
+		/* Allocate Dma buffers for DDP */
+		ddp_desc->vaddr = pci_alloc_consistent(hw->pdev, unit_size,
+							&ddp_desc->paddr);
+		if (!ddp_desc->vaddr) {
+			csio_err(hw,
+				 "SCSI response DMA buffer (ddp) allocation"
+				 " failed!\n");
+			kfree(ddp_desc);
+			goto no_mem;
+		}
+
+		ddp_desc->len = unit_size;
+
+		/* Added it to scsi ddp freelist */
+		list_add_tail(&ddp_desc->list, &scm->ddp_freelist);
+		CSIO_INC_STATS(scm, n_free_ddp);
+	}
+
+	return 0;
+no_mem:
+	/* release dma descs back to freelist and free dma memory */
+	list_for_each(tmp, &scm->ddp_freelist) {
+		ddp_desc = (struct csio_dma_buf *) tmp;
+		tmp = csio_list_prev(tmp);
+		pci_free_consistent(hw->pdev, ddp_desc->len, ddp_desc->vaddr,
+				    ddp_desc->paddr);
+		list_del_init(&ddp_desc->list);
+		kfree(ddp_desc);
+	}
+	scm->stats.n_free_ddp = 0;
+
+	return -ENOMEM;
+}
+
+/*
+ * csio_scsi_free_ddp_bufs - free DDP buffers of unaligned SGLs.
+ * @scm: SCSI Module
+ * @hw: HW device.
+ *
+ * This routine frees ddp buffers.
+ */
+static void
+csio_scsi_free_ddp_bufs(struct csio_scsim *scm, struct csio_hw *hw)
+{
+	struct list_head *tmp;
+	struct csio_dma_buf *ddp_desc;
+
+	/* release dma descs back to freelist and free dma memory */
+	list_for_each(tmp, &scm->ddp_freelist) {
+		ddp_desc = (struct csio_dma_buf *) tmp;
+		tmp = csio_list_prev(tmp);
+		pci_free_consistent(hw->pdev, ddp_desc->len, ddp_desc->vaddr,
+				    ddp_desc->paddr);
+		list_del_init(&ddp_desc->list);
+		kfree(ddp_desc);
+	}
+	scm->stats.n_free_ddp = 0;
+}
+
+/**
+ * csio_scsim_init - Initialize SCSI Module
+ * @scm:	SCSI Module
+ * @hw:		HW module
+ *
+ */
+int
+csio_scsim_init(struct csio_scsim *scm, struct csio_hw *hw)
+{
+	int i;
+	struct csio_ioreq *ioreq;
+	struct csio_dma_buf *dma_buf;
+
+	INIT_LIST_HEAD(&scm->active_q);
+	scm->hw = hw;
+
+	scm->proto_cmd_len = sizeof(struct fcp_cmnd);
+	scm->proto_rsp_len = CSIO_SCSI_RSP_LEN;
+	scm->max_sge = CSIO_SCSI_MAX_SGE;
+
+	spin_lock_init(&scm->freelist_lock);
+
+	/* Pre-allocate ioreqs and initialize them */
+	INIT_LIST_HEAD(&scm->ioreq_freelist);
+	for (i = 0; i < csio_scsi_ioreqs; i++) {
+
+		ioreq = kzalloc(sizeof(struct csio_ioreq), GFP_KERNEL);
+		if (!ioreq) {
+			csio_err(hw,
+				 "I/O request element allocation failed, "
+				 " Num allocated = %d.\n",
+				 scm->stats.n_free_ioreq);
+
+			goto free_ioreq;
+		}
+
+		/* Allocate Dma buffers for Response Payload */
+		dma_buf = &ioreq->dma_buf;
+		dma_buf->vaddr = pci_pool_alloc(hw->scsi_pci_pool, GFP_KERNEL,
+						&dma_buf->paddr);
+		if (!dma_buf->vaddr) {
+			csio_err(hw,
+				 "SCSI response DMA buffer allocation"
+				 " failed!\n");
+			kfree(ioreq);
+			goto free_ioreq;
+		}
+
+		dma_buf->len = scm->proto_rsp_len;
+
+		/* Set state to uninit */
+		csio_init_state(&ioreq->sm, csio_scsis_uninit);
+		INIT_LIST_HEAD(&ioreq->gen_list);
+		init_completion(&ioreq->cmplobj);
+
+		list_add_tail(&ioreq->sm.sm_list, &scm->ioreq_freelist);
+		CSIO_INC_STATS(scm, n_free_ioreq);
+	}
+
+	if (csio_scsi_alloc_ddp_bufs(scm, hw, PAGE_SIZE, csio_ddp_descs))
+		goto free_ioreq;
+
+	return 0;
+
+free_ioreq:
+	/*
+	 * Free up existing allocations, since an error
+	 * from here means we are returning for good
+	 */
+	while (!list_empty(&scm->ioreq_freelist)) {
+		struct csio_sm *tmp;
+
+		tmp = list_first_entry(&scm->ioreq_freelist,
+				       struct csio_sm, sm_list);
+		list_del_init(&tmp->sm_list);
+		ioreq = (struct csio_ioreq *)tmp;
+
+		dma_buf = &ioreq->dma_buf;
+		pci_pool_free(hw->scsi_pci_pool, dma_buf->vaddr,
+			      dma_buf->paddr);
+
+		kfree(ioreq);
+	}
+
+	scm->stats.n_free_ioreq = 0;
+
+	return -ENOMEM;
+}
+
+/**
+ * csio_scsim_exit: Uninitialize SCSI Module
+ * @scm: SCSI Module
+ *
+ */
+void
+csio_scsim_exit(struct csio_scsim *scm)
+{
+	struct csio_ioreq *ioreq;
+	struct csio_dma_buf *dma_buf;
+
+	while (!list_empty(&scm->ioreq_freelist)) {
+		struct csio_sm *tmp;
+
+		tmp = list_first_entry(&scm->ioreq_freelist,
+				       struct csio_sm, sm_list);
+		list_del_init(&tmp->sm_list);
+		ioreq = (struct csio_ioreq *)tmp;
+
+		dma_buf = &ioreq->dma_buf;
+		pci_pool_free(scm->hw->scsi_pci_pool, dma_buf->vaddr,
+			      dma_buf->paddr);
+
+		kfree(ioreq);
+	}
+
+	scm->stats.n_free_ioreq = 0;
+
+	csio_scsi_free_ddp_bufs(scm, scm->hw);
+}
diff --git a/drivers/scsi/csiostor/csio_scsi.h b/drivers/scsi/csiostor/csio_scsi.h
new file mode 100644
index 0000000..2257c3d
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_scsi.h
@@ -0,0 +1,342 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_SCSI_H__
+#define __CSIO_SCSI_H__
+
+#include <linux/spinlock_types.h>
+#include <linux/completion.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/fc/fc_fcp.h>
+
+#include "csio_defs.h"
+#include "csio_wr.h"
+
+extern struct scsi_host_template csio_fcoe_shost_template;
+extern struct scsi_host_template csio_fcoe_shost_vport_template;
+
+extern int csio_scsi_eqsize;
+extern int csio_scsi_iqlen;
+extern int csio_scsi_ioreqs;
+extern uint32_t csio_max_scan_tmo;
+extern uint32_t csio_delta_scan_tmo;
+extern int csio_lun_qdepth;
+
+/*
+ **************************** NOTE *******************************
+ * How do we calculate MAX FCoE SCSI SGEs? Here is the math:
+ * Max Egress WR size = 512 bytes
+ * One SCSI egress WR has the following fixed no of bytes:
+ *      48 (sizeof(struct fw_scsi_write[read]_wr)) - FW WR
+ *    + 32 (sizeof(struct fc_fcp_cmnd)) - Immediate FCP_CMD
+ *    ------
+ *      80
+ *    ------
+ * That leaves us with 512 - 96 = 432 bytes for data SGE. Using
+ * struct ulptx_sgl header for the SGE consumes:
+ *	- 4 bytes for cmnd_sge.
+ *	- 12 bytes for the first SGL.
+ * That leaves us with 416 bytes for the remaining SGE pairs. Which is
+ * is 416 / 24 (size(struct ulptx_sge_pair)) = 17 SGE pairs,
+ * or 34 SGEs. Adding the first SGE fetches us 35 SGEs.
+ */
+#define CSIO_SCSI_MAX_SGE		35
+#define CSIO_SCSI_ABRT_TMO_MS		60000
+#define CSIO_SCSI_LUNRST_TMO_MS		60000
+#define CSIO_SCSI_TM_POLL_MS		2000	/* should be less than
+						 * all TM timeouts.
+						 */
+#define CSIO_SCSI_IQ_WRSZ		128
+#define CSIO_SCSI_IQSIZE		(csio_scsi_iqlen * CSIO_SCSI_IQ_WRSZ)
+
+#define	CSIO_MAX_SNS_LEN		128
+#define	CSIO_SCSI_RSP_LEN	(FCP_RESP_WITH_EXT + 4 + CSIO_MAX_SNS_LEN)
+
+/* Reference to scsi_cmnd */
+#define csio_scsi_cmnd(req)		((req)->scratch1)
+
+struct csio_scsi_stats {
+	uint64_t		n_tot_success;	/* Total number of good I/Os */
+	uint32_t		n_rn_nr_error;	/* No. of remote-node-not-
+						 * ready errors
+						 */
+	uint32_t		n_hw_nr_error;	/* No. of hw-module-not-
+						 * ready errors
+						 */
+	uint32_t		n_dmamap_error;	/* No. of DMA map erros */
+	uint32_t		n_unsupp_sge_error; /* No. of too-many-SGes
+						     * errors.
+						     */
+	uint32_t		n_no_req_error;	/* No. of Out-of-ioreqs error */
+	uint32_t		n_busy_error;	/* No. of -EBUSY errors */
+	uint32_t		n_hosterror;	/* No. of FW_HOSTERROR I/O */
+	uint32_t		n_rsperror;	/* No. of response errors */
+	uint32_t		n_autosense;	/* No. of auto sense replies */
+	uint32_t		n_ovflerror;	/* No. of overflow errors */
+	uint32_t		n_unflerror;	/* No. of underflow errors */
+	uint32_t		n_rdev_nr_error;/* No. of rdev not
+						 * ready errors
+						 */
+	uint32_t		n_rdev_lost_error;/* No. of rdev lost errors */
+	uint32_t		n_rdev_logo_error;/* No. of rdev logo errors */
+	uint32_t		n_link_down_error;/* No. of link down errors */
+	uint32_t		n_no_xchg_error; /* No. no exchange error */
+	uint32_t		n_unknown_error;/* No. of unhandled errors */
+	uint32_t		n_aborted;	/* No. of aborted I/Os */
+	uint32_t		n_abrt_timedout; /* No. of abort timedouts */
+	uint32_t		n_abrt_fail;	/* No. of abort failures */
+	uint32_t		n_abrt_dups;	/* No. of duplicate aborts */
+	uint32_t		n_abrt_race_comp; /* No. of aborts that raced
+						   * with completions.
+						   */
+	uint32_t		n_abrt_busy_error;/* No. of abort failures
+						   * due to -EBUSY.
+						   */
+	uint32_t		n_closed;	/* No. of closed I/Os */
+	uint32_t		n_cls_busy_error; /* No. of close failures
+						   * due to -EBUSY.
+						   */
+	uint32_t		n_active;	/* No. of IOs in active_q */
+	uint32_t		n_tm_active;	/* No. of TMs in active_q */
+	uint32_t		n_wcbfn;	/* No. of I/Os in worker
+						 * cbfn q
+						 */
+	uint32_t		n_free_ioreq;	/* No. of freelist entries */
+	uint32_t		n_free_ddp;	/* No. of DDP freelist */
+	uint32_t		n_unaligned;	/* No. of Unaligned SGls */
+	uint32_t		n_inval_cplop;	/* No. invalid CPL op's in IQ */
+	uint32_t		n_inval_scsiop;	/* No. invalid scsi op's in IQ*/
+};
+
+struct csio_scsim {
+	struct csio_hw		*hw;		/* Pointer to HW moduel */
+	uint8_t			max_sge;	/* Max SGE */
+	uint8_t			proto_cmd_len;	/* Proto specific SCSI
+						 * cmd length
+						 */
+	uint16_t		proto_rsp_len;	/* Proto specific SCSI
+						 * response length
+						 */
+	spinlock_t		freelist_lock;	/* Lock for ioreq freelist */
+	struct list_head	active_q;	/* Outstanding SCSI I/Os */
+	struct list_head	ioreq_freelist;	/* Free list of ioreq's */
+	struct list_head	ddp_freelist;	/* DDP descriptor freelist */
+	struct csio_scsi_stats	stats;		/* This module's statistics */
+};
+
+/* State machine defines */
+enum csio_scsi_ev {
+	CSIO_SCSIE_START_IO = 1,		/* Start a regular SCSI IO */
+	CSIO_SCSIE_START_TM,			/* Start a TM IO */
+	CSIO_SCSIE_COMPLETED,			/* IO Completed */
+	CSIO_SCSIE_ABORT,			/* Abort IO */
+	CSIO_SCSIE_ABORTED,			/* IO Aborted */
+	CSIO_SCSIE_CLOSE,			/* Close exchange */
+	CSIO_SCSIE_CLOSED,			/* Exchange closed */
+	CSIO_SCSIE_DRVCLEANUP,			/* Driver wants to manually
+						 * cleanup this I/O.
+						 */
+};
+
+enum csio_scsi_lev {
+	CSIO_LEV_ALL = 1,
+	CSIO_LEV_LNODE,
+	CSIO_LEV_RNODE,
+	CSIO_LEV_LUN,
+};
+
+struct csio_scsi_level_data {
+	enum csio_scsi_lev	level;
+	struct csio_rnode	*rnode;
+	struct csio_lnode	*lnode;
+	uint64_t		oslun;
+};
+
+static inline struct csio_ioreq *
+csio_get_scsi_ioreq(struct csio_scsim *scm)
+{
+	struct csio_sm *req;
+
+	if (likely(!list_empty(&scm->ioreq_freelist))) {
+		req = list_first_entry(&scm->ioreq_freelist,
+				       struct csio_sm, sm_list);
+		list_del_init(&req->sm_list);
+		CSIO_DEC_STATS(scm, n_free_ioreq);
+		return (struct csio_ioreq *)req;
+	} else
+		return NULL;
+}
+
+static inline void
+csio_put_scsi_ioreq(struct csio_scsim *scm, struct csio_ioreq *ioreq)
+{
+	list_add_tail(&ioreq->sm.sm_list, &scm->ioreq_freelist);
+	CSIO_INC_STATS(scm, n_free_ioreq);
+}
+
+static inline void
+csio_put_scsi_ioreq_list(struct csio_scsim *scm, struct list_head *reqlist,
+			 int n)
+{
+	list_splice_init(reqlist, &scm->ioreq_freelist);
+	scm->stats.n_free_ioreq += n;
+}
+
+static inline struct csio_dma_buf *
+csio_get_scsi_ddp(struct csio_scsim *scm)
+{
+	struct csio_dma_buf *ddp;
+
+	if (likely(!list_empty(&scm->ddp_freelist))) {
+		ddp = list_first_entry(&scm->ddp_freelist,
+				       struct csio_dma_buf, list);
+		list_del_init(&ddp->list);
+		CSIO_DEC_STATS(scm, n_free_ddp);
+		return ddp;
+	} else
+		return NULL;
+}
+
+static inline void
+csio_put_scsi_ddp(struct csio_scsim *scm, struct csio_dma_buf *ddp)
+{
+	list_add_tail(&ddp->list, &scm->ddp_freelist);
+	CSIO_INC_STATS(scm, n_free_ddp);
+}
+
+static inline void
+csio_put_scsi_ddp_list(struct csio_scsim *scm, struct list_head *reqlist,
+			 int n)
+{
+	list_splice_tail_init(reqlist, &scm->ddp_freelist);
+	scm->stats.n_free_ddp += n;
+}
+
+static inline void
+csio_scsi_completed(struct csio_ioreq *ioreq, struct list_head *cbfn_q)
+{
+	csio_post_event(&ioreq->sm, CSIO_SCSIE_COMPLETED);
+	if (csio_list_deleted(&ioreq->sm.sm_list))
+		list_add_tail(&ioreq->sm.sm_list, cbfn_q);
+}
+
+static inline void
+csio_scsi_aborted(struct csio_ioreq *ioreq, struct list_head *cbfn_q)
+{
+	csio_post_event(&ioreq->sm, CSIO_SCSIE_ABORTED);
+	list_add_tail(&ioreq->sm.sm_list, cbfn_q);
+}
+
+static inline void
+csio_scsi_closed(struct csio_ioreq *ioreq, struct list_head *cbfn_q)
+{
+	csio_post_event(&ioreq->sm, CSIO_SCSIE_CLOSED);
+	list_add_tail(&ioreq->sm.sm_list, cbfn_q);
+}
+
+static inline void
+csio_scsi_drvcleanup(struct csio_ioreq *ioreq)
+{
+	csio_post_event(&ioreq->sm, CSIO_SCSIE_DRVCLEANUP);
+}
+
+/*
+ * csio_scsi_start_io - Kick starts the IO SM.
+ * @req: io request SM.
+ *
+ * needs to be called with lock held.
+ */
+static inline int
+csio_scsi_start_io(struct csio_ioreq *ioreq)
+{
+	csio_post_event(&ioreq->sm, CSIO_SCSIE_START_IO);
+	return ioreq->drv_status;
+}
+
+/*
+ * csio_scsi_start_tm - Kicks off the Task management IO SM.
+ * @req: io request SM.
+ *
+ * needs to be called with lock held.
+ */
+static inline int
+csio_scsi_start_tm(struct csio_ioreq *ioreq)
+{
+	csio_post_event(&ioreq->sm, CSIO_SCSIE_START_TM);
+	return ioreq->drv_status;
+}
+
+/*
+ * csio_scsi_abort - Abort an IO request
+ * @req: io request SM.
+ *
+ * needs to be called with lock held.
+ */
+static inline int
+csio_scsi_abort(struct csio_ioreq *ioreq)
+{
+	csio_post_event(&ioreq->sm, CSIO_SCSIE_ABORT);
+	return ioreq->drv_status;
+}
+
+/*
+ * csio_scsi_close - Close an IO request
+ * @req: io request SM.
+ *
+ * needs to be called with lock held.
+ */
+static inline int
+csio_scsi_close(struct csio_ioreq *ioreq)
+{
+	csio_post_event(&ioreq->sm, CSIO_SCSIE_CLOSE);
+	return ioreq->drv_status;
+}
+
+void csio_scsi_cleanup_io_q(struct csio_scsim *, struct list_head *);
+int csio_scsim_cleanup_io(struct csio_scsim *, bool abort);
+int csio_scsim_cleanup_io_lnode(struct csio_scsim *,
+					  struct csio_lnode *);
+struct csio_ioreq *csio_scsi_cmpl_handler(struct csio_hw *, void *, uint32_t,
+					  struct csio_fl_dma_buf *,
+					  void *, uint8_t **);
+int csio_scsi_qconfig(struct csio_hw *);
+int csio_scsim_init(struct csio_scsim *, struct csio_hw *);
+void csio_scsim_exit(struct csio_scsim *);
+
+#endif /* __CSIO_SCSI_H__ */
diff --git a/drivers/scsi/csiostor/csio_wr.c b/drivers/scsi/csiostor/csio_wr.c
new file mode 100644
index 0000000..c32df1b
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_wr.c
@@ -0,0 +1,1632 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/compiler.h>
+#include <linux/slab.h>
+#include <asm/page.h>
+#include <linux/cache.h>
+
+#include "csio_hw.h"
+#include "csio_wr.h"
+#include "csio_mb.h"
+#include "csio_defs.h"
+
+int csio_intr_coalesce_cnt;		/* value:SGE_INGRESS_RX_THRESHOLD[0] */
+static int csio_sge_thresh_reg;		/* SGE_INGRESS_RX_THRESHOLD[0] */
+
+int csio_intr_coalesce_time = 10;	/* value:SGE_TIMER_VALUE_1 */
+static int csio_sge_timer_reg = 1;
+
+#define CSIO_SET_FLBUF_SIZE(_hw, _reg, _val)				\
+	csio_wr_reg32((_hw), (_val), SGE_FL_BUFFER_SIZE##_reg)
+
+static void
+csio_get_flbuf_size(struct csio_hw *hw, struct csio_sge *sge, uint32_t reg)
+{
+	sge->sge_fl_buf_size[reg] = csio_rd_reg32(hw, SGE_FL_BUFFER_SIZE0 +
+							reg * sizeof(uint32_t));
+}
+
+/* Free list buffer size */
+static inline uint32_t
+csio_wr_fl_bufsz(struct csio_sge *sge, struct csio_dma_buf *buf)
+{
+	return sge->sge_fl_buf_size[buf->paddr & 0xF];
+}
+
+/* Size of the egress queue status page */
+static inline uint32_t
+csio_wr_qstat_pgsz(struct csio_hw *hw)
+{
+	return (hw->wrm.sge.sge_control & EGRSTATUSPAGESIZE(1)) ?  128 : 64;
+}
+
+/* Ring freelist doorbell */
+static inline void
+csio_wr_ring_fldb(struct csio_hw *hw, struct csio_q *flq)
+{
+	/*
+	 * Ring the doorbell only when we have atleast CSIO_QCREDIT_SZ
+	 * number of bytes in the freelist queue. This translates to atleast
+	 * 8 freelist buffer pointers (since each pointer is 8 bytes).
+	 */
+	if (flq->inc_idx >= 8) {
+		csio_wr_reg32(hw, DBPRIO(1) | QID(flq->un.fl.flid) |
+			      PIDX(flq->inc_idx / 8),
+			      MYPF_REG(SGE_PF_KDOORBELL));
+		flq->inc_idx &= 7;
+	}
+}
+
+/* Write a 0 cidx increment value to enable SGE interrupts for this queue */
+static void
+csio_wr_sge_intr_enable(struct csio_hw *hw, uint16_t iqid)
+{
+	csio_wr_reg32(hw, CIDXINC(0)		|
+			  INGRESSQID(iqid)	|
+			  TIMERREG(X_TIMERREG_RESTART_COUNTER),
+			  MYPF_REG(SGE_PF_GTS));
+}
+
+/*
+ * csio_wr_fill_fl - Populate the FL buffers of a FL queue.
+ * @hw: HW module.
+ * @flq: Freelist queue.
+ *
+ * Fill up freelist buffer entries with buffers of size specified
+ * in the size register.
+ *
+ */
+static int
+csio_wr_fill_fl(struct csio_hw *hw, struct csio_q *flq)
+{
+	struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+	struct csio_sge *sge = &wrm->sge;
+	__be64 *d = (__be64 *)(flq->vstart);
+	struct csio_dma_buf *buf = &flq->un.fl.bufs[0];
+	uint64_t paddr;
+	int sreg = flq->un.fl.sreg;
+	int n = flq->credits;
+
+	while (n--) {
+		buf->len = sge->sge_fl_buf_size[sreg];
+		buf->vaddr = pci_alloc_consistent(hw->pdev, buf->len,
+						  &buf->paddr);
+		if (!buf->vaddr) {
+			csio_err(hw, "Could only fill %d buffers!\n", n + 1);
+			return -ENOMEM;
+		}
+
+		paddr = buf->paddr | (sreg & 0xF);
+
+		*d++ = cpu_to_be64(paddr);
+		buf++;
+	}
+
+	return 0;
+}
+
+/*
+ * csio_wr_update_fl -
+ * @hw: HW module.
+ * @flq: Freelist queue.
+ *
+ *
+ */
+static inline void
+csio_wr_update_fl(struct csio_hw *hw, struct csio_q *flq, uint16_t n)
+{
+
+	flq->inc_idx += n;
+	flq->pidx += n;
+	if (unlikely(flq->pidx >= flq->credits))
+		flq->pidx -= (uint16_t)flq->credits;
+
+	CSIO_INC_STATS(flq, n_flq_refill);
+}
+
+/*
+ * csio_wr_alloc_q - Allocate a WR queue and initialize it.
+ * @hw: HW module
+ * @qsize: Size of the queue in bytes
+ * @wrsize: Since of WR in this queue, if fixed.
+ * @type: Type of queue (Ingress/Egress/Freelist)
+ * @owner: Module that owns this queue.
+ * @nflb: Number of freelist buffers for FL.
+ * @sreg: What is the FL buffer size register?
+ * @iq_int_handler: Ingress queue handler in INTx mode.
+ *
+ * This function allocates and sets up a queue for the caller
+ * of size qsize, aligned at the required boundary. This is subject to
+ * be free entries being available in the queue array. If one is found,
+ * it is initialized with the allocated queue, marked as being used (owner),
+ * and a handle returned to the caller in form of the queue's index
+ * into the q_arr array.
+ * If user has indicated a freelist (by specifying nflb > 0), create
+ * another queue (with its own index into q_arr) for the freelist. Allocate
+ * memory for DMA buffer metadata (vaddr, len etc). Save off the freelist
+ * idx in the ingress queue's flq.idx. This is how a Freelist is associated
+ * with its owning ingress queue.
+ */
+int
+csio_wr_alloc_q(struct csio_hw *hw, uint32_t qsize, uint32_t wrsize,
+		uint16_t type, void *owner, uint32_t nflb, int sreg,
+		iq_handler_t iq_intx_handler)
+{
+	struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+	struct csio_q	*q, *flq;
+	int		free_idx = wrm->free_qidx;
+	int		ret_idx = free_idx;
+	uint32_t	qsz;
+	int flq_idx;
+
+	if (free_idx >= wrm->num_q) {
+		csio_err(hw, "No more free queues.\n");
+		return -1;
+	}
+
+	switch (type) {
+	case CSIO_EGRESS:
+		qsz = ALIGN(qsize, CSIO_QCREDIT_SZ) + csio_wr_qstat_pgsz(hw);
+		break;
+	case CSIO_INGRESS:
+		switch (wrsize) {
+		case 16:
+		case 32:
+		case 64:
+		case 128:
+			break;
+		default:
+			csio_err(hw, "Invalid Ingress queue WR size:%d\n",
+				    wrsize);
+			return -1;
+		}
+
+		/*
+		 * Number of elements must be a multiple of 16
+		 * So this includes status page size
+		 */
+		qsz = ALIGN(qsize/wrsize, 16) * wrsize;
+
+		break;
+	case CSIO_FREELIST:
+		qsz = ALIGN(qsize/wrsize, 8) * wrsize + csio_wr_qstat_pgsz(hw);
+		break;
+	default:
+		csio_err(hw, "Invalid queue type: 0x%x\n", type);
+		return -1;
+	}
+
+	q = wrm->q_arr[free_idx];
+
+	q->vstart = pci_alloc_consistent(hw->pdev, qsz, &q->pstart);
+	if (!q->vstart) {
+		csio_err(hw,
+			 "Failed to allocate DMA memory for "
+			 "queue at id: %d size: %d\n", free_idx, qsize);
+		return -1;
+	}
+
+	/*
+	 * We need to zero out the contents, importantly for ingress,
+	 * since we start with a generatiom bit of 1 for ingress.
+	 */
+	memset(q->vstart, 0, qsz);
+
+	q->type		= type;
+	q->owner	= owner;
+	q->pidx		= q->cidx = q->inc_idx = 0;
+	q->size		= qsz;
+	q->wr_sz	= wrsize;	/* If using fixed size WRs */
+
+	wrm->free_qidx++;
+
+	if (type == CSIO_INGRESS) {
+		/* Since queue area is set to zero */
+		q->un.iq.genbit	= 1;
+
+		/*
+		 * Ingress queue status page size is always the size of
+		 * the ingress queue entry.
+		 */
+		q->credits	= (qsz - q->wr_sz) / q->wr_sz;
+		q->vwrap	= (void *)((uintptr_t)(q->vstart) + qsz
+							- q->wr_sz);
+
+		/* Allocate memory for FL if requested */
+		if (nflb > 0) {
+			flq_idx = csio_wr_alloc_q(hw, nflb * sizeof(__be64),
+						  sizeof(__be64), CSIO_FREELIST,
+						  owner, 0, sreg, NULL);
+			if (flq_idx == -1) {
+				csio_err(hw,
+					 "Failed to allocate FL queue"
+					 " for IQ idx:%d\n", free_idx);
+				return -1;
+			}
+
+			/* Associate the new FL with the Ingress quue */
+			q->un.iq.flq_idx = flq_idx;
+
+			flq = wrm->q_arr[q->un.iq.flq_idx];
+			flq->un.fl.bufs = kzalloc(flq->credits *
+						  sizeof(struct csio_dma_buf),
+						  GFP_KERNEL);
+			if (!flq->un.fl.bufs) {
+				csio_err(hw,
+					 "Failed to allocate FL queue bufs"
+					 " for IQ idx:%d\n", free_idx);
+				return -1;
+			}
+
+			flq->un.fl.packen = 0;
+			flq->un.fl.offset = 0;
+			flq->un.fl.sreg = sreg;
+
+			/* Fill up the free list buffers */
+			if (csio_wr_fill_fl(hw, flq))
+				return -1;
+
+			/*
+			 * Make sure in a FLQ, atleast 1 credit (8 FL buffers)
+			 * remains unpopulated,otherwise HW thinks
+			 * FLQ is empty.
+			 */
+			flq->pidx = flq->inc_idx = flq->credits - 8;
+		} else {
+			q->un.iq.flq_idx = -1;
+		}
+
+		/* Associate the IQ INTx handler. */
+		q->un.iq.iq_intx_handler = iq_intx_handler;
+
+		csio_q_iqid(hw, ret_idx) = CSIO_MAX_QID;
+
+	} else if (type == CSIO_EGRESS) {
+		q->credits = (qsz - csio_wr_qstat_pgsz(hw)) / CSIO_QCREDIT_SZ;
+		q->vwrap   = (void *)((uintptr_t)(q->vstart) + qsz
+						- csio_wr_qstat_pgsz(hw));
+		csio_q_eqid(hw, ret_idx) = CSIO_MAX_QID;
+	} else { /* Freelist */
+		q->credits = (qsz - csio_wr_qstat_pgsz(hw)) / sizeof(__be64);
+		q->vwrap   = (void *)((uintptr_t)(q->vstart) + qsz
+						- csio_wr_qstat_pgsz(hw));
+		csio_q_flid(hw, ret_idx) = CSIO_MAX_QID;
+	}
+
+	return ret_idx;
+}
+
+/*
+ * csio_wr_iq_create_rsp - Response handler for IQ creation.
+ * @hw: The HW module.
+ * @mbp: Mailbox.
+ * @iq_idx: Ingress queue that got created.
+ *
+ * Handle FW_IQ_CMD mailbox completion. Save off the assigned IQ/FL ids.
+ */
+static int
+csio_wr_iq_create_rsp(struct csio_hw *hw, struct csio_mb *mbp, int iq_idx)
+{
+	struct csio_iq_params iqp;
+	enum fw_retval retval;
+	uint32_t iq_id;
+	int flq_idx;
+
+	memset(&iqp, 0, sizeof(struct csio_iq_params));
+
+	csio_mb_iq_alloc_write_rsp(hw, mbp, &retval, &iqp);
+
+	if (retval != FW_SUCCESS) {
+		csio_err(hw, "IQ cmd returned 0x%x!\n", retval);
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	csio_q_iqid(hw, iq_idx)		= iqp.iqid;
+	csio_q_physiqid(hw, iq_idx)	= iqp.physiqid;
+	csio_q_pidx(hw, iq_idx)		= csio_q_cidx(hw, iq_idx) = 0;
+	csio_q_inc_idx(hw, iq_idx)	= 0;
+
+	/* Actual iq-id. */
+	iq_id = iqp.iqid - hw->wrm.fw_iq_start;
+
+	/* Set the iq-id to iq map table. */
+	if (iq_id >= CSIO_MAX_IQ) {
+		csio_err(hw,
+			 "Exceeding MAX_IQ(%d) supported!"
+			 " iqid:%d rel_iqid:%d FW iq_start:%d\n",
+			 CSIO_MAX_IQ, iq_id, iqp.iqid, hw->wrm.fw_iq_start);
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+	csio_q_set_intr_map(hw, iq_idx, iq_id);
+
+	/*
+	 * During FW_IQ_CMD, FW sets interrupt_sent bit to 1 in the SGE
+	 * ingress context of this queue. This will block interrupts to
+	 * this queue until the next GTS write. Therefore, we do a
+	 * 0-cidx increment GTS write for this queue just to clear the
+	 * interrupt_sent bit. This will re-enable interrupts to this
+	 * queue.
+	 */
+	csio_wr_sge_intr_enable(hw, iqp.physiqid);
+
+	flq_idx = csio_q_iq_flq_idx(hw, iq_idx);
+	if (flq_idx != -1) {
+		struct csio_q *flq = hw->wrm.q_arr[flq_idx];
+
+		csio_q_flid(hw, flq_idx) = iqp.fl0id;
+		csio_q_cidx(hw, flq_idx) = 0;
+		csio_q_pidx(hw, flq_idx)    = csio_q_credits(hw, flq_idx) - 8;
+		csio_q_inc_idx(hw, flq_idx) = csio_q_credits(hw, flq_idx) - 8;
+
+		/* Now update SGE about the buffers allocated during init */
+		csio_wr_ring_fldb(hw, flq);
+	}
+
+	mempool_free(mbp, hw->mb_mempool);
+
+	return 0;
+}
+
+/*
+ * csio_wr_iq_create - Configure an Ingress queue with FW.
+ * @hw: The HW module.
+ * @priv: Private data object.
+ * @iq_idx: Ingress queue index in the WR module.
+ * @vec: MSIX vector.
+ * @portid: PCIE Channel to be associated with this queue.
+ * @async: Is this a FW asynchronous message handling queue?
+ * @cbfn: Completion callback.
+ *
+ * This API configures an ingress queue with FW by issuing a FW_IQ_CMD mailbox
+ * with alloc/write bits set.
+ */
+int
+csio_wr_iq_create(struct csio_hw *hw, void *priv, int iq_idx,
+		  uint32_t vec, uint8_t portid, bool async,
+		  void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct csio_mb  *mbp;
+	struct csio_iq_params iqp;
+	int flq_idx;
+
+	memset(&iqp, 0, sizeof(struct csio_iq_params));
+	csio_q_portid(hw, iq_idx) = portid;
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		csio_err(hw, "IQ command out of memory!\n");
+		return -ENOMEM;
+	}
+
+	switch (hw->intr_mode) {
+	case CSIO_IM_INTX:
+	case CSIO_IM_MSI:
+		/* For interrupt forwarding queue only */
+		if (hw->intr_iq_idx == iq_idx)
+			iqp.iqandst	= X_INTERRUPTDESTINATION_PCIE;
+		else
+			iqp.iqandst	= X_INTERRUPTDESTINATION_IQ;
+		iqp.iqandstindex	=
+			csio_q_physiqid(hw, hw->intr_iq_idx);
+		break;
+	case CSIO_IM_MSIX:
+		iqp.iqandst		= X_INTERRUPTDESTINATION_PCIE;
+		iqp.iqandstindex	= (uint16_t)vec;
+		break;
+	case CSIO_IM_NONE:
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	/* Pass in the ingress queue cmd parameters */
+	iqp.pfn			= hw->pfn;
+	iqp.vfn			= 0;
+	iqp.iq_start		= 1;
+	iqp.viid		= 0;
+	iqp.type		= FW_IQ_TYPE_FL_INT_CAP;
+	iqp.iqasynch		= async;
+	if (csio_intr_coalesce_cnt)
+		iqp.iqanus	= X_UPDATESCHEDULING_COUNTER_OPTTIMER;
+	else
+		iqp.iqanus	= X_UPDATESCHEDULING_TIMER;
+	iqp.iqanud		= X_UPDATEDELIVERY_INTERRUPT;
+	iqp.iqpciech		= portid;
+	iqp.iqintcntthresh	= (uint8_t)csio_sge_thresh_reg;
+
+	switch (csio_q_wr_sz(hw, iq_idx)) {
+	case 16:
+		iqp.iqesize = 0; break;
+	case 32:
+		iqp.iqesize = 1; break;
+	case 64:
+		iqp.iqesize = 2; break;
+	case 128:
+		iqp.iqesize = 3; break;
+	}
+
+	iqp.iqsize		= csio_q_size(hw, iq_idx) /
+						csio_q_wr_sz(hw, iq_idx);
+	iqp.iqaddr		= csio_q_pstart(hw, iq_idx);
+
+	flq_idx = csio_q_iq_flq_idx(hw, iq_idx);
+	if (flq_idx != -1) {
+		struct csio_q *flq = hw->wrm.q_arr[flq_idx];
+
+		iqp.fl0paden	= 1;
+		iqp.fl0packen	= flq->un.fl.packen ? 1 : 0;
+		iqp.fl0fbmin	= X_FETCHBURSTMIN_64B;
+		iqp.fl0fbmax	= X_FETCHBURSTMAX_512B;
+		iqp.fl0size	= csio_q_size(hw, flq_idx) / CSIO_QCREDIT_SZ;
+		iqp.fl0addr	= csio_q_pstart(hw, flq_idx);
+	}
+
+	csio_mb_iq_alloc_write(hw, mbp, priv, CSIO_MB_DEFAULT_TMO, &iqp, cbfn);
+
+	if (csio_mb_issue(hw, mbp)) {
+		csio_err(hw, "Issue of IQ cmd failed!\n");
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	if (cbfn != NULL)
+		return 0;
+
+	return csio_wr_iq_create_rsp(hw, mbp, iq_idx);
+}
+
+/*
+ * csio_wr_eq_create_rsp - Response handler for EQ creation.
+ * @hw: The HW module.
+ * @mbp: Mailbox.
+ * @eq_idx: Egress queue that got created.
+ *
+ * Handle FW_EQ_OFLD_CMD mailbox completion. Save off the assigned EQ ids.
+ */
+static int
+csio_wr_eq_cfg_rsp(struct csio_hw *hw, struct csio_mb *mbp, int eq_idx)
+{
+	struct csio_eq_params eqp;
+	enum fw_retval retval;
+
+	memset(&eqp, 0, sizeof(struct csio_eq_params));
+
+	csio_mb_eq_ofld_alloc_write_rsp(hw, mbp, &retval, &eqp);
+
+	if (retval != FW_SUCCESS) {
+		csio_err(hw, "EQ OFLD cmd returned 0x%x!\n", retval);
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	csio_q_eqid(hw, eq_idx)	= (uint16_t)eqp.eqid;
+	csio_q_physeqid(hw, eq_idx) = (uint16_t)eqp.physeqid;
+	csio_q_pidx(hw, eq_idx)	= csio_q_cidx(hw, eq_idx) = 0;
+	csio_q_inc_idx(hw, eq_idx) = 0;
+
+	mempool_free(mbp, hw->mb_mempool);
+
+	return 0;
+}
+
+/*
+ * csio_wr_eq_create - Configure an Egress queue with FW.
+ * @hw: HW module.
+ * @priv: Private data.
+ * @eq_idx: Egress queue index in the WR module.
+ * @iq_idx: Associated ingress queue index.
+ * @cbfn: Completion callback.
+ *
+ * This API configures a offload egress queue with FW by issuing a
+ * FW_EQ_OFLD_CMD  (with alloc + write ) mailbox.
+ */
+int
+csio_wr_eq_create(struct csio_hw *hw, void *priv, int eq_idx,
+		  int iq_idx, uint8_t portid,
+		  void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	struct csio_mb  *mbp;
+	struct csio_eq_params eqp;
+
+	memset(&eqp, 0, sizeof(struct csio_eq_params));
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp) {
+		csio_err(hw, "EQ command out of memory!\n");
+		return -ENOMEM;
+	}
+
+	eqp.pfn			= hw->pfn;
+	eqp.vfn			= 0;
+	eqp.eqstart		= 1;
+	eqp.hostfcmode		= X_HOSTFCMODE_STATUS_PAGE;
+	eqp.iqid		= csio_q_iqid(hw, iq_idx);
+	eqp.fbmin		= X_FETCHBURSTMIN_64B;
+	eqp.fbmax		= X_FETCHBURSTMAX_512B;
+	eqp.cidxfthresh		= 0;
+	eqp.pciechn		= portid;
+	eqp.eqsize		= csio_q_size(hw, eq_idx) / CSIO_QCREDIT_SZ;
+	eqp.eqaddr		= csio_q_pstart(hw, eq_idx);
+
+	csio_mb_eq_ofld_alloc_write(hw, mbp, priv, CSIO_MB_DEFAULT_TMO,
+				    &eqp, cbfn);
+
+	if (csio_mb_issue(hw, mbp)) {
+		csio_err(hw, "Issue of EQ OFLD cmd failed!\n");
+		mempool_free(mbp, hw->mb_mempool);
+		return -EINVAL;
+	}
+
+	if (cbfn != NULL)
+		return 0;
+
+	return csio_wr_eq_cfg_rsp(hw, mbp, eq_idx);
+}
+
+/*
+ * csio_wr_iq_destroy_rsp - Response handler for IQ removal.
+ * @hw: The HW module.
+ * @mbp: Mailbox.
+ * @iq_idx: Ingress queue that was freed.
+ *
+ * Handle FW_IQ_CMD (free) mailbox completion.
+ */
+static int
+csio_wr_iq_destroy_rsp(struct csio_hw *hw, struct csio_mb *mbp, int iq_idx)
+{
+	enum fw_retval retval = csio_mb_fw_retval(mbp);
+	int rv = 0;
+
+	if (retval != FW_SUCCESS)
+		rv = -EINVAL;
+
+	mempool_free(mbp, hw->mb_mempool);
+
+	return rv;
+}
+
+/*
+ * csio_wr_iq_destroy - Free an ingress queue.
+ * @hw: The HW module.
+ * @priv: Private data object.
+ * @iq_idx: Ingress queue index to destroy
+ * @cbfn: Completion callback.
+ *
+ * This API frees an ingress queue by issuing the FW_IQ_CMD
+ * with the free bit set.
+ */
+static int
+csio_wr_iq_destroy(struct csio_hw *hw, void *priv, int iq_idx,
+		   void (*cbfn)(struct csio_hw *, struct csio_mb *))
+{
+	int rv = 0;
+	struct csio_mb  *mbp;
+	struct csio_iq_params iqp;
+	int flq_idx;
+
+	memset(&iqp, 0, sizeof(struct csio_iq_params));
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp)
+		return -ENOMEM;
+
+	iqp.pfn		= hw->pfn;
+	iqp.vfn		= 0;
+	iqp.iqid	= csio_q_iqid(hw, iq_idx);
+	iqp.type	= FW_IQ_TYPE_FL_INT_CAP;
+
+	flq_idx = csio_q_iq_flq_idx(hw, iq_idx);
+	if (flq_idx != -1)
+		iqp.fl0id = csio_q_flid(hw, flq_idx);
+	else
+		iqp.fl0id = 0xFFFF;
+
+	iqp.fl1id = 0xFFFF;
+
+	csio_mb_iq_free(hw, mbp, priv, CSIO_MB_DEFAULT_TMO, &iqp, cbfn);
+
+	rv = csio_mb_issue(hw, mbp);
+	if (rv != 0) {
+		mempool_free(mbp, hw->mb_mempool);
+		return rv;
+	}
+
+	if (cbfn != NULL)
+		return 0;
+
+	return csio_wr_iq_destroy_rsp(hw, mbp, iq_idx);
+}
+
+/*
+ * csio_wr_eq_destroy_rsp - Response handler for OFLD EQ creation.
+ * @hw: The HW module.
+ * @mbp: Mailbox.
+ * @eq_idx: Egress queue that was freed.
+ *
+ * Handle FW_OFLD_EQ_CMD (free) mailbox completion.
+ */
+static int
+csio_wr_eq_destroy_rsp(struct csio_hw *hw, struct csio_mb *mbp, int eq_idx)
+{
+	enum fw_retval retval = csio_mb_fw_retval(mbp);
+	int rv = 0;
+
+	if (retval != FW_SUCCESS)
+		rv = -EINVAL;
+
+	mempool_free(mbp, hw->mb_mempool);
+
+	return rv;
+}
+
+/*
+ * csio_wr_eq_destroy - Free an Egress queue.
+ * @hw: The HW module.
+ * @priv: Private data object.
+ * @eq_idx: Egress queue index to destroy
+ * @cbfn: Completion callback.
+ *
+ * This API frees an Egress queue by issuing the FW_EQ_OFLD_CMD
+ * with the free bit set.
+ */
+static int
+csio_wr_eq_destroy(struct csio_hw *hw, void *priv, int eq_idx,
+		   void (*cbfn) (struct csio_hw *, struct csio_mb *))
+{
+	int rv = 0;
+	struct csio_mb  *mbp;
+	struct csio_eq_params eqp;
+
+	memset(&eqp, 0, sizeof(struct csio_eq_params));
+
+	mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+	if (!mbp)
+		return -ENOMEM;
+
+	eqp.pfn		= hw->pfn;
+	eqp.vfn		= 0;
+	eqp.eqid	= csio_q_eqid(hw, eq_idx);
+
+	csio_mb_eq_ofld_free(hw, mbp, priv, CSIO_MB_DEFAULT_TMO, &eqp, cbfn);
+
+	rv = csio_mb_issue(hw, mbp);
+	if (rv != 0) {
+		mempool_free(mbp, hw->mb_mempool);
+		return rv;
+	}
+
+	if (cbfn != NULL)
+		return 0;
+
+	return csio_wr_eq_destroy_rsp(hw, mbp, eq_idx);
+}
+
+/*
+ * csio_wr_cleanup_eq_stpg - Cleanup Egress queue status page
+ * @hw: HW module
+ * @qidx: Egress queue index
+ *
+ * Cleanup the Egress queue status page.
+ */
+static void
+csio_wr_cleanup_eq_stpg(struct csio_hw *hw, int qidx)
+{
+	struct csio_q	*q = csio_hw_to_wrm(hw)->q_arr[qidx];
+	struct csio_qstatus_page *stp = (struct csio_qstatus_page *)q->vwrap;
+
+	memset(stp, 0, sizeof(*stp));
+}
+
+/*
+ * csio_wr_cleanup_iq_ftr - Cleanup Footer entries in IQ
+ * @hw: HW module
+ * @qidx: Ingress queue index
+ *
+ * Cleanup the footer entries in the given ingress queue,
+ * set to 1 the internal copy of genbit.
+ */
+static void
+csio_wr_cleanup_iq_ftr(struct csio_hw *hw, int qidx)
+{
+	struct csio_wrm *wrm	= csio_hw_to_wrm(hw);
+	struct csio_q	*q	= wrm->q_arr[qidx];
+	void *wr;
+	struct csio_iqwr_footer *ftr;
+	uint32_t i = 0;
+
+	/* set to 1 since we are just about zero out genbit */
+	q->un.iq.genbit = 1;
+
+	for (i = 0; i < q->credits; i++) {
+		/* Get the WR */
+		wr = (void *)((uintptr_t)q->vstart +
+					   (i * q->wr_sz));
+		/* Get the footer */
+		ftr = (struct csio_iqwr_footer *)((uintptr_t)wr +
+					  (q->wr_sz - sizeof(*ftr)));
+		/* Zero out footer */
+		memset(ftr, 0, sizeof(*ftr));
+	}
+}
+
+int
+csio_wr_destroy_queues(struct csio_hw *hw, bool cmd)
+{
+	int i, flq_idx;
+	struct csio_q *q;
+	struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+	int rv;
+
+	for (i = 0; i < wrm->free_qidx; i++) {
+		q = wrm->q_arr[i];
+
+		switch (q->type) {
+		case CSIO_EGRESS:
+			if (csio_q_eqid(hw, i) != CSIO_MAX_QID) {
+				csio_wr_cleanup_eq_stpg(hw, i);
+				if (!cmd) {
+					csio_q_eqid(hw, i) = CSIO_MAX_QID;
+					continue;
+				}
+
+				rv = csio_wr_eq_destroy(hw, NULL, i, NULL);
+				if ((rv == -EBUSY) || (rv == -ETIMEDOUT))
+					cmd = false;
+
+				csio_q_eqid(hw, i) = CSIO_MAX_QID;
+			}
+		case CSIO_INGRESS:
+			if (csio_q_iqid(hw, i) != CSIO_MAX_QID) {
+				csio_wr_cleanup_iq_ftr(hw, i);
+				if (!cmd) {
+					csio_q_iqid(hw, i) = CSIO_MAX_QID;
+					flq_idx = csio_q_iq_flq_idx(hw, i);
+					if (flq_idx != -1)
+						csio_q_flid(hw, flq_idx) =
+								CSIO_MAX_QID;
+					continue;
+				}
+
+				rv = csio_wr_iq_destroy(hw, NULL, i, NULL);
+				if ((rv == -EBUSY) || (rv == -ETIMEDOUT))
+					cmd = false;
+
+				csio_q_iqid(hw, i) = CSIO_MAX_QID;
+				flq_idx = csio_q_iq_flq_idx(hw, i);
+				if (flq_idx != -1)
+					csio_q_flid(hw, flq_idx) = CSIO_MAX_QID;
+			}
+		default:
+			break;
+		}
+	}
+
+	hw->flags &= ~CSIO_HWF_Q_FW_ALLOCED;
+
+	return 0;
+}
+
+/*
+ * csio_wr_get - Get requested size of WR entry/entries from queue.
+ * @hw: HW module.
+ * @qidx: Index of queue.
+ * @size: Cumulative size of Work request(s).
+ * @wrp: Work request pair.
+ *
+ * If requested credits are available, return the start address of the
+ * work request in the work request pair. Set pidx accordingly and
+ * return.
+ *
+ * NOTE about WR pair:
+ * ==================
+ * A WR can start towards the end of a queue, and then continue at the
+ * beginning, since the queue is considered to be circular. This will
+ * require a pair of address/size to be passed back to the caller -
+ * hence Work request pair format.
+ */
+int
+csio_wr_get(struct csio_hw *hw, int qidx, uint32_t size,
+	    struct csio_wr_pair *wrp)
+{
+	struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+	struct csio_q *q = wrm->q_arr[qidx];
+	void *cwr = (void *)((uintptr_t)(q->vstart) +
+						(q->pidx * CSIO_QCREDIT_SZ));
+	struct csio_qstatus_page *stp = (struct csio_qstatus_page *)q->vwrap;
+	uint16_t cidx = q->cidx = ntohs(stp->cidx);
+	uint16_t pidx = q->pidx;
+	uint32_t req_sz	= ALIGN(size, CSIO_QCREDIT_SZ);
+	int req_credits	= req_sz / CSIO_QCREDIT_SZ;
+	int credits;
+
+	CSIO_DB_ASSERT(q->owner != NULL);
+	CSIO_DB_ASSERT((qidx >= 0) && (qidx < wrm->free_qidx));
+	CSIO_DB_ASSERT(cidx <= q->credits);
+
+	/* Calculate credits */
+	if (pidx > cidx) {
+		credits = q->credits - (pidx - cidx) - 1;
+	} else if (cidx > pidx) {
+		credits = cidx - pidx - 1;
+	} else {
+		/* cidx == pidx, empty queue */
+		credits = q->credits;
+		CSIO_INC_STATS(q, n_qempty);
+	}
+
+	/*
+	 * Check if we have enough credits.
+	 * credits = 1 implies queue is full.
+	 */
+	if (!credits || (req_credits > credits)) {
+		CSIO_INC_STATS(q, n_qfull);
+		return -EBUSY;
+	}
+
+	/*
+	 * If we are here, we have enough credits to satisfy the
+	 * request. Check if we are near the end of q, and if WR spills over.
+	 * If it does, use the first addr/size to cover the queue until
+	 * the end. Fit the remainder portion of the request at the top
+	 * of queue and return it in the second addr/len. Set pidx
+	 * accordingly.
+	 */
+	if (unlikely(((uintptr_t)cwr + req_sz) > (uintptr_t)(q->vwrap))) {
+		wrp->addr1 = cwr;
+		wrp->size1 = (uint32_t)((uintptr_t)q->vwrap - (uintptr_t)cwr);
+		wrp->addr2 = q->vstart;
+		wrp->size2 = req_sz - wrp->size1;
+		q->pidx	= (uint16_t)(ALIGN(wrp->size2, CSIO_QCREDIT_SZ) /
+							CSIO_QCREDIT_SZ);
+		CSIO_INC_STATS(q, n_qwrap);
+		CSIO_INC_STATS(q, n_eq_wr_split);
+	} else {
+		wrp->addr1 = cwr;
+		wrp->size1 = req_sz;
+		wrp->addr2 = NULL;
+		wrp->size2 = 0;
+		q->pidx	+= (uint16_t)req_credits;
+
+		/* We are the end of queue, roll back pidx to top of queue */
+		if (unlikely(q->pidx == q->credits)) {
+			q->pidx = 0;
+			CSIO_INC_STATS(q, n_qwrap);
+		}
+	}
+
+	q->inc_idx = (uint16_t)req_credits;
+
+	CSIO_INC_STATS(q, n_tot_reqs);
+
+	return 0;
+}
+
+/*
+ * csio_wr_copy_to_wrp - Copies given data into WR.
+ * @data_buf - Data buffer
+ * @wrp - Work request pair.
+ * @wr_off - Work request offset.
+ * @data_len - Data length.
+ *
+ * Copies the given data in Work Request. Work request pair(wrp) specifies
+ * address information of Work request.
+ * Returns: none
+ */
+void
+csio_wr_copy_to_wrp(void *data_buf, struct csio_wr_pair *wrp,
+		   uint32_t wr_off, uint32_t data_len)
+{
+	uint32_t nbytes;
+
+	/* Number of space available in buffer addr1 of WRP */
+	nbytes = ((wrp->size1 - wr_off) >= data_len) ?
+					data_len : (wrp->size1 - wr_off);
+
+	memcpy((uint8_t *) wrp->addr1 + wr_off, data_buf, nbytes);
+	data_len -= nbytes;
+
+	/* Write the remaining data from the begining of circular buffer */
+	if (data_len) {
+		CSIO_DB_ASSERT(data_len <= wrp->size2);
+		CSIO_DB_ASSERT(wrp->addr2 != NULL);
+		memcpy(wrp->addr2, (uint8_t *) data_buf + nbytes, data_len);
+	}
+}
+
+/*
+ * csio_wr_issue - Notify chip of Work request.
+ * @hw: HW module.
+ * @qidx: Index of queue.
+ * @prio: 0: Low priority, 1: High priority
+ *
+ * Rings the SGE Doorbell by writing the current producer index of the passed
+ * in queue into the register.
+ *
+ */
+int
+csio_wr_issue(struct csio_hw *hw, int qidx, bool prio)
+{
+	struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+	struct csio_q *q = wrm->q_arr[qidx];
+
+	CSIO_DB_ASSERT((qidx >= 0) && (qidx < wrm->free_qidx));
+
+	wmb();
+	/* Ring SGE Doorbell writing q->pidx into it */
+	csio_wr_reg32(hw, DBPRIO(prio) | QID(q->un.eq.physeqid) |
+		      PIDX(q->inc_idx), MYPF_REG(SGE_PF_KDOORBELL));
+	q->inc_idx = 0;
+
+	return 0;
+}
+
+static inline uint32_t
+csio_wr_avail_qcredits(struct csio_q *q)
+{
+	if (q->pidx > q->cidx)
+		return q->pidx - q->cidx;
+	else if (q->cidx > q->pidx)
+		return q->credits - (q->cidx - q->pidx);
+	else
+		return 0;	/* cidx == pidx, empty queue */
+}
+
+/*
+ * csio_wr_inval_flq_buf - Invalidate a free list buffer entry.
+ * @hw: HW module.
+ * @flq: The freelist queue.
+ *
+ * Invalidate the driver's version of a freelist buffer entry,
+ * without freeing the associated the DMA memory. The entry
+ * to be invalidated is picked up from the current Free list
+ * queue cidx.
+ *
+ */
+static inline void
+csio_wr_inval_flq_buf(struct csio_hw *hw, struct csio_q *flq)
+{
+	flq->cidx++;
+	if (flq->cidx == flq->credits) {
+		flq->cidx = 0;
+		CSIO_INC_STATS(flq, n_qwrap);
+	}
+}
+
+/*
+ * csio_wr_process_fl - Process a freelist completion.
+ * @hw: HW module.
+ * @q: The ingress queue attached to the Freelist.
+ * @wr: The freelist completion WR in the ingress queue.
+ * @len_to_qid: The lower 32-bits of the first flit of the RSP footer
+ * @iq_handler: Caller's handler for this completion.
+ * @priv: Private pointer of caller
+ *
+ */
+static inline void
+csio_wr_process_fl(struct csio_hw *hw, struct csio_q *q,
+		   void *wr, uint32_t len_to_qid,
+		   void (*iq_handler)(struct csio_hw *, void *,
+				      uint32_t, struct csio_fl_dma_buf *,
+				      void *),
+		   void *priv)
+{
+	struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+	struct csio_sge *sge = &wrm->sge;
+	struct csio_fl_dma_buf flb;
+	struct csio_dma_buf *buf, *fbuf;
+	uint32_t bufsz, len, lastlen = 0;
+	int n;
+	struct csio_q *flq = hw->wrm.q_arr[q->un.iq.flq_idx];
+
+	CSIO_DB_ASSERT(flq != NULL);
+
+	len = len_to_qid;
+
+	if (len & IQWRF_NEWBUF) {
+		if (flq->un.fl.offset > 0) {
+			csio_wr_inval_flq_buf(hw, flq);
+			flq->un.fl.offset = 0;
+		}
+		len = IQWRF_LEN_GET(len);
+	}
+
+	CSIO_DB_ASSERT(len != 0);
+
+	flb.totlen = len;
+
+	/* Consume all freelist buffers used for len bytes */
+	for (n = 0, fbuf = flb.flbufs; ; n++, fbuf++) {
+		buf = &flq->un.fl.bufs[flq->cidx];
+		bufsz = csio_wr_fl_bufsz(sge, buf);
+
+		fbuf->paddr	= buf->paddr;
+		fbuf->vaddr	= buf->vaddr;
+
+		flb.offset	= flq->un.fl.offset;
+		lastlen		= min(bufsz, len);
+		fbuf->len	= lastlen;
+
+		len -= lastlen;
+		if (!len)
+			break;
+		csio_wr_inval_flq_buf(hw, flq);
+	}
+
+	flb.defer_free = flq->un.fl.packen ? 0 : 1;
+
+	iq_handler(hw, wr, q->wr_sz - sizeof(struct csio_iqwr_footer),
+		   &flb, priv);
+
+	if (flq->un.fl.packen)
+		flq->un.fl.offset += ALIGN(lastlen, sge->csio_fl_align);
+	else
+		csio_wr_inval_flq_buf(hw, flq);
+
+}
+
+/*
+ * csio_is_new_iqwr - Is this a new Ingress queue entry ?
+ * @q: Ingress quueue.
+ * @ftr: Ingress queue WR SGE footer.
+ *
+ * The entry is new if our generation bit matches the corresponding
+ * bit in the footer of the current WR.
+ */
+static inline bool
+csio_is_new_iqwr(struct csio_q *q, struct csio_iqwr_footer *ftr)
+{
+	return (q->un.iq.genbit == (ftr->u.type_gen >> IQWRF_GEN_SHIFT));
+}
+
+/*
+ * csio_wr_process_iq - Process elements in Ingress queue.
+ * @hw:  HW pointer
+ * @qidx: Index of queue
+ * @iq_handler: Handler for this queue
+ * @priv: Caller's private pointer
+ *
+ * This routine walks through every entry of the ingress queue, calling
+ * the provided iq_handler with the entry, until the generation bit
+ * flips.
+ */
+int
+csio_wr_process_iq(struct csio_hw *hw, struct csio_q *q,
+		   void (*iq_handler)(struct csio_hw *, void *,
+				      uint32_t, struct csio_fl_dma_buf *,
+				      void *),
+		   void *priv)
+{
+	struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+	void *wr = (void *)((uintptr_t)q->vstart + (q->cidx * q->wr_sz));
+	struct csio_iqwr_footer *ftr;
+	uint32_t wr_type, fw_qid, qid;
+	struct csio_q *q_completed;
+	struct csio_q *flq = csio_iq_has_fl(q) ?
+					wrm->q_arr[q->un.iq.flq_idx] : NULL;
+	int rv = 0;
+
+	/* Get the footer */
+	ftr = (struct csio_iqwr_footer *)((uintptr_t)wr +
+					  (q->wr_sz - sizeof(*ftr)));
+
+	/*
+	 * When q wrapped around last time, driver should have inverted
+	 * ic.genbit as well.
+	 */
+	while (csio_is_new_iqwr(q, ftr)) {
+
+		CSIO_DB_ASSERT(((uintptr_t)wr + q->wr_sz) <=
+						(uintptr_t)q->vwrap);
+		rmb();
+		wr_type = IQWRF_TYPE_GET(ftr->u.type_gen);
+
+		switch (wr_type) {
+		case X_RSPD_TYPE_CPL:
+			/* Subtract footer from WR len */
+			iq_handler(hw, wr, q->wr_sz - sizeof(*ftr), NULL, priv);
+			break;
+		case X_RSPD_TYPE_FLBUF:
+			csio_wr_process_fl(hw, q, wr,
+					   ntohl(ftr->pldbuflen_qid),
+					   iq_handler, priv);
+			break;
+		case X_RSPD_TYPE_INTR:
+			fw_qid = ntohl(ftr->pldbuflen_qid);
+			qid = fw_qid - wrm->fw_iq_start;
+			q_completed = hw->wrm.intr_map[qid];
+
+			if (unlikely(qid ==
+					csio_q_physiqid(hw, hw->intr_iq_idx))) {
+				/*
+				 * We are already in the Forward Interrupt
+				 * Interrupt Queue Service! Do-not service
+				 * again!
+				 *
+				 */
+			} else {
+				CSIO_DB_ASSERT(q_completed);
+				CSIO_DB_ASSERT(
+					q_completed->un.iq.iq_intx_handler);
+
+				/* Call the queue handler. */
+				q_completed->un.iq.iq_intx_handler(hw, NULL,
+						0, NULL, (void *)q_completed);
+			}
+			break;
+		default:
+			csio_warn(hw, "Unknown resp type 0x%x received\n",
+				 wr_type);
+			CSIO_INC_STATS(q, n_rsp_unknown);
+			break;
+		}
+
+		/*
+		 * Ingress *always* has fixed size WR entries. Therefore,
+		 * there should always be complete WRs towards the end of
+		 * queue.
+		 */
+		if (((uintptr_t)wr + q->wr_sz) == (uintptr_t)q->vwrap) {
+
+			/* Roll over to start of queue */
+			q->cidx = 0;
+			wr	= q->vstart;
+
+			/* Toggle genbit */
+			q->un.iq.genbit ^= 0x1;
+
+			CSIO_INC_STATS(q, n_qwrap);
+		} else {
+			q->cidx++;
+			wr	= (void *)((uintptr_t)(q->vstart) +
+					   (q->cidx * q->wr_sz));
+		}
+
+		ftr = (struct csio_iqwr_footer *)((uintptr_t)wr +
+						  (q->wr_sz - sizeof(*ftr)));
+		q->inc_idx++;
+
+	} /* while (q->un.iq.genbit == hdr->genbit) */
+
+	/*
+	 * We need to re-arm SGE interrupts in case we got a stray interrupt,
+	 * especially in msix mode. With INTx, this may be a common occurence.
+	 */
+	if (unlikely(!q->inc_idx)) {
+		CSIO_INC_STATS(q, n_stray_comp);
+		rv = -EINVAL;
+		goto restart;
+	}
+
+	/* Replenish free list buffers if pending falls below low water mark */
+	if (flq) {
+		uint32_t avail  = csio_wr_avail_qcredits(flq);
+		if (avail <= 16) {
+			/* Make sure in FLQ, atleast 1 credit (8 FL buffers)
+			 * remains unpopulated otherwise HW thinks
+			 * FLQ is empty.
+			 */
+			csio_wr_update_fl(hw, flq, (flq->credits - 8) - avail);
+			csio_wr_ring_fldb(hw, flq);
+		}
+	}
+
+restart:
+	/* Now inform SGE about our incremental index value */
+	csio_wr_reg32(hw, CIDXINC(q->inc_idx)		|
+			  INGRESSQID(q->un.iq.physiqid)	|
+			  TIMERREG(csio_sge_timer_reg),
+			  MYPF_REG(SGE_PF_GTS));
+	q->stats.n_tot_rsps += q->inc_idx;
+
+	q->inc_idx = 0;
+
+	return rv;
+}
+
+int
+csio_wr_process_iq_idx(struct csio_hw *hw, int qidx,
+		   void (*iq_handler)(struct csio_hw *, void *,
+				      uint32_t, struct csio_fl_dma_buf *,
+				      void *),
+		   void *priv)
+{
+	struct csio_wrm *wrm	= csio_hw_to_wrm(hw);
+	struct csio_q	*iq	= wrm->q_arr[qidx];
+
+	return csio_wr_process_iq(hw, iq, iq_handler, priv);
+}
+
+static int
+csio_closest_timer(struct csio_sge *s, int time)
+{
+	int i, delta, match = 0, min_delta = INT_MAX;
+
+	for (i = 0; i < ARRAY_SIZE(s->timer_val); i++) {
+		delta = time - s->timer_val[i];
+		if (delta < 0)
+			delta = -delta;
+		if (delta < min_delta) {
+			min_delta = delta;
+			match = i;
+		}
+	}
+	return match;
+}
+
+static int
+csio_closest_thresh(struct csio_sge *s, int cnt)
+{
+	int i, delta, match = 0, min_delta = INT_MAX;
+
+	for (i = 0; i < ARRAY_SIZE(s->counter_val); i++) {
+		delta = cnt - s->counter_val[i];
+		if (delta < 0)
+			delta = -delta;
+		if (delta < min_delta) {
+			min_delta = delta;
+			match = i;
+		}
+	}
+	return match;
+}
+
+static void
+csio_wr_fixup_host_params(struct csio_hw *hw)
+{
+	struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+	struct csio_sge *sge = &wrm->sge;
+	uint32_t clsz = L1_CACHE_BYTES;
+	uint32_t s_hps = PAGE_SHIFT - 10;
+	uint32_t ingpad = 0;
+	uint32_t stat_len = clsz > 64 ? 128 : 64;
+
+	csio_wr_reg32(hw, HOSTPAGESIZEPF0(s_hps) | HOSTPAGESIZEPF1(s_hps) |
+		      HOSTPAGESIZEPF2(s_hps) | HOSTPAGESIZEPF3(s_hps) |
+		      HOSTPAGESIZEPF4(s_hps) | HOSTPAGESIZEPF5(s_hps) |
+		      HOSTPAGESIZEPF6(s_hps) | HOSTPAGESIZEPF7(s_hps),
+		      SGE_HOST_PAGE_SIZE);
+
+	sge->csio_fl_align = clsz < 32 ? 32 : clsz;
+	ingpad = ilog2(sge->csio_fl_align) - 5;
+
+	csio_set_reg_field(hw, SGE_CONTROL, INGPADBOUNDARY_MASK |
+					    EGRSTATUSPAGESIZE(1),
+			   INGPADBOUNDARY(ingpad) |
+			   EGRSTATUSPAGESIZE(stat_len != 64));
+
+	/* FL BUFFER SIZE#0 is Page size i,e already aligned to cache line */
+	csio_wr_reg32(hw, PAGE_SIZE, SGE_FL_BUFFER_SIZE0);
+	csio_wr_reg32(hw,
+		      (csio_rd_reg32(hw, SGE_FL_BUFFER_SIZE2) +
+		      sge->csio_fl_align - 1) & ~(sge->csio_fl_align - 1),
+		      SGE_FL_BUFFER_SIZE2);
+	csio_wr_reg32(hw,
+		      (csio_rd_reg32(hw, SGE_FL_BUFFER_SIZE3) +
+		      sge->csio_fl_align - 1) & ~(sge->csio_fl_align - 1),
+		      SGE_FL_BUFFER_SIZE3);
+
+	csio_wr_reg32(hw, HPZ0(PAGE_SHIFT - 12), ULP_RX_TDDP_PSZ);
+
+	/* default value of rx_dma_offset of the NIC driver */
+	csio_set_reg_field(hw, SGE_CONTROL, PKTSHIFT_MASK,
+			   PKTSHIFT(CSIO_SGE_RX_DMA_OFFSET));
+}
+
+static void
+csio_init_intr_coalesce_parms(struct csio_hw *hw)
+{
+	struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+	struct csio_sge *sge = &wrm->sge;
+
+	csio_sge_thresh_reg = csio_closest_thresh(sge, csio_intr_coalesce_cnt);
+	if (csio_intr_coalesce_cnt) {
+		csio_sge_thresh_reg = 0;
+		csio_sge_timer_reg = X_TIMERREG_RESTART_COUNTER;
+		return;
+	}
+
+	csio_sge_timer_reg = csio_closest_timer(sge, csio_intr_coalesce_time);
+}
+
+/*
+ * csio_wr_get_sge - Get SGE register values.
+ * @hw: HW module.
+ *
+ * Used by non-master functions and by master-functions relying on config file.
+ */
+static void
+csio_wr_get_sge(struct csio_hw *hw)
+{
+	struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+	struct csio_sge *sge = &wrm->sge;
+	uint32_t ingpad;
+	int i;
+	u32 timer_value_0_and_1, timer_value_2_and_3, timer_value_4_and_5;
+	u32 ingress_rx_threshold;
+
+	sge->sge_control = csio_rd_reg32(hw, SGE_CONTROL);
+
+	ingpad = INGPADBOUNDARY_GET(sge->sge_control);
+
+	switch (ingpad) {
+	case X_INGPCIEBOUNDARY_32B:
+		sge->csio_fl_align = 32; break;
+	case X_INGPCIEBOUNDARY_64B:
+		sge->csio_fl_align = 64; break;
+	case X_INGPCIEBOUNDARY_128B:
+		sge->csio_fl_align = 128; break;
+	case X_INGPCIEBOUNDARY_256B:
+		sge->csio_fl_align = 256; break;
+	case X_INGPCIEBOUNDARY_512B:
+		sge->csio_fl_align = 512; break;
+	case X_INGPCIEBOUNDARY_1024B:
+		sge->csio_fl_align = 1024; break;
+	case X_INGPCIEBOUNDARY_2048B:
+		sge->csio_fl_align = 2048; break;
+	case X_INGPCIEBOUNDARY_4096B:
+		sge->csio_fl_align = 4096; break;
+	}
+
+	for (i = 0; i < CSIO_SGE_FL_SIZE_REGS; i++)
+		csio_get_flbuf_size(hw, sge, i);
+
+	timer_value_0_and_1 = csio_rd_reg32(hw, SGE_TIMER_VALUE_0_AND_1);
+	timer_value_2_and_3 = csio_rd_reg32(hw, SGE_TIMER_VALUE_2_AND_3);
+	timer_value_4_and_5 = csio_rd_reg32(hw, SGE_TIMER_VALUE_4_AND_5);
+
+	sge->timer_val[0] = (uint16_t)csio_core_ticks_to_us(hw,
+					TIMERVALUE0_GET(timer_value_0_and_1));
+	sge->timer_val[1] = (uint16_t)csio_core_ticks_to_us(hw,
+					TIMERVALUE1_GET(timer_value_0_and_1));
+	sge->timer_val[2] = (uint16_t)csio_core_ticks_to_us(hw,
+					TIMERVALUE2_GET(timer_value_2_and_3));
+	sge->timer_val[3] = (uint16_t)csio_core_ticks_to_us(hw,
+					TIMERVALUE3_GET(timer_value_2_and_3));
+	sge->timer_val[4] = (uint16_t)csio_core_ticks_to_us(hw,
+					TIMERVALUE4_GET(timer_value_4_and_5));
+	sge->timer_val[5] = (uint16_t)csio_core_ticks_to_us(hw,
+					TIMERVALUE5_GET(timer_value_4_and_5));
+
+	ingress_rx_threshold = csio_rd_reg32(hw, SGE_INGRESS_RX_THRESHOLD);
+	sge->counter_val[0] = THRESHOLD_0_GET(ingress_rx_threshold);
+	sge->counter_val[1] = THRESHOLD_1_GET(ingress_rx_threshold);
+	sge->counter_val[2] = THRESHOLD_2_GET(ingress_rx_threshold);
+	sge->counter_val[3] = THRESHOLD_3_GET(ingress_rx_threshold);
+
+	csio_init_intr_coalesce_parms(hw);
+}
+
+/*
+ * csio_wr_set_sge - Initialize SGE registers
+ * @hw: HW module.
+ *
+ * Used by Master function to initialize SGE registers in the absence
+ * of a config file.
+ */
+static void
+csio_wr_set_sge(struct csio_hw *hw)
+{
+	struct csio_wrm *wrm = csio_hw_to_wrm(hw);
+	struct csio_sge *sge = &wrm->sge;
+	int i;
+
+	/*
+	 * Set up our basic SGE mode to deliver CPL messages to our Ingress
+	 * Queue and Packet Date to the Free List.
+	 */
+	csio_set_reg_field(hw, SGE_CONTROL, RXPKTCPLMODE(1), RXPKTCPLMODE(1));
+
+	sge->sge_control = csio_rd_reg32(hw, SGE_CONTROL);
+
+	/* sge->csio_fl_align is set up by csio_wr_fixup_host_params(). */
+
+	/*
+	 * Set up to drop DOORBELL writes when the DOORBELL FIFO overflows
+	 * and generate an interrupt when this occurs so we can recover.
+	 */
+	csio_set_reg_field(hw, SGE_DBFIFO_STATUS,
+			   HP_INT_THRESH(HP_INT_THRESH_MASK) |
+			   LP_INT_THRESH(LP_INT_THRESH_MASK),
+			   HP_INT_THRESH(CSIO_SGE_DBFIFO_INT_THRESH) |
+			   LP_INT_THRESH(CSIO_SGE_DBFIFO_INT_THRESH));
+	csio_set_reg_field(hw, SGE_DOORBELL_CONTROL, ENABLE_DROP,
+			   ENABLE_DROP);
+
+	/* SGE_FL_BUFFER_SIZE0 is set up by csio_wr_fixup_host_params(). */
+
+	CSIO_SET_FLBUF_SIZE(hw, 1, CSIO_SGE_FLBUF_SIZE1);
+	CSIO_SET_FLBUF_SIZE(hw, 2, CSIO_SGE_FLBUF_SIZE2);
+	CSIO_SET_FLBUF_SIZE(hw, 3, CSIO_SGE_FLBUF_SIZE3);
+	CSIO_SET_FLBUF_SIZE(hw, 4, CSIO_SGE_FLBUF_SIZE4);
+	CSIO_SET_FLBUF_SIZE(hw, 5, CSIO_SGE_FLBUF_SIZE5);
+	CSIO_SET_FLBUF_SIZE(hw, 6, CSIO_SGE_FLBUF_SIZE6);
+	CSIO_SET_FLBUF_SIZE(hw, 7, CSIO_SGE_FLBUF_SIZE7);
+	CSIO_SET_FLBUF_SIZE(hw, 8, CSIO_SGE_FLBUF_SIZE8);
+
+	for (i = 0; i < CSIO_SGE_FL_SIZE_REGS; i++)
+		csio_get_flbuf_size(hw, sge, i);
+
+	/* Initialize interrupt coalescing attributes */
+	sge->timer_val[0] = CSIO_SGE_TIMER_VAL_0;
+	sge->timer_val[1] = CSIO_SGE_TIMER_VAL_1;
+	sge->timer_val[2] = CSIO_SGE_TIMER_VAL_2;
+	sge->timer_val[3] = CSIO_SGE_TIMER_VAL_3;
+	sge->timer_val[4] = CSIO_SGE_TIMER_VAL_4;
+	sge->timer_val[5] = CSIO_SGE_TIMER_VAL_5;
+
+	sge->counter_val[0] = CSIO_SGE_INT_CNT_VAL_0;
+	sge->counter_val[1] = CSIO_SGE_INT_CNT_VAL_1;
+	sge->counter_val[2] = CSIO_SGE_INT_CNT_VAL_2;
+	sge->counter_val[3] = CSIO_SGE_INT_CNT_VAL_3;
+
+	csio_wr_reg32(hw, THRESHOLD_0(sge->counter_val[0]) |
+		      THRESHOLD_1(sge->counter_val[1]) |
+		      THRESHOLD_2(sge->counter_val[2]) |
+		      THRESHOLD_3(sge->counter_val[3]),
+		      SGE_INGRESS_RX_THRESHOLD);
+
+	csio_wr_reg32(hw,
+		   TIMERVALUE0(csio_us_to_core_ticks(hw, sge->timer_val[0])) |
+		   TIMERVALUE1(csio_us_to_core_ticks(hw, sge->timer_val[1])),
+		   SGE_TIMER_VALUE_0_AND_1);
+
+	csio_wr_reg32(hw,
+		   TIMERVALUE2(csio_us_to_core_ticks(hw, sge->timer_val[2])) |
+		   TIMERVALUE3(csio_us_to_core_ticks(hw, sge->timer_val[3])),
+		   SGE_TIMER_VALUE_2_AND_3);
+
+	csio_wr_reg32(hw,
+		   TIMERVALUE4(csio_us_to_core_ticks(hw, sge->timer_val[4])) |
+		   TIMERVALUE5(csio_us_to_core_ticks(hw, sge->timer_val[5])),
+		   SGE_TIMER_VALUE_4_AND_5);
+
+	csio_init_intr_coalesce_parms(hw);
+}
+
+void
+csio_wr_sge_init(struct csio_hw *hw)
+{
+	/*
+	 * If we are master:
+	 *    - If we plan to use the config file, we need to fixup some
+	 *      host specific registers, and read the rest of the SGE
+	 *      configuration.
+	 *    - If we dont plan to use the config file, we need to initialize
+	 *      SGE entirely, including fixing the host specific registers.
+	 * If we arent the master, we are only allowed to read and work off of
+	 *      the already initialized SGE values.
+	 *
+	 * Therefore, before calling this function, we assume that the master-
+	 * ship of the card, and whether to use config file or not, have
+	 * already been decided. In other words, CSIO_HWF_USING_SOFT_PARAMS and
+	 * CSIO_HWF_MASTER should be set/unset.
+	 */
+	if (csio_is_hw_master(hw)) {
+		csio_wr_fixup_host_params(hw);
+
+		if (hw->flags & CSIO_HWF_USING_SOFT_PARAMS)
+			csio_wr_get_sge(hw);
+		else
+			csio_wr_set_sge(hw);
+	} else
+		csio_wr_get_sge(hw);
+}
+
+/*
+ * csio_wrm_init - Initialize Work request module.
+ * @wrm: WR module
+ * @hw: HW pointer
+ *
+ * Allocates memory for an array of queue pointers starting at q_arr.
+ */
+int
+csio_wrm_init(struct csio_wrm *wrm, struct csio_hw *hw)
+{
+	int i;
+
+	if (!wrm->num_q) {
+		csio_err(hw, "Num queues is not set\n");
+		return -EINVAL;
+	}
+
+	wrm->q_arr = kzalloc(sizeof(struct csio_q *) * wrm->num_q, GFP_KERNEL);
+	if (!wrm->q_arr)
+		goto err;
+
+	for (i = 0; i < wrm->num_q; i++) {
+		wrm->q_arr[i] = kzalloc(sizeof(struct csio_q), GFP_KERNEL);
+		if (!wrm->q_arr[i]) {
+			while (--i >= 0)
+				kfree(wrm->q_arr[i]);
+			goto err_free_arr;
+		}
+	}
+	wrm->free_qidx	= 0;
+
+	return 0;
+
+err_free_arr:
+	kfree(wrm->q_arr);
+err:
+	return -ENOMEM;
+}
+
+/*
+ * csio_wrm_exit - Initialize Work request module.
+ * @wrm: WR module
+ * @hw: HW module
+ *
+ * Uninitialize WR module. Free q_arr and pointers in it.
+ * We have the additional job of freeing the DMA memory associated
+ * with the queues.
+ */
+void
+csio_wrm_exit(struct csio_wrm *wrm, struct csio_hw *hw)
+{
+	int i;
+	uint32_t j;
+	struct csio_q *q;
+	struct csio_dma_buf *buf;
+
+	for (i = 0; i < wrm->num_q; i++) {
+		q = wrm->q_arr[i];
+
+		if (wrm->free_qidx && (i < wrm->free_qidx)) {
+			if (q->type == CSIO_FREELIST) {
+				if (!q->un.fl.bufs)
+					continue;
+				for (j = 0; j < q->credits; j++) {
+					buf = &q->un.fl.bufs[j];
+					if (!buf->vaddr)
+						continue;
+					pci_free_consistent(hw->pdev, buf->len,
+							    buf->vaddr,
+							    buf->paddr);
+				}
+				kfree(q->un.fl.bufs);
+			}
+			pci_free_consistent(hw->pdev, q->size,
+					    q->vstart, q->pstart);
+		}
+		kfree(q);
+	}
+
+	hw->flags &= ~CSIO_HWF_Q_MEM_ALLOCED;
+
+	kfree(wrm->q_arr);
+}
diff --git a/drivers/scsi/csiostor/csio_wr.h b/drivers/scsi/csiostor/csio_wr.h
new file mode 100644
index 0000000..8d30e7a
--- /dev/null
+++ b/drivers/scsi/csiostor/csio_wr.h
@@ -0,0 +1,512 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CSIO_WR_H__
+#define __CSIO_WR_H__
+
+#include <linux/cache.h>
+
+#include "csio_defs.h"
+#include "t4fw_api.h"
+#include "t4fw_api_stor.h"
+
+/*
+ * SGE register field values.
+ */
+#define X_INGPCIEBOUNDARY_32B		0
+#define X_INGPCIEBOUNDARY_64B		1
+#define X_INGPCIEBOUNDARY_128B		2
+#define X_INGPCIEBOUNDARY_256B		3
+#define X_INGPCIEBOUNDARY_512B		4
+#define X_INGPCIEBOUNDARY_1024B		5
+#define X_INGPCIEBOUNDARY_2048B		6
+#define X_INGPCIEBOUNDARY_4096B		7
+
+/* GTS register */
+#define X_TIMERREG_COUNTER0		0
+#define X_TIMERREG_COUNTER1		1
+#define X_TIMERREG_COUNTER2		2
+#define X_TIMERREG_COUNTER3		3
+#define X_TIMERREG_COUNTER4		4
+#define X_TIMERREG_COUNTER5		5
+#define X_TIMERREG_RESTART_COUNTER	6
+#define X_TIMERREG_UPDATE_CIDX		7
+
+/*
+ * Egress Context field values
+ */
+#define X_FETCHBURSTMIN_16B		0
+#define X_FETCHBURSTMIN_32B		1
+#define X_FETCHBURSTMIN_64B		2
+#define X_FETCHBURSTMIN_128B		3
+
+#define X_FETCHBURSTMAX_64B		0
+#define X_FETCHBURSTMAX_128B		1
+#define X_FETCHBURSTMAX_256B		2
+#define X_FETCHBURSTMAX_512B		3
+
+#define X_HOSTFCMODE_NONE		0
+#define X_HOSTFCMODE_INGRESS_QUEUE	1
+#define X_HOSTFCMODE_STATUS_PAGE	2
+#define X_HOSTFCMODE_BOTH		3
+
+/*
+ * Ingress Context field values
+ */
+#define X_UPDATESCHEDULING_TIMER	0
+#define X_UPDATESCHEDULING_COUNTER_OPTTIMER	1
+
+#define X_UPDATEDELIVERY_NONE		0
+#define X_UPDATEDELIVERY_INTERRUPT	1
+#define X_UPDATEDELIVERY_STATUS_PAGE	2
+#define X_UPDATEDELIVERY_BOTH		3
+
+#define X_INTERRUPTDESTINATION_PCIE	0
+#define X_INTERRUPTDESTINATION_IQ	1
+
+#define X_RSPD_TYPE_FLBUF		0
+#define X_RSPD_TYPE_CPL			1
+#define X_RSPD_TYPE_INTR		2
+
+/* WR status is at the same position as retval in a CMD header */
+#define csio_wr_status(_wr)		\
+		(FW_CMD_RETVAL_GET(ntohl(((struct fw_cmd_hdr *)(_wr))->lo)))
+
+struct csio_hw;
+
+extern int csio_intr_coalesce_cnt;
+extern int csio_intr_coalesce_time;
+
+/* Ingress queue params */
+struct csio_iq_params {
+
+	uint8_t		iq_start:1;
+	uint8_t		iq_stop:1;
+	uint8_t		pfn:3;
+
+	uint8_t		vfn;
+
+	uint16_t	physiqid;
+	uint16_t	iqid;
+
+	uint16_t	fl0id;
+	uint16_t	fl1id;
+
+	uint8_t		viid;
+
+	uint8_t		type;
+	uint8_t		iqasynch;
+	uint8_t		reserved4;
+
+	uint8_t		iqandst;
+	uint8_t		iqanus;
+	uint8_t		iqanud;
+
+	uint16_t	iqandstindex;
+
+	uint8_t		iqdroprss;
+	uint8_t		iqpciech;
+	uint8_t		iqdcaen;
+
+	uint8_t		iqdcacpu;
+	uint8_t		iqintcntthresh;
+	uint8_t		iqo;
+
+	uint8_t		iqcprio;
+	uint8_t		iqesize;
+
+	uint16_t	iqsize;
+
+	uint64_t	iqaddr;
+
+	uint8_t		iqflintiqhsen;
+	uint8_t		reserved5;
+	uint8_t		iqflintcongen;
+	uint8_t		iqflintcngchmap;
+
+	uint32_t	reserved6;
+
+	uint8_t		fl0hostfcmode;
+	uint8_t		fl0cprio;
+	uint8_t		fl0paden;
+	uint8_t		fl0packen;
+	uint8_t		fl0congen;
+	uint8_t		fl0dcaen;
+
+	uint8_t		fl0dcacpu;
+	uint8_t		fl0fbmin;
+
+	uint8_t		fl0fbmax;
+	uint8_t		fl0cidxfthresho;
+	uint8_t		fl0cidxfthresh;
+
+	uint16_t	fl0size;
+
+	uint64_t	fl0addr;
+
+	uint64_t	reserved7;
+
+	uint8_t		fl1hostfcmode;
+	uint8_t		fl1cprio;
+	uint8_t		fl1paden;
+	uint8_t		fl1packen;
+	uint8_t		fl1congen;
+	uint8_t		fl1dcaen;
+
+	uint8_t		fl1dcacpu;
+	uint8_t		fl1fbmin;
+
+	uint8_t		fl1fbmax;
+	uint8_t		fl1cidxfthresho;
+	uint8_t		fl1cidxfthresh;
+
+	uint16_t	fl1size;
+
+	uint64_t	fl1addr;
+};
+
+/* Egress queue params */
+struct csio_eq_params {
+
+	uint8_t		pfn;
+	uint8_t		vfn;
+
+	uint8_t		eqstart:1;
+	uint8_t		eqstop:1;
+
+	uint16_t        physeqid;
+	uint32_t	eqid;
+
+	uint8_t		hostfcmode:2;
+	uint8_t		cprio:1;
+	uint8_t		pciechn:3;
+
+	uint16_t	iqid;
+
+	uint8_t		dcaen:1;
+	uint8_t		dcacpu:5;
+
+	uint8_t		fbmin:3;
+	uint8_t		fbmax:3;
+
+	uint8_t		cidxfthresho:1;
+	uint8_t		cidxfthresh:3;
+
+	uint16_t	eqsize;
+
+	uint64_t	eqaddr;
+};
+
+struct csio_dma_buf {
+	struct list_head	list;
+	void			*vaddr;		/* Virtual address */
+	dma_addr_t		paddr;		/* Physical address */
+	uint32_t		len;		/* Buffer size */
+};
+
+/* Generic I/O request structure */
+struct csio_ioreq {
+	struct csio_sm		sm;		/* SM, List
+						 * should be the first member
+						 */
+	int			iq_idx;		/* Ingress queue index */
+	int			eq_idx;		/* Egress queue index */
+	uint32_t		nsge;		/* Number of SG elements */
+	uint32_t		tmo;		/* Driver timeout */
+	uint32_t		datadir;	/* Data direction */
+	struct csio_dma_buf	dma_buf;	/* Req/resp DMA buffers */
+	uint16_t		wr_status;	/* WR completion status */
+	int16_t			drv_status;	/* Driver internal status */
+	struct csio_lnode	*lnode;		/* Owner lnode */
+	struct csio_rnode	*rnode;		/* Src/destination rnode */
+	void (*io_cbfn) (struct csio_hw *, struct csio_ioreq *);
+						/* completion callback */
+	void			*scratch1;	/* Scratch area 1.
+						 */
+	void			*scratch2;	/* Scratch area 2. */
+	struct list_head	gen_list;	/* Any list associated with
+						 * this ioreq.
+						 */
+	uint64_t		fw_handle;	/* Unique handle passed
+						 * to FW
+						 */
+	uint8_t			dcopy;		/* Data copy required */
+	uint8_t			reserved1;
+	uint16_t		reserved2;
+	struct completion	cmplobj;	/* ioreq completion object */
+} ____cacheline_aligned_in_smp;
+
+/*
+ * Egress status page for egress cidx updates
+ */
+struct csio_qstatus_page {
+	__be32 qid;
+	__be16 cidx;
+	__be16 pidx;
+};
+
+
+enum {
+	CSIO_MAX_FLBUF_PER_IQWR = 4,
+	CSIO_QCREDIT_SZ  = 64,			/* pidx/cidx increments
+						 * in bytes
+						 */
+	CSIO_MAX_QID = 0xFFFF,
+	CSIO_MAX_IQ = 128,
+
+	CSIO_SGE_NTIMERS = 6,
+	CSIO_SGE_NCOUNTERS = 4,
+	CSIO_SGE_FL_SIZE_REGS = 16,
+};
+
+/* Defines for type */
+enum {
+	CSIO_EGRESS	= 1,
+	CSIO_INGRESS	= 2,
+	CSIO_FREELIST	= 3,
+};
+
+/*
+ * Structure for footer (last 2 flits) of Ingress Queue Entry.
+ */
+struct csio_iqwr_footer {
+	__be32			hdrbuflen_pidx;
+	__be32			pldbuflen_qid;
+	union {
+		u8		type_gen;
+		__be64		last_flit;
+	} u;
+};
+
+#define IQWRF_NEWBUF		(1 << 31)
+#define IQWRF_LEN_GET(x)	(((x) >> 0) & 0x7fffffffU)
+#define IQWRF_GEN_SHIFT		7
+#define IQWRF_TYPE_GET(x)	(((x) >> 4) & 0x3U)
+
+
+/*
+ * WR pair:
+ * ========
+ * A WR can start towards the end of a queue, and then continue at the
+ * beginning, since the queue is considered to be circular. This will
+ * require a pair of address/len to be passed back to the caller -
+ * hence the Work request pair structure.
+ */
+struct csio_wr_pair {
+	void			*addr1;
+	uint32_t		size1;
+	void			*addr2;
+	uint32_t		size2;
+};
+
+/*
+ * The following structure is used by ingress processing to return the
+ * free list buffers to consumers.
+ */
+struct csio_fl_dma_buf {
+	struct csio_dma_buf	flbufs[CSIO_MAX_FLBUF_PER_IQWR];
+						/* Freelist DMA buffers */
+	int			offset;		/* Offset within the
+						 * first FL buf.
+						 */
+	uint32_t		totlen;		/* Total length */
+	uint8_t			defer_free;	/* Free of buffer can
+						 * deferred
+						 */
+};
+
+/* Data-types */
+typedef void (*iq_handler_t)(struct csio_hw *, void *, uint32_t,
+			     struct csio_fl_dma_buf *, void *);
+
+struct csio_iq {
+	uint16_t		iqid;		/* Queue ID */
+	uint16_t		physiqid;	/* Physical Queue ID */
+	uint16_t		genbit;		/* Generation bit,
+						 * initially set to 1
+						 */
+	int			flq_idx;	/* Freelist queue index */
+	iq_handler_t		iq_intx_handler; /* IQ INTx handler routine */
+};
+
+struct csio_eq {
+	uint16_t		eqid;		/* Qid */
+	uint16_t		physeqid;	/* Physical Queue ID */
+	uint8_t			wrap[512];	/* Temp area for q-wrap around*/
+};
+
+struct csio_fl {
+	uint16_t		flid;		/* Qid */
+	uint16_t		packen;		/* Packing enabled? */
+	int			offset;		/* Offset within FL buf */
+	int			sreg;		/* Size register */
+	struct csio_dma_buf	*bufs;		/* Free list buffer ptr array
+						 * indexed using flq->cidx/pidx
+						 */
+};
+
+struct csio_qstats {
+	uint32_t	n_tot_reqs;		/* Total no. of Requests */
+	uint32_t	n_tot_rsps;		/* Total no. of responses */
+	uint32_t	n_qwrap;		/* Queue wraps */
+	uint32_t	n_eq_wr_split;		/* Number of split EQ WRs */
+	uint32_t	n_qentry;		/* Queue entry */
+	uint32_t	n_qempty;		/* Queue empty */
+	uint32_t	n_qfull;		/* Queue fulls */
+	uint32_t	n_rsp_unknown;		/* Unknown response type */
+	uint32_t	n_stray_comp;		/* Stray completion intr */
+	uint32_t	n_flq_refill;		/* Number of FL refills */
+};
+
+/* Queue metadata */
+struct csio_q {
+	uint16_t		type;		/* Type: Ingress/Egress/FL */
+	uint16_t		pidx;		/* producer index */
+	uint16_t		cidx;		/* consumer index */
+	uint16_t		inc_idx;	/* Incremental index */
+	uint32_t		wr_sz;		/* Size of all WRs in this q
+						 * if fixed
+						 */
+	void			*vstart;	/* Base virtual address
+						 * of queue
+						 */
+	void			*vwrap;		/* Virtual end address to
+						 * wrap around at
+						 */
+	uint32_t		credits;	/* Size of queue in credits */
+	void			*owner;		/* Owner */
+	union {					/* Queue contexts */
+		struct csio_iq	iq;
+		struct csio_eq	eq;
+		struct csio_fl	fl;
+	} un;
+
+	dma_addr_t		pstart;		/* Base physical address of
+						 * queue
+						 */
+	uint32_t		portid;		/* PCIE Channel */
+	uint32_t		size;		/* Size of queue in bytes */
+	struct csio_qstats	stats;		/* Statistics */
+} ____cacheline_aligned_in_smp;
+
+struct csio_sge {
+	uint32_t	csio_fl_align;		/* Calculated and cached
+						 * for fast path
+						 */
+	uint32_t	sge_control;		/* padding, boundaries,
+						 * lengths, etc.
+						 */
+	uint32_t	sge_host_page_size;	/* Host page size */
+	uint32_t	sge_fl_buf_size[CSIO_SGE_FL_SIZE_REGS];
+						/* free list buffer sizes */
+	uint16_t	timer_val[CSIO_SGE_NTIMERS];
+	uint8_t		counter_val[CSIO_SGE_NCOUNTERS];
+};
+
+/* Work request module */
+struct csio_wrm {
+	int			num_q;		/* Number of queues */
+	struct csio_q		**q_arr;	/* Array of queue pointers
+						 * allocated dynamically
+						 * based on configured values
+						 */
+	uint32_t		fw_iq_start;	/* Start ID of IQ for this fn*/
+	uint32_t		fw_eq_start;	/* Start ID of EQ for this fn*/
+	struct csio_q		*intr_map[CSIO_MAX_IQ];
+						/* IQ-id to IQ map table. */
+	int			free_qidx;	/* queue idx of free queue */
+	struct csio_sge		sge;		/* SGE params */
+};
+
+#define csio_get_q(__hw, __idx)		((__hw)->wrm.q_arr[__idx])
+#define	csio_q_type(__hw, __idx)	((__hw)->wrm.q_arr[(__idx)]->type)
+#define	csio_q_pidx(__hw, __idx)	((__hw)->wrm.q_arr[(__idx)]->pidx)
+#define	csio_q_cidx(__hw, __idx)	((__hw)->wrm.q_arr[(__idx)]->cidx)
+#define	csio_q_inc_idx(__hw, __idx)	((__hw)->wrm.q_arr[(__idx)]->inc_idx)
+#define	csio_q_vstart(__hw, __idx)	((__hw)->wrm.q_arr[(__idx)]->vstart)
+#define	csio_q_pstart(__hw, __idx)	((__hw)->wrm.q_arr[(__idx)]->pstart)
+#define	csio_q_size(__hw, __idx)	((__hw)->wrm.q_arr[(__idx)]->size)
+#define	csio_q_credits(__hw, __idx)	((__hw)->wrm.q_arr[(__idx)]->credits)
+#define	csio_q_portid(__hw, __idx)	((__hw)->wrm.q_arr[(__idx)]->portid)
+#define	csio_q_wr_sz(__hw, __idx)	((__hw)->wrm.q_arr[(__idx)]->wr_sz)
+#define	csio_q_iqid(__hw, __idx)	((__hw)->wrm.q_arr[(__idx)]->un.iq.iqid)
+#define csio_q_physiqid(__hw, __idx)					\
+				((__hw)->wrm.q_arr[(__idx)]->un.iq.physiqid)
+#define csio_q_iq_flq_idx(__hw, __idx)					\
+				((__hw)->wrm.q_arr[(__idx)]->un.iq.flq_idx)
+#define	csio_q_eqid(__hw, __idx)	((__hw)->wrm.q_arr[(__idx)]->un.eq.eqid)
+#define	csio_q_flid(__hw, __idx)	((__hw)->wrm.q_arr[(__idx)]->un.fl.flid)
+
+#define csio_q_physeqid(__hw, __idx)					\
+				((__hw)->wrm.q_arr[(__idx)]->un.eq.physeqid)
+#define csio_iq_has_fl(__iq)		((__iq)->un.iq.flq_idx != -1)
+
+#define csio_q_iq_to_flid(__hw, __iq_idx)				\
+	csio_q_flid((__hw), (__hw)->wrm.q_arr[(__iq_qidx)]->un.iq.flq_idx)
+#define csio_q_set_intr_map(__hw, __iq_idx, __rel_iq_id)		\
+		(__hw)->wrm.intr_map[__rel_iq_id] = csio_get_q(__hw, __iq_idx)
+#define	csio_q_eq_wrap(__hw, __idx)	((__hw)->wrm.q_arr[(__idx)]->un.eq.wrap)
+
+struct csio_mb;
+
+int csio_wr_alloc_q(struct csio_hw *, uint32_t, uint32_t,
+		    uint16_t, void *, uint32_t, int, iq_handler_t);
+int csio_wr_iq_create(struct csio_hw *, void *, int,
+				uint32_t, uint8_t, bool,
+				void (*)(struct csio_hw *, struct csio_mb *));
+int csio_wr_eq_create(struct csio_hw *, void *, int, int, uint8_t,
+				void (*)(struct csio_hw *, struct csio_mb *));
+int csio_wr_destroy_queues(struct csio_hw *, bool cmd);
+
+
+int csio_wr_get(struct csio_hw *, int, uint32_t,
+			  struct csio_wr_pair *);
+void csio_wr_copy_to_wrp(void *, struct csio_wr_pair *, uint32_t, uint32_t);
+int csio_wr_issue(struct csio_hw *, int, bool);
+int csio_wr_process_iq(struct csio_hw *, struct csio_q *,
+				 void (*)(struct csio_hw *, void *,
+					  uint32_t, struct csio_fl_dma_buf *,
+					  void *),
+				 void *);
+int csio_wr_process_iq_idx(struct csio_hw *, int,
+				 void (*)(struct csio_hw *, void *,
+					  uint32_t, struct csio_fl_dma_buf *,
+					  void *),
+				 void *);
+
+void csio_wr_sge_init(struct csio_hw *);
+int csio_wrm_init(struct csio_wrm *, struct csio_hw *);
+void csio_wrm_exit(struct csio_wrm *, struct csio_hw *);
+
+#endif /* ifndef __CSIO_WR_H__ */
diff --git a/drivers/scsi/csiostor/t4fw_api_stor.h b/drivers/scsi/csiostor/t4fw_api_stor.h
new file mode 100644
index 0000000..b96903a
--- /dev/null
+++ b/drivers/scsi/csiostor/t4fw_api_stor.h
@@ -0,0 +1,578 @@
+/*
+ * This file is part of the Chelsio FCoE driver for Linux.
+ *
+ * Copyright (c) 2009-2010 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _T4FW_API_STOR_H_
+#define _T4FW_API_STOR_H_
+
+
+/******************************************************************************
+ *   R E T U R N   V A L U E S
+ ********************************/
+
+enum fw_retval {
+	FW_SUCCESS		= 0,	/* completed sucessfully */
+	FW_EPERM		= 1,	/* operation not permitted */
+	FW_ENOENT		= 2,	/* no such file or directory */
+	FW_EIO			= 5,	/* input/output error; hw bad */
+	FW_ENOEXEC		= 8,	/* exec format error; inv microcode */
+	FW_EAGAIN		= 11,	/* try again */
+	FW_ENOMEM		= 12,	/* out of memory */
+	FW_EFAULT		= 14,	/* bad address; fw bad */
+	FW_EBUSY		= 16,	/* resource busy */
+	FW_EEXIST		= 17,	/* file exists */
+	FW_EINVAL		= 22,	/* invalid argument */
+	FW_ENOSPC		= 28,	/* no space left on device */
+	FW_ENOSYS		= 38,	/* functionality not implemented */
+	FW_EPROTO		= 71,	/* protocol error */
+	FW_EADDRINUSE		= 98,	/* address already in use */
+	FW_EADDRNOTAVAIL	= 99,	/* cannot assigned requested address */
+	FW_ENETDOWN		= 100,	/* network is down */
+	FW_ENETUNREACH		= 101,	/* network is unreachable */
+	FW_ENOBUFS		= 105,	/* no buffer space available */
+	FW_ETIMEDOUT		= 110,	/* timeout */
+	FW_EINPROGRESS		= 115,	/* fw internal */
+	FW_SCSI_ABORT_REQUESTED	= 128,	/* */
+	FW_SCSI_ABORT_TIMEDOUT	= 129,	/* */
+	FW_SCSI_ABORTED		= 130,	/* */
+	FW_SCSI_CLOSE_REQUESTED	= 131,	/* */
+	FW_ERR_LINK_DOWN	= 132,	/* */
+	FW_RDEV_NOT_READY	= 133,	/* */
+	FW_ERR_RDEV_LOST	= 134,	/* */
+	FW_ERR_RDEV_LOGO	= 135,	/* */
+	FW_FCOE_NO_XCHG		= 136,	/* */
+	FW_SCSI_RSP_ERR		= 137,	/* */
+	FW_ERR_RDEV_IMPL_LOGO	= 138,	/* */
+	FW_SCSI_UNDER_FLOW_ERR  = 139,	/* */
+	FW_SCSI_OVER_FLOW_ERR   = 140,	/* */
+	FW_SCSI_DDP_ERR		= 141,	/* DDP error*/
+	FW_SCSI_TASK_ERR	= 142,	/* No SCSI tasks available */
+};
+
+enum fw_fcoe_link_sub_op {
+	FCOE_LINK_DOWN	= 0x0,
+	FCOE_LINK_UP	= 0x1,
+	FCOE_LINK_COND	= 0x2,
+};
+
+enum fw_fcoe_link_status {
+	FCOE_LINKDOWN	= 0x0,
+	FCOE_LINKUP	= 0x1,
+};
+
+enum fw_ofld_prot {
+	PROT_FCOE	= 0x1,
+	PROT_ISCSI	= 0x2,
+};
+
+enum rport_type_fcoe {
+	FLOGI_VFPORT	= 0x1,		/* 0xfffffe */
+	FDISC_VFPORT	= 0x2,		/* 0xfffffe */
+	NS_VNPORT	= 0x3,		/* 0xfffffc */
+	REG_FC4_VNPORT	= 0x4,		/* any FC4 type VN_PORT */
+	REG_VNPORT	= 0x5,		/* 0xfffxxx - non FC4 port in switch */
+	FDMI_VNPORT	= 0x6,		/* 0xfffffa */
+	FAB_CTLR_VNPORT	= 0x7,		/* 0xfffffd */
+};
+
+enum event_cause_fcoe {
+	PLOGI_ACC_RCVD		= 0x01,
+	PLOGI_RJT_RCVD		= 0x02,
+	PLOGI_RCVD		= 0x03,
+	PLOGO_RCVD		= 0x04,
+	PRLI_ACC_RCVD		= 0x05,
+	PRLI_RJT_RCVD		= 0x06,
+	PRLI_RCVD		= 0x07,
+	PRLO_RCVD		= 0x08,
+	NPORT_ID_CHGD		= 0x09,
+	FLOGO_RCVD		= 0x0a,
+	CLR_VIRT_LNK_RCVD	= 0x0b,
+	FLOGI_ACC_RCVD		= 0x0c,
+	FLOGI_RJT_RCVD		= 0x0d,
+	FDISC_ACC_RCVD		= 0x0e,
+	FDISC_RJT_RCVD		= 0x0f,
+	FLOGI_TMO_MAX_RETRY	= 0x10,
+	IMPL_LOGO_ADISC_ACC	= 0x11,
+	IMPL_LOGO_ADISC_RJT	= 0x12,
+	IMPL_LOGO_ADISC_CNFLT	= 0x13,
+	PRLI_TMO		= 0x14,
+	ADISC_TMO		= 0x15,
+	RSCN_DEV_LOST		= 0x16,
+	SCR_ACC_RCVD		= 0x17,
+	ADISC_RJT_RCVD		= 0x18,
+	LOGO_SNT		= 0x19,
+	PROTO_ERR_IMPL_LOGO	= 0x1a,
+};
+
+enum fcoe_cmn_type {
+	FCOE_ELS,
+	FCOE_CT,
+	FCOE_SCSI_CMD,
+	FCOE_UNSOL_ELS,
+};
+
+enum fw_wr_stor_opcodes {
+	FW_RDEV_WR                     = 0x38,
+	FW_FCOE_ELS_CT_WR              = 0x30,
+	FW_SCSI_WRITE_WR               = 0x31,
+	FW_SCSI_READ_WR                = 0x32,
+	FW_SCSI_CMD_WR                 = 0x33,
+	FW_SCSI_ABRT_CLS_WR            = 0x34,
+};
+
+struct fw_rdev_wr {
+	__be32 op_to_immdlen;
+	__be32 alloc_to_len16;
+	__be64 cookie;
+	u8     protocol;
+	u8     event_cause;
+	u8     cur_state;
+	u8     prev_state;
+	__be32 flags_to_assoc_flowid;
+	union rdev_entry {
+		struct fcoe_rdev_entry {
+			__be32 flowid;
+			u8     protocol;
+			u8     event_cause;
+			u8     flags;
+			u8     rjt_reason;
+			u8     cur_login_st;
+			u8     prev_login_st;
+			__be16 rcv_fr_sz;
+			u8     rd_xfer_rdy_to_rport_type;
+			u8     vft_to_qos;
+			u8     org_proc_assoc_to_acc_rsp_code;
+			u8     enh_disc_to_tgt;
+			u8     wwnn[8];
+			u8     wwpn[8];
+			__be16 iqid;
+			u8     fc_oui[3];
+			u8     r_id[3];
+		} fcoe_rdev;
+		struct iscsi_rdev_entry {
+			__be32 flowid;
+			u8     protocol;
+			u8     event_cause;
+			u8     flags;
+			u8     r3;
+			__be16 iscsi_opts;
+			__be16 tcp_opts;
+			__be16 ip_opts;
+			__be16 max_rcv_len;
+			__be16 max_snd_len;
+			__be16 first_brst_len;
+			__be16 max_brst_len;
+			__be16 r4;
+			__be16 def_time2wait;
+			__be16 def_time2ret;
+			__be16 nop_out_intrvl;
+			__be16 non_scsi_to;
+			__be16 isid;
+			__be16 tsid;
+			__be16 port;
+			__be16 tpgt;
+			u8     r5[6];
+			__be16 iqid;
+		} iscsi_rdev;
+	} u;
+};
+
+#define FW_RDEV_WR_FLOWID_GET(x)	(((x) >> 8) & 0xfffff)
+#define FW_RDEV_WR_ASSOC_FLOWID_GET(x)	(((x) >> 0) & 0xfffff)
+#define FW_RDEV_WR_RPORT_TYPE_GET(x)	(((x) >> 0) & 0x1f)
+#define FW_RDEV_WR_NPIV_GET(x)		(((x) >> 6) & 0x1)
+#define FW_RDEV_WR_CLASS_GET(x)		(((x) >> 4) & 0x3)
+#define FW_RDEV_WR_TASK_RETRY_ID_GET(x)	(((x) >> 5) & 0x1)
+#define FW_RDEV_WR_RETRY_GET(x)		(((x) >> 4) & 0x1)
+#define FW_RDEV_WR_CONF_CMPL_GET(x)	(((x) >> 3) & 0x1)
+#define FW_RDEV_WR_INI_GET(x)		(((x) >> 1) & 0x1)
+#define FW_RDEV_WR_TGT_GET(x)		(((x) >> 0) & 0x1)
+
+struct fw_fcoe_els_ct_wr {
+	__be32 op_immdlen;
+	__be32 flowid_len16;
+	__be64 cookie;
+	__be16 iqid;
+	u8     tmo_val;
+	u8     els_ct_type;
+	u8     ctl_pri;
+	u8     cp_en_class;
+	__be16 xfer_cnt;
+	u8     fl_to_sp;
+	u8     l_id[3];
+	u8     r5;
+	u8     r_id[3];
+	__be64 rsp_dmaaddr;
+	__be32 rsp_dmalen;
+	__be32 r6;
+};
+
+#define FW_FCOE_ELS_CT_WR_OPCODE(x)		((x) << 24)
+#define FW_FCOE_ELS_CT_WR_OPCODE_GET(x)		(((x) >> 24) & 0xff)
+#define FW_FCOE_ELS_CT_WR_IMMDLEN(x)		((x) << 0)
+#define FW_FCOE_ELS_CT_WR_IMMDLEN_GET(x)	(((x) >> 0) & 0xff)
+#define FW_FCOE_ELS_CT_WR_SP(x)			((x) << 0)
+
+struct fw_scsi_write_wr {
+	__be32 op_immdlen;
+	__be32 flowid_len16;
+	__be64 cookie;
+	__be16 iqid;
+	u8     tmo_val;
+	u8     use_xfer_cnt;
+	union fw_scsi_write_priv {
+		struct fcoe_write_priv {
+			u8   ctl_pri;
+			u8   cp_en_class;
+			u8   r3_lo[2];
+		} fcoe;
+		struct iscsi_write_priv {
+			u8   r3[4];
+		} iscsi;
+	} u;
+	__be32 xfer_cnt;
+	__be32 ini_xfer_cnt;
+	__be64 rsp_dmaaddr;
+	__be32 rsp_dmalen;
+	__be32 r4;
+};
+
+#define FW_SCSI_WRITE_WR_IMMDLEN(x)	((x) << 0)
+
+struct fw_scsi_read_wr {
+	__be32 op_immdlen;
+	__be32 flowid_len16;
+	__be64 cookie;
+	__be16 iqid;
+	u8     tmo_val;
+	u8     use_xfer_cnt;
+	union fw_scsi_read_priv {
+		struct fcoe_read_priv {
+			u8   ctl_pri;
+			u8   cp_en_class;
+			u8   r3_lo[2];
+		} fcoe;
+		struct iscsi_read_priv {
+			u8   r3[4];
+		} iscsi;
+	} u;
+	__be32 xfer_cnt;
+	__be32 ini_xfer_cnt;
+	__be64 rsp_dmaaddr;
+	__be32 rsp_dmalen;
+	__be32 r4;
+};
+
+#define FW_SCSI_READ_WR_IMMDLEN(x)	((x) << 0)
+
+struct fw_scsi_cmd_wr {
+	__be32 op_immdlen;
+	__be32 flowid_len16;
+	__be64 cookie;
+	__be16 iqid;
+	u8     tmo_val;
+	u8     r3;
+	union fw_scsi_cmd_priv {
+		struct fcoe_cmd_priv {
+			u8   ctl_pri;
+			u8   cp_en_class;
+			u8   r4_lo[2];
+		} fcoe;
+		struct iscsi_cmd_priv {
+			u8   r4[4];
+		} iscsi;
+	} u;
+	u8     r5[8];
+	__be64 rsp_dmaaddr;
+	__be32 rsp_dmalen;
+	__be32 r6;
+};
+
+#define FW_SCSI_CMD_WR_IMMDLEN(x)	((x) << 0)
+
+#define SCSI_ABORT 0
+#define SCSI_CLOSE 1
+
+struct fw_scsi_abrt_cls_wr {
+	__be32 op_immdlen;
+	__be32 flowid_len16;
+	__be64 cookie;
+	__be16 iqid;
+	u8     tmo_val;
+	u8     sub_opcode_to_chk_all_io;
+	u8     r3[4];
+	__be64 t_cookie;
+};
+
+#define FW_SCSI_ABRT_CLS_WR_SUB_OPCODE(x)	((x) << 2)
+#define FW_SCSI_ABRT_CLS_WR_SUB_OPCODE_GET(x)	(((x) >> 2) & 0x3f)
+#define FW_SCSI_ABRT_CLS_WR_CHK_ALL_IO(x)	((x) << 0)
+
+enum fw_cmd_stor_opcodes {
+	FW_FCOE_RES_INFO_CMD           = 0x31,
+	FW_FCOE_LINK_CMD               = 0x32,
+	FW_FCOE_VNP_CMD                = 0x33,
+	FW_FCOE_SPARAMS_CMD            = 0x35,
+	FW_FCOE_STATS_CMD              = 0x37,
+	FW_FCOE_FCF_CMD                = 0x38,
+};
+
+struct fw_fcoe_res_info_cmd {
+	__be32 op_to_read;
+	__be32 retval_len16;
+	__be16 e_d_tov;
+	__be16 r_a_tov_seq;
+	__be16 r_a_tov_els;
+	__be16 r_r_tov;
+	__be32 max_xchgs;
+	__be32 max_ssns;
+	__be32 used_xchgs;
+	__be32 used_ssns;
+	__be32 max_fcfs;
+	__be32 max_vnps;
+	__be32 used_fcfs;
+	__be32 used_vnps;
+};
+
+struct fw_fcoe_link_cmd {
+	__be32 op_to_portid;
+	__be32 retval_len16;
+	__be32 sub_opcode_fcfi;
+	u8     r3;
+	u8     lstatus;
+	__be16 flags;
+	u8     r4;
+	u8     set_vlan;
+	__be16 vlan_id;
+	__be32 vnpi_pkd;
+	__be16 r6;
+	u8     phy_mac[6];
+	u8     vnport_wwnn[8];
+	u8     vnport_wwpn[8];
+};
+
+#define FW_FCOE_LINK_CMD_PORTID(x)	((x) << 0)
+#define FW_FCOE_LINK_CMD_PORTID_GET(x)	(((x) >> 0) & 0xf)
+#define FW_FCOE_LINK_CMD_SUB_OPCODE(x)  ((x) << 24U)
+#define FW_FCOE_LINK_CMD_FCFI(x)	((x) << 0)
+#define FW_FCOE_LINK_CMD_FCFI_GET(x)	(((x) >> 0) & 0xffffff)
+#define FW_FCOE_LINK_CMD_VNPI_GET(x)	(((x) >> 0) & 0xfffff)
+
+struct fw_fcoe_vnp_cmd {
+	__be32 op_to_fcfi;
+	__be32 alloc_to_len16;
+	__be32 gen_wwn_to_vnpi;
+	__be32 vf_id;
+	__be16 iqid;
+	u8   vnport_mac[6];
+	u8   vnport_wwnn[8];
+	u8   vnport_wwpn[8];
+	u8   cmn_srv_parms[16];
+	u8   clsp_word_0_1[8];
+};
+
+#define FW_FCOE_VNP_CMD_FCFI(x)		((x) << 0)
+#define FW_FCOE_VNP_CMD_ALLOC		(1U << 31)
+#define FW_FCOE_VNP_CMD_FREE		(1U << 30)
+#define FW_FCOE_VNP_CMD_MODIFY		(1U << 29)
+#define FW_FCOE_VNP_CMD_GEN_WWN		(1U << 22)
+#define FW_FCOE_VNP_CMD_VFID_EN		(1U << 20)
+#define FW_FCOE_VNP_CMD_VNPI(x)		((x) << 0)
+#define FW_FCOE_VNP_CMD_VNPI_GET(x)	(((x) >> 0) & 0xfffff)
+
+struct fw_fcoe_sparams_cmd {
+	__be32 op_to_portid;
+	__be32 retval_len16;
+	u8     r3[7];
+	u8     cos;
+	u8     lport_wwnn[8];
+	u8     lport_wwpn[8];
+	u8     cmn_srv_parms[16];
+	u8     cls_srv_parms[16];
+};
+
+#define FW_FCOE_SPARAMS_CMD_PORTID(x)	((x) << 0)
+
+struct fw_fcoe_stats_cmd {
+	__be32 op_to_flowid;
+	__be32 free_to_len16;
+	union fw_fcoe_stats {
+		struct fw_fcoe_stats_ctl {
+			u8   nstats_port;
+			u8   port_valid_ix;
+			__be16 r6;
+			__be32 r7;
+			__be64 stat0;
+			__be64 stat1;
+			__be64 stat2;
+			__be64 stat3;
+			__be64 stat4;
+			__be64 stat5;
+		} ctl;
+		struct fw_fcoe_port_stats {
+			__be64 tx_bcast_bytes;
+			__be64 tx_bcast_frames;
+			__be64 tx_mcast_bytes;
+			__be64 tx_mcast_frames;
+			__be64 tx_ucast_bytes;
+			__be64 tx_ucast_frames;
+			__be64 tx_drop_frames;
+			__be64 tx_offload_bytes;
+			__be64 tx_offload_frames;
+			__be64 rx_bcast_bytes;
+			__be64 rx_bcast_frames;
+			__be64 rx_mcast_bytes;
+			__be64 rx_mcast_frames;
+			__be64 rx_ucast_bytes;
+			__be64 rx_ucast_frames;
+			__be64 rx_err_frames;
+		} port_stats;
+		struct fw_fcoe_fcf_stats {
+			__be32 fip_tx_bytes;
+			__be32 fip_tx_fr;
+			__be64 fcf_ka;
+			__be64 mcast_adv_rcvd;
+			__be16 ucast_adv_rcvd;
+			__be16 sol_sent;
+			__be16 vlan_req;
+			__be16 vlan_rpl;
+			__be16 clr_vlink;
+			__be16 link_down;
+			__be16 link_up;
+			__be16 logo;
+			__be16 flogi_req;
+			__be16 flogi_rpl;
+			__be16 fdisc_req;
+			__be16 fdisc_rpl;
+			__be16 fka_prd_chg;
+			__be16 fc_map_chg;
+			__be16 vfid_chg;
+			u8   no_fka_req;
+			u8   no_vnp;
+		} fcf_stats;
+		struct fw_fcoe_pcb_stats {
+			__be64 tx_bytes;
+			__be64 tx_frames;
+			__be64 rx_bytes;
+			__be64 rx_frames;
+			__be32 vnp_ka;
+			__be32 unsol_els_rcvd;
+			__be64 unsol_cmd_rcvd;
+			__be16 implicit_logo;
+			__be16 flogi_inv_sparm;
+			__be16 fdisc_inv_sparm;
+			__be16 flogi_rjt;
+			__be16 fdisc_rjt;
+			__be16 no_ssn;
+			__be16 mac_flt_fail;
+			__be16 inv_fr_rcvd;
+		} pcb_stats;
+		struct fw_fcoe_scb_stats {
+			__be64 tx_bytes;
+			__be64 tx_frames;
+			__be64 rx_bytes;
+			__be64 rx_frames;
+			__be32 host_abrt_req;
+			__be32 adap_auto_abrt;
+			__be32 adap_abrt_rsp;
+			__be32 host_ios_req;
+			__be16 ssn_offl_ios;
+			__be16 ssn_not_rdy_ios;
+			u8   rx_data_ddp_err;
+			u8   ddp_flt_set_err;
+			__be16 rx_data_fr_err;
+			u8   bad_st_abrt_req;
+			u8   no_io_abrt_req;
+			u8   abort_tmo;
+			u8   abort_tmo_2;
+			__be32 abort_req;
+			u8   no_ppod_res_tmo;
+			u8   bp_tmo;
+			u8   adap_auto_cls;
+			u8   no_io_cls_req;
+			__be32 host_cls_req;
+			__be64 unsol_cmd_rcvd;
+			__be32 plogi_req_rcvd;
+			__be32 prli_req_rcvd;
+			__be16 logo_req_rcvd;
+			__be16 prlo_req_rcvd;
+			__be16 plogi_rjt_rcvd;
+			__be16 prli_rjt_rcvd;
+			__be32 adisc_req_rcvd;
+			__be32 rscn_rcvd;
+			__be32 rrq_req_rcvd;
+			__be32 unsol_els_rcvd;
+			u8   adisc_rjt_rcvd;
+			u8   scr_rjt;
+			u8   ct_rjt;
+			u8   inval_bls_rcvd;
+			__be32 ba_rjt_rcvd;
+		} scb_stats;
+	} u;
+};
+
+#define FW_FCOE_STATS_CMD_FLOWID(x)	((x) << 0)
+#define FW_FCOE_STATS_CMD_FREE		(1U << 30)
+#define FW_FCOE_STATS_CMD_NSTATS(x)	((x) << 4)
+#define FW_FCOE_STATS_CMD_PORT(x)	((x) << 0)
+#define FW_FCOE_STATS_CMD_PORT_VALID	(1U << 7)
+#define FW_FCOE_STATS_CMD_IX(x)		((x) << 0)
+
+struct fw_fcoe_fcf_cmd {
+	__be32 op_to_fcfi;
+	__be32 retval_len16;
+	__be16 priority_pkd;
+	u8     mac[6];
+	u8     name_id[8];
+	u8     fabric[8];
+	__be16 vf_id;
+	__be16 max_fcoe_size;
+	u8     vlan_id;
+	u8     fc_map[3];
+	__be32 fka_adv;
+	__be32 r6;
+	u8     r7_hi;
+	u8     fpma_to_portid;
+	u8     spma_mac[6];
+	__be64 r8;
+};
+
+#define FW_FCOE_FCF_CMD_FCFI(x)		((x) << 0)
+#define FW_FCOE_FCF_CMD_FCFI_GET(x)	(((x) >> 0) & 0xfffff)
+#define FW_FCOE_FCF_CMD_PRIORITY_GET(x)	(((x) >> 0) & 0xff)
+#define FW_FCOE_FCF_CMD_FPMA_GET(x)	(((x) >> 6) & 0x1)
+#define FW_FCOE_FCF_CMD_SPMA_GET(x)	(((x) >> 5) & 0x1)
+#define FW_FCOE_FCF_CMD_LOGIN_GET(x)	(((x) >> 4) & 0x1)
+#define FW_FCOE_FCF_CMD_PORTID_GET(x)	(((x) >> 0) & 0xf)
+
+#endif /* _T4FW_API_STOR_H_ */
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index 2ebe03a..4a909d7 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -2144,7 +2144,7 @@ static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip)
 	 */
 	port_id = fip->port_id;
 	if (fip->probe_tries)
-		port_id = prandom32(&fip->rnd_state) & 0xffff;
+		port_id = prandom_u32_state(&fip->rnd_state) & 0xffff;
 	else if (!port_id)
 		port_id = fip->lp->wwpn & 0xffff;
 	if (!port_id || port_id == 0xffff)
@@ -2169,7 +2169,7 @@ static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip)
 static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip)
 {
 	fip->probe_tries = 0;
-	prandom32_seed(&fip->rnd_state, fip->lp->wwpn);
+	prandom_seed_state(&fip->rnd_state, fip->lp->wwpn);
 	fcoe_ctlr_vn_restart(fip);
 }
 
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index 192724e..138e573 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -1,6 +1,6 @@
 /*
  * HighPoint RR3xxx/4xxx controller driver for Linux
- * Copyright (C) 2006-2009 HighPoint Technologies, Inc. All Rights Reserved.
+ * Copyright (C) 2006-2012 HighPoint Technologies, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -42,7 +42,7 @@ MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx/4xxx Controller Driver");
 
 static char driver_name[] = "hptiop";
 static const char driver_name_long[] = "RocketRAID 3xxx/4xxx Controller driver";
-static const char driver_ver[] = "v1.6 (091225)";
+static const char driver_ver[] = "v1.8";
 
 static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec);
 static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag,
@@ -77,6 +77,11 @@ static int iop_wait_ready_mv(struct hptiop_hba *hba, u32 millisec)
 	return iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec);
 }
 
+static int iop_wait_ready_mvfrey(struct hptiop_hba *hba, u32 millisec)
+{
+	return iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec);
+}
+
 static void hptiop_request_callback_itl(struct hptiop_hba *hba, u32 tag)
 {
 	if (tag & IOPMU_QUEUE_ADDR_HOST_BIT)
@@ -230,6 +235,74 @@ static int iop_intr_mv(struct hptiop_hba *hba)
 	return ret;
 }
 
+static void hptiop_request_callback_mvfrey(struct hptiop_hba *hba, u32 _tag)
+{
+	u32 req_type = _tag & 0xf;
+	struct hpt_iop_request_scsi_command *req;
+
+	switch (req_type) {
+	case IOP_REQUEST_TYPE_GET_CONFIG:
+	case IOP_REQUEST_TYPE_SET_CONFIG:
+		hba->msg_done = 1;
+		break;
+
+	case IOP_REQUEST_TYPE_SCSI_COMMAND:
+		req = hba->reqs[(_tag >> 4) & 0xff].req_virt;
+		if (likely(_tag & IOPMU_QUEUE_REQUEST_RESULT_BIT))
+			req->header.result = IOP_RESULT_SUCCESS;
+		hptiop_finish_scsi_req(hba, (_tag >> 4) & 0xff, req);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static int iop_intr_mvfrey(struct hptiop_hba *hba)
+{
+	u32 _tag, status, cptr, cur_rptr;
+	int ret = 0;
+
+	if (hba->initialized)
+		writel(0, &(hba->u.mvfrey.mu->pcie_f0_int_enable));
+
+	status = readl(&(hba->u.mvfrey.mu->f0_doorbell));
+	if (status) {
+		writel(status, &(hba->u.mvfrey.mu->f0_doorbell));
+		if (status & CPU_TO_F0_DRBL_MSG_BIT) {
+			u32 msg = readl(&(hba->u.mvfrey.mu->cpu_to_f0_msg_a));
+			dprintk("received outbound msg %x\n", msg);
+			hptiop_message_callback(hba, msg);
+		}
+		ret = 1;
+	}
+
+	status = readl(&(hba->u.mvfrey.mu->isr_cause));
+	if (status) {
+		writel(status, &(hba->u.mvfrey.mu->isr_cause));
+		do {
+			cptr = *hba->u.mvfrey.outlist_cptr & 0xff;
+			cur_rptr = hba->u.mvfrey.outlist_rptr;
+			while (cur_rptr != cptr) {
+				cur_rptr++;
+				if (cur_rptr ==	hba->u.mvfrey.list_count)
+					cur_rptr = 0;
+
+				_tag = hba->u.mvfrey.outlist[cur_rptr].val;
+				BUG_ON(!(_tag & IOPMU_QUEUE_MASK_HOST_BITS));
+				hptiop_request_callback_mvfrey(hba, _tag);
+				ret = 1;
+			}
+			hba->u.mvfrey.outlist_rptr = cur_rptr;
+		} while (cptr != (*hba->u.mvfrey.outlist_cptr & 0xff));
+	}
+
+	if (hba->initialized)
+		writel(0x1010, &(hba->u.mvfrey.mu->pcie_f0_int_enable));
+
+	return ret;
+}
+
 static int iop_send_sync_request_itl(struct hptiop_hba *hba,
 					void __iomem *_req, u32 millisec)
 {
@@ -272,6 +345,26 @@ static int iop_send_sync_request_mv(struct hptiop_hba *hba,
 	return -1;
 }
 
+static int iop_send_sync_request_mvfrey(struct hptiop_hba *hba,
+					u32 size_bits, u32 millisec)
+{
+	struct hpt_iop_request_header *reqhdr =
+		hba->u.mvfrey.internal_req.req_virt;
+	u32 i;
+
+	hba->msg_done = 0;
+	reqhdr->flags |= cpu_to_le32(IOP_REQUEST_FLAG_SYNC_REQUEST);
+	hba->ops->post_req(hba, &(hba->u.mvfrey.internal_req));
+
+	for (i = 0; i < millisec; i++) {
+		iop_intr_mvfrey(hba);
+		if (hba->msg_done)
+			break;
+		msleep(1);
+	}
+	return hba->msg_done ? 0 : -1;
+}
+
 static void hptiop_post_msg_itl(struct hptiop_hba *hba, u32 msg)
 {
 	writel(msg, &hba->u.itl.iop->inbound_msgaddr0);
@@ -285,11 +378,18 @@ static void hptiop_post_msg_mv(struct hptiop_hba *hba, u32 msg)
 	readl(&hba->u.mv.regs->inbound_doorbell);
 }
 
+static void hptiop_post_msg_mvfrey(struct hptiop_hba *hba, u32 msg)
+{
+	writel(msg, &(hba->u.mvfrey.mu->f0_to_cpu_msg_a));
+	readl(&(hba->u.mvfrey.mu->f0_to_cpu_msg_a));
+}
+
 static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec)
 {
 	u32 i;
 
 	hba->msg_done = 0;
+	hba->ops->disable_intr(hba);
 	hba->ops->post_msg(hba, msg);
 
 	for (i = 0; i < millisec; i++) {
@@ -301,6 +401,7 @@ static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec)
 		msleep(1);
 	}
 
+	hba->ops->enable_intr(hba);
 	return hba->msg_done? 0 : -1;
 }
 
@@ -354,6 +455,28 @@ static int iop_get_config_mv(struct hptiop_hba *hba,
 	return 0;
 }
 
+static int iop_get_config_mvfrey(struct hptiop_hba *hba,
+				struct hpt_iop_request_get_config *config)
+{
+	struct hpt_iop_request_get_config *info = hba->u.mvfrey.config;
+
+	if (info->header.size != sizeof(struct hpt_iop_request_get_config) ||
+			info->header.type != IOP_REQUEST_TYPE_GET_CONFIG)
+		return -1;
+
+	config->interface_version = info->interface_version;
+	config->firmware_version = info->firmware_version;
+	config->max_requests = info->max_requests;
+	config->request_size = info->request_size;
+	config->max_sg_count = info->max_sg_count;
+	config->data_transfer_length = info->data_transfer_length;
+	config->alignment_mask = info->alignment_mask;
+	config->max_devices = info->max_devices;
+	config->sdram_size = info->sdram_size;
+
+	return 0;
+}
+
 static int iop_set_config_itl(struct hptiop_hba *hba,
 				struct hpt_iop_request_set_config *config)
 {
@@ -408,6 +531,29 @@ static int iop_set_config_mv(struct hptiop_hba *hba,
 	return 0;
 }
 
+static int iop_set_config_mvfrey(struct hptiop_hba *hba,
+				struct hpt_iop_request_set_config *config)
+{
+	struct hpt_iop_request_set_config *req =
+		hba->u.mvfrey.internal_req.req_virt;
+
+	memcpy(req, config, sizeof(struct hpt_iop_request_set_config));
+	req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT);
+	req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG);
+	req->header.size =
+		cpu_to_le32(sizeof(struct hpt_iop_request_set_config));
+	req->header.result = cpu_to_le32(IOP_RESULT_PENDING);
+	req->header.context = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG<<5);
+	req->header.context_hi32 = 0;
+
+	if (iop_send_sync_request_mvfrey(hba, 0, 20000)) {
+		dprintk("Set config send cmd failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
 static void hptiop_enable_intr_itl(struct hptiop_hba *hba)
 {
 	writel(~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0),
@@ -420,6 +566,13 @@ static void hptiop_enable_intr_mv(struct hptiop_hba *hba)
 		&hba->u.mv.regs->outbound_intmask);
 }
 
+static void hptiop_enable_intr_mvfrey(struct hptiop_hba *hba)
+{
+	writel(CPU_TO_F0_DRBL_MSG_BIT, &(hba->u.mvfrey.mu->f0_doorbell_enable));
+	writel(0x1, &(hba->u.mvfrey.mu->isr_enable));
+	writel(0x1010, &(hba->u.mvfrey.mu->pcie_f0_int_enable));
+}
+
 static int hptiop_initialize_iop(struct hptiop_hba *hba)
 {
 	/* enable interrupts */
@@ -502,17 +655,39 @@ static int hptiop_map_pci_bar_mv(struct hptiop_hba *hba)
 	return 0;
 }
 
+static int hptiop_map_pci_bar_mvfrey(struct hptiop_hba *hba)
+{
+	hba->u.mvfrey.config = hptiop_map_pci_bar(hba, 0);
+	if (hba->u.mvfrey.config == NULL)
+		return -1;
+
+	hba->u.mvfrey.mu = hptiop_map_pci_bar(hba, 2);
+	if (hba->u.mvfrey.mu == NULL) {
+		iounmap(hba->u.mvfrey.config);
+		return -1;
+	}
+
+	return 0;
+}
+
 static void hptiop_unmap_pci_bar_mv(struct hptiop_hba *hba)
 {
 	iounmap(hba->u.mv.regs);
 	iounmap(hba->u.mv.mu);
 }
 
+static void hptiop_unmap_pci_bar_mvfrey(struct hptiop_hba *hba)
+{
+	iounmap(hba->u.mvfrey.config);
+	iounmap(hba->u.mvfrey.mu);
+}
+
 static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg)
 {
 	dprintk("iop message 0x%x\n", msg);
 
-	if (msg == IOPMU_INBOUND_MSG0_NOP)
+	if (msg == IOPMU_INBOUND_MSG0_NOP ||
+		msg == IOPMU_INBOUND_MSG0_RESET_COMM)
 		hba->msg_done = 1;
 
 	if (!hba->initialized)
@@ -592,6 +767,7 @@ static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag,
 		memcpy(scp->sense_buffer, &req->sg_list,
 				min_t(size_t, SCSI_SENSE_BUFFERSIZE,
 					le32_to_cpu(req->dataxfer_length)));
+		goto skip_resid;
 		break;
 
 	default:
@@ -599,6 +775,10 @@ static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag,
 		break;
 	}
 
+	scsi_set_resid(scp,
+		scsi_bufflen(scp) - le32_to_cpu(req->dataxfer_length));
+
+skip_resid:
 	dprintk("scsi_done(%p)\n", scp);
 	scp->scsi_done(scp);
 	free_req(hba, &hba->reqs[tag]);
@@ -692,7 +872,8 @@ static int hptiop_buildsgl(struct scsi_cmnd *scp, struct hpt_iopsg *psg)
 	BUG_ON(HPT_SCP(scp)->sgcnt > hba->max_sg_descriptors);
 
 	scsi_for_each_sg(scp, sg, HPT_SCP(scp)->sgcnt, idx) {
-		psg[idx].pci_address = cpu_to_le64(sg_dma_address(sg));
+		psg[idx].pci_address = cpu_to_le64(sg_dma_address(sg)) |
+			hba->ops->host_phy_flag;
 		psg[idx].size = cpu_to_le32(sg_dma_len(sg));
 		psg[idx].eot = (idx == HPT_SCP(scp)->sgcnt - 1) ?
 			cpu_to_le32(1) : 0;
@@ -751,6 +932,78 @@ static void hptiop_post_req_mv(struct hptiop_hba *hba,
 		MVIOP_MU_QUEUE_ADDR_HOST_BIT | size_bit, hba);
 }
 
+static void hptiop_post_req_mvfrey(struct hptiop_hba *hba,
+					struct hptiop_request *_req)
+{
+	struct hpt_iop_request_header *reqhdr = _req->req_virt;
+	u32 index;
+
+	reqhdr->flags |= cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT |
+			IOP_REQUEST_FLAG_ADDR_BITS |
+			((_req->req_shifted_phy >> 11) & 0xffff0000));
+	reqhdr->context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT |
+			(_req->index << 4) | reqhdr->type);
+	reqhdr->context_hi32 = cpu_to_le32((_req->req_shifted_phy << 5) &
+			0xffffffff);
+
+	hba->u.mvfrey.inlist_wptr++;
+	index = hba->u.mvfrey.inlist_wptr & 0x3fff;
+
+	if (index == hba->u.mvfrey.list_count) {
+		index = 0;
+		hba->u.mvfrey.inlist_wptr &= ~0x3fff;
+		hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE;
+	}
+
+	hba->u.mvfrey.inlist[index].addr =
+			(dma_addr_t)_req->req_shifted_phy << 5;
+	hba->u.mvfrey.inlist[index].intrfc_len = (reqhdr->size + 3) / 4;
+	writel(hba->u.mvfrey.inlist_wptr,
+		&(hba->u.mvfrey.mu->inbound_write_ptr));
+	readl(&(hba->u.mvfrey.mu->inbound_write_ptr));
+}
+
+static int hptiop_reset_comm_itl(struct hptiop_hba *hba)
+{
+	return 0;
+}
+
+static int hptiop_reset_comm_mv(struct hptiop_hba *hba)
+{
+	return 0;
+}
+
+static int hptiop_reset_comm_mvfrey(struct hptiop_hba *hba)
+{
+	u32 list_count = hba->u.mvfrey.list_count;
+
+	if (iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET_COMM, 3000))
+		return -1;
+
+	/* wait 100ms for MCU ready */
+	msleep(100);
+
+	writel(cpu_to_le32(hba->u.mvfrey.inlist_phy & 0xffffffff),
+			&(hba->u.mvfrey.mu->inbound_base));
+	writel(cpu_to_le32((hba->u.mvfrey.inlist_phy >> 16) >> 16),
+			&(hba->u.mvfrey.mu->inbound_base_high));
+
+	writel(cpu_to_le32(hba->u.mvfrey.outlist_phy & 0xffffffff),
+			&(hba->u.mvfrey.mu->outbound_base));
+	writel(cpu_to_le32((hba->u.mvfrey.outlist_phy >> 16) >> 16),
+			&(hba->u.mvfrey.mu->outbound_base_high));
+
+	writel(cpu_to_le32(hba->u.mvfrey.outlist_cptr_phy & 0xffffffff),
+			&(hba->u.mvfrey.mu->outbound_shadow_base));
+	writel(cpu_to_le32((hba->u.mvfrey.outlist_cptr_phy >> 16) >> 16),
+			&(hba->u.mvfrey.mu->outbound_shadow_base_high));
+
+	hba->u.mvfrey.inlist_wptr = (list_count - 1) | CL_POINTER_TOGGLE;
+	*hba->u.mvfrey.outlist_cptr = (list_count - 1) | CL_POINTER_TOGGLE;
+	hba->u.mvfrey.outlist_rptr = list_count - 1;
+	return 0;
+}
+
 static int hptiop_queuecommand_lck(struct scsi_cmnd *scp,
 				void (*done)(struct scsi_cmnd *))
 {
@@ -771,14 +1024,15 @@ static int hptiop_queuecommand_lck(struct scsi_cmnd *scp,
 
 	_req->scp = scp;
 
-	dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%d cdb=(%x-%x-%x) "
+	dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%d cdb=(%08x-%08x-%08x-%08x) "
 			"req_index=%d, req=%p\n",
 			scp,
 			host->host_no, scp->device->channel,
 			scp->device->id, scp->device->lun,
-			((u32 *)scp->cmnd)[0],
-			((u32 *)scp->cmnd)[1],
-			((u32 *)scp->cmnd)[2],
+			cpu_to_be32(((u32 *)scp->cmnd)[0]),
+			cpu_to_be32(((u32 *)scp->cmnd)[1]),
+			cpu_to_be32(((u32 *)scp->cmnd)[2]),
+			cpu_to_be32(((u32 *)scp->cmnd)[3]),
 			_req->index, _req->req_virt);
 
 	scp->result = 0;
@@ -933,6 +1187,11 @@ static struct scsi_host_template driver_template = {
 	.change_queue_depth         = hptiop_adjust_disk_queue_depth,
 };
 
+static int hptiop_internal_memalloc_itl(struct hptiop_hba *hba)
+{
+	return 0;
+}
+
 static int hptiop_internal_memalloc_mv(struct hptiop_hba *hba)
 {
 	hba->u.mv.internal_req = dma_alloc_coherent(&hba->pcidev->dev,
@@ -943,6 +1202,63 @@ static int hptiop_internal_memalloc_mv(struct hptiop_hba *hba)
 		return -1;
 }
 
+static int hptiop_internal_memalloc_mvfrey(struct hptiop_hba *hba)
+{
+	u32 list_count = readl(&hba->u.mvfrey.mu->inbound_conf_ctl);
+	char *p;
+	dma_addr_t phy;
+
+	BUG_ON(hba->max_request_size == 0);
+
+	if (list_count == 0) {
+		BUG_ON(1);
+		return -1;
+	}
+
+	list_count >>= 16;
+
+	hba->u.mvfrey.list_count = list_count;
+	hba->u.mvfrey.internal_mem_size = 0x800 +
+			list_count * sizeof(struct mvfrey_inlist_entry) +
+			list_count * sizeof(struct mvfrey_outlist_entry) +
+			sizeof(int);
+
+	p = dma_alloc_coherent(&hba->pcidev->dev,
+			hba->u.mvfrey.internal_mem_size, &phy, GFP_KERNEL);
+	if (!p)
+		return -1;
+
+	hba->u.mvfrey.internal_req.req_virt = p;
+	hba->u.mvfrey.internal_req.req_shifted_phy = phy >> 5;
+	hba->u.mvfrey.internal_req.scp = NULL;
+	hba->u.mvfrey.internal_req.next = NULL;
+
+	p += 0x800;
+	phy += 0x800;
+
+	hba->u.mvfrey.inlist = (struct mvfrey_inlist_entry *)p;
+	hba->u.mvfrey.inlist_phy = phy;
+
+	p += list_count * sizeof(struct mvfrey_inlist_entry);
+	phy += list_count * sizeof(struct mvfrey_inlist_entry);
+
+	hba->u.mvfrey.outlist = (struct mvfrey_outlist_entry *)p;
+	hba->u.mvfrey.outlist_phy = phy;
+
+	p += list_count * sizeof(struct mvfrey_outlist_entry);
+	phy += list_count * sizeof(struct mvfrey_outlist_entry);
+
+	hba->u.mvfrey.outlist_cptr = (__le32 *)p;
+	hba->u.mvfrey.outlist_cptr_phy = phy;
+
+	return 0;
+}
+
+static int hptiop_internal_memfree_itl(struct hptiop_hba *hba)
+{
+	return 0;
+}
+
 static int hptiop_internal_memfree_mv(struct hptiop_hba *hba)
 {
 	if (hba->u.mv.internal_req) {
@@ -953,6 +1269,19 @@ static int hptiop_internal_memfree_mv(struct hptiop_hba *hba)
 		return -1;
 }
 
+static int hptiop_internal_memfree_mvfrey(struct hptiop_hba *hba)
+{
+	if (hba->u.mvfrey.internal_req.req_virt) {
+		dma_free_coherent(&hba->pcidev->dev,
+			hba->u.mvfrey.internal_mem_size,
+			hba->u.mvfrey.internal_req.req_virt,
+			(dma_addr_t)
+			hba->u.mvfrey.internal_req.req_shifted_phy << 5);
+		return 0;
+	} else
+		return -1;
+}
+
 static int __devinit hptiop_probe(struct pci_dev *pcidev,
 					const struct pci_device_id *id)
 {
@@ -1027,7 +1356,7 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev,
 		goto unmap_pci_bar;
 	}
 
-	if (hba->ops->internal_memalloc) {
+	if (hba->ops->family == MV_BASED_IOP) {
 		if (hba->ops->internal_memalloc(hba)) {
 			printk(KERN_ERR "scsi%d: internal_memalloc failed\n",
 				hba->host->host_no);
@@ -1050,6 +1379,19 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev,
 	hba->interface_version = le32_to_cpu(iop_config.interface_version);
 	hba->sdram_size = le32_to_cpu(iop_config.sdram_size);
 
+	if (hba->ops->family == MVFREY_BASED_IOP) {
+		if (hba->ops->internal_memalloc(hba)) {
+			printk(KERN_ERR "scsi%d: internal_memalloc failed\n",
+				hba->host->host_no);
+			goto unmap_pci_bar;
+		}
+		if (hba->ops->reset_comm(hba)) {
+			printk(KERN_ERR "scsi%d: reset comm failed\n",
+					hba->host->host_no);
+			goto unmap_pci_bar;
+		}
+	}
+
 	if (hba->firmware_version > 0x01020000 ||
 			hba->interface_version > 0x01020000)
 		hba->iopintf_v2 = 1;
@@ -1104,14 +1446,13 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev,
 	hba->dma_coherent = start_virt;
 	hba->dma_coherent_handle = start_phy;
 
-	if ((start_phy & 0x1f) != 0)
-	{
+	if ((start_phy & 0x1f) != 0) {
 		offset = ((start_phy + 0x1f) & ~0x1f) - start_phy;
 		start_phy += offset;
 		start_virt += offset;
 	}
 
-	hba->req_list = start_virt;
+	hba->req_list = NULL;
 	for (i = 0; i < hba->max_requests; i++) {
 		hba->reqs[i].next = NULL;
 		hba->reqs[i].req_virt = start_virt;
@@ -1132,7 +1473,6 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev,
 		goto free_request_mem;
 	}
 
-
 	scsi_scan_host(host);
 
 	dprintk("scsi%d: hptiop_probe successfully\n", hba->host->host_no);
@@ -1147,8 +1487,7 @@ free_request_irq:
 	free_irq(hba->pcidev->irq, hba);
 
 unmap_pci_bar:
-	if (hba->ops->internal_memfree)
-		hba->ops->internal_memfree(hba);
+	hba->ops->internal_memfree(hba);
 
 	hba->ops->unmap_pci_bar(hba);
 
@@ -1198,6 +1537,16 @@ static void hptiop_disable_intr_mv(struct hptiop_hba *hba)
 	readl(&hba->u.mv.regs->outbound_intmask);
 }
 
+static void hptiop_disable_intr_mvfrey(struct hptiop_hba *hba)
+{
+	writel(0, &(hba->u.mvfrey.mu->f0_doorbell_enable));
+	readl(&(hba->u.mvfrey.mu->f0_doorbell_enable));
+	writel(0, &(hba->u.mvfrey.mu->isr_enable));
+	readl(&(hba->u.mvfrey.mu->isr_enable));
+	writel(0, &(hba->u.mvfrey.mu->pcie_f0_int_enable));
+	readl(&(hba->u.mvfrey.mu->pcie_f0_int_enable));
+}
+
 static void hptiop_remove(struct pci_dev *pcidev)
 {
 	struct Scsi_Host *host = pci_get_drvdata(pcidev);
@@ -1216,8 +1565,7 @@ static void hptiop_remove(struct pci_dev *pcidev)
 			hba->dma_coherent,
 			hba->dma_coherent_handle);
 
-	if (hba->ops->internal_memfree)
-		hba->ops->internal_memfree(hba);
+	hba->ops->internal_memfree(hba);
 
 	hba->ops->unmap_pci_bar(hba);
 
@@ -1229,9 +1577,10 @@ static void hptiop_remove(struct pci_dev *pcidev)
 }
 
 static struct hptiop_adapter_ops hptiop_itl_ops = {
+	.family            = INTEL_BASED_IOP,
 	.iop_wait_ready    = iop_wait_ready_itl,
-	.internal_memalloc = NULL,
-	.internal_memfree  = NULL,
+	.internal_memalloc = hptiop_internal_memalloc_itl,
+	.internal_memfree  = hptiop_internal_memfree_itl,
 	.map_pci_bar       = hptiop_map_pci_bar_itl,
 	.unmap_pci_bar     = hptiop_unmap_pci_bar_itl,
 	.enable_intr       = hptiop_enable_intr_itl,
@@ -1242,9 +1591,12 @@ static struct hptiop_adapter_ops hptiop_itl_ops = {
 	.post_msg          = hptiop_post_msg_itl,
 	.post_req          = hptiop_post_req_itl,
 	.hw_dma_bit_mask   = 64,
+	.reset_comm        = hptiop_reset_comm_itl,
+	.host_phy_flag     = cpu_to_le64(0),
 };
 
 static struct hptiop_adapter_ops hptiop_mv_ops = {
+	.family            = MV_BASED_IOP,
 	.iop_wait_ready    = iop_wait_ready_mv,
 	.internal_memalloc = hptiop_internal_memalloc_mv,
 	.internal_memfree  = hptiop_internal_memfree_mv,
@@ -1258,6 +1610,27 @@ static struct hptiop_adapter_ops hptiop_mv_ops = {
 	.post_msg          = hptiop_post_msg_mv,
 	.post_req          = hptiop_post_req_mv,
 	.hw_dma_bit_mask   = 33,
+	.reset_comm        = hptiop_reset_comm_mv,
+	.host_phy_flag     = cpu_to_le64(0),
+};
+
+static struct hptiop_adapter_ops hptiop_mvfrey_ops = {
+	.family            = MVFREY_BASED_IOP,
+	.iop_wait_ready    = iop_wait_ready_mvfrey,
+	.internal_memalloc = hptiop_internal_memalloc_mvfrey,
+	.internal_memfree  = hptiop_internal_memfree_mvfrey,
+	.map_pci_bar       = hptiop_map_pci_bar_mvfrey,
+	.unmap_pci_bar     = hptiop_unmap_pci_bar_mvfrey,
+	.enable_intr       = hptiop_enable_intr_mvfrey,
+	.disable_intr      = hptiop_disable_intr_mvfrey,
+	.get_config        = iop_get_config_mvfrey,
+	.set_config        = iop_set_config_mvfrey,
+	.iop_intr          = iop_intr_mvfrey,
+	.post_msg          = hptiop_post_msg_mvfrey,
+	.post_req          = hptiop_post_req_mvfrey,
+	.hw_dma_bit_mask   = 64,
+	.reset_comm        = hptiop_reset_comm_mvfrey,
+	.host_phy_flag     = cpu_to_le64(1),
 };
 
 static struct pci_device_id hptiop_id_table[] = {
@@ -1283,6 +1656,8 @@ static struct pci_device_id hptiop_id_table[] = {
 	{ PCI_VDEVICE(TTI, 0x3120), (kernel_ulong_t)&hptiop_mv_ops },
 	{ PCI_VDEVICE(TTI, 0x3122), (kernel_ulong_t)&hptiop_mv_ops },
 	{ PCI_VDEVICE(TTI, 0x3020), (kernel_ulong_t)&hptiop_mv_ops },
+	{ PCI_VDEVICE(TTI, 0x4520), (kernel_ulong_t)&hptiop_mvfrey_ops },
+	{ PCI_VDEVICE(TTI, 0x4522), (kernel_ulong_t)&hptiop_mvfrey_ops },
 	{},
 };
 
diff --git a/drivers/scsi/hptiop.h b/drivers/scsi/hptiop.h
index baa648d..020619d 100644
--- a/drivers/scsi/hptiop.h
+++ b/drivers/scsi/hptiop.h
@@ -1,6 +1,6 @@
 /*
  * HighPoint RR3xxx/4xxx controller driver for Linux
- * Copyright (C) 2006-2009 HighPoint Technologies, Inc. All Rights Reserved.
+ * Copyright (C) 2006-2012 HighPoint Technologies, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -75,6 +75,45 @@ struct hpt_iopmv_regs {
 	__le32 outbound_intmask;
 };
 
+#pragma pack(1)
+struct hpt_iopmu_mvfrey {
+	__le32 reserved0[(0x4000 - 0) / 4];
+	__le32 inbound_base;
+	__le32 inbound_base_high;
+	__le32 reserved1[(0x4018 - 0x4008) / 4];
+	__le32 inbound_write_ptr;
+	__le32 reserved2[(0x402c - 0x401c) / 4];
+	__le32 inbound_conf_ctl;
+	__le32 reserved3[(0x4050 - 0x4030) / 4];
+	__le32 outbound_base;
+	__le32 outbound_base_high;
+	__le32 outbound_shadow_base;
+	__le32 outbound_shadow_base_high;
+	__le32 reserved4[(0x4088 - 0x4060) / 4];
+	__le32 isr_cause;
+	__le32 isr_enable;
+	__le32 reserved5[(0x1020c - 0x4090) / 4];
+	__le32 pcie_f0_int_enable;
+	__le32 reserved6[(0x10400 - 0x10210) / 4];
+	__le32 f0_to_cpu_msg_a;
+	__le32 reserved7[(0x10420 - 0x10404) / 4];
+	__le32 cpu_to_f0_msg_a;
+	__le32 reserved8[(0x10480 - 0x10424) / 4];
+	__le32 f0_doorbell;
+	__le32 f0_doorbell_enable;
+};
+
+struct mvfrey_inlist_entry {
+	dma_addr_t addr;
+	__le32 intrfc_len;
+	__le32 reserved;
+};
+
+struct mvfrey_outlist_entry {
+	__le32 val;
+};
+#pragma pack()
+
 #define MVIOP_MU_QUEUE_ADDR_HOST_MASK   (~(0x1full))
 #define MVIOP_MU_QUEUE_ADDR_HOST_BIT    4
 
@@ -87,6 +126,9 @@ struct hpt_iopmv_regs {
 #define MVIOP_MU_OUTBOUND_INT_MSG       1
 #define MVIOP_MU_OUTBOUND_INT_POSTQUEUE 2
 
+#define CL_POINTER_TOGGLE        0x00004000
+#define CPU_TO_F0_DRBL_MSG_BIT   0x02000000
+
 enum hpt_iopmu_message {
 	/* host-to-iop messages */
 	IOPMU_INBOUND_MSG0_NOP = 0,
@@ -95,6 +137,7 @@ enum hpt_iopmu_message {
 	IOPMU_INBOUND_MSG0_SHUTDOWN,
 	IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK,
 	IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK,
+	IOPMU_INBOUND_MSG0_RESET_COMM,
 	IOPMU_INBOUND_MSG0_MAX = 0xff,
 	/* iop-to-host messages */
 	IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_0 = 0x100,
@@ -118,6 +161,7 @@ struct hpt_iop_request_header {
 #define IOP_REQUEST_FLAG_BIST_REQUEST 2
 #define IOP_REQUEST_FLAG_REMAPPED     4
 #define IOP_REQUEST_FLAG_OUTPUT_CONTEXT 8
+#define IOP_REQUEST_FLAG_ADDR_BITS 0x40 /* flags[31:16] is phy_addr[47:32] */
 
 enum hpt_iop_request_type {
 	IOP_REQUEST_TYPE_GET_CONFIG = 0,
@@ -223,6 +267,13 @@ struct hpt_scsi_pointer {
 
 #define HPT_SCP(scp) ((struct hpt_scsi_pointer *)&(scp)->SCp)
 
+enum hptiop_family {
+	UNKNOWN_BASED_IOP,
+	INTEL_BASED_IOP,
+	MV_BASED_IOP,
+	MVFREY_BASED_IOP
+} ;
+
 struct hptiop_hba {
 	struct hptiop_adapter_ops *ops;
 	union {
@@ -236,6 +287,22 @@ struct hptiop_hba {
 			void *internal_req;
 			dma_addr_t internal_req_phy;
 		} mv;
+		struct {
+			struct hpt_iop_request_get_config __iomem *config;
+			struct hpt_iopmu_mvfrey __iomem *mu;
+
+			int internal_mem_size;
+			struct hptiop_request internal_req;
+			int list_count;
+			struct mvfrey_inlist_entry *inlist;
+			dma_addr_t inlist_phy;
+			__le32 inlist_wptr;
+			struct mvfrey_outlist_entry *outlist;
+			dma_addr_t outlist_phy;
+			__le32 *outlist_cptr; /* copy pointer shadow */
+			dma_addr_t outlist_cptr_phy;
+			__le32 outlist_rptr;
+		} mvfrey;
 	} u;
 
 	struct Scsi_Host *host;
@@ -283,6 +350,7 @@ struct hpt_ioctl_k {
 };
 
 struct hptiop_adapter_ops {
+	enum hptiop_family family;
 	int  (*iop_wait_ready)(struct hptiop_hba *hba, u32 millisec);
 	int  (*internal_memalloc)(struct hptiop_hba *hba);
 	int  (*internal_memfree)(struct hptiop_hba *hba);
@@ -298,6 +366,8 @@ struct hptiop_adapter_ops {
 	void (*post_msg)(struct hptiop_hba *hba, u32 msg);
 	void (*post_req)(struct hptiop_hba *hba, struct hptiop_request *_req);
 	int  hw_dma_bit_mask;
+	int  (*reset_comm)(struct hptiop_hba *hba);
+	__le64  host_phy_flag;
 };
 
 #define HPT_IOCTL_RESULT_OK         0
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index efc6e72..aec2e0d 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -1800,7 +1800,7 @@ out:
  * @dev:domain device to be detect.
  * @src_dev: the device which originated BROADCAST(CHANGE).
  *
- * Add self-configuration expander suport. Suppose two expander cascading,
+ * Add self-configuration expander support. Suppose two expander cascading,
  * when the first level expander is self-configuring, hotplug the disks in
  * second level expander, BROADCAST(CHANGE) will not only be originated
  * in the second level expander, but also be originated in the first level
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 69b5993..df4c13a 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -689,6 +689,7 @@ struct lpfc_hba {
 #define LPFC_FCF_PRIORITY 2	/* Priority fcf failover */
 	uint32_t cfg_fcf_failover_policy;
 	uint32_t cfg_fcp_io_sched;
+	uint32_t cfg_fcp2_no_tgt_reset;
 	uint32_t cfg_cr_delay;
 	uint32_t cfg_cr_count;
 	uint32_t cfg_multi_ring_support;
@@ -714,6 +715,7 @@ struct lpfc_hba {
 	uint32_t cfg_log_verbose;
 	uint32_t cfg_aer_support;
 	uint32_t cfg_sriov_nr_virtfn;
+	uint32_t cfg_request_firmware_upgrade;
 	uint32_t cfg_iocb_cnt;
 	uint32_t cfg_suppress_link_up;
 #define LPFC_INITIALIZE_LINK              0	/* do normal init_link mbox */
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index ad16e54..a364cae 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -3618,6 +3618,77 @@ static DEVICE_ATTR(lpfc_sriov_nr_virtfn, S_IRUGO | S_IWUSR,
 		   lpfc_sriov_nr_virtfn_show, lpfc_sriov_nr_virtfn_store);
 
 /**
+ * lpfc_request_firmware_store - Request for Linux generic firmware upgrade
+ *
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: containing the string the number of vfs to be enabled.
+ * @count: unused variable.
+ *
+ * Description:
+ *
+ * Returns:
+ * length of the buf on success if val is in range the intended mode
+ * is supported.
+ * -EINVAL if val out of range or intended mode is not supported.
+ **/
+static ssize_t
+lpfc_request_firmware_upgrade_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	struct Scsi_Host *shost = class_to_shost(dev);
+	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
+	struct lpfc_hba *phba = vport->phba;
+	int val = 0, rc = -EINVAL;
+
+	/* Sanity check on user data */
+	if (!isdigit(buf[0]))
+		return -EINVAL;
+	if (sscanf(buf, "%i", &val) != 1)
+		return -EINVAL;
+	if (val != 1)
+		return -EINVAL;
+
+	rc = lpfc_sli4_request_firmware_update(phba, RUN_FW_UPGRADE);
+	if (rc)
+		rc = -EPERM;
+	else
+		rc = strlen(buf);
+	return rc;
+}
+
+static int lpfc_req_fw_upgrade;
+module_param(lpfc_req_fw_upgrade, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(lpfc_req_fw_upgrade, "Enable Linux generic firmware upgrade");
+lpfc_param_show(request_firmware_upgrade)
+
+/**
+ * lpfc_request_firmware_upgrade_init - Enable initial linux generic fw upgrade
+ * @phba: lpfc_hba pointer.
+ * @val: 0 or 1.
+ *
+ * Description:
+ * Set the initial Linux generic firmware upgrade enable or disable flag.
+ *
+ * Returns:
+ * zero if val saved.
+ * -EINVAL val out of range
+ **/
+static int
+lpfc_request_firmware_upgrade_init(struct lpfc_hba *phba, int val)
+{
+	if (val >= 0 && val <= 1) {
+		phba->cfg_request_firmware_upgrade = val;
+		return 0;
+	}
+	return -EINVAL;
+}
+static DEVICE_ATTR(lpfc_req_fw_upgrade, S_IRUGO | S_IWUSR,
+		   lpfc_request_firmware_upgrade_show,
+		   lpfc_request_firmware_upgrade_store);
+
+/**
  * lpfc_fcp_imax_store
  *
  * @dev: class device that is converted into a Scsi_host.
@@ -3788,6 +3859,16 @@ LPFC_ATTR_RW(fcp_io_sched, 0, 0, 1, "Determine scheduling algrithmn for "
 		"issuing commands [0] - Round Robin, [1] - Current CPU");
 
 /*
+# lpfc_fcp2_no_tgt_reset: Determine bus reset behavior
+# range is [0,1]. Default value is 0.
+# For [0], bus reset issues target reset to ALL devices
+# For [1], bus reset issues target reset to non-FCP2 devices
+*/
+LPFC_ATTR_RW(fcp2_no_tgt_reset, 0, 0, 1, "Determine bus reset behavior for "
+	     "FCP2 devices [0] - issue tgt reset, [1] - no tgt reset");
+
+
+/*
 # lpfc_cr_delay & lpfc_cr_count: Default values for I/O colaesing
 # cr_delay (msec) or cr_count outstanding commands. cr_delay can take
 # value [0,63]. cr_count can take value [1,255]. Default value of cr_delay
@@ -4029,6 +4110,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
 	&dev_attr_lpfc_scan_down,
 	&dev_attr_lpfc_link_speed,
 	&dev_attr_lpfc_fcp_io_sched,
+	&dev_attr_lpfc_fcp2_no_tgt_reset,
 	&dev_attr_lpfc_cr_delay,
 	&dev_attr_lpfc_cr_count,
 	&dev_attr_lpfc_multi_ring_support,
@@ -4069,6 +4151,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
 	&dev_attr_lpfc_aer_support,
 	&dev_attr_lpfc_aer_state_cleanup,
 	&dev_attr_lpfc_sriov_nr_virtfn,
+	&dev_attr_lpfc_req_fw_upgrade,
 	&dev_attr_lpfc_suppress_link_up,
 	&dev_attr_lpfc_iocb_cnt,
 	&dev_attr_iocb_hw,
@@ -5019,6 +5102,7 @@ void
 lpfc_get_cfgparam(struct lpfc_hba *phba)
 {
 	lpfc_fcp_io_sched_init(phba, lpfc_fcp_io_sched);
+	lpfc_fcp2_no_tgt_reset_init(phba, lpfc_fcp2_no_tgt_reset);
 	lpfc_cr_delay_init(phba, lpfc_cr_delay);
 	lpfc_cr_count_init(phba, lpfc_cr_count);
 	lpfc_multi_ring_support_init(phba, lpfc_multi_ring_support);
@@ -5051,6 +5135,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
 	lpfc_hba_log_verbose_init(phba, lpfc_log_verbose);
 	lpfc_aer_support_init(phba, lpfc_aer_support);
 	lpfc_sriov_nr_virtfn_init(phba, lpfc_sriov_nr_virtfn);
+	lpfc_request_firmware_upgrade_init(phba, lpfc_req_fw_upgrade);
 	lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up);
 	lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt);
 	phba->cfg_enable_dss = 1;
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 4380a44..69d66e3 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -468,3 +468,4 @@ void lpfc_sli4_node_prep(struct lpfc_hba *);
 int lpfc_sli4_xri_sgl_update(struct lpfc_hba *);
 void lpfc_free_sgl_list(struct lpfc_hba *, struct list_head *);
 uint32_t lpfc_sli_port_speed_get(struct lpfc_hba *);
+int lpfc_sli4_request_firmware_update(struct lpfc_hba *, uint8_t);
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 7ffabb7..65f9fb6 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -634,7 +634,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 		/* Check for retry */
 		if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
 			if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
-			    (irsp->un.ulpWord[4] && IOERR_PARAM_MASK) !=
+			    (irsp->un.ulpWord[4] & IOERR_PARAM_MASK) !=
 			    IOERR_NO_RESOURCES)
 				vport->fc_ns_retry++;
 
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index f19e9b6..b9440de 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1182,8 +1182,6 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 	sp->cmn.w2.r_a_tov = 0;
 	sp->cmn.virtual_fabric_support = 0;
 	sp->cls1.classValid = 0;
-	sp->cls2.seqDelivery = 1;
-	sp->cls3.seqDelivery = 1;
 	if (sp->cmn.fcphLow < FC_PH3)
 		sp->cmn.fcphLow = FC_PH3;
 	if (sp->cmn.fcphHigh < FC_PH3)
@@ -1198,7 +1196,13 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 			/* Set the fcfi to the fcfi we registered with */
 			elsiocb->iocb.ulpContext = phba->fcf.fcfi;
 		}
+		/* Can't do SLI4 class2 without support sequence coalescing */
+		sp->cls2.classValid = 0;
+		sp->cls2.seqDelivery = 0;
 	} else {
+		/* Historical, setting sequential-delivery bit for SLI3 */
+		sp->cls2.seqDelivery = (sp->cls2.classValid) ? 1 : 0;
+		sp->cls3.seqDelivery = (sp->cls3.classValid) ? 1 : 0;
 		if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
 			sp->cmn.request_multiple_Nport = 1;
 			/* For FLOGI, Let FLOGI rsp set the NPortID for VPI 0 */
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 2cdeb54..a47cfbd 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -3219,6 +3219,9 @@ struct wqe_common {
 #define wqe_dif_SHIFT         0
 #define wqe_dif_MASK          0x00000003
 #define wqe_dif_WORD          word7
+#define LPFC_WQE_DIF_PASSTHRU	1
+#define LPFC_WQE_DIF_STRIP	2
+#define LPFC_WQE_DIF_INSERT	3
 #define wqe_ct_SHIFT          2
 #define wqe_ct_MASK           0x00000003
 #define wqe_ct_WORD           word7
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 7dc4218..c20eec7 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -3854,7 +3854,7 @@ static void
 lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli)
 {
 	char port_name;
-	char message[80];
+	char message[128];
 	uint8_t status;
 	struct lpfc_acqe_misconfigured_event *misconfigured;
 
@@ -9450,7 +9450,7 @@ lpfc_write_firmware(const struct firmware *fw, void *context)
 	struct lpfc_dmabuf *dmabuf, *next;
 	uint32_t offset = 0, temp_offset = 0;
 
-	/* It can be null, sanity check */
+	/* It can be null in no-wait mode, sanity check */
 	if (!fw) {
 		rc = -ENXIO;
 		goto out;
@@ -9528,11 +9528,48 @@ release_out:
 	release_firmware(fw);
 out:
 	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-			"3024 Firmware update done: %d.", rc);
+			"3024 Firmware update done: %d.\n", rc);
 	return;
 }
 
 /**
+ * lpfc_sli4_request_firmware_update - Request linux generic firmware upgrade
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is called to perform Linux generic firmware upgrade on device
+ * that supports such feature.
+ **/
+int
+lpfc_sli4_request_firmware_update(struct lpfc_hba *phba, uint8_t fw_upgrade)
+{
+	uint8_t file_name[ELX_MODEL_NAME_SIZE];
+	int ret;
+	const struct firmware *fw;
+
+	/* Only supported on SLI4 interface type 2 for now */
+	if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
+	    LPFC_SLI_INTF_IF_TYPE_2)
+		return -EPERM;
+
+	snprintf(file_name, ELX_MODEL_NAME_SIZE, "%s.grp", phba->ModelName);
+
+	if (fw_upgrade == INT_FW_UPGRADE) {
+		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					file_name, &phba->pcidev->dev,
+					GFP_KERNEL, (void *)phba,
+					lpfc_write_firmware);
+	} else if (fw_upgrade == RUN_FW_UPGRADE) {
+		ret = request_firmware(&fw, file_name, &phba->pcidev->dev);
+		if (!ret)
+			lpfc_write_firmware(fw, (void *)phba);
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/**
  * lpfc_pci_probe_one_s4 - PCI probe func to reg SLI-4 device to PCI subsys
  * @pdev: pointer to PCI device
  * @pid: pointer to PCI device identifier
@@ -9560,7 +9597,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
 	uint32_t cfg_mode, intr_mode;
 	int mcnt;
 	int adjusted_fcp_io_channel;
-	uint8_t file_name[ELX_MODEL_NAME_SIZE];
 
 	/* Allocate memory for HBA structure */
 	phba = lpfc_hba_alloc(pdev);
@@ -9703,16 +9739,9 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
 	/* Perform post initialization setup */
 	lpfc_post_init_setup(phba);
 
-	/* check for firmware upgrade or downgrade (if_type 2 only) */
-	if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
-	    LPFC_SLI_INTF_IF_TYPE_2) {
-		snprintf(file_name, ELX_MODEL_NAME_SIZE, "%s.grp",
-			 phba->ModelName);
-		ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
-					file_name, &phba->pcidev->dev,
-					GFP_KERNEL, (void *)phba,
-					lpfc_write_firmware);
-	}
+	/* check for firmware upgrade or downgrade */
+	if (phba->cfg_request_firmware_upgrade)
+		ret = lpfc_sli4_request_firmware_update(phba, INT_FW_UPGRADE);
 
 	/* Check if there are static vports to be created. */
 	lpfc_create_static_vport(phba);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 7f45ac9..60e5a17 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -3227,6 +3227,21 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
 		}
 	}
 
+	switch (scsi_get_prot_op(scsi_cmnd)) {
+	case SCSI_PROT_WRITE_STRIP:
+	case SCSI_PROT_READ_STRIP:
+		lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_STRIP;
+		break;
+	case SCSI_PROT_WRITE_INSERT:
+	case SCSI_PROT_READ_INSERT:
+		lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_INSERT;
+		break;
+	case SCSI_PROT_WRITE_PASS:
+	case SCSI_PROT_READ_PASS:
+		lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_PASS;
+		break;
+	}
+
 	fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd);
 
 	fcp_cmnd->fcpDl = be32_to_cpu(fcpdl);
@@ -3236,7 +3251,6 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
 	 * we need to set word 4 of IOCB here
 	 */
 	iocb_cmd->un.fcpi.fcpi_parm = fcpdl;
-	lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF;
 
 	return 0;
 err:
@@ -4914,6 +4928,9 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
 		list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
 			if (!NLP_CHK_NODE_ACT(ndlp))
 				continue;
+			if (vport->phba->cfg_fcp2_no_tgt_reset &&
+			    (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE))
+				continue;
 			if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
 			    ndlp->nlp_sid == i &&
 			    ndlp->rport) {
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index d7f3313..624eab3 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -8068,10 +8068,6 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
 		       LPFC_WQE_LENLOC_WORD4);
 		bf_set(wqe_ebde_cnt, &wqe->fcp_iwrite.wqe_com, 0);
 		bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpPU);
-		if (iocbq->iocb_flag & LPFC_IO_DIF) {
-			iocbq->iocb_flag &= ~LPFC_IO_DIF;
-			bf_set(wqe_dif, &wqe->generic.wqe_com, 1);
-		}
 		bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 1);
 		break;
 	case CMD_FCP_IREAD64_CR:
@@ -8091,10 +8087,6 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
 		       LPFC_WQE_LENLOC_WORD4);
 		bf_set(wqe_ebde_cnt, &wqe->fcp_iread.wqe_com, 0);
 		bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpPU);
-		if (iocbq->iocb_flag & LPFC_IO_DIF) {
-			iocbq->iocb_flag &= ~LPFC_IO_DIF;
-			bf_set(wqe_dif, &wqe->generic.wqe_com, 1);
-		}
 		bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 1);
 		break;
 	case CMD_FCP_ICMND64_CR:
@@ -8304,6 +8296,14 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
 		break;
 	}
 
+	if (iocbq->iocb_flag & LPFC_IO_DIF_PASS)
+		bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_PASSTHRU);
+	else if (iocbq->iocb_flag & LPFC_IO_DIF_STRIP)
+		bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_STRIP);
+	else if (iocbq->iocb_flag & LPFC_IO_DIF_INSERT)
+		bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_INSERT);
+	iocbq->iocb_flag &= ~(LPFC_IO_DIF_PASS | LPFC_IO_DIF_STRIP |
+			      LPFC_IO_DIF_INSERT);
 	bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag);
 	bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag);
 	wqe->generic.wqe_com.abort_tag = abort_tag;
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index 2f48d00..9d2e0c6 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -69,7 +69,9 @@ struct lpfc_iocbq {
 #define LPFC_USE_FCPWQIDX	0x80    /* Submit to specified FCPWQ index */
 #define DSS_SECURITY_OP		0x100	/* security IO */
 #define LPFC_IO_ON_TXCMPLQ	0x200	/* The IO is still on the TXCMPLQ */
-#define LPFC_IO_DIF		0x400	/* T10 DIF IO */
+#define LPFC_IO_DIF_PASS	0x400	/* T10 DIF IO pass-thru prot */
+#define LPFC_IO_DIF_STRIP	0x800	/* T10 DIF IO strip prot */
+#define LPFC_IO_DIF_INSERT	0x1000	/* T10 DIF IO insert prot */
 
 #define LPFC_FIP_ELS_ID_MASK	0xc000	/* ELS_ID range 0-3, non-shifted mask */
 #define LPFC_FIP_ELS_ID_SHIFT	14
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index f44a06a..44c427a 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -82,6 +82,9 @@
 
 #define LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT 12000
 
+#define INT_FW_UPGRADE	0
+#define RUN_FW_UPGRADE	1
+
 enum lpfc_sli4_queue_type {
 	LPFC_EQ,
 	LPFC_GCQ,
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 0c21491..ba596e8 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.3.35"
+#define LPFC_DRIVER_VERSION "8.3.36"
 #define LPFC_DRIVER_NAME		"lpfc"
 
 /* Used for SLI 2/3 */
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index d4ed9eb..4375417 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -97,9 +97,37 @@ struct osd_dev_handle {
 
 static DEFINE_IDA(osd_minor_ida);
 
+/*
+ * scsi sysfs attribute operations
+ */
+static ssize_t osdname_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	struct osd_uld_device *ould = container_of(dev, struct osd_uld_device,
+						   class_dev);
+	return sprintf(buf, "%s\n", ould->odi.osdname);
+}
+
+static ssize_t systemid_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	struct osd_uld_device *ould = container_of(dev, struct osd_uld_device,
+						   class_dev);
+
+	memcpy(buf, ould->odi.systemid, ould->odi.systemid_len);
+	return ould->odi.systemid_len;
+}
+
+static struct device_attribute osd_uld_attrs[] = {
+	__ATTR(osdname, S_IRUGO, osdname_show, NULL),
+	__ATTR(systemid, S_IRUGO, systemid_show, NULL),
+	__ATTR_NULL,
+};
+
 static struct class osd_uld_class = {
 	.owner		= THIS_MODULE,
 	.name		= "scsi_osd",
+	.dev_attrs	= osd_uld_attrs,
 };
 
 /*
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 5733811..9d1c7b5 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -251,7 +251,7 @@ qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
 	/* Read all mbox registers? */
 	mboxes = (1 << ha->mbx_count) - 1;
 	if (!ha->mcp)
-		ql_dbg(ql_dbg_async, vha, 0x5001, "MBX pointer ERRROR.\n");
+		ql_dbg(ql_dbg_async, vha, 0x5001, "MBX pointer ERROR.\n");
 	else
 		mboxes = ha->mcp->in_mb;
 
@@ -2318,7 +2318,7 @@ qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
 	/* Read all mbox registers? */
 	mboxes = (1 << ha->mbx_count) - 1;
 	if (!ha->mcp)
-		ql_dbg(ql_dbg_async, vha, 0x504e, "MBX pointer ERRROR.\n");
+		ql_dbg(ql_dbg_async, vha, 0x504e, "MBX pointer ERROR.\n");
 	else
 		mboxes = ha->mcp->in_mb;
 
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index 14cd361..f5e297c 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -955,7 +955,7 @@ qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp)
 	}
 	if (loops >= 50000) {
 		ql_log(ql_log_fatal, vha, 0x00b9,
-		    "Failed to aquire SEM2 lock.\n");
+		    "Failed to acquire SEM2 lock.\n");
 		return -1;
 	}
 	ret = qla82xx_do_rom_fast_read(ha, addr, valp);
@@ -1122,7 +1122,7 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
 		long data;
 	};
 
-	/* Halt all the indiviual PEGs and other blocks of the ISP */
+	/* Halt all the individual PEGs and other blocks of the ISP */
 	qla82xx_rom_lock(ha);
 
 	/* disable all I2Q */
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 62aa558..c837fe0 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -73,7 +73,7 @@ enum fcp_resp_rsp_codes {
 #define FCP_PTA_SIMPLE      0   /* simple task attribute */
 #define FCP_PTA_HEADQ       1   /* head of queue task attribute */
 #define FCP_PTA_ORDERED     2   /* ordered task attribute */
-#define FCP_PTA_ACA         4   /* auto. contigent allegiance */
+#define FCP_PTA_ACA         4   /* auto. contingent allegiance */
 #define FCP_PTA_MASK        7   /* mask for task attribute field */
 #define FCP_PRI_SHIFT       3   /* priority field starts in bit 3 */
 #define FCP_PRI_RESVD_MASK  0x80        /* reserved bits in priority field */
@@ -1264,8 +1264,27 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,
 	struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess)
 {
 	struct qla_hw_data *ha = vha->hw;
+	struct se_session *se_sess = sess->se_sess;
 	struct qla_tgt_mgmt_cmd *mcmd;
+	struct se_cmd *se_cmd;
+	u32 lun = 0;
 	int rc;
+	bool found_lun = false;
+
+	spin_lock(&se_sess->sess_cmd_lock);
+	list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) {
+		struct qla_tgt_cmd *cmd =
+			container_of(se_cmd, struct qla_tgt_cmd, se_cmd);
+		if (cmd->tag == abts->exchange_addr_to_abort) {
+			lun = cmd->unpacked_lun;
+			found_lun = true;
+			break;
+		}
+	}
+	spin_unlock(&se_sess->sess_cmd_lock);
+
+	if (!found_lun)
+		return -ENOENT;
 
 	ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f,
 	    "qla_target(%d): task abort (tag=%d)\n",
@@ -1283,7 +1302,7 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,
 	mcmd->sess = sess;
 	memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts));
 
-	rc = ha->tgt.tgt_ops->handle_tmr(mcmd, 0, TMR_ABORT_TASK,
+	rc = ha->tgt.tgt_ops->handle_tmr(mcmd, lun, TMR_ABORT_TASK,
 	    abts->exchange_addr_to_abort);
 	if (rc != 0) {
 		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf052,
@@ -3980,7 +3999,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
 	case MBA_RSP_TRANSFER_ERR:	/* Response Transfer Error */
 		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03a,
 		    "qla_target(%d): System error async event %#x "
-		    "occured", vha->vp_idx, code);
+		    "occurred", vha->vp_idx, code);
 		break;
 	case MBA_WAKEUP_THRES:		/* Request Queue Wake-up. */
 		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
@@ -3989,7 +4008,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
 	case MBA_LOOP_UP:
 	{
 		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03b,
-		    "qla_target(%d): Async LOOP_UP occured "
+		    "qla_target(%d): Async LOOP_UP occurred "
 		    "(m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx,
 		    le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
 		    le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
@@ -4006,7 +4025,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
 	case MBA_LIP_RESET:
 	case MBA_RSCN_UPDATE:
 		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03c,
-		    "qla_target(%d): Async event %#x occured "
+		    "qla_target(%d): Async event %#x occurred "
 		    "(m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx, code,
 		    le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
 		    le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
@@ -4015,7 +4034,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
 	case MBA_PORT_UPDATE:
 		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03d,
 		    "qla_target(%d): Port update async event %#x "
-		    "occured: updating the ports database (m[0]=%x, m[1]=%x, "
+		    "occurred: updating the ports database (m[0]=%x, m[1]=%x, "
 		    "m[2]=%x, m[3]=%x)", vha->vp_idx, code,
 		    le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
 		    le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
@@ -4031,7 +4050,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
 
 	default:
 		ql_dbg(ql_dbg_tgt_mgt, vha, 0xf040,
-		    "qla_target(%d): Async event %#x occured: "
+		    "qla_target(%d): Async event %#x occurred: "
 		    "ignore (m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx,
 		    code, le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
 		    le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 3d74f2f..d182c96 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -367,7 +367,7 @@ static struct se_node_acl *tcm_qla2xxx_alloc_fabric_acl(
 
 	nacl = kzalloc(sizeof(struct tcm_qla2xxx_nacl), GFP_KERNEL);
 	if (!nacl) {
-		pr_err("Unable to alocate struct tcm_qla2xxx_nacl\n");
+		pr_err("Unable to allocate struct tcm_qla2xxx_nacl\n");
 		return NULL;
 	}
 
@@ -620,8 +620,8 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
 			return;
 		}
 
-		cmd->se_cmd.scsi_sense_reason = TCM_CHECK_CONDITION_ABORT_CMD;
-		transport_generic_request_failure(&cmd->se_cmd);
+		transport_generic_request_failure(&cmd->se_cmd,
+						  TCM_CHECK_CONDITION_ABORT_CMD);
 		return;
 	}
 
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 352bc77..c5a189c 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1011,7 +1011,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
 		SCpnt->cmnd[29] = (unsigned char) (this_count >> 16) & 0xff;
 		SCpnt->cmnd[30] = (unsigned char) (this_count >> 8) & 0xff;
 		SCpnt->cmnd[31] = (unsigned char) this_count & 0xff;
-	} else if (block > 0xffffffff) {
+	} else if (sdp->use_16_for_rw) {
 		SCpnt->cmnd[0] += READ_16 - READ_6;
 		SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0);
 		SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0;
@@ -2203,6 +2203,8 @@ got_data:
 		}
 	}
 
+	sdp->use_16_for_rw = (sdkp->capacity > 0xffffffff);
+
 	/* Rescale capacity to 512-byte units */
 	if (sector_size == 4096)
 		sdkp->capacity <<= 3;
@@ -3116,10 +3118,6 @@ static int __init init_sd(void)
 	if (err)
 		goto err_out;
 
-	err = scsi_register_driver(&sd_template.gendrv);
-	if (err)
-		goto err_out_class;
-
 	sd_cdb_cache = kmem_cache_create("sd_ext_cdb", SD_EXT_CDB_SIZE,
 					 0, 0, NULL);
 	if (!sd_cdb_cache) {
@@ -3133,8 +3131,15 @@ static int __init init_sd(void)
 		goto err_out_cache;
 	}
 
+	err = scsi_register_driver(&sd_template.gendrv);
+	if (err)
+		goto err_out_driver;
+
 	return 0;
 
+err_out_driver:
+	mempool_destroy(sd_cdb_pool);
+
 err_out_cache:
 	kmem_cache_destroy(sd_cdb_cache);
 
@@ -3157,10 +3162,10 @@ static void __exit exit_sd(void)
 
 	SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n"));
 
+	scsi_unregister_driver(&sd_template.gendrv);
 	mempool_destroy(sd_cdb_pool);
 	kmem_cache_destroy(sd_cdb_cache);
 
-	scsi_unregister_driver(&sd_template.gendrv);
 	class_unregister(&sd_disk_class);
 
 	for (i = 0; i < SD_MAJORS; i++)
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 595af1a..74ab67a 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -215,7 +215,7 @@ static void virtscsi_ctrl_done(struct virtqueue *vq)
 static int virtscsi_kick_event(struct virtio_scsi *vscsi,
 			       struct virtio_scsi_event_node *event_node)
 {
-	int ret;
+	int err;
 	struct scatterlist sg;
 	unsigned long flags;
 
@@ -223,13 +223,14 @@ static int virtscsi_kick_event(struct virtio_scsi *vscsi,
 
 	spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
 
-	ret = virtqueue_add_buf(vscsi->event_vq.vq, &sg, 0, 1, event_node, GFP_ATOMIC);
-	if (ret >= 0)
+	err = virtqueue_add_buf(vscsi->event_vq.vq, &sg, 0, 1, event_node,
+				GFP_ATOMIC);
+	if (!err)
 		virtqueue_kick(vscsi->event_vq.vq);
 
 	spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags);
 
-	return ret;
+	return err;
 }
 
 static int virtscsi_kick_event_all(struct virtio_scsi *vscsi)
@@ -410,22 +411,23 @@ static int virtscsi_kick_cmd(struct virtio_scsi_target_state *tgt,
 {
 	unsigned int out_num, in_num;
 	unsigned long flags;
-	int ret;
+	int err;
+	bool needs_kick = false;
 
 	spin_lock_irqsave(&tgt->tgt_lock, flags);
 	virtscsi_map_cmd(tgt, cmd, &out_num, &in_num, req_size, resp_size);
 
 	spin_lock(&vq->vq_lock);
-	ret = virtqueue_add_buf(vq->vq, tgt->sg, out_num, in_num, cmd, gfp);
+	err = virtqueue_add_buf(vq->vq, tgt->sg, out_num, in_num, cmd, gfp);
 	spin_unlock(&tgt->tgt_lock);
-	if (ret >= 0)
-		ret = virtqueue_kick_prepare(vq->vq);
+	if (!err)
+		needs_kick = virtqueue_kick_prepare(vq->vq);
 
 	spin_unlock_irqrestore(&vq->vq_lock, flags);
 
-	if (ret > 0)
+	if (needs_kick)
 		virtqueue_notify(vq->vq);
-	return ret;
+	return err;
 }
 
 static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
@@ -467,8 +469,10 @@ static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
 
 	if (virtscsi_kick_cmd(tgt, &vscsi->req_vq, cmd,
 			      sizeof cmd->req.cmd, sizeof cmd->resp.cmd,
-			      GFP_ATOMIC) >= 0)
+			      GFP_ATOMIC) == 0)
 		ret = 0;
+	else
+		mempool_free(cmd, virtscsi_cmd_pool);
 
 out:
 	return ret;
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
index 07e9fb4..5aedcdf 100644
--- a/drivers/sh/clk/cpg.c
+++ b/drivers/sh/clk/cpg.c
@@ -361,3 +361,88 @@ int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
 	return sh_clk_div_register_ops(clks, nr, table,
 				       &sh_clk_div4_reparent_clk_ops);
 }
+
+/* FSI-DIV */
+static unsigned long fsidiv_recalc(struct clk *clk)
+{
+	u32 value;
+
+	value = __raw_readl(clk->mapping->base);
+
+	value >>= 16;
+	if (value < 2)
+		return clk->parent->rate;
+
+	return clk->parent->rate / value;
+}
+
+static long fsidiv_round_rate(struct clk *clk, unsigned long rate)
+{
+	return clk_rate_div_range_round(clk, 1, 0xffff, rate);
+}
+
+static void fsidiv_disable(struct clk *clk)
+{
+	__raw_writel(0, clk->mapping->base);
+}
+
+static int fsidiv_enable(struct clk *clk)
+{
+	u32 value;
+
+	value  = __raw_readl(clk->mapping->base) >> 16;
+	if (value < 2)
+		return 0;
+
+	__raw_writel((value << 16) | 0x3, clk->mapping->base);
+
+	return 0;
+}
+
+static int fsidiv_set_rate(struct clk *clk, unsigned long rate)
+{
+	int idx;
+
+	idx = (clk->parent->rate / rate) & 0xffff;
+	if (idx < 2)
+		__raw_writel(0, clk->mapping->base);
+	else
+		__raw_writel(idx << 16, clk->mapping->base);
+
+	return 0;
+}
+
+static struct sh_clk_ops fsidiv_clk_ops = {
+	.recalc		= fsidiv_recalc,
+	.round_rate	= fsidiv_round_rate,
+	.set_rate	= fsidiv_set_rate,
+	.enable		= fsidiv_enable,
+	.disable	= fsidiv_disable,
+};
+
+int __init sh_clk_fsidiv_register(struct clk *clks, int nr)
+{
+	struct clk_mapping *map;
+	int i;
+
+	for (i = 0; i < nr; i++) {
+
+		map = kzalloc(sizeof(struct clk_mapping), GFP_KERNEL);
+		if (!map) {
+			pr_err("%s: unable to alloc memory\n", __func__);
+			return -ENOMEM;
+		}
+
+		/* clks[i].enable_reg came from SH_CLK_FSIDIV() */
+		map->phys		= (phys_addr_t)clks[i].enable_reg;
+		map->len		= 8;
+
+		clks[i].enable_reg	= 0; /* remove .enable_reg */
+		clks[i].ops		= &fsidiv_clk_ops;
+		clks[i].mapping		= map;
+
+		clk_register(&clks[i]);
+	}
+
+	return 0;
+}
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 1acae35..3cbc9fb 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -385,6 +385,20 @@ config SPI_MXS
 	help
 	  SPI driver for Freescale MXS devices.
 
+config SPI_TEGRA20_SFLASH
+	tristate "Nvidia Tegra20 Serial flash Controller"
+	depends on ARCH_TEGRA
+	help
+	  SPI driver for Nvidia Tegra20 Serial flash Controller interface.
+	  The main usecase of this controller is to use spi flash as boot
+	  device.
+
+config SPI_TEGRA20_SLINK
+	tristate "Nvidia Tegra20/Tegra30 SLINK Controller"
+	depends on ARCH_TEGRA && TEGRA20_APB_DMA
+	help
+	  SPI driver for Nvidia Tegra20/Tegra30 SLINK Controller interface.
+
 config SPI_TI_SSP
 	tristate "TI Sequencer Serial Port - SPI Support"
 	depends on MFD_TI_SSP
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index c48df47..9f6b3d8 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -60,10 +60,11 @@ obj-$(CONFIG_SPI_SH_MSIOF)		+= spi-sh-msiof.o
 obj-$(CONFIG_SPI_SH_SCI)		+= spi-sh-sci.o
 obj-$(CONFIG_SPI_SIRF)		+= spi-sirf.o
 obj-$(CONFIG_SPI_STMP3XXX)		+= spi-stmp.o
+obj-$(CONFIG_SPI_TEGRA20_SFLASH)	+= spi-tegra20-sflash.o
+obj-$(CONFIG_SPI_TEGRA20_SLINK)		+= spi-tegra20-slink.o
 obj-$(CONFIG_SPI_TI_SSP)		+= spi-ti-ssp.o
 obj-$(CONFIG_SPI_TLE62X0)		+= spi-tle62x0.o
 obj-$(CONFIG_SPI_TOPCLIFF_PCH)		+= spi-topcliff-pch.o
 obj-$(CONFIG_SPI_TXX9)			+= spi-txx9.o
 obj-$(CONFIG_SPI_XCOMM)		+= spi-xcomm.o
 obj-$(CONFIG_SPI_XILINX)		+= spi-xilinx.o
-
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 16d6a83..61fb0ec 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -19,9 +19,9 @@
 #include <linux/interrupt.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
+#include <linux/platform_data/atmel.h>
 
 #include <asm/io.h>
-#include <mach/board.h>
 #include <asm/gpio.h>
 #include <mach/cpu.h>
 
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c
index a9f4049..6d97047 100644
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -36,7 +36,6 @@
 #include <bcm63xx_dev_spi.h>
 
 #define PFX		KBUILD_MODNAME
-#define DRV_VER		"0.1.2"
 
 struct bcm63xx_spi {
 	struct completion	done;
@@ -170,13 +169,6 @@ static int bcm63xx_spi_setup(struct spi_device *spi)
 		return -EINVAL;
 	}
 
-	ret = bcm63xx_spi_check_transfer(spi, NULL);
-	if (ret < 0) {
-		dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
-			spi->mode & ~MODEBITS);
-		return ret;
-	}
-
 	dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
 		__func__, spi->mode & MODEBITS, spi->bits_per_word, 0);
 
@@ -441,8 +433,8 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev)
 		goto out_clk_disable;
 	}
 
-	dev_info(dev, "at 0x%08x (irq %d, FIFOs size %d) v%s\n",
-		 r->start, irq, bs->fifo_size, DRV_VER);
+	dev_info(dev, "at 0x%08x (irq %d, FIFOs size %d)\n",
+		 r->start, irq, bs->fifo_size);
 
 	return 0;
 
@@ -485,6 +477,8 @@ static int bcm63xx_spi_suspend(struct device *dev)
 			platform_get_drvdata(to_platform_device(dev));
 	struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 
+	spi_master_suspend(master);
+
 	clk_disable(bs->clk);
 
 	return 0;
@@ -498,6 +492,8 @@ static int bcm63xx_spi_resume(struct device *dev)
 
 	clk_enable(bs->clk);
 
+	spi_master_resume(master);
+
 	return 0;
 }
 
diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c
index aef59b1..8b3d8ef 100644
--- a/drivers/spi/spi-bitbang.c
+++ b/drivers/spi/spi-bitbang.c
@@ -260,11 +260,11 @@ static void bitbang_work(struct work_struct *work)
 	struct spi_bitbang	*bitbang =
 		container_of(work, struct spi_bitbang, work);
 	unsigned long		flags;
+	struct spi_message	*m, *_m;
 
 	spin_lock_irqsave(&bitbang->lock, flags);
 	bitbang->busy = 1;
-	while (!list_empty(&bitbang->queue)) {
-		struct spi_message	*m;
+	list_for_each_entry_safe(m, _m, &bitbang->queue, queue) {
 		struct spi_device	*spi;
 		unsigned		nsecs;
 		struct spi_transfer	*t = NULL;
@@ -273,9 +273,7 @@ static void bitbang_work(struct work_struct *work)
 		int			status;
 		int			do_setup = -1;
 
-		m = container_of(bitbang->queue.next, struct spi_message,
-				queue);
-		list_del_init(&m->queue);
+		list_del(&m->queue);
 		spin_unlock_irqrestore(&bitbang->lock, flags);
 
 		/* FIXME this is made-up ... the correct value is known to
@@ -346,17 +344,14 @@ static void bitbang_work(struct work_struct *work)
 			if (t->delay_usecs)
 				udelay(t->delay_usecs);
 
-			if (!cs_change)
-				continue;
-			if (t->transfer_list.next == &m->transfers)
-				break;
-
-			/* sometimes a short mid-message deselect of the chip
-			 * may be needed to terminate a mode or command
-			 */
-			ndelay(nsecs);
-			bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
-			ndelay(nsecs);
+			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
+				 */
+				ndelay(nsecs);
+				bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
+				ndelay(nsecs);
+			}
 		}
 
 		m->status = status;
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 3542fdc..a2cfde6 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -39,7 +39,6 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/pinctrl/consumer.h>
-#include <linux/err.h>
 
 #include <linux/spi/spi.h>
 
@@ -130,6 +129,7 @@ struct omap2_mcspi {
 	struct omap2_mcspi_dma	*dma_channels;
 	struct device		*dev;
 	struct omap2_mcspi_regs ctx;
+	unsigned int		pin_dir:1;
 };
 
 struct omap2_mcspi_cs {
@@ -323,18 +323,13 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,
 	struct omap2_mcspi	*mcspi;
 	struct omap2_mcspi_dma  *mcspi_dma;
 	unsigned int		count;
-	u8			* rx;
 	const u8		* tx;
-	void __iomem		*chstat_reg;
-	struct omap2_mcspi_cs	*cs = spi->controller_state;
 
 	mcspi = spi_master_get_devdata(spi->master);
 	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
 	count = xfer->len;
 
-	rx = xfer->rx_buf;
 	tx = xfer->tx_buf;
-	chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
 
 	if (mcspi_dma->dma_tx) {
 		struct dma_async_tx_descriptor *tx;
@@ -359,19 +354,6 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,
 	dma_async_issue_pending(mcspi_dma->dma_tx);
 	omap2_mcspi_set_dma_req(spi, 0, 1);
 
-	wait_for_completion(&mcspi_dma->dma_tx_completion);
-	dma_unmap_single(mcspi->dev, xfer->tx_dma, count,
-			 DMA_TO_DEVICE);
-
-	/* for TX_ONLY mode, be sure all words have shifted out */
-	if (rx == NULL) {
-		if (mcspi_wait_for_reg_bit(chstat_reg,
-					OMAP2_MCSPI_CHSTAT_TXS) < 0)
-			dev_err(&spi->dev, "TXS timed out\n");
-		else if (mcspi_wait_for_reg_bit(chstat_reg,
-					OMAP2_MCSPI_CHSTAT_EOT) < 0)
-			dev_err(&spi->dev, "EOT timed out\n");
-	}
 }
 
 static unsigned
@@ -492,6 +474,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
 	struct dma_slave_config	cfg;
 	enum dma_slave_buswidth width;
 	unsigned es;
+	void __iomem		*chstat_reg;
 
 	mcspi = spi_master_get_devdata(spi->master);
 	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
@@ -526,8 +509,24 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
 		omap2_mcspi_tx_dma(spi, xfer, cfg);
 
 	if (rx != NULL)
-		return omap2_mcspi_rx_dma(spi, xfer, cfg, es);
-
+		count = omap2_mcspi_rx_dma(spi, xfer, cfg, es);
+
+	if (tx != NULL) {
+		chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
+		wait_for_completion(&mcspi_dma->dma_tx_completion);
+		dma_unmap_single(mcspi->dev, xfer->tx_dma, xfer->len,
+				 DMA_TO_DEVICE);
+
+		/* for TX_ONLY mode, be sure all words have shifted out */
+		if (rx == NULL) {
+			if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_TXS) < 0)
+				dev_err(&spi->dev, "TXS timed out\n");
+			else if (mcspi_wait_for_reg_bit(chstat_reg,
+						OMAP2_MCSPI_CHSTAT_EOT) < 0)
+				dev_err(&spi->dev, "EOT timed out\n");
+		}
+	}
 	return count;
 }
 
@@ -765,8 +764,15 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
 	/* standard 4-wire master mode:  SCK, MOSI/out, MISO/in, nCS
 	 * REVISIT: this controller could support SPI_3WIRE mode.
 	 */
-	l &= ~(OMAP2_MCSPI_CHCONF_IS|OMAP2_MCSPI_CHCONF_DPE1);
-	l |= OMAP2_MCSPI_CHCONF_DPE0;
+	if (mcspi->pin_dir == MCSPI_PINDIR_D0_IN_D1_OUT) {
+		l &= ~OMAP2_MCSPI_CHCONF_IS;
+		l &= ~OMAP2_MCSPI_CHCONF_DPE1;
+		l |= OMAP2_MCSPI_CHCONF_DPE0;
+	} else {
+		l |= OMAP2_MCSPI_CHCONF_IS;
+		l |= OMAP2_MCSPI_CHCONF_DPE1;
+		l &= ~OMAP2_MCSPI_CHCONF_DPE0;
+	}
 
 	/* wordlength */
 	l &= ~OMAP2_MCSPI_CHCONF_WL_MASK;
@@ -1167,6 +1173,11 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev)
 	master->cleanup = omap2_mcspi_cleanup;
 	master->dev.of_node = node;
 
+	dev_set_drvdata(&pdev->dev, master);
+
+	mcspi = spi_master_get_devdata(master);
+	mcspi->master = master;
+
 	match = of_match_device(omap_mcspi_of_match, &pdev->dev);
 	if (match) {
 		u32 num_cs = 1; /* default number of chipselect */
@@ -1175,19 +1186,17 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev)
 		of_property_read_u32(node, "ti,spi-num-cs", &num_cs);
 		master->num_chipselect = num_cs;
 		master->bus_num = bus_num++;
+		if (of_get_property(node, "ti,pindir-d0-out-d1-in", NULL))
+			mcspi->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
 	} else {
 		pdata = pdev->dev.platform_data;
 		master->num_chipselect = pdata->num_cs;
 		if (pdev->id != -1)
 			master->bus_num = pdev->id;
+		mcspi->pin_dir = pdata->pin_dir;
 	}
 	regs_offset = pdata->regs_offset;
 
-	dev_set_drvdata(&pdev->dev, master);
-
-	mcspi = spi_master_get_devdata(master);
-	mcspi->master = master;
-
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (r == NULL) {
 		status = -ENODEV;
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index a1db91a..1361868 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -371,6 +371,7 @@ struct pl022 {
 	/* Two optional pin states - default & sleep */
 	struct pinctrl			*pinctrl;
 	struct pinctrl_state		*pins_default;
+	struct pinctrl_state		*pins_idle;
 	struct pinctrl_state		*pins_sleep;
 	struct spi_master		*master;
 	struct pl022_ssp_controller	*master_info;
@@ -2116,6 +2117,11 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 	} else
 		dev_err(dev, "could not get default pinstate\n");
 
+	pl022->pins_idle = pinctrl_lookup_state(pl022->pinctrl,
+					      PINCTRL_STATE_IDLE);
+	if (IS_ERR(pl022->pins_idle))
+		dev_dbg(dev, "could not get idle pinstate\n");
+
 	pl022->pins_sleep = pinctrl_lookup_state(pl022->pinctrl,
 					       PINCTRL_STATE_SLEEP);
 	if (IS_ERR(pl022->pins_sleep))
@@ -2246,10 +2252,9 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 		pm_runtime_set_autosuspend_delay(dev,
 			platform_info->autosuspend_delay);
 		pm_runtime_use_autosuspend(dev);
-		pm_runtime_put_autosuspend(dev);
-	} else {
-		pm_runtime_put(dev);
 	}
+	pm_runtime_put(dev);
+
 	return 0;
 
  err_spi_register:
@@ -2303,35 +2308,47 @@ pl022_remove(struct amba_device *adev)
  * the runtime counterparts to handle external resources like
  * clocks, pins and regulators when going to sleep.
  */
-static void pl022_suspend_resources(struct pl022 *pl022)
+static void pl022_suspend_resources(struct pl022 *pl022, bool runtime)
 {
 	int ret;
+	struct pinctrl_state *pins_state;
 
 	clk_disable(pl022->clk);
 
+	pins_state = runtime ? pl022->pins_idle : pl022->pins_sleep;
 	/* Optionally let pins go into sleep states */
-	if (!IS_ERR(pl022->pins_sleep)) {
-		ret = pinctrl_select_state(pl022->pinctrl,
-					   pl022->pins_sleep);
+	if (!IS_ERR(pins_state)) {
+		ret = pinctrl_select_state(pl022->pinctrl, pins_state);
 		if (ret)
-			dev_err(&pl022->adev->dev,
-				"could not set pins to sleep state\n");
+			dev_err(&pl022->adev->dev, "could not set %s pins\n",
+				runtime ? "idle" : "sleep");
 	}
 }
 
-static void pl022_resume_resources(struct pl022 *pl022)
+static void pl022_resume_resources(struct pl022 *pl022, bool runtime)
 {
 	int ret;
 
 	/* Optionaly enable pins to be muxed in and configured */
+	/* First go to the default state */
 	if (!IS_ERR(pl022->pins_default)) {
-		ret = pinctrl_select_state(pl022->pinctrl,
-					   pl022->pins_default);
+		ret = pinctrl_select_state(pl022->pinctrl, pl022->pins_default);
 		if (ret)
 			dev_err(&pl022->adev->dev,
 				"could not set default pins\n");
 	}
 
+	if (!runtime) {
+		/* Then let's idle the pins until the next transfer happens */
+		if (!IS_ERR(pl022->pins_idle)) {
+			ret = pinctrl_select_state(pl022->pinctrl,
+					pl022->pins_idle);
+		if (ret)
+			dev_err(&pl022->adev->dev,
+				"could not set idle pins\n");
+		}
+	}
+
 	clk_enable(pl022->clk);
 }
 #endif
@@ -2347,7 +2364,9 @@ static int pl022_suspend(struct device *dev)
 		dev_warn(dev, "cannot suspend master\n");
 		return ret;
 	}
-	pl022_suspend_resources(pl022);
+
+	pm_runtime_get_sync(dev);
+	pl022_suspend_resources(pl022, false);
 
 	dev_dbg(dev, "suspended\n");
 	return 0;
@@ -2358,7 +2377,8 @@ static int pl022_resume(struct device *dev)
 	struct pl022 *pl022 = dev_get_drvdata(dev);
 	int ret;
 
-	pl022_resume_resources(pl022);
+	pl022_resume_resources(pl022, false);
+	pm_runtime_put(dev);
 
 	/* Start the queue running */
 	ret = spi_master_resume(pl022->master);
@@ -2376,7 +2396,7 @@ static int pl022_runtime_suspend(struct device *dev)
 {
 	struct pl022 *pl022 = dev_get_drvdata(dev);
 
-	pl022_suspend_resources(pl022);
+	pl022_suspend_resources(pl022, true);
 	return 0;
 }
 
@@ -2384,7 +2404,7 @@ static int pl022_runtime_resume(struct device *dev)
 {
 	struct pl022 *pl022 = dev_get_drvdata(dev);
 
-	pl022_resume_resources(pl022);
+	pl022_resume_resources(pl022, true);
 	return 0;
 }
 #endif
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index 6e7a805..57900a8 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -516,7 +516,7 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 
 	/* Disable Clock */
 	if (sdd->port_conf->clk_from_cmu) {
-		clk_disable(sdd->src_clk);
+		clk_disable_unprepare(sdd->src_clk);
 	} else {
 		val = readl(regs + S3C64XX_SPI_CLK_CFG);
 		val &= ~S3C64XX_SPI_ENCLK_ENABLE;
@@ -564,7 +564,7 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 		/* There is half-multiplier before the SPI */
 		clk_set_rate(sdd->src_clk, sdd->cur_speed * 2);
 		/* Enable Clock */
-		clk_enable(sdd->src_clk);
+		clk_prepare_enable(sdd->src_clk);
 	} else {
 		/* Configure Clock */
 		val = readl(regs + S3C64XX_SPI_CLK_CFG);
@@ -1112,7 +1112,7 @@ static int s3c64xx_spi_parse_dt_gpio(struct s3c64xx_spi_driver_data *sdd)
 			dev_err(dev, "invalid gpio[%d]: %d\n", idx, gpio);
 			goto free_gpio;
 		}
-
+		sdd->gpios[idx] = gpio;
 		ret = gpio_request(gpio, "spi-bus");
 		if (ret) {
 			dev_err(dev, "gpio [%d] request failed: %d\n",
@@ -1302,7 +1302,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
 		goto err3;
 	}
 
-	if (clk_enable(sdd->clk)) {
+	if (clk_prepare_enable(sdd->clk)) {
 		dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n");
 		ret = -EBUSY;
 		goto err4;
@@ -1317,7 +1317,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
 		goto err5;
 	}
 
-	if (clk_enable(sdd->src_clk)) {
+	if (clk_prepare_enable(sdd->src_clk)) {
 		dev_err(&pdev->dev, "Couldn't enable clock '%s'\n", clk_name);
 		ret = -EBUSY;
 		goto err6;
@@ -1361,11 +1361,11 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
 err8:
 	free_irq(irq, sdd);
 err7:
-	clk_disable(sdd->src_clk);
+	clk_disable_unprepare(sdd->src_clk);
 err6:
 	clk_put(sdd->src_clk);
 err5:
-	clk_disable(sdd->clk);
+	clk_disable_unprepare(sdd->clk);
 err4:
 	clk_put(sdd->clk);
 err3:
@@ -1393,10 +1393,10 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
 
 	free_irq(platform_get_irq(pdev, 0), sdd);
 
-	clk_disable(sdd->src_clk);
+	clk_disable_unprepare(sdd->src_clk);
 	clk_put(sdd->src_clk);
 
-	clk_disable(sdd->clk);
+	clk_disable_unprepare(sdd->clk);
 	clk_put(sdd->clk);
 
 	if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node)
@@ -1417,8 +1417,8 @@ static int s3c64xx_spi_suspend(struct device *dev)
 	spi_master_suspend(master);
 
 	/* Disable the clock */
-	clk_disable(sdd->src_clk);
-	clk_disable(sdd->clk);
+	clk_disable_unprepare(sdd->src_clk);
+	clk_disable_unprepare(sdd->clk);
 
 	if (!sdd->cntrlr_info->cfg_gpio && dev->of_node)
 		s3c64xx_spi_dt_gpio_free(sdd);
@@ -1440,8 +1440,8 @@ static int s3c64xx_spi_resume(struct device *dev)
 		sci->cfg_gpio();
 
 	/* Enable the clock */
-	clk_enable(sdd->src_clk);
-	clk_enable(sdd->clk);
+	clk_prepare_enable(sdd->src_clk);
+	clk_prepare_enable(sdd->clk);
 
 	s3c64xx_spi_hwinit(sdd, sdd->port_id);
 
@@ -1457,8 +1457,8 @@ static int s3c64xx_spi_runtime_suspend(struct device *dev)
 	struct spi_master *master = dev_get_drvdata(dev);
 	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
 
-	clk_disable(sdd->clk);
-	clk_disable(sdd->src_clk);
+	clk_disable_unprepare(sdd->clk);
+	clk_disable_unprepare(sdd->src_clk);
 
 	return 0;
 }
@@ -1468,8 +1468,8 @@ static int s3c64xx_spi_runtime_resume(struct device *dev)
 	struct spi_master *master = dev_get_drvdata(dev);
 	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
 
-	clk_enable(sdd->src_clk);
-	clk_enable(sdd->clk);
+	clk_prepare_enable(sdd->src_clk);
+	clk_prepare_enable(sdd->clk);
 
 	return 0;
 }
diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c
new file mode 100644
index 0000000..54eb948
--- /dev/null
+++ b/drivers/spi/spi-tegra20-sflash.c
@@ -0,0 +1,665 @@
+/*
+ * SPI driver for Nvidia's Tegra20 Serial Flash Controller.
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.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/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi-tegra.h>
+#include <mach/clk.h>
+
+#define SPI_COMMAND				0x000
+#define SPI_GO					BIT(30)
+#define SPI_M_S					BIT(28)
+#define SPI_ACTIVE_SCLK_MASK			(0x3 << 26)
+#define SPI_ACTIVE_SCLK_DRIVE_LOW		(0 << 26)
+#define SPI_ACTIVE_SCLK_DRIVE_HIGH		(1 << 26)
+#define SPI_ACTIVE_SCLK_PULL_LOW		(2 << 26)
+#define SPI_ACTIVE_SCLK_PULL_HIGH		(3 << 26)
+
+#define SPI_CK_SDA_FALLING			(1 << 21)
+#define SPI_CK_SDA_RISING			(0 << 21)
+#define SPI_CK_SDA_MASK				(1 << 21)
+#define SPI_ACTIVE_SDA				(0x3 << 18)
+#define SPI_ACTIVE_SDA_DRIVE_LOW		(0 << 18)
+#define SPI_ACTIVE_SDA_DRIVE_HIGH		(1 << 18)
+#define SPI_ACTIVE_SDA_PULL_LOW			(2 << 18)
+#define SPI_ACTIVE_SDA_PULL_HIGH		(3 << 18)
+
+#define SPI_CS_POL_INVERT			BIT(16)
+#define SPI_TX_EN				BIT(15)
+#define SPI_RX_EN				BIT(14)
+#define SPI_CS_VAL_HIGH				BIT(13)
+#define SPI_CS_VAL_LOW				0x0
+#define SPI_CS_SW				BIT(12)
+#define SPI_CS_HW				0x0
+#define SPI_CS_DELAY_MASK			(7 << 9)
+#define SPI_CS3_EN				BIT(8)
+#define SPI_CS2_EN				BIT(7)
+#define SPI_CS1_EN				BIT(6)
+#define SPI_CS0_EN				BIT(5)
+
+#define SPI_CS_MASK			(SPI_CS3_EN | SPI_CS2_EN |	\
+					SPI_CS1_EN | SPI_CS0_EN)
+#define SPI_BIT_LENGTH(x)		(((x) & 0x1f) << 0)
+
+#define SPI_MODES			(SPI_ACTIVE_SCLK_MASK | SPI_CK_SDA_MASK)
+
+#define SPI_STATUS			0x004
+#define SPI_BSY				BIT(31)
+#define SPI_RDY				BIT(30)
+#define SPI_TXF_FLUSH			BIT(29)
+#define SPI_RXF_FLUSH			BIT(28)
+#define SPI_RX_UNF			BIT(27)
+#define SPI_TX_OVF			BIT(26)
+#define SPI_RXF_EMPTY			BIT(25)
+#define SPI_RXF_FULL			BIT(24)
+#define SPI_TXF_EMPTY			BIT(23)
+#define SPI_TXF_FULL			BIT(22)
+#define SPI_BLK_CNT(count)		(((count) & 0xffff) + 1)
+
+#define SPI_FIFO_ERROR			(SPI_RX_UNF | SPI_TX_OVF)
+#define SPI_FIFO_EMPTY			(SPI_TX_EMPTY | SPI_RX_EMPTY)
+
+#define SPI_RX_CMP			0x8
+#define SPI_DMA_CTL			0x0C
+#define SPI_DMA_EN			BIT(31)
+#define SPI_IE_RXC			BIT(27)
+#define SPI_IE_TXC			BIT(26)
+#define SPI_PACKED			BIT(20)
+#define SPI_RX_TRIG_MASK		(0x3 << 18)
+#define SPI_RX_TRIG_1W			(0x0 << 18)
+#define SPI_RX_TRIG_4W			(0x1 << 18)
+#define SPI_TX_TRIG_MASK		(0x3 << 16)
+#define SPI_TX_TRIG_1W			(0x0 << 16)
+#define SPI_TX_TRIG_4W			(0x1 << 16)
+#define SPI_DMA_BLK_COUNT(count)	(((count) - 1) & 0xFFFF);
+
+#define SPI_TX_FIFO			0x10
+#define SPI_RX_FIFO			0x20
+
+#define DATA_DIR_TX			(1 << 0)
+#define DATA_DIR_RX			(1 << 1)
+
+#define MAX_CHIP_SELECT			4
+#define SPI_FIFO_DEPTH			4
+#define SPI_DMA_TIMEOUT               (msecs_to_jiffies(1000))
+
+struct tegra_sflash_data {
+	struct device				*dev;
+	struct spi_master			*master;
+	spinlock_t				lock;
+
+	struct clk				*clk;
+	void __iomem				*base;
+	unsigned				irq;
+	u32					spi_max_frequency;
+	u32					cur_speed;
+
+	struct spi_device			*cur_spi;
+	unsigned				cur_pos;
+	unsigned				cur_len;
+	unsigned				bytes_per_word;
+	unsigned				cur_direction;
+	unsigned				curr_xfer_words;
+
+	unsigned				cur_rx_pos;
+	unsigned				cur_tx_pos;
+
+	u32					tx_status;
+	u32					rx_status;
+	u32					status_reg;
+
+	u32					def_command_reg;
+	u32					command_reg;
+	u32					dma_control_reg;
+
+	struct completion			xfer_completion;
+	struct spi_transfer			*curr_xfer;
+};
+
+static int tegra_sflash_runtime_suspend(struct device *dev);
+static int tegra_sflash_runtime_resume(struct device *dev);
+
+static inline unsigned long tegra_sflash_readl(struct tegra_sflash_data *tsd,
+		unsigned long reg)
+{
+	return readl(tsd->base + reg);
+}
+
+static inline void tegra_sflash_writel(struct tegra_sflash_data *tsd,
+		unsigned long val, unsigned long reg)
+{
+	writel(val, tsd->base + reg);
+}
+
+static void tegra_sflash_clear_status(struct tegra_sflash_data *tsd)
+{
+	/* Write 1 to clear status register */
+	tegra_sflash_writel(tsd, SPI_RDY | SPI_FIFO_ERROR, SPI_STATUS);
+}
+
+static unsigned tegra_sflash_calculate_curr_xfer_param(
+	struct spi_device *spi, struct tegra_sflash_data *tsd,
+	struct spi_transfer *t)
+{
+	unsigned remain_len = t->len - tsd->cur_pos;
+	unsigned max_word;
+
+	tsd->bytes_per_word = (t->bits_per_word - 1) / 8 + 1;
+	max_word = remain_len / tsd->bytes_per_word;
+	if (max_word > SPI_FIFO_DEPTH)
+		max_word = SPI_FIFO_DEPTH;
+	tsd->curr_xfer_words = max_word;
+	return max_word;
+}
+
+static unsigned tegra_sflash_fill_tx_fifo_from_client_txbuf(
+	struct tegra_sflash_data *tsd, struct spi_transfer *t)
+{
+	unsigned nbytes;
+	unsigned long status;
+	unsigned max_n_32bit = tsd->curr_xfer_words;
+	u8 *tx_buf = (u8 *)t->tx_buf + tsd->cur_tx_pos;
+
+	if (max_n_32bit > SPI_FIFO_DEPTH)
+		max_n_32bit = SPI_FIFO_DEPTH;
+	nbytes = max_n_32bit * tsd->bytes_per_word;
+
+	status = tegra_sflash_readl(tsd, SPI_STATUS);
+	while (!(status & SPI_TXF_FULL)) {
+		int i;
+		unsigned int x = 0;
+
+		for (i = 0; nbytes && (i < tsd->bytes_per_word);
+							i++, nbytes--)
+				x |= ((*tx_buf++) << i*8);
+		tegra_sflash_writel(tsd, x, SPI_TX_FIFO);
+		if (!nbytes)
+			break;
+
+		status = tegra_sflash_readl(tsd, SPI_STATUS);
+	}
+	tsd->cur_tx_pos += max_n_32bit * tsd->bytes_per_word;
+	return max_n_32bit;
+}
+
+static int tegra_sflash_read_rx_fifo_to_client_rxbuf(
+		struct tegra_sflash_data *tsd, struct spi_transfer *t)
+{
+	unsigned long status;
+	unsigned int read_words = 0;
+	u8 *rx_buf = (u8 *)t->rx_buf + tsd->cur_rx_pos;
+
+	status = tegra_sflash_readl(tsd, SPI_STATUS);
+	while (!(status & SPI_RXF_EMPTY)) {
+		int i;
+		unsigned long x;
+
+		x = tegra_sflash_readl(tsd, SPI_RX_FIFO);
+		for (i = 0; (i < tsd->bytes_per_word); i++)
+			*rx_buf++ = (x >> (i*8)) & 0xFF;
+		read_words++;
+		status = tegra_sflash_readl(tsd, SPI_STATUS);
+	}
+	tsd->cur_rx_pos += read_words * tsd->bytes_per_word;
+	return 0;
+}
+
+static int tegra_sflash_start_cpu_based_transfer(
+		struct tegra_sflash_data *tsd, struct spi_transfer *t)
+{
+	unsigned long val = 0;
+	unsigned cur_words;
+
+	if (tsd->cur_direction & DATA_DIR_TX)
+		val |= SPI_IE_TXC;
+
+	if (tsd->cur_direction & DATA_DIR_RX)
+		val |= SPI_IE_RXC;
+
+	tegra_sflash_writel(tsd, val, SPI_DMA_CTL);
+	tsd->dma_control_reg = val;
+
+	if (tsd->cur_direction & DATA_DIR_TX)
+		cur_words = tegra_sflash_fill_tx_fifo_from_client_txbuf(tsd, t);
+	else
+		cur_words = tsd->curr_xfer_words;
+	val |= SPI_DMA_BLK_COUNT(cur_words);
+	tegra_sflash_writel(tsd, val, SPI_DMA_CTL);
+	tsd->dma_control_reg = val;
+	val |= SPI_DMA_EN;
+	tegra_sflash_writel(tsd, val, SPI_DMA_CTL);
+	return 0;
+}
+
+static int tegra_sflash_start_transfer_one(struct spi_device *spi,
+		struct spi_transfer *t, bool is_first_of_msg,
+		bool is_single_xfer)
+{
+	struct tegra_sflash_data *tsd = spi_master_get_devdata(spi->master);
+	u32 speed;
+	unsigned long command;
+
+	speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz;
+	if (!speed)
+		speed = tsd->spi_max_frequency;
+	if (speed != tsd->cur_speed) {
+		clk_set_rate(tsd->clk, speed);
+		tsd->cur_speed = speed;
+	}
+
+	tsd->cur_spi = spi;
+	tsd->cur_pos = 0;
+	tsd->cur_rx_pos = 0;
+	tsd->cur_tx_pos = 0;
+	tsd->curr_xfer = t;
+	tegra_sflash_calculate_curr_xfer_param(spi, tsd, t);
+	if (is_first_of_msg) {
+		command = tsd->def_command_reg;
+		command |= SPI_BIT_LENGTH(t->bits_per_word - 1);
+		command |= SPI_CS_VAL_HIGH;
+
+		command &= ~SPI_MODES;
+		if (spi->mode & SPI_CPHA)
+			command |= SPI_CK_SDA_FALLING;
+
+		if (spi->mode & SPI_CPOL)
+			command |= SPI_ACTIVE_SCLK_DRIVE_HIGH;
+		else
+			command |= SPI_ACTIVE_SCLK_DRIVE_LOW;
+		command |= SPI_CS0_EN << spi->chip_select;
+	} else {
+		command = tsd->command_reg;
+		command &= ~SPI_BIT_LENGTH(~0);
+		command |= SPI_BIT_LENGTH(t->bits_per_word - 1);
+		command &= ~(SPI_RX_EN | SPI_TX_EN);
+	}
+
+	tsd->cur_direction = 0;
+	if (t->rx_buf) {
+		command |= SPI_RX_EN;
+		tsd->cur_direction |= DATA_DIR_RX;
+	}
+	if (t->tx_buf) {
+		command |= SPI_TX_EN;
+		tsd->cur_direction |= DATA_DIR_TX;
+	}
+	tegra_sflash_writel(tsd, command, SPI_COMMAND);
+	tsd->command_reg = command;
+
+	return  tegra_sflash_start_cpu_based_transfer(tsd, t);
+}
+
+static int tegra_sflash_transfer_one_message(struct spi_master *master,
+			struct spi_message *msg)
+{
+	bool is_first_msg = true;
+	int single_xfer;
+	struct tegra_sflash_data *tsd = spi_master_get_devdata(master);
+	struct spi_transfer *xfer;
+	struct spi_device *spi = msg->spi;
+	int ret;
+
+	ret = pm_runtime_get_sync(tsd->dev);
+	if (ret < 0) {
+		dev_err(tsd->dev, "pm_runtime_get() failed, err = %d\n", ret);
+		return 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(tsd->xfer_completion);
+		ret = tegra_sflash_start_transfer_one(spi, xfer,
+					is_first_msg, single_xfer);
+		if (ret < 0) {
+			dev_err(tsd->dev,
+				"spi can not start transfer, err %d\n", ret);
+			goto exit;
+		}
+		is_first_msg = false;
+		ret = wait_for_completion_timeout(&tsd->xfer_completion,
+						SPI_DMA_TIMEOUT);
+		if (WARN_ON(ret == 0)) {
+			dev_err(tsd->dev,
+				"spi trasfer timeout, err %d\n", ret);
+			ret = -EIO;
+			goto exit;
+		}
+
+		if (tsd->tx_status ||  tsd->rx_status) {
+			dev_err(tsd->dev, "Error in Transfer\n");
+			ret = -EIO;
+			goto exit;
+		}
+		msg->actual_length += xfer->len;
+		if (xfer->cs_change && xfer->delay_usecs) {
+			tegra_sflash_writel(tsd, tsd->def_command_reg,
+					SPI_COMMAND);
+			udelay(xfer->delay_usecs);
+		}
+	}
+	ret = 0;
+exit:
+	tegra_sflash_writel(tsd, tsd->def_command_reg, SPI_COMMAND);
+	msg->status = ret;
+	spi_finalize_current_message(master);
+	pm_runtime_put(tsd->dev);
+	return ret;
+}
+
+static irqreturn_t handle_cpu_based_xfer(struct tegra_sflash_data *tsd)
+{
+	struct spi_transfer *t = tsd->curr_xfer;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tsd->lock, flags);
+	if (tsd->tx_status || tsd->rx_status || (tsd->status_reg & SPI_BSY)) {
+		dev_err(tsd->dev,
+			"CpuXfer ERROR bit set 0x%x\n", tsd->status_reg);
+		dev_err(tsd->dev,
+			"CpuXfer 0x%08x:0x%08x\n", tsd->command_reg,
+				tsd->dma_control_reg);
+		tegra_periph_reset_assert(tsd->clk);
+		udelay(2);
+		tegra_periph_reset_deassert(tsd->clk);
+		complete(&tsd->xfer_completion);
+		goto exit;
+	}
+
+	if (tsd->cur_direction & DATA_DIR_RX)
+		tegra_sflash_read_rx_fifo_to_client_rxbuf(tsd, t);
+
+	if (tsd->cur_direction & DATA_DIR_TX)
+		tsd->cur_pos = tsd->cur_tx_pos;
+	else
+		tsd->cur_pos = tsd->cur_rx_pos;
+
+	if (tsd->cur_pos == t->len) {
+		complete(&tsd->xfer_completion);
+		goto exit;
+	}
+
+	tegra_sflash_calculate_curr_xfer_param(tsd->cur_spi, tsd, t);
+	tegra_sflash_start_cpu_based_transfer(tsd, t);
+exit:
+	spin_unlock_irqrestore(&tsd->lock, flags);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t tegra_sflash_isr(int irq, void *context_data)
+{
+	struct tegra_sflash_data *tsd = context_data;
+
+	tsd->status_reg = tegra_sflash_readl(tsd, SPI_STATUS);
+	if (tsd->cur_direction & DATA_DIR_TX)
+		tsd->tx_status = tsd->status_reg & SPI_TX_OVF;
+
+	if (tsd->cur_direction & DATA_DIR_RX)
+		tsd->rx_status = tsd->status_reg & SPI_RX_UNF;
+	tegra_sflash_clear_status(tsd);
+
+	return handle_cpu_based_xfer(tsd);
+}
+
+static struct tegra_spi_platform_data *tegra_sflash_parse_dt(
+		struct platform_device *pdev)
+{
+	struct tegra_spi_platform_data *pdata;
+	struct device_node *np = pdev->dev.of_node;
+	u32 max_freq;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		dev_err(&pdev->dev, "Memory alloc for pdata failed\n");
+		return NULL;
+	}
+
+	if (!of_property_read_u32(np, "spi-max-frequency", &max_freq))
+		pdata->spi_max_frequency = max_freq;
+
+	return pdata;
+}
+
+static struct of_device_id tegra_sflash_of_match[] __devinitconst = {
+	{ .compatible = "nvidia,tegra20-sflash", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, tegra_sflash_of_match);
+
+static int __devinit tegra_sflash_probe(struct platform_device *pdev)
+{
+	struct spi_master	*master;
+	struct tegra_sflash_data	*tsd;
+	struct resource		*r;
+	struct tegra_spi_platform_data *pdata = pdev->dev.platform_data;
+	int ret;
+	const struct of_device_id *match;
+
+	match = of_match_device(of_match_ptr(tegra_sflash_of_match),
+					&pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "Error: No device match found\n");
+		return -ENODEV;
+	}
+
+	if (!pdata && pdev->dev.of_node)
+		pdata = tegra_sflash_parse_dt(pdev);
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "No platform data, exiting\n");
+		return -ENODEV;
+	}
+
+	if (!pdata->spi_max_frequency)
+		pdata->spi_max_frequency = 25000000; /* 25MHz */
+
+	master = spi_alloc_master(&pdev->dev, sizeof(*tsd));
+	if (!master) {
+		dev_err(&pdev->dev, "master allocation failed\n");
+		return -ENOMEM;
+	}
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA;
+	master->transfer_one_message = tegra_sflash_transfer_one_message;
+	master->num_chipselect = MAX_CHIP_SELECT;
+	master->bus_num = -1;
+
+	dev_set_drvdata(&pdev->dev, master);
+	tsd = spi_master_get_devdata(master);
+	tsd->master = master;
+	tsd->dev = &pdev->dev;
+	spin_lock_init(&tsd->lock);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "No IO memory resource\n");
+		ret = -ENODEV;
+		goto exit_free_master;
+	}
+	tsd->base = devm_request_and_ioremap(&pdev->dev, r);
+	if (!tsd->base) {
+		dev_err(&pdev->dev,
+			"Cannot request memregion/iomap dma address\n");
+		ret = -EADDRNOTAVAIL;
+		goto exit_free_master;
+	}
+
+	tsd->irq = platform_get_irq(pdev, 0);
+	ret = request_irq(tsd->irq, tegra_sflash_isr, 0,
+			dev_name(&pdev->dev), tsd);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n",
+					tsd->irq);
+		goto exit_free_master;
+	}
+
+	tsd->clk = devm_clk_get(&pdev->dev, "spi");
+	if (IS_ERR(tsd->clk)) {
+		dev_err(&pdev->dev, "can not get clock\n");
+		ret = PTR_ERR(tsd->clk);
+		goto exit_free_irq;
+	}
+
+	tsd->spi_max_frequency = pdata->spi_max_frequency;
+	init_completion(&tsd->xfer_completion);
+	pm_runtime_enable(&pdev->dev);
+	if (!pm_runtime_enabled(&pdev->dev)) {
+		ret = tegra_sflash_runtime_resume(&pdev->dev);
+		if (ret)
+			goto exit_pm_disable;
+	}
+
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret);
+		goto exit_pm_disable;
+	}
+
+	/* Reset controller */
+	tegra_periph_reset_assert(tsd->clk);
+	udelay(2);
+	tegra_periph_reset_deassert(tsd->clk);
+
+	tsd->def_command_reg  = SPI_M_S | SPI_CS_SW;
+	tegra_sflash_writel(tsd, tsd->def_command_reg, SPI_COMMAND);
+	pm_runtime_put(&pdev->dev);
+
+	master->dev.of_node = pdev->dev.of_node;
+	ret = spi_register_master(master);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "can not register to master err %d\n", ret);
+		goto exit_pm_disable;
+	}
+	return ret;
+
+exit_pm_disable:
+	pm_runtime_disable(&pdev->dev);
+	if (!pm_runtime_status_suspended(&pdev->dev))
+		tegra_sflash_runtime_suspend(&pdev->dev);
+exit_free_irq:
+	free_irq(tsd->irq, tsd);
+exit_free_master:
+	spi_master_put(master);
+	return ret;
+}
+
+static int __devexit tegra_sflash_remove(struct platform_device *pdev)
+{
+	struct spi_master *master = dev_get_drvdata(&pdev->dev);
+	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))
+		tegra_sflash_runtime_suspend(&pdev->dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra_sflash_suspend(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+
+	return spi_master_suspend(master);
+}
+
+static int tegra_sflash_resume(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct tegra_sflash_data *tsd = spi_master_get_devdata(master);
+	int ret;
+
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0) {
+		dev_err(dev, "pm runtime failed, e = %d\n", ret);
+		return ret;
+	}
+	tegra_sflash_writel(tsd, tsd->command_reg, SPI_COMMAND);
+	pm_runtime_put(dev);
+
+	return spi_master_resume(master);
+}
+#endif
+
+static int tegra_sflash_runtime_suspend(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct tegra_sflash_data *tsd = spi_master_get_devdata(master);
+
+	/* Flush all write which are in PPSB queue by reading back */
+	tegra_sflash_readl(tsd, SPI_COMMAND);
+
+	clk_disable_unprepare(tsd->clk);
+	return 0;
+}
+
+static int tegra_sflash_runtime_resume(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct tegra_sflash_data *tsd = spi_master_get_devdata(master);
+	int ret;
+
+	ret = clk_prepare_enable(tsd->clk);
+	if (ret < 0) {
+		dev_err(tsd->dev, "clk_prepare failed: %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+static const struct dev_pm_ops slink_pm_ops = {
+	SET_RUNTIME_PM_OPS(tegra_sflash_runtime_suspend,
+		tegra_sflash_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(tegra_sflash_suspend, tegra_sflash_resume)
+};
+static struct platform_driver tegra_sflash_driver = {
+	.driver = {
+		.name		= "spi-tegra-sflash",
+		.owner		= THIS_MODULE,
+		.pm		= &slink_pm_ops,
+		.of_match_table	= of_match_ptr(tegra_sflash_of_match),
+	},
+	.probe =	tegra_sflash_probe,
+	.remove =	__devexit_p(tegra_sflash_remove),
+};
+module_platform_driver(tegra_sflash_driver);
+
+MODULE_ALIAS("platform:spi-tegra-sflash");
+MODULE_DESCRIPTION("NVIDIA Tegra20 Serial Flash Controller Driver");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c
new file mode 100644
index 0000000..7882b50
--- /dev/null
+++ b/drivers/spi/spi-tegra20-slink.c
@@ -0,0 +1,1358 @@
+/*
+ * SPI driver for Nvidia's Tegra20/Tegra30 SLINK Controller.
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi-tegra.h>
+#include <mach/clk.h>
+
+#define SLINK_COMMAND			0x000
+#define SLINK_BIT_LENGTH(x)		(((x) & 0x1f) << 0)
+#define SLINK_WORD_SIZE(x)		(((x) & 0x1f) << 5)
+#define SLINK_BOTH_EN			(1 << 10)
+#define SLINK_CS_SW			(1 << 11)
+#define SLINK_CS_VALUE			(1 << 12)
+#define SLINK_CS_POLARITY		(1 << 13)
+#define SLINK_IDLE_SDA_DRIVE_LOW	(0 << 16)
+#define SLINK_IDLE_SDA_DRIVE_HIGH	(1 << 16)
+#define SLINK_IDLE_SDA_PULL_LOW		(2 << 16)
+#define SLINK_IDLE_SDA_PULL_HIGH	(3 << 16)
+#define SLINK_IDLE_SDA_MASK		(3 << 16)
+#define SLINK_CS_POLARITY1		(1 << 20)
+#define SLINK_CK_SDA			(1 << 21)
+#define SLINK_CS_POLARITY2		(1 << 22)
+#define SLINK_CS_POLARITY3		(1 << 23)
+#define SLINK_IDLE_SCLK_DRIVE_LOW	(0 << 24)
+#define SLINK_IDLE_SCLK_DRIVE_HIGH	(1 << 24)
+#define SLINK_IDLE_SCLK_PULL_LOW	(2 << 24)
+#define SLINK_IDLE_SCLK_PULL_HIGH	(3 << 24)
+#define SLINK_IDLE_SCLK_MASK		(3 << 24)
+#define SLINK_M_S			(1 << 28)
+#define SLINK_WAIT			(1 << 29)
+#define SLINK_GO			(1 << 30)
+#define SLINK_ENB			(1 << 31)
+
+#define SLINK_MODES			(SLINK_IDLE_SCLK_MASK | SLINK_CK_SDA)
+
+#define SLINK_COMMAND2			0x004
+#define SLINK_LSBFE			(1 << 0)
+#define SLINK_SSOE			(1 << 1)
+#define SLINK_SPIE			(1 << 4)
+#define SLINK_BIDIROE			(1 << 6)
+#define SLINK_MODFEN			(1 << 7)
+#define SLINK_INT_SIZE(x)		(((x) & 0x1f) << 8)
+#define SLINK_CS_ACTIVE_BETWEEN		(1 << 17)
+#define SLINK_SS_EN_CS(x)		(((x) & 0x3) << 18)
+#define SLINK_SS_SETUP(x)		(((x) & 0x3) << 20)
+#define SLINK_FIFO_REFILLS_0		(0 << 22)
+#define SLINK_FIFO_REFILLS_1		(1 << 22)
+#define SLINK_FIFO_REFILLS_2		(2 << 22)
+#define SLINK_FIFO_REFILLS_3		(3 << 22)
+#define SLINK_FIFO_REFILLS_MASK		(3 << 22)
+#define SLINK_WAIT_PACK_INT(x)		(((x) & 0x7) << 26)
+#define SLINK_SPC0			(1 << 29)
+#define SLINK_TXEN			(1 << 30)
+#define SLINK_RXEN			(1 << 31)
+
+#define SLINK_STATUS			0x008
+#define SLINK_COUNT(val)		(((val) >> 0) & 0x1f)
+#define SLINK_WORD(val)			(((val) >> 5) & 0x1f)
+#define SLINK_BLK_CNT(val)		(((val) >> 0) & 0xffff)
+#define SLINK_MODF			(1 << 16)
+#define SLINK_RX_UNF			(1 << 18)
+#define SLINK_TX_OVF			(1 << 19)
+#define SLINK_TX_FULL			(1 << 20)
+#define SLINK_TX_EMPTY			(1 << 21)
+#define SLINK_RX_FULL			(1 << 22)
+#define SLINK_RX_EMPTY			(1 << 23)
+#define SLINK_TX_UNF			(1 << 24)
+#define SLINK_RX_OVF			(1 << 25)
+#define SLINK_TX_FLUSH			(1 << 26)
+#define SLINK_RX_FLUSH			(1 << 27)
+#define SLINK_SCLK			(1 << 28)
+#define SLINK_ERR			(1 << 29)
+#define SLINK_RDY			(1 << 30)
+#define SLINK_BSY			(1 << 31)
+#define SLINK_FIFO_ERROR		(SLINK_TX_OVF | SLINK_RX_UNF |	\
+					SLINK_TX_UNF | SLINK_RX_OVF)
+
+#define SLINK_FIFO_EMPTY		(SLINK_TX_EMPTY | SLINK_RX_EMPTY)
+
+#define SLINK_MAS_DATA			0x010
+#define SLINK_SLAVE_DATA		0x014
+
+#define SLINK_DMA_CTL			0x018
+#define SLINK_DMA_BLOCK_SIZE(x)		(((x) & 0xffff) << 0)
+#define SLINK_TX_TRIG_1			(0 << 16)
+#define SLINK_TX_TRIG_4			(1 << 16)
+#define SLINK_TX_TRIG_8			(2 << 16)
+#define SLINK_TX_TRIG_16		(3 << 16)
+#define SLINK_TX_TRIG_MASK		(3 << 16)
+#define SLINK_RX_TRIG_1			(0 << 18)
+#define SLINK_RX_TRIG_4			(1 << 18)
+#define SLINK_RX_TRIG_8			(2 << 18)
+#define SLINK_RX_TRIG_16		(3 << 18)
+#define SLINK_RX_TRIG_MASK		(3 << 18)
+#define SLINK_PACKED			(1 << 20)
+#define SLINK_PACK_SIZE_4		(0 << 21)
+#define SLINK_PACK_SIZE_8		(1 << 21)
+#define SLINK_PACK_SIZE_16		(2 << 21)
+#define SLINK_PACK_SIZE_32		(3 << 21)
+#define SLINK_PACK_SIZE_MASK		(3 << 21)
+#define SLINK_IE_TXC			(1 << 26)
+#define SLINK_IE_RXC			(1 << 27)
+#define SLINK_DMA_EN			(1 << 31)
+
+#define SLINK_STATUS2			0x01c
+#define SLINK_TX_FIFO_EMPTY_COUNT(val)	(((val) & 0x3f) >> 0)
+#define SLINK_RX_FIFO_FULL_COUNT(val)	(((val) & 0x3f0000) >> 16)
+#define SLINK_SS_HOLD_TIME(val)		(((val) & 0xF) << 6)
+
+#define SLINK_TX_FIFO			0x100
+#define SLINK_RX_FIFO			0x180
+
+#define DATA_DIR_TX			(1 << 0)
+#define DATA_DIR_RX			(1 << 1)
+
+#define SLINK_DMA_TIMEOUT		(msecs_to_jiffies(1000))
+
+#define DEFAULT_SPI_DMA_BUF_LEN		(16*1024)
+#define TX_FIFO_EMPTY_COUNT_MAX		SLINK_TX_FIFO_EMPTY_COUNT(0x20)
+#define RX_FIFO_FULL_COUNT_ZERO		SLINK_RX_FIFO_FULL_COUNT(0)
+
+#define SLINK_STATUS2_RESET \
+	(TX_FIFO_EMPTY_COUNT_MAX | RX_FIFO_FULL_COUNT_ZERO << 16)
+
+#define MAX_CHIP_SELECT			4
+#define SLINK_FIFO_DEPTH		32
+
+struct tegra_slink_chip_data {
+	bool cs_hold_time;
+};
+
+struct tegra_slink_data {
+	struct device				*dev;
+	struct spi_master			*master;
+	const struct tegra_slink_chip_data	*chip_data;
+	spinlock_t				lock;
+
+	struct clk				*clk;
+	void __iomem				*base;
+	phys_addr_t				phys;
+	unsigned				irq;
+	int					dma_req_sel;
+	u32					spi_max_frequency;
+	u32					cur_speed;
+
+	struct spi_device			*cur_spi;
+	unsigned				cur_pos;
+	unsigned				cur_len;
+	unsigned				words_per_32bit;
+	unsigned				bytes_per_word;
+	unsigned				curr_dma_words;
+	unsigned				cur_direction;
+
+	unsigned				cur_rx_pos;
+	unsigned				cur_tx_pos;
+
+	unsigned				dma_buf_size;
+	unsigned				max_buf_size;
+	bool					is_curr_dma_xfer;
+	bool					is_hw_based_cs;
+
+	struct completion			rx_dma_complete;
+	struct completion			tx_dma_complete;
+
+	u32					tx_status;
+	u32					rx_status;
+	u32					status_reg;
+	bool					is_packed;
+	unsigned long				packed_size;
+
+	u32					command_reg;
+	u32					command2_reg;
+	u32					dma_control_reg;
+	u32					def_command_reg;
+	u32					def_command2_reg;
+
+	struct completion			xfer_completion;
+	struct spi_transfer			*curr_xfer;
+	struct dma_chan				*rx_dma_chan;
+	u32					*rx_dma_buf;
+	dma_addr_t				rx_dma_phys;
+	struct dma_async_tx_descriptor		*rx_dma_desc;
+
+	struct dma_chan				*tx_dma_chan;
+	u32					*tx_dma_buf;
+	dma_addr_t				tx_dma_phys;
+	struct dma_async_tx_descriptor		*tx_dma_desc;
+};
+
+static int tegra_slink_runtime_suspend(struct device *dev);
+static int tegra_slink_runtime_resume(struct device *dev);
+
+static inline unsigned long tegra_slink_readl(struct tegra_slink_data *tspi,
+		unsigned long reg)
+{
+	return readl(tspi->base + reg);
+}
+
+static inline void tegra_slink_writel(struct tegra_slink_data *tspi,
+		unsigned long val, unsigned long reg)
+{
+	writel(val, tspi->base + reg);
+
+	/* Read back register to make sure that register writes completed */
+	if (reg != SLINK_TX_FIFO)
+		readl(tspi->base + SLINK_MAS_DATA);
+}
+
+static void tegra_slink_clear_status(struct tegra_slink_data *tspi)
+{
+	unsigned long val;
+	unsigned long val_write = 0;
+
+	val = tegra_slink_readl(tspi, SLINK_STATUS);
+
+	/* Write 1 to clear status register */
+	val_write = SLINK_RDY | SLINK_FIFO_ERROR;
+	tegra_slink_writel(tspi, val_write, SLINK_STATUS);
+}
+
+static unsigned long tegra_slink_get_packed_size(struct tegra_slink_data *tspi,
+				  struct spi_transfer *t)
+{
+	unsigned long val;
+
+	switch (tspi->bytes_per_word) {
+	case 0:
+		val = SLINK_PACK_SIZE_4;
+		break;
+	case 1:
+		val = SLINK_PACK_SIZE_8;
+		break;
+	case 2:
+		val = SLINK_PACK_SIZE_16;
+		break;
+	case 4:
+		val = SLINK_PACK_SIZE_32;
+		break;
+	default:
+		val = 0;
+	}
+	return val;
+}
+
+static unsigned tegra_slink_calculate_curr_xfer_param(
+	struct spi_device *spi, struct tegra_slink_data *tspi,
+	struct spi_transfer *t)
+{
+	unsigned remain_len = t->len - tspi->cur_pos;
+	unsigned max_word;
+	unsigned bits_per_word ;
+	unsigned max_len;
+	unsigned total_fifo_words;
+
+	bits_per_word = t->bits_per_word ? t->bits_per_word :
+						spi->bits_per_word;
+	tspi->bytes_per_word = (bits_per_word - 1) / 8 + 1;
+
+	if (bits_per_word == 8 || bits_per_word == 16) {
+		tspi->is_packed = 1;
+		tspi->words_per_32bit = 32/bits_per_word;
+	} else {
+		tspi->is_packed = 0;
+		tspi->words_per_32bit = 1;
+	}
+	tspi->packed_size = tegra_slink_get_packed_size(tspi, t);
+
+	if (tspi->is_packed) {
+		max_len = min(remain_len, tspi->max_buf_size);
+		tspi->curr_dma_words = max_len/tspi->bytes_per_word;
+		total_fifo_words = max_len/4;
+	} else {
+		max_word = (remain_len - 1) / tspi->bytes_per_word + 1;
+		max_word = min(max_word, tspi->max_buf_size/4);
+		tspi->curr_dma_words = max_word;
+		total_fifo_words = max_word;
+	}
+	return total_fifo_words;
+}
+
+static unsigned tegra_slink_fill_tx_fifo_from_client_txbuf(
+	struct tegra_slink_data *tspi, struct spi_transfer *t)
+{
+	unsigned nbytes;
+	unsigned tx_empty_count;
+	unsigned long fifo_status;
+	unsigned max_n_32bit;
+	unsigned i, count;
+	unsigned long x;
+	unsigned int written_words;
+	unsigned fifo_words_left;
+	u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
+
+	fifo_status = tegra_slink_readl(tspi, SLINK_STATUS2);
+	tx_empty_count = SLINK_TX_FIFO_EMPTY_COUNT(fifo_status);
+
+	if (tspi->is_packed) {
+		fifo_words_left = tx_empty_count * tspi->words_per_32bit;
+		written_words = min(fifo_words_left, tspi->curr_dma_words);
+		nbytes = written_words * tspi->bytes_per_word;
+		max_n_32bit = DIV_ROUND_UP(nbytes, 4);
+		for (count = 0; count < max_n_32bit; count++) {
+			x = 0;
+			for (i = 0; (i < 4) && nbytes; i++, nbytes--)
+				x |= (*tx_buf++) << (i*8);
+			tegra_slink_writel(tspi, x, SLINK_TX_FIFO);
+		}
+	} else {
+		max_n_32bit = min(tspi->curr_dma_words,  tx_empty_count);
+		written_words = max_n_32bit;
+		nbytes = written_words * tspi->bytes_per_word;
+		for (count = 0; count < max_n_32bit; count++) {
+			x = 0;
+			for (i = 0; nbytes && (i < tspi->bytes_per_word);
+							i++, nbytes--)
+				x |= ((*tx_buf++) << i*8);
+			tegra_slink_writel(tspi, x, SLINK_TX_FIFO);
+		}
+	}
+	tspi->cur_tx_pos += written_words * tspi->bytes_per_word;
+	return written_words;
+}
+
+static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
+		struct tegra_slink_data *tspi, struct spi_transfer *t)
+{
+	unsigned rx_full_count;
+	unsigned long fifo_status;
+	unsigned i, count;
+	unsigned long x;
+	unsigned int read_words = 0;
+	unsigned len;
+	u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_rx_pos;
+
+	fifo_status = tegra_slink_readl(tspi, SLINK_STATUS2);
+	rx_full_count = SLINK_RX_FIFO_FULL_COUNT(fifo_status);
+	if (tspi->is_packed) {
+		len = tspi->curr_dma_words * tspi->bytes_per_word;
+		for (count = 0; count < rx_full_count; count++) {
+			x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
+			for (i = 0; len && (i < 4); i++, len--)
+				*rx_buf++ = (x >> i*8) & 0xFF;
+		}
+		tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
+		read_words += tspi->curr_dma_words;
+	} else {
+		unsigned int bits_per_word;
+
+		bits_per_word = t->bits_per_word ? t->bits_per_word :
+						tspi->cur_spi->bits_per_word;
+		for (count = 0; count < rx_full_count; count++) {
+			x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
+			for (i = 0; (i < tspi->bytes_per_word); i++)
+				*rx_buf++ = (x >> (i*8)) & 0xFF;
+		}
+		tspi->cur_rx_pos += rx_full_count * tspi->bytes_per_word;
+		read_words += rx_full_count;
+	}
+	return read_words;
+}
+
+static void tegra_slink_copy_client_txbuf_to_spi_txbuf(
+		struct tegra_slink_data *tspi, struct spi_transfer *t)
+{
+	unsigned len;
+
+	/* Make the dma buffer to read by cpu */
+	dma_sync_single_for_cpu(tspi->dev, tspi->tx_dma_phys,
+				tspi->dma_buf_size, DMA_TO_DEVICE);
+
+	if (tspi->is_packed) {
+		len = tspi->curr_dma_words * tspi->bytes_per_word;
+		memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len);
+	} else {
+		unsigned int i;
+		unsigned int count;
+		u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
+		unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word;
+		unsigned int x;
+
+		for (count = 0; count < tspi->curr_dma_words; count++) {
+			x = 0;
+			for (i = 0; consume && (i < tspi->bytes_per_word);
+							i++, consume--)
+				x |= ((*tx_buf++) << i * 8);
+			tspi->tx_dma_buf[count] = x;
+		}
+	}
+	tspi->cur_tx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
+
+	/* Make the dma buffer to read by dma */
+	dma_sync_single_for_device(tspi->dev, tspi->tx_dma_phys,
+				tspi->dma_buf_size, DMA_TO_DEVICE);
+}
+
+static void tegra_slink_copy_spi_rxbuf_to_client_rxbuf(
+		struct tegra_slink_data *tspi, struct spi_transfer *t)
+{
+	unsigned len;
+
+	/* Make the dma buffer to read by cpu */
+	dma_sync_single_for_cpu(tspi->dev, tspi->rx_dma_phys,
+		tspi->dma_buf_size, DMA_FROM_DEVICE);
+
+	if (tspi->is_packed) {
+		len = tspi->curr_dma_words * tspi->bytes_per_word;
+		memcpy(t->rx_buf + tspi->cur_rx_pos, tspi->rx_dma_buf, len);
+	} else {
+		unsigned int i;
+		unsigned int count;
+		unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos;
+		unsigned int x;
+		unsigned int rx_mask, bits_per_word;
+
+		bits_per_word = t->bits_per_word ? t->bits_per_word :
+						tspi->cur_spi->bits_per_word;
+		rx_mask = (1 << bits_per_word) - 1;
+		for (count = 0; count < tspi->curr_dma_words; count++) {
+			x = tspi->rx_dma_buf[count];
+			x &= rx_mask;
+			for (i = 0; (i < tspi->bytes_per_word); i++)
+				*rx_buf++ = (x >> (i*8)) & 0xFF;
+		}
+	}
+	tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
+
+	/* Make the dma buffer to read by dma */
+	dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys,
+		tspi->dma_buf_size, DMA_FROM_DEVICE);
+}
+
+static void tegra_slink_dma_complete(void *args)
+{
+	struct completion *dma_complete = args;
+
+	complete(dma_complete);
+}
+
+static int tegra_slink_start_tx_dma(struct tegra_slink_data *tspi, int len)
+{
+	INIT_COMPLETION(tspi->tx_dma_complete);
+	tspi->tx_dma_desc = dmaengine_prep_slave_single(tspi->tx_dma_chan,
+				tspi->tx_dma_phys, len, DMA_MEM_TO_DEV,
+				DMA_PREP_INTERRUPT |  DMA_CTRL_ACK);
+	if (!tspi->tx_dma_desc) {
+		dev_err(tspi->dev, "Not able to get desc for Tx\n");
+		return -EIO;
+	}
+
+	tspi->tx_dma_desc->callback = tegra_slink_dma_complete;
+	tspi->tx_dma_desc->callback_param = &tspi->tx_dma_complete;
+
+	dmaengine_submit(tspi->tx_dma_desc);
+	dma_async_issue_pending(tspi->tx_dma_chan);
+	return 0;
+}
+
+static int tegra_slink_start_rx_dma(struct tegra_slink_data *tspi, int len)
+{
+	INIT_COMPLETION(tspi->rx_dma_complete);
+	tspi->rx_dma_desc = dmaengine_prep_slave_single(tspi->rx_dma_chan,
+				tspi->rx_dma_phys, len, DMA_DEV_TO_MEM,
+				DMA_PREP_INTERRUPT |  DMA_CTRL_ACK);
+	if (!tspi->rx_dma_desc) {
+		dev_err(tspi->dev, "Not able to get desc for Rx\n");
+		return -EIO;
+	}
+
+	tspi->rx_dma_desc->callback = tegra_slink_dma_complete;
+	tspi->rx_dma_desc->callback_param = &tspi->rx_dma_complete;
+
+	dmaengine_submit(tspi->rx_dma_desc);
+	dma_async_issue_pending(tspi->rx_dma_chan);
+	return 0;
+}
+
+static int tegra_slink_start_dma_based_transfer(
+		struct tegra_slink_data *tspi, struct spi_transfer *t)
+{
+	unsigned long val;
+	unsigned long test_val;
+	unsigned int len;
+	int ret = 0;
+	unsigned long status;
+
+	/* Make sure that Rx and Tx fifo are empty */
+	status = tegra_slink_readl(tspi, SLINK_STATUS);
+	if ((status & SLINK_FIFO_EMPTY) != SLINK_FIFO_EMPTY) {
+		dev_err(tspi->dev,
+			"Rx/Tx fifo are not empty status 0x%08lx\n", status);
+		return -EIO;
+	}
+
+	val = SLINK_DMA_BLOCK_SIZE(tspi->curr_dma_words - 1);
+	val |= tspi->packed_size;
+	if (tspi->is_packed)
+		len = DIV_ROUND_UP(tspi->curr_dma_words * tspi->bytes_per_word,
+					4) * 4;
+	else
+		len = tspi->curr_dma_words * 4;
+
+	/* Set attention level based on length of transfer */
+	if (len & 0xF)
+		val |= SLINK_TX_TRIG_1 | SLINK_RX_TRIG_1;
+	else if (((len) >> 4) & 0x1)
+		val |= SLINK_TX_TRIG_4 | SLINK_RX_TRIG_4;
+	else
+		val |= SLINK_TX_TRIG_8 | SLINK_RX_TRIG_8;
+
+	if (tspi->cur_direction & DATA_DIR_TX)
+		val |= SLINK_IE_TXC;
+
+	if (tspi->cur_direction & DATA_DIR_RX)
+		val |= SLINK_IE_RXC;
+
+	tegra_slink_writel(tspi, val, SLINK_DMA_CTL);
+	tspi->dma_control_reg = val;
+
+	if (tspi->cur_direction & DATA_DIR_TX) {
+		tegra_slink_copy_client_txbuf_to_spi_txbuf(tspi, t);
+		wmb();
+		ret = tegra_slink_start_tx_dma(tspi, len);
+		if (ret < 0) {
+			dev_err(tspi->dev,
+				"Starting tx dma failed, err %d\n", ret);
+			return ret;
+		}
+
+		/* Wait for tx fifo to be fill before starting slink */
+		test_val = tegra_slink_readl(tspi, SLINK_STATUS);
+		while (!(test_val & SLINK_TX_FULL))
+			test_val = tegra_slink_readl(tspi, SLINK_STATUS);
+	}
+
+	if (tspi->cur_direction & DATA_DIR_RX) {
+		/* Make the dma buffer to read by dma */
+		dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys,
+				tspi->dma_buf_size, DMA_FROM_DEVICE);
+
+		ret = tegra_slink_start_rx_dma(tspi, len);
+		if (ret < 0) {
+			dev_err(tspi->dev,
+				"Starting rx dma failed, err %d\n", ret);
+			if (tspi->cur_direction & DATA_DIR_TX)
+				dmaengine_terminate_all(tspi->tx_dma_chan);
+			return ret;
+		}
+	}
+	tspi->is_curr_dma_xfer = true;
+	if (tspi->is_packed) {
+		val |= SLINK_PACKED;
+		tegra_slink_writel(tspi, val, SLINK_DMA_CTL);
+		/* HW need small delay after settign Packed mode */
+		udelay(1);
+	}
+	tspi->dma_control_reg = val;
+
+	val |= SLINK_DMA_EN;
+	tegra_slink_writel(tspi, val, SLINK_DMA_CTL);
+	return ret;
+}
+
+static int tegra_slink_start_cpu_based_transfer(
+		struct tegra_slink_data *tspi, struct spi_transfer *t)
+{
+	unsigned long val;
+	unsigned cur_words;
+
+	val = tspi->packed_size;
+	if (tspi->cur_direction & DATA_DIR_TX)
+		val |= SLINK_IE_TXC;
+
+	if (tspi->cur_direction & DATA_DIR_RX)
+		val |= SLINK_IE_RXC;
+
+	tegra_slink_writel(tspi, val, SLINK_DMA_CTL);
+	tspi->dma_control_reg = val;
+
+	if (tspi->cur_direction & DATA_DIR_TX)
+		cur_words = tegra_slink_fill_tx_fifo_from_client_txbuf(tspi, t);
+	else
+		cur_words = tspi->curr_dma_words;
+	val |= SLINK_DMA_BLOCK_SIZE(cur_words - 1);
+	tegra_slink_writel(tspi, val, SLINK_DMA_CTL);
+	tspi->dma_control_reg = val;
+
+	tspi->is_curr_dma_xfer = false;
+	if (tspi->is_packed) {
+		val |= SLINK_PACKED;
+		tegra_slink_writel(tspi, val, SLINK_DMA_CTL);
+		udelay(1);
+		wmb();
+	}
+	tspi->dma_control_reg = val;
+	val |= SLINK_DMA_EN;
+	tegra_slink_writel(tspi, val, SLINK_DMA_CTL);
+	return 0;
+}
+
+static int tegra_slink_init_dma_param(struct tegra_slink_data *tspi,
+			bool dma_to_memory)
+{
+	struct dma_chan *dma_chan;
+	u32 *dma_buf;
+	dma_addr_t dma_phys;
+	int ret;
+	struct dma_slave_config dma_sconfig;
+	dma_cap_mask_t mask;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	dma_chan = dma_request_channel(mask, NULL, NULL);
+	if (!dma_chan) {
+		dev_err(tspi->dev,
+			"Dma channel is not available, will try later\n");
+		return -EPROBE_DEFER;
+	}
+
+	dma_buf = dma_alloc_coherent(tspi->dev, tspi->dma_buf_size,
+				&dma_phys, GFP_KERNEL);
+	if (!dma_buf) {
+		dev_err(tspi->dev, " Not able to allocate the dma buffer\n");
+		dma_release_channel(dma_chan);
+		return -ENOMEM;
+	}
+
+	dma_sconfig.slave_id = tspi->dma_req_sel;
+	if (dma_to_memory) {
+		dma_sconfig.src_addr = tspi->phys + SLINK_RX_FIFO;
+		dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+		dma_sconfig.src_maxburst = 0;
+	} else {
+		dma_sconfig.dst_addr = tspi->phys + SLINK_TX_FIFO;
+		dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+		dma_sconfig.dst_maxburst = 0;
+	}
+
+	ret = dmaengine_slave_config(dma_chan, &dma_sconfig);
+	if (ret)
+		goto scrub;
+	if (dma_to_memory) {
+		tspi->rx_dma_chan = dma_chan;
+		tspi->rx_dma_buf = dma_buf;
+		tspi->rx_dma_phys = dma_phys;
+	} else {
+		tspi->tx_dma_chan = dma_chan;
+		tspi->tx_dma_buf = dma_buf;
+		tspi->tx_dma_phys = dma_phys;
+	}
+	return 0;
+
+scrub:
+	dma_free_coherent(tspi->dev, tspi->dma_buf_size, dma_buf, dma_phys);
+	dma_release_channel(dma_chan);
+	return ret;
+}
+
+static void tegra_slink_deinit_dma_param(struct tegra_slink_data *tspi,
+	bool dma_to_memory)
+{
+	u32 *dma_buf;
+	dma_addr_t dma_phys;
+	struct dma_chan *dma_chan;
+
+	if (dma_to_memory) {
+		dma_buf = tspi->rx_dma_buf;
+		dma_chan = tspi->rx_dma_chan;
+		dma_phys = tspi->rx_dma_phys;
+		tspi->rx_dma_chan = NULL;
+		tspi->rx_dma_buf = NULL;
+	} else {
+		dma_buf = tspi->tx_dma_buf;
+		dma_chan = tspi->tx_dma_chan;
+		dma_phys = tspi->tx_dma_phys;
+		tspi->tx_dma_buf = NULL;
+		tspi->tx_dma_chan = NULL;
+	}
+	if (!dma_chan)
+		return;
+
+	dma_free_coherent(tspi->dev, tspi->dma_buf_size, dma_buf, dma_phys);
+	dma_release_channel(dma_chan);
+}
+
+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 tegra_slink_data *tspi = spi_master_get_devdata(spi->master);
+	u32 speed;
+	u8 bits_per_word;
+	unsigned total_fifo_words;
+	int ret;
+	struct tegra_spi_device_controller_data *cdata = spi->controller_data;
+	unsigned long command;
+	unsigned long command2;
+
+	bits_per_word = t->bits_per_word;
+	speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz;
+	if (!speed)
+		speed = tspi->spi_max_frequency;
+	if (speed != tspi->cur_speed) {
+		clk_set_rate(tspi->clk, speed * 4);
+		tspi->cur_speed = speed;
+	}
+
+	tspi->cur_spi = spi;
+	tspi->cur_pos = 0;
+	tspi->cur_rx_pos = 0;
+	tspi->cur_tx_pos = 0;
+	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->def_command_reg;
+		command |= SLINK_BIT_LENGTH(bits_per_word - 1);
+
+		command2 = tspi->def_command2_reg;
+		command2 |= SLINK_SS_EN_CS(spi->chip_select);
+
+		/* possibly use the hw based chip select */
+		tspi->is_hw_based_cs = false;
+		if (cdata && cdata->is_hw_based_cs && is_single_xfer &&
+			((tspi->curr_dma_words * tspi->bytes_per_word) ==
+						(t->len - tspi->cur_pos))) {
+			int setup_count;
+			int sts2;
+
+			setup_count = cdata->cs_setup_clk_count >> 1;
+			setup_count = max(setup_count, 3);
+			command2 |= SLINK_SS_SETUP(setup_count);
+			if (tspi->chip_data->cs_hold_time) {
+				int hold_count;
+
+				hold_count = cdata->cs_hold_clk_count;
+				hold_count = max(hold_count, 0xF);
+				sts2 = tegra_slink_readl(tspi, SLINK_STATUS2);
+				sts2 &= ~SLINK_SS_HOLD_TIME(0xF);
+				sts2 |= SLINK_SS_HOLD_TIME(hold_count);
+				tegra_slink_writel(tspi, sts2, SLINK_STATUS2);
+			}
+			tspi->is_hw_based_cs = true;
+		}
+
+		if (tspi->is_hw_based_cs)
+			command &= ~SLINK_CS_SW;
+		else
+			command |= SLINK_CS_SW | SLINK_CS_VALUE;
+
+		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);
+	}
+
+	tegra_slink_writel(tspi, command, SLINK_COMMAND);
+	tspi->command_reg = command;
+
+	tspi->cur_direction = 0;
+	if (t->rx_buf) {
+		command2 |= SLINK_RXEN;
+		tspi->cur_direction |= DATA_DIR_RX;
+	}
+	if (t->tx_buf) {
+		command2 |= SLINK_TXEN;
+		tspi->cur_direction |= DATA_DIR_TX;
+	}
+	tegra_slink_writel(tspi, command2, SLINK_COMMAND2);
+	tspi->command2_reg = command2;
+
+	if (total_fifo_words > SLINK_FIFO_DEPTH)
+		ret = tegra_slink_start_dma_based_transfer(tspi, t);
+	else
+		ret = tegra_slink_start_cpu_based_transfer(tspi, t);
+	return ret;
+}
+
+static int tegra_slink_setup(struct spi_device *spi)
+{
+	struct tegra_slink_data *tspi = spi_master_get_devdata(spi->master);
+	unsigned long val;
+	unsigned long flags;
+	int ret;
+	unsigned int cs_pol_bit[MAX_CHIP_SELECT] = {
+			SLINK_CS_POLARITY,
+			SLINK_CS_POLARITY1,
+			SLINK_CS_POLARITY2,
+			SLINK_CS_POLARITY3,
+	};
+
+	dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n",
+		spi->bits_per_word,
+		spi->mode & SPI_CPOL ? "" : "~",
+		spi->mode & SPI_CPHA ? "" : "~",
+		spi->max_speed_hz);
+
+	BUG_ON(spi->chip_select >= MAX_CHIP_SELECT);
+
+	ret = pm_runtime_get_sync(tspi->dev);
+	if (ret < 0) {
+		dev_err(tspi->dev, "pm runtime failed, e = %d\n", ret);
+		return ret;
+	}
+
+	spin_lock_irqsave(&tspi->lock, flags);
+	val = tspi->def_command_reg;
+	if (spi->mode & SPI_CS_HIGH)
+		val |= cs_pol_bit[spi->chip_select];
+	else
+		val &= ~cs_pol_bit[spi->chip_select];
+	tspi->def_command_reg = val;
+	tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND);
+	spin_unlock_irqrestore(&tspi->lock, flags);
+
+	pm_runtime_put(tspi->dev);
+	return 0;
+}
+
+static int tegra_slink_prepare_transfer(struct spi_master *master)
+{
+	struct tegra_slink_data *tspi = spi_master_get_devdata(master);
+
+	return pm_runtime_get_sync(tspi->dev);
+}
+
+static int tegra_slink_unprepare_transfer(struct spi_master *master)
+{
+	struct tegra_slink_data *tspi = spi_master_get_devdata(master);
+
+	pm_runtime_put(tspi->dev);
+	return 0;
+}
+
+static int tegra_slink_transfer_one_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;
+	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);
+		}
+	}
+	ret = 0;
+exit:
+	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;
+}
+
+static irqreturn_t handle_cpu_based_xfer(struct tegra_slink_data *tspi)
+{
+	struct spi_transfer *t = tspi->curr_xfer;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tspi->lock, flags);
+	if (tspi->tx_status ||  tspi->rx_status ||
+				(tspi->status_reg & SLINK_BSY)) {
+		dev_err(tspi->dev,
+			"CpuXfer ERROR bit set 0x%x\n", tspi->status_reg);
+		dev_err(tspi->dev,
+			"CpuXfer 0x%08x:0x%08x:0x%08x\n", tspi->command_reg,
+				tspi->command2_reg, tspi->dma_control_reg);
+		tegra_periph_reset_assert(tspi->clk);
+		udelay(2);
+		tegra_periph_reset_deassert(tspi->clk);
+		complete(&tspi->xfer_completion);
+		goto exit;
+	}
+
+	if (tspi->cur_direction & DATA_DIR_RX)
+		tegra_slink_read_rx_fifo_to_client_rxbuf(tspi, t);
+
+	if (tspi->cur_direction & DATA_DIR_TX)
+		tspi->cur_pos = tspi->cur_tx_pos;
+	else
+		tspi->cur_pos = tspi->cur_rx_pos;
+
+	if (tspi->cur_pos == t->len) {
+		complete(&tspi->xfer_completion);
+		goto exit;
+	}
+
+	tegra_slink_calculate_curr_xfer_param(tspi->cur_spi, tspi, t);
+	tegra_slink_start_cpu_based_transfer(tspi, t);
+exit:
+	spin_unlock_irqrestore(&tspi->lock, flags);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t handle_dma_based_xfer(struct tegra_slink_data *tspi)
+{
+	struct spi_transfer *t = tspi->curr_xfer;
+	long wait_status;
+	int err = 0;
+	unsigned total_fifo_words;
+	unsigned long flags;
+
+	/* Abort dmas if any error */
+	if (tspi->cur_direction & DATA_DIR_TX) {
+		if (tspi->tx_status) {
+			dmaengine_terminate_all(tspi->tx_dma_chan);
+			err += 1;
+		} else {
+			wait_status = wait_for_completion_interruptible_timeout(
+				&tspi->tx_dma_complete, SLINK_DMA_TIMEOUT);
+			if (wait_status <= 0) {
+				dmaengine_terminate_all(tspi->tx_dma_chan);
+				dev_err(tspi->dev, "TxDma Xfer failed\n");
+				err += 1;
+			}
+		}
+	}
+
+	if (tspi->cur_direction & DATA_DIR_RX) {
+		if (tspi->rx_status) {
+			dmaengine_terminate_all(tspi->rx_dma_chan);
+			err += 2;
+		} else {
+			wait_status = wait_for_completion_interruptible_timeout(
+				&tspi->rx_dma_complete, SLINK_DMA_TIMEOUT);
+			if (wait_status <= 0) {
+				dmaengine_terminate_all(tspi->rx_dma_chan);
+				dev_err(tspi->dev, "RxDma Xfer failed\n");
+				err += 2;
+			}
+		}
+	}
+
+	spin_lock_irqsave(&tspi->lock, flags);
+	if (err) {
+		dev_err(tspi->dev,
+			"DmaXfer: ERROR bit set 0x%x\n", tspi->status_reg);
+		dev_err(tspi->dev,
+			"DmaXfer 0x%08x:0x%08x:0x%08x\n", tspi->command_reg,
+				tspi->command2_reg, tspi->dma_control_reg);
+		tegra_periph_reset_assert(tspi->clk);
+		udelay(2);
+		tegra_periph_reset_deassert(tspi->clk);
+		complete(&tspi->xfer_completion);
+		spin_unlock_irqrestore(&tspi->lock, flags);
+		return IRQ_HANDLED;
+	}
+
+	if (tspi->cur_direction & DATA_DIR_RX)
+		tegra_slink_copy_spi_rxbuf_to_client_rxbuf(tspi, t);
+
+	if (tspi->cur_direction & DATA_DIR_TX)
+		tspi->cur_pos = tspi->cur_tx_pos;
+	else
+		tspi->cur_pos = tspi->cur_rx_pos;
+
+	if (tspi->cur_pos == t->len) {
+		complete(&tspi->xfer_completion);
+		goto exit;
+	}
+
+	/* Continue transfer in current message */
+	total_fifo_words = tegra_slink_calculate_curr_xfer_param(tspi->cur_spi,
+							tspi, t);
+	if (total_fifo_words > SLINK_FIFO_DEPTH)
+		err = tegra_slink_start_dma_based_transfer(tspi, t);
+	else
+		err = tegra_slink_start_cpu_based_transfer(tspi, t);
+
+exit:
+	spin_unlock_irqrestore(&tspi->lock, flags);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t tegra_slink_isr_thread(int irq, void *context_data)
+{
+	struct tegra_slink_data *tspi = context_data;
+
+	if (!tspi->is_curr_dma_xfer)
+		return handle_cpu_based_xfer(tspi);
+	return handle_dma_based_xfer(tspi);
+}
+
+static irqreturn_t tegra_slink_isr(int irq, void *context_data)
+{
+	struct tegra_slink_data *tspi = context_data;
+
+	tspi->status_reg = tegra_slink_readl(tspi, SLINK_STATUS);
+	if (tspi->cur_direction & DATA_DIR_TX)
+		tspi->tx_status = tspi->status_reg &
+					(SLINK_TX_OVF | SLINK_TX_UNF);
+
+	if (tspi->cur_direction & DATA_DIR_RX)
+		tspi->rx_status = tspi->status_reg &
+					(SLINK_RX_OVF | SLINK_RX_UNF);
+	tegra_slink_clear_status(tspi);
+
+	return IRQ_WAKE_THREAD;
+}
+
+static struct tegra_spi_platform_data *tegra_slink_parse_dt(
+		struct platform_device *pdev)
+{
+	struct tegra_spi_platform_data *pdata;
+	const unsigned int *prop;
+	struct device_node *np = pdev->dev.of_node;
+	u32 of_dma[2];
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		dev_err(&pdev->dev, "Memory alloc for pdata failed\n");
+		return NULL;
+	}
+
+	if (of_property_read_u32_array(np, "nvidia,dma-request-selector",
+				of_dma, 2) >= 0)
+		pdata->dma_req_sel = of_dma[1];
+
+	prop = of_get_property(np, "spi-max-frequency", NULL);
+	if (prop)
+		pdata->spi_max_frequency = be32_to_cpup(prop);
+
+	return pdata;
+}
+
+const struct tegra_slink_chip_data tegra30_spi_cdata = {
+	.cs_hold_time = true,
+};
+
+const struct tegra_slink_chip_data tegra20_spi_cdata = {
+	.cs_hold_time = false,
+};
+
+static struct of_device_id tegra_slink_of_match[] __devinitconst = {
+	{ .compatible = "nvidia,tegra30-slink", .data = &tegra30_spi_cdata, },
+	{ .compatible = "nvidia,tegra20-slink", .data = &tegra20_spi_cdata, },
+	{}
+};
+MODULE_DEVICE_TABLE(of, tegra_slink_of_match);
+
+static int __devinit tegra_slink_probe(struct platform_device *pdev)
+{
+	struct spi_master	*master;
+	struct tegra_slink_data	*tspi;
+	struct resource		*r;
+	struct tegra_spi_platform_data *pdata = pdev->dev.platform_data;
+	int ret, spi_irq;
+	const struct tegra_slink_chip_data *cdata = NULL;
+	const struct of_device_id *match;
+
+	match = of_match_device(of_match_ptr(tegra_slink_of_match), &pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "Error: No device match found\n");
+		return -ENODEV;
+	}
+	cdata = match->data;
+	if (!pdata && pdev->dev.of_node)
+		pdata = tegra_slink_parse_dt(pdev);
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "No platform data, exiting\n");
+		return -ENODEV;
+	}
+
+	if (!pdata->spi_max_frequency)
+		pdata->spi_max_frequency = 25000000; /* 25MHz */
+
+	master = spi_alloc_master(&pdev->dev, sizeof(*tspi));
+	if (!master) {
+		dev_err(&pdev->dev, "master allocation failed\n");
+		return -ENOMEM;
+	}
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+	master->setup = tegra_slink_setup;
+	master->prepare_transfer_hardware = tegra_slink_prepare_transfer;
+	master->transfer_one_message = tegra_slink_transfer_one_message;
+	master->unprepare_transfer_hardware = tegra_slink_unprepare_transfer;
+	master->num_chipselect = MAX_CHIP_SELECT;
+	master->bus_num = -1;
+
+	dev_set_drvdata(&pdev->dev, master);
+	tspi = spi_master_get_devdata(master);
+	tspi->master = master;
+	tspi->dma_req_sel = pdata->dma_req_sel;
+	tspi->dev = &pdev->dev;
+	tspi->chip_data = cdata;
+	spin_lock_init(&tspi->lock);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		dev_err(&pdev->dev, "No IO memory resource\n");
+		ret = -ENODEV;
+		goto exit_free_master;
+	}
+	tspi->phys = r->start;
+	tspi->base = devm_request_and_ioremap(&pdev->dev, r);
+	if (!tspi->base) {
+		dev_err(&pdev->dev,
+			"Cannot request memregion/iomap dma address\n");
+		ret = -EADDRNOTAVAIL;
+		goto exit_free_master;
+	}
+
+	spi_irq = platform_get_irq(pdev, 0);
+	tspi->irq = spi_irq;
+	ret = request_threaded_irq(tspi->irq, tegra_slink_isr,
+			tegra_slink_isr_thread, IRQF_ONESHOT,
+			dev_name(&pdev->dev), tspi);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n",
+					tspi->irq);
+		goto exit_free_master;
+	}
+
+	tspi->clk = devm_clk_get(&pdev->dev, "slink");
+	if (IS_ERR(tspi->clk)) {
+		dev_err(&pdev->dev, "can not get clock\n");
+		ret = PTR_ERR(tspi->clk);
+		goto exit_free_irq;
+	}
+
+	tspi->max_buf_size = SLINK_FIFO_DEPTH << 2;
+	tspi->dma_buf_size = DEFAULT_SPI_DMA_BUF_LEN;
+	tspi->spi_max_frequency = pdata->spi_max_frequency;
+
+	if (pdata->dma_req_sel) {
+		ret = tegra_slink_init_dma_param(tspi, true);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "RxDma Init failed, err %d\n", ret);
+			goto exit_free_irq;
+		}
+
+		ret = tegra_slink_init_dma_param(tspi, false);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "TxDma Init failed, err %d\n", ret);
+			goto exit_rx_dma_free;
+		}
+		tspi->max_buf_size = tspi->dma_buf_size;
+		init_completion(&tspi->tx_dma_complete);
+		init_completion(&tspi->rx_dma_complete);
+	}
+
+	init_completion(&tspi->xfer_completion);
+
+	pm_runtime_enable(&pdev->dev);
+	if (!pm_runtime_enabled(&pdev->dev)) {
+		ret = tegra_slink_runtime_resume(&pdev->dev);
+		if (ret)
+			goto exit_pm_disable;
+	}
+
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret);
+		goto exit_pm_disable;
+	}
+	tspi->def_command_reg  = SLINK_M_S;
+	tspi->def_command2_reg = SLINK_CS_ACTIVE_BETWEEN;
+	tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND);
+	tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2);
+	pm_runtime_put(&pdev->dev);
+
+	master->dev.of_node = pdev->dev.of_node;
+	ret = spi_register_master(master);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "can not register to master err %d\n", ret);
+		goto exit_pm_disable;
+	}
+	return ret;
+
+exit_pm_disable:
+	pm_runtime_disable(&pdev->dev);
+	if (!pm_runtime_status_suspended(&pdev->dev))
+		tegra_slink_runtime_suspend(&pdev->dev);
+	tegra_slink_deinit_dma_param(tspi, false);
+exit_rx_dma_free:
+	tegra_slink_deinit_dma_param(tspi, true);
+exit_free_irq:
+	free_irq(spi_irq, tspi);
+exit_free_master:
+	spi_master_put(master);
+	return ret;
+}
+
+static int __devexit tegra_slink_remove(struct platform_device *pdev)
+{
+	struct spi_master *master = dev_get_drvdata(&pdev->dev);
+	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);
+
+	if (tspi->rx_dma_chan)
+		tegra_slink_deinit_dma_param(tspi, true);
+
+	pm_runtime_disable(&pdev->dev);
+	if (!pm_runtime_status_suspended(&pdev->dev))
+		tegra_slink_runtime_suspend(&pdev->dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra_slink_suspend(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+
+	return spi_master_suspend(master);
+}
+
+static int tegra_slink_resume(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct tegra_slink_data *tspi = spi_master_get_devdata(master);
+	int ret;
+
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0) {
+		dev_err(dev, "pm runtime failed, e = %d\n", ret);
+		return ret;
+	}
+	tegra_slink_writel(tspi, tspi->command_reg, SLINK_COMMAND);
+	tegra_slink_writel(tspi, tspi->command2_reg, SLINK_COMMAND2);
+	pm_runtime_put(dev);
+
+	return spi_master_resume(master);
+}
+#endif
+
+static int tegra_slink_runtime_suspend(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct tegra_slink_data *tspi = spi_master_get_devdata(master);
+
+	/* Flush all write which are in PPSB queue by reading back */
+	tegra_slink_readl(tspi, SLINK_MAS_DATA);
+
+	clk_disable_unprepare(tspi->clk);
+	return 0;
+}
+
+static int tegra_slink_runtime_resume(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct tegra_slink_data *tspi = spi_master_get_devdata(master);
+	int ret;
+
+	ret = clk_prepare_enable(tspi->clk);
+	if (ret < 0) {
+		dev_err(tspi->dev, "clk_prepare failed: %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+static const struct dev_pm_ops slink_pm_ops = {
+	SET_RUNTIME_PM_OPS(tegra_slink_runtime_suspend,
+		tegra_slink_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(tegra_slink_suspend, tegra_slink_resume)
+};
+static struct platform_driver tegra_slink_driver = {
+	.driver = {
+		.name		= "spi-tegra-slink",
+		.owner		= THIS_MODULE,
+		.pm		= &slink_pm_ops,
+		.of_match_table	= of_match_ptr(tegra_slink_of_match),
+	},
+	.probe =	tegra_slink_probe,
+	.remove =	__devexit_p(tegra_slink_remove),
+};
+module_platform_driver(tegra_slink_driver);
+
+MODULE_ALIAS("platform:spi-tegra-slink");
+MODULE_DESCRIPTION("NVIDIA Tegra20/Tegra30 SLINK Controller Driver");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 84c2861..39c0391 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -30,11 +30,14 @@
 #include <linux/slab.h>
 #include <linux/mod_devicetable.h>
 #include <linux/spi/spi.h>
+#include <linux/of_gpio.h>
 #include <linux/pm_runtime.h>
 #include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
+#include <linux/ioport.h>
+#include <linux/acpi.h>
 
 static void spidev_release(struct device *dev)
 {
@@ -93,6 +96,10 @@ static int spi_match_device(struct device *dev, struct device_driver *drv)
 	if (of_driver_match_device(dev, drv))
 		return 1;
 
+	/* Then try ACPI */
+	if (acpi_driver_match_device(dev, drv))
+		return 1;
+
 	if (sdrv->id_table)
 		return !!spi_match_id(sdrv->id_table, spi);
 
@@ -327,6 +334,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master)
 	spi->dev.parent = &master->dev;
 	spi->dev.bus = &spi_bus_type;
 	spi->dev.release = spidev_release;
+	spi->cs_gpio = -EINVAL;
 	device_initialize(&spi->dev);
 	return spi;
 }
@@ -344,15 +352,16 @@ EXPORT_SYMBOL_GPL(spi_alloc_device);
 int spi_add_device(struct spi_device *spi)
 {
 	static DEFINE_MUTEX(spi_add_lock);
-	struct device *dev = spi->master->dev.parent;
+	struct spi_master *master = spi->master;
+	struct device *dev = master->dev.parent;
 	struct device *d;
 	int status;
 
 	/* Chipselects are numbered 0..max; validate. */
-	if (spi->chip_select >= spi->master->num_chipselect) {
+	if (spi->chip_select >= master->num_chipselect) {
 		dev_err(dev, "cs%d >= max %d\n",
 			spi->chip_select,
-			spi->master->num_chipselect);
+			master->num_chipselect);
 		return -EINVAL;
 	}
 
@@ -376,6 +385,9 @@ int spi_add_device(struct spi_device *spi)
 		goto done;
 	}
 
+	if (master->cs_gpios)
+		spi->cs_gpio = master->cs_gpios[spi->chip_select];
+
 	/* Drivers may modify this initial i/o setup, but will
 	 * normally rely on the device being setup.  Devices
 	 * using SPI_CS_HIGH can't coexist well otherwise...
@@ -888,6 +900,100 @@ static void of_register_spi_devices(struct spi_master *master)
 static void of_register_spi_devices(struct spi_master *master) { }
 #endif
 
+#ifdef CONFIG_ACPI
+static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
+{
+	struct spi_device *spi = data;
+
+	if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+		struct acpi_resource_spi_serialbus *sb;
+
+		sb = &ares->data.spi_serial_bus;
+		if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_SPI) {
+			spi->chip_select = sb->device_selection;
+			spi->max_speed_hz = sb->connection_speed;
+
+			if (sb->clock_phase == ACPI_SPI_SECOND_PHASE)
+				spi->mode |= SPI_CPHA;
+			if (sb->clock_polarity == ACPI_SPI_START_HIGH)
+				spi->mode |= SPI_CPOL;
+			if (sb->device_polarity == ACPI_SPI_ACTIVE_HIGH)
+				spi->mode |= SPI_CS_HIGH;
+		}
+	} else if (spi->irq < 0) {
+		struct resource r;
+
+		if (acpi_dev_resource_interrupt(ares, 0, &r))
+			spi->irq = r.start;
+	}
+
+	/* Always tell the ACPI core to skip this resource */
+	return 1;
+}
+
+static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level,
+				       void *data, void **return_value)
+{
+	struct spi_master *master = data;
+	struct list_head resource_list;
+	struct acpi_device *adev;
+	struct spi_device *spi;
+	int ret;
+
+	if (acpi_bus_get_device(handle, &adev))
+		return AE_OK;
+	if (acpi_bus_get_status(adev) || !adev->status.present)
+		return AE_OK;
+
+	spi = spi_alloc_device(master);
+	if (!spi) {
+		dev_err(&master->dev, "failed to allocate SPI device for %s\n",
+			dev_name(&adev->dev));
+		return AE_NO_MEMORY;
+	}
+
+	ACPI_HANDLE_SET(&spi->dev, handle);
+	spi->irq = -1;
+
+	INIT_LIST_HEAD(&resource_list);
+	ret = acpi_dev_get_resources(adev, &resource_list,
+				     acpi_spi_add_resource, spi);
+	acpi_dev_free_resource_list(&resource_list);
+
+	if (ret < 0 || !spi->max_speed_hz) {
+		spi_dev_put(spi);
+		return AE_OK;
+	}
+
+	strlcpy(spi->modalias, dev_name(&adev->dev), 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));
+		spi_dev_put(spi);
+	}
+
+	return AE_OK;
+}
+
+static void acpi_register_spi_devices(struct spi_master *master)
+{
+	acpi_status status;
+	acpi_handle handle;
+
+	handle = ACPI_HANDLE(&master->dev);
+	if (!handle)
+		return;
+
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+				     acpi_spi_add_device, NULL,
+				     master, NULL);
+	if (ACPI_FAILURE(status))
+		dev_warn(&master->dev, "failed to enumerate SPI slaves\n");
+}
+#else
+static inline void acpi_register_spi_devices(struct spi_master *master) {}
+#endif /* CONFIG_ACPI */
+
 static void spi_master_release(struct device *dev)
 {
 	struct spi_master *master;
@@ -946,6 +1052,44 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
 }
 EXPORT_SYMBOL_GPL(spi_alloc_master);
 
+#ifdef CONFIG_OF
+static int of_spi_register_master(struct spi_master *master)
+{
+	u16 nb;
+	int i, *cs;
+	struct device_node *np = master->dev.of_node;
+
+	if (!np)
+		return 0;
+
+	nb = of_gpio_named_count(np, "cs-gpios");
+	master->num_chipselect = max(nb, master->num_chipselect);
+
+	if (nb < 1)
+		return 0;
+
+	cs = devm_kzalloc(&master->dev,
+			  sizeof(int) * master->num_chipselect,
+			  GFP_KERNEL);
+	master->cs_gpios = cs;
+
+	if (!master->cs_gpios)
+		return -ENOMEM;
+
+	memset(cs, -EINVAL, master->num_chipselect);
+
+	for (i = 0; i < nb; i++)
+		cs[i] = of_get_named_gpio(np, "cs-gpios", i);
+
+	return 0;
+}
+#else
+static int of_spi_register_master(struct spi_master *master)
+{
+	return 0;
+}
+#endif
+
 /**
  * spi_register_master - register SPI master controller
  * @master: initialized master, originally from spi_alloc_master()
@@ -977,6 +1121,10 @@ int spi_register_master(struct spi_master *master)
 	if (!dev)
 		return -ENODEV;
 
+	status = of_spi_register_master(master);
+	if (status)
+		return status;
+
 	/* even if it's just one always-selected device, there must
 	 * be at least one chipselect
 	 */
@@ -1023,8 +1171,9 @@ int spi_register_master(struct spi_master *master)
 		spi_match_master_to_boardinfo(master, &bi->board_info);
 	mutex_unlock(&board_lock);
 
-	/* Register devices from the device tree */
+	/* Register devices from the device tree and ACPI */
 	of_register_spi_devices(master);
+	acpi_register_spi_devices(master);
 done:
 	return status;
 }
@@ -1156,7 +1305,7 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master);
 int spi_setup(struct spi_device *spi)
 {
 	unsigned	bad_bits;
-	int		status;
+	int		status = 0;
 
 	/* help drivers fail *cleanly* when they need options
 	 * that aren't supported with their current master
@@ -1171,7 +1320,8 @@ int spi_setup(struct spi_device *spi)
 	if (!spi->bits_per_word)
 		spi->bits_per_word = 8;
 
-	status = spi->master->setup(spi);
+	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",
@@ -1190,6 +1340,7 @@ EXPORT_SYMBOL_GPL(spi_setup);
 static int __spi_async(struct spi_device *spi, struct spi_message *message)
 {
 	struct spi_master *master = spi->master;
+	struct spi_transfer *xfer;
 
 	/* Half-duplex links include original MicroWire, and ones with
 	 * only one data pin like SPI_3WIRE (switches direction) or where
@@ -1198,7 +1349,6 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
 	 */
 	if ((master->flags & SPI_MASTER_HALF_DUPLEX)
 			|| (spi->mode & SPI_3WIRE)) {
-		struct spi_transfer *xfer;
 		unsigned flags = master->flags;
 
 		list_for_each_entry(xfer, &message->transfers, transfer_list) {
@@ -1211,6 +1361,15 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
 		}
 	}
 
+	/**
+	 * Set transfer bits_per_word as spi device default if it is not
+	 * set for this transfer.
+	 */
+	list_for_each_entry(xfer, &message->transfers, transfer_list) {
+		if (!xfer->bits_per_word)
+			xfer->bits_per_word = spi->bits_per_word;
+	}
+
 	message->spi = spi;
 	message->status = -EINPROGRESS;
 	return master->transfer(spi, message);
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 830adbe..e44abc9 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -31,6 +31,8 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/compat.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spidev.h>
@@ -642,10 +644,18 @@ static int __devexit spidev_remove(struct spi_device *spi)
 	return 0;
 }
 
+static const struct of_device_id spidev_dt_ids[] = {
+	{ .compatible = "rohm,dh2228fv" },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, spidev_dt_ids);
+
 static struct spi_driver spidev_spi_driver = {
 	.driver = {
 		.name =		"spidev",
 		.owner =	THIS_MODULE,
+		.of_match_table = of_match_ptr(spidev_dt_ids),
 	},
 	.probe =	spidev_probe,
 	.remove =	__devexit_p(spidev_remove),
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
index 42cdaa9..ff3c8a2 100644
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -160,4 +160,13 @@ config SSB_DRIVER_GIGE
 
 	  If unsure, say N
 
+config SSB_DRIVER_GPIO
+	bool "SSB GPIO driver"
+	depends on SSB
+	select GPIOLIB
+	help
+	  Driver to provide access to the GPIO pins on the bus.
+
+	  If unsure, say N
+
 endmenu
diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile
index 656e58b..9159ba7 100644
--- a/drivers/ssb/Makefile
+++ b/drivers/ssb/Makefile
@@ -15,6 +15,7 @@ ssb-$(CONFIG_SSB_DRIVER_MIPS)		+= driver_mipscore.o
 ssb-$(CONFIG_SSB_DRIVER_EXTIF)		+= driver_extif.o
 ssb-$(CONFIG_SSB_DRIVER_PCICORE)	+= driver_pcicore.o
 ssb-$(CONFIG_SSB_DRIVER_GIGE)		+= driver_gige.o
+ssb-$(CONFIG_SSB_DRIVER_GPIO)		+= driver_gpio.o
 
 # b43 pci-ssb-bridge driver
 # Not strictly a part of SSB, but kept here for convenience
diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c
index 266aa16..19396dc 100644
--- a/drivers/ssb/b43_pci_bridge.c
+++ b/drivers/ssb/b43_pci_bridge.c
@@ -37,6 +37,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432c) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4350) },
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl);
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
index e9d2ca1..24e02bb 100644
--- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c
@@ -284,6 +284,9 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc)
 {
 	if (!cc->dev)
 		return; /* We don't have a ChipCommon */
+
+	spin_lock_init(&cc->gpio_lock);
+
 	if (cc->dev->id.revision >= 11)
 		cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT);
 	ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status);
@@ -418,28 +421,93 @@ u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask)
 
 u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value)
 {
-	return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value);
+	unsigned long flags;
+	u32 res = 0;
+
+	spin_lock_irqsave(&cc->gpio_lock, flags);
+	res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value);
+	spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+	return res;
 }
 
 u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value)
 {
-	return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value);
+	unsigned long flags;
+	u32 res = 0;
+
+	spin_lock_irqsave(&cc->gpio_lock, flags);
+	res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value);
+	spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+	return res;
 }
 
 u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value)
 {
-	return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value);
+	unsigned long flags;
+	u32 res = 0;
+
+	spin_lock_irqsave(&cc->gpio_lock, flags);
+	res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value);
+	spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+	return res;
 }
 EXPORT_SYMBOL(ssb_chipco_gpio_control);
 
 u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value)
 {
-	return chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value);
+	unsigned long flags;
+	u32 res = 0;
+
+	spin_lock_irqsave(&cc->gpio_lock, flags);
+	res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value);
+	spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+	return res;
 }
 
 u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value)
 {
-	return chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value);
+	unsigned long flags;
+	u32 res = 0;
+
+	spin_lock_irqsave(&cc->gpio_lock, flags);
+	res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value);
+	spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+	return res;
+}
+
+u32 ssb_chipco_gpio_pullup(struct ssb_chipcommon *cc, u32 mask, u32 value)
+{
+	unsigned long flags;
+	u32 res = 0;
+
+	if (cc->dev->id.revision < 20)
+		return 0xffffffff;
+
+	spin_lock_irqsave(&cc->gpio_lock, flags);
+	res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPULLUP, mask, value);
+	spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+	return res;
+}
+
+u32 ssb_chipco_gpio_pulldown(struct ssb_chipcommon *cc, u32 mask, u32 value)
+{
+	unsigned long flags;
+	u32 res = 0;
+
+	if (cc->dev->id.revision < 20)
+		return 0xffffffff;
+
+	spin_lock_irqsave(&cc->gpio_lock, flags);
+	res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPULLDOWN, mask, value);
+	spin_unlock_irqrestore(&cc->gpio_lock, flags);
+
+	return res;
 }
 
 #ifdef CONFIG_SSB_SERIAL
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c
index b58fef7..d7d5804 100644
--- a/drivers/ssb/driver_chipcommon_pmu.c
+++ b/drivers/ssb/driver_chipcommon_pmu.c
@@ -346,6 +346,8 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc)
 			chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0);
 		}
 		break;
+	case 43222:
+		break;
 	default:
 		ssb_printk(KERN_ERR PFX
 			   "ERROR: PLL init unknown for device %04X\n",
@@ -434,6 +436,7 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc)
 		 min_msk = 0xCBB;
 		 break;
 	case 0x4322:
+	case 43222:
 		/* We keep the default settings:
 		 * min_msk = 0xCBB
 		 * max_msk = 0x7FFFF
diff --git a/drivers/ssb/driver_extif.c b/drivers/ssb/driver_extif.c
index dc47f30..e1d0bb8 100644
--- a/drivers/ssb/driver_extif.c
+++ b/drivers/ssb/driver_extif.c
@@ -118,6 +118,13 @@ void ssb_extif_watchdog_timer_set(struct ssb_extif *extif,
 	extif_write32(extif, SSB_EXTIF_WATCHDOG, ticks);
 }
 
+void ssb_extif_init(struct ssb_extif *extif)
+{
+	if (!extif->dev)
+		return; /* We don't have a Extif core */
+	spin_lock_init(&extif->gpio_lock);
+}
+
 u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
 {
 	return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask;
@@ -125,22 +132,50 @@ u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
 
 u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value)
 {
-	return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0),
+	unsigned long flags;
+	u32 res = 0;
+
+	spin_lock_irqsave(&extif->gpio_lock, flags);
+	res = extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0),
 				   mask, value);
+	spin_unlock_irqrestore(&extif->gpio_lock, flags);
+
+	return res;
 }
 
 u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value)
 {
-	return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0),
+	unsigned long flags;
+	u32 res = 0;
+
+	spin_lock_irqsave(&extif->gpio_lock, flags);
+	res = extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0),
 				   mask, value);
+	spin_unlock_irqrestore(&extif->gpio_lock, flags);
+
+	return res;
 }
 
 u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value)
 {
-	return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value);
+	unsigned long flags;
+	u32 res = 0;
+
+	spin_lock_irqsave(&extif->gpio_lock, flags);
+	res = extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value);
+	spin_unlock_irqrestore(&extif->gpio_lock, flags);
+
+	return res;
 }
 
 u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value)
 {
-	return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value);
+	unsigned long flags;
+	u32 res = 0;
+
+	spin_lock_irqsave(&extif->gpio_lock, flags);
+	res = extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value);
+	spin_unlock_irqrestore(&extif->gpio_lock, flags);
+
+	return res;
 }
diff --git a/drivers/ssb/driver_gpio.c b/drivers/ssb/driver_gpio.c
new file mode 100644
index 0000000..97ac0a3
--- /dev/null
+++ b/drivers/ssb/driver_gpio.c
@@ -0,0 +1,176 @@
+/*
+ * Sonics Silicon Backplane
+ * GPIO driver
+ *
+ * Copyright 2011, Broadcom Corporation
+ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/gpio.h>
+#include <linux/export.h>
+#include <linux/ssb/ssb.h>
+
+#include "ssb_private.h"
+
+static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip)
+{
+	return container_of(chip, struct ssb_bus, gpio);
+}
+
+static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+	return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio);
+}
+
+static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio,
+				      int value)
+{
+	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+	ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
+}
+
+static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip,
+					   unsigned gpio)
+{
+	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+	ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0);
+	return 0;
+}
+
+static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip,
+					    unsigned gpio, int value)
+{
+	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+	ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio);
+	ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
+	return 0;
+}
+
+static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio)
+{
+	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+	ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0);
+	/* clear pulldown */
+	ssb_chipco_gpio_pulldown(&bus->chipco, 1 << gpio, 0);
+	/* Set pullup */
+	ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 1 << gpio);
+
+	return 0;
+}
+
+static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio)
+{
+	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+	/* clear pullup */
+	ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0);
+}
+
+static int ssb_gpio_chipco_init(struct ssb_bus *bus)
+{
+	struct gpio_chip *chip = &bus->gpio;
+
+	chip->label		= "ssb_chipco_gpio";
+	chip->owner		= THIS_MODULE;
+	chip->request		= ssb_gpio_chipco_request;
+	chip->free		= ssb_gpio_chipco_free;
+	chip->get		= ssb_gpio_chipco_get_value;
+	chip->set		= ssb_gpio_chipco_set_value;
+	chip->direction_input	= ssb_gpio_chipco_direction_input;
+	chip->direction_output	= ssb_gpio_chipco_direction_output;
+	chip->ngpio		= 16;
+	/* There is just one SoC in one device and its GPIO addresses should be
+	 * deterministic to address them more easily. The other buses could get
+	 * a random base number. */
+	if (bus->bustype == SSB_BUSTYPE_SSB)
+		chip->base		= 0;
+	else
+		chip->base		= -1;
+
+	return gpiochip_add(chip);
+}
+
+#ifdef CONFIG_SSB_DRIVER_EXTIF
+
+static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+	return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio);
+}
+
+static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio,
+				     int value)
+{
+	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+	ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
+}
+
+static int ssb_gpio_extif_direction_input(struct gpio_chip *chip,
+					  unsigned gpio)
+{
+	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+	ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0);
+	return 0;
+}
+
+static int ssb_gpio_extif_direction_output(struct gpio_chip *chip,
+					   unsigned gpio, int value)
+{
+	struct ssb_bus *bus = ssb_gpio_get_bus(chip);
+
+	ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio);
+	ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
+	return 0;
+}
+
+static int ssb_gpio_extif_init(struct ssb_bus *bus)
+{
+	struct gpio_chip *chip = &bus->gpio;
+
+	chip->label		= "ssb_extif_gpio";
+	chip->owner		= THIS_MODULE;
+	chip->get		= ssb_gpio_extif_get_value;
+	chip->set		= ssb_gpio_extif_set_value;
+	chip->direction_input	= ssb_gpio_extif_direction_input;
+	chip->direction_output	= ssb_gpio_extif_direction_output;
+	chip->ngpio		= 5;
+	/* There is just one SoC in one device and its GPIO addresses should be
+	 * deterministic to address them more easily. The other buses could get
+	 * a random base number. */
+	if (bus->bustype == SSB_BUSTYPE_SSB)
+		chip->base		= 0;
+	else
+		chip->base		= -1;
+
+	return gpiochip_add(chip);
+}
+
+#else
+static int ssb_gpio_extif_init(struct ssb_bus *bus)
+{
+	return -ENOTSUPP;
+}
+#endif
+
+int ssb_gpio_init(struct ssb_bus *bus)
+{
+	if (ssb_chipco_available(&bus->chipco))
+		return ssb_gpio_chipco_init(bus);
+	else if (ssb_extif_available(&bus->extif))
+		return ssb_gpio_extif_init(bus);
+	else
+		SSB_WARN_ON(1);
+
+	return -1;
+}
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
index c625086..b918ba9 100644
--- a/drivers/ssb/driver_mipscore.c
+++ b/drivers/ssb/driver_mipscore.c
@@ -192,9 +192,10 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore)
 
 	/* When there is no chipcommon on the bus there is 4MB flash */
 	if (!bus->chipco.dev) {
-		mcore->flash_buswidth = 2;
-		mcore->flash_window = SSB_FLASH1;
-		mcore->flash_window_size = SSB_FLASH1_SZ;
+		mcore->pflash.present = true;
+		mcore->pflash.buswidth = 2;
+		mcore->pflash.window = SSB_FLASH1;
+		mcore->pflash.window_size = SSB_FLASH1_SZ;
 		return;
 	}
 
@@ -206,13 +207,14 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore)
 		break;
 	case SSB_CHIPCO_FLASHT_PARA:
 		pr_debug("Found parallel flash\n");
-		mcore->flash_window = SSB_FLASH2;
-		mcore->flash_window_size = SSB_FLASH2_SZ;
+		mcore->pflash.present = true;
+		mcore->pflash.window = SSB_FLASH2;
+		mcore->pflash.window_size = SSB_FLASH2_SZ;
 		if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG)
 		               & SSB_CHIPCO_CFG_DS16) == 0)
-			mcore->flash_buswidth = 1;
+			mcore->pflash.buswidth = 1;
 		else
-			mcore->flash_buswidth = 2;
+			mcore->pflash.buswidth = 2;
 		break;
 	}
 }
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index df0f145..87f0ddf 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -796,7 +796,14 @@ static int __devinit ssb_bus_register(struct ssb_bus *bus,
 	if (err)
 		goto err_pcmcia_exit;
 	ssb_chipcommon_init(&bus->chipco);
+	ssb_extif_init(&bus->extif);
 	ssb_mipscore_init(&bus->mipscore);
+	err = ssb_gpio_init(bus);
+	if (err == -ENOTSUPP)
+		ssb_dprintk(KERN_DEBUG PFX "GPIO driver not activated\n");
+	else if (err)
+		ssb_dprintk(KERN_ERR PFX
+			   "Error registering GPIO driver: %i\n", err);
 	err = ssb_fetch_invariants(bus, get_invariants);
 	if (err) {
 		ssb_bus_may_powerdown(bus);
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h
index a305550..463b76a2 100644
--- a/drivers/ssb/ssb_private.h
+++ b/drivers/ssb/ssb_private.h
@@ -211,4 +211,21 @@ static inline void b43_pci_ssb_bridge_exit(void)
 extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc);
 extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc);
 
+#ifdef CONFIG_SSB_DRIVER_EXTIF
+extern void ssb_extif_init(struct ssb_extif *extif);
+#else
+static inline void ssb_extif_init(struct ssb_extif *extif)
+{
+}
+#endif
+
+#ifdef CONFIG_SSB_DRIVER_GPIO
+extern int ssb_gpio_init(struct ssb_bus *bus);
+#else /* CONFIG_SSB_DRIVER_GPIO */
+static inline int ssb_gpio_init(struct ssb_bus *bus)
+{
+	return -ENOTSUPP;
+}
+#endif /* CONFIG_SSB_DRIVER_GPIO */
+
 #endif /* LINUX_SSB_PRIVATE_H_ */
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index d805eef..329bdb4 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -52,8 +52,6 @@ source "drivers/staging/rtl8192e/Kconfig"
 
 source "drivers/staging/rtl8712/Kconfig"
 
-source "drivers/staging/rts_pstor/Kconfig"
-
 source "drivers/staging/rts5139/Kconfig"
 
 source "drivers/staging/frontier/Kconfig"
@@ -120,14 +118,10 @@ source "drivers/staging/omapdrm/Kconfig"
 
 source "drivers/staging/android/Kconfig"
 
-source "drivers/staging/telephony/Kconfig"
-
 source "drivers/staging/ozwpan/Kconfig"
 
 source "drivers/staging/ccg/Kconfig"
 
-source "drivers/staging/ipack/Kconfig"
-
 source "drivers/staging/gdm72xx/Kconfig"
 
 source "drivers/staging/csr/Kconfig"
@@ -144,4 +138,8 @@ source "drivers/staging/imx-drm/Kconfig"
 
 source "drivers/staging/dgrp/Kconfig"
 
+source "drivers/staging/sb105x/Kconfig"
+
+source "drivers/staging/fwserial/Kconfig"
+
 endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 76e2ebd..c7ec486 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -19,7 +19,6 @@ obj-$(CONFIG_R8187SE)		+= rtl8187se/
 obj-$(CONFIG_RTL8192U)		+= rtl8192u/
 obj-$(CONFIG_RTL8192E)		+= rtl8192e/
 obj-$(CONFIG_R8712U)		+= rtl8712/
-obj-$(CONFIG_RTS_PSTOR)		+= rts_pstor/
 obj-$(CONFIG_RTS5139)		+= rts5139/
 obj-$(CONFIG_TRANZPORT)		+= frontier/
 obj-$(CONFIG_IDE_PHISON)	+= phison/
@@ -29,7 +28,6 @@ obj-$(CONFIG_OCTEON_ETHERNET)	+= octeon/
 obj-$(CONFIG_VT6655)		+= vt6655/
 obj-$(CONFIG_VT6656)		+= vt6656/
 obj-$(CONFIG_VME_BUS)		+= vme/
-obj-$(CONFIG_IPACK_BUS)		+= ipack/
 obj-$(CONFIG_DX_SEP)            += sep/
 obj-$(CONFIG_IIO)		+= iio/
 obj-$(CONFIG_ZRAM)		+= zram/
@@ -53,7 +51,6 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4)	+= ste_rmi4/
 obj-$(CONFIG_MFD_NVEC)		+= nvec/
 obj-$(CONFIG_DRM_OMAP)		+= omapdrm/
 obj-$(CONFIG_ANDROID)		+= android/
-obj-$(CONFIG_PHONE)		+= telephony/
 obj-$(CONFIG_USB_WPAN_HCD)	+= ozwpan/
 obj-$(CONFIG_USB_G_CCG)		+= ccg/
 obj-$(CONFIG_WIMAX_GDM72XX)	+= gdm72xx/
@@ -64,3 +61,5 @@ obj-$(CONFIG_NET_VENDOR_SILICOM)	+= silicom/
 obj-$(CONFIG_CED1401)		+= ced1401/
 obj-$(CONFIG_DRM_IMX)		+= imx-drm/
 obj-$(CONFIG_DGRP)		+= dgrp/
+obj-$(CONFIG_SB105X)		+= sb105x/
+obj-$(CONFIG_FIREWIRE_SERIAL)	+= fwserial/
diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile
index e16fcd5..b35a631 100644
--- a/drivers/staging/android/Makefile
+++ b/drivers/staging/android/Makefile
@@ -1,3 +1,5 @@
+ccflags-y += -I$(src)			# needed for trace events
+
 obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o
 obj-$(CONFIG_ASHMEM)			+= ashmem.o
 obj-$(CONFIG_ANDROID_LOGGER)		+= logger.o
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 5d4610b..2d12e8a 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -15,6 +15,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <asm/cacheflush.h>
 #include <linux/fdtable.h>
 #include <linux/file.h>
@@ -33,10 +35,12 @@
 #include <linux/uaccess.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
+#include <linux/pid_namespace.h>
 
 #include "binder.h"
+#include "binder_trace.h"
 
-static DEFINE_MUTEX(binder_lock);
+static DEFINE_MUTEX(binder_main_lock);
 static DEFINE_MUTEX(binder_deferred_lock);
 static DEFINE_MUTEX(binder_mmap_lock);
 
@@ -411,6 +415,19 @@ static long task_close_fd(struct binder_proc *proc, unsigned int fd)
 	return retval;
 }
 
+static inline void binder_lock(const char *tag)
+{
+	trace_binder_lock(tag);
+	mutex_lock(&binder_main_lock);
+	trace_binder_locked(tag);
+}
+
+static inline void binder_unlock(const char *tag)
+{
+	trace_binder_unlock(tag);
+	mutex_unlock(&binder_main_lock);
+}
+
 static void binder_set_nice(long nice)
 {
 	long min_nice;
@@ -420,12 +437,12 @@ static void binder_set_nice(long nice)
 	}
 	min_nice = 20 - current->signal->rlim[RLIMIT_NICE].rlim_cur;
 	binder_debug(BINDER_DEBUG_PRIORITY_CAP,
-		     "binder: %d: nice value %ld not allowed use "
-		     "%ld instead\n", current->pid, nice, min_nice);
+		     "%d: nice value %ld not allowed use %ld instead\n",
+		      current->pid, nice, min_nice);
 	set_user_nice(current, min_nice);
 	if (min_nice < 20)
 		return;
-	binder_user_error("binder: %d RLIMIT_NICE not set\n", current->pid);
+	binder_user_error("%d RLIMIT_NICE not set\n", current->pid);
 }
 
 static size_t binder_buffer_size(struct binder_proc *proc,
@@ -452,8 +469,8 @@ static void binder_insert_free_buffer(struct binder_proc *proc,
 	new_buffer_size = binder_buffer_size(proc, new_buffer);
 
 	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-		     "binder: %d: add free buffer, size %zd, "
-		     "at %p\n", proc->pid, new_buffer_size, new_buffer);
+		     "%d: add free buffer, size %zd, at %p\n",
+		      proc->pid, new_buffer_size, new_buffer);
 
 	while (*p) {
 		parent = *p;
@@ -531,12 +548,14 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
 	struct mm_struct *mm;
 
 	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-		     "binder: %d: %s pages %p-%p\n", proc->pid,
+		     "%d: %s pages %p-%p\n", proc->pid,
 		     allocate ? "allocate" : "free", start, end);
 
 	if (end <= start)
 		return 0;
 
+	trace_binder_update_page_range(proc, allocate, start, end);
+
 	if (vma)
 		mm = NULL;
 	else
@@ -546,7 +565,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
 		down_write(&mm->mmap_sem);
 		vma = proc->vma;
 		if (vma && mm != proc->vma_vm_mm) {
-			pr_err("binder: %d: vma mm and task mm mismatch\n",
+			pr_err("%d: vma mm and task mm mismatch\n",
 				proc->pid);
 			vma = NULL;
 		}
@@ -556,8 +575,8 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
 		goto free_range;
 
 	if (vma == NULL) {
-		pr_err("binder: %d: binder_alloc_buf failed to "
-		       "map pages in userspace, no vma\n", proc->pid);
+		pr_err("%d: binder_alloc_buf failed to map pages in userspace, no vma\n",
+			proc->pid);
 		goto err_no_vma;
 	}
 
@@ -569,8 +588,8 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
 		BUG_ON(*page);
 		*page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
 		if (*page == NULL) {
-			pr_err("binder: %d: binder_alloc_buf failed "
-			       "for page at %p\n", proc->pid, page_addr);
+			pr_err("%d: binder_alloc_buf failed for page at %p\n",
+				proc->pid, page_addr);
 			goto err_alloc_page_failed;
 		}
 		tmp_area.addr = page_addr;
@@ -578,8 +597,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
 		page_array_ptr = page;
 		ret = map_vm_area(&tmp_area, PAGE_KERNEL, &page_array_ptr);
 		if (ret) {
-			pr_err("binder: %d: binder_alloc_buf failed "
-			       "to map page at %p in kernel\n",
+			pr_err("%d: binder_alloc_buf failed to map page at %p in kernel\n",
 			       proc->pid, page_addr);
 			goto err_map_kernel_failed;
 		}
@@ -587,8 +605,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
 			(uintptr_t)page_addr + proc->user_buffer_offset;
 		ret = vm_insert_page(vma, user_page_addr, page[0]);
 		if (ret) {
-			pr_err("binder: %d: binder_alloc_buf failed "
-			       "to map page at %lx in userspace\n",
+			pr_err("%d: binder_alloc_buf failed to map page at %lx in userspace\n",
 			       proc->pid, user_page_addr);
 			goto err_vm_insert_page_failed;
 		}
@@ -636,7 +653,7 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
 	size_t size;
 
 	if (proc->vma == NULL) {
-		pr_err("binder: %d: binder_alloc_buf, no vma\n",
+		pr_err("%d: binder_alloc_buf, no vma\n",
 		       proc->pid);
 		return NULL;
 	}
@@ -645,16 +662,16 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
 		ALIGN(offsets_size, sizeof(void *));
 
 	if (size < data_size || size < offsets_size) {
-		binder_user_error("binder: %d: got transaction with invalid "
-			"size %zd-%zd\n", proc->pid, data_size, offsets_size);
+		binder_user_error("%d: got transaction with invalid size %zd-%zd\n",
+				proc->pid, data_size, offsets_size);
 		return NULL;
 	}
 
 	if (is_async &&
 	    proc->free_async_space < size + sizeof(struct binder_buffer)) {
 		binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-			     "binder: %d: binder_alloc_buf size %zd"
-			     "failed, no async space left\n", proc->pid, size);
+			     "%d: binder_alloc_buf size %zd failed, no async space left\n",
+			      proc->pid, size);
 		return NULL;
 	}
 
@@ -674,8 +691,8 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
 		}
 	}
 	if (best_fit == NULL) {
-		pr_err("binder: %d: binder_alloc_buf size %zd failed, "
-		       "no address space\n", proc->pid, size);
+		pr_err("%d: binder_alloc_buf size %zd failed, no address space\n",
+			proc->pid, size);
 		return NULL;
 	}
 	if (n == NULL) {
@@ -684,8 +701,8 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
 	}
 
 	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-		     "binder: %d: binder_alloc_buf size %zd got buff"
-		     "er %p size %zd\n", proc->pid, size, buffer, buffer_size);
+		     "%d: binder_alloc_buf size %zd got buffer %p size %zd\n",
+		      proc->pid, size, buffer, buffer_size);
 
 	has_page_addr =
 		(void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK);
@@ -713,17 +730,16 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
 		binder_insert_free_buffer(proc, new_buffer);
 	}
 	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-		     "binder: %d: binder_alloc_buf size %zd got "
-		     "%p\n", proc->pid, size, buffer);
+		     "%d: binder_alloc_buf size %zd got %p\n",
+		      proc->pid, size, buffer);
 	buffer->data_size = data_size;
 	buffer->offsets_size = offsets_size;
 	buffer->async_transaction = is_async;
 	if (is_async) {
 		proc->free_async_space -= size + sizeof(struct binder_buffer);
 		binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
-			     "binder: %d: binder_alloc_buf size %zd "
-			     "async free %zd\n", proc->pid, size,
-			     proc->free_async_space);
+			     "%d: binder_alloc_buf size %zd async free %zd\n",
+			      proc->pid, size, proc->free_async_space);
 	}
 
 	return buffer;
@@ -754,8 +770,8 @@ static void binder_delete_free_buffer(struct binder_proc *proc,
 		if (buffer_end_page(prev) == buffer_end_page(buffer))
 			free_page_end = 0;
 		binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-			     "binder: %d: merge free, buffer %p "
-			     "share page with %p\n", proc->pid, buffer, prev);
+			     "%d: merge free, buffer %p share page with %p\n",
+			      proc->pid, buffer, prev);
 	}
 
 	if (!list_is_last(&buffer->entry, &proc->buffers)) {
@@ -767,16 +783,14 @@ static void binder_delete_free_buffer(struct binder_proc *proc,
 			    buffer_start_page(buffer))
 				free_page_start = 0;
 			binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-				     "binder: %d: merge free, buffer"
-				     " %p share page with %p\n", proc->pid,
-				     buffer, prev);
+				     "%d: merge free, buffer %p share page with %p\n",
+				      proc->pid, buffer, prev);
 		}
 	}
 	list_del(&buffer->entry);
 	if (free_page_start || free_page_end) {
 		binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-			     "binder: %d: merge free, buffer %p do "
-			     "not share page%s%s with with %p or %p\n",
+			     "%d: merge free, buffer %p do not share page%s%s with with %p or %p\n",
 			     proc->pid, buffer, free_page_start ? "" : " end",
 			     free_page_end ? "" : " start", prev, next);
 		binder_update_page_range(proc, 0, free_page_start ?
@@ -797,8 +811,8 @@ static void binder_free_buf(struct binder_proc *proc,
 		ALIGN(buffer->offsets_size, sizeof(void *));
 
 	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-		     "binder: %d: binder_free_buf %p size %zd buffer"
-		     "_size %zd\n", proc->pid, buffer, size, buffer_size);
+		     "%d: binder_free_buf %p size %zd buffer_size %zd\n",
+		      proc->pid, buffer, size, buffer_size);
 
 	BUG_ON(buffer->free);
 	BUG_ON(size > buffer_size);
@@ -810,9 +824,8 @@ static void binder_free_buf(struct binder_proc *proc,
 		proc->free_async_space += size + sizeof(struct binder_buffer);
 
 		binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
-			     "binder: %d: binder_free_buf size %zd "
-			     "async free %zd\n", proc->pid, size,
-			     proc->free_async_space);
+			     "%d: binder_free_buf size %zd async free %zd\n",
+			      proc->pid, size, proc->free_async_space);
 	}
 
 	binder_update_page_range(proc, 0,
@@ -894,7 +907,7 @@ static struct binder_node *binder_new_node(struct binder_proc *proc,
 	INIT_LIST_HEAD(&node->work.entry);
 	INIT_LIST_HEAD(&node->async_todo);
 	binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-		     "binder: %d:%d node %d u%p c%p created\n",
+		     "%d:%d node %d u%p c%p created\n",
 		     proc->pid, current->pid, node->debug_id,
 		     node->ptr, node->cookie);
 	return node;
@@ -909,8 +922,8 @@ static int binder_inc_node(struct binder_node *node, int strong, int internal,
 			    node->internal_strong_refs == 0 &&
 			    !(node == binder_context_mgr_node &&
 			    node->has_strong_ref)) {
-				pr_err("binder: invalid inc strong "
-					"node for %d\n", node->debug_id);
+				pr_err("invalid inc strong node for %d\n",
+					node->debug_id);
 				return -EINVAL;
 			}
 			node->internal_strong_refs++;
@@ -925,8 +938,8 @@ static int binder_inc_node(struct binder_node *node, int strong, int internal,
 			node->local_weak_refs++;
 		if (!node->has_weak_ref && list_empty(&node->work.entry)) {
 			if (target_list == NULL) {
-				pr_err("binder: invalid inc weak node "
-					"for %d\n", node->debug_id);
+				pr_err("invalid inc weak node for %d\n",
+					node->debug_id);
 				return -EINVAL;
 			}
 			list_add_tail(&node->work.entry, target_list);
@@ -962,12 +975,12 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal)
 			if (node->proc) {
 				rb_erase(&node->rb_node, &node->proc->nodes);
 				binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-					     "binder: refless node %d deleted\n",
+					     "refless node %d deleted\n",
 					     node->debug_id);
 			} else {
 				hlist_del(&node->dead_node);
 				binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-					     "binder: dead node %d deleted\n",
+					     "dead node %d deleted\n",
 					     node->debug_id);
 			}
 			kfree(node);
@@ -1053,14 +1066,13 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
 		hlist_add_head(&new_ref->node_entry, &node->refs);
 
 		binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-			     "binder: %d new ref %d desc %d for "
-			     "node %d\n", proc->pid, new_ref->debug_id,
-			     new_ref->desc, node->debug_id);
+			     "%d new ref %d desc %d for node %d\n",
+			      proc->pid, new_ref->debug_id, new_ref->desc,
+			      node->debug_id);
 	} else {
 		binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-			     "binder: %d new ref %d desc %d for "
-			     "dead node\n", proc->pid, new_ref->debug_id,
-			      new_ref->desc);
+			     "%d new ref %d desc %d for dead node\n",
+			      proc->pid, new_ref->debug_id, new_ref->desc);
 	}
 	return new_ref;
 }
@@ -1068,9 +1080,9 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
 static void binder_delete_ref(struct binder_ref *ref)
 {
 	binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-		     "binder: %d delete ref %d desc %d for "
-		     "node %d\n", ref->proc->pid, ref->debug_id,
-		     ref->desc, ref->node->debug_id);
+		     "%d delete ref %d desc %d for node %d\n",
+		      ref->proc->pid, ref->debug_id, ref->desc,
+		      ref->node->debug_id);
 
 	rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc);
 	rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node);
@@ -1080,9 +1092,8 @@ static void binder_delete_ref(struct binder_ref *ref)
 	binder_dec_node(ref->node, 0, 1);
 	if (ref->death) {
 		binder_debug(BINDER_DEBUG_DEAD_BINDER,
-			     "binder: %d delete ref %d desc %d "
-			     "has death notification\n", ref->proc->pid,
-			     ref->debug_id, ref->desc);
+			     "%d delete ref %d desc %d has death notification\n",
+			      ref->proc->pid, ref->debug_id, ref->desc);
 		list_del(&ref->death->work.entry);
 		kfree(ref->death);
 		binder_stats_deleted(BINDER_STAT_DEATH);
@@ -1118,8 +1129,7 @@ static int binder_dec_ref(struct binder_ref *ref, int strong)
 {
 	if (strong) {
 		if (ref->strong == 0) {
-			binder_user_error("binder: %d invalid dec strong, "
-					  "ref %d desc %d s %d w %d\n",
+			binder_user_error("%d invalid dec strong, ref %d desc %d s %d w %d\n",
 					  ref->proc->pid, ref->debug_id,
 					  ref->desc, ref->strong, ref->weak);
 			return -EINVAL;
@@ -1133,8 +1143,7 @@ static int binder_dec_ref(struct binder_ref *ref, int strong)
 		}
 	} else {
 		if (ref->weak == 0) {
-			binder_user_error("binder: %d invalid dec weak, "
-					  "ref %d desc %d s %d w %d\n",
+			binder_user_error("%d invalid dec weak, ref %d desc %d s %d w %d\n",
 					  ref->proc->pid, ref->debug_id,
 					  ref->desc, ref->strong, ref->weak);
 			return -EINVAL;
@@ -1179,8 +1188,7 @@ static void binder_send_failed_reply(struct binder_transaction *t,
 			}
 			if (target_thread->return_error == BR_OK) {
 				binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-					     "binder: send failed reply for "
-					     "transaction %d to %d:%d\n",
+					     "send failed reply for transaction %d to %d:%d\n",
 					      t->debug_id, target_thread->proc->pid,
 					      target_thread->pid);
 
@@ -1188,9 +1196,8 @@ static void binder_send_failed_reply(struct binder_transaction *t,
 				target_thread->return_error = error_code;
 				wake_up_interruptible(&target_thread->wait);
 			} else {
-				pr_err("binder: reply failed, target "
-					"thread, %d:%d, has error code %d "
-					"already\n", target_thread->proc->pid,
+				pr_err("reply failed, target thread, %d:%d, has error code %d already\n",
+					target_thread->proc->pid,
 					target_thread->pid,
 					target_thread->return_error);
 			}
@@ -1199,21 +1206,19 @@ static void binder_send_failed_reply(struct binder_transaction *t,
 			struct binder_transaction *next = t->from_parent;
 
 			binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-				     "binder: send failed reply "
-				     "for transaction %d, target dead\n",
+				     "send failed reply for transaction %d, target dead\n",
 				     t->debug_id);
 
 			binder_pop_transaction(target_thread, t);
 			if (next == NULL) {
 				binder_debug(BINDER_DEBUG_DEAD_BINDER,
-					     "binder: reply failed,"
-					     " no target thread at root\n");
+					     "reply failed, no target thread at root\n");
 				return;
 			}
 			t = next;
 			binder_debug(BINDER_DEBUG_DEAD_BINDER,
-				     "binder: reply failed, no target "
-				     "thread -- retry %d\n", t->debug_id);
+				     "reply failed, no target thread -- retry %d\n",
+				      t->debug_id);
 		}
 	}
 }
@@ -1226,7 +1231,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
 	int debug_id = buffer->debug_id;
 
 	binder_debug(BINDER_DEBUG_TRANSACTION,
-		     "binder: %d buffer release %d, size %zd-%zd, failed at %p\n",
+		     "%d buffer release %d, size %zd-%zd, failed at %p\n",
 		     proc->pid, buffer->debug_id,
 		     buffer->data_size, buffer->offsets_size, failed_at);
 
@@ -1243,9 +1248,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
 		if (*offp > buffer->data_size - sizeof(*fp) ||
 		    buffer->data_size < sizeof(*fp) ||
 		    !IS_ALIGNED(*offp, sizeof(void *))) {
-			pr_err("binder: transaction release %d bad"
-					"offset %zd, size %zd\n", debug_id,
-					*offp, buffer->data_size);
+			pr_err("transaction release %d bad offset %zd, size %zd\n",
+			 debug_id, *offp, buffer->data_size);
 			continue;
 		}
 		fp = (struct flat_binder_object *)(buffer->data + *offp);
@@ -1254,8 +1258,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
 		case BINDER_TYPE_WEAK_BINDER: {
 			struct binder_node *node = binder_get_node(proc, fp->binder);
 			if (node == NULL) {
-				pr_err("binder: transaction release %d"
-				       " bad node %p\n", debug_id, fp->binder);
+				pr_err("transaction release %d bad node %p\n",
+					debug_id, fp->binder);
 				break;
 			}
 			binder_debug(BINDER_DEBUG_TRANSACTION,
@@ -1267,9 +1271,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
 		case BINDER_TYPE_WEAK_HANDLE: {
 			struct binder_ref *ref = binder_get_ref(proc, fp->handle);
 			if (ref == NULL) {
-				pr_err("binder: transaction release %d"
-				       " bad handle %ld\n", debug_id,
-				       fp->handle);
+				pr_err("transaction release %d bad handle %ld\n",
+				 debug_id, fp->handle);
 				break;
 			}
 			binder_debug(BINDER_DEBUG_TRANSACTION,
@@ -1286,8 +1289,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
 			break;
 
 		default:
-			pr_err("binder: transaction release %d bad "
-			       "object type %lx\n", debug_id, fp->type);
+			pr_err("transaction release %d bad object type %lx\n",
+				debug_id, fp->type);
 			break;
 		}
 	}
@@ -1320,17 +1323,14 @@ static void binder_transaction(struct binder_proc *proc,
 	if (reply) {
 		in_reply_to = thread->transaction_stack;
 		if (in_reply_to == NULL) {
-			binder_user_error("binder: %d:%d got reply transaction "
-					  "with no transaction stack\n",
+			binder_user_error("%d:%d got reply transaction with no transaction stack\n",
 					  proc->pid, thread->pid);
 			return_error = BR_FAILED_REPLY;
 			goto err_empty_call_stack;
 		}
 		binder_set_nice(in_reply_to->saved_priority);
 		if (in_reply_to->to_thread != thread) {
-			binder_user_error("binder: %d:%d got reply transaction "
-				"with bad transaction stack,"
-				" transaction %d has target %d:%d\n",
+			binder_user_error("%d:%d got reply transaction with bad transaction stack, transaction %d has target %d:%d\n",
 				proc->pid, thread->pid, in_reply_to->debug_id,
 				in_reply_to->to_proc ?
 				in_reply_to->to_proc->pid : 0,
@@ -1347,9 +1347,7 @@ static void binder_transaction(struct binder_proc *proc,
 			goto err_dead_binder;
 		}
 		if (target_thread->transaction_stack != in_reply_to) {
-			binder_user_error("binder: %d:%d got reply transaction "
-				"with bad target transaction stack %d, "
-				"expected %d\n",
+			binder_user_error("%d:%d got reply transaction with bad target transaction stack %d, expected %d\n",
 				proc->pid, thread->pid,
 				target_thread->transaction_stack ?
 				target_thread->transaction_stack->debug_id : 0,
@@ -1365,8 +1363,7 @@ static void binder_transaction(struct binder_proc *proc,
 			struct binder_ref *ref;
 			ref = binder_get_ref(proc, tr->target.handle);
 			if (ref == NULL) {
-				binder_user_error("binder: %d:%d got "
-					"transaction to invalid handle\n",
+				binder_user_error("%d:%d got transaction to invalid handle\n",
 					proc->pid, thread->pid);
 				return_error = BR_FAILED_REPLY;
 				goto err_invalid_target_handle;
@@ -1389,9 +1386,7 @@ static void binder_transaction(struct binder_proc *proc,
 			struct binder_transaction *tmp;
 			tmp = thread->transaction_stack;
 			if (tmp->to_thread != thread) {
-				binder_user_error("binder: %d:%d got new "
-					"transaction with bad transaction stack"
-					", transaction %d has target %d:%d\n",
+				binder_user_error("%d:%d got new transaction with bad transaction stack, transaction %d has target %d:%d\n",
 					proc->pid, thread->pid, tmp->debug_id,
 					tmp->to_proc ? tmp->to_proc->pid : 0,
 					tmp->to_thread ?
@@ -1436,16 +1431,14 @@ static void binder_transaction(struct binder_proc *proc,
 
 	if (reply)
 		binder_debug(BINDER_DEBUG_TRANSACTION,
-			     "binder: %d:%d BC_REPLY %d -> %d:%d, "
-			     "data %p-%p size %zd-%zd\n",
+			     "%d:%d BC_REPLY %d -> %d:%d, data %p-%p size %zd-%zd\n",
 			     proc->pid, thread->pid, t->debug_id,
 			     target_proc->pid, target_thread->pid,
 			     tr->data.ptr.buffer, tr->data.ptr.offsets,
 			     tr->data_size, tr->offsets_size);
 	else
 		binder_debug(BINDER_DEBUG_TRANSACTION,
-			     "binder: %d:%d BC_TRANSACTION %d -> "
-			     "%d - node %d, data %p-%p size %zd-%zd\n",
+			     "%d:%d BC_TRANSACTION %d -> %d - node %d, data %p-%p size %zd-%zd\n",
 			     proc->pid, thread->pid, t->debug_id,
 			     target_proc->pid, target_node->debug_id,
 			     tr->data.ptr.buffer, tr->data.ptr.offsets,
@@ -1461,6 +1454,9 @@ static void binder_transaction(struct binder_proc *proc,
 	t->code = tr->code;
 	t->flags = tr->flags;
 	t->priority = task_nice(current);
+
+	trace_binder_transaction(reply, t, target_node);
+
 	t->buffer = binder_alloc_buf(target_proc, tr->data_size,
 		tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
 	if (t->buffer == NULL) {
@@ -1471,27 +1467,27 @@ static void binder_transaction(struct binder_proc *proc,
 	t->buffer->debug_id = t->debug_id;
 	t->buffer->transaction = t;
 	t->buffer->target_node = target_node;
+	trace_binder_transaction_alloc_buf(t->buffer);
 	if (target_node)
 		binder_inc_node(target_node, 1, 0, NULL);
 
 	offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));
 
 	if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {
-		binder_user_error("binder: %d:%d got transaction with invalid "
-			"data ptr\n", proc->pid, thread->pid);
+		binder_user_error("%d:%d got transaction with invalid data ptr\n",
+				proc->pid, thread->pid);
 		return_error = BR_FAILED_REPLY;
 		goto err_copy_data_failed;
 	}
 	if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) {
-		binder_user_error("binder: %d:%d got transaction with invalid "
-			"offsets ptr\n", proc->pid, thread->pid);
+		binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
+				proc->pid, thread->pid);
 		return_error = BR_FAILED_REPLY;
 		goto err_copy_data_failed;
 	}
 	if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) {
-		binder_user_error("binder: %d:%d got transaction with "
-			"invalid offsets size, %zd\n",
-			proc->pid, thread->pid, tr->offsets_size);
+		binder_user_error("%d:%d got transaction with invalid offsets size, %zd\n",
+				proc->pid, thread->pid, tr->offsets_size);
 		return_error = BR_FAILED_REPLY;
 		goto err_bad_offset;
 	}
@@ -1501,9 +1497,8 @@ static void binder_transaction(struct binder_proc *proc,
 		if (*offp > t->buffer->data_size - sizeof(*fp) ||
 		    t->buffer->data_size < sizeof(*fp) ||
 		    !IS_ALIGNED(*offp, sizeof(void *))) {
-			binder_user_error("binder: %d:%d got transaction with "
-				"invalid offset, %zd\n",
-				proc->pid, thread->pid, *offp);
+			binder_user_error("%d:%d got transaction with invalid offset, %zd\n",
+					proc->pid, thread->pid, *offp);
 			return_error = BR_FAILED_REPLY;
 			goto err_bad_offset;
 		}
@@ -1523,8 +1518,7 @@ static void binder_transaction(struct binder_proc *proc,
 				node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
 			}
 			if (fp->cookie != node->cookie) {
-				binder_user_error("binder: %d:%d sending u%p "
-					"node %d, cookie mismatch %p != %p\n",
+				binder_user_error("%d:%d sending u%p node %d, cookie mismatch %p != %p\n",
 					proc->pid, thread->pid,
 					fp->binder, node->debug_id,
 					fp->cookie, node->cookie);
@@ -1543,6 +1537,7 @@ static void binder_transaction(struct binder_proc *proc,
 			binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
 				       &thread->todo);
 
+			trace_binder_transaction_node_to_ref(t, node, ref);
 			binder_debug(BINDER_DEBUG_TRANSACTION,
 				     "        node %d u%p -> ref %d desc %d\n",
 				     node->debug_id, node->ptr, ref->debug_id,
@@ -1552,10 +1547,9 @@ static void binder_transaction(struct binder_proc *proc,
 		case BINDER_TYPE_WEAK_HANDLE: {
 			struct binder_ref *ref = binder_get_ref(proc, fp->handle);
 			if (ref == NULL) {
-				binder_user_error("binder: %d:%d got "
-					"transaction with invalid "
-					"handle, %ld\n", proc->pid,
-					thread->pid, fp->handle);
+				binder_user_error("%d:%d got transaction with invalid handle, %ld\n",
+						proc->pid,
+						thread->pid, fp->handle);
 				return_error = BR_FAILED_REPLY;
 				goto err_binder_get_ref_failed;
 			}
@@ -1567,6 +1561,7 @@ static void binder_transaction(struct binder_proc *proc,
 				fp->binder = ref->node->ptr;
 				fp->cookie = ref->node->cookie;
 				binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
+				trace_binder_transaction_ref_to_node(t, ref);
 				binder_debug(BINDER_DEBUG_TRANSACTION,
 					     "        ref %d desc %d -> node %d u%p\n",
 					     ref->debug_id, ref->desc, ref->node->debug_id,
@@ -1580,6 +1575,8 @@ static void binder_transaction(struct binder_proc *proc,
 				}
 				fp->handle = new_ref->desc;
 				binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
+				trace_binder_transaction_ref_to_ref(t, ref,
+								    new_ref);
 				binder_debug(BINDER_DEBUG_TRANSACTION,
 					     "        ref %d desc %d -> ref %d desc %d (node %d)\n",
 					     ref->debug_id, ref->desc, new_ref->debug_id,
@@ -1593,13 +1590,13 @@ static void binder_transaction(struct binder_proc *proc,
 
 			if (reply) {
 				if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {
-					binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n",
+					binder_user_error("%d:%d got reply with fd, %ld, but target does not allow fds\n",
 						proc->pid, thread->pid, fp->handle);
 					return_error = BR_FAILED_REPLY;
 					goto err_fd_not_allowed;
 				}
 			} else if (!target_node->accept_fds) {
-				binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n",
+				binder_user_error("%d:%d got transaction with fd, %ld, but target does not allow fds\n",
 					proc->pid, thread->pid, fp->handle);
 				return_error = BR_FAILED_REPLY;
 				goto err_fd_not_allowed;
@@ -1607,7 +1604,7 @@ static void binder_transaction(struct binder_proc *proc,
 
 			file = fget(fp->handle);
 			if (file == NULL) {
-				binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n",
+				binder_user_error("%d:%d got transaction with invalid fd, %ld\n",
 					proc->pid, thread->pid, fp->handle);
 				return_error = BR_FAILED_REPLY;
 				goto err_fget_failed;
@@ -1619,6 +1616,7 @@ static void binder_transaction(struct binder_proc *proc,
 				goto err_get_unused_fd_failed;
 			}
 			task_fd_install(target_proc, target_fd, file);
+			trace_binder_transaction_fd(t, fp->handle, target_fd);
 			binder_debug(BINDER_DEBUG_TRANSACTION,
 				     "        fd %ld -> %d\n", fp->handle, target_fd);
 			/* TODO: fput? */
@@ -1626,8 +1624,7 @@ static void binder_transaction(struct binder_proc *proc,
 		} break;
 
 		default:
-			binder_user_error("binder: %d:%d got transactio"
-				"n with invalid object type, %lx\n",
+			binder_user_error("%d:%d got transaction with invalid object type, %lx\n",
 				proc->pid, thread->pid, fp->type);
 			return_error = BR_FAILED_REPLY;
 			goto err_bad_object_type;
@@ -1667,6 +1664,7 @@ err_binder_new_node_failed:
 err_bad_object_type:
 err_bad_offset:
 err_copy_data_failed:
+	trace_binder_transaction_failed_buffer_release(t->buffer);
 	binder_transaction_buffer_release(target_proc, t->buffer, offp);
 	t->buffer->transaction = NULL;
 	binder_free_buf(target_proc, t->buffer);
@@ -1683,7 +1681,7 @@ err_dead_binder:
 err_invalid_target_handle:
 err_no_context_mgr_node:
 	binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-		     "binder: %d:%d transaction failed %d, size %zd-%zd\n",
+		     "%d:%d transaction failed %d, size %zd-%zd\n",
 		     proc->pid, thread->pid, return_error,
 		     tr->data_size, tr->offsets_size);
 
@@ -1712,6 +1710,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 		if (get_user(cmd, (uint32_t __user *)ptr))
 			return -EFAULT;
 		ptr += sizeof(uint32_t);
+		trace_binder_command(cmd);
 		if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {
 			binder_stats.bc[_IOC_NR(cmd)]++;
 			proc->stats.bc[_IOC_NR(cmd)]++;
@@ -1734,18 +1733,14 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 				ref = binder_get_ref_for_node(proc,
 					       binder_context_mgr_node);
 				if (ref->desc != target) {
-					binder_user_error("binder: %d:"
-						"%d tried to acquire "
-						"reference to desc 0, "
-						"got %d instead\n",
+					binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n",
 						proc->pid, thread->pid,
 						ref->desc);
 				}
 			} else
 				ref = binder_get_ref(proc, target);
 			if (ref == NULL) {
-				binder_user_error("binder: %d:%d refcou"
-					"nt change on invalid ref %d\n",
+				binder_user_error("%d:%d refcount change on invalid ref %d\n",
 					proc->pid, thread->pid, target);
 				break;
 			}
@@ -1769,7 +1764,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 				break;
 			}
 			binder_debug(BINDER_DEBUG_USER_REFS,
-				     "binder: %d:%d %s ref %d desc %d s %d w %d for node %d\n",
+				     "%d:%d %s ref %d desc %d s %d w %d for node %d\n",
 				     proc->pid, thread->pid, debug_string, ref->debug_id,
 				     ref->desc, ref->strong, ref->weak, ref->node->debug_id);
 			break;
@@ -1788,8 +1783,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 			ptr += sizeof(void *);
 			node = binder_get_node(proc, node_ptr);
 			if (node == NULL) {
-				binder_user_error("binder: %d:%d "
-					"%s u%p no match\n",
+				binder_user_error("%d:%d %s u%p no match\n",
 					proc->pid, thread->pid,
 					cmd == BC_INCREFS_DONE ?
 					"BC_INCREFS_DONE" :
@@ -1798,8 +1792,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 				break;
 			}
 			if (cookie != node->cookie) {
-				binder_user_error("binder: %d:%d %s u%p node %d"
-					" cookie mismatch %p != %p\n",
+				binder_user_error("%d:%d %s u%p node %d cookie mismatch %p != %p\n",
 					proc->pid, thread->pid,
 					cmd == BC_INCREFS_DONE ?
 					"BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
@@ -1809,9 +1802,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 			}
 			if (cmd == BC_ACQUIRE_DONE) {
 				if (node->pending_strong_ref == 0) {
-					binder_user_error("binder: %d:%d "
-						"BC_ACQUIRE_DONE node %d has "
-						"no pending acquire request\n",
+					binder_user_error("%d:%d BC_ACQUIRE_DONE node %d has no pending acquire request\n",
 						proc->pid, thread->pid,
 						node->debug_id);
 					break;
@@ -1819,9 +1810,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 				node->pending_strong_ref = 0;
 			} else {
 				if (node->pending_weak_ref == 0) {
-					binder_user_error("binder: %d:%d "
-						"BC_INCREFS_DONE node %d has "
-						"no pending increfs request\n",
+					binder_user_error("%d:%d BC_INCREFS_DONE node %d has no pending increfs request\n",
 						proc->pid, thread->pid,
 						node->debug_id);
 					break;
@@ -1830,17 +1819,17 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 			}
 			binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0);
 			binder_debug(BINDER_DEBUG_USER_REFS,
-				     "binder: %d:%d %s node %d ls %d lw %d\n",
+				     "%d:%d %s node %d ls %d lw %d\n",
 				     proc->pid, thread->pid,
 				     cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
 				     node->debug_id, node->local_strong_refs, node->local_weak_refs);
 			break;
 		}
 		case BC_ATTEMPT_ACQUIRE:
-			pr_err("binder: BC_ATTEMPT_ACQUIRE not supported\n");
+			pr_err("BC_ATTEMPT_ACQUIRE not supported\n");
 			return -EINVAL;
 		case BC_ACQUIRE_RESULT:
-			pr_err("binder: BC_ACQUIRE_RESULT not supported\n");
+			pr_err("BC_ACQUIRE_RESULT not supported\n");
 			return -EINVAL;
 
 		case BC_FREE_BUFFER: {
@@ -1853,20 +1842,17 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 
 			buffer = binder_buffer_lookup(proc, data_ptr);
 			if (buffer == NULL) {
-				binder_user_error("binder: %d:%d "
-					"BC_FREE_BUFFER u%p no match\n",
+				binder_user_error("%d:%d BC_FREE_BUFFER u%p no match\n",
 					proc->pid, thread->pid, data_ptr);
 				break;
 			}
 			if (!buffer->allow_user_free) {
-				binder_user_error("binder: %d:%d "
-					"BC_FREE_BUFFER u%p matched "
-					"unreturned buffer\n",
+				binder_user_error("%d:%d BC_FREE_BUFFER u%p matched unreturned buffer\n",
 					proc->pid, thread->pid, data_ptr);
 				break;
 			}
 			binder_debug(BINDER_DEBUG_FREE_BUFFER,
-				     "binder: %d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n",
+				     "%d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n",
 				     proc->pid, thread->pid, data_ptr, buffer->debug_id,
 				     buffer->transaction ? "active" : "finished");
 
@@ -1881,6 +1867,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 				else
 					list_move_tail(buffer->target_node->async_todo.next, &thread->todo);
 			}
+			trace_binder_transaction_buffer_release(buffer);
 			binder_transaction_buffer_release(proc, buffer, NULL);
 			binder_free_buf(proc, buffer);
 			break;
@@ -1899,19 +1886,15 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 
 		case BC_REGISTER_LOOPER:
 			binder_debug(BINDER_DEBUG_THREADS,
-				     "binder: %d:%d BC_REGISTER_LOOPER\n",
+				     "%d:%d BC_REGISTER_LOOPER\n",
 				     proc->pid, thread->pid);
 			if (thread->looper & BINDER_LOOPER_STATE_ENTERED) {
 				thread->looper |= BINDER_LOOPER_STATE_INVALID;
-				binder_user_error("binder: %d:%d ERROR:"
-					" BC_REGISTER_LOOPER called "
-					"after BC_ENTER_LOOPER\n",
+				binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called after BC_ENTER_LOOPER\n",
 					proc->pid, thread->pid);
 			} else if (proc->requested_threads == 0) {
 				thread->looper |= BINDER_LOOPER_STATE_INVALID;
-				binder_user_error("binder: %d:%d ERROR:"
-					" BC_REGISTER_LOOPER called "
-					"without request\n",
+				binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called without request\n",
 					proc->pid, thread->pid);
 			} else {
 				proc->requested_threads--;
@@ -1921,20 +1904,18 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 			break;
 		case BC_ENTER_LOOPER:
 			binder_debug(BINDER_DEBUG_THREADS,
-				     "binder: %d:%d BC_ENTER_LOOPER\n",
+				     "%d:%d BC_ENTER_LOOPER\n",
 				     proc->pid, thread->pid);
 			if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) {
 				thread->looper |= BINDER_LOOPER_STATE_INVALID;
-				binder_user_error("binder: %d:%d ERROR:"
-					" BC_ENTER_LOOPER called after "
-					"BC_REGISTER_LOOPER\n",
+				binder_user_error("%d:%d ERROR: BC_ENTER_LOOPER called after BC_REGISTER_LOOPER\n",
 					proc->pid, thread->pid);
 			}
 			thread->looper |= BINDER_LOOPER_STATE_ENTERED;
 			break;
 		case BC_EXIT_LOOPER:
 			binder_debug(BINDER_DEBUG_THREADS,
-				     "binder: %d:%d BC_EXIT_LOOPER\n",
+				     "%d:%d BC_EXIT_LOOPER\n",
 				     proc->pid, thread->pid);
 			thread->looper |= BINDER_LOOPER_STATE_EXITED;
 			break;
@@ -1954,8 +1935,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 			ptr += sizeof(void *);
 			ref = binder_get_ref(proc, target);
 			if (ref == NULL) {
-				binder_user_error("binder: %d:%d %s "
-					"invalid ref %d\n",
+				binder_user_error("%d:%d %s invalid ref %d\n",
 					proc->pid, thread->pid,
 					cmd == BC_REQUEST_DEATH_NOTIFICATION ?
 					"BC_REQUEST_DEATH_NOTIFICATION" :
@@ -1965,7 +1945,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 			}
 
 			binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
-				     "binder: %d:%d %s %p ref %d desc %d s %d w %d for node %d\n",
+				     "%d:%d %s %p ref %d desc %d s %d w %d for node %d\n",
 				     proc->pid, thread->pid,
 				     cmd == BC_REQUEST_DEATH_NOTIFICATION ?
 				     "BC_REQUEST_DEATH_NOTIFICATION" :
@@ -1975,10 +1955,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 
 			if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
 				if (ref->death) {
-					binder_user_error("binder: %d:%"
-						"d BC_REQUEST_DEATH_NOTI"
-						"FICATION death notific"
-						"ation already set\n",
+					binder_user_error("%d:%d BC_REQUEST_DEATH_NOTIFICATION death notification already set\n",
 						proc->pid, thread->pid);
 					break;
 				}
@@ -1986,8 +1963,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 				if (death == NULL) {
 					thread->return_error = BR_ERROR;
 					binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-						     "binder: %d:%d "
-						     "BC_REQUEST_DEATH_NOTIFICATION failed\n",
+						     "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n",
 						     proc->pid, thread->pid);
 					break;
 				}
@@ -2006,20 +1982,13 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 				}
 			} else {
 				if (ref->death == NULL) {
-					binder_user_error("binder: %d:%"
-						"d BC_CLEAR_DEATH_NOTIFI"
-						"CATION death notificat"
-						"ion not active\n",
+					binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification not active\n",
 						proc->pid, thread->pid);
 					break;
 				}
 				death = ref->death;
 				if (death->cookie != cookie) {
-					binder_user_error("binder: %d:%"
-						"d BC_CLEAR_DEATH_NOTIFI"
-						"CATION death notificat"
-						"ion cookie mismatch "
-						"%p != %p\n",
+					binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %p != %p\n",
 						proc->pid, thread->pid,
 						death->cookie, cookie);
 					break;
@@ -2055,11 +2024,10 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 				}
 			}
 			binder_debug(BINDER_DEBUG_DEAD_BINDER,
-				     "binder: %d:%d BC_DEAD_BINDER_DONE %p found %p\n",
+				     "%d:%d BC_DEAD_BINDER_DONE %p found %p\n",
 				     proc->pid, thread->pid, cookie, death);
 			if (death == NULL) {
-				binder_user_error("binder: %d:%d BC_DEAD"
-					"_BINDER_DONE %p not found\n",
+				binder_user_error("%d:%d BC_DEAD_BINDER_DONE %p not found\n",
 					proc->pid, thread->pid, cookie);
 				break;
 			}
@@ -2077,7 +2045,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 		} break;
 
 		default:
-			pr_err("binder: %d:%d unknown command %d\n",
+			pr_err("%d:%d unknown command %d\n",
 			       proc->pid, thread->pid, cmd);
 			return -EINVAL;
 		}
@@ -2089,6 +2057,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
 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)) {
 		binder_stats.br[_IOC_NR(cmd)]++;
 		proc->stats.br[_IOC_NR(cmd)]++;
@@ -2135,6 +2104,7 @@ retry:
 			if (put_user(thread->return_error2, (uint32_t __user *)ptr))
 				return -EFAULT;
 			ptr += sizeof(uint32_t);
+			binder_stat_br(proc, thread, thread->return_error2);
 			if (ptr == end)
 				goto done;
 			thread->return_error2 = BR_OK;
@@ -2142,6 +2112,7 @@ retry:
 		if (put_user(thread->return_error, (uint32_t __user *)ptr))
 			return -EFAULT;
 		ptr += sizeof(uint32_t);
+		binder_stat_br(proc, thread, thread->return_error);
 		thread->return_error = BR_OK;
 		goto done;
 	}
@@ -2150,13 +2121,16 @@ retry:
 	thread->looper |= BINDER_LOOPER_STATE_WAITING;
 	if (wait_for_proc_work)
 		proc->ready_threads++;
-	mutex_unlock(&binder_lock);
+
+	binder_unlock(__func__);
+
+	trace_binder_wait_for_work(wait_for_proc_work,
+				   !!thread->transaction_stack,
+				   !list_empty(&thread->todo));
 	if (wait_for_proc_work) {
 		if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
 					BINDER_LOOPER_STATE_ENTERED))) {
-			binder_user_error("binder: %d:%d ERROR: Thread waiting "
-				"for process work before calling BC_REGISTER_"
-				"LOOPER or BC_ENTER_LOOPER (state %x)\n",
+			binder_user_error("%d:%d ERROR: Thread waiting for process work before calling BC_REGISTER_LOOPER or BC_ENTER_LOOPER (state %x)\n",
 				proc->pid, thread->pid, thread->looper);
 			wait_event_interruptible(binder_user_error_wait,
 						 binder_stop_on_user_error < 2);
@@ -2174,7 +2148,9 @@ retry:
 		} else
 			ret = wait_event_interruptible(thread->wait, binder_has_thread_work(thread));
 	}
-	mutex_lock(&binder_lock);
+
+	binder_lock(__func__);
+
 	if (wait_for_proc_work)
 		proc->ready_threads--;
 	thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
@@ -2213,7 +2189,7 @@ retry:
 
 			binder_stat_br(proc, thread, cmd);
 			binder_debug(BINDER_DEBUG_TRANSACTION_COMPLETE,
-				     "binder: %d:%d BR_TRANSACTION_COMPLETE\n",
+				     "%d:%d BR_TRANSACTION_COMPLETE\n",
 				     proc->pid, thread->pid);
 
 			list_del(&w->entry);
@@ -2260,13 +2236,13 @@ retry:
 
 				binder_stat_br(proc, thread, cmd);
 				binder_debug(BINDER_DEBUG_USER_REFS,
-					     "binder: %d:%d %s %d u%p c%p\n",
+					     "%d:%d %s %d u%p c%p\n",
 					     proc->pid, thread->pid, cmd_name, node->debug_id, node->ptr, node->cookie);
 			} else {
 				list_del_init(&w->entry);
 				if (!weak && !strong) {
 					binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-						     "binder: %d:%d node %d u%p c%p deleted\n",
+						     "%d:%d node %d u%p c%p deleted\n",
 						     proc->pid, thread->pid, node->debug_id,
 						     node->ptr, node->cookie);
 					rb_erase(&node->rb_node, &proc->nodes);
@@ -2274,7 +2250,7 @@ retry:
 					binder_stats_deleted(BINDER_STAT_NODE);
 				} else {
 					binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-						     "binder: %d:%d node %d u%p c%p state unchanged\n",
+						     "%d:%d node %d u%p c%p state unchanged\n",
 						     proc->pid, thread->pid, node->debug_id, node->ptr,
 						     node->cookie);
 				}
@@ -2297,8 +2273,9 @@ retry:
 			if (put_user(death->cookie, (void * __user *)ptr))
 				return -EFAULT;
 			ptr += sizeof(void *);
+			binder_stat_br(proc, thread, cmd);
 			binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
-				     "binder: %d:%d %s %p\n",
+				     "%d:%d %s %p\n",
 				      proc->pid, thread->pid,
 				      cmd == BR_DEAD_BINDER ?
 				      "BR_DEAD_BINDER" :
@@ -2344,7 +2321,7 @@ retry:
 		if (t->from) {
 			struct task_struct *sender = t->from->proc->tsk;
 			tr.sender_pid = task_tgid_nr_ns(sender,
-							current->nsproxy->pid_ns);
+							task_active_pid_ns(current));
 		} else {
 			tr.sender_pid = 0;
 		}
@@ -2364,10 +2341,10 @@ retry:
 			return -EFAULT;
 		ptr += sizeof(tr);
 
+		trace_binder_transaction_received(t);
 		binder_stat_br(proc, thread, cmd);
 		binder_debug(BINDER_DEBUG_TRANSACTION,
-			     "binder: %d:%d %s %d %d:%d, cmd %d"
-			     "size %zd-%zd ptr %p-%p\n",
+			     "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %p-%p\n",
 			     proc->pid, thread->pid,
 			     (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
 			     "BR_REPLY",
@@ -2400,10 +2377,11 @@ done:
 	     /*spawn a new thread if we leave this out */) {
 		proc->requested_threads++;
 		binder_debug(BINDER_DEBUG_THREADS,
-			     "binder: %d:%d BR_SPAWN_LOOPER\n",
+			     "%d:%d BR_SPAWN_LOOPER\n",
 			     proc->pid, thread->pid);
 		if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
 			return -EFAULT;
+		binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
 	}
 	return 0;
 }
@@ -2424,7 +2402,7 @@ static void binder_release_work(struct list_head *list)
 				binder_send_failed_reply(t, BR_DEAD_REPLY);
 			} else {
 				binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
-					"binder: undelivered transaction %d\n",
+					"undelivered transaction %d\n",
 					t->debug_id);
 				t->buffer->transaction = NULL;
 				kfree(t);
@@ -2433,7 +2411,7 @@ static void binder_release_work(struct list_head *list)
 		} break;
 		case BINDER_WORK_TRANSACTION_COMPLETE: {
 			binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
-				"binder: undelivered TRANSACTION_COMPLETE\n");
+				"undelivered TRANSACTION_COMPLETE\n");
 			kfree(w);
 			binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
 		} break;
@@ -2443,13 +2421,13 @@ static void binder_release_work(struct list_head *list)
 
 			death = container_of(w, struct binder_ref_death, work);
 			binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
-				"binder: undelivered death notification, %p\n",
+				"undelivered death notification, %p\n",
 				death->cookie);
 			kfree(death);
 			binder_stats_deleted(BINDER_STAT_DEATH);
 		} break;
 		default:
-			pr_err("binder: unexpected work type, %d, not freed\n",
+			pr_err("unexpected work type, %d, not freed\n",
 			       w->type);
 			break;
 		}
@@ -2506,8 +2484,8 @@ static int binder_free_thread(struct binder_proc *proc,
 	while (t) {
 		active_transactions++;
 		binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
-			     "binder: release %d:%d transaction %d "
-			     "%s, still active\n", proc->pid, thread->pid,
+			     "release %d:%d transaction %d %s, still active\n",
+			      proc->pid, thread->pid,
 			     t->debug_id,
 			     (t->to_thread == thread) ? "in" : "out");
 
@@ -2540,12 +2518,14 @@ static unsigned int binder_poll(struct file *filp,
 	struct binder_thread *thread = NULL;
 	int wait_for_proc_work;
 
-	mutex_lock(&binder_lock);
+	binder_lock(__func__);
+
 	thread = binder_get_thread(proc);
 
 	wait_for_proc_work = thread->transaction_stack == NULL &&
 		list_empty(&thread->todo) && thread->return_error == BR_OK;
-	mutex_unlock(&binder_lock);
+
+	binder_unlock(__func__);
 
 	if (wait_for_proc_work) {
 		if (binder_has_proc_work(proc, thread))
@@ -2573,11 +2553,13 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 
 	/*pr_info("binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/
 
+	trace_binder_ioctl(cmd, arg);
+
 	ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
 	if (ret)
-		return ret;
+		goto err_unlocked;
 
-	mutex_lock(&binder_lock);
+	binder_lock(__func__);
 	thread = binder_get_thread(proc);
 	if (thread == NULL) {
 		ret = -ENOMEM;
@@ -2596,12 +2578,13 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 			goto err;
 		}
 		binder_debug(BINDER_DEBUG_READ_WRITE,
-			     "binder: %d:%d write %ld at %08lx, read %ld at %08lx\n",
-			     proc->pid, thread->pid, bwr.write_size, bwr.write_buffer,
-			     bwr.read_size, bwr.read_buffer);
+			     "%d:%d write %ld at %08lx, read %ld at %08lx\n",
+			     proc->pid, thread->pid, bwr.write_size,
+			     bwr.write_buffer, bwr.read_size, bwr.read_buffer);
 
 		if (bwr.write_size > 0) {
 			ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);
+			trace_binder_write_done(ret);
 			if (ret < 0) {
 				bwr.read_consumed = 0;
 				if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
@@ -2611,6 +2594,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		}
 		if (bwr.read_size > 0) {
 			ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);
+			trace_binder_read_done(ret);
 			if (!list_empty(&proc->todo))
 				wake_up_interruptible(&proc->wait);
 			if (ret < 0) {
@@ -2620,7 +2604,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 			}
 		}
 		binder_debug(BINDER_DEBUG_READ_WRITE,
-			     "binder: %d:%d wrote %ld of %ld, read return %ld of %ld\n",
+			     "%d:%d wrote %ld of %ld, read return %ld of %ld\n",
 			     proc->pid, thread->pid, bwr.write_consumed, bwr.write_size,
 			     bwr.read_consumed, bwr.read_size);
 		if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
@@ -2637,14 +2621,13 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		break;
 	case BINDER_SET_CONTEXT_MGR:
 		if (binder_context_mgr_node != NULL) {
-			pr_err("binder: BINDER_SET_CONTEXT_MGR already set\n");
+			pr_err("BINDER_SET_CONTEXT_MGR already set\n");
 			ret = -EBUSY;
 			goto err;
 		}
 		if (uid_valid(binder_context_mgr_uid)) {
 			if (!uid_eq(binder_context_mgr_uid, current->cred->euid)) {
-				pr_err("binder: BINDER_SET_"
-				       "CONTEXT_MGR bad uid %d != %d\n",
+				pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n",
 				       from_kuid(&init_user_ns, current->cred->euid),
 				       from_kuid(&init_user_ns, binder_context_mgr_uid));
 				ret = -EPERM;
@@ -2663,7 +2646,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		binder_context_mgr_node->has_weak_ref = 1;
 		break;
 	case BINDER_THREAD_EXIT:
-		binder_debug(BINDER_DEBUG_THREADS, "binder: %d:%d exit\n",
+		binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n",
 			     proc->pid, thread->pid);
 		binder_free_thread(proc, thread);
 		thread = NULL;
@@ -2686,10 +2669,12 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 err:
 	if (thread)
 		thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
-	mutex_unlock(&binder_lock);
+	binder_unlock(__func__);
 	wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
 	if (ret && ret != -ERESTARTSYS)
-		pr_info("binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
+		pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
+err_unlocked:
+	trace_binder_ioctl_done(ret);
 	return ret;
 }
 
@@ -2697,7 +2682,7 @@ static void binder_vma_open(struct vm_area_struct *vma)
 {
 	struct binder_proc *proc = vma->vm_private_data;
 	binder_debug(BINDER_DEBUG_OPEN_CLOSE,
-		     "binder: %d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",
+		     "%d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",
 		     proc->pid, vma->vm_start, vma->vm_end,
 		     (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
 		     (unsigned long)pgprot_val(vma->vm_page_prot));
@@ -2707,7 +2692,7 @@ static void binder_vma_close(struct vm_area_struct *vma)
 {
 	struct binder_proc *proc = vma->vm_private_data;
 	binder_debug(BINDER_DEBUG_OPEN_CLOSE,
-		     "binder: %d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",
+		     "%d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",
 		     proc->pid, vma->vm_start, vma->vm_end,
 		     (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
 		     (unsigned long)pgprot_val(vma->vm_page_prot));
@@ -2835,13 +2820,16 @@ static int binder_open(struct inode *nodp, struct file *filp)
 	INIT_LIST_HEAD(&proc->todo);
 	init_waitqueue_head(&proc->wait);
 	proc->default_priority = task_nice(current);
-	mutex_lock(&binder_lock);
+
+	binder_lock(__func__);
+
 	binder_stats_created(BINDER_STAT_PROC);
 	hlist_add_head(&proc->proc_node, &binder_procs);
 	proc->pid = current->group_leader->pid;
 	INIT_LIST_HEAD(&proc->delivered_death);
 	filp->private_data = proc;
-	mutex_unlock(&binder_lock);
+
+	binder_unlock(__func__);
 
 	if (binder_debugfs_dir_entry_proc) {
 		char strbuf[11];
@@ -2949,9 +2937,8 @@ static void binder_deferred_release(struct binder_proc *proc)
 				}
 			}
 			binder_debug(BINDER_DEBUG_DEAD_BINDER,
-				     "binder: node %d now dead, "
-				     "refs %d, death %d\n", node->debug_id,
-				     incoming_refs, death);
+				     "node %d now dead, refs %d, death %d\n",
+				      node->debug_id, incoming_refs, death);
 		}
 	}
 	outgoing_refs = 0;
@@ -2972,8 +2959,7 @@ static void binder_deferred_release(struct binder_proc *proc)
 		if (t) {
 			t->buffer = NULL;
 			buffer->transaction = NULL;
-			pr_err("binder: release proc %d, "
-			       "transaction %d, not freed\n",
+			pr_err("release proc %d, transaction %d, not freed\n",
 			       proc->pid, t->debug_id);
 			/*BUG();*/
 		}
@@ -2990,8 +2976,7 @@ static void binder_deferred_release(struct binder_proc *proc)
 			if (proc->pages[i]) {
 				void *page_addr = proc->buffer + i * PAGE_SIZE;
 				binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-					     "binder_release: %d: "
-					     "page %d at %p not freed\n",
+					     "binder_release: %d: page %d at %p not freed\n",
 					     proc->pid, i,
 					     page_addr);
 				unmap_kernel_range((unsigned long)page_addr,
@@ -3007,9 +2992,7 @@ static void binder_deferred_release(struct binder_proc *proc)
 	put_task_struct(proc->tsk);
 
 	binder_debug(BINDER_DEBUG_OPEN_CLOSE,
-		     "binder_release: %d threads %d, nodes %d (ref %d), "
-		     "refs %d, active transactions %d, buffers %d, "
-		     "pages %d\n",
+		     "binder_release: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d, buffers %d, pages %d\n",
 		     proc->pid, threads, nodes, incoming_refs, outgoing_refs,
 		     active_transactions, buffers, page_count);
 
@@ -3023,7 +3006,7 @@ static void binder_deferred_func(struct work_struct *work)
 
 	int defer;
 	do {
-		mutex_lock(&binder_lock);
+		binder_lock(__func__);
 		mutex_lock(&binder_deferred_lock);
 		if (!hlist_empty(&binder_deferred_list)) {
 			proc = hlist_entry(binder_deferred_list.first,
@@ -3050,7 +3033,7 @@ static void binder_deferred_func(struct work_struct *work)
 		if (defer & BINDER_DEFERRED_RELEASE)
 			binder_deferred_release(proc); /* frees proc */
 
-		mutex_unlock(&binder_lock);
+		binder_unlock(__func__);
 		if (files)
 			put_files_struct(files);
 	} while (proc);
@@ -3391,7 +3374,7 @@ static int binder_state_show(struct seq_file *m, void *unused)
 	int do_lock = !binder_debug_no_lock;
 
 	if (do_lock)
-		mutex_lock(&binder_lock);
+		binder_lock(__func__);
 
 	seq_puts(m, "binder state:\n");
 
@@ -3403,7 +3386,7 @@ static int binder_state_show(struct seq_file *m, void *unused)
 	hlist_for_each_entry(proc, pos, &binder_procs, proc_node)
 		print_binder_proc(m, proc, 1);
 	if (do_lock)
-		mutex_unlock(&binder_lock);
+		binder_unlock(__func__);
 	return 0;
 }
 
@@ -3414,7 +3397,7 @@ static int binder_stats_show(struct seq_file *m, void *unused)
 	int do_lock = !binder_debug_no_lock;
 
 	if (do_lock)
-		mutex_lock(&binder_lock);
+		binder_lock(__func__);
 
 	seq_puts(m, "binder stats:\n");
 
@@ -3423,7 +3406,7 @@ static int binder_stats_show(struct seq_file *m, void *unused)
 	hlist_for_each_entry(proc, pos, &binder_procs, proc_node)
 		print_binder_proc_stats(m, proc);
 	if (do_lock)
-		mutex_unlock(&binder_lock);
+		binder_unlock(__func__);
 	return 0;
 }
 
@@ -3434,13 +3417,13 @@ static int binder_transactions_show(struct seq_file *m, void *unused)
 	int do_lock = !binder_debug_no_lock;
 
 	if (do_lock)
-		mutex_lock(&binder_lock);
+		binder_lock(__func__);
 
 	seq_puts(m, "binder transactions:\n");
 	hlist_for_each_entry(proc, pos, &binder_procs, proc_node)
 		print_binder_proc(m, proc, 0);
 	if (do_lock)
-		mutex_unlock(&binder_lock);
+		binder_unlock(__func__);
 	return 0;
 }
 
@@ -3450,11 +3433,11 @@ static int binder_proc_show(struct seq_file *m, void *unused)
 	int do_lock = !binder_debug_no_lock;
 
 	if (do_lock)
-		mutex_lock(&binder_lock);
+		binder_lock(__func__);
 	seq_puts(m, "binder proc state:\n");
 	print_binder_proc(m, proc, 1);
 	if (do_lock)
-		mutex_unlock(&binder_lock);
+		binder_unlock(__func__);
 	return 0;
 }
 
@@ -3549,4 +3532,7 @@ static int __init binder_init(void)
 
 device_initcall(binder_init);
 
+#define CREATE_TRACE_POINTS
+#include "binder_trace.h"
+
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/android/binder_trace.h b/drivers/staging/android/binder_trace.h
new file mode 100644
index 0000000..82a567c
--- /dev/null
+++ b/drivers/staging/android/binder_trace.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM binder
+
+#if !defined(_BINDER_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _BINDER_TRACE_H
+
+#include <linux/tracepoint.h>
+
+struct binder_buffer;
+struct binder_node;
+struct binder_proc;
+struct binder_ref;
+struct binder_thread;
+struct binder_transaction;
+
+TRACE_EVENT(binder_ioctl,
+	TP_PROTO(unsigned int cmd, unsigned long arg),
+	TP_ARGS(cmd, arg),
+
+	TP_STRUCT__entry(
+		__field(unsigned int, cmd)
+		__field(unsigned long, arg)
+	),
+	TP_fast_assign(
+		__entry->cmd = cmd;
+		__entry->arg = arg;
+	),
+	TP_printk("cmd=0x%x arg=0x%lx", __entry->cmd, __entry->arg)
+);
+
+DECLARE_EVENT_CLASS(binder_lock_class,
+	TP_PROTO(const char *tag),
+	TP_ARGS(tag),
+	TP_STRUCT__entry(
+		__field(const char *, tag)
+	),
+	TP_fast_assign(
+		__entry->tag = tag;
+	),
+	TP_printk("tag=%s", __entry->tag)
+);
+
+#define DEFINE_BINDER_LOCK_EVENT(name)	\
+DEFINE_EVENT(binder_lock_class, name,	\
+	TP_PROTO(const char *func), \
+	TP_ARGS(func))
+
+DEFINE_BINDER_LOCK_EVENT(binder_lock);
+DEFINE_BINDER_LOCK_EVENT(binder_locked);
+DEFINE_BINDER_LOCK_EVENT(binder_unlock);
+
+DECLARE_EVENT_CLASS(binder_function_return_class,
+	TP_PROTO(int ret),
+	TP_ARGS(ret),
+	TP_STRUCT__entry(
+		__field(int, ret)
+	),
+	TP_fast_assign(
+		__entry->ret = ret;
+	),
+	TP_printk("ret=%d", __entry->ret)
+);
+
+#define DEFINE_BINDER_FUNCTION_RETURN_EVENT(name)	\
+DEFINE_EVENT(binder_function_return_class, name,	\
+	TP_PROTO(int ret), \
+	TP_ARGS(ret))
+
+DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_ioctl_done);
+DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_write_done);
+DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_read_done);
+
+TRACE_EVENT(binder_wait_for_work,
+	TP_PROTO(bool proc_work, bool transaction_stack, bool thread_todo),
+	TP_ARGS(proc_work, transaction_stack, thread_todo),
+
+	TP_STRUCT__entry(
+		__field(bool, proc_work)
+		__field(bool, transaction_stack)
+		__field(bool, thread_todo)
+	),
+	TP_fast_assign(
+		__entry->proc_work = proc_work;
+		__entry->transaction_stack = transaction_stack;
+		__entry->thread_todo = thread_todo;
+	),
+	TP_printk("proc_work=%d transaction_stack=%d thread_todo=%d",
+		  __entry->proc_work, __entry->transaction_stack,
+		  __entry->thread_todo)
+);
+
+TRACE_EVENT(binder_transaction,
+	TP_PROTO(bool reply, struct binder_transaction *t,
+		 struct binder_node *target_node),
+	TP_ARGS(reply, t, target_node),
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+		__field(int, target_node)
+		__field(int, to_proc)
+		__field(int, to_thread)
+		__field(int, reply)
+		__field(unsigned int, code)
+		__field(unsigned int, flags)
+	),
+	TP_fast_assign(
+		__entry->debug_id = t->debug_id;
+		__entry->target_node = target_node ? target_node->debug_id : 0;
+		__entry->to_proc = t->to_proc->pid;
+		__entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
+		__entry->reply = reply;
+		__entry->code = t->code;
+		__entry->flags = t->flags;
+	),
+	TP_printk("transaction=%d dest_node=%d dest_proc=%d dest_thread=%d reply=%d flags=0x%x code=0x%x",
+		  __entry->debug_id, __entry->target_node,
+		  __entry->to_proc, __entry->to_thread,
+		  __entry->reply, __entry->flags, __entry->code)
+);
+
+TRACE_EVENT(binder_transaction_received,
+	TP_PROTO(struct binder_transaction *t),
+	TP_ARGS(t),
+
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+	),
+	TP_fast_assign(
+		__entry->debug_id = t->debug_id;
+	),
+	TP_printk("transaction=%d", __entry->debug_id)
+);
+
+TRACE_EVENT(binder_transaction_node_to_ref,
+	TP_PROTO(struct binder_transaction *t, struct binder_node *node,
+		 struct binder_ref *ref),
+	TP_ARGS(t, node, ref),
+
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+		__field(int, node_debug_id)
+		__field(void __user *, node_ptr)
+		__field(int, ref_debug_id)
+		__field(uint32_t, ref_desc)
+	),
+	TP_fast_assign(
+		__entry->debug_id = t->debug_id;
+		__entry->node_debug_id = node->debug_id;
+		__entry->node_ptr = node->ptr;
+		__entry->ref_debug_id = ref->debug_id;
+		__entry->ref_desc = ref->desc;
+	),
+	TP_printk("transaction=%d node=%d src_ptr=0x%p ==> dest_ref=%d dest_desc=%d",
+		  __entry->debug_id, __entry->node_debug_id, __entry->node_ptr,
+		  __entry->ref_debug_id, __entry->ref_desc)
+);
+
+TRACE_EVENT(binder_transaction_ref_to_node,
+	TP_PROTO(struct binder_transaction *t, struct binder_ref *ref),
+	TP_ARGS(t, ref),
+
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+		__field(int, ref_debug_id)
+		__field(uint32_t, ref_desc)
+		__field(int, node_debug_id)
+		__field(void __user *, node_ptr)
+	),
+	TP_fast_assign(
+		__entry->debug_id = t->debug_id;
+		__entry->ref_debug_id = ref->debug_id;
+		__entry->ref_desc = ref->desc;
+		__entry->node_debug_id = ref->node->debug_id;
+		__entry->node_ptr = ref->node->ptr;
+	),
+	TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%p",
+		  __entry->debug_id, __entry->node_debug_id,
+		  __entry->ref_debug_id, __entry->ref_desc, __entry->node_ptr)
+);
+
+TRACE_EVENT(binder_transaction_ref_to_ref,
+	TP_PROTO(struct binder_transaction *t, struct binder_ref *src_ref,
+		 struct binder_ref *dest_ref),
+	TP_ARGS(t, src_ref, dest_ref),
+
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+		__field(int, node_debug_id)
+		__field(int, src_ref_debug_id)
+		__field(uint32_t, src_ref_desc)
+		__field(int, dest_ref_debug_id)
+		__field(uint32_t, dest_ref_desc)
+	),
+	TP_fast_assign(
+		__entry->debug_id = t->debug_id;
+		__entry->node_debug_id = src_ref->node->debug_id;
+		__entry->src_ref_debug_id = src_ref->debug_id;
+		__entry->src_ref_desc = src_ref->desc;
+		__entry->dest_ref_debug_id = dest_ref->debug_id;
+		__entry->dest_ref_desc = dest_ref->desc;
+	),
+	TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ref=%d dest_desc=%d",
+		  __entry->debug_id, __entry->node_debug_id,
+		  __entry->src_ref_debug_id, __entry->src_ref_desc,
+		  __entry->dest_ref_debug_id, __entry->dest_ref_desc)
+);
+
+TRACE_EVENT(binder_transaction_fd,
+	TP_PROTO(struct binder_transaction *t, int src_fd, int dest_fd),
+	TP_ARGS(t, src_fd, dest_fd),
+
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+		__field(int, src_fd)
+		__field(int, dest_fd)
+	),
+	TP_fast_assign(
+		__entry->debug_id = t->debug_id;
+		__entry->src_fd = src_fd;
+		__entry->dest_fd = dest_fd;
+	),
+	TP_printk("transaction=%d src_fd=%d ==> dest_fd=%d",
+		  __entry->debug_id, __entry->src_fd, __entry->dest_fd)
+);
+
+DECLARE_EVENT_CLASS(binder_buffer_class,
+	TP_PROTO(struct binder_buffer *buf),
+	TP_ARGS(buf),
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+		__field(size_t, data_size)
+		__field(size_t, offsets_size)
+	),
+	TP_fast_assign(
+		__entry->debug_id = buf->debug_id;
+		__entry->data_size = buf->data_size;
+		__entry->offsets_size = buf->offsets_size;
+	),
+	TP_printk("transaction=%d data_size=%zd offsets_size=%zd",
+		  __entry->debug_id, __entry->data_size, __entry->offsets_size)
+);
+
+DEFINE_EVENT(binder_buffer_class, binder_transaction_alloc_buf,
+	TP_PROTO(struct binder_buffer *buffer),
+	TP_ARGS(buffer));
+
+DEFINE_EVENT(binder_buffer_class, binder_transaction_buffer_release,
+	TP_PROTO(struct binder_buffer *buffer),
+	TP_ARGS(buffer));
+
+DEFINE_EVENT(binder_buffer_class, binder_transaction_failed_buffer_release,
+	TP_PROTO(struct binder_buffer *buffer),
+	TP_ARGS(buffer));
+
+TRACE_EVENT(binder_update_page_range,
+	TP_PROTO(struct binder_proc *proc, bool allocate,
+		 void *start, void *end),
+	TP_ARGS(proc, allocate, start, end),
+	TP_STRUCT__entry(
+		__field(int, proc)
+		__field(bool, allocate)
+		__field(size_t, offset)
+		__field(size_t, size)
+	),
+	TP_fast_assign(
+		__entry->proc = proc->pid;
+		__entry->allocate = allocate;
+		__entry->offset = start - proc->buffer;
+		__entry->size = end - start;
+	),
+	TP_printk("proc=%d allocate=%d offset=%zu size=%zu",
+		  __entry->proc, __entry->allocate,
+		  __entry->offset, __entry->size)
+);
+
+TRACE_EVENT(binder_command,
+	TP_PROTO(uint32_t cmd),
+	TP_ARGS(cmd),
+	TP_STRUCT__entry(
+		__field(uint32_t, cmd)
+	),
+	TP_fast_assign(
+		__entry->cmd = cmd;
+	),
+	TP_printk("cmd=0x%x %s",
+		  __entry->cmd,
+		  _IOC_NR(__entry->cmd) < ARRAY_SIZE(binder_command_strings) ?
+			  binder_command_strings[_IOC_NR(__entry->cmd)] :
+			  "unknown")
+);
+
+TRACE_EVENT(binder_return,
+	TP_PROTO(uint32_t cmd),
+	TP_ARGS(cmd),
+	TP_STRUCT__entry(
+		__field(uint32_t, cmd)
+	),
+	TP_fast_assign(
+		__entry->cmd = cmd;
+	),
+	TP_printk("cmd=0x%x %s",
+		  __entry->cmd,
+		  _IOC_NR(__entry->cmd) < ARRAY_SIZE(binder_return_strings) ?
+			  binder_return_strings[_IOC_NR(__entry->cmd)] :
+			  "unknown")
+);
+
+#endif /* _BINDER_TRACE_H */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE binder_trace
+#include <trace/define_trace.h>
diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c
index 1d5ed47..dbc63cb 100644
--- a/drivers/staging/android/logger.c
+++ b/drivers/staging/android/logger.c
@@ -676,4 +676,25 @@ static int __init logger_init(void)
 out:
 	return ret;
 }
+
+static void __exit logger_exit(void)
+{
+	struct logger_log *current_log, *next_log;
+
+	list_for_each_entry_safe(current_log, next_log, &log_list, logs) {
+		/* we have to delete all the entry inside log_list */
+		misc_deregister(&current_log->misc);
+		vfree(current_log->buffer);
+		kfree(current_log->misc.name);
+		list_del(&current_log->logs);
+		kfree(current_log);
+	}
+}
+
+
 device_initcall(logger_init);
+module_exit(logger_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Robert Love, <rlove@google.com>");
+MODULE_DESCRIPTION("Android Logger");
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index b91e4bc..3b91b0f 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -40,7 +40,7 @@
 #include <linux/notifier.h>
 
 static uint32_t lowmem_debug_level = 2;
-static int lowmem_adj[6] = {
+static short lowmem_adj[6] = {
 	0,
 	1,
 	6,
@@ -70,9 +70,9 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
 	int rem = 0;
 	int tasksize;
 	int i;
-	int min_score_adj = OOM_SCORE_ADJ_MAX + 1;
+	short min_score_adj = OOM_SCORE_ADJ_MAX + 1;
 	int selected_tasksize = 0;
-	int selected_oom_score_adj;
+	short selected_oom_score_adj;
 	int array_size = ARRAY_SIZE(lowmem_adj);
 	int other_free = global_page_state(NR_FREE_PAGES);
 	int other_file = global_page_state(NR_FILE_PAGES) -
@@ -90,7 +90,7 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
 		}
 	}
 	if (sc->nr_to_scan > 0)
-		lowmem_print(3, "lowmem_shrink %lu, %x, ofree %d %d, ma %d\n",
+		lowmem_print(3, "lowmem_shrink %lu, %x, ofree %d %d, ma %hd\n",
 				sc->nr_to_scan, sc->gfp_mask, other_free,
 				other_file, min_score_adj);
 	rem = global_page_state(NR_ACTIVE_ANON) +
@@ -107,7 +107,7 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
 	rcu_read_lock();
 	for_each_process(tsk) {
 		struct task_struct *p;
-		int oom_score_adj;
+		short oom_score_adj;
 
 		if (tsk->flags & PF_KTHREAD)
 			continue;
@@ -141,11 +141,11 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
 		selected = p;
 		selected_tasksize = tasksize;
 		selected_oom_score_adj = oom_score_adj;
-		lowmem_print(2, "select %d (%s), adj %d, size %d, to kill\n",
+		lowmem_print(2, "select %d (%s), adj %hd, size %d, to kill\n",
 			     p->pid, p->comm, oom_score_adj, tasksize);
 	}
 	if (selected) {
-		lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",
+		lowmem_print(1, "send sigkill to %d (%s), adj %hd, size %d\n",
 			     selected->pid, selected->comm,
 			     selected_oom_score_adj, selected_tasksize);
 		lowmem_deathpending_timeout = jiffies + HZ;
@@ -176,7 +176,7 @@ static void __exit lowmem_exit(void)
 }
 
 module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR);
-module_param_array_named(adj, lowmem_adj, int, &lowmem_adj_size,
+module_param_array_named(adj, lowmem_adj, short, &lowmem_adj_size,
 			 S_IRUGO | S_IWUSR);
 module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size,
 			 S_IRUGO | S_IWUSR);
diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h
index 4d490a9..f577948 100644
--- a/drivers/staging/bcm/Adapter.h
+++ b/drivers/staging/bcm/Adapter.h
@@ -151,7 +151,7 @@ struct bcm_packet_info {
 	UINT		NumOfPacketsSent;
 	UCHAR		ucDirection;
 	USHORT		usCID;
-	S_MIBS_EXTSERVICEFLOW_PARAMETERS	stMibsExtServiceFlowTable;
+	struct bcm_mibs_parameters stMibsExtServiceFlowTable;
 	UINT		uiCurrentRxRate;
 	UINT		uiThisPeriodRxBytes;
 	UINT		uiTotalRxBytes;
@@ -198,7 +198,7 @@ struct bcm_tarang_data {
 	int			AppCtrlQueueLen;
 	BOOLEAN			MacTracingEnabled;
 	BOOLEAN			bApplicationToExit;
-	S_MIBS_DROPPED_APP_CNTRL_MESSAGES	stDroppedAppCntrlMsgs;
+	struct bcm_mibs_dropped_cntrl_msg stDroppedAppCntrlMsgs;
 	ULONG			RxCntrlMsgBitMask;
 };
 
@@ -371,8 +371,8 @@ struct bcm_mini_adapter {
 	PFLASH2X_VENDORSPECIFIC_INFO psFlash2xVendorInfo;
 	UINT			uiFlashBaseAdd; /* Flash start address */
 	UINT			uiActiveISOOffset; /* Active ISO offset chosen before f/w download */
-	FLASH2X_SECTION_VAL	eActiveISO; /* Active ISO section val */
-	FLASH2X_SECTION_VAL	eActiveDSD;	/* Active DSD val chosen before f/w download */
+	enum bcm_flash2x_section_val eActiveISO; /* Active ISO section val */
+	enum bcm_flash2x_section_val eActiveDSD; /* Active DSD val chosen before f/w download */
 	UINT			uiActiveDSDOffsetAtFwDld;  /* For accessing Active DSD chosen before f/w download */
 	UINT			uiFlashLayoutMajorVersion;
 	UINT			uiFlashLayoutMinorVersion;
diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c
index 3d02c2e..efad33e 100644
--- a/drivers/staging/bcm/Bcmchar.c
+++ b/drivers/staging/bcm/Bcmchar.c
@@ -160,7 +160,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 	struct bcm_mini_adapter *Adapter = pTarang->Adapter;
 	INT Status = STATUS_FAILURE;
 	int timeout = 0;
-	IOCTL_BUFFER IoBuffer;
+	struct bcm_ioctl_buffer IoBuffer;
 	int bytes;
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg);
@@ -203,13 +203,13 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 	switch (cmd) {
 	/* Rdms for Swin Idle... */
 	case IOCTL_BCM_REGISTER_READ_PRIVATE: {
-		RDM_BUFFER  sRdmBuffer = {0};
+		struct bcm_rdm_buffer sRdmBuffer = {0};
 		PCHAR temp_buff;
 		UINT Bufflen;
 		u16 temp_value;
 
 		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		if (IoBuffer.InputLength > sizeof(sRdmBuffer))
@@ -248,11 +248,11 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 	}
 
 	case IOCTL_BCM_REGISTER_WRITE_PRIVATE: {
-		WRM_BUFFER  sWrmBuffer = {0};
+		struct bcm_wrm_buffer sWrmBuffer = {0};
 		UINT uiTempVar = 0;
 		/* Copy Ioctl Buffer structure */
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		if (IoBuffer.InputLength > sizeof(sWrmBuffer))
@@ -287,7 +287,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 
 	case IOCTL_BCM_REGISTER_READ:
 	case IOCTL_BCM_EEPROM_REGISTER_READ: {
-		RDM_BUFFER  sRdmBuffer = {0};
+		struct bcm_rdm_buffer sRdmBuffer = {0};
 		PCHAR temp_buff = NULL;
 		UINT uiTempVar = 0;
 		if ((Adapter->IdleMode == TRUE) ||
@@ -299,7 +299,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 		}
 
 		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		if (IoBuffer.InputLength > sizeof(sRdmBuffer))
@@ -345,8 +345,9 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 	}
 	case IOCTL_BCM_REGISTER_WRITE:
 	case IOCTL_BCM_EEPROM_REGISTER_WRITE: {
-		WRM_BUFFER  sWrmBuffer = {0};
+		struct bcm_wrm_buffer sWrmBuffer = {0};
 		UINT uiTempVar = 0;
+
 		if ((Adapter->IdleMode == TRUE) ||
 			(Adapter->bShutStatus == TRUE) ||
 			(Adapter->bPreparingForLowPowerMode == TRUE)) {
@@ -356,7 +357,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 		}
 
 		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		if (IoBuffer.InputLength > sizeof(sWrmBuffer))
@@ -401,8 +402,8 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 		UINT value = 0;
 		UINT uiBit = 0;
 		UINT uiOperation = 0;
+		struct bcm_gpio_info gpio_info = {0};
 
-		GPIO_INFO   gpio_info = {0};
 		if ((Adapter->IdleMode == TRUE) ||
 			(Adapter->bShutStatus == TRUE) ||
 			(Adapter->bPreparingForLowPowerMode == TRUE)) {
@@ -411,7 +412,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 			return -EACCES;
 		}
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		if (IoBuffer.InputLength > sizeof(gpio_info))
@@ -478,7 +479,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 	break;
 
 	case BCM_LED_THREAD_STATE_CHANGE_REQ: {
-		USER_THREAD_REQ threadReq = {0};
+		struct bcm_user_thread_req threadReq = {0};
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "User made LED thread InActive");
 
 		if ((Adapter->IdleMode == TRUE) ||
@@ -490,7 +491,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 			break;
 		}
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		if (IoBuffer.InputLength > sizeof(threadReq))
@@ -518,14 +519,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 	case IOCTL_BCM_GPIO_STATUS_REQUEST: {
 		ULONG uiBit = 0;
 		UCHAR ucRead[4];
-		GPIO_INFO   gpio_info = {0};
+		struct bcm_gpio_info gpio_info = {0};
 
 		if ((Adapter->IdleMode == TRUE) ||
 			(Adapter->bShutStatus == TRUE) ||
 			(Adapter->bPreparingForLowPowerMode == TRUE))
 			return -EACCES;
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		if (IoBuffer.InputLength > sizeof(gpio_info))
@@ -552,17 +553,17 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 
 	case IOCTL_BCM_GPIO_MULTI_REQUEST: {
 		UCHAR ucResetValue[4];
-		GPIO_MULTI_INFO gpio_multi_info[MAX_IDX];
-		PGPIO_MULTI_INFO pgpio_multi_info = (PGPIO_MULTI_INFO)gpio_multi_info;
+		struct bcm_gpio_multi_info gpio_multi_info[MAX_IDX];
+		struct bcm_gpio_multi_info *pgpio_multi_info = (struct bcm_gpio_multi_info *)gpio_multi_info;
 
-		memset(pgpio_multi_info, 0, MAX_IDX * sizeof(GPIO_MULTI_INFO));
+		memset(pgpio_multi_info, 0, MAX_IDX * sizeof(struct bcm_gpio_multi_info));
 
 		if ((Adapter->IdleMode == TRUE) ||
 			(Adapter->bShutStatus == TRUE) ||
 			(Adapter->bPreparingForLowPowerMode == TRUE))
 			return -EINVAL;
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		if (IoBuffer.InputLength > sizeof(gpio_multi_info))
@@ -636,15 +637,15 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 
 	case IOCTL_BCM_GPIO_MODE_REQUEST: {
 		UCHAR ucResetValue[4];
-		GPIO_MULTI_MODE gpio_multi_mode[MAX_IDX];
-		PGPIO_MULTI_MODE pgpio_multi_mode = (PGPIO_MULTI_MODE)gpio_multi_mode;
+		struct bcm_gpio_multi_mode gpio_multi_mode[MAX_IDX];
+		struct bcm_gpio_multi_mode *pgpio_multi_mode = (struct bcm_gpio_multi_mode *)gpio_multi_mode;
 
 		if ((Adapter->IdleMode == TRUE) ||
 			(Adapter->bShutStatus == TRUE) ||
 			(Adapter->bPreparingForLowPowerMode == TRUE))
 			return -EINVAL;
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		if (IoBuffer.InputLength > sizeof(gpio_multi_mode))
@@ -719,7 +720,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 		PVOID pvBuffer = NULL;
 
 		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		if (IoBuffer.InputLength < sizeof(struct bcm_link_request))
@@ -799,7 +800,7 @@ cntrlEnd:
 		}
 
 		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) {
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) {
 			up(&Adapter->fw_download_sema);
 			return -EFAULT;
 		}
@@ -895,7 +896,7 @@ cntrlEnd:
 		mdelay(10);
 
 		/* Wait for MailBox Interrupt */
-		if (StartInterruptUrb((PS_INTERFACE_ADAPTER)Adapter->pvInterfaceAdapter))
+		if (StartInterruptUrb((struct bcm_interface_adapter *)Adapter->pvInterfaceAdapter))
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n");
 
 		timeout = 5*HZ;
@@ -1000,7 +1001,7 @@ cntrlEnd:
 		ulong len;
 
 		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		len = min_t(ulong, IoBuffer.OutputLength, strlen(VER_FILEVERSION_STR) + 1);
@@ -1015,7 +1016,7 @@ cntrlEnd:
 		LINK_STATE link_state;
 
 		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) {
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user failed..\n");
 			return -EFAULT;
 		}
@@ -1042,7 +1043,7 @@ cntrlEnd:
 		UINT  tracing_flag;
 
 		/* copy ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		if (copy_from_user(&tracing_flag, IoBuffer.InputBuffer, sizeof(UINT)))
@@ -1057,13 +1058,13 @@ cntrlEnd:
 
 	case IOCTL_BCM_GET_DSX_INDICATION: {
 		ULONG ulSFId = 0;
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
-		if (IoBuffer.OutputLength < sizeof(stLocalSFAddIndicationAlt)) {
+		if (IoBuffer.OutputLength < sizeof(struct bcm_add_indication_alt)) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
 					"Mismatch req: %lx needed is =0x%zx!!!",
-					IoBuffer.OutputLength, sizeof(stLocalSFAddIndicationAlt));
+					IoBuffer.OutputLength, sizeof(struct bcm_add_indication_alt));
 			return -EINVAL;
 		}
 
@@ -1079,18 +1080,18 @@ cntrlEnd:
 	case IOCTL_BCM_GET_HOST_MIBS: {
 		PVOID temp_buff;
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
-		if (IoBuffer.OutputLength != sizeof(S_MIBS_HOST_STATS_MIBS)) {
+		if (IoBuffer.OutputLength != sizeof(struct bcm_host_stats_mibs)) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
 					"Length Check failed %lu %zd\n",
-					IoBuffer.OutputLength, sizeof(S_MIBS_HOST_STATS_MIBS));
+					IoBuffer.OutputLength, sizeof(struct bcm_host_stats_mibs));
 			return -EINVAL;
 		}
 
 		/* FIXME: HOST_STATS are too big for kmalloc (122048)! */
-		temp_buff = kzalloc(sizeof(S_MIBS_HOST_STATS_MIBS), GFP_KERNEL);
+		temp_buff = kzalloc(sizeof(struct bcm_host_stats_mibs), GFP_KERNEL);
 		if (!temp_buff)
 			return STATUS_FAILURE;
 
@@ -1098,7 +1099,7 @@ cntrlEnd:
 		GetDroppedAppCntrlPktMibs(temp_buff, pTarang);
 
 		if (Status != STATUS_FAILURE)
-			if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(S_MIBS_HOST_STATS_MIBS))) {
+			if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(struct bcm_host_stats_mibs))) {
 				kfree(temp_buff);
 				return -EFAULT;
 			}
@@ -1118,7 +1119,7 @@ cntrlEnd:
 		break;
 
 	case IOCTL_BCM_BULK_WRM: {
-		PBULKWRM_BUFFER pBulkBuffer;
+		struct bcm_bulk_wrm_buffer *pBulkBuffer;
 		UINT uiTempVar = 0;
 		PCHAR pvBuffer = NULL;
 
@@ -1132,7 +1133,7 @@ cntrlEnd:
 		}
 
 		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		if (IoBuffer.InputLength < sizeof(ULONG) * 2)
@@ -1143,7 +1144,7 @@ cntrlEnd:
 		if (IS_ERR(pvBuffer))
 			return PTR_ERR(pvBuffer);
 
-		pBulkBuffer = (PBULKWRM_BUFFER)pvBuffer;
+		pBulkBuffer = (struct bcm_bulk_wrm_buffer *)pvBuffer;
 
 		if (((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 ||
 			((ULONG)pBulkBuffer->Register & 0x3)) {
@@ -1180,7 +1181,7 @@ cntrlEnd:
 	}
 
 	case IOCTL_BCM_GET_NVM_SIZE:
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		if (Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH) {
@@ -1194,7 +1195,7 @@ cntrlEnd:
 	case IOCTL_BCM_CAL_INIT: {
 		UINT uiSectorSize = 0 ;
 		if (Adapter->eNVMType == NVM_FLASH) {
-			if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+			if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 				return -EFAULT;
 
 			if (copy_from_user(&uiSectorSize, IoBuffer.InputBuffer, sizeof(UINT)))
@@ -1231,7 +1232,7 @@ cntrlEnd:
 		USER_BCM_DBG_STATE sUserDebugState;
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In SET_DEBUG ioctl\n");
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		if (copy_from_user(&sUserDebugState, IoBuffer.InputBuffer, sizeof(USER_BCM_DBG_STATE)))
@@ -1262,7 +1263,7 @@ cntrlEnd:
 
 	case IOCTL_BCM_NVM_READ:
 	case IOCTL_BCM_NVM_WRITE: {
-		NVM_READWRITE  stNVMReadWrite;
+		struct bcm_nvm_readwrite stNVMReadWrite;
 		PUCHAR pReadData = NULL;
 		ULONG ulDSDMagicNumInUsrBuff = 0;
 		struct timeval tv0, tv1;
@@ -1284,12 +1285,12 @@ cntrlEnd:
 		}
 
 		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		if (copy_from_user(&stNVMReadWrite,
 					(IOCTL_BCM_NVM_READ == cmd) ? IoBuffer.OutputBuffer : IoBuffer.InputBuffer,
-					sizeof(NVM_READWRITE)))
+					sizeof(struct bcm_nvm_readwrite)))
 			return -EFAULT;
 
 		/*
@@ -1404,7 +1405,7 @@ cntrlEnd:
 	}
 
 	case IOCTL_BCM_FLASH2X_SECTION_READ: {
-		FLASH2X_READWRITE sFlash2xRead = {0};
+		struct bcm_flash2x_readwrite sFlash2xRead = {0};
 		PUCHAR pReadBuff = NULL ;
 		UINT NOB = 0;
 		UINT BuffSize = 0;
@@ -1418,11 +1419,11 @@ cntrlEnd:
 		}
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called");
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		/* Reading FLASH 2.x READ structure */
-		if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE)))
+		if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer, sizeof(struct bcm_flash2x_readwrite)))
 			return -EFAULT;
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xRead.Section);
@@ -1495,7 +1496,7 @@ cntrlEnd:
 	break;
 
 	case IOCTL_BCM_FLASH2X_SECTION_WRITE: {
-		FLASH2X_READWRITE sFlash2xWrite = {0};
+		struct bcm_flash2x_readwrite sFlash2xWrite = {0};
 		PUCHAR pWriteBuff;
 		void __user *InputAddr;
 		UINT NOB = 0;
@@ -1513,11 +1514,11 @@ cntrlEnd:
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_WRITE Called");
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		/* Reading FLASH 2.x READ structure */
-		if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE)))
+		if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(struct bcm_flash2x_readwrite)))
 			return -EFAULT;
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xWrite.Section);
@@ -1604,16 +1605,16 @@ cntrlEnd:
 	break;
 
 	case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP: {
-		PFLASH2X_BITMAP psFlash2xBitMap;
+		struct bcm_flash2x_bitmap *psFlash2xBitMap;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called");
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
-		if (IoBuffer.OutputLength != sizeof(FLASH2X_BITMAP))
+		if (IoBuffer.OutputLength != sizeof(struct bcm_flash2x_bitmap))
 			return -EINVAL;
 
-		psFlash2xBitMap = kzalloc(sizeof(FLASH2X_BITMAP), GFP_KERNEL);
+		psFlash2xBitMap = kzalloc(sizeof(struct bcm_flash2x_bitmap), GFP_KERNEL);
 		if (psFlash2xBitMap == NULL) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory is not available");
 			return -ENOMEM;
@@ -1634,7 +1635,7 @@ cntrlEnd:
 
 		BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap);
 		up(&Adapter->NVMRdmWrmLock);
-		if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(FLASH2X_BITMAP))) {
+		if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(struct bcm_flash2x_bitmap))) {
 			kfree(psFlash2xBitMap);
 			return -EFAULT;
 		}
@@ -1644,7 +1645,7 @@ cntrlEnd:
 	break;
 
 	case IOCTL_BCM_SET_ACTIVE_SECTION: {
-		FLASH2X_SECTION_VAL eFlash2xSectionVal = 0;
+		enum bcm_flash2x_section_val eFlash2xSectionVal = 0;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SET_ACTIVE_SECTION Called");
 
 		if (IsFlash2x(Adapter) != TRUE) {
@@ -1652,7 +1653,7 @@ cntrlEnd:
 			return -EINVAL;
 		}
 
-		Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+		Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer));
 		if (Status) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
 			return -EFAULT;
@@ -1692,7 +1693,7 @@ cntrlEnd:
 	break;
 
 	case IOCTL_BCM_COPY_SECTION: {
-		FLASH2X_COPY_SECTION sCopySectStrut = {0};
+		struct bcm_flash2x_copy_section sCopySectStrut = {0};
 		Status = STATUS_SUCCESS;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_COPY_SECTION  Called");
 
@@ -1702,13 +1703,13 @@ cntrlEnd:
 			return -EINVAL;
 		}
 
-		Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+		Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer));
 		if (Status) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status);
 			return -EFAULT;
 		}
 
-		Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(FLASH2X_COPY_SECTION));
+		Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(struct bcm_flash2x_copy_section));
 		if (Status) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status);
 			return -EFAULT;
@@ -1769,7 +1770,7 @@ cntrlEnd:
 		Status = STATUS_SUCCESS;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_GET_FLASH_CS_INFO Called");
 
-		Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+		Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer));
 		if (Status) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
 			return -EFAULT;
@@ -1799,7 +1800,7 @@ cntrlEnd:
 
 	case IOCTL_BCM_SELECT_DSD: {
 		UINT SectOfset = 0;
-		FLASH2X_SECTION_VAL eFlash2xSectionVal;
+		enum bcm_flash2x_section_val eFlash2xSectionVal;
 		eFlash2xSectionVal = NO_SECTION_VAL;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SELECT_DSD Called");
 
@@ -1808,7 +1809,7 @@ cntrlEnd:
 			return -EINVAL;
 		}
 
-		Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+		Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer));
 		if (Status) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
 			return -EFAULT;
@@ -1842,7 +1843,7 @@ cntrlEnd:
 	break;
 
 	case IOCTL_BCM_NVM_RAW_READ: {
-		NVM_READWRITE stNVMRead;
+		struct bcm_nvm_readwrite stNVMRead;
 		INT NOB ;
 		INT BuffSize ;
 		INT ReadOffset = 0;
@@ -1856,12 +1857,12 @@ cntrlEnd:
 		}
 
 		/* Copy Ioctl Buffer structure */
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) {
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer))) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n");
 			return -EFAULT;
 		}
 
-		if (copy_from_user(&stNVMRead, IoBuffer.OutputBuffer, sizeof(NVM_READWRITE)))
+		if (copy_from_user(&stNVMRead, IoBuffer.OutputBuffer, sizeof(struct bcm_nvm_readwrite)))
 			return -EFAULT;
 
 		NOB = stNVMRead.uiNumBytes;
@@ -1933,7 +1934,7 @@ cntrlEnd:
 		ULONG RxCntrlMsgBitMask = 0;
 
 		/* Copy Ioctl Buffer structure */
-		Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
+		Status = copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer));
 		if (Status) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of Ioctl buffer is failed from user space");
 			return -EFAULT;
@@ -1955,7 +1956,7 @@ cntrlEnd:
 	break;
 
 	case IOCTL_BCM_GET_DEVICE_DRIVER_INFO: {
-		DEVICE_DRIVER_INFO DevInfo;
+		struct bcm_driver_info DevInfo;
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n");
 
@@ -1965,7 +1966,7 @@ cntrlEnd:
 		DevInfo.u32NVMType = Adapter->eNVMType;
 		DevInfo.u32InterfaceType = BCM_USB;
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
 		if (IoBuffer.OutputLength < sizeof(DevInfo))
@@ -1977,19 +1978,19 @@ cntrlEnd:
 	break;
 
 	case IOCTL_BCM_TIME_SINCE_NET_ENTRY: {
-		ST_TIME_ELAPSED stTimeElapsedSinceNetEntry = {0};
+		struct bcm_time_elapsed stTimeElapsedSinceNetEntry = {0};
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_TIME_SINCE_NET_ENTRY called");
 
-		if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
+		if (copy_from_user(&IoBuffer, argp, sizeof(struct bcm_ioctl_buffer)))
 			return -EFAULT;
 
-		if (IoBuffer.OutputLength < sizeof(ST_TIME_ELAPSED))
+		if (IoBuffer.OutputLength < sizeof(struct bcm_time_elapsed))
 			return -EINVAL;
 
 		stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = get_seconds() - Adapter->liTimeSinceLastNetEntry;
 
-		if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(ST_TIME_ELAPSED)))
+		if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(struct bcm_time_elapsed)))
 			return -EFAULT;
 	}
 	break;
diff --git a/drivers/staging/bcm/Bcmnet.c b/drivers/staging/bcm/Bcmnet.c
index 6e8c7f5..a3b91c7 100644
--- a/drivers/staging/bcm/Bcmnet.c
+++ b/drivers/staging/bcm/Bcmnet.c
@@ -142,7 +142,7 @@ static void bcm_get_drvinfo(struct net_device *dev,
 			    struct ethtool_drvinfo *info)
 {
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
-	PS_INTERFACE_ADAPTER psIntfAdapter = Adapter->pvInterfaceAdapter;
+	struct bcm_interface_adapter *psIntfAdapter = Adapter->pvInterfaceAdapter;
 	struct usb_device *udev = interface_to_usbdev(psIntfAdapter->interface);
 
 	strcpy(info->driver, DRV_NAME);
@@ -186,7 +186,7 @@ static const struct ethtool_ops bcm_ethtool_ops = {
 int register_networkdev(struct bcm_mini_adapter *Adapter)
 {
 	struct net_device *net = Adapter->dev;
-	PS_INTERFACE_ADAPTER IntfAdapter = Adapter->pvInterfaceAdapter;
+	struct bcm_interface_adapter *IntfAdapter = Adapter->pvInterfaceAdapter;
 	struct usb_interface *udev = IntfAdapter->interface;
 	struct usb_device *xdev = IntfAdapter->udev;
 
@@ -227,7 +227,7 @@ int register_networkdev(struct bcm_mini_adapter *Adapter)
 void unregister_networkdev(struct bcm_mini_adapter *Adapter)
 {
 	struct net_device *net = Adapter->dev;
-	PS_INTERFACE_ADAPTER IntfAdapter = Adapter->pvInterfaceAdapter;
+	struct bcm_interface_adapter *IntfAdapter = Adapter->pvInterfaceAdapter;
 	struct usb_interface *udev = IntfAdapter->interface;
 	struct usb_device *xdev = IntfAdapter->udev;
 
diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c
index 325b592..23ddc3d 100644
--- a/drivers/staging/bcm/CmHost.c
+++ b/drivers/staging/bcm/CmHost.c
@@ -107,7 +107,7 @@ static VOID deleteSFBySfid(struct bcm_mini_adapter *Adapter, UINT uiSearchRuleIn
 	DeleteAllClassifiersForSF(Adapter, uiSearchRuleIndex);
 
 	/* Resetting only MIBS related entries in the SF */
-	memset((PVOID)&Adapter->PackInfo[uiSearchRuleIndex], 0, sizeof(S_MIBS_SERVICEFLOW_TABLE));
+	memset((PVOID)&Adapter->PackInfo[uiSearchRuleIndex], 0, sizeof(struct bcm_mibs_table));
 }
 
 static inline VOID
@@ -431,7 +431,7 @@ static VOID CopyToAdapter(register struct bcm_mini_adapter *Adapter, /* <Pointer
 			register struct bcm_connect_mgr_params *psfLocalSet, /* Pointer to the connection manager parameters structure */
 			register UINT uiSearchRuleIndex, /* <Index of Queue, to which this data belongs */
 			register UCHAR ucDsxType,
-			stLocalSFAddIndicationAlt *pstAddIndication) {
+			struct bcm_add_indication_alt *pstAddIndication) {
 
 	/* UCHAR ucProtocolLength = 0; */
 	ULONG ulSFID;
@@ -833,11 +833,11 @@ static VOID DumpCmControlPacket(PVOID pvBuffer)
 {
 	int uiLoopIndex;
 	int nIndex;
-	stLocalSFAddIndicationAlt *pstAddIndication;
+	struct bcm_add_indication_alt *pstAddIndication;
 	UINT nCurClassifierCnt;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
-	pstAddIndication = (stLocalSFAddIndicationAlt *)pvBuffer;
+	pstAddIndication = (struct bcm_add_indication_alt *)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);
@@ -1333,13 +1333,13 @@ static ULONG StoreSFParam(struct bcm_mini_adapter *Adapter, PUCHAR pucSrcBuffer,
 
 ULONG StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBuffer, UINT *puBufferLength)
 {
-	stLocalSFAddIndicationAlt *pstAddIndicationAlt = NULL;
+	struct bcm_add_indication_alt *pstAddIndicationAlt = NULL;
 	struct bcm_add_indication *pstAddIndication = NULL;
 	struct bcm_del_request *pstDeletionRequest;
 	UINT uiSearchRuleIndex;
 	ULONG ulSFID;
 
-	pstAddIndicationAlt = (stLocalSFAddIndicationAlt *)(pvBuffer);
+	pstAddIndicationAlt = (struct bcm_add_indication_alt *)(pvBuffer);
 
 	/*
 	 * In case of DSD Req By MS, we should immediately delete this SF so that
@@ -1445,29 +1445,29 @@ ULONG StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBu
 	return 1;
 }
 
-static inline stLocalSFAddIndicationAlt
+static inline struct bcm_add_indication_alt
 *RestoreCmControlResponseMessage(register struct bcm_mini_adapter *Adapter, register PVOID pvBuffer)
 {
 	ULONG ulStatus = 0;
 	struct bcm_add_indication *pstAddIndication = NULL;
-	stLocalSFAddIndicationAlt *pstAddIndicationDest = NULL;
+	struct bcm_add_indication_alt *pstAddIndicationDest = NULL;
 
 	pstAddIndication = (struct bcm_add_indication *)(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 (stLocalSFAddIndicationAlt *)pvBuffer;
+		return (struct bcm_add_indication_alt *)pvBuffer;
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Inside RestoreCmControlResponseMessage ");
 	/*
 	 * Need to Allocate memory to contain the SUPER Large structures
 	 * Our driver can't create these structures on Stack :(
 	 */
-	pstAddIndicationDest = kmalloc(sizeof(stLocalSFAddIndicationAlt), GFP_KERNEL);
+	pstAddIndicationDest = kmalloc(sizeof(struct bcm_add_indication_alt), GFP_KERNEL);
 
 	if (pstAddIndicationDest) {
-		memset(pstAddIndicationDest, 0, sizeof(stLocalSFAddIndicationAlt));
+		memset(pstAddIndicationDest, 0, sizeof(struct bcm_add_indication_alt));
 	} else {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Failed to allocate memory for SF Add Indication Structure ");
 		return NULL;
@@ -1573,36 +1573,36 @@ ULONG SetUpTargetDsxBuffers(struct bcm_mini_adapter *Adapter)
 
 static ULONG GetNextTargetBufferLocation(struct bcm_mini_adapter *Adapter, B_UINT16 tid)
 {
-	ULONG ulTargetDSXBufferAddress;
-	ULONG ulTargetDsxBufferIndexToUse, ulMaxTry;
+	ULONG dsx_buf;
+	ULONG idx, max_try;
 
 	if ((Adapter->ulTotalTargetBuffersAvailable == 0) || (Adapter->ulFreeTargetBufferCnt == 0)) {
 		ClearTargetDSXBuffer(Adapter, tid, FALSE);
 		return 0;
 	}
 
-	ulTargetDsxBufferIndexToUse = Adapter->ulCurrentTargetBuffer;
-	ulMaxTry = Adapter->ulTotalTargetBuffersAvailable;
-	while ((ulMaxTry) && (Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].valid != 1)) {
-		ulTargetDsxBufferIndexToUse = (ulTargetDsxBufferIndexToUse+1) % Adapter->ulTotalTargetBuffersAvailable;
-		ulMaxTry--;
+	idx = Adapter->ulCurrentTargetBuffer;
+	max_try = Adapter->ulTotalTargetBuffersAvailable;
+	while ((max_try) && (Adapter->astTargetDsxBuffer[idx].valid != 1)) {
+		idx = (idx+1) % Adapter->ulTotalTargetBuffersAvailable;
+		max_try--;
 	}
 
-	if (ulMaxTry == 0) {
+	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);
 		return 0;
 	}
 
-	ulTargetDSXBufferAddress = Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].ulTargetDsxBuffer;
-	Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].valid = 0;
-	Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].tid = tid;
+	dsx_buf = Adapter->astTargetDsxBuffer[idx].ulTargetDsxBuffer;
+	Adapter->astTargetDsxBuffer[idx].valid = 0;
+	Adapter->astTargetDsxBuffer[idx].tid = tid;
 	Adapter->ulFreeTargetBufferCnt--;
-	ulTargetDsxBufferIndexToUse = (ulTargetDsxBufferIndexToUse+1)%Adapter->ulTotalTargetBuffersAvailable;
-	Adapter->ulCurrentTargetBuffer = ulTargetDsxBufferIndexToUse;
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "GetNextTargetBufferLocation :Returning address %lx tid %d\n", ulTargetDSXBufferAddress, tid);
+	idx = (idx+1)%Adapter->ulTotalTargetBuffersAvailable;
+	Adapter->ulCurrentTargetBuffer = idx;
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "GetNextTargetBufferLocation :Returning address %lx tid %d\n", dsx_buf, tid);
 
-	return ulTargetDSXBufferAddress;
+	return dsx_buf;
 }
 
 int AllocAdapterDsxBuffer(struct bcm_mini_adapter *Adapter)
@@ -1611,7 +1611,7 @@ int AllocAdapterDsxBuffer(struct bcm_mini_adapter *Adapter)
 	 * Need to Allocate memory to contain the SUPER Large structures
 	 * Our driver can't create these structures on Stack
 	 */
-	Adapter->caDsxReqResp = kmalloc(sizeof(stLocalSFAddIndicationAlt)+LEADER_SIZE, GFP_KERNEL);
+	Adapter->caDsxReqResp = kmalloc(sizeof(struct bcm_add_indication_alt)+LEADER_SIZE, GFP_KERNEL);
 	if (!Adapter->caDsxReqResp)
 		return -ENOMEM;
 
@@ -1634,8 +1634,8 @@ BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter,  /* <Pointer
 				PVOID pvBuffer /* Starting Address of the Buffer, that contains the AddIndication Data */)
 {
 	struct bcm_connect_mgr_params *psfLocalSet = NULL;
-	stLocalSFAddIndicationAlt *pstAddIndication = NULL;
-	stLocalSFChangeIndicationAlt *pstChangeIndication = NULL;
+	struct bcm_add_indication_alt *pstAddIndication = NULL;
+	struct bcm_change_indication *pstChangeIndication = NULL;
 	struct bcm_leader *pLeader = NULL;
 
 	/*
@@ -1661,12 +1661,12 @@ BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter,  /* <Pointer
 	switch (pstAddIndication->u8Type) {
 	case DSA_REQ:
 	{
-		pLeader->PLength = sizeof(stLocalSFAddIndicationAlt);
+		pLeader->PLength = sizeof(struct bcm_add_indication_alt);
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Sending DSA Response....\n");
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSA RESPONSE TO MAC %d", pLeader->PLength);
-		*((stLocalSFAddIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))
+		*((struct bcm_add_indication_alt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))
 			= *pstAddIndication;
-		((stLocalSFAddIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSA_RSP;
+		((struct bcm_add_indication_alt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSA_RSP;
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " VCID = %x", ntohs(pstAddIndication->u16VCID));
 		CopyBufferToControlPacket(Adapter, (PVOID)Adapter->caDsxReqResp);
@@ -1675,12 +1675,12 @@ BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter,  /* <Pointer
 	break;
 	case DSA_RSP:
 	{
-		pLeader->PLength = sizeof(stLocalSFAddIndicationAlt);
+		pLeader->PLength = sizeof(struct bcm_add_indication_alt);
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSA ACK TO MAC %d",
 				pLeader->PLength);
-		*((stLocalSFAddIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))
+		*((struct bcm_add_indication_alt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))
 			= *pstAddIndication;
-		((stLocalSFAddIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSA_ACK;
+		((struct bcm_add_indication_alt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSA_ACK;
 
 	} /* no break here..we should go down. */
 	case DSA_ACK:
@@ -1773,12 +1773,12 @@ BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter,  /* <Pointer
 	break;
 	case DSC_REQ:
 	{
-		pLeader->PLength = sizeof(stLocalSFChangeIndicationAlt);
-		pstChangeIndication = (stLocalSFChangeIndicationAlt *)pstAddIndication;
+		pLeader->PLength = sizeof(struct bcm_change_indication);
+		pstChangeIndication = (struct bcm_change_indication *)pstAddIndication;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSC RESPONSE TO MAC %d", pLeader->PLength);
 
-		*((stLocalSFChangeIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstChangeIndication;
-		((stLocalSFChangeIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_RSP;
+		*((struct bcm_change_indication *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstChangeIndication;
+		((struct bcm_change_indication *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_RSP;
 
 		CopyBufferToControlPacket(Adapter, (PVOID)Adapter->caDsxReqResp);
 		kfree(pstAddIndication);
@@ -1786,17 +1786,17 @@ BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter,  /* <Pointer
 	break;
 	case DSC_RSP:
 	{
-		pLeader->PLength = sizeof(stLocalSFChangeIndicationAlt);
-		pstChangeIndication = (stLocalSFChangeIndicationAlt *)pstAddIndication;
+		pLeader->PLength = sizeof(struct bcm_change_indication);
+		pstChangeIndication = (struct bcm_change_indication *)pstAddIndication;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSC ACK TO MAC %d", pLeader->PLength);
-		*((stLocalSFChangeIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstChangeIndication;
-		((stLocalSFChangeIndicationAlt *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_ACK;
+		*((struct bcm_change_indication *)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstChangeIndication;
+		((struct bcm_change_indication *)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_ACK;
 	}
 	case DSC_ACK:
 	{
 		UINT uiSearchRuleIndex = 0;
 
-		pstChangeIndication = (stLocalSFChangeIndicationAlt *)pstAddIndication;
+		pstChangeIndication = (struct bcm_change_indication *)pstAddIndication;
 		uiSearchRuleIndex = SearchSfid(Adapter, ntohl(pstChangeIndication->sfActiveSet.u32SFID));
 		if (uiSearchRuleIndex > NO_OF_QUEUES-1)
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "SF doesn't exist for which DSC_ACK is received");
@@ -1902,7 +1902,7 @@ int get_dsx_sf_data_to_application(struct bcm_mini_adapter *Adapter, UINT uiSFId
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "status =%d", status);
 	psSfInfo = &Adapter->PackInfo[status];
 	if (psSfInfo->pstSFIndication && copy_to_user(user_buffer,
-							psSfInfo->pstSFIndication, sizeof(stLocalSFAddIndicationAlt))) {
+							psSfInfo->pstSFIndication, sizeof(struct bcm_add_indication_alt))) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy to user failed SFID %d, present in queue !!!", uiSFId);
 		status = -EFAULT;
 		return status;
diff --git a/drivers/staging/bcm/CmHost.h b/drivers/staging/bcm/CmHost.h
index 1c5a07c..eecad8d 100644
--- a/drivers/staging/bcm/CmHost.h
+++ b/drivers/staging/bcm/CmHost.h
@@ -1,147 +1,66 @@
-/// **************************************************************************
-/// (c) Beceem Communications Inc.
-///     All Rights Reserved
-///
-///   \file        : CmHost.h
-///   \author      : Rajeev Tirumala
-///   \date        : September 8 , 2006
-///   \brief       : Definitions for Connection Management Requests structure
-///                  which we will use to setup our connection structures.Its high
-///                  time we had a header file for CmHost.cpp to isolate the way
-///                  f/w sends DSx messages and the way we interpret them in code.
-///                              Revision History
-///
-///    Date       Author   Version   Description
-///  08-Sep-06    Rajeev       0.1      Created
-/// **************************************************************************
+/***************************************************************************
+ * (c) Beceem Communications Inc.
+ * All Rights Reserved
+ *
+ * file  : CmHost.h
+ * author: Rajeev Tirumala
+ * date  : September 8 , 2006
+ * brief : Definitions for Connection Management Requests structure
+ *          which we will use to setup our connection structures.Its high
+ *          time we had a header file for CmHost.cpp to isolate the way
+ *          f/w sends DSx messages and the way we interpret them in code.
+ *          Revision History
+ *
+ *   Date       Author   Version   Description
+ *   08-Sep-06    Rajeev       0.1      Created
+ ***************************************************************************/
 #ifndef _CM_HOST_H
 #define _CM_HOST_H
 
 #pragma once
-#pragma pack (push,4)
-
-#define  DSX_MESSAGE_EXCHANGE_BUFFER        0xBF60AC84 // This contains the pointer
-#define  DSX_MESSAGE_EXCHANGE_BUFFER_SIZE   72000 // 24 K Bytes
-
-/// \brief structure stLocalSFAddRequest
-typedef struct stLocalSFAddRequestAlt{
-	B_UINT8                         u8Type;
-	B_UINT8      u8Direction;
-
-	B_UINT16                        u16TID;
-   /// \brief 16bitCID
-    B_UINT16                        u16CID;
-    /// \brief 16bitVCID
-    B_UINT16                        u16VCID;
-
-
-	struct bcm_connect_mgr_params sfParameterSet;
-
-    //USE_MEMORY_MANAGER();
-}stLocalSFAddRequestAlt;
-
-/// \brief structure stLocalSFAddIndication
-typedef struct stLocalSFAddIndicationAlt{
-    B_UINT8                         u8Type;
-	B_UINT8      u8Direction;
-	B_UINT16                         u16TID;
-    /// \brief 16bitCID
-    B_UINT16                        u16CID;
-    /// \brief 16bitVCID
-    B_UINT16                        u16VCID;
+#pragma pack(push, 4)
+
+#define DSX_MESSAGE_EXCHANGE_BUFFER        0xBF60AC84 /* This contains the pointer */
+#define DSX_MESSAGE_EXCHANGE_BUFFER_SIZE   72000      /* 24 K Bytes */
+
+struct bcm_add_indication_alt {
+	u8	u8Type;
+	u8	u8Direction;
+	u16	u16TID;
+	/* brief 16bitCID */
+	u16	u16CID;
+	/* brief 16bitVCID */
+	u16	u16VCID;
 	struct bcm_connect_mgr_params sfAuthorizedSet;
 	struct bcm_connect_mgr_params sfAdmittedSet;
 	struct bcm_connect_mgr_params sfActiveSet;
-
-	B_UINT8 						u8CC;	/**<  Confirmation Code*/
-	B_UINT8 						u8Padd; 	/**<  8-bit Padding */
-	B_UINT16						u16Padd;	/**< 16 bit Padding */
-//    USE_MEMORY_MANAGER();
-}stLocalSFAddIndicationAlt;
-
-/// \brief structure stLocalSFAddConfirmation
-typedef struct stLocalSFAddConfirmationAlt{
-	B_UINT8                     u8Type;
-	B_UINT8      				u8Direction;
-	B_UINT16					u16TID;
-    /// \brief 16bitCID
-    B_UINT16                        u16CID;
-    /// \brief 16bitVCID
-    B_UINT16                        u16VCID;
+	u8	u8CC;    /* < Confirmation Code */
+	u8	u8Padd;  /* < 8-bit Padding */
+	u16	u16Padd; /* < 16 bit Padding */
+};
+
+struct bcm_change_indication {
+	u8	u8Type;
+	u8	u8Direction;
+	u16	u16TID;
+	/* brief 16bitCID */
+	u16	u16CID;
+	/* brief 16bitVCID */
+	u16	u16VCID;
 	struct bcm_connect_mgr_params sfAuthorizedSet;
 	struct bcm_connect_mgr_params sfAdmittedSet;
 	struct bcm_connect_mgr_params sfActiveSet;
-}stLocalSFAddConfirmationAlt;
-
-
-/// \brief structure stLocalSFChangeRequest
-typedef struct stLocalSFChangeRequestAlt{
-    B_UINT8                         u8Type;
-	B_UINT8      u8Direction;
-	B_UINT16					u16TID;
-    /// \brief 16bitCID
-    B_UINT16                        u16CID;
-    /// \brief 16bitVCID
-    B_UINT16                        u16VCID;
-	/*
-	//Pointer location at which following connection manager param Structure can be read
-	//from the target. We only get the address location and we need to read out the
-	//entire connection manager param structure at the given location on target
-	*/
-	struct bcm_connect_mgr_params sfAuthorizedSet;
-	struct bcm_connect_mgr_params sfAdmittedSet;
-	struct bcm_connect_mgr_params sfActiveSet;
-
-	B_UINT8 						u8CC;	/**<  Confirmation Code*/
-	B_UINT8 						u8Padd; 	/**<  8-bit Padding */
-	B_UINT16						u16Padd;	/**< 16 bit */
-
-}stLocalSFChangeRequestAlt;
-
-/// \brief structure stLocalSFChangeConfirmation
-typedef struct stLocalSFChangeConfirmationAlt{
-	B_UINT8                         u8Type;
-	B_UINT8      					u8Direction;
-	B_UINT16						u16TID;
-    /// \brief 16bitCID
-    B_UINT16                        u16CID;
-    /// \brief 16bitVCID
-    B_UINT16                        u16VCID;
-	struct bcm_connect_mgr_params sfAuthorizedSet;
-	struct bcm_connect_mgr_params sfAdmittedSet;
-	struct bcm_connect_mgr_params sfActiveSet;
-
-}stLocalSFChangeConfirmationAlt;
-
-/// \brief structure stLocalSFChangeIndication
-typedef struct stLocalSFChangeIndicationAlt{
-	B_UINT8                         u8Type;
-		B_UINT8      u8Direction;
-	B_UINT16						u16TID;
-    /// \brief 16bitCID
-    B_UINT16                        u16CID;
-    /// \brief 16bitVCID
-    B_UINT16                        u16VCID;
-	struct bcm_connect_mgr_params sfAuthorizedSet;
-	struct bcm_connect_mgr_params sfAdmittedSet;
-	struct bcm_connect_mgr_params sfActiveSet;
-
-	B_UINT8 						u8CC;	/**<  Confirmation Code*/
-	B_UINT8 						u8Padd; 	/**<  8-bit Padding */
-	B_UINT16						u16Padd;	/**< 16 bit */
-
-}stLocalSFChangeIndicationAlt;
-
-ULONG StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBuffer,UINT *puBufferLength);
-
-INT AllocAdapterDsxBuffer(struct bcm_mini_adapter *Adapter);
-
-INT FreeAdapterDsxBuffer(struct bcm_mini_adapter *Adapter);
-ULONG SetUpTargetDsxBuffers(struct bcm_mini_adapter *Adapter);
-
-BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter, PVOID pvBuffer);
-
-
-#pragma pack (pop)
+	u8	u8CC;    /* < Confirmation Code */
+	u8	u8Padd;  /* < 8-bit Padding */
+	u16	u16Padd; /* < 16 bit */
+};
+
+unsigned long StoreCmControlResponseMessage(struct bcm_mini_adapter *Adapter, void *pvBuffer, unsigned int *puBufferLength);
+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);
+
+#pragma pack(pop)
 
 #endif
diff --git a/drivers/staging/bcm/HandleControlPacket.c b/drivers/staging/bcm/HandleControlPacket.c
index 25e5c68..1bb53e2 100644
--- a/drivers/staging/bcm/HandleControlPacket.c
+++ b/drivers/staging/bcm/HandleControlPacket.c
@@ -226,7 +226,7 @@ INT flushAllAppQ(void)
 		pTarang->AppCtrlQueueLen = 0;
 		/* dropped contrl packet statistics also should be reset. */
 		memset((PVOID)&pTarang->stDroppedAppCntrlMsgs, 0,
-			sizeof(S_MIBS_DROPPED_APP_CNTRL_MESSAGES));
+			sizeof(struct bcm_mibs_dropped_cntrl_msg));
 
 	}
 	return STATUS_SUCCESS;
diff --git a/drivers/staging/bcm/HostMIBSInterface.h b/drivers/staging/bcm/HostMIBSInterface.h
index e34531b..f922ac4 100644
--- a/drivers/staging/bcm/HostMIBSInterface.h
+++ b/drivers/staging/bcm/HostMIBSInterface.h
@@ -1,5 +1,3 @@
-
-
 #ifndef _HOST_MIBSINTERFACE_H
 #define _HOST_MIBSINTERFACE_H
 
@@ -10,221 +8,185 @@
  * statistics used for the MIBS.
  */
 
-#define MIBS_MAX_CLASSIFIERS 100
-#define MIBS_MAX_PHSRULES 100
-#define MIBS_MAX_SERVICEFLOWS 17
-#define MIBS_MAX_IP_RANGE_LENGTH 4
-#define MIBS_MAX_PORT_RANGE 4
-#define MIBS_MAX_PROTOCOL_LENGTH   32
-#define MIBS_MAX_PHS_LENGTHS	 255
-#define MIBS_IPV6_ADDRESS_SIZEINBYTES 0x10
+#define MIBS_MAX_CLASSIFIERS		100
+#define MIBS_MAX_PHSRULES		100
+#define MIBS_MAX_SERVICEFLOWS		17
+#define MIBS_MAX_IP_RANGE_LENGTH	4
+#define MIBS_MAX_PORT_RANGE		4
+#define MIBS_MAX_PROTOCOL_LENGTH	32
+#define MIBS_MAX_PHS_LENGTHS		255
+#define MIBS_IPV6_ADDRESS_SIZEINBYTES	0x10
 #define MIBS_IP_LENGTH_OF_ADDRESS	4
-#define MIBS_MAX_HIST_ENTRIES 12
-#define MIBS_PKTSIZEHIST_RANGE 128
-
-typedef union _U_MIBS_IP_ADDRESS
-{
-    struct
-	{
-		//Source Ip Address Range
-		ULONG		ulIpv4Addr[MIBS_MAX_IP_RANGE_LENGTH];
-		//Source Ip Mask Address Range
-		ULONG       ulIpv4Mask[MIBS_MAX_IP_RANGE_LENGTH];
+#define MIBS_MAX_HIST_ENTRIES		12
+#define MIBS_PKTSIZEHIST_RANGE		128
+
+union bcm_mibs_ip_addr {
+	struct {
+		/* Source Ip Address Range */
+		unsigned long ulIpv4Addr[MIBS_MAX_IP_RANGE_LENGTH];
+		/* Source Ip Mask Address Range */
+		unsigned long ulIpv4Mask[MIBS_MAX_IP_RANGE_LENGTH];
 	};
-	struct
-	{
-		//Source Ip Address Range
-		ULONG		ulIpv6Addr[MIBS_MAX_IP_RANGE_LENGTH * 4];
-		//Source Ip Mask Address Range
-		ULONG       ulIpv6Mask[MIBS_MAX_IP_RANGE_LENGTH * 4];
-
+	struct {
+		/* Source Ip Address Range */
+		unsigned long ulIpv6Addr[MIBS_MAX_IP_RANGE_LENGTH * 4];
+		/* Source Ip Mask Address Range */
+		unsigned long ulIpv6Mask[MIBS_MAX_IP_RANGE_LENGTH * 4];
 	};
-	struct
-	{
-		UCHAR		ucIpv4Address[MIBS_MAX_IP_RANGE_LENGTH *
-									MIBS_IP_LENGTH_OF_ADDRESS];
-		UCHAR		ucIpv4Mask[MIBS_MAX_IP_RANGE_LENGTH *
-									MIBS_IP_LENGTH_OF_ADDRESS];
+	struct {
+		unsigned char ucIpv4Address[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IP_LENGTH_OF_ADDRESS];
+		unsigned char ucIpv4Mask[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IP_LENGTH_OF_ADDRESS];
 	};
-	struct
-	{
-		UCHAR		ucIpv6Address[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IPV6_ADDRESS_SIZEINBYTES];
-		UCHAR		ucIpv6Mask[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IPV6_ADDRESS_SIZEINBYTES];
+	struct {
+		unsigned char ucIpv6Address[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IPV6_ADDRESS_SIZEINBYTES];
+		unsigned char ucIpv6Mask[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IPV6_ADDRESS_SIZEINBYTES];
 	};
-}U_MIBS_IP_ADDRESS;
-
-
-typedef struct _S_MIBS_HOST_INFO
-{
-	ULONG64			GoodTransmits;
-	ULONG64			GoodReceives;
-	// this to keep track of the Tx and Rx MailBox Registers.
-	ULONG			NumDesUsed;
-	ULONG			CurrNumFreeDesc;
-	ULONG			PrevNumFreeDesc;
-	// to keep track the no of byte received
-	ULONG			PrevNumRcevBytes;
-	ULONG			CurrNumRcevBytes;
-
+};
+
+struct bcm_mibs_host_info {
+	u64	GoodTransmits;
+	u64	GoodReceives;
+	/* this to keep track of the Tx and Rx MailBox Registers. */
+	unsigned long	NumDesUsed;
+	unsigned long	CurrNumFreeDesc;
+	unsigned long	PrevNumFreeDesc;
+	/* to keep track the no of byte received */
+	unsigned long	PrevNumRcevBytes;
+	unsigned long	CurrNumRcevBytes;
 	/* QOS Related */
-	ULONG			BEBucketSize;
-	ULONG			rtPSBucketSize;
-	ULONG			LastTxQueueIndex;
-	BOOLEAN			TxOutofDescriptors;
-	BOOLEAN			TimerActive;
-	UINT32			u32TotalDSD;
-	UINT32			aTxPktSizeHist[MIBS_MAX_HIST_ENTRIES];
-	UINT32			aRxPktSizeHist[MIBS_MAX_HIST_ENTRIES];
-}S_MIBS_HOST_INFO;
-
-typedef struct _S_MIBS_CLASSIFIER_RULE
-{
-	ULONG				ulSFID;
-	UCHAR               ucReserved[2];
-	B_UINT16            uiClassifierRuleIndex;
-	BOOLEAN				bUsed;
-	USHORT				usVCID_Value;
-	// This field detemines the Classifier Priority
-	B_UINT8             u8ClassifierRulePriority;
-	U_MIBS_IP_ADDRESS   stSrcIpAddress;
-	/*IP Source Address Length*/
-	UCHAR               ucIPSourceAddressLength;
-
-	U_MIBS_IP_ADDRESS   stDestIpAddress;
+	unsigned long	BEBucketSize;
+	unsigned long	rtPSBucketSize;
+	unsigned long	LastTxQueueIndex;
+	bool	TxOutofDescriptors;
+	bool	TimerActive;
+	u32	u32TotalDSD;
+	u32	aTxPktSizeHist[MIBS_MAX_HIST_ENTRIES];
+	u32	aRxPktSizeHist[MIBS_MAX_HIST_ENTRIES];
+};
+
+struct bcm_mibs_classifier_rule {
+	unsigned long	ulSFID;
+	unsigned char	ucReserved[2];
+	u16	uiClassifierRuleIndex;
+	bool	bUsed;
+	unsigned short	usVCID_Value;
+	u8	u8ClassifierRulePriority;
+	union bcm_mibs_ip_addr stSrcIpAddress;
+	/* IP Source Address Length */
+	unsigned char	ucIPSourceAddressLength;
+	union bcm_mibs_ip_addr stDestIpAddress;
 	/* IP Destination Address Length */
-	UCHAR               ucIPDestinationAddressLength;
-	UCHAR               ucIPTypeOfServiceLength;//Type of service Length
-	UCHAR               ucTosLow;//Tos Low
-	UCHAR               ucTosHigh;//Tos High
-	UCHAR               ucTosMask;//Tos Mask
-	UCHAR               ucProtocolLength;//protocol Length
-	UCHAR               ucProtocol[MIBS_MAX_PROTOCOL_LENGTH];//protocol Length
-	USHORT				usSrcPortRangeLo[MIBS_MAX_PORT_RANGE];
-	USHORT				usSrcPortRangeHi[MIBS_MAX_PORT_RANGE];
-	UCHAR               ucSrcPortRangeLength;
-	USHORT				usDestPortRangeLo[MIBS_MAX_PORT_RANGE];
-	USHORT				usDestPortRangeHi[MIBS_MAX_PORT_RANGE];
-	UCHAR               ucDestPortRangeLength;
-	BOOLEAN				bProtocolValid;
-	BOOLEAN				bTOSValid;
-	BOOLEAN				bDestIpValid;
-	BOOLEAN				bSrcIpValid;
-	UCHAR				ucDirection;
-	BOOLEAN             bIpv6Protocol;
-	UINT32              u32PHSRuleID;
-}S_MIBS_CLASSIFIER_RULE;
-
-
-typedef struct _S_MIBS_PHS_RULE
-{
-	ULONG		ulSFID;
-	/// brief 8bit PHSI Of The Service Flow
-	B_UINT8     u8PHSI;
-	/// brief PHSF Of The Service Flow
-	B_UINT8     u8PHSFLength;
-	B_UINT8     u8PHSF[MIBS_MAX_PHS_LENGTHS];
-	/// brief PHSM Of The Service Flow
-	B_UINT8     u8PHSMLength;
-	B_UINT8     u8PHSM[MIBS_MAX_PHS_LENGTHS];
-	/// brief 8bit PHSS Of The Service Flow
-	B_UINT8     u8PHSS;
-	/// brief 8bit PHSV Of The Service Flow
-	B_UINT8     u8PHSV;
-	// Reserved bytes are 5, so that it is similar to S_PHS_RULE structure.
-	B_UINT8	    reserved[5];
+	unsigned char	ucIPDestinationAddressLength;
+	unsigned char	ucIPTypeOfServiceLength;
+	unsigned char	ucTosLow;
+	unsigned char	ucTosHigh;
+	unsigned char	ucTosMask;
+	unsigned char	ucProtocolLength;
+	unsigned char	ucProtocol[MIBS_MAX_PROTOCOL_LENGTH];
+	unsigned short	usSrcPortRangeLo[MIBS_MAX_PORT_RANGE];
+	unsigned short	usSrcPortRangeHi[MIBS_MAX_PORT_RANGE];
+	unsigned char	ucSrcPortRangeLength;
+	unsigned short	usDestPortRangeLo[MIBS_MAX_PORT_RANGE];
+	unsigned short	usDestPortRangeHi[MIBS_MAX_PORT_RANGE];
+	unsigned char	ucDestPortRangeLength;
+	bool	bProtocolValid;
+	bool	bTOSValid;
+	bool	bDestIpValid;
+	bool	bSrcIpValid;
+	unsigned char	ucDirection;
+	bool	bIpv6Protocol;
+	u32	u32PHSRuleID;
+};
+
+struct bcm_mibs_phs_rule {
+	unsigned long	ulSFID;
+	u8	u8PHSI;
+	u8	u8PHSFLength;
+	u8	u8PHSF[MIBS_MAX_PHS_LENGTHS];
+	u8	u8PHSMLength;
+	u8	u8PHSM[MIBS_MAX_PHS_LENGTHS];
+	u8	u8PHSS;
+	u8	u8PHSV;
+	u8	reserved[5];
+	long	PHSModifiedBytes;
+	unsigned long	PHSModifiedNumPackets;
+	unsigned long	PHSErrorNumPackets;
+};
+
+struct bcm_mibs_parameters {
+	u32 wmanIfSfid;
+	u32 wmanIfCmnCpsSfState;
+	u32 wmanIfCmnCpsMaxSustainedRate;
+	u32 wmanIfCmnCpsMaxTrafficBurst;
+	u32 wmanIfCmnCpsMinReservedRate;
+	u32 wmanIfCmnCpsToleratedJitter;
+	u32 wmanIfCmnCpsMaxLatency;
+	u32 wmanIfCmnCpsFixedVsVariableSduInd;
+	u32 wmanIfCmnCpsSduSize;
+	u32 wmanIfCmnCpsSfSchedulingType;
+	u32 wmanIfCmnCpsArqEnable;
+	u32 wmanIfCmnCpsArqWindowSize;
+	u32 wmanIfCmnCpsArqBlockLifetime;
+	u32 wmanIfCmnCpsArqSyncLossTimeout;
+	u32 wmanIfCmnCpsArqDeliverInOrder;
+	u32 wmanIfCmnCpsArqRxPurgeTimeout;
+	u32 wmanIfCmnCpsArqBlockSize;
+	u32 wmanIfCmnCpsMinRsvdTolerableRate;
+	u32 wmanIfCmnCpsReqTxPolicy;
+	u32 wmanIfCmnSfCsSpecification;
+	u32 wmanIfCmnCpsTargetSaid;
+};
+
+struct bcm_mibs_table {
+	unsigned long	ulSFID;
+	unsigned short	usVCID_Value;
+	unsigned int	uiThreshold;
+	u8	u8TrafficPriority;
+	bool	bValid;
+	bool	bActive;
+	bool	bActivateRequestSent;
+	u8	u8QueueType;
+	unsigned int	uiMaxBucketSize;
+	unsigned int	uiCurrentQueueDepthOnTarget;
+	unsigned int	uiCurrentBytesOnHost;
+	unsigned int	uiCurrentPacketsOnHost;
+	unsigned int	uiDroppedCountBytes;
+	unsigned int	uiDroppedCountPackets;
+	unsigned int	uiSentBytes;
+	unsigned int	uiSentPackets;
+	unsigned int	uiCurrentDrainRate;
+	unsigned int	uiThisPeriodSentBytes;
+	u64	liDrainCalculated;
+	unsigned int	uiCurrentTokenCount;
+	u64	liLastUpdateTokenAt;
+	unsigned int	uiMaxAllowedRate;
+	unsigned int	NumOfPacketsSent;
+	unsigned char ucDirection;
+	unsigned short	usCID;
+	struct bcm_mibs_parameters stMibsExtServiceFlowTable;
+	unsigned int	uiCurrentRxRate;
+	unsigned int	uiThisPeriodRxBytes;
+	unsigned int	uiTotalRxBytes;
+	unsigned int	uiTotalTxBytes;
+};
+
+struct bcm_mibs_dropped_cntrl_msg {
+	unsigned long cm_responses;
+	unsigned long cm_control_newdsx_multiclassifier_resp;
+	unsigned long link_control_resp;
+	unsigned long status_rsp;
+	unsigned long stats_pointer_resp;
+	unsigned long idle_mode_status;
+	unsigned long auth_ss_host_msg;
+	unsigned long low_priority_message;
+};
+
+struct bcm_host_stats_mibs {
+	struct bcm_mibs_host_info stHostInfo;
+	struct bcm_mibs_classifier_rule astClassifierTable[MIBS_MAX_CLASSIFIERS];
+	struct bcm_mibs_table	astSFtable[MIBS_MAX_SERVICEFLOWS];
+	struct bcm_mibs_phs_rule astPhsRulesTable[MIBS_MAX_PHSRULES];
+	struct bcm_mibs_dropped_cntrl_msg stDroppedAppCntrlMsgs;
+};
 
-	LONG	    PHSModifiedBytes;
-	ULONG	    PHSModifiedNumPackets;
-	ULONG		PHSErrorNumPackets;
-}S_MIBS_PHS_RULE;
-
-typedef struct _S_MIBS_EXTSERVICEFLOW_PARAMETERS
-{
-	UINT32 		wmanIfSfid;
-	UINT32 		wmanIfCmnCpsSfState;
-	UINT32 		wmanIfCmnCpsMaxSustainedRate;
-	UINT32 		wmanIfCmnCpsMaxTrafficBurst;
-	UINT32 		wmanIfCmnCpsMinReservedRate;
-	UINT32 		wmanIfCmnCpsToleratedJitter;
-	UINT32 		wmanIfCmnCpsMaxLatency;
-	UINT32 		wmanIfCmnCpsFixedVsVariableSduInd;
-	UINT32 		wmanIfCmnCpsSduSize;
-	UINT32 		wmanIfCmnCpsSfSchedulingType;
-	UINT32 		wmanIfCmnCpsArqEnable;
-	UINT32 		wmanIfCmnCpsArqWindowSize;
-	UINT32 		wmanIfCmnCpsArqBlockLifetime;
-	UINT32 		wmanIfCmnCpsArqSyncLossTimeout;
-	UINT32 		wmanIfCmnCpsArqDeliverInOrder;
-	UINT32 		wmanIfCmnCpsArqRxPurgeTimeout;
-	UINT32 		wmanIfCmnCpsArqBlockSize;
-	UINT32 		wmanIfCmnCpsMinRsvdTolerableRate;
-	UINT32 		wmanIfCmnCpsReqTxPolicy;
-	UINT32 		wmanIfCmnSfCsSpecification;
-	UINT32 		wmanIfCmnCpsTargetSaid;
-
-}S_MIBS_EXTSERVICEFLOW_PARAMETERS;
-
-
-typedef struct _S_MIBS_SERVICEFLOW_TABLE
-{
-	 //classification extension Rule
-	ULONG		ulSFID;
-    USHORT		usVCID_Value;
-	UINT		uiThreshold;
-	// This field determines the priority of the SF Queues
-	B_UINT8     u8TrafficPriority;
-
-	BOOLEAN		bValid;
-   	BOOLEAN     bActive;
-	BOOLEAN		bActivateRequestSent;
-	//BE or rtPS
-	B_UINT8		u8QueueType;
-	//maximum size of the bucket for the queue
-	UINT		uiMaxBucketSize;
-	UINT		uiCurrentQueueDepthOnTarget;
-	UINT		uiCurrentBytesOnHost;
-	UINT		uiCurrentPacketsOnHost;
-	UINT		uiDroppedCountBytes;
-	UINT		uiDroppedCountPackets;
-	UINT		uiSentBytes;
-	UINT		uiSentPackets;
-	UINT		uiCurrentDrainRate;
-	UINT		uiThisPeriodSentBytes;
-	LARGE_INTEGER	liDrainCalculated;
-	UINT		uiCurrentTokenCount;
-	LARGE_INTEGER	liLastUpdateTokenAt;
-	UINT		uiMaxAllowedRate;
-	UINT        NumOfPacketsSent;
-	UCHAR		ucDirection;
-	USHORT		usCID;
-	S_MIBS_EXTSERVICEFLOW_PARAMETERS	stMibsExtServiceFlowTable;
-	UINT		uiCurrentRxRate;
-	UINT		uiThisPeriodRxBytes;
-	UINT		uiTotalRxBytes;
-	UINT		uiTotalTxBytes;
-}S_MIBS_SERVICEFLOW_TABLE;
-
-typedef struct _S_MIBS_DROPPED_APP_CNTRL_MESSAGES
-{
-	ULONG cm_responses;
-	ULONG cm_control_newdsx_multiclassifier_resp;
-	ULONG link_control_resp;
-	ULONG status_rsp;
-	ULONG stats_pointer_resp;
-	ULONG idle_mode_status;
-	ULONG auth_ss_host_msg;
-	ULONG low_priority_message;
-
-}S_MIBS_DROPPED_APP_CNTRL_MESSAGES;
-
-typedef struct _S_MIBS_HOST_STATS_MIBS
-{
-	S_MIBS_HOST_INFO				stHostInfo;
-	S_MIBS_CLASSIFIER_RULE			astClassifierTable[MIBS_MAX_CLASSIFIERS];
-	S_MIBS_SERVICEFLOW_TABLE		astSFtable[MIBS_MAX_SERVICEFLOWS];
-	S_MIBS_PHS_RULE                 astPhsRulesTable[MIBS_MAX_PHSRULES];
-	S_MIBS_DROPPED_APP_CNTRL_MESSAGES	stDroppedAppCntrlMsgs;
-}S_MIBS_HOST_STATS_MIBS;
 #endif
-
-
diff --git a/drivers/staging/bcm/InterfaceAdapter.h b/drivers/staging/bcm/InterfaceAdapter.h
index 4607c26..06a6b18 100644
--- a/drivers/staging/bcm/InterfaceAdapter.h
+++ b/drivers/staging/bcm/InterfaceAdapter.h
@@ -1,97 +1,79 @@
 #ifndef _INTERFACE_ADAPTER_H
 #define _INTERFACE_ADAPTER_H
 
-typedef struct _BULK_ENDP_IN
-{
-    PCHAR		    bulk_in_buffer;
-    size_t          bulk_in_size;
-    UCHAR			bulk_in_endpointAddr;
-    UINT bulk_in_pipe;
-}BULK_ENDP_IN, *PBULK_ENDP_IN;
-
-
-typedef struct _BULK_ENDP_OUT
-{
-    UCHAR			bulk_out_buffer;
-    size_t          bulk_out_size;
-    UCHAR			bulk_out_endpointAddr;
-    UINT bulk_out_pipe;
-    //this is used when int out endpoint is used as bulk out end point
-	UCHAR			int_out_interval;
-}BULK_ENDP_OUT, *PBULK_ENDP_OUT;
-
-typedef struct _INTR_ENDP_IN
-{
-    PCHAR		    int_in_buffer;
-    size_t          int_in_size;
-    UCHAR			int_in_endpointAddr;
-    UCHAR			int_in_interval;
-    UINT int_in_pipe;
-}INTR_ENDP_IN, *PINTR_ENDP_IN;
-
-typedef struct _INTR_ENDP_OUT
-{
-    PCHAR		    int_out_buffer;
-    size_t          int_out_size;
-    UCHAR			int_out_endpointAddr;
-    UCHAR			int_out_interval;
-    UINT int_out_pipe;
-}INTR_ENDP_OUT, *PINTR_ENDP_OUT;
-
-
-typedef struct _USB_TCB
-{
+struct bcm_bulk_endpoint_in {
+	char	*bulk_in_buffer;
+	size_t	bulk_in_size;
+	unsigned char	bulk_in_endpointAddr;
+	unsigned int	bulk_in_pipe;
+};
+
+struct bcm_bulk_endpoint_out {
+	unsigned char	bulk_out_buffer;
+	size_t	bulk_out_size;
+	unsigned char	bulk_out_endpointAddr;
+	unsigned int	bulk_out_pipe;
+	/* this is used when int out endpoint is used as bulk out end point */
+	unsigned char	int_out_interval;
+};
+
+struct bcm_intr_endpoint_in {
+	char	*int_in_buffer;
+	size_t	int_in_size;
+	unsigned char	int_in_endpointAddr;
+	unsigned char	int_in_interval;
+	unsigned int	int_in_pipe;
+};
+
+struct bcm_intr_endpoint_out {
+	char	*int_out_buffer;
+	size_t	int_out_size;
+	unsigned char	int_out_endpointAddr;
+	unsigned char	int_out_interval;
+	unsigned int	int_out_pipe;
+};
+
+struct bcm_usb_tcb {
 	struct urb *urb;
-	PVOID psIntfAdapter;
-	BOOLEAN bUsed;
-}USB_TCB, *PUSB_TCB;
+	void *psIntfAdapter;
+	bool bUsed;
+};
 
-
-typedef struct _USB_RCB
-{
+struct bcm_usb_rcb {
 	struct urb *urb;
-	PVOID psIntfAdapter;
-	BOOLEAN bUsed;
-}USB_RCB, *PUSB_RCB;
+	void *psIntfAdapter;
+	bool bUsed;
+};
 
 /*
-//This is the interface specific Sub-Adapter
-//Structure.
-*/
-typedef struct _S_INTERFACE_ADAPTER
-{
-    struct usb_device * udev;
-    struct usb_interface *  interface;
-
+ * This is the interface specific Sub-Adapter
+ * Structure.
+ */
+struct bcm_interface_adapter {
+	struct usb_device *udev;
+	struct usb_interface *interface;
 	/* Bulk endpoint in info */
-	BULK_ENDP_IN	sBulkIn;
+	struct bcm_bulk_endpoint_in	sBulkIn;
 	/* Bulk endpoint out info */
-	BULK_ENDP_OUT	sBulkOut;
+	struct bcm_bulk_endpoint_out	sBulkOut;
 	/* Interrupt endpoint in info */
-	INTR_ENDP_IN	sIntrIn;
+	struct bcm_intr_endpoint_in	sIntrIn;
 	/* Interrupt endpoint out info */
-	INTR_ENDP_OUT	sIntrOut;
-
-
-
-	ULONG ulInterruptData[2];
-
+	struct bcm_intr_endpoint_out	sIntrOut;
+	unsigned long		ulInterruptData[2];
 	struct urb *psInterruptUrb;
-
-	USB_TCB			asUsbTcb[MAXIMUM_USB_TCB];
-	USB_RCB			asUsbRcb[MAXIMUM_USB_RCB];
-	atomic_t	  	uNumTcbUsed;
-	atomic_t		uCurrTcb;
-	atomic_t		uNumRcbUsed;
-	atomic_t		uCurrRcb;
-
+	struct bcm_usb_tcb	asUsbTcb[MAXIMUM_USB_TCB];
+	struct bcm_usb_rcb	asUsbRcb[MAXIMUM_USB_RCB];
+	atomic_t	uNumTcbUsed;
+	atomic_t	uCurrTcb;
+	atomic_t	uNumRcbUsed;
+	atomic_t	uCurrRcb;
 	struct bcm_mini_adapter *psAdapter;
-	BOOLEAN                 bFlashBoot;
-	BOOLEAN 		bHighSpeedDevice ;
-
-	BOOLEAN 		bSuspended;
-	BOOLEAN 		bPreparingForBusSuspend;
+	bool		bFlashBoot;
+	bool		bHighSpeedDevice;
+	bool		bSuspended;
+	bool		bPreparingForBusSuspend;
 	struct work_struct usbSuspendWork;
-}S_INTERFACE_ADAPTER,*PS_INTERFACE_ADAPTER;
+};
 
 #endif
diff --git a/drivers/staging/bcm/InterfaceDld.c b/drivers/staging/bcm/InterfaceDld.c
index 3a89e33..87117a7 100644
--- a/drivers/staging/bcm/InterfaceDld.c
+++ b/drivers/staging/bcm/InterfaceDld.c
@@ -6,7 +6,7 @@ int InterfaceFileDownload(PVOID arg, struct file *flp, unsigned int on_chip_loc)
 	mm_segment_t oldfs = {0};
 	int errno = 0, len = 0; /* ,is_config_file = 0 */
 	loff_t pos = 0;
-	PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg;
+	struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)arg;
 	/* struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter; */
 	char *buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
 
@@ -61,7 +61,7 @@ int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp, unsigned int on_c
 	loff_t pos = 0;
 	static int fw_down;
 	INT Status = STATUS_SUCCESS;
-	PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg;
+	struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)arg;
 	int bytes;
 
 	buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA);
diff --git a/drivers/staging/bcm/InterfaceIdleMode.c b/drivers/staging/bcm/InterfaceIdleMode.c
index 4f2f490..a1bf215 100644
--- a/drivers/staging/bcm/InterfaceIdleMode.c
+++ b/drivers/staging/bcm/InterfaceIdleMode.c
@@ -156,7 +156,7 @@ static int InterfaceAbortIdlemode(struct bcm_mini_adapter *Adapter, unsigned int
 
 	int 	lenwritten = 0;
 	unsigned char aucAbortPattern[8]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
-	PS_INTERFACE_ADAPTER psInterfaceAdapter = Adapter->pvInterfaceAdapter;
+	struct bcm_interface_adapter *psInterfaceAdapter = Adapter->pvInterfaceAdapter;
 
 	//Abort Bus suspend if its already suspended
 	if((TRUE == psInterfaceAdapter->bSuspended) && (TRUE == Adapter->bDoSuspend))
diff --git a/drivers/staging/bcm/InterfaceIdleMode.h b/drivers/staging/bcm/InterfaceIdleMode.h
index c3338c8..2ef6400 100644
--- a/drivers/staging/bcm/InterfaceIdleMode.h
+++ b/drivers/staging/bcm/InterfaceIdleMode.h
@@ -3,11 +3,12 @@
 
 INT InterfaceIdleModeWakeup(struct bcm_mini_adapter *Adapter);
 
-INT InterfaceIdleModeRespond(struct bcm_mini_adapter *Adapter, unsigned int *puiBuffer);
+INT InterfaceIdleModeRespond(struct bcm_mini_adapter *Adapter,
+				unsigned int *puiBuffer);
 
 VOID InterfaceWriteIdleModeWakePattern(struct bcm_mini_adapter *Adapter);
 
-INT InterfaceWakeUp(struct bcm_mini_adapter * Adapter);
+INT InterfaceWakeUp(struct bcm_mini_adapter *Adapter);
 
 VOID InterfaceHandleShutdownModeWakeup(struct bcm_mini_adapter *Adapter);
 #endif
diff --git a/drivers/staging/bcm/InterfaceInit.c b/drivers/staging/bcm/InterfaceInit.c
index b05f5f7..eb24643 100644
--- a/drivers/staging/bcm/InterfaceInit.c
+++ b/drivers/staging/bcm/InterfaceInit.c
@@ -4,11 +4,12 @@ static struct usb_device_id InterfaceUsbtable[] = {
 	{ USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3) },
 	{ USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3B) },
 	{ USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3L) },
-	{ USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_SM250) },
+	{ USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_SYM) },
 	{ USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_226) },
 	{ USB_DEVICE(BCM_USB_VENDOR_ID_FOXCONN, BCM_USB_PRODUCT_ID_1901) },
 	{ USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_ZTE_TU25) },
 	{ USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_ZTE_226) },
+	{ USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_ZTE_326) },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, InterfaceUsbtable);
@@ -22,9 +23,9 @@ static const u32 default_msg =
 	| NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR
 	| NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;
 
-static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER Adapter);
+static int InterfaceAdapterInit(struct bcm_interface_adapter *Adapter);
 
-static void InterfaceAdapterFree(PS_INTERFACE_ADAPTER psIntfAdapter)
+static void InterfaceAdapterFree(struct bcm_interface_adapter *psIntfAdapter)
 {
 	int i = 0;
 
@@ -79,7 +80,7 @@ static void ConfigureEndPointTypesThroughEEPROM(struct bcm_mini_adapter *Adapter
 
 	ulReg = ntohl(EP2_CFG_REG);
 	BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x132, 4, TRUE);
-	if (((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter))->bHighSpeedDevice == TRUE) {
+	if (((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter))->bHighSpeedDevice == TRUE) {
 		ulReg = ntohl(EP2_CFG_INT);
 		BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x136, 4, TRUE);
 	} else {
@@ -145,7 +146,7 @@ static int usbbcm_device_probe(struct usb_interface *intf, const struct usb_devi
 	struct usb_device *udev = interface_to_usbdev(intf);
 	int retval;
 	struct bcm_mini_adapter *psAdapter;
-	PS_INTERFACE_ADAPTER psIntfAdapter;
+	struct bcm_interface_adapter *psIntfAdapter;
 	struct net_device *ndev;
 
 	/* Reserve one extra queue for the bit-bucket */
@@ -189,7 +190,7 @@ static int usbbcm_device_probe(struct usb_interface *intf, const struct usb_devi
 	}
 
 	/* Allocate interface adapter structure */
-	psIntfAdapter = kzalloc(sizeof(S_INTERFACE_ADAPTER), GFP_KERNEL);
+	psIntfAdapter = kzalloc(sizeof(struct bcm_interface_adapter), GFP_KERNEL);
 	if (psIntfAdapter == NULL) {
 		dev_err(&udev->dev, DRV_NAME ": no memory for Interface adapter\n");
 		AdapterFree(psAdapter);
@@ -257,7 +258,7 @@ static int usbbcm_device_probe(struct usb_interface *intf, const struct usb_devi
 
 static void usbbcm_disconnect(struct usb_interface *intf)
 {
-	PS_INTERFACE_ADAPTER psIntfAdapter = usb_get_intfdata(intf);
+	struct bcm_interface_adapter *psIntfAdapter = usb_get_intfdata(intf);
 	struct bcm_mini_adapter *psAdapter;
 	struct usb_device  *udev = interface_to_usbdev(intf);
 
@@ -276,7 +277,7 @@ static void usbbcm_disconnect(struct usb_interface *intf)
 	usb_put_dev(udev);
 }
 
-static int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter)
+static int AllocUsbCb(struct bcm_interface_adapter *psIntfAdapter)
 {
 	int i = 0;
 
@@ -311,7 +312,7 @@ static int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter)
 	return 0;
 }
 
-static int device_run(PS_INTERFACE_ADAPTER psIntfAdapter)
+static int device_run(struct bcm_interface_adapter *psIntfAdapter)
 {
 	int value = 0;
 	UINT status = STATUS_SUCCESS;
@@ -421,7 +422,7 @@ static inline int bcm_usb_endpoint_is_isoc_out(const struct usb_endpoint_descrip
 	return bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd);
 }
 
-static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
+static int InterfaceAdapterInit(struct bcm_interface_adapter *psIntfAdapter)
 {
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
@@ -619,7 +620,7 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
 
 static int InterfaceSuspend(struct usb_interface *intf, pm_message_t message)
 {
-	PS_INTERFACE_ADAPTER  psIntfAdapter = usb_get_intfdata(intf);
+	struct bcm_interface_adapter *psIntfAdapter = usb_get_intfdata(intf);
 
 	psIntfAdapter->bSuspended = TRUE;
 
@@ -646,7 +647,7 @@ static int InterfaceSuspend(struct usb_interface *intf, pm_message_t message)
 
 static int InterfaceResume(struct usb_interface *intf)
 {
-	PS_INTERFACE_ADAPTER  psIntfAdapter = usb_get_intfdata(intf);
+	struct bcm_interface_adapter *psIntfAdapter = usb_get_intfdata(intf);
 
 	mdelay(100);
 	psIntfAdapter->bSuspended = FALSE;
diff --git a/drivers/staging/bcm/InterfaceInit.h b/drivers/staging/bcm/InterfaceInit.h
index 866924e..ffa6e96 100644
--- a/drivers/staging/bcm/InterfaceInit.h
+++ b/drivers/staging/bcm/InterfaceInit.h
@@ -8,11 +8,11 @@
 #define BCM_USB_PRODUCT_ID_T3	0x0300
 #define BCM_USB_PRODUCT_ID_T3B	0x0210
 #define BCM_USB_PRODUCT_ID_T3L	0x0220
-#define BCM_USB_PRODUCT_ID_SM250	0xbccd
 #define BCM_USB_PRODUCT_ID_SYM	0x15E
 #define BCM_USB_PRODUCT_ID_1901	0xe017
 #define BCM_USB_PRODUCT_ID_226	0x0132 /* not sure if this is valid */
 #define BCM_USB_PRODUCT_ID_ZTE_226 0x172
+#define BCM_USB_PRODUCT_ID_ZTE_326 0x173 /* ZTE AX326 */
 #define BCM_USB_PRODUCT_ID_ZTE_TU25	0x0007
 
 #define BCM_USB_MINOR_BASE	192
@@ -21,6 +21,6 @@ int InterfaceInitialize(void);
 
 int InterfaceExit(void);
 
-int usbbcm_worker_thread(PS_INTERFACE_ADAPTER psIntfAdapter);
+int usbbcm_worker_thread(struct bcm_interface_adapter *psIntfAdapter);
 
 #endif
diff --git a/drivers/staging/bcm/InterfaceIsr.c b/drivers/staging/bcm/InterfaceIsr.c
index 6ee3428..8322f1b 100644
--- a/drivers/staging/bcm/InterfaceIsr.c
+++ b/drivers/staging/bcm/InterfaceIsr.c
@@ -4,7 +4,7 @@
 static void read_int_callback(struct urb *urb/*, struct pt_regs *regs*/)
 {
 	int		status = urb->status;
-	PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)urb->context;
+	struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)urb->context;
 	struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter ;
 
 	if (netif_msg_intr(Adapter))
@@ -114,7 +114,7 @@ static void read_int_callback(struct urb *urb/*, struct pt_regs *regs*/)
 
 }
 
-int CreateInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter)
+int CreateInterruptUrb(struct bcm_interface_adapter *psIntfAdapter)
 {
 	psIntfAdapter->psInterruptUrb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!psIntfAdapter->psInterruptUrb)
@@ -143,7 +143,7 @@ int CreateInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter)
 }
 
 
-INT StartInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter)
+INT StartInterruptUrb(struct bcm_interface_adapter *psIntfAdapter)
 {
 	INT status = 0;
 
diff --git a/drivers/staging/bcm/InterfaceIsr.h b/drivers/staging/bcm/InterfaceIsr.h
index 4039978..3073bd7 100644
--- a/drivers/staging/bcm/InterfaceIsr.h
+++ b/drivers/staging/bcm/InterfaceIsr.h
@@ -1,10 +1,10 @@
 #ifndef _INTERFACE_ISR_H
 #define _INTERFACE_ISR_H
 
-int CreateInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter);
+int CreateInterruptUrb(struct bcm_interface_adapter *psIntfAdapter);
 
 
-INT StartInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter);
+INT StartInterruptUrb(struct bcm_interface_adapter *psIntfAdapter);
 
 
 VOID InterfaceEnableInterrupt(struct bcm_mini_adapter *Adapter);
diff --git a/drivers/staging/bcm/InterfaceMisc.c b/drivers/staging/bcm/InterfaceMisc.c
index bbe9099..afca010 100644
--- a/drivers/staging/bcm/InterfaceMisc.c
+++ b/drivers/staging/bcm/InterfaceMisc.c
@@ -1,17 +1,14 @@
 #include "headers.h"
 
-INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
-		UINT addr,
-		PVOID buff,
-		INT len)
+int InterfaceRDM(struct bcm_interface_adapter *psIntfAdapter,
+		unsigned int addr,
+		void *buff,
+		int len)
 {
 	int bytes;
-	USHORT usRetries = 0;
 
-	if (psIntfAdapter == NULL) {
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL");
+	if (!psIntfAdapter)
 		return -EINVAL;
-	}
 
 	if (psIntfAdapter->psAdapter->device_removed == TRUE) {
 		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
@@ -29,27 +26,21 @@ INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
 	}
 	psIntfAdapter->psAdapter->DeviceAccess = TRUE;
 
-	do {
-		bytes = usb_control_msg(psIntfAdapter->udev,
-					usb_rcvctrlpipe(psIntfAdapter->udev, 0),
-					0x02,
-					0xC2,
-					(addr & 0xFFFF),
-					((addr >> 16) & 0xFFFF),
-					buff,
-					len,
-					5000);
-
-		usRetries++;
-		if (-ENODEV == bytes) {
-			psIntfAdapter->psAdapter->device_removed = TRUE;
-			break;
-		}
+	bytes = usb_control_msg(psIntfAdapter->udev,
+				usb_rcvctrlpipe(psIntfAdapter->udev, 0),
+				0x02,
+				0xC2,
+				(addr & 0xFFFF),
+				((addr >> 16) & 0xFFFF),
+				buff,
+				len,
+				5000);
 
-	} while ((bytes < 0) && (usRetries < MAX_RDM_WRM_RETIRES));
+	if (-ENODEV == bytes)
+		psIntfAdapter->psAdapter->device_removed = TRUE;
 
 	if (bytes < 0)
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", bytes, usRetries);
+		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d", bytes);
 	else
 		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", bytes);
 
@@ -57,18 +48,15 @@ INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
 	return bytes;
 }
 
-INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
-		UINT addr,
-		PVOID buff,
-		INT len)
+int InterfaceWRM(struct bcm_interface_adapter *psIntfAdapter,
+		unsigned int addr,
+		void *buff,
+		int len)
 {
 	int retval = 0;
-	USHORT usRetries = 0;
 
-	if (psIntfAdapter == NULL) {
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter  is NULL");
+	if (!psIntfAdapter)
 		return -EINVAL;
-	}
 
 	if (psIntfAdapter->psAdapter->device_removed == TRUE) {
 		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
@@ -87,27 +75,21 @@ INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
 
 	psIntfAdapter->psAdapter->DeviceAccess = TRUE;
 
-	do {
-		retval = usb_control_msg(psIntfAdapter->udev,
-					usb_sndctrlpipe(psIntfAdapter->udev, 0),
-					0x01,
-					0x42,
-					(addr & 0xFFFF),
-					((addr >> 16) & 0xFFFF),
-					buff,
-					len,
-					5000);
-
-		usRetries++;
-		if (-ENODEV == retval) {
-			psIntfAdapter->psAdapter->device_removed = TRUE;
-			break;
-		}
+	retval = usb_control_msg(psIntfAdapter->udev,
+				usb_sndctrlpipe(psIntfAdapter->udev, 0),
+				0x01,
+				0x42,
+				(addr & 0xFFFF),
+				((addr >> 16) & 0xFFFF),
+				buff,
+				len,
+				5000);
 
-	} while ((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES));
+	if (-ENODEV == retval)
+		psIntfAdapter->psAdapter->device_removed = TRUE;
 
 	if (retval < 0)	{
-		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d, retires :%d", retval, usRetries);
+		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d", retval);
 		psIntfAdapter->psAdapter->DeviceAccess = FALSE;
 		return retval;
 	} else {
@@ -117,26 +99,26 @@ INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
 	}
 }
 
-INT BcmRDM(PVOID arg,
-	UINT addr,
-	PVOID buff,
-	INT len)
+int BcmRDM(void *arg,
+	unsigned int addr,
+	void *buff,
+	int len)
 {
-	return InterfaceRDM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
+	return InterfaceRDM((struct bcm_interface_adapter*)arg, addr, buff, len);
 }
 
-INT BcmWRM(PVOID arg,
-	UINT addr,
-	PVOID buff,
-	INT len)
+int BcmWRM(void *arg,
+	unsigned int addr,
+	void *buff,
+	int len)
 {
-	return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
+	return InterfaceWRM((struct bcm_interface_adapter *)arg, addr, buff, len);
 }
 
-INT Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter)
+int Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter)
 {
-	PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter);
-	INT status = STATUS_SUCCESS;
+	struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter);
+	int status = STATUS_SUCCESS;
 
 	/*
 	 * usb_clear_halt - tells device to clear endpoint halt/stall condition
@@ -172,10 +154,10 @@ INT Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter)
 	return status;
 }
 
-VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
+void Bcm_kill_all_URBs(struct bcm_interface_adapter *psIntfAdapter)
 {
 	struct urb *tempUrb = NULL;
-	UINT i;
+	unsigned int i;
 
 	/*
 	 * usb_kill_urb - cancel a transfer request and wait for it to finish
@@ -193,7 +175,7 @@ VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
 	 */
 
 	/* Cancel submitted Interrupt-URB's */
-	if (psIntfAdapter->psInterruptUrb != NULL) {
+	if (psIntfAdapter->psInterruptUrb) {
 		if (psIntfAdapter->psInterruptUrb->status == -EINPROGRESS)
 			usb_kill_urb(psIntfAdapter->psInterruptUrb);
 	}
@@ -222,11 +204,11 @@ VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
 	atomic_set(&psIntfAdapter->uCurrRcb, 0);
 }
 
-VOID putUsbSuspend(struct work_struct *work)
+void putUsbSuspend(struct work_struct *work)
 {
-	PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
+	struct bcm_interface_adapter *psIntfAdapter = NULL;
 	struct usb_interface *intf = NULL;
-	psIntfAdapter = container_of(work, S_INTERFACE_ADAPTER, usbSuspendWork);
+	psIntfAdapter = container_of(work, struct bcm_interface_adapter, usbSuspendWork);
 	intf = psIntfAdapter->interface;
 
 	if (psIntfAdapter->bSuspended == FALSE)
diff --git a/drivers/staging/bcm/InterfaceMisc.h b/drivers/staging/bcm/InterfaceMisc.h
index 1dfabdc..bce6869 100644
--- a/drivers/staging/bcm/InterfaceMisc.h
+++ b/drivers/staging/bcm/InterfaceMisc.h
@@ -2,13 +2,13 @@
 #define __INTERFACE_MISC_H
 
 INT
-InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
+InterfaceRDM(struct bcm_interface_adapter *psIntfAdapter,
 			UINT addr,
 			PVOID buff,
 			INT len);
 
 INT
-InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
+InterfaceWRM(struct bcm_interface_adapter *psIntfAdapter,
 			UINT addr,
 			PVOID buff,
 			INT len);
@@ -35,7 +35,7 @@ int BcmWRM(PVOID arg,
 
 INT Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter);
 
-VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter);
+VOID Bcm_kill_all_URBs(struct bcm_interface_adapter *psIntfAdapter);
 
 #define DISABLE_USB_ZERO_LEN_INT 0x0F011878
 
diff --git a/drivers/staging/bcm/InterfaceRx.c b/drivers/staging/bcm/InterfaceRx.c
index 8a9f90f..26f5bc7 100644
--- a/drivers/staging/bcm/InterfaceRx.c
+++ b/drivers/staging/bcm/InterfaceRx.c
@@ -12,10 +12,10 @@ static int SearchVcid(struct bcm_mini_adapter *Adapter,unsigned short usVcid)
 }
 
 
-static PUSB_RCB
-GetBulkInRcb(PS_INTERFACE_ADAPTER psIntfAdapter)
+static struct bcm_usb_rcb *
+GetBulkInRcb(struct bcm_interface_adapter *psIntfAdapter)
 {
-	PUSB_RCB pRcb = NULL;
+	struct bcm_usb_rcb *pRcb = NULL;
 	UINT index = 0;
 
 	if((atomic_read(&psIntfAdapter->uNumRcbUsed) < MAXIMUM_USB_RCB) &&
@@ -43,8 +43,8 @@ static void read_bulk_callback(struct urb *urb)
 	UINT uiIndex=0;
 	int process_done = 1;
 	//int idleflag = 0 ;
-	PUSB_RCB pRcb = (PUSB_RCB)urb->context;
-	PS_INTERFACE_ADAPTER psIntfAdapter = pRcb->psIntfAdapter;
+	struct bcm_usb_rcb *pRcb = (struct bcm_usb_rcb *)urb->context;
+	struct bcm_interface_adapter *psIntfAdapter = pRcb->psIntfAdapter;
 	struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter;
 	struct bcm_leader *pLeader = urb->transfer_buffer;
 
@@ -196,7 +196,7 @@ static void read_bulk_callback(struct urb *urb)
 	atomic_dec(&psIntfAdapter->uNumRcbUsed);
 }
 
-static int ReceiveRcb(PS_INTERFACE_ADAPTER psIntfAdapter, PUSB_RCB pRcb)
+static int ReceiveRcb(struct bcm_interface_adapter *psIntfAdapter, struct bcm_usb_rcb *pRcb)
 {
 	struct urb *urb = pRcb->urb;
 	int retval = 0;
@@ -240,10 +240,10 @@ Return:				TRUE  - If Rx was successful.
 					Other - If an error occurred.
 */
 
-BOOLEAN InterfaceRx (PS_INTERFACE_ADAPTER psIntfAdapter)
+BOOLEAN InterfaceRx (struct bcm_interface_adapter *psIntfAdapter)
 {
 	USHORT RxDescCount = NUM_RX_DESC - atomic_read(&psIntfAdapter->uNumRcbUsed);
-	PUSB_RCB pRcb = NULL;
+	struct bcm_usb_rcb *pRcb = NULL;
 
 //	RxDescCount = psIntfAdapter->psAdapter->CurrNumRecvDescs -
 //				psIntfAdapter->psAdapter->PrevNumRecvDescs;
diff --git a/drivers/staging/bcm/InterfaceRx.h b/drivers/staging/bcm/InterfaceRx.h
index 96e81a1..424645e 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(PS_INTERFACE_ADAPTER Adapter);
+BOOLEAN InterfaceRx(struct bcm_interface_adapter *Adapter);
 
 #endif
 
diff --git a/drivers/staging/bcm/InterfaceTx.c b/drivers/staging/bcm/InterfaceTx.c
index 7e2b53b..b8c7855 100644
--- a/drivers/staging/bcm/InterfaceTx.c
+++ b/drivers/staging/bcm/InterfaceTx.c
@@ -3,8 +3,8 @@
 /*this is transmit call-back(BULK OUT)*/
 static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/)
 {
-	PUSB_TCB pTcb= (PUSB_TCB)urb->context;
-	PS_INTERFACE_ADAPTER psIntfAdapter = pTcb->psIntfAdapter;
+	struct bcm_usb_tcb *pTcb= (struct bcm_usb_tcb *)urb->context;
+	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 ;
@@ -107,9 +107,9 @@ err_exit :
 }
 
 
-static PUSB_TCB GetBulkOutTcb(PS_INTERFACE_ADAPTER psIntfAdapter)
+static struct bcm_usb_tcb *GetBulkOutTcb(struct bcm_interface_adapter *psIntfAdapter)
 {
-	PUSB_TCB pTcb = NULL;
+	struct bcm_usb_tcb *pTcb = NULL;
 	UINT index = 0;
 
 	if((atomic_read(&psIntfAdapter->uNumTcbUsed) < MAXIMUM_USB_TCB) &&
@@ -128,7 +128,7 @@ static PUSB_TCB GetBulkOutTcb(PS_INTERFACE_ADAPTER psIntfAdapter)
 	return pTcb;
 }
 
-static int TransmitTcb(PS_INTERFACE_ADAPTER psIntfAdapter, PUSB_TCB pTcb, PVOID data, int len)
+static int TransmitTcb(struct bcm_interface_adapter *psIntfAdapter, struct bcm_usb_tcb *pTcb, PVOID data, int len)
 {
 
 	struct urb *urb = pTcb->urb;
@@ -182,9 +182,9 @@ static int TransmitTcb(PS_INTERFACE_ADAPTER psIntfAdapter, PUSB_TCB pTcb, PVOID
 
 int InterfaceTransmitPacket(PVOID arg, PVOID data, UINT len)
 {
-	PUSB_TCB pTcb= NULL;
+	struct bcm_usb_tcb *pTcb= NULL;
 
-	PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg;
+	struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)arg;
 	pTcb= GetBulkOutTcb(psIntfAdapter);
 	if(pTcb == NULL)
 	{
diff --git a/drivers/staging/bcm/Ioctl.h b/drivers/staging/bcm/Ioctl.h
index f859cf1..8c70af9 100644
--- a/drivers/staging/bcm/Ioctl.h
+++ b/drivers/staging/bcm/Ioctl.h
@@ -1,247 +1,136 @@
 #ifndef _IOCTL_H_
 #define _IOCTL_H_
 
-typedef struct rdmbuffer
-{
-	ULONG	Register;
-	ULONG	Length;
-}__attribute__((packed)) RDM_BUFFER, *PRDM_BUFFER;
-
-
-typedef struct wrmbuffer
-{
-	ULONG	Register;
-	ULONG	Length;
-	UCHAR	Data[4];
-}__attribute__((packed)) WRM_BUFFER, *PWRM_BUFFER;
-
-
-typedef struct ioctlbuffer
-{
+struct bcm_rdm_buffer {
+	unsigned long Register;
+	unsigned long Length;
+} __packed;
+
+struct bcm_wrm_buffer {
+	unsigned long Register;
+	unsigned long Length;
+	unsigned char Data[4];
+} __packed;
+
+struct bcm_ioctl_buffer {
 	void __user *InputBuffer;
-	ULONG	InputLength;
+	unsigned long InputLength;
 	void __user *OutputBuffer;
-	ULONG	OutputLength;
-}__attribute__((packed)) IOCTL_BUFFER, *PIOCTL_BUFFER;
-
-typedef struct stGPIOInfo
-{
-	UINT  uiGpioNumber ; /* valid numbers 0-15 */
-	UINT uiGpioValue; /* 1 set ; 0 not  set */
-}__attribute__((packed))GPIO_INFO,*PGPIO_INFO;
-typedef struct stUserThreadReq
-{
-	//0->Inactivate LED thread.
-	//1->Activate the LED thread
-	UINT ThreadState;
-}__attribute__((packed))USER_THREAD_REQ,*PUSER_THREAD_REQ;
-#define LED_THREAD_ACTIVATION_REQ  1
-
-
-////********** ioctl codes ***********////
-
-#define BCM_IOCTL 				'k'
-
-//1.Control code for CONTROL MESSAGES
-
-#define IOCTL_SEND_CONTROL_MESSAGE 			_IOW(BCM_IOCTL,	0x801,int)
-
-//2.Control code to write a particular value to a particular register
-#define IOCTL_BCM_REGISTER_WRITE            _IOW(BCM_IOCTL, 0x802, int) //
-
-//3.
-#define IOCTL_BCM_REGISTER_READ             _IOR(BCM_IOCTL, 0x803, int) //
+	unsigned long OutputLength;
+} __packed;
 
-//4.Control code to write x number of bytes to common memory
-//starting from address y
-#define IOCTL_BCM_COMMON_MEMORY_WRITE  	    _IOW(BCM_IOCTL, 0x804, int)//
+struct bcm_gpio_info {
+	unsigned int uiGpioNumber; /* valid numbers 0-15 */
+	unsigned int uiGpioValue; /* 1 set ; 0 not  set */
+} __packed;
 
-//5.Control code to write x number of bytes to common memory
-//starting from address y
-#define IOCTL_BCM_COMMON_MEMORY_READ 	    _IOR(BCM_IOCTL, 0x805, int)//
-
-//6.Control code for CONTROL MESSAGES
-#define IOCTL_GET_CONTROL_MESSAGE 			_IOR(BCM_IOCTL,	0x806, int)//
-
-//7.Control code for FIRMWARE DOWNLOAD
-#define IOCTL_BCM_FIRMWARE_DOWNLOAD 		_IOW(BCM_IOCTL, 0x807, int)//
-
-#define IOCTL_BCM_SET_SEND_VCID 	        _IOW(BCM_IOCTL,	0x808, int)
-
-//9.Control code for TRANSFER MODE SWITCHING
-#define IOCTL_BCM_SWITCH_TRANSFER_MODE 		_IOW(BCM_IOCTL, 0x809, int)
-//10.Control code for LINK UP
-#define IOCTL_LINK_REQ 						_IOW(BCM_IOCTL, 0x80A, int)
-
-//11.Control code for RSSI Level Request
-#define IOCTL_RSSI_LEVEL_REQ				_IOW(BCM_IOCTL, 0x80B, int)
-//12.Control code for IDLE MODE CONTROL
-#define IOCTL_IDLE_REQ						_IOW(BCM_IOCTL, 0x80C, int)
-//13.Control code for SS/BS info
-#define IOCTL_SS_INFO_REQ					_IOW(BCM_IOCTL, 0x80D, int)
+struct bcm_user_thread_req {
+	/* 0->Inactivate LED thread. */
+	/* 1->Activate the LED thread */
+	unsigned int ThreadState;
+} __packed;
 
+#define LED_THREAD_ACTIVATION_REQ  1
+#define BCM_IOCTL				'k'
+#define IOCTL_SEND_CONTROL_MESSAGE		_IOW(BCM_IOCTL,	0x801, int)
+#define IOCTL_BCM_REGISTER_WRITE		_IOW(BCM_IOCTL, 0x802, int)
+#define IOCTL_BCM_REGISTER_READ			_IOR(BCM_IOCTL, 0x803, int)
+#define IOCTL_BCM_COMMON_MEMORY_WRITE		_IOW(BCM_IOCTL, 0x804, int)
+#define IOCTL_BCM_COMMON_MEMORY_READ		_IOR(BCM_IOCTL, 0x805, int)
+#define IOCTL_GET_CONTROL_MESSAGE		_IOR(BCM_IOCTL,	0x806, int)
+#define IOCTL_BCM_FIRMWARE_DOWNLOAD		_IOW(BCM_IOCTL, 0x807, int)
+#define IOCTL_BCM_SET_SEND_VCID			_IOW(BCM_IOCTL,	0x808, int)
+#define IOCTL_BCM_SWITCH_TRANSFER_MODE		_IOW(BCM_IOCTL, 0x809, int)
+#define IOCTL_LINK_REQ				_IOW(BCM_IOCTL, 0x80A, int)
+#define IOCTL_RSSI_LEVEL_REQ			_IOW(BCM_IOCTL, 0x80B, int)
+#define IOCTL_IDLE_REQ				_IOW(BCM_IOCTL, 0x80C, int)
+#define IOCTL_SS_INFO_REQ			_IOW(BCM_IOCTL, 0x80D, int)
 #define IOCTL_GET_STATISTICS_POINTER		_IOW(BCM_IOCTL, 0x80E, int)
-
-#define IOCTL_CM_REQUEST    				_IOW(BCM_IOCTL, 0x80F, int)
-
-#define IOCTL_INIT_PARAM_REQ 				_IOW(BCM_IOCTL, 0x810, int)
-
-#define IOCTL_MAC_ADDR_REQ				_IOW(BCM_IOCTL, 0x811, int)
-
-#define IOCTL_MAC_ADDR_RESP				_IOWR(BCM_IOCTL, 0x812, int)
-
-#define IOCTL_CLASSIFICATION_RULE	  	_IOW(BCM_IOCTL, 0x813, char)
-
+#define IOCTL_CM_REQUEST			_IOW(BCM_IOCTL, 0x80F, int)
+#define IOCTL_INIT_PARAM_REQ			_IOW(BCM_IOCTL, 0x810, int)
+#define IOCTL_MAC_ADDR_REQ			_IOW(BCM_IOCTL, 0x811, int)
+#define IOCTL_MAC_ADDR_RESP			_IOWR(BCM_IOCTL, 0x812, int)
+#define IOCTL_CLASSIFICATION_RULE		_IOW(BCM_IOCTL, 0x813, char)
 #define IOCTL_CLOSE_NOTIFICATION		_IO(BCM_IOCTL, 0x814)
-
-#define IOCTL_LINK_UP					_IO(BCM_IOCTL, 0x815)
-
-#define IOCTL_LINK_DOWN					_IO(BCM_IOCTL, 0x816, IOCTL_BUFFER)
-
-#define IOCTL_CHIP_RESET                _IO(BCM_IOCTL, 0x816)
-
+#define IOCTL_LINK_UP				_IO(BCM_IOCTL, 0x815)
+#define IOCTL_LINK_DOWN				_IO(BCM_IOCTL, 0x816, struct bcm_ioctl_buffer)
+#define IOCTL_CHIP_RESET			_IO(BCM_IOCTL, 0x816)
 #define IOCTL_CINR_LEVEL_REQ			_IOW(BCM_IOCTL, 0x817, char)
-
-#define IOCTL_WTM_CONTROL_REQ			_IOW(BCM_IOCTL, 0x817,char)
-
+#define IOCTL_WTM_CONTROL_REQ			_IOW(BCM_IOCTL, 0x817, char)
 #define IOCTL_BE_BUCKET_SIZE			_IOW(BCM_IOCTL, 0x818, unsigned long)
-
 #define IOCTL_RTPS_BUCKET_SIZE			_IOW(BCM_IOCTL, 0x819, unsigned long)
-
-#define IOCTL_QOS_THRESHOLD				_IOW(BCM_IOCTL, 0x820, unsigned long)
-
-#define IOCTL_DUMP_PACKET_INFO				_IO(BCM_IOCTL, 0x821)
-
-#define IOCTL_GET_PACK_INFO					_IOR(BCM_IOCTL, 0x823, int)
-
+#define IOCTL_QOS_THRESHOLD			_IOW(BCM_IOCTL, 0x820, unsigned long)
+#define IOCTL_DUMP_PACKET_INFO			_IO(BCM_IOCTL, 0x821)
+#define IOCTL_GET_PACK_INFO			_IOR(BCM_IOCTL, 0x823, int)
 #define IOCTL_BCM_GET_DRIVER_VERSION		_IOR(BCM_IOCTL, 0x829, int)
-
-#define IOCTL_BCM_GET_CURRENT_STATUS 		_IOW(BCM_IOCTL, 0x828, int)
-
-#define IOCTL_BCM_GPIO_SET_REQUEST	  		_IOW(BCM_IOCTL, 0x82A, int)
-
-#define IOCTL_BCM_GPIO_STATUS_REQUEST 		_IOW(BCM_IOCTL, 0x82b, int)
-
-#define IOCTL_BCM_GET_DSX_INDICATION 		_IOR(BCM_IOCTL, 0x854, int)
-
-#define IOCTL_BCM_BUFFER_DOWNLOAD_START 	_IOW(BCM_IOCTL, 0x855, int)
-
-#define IOCTL_BCM_BUFFER_DOWNLOAD 			_IOW(BCM_IOCTL, 0x856, int)
-
-#define IOCTL_BCM_BUFFER_DOWNLOAD_STOP 		_IOW(BCM_IOCTL, 0x857, int)
-
-#define IOCTL_BCM_REGISTER_WRITE_PRIVATE 	_IOW(BCM_IOCTL, 0x826, char)
-
+#define IOCTL_BCM_GET_CURRENT_STATUS		_IOW(BCM_IOCTL, 0x828, int)
+#define IOCTL_BCM_GPIO_SET_REQUEST		_IOW(BCM_IOCTL, 0x82A, int)
+#define IOCTL_BCM_GPIO_STATUS_REQUEST		_IOW(BCM_IOCTL, 0x82b, int)
+#define IOCTL_BCM_GET_DSX_INDICATION		_IOR(BCM_IOCTL, 0x854, int)
+#define IOCTL_BCM_BUFFER_DOWNLOAD_START		_IOW(BCM_IOCTL, 0x855, int)
+#define IOCTL_BCM_BUFFER_DOWNLOAD		_IOW(BCM_IOCTL, 0x856, int)
+#define IOCTL_BCM_BUFFER_DOWNLOAD_STOP		_IOW(BCM_IOCTL, 0x857, int)
+#define IOCTL_BCM_REGISTER_WRITE_PRIVATE	_IOW(BCM_IOCTL, 0x826, char)
 #define IOCTL_BCM_REGISTER_READ_PRIVATE		_IOW(BCM_IOCTL, 0x827, char)
-
-#define IOCTL_BCM_SET_DEBUG                 _IOW(BCM_IOCTL, 0x824, IOCTL_BUFFER)
-
-#define IOCTL_BCM_EEPROM_REGISTER_WRITE  	_IOW(BCM_IOCTL, 0x858, int)
-
-#define IOCTL_BCM_EEPROM_REGISTER_READ     	_IOR(BCM_IOCTL, 0x859, int)
-
+#define IOCTL_BCM_SET_DEBUG			_IOW(BCM_IOCTL, 0x824, struct bcm_ioctl_buffer)
+#define IOCTL_BCM_EEPROM_REGISTER_WRITE		_IOW(BCM_IOCTL, 0x858, int)
+#define IOCTL_BCM_EEPROM_REGISTER_READ		_IOR(BCM_IOCTL, 0x859, int)
 #define IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE	_IOR(BCM_IOCTL, 0x860, int)
-
-#define IOCTL_BCM_SET_MAC_TRACING     		_IOW(BCM_IOCTL, 0x82c, int)
-
-#define IOCTL_BCM_GET_HOST_MIBS 		  	_IOW(BCM_IOCTL, 0x853, int)
-
-#define IOCTL_BCM_NVM_READ 					_IOR(BCM_IOCTL, 0x861, int)
-
-#define IOCTL_BCM_NVM_WRITE					_IOW(BCM_IOCTL, 0x862, int)
-
-#define IOCTL_BCM_GET_NVM_SIZE				_IOR(BCM_IOCTL, 0x863, int)
-
-#define IOCTL_BCM_CAL_INIT					_IOR(BCM_IOCTL, 0x864, int)
-
-#define IOCTL_BCM_BULK_WRM 					_IOW(BCM_IOCTL, 0x90B, int)
-
-#define IOCTL_BCM_FLASH2X_SECTION_READ 		_IOR(BCM_IOCTL, 0x865, int)
-
+#define IOCTL_BCM_SET_MAC_TRACING		_IOW(BCM_IOCTL, 0x82c, int)
+#define IOCTL_BCM_GET_HOST_MIBS			_IOW(BCM_IOCTL, 0x853, int)
+#define IOCTL_BCM_NVM_READ			_IOR(BCM_IOCTL, 0x861, int)
+#define IOCTL_BCM_NVM_WRITE			_IOW(BCM_IOCTL, 0x862, int)
+#define IOCTL_BCM_GET_NVM_SIZE			_IOR(BCM_IOCTL, 0x863, int)
+#define IOCTL_BCM_CAL_INIT			_IOR(BCM_IOCTL, 0x864, int)
+#define IOCTL_BCM_BULK_WRM			_IOW(BCM_IOCTL, 0x90B, int)
+#define IOCTL_BCM_FLASH2X_SECTION_READ		_IOR(BCM_IOCTL, 0x865, int)
 #define IOCTL_BCM_FLASH2X_SECTION_WRITE		_IOW(BCM_IOCTL, 0x866, int)
+#define IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP	_IOR(BCM_IOCTL, 0x867, int)
+#define IOCTL_BCM_SET_ACTIVE_SECTION		_IOW(BCM_IOCTL, 0x868, int)
+#define	IOCTL_BCM_IDENTIFY_ACTIVE_SECTION	_IO(BCM_IOCTL, 0x869)
+#define IOCTL_BCM_COPY_SECTION			_IOW(BCM_IOCTL, 0x870, int)
+#define	IOCTL_BCM_GET_FLASH_CS_INFO		_IOR(BCM_IOCTL, 0x871, int)
+#define IOCTL_BCM_SELECT_DSD			_IOW(BCM_IOCTL, 0x872, int)
+#define IOCTL_BCM_NVM_RAW_READ			_IOR(BCM_IOCTL, 0x875, int)
+#define IOCTL_BCM_CNTRLMSG_MASK			_IOW(BCM_IOCTL, 0x874, int)
+#define IOCTL_BCM_GET_DEVICE_DRIVER_INFO	_IOR(BCM_IOCTL, 0x877, int)
+#define IOCTL_BCM_TIME_SINCE_NET_ENTRY		_IOR(BCM_IOCTL, 0x876, int)
+#define BCM_LED_THREAD_STATE_CHANGE_REQ		_IOW(BCM_IOCTL, 0x878, int)
+#define IOCTL_BCM_GPIO_MULTI_REQUEST		_IOW(BCM_IOCTL, 0x82D, struct bcm_ioctl_buffer)
+#define IOCTL_BCM_GPIO_MODE_REQUEST		_IOW(BCM_IOCTL, 0x82E, struct bcm_ioctl_buffer)
+
+enum bcm_interface_type {
+	BCM_MII,
+	BCM_CARDBUS,
+	BCM_USB,
+	BCM_SDIO,
+	BCM_PCMCIA
+};
 
-#define IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP _IOR(BCM_IOCTL,0x867, int)
-
-#define IOCTL_BCM_SET_ACTIVE_SECTION 		_IOW(BCM_IOCTL,0x868, int)
-
-#define	IOCTL_BCM_IDENTIFY_ACTIVE_SECTION 	_IO(BCM_IOCTL,0x869)
-
-#define IOCTL_BCM_COPY_SECTION 				_IOW(BCM_IOCTL, 0x870,int)
-
-#define	IOCTL_BCM_GET_FLASH_CS_INFO 		_IOR(BCM_IOCTL, 0x871, int)
-
-#define IOCTL_BCM_SELECT_DSD 				_IOW(BCM_IOCTL, 0x872, int)
-
-#define IOCTL_BCM_NVM_RAW_READ  			_IOR(BCM_IOCTL, 0x875, int)
-
-#define IOCTL_BCM_CNTRLMSG_MASK  			_IOW(BCM_IOCTL, 0x874, int)
-
-#define IOCTL_BCM_GET_DEVICE_DRIVER_INFO  _IOR(BCM_IOCTL, 0x877, int)
-
-#define IOCTL_BCM_TIME_SINCE_NET_ENTRY  _IOR(BCM_IOCTL, 0x876, int)
-
-#define BCM_LED_THREAD_STATE_CHANGE_REQ	  _IOW(BCM_IOCTL, 0x878, int)
-
-#define IOCTL_BCM_GPIO_MULTI_REQUEST		_IOW(BCM_IOCTL, 0x82D, IOCTL_BUFFER)
-#define IOCTL_BCM_GPIO_MODE_REQUEST			_IOW(BCM_IOCTL, 0x82E, IOCTL_BUFFER)
-
-
-
-typedef enum _BCM_INTERFACE_TYPE
-{
-        BCM_MII,
-        BCM_CARDBUS,
-        BCM_USB,
-        BCM_SDIO,
-        BCM_PCMCIA
-}BCM_INTERFACE_TYPE;
-
-typedef struct _DEVICE_DRIVER_INFO
-{
-	NVM_TYPE 			u32NVMType;
-	UINT 				MaxRDMBufferSize;
-	BCM_INTERFACE_TYPE 	u32InterfaceType;
-	UINT 				u32DSDStartOffset;
-	UINT				u32RxAlignmentCorrection;
-	UINT 				u32Reserved[10];
-} DEVICE_DRIVER_INFO;
-
-typedef  struct _NVM_READWRITE
-{
+struct bcm_driver_info {
+	NVM_TYPE	u32NVMType;
+	unsigned int		MaxRDMBufferSize;
+	enum bcm_interface_type	u32InterfaceType;
+	unsigned int		u32DSDStartOffset;
+	unsigned int		u32RxAlignmentCorrection;
+	unsigned int		u32Reserved[10];
+};
 
+struct bcm_nvm_readwrite {
 	void __user *pBuffer;
-// Data to be written from|read to. Memory should be allocated by the caller.
-
 	uint32_t  uiOffset;
-// offset at which data should be written to or read from.
-
-	uint32_t  uiNumBytes;
-// No. of bytes to be written or read.
-
-	bool  bVerify;
-// Applicable only for write. If set verification of written data will be done.
-
-} NVM_READWRITE,*PNVM_READWRITE;
-typedef struct bulkwrmbuffer
-{
-	ULONG	Register;
-	ULONG	SwapEndian;
-	ULONG	Values[1];
-
-}BULKWRM_BUFFER,*PBULKWRM_BUFFER;
-
-
-/***********Structure used for FlashMap2.x *******************************/
+	uint32_t uiNumBytes;
+	bool bVerify;
+};
 
-/*
-*	These are Sction present inside the Flash.
-*	There is sectional RD/WR for flash Map 2.x.
-*	hence these section will be used in read/write API.
-*/
+struct bcm_bulk_wrm_buffer {
+	unsigned long Register;
+	unsigned long SwapEndian;
+	unsigned long Values[1];
+};
 
-typedef enum _FLASH2X_SECTION_VAL
-{
-	NO_SECTION_VAL = 0, //no section is chosen when absolute offset is given for RD/WR
+enum bcm_flash2x_section_val {
+	NO_SECTION_VAL = 0, /* no section is chosen when absolute offset is given for RD/WR */
 	ISO_IMAGE1,
 	ISO_IMAGE2,
 	DSD0,
@@ -257,104 +146,81 @@ typedef enum _FLASH2X_SECTION_VAL
 	ISO_IMAGE2_PART2,
 	ISO_IMAGE2_PART3,
 	TOTAL_SECTIONS
-}FLASH2X_SECTION_VAL;
+};
 
 /*
-*	Structure used for READ/WRITE Flash  Map2.x
-*/
-typedef struct _FLASH2X_READWRITE
-{
-
-	FLASH2X_SECTION_VAL Section; //which section has to be read/written
-	B_UINT32 offset;		//Offset within Section.
-	B_UINT32 numOfBytes;	//NOB from the offset
-	B_UINT32  bVerify;
-	void __user *pDataBuff;	//Buffer for reading/writing
+ * Structure used for READ/WRITE Flash Map2.x
+ */
+struct bcm_flash2x_readwrite {
+	enum bcm_flash2x_section_val Section; /* which section has to be read/written */
+	u32 offset;	     /* Offset within Section. */
+	u32 numOfBytes;	     /* NOB from the offset */
+	u32 bVerify;
+	void __user *pDataBuff;	     /* Buffer for reading/writing */
+};
 
-}FLASH2X_READWRITE, *PFLASH2X_READWRITE;
 /*
-*	This structure is used for coping one section to other.
-*	there are two ways to copy one section to other.
-*	it NOB =0, complete section will be copied on to other.
-*	if NOB !=0, only NOB will be copied from the given offset.
-*/
-
-typedef struct _FLASH2X_COPY_SECTION
-{
-	//Src Section from which Data has to be copied to DstSection
-	FLASH2X_SECTION_VAL SrcSection;
-
-	//Destination Section from where Data has to be coppied.
-	FLASH2X_SECTION_VAL DstSection;
-
-	//Offset within Section. if NOB =0 it will be ignored and data will be coped from offset 0.
-	B_UINT32 offset;
-
-	//NOB from the offset. if NOB = 0 complete src section will be copied to Destination section.
-	B_UINT32 numOfBytes;
-} FLASH2X_COPY_SECTION, *PFLASH2X_COPY_SECTION;
-
-
-typedef enum _SECTION_TYPE
-{
-	ISO = 0,
-	VSA = 1,
-	DSD = 2
-} SECTION_TYPE, *PSECTION_TYPE;
+ * This structure is used for coping one section to other.
+ * there are two ways to copy one section to other.
+ * it NOB =0, complete section will be copied on to other.
+ * if NOB !=0, only NOB will be copied from the given offset.
+ */
+
+struct bcm_flash2x_copy_section {
+	enum bcm_flash2x_section_val SrcSection;
+	enum bcm_flash2x_section_val DstSection;
+	u32 offset;
+	u32 numOfBytes;
+};
 
 /*
-*	This section provide the complete bitmap of the Flash.
-*	using this map lib/APP will isssue read/write command.
-	Fields are defined as :
-	Bit [0] = section is present  //1:present, 0: Not present
-*      Bit [1] = section is valid  //1: valid, 0: not valid
-*      Bit [2] = Section is R/W  //0: RW, 1: RO
-*	Bit [3] = Section is Active or not 1 means Active, 0->inactive
-*      Bit [7...3] = Reserved
-*/
-
-typedef struct _FLASH2X_BITMAP
-{
-	UCHAR ISO_IMAGE1;
-	UCHAR ISO_IMAGE2;
-	UCHAR DSD0;
-	UCHAR DSD1;
-	UCHAR DSD2;
-	UCHAR VSA0;
-	UCHAR VSA1;
-	UCHAR VSA2;
-	UCHAR SCSI;
-	UCHAR CONTROL_SECTION;
-	//Reserved for future use
-	UCHAR Reserved0;
-	UCHAR Reserved1;
-	UCHAR Reserved2;
-}FLASH2X_BITMAP, *PFLASH2X_BITMAP;
+ * This section provide the complete bitmap of the Flash.
+ * using this map lib/APP will isssue read/write command.
+ * Fields are defined as :
+ * Bit [0] = section is present  //1:present, 0: Not present
+ * Bit [1] = section is valid  //1: valid, 0: not valid
+ * Bit [2] = Section is R/W  //0: RW, 1: RO
+ * Bit [3] = Section is Active or not 1 means Active, 0->inactive
+ * Bit [7...3] = Reserved
+ */
+
+struct bcm_flash2x_bitmap {
+	unsigned char ISO_IMAGE1;
+	unsigned char ISO_IMAGE2;
+	unsigned char DSD0;
+	unsigned char DSD1;
+	unsigned char DSD2;
+	unsigned char VSA0;
+	unsigned char VSA1;
+	unsigned char VSA2;
+	unsigned char SCSI;
+	unsigned char CONTROL_SECTION;
+	/* Reserved for future use */
+	unsigned char Reserved0;
+	unsigned char Reserved1;
+	unsigned char Reserved2;
+};
 
-//for net entry time check
-typedef struct _ST_TIME_ELAPSED_
-{
-	ULONG64	ul64TimeElapsedSinceNetEntry;
-	UINT32   uiReserved[4]; //By chance if required for future proofing
-}ST_TIME_ELAPSED,*PST_TIME_ELAPSED;
+struct bcm_time_elapsed {
+	unsigned long long ul64TimeElapsedSinceNetEntry;
+	u32  uiReserved[4];
+};
 
 enum {
-  WIMAX_IDX=0, /*To access WiMAX chip GPIO's for GPIO_MULTI_INFO or GPIO_MULTI_MODE*/
-  HOST_IDX,    /*To access Host chip GPIO's for GPIO_MULTI_INFO or GPIO_MULTI_MODE*/
-  MAX_IDX
+	WIMAX_IDX = 0,  /* To access WiMAX chip GPIO's for GPIO_MULTI_INFO or GPIO_MULTI_MODE */
+	HOST_IDX,	/* To access Host chip GPIO's for GPIO_MULTI_INFO or GPIO_MULTI_MODE */
+	MAX_IDX
 };
-typedef struct stGPIOMultiInfo
-{
-  UINT uiGPIOCommand; /* 1 for set and 0 for get*/
-  UINT uiGPIOMask;    /* set the correspondig bit to 1 to access GPIO*/
-  UINT uiGPIOValue;   /* 0 or 1; value to be set when command is 1.*/
-}__attribute__((packed))GPIO_MULTI_INFO , *PGPIO_MULTI_INFO;
 
-typedef struct stGPIOMultiMode
-{
-  UINT uiGPIOMode;    /* 1 for OUT mode, 0 for IN mode*/
-  UINT uiGPIOMask;    /* GPIO mask to set mode*/
-}__attribute__((packed))GPIO_MULTI_MODE, *PGPIO_MULTI_MODE;
+struct bcm_gpio_multi_info {
+	unsigned int uiGPIOCommand; /* 1 for set and 0 for get */
+	unsigned int uiGPIOMask;    /* set the correspondig bit to 1 to access GPIO */
+	unsigned int uiGPIOValue;   /* 0 or 1; value to be set when command is 1. */
+} __packed;
 
+struct bcm_gpio_multi_mode {
+	unsigned int uiGPIOMode;    /* 1 for OUT mode, 0 for IN mode */
+	unsigned int uiGPIOMask;    /* GPIO mask to set mode */
+} __packed;
 
 #endif
diff --git a/drivers/staging/bcm/LeakyBucket.c b/drivers/staging/bcm/LeakyBucket.c
index 6e8a327..877cf0b 100644
--- a/drivers/staging/bcm/LeakyBucket.c
+++ b/drivers/staging/bcm/LeakyBucket.c
@@ -21,10 +21,12 @@ static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter)
 	INT 	i = 0;
 	struct timeval tv;
 
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "=====>\n");
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL,
+			"=====>\n");
 	if(NULL == Adapter)
 	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Adapter found NULL!\n");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, 
+				DBG_LVL_ALL, "Adapter found NULL!\n");
 		return;
 	}
 
diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c
index f13a958..c92078e 100644
--- a/drivers/staging/bcm/Misc.c
+++ b/drivers/staging/bcm/Misc.c
@@ -1,14 +1,14 @@
 #include "headers.h"
 
 static int BcmFileDownload(struct bcm_mini_adapter *Adapter, const char *path, unsigned int loc);
-static VOID doPowerAutoCorrection(struct bcm_mini_adapter *psAdapter);
+static void doPowerAutoCorrection(struct bcm_mini_adapter *psAdapter);
 static void HandleShutDownModeRequest(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer);
 static int bcm_parse_target_params(struct bcm_mini_adapter *Adapter);
 static void beceem_protocol_reset(struct bcm_mini_adapter *Adapter);
 
-static VOID default_wimax_protocol_initialize(struct bcm_mini_adapter *Adapter)
+static void default_wimax_protocol_initialize(struct bcm_mini_adapter *Adapter)
 {
-	UINT uiLoopIndex;
+	unsigned int uiLoopIndex;
 
 	for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES-1; uiLoopIndex++) {
 		Adapter->PackInfo[uiLoopIndex].uiThreshold = TX_PACKET_THRESHOLD;
@@ -24,10 +24,10 @@ static VOID default_wimax_protocol_initialize(struct bcm_mini_adapter *Adapter)
 	return;
 }
 
-INT InitAdapter(struct bcm_mini_adapter *psAdapter)
+int InitAdapter(struct bcm_mini_adapter *psAdapter)
 {
 	int i = 0;
-	INT Status = STATUS_SUCCESS;
+	int Status = STATUS_SUCCESS;
 	BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Initialising Adapter = %p", psAdapter);
 
 	if (psAdapter == NULL) {
@@ -93,7 +93,7 @@ INT InitAdapter(struct bcm_mini_adapter *psAdapter)
 	return STATUS_SUCCESS;
 }
 
-VOID AdapterFree(struct bcm_mini_adapter *Adapter)
+void AdapterFree(struct bcm_mini_adapter *Adapter)
 {
 	int count;
 	beceem_protocol_reset(Adapter);
@@ -216,12 +216,12 @@ exit_download:
  * Logical Adapter
  * Control Packet Buffer
  */
-INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, PVOID ioBuffer)
+int CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, void *ioBuffer)
 {
 	struct bcm_leader *pLeader = NULL;
-	INT Status = 0;
-	unsigned char *ctrl_buff = NULL;
-	UINT pktlen = 0;
+	int Status = 0;
+	unsigned char *ctrl_buff;
+	unsigned int pktlen = 0;
 	struct bcm_link_request *pLinkReq = NULL;
 	PUCHAR pucAddIndication = NULL;
 
@@ -253,7 +253,7 @@ INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, PVOID ioBuffer)
 			return STATUS_FAILURE;
 		}
 
-		if (TRUE == Adapter->bShutStatus) {
+		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) {
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Waking up for the First Time..\n");
@@ -275,7 +275,7 @@ INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, PVOID ioBuffer)
 		}
 	}
 
-	if (TRUE == Adapter->IdleMode) {
+	if (Adapter->IdleMode == TRUE) {
 		/* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle mode ... hence\n"); */
 		if (pLeader->Status == LINK_UP_CONTROL_REQ || pLeader->Status == 0x80 ||
 			pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ) {
@@ -325,64 +325,66 @@ INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, PVOID ioBuffer)
 	pktlen = pLeader->PLength;
 	ctrl_buff = (char *)Adapter->txctlpacket[atomic_read(&Adapter->index_wr_txcntrlpkt)%MAX_CNTRL_PKTS];
 
+	if (!ctrl_buff) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "mem allocation Failed");
+		return -ENOMEM;
+	}
+
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Control packet to be taken =%d and address is =%pincoming address is =%p and packet len=%x",
 			atomic_read(&Adapter->index_wr_txcntrlpkt), ctrl_buff, ioBuffer, pktlen);
-	if (ctrl_buff) {
-		if (pLeader) {
-			if ((pLeader->Status == 0x80) ||
-				(pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ)) {
-				/*
-				 * Restructure the DSX message to handle Multiple classifier Support
-				 * Write the Service Flow param Structures directly to the target
-				 * and embed the pointers in the DSX messages sent to target.
-				 */
-				/* Lets store the current length of the control packet we are transmitting */
-				pucAddIndication = (PUCHAR)ioBuffer + LEADER_SIZE;
-				pktlen = pLeader->PLength;
-				Status = StoreCmControlResponseMessage(Adapter, pucAddIndication, &pktlen);
-				if (Status != 1) {
-					ClearTargetDSXBuffer(Adapter, ((stLocalSFAddIndicationAlt *)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;
-				}
-				/*
-				 * update the leader to use the new length
-				 * The length of the control packet is length of message being sent + Leader length
-				 */
-				pLeader->PLength = pktlen;
+
+	if (pLeader) {
+		if ((pLeader->Status == 0x80) ||
+			(pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ)) {
+			/*
+			 * Restructure the DSX message to handle Multiple classifier Support
+			 * Write the Service Flow param Structures directly to the target
+			 * and embed the pointers in the DSX messages sent to target.
+			 */
+			/* Lets store the current length of the control packet we are transmitting */
+			pucAddIndication = (PUCHAR)ioBuffer + LEADER_SIZE;
+			pktlen = pLeader->PLength;
+			Status = StoreCmControlResponseMessage(Adapter, pucAddIndication, &pktlen);
+			if (Status != 1) {
+				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;
 			}
+			/*
+			 * update the leader to use the new length
+			 * The length of the control packet is length of message being sent + Leader length
+			 */
+			pLeader->PLength = pktlen;
 		}
-
-		if (pktlen + LEADER_SIZE > MAX_CNTL_PKT_SIZE)
-			return -EINVAL;
-
-		memset(ctrl_buff, 0, pktlen+LEADER_SIZE);
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Copying the Control Packet Buffer with length=%d\n", pLeader->PLength);
-		*(struct bcm_leader *)ctrl_buff = *pLeader;
-		memcpy(ctrl_buff + LEADER_SIZE, ((PUCHAR)ioBuffer + LEADER_SIZE), pLeader->PLength);
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Enqueuing the Control Packet");
-
-		/* Update the statistics counters */
-		spin_lock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock);
-		Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost += pLeader->PLength;
-		Adapter->PackInfo[HiPriority].uiCurrentPacketsOnHost++;
-		atomic_inc(&Adapter->TotalPacketCount);
-		spin_unlock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock);
-		Adapter->PackInfo[HiPriority].bValid = TRUE;
-
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "CurrBytesOnHost: %x bValid: %x",
-				Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost,
-				Adapter->PackInfo[HiPriority].bValid);
-		Status = STATUS_SUCCESS;
-		/*Queue the packet for transmission */
-		atomic_inc(&Adapter->index_wr_txcntrlpkt);
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Calling transmit_packets");
-		atomic_set(&Adapter->TxPktAvail, 1);
-		wake_up(&Adapter->tx_packet_wait_queue);
-	} else {
-		Status = -ENOMEM;
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "mem allocation Failed");
 	}
+
+	if (pktlen + LEADER_SIZE > MAX_CNTL_PKT_SIZE)
+		return -EINVAL;
+
+	memset(ctrl_buff, 0, pktlen+LEADER_SIZE);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Copying the Control Packet Buffer with length=%d\n", pLeader->PLength);
+	*(struct bcm_leader *)ctrl_buff = *pLeader;
+	memcpy(ctrl_buff + LEADER_SIZE, ((PUCHAR)ioBuffer + LEADER_SIZE), pLeader->PLength);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Enqueuing the Control Packet");
+
+	/* Update the statistics counters */
+	spin_lock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock);
+	Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost += pLeader->PLength;
+	Adapter->PackInfo[HiPriority].uiCurrentPacketsOnHost++;
+	atomic_inc(&Adapter->TotalPacketCount);
+	spin_unlock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock);
+	Adapter->PackInfo[HiPriority].bValid = TRUE;
+
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "CurrBytesOnHost: %x bValid: %x",
+			Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost,
+			Adapter->PackInfo[HiPriority].bValid);
+	Status = STATUS_SUCCESS;
+	/*Queue the packet for transmission */
+	atomic_inc(&Adapter->index_wr_txcntrlpkt);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Calling transmit_packets");
+	atomic_set(&Adapter->TxPktAvail, 1);
+	wake_up(&Adapter->tx_packet_wait_queue);
+
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<====");
 	return Status;
 }
@@ -397,7 +399,7 @@ INT CopyBufferToControlPacket(struct bcm_mini_adapter *Adapter, PVOID ioBuffer)
 *
 * Returns     - None.
 *******************************************************************/
-VOID LinkMessage(struct bcm_mini_adapter *Adapter)
+void LinkMessage(struct bcm_mini_adapter *Adapter)
 {
 	struct bcm_link_request *pstLinkRequest = NULL;
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "=====>");
@@ -448,11 +450,11 @@ VOID LinkMessage(struct bcm_mini_adapter *Adapter)
 *
 * Returns     - None.
 ************************************************************************/
-VOID StatisticsResponse(struct bcm_mini_adapter *Adapter, PVOID pvBuffer)
+void StatisticsResponse(struct bcm_mini_adapter *Adapter, void *pvBuffer)
 {
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s====>", __func__);
 	Adapter->StatisticsPointer = ntohl(*(__be32 *)pvBuffer);
-	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Stats at %x", (UINT)Adapter->StatisticsPointer);
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Stats at %x", (unsigned int)Adapter->StatisticsPointer);
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s <====", __func__);
 	return;
 }
@@ -467,7 +469,7 @@ VOID StatisticsResponse(struct bcm_mini_adapter *Adapter, PVOID pvBuffer)
 *
 * Returns     - None.
 ***********************************************************************/
-VOID LinkControlResponseMessage(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer)
+void LinkControlResponseMessage(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer)
 {
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "=====>");
 
@@ -543,7 +545,7 @@ VOID LinkControlResponseMessage(struct bcm_mini_adapter *Adapter, PUCHAR pucBuff
 
 void SendIdleModeResponse(struct bcm_mini_adapter *Adapter)
 {
-	INT status = 0, NVMAccess = 0, lowPwrAbortMsg = 0;
+	int status = 0, NVMAccess = 0, lowPwrAbortMsg = 0;
 	struct timeval tv;
 	struct bcm_link_request stIdleResponse = {{0} };
 	memset(&tv, 0, sizeof(tv));
@@ -583,7 +585,7 @@ void SendIdleModeResponse(struct bcm_mini_adapter *Adapter)
 
 		/* Wait for the LED to TURN OFF before sending ACK response */
 		if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
-			INT iRetVal = 0;
+			int iRetVal = 0;
 
 			/* Wake the LED Thread with IDLEMODE_ENTER State */
 			Adapter->DriverState = LOWPOWER_MODE_ENTER;
@@ -609,7 +611,7 @@ void SendIdleModeResponse(struct bcm_mini_adapter *Adapter)
 			up(&Adapter->rdmwrmsync);
 			/* Killing all URBS. */
 			if (Adapter->bDoSuspend == TRUE)
-				Bcm_kill_all_URBs((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
+				Bcm_kill_all_URBs((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
 		} else {
 			Adapter->bPreparingForLowPowerMode = FALSE;
 		}
@@ -625,7 +627,7 @@ void SendIdleModeResponse(struct bcm_mini_adapter *Adapter)
 	if ((status != STATUS_SUCCESS)) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "fail to send the Idle mode Request\n");
 		Adapter->bPreparingForLowPowerMode = FALSE;
-		StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
+		StartInterruptUrb((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
 	}
 	do_gettimeofday(&tv);
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "IdleMode Msg submitter to Q :%ld ms", tv.tv_sec * 1000 + tv.tv_usec / 1000);
@@ -640,11 +642,11 @@ void SendIdleModeResponse(struct bcm_mini_adapter *Adapter)
 *
 * Returns     - None.
 *******************************************************************/
-VOID DumpPackInfo(struct bcm_mini_adapter *Adapter)
+void DumpPackInfo(struct bcm_mini_adapter *Adapter)
 {
-	UINT uiLoopIndex = 0;
-	UINT uiIndex = 0;
-	UINT uiClsfrIndex = 0;
+	unsigned int uiLoopIndex = 0;
+	unsigned int uiIndex = 0;
+	unsigned int uiClsfrIndex = 0;
 	struct bcm_classifier_rule *pstClassifierEntry = NULL;
 
 	for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) {
@@ -776,11 +778,11 @@ int reset_card_proc(struct bcm_mini_adapter *ps_adapter)
 {
 	int retval = STATUS_SUCCESS;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
-	PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
+	struct bcm_interface_adapter *psIntfAdapter = NULL;
 	unsigned int value = 0, uiResetValue = 0;
 	int bytes;
 
-	psIntfAdapter = ((PS_INTERFACE_ADAPTER)(ps_adapter->pvInterfaceAdapter));
+	psIntfAdapter = ((struct bcm_interface_adapter *)(ps_adapter->pvInterfaceAdapter));
 	ps_adapter->bDDRInitDone = FALSE;
 
 	if (ps_adapter->chip_id >= T3LPB) {
@@ -920,7 +922,7 @@ int run_card_proc(struct bcm_mini_adapter *ps_adapter)
 int InitCardAndDownloadFirmware(struct bcm_mini_adapter *ps_adapter)
 {
 	int status;
-	UINT value = 0;
+	unsigned int value = 0;
 	/*
 	 * Create the threads first and then download the
 	 * Firm/DDR Settings..
@@ -1088,7 +1090,7 @@ static int bcm_parse_target_params(struct bcm_mini_adapter *Adapter)
 
 void beceem_parse_target_struct(struct bcm_mini_adapter *Adapter)
 {
-	UINT uiHostDrvrCfg6 = 0, uiEEPROMFlag = 0;
+	unsigned int uiHostDrvrCfg6 = 0, uiEEPROMFlag = 0;
 
 	if (ntohl(Adapter->pstargetparams->m_u32PhyParameter2) & AUTO_SYNC_DISABLE) {
 		pr_info(DRV_NAME ": AutoSyncup is Disabled\n");
@@ -1144,9 +1146,9 @@ void beceem_parse_target_struct(struct bcm_mini_adapter *Adapter)
 		doPowerAutoCorrection(Adapter);
 }
 
-static VOID doPowerAutoCorrection(struct bcm_mini_adapter *psAdapter)
+static void doPowerAutoCorrection(struct bcm_mini_adapter *psAdapter)
 {
-	UINT reporting_mode;
+	unsigned int reporting_mode;
 
 	reporting_mode = ntohl(psAdapter->pstargetparams->m_u32PowerSavingModeOptions) & 0x02;
 	psAdapter->bIsAutoCorrectEnabled = !((char)(psAdapter->ulPowerSaveMode >> 3) & 0x1);
@@ -1175,26 +1177,26 @@ static VOID doPowerAutoCorrection(struct bcm_mini_adapter *psAdapter)
 	}
 }
 
-static void convertEndian(B_UINT8 rwFlag, PUINT puiBuffer, UINT uiByteCount)
+static void convertEndian(unsigned char rwFlag, unsigned int *puiBuffer, unsigned int uiByteCount)
 {
-	UINT uiIndex = 0;
+	unsigned int uiIndex = 0;
 
 	if (RWM_WRITE == rwFlag) {
-		for (uiIndex = 0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++)
+		for (uiIndex = 0; uiIndex < (uiByteCount/sizeof(unsigned int)); uiIndex++)
 			puiBuffer[uiIndex] = htonl(puiBuffer[uiIndex]);
 	} else {
-		for (uiIndex = 0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++)
+		for (uiIndex = 0; uiIndex < (uiByteCount/sizeof(unsigned int)); uiIndex++)
 			puiBuffer[uiIndex] = ntohl(puiBuffer[uiIndex]);
 	}
 }
 
-int rdm(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
+int rdm(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, PCHAR pucBuff, size_t sSize)
 {
 	return Adapter->interface_rdm(Adapter->pvInterfaceAdapter,
 				uiAddress, pucBuff, sSize);
 }
 
-int wrm(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
+int wrm(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, PCHAR pucBuff, size_t sSize)
 {
 	int iRetVal;
 
@@ -1203,25 +1205,25 @@ int wrm(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t
 	return iRetVal;
 }
 
-int wrmalt(struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
+int wrmalt(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, unsigned int *pucBuff, size_t size)
 {
 	convertEndian(RWM_WRITE, pucBuff, size);
 	return wrm(Adapter, uiAddress, (PUCHAR)pucBuff, size);
 }
 
-int rdmalt(struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
+int rdmalt(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, unsigned int *pucBuff, size_t size)
 {
-	INT uiRetVal = 0;
+	int uiRetVal = 0;
 
 	uiRetVal = rdm(Adapter, uiAddress, (PUCHAR)pucBuff, size);
-	convertEndian(RWM_READ, (PUINT)pucBuff, size);
+	convertEndian(RWM_READ, (unsigned int *)pucBuff, size);
 
 	return uiRetVal;
 }
 
-int wrmWithLock(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize)
+int wrmWithLock(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, PCHAR pucBuff, size_t sSize)
 {
-	INT status = STATUS_SUCCESS;
+	int status = STATUS_SUCCESS;
 	down(&Adapter->rdmwrmsync);
 
 	if ((Adapter->IdleMode == TRUE) ||
@@ -1238,7 +1240,7 @@ exit:
 	return status;
 }
 
-int wrmaltWithLock(struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
+int wrmaltWithLock(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, unsigned int *pucBuff, size_t size)
 {
 	int iRetVal = STATUS_SUCCESS;
 
@@ -1258,9 +1260,9 @@ exit:
 	return iRetVal;
 }
 
-int rdmaltWithLock(struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t size)
+int rdmaltWithLock(struct bcm_mini_adapter *Adapter, unsigned int uiAddress, unsigned int *pucBuff, size_t size)
 {
-	INT uiRetVal = STATUS_SUCCESS;
+	int uiRetVal = STATUS_SUCCESS;
 
 	down(&Adapter->rdmwrmsync);
 	if ((Adapter->IdleMode == TRUE) ||
@@ -1277,13 +1279,13 @@ exit:
 	return uiRetVal;
 }
 
-static VOID HandleShutDownModeWakeup(struct bcm_mini_adapter *Adapter)
+static void HandleShutDownModeWakeup(struct bcm_mini_adapter *Adapter)
 {
 	int clear_abort_pattern = 0, Status = 0;
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n");
 	/* target has woken up From Shut Down */
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Clearing Shut Down Software abort pattern\n");
-	Status = wrmalt(Adapter, SW_ABORT_IDLEMODE_LOC, (PUINT)&clear_abort_pattern, sizeof(clear_abort_pattern));
+	Status = wrmalt(Adapter, SW_ABORT_IDLEMODE_LOC, (unsigned int *)&clear_abort_pattern, sizeof(clear_abort_pattern));
 	if (Status) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "WRM to SW_ABORT_IDLEMODE_LOC failed with err:%d", Status);
 		return;
@@ -1306,11 +1308,11 @@ static VOID HandleShutDownModeWakeup(struct bcm_mini_adapter *Adapter)
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n");
 }
 
-static VOID SendShutModeResponse(struct bcm_mini_adapter *Adapter)
+static void SendShutModeResponse(struct bcm_mini_adapter *Adapter)
 {
 	struct bcm_link_request stShutdownResponse;
-	UINT NVMAccess = 0, lowPwrAbortMsg = 0;
-	UINT Status = 0;
+	unsigned int NVMAccess = 0, lowPwrAbortMsg = 0;
+	unsigned int Status = 0;
 
 	memset(&stShutdownResponse, 0, sizeof(struct bcm_link_request));
 	stShutdownResponse.Leader.Status  = LINK_UP_CONTROL_REQ;
@@ -1346,7 +1348,7 @@ static VOID SendShutModeResponse(struct bcm_mini_adapter *Adapter)
 
 		/* Wait for the LED to TURN OFF before sending ACK response */
 		if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
-			INT iRetVal = 0;
+			int iRetVal = 0;
 
 			/* Wake the LED Thread with LOWPOWER_MODE_ENTER State */
 			Adapter->DriverState = LOWPOWER_MODE_ENTER;
@@ -1370,7 +1372,7 @@ static VOID SendShutModeResponse(struct bcm_mini_adapter *Adapter)
 			up(&Adapter->rdmwrmsync);
 			/* Killing all URBS. */
 			if (Adapter->bDoSuspend == TRUE)
-				Bcm_kill_all_URBs((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
+				Bcm_kill_all_URBs((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
 		} else {
 			Adapter->bPreparingForLowPowerMode = FALSE;
 		}
@@ -1386,13 +1388,13 @@ static VOID SendShutModeResponse(struct bcm_mini_adapter *Adapter)
 	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;
-		StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
+		StartInterruptUrb((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
 	}
 }
 
 static void HandleShutDownModeRequest(struct bcm_mini_adapter *Adapter, PUCHAR pucBuffer)
 {
-	B_UINT32 uiResetValue = 0;
+	unsigned int uiResetValue = 0;
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n");
 
@@ -1412,14 +1414,14 @@ static void HandleShutDownModeRequest(struct bcm_mini_adapter *Adapter, PUCHAR p
 		}
 
 		SendShutModeResponse(Adapter);
-		BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "ShutDownModeResponse:Notification received: Sending the response(Ack/Nack)\n");
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "ShutDownModeResponse:Notification received: Sending the response(Ack/Nack)\n");
 	}
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n");
 	return;
 }
 
-VOID ResetCounters(struct bcm_mini_adapter *Adapter)
+void ResetCounters(struct bcm_mini_adapter *Adapter)
 {
 	beceem_protocol_reset(Adapter);
 	Adapter->CurrNumRecvDescs = 0;
@@ -1437,7 +1439,7 @@ VOID ResetCounters(struct bcm_mini_adapter *Adapter)
 
 struct bcm_classifier_rule *GetFragIPClsEntry(struct bcm_mini_adapter *Adapter, USHORT usIpIdentification, ULONG SrcIP)
 {
-	UINT uiIndex = 0;
+	unsigned int uiIndex = 0;
 	for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
 		if ((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) &&
 			(Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification) &&
@@ -1451,7 +1453,7 @@ struct bcm_classifier_rule *GetFragIPClsEntry(struct bcm_mini_adapter *Adapter,
 
 void AddFragIPClsEntry(struct bcm_mini_adapter *Adapter, struct bcm_fragmented_packet_info *psFragPktInfo)
 {
-	UINT uiIndex = 0;
+	unsigned int uiIndex = 0;
 	for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
 		if (!Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) {
 			memcpy(&Adapter->astFragmentedPktClassifierTable[uiIndex], psFragPktInfo, sizeof(struct bcm_fragmented_packet_info));
@@ -1462,7 +1464,7 @@ void AddFragIPClsEntry(struct bcm_mini_adapter *Adapter, struct bcm_fragmented_p
 
 void DelFragIPClsEntry(struct bcm_mini_adapter *Adapter, USHORT usIpIdentification, ULONG SrcIp)
 {
-	UINT uiIndex = 0;
+	unsigned int uiIndex = 0;
 	for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) {
 		if ((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) &&
 			(Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification) &&
@@ -1474,7 +1476,7 @@ void DelFragIPClsEntry(struct bcm_mini_adapter *Adapter, USHORT usIpIdentificati
 
 void update_per_cid_rx(struct bcm_mini_adapter *Adapter)
 {
-	UINT qindex = 0;
+	unsigned int qindex = 0;
 
 	if ((jiffies - Adapter->liDrainCalculated) < XSECONDS)
 		return;
@@ -1498,14 +1500,14 @@ void update_per_cid_rx(struct bcm_mini_adapter *Adapter)
 
 void update_per_sf_desc_cnts(struct bcm_mini_adapter *Adapter)
 {
-	INT iIndex = 0;
+	int iIndex = 0;
 	u32 uibuff[MAX_TARGET_DSX_BUFFERS];
 	int bytes;
 
 	if (!atomic_read(&Adapter->uiMBupdate))
 		return;
 
-	bytes = rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (PUINT)uibuff, sizeof(UINT) * MAX_TARGET_DSX_BUFFERS);
+	bytes = rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (unsigned int *)uibuff, sizeof(unsigned int) * MAX_TARGET_DSX_BUFFERS);
 	if (bytes < 0) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "rdm failed\n");
 		return;
@@ -1522,7 +1524,7 @@ void update_per_sf_desc_cnts(struct bcm_mini_adapter *Adapter)
 	atomic_set(&Adapter->uiMBupdate, FALSE);
 }
 
-void flush_queue(struct bcm_mini_adapter *Adapter, UINT iQIndex)
+void flush_queue(struct bcm_mini_adapter *Adapter, unsigned int iQIndex)
 {
 	struct sk_buff *PacketToDrop = NULL;
 	struct net_device_stats *netstats = &Adapter->dev->stats;
@@ -1573,6 +1575,6 @@ static void beceem_protocol_reset(struct bcm_mini_adapter *Adapter)
 	for (i = 0; i < HiPriority; i++) {
 		/* resetting only the first size (S_MIBS_SERVICEFLOW_TABLE) for the SF. */
 		/* It is same between MIBs and SF. */
-		memset(&Adapter->PackInfo[i].stMibsExtServiceFlowTable, 0, sizeof(S_MIBS_EXTSERVICEFLOW_PARAMETERS));
+		memset(&Adapter->PackInfo[i].stMibsExtServiceFlowTable, 0, sizeof(struct bcm_mibs_parameters));
 	}
 }
diff --git a/drivers/staging/bcm/Prototypes.h b/drivers/staging/bcm/Prototypes.h
index 3ec8f80..90dbe0f 100644
--- a/drivers/staging/bcm/Prototypes.h
+++ b/drivers/staging/bcm/Prototypes.h
@@ -79,17 +79,17 @@ int rdm(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t
 
 int wrm(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t size);
 
-int wrmalt (struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t sSize);
+int wrmalt (struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
 
-int rdmalt (struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t sSize);
+int rdmalt (struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
 
 int get_dsx_sf_data_to_application(struct bcm_mini_adapter *Adapter, UINT uiSFId, void __user * user_buffer);
 
 void SendIdleModeResponse(struct bcm_mini_adapter *Adapter);
 
 
-int  ProcessGetHostMibs(struct bcm_mini_adapter *Adapter, S_MIBS_HOST_STATS_MIBS *buf);
-void GetDroppedAppCntrlPktMibs(S_MIBS_HOST_STATS_MIBS *ioBuffer, struct bcm_tarang_data *pTarang);
+int  ProcessGetHostMibs(struct bcm_mini_adapter *Adapter, struct bcm_host_stats_mibs *buf);
+void GetDroppedAppCntrlPktMibs(struct bcm_host_stats_mibs *ioBuffer, struct bcm_tarang_data *pTarang);
 void beceem_parse_target_struct(struct bcm_mini_adapter *Adapter);
 
 int bcm_ioctl_fw_download(struct bcm_mini_adapter *Adapter, struct bcm_firmware_info *psFwInfo);
@@ -161,14 +161,14 @@ INT BeceemNVMWrite(
 INT BcmInitNVM(struct bcm_mini_adapter *Adapter);
 
 INT BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter,UINT uiSectorSize);
-BOOLEAN IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL section);
+BOOLEAN IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section);
 
-INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITMAP psFlash2xBitMap);
+INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_bitmap *psFlash2xBitMap);
 
 INT BcmFlash2xBulkWrite(
 	struct bcm_mini_adapter *Adapter,
 	PUINT pBuffer,
-	FLASH2X_SECTION_VAL eFlashSectionVal,
+	enum bcm_flash2x_section_val eFlashSectionVal,
 	UINT uiOffset,
 	UINT uiNumBytes,
 	UINT bVerify);
@@ -176,24 +176,24 @@ INT BcmFlash2xBulkWrite(
 INT BcmFlash2xBulkRead(
 	struct bcm_mini_adapter *Adapter,
 	PUINT pBuffer,
-	FLASH2X_SECTION_VAL eFlashSectionVal,
+	enum bcm_flash2x_section_val eFlashSectionVal,
 	UINT uiOffsetWithinSectionVal,
 	UINT uiNumBytes);
 
-INT BcmGetSectionValStartOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlashSectionVal);
+INT BcmGetSectionValStartOffset(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlashSectionVal);
 
-INT BcmSetActiveSection(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectVal);
+INT BcmSetActiveSection(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectVal);
 INT BcmAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter);
 INT BcmDeAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter);
 
-INT BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectStrut);
-INT BcmFlash2xCorruptSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal);
-INT BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlashSectionVal);
-INT	validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, PFLASH2X_READWRITE psFlash2xReadWrite);
+INT BcmCopyISO(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_copy_section sCopySectStrut);
+INT BcmFlash2xCorruptSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal);
+INT BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlashSectionVal);
+INT	validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_readwrite *psFlash2xReadWrite);
 INT IsFlash2x(struct bcm_mini_adapter *Adapter);
 INT	BcmCopySection(struct bcm_mini_adapter *Adapter,
-						FLASH2X_SECTION_VAL SrcSection,
-						FLASH2X_SECTION_VAL DstSection,
+						enum bcm_flash2x_section_val SrcSection,
+						enum bcm_flash2x_section_val DstSection,
 						UINT offset,
 						UINT numOfBytes);
 
@@ -203,8 +203,8 @@ BOOLEAN IsNonCDLessDevice(struct bcm_mini_adapter *Adapter);
 
 VOID OverrideServiceFlowParams(struct bcm_mini_adapter *Adapter,PUINT puiBuffer);
 
-int wrmaltWithLock (struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t sSize);
-int rdmaltWithLock (struct bcm_mini_adapter *Adapter, UINT uiAddress, PUINT pucBuff, size_t sSize);
+int wrmaltWithLock (struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
+int rdmaltWithLock (struct bcm_mini_adapter *Adapter, UINT uiAddress, unsigned int *pucBuff, size_t sSize);
 
 int wrmWithLock(struct bcm_mini_adapter *Adapter, UINT uiAddress, PCHAR pucBuff, size_t size);
 INT buffDnldVerify(struct bcm_mini_adapter *Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength,
diff --git a/drivers/staging/bcm/Transmit.c b/drivers/staging/bcm/Transmit.c
index 27e8c89..f8dc3e2 100644
--- a/drivers/staging/bcm/Transmit.c
+++ b/drivers/staging/bcm/Transmit.c
@@ -205,7 +205,7 @@ int tx_pkt_handler(struct bcm_mini_adapter *Adapter /**< pointer to adapter obje
 		if (Adapter->bEndPointHalted == TRUE) {
 			Bcm_clear_halt_of_endpoints(Adapter);
 			Adapter->bEndPointHalted = FALSE;
-			StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
+			StartInterruptUrb((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
 		}
 
 		if (Adapter->LinkUpStatus && !Adapter->IdleMode) {
diff --git a/drivers/staging/bcm/cntrl_SignalingInterface.h b/drivers/staging/bcm/cntrl_SignalingInterface.h
index 990e809..8683c2d 100644
--- a/drivers/staging/bcm/cntrl_SignalingInterface.h
+++ b/drivers/staging/bcm/cntrl_SignalingInterface.h
@@ -36,91 +36,91 @@
 
 struct bcm_packet_class_rules {
 	/* 16bit UserPriority Of The Service Flow */
-	B_UINT16 u16UserPriority;
+	u16 u16UserPriority;
 	/* 16bit VLANID Of The Service Flow */
-	B_UINT16 u16VLANID;
+	u16 u16VLANID;
 	/* 16bit Packet Classification RuleIndex Of The Service Flow */
-	B_UINT16 u16PacketClassificationRuleIndex;
+	u16 u16PacketClassificationRuleIndex;
 	/* 8bit Classifier Rule Priority Of The Service Flow */
-	B_UINT8 u8ClassifierRulePriority;
+	u8 u8ClassifierRulePriority;
 	/* Length of IP TypeOfService field */
-	B_UINT8 u8IPTypeOfServiceLength;
+	u8 u8IPTypeOfServiceLength;
 	/* 3bytes IP TypeOfService */
-	B_UINT8 u8IPTypeOfService[TYPE_OF_SERVICE_LENGTH];
+	u8 u8IPTypeOfService[TYPE_OF_SERVICE_LENGTH];
 	/* Protocol used in classification of Service Flow */
-	B_UINT8 u8Protocol;
+	u8 u8Protocol;
 	/* Length of IP Masked Source Address */
-	B_UINT8 u8IPMaskedSourceAddressLength;
+	u8 u8IPMaskedSourceAddressLength;
 	/* IP Masked Source Address used in classification for the Service Flow */
-	B_UINT8 u8IPMaskedSourceAddress[IP_MASKED_SRC_ADDRESS_LENGTH];
+	u8 u8IPMaskedSourceAddress[IP_MASKED_SRC_ADDRESS_LENGTH];
 	/* Length of IP Destination Address */
-	B_UINT8 u8IPDestinationAddressLength;
+	u8 u8IPDestinationAddressLength;
 	/* IP Destination Address used in classification for the Service Flow */
-	B_UINT8 u8IPDestinationAddress[IP_MASKED_DEST_ADDRESS_LENGTH];
+	u8 u8IPDestinationAddress[IP_MASKED_DEST_ADDRESS_LENGTH];
 	/* Length of Protocol Source Port Range */
-	B_UINT8 u8ProtocolSourcePortRangeLength;
+	u8 u8ProtocolSourcePortRangeLength;
 	/* Protocol Source Port Range used in the Service Flow */
-	B_UINT8 u8ProtocolSourcePortRange[PROTOCOL_SRC_PORT_RANGE_LENGTH];
+	u8 u8ProtocolSourcePortRange[PROTOCOL_SRC_PORT_RANGE_LENGTH];
 	/* Length of Protocol Dest Port Range */
-	B_UINT8 u8ProtocolDestPortRangeLength;
+	u8 u8ProtocolDestPortRangeLength;
 	/* Protocol Dest Port Range used in the Service Flow */
-	B_UINT8 u8ProtocolDestPortRange[PROTOCOL_DEST_PORT_RANGE_LENGTH];
+	u8 u8ProtocolDestPortRange[PROTOCOL_DEST_PORT_RANGE_LENGTH];
 	/* Length of Ethernet Destination MAC Address */
-	B_UINT8 u8EthernetDestMacAddressLength;
+	u8 u8EthernetDestMacAddressLength;
 	/* Ethernet Destination MAC Address  used in classification of the Service Flow */
-	B_UINT8 u8EthernetDestMacAddress[ETHERNET_DEST_MAC_ADDR_LENGTH];
+	u8 u8EthernetDestMacAddress[ETHERNET_DEST_MAC_ADDR_LENGTH];
 	/* Length of Ethernet Source MAC Address */
-	B_UINT8 u8EthernetSourceMACAddressLength;
+	u8 u8EthernetSourceMACAddressLength;
 	/* Ethernet Source MAC Address  used in classification of the Service Flow */
-	B_UINT8 u8EthernetSourceMACAddress[ETHERNET_SRC_MAC_ADDR_LENGTH];
+	u8 u8EthernetSourceMACAddress[ETHERNET_SRC_MAC_ADDR_LENGTH];
 	/* Length of Ethertype */
-	B_UINT8 u8EthertypeLength;
+	u8 u8EthertypeLength;
 	/* 3bytes Ethertype Of The Service Flow */
-	B_UINT8 u8Ethertype[NUM_ETHERTYPE_BYTES];
+	u8 u8Ethertype[NUM_ETHERTYPE_BYTES];
 	/* 8bit Associated PHSI Of The Service Flow */
-	B_UINT8 u8AssociatedPHSI;
+	u8 u8AssociatedPHSI;
 	/* Length of Vendor Specific Classifier Param length Of The Service Flow */
-	B_UINT8 u8VendorSpecificClassifierParamLength;
+	u8 u8VendorSpecificClassifierParamLength;
 	/* Vendor Specific Classifier Param Of The Service Flow */
-	B_UINT8 u8VendorSpecificClassifierParam[VENDOR_CLASSIFIER_PARAM_LENGTH];
+	u8 u8VendorSpecificClassifierParam[VENDOR_CLASSIFIER_PARAM_LENGTH];
 	/* Length Of IPv6 Flow Lable of the Service Flow */
-	B_UINT8 u8IPv6FlowLableLength;
+	u8 u8IPv6FlowLableLength;
 	/* IPv6 Flow Lable Of The Service Flow */
-	B_UINT8 u8IPv6FlowLable[NUM_IPV6_FLOWLABLE_BYTES];
+	u8 u8IPv6FlowLable[NUM_IPV6_FLOWLABLE_BYTES];
 	/* Action associated with the classifier rule */
-	B_UINT8 u8ClassifierActionRule;
-	B_UINT16 u16ValidityBitMap;
+	u8 u8ClassifierActionRule;
+	u16 u16ValidityBitMap;
 };
 
 struct bcm_phs_rules {
 	/* 8bit PHS Index Of The Service Flow */
-	B_UINT8 u8PHSI;
+	u8 u8PHSI;
 	/* PHSF Length Of The Service Flow */
-	B_UINT8 u8PHSFLength;
+	u8 u8PHSFLength;
 	/* String of bytes containing header information to be suppressed by the sending CS and reconstructed by the receiving CS */
-	B_UINT8 u8PHSF[MAX_PHS_LENGTHS];
+	u8 u8PHSF[MAX_PHS_LENGTHS];
 	/* PHSM Length Of The Service Flow */
-	B_UINT8 u8PHSMLength;
+	u8 u8PHSMLength;
 	/* PHS Mask for the SF */
-	B_UINT8 u8PHSM[MAX_PHS_LENGTHS];
+	u8 u8PHSM[MAX_PHS_LENGTHS];
 	/* 8bit Total number of bytes to be suppressed for the Service Flow */
-	B_UINT8 u8PHSS;
+	u8 u8PHSS;
 	/* 8bit Indicates whether or not Packet Header contents need to be verified prior to suppression */
-	B_UINT8 u8PHSV;
+	u8 u8PHSV;
 	/* Vendor Specific PHS param Length Of The Service Flow */
-	B_UINT8 u8VendorSpecificPHSParamsLength;
+	u8 u8VendorSpecificPHSParamsLength;
 	/* Vendor Specific PHS param Of The Service Flow */
-	B_UINT8 u8VendorSpecificPHSParams[VENDOR_PHS_PARAM_LENGTH];
-	B_UINT8 u8Padding[2];
+	u8 u8VendorSpecificPHSParams[VENDOR_PHS_PARAM_LENGTH];
+	u8 u8Padding[2];
 };
 
 struct bcm_convergence_types {
 	/* 8bit Phs Classfier Action Of The Service Flow */
-	B_UINT8 u8ClassfierDSCAction;
+	u8 u8ClassfierDSCAction;
 	/* 8bit Phs DSC Action Of The Service Flow */
-	B_UINT8 u8PhsDSCAction;
+	u8 u8PhsDSCAction;
 	/* 16bit Padding */
-	B_UINT8 u8Padding[2];
+	u8 u8Padding[2];
 	/* Packet classification rules structure */
 	struct bcm_packet_class_rules cCPacketClassificationRule;
 	/* Payload header suppression rules structure */
@@ -129,118 +129,118 @@ struct bcm_convergence_types {
 
 struct bcm_connect_mgr_params {
 	/* 32bitSFID Of The Service Flow */
-	B_UINT32 u32SFID;
+	u32 u32SFID;
 	/* 32bit Maximum Sustained Traffic Rate of the Service Flow */
-	B_UINT32 u32MaxSustainedTrafficRate;
+	u32 u32MaxSustainedTrafficRate;
 	/* 32bit Maximum Traffic Burst allowed for the Service Flow */
-	B_UINT32 u32MaxTrafficBurst;
+	u32 u32MaxTrafficBurst;
 	/* 32bit Minimum Reserved Traffic Rate of the Service Flow */
-	B_UINT32 u32MinReservedTrafficRate;
+	u32 u32MinReservedTrafficRate;
 	/* 32bit Tolerated Jitter of the Service Flow */
-	B_UINT32 u32ToleratedJitter;
+	u32 u32ToleratedJitter;
 	/* 32bit Maximum Latency of the Service Flow */
-	B_UINT32 u32MaximumLatency;
+	u32 u32MaximumLatency;
 	/* 16bitCID Of The Service Flow */
-	B_UINT16 u16CID;
+	u16 u16CID;
 	/* 16bit SAID on which the service flow being set up shall be mapped */
-	B_UINT16 u16TargetSAID;
+	u16 u16TargetSAID;
 	/* 16bit  ARQ window size negotiated */
-	B_UINT16 u16ARQWindowSize;
+	u16 u16ARQWindowSize;
 	/* 16bit Total Tx delay incl sending, receiving & processing delays */
-	B_UINT16 u16ARQRetryTxTimeOut;
+	u16 u16ARQRetryTxTimeOut;
 	/* 16bit Total Rx delay incl sending, receiving & processing delays */
-	B_UINT16 u16ARQRetryRxTimeOut;
+	u16 u16ARQRetryRxTimeOut;
 	/* 16bit ARQ block lifetime */
-	B_UINT16 u16ARQBlockLifeTime;
+	u16 u16ARQBlockLifeTime;
 	/* 16bit ARQ Sync loss timeout */
-	B_UINT16 u16ARQSyncLossTimeOut;
+	u16 u16ARQSyncLossTimeOut;
 	/* 16bit ARQ Purge timeout */
-	B_UINT16 u16ARQRxPurgeTimeOut;
+	u16 u16ARQRxPurgeTimeOut;
 	/* TODO::Remove this once we move to a new CORR2 driver
 	 * brief Size of an ARQ block
 	 */
-	B_UINT16 u16ARQBlockSize;
+	u16 u16ARQBlockSize;
 	/* #endif */
 	/* 16bit Nominal interval b/w consecutive SDU arrivals at MAC SAP */
-	B_UINT16 u16SDUInterArrivalTime;
+	u16 u16SDUInterArrivalTime;
 	/* 16bit Specifies the time base for rate measurement */
-	B_UINT16 u16TimeBase;
+	u16 u16TimeBase;
 	/* 16bit Interval b/w Successive Grant oppurtunities */
-	B_UINT16 u16UnsolicitedGrantInterval;
+	u16 u16UnsolicitedGrantInterval;
 	/* 16bit Interval b/w Successive Polling grant oppurtunities */
-	B_UINT16 u16UnsolicitedPollingInterval;
+	u16 u16UnsolicitedPollingInterval;
 	/* internal var to get the overhead */
-	B_UINT16 u16MacOverhead;
+	u16 u16MacOverhead;
 	/* MBS contents Identifier */
-	B_UINT16 u16MBSContentsID[MBS_CONTENTS_ID_LENGTH];
+	u16 u16MBSContentsID[MBS_CONTENTS_ID_LENGTH];
 	/* MBS contents Identifier length */
-	B_UINT8 u8MBSContentsIDLength;
+	u8 u8MBSContentsIDLength;
 	/* ServiceClassName Length Of The Service Flow */
-	B_UINT8 u8ServiceClassNameLength;
+	u8 u8ServiceClassNameLength;
 	/* 32bytes ServiceClassName Of The Service Flow */
-	B_UINT8 u8ServiceClassName[32];
+	u8 u8ServiceClassName[32];
 	/* 8bit Indicates whether or not MBS service is requested for this Serivce Flow */
-	B_UINT8 u8MBSService;
+	u8 u8MBSService;
 	/* 8bit QOS Parameter Set specifies proper application of QoS parameters to Provisioned, Admitted and Active sets */
-	B_UINT8 u8QosParamSet;
+	u8 u8QosParamSet;
 	/* 8bit Traffic Priority Of the Service Flow */
-	B_UINT8 u8TrafficPriority;
+	u8 u8TrafficPriority;
 	/* 8bit Uplink Grant Scheduling Type of The Service Flow */
-	B_UINT8 u8ServiceFlowSchedulingType;
+	u8 u8ServiceFlowSchedulingType;
 	/* 8bit Request transmission Policy of the Service Flow */
-	B_UINT8 u8RequesttransmissionPolicy;
+	u8 u8RequesttransmissionPolicy;
 	/* 8bit Specifies whether SDUs for this Service flow are of FixedLength or Variable length */
-	B_UINT8 u8FixedLengthVSVariableLengthSDUIndicator;
+	u8 u8FixedLengthVSVariableLengthSDUIndicator;
 	/* 8bit Length of the SDU for a fixed length SDU service flow */
-	B_UINT8 u8SDUSize;
+	u8 u8SDUSize;
 	/* 8bit Indicates whether or not ARQ is requested for this connection */
-	B_UINT8 u8ARQEnable;
+	u8 u8ARQEnable;
 	/* < 8bit Indicates whether or not data has tobe delivered in order to higher layer */
-	B_UINT8 u8ARQDeliverInOrder;
+	u8 u8ARQDeliverInOrder;
 	/* 8bit Receiver ARQ ACK processing time */
-	B_UINT8 u8RxARQAckProcessingTime;
+	u8 u8RxARQAckProcessingTime;
 	/* 8bit Convergence Sublayer Specification Of The Service Flow */
-	B_UINT8 u8CSSpecification;
+	u8 u8CSSpecification;
 	/* 8 bit Type of data delivery service */
-	B_UINT8 u8TypeOfDataDeliveryService;
+	u8 u8TypeOfDataDeliveryService;
 	/* 8bit Specifies whether a service flow may generate Paging */
-	B_UINT8 u8PagingPreference;
+	u8 u8PagingPreference;
 	/* 8bit Indicates the MBS Zone through which the connection or virtual connection is valid */
-	B_UINT8 u8MBSZoneIdentifierassignment;
+	u8 u8MBSZoneIdentifierassignment;
 	/* 8bit Specifies whether traffic on SF should generate MOB_TRF_IND to MS in sleep mode */
-	B_UINT8 u8TrafficIndicationPreference;
+	u8 u8TrafficIndicationPreference;
 	/* 8bit Speciifes the length of predefined Global QoS parameter set encoding for this SF */
-	B_UINT8 u8GlobalServicesClassNameLength;
+	u8 u8GlobalServicesClassNameLength;
 	/* 6 byte Speciifes the predefined Global QoS parameter set encoding for this SF */
-	B_UINT8 u8GlobalServicesClassName[GLOBAL_SF_CLASSNAME_LENGTH];
+	u8 u8GlobalServicesClassName[GLOBAL_SF_CLASSNAME_LENGTH];
 	/* 8bit Indicates whether or not SN feedback is enabled for the conn */
-	B_UINT8 u8SNFeedbackEnabled;
+	u8 u8SNFeedbackEnabled;
 	/* Indicates the size of the Fragment Sequence Number for the connection */
-	B_UINT8 u8FSNSize;
+	u8 u8FSNSize;
 	/* 8bit Number of CIDs in active BS list */
-	B_UINT8 u8CIDAllocation4activeBSsLength;
+	u8 u8CIDAllocation4activeBSsLength;
 	/* CIDs of BS in the active list */
-	B_UINT8 u8CIDAllocation4activeBSs[MAX_NUM_ACTIVE_BS];
+	u8 u8CIDAllocation4activeBSs[MAX_NUM_ACTIVE_BS];
 	/* Specifies if PDU extended subheader should be applied on every PDU on this conn */
-	B_UINT8 u8PDUSNExtendedSubheader4HarqReordering;
+	u8 u8PDUSNExtendedSubheader4HarqReordering;
 	/* 8bit Specifies whether the connection uses HARQ or not */
-	B_UINT8 u8HARQServiceFlows;
+	u8 u8HARQServiceFlows;
 	/* Specifies the length of Authorization token */
-	B_UINT8 u8AuthTokenLength;
+	u8 u8AuthTokenLength;
 	/* Specifies the Authorization token */
-	B_UINT8 u8AuthToken[AUTH_TOKEN_LENGTH];
+	u8 u8AuthToken[AUTH_TOKEN_LENGTH];
 	/* specifes Number of HARQ channels used to carry data length */
-	B_UINT8 u8HarqChannelMappingLength;
+	u8 u8HarqChannelMappingLength;
 	/* specifes HARQ channels used to carry data */
-	B_UINT8 u8HARQChannelMapping[NUM_HARQ_CHANNELS];
+	u8 u8HARQChannelMapping[NUM_HARQ_CHANNELS];
 	/* 8bit Length of Vendor Specific QoS Params */
-	B_UINT8 u8VendorSpecificQoSParamLength;
+	u8 u8VendorSpecificQoSParamLength;
 	/* 1byte  Vendor Specific QoS Param Of The Service Flow */
-	B_UINT8 u8VendorSpecificQoSParam[VENDOR_SPECIF_QOS_PARAM];
+	u8 u8VendorSpecificQoSParam[VENDOR_SPECIF_QOS_PARAM];
 	/* indicates total classifiers in the SF */
-	B_UINT8 u8TotalClassifiers;  /* < Total number of valid classifiers */
-	B_UINT8 bValid;	/* < Validity flag */
-	B_UINT8 u8Padding;	 /* < Padding byte */
+	u8 u8TotalClassifiers;  /* < Total number of valid classifiers */
+	u8 bValid;	/* < Validity flag */
+	u8 u8Padding;	 /* < Padding byte */
 	/*
 	 * Structure for Convergence SubLayer Types with a maximum of 4 classifiers
 	 */
@@ -248,64 +248,64 @@ struct bcm_connect_mgr_params {
 };
 
 struct bcm_add_request {
-	B_UINT8 u8Type;	/* < Type */
-	B_UINT8 eConnectionDir; /* < Connection direction */
+	u8 u8Type;	/* < Type */
+	u8 eConnectionDir; /* < Connection direction */
 	/* brief 16 bit TID */
-	B_UINT16 u16TID; /* < 16bit TID */
+	u16 u16TID; /* < 16bit TID */
 	/* brief 16bitCID */
-	B_UINT16 u16CID; /* < 16bit CID */
+	u16 u16CID; /* < 16bit CID */
 	/* brief 16bitVCID */
-	B_UINT16 u16VCID; /* < 16bit VCID */
+	u16 u16VCID; /* < 16bit VCID */
 	struct bcm_connect_mgr_params *psfParameterSet; /* < connection manager parameters */
 };
 
 struct bcm_add_indication {
-	B_UINT8 u8Type;	/* < Type */
-	B_UINT8 eConnectionDir;	/* < Connection Direction */
+	u8 u8Type;	/* < Type */
+	u8 eConnectionDir;	/* < Connection Direction */
 	/* brief 16 bit TID */
-	B_UINT16 u16TID; /* < TID */
+	u16 u16TID; /* < TID */
 	/* brief 16bitCID */
-	B_UINT16 u16CID; /* < 16bitCID */
+	u16 u16CID; /* < 16bitCID */
 	/* brief 16bitVCID */
-	B_UINT16 u16VCID; /* < 16bitVCID */
+	u16 u16VCID; /* < 16bitVCID */
 	struct bcm_connect_mgr_params *psfAuthorizedSet; /* Authorized set of connection manager parameters */
 	struct bcm_connect_mgr_params *psfAdmittedSet; /* Admitted set of connection manager parameters */
 	struct bcm_connect_mgr_params *psfActiveSet; /* Activeset of connection manager parameters */
-	B_UINT8 u8CC; /* <Confirmation Code */
-	B_UINT8 u8Padd; /* < 8-bit Padding */
-	B_UINT16 u16Padd; /* < 16 bit Padding */
+	u8 u8CC; /* <Confirmation Code */
+	u8 u8Padd; /* < 8-bit Padding */
+	u16 u16Padd; /* < 16 bit Padding */
 };
 
 struct bcm_del_request {
-	B_UINT8 u8Type; /* < Type */
-	B_UINT8 u8Padding; /* < Padding byte */
-	B_UINT16 u16TID; /* < TID */
+	u8 u8Type; /* < Type */
+	u8 u8Padding; /* < Padding byte */
+	u16 u16TID; /* < TID */
 	/* brief 32bitSFID */
-	B_UINT32 u32SFID; /* < SFID */
+	u32 u32SFID; /* < SFID */
 };
 
 struct bcm_del_indication {
-	B_UINT8 u8Type;	/* < Type */
-	B_UINT8 u8Padding; /* < Padding */
-	B_UINT16 u16TID; /* < TID */
+	u8 u8Type;	/* < Type */
+	u8 u8Padding; /* < Padding */
+	u16 u16TID; /* < TID */
 	/* brief 16bitCID */
-	B_UINT16 u16CID; /* < CID */
+	u16 u16CID; /* < CID */
 	/* brief 16bitVCID */
-	B_UINT16 u16VCID; /* < VCID */
+	u16 u16VCID; /* < VCID */
 	/* brief 32bitSFID */
-	B_UINT32 u32SFID; /* < SFID */
+	u32 u32SFID; /* < SFID */
 	/* brief 8bit Confirmation code */
-	B_UINT8 u8ConfirmationCode; /* < Confirmation code */
-	B_UINT8 u8Padding1[3]; /* < 3 byte Padding */
+	u8 u8ConfirmationCode; /* < Confirmation code */
+	u8 u8Padding1[3]; /* < 3 byte Padding */
 };
 
 struct bcm_stim_sfhostnotify {
-	B_UINT32 SFID; /* SFID of the service flow */
-	B_UINT16 newCID; /* the new/changed CID */
-	B_UINT16 VCID; /* Get new Vcid if the flow has been made active in CID update TLV, but was inactive earlier or the orig vcid */
-	B_UINT8 RetainSF; /* Indication to Host if the SF is to be retained or deleted; if TRUE-retain else delete */
-	B_UINT8 QoSParamSet; /* QoS paramset of the retained SF */
-	B_UINT16 u16reserved; /* For byte alignment */
+	u32 SFID; /* SFID of the service flow */
+	u16 newCID; /* the new/changed CID */
+	u16 VCID; /* Get new Vcid if the flow has been made active in CID update TLV, but was inactive earlier or the orig vcid */
+	u8 RetainSF; /* Indication to Host if the SF is to be retained or deleted; if TRUE-retain else delete */
+	u8 QoSParamSet; /* QoS paramset of the retained SF */
+	u16 u16reserved; /* For byte alignment */
 };
 
 #endif
diff --git a/drivers/staging/bcm/hostmibs.c b/drivers/staging/bcm/hostmibs.c
index 10361bb..3c5f4a5 100644
--- a/drivers/staging/bcm/hostmibs.c
+++ b/drivers/staging/bcm/hostmibs.c
@@ -9,7 +9,7 @@
 
 #include "headers.h"
 
-INT ProcessGetHostMibs(struct bcm_mini_adapter *Adapter, S_MIBS_HOST_STATS_MIBS *pstHostMibs)
+INT ProcessGetHostMibs(struct bcm_mini_adapter *Adapter, struct bcm_host_stats_mibs *pstHostMibs)
 {
 	S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
 	S_PHS_RULE *pstPhsRule = NULL;
@@ -31,7 +31,7 @@ INT ProcessGetHostMibs(struct bcm_mini_adapter *Adapter, S_MIBS_HOST_STATS_MIBS
 			       astClassifierTable[nClassifierIndex],
 			       (PVOID) & Adapter->
 			       astClassifierTable[nClassifierIndex],
-			       sizeof(S_MIBS_CLASSIFIER_RULE));
+			       sizeof(struct bcm_mibs_classifier_rule));
 	}
 
 	/* Copy the SF Table */
@@ -39,7 +39,7 @@ INT ProcessGetHostMibs(struct bcm_mini_adapter *Adapter, S_MIBS_HOST_STATS_MIBS
 		if (Adapter->PackInfo[nSfIndex].bValid) {
 			memcpy((PVOID) & pstHostMibs->astSFtable[nSfIndex],
 			       (PVOID) & Adapter->PackInfo[nSfIndex],
-			       sizeof(S_MIBS_SERVICEFLOW_TABLE));
+				sizeof(struct bcm_mibs_table));
 		} else {
 			/* If index in not valid,
 			 * don't process this for the PHS table.
@@ -94,16 +94,16 @@ INT ProcessGetHostMibs(struct bcm_mini_adapter *Adapter, S_MIBS_HOST_STATS_MIBS
 	return STATUS_SUCCESS;
 }
 
-VOID GetDroppedAppCntrlPktMibs(S_MIBS_HOST_STATS_MIBS *pstHostMibs, struct bcm_tarang_data *pTarang)
+VOID GetDroppedAppCntrlPktMibs(struct bcm_host_stats_mibs *pstHostMibs, struct bcm_tarang_data *pTarang)
 {
 	memcpy(&(pstHostMibs->stDroppedAppCntrlMsgs),
 	       &(pTarang->stDroppedAppCntrlMsgs),
-	       sizeof(S_MIBS_DROPPED_APP_CNTRL_MESSAGES));
+	       sizeof(struct bcm_mibs_dropped_cntrl_msg));
 }
 
 VOID CopyMIBSExtendedSFParameters(struct bcm_mini_adapter *Adapter, struct bcm_connect_mgr_params *psfLocalSet, UINT uiSearchRuleIndex)
 {
-	S_MIBS_EXTSERVICEFLOW_PARAMETERS *t = &Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable;
+	struct bcm_mibs_parameters *t = &Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable;
 
 	t->wmanIfSfid = psfLocalSet->u32SFID;
 	t->wmanIfCmnCpsMaxSustainedRate = psfLocalSet->u32MaxSustainedTrafficRate;
diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c
index b034eb5..eab676f 100644
--- a/drivers/staging/bcm/nvm.c
+++ b/drivers/staging/bcm/nvm.c
@@ -14,25 +14,25 @@ static int BcmGetNvmSize(struct bcm_mini_adapter *Adapter);
 static unsigned int BcmGetFlashSize(struct bcm_mini_adapter *Adapter);
 static NVM_TYPE BcmGetNvmType(struct bcm_mini_adapter *Adapter);
 
-static int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal);
+static int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal);
 
 static B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter, unsigned int uiOffset);
-static int IsSectionWritable(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL Section);
-static int IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL section);
+static int IsSectionWritable(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val Section);
+static int IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section);
 
-static int ReadDSDPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd);
-static int ReadDSDSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd);
-static int ReadISOPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso);
-static int ReadISOSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso);
+static int ReadDSDPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val dsd);
+static int ReadDSDSignature(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val dsd);
+static int ReadISOPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso);
+static int ReadISOSignature(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso);
 
-static int CorruptDSDSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal);
-static int CorruptISOSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal);
+static int CorruptDSDSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal);
+static int CorruptISOSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal);
 static int SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, unsigned int uiSectAlignAddr);
 static int WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter, PUINT pBuff,
-					FLASH2X_SECTION_VAL eFlash2xSectionVal,
+					enum bcm_flash2x_section_val eFlash2xSectionVal,
 					unsigned int uiOffset, unsigned int uiNumBytes);
-static FLASH2X_SECTION_VAL getHighestPriDSD(struct bcm_mini_adapter *Adapter);
-static FLASH2X_SECTION_VAL getHighestPriISO(struct bcm_mini_adapter *Adapter);
+static enum bcm_flash2x_section_val getHighestPriDSD(struct bcm_mini_adapter *Adapter);
+static enum bcm_flash2x_section_val getHighestPriISO(struct bcm_mini_adapter *Adapter);
 
 static int BeceemFlashBulkRead(
 	struct bcm_mini_adapter *Adapter,
@@ -2413,7 +2413,7 @@ static int ConvertEndianOfCSStructure(PFLASH_CS_INFO psFlashCSInfo)
 	return STATUS_SUCCESS;
 }
 
-static int IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL section)
+static int IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section)
 {
 	return (Adapter->uiVendorExtnFlag &&
 		(Adapter->psFlash2xVendorInfo->VendorSection[section].AccessFlags & FLASH2X_SECTION_PRESENT) &&
@@ -2660,14 +2660,14 @@ static NVM_TYPE BcmGetNvmType(struct bcm_mini_adapter *Adapter)
 /*
  * BcmGetSectionValStartOffset - this will calculate the section's starting offset if section val is given
  * @Adapter : Drivers Private Data structure
- * @eFlashSectionVal : Flash secion value defined in enum FLASH2X_SECTION_VAL
+ * @eFlashSectionVal : Flash secion value defined in enum bcm_flash2x_section_val
  *
  * Return value:-
  * On success it return the start offset of the provided section val
  * On Failure -returns STATUS_FAILURE
  */
 
-int BcmGetSectionValStartOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlashSectionVal)
+int BcmGetSectionValStartOffset(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlashSectionVal)
 {
 	/*
 	 * Considering all the section for which end offset can be calculated or directly given
@@ -2752,14 +2752,14 @@ int BcmGetSectionValStartOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTIO
 /*
  * BcmGetSectionValEndOffset - this will calculate the section's Ending offset if section val is given
  * @Adapter : Drivers Private Data structure
- * @eFlashSectionVal : Flash secion value defined in enum FLASH2X_SECTION_VAL
+ * @eFlashSectionVal : Flash secion value defined in enum bcm_flash2x_section_val
  *
  * Return value:-
  * On success it return the end offset of the provided section val
  * On Failure -returns STATUS_FAILURE
  */
 
-int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal)
+int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal)
 {
 	int SectEndOffset = 0;
 
@@ -2837,7 +2837,7 @@ int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_
  * BcmFlash2xBulkRead:- Read API for Flash Map 2.x .
  * @Adapter :Driver Private Data Structure
  * @pBuffer : Buffer where data has to be put after reading
- * @eFlashSectionVal :Flash Section Val defined in FLASH2X_SECTION_VAL
+ * @eFlashSectionVal :Flash Section Val defined in enum bcm_flash2x_section_val
  * @uiOffsetWithinSectionVal :- Offset with in provided section
  * @uiNumBytes : Number of Bytes for Read
  *
@@ -2847,7 +2847,7 @@ int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_
 
 int BcmFlash2xBulkRead(struct bcm_mini_adapter *Adapter,
 		PUINT pBuffer,
-		FLASH2X_SECTION_VAL eFlash2xSectionVal,
+		enum bcm_flash2x_section_val eFlash2xSectionVal,
 		unsigned int uiOffsetWithinSectionVal,
 		unsigned int uiNumBytes)
 {
@@ -2898,7 +2898,7 @@ int BcmFlash2xBulkRead(struct bcm_mini_adapter *Adapter,
  * BcmFlash2xBulkWrite :-API for Writing on the Flash Map 2.x.
  * @Adapter :Driver Private Data Structure
  * @pBuffer : Buffer From where data has to taken for writing
- * @eFlashSectionVal :Flash Section Val defined in FLASH2X_SECTION_VAL
+ * @eFlashSectionVal :Flash Section Val defined in enum bcm_flash2x_section_val
  * @uiOffsetWithinSectionVal :- Offset with in provided section
  * @uiNumBytes : Number of Bytes for Write
  *
@@ -2909,7 +2909,7 @@ int BcmFlash2xBulkRead(struct bcm_mini_adapter *Adapter,
 
 int BcmFlash2xBulkWrite(struct bcm_mini_adapter *Adapter,
 			PUINT pBuffer,
-			FLASH2X_SECTION_VAL eFlash2xSectVal,
+			enum bcm_flash2x_section_val eFlash2xSectVal,
 			unsigned int uiOffset,
 			unsigned int uiNumBytes,
 			unsigned int bVerify)
@@ -2971,7 +2971,7 @@ int BcmFlash2xBulkWrite(struct bcm_mini_adapter *Adapter,
 
 static int BcmGetActiveDSD(struct bcm_mini_adapter *Adapter)
 {
-	FLASH2X_SECTION_VAL uiHighestPriDSD = 0;
+	enum bcm_flash2x_section_val uiHighestPriDSD = 0;
 
 	uiHighestPriDSD = getHighestPriDSD(Adapter);
 	Adapter->eActiveDSD = uiHighestPriDSD;
@@ -3064,7 +3064,7 @@ B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter, unsigned int uiOffset
 		return FALSE;
 }
 
-static int BcmDumpFlash2xSectionBitMap(PFLASH2X_BITMAP psFlash2xBitMap)
+static int BcmDumpFlash2xSectionBitMap(struct bcm_flash2x_bitmap *psFlash2xBitMap)
 {
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
@@ -3099,11 +3099,11 @@ static int BcmDumpFlash2xSectionBitMap(PFLASH2X_BITMAP psFlash2xBitMap)
  * Failure:- negative error code
  */
 
-int BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITMAP psFlash2xBitMap)
+int BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_bitmap *psFlash2xBitMap)
 {
 	PFLASH2X_CS_INFO psFlash2xCSInfo = Adapter->psFlash2xCSInfo;
-	FLASH2X_SECTION_VAL uiHighestPriDSD = 0;
-	FLASH2X_SECTION_VAL uiHighestPriISO = 0;
+	enum bcm_flash2x_section_val uiHighestPriDSD = 0;
+	enum bcm_flash2x_section_val uiHighestPriISO = 0;
 	BOOLEAN SetActiveDSDDone = FALSE;
 	BOOLEAN SetActiveISODone = FALSE;
 
@@ -3349,7 +3349,7 @@ int BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, PFLASH2X_BITM
  *
  */
 
-int BcmSetActiveSection(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectVal)
+int BcmSetActiveSection(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectVal)
 {
 	unsigned int SectImagePriority = 0;
 	int Status = STATUS_SUCCESS;
@@ -3529,10 +3529,10 @@ int BcmSetActiveSection(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eF
  *
  */
 
-int BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
+int BcmCopyISO(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_copy_section sCopySectStrut)
 {
 	PCHAR Buff = NULL;
-	FLASH2X_SECTION_VAL eISOReadPart = 0, eISOWritePart = 0;
+	enum bcm_flash2x_section_val eISOReadPart = 0, eISOWritePart = 0;
 	unsigned int uiReadOffsetWithinPart = 0, uiWriteOffsetWithinPart = 0;
 	unsigned int uiTotalDataToCopy = 0;
 	BOOLEAN IsThisHeaderSector = FALSE;
@@ -3813,7 +3813,7 @@ out:
  *	Failure :-Return negative error code
  */
 
-int BcmFlash2xCorruptSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal)
+int BcmFlash2xCorruptSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal)
 {
 	int Status = STATUS_SUCCESS;
 
@@ -3841,7 +3841,7 @@ int BcmFlash2xCorruptSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL e
  *	Failure :-Return negative error code
  */
 
-int BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlashSectionVal)
+int BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlashSectionVal)
 {
 	unsigned int uiSignature = 0;
 	unsigned int uiOffset = 0;
@@ -3901,7 +3901,7 @@ int BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFl
  * Return values:-Return TRUE is request is valid else FALSE.
  */
 
-int validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, PFLASH2X_READWRITE psFlash2xReadWrite)
+int validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_readwrite *psFlash2xReadWrite)
 {
 	unsigned int uiNumOfBytes = 0;
 	unsigned int uiSectStartOffset = 0;
@@ -4021,8 +4021,8 @@ static int GetFlashBaseAddr(struct bcm_mini_adapter *Adapter)
  */
 
 int BcmCopySection(struct bcm_mini_adapter *Adapter,
-		FLASH2X_SECTION_VAL SrcSection,
-		FLASH2X_SECTION_VAL DstSection,
+		enum bcm_flash2x_section_val SrcSection,
+		enum bcm_flash2x_section_val DstSection,
 		unsigned int offset,
 		unsigned int numOfBytes)
 {
@@ -4264,7 +4264,7 @@ static int BcmDoChipSelect(struct bcm_mini_adapter *Adapter, unsigned int offset
 	return STATUS_SUCCESS;
 }
 
-int ReadDSDSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd)
+int ReadDSDSignature(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val dsd)
 {
 	unsigned int uiDSDsig = 0;
 	/* unsigned int sigoffsetInMap = 0;
@@ -4289,7 +4289,7 @@ int ReadDSDSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd)
 	return uiDSDsig;
 }
 
-int ReadDSDPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd)
+int ReadDSDPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val dsd)
 {
 	/* unsigned int priOffsetInMap = 0 ; */
 	unsigned int uiDSDPri = STATUS_FAILURE;
@@ -4312,11 +4312,11 @@ int ReadDSDPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd)
 	return uiDSDPri;
 }
 
-FLASH2X_SECTION_VAL getHighestPriDSD(struct bcm_mini_adapter *Adapter)
+enum bcm_flash2x_section_val getHighestPriDSD(struct bcm_mini_adapter *Adapter)
 {
 	int DSDHighestPri = STATUS_FAILURE;
 	int DsdPri = 0;
-	FLASH2X_SECTION_VAL HighestPriDSD = 0;
+	enum bcm_flash2x_section_val HighestPriDSD = 0;
 
 	if (IsSectionWritable(Adapter, DSD2)) {
 		DSDHighestPri = ReadDSDPriority(Adapter, DSD2);
@@ -4344,7 +4344,7 @@ FLASH2X_SECTION_VAL getHighestPriDSD(struct bcm_mini_adapter *Adapter)
 	return  HighestPriDSD;
 }
 
-int ReadISOSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso)
+int ReadISOSignature(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso)
 {
 	unsigned int uiISOsig = 0;
 	/* unsigned int sigoffsetInMap = 0;
@@ -4367,7 +4367,7 @@ int ReadISOSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso)
 	return uiISOsig;
 }
 
-int ReadISOPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso)
+int ReadISOPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso)
 {
 	unsigned int ISOPri = STATUS_FAILURE;
 	if (IsSectionWritable(Adapter, iso)) {
@@ -4386,11 +4386,11 @@ int ReadISOPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso)
 	return ISOPri;
 }
 
-FLASH2X_SECTION_VAL getHighestPriISO(struct bcm_mini_adapter *Adapter)
+enum bcm_flash2x_section_val getHighestPriISO(struct bcm_mini_adapter *Adapter)
 {
 	int ISOHighestPri = STATUS_FAILURE;
 	int ISOPri = 0;
-	FLASH2X_SECTION_VAL HighestPriISO = NO_SECTION_VAL;
+	enum bcm_flash2x_section_val HighestPriISO = NO_SECTION_VAL;
 
 	if (IsSectionWritable(Adapter, ISO_IMAGE2)) {
 		ISOHighestPri = ReadISOPriority(Adapter, ISO_IMAGE2);
@@ -4412,7 +4412,7 @@ FLASH2X_SECTION_VAL getHighestPriISO(struct bcm_mini_adapter *Adapter)
 
 int WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter,
 				PUINT pBuff,
-				FLASH2X_SECTION_VAL eFlash2xSectionVal,
+				enum bcm_flash2x_section_val eFlash2xSectionVal,
 				unsigned int uiOffset,
 				unsigned int uiNumBytes)
 {
@@ -4468,7 +4468,7 @@ int WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter,
 	return Status;
 }
 
-BOOLEAN IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL section)
+BOOLEAN IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section)
 {
 	BOOLEAN SectionPresent = FALSE;
 
@@ -4523,7 +4523,7 @@ BOOLEAN IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_
 	return SectionPresent;
 }
 
-int IsSectionWritable(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL Section)
+int IsSectionWritable(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val Section)
 {
 	int offset = STATUS_FAILURE;
 	int Status = FALSE;
@@ -4546,7 +4546,7 @@ int IsSectionWritable(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL Sect
 	return Status;
 }
 
-static int CorruptDSDSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal)
+static int CorruptDSDSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal)
 {
 	PUCHAR pBuff = NULL;
 	unsigned int sig = 0;
@@ -4608,7 +4608,7 @@ static int CorruptDSDSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL e
 	return STATUS_SUCCESS;
 }
 
-static int CorruptISOSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal)
+static int CorruptISOSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal)
 {
 	PUCHAR pBuff = NULL;
 	unsigned int sig = 0;
diff --git a/drivers/staging/bcm/vendorspecificextn.c b/drivers/staging/bcm/vendorspecificextn.c
index 833883c..40be60a 100644
--- a/drivers/staging/bcm/vendorspecificextn.c
+++ b/drivers/staging/bcm/vendorspecificextn.c
@@ -89,7 +89,7 @@ INT vendorextnIoctl(struct bcm_mini_adapter *Adapter, UINT cmd, ULONG arg)
 //
 //------------------------------------------------------------------
 
-INT vendorextnReadSection(PVOID  pContext, PUCHAR pBuffer, FLASH2X_SECTION_VAL SectionVal,
+INT vendorextnReadSection(PVOID  pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
 			UINT offset, UINT numOfBytes)
 {
 	return STATUS_FAILURE;
@@ -114,7 +114,7 @@ INT vendorextnReadSection(PVOID  pContext, PUCHAR pBuffer, FLASH2X_SECTION_VAL S
 //		STATUS_SUCCESS/STATUS_FAILURE
 //
 //------------------------------------------------------------------
-INT vendorextnWriteSection(PVOID  pContext, PUCHAR pBuffer, FLASH2X_SECTION_VAL SectionVal,
+INT vendorextnWriteSection(PVOID  pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
 			UINT offset, UINT numOfBytes, BOOLEAN bVerify)
 {
 	return STATUS_FAILURE;
@@ -138,7 +138,7 @@ INT vendorextnWriteSection(PVOID  pContext, PUCHAR pBuffer, FLASH2X_SECTION_VAL
 //		STATUS_SUCCESS/STATUS_FAILURE
 //
 //------------------------------------------------------------------
-INT vendorextnWriteSectionWithoutErase(PVOID  pContext, PUCHAR pBuffer, FLASH2X_SECTION_VAL SectionVal,
+INT vendorextnWriteSectionWithoutErase(PVOID  pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
 			UINT offset, UINT numOfBytes)
 {
 	return STATUS_FAILURE;
diff --git a/drivers/staging/bcm/vendorspecificextn.h b/drivers/staging/bcm/vendorspecificextn.h
index f237891b..834410e 100644
--- a/drivers/staging/bcm/vendorspecificextn.h
+++ b/drivers/staging/bcm/vendorspecificextn.h
@@ -8,11 +8,11 @@ INT vendorextnGetSectionInfo(PVOID  pContext,PFLASH2X_VENDORSPECIFIC_INFO pVendo
 INT vendorextnExit(struct bcm_mini_adapter *Adapter);
 INT vendorextnInit(struct bcm_mini_adapter *Adapter);
 INT vendorextnIoctl(struct bcm_mini_adapter *Adapter, UINT cmd, ULONG arg);
-INT vendorextnReadSection(PVOID  pContext, PUCHAR pBuffer, FLASH2X_SECTION_VAL SectionVal,
+INT vendorextnReadSection(PVOID  pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
 			UINT offset, UINT numOfBytes);
-INT vendorextnWriteSection(PVOID  pContext, PUCHAR pBuffer, FLASH2X_SECTION_VAL SectionVal,
+INT vendorextnWriteSection(PVOID  pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
 			UINT offset, UINT numOfBytes, BOOLEAN bVerify);
-INT vendorextnWriteSectionWithoutErase(PVOID  pContext, PUCHAR pBuffer, FLASH2X_SECTION_VAL SectionVal,
+INT vendorextnWriteSectionWithoutErase(PVOID  pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
 			UINT offset, UINT numOfBytes);
 
 #endif /*  */
diff --git a/drivers/staging/ccg/ccg.c b/drivers/staging/ccg/ccg.c
index 93e1e2f..ffc5f73 100644
--- a/drivers/staging/ccg/ccg.c
+++ b/drivers/staging/ccg/ccg.c
@@ -1239,7 +1239,7 @@ static int ccg_create_device(struct ccg_dev *dev)
 }
 
 
-static int __init init(void)
+static int __init ccg_init(void)
 {
 	struct ccg_dev *dev;
 	int err;
@@ -1280,13 +1280,13 @@ static int __init init(void)
 
 	return err;
 }
-module_init(init);
+module_init(ccg_init);
 
-static void __exit cleanup(void)
+static void __exit ccg_exit(void)
 {
 	usb_composite_unregister(&ccg_usb_driver);
 	class_destroy(ccg_class);
 	kfree(_ccg_dev);
 	_ccg_dev = NULL;
 }
-module_exit(cleanup);
+module_exit(ccg_exit);
diff --git a/drivers/staging/ccg/u_serial.c b/drivers/staging/ccg/u_serial.c
index 5b3f5ff..373c406 100644
--- a/drivers/staging/ccg/u_serial.c
+++ b/drivers/staging/ccg/u_serial.c
@@ -1140,8 +1140,10 @@ int gserial_setup(struct usb_gadget *g, unsigned count)
 
 	return status;
 fail:
-	while (count--)
+	while (count--) {
+		tty_port_destroy(&ports[count].port->port);
 		kfree(ports[count].port);
+	}
 	put_tty_driver(gs_tty_driver);
 	gs_tty_driver = NULL;
 	return status;
@@ -1195,6 +1197,7 @@ void gserial_cleanup(void)
 
 		WARN_ON(port->port_usb != NULL);
 
+		tty_port_destroy(&port->port);
 		kfree(port);
 	}
 	n_ports = 0;
diff --git a/drivers/staging/ced1401/ced_ioc.c b/drivers/staging/ced1401/ced_ioc.c
index c9492ed..d043471 100644
--- a/drivers/staging/ced1401/ced_ioc.c
+++ b/drivers/staging/ced1401/ced_ioc.c
@@ -341,7 +341,7 @@ bool Is1401(DEVICE_EXTENSION * pdx)
 		}
 
 		if (iReturn == 0)	// if all is OK...
-			iReturn = state == 0;	// then sucess is that the state is 0
+			iReturn = state == 0;	// then success is that the state is 0
 	} else
 		iReturn = 0;	// we failed
 	pdx->bForceReset = false;	// Clear forced reset flag now
@@ -565,7 +565,7 @@ int LineCount(DEVICE_EXTENSION * pdx)
 			if (dwIndex >= INBUF_SZ)	// see if we fall off buff
 				dwIndex = 0;
 		}
-		while (dwIndex != dwEnd);	// go to last avaliable
+		while (dwIndex != dwEnd);	// go to last available
 	}
 
 	spin_unlock_irq(&pdx->charInLock);
@@ -697,8 +697,7 @@ static int SetArea(DEVICE_EXTENSION * pdx, int nArea, char __user * puBuf,
 		return -EFAULT;	// ...then we are done
 
 	// Now allocate space to hold the page pointer and virtual address pointer tables
-	pPages =
-	    (struct page **)kmalloc(len * sizeof(struct page *), GFP_KERNEL);
+	pPages = kmalloc(len * sizeof(struct page *), GFP_KERNEL);
 	if (!pPages) {
 		iReturn = U14ERR_NOMEMORY;
 		goto error;
@@ -913,18 +912,24 @@ int GetTransfer(DEVICE_EXTENSION * pdx, TGET_TX_BLOCK __user * pTX)
 		iReturn = U14ERR_BADAREA;
 	else {
 		// Return the best information we have - we don't have physical addresses
-		TGET_TX_BLOCK tx;
-		memset(&tx, 0, sizeof(tx));	// clean out local work structure
-		tx.size = pdx->rTransDef[dwIdent].dwLength;
-		tx.linear = (long long)((long)pdx->rTransDef[dwIdent].lpvBuff);
-		tx.avail = GET_TX_MAXENTRIES;	// how many blocks we could return
-		tx.used = 1;	// number we actually return
-		tx.entries[0].physical =
-		    (long long)(tx.linear + pdx->StagedOffset);
-		tx.entries[0].size = tx.size;
-
-		if (copy_to_user(pTX, &tx, sizeof(tx)))
+		TGET_TX_BLOCK *tx;
+
+		tx = kzalloc(sizeof(*tx), GFP_KERNEL);
+		if (!tx) {
+			mutex_unlock(&pdx->io_mutex);
+			return -ENOMEM;
+		}
+		tx->size = pdx->rTransDef[dwIdent].dwLength;
+		tx->linear = (long long)((long)pdx->rTransDef[dwIdent].lpvBuff);
+		tx->avail = GET_TX_MAXENTRIES;	// how many blocks we could return
+		tx->used = 1;	// number we actually return
+		tx->entries[0].physical =
+		    (long long)(tx->linear + pdx->StagedOffset);
+		tx->entries[0].size = tx->size;
+
+		if (copy_to_user(pTX, tx, sizeof(*tx)))
 			iReturn = -EFAULT;
+		kfree(tx);
 	}
 	mutex_unlock(&pdx->io_mutex);
 	return iReturn;
@@ -1508,7 +1513,7 @@ int FreeCircBlock(DEVICE_EXTENSION * pdx, TCIRCBLOCK __user * pCB)
 		iReturn = U14ERR_BADAREA;
 
 	if (copy_to_user(pCB, &cb, sizeof(cb)))
-		return -EFAULT;
+		iReturn = -EFAULT;
 
 	mutex_unlock(&pdx->io_mutex);
 	return iReturn;
diff --git a/drivers/staging/ced1401/usb1401.c b/drivers/staging/ced1401/usb1401.c
index 6ba0ef6..a27043a 100644
--- a/drivers/staging/ced1401/usb1401.c
+++ b/drivers/staging/ced1401/usb1401.c
@@ -89,14 +89,11 @@ synchronous non-Urb based transfers.
 #include <linux/mutex.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
-#include <linux/version.h>
-#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) )
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/kref.h>
 #include <linux/uaccess.h>
-#endif
 
 #include "usb1401.h"
 
@@ -123,19 +120,6 @@ MODULE_DEVICE_TABLE(usb, ced_table);
 #define WRITES_IN_FLIGHT	8
 /* arbitrarily chosen */
 
-/* 
-The cause for these errors is that the driver makes use of the functions usb_buffer_alloc() and usb_buffer_free() which got renamed in kernel 2.6.35. This is stated in the Changelog:   USB: rename usb_buffer_alloc() and usb_buffer_free() users
-    For more clearance what the functions actually do,
-      usb_buffer_alloc() is renamed to usb_alloc_coherent()
-      usb_buffer_free()  is renamed to usb_free_coherent()
-   This is needed on Debian 2.6.32-5-amd64
-*/
-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) )
-#define usb_alloc_coherent usb_buffer_alloc
-#define usb_free_coherent  usb_buffer_free
-#define noop_llseek NULL
-#endif
-
 static struct usb_driver ced_driver;
 
 static void ced_delete(struct kref *kref)
@@ -927,9 +911,9 @@ static bool ReadWord(unsigned short *pWord, char *pBuf, unsigned int *pdDone,
 ** ReadHuff
 **
 ** Reads a coded number in and returns it, Code is:
-** If data is in range 0..127 we recieve 1 byte. If data in range 128-16383
-** we recieve two bytes, top bit of first indicates another on its way. If
-** data in range 16383-4194303 we get three bytes, top two bits of first set
+** If data is in range 0..127 we receive 1 byte. If data in range 128-16383
+** we receive two bytes, top bit of first indicates another on its way. If
+** data in range 16384-4194303 we get three bytes, top two bits of first set
 ** to indicate three byte total.
 **
 *****************************************************************************/
@@ -1252,12 +1236,7 @@ int Allowi(DEVICE_EXTENSION * pdx, bool bInCallback)
 ** ulArg    The argument passed in. Note that long is 64-bits in 64-bit system, i.e. it is big
 **          enough for a 64-bit pointer.
 *****************************************************************************/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
 static long ced_ioctl(struct file *file, unsigned int cmd, unsigned long ulArg)
-#else
-static int ced_ioctl(struct inode *node, struct file *file, unsigned int cmd,
-		     unsigned long ulArg)
-#endif
 {
 	int err = 0;
 	DEVICE_EXTENSION *pdx = file->private_data;
@@ -1388,11 +1367,7 @@ static const struct file_operations ced_fops = {
 	.release = ced_release,
 	.flush = ced_flush,
 	.llseek = noop_llseek,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
 	.unlocked_ioctl = ced_ioctl,
-#else
-	.ioctl = ced_ioctl,
-#endif
 };
 
 /*
@@ -1537,7 +1512,7 @@ error:
 static void ced_disconnect(struct usb_interface *interface)
 {
 	DEVICE_EXTENSION *pdx = usb_get_intfdata(interface);
-	int minor = interface->minor;	// save for message at the end
+	int minor = interface->minor;
 	int i;
 
 	usb_set_intfdata(interface, NULL);	// remove the pdx from the interface
@@ -1572,8 +1547,7 @@ void ced_draw_down(DEVICE_EXTENSION * pdx)
 
 	pdx->bInDrawDown = true;
 	time = usb_wait_anchor_empty_timeout(&pdx->submitted, 3000);
-	if (!time)		// if we timed out we kill the urbs
-	{
+	if (!time) {		// if we timed out we kill the urbs
 		usb_kill_anchored_urbs(&pdx->submitted);
 		dev_err(&pdx->interface->dev, "%s timed out", __func__);
 	}
diff --git a/drivers/staging/ced1401/usb1401.h b/drivers/staging/ced1401/usb1401.h
index 331ca98..adb5fa4 100644
--- a/drivers/staging/ced1401/usb1401.h
+++ b/drivers/staging/ced1401/usb1401.h
@@ -165,7 +165,7 @@ typedef struct _DEVICE_EXTENSION
 
     // Parameters relating to a block read\write that is in progress. Some of these values
     //  are equivalent to values in rDMAInfo. The values here are those in use, while those
-    //  in rDMAInfo are those recieved from the 1401 via an escape sequence. If another
+    //  in rDMAInfo are those received from the 1401 via an escape sequence. If another
     //  escape sequence arrives before the previous xfer ends, rDMAInfo values are updated while these
     //  are used to finish off the current transfer.
     volatile short StagedId;            // The transfer area id for this transfer
diff --git a/drivers/staging/ced1401/userspace/use1401.c b/drivers/staging/ced1401/userspace/use1401.c
index d4c6316..38e7c1c 100644
--- a/drivers/staging/ced1401/userspace/use1401.c
+++ b/drivers/staging/ced1401/userspace/use1401.c
@@ -145,7 +145,7 @@
 ** You should add a new one of these to keep things tidy for applications.
 **
 ** DRIVERET_MAX (below) specifies the maximum allowed type code from the
-** 1401 driver; I have set this high to accomodate as yet undesigned 1401
+** 1401 driver; I have set this high to accommodate as yet undesigned 1401
 ** types. Similarly, as long as the command file names follow the ARM,
 ** ARN, ARO sequence, these are calculated by the ExtForType function, so
 ** you don't need to do anything here either.
@@ -160,7 +160,7 @@
 ** have broken backwards compatibility. Minor number changes mean that we
 ** have added new functionality that does not break backwards compatibility.
 ** we starts at 0. Revision changes mean we have fixed something. Each index
-** returns to 0 when a higer one changes.
+** returns to 0 when a higher one changes.
 */
 #define U14LIB_MAJOR 4
 #define U14LIB_MINOR 0
@@ -211,7 +211,7 @@
 
 /*
 ** These are the 1401 type codes returned by the driver, they are a slightly
-** odd sequence & start for reasons of compatability with the DOS driver.
+** odd sequence & start for reasons of compatibility with the DOS driver.
 ** The maximum code value is the upper limit of 1401 device types.
 */
 #define DRIVRET_STD     4       // Codes for 1401 types matching driver values
@@ -2327,7 +2327,7 @@ U14API(short) U14SetTransArea(short hand, WORD wArea, void *pvBuff,
 
 /****************************************************************************
 ** U14SetTransferEvent  Sets an event for notification of application
-** wArea       The tranfer area index, from 0 to MAXAREAS-1
+** wArea       The transfer area index, from 0 to MAXAREAS-1
 **    bEvent      True to create an event, false to remove it
 **    bToHost     Set 0 for notification on to1401 tranfers, 1 for
 **                notification of transfers to the host PC
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index 2093403..7de2a10 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -568,7 +568,6 @@ config COMEDI_8255_PCI
 
 config COMEDI_ADDI_APCI_035
 	tristate "ADDI-DATA APCI_035 support"
-	depends on VIRT_TO_BUS
 	---help---
 	  Enable support for ADDI-DATA APCI_035 cards
 
@@ -577,7 +576,6 @@ config COMEDI_ADDI_APCI_035
 
 config COMEDI_ADDI_APCI_1032
 	tristate "ADDI-DATA APCI_1032 support"
-	depends on VIRT_TO_BUS
 	---help---
 	  Enable support for ADDI-DATA APCI_1032 cards
 
@@ -586,7 +584,6 @@ config COMEDI_ADDI_APCI_1032
 
 config COMEDI_ADDI_APCI_1500
 	tristate "ADDI-DATA APCI_1500 support"
-	depends on VIRT_TO_BUS
 	---help---
 	  Enable support for ADDI-DATA APCI_1500 cards
 
@@ -594,17 +591,17 @@ config COMEDI_ADDI_APCI_1500
 	  called addi_apci_1500.
 
 config COMEDI_ADDI_APCI_1516
-	tristate "ADDI-DATA APCI_1516 support"
-	depends on VIRT_TO_BUS
+	tristate "ADDI-DATA APCI-1016/1516/2016 support"
 	---help---
-	  Enable support for ADDI-DATA APCI_1516 cards
+	  Enable support for ADDI-DATA APCI-1016, APCI-1516 and APCI-2016 boards.
+	  These are 16 channel, optically isolated, digital I/O boards. The 1516
+	  and 2016 boards also have a watchdog for resetting the outputs to "0".
 
 	  To compile this driver as a module, choose M here: the module will be
 	  called addi_apci_1516.
 
 config COMEDI_ADDI_APCI_1564
 	tristate "ADDI-DATA APCI_1564 support"
-	depends on VIRT_TO_BUS
 	---help---
 	  Enable support for ADDI-DATA APCI_1564 cards
 
@@ -613,25 +610,14 @@ config COMEDI_ADDI_APCI_1564
 
 config COMEDI_ADDI_APCI_16XX
 	tristate "ADDI-DATA APCI_16xx support"
-	depends on VIRT_TO_BUS
 	---help---
 	  Enable support for ADDI-DATA APCI_16xx cards
 
 	  To compile this driver as a module, choose M here: the module will be
 	  called addi_apci_16xx.
 
-config COMEDI_ADDI_APCI_2016
-	tristate "ADDI-DATA APCI_2016 support"
-	depends on VIRT_TO_BUS
-	---help---
-	  Enable support for ADDI-DATA APCI_2016 cards
-
-	  To compile this driver as a module, choose M here: the module will be
-	  called addi_apci_2016.
-
 config COMEDI_ADDI_APCI_2032
 	tristate "ADDI-DATA APCI_2032 support"
-	depends on VIRT_TO_BUS
 	---help---
 	  Enable support for ADDI-DATA APCI_2032 cards
 
@@ -640,36 +626,24 @@ config COMEDI_ADDI_APCI_2032
 
 config COMEDI_ADDI_APCI_2200
 	tristate "ADDI-DATA APCI_2200 support"
-	depends on VIRT_TO_BUS
 	---help---
 	  Enable support for ADDI-DATA APCI_2200 cards
 
 	  To compile this driver as a module, choose M here: the module will be
 	  called addi_apci_2200.
 
-config COMEDI_ADDI_APCI_3001
-	tristate "ADDI-DATA APCI_3001 support"
-	depends on VIRT_TO_BUS
-	select COMEDI_FC
-	---help---
-	  Enable support for ADDI-DATA APCI_3001 cards
-
-	  To compile this driver as a module, choose M here: the module will be
-	  called addi_apci_3001.
-
 config COMEDI_ADDI_APCI_3120
-	tristate "ADDI-DATA APCI_3520 support"
+	tristate "ADDI-DATA APCI_3120/3001 support"
 	depends on VIRT_TO_BUS
 	select COMEDI_FC
 	---help---
-	  Enable support for ADDI-DATA APCI_3520 cards
+	  Enable support for ADDI-DATA APCI_3120/3001 cards
 
 	  To compile this driver as a module, choose M here: the module will be
 	  called addi_apci_3120.
 
 config COMEDI_ADDI_APCI_3501
 	tristate "ADDI-DATA APCI_3501 support"
-	depends on VIRT_TO_BUS
 	---help---
 	  Enable support for ADDI-DATA APCI_3501 cards
 
@@ -678,7 +652,6 @@ config COMEDI_ADDI_APCI_3501
 
 config COMEDI_ADDI_APCI_3XXX
 	tristate "ADDI-DATA APCI_3xxx support"
-	depends on VIRT_TO_BUS
 	---help---
 	  Enable support for ADDI-DATA APCI_3xxx cards
 
@@ -761,10 +734,11 @@ config COMEDI_ADV_PCI_DIO
 	  called adv_pci_dio.
 
 config COMEDI_AMPLC_DIO200_PCI
-	tristate "Amplicon PCI215 and PCI272 DIO board support"
+	tristate "Amplicon PCI215/PCI272/PCIe215/PCIe236/PCIe296 DIO support"
 	select COMEDI_AMPLC_DIO200
 	---help---
-	  Enable support for Amplicon PCI215 and PCI272 DIO boards.
+	  Enable support for Amplicon PCI215, PCI272, PCIe215, PCIe236
+	  and PCIe296 DIO boards.
 
 	  To compile this driver as a module, choose M here: the module will be
 	  called amplc_dio200.
@@ -1263,7 +1237,6 @@ config COMEDI_FC
 
 config COMEDI_AMPLC_DIO200
 	tristate
-	select COMEDI_8255
 
 config COMEDI_AMPLC_PC236
 	tristate
diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
index 133f013..c8a8ca1 100644
--- a/drivers/staging/comedi/comedi.h
+++ b/drivers/staging/comedi/comedi.h
@@ -283,6 +283,44 @@ enum configuration_ids {
 	INSN_CONFIG_PWM_GET_H_BRIDGE = 5004
 };
 
+/*
+ * Settings for INSN_CONFIG_DIGITAL_TRIG:
+ * data[0] = INSN_CONFIG_DIGITAL_TRIG
+ * data[1] = trigger ID
+ * data[2] = configuration operation
+ * data[3] = configuration parameter 1
+ * data[4] = configuration parameter 2
+ * data[5] = configuration parameter 3
+ *
+ * operation                           parameter 1   parameter 2   parameter 3
+ * ---------------------------------   -----------   -----------   -----------
+ * COMEDI_DIGITAL_TRIG_DISABLE
+ * COMEDI_DIGITAL_TRIG_ENABLE_EDGES    left-shift    rising-edges  falling-edges
+ * COMEDI_DIGITAL_TRIG_ENABLE_LEVELS   left-shift    high-levels   low-levels
+ *
+ * COMEDI_DIGITAL_TRIG_DISABLE returns the trigger to its default, inactive,
+ * unconfigured state.
+ *
+ * COMEDI_DIGITAL_TRIG_ENABLE_EDGES sets the rising and/or falling edge inputs
+ * that each can fire the trigger.
+ *
+ * COMEDI_DIGITAL_TRIG_ENABLE_LEVELS sets a combination of high and/or low
+ * level inputs that can fire the trigger.
+ *
+ * "left-shift" is useful if the trigger has more than 32 inputs to specify the
+ * first input for this configuration.
+ *
+ * Some sequences of INSN_CONFIG_DIGITAL_TRIG instructions may have a (partly)
+ * accumulative effect, depending on the low-level driver.  This is useful
+ * when setting up a trigger that has more than 32 inputs or has a combination
+ * of edge and level triggered inputs.
+ */
+enum comedi_digital_trig_op {
+	COMEDI_DIGITAL_TRIG_DISABLE = 0,
+	COMEDI_DIGITAL_TRIG_ENABLE_EDGES = 1,
+	COMEDI_DIGITAL_TRIG_ENABLE_LEVELS = 2
+};
+
 enum comedi_io_direction {
 	COMEDI_INPUT = 0,
 	COMEDI_OUTPUT = 1,
@@ -888,7 +926,20 @@ enum amplc_dio_clock_source {
 				   subdevice, preceding counter
 				   subdevice is the last counter
 				   subdevice) */
-	AMPLC_DIO_CLK_EXT	/* per chip external input pin */
+	AMPLC_DIO_CLK_EXT,	/* per chip external input pin */
+	/* the following are "enhanced" clock sources for PCIe models */
+	AMPLC_DIO_CLK_VCC,	/* clock input HIGH */
+	AMPLC_DIO_CLK_GND,	/* clock input LOW */
+	AMPLC_DIO_CLK_PAT_PRESENT, /* "pattern present" signal */
+	AMPLC_DIO_CLK_20MHZ	/* 20 MHz internal clock */
+};
+
+/* Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for
+ * timer subdevice on some Amplicon DIO PCIe boards (amplc_dio200 driver). */
+enum amplc_dio_ts_clock_src {
+	AMPLC_DIO_TS_CLK_1GHZ,	/* 1 ns period with 20 ns granularity */
+	AMPLC_DIO_TS_CLK_1MHZ,	/* 1 us period */
+	AMPLC_DIO_TS_CLK_1KHZ	/* 1 ms period */
 };
 
 /* Values for setting a gate source with INSN_CONFIG_SET_GATE_SRC for
@@ -907,7 +958,17 @@ enum amplc_dio_gate_source {
 	AMPLC_DIO_GAT_RESERVED4,
 	AMPLC_DIO_GAT_RESERVED5,
 	AMPLC_DIO_GAT_RESERVED6,
-	AMPLC_DIO_GAT_RESERVED7
+	AMPLC_DIO_GAT_RESERVED7,
+	/* the following are "enhanced" gate sources for PCIe models */
+	AMPLC_DIO_GAT_NGATN = 6, /* negated per channel gate input */
+	AMPLC_DIO_GAT_OUTNM2,	/* non-negated output of counter
+				   channel minus 2 */
+	AMPLC_DIO_GAT_PAT_PRESENT, /* "pattern present" signal */
+	AMPLC_DIO_GAT_PAT_OCCURRED, /* "pattern occurred" latched */
+	AMPLC_DIO_GAT_PAT_GONE,	/* "pattern gone away" latched */
+	AMPLC_DIO_GAT_NPAT_PRESENT, /* negated "pattern present" */
+	AMPLC_DIO_GAT_NPAT_OCCURRED, /* negated "pattern occurred" */
+	AMPLC_DIO_GAT_NPAT_GONE	/* negated "pattern gone away" */
 };
 
 #endif /* _COMEDI_H */
diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
index 0a5057f..4b7cbfa 100644
--- a/drivers/staging/comedi/comedi_compat32.c
+++ b/drivers/staging/comedi/comedi_compat32.c
@@ -24,7 +24,6 @@
 
 */
 
-#define __NO_VERSION__
 #include <linux/uaccess.h>
 #include <linux/compat.h>
 #include <linux/fs.h>
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index c2a32cf..b7bba17 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -23,7 +23,6 @@
 
 #undef DEBUG
 
-#define __NO_VERSION__
 #include "comedi_compat32.h"
 
 #include <linux/module.h>
@@ -880,6 +879,10 @@ static int check_insn_config_length(struct comedi_insn *insn,
 		if (insn->n == 5)
 			return 0;
 		break;
+	case INSN_CONFIG_DIGITAL_TRIG:
+		if (insn->n == 6)
+			return 0;
+		break;
 		/* by default we allow the insn since we don't have checks for
 		 * all possible cases yet */
 	default:
diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
index cb67a5c..692e1e6 100644
--- a/drivers/staging/comedi/comedidev.h
+++ b/drivers/staging/comedi/comedidev.h
@@ -41,6 +41,7 @@
 #include <linux/io.h>
 #include <linux/timer.h>
 #include <linux/pci.h>
+#include <linux/usb.h>
 
 #include "comedi.h"
 
@@ -54,9 +55,21 @@
 	COMEDI_MINORVERSION, COMEDI_MICROVERSION)
 #define COMEDI_RELEASE VERSION
 
-#define PCI_VENDOR_ID_ADLINK		0x144a
+/*
+ * PCI Vendor IDs not in <linux/pci_ids.h>
+ */
+#define PCI_VENDOR_ID_KOLTER		0x1001
 #define PCI_VENDOR_ID_ICP		0x104c
+#define PCI_VENDOR_ID_AMCC		0x10e8
+#define PCI_VENDOR_ID_DT		0x1116
+#define PCI_VENDOR_ID_IOTECH		0x1616
 #define PCI_VENDOR_ID_CONTEC		0x1221
+#define PCI_VENDOR_ID_CB		0x1307	/* Measurement Computing */
+#define PCI_VENDOR_ID_ADVANTECH		0x13fe
+#define PCI_VENDOR_ID_MEILHAUS		0x1402
+#define PCI_VENDOR_ID_RTD		0x1435
+#define PCI_VENDOR_ID_ADLINK		0x144a
+#define PCI_VENDOR_ID_AMPLICON		0x14dc
 
 #define COMEDI_NUM_MINORS 0x100
 #define COMEDI_NUM_BOARD_MINORS 0x30
@@ -181,8 +194,6 @@ struct comedi_async {
 			unsigned int x);
 };
 
-struct usb_interface;
-
 struct comedi_driver {
 	struct comedi_driver *next;
 
@@ -190,8 +201,7 @@ struct comedi_driver {
 	struct module *module;
 	int (*attach) (struct comedi_device *, struct comedi_devconfig *);
 	void (*detach) (struct comedi_device *);
-	int (*attach_pci) (struct comedi_device *, struct pci_dev *);
-	int (*attach_usb) (struct comedi_device *, struct usb_interface *);
+	int (*auto_attach) (struct comedi_device *, unsigned long);
 
 	/* number of elements in board_name and board_id arrays */
 	unsigned int num_names;
@@ -235,7 +245,7 @@ struct comedi_device {
 	void (*close) (struct comedi_device *dev);
 };
 
-static inline const void *comedi_board(struct comedi_device *dev)
+static inline const void *comedi_board(const struct comedi_device *dev)
 {
 	return dev->board_ptr;
 }
@@ -415,14 +425,6 @@ struct comedi_lrange {
 
 /* some silly little inline functions */
 
-static inline int alloc_private(struct comedi_device *dev, int size)
-{
-	dev->private = kzalloc(size, GFP_KERNEL);
-	if (!dev->private)
-		return -ENOMEM;
-	return 0;
-}
-
 static inline unsigned int bytes_per_sample(const struct comedi_subdevice *subd)
 {
 	if (subd->subdev_flags & SDF_LSAMPL)
@@ -436,9 +438,10 @@ into comedi's buffer */
 static inline void comedi_set_hw_dev(struct comedi_device *dev,
 				     struct device *hw_dev)
 {
+	if (dev->hw_dev == hw_dev)
+		return;
 	if (dev->hw_dev)
 		put_device(dev->hw_dev);
-
 	dev->hw_dev = hw_dev;
 	if (dev->hw_dev) {
 		dev->hw_dev = get_device(dev->hw_dev);
@@ -451,6 +454,12 @@ static inline struct pci_dev *comedi_to_pci_dev(struct comedi_device *dev)
 	return dev->hw_dev ? to_pci_dev(dev->hw_dev) : NULL;
 }
 
+static inline struct usb_interface *
+comedi_to_usb_interface(struct comedi_device *dev)
+{
+	return dev->hw_dev ? to_usb_interface(dev->hw_dev) : NULL;
+}
+
 int comedi_buf_put(struct comedi_async *async, short x);
 int comedi_buf_get(struct comedi_async *async, short *x);
 
@@ -505,11 +514,30 @@ static inline void *comedi_aux_data(int options[], int n)
 int comedi_alloc_subdevice_minor(struct comedi_device *dev,
 				 struct comedi_subdevice *s);
 void comedi_free_subdevice_minor(struct comedi_subdevice *s);
-int comedi_pci_auto_config(struct pci_dev *pcidev,
-			   struct comedi_driver *driver);
-void comedi_pci_auto_unconfig(struct pci_dev *pcidev);
-int comedi_usb_auto_config(struct usb_interface *intf,
-			   struct comedi_driver *driver);
-void comedi_usb_auto_unconfig(struct usb_interface *intf);
+int comedi_auto_config(struct device *hardware_device,
+		       struct comedi_driver *driver, unsigned long context);
+void comedi_auto_unconfig(struct device *hardware_device);
+
+static inline int comedi_pci_auto_config(struct pci_dev *pcidev,
+					 struct comedi_driver *driver)
+{
+	return comedi_auto_config(&pcidev->dev, driver, 0);
+}
+
+static inline void comedi_pci_auto_unconfig(struct pci_dev *pcidev)
+{
+	comedi_auto_unconfig(&pcidev->dev);
+}
+
+static inline int comedi_usb_auto_config(struct usb_interface *intf,
+					 struct comedi_driver *driver)
+{
+	return comedi_auto_config(&intf->dev, driver, 0);
+}
+
+static inline void comedi_usb_auto_unconfig(struct usb_interface *intf)
+{
+	comedi_auto_unconfig(&intf->dev);
+}
 
 #endif /* _COMEDIDEV_H */
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index 1db6bfd..50cf498 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -21,9 +21,6 @@
 
 */
 
-#define _GNU_SOURCE
-
-#define __NO_VERSION__
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -833,11 +830,8 @@ void comedi_reset_async_buf(struct comedi_async *async)
 	async->events = 0;
 }
 
-static int
-comedi_auto_config_helper(struct device *hardware_device,
-			  struct comedi_driver *driver,
-			  int (*attach_wrapper) (struct comedi_device *,
-						 void *), void *context)
+int comedi_auto_config(struct device *hardware_device,
+		       struct comedi_driver *driver, unsigned long context)
 {
 	int minor;
 	struct comedi_device_file_info *dev_file_info;
@@ -847,6 +841,13 @@ comedi_auto_config_helper(struct device *hardware_device,
 	if (!comedi_autoconfig)
 		return 0;
 
+	if (!driver->auto_attach) {
+		dev_warn(hardware_device,
+			 "BUG! comedi driver '%s' has no auto_attach handler\n",
+			 driver->driver_name);
+		return -EINVAL;
+	}
+
 	minor = comedi_alloc_board_minor(hardware_device);
 	if (minor < 0)
 		return minor;
@@ -860,9 +861,9 @@ comedi_auto_config_helper(struct device *hardware_device,
 	else if (!try_module_get(driver->module))
 		ret = -EIO;
 	else {
-		/* set comedi_dev->driver here for attach wrapper */
+		comedi_set_hw_dev(comedi_dev, hardware_device);
 		comedi_dev->driver = driver;
-		ret = (*attach_wrapper)(comedi_dev, context);
+		ret = driver->auto_attach(comedi_dev, context);
 		if (ret < 0) {
 			module_put(driver->module);
 			__comedi_device_detach(comedi_dev);
@@ -876,49 +877,9 @@ comedi_auto_config_helper(struct device *hardware_device,
 		comedi_free_board_minor(minor);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(comedi_auto_config);
 
-static int comedi_auto_config_wrapper(struct comedi_device *dev, void *context)
-{
-	struct comedi_devconfig *it = context;
-	struct comedi_driver *driv = dev->driver;
-
-	if (driv->num_names) {
-		/* look for generic board entry matching driver name, which
-		 * has already been copied to it->board_name */
-		dev->board_ptr = comedi_recognize(driv, it->board_name);
-		if (dev->board_ptr == NULL) {
-			dev_warn(dev->class_dev,
-				 "auto config failed to find board entry '%s' for driver '%s'\n",
-				 it->board_name, driv->driver_name);
-			comedi_report_boards(driv);
-			return -EINVAL;
-		}
-	}
-	if (!driv->attach) {
-		dev_warn(dev->class_dev,
-			 "BUG! driver '%s' using old-style auto config but has no attach handler\n",
-			 driv->driver_name);
-		return -EINVAL;
-	}
-	return driv->attach(dev, it);
-}
-
-static int comedi_auto_config(struct device *hardware_device,
-			      struct comedi_driver *driver, const int *options,
-			      unsigned num_options)
-{
-	struct comedi_devconfig it;
-
-	memset(&it, 0, sizeof(it));
-	strncpy(it.board_name, driver->driver_name, COMEDI_NAMELEN);
-	it.board_name[COMEDI_NAMELEN - 1] = '\0';
-	BUG_ON(num_options > COMEDI_NDEVCONFOPTS);
-	memcpy(it.options, options, num_options * sizeof(int));
-	return comedi_auto_config_helper(hardware_device, driver,
-					 comedi_auto_config_wrapper, &it);
-}
-
-static void comedi_auto_unconfig(struct device *hardware_device)
+void comedi_auto_unconfig(struct device *hardware_device)
 {
 	int minor;
 
@@ -930,6 +891,7 @@ static void comedi_auto_unconfig(struct device *hardware_device)
 	BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
 	comedi_free_board_minor(minor);
 }
+EXPORT_SYMBOL_GPL(comedi_auto_unconfig);
 
 /**
  * comedi_pci_enable() - Enable the PCI device and request the regions.
@@ -965,48 +927,6 @@ void comedi_pci_disable(struct pci_dev *pdev)
 }
 EXPORT_SYMBOL_GPL(comedi_pci_disable);
 
-static int comedi_old_pci_auto_config(struct pci_dev *pcidev,
-				      struct comedi_driver *driver)
-{
-	int options[2];
-
-	/*  pci bus */
-	options[0] = pcidev->bus->number;
-	/*  pci slot */
-	options[1] = PCI_SLOT(pcidev->devfn);
-
-	return comedi_auto_config(&pcidev->dev, driver,
-				  options, ARRAY_SIZE(options));
-}
-
-static int comedi_pci_attach_wrapper(struct comedi_device *dev, void *pcidev)
-{
-	return dev->driver->attach_pci(dev, pcidev);
-}
-
-static int comedi_new_pci_auto_config(struct pci_dev *pcidev,
-				      struct comedi_driver *driver)
-{
-	return comedi_auto_config_helper(&pcidev->dev, driver,
-					 comedi_pci_attach_wrapper, pcidev);
-}
-
-int comedi_pci_auto_config(struct pci_dev *pcidev, struct comedi_driver *driver)
-{
-
-	if (driver->attach_pci)
-		return comedi_new_pci_auto_config(pcidev, driver);
-	else
-		return comedi_old_pci_auto_config(pcidev, driver);
-}
-EXPORT_SYMBOL_GPL(comedi_pci_auto_config);
-
-void comedi_pci_auto_unconfig(struct pci_dev *pcidev)
-{
-	comedi_auto_unconfig(&pcidev->dev);
-}
-EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig);
-
 int comedi_pci_driver_register(struct comedi_driver *comedi_driver,
 		struct pci_driver *pci_driver)
 {
@@ -1040,42 +960,6 @@ EXPORT_SYMBOL_GPL(comedi_pci_driver_unregister);
 
 #if IS_ENABLED(CONFIG_USB)
 
-static int comedi_old_usb_auto_config(struct usb_interface *intf,
-				      struct comedi_driver *driver)
-{
-	return comedi_auto_config(&intf->dev, driver, NULL, 0);
-}
-
-static int comedi_usb_attach_wrapper(struct comedi_device *dev, void *intf)
-{
-	return dev->driver->attach_usb(dev, intf);
-}
-
-static int comedi_new_usb_auto_config(struct usb_interface *intf,
-				      struct comedi_driver *driver)
-{
-	return comedi_auto_config_helper(&intf->dev, driver,
-					 comedi_usb_attach_wrapper, intf);
-}
-
-int comedi_usb_auto_config(struct usb_interface *intf,
-			   struct comedi_driver *driver)
-{
-	BUG_ON(intf == NULL);
-	if (driver->attach_usb)
-		return comedi_new_usb_auto_config(intf, driver);
-	else
-		return comedi_old_usb_auto_config(intf, driver);
-}
-EXPORT_SYMBOL_GPL(comedi_usb_auto_config);
-
-void comedi_usb_auto_unconfig(struct usb_interface *intf)
-{
-	BUG_ON(intf == NULL);
-	comedi_auto_unconfig(&intf->dev);
-}
-EXPORT_SYMBOL_GPL(comedi_usb_auto_unconfig);
-
 int comedi_usb_driver_register(struct comedi_driver *comedi_driver,
 		struct usb_driver *usb_driver)
 {
diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
index a256622..c7aa41a 100644
--- a/drivers/staging/comedi/drivers/8255.c
+++ b/drivers/staging/comedi/drivers/8255.c
@@ -249,28 +249,13 @@ static int subdev_8255_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3 */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
-	if (cmd->scan_begin_arg != 0) {
-		cmd->scan_begin_arg = 0;
-		err++;
-	}
-	if (cmd->convert_arg != 0) {
-		cmd->convert_arg = 0;
-		err++;
-	}
-	if (cmd->scan_end_arg != 1) {
-		cmd->scan_end_arg = 1;
-		err++;
-	}
-	if (cmd->stop_arg != 0) {
-		cmd->stop_arg = 0;
-		err++;
-	}
+	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;
diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c
index d00aff6..e0a7952 100644
--- a/drivers/staging/comedi/drivers/8255_pci.c
+++ b/drivers/staging/comedi/drivers/8255_pci.c
@@ -65,9 +65,6 @@ Configuration Options: not applicable, uses PCI auto config
 #define PCI_DEVICE_ID_ADLINK_PCI7248	0x7248
 #define PCI_DEVICE_ID_ADLINK_PCI7296	0x7296
 
-/* ComputerBoards is now known as Measurement Computing */
-#define PCI_VENDOR_ID_CB		0x1307
-
 #define PCI_DEVICE_ID_CB_PCIDIO48H	0x000b
 #define PCI_DEVICE_ID_CB_PCIDIO24H	0x0014
 #define PCI_DEVICE_ID_CB_PCIDIO96H	0x0017
@@ -216,9 +213,10 @@ static const void *pci_8255_find_boardinfo(struct comedi_device *dev,
 	return NULL;
 }
 
-static int pci_8255_attach_pci(struct comedi_device *dev,
-			       struct pci_dev *pcidev)
+static int pci_8255_auto_attach(struct comedi_device *dev,
+					  unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	const struct pci_8255_boardinfo *board;
 	struct pci_8255_private *devpriv;
 	struct comedi_subdevice *s;
@@ -227,18 +225,16 @@ static int pci_8255_attach_pci(struct comedi_device *dev,
 	int ret;
 	int i;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
-
 	board = pci_8255_find_boardinfo(dev, pcidev);
 	if (!board)
 		return -ENODEV;
 	dev->board_ptr = board;
 	dev->board_name = board->name;
 
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret < 0)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_pci_enable(pcidev, dev->board_name);
 	if (ret)
@@ -308,17 +304,17 @@ static void pci_8255_detach(struct comedi_device *dev)
 static struct comedi_driver pci_8255_driver = {
 	.driver_name	= "8255_pci",
 	.module		= THIS_MODULE,
-	.attach_pci	= pci_8255_attach_pci,
+	.auto_attach	= pci_8255_auto_attach,
 	.detach		= pci_8255_detach,
 };
 
-static int __devinit pci_8255_pci_probe(struct pci_dev *dev,
+static int pci_8255_pci_probe(struct pci_dev *dev,
 					const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &pci_8255_driver);
 }
 
-static void __devexit pci_8255_pci_remove(struct pci_dev *dev)
+static void pci_8255_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -346,7 +342,7 @@ static struct pci_driver pci_8255_pci_driver = {
 	.name		= "8255_pci",
 	.id_table	= pci_8255_pci_table,
 	.probe		= pci_8255_pci_probe,
-	.remove		= __devexit_p(pci_8255_pci_remove),
+	.remove		= pci_8255_pci_remove,
 };
 module_comedi_pci_driver(pci_8255_driver, pci_8255_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile
index a2787c0..0de4d2e 100644
--- a/drivers/staging/comedi/drivers/Makefile
+++ b/drivers/staging/comedi/drivers/Makefile
@@ -62,10 +62,8 @@ obj-$(CONFIG_COMEDI_ADDI_APCI_1500)	+= addi_apci_1500.o
 obj-$(CONFIG_COMEDI_ADDI_APCI_1516)	+= addi_apci_1516.o
 obj-$(CONFIG_COMEDI_ADDI_APCI_1564)	+= addi_apci_1564.o
 obj-$(CONFIG_COMEDI_ADDI_APCI_16XX)	+= addi_apci_16xx.o
-obj-$(CONFIG_COMEDI_ADDI_APCI_2016)	+= addi_apci_2016.o
 obj-$(CONFIG_COMEDI_ADDI_APCI_2032)	+= addi_apci_2032.o
 obj-$(CONFIG_COMEDI_ADDI_APCI_2200)	+= addi_apci_2200.o
-obj-$(CONFIG_COMEDI_ADDI_APCI_3001)	+= addi_apci_3001.o
 obj-$(CONFIG_COMEDI_ADDI_APCI_3120)	+= addi_apci_3120.o
 obj-$(CONFIG_COMEDI_ADDI_APCI_3501)	+= addi_apci_3501.o
 obj-$(CONFIG_COMEDI_ADDI_APCI_3XXX)	+= addi_apci_3xxx.o
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
index b59f2d4..d070208 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c
@@ -18,7 +18,19 @@
   | Description :   APCI-1710 82X54 timer module                          |
 */
 
-#include "APCI1710_82x54.h"
+#define APCI1710_PCI_BUS_CLOCK			0
+#define APCI1710_FRONT_CONNECTOR_INPUT		1
+#define APCI1710_TIMER_READVALUE		0
+#define APCI1710_TIMER_GETOUTPUTLEVEL		1
+#define APCI1710_TIMER_GETPROGRESSSTATUS	2
+#define APCI1710_TIMER_WRITEVALUE		3
+
+#define APCI1710_TIMER_READINTERRUPT		1
+#define APCI1710_TIMER_READALLTIMER		2
+
+#ifndef APCI1710_10MHZ
+#define APCI1710_10MHZ				10
+#endif
 
 /*
 +----------------------------------------------------------------------------+
@@ -218,11 +230,12 @@ int i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s,
 |                    -9: Selection from hardware gate level is wrong         |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev, struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev,
+					  struct comedi_subdevice *s,
+					  struct comedi_insn *insn,
+					  unsigned int *data)
 {
-
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned char b_ModulNbr;
 	unsigned char b_TimerNbr;
@@ -447,11 +460,12 @@ i_ReturnValue=insn->n;
 |                        See function "i_APCI1710_SetBoardIntRoutineX"       |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,
-					   struct comedi_subdevice *s,
-					   struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,
+						 struct comedi_subdevice *s,
+						 struct comedi_insn *insn,
+						 unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_DummyRead;
 	unsigned char b_ModulNbr;
@@ -589,10 +603,12 @@ int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_sub
 |                        "i_APCI1710_InitTimer"                              |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s,
-				     struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,
+					    struct comedi_subdevice *s,
+					    struct comedi_insn *insn,
+					    unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned char b_ModulNbr, b_ReadType;
 	unsigned int *pul_TimerValueArray;
@@ -668,70 +684,6 @@ int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_su
 
 /*
 +----------------------------------------------------------------------------+
-| Function Name     :INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev,
-struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)                   |
-+----------------------------------------------------------------------------+
-| Task              : Read write functions for Timer                                          |
-+----------------------------------------------------------------------------+
-| Input Parameters  :
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice *s,
-			     struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned char b_BitsType;
-	int i_ReturnValue = 0;
-	b_BitsType = data[0];
-
-	printk("\n82X54");
-
-	switch (b_BitsType) {
-	case APCI1710_TIMER_READVALUE:
-		i_ReturnValue = i_APCI1710_ReadTimerValue(dev,
-							  (unsigned char)CR_AREF(insn->chanspec),
-							  (unsigned char)CR_CHAN(insn->chanspec),
-							  (unsigned int *) &data[0]);
-		break;
-
-	case APCI1710_TIMER_GETOUTPUTLEVEL:
-		i_ReturnValue = i_APCI1710_GetTimerOutputLevel(dev,
-							       (unsigned char)CR_AREF(insn->chanspec),
-							       (unsigned char)CR_CHAN(insn->chanspec),
-							       (unsigned char *) &data[0]);
-		break;
-
-	case APCI1710_TIMER_GETPROGRESSSTATUS:
-		i_ReturnValue = i_APCI1710_GetTimerProgressStatus(dev,
-								  (unsigned char)CR_AREF(insn->chanspec),
-								  (unsigned char)CR_CHAN(insn->chanspec),
-								  (unsigned char *)&data[0]);
-		break;
-
-	case APCI1710_TIMER_WRITEVALUE:
-		i_ReturnValue = i_APCI1710_WriteTimerValue(dev,
-							   (unsigned char)CR_AREF(insn->chanspec),
-							   (unsigned char)CR_CHAN(insn->chanspec),
-							   (unsigned int)data[1]);
-
-		break;
-
-	default:
-		printk("Bits Config Parameter Wrong\n");
-		i_ReturnValue = -1;
-	}
-
-	if (i_ReturnValue >= 0)
-		i_ReturnValue = insn->n;
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
 | Function Name     : _INT_     i_APCI1710_ReadTimerValue                    |
 |                                       (unsigned char_     b_BoardHandle,            |
 |                                        unsigned char_     b_ModulNbr,               |
@@ -759,11 +711,12 @@ int i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice
 |                        "i_APCI1710_InitTimer"                              |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_ReadTimerValue(struct comedi_device *dev,
-			      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
-			      unsigned int *pul_TimerValue)
+static int i_APCI1710_ReadTimerValue(struct comedi_device *dev,
+				     unsigned char b_ModulNbr,
+				     unsigned char b_TimerNbr,
+				     unsigned int *pul_TimerValue)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/* Test the module number */
@@ -847,11 +800,12 @@ int i_APCI1710_ReadTimerValue(struct comedi_device *dev,
 	   |                        "i_APCI1710_InitTimer"                              |
 	   +----------------------------------------------------------------------------+
 	 */
-
-int i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
-				   unsigned char b_ModulNbr, unsigned char b_TimerNbr,
-				   unsigned char *pb_OutputLevel)
+static int i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
+					  unsigned char b_ModulNbr,
+					  unsigned char b_TimerNbr,
+					  unsigned char *pb_OutputLevel)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_TimerStatus;
 
@@ -926,11 +880,12 @@ int i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
 |                        "i_APCI1710_InitTimer"                              |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
-				      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
-				      unsigned char *pb_TimerStatus)
+static int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
+					     unsigned char b_ModulNbr,
+					     unsigned char b_TimerNbr,
+					     unsigned char *pb_TimerStatus)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_TimerStatus;
 
@@ -1005,11 +960,12 @@ int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
 |                        "i_APCI1710_InitTimer"                              |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_WriteTimerValue(struct comedi_device *dev,
-			       unsigned char b_ModulNbr, unsigned char b_TimerNbr,
-			       unsigned int ul_WriteValue)
+static int i_APCI1710_WriteTimerValue(struct comedi_device *dev,
+				      unsigned char b_ModulNbr,
+				      unsigned char b_TimerNbr,
+				      unsigned int ul_WriteValue)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/* Test the module number */
@@ -1045,3 +1001,68 @@ int i_APCI1710_WriteTimerValue(struct comedi_device *dev,
 
 	return i_ReturnValue;
 }
+
+/*
++----------------------------------------------------------------------------+
+| Function Name     :INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev,
+struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)                   |
++----------------------------------------------------------------------------+
+| Task              : Read write functions for Timer                                          |
++----------------------------------------------------------------------------+
+| Input Parameters  :
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :
++----------------------------------------------------------------------------+
+*/
+static int i_APCI1710_InsnBitsTimer(struct comedi_device *dev,
+				    struct comedi_subdevice *s,
+				    struct comedi_insn *insn,
+				    unsigned int *data)
+{
+	unsigned char b_BitsType;
+	int i_ReturnValue = 0;
+	b_BitsType = data[0];
+
+	printk("\n82X54");
+
+	switch (b_BitsType) {
+	case APCI1710_TIMER_READVALUE:
+		i_ReturnValue = i_APCI1710_ReadTimerValue(dev,
+							  (unsigned char)CR_AREF(insn->chanspec),
+							  (unsigned char)CR_CHAN(insn->chanspec),
+							  (unsigned int *) &data[0]);
+		break;
+
+	case APCI1710_TIMER_GETOUTPUTLEVEL:
+		i_ReturnValue = i_APCI1710_GetTimerOutputLevel(dev,
+							       (unsigned char)CR_AREF(insn->chanspec),
+							       (unsigned char)CR_CHAN(insn->chanspec),
+							       (unsigned char *) &data[0]);
+		break;
+
+	case APCI1710_TIMER_GETPROGRESSSTATUS:
+		i_ReturnValue = i_APCI1710_GetTimerProgressStatus(dev,
+								  (unsigned char)CR_AREF(insn->chanspec),
+								  (unsigned char)CR_CHAN(insn->chanspec),
+								  (unsigned char *)&data[0]);
+		break;
+
+	case APCI1710_TIMER_WRITEVALUE:
+		i_ReturnValue = i_APCI1710_WriteTimerValue(dev,
+							   (unsigned char)CR_AREF(insn->chanspec),
+							   (unsigned char)CR_CHAN(insn->chanspec),
+							   (unsigned int)data[1]);
+
+		break;
+
+	default:
+		printk("Bits Config Parameter Wrong\n");
+		i_ReturnValue = -1;
+	}
+
+	if (i_ReturnValue >= 0)
+		i_ReturnValue = insn->n;
+	return i_ReturnValue;
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
deleted file mode 100644
index 81346db..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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 APCI1710_PCI_BUS_CLOCK 			0
-#define APCI1710_FRONT_CONNECTOR_INPUT 		1
-#define APCI1710_TIMER_READVALUE		0
-#define APCI1710_TIMER_GETOUTPUTLEVEL		1
-#define APCI1710_TIMER_GETPROGRESSSTATUS	2
-#define APCI1710_TIMER_WRITEVALUE		3
-
-#define APCI1710_TIMER_READINTERRUPT		1
-#define APCI1710_TIMER_READALLTIMER		2
-
-/* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
-#ifndef APCI1710_10MHZ
-#define APCI1710_10MHZ	10
-#endif
-/* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */
-
-/*
- * 82X54 TIMER INISIALISATION FUNCTION
- */
-int i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev, struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,
-					   struct comedi_subdevice *s,
-					   struct comedi_insn *insn, unsigned int *data);
-
-/*
- * 82X54 READ FUNCTION
- */
-int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, struct comedi_subdevice *s,
-				     struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI1710_InsnBitsTimer(struct comedi_device *dev, struct comedi_subdevice *s,
-			     struct comedi_insn *insn, unsigned int *data);
-
-/*
- * 82X54 READ & WRITE FUNCTION
- */
-int i_APCI1710_ReadTimerValue(struct comedi_device *dev,
-			      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
-			      unsigned int *pul_TimerValue);
-
-int i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev,
-				   unsigned char b_ModulNbr, unsigned char b_TimerNbr,
-				   unsigned char *pb_OutputLevel);
-
-int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev,
-				      unsigned char b_ModulNbr, unsigned char b_TimerNbr,
-				      unsigned char *pb_TimerStatus);
-
-/*
- * 82X54 WRITE FUNCTION
- */
-int i_APCI1710_WriteTimerValue(struct comedi_device *dev,
-			       unsigned char b_ModulNbr, unsigned char b_TimerNbr,
-			       unsigned int ul_WriteValue);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
index 482a412..5bd7fe6 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
@@ -52,12 +52,22 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +-----------------------------------------------------------------------+
 */
 
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
-#include "APCI1710_Chrono.h"
+#define APCI1710_30MHZ			30
+#define APCI1710_33MHZ			33
+#define APCI1710_40MHZ			40
+
+#define APCI1710_SINGLE			0
+#define APCI1710_CONTINUOUS		1
+
+#define APCI1710_CHRONO_PROGRESS_STATUS	0
+#define APCI1710_CHRONO_READVALUE	1
+#define APCI1710_CHRONO_CONVERTVALUE	2
+#define APCI1710_CHRONO_READINTERRUPT	3
+
+#define APCI1710_CHRONO_SET_CHANNELON	0
+#define APCI1710_CHRONO_SET_CHANNELOFF	1
+#define APCI1710_CHRONO_READ_CHANNEL	2
+#define APCI1710_CHRONO_READ_PORT	3
 
 /*
 +----------------------------------------------------------------------------+
@@ -130,10 +140,12 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 |                         this CHRONOS version                               |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev,
+					   struct comedi_subdevice *s,
+					   struct comedi_insn *insn,
+					   unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int ul_TimerValue = 0;
 	unsigned int ul_TimingInterval = 0;
@@ -839,10 +851,12 @@ struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)						 |
                       -8: data[0] wrong input    |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
+						   struct comedi_subdevice *s,
+						   struct comedi_insn *insn,
+						   unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned char b_ModulNbr, b_CycleMode, b_InterruptEnable, b_Action;
 	b_ModulNbr = CR_AREF(insn->chanspec);
@@ -1077,87 +1091,6 @@ int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
 
 /*
 +----------------------------------------------------------------------------+
-| Function Name     :INT	i_APCI1710_InsnReadChrono(struct comedi_device *dev,struct comedi_subdevice *s,
-struct comedi_insn *insn,unsigned int *data)                   |
-+----------------------------------------------------------------------------+
-| Task              : Read  functions for Timer                                     |
-+----------------------------------------------------------------------------+
-| Input Parameters  :
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned char b_ReadType;
-	int i_ReturnValue = insn->n;
-
-	b_ReadType = CR_CHAN(insn->chanspec);
-
-	switch (b_ReadType) {
-	case APCI1710_CHRONO_PROGRESS_STATUS:
-		i_ReturnValue = i_APCI1710_GetChronoProgressStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
-		break;
-
-	case APCI1710_CHRONO_READVALUE:
-		i_ReturnValue = i_APCI1710_ReadChronoValue(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned int) insn->unused[0],
-			(unsigned char *) &data[0], (unsigned int *) &data[1]);
-		break;
-
-	case APCI1710_CHRONO_CONVERTVALUE:
-		i_ReturnValue = i_APCI1710_ConvertChronoValue(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned int) insn->unused[0],
-			(unsigned int *) &data[0],
-			(unsigned char *) &data[1],
-			(unsigned char *) &data[2],
-			(unsigned int *) &data[3],
-			(unsigned int *) &data[4], (unsigned int *) &data[5]);
-		break;
-
-	case APCI1710_CHRONO_READINTERRUPT:
-		printk("In Chrono Read Interrupt\n");
-
-		data[0] = devpriv->s_InterruptParameters.
-			s_FIFOInterruptParameters[devpriv->
-			s_InterruptParameters.ui_Read].b_OldModuleMask;
-		data[1] = devpriv->s_InterruptParameters.
-			s_FIFOInterruptParameters[devpriv->
-			s_InterruptParameters.ui_Read].ul_OldInterruptMask;
-		data[2] = devpriv->s_InterruptParameters.
-			s_FIFOInterruptParameters[devpriv->
-			s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
-
-			     /**************************/
-		/* Increment the read FIFO */
-			     /***************************/
-
-		devpriv->
-			s_InterruptParameters.
-			ui_Read = (devpriv->
-			s_InterruptParameters.
-			ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
-		break;
-
-	default:
-		printk("ReadType Parameter wrong\n");
-	}
-
-	if (i_ReturnValue >= 0)
-		i_ReturnValue = insn->n;
-	return i_ReturnValue;
-
-}
-
-/*
-+----------------------------------------------------------------------------+
 | Function Name     : _INT_ i_APCI1710_GetChronoProgressStatus               |
 |                               (unsigned char_    b_BoardHandle,                     |
 |                                unsigned char_    b_ModulNbr,                        |
@@ -1193,10 +1126,11 @@ int i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice
 |                         "i_APCI1710_InitChrono"                            |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char *pb_ChronoStatus)
+static int i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
+					      unsigned char b_ModulNbr,
+					      unsigned char *pb_ChronoStatus)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_Status;
 
@@ -1354,11 +1288,13 @@ int i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
 |                         directly the chronometer measured timing.          |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_ReadChronoValue(struct comedi_device *dev,
-	unsigned char b_ModulNbr,
-	unsigned int ui_TimeOut, unsigned char *pb_ChronoStatus, unsigned int *pul_ChronoValue)
+static int i_APCI1710_ReadChronoValue(struct comedi_device *dev,
+				      unsigned char b_ModulNbr,
+				      unsigned int ui_TimeOut,
+				      unsigned char *pb_ChronoStatus,
+				      unsigned int *pul_ChronoValue)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_Status;
 	unsigned int dw_TimeOut = 0;
@@ -1617,15 +1553,17 @@ int i_APCI1710_ReadChronoValue(struct comedi_device *dev,
 |                         "i_APCI1710_InitChrono"                            |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
-	unsigned char b_ModulNbr,
-	unsigned int ul_ChronoValue,
-	unsigned int *pul_Hour,
-	unsigned char *pb_Minute,
-	unsigned char *pb_Second,
-	unsigned int *pui_MilliSecond, unsigned int *pui_MicroSecond, unsigned int *pui_NanoSecond)
+static int i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
+					 unsigned char b_ModulNbr,
+					 unsigned int ul_ChronoValue,
+					 unsigned int *pul_Hour,
+					 unsigned char *pb_Minute,
+					 unsigned char *pb_Second,
+					 unsigned int *pui_MilliSecond,
+					 unsigned int *pui_MicroSecond,
+					 unsigned int *pui_NanoSecond)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	double d_Hour;
 	double d_Minute;
@@ -1756,6 +1694,89 @@ int i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
 
 /*
 +----------------------------------------------------------------------------+
+| Function Name     :INT	i_APCI1710_InsnReadChrono(struct comedi_device *dev,struct comedi_subdevice *s,
+struct comedi_insn *insn,unsigned int *data)                   |
++----------------------------------------------------------------------------+
+| Task              : Read  functions for Timer                                     |
++----------------------------------------------------------------------------+
+| Input Parameters  :
++----------------------------------------------------------------------------+
+| Output Parameters : -                                                      |
++----------------------------------------------------------------------------+
+| Return Value      :
++----------------------------------------------------------------------------+
+*/
+static int i_APCI1710_InsnReadChrono(struct comedi_device *dev,
+				     struct comedi_subdevice *s,
+				     struct comedi_insn *insn,
+				     unsigned int *data)
+{
+	struct addi_private *devpriv = dev->private;
+	unsigned char b_ReadType;
+	int i_ReturnValue = insn->n;
+
+	b_ReadType = CR_CHAN(insn->chanspec);
+
+	switch (b_ReadType) {
+	case APCI1710_CHRONO_PROGRESS_STATUS:
+		i_ReturnValue = i_APCI1710_GetChronoProgressStatus(dev,
+			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
+		break;
+
+	case APCI1710_CHRONO_READVALUE:
+		i_ReturnValue = i_APCI1710_ReadChronoValue(dev,
+			(unsigned char) CR_AREF(insn->chanspec),
+			(unsigned int) insn->unused[0],
+			(unsigned char *) &data[0], (unsigned int *) &data[1]);
+		break;
+
+	case APCI1710_CHRONO_CONVERTVALUE:
+		i_ReturnValue = i_APCI1710_ConvertChronoValue(dev,
+			(unsigned char) CR_AREF(insn->chanspec),
+			(unsigned int) insn->unused[0],
+			(unsigned int *) &data[0],
+			(unsigned char *) &data[1],
+			(unsigned char *) &data[2],
+			(unsigned int *) &data[3],
+			(unsigned int *) &data[4], (unsigned int *) &data[5]);
+		break;
+
+	case APCI1710_CHRONO_READINTERRUPT:
+		printk("In Chrono Read Interrupt\n");
+
+		data[0] = devpriv->s_InterruptParameters.
+			s_FIFOInterruptParameters[devpriv->
+			s_InterruptParameters.ui_Read].b_OldModuleMask;
+		data[1] = devpriv->s_InterruptParameters.
+			s_FIFOInterruptParameters[devpriv->
+			s_InterruptParameters.ui_Read].ul_OldInterruptMask;
+		data[2] = devpriv->s_InterruptParameters.
+			s_FIFOInterruptParameters[devpriv->
+			s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
+
+			     /**************************/
+		/* Increment the read FIFO */
+			     /***************************/
+
+		devpriv->
+			s_InterruptParameters.
+			ui_Read = (devpriv->
+			s_InterruptParameters.
+			ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
+		break;
+
+	default:
+		printk("ReadType Parameter wrong\n");
+	}
+
+	if (i_ReturnValue >= 0)
+		i_ReturnValue = insn->n;
+	return i_ReturnValue;
+
+}
+
+/*
++----------------------------------------------------------------------------+
 | Function Name     : int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,struct comedi_subdevice *s,
 	struct comedi_insn *insn,unsigned int *data)                    |
 +----------------------------------------------------------------------------+
@@ -1874,10 +1895,12 @@ int i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
 |                         "i_APCI1710_InitChrono"                            |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
+					      struct comedi_subdevice *s,
+					      struct comedi_insn *insn,
+					      unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned char b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType;
 	unsigned int dw_Status;
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
deleted file mode 100644
index 29bad1d..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data-com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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 APCI1710_30MHZ			30
-#define APCI1710_33MHZ			33
-#define APCI1710_40MHZ			40
-
-#define APCI1710_SINGLE			0
-#define APCI1710_CONTINUOUS		1
-
-#define APCI1710_CHRONO_PROGRESS_STATUS	0
-#define APCI1710_CHRONO_READVALUE	1
-#define APCI1710_CHRONO_CONVERTVALUE	2
-#define APCI1710_CHRONO_READINTERRUPT	3
-
-#define APCI1710_CHRONO_SET_CHANNELON	0
-#define APCI1710_CHRONO_SET_CHANNELOFF	1
-#define APCI1710_CHRONO_READ_CHANNEL	2
-#define APCI1710_CHRONO_READ_PORT	3
-
-/*
- * CHRONOMETER INISIALISATION FUNCTION
- */
-int i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev, struct comedi_subdevice *s,
-				    struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev,
-					    struct comedi_subdevice *s,
-					    struct comedi_insn *insn,
-					    unsigned int *data);
-
-/*
- * CHRONOMETER READ FUNCTION
- */
-int i_APCI1710_InsnReadChrono(struct comedi_device *dev, struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev,
-				       unsigned char b_ModulNbr, unsigned char *pb_ChronoStatus);
-
-int i_APCI1710_ReadChronoValue(struct comedi_device *dev,
-			       unsigned char b_ModulNbr,
-			       unsigned int ui_TimeOut, unsigned char *pb_ChronoStatus,
-			       unsigned int *pul_ChronoValue);
-
-int i_APCI1710_ConvertChronoValue(struct comedi_device *dev,
-				  unsigned char b_ModulNbr,
-				  unsigned int ul_ChronoValue,
-				  unsigned int *pul_Hour,
-				  unsigned char *pb_Minute,
-				  unsigned char *pb_Second,
-				  unsigned int *pui_MilliSecond, unsigned int *pui_MicroSecond,
-				  unsigned int *pui_NanoSecond);
-
-/*
- * CHRONOMETER DIGITAL INPUT OUTPUT FUNCTION
- */
-int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,
-				       struct comedi_subdevice *s, struct comedi_insn *insn,
-				       unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
index 07108f9..6b38ce7 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
@@ -52,12 +52,16 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +-----------------------------------------------------------------------+
 */
 
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
-#include "APCI1710_Dig_io.h"
+/* Digital Output ON or OFF */
+#define APCI1710_ON			1
+#define APCI1710_OFF			0
+
+/* Digital I/O */
+#define APCI1710_INPUT			0
+#define APCI1710_OUTPUT			1
+
+#define APCI1710_DIGIO_MEMORYONOFF	0x10
+#define APCI1710_DIGIO_INIT		0x11
 
 /*
 +----------------------------------------------------------------------------+
@@ -99,9 +103,12 @@ Activates and deactivates the digital output memory.
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev,
+					  struct comedi_subdevice *s,
+					  struct comedi_insn *insn,
+					  unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned char b_ModulNbr, b_ChannelAMode, b_ChannelBMode;
 	unsigned char b_MemoryOnOff, b_ConfigType;
 	int i_ReturnValue = 0;
@@ -293,9 +300,12 @@ int i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, struct comedi_subd
 * unsigned char_ b_ModulNbr, unsigned char_ b_InputChannel,
 * unsigned char *_ pb_ChannelStatus)
 */
-int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
+						struct comedi_subdevice *s,
+						struct comedi_insn *insn,
+						unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_StatusReg;
 	unsigned char b_ModulNbr, b_InputChannel;
@@ -481,9 +491,12 @@ int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
 * _INT_ i_APCI1710_SetDigitalIOChlOn (unsigned char_ b_BoardHandle,
 * unsigned char_ b_ModulNbr, unsigned char_ b_OutputChannel)
 */
-int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
+						 struct comedi_subdevice *s,
+						 struct comedi_insn *insn,
+						 unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_WriteValue = 0;
 	unsigned char b_ModulNbr, b_OutputChannel;
@@ -731,9 +744,12 @@ int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
  * b_BoardHandle, unsigned char_ b_ModulNbr, unsigned char_
  * b_PortValue)
 */
-int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,
+						 struct comedi_subdevice *s,
+						 struct comedi_insn *insn,
+						 unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_WriteValue = 0;
 	unsigned int dw_StatusReg;
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
deleted file mode 100644
index cc3973d..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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 APCI1710_ON			1	/* Digital  Output ON or OFF */
-#define APCI1710_OFF			0
-
-#define APCI1710_INPUT			0	/* Digital I/O */
-#define APCI1710_OUTPUT			1
-
-#define APCI1710_DIGIO_MEMORYONOFF	0x10
-#define APCI1710_DIGIO_INIT		0x11
-
-/*
- * DIGITAL I/O INISIALISATION FUNCTION
- */
-int i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data);
-
-/*
- * INPUT OUTPUT  FUNCTIONS
- */
-int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,
-					 struct comedi_subdevice *s,
-					 struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev,
-					  struct comedi_subdevice *s,
-					  struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,
-					  struct comedi_subdevice *s,
-					  struct comedi_insn *insn, unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
index 14b13ea..70a7f95 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
@@ -51,93 +51,121 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +-----------------------------------------------------------------------+
 */
 
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
-
-#include "APCI1710_INCCPT.h"
-
-/*
-+----------------------------------------------------------------------------+
-| int	i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
-struct comedi_insn *insn,unsigned int *data)
-
-+----------------------------------------------------------------------------+
-| Task              : Configuration function for INC_CPT                             |
-+----------------------------------------------------------------------------+
-| Input Parameters  :														 |
-+----------------------------------------------------------------------------+
-| Output Parameters : *data
-+----------------------------------------------------------------------------+
-| Return Value      :                 |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int ui_ConfigType;
-	int i_ReturnValue = 0;
-	ui_ConfigType = CR_CHAN(insn->chanspec);
-
-	printk("\nINC_CPT");
-
-	devpriv->tsk_Current = current;	/*  Save the current process task structure */
-	switch (ui_ConfigType) {
-	case APCI1710_INCCPT_INITCOUNTER:
-		i_ReturnValue = i_APCI1710_InitCounter(dev,
-			CR_AREF(insn->chanspec),
-			(unsigned char) data[0],
-			(unsigned char) data[1],
-			(unsigned char) data[2], (unsigned char) data[3], (unsigned char) data[4]);
-		break;
-
-	case APCI1710_INCCPT_COUNTERAUTOTEST:
-		i_ReturnValue = i_APCI1710_CounterAutoTest(dev,
-			(unsigned char *) &data[0]);
-		break;
-
-	case APCI1710_INCCPT_INITINDEX:
-		i_ReturnValue = i_APCI1710_InitIndex(dev,
-			CR_AREF(insn->chanspec),
-			(unsigned char) data[0],
-			(unsigned char) data[1], (unsigned char) data[2], (unsigned char) data[3]);
-		break;
-
-	case APCI1710_INCCPT_INITREFERENCE:
-		i_ReturnValue = i_APCI1710_InitReference(dev,
-			CR_AREF(insn->chanspec), (unsigned char) data[0]);
-		break;
-
-	case APCI1710_INCCPT_INITEXTERNALSTROBE:
-		i_ReturnValue = i_APCI1710_InitExternalStrobe(dev,
-			CR_AREF(insn->chanspec),
-			(unsigned char) data[0], (unsigned char) data[1]);
-		break;
-
-	case APCI1710_INCCPT_INITCOMPARELOGIC:
-		i_ReturnValue = i_APCI1710_InitCompareLogic(dev,
-			CR_AREF(insn->chanspec), (unsigned int) data[0]);
-		break;
-
-	case APCI1710_INCCPT_INITFREQUENCYMEASUREMENT:
-		i_ReturnValue = i_APCI1710_InitFrequencyMeasurement(dev,
-			CR_AREF(insn->chanspec),
-			(unsigned char) data[0],
-			(unsigned char) data[1], (unsigned int) data[2], (unsigned int *) &data[0]);
-		break;
-
-	default:
-		printk("Insn Config : Config Parameter Wrong\n");
-
-	}
-
-	if (i_ReturnValue >= 0)
-		i_ReturnValue = insn->n;
-	return i_ReturnValue;
-}
+#define APCI1710_16BIT_COUNTER			0x10
+#define APCI1710_32BIT_COUNTER			0x0
+#define APCI1710_QUADRUPLE_MODE			0x0
+#define APCI1710_DOUBLE_MODE			0x3
+#define APCI1710_SIMPLE_MODE			0xF
+#define APCI1710_DIRECT_MODE			0x80
+#define APCI1710_HYSTERESIS_ON			0x60
+#define APCI1710_HYSTERESIS_OFF			0x0
+#define APCI1710_INCREMENT			0x60
+#define APCI1710_DECREMENT			0x0
+#define APCI1710_LATCH_COUNTER			0x1
+#define APCI1710_CLEAR_COUNTER			0x0
+#define APCI1710_LOW				0x0
+#define APCI1710_HIGH				0x1
+
+/*********************/
+/* Version 0600-0229 */
+/*********************/
+#define APCI1710_HIGH_EDGE_CLEAR_COUNTER		0x0
+#define APCI1710_HIGH_EDGE_LATCH_COUNTER		0x1
+#define APCI1710_LOW_EDGE_CLEAR_COUNTER			0x2
+#define APCI1710_LOW_EDGE_LATCH_COUNTER			0x3
+#define APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER	0x4
+#define APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER	0x5
+#define APCI1710_SOURCE_0				0x0
+#define APCI1710_SOURCE_1				0x1
+
+#define APCI1710_30MHZ				30
+#define APCI1710_33MHZ				33
+#define APCI1710_40MHZ				40
+
+#define APCI1710_ENABLE_LATCH_INT    		0x80
+#define APCI1710_DISABLE_LATCH_INT   		(~APCI1710_ENABLE_LATCH_INT)
+
+#define APCI1710_INDEX_LATCH_COUNTER		0x10
+#define APCI1710_INDEX_AUTO_MODE		0x8
+#define APCI1710_ENABLE_INDEX			0x4
+#define APCI1710_DISABLE_INDEX			(~APCI1710_ENABLE_INDEX)
+#define APCI1710_ENABLE_LATCH_AND_CLEAR		0x8
+#define APCI1710_DISABLE_LATCH_AND_CLEAR	(~APCI1710_ENABLE_LATCH_AND_CLEAR)
+#define APCI1710_SET_LOW_INDEX_LEVEL		0x4
+#define APCI1710_SET_HIGH_INDEX_LEVEL		(~APCI1710_SET_LOW_INDEX_LEVEL)
+#define APCI1710_INVERT_INDEX_RFERENCE		0x2
+#define APCI1710_DEFAULT_INDEX_RFERENCE         (~APCI1710_INVERT_INDEX_RFERENCE)
+
+#define APCI1710_ENABLE_INDEX_INT		0x1
+#define APCI1710_DISABLE_INDEX_INT		(~APCI1710_ENABLE_INDEX_INT)
+
+#define APCI1710_ENABLE_FREQUENCY		0x4
+#define APCI1710_DISABLE_FREQUENCY		(~APCI1710_ENABLE_FREQUENCY)
+
+#define APCI1710_ENABLE_FREQUENCY_INT		0x8
+#define APCI1710_DISABLE_FREQUENCY_INT		(~APCI1710_ENABLE_FREQUENCY_INT)
+
+#define APCI1710_ENABLE_40MHZ_FREQUENCY		0x40
+#define APCI1710_DISABLE_40MHZ_FREQUENCY	(~APCI1710_ENABLE_40MHZ_FREQUENCY)
+
+#define APCI1710_ENABLE_40MHZ_FILTER		0x80
+#define APCI1710_DISABLE_40MHZ_FILTER		(~APCI1710_ENABLE_40MHZ_FILTER)
+
+#define APCI1710_ENABLE_COMPARE_INT		0x2
+#define APCI1710_DISABLE_COMPARE_INT		(~APCI1710_ENABLE_COMPARE_INT)
+
+#define APCI1710_ENABLE_INDEX_ACTION		0x20
+#define APCI1710_DISABLE_INDEX_ACTION		(~APCI1710_ENABLE_INDEX_ACTION)
+#define APCI1710_REFERENCE_HIGH			0x40
+#define APCI1710_REFERENCE_LOW			(~APCI1710_REFERENCE_HIGH)
+
+#define APCI1710_TOR_GATE_LOW			0x40
+#define APCI1710_TOR_GATE_HIGH			(~APCI1710_TOR_GATE_LOW)
+
+/* INSN CONFIG */
+#define	APCI1710_INCCPT_INITCOUNTER			100
+#define APCI1710_INCCPT_COUNTERAUTOTEST			101
+#define APCI1710_INCCPT_INITINDEX			102
+#define APCI1710_INCCPT_INITREFERENCE			103
+#define APCI1710_INCCPT_INITEXTERNALSTROBE		104
+#define APCI1710_INCCPT_INITCOMPARELOGIC		105
+#define APCI1710_INCCPT_INITFREQUENCYMEASUREMENT	106
+
+/* INSN READ */
+#define APCI1710_INCCPT_READLATCHREGISTERSTATUS		200
+#define APCI1710_INCCPT_READLATCHREGISTERVALUE		201
+#define APCI1710_INCCPT_READ16BITCOUNTERVALUE		202
+#define APCI1710_INCCPT_READ32BITCOUNTERVALUE		203
+#define APCI1710_INCCPT_GETINDEXSTATUS			204
+#define APCI1710_INCCPT_GETREFERENCESTATUS		205
+#define APCI1710_INCCPT_GETUASSTATUS			206
+#define APCI1710_INCCPT_GETCBSTATUS			207
+#define APCI1710_INCCPT_GET16BITCBSTATUS		208
+#define APCI1710_INCCPT_GETUDSTATUS			209
+#define APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS	210
+#define APCI1710_INCCPT_READFREQUENCYMEASUREMENT	211
+#define APCI1710_INCCPT_READINTERRUPT			212
+
+/* INSN BITS */
+#define APCI1710_INCCPT_CLEARCOUNTERVALUE		300
+#define APCI1710_INCCPT_CLEARALLCOUNTERVALUE		301
+#define APCI1710_INCCPT_SETINPUTFILTER			302
+#define APCI1710_INCCPT_LATCHCOUNTER			303
+#define APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE	304
+#define APCI1710_INCCPT_SETDIGITALCHLON			305
+#define APCI1710_INCCPT_SETDIGITALCHLOFF		306
+
+/* INSN WRITE */
+#define APCI1710_INCCPT_ENABLELATCHINTERRUPT		400
+#define APCI1710_INCCPT_DISABLELATCHINTERRUPT		401
+#define APCI1710_INCCPT_WRITE16BITCOUNTERVALUE		402
+#define APCI1710_INCCPT_WRITE32BITCOUNTERVALUE		403
+#define APCI1710_INCCPT_ENABLEINDEX			404
+#define APCI1710_INCCPT_DISABLEINDEX			405
+#define APCI1710_INCCPT_ENABLECOMPARELOGIC		406
+#define APCI1710_INCCPT_DISABLECOMPARELOGIC		407
+#define APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT	408
+#define APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT	409
 
 /*
 +----------------------------------------------------------------------------+
@@ -298,14 +326,15 @@ int i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, struct comedi_subdevi
 |                        wrong.                                              |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_InitCounter(struct comedi_device *dev,
-	unsigned char b_ModulNbr,
-	unsigned char b_CounterRange,
-	unsigned char b_FirstCounterModus,
-	unsigned char b_FirstCounterOption,
-	unsigned char b_SecondCounterModus, unsigned char b_SecondCounterOption)
+static int i_APCI1710_InitCounter(struct comedi_device *dev,
+				  unsigned char b_ModulNbr,
+				  unsigned char b_CounterRange,
+				  unsigned char b_FirstCounterModus,
+				  unsigned char b_FirstCounterOption,
+				  unsigned char b_SecondCounterModus,
+				  unsigned char b_SecondCounterOption)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/*******************************/
@@ -544,9 +573,10 @@ int i_APCI1710_InitCounter(struct comedi_device *dev,
 |                     -2: No counter module found                            |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_CounterAutoTest(struct comedi_device *dev, unsigned char *pb_TestStatus)
+static int i_APCI1710_CounterAutoTest(struct comedi_device *dev,
+				      unsigned char *pb_TestStatus)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned char b_ModulCpt = 0;
 	int i_ReturnValue = 0;
 	unsigned int dw_LathchValue;
@@ -707,12 +737,14 @@ int i_APCI1710_CounterAutoTest(struct comedi_device *dev, unsigned char *pb_Test
 |                         See function "i_APCI1710_SetBoardIntRoutineX"      |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_InitIndex(struct comedi_device *dev,
-	unsigned char b_ModulNbr,
-	unsigned char b_ReferenceAction,
-	unsigned char b_IndexOperation, unsigned char b_AutoMode, unsigned char b_InterruptEnable)
+static int i_APCI1710_InitIndex(struct comedi_device *dev,
+				unsigned char b_ModulNbr,
+				unsigned char b_ReferenceAction,
+				unsigned char b_IndexOperation,
+				unsigned char b_AutoMode,
+				unsigned char b_InterruptEnable)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -1151,10 +1183,11 @@ int i_APCI1710_InitIndex(struct comedi_device *dev,
 |                     -4: Reference level parameter is wrong                 |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_InitReference(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char b_ReferenceLevel)
+static int i_APCI1710_InitReference(struct comedi_device *dev,
+				    unsigned char b_ModulNbr,
+				    unsigned char b_ReferenceLevel)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -1276,10 +1309,12 @@ int i_APCI1710_InitReference(struct comedi_device *dev,
 |                     -5: External strobe level parameter is wrong           |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_InitExternalStrobe(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char b_ExternalStrobe, unsigned char b_ExternalStrobeLevel)
+static int i_APCI1710_InitExternalStrobe(struct comedi_device *dev,
+					 unsigned char b_ModulNbr,
+					 unsigned char b_ExternalStrobe,
+					 unsigned char b_ExternalStrobeLevel)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -1390,10 +1425,11 @@ int i_APCI1710_InitExternalStrobe(struct comedi_device *dev,
 	   |                         "i_APCI1710_InitCounter"                           |
 	   +----------------------------------------------------------------------------+
 	 */
-
-int i_APCI1710_InitCompareLogic(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned int ui_CompareValue)
+static int i_APCI1710_InitCompareLogic(struct comedi_device *dev,
+				       unsigned char b_ModulNbr,
+				       unsigned int ui_CompareValue)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -1486,13 +1522,14 @@ int i_APCI1710_InitCompareLogic(struct comedi_device *dev,
 |		      -7: 40MHz quartz not on board                          |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
-	unsigned char b_ModulNbr,
-	unsigned char b_PCIInputClock,
-	unsigned char b_TimingUnity,
-	unsigned int ul_TimingInterval, unsigned int *pul_RealTimingInterval)
+static int i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
+					       unsigned char b_ModulNbr,
+					       unsigned char b_PCIInputClock,
+					       unsigned char b_TimingUnity,
+					       unsigned int ul_TimingInterval,
+					       unsigned int *pul_RealTimingInterval)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int ul_TimerValue = 0;
 	double d_RealTimingInterval;
@@ -1995,72 +2032,70 @@ int i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
 	return i_ReturnValue;
 }
 
-/*########################################################################### */
-
-							/* INSN BITS */
-/*########################################################################### */
-
 /*
-+----------------------------------------------------------------------------+
-| Function Name     :INT	i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
-struct comedi_insn *insn,unsigned int *data)                   |
-+----------------------------------------------------------------------------+
-| Task              : Set & Clear Functions for INC_CPT                                          |
-+----------------------------------------------------------------------------+
-| Input Parameters  :
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+ * Configuration function for INC_CPT
+ */
+static int i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev,
+				       struct comedi_subdevice *s,
+				       struct comedi_insn *insn,
+				       unsigned int *data)
 {
-	unsigned int ui_BitsType;
+	struct addi_private *devpriv = dev->private;
+	unsigned int ui_ConfigType;
 	int i_ReturnValue = 0;
-	ui_BitsType = CR_CHAN(insn->chanspec);
-	devpriv->tsk_Current = current;	/*  Save the current process task structure */
 
-	switch (ui_BitsType) {
-	case APCI1710_INCCPT_CLEARCOUNTERVALUE:
-		i_ReturnValue = i_APCI1710_ClearCounterValue(dev,
-			(unsigned char) CR_AREF(insn->chanspec));
+	ui_ConfigType = CR_CHAN(insn->chanspec);
+
+	printk("\nINC_CPT");
+
+	devpriv->tsk_Current = current;	/*  Save the current process task structure */
+	switch (ui_ConfigType) {
+	case APCI1710_INCCPT_INITCOUNTER:
+		i_ReturnValue = i_APCI1710_InitCounter(dev,
+			CR_AREF(insn->chanspec),
+			(unsigned char) data[0],
+			(unsigned char) data[1],
+			(unsigned char) data[2], (unsigned char) data[3], (unsigned char) data[4]);
 		break;
 
-	case APCI1710_INCCPT_CLEARALLCOUNTERVALUE:
-		i_ReturnValue = i_APCI1710_ClearAllCounterValue(dev);
+	case APCI1710_INCCPT_COUNTERAUTOTEST:
+		i_ReturnValue = i_APCI1710_CounterAutoTest(dev,
+			(unsigned char *) &data[0]);
 		break;
 
-	case APCI1710_INCCPT_SETINPUTFILTER:
-		i_ReturnValue = i_APCI1710_SetInputFilter(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char) data[0], (unsigned char) data[1]);
+	case APCI1710_INCCPT_INITINDEX:
+		i_ReturnValue = i_APCI1710_InitIndex(dev,
+			CR_AREF(insn->chanspec),
+			(unsigned char) data[0],
+			(unsigned char) data[1], (unsigned char) data[2], (unsigned char) data[3]);
 		break;
 
-	case APCI1710_INCCPT_LATCHCOUNTER:
-		i_ReturnValue = i_APCI1710_LatchCounter(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]);
+	case APCI1710_INCCPT_INITREFERENCE:
+		i_ReturnValue = i_APCI1710_InitReference(dev,
+			CR_AREF(insn->chanspec), (unsigned char) data[0]);
 		break;
 
-	case APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE:
-		i_ReturnValue = i_APCI1710_SetIndexAndReferenceSource(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]);
+	case APCI1710_INCCPT_INITEXTERNALSTROBE:
+		i_ReturnValue = i_APCI1710_InitExternalStrobe(dev,
+			CR_AREF(insn->chanspec),
+			(unsigned char) data[0], (unsigned char) data[1]);
 		break;
 
-	case APCI1710_INCCPT_SETDIGITALCHLON:
-		i_ReturnValue = i_APCI1710_SetDigitalChlOn(dev,
-			(unsigned char) CR_AREF(insn->chanspec));
+	case APCI1710_INCCPT_INITCOMPARELOGIC:
+		i_ReturnValue = i_APCI1710_InitCompareLogic(dev,
+			CR_AREF(insn->chanspec), (unsigned int) data[0]);
 		break;
 
-	case APCI1710_INCCPT_SETDIGITALCHLOFF:
-		i_ReturnValue = i_APCI1710_SetDigitalChlOff(dev,
-			(unsigned char) CR_AREF(insn->chanspec));
+	case APCI1710_INCCPT_INITFREQUENCYMEASUREMENT:
+		i_ReturnValue = i_APCI1710_InitFrequencyMeasurement(dev,
+			CR_AREF(insn->chanspec),
+			(unsigned char) data[0],
+			(unsigned char) data[1], (unsigned int) data[2], (unsigned int *) &data[0]);
 		break;
 
 	default:
-		printk("Bits Config Parameter Wrong\n");
+		printk("Insn Config : Config Parameter Wrong\n");
+
 	}
 
 	if (i_ReturnValue >= 0)
@@ -2090,9 +2125,10 @@ int i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, struct comedi_subdevice
 |                         "i_APCI1710_InitCounter"                           |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_ClearCounterValue(struct comedi_device *dev, unsigned char b_ModulNbr)
+static int i_APCI1710_ClearCounterValue(struct comedi_device *dev,
+					unsigned char b_ModulNbr)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -2150,9 +2186,9 @@ int i_APCI1710_ClearCounterValue(struct comedi_device *dev, unsigned char b_Modu
 |                     -2: No counter module found                            |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_ClearAllCounterValue(struct comedi_device *dev)
+static int i_APCI1710_ClearAllCounterValue(struct comedi_device *dev)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned char b_ModulCpt = 0;
 	int i_ReturnValue = 0;
 
@@ -2296,10 +2332,12 @@ int i_APCI1710_ClearAllCounterValue(struct comedi_device *dev)
 |					  -6: 40MHz quartz not on board                          |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_SetInputFilter(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char b_PCIInputClock, unsigned char b_Filter)
+static int i_APCI1710_SetInputFilter(struct comedi_device *dev,
+				     unsigned char b_ModulNbr,
+				     unsigned char b_PCIInputClock,
+				     unsigned char b_Filter)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_Status = 0;
 
@@ -2560,10 +2598,11 @@ int i_APCI1710_SetInputFilter(struct comedi_device *dev,
 |                     -4: The selected latch register parameter is wrong     |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_LatchCounter(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char b_LatchReg)
+static int i_APCI1710_LatchCounter(struct comedi_device *dev,
+				   unsigned char b_ModulNbr,
+				   unsigned char b_LatchReg)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -2657,10 +2696,11 @@ int i_APCI1710_LatchCounter(struct comedi_device *dev,
 |		      -4: The source selection is wrong                      |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char b_SourceSelection)
+static int i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev,
+						 unsigned char b_ModulNbr,
+						 unsigned char b_SourceSelection)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -2794,9 +2834,10 @@ int i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev,
 |			  "i_APCI1710_InitCounter"                           |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_SetDigitalChlOn(struct comedi_device *dev, unsigned char b_ModulNbr)
+static int i_APCI1710_SetDigitalChlOn(struct comedi_device *dev,
+				      unsigned char b_ModulNbr)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -2874,9 +2915,10 @@ int i_APCI1710_SetDigitalChlOn(struct comedi_device *dev, unsigned char b_ModulN
 |			  "i_APCI1710_InitCounter"                           |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_SetDigitalChlOff(struct comedi_device *dev, unsigned char b_ModulNbr)
+static int i_APCI1710_SetDigitalChlOff(struct comedi_device *dev,
+				       unsigned char b_ModulNbr)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -2932,88 +2974,59 @@ int i_APCI1710_SetDigitalChlOff(struct comedi_device *dev, unsigned char b_Modul
 	return i_ReturnValue;
 }
 
-/*########################################################################### */
-
-							/*  INSN WRITE */
-/*########################################################################### */
-
 /*
-+----------------------------------------------------------------------------+
-| Function Name     :INT	i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
-struct comedi_insn *insn,unsigned int *data)                   |
-+----------------------------------------------------------------------------+
-| Task              : Enable Disable functions for INC_CPT                                       |
-+----------------------------------------------------------------------------+
-| Input Parameters  :
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :
-+----------------------------------------------------------------------------+
-*/
-int i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+ * Set & Clear Functions for INC_CPT
+ */
+static int i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev,
+				     struct comedi_subdevice *s,
+				     struct comedi_insn *insn,
+				     unsigned int *data)
 {
-	unsigned int ui_WriteType;
+	struct addi_private *devpriv = dev->private;
+	unsigned int ui_BitsType;
 	int i_ReturnValue = 0;
 
-	ui_WriteType = CR_CHAN(insn->chanspec);
+	ui_BitsType = CR_CHAN(insn->chanspec);
 	devpriv->tsk_Current = current;	/*  Save the current process task structure */
 
-	switch (ui_WriteType) {
-	case APCI1710_INCCPT_ENABLELATCHINTERRUPT:
-		i_ReturnValue = i_APCI1710_EnableLatchInterrupt(dev,
+	switch (ui_BitsType) {
+	case APCI1710_INCCPT_CLEARCOUNTERVALUE:
+		i_ReturnValue = i_APCI1710_ClearCounterValue(dev,
 			(unsigned char) CR_AREF(insn->chanspec));
 		break;
 
-	case APCI1710_INCCPT_DISABLELATCHINTERRUPT:
-		i_ReturnValue = i_APCI1710_DisableLatchInterrupt(dev,
-			(unsigned char) CR_AREF(insn->chanspec));
+	case APCI1710_INCCPT_CLEARALLCOUNTERVALUE:
+		i_ReturnValue = i_APCI1710_ClearAllCounterValue(dev);
 		break;
 
-	case APCI1710_INCCPT_WRITE16BITCOUNTERVALUE:
-		i_ReturnValue = i_APCI1710_Write16BitCounterValue(dev,
+	case APCI1710_INCCPT_SETINPUTFILTER:
+		i_ReturnValue = i_APCI1710_SetInputFilter(dev,
 			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char) data[0], (unsigned int) data[1]);
-		break;
-
-	case APCI1710_INCCPT_WRITE32BITCOUNTERVALUE:
-		i_ReturnValue = i_APCI1710_Write32BitCounterValue(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned int) data[0]);
-
-		break;
-
-	case APCI1710_INCCPT_ENABLEINDEX:
-		i_APCI1710_EnableIndex(dev, (unsigned char) CR_AREF(insn->chanspec));
+			(unsigned char) data[0], (unsigned char) data[1]);
 		break;
 
-	case APCI1710_INCCPT_DISABLEINDEX:
-		i_ReturnValue = i_APCI1710_DisableIndex(dev,
-			(unsigned char) CR_AREF(insn->chanspec));
+	case APCI1710_INCCPT_LATCHCOUNTER:
+		i_ReturnValue = i_APCI1710_LatchCounter(dev,
+			(unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]);
 		break;
 
-	case APCI1710_INCCPT_ENABLECOMPARELOGIC:
-		i_ReturnValue = i_APCI1710_EnableCompareLogic(dev,
-			(unsigned char) CR_AREF(insn->chanspec));
+	case APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE:
+		i_ReturnValue = i_APCI1710_SetIndexAndReferenceSource(dev,
+			(unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]);
 		break;
 
-	case APCI1710_INCCPT_DISABLECOMPARELOGIC:
-		i_ReturnValue = i_APCI1710_DisableCompareLogic(dev,
+	case APCI1710_INCCPT_SETDIGITALCHLON:
+		i_ReturnValue = i_APCI1710_SetDigitalChlOn(dev,
 			(unsigned char) CR_AREF(insn->chanspec));
 		break;
 
-	case APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT:
-		i_ReturnValue = i_APCI1710_EnableFrequencyMeasurement(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]);
-		break;
-
-	case APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT:
-		i_ReturnValue = i_APCI1710_DisableFrequencyMeasurement(dev,
+	case APCI1710_INCCPT_SETDIGITALCHLOFF:
+		i_ReturnValue = i_APCI1710_SetDigitalChlOff(dev,
 			(unsigned char) CR_AREF(insn->chanspec));
 		break;
 
 	default:
-		printk("Write Config Parameter Wrong\n");
+		printk("Bits Config Parameter Wrong\n");
 	}
 
 	if (i_ReturnValue >= 0)
@@ -3046,9 +3059,10 @@ int i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, struct comedi_subdevic
 |                         "i_APCI1710_SetBoardIntRoutine"                    |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev, unsigned char b_ModulNbr)
+static int i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev,
+					   unsigned char b_ModulNbr)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -3132,9 +3146,10 @@ int i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev, unsigned char b_M
 |                         "i_APCI1710_SetBoardIntRoutine"                    |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, unsigned char b_ModulNbr)
+static int i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev,
+					    unsigned char b_ModulNbr)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -3230,10 +3245,12 @@ int i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, unsigned char b_
 |                     -4: The selected 16-Bit counter parameter is wrong     |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char b_SelectedCounter, unsigned int ui_WriteValue)
+static int i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
+					     unsigned char b_ModulNbr,
+					     unsigned char b_SelectedCounter,
+					     unsigned int ui_WriteValue)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -3315,10 +3332,11 @@ int i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
 |                         "i_APCI1710_InitCounter"                           |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned int ul_WriteValue)
+static int i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
+					     unsigned char b_ModulNbr,
+					     unsigned int ul_WriteValue)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -3382,9 +3400,10 @@ int i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
 |                         "i_APCI1710_InitIndex"                             |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_EnableIndex(struct comedi_device *dev, unsigned char b_ModulNbr)
+static int i_APCI1710_EnableIndex(struct comedi_device *dev,
+				  unsigned char b_ModulNbr)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int ul_InterruptLatchReg;
 
@@ -3480,9 +3499,10 @@ int i_APCI1710_EnableIndex(struct comedi_device *dev, unsigned char b_ModulNbr)
 |                         "i_APCI1710_InitIndex"                             |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_DisableIndex(struct comedi_device *dev, unsigned char b_ModulNbr)
+static int i_APCI1710_DisableIndex(struct comedi_device *dev,
+				   unsigned char b_ModulNbr)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -3579,9 +3599,10 @@ int i_APCI1710_DisableIndex(struct comedi_device *dev, unsigned char b_ModulNbr)
 |                         See function "i_APCI1710_SetBoardIntRoutineX"      |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_EnableCompareLogic(struct comedi_device *dev, unsigned char b_ModulNbr)
+static int i_APCI1710_EnableCompareLogic(struct comedi_device *dev,
+					 unsigned char b_ModulNbr)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -3679,9 +3700,10 @@ int i_APCI1710_EnableCompareLogic(struct comedi_device *dev, unsigned char b_Mod
 |                         See function "i_APCI1710_InitCompareLogic"         |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_DisableCompareLogic(struct comedi_device *dev, unsigned char b_ModulNbr)
+static int i_APCI1710_DisableCompareLogic(struct comedi_device *dev,
+					  unsigned char b_ModulNbr)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -3788,10 +3810,11 @@ int i_APCI1710_DisableCompareLogic(struct comedi_device *dev, unsigned char b_Mo
 	   |                     -6: Interrupt function not initialised.                |
 	   +----------------------------------------------------------------------------+
 	 */
-
-int i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char b_InterruptEnable)
+static int i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev,
+						 unsigned char b_ModulNbr,
+						 unsigned char b_InterruptEnable)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -3935,9 +3958,10 @@ int i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev,
 	   |                      See function "i_APCI1710_InitFrequencyMeasurement" |
 	   +----------------------------------------------------------------------------+
 	 */
-
-int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev, unsigned char b_ModulNbr)
+static int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev,
+						  unsigned char b_ModulNbr)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -4029,134 +4053,80 @@ int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev, unsigned c
 	return i_ReturnValue;
 }
 
-/*########################################################################### */
-
-							/*  INSN READ */
-
-/*########################################################################### */
-
 /*
-+----------------------------------------------------------------------------+
-| Function Name     :INT	i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev,struct comedi_subdevice *s,
-struct comedi_insn *insn,unsigned int *data)                   |
-+----------------------------------------------------------------------------+
-| Task              : Read and Get functions for INC_CPT                                       |
-+----------------------------------------------------------------------------+
-| Input Parameters  :
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :
-+----------------------------------------------------------------------------+
-*/
-int i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+ * Enable Disable functions for INC_CPT
+ */
+static int i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev,
+				      struct comedi_subdevice *s,
+				      struct comedi_insn *insn,
+				      unsigned int *data)
 {
-	unsigned int ui_ReadType;
+	struct addi_private *devpriv = dev->private;
+	unsigned int ui_WriteType;
 	int i_ReturnValue = 0;
 
-	ui_ReadType = CR_CHAN(insn->chanspec);
-
+	ui_WriteType = CR_CHAN(insn->chanspec);
 	devpriv->tsk_Current = current;	/*  Save the current process task structure */
-	switch (ui_ReadType) {
-	case APCI1710_INCCPT_READLATCHREGISTERSTATUS:
-		i_ReturnValue = i_APCI1710_ReadLatchRegisterStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char) CR_RANGE(insn->chanspec), (unsigned char *) &data[0]);
-		break;
 
-	case APCI1710_INCCPT_READLATCHREGISTERVALUE:
-		i_ReturnValue = i_APCI1710_ReadLatchRegisterValue(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char) CR_RANGE(insn->chanspec), (unsigned int *) &data[0]);
-		printk("Latch Register Value %d\n", data[0]);
+	switch (ui_WriteType) {
+	case APCI1710_INCCPT_ENABLELATCHINTERRUPT:
+		i_ReturnValue = i_APCI1710_EnableLatchInterrupt(dev,
+			(unsigned char) CR_AREF(insn->chanspec));
 		break;
 
-	case APCI1710_INCCPT_READ16BITCOUNTERVALUE:
-		i_ReturnValue = i_APCI1710_Read16BitCounterValue(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char) CR_RANGE(insn->chanspec), (unsigned int *) &data[0]);
+	case APCI1710_INCCPT_DISABLELATCHINTERRUPT:
+		i_ReturnValue = i_APCI1710_DisableLatchInterrupt(dev,
+			(unsigned char) CR_AREF(insn->chanspec));
 		break;
 
-	case APCI1710_INCCPT_READ32BITCOUNTERVALUE:
-		i_ReturnValue = i_APCI1710_Read32BitCounterValue(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned int *) &data[0]);
+	case APCI1710_INCCPT_WRITE16BITCOUNTERVALUE:
+		i_ReturnValue = i_APCI1710_Write16BitCounterValue(dev,
+			(unsigned char) CR_AREF(insn->chanspec),
+			(unsigned char) data[0], (unsigned int) data[1]);
 		break;
 
-	case APCI1710_INCCPT_GETINDEXSTATUS:
-		i_ReturnValue = i_APCI1710_GetIndexStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
-		break;
+	case APCI1710_INCCPT_WRITE32BITCOUNTERVALUE:
+		i_ReturnValue = i_APCI1710_Write32BitCounterValue(dev,
+			(unsigned char) CR_AREF(insn->chanspec), (unsigned int) data[0]);
 
-	case APCI1710_INCCPT_GETREFERENCESTATUS:
-		i_ReturnValue = i_APCI1710_GetReferenceStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
 		break;
 
-	case APCI1710_INCCPT_GETUASSTATUS:
-		i_ReturnValue = i_APCI1710_GetUASStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
-		break;
-
-	case APCI1710_INCCPT_GETCBSTATUS:
-		i_ReturnValue = i_APCI1710_GetCBStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
+	case APCI1710_INCCPT_ENABLEINDEX:
+		i_APCI1710_EnableIndex(dev, (unsigned char) CR_AREF(insn->chanspec));
 		break;
 
-	case APCI1710_INCCPT_GET16BITCBSTATUS:
-		i_ReturnValue = i_APCI1710_Get16BitCBStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char *) &data[0], (unsigned char *) &data[1]);
+	case APCI1710_INCCPT_DISABLEINDEX:
+		i_ReturnValue = i_APCI1710_DisableIndex(dev,
+			(unsigned char) CR_AREF(insn->chanspec));
 		break;
 
-	case APCI1710_INCCPT_GETUDSTATUS:
-		i_ReturnValue = i_APCI1710_GetUDStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
-
+	case APCI1710_INCCPT_ENABLECOMPARELOGIC:
+		i_ReturnValue = i_APCI1710_EnableCompareLogic(dev,
+			(unsigned char) CR_AREF(insn->chanspec));
 		break;
 
-	case APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS:
-		i_ReturnValue = i_APCI1710_GetInterruptUDLatchedStatus(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
+	case APCI1710_INCCPT_DISABLECOMPARELOGIC:
+		i_ReturnValue = i_APCI1710_DisableCompareLogic(dev,
+			(unsigned char) CR_AREF(insn->chanspec));
 		break;
 
-	case APCI1710_INCCPT_READFREQUENCYMEASUREMENT:
-		i_ReturnValue = i_APCI1710_ReadFrequencyMeasurement(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char *) &data[0],
-			(unsigned char *) &data[1], (unsigned int *) &data[2]);
+	case APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT:
+		i_ReturnValue = i_APCI1710_EnableFrequencyMeasurement(dev,
+			(unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]);
 		break;
 
-	case APCI1710_INCCPT_READINTERRUPT:
-		data[0] = devpriv->s_InterruptParameters.
-			s_FIFOInterruptParameters[devpriv->
-			s_InterruptParameters.ui_Read].b_OldModuleMask;
-		data[1] = devpriv->s_InterruptParameters.
-			s_FIFOInterruptParameters[devpriv->
-			s_InterruptParameters.ui_Read].ul_OldInterruptMask;
-		data[2] = devpriv->s_InterruptParameters.
-			s_FIFOInterruptParameters[devpriv->
-			s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
-
-		/**************************/
-		/* Increment the read FIFO */
-		/***************************/
-
-		devpriv->
-			s_InterruptParameters.
-			ui_Read = (devpriv->s_InterruptParameters.
-			ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
-
+	case APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT:
+		i_ReturnValue = i_APCI1710_DisableFrequencyMeasurement(dev,
+			(unsigned char) CR_AREF(insn->chanspec));
 		break;
 
 	default:
-		printk("ReadType Parameter wrong\n");
+		printk("Write Config Parameter Wrong\n");
 	}
 
 	if (i_ReturnValue >= 0)
 		i_ReturnValue = insn->n;
 	return i_ReturnValue;
-
 }
 
 /*
@@ -4192,10 +4162,12 @@ int i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, struct comedi_subdevice
 |                     -4: The selected latch register parameter is wrong     |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char b_LatchReg, unsigned char *pb_LatchStatus)
+static int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
+					      unsigned char b_ModulNbr,
+					      unsigned char b_LatchReg,
+					      unsigned char *pb_LatchStatus)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_LatchReg;
 
@@ -4279,10 +4251,12 @@ int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
 |                     -4: The selected latch register parameter is wrong     |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char b_LatchReg, unsigned int *pul_LatchValue)
+static int i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
+					     unsigned char b_ModulNbr,
+					     unsigned char b_LatchReg,
+					     unsigned int *pul_LatchValue)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -4363,10 +4337,12 @@ int i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
 |                     -4: The selected 16-Bit counter parameter is wrong     |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char b_SelectedCounter, unsigned int *pui_CounterValue)
+static int i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
+					    unsigned char b_ModulNbr,
+					    unsigned char b_SelectedCounter,
+					    unsigned int *pui_CounterValue)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_LathchValue = 0;
 
@@ -4458,10 +4434,11 @@ int i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
 |                         "i_APCI1710_InitCounter"                           |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned int *pul_CounterValue)
+static int i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
+					    unsigned char b_ModulNbr,
+					    unsigned int *pul_CounterValue)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 
 	/**************************/
@@ -4534,10 +4511,11 @@ int i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
 |                         "i_APCI1710_InitIndex"                             |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_GetIndexStatus(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char *pb_IndexStatus)
+static int i_APCI1710_GetIndexStatus(struct comedi_device *dev,
+				     unsigned char b_ModulNbr,
+				     unsigned char *pb_IndexStatus)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_StatusReg = 0;
 
@@ -4618,10 +4596,11 @@ int i_APCI1710_GetIndexStatus(struct comedi_device *dev,
 |                         "i_APCI1710_InitReference"                         |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_GetReferenceStatus(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char *pb_ReferenceStatus)
+static int i_APCI1710_GetReferenceStatus(struct comedi_device *dev,
+					 unsigned char b_ModulNbr,
+					 unsigned char *pb_ReferenceStatus)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_StatusReg = 0;
 
@@ -4702,10 +4681,11 @@ int i_APCI1710_GetReferenceStatus(struct comedi_device *dev,
 |                         "i_APCI1710_InitCounter"                           |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_GetUASStatus(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char *pb_UASStatus)
+static int i_APCI1710_GetUASStatus(struct comedi_device *dev,
+				   unsigned char b_ModulNbr,
+				   unsigned char *pb_UASStatus)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_StatusReg = 0;
 
@@ -4770,10 +4750,11 @@ int i_APCI1710_GetUASStatus(struct comedi_device *dev,
 |                         "i_APCI1710_InitCounter"                           |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_GetCBStatus(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char *pb_CBStatus)
+static int i_APCI1710_GetCBStatus(struct comedi_device *dev,
+				  unsigned char b_ModulNbr,
+				  unsigned char *pb_CBStatus)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_StatusReg = 0;
 
@@ -4852,10 +4833,12 @@ int i_APCI1710_GetCBStatus(struct comedi_device *dev,
 |                     -5: Firmware revision error                            |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_Get16BitCBStatus(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char *pb_CBStatusCounter0, unsigned char *pb_CBStatusCounter1)
+static int i_APCI1710_Get16BitCBStatus(struct comedi_device *dev,
+				       unsigned char b_ModulNbr,
+				       unsigned char *pb_CBStatusCounter0,
+				       unsigned char *pb_CBStatusCounter1)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_StatusReg = 0;
 
@@ -4965,10 +4948,11 @@ int i_APCI1710_Get16BitCBStatus(struct comedi_device *dev,
 |                         "i_APCI1710_InitCounter"                           |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_GetUDStatus(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char *pb_UDStatus)
+static int i_APCI1710_GetUDStatus(struct comedi_device *dev,
+				  unsigned char b_ModulNbr,
+				  unsigned char *pb_UDStatus)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_StatusReg = 0;
 
@@ -5039,10 +5023,11 @@ int i_APCI1710_GetUDStatus(struct comedi_device *dev,
 |                         See function "i_APCI1710_SetBoardIntRoutineX"      |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev,
-	unsigned char b_ModulNbr, unsigned char *pb_UDStatus)
+static int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev,
+						  unsigned char b_ModulNbr,
+						  unsigned char *pb_UDStatus)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_StatusReg = 0;
 
@@ -5144,11 +5129,13 @@ int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev,
 	   |                      See function "i_APCI1710_InitFrequencyMeasurement" |
 	   +----------------------------------------------------------------------------+
 	 */
-
-int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
-	unsigned char b_ModulNbr,
-	unsigned char *pb_Status, unsigned char *pb_UDStatus, unsigned int *pul_ReadValue)
+static int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
+					       unsigned char b_ModulNbr,
+					       unsigned char *pb_Status,
+					       unsigned char *pb_UDStatus,
+					       unsigned int *pul_ReadValue)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int ui_16BitValue;
 	unsigned int dw_StatusReg;
@@ -5361,3 +5348,118 @@ int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
 
 	return i_ReturnValue;
 }
+/*
+ * Read and Get functions for INC_CPT
+ */
+static int i_APCI1710_InsnReadINCCPT(struct comedi_device *dev,
+				     struct comedi_subdevice *s,
+				     struct comedi_insn *insn,
+				     unsigned int *data)
+{
+	struct addi_private *devpriv = dev->private;
+	unsigned int ui_ReadType;
+	int i_ReturnValue = 0;
+
+	ui_ReadType = CR_CHAN(insn->chanspec);
+
+	devpriv->tsk_Current = current;	/*  Save the current process task structure */
+	switch (ui_ReadType) {
+	case APCI1710_INCCPT_READLATCHREGISTERSTATUS:
+		i_ReturnValue = i_APCI1710_ReadLatchRegisterStatus(dev,
+			(unsigned char) CR_AREF(insn->chanspec),
+			(unsigned char) CR_RANGE(insn->chanspec), (unsigned char *) &data[0]);
+		break;
+
+	case APCI1710_INCCPT_READLATCHREGISTERVALUE:
+		i_ReturnValue = i_APCI1710_ReadLatchRegisterValue(dev,
+			(unsigned char) CR_AREF(insn->chanspec),
+			(unsigned char) CR_RANGE(insn->chanspec), (unsigned int *) &data[0]);
+		printk("Latch Register Value %d\n", data[0]);
+		break;
+
+	case APCI1710_INCCPT_READ16BITCOUNTERVALUE:
+		i_ReturnValue = i_APCI1710_Read16BitCounterValue(dev,
+			(unsigned char) CR_AREF(insn->chanspec),
+			(unsigned char) CR_RANGE(insn->chanspec), (unsigned int *) &data[0]);
+		break;
+
+	case APCI1710_INCCPT_READ32BITCOUNTERVALUE:
+		i_ReturnValue = i_APCI1710_Read32BitCounterValue(dev,
+			(unsigned char) CR_AREF(insn->chanspec), (unsigned int *) &data[0]);
+		break;
+
+	case APCI1710_INCCPT_GETINDEXSTATUS:
+		i_ReturnValue = i_APCI1710_GetIndexStatus(dev,
+			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
+		break;
+
+	case APCI1710_INCCPT_GETREFERENCESTATUS:
+		i_ReturnValue = i_APCI1710_GetReferenceStatus(dev,
+			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
+		break;
+
+	case APCI1710_INCCPT_GETUASSTATUS:
+		i_ReturnValue = i_APCI1710_GetUASStatus(dev,
+			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
+		break;
+
+	case APCI1710_INCCPT_GETCBSTATUS:
+		i_ReturnValue = i_APCI1710_GetCBStatus(dev,
+			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
+		break;
+
+	case APCI1710_INCCPT_GET16BITCBSTATUS:
+		i_ReturnValue = i_APCI1710_Get16BitCBStatus(dev,
+			(unsigned char) CR_AREF(insn->chanspec),
+			(unsigned char *) &data[0], (unsigned char *) &data[1]);
+		break;
+
+	case APCI1710_INCCPT_GETUDSTATUS:
+		i_ReturnValue = i_APCI1710_GetUDStatus(dev,
+			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
+
+		break;
+
+	case APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS:
+		i_ReturnValue = i_APCI1710_GetInterruptUDLatchedStatus(dev,
+			(unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]);
+		break;
+
+	case APCI1710_INCCPT_READFREQUENCYMEASUREMENT:
+		i_ReturnValue = i_APCI1710_ReadFrequencyMeasurement(dev,
+			(unsigned char) CR_AREF(insn->chanspec),
+			(unsigned char *) &data[0],
+			(unsigned char *) &data[1], (unsigned int *) &data[2]);
+		break;
+
+	case APCI1710_INCCPT_READINTERRUPT:
+		data[0] = devpriv->s_InterruptParameters.
+			s_FIFOInterruptParameters[devpriv->
+			s_InterruptParameters.ui_Read].b_OldModuleMask;
+		data[1] = devpriv->s_InterruptParameters.
+			s_FIFOInterruptParameters[devpriv->
+			s_InterruptParameters.ui_Read].ul_OldInterruptMask;
+		data[2] = devpriv->s_InterruptParameters.
+			s_FIFOInterruptParameters[devpriv->
+			s_InterruptParameters.ui_Read].ul_OldCounterLatchValue;
+
+		/**************************/
+		/* Increment the read FIFO */
+		/***************************/
+
+		devpriv->
+			s_InterruptParameters.
+			ui_Read = (devpriv->s_InterruptParameters.
+			ui_Read + 1) % APCI1710_SAVE_INTERRUPT;
+
+		break;
+
+	default:
+		printk("ReadType Parameter wrong\n");
+	}
+
+	if (i_ReturnValue >= 0)
+		i_ReturnValue = insn->n;
+	return i_ReturnValue;
+
+}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
deleted file mode 100644
index 358298b..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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 APCI1710_16BIT_COUNTER			0x10
-#define APCI1710_32BIT_COUNTER			0x0
-#define APCI1710_QUADRUPLE_MODE			0x0
-#define APCI1710_DOUBLE_MODE			0x3
-#define APCI1710_SIMPLE_MODE			0xF
-#define APCI1710_DIRECT_MODE			0x80
-#define APCI1710_HYSTERESIS_ON			0x60
-#define APCI1710_HYSTERESIS_OFF			0x0
-#define APCI1710_INCREMENT			0x60
-#define APCI1710_DECREMENT			0x0
-#define APCI1710_LATCH_COUNTER			0x1
-#define APCI1710_CLEAR_COUNTER			0x0
-#define APCI1710_LOW				0x0
-#define APCI1710_HIGH				0x1
-
-/*********************/
-/* Version 0600-0229 */
-/*********************/
-#define APCI1710_HIGH_EDGE_CLEAR_COUNTER		0x0
-#define APCI1710_HIGH_EDGE_LATCH_COUNTER		0x1
-#define APCI1710_LOW_EDGE_CLEAR_COUNTER			0x2
-#define APCI1710_LOW_EDGE_LATCH_COUNTER			0x3
-#define APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER	0x4
-#define APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER	0x5
-#define APCI1710_SOURCE_0				0x0
-#define APCI1710_SOURCE_1				0x1
-
-#define APCI1710_30MHZ				30
-#define APCI1710_33MHZ				33
-#define APCI1710_40MHZ				40
-
-#define APCI1710_ENABLE_LATCH_INT    		0x80
-#define APCI1710_DISABLE_LATCH_INT   		(~APCI1710_ENABLE_LATCH_INT)
-
-#define APCI1710_INDEX_LATCH_COUNTER		0x10
-#define APCI1710_INDEX_AUTO_MODE		0x8
-#define APCI1710_ENABLE_INDEX			0x4
-#define APCI1710_DISABLE_INDEX			(~APCI1710_ENABLE_INDEX)
-#define APCI1710_ENABLE_LATCH_AND_CLEAR		0x8
-#define APCI1710_DISABLE_LATCH_AND_CLEAR	(~APCI1710_ENABLE_LATCH_AND_CLEAR)
-#define APCI1710_SET_LOW_INDEX_LEVEL		0x4
-#define APCI1710_SET_HIGH_INDEX_LEVEL		(~APCI1710_SET_LOW_INDEX_LEVEL)
-#define APCI1710_INVERT_INDEX_RFERENCE		0x2
-#define APCI1710_DEFAULT_INDEX_RFERENCE         (~APCI1710_INVERT_INDEX_RFERENCE)
-
-#define APCI1710_ENABLE_INDEX_INT		0x1
-#define APCI1710_DISABLE_INDEX_INT		(~APCI1710_ENABLE_INDEX_INT)
-
-#define APCI1710_ENABLE_FREQUENCY		0x4
-#define APCI1710_DISABLE_FREQUENCY		(~APCI1710_ENABLE_FREQUENCY)
-
-#define APCI1710_ENABLE_FREQUENCY_INT		0x8
-#define APCI1710_DISABLE_FREQUENCY_INT		(~APCI1710_ENABLE_FREQUENCY_INT)
-
-#define APCI1710_ENABLE_40MHZ_FREQUENCY		0x40
-#define APCI1710_DISABLE_40MHZ_FREQUENCY	(~APCI1710_ENABLE_40MHZ_FREQUENCY)
-
-#define APCI1710_ENABLE_40MHZ_FILTER		0x80
-#define APCI1710_DISABLE_40MHZ_FILTER		(~APCI1710_ENABLE_40MHZ_FILTER)
-
-#define APCI1710_ENABLE_COMPARE_INT		0x2
-#define APCI1710_DISABLE_COMPARE_INT		(~APCI1710_ENABLE_COMPARE_INT)
-
-#define APCI1710_ENABLE_INDEX_ACTION		0x20
-#define APCI1710_DISABLE_INDEX_ACTION		(~APCI1710_ENABLE_INDEX_ACTION)
-#define APCI1710_REFERENCE_HIGH			0x40
-#define APCI1710_REFERENCE_LOW			(~APCI1710_REFERENCE_HIGH)
-
-#define APCI1710_TOR_GATE_LOW			0x40
-#define APCI1710_TOR_GATE_HIGH			(~APCI1710_TOR_GATE_LOW)
-
-/* INSN CONFIG */
-#define	APCI1710_INCCPT_INITCOUNTER				100
-#define APCI1710_INCCPT_COUNTERAUTOTEST				101
-#define APCI1710_INCCPT_INITINDEX				102
-#define APCI1710_INCCPT_INITREFERENCE				103
-#define APCI1710_INCCPT_INITEXTERNALSTROBE			104
-#define APCI1710_INCCPT_INITCOMPARELOGIC			105
-#define APCI1710_INCCPT_INITFREQUENCYMEASUREMENT		106
-
-/* INSN READ */
-#define APCI1710_INCCPT_READLATCHREGISTERSTATUS			200
-#define APCI1710_INCCPT_READLATCHREGISTERVALUE			201
-#define APCI1710_INCCPT_READ16BITCOUNTERVALUE			202
-#define APCI1710_INCCPT_READ32BITCOUNTERVALUE			203
-#define APCI1710_INCCPT_GETINDEXSTATUS				204
-#define APCI1710_INCCPT_GETREFERENCESTATUS			205
-#define APCI1710_INCCPT_GETUASSTATUS				206
-#define APCI1710_INCCPT_GETCBSTATUS				207
-#define APCI1710_INCCPT_GET16BITCBSTATUS			208
-#define APCI1710_INCCPT_GETUDSTATUS				209
-#define APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS		210
-#define APCI1710_INCCPT_READFREQUENCYMEASUREMENT		211
-#define APCI1710_INCCPT_READINTERRUPT				212
-
-/* INSN BITS */
-#define APCI1710_INCCPT_CLEARCOUNTERVALUE			300
-#define APCI1710_INCCPT_CLEARALLCOUNTERVALUE			301
-#define APCI1710_INCCPT_SETINPUTFILTER				302
-#define APCI1710_INCCPT_LATCHCOUNTER				303
-#define APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE		304
-#define APCI1710_INCCPT_SETDIGITALCHLON				305
-#define APCI1710_INCCPT_SETDIGITALCHLOFF			306
-
-/* INSN WRITE */
-#define APCI1710_INCCPT_ENABLELATCHINTERRUPT			400
-#define APCI1710_INCCPT_DISABLELATCHINTERRUPT			401
-#define APCI1710_INCCPT_WRITE16BITCOUNTERVALUE			402
-#define APCI1710_INCCPT_WRITE32BITCOUNTERVALUE			403
-#define APCI1710_INCCPT_ENABLEINDEX				404
-#define APCI1710_INCCPT_DISABLEINDEX				405
-#define APCI1710_INCCPT_ENABLECOMPARELOGIC			406
-#define APCI1710_INCCPT_DISABLECOMPARELOGIC			407
-#define APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT		408
-#define APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT		409
-
-/************ Main Functions *************/
-int i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int * data);
-
-int i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
-			      struct comedi_insn *insn, unsigned int * data);
-
-int i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
-			       struct comedi_insn *insn, unsigned int * data);
-
-int i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, struct comedi_subdevice * s,
-			      struct comedi_insn *insn, unsigned int * data);
-
-/*********** Supplementary Functions********/
-
-/* INSN CONFIG */
-int i_APCI1710_InitCounter(struct comedi_device *dev,
-			   unsigned char b_ModulNbr,
-			   unsigned char b_CounterRange,
-			   unsigned char b_FirstCounterModus,
-			   unsigned char b_FirstCounterOption,
-			   unsigned char b_SecondCounterModus,
-			   unsigned char b_SecondCounterOption);
-
-int i_APCI1710_CounterAutoTest(struct comedi_device *dev, unsigned char * pb_TestStatus);
-
-int i_APCI1710_InitIndex(struct comedi_device *dev,
-			 unsigned char b_ModulNbr,
-			 unsigned char b_ReferenceAction,
-			 unsigned char b_IndexOperation, unsigned char b_AutoMode,
-			 unsigned char b_InterruptEnable);
-
-int i_APCI1710_InitReference(struct comedi_device *dev,
-			     unsigned char b_ModulNbr, unsigned char b_ReferenceLevel);
-
-int i_APCI1710_InitExternalStrobe(struct comedi_device *dev,
-				  unsigned char b_ModulNbr, unsigned char b_ExternalStrobe,
-				  unsigned char b_ExternalStrobeLevel);
-
-int i_APCI1710_InitCompareLogic(struct comedi_device *dev,
-				unsigned char b_ModulNbr, unsigned int ui_CompareValue);
-
-int i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev,
-					unsigned char b_ModulNbr,
-					unsigned char b_PCIInputClock,
-					unsigned char b_TimingUnity,
-					unsigned int ul_TimingInterval,
-					unsigned int *pul_RealTimingInterval);
-
-/* INSN BITS */
-int i_APCI1710_ClearCounterValue(struct comedi_device *dev, unsigned char b_ModulNbr);
-
-int i_APCI1710_ClearAllCounterValue(struct comedi_device *dev);
-
-int i_APCI1710_SetInputFilter(struct comedi_device *dev,
-			      unsigned char b_ModulNbr, unsigned char b_PCIInputClock,
-			      unsigned char b_Filter);
-
-int i_APCI1710_LatchCounter(struct comedi_device *dev,
-			    unsigned char b_ModulNbr, unsigned char b_LatchReg);
-
-int i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev,
-					  unsigned char b_ModulNbr,
-					  unsigned char b_SourceSelection);
-
-int i_APCI1710_SetDigitalChlOn(struct comedi_device *dev, unsigned char b_ModulNbr);
-
-int i_APCI1710_SetDigitalChlOff(struct comedi_device *dev, unsigned char b_ModulNbr);
-
-/* INSN WRITE */
-int i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev, unsigned char b_ModulNbr);
-
-int i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, unsigned char b_ModulNbr);
-
-int i_APCI1710_Write16BitCounterValue(struct comedi_device *dev,
-				      unsigned char b_ModulNbr, unsigned char b_SelectedCounter,
-				      unsigned int ui_WriteValue);
-
-int i_APCI1710_Write32BitCounterValue(struct comedi_device *dev,
-				      unsigned char b_ModulNbr, unsigned int ul_WriteValue);
-
-int i_APCI1710_EnableIndex(struct comedi_device *dev, unsigned char b_ModulNbr);
-
-int i_APCI1710_DisableIndex(struct comedi_device *dev, unsigned char b_ModulNbr);
-
-int i_APCI1710_EnableCompareLogic(struct comedi_device *dev, unsigned char b_ModulNbr);
-
-int i_APCI1710_DisableCompareLogic(struct comedi_device *dev, unsigned char b_ModulNbr);
-
-int i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev,
-					  unsigned char b_ModulNbr,
-					  unsigned char b_InterruptEnable);
-
-int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev,
-					   unsigned char b_ModulNbr);
-
-/* INSN READ */
-int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev,
-				       unsigned char b_ModulNbr, unsigned char b_LatchReg,
-				       unsigned char *pb_LatchStatus);
-
-int i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev,
-				      unsigned char b_ModulNbr, unsigned char b_LatchReg,
-				      unsigned int *pul_LatchValue);
-
-int i_APCI1710_Read16BitCounterValue(struct comedi_device *dev,
-				     unsigned char b_ModulNbr, unsigned char b_SelectedCounter,
-				     unsigned int *pui_CounterValue);
-
-int i_APCI1710_Read32BitCounterValue(struct comedi_device *dev,
-				     unsigned char b_ModulNbr, unsigned int *pul_CounterValue);
-
-int i_APCI1710_GetIndexStatus(struct comedi_device *dev,
-			      unsigned char b_ModulNbr, unsigned char *pb_IndexStatus);
-
-int i_APCI1710_GetReferenceStatus(struct comedi_device *dev,
-				  unsigned char b_ModulNbr, unsigned char *pb_ReferenceStatus);
-
-int i_APCI1710_GetUASStatus(struct comedi_device *dev,
-			    unsigned char b_ModulNbr, unsigned char *pb_UASStatus);
-
-int i_APCI1710_GetCBStatus(struct comedi_device *dev,
-			   unsigned char b_ModulNbr, unsigned char *pb_CBStatus);
-
-int i_APCI1710_Get16BitCBStatus(struct comedi_device *dev,
-				unsigned char b_ModulNbr, unsigned char *pb_CBStatusCounter0,
-				unsigned char *pb_CBStatusCounter1);
-
-int i_APCI1710_GetUDStatus(struct comedi_device *dev,
-			   unsigned char b_ModulNbr, unsigned char *pb_UDStatus);
-
-int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev,
-					   unsigned char b_ModulNbr, unsigned char *pb_UDStatus);
-
-int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
-					unsigned char b_ModulNbr,
-					unsigned char *pb_Status, unsigned char *pb_UDStatus,
-					unsigned int *pul_ReadValue);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
index 3f9cfa2..be0c6ad 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
@@ -49,13 +49,11 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +-----------------------------------------------------------------------+
 */
 
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
+#define APCI1710_SINGLE			0
+#define APCI1710_CONTINUOUS		1
 
-#include "APCI1710_Inp_cpt.h"
+#define APCI1710_PULSEENCODER_READ	0
+#define APCI1710_PULSEENCODER_WRITE	1
 
 /*
 +----------------------------------------------------------------------------+
@@ -123,12 +121,14 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev,
+						 struct comedi_subdevice *s,
+						 struct comedi_insn *insn,
+						 unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_IntRegister;
-
 	unsigned char b_ModulNbr;
 	unsigned char b_PulseEncoderNbr;
 	unsigned char b_InputLevelSelection;
@@ -414,9 +414,12 @@ int i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev,
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
+							 struct comedi_subdevice *s,
+							 struct comedi_insn *insn,
+							 unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned char b_ModulNbr;
 	unsigned char b_PulseEncoderNbr;
@@ -708,9 +711,12 @@ int i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
 
 						 unsigned char *_ pb_Status)
 						 */
-int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
+						    struct comedi_subdevice *s,
+						    struct comedi_insn *insn,
+						    unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_StatusRegister;
 	unsigned char b_ModulNbr;
@@ -834,9 +840,12 @@ int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
 	return i_ReturnValue;
 }
 
-int i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
+						    struct comedi_subdevice *s,
+						    struct comedi_insn *insn,
+						    unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 
 	data[0] = devpriv->s_InterruptParameters.
 		s_FIFOInterruptParameters[devpriv->
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
deleted file mode 100644
index 31fbb0b..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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 APCI1710_SINGLE			0
-#define APCI1710_CONTINUOUS		1
-
-#define APCI1710_PULSEENCODER_READ	0
-#define APCI1710_PULSEENCODER_WRITE	1
-
-int i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev,
-					  struct comedi_subdevice *s,
-					  struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev,
-						  struct comedi_subdevice *s,
-						  struct comedi_insn *insn,
-						  unsigned int *data);
-
-/*
- * READ PULSE ENCODER FUNCTIONS
- */
-int i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev,
-					     struct comedi_subdevice *s,
-					     struct comedi_insn *insn,
-					     unsigned int *data);
-
-/*
- * WRITE PULSE ENCODER FUNCTIONS
- */
-int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev,
-					     struct comedi_subdevice *s,
-					     struct comedi_insn *insn,
-					     unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
index 8883e66..a211e78 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
@@ -47,72 +47,16 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +-----------------------------------------------------------------------+
 */
 
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
-
-#include "APCI1710_Pwm.h"
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name     :INT i_APCI1710_InsnConfigPWM(struct comedi_device *dev,
-struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)                        |
-+----------------------------------------------------------------------------+
-| Task              : Pwm Init and Get Pwm Initialisation                    |
-+----------------------------------------------------------------------------+
-| Input Parameters  :
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :
-+----------------------------------------------------------------------------+
-*/
+#define APCI1710_30MHZ			30
+#define APCI1710_33MHZ			33
+#define APCI1710_40MHZ			40
 
-int i_APCI1710_InsnConfigPWM(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned char b_ConfigType;
-	int i_ReturnValue = 0;
-	b_ConfigType = CR_CHAN(insn->chanspec);
+#define APCI1710_PWM_INIT		0
+#define APCI1710_PWM_GETINITDATA	1
 
-	switch (b_ConfigType) {
-	case APCI1710_PWM_INIT:
-		i_ReturnValue = i_APCI1710_InitPWM(dev, (unsigned char) CR_AREF(insn->chanspec),	/*   b_ModulNbr */
-			(unsigned char) data[0],	/* b_PWM */
-			(unsigned char) data[1],	/*  b_ClockSelection */
-			(unsigned char) data[2],	/*  b_TimingUnit */
-			(unsigned int) data[3],	/* ul_LowTiming */
-			(unsigned int) data[4],	/* ul_HighTiming */
-			(unsigned int *) &data[0],	/* pul_RealLowTiming */
-			(unsigned int *) &data[1]	/* pul_RealHighTiming */
-			);
-		break;
-
-	case APCI1710_PWM_GETINITDATA:
-		i_ReturnValue = i_APCI1710_GetPWMInitialisation(dev, (unsigned char) CR_AREF(insn->chanspec),	/*  b_ModulNbr */
-			(unsigned char) data[0],	/* b_PWM */
-			(unsigned char *) &data[0],	/* pb_TimingUnit */
-			(unsigned int *) &data[1],	/* pul_LowTiming */
-			(unsigned int *) &data[2],	/* pul_HighTiming */
-			(unsigned char *) &data[3],	/*  pb_StartLevel */
-			(unsigned char *) &data[4],	/*  pb_StopMode */
-			(unsigned char *) &data[5],	/*  pb_StopLevel */
-			(unsigned char *) &data[6],	/*  pb_ExternGate */
-			(unsigned char *) &data[7],	/*  pb_InterruptEnable */
-			(unsigned char *) &data[8]	/*  pb_Enable */
-			);
-		break;
-
-	default:
-		printk(" Config Parameter Wrong\n");
-	}
-
-	if (i_ReturnValue >= 0)
-		i_ReturnValue = insn->n;
-	return i_ReturnValue;
-}
+#define APCI1710_PWM_DISABLE		0
+#define APCI1710_PWM_ENABLE		1
+#define APCI1710_PWM_NEWTIMING		2
 
 /*
 +----------------------------------------------------------------------------+
@@ -178,16 +122,17 @@ int i_APCI1710_InsnConfigPWM(struct comedi_device *dev, struct comedi_subdevice
 |                        this board                                          |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_InitPWM(struct comedi_device *dev,
-	unsigned char b_ModulNbr,
-	unsigned char b_PWM,
-	unsigned char b_ClockSelection,
-	unsigned char b_TimingUnit,
-	unsigned int ul_LowTiming,
-	unsigned int ul_HighTiming,
-	unsigned int *pul_RealLowTiming, unsigned int *pul_RealHighTiming)
+static int i_APCI1710_InitPWM(struct comedi_device *dev,
+			      unsigned char b_ModulNbr,
+			      unsigned char b_PWM,
+			      unsigned char b_ClockSelection,
+			      unsigned char b_TimingUnit,
+			      unsigned int ul_LowTiming,
+			      unsigned int ul_HighTiming,
+			      unsigned int *pul_RealLowTiming,
+			      unsigned int *pul_RealHighTiming)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int ul_LowTimerValue = 0;
 	unsigned int ul_HighTimerValue = 0;
@@ -1533,18 +1478,20 @@ int i_APCI1710_InitPWM(struct comedi_device *dev,
 |                         "i_APCI1710_InitPWM"                               |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
-	unsigned char b_ModulNbr,
-	unsigned char b_PWM,
-	unsigned char *pb_TimingUnit,
-	unsigned int *pul_LowTiming,
-	unsigned int *pul_HighTiming,
-	unsigned char *pb_StartLevel,
-	unsigned char *pb_StopMode,
-	unsigned char *pb_StopLevel,
-	unsigned char *pb_ExternGate, unsigned char *pb_InterruptEnable, unsigned char *pb_Enable)
+static int i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
+					   unsigned char b_ModulNbr,
+					   unsigned char b_PWM,
+					   unsigned char *pb_TimingUnit,
+					   unsigned int *pul_LowTiming,
+					   unsigned int *pul_HighTiming,
+					   unsigned char *pb_StartLevel,
+					   unsigned char *pb_StopMode,
+					   unsigned char *pb_StopLevel,
+					   unsigned char *pb_ExternGate,
+					   unsigned char *pb_InterruptEnable,
+					   unsigned char *pb_Enable)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_Status;
 	unsigned int dw_Command;
@@ -1669,51 +1616,47 @@ int i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
 }
 
 /*
-+----------------------------------------------------------------------------+
-| Function Name     :INT i_APCI1710_InsnWritePWM(struct comedi_device *dev,
-struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)                        |
-+----------------------------------------------------------------------------+
-| Task              : Pwm Enable Disable and Set New Timing                  |
-+----------------------------------------------------------------------------+
-| Input Parameters  :
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      :
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI1710_InsnWritePWM(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+ * Pwm Init and Get Pwm Initialisation
+ */
+static int i_APCI1710_InsnConfigPWM(struct comedi_device *dev,
+				    struct comedi_subdevice *s,
+				    struct comedi_insn *insn,
+				    unsigned int *data)
 {
-	unsigned char b_WriteType;
+	unsigned char b_ConfigType;
 	int i_ReturnValue = 0;
-	b_WriteType = CR_CHAN(insn->chanspec);
-
-	switch (b_WriteType) {
-	case APCI1710_PWM_ENABLE:
-		i_ReturnValue = i_APCI1710_EnablePWM(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char) data[0],
-			(unsigned char) data[1],
-			(unsigned char) data[2],
-			(unsigned char) data[3], (unsigned char) data[4], (unsigned char) data[5]);
-		break;
+	b_ConfigType = CR_CHAN(insn->chanspec);
 
-	case APCI1710_PWM_DISABLE:
-		i_ReturnValue = i_APCI1710_DisablePWM(dev,
-			(unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]);
+	switch (b_ConfigType) {
+	case APCI1710_PWM_INIT:
+		i_ReturnValue = i_APCI1710_InitPWM(dev, (unsigned char) CR_AREF(insn->chanspec),	/*   b_ModulNbr */
+			(unsigned char) data[0],	/* b_PWM */
+			(unsigned char) data[1],	/*  b_ClockSelection */
+			(unsigned char) data[2],	/*  b_TimingUnit */
+			(unsigned int) data[3],	/* ul_LowTiming */
+			(unsigned int) data[4],	/* ul_HighTiming */
+			(unsigned int *) &data[0],	/* pul_RealLowTiming */
+			(unsigned int *) &data[1]	/* pul_RealHighTiming */
+			);
 		break;
 
-	case APCI1710_PWM_NEWTIMING:
-		i_ReturnValue = i_APCI1710_SetNewPWMTiming(dev,
-			(unsigned char) CR_AREF(insn->chanspec),
-			(unsigned char) data[0],
-			(unsigned char) data[1], (unsigned int) data[2], (unsigned int) data[3]);
+	case APCI1710_PWM_GETINITDATA:
+		i_ReturnValue = i_APCI1710_GetPWMInitialisation(dev, (unsigned char) CR_AREF(insn->chanspec),	/*  b_ModulNbr */
+			(unsigned char) data[0],	/* b_PWM */
+			(unsigned char *) &data[0],	/* pb_TimingUnit */
+			(unsigned int *) &data[1],	/* pul_LowTiming */
+			(unsigned int *) &data[2],	/* pul_HighTiming */
+			(unsigned char *) &data[3],	/*  pb_StartLevel */
+			(unsigned char *) &data[4],	/*  pb_StopMode */
+			(unsigned char *) &data[5],	/*  pb_StopLevel */
+			(unsigned char *) &data[6],	/*  pb_ExternGate */
+			(unsigned char *) &data[7],	/*  pb_InterruptEnable */
+			(unsigned char *) &data[8]	/*  pb_Enable */
+			);
 		break;
 
 	default:
-		printk("Write Config Parameter Wrong\n");
+		printk(" Config Parameter Wrong\n");
 	}
 
 	if (i_ReturnValue >= 0)
@@ -1805,14 +1748,16 @@ int i_APCI1710_InsnWritePWM(struct comedi_device *dev, struct comedi_subdevice *
 |                         See function "i_APCI1710_SetBoardIntRoutineX"      |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_EnablePWM(struct comedi_device *dev,
-	unsigned char b_ModulNbr,
-	unsigned char b_PWM,
-	unsigned char b_StartLevel,
-	unsigned char b_StopMode,
-	unsigned char b_StopLevel, unsigned char b_ExternGate, unsigned char b_InterruptEnable)
+static int i_APCI1710_EnablePWM(struct comedi_device *dev,
+				unsigned char b_ModulNbr,
+				unsigned char b_PWM,
+				unsigned char b_StartLevel,
+				unsigned char b_StopMode,
+				unsigned char b_StopLevel,
+				unsigned char b_ExternGate,
+				unsigned char b_InterruptEnable)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_Status;
 	unsigned int dw_Command;
@@ -2061,9 +2006,11 @@ int i_APCI1710_EnablePWM(struct comedi_device *dev,
 |                         "i_APCI1710_EnablePWM"                             |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_DisablePWM(struct comedi_device *dev, unsigned char b_ModulNbr, unsigned char b_PWM)
+static int i_APCI1710_DisablePWM(struct comedi_device *dev,
+				 unsigned char b_ModulNbr,
+				 unsigned char b_PWM)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_Status;
 
@@ -2188,11 +2135,14 @@ int i_APCI1710_DisablePWM(struct comedi_device *dev, unsigned char b_ModulNbr, u
 |                    -8: High base timing selection is wrong                 |
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
-	unsigned char b_ModulNbr,
-	unsigned char b_PWM, unsigned char b_TimingUnit, unsigned int ul_LowTiming, unsigned int ul_HighTiming)
+static int i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
+				      unsigned char b_ModulNbr,
+				      unsigned char b_PWM,
+				      unsigned char b_TimingUnit,
+				      unsigned int ul_LowTiming,
+				      unsigned int ul_HighTiming)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned char b_ClockSelection;
 	int i_ReturnValue = 0;
 	unsigned int ul_LowTimerValue = 0;
@@ -3415,6 +3365,49 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
 }
 
 /*
+ * Pwm Enable Disable and Set New Timing
+ */
+static int i_APCI1710_InsnWritePWM(struct comedi_device *dev,
+				   struct comedi_subdevice *s,
+				   struct comedi_insn *insn,
+				   unsigned int *data)
+{
+	unsigned char b_WriteType;
+	int i_ReturnValue = 0;
+	b_WriteType = CR_CHAN(insn->chanspec);
+
+	switch (b_WriteType) {
+	case APCI1710_PWM_ENABLE:
+		i_ReturnValue = i_APCI1710_EnablePWM(dev,
+			(unsigned char) CR_AREF(insn->chanspec),
+			(unsigned char) data[0],
+			(unsigned char) data[1],
+			(unsigned char) data[2],
+			(unsigned char) data[3], (unsigned char) data[4], (unsigned char) data[5]);
+		break;
+
+	case APCI1710_PWM_DISABLE:
+		i_ReturnValue = i_APCI1710_DisablePWM(dev,
+			(unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]);
+		break;
+
+	case APCI1710_PWM_NEWTIMING:
+		i_ReturnValue = i_APCI1710_SetNewPWMTiming(dev,
+			(unsigned char) CR_AREF(insn->chanspec),
+			(unsigned char) data[0],
+			(unsigned char) data[1], (unsigned int) data[2], (unsigned int) data[3]);
+		break;
+
+	default:
+		printk("Write Config Parameter Wrong\n");
+	}
+
+	if (i_ReturnValue >= 0)
+		i_ReturnValue = insn->n;
+	return i_ReturnValue;
+}
+
+/*
 +----------------------------------------------------------------------------+
 | Function Name     : _INT_ i_APCI1710_GetPWMStatus                          |
 |                               (unsigned char_    b_BoardHandle,                     |
@@ -3459,13 +3452,14 @@ int i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
 |                     -6: PWM not enabled see function "i_APCI1710_EnablePWM"|
 +----------------------------------------------------------------------------+
 */
-
-int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev,
+					   struct comedi_subdevice *s,
+					   struct comedi_insn *insn,
+					   unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_Status;
-
 	unsigned char b_ModulNbr;
 	unsigned char b_PWM;
 	unsigned char *pb_PWMOutputStatus;
@@ -3561,9 +3555,13 @@ int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, struct comedi_sub
 	return i_ReturnValue;
 }
 
-int i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device *dev,
+					       struct comedi_subdevice *s,
+					       struct comedi_insn *insn,
+					       unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
+
 	data[0] = devpriv->s_InterruptParameters.
 		s_FIFOInterruptParameters[devpriv->
 		s_InterruptParameters.ui_Read].b_OldModuleMask;
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
deleted file mode 100644
index d8ad0b9..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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 APCI1710_30MHZ		30
-#define APCI1710_33MHZ		33
-#define APCI1710_40MHZ		40
-
-#define APCI1710_PWM_INIT		0
-#define APCI1710_PWM_GETINITDATA	1
-
-#define APCI1710_PWM_DISABLE		0
-#define APCI1710_PWM_ENABLE		1
-#define APCI1710_PWM_NEWTIMING		2
-
-int i_APCI1710_InsnConfigPWM(struct comedi_device *dev, struct comedi_subdevice *s,
-			     struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI1710_InitPWM(struct comedi_device *dev,
-		       unsigned char b_ModulNbr,
-		       unsigned char b_PWM,
-		       unsigned char b_ClockSelection,
-		       unsigned char b_TimingUnit,
-		       unsigned int ul_LowTiming,
-		       unsigned int ul_HighTiming,
-		       unsigned int *pul_RealLowTiming, unsigned int *pul_RealHighTiming);
-
-int i_APCI1710_GetPWMInitialisation(struct comedi_device *dev,
-				    unsigned char b_ModulNbr,
-				    unsigned char b_PWM,
-				    unsigned char *pb_TimingUnit,
-				    unsigned int *pul_LowTiming,
-				    unsigned int *pul_HighTiming,
-				    unsigned char *pb_StartLevel,
-				    unsigned char *pb_StopMode,
-				    unsigned char *pb_StopLevel,
-				    unsigned char *pb_ExternGate,
-				    unsigned char *pb_InterruptEnable, unsigned char *pb_Enable);
-
-int i_APCI1710_InsnWritePWM(struct comedi_device *dev, struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI1710_EnablePWM(struct comedi_device *dev,
-			 unsigned char b_ModulNbr,
-			 unsigned char b_PWM,
-			 unsigned char b_StartLevel,
-			 unsigned char b_StopMode,
-			 unsigned char b_StopLevel, unsigned char b_ExternGate,
-			 unsigned char b_InterruptEnable);
-
-int i_APCI1710_SetNewPWMTiming(struct comedi_device *dev,
-			       unsigned char b_ModulNbr,
-			       unsigned char b_PWM, unsigned char b_TimingUnit,
-			       unsigned int ul_LowTiming, unsigned int ul_HighTiming);
-
-int i_APCI1710_DisablePWM(struct comedi_device *dev, unsigned char b_ModulNbr, unsigned char b_PWM);
-
-int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, struct comedi_subdevice *s,
-				    struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device *dev,
-					struct comedi_subdevice *s,
-					struct comedi_insn *insn, unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
index c13b002..1e05732 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
@@ -40,13 +40,20 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +-----------------------------------------------------------------------+
 */
 
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
+#define APCI1710_30MHZ			30
+#define APCI1710_33MHZ			33
+#define APCI1710_40MHZ			40
 
-#include "APCI1710_Ssi.h"
+#define APCI1710_BINARY_MODE		0x1
+#define APCI1710_GRAY_MODE		0x0
+
+#define APCI1710_SSI_READ1VALUE		1
+#define APCI1710_SSI_READALLVALUE	2
+
+#define APCI1710_SSI_SET_CHANNELON	0
+#define APCI1710_SSI_SET_CHANNELOFF	1
+#define APCI1710_SSI_READ_1CHANNEL	2
+#define APCI1710_SSI_READ_ALLCHANNEL	3
 
 /*
 +----------------------------------------------------------------------------+
@@ -119,9 +126,12 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev,
+					struct comedi_subdevice *s,
+					struct comedi_insn *insn,
+					unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int ui_TimerValue;
 	unsigned char b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength,
@@ -386,9 +396,12 @@ pul_Position	=	(unsigned int *) &data[0];
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev,
+				       struct comedi_subdevice *s,
+				       struct comedi_insn *insn,
+				       unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned char b_Cpt;
 	unsigned char b_Length;
@@ -719,9 +732,12 @@ int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevi
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev,
+					   struct comedi_subdevice *s,
+					   struct comedi_insn *insn,
+					   unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_StatusReg;
 	unsigned char b_ModulNbr;
@@ -729,6 +745,7 @@ int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_sub
 	unsigned char *pb_ChannelStatus;
 	unsigned char *pb_InputStatus;
 	unsigned char b_IOType;
+
 	i_ReturnValue = insn->n;
 	b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
 	b_IOType = (unsigned char) data[0];
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
deleted file mode 100644
index ef4d887..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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 APCI1710_30MHZ		30
-#define APCI1710_33MHZ		33
-#define APCI1710_40MHZ		40
-
-#define APCI1710_BINARY_MODE	0x1
-#define APCI1710_GRAY_MODE	0x0
-
-#define APCI1710_SSI_READ1VALUE		1
-#define APCI1710_SSI_READALLVALUE	2
-
-#define APCI1710_SSI_SET_CHANNELON	0
-#define APCI1710_SSI_SET_CHANNELOFF	1
-#define APCI1710_SSI_READ_1CHANNEL	2
-#define APCI1710_SSI_READ_ALLCHANNEL	3
-
-/*
- * SSI INISIALISATION FUNCTION
- */
-int i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
-				    struct comedi_insn *insn, unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
index 0e6affd..3bc9826 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
@@ -52,13 +52,22 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +-----------------------------------------------------------------------+
 */
 
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
+#define APCI1710_30MHZ			30
+#define APCI1710_33MHZ			33
+#define APCI1710_40MHZ			40
 
-#include "APCI1710_Tor.h"
+#define APCI1710_GATE_INPUT		10
+
+#define APCI1710_TOR_SIMPLE_MODE	2
+#define APCI1710_TOR_DOUBLE_MODE	3
+#define APCI1710_TOR_QUADRUPLE_MODE	4
+
+#define APCI1710_SINGLE			0
+#define APCI1710_CONTINUOUS		1
+
+#define APCI1710_TOR_GETPROGRESSSTATUS	0
+#define APCI1710_TOR_GETCOUNTERVALUE	1
+#define APCI1710_TOR_READINTERRUPT	2
 
 /*
 +----------------------------------------------------------------------------+
@@ -130,9 +139,12 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev,
+					       struct comedi_subdevice *s,
+					       struct comedi_insn *insn,
+					       unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int ul_TimerValue = 0;
 	unsigned int dw_Command;
@@ -987,9 +999,12 @@ int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev,
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev,
+						       struct comedi_subdevice *s,
+						       struct comedi_insn *insn,
+						       unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_Status;
 	unsigned int dw_DummyRead;
@@ -1460,9 +1475,12 @@ int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev,
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
+							  struct comedi_subdevice *s,
+							  struct comedi_insn *insn,
+							  unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_Status;
 	unsigned char b_ModulNbr;
@@ -1700,13 +1718,15 @@ int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device *dev,
+								  struct comedi_subdevice *s,
+								  struct comedi_insn *insn,
+								  unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_Status;
 	unsigned int dw_TimeOut = 0;
-
 	unsigned char b_ModulNbr;
 	unsigned char b_TorCounter;
 	unsigned char b_ReadType;
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
deleted file mode 100644
index 537d475..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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 APCI1710_30MHZ		30
-#define APCI1710_33MHZ		33
-#define APCI1710_40MHZ		40
-
-#define APCI1710_GATE_INPUT	10
-
-#define APCI1710_TOR_SIMPLE_MODE	2
-#define APCI1710_TOR_DOUBLE_MODE	3
-#define APCI1710_TOR_QUADRUPLE_MODE	4
-
-#define APCI1710_SINGLE			0
-#define APCI1710_CONTINUOUS		1
-
-#define APCI1710_TOR_GETPROGRESSSTATUS	0
-#define APCI1710_TOR_GETCOUNTERVALUE	1
-#define APCI1710_TOR_READINTERRUPT	2
-
-/*
- * TOR_COUNTER INISIALISATION FUNCTION
- */
-int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev,
-					struct comedi_subdevice *s,
-					struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev,
-						struct comedi_subdevice *s,
-						struct comedi_insn *insn,
-						unsigned int *data);
-
-int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev,
-						   struct comedi_subdevice *s,
-						   struct comedi_insn *insn,
-						   unsigned int *data);
-/*
- * TOR_COUNTER READ FUNCTION
- */
-int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device *dev,
-							   struct comedi_subdevice *s,
-							   struct comedi_insn *insn,
-							   unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
index 9e177f4..c8238b8 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
@@ -52,13 +52,11 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +-----------------------------------------------------------------------+
 */
 
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
+#define APCI1710_TTL_INIT		0
+#define APCI1710_TTL_INITDIRECTION	1
 
-#include "APCI1710_Ttl.h"
+#define APCI1710_TTL_READCHANNEL	0
+#define APCI1710_TTL_READPORT		1
 
 /*
 +----------------------------------------------------------------------------+
@@ -100,9 +98,12 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev,
+					  struct comedi_subdevice *s,
+					  struct comedi_insn *insn,
+					  unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned char b_ModulNbr;
 	unsigned char b_InitType;
@@ -406,9 +407,12 @@ APCI1710_TTL_READCHANNEL
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev,
+					struct comedi_subdevice *s,
+					struct comedi_insn *insn,
+					unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_StatusReg;
 	unsigned char b_ModulNbr;
@@ -655,9 +659,12 @@ int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, struct comedi_subdev
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
+						struct comedi_subdevice *s,
+						struct comedi_insn *insn,
+						unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_StatusReg;
 	unsigned char b_ModulNbr;
@@ -825,9 +832,12 @@ int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,struct comedi
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,
+						struct comedi_subdevice *s,
+						struct comedi_insn *insn,
+						unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = 0;
 	unsigned int dw_StatusReg = 0;
 	unsigned char b_ModulNbr;
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
deleted file mode 100644
index adcab82..0000000
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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 APCI1710_TTL_INIT		0
-#define APCI1710_TTL_INITDIRECTION	1
-
-#define APCI1710_TTL_READCHANNEL	0
-#define APCI1710_TTL_READPORT		1
-
-/*
- * TTL INISIALISATION FUNCTION
- */
-int i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data);
-
-/*
- * TTL INPUT FUNCTION
- */
-int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-int i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
-					 struct comedi_subdevice *s,
-					 struct comedi_insn *insn, unsigned int *data);
-
-/*
- * TTL OUTPUT FUNCTIONS
- */
-int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,
-					 struct comedi_subdevice *s,
-					 struct comedi_insn *insn, unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h b/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h
deleted file mode 100644
index 95f7dc6..0000000
--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- *  Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/* Header file for AMCC  s 5933 */
-
-#ifndef _AMCC_S5933_H_
-#define _AMCC_S5933_H_
-
-#include "../../comedidev.h"
-
-/* written on base0 */
-#define FIFO_ADVANCE_ON_BYTE_2	0x20000000
-
-/* added for step 6 dma written on base2 */
-#define AMWEN_ENABLE		0x02
-
-#define A2P_FIFO_WRITE_ENABLE	0x01
-
-/* for transfer count enable bit */
-#define AGCSTS_TC_ENABLE	0x10000000
-
-/*
- * ADDON RELATED ADDITIONS
- */
-/* Constant */
-#define APCI3120_ENABLE_TRANSFER_ADD_ON_LOW		0x00
-#define APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH		0x1200
-#define APCI3120_A2P_FIFO_MANAGEMENT			0x04000400L
-#define APCI3120_AMWEN_ENABLE				0x02
-#define APCI3120_A2P_FIFO_WRITE_ENABLE			0x01
-#define APCI3120_FIFO_ADVANCE_ON_BYTE_2			0x20000000L
-#define APCI3120_ENABLE_WRITE_TC_INT			0x00004000L
-#define APCI3120_CLEAR_WRITE_TC_INT			0x00040000L
-#define APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE	0x0
-#define APCI3120_DISABLE_BUS_MASTER_ADD_ON		0x0
-#define APCI3120_DISABLE_BUS_MASTER_PCI			0x0
-
-/* ADD_ON ::: this needed since apci supports 16 bit interface to add on */
-#define APCI3120_ADD_ON_AGCSTS_LOW	0x3C
-#define APCI3120_ADD_ON_AGCSTS_HIGH	(APCI3120_ADD_ON_AGCSTS_LOW + 2)
-#define APCI3120_ADD_ON_MWAR_LOW	0x24
-#define APCI3120_ADD_ON_MWAR_HIGH	(APCI3120_ADD_ON_MWAR_LOW + 2)
-#define APCI3120_ADD_ON_MWTC_LOW	0x058
-#define APCI3120_ADD_ON_MWTC_HIGH	(APCI3120_ADD_ON_MWTC_LOW + 2)
-
-/* AMCC */
-#define APCI3120_AMCC_OP_MCSR		0x3C
-#define APCI3120_AMCC_OP_REG_INTCSR	0x38
-
-/*
- * AMCC Operation Register Offsets - PCI
- */
-#define AMCC_OP_REG_OMB1		0x00
-#define AMCC_OP_REG_OMB2		0x04
-#define AMCC_OP_REG_OMB3		0x08
-#define AMCC_OP_REG_OMB4		0x0c
-#define AMCC_OP_REG_IMB1		0x10
-#define AMCC_OP_REG_IMB2		0x14
-#define AMCC_OP_REG_IMB3		0x18
-#define AMCC_OP_REG_IMB4		0x1c
-#define AMCC_OP_REG_FIFO		0x20
-#define AMCC_OP_REG_MWAR		0x24
-#define AMCC_OP_REG_MWTC		0x28
-#define AMCC_OP_REG_MRAR		0x2c
-#define AMCC_OP_REG_MRTC		0x30
-#define AMCC_OP_REG_MBEF		0x34
-#define AMCC_OP_REG_INTCSR		0x38
-/* int source */
-#define  AMCC_OP_REG_INTCSR_SRC		(AMCC_OP_REG_INTCSR + 2)
-/* FIFO ctrl */
-#define  AMCC_OP_REG_INTCSR_FEC		(AMCC_OP_REG_INTCSR + 3)
-#define AMCC_OP_REG_MCSR		0x3c
-/* Data in byte 2 */
-#define  AMCC_OP_REG_MCSR_NVDATA	(AMCC_OP_REG_MCSR + 2)
-/* Command in byte 3 */
-#define  AMCC_OP_REG_MCSR_NVCMD		(AMCC_OP_REG_MCSR + 3)
-
-#define AMCC_FIFO_DEPTH_DWORD	8
-#define AMCC_FIFO_DEPTH_BYTES	(8 * sizeof(u32))
-
-/*
- * AMCC Operation Registers Size - PCI
- */
-#define AMCC_OP_REG_SIZE	 64	/* in bytes */
-
-/*
- * AMCC Operation Register Offsets - Add-on
- */
-#define AMCC_OP_REG_AIMB1	0x00
-#define AMCC_OP_REG_AIMB2	0x04
-#define AMCC_OP_REG_AIMB3	0x08
-#define AMCC_OP_REG_AIMB4	0x0c
-#define AMCC_OP_REG_AOMB1	0x10
-#define AMCC_OP_REG_AOMB2	0x14
-#define AMCC_OP_REG_AOMB3	0x18
-#define AMCC_OP_REG_AOMB4	0x1c
-#define AMCC_OP_REG_AFIFO	0x20
-#define AMCC_OP_REG_AMWAR	0x24
-#define AMCC_OP_REG_APTA	0x28
-#define AMCC_OP_REG_APTD	0x2c
-#define AMCC_OP_REG_AMRAR	0x30
-#define AMCC_OP_REG_AMBEF	0x34
-#define AMCC_OP_REG_AINT	0x38
-#define AMCC_OP_REG_AGCSTS	0x3c
-#define AMCC_OP_REG_AMWTC	0x58
-#define AMCC_OP_REG_AMRTC	0x5c
-
-/*
- * AMCC - Add-on General Control/Status Register
- */
-#define AGCSTS_CONTROL_MASK	0xfffff000
-#define  AGCSTS_NV_ACC_MASK	0xe0000000
-#define  AGCSTS_RESET_MASK	0x0e000000
-#define  AGCSTS_NV_DA_MASK	0x00ff0000
-#define  AGCSTS_BIST_MASK	0x0000f000
-#define AGCSTS_STATUS_MASK	0x000000ff
-#define  AGCSTS_TCZERO_MASK	0x000000c0
-#define  AGCSTS_FIFO_ST_MASK	0x0000003f
-
-#define AGCSTS_RESET_MBFLAGS	0x08000000
-#define AGCSTS_RESET_P2A_FIFO	0x04000000
-#define AGCSTS_RESET_A2P_FIFO	0x02000000
-#define AGCSTS_RESET_FIFOS	(AGCSTS_RESET_A2P_FIFO | AGCSTS_RESET_P2A_FIFO)
-
-#define AGCSTS_A2P_TCOUNT	0x00000080
-#define AGCSTS_P2A_TCOUNT	0x00000040
-
-#define AGCSTS_FS_P2A_EMPTY	0x00000020
-#define AGCSTS_FS_P2A_HALF	0x00000010
-#define AGCSTS_FS_P2A_FULL	0x00000008
-
-#define AGCSTS_FS_A2P_EMPTY	0x00000004
-#define AGCSTS_FS_A2P_HALF	0x00000002
-#define AGCSTS_FS_A2P_FULL	0x00000001
-
-/*
- * AMCC - Add-on Interrupt Control/Status Register
- */
-#define AINT_INT_MASK		0x00ff0000
-#define AINT_SEL_MASK		0x0000ffff
-#define  AINT_IS_ENSEL_MASK	0x00001f1f
-
-#define AINT_INT_ASSERTED	0x00800000
-#define AINT_BM_ERROR		0x00200000
-#define AINT_BIST_INT		0x00100000
-
-#define AINT_RT_COMPLETE	0x00080000
-#define AINT_WT_COMPLETE	0x00040000
-
-#define AINT_OUT_MB_INT		0x00020000
-#define AINT_IN_MB_INT		0x00010000
-
-#define AINT_READ_COMPL		0x00008000
-#define AINT_WRITE_COMPL	0x00004000
-
-#define AINT_OMB_ENABLE 	0x00001000
-#define AINT_OMB_SELECT 	0x00000c00
-#define AINT_OMB_BYTE		0x00000300
-
-#define AINT_IMB_ENABLE 	0x00000010
-#define AINT_IMB_SELECT 	0x0000000c
-#define AINT_IMB_BYTE		0x00000003
-
-/* Enable Bus Mastering */
-#define EN_A2P_TRANSFERS	0x00000400
-/* FIFO Flag Reset */
-#define RESET_A2P_FLAGS		0x04000000L
-/* FIFO Relative Priority */
-#define A2P_HI_PRIORITY		0x00000100L
-/* Identify Interrupt Sources */
-#define ANY_S593X_INT		0x00800000L
-#define READ_TC_INT		0x00080000L
-#define WRITE_TC_INT		0x00040000L
-#define IN_MB_INT		0x00020000L
-#define MASTER_ABORT_INT	0x00100000L
-#define TARGET_ABORT_INT	0x00200000L
-#define BUS_MASTER_INT		0x00200000L
-
-/****************************************************************************/
-
-struct pcilst_struct {
-	struct pcilst_struct *next;
-	int used;
-	struct pci_dev *pcidev;
-	unsigned short vendor;
-	unsigned short device;
-	unsigned char pci_bus;
-	unsigned char pci_slot;
-	unsigned char pci_func;
-	resource_size_t io_addr[5];
-	unsigned int irq;
-};
-
-/* ptr to root list of all amcc devices */
-static struct pcilst_struct *amcc_devices;
-
-static const int i_ADDIDATADeviceID[] = { 0x15B8, 0x10E8 };
-
-/****************************************************************************/
-
-void v_pci_card_list_init(unsigned short pci_vendor, char display);
-void v_pci_card_list_cleanup(unsigned short pci_vendor);
-struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id,
-						       unsigned short
-						       device_id);
-int i_find_free_pci_card_by_position(unsigned short vendor_id,
-				     unsigned short device_id,
-				     unsigned short pci_bus,
-				     unsigned short pci_slot,
-				     struct pcilst_struct **card);
-struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
-						    unsigned short device_id,
-						    unsigned short pci_bus,
-						    unsigned short pci_slot,
-						    int i_Master);
-
-int pci_card_alloc(struct pcilst_struct *amcc, int master);
-int i_pci_card_free(struct pcilst_struct *amcc);
-void v_pci_card_list_display(void);
-int i_pci_card_data(struct pcilst_struct *amcc,
-		    unsigned char *pci_bus, unsigned char *pci_slot,
-		    unsigned char *pci_func, resource_size_t * io_addr,
-		    unsigned int *irq);
-
-/****************************************************************************/
-
-/* build list of amcc cards in this system */
-void v_pci_card_list_init(unsigned short pci_vendor, char display)
-{
-	struct pci_dev *pcidev = NULL;
-	struct pcilst_struct *amcc, *last;
-	int i;
-	int i_Count = 0;
-	amcc_devices = NULL;
-	last = NULL;
-
-	for_each_pci_dev(pcidev) {
-		for (i_Count = 0; i_Count < 2; i_Count++) {
-			pci_vendor = i_ADDIDATADeviceID[i_Count];
-			if (pcidev->vendor == pci_vendor) {
-				amcc = kzalloc(sizeof(*amcc), GFP_KERNEL);
-				if (amcc == NULL)
-					continue;
-
-				amcc->pcidev = pcidev;
-				if (last)
-					last->next = amcc;
-				else
-					amcc_devices = amcc;
-				last = amcc;
-
-				amcc->vendor = pcidev->vendor;
-				amcc->device = pcidev->device;
-				amcc->pci_bus = pcidev->bus->number;
-				amcc->pci_slot = PCI_SLOT(pcidev->devfn);
-				amcc->pci_func = PCI_FUNC(pcidev->devfn);
-				/* Note: resources may be invalid if PCI device
-				 * not enabled, but they are corrected in
-				 * pci_card_alloc. */
-				for (i = 0; i < 5; i++)
-					amcc->io_addr[i] =
-					    pci_resource_start(pcidev, i);
-				amcc->irq = pcidev->irq;
-
-			}
-		}
-	}
-
-	if (display)
-		v_pci_card_list_display();
-}
-
-/****************************************************************************/
-/* free up list of amcc cards in this system */
-void v_pci_card_list_cleanup(unsigned short pci_vendor)
-{
-	struct pcilst_struct *amcc, *next;
-
-	for (amcc = amcc_devices; amcc; amcc = next) {
-		next = amcc->next;
-		kfree(amcc);
-	}
-
-	amcc_devices = NULL;
-}
-
-/****************************************************************************/
-/* find first unused card with this device_id */
-struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id,
-						       unsigned short device_id)
-{
-	struct pcilst_struct *amcc, *next;
-
-	for (amcc = amcc_devices; amcc; amcc = next) {
-		next = amcc->next;
-		if ((!amcc->used) && (amcc->device == device_id)
-		    && (amcc->vendor == vendor_id))
-			return amcc;
-
-	}
-
-	return NULL;
-}
-
-/****************************************************************************/
-/* find card on requested position */
-int i_find_free_pci_card_by_position(unsigned short vendor_id,
-				     unsigned short device_id,
-				     unsigned short pci_bus,
-				     unsigned short pci_slot,
-				     struct pcilst_struct **card)
-{
-	struct pcilst_struct *amcc, *next;
-
-	*card = NULL;
-	for (amcc = amcc_devices; amcc; amcc = next) {
-		next = amcc->next;
-		if ((amcc->vendor == vendor_id) && (amcc->device == device_id)
-		    && (amcc->pci_bus == pci_bus)
-		    && (amcc->pci_slot == pci_slot)) {
-			if (!(amcc->used)) {
-				*card = amcc;
-				return 0;	/* ok, card is found */
-			} else {
-				printk(" - \nCard on requested position is used b:s %d:%d!\n",
-					  pci_bus, pci_slot);
-				return 2;	/* card exist but is used */
-			}
-		}
-	}
-
-	/* no card found */
-	return 1;
-}
-
-/****************************************************************************/
-/* mark card as used */
-int pci_card_alloc(struct pcilst_struct *amcc, int master)
-{
-	int i;
-
-	if (!amcc)
-		return -1;
-
-	if (amcc->used)
-		return 1;
-	if (comedi_pci_enable(amcc->pcidev, "addi_amcc_s5933"))
-		return -1;
-	/* Resources will be accurate now. */
-	for (i = 0; i < 5; i++)
-		amcc->io_addr[i] = pci_resource_start(amcc->pcidev, i);
-	if (master)
-		pci_set_master(amcc->pcidev);
-	amcc->used = 1;
-
-	return 0;
-}
-
-/****************************************************************************/
-/* mark card as free */
-int i_pci_card_free(struct pcilst_struct *amcc)
-{
-	if (!amcc)
-		return -1;
-
-	if (!amcc->used)
-		return 1;
-	amcc->used = 0;
-	comedi_pci_disable(amcc->pcidev);
-	return 0;
-}
-
-/****************************************************************************/
-/* display list of found cards */
-void v_pci_card_list_display(void)
-{
-	struct pcilst_struct *amcc, *next;
-
-	printk(KERN_DEBUG "List of pci cards\n");
-	printk(KERN_DEBUG "bus:slot:func vendor device io_amcc io_daq irq used\n");
-
-	for (amcc = amcc_devices; amcc; amcc = next) {
-		next = amcc->next;
-		printk
-		    ("%2d   %2d   %2d  0x%4x 0x%4x   0x%8llx 0x%8llx  %2u  %2d\n",
-		     amcc->pci_bus, amcc->pci_slot, amcc->pci_func,
-		     amcc->vendor, amcc->device,
-		     (unsigned long long)amcc->io_addr[0],
-		     (unsigned long long)amcc->io_addr[2], amcc->irq,
-		     amcc->used);
-
-	}
-}
-
-/****************************************************************************/
-/* return all card information for driver */
-int i_pci_card_data(struct pcilst_struct *amcc,
-		    unsigned char *pci_bus, unsigned char *pci_slot,
-		    unsigned char *pci_func, resource_size_t * io_addr,
-		    unsigned int *irq)
-{
-	int i;
-
-	if (!amcc)
-		return -1;
-	*pci_bus = amcc->pci_bus;
-	*pci_slot = amcc->pci_slot;
-	*pci_func = amcc->pci_func;
-	for (i = 0; i < 5; i++)
-		io_addr[i] = amcc->io_addr[i];
-	*irq = amcc->irq;
-	return 0;
-}
-
-/****************************************************************************/
-/* select and alloc card */
-struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id,
-						    unsigned short device_id,
-						    unsigned short pci_bus,
-						    unsigned short pci_slot,
-						    int i_Master)
-{
-	struct pcilst_struct *card;
-
-	if ((pci_bus < 1) & (pci_slot < 1)) {
-		/* use autodetection */
-		card = ptr_find_free_pci_card_by_device(vendor_id, device_id);
-		if (card == NULL) {
-			printk(" - Unused card not found in system!\n");
-			return NULL;
-		}
-	} else {
-		switch (i_find_free_pci_card_by_position(vendor_id, device_id,
-							 pci_bus, pci_slot,
-							 &card)) {
-		case 1:
-			printk(" - Card not found on requested position b:s %d:%d!\n",
-				  pci_bus, pci_slot);
-			return NULL;
-		case 2:
-			printk(" - Card on requested position is used b:s %d:%d!\n",
-				  pci_bus, pci_slot);
-			return NULL;
-		}
-	}
-
-	if (pci_card_alloc(card, i_Master) != 0) {
-		printk(" - Can't allocate card!\n");
-		return NULL;
-
-	}
-
-	return card;
-}
-#endif
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
index 99a96bd..90cc432 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -36,1518 +36,107 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +-----------------------------------------------------------------------+
   | Description : ADDI COMMON Main Module                                 |
   +-----------------------------------------------------------------------+
-  | CONFIG OPTIONS                                                        |
-  |	option[0] - PCI bus number - if bus number and slot number are 0, |
-  |			         then driver search for first unused card |
-  |	option[1] - PCI slot number                                       |
-  |							                  |
-  |	option[2] = 0  - DMA ENABLE                                       |
-  |               = 1  - DMA DISABLE                                      |
-  +----------+-----------+------------------------------------------------+
 */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/timer.h>
-#include <linux/pci.h>
-#include <linux/gfp.h>
-#include <linux/io.h>
-#include "../../comedidev.h"
-#if defined(CONFIG_APCI_1710) || defined(CONFIG_APCI_3200) || defined(CONFIG_APCI_3300)
-#include <asm/i387.h>
-#endif
-#include "../comedi_fc.h"
-
-#include "addi_common.h"
-#include "addi_amcc_s5933.h"
-
-#ifndef ADDIDATA_DRIVER_NAME
-#define ADDIDATA_DRIVER_NAME	"addi_common"
-#endif
-
-/* Update-0.7.57->0.7.68MODULE_AUTHOR("ADDI-DATA GmbH <info@addi-data.com>"); */
-/* Update-0.7.57->0.7.68MODULE_DESCRIPTION("Comedi ADDI-DATA module"); */
-/* Update-0.7.57->0.7.68MODULE_LICENSE("GPL"); */
-
-#define devpriv ((struct addi_private *)dev->private)
-#define this_board ((const struct addi_board *)dev->board_ptr)
-
-#if defined(CONFIG_APCI_1710) || defined(CONFIG_APCI_3200) || defined(CONFIG_APCI_3300)
-/* BYTE b_SaveFPUReg [94]; */
-
-void fpu_begin(void)
-{
-	/* asm ("fstenv b_SaveFPUReg"); */
-	kernel_fpu_begin();
-}
-
-void fpu_end(void)
-{
-	/*  asm ("frstor b_SaveFPUReg"); */
-	kernel_fpu_end();
-}
-#endif
-
-#include "addi_eeprom.c"
-#if (defined (CONFIG_APCI_3120) || defined (CONFIG_APCI_3001))
-#include "hwdrv_apci3120.c"
-#endif
-#ifdef CONFIG_APCI_1032
-#include "hwdrv_apci1032.c"
-#endif
-#ifdef CONFIG_APCI_1516
-#include "hwdrv_apci1516.c"
-#endif
-#ifdef CONFIG_APCI_2016
-#include "hwdrv_apci2016.c"
-#endif
-#ifdef CONFIG_APCI_2032
-#include "hwdrv_apci2032.c"
-#endif
-#ifdef CONFIG_APCI_2200
-#include "hwdrv_apci2200.c"
-#endif
-#ifdef CONFIG_APCI_1564
-#include "hwdrv_apci1564.c"
-#endif
-#ifdef CONFIG_APCI_1500
-#include "hwdrv_apci1500.c"
-#endif
-#ifdef CONFIG_APCI_3501
-#include "hwdrv_apci3501.c"
-#endif
-#ifdef CONFIG_APCI_035
-#include "hwdrv_apci035.c"
-#endif
-#if (defined (CONFIG_APCI_3200) || defined (CONFIG_APCI_3300))
-#include "hwdrv_apci3200.c"
-#endif
-#ifdef CONFIG_APCI_1710
-#include "hwdrv_APCI1710.c"
-#endif
-#ifdef CONFIG_APCI_16XX
-#include "hwdrv_apci16xx.c"
-#endif
-#ifdef CONFIG_APCI_3XXX
-#include "hwdrv_apci3xxx.c"
-#endif
-
 #ifndef COMEDI_SUBD_TTLIO
 #define COMEDI_SUBD_TTLIO   11	/* Digital Input Output But TTL */
 #endif
 
-static DEFINE_PCI_DEVICE_TABLE(addi_apci_tbl) = {
-#ifdef CONFIG_APCI_3120
-	{PCI_DEVICE(APCI3120_BOARD_VENDOR_ID, 0x818D)},
-#endif
-#ifdef CONFIG_APCI_1032
-	{PCI_DEVICE(APCI1032_BOARD_VENDOR_ID, 0x1003)},
-#endif
-#ifdef CONFIG_APCI_1516
-	{PCI_DEVICE(APCI1516_BOARD_VENDOR_ID, 0x1001)},
-#endif
-#ifdef CONFIG_APCI_2016
-	{PCI_DEVICE(APCI2016_BOARD_VENDOR_ID, 0x1002)},
-#endif
-#ifdef CONFIG_APCI_2032
-	{PCI_DEVICE(APCI2032_BOARD_VENDOR_ID, 0x1004)},
-#endif
-#ifdef CONFIG_APCI_2200
-	{PCI_DEVICE(APCI2200_BOARD_VENDOR_ID, 0x1005)},
-#endif
-#ifdef CONFIG_APCI_1564
-	{PCI_DEVICE(APCI1564_BOARD_VENDOR_ID, 0x1006)},
-#endif
-#ifdef CONFIG_APCI_1500
-	{PCI_DEVICE(APCI1500_BOARD_VENDOR_ID, 0x80fc)},
-#endif
-#ifdef CONFIG_APCI_3001
-	{PCI_DEVICE(APCI3120_BOARD_VENDOR_ID, 0x828D)},
-#endif
-#ifdef CONFIG_APCI_3501
-	{PCI_DEVICE(APCI3501_BOARD_VENDOR_ID, 0x3001)},
-#endif
-#ifdef CONFIG_APCI_035
-	{PCI_DEVICE(APCI035_BOARD_VENDOR_ID,  0x0300)},
-#endif
-#ifdef CONFIG_APCI_3200
-	{PCI_DEVICE(APCI3200_BOARD_VENDOR_ID, 0x3000)},
-#endif
-#ifdef CONFIG_APCI_3300
-	{PCI_DEVICE(APCI3200_BOARD_VENDOR_ID, 0x3007)},
-#endif
-#ifdef CONFIG_APCI_1710
-	{PCI_DEVICE(APCI1710_BOARD_VENDOR_ID, APCI1710_BOARD_DEVICE_ID)},
-#endif
-#ifdef CONFIG_APCI_16XX
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1009)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x100A)},
-#endif
-#ifdef CONFIG_APCI_3XXX
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3010)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x300F)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x300E)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3013)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3014)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3015)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3016)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3017)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3018)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3019)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301A)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301B)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301C)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301D)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301E)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301F)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3020)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3021)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3022)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3023)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x300B)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3002)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3003)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3004)},
-	{PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3024)},
-#endif
-	{0}
-};
-
-MODULE_DEVICE_TABLE(pci, addi_apci_tbl);
-
-static const struct addi_board boardtypes[] = {
-#ifdef CONFIG_APCI_3120
-	{
-		.pc_DriverName		= "apci3120",
-		.i_VendorId		= APCI3120_BOARD_VENDOR_ID,
-		.i_DeviceId		= 0x818D,
-		.i_IorangeBase0		= AMCC_OP_REG_SIZE,
-		.i_IorangeBase1		= APCI3120_ADDRESS_RANGE,
-		.i_IorangeBase2		= 8,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.i_NbrAiChannel		= 16,
-		.i_NbrAiChannelDiff	= 8,
-		.i_AiChannelList	= 16,
-		.i_NbrAoChannel		= 8,
-		.i_AiMaxdata		= 0xffff,
-		.i_AoMaxdata		= 0x3fff,
-		.pr_AiRangelist		= &range_apci3120_ai,
-		.pr_AoRangelist		= &range_apci3120_ao,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.i_DoMaxdata		= 0x0f,
-		.i_Dma			= 1,
-		.i_Timer		= 1,
-		.b_AvailableConvertUnit	= 1,
-		.ui_MinAcquisitiontimeNs = 10000,
-		.ui_MinDelaytimeNs	= 100000,
-		.interrupt		= v_APCI3120_Interrupt,
-		.reset			= i_APCI3120_Reset,
-		.ai_config		= i_APCI3120_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3120_InsnReadAnalogInput,
-		.ai_cmdtest		= i_APCI3120_CommandTestAnalogInput,
-		.ai_cmd			= i_APCI3120_CommandAnalogInput,
-		.ai_cancel		= i_APCI3120_StopCyclicAcquisition,
-		.ao_write		= i_APCI3120_InsnWriteAnalogOutput,
-		.di_read		= i_APCI3120_InsnReadDigitalInput,
-		.di_bits		= i_APCI3120_InsnBitsDigitalInput,
-		.do_config		= i_APCI3120_InsnConfigDigitalOutput,
-		.do_write		= i_APCI3120_InsnWriteDigitalOutput,
-		.do_bits		= i_APCI3120_InsnBitsDigitalOutput,
-		.timer_config		= i_APCI3120_InsnConfigTimer,
-		.timer_write		= i_APCI3120_InsnWriteTimer,
-		.timer_read		= i_APCI3120_InsnReadTimer,
-	},
-#endif
-#ifdef CONFIG_APCI_1032
-	{
-		.pc_DriverName		= "apci1032",
-		.i_VendorId		= APCI1032_BOARD_VENDOR_ID,
-		.i_DeviceId		= 0x1003,
-		.i_IorangeBase0		= 4,
-		.i_IorangeBase1		= APCI1032_ADDRESS_RANGE,
-		.i_PCIEeprom		= ADDIDATA_EEPROM,
-		.pc_EepromChip		= ADDIDATA_93C76,
-		.i_NbrDiChannel		= 32,
-		.interrupt		= v_APCI1032_Interrupt,
-		.reset			= i_APCI1032_Reset,
-		.di_config		= i_APCI1032_ConfigDigitalInput,
-		.di_read		= i_APCI1032_Read1DigitalInput,
-		.di_bits		= i_APCI1032_ReadMoreDigitalInput,
-	},
-#endif
-#ifdef CONFIG_APCI_1516
-	{
-		.pc_DriverName		= "apci1516",
-		.i_VendorId		= APCI1516_BOARD_VENDOR_ID,
-		.i_DeviceId		= 0x1001,
-		.i_IorangeBase0		= 128,
-		.i_IorangeBase1		= APCI1516_ADDRESS_RANGE,
-		.i_IorangeBase2		= 32,
-		.i_PCIEeprom		= ADDIDATA_EEPROM,
-		.pc_EepromChip		= ADDIDATA_S5920,
-		.i_NbrDiChannel		= 8,
-		.i_NbrDoChannel		= 8,
-		.i_Timer		= 1,
-		.reset			= i_APCI1516_Reset,
-		.di_read		= i_APCI1516_Read1DigitalInput,
-		.di_bits		= i_APCI1516_ReadMoreDigitalInput,
-		.do_config		= i_APCI1516_ConfigDigitalOutput,
-		.do_write		= i_APCI1516_WriteDigitalOutput,
-		.do_bits		= i_APCI1516_ReadDigitalOutput,
-		.timer_config		= i_APCI1516_ConfigWatchdog,
-		.timer_write		= i_APCI1516_StartStopWriteWatchdog,
-		.timer_read		= i_APCI1516_ReadWatchdog,
-	},
-#endif
-#ifdef CONFIG_APCI_2016
-	{
-		.pc_DriverName		= "apci2016",
-		.i_VendorId		= APCI2016_BOARD_VENDOR_ID,
-		.i_DeviceId		= 0x1002,
-		.i_IorangeBase0		= 128,
-		.i_IorangeBase1		= APCI2016_ADDRESS_RANGE,
-		.i_IorangeBase2		= 32,
-		.i_PCIEeprom		= ADDIDATA_EEPROM,
-		.pc_EepromChip		= ADDIDATA_S5920,
-		.i_NbrDoChannel		= 16,
-		.i_Timer		= 1,
-		.reset			= i_APCI2016_Reset,
-		.do_config		= i_APCI2016_ConfigDigitalOutput,
-		.do_write		= i_APCI2016_WriteDigitalOutput,
-		.do_bits		= i_APCI2016_BitsDigitalOutput,
-		.timer_config		= i_APCI2016_ConfigWatchdog,
-		.timer_write		= i_APCI2016_StartStopWriteWatchdog,
-		.timer_read		= i_APCI2016_ReadWatchdog,
-	},
-#endif
-#ifdef CONFIG_APCI_2032
-	{
-		.pc_DriverName		= "apci2032",
-		.i_VendorId		= APCI2032_BOARD_VENDOR_ID,
-		.i_DeviceId		= 0x1004,
-		.i_IorangeBase0		= 4,
-		.i_IorangeBase1		= APCI2032_ADDRESS_RANGE,
-		.i_PCIEeprom		= ADDIDATA_EEPROM,
-		.pc_EepromChip		= ADDIDATA_93C76,
-		.i_NbrDoChannel		= 32,
-		.i_DoMaxdata		= 0xffffffff,
-		.i_Timer		= 1,
-		.interrupt		= v_APCI2032_Interrupt,
-		.reset			= i_APCI2032_Reset,
-		.do_config		= i_APCI2032_ConfigDigitalOutput,
-		.do_write		= i_APCI2032_WriteDigitalOutput,
-		.do_bits		= i_APCI2032_ReadDigitalOutput,
-		.do_read		= i_APCI2032_ReadInterruptStatus,
-		.timer_config		= i_APCI2032_ConfigWatchdog,
-		.timer_write		= i_APCI2032_StartStopWriteWatchdog,
-		.timer_read		= i_APCI2032_ReadWatchdog,
-	},
-#endif
-#ifdef CONFIG_APCI_2200
-	{
-		.pc_DriverName		= "apci2200",
-		.i_VendorId		= APCI2200_BOARD_VENDOR_ID,
-		.i_DeviceId		= 0x1005,
-		.i_IorangeBase0		= 4,
-		.i_IorangeBase1		= APCI2200_ADDRESS_RANGE,
-		.i_PCIEeprom		= ADDIDATA_EEPROM,
-		.pc_EepromChip		= ADDIDATA_93C76,
-		.i_NbrDiChannel		= 8,
-		.i_NbrDoChannel		= 16,
-		.i_Timer		= 1,
-		.reset			= i_APCI2200_Reset,
-		.di_read		= i_APCI2200_Read1DigitalInput,
-		.di_bits		= i_APCI2200_ReadMoreDigitalInput,
-		.do_config		= i_APCI2200_ConfigDigitalOutput,
-		.do_write		= i_APCI2200_WriteDigitalOutput,
-		.do_bits		= i_APCI2200_ReadDigitalOutput,
-		.timer_config		= i_APCI2200_ConfigWatchdog,
-		.timer_write		= i_APCI2200_StartStopWriteWatchdog,
-		.timer_read		= i_APCI2200_ReadWatchdog,
-	},
-#endif
-#ifdef CONFIG_APCI_1564
-	{
-		.pc_DriverName		= "apci1564",
-		.i_VendorId		= APCI1564_BOARD_VENDOR_ID,
-		.i_DeviceId		= 0x1006,
-		.i_IorangeBase0		= 128,
-		.i_IorangeBase1		= APCI1564_ADDRESS_RANGE,
-		.i_PCIEeprom		= ADDIDATA_EEPROM,
-		.pc_EepromChip		= ADDIDATA_93C76,
-		.i_NbrDiChannel		= 32,
-		.i_NbrDoChannel		= 32,
-		.i_DoMaxdata		= 0xffffffff,
-		.i_Timer		= 1,
-		.interrupt		= v_APCI1564_Interrupt,
-		.reset			= i_APCI1564_Reset,
-		.di_config		= i_APCI1564_ConfigDigitalInput,
-		.di_read		= i_APCI1564_Read1DigitalInput,
-		.di_bits		= i_APCI1564_ReadMoreDigitalInput,
-		.do_config		= i_APCI1564_ConfigDigitalOutput,
-		.do_write		= i_APCI1564_WriteDigitalOutput,
-		.do_bits		= i_APCI1564_ReadDigitalOutput,
-		.do_read		= i_APCI1564_ReadInterruptStatus,
-		.timer_config		= i_APCI1564_ConfigTimerCounterWatchdog,
-		.timer_write		= i_APCI1564_StartStopWriteTimerCounterWatchdog,
-		.timer_read		= i_APCI1564_ReadTimerCounterWatchdog,
-	},
-#endif
-#ifdef CONFIG_APCI_1500
-	{
-		.pc_DriverName		= "apci1500",
-		.i_VendorId		= APCI1500_BOARD_VENDOR_ID,
-		.i_DeviceId		= 0x80fc,
-		.i_IorangeBase0		= 128,
-		.i_IorangeBase1		= APCI1500_ADDRESS_RANGE,
-		.i_IorangeBase2		= 4,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.i_NbrDiChannel		= 16,
-		.i_NbrDoChannel		= 16,
-		.i_DoMaxdata		= 0xffff,
-		.i_Timer		= 1,
-		.interrupt		= v_APCI1500_Interrupt,
-		.reset			= i_APCI1500_Reset,
-		.di_config		= i_APCI1500_ConfigDigitalInputEvent,
-		.di_read		= i_APCI1500_Initialisation,
-		.di_write		= i_APCI1500_StartStopInputEvent,
-		.di_bits		= i_APCI1500_ReadMoreDigitalInput,
-		.do_config		= i_APCI1500_ConfigDigitalOutputErrorInterrupt,
-		.do_write		= i_APCI1500_WriteDigitalOutput,
-		.do_bits		= i_APCI1500_ConfigureInterrupt,
-		.timer_config		= i_APCI1500_ConfigCounterTimerWatchdog,
-		.timer_write		= i_APCI1500_StartStopTriggerTimerCounterWatchdog,
-		.timer_read		= i_APCI1500_ReadInterruptMask,
-		.timer_bits		= i_APCI1500_ReadCounterTimerWatchdog,
-	},
-#endif
-#ifdef CONFIG_APCI_3001
-	{
-		.pc_DriverName		= "apci3001",
-		.i_VendorId		= APCI3120_BOARD_VENDOR_ID,
-		.i_DeviceId		= 0x828D,
-		.i_IorangeBase0		= AMCC_OP_REG_SIZE,
-		.i_IorangeBase1		= APCI3120_ADDRESS_RANGE,
-		.i_IorangeBase2		= 8,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.i_NbrAiChannel		= 16,
-		.i_NbrAiChannelDiff	= 8,
-		.i_AiChannelList	= 16,
-		.i_AiMaxdata		= 0xfff,
-		.pr_AiRangelist		= &range_apci3120_ai,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.i_DoMaxdata		= 0x0f,
-		.i_Dma			= 1,
-		.i_Timer		= 1,
-		.b_AvailableConvertUnit	= 1,
-		.ui_MinAcquisitiontimeNs = 10000,
-		.ui_MinDelaytimeNs	= 100000,
-		.interrupt		= v_APCI3120_Interrupt,
-		.reset			= i_APCI3120_Reset,
-		.ai_config		= i_APCI3120_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3120_InsnReadAnalogInput,
-		.ai_cmdtest		= i_APCI3120_CommandTestAnalogInput,
-		.ai_cmd			= i_APCI3120_CommandAnalogInput,
-		.ai_cancel		= i_APCI3120_StopCyclicAcquisition,
-		.di_read		= i_APCI3120_InsnReadDigitalInput,
-		.di_bits		= i_APCI3120_InsnBitsDigitalInput,
-		.do_config		= i_APCI3120_InsnConfigDigitalOutput,
-		.do_write		= i_APCI3120_InsnWriteDigitalOutput,
-		.do_bits		= i_APCI3120_InsnBitsDigitalOutput,
-		.timer_config		= i_APCI3120_InsnConfigTimer,
-		.timer_write		= i_APCI3120_InsnWriteTimer,
-		.timer_read		= i_APCI3120_InsnReadTimer,
-	},
-#endif
-#ifdef CONFIG_APCI_3501
-	{
-		.pc_DriverName		= "apci3501",
-		.i_VendorId		= APCI3501_BOARD_VENDOR_ID,
-		.i_DeviceId		= 0x3001,
-		.i_IorangeBase0		= 64,
-		.i_IorangeBase1		= APCI3501_ADDRESS_RANGE,
-		.i_PCIEeprom		= ADDIDATA_EEPROM,
-		.pc_EepromChip		= ADDIDATA_S5933,
-		.i_AoMaxdata		= 16383,
-		.pr_AoRangelist		= &range_apci3501_ao,
-		.i_NbrDiChannel		= 2,
-		.i_NbrDoChannel		= 2,
-		.i_DoMaxdata		= 0x3,
-		.i_Timer		= 1,
-		.interrupt		= v_APCI3501_Interrupt,
-		.reset			= i_APCI3501_Reset,
-		.ao_config		= i_APCI3501_ConfigAnalogOutput,
-		.ao_write		= i_APCI3501_WriteAnalogOutput,
-		.di_bits		= i_APCI3501_ReadDigitalInput,
-		.do_config		= i_APCI3501_ConfigDigitalOutput,
-		.do_write		= i_APCI3501_WriteDigitalOutput,
-		.do_bits		= i_APCI3501_ReadDigitalOutput,
-		.timer_config		= i_APCI3501_ConfigTimerCounterWatchdog,
-		.timer_write		= i_APCI3501_StartStopWriteTimerCounterWatchdog,
-		.timer_read		= i_APCI3501_ReadTimerCounterWatchdog,
-	},
-#endif
-#ifdef CONFIG_APCI_035
-	{
-		.pc_DriverName		= "apci035",
-		.i_VendorId		= APCI035_BOARD_VENDOR_ID,
-		.i_DeviceId		= 0x0300,
-		.i_IorangeBase0		= 127,
-		.i_IorangeBase1		= APCI035_ADDRESS_RANGE,
-		.i_PCIEeprom		= 1,
-		.pc_EepromChip		= ADDIDATA_S5920,
-		.i_NbrAiChannel		= 16,
-		.i_NbrAiChannelDiff	= 8,
-		.i_AiChannelList	= 16,
-		.i_AiMaxdata		= 0xff,
-		.pr_AiRangelist		= &range_apci035_ai,
-		.i_Timer		= 1,
-		.ui_MinAcquisitiontimeNs = 10000,
-		.ui_MinDelaytimeNs	= 100000,
-		.interrupt		= v_APCI035_Interrupt,
-		.reset			= i_APCI035_Reset,
-		.ai_config		= i_APCI035_ConfigAnalogInput,
-		.ai_read		= i_APCI035_ReadAnalogInput,
-		.timer_config		= i_APCI035_ConfigTimerWatchdog,
-		.timer_write		= i_APCI035_StartStopWriteTimerWatchdog,
-		.timer_read		= i_APCI035_ReadTimerWatchdog,
-	},
-#endif
-#ifdef CONFIG_APCI_3200
-	{
-		.pc_DriverName		= "apci3200",
-		.i_VendorId		= APCI3200_BOARD_VENDOR_ID,
-		.i_DeviceId		= 0x3000,
-		.i_IorangeBase0		= 128,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 4,
-		.i_IorangeBase3		= 4,
-		.i_PCIEeprom		= ADDIDATA_EEPROM,
-		.pc_EepromChip		= ADDIDATA_S5920,
-		.i_NbrAiChannel		= 16,
-		.i_NbrAiChannelDiff	= 8,
-		.i_AiChannelList	= 16,
-		.i_AiMaxdata		= 0x3ffff,
-		.pr_AiRangelist		= &range_apci3200_ai,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.ui_MinAcquisitiontimeNs = 10000,
-		.ui_MinDelaytimeNs	= 100000,
-		.interrupt		= v_APCI3200_Interrupt,
-		.reset			= i_APCI3200_Reset,
-		.ai_config		= i_APCI3200_ConfigAnalogInput,
-		.ai_read		= i_APCI3200_ReadAnalogInput,
-		.ai_write		= i_APCI3200_InsnWriteReleaseAnalogInput,
-		.ai_bits		= i_APCI3200_InsnBits_AnalogInput_Test,
-		.ai_cmdtest		= i_APCI3200_CommandTestAnalogInput,
-		.ai_cmd			= i_APCI3200_CommandAnalogInput,
-		.ai_cancel		= i_APCI3200_StopCyclicAcquisition,
-		.di_bits		= i_APCI3200_ReadDigitalInput,
-		.do_config		= i_APCI3200_ConfigDigitalOutput,
-		.do_write		= i_APCI3200_WriteDigitalOutput,
-		.do_bits		= i_APCI3200_ReadDigitalOutput,
-	},
-#endif
-#ifdef CONFIG_APCI_3300
-	/* Begin JK	.20.10.2004 = APCI-3300 integration */
-	{
-		.pc_DriverName		= "apci3300",
-		.i_VendorId		= APCI3200_BOARD_VENDOR_ID,
-		.i_DeviceId		= 0x3007,
-		.i_IorangeBase0		= 128,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 4,
-		.i_IorangeBase3		= 4,
-		.i_PCIEeprom		= ADDIDATA_EEPROM,
-		.pc_EepromChip		= ADDIDATA_S5920,
-		.i_NbrAiChannelDiff	= 8,
-		.i_AiChannelList	= 8,
-		.i_AiMaxdata		= 0x3ffff,
-		.pr_AiRangelist		= &range_apci3300_ai,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.ui_MinAcquisitiontimeNs = 10000,
-		.ui_MinDelaytimeNs	= 100000,
-		.interrupt		= v_APCI3200_Interrupt,
-		.reset			= i_APCI3200_Reset,
-		.ai_config		= i_APCI3200_ConfigAnalogInput,
-		.ai_read		= i_APCI3200_ReadAnalogInput,
-		.ai_write		= i_APCI3200_InsnWriteReleaseAnalogInput,
-		.ai_bits		= i_APCI3200_InsnBits_AnalogInput_Test,
-		.ai_cmdtest		= i_APCI3200_CommandTestAnalogInput,
-		.ai_cmd			= i_APCI3200_CommandAnalogInput,
-		.ai_cancel		= i_APCI3200_StopCyclicAcquisition,
-		.di_bits		= i_APCI3200_ReadDigitalInput,
-		.do_config		= i_APCI3200_ConfigDigitalOutput,
-		.do_write		= i_APCI3200_WriteDigitalOutput,
-		.do_bits		= i_APCI3200_ReadDigitalOutput,
-	},
-#endif
-#ifdef CONFIG_APCI_1710
-	{
-		.pc_DriverName		= "apci1710",
-		.i_VendorId		= APCI1710_BOARD_VENDOR_ID,
-		.i_DeviceId		= APCI1710_BOARD_DEVICE_ID,
-		.i_IorangeBase0		= 128,
-		.i_IorangeBase1		= 8,
-		.i_IorangeBase2		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.interrupt		= v_APCI1710_Interrupt,
-		.reset			= i_APCI1710_Reset,
-	},
-#endif
-#ifdef CONFIG_APCI_16XX
-	{
-		.pc_DriverName		= "apci1648",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x1009,
-		.i_IorangeBase0		= 128,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.i_NbrTTLChannel	= 48,
-		.reset			= i_APCI16XX_Reset,
-		.ttl_config		= i_APCI16XX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI16XX_InsnBitsReadTTLIO,
-		.ttl_read		= i_APCI16XX_InsnReadTTLIOAllPortValue,
-		.ttl_write		= i_APCI16XX_InsnBitsWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci1696",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x100A,
-		.i_IorangeBase0		= 128,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.i_NbrTTLChannel	= 96,
-		.reset			= i_APCI16XX_Reset,
-		.ttl_config		= i_APCI16XX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI16XX_InsnBitsReadTTLIO,
-		.ttl_read		= i_APCI16XX_InsnReadTTLIOAllPortValue,
-		.ttl_write		= i_APCI16XX_InsnBitsWriteTTLIO,
-	},
-#endif
-#ifdef CONFIG_APCI_3XXX
-	{
-		.pc_DriverName		= "apci3000-16",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3010,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 16,
-		.i_NbrAiChannelDiff	= 8,
-		.i_AiChannelList	= 16,
-		.i_AiMaxdata		= 4095,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 10000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3000-8",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x300F,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 8,
-		.i_NbrAiChannelDiff	= 4,
-		.i_AiChannelList	= 8,
-		.i_AiMaxdata		= 4095,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 10000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3000-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x300E,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 4,
-		.i_NbrAiChannelDiff	= 2,
-		.i_AiChannelList	= 4,
-		.i_AiMaxdata		= 4095,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 10000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3006-16",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3013,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 16,
-		.i_NbrAiChannelDiff	= 8,
-		.i_AiChannelList	= 16,
-		.i_AiMaxdata		= 65535,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 10000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3006-8",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3014,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 8,
-		.i_NbrAiChannelDiff	= 4,
-		.i_AiChannelList	= 8,
-		.i_AiMaxdata		= 65535,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 10000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3006-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3015,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 4,
-		.i_NbrAiChannelDiff	= 2,
-		.i_AiChannelList	= 4,
-		.i_AiMaxdata		= 65535,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 10000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3010-16",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3016,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 16,
-		.i_NbrAiChannelDiff	= 8,
-		.i_AiChannelList	= 16,
-		.i_AiMaxdata		= 4095,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.i_DoMaxdata		= 1,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 5000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.di_read		= i_APCI3XXX_InsnReadDigitalInput,
-		.di_bits		= i_APCI3XXX_InsnBitsDigitalInput,
-		.do_write		= i_APCI3XXX_InsnWriteDigitalOutput,
-		.do_bits		= i_APCI3XXX_InsnBitsDigitalOutput,
-		.do_read		= i_APCI3XXX_InsnReadDigitalOutput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3010-8",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3017,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 8,
-		.i_NbrAiChannelDiff	= 4,
-		.i_AiChannelList	= 8,
-		.i_AiMaxdata		= 4095,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.i_DoMaxdata		= 1,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 5000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.di_read		= i_APCI3XXX_InsnReadDigitalInput,
-		.di_bits		= i_APCI3XXX_InsnBitsDigitalInput,
-		.do_write		= i_APCI3XXX_InsnWriteDigitalOutput,
-		.do_bits		= i_APCI3XXX_InsnBitsDigitalOutput,
-		.do_read		= i_APCI3XXX_InsnReadDigitalOutput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3010-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3018,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 4,
-		.i_NbrAiChannelDiff	= 2,
-		.i_AiChannelList	= 4,
-		.i_AiMaxdata		= 4095,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.i_DoMaxdata		= 1,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 5000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.di_read		= i_APCI3XXX_InsnReadDigitalInput,
-		.di_bits		= i_APCI3XXX_InsnBitsDigitalInput,
-		.do_write		= i_APCI3XXX_InsnWriteDigitalOutput,
-		.do_bits		= i_APCI3XXX_InsnBitsDigitalOutput,
-		.do_read		= i_APCI3XXX_InsnReadDigitalOutput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3016-16",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3019,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 16,
-		.i_NbrAiChannelDiff	= 8,
-		.i_AiChannelList	= 16,
-		.i_AiMaxdata		= 65535,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.i_DoMaxdata		= 1,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 5000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.di_read		= i_APCI3XXX_InsnReadDigitalInput,
-		.di_bits		= i_APCI3XXX_InsnBitsDigitalInput,
-		.do_write		= i_APCI3XXX_InsnWriteDigitalOutput,
-		.do_bits		= i_APCI3XXX_InsnBitsDigitalOutput,
-		.do_read		= i_APCI3XXX_InsnReadDigitalOutput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3016-8",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x301A,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 8,
-		.i_NbrAiChannelDiff	= 4,
-		.i_AiChannelList	= 8,
-		.i_AiMaxdata		= 65535,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.i_DoMaxdata		= 1,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 5000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.di_read		= i_APCI3XXX_InsnReadDigitalInput,
-		.di_bits		= i_APCI3XXX_InsnBitsDigitalInput,
-		.do_write		= i_APCI3XXX_InsnWriteDigitalOutput,
-		.do_bits		= i_APCI3XXX_InsnBitsDigitalOutput,
-		.do_read		= i_APCI3XXX_InsnReadDigitalOutput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3016-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x301B,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 4,
-		.i_NbrAiChannelDiff	= 2,
-		.i_AiChannelList	= 4,
-		.i_AiMaxdata		= 65535,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.i_DoMaxdata		= 1,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 5000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.di_read		= i_APCI3XXX_InsnReadDigitalInput,
-		.di_bits		= i_APCI3XXX_InsnBitsDigitalInput,
-		.do_write		= i_APCI3XXX_InsnWriteDigitalOutput,
-		.do_bits		= i_APCI3XXX_InsnBitsDigitalOutput,
-		.do_read		= i_APCI3XXX_InsnReadDigitalOutput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3100-16-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x301C,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 16,
-		.i_NbrAiChannelDiff	= 8,
-		.i_AiChannelList	= 16,
-		.i_NbrAoChannel		= 4,
-		.i_AiMaxdata		= 4095,
-		.i_AoMaxdata		= 4095,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.pr_AoRangelist		= &range_apci3XXX_ao,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 10000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3100-8-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x301D,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 8,
-		.i_NbrAiChannelDiff	= 4,
-		.i_AiChannelList	= 8,
-		.i_NbrAoChannel		= 4,
-		.i_AiMaxdata		= 4095,
-		.i_AoMaxdata		= 4095,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.pr_AoRangelist		= &range_apci3XXX_ao,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 10000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3106-16-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x301E,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 16,
-		.i_NbrAiChannelDiff	= 8,
-		.i_AiChannelList	= 16,
-		.i_NbrAoChannel		= 4,
-		.i_AiMaxdata		= 65535,
-		.i_AoMaxdata		= 4095,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.pr_AoRangelist		= &range_apci3XXX_ao,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 10000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3106-8-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x301F,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 8,
-		.i_NbrAiChannelDiff	= 4,
-		.i_AiChannelList	= 8,
-		.i_NbrAoChannel		= 4,
-		.i_AiMaxdata		= 65535,
-		.i_AoMaxdata		= 4095,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.pr_AoRangelist		= &range_apci3XXX_ao,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 10000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3110-16-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3020,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 16,
-		.i_NbrAiChannelDiff	= 8,
-		.i_AiChannelList	= 16,
-		.i_NbrAoChannel		= 4,
-		.i_AiMaxdata		= 4095,
-		.i_AoMaxdata		= 4095,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.pr_AoRangelist		= &range_apci3XXX_ao,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.i_DoMaxdata		= 1,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 5000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
-		.di_read		= i_APCI3XXX_InsnReadDigitalInput,
-		.di_bits		= i_APCI3XXX_InsnBitsDigitalInput,
-		.do_write		= i_APCI3XXX_InsnWriteDigitalOutput,
-		.do_bits		= i_APCI3XXX_InsnBitsDigitalOutput,
-		.do_read		= i_APCI3XXX_InsnReadDigitalOutput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3110-8-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3021,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 8,
-		.i_NbrAiChannelDiff	= 4,
-		.i_AiChannelList	= 8,
-		.i_NbrAoChannel		= 4,
-		.i_AiMaxdata		= 4095,
-		.i_AoMaxdata		= 4095,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.pr_AoRangelist		= &range_apci3XXX_ao,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.i_DoMaxdata		= 1,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 5000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
-		.di_read		= i_APCI3XXX_InsnReadDigitalInput,
-		.di_bits		= i_APCI3XXX_InsnBitsDigitalInput,
-		.do_write		= i_APCI3XXX_InsnWriteDigitalOutput,
-		.do_bits		= i_APCI3XXX_InsnBitsDigitalOutput,
-		.do_read		= i_APCI3XXX_InsnReadDigitalOutput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3116-16-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3022,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 16,
-		.i_NbrAiChannelDiff	= 8,
-		.i_AiChannelList	= 16,
-		.i_NbrAoChannel		= 4,
-		.i_AiMaxdata		= 65535,
-		.i_AoMaxdata		= 4095,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.pr_AoRangelist		= &range_apci3XXX_ao,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.i_DoMaxdata		= 1,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 5000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
-		.di_read		= i_APCI3XXX_InsnReadDigitalInput,
-		.di_bits		= i_APCI3XXX_InsnBitsDigitalInput,
-		.do_write		= i_APCI3XXX_InsnWriteDigitalOutput,
-		.do_bits		= i_APCI3XXX_InsnBitsDigitalOutput,
-		.do_read		= i_APCI3XXX_InsnReadDigitalOutput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3116-8-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3023,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannel		= 8,
-		.i_NbrAiChannelDiff	= 4,
-		.i_AiChannelList	= 8,
-		.i_NbrAoChannel		= 4,
-		.i_AiMaxdata		= 65535,
-		.i_AoMaxdata		= 4095,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.pr_AoRangelist		= &range_apci3XXX_ao,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.i_DoMaxdata		= 1,
-		.i_NbrTTLChannel	= 24,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 5000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
-		.di_read		= i_APCI3XXX_InsnReadDigitalInput,
-		.di_bits		= i_APCI3XXX_InsnBitsDigitalInput,
-		.do_write		= i_APCI3XXX_InsnWriteDigitalOutput,
-		.do_bits		= i_APCI3XXX_InsnBitsDigitalOutput,
-		.do_read		= i_APCI3XXX_InsnReadDigitalOutput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	}, {
-		.pc_DriverName		= "apci3003",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x300B,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannelDiff	= 4,
-		.i_AiChannelList	= 4,
-		.i_AiMaxdata		= 65535,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.i_DoMaxdata		= 1,
-		.b_AvailableConvertUnit	= 7,
-		.ui_MinAcquisitiontimeNs = 2500,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.di_read		= i_APCI3XXX_InsnReadDigitalInput,
-		.di_bits		= i_APCI3XXX_InsnBitsDigitalInput,
-		.do_write		= i_APCI3XXX_InsnWriteDigitalOutput,
-		.do_bits		= i_APCI3XXX_InsnBitsDigitalOutput,
-		.do_read		= i_APCI3XXX_InsnReadDigitalOutput,
-	}, {
-		.pc_DriverName		= "apci3002-16",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3002,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannelDiff	= 16,
-		.i_AiChannelList	= 16,
-		.i_AiMaxdata		= 65535,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.i_DoMaxdata		= 1,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 5000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.di_read		= i_APCI3XXX_InsnReadDigitalInput,
-		.di_bits		= i_APCI3XXX_InsnBitsDigitalInput,
-		.do_write		= i_APCI3XXX_InsnWriteDigitalOutput,
-		.do_bits		= i_APCI3XXX_InsnBitsDigitalOutput,
-		.do_read		= i_APCI3XXX_InsnReadDigitalOutput,
-	}, {
-		.pc_DriverName		= "apci3002-8",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3003,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannelDiff	= 8,
-		.i_AiChannelList	= 8,
-		.i_AiMaxdata		= 65535,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.i_DoMaxdata		= 1,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 5000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.di_read		= i_APCI3XXX_InsnReadDigitalInput,
-		.di_bits		= i_APCI3XXX_InsnBitsDigitalInput,
-		.do_write		= i_APCI3XXX_InsnWriteDigitalOutput,
-		.do_bits		= i_APCI3XXX_InsnBitsDigitalOutput,
-		.do_read		= i_APCI3XXX_InsnReadDigitalOutput,
-	}, {
-		.pc_DriverName		= "apci3002-4",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3004,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAiChannelDiff	= 4,
-		.i_AiChannelList	= 4,
-		.i_AiMaxdata		= 65535,
-		.pr_AiRangelist		= &range_apci3XXX_ai,
-		.i_NbrDiChannel		= 4,
-		.i_NbrDoChannel		= 4,
-		.i_DoMaxdata		= 1,
-		.b_AvailableConvertUnit	= 6,
-		.ui_MinAcquisitiontimeNs = 5000,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
-		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
-		.di_read		= i_APCI3XXX_InsnReadDigitalInput,
-		.di_bits		= i_APCI3XXX_InsnBitsDigitalInput,
-		.do_write		= i_APCI3XXX_InsnWriteDigitalOutput,
-		.do_bits		= i_APCI3XXX_InsnBitsDigitalOutput,
-		.do_read		= i_APCI3XXX_InsnReadDigitalOutput,
-	}, {
-		.pc_DriverName		= "apci3500",
-		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
-		.i_DeviceId		= 0x3024,
-		.i_IorangeBase0		= 256,
-		.i_IorangeBase1		= 256,
-		.i_IorangeBase2		= 256,
-		.i_IorangeBase3		= 256,
-		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
-		.pc_EepromChip		= ADDIDATA_9054,
-		.i_NbrAoChannel		= 4,
-		.i_AoMaxdata		= 4095,
-		.pr_AoRangelist		= &range_apci3XXX_ao,
-		.i_NbrTTLChannel	= 24,
-		.interrupt		= v_APCI3XXX_Interrupt,
-		.reset			= i_APCI3XXX_Reset,
-		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
-		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
-		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
-		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
-		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
-	},
-#endif
-};
+static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev,
+				     struct comedi_subdevice *s,
+				     struct comedi_insn *insn,
+				     unsigned int *data)
+{
+	const struct addi_board *this_board = comedi_board(dev);
+	struct addi_private *devpriv = dev->private;
+	unsigned short w_Address = CR_CHAN(insn->chanspec);
+	unsigned short w_Data;
 
-static struct comedi_driver driver_addi = {
-	.driver_name = ADDIDATA_DRIVER_NAME,
-	.module = THIS_MODULE,
-	.attach = i_ADDI_Attach,
-	.detach = i_ADDI_Detach,
-	.num_names = ARRAY_SIZE(boardtypes),
-	.board_name = &boardtypes[0].pc_DriverName,
-	.offset = sizeof(struct addi_board),
-};
+	w_Data = addi_eeprom_readw(devpriv->i_IobaseAmcc,
+		this_board->pc_EepromChip, 2 * w_Address);
+	data[0] = w_Data;
 
-static int __devinit driver_addi_pci_probe(struct pci_dev *dev,
-					   const struct pci_device_id *ent)
-{
-	return comedi_pci_auto_config(dev, &driver_addi);
+	return insn->n;
 }
 
-static void __devexit driver_addi_pci_remove(struct pci_dev *dev)
+static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
 {
-	comedi_pci_auto_unconfig(dev);
-}
+	struct comedi_device *dev = d;
+	const struct addi_board *this_board = comedi_board(dev);
 
-static struct pci_driver driver_addi_pci_driver = {
-	.id_table = addi_apci_tbl,
-	.probe = &driver_addi_pci_probe,
-	.remove = __devexit_p(&driver_addi_pci_remove)
-};
+	this_board->interrupt(irq, d);
+	return IRQ_RETVAL(1);
+}
 
-static int __init driver_addi_init_module(void)
+static int i_ADDI_Reset(struct comedi_device *dev)
 {
-	int retval;
-
-	retval = comedi_driver_register(&driver_addi);
-	if (retval < 0)
-		return retval;
+	const struct addi_board *this_board = comedi_board(dev);
 
-	driver_addi_pci_driver.name = (char *)driver_addi.driver_name;
-	return pci_register_driver(&driver_addi_pci_driver);
+	this_board->reset(dev);
+	return 0;
 }
 
-static void __exit driver_addi_cleanup_module(void)
+static const void *addi_find_boardinfo(struct comedi_device *dev,
+				       struct pci_dev *pcidev)
 {
-	pci_unregister_driver(&driver_addi_pci_driver);
-	comedi_driver_unregister(&driver_addi);
+	const void *p = dev->driver->board_name;
+	const struct addi_board *this_board;
+	int i;
+
+	for (i = 0; i < dev->driver->num_names; i++) {
+		this_board = p;
+		if (this_board->i_VendorId == pcidev->vendor &&
+		    this_board->i_DeviceId == pcidev->device)
+			return this_board;
+		p += dev->driver->offset;
+	}
+	return NULL;
 }
 
-module_init(driver_addi_init_module);
-module_exit(driver_addi_cleanup_module);
-
-/*
-+----------------------------------------------------------------------------+
-| Function name     :static int i_ADDI_Attach(struct comedi_device *dev,            |
-|										struct comedi_devconfig *it)        |
-|                                        									 |
-+----------------------------------------------------------------------------+
-| Task              :Detects the card.                                       |
-|  			 Configure the driver for a particular board.            |
-|  			 This function does all the initializations and memory   |
-|			 allocation of data structures for the driver.	         |
-+----------------------------------------------------------------------------+
-| Input Parameters  :struct comedi_device *dev										 |
-|                    struct comedi_devconfig *it									 |
-|                                                 					         |
-+----------------------------------------------------------------------------+
-| Return Value      :  0            					                     |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int addi_auto_attach(struct comedi_device *dev,
+				      unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	const struct addi_board *this_board;
+	struct addi_private *devpriv;
 	struct comedi_subdevice *s;
-	int ret, pages, i, n_subdevices;
+	int ret, n_subdevices;
 	unsigned int dw_Dummy;
-	resource_size_t io_addr[5];
-	unsigned int irq;
-	resource_size_t iobase_a, iobase_main, iobase_addon, iobase_reserved;
-	struct pcilst_struct *card = NULL;
-	unsigned char pci_bus, pci_slot, pci_func;
-	int i_Dma = 0;
-
-	ret = alloc_private(dev, sizeof(struct addi_private));
-	if (ret < 0)
-		return -ENOMEM;
-
-	if (!pci_list_builded) {
-		v_pci_card_list_init(this_board->i_VendorId, 1);	/* 1 for displaying the list.. */
-		pci_list_builded = 1;
-	}
-	/* printk("comedi%d: "ADDIDATA_DRIVER_NAME": board=%s",dev->minor,this_board->pc_DriverName); */
-
-	if ((this_board->i_Dma) && (it->options[2] == 0)) {
-		i_Dma = 1;
-	}
-
-	card = ptr_select_and_alloc_pci_card(this_board->i_VendorId,
-					     this_board->i_DeviceId,
-					     it->options[0],
-					     it->options[1], i_Dma);
-
-	if (card == NULL)
-		return -EIO;
-
-	devpriv->allocated = 1;
-
-	if ((i_pci_card_data(card, &pci_bus, &pci_slot, &pci_func, &io_addr[0],
-				&irq)) < 0) {
-		i_pci_card_free(card);
-		printk(" - Can't get AMCC data!\n");
-		return -EIO;
-	}
-
-	iobase_a = io_addr[0];
-	iobase_main = io_addr[1];
-	iobase_addon = io_addr[2];
-	iobase_reserved = io_addr[3];
-	printk("\nBus %d: Slot %d: Funct%d\nBase0: 0x%8llx\nBase1: 0x%8llx\nBase2: 0x%8llx\nBase3: 0x%8llx\n", pci_bus, pci_slot, pci_func, (unsigned long long)io_addr[0], (unsigned long long)io_addr[1], (unsigned long long)io_addr[2], (unsigned long long)io_addr[3]);
 
-	if ((this_board->pc_EepromChip == NULL)
-		|| (strcmp(this_board->pc_EepromChip, ADDIDATA_9054) != 0)) {
-	   /************************************/
-		/* Test if more that 1 address used */
-	   /************************************/
+	this_board = addi_find_boardinfo(dev, pcidev);
+	if (!this_board)
+		return -ENODEV;
+	dev->board_ptr = this_board;
+	dev->board_name = this_board->pc_DriverName;
 
-		if (this_board->i_IorangeBase1 != 0) {
-			dev->iobase = (unsigned long)iobase_main;	/*  DAQ base address... */
-		} else {
-			dev->iobase = (unsigned long)iobase_a;	/*  DAQ base address... */
-		}
-
-		dev->board_name = this_board->pc_DriverName;
-		devpriv->amcc = card;
-		devpriv->iobase = (int) dev->iobase;
-		devpriv->i_IobaseAmcc = (int) iobase_a;	/* AMCC base address... */
-		devpriv->i_IobaseAddon = (int) iobase_addon;	/* ADD ON base address.... */
-		devpriv->i_IobaseReserved = (int) iobase_reserved;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
+	ret = comedi_pci_enable(pcidev, dev->board_name);
+	if (ret)
+		return ret;
+
+	if (!this_board->pc_EepromChip ||
+	    strcmp(this_board->pc_EepromChip, ADDIDATA_9054)) {
+		/* board does not have an eeprom or is not ADDIDATA_9054 */
+		if (this_board->i_IorangeBase1)
+			dev->iobase = pci_resource_start(pcidev, 1);
+		else
+			dev->iobase = pci_resource_start(pcidev, 0);
+
+		devpriv->iobase = dev->iobase;
+		devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
+		devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2);
 	} else {
-		dev->board_name = this_board->pc_DriverName;
-		dev->iobase = (unsigned long)io_addr[2];
-		devpriv->amcc = card;
-		devpriv->iobase = (int) io_addr[2];
-		devpriv->i_IobaseReserved = (int) io_addr[3];
-		printk("\nioremap begin");
-		devpriv->dw_AiBase = ioremap(io_addr[3],
+		/* board has an ADDIDATA_9054 eeprom */
+		dev->iobase = pci_resource_start(pcidev, 2);
+		devpriv->iobase = pci_resource_start(pcidev, 2);
+		devpriv->dw_AiBase = ioremap(pci_resource_start(pcidev, 3),
 					     this_board->i_IorangeBase3);
-		printk("\nioremap end");
 	}
+	devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3);
 
 	/* Initialize parameters that can be overridden in EEPROM */
 	devpriv->s_EeParameters.i_NbrAiChannel = this_board->i_NbrAiChannel;
@@ -1566,30 +155,19 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 	/* ## */
 
-	if (irq > 0) {
-		if (request_irq(irq, v_ADDI_Interrupt, IRQF_SHARED,
-				this_board->pc_DriverName, dev) < 0) {
-			printk(", unable to allocate IRQ %u, DISABLING IT",
-				irq);
-			irq = 0;	/* Can't use IRQ */
-		} else {
-			printk("\nirq=%u", irq);
-		}
-	} else {
-		printk(", IRQ disabled");
+	if (pcidev->irq > 0) {
+		ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED,
+				  dev->board_name, dev);
+		if (ret == 0)
+			dev->irq = pcidev->irq;
 	}
 
-	printk("\nOption %d %d %d\n", it->options[0], it->options[1],
-		it->options[2]);
-	dev->irq = irq;
-
 	/*  Read eepeom and fill addi_board Structure */
 
 	if (this_board->i_PCIEeprom) {
-		printk("\nPCI Eeprom used");
 		if (!(strcmp(this_board->pc_EepromChip, "S5920"))) {
 			/*  Set 3 wait stait */
-			if (!(strcmp(this_board->pc_DriverName, "apci035"))) {
+			if (!(strcmp(dev->board_name, "apci035"))) {
 				outl(0x80808082, devpriv->i_IobaseAmcc + 0x60);
 			} else {
 				outl(0x83838383, devpriv->i_IobaseAmcc + 0x60);
@@ -1597,340 +175,174 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
 			/*  Enable the interrupt for the controller */
 			dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38);
 			outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38);
-			printk("\nEnable the interrupt for the controller");
 		}
-		printk("\nRead Eeprom");
-		i_EepromReadMainHeader(io_addr[0], this_board->pc_EepromChip,
-			dev);
-	} else {
-		printk("\nPCI Eeprom unused");
-	}
-
-	if (it->options[2] > 0) {
-		devpriv->us_UseDma = ADDI_DISABLE;
-	} else {
-		devpriv->us_UseDma = ADDI_ENABLE;
+		addi_eeprom_read_info(dev, pci_resource_start(pcidev, 0));
 	}
 
-	if (devpriv->s_EeParameters.i_Dma) {
-		printk("\nDMA used");
-		if (devpriv->us_UseDma == ADDI_ENABLE) {
-			/*  alloc DMA buffers */
-			devpriv->b_DmaDoubleBuffer = 0;
-			for (i = 0; i < 2; i++) {
-				for (pages = 4; pages >= 0; pages--) {
-					devpriv->ul_DmaBufferVirtual[i] =
-						(void *) __get_free_pages(GFP_KERNEL, pages);
-
-					if (devpriv->ul_DmaBufferVirtual[i])
-						break;
-				}
-				if (devpriv->ul_DmaBufferVirtual[i]) {
-					devpriv->ui_DmaBufferPages[i] = pages;
-					devpriv->ui_DmaBufferSize[i] =
-						PAGE_SIZE * pages;
-					devpriv->ui_DmaBufferSamples[i] =
-						devpriv->
-						ui_DmaBufferSize[i] >> 1;
-					devpriv->ul_DmaBufferHw[i] =
-						virt_to_bus((void *)devpriv->
-						ul_DmaBufferVirtual[i]);
-				}
-			}
-			if (!devpriv->ul_DmaBufferVirtual[0]) {
-				printk
-					(", Can't allocate DMA buffer, DMA disabled!");
-				devpriv->us_UseDma = ADDI_DISABLE;
-			}
-
-			if (devpriv->ul_DmaBufferVirtual[1]) {
-				devpriv->b_DmaDoubleBuffer = 1;
-			}
-		}
-
-		if ((devpriv->us_UseDma == ADDI_ENABLE)) {
-			printk("\nDMA ENABLED\n");
+	n_subdevices = 7;
+	ret = comedi_alloc_subdevices(dev, n_subdevices);
+	if (ret)
+		return ret;
+
+	/*  Allocate and Initialise AI Subdevice Structures */
+	s = &dev->subdevices[0];
+	if ((devpriv->s_EeParameters.i_NbrAiChannel)
+		|| (this_board->i_NbrAiChannelDiff)) {
+		dev->read_subdev = s;
+		s->type = COMEDI_SUBD_AI;
+		s->subdev_flags =
+			SDF_READABLE | SDF_COMMON | SDF_GROUND
+			| SDF_DIFF;
+		if (devpriv->s_EeParameters.i_NbrAiChannel) {
+			s->n_chan =
+				devpriv->s_EeParameters.i_NbrAiChannel;
+			devpriv->b_SingelDiff = 0;
 		} else {
-			printk("\nDMA DISABLED\n");
+			s->n_chan = this_board->i_NbrAiChannelDiff;
+			devpriv->b_SingelDiff = 1;
 		}
-	}
-
-	if (!strcmp(this_board->pc_DriverName, "apci1710")) {
-#ifdef CONFIG_APCI_1710
-		i_ADDI_AttachPCI1710(dev);
-
-		/*  save base address */
-		devpriv->s_BoardInfos.ui_Address = io_addr[2];
-#endif
-	} else {
-		n_subdevices = 7;
-		ret = comedi_alloc_subdevices(dev, n_subdevices);
-		if (ret)
-			return ret;
+		s->maxdata = devpriv->s_EeParameters.i_AiMaxdata;
+		s->len_chanlist = this_board->i_AiChannelList;
+		s->range_table = this_board->pr_AiRangelist;
 
-		/*  Allocate and Initialise AI Subdevice Structures */
-		s = &dev->subdevices[0];
-		if ((devpriv->s_EeParameters.i_NbrAiChannel)
-			|| (this_board->i_NbrAiChannelDiff)) {
-			dev->read_subdev = s;
-			s->type = COMEDI_SUBD_AI;
-			s->subdev_flags =
-				SDF_READABLE | SDF_COMMON | SDF_GROUND
-				| SDF_DIFF;
-			if (devpriv->s_EeParameters.i_NbrAiChannel) {
-				s->n_chan =
-					devpriv->s_EeParameters.i_NbrAiChannel;
-				devpriv->b_SingelDiff = 0;
-			} else {
-				s->n_chan = this_board->i_NbrAiChannelDiff;
-				devpriv->b_SingelDiff = 1;
-			}
-			s->maxdata = devpriv->s_EeParameters.i_AiMaxdata;
-			s->len_chanlist = this_board->i_AiChannelList;
-			s->range_table = this_board->pr_AiRangelist;
-
-			/* Set the initialisation flag */
-			devpriv->b_AiInitialisation = 1;
-
-			s->insn_config = this_board->ai_config;
-			s->insn_read = this_board->ai_read;
-			s->insn_write = this_board->ai_write;
-			s->insn_bits = this_board->ai_bits;
-			s->do_cmdtest = this_board->ai_cmdtest;
-			s->do_cmd = this_board->ai_cmd;
-			s->cancel = this_board->ai_cancel;
-
-		} else {
-			s->type = COMEDI_SUBD_UNUSED;
-		}
+		/* Set the initialisation flag */
+		devpriv->b_AiInitialisation = 1;
 
-		/*  Allocate and Initialise AO Subdevice Structures */
-		s = &dev->subdevices[1];
-		if (devpriv->s_EeParameters.i_NbrAoChannel) {
-			s->type = COMEDI_SUBD_AO;
-			s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
-			s->n_chan = devpriv->s_EeParameters.i_NbrAoChannel;
-			s->maxdata = devpriv->s_EeParameters.i_AoMaxdata;
-			s->len_chanlist =
-				devpriv->s_EeParameters.i_NbrAoChannel;
-			s->range_table = this_board->pr_AoRangelist;
-			s->insn_config = this_board->ao_config;
-			s->insn_write = this_board->ao_write;
-		} else {
-			s->type = COMEDI_SUBD_UNUSED;
-		}
-		/*  Allocate and Initialise DI Subdevice Structures */
-		s = &dev->subdevices[2];
-		if (devpriv->s_EeParameters.i_NbrDiChannel) {
-			s->type = COMEDI_SUBD_DI;
-			s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
-			s->n_chan = devpriv->s_EeParameters.i_NbrDiChannel;
-			s->maxdata = 1;
-			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;
-			s->insn_bits = this_board->di_bits;
-		} else {
-			s->type = COMEDI_SUBD_UNUSED;
-		}
-		/*  Allocate and Initialise DO Subdevice Structures */
-		s = &dev->subdevices[3];
-		if (devpriv->s_EeParameters.i_NbrDoChannel) {
-			s->type = COMEDI_SUBD_DO;
-			s->subdev_flags =
-				SDF_READABLE | SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
-			s->n_chan = devpriv->s_EeParameters.i_NbrDoChannel;
-			s->maxdata = devpriv->s_EeParameters.i_DoMaxdata;
-			s->len_chanlist =
-				devpriv->s_EeParameters.i_NbrDoChannel;
-			s->range_table = &range_digital;
-			s->io_bits = 0xf;	/* all bits output */
+		s->insn_config = this_board->ai_config;
+		s->insn_read = this_board->ai_read;
+		s->insn_write = this_board->ai_write;
+		s->insn_bits = this_board->ai_bits;
+		s->do_cmdtest = this_board->ai_cmdtest;
+		s->do_cmd = this_board->ai_cmd;
+		s->cancel = this_board->ai_cancel;
 
-			/* insn_config - for digital output memory */
-			s->insn_config = this_board->do_config;
-			s->insn_write = this_board->do_write;
-			s->insn_bits = this_board->do_bits;
-			s->insn_read = this_board->do_read;
-		} else {
-			s->type = COMEDI_SUBD_UNUSED;
-		}
+	} else {
+		s->type = COMEDI_SUBD_UNUSED;
+	}
 
-		/*  Allocate and Initialise Timer Subdevice Structures */
-		s = &dev->subdevices[4];
-		if (devpriv->s_EeParameters.i_Timer) {
-			s->type = COMEDI_SUBD_TIMER;
-			s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
-			s->n_chan = 1;
-			s->maxdata = 0;
-			s->len_chanlist = 1;
-			s->range_table = &range_digital;
+	/*  Allocate and Initialise AO Subdevice Structures */
+	s = &dev->subdevices[1];
+	if (devpriv->s_EeParameters.i_NbrAoChannel) {
+		s->type = COMEDI_SUBD_AO;
+		s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
+		s->n_chan = devpriv->s_EeParameters.i_NbrAoChannel;
+		s->maxdata = devpriv->s_EeParameters.i_AoMaxdata;
+		s->len_chanlist =
+			devpriv->s_EeParameters.i_NbrAoChannel;
+		s->range_table = this_board->pr_AoRangelist;
+		s->insn_config = this_board->ao_config;
+		s->insn_write = this_board->ao_write;
+	} else {
+		s->type = COMEDI_SUBD_UNUSED;
+	}
+	/*  Allocate and Initialise DI Subdevice Structures */
+	s = &dev->subdevices[2];
+	if (devpriv->s_EeParameters.i_NbrDiChannel) {
+		s->type = COMEDI_SUBD_DI;
+		s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
+		s->n_chan = devpriv->s_EeParameters.i_NbrDiChannel;
+		s->maxdata = 1;
+		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;
+		s->insn_bits = this_board->di_bits;
+	} else {
+		s->type = COMEDI_SUBD_UNUSED;
+	}
+	/*  Allocate and Initialise DO Subdevice Structures */
+	s = &dev->subdevices[3];
+	if (devpriv->s_EeParameters.i_NbrDoChannel) {
+		s->type = COMEDI_SUBD_DO;
+		s->subdev_flags =
+			SDF_READABLE | SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
+		s->n_chan = devpriv->s_EeParameters.i_NbrDoChannel;
+		s->maxdata = devpriv->s_EeParameters.i_DoMaxdata;
+		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;
+		s->insn_write = this_board->do_write;
+		s->insn_bits = this_board->do_bits;
+		s->insn_read = this_board->do_read;
+	} else {
+		s->type = COMEDI_SUBD_UNUSED;
+	}
 
-			s->insn_write = this_board->timer_write;
-			s->insn_read = this_board->timer_read;
-			s->insn_config = this_board->timer_config;
-			s->insn_bits = this_board->timer_bits;
-		} else {
-			s->type = COMEDI_SUBD_UNUSED;
-		}
+	/*  Allocate and Initialise Timer Subdevice Structures */
+	s = &dev->subdevices[4];
+	if (devpriv->s_EeParameters.i_Timer) {
+		s->type = COMEDI_SUBD_TIMER;
+		s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
+		s->n_chan = 1;
+		s->maxdata = 0;
+		s->len_chanlist = 1;
+		s->range_table = &range_digital;
+
+		s->insn_write = this_board->timer_write;
+		s->insn_read = this_board->timer_read;
+		s->insn_config = this_board->timer_config;
+		s->insn_bits = this_board->timer_bits;
+	} else {
+		s->type = COMEDI_SUBD_UNUSED;
+	}
 
-		/*  Allocate and Initialise TTL */
-		s = &dev->subdevices[5];
-		if (this_board->i_NbrTTLChannel) {
-			s->type = COMEDI_SUBD_TTLIO;
-			s->subdev_flags =
-				SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
-			s->n_chan = this_board->i_NbrTTLChannel;
-			s->maxdata = 1;
-			s->io_bits = 0;	/* all bits input */
-			s->len_chanlist = this_board->i_NbrTTLChannel;
-			s->range_table = &range_digital;
-			s->insn_config = this_board->ttl_config;
-			s->insn_bits = this_board->ttl_bits;
-			s->insn_read = this_board->ttl_read;
-			s->insn_write = this_board->ttl_write;
-		} else {
-			s->type = COMEDI_SUBD_UNUSED;
-		}
+	/*  Allocate and Initialise TTL */
+	s = &dev->subdevices[5];
+	if (this_board->i_NbrTTLChannel) {
+		s->type = COMEDI_SUBD_TTLIO;
+		s->subdev_flags =
+			SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
+		s->n_chan = this_board->i_NbrTTLChannel;
+		s->maxdata = 1;
+		s->io_bits = 0;	/* all bits input */
+		s->len_chanlist = this_board->i_NbrTTLChannel;
+		s->range_table = &range_digital;
+		s->insn_config = this_board->ttl_config;
+		s->insn_bits = this_board->ttl_bits;
+		s->insn_read = this_board->ttl_read;
+		s->insn_write = this_board->ttl_write;
+	} else {
+		s->type = COMEDI_SUBD_UNUSED;
+	}
 
-		/* EEPROM */
-		s = &dev->subdevices[6];
-		if (this_board->i_PCIEeprom) {
-			s->type = COMEDI_SUBD_MEMORY;
-			s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
-			s->n_chan = 256;
-			s->maxdata = 0xffff;
-			s->insn_read = i_ADDIDATA_InsnReadEeprom;
-		} else {
-			s->type = COMEDI_SUBD_UNUSED;
-		}
+	/* EEPROM */
+	s = &dev->subdevices[6];
+	if (this_board->i_PCIEeprom) {
+		s->type = COMEDI_SUBD_MEMORY;
+		s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
+		s->n_chan = 256;
+		s->maxdata = 0xffff;
+		s->insn_read = i_ADDIDATA_InsnReadEeprom;
+	} else {
+		s->type = COMEDI_SUBD_UNUSED;
 	}
 
-	printk("\ni_ADDI_Attach end\n");
 	i_ADDI_Reset(dev);
-	devpriv->b_ValidDriver = 1;
 	return 0;
 }
 
 static void i_ADDI_Detach(struct comedi_device *dev)
 {
-	if (dev->private) {
-		if (devpriv->b_ValidDriver)
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct addi_private *devpriv = dev->private;
+
+	if (devpriv) {
+		if (dev->iobase)
 			i_ADDI_Reset(dev);
 		if (dev->irq)
 			free_irq(dev->irq, dev);
-		if ((this_board->pc_EepromChip == NULL) ||
-		    (strcmp(this_board->pc_EepromChip, ADDIDATA_9054) != 0)) {
-			if (devpriv->allocated)
-				i_pci_card_free(devpriv->amcc);
-			if (devpriv->ul_DmaBufferVirtual[0]) {
-				free_pages((unsigned long)devpriv->
-					ul_DmaBufferVirtual[0],
-					devpriv->ui_DmaBufferPages[0]);
-			}
-			if (devpriv->ul_DmaBufferVirtual[1]) {
-				free_pages((unsigned long)devpriv->
-					ul_DmaBufferVirtual[1],
-					devpriv->ui_DmaBufferPages[1]);
-			}
-		} else {
+		if (devpriv->dw_AiBase)
 			iounmap(devpriv->dw_AiBase);
-			if (devpriv->allocated)
-				i_pci_card_free(devpriv->amcc);
-		}
-		if (pci_list_builded) {
-			v_pci_card_list_cleanup(this_board->i_VendorId);
-			pci_list_builded = 0;
-		}
 	}
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function name     : static int i_ADDI_Reset(struct comedi_device *dev)			 |
-|                                        									 |
-+----------------------------------------------------------------------------+
-| Task              : Disables all interrupts, Resets digital output to low, |
-|				Set all analog output to low						 |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev									 |
-|                     														 |
-|                                                 					         |
-+----------------------------------------------------------------------------+
-| Return Value      : 0           					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_ADDI_Reset(struct comedi_device *dev)
-{
-
-	this_board->reset(dev);
-	return 0;
-}
-
-/* Interrupt function */
-/*
-+----------------------------------------------------------------------------+
-| Function name     :                                                        |
-|static void v_ADDI_Interrupt(int irq, void *d)                 |
-|                                        									 |
-+----------------------------------------------------------------------------+
-| Task              : Registerd interrupt routine						     |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : 	int irq												 |
-|                     														 |
-|                                                 					         |
-+----------------------------------------------------------------------------+
-| Return Value      :              					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
-{
-	struct comedi_device *dev = d;
-	this_board->interrupt(irq, d);
-	return IRQ_RETVAL(1);
-}
-
-/* EEPROM Read Function */
-/*
-+----------------------------------------------------------------------------+
-| Function name     :                                                        |
-|INT i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev,struct comedi_subdevice *s,
-							struct comedi_insn *insn,unsigned int *data)
-|                                        									 |
-+----------------------------------------------------------------------------+
-| Task              : Read 256 words from EEPROM          				     |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  :(struct comedi_device *dev,struct comedi_subdevice *s,
-			struct comedi_insn *insn,unsigned int *data) 						 |
-|                     														 |
-|                                                 					         |
-+----------------------------------------------------------------------------+
-| Return Value      :              					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned short w_Data;
-	unsigned short w_Address;
-	w_Address = CR_CHAN(insn->chanspec);	/*  address to be read as 0,1,2,3...255 */
-
-	w_Data = w_EepromReadWord(devpriv->i_IobaseAmcc,
-		this_board->pc_EepromChip, 0x100 + (2 * w_Address));
-	data[0] = w_Data;
-	/* multiplied by 2 bcozinput will be like 0,1,2...255 */
-	return insn->n;
-
+	if (pcidev) {
+		if (dev->iobase)
+			comedi_pci_disable(pcidev);
+	}
 }
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
index b7bbb71..6d8b29f94 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
@@ -15,26 +15,8 @@
  * any later version.
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/timer.h>
-#include <linux/pci.h>
-#include <linux/io.h>
-#include <linux/kmod.h>
-#include <linux/uaccess.h>
-#include "../../comedidev.h"
-#include "addi_amcc_s5933.h"
-
-#define ERROR	-1
-#define SUCCESS	1
 
 #define LOBYTE(W)	(unsigned char)((W) & 0xFF)
 #define HIBYTE(W)	(unsigned char)(((W) >> 8) & 0xFF)
@@ -312,9 +294,6 @@ struct addi_private {
 	int i_IobaseAddon;	/* addon base address */
 	int i_IobaseReserved;
 	void __iomem *dw_AiBase;
-	struct pcilst_struct *amcc;	/*  ptr too AMCC data */
-	unsigned char allocated;		/*  we have blocked card */
-	unsigned char b_ValidDriver;	/*  driver is ok */
 	unsigned char b_AiContinuous;	/*  we do unlimited AI */
 	unsigned char b_AiInitialisation;
 	unsigned int ui_AiActualScan;	/* how many scans we finished */
@@ -410,14 +389,3 @@ struct addi_private {
 					/*  Minimum Delay in Nano secs */
 	} s_EeParameters;
 };
-
-static unsigned short pci_list_builded;	/* set to 1 when list of card is known */
-
-/* Function declarations */
-static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static void i_ADDI_Detach(struct comedi_device *dev);
-static int i_ADDI_Reset(struct comedi_device *dev);
-
-static irqreturn_t v_ADDI_Interrupt(int irq, void *d);
-static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev, struct comedi_subdevice *s,
-				     struct comedi_insn *insn, unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
index 3a9339b..5124ac9 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
@@ -1,1162 +1,365 @@
-/**
-@verbatim
-
-Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
-
-	ADDI-DATA GmbH
-	Dieselstrasse 3
-	D-77833 Ottersweier
-	Tel: +19(0)7223/9493-0
-	Fax: +49(0)7223/9493-92
-	http://www.addi-data.com
-	info@addi-data.com
-
-This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
-@endverbatim
-*/
 /*
-
-  +-----------------------------------------------------------------------+
-  | (C) ADDI-DATA GmbH          Dieselstrasse 3      D-77833 Ottersweier  |
-  +-----------------------------------------------------------------------+
-  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
-  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
-  +-----------------------------------------------------------------------+
-  | Project   : ADDI DATA         | Compiler : GCC 			              |
-  | Modulname : addi_eeprom.c     | Version  : 2.96                       |
-  +-------------------------------+---------------------------------------+
-  | Project manager: Eric Stolz   | Date     :  02/12/2002                |
-  +-----------------------------------------------------------------------+
-  | Description : ADDI EEPROM  Module                                     |
-  +-----------------------------------------------------------------------+
-  |                             UPDATE'S                                  |
-  +-----------------------------------------------------------------------+
-  |   Date   |   Author  |          Description of updates                |
-  +----------+-----------+------------------------------------------------+
-  |          | 		 | 						  |
-  |          |           | 						  |
-  +----------+-----------+------------------------------------------------+
-*/
-
-#define NVCMD_BEGIN_READ 	(0x7 << 5)	/*  nvRam begin read command */
-#define NVCMD_LOAD_LOW   	(0x4 << 5)	/*  nvRam load low command */
-#define NVCMD_LOAD_HIGH  	(0x5 << 5)	/*  nvRam load high command */
-#define EE76_CMD_LEN    	13	/*  bits in instructions */
-#define EE_READ         	0x0180	/*  01 1000 0000 read instruction */
-
-#define EEPROM_DIGITALINPUT 			0
-#define EEPROM_DIGITALOUTPUT			1
-#define EEPROM_ANALOGINPUT				2
-#define EEPROM_ANALOGOUTPUT				3
-#define EEPROM_TIMER					4
-#define EEPROM_WATCHDOG					5
+ * addi_eeprom.c - ADDI EEPROM Module
+ * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ * Project manager: Eric Stolz
+ *
+ *	ADDI-DATA GmbH
+ *	Dieselstrasse 3
+ *	D-77833 Ottersweier
+ *	Tel: +19(0)7223/9493-0
+ *	Fax: +49(0)7223/9493-92
+ *	http://www.addi-data.com
+ *	info@addi-data.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * You should also find the complete GPL in the COPYING file accompanying
+ * this source code.
+ */
+
+#define NVRAM_USER_DATA_START	0x100
+
+#define NVCMD_BEGIN_READ	(0x7 << 5)	/* nvRam begin read command */
+#define NVCMD_LOAD_LOW		(0x4 << 5)	/* nvRam load low command */
+#define NVCMD_LOAD_HIGH		(0x5 << 5)	/* nvRam load high command */
+
+#define EE93C76_CLK_BIT		(1 << 0)
+#define EE93C76_CS_BIT		(1 << 1)
+#define EE93C76_DOUT_BIT	(1 << 2)
+#define EE93C76_DIN_BIT		(1 << 3)
+#define EE93C76_READ_CMD	(0x0180 << 4)
+#define EE93C76_CMD_LEN		13
+
+#define EEPROM_DIGITALINPUT		0
+#define EEPROM_DIGITALOUTPUT		1
+#define EEPROM_ANALOGINPUT		2
+#define EEPROM_ANALOGOUTPUT		3
+#define EEPROM_TIMER			4
+#define EEPROM_WATCHDOG			5
 #define EEPROM_TIMER_WATCHDOG_COUNTER	10
 
-struct str_Functionality {
-	unsigned char b_Type;
-	unsigned short w_Address;
-};
-
-struct str_MainHeader {
-	unsigned short w_HeaderSize;
-	unsigned char b_Nfunctions;
-	struct str_Functionality s_Functions[7];
-};
-
-struct str_DigitalInputHeader {
-	unsigned short w_Nchannel;
-	unsigned char b_Interruptible;
-	unsigned short w_NinterruptLogic;
-};
-
-struct str_DigitalOutputHeader {
-
-	unsigned short w_Nchannel;
-};
-
-
-/* used for timer as well as watchdog */
-
-struct str_TimerDetails {
-
-	unsigned short w_HeaderSize;
-	unsigned char b_Resolution;
-	unsigned char b_Mode;		/*  in case of Watchdog it is functionality */
-	unsigned short w_MinTiming;
-	unsigned char b_TimeBase;
-};
-
-struct str_TimerMainHeader {
-
-
-	unsigned short w_Ntimer;
-	struct str_TimerDetails s_TimerDetails[4];	/*   supports 4 timers */
-};
-
-
-struct str_AnalogOutputHeader {
-	unsigned short w_Nchannel;
-	unsigned char b_Resolution;
-};
-
-struct str_AnalogInputHeader {
-	unsigned short w_Nchannel;
-	unsigned short w_MinConvertTiming;
-	unsigned short w_MinDelayTiming;
-	unsigned char b_HasDma;
-	unsigned char b_Resolution;
-};
-
-
-		/*****************************************/
-		/*            Read Header Functions              */
-		/*****************************************/
-
-int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
-	char *pc_PCIChipInformation, struct comedi_device *dev);
-
-int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
-	char *pc_PCIChipInformation, unsigned short w_Address,
-	struct str_DigitalInputHeader *s_Header);
-
-int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
-	char *pc_PCIChipInformation, unsigned short w_Address,
-	struct str_DigitalOutputHeader *s_Header);
-
-int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
-	char *pc_PCIChipInformation, unsigned short w_Address,
-	struct str_TimerMainHeader *s_Header);
-
-int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
-	char *pc_PCIChipInformation, unsigned short w_Address,
-	struct str_AnalogOutputHeader *s_Header);
-
-int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
-	char *pc_PCIChipInformation, unsigned short w_Address,
-	struct str_AnalogInputHeader *s_Header);
-
-		/******************************************/
-		/*      Eeprom Specific Functions                         */
-		/******************************************/
-unsigned short w_EepromReadWord(unsigned short w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
-	unsigned short w_EepromStartAddress);
-void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress);
-void v_EepromClock76(unsigned int dw_Address, unsigned int dw_RegisterValue);
-void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress);
-void v_EepromSendCommand76(unsigned int dw_Address, unsigned int dw_EepromCommand,
-	unsigned char b_DataLengthInBits);
-void v_EepromCs76Read(unsigned int dw_Address, unsigned short w_offset, unsigned short *pw_Value);
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : unsigned short w_EepromReadWord                                  |
-|				(unsigned short	w_PCIBoardEepromAddress,             		 |
-|				 char *	pc_PCIChipInformation,               		 |
-|				 unsigned short   w_EepromStartAddress)                		 |
-+----------------------------------------------------------------------------+
-| Task              : Read from eepromn a word                               |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
-|																	 |
-|		      char *pc_PCIChipInformation  : PCI Chip Type.          |
-|																	 |
-|		      unsigned short w_EepromStartAddress    : Selected eeprom address |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : Read word value from eeprom                            |
-+----------------------------------------------------------------------------+
-*/
-
-unsigned short w_EepromReadWord(unsigned short w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
-	unsigned short w_EepromStartAddress)
+static void addi_eeprom_clk_93c76(unsigned long iobase, unsigned int val)
 {
-
-	unsigned char b_Counter = 0;
-
-	unsigned char b_ReadByte = 0;
-
-	unsigned char b_ReadLowByte = 0;
-
-	unsigned char b_ReadHighByte = 0;
-
-	unsigned char b_SelectedAddressLow = 0;
-
-	unsigned char b_SelectedAddressHigh = 0;
-
-	unsigned short w_ReadWord = 0;
-
-	/**************************/
-
-	/* Test the PCI chip type */
-
-	/**************************/
-
-	if ((!strcmp(pc_PCIChipInformation, "S5920")) ||
-		(!strcmp(pc_PCIChipInformation, "S5933")))
-	{
-
-		for (b_Counter = 0; b_Counter < 2; b_Counter++)
-		{
-
-			b_SelectedAddressLow = (w_EepromStartAddress + b_Counter) % 256;	/* Read the low 8 bit part */
-
-			b_SelectedAddressHigh = (w_EepromStartAddress + b_Counter) / 256;	/* Read the high 8 bit part */
-
-	      /************************************/
-
-			/* Select the load low address mode */
-
-	      /************************************/
-
-			outb(NVCMD_LOAD_LOW, w_PCIBoardEepromAddress + 0x3F);
-
-	      /****************/
-
-			/* Wait on busy */
-
-	      /****************/
-
-			v_EepromWaitBusy(w_PCIBoardEepromAddress);
-
-	      /************************/
-
-			/* Load the low address */
-
-	      /************************/
-
-			outb(b_SelectedAddressLow,
-				w_PCIBoardEepromAddress + 0x3E);
-
-	      /****************/
-
-			/* Wait on busy */
-
-	      /****************/
-
-			v_EepromWaitBusy(w_PCIBoardEepromAddress);
-
-	      /*************************************/
-
-			/* Select the load high address mode */
-
-	      /*************************************/
-
-			outb(NVCMD_LOAD_HIGH, w_PCIBoardEepromAddress + 0x3F);
-
-	      /****************/
-
-			/* Wait on busy */
-
-	      /****************/
-
-			v_EepromWaitBusy(w_PCIBoardEepromAddress);
-
-	      /*************************/
-
-			/* Load the high address */
-
-	      /*************************/
-
-			outb(b_SelectedAddressHigh,
-				w_PCIBoardEepromAddress + 0x3E);
-
-	      /****************/
-
-			/* Wait on busy */
-
-	      /****************/
-
-			v_EepromWaitBusy(w_PCIBoardEepromAddress);
-
-	      /************************/
-
-			/* Select the READ mode */
-
-	      /************************/
-
-			outb(NVCMD_BEGIN_READ, w_PCIBoardEepromAddress + 0x3F);
-
-	      /****************/
-
-			/* Wait on busy */
-
-	      /****************/
-
-			v_EepromWaitBusy(w_PCIBoardEepromAddress);
-
-	      /*****************************/
-
-			/* Read data into the EEPROM */
-
-	      /*****************************/
-
-			b_ReadByte = inb(w_PCIBoardEepromAddress + 0x3E);
-
-	      /****************/
-
-			/* Wait on busy */
-
-	      /****************/
-
-			v_EepromWaitBusy(w_PCIBoardEepromAddress);
-
-	      /*********************************/
-
-			/* Select the upper address part */
-
-	      /*********************************/
-
-			if (b_Counter == 0)
-			{
-
-				b_ReadLowByte = b_ReadByte;
-
-			}	/*  if(b_Counter==0) */
-
-			else
-			{
-
-				b_ReadHighByte = b_ReadByte;
-
-			}	/*  if(b_Counter==0) */
-
-		}		/*  for (b_Counter=0; b_Counter<2; b_Counter++) */
-
-		w_ReadWord = (b_ReadLowByte | (((unsigned short) b_ReadHighByte) * 256));
-
-	}			/*  end of if ((!strcmp(pc_PCIChipInformation, "S5920")) || (!strcmp(pc_PCIChipInformation, "S5933"))) */
-
-	if (!strcmp(pc_PCIChipInformation, "93C76"))
-	{
-
-	   /*************************************/
-
-		/* Read 16 bit from the EEPROM 93C76 */
-
-	   /*************************************/
-
-		v_EepromCs76Read(w_PCIBoardEepromAddress, w_EepromStartAddress,
-			&w_ReadWord);
-
-	}
-
-	return w_ReadWord;
-
-}
-
-/*
-
-+----------------------------------------------------------------------------+
-
-| Function   Name   : void v_EepromWaitBusy                                  |
-
-|			(unsigned short	w_PCIBoardEepromAddress)                    	 |
-
-+----------------------------------------------------------------------------+
-
-| Task              : Wait the busy flag from PCI controller                 |
-
-+----------------------------------------------------------------------------+
-
-| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom base address |
-
-+----------------------------------------------------------------------------+
-
-| Output Parameters : -                                                      |
-
-+----------------------------------------------------------------------------+
-
-| Return Value      : -                                                      |
-
-+----------------------------------------------------------------------------+
-
-*/
-
-void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress)
-{
-
-	unsigned char b_EepromBusy = 0;
-
-	do
-	{
-
-	   /*************/
-
-		/* IMPORTANT */
-
-	   /*************/
-
-	   /************************************************************************/
-
-		/* An error has been written in the AMCC 5933 book at the page B-13 */
-
-		/* Ex: if you read a byte and look for the busy statusEEPROM=0x80 and   */
-
-		/*      the operator register is AMCC_OP_REG_MCSR+3 */
-
-		/*      unsigned short read  EEPROM=0x8000 andAMCC_OP_REG_MCSR+2                  */
-
-		/*      unsigned int read  EEPROM=0x80000000 and AMCC_OP_REG_MCSR */
-
-	   /************************************************************************/
-
-		b_EepromBusy = inb(w_PCIBoardEepromAddress + 0x3F);
-		b_EepromBusy = b_EepromBusy & 0x80;
-
-	} while (b_EepromBusy == 0x80);
-
-}
-
-/*
-
-+---------------------------------------------------------------------------------+
-
-| Function   Name   : void v_EepromClock76(unsigned int dw_Address,                      |
-
-|					   unsigned int dw_RegisterValue)                 			  |
-
-+---------------------------------------------------------------------------------+
-
-| Task              : This function sends the clocking sequence to the EEPROM.    |
-
-+---------------------------------------------------------------------------------+
-
-| Input Parameters  : unsigned int dw_Address : PCI eeprom base address                  |
-
-|		      unsigned int dw_RegisterValue : PCI eeprom register value to write.|
-
-+---------------------------------------------------------------------------------+
-
-| Output Parameters : -                                                           |
-
-+---------------------------------------------------------------------------------+
-
-| Return Value      : -                                                           |
-
-+---------------------------------------------------------------------------------+
-
-*/
-
-void v_EepromClock76(unsigned int dw_Address, unsigned int dw_RegisterValue)
-{
-
-   /************************/
-
-	/* Set EEPROM clock Low */
-
-   /************************/
-
-	outl(dw_RegisterValue & 0x6, dw_Address);
-
-   /***************/
-
-	/* Wait 0.1 ms */
-
-   /***************/
-
+	outl(val & ~EE93C76_CLK_BIT, iobase);
 	udelay(100);
 
-   /*************************/
-
-	/* Set EEPROM clock High */
-
-   /*************************/
-
-	outl(dw_RegisterValue | 0x1, dw_Address);
-
-   /***************/
-
-	/* Wait 0.1 ms */
-
-   /***************/
-
+	outl(val | EE93C76_CLK_BIT, iobase);
 	udelay(100);
-
 }
 
-/*
-
-+---------------------------------------------------------------------------------+
-
-| Function   Name   : void v_EepromSendCommand76(unsigned int dw_Address,                |
-
-|					   unsigned int   dw_EepromCommand,                		  |
-
-|					   unsigned char    b_DataLengthInBits)                        |
-
-+---------------------------------------------------------------------------------+
-
-| Task              : This function sends a Command to the EEPROM 93C76.          |
-
-+---------------------------------------------------------------------------------+
-
-| Input Parameters  : unsigned int dw_Address : PCI eeprom base address                  |
-
-|		      unsigned int dw_EepromCommand : PCI eeprom command to write.       |
-
-|		      unsigned char  b_DataLengthInBits : PCI eeprom command data length.  |
-
-+---------------------------------------------------------------------------------+
-
-| Output Parameters : -                                                           |
-
-+---------------------------------------------------------------------------------+
-
-| Return Value      : -                                                           |
-
-+---------------------------------------------------------------------------------+
-
-*/
-
-void v_EepromSendCommand76(unsigned int dw_Address, unsigned int dw_EepromCommand,
-	unsigned char b_DataLengthInBits)
+static unsigned int addi_eeprom_cmd_93c76(unsigned long iobase,
+					  unsigned int cmd,
+					  unsigned char len)
 {
-
-	char c_BitPos = 0;
-
-	unsigned int dw_RegisterValue = 0;
-
-   /*****************************/
-
-	/* Enable EEPROM Chip Select */
-
-   /*****************************/
-
-	dw_RegisterValue = 0x2;
-
-   /********************************************************************/
+	unsigned int val = EE93C76_CS_BIT;
+	int i;
 
 	/* Toggle EEPROM's Chip select to get it out of Shift Register Mode */
-
-   /********************************************************************/
-
-	outl(dw_RegisterValue, dw_Address);
-
-   /***************/
-
-	/* Wait 0.1 ms */
-
-   /***************/
-
+	outl(val, iobase);
 	udelay(100);
 
-   /*******************************************/
-
 	/* Send EEPROM command - one bit at a time */
-
-   /*******************************************/
-
-	for (c_BitPos = (b_DataLengthInBits - 1); c_BitPos >= 0; c_BitPos--)
-	{
-
-      /**********************************/
-
-		/* Check if current bit is 0 or 1 */
-
-      /**********************************/
-
-		if (dw_EepromCommand & (1 << c_BitPos))
-		{
-
-	 /***********/
-
-			/* Write 1 */
-
-	 /***********/
-
-			dw_RegisterValue = dw_RegisterValue | 0x4;
-
-		}
-
+	for (i = (len - 1); i >= 0; i--) {
+		if (cmd & (1 << i))
+			val |= EE93C76_DOUT_BIT;
 		else
-		{
-
-	 /***********/
-
-			/* Write 0 */
-
-	 /***********/
-
-			dw_RegisterValue = dw_RegisterValue & 0x3;
-
-		}
-
-      /*********************/
+			val &= ~EE93C76_DOUT_BIT;
 
 		/* Write the command */
-
-      /*********************/
-
-		outl(dw_RegisterValue, dw_Address);
-
-      /***************/
-
-		/* Wait 0.1 ms */
-
-      /***************/
-
+		outl(val, iobase);
 		udelay(100);
 
-      /****************************/
-
-		/* Trigger the EEPROM clock */
-
-      /****************************/
-
-		v_EepromClock76(dw_Address, dw_RegisterValue);
-
+		addi_eeprom_clk_93c76(iobase, val);
 	}
-
+	return val;
 }
 
-/*
-
-+---------------------------------------------------------------------------------+
-
-| Function   Name   : void v_EepromCs76Read(unsigned int dw_Address,                     |
-
-|					   unsigned short    w_offset,                      			  |
-
-|					   unsigned short *   pw_Value)                      			  |
-
-+---------------------------------------------------------------------------------+
-
-| Task              : This function read a value from the EEPROM 93C76.           |
-
-+---------------------------------------------------------------------------------+
-
-| Input Parameters  : unsigned int dw_Address : PCI eeprom base address                  |
-
-|		      unsigned short    w_offset : Offset of the address to read             |
-
-|		      unsigned short *   pw_Value : PCI eeprom 16 bit read value.            |
-
-+---------------------------------------------------------------------------------+
-
-| Output Parameters : -                                                           |
-
-+---------------------------------------------------------------------------------+
-
-| Return Value      : -                                                           |
-
-+---------------------------------------------------------------------------------+
-
-*/
-
-void v_EepromCs76Read(unsigned int dw_Address, unsigned short w_offset, unsigned short *pw_Value)
+static unsigned short addi_eeprom_readw_93c76(unsigned long iobase,
+					      unsigned short addr)
 {
-
-        char c_BitPos = 0;
-
-	unsigned int dw_RegisterValue = 0;
-
-	unsigned int dw_RegisterValueRead = 0;
-
-   /*************************************************/
+	unsigned short val = 0;
+	unsigned int cmd;
+	unsigned int tmp;
+	int i;
 
 	/* Send EEPROM read command and offset to EEPROM */
-
-   /*************************************************/
-
-	v_EepromSendCommand76(dw_Address, (EE_READ << 4) | (w_offset / 2),
-		EE76_CMD_LEN);
-
-   /*******************************/
-
-	/* Get the last register value */
-
-   /*******************************/
-
-	dw_RegisterValue = (((w_offset / 2) & 0x1) << 2) | 0x2;
-
-   /*****************************/
-
-	/* Set the 16-bit value of 0 */
-
-   /*****************************/
-
-	*pw_Value = 0;
-
-   /************************/
+	cmd = EE93C76_READ_CMD | (addr / 2);
+	cmd = addi_eeprom_cmd_93c76(iobase, cmd, EE93C76_CMD_LEN);
 
 	/* Get the 16-bit value */
+	for (i = 0; i < 16; i++) {
+		addi_eeprom_clk_93c76(iobase, cmd);
 
-   /************************/
-
-	for (c_BitPos = 0; c_BitPos < 16; c_BitPos++)
-	{
-
-      /****************************/
-
-		/* Trigger the EEPROM clock */
-
-      /****************************/
-
-		v_EepromClock76(dw_Address, dw_RegisterValue);
-
-      /**********************/
-
-		/* Get the result bit */
-
-      /**********************/
-
-		dw_RegisterValueRead = inl(dw_Address);
-
-      /***************/
-
-		/* Wait 0.1 ms */
-
-      /***************/
-
+		tmp = inl(iobase);
 		udelay(100);
 
-      /***************************************/
-
-		/* Get bit value and shift into result */
-
-      /***************************************/
-
-		if (dw_RegisterValueRead & 0x8)
-		{
-
-	 /**********/
+		val <<= 1;
+		if (tmp & EE93C76_DIN_BIT)
+			val |= 0x1;
+	}
 
-			/* Read 1 */
+	/* Toggle EEPROM's Chip select to get it out of Shift Register Mode */
+	outl(0, iobase);
+	udelay(100);
 
-	 /**********/
+	return val;
+}
 
-			*pw_Value = (*pw_Value << 1) | 0x1;
+static void addi_eeprom_nvram_wait(unsigned long iobase)
+{
+	unsigned char val;
 
-		}
+	do {
+		val = inb(iobase + AMCC_OP_REG_MCSR_NVCMD);
+	} while (val & 0x80);
+}
 
+static unsigned short addi_eeprom_readw_nvram(unsigned long iobase,
+					      unsigned short addr)
+{
+	unsigned short val = 0;
+	unsigned char tmp;
+	unsigned char i;
+
+	for (i = 0; i < 2; i++) {
+		/* Load the low 8 bit address */
+		outb(NVCMD_LOAD_LOW, iobase + AMCC_OP_REG_MCSR_NVCMD);
+		addi_eeprom_nvram_wait(iobase);
+		outb((addr + i) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
+		addi_eeprom_nvram_wait(iobase);
+
+		/* Load the high 8 bit address */
+		outb(NVCMD_LOAD_HIGH, iobase + AMCC_OP_REG_MCSR_NVCMD);
+		addi_eeprom_nvram_wait(iobase);
+		outb(((addr + i) >> 8) & 0xff,
+			iobase + AMCC_OP_REG_MCSR_NVDATA);
+		addi_eeprom_nvram_wait(iobase);
+
+		/* Read the eeprom data byte */
+		outb(NVCMD_BEGIN_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
+		addi_eeprom_nvram_wait(iobase);
+		tmp = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
+		addi_eeprom_nvram_wait(iobase);
+
+		if (i == 0)
+			val |= tmp;
 		else
-		{
-
-	 /**********/
-
-			/* Read 0 */
+			val |= (tmp << 8);
+	}
 
-	 /**********/
+	return val;
+}
 
-			*pw_Value = (*pw_Value << 1);
+static unsigned short addi_eeprom_readw(unsigned long iobase,
+					char *type,
+					unsigned short addr)
+{
+	unsigned short val = 0;
 
-		}
+	/* Add the offset to the start of the user data */
+	addr += NVRAM_USER_DATA_START;
 
-	}
+	if (!strcmp(type, "S5920") || !strcmp(type, "S5933"))
+		val = addi_eeprom_readw_nvram(iobase, addr);
 
-   /*************************/
+	if (!strcmp(type, "93C76"))
+		val = addi_eeprom_readw_93c76(iobase, addr);
 
-	/* Clear all EEPROM bits */
+	return val;
+}
 
-   /*************************/
+static void addi_eeprom_read_di_info(struct comedi_device *dev,
+				     unsigned long iobase,
+				     unsigned short addr)
+{
+	const struct addi_board *this_board = comedi_board(dev);
+	struct addi_private *devpriv = dev->private;
+	char *type = this_board->pc_EepromChip;
+	unsigned short tmp;
 
-	dw_RegisterValue = 0x0;
+	/* Number of channels */
+	tmp = addi_eeprom_readw(iobase, type, addr + 6);
+	devpriv->s_EeParameters.i_NbrDiChannel = tmp;
 
-   /********************************************************************/
+	/* Interruptible or not */
+	tmp = addi_eeprom_readw(iobase, type, addr + 8);
+	tmp = (tmp >> 7) & 0x01;
 
-	/* Toggle EEPROM's Chip select to get it out of Shift Register Mode */
+	/* How many interruptible logic */
+	tmp = addi_eeprom_readw(iobase, type, addr + 10);
+}
 
-   /********************************************************************/
+static void addi_eeprom_read_do_info(struct comedi_device *dev,
+				     unsigned long iobase,
+				     unsigned short addr)
+{
+	const struct addi_board *this_board = comedi_board(dev);
+	struct addi_private *devpriv = dev->private;
+	char *type = this_board->pc_EepromChip;
+	unsigned short tmp;
 
-	outl(dw_RegisterValue, dw_Address);
+	/* Number of channels */
+	tmp = addi_eeprom_readw(iobase, type, addr + 6);
+	devpriv->s_EeParameters.i_NbrDoChannel = tmp;
 
-   /***************/
+	devpriv->s_EeParameters.i_DoMaxdata = 0xffffffff >> (32 - tmp);
+}
 
-	/* Wait 0.1 ms */
+static void addi_eeprom_read_timer_info(struct comedi_device *dev,
+					unsigned long iobase,
+					unsigned short addr)
+{
+	struct addi_private *devpriv = dev->private;
+#if 0
+	const struct addi_board *this_board = comedi_board(dev);
+	char *type = this_board->pc_EepromChip;
+	unsigned short offset = 0;
+	unsigned short ntimers;
+	unsigned short tmp;
+	int i;
+
+	/* Number of Timers */
+	ntimers = addi_eeprom_readw(iobase, type, addr + 6);
+
+	/* Read header size */
+	for (i = 0; i < ntimers; i++) {
+		unsigned short size;
+		unsigned short res;
+		unsigned short mode;
+		unsigned short min_timing;
+		unsigned short timebase;
+
+		size = addi_eeprom_readw(iobase, type, addr + 8 + offset + 0);
+
+		/* Resolution / Mode */
+		tmp = addi_eeprom_readw(iobase, type, addr + 8 + offset + 2);
+		res = (tmp >> 10) & 0x3f;
+		mode = (tmp >> 4) & 0x3f;
+
+		/* MinTiming / Timebase */
+		tmp = addi_eeprom_readw(iobase, type, addr + 8 + offset + 4);
+		min_timing = (tmp  >> 6) & 0x3ff;
+		Timebase = tmp & 0x3f;
+
+		offset += size;
+	}
+#endif
+	/* Timer subdevice present */
+	devpriv->s_EeParameters.i_Timer = 1;
+}
 
-   /***************/
+static void addi_eeprom_read_ao_info(struct comedi_device *dev,
+				     unsigned long iobase,
+				     unsigned short addr)
+{
+	const struct addi_board *this_board = comedi_board(dev);
+	struct addi_private *devpriv = dev->private;
+	char *type = this_board->pc_EepromChip;
+	unsigned short tmp;
+
+	/* No of channels for 1st hard component */
+	tmp = addi_eeprom_readw(iobase, type, addr + 10);
+	devpriv->s_EeParameters.i_NbrAoChannel = (tmp >> 4) & 0x3ff;
+
+	/* Resolution for 1st hard component */
+	tmp = addi_eeprom_readw(iobase, type, addr + 16);
+	tmp = (tmp >> 8) & 0xff;
+	devpriv->s_EeParameters.i_AoMaxdata = 0xfff >> (16 - tmp);
+}
 
-	udelay(100);
+static void addi_eeprom_read_ai_info(struct comedi_device *dev,
+				     unsigned long iobase,
+				     unsigned short addr)
+{
+	const struct addi_board *this_board = comedi_board(dev);
+	struct addi_private *devpriv = dev->private;
+	char *type = this_board->pc_EepromChip;
+	unsigned short offset;
+	unsigned short tmp;
+
+	/* No of channels for 1st hard component */
+	tmp = addi_eeprom_readw(iobase, type, addr + 10);
+	devpriv->s_EeParameters.i_NbrAiChannel = (tmp >> 4) & 0x3ff;
+	if (!strcmp(this_board->pc_DriverName, "apci3200"))
+		devpriv->s_EeParameters.i_NbrAiChannel *= 4;
+
+	tmp = addi_eeprom_readw(iobase, type, addr + 16);
+	devpriv->s_EeParameters.ui_MinAcquisitiontimeNs = tmp * 1000;
+
+	tmp = addi_eeprom_readw(iobase, type, addr + 30);
+	devpriv->s_EeParameters.ui_MinDelaytimeNs = tmp * 1000;
+
+	tmp = addi_eeprom_readw(iobase, type, addr + 20);
+	devpriv->s_EeParameters.i_Dma = (tmp >> 13) & 0x01;
+
+	tmp = addi_eeprom_readw(iobase, type, addr + 72) & 0xff;
+	if (tmp) {		/* > 0 */
+		/* offset of first analog input single header */
+		offset = 74 + (2 * tmp) + (10 * (1 + (tmp / 16)));
+	} else {		/* = 0 */
+		offset = 74;
+	}
 
+	/* Resolution */
+	tmp = addi_eeprom_readw(iobase, type, addr + offset + 2) & 0x1f;
+	devpriv->s_EeParameters.i_AiMaxdata = 0xffff >> (16 - tmp);
 }
 
-	/******************************************/
-	/*      EEPROM HEADER READ FUNCTIONS      */
-	/******************************************/
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name  : int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,  |
-|				char *	pc_PCIChipInformation,struct comedi_device *dev)    |
-+----------------------------------------------------------------------------+
-| Task              : Read from eeprom Main Header                           |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
-|																	 |
-|		      char *pc_PCIChipInformation  : PCI Chip Type.          |
-|																	 |
-|			  struct comedi_device *dev		   : comedi device structure |
-|											 pointer				 |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0							                             |
-+----------------------------------------------------------------------------+
-*/
-
-int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
-	char *pc_PCIChipInformation, struct comedi_device *dev)
+static void addi_eeprom_read_info(struct comedi_device *dev,
+				  unsigned long iobase)
 {
-	unsigned short w_Temp, i, w_Count = 0;
-	unsigned int ui_Temp;
-	struct str_MainHeader s_MainHeader;
-	struct str_DigitalInputHeader s_DigitalInputHeader;
-	struct str_DigitalOutputHeader s_DigitalOutputHeader;
-	/* struct str_TimerMainHeader     s_TimerMainHeader,s_WatchdogMainHeader; */
-	struct str_AnalogOutputHeader s_AnalogOutputHeader;
-	struct str_AnalogInputHeader s_AnalogInputHeader;
-
-	/* Read size */
-	s_MainHeader.w_HeaderSize =
-		w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
-		0x100 + 8);
-
-	/* Read nbr of functionality */
-	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
-		pc_PCIChipInformation, 0x100 + 10);
-	s_MainHeader.b_Nfunctions = (unsigned char) w_Temp & 0x00FF;
+	const struct addi_board *this_board = comedi_board(dev);
+	char *type = this_board->pc_EepromChip;
+	unsigned short size;
+	unsigned char nfuncs;
+	int i;
+
+	size = addi_eeprom_readw(iobase, type, 8);
+	nfuncs = addi_eeprom_readw(iobase, type, 10) & 0xff;
 
 	/* Read functionality details */
-	for (i = 0; i < s_MainHeader.b_Nfunctions; i++) {
-		/* Read Type */
-		w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
-			pc_PCIChipInformation, 0x100 + 12 + w_Count);
-		s_MainHeader.s_Functions[i].b_Type = (unsigned char) w_Temp & 0x3F;
-		w_Count = w_Count + 2;
-		/* Read Address */
-		s_MainHeader.s_Functions[i].w_Address =
-			w_EepromReadWord(w_PCIBoardEepromAddress,
-			pc_PCIChipInformation, 0x100 + 12 + w_Count);
-		w_Count = w_Count + 2;
-	}
+	for (i = 0; i < nfuncs; i++) {
+		unsigned short offset = i * 4;
+		unsigned short addr;
+		unsigned char func;
 
-	/* Display main header info */
-	for (i = 0; i < s_MainHeader.b_Nfunctions; i++) {
+		func = addi_eeprom_readw(iobase, type, 12 + offset) & 0x3f;
+		addr = addi_eeprom_readw(iobase, type, 14 + offset);
 
-		switch (s_MainHeader.s_Functions[i].b_Type) {
+		switch (func) {
 		case EEPROM_DIGITALINPUT:
-			i_EepromReadDigitalInputHeader(w_PCIBoardEepromAddress,
-				pc_PCIChipInformation,
-				s_MainHeader.s_Functions[i].w_Address,
-				&s_DigitalInputHeader);
-			devpriv->s_EeParameters.i_NbrDiChannel =
-				s_DigitalInputHeader.w_Nchannel;
+			addi_eeprom_read_di_info(dev, iobase, addr);
 			break;
 
 		case EEPROM_DIGITALOUTPUT:
-			i_EepromReadDigitalOutputHeader(w_PCIBoardEepromAddress,
-				pc_PCIChipInformation,
-				s_MainHeader.s_Functions[i].w_Address,
-				&s_DigitalOutputHeader);
-			devpriv->s_EeParameters.i_NbrDoChannel =
-				s_DigitalOutputHeader.w_Nchannel;
-			ui_Temp = 0xffffffff;
-			devpriv->s_EeParameters.i_DoMaxdata =
-				ui_Temp >> (32 -
-					devpriv->s_EeParameters.i_NbrDoChannel);
+			addi_eeprom_read_do_info(dev, iobase, addr);
 			break;
 
 		case EEPROM_ANALOGINPUT:
-			i_EepromReadAnlogInputHeader(w_PCIBoardEepromAddress,
-				pc_PCIChipInformation,
-				s_MainHeader.s_Functions[i].w_Address,
-				&s_AnalogInputHeader);
-			if (!(strcmp(this_board->pc_DriverName, "apci3200")))
-				devpriv->s_EeParameters.i_NbrAiChannel =
-					s_AnalogInputHeader.w_Nchannel * 4;
-			else
-				devpriv->s_EeParameters.i_NbrAiChannel =
-					s_AnalogInputHeader.w_Nchannel;
-			devpriv->s_EeParameters.i_Dma =
-				s_AnalogInputHeader.b_HasDma;
-			devpriv->s_EeParameters.ui_MinAcquisitiontimeNs =
-				(unsigned int) s_AnalogInputHeader.w_MinConvertTiming *
-				1000;
-			devpriv->s_EeParameters.ui_MinDelaytimeNs =
-				(unsigned int) s_AnalogInputHeader.w_MinDelayTiming *
-				1000;
-			ui_Temp = 0xffff;
-			devpriv->s_EeParameters.i_AiMaxdata =
-				ui_Temp >> (16 -
-				s_AnalogInputHeader.b_Resolution);
+			addi_eeprom_read_ai_info(dev, iobase, addr);
 			break;
 
 		case EEPROM_ANALOGOUTPUT:
-			i_EepromReadAnlogOutputHeader(w_PCIBoardEepromAddress,
-				pc_PCIChipInformation,
-				s_MainHeader.s_Functions[i].w_Address,
-				&s_AnalogOutputHeader);
-			devpriv->s_EeParameters.i_NbrAoChannel =
-				s_AnalogOutputHeader.w_Nchannel;
-			ui_Temp = 0xffff;
-			devpriv->s_EeParameters.i_AoMaxdata =
-				ui_Temp >> (16 -
-				s_AnalogOutputHeader.b_Resolution);
+			addi_eeprom_read_ao_info(dev, iobase, addr);
 			break;
 
 		case EEPROM_TIMER:
-			/* Timer subdevice present */
-			devpriv->s_EeParameters.i_Timer = 1;
-			break;
-
 		case EEPROM_WATCHDOG:
-			/* Timer subdevice present */
-			devpriv->s_EeParameters.i_Timer = 1;
-			break;
-
 		case EEPROM_TIMER_WATCHDOG_COUNTER:
-			/* Timer subdevice present */
-			devpriv->s_EeParameters.i_Timer = 1;
+			addi_eeprom_read_timer_info(dev, iobase, addr);
 			break;
 		}
 	}
-
-	return 0;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name  : int i_EepromReadDigitalInputHeader(unsigned short 					 |
-|			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,	 |
-|			unsigned short w_Address,struct str_DigitalInputHeader *s_Header)		 |
-|																	 |
-+----------------------------------------------------------------------------+
-| Task              : Read Digital Input Header                              |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
-|																	 |
-|		      char *pc_PCIChipInformation  : PCI Chip Type.          |
-|																	 |
-|			 struct str_DigitalInputHeader *s_Header: Digita Input Header   |
-|												   Pointer			 |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0							                             |
-+----------------------------------------------------------------------------+
-*/
-int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
-	char *pc_PCIChipInformation, unsigned short w_Address,
-	struct str_DigitalInputHeader *s_Header)
-{
-	unsigned short w_Temp;
-
-	/*  read nbr of channels */
-	s_Header->w_Nchannel =
-		w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
-		0x100 + w_Address + 6);
-
-	/*  interruptible or not */
-	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
-		pc_PCIChipInformation, 0x100 + w_Address + 8);
-	s_Header->b_Interruptible = (unsigned char) (w_Temp >> 7) & 0x01;
-
-/* How many interruptible logic */
-	s_Header->w_NinterruptLogic =
-		w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
-		0x100 + w_Address + 10);
-
-	return 0;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name  : int i_EepromReadDigitalOutputHeader(unsigned short 				 |
-|			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,	 |
-|			unsigned short w_Address,struct str_DigitalOutputHeader *s_Header)	     |
-|																	 |
-+----------------------------------------------------------------------------+
-| Task              : Read Digital Output Header                             |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
-|																	 |
-|		      char *pc_PCIChipInformation  : PCI Chip Type.          |
-|																	 |
-|			 struct str_DigitalOutputHeader *s_Header: Digital Output Header|
-|											   Pointer				 |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0							                             |
-+----------------------------------------------------------------------------+
-*/
-int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
-	char *pc_PCIChipInformation, unsigned short w_Address,
-	struct str_DigitalOutputHeader *s_Header)
-{
-/* Read Nbr channels */
-	s_Header->w_Nchannel =
-		w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
-		0x100 + w_Address + 6);
-	return 0;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name  : int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress, |
-|			char *pc_PCIChipInformation,WORD w_Address,				 |
-|			struct str_TimerMainHeader *s_Header)							 |
-+----------------------------------------------------------------------------+
-| Task              : Read Timer or Watchdog Header                          |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
-|																	 |
-|		      char *pc_PCIChipInformation  : PCI Chip Type.          |
-|																	 |
-|			 struct str_TimerMainHeader *s_Header: Timer Header			 |
-|											   Pointer				 |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0							                             |
-+----------------------------------------------------------------------------+
-*/
-int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
-	char *pc_PCIChipInformation, unsigned short w_Address,
-	struct str_TimerMainHeader *s_Header)
-{
-
-	unsigned short i, w_Size = 0, w_Temp;
-
-/* Read No of Timer */
-	s_Header->w_Ntimer =
-		w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
-		0x100 + w_Address + 6);
-/* Read header size */
-
-	for (i = 0; i < s_Header->w_Ntimer; i++) {
-		s_Header->s_TimerDetails[i].w_HeaderSize =
-			w_EepromReadWord(w_PCIBoardEepromAddress,
-			pc_PCIChipInformation,
-			0x100 + w_Address + 8 + w_Size + 0);
-		w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
-			pc_PCIChipInformation,
-			0x100 + w_Address + 8 + w_Size + 2);
-
-		/* Read Resolution */
-		s_Header->s_TimerDetails[i].b_Resolution =
-			(unsigned char) (w_Temp >> 10) & 0x3F;
-
-		/* Read Mode */
-		s_Header->s_TimerDetails[i].b_Mode =
-			(unsigned char) (w_Temp >> 4) & 0x3F;
-
-		w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
-			pc_PCIChipInformation,
-			0x100 + w_Address + 8 + w_Size + 4);
-
-		/* Read MinTiming */
-		s_Header->s_TimerDetails[i].w_MinTiming = (w_Temp >> 6) & 0x3FF;
-
-		/* Read Timebase */
-		s_Header->s_TimerDetails[i].b_TimeBase = (unsigned char) (w_Temp) & 0x3F;
-		w_Size += s_Header->s_TimerDetails[i].w_HeaderSize;
-	}
-
-	return 0;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name  : int i_EepromReadAnlogOutputHeader(unsigned short 					 |
-|			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,	 |
-|			unsigned short w_Address,str_AnalogOutputHeader *s_Header)         |
-+----------------------------------------------------------------------------+
-| Task              : Read Nalog Output  Header                              |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
-|																	 |
-|		      char *pc_PCIChipInformation  : PCI Chip Type.          |
-|																	 |
-|			 str_AnalogOutputHeader *s_Header:Anlog Output Header    |
-|											   Pointer				 |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0							                             |
-+----------------------------------------------------------------------------+
-*/
-
-int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
-	char *pc_PCIChipInformation, unsigned short w_Address,
-	struct str_AnalogOutputHeader *s_Header)
-{
-	unsigned short w_Temp;
-	/*  No of channels for 1st hard component */
-	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
-		pc_PCIChipInformation, 0x100 + w_Address + 10);
-	s_Header->w_Nchannel = (w_Temp >> 4) & 0x03FF;
-	/*  Resolution for 1st hard component */
-	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
-		pc_PCIChipInformation, 0x100 + w_Address + 16);
-	s_Header->b_Resolution = (unsigned char) (w_Temp >> 8) & 0xFF;
-	return 0;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function Name  : int i_EepromReadAnlogInputHeader(unsigned short 					 |
-|			w_PCIBoardEepromAddress,char *pc_PCIChipInformation,     |
-|			unsigned short w_Address,struct str_AnalogInputHeader *s_Header)          |
-+----------------------------------------------------------------------------+
-| Task              : Read Nalog Output  Header                              |
-+----------------------------------------------------------------------------+
-| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
-|																	 |
-|		      char *pc_PCIChipInformation  : PCI Chip Type.          |
-|																	 |
-|			 struct str_AnalogInputHeader *s_Header:Anlog Input Header      |
-|											   Pointer				 |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : 0							                             |
-+----------------------------------------------------------------------------+
-*/
-
-/* Reads only for ONE  hardware component */
-int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
-	char *pc_PCIChipInformation, unsigned short w_Address,
-	struct str_AnalogInputHeader *s_Header)
-{
-	unsigned short w_Temp, w_Offset;
-	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
-		pc_PCIChipInformation, 0x100 + w_Address + 10);
-	s_Header->w_Nchannel = (w_Temp >> 4) & 0x03FF;
-	s_Header->w_MinConvertTiming =
-		w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
-		0x100 + w_Address + 16);
-	s_Header->w_MinDelayTiming =
-		w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
-		0x100 + w_Address + 30);
-	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
-		pc_PCIChipInformation, 0x100 + w_Address + 20);
-	s_Header->b_HasDma = (w_Temp >> 13) & 0x01;	/*  whether dma present or not */
-
-	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, 0x100 + w_Address + 72);	/*  reading Y */
-	w_Temp = w_Temp & 0x00FF;
-	if (w_Temp)		/* Y>0 */
-	{
-		w_Offset = 74 + (2 * w_Temp) + (10 * (1 + (w_Temp / 16)));	/*  offset of first analog input single header */
-		w_Offset = w_Offset + 2;	/*  resolution */
-	} else			/* Y=0 */
-	{
-		w_Offset = 74;
-		w_Offset = w_Offset + 2;	/*  resolution */
-	}
-
-/* read Resolution */
-	w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
-		pc_PCIChipInformation, 0x100 + w_Address + w_Offset);
-	s_Header->b_Resolution = w_Temp & 0x001F;	/*  last 5 bits */
-
-	return 0;
 }
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
index f9a8937..b05f850 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
@@ -44,7 +44,35 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   |          |           |                                                |
   +----------+-----------+------------------------------------------------+
 */
-#include "hwdrv_APCI1710.h"
+
+#define COMEDI_SUBD_TTLIO		11	/* Digital Input Output But TTL */
+#define COMEDI_SUBD_PWM			12	/* Pulse width Measurement */
+#define COMEDI_SUBD_SSI			13	/* Synchronous serial interface */
+#define COMEDI_SUBD_TOR			14	/* Tor counter */
+#define COMEDI_SUBD_CHRONO		15	/* Chrono meter */
+#define COMEDI_SUBD_PULSEENCODER	16	/* Pulse Encoder INP CPT */
+#define COMEDI_SUBD_INCREMENTALCOUNTER	17	/* Incremental Counter */
+
+#define APCI1710_BOARD_NAME		"apci1710"
+#define APCI1710_BOARD_DEVICE_ID	0x818F
+#define APCI1710_ADDRESS_RANGE		256
+#define APCI1710_CONFIG_ADDRESS_RANGE	8
+#define APCI1710_INCREMENTAL_COUNTER	0x53430000UL
+#define APCI1710_SSI_COUNTER		0x53490000UL
+#define APCI1710_TTL_IO			0x544C0000UL
+#define APCI1710_DIGITAL_IO		0x44490000UL
+#define APCI1710_82X54_TIMER		0x49430000UL
+#define APCI1710_CHRONOMETER		0x43480000UL
+#define APCI1710_PULSE_ENCODER		0x495A0000UL
+#define APCI1710_TOR_COUNTER		0x544F0000UL
+#define APCI1710_PWM			0x50570000UL
+#define APCI1710_ETM			0x45540000UL
+#define APCI1710_CDA			0x43440000UL
+#define APCI1710_DISABLE		0
+#define APCI1710_ENABLE			1
+#define APCI1710_SYNCHRONOUS_MODE	1
+#define APCI1710_ASYNCHRONOUS_MODE	0
+
 #include "APCI1710_Inp_cpt.c"
 
 #include "APCI1710_Ssi.c"
@@ -56,7 +84,34 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 #include "APCI1710_Pwm.c"
 #include "APCI1710_INCCPT.c"
 
-void i_ADDI_AttachPCI1710(struct comedi_device *dev)
+static const struct comedi_lrange range_apci1710_ttl = {
+	4, {
+		BIP_RANGE(10),
+		BIP_RANGE(5),
+		BIP_RANGE(2),
+		BIP_RANGE(1)
+	}
+};
+
+static const struct comedi_lrange range_apci1710_ssi = {
+	4, {
+		BIP_RANGE(10),
+		BIP_RANGE(5),
+		BIP_RANGE(2),
+		BIP_RANGE(1)
+	}
+};
+
+static const struct comedi_lrange range_apci1710_inccpt = {
+	4, {
+		BIP_RANGE(10),
+		BIP_RANGE(5),
+		BIP_RANGE(2),
+		BIP_RANGE(1)
+	}
+};
+
+static void i_ADDI_AttachPCI1710(struct comedi_device *dev)
 {
 	struct comedi_subdevice *s;
 	int ret = 0;
@@ -195,12 +250,9 @@ void i_ADDI_AttachPCI1710(struct comedi_device *dev)
 	s->insn_bits = i_APCI1710_InsnBitsINCCPT;
 }
 
-int i_APCI1710_Reset(struct comedi_device *dev);
-void v_APCI1710_Interrupt(int irq, void *d);
-/* for 1710 */
-
-int i_APCI1710_Reset(struct comedi_device *dev)
+static int i_APCI1710_Reset(struct comedi_device *dev)
 {
+	struct addi_private *devpriv = dev->private;
 	int ret;
 	unsigned int dw_Dummy;
 
@@ -247,9 +299,10 @@ int i_APCI1710_Reset(struct comedi_device *dev)
 +----------------------------------------------------------------------------+
 */
 
-void v_APCI1710_Interrupt(int irq, void *d)
+static void v_APCI1710_Interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct addi_private *devpriv = dev->private;
 	unsigned char b_ModuleCpt = 0;
 	unsigned char b_InterruptFlag = 0;
 	unsigned char b_PWMCpt = 0;
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h
deleted file mode 100644
index 89c99eb..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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 COMEDI_SUBD_TTLIO		11	/* Digital Input Output But TTL */
-#define COMEDI_SUBD_PWM			12	/* Pulse width Measurement */
-#define COMEDI_SUBD_SSI			13	/* Synchronous serial interface */
-#define COMEDI_SUBD_TOR			14	/* Tor counter */
-#define COMEDI_SUBD_CHRONO		15	/* Chrono meter */
-#define COMEDI_SUBD_PULSEENCODER	16	/* Pulse Encoder INP CPT */
-#define COMEDI_SUBD_INCREMENTALCOUNTER	17	/* Incremental Counter */
-
-#define APCI1710_BOARD_NAME		"apci1710"
-#define APCI1710_BOARD_VENDOR_ID	0x10E8
-#define APCI1710_BOARD_DEVICE_ID	0x818F
-#define APCI1710_ADDRESS_RANGE		256
-#define APCI1710_CONFIG_ADDRESS_RANGE	8
-#define APCI1710_INCREMENTAL_COUNTER	0x53430000UL
-#define APCI1710_SSI_COUNTER		0x53490000UL
-#define APCI1710_TTL_IO			0x544C0000UL
-#define APCI1710_DIGITAL_IO		0x44490000UL
-#define APCI1710_82X54_TIMER		0x49430000UL
-#define APCI1710_CHRONOMETER		0x43480000UL
-#define APCI1710_PULSE_ENCODER		0x495A0000UL
-#define APCI1710_TOR_COUNTER		0x544F0000UL
-#define APCI1710_PWM			0x50570000UL
-#define APCI1710_ETM			0x45540000UL
-#define APCI1710_CDA			0x43440000UL
-#define APCI1710_DISABLE		0
-#define APCI1710_ENABLE			1
-#define APCI1710_SYNCHRONOUS_MODE	1
-#define APCI1710_ASYNCHRONOUS_MODE	0
-
-/* MODULE INFO STRUCTURE */
-
-static const struct comedi_lrange range_apci1710_ttl = { 4, {
-						      BIP_RANGE(10),
-						      BIP_RANGE(5),
-						      BIP_RANGE(2),
-						      BIP_RANGE(1)
-						      }
-};
-
-static const struct comedi_lrange range_apci1710_ssi = { 4, {
-						      BIP_RANGE(10),
-						      BIP_RANGE(5),
-						      BIP_RANGE(2),
-						      BIP_RANGE(1)
-						      }
-};
-
-static const struct comedi_lrange range_apci1710_inccpt = { 4, {
-							 BIP_RANGE(10),
-							 BIP_RANGE(5),
-							 BIP_RANGE(2),
-							 BIP_RANGE(1)
-							 }
-};
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
index 5997b2f..3d66e48 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
@@ -46,12 +46,70 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +----------+-----------+------------------------------------------------+
 */
 
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
-#include "hwdrv_apci035.h"
+/* Card Specific information */
+#define APCI035_ADDRESS_RANGE		255
+
+/* Timer / Watchdog Related Defines */
+#define APCI035_TCW_SYNC_ENABLEDISABLE	0
+#define APCI035_TCW_RELOAD_VALUE	4
+#define APCI035_TCW_TIMEBASE		8
+#define APCI035_TCW_PROG		12
+#define APCI035_TCW_TRIG_STATUS		16
+#define APCI035_TCW_IRQ			20
+#define APCI035_TCW_WARN_TIMEVAL	24
+#define APCI035_TCW_WARN_TIMEBASE	28
+
+#define ADDIDATA_TIMER			0
+/* #define ADDIDATA_WATCHDOG		1 */
+
+#define APCI035_TW1			0
+#define APCI035_TW2			32
+#define APCI035_TW3			64
+#define APCI035_TW4			96
+
+#define APCI035_AI_OFFSET		0
+#define APCI035_TEMP			128
+#define APCI035_ALR_SEQ			4
+#define APCI035_START_STOP_INDEX	8
+#define APCI035_ALR_START_STOP		12
+#define APCI035_ALR_IRQ			16
+#define APCI035_EOS			20
+#define APCI035_CHAN_NO			24
+#define APCI035_CHAN_VAL		28
+#define APCI035_CONV_TIME_TIME_BASE	36
+#define APCI035_RELOAD_CONV_TIME_VAL	32
+#define APCI035_DELAY_TIME_TIME_BASE	44
+#define APCI035_RELOAD_DELAY_TIME_VAL	40
+#define ENABLE_EXT_TRIG			1
+#define ENABLE_EXT_GATE			2
+#define ENABLE_EXT_TRIG_GATE		3
+
+#define ANALOG_INPUT			0
+#define TEMPERATURE			1
+#define RESISTANCE			2
+
+#define ADDIDATA_GREATER_THAN_TEST	0
+#define ADDIDATA_LESS_THAN_TEST		1
+
+#define APCI035_MAXVOLT			2.5
+
+#define ADDIDATA_UNIPOLAR		1
+#define ADDIDATA_BIPOLAR		2
+
+/* ANALOG INPUT RANGE */
+static struct comedi_lrange range_apci035_ai = {
+	8, {
+		BIP_RANGE(10),
+		BIP_RANGE(5),
+		BIP_RANGE(2),
+		BIP_RANGE(1),
+		UNI_RANGE(10),
+		UNI_RANGE(5),
+		UNI_RANGE(2),
+		UNI_RANGE(1)
+	}
+};
+
 static int i_WatchdogNbr = 0;
 static int i_Temp = 0;
 static int i_Flag = 1;
@@ -109,12 +167,16 @@ static int i_Flag = 1;
 |			                                                         |
 +----------------------------------------------------------------------------+
 */
-int i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev,
+					 struct comedi_subdevice *s,
+					 struct comedi_insn *insn,
+					 unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_Status = 0;
 	unsigned int ui_Command = 0;
 	unsigned int ui_Mode = 0;
+
 	i_Temp = 0;
 	devpriv->tsk_Current = current;
 	devpriv->b_TimerSelectMode = data[0];
@@ -278,11 +340,15 @@ int i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev, struct comedi_subde
 |					                                                 |
 +----------------------------------------------------------------------------+
 */
-int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
+						 struct comedi_subdevice *s,
+						 struct comedi_insn *insn,
+						 unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_Command = 0;
 	int i_Count = 0;
+
 	if (data[0] == 1) {
 		ui_Command =
 			inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12);
@@ -393,10 +459,14 @@ int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
 |			                                                         |
 +----------------------------------------------------------------------------+
 */
-int i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI035_ReadTimerWatchdog(struct comedi_device *dev,
+				       struct comedi_subdevice *s,
+				       struct comedi_insn *insn,
+				       unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_Status = 0;	/*  Status register */
+
 	i_WatchdogNbr = insn->unused[0];
 
 	/******************/
@@ -453,9 +523,13 @@ int i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, struct comedi_subdevi
 |			                                                         |
 +----------------------------------------------------------------------------+
 */
-int i_APCI035_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI035_ConfigAnalogInput(struct comedi_device *dev,
+				       struct comedi_subdevice *s,
+				       struct comedi_insn *insn,
+				       unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
+
 	devpriv->tsk_Current = current;
 	outl(0x200 | 0, devpriv->iobase + 128 + 0x4);
 	outl(0, devpriv->iobase + 128 + 0);
@@ -490,10 +564,14 @@ int i_APCI035_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevi
 |			                                                         |
 +----------------------------------------------------------------------------+
 */
-int i_APCI035_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI035_ReadAnalogInput(struct comedi_device *dev,
+				     struct comedi_subdevice *s,
+				     struct comedi_insn *insn,
+				     unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_CommandRegister = 0;
+
 /******************/
 /*  Set the start */
 /******************/
@@ -525,9 +603,11 @@ int i_APCI035_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice
 |			                                                                 |
 +----------------------------------------------------------------------------+
 */
-int i_APCI035_Reset(struct comedi_device *dev)
+static int i_APCI035_Reset(struct comedi_device *dev)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_Count = 0;
+
 	for (i_Count = 1; i_Count <= 4; i_Count++) {
 		i_WatchdogNbr = i_Count;
 		outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0);	/* stop all timers */
@@ -557,11 +637,13 @@ int i_APCI035_Reset(struct comedi_device *dev)
 static void v_APCI035_Interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_StatusRegister1 = 0;
 	unsigned int ui_StatusRegister2 = 0;
 	unsigned int ui_ReadCommand = 0;
 	unsigned int ui_ChannelNumber = 0;
 	unsigned int ui_DigitalTemperature = 0;
+
 	if (i_Temp == 1) {
 		i_WatchdogNbr = i_Flag;
 		i_Flag = i_Flag + 1;
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
deleted file mode 100644
index 3c700c7..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/* Card Specific information */
-#define APCI035_BOARD_VENDOR_ID		0x15B8
-#define APCI035_ADDRESS_RANGE		255
-
-/* ANALOG INPUT RANGE */
-static struct comedi_lrange range_apci035_ai = { 8, {
-				       BIP_RANGE(10),
-				       BIP_RANGE(5),
-				       BIP_RANGE(2),
-				       BIP_RANGE(1),
-				       UNI_RANGE(10),
-				       UNI_RANGE(5),
-				       UNI_RANGE(2),
-				       UNI_RANGE(1)
-				       }
-};
-
-/* Timer / Watchdog Related Defines */
-#define APCI035_TCW_SYNC_ENABLEDISABLE	0
-#define APCI035_TCW_RELOAD_VALUE	4
-#define APCI035_TCW_TIMEBASE		8
-#define APCI035_TCW_PROG		12
-#define APCI035_TCW_TRIG_STATUS		16
-#define APCI035_TCW_IRQ			20
-#define APCI035_TCW_WARN_TIMEVAL	24
-#define APCI035_TCW_WARN_TIMEBASE	28
-
-#define ADDIDATA_TIMER			0
-/* #define ADDIDATA_WATCHDOG		1 */
-
-#define APCI035_TW1                               0
-#define APCI035_TW2                               32
-#define APCI035_TW3                               64
-#define APCI035_TW4                               96
-
-#define APCI035_AI_OFFSET                        0
-#define APCI035_TEMP                             128
-#define APCI035_ALR_SEQ                          4
-#define APCI035_START_STOP_INDEX                 8
-#define APCI035_ALR_START_STOP                   12
-#define APCI035_ALR_IRQ                          16
-#define APCI035_EOS                              20
-#define APCI035_CHAN_NO                          24
-#define APCI035_CHAN_VAL                         28
-#define APCI035_CONV_TIME_TIME_BASE	36
-#define APCI035_RELOAD_CONV_TIME_VAL	32
-#define APCI035_DELAY_TIME_TIME_BASE	44
-#define APCI035_RELOAD_DELAY_TIME_VAL	40
-#define ENABLE_EXT_TRIG			1
-#define ENABLE_EXT_GATE			2
-#define ENABLE_EXT_TRIG_GATE		3
-
-#define ANALOG_INPUT			0
-#define TEMPERATURE			1
-#define RESISTANCE			2
-
-#define ADDIDATA_GREATER_THAN_TEST	0
-#define ADDIDATA_LESS_THAN_TEST		1
-
-#define APCI035_MAXVOLT                         2.5
-
-#define ADDIDATA_UNIPOLAR                        1
-#define ADDIDATA_BIPOLAR                         2
-
-/* ADDIDATA Enable Disable */
-#define ADDIDATA_ENABLE				1
-#define ADDIDATA_DISABLE			0
-
-/* Hardware Layer functions for Apci035 */
-
-/* TIMER */
-/* timer value is passed as u seconds */
-int i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data);
-int i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev,
-					  struct comedi_subdevice *s,
-					  struct comedi_insn *insn, unsigned int *data);
-int i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data);
-
-/* Temperature Related Defines (Analog Input Subdevice) */
-
-int i_APCI035_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data);
-int i_APCI035_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data);
-
-/* Interrupt */
-static void v_APCI035_Interrupt(int irq, void *d);
-
-/* Reset functions */
-int i_APCI035_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
deleted file mode 100644
index bab7b61..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/**
-@verbatim
-
-Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
-
-	ADDI-DATA GmbH
-	Dieselstrasse 3
-	D-77833 Ottersweier
-	Tel: +19(0)7223/9493-0
-	Fax: +49(0)7223/9493-92
-	http://www.addi-data.com
-	info@addi-data.com
-
-This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
-@endverbatim
-*/
-/*
-
-  +-----------------------------------------------------------------------+
-  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
-  +-----------------------------------------------------------------------+
-  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
-  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
-  +-------------------------------+---------------------------------------+
-  | Project     : APCI-1032       | Compiler   : GCC                      |
-  | Module name : hwdrv_apci1032.c| Version    : 2.96                     |
-  +-------------------------------+---------------------------------------+
-  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
-  +-------------------------------+---------------------------------------+
-  | Description :   Hardware Layer Access For APCI-1032                   |
-  +-----------------------------------------------------------------------+
-  |                             UPDATES                                   |
-  +----------+-----------+------------------------------------------------+
-  |   Date   |   Author  |          Description of updates                |
-  +----------+-----------+------------------------------------------------+
-  |          |           |                                                |
-  |          |           |                                                |
-  |          |           |                                                |
-  +----------+-----------+------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
-#include "hwdrv_apci1032.h"
-#include <linux/delay.h>
-
-static unsigned int ui_InterruptStatus;
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1032_ConfigDigitalInput                      |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Configures the digital input Subdevice                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev : Driver handle                     |
-|                     unsigned int *data         : Data Pointer contains         |
-|                                          configuration parameters as below |
-|                                                                            |
-|			  data[0]            : 1 Enable  Digital Input Interrupt |
-|								   0 Disable Digital Input Interrupt |
-|			  data[1]            : 0 ADDIDATA Interrupt OR LOGIC	 |
-|								 : 1 ADDIDATA Interrupt AND LOGIC    |
-|			  data[2]			 : Interrupt mask for the mode 1	 |
-|			  data[3]			 : Interrupt mask for the mode 2	 |
-|																	 |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int ui_TmpValue;
-
-	unsigned int ul_Command1 = 0;
-	unsigned int ul_Command2 = 0;
-	devpriv->tsk_Current = current;
-
-  /*******************************/
-	/* Set the digital input logic */
-  /*******************************/
-	if (data[0] == ADDIDATA_ENABLE) {
-		ul_Command1 = ul_Command1 | data[2];
-		ul_Command2 = ul_Command2 | data[3];
-		outl(ul_Command1,
-			devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1);
-		outl(ul_Command2,
-			devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2);
-		if (data[1] == ADDIDATA_OR) {
-			outl(0x4, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
-			ui_TmpValue =
-				inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
-		}		/* if (data[1] == ADDIDATA_OR) */
-		else
-			outl(0x6, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
-				/* else if(data[1] == ADDIDATA_OR) */
-	}			/*  if( data[0] == ADDIDATA_ENABLE) */
-	else {
-		ul_Command1 = ul_Command1 & 0xFFFF0000;
-		ul_Command2 = ul_Command2 & 0xFFFF0000;
-		outl(ul_Command1,
-			devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1);
-		outl(ul_Command2,
-			devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2);
-		outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
-	}			/* else if  ( data[0] == ADDIDATA_ENABLE) */
-
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1032_Read1DigitalInput                       |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Return the status of the digital input                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|		              unsigned int ui_Channel : Channel number to read       |
-|                     unsigned int *data          : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI1032_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int ui_TmpValue = 0;
-	unsigned int ui_Channel;
-	ui_Channel = CR_CHAN(insn->chanspec);
-	if (ui_Channel <= 31) {
-		ui_TmpValue = (unsigned int) inl(devpriv->iobase + APCI1032_DIGITAL_IP);
-/*
-* since only 1 channel reqd to bring it to last bit it is rotated 8
-* +(chan - 1) times then ANDed with 1 for last bit.
-*/
-		*data = (ui_TmpValue >> ui_Channel) & 0x1;
-	}			/* if(ui_Channel >= 0 && ui_Channel <=31) */
-	else {
-		/* comedi_error(dev," \n chan spec wrong\n"); */
-		return -EINVAL;	/*  "sorry channel spec wrong " */
-	}			/* else if(ui_Channel >= 0 && ui_Channel <=31) */
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1032_ReadMoreDigitalInput                    |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                     struct comedi_insn *insn,unsigned int *data)                      |
-+----------------------------------------------------------------------------+
-| Task              : Return the status of the Requested digital inputs      |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     unsigned int ui_NoOfChannels    : No Of Channels To be Read    |
-|                      unsigned int *data             : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int ui_PortValue = data[0];
-	unsigned int ui_Mask = 0;
-	unsigned int ui_NoOfChannels;
-
-	ui_NoOfChannels = CR_CHAN(insn->chanspec);
-	if (data[1] == 0) {
-		*data = (unsigned int) inl(devpriv->iobase + APCI1032_DIGITAL_IP);
-		switch (ui_NoOfChannels) {
-		case 2:
-			ui_Mask = 3;
-			*data = (*data >> (2 * ui_PortValue)) & ui_Mask;
-			break;
-		case 4:
-			ui_Mask = 15;
-			*data = (*data >> (4 * ui_PortValue)) & ui_Mask;
-			break;
-		case 8:
-			ui_Mask = 255;
-			*data = (*data >> (8 * ui_PortValue)) & ui_Mask;
-			break;
-		case 16:
-			ui_Mask = 65535;
-			*data = (*data >> (16 * ui_PortValue)) & ui_Mask;
-			break;
-		case 31:
-			break;
-		default:
-			/* comedi_error(dev," \nchan spec wrong\n"); */
-			return -EINVAL;	/*  "sorry channel spec wrong " */
-			break;
-		}		/* switch(ui_NoOfChannels) */
-	}			/* if(data[1]==0) */
-	else {
-		if (data[1] == 1)
-			*data = ui_InterruptStatus;
-				/* if(data[1]==1) */
-	}			/* else if(data[1]==0) */
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : static void v_APCI1032_Interrupt					     |
-|					  (int irq , void *d)      |
-+----------------------------------------------------------------------------+
-| Task              : Interrupt handler for the interruptible digital inputs |
-+----------------------------------------------------------------------------+
-| Input Parameters  : int irq                 : irq number                   |
-|                     void *d                 : void pointer                 |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--						     |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                     |
-+----------------------------------------------------------------------------+
-*/
-static void v_APCI1032_Interrupt(int irq, void *d)
-{
-	struct comedi_device *dev = d;
-
-	unsigned int ui_Temp;
-	/* disable the interrupt */
-	ui_Temp = inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
-	outl(ui_Temp & APCI1032_DIGITAL_IP_INTERRUPT_DISABLE,
-		devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
-	ui_InterruptStatus =
-		inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS);
-	ui_InterruptStatus = ui_InterruptStatus & 0X0000FFFF;
-	send_sig(SIGIO, devpriv->tsk_Current, 0);	/*  send signal to the sample */
-	outl(ui_Temp, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);	/* enable the interrupt */
-	return;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1032_Reset(struct comedi_device *dev)               |                                                       |
-+----------------------------------------------------------------------------+
-| Task              :resets all the registers                                |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      :                                                        |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI1032_Reset(struct comedi_device *dev)
-{
-	outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);	/* disable the interrupts */
-	inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS);	/* Reset the interrupt status register */
-	outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1);	/* Disable the and/or interrupt */
-	outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2);
-	return 0;
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
deleted file mode 100644
index 7114acb..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/*********      Definitions for APCI-1032 card  *****/
-
-#define APCI1032_BOARD_VENDOR_ID 0x15B8
-#define APCI1032_ADDRESS_RANGE  20
-/* DIGITAL INPUT DEFINE */
-
-#define APCI1032_DIGITAL_IP                     0
-#define APCI1032_DIGITAL_IP_INTERRUPT_MODE1     4
-#define APCI1032_DIGITAL_IP_INTERRUPT_MODE2     8
-#define APCI1032_DIGITAL_IP_IRQ                 16
-
-/* Digital Input IRQ Function Selection */
-#define ADDIDATA_OR                  0
-#define ADDIDATA_AND                 1
-
-/* Digital Input Interrupt Status */
-#define APCI1032_DIGITAL_IP_INTERRUPT_STATUS    12
-
-/* Digital Input Interrupt Enable Disable. */
-#define APCI1032_DIGITAL_IP_INTERRUPT_ENABLE    0x4
-#define APCI1032_DIGITAL_IP_INTERRUPT_DISABLE   0xFFFFFFFB
-
-/* ADDIDATA Enable Disable */
-
-#define ADDIDATA_ENABLE                            1
-#define ADDIDATA_DISABLE                           0
-
-/* Hardware Layer  functions for Apci1032 */
-
-/*
-* DI for di read
-*/
-
-int i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI1032_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				    struct comedi_insn *insn, unsigned int *data);
-
-/* Interrupt functions..... */
-
-static void v_APCI1032_Interrupt(int irq, void *d);
-/* Reset */
-int i_APCI1032_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
index 62f421a..24c4c98 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
@@ -45,7 +45,105 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   |          |           |                                                |
   +----------+-----------+------------------------------------------------+
 */
-#include "hwdrv_apci1500.h"
+
+/*********      Definitions for APCI-1500 card  *****/
+
+/* Card Specific information */
+#define APCI1500_ADDRESS_RANGE		4
+
+/* DIGITAL INPUT-OUTPUT DEFINE */
+
+#define APCI1500_DIGITAL_OP		2
+#define APCI1500_DIGITAL_IP		0
+#define APCI1500_AND			2
+#define APCI1500_OR			4
+#define APCI1500_OR_PRIORITY		6
+#define APCI1500_CLK_SELECT		0
+#define COUNTER1			0
+#define COUNTER2			1
+#define COUNTER3			2
+#define APCI1500_COUNTER		0x20
+#define APCI1500_TIMER			0
+#define APCI1500_WATCHDOG		0
+#define APCI1500_SINGLE			0
+#define APCI1500_CONTINUOUS		0x80
+#define APCI1500_DISABLE		0
+#define APCI1500_ENABLE			1
+#define APCI1500_SOFTWARE_TRIGGER	0x4
+#define APCI1500_HARDWARE_TRIGGER	0x10
+#define APCI1500_SOFTWARE_GATE		0
+#define APCI1500_HARDWARE_GATE		0x8
+#define START				0
+#define STOP				1
+#define TRIGGER				2
+
+/*
+ * Zillog I/O enumeration
+ */
+enum {
+	APCI1500_Z8536_PORT_C,
+	APCI1500_Z8536_PORT_B,
+	APCI1500_Z8536_PORT_A,
+	APCI1500_Z8536_CONTROL_REGISTER
+};
+
+/*
+ * Z8536 CIO Internal Address
+ */
+enum {
+	APCI1500_RW_MASTER_INTERRUPT_CONTROL,
+	APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
+	APCI1500_RW_PORT_A_INTERRUPT_CONTROL,
+	APCI1500_RW_PORT_B_INTERRUPT_CONTROL,
+	APCI1500_RW_TIMER_COUNTER_INTERRUPT_VECTOR,
+	APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY,
+	APCI1500_RW_PORT_C_DATA_DIRECTION,
+	APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL,
+
+	APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
+	APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
+	APCI1500_RW_CPT_TMR1_CMD_STATUS,
+	APCI1500_RW_CPT_TMR2_CMD_STATUS,
+	APCI1500_RW_CPT_TMR3_CMD_STATUS,
+	APCI1500_RW_PORT_A_DATA,
+	APCI1500_RW_PORT_B_DATA,
+	APCI1500_RW_PORT_C_DATA,
+
+	APCI1500_R_CPT_TMR1_VALUE_HIGH,
+	APCI1500_R_CPT_TMR1_VALUE_LOW,
+	APCI1500_R_CPT_TMR2_VALUE_HIGH,
+	APCI1500_R_CPT_TMR2_VALUE_LOW,
+	APCI1500_R_CPT_TMR3_VALUE_HIGH,
+	APCI1500_R_CPT_TMR3_VALUE_LOW,
+	APCI1500_RW_CPT_TMR1_TIME_CST_HIGH,
+	APCI1500_RW_CPT_TMR1_TIME_CST_LOW,
+	APCI1500_RW_CPT_TMR2_TIME_CST_HIGH,
+	APCI1500_RW_CPT_TMR2_TIME_CST_LOW,
+	APCI1500_RW_CPT_TMR3_TIME_CST_HIGH,
+	APCI1500_RW_CPT_TMR3_TIME_CST_LOW,
+	APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION,
+	APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION,
+	APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION,
+	APCI1500_R_CURRENT_VECTOR,
+
+	APCI1500_RW_PORT_A_SPECIFICATION,
+	APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION,
+	APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY,
+	APCI1500_RW_PORT_A_DATA_DIRECTION,
+	APCI1500_RW_PORT_A_SPECIAL_IO_CONTROL,
+	APCI1500_RW_PORT_A_PATTERN_POLARITY,
+	APCI1500_RW_PORT_A_PATTERN_TRANSITION,
+	APCI1500_RW_PORT_A_PATTERN_MASK,
+
+	APCI1500_RW_PORT_B_SPECIFICATION,
+	APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION,
+	APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY,
+	APCI1500_RW_PORT_B_DATA_DIRECTION,
+	APCI1500_RW_PORT_B_SPECIAL_IO_CONTROL,
+	APCI1500_RW_PORT_B_PATTERN_POLARITY,
+	APCI1500_RW_PORT_B_PATTERN_TRANSITION,
+	APCI1500_RW_PORT_B_PATTERN_MASK
+};
 
 static int i_TimerCounter1Init = 0;
 static int i_TimerCounter2Init = 0;
@@ -141,6 +239,7 @@ static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
 					      struct comedi_insn *insn,
 					      unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_PatternPolarity = 0, i_PatternTransition = 0, i_PatternMask = 0;
 	int i_MaxChannel = 0, i_Count = 0, i_EventMask = 0;
 	int i_PatternTransitionCount = 0, i_RegValue;
@@ -525,8 +624,10 @@ static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
 					  struct comedi_insn *insn,
 					  unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_Event1InterruptStatus = 0, i_Event2InterruptStatus =
 		0, i_RegValue;
+
 	switch (data[0]) {
 	case START:
 	      /*************************/
@@ -792,7 +893,9 @@ static int i_APCI1500_Initialisation(struct comedi_device *dev,
 				     struct comedi_insn *insn,
 				     unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_DummyRead = 0;
+
     /******************/
 	/* Software reset */
     /******************/
@@ -939,82 +1042,15 @@ static int i_APCI1500_Initialisation(struct comedi_device *dev,
 	return insn->n;
 }
 
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1500_ReadMoreDigitalInput                    |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                     struct comedi_insn *insn,unsigned int *data)                      |
-+----------------------------------------------------------------------------+
-| Task              : Return the status of the Requested digital inputs      |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     unsigned int ui_NoOfChannels    : No Of Channels To be Read    |
-|                      unsigned int *data             : Data Pointer
-|                      data[0]                 : 0 Read a single channel
-|                                                1 read a port value
-|                      data[1]                 : port value
-+----------------------------------------------------------------------------+
-| Output Parameters :	--	data[0]    :The read status value
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI1500_ReadMoreDigitalInput(struct comedi_device *dev,
-					   struct comedi_subdevice *s,
-					   struct comedi_insn *insn,
-					   unsigned int *data)
+static int apci1500_di_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	unsigned int ui_PortValue = data[1];
-	unsigned int ui_Mask = 0;
-	unsigned int ui_Channel;
-	unsigned int ui_TmpValue = 0;
-	ui_Channel = CR_CHAN(insn->chanspec);
+	struct addi_private *devpriv = dev->private;
 
-	switch (data[0]) {
-	case 0:
-		if (ui_Channel <= 15) {
-			ui_TmpValue =
-				(unsigned int) inw(devpriv->i_IobaseAddon +
-				APCI1500_DIGITAL_IP);
-			*data = (ui_TmpValue >> ui_Channel) & 0x1;
-		}		/* if(ui_Channel >= 0 && ui_Channel <=15) */
-		else {
-			printk("\nThe channel specification are in error\n");
-			return -EINVAL;	/*  "sorry channel spec wrong " */
-		}		/* else if(ui_Channel >= 0 && ui_Channel <=15) */
-		break;
-	case 1:
+	data[1] = inw(devpriv->i_IobaseAddon + APCI1500_DIGITAL_IP);
 
-		*data = (unsigned int) inw(devpriv->i_IobaseAddon +
-			APCI1500_DIGITAL_IP);
-		switch (ui_Channel) {
-		case 2:
-			ui_Mask = 3;
-			*data = (*data >> (2 * ui_PortValue)) & ui_Mask;
-			break;
-		case 4:
-			ui_Mask = 15;
-			*data = (*data >> (4 * ui_PortValue)) & ui_Mask;
-			break;
-		case 8:
-			ui_Mask = 255;
-			*data = (*data >> (8 * ui_PortValue)) & ui_Mask;
-			break;
-		case 15:
-			break;
-
-		default:
-			printk("\nSpecified channel cannot be read \n");
-			return -EINVAL;	/*  "sorry channel spec wrong " */
-			break;
-		}		/* switch(ui_Channel) */
-		break;
-	default:
-		printk("\nThe specified functionality does not exist\n");
-		return -EINVAL;
-	}			/* switch(data[0]) */
 	return insn->n;
 }
 
@@ -1051,6 +1087,8 @@ static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device *de
 							struct comedi_insn *insn,
 							unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
+
 	devpriv->b_OutputMemoryStatus = data[0];
 	return insn->n;
 }
@@ -1079,9 +1117,9 @@ static int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev,
 					 struct comedi_insn *insn,
 					 unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	static unsigned int ui_Temp = 0;
 	unsigned int ui_Temp1;
-
 	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
 
 	if (!devpriv->b_OutputMemoryStatus) {
@@ -1274,6 +1312,7 @@ static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
 						 struct comedi_insn *insn,
 						 unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_TimerCounterMode, i_MasterConfiguration;
 
 	devpriv->tsk_Current = current;
@@ -1875,6 +1914,7 @@ static int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device
 							   struct comedi_insn *insn,
 							   unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_CommandAndStatusValue;
 
 	switch (data[0]) {
@@ -2198,7 +2238,9 @@ static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
 					       struct comedi_insn *insn,
 					       unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_CommandAndStatusValue;
+
 	switch (data[0]) {
 	case COUNTER1:
 		/* Read counter/timer1 */
@@ -2421,9 +2463,11 @@ static int i_APCI1500_ConfigureInterrupt(struct comedi_device *dev,
 					 struct comedi_insn *insn,
 					 unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_Status;
 	int i_RegValue;
 	int i_Constant;
+
 	devpriv->tsk_Current = current;
 	outl(0x0, devpriv->i_IobaseAmcc + 0x38);
 	if (data[0] == 1) {
@@ -2597,6 +2641,7 @@ static void v_APCI1500_Interrupt(int irq, void *d)
 {
 
 	struct comedi_device *dev = d;
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_InterruptStatus = 0;
 	int i_RegValue = 0;
 	i_InterruptMask = 0;
@@ -2840,7 +2885,9 @@ static void v_APCI1500_Interrupt(int irq, void *d)
 */
 static int i_APCI1500_Reset(struct comedi_device *dev)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_DummyRead = 0;
+
 	i_TimerCounter1Init = 0;
 	i_TimerCounter2Init = 0;
 	i_WatchdogCounter3Init = 0;
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
deleted file mode 100644
index 647f9eb..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/*********      Definitions for APCI-1500 card  *****/
-
-/* Card Specific information */
-#define APCI1500_BOARD_VENDOR_ID           0x10e8
-#define APCI1500_ADDRESS_RANGE              4
-
-/* DIGITAL INPUT-OUTPUT DEFINE */
-
-#define  APCI1500_DIGITAL_OP                 	2
-#define  APCI1500_DIGITAL_IP                    0
-#define  APCI1500_AND               		    2
-#define  APCI1500_OR                		    4
-#define  APCI1500_OR_PRIORITY       		    6
-#define  APCI1500_CLK_SELECT                    0
-#define  COUNTER1                               0
-#define  COUNTER2                               1
-#define  COUNTER3                               2
-#define  APCI1500_COUNTER                		0x20
-#define  APCI1500_TIMER                  		0
-#define  APCI1500_WATCHDOG          		    0
-#define  APCI1500_SINGLE            		    0
-#define  APCI1500_CONTINUOUS        		    0x80
-#define  APCI1500_DISABLE                		0
-#define  APCI1500_ENABLE                		1
-#define  APCI1500_SOFTWARE_TRIGGER  		    0x4
-#define  APCI1500_HARDWARE_TRIGGER  		    0x10
-#define  APCI1500_SOFTWARE_GATE     		    0
-#define  APCI1500_HARDWARE_GATE     		    0x8
-#define  START                       		    0
-#define  STOP                       		    1
-#define  TRIGGER                       		    2
-
-/*
- * Zillog I/O enumeration
- */
-enum {
-	APCI1500_Z8536_PORT_C,
-	APCI1500_Z8536_PORT_B,
-	APCI1500_Z8536_PORT_A,
-	APCI1500_Z8536_CONTROL_REGISTER
-};
-
-/*
- * Z8536 CIO Internal Address
- */
-enum {
-	APCI1500_RW_MASTER_INTERRUPT_CONTROL,
-	APCI1500_RW_MASTER_CONFIGURATION_CONTROL,
-	APCI1500_RW_PORT_A_INTERRUPT_CONTROL,
-	APCI1500_RW_PORT_B_INTERRUPT_CONTROL,
-	APCI1500_RW_TIMER_COUNTER_INTERRUPT_VECTOR,
-	APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY,
-	APCI1500_RW_PORT_C_DATA_DIRECTION,
-	APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL,
-
-	APCI1500_RW_PORT_A_COMMAND_AND_STATUS,
-	APCI1500_RW_PORT_B_COMMAND_AND_STATUS,
-	APCI1500_RW_CPT_TMR1_CMD_STATUS,
-	APCI1500_RW_CPT_TMR2_CMD_STATUS,
-	APCI1500_RW_CPT_TMR3_CMD_STATUS,
-	APCI1500_RW_PORT_A_DATA,
-	APCI1500_RW_PORT_B_DATA,
-	APCI1500_RW_PORT_C_DATA,
-
-	APCI1500_R_CPT_TMR1_VALUE_HIGH,
-	APCI1500_R_CPT_TMR1_VALUE_LOW,
-	APCI1500_R_CPT_TMR2_VALUE_HIGH,
-	APCI1500_R_CPT_TMR2_VALUE_LOW,
-	APCI1500_R_CPT_TMR3_VALUE_HIGH,
-	APCI1500_R_CPT_TMR3_VALUE_LOW,
-	APCI1500_RW_CPT_TMR1_TIME_CST_HIGH,
-	APCI1500_RW_CPT_TMR1_TIME_CST_LOW,
-	APCI1500_RW_CPT_TMR2_TIME_CST_HIGH,
-	APCI1500_RW_CPT_TMR2_TIME_CST_LOW,
-	APCI1500_RW_CPT_TMR3_TIME_CST_HIGH,
-	APCI1500_RW_CPT_TMR3_TIME_CST_LOW,
-	APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION,
-	APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION,
-	APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION,
-	APCI1500_R_CURRENT_VECTOR,
-
-	APCI1500_RW_PORT_A_SPECIFICATION,
-	APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION,
-	APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY,
-	APCI1500_RW_PORT_A_DATA_DIRECTION,
-	APCI1500_RW_PORT_A_SPECIAL_IO_CONTROL,
-	APCI1500_RW_PORT_A_PATTERN_POLARITY,
-	APCI1500_RW_PORT_A_PATTERN_TRANSITION,
-	APCI1500_RW_PORT_A_PATTERN_MASK,
-
-	APCI1500_RW_PORT_B_SPECIFICATION,
-	APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION,
-	APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY,
-	APCI1500_RW_PORT_B_DATA_DIRECTION,
-	APCI1500_RW_PORT_B_SPECIAL_IO_CONTROL,
-	APCI1500_RW_PORT_B_PATTERN_POLARITY,
-	APCI1500_RW_PORT_B_PATTERN_TRANSITION,
-	APCI1500_RW_PORT_B_PATTERN_MASK
-};
-
- /*----------DIGITAL INPUT----------------*/
-static int i_APCI1500_Initialisation(struct comedi_device *dev, struct comedi_subdevice *s,
-				     struct comedi_insn *insn, unsigned int *data);
-static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
-					      struct comedi_subdevice *s,
-					      struct comedi_insn *insn,
-					      unsigned int *data);
-
-static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
-					  struct comedi_subdevice *s,
-					  struct comedi_insn *insn, unsigned int *data);
-static int i_APCI1500_ReadMoreDigitalInput(struct comedi_device *dev,
-					   struct comedi_subdevice *s,
-					   struct comedi_insn *insn, unsigned int *data);
-
-/*----------	DIGITAL OUTPUT------------*/
-static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device *dev,
-							struct comedi_subdevice *s,
-							struct comedi_insn *insn,
-							unsigned int *data);
-static int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev,
-					 struct comedi_subdevice *s,
-					 struct comedi_insn *insn, unsigned int *data);
-
-/*----------TIMER----------------*/
-static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
-						 struct comedi_subdevice *s,
-						 struct comedi_insn *insn,
-						 unsigned int *data);
-static int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device *dev,
-							   struct comedi_subdevice *s,
-							   struct comedi_insn *insn,
-							   unsigned int *data);
-static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
-					       struct comedi_subdevice *s,
-					       struct comedi_insn *insn,
-					       unsigned int *data);
-static int i_APCI1500_ReadInterruptMask(struct comedi_device *dev,
-					struct comedi_subdevice *s,
-					struct comedi_insn *insn, unsigned int *data);
-
-/*----------INTERRUPT HANDLER------*/
-static void v_APCI1500_Interrupt(int irq, void *d);
-static int i_APCI1500_ConfigureInterrupt(struct comedi_device *dev,
-					 struct comedi_subdevice *s,
-					 struct comedi_insn *insn, unsigned int *data);
-/*----------RESET---------------*/
-static int i_APCI1500_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
deleted file mode 100644
index 8a584a0..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+++ /dev/null
@@ -1,542 +0,0 @@
-/**
-@verbatim
-
-Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
-
-	ADDI-DATA GmbH
-	Dieselstrasse 3
-	D-77833 Ottersweier
-	Tel: +19(0)7223/9493-0
-	Fax: +49(0)7223/9493-92
-	http://www.addi-data.com
-	info@addi-data.com
-
-This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
-@endverbatim
-*/
-/*
-
-  +-----------------------------------------------------------------------+
-  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
-  +-----------------------------------------------------------------------+
-  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
-  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
-  +-------------------------------+---------------------------------------+
-  | Project     : APCI-1516       | Compiler   : GCC                      |
-  | Module name : hwdrv_apci1516.c| Version    : 2.96                     |
-  +-------------------------------+---------------------------------------+
-  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
-  +-------------------------------+---------------------------------------+
-  | Description :   Hardware Layer Access For APCI-1516                   |
-  +-----------------------------------------------------------------------+
-  |                             UPDATES                                   |
-  +----------+-----------+------------------------------------------------+
-  |   Date   |   Author  |          Description of updates                |
-  +----------+-----------+------------------------------------------------+
-  |          |           |                                                |
-  |          |           |                                                |
-  |          |           |                                                |
-  +----------+-----------+------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
-#include "hwdrv_apci1516.h"
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1516_Read1DigitalInput                       |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Return the status of the digital input                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|		       struct comedi_subdevice *s,   :pointer to subdevice structure
-|                       struct comedi_insn *insn      :pointer to insn structure     |
-|                     unsigned int *data          : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int ui_TmpValue = 0;
-	unsigned int ui_Channel;
-	ui_Channel = CR_CHAN(insn->chanspec);
-	if (ui_Channel <= 7) {
-		ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI1516_DIGITAL_IP);
-		/*   since only 1 channel reqd  to bring it to last bit it is rotated */
-		/*   8 +(chan - 1) times then ANDed with 1 for last bit. */
-		*data = (ui_TmpValue >> ui_Channel) & 0x1;
-	}			/* if(ui_Channel >= 0 && ui_Channel <=7) */
-	else {
-		/* comedi_error(dev," \n chan spec wrong\n"); */
-		return -EINVAL;	/*  "sorry channel spec wrong " */
-	}			/* else if(ui_Channel >= 0 && ui_Channel <=7) */
-
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1516_ReadMoreDigitalInput                    |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                     struct comedi_insn *insn,unsigned int *data)                      |
-+----------------------------------------------------------------------------+
-| Task              : Return the status of the Requested digital inputs      |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                      struct comedi_subdevice *s,   :pointer to subdevice structure
-|                       struct comedi_insn *insn      :pointer to insn structure     |
-|                      unsigned int *data         : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-
-	unsigned int ui_PortValue = data[0];
-	unsigned int ui_Mask = 0;
-	unsigned int ui_NoOfChannels;
-
-	ui_NoOfChannels = CR_CHAN(insn->chanspec);
-
-	*data = (unsigned int) inw(devpriv->iobase + APCI1516_DIGITAL_IP);
-	switch (ui_NoOfChannels) {
-	case 2:
-		ui_Mask = 3;
-		*data = (*data >> (2 * ui_PortValue)) & ui_Mask;
-		break;
-	case 4:
-		ui_Mask = 15;
-		*data = (*data >> (4 * ui_PortValue)) & ui_Mask;
-		break;
-	case 7:
-		break;
-
-	default:
-		printk("\nWrong parameters\n");
-		return -EINVAL;	/*  "sorry channel spec wrong " */
-		break;
-	}			/* switch(ui_NoOfChannels) */
-
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1516_ConfigDigitalOutput (struct comedi_device *dev,
-|                    struct comedi_subdevice *s struct comedi_insn *insn,unsigned int *data)    |
-|				                                                     |
-+----------------------------------------------------------------------------+
-| Task              : Configures The Digital Output Subdevice.               |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev : Driver handle                     |
-|                     unsigned int *data         : Data Pointer contains         |
-|                                          configuration parameters as below |
-|                      struct comedi_subdevice *s,   :pointer to subdevice structure
-|                      struct comedi_insn *insn      :pointer to insn structure                                                           |
-|					  data[0]  :1:Memory on                          |
-|					            0:Memory off                         |
-|										                             |
-|																	 |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI1516_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	devpriv->b_OutputMemoryStatus = data[0];
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1516_WriteDigitalOutput                      |
-|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
-|                     unsigned int *data)                                         |
-+----------------------------------------------------------------------------+
-| Task              : Writes port value  To the selected port                |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     struct comedi_subdevice *s,   :pointer to subdevice structure
-|                     struct comedi_insn *insn      :pointer to insn structure      |
-|                    unsigned int *data           : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int ui_Temp, ui_Temp1;
-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
-
-	printk("EL311003 : @=%x\n", devpriv->iobase + APCI1516_DIGITAL_OP);
-
-	if (devpriv->b_OutputMemoryStatus) {
-		ui_Temp = inw(devpriv->iobase + APCI1516_DIGITAL_OP);
-
-	}			/* if(devpriv->b_OutputMemoryStatus ) */
-	else {
-		ui_Temp = 0;
-	}			/* if(devpriv->b_OutputMemoryStatus ) */
-	if (data[3] == 0) {
-		if (data[1] == 0) {
-			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
-			outw(data[0], devpriv->iobase + APCI1516_DIGITAL_OP);
-
-			printk("EL311003 : d=%d @=%x\n", data[0],
-				devpriv->iobase + APCI1516_DIGITAL_OP);
-
-		}		/* if(data[1]==0) */
-		else {
-			if (data[1] == 1) {
-				switch (ui_NoOfChannel) {
-
-				case 2:
-					data[0] =
-						(data[0] << (2 *
-							data[2])) | ui_Temp;
-					break;
-
-				case 4:
-					data[0] =
-						(data[0] << (4 *
-							data[2])) | ui_Temp;
-					break;
-
-				case 7:
-					data[0] = data[0] | ui_Temp;
-					break;
-
-				default:
-					comedi_error(dev, " chan spec wrong");
-					return -EINVAL;	/*  "sorry channel spec wrong " */
-
-				}	/* switch(ui_NoOfChannels) */
-
-				outw(data[0],
-					devpriv->iobase + APCI1516_DIGITAL_OP);
-
-				printk("EL311003 : d=%d @=%x\n", data[0],
-					devpriv->iobase + APCI1516_DIGITAL_OP);
-			}	/*  if(data[1]==1) */
-			else {
-				printk("\nSpecified channel not supported\n");
-			}	/* else if(data[1]==1) */
-		}		/* elseif(data[1]==0) */
-	}			/* if(data[3]==0) */
-	else {
-		if (data[3] == 1) {
-			if (data[1] == 0) {
-				data[0] = ~data[0] & 0x1;
-				ui_Temp1 = 1;
-				ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
-				ui_Temp = ui_Temp | ui_Temp1;
-				data[0] = (data[0] << ui_NoOfChannel) ^ 0xff;
-				data[0] = data[0] & ui_Temp;
-				outw(data[0],
-					devpriv->iobase + APCI1516_DIGITAL_OP);
-
-				printk("EL311003 : d=%d @=%x\n", data[0],
-					devpriv->iobase + APCI1516_DIGITAL_OP);
-
-			}	/* if(data[1]==0) */
-			else {
-				if (data[1] == 1) {
-					switch (ui_NoOfChannel) {
-
-					case 2:
-						data[0] = ~data[0] & 0x3;
-						ui_Temp1 = 3;
-						ui_Temp1 =
-							ui_Temp1 << 2 * data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (2 *
-									data
-									[2])) ^
-							0xff) & ui_Temp;
-						break;
-
-					case 4:
-						data[0] = ~data[0] & 0xf;
-						ui_Temp1 = 15;
-						ui_Temp1 =
-							ui_Temp1 << 4 * data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (4 *
-									data
-									[2])) ^
-							0xff) & ui_Temp;
-						break;
-
-					case 7:
-						break;
-
-					default:
-						comedi_error(dev,
-							" chan spec wrong");
-						return -EINVAL;	/*  "sorry channel spec wrong " */
-
-					}	/* switch(ui_NoOfChannels) */
-
-					outw(data[0],
-						devpriv->iobase +
-						APCI1516_DIGITAL_OP);
-
-					printk("EL311003 : d=%d @=%x\n",
-						data[0],
-						devpriv->iobase +
-						APCI1516_DIGITAL_OP);
-				}	/*  if(data[1]==1) */
-				else {
-					printk("\nSpecified channel not supported\n");
-				}	/* else if(data[1]==1) */
-			}	/* elseif(data[1]==0) */
-		}		/* if(data[3]==1); */
-		else {
-			printk("\nSpecified functionality does not exist\n");
-			return -EINVAL;
-		}		/* if else data[3]==1) */
-	}			/* if else data[3]==0) */
-	return (insn->n);
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1516_ReadDigitalOutput                       |
-|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
-|                    unsigned int *data) 	                                     |
-+----------------------------------------------------------------------------+
-| Task              : Read  value  of the selected channel or port           |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     struct comedi_subdevice *s,   :pointer to subdevice structure
-|                     struct comedi_insn *insn      :pointer to insn structure      |
-|                     unsigned int *data          : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-
-	unsigned int ui_Temp;
-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
-	ui_Temp = data[0];
-	*data = inw(devpriv->iobase + APCI1516_DIGITAL_OP_RW);
-	if (ui_Temp == 0) {
-		*data = (*data >> ui_NoOfChannel) & 0x1;
-	}			/* if(ui_Temp==0) */
-	else {
-		if (ui_Temp == 1) {
-			switch (ui_NoOfChannel) {
-
-			case 2:
-				*data = (*data >> (2 * data[1])) & 3;
-				break;
-
-			case 4:
-				*data = (*data >> (4 * data[1])) & 15;
-				break;
-
-			case 7:
-				break;
-
-			default:
-				comedi_error(dev, " chan spec wrong");
-				return -EINVAL;	/*  "sorry channel spec wrong " */
-
-			}	/* switch(ui_NoOfChannels) */
-		}		/* if(ui_Temp==1) */
-		else {
-			printk("\nSpecified channel not supported \n");
-		}		/* elseif(ui_Temp==1) */
-	}			/* elseif(ui_Temp==0) */
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1516_ConfigWatchdog(struct comedi_device *dev,
-|                      struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)  |
-|				                                                     |
-+----------------------------------------------------------------------------+
-| Task              : Configures The Watchdog                                |
-+----------------------------------------------------------------------------+
-| Input Parameters  :   struct comedi_device *dev      : Driver handle              |
-|                     struct comedi_subdevice *s,   :pointer to subdevice structure
-|                      struct comedi_insn *insn      :pointer to insn structure      |
-|                     unsigned int *data          : Data Pointer to read status                                                     |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI1516_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	if (data[0] == 0) {
-		/* Disable the watchdog */
-		outw(0x0,
-			devpriv->i_IobaseAddon +
-			APCI1516_WATCHDOG_ENABLEDISABLE);
-		/* Loading the Reload value */
-		outw(data[1],
-			devpriv->i_IobaseAddon +
-			APCI1516_WATCHDOG_RELOAD_VALUE);
-		data[1] = data[1] >> 16;
-		outw(data[1],
-			devpriv->i_IobaseAddon +
-			APCI1516_WATCHDOG_RELOAD_VALUE + 2);
-	}			/* if(data[0]==0) */
-	else {
-		printk("\nThe input parameters are wrong\n");
-		return -EINVAL;
-	}			/* elseif(data[0]==0) */
-
-	return insn->n;
-}
-
- /*
-    +----------------------------------------------------------------------------+
-    | Function   Name   : int i_APCI1516_StartStopWriteWatchdog                  |
-    |                           (struct comedi_device *dev,struct comedi_subdevice *s,
-    struct comedi_insn *insn,unsigned int *data);                      |
-    +----------------------------------------------------------------------------+
-    | Task              : Start / Stop The Watchdog                              |
-    +----------------------------------------------------------------------------+
-    | Input Parameters  : struct comedi_device *dev      : Driver handle                |
-    |                     struct comedi_subdevice *s,   :pointer to subdevice structure
-    struct comedi_insn *insn      :pointer to insn structure      |
-    |                     unsigned int *data          : Data Pointer to read status  |
-    +----------------------------------------------------------------------------+
-    | Output Parameters :       --                                                                                                       |
-    +----------------------------------------------------------------------------+
-    | Return Value      : TRUE  : No error occur                                 |
-    |                       : FALSE : Error occur. Return the error          |
-    |                                                                            |
-    +----------------------------------------------------------------------------+
-  */
-
-int i_APCI1516_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	switch (data[0]) {
-	case 0:		/* stop the watchdog */
-		outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE);	/* disable the watchdog */
-		break;
-	case 1:		/* start the watchdog */
-		outw(0x0001,
-			devpriv->i_IobaseAddon +
-			APCI1516_WATCHDOG_ENABLEDISABLE);
-		break;
-	case 2:		/* Software trigger */
-		outw(0x0201,
-			devpriv->i_IobaseAddon +
-			APCI1516_WATCHDOG_ENABLEDISABLE);
-		break;
-	default:
-		printk("\nSpecified functionality does not exist\n");
-		return -EINVAL;
-	}			/*  switch(data[0]) */
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1516_ReadWatchdog                            |
-|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
-                    unsigned int *data); 	                                     |
-+----------------------------------------------------------------------------+
-| Task              : Read The Watchdog                                      |
-+----------------------------------------------------------------------------+
-| Input Parameters  :   struct comedi_device *dev      : Driver handle              |
-|                     struct comedi_subdevice *s,   :pointer to subdevice structure
-                      struct comedi_insn *insn      :pointer to insn structure      |
-|                     unsigned int *data          : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI1516_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	data[0] = inw(devpriv->i_IobaseAddon + APCI1516_WATCHDOG_STATUS) & 0x1;
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1516_Reset(struct comedi_device *dev)               |                                                                                                          |
-+----------------------------------------------------------------------------+
-| Task              :resets all the registers                                |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      :                                                        |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI1516_Reset(struct comedi_device *dev)
-{
-	outw(0x0, devpriv->iobase + APCI1516_DIGITAL_OP);	/* RESETS THE DIGITAL OUTPUTS */
-	outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE);
-	outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_RELOAD_VALUE);
-	outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_RELOAD_VALUE + 2);
-	return 0;
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
deleted file mode 100644
index 4472829..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/*********      Definitions for APCI-1516 card  *****/
-
-/* Card Specific information */
-#define APCI1516_BOARD_VENDOR_ID                 0x15B8
-#define APCI1516_ADDRESS_RANGE                   8
-
-/* DIGITAL INPUT-OUTPUT DEFINE */
-
-#define APCI1516_DIGITAL_OP                 	4
-#define APCI1516_DIGITAL_OP_RW                 	4
-#define APCI1516_DIGITAL_IP                     0
-
-/* TIMER COUNTER WATCHDOG DEFINES */
-
-#define ADDIDATA_WATCHDOG                          2
-#define APCI1516_DIGITAL_OP_WATCHDOG               0
-#define APCI1516_WATCHDOG_ENABLEDISABLE            12
-#define APCI1516_WATCHDOG_RELOAD_VALUE             4
-#define APCI1516_WATCHDOG_STATUS                   16
-
-/* Hardware Layer  functions for Apci1516 */
-
-/* Digital Input */
-int i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				    struct comedi_insn *insn, unsigned int *data);
-int i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-
-/* Digital Output */
-int i_APCI1516_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data);
-int i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data);
-int i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-
-/*
-* TIMER timer value is passed as u seconds
-*/
-int i_APCI1516_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data);
-int i_APCI1516_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-				      struct comedi_insn *insn, unsigned int *data);
-int i_APCI1516_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data);
-
-/* reset */
-int i_APCI1516_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
index 5b92e45..fc31c4b 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
@@ -46,14 +46,62 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +----------+-----------+------------------------------------------------+
 */
 
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
-
-#include <linux/delay.h>
-#include "hwdrv_apci1564.h"
+/*********      Definitions for APCI-1564 card  *****/
+
+#define APCI1564_ADDRESS_RANGE				128
+
+/* DIGITAL INPUT-OUTPUT DEFINE */
+/* Input defines */
+#define APCI1564_DIGITAL_IP				0x04
+#define APCI1564_DIGITAL_IP_INTERRUPT_MODE1		4
+#define APCI1564_DIGITAL_IP_INTERRUPT_MODE2		8
+#define APCI1564_DIGITAL_IP_IRQ				16
+
+/* Output defines */
+#define APCI1564_DIGITAL_OP				0x18
+#define APCI1564_DIGITAL_OP_RW				0
+#define APCI1564_DIGITAL_OP_INTERRUPT			4
+#define APCI1564_DIGITAL_OP_IRQ				12
+
+/* Digital Input IRQ Function Selection */
+#define ADDIDATA_OR					0
+#define ADDIDATA_AND					1
+
+/* Digital Input Interrupt Status */
+#define APCI1564_DIGITAL_IP_INTERRUPT_STATUS		12
+
+/* Digital Output Interrupt Status */
+#define APCI1564_DIGITAL_OP_INTERRUPT_STATUS		8
+
+/* Digital Input Interrupt Enable Disable. */
+#define APCI1564_DIGITAL_IP_INTERRUPT_ENABLE		0x4
+#define APCI1564_DIGITAL_IP_INTERRUPT_DISABLE		0xfffffffb
+
+/* Digital Output Interrupt Enable Disable. */
+#define APCI1564_DIGITAL_OP_VCC_INTERRUPT_ENABLE	0x1
+#define APCI1564_DIGITAL_OP_VCC_INTERRUPT_DISABLE	0xfffffffe
+#define APCI1564_DIGITAL_OP_CC_INTERRUPT_ENABLE		0x2
+#define APCI1564_DIGITAL_OP_CC_INTERRUPT_DISABLE	0xfffffffd
+
+/* TIMER COUNTER WATCHDOG DEFINES */
+
+#define ADDIDATA_TIMER					0
+#define ADDIDATA_COUNTER				1
+#define ADDIDATA_WATCHDOG				2
+#define APCI1564_DIGITAL_OP_WATCHDOG			0x28
+#define APCI1564_TIMER					0x48
+#define APCI1564_COUNTER1				0x0
+#define APCI1564_COUNTER2				0x20
+#define APCI1564_COUNTER3				0x40
+#define APCI1564_COUNTER4				0x60
+#define APCI1564_TCW_SYNC_ENABLEDISABLE			0
+#define APCI1564_TCW_RELOAD_VALUE			4
+#define APCI1564_TCW_TIMEBASE				8
+#define APCI1564_TCW_PROG				12
+#define APCI1564_TCW_TRIG_STATUS			16
+#define APCI1564_TCW_IRQ				20
+#define APCI1564_TCW_WARN_TIMEVAL			24
+#define APCI1564_TCW_WARN_TIMEBASE			28
 
 /* Global variables */
 static unsigned int ui_InterruptStatus_1564 = 0;
@@ -86,9 +134,13 @@ static unsigned int ui_InterruptData, ui_Type;
 |			                                                         |
 +----------------------------------------------------------------------------+
 */
-int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev,
+					 struct comedi_subdevice *s,
+					 struct comedi_insn *insn,
+					 unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
+
 	devpriv->tsk_Current = current;
    /*******************************/
 	/* Set the digital input logic */
@@ -128,107 +180,15 @@ int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subde
 	return insn->n;
 }
 
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1564_Read1DigitalInput                       |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Return the status of the digital input                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|		              unsigned int ui_Channel : Channel number to read       |
-|                     unsigned int *data          : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI1564_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int apci1564_di_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	unsigned int ui_TmpValue = 0;
-	unsigned int ui_Channel;
+	struct addi_private *devpriv = dev->private;
 
-	ui_Channel = CR_CHAN(insn->chanspec);
-	if (ui_Channel <= 31) {
-		ui_TmpValue =
-			(unsigned int) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
-/*
-* since only 1 channel reqd to bring it to last bit it is rotated 8
-* +(chan - 1) times then ANDed with 1 for last bit.
-*/
-		*data = (ui_TmpValue >> ui_Channel) & 0x1;
-	}			/*  if  (ui_Channel >= 0 && ui_Channel <=31) */
-	else {
-		comedi_error(dev, "Not a valid channel number !!! \n");
-		return -EINVAL;	/*  "sorry channel spec wrong " */
-	}			/* else if  (ui_Channel >= 0 && ui_Channel <=31) */
-	return insn->n;
-}
+	data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
 
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1564_ReadMoreDigitalInput                    |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                     struct comedi_insn *insn,unsigned int *data)                      |
-+----------------------------------------------------------------------------+
-| Task              : Return the status of the Requested digital inputs      |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     unsigned int ui_NoOfChannels    : No Of Channels To be Read    |
-|                      unsigned int *data             : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int ui_PortValue = data[0];
-	unsigned int ui_Mask = 0;
-	unsigned int ui_NoOfChannels;
-
-	ui_NoOfChannels = CR_CHAN(insn->chanspec);
-	if (data[1] == 0) {
-		*data = (unsigned int) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
-		switch (ui_NoOfChannels) {
-		case 2:
-			ui_Mask = 3;
-			*data = (*data >> (2 * ui_PortValue)) & ui_Mask;
-			break;
-		case 4:
-			ui_Mask = 15;
-			*data = (*data >> (4 * ui_PortValue)) & ui_Mask;
-			break;
-		case 8:
-			ui_Mask = 255;
-			*data = (*data >> (8 * ui_PortValue)) & ui_Mask;
-			break;
-		case 16:
-			ui_Mask = 65535;
-			*data = (*data >> (16 * ui_PortValue)) & ui_Mask;
-			break;
-		case 31:
-			break;
-		default:
-			comedi_error(dev, "Not a valid Channel number !!!\n");
-			return -EINVAL;	/*  "sorry channel spec wrong " */
-			break;
-		}		/*  switch  (ui_NoOfChannels) */
-	}			/*  if  (data[1]==0) */
-	else {
-		if (data[1] == 1) {
-			*data = ui_InterruptStatus_1564;
-		}		/*  if  (data[1]==1) */
-	}			/*  else if  (data[1]==0) */
 	return insn->n;
 }
 
@@ -257,9 +217,12 @@ int i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_sub
 |			                                                         |
 +----------------------------------------------------------------------------+
 */
-int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev,
+					  struct comedi_subdevice *s,
+					  struct comedi_insn *insn,
+					  unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ul_Command = 0;
 
 	if ((data[0] != 0) && (data[0] != 1)) {
@@ -295,244 +258,27 @@ int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subd
 	return insn->n;
 }
 
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1564_WriteDigitalOutput                      |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Writes port value  To the selected port                |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     unsigned int ui_NoOfChannels    : No Of Channels To Write      |
-|                     unsigned int *data              : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI1564_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int apci1564_do_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	unsigned int ui_Temp, ui_Temp1;
-	unsigned int ui_NoOfChannel;
+	struct addi_private *devpriv = dev->private;
+	unsigned int mask = data[0];
+	unsigned int bits = data[1];
 
-	ui_NoOfChannel = CR_CHAN(insn->chanspec);
-	if (devpriv->b_OutputMemoryStatus) {
-		ui_Temp =
-			inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+	s->state = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
 			APCI1564_DIGITAL_OP_RW);
-	}			/*  if  (devpriv->b_OutputMemoryStatus ) */
-	else {
-		ui_Temp = 0;
-	}			/*  else if  (devpriv->b_OutputMemoryStatus ) */
-	if (data[3] == 0) {
-		if (data[1] == 0) {
-			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
-			outl(data[0],
-				devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
-				APCI1564_DIGITAL_OP_RW);
-		}		/*  if  (data[1]==0) */
-		else {
-			if (data[1] == 1) {
-				switch (ui_NoOfChannel) {
-				case 2:
-					data[0] =
-						(data[0] << (2 *
-							data[2])) | ui_Temp;
-					break;
-				case 4:
-					data[0] =
-						(data[0] << (4 *
-							data[2])) | ui_Temp;
-					break;
-				case 8:
-					data[0] =
-						(data[0] << (8 *
-							data[2])) | ui_Temp;
-					break;
-				case 16:
-					data[0] =
-						(data[0] << (16 *
-							data[2])) | ui_Temp;
-					break;
-				case 31:
-					data[0] = data[0] | ui_Temp;
-					break;
-				default:
-					comedi_error(dev, " chan spec wrong");
-					return -EINVAL;	/*  "sorry channel spec wrong " */
-				}	/*  switch (ui_NoOfChannels) */
-				outl(data[0],
-					devpriv->i_IobaseAmcc +
-					APCI1564_DIGITAL_OP +
-					APCI1564_DIGITAL_OP_RW);
-			}	/*  if  (data[1]==1) */
-			else {
-				printk("\nSpecified channel not supported\n");
-			}	/*  else if  (data[1]==1) */
-		}		/*  else if (data[1]==0) */
-	}			/* if(data[3]==0) */
-	else {
-		if (data[3] == 1) {
-			if (data[1] == 0) {
-				data[0] = ~data[0] & 0x1;
-				ui_Temp1 = 1;
-				ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
-				ui_Temp = ui_Temp | ui_Temp1;
-				data[0] =
-					(data[0] << ui_NoOfChannel) ^
-					0xffffffff;
-				data[0] = data[0] & ui_Temp;
-				outl(data[0],
-					devpriv->i_IobaseAmcc +
-					APCI1564_DIGITAL_OP +
-					APCI1564_DIGITAL_OP_RW);
-			}	/*  if  (data[1]==0) */
-			else {
-				if (data[1] == 1) {
-					switch (ui_NoOfChannel) {
-					case 2:
-						data[0] = ~data[0] & 0x3;
-						ui_Temp1 = 3;
-						ui_Temp1 =
-							ui_Temp1 << 2 * data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (2 *
-									data
-									[2])) ^
-							0xffffffff) & ui_Temp;
-						break;
-					case 4:
-						data[0] = ~data[0] & 0xf;
-						ui_Temp1 = 15;
-						ui_Temp1 =
-							ui_Temp1 << 4 * data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (4 *
-									data
-									[2])) ^
-							0xffffffff) & ui_Temp;
-						break;
-					case 8:
-						data[0] = ~data[0] & 0xff;
-						ui_Temp1 = 255;
-						ui_Temp1 =
-							ui_Temp1 << 8 * data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (8 *
-									data
-									[2])) ^
-							0xffffffff) & ui_Temp;
-						break;
-					case 16:
-						data[0] = ~data[0] & 0xffff;
-						ui_Temp1 = 65535;
-						ui_Temp1 =
-							ui_Temp1 << 16 *
-							data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (16 *
-									data
-									[2])) ^
-							0xffffffff) & ui_Temp;
-						break;
-					case 31:
-						break;
-					default:
-						comedi_error(dev,
-							" chan spec wrong");
-						return -EINVAL;	/*  "sorry channel spec wrong " */
-					}	/* switch(ui_NoOfChannels) */
-					outl(data[0],
-						devpriv->i_IobaseAmcc +
-						APCI1564_DIGITAL_OP +
-						APCI1564_DIGITAL_OP_RW);
-				}	/*  if  (data[1]==1) */
-				else {
-					printk("\nSpecified channel not supported\n");
-				}	/*  else if  (data[1]==1) */
-			}	/*  else if  (data[1]==0) */
-		}		/*  if  (data[3]==1); */
-		else {
-			printk("\nSpecified functionality does not exist\n");
-			return -EINVAL;
-		}		/*  else if (data[3]==1) */
-	}			/*  else if (data[3]==0) */
-	return insn->n;
-}
+	if (mask) {
+		s->state &= ~mask;
+		s->state |= (bits & mask);
+
+		outl(s->state, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
+			APCI1564_DIGITAL_OP_RW);
+	}
+
+	data[1] = s->state;
 
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI1564_ReadDigitalOutput                       |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Read  value  of the selected channel or port           |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
-|                     unsigned int *data              : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int ui_Temp;
-	unsigned int ui_NoOfChannel;
-
-	ui_NoOfChannel = CR_CHAN(insn->chanspec);
-	ui_Temp = data[0];
-	*data = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
-		APCI1564_DIGITAL_OP_RW);
-	if (ui_Temp == 0) {
-		*data = (*data >> ui_NoOfChannel) & 0x1;
-	}			/*  if  (ui_Temp==0) */
-	else {
-		if (ui_Temp == 1) {
-			switch (ui_NoOfChannel) {
-			case 2:
-				*data = (*data >> (2 * data[1])) & 3;
-				break;
-
-			case 4:
-				*data = (*data >> (4 * data[1])) & 15;
-				break;
-
-			case 8:
-				*data = (*data >> (8 * data[1])) & 255;
-				break;
-
-			case 16:
-				*data = (*data >> (16 * data[1])) & 65535;
-				break;
-
-			case 31:
-				break;
-
-			default:
-				comedi_error(dev, " chan spec wrong");
-				return -EINVAL;	/*  "sorry channel spec wrong " */
-				break;
-			}	/*  switch(ui_NoOfChannels) */
-		}		/*  if  (ui_Temp==1) */
-		else {
-			printk("\nSpecified channel not supported \n");
-		}		/*  else if (ui_Temp==1) */
-	}			/*  else if  (ui_Temp==0) */
 	return insn->n;
 }
 
@@ -566,10 +312,14 @@ int i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev
 |			                                                         |
 +----------------------------------------------------------------------------+
 */
-int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
+						 struct comedi_subdevice *s,
+						 struct comedi_insn *insn,
+						 unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ul_Command1 = 0;
+
 	devpriv->tsk_Current = current;
 	if (data[0] == ADDIDATA_WATCHDOG) {
 		devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
@@ -720,10 +470,14 @@ int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
 |			                                                         |
 +----------------------------------------------------------------------------+
 */
-int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
+							 struct comedi_subdevice *s,
+							 struct comedi_insn *insn,
+							 unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ul_Command1 = 0;
+
 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
 		switch (data[1]) {
 		case 0:	/* stop the watchdog */
@@ -815,9 +569,12 @@ int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
 |			                                                         |
 +----------------------------------------------------------------------------+
 */
-int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
+					       struct comedi_subdevice *s,
+					       struct comedi_insn *insn,
+					       unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ul_Command1 = 0;
 
 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
@@ -894,8 +651,10 @@ int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev,
+					  struct comedi_subdevice *s,
+					  struct comedi_insn *insn,
+					  unsigned int *data)
 {
 	*data = ui_Type;
 	return insn->n;
@@ -921,10 +680,12 @@ int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subd
 static void v_APCI1564_Interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_DO, ui_DI;
 	unsigned int ui_Timer;
 	unsigned int ui_C1, ui_C2, ui_C3, ui_C4;
 	unsigned int ul_Command2 = 0;
+
 	ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP +
 		APCI1564_DIGITAL_IP_IRQ) & 0x01;
 	ui_DO = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
@@ -1104,8 +865,10 @@ static void v_APCI1564_Interrupt(int irq, void *d)
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI1564_Reset(struct comedi_device *dev)
+static int i_APCI1564_Reset(struct comedi_device *dev)
 {
+	struct addi_private *devpriv = dev->private;
+
 	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_IRQ);	/* disable the interrupts */
 	inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_STATUS);	/* Reset the interrupt status register */
 	outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE1);	/* Disable the and/or interrupt */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
deleted file mode 100644
index c91594d..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/*********      Definitions for APCI-1564 card  *****/
-
-#define APCI1564_BOARD_VENDOR_ID                0x15B8
-#define APCI1564_ADDRESS_RANGE                  128
-
-/* DIGITAL INPUT-OUTPUT DEFINE */
-/* Input defines */
-#define APCI1564_DIGITAL_IP                     0x04
-#define APCI1564_DIGITAL_IP_INTERRUPT_MODE1     4
-#define APCI1564_DIGITAL_IP_INTERRUPT_MODE2     8
-#define APCI1564_DIGITAL_IP_IRQ                 16
-
-/* Output defines */
-#define APCI1564_DIGITAL_OP                 	0x18
-#define APCI1564_DIGITAL_OP_RW               	0
-#define APCI1564_DIGITAL_OP_INTERRUPT           4
-#define APCI1564_DIGITAL_OP_IRQ                 12
-
-/* Digital Input IRQ Function Selection */
-#define ADDIDATA_OR                             0
-#define ADDIDATA_AND                            1
-
-/* Digital Input Interrupt Status */
-#define APCI1564_DIGITAL_IP_INTERRUPT_STATUS    12
-
-/* Digital Output Interrupt Status */
-#define APCI1564_DIGITAL_OP_INTERRUPT_STATUS    8
-
-/* Digital Input Interrupt Enable Disable. */
-#define APCI1564_DIGITAL_IP_INTERRUPT_ENABLE    0x4
-#define APCI1564_DIGITAL_IP_INTERRUPT_DISABLE   0xFFFFFFFB
-
-/* Digital Output Interrupt Enable Disable. */
-#define APCI1564_DIGITAL_OP_VCC_INTERRUPT_ENABLE   0x1
-#define APCI1564_DIGITAL_OP_VCC_INTERRUPT_DISABLE  0xFFFFFFFE
-#define APCI1564_DIGITAL_OP_CC_INTERRUPT_ENABLE    0x2
-#define APCI1564_DIGITAL_OP_CC_INTERRUPT_DISABLE   0xFFFFFFFD
-
-/* ADDIDATA Enable Disable */
-
-#define ADDIDATA_ENABLE                            1
-#define ADDIDATA_DISABLE                           0
-
-/* TIMER COUNTER WATCHDOG DEFINES */
-
-#define ADDIDATA_TIMER                             0
-#define ADDIDATA_COUNTER                           1
-#define ADDIDATA_WATCHDOG                          2
-#define APCI1564_DIGITAL_OP_WATCHDOG               0x28
-#define APCI1564_TIMER                             0x48
-#define APCI1564_COUNTER1                          0x0
-#define APCI1564_COUNTER2                          0x20
-#define APCI1564_COUNTER3                          0x40
-#define APCI1564_COUNTER4                          0x60
-#define APCI1564_TCW_SYNC_ENABLEDISABLE            0
-#define APCI1564_TCW_RELOAD_VALUE                  4
-#define APCI1564_TCW_TIMEBASE                      8
-#define APCI1564_TCW_PROG                          12
-#define APCI1564_TCW_TRIG_STATUS                   16
-#define APCI1564_TCW_IRQ                           20
-#define APCI1564_TCW_WARN_TIMEVAL                  24
-#define APCI1564_TCW_WARN_TIMEBASE                 28
-
-/* Hardware Layer  functions for Apci1564 */
-
-/*
-* DI for di read
-*/
-int i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data);
-int i_APCI1564_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-int i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				    struct comedi_insn *insn, unsigned int *data);
-
-/* DO */
-int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data);
-int i_APCI1564_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data);
-int i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data);
-
-/*
-* TIMER timer value is passed as u seconds
-*/
-int i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev,
-					  struct comedi_subdevice *s,
-					  struct comedi_insn *insn, unsigned int *data);
-int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
-						  struct comedi_subdevice *s,
-						  struct comedi_insn *insn,
-						  unsigned int *data);
-int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev,
-					struct comedi_subdevice *s,
-					struct comedi_insn *insn, unsigned int *data);
-
-/* intERRUPT */
-static void v_APCI1564_Interrupt(int irq, void *d);
-
-/* RESET */
-int i_APCI1564_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
index 00a088f..5958a9c 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
@@ -47,13 +47,24 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +-----------------------------------------------------------------------+
 */
 
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
+#ifndef COMEDI_SUBD_TTLIO
+#define COMEDI_SUBD_TTLIO		11 /* Digital Input Output But TTL */
+#endif
+
+#define APCI16XX_TTL_INIT		0
+#define APCI16XX_TTL_INITDIRECTION	1
+#define APCI16XX_TTL_OUTPUTMEMORY	2
+
+#define APCI16XX_TTL_READCHANNEL	0
+#define APCI16XX_TTL_READPORT		1
+
+#define APCI16XX_TTL_WRITECHANNEL_ON	0
+#define APCI16XX_TTL_WRITECHANNEL_OFF	1
+#define APCI16XX_TTL_WRITEPORT_ON	2
+#define APCI16XX_TTL_WRITEPORT_OFF	3
 
-#include "hwdrv_apci16xx.h"
+#define APCI16XX_TTL_READ_ALL_INPUTS	0
+#define APCI16XX_TTL_READ_ALL_OUTPUTS	1
 
 /*
 +----------------------------------------------------------------------------+
@@ -90,9 +101,13 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
+					  struct comedi_subdevice *s,
+					  struct comedi_insn *insn,
+					  unsigned int *data)
 {
+	const struct addi_board *this_board = comedi_board(dev);
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = insn->n;
 	unsigned char b_Command = 0;
 	unsigned char b_Cpt = 0;
@@ -283,9 +298,13 @@ int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev,
+					struct comedi_subdevice *s,
+					struct comedi_insn *insn,
+					unsigned int *data)
 {
+	const struct addi_board *this_board = comedi_board(dev);
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = insn->n;
 	unsigned char b_Command = 0;
 	unsigned char b_NumberOfPort =
@@ -430,9 +449,13 @@ int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev,
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
+						struct comedi_subdevice *s,
+						struct comedi_insn *insn,
+						unsigned int *data)
 {
+	const struct addi_board *this_board = comedi_board(dev);
+	struct addi_private *devpriv = dev->private;
 	unsigned char b_Command = (unsigned char) CR_AREF(insn->chanspec);
 	int i_ReturnValue = insn->n;
 	unsigned char b_Cpt = 0;
@@ -570,9 +593,13 @@ int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device *dev,
+					 struct comedi_subdevice *s,
+					 struct comedi_insn *insn,
+					 unsigned int *data)
 {
+	const struct addi_board *this_board = comedi_board(dev);
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = insn->n;
 	unsigned char b_Command = 0;
 	unsigned char b_NumberOfPort =
@@ -774,7 +801,7 @@ int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device *dev,
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI16XX_Reset(struct comedi_device *dev)
+static int i_APCI16XX_Reset(struct comedi_device *dev)
 {
 	return 0;
 }
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
deleted file mode 100644
index a12df4b..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data-com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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 COMEDI_SUBD_TTLIO
-#define COMEDI_SUBD_TTLIO   11	/* Digital Input Output But TTL */
-#endif
-
-#ifndef ADDIDATA_ENABLE
-#define ADDIDATA_ENABLE  1
-#define ADDIDATA_DISABLE 0
-#endif
-
-#define APCI16XX_TTL_INIT           0
-#define APCI16XX_TTL_INITDIRECTION  1
-#define APCI16XX_TTL_OUTPUTMEMORY   2
-
-#define APCI16XX_TTL_READCHANNEL            0
-#define APCI16XX_TTL_READPORT               1
-
-#define APCI16XX_TTL_WRITECHANNEL_ON        0
-#define APCI16XX_TTL_WRITECHANNEL_OFF       1
-#define APCI16XX_TTL_WRITEPORT_ON           2
-#define APCI16XX_TTL_WRITEPORT_OFF          3
-
-#define APCI16XX_TTL_READ_ALL_INPUTS        0
-#define APCI16XX_TTL_READ_ALL_OUTPUTS       1
-
-#ifdef __KERNEL__
-
-/*
-+----------------------------------------------------------------------------+
-|                       TTL INISIALISATION FUNCTION                          |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev,
-				   struct comedi_subdevice *s, struct comedi_insn *insn,
-				   unsigned int *data);
-
-/*
-+----------------------------------------------------------------------------+
-|                       TTL INPUT FUNCTION                                   |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev,
-				 struct comedi_subdevice *s, struct comedi_insn *insn,
-				 unsigned int *data);
-
-int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev,
-					 struct comedi_subdevice *s,
-					 struct comedi_insn *insn, unsigned int *data);
-
-/*
-+----------------------------------------------------------------------------+
-|                            TTL OUTPUT FUNCTIONS                            |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device *dev,
-				  struct comedi_subdevice *s, struct comedi_insn *insn,
-				  unsigned int *data);
-
-int i_APCI16XX_Reset(struct comedi_device *dev);
-#endif
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
deleted file mode 100644
index 49dcbe2..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+++ /dev/null
@@ -1,460 +0,0 @@
-/**
-@verbatim
-
-Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
-
-	ADDI-DATA GmbH
-	Dieselstrasse 3
-	D-77833 Ottersweier
-	Tel: +19(0)7223/9493-0
-	Fax: +49(0)7223/9493-92
-	http://www.addi-data.com
-	info@addi-data.com
-
-This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-You should also find the complete GPL in the COPYING file accompanying this source code.
-
-@endverbatim
-*/
-/*
-
-  +-----------------------------------------------------------------------+
-  | (C) ADDI-DATA GmbH          Dieselstraße 3       D-77833 Ottersweier  |
-  +-----------------------------------------------------------------------+
-  | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
-  | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
-  +-------------------------------+---------------------------------------+
-  | Project     : APCI-2016       | Compiler   : GCC                      |
-  | Module name : hwdrv_apci2016.c| Version    : 2.96                     |
-  +-------------------------------+---------------------------------------+
-  | Project manager: Eric Stolz   | Date       :  02/12/2002              |
-  +-------------------------------+---------------------------------------+
-  | Description :   Hardware Layer Access For APCI-2016                   |
-  +-----------------------------------------------------------------------+
-  |                             UPDATES                                   |
-  +----------+-----------+------------------------------------------------+
-  |   Date   |   Author  |          Description of updates                |
-  +----------+-----------+------------------------------------------------+
-  |          |           |                                                |
-  |          |           |                                                |
-  |          |           |                                                |
-  +----------+-----------+------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
-#include "hwdrv_apci2016.h"
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI2016_ConfigDigitalOutput                     |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Configures The Digital Output Subdevice.               |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev : Driver handle                     |
-|                     unsigned int *data         : Data Pointer contains             |
-|                                          configuration parameters as below |
-|                                                                            |
-|			  data[0]            : 1 Digital Memory On               |
-|				     			   0 Digital Memory Off              |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI2016_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	if ((data[0] != 0) && (data[0] != 1)) {
-		comedi_error(dev,
-			"Not a valid Data !!! ,Data should be 1 or 0\n");
-		return -EINVAL;
-	}			/*  if  ((data[0]!=0) && (data[0]!=1)) */
-	if (data[0]) {
-		devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
-	}			/*  if  (data[0] */
-	else {
-		devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
-	}			/*  else if  (data[0] */
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI2016_WriteDigitalOutput                      |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Writes port value  To the selected port                |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     unsigned int ui_NoOfChannels    : No Of Channels To Write      |
-|                     unsigned int *data              : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int ui_NoOfChannel;
-	unsigned int ui_Temp, ui_Temp1;
-	ui_NoOfChannel = CR_CHAN(insn->chanspec);
-	if (ui_NoOfChannel > 15) {
-		comedi_error(dev,
-			"Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n");
-		return -EINVAL;
-	}			/*  if  ((ui_NoOfChannel<0) || (ui_NoOfChannel>15)) */
-	if (devpriv->b_OutputMemoryStatus) {
-		ui_Temp = inw(devpriv->iobase + APCI2016_DIGITAL_OP);
-	}			/*  if  (devpriv->b_OutputMemoryStatus ) */
-	else {
-		ui_Temp = 0;
-	}			/*  else if  (devpriv->b_OutputMemoryStatus ) */
-	if ((data[1] != 0) && (data[1] != 1)) {
-		comedi_error(dev,
-			"Invalid Data[1] value !!!, Data[1] should be 0 or 1\n");
-		return -EINVAL;
-	}			/*  if  ((data[1]!=0) && (data[1]!=1)) */
-
-	if (data[3] == 0) {
-		if (data[1] == 0) {
-			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
-			outw(data[0], devpriv->iobase + APCI2016_DIGITAL_OP);
-		}		/*  if (data[1]==0) */
-		else {
-			if (data[1] == 1) {
-				switch (ui_NoOfChannel) {
-				case 2:
-					data[0] =
-						(data[0] << (2 *
-							data[2])) | ui_Temp;
-					break;
-				case 4:
-					data[0] =
-						(data[0] << (4 *
-							data[2])) | ui_Temp;
-					break;
-				case 8:
-					data[0] =
-						(data[0] << (8 *
-							data[2])) | ui_Temp;
-					break;
-				case 15:
-					data[0] = data[0] | ui_Temp;
-					break;
-				default:
-					comedi_error(dev, " chan spec wrong");
-					return -EINVAL;	/*  "sorry channel spec wrong " */
-				}	/* switch(ui_NoOfChannels) */
-				outw(data[0],
-					devpriv->iobase + APCI2016_DIGITAL_OP);
-			}	/*  if  (data[1]==1) */
-			else {
-				printk("\nSpecified channel not supported\n");
-			}	/*  else if  (data[1]==1) */
-		}		/*  else if (data[1]==0) */
-	}			/*  if (data[3]==0) */
-	else {
-		if (data[3] == 1) {
-			if (data[1] == 0) {
-				data[0] = ~data[0] & 0x1;
-				ui_Temp1 = 1;
-				ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
-				ui_Temp = ui_Temp | ui_Temp1;
-				data[0] = (data[0] << ui_NoOfChannel) ^ 0xffff;
-				data[0] = data[0] & ui_Temp;
-				outw(data[0],
-					devpriv->iobase + APCI2016_DIGITAL_OP);
-			}	/*  if  (data[1]==0) */
-			else {
-				if (data[1] == 1) {
-					switch (ui_NoOfChannel) {
-					case 2:
-						data[0] = ~data[0] & 0x3;
-						ui_Temp1 = 3;
-						ui_Temp1 =
-							ui_Temp1 << 2 * data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (2 *
-									data
-									[2])) ^
-							0xffff) & ui_Temp;
-						break;
-					case 4:
-						data[0] = ~data[0] & 0xf;
-						ui_Temp1 = 15;
-						ui_Temp1 =
-							ui_Temp1 << 4 * data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (4 *
-									data
-									[2])) ^
-							0xffff) & ui_Temp;
-						break;
-					case 8:
-						data[0] = ~data[0] & 0xff;
-						ui_Temp1 = 255;
-						ui_Temp1 =
-							ui_Temp1 << 8 * data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (8 *
-									data
-									[2])) ^
-							0xffff) & ui_Temp;
-						break;
-					case 15:
-						break;
-					default:
-						comedi_error(dev,
-							" chan spec wrong");
-						return -EINVAL;	/*  "sorry channel spec wrong " */
-					}	/* switch(ui_NoOfChannels) */
-					outw(data[0],
-						devpriv->iobase +
-						APCI2016_DIGITAL_OP);
-				}	/*  if(data[1]==1) */
-				else {
-					printk("\nSpecified channel not supported\n");
-				}	/* else if(data[1]==1) */
-			}	/* elseif(data[1]==0) */
-		}		/* if(data[3]==1); */
-		else {
-			printk("\nSpecified functionality does not exist\n");
-			return -EINVAL;
-		}		/* if else data[3]==1) */
-	}			/* if else data[3]==0) */
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI2016_BitsDigitalOutput                       |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Read  value  of the selected channel or port           |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
-|                     unsigned int *data              : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int ui_Temp;
-	unsigned int ui_NoOfChannel;
-	ui_NoOfChannel = CR_CHAN(insn->chanspec);
-	if (ui_NoOfChannel > 15) {
-		comedi_error(dev,
-			"Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n");
-		return -EINVAL;
-	}			/*  if  ((ui_NoOfChannel<0) || (ui_NoOfChannel>15)) */
-	if ((data[0] != 0) && (data[0] != 1)) {
-		comedi_error(dev,
-			"Invalid Data[0] value !!!, Data[0] should be 0 or 1\n");
-		return -EINVAL;
-	}			/*  if  ((data[0]!=0) && (data[0]!=1)) */
-	ui_Temp = data[0];
-	*data = inw(devpriv->iobase + APCI2016_DIGITAL_OP_RW);
-	if (ui_Temp == 0) {
-		*data = (*data >> ui_NoOfChannel) & 0x1;
-	}			/*  if  (ui_Temp==0) */
-	else {
-		if (ui_Temp == 1) {
-			switch (ui_NoOfChannel) {
-			case 2:
-				*data = (*data >> (2 * data[1])) & 3;
-				break;
-
-			case 4:
-				*data = (*data >> (4 * data[1])) & 15;
-				break;
-
-			case 8:
-				*data = (*data >> (8 * data[1])) & 255;
-				break;
-
-			case 15:
-				break;
-
-			default:
-				comedi_error(dev, " chan spec wrong");
-				return -EINVAL;	/*  "sorry channel spec wrong " */
-			}	/* switch(ui_NoOfChannel) */
-		}		/*  if  (ui_Temp==1) */
-		else {
-			printk("\nSpecified channel not supported \n");
-		}		/*  else if  (ui_Temp==1) */
-	}			/*  if  (ui_Temp==0) */
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI2016_ConfigWatchdog                          |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Configures The Watchdog                                |
-+----------------------------------------------------------------------------+
-| Input Parameters  :   struct comedi_device *dev      : Driver handle              |
-|                     struct comedi_subdevice *s,   :pointer to subdevice structure |
-|                     struct comedi_insn *insn      :pointer to insn structure      |
-|                     unsigned int *data          : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI2016_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-
-	if (data[0] == 0) {
-		/* Disable the watchdog */
-		outw(0x0,
-			devpriv->i_IobaseAddon +
-			APCI2016_WATCHDOG_ENABLEDISABLE);
-		/* Loading the Reload value */
-		outw(data[1],
-			devpriv->i_IobaseAddon +
-			APCI2016_WATCHDOG_RELOAD_VALUE);
-		data[1] = data[1] >> 16;
-		outw(data[1],
-			devpriv->i_IobaseAddon +
-			APCI2016_WATCHDOG_RELOAD_VALUE + 2);
-	} else {
-		printk("\nThe input parameters are wrong\n");
-	}
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI2016_StartStopWriteWatchdog                  |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Start / Stop The Watchdog                              |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     struct comedi_subdevice *s,   :pointer to subdevice structure |
-|                     struct comedi_insn *insn      :pointer to insn structure      |
-|                     unsigned int *data          : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI2016_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-
-	switch (data[0]) {
-	case 0:		/* stop the watchdog */
-		outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE);	/* disable the watchdog */
-		break;
-	case 1:		/* start the watchdog */
-		outw(0x0001,
-			devpriv->i_IobaseAddon +
-			APCI2016_WATCHDOG_ENABLEDISABLE);
-		break;
-	case 2:		/* Software trigger */
-		outw(0x0201,
-			devpriv->i_IobaseAddon +
-			APCI2016_WATCHDOG_ENABLEDISABLE);
-		break;
-	default:
-		printk("\nSpecified functionality does not exist\n");
-		return -EINVAL;
-	}			/*  switch(data[0]) */
-
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI2016_ReadWatchdog                            |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Read The Watchdog                                      |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     struct comedi_subdevice *s,   :pointer to subdevice structure |
-|                     struct comedi_insn *insn      :pointer to insn structure      |
-|                     unsigned int *data          : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI2016_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	udelay(5);
-	data[0] = inw(devpriv->i_IobaseAddon + APCI2016_WATCHDOG_STATUS) & 0x1;
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI2016_Reset(struct comedi_device *dev)               |                                                       |
-+----------------------------------------------------------------------------+
-| Task              :resets all the registers                                |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      :                                                        |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI2016_Reset(struct comedi_device *dev)
-{
-	outw(0x0, devpriv->iobase + APCI2016_DIGITAL_OP);	/*  Resets the digital output channels */
-	outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE);
-	outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE);
-	outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE + 2);
-	return 0;
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
deleted file mode 100644
index c42612a..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-/*********      Definitions for APCI-2016 card  *****/
-
-#define APCI2016_BOARD_VENDOR_ID 0x15B8
-#define APCI2016_ADDRESS_RANGE   8
-
-/* DIGITAL INPUT-OUTPUT DEFINE */
-
-#define APCI2016_DIGITAL_OP                 	0x04
-#define APCI2016_DIGITAL_OP_RW                 	4
-
-/* ADDIDATA Enable Disable */
-
-#define ADDIDATA_ENABLE                            1
-#define ADDIDATA_DISABLE                           0
-
-/* TIMER COUNTER WATCHDOG DEFINES */
-
-#define ADDIDATA_WATCHDOG                          2
-#define APCI2016_DIGITAL_OP_WATCHDOG               0
-#define APCI2016_WATCHDOG_ENABLEDISABLE            12
-#define APCI2016_WATCHDOG_RELOAD_VALUE             4
-#define APCI2016_WATCHDOG_STATUS                   16
-
-/* Hardware Layer  functions for Apci2016 */
-
-/* DO */
-int i_APCI2016_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-
-/*
-* TIMER
-* timer value is passed as u seconds
-*/
-
-int i_APCI2016_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI2016_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-				      struct comedi_insn *insn, unsigned int *data);
-
-int i_APCI2016_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data);
-
-/* Interrupt functions..... */
-
-/* void v_APCI2016_Interrupt(int irq, void *d); */
-
-/* void v_APCI2016_Interrupt(int irq, void *d); */
-/* RESET */
-int i_APCI2016_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
index 002297d..8422b68 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
@@ -46,14 +46,39 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +----------+-----------+------------------------------------------------+
 */
 
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
+/*********      Definitions for APCI-2032 card  *****/
+
+/* Card Specific information */
+#define APCI2032_ADDRESS_RANGE				63
+
+/* DIGITAL INPUT-OUTPUT DEFINE */
+
+#define APCI2032_DIGITAL_OP				0
+#define APCI2032_DIGITAL_OP_RW				0
+#define APCI2032_DIGITAL_OP_INTERRUPT			4
+#define APCI2032_DIGITAL_OP_IRQ				12
+
+/* Digital Output Interrupt Status */
+#define APCI2032_DIGITAL_OP_INTERRUPT_STATUS		8
+
+/* Digital Output Interrupt Enable Disable. */
+#define APCI2032_DIGITAL_OP_VCC_INTERRUPT_ENABLE	0x1
+#define APCI2032_DIGITAL_OP_VCC_INTERRUPT_DISABLE	0xfffffffe
+#define APCI2032_DIGITAL_OP_CC_INTERRUPT_ENABLE		0x2
+#define APCI2032_DIGITAL_OP_CC_INTERRUPT_DISABLE	0xfffffffd
+
+/* TIMER COUNTER WATCHDOG DEFINES */
+
+#define ADDIDATA_WATCHDOG				2
+#define APCI2032_DIGITAL_OP_WATCHDOG			16
+#define APCI2032_TCW_RELOAD_VALUE			4
+#define APCI2032_TCW_TIMEBASE				8
+#define APCI2032_TCW_PROG				12
+#define APCI2032_TCW_TRIG_STATUS			16
+#define APCI2032_TCW_IRQ				20
 
-#include "hwdrv_apci2032.h"
 static unsigned int ui_InterruptData, ui_Type;
+
 /*
 +----------------------------------------------------------------------------+
 | Function   Name   : int i_APCI2032_ConfigDigitalOutput                     |
@@ -79,10 +104,14 @@ static unsigned int ui_InterruptData, ui_Type;
 |			                                                         |
 +----------------------------------------------------------------------------+
 */
-int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev,
+					  struct comedi_subdevice *s,
+					  struct comedi_insn *insn,
+					  unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ul_Command = 0;
+
 	devpriv->tsk_Current = current;
 
 	if ((data[0] != 0) && (data[0] != 1)) {
@@ -114,249 +143,25 @@ int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subd
 	return insn->n;
 }
 
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI2032_WriteDigitalOutput                      |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Writes port value  To the selected port                |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     unsigned int ui_NoOfChannels    : No Of Channels To Write      |
-|                     unsigned int *data              : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int apci2032_do_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	unsigned int ui_Temp, ui_Temp1;
-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
-	if (devpriv->b_OutputMemoryStatus) {
-		ui_Temp = inl(devpriv->iobase + APCI2032_DIGITAL_OP);
+	struct addi_private *devpriv = dev->private;
+	unsigned int mask = data[0];
+	unsigned int bits = data[1];
 
-	}			/* if(devpriv->b_OutputMemoryStatus ) */
-	else {
-		ui_Temp = 0;
-	}			/* if(devpriv->b_OutputMemoryStatus ) */
-	if (data[3] == 0) {
-		if (data[1] == 0) {
-			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
-			outl(data[0], devpriv->iobase + APCI2032_DIGITAL_OP);
-		}		/* if(data[1]==0) */
-		else {
-			if (data[1] == 1) {
-				switch (ui_NoOfChannel) {
-
-				case 2:
-					data[0] =
-						(data[0] << (2 *
-							data[2])) | ui_Temp;
-					break;
-
-				case 4:
-					data[0] =
-						(data[0] << (4 *
-							data[2])) | ui_Temp;
-					break;
-
-				case 8:
-					data[0] =
-						(data[0] << (8 *
-							data[2])) | ui_Temp;
-					break;
-
-				case 16:
-					data[0] =
-						(data[0] << (16 *
-							data[2])) | ui_Temp;
-					break;
-				case 31:
-					data[0] = data[0] | ui_Temp;
-					break;
-
-				default:
-					comedi_error(dev, " chan spec wrong");
-					return -EINVAL;	/*  "sorry channel spec wrong " */
-
-				}	/* switch(ui_NoOfChannels) */
-
-				outl(data[0],
-					devpriv->iobase + APCI2032_DIGITAL_OP);
-			}	/*  if(data[1]==1) */
-			else {
-				printk("\nSpecified channel not supported\n");
-			}	/* else if(data[1]==1) */
-		}		/* elseif(data[1]==0) */
-	}			/* if(data[3]==0) */
-	else {
-		if (data[3] == 1) {
-			if (data[1] == 0) {
-				data[0] = ~data[0] & 0x1;
-				ui_Temp1 = 1;
-				ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
-				ui_Temp = ui_Temp | ui_Temp1;
-				data[0] =
-					(data[0] << ui_NoOfChannel) ^
-					0xffffffff;
-				data[0] = data[0] & ui_Temp;
-				outl(data[0],
-					devpriv->iobase + APCI2032_DIGITAL_OP);
-			}	/* if(data[1]==0) */
-			else {
-				if (data[1] == 1) {
-					switch (ui_NoOfChannel) {
-
-					case 2:
-						data[0] = ~data[0] & 0x3;
-						ui_Temp1 = 3;
-						ui_Temp1 =
-							ui_Temp1 << 2 * data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (2 *
-									data
-									[2])) ^
-							0xffffffff) & ui_Temp;
-						break;
-
-					case 4:
-						data[0] = ~data[0] & 0xf;
-						ui_Temp1 = 15;
-						ui_Temp1 =
-							ui_Temp1 << 4 * data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (4 *
-									data
-									[2])) ^
-							0xffffffff) & ui_Temp;
-						break;
-
-					case 8:
-						data[0] = ~data[0] & 0xff;
-						ui_Temp1 = 255;
-						ui_Temp1 =
-							ui_Temp1 << 8 * data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (8 *
-									data
-									[2])) ^
-							0xffffffff) & ui_Temp;
-						break;
-
-					case 16:
-						data[0] = ~data[0] & 0xffff;
-						ui_Temp1 = 65535;
-						ui_Temp1 =
-							ui_Temp1 << 16 *
-							data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (16 *
-									data
-									[2])) ^
-							0xffffffff) & ui_Temp;
-						break;
-
-					case 31:
-						break;
-					default:
-						comedi_error(dev,
-							" chan spec wrong");
-						return -EINVAL;	/*  "sorry channel spec wrong " */
-
-					}	/* switch(ui_NoOfChannels) */
-
-					outl(data[0],
-						devpriv->iobase +
-						APCI2032_DIGITAL_OP);
-				}	/*  if(data[1]==1) */
-				else {
-					printk("\nSpecified channel not supported\n");
-				}	/* else if(data[1]==1) */
-			}	/* elseif(data[1]==0) */
-		}		/* if(data[3]==1); */
-		else {
-			printk("\nSpecified functionality does not exist\n");
-			return -EINVAL;
-		}		/* if else data[3]==1) */
-	}			/* if else data[3]==0) */
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI2032_ReadDigitalOutput                       |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Read  value  of the selected channel or port           |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
-|                     unsigned int *data              : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int ui_Temp;
-	unsigned int ui_NoOfChannel;
-	ui_NoOfChannel = CR_CHAN(insn->chanspec);
-	ui_Temp = data[0];
-	*data = inl(devpriv->iobase + APCI2032_DIGITAL_OP_RW);
-	if (ui_Temp == 0) {
-		*data = (*data >> ui_NoOfChannel) & 0x1;
-	}			/* if  (ui_Temp==0) */
-	else {
-		if (ui_Temp == 1) {
-			switch (ui_NoOfChannel) {
-
-			case 2:
-				*data = (*data >> (2 * data[1])) & 3;
-				break;
-
-			case 4:
-				*data = (*data >> (4 * data[1])) & 15;
-				break;
+	s->state = inl(devpriv->iobase + APCI2032_DIGITAL_OP_RW);
+	if (mask) {
+		s->state &= ~mask;
+		s->state |= (bits & mask);
 
-			case 8:
-				*data = (*data >> (8 * data[1])) & 255;
-				break;
-
-			case 16:
-				*data = (*data >> (16 * data[1])) & 65535;
-				break;
-
-			case 31:
-				break;
+		outl(s->state, devpriv->iobase + APCI2032_DIGITAL_OP);
+	}
 
-			default:
-				comedi_error(dev, " chan spec wrong");
-				return -EINVAL;	/*  "sorry channel spec wrong " */
+	data[1] = s->state;
 
-			}	/* switch(ui_NoOfChannels) */
-		}		/* if  (ui_Temp==1) */
-		else {
-			printk("\nSpecified channel not supported \n");
-		}		/* elseif  (ui_Temp==1) */
-	}
 	return insn->n;
 }
 
@@ -380,9 +185,13 @@ int i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev
 |			                                                         |
 +----------------------------------------------------------------------------+
 */
-int i_APCI2032_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI2032_ConfigWatchdog(struct comedi_device *dev,
+				     struct comedi_subdevice *s,
+				     struct comedi_insn *insn,
+				     unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
+
 	if (data[0] == 0) {
 		/* Disable the watchdog */
 		outl(0x0,
@@ -421,9 +230,13 @@ int i_APCI2032_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice
     +----------------------------------------------------------------------------+
   */
 
-int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev,
+					     struct comedi_subdevice *s,
+					     struct comedi_insn *insn,
+					     unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
+
 	switch (data[0]) {
 	case 0:		/* stop the watchdog */
 		outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG);	/* disable the watchdog */
@@ -466,9 +279,12 @@ int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_s
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI2032_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI2032_ReadWatchdog(struct comedi_device *dev,
+				   struct comedi_subdevice *s,
+				   struct comedi_insn *insn,
+				   unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 
 	data[0] =
 		inl(devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG +
@@ -493,9 +309,10 @@ int i_APCI2032_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *
 |			                                                         |
 +----------------------------------------------------------------------------+
 */
-void v_APCI2032_Interrupt(int irq, void *d)
+static void v_APCI2032_Interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_DO;
 
 	ui_DO = inl(devpriv->iobase + APCI2032_DIGITAL_OP_IRQ) & 0x1;	/* Check if VCC OR CC interrupt has occurred. */
@@ -544,8 +361,10 @@ void v_APCI2032_Interrupt(int irq, void *d)
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI2032_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI2032_ReadInterruptStatus(struct comedi_device *dev,
+					  struct comedi_subdevice *s,
+					  struct comedi_insn *insn,
+					  unsigned int *data)
 {
 	*data = ui_Type;
 	return insn->n;
@@ -567,8 +386,10 @@ int i_APCI2032_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subd
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI2032_Reset(struct comedi_device *dev)
+static int i_APCI2032_Reset(struct comedi_device *dev)
 {
+	struct addi_private *devpriv = dev->private;
+
 	devpriv->b_DigitalOutputRegister = 0;
 	ui_Type = 0;
 	outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP);	/* Resets the output channels */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
deleted file mode 100644
index ab145e7..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/*********      Definitions for APCI-2032 card  *****/
-
-/* Card Specific information */
-#define APCI2032_BOARD_VENDOR_ID                 0x15B8
-#define APCI2032_ADDRESS_RANGE                   63
-
-/* DIGITAL INPUT-OUTPUT DEFINE */
-
-#define APCI2032_DIGITAL_OP                 	0
-#define APCI2032_DIGITAL_OP_RW                 	0
-#define APCI2032_DIGITAL_OP_INTERRUPT           4
-#define APCI2032_DIGITAL_OP_IRQ                 12
-
-/* Digital Output Interrupt Status */
-#define APCI2032_DIGITAL_OP_INTERRUPT_STATUS    8
-
-/* Digital Output Interrupt Enable Disable. */
-#define APCI2032_DIGITAL_OP_VCC_INTERRUPT_ENABLE   0x1
-#define APCI2032_DIGITAL_OP_VCC_INTERRUPT_DISABLE  0xFFFFFFFE
-#define APCI2032_DIGITAL_OP_CC_INTERRUPT_ENABLE    0x2
-#define APCI2032_DIGITAL_OP_CC_INTERRUPT_DISABLE   0xFFFFFFFD
-
-/* ADDIDATA Enable Disable */
-
-#define ADDIDATA_ENABLE                            1
-#define ADDIDATA_DISABLE                           0
-
-/* TIMER COUNTER WATCHDOG DEFINES */
-
-#define ADDIDATA_WATCHDOG                          2
-#define APCI2032_DIGITAL_OP_WATCHDOG               16
-#define APCI2032_TCW_RELOAD_VALUE                  4
-#define APCI2032_TCW_TIMEBASE                      8
-#define APCI2032_TCW_PROG                          12
-#define APCI2032_TCW_TRIG_STATUS                   16
-#define APCI2032_TCW_IRQ                           20
-
-/* Hardware Layer  functions for Apci2032 */
-
-/* DO */
-int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data);
-int i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data);
-int i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-int i_APCI2032_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data);
-
-/* TIMER
- * timer value is passed as u seconds
-*/
-
-int i_APCI2032_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data);
-int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-				      struct comedi_insn *insn, unsigned int *data);
-int i_APCI2032_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data);
-
-/* Interrupt functions..... */
-
-void v_APCI2032_Interrupt(int irq, void *d);
-
-/* Reset functions */
-int i_APCI2032_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
index 3d378b5..9d4a117 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
@@ -46,354 +46,54 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +----------+-----------+------------------------------------------------+
 */
 
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
-#include "hwdrv_apci2200.h"
+/*********      Definitions for APCI-2200 card  *****/
 
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI2200_Read1DigitalInput                       |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Return the status of the digital input                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|		       struct comedi_subdevice *s,   :pointer to subdevice structure
-|                       struct comedi_insn *insn      :pointer to insn structure     |
-|                     unsigned int *data          : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int ui_TmpValue = 0;
-	unsigned int ui_Channel;
-	ui_Channel = CR_CHAN(insn->chanspec);
-	if (ui_Channel <= 7) {
-		ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
-		*data = (ui_TmpValue >> ui_Channel) & 0x1;
-	}			/* if(ui_Channel >= 0 && ui_Channel <=7) */
-	else {
-		printk("\nThe specified channel does not exist\n");
-		return -EINVAL;	/*  "sorry channel spec wrong " */
-	}			/* else if(ui_Channel >= 0 && ui_Channel <=7) */
+/* Card Specific information */
+#define APCI2200_ADDRESS_RANGE		64
 
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI2200_ReadMoreDigitalInput                    |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                     struct comedi_insn *insn,unsigned int *data)                      |
-+----------------------------------------------------------------------------+
-| Task              : Return the status of the Requested digital inputs      |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                      struct comedi_subdevice *s,   :pointer to subdevice structure
-|                       struct comedi_insn *insn      :pointer to insn structure     |
-|                      unsigned int *data         : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
+/* DIGITAL INPUT-OUTPUT DEFINE */
 
-int i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
+#define APCI2200_DIGITAL_OP		4
+#define APCI2200_DIGITAL_IP		0
 
-	unsigned int ui_PortValue = data[0];
-	unsigned int ui_Mask = 0;
-	unsigned int ui_NoOfChannels;
+/* TIMER COUNTER WATCHDOG DEFINES */
 
-	ui_NoOfChannels = CR_CHAN(insn->chanspec);
+#define APCI2200_WATCHDOG		0x08
+#define APCI2200_WATCHDOG_ENABLEDISABLE	12
+#define APCI2200_WATCHDOG_RELOAD_VALUE	4
+#define APCI2200_WATCHDOG_STATUS	16
 
-	*data = (unsigned int) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
-	switch (ui_NoOfChannels) {
-	case 2:
-		ui_Mask = 3;
-		*data = (*data >> (2 * ui_PortValue)) & ui_Mask;
-		break;
-	case 4:
-		ui_Mask = 15;
-		*data = (*data >> (4 * ui_PortValue)) & ui_Mask;
-		break;
-	case 7:
-		break;
+static int apci2200_di_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
+{
+	struct addi_private *devpriv = dev->private;
 
-	default:
-		printk("\nWrong parameters\n");
-		return -EINVAL;	/*  "sorry channel spec wrong " */
-		break;
-	}			/* switch(ui_NoOfChannels) */
+	data[1] = inw(devpriv->iobase + APCI2200_DIGITAL_IP);
 
 	return insn->n;
 }
 
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI2200_ConfigDigitalOutput (struct comedi_device *dev,
-|                    struct comedi_subdevice *s struct comedi_insn *insn,unsigned int *data)    |
-|				                                                     |
-+----------------------------------------------------------------------------+
-| Task              : Configures The Digital Output Subdevice.               |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev : Driver handle                     |
-|                     unsigned int *data         : Data Pointer contains         |
-|                                          configuration parameters as below |
-|                      struct comedi_subdevice *s,   :pointer to subdevice structure
-|                       struct comedi_insn *insn      :pointer to insn structure                                                           |
-|					  data[0]  :1:Memory on                          |
-|					            0:Memory off                         |
-|										                             |
-|																	 |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int apci2200_do_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	devpriv->b_OutputMemoryStatus = data[0];
-	return insn->n;
-}
+	struct addi_private *devpriv = dev->private;
+	unsigned int mask = data[0];
+	unsigned int bits = data[1];
 
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI2200_WriteDigitalOutput                      |
-|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
-|                     unsigned int *data)                                         |
-+----------------------------------------------------------------------------+
-| Task              : Writes port value  To the selected port                |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     struct comedi_subdevice *s,   :pointer to subdevice structure
-|                      struct comedi_insn *insn      :pointer to insn structure      |
-|                    unsigned int *data           : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
+	s->state = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
+	if (mask) {
+		s->state &= ~mask;
+		s->state |= (bits & mask);
 
-int i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int ui_Temp, ui_Temp1;
-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
-	if (devpriv->b_OutputMemoryStatus) {
-		ui_Temp = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
+		outw(s->state, devpriv->iobase + APCI2200_DIGITAL_OP);
+	}
 
-	}			/* if(devpriv->b_OutputMemoryStatus ) */
-	else {
-		ui_Temp = 0;
-	}			/* if(devpriv->b_OutputMemoryStatus ) */
-	if (data[3] == 0) {
-		if (data[1] == 0) {
-			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
-			outw(data[0], devpriv->iobase + APCI2200_DIGITAL_OP);
-		}		/* if(data[1]==0) */
-		else {
-			if (data[1] == 1) {
-				switch (ui_NoOfChannel) {
-
-				case 2:
-					data[0] =
-						(data[0] << (2 *
-							data[2])) | ui_Temp;
-					break;
-
-				case 4:
-					data[0] =
-						(data[0] << (4 *
-							data[2])) | ui_Temp;
-					break;
-
-				case 8:
-					data[0] =
-						(data[0] << (8 *
-							data[2])) | ui_Temp;
-					break;
-				case 15:
-					data[0] = data[0] | ui_Temp;
-					break;
-				default:
-					comedi_error(dev, " chan spec wrong");
-					return -EINVAL;	/*  "sorry channel spec wrong " */
-
-				}	/* switch(ui_NoOfChannels) */
-
-				outw(data[0],
-					devpriv->iobase + APCI2200_DIGITAL_OP);
-			}	/*  if(data[1]==1) */
-			else {
-				printk("\nSpecified channel not supported\n");
-			}	/* else if(data[1]==1) */
-		}		/* elseif(data[1]==0) */
-	}			/* if(data[3]==0) */
-	else {
-		if (data[3] == 1) {
-			if (data[1] == 0) {
-				data[0] = ~data[0] & 0x1;
-				ui_Temp1 = 1;
-				ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
-				ui_Temp = ui_Temp | ui_Temp1;
-				data[0] = (data[0] << ui_NoOfChannel) ^ 0xffff;
-				data[0] = data[0] & ui_Temp;
-				outw(data[0],
-					devpriv->iobase + APCI2200_DIGITAL_OP);
-			}	/* if(data[1]==0) */
-			else {
-				if (data[1] == 1) {
-					switch (ui_NoOfChannel) {
-
-					case 2:
-						data[0] = ~data[0] & 0x3;
-						ui_Temp1 = 3;
-						ui_Temp1 =
-							ui_Temp1 << 2 * data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (2 *
-									data
-									[2])) ^
-							0xffff) & ui_Temp;
-						break;
-
-					case 4:
-						data[0] = ~data[0] & 0xf;
-						ui_Temp1 = 15;
-						ui_Temp1 =
-							ui_Temp1 << 4 * data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (4 *
-									data
-									[2])) ^
-							0xffff) & ui_Temp;
-						break;
-
-					case 8:
-						data[0] = ~data[0] & 0xff;
-						ui_Temp1 = 255;
-						ui_Temp1 =
-							ui_Temp1 << 8 * data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (8 *
-									data
-									[2])) ^
-							0xffff) & ui_Temp;
-						break;
-					case 15:
-						break;
-
-					default:
-						comedi_error(dev,
-							" chan spec wrong");
-						return -EINVAL;	/*  "sorry channel spec wrong " */
-
-					}	/* switch(ui_NoOfChannels) */
-
-					outw(data[0],
-						devpriv->iobase +
-						APCI2200_DIGITAL_OP);
-				}	/*  if(data[1]==1) */
-				else {
-					printk("\nSpecified channel not supported\n");
-				}	/* else if(data[1]==1) */
-			}	/* elseif(data[1]==0) */
-		}		/* if(data[3]==1); */
-		else {
-			printk("\nSpecified functionality does not exist\n");
-			return -EINVAL;
-		}		/* if else data[3]==1) */
-	}			/* if else data[3]==0) */
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI2200_ReadDigitalOutput                       |
-|			(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,
-|                    unsigned int *data) 	                                     |
-+----------------------------------------------------------------------------+
-| Task              : Read  value  of the selected channel or port           |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     struct comedi_subdevice *s,   :pointer to subdevice structure
-|                     struct comedi_insn *insn      :pointer to insn structure      |
-|                     unsigned int *data          : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
+	data[1] = s->state;
 
-	unsigned int ui_Temp;
-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
-	ui_Temp = data[0];
-	*data = inw(devpriv->iobase + APCI2200_DIGITAL_OP);
-	if (ui_Temp == 0) {
-		*data = (*data >> ui_NoOfChannel) & 0x1;
-	}			/* if(ui_Temp==0) */
-	else {
-		if (ui_Temp == 1) {
-			switch (ui_NoOfChannel) {
-
-			case 2:
-				*data = (*data >> (2 * data[1])) & 3;
-				break;
-
-			case 4:
-				*data = (*data >> (4 * data[1])) & 15;
-				break;
-
-			case 8:
-				*data = (*data >> (8 * data[1])) & 255;
-				break;
-
-			case 15:
-				break;
-
-			default:
-				comedi_error(dev, " chan spec wrong");
-				return -EINVAL;	/*  "sorry channel spec wrong " */
-
-			}	/* switch(ui_NoOfChannels) */
-		}		/* if(ui_Temp==1) */
-		else {
-			printk("\nSpecified channel not supported \n");
-		}		/* elseif(ui_Temp==1) */
-	}			/* elseif(ui_Temp==0) */
 	return insn->n;
 }
 
@@ -418,9 +118,13 @@ int i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI2200_ConfigWatchdog(struct comedi_device *dev,
+				     struct comedi_subdevice *s,
+				     struct comedi_insn *insn,
+				     unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
+
 	if (data[0] == 0) {
 		/* Disable the watchdog */
 		outw(0x0,
@@ -464,9 +168,13 @@ int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice
     +----------------------------------------------------------------------------+
   */
 
-int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev,
+					     struct comedi_subdevice *s,
+					     struct comedi_insn *insn,
+					     unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
+
 	switch (data[0]) {
 	case 0:		/* stop the watchdog */
 		outw(0x0, devpriv->iobase + APCI2200_WATCHDOG + APCI2200_WATCHDOG_ENABLEDISABLE);	/* disable the watchdog */
@@ -509,9 +217,13 @@ int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_s
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI2200_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI2200_ReadWatchdog(struct comedi_device *dev,
+				   struct comedi_subdevice *s,
+				   struct comedi_insn *insn,
+				   unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
+
 	data[0] =
 		inw(devpriv->iobase + APCI2200_WATCHDOG +
 		APCI2200_WATCHDOG_STATUS) & 0x1;
@@ -533,8 +245,10 @@ int i_APCI2200_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI2200_Reset(struct comedi_device *dev)
+static int i_APCI2200_Reset(struct comedi_device *dev)
 {
+	struct addi_private *devpriv = dev->private;
+
 	outw(0x0, devpriv->iobase + APCI2200_DIGITAL_OP);	/* RESETS THE DIGITAL OUTPUTS */
 	outw(0x0,
 		devpriv->iobase + APCI2200_WATCHDOG +
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
deleted file mode 100644
index 83f42af..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/*********      Definitions for APCI-2200 card  *****/
-
-/* Card Specific information */
-#define APCI2200_BOARD_VENDOR_ID                 0x15b8
-#define APCI2200_ADDRESS_RANGE                   64
-
-/* DIGITAL INPUT-OUTPUT DEFINE */
-
-#define APCI2200_DIGITAL_OP                 	4
-#define APCI2200_DIGITAL_IP                     0
-
-/* TIMER COUNTER WATCHDOG DEFINES */
-
-#define APCI2200_WATCHDOG                          0x08
-#define APCI2200_WATCHDOG_ENABLEDISABLE            12
-#define APCI2200_WATCHDOG_RELOAD_VALUE             4
-#define APCI2200_WATCHDOG_STATUS                   16
-
-/* Hardware Layer  functions for Apci2200 */
-
-/* Digital Input */
-int i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				    struct comedi_insn *insn, unsigned int *data);
-int i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-
-/* Digital Output */
-int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data);
-int i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data);
-int i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-
-/* TIMER */
-int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data);
-int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-				      struct comedi_insn *insn, unsigned int *data);
-int i_APCI2200_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data);
-
-/* reset */
-int i_APCI2200_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
index f406dfb..74065ba 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
@@ -44,8 +44,203 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +----------+-----------+------------------------------------------------+
 */
 
-#include "hwdrv_apci3120.h"
-static unsigned int ui_Temp;
+/*
+ * ADDON RELATED ADDITIONS
+ */
+/* Constant */
+#define APCI3120_ENABLE_TRANSFER_ADD_ON_LOW		0x00
+#define APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH		0x1200
+#define APCI3120_A2P_FIFO_MANAGEMENT			0x04000400L
+#define APCI3120_AMWEN_ENABLE				0x02
+#define APCI3120_A2P_FIFO_WRITE_ENABLE			0x01
+#define APCI3120_FIFO_ADVANCE_ON_BYTE_2			0x20000000L
+#define APCI3120_ENABLE_WRITE_TC_INT			0x00004000L
+#define APCI3120_CLEAR_WRITE_TC_INT			0x00040000L
+#define APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE	0x0
+#define APCI3120_DISABLE_BUS_MASTER_ADD_ON		0x0
+#define APCI3120_DISABLE_BUS_MASTER_PCI			0x0
+
+/* ADD_ON ::: this needed since apci supports 16 bit interface to add on */
+#define APCI3120_ADD_ON_AGCSTS_LOW	0x3C
+#define APCI3120_ADD_ON_AGCSTS_HIGH	(APCI3120_ADD_ON_AGCSTS_LOW + 2)
+#define APCI3120_ADD_ON_MWAR_LOW	0x24
+#define APCI3120_ADD_ON_MWAR_HIGH	(APCI3120_ADD_ON_MWAR_LOW + 2)
+#define APCI3120_ADD_ON_MWTC_LOW	0x058
+#define APCI3120_ADD_ON_MWTC_HIGH	(APCI3120_ADD_ON_MWTC_LOW + 2)
+
+/* AMCC */
+#define APCI3120_AMCC_OP_MCSR		0x3C
+#define APCI3120_AMCC_OP_REG_INTCSR	0x38
+
+/* for transfer count enable bit */
+#define AGCSTS_TC_ENABLE	0x10000000
+
+/* used for test on mixture of BIP/UNI ranges */
+#define APCI3120_BIPOLAR_RANGES		4
+
+#define APCI3120_ADDRESS_RANGE		16
+
+#define APCI3120_DISABLE		0
+#define APCI3120_ENABLE			1
+
+#define APCI3120_START			1
+#define APCI3120_STOP			0
+
+#define APCI3120_EOC_MODE		1
+#define APCI3120_EOS_MODE		2
+#define APCI3120_DMA_MODE		3
+
+/* DIGITAL INPUT-OUTPUT DEFINE */
+
+#define APCI3120_DIGITAL_OUTPUT		0x0d
+#define APCI3120_RD_STATUS		0x02
+#define APCI3120_RD_FIFO		0x00
+
+/* digital output insn_write ON /OFF selection */
+#define	APCI3120_SET4DIGITALOUTPUTON	1
+#define APCI3120_SET4DIGITALOUTPUTOFF	0
+
+/* analog output SELECT BIT */
+#define APCI3120_ANALOG_OP_CHANNEL_1	0x0000
+#define APCI3120_ANALOG_OP_CHANNEL_2	0x4000
+#define APCI3120_ANALOG_OP_CHANNEL_3	0x8000
+#define APCI3120_ANALOG_OP_CHANNEL_4	0xc000
+#define APCI3120_ANALOG_OP_CHANNEL_5	0x0000
+#define APCI3120_ANALOG_OP_CHANNEL_6	0x4000
+#define APCI3120_ANALOG_OP_CHANNEL_7	0x8000
+#define APCI3120_ANALOG_OP_CHANNEL_8	0xc000
+
+/* Enable external trigger bit in nWrAddress */
+#define APCI3120_ENABLE_EXT_TRIGGER	0x8000
+
+/* ANALOG OUTPUT AND INPUT DEFINE */
+#define APCI3120_UNIPOLAR		0x80
+#define APCI3120_BIPOLAR		0x00
+#define APCI3120_ANALOG_OUTPUT_1	0x08
+#define APCI3120_ANALOG_OUTPUT_2	0x0a
+#define APCI3120_1_GAIN			0x00
+#define APCI3120_2_GAIN			0x10
+#define APCI3120_5_GAIN			0x20
+#define APCI3120_10_GAIN		0x30
+#define APCI3120_SEQ_RAM_ADDRESS	0x06
+#define APCI3120_RESET_FIFO		0x0c
+#define APCI3120_TIMER_0_MODE_2		0x01
+#define APCI3120_TIMER_0_MODE_4		0x2
+#define APCI3120_SELECT_TIMER_0_WORD	0x00
+#define APCI3120_ENABLE_TIMER0		0x1000
+#define APCI3120_CLEAR_PR		0xf0ff
+#define APCI3120_CLEAR_PA		0xfff0
+#define APCI3120_CLEAR_PA_PR		(APCI3120_CLEAR_PR & APCI3120_CLEAR_PA)
+
+/* nWrMode_Select */
+#define APCI3120_ENABLE_SCAN		0x8
+#define APCI3120_DISABLE_SCAN		(~APCI3120_ENABLE_SCAN)
+#define APCI3120_ENABLE_EOS_INT		0x2
+
+#define APCI3120_DISABLE_EOS_INT	(~APCI3120_ENABLE_EOS_INT)
+#define APCI3120_ENABLE_EOC_INT		0x1
+#define APCI3120_DISABLE_EOC_INT	(~APCI3120_ENABLE_EOC_INT)
+#define APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER	\
+	(APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT)
+#define APCI3120_DISABLE_ALL_INTERRUPT			\
+	(APCI3120_DISABLE_TIMER_INT & APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT)
+
+/* status register bits */
+#define APCI3120_EOC			0x8000
+#define APCI3120_EOS			0x2000
+
+/* software trigger dummy register */
+#define APCI3120_START_CONVERSION	0x02
+
+/* TIMER DEFINE */
+#define APCI3120_QUARTZ_A		70
+#define APCI3120_QUARTZ_B		50
+#define APCI3120_TIMER			1
+#define APCI3120_WATCHDOG		2
+#define APCI3120_TIMER_DISABLE		0
+#define APCI3120_TIMER_ENABLE		1
+#define APCI3120_ENABLE_TIMER2		0x4000
+#define APCI3120_DISABLE_TIMER2		(~APCI3120_ENABLE_TIMER2)
+#define APCI3120_ENABLE_TIMER_INT	0x04
+#define APCI3120_DISABLE_TIMER_INT	(~APCI3120_ENABLE_TIMER_INT)
+#define APCI3120_WRITE_MODE_SELECT	0x0e
+#define APCI3120_SELECT_TIMER_0_WORD	0x00
+#define APCI3120_SELECT_TIMER_1_WORD	0x01
+#define APCI3120_TIMER_1_MODE_2		0x4
+
+/* $$ BIT FOR MODE IN nCsTimerCtr1 */
+#define APCI3120_TIMER_2_MODE_0		0x0
+#define APCI3120_TIMER_2_MODE_2		0x10
+#define APCI3120_TIMER_2_MODE_5		0x30
+
+/* $$ BIT FOR MODE IN nCsTimerCtr0 */
+#define APCI3120_SELECT_TIMER_2_LOW_WORD	0x02
+#define APCI3120_SELECT_TIMER_2_HIGH_WORD	0x03
+
+#define APCI3120_TIMER_CRT0		0x0d
+#define APCI3120_TIMER_CRT1		0x0c
+
+#define APCI3120_TIMER_VALUE		0x04
+#define APCI3120_TIMER_STATUS_REGISTER	0x0d
+#define APCI3120_RD_STATUS		0x02
+#define APCI3120_WR_ADDRESS		0x00
+#define APCI3120_ENABLE_WATCHDOG	0x20
+#define APCI3120_DISABLE_WATCHDOG	(~APCI3120_ENABLE_WATCHDOG)
+#define APCI3120_ENABLE_TIMER_COUNTER	0x10
+#define APCI3120_DISABLE_TIMER_COUNTER	(~APCI3120_ENABLE_TIMER_COUNTER)
+#define APCI3120_FC_TIMER		0x1000
+#define APCI3120_ENABLE_TIMER0		0x1000
+#define APCI3120_ENABLE_TIMER1		0x2000
+#define APCI3120_ENABLE_TIMER2		0x4000
+#define APCI3120_DISABLE_TIMER0		(~APCI3120_ENABLE_TIMER0)
+#define APCI3120_DISABLE_TIMER1		(~APCI3120_ENABLE_TIMER1)
+#define APCI3120_DISABLE_TIMER2		(~APCI3120_ENABLE_TIMER2)
+
+#define APCI3120_TIMER2_SELECT_EOS	0xc0
+#define APCI3120_COUNTER		3
+#define APCI3120_DISABLE_ALL_TIMER	(APCI3120_DISABLE_TIMER0 &	\
+					 APCI3120_DISABLE_TIMER1 &	\
+					 APCI3120_DISABLE_TIMER2)
+
+#define MAX_ANALOGINPUT_CHANNELS	32
+
+struct str_AnalogReadInformation {
+	/* EOC or EOS */
+	unsigned char b_Type;
+	/* Interrupt use or not */
+	unsigned char b_InterruptFlag;
+	/* Selection of the conversion time */
+	unsigned int ui_ConvertTiming;
+	/* Number of channel to read */
+	unsigned char b_NbrOfChannel;
+	/* Number of the channel to be read */
+	unsigned int ui_ChannelList[MAX_ANALOGINPUT_CHANNELS];
+	/* Gain of each channel */
+	unsigned int ui_RangeList[MAX_ANALOGINPUT_CHANNELS];
+};
+
+/* ANALOG INPUT RANGE */
+static const struct comedi_lrange range_apci3120_ai = {
+	8, {
+		BIP_RANGE(10),
+		BIP_RANGE(5),
+		BIP_RANGE(2),
+		BIP_RANGE(1),
+		UNI_RANGE(10),
+		UNI_RANGE(5),
+		UNI_RANGE(2),
+		UNI_RANGE(1)
+	}
+};
+
+/* ANALOG OUTPUT RANGE */
+static const struct comedi_lrange range_apci3120_ao = {
+	2, {
+		BIP_RANGE(10),
+		UNI_RANGE(10)
+	}
+};
+
 
 /* FUNCTION DEFINITIONS */
 
@@ -55,28 +250,13 @@ static unsigned int ui_Temp;
 +----------------------------------------------------------------------------+
 */
 
-/*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev,|
-|  struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)					 |
-|                                            						         |
-+----------------------------------------------------------------------------+
-| Task              : Calls card specific function  					     |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev									 |
-|                     struct comedi_subdevice *s									 |
-|                     struct comedi_insn *insn                                      |
-|                     unsigned int *data      					         		 |
-+----------------------------------------------------------------------------+
-| Return Value      :              					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev,
+					    struct comedi_subdevice *s,
+					    struct comedi_insn *insn,
+					    unsigned int *data)
 {
+	const struct addi_board *this_board = comedi_board(dev);
+	struct addi_private *devpriv = dev->private;
 	unsigned int i;
 
 	if ((data[0] != APCI3120_EOC_MODE) && (data[0] != APCI3120_EOS_MODE))
@@ -91,7 +271,7 @@ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_su
 		for (i = 0; i < data[3]; i++) {
 
 			if (CR_CHAN(data[4 + i]) >=
-				devpriv->s_EeParameters.i_NbrAiChannel) {
+				this_board->i_NbrAiChannel) {
 				printk("bad channel list\n");
 				return -2;
 			}
@@ -121,31 +301,72 @@ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_su
 }
 
 /*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev,  |
-|			struct comedi_subdevice *s,struct comedi_insn *insn, unsigned int *data)	 |
-|                                            						         |
-+----------------------------------------------------------------------------+
-| Task              :  card specific function								 |
-|				Reads analog input in synchronous mode               |
-|			  EOC and EOS is selected as per configured              |
-|                     if no conversion time is set uses default conversion   |
-|			  time 10 microsec.					      				 |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev									 |
-|                     struct comedi_subdevice *s									 |
-|                     struct comedi_insn *insn                                      |
-|                     unsigned int *data     									 |
-+----------------------------------------------------------------------------+
-| Return Value      :              					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
+ * This function will first check channel list is ok or not and then
+ * initialize the sequence RAM with the polarity, Gain,Channel number.
+ * If the last argument of function "check"is 1 then it only checks
+ * the channel list is ok or not.
+ */
+static int i_APCI3120_SetupChannelList(struct comedi_device *dev,
+				       struct comedi_subdevice *s,
+				       int n_chan,
+				       unsigned int *chanlist,
+				       char check)
+{
+	struct addi_private *devpriv = dev->private;
+	unsigned int i;		/* , differencial=0, bipolar=0; */
+	unsigned int gain;
+	unsigned short us_TmpValue;
+
+	/* correct channel and range number check itself comedi/range.c */
+	if (n_chan < 1) {
+		if (!check)
+			comedi_error(dev, "range/channel list is empty!");
+		return 0;
+	}
+	/*  All is ok, so we can setup channel/range list */
+	if (check)
+		return 1;
+
+	/* Code  to set the PA and PR...Here it set PA to 0.. */
+	devpriv->us_OutputRegister =
+		devpriv->us_OutputRegister & APCI3120_CLEAR_PA_PR;
+	devpriv->us_OutputRegister = ((n_chan - 1) & 0xf) << 8;
+	outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+
+	for (i = 0; i < n_chan; i++) {
+		/*  store range list to card */
+		us_TmpValue = CR_CHAN(chanlist[i]);	/*  get channel number; */
+
+		if (CR_RANGE(chanlist[i]) < APCI3120_BIPOLAR_RANGES)
+			us_TmpValue &= ((~APCI3120_UNIPOLAR) & 0xff);	/*  set bipolar */
+		else
+			us_TmpValue |= APCI3120_UNIPOLAR;	/*  enable unipolar...... */
+
+		gain = CR_RANGE(chanlist[i]);	/*  get gain number */
+		us_TmpValue |= ((gain & 0x03) << 4);	/* <<4 for G0 and G1 bit in RAM */
+		us_TmpValue |= i << 8;	/* To select the RAM LOCATION.... */
+		outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS);
+
+		printk("\n Gain = %i",
+			(((unsigned char)CR_RANGE(chanlist[i]) & 0x03) << 2));
+		printk("\n Channel = %i", CR_CHAN(chanlist[i]));
+		printk("\n Polarity = %i", us_TmpValue & APCI3120_UNIPOLAR);
+	}
+	return 1;		/*  we can serve this with scan logic */
+}
 
-int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+/*
+ * Reads analog input in synchronous mode EOC and EOS is selected
+ * as per configured if no conversion time is set uses default
+ * conversion time 10 microsec.
+ */
+static int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev,
+					  struct comedi_subdevice *s,
+					  struct comedi_insn *insn,
+					  unsigned int *data)
 {
+	const struct addi_board *this_board = comedi_board(dev);
+	struct addi_private *devpriv = dev->private;
 	unsigned short us_ConvertTiming, us_TmpValue, i;
 	unsigned char b_Tmp;
 
@@ -387,26 +608,86 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subd
 
 }
 
+static int i_APCI3120_Reset(struct comedi_device *dev)
+{
+	struct addi_private *devpriv = dev->private;
+	unsigned int i;
+	unsigned short us_TmpValue;
+
+	devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+	devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
+	devpriv->b_InterruptMode = APCI3120_EOC_MODE;
+	devpriv->ui_EocEosConversionTime = 0;	/*  set eoc eos conv time to 0 */
+	devpriv->b_OutputMemoryStatus = 0;
+
+	/*  variables used in timer subdevice */
+	devpriv->b_Timer2Mode = 0;
+	devpriv->b_Timer2Interrupt = 0;
+	devpriv->b_ExttrigEnable = 0;	/*  Disable ext trigger */
+
+	/* Disable all interrupts, watchdog for the anolog output */
+	devpriv->b_ModeSelectRegister = 0;
+	outb(devpriv->b_ModeSelectRegister,
+		dev->iobase + APCI3120_WRITE_MODE_SELECT);
+
+	/*  Disables all counters, ext trigger and clears PA, PR */
+	devpriv->us_OutputRegister = 0;
+	outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+
 /*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev,|
-| 											     struct comedi_subdevice *s)|
-|                                        									 |
-+----------------------------------------------------------------------------+
-| Task              : Stops Cyclic acquisition  						     |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev									 |
-|                     struct comedi_subdevice *s									 |
-|                                                 					         |
-+----------------------------------------------------------------------------+
-| Return Value      :0              					                     |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
+ * Code to set the all anolog o/p channel to 0v 8191 is decimal
+ * value for zero(0 v)volt in bipolar mode(default)
+ */
+	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_1, dev->iobase + APCI3120_ANALOG_OUTPUT_1);	/* channel 1 */
+	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_2, dev->iobase + APCI3120_ANALOG_OUTPUT_1);	/* channel 2 */
+	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_3, dev->iobase + APCI3120_ANALOG_OUTPUT_1);	/* channel 3 */
+	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_4, dev->iobase + APCI3120_ANALOG_OUTPUT_1);	/* channel 4 */
+
+	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_5, dev->iobase + APCI3120_ANALOG_OUTPUT_2);	/* channel 5 */
+	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_6, dev->iobase + APCI3120_ANALOG_OUTPUT_2);	/* channel 6 */
+	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_7, dev->iobase + APCI3120_ANALOG_OUTPUT_2);	/* channel 7 */
+	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_8, dev->iobase + APCI3120_ANALOG_OUTPUT_2);	/* channel 8 */
+
+	/*   Reset digital output to L0W */
+
+/* ES05  outb(0x0,dev->iobase+APCI3120_DIGITAL_OUTPUT); */
+	udelay(10);
+
+	inw(dev->iobase + 0);	/* make a dummy read */
+	inb(dev->iobase + APCI3120_RESET_FIFO);	/*  flush FIFO */
+	inw(dev->iobase + APCI3120_RD_STATUS);	/*  flush A/D status register */
+
+	/* code to reset the RAM sequence */
+	for (i = 0; i < 16; i++) {
+		us_TmpValue = i << 8;	/* select the location */
+		outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS);
+	}
+	return 0;
+}
+
+static int i_APCI3120_ExttrigEnable(struct comedi_device *dev)
+{
+	struct addi_private *devpriv = dev->private;
+
+	devpriv->us_OutputRegister |= APCI3120_ENABLE_EXT_TRIGGER;
+	outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+	return 0;
+}
+
+static int i_APCI3120_ExttrigDisable(struct comedi_device *dev)
+{
+	struct addi_private *devpriv = dev->private;
+
+	devpriv->us_OutputRegister &= ~APCI3120_ENABLE_EXT_TRIGGER;
+	outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+	return 0;
+}
 
-int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s)
+static int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev,
+					    struct comedi_subdevice *s)
 {
+	struct addi_private *devpriv = dev->private;
+
 	/*  Disable A2P Fifo write and AMWEN signal */
 	outw(0, devpriv->i_IobaseAddon + 4);
 
@@ -456,28 +737,11 @@ int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_su
 	return 0;
 }
 
-/*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev|
-|			,struct comedi_subdevice *s,struct comedi_cmd *cmd)					 |
-|                                        									 |
-+----------------------------------------------------------------------------+
-| Task              : Test validity for a command for cyclic anlog input     |
-|                       acquisition  						     			 |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev									 |
-|                     struct comedi_subdevice *s									 |
-|                     struct comedi_cmd *cmd              					         |
-+----------------------------------------------------------------------------+
-| Return Value      :0              					                     |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_cmd *cmd)
+static int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev,
+					     struct comedi_subdevice *s,
+					     struct comedi_cmd *cmd)
 {
+	const struct addi_board *this_board = comedi_board(dev);
 	int err = 0;
 
 	/* Step 1 : check if triggers are trivially valid */
@@ -503,63 +767,32 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s
 	if (err)
 		return 2;
 
-	/*  step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->scan_begin_src == TRIG_TIMER) {	/*  Test Delay timing */
-		if (cmd->scan_begin_arg <
-				devpriv->s_EeParameters.ui_MinDelaytimeNs) {
-			cmd->scan_begin_arg =
-				devpriv->s_EeParameters.ui_MinDelaytimeNs;
-			err++;
-		}
-	}
+	if (cmd->scan_begin_src == TRIG_TIMER)	/* Test Delay timing */
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, 100000);
 
 	if (cmd->convert_src == TRIG_TIMER) {	/*  Test Acquisition timing */
 		if (cmd->scan_begin_src == TRIG_TIMER) {
-			if ((cmd->convert_arg)
-				&& (cmd->convert_arg <
-					devpriv->s_EeParameters.
-						ui_MinAcquisitiontimeNs)) {
-				cmd->convert_arg = devpriv->s_EeParameters.
-					ui_MinAcquisitiontimeNs;
-				err++;
-			}
+			if (cmd->convert_arg)
+				err |= cfc_check_trigger_arg_min(
+						&cmd->convert_arg, 10000);
 		} else {
-			if (cmd->convert_arg <
-				devpriv->s_EeParameters.ui_MinAcquisitiontimeNs
-				) {
-				cmd->convert_arg = devpriv->s_EeParameters.
-					ui_MinAcquisitiontimeNs;
-				err++;
-
-			}
+			err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+							10000);
 		}
 	}
 
-	if (!cmd->chanlist_len) {
-		cmd->chanlist_len = 1;
-		err++;
-	}
-	if (cmd->chanlist_len > this_board->i_AiChannelList) {
-		cmd->chanlist_len = this_board->i_AiChannelList;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (!cmd->stop_arg) {
-			cmd->stop_arg = 1;
-			err++;
-		}
-	} else {		/*  TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
+	err |= cfc_check_trigger_arg_max(&cmd->chanlist_len,
+					 this_board->i_AiChannelList);
+
+	if (cmd->stop_src == TRIG_COUNT)
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+	else	/*  TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -584,100 +817,17 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s
 }
 
 /*
-+----------------------------------------------------------------------------+
-| Function name     : int i_APCI3120_CommandAnalogInput(struct comedi_device *dev,  |
-|												struct comedi_subdevice *s) |
-|                                        									 |
-+----------------------------------------------------------------------------+
-| Task              : Does asynchronous acquisition                          |
-|                     Determines the mode 1 or 2.						     |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev									 |
-|                     struct comedi_subdevice *s									 |
-|                     														 |
-+----------------------------------------------------------------------------+
-| Return Value      :              					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s)
-{
-	struct comedi_cmd *cmd = &s->async->cmd;
-
-	/* loading private structure with cmd structure inputs */
-	devpriv->ui_AiFlags = cmd->flags;
-	devpriv->ui_AiNbrofChannels = cmd->chanlist_len;
-	devpriv->ui_AiScanLength = cmd->scan_end_arg;
-	devpriv->pui_AiChannelList = cmd->chanlist;
-
-	/* UPDATE-0.7.57->0.7.68devpriv->AiData=s->async->data; */
-	devpriv->AiData = s->async->prealloc_buf;
-	/* UPDATE-0.7.57->0.7.68devpriv->ui_AiDataLength=s->async->data_len; */
-	devpriv->ui_AiDataLength = s->async->prealloc_bufsz;
-
-	if (cmd->stop_src == TRIG_COUNT)
-		devpriv->ui_AiNbrofScans = cmd->stop_arg;
-	else
-		devpriv->ui_AiNbrofScans = 0;
-
-	devpriv->ui_AiTimer0 = 0;	/*  variables changed to timer0,timer1 */
-	devpriv->ui_AiTimer1 = 0;
-	if ((devpriv->ui_AiNbrofScans == 0) || (devpriv->ui_AiNbrofScans == -1))
-		devpriv->b_AiContinuous = 1;	/*  user want neverending analog acquisition */
-	/*  stopped using cancel */
-
-	if (cmd->start_src == TRIG_EXT)
-		devpriv->b_ExttrigEnable = APCI3120_ENABLE;
-	else
-		devpriv->b_ExttrigEnable = APCI3120_DISABLE;
-
-	if (cmd->scan_begin_src == TRIG_FOLLOW) {
-		/*  mode 1 or 3 */
-		if (cmd->convert_src == TRIG_TIMER) {
-			/*  mode 1 */
-
-			devpriv->ui_AiTimer0 = cmd->convert_arg;	/*  timer constant in nano seconds */
-			/* return this_board->ai_cmd(1,dev,s); */
-			return i_APCI3120_CyclicAnalogInput(1, dev, s);
-		}
-
-	}
-	if ((cmd->scan_begin_src == TRIG_TIMER)
-		&& (cmd->convert_src == TRIG_TIMER)) {
-		/*  mode 2 */
-		devpriv->ui_AiTimer1 = cmd->scan_begin_arg;
-		devpriv->ui_AiTimer0 = cmd->convert_arg;	/*  variable changed timer2 to timer0 */
-		/* return this_board->ai_cmd(2,dev,s); */
-		return i_APCI3120_CyclicAnalogInput(2, dev, s);
-	}
-	return -1;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function name     :  int i_APCI3120_CyclicAnalogInput(int mode,            |
-|		 	   struct comedi_device * dev,struct comedi_subdevice * s)			 |
-+----------------------------------------------------------------------------+
-| Task              : This is used for analog input cyclic acquisition       |
-|			  Performs the command operations.                       |
-|			  If DMA is configured does DMA initialization           |
-|			  otherwise does the acquisition with EOS interrupt.     |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : 														 |
-|                     														 |
-|                                                 					         |
-+----------------------------------------------------------------------------+
-| Return Value      :              					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
-	struct comedi_subdevice *s)
+ * This is used for analog input cyclic acquisition.
+ * Performs the command operations.
+ * If DMA is configured does DMA initialization otherwise does the
+ * acquisition with EOS interrupt.
+ */
+static int i_APCI3120_CyclicAnalogInput(int mode,
+					struct comedi_device *dev,
+					struct comedi_subdevice *s)
 {
+	const struct addi_board *this_board = comedi_board(dev);
+	struct addi_private *devpriv = dev->private;
 	unsigned char b_Tmp;
 	unsigned int ui_Tmp, ui_DelayTiming = 0, ui_TimerValue1 = 0, dmalen0 =
 		0, dmalen1 = 0, ui_TimerValue2 =
@@ -1186,241 +1336,277 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
 }
 
 /*
-+----------------------------------------------------------------------------+
-| 			intERNAL FUNCTIONS						                 |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function name     : int i_APCI3120_Reset(struct comedi_device *dev)               |
-|                                        									 |
-|                                            						         |
-+----------------------------------------------------------------------------+
-| Task              : Hardware reset function   						     |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : 	struct comedi_device *dev									 |
-|                     														 |
-|                                                 					         |
-+----------------------------------------------------------------------------+
-| Return Value      :              					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI3120_Reset(struct comedi_device *dev)
+ * Does asynchronous acquisition.
+ * Determines the mode 1 or 2.
+ */
+static int i_APCI3120_CommandAnalogInput(struct comedi_device *dev,
+					 struct comedi_subdevice *s)
 {
-	unsigned int i;
-	unsigned short us_TmpValue;
-
-	devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
-	devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
-	devpriv->b_InterruptMode = APCI3120_EOC_MODE;
-	devpriv->ui_EocEosConversionTime = 0;	/*  set eoc eos conv time to 0 */
-	devpriv->b_OutputMemoryStatus = 0;
+	struct addi_private *devpriv = dev->private;
+	struct comedi_cmd *cmd = &s->async->cmd;
 
-	/*  variables used in timer subdevice */
-	devpriv->b_Timer2Mode = 0;
-	devpriv->b_Timer2Interrupt = 0;
-	devpriv->b_ExttrigEnable = 0;	/*  Disable ext trigger */
-
-	/* Disable all interrupts, watchdog for the anolog output */
-	devpriv->b_ModeSelectRegister = 0;
-	outb(devpriv->b_ModeSelectRegister,
-		dev->iobase + APCI3120_WRITE_MODE_SELECT);
+	/* loading private structure with cmd structure inputs */
+	devpriv->ui_AiFlags = cmd->flags;
+	devpriv->ui_AiNbrofChannels = cmd->chanlist_len;
+	devpriv->ui_AiScanLength = cmd->scan_end_arg;
+	devpriv->pui_AiChannelList = cmd->chanlist;
 
-	/*  Disables all counters, ext trigger and clears PA, PR */
-	devpriv->us_OutputRegister = 0;
-	outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+	/* UPDATE-0.7.57->0.7.68devpriv->AiData=s->async->data; */
+	devpriv->AiData = s->async->prealloc_buf;
+	/* UPDATE-0.7.57->0.7.68devpriv->ui_AiDataLength=s->async->data_len; */
+	devpriv->ui_AiDataLength = s->async->prealloc_bufsz;
 
-/*
- * Code to set the all anolog o/p channel to 0v 8191 is decimal
- * value for zero(0 v)volt in bipolar mode(default)
- */
-	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_1, dev->iobase + APCI3120_ANALOG_OUTPUT_1);	/* channel 1 */
-	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_2, dev->iobase + APCI3120_ANALOG_OUTPUT_1);	/* channel 2 */
-	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_3, dev->iobase + APCI3120_ANALOG_OUTPUT_1);	/* channel 3 */
-	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_4, dev->iobase + APCI3120_ANALOG_OUTPUT_1);	/* channel 4 */
+	if (cmd->stop_src == TRIG_COUNT)
+		devpriv->ui_AiNbrofScans = cmd->stop_arg;
+	else
+		devpriv->ui_AiNbrofScans = 0;
 
-	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_5, dev->iobase + APCI3120_ANALOG_OUTPUT_2);	/* channel 5 */
-	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_6, dev->iobase + APCI3120_ANALOG_OUTPUT_2);	/* channel 6 */
-	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_7, dev->iobase + APCI3120_ANALOG_OUTPUT_2);	/* channel 7 */
-	outw(8191 | APCI3120_ANALOG_OP_CHANNEL_8, dev->iobase + APCI3120_ANALOG_OUTPUT_2);	/* channel 8 */
+	devpriv->ui_AiTimer0 = 0;	/*  variables changed to timer0,timer1 */
+	devpriv->ui_AiTimer1 = 0;
+	if ((devpriv->ui_AiNbrofScans == 0) || (devpriv->ui_AiNbrofScans == -1))
+		devpriv->b_AiContinuous = 1;	/*  user want neverending analog acquisition */
+	/*  stopped using cancel */
 
-	/*   Reset digital output to L0W */
+	if (cmd->start_src == TRIG_EXT)
+		devpriv->b_ExttrigEnable = APCI3120_ENABLE;
+	else
+		devpriv->b_ExttrigEnable = APCI3120_DISABLE;
 
-/* ES05  outb(0x0,dev->iobase+APCI3120_DIGITAL_OUTPUT); */
-	udelay(10);
+	if (cmd->scan_begin_src == TRIG_FOLLOW) {
+		/*  mode 1 or 3 */
+		if (cmd->convert_src == TRIG_TIMER) {
+			/*  mode 1 */
 
-	inw(dev->iobase + 0);	/* make a dummy read */
-	inb(dev->iobase + APCI3120_RESET_FIFO);	/*  flush FIFO */
-	inw(dev->iobase + APCI3120_RD_STATUS);	/*  flush A/D status register */
+			devpriv->ui_AiTimer0 = cmd->convert_arg;	/*  timer constant in nano seconds */
+			/* return this_board->ai_cmd(1,dev,s); */
+			return i_APCI3120_CyclicAnalogInput(1, dev, s);
+		}
 
-	/* code to reset the RAM sequence */
-	for (i = 0; i < 16; i++) {
-		us_TmpValue = i << 8;	/* select the location */
-		outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS);
 	}
-	return 0;
+	if ((cmd->scan_begin_src == TRIG_TIMER)
+		&& (cmd->convert_src == TRIG_TIMER)) {
+		/*  mode 2 */
+		devpriv->ui_AiTimer1 = cmd->scan_begin_arg;
+		devpriv->ui_AiTimer0 = cmd->convert_arg;	/*  variable changed timer2 to timer0 */
+		/* return this_board->ai_cmd(2,dev,s); */
+		return i_APCI3120_CyclicAnalogInput(2, dev, s);
+	}
+	return -1;
 }
 
 /*
-+----------------------------------------------------------------------------+
-| Function name     : int i_APCI3120_SetupChannelList(struct comedi_device * dev,   |
-|                     struct comedi_subdevice * s, int n_chan,unsigned int *chanlist|
-|			  ,char check)											 |
-|                                            						         |
-+----------------------------------------------------------------------------+
-| Task              :This function will first check channel list is ok or not|
-|and then initialize the sequence RAM with the polarity, Gain,Channel number |
-|If the last argument of function "check"is 1 then it only checks the channel|
-|list is ok or not.												     		 |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device * dev									 |
-|                     struct comedi_subdevice * s									 |
-|                     int n_chan                   					         |
-			  unsigned int *chanlist
-			  char check
-+----------------------------------------------------------------------------+
-| Return Value      :              					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
+ * This function copies the data from DMA buffer to the Comedi buffer.
+ */
+static void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,
+						  struct comedi_subdevice *s,
+						  short *dma_buffer,
+						  unsigned int num_samples)
+{
+	struct addi_private *devpriv = dev->private;
 
-int i_APCI3120_SetupChannelList(struct comedi_device *dev, struct comedi_subdevice *s,
-	int n_chan, unsigned int *chanlist, char check)
+	devpriv->ui_AiActualScan +=
+		(s->async->cur_chan + num_samples) / devpriv->ui_AiScanLength;
+	s->async->cur_chan += num_samples;
+	s->async->cur_chan %= devpriv->ui_AiScanLength;
+
+	cfc_write_array_to_buffer(s, dma_buffer, num_samples * sizeof(short));
+}
+
+/*
+ * This is a handler for the DMA interrupt.
+ * This function copies the data to Comedi Buffer.
+ * For continuous DMA it reinitializes the DMA operation.
+ * For single mode DMA it stop the acquisition.
+ */
+static void v_APCI3120_InterruptDma(int irq, void *d)
 {
-	unsigned int i;		/* , differencial=0, bipolar=0; */
-	unsigned int gain;
-	unsigned short us_TmpValue;
+	struct comedi_device *dev = d;
+	struct addi_private *devpriv = dev->private;
+	struct comedi_subdevice *s = &dev->subdevices[0];
+	unsigned int next_dma_buf, samplesinbuf;
+	unsigned long low_word, high_word, var;
+	unsigned int ui_Tmp;
 
-	/* correct channel and range number check itself comedi/range.c */
-	if (n_chan < 1) {
-		if (!check)
-			comedi_error(dev, "range/channel list is empty!");
-		return 0;
+	samplesinbuf =
+		devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer] -
+		inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_MWTC);
+
+	if (samplesinbuf <
+		devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer]) {
+		comedi_error(dev, "Interrupted DMA transfer!");
 	}
-	/*  All is ok, so we can setup channel/range list */
-	if (check)
-		return 1;
+	if (samplesinbuf & 1) {
+		comedi_error(dev, "Odd count of bytes in DMA ring!");
+		i_APCI3120_StopCyclicAcquisition(dev, s);
+		devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
 
-	/* Code  to set the PA and PR...Here it set PA to 0.. */
-	devpriv->us_OutputRegister =
-		devpriv->us_OutputRegister & APCI3120_CLEAR_PA_PR;
-	devpriv->us_OutputRegister = ((n_chan - 1) & 0xf) << 8;
-	outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
+		return;
+	}
+	samplesinbuf = samplesinbuf >> 1;	/*  number of received samples */
+	if (devpriv->b_DmaDoubleBuffer) {
+		/*  switch DMA buffers if is used double buffering */
+		next_dma_buf = 1 - devpriv->ui_DmaActualBuffer;
 
-	for (i = 0; i < n_chan; i++) {
-		/*  store range list to card */
-		us_TmpValue = CR_CHAN(chanlist[i]);	/*  get channel number; */
+		ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
+		outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS);
 
-		if (CR_RANGE(chanlist[i]) < APCI3120_BIPOLAR_RANGES)
-			us_TmpValue &= ((~APCI3120_UNIPOLAR) & 0xff);	/*  set bipolar */
-		else
-			us_TmpValue |= APCI3120_UNIPOLAR;	/*  enable unipolar...... */
+		/*  changed  since 16 bit interface for add on */
+		outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
+		outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
+			devpriv->i_IobaseAddon + 2);
+		outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
+		outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2);	/*  0x1000 is out putted in windows driver */
 
-		gain = CR_RANGE(chanlist[i]);	/*  get gain number */
-		us_TmpValue |= ((gain & 0x03) << 4);	/* <<4 for G0 and G1 bit in RAM */
-		us_TmpValue |= i << 8;	/* To select the RAM LOCATION.... */
-		outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS);
+		var = devpriv->ul_DmaBufferHw[next_dma_buf];
+		low_word = var & 0xffff;
+		var = devpriv->ul_DmaBufferHw[next_dma_buf];
+		high_word = var / 65536;
 
-		printk("\n Gain = %i",
-			(((unsigned char)CR_RANGE(chanlist[i]) & 0x03) << 2));
-		printk("\n Channel = %i", CR_CHAN(chanlist[i]));
-		printk("\n Polarity = %i", us_TmpValue & APCI3120_UNIPOLAR);
-	}
-	return 1;		/*  we can serve this with scan logic */
-}
+		/* DMA Start Address Low */
+		outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
+		outw(low_word, devpriv->i_IobaseAddon + 2);
+
+		/* DMA Start Address High */
+		outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
+		outw(high_word, devpriv->i_IobaseAddon + 2);
+
+		var = devpriv->ui_DmaBufferUsesize[next_dma_buf];
+		low_word = var & 0xffff;
+		var = devpriv->ui_DmaBufferUsesize[next_dma_buf];
+		high_word = var / 65536;
+
+		/* Nbr of acquisition LOW */
+		outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
+		outw(low_word, devpriv->i_IobaseAddon + 2);
+
+		/* Nbr of acquisition HIGH */
+		outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
+		outw(high_word, devpriv->i_IobaseAddon + 2);
 
 /*
-+----------------------------------------------------------------------------+
-| Function name     :	int i_APCI3120_ExttrigEnable(struct comedi_device * dev)    |
-|                                        									 |
-|                                            						         |
-+----------------------------------------------------------------------------+
-| Task              : 	Enable the external trigger						     |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : 	struct comedi_device * dev									 |
-|                     														 |
-|                                                 					         |
-+----------------------------------------------------------------------------+
-| Return Value      :      0        					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
+ * To configure A2P FIFO
+ * ENABLE A2P FIFO WRITE AND ENABLE AMWEN
+ * AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
+ */
+		outw(3, devpriv->i_IobaseAddon + 4);
+		/* initialise end of dma interrupt  AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) */
+		outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
+				APCI3120_ENABLE_WRITE_TC_INT),
+			devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
 
-int i_APCI3120_ExttrigEnable(struct comedi_device *dev)
-{
+	}
+	if (samplesinbuf) {
+		v_APCI3120_InterruptDmaMoveBlock16bit(dev, s,
+			devpriv->ul_DmaBufferVirtual[devpriv->
+				ui_DmaActualBuffer], samplesinbuf);
 
-	devpriv->us_OutputRegister |= APCI3120_ENABLE_EXT_TRIGGER;
-	outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
-	return 0;
-}
+		if (!(devpriv->ui_AiFlags & TRIG_WAKE_EOS)) {
+			s->async->events |= COMEDI_CB_EOS;
+			comedi_event(dev, s);
+		}
+	}
+	if (!devpriv->b_AiContinuous)
+		if (devpriv->ui_AiActualScan >= devpriv->ui_AiNbrofScans) {
+			/*  all data sampled */
+			i_APCI3120_StopCyclicAcquisition(dev, s);
+			devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
+			s->async->events |= COMEDI_CB_EOA;
+			comedi_event(dev, s);
+			return;
+		}
 
+	if (devpriv->b_DmaDoubleBuffer) {	/*  switch dma buffers */
+		devpriv->ui_DmaActualBuffer = 1 - devpriv->ui_DmaActualBuffer;
+	} else {
 /*
-+----------------------------------------------------------------------------+
-| Function name     : 	int i_APCI3120_ExttrigDisable(struct comedi_device * dev)   |
-|                                        									 |
-+----------------------------------------------------------------------------+
-| Task              : 	Disables the external trigger					     |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : 	struct comedi_device * dev									 |
-|                     														 |
-|                                                 					         |
-+----------------------------------------------------------------------------+
-| Return Value      :    0          					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
+ * restart DMA if is not used double buffering
+ * ADDED REINITIALISE THE DMA
+ */
+		ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
+		outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS);
 
-int i_APCI3120_ExttrigDisable(struct comedi_device *dev)
-{
-	devpriv->us_OutputRegister &= ~APCI3120_ENABLE_EXT_TRIGGER;
-	outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
-	return 0;
-}
+		/*  changed  since 16 bit interface for add on */
+		outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
+		outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
+			devpriv->i_IobaseAddon + 2);
+		outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
+		outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2);	/*  */
+/*
+ * A2P FIFO MANAGEMENT
+ * A2P fifo reset & transfer control enable
+ */
+		outl(APCI3120_A2P_FIFO_MANAGEMENT,
+			devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
+
+		var = devpriv->ul_DmaBufferHw[0];
+		low_word = var & 0xffff;
+		var = devpriv->ul_DmaBufferHw[0];
+		high_word = var / 65536;
+		outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
+		outw(low_word, devpriv->i_IobaseAddon + 2);
+		outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
+		outw(high_word, devpriv->i_IobaseAddon + 2);
+
+		var = devpriv->ui_DmaBufferUsesize[0];
+		low_word = var & 0xffff;	/* changed */
+		var = devpriv->ui_DmaBufferUsesize[0];
+		high_word = var / 65536;
+		outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
+		outw(low_word, devpriv->i_IobaseAddon + 2);
+		outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
+		outw(high_word, devpriv->i_IobaseAddon + 2);
 
 /*
-+----------------------------------------------------------------------------+
-|                    intERRUPT FUNCTIONS		    		                 |
-+----------------------------------------------------------------------------+
-*/
+ * To configure A2P FIFO
+ * ENABLE A2P FIFO WRITE AND ENABLE AMWEN
+ * AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
+ */
+		outw(3, devpriv->i_IobaseAddon + 4);
+		/* initialise end of dma interrupt  AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) */
+		outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
+				APCI3120_ENABLE_WRITE_TC_INT),
+			devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
+	}
+}
 
 /*
-+----------------------------------------------------------------------------+
-| Function name     : void v_APCI3120_Interrupt(int irq, void *d) 								 |
-|                                        									 |
-|                                            						         |
-+----------------------------------------------------------------------------+
-| Task              :Interrupt handler for APCI3120                        	 |
-|			 When interrupt occurs this gets called.                 |
-|			 First it finds which interrupt has been generated and   |
-|			 handles  corresponding interrupt                        |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : 	int irq 											 |
-|                        void *d											 |
-|                                                 					         |
-+----------------------------------------------------------------------------+
-| Return Value      : void         					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
+ * This function handles EOS interrupt.
+ * This function copies the acquired data(from FIFO) to Comedi buffer.
+ */
+static int i_APCI3120_InterruptHandleEos(struct comedi_device *dev)
+{
+	struct addi_private *devpriv = dev->private;
+	int n_chan, i;
+	struct comedi_subdevice *s = &dev->subdevices[0];
+	int err = 1;
+
+	n_chan = devpriv->ui_AiNbrofChannels;
+
+	s->async->events = 0;
+
+	for (i = 0; i < n_chan; i++)
+		err &= comedi_buf_put(s->async, inw(dev->iobase + 0));
+
+	s->async->events |= COMEDI_CB_EOS;
+
+	if (err == 0)
+		s->async->events |= COMEDI_CB_OVERFLOW;
 
-void v_APCI3120_Interrupt(int irq, void *d)
+	comedi_event(dev, s);
+
+	return 0;
+}
+
+static void v_APCI3120_Interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct addi_private *devpriv = dev->private;
 	unsigned short int_daq;
-
 	unsigned int int_amcc, ui_Check, i;
 	unsigned short us_TmpValue;
 	unsigned char b_DummyRead;
-
 	struct comedi_subdevice *s = &dev->subdevices[0];
+
 	ui_Check = 1;
 
 	int_daq = inw(dev->iobase + APCI3120_RD_STATUS) & 0xf000;	/*  get IRQ reasons */
@@ -1561,325 +1747,61 @@ void v_APCI3120_Interrupt(int irq, void *d)
 			devpriv->b_ModeSelectRegister =
 				devpriv->
 				b_ModeSelectRegister &
-				APCI3120_DISABLE_TIMER_INT;
-
-			outb(devpriv->b_ModeSelectRegister,
-				dev->iobase + APCI3120_WRITE_MODE_SELECT);
-
-		}
-
-		b_DummyRead = inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
-
-	}
-
-	if ((int_daq & 0x4) && (devpriv->b_InterruptMode == APCI3120_DMA_MODE)) {
-		if (devpriv->b_AiCyclicAcquisition == APCI3120_ENABLE) {
-
-			/****************************/
-			/* Clear Timer Write TC int */
-			/****************************/
-
-			outl(APCI3120_CLEAR_WRITE_TC_INT,
-				devpriv->i_IobaseAmcc +
-				APCI3120_AMCC_OP_REG_INTCSR);
-
-			/************************************/
-			/* Clears the timer status register */
-			/************************************/
-			inw(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
-			v_APCI3120_InterruptDma(irq, d);	/*  do some data transfer */
-		} else {
-			/* Stops the Timer */
-			outw(devpriv->
-				us_OutputRegister & APCI3120_DISABLE_TIMER0 &
-				APCI3120_DISABLE_TIMER1,
-				dev->iobase + APCI3120_WR_ADDRESS);
-		}
-
-	}
-
-	return;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3120_InterruptHandleEos(struct comedi_device *dev)   |
-|                                        									 |
-|                                            						         |
-+----------------------------------------------------------------------------+
-| Task              : This function handles EOS interrupt.                   |
-|                     This function copies the acquired data(from FIFO)      |
-|				to Comedi buffer.		 							 |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev									 |
-|                     														 |
-|                                                 					         |
-+----------------------------------------------------------------------------+
-| Return Value      : 0            					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-
-int i_APCI3120_InterruptHandleEos(struct comedi_device *dev)
-{
-	int n_chan, i;
-	struct comedi_subdevice *s = &dev->subdevices[0];
-	int err = 1;
-
-	n_chan = devpriv->ui_AiNbrofChannels;
-
-	s->async->events = 0;
-
-	for (i = 0; i < n_chan; i++)
-		err &= comedi_buf_put(s->async, inw(dev->iobase + 0));
-
-	s->async->events |= COMEDI_CB_EOS;
-
-	if (err == 0)
-		s->async->events |= COMEDI_CB_OVERFLOW;
-
-	comedi_event(dev, s);
-
-	return 0;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function name     : void v_APCI3120_InterruptDma(int irq, void *d) 									 |
-|                                        									 |
-+----------------------------------------------------------------------------+
-| Task              : This is a handler for the DMA interrupt                |
-|			  This function copies the data to Comedi Buffer.        |
-|			  For continuous DMA it reinitializes the DMA operation. |
-|			  For single mode DMA it stop the acquisition.           |
-|													     			 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : int irq, void *d				 |
-|                     														 |
-+----------------------------------------------------------------------------+
-| Return Value      :  void        					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-void v_APCI3120_InterruptDma(int irq, void *d)
-{
-	struct comedi_device *dev = d;
-	struct comedi_subdevice *s = &dev->subdevices[0];
-	unsigned int next_dma_buf, samplesinbuf;
-	unsigned long low_word, high_word, var;
-
-	unsigned int ui_Tmp;
-	samplesinbuf =
-		devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer] -
-		inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_MWTC);
-
-	if (samplesinbuf <
-		devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer]) {
-		comedi_error(dev, "Interrupted DMA transfer!");
-	}
-	if (samplesinbuf & 1) {
-		comedi_error(dev, "Odd count of bytes in DMA ring!");
-		i_APCI3120_StopCyclicAcquisition(dev, s);
-		devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
-
-		return;
-	}
-	samplesinbuf = samplesinbuf >> 1;	/*  number of received samples */
-	if (devpriv->b_DmaDoubleBuffer) {
-		/*  switch DMA buffers if is used double buffering */
-		next_dma_buf = 1 - devpriv->ui_DmaActualBuffer;
-
-		ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
-		outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS);
-
-		/*  changed  since 16 bit interface for add on */
-		outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
-		outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
-			devpriv->i_IobaseAddon + 2);
-		outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
-		outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2);	/*  0x1000 is out putted in windows driver */
-
-		var = devpriv->ul_DmaBufferHw[next_dma_buf];
-		low_word = var & 0xffff;
-		var = devpriv->ul_DmaBufferHw[next_dma_buf];
-		high_word = var / 65536;
-
-		/* DMA Start Address Low */
-		outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
-		outw(low_word, devpriv->i_IobaseAddon + 2);
-
-		/* DMA Start Address High */
-		outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
-		outw(high_word, devpriv->i_IobaseAddon + 2);
-
-		var = devpriv->ui_DmaBufferUsesize[next_dma_buf];
-		low_word = var & 0xffff;
-		var = devpriv->ui_DmaBufferUsesize[next_dma_buf];
-		high_word = var / 65536;
-
-		/* Nbr of acquisition LOW */
-		outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
-		outw(low_word, devpriv->i_IobaseAddon + 2);
-
-		/* Nbr of acquisition HIGH */
-		outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
-		outw(high_word, devpriv->i_IobaseAddon + 2);
-
-/*
- * To configure A2P FIFO
- * ENABLE A2P FIFO WRITE AND ENABLE AMWEN
- * AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
- */
-		outw(3, devpriv->i_IobaseAddon + 4);
-		/* initialise end of dma interrupt  AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) */
-		outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
-				APCI3120_ENABLE_WRITE_TC_INT),
-			devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
-
-	}
-	if (samplesinbuf) {
-		v_APCI3120_InterruptDmaMoveBlock16bit(dev, s,
-			devpriv->ul_DmaBufferVirtual[devpriv->
-				ui_DmaActualBuffer], samplesinbuf);
-
-		if (!(devpriv->ui_AiFlags & TRIG_WAKE_EOS)) {
-			s->async->events |= COMEDI_CB_EOS;
-			comedi_event(dev, s);
-		}
-	}
-	if (!devpriv->b_AiContinuous)
-		if (devpriv->ui_AiActualScan >= devpriv->ui_AiNbrofScans) {
-			/*  all data sampled */
-			i_APCI3120_StopCyclicAcquisition(dev, s);
-			devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
-			s->async->events |= COMEDI_CB_EOA;
-			comedi_event(dev, s);
-			return;
+				APCI3120_DISABLE_TIMER_INT;
+
+			outb(devpriv->b_ModeSelectRegister,
+				dev->iobase + APCI3120_WRITE_MODE_SELECT);
+
 		}
 
-	if (devpriv->b_DmaDoubleBuffer) {	/*  switch dma buffers */
-		devpriv->ui_DmaActualBuffer = 1 - devpriv->ui_DmaActualBuffer;
-	} else {
-/*
- * restart DMA if is not used double buffering
- * ADDED REINITIALISE THE DMA
- */
-		ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
-		outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS);
+		b_DummyRead = inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
 
-		/*  changed  since 16 bit interface for add on */
-		outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
-		outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
-			devpriv->i_IobaseAddon + 2);
-		outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
-		outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2);	/*  */
-/*
- * A2P FIFO MANAGEMENT
- * A2P fifo reset & transfer control enable
- */
-		outl(APCI3120_A2P_FIFO_MANAGEMENT,
-			devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
+	}
 
-		var = devpriv->ul_DmaBufferHw[0];
-		low_word = var & 0xffff;
-		var = devpriv->ul_DmaBufferHw[0];
-		high_word = var / 65536;
-		outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
-		outw(low_word, devpriv->i_IobaseAddon + 2);
-		outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
-		outw(high_word, devpriv->i_IobaseAddon + 2);
+	if ((int_daq & 0x4) && (devpriv->b_InterruptMode == APCI3120_DMA_MODE)) {
+		if (devpriv->b_AiCyclicAcquisition == APCI3120_ENABLE) {
 
-		var = devpriv->ui_DmaBufferUsesize[0];
-		low_word = var & 0xffff;	/* changed */
-		var = devpriv->ui_DmaBufferUsesize[0];
-		high_word = var / 65536;
-		outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
-		outw(low_word, devpriv->i_IobaseAddon + 2);
-		outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
-		outw(high_word, devpriv->i_IobaseAddon + 2);
+			/****************************/
+			/* Clear Timer Write TC int */
+			/****************************/
 
-/*
- * To configure A2P FIFO
- * ENABLE A2P FIFO WRITE AND ENABLE AMWEN
- * AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03
- */
-		outw(3, devpriv->i_IobaseAddon + 4);
-		/* initialise end of dma interrupt  AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) */
-		outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
-				APCI3120_ENABLE_WRITE_TC_INT),
-			devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
-	}
-}
+			outl(APCI3120_CLEAR_WRITE_TC_INT,
+				devpriv->i_IobaseAmcc +
+				APCI3120_AMCC_OP_REG_INTCSR);
 
-/*
-+----------------------------------------------------------------------------+
-| Function name     :void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device|
-|*dev,struct comedi_subdevice *s,short *dma,short *data,int n)				     |
-|                                        									 |
-+----------------------------------------------------------------------------+
-| Task              : This function copies the data from DMA buffer to the   |
-|				 Comedi buffer  									 |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev									 |
-|                     struct comedi_subdevice *s									 |
-|                     short *dma											 |
-|                     short *data,int n          					         |
-+----------------------------------------------------------------------------+
-| Return Value      : void         					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
+			/************************************/
+			/* Clears the timer status register */
+			/************************************/
+			inw(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
+			v_APCI3120_InterruptDma(irq, d);	/*  do some data transfer */
+		} else {
+			/* Stops the Timer */
+			outw(devpriv->
+				us_OutputRegister & APCI3120_DISABLE_TIMER0 &
+				APCI3120_DISABLE_TIMER1,
+				dev->iobase + APCI3120_WR_ADDRESS);
+		}
 
-void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,
-	struct comedi_subdevice *s, short *dma_buffer, unsigned int num_samples)
-{
-	devpriv->ui_AiActualScan +=
-		(s->async->cur_chan + num_samples) / devpriv->ui_AiScanLength;
-	s->async->cur_chan += num_samples;
-	s->async->cur_chan %= devpriv->ui_AiScanLength;
+	}
 
-	cfc_write_array_to_buffer(s, dma_buffer, num_samples * sizeof(short));
+	return;
 }
 
 /*
-+----------------------------------------------------------------------------+
-|                           TIMER SUBDEVICE   		                         |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3120_InsnConfigTimer(struct comedi_device *dev,          |
-|	struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) 			     |
-|                                        									 |
-+----------------------------------------------------------------------------+
-| Task              :Configure Timer 2  								     |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev									 |
-|                     struct comedi_subdevice *s									 |
-|                     struct comedi_insn *insn                                      |
-|                     unsigned int *data 										 |
-|                     														 |
-|                      data[0]= TIMER  configure as timer                    |
-|              				 = WATCHDOG configure as watchdog				 |
-|       			  data[1] = Timer constant							 |
-|       			  data[2] = Timer2 interrupt (1)enable or(0) disable |
-|                                                 					         |
-+----------------------------------------------------------------------------+
-| Return Value      :              					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+ * Configure Timer 2
+ *
+ * data[0] = TIMER configure as timer
+ *	   = WATCHDOG configure as watchdog
+ * data[1] = Timer constant
+ * data[2] = Timer2 interrupt (1)enable or(0) disable
+ */
+static int i_APCI3120_InsnConfigTimer(struct comedi_device *dev,
+				      struct comedi_subdevice *s,
+				      struct comedi_insn *insn,
+				      unsigned int *data)
 {
-
+	const struct addi_board *this_board = comedi_board(dev);
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_Timervalue2;
 	unsigned short us_TmpValue;
 	unsigned char b_Tmp;
@@ -2007,37 +1929,24 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevic
 }
 
 /*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3120_InsnWriteTimer(struct comedi_device *dev,           |
-|                    struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data)  |
-|                                            						         |
-+----------------------------------------------------------------------------+
-| Task              :    To start and stop the timer		                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev									 |
-|                     struct comedi_subdevice *s									 |
-|                     struct comedi_insn *insn                                      |
-|                     unsigned int *data                                         |
-|                                                                            |
-|				data[0] = 1 (start)                                  |
-|				data[0] = 0 (stop )                                  |
-|	 			data[0] = 2  (write new value)                       |
-|	   			data[1]= new value                                   |
-|                                                                            |
-|    				devpriv->b_Timer2Mode =  0 DISABLE                   |
-|	                     					 1 Timer                     |
-|					 					 2 Watch dog			     |
-|                                                 					         |
-+----------------------------------------------------------------------------+
-| Return Value      :              					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+ * To start and stop the timer
+ *
+ * data[0] = 1 (start)
+ *	   = 0 (stop)
+ *	   = 2 (write new value)
+ * data[1] = new value
+ *
+ * devpriv->b_Timer2Mode = 0 DISABLE
+ *			 = 1 Timer
+ *			 = 2 Watch dog
+ */
+static int i_APCI3120_InsnWriteTimer(struct comedi_device *dev,
+				     struct comedi_subdevice *s,
+				     struct comedi_insn *insn,
+				     unsigned int *data)
 {
-
+	const struct addi_board *this_board = comedi_board(dev);
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_Timervalue2 = 0;
 	unsigned short us_TmpValue;
 	unsigned char b_Tmp;
@@ -2196,31 +2105,19 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice
 }
 
 /*
-+----------------------------------------------------------------------------+
-| Function name     : int i_APCI3120_InsnReadTimer(struct comedi_device *dev,           |
-|		struct comedi_subdevice *s,struct comedi_insn *insn, unsigned int *data) 		 |
-|                                        									 |
-|                                            						         |
-+----------------------------------------------------------------------------+
-| Task              : read the Timer value 				                 	 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : 	struct comedi_device *dev									 |
-|                     struct comedi_subdevice *s									 |
-|                     struct comedi_insn *insn                                      |
-|                     unsigned int *data 										 |
-|                     														 |
-+----------------------------------------------------------------------------+
-| Return Value      :   													 |
-|			for Timer:	data[0]= Timer constant						 |
-|																	 |
-|         		for watchdog: data[0]=0 (still running)                  |
-|	               			  data[0]=1  (run down)            			 |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI3120_InsnReadTimer(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+ * Read the Timer value
+ *
+ * for Timer: data[0]= Timer constant
+ *
+ * for watchdog: data[0] = 0 (still running)
+ *			 = 1 (run down)
+ */
+static int i_APCI3120_InsnReadTimer(struct comedi_device *dev,
+				    struct comedi_subdevice *s,
+				    struct comedi_insn *insn,
+				    unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned char b_Tmp;
 	unsigned short us_TmpValue, us_TmpValue_2, us_StatusValue;
 
@@ -2265,299 +2162,52 @@ int i_APCI3120_InsnReadTimer(struct comedi_device *dev, struct comedi_subdevice
 	return insn->n;
 }
 
-/*
-+----------------------------------------------------------------------------+
-|                           DIGITAL INPUT SUBDEVICE   		                 |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,     |
-|			struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data)   |
-|                                        									 |
-|                                            						         |
-+----------------------------------------------------------------------------+
-| Task              : Reads the value of the specified  Digital input channel|
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev									 |
-|                     struct comedi_subdevice *s									 |
-|                     struct comedi_insn *insn                                      |
-|                     unsigned int *data 										 |
-+----------------------------------------------------------------------------+
-| Return Value      :              					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
-				    struct comedi_subdevice *s,
-				    struct comedi_insn *insn,
-				    unsigned int *data)
-{
-	unsigned int ui_Chan, ui_TmpValue;
-
-	ui_Chan = CR_CHAN(insn->chanspec);	/*  channel specified */
-
-	/* this_board->di_read(dev,ui_Chan,data); */
-	if (ui_Chan <= 3) {
-		ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI3120_RD_STATUS);
-
-/*
- * since only 1 channel reqd to bring it to last bit it is rotated 8
- * +(chan - 1) times then ANDed with 1 for last bit.
- */
-		*data = (ui_TmpValue >> (ui_Chan + 8)) & 1;
-		/* return 0; */
-	} else {
-		/*       comedi_error(dev," chan spec wrong"); */
-		return -EINVAL;	/*  "sorry channel spec wrong " */
-	}
-	return insn->n;
-
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, |
-|struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data)                      |
-|                                        									 |
-+----------------------------------------------------------------------------+
-| Task              : Reads the value of the Digital input Port i.e.4channels|
-|   value is returned in data[0]											 |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev									 |
-|                     struct comedi_subdevice *s									 |
-|                     struct comedi_insn *insn                                      |
-|                     unsigned int *data 										 |
-+----------------------------------------------------------------------------+
-| Return Value      :              					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int ui_TmpValue;
-	ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI3120_RD_STATUS);
-	/*****	state of 4 channels  in the 11, 10, 9, 8   bits of status reg
-			rotated right 8 times to bring them to last four bits
-			ANDed with oxf for  value.
-	*****/
-
-	*data = (ui_TmpValue >> 8) & 0xf;
-	/* this_board->di_bits(dev,data); */
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-|                           DIGITAL OUTPUT SUBDEVICE   		                 |
-+----------------------------------------------------------------------------+
-*/
-/*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device    |
-| *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)				 |
-|                                            						         |
-+----------------------------------------------------------------------------+
-| Task              :Configure the output memory ON or OFF				     |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  :struct comedi_device *dev									 	 |
-|                     struct comedi_subdevice *s									 |
-|                     struct comedi_insn *insn                                      |
-|                     unsigned int *data 										 |
-+----------------------------------------------------------------------------+
-| Return Value      :              					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
-{
-
-	if ((data[0] != 0) && (data[0] != 1)) {
-		comedi_error(dev,
-			"Not a valid Data !!! ,Data should be 1 or 0\n");
-		return -EINVAL;
-	}
-	if (data[0]) {
-		devpriv->b_OutputMemoryStatus = APCI3120_ENABLE;
-
-	} else {
-		devpriv->b_OutputMemoryStatus = APCI3120_DISABLE;
-		devpriv->b_DigitalOutputRegister = 0;
-	}
-	if (!devpriv->b_OutputMemoryStatus)
-		ui_Temp = 0;
-				/* if(!devpriv->b_OutputMemoryStatus ) */
-
-	return insn->n;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev,    |
-|		struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) 		 |
-|                                        									 |
-+----------------------------------------------------------------------------+
-| Task              : write diatal output port							     |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev									 |
-|                     struct comedi_subdevice *s									 |
-|                     struct comedi_insn *insn                                      |
-|                     unsigned int *data 										 |
-|                      data[0]     Value to be written
-|                      data[1]    :1 Set digital o/p ON
-|                      data[1]     2 Set digital o/p OFF with memory ON
-+----------------------------------------------------------------------------+
-| Return Value      :              					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev,
-				     struct comedi_subdevice *s,
-				     struct comedi_insn *insn,
-				     unsigned int *data)
+static int apci3120_di_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	if ((data[0] > devpriv->s_EeParameters.i_DoMaxdata) || (data[0] < 0)) {
-
-		comedi_error(dev, "Data is not valid !!! \n");
-		return -EINVAL;
-	}
-
-	switch (data[1]) {
-	case 1:
-		data[0] = (data[0] << 4) | devpriv->b_DigitalOutputRegister;
-		break;
-
-	case 2:
-		data[0] = data[0];
-		break;
-	default:
-		printk("\nThe parameter passed is in error \n");
-		return -EINVAL;
-	}			/*  switch(data[1]) */
-	outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
+	struct addi_private *devpriv = dev->private;
+	unsigned int val;
 
-	devpriv->b_DigitalOutputRegister = data[0] & 0xF0;
+	/* the input channels are bits 11:8 of the status reg */
+	val = inw(devpriv->iobase + APCI3120_RD_STATUS);
+	data[1] = (val >> 8) & 0xf;
 
 	return insn->n;
-
 }
 
-/*
-+----------------------------------------------------------------------------+
-| Function name		:int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,|
-|struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)	|
-|										|
-+----------------------------------------------------------------------------+
-| Task			: Write digiatl output					|
-| 										|
-+----------------------------------------------------------------------------+
-| Input Parameters	: struct comedi_device *dev				|
-|			struct comedi_subdevice *s			 	|
-|			struct comedi_insn *insn				|
-|			unsigned int *data					|
-			data[0]     Value to be written
-			data[1]    :1 Set digital o/p ON
-			data[1]     2 Set digital o/p OFF with memory ON
-+----------------------------------------------------------------------------+
-| Return Value		:							|
-|										|
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,
-				      struct comedi_subdevice *s,
-				      struct comedi_insn *insn,
-				      unsigned int *data)
+static int apci3120_do_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-
-	unsigned int ui_Temp1;
-
-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
-
-	if ((data[0] != 0) && (data[0] != 1)) {
-		comedi_error(dev,
-			"Not a valid Data !!! ,Data should be 1 or 0\n");
-		return -EINVAL;
-	}
-	if (ui_NoOfChannel > devpriv->s_EeParameters.i_NbrDoChannel - 1) {
-		comedi_error(dev,
-			"This board doesn't have specified channel !!! \n");
-		return -EINVAL;
+	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;
+
+		outb(val << 4, devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
 	}
 
-	switch (data[1]) {
-	case 1:
-		data[0] = (data[0] << ui_NoOfChannel);
-/* ES05                   data[0]=(data[0]<<4)|ui_Temp; */
-		data[0] = (data[0] << 4) | devpriv->b_DigitalOutputRegister;
-		break;
-
-	case 2:
-		data[0] = ~data[0] & 0x1;
-		ui_Temp1 = 1;
-		ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
-		ui_Temp1 = ui_Temp1 << 4;
-/* ES05                   ui_Temp=ui_Temp|ui_Temp1; */
-		devpriv->b_DigitalOutputRegister =
-			devpriv->b_DigitalOutputRegister | ui_Temp1;
-
-		data[0] = (data[0] << ui_NoOfChannel) ^ 0xf;
-		data[0] = data[0] << 4;
-/* ES05                   data[0]=data[0]& ui_Temp; */
-		data[0] = data[0] & devpriv->b_DigitalOutputRegister;
-		break;
-	default:
-		printk("\nThe parameter passed is in error \n");
-		return -EINVAL;
-	}			/*  switch(data[1]) */
-	outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
+	data[1] = val;
 
-/* ES05        ui_Temp=data[0] & 0xf0; */
-	devpriv->b_DigitalOutputRegister = data[0] & 0xf0;
 	return insn->n;
-
 }
 
-/*
-+----------------------------------------------------------------------------+
-|                            ANALOG OUTPUT SUBDEVICE                         |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,|
-|struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data)			             |
-|                                        									 |
-+----------------------------------------------------------------------------+
-| Task              : Write  analog output   							     |
-|                     										                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev									 |
-|                     struct comedi_subdevice *s									 |
-|                     struct comedi_insn *insn                                      |
-|                     unsigned int *data  										 |
-+----------------------------------------------------------------------------+
-| Return Value      :              					                         |
-|                    													     |
-+----------------------------------------------------------------------------+
-*/
-
-int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
-				     struct comedi_subdevice *s,
-				     struct comedi_insn *insn,
-				     unsigned int *data)
+static int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
+					    struct comedi_subdevice *s,
+					    struct comedi_insn *insn,
+					    unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_Range, ui_Channel;
 	unsigned short us_TmpValue;
 
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
deleted file mode 100644
index 50eb0a0..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h
+++ /dev/null
@@ -1,249 +0,0 @@
-
-/* hwdrv_apci3120.h */
-
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/* comedi related defines */
-
-/* ANALOG INPUT RANGE */
-static const struct comedi_lrange range_apci3120_ai = { 8, {
-						     BIP_RANGE(10),
-						     BIP_RANGE(5),
-						     BIP_RANGE(2),
-						     BIP_RANGE(1),
-						     UNI_RANGE(10),
-						     UNI_RANGE(5),
-						     UNI_RANGE(2),
-						     UNI_RANGE(1)
-						     }
-};
-
-/* ANALOG OUTPUT RANGE */
-static const struct comedi_lrange range_apci3120_ao = { 2, {
-						     BIP_RANGE(10),
-						     UNI_RANGE(10)
-						     }
-};
-
-#define APCI3120_BIPOLAR_RANGES	4	/*  used for test on mixture of BIP/UNI ranges */
-
-#define APCI3120_BOARD_VENDOR_ID                 0x10E8
-#define APCI3120_ADDRESS_RANGE            			16
-
-#define APCI3120_DISABLE                         0
-#define APCI3120_ENABLE                          1
-
-#define APCI3120_START                           1
-#define APCI3120_STOP                            0
-
-#define     APCI3120_EOC_MODE         1
-#define     APCI3120_EOS_MODE         2
-#define     APCI3120_DMA_MODE         3
-
-/* DIGITAL INPUT-OUTPUT DEFINE */
-
-#define APCI3120_DIGITAL_OUTPUT                  	0x0D
-#define APCI3120_RD_STATUS                       	0x02
-#define APCI3120_RD_FIFO                     		0x00
-
-/* digital output insn_write ON /OFF selection */
-#define	APCI3120_SET4DIGITALOUTPUTON				1
-#define APCI3120_SET4DIGITALOUTPUTOFF				0
-
-/* analog output SELECT BIT */
-#define APCI3120_ANALOG_OP_CHANNEL_1   0x0000
-#define APCI3120_ANALOG_OP_CHANNEL_2   0x4000
-#define APCI3120_ANALOG_OP_CHANNEL_3   0x8000
-#define APCI3120_ANALOG_OP_CHANNEL_4   0xC000
-#define APCI3120_ANALOG_OP_CHANNEL_5   0x0000
-#define APCI3120_ANALOG_OP_CHANNEL_6   0x4000
-#define APCI3120_ANALOG_OP_CHANNEL_7   0x8000
-#define APCI3120_ANALOG_OP_CHANNEL_8   0xC000
-
-/* Enable external trigger bit in nWrAddress */
-#define APCI3120_ENABLE_EXT_TRIGGER    0x8000
-
-/* ANALOG OUTPUT AND INPUT DEFINE */
-#define APCI3120_UNIPOLAR 0x80	/* $$ RAM sequence polarity BIT */
-#define APCI3120_BIPOLAR  0x00	/* $$ RAM sequence polarity BIT */
-#define APCI3120_ANALOG_OUTPUT_1 0x08	/*  (ADDRESS ) */
-#define APCI3120_ANALOG_OUTPUT_2 0x0A	/*  (ADDRESS ) */
-#define APCI3120_1_GAIN              0x00	/* $$ RAM sequence Gain Bits for gain 1 */
-#define APCI3120_2_GAIN              0x10	/* $$ RAM sequence Gain Bits for gain 2 */
-#define APCI3120_5_GAIN              0x20	/* $$ RAM sequence Gain Bits for gain 5 */
-#define APCI3120_10_GAIN             0x30	/* $$ RAM sequence Gain Bits for gain 10 */
-#define APCI3120_SEQ_RAM_ADDRESS        0x06	/* $$ EARLIER NAMED APCI3120_FIFO_ADDRESS */
-#define APCI3120_RESET_FIFO          0x0C	/* (ADDRESS) */
-#define APCI3120_TIMER_0_MODE_2      0x01	/* $$ Bits for timer mode */
-#define APCI3120_TIMER_0_MODE_4       0x2
-#define APCI3120_SELECT_TIMER_0_WORD 0x00
-#define APCI3120_ENABLE_TIMER0     0x1000	/* $$Gatebit 0 in nWrAddress */
-#define APCI3120_CLEAR_PR          0xF0FF
-#define APCI3120_CLEAR_PA          0xFFF0
-#define APCI3120_CLEAR_PA_PR       (APCI3120_CLEAR_PR & APCI3120_CLEAR_PA)
-
-/* nWrMode_Select */
-#define APCI3120_ENABLE_SCAN          0x8	/* $$ bit in nWrMode_Select */
-#define APCI3120_DISABLE_SCAN      (~APCI3120_ENABLE_SCAN)
-#define APCI3120_ENABLE_EOS_INT       0x2	/* $$ bit in nWrMode_Select */
-
-#define APCI3120_DISABLE_EOS_INT   (~APCI3120_ENABLE_EOS_INT)
-#define APCI3120_ENABLE_EOC_INT       0x1
-#define APCI3120_DISABLE_EOC_INT   (~APCI3120_ENABLE_EOC_INT)
-#define APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER   (APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT)
-#define APCI3120_DISABLE_ALL_INTERRUPT   (APCI3120_DISABLE_TIMER_INT & APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT)
-
-/* status register bits */
-#define APCI3120_EOC                     0x8000
-#define APCI3120_EOS                     0x2000
-
-/* software trigger dummy register */
-#define APCI3120_START_CONVERSION        0x02	/* (ADDRESS) */
-
-/* TIMER DEFINE */
-#define APCI3120_QUARTZ_A				  70
-#define APCI3120_QUARTZ_B				  50
-#define APCI3120_TIMER                            1
-#define APCI3120_WATCHDOG                         2
-#define APCI3120_TIMER_DISABLE                    0
-#define APCI3120_TIMER_ENABLE                     1
-#define APCI3120_ENABLE_TIMER2                    0x4000	/* $$ gatebit 2 in nWrAddress */
-#define APCI3120_DISABLE_TIMER2                   (~APCI3120_ENABLE_TIMER2)
-#define APCI3120_ENABLE_TIMER_INT                 0x04	/* $$ ENAIRQ_FC_Bit in nWrModeSelect */
-#define APCI3120_DISABLE_TIMER_INT                (~APCI3120_ENABLE_TIMER_INT)
-#define APCI3120_WRITE_MODE_SELECT                0x0E	/*  (ADDRESS) */
-#define APCI3120_SELECT_TIMER_0_WORD  0x00
-#define APCI3120_SELECT_TIMER_1_WORD  0x01
-#define APCI3120_TIMER_1_MODE_2       0x4
-
-/* $$ BIT FOR MODE IN nCsTimerCtr1 */
-#define APCI3120_TIMER_2_MODE_0                   0x0
-#define APCI3120_TIMER_2_MODE_2                   0x10
-#define APCI3120_TIMER_2_MODE_5                   0x30
-
-/* $$ BIT FOR MODE IN nCsTimerCtr0 */
-#define APCI3120_SELECT_TIMER_2_LOW_WORD          0x02
-#define APCI3120_SELECT_TIMER_2_HIGH_WORD         0x03
-
-#define APCI3120_TIMER_CRT0                       0x0D	/* (ADDRESS for cCsTimerCtr0) */
-#define APCI3120_TIMER_CRT1                       0x0C	/* (ADDRESS for cCsTimerCtr1) */
-
-#define APCI3120_TIMER_VALUE                      0x04	/* ADDRESS for nCsTimerWert */
-#define APCI3120_TIMER_STATUS_REGISTER            0x0D	/* ADDRESS for delete timer 2 interrupt */
-#define APCI3120_RD_STATUS                        0x02	/* ADDRESS */
-#define APCI3120_WR_ADDRESS                       0x00	/* ADDRESS */
-#define APCI3120_ENABLE_WATCHDOG                  0x20	/* $$BIT in nWrMode_Select */
-#define APCI3120_DISABLE_WATCHDOG                 (~APCI3120_ENABLE_WATCHDOG)
-#define APCI3120_ENABLE_TIMER_COUNTER    		  0x10	/* $$BIT in nWrMode_Select */
-#define APCI3120_DISABLE_TIMER_COUNTER            (~APCI3120_ENABLE_TIMER_COUNTER)
-#define APCI3120_FC_TIMER                         0x1000	/* bit in  status register */
-#define APCI3120_ENABLE_TIMER0                    0x1000
-#define APCI3120_ENABLE_TIMER1                    0x2000
-#define APCI3120_ENABLE_TIMER2                    0x4000
-#define APCI3120_DISABLE_TIMER0			          (~APCI3120_ENABLE_TIMER0)
-#define APCI3120_DISABLE_TIMER1		              (~APCI3120_ENABLE_TIMER1)
-#define APCI3120_DISABLE_TIMER2	                  (~APCI3120_ENABLE_TIMER2)
-
-#define APCI3120_TIMER2_SELECT_EOS                0xC0	/*  ADDED on 20-6 */
-#define APCI3120_COUNTER                          3	/*  on 20-6 */
-#define APCI3120_DISABLE_ALL_TIMER                (APCI3120_DISABLE_TIMER0 & APCI3120_DISABLE_TIMER1 & APCI3120_DISABLE_TIMER2)	/*  on 20-6 */
-
-#define MAX_ANALOGINPUT_CHANNELS    32
-
-struct str_AnalogReadInformation {
-
-	unsigned char b_Type;		/* EOC or EOS */
-	unsigned char b_InterruptFlag;	/* Interrupt use or not                    */
-	unsigned int ui_ConvertTiming;	/* Selection of the conversion time        */
-	unsigned char b_NbrOfChannel;	/* Number of channel to read               */
-	unsigned int ui_ChannelList[MAX_ANALOGINPUT_CHANNELS];	/* Number of the channel to be read        */
-	unsigned int ui_RangeList[MAX_ANALOGINPUT_CHANNELS];	/* Gain of each channel                    */
-
-};
-
-
-/* Function Declaration For APCI-3120 */
-
-/* Internal functions */
-int i_APCI3120_SetupChannelList(struct comedi_device *dev, struct comedi_subdevice *s,
-				int n_chan, unsigned int *chanlist, char check);
-int i_APCI3120_ExttrigEnable(struct comedi_device *dev);
-int i_APCI3120_ExttrigDisable(struct comedi_device *dev);
-int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
-int i_APCI3120_Reset(struct comedi_device *dev);
-int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
-				 struct comedi_subdevice *s);
-/* Interrupt functions */
-void v_APCI3120_Interrupt(int irq, void *d);
-/* UPDATE-0.7.57->0.7.68 void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,struct comedi_subdevice *s,short *dma,short *data,int n); */
-void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,
-					   struct comedi_subdevice *s,
-					   short *dma_buffer,
-					   unsigned int num_samples);
-int i_APCI3120_InterruptHandleEos(struct comedi_device *dev);
-void v_APCI3120_InterruptDma(int irq, void *d);
-
-/* TIMER */
-
-int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data);
-int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data);
-int i_APCI3120_InsnReadTimer(struct comedi_device *dev, struct comedi_subdevice *s,
-			     struct comedi_insn *insn, unsigned int *data);
-
-/*
-* DI for di read
-*/
-
-int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				    struct comedi_insn *insn, unsigned int *data);
-int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				    struct comedi_insn *insn, unsigned int *data);
-
-/* DO */
-/* int i_APCI3120_WriteDigitalOutput(struct comedi_device *dev,
- * unsigned char data);
- */
-int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device *dev,
-				       struct comedi_subdevice *s, struct comedi_insn *insn,
-				       unsigned int *data);
-int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				     struct comedi_insn *insn, unsigned int *data);
-int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				      struct comedi_insn *insn, unsigned int *data);
-
-/* AO */
-/* int i_APCI3120_Write1AnalogValue(struct comedi_device *dev,UINT ui_Range,
- * UINT ui_Channel,UINT data );
- */
-
-int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				     struct comedi_insn *insn, unsigned int *data);
-
-/* AI HArdware layer */
-
-int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				     struct comedi_insn *insn, unsigned int *data);
-int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data);
-int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				      struct comedi_cmd *cmd);
-int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
-/* int i_APCI3120_CancelAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s); */
-int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
index 38ab499..829af18 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
@@ -51,15 +51,131 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +----------+-----------+------------------------------------------------+
 */
 
-/*
-  +----------------------------------------------------------------------------+
-  |                               Included files                               |
-  +----------------------------------------------------------------------------+
-*/
-#include "hwdrv_apci3200.h"
-
 /* #define PRINT_INFO */
 
+/* Card Specific information */
+/* #define APCI3200_ADDRESS_RANGE	264 */
+
+/* Analog Input related Defines */
+#define APCI3200_AI_OFFSET_GAIN		0
+#define APCI3200_AI_SC_TEST		4
+#define APCI3200_AI_IRQ			8
+#define APCI3200_AI_AUTOCAL		12
+#define APCI3200_RELOAD_CONV_TIME_VAL	32
+#define APCI3200_CONV_TIME_TIME_BASE	36
+#define APCI3200_RELOAD_DELAY_TIME_VAL	40
+#define APCI3200_DELAY_TIME_TIME_BASE	44
+#define APCI3200_AI_MODULE1		0
+#define APCI3200_AI_MODULE2		64
+#define APCI3200_AI_MODULE3		128
+#define APCI3200_AI_MODULE4		192
+#define TRUE				1
+#define FALSE				0
+#define APCI3200_AI_EOSIRQ		16
+#define APCI3200_AI_EOS			20
+#define APCI3200_AI_CHAN_ID		24
+#define APCI3200_AI_CHAN_VAL		28
+#define ANALOG_INPUT			0
+#define TEMPERATURE			1
+#define RESISTANCE			2
+
+#define ENABLE_EXT_TRIG			1
+#define ENABLE_EXT_GATE			2
+#define ENABLE_EXT_TRIG_GATE		3
+
+#define APCI3200_MAXVOLT		2.5
+#define ADDIDATA_GREATER_THAN_TEST	0
+#define ADDIDATA_LESS_THAN_TEST		1
+
+#define ADDIDATA_UNIPOLAR		1
+#define ADDIDATA_BIPOLAR		2
+
+#define MAX_MODULE			4
+
+/* ANALOG INPUT RANGE */
+static const struct comedi_lrange range_apci3200_ai = {
+	8, {
+		BIP_RANGE(10),
+		BIP_RANGE(5),
+		BIP_RANGE(2),
+		BIP_RANGE(1),
+		UNI_RANGE(10),
+		UNI_RANGE(5),
+		UNI_RANGE(2),
+		UNI_RANGE(1)
+	}
+};
+
+static const struct comedi_lrange range_apci3300_ai = {
+	4, {
+		UNI_RANGE(10),
+		UNI_RANGE(5),
+		UNI_RANGE(2),
+		UNI_RANGE(1)
+	}
+};
+
+int MODULE_NO;
+struct {
+	int i_Gain;
+	int i_Polarity;
+	int i_OffsetRange;
+	int i_Coupling;
+	int i_SingleDiff;
+	int i_AutoCalibration;
+	unsigned int ui_ReloadValue;
+	unsigned int ui_TimeUnitReloadVal;
+	int i_Interrupt;
+	int i_ModuleSelection;
+} Config_Parameters_Module1, Config_Parameters_Module2,
+    Config_Parameters_Module3, Config_Parameters_Module4;
+
+
+struct str_ADDIDATA_RTDStruct {
+	unsigned int ul_NumberOfValue;
+	unsigned int *pul_ResistanceValue;
+	unsigned int *pul_TemperatureValue;
+};
+
+struct str_Module {
+	unsigned long ul_CurrentSourceCJC;
+	unsigned long ul_CurrentSource[5];
+	unsigned long ul_GainFactor[8];	/*  Gain Factor */
+	unsigned int w_GainValue[10];
+};
+
+struct str_BoardInfos {
+
+	int i_CJCAvailable;
+	int i_CJCPolarity;
+	int i_CJCGain;
+	int i_InterruptFlag;
+	int i_ADDIDATAPolarity;
+	int i_ADDIDATAGain;
+	int i_AutoCalibration;
+	int i_ADDIDATAConversionTime;
+	int i_ADDIDATAConversionTimeUnit;
+	int i_ADDIDATAType;
+	int i_ChannelNo;
+	int i_ChannelCount;
+	int i_ScanType;
+	int i_FirstChannel;
+	int i_LastChannel;
+	int i_Sum;
+	int i_Offset;
+	unsigned int ui_Channel_num;
+	int i_Count;
+	int i_Initialised;
+	unsigned int ui_InterruptChannelValue[144];	/* Buffer */
+	unsigned char b_StructInitialized;
+	/* 7 is the maximal number of channels */
+	unsigned int ui_ScanValueArray[7 + 12];	
+
+	int i_ConnectionType;
+	int i_NbrOfModule;
+	struct str_Module s_Module[MAX_MODULE];
+};
+
 /* BEGIN JK 06.07.04: Management of sevrals boards */
 /*
   int i_CJCAvailable=1;
@@ -94,27 +210,10 @@ struct str_BoardInfos s_BoardInfos[100];	/*  100 will be the max number of board
 #define NVCMD_BEGIN_READ	(0x7 << 5)	/* nvRam begin read command */
 #define NVCMD_BEGIN_WRITE	(0x6 << 5)	/* EEPROM begin write command */
 
-/*+----------------------------------------------------------------------------+*/
-/*| Function   Name   : int i_AddiHeaderRW_ReadEeprom                          |*/
-/*|                               (int    i_NbOfWordsToRead,                   |*/
-/*|                                unsigned int dw_PCIBoardEepromAddress,             |*/
-/*|                                unsigned short   w_EepromStartAddress,                |*/
-/*|                                unsigned short * pw_DataRead)                          |*/
-/*+----------------------------------------------------------------------------+*/
-/*| Task              : Read word from the 5920 eeprom.                        |*/
-/*+----------------------------------------------------------------------------+*/
-/*| Input Parameters  : int    i_NbOfWordsToRead : Nbr. of word to read        |*/
-/*|                     unsigned int dw_PCIBoardEepromAddress : Address of the eeprom |*/
-/*|                     unsigned short   w_EepromStartAddress : Eeprom start address     |*/
-/*+----------------------------------------------------------------------------+*/
-/*| Output Parameters : unsigned short * pw_DataRead : Read data                          |*/
-/*+----------------------------------------------------------------------------+*/
-/*| Return Value      : -                                                      |*/
-/*+----------------------------------------------------------------------------+*/
-
-int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
-	unsigned int dw_PCIBoardEepromAddress,
-	unsigned short w_EepromStartAddress, unsigned short *pw_DataRead)
+static int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
+				     unsigned int dw_PCIBoardEepromAddress,
+				     unsigned short w_EepromStartAddress,
+				     unsigned short *pw_DataRead)
 {
 	unsigned int dw_eeprom_busy = 0;
 	int i_Counter = 0;
@@ -241,20 +340,8 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
 	return 0;
 }
 
-/*+----------------------------------------------------------------------------+*/
-/*| Function   Name   : void v_GetAPCI3200EepromCalibrationValue (void)        |*/
-/*+----------------------------------------------------------------------------+*/
-/*| Task              : Read calibration value from the APCI-3200 eeprom.      |*/
-/*+----------------------------------------------------------------------------+*/
-/*| Input Parameters  : -                                                      |*/
-/*+----------------------------------------------------------------------------+*/
-/*| Output Parameters : -                                                      |*/
-/*+----------------------------------------------------------------------------+*/
-/*| Return Value      : -                                                      |*/
-/*+----------------------------------------------------------------------------+*/
-
-void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
-	struct str_BoardInfos *BoardInformations)
+static void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
+						struct str_BoardInfos *BoardInformations)
 {
 	unsigned short w_AnalogInputMainHeaderAddress;
 	unsigned short w_AnalogInputComponentAddress;
@@ -448,9 +535,11 @@ void v_GetAPCI3200EepromCalibrationValue(unsigned int dw_PCIBoardEepromAddress,
 	}
 }
 
-int i_APCI3200_GetChannelCalibrationValue(struct comedi_device *dev,
-	unsigned int ui_Channel_num, unsigned int *CJCCurrentSource,
-	unsigned int *ChannelCurrentSource, unsigned int *ChannelGainFactor)
+static int i_APCI3200_GetChannelCalibrationValue(struct comedi_device *dev,
+						 unsigned int ui_Channel_num,
+						 unsigned int *CJCCurrentSource,
+						 unsigned int *ChannelCurrentSource,
+						 unsigned int *ChannelGainFactor)
 {
 	int i_DiffChannel = 0;
 	int i_Module = 0;
@@ -520,1159 +609,394 @@ int i_APCI3200_GetChannelCalibrationValue(struct comedi_device *dev,
 	return 0;
 }
 
-/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-
-/*
-  +----------------------------------------------------------------------------+
-  | Function   Name   : int i_APCI3200_ReadDigitalInput                       |
-  |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-  |                      struct comedi_insn *insn,unsigned int *data)                     |
-  +----------------------------------------------------------------------------+
-  | Task              : Read  value  of the selected channel or port           |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
-  |                     unsigned int ui_NoOfChannels    : No Of Channels To read  for Port
-  Channel Numberfor single channel
-  |                     unsigned int data[0]            : 0: Read single channel
-  1: Read port value
-  data[1]              Port number
-  +----------------------------------------------------------------------------+
-  | Output Parameters :	--	data[0] :Read status value
-  +----------------------------------------------------------------------------+
-  | Return Value      : TRUE  : No error occur                                 |
-  |		            : FALSE : Error occur. Return the error          |
-  |			                                                         |
-  +----------------------------------------------------------------------------+
-*/
-
-int i_APCI3200_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int apci3200_di_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	unsigned int ui_Temp = 0;
-	unsigned int ui_NoOfChannel = 0;
-	ui_NoOfChannel = CR_CHAN(insn->chanspec);
-	ui_Temp = data[0];
-	*data = inl(devpriv->i_IobaseReserved);
-
-	if (ui_Temp == 0) {
-		*data = (*data >> ui_NoOfChannel) & 0x1;
-	}			/* if  (ui_Temp==0) */
-	else {
-		if (ui_Temp == 1) {
-			if (data[1] < 0 || data[1] > 1) {
-				printk("\nThe port number is in error\n");
-				return -EINVAL;
-			}	/* if(data[1] < 0 || data[1] >1) */
-			switch (ui_NoOfChannel) {
-
-			case 2:
-				*data = (*data >> (2 * data[1])) & 0x3;
-				break;
-			case 3:
-				*data = (*data & 15);
-				break;
-			default:
-				comedi_error(dev, " chan spec wrong");
-				return -EINVAL;	/*  "sorry channel spec wrong " */
-
-			}	/* switch(ui_NoOfChannels) */
-		}		/* if  (ui_Temp==1) */
-		else {
-			printk("\nSpecified channel not supported \n");
-		}		/* elseif  (ui_Temp==1) */
-	}
-	return insn->n;
-}
+	struct addi_private *devpriv = dev->private;
 
-/*
-  +----------------------------------------------------------------------------+
-  | Function   Name   : int i_APCI3200_ConfigDigitalOutput                     |
-  |			  (struct comedi_device *dev,struct comedi_subdevice *s,				 |
-  |                      struct comedi_insn *insn,unsigned int *data)                     |
-  +----------------------------------------------------------------------------+
-  | Task              : Configures The Digital Output Subdevice.               |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev : Driver handle                     |
-  |			  data[0]  :1  Memory enable
-  0  Memory Disable
-  +----------------------------------------------------------------------------+
-  | Output Parameters :	--													 |
-  +----------------------------------------------------------------------------+
-  | Return Value      : TRUE  : No error occur                                 |
-  |		            : FALSE : Error occur. Return the error			 |
-  |																	 |
-  +----------------------------------------------------------------------------+
-*/
-int i_APCI3200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
+	data[1] = inl(devpriv->i_IobaseReserved) & 0xf;
 
-	if ((data[0] != 0) && (data[0] != 1)) {
-		comedi_error(dev,
-			"Not a valid Data !!! ,Data should be 1 or 0\n");
-		return -EINVAL;
-	}			/* if  ( (data[0]!=0) && (data[0]!=1) ) */
-	if (data[0]) {
-		devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
-	}			/*  if  (data[0]) */
-	else {
-		devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
-	}			/* else if  (data[0]) */
 	return insn->n;
 }
 
-/*
-  +----------------------------------------------------------------------------+
-  | Function   Name   : int i_APCI3200_WriteDigitalOutput                      |
-  |			  (struct comedi_device *dev,struct comedi_subdevice *s,				 |
-  |                      struct comedi_insn *insn,unsigned int *data)                     |
-  +----------------------------------------------------------------------------+
-  | Task              : writes To the digital Output Subdevice                 |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
-  |                     struct comedi_subdevice *s     : Subdevice Pointer            |
-  |                     struct comedi_insn *insn       : Insn Structure Pointer       |
-  |                     unsigned int *data          : Data Pointer contains        |
-  |                                          configuration parameters as below |
-  |                     data[0]             :Value to output
-  data[1]             : 0 o/p single channel
-  1 o/p port
-  data[2]             : port no
-  data[3]             :0 set the digital o/p on
-  1 set the digital o/p off
-  +----------------------------------------------------------------------------+
-  | Output Parameters :	--													 |
-  +----------------------------------------------------------------------------+
-  | Return Value      : TRUE  : No error occur                                 |
-  |		            : FALSE : Error occur. Return the error	     	 |
-  |			                                                         |
-  +----------------------------------------------------------------------------+
-*/
-int i_APCI3200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int apci3200_do_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	unsigned int ui_Temp = 0, ui_Temp1 = 0;
-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
-	if (devpriv->b_OutputMemoryStatus) {
-		ui_Temp = inl(devpriv->i_IobaseAddon);
+	struct addi_private *devpriv = dev->private;
+	unsigned int mask = data[0];
+	unsigned int bits = data[1];
 
-	}			/* if(devpriv->b_OutputMemoryStatus ) */
-	else {
-		ui_Temp = 0;
-	}			/* if(devpriv->b_OutputMemoryStatus ) */
-	if (data[3] == 0) {
-		if (data[1] == 0) {
-			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
-			outl(data[0], devpriv->i_IobaseAddon);
-		}		/* if(data[1]==0) */
-		else {
-			if (data[1] == 1) {
-				switch (ui_NoOfChannel) {
-
-				case 2:
-					data[0] =
-						(data[0] << (2 *
-							data[2])) | ui_Temp;
-					break;
-				case 3:
-					data[0] = (data[0] | ui_Temp);
-					break;
-				}	/* switch(ui_NoOfChannels) */
-
-				outl(data[0], devpriv->i_IobaseAddon);
-			}	/*  if(data[1]==1) */
-			else {
-				printk("\nSpecified channel not supported\n");
-			}	/* else if(data[1]==1) */
-		}		/* elseif(data[1]==0) */
-	}			/* if(data[3]==0) */
-	else {
-		if (data[3] == 1) {
-			if (data[1] == 0) {
-				data[0] = ~data[0] & 0x1;
-				ui_Temp1 = 1;
-				ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
-				ui_Temp = ui_Temp | ui_Temp1;
-				data[0] = (data[0] << ui_NoOfChannel) ^ 0xf;
-				data[0] = data[0] & ui_Temp;
-				outl(data[0], devpriv->i_IobaseAddon);
-			}	/* if(data[1]==0) */
-			else {
-				if (data[1] == 1) {
-					switch (ui_NoOfChannel) {
-
-					case 2:
-						data[0] = ~data[0] & 0x3;
-						ui_Temp1 = 3;
-						ui_Temp1 =
-							ui_Temp1 << 2 * data[2];
-						ui_Temp = ui_Temp | ui_Temp1;
-						data[0] =
-							((data[0] << (2 *
-									data
-									[2])) ^
-							0xf) & ui_Temp;
-
-						break;
-					case 3:
-						break;
-
-					default:
-						comedi_error(dev,
-							" chan spec wrong");
-						return -EINVAL;	/*  "sorry channel spec wrong " */
-					}	/* switch(ui_NoOfChannels) */
-
-					outl(data[0], devpriv->i_IobaseAddon);
-				}	/*  if(data[1]==1) */
-				else {
-					printk("\nSpecified channel not supported\n");
-				}	/* else if(data[1]==1) */
-			}	/* elseif(data[1]==0) */
-		}		/* if(data[3]==1); */
-		else {
-			printk("\nSpecified functionality does not exist\n");
-			return -EINVAL;
-		}		/* if else data[3]==1) */
-	}			/* if else data[3]==0) */
-	return insn->n;
-}
+	s->state = inl(devpriv->i_IobaseAddon) & 0xf;
+	if (mask) {
+		s->state &= ~mask;
+		s->state |= (bits & mask)
 
-/*
-  +----------------------------------------------------------------------------+
-  | Function   Name   : int i_APCI3200_ReadDigitalOutput                       |
-  |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-  |                      struct comedi_insn *insn,unsigned int *data)                     |
-  +----------------------------------------------------------------------------+
-  | Task              : Read  value  of the selected channel or port           |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
-  |                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
-  |                     unsigned int *data              : Data Pointer to read status  |
-  data[0]                 :0 read single channel
-  1 read port value
-  data[1]                  port no
-
-  +----------------------------------------------------------------------------+
-  | Output Parameters :	--													 |
-  +----------------------------------------------------------------------------+
-  | Return Value      : TRUE  : No error occur                                 |
-  |		            : FALSE : Error occur. Return the error          |
-  |			                                                         |
-  +----------------------------------------------------------------------------+
-*/
-int i_APCI3200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int ui_Temp;
-	unsigned int ui_NoOfChannel;
-	ui_NoOfChannel = CR_CHAN(insn->chanspec);
-	ui_Temp = data[0];
-	*data = inl(devpriv->i_IobaseAddon);
-	if (ui_Temp == 0) {
-		*data = (*data >> ui_NoOfChannel) & 0x1;
-	}			/*  if  (ui_Temp==0) */
-	else {
-		if (ui_Temp == 1) {
-			if (data[1] < 0 || data[1] > 1) {
-				printk("\nThe port selection is in error\n");
-				return -EINVAL;
-			}	/* if(data[1] <0 ||data[1] >1) */
-			switch (ui_NoOfChannel) {
-			case 2:
-				*data = (*data >> (2 * data[1])) & 3;
-				break;
+		outl(s->state, devpriv->i_IobaseAddon);
+	}
 
-			case 3:
-				break;
+	data[1] = s->state;
 
-			default:
-				comedi_error(dev, " chan spec wrong");
-				return -EINVAL;	/*  "sorry channel spec wrong " */
-				break;
-			}	/*  switch(ui_NoOfChannels) */
-		}		/*  if  (ui_Temp==1) */
-		else {
-			printk("\nSpecified channel not supported \n");
-		}		/*  else if (ui_Temp==1) */
-	}			/*  else if  (ui_Temp==0) */
 	return insn->n;
 }
 
-/*
-  +----------------------------------------------------------------------------+
-  | Function   Name   : int i_APCI3200_ConfigAnalogInput                       |
-  |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-  |                      struct comedi_insn *insn,unsigned int *data)                     |
-  +----------------------------------------------------------------------------+
-  | Task              : Configures The Analog Input Subdevice                  |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
-  |                     struct comedi_subdevice *s     : Subdevice Pointer            |
-  |                     struct comedi_insn *insn       : Insn Structure Pointer       |
-  |                     unsigned int *data          : Data Pointer contains        |
-  |                                          configuration parameters as below |
-  |                                                                            |
-  |					data[0]
-  |                                               0:Normal AI                  |
-  |                                               1:RTD                        |
-  |                                               2:THERMOCOUPLE               |
-  |				    data[1]            : Gain To Use                 |
-  |                                                                            |
-  |                           data[2]            : Polarity
-  |                                                0:Bipolar                   |
-  |                                                1:Unipolar                  |
-  |															    	 |
-  |                           data[3]            : Offset Range
-  |                                                                            |
-  |                           data[4]            : Coupling
-  |                                                0:DC Coupling               |
-  |                                                1:AC Coupling               |
-  |                                                                            |
-  |                           data[5]            :Differential/Single
-  |                                                0:Single                    |
-  |                                                1:Differential              |
-  |                                                                            |
-  |                           data[6]            :TimerReloadValue
-  |                                                                            |
-  |                           data[7]            :ConvertingTimeUnit
-  |                                                                            |
-  |                           data[8]             :0 Analog voltage measurement
-  1 Resistance measurement
-  2 Temperature measurement
-  |                           data[9]            :Interrupt
-  |                                              0:Disable
-  |                                              1:Enable
-  data[10]           :Type of Thermocouple
-  |                          data[11]           : 0: single channel
-  Module Number
-  |
-  |                          data[12]
-  |                                             0:Single Read
-  |                                             1:Read more channel
-  2:Single scan
-  |                                             3:Continuous Scan
-  data[13]          :Number of channels to read
-  |                          data[14]          :RTD connection type
-  :0:RTD not used
-  1:RTD 2 wire connection
-  2:RTD 3 wire connection
-  3:RTD 4 wire connection
-  |                                                                            |
-  |                                                                            |
-  |                                                                            |
-  +----------------------------------------------------------------------------+
-  | Output Parameters :	--													 |
-  +----------------------------------------------------------------------------+
-  | Return Value      : TRUE  : No error occur                                 |
-  |		            : FALSE : Error occur. Return the error          |
-  |			                                                         |
-  +----------------------------------------------------------------------------+
-*/
-int i_APCI3200_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev,
+					      struct comedi_subdevice *s,
+					      struct comedi_insn *insn,
+					      unsigned int *data)
 {
-
-	unsigned int ul_Config = 0, ul_Temp = 0;
+	struct addi_private *devpriv = dev->private;
+	unsigned int ui_EOC = 0;
 	unsigned int ui_ChannelNo = 0;
-	unsigned int ui_Dummy = 0;
-	int i_err = 0;
+	unsigned int ui_CommandRegister = 0;
 
-	/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+	/* BEGIN JK 06.07.04: Management of sevrals boards */
+	/* ui_ChannelNo=i_ChannelNo; */
+	ui_ChannelNo = s_BoardInfos[dev->minor].i_ChannelNo;
 
-#ifdef PRINT_INFO
-	int i = 0, i2 = 0;
-#endif
-	/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+					12) >> 19) & 1) != 1) ;
+  /*********************************/
+	/* Write the channel to configure */
+  /*********************************/
+	/* Begin JK 20.10.2004: Bad channel value is used when using differential mode */
+	/* outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); */
+	/* outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4); */
+	outl(0 | s_BoardInfos[dev->minor].i_ChannelNo,
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x4);
+	/* End JK 20.10.2004: Bad channel value is used when using differential mode */
 
-	/* BEGIN JK 06.07.04: Management of sevrals boards */
-	/*  Initialize the structure */
-	if (s_BoardInfos[dev->minor].b_StructInitialized != 1) {
-		s_BoardInfos[dev->minor].i_CJCAvailable = 1;
-		s_BoardInfos[dev->minor].i_CJCPolarity = 0;
-		s_BoardInfos[dev->minor].i_CJCGain = 2;	/* changed from 0 to 2 */
-		s_BoardInfos[dev->minor].i_InterruptFlag = 0;
-		s_BoardInfos[dev->minor].i_AutoCalibration = 0;	/* : auto calibration */
-		s_BoardInfos[dev->minor].i_ChannelCount = 0;
-		s_BoardInfos[dev->minor].i_Sum = 0;
-		s_BoardInfos[dev->minor].ui_Channel_num = 0;
-		s_BoardInfos[dev->minor].i_Count = 0;
-		s_BoardInfos[dev->minor].i_Initialised = 0;
-		s_BoardInfos[dev->minor].b_StructInitialized = 1;
+  /*******************************/
+	/* Set the convert timing unit */
+  /*******************************/
+	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+					12) >> 19) & 1) != 1) ;
 
-		/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-		s_BoardInfos[dev->minor].i_ConnectionType = 0;
-		/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+	/* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
+	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
 
-		/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-		memset(s_BoardInfos[dev->minor].s_Module, 0,
-			sizeof(s_BoardInfos[dev->minor].s_Module[MAX_MODULE]));
+  /**************************/
+	/* Set the convert timing */
+  /**************************/
+	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+					12) >> 19) & 1) != 1) ;
 
-		v_GetAPCI3200EepromCalibrationValue(devpriv->i_IobaseAmcc,
-			&s_BoardInfos[dev->minor]);
+	/* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
+	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
 
-#ifdef PRINT_INFO
-		for (i = 0; i < MAX_MODULE; i++) {
-			printk("\n s_Module[%i].ul_CurrentSourceCJC = %lu", i,
-				s_BoardInfos[dev->minor].s_Module[i].
-				ul_CurrentSourceCJC);
+  /**************************************************************************/
+	/* Set the start end stop index to the selected channel and set the start */
+  /**************************************************************************/
 
-			for (i2 = 0; i2 < 5; i2++) {
-				printk("\n s_Module[%i].ul_CurrentSource [%i] = %lu", i, i2, s_BoardInfos[dev->minor].s_Module[i].ul_CurrentSource[i2]);
-			}
+	ui_CommandRegister = ui_ChannelNo | (ui_ChannelNo << 8) | 0x80000;
 
-			for (i2 = 0; i2 < 8; i2++) {
-				printk("\n s_Module[%i].ul_GainFactor [%i] = %lu", i, i2, s_BoardInfos[dev->minor].s_Module[i].ul_GainFactor[i2]);
-			}
+  /*********************************/
+	/*Test if the interrupt is enable */
+  /*********************************/
 
-			for (i2 = 0; i2 < 8; i2++) {
-				printk("\n s_Module[%i].w_GainValue [%i] = %u",
-					i, i2,
-					s_BoardInfos[dev->minor].s_Module[i].
-					w_GainValue[i2]);
-			}
-		}
-#endif
-		/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-	}
+	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+      /************************/
+		/* Enable the interrupt */
+      /************************/
+		ui_CommandRegister = ui_CommandRegister | 0x00100000;
+	}			/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
 
-	if (data[0] != 0 && data[0] != 1 && data[0] != 2) {
-		printk("\nThe selection of acquisition type is in error\n");
-		i_err++;
-	}			/* if(data[0]!=0 && data[0]!=1 && data[0]!=2) */
-	if (data[0] == 1) {
-		if (data[14] != 0 && data[14] != 1 && data[14] != 2
-			&& data[14] != 4) {
-			printk("\n Error in selection of RTD connection type\n");
-			i_err++;
-		}		/* if(data[14]!=0 && data[14]!=1 && data[14]!=2 && data[14]!=4) */
-	}			/* if(data[0]==1 ) */
-	if (data[1] < 0 || data[1] > 7) {
-		printk("\nThe selection of gain is in error\n");
-		i_err++;
-	}			/*  if(data[1]<0 || data[1]>7) */
-	if (data[2] != 0 && data[2] != 1) {
-		printk("\nThe selection of polarity is in error\n");
-		i_err++;
-	}			/* if(data[2]!=0 &&  data[2]!=1) */
-	if (data[3] != 0) {
-		printk("\nThe selection of offset range  is in error\n");
-		i_err++;
-	}			/*  if(data[3]!=0) */
-	if (data[4] != 0 && data[4] != 1) {
-		printk("\nThe selection of coupling is in error\n");
-		i_err++;
-	}			/* if(data[4]!=0 &&  data[4]!=1) */
-	if (data[5] != 0 && data[5] != 1) {
-		printk("\nThe selection of single/differential mode is in error\n");
-		i_err++;
-	}			/* if(data[5]!=0 &&  data[5]!=1) */
-	if (data[8] != 0 && data[8] != 1 && data[2] != 2) {
-		printk("\nError in selection of functionality\n");
-	}			/* if(data[8]!=0 && data[8]!=1 && data[2]!=2) */
-	if (data[12] == 0 || data[12] == 1) {
-		if (data[6] != 20 && data[6] != 40 && data[6] != 80
-			&& data[6] != 160) {
-			printk("\nThe selection of conversion time reload value is in error\n");
-			i_err++;
-		}		/*  if (data[6]!=20 && data[6]!=40 && data[6]!=80 && data[6]!=160 ) */
-		if (data[7] != 2) {
-			printk("\nThe selection of conversion time unit  is in error\n");
-			i_err++;
-		}		/*  if(data[7]!=2) */
-	}
-	if (data[9] != 0 && data[9] != 1) {
-		printk("\nThe selection of interrupt enable is in error\n");
-		i_err++;
-	}			/* if(data[9]!=0 &&  data[9]!=1) */
-	if (data[11] < 0 || data[11] > 4) {
-		printk("\nThe selection of module is in error\n");
-		i_err++;
-	}			/* if(data[11] <0 ||  data[11]>1) */
-	if (data[12] < 0 || data[12] > 3) {
-		printk("\nThe selection of singlechannel/scan selection is in error\n");
-		i_err++;
-	}			/* if(data[12] < 0 ||  data[12]> 3) */
-	if (data[13] < 0 || data[13] > 16) {
-		printk("\nThe selection of number of channels is in error\n");
-		i_err++;
-	}			/*  if(data[13] <0 ||data[13] >15) */
+  /******************************/
+	/* Write the command register */
+  /******************************/
+	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+					12) >> 19) & 1) != 1) ;
 
-	/* BEGIN JK 06.07.04: Management of sevrals boards */
-	/*
-	   i_ChannelCount=data[13];
-	   i_ScanType=data[12];
-	   i_ADDIDATAPolarity = data[2];
-	   i_ADDIDATAGain=data[1];
-	   i_ADDIDATAConversionTime=data[6];
-	   i_ADDIDATAConversionTimeUnit=data[7];
-	   i_ADDIDATAType=data[0];
-	 */
+	/* outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8); */
+	outl(ui_CommandRegister,
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
 
-	/*  Save acquisition configuration for the actual board */
-	s_BoardInfos[dev->minor].i_ChannelCount = data[13];
-	s_BoardInfos[dev->minor].i_ScanType = data[12];
-	s_BoardInfos[dev->minor].i_ADDIDATAPolarity = data[2];
-	s_BoardInfos[dev->minor].i_ADDIDATAGain = data[1];
-	s_BoardInfos[dev->minor].i_ADDIDATAConversionTime = data[6];
-	s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit = data[7];
-	s_BoardInfos[dev->minor].i_ADDIDATAType = data[0];
-	/* Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-	s_BoardInfos[dev->minor].i_ConnectionType = data[5];
-	/* End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-	/* END JK 06.07.04: Management of sevrals boards */
+  /*****************************/
+	/*Test if interrupt is enable */
+  /*****************************/
+	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
+		do {
+	  /*************************/
+			/*Read the EOC Status bit */
+	  /*************************/
 
-	/* Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-	memset(s_BoardInfos[dev->minor].ui_ScanValueArray, 0, (7 + 12) * sizeof(unsigned int));	/*  7 is the maximal number of channels */
-	/* End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+			/* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
+			ui_EOC = inl(devpriv->iobase +
+				s_BoardInfos[dev->minor].i_Offset + 20) & 1;
 
-	/* BEGIN JK 02.07.04 : This while can't be do, it block the process when using severals boards */
-	/* while(i_InterruptFlag==1) */
-	while (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
-#ifndef MSXBOX
-		udelay(1);
-#else
-		/*  In the case where the driver is compiled for the MSX-Box */
-		/*  we used a printk to have a little delay because udelay */
-		/*  seems to be broken under the MSX-Box. */
-		/*  This solution hat to be studied. */
-		printk("");
-#endif
-	}
-	/* END JK 02.07.04 : This while can't be do, it block the process when using severals boards */
-
-	ui_ChannelNo = CR_CHAN(insn->chanspec);	/*  get the channel */
-	/* BEGIN JK 06.07.04: Management of sevrals boards */
-	/* i_ChannelNo=ui_ChannelNo; */
-	/* ui_Channel_num =ui_ChannelNo; */
-
-	s_BoardInfos[dev->minor].i_ChannelNo = ui_ChannelNo;
-	s_BoardInfos[dev->minor].ui_Channel_num = ui_ChannelNo;
+		} while (ui_EOC != 1);
 
-	/* END JK 06.07.04: Management of sevrals boards */
+      /***************************************/
+		/* Read the digital value of the input */
+      /***************************************/
 
-	if (data[5] == 0) {
-		if (ui_ChannelNo < 0 || ui_ChannelNo > 15) {
-			printk("\nThe Selection of the channel is in error\n");
-			i_err++;
-		}		/*  if(ui_ChannelNo<0 || ui_ChannelNo>15) */
-	}			/* if(data[5]==0) */
-	else {
-		if (data[14] == 2) {
-			if (ui_ChannelNo < 0 || ui_ChannelNo > 3) {
-				printk("\nThe Selection of the channel is in error\n");
-				i_err++;
-			}	/*  if(ui_ChannelNo<0 || ui_ChannelNo>3) */
-		}		/* if(data[14]==2) */
-		else {
-			if (ui_ChannelNo < 0 || ui_ChannelNo > 7) {
-				printk("\nThe Selection of the channel is in error\n");
-				i_err++;
-			}	/*  if(ui_ChannelNo<0 || ui_ChannelNo>7) */
-		}		/* elseif(data[14]==2) */
-	}			/* elseif(data[5]==0) */
-	if (data[12] == 0 || data[12] == 1) {
-		switch (data[5]) {
-		case 0:
-			if (ui_ChannelNo >= 0 && ui_ChannelNo <= 3) {
-				/* BEGIN JK 06.07.04: Management of sevrals boards */
-				/* i_Offset=0; */
-				s_BoardInfos[dev->minor].i_Offset = 0;
-				/* END JK 06.07.04: Management of sevrals boards */
-			}	/* if(ui_ChannelNo >=0 && ui_ChannelNo <=3) */
-			if (ui_ChannelNo >= 4 && ui_ChannelNo <= 7) {
-				/* BEGIN JK 06.07.04: Management of sevrals boards */
-				/* i_Offset=64; */
-				s_BoardInfos[dev->minor].i_Offset = 64;
-				/* END JK 06.07.04: Management of sevrals boards */
-			}	/* if(ui_ChannelNo >=4 && ui_ChannelNo <=7) */
-			if (ui_ChannelNo >= 8 && ui_ChannelNo <= 11) {
-				/* BEGIN JK 06.07.04: Management of sevrals boards */
-				/* i_Offset=128; */
-				s_BoardInfos[dev->minor].i_Offset = 128;
-				/* END JK 06.07.04: Management of sevrals boards */
-			}	/* if(ui_ChannelNo >=8 && ui_ChannelNo <=11) */
-			if (ui_ChannelNo >= 12 && ui_ChannelNo <= 15) {
-				/* BEGIN JK 06.07.04: Management of sevrals boards */
-				/* i_Offset=192; */
-				s_BoardInfos[dev->minor].i_Offset = 192;
-				/* END JK 06.07.04: Management of sevrals boards */
-			}	/* if(ui_ChannelNo >=12 && ui_ChannelNo <=15) */
-			break;
-		case 1:
-			if (data[14] == 2) {
-				if (ui_ChannelNo == 0) {
-					/* BEGIN JK 06.07.04: Management of sevrals boards */
-					/* i_Offset=0; */
-					s_BoardInfos[dev->minor].i_Offset = 0;
-					/* END JK 06.07.04: Management of sevrals boards */
-				}	/* if(ui_ChannelNo ==0 ) */
-				if (ui_ChannelNo == 1) {
-					/* BEGIN JK 06.07.04: Management of sevrals boards */
-					/* i_Offset=0; */
-					s_BoardInfos[dev->minor].i_Offset = 64;
-					/* END JK 06.07.04: Management of sevrals boards */
-				}	/*  if(ui_ChannelNo ==1) */
-				if (ui_ChannelNo == 2) {
-					/* BEGIN JK 06.07.04: Management of sevrals boards */
-					/* i_Offset=128; */
-					s_BoardInfos[dev->minor].i_Offset = 128;
-					/* END JK 06.07.04: Management of sevrals boards */
-				}	/* if(ui_ChannelNo ==2 ) */
-				if (ui_ChannelNo == 3) {
-					/* BEGIN JK 06.07.04: Management of sevrals boards */
-					/* i_Offset=192; */
-					s_BoardInfos[dev->minor].i_Offset = 192;
-					/* END JK 06.07.04: Management of sevrals boards */
-				}	/* if(ui_ChannelNo ==3) */
+		/* data[0] = inl (devpriv->iobase+i_Offset + 28); */
+		data[0] =
+			inl(devpriv->iobase +
+			s_BoardInfos[dev->minor].i_Offset + 28);
+		/* END JK 06.07.04: Management of sevrals boards */
 
-				/* BEGIN JK 06.07.04: Management of sevrals boards */
-				/* i_ChannelNo=0; */
-				s_BoardInfos[dev->minor].i_ChannelNo = 0;
-				/* END JK 06.07.04: Management of sevrals boards */
-				ui_ChannelNo = 0;
-				break;
-			}	/* if(data[14]==2) */
-			if (ui_ChannelNo >= 0 && ui_ChannelNo <= 1) {
-				/* BEGIN JK 06.07.04: Management of sevrals boards */
-				/* i_Offset=0; */
-				s_BoardInfos[dev->minor].i_Offset = 0;
-				/* END JK 06.07.04: Management of sevrals boards */
-			}	/* if(ui_ChannelNo >=0 && ui_ChannelNo <=1) */
-			if (ui_ChannelNo >= 2 && ui_ChannelNo <= 3) {
-				/* BEGIN JK 06.07.04: Management of sevrals boards */
-				/* i_ChannelNo=i_ChannelNo-2; */
-				/* i_Offset=64; */
-				s_BoardInfos[dev->minor].i_ChannelNo =
-					s_BoardInfos[dev->minor].i_ChannelNo -
-					2;
-				s_BoardInfos[dev->minor].i_Offset = 64;
-				/* END JK 06.07.04: Management of sevrals boards */
-				ui_ChannelNo = ui_ChannelNo - 2;
-			}	/* if(ui_ChannelNo >=2 && ui_ChannelNo <=3) */
-			if (ui_ChannelNo >= 4 && ui_ChannelNo <= 5) {
-				/* BEGIN JK 06.07.04: Management of sevrals boards */
-				/* i_ChannelNo=i_ChannelNo-4; */
-				/* i_Offset=128; */
-				s_BoardInfos[dev->minor].i_ChannelNo =
-					s_BoardInfos[dev->minor].i_ChannelNo -
-					4;
-				s_BoardInfos[dev->minor].i_Offset = 128;
-				/* END JK 06.07.04: Management of sevrals boards */
-				ui_ChannelNo = ui_ChannelNo - 4;
-			}	/* if(ui_ChannelNo >=4 && ui_ChannelNo <=5) */
-			if (ui_ChannelNo >= 6 && ui_ChannelNo <= 7) {
-				/* BEGIN JK 06.07.04: Management of sevrals boards */
-				/* i_ChannelNo=i_ChannelNo-6; */
-				/* i_Offset=192; */
-				s_BoardInfos[dev->minor].i_ChannelNo =
-					s_BoardInfos[dev->minor].i_ChannelNo -
-					6;
-				s_BoardInfos[dev->minor].i_Offset = 192;
-				/* END JK 06.07.04: Management of sevrals boards */
-				ui_ChannelNo = ui_ChannelNo - 6;
-			}	/* if(ui_ChannelNo >=6 && ui_ChannelNo <=7) */
-			break;
+	}			/*  if (i_InterruptFlag == ADDIDATA_DISABLE) */
+	return 0;
+}
 
-		default:
-			printk("\n This selection of polarity does not exist\n");
-			i_err++;
-		}		/* switch(data[2]) */
-	}			/* if(data[12]==0 || data[12]==1) */
-	else {
-		switch (data[11]) {
-		case 1:
-			/* BEGIN JK 06.07.04: Management of sevrals boards */
-			/* i_Offset=0; */
-			s_BoardInfos[dev->minor].i_Offset = 0;
-			/* END JK 06.07.04: Management of sevrals boards */
-			break;
-		case 2:
-			/* BEGIN JK 06.07.04: Management of sevrals boards */
-			/* i_Offset=64; */
-			s_BoardInfos[dev->minor].i_Offset = 64;
-			/* END JK 06.07.04: Management of sevrals boards */
-			break;
-		case 3:
-			/* BEGIN JK 06.07.04: Management of sevrals boards */
-			/* i_Offset=128; */
-			s_BoardInfos[dev->minor].i_Offset = 128;
-			/* END JK 06.07.04: Management of sevrals boards */
-			break;
-		case 4:
-			/* BEGIN JK 06.07.04: Management of sevrals boards */
-			/* i_Offset=192; */
-			s_BoardInfos[dev->minor].i_Offset = 192;
-			/* END JK 06.07.04: Management of sevrals boards */
-			break;
-		default:
-			printk("\nError in module selection\n");
-			i_err++;
-		}		/*  switch(data[11]) */
-	}			/*  elseif(data[12]==0 || data[12]==1) */
-	if (i_err) {
-		i_APCI3200_Reset(dev);
-		return -EINVAL;
-	}
-	/* if(i_ScanType!=1) */
-	if (s_BoardInfos[dev->minor].i_ScanType != 1) {
-		/* BEGIN JK 06.07.04: Management of sevrals boards */
-		/* i_Count=0; */
-		/* i_Sum=0; */
-		s_BoardInfos[dev->minor].i_Count = 0;
-		s_BoardInfos[dev->minor].i_Sum = 0;
-		/* END JK 06.07.04: Management of sevrals boards */
-	}			/* if(i_ScanType!=1) */
+static int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev,
+						 unsigned int *data)
+{
+	struct addi_private *devpriv = dev->private;
+	unsigned int ui_Temp = 0, ui_EOC = 0;
+	unsigned int ui_CommandRegister = 0;
 
-	ul_Config =
-		data[1] | (data[2] << 6) | (data[5] << 7) | (data[3] << 8) |
-		(data[4] << 9);
 	/* BEGIN JK 06.07.04: Management of sevrals boards */
 	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
 					12) >> 19) & 1) != 1) ;
-	/* END JK 06.07.04: Management of sevrals boards */
   /*********************************/
 	/* Write the channel to configure */
   /*********************************/
-	/* BEGIN JK 06.07.04: Management of sevrals boards */
-	/* outl(0 | ui_ChannelNo , devpriv->iobase+i_Offset + 0x4); */
-	outl(0 | ui_ChannelNo,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x4);
-	/* END JK 06.07.04: Management of sevrals boards */
+	/* Begin JK 20.10.2004: This seems not necessary ! */
+	/* outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); */
+	/* outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4); */
+	/* End JK 20.10.2004: This seems not necessary ! */
 
-	/* BEGIN JK 06.07.04: Management of sevrals boards */
+  /*******************************/
+	/* Set the convert timing unit */
+  /*******************************/
 	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
 					12) >> 19) & 1) != 1) ;
-	/* END JK 06.07.04: Management of sevrals boards */
+	/* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
+	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
   /**************************/
-	/* Reset the configuration */
+	/* Set the convert timing */
   /**************************/
-	/* BEGIN JK 06.07.04: Management of sevrals boards */
-	/* outl(0 , devpriv->iobase+i_Offset + 0x0); */
-	outl(0, devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x0);
-	/* END JK 06.07.04: Management of sevrals boards */
+	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+					12) >> 19) & 1) != 1) ;
+	/* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
+	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+  /*****************************/
+	/*Read the calibration offset */
+  /*****************************/
+	/* ui_Temp = inl(devpriv->iobase+i_Offset + 12); */
+	ui_Temp = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
 
-	/* BEGIN JK 06.07.04: Management of sevrals boards */
+  /*********************************/
+	/*Configure the Offset Conversion */
+  /*********************************/
 	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
 					12) >> 19) & 1) != 1) ;
-	/* END JK 06.07.04: Management of sevrals boards */
+	/* outl((ui_Temp | 0x00020000), devpriv->iobase+i_Offset + 12); */
+	outl((ui_Temp | 0x00020000),
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+  /*******************************/
+	/*Initialise ui_CommandRegister */
+  /*******************************/
 
-  /***************************/
-	/* Write the configuration */
-  /***************************/
-	/* BEGIN JK 06.07.04: Management of sevrals boards */
-	/* outl(ul_Config , devpriv->iobase+i_Offset + 0x0); */
-	outl(ul_Config,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x0);
-	/* END JK 06.07.04: Management of sevrals boards */
+	ui_CommandRegister = 0;
+
+  /*********************************/
+	/*Test if the interrupt is enable */
+  /*********************************/
+
+	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
+
+      /**********************/
+		/*Enable the interrupt */
+      /**********************/
+
+		ui_CommandRegister = ui_CommandRegister | 0x00100000;
+
+	}			/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+
+  /**********************/
+	/*Start the conversion */
+  /**********************/
+	ui_CommandRegister = ui_CommandRegister | 0x00080000;
 
   /***************************/
-	/*Reset the calibration bit */
+	/*Write the command regiter */
   /***************************/
-	/* BEGIN JK 06.07.04: Management of sevrals boards */
-	/* ul_Temp = inl(devpriv->iobase+i_Offset + 12); */
-	ul_Temp = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
-	/* END JK 06.07.04: Management of sevrals boards */
-
-	/* BEGIN JK 06.07.04: Management of sevrals boards */
 	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
 					12) >> 19) & 1) != 1) ;
-	/* END JK 06.07.04: Management of sevrals boards */
+	/* outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8); */
+	outl(ui_CommandRegister,
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
 
-	/* BEGIN JK 06.07.04: Management of sevrals boards */
-	/* outl((ul_Temp & 0xFFF9FFFF) , devpriv->iobase+.i_Offset + 12); */
-	outl((ul_Temp & 0xFFF9FFFF),
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
-	/* END JK 06.07.04: Management of sevrals boards */
+  /*****************************/
+	/*Test if interrupt is enable */
+  /*****************************/
 
-	if (data[9] == 1) {
-		devpriv->tsk_Current = current;
-		/* BEGIN JK 06.07.04: Management of sevrals boards */
-		/* i_InterruptFlag=1; */
-		s_BoardInfos[dev->minor].i_InterruptFlag = 1;
-		/* END JK 06.07.04: Management of sevrals boards */
-	}			/*  if(data[9]==1) */
-	else {
-		/* BEGIN JK 06.07.04: Management of sevrals boards */
-		/* i_InterruptFlag=0; */
-		s_BoardInfos[dev->minor].i_InterruptFlag = 0;
-		/* END JK 06.07.04: Management of sevrals boards */
-	}			/* else  if(data[9]==1) */
+	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
 
-	/* BEGIN JK 06.07.04: Management of sevrals boards */
-	/* i_Initialised=1; */
-	s_BoardInfos[dev->minor].i_Initialised = 1;
-	/* END JK 06.07.04: Management of sevrals boards */
+		do {
+	  /*******************/
+			/*Read the EOC flag */
+	  /*******************/
 
-	/* BEGIN JK 06.07.04: Management of sevrals boards */
-	/* if(i_ScanType==1) */
-	if (s_BoardInfos[dev->minor].i_ScanType == 1)
-		/* END JK 06.07.04: Management of sevrals boards */
-	{
-		/* BEGIN JK 06.07.04: Management of sevrals boards */
-		/* i_Sum=i_Sum+1; */
-		s_BoardInfos[dev->minor].i_Sum =
-			s_BoardInfos[dev->minor].i_Sum + 1;
-		/* END JK 06.07.04: Management of sevrals boards */
+			/* ui_EOC = inl (devpriv->iobase+i_Offset + 20) & 1; */
+			ui_EOC = inl(devpriv->iobase +
+				s_BoardInfos[dev->minor].i_Offset + 20) & 1;
 
-		insn->unused[0] = 0;
-		i_APCI3200_ReadAnalogInput(dev, s, insn, &ui_Dummy);
-	}
+		} while (ui_EOC != 1);
 
-	return insn->n;
+      /**************************************************/
+		/*Read the digital value of the calibration Offset */
+      /**************************************************/
+
+		/* data[0] = inl(devpriv->iobase+i_Offset+ 28); */
+		data[0] =
+			inl(devpriv->iobase +
+			s_BoardInfos[dev->minor].i_Offset + 28);
+	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+	return 0;
 }
 
-/*
-  +----------------------------------------------------------------------------+
-  | Function   Name   : int i_APCI3200_ReadAnalogInput                         |
-  |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
-  |                     struct comedi_insn *insn,unsigned int *data)                      |
-  +----------------------------------------------------------------------------+
-  | Task              : Read  value  of the selected channel			         |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
-  |                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
-  |                     unsigned int *data              : Data Pointer to read status  |
-  +----------------------------------------------------------------------------+
-  | Output Parameters :	--													 |
-  |				data[0]  : Digital Value Of Input             |
-  |				data[1]  : Calibration Offset Value           |
-  |				data[2]  : Calibration Gain Value
-  |				data[3]  : CJC value
-  |				data[4]  : CJC offset value
-  |				data[5]  : CJC gain value
-  | Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
-  |				data[6] : CJC current source from eeprom
-  |				data[7] : Channel current source from eeprom
-  |				data[8] : Channle gain factor from eeprom
-  | End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values
-  +----------------------------------------------------------------------------+
-  | Return Value      : TRUE  : No error occur                                 |
-  |		            : FALSE : Error occur. Return the error          |
-  |			                                                         |
-  +----------------------------------------------------------------------------+
-*/
-int i_APCI3200_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev,
+					       unsigned int *data)
 {
-	unsigned int ui_DummyValue = 0;
-	int i_ConvertCJCCalibration;
-	int i = 0;
-
-	/* BEGIN JK 06.07.04: Management of sevrals boards */
-	/* if(i_Initialised==0) */
-	if (s_BoardInfos[dev->minor].i_Initialised == 0)
-		/* END JK 06.07.04: Management of sevrals boards */
-	{
-		i_APCI3200_Reset(dev);
-		return -EINVAL;
-	}			/* if(i_Initialised==0); */
+	struct addi_private *devpriv = dev->private;
+	unsigned int ui_EOC = 0;
+	int ui_CommandRegister = 0;
 
-#ifdef PRINT_INFO
-	printk("\n insn->unused[0] = %i", insn->unused[0]);
-#endif
+	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+					12) >> 19) & 1) != 1) ;
+  /*********************************/
+	/* Write the channel to configure */
+  /*********************************/
+	/* Begin JK 20.10.2004: This seems not necessary ! */
+	/* outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); */
+	/* outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4); */
+	/* End JK 20.10.2004: This seems not necessary ! */
 
-	switch (insn->unused[0]) {
-	case 0:
+  /***************************/
+	/*Read the calibration gain */
+  /***************************/
+  /*******************************/
+	/* Set the convert timing unit */
+  /*******************************/
+	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+					12) >> 19) & 1) != 1) ;
+	/* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
+	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
+  /**************************/
+	/* Set the convert timing */
+  /**************************/
+	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+					12) >> 19) & 1) != 1) ;
+	/* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
+	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+  /*******************************/
+	/*Configure the Gain Conversion */
+  /*******************************/
+	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+					12) >> 19) & 1) != 1) ;
+	/* outl(0x00040000 , devpriv->iobase+i_Offset + 12); */
+	outl(0x00040000,
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
 
-		i_APCI3200_Read1AnalogInputChannel(dev, s, insn,
-			&ui_DummyValue);
-		/* BEGIN JK 06.07.04: Management of sevrals boards */
-		/* ui_InterruptChannelValue[i_Count+0]=ui_DummyValue; */
-		s_BoardInfos[dev->minor].
-			ui_InterruptChannelValue[s_BoardInfos[dev->minor].
-			i_Count + 0] = ui_DummyValue;
-		/* END JK 06.07.04: Management of sevrals boards */
+  /*******************************/
+	/*Initialise ui_CommandRegister */
+  /*******************************/
 
-		/* Begin JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-		i_APCI3200_GetChannelCalibrationValue(dev,
-			s_BoardInfos[dev->minor].ui_Channel_num,
-			&s_BoardInfos[dev->minor].
-			ui_InterruptChannelValue[s_BoardInfos[dev->minor].
-				i_Count + 6],
-			&s_BoardInfos[dev->minor].
-			ui_InterruptChannelValue[s_BoardInfos[dev->minor].
-				i_Count + 7],
-			&s_BoardInfos[dev->minor].
-			ui_InterruptChannelValue[s_BoardInfos[dev->minor].
-				i_Count + 8]);
+	ui_CommandRegister = 0;
 
-#ifdef PRINT_INFO
-		printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+6] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 6]);
+  /*********************************/
+	/*Test if the interrupt is enable */
+  /*********************************/
 
-		printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+7] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 7]);
+	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
 
-		printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+8] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 8]);
-#endif
+      /**********************/
+		/*Enable the interrupt */
+      /**********************/
 
-		/* End JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+		ui_CommandRegister = ui_CommandRegister | 0x00100000;
 
-		/* BEGIN JK 06.07.04: Management of sevrals boards */
-		/* if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1)) */
-		if ((s_BoardInfos[dev->minor].i_ADDIDATAType == 2)
-			&& (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE)
-			&& (s_BoardInfos[dev->minor].i_CJCAvailable == 1))
-			/* END JK 06.07.04: Management of sevrals boards */
-		{
-			i_APCI3200_ReadCJCValue(dev, &ui_DummyValue);
-			/* BEGIN JK 06.07.04: Management of sevrals boards */
-			/* ui_InterruptChannelValue[i_Count + 3]=ui_DummyValue; */
-			s_BoardInfos[dev->minor].
-				ui_InterruptChannelValue[s_BoardInfos[dev->
-					minor].i_Count + 3] = ui_DummyValue;
-			/* END JK 06.07.04: Management of sevrals boards */
-		}		/* if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)) */
-		else {
-			/* BEGIN JK 06.07.04: Management of sevrals boards */
-			/* ui_InterruptChannelValue[i_Count + 3]=0; */
-			s_BoardInfos[dev->minor].
-				ui_InterruptChannelValue[s_BoardInfos[dev->
-					minor].i_Count + 3] = 0;
-			/* END JK 06.07.04: Management of sevrals boards */
-		}		/* elseif((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1)) */
+	}			/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
 
-		/* BEGIN JK 06.07.04: Management of sevrals boards */
-		/* if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE)) */
-		if ((s_BoardInfos[dev->minor].i_AutoCalibration == FALSE)
-			&& (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE))
-			/* END JK 06.07.04: Management of sevrals boards */
-		{
-			i_APCI3200_ReadCalibrationOffsetValue(dev,
-				&ui_DummyValue);
-			/* BEGIN JK 06.07.04: Management of sevrals boards */
-			/* ui_InterruptChannelValue[i_Count + 1]=ui_DummyValue; */
-			s_BoardInfos[dev->minor].
-				ui_InterruptChannelValue[s_BoardInfos[dev->
-					minor].i_Count + 1] = ui_DummyValue;
-			/* END JK 06.07.04: Management of sevrals boards */
-			i_APCI3200_ReadCalibrationGainValue(dev,
-				&ui_DummyValue);
-			/* BEGIN JK 06.07.04: Management of sevrals boards */
-			/* ui_InterruptChannelValue[i_Count + 2]=ui_DummyValue; */
-			s_BoardInfos[dev->minor].
-				ui_InterruptChannelValue[s_BoardInfos[dev->
-					minor].i_Count + 2] = ui_DummyValue;
-			/* END JK 06.07.04: Management of sevrals boards */
-		}		/* if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE)) */
+  /**********************/
+	/*Start the conversion */
+  /**********************/
 
-		/* BEGIN JK 06.07.04: Management of sevrals boards */
-		/* if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)&& (i_CJCAvailable==1)) */
-		if ((s_BoardInfos[dev->minor].i_ADDIDATAType == 2)
-			&& (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE)
-			&& (s_BoardInfos[dev->minor].i_CJCAvailable == 1))
-			/* END JK 06.07.04: Management of sevrals boards */
-		{
-	  /**********************************************************/
-			/*Test if the Calibration channel must be read for the CJC */
-	  /**********************************************************/
-	  /**********************************/
-			/*Test if the polarity is the same */
-	  /**********************************/
-			/* BEGIN JK 06.07.04: Management of sevrals boards */
-			/* if(i_CJCPolarity!=i_ADDIDATAPolarity) */
-			if (s_BoardInfos[dev->minor].i_CJCPolarity !=
-				s_BoardInfos[dev->minor].i_ADDIDATAPolarity)
-				/* END JK 06.07.04: Management of sevrals boards */
-			{
-				i_ConvertCJCCalibration = 1;
-			}	/* if(i_CJCPolarity!=i_ADDIDATAPolarity) */
-			else {
-				/* BEGIN JK 06.07.04: Management of sevrals boards */
-				/* if(i_CJCGain==i_ADDIDATAGain) */
-				if (s_BoardInfos[dev->minor].i_CJCGain ==
-					s_BoardInfos[dev->minor].i_ADDIDATAGain)
-					/* END JK 06.07.04: Management of sevrals boards */
-				{
-					i_ConvertCJCCalibration = 0;
-				}	/* if(i_CJCGain==i_ADDIDATAGain) */
-				else {
-					i_ConvertCJCCalibration = 1;
-				}	/* elseif(i_CJCGain==i_ADDIDATAGain) */
-			}	/* elseif(i_CJCPolarity!=i_ADDIDATAPolarity) */
-			if (i_ConvertCJCCalibration == 1) {
-				i_APCI3200_ReadCJCCalOffset(dev,
-					&ui_DummyValue);
-				/* BEGIN JK 06.07.04: Management of sevrals boards */
-				/* ui_InterruptChannelValue[i_Count+4]=ui_DummyValue; */
-				s_BoardInfos[dev->minor].
-					ui_InterruptChannelValue[s_BoardInfos
-					[dev->minor].i_Count + 4] =
-					ui_DummyValue;
-				/* END JK 06.07.04: Management of sevrals boards */
+	ui_CommandRegister = ui_CommandRegister | 0x00080000;
+  /***************************/
+	/*Write the command regiter */
+  /***************************/
+	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+					12) >> 19) & 1) != 1) ;
+	/* outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8); */
+	outl(ui_CommandRegister,
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
 
-				i_APCI3200_ReadCJCCalGain(dev, &ui_DummyValue);
+  /*****************************/
+	/*Test if interrupt is enable */
+  /*****************************/
 
-				/* BEGIN JK 06.07.04: Management of sevrals boards */
-				/* ui_InterruptChannelValue[i_Count+5]=ui_DummyValue; */
-				s_BoardInfos[dev->minor].
-					ui_InterruptChannelValue[s_BoardInfos
-					[dev->minor].i_Count + 5] =
-					ui_DummyValue;
-				/* END JK 06.07.04: Management of sevrals boards */
-			}	/* if(i_ConvertCJCCalibration==1) */
-			else {
-				/* BEGIN JK 06.07.04: Management of sevrals boards */
-				/* ui_InterruptChannelValue[i_Count+4]=0; */
-				/* ui_InterruptChannelValue[i_Count+5]=0; */
+	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
 
-				s_BoardInfos[dev->minor].
-					ui_InterruptChannelValue[s_BoardInfos
-					[dev->minor].i_Count + 4] = 0;
-				s_BoardInfos[dev->minor].
-					ui_InterruptChannelValue[s_BoardInfos
-					[dev->minor].i_Count + 5] = 0;
-				/* END JK 06.07.04: Management of sevrals boards */
-			}	/* elseif(i_ConvertCJCCalibration==1) */
-		}		/* if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)) */
+		do {
 
-		/* BEGIN JK 06.07.04: Management of sevrals boards */
-		/* if(i_ScanType!=1) */
-		if (s_BoardInfos[dev->minor].i_ScanType != 1) {
-			/* i_Count=0; */
-			s_BoardInfos[dev->minor].i_Count = 0;
-		}		/* if(i_ScanType!=1) */
-		else {
-			/* i_Count=i_Count +6; */
-			/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-			/* s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count +6; */
-			s_BoardInfos[dev->minor].i_Count =
-				s_BoardInfos[dev->minor].i_Count + 9;
-			/* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-		}		/* else if(i_ScanType!=1) */
+	  /*******************/
+			/*Read the EOC flag */
+	  /*******************/
 
-		/* if((i_ScanType==1) &&(i_InterruptFlag==1)) */
-		if ((s_BoardInfos[dev->minor].i_ScanType == 1)
-			&& (s_BoardInfos[dev->minor].i_InterruptFlag == 1)) {
-			/* i_Count=i_Count-6; */
-			/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-			/* s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count-6; */
-			s_BoardInfos[dev->minor].i_Count =
-				s_BoardInfos[dev->minor].i_Count - 9;
-			/* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-		}
-		/* if(i_ScanType==0) */
-		if (s_BoardInfos[dev->minor].i_ScanType == 0) {
-			/*
-			   data[0]= ui_InterruptChannelValue[0];
-			   data[1]= ui_InterruptChannelValue[1];
-			   data[2]= ui_InterruptChannelValue[2];
-			   data[3]= ui_InterruptChannelValue[3];
-			   data[4]= ui_InterruptChannelValue[4];
-			   data[5]= ui_InterruptChannelValue[5];
-			 */
-#ifdef PRINT_INFO
-			printk("\n data[0]= s_BoardInfos [dev->minor].ui_InterruptChannelValue[0];");
-#endif
-			data[0] =
-				s_BoardInfos[dev->minor].
-				ui_InterruptChannelValue[0];
-			data[1] =
-				s_BoardInfos[dev->minor].
-				ui_InterruptChannelValue[1];
-			data[2] =
-				s_BoardInfos[dev->minor].
-				ui_InterruptChannelValue[2];
-			data[3] =
-				s_BoardInfos[dev->minor].
-				ui_InterruptChannelValue[3];
-			data[4] =
-				s_BoardInfos[dev->minor].
-				ui_InterruptChannelValue[4];
-			data[5] =
-				s_BoardInfos[dev->minor].
-				ui_InterruptChannelValue[5];
+			/* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
+			ui_EOC = inl(devpriv->iobase +
+				s_BoardInfos[dev->minor].i_Offset + 20) & 1;
 
-			/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-			/* printk("\n 0 - i_APCI3200_GetChannelCalibrationValue data [6] = %lu, data [7] = %lu, data [8] = %lu", data [6], data [7], data [8]); */
-			i_APCI3200_GetChannelCalibrationValue(dev,
-				s_BoardInfos[dev->minor].ui_Channel_num,
-				&data[6], &data[7], &data[8]);
-			/* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-		}
-		break;
-	case 1:
+		} while (ui_EOC != 1);
 
-		for (i = 0; i < insn->n; i++) {
-			/* data[i]=ui_InterruptChannelValue[i]; */
-			data[i] =
-				s_BoardInfos[dev->minor].
-				ui_InterruptChannelValue[i];
-		}
+      /************************************************/
+		/*Read the digital value of the calibration Gain */
+      /************************************************/
 
-		/* i_Count=0; */
-		/* i_Sum=0; */
-		/* if(i_ScanType==1) */
-		s_BoardInfos[dev->minor].i_Count = 0;
-		s_BoardInfos[dev->minor].i_Sum = 0;
-		if (s_BoardInfos[dev->minor].i_ScanType == 1) {
-			/* i_Initialised=0; */
-			/* i_InterruptFlag=0; */
-			s_BoardInfos[dev->minor].i_Initialised = 0;
-			s_BoardInfos[dev->minor].i_InterruptFlag = 0;
-			/* END JK 06.07.04: Management of sevrals boards */
-		}
-		break;
-	default:
-		printk("\nThe parameters passed are in error\n");
-		i_APCI3200_Reset(dev);
-		return -EINVAL;
-	}			/* switch(insn->unused[0]) */
+		/* data[0] = inl(devpriv->iobase+i_Offset + 28); */
+		data[0] =
+			inl(devpriv->iobase +
+			s_BoardInfos[dev->minor].i_Offset + 28);
 
-	return insn->n;
+	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+	return 0;
 }
 
-/*
-  +----------------------------------------------------------------------------+
-  | Function   Name   : int i_APCI3200_Read1AnalogInputChannel                 |
-  |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
-  |                     struct comedi_insn *insn,unsigned int *data)                      |
-  +----------------------------------------------------------------------------+
-  | Task              : Read  value  of the selected channel			         |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
-  |                     unsigned int ui_NoOfChannel    : Channel No to read            |
-  |                     unsigned int *data              : Data Pointer to read status  |
-  +----------------------------------------------------------------------------+
-  | Output Parameters :	--													 |
-  |			          data[0]  : Digital Value read                   |
-  |
-  +----------------------------------------------------------------------------+
-  | Return Value      : TRUE  : No error occur                                 |
-  |		            : FALSE : Error occur. Return the error          |
-  |			                                                         |
-  +----------------------------------------------------------------------------+
-*/
-int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI3200_ReadCJCValue(struct comedi_device *dev,
+				   unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_EOC = 0;
-	unsigned int ui_ChannelNo = 0;
-	unsigned int ui_CommandRegister = 0;
-
-	/* BEGIN JK 06.07.04: Management of sevrals boards */
-	/* ui_ChannelNo=i_ChannelNo; */
-	ui_ChannelNo = s_BoardInfos[dev->minor].i_ChannelNo;
+	int ui_CommandRegister = 0;
 
-	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
-	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
-					12) >> 19) & 1) != 1) ;
-  /*********************************/
-	/* Write the channel to configure */
-  /*********************************/
-	/* Begin JK 20.10.2004: Bad channel value is used when using differential mode */
-	/* outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); */
-	/* outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4); */
-	outl(0 | s_BoardInfos[dev->minor].i_ChannelNo,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x4);
-	/* End JK 20.10.2004: Bad channel value is used when using differential mode */
+  /******************************/
+	/*Set the converting time unit */
+  /******************************/
 
-  /*******************************/
-	/* Set the convert timing unit */
-  /*******************************/
 	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
 					12) >> 19) & 1) != 1) ;
@@ -1680,7 +1004,6 @@ int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev,
 	/* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
 	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
-
   /**************************/
 	/* Set the convert timing */
   /**************************/
@@ -1692,102 +1015,88 @@ int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev,
 	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
 
-  /**************************************************************************/
-	/* Set the start end stop index to the selected channel and set the start */
-  /**************************************************************************/
-
-	ui_CommandRegister = ui_ChannelNo | (ui_ChannelNo << 8) | 0x80000;
+  /******************************/
+	/*Configure the CJC Conversion */
+  /******************************/
+	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+					12) >> 19) & 1) != 1) ;
 
+	/* outl( 0x00000400 , devpriv->iobase+i_Offset + 4); */
+	outl(0x00000400,
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+  /*******************************/
+	/*Initialise dw_CommandRegister */
+  /*******************************/
+	ui_CommandRegister = 0;
   /*********************************/
 	/*Test if the interrupt is enable */
   /*********************************/
-
 	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
-      /************************/
-		/* Enable the interrupt */
-      /************************/
+      /**********************/
+		/*Enable the interrupt */
+      /**********************/
 		ui_CommandRegister = ui_CommandRegister | 0x00100000;
-	}			/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+	}
 
-  /******************************/
-	/* Write the command register */
-  /******************************/
+  /**********************/
+	/*Start the conversion */
+  /**********************/
+
+	ui_CommandRegister = ui_CommandRegister | 0x00080000;
+
+  /***************************/
+	/*Write the command regiter */
+  /***************************/
 	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
 					12) >> 19) & 1) != 1) ;
-
-	/* outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8); */
+	/* outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8); */
 	outl(ui_CommandRegister,
 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
 
   /*****************************/
 	/*Test if interrupt is enable */
   /*****************************/
+
 	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
 		do {
-	  /*************************/
-			/*Read the EOC Status bit */
-	  /*************************/
 
-			/* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
-			ui_EOC = inl(devpriv->iobase +
-				s_BoardInfos[dev->minor].i_Offset + 20) & 1;
+	  /*******************/
+			/*Read the EOC flag */
+	  /*******************/
+
+			/* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
+			ui_EOC = inl(devpriv->iobase +
+				s_BoardInfos[dev->minor].i_Offset + 20) & 1;
 
 		} while (ui_EOC != 1);
 
-      /***************************************/
-		/* Read the digital value of the input */
-      /***************************************/
+      /***********************************/
+		/*Read the digital value of the CJC */
+      /***********************************/
 
-		/* data[0] = inl (devpriv->iobase+i_Offset + 28); */
+		/* data[0] = inl(devpriv->iobase+i_Offset + 28); */
 		data[0] =
 			inl(devpriv->iobase +
 			s_BoardInfos[dev->minor].i_Offset + 28);
-		/* END JK 06.07.04: Management of sevrals boards */
 
-	}			/*  if (i_InterruptFlag == ADDIDATA_DISABLE) */
+	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
 	return 0;
 }
 
-/*
-  +----------------------------------------------------------------------------+
-  | Function   Name   : int i_APCI3200_ReadCalibrationOffsetValue              |
-  |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
-  |                     struct comedi_insn *insn,unsigned int *data)                      |
-  +----------------------------------------------------------------------------+
-  | Task              : Read calibration offset  value  of the selected channel|
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
-  |                     unsigned int *data              : Data Pointer to read status  |
-  +----------------------------------------------------------------------------+
-  | Output Parameters :	--													 |
-  |			          data[0]  : Calibration offset Value   |
-  |
-  +----------------------------------------------------------------------------+
-  | Return Value      : TRUE  : No error occur                                 |
-  |		            : FALSE : Error occur. Return the error          |
-  |			                                                         |
-  +----------------------------------------------------------------------------+
-*/
-int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, unsigned int *data)
+static int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev,
+				       unsigned int *data)
 {
-	unsigned int ui_Temp = 0, ui_EOC = 0;
-	unsigned int ui_CommandRegister = 0;
-
-	/* BEGIN JK 06.07.04: Management of sevrals boards */
-	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
-	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
-					12) >> 19) & 1) != 1) ;
-  /*********************************/
-	/* Write the channel to configure */
-  /*********************************/
-	/* Begin JK 20.10.2004: This seems not necessary ! */
-	/* outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); */
-	/* outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4); */
-	/* End JK 20.10.2004: This seems not necessary ! */
+	struct addi_private *devpriv = dev->private;
+	unsigned int ui_EOC = 0;
+	int ui_CommandRegister = 0;
 
+  /*******************************************/
+	/*Read calibration offset value for the CJC */
+  /*******************************************/
   /*******************************/
 	/* Set the convert timing unit */
   /*******************************/
@@ -1806,80 +1115,69 @@ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, unsigned in
 	/* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
 	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
-  /*****************************/
-	/*Read the calibration offset */
-  /*****************************/
-	/* ui_Temp = inl(devpriv->iobase+i_Offset + 12); */
-	ui_Temp = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
-
+  /******************************/
+	/*Configure the CJC Conversion */
+  /******************************/
+	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+					12) >> 19) & 1) != 1) ;
+	/* outl(0x00000400 , devpriv->iobase+i_Offset + 4); */
+	outl(0x00000400,
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
   /*********************************/
 	/*Configure the Offset Conversion */
   /*********************************/
 	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
 					12) >> 19) & 1) != 1) ;
-	/* outl((ui_Temp | 0x00020000), devpriv->iobase+i_Offset + 12); */
-	outl((ui_Temp | 0x00020000),
+	/* outl(0x00020000, devpriv->iobase+i_Offset + 12); */
+	outl(0x00020000,
 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
   /*******************************/
 	/*Initialise ui_CommandRegister */
   /*******************************/
-
 	ui_CommandRegister = 0;
-
   /*********************************/
 	/*Test if the interrupt is enable */
   /*********************************/
 
 	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
-
       /**********************/
 		/*Enable the interrupt */
       /**********************/
-
 		ui_CommandRegister = ui_CommandRegister | 0x00100000;
 
-	}			/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
+	}
 
   /**********************/
 	/*Start the conversion */
   /**********************/
 	ui_CommandRegister = ui_CommandRegister | 0x00080000;
-
   /***************************/
 	/*Write the command regiter */
   /***************************/
 	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
 					12) >> 19) & 1) != 1) ;
-	/* outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8); */
+	/* outl(ui_CommandRegister,devpriv->iobase+i_Offset + 8); */
 	outl(ui_CommandRegister,
 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
-
-  /*****************************/
-	/*Test if interrupt is enable */
-  /*****************************/
-
 	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
-
 		do {
 	  /*******************/
 			/*Read the EOC flag */
 	  /*******************/
-
-			/* ui_EOC = inl (devpriv->iobase+i_Offset + 20) & 1; */
+			/* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
 			ui_EOC = inl(devpriv->iobase +
 				s_BoardInfos[dev->minor].i_Offset + 20) & 1;
-
 		} while (ui_EOC != 1);
 
       /**************************************************/
 		/*Read the digital value of the calibration Offset */
       /**************************************************/
-
-		/* data[0] = inl(devpriv->iobase+i_Offset+ 28); */
+		/* data[0] = inl(devpriv->iobase+i_Offset + 28); */
 		data[0] =
 			inl(devpriv->iobase +
 			s_BoardInfos[dev->minor].i_Offset + 28);
@@ -1887,45 +1185,13 @@ int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, unsigned in
 	return 0;
 }
 
-/*
-  +----------------------------------------------------------------------------+
-  | Function   Name   : int i_APCI3200_ReadCalibrationGainValue                |
-  |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
-  |                     struct comedi_insn *insn,unsigned int *data)                      |
-  +----------------------------------------------------------------------------+
-  | Task              : Read calibration gain  value  of the selected channel  |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
-  |                     unsigned int *data              : Data Pointer to read status  |
-  +----------------------------------------------------------------------------+
-  | Output Parameters :	--													 |
-  |			          data[0]  : Calibration gain Value Of Input     |
-  |
-  +----------------------------------------------------------------------------+
-  | Return Value      : TRUE  : No error occur                                 |
-  |		            : FALSE : Error occur. Return the error          |
-  |			                                                         |
-  +----------------------------------------------------------------------------+
-*/
-int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, unsigned int *data)
+static int i_APCI3200_ReadCJCCalGain(struct comedi_device *dev,
+				     unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_EOC = 0;
 	int ui_CommandRegister = 0;
 
-	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
-	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
-					12) >> 19) & 1) != 1) ;
-  /*********************************/
-	/* Write the channel to configure */
-  /*********************************/
-	/* Begin JK 20.10.2004: This seems not necessary ! */
-	/* outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); */
-	/* outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4); */
-	/* End JK 20.10.2004: This seems not necessary ! */
-
-  /***************************/
-	/*Read the calibration gain */
-  /***************************/
   /*******************************/
 	/* Set the convert timing unit */
   /*******************************/
@@ -1944,41 +1210,42 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, unsigned int
 	/* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
 	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
+  /******************************/
+	/*Configure the CJC Conversion */
+  /******************************/
+	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+					12) >> 19) & 1) != 1) ;
+	/* outl(0x00000400,devpriv->iobase+i_Offset + 4); */
+	outl(0x00000400,
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
   /*******************************/
 	/*Configure the Gain Conversion */
   /*******************************/
 	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
 					12) >> 19) & 1) != 1) ;
-	/* outl(0x00040000 , devpriv->iobase+i_Offset + 12); */
+	/* outl(0x00040000,devpriv->iobase+i_Offset + 12); */
 	outl(0x00040000,
 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
 
   /*******************************/
-	/*Initialise ui_CommandRegister */
+	/*Initialise dw_CommandRegister */
   /*******************************/
-
 	ui_CommandRegister = 0;
-
   /*********************************/
 	/*Test if the interrupt is enable */
   /*********************************/
-
 	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
-
       /**********************/
 		/*Enable the interrupt */
       /**********************/
-
 		ui_CommandRegister = ui_CommandRegister | 0x00100000;
-
-	}			/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
-
+	}
   /**********************/
 	/*Start the conversion */
   /**********************/
-
 	ui_CommandRegister = ui_CommandRegister | 0x00080000;
   /***************************/
 	/*Write the command regiter */
@@ -1986,424 +1253,866 @@ int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, unsigned int
 	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
 					12) >> 19) & 1) != 1) ;
-	/* outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8); */
+	/* outl(ui_CommandRegister ,devpriv->iobase+i_Offset + 8); */
 	outl(ui_CommandRegister,
 		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
-
-  /*****************************/
-	/*Test if interrupt is enable */
-  /*****************************/
-
 	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
 	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
-
 		do {
-
 	  /*******************/
 			/*Read the EOC flag */
 	  /*******************/
-
 			/* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
 			ui_EOC = inl(devpriv->iobase +
 				s_BoardInfos[dev->minor].i_Offset + 20) & 1;
-
 		} while (ui_EOC != 1);
-
       /************************************************/
 		/*Read the digital value of the calibration Gain */
       /************************************************/
-
-		/* data[0] = inl(devpriv->iobase+i_Offset + 28); */
+		/* data[0] = inl (devpriv->iobase+i_Offset + 28); */
 		data[0] =
 			inl(devpriv->iobase +
 			s_BoardInfos[dev->minor].i_Offset + 28);
-
 	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
 	return 0;
 }
 
-/*
-  +----------------------------------------------------------------------------+
-  | Function   Name   : int i_APCI3200_ReadCJCValue                            |
-  |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
-  |                     struct comedi_insn *insn,unsigned int *data)                      |
-  +----------------------------------------------------------------------------+
-  | Task              : Read CJC  value  of the selected channel               |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
-  |                     unsigned int *data              : Data Pointer to read status  |
-  +----------------------------------------------------------------------------+
-  | Output Parameters :	--													 |
-  |			          data[0]  : CJC Value                           |
-  |
-  +----------------------------------------------------------------------------+
-  | Return Value      : TRUE  : No error occur                                 |
-  |		            : FALSE : Error occur. Return the error          |
-  |			                                                         |
-  +----------------------------------------------------------------------------+
-*/
-
-int i_APCI3200_ReadCJCValue(struct comedi_device *dev, unsigned int *data)
+static int i_APCI3200_Reset(struct comedi_device *dev)
 {
-	unsigned int ui_EOC = 0;
-	int ui_CommandRegister = 0;
-
-  /******************************/
-	/*Set the converting time unit */
-  /******************************/
-
-	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
-	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
-					12) >> 19) & 1) != 1) ;
-
-	/* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
-	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
-  /**************************/
-	/* Set the convert timing */
-  /**************************/
-	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
-	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
-					12) >> 19) & 1) != 1) ;
-
-	/* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
-	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
-
-  /******************************/
-	/*Configure the CJC Conversion */
-  /******************************/
-	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
-	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
-					12) >> 19) & 1) != 1) ;
-
-	/* outl( 0x00000400 , devpriv->iobase+i_Offset + 4); */
-	outl(0x00000400,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
-  /*******************************/
-	/*Initialise dw_CommandRegister */
-  /*******************************/
-	ui_CommandRegister = 0;
-  /*********************************/
-	/*Test if the interrupt is enable */
-  /*********************************/
-	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
-      /**********************/
-		/*Enable the interrupt */
-      /**********************/
-		ui_CommandRegister = ui_CommandRegister | 0x00100000;
-	}
+	struct addi_private *devpriv = dev->private;
+	int i_Temp;
+	unsigned int dw_Dummy;
 
-  /**********************/
-	/*Start the conversion */
-  /**********************/
+	/* i_InterruptFlag=0; */
+	/* i_Initialised==0; */
+	/* i_Count=0; */
+	/* i_Sum=0; */
 
-	ui_CommandRegister = ui_CommandRegister | 0x00080000;
+	s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+	s_BoardInfos[dev->minor].i_Initialised = 0;
+	s_BoardInfos[dev->minor].i_Count = 0;
+	s_BoardInfos[dev->minor].i_Sum = 0;
+	s_BoardInfos[dev->minor].b_StructInitialized = 0;
 
-  /***************************/
-	/*Write the command regiter */
-  /***************************/
-	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
-	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
-					12) >> 19) & 1) != 1) ;
-	/* outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8); */
-	outl(ui_CommandRegister,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+	outl(0x83838383, devpriv->i_IobaseAmcc + 0x60);
 
+	/*  Enable the interrupt for the controller */
+	dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38);
+	outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38);
+	outl(0, devpriv->i_IobaseAddon);	/* Resets the output */
+  /***************/
+	/*Empty the buffer */
+  /**************/
+	for (i_Temp = 0; i_Temp <= 95; i_Temp++) {
+		/* ui_InterruptChannelValue[i_Temp]=0; */
+		s_BoardInfos[dev->minor].ui_InterruptChannelValue[i_Temp] = 0;
+	}			/* for(i_Temp=0;i_Temp<=95;i_Temp++) */
   /*****************************/
-	/*Test if interrupt is enable */
+	/*Reset the START and IRQ bit */
   /*****************************/
-
-	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
-		do {
-
-	  /*******************/
-			/*Read the EOC flag */
-	  /*******************/
-
-			/* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
-			ui_EOC = inl(devpriv->iobase +
-				s_BoardInfos[dev->minor].i_Offset + 20) & 1;
-
-		} while (ui_EOC != 1);
-
-      /***********************************/
-		/*Read the digital value of the CJC */
-      /***********************************/
-
-		/* data[0] = inl(devpriv->iobase+i_Offset + 28); */
-		data[0] =
-			inl(devpriv->iobase +
-			s_BoardInfos[dev->minor].i_Offset + 28);
-
-	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
+	for (i_Temp = 0; i_Temp <= 192;) {
+		while (((inl(devpriv->iobase + i_Temp + 12) >> 19) & 1) != 1) ;
+		outl(0, devpriv->iobase + i_Temp + 8);
+		i_Temp = i_Temp + 64;
+	}			/* for(i_Temp=0;i_Temp<=192;i_Temp+64) */
 	return 0;
 }
 
 /*
-  +----------------------------------------------------------------------------+
-  | Function   Name   : int i_APCI3200_ReadCJCCalOffset                        |
-  |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
-  |                     struct comedi_insn *insn,unsigned int *data)                      |
-  +----------------------------------------------------------------------------+
-  | Task              : Read CJC calibration offset  value  of the selected channel
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
-  |                     unsigned int *data              : Data Pointer to read status  |
-  +----------------------------------------------------------------------------+
-  | Output Parameters :	--													 |
-  |			          data[0]  : CJC calibration offset Value
-  |
-  +----------------------------------------------------------------------------+
-  | Return Value      : TRUE  : No error occur                                 |
-  |		            : FALSE : Error occur. Return the error          |
-  |			                                                         |
-  +----------------------------------------------------------------------------+
-*/
-int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev, unsigned int *data)
+ * Read value of the selected channel
+ *
+ * data[0]  : Digital Value Of Input
+ * data[1]  : Calibration Offset Value
+ * data[2]  : Calibration Gain Value
+ * data[3]  : CJC value
+ * data[4]  : CJC offset value
+ * data[5]  : CJC gain value
+ * data[6] : CJC current source from eeprom
+ * data[7] : Channel current source from eeprom
+ * data[8] : Channle gain factor from eeprom
+ */
+static int i_APCI3200_ReadAnalogInput(struct comedi_device *dev,
+				      struct comedi_subdevice *s,
+				      struct comedi_insn *insn,
+				      unsigned int *data)
 {
-	unsigned int ui_EOC = 0;
-	int ui_CommandRegister = 0;
-  /*******************************************/
-	/*Read calibration offset value for the CJC */
-  /*******************************************/
-  /*******************************/
-	/* Set the convert timing unit */
-  /*******************************/
-	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
-	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
-					12) >> 19) & 1) != 1) ;
-	/* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
-	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
-  /**************************/
-	/* Set the convert timing */
-  /**************************/
-	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
-	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
-					12) >> 19) & 1) != 1) ;
-	/* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
-	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
-  /******************************/
-	/*Configure the CJC Conversion */
-  /******************************/
-	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
-	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
-					12) >> 19) & 1) != 1) ;
-	/* outl(0x00000400 , devpriv->iobase+i_Offset + 4); */
-	outl(0x00000400,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
-  /*********************************/
-	/*Configure the Offset Conversion */
-  /*********************************/
-	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
-	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
-					12) >> 19) & 1) != 1) ;
-	/* outl(0x00020000, devpriv->iobase+i_Offset + 12); */
-	outl(0x00020000,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
-  /*******************************/
-	/*Initialise ui_CommandRegister */
-  /*******************************/
-	ui_CommandRegister = 0;
-  /*********************************/
-	/*Test if the interrupt is enable */
-  /*********************************/
+	unsigned int ui_DummyValue = 0;
+	int i_ConvertCJCCalibration;
+	int i = 0;
+
+	/* BEGIN JK 06.07.04: Management of sevrals boards */
+	/* if(i_Initialised==0) */
+	if (s_BoardInfos[dev->minor].i_Initialised == 0)
+		/* END JK 06.07.04: Management of sevrals boards */
+	{
+		i_APCI3200_Reset(dev);
+		return -EINVAL;
+	}			/* if(i_Initialised==0); */
+
+#ifdef PRINT_INFO
+	printk("\n insn->unused[0] = %i", insn->unused[0]);
+#endif
+
+	switch (insn->unused[0]) {
+	case 0:
+
+		i_APCI3200_Read1AnalogInputChannel(dev, s, insn,
+			&ui_DummyValue);
+		/* BEGIN JK 06.07.04: Management of sevrals boards */
+		/* ui_InterruptChannelValue[i_Count+0]=ui_DummyValue; */
+		s_BoardInfos[dev->minor].
+			ui_InterruptChannelValue[s_BoardInfos[dev->minor].
+			i_Count + 0] = ui_DummyValue;
+		/* END JK 06.07.04: Management of sevrals boards */
+
+		/* Begin JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+		i_APCI3200_GetChannelCalibrationValue(dev,
+			s_BoardInfos[dev->minor].ui_Channel_num,
+			&s_BoardInfos[dev->minor].
+			ui_InterruptChannelValue[s_BoardInfos[dev->minor].
+				i_Count + 6],
+			&s_BoardInfos[dev->minor].
+			ui_InterruptChannelValue[s_BoardInfos[dev->minor].
+				i_Count + 7],
+			&s_BoardInfos[dev->minor].
+			ui_InterruptChannelValue[s_BoardInfos[dev->minor].
+				i_Count + 8]);
+
+#ifdef PRINT_INFO
+		printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+6] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 6]);
+
+		printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+7] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 7]);
+
+		printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+8] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 8]);
+#endif
+
+		/* End JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+
+		/* BEGIN JK 06.07.04: Management of sevrals boards */
+		/* if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1)) */
+		if ((s_BoardInfos[dev->minor].i_ADDIDATAType == 2)
+			&& (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE)
+			&& (s_BoardInfos[dev->minor].i_CJCAvailable == 1))
+			/* END JK 06.07.04: Management of sevrals boards */
+		{
+			i_APCI3200_ReadCJCValue(dev, &ui_DummyValue);
+			/* BEGIN JK 06.07.04: Management of sevrals boards */
+			/* ui_InterruptChannelValue[i_Count + 3]=ui_DummyValue; */
+			s_BoardInfos[dev->minor].
+				ui_InterruptChannelValue[s_BoardInfos[dev->
+					minor].i_Count + 3] = ui_DummyValue;
+			/* END JK 06.07.04: Management of sevrals boards */
+		}		/* if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)) */
+		else {
+			/* BEGIN JK 06.07.04: Management of sevrals boards */
+			/* ui_InterruptChannelValue[i_Count + 3]=0; */
+			s_BoardInfos[dev->minor].
+				ui_InterruptChannelValue[s_BoardInfos[dev->
+					minor].i_Count + 3] = 0;
+			/* END JK 06.07.04: Management of sevrals boards */
+		}		/* elseif((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1)) */
+
+		/* BEGIN JK 06.07.04: Management of sevrals boards */
+		/* if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE)) */
+		if ((s_BoardInfos[dev->minor].i_AutoCalibration == FALSE)
+			&& (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE))
+			/* END JK 06.07.04: Management of sevrals boards */
+		{
+			i_APCI3200_ReadCalibrationOffsetValue(dev,
+				&ui_DummyValue);
+			/* BEGIN JK 06.07.04: Management of sevrals boards */
+			/* ui_InterruptChannelValue[i_Count + 1]=ui_DummyValue; */
+			s_BoardInfos[dev->minor].
+				ui_InterruptChannelValue[s_BoardInfos[dev->
+					minor].i_Count + 1] = ui_DummyValue;
+			/* END JK 06.07.04: Management of sevrals boards */
+			i_APCI3200_ReadCalibrationGainValue(dev,
+				&ui_DummyValue);
+			/* BEGIN JK 06.07.04: Management of sevrals boards */
+			/* ui_InterruptChannelValue[i_Count + 2]=ui_DummyValue; */
+			s_BoardInfos[dev->minor].
+				ui_InterruptChannelValue[s_BoardInfos[dev->
+					minor].i_Count + 2] = ui_DummyValue;
+			/* END JK 06.07.04: Management of sevrals boards */
+		}		/* if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE)) */
+
+		/* BEGIN JK 06.07.04: Management of sevrals boards */
+		/* if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)&& (i_CJCAvailable==1)) */
+		if ((s_BoardInfos[dev->minor].i_ADDIDATAType == 2)
+			&& (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE)
+			&& (s_BoardInfos[dev->minor].i_CJCAvailable == 1))
+			/* END JK 06.07.04: Management of sevrals boards */
+		{
+	  /**********************************************************/
+			/*Test if the Calibration channel must be read for the CJC */
+	  /**********************************************************/
+	  /**********************************/
+			/*Test if the polarity is the same */
+	  /**********************************/
+			/* BEGIN JK 06.07.04: Management of sevrals boards */
+			/* if(i_CJCPolarity!=i_ADDIDATAPolarity) */
+			if (s_BoardInfos[dev->minor].i_CJCPolarity !=
+				s_BoardInfos[dev->minor].i_ADDIDATAPolarity)
+				/* END JK 06.07.04: Management of sevrals boards */
+			{
+				i_ConvertCJCCalibration = 1;
+			}	/* if(i_CJCPolarity!=i_ADDIDATAPolarity) */
+			else {
+				/* BEGIN JK 06.07.04: Management of sevrals boards */
+				/* if(i_CJCGain==i_ADDIDATAGain) */
+				if (s_BoardInfos[dev->minor].i_CJCGain ==
+					s_BoardInfos[dev->minor].i_ADDIDATAGain)
+					/* END JK 06.07.04: Management of sevrals boards */
+				{
+					i_ConvertCJCCalibration = 0;
+				}	/* if(i_CJCGain==i_ADDIDATAGain) */
+				else {
+					i_ConvertCJCCalibration = 1;
+				}	/* elseif(i_CJCGain==i_ADDIDATAGain) */
+			}	/* elseif(i_CJCPolarity!=i_ADDIDATAPolarity) */
+			if (i_ConvertCJCCalibration == 1) {
+				i_APCI3200_ReadCJCCalOffset(dev,
+					&ui_DummyValue);
+				/* BEGIN JK 06.07.04: Management of sevrals boards */
+				/* ui_InterruptChannelValue[i_Count+4]=ui_DummyValue; */
+				s_BoardInfos[dev->minor].
+					ui_InterruptChannelValue[s_BoardInfos
+					[dev->minor].i_Count + 4] =
+					ui_DummyValue;
+				/* END JK 06.07.04: Management of sevrals boards */
+
+				i_APCI3200_ReadCJCCalGain(dev, &ui_DummyValue);
+
+				/* BEGIN JK 06.07.04: Management of sevrals boards */
+				/* ui_InterruptChannelValue[i_Count+5]=ui_DummyValue; */
+				s_BoardInfos[dev->minor].
+					ui_InterruptChannelValue[s_BoardInfos
+					[dev->minor].i_Count + 5] =
+					ui_DummyValue;
+				/* END JK 06.07.04: Management of sevrals boards */
+			}	/* if(i_ConvertCJCCalibration==1) */
+			else {
+				/* BEGIN JK 06.07.04: Management of sevrals boards */
+				/* ui_InterruptChannelValue[i_Count+4]=0; */
+				/* ui_InterruptChannelValue[i_Count+5]=0; */
+
+				s_BoardInfos[dev->minor].
+					ui_InterruptChannelValue[s_BoardInfos
+					[dev->minor].i_Count + 4] = 0;
+				s_BoardInfos[dev->minor].
+					ui_InterruptChannelValue[s_BoardInfos
+					[dev->minor].i_Count + 5] = 0;
+				/* END JK 06.07.04: Management of sevrals boards */
+			}	/* elseif(i_ConvertCJCCalibration==1) */
+		}		/* if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)) */
+
+		/* BEGIN JK 06.07.04: Management of sevrals boards */
+		/* if(i_ScanType!=1) */
+		if (s_BoardInfos[dev->minor].i_ScanType != 1) {
+			/* i_Count=0; */
+			s_BoardInfos[dev->minor].i_Count = 0;
+		}		/* if(i_ScanType!=1) */
+		else {
+			/* i_Count=i_Count +6; */
+			/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+			/* s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count +6; */
+			s_BoardInfos[dev->minor].i_Count =
+				s_BoardInfos[dev->minor].i_Count + 9;
+			/* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+		}		/* else if(i_ScanType!=1) */
+
+		/* if((i_ScanType==1) &&(i_InterruptFlag==1)) */
+		if ((s_BoardInfos[dev->minor].i_ScanType == 1)
+			&& (s_BoardInfos[dev->minor].i_InterruptFlag == 1)) {
+			/* i_Count=i_Count-6; */
+			/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+			/* s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count-6; */
+			s_BoardInfos[dev->minor].i_Count =
+				s_BoardInfos[dev->minor].i_Count - 9;
+			/* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+		}
+		/* if(i_ScanType==0) */
+		if (s_BoardInfos[dev->minor].i_ScanType == 0) {
+			/*
+			   data[0]= ui_InterruptChannelValue[0];
+			   data[1]= ui_InterruptChannelValue[1];
+			   data[2]= ui_InterruptChannelValue[2];
+			   data[3]= ui_InterruptChannelValue[3];
+			   data[4]= ui_InterruptChannelValue[4];
+			   data[5]= ui_InterruptChannelValue[5];
+			 */
+#ifdef PRINT_INFO
+			printk("\n data[0]= s_BoardInfos [dev->minor].ui_InterruptChannelValue[0];");
+#endif
+			data[0] =
+				s_BoardInfos[dev->minor].
+				ui_InterruptChannelValue[0];
+			data[1] =
+				s_BoardInfos[dev->minor].
+				ui_InterruptChannelValue[1];
+			data[2] =
+				s_BoardInfos[dev->minor].
+				ui_InterruptChannelValue[2];
+			data[3] =
+				s_BoardInfos[dev->minor].
+				ui_InterruptChannelValue[3];
+			data[4] =
+				s_BoardInfos[dev->minor].
+				ui_InterruptChannelValue[4];
+			data[5] =
+				s_BoardInfos[dev->minor].
+				ui_InterruptChannelValue[5];
+
+			/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+			/* printk("\n 0 - i_APCI3200_GetChannelCalibrationValue data [6] = %lu, data [7] = %lu, data [8] = %lu", data [6], data [7], data [8]); */
+			i_APCI3200_GetChannelCalibrationValue(dev,
+				s_BoardInfos[dev->minor].ui_Channel_num,
+				&data[6], &data[7], &data[8]);
+			/* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+		}
+		break;
+	case 1:
+
+		for (i = 0; i < insn->n; i++) {
+			/* data[i]=ui_InterruptChannelValue[i]; */
+			data[i] =
+				s_BoardInfos[dev->minor].
+				ui_InterruptChannelValue[i];
+		}
+
+		/* i_Count=0; */
+		/* i_Sum=0; */
+		/* if(i_ScanType==1) */
+		s_BoardInfos[dev->minor].i_Count = 0;
+		s_BoardInfos[dev->minor].i_Sum = 0;
+		if (s_BoardInfos[dev->minor].i_ScanType == 1) {
+			/* i_Initialised=0; */
+			/* i_InterruptFlag=0; */
+			s_BoardInfos[dev->minor].i_Initialised = 0;
+			s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+			/* END JK 06.07.04: Management of sevrals boards */
+		}
+		break;
+	default:
+		printk("\nThe parameters passed are in error\n");
+		i_APCI3200_Reset(dev);
+		return -EINVAL;
+	}			/* switch(insn->unused[0]) */
+
+	return insn->n;
+}
+
+/*
+ * Configures The Analog Input Subdevice
+ *
+ * data[0]  = 0  Normal AI
+ *	    = 1  RTD
+ *	    = 2  THERMOCOUPLE
+ * data[1]  = Gain To Use
+ * data[2]  = 0  Bipolar
+ *	    = 1  Unipolar
+ * data[3]  = Offset Range
+ * data[4]  = 0  DC Coupling
+ *	    = 1  AC Coupling
+ * data[5]  = 0  Single
+ *	    = 1  Differential
+ * data[6]  = TimerReloadValue
+ * data[7]  = ConvertingTimeUnit
+ * data[8]  = 0  Analog voltage measurement
+ *	    = 1  Resistance measurement
+ *	    = 2  Temperature measurement
+ * data[9]  = 0  Interrupt Disable
+ *	    = 1  INterrupt Enable
+ * data[10] = Type of Thermocouple
+ * data[11] = single channel Module Number
+ * data[12] = 0  Single Read
+ *	    = 1  Read more channel
+ *	    = 2  Single scan
+ *	    = 3  Continuous Scan
+ * data[13] = Number of channels to read
+ * data[14] = 0  RTD not used
+ *	    = 1  RTD 2 wire connection
+ *	    = 2  RTD 3 wire connection
+ *	    = 3  RTD 4 wire connection
+ */
+static int i_APCI3200_ConfigAnalogInput(struct comedi_device *dev,
+					struct comedi_subdevice *s,
+					struct comedi_insn *insn,
+					unsigned int *data)
+{
+	struct addi_private *devpriv = dev->private;
+	unsigned int ul_Config = 0, ul_Temp = 0;
+	unsigned int ui_ChannelNo = 0;
+	unsigned int ui_Dummy = 0;
+	int i_err = 0;
+
+	/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+
+#ifdef PRINT_INFO
+	int i = 0, i2 = 0;
+#endif
+	/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+
+	/* BEGIN JK 06.07.04: Management of sevrals boards */
+	/*  Initialize the structure */
+	if (s_BoardInfos[dev->minor].b_StructInitialized != 1) {
+		s_BoardInfos[dev->minor].i_CJCAvailable = 1;
+		s_BoardInfos[dev->minor].i_CJCPolarity = 0;
+		s_BoardInfos[dev->minor].i_CJCGain = 2;	/* changed from 0 to 2 */
+		s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+		s_BoardInfos[dev->minor].i_AutoCalibration = 0;	/* : auto calibration */
+		s_BoardInfos[dev->minor].i_ChannelCount = 0;
+		s_BoardInfos[dev->minor].i_Sum = 0;
+		s_BoardInfos[dev->minor].ui_Channel_num = 0;
+		s_BoardInfos[dev->minor].i_Count = 0;
+		s_BoardInfos[dev->minor].i_Initialised = 0;
+		s_BoardInfos[dev->minor].b_StructInitialized = 1;
+
+		/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+		s_BoardInfos[dev->minor].i_ConnectionType = 0;
+		/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+
+		/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+		memset(s_BoardInfos[dev->minor].s_Module, 0,
+			sizeof(s_BoardInfos[dev->minor].s_Module[MAX_MODULE]));
+
+		v_GetAPCI3200EepromCalibrationValue(devpriv->i_IobaseAmcc,
+			&s_BoardInfos[dev->minor]);
+
+#ifdef PRINT_INFO
+		for (i = 0; i < MAX_MODULE; i++) {
+			printk("\n s_Module[%i].ul_CurrentSourceCJC = %lu", i,
+				s_BoardInfos[dev->minor].s_Module[i].
+				ul_CurrentSourceCJC);
+
+			for (i2 = 0; i2 < 5; i2++) {
+				printk("\n s_Module[%i].ul_CurrentSource [%i] = %lu", i, i2, s_BoardInfos[dev->minor].s_Module[i].ul_CurrentSource[i2]);
+			}
+
+			for (i2 = 0; i2 < 8; i2++) {
+				printk("\n s_Module[%i].ul_GainFactor [%i] = %lu", i, i2, s_BoardInfos[dev->minor].s_Module[i].ul_GainFactor[i2]);
+			}
+
+			for (i2 = 0; i2 < 8; i2++) {
+				printk("\n s_Module[%i].w_GainValue [%i] = %u",
+					i, i2,
+					s_BoardInfos[dev->minor].s_Module[i].
+					w_GainValue[i2]);
+			}
+		}
+#endif
+		/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+	}
+
+	if (data[0] != 0 && data[0] != 1 && data[0] != 2) {
+		printk("\nThe selection of acquisition type is in error\n");
+		i_err++;
+	}			/* if(data[0]!=0 && data[0]!=1 && data[0]!=2) */
+	if (data[0] == 1) {
+		if (data[14] != 0 && data[14] != 1 && data[14] != 2
+			&& data[14] != 4) {
+			printk("\n Error in selection of RTD connection type\n");
+			i_err++;
+		}		/* if(data[14]!=0 && data[14]!=1 && data[14]!=2 && data[14]!=4) */
+	}			/* if(data[0]==1 ) */
+	if (data[1] < 0 || data[1] > 7) {
+		printk("\nThe selection of gain is in error\n");
+		i_err++;
+	}			/*  if(data[1]<0 || data[1]>7) */
+	if (data[2] != 0 && data[2] != 1) {
+		printk("\nThe selection of polarity is in error\n");
+		i_err++;
+	}			/* if(data[2]!=0 &&  data[2]!=1) */
+	if (data[3] != 0) {
+		printk("\nThe selection of offset range  is in error\n");
+		i_err++;
+	}			/*  if(data[3]!=0) */
+	if (data[4] != 0 && data[4] != 1) {
+		printk("\nThe selection of coupling is in error\n");
+		i_err++;
+	}			/* if(data[4]!=0 &&  data[4]!=1) */
+	if (data[5] != 0 && data[5] != 1) {
+		printk("\nThe selection of single/differential mode is in error\n");
+		i_err++;
+	}			/* if(data[5]!=0 &&  data[5]!=1) */
+	if (data[8] != 0 && data[8] != 1 && data[2] != 2) {
+		printk("\nError in selection of functionality\n");
+	}			/* if(data[8]!=0 && data[8]!=1 && data[2]!=2) */
+	if (data[12] == 0 || data[12] == 1) {
+		if (data[6] != 20 && data[6] != 40 && data[6] != 80
+			&& data[6] != 160) {
+			printk("\nThe selection of conversion time reload value is in error\n");
+			i_err++;
+		}		/*  if (data[6]!=20 && data[6]!=40 && data[6]!=80 && data[6]!=160 ) */
+		if (data[7] != 2) {
+			printk("\nThe selection of conversion time unit  is in error\n");
+			i_err++;
+		}		/*  if(data[7]!=2) */
+	}
+	if (data[9] != 0 && data[9] != 1) {
+		printk("\nThe selection of interrupt enable is in error\n");
+		i_err++;
+	}			/* if(data[9]!=0 &&  data[9]!=1) */
+	if (data[11] < 0 || data[11] > 4) {
+		printk("\nThe selection of module is in error\n");
+		i_err++;
+	}			/* if(data[11] <0 ||  data[11]>1) */
+	if (data[12] < 0 || data[12] > 3) {
+		printk("\nThe selection of singlechannel/scan selection is in error\n");
+		i_err++;
+	}			/* if(data[12] < 0 ||  data[12]> 3) */
+	if (data[13] < 0 || data[13] > 16) {
+		printk("\nThe selection of number of channels is in error\n");
+		i_err++;
+	}			/*  if(data[13] <0 ||data[13] >15) */
+
+	/* BEGIN JK 06.07.04: Management of sevrals boards */
+	/*
+	   i_ChannelCount=data[13];
+	   i_ScanType=data[12];
+	   i_ADDIDATAPolarity = data[2];
+	   i_ADDIDATAGain=data[1];
+	   i_ADDIDATAConversionTime=data[6];
+	   i_ADDIDATAConversionTimeUnit=data[7];
+	   i_ADDIDATAType=data[0];
+	 */
+
+	/*  Save acquisition configuration for the actual board */
+	s_BoardInfos[dev->minor].i_ChannelCount = data[13];
+	s_BoardInfos[dev->minor].i_ScanType = data[12];
+	s_BoardInfos[dev->minor].i_ADDIDATAPolarity = data[2];
+	s_BoardInfos[dev->minor].i_ADDIDATAGain = data[1];
+	s_BoardInfos[dev->minor].i_ADDIDATAConversionTime = data[6];
+	s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit = data[7];
+	s_BoardInfos[dev->minor].i_ADDIDATAType = data[0];
+	/* Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+	s_BoardInfos[dev->minor].i_ConnectionType = data[5];
+	/* End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+	/* END JK 06.07.04: Management of sevrals boards */
 
-	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
-      /**********************/
-		/*Enable the interrupt */
-      /**********************/
-		ui_CommandRegister = ui_CommandRegister | 0x00100000;
+	/* Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+	memset(s_BoardInfos[dev->minor].ui_ScanValueArray, 0, (7 + 12) * sizeof(unsigned int));	/*  7 is the maximal number of channels */
+	/* End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
 
+	/* BEGIN JK 02.07.04 : This while can't be do, it block the process when using severals boards */
+	/* while(i_InterruptFlag==1) */
+	while (s_BoardInfos[dev->minor].i_InterruptFlag == 1) {
+#ifndef MSXBOX
+		udelay(1);
+#else
+		/*  In the case where the driver is compiled for the MSX-Box */
+		/*  we used a printk to have a little delay because udelay */
+		/*  seems to be broken under the MSX-Box. */
+		/*  This solution hat to be studied. */
+		printk("");
+#endif
 	}
+	/* END JK 02.07.04 : This while can't be do, it block the process when using severals boards */
 
-  /**********************/
-	/*Start the conversion */
-  /**********************/
-	ui_CommandRegister = ui_CommandRegister | 0x00080000;
-  /***************************/
-	/*Write the command regiter */
-  /***************************/
-	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
-	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
-					12) >> 19) & 1) != 1) ;
-	/* outl(ui_CommandRegister,devpriv->iobase+i_Offset + 8); */
-	outl(ui_CommandRegister,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
-	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
-		do {
-	  /*******************/
-			/*Read the EOC flag */
-	  /*******************/
-			/* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
-			ui_EOC = inl(devpriv->iobase +
-				s_BoardInfos[dev->minor].i_Offset + 20) & 1;
-		} while (ui_EOC != 1);
+	ui_ChannelNo = CR_CHAN(insn->chanspec);	/*  get the channel */
+	/* BEGIN JK 06.07.04: Management of sevrals boards */
+	/* i_ChannelNo=ui_ChannelNo; */
+	/* ui_Channel_num =ui_ChannelNo; */
 
-      /**************************************************/
-		/*Read the digital value of the calibration Offset */
-      /**************************************************/
-		/* data[0] = inl(devpriv->iobase+i_Offset + 28); */
-		data[0] =
-			inl(devpriv->iobase +
-			s_BoardInfos[dev->minor].i_Offset + 28);
-	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
-	return 0;
-}
+	s_BoardInfos[dev->minor].i_ChannelNo = ui_ChannelNo;
+	s_BoardInfos[dev->minor].ui_Channel_num = ui_ChannelNo;
 
-/*
-  +----------------------------------------------------------------------------+
-  | Function   Name   : int i_APCI3200_ReadCJCGainValue                        |
-  |			          (struct comedi_device *dev,struct comedi_subdevice *s,       |
-  |                     struct comedi_insn *insn,unsigned int *data)                      |
-  +----------------------------------------------------------------------------+
-  | Task              : Read CJC calibration gain value
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
-  |                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
-  |                     unsigned int *data              : Data Pointer to read status  |
-  +----------------------------------------------------------------------------+
-  | Output Parameters :	--													 |
-  |			          data[0]  : CJC calibration gain value
-  |
-  +----------------------------------------------------------------------------+
-  | Return Value      : TRUE  : No error occur                                 |
-  |		            : FALSE : Error occur. Return the error          |
-  |			                                                         |
-  +----------------------------------------------------------------------------+
-*/
-int i_APCI3200_ReadCJCCalGain(struct comedi_device *dev, unsigned int *data)
-{
-	unsigned int ui_EOC = 0;
-	int ui_CommandRegister = 0;
-  /*******************************/
-	/* Set the convert timing unit */
-  /*******************************/
-	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
-	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
-					12) >> 19) & 1) != 1) ;
-	/* outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); */
-	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36);
-  /**************************/
-	/* Set the convert timing */
-  /**************************/
+	/* END JK 06.07.04: Management of sevrals boards */
+
+	if (data[5] == 0) {
+		if (ui_ChannelNo < 0 || ui_ChannelNo > 15) {
+			printk("\nThe Selection of the channel is in error\n");
+			i_err++;
+		}		/*  if(ui_ChannelNo<0 || ui_ChannelNo>15) */
+	}			/* if(data[5]==0) */
+	else {
+		if (data[14] == 2) {
+			if (ui_ChannelNo < 0 || ui_ChannelNo > 3) {
+				printk("\nThe Selection of the channel is in error\n");
+				i_err++;
+			}	/*  if(ui_ChannelNo<0 || ui_ChannelNo>3) */
+		}		/* if(data[14]==2) */
+		else {
+			if (ui_ChannelNo < 0 || ui_ChannelNo > 7) {
+				printk("\nThe Selection of the channel is in error\n");
+				i_err++;
+			}	/*  if(ui_ChannelNo<0 || ui_ChannelNo>7) */
+		}		/* elseif(data[14]==2) */
+	}			/* elseif(data[5]==0) */
+	if (data[12] == 0 || data[12] == 1) {
+		switch (data[5]) {
+		case 0:
+			if (ui_ChannelNo >= 0 && ui_ChannelNo <= 3) {
+				/* BEGIN JK 06.07.04: Management of sevrals boards */
+				/* i_Offset=0; */
+				s_BoardInfos[dev->minor].i_Offset = 0;
+				/* END JK 06.07.04: Management of sevrals boards */
+			}	/* if(ui_ChannelNo >=0 && ui_ChannelNo <=3) */
+			if (ui_ChannelNo >= 4 && ui_ChannelNo <= 7) {
+				/* BEGIN JK 06.07.04: Management of sevrals boards */
+				/* i_Offset=64; */
+				s_BoardInfos[dev->minor].i_Offset = 64;
+				/* END JK 06.07.04: Management of sevrals boards */
+			}	/* if(ui_ChannelNo >=4 && ui_ChannelNo <=7) */
+			if (ui_ChannelNo >= 8 && ui_ChannelNo <= 11) {
+				/* BEGIN JK 06.07.04: Management of sevrals boards */
+				/* i_Offset=128; */
+				s_BoardInfos[dev->minor].i_Offset = 128;
+				/* END JK 06.07.04: Management of sevrals boards */
+			}	/* if(ui_ChannelNo >=8 && ui_ChannelNo <=11) */
+			if (ui_ChannelNo >= 12 && ui_ChannelNo <= 15) {
+				/* BEGIN JK 06.07.04: Management of sevrals boards */
+				/* i_Offset=192; */
+				s_BoardInfos[dev->minor].i_Offset = 192;
+				/* END JK 06.07.04: Management of sevrals boards */
+			}	/* if(ui_ChannelNo >=12 && ui_ChannelNo <=15) */
+			break;
+		case 1:
+			if (data[14] == 2) {
+				if (ui_ChannelNo == 0) {
+					/* BEGIN JK 06.07.04: Management of sevrals boards */
+					/* i_Offset=0; */
+					s_BoardInfos[dev->minor].i_Offset = 0;
+					/* END JK 06.07.04: Management of sevrals boards */
+				}	/* if(ui_ChannelNo ==0 ) */
+				if (ui_ChannelNo == 1) {
+					/* BEGIN JK 06.07.04: Management of sevrals boards */
+					/* i_Offset=0; */
+					s_BoardInfos[dev->minor].i_Offset = 64;
+					/* END JK 06.07.04: Management of sevrals boards */
+				}	/*  if(ui_ChannelNo ==1) */
+				if (ui_ChannelNo == 2) {
+					/* BEGIN JK 06.07.04: Management of sevrals boards */
+					/* i_Offset=128; */
+					s_BoardInfos[dev->minor].i_Offset = 128;
+					/* END JK 06.07.04: Management of sevrals boards */
+				}	/* if(ui_ChannelNo ==2 ) */
+				if (ui_ChannelNo == 3) {
+					/* BEGIN JK 06.07.04: Management of sevrals boards */
+					/* i_Offset=192; */
+					s_BoardInfos[dev->minor].i_Offset = 192;
+					/* END JK 06.07.04: Management of sevrals boards */
+				}	/* if(ui_ChannelNo ==3) */
+
+				/* BEGIN JK 06.07.04: Management of sevrals boards */
+				/* i_ChannelNo=0; */
+				s_BoardInfos[dev->minor].i_ChannelNo = 0;
+				/* END JK 06.07.04: Management of sevrals boards */
+				ui_ChannelNo = 0;
+				break;
+			}	/* if(data[14]==2) */
+			if (ui_ChannelNo >= 0 && ui_ChannelNo <= 1) {
+				/* BEGIN JK 06.07.04: Management of sevrals boards */
+				/* i_Offset=0; */
+				s_BoardInfos[dev->minor].i_Offset = 0;
+				/* END JK 06.07.04: Management of sevrals boards */
+			}	/* if(ui_ChannelNo >=0 && ui_ChannelNo <=1) */
+			if (ui_ChannelNo >= 2 && ui_ChannelNo <= 3) {
+				/* BEGIN JK 06.07.04: Management of sevrals boards */
+				/* i_ChannelNo=i_ChannelNo-2; */
+				/* i_Offset=64; */
+				s_BoardInfos[dev->minor].i_ChannelNo =
+					s_BoardInfos[dev->minor].i_ChannelNo -
+					2;
+				s_BoardInfos[dev->minor].i_Offset = 64;
+				/* END JK 06.07.04: Management of sevrals boards */
+				ui_ChannelNo = ui_ChannelNo - 2;
+			}	/* if(ui_ChannelNo >=2 && ui_ChannelNo <=3) */
+			if (ui_ChannelNo >= 4 && ui_ChannelNo <= 5) {
+				/* BEGIN JK 06.07.04: Management of sevrals boards */
+				/* i_ChannelNo=i_ChannelNo-4; */
+				/* i_Offset=128; */
+				s_BoardInfos[dev->minor].i_ChannelNo =
+					s_BoardInfos[dev->minor].i_ChannelNo -
+					4;
+				s_BoardInfos[dev->minor].i_Offset = 128;
+				/* END JK 06.07.04: Management of sevrals boards */
+				ui_ChannelNo = ui_ChannelNo - 4;
+			}	/* if(ui_ChannelNo >=4 && ui_ChannelNo <=5) */
+			if (ui_ChannelNo >= 6 && ui_ChannelNo <= 7) {
+				/* BEGIN JK 06.07.04: Management of sevrals boards */
+				/* i_ChannelNo=i_ChannelNo-6; */
+				/* i_Offset=192; */
+				s_BoardInfos[dev->minor].i_ChannelNo =
+					s_BoardInfos[dev->minor].i_ChannelNo -
+					6;
+				s_BoardInfos[dev->minor].i_Offset = 192;
+				/* END JK 06.07.04: Management of sevrals boards */
+				ui_ChannelNo = ui_ChannelNo - 6;
+			}	/* if(ui_ChannelNo >=6 && ui_ChannelNo <=7) */
+			break;
+
+		default:
+			printk("\n This selection of polarity does not exist\n");
+			i_err++;
+		}		/* switch(data[2]) */
+	}			/* if(data[12]==0 || data[12]==1) */
+	else {
+		switch (data[11]) {
+		case 1:
+			/* BEGIN JK 06.07.04: Management of sevrals boards */
+			/* i_Offset=0; */
+			s_BoardInfos[dev->minor].i_Offset = 0;
+			/* END JK 06.07.04: Management of sevrals boards */
+			break;
+		case 2:
+			/* BEGIN JK 06.07.04: Management of sevrals boards */
+			/* i_Offset=64; */
+			s_BoardInfos[dev->minor].i_Offset = 64;
+			/* END JK 06.07.04: Management of sevrals boards */
+			break;
+		case 3:
+			/* BEGIN JK 06.07.04: Management of sevrals boards */
+			/* i_Offset=128; */
+			s_BoardInfos[dev->minor].i_Offset = 128;
+			/* END JK 06.07.04: Management of sevrals boards */
+			break;
+		case 4:
+			/* BEGIN JK 06.07.04: Management of sevrals boards */
+			/* i_Offset=192; */
+			s_BoardInfos[dev->minor].i_Offset = 192;
+			/* END JK 06.07.04: Management of sevrals boards */
+			break;
+		default:
+			printk("\nError in module selection\n");
+			i_err++;
+		}		/*  switch(data[11]) */
+	}			/*  elseif(data[12]==0 || data[12]==1) */
+	if (i_err) {
+		i_APCI3200_Reset(dev);
+		return -EINVAL;
+	}
+	/* if(i_ScanType!=1) */
+	if (s_BoardInfos[dev->minor].i_ScanType != 1) {
+		/* BEGIN JK 06.07.04: Management of sevrals boards */
+		/* i_Count=0; */
+		/* i_Sum=0; */
+		s_BoardInfos[dev->minor].i_Count = 0;
+		s_BoardInfos[dev->minor].i_Sum = 0;
+		/* END JK 06.07.04: Management of sevrals boards */
+	}			/* if(i_ScanType!=1) */
+
+	ul_Config =
+		data[1] | (data[2] << 6) | (data[5] << 7) | (data[3] << 8) |
+		(data[4] << 9);
+	/* BEGIN JK 06.07.04: Management of sevrals boards */
 	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
 					12) >> 19) & 1) != 1) ;
-	/* outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); */
-	outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32);
-  /******************************/
-	/*Configure the CJC Conversion */
-  /******************************/
+	/* END JK 06.07.04: Management of sevrals boards */
+  /*********************************/
+	/* Write the channel to configure */
+  /*********************************/
+	/* BEGIN JK 06.07.04: Management of sevrals boards */
+	/* outl(0 | ui_ChannelNo , devpriv->iobase+i_Offset + 0x4); */
+	outl(0 | ui_ChannelNo,
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x4);
+	/* END JK 06.07.04: Management of sevrals boards */
+
+	/* BEGIN JK 06.07.04: Management of sevrals boards */
 	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
 					12) >> 19) & 1) != 1) ;
-	/* outl(0x00000400,devpriv->iobase+i_Offset + 4); */
-	outl(0x00000400,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
-  /*******************************/
-	/*Configure the Gain Conversion */
-  /*******************************/
+	/* END JK 06.07.04: Management of sevrals boards */
+  /**************************/
+	/* Reset the configuration */
+  /**************************/
+	/* BEGIN JK 06.07.04: Management of sevrals boards */
+	/* outl(0 , devpriv->iobase+i_Offset + 0x0); */
+	outl(0, devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x0);
+	/* END JK 06.07.04: Management of sevrals boards */
+
+	/* BEGIN JK 06.07.04: Management of sevrals boards */
 	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
 					12) >> 19) & 1) != 1) ;
-	/* outl(0x00040000,devpriv->iobase+i_Offset + 12); */
-	outl(0x00040000,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+	/* END JK 06.07.04: Management of sevrals boards */
 
-  /*******************************/
-	/*Initialise dw_CommandRegister */
-  /*******************************/
-	ui_CommandRegister = 0;
-  /*********************************/
-	/*Test if the interrupt is enable */
-  /*********************************/
-	/* if (i_InterruptFlag == ADDIDATA_ENABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) {
-      /**********************/
-		/*Enable the interrupt */
-      /**********************/
-		ui_CommandRegister = ui_CommandRegister | 0x00100000;
-	}
-  /**********************/
-	/*Start the conversion */
-  /**********************/
-	ui_CommandRegister = ui_CommandRegister | 0x00080000;
   /***************************/
-	/*Write the command regiter */
+	/* Write the configuration */
+  /***************************/
+	/* BEGIN JK 06.07.04: Management of sevrals boards */
+	/* outl(ul_Config , devpriv->iobase+i_Offset + 0x0); */
+	outl(ul_Config,
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x0);
+	/* END JK 06.07.04: Management of sevrals boards */
+
+  /***************************/
+	/*Reset the calibration bit */
   /***************************/
+	/* BEGIN JK 06.07.04: Management of sevrals boards */
+	/* ul_Temp = inl(devpriv->iobase+i_Offset + 12); */
+	ul_Temp = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+	/* END JK 06.07.04: Management of sevrals boards */
+
+	/* BEGIN JK 06.07.04: Management of sevrals boards */
 	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
 					12) >> 19) & 1) != 1) ;
-	/* outl(ui_CommandRegister ,devpriv->iobase+i_Offset + 8); */
-	outl(ui_CommandRegister,
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
-	/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
-	if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) {
-		do {
-	  /*******************/
-			/*Read the EOC flag */
-	  /*******************/
-			/* ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; */
-			ui_EOC = inl(devpriv->iobase +
-				s_BoardInfos[dev->minor].i_Offset + 20) & 1;
-		} while (ui_EOC != 1);
-      /************************************************/
-		/*Read the digital value of the calibration Gain */
-      /************************************************/
-		/* data[0] = inl (devpriv->iobase+i_Offset + 28); */
-		data[0] =
-			inl(devpriv->iobase +
-			s_BoardInfos[dev->minor].i_Offset + 28);
-	}			/* if (i_InterruptFlag == ADDIDATA_DISABLE) */
-	return 0;
+	/* END JK 06.07.04: Management of sevrals boards */
+
+	/* BEGIN JK 06.07.04: Management of sevrals boards */
+	/* outl((ul_Temp & 0xFFF9FFFF) , devpriv->iobase+.i_Offset + 12); */
+	outl((ul_Temp & 0xFFF9FFFF),
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12);
+	/* END JK 06.07.04: Management of sevrals boards */
+
+	if (data[9] == 1) {
+		devpriv->tsk_Current = current;
+		/* BEGIN JK 06.07.04: Management of sevrals boards */
+		/* i_InterruptFlag=1; */
+		s_BoardInfos[dev->minor].i_InterruptFlag = 1;
+		/* END JK 06.07.04: Management of sevrals boards */
+	}			/*  if(data[9]==1) */
+	else {
+		/* BEGIN JK 06.07.04: Management of sevrals boards */
+		/* i_InterruptFlag=0; */
+		s_BoardInfos[dev->minor].i_InterruptFlag = 0;
+		/* END JK 06.07.04: Management of sevrals boards */
+	}			/* else  if(data[9]==1) */
+
+	/* BEGIN JK 06.07.04: Management of sevrals boards */
+	/* i_Initialised=1; */
+	s_BoardInfos[dev->minor].i_Initialised = 1;
+	/* END JK 06.07.04: Management of sevrals boards */
+
+	/* BEGIN JK 06.07.04: Management of sevrals boards */
+	/* if(i_ScanType==1) */
+	if (s_BoardInfos[dev->minor].i_ScanType == 1)
+		/* END JK 06.07.04: Management of sevrals boards */
+	{
+		/* BEGIN JK 06.07.04: Management of sevrals boards */
+		/* i_Sum=i_Sum+1; */
+		s_BoardInfos[dev->minor].i_Sum =
+			s_BoardInfos[dev->minor].i_Sum + 1;
+		/* END JK 06.07.04: Management of sevrals boards */
+
+		insn->unused[0] = 0;
+		i_APCI3200_ReadAnalogInput(dev, s, insn, &ui_Dummy);
+	}
+
+	return insn->n;
 }
 
 /*
-  +----------------------------------------------------------------------------+
-  | Function   Name   : int i_APCI3200_InsnBits_AnalogInput_Test               |
-  |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-  |                      struct comedi_insn *insn,unsigned int *data)                     |
-  +----------------------------------------------------------------------------+
-  | Task              : Tests the Selected Anlog Input Channel                 |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
-  |                     struct comedi_subdevice *s     : Subdevice Pointer            |
-  |                     struct comedi_insn *insn       : Insn Structure Pointer       |
-  |                     unsigned int *data          : Data Pointer contains        |
-  |                                          configuration parameters as below |
-  |
-  |
-  |                           data[0]            : 0 TestAnalogInputShortCircuit
-  |									     1 TestAnalogInputConnection							 														                        |
-
-  +----------------------------------------------------------------------------+
-  | Output Parameters :	--													 |
-  |			        data[0]            : Digital value obtained      |
-  |                           data[1]            : calibration offset          |
-  |                           data[2]            : calibration gain            |
-  |			                                                         |
-  |			                                                         |
-  +----------------------------------------------------------------------------+
-  | Return Value      : TRUE  : No error occur                                 |
-  |		            : FALSE : Error occur. Return the error          |
-  |			                                                         |
-  +----------------------------------------------------------------------------+
-*/
-
-int i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+ * Tests the Selected Anlog Input Channel
+ *
+ * data[0] = 0  TestAnalogInputShortCircuit
+ *	   = 1  TestAnalogInputConnection
+ *
+ * data[0] : Digital value obtained
+ * data[1] : calibration offset
+ * data[2] : calibration gain
+ */
+static int i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device *dev,
+						struct comedi_subdevice *s,
+						struct comedi_insn *insn,
+						unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_Configuration = 0;
 	int i_Temp;		/* ,i_TimeUnit; */
+
 	/* if(i_Initialised==0) */
 
 	if (s_BoardInfos[dev->minor].i_Initialised == 0) {
@@ -2502,61 +2211,18 @@ int i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device *dev,
 	return insn->n;
 }
 
-/*
-  +----------------------------------------------------------------------------+
-  | Function   Name   : int i_APCI3200_InsnWriteReleaseAnalogInput             |
-  |			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-  |                      struct comedi_insn *insn,unsigned int *data)                     |
-  +----------------------------------------------------------------------------+
-  | Task              :  Resets the channels                                                      |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev      : Driver handle                |
-  |                     struct comedi_subdevice *s     : Subdevice Pointer            |
-  |                     struct comedi_insn *insn       : Insn Structure Pointer       |
-  |                     unsigned int *data          : Data Pointer
-  +----------------------------------------------------------------------------+
-  | Output Parameters :	--													 |
-
-  +----------------------------------------------------------------------------+
-  | Return Value      : TRUE  : No error occur                                 |
-  |		            : FALSE : Error occur. Return the error          |
-  |			                                                         |
-  +----------------------------------------------------------------------------+
-*/
-
-int i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device *dev,
+						  struct comedi_subdevice *s,
+						  struct comedi_insn *insn,
+						  unsigned int *data)
 {
 	i_APCI3200_Reset(dev);
 	return insn->n;
 }
 
-/*
-  +----------------------------------------------------------------------------+
-  | Function name     :int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev|
-  |			,struct comedi_subdevice *s,struct comedi_cmd *cmd)			         |
-  |                                        									 |
-  +----------------------------------------------------------------------------+
-  | Task              : Test validity for a command for cyclic anlog input     |
-  |                       acquisition  						     			 |
-  |                     										                 |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev									 |
-  |                     struct comedi_subdevice *s									 |
-  |                     struct comedi_cmd *cmd              					         |
-  |                     										                 |
-  |
-  |                     										                 |
-  |                     										                 |
-  |                     										                 |
-  +----------------------------------------------------------------------------+
-  | Return Value      :0              					                     |
-  |                    													     |
-  +----------------------------------------------------------------------------+
-*/
-
-int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_cmd *cmd)
+static int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev,
+					     struct comedi_subdevice *s,
+					     struct comedi_cmd *cmd)
 {
 
 	int err = 0;
@@ -2716,27 +2382,12 @@ int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s
 	return 0;
 }
 
-/*
-  +----------------------------------------------------------------------------+
-  | Function name     :int i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev,|
-  | 											     struct comedi_subdevice *s)|
-  |                                        									 |
-  +----------------------------------------------------------------------------+
-  | Task              : Stop the  acquisition  						     |
-  |                     										                 |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev									 |
-  |                     struct comedi_subdevice *s									 |
-  |                                                 					         |
-  +----------------------------------------------------------------------------+
-  | Return Value      :0              					                     |
-  |                    													     |
-  +----------------------------------------------------------------------------+
-*/
-
-int i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s)
+static int i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev,
+					    struct comedi_subdevice *s)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_Configuration = 0;
+
 	/* i_InterruptFlag=0; */
 	/* i_Initialised=0; */
 	/* i_Count=0; */
@@ -2765,27 +2416,13 @@ int i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_su
 }
 
 /*
-  +----------------------------------------------------------------------------+
-  | Function name     : int i_APCI3200_CommandAnalogInput(struct comedi_device *dev,  |
-  |												struct comedi_subdevice *s) |
-  |                                        									 |
-  +----------------------------------------------------------------------------+
-  | Task              : Does asynchronous acquisition                          |
-  |                     Determines the mode 1 or 2.						     |
-  |                     										                 |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev									 |
-  |                     struct comedi_subdevice *s									 |
-  |                     														 |
-  |                     														 |
-  +----------------------------------------------------------------------------+
-  | Return Value      :              					                         |
-  |                    													     |
-  +----------------------------------------------------------------------------+
-*/
-
-int i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s)
+ * Does asynchronous acquisition
+ * Determines the mode 1 or 2.
+ */
+static int i_APCI3200_CommandAnalogInput(struct comedi_device *dev,
+					 struct comedi_subdevice *s)
 {
+	struct addi_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
 	unsigned int ui_Configuration = 0;
 	/* INT  i_CurrentSource = 0; */
@@ -2798,6 +2435,7 @@ int i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subde
 	unsigned int ui_DelayTime = 0;
 	unsigned int ui_DelayTimeBase = 0;
 	unsigned int ui_DelayMode = 0;
+
 	/* i_FirstChannel=cmd->chanlist[0]; */
 	/* i_LastChannel=cmd->chanlist[1]; */
 	s_BoardInfos[dev->minor].i_FirstChannel = cmd->chanlist[0];
@@ -2932,104 +2570,179 @@ int i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subde
 	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
 					12) >> 19) & 1) != 1) ;
 
-	/* outl(((ui_Configuration & 0x1E0FF) | 0x00002000),devpriv->iobase+i_Offset + 4); */
-	outl(((ui_Configuration & 0x1E0FF) | 0x00002000),
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
-  /*******************/
-	/*Read the register */
-  /*******************/
-	ui_Configuration = 0;
-	/* ui_Configuration = inl(devpriv->iobase+i_Offset + 8); */
-	ui_Configuration =
-		inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+	/* outl(((ui_Configuration & 0x1E0FF) | 0x00002000),devpriv->iobase+i_Offset + 4); */
+	outl(((ui_Configuration & 0x1E0FF) | 0x00002000),
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4);
+  /*******************/
+	/*Read the register */
+  /*******************/
+	ui_Configuration = 0;
+	/* ui_Configuration = inl(devpriv->iobase+i_Offset + 8); */
+	ui_Configuration =
+		inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+
+  /*******************/
+	/*Set the START bit */
+  /*******************/
+	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
+	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
+					12) >> 19) & 1) != 1) ;
+	/* outl((ui_Configuration | 0x00080000),devpriv->iobase+i_Offset + 8); */
+	outl((ui_Configuration | 0x00080000),
+		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
+	return 0;
+}
+
+/*
+ * This function copies the acquired data(from FIFO) to Comedi buffer.
+ */
+static int i_APCI3200_InterruptHandleEos(struct comedi_device *dev)
+{
+	struct addi_private *devpriv = dev->private;
+	unsigned int ui_StatusRegister = 0;
+	struct comedi_subdevice *s = &dev->subdevices[0];
+
+	/* BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+	/* comedi_async *async = s->async; */
+	/* UINT *data; */
+	/* data=async->data+async->buf_int_ptr;//new samples added from here onwards */
+	int n = 0, i = 0;
+	/* END JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+
+  /************************************/
+	/*Read the interrupt status register */
+  /************************************/
+	/* ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16); */
+	ui_StatusRegister =
+		inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 16);
+
+  /*************************/
+	/*Test if interrupt occur */
+  /*************************/
+
+	if ((ui_StatusRegister & 0x2) == 0x2) {
+      /*************************/
+		/*Read the channel number */
+      /*************************/
+		/* ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24); */
+		/* BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+		/* This value is not used */
+		/* ui_ChannelNumber = inl(devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 24); */
+		s->async->events = 0;
+		/* END JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+
+      /*************************************/
+		/*Read the digital Analog Input value */
+      /*************************************/
+
+		/* data[i_Count] = inl(devpriv->iobase+i_Offset + 28); */
+		/* Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+		/* data[s_BoardInfos [dev->minor].i_Count] = inl(devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 28); */
+		s_BoardInfos[dev->minor].ui_ScanValueArray[s_BoardInfos[dev->
+				minor].i_Count] =
+			inl(devpriv->iobase +
+			s_BoardInfos[dev->minor].i_Offset + 28);
+		/* End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+
+		/* if((i_Count == (i_LastChannel-i_FirstChannel+3))) */
+		if ((s_BoardInfos[dev->minor].i_Count ==
+				(s_BoardInfos[dev->minor].i_LastChannel -
+					s_BoardInfos[dev->minor].
+					i_FirstChannel + 3))) {
+
+			/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
+			s_BoardInfos[dev->minor].i_Count++;
+
+			for (i = s_BoardInfos[dev->minor].i_FirstChannel;
+				i <= s_BoardInfos[dev->minor].i_LastChannel;
+				i++) {
+				i_APCI3200_GetChannelCalibrationValue(dev, i,
+					&s_BoardInfos[dev->minor].
+					ui_ScanValueArray[s_BoardInfos[dev->
+							minor].i_Count + ((i -
+								s_BoardInfos
+								[dev->minor].
+								i_FirstChannel)
+							* 3)],
+					&s_BoardInfos[dev->minor].
+					ui_ScanValueArray[s_BoardInfos[dev->
+							minor].i_Count + ((i -
+								s_BoardInfos
+								[dev->minor].
+								i_FirstChannel)
+							* 3) + 1],
+					&s_BoardInfos[dev->minor].
+					ui_ScanValueArray[s_BoardInfos[dev->
+							minor].i_Count + ((i -
+								s_BoardInfos
+								[dev->minor].
+								i_FirstChannel)
+							* 3) + 2]);
+			}
+
+			/* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
 
-  /*******************/
-	/*Set the START bit */
-  /*******************/
-	/* while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); */
-	while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset +
-					12) >> 19) & 1) != 1) ;
-	/* outl((ui_Configuration | 0x00080000),devpriv->iobase+i_Offset + 8); */
-	outl((ui_Configuration | 0x00080000),
-		devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8);
-	return 0;
-}
+			/* i_Count=-1; */
 
-/*
-  +----------------------------------------------------------------------------+
-  | Function   Name   :  int i_APCI3200_Reset(struct comedi_device *dev)			     |
-  |							                                         |
-  +----------------------------------------------------------------------------+
-  | Task              :Resets the registers of the card                        |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  :                                                        |
-  +----------------------------------------------------------------------------+
-  | Output Parameters :	--													 |
-  +----------------------------------------------------------------------------+
-  | Return Value      :                                                        |
-  |					                                                 |
-  +----------------------------------------------------------------------------+
-*/
+			s_BoardInfos[dev->minor].i_Count = -1;
 
-int i_APCI3200_Reset(struct comedi_device *dev)
-{
-	int i_Temp;
-	unsigned int dw_Dummy;
-	/* i_InterruptFlag=0; */
-	/* i_Initialised==0; */
-	/* i_Count=0; */
-	/* i_Sum=0; */
+			/* async->buf_int_count+=(i_LastChannel-i_FirstChannel+4)*sizeof(unsigned int); */
+			/* Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+			/* async->buf_int_count+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(unsigned int); */
+			/* End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+			/* async->buf_int_ptr+=(i_LastChannel-i_FirstChannel+4)*sizeof(unsigned int); */
+			/* Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+			/* async->buf_int_ptr+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(unsigned int); */
+			/* comedi_eos(dev,s); */
 
-	s_BoardInfos[dev->minor].i_InterruptFlag = 0;
-	s_BoardInfos[dev->minor].i_Initialised = 0;
-	s_BoardInfos[dev->minor].i_Count = 0;
-	s_BoardInfos[dev->minor].i_Sum = 0;
-	s_BoardInfos[dev->minor].b_StructInitialized = 0;
+			/*  Set the event type (Comedi Buffer End Of Scan) */
+			s->async->events |= COMEDI_CB_EOS;
 
-	outl(0x83838383, devpriv->i_IobaseAmcc + 0x60);
+			/*  Test if enougth memory is available and allocate it for 7 values */
+			/* n = comedi_buf_write_alloc(s->async, 7*sizeof(unsigned int)); */
+			n = comedi_buf_write_alloc(s->async,
+				(7 + 12) * sizeof(unsigned int));
 
-	/*  Enable the interrupt for the controller */
-	dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38);
-	outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38);
-	outl(0, devpriv->i_IobaseAddon);	/* Resets the output */
-  /***************/
-	/*Empty the buffer */
-  /**************/
-	for (i_Temp = 0; i_Temp <= 95; i_Temp++) {
-		/* ui_InterruptChannelValue[i_Temp]=0; */
-		s_BoardInfos[dev->minor].ui_InterruptChannelValue[i_Temp] = 0;
-	}			/* for(i_Temp=0;i_Temp<=95;i_Temp++) */
-  /*****************************/
-	/*Reset the START and IRQ bit */
-  /*****************************/
-	for (i_Temp = 0; i_Temp <= 192;) {
-		while (((inl(devpriv->iobase + i_Temp + 12) >> 19) & 1) != 1) ;
-		outl(0, devpriv->iobase + i_Temp + 8);
-		i_Temp = i_Temp + 64;
-	}			/* for(i_Temp=0;i_Temp<=192;i_Temp+64) */
+			/*  If not enough memory available, event is set to Comedi Buffer Error */
+			if (n > ((7 + 12) * sizeof(unsigned int))) {
+				printk("\ncomedi_buf_write_alloc n = %i", n);
+				s->async->events |= COMEDI_CB_ERROR;
+			}
+			/*  Write all 7 scan values in the comedi buffer */
+			comedi_buf_memcpy_to(s->async, 0,
+				(unsigned int *) s_BoardInfos[dev->minor].
+				ui_ScanValueArray, (7 + 12) * sizeof(unsigned int));
+
+			/*  Update comedi buffer pinters indexes */
+			comedi_buf_write_free(s->async,
+				(7 + 12) * sizeof(unsigned int));
+
+			/*  Send events */
+			comedi_event(dev, s);
+			/* End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+
+			/* BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+			/*  */
+			/* if (s->async->buf_int_ptr>=s->async->data_len) //  for buffer rool over */
+			/*   { */
+			/*     /* buffer rollover */ */
+			/*     s->async->buf_int_ptr=0; */
+			/*     comedi_eobuf(dev,s); */
+			/*   } */
+			/* End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
+		}
+		/* i_Count++; */
+		s_BoardInfos[dev->minor].i_Count++;
+	}
+	/* i_InterruptFlag=0; */
+	s_BoardInfos[dev->minor].i_InterruptFlag = 0;
 	return 0;
 }
 
-/*
-  +----------------------------------------------------------------------------+
-  | Function   Name   : static void v_APCI3200_Interrupt					     |
-  |					  (int irq , void *d)				 |
-  +----------------------------------------------------------------------------+
-  | Task              : Interrupt processing Routine                           |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : int irq                 : irq number                   |
-  |                     void *d                 : void pointer                 |
-  +----------------------------------------------------------------------------+
-  | Output Parameters :	--													 |
-  +----------------------------------------------------------------------------+
-  | Return Value      : TRUE  : No error occur                                 |
-  |		            : FALSE : Error occur. Return the error					 |
-  |					                                                         |
-  +----------------------------------------------------------------------------+
-*/
-void v_APCI3200_Interrupt(int irq, void *d)
+static void v_APCI3200_Interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_StatusRegister = 0;
 	unsigned int ui_ChannelNumber = 0;
 	int i_CalibrationFlag = 0;
@@ -3038,7 +2751,6 @@ void v_APCI3200_Interrupt(int irq, void *d)
 	unsigned int ui_DigitalTemperature = 0;
 	unsigned int ui_DigitalInput = 0;
 	int i_ConvertCJCCalibration;
-
 	/* BEGIN JK TEST */
 	int i_ReturnValue = 0;
 	/* END JK TEST */
@@ -3449,164 +3161,3 @@ void v_APCI3200_Interrupt(int irq, void *d)
 	}			/* switch(i_ScanType) */
 	return;
 }
-
-/*
-  +----------------------------------------------------------------------------+
-  | Function name     :int i_APCI3200_InterruptHandleEos(struct comedi_device *dev)   |
-  |                                        									 |
-  |                                            						         |
-  +----------------------------------------------------------------------------+
-  | Task              : .                   |
-  |                     This function copies the acquired data(from FIFO)      |
-  |				to Comedi buffer.		 							 |
-  |                     										                 |
-  +----------------------------------------------------------------------------+
-  | Input Parameters  : struct comedi_device *dev									 |
-  |                     														 |
-  |                                                 					         |
-  +----------------------------------------------------------------------------+
-  | Return Value      : 0            					                         |
-  |                    													     |
-  +----------------------------------------------------------------------------+
-*/
-int i_APCI3200_InterruptHandleEos(struct comedi_device *dev)
-{
-	unsigned int ui_StatusRegister = 0;
-	struct comedi_subdevice *s = &dev->subdevices[0];
-
-	/* BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-	/* comedi_async *async = s->async; */
-	/* UINT *data; */
-	/* data=async->data+async->buf_int_ptr;//new samples added from here onwards */
-	int n = 0, i = 0;
-	/* END JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-
-  /************************************/
-	/*Read the interrupt status register */
-  /************************************/
-	/* ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16); */
-	ui_StatusRegister =
-		inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 16);
-
-  /*************************/
-	/*Test if interrupt occur */
-  /*************************/
-
-	if ((ui_StatusRegister & 0x2) == 0x2) {
-      /*************************/
-		/*Read the channel number */
-      /*************************/
-		/* ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24); */
-		/* BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-		/* This value is not used */
-		/* ui_ChannelNumber = inl(devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 24); */
-		s->async->events = 0;
-		/* END JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-
-      /*************************************/
-		/*Read the digital Analog Input value */
-      /*************************************/
-
-		/* data[i_Count] = inl(devpriv->iobase+i_Offset + 28); */
-		/* Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-		/* data[s_BoardInfos [dev->minor].i_Count] = inl(devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 28); */
-		s_BoardInfos[dev->minor].ui_ScanValueArray[s_BoardInfos[dev->
-				minor].i_Count] =
-			inl(devpriv->iobase +
-			s_BoardInfos[dev->minor].i_Offset + 28);
-		/* End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-
-		/* if((i_Count == (i_LastChannel-i_FirstChannel+3))) */
-		if ((s_BoardInfos[dev->minor].i_Count ==
-				(s_BoardInfos[dev->minor].i_LastChannel -
-					s_BoardInfos[dev->minor].
-					i_FirstChannel + 3))) {
-
-			/* Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-			s_BoardInfos[dev->minor].i_Count++;
-
-			for (i = s_BoardInfos[dev->minor].i_FirstChannel;
-				i <= s_BoardInfos[dev->minor].i_LastChannel;
-				i++) {
-				i_APCI3200_GetChannelCalibrationValue(dev, i,
-					&s_BoardInfos[dev->minor].
-					ui_ScanValueArray[s_BoardInfos[dev->
-							minor].i_Count + ((i -
-								s_BoardInfos
-								[dev->minor].
-								i_FirstChannel)
-							* 3)],
-					&s_BoardInfos[dev->minor].
-					ui_ScanValueArray[s_BoardInfos[dev->
-							minor].i_Count + ((i -
-								s_BoardInfos
-								[dev->minor].
-								i_FirstChannel)
-							* 3) + 1],
-					&s_BoardInfos[dev->minor].
-					ui_ScanValueArray[s_BoardInfos[dev->
-							minor].i_Count + ((i -
-								s_BoardInfos
-								[dev->minor].
-								i_FirstChannel)
-							* 3) + 2]);
-			}
-
-			/* End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-
-			/* i_Count=-1; */
-
-			s_BoardInfos[dev->minor].i_Count = -1;
-
-			/* async->buf_int_count+=(i_LastChannel-i_FirstChannel+4)*sizeof(unsigned int); */
-			/* Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-			/* async->buf_int_count+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(unsigned int); */
-			/* End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-			/* async->buf_int_ptr+=(i_LastChannel-i_FirstChannel+4)*sizeof(unsigned int); */
-			/* Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-			/* async->buf_int_ptr+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(unsigned int); */
-			/* comedi_eos(dev,s); */
-
-			/*  Set the event type (Comedi Buffer End Of Scan) */
-			s->async->events |= COMEDI_CB_EOS;
-
-			/*  Test if enougth memory is available and allocate it for 7 values */
-			/* n = comedi_buf_write_alloc(s->async, 7*sizeof(unsigned int)); */
-			n = comedi_buf_write_alloc(s->async,
-				(7 + 12) * sizeof(unsigned int));
-
-			/*  If not enough memory available, event is set to Comedi Buffer Error */
-			if (n > ((7 + 12) * sizeof(unsigned int))) {
-				printk("\ncomedi_buf_write_alloc n = %i", n);
-				s->async->events |= COMEDI_CB_ERROR;
-			}
-			/*  Write all 7 scan values in the comedi buffer */
-			comedi_buf_memcpy_to(s->async, 0,
-				(unsigned int *) s_BoardInfos[dev->minor].
-				ui_ScanValueArray, (7 + 12) * sizeof(unsigned int));
-
-			/*  Update comedi buffer pinters indexes */
-			comedi_buf_write_free(s->async,
-				(7 + 12) * sizeof(unsigned int));
-
-			/*  Send events */
-			comedi_event(dev, s);
-			/* End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-
-			/* BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-			/*  */
-			/* if (s->async->buf_int_ptr>=s->async->data_len) //  for buffer rool over */
-			/*   { */
-			/*     /* buffer rollover */ */
-			/*     s->async->buf_int_ptr=0; */
-			/*     comedi_eobuf(dev,s); */
-			/*   } */
-			/* End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-		}
-		/* i_Count++; */
-		s_BoardInfos[dev->minor].i_Count++;
-	}
-	/* i_InterruptFlag=0; */
-	s_BoardInfos[dev->minor].i_InterruptFlag = 0;
-	return 0;
-}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
deleted file mode 100644
index 812a9c4..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/* Card Specific information */
-#define APCI3200_BOARD_VENDOR_ID                 0x15B8
-/* #define APCI3200_ADDRESS_RANGE                   264 */
-
-int MODULE_NO;
-struct {
-	int i_Gain;
-	int i_Polarity;
-	int i_OffsetRange;
-	int i_Coupling;
-	int i_SingleDiff;
-	int i_AutoCalibration;
-	unsigned int ui_ReloadValue;
-	unsigned int ui_TimeUnitReloadVal;
-	int i_Interrupt;
-	int i_ModuleSelection;
-} Config_Parameters_Module1, Config_Parameters_Module2,
-    Config_Parameters_Module3, Config_Parameters_Module4;
-
-/* ANALOG INPUT RANGE */
-static const struct comedi_lrange range_apci3200_ai = { 8, {
-						     BIP_RANGE(10),
-						     BIP_RANGE(5),
-						     BIP_RANGE(2),
-						     BIP_RANGE(1),
-						     UNI_RANGE(10),
-						     UNI_RANGE(5),
-						     UNI_RANGE(2),
-						     UNI_RANGE(1)
-						     }
-};
-
-static const struct comedi_lrange range_apci3300_ai = { 4, {
-						     UNI_RANGE(10),
-						     UNI_RANGE(5),
-						     UNI_RANGE(2),
-						     UNI_RANGE(1)
-						     }
-};
-
-/* Analog Input related Defines */
-#define APCI3200_AI_OFFSET_GAIN                  0
-#define APCI3200_AI_SC_TEST                      4
-#define APCI3200_AI_IRQ                          8
-#define APCI3200_AI_AUTOCAL                      12
-#define APCI3200_RELOAD_CONV_TIME_VAL            32
-#define APCI3200_CONV_TIME_TIME_BASE             36
-#define APCI3200_RELOAD_DELAY_TIME_VAL           40
-#define APCI3200_DELAY_TIME_TIME_BASE            44
-#define APCI3200_AI_MODULE1                      0
-#define APCI3200_AI_MODULE2                      64
-#define APCI3200_AI_MODULE3                      128
-#define APCI3200_AI_MODULE4                      192
-#define TRUE                                     1
-#define FALSE                                    0
-#define APCI3200_AI_EOSIRQ                       16
-#define APCI3200_AI_EOS                          20
-#define APCI3200_AI_CHAN_ID                      24
-#define APCI3200_AI_CHAN_VAL                     28
-#define ANALOG_INPUT                             0
-#define TEMPERATURE                              1
-#define RESISTANCE                               2
-
-#define ENABLE_EXT_TRIG                          1
-#define ENABLE_EXT_GATE                          2
-#define ENABLE_EXT_TRIG_GATE                     3
-
-#define APCI3200_MAXVOLT                         2.5
-#define ADDIDATA_GREATER_THAN_TEST               0
-#define ADDIDATA_LESS_THAN_TEST                  1
-
-#define ADDIDATA_UNIPOLAR                        1
-#define ADDIDATA_BIPOLAR                         2
-
-/* BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-#define MAX_MODULE				4
-/* END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-
-struct str_ADDIDATA_RTDStruct {
-	unsigned int ul_NumberOfValue;
-	unsigned int *pul_ResistanceValue;
-	unsigned int *pul_TemperatureValue;
-};
-
-/* BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-struct str_Module {
-
-	/*  Begin JK 05/08/2003 change for Linux */
-	unsigned long ul_CurrentSourceCJC;
-	unsigned long ul_CurrentSource[5];
-	/*  End JK 05/08/2003 change for Linux */
-
-	/*  Begin CG 15/02/02 Rev 1.0 -> Rev 1.1 : Add Header Type 1 */
-	unsigned long ul_GainFactor[8];	/*  Gain Factor */
-	unsigned int w_GainValue[10];
-	/*  End CG 15/02/02 Rev 1.0 -> Rev 1.1 : Add Header Type 1 */
-};
-
-/* END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-
-/* BEGIN JK 06.07.04: Management of sevrals boards */
-struct str_BoardInfos {
-
-	int i_CJCAvailable;
-	int i_CJCPolarity;
-	int i_CJCGain;
-	int i_InterruptFlag;
-	int i_ADDIDATAPolarity;
-	int i_ADDIDATAGain;
-	int i_AutoCalibration;
-	int i_ADDIDATAConversionTime;
-	int i_ADDIDATAConversionTimeUnit;
-	int i_ADDIDATAType;
-	int i_ChannelNo;
-	int i_ChannelCount;
-	int i_ScanType;
-	int i_FirstChannel;
-	int i_LastChannel;
-	int i_Sum;
-	int i_Offset;
-	unsigned int ui_Channel_num;
-	int i_Count;
-	int i_Initialised;
-	/* UINT ui_InterruptChannelValue[96]; //Buffer */
-	unsigned int ui_InterruptChannelValue[144];	/* Buffer */
-	unsigned char b_StructInitialized;
-	/* Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-	unsigned int ui_ScanValueArray[7 + 12];	/*  7 is the maximal number of channels */
-	/* End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 */
-
-	/* Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-	int i_ConnectionType;
-	int i_NbrOfModule;
-	struct str_Module s_Module[MAX_MODULE];
-	/* End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values */
-};
-
-/* END JK 06.07.04: Management of sevrals boards */
-
-/* Hardware Layer  functions for Apci3200 */
-
-/* AI */
-
-int i_APCI3200_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-int i_APCI3200_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data);
-int i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device *dev,
-					   struct comedi_subdevice *s,
-					   struct comedi_insn *insn, unsigned int *data);
-int i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device *dev,
-					 struct comedi_subdevice *s,
-					 struct comedi_insn *insn, unsigned int *data);
-int i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s);
-int i_APCI3200_InterruptHandleEos(struct comedi_device *dev);
-int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				      struct comedi_cmd *cmd);
-int i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s);
-int i_APCI3200_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data);
-/* Interrupt */
-void v_APCI3200_Interrupt(int irq, void *d);
-int i_APCI3200_InterruptHandleEos(struct comedi_device *dev);
-/* Reset functions */
-int i_APCI3200_Reset(struct comedi_device *dev);
-
-int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev, unsigned int *data);
-int i_APCI3200_ReadCJCValue(struct comedi_device *dev, unsigned int *data);
-int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, unsigned int *data);
-int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, unsigned int *data);
-int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev,
-				       struct comedi_subdevice *s, struct comedi_insn *insn,
-				       unsigned int *data);
-int i_APCI3200_ReadCJCCalGain(struct comedi_device *dev, unsigned int *data);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
index acaceb0..7a18ce7 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
@@ -46,229 +46,75 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +----------+-----------+------------------------------------------------+
 */
 
-/*
-+----------------------------------------------------------------------------+
-|                               Included files                               |
-+----------------------------------------------------------------------------+
-*/
-#include "hwdrv_apci3501.h"
-
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI3501_ReadDigitalInput                    |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Read  value  of the selected channel or port           |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
-|                     unsigned int *data              : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
+/* Card Specific information */
+#define APCI3501_ADDRESS_RANGE		255
+
+#define APCI3501_DIGITAL_IP		0x50
+#define APCI3501_DIGITAL_OP		0x40
+#define APCI3501_ANALOG_OUTPUT		0x00
+
+/* Analog Output related Defines */
+#define APCI3501_AO_VOLT_MODE		0
+#define APCI3501_AO_PROG		4
+#define APCI3501_AO_TRIG_SCS		8
+#define UNIPOLAR			0
+#define BIPOLAR				1
+#define MODE0				0
+#define MODE1				1
+
+/* Watchdog Related Defines */
+
+#define APCI3501_WATCHDOG		0x20
+#define APCI3501_TCW_SYNC_ENABLEDISABLE	0
+#define APCI3501_TCW_RELOAD_VALUE	4
+#define APCI3501_TCW_TIMEBASE		8
+#define APCI3501_TCW_PROG		12
+#define APCI3501_TCW_TRIG_STATUS	16
+#define APCI3501_TCW_IRQ		20
+#define APCI3501_TCW_WARN_TIMEVAL	24
+#define APCI3501_TCW_WARN_TIMEBASE	28
+#define ADDIDATA_TIMER			0
+#define ADDIDATA_WATCHDOG		2
+
+/* ANALOG OUTPUT RANGE */
+static struct comedi_lrange range_apci3501_ao = {
+	2, {
+		BIP_RANGE(10),
+		UNI_RANGE(10)
+	}
+};
 
-int i_APCI3501_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int apci3501_di_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	unsigned int ui_Temp;
-	unsigned int ui_NoOfChannel;
-	ui_NoOfChannel = CR_CHAN(insn->chanspec);
-	ui_Temp = data[0];
-	*data = inl(devpriv->iobase + APCI3501_DIGITAL_IP);
-	if (ui_Temp == 0) {
-		*data = (*data >> ui_NoOfChannel) & 0x1;
-	}			/* if  (ui_Temp==0) */
-	else {
-		if (ui_Temp == 1) {
-
-			*data = *data & 0x3;
-		}		/* if  (ui_Temp==1) */
-		else {
-			printk("\nSpecified channel not supported \n");
-		}		/* elseif  (ui_Temp==1) */
-	}			/* elseif  (ui_Temp==0) */
-	return insn->n;
-}
+	struct addi_private *devpriv = dev->private;
 
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI3501_ConfigDigitalOutput                     |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Configures The Digital Output Subdevice.               |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev : Driver handle                     |
-|                     unsigned int *data         : Data Pointer contains             |
-|                                          configuration parameters as below |
-|                                                                            |
-|					  data[1]            : 1 Enable  VCC  Interrupt  |
-|										   0 Disable VCC  Interrupt  |
-|					  data[2]            : 1 Enable  CC  Interrupt   |
-|										   0 Disable CC  Interrupt   |
-|																	 |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI3501_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
+	data[1] = inl(devpriv->iobase + APCI3501_DIGITAL_IP) & 0x3;
 
-	if ((data[0] != 0) && (data[0] != 1)) {
-		comedi_error(dev,
-			"Not a valid Data !!! ,Data should be 1 or 0\n");
-		return -EINVAL;
-	}			/* if  ( (data[0]!=0) && (data[0]!=1) ) */
-	if (data[0]) {
-		devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE;
-	}			/*  if  (data[0]) */
-	else {
-		devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE;
-	}			/* else if  (data[0]) */
 	return insn->n;
 }
 
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI3501_WriteDigitalOutput                      |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : writes To the digital Output Subdevice                 |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     struct comedi_subdevice *s     : Subdevice Pointer            |
-|                     struct comedi_insn *insn       : Insn Structure Pointer       |
-|                     unsigned int *data          : Data Pointer contains        |
-|                                          configuration parameters as below |
-|                                                                            |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int apci3501_do_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	unsigned int ui_Temp, ui_Temp1;
-	unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);	/*  get the channel */
-	if (devpriv->b_OutputMemoryStatus) {
-		ui_Temp = inl(devpriv->iobase + APCI3501_DIGITAL_OP);
-	}			/* if(devpriv->b_OutputMemoryStatus ) */
-	else {
-		ui_Temp = 0;
-	}			/* if(devpriv->b_OutputMemoryStatus ) */
-	if (data[3] == 0) {
-		if (data[1] == 0) {
-			data[0] = (data[0] << ui_NoOfChannel) | ui_Temp;
-			outl(data[0], devpriv->iobase + APCI3501_DIGITAL_OP);
-		}		/* if(data[1]==0) */
-		else {
-			if (data[1] == 1) {
-				data[0] = (data[0] << (2 * data[2])) | ui_Temp;
-				outl(data[0],
-					devpriv->iobase + APCI3501_DIGITAL_OP);
-			}	/*  if(data[1]==1) */
-			else {
-				printk("\nSpecified channel not supported\n");
-			}	/* else if(data[1]==1) */
-		}		/* elseif(data[1]==0) */
-	}			/* if(data[3]==0) */
-	else {
-		if (data[3] == 1) {
-			if (data[1] == 0) {
-				data[0] = ~data[0] & 0x1;
-				ui_Temp1 = 1;
-				ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
-				ui_Temp = ui_Temp | ui_Temp1;
-				data[0] =
-					(data[0] << ui_NoOfChannel) ^
-					0xffffffff;
-				data[0] = data[0] & ui_Temp;
-				outl(data[0],
-					devpriv->iobase + APCI3501_DIGITAL_OP);
-			}	/* if(data[1]==0) */
-			else {
-				if (data[1] == 1) {
-					data[0] = ~data[0] & 0x3;
-					ui_Temp1 = 3;
-					ui_Temp1 = ui_Temp1 << 2 * data[2];
-					ui_Temp = ui_Temp | ui_Temp1;
-					data[0] =
-						((data[0] << (2 *
-								data[2])) ^
-						0xffffffff) & ui_Temp;
-					outl(data[0],
-						devpriv->iobase +
-						APCI3501_DIGITAL_OP);
-				}	/*  if(data[1]==1) */
-				else {
-					printk("\nSpecified channel not supported\n");
-				}	/* else if(data[1]==1) */
-			}	/* elseif(data[1]==0) */
-		}		/* if(data[3]==1); */
-		else {
-			printk("\nSpecified functionality does not exist\n");
-			return -EINVAL;
-		}		/* if else data[3]==1) */
-	}			/* if else data[3]==0) */
-	return insn->n;
-}
+	struct addi_private *devpriv = dev->private;
+	unsigned int mask = data[0];
+	unsigned int bits = data[1];
+
+	s->state = inl(devpriv->iobase + APCI3501_DIGITAL_OP);
+	if (mask) {
+		s->state &= ~mask;
+		s->state |= (bits & mask);
+
+		outl(s->state, devpriv->iobase + APCI3501_DIGITAL_OP);
+	}
+
+	data[1] = s->state;
 
-/*
-+----------------------------------------------------------------------------+
-| Function   Name   : int i_APCI3501_ReadDigitalOutput                       |
-|			  (struct comedi_device *dev,struct comedi_subdevice *s,               |
-|                      struct comedi_insn *insn,unsigned int *data)                     |
-+----------------------------------------------------------------------------+
-| Task              : Read  value  of the selected channel or port           |
-+----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev      : Driver handle                |
-|                     unsigned int ui_NoOfChannels    : No Of Channels To read       |
-|                     unsigned int *data              : Data Pointer to read status  |
-+----------------------------------------------------------------------------+
-| Output Parameters :	--													 |
-+----------------------------------------------------------------------------+
-| Return Value      : TRUE  : No error occur                                 |
-|		            : FALSE : Error occur. Return the error          |
-|			                                                         |
-+----------------------------------------------------------------------------+
-*/
-int i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
-{
-	unsigned int ui_Temp;
-	unsigned int ui_NoOfChannel;
-
-	ui_NoOfChannel = CR_CHAN(insn->chanspec);
-	ui_Temp = data[0];
-	*data = inl(devpriv->iobase + APCI3501_DIGITAL_OP);
-	if (ui_Temp == 0) {
-		*data = (*data >> ui_NoOfChannel) & 0x1;
-	}			/*  if  (ui_Temp==0) */
-	else {
-		if (ui_Temp == 1) {
-			*data = *data & 0x3;
-
-		}		/*  if  (ui_Temp==1) */
-		else {
-			printk("\nSpecified channel not supported \n");
-		}		/*  else if (ui_Temp==1) */
-	}			/*  else if  (ui_Temp==0) */
 	return insn->n;
 }
 
@@ -298,9 +144,13 @@ int i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdev
 |			                                                         |
 +----------------------------------------------------------------------------+
 */
-int i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev,
+					 struct comedi_subdevice *s,
+					 struct comedi_insn *insn,
+					 unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
+
 	outl(data[0],
 		devpriv->iobase + APCI3501_ANALOG_OUTPUT +
 		APCI3501_AO_VOLT_MODE);
@@ -336,9 +186,12 @@ int i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, struct comedi_subde
 |			                                                         |
 +----------------------------------------------------------------------------+
 */
-int i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-	struct comedi_insn *insn, unsigned int *data)
+static int i_APCI3501_WriteAnalogOutput(struct comedi_device *dev,
+					struct comedi_subdevice *s,
+					struct comedi_insn *insn,
+					unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0;
 
 	ul_Channel_no = CR_CHAN(insn->chanspec);
@@ -410,10 +263,14 @@ int i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, struct comedi_subdev
 |			                                                         |
 +----------------------------------------------------------------------------+
 */
-int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
+						 struct comedi_subdevice *s,
+						 struct comedi_insn *insn,
+						 unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ul_Command1 = 0;
+
 	devpriv->tsk_Current = current;
 	if (data[0] == ADDIDATA_WATCHDOG) {
 
@@ -511,11 +368,15 @@ int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
+							 struct comedi_subdevice *s,
+							 struct comedi_insn *insn,
+							 unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned int ul_Command1 = 0;
 	int i_Temp;
+
 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
 
 		if (data[1] == 1) {
@@ -613,9 +474,12 @@ int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev,
-	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
+static int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev,
+					       struct comedi_subdevice *s,
+					       struct comedi_insn *insn,
+					       unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 
 	if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
 		data[0] =
@@ -654,10 +518,12 @@ int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev,
 +----------------------------------------------------------------------------+
 */
 
-int i_APCI3501_Reset(struct comedi_device *dev)
+static int i_APCI3501_Reset(struct comedi_device *dev)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_Count = 0, i_temp = 0;
 	unsigned int ul_Command1 = 0, ul_Polarity, ul_DAC_Ready = 0;
+
 	outl(0x0, devpriv->iobase + APCI3501_DIGITAL_OP);
 	outl(1, devpriv->iobase + APCI3501_ANALOG_OUTPUT +
 		APCI3501_AO_VOLT_MODE);
@@ -705,12 +571,14 @@ int i_APCI3501_Reset(struct comedi_device *dev)
 |			                                                         |
 +----------------------------------------------------------------------------+
 */
-void v_APCI3501_Interrupt(int irq, void *d)
+static void v_APCI3501_Interrupt(int irq, void *d)
 {
 	int i_temp;
 	struct comedi_device *dev = d;
+	struct addi_private *devpriv = dev->private;
 	unsigned int ui_Timer_AOWatchdog;
 	unsigned long ul_Command1;
+
 	/*  Disable Interrupt */
 	ul_Command1 =
 		inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
deleted file mode 100644
index 63df635..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/* Card Specific information */
-#define APCI3501_BOARD_VENDOR_ID                 0x15B8
-#define APCI3501_ADDRESS_RANGE                   255
-
-#define APCI3501_DIGITAL_IP                       0x50
-#define APCI3501_DIGITAL_OP                       0x40
-#define APCI3501_ANALOG_OUTPUT                    0x00
-
-/* Analog Output related Defines */
-#define APCI3501_AO_VOLT_MODE                     0
-#define APCI3501_AO_PROG                          4
-#define APCI3501_AO_TRIG_SCS                      8
-#define UNIPOLAR                                  0
-#define BIPOLAR                                   1
-#define MODE0                                     0
-#define MODE1                                     1
-/* ANALOG OUTPUT RANGE */
-static struct comedi_lrange range_apci3501_ao = { 2, {
-					BIP_RANGE(10),
-					UNI_RANGE(10)
-					}
-};
-
-/* Watchdog Related Defines */
-
-#define APCI3501_WATCHDOG                         0x20
-#define APCI3501_TCW_SYNC_ENABLEDISABLE           0
-#define APCI3501_TCW_RELOAD_VALUE                 4
-#define APCI3501_TCW_TIMEBASE                     8
-#define APCI3501_TCW_PROG                         12
-#define APCI3501_TCW_TRIG_STATUS                  16
-#define APCI3501_TCW_IRQ                          20
-#define APCI3501_TCW_WARN_TIMEVAL                 24
-#define APCI3501_TCW_WARN_TIMEBASE                28
-#define ADDIDATA_TIMER                            0
-#define ADDIDATA_WATCHDOG                         2
-
-/* Hardware Layer  functions for Apci3501 */
-
-/* AO */
-int i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data);
-int i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-
-/*
-* DI for di read INT i_APCI3501_ReadDigitalInput(struct
-* comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn
-* *insn,unsigned int *data);
-*/
-
-int i_APCI3501_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data);
-
-/* DO */
-int i_APCI3501_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data);
-int i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data);
-int i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-
-/* TIMER
- * timer value is passed as u seconds
- */
-
-int i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev,
-					  struct comedi_subdevice *s,
-					  struct comedi_insn *insn, unsigned int *data);
-int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev,
-						  struct comedi_subdevice *s,
-						  struct comedi_insn *insn,
-						  unsigned int *data);
-int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev,
-					struct comedi_subdevice *s,
-					struct comedi_insn *insn, unsigned int *data);
-/* Interrupt */
-void v_APCI3501_Interrupt(int irq, void *d);
-
-/* Reset functions */
-int i_APCI3501_Reset(struct comedi_device *dev);
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
index fff99df..a45a2a2 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
@@ -44,7 +44,35 @@ You should also find the complete GPL in the COPYING file accompanying this sour
   +----------+-----------+------------------------------------------------+
 */
 
-#include "hwdrv_apci3xxx.h"
+#ifndef COMEDI_SUBD_TTLIO
+#define COMEDI_SUBD_TTLIO	11	/* Digital Input Output But TTL */
+#endif
+
+#define APCI3XXX_SINGLE				0
+#define APCI3XXX_DIFF				1
+#define APCI3XXX_CONFIGURATION			0
+
+#define APCI3XXX_TTL_INIT_DIRECTION_PORT2	0
+
+static const struct comedi_lrange range_apci3XXX_ai = {
+	8, {
+		BIP_RANGE(10),
+		BIP_RANGE(5),
+		BIP_RANGE(2),
+		BIP_RANGE(1),
+		UNI_RANGE(10),
+		UNI_RANGE(5),
+		UNI_RANGE(2),
+		UNI_RANGE(1)
+	}
+};
+
+static const struct comedi_lrange range_apci3XXX_ao = {
+	2, {
+		BIP_RANGE(10),
+		UNI_RANGE(10)
+	}
+};
 
 /*
 +----------------------------------------------------------------------------+
@@ -69,6 +97,8 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 */
 static int i_APCI3XXX_TestConversionStarted(struct comedi_device *dev)
 {
+	struct addi_private *devpriv = dev->private;
+
 	if ((readl(devpriv->dw_AiBase + 8) & 0x80000UL) == 0x80000UL)
 		return 1;
 	else
@@ -108,6 +138,8 @@ static int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device *dev,
 						     struct comedi_insn *insn,
 						     unsigned int *data)
 {
+	const struct addi_board *this_board = comedi_board(dev);
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = insn->n;
 	unsigned char b_TimeBase = 0;
 	unsigned char b_SingleDiff = 0;
@@ -358,6 +390,8 @@ static int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
 					  struct comedi_insn *insn,
 					  unsigned int *data)
 {
+	const struct addi_board *this_board = comedi_board(dev);
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = insn->n;
 	unsigned char b_Configuration = (unsigned char) CR_RANGE(insn->chanspec);
 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
@@ -571,6 +605,7 @@ static int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
 static void v_APCI3XXX_Interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct addi_private *devpriv = dev->private;
 	unsigned char b_CopyCpt = 0;
 	unsigned int dw_Status = 0;
 
@@ -651,6 +686,7 @@ static int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device *dev,
 					    struct comedi_insn *insn,
 					    unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned char b_Range = (unsigned char) CR_RANGE(insn->chanspec);
 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
 	unsigned int dw_Status = 0;
@@ -755,6 +791,7 @@ static int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device *dev,
 					  struct comedi_insn *insn,
 					  unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = insn->n;
 	unsigned char b_Command = 0;
 
@@ -884,6 +921,7 @@ static int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device *dev,
 				    struct comedi_insn *insn,
 				    unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = insn->n;
 	unsigned char b_ChannelCpt = 0;
 	unsigned int dw_ChannelMask = 0;
@@ -1040,6 +1078,7 @@ static int i_APCI3XXX_InsnReadTTLIO(struct comedi_device *dev,
 				    struct comedi_insn *insn,
 				    unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
 	int i_ReturnValue = insn->n;
 	unsigned int *pls_ReadData = data;
@@ -1154,6 +1193,7 @@ static int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device *dev,
 				     struct comedi_insn *insn,
 				     unsigned int *data)
 {
+	struct addi_private *devpriv = dev->private;
 	int i_ReturnValue = insn->n;
 	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
 	unsigned char b_State = 0;
@@ -1236,367 +1276,38 @@ static int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device *dev,
 	return i_ReturnValue;
 }
 
-/*
-+----------------------------------------------------------------------------+
-|                           DIGITAL INPUT SUBDEVICE                          |
-+----------------------------------------------------------------------------+
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3XXX_InsnReadDigitalInput                     |
-|                                          (struct comedi_device *dev,              |
-|                                           struct comedi_subdevice *s,             |
-|                                           struct comedi_insn *insn,               |
-|                                           unsigned int *data)                  |
-+----------------------------------------------------------------------------+
-| Task              : Reads the value of the specified Digital input channel |
-+----------------------------------------------------------------------------+
-| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec) (0 to 3)           |
-+----------------------------------------------------------------------------+
-| Output Parameters : data[0] : Channel value                                |
-+----------------------------------------------------------------------------+
-| Return Value      : 0   : No error                                         |
-|                    -3   : Channel selection error                          |
-|                    -101 : Data size error                                  |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device *dev,
-					   struct comedi_subdevice *s,
-					   struct comedi_insn *insn,
-					   unsigned int *data)
-{
-	int i_ReturnValue = insn->n;
-	unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
-	unsigned int dw_Temp = 0;
-
-	/***************************/
-	/* Test the channel number */
-	/***************************/
-
-	if (b_Channel <= devpriv->s_EeParameters.i_NbrDiChannel) {
-	   /************************/
-		/* Test the buffer size */
-	   /************************/
-
-		if (insn->n >= 1) {
-			dw_Temp = inl(devpriv->iobase + 32);
-			*data = (dw_Temp >> b_Channel) & 1;
-		} else {
-	      /*******************/
-			/* Data size error */
-	      /*******************/
-
-			printk("Buffer size error\n");
-			i_ReturnValue = -101;
-		}
-	} else {
-	   /***************************/
-		/* Channel selection error */
-	   /***************************/
-
-		printk("Channel selection error\n");
-		i_ReturnValue = -3;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3XXX_InsnBitsDigitalInput                     |
-|                                          (struct comedi_device *dev,              |
-|                                           struct comedi_subdevice *s,             |
-|                                           struct comedi_insn *insn,               |
-|                                           unsigned int *data)                  |
-+----------------------------------------------------------------------------+
-| Task              : Reads the value of the Digital input Port i.e.4channels|
-+----------------------------------------------------------------------------+
-| Input Parameters  : -                                                      |
-+----------------------------------------------------------------------------+
-| Output Parameters : data[0] : Port value                                   |
-+----------------------------------------------------------------------------+
-| Return Value      :>0: No error                                            |
-|                    ....                                                    |
-|                    -101 : Data size error                                  |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device *dev,
-					   struct comedi_subdevice *s,
-					   struct comedi_insn *insn,
-					   unsigned int *data)
-{
-	int i_ReturnValue = insn->n;
-	unsigned int dw_Temp = 0;
-
-	/************************/
-	/* Test the buffer size */
-	/************************/
-
-	if (insn->n >= 1) {
-		dw_Temp = inl(devpriv->iobase + 32);
-		*data = dw_Temp & 0xf;
-	} else {
-	   /*******************/
-		/* Data size error */
-	   /*******************/
-
-		printk("Buffer size error\n");
-		i_ReturnValue = -101;
-	}
-
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-|                           DIGITAL OUTPUT SUBDEVICE                         |
-+----------------------------------------------------------------------------+
-
-*/
-
-/*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3XXX_InsnBitsDigitalOutput                    |
-|                                          (struct comedi_device *dev,              |
-|                                           struct comedi_subdevice *s,             |
-|                                           struct comedi_insn *insn,               |
-|                                           unsigned int *data)                  |
-+----------------------------------------------------------------------------+
-| Task              : Write the selected output mask and read the status from|
-|                     all digital output channles                            |
-+----------------------------------------------------------------------------+
-| Input Parameters  : dw_ChannelMask = data [0];                             |
-|                     dw_BitMask     = data [1];                             |
-+----------------------------------------------------------------------------+
-| Output Parameters : data[1] : All digital output channles states           |
-+----------------------------------------------------------------------------+
-| Return Value      : >0  : No error                                         |
-|                    -4   : Channel mask error                               |
-|                    -101 : Data size error                                  |
-+----------------------------------------------------------------------------+
-*/
-static int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device *dev,
-					    struct comedi_subdevice *s,
-					    struct comedi_insn *insn,
-					    unsigned int *data)
+static int apci3xxx_di_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	int i_ReturnValue = insn->n;
-	unsigned char b_ChannelCpt = 0;
-	unsigned int dw_ChannelMask = 0;
-	unsigned int dw_BitMask = 0;
-	unsigned int dw_Status = 0;
-
-	/************************/
-	/* Test the buffer size */
-	/************************/
-
-	if (insn->n >= 2) {
-	   /*******************************/
-		/* Get the channe and bit mask */
-	   /*******************************/
-
-		dw_ChannelMask = data[0];
-		dw_BitMask = data[1];
-
-	   /*************************/
-		/* Test the channel mask */
-	   /*************************/
-
-		if ((dw_ChannelMask & 0XFFFFFFF0) == 0) {
-	      /*********************************/
-			/* Test if set/reset any channel */
-	      /*********************************/
-
-			if (dw_ChannelMask & 0xF) {
-		 /********************************/
-				/* Read the digital output port */
-		 /********************************/
-
-				dw_Status = inl(devpriv->iobase + 48);
+	struct addi_private *devpriv = dev->private;
 
-				for (b_ChannelCpt = 0; b_ChannelCpt < 4;
-					b_ChannelCpt++) {
-					if ((dw_ChannelMask >> b_ChannelCpt) &
-						1) {
-						dw_Status =
-							(dw_Status & (0xF -
-								(1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt));
-					}
-				}
-
-				outl(dw_Status, devpriv->iobase + 48);
-			}
-
-	      /********************************/
-			/* Read the digital output port */
-	      /********************************/
-
-			data[1] = inl(devpriv->iobase + 48);
-		} else {
-	      /************************/
-			/* Config command error */
-	      /************************/
-
-			printk("Channel mask error\n");
-			i_ReturnValue = -4;
-		}
-	} else {
-	   /*******************/
-		/* Data size error */
-	   /*******************/
-
-		printk("Buffer size error\n");
-		i_ReturnValue = -101;
-	}
+	data[1] = inl(devpriv->iobase + 32) & 0xf;
 
-	return i_ReturnValue;
+	return insn->n;
 }
 
-/*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3XXX_InsnWriteDigitalOutput                   |
-|                                          (struct comedi_device *dev,              |
-|                                           struct comedi_subdevice *s,             |
-|                                           struct comedi_insn *insn,               |
-|                                           unsigned int *data)                  |
-+----------------------------------------------------------------------------+
-| Task              : Set the state from digital output channel              |
-+----------------------------------------------------------------------------+
-| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec)                    |
-|                     b_State   = data [0]                                   |
-+----------------------------------------------------------------------------+
-| Output Parameters : -                                                      |
-+----------------------------------------------------------------------------+
-| Return Value      : >0  : No error                                         |
-|                    -3   : Channel selection error                          |
-|                    -101 : Data size error                                  |
-+----------------------------------------------------------------------------+
-*/
-
-static int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device *dev,
-					     struct comedi_subdevice *s,
-					     struct comedi_insn *insn,
-					     unsigned int *data)
+static int apci3xxx_do_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	int i_ReturnValue = insn->n;
-	unsigned char b_Channel = CR_CHAN(insn->chanspec);
-	unsigned char b_State = 0;
-	unsigned int dw_Status = 0;
-
-	/************************/
-	/* Test the buffer size */
-	/************************/
-
-	if (insn->n >= 1) {
-	   /***************************/
-		/* Test the channel number */
-	   /***************************/
-
-		if (b_Channel < devpriv->s_EeParameters.i_NbrDoChannel) {
-	      /*******************/
-			/* Get the command */
-	      /*******************/
-
-			b_State = (unsigned char) data[0];
-
-	      /********************************/
-			/* Read the digital output port */
-	      /********************************/
-
-			dw_Status = inl(devpriv->iobase + 48);
-
-			dw_Status =
-				(dw_Status & (0xF -
-					(1 << b_Channel))) | ((b_State & 1) <<
-				b_Channel);
-			outl(dw_Status, devpriv->iobase + 48);
-		} else {
-	      /***************************/
-			/* Channel selection error */
-	      /***************************/
+	struct addi_private *devpriv = dev->private;
+	unsigned int mask = data[0];
+	unsigned int bits = data[1];
 
-			printk("Channel selection error\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*******************/
-		/* Data size error */
-	   /*******************/
+	s->state = inl(devpriv->iobase + 48) & 0xf;
+	if (mask) {
+		s->state &= ~mask;
+		s->state |= (bits & mask);
 
-		printk("Buffer size error\n");
-		i_ReturnValue = -101;
+		outl(s->state, devpriv->iobase + 48);
 	}
 
-	return i_ReturnValue;
-}
-
-/*
-+----------------------------------------------------------------------------+
-| Function name     :int i_APCI3XXX_InsnReadDigitalOutput                    |
-|                                          (struct comedi_device *dev,              |
-|                                           struct comedi_subdevice *s,             |
-|                                           struct comedi_insn *insn,               |
-|                                           unsigned int *data)                  |
-+----------------------------------------------------------------------------+
-| Task              : Read the state from digital output channel             |
-+----------------------------------------------------------------------------+
-| Input Parameters  : b_Channel = CR_CHAN(insn->chanspec)                    |
-+----------------------------------------------------------------------------+
-| Output Parameters : b_State   = data [0]                                   |
-+----------------------------------------------------------------------------+
-| Return Value      : >0  : No error                                         |
-|                    -3   : Channel selection error                          |
-|                    -101 : Data size error                                  |
-+----------------------------------------------------------------------------+
-*/
+	data[1] = s->state;
 
-static int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device *dev,
-					    struct comedi_subdevice *s,
-					    struct comedi_insn *insn,
-					    unsigned int *data)
-{
-	int i_ReturnValue = insn->n;
-	unsigned char b_Channel = CR_CHAN(insn->chanspec);
-	unsigned int dw_Status = 0;
-
-	/************************/
-	/* Test the buffer size */
-	/************************/
-
-	if (insn->n >= 1) {
-	   /***************************/
-		/* Test the channel number */
-	   /***************************/
-
-		if (b_Channel < devpriv->s_EeParameters.i_NbrDoChannel) {
-	      /********************************/
-			/* Read the digital output port */
-	      /********************************/
-
-			dw_Status = inl(devpriv->iobase + 48);
-
-			dw_Status = (dw_Status >> b_Channel) & 1;
-			*data = dw_Status;
-		} else {
-	      /***************************/
-			/* Channel selection error */
-	      /***************************/
-
-			printk("Channel selection error\n");
-			i_ReturnValue = -3;
-		}
-	} else {
-	   /*******************/
-		/* Data size error */
-	   /*******************/
-
-		printk("Buffer size error\n");
-		i_ReturnValue = -101;
-	}
-
-	return i_ReturnValue;
+	return insn->n;
 }
 
 /*
@@ -1614,6 +1325,7 @@ static int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device *dev,
 
 static int i_APCI3XXX_Reset(struct comedi_device *dev)
 {
+	struct addi_private *devpriv = dev->private;
 	unsigned char b_Cpt = 0;
 
 	/*************************/
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h
deleted file mode 100644
index e10b7e5..0000000
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
- *
- *	ADDI-DATA GmbH
- *	Dieselstrasse 3
- *	D-77833 Ottersweier
- *	Tel: +19(0)7223/9493-0
- *	Fax: +49(0)7223/9493-92
- *	http://www.addi-data.com
- *	info@addi-data.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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 COMEDI_SUBD_TTLIO
-#define COMEDI_SUBD_TTLIO   11	/* Digital Input Output But TTL */
-#endif
-
-#ifndef ADDIDATA_ENABLE
-#define ADDIDATA_ENABLE  1
-#define ADDIDATA_DISABLE 0
-#endif
-
-#define APCI3XXX_SINGLE                              0
-#define APCI3XXX_DIFF                                1
-#define APCI3XXX_CONFIGURATION                       0
-
-#define APCI3XXX_TTL_INIT_DIRECTION_PORT2   0
-
-#ifdef __KERNEL__
-
-static const struct comedi_lrange range_apci3XXX_ai = { 8, {BIP_RANGE(10),
-						     BIP_RANGE(5),
-						     BIP_RANGE(2),
-						     BIP_RANGE(1),
-						     UNI_RANGE(10),
-						     UNI_RANGE(5),
-						     UNI_RANGE(2),
-						     UNI_RANGE(1)}
-};
-
-static const struct comedi_lrange range_apci3XXX_ao = { 2, {BIP_RANGE(10),
-						     UNI_RANGE(10)}
-};
-#endif
diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c
index 4c00df4..c981d4b 100644
--- a/drivers/staging/comedi/drivers/addi_apci_035.c
+++ b/drivers/staging/comedi/drivers/addi_apci_035.c
@@ -1,11 +1,77 @@
-#define CONFIG_APCI_035 1
+#include "../comedidev.h"
+#include "comedi_fc.h"
+#include "amcc_s5933.h"
 
-#define ADDIDATA_WATCHDOG 2	/*  Or shold it be something else */
+#include "addi-data/addi_common.h"
 
-#define ADDIDATA_DRIVER_NAME	"addi_apci_035"
+#define ADDIDATA_WATCHDOG 2	/*  Or shold it be something else */
 
+#include "addi-data/addi_eeprom.c"
+#include "addi-data/hwdrv_apci035.c"
 #include "addi-data/addi_common.c"
 
+static const struct addi_board apci035_boardtypes[] = {
+	{
+		.pc_DriverName		= "apci035",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x0300,
+		.i_IorangeBase0		= 127,
+		.i_IorangeBase1		= APCI035_ADDRESS_RANGE,
+		.i_PCIEeprom		= 1,
+		.pc_EepromChip		= ADDIDATA_S5920,
+		.i_NbrAiChannel		= 16,
+		.i_NbrAiChannelDiff	= 8,
+		.i_AiChannelList	= 16,
+		.i_AiMaxdata		= 0xff,
+		.pr_AiRangelist		= &range_apci035_ai,
+		.i_Timer		= 1,
+		.ui_MinAcquisitiontimeNs = 10000,
+		.ui_MinDelaytimeNs	= 100000,
+		.interrupt		= v_APCI035_Interrupt,
+		.reset			= i_APCI035_Reset,
+		.ai_config		= i_APCI035_ConfigAnalogInput,
+		.ai_read		= i_APCI035_ReadAnalogInput,
+		.timer_config		= i_APCI035_ConfigTimerWatchdog,
+		.timer_write		= i_APCI035_StartStopWriteTimerWatchdog,
+		.timer_read		= i_APCI035_ReadTimerWatchdog,
+	},
+};
+
+static struct comedi_driver apci035_driver = {
+	.driver_name	= "addi_apci_035",
+	.module		= THIS_MODULE,
+	.auto_attach	= addi_auto_attach,
+	.detach		= i_ADDI_Detach,
+	.num_names	= ARRAY_SIZE(apci035_boardtypes),
+	.board_name	= &apci035_boardtypes[0].pc_DriverName,
+	.offset		= sizeof(struct addi_board),
+};
+
+static int apci035_pci_probe(struct pci_dev *dev,
+				       const struct pci_device_id *ent)
+{
+	return comedi_pci_auto_config(dev, &apci035_driver);
+}
+
+static void apci035_pci_remove(struct pci_dev *dev)
+{
+	comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(apci035_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA,  0x0300) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, apci035_pci_table);
+
+static struct pci_driver apci035_pci_driver = {
+	.name		= "addi_apci_035",
+	.id_table	= apci035_pci_table,
+	.probe		= apci035_pci_probe,
+	.remove		= apci035_pci_remove,
+};
+module_comedi_pci_driver(apci035_driver, apci035_pci_driver);
+
 MODULE_AUTHOR("Comedi http://www.comedi.org");
 MODULE_DESCRIPTION("Comedi low-level driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c
index 7831ce3..7f94242 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1032.c
@@ -1,8 +1,398 @@
-#define CONFIG_APCI_1032 1
+/*
+ * addi_apci_1032.c
+ * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ * Project manager: Eric Stolz
+ *
+ *	ADDI-DATA GmbH
+ *	Dieselstrasse 3
+ *	D-77833 Ottersweier
+ *	Tel: +19(0)7223/9493-0
+ *	Fax: +49(0)7223/9493-92
+ *	http://www.addi-data.com
+ *	info@addi-data.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * You should also find the complete GPL in the COPYING file accompanying this
+ * source code.
+ */
 
-#define ADDIDATA_DRIVER_NAME	"addi_apci_1032"
+#include "../comedidev.h"
+#include "comedi_fc.h"
+#include "amcc_s5933.h"
 
-#include "addi-data/addi_common.c"
+/*
+ * I/O Register Map
+ */
+#define APCI1032_DI_REG			0x00
+#define APCI1032_MODE1_REG		0x04
+#define APCI1032_MODE2_REG		0x08
+#define APCI1032_STATUS_REG		0x0c
+#define APCI1032_CTRL_REG		0x10
+#define APCI1032_CTRL_INT_OR		(0 << 1)
+#define APCI1032_CTRL_INT_AND		(1 << 1)
+#define APCI1032_CTRL_INT_ENA		(1 << 2)
+
+struct apci1032_private {
+	unsigned long amcc_iobase;	/* base of AMCC I/O registers */
+	unsigned int mode1;	/* rising-edge/high level channels */
+	unsigned int mode2;	/* falling-edge/low level channels */
+	unsigned int ctrl;	/* interrupt mode OR (edge) . AND (level) */
+};
+
+static int apci1032_reset(struct comedi_device *dev)
+{
+	/* disable the interrupts */
+	outl(0x0, dev->iobase + APCI1032_CTRL_REG);
+	/* Reset the interrupt status register */
+	inl(dev->iobase + APCI1032_STATUS_REG);
+	/* Disable the and/or interrupt */
+	outl(0x0, dev->iobase + APCI1032_MODE1_REG);
+	outl(0x0, dev->iobase + APCI1032_MODE2_REG);
+
+	return 0;
+}
+
+/*
+ * Change-Of-State (COS) interrupt configuration
+ *
+ * Channels 0 to 15 are interruptible. These channels can be configured
+ * to generate interrupts based on AND/OR logic for the desired channels.
+ *
+ *	OR logic
+ *		- reacts to rising or falling edges
+ *		- interrupt is generated when any enabled channel
+ *		  meet the desired interrupt condition
+ *
+ *	AND logic
+ *		- reacts to changes in level of the selected inputs
+ *		- interrupt is generated when all enabled channels
+ *		  meet the desired interrupt condition
+ *		- after an interrupt, a change in level must occur on
+ *		  the selected inputs to release the IRQ logic
+ *
+ * The COS interrupt must be configured before it can be enabled.
+ *
+ *	data[0] : INSN_CONFIG_DIGITAL_TRIG
+ *	data[1] : trigger number (= 0)
+ *	data[2] : configuration operation:
+ *	          COMEDI_DIGITAL_TRIG_DISABLE = no interrupts
+ *	          COMEDI_DIGITAL_TRIG_ENABLE_EDGES = OR (edge) interrupts
+ *	          COMEDI_DIGITAL_TRIG_ENABLE_LEVELS = AND (level) interrupts
+ *	data[3] : left-shift for data[4] and data[5]
+ *	data[4] : rising-edge/high level channels
+ *	data[5] : falling-edge/low level channels
+ */
+static int apci1032_cos_insn_config(struct comedi_device *dev,
+				    struct comedi_subdevice *s,
+				    struct comedi_insn *insn,
+				    unsigned int *data)
+{
+	struct apci1032_private *devpriv = dev->private;
+	unsigned int shift, oldmask;
+
+	switch (data[0]) {
+	case INSN_CONFIG_DIGITAL_TRIG:
+		if (data[1] != 0)
+			return -EINVAL;
+		shift = data[3];
+		oldmask = (1U << shift) - 1;
+		switch (data[2]) {
+		case COMEDI_DIGITAL_TRIG_DISABLE:
+			devpriv->ctrl = 0;
+			devpriv->mode1 = 0;
+			devpriv->mode2 = 0;
+			apci1032_reset(dev);
+			break;
+		case COMEDI_DIGITAL_TRIG_ENABLE_EDGES:
+			if (devpriv->ctrl != (APCI1032_CTRL_INT_ENA |
+					      APCI1032_CTRL_INT_OR)) {
+				/* switching to 'OR' mode */
+				devpriv->ctrl = APCI1032_CTRL_INT_ENA |
+						APCI1032_CTRL_INT_OR;
+				/* wipe old channels */
+				devpriv->mode1 = 0;
+				devpriv->mode2 = 0;
+			} else {
+				/* preserve unspecified channels */
+				devpriv->mode1 &= oldmask;
+				devpriv->mode2 &= oldmask;
+			}
+			/* configure specified channels */
+			devpriv->mode1 |= data[4] << shift;
+			devpriv->mode2 |= data[5] << shift;
+			break;
+		case COMEDI_DIGITAL_TRIG_ENABLE_LEVELS:
+			if (devpriv->ctrl != (APCI1032_CTRL_INT_ENA |
+					      APCI1032_CTRL_INT_AND)) {
+				/* switching to 'AND' mode */
+				devpriv->ctrl = APCI1032_CTRL_INT_ENA |
+						APCI1032_CTRL_INT_AND;
+				/* wipe old channels */
+				devpriv->mode1 = 0;
+				devpriv->mode2 = 0;
+			} else {
+				/* preserve unspecified channels */
+				devpriv->mode1 &= oldmask;
+				devpriv->mode2 &= oldmask;
+			}
+			/* configure specified channels */
+			devpriv->mode1 |= data[4] << shift;
+			devpriv->mode2 |= data[5] << shift;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return insn->n;
+}
+
+static int apci1032_cos_insn_bits(struct comedi_device *dev,
+				  struct comedi_subdevice *s,
+				  struct comedi_insn *insn,
+				  unsigned int *data)
+{
+	data[1] = s->state;
+
+	return 0;
+}
+
+static int apci1032_cos_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;
+}
+
+/*
+ * Change-Of-State (COS) 'do_cmd' operation
+ *
+ * Enable the COS interrupt as configured by apci1032_cos_insn_config().
+ */
+static int apci1032_cos_cmd(struct comedi_device *dev,
+			    struct comedi_subdevice *s)
+{
+	struct apci1032_private *devpriv = dev->private;
+
+	if (!devpriv->ctrl) {
+		dev_warn(dev->class_dev,
+			"Interrupts disabled due to mode configuration!\n");
+		return -EINVAL;
+	}
+
+	outl(devpriv->mode1, dev->iobase + APCI1032_MODE1_REG);
+	outl(devpriv->mode2, dev->iobase + APCI1032_MODE2_REG);
+	outl(devpriv->ctrl, dev->iobase + APCI1032_CTRL_REG);
+
+	return 0;
+}
+
+static int apci1032_cos_cancel(struct comedi_device *dev,
+			       struct comedi_subdevice *s)
+{
+	return apci1032_reset(dev);
+}
+
+static irqreturn_t apci1032_interrupt(int irq, void *d)
+{
+	struct comedi_device *dev = d;
+	struct apci1032_private *devpriv = dev->private;
+	struct comedi_subdevice *s = dev->read_subdev;
+	unsigned int ctrl;
+
+	/* check interrupt is from this device */
+	if ((inl(devpriv->amcc_iobase + AMCC_OP_REG_INTCSR) &
+	     INTCSR_INTR_ASSERTED) == 0)
+		return IRQ_NONE;
+
+	/* check interrupt is enabled */
+	ctrl = inl(dev->iobase + APCI1032_CTRL_REG);
+	if ((ctrl & APCI1032_CTRL_INT_ENA) == 0)
+		return IRQ_HANDLED;
+
+	/* disable the interrupt */
+	outl(ctrl & ~APCI1032_CTRL_INT_ENA, dev->iobase + APCI1032_CTRL_REG);
+
+	s->state = inl(dev->iobase + APCI1032_STATUS_REG) & 0xffff;
+	comedi_buf_put(s->async, s->state);
+	s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
+	comedi_event(dev, s);
+
+	/* enable the interrupt */
+	outl(ctrl, dev->iobase + APCI1032_CTRL_REG);
+
+	return IRQ_HANDLED;
+}
+
+static int apci1032_di_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
+{
+	data[1] = inl(dev->iobase + APCI1032_DI_REG);
+
+	return insn->n;
+}
+
+static int apci1032_auto_attach(struct comedi_device *dev,
+					  unsigned long context_unused)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct apci1032_private *devpriv;
+	struct comedi_subdevice *s;
+	int ret;
+
+	dev->board_name = dev->driver->driver_name;
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
+	ret = comedi_pci_enable(pcidev, dev->board_name);
+	if (ret)
+		return ret;
+
+	devpriv->amcc_iobase = pci_resource_start(pcidev, 0);
+	dev->iobase = pci_resource_start(pcidev, 1);
+	apci1032_reset(dev);
+	if (pcidev->irq > 0) {
+		ret = request_irq(pcidev->irq, apci1032_interrupt, IRQF_SHARED,
+				  dev->board_name, dev);
+		if (ret == 0)
+			dev->irq = pcidev->irq;
+	}
+
+	ret = comedi_alloc_subdevices(dev, 2);
+	if (ret)
+		return ret;
+
+	/*  Allocate and Initialise DI Subdevice Structures */
+	s = &dev->subdevices[0];
+	s->type		= COMEDI_SUBD_DI;
+	s->subdev_flags	= SDF_READABLE;
+	s->n_chan	= 32;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= apci1032_di_insn_bits;
+
+	/* Change-Of-State (COS) interrupt subdevice */
+	s = &dev->subdevices[1];
+	if (dev->irq) {
+		dev->read_subdev = s;
+		s->type		= COMEDI_SUBD_DI | SDF_CMD_READ;
+		s->subdev_flags	= SDF_READABLE;
+		s->n_chan	= 1;
+		s->maxdata	= 1;
+		s->range_table	= &range_digital;
+		s->insn_config	= apci1032_cos_insn_config;
+		s->insn_bits	= apci1032_cos_insn_bits;
+		s->do_cmdtest	= apci1032_cos_cmdtest;
+		s->do_cmd	= apci1032_cos_cmd;
+		s->cancel	= apci1032_cos_cancel;
+	} else {
+		s->type		= COMEDI_SUBD_UNUSED;
+	}
+
+	return 0;
+}
+
+static void apci1032_detach(struct comedi_device *dev)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+
+	if (dev->iobase)
+		apci1032_reset(dev);
+	if (dev->irq)
+		free_irq(dev->irq, dev);
+	if (pcidev) {
+		if (dev->iobase)
+			comedi_pci_disable(pcidev);
+	}
+}
+
+static struct comedi_driver apci1032_driver = {
+	.driver_name	= "addi_apci_1032",
+	.module		= THIS_MODULE,
+	.auto_attach	= apci1032_auto_attach,
+	.detach		= apci1032_detach,
+};
+
+static int apci1032_pci_probe(struct pci_dev *dev,
+					const struct pci_device_id *ent)
+{
+	return comedi_pci_auto_config(dev, &apci1032_driver);
+}
+
+static void apci1032_pci_remove(struct pci_dev *dev)
+{
+	comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(apci1032_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1003) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, apci1032_pci_table);
+
+static struct pci_driver apci1032_pci_driver = {
+	.name		= "addi_apci_1032",
+	.id_table	= apci1032_pci_table,
+	.probe		= apci1032_pci_probe,
+	.remove		= apci1032_pci_remove,
+};
+module_comedi_pci_driver(apci1032_driver, apci1032_pci_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
 MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c
index bfd84f6..8e686a9 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1500.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1500.c
@@ -1,9 +1,77 @@
-#define CONFIG_APCI_1500 1
+#include "../comedidev.h"
+#include "comedi_fc.h"
+#include "amcc_s5933.h"
 
-#define ADDIDATA_DRIVER_NAME	"addi_apci_1500"
+#include "addi-data/addi_common.h"
 
+#include "addi-data/addi_eeprom.c"
+#include "addi-data/hwdrv_apci1500.c"
 #include "addi-data/addi_common.c"
 
+static const struct addi_board apci1500_boardtypes[] = {
+	{
+		.pc_DriverName		= "apci1500",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA_OLD,
+		.i_DeviceId		= 0x80fc,
+		.i_IorangeBase0		= 128,
+		.i_IorangeBase1		= APCI1500_ADDRESS_RANGE,
+		.i_IorangeBase2		= 4,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.i_NbrDiChannel		= 16,
+		.i_NbrDoChannel		= 16,
+		.i_DoMaxdata		= 0xffff,
+		.i_Timer		= 1,
+		.interrupt		= v_APCI1500_Interrupt,
+		.reset			= i_APCI1500_Reset,
+		.di_config		= i_APCI1500_ConfigDigitalInputEvent,
+		.di_read		= i_APCI1500_Initialisation,
+		.di_write		= i_APCI1500_StartStopInputEvent,
+		.di_bits		= apci1500_di_insn_bits,
+		.do_config		= i_APCI1500_ConfigDigitalOutputErrorInterrupt,
+		.do_write		= i_APCI1500_WriteDigitalOutput,
+		.do_bits		= i_APCI1500_ConfigureInterrupt,
+		.timer_config		= i_APCI1500_ConfigCounterTimerWatchdog,
+		.timer_write		= i_APCI1500_StartStopTriggerTimerCounterWatchdog,
+		.timer_read		= i_APCI1500_ReadInterruptMask,
+		.timer_bits		= i_APCI1500_ReadCounterTimerWatchdog,
+	},
+};
+
+static struct comedi_driver apci1500_driver = {
+	.driver_name	= "addi_apci_1500",
+	.module		= THIS_MODULE,
+	.auto_attach	= addi_auto_attach,
+	.detach		= i_ADDI_Detach,
+	.num_names	= ARRAY_SIZE(apci1500_boardtypes),
+	.board_name	= &apci1500_boardtypes[0].pc_DriverName,
+	.offset		= sizeof(struct addi_board),
+};
+
+static int apci1500_pci_probe(struct pci_dev *dev,
+					const struct pci_device_id *ent)
+{
+	return comedi_pci_auto_config(dev, &apci1500_driver);
+}
+
+static void apci1500_pci_remove(struct pci_dev *dev)
+{
+	comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(apci1500_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA_OLD, 0x80fc) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, apci1500_pci_table);
+
+static struct pci_driver apci1500_pci_driver = {
+	.name		= "addi_apci_1500",
+	.id_table	= apci1500_pci_table,
+	.probe		= apci1500_pci_probe,
+	.remove		= apci1500_pci_remove,
+};
+module_comedi_pci_driver(apci1500_driver, apci1500_pci_driver);
+
 MODULE_AUTHOR("Comedi http://www.comedi.org");
 MODULE_DESCRIPTION("Comedi low-level driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c
index a12e2f4..8fef04b 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1516.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1516.c
@@ -1,9 +1,349 @@
-#define CONFIG_APCI_1516 1
+/*
+ * addi_apci_1516.c
+ * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
+ * Project manager: Eric Stolz
+ *
+ *	ADDI-DATA GmbH
+ *	Dieselstrasse 3
+ *	D-77833 Ottersweier
+ *	Tel: +19(0)7223/9493-0
+ *	Fax: +49(0)7223/9493-92
+ *	http://www.addi-data.com
+ *	info@addi-data.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * You should also find the complete GPL in the COPYING file accompanying
+ * this source code.
+ */
 
-#define ADDIDATA_DRIVER_NAME	"addi_apci_1516"
+#include "../comedidev.h"
+#include "comedi_fc.h"
 
-#include "addi-data/addi_common.c"
+/*
+ * PCI device ids supported by this driver
+ */
+#define PCI_DEVICE_ID_APCI1016		0x1000
+#define PCI_DEVICE_ID_APCI1516		0x1001
+#define PCI_DEVICE_ID_APCI2016		0x1002
 
+/*
+ * PCI bar 1 I/O Register map - Digital input/output
+ */
+#define APCI1516_DI_REG			0x00
+#define APCI1516_DO_REG			0x04
+
+/*
+ * PCI bar 2 I/O Register map - Watchdog (APCI-1516 and APCI-2016)
+ */
+#define APCI1516_WDOG_REG		0x00
+#define APCI1516_WDOG_RELOAD_REG	0x04
+#define APCI1516_WDOG_CTRL_REG		0x0c
+#define APCI1516_WDOG_CTRL_ENABLE	(1 << 0)
+#define APCI1516_WDOG_CTRL_SW_TRIG	(1 << 9)
+#define APCI1516_WDOG_STATUS_REG	0x10
+#define APCI1516_WDOG_STATUS_ENABLED	(1 << 0)
+#define APCI1516_WDOG_STATUS_SW_TRIG	(1 << 1)
+
+struct apci1516_boardinfo {
+	const char *name;
+	unsigned short device;
+	int di_nchan;
+	int do_nchan;
+	int has_wdog;
+};
+
+static const struct apci1516_boardinfo apci1516_boardtypes[] = {
+	{
+		.name		= "apci1016",
+		.device		= PCI_DEVICE_ID_APCI1016,
+		.di_nchan	= 16,
+	}, {
+		.name		= "apci1516",
+		.device		= PCI_DEVICE_ID_APCI1516,
+		.di_nchan	= 8,
+		.do_nchan	= 8,
+		.has_wdog	= 1,
+	}, {
+		.name		= "apci2016",
+		.device		= PCI_DEVICE_ID_APCI2016,
+		.do_nchan	= 16,
+		.has_wdog	= 1,
+	},
+};
+
+struct apci1516_private {
+	unsigned long wdog_iobase;
+	unsigned int ctrl;
+};
+
+static int apci1516_di_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
+{
+	data[1] = inw(dev->iobase + APCI1516_DI_REG);
+
+	return insn->n;
+}
+
+static int apci1516_do_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 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);
+
+		outw(s->state, dev->iobase + APCI1516_DO_REG);
+	}
+
+	data[1] = s->state;
+
+	return insn->n;
+}
+
+/*
+ * The watchdog subdevice is configured with two INSN_CONFIG instructions:
+ *
+ * Enable the watchdog and set the reload timeout:
+ *	data[0] = INSN_CONFIG_ARM
+ *	data[1] = timeout reload value
+ *
+ * Disable the watchdog:
+ *	data[0] = INSN_CONFIG_DISARM
+ */
+static int apci1516_wdog_insn_config(struct comedi_device *dev,
+				     struct comedi_subdevice *s,
+				     struct comedi_insn *insn,
+				     unsigned int *data)
+{
+	struct apci1516_private *devpriv = dev->private;
+	unsigned int reload;
+
+	switch (data[0]) {
+	case INSN_CONFIG_ARM:
+		devpriv->ctrl = APCI1516_WDOG_CTRL_ENABLE;
+		reload = data[1] & s->maxdata;
+		outw(reload, devpriv->wdog_iobase + APCI1516_WDOG_RELOAD_REG);
+
+		/* Time base is 20ms, let the user know the timeout */
+		dev_info(dev->class_dev, "watchdog enabled, timeout:%dms\n",
+			20 * reload + 20);
+		break;
+	case INSN_CONFIG_DISARM:
+		devpriv->ctrl = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	outw(devpriv->ctrl, devpriv->wdog_iobase + APCI1516_WDOG_CTRL_REG);
+
+	return insn->n;
+}
+
+static int apci1516_wdog_insn_write(struct comedi_device *dev,
+				    struct comedi_subdevice *s,
+				    struct comedi_insn *insn,
+				    unsigned int *data)
+{
+	struct apci1516_private *devpriv = dev->private;
+	int i;
+
+	if (devpriv->ctrl == 0) {
+		dev_warn(dev->class_dev, "watchdog is disabled\n");
+		return -EINVAL;
+	}
+
+	/* "ping" the watchdog */
+	for (i = 0; i < insn->n; i++) {
+		outw(devpriv->ctrl | APCI1516_WDOG_CTRL_SW_TRIG,
+			devpriv->wdog_iobase + APCI1516_WDOG_CTRL_REG);
+	}
+
+	return insn->n;
+}
+
+static int apci1516_wdog_insn_read(struct comedi_device *dev,
+				   struct comedi_subdevice *s,
+				   struct comedi_insn *insn,
+				   unsigned int *data)
+{
+	struct apci1516_private *devpriv = dev->private;
+	int i;
+
+	for (i = 0; i < insn->n; i++)
+		data[i] = inw(devpriv->wdog_iobase + APCI1516_WDOG_STATUS_REG);
+
+	return insn->n;
+}
+
+static int apci1516_reset(struct comedi_device *dev)
+{
+	const struct apci1516_boardinfo *this_board = comedi_board(dev);
+	struct apci1516_private *devpriv = dev->private;
+
+	if (!this_board->has_wdog)
+		return 0;
+
+	outw(0x0, dev->iobase + APCI1516_DO_REG);
+	outw(0x0, devpriv->wdog_iobase + APCI1516_WDOG_CTRL_REG);
+	outw(0x0, devpriv->wdog_iobase + APCI1516_WDOG_RELOAD_REG);
+
+	return 0;
+}
+
+static const void *apci1516_find_boardinfo(struct comedi_device *dev,
+					   struct pci_dev *pcidev)
+{
+	const struct apci1516_boardinfo *this_board;
+	int i;
+
+	for (i = 0; i < dev->driver->num_names; i++) {
+		this_board = &apci1516_boardtypes[i];
+		if (this_board->device == pcidev->device)
+			return this_board;
+	}
+	return NULL;
+}
+
+static int apci1516_auto_attach(struct comedi_device *dev,
+					  unsigned long context_unused)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	const struct apci1516_boardinfo *this_board;
+	struct apci1516_private *devpriv;
+	struct comedi_subdevice *s;
+	int ret;
+
+	this_board = apci1516_find_boardinfo(dev, pcidev);
+	if (!this_board)
+		return -ENODEV;
+	dev->board_ptr = this_board;
+	dev->board_name = this_board->name;
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
+	ret = comedi_pci_enable(pcidev, dev->board_name);
+	if (ret)
+		return ret;
+
+	dev->iobase = pci_resource_start(pcidev, 1);
+	devpriv->wdog_iobase = pci_resource_start(pcidev, 2);
+
+	ret = comedi_alloc_subdevices(dev, 3);
+	if (ret)
+		return ret;
+
+	/* Initialize the digital input subdevice */
+	s = &dev->subdevices[0];
+	if (this_board->di_nchan) {
+		s->type		= COMEDI_SUBD_DI;
+		s->subdev_flags	= SDF_READABLE;
+		s->n_chan	= this_board->di_nchan;
+		s->maxdata	= 1;
+		s->range_table	= &range_digital;
+		s->insn_bits	= apci1516_di_insn_bits;
+	} else {
+		s->type		= COMEDI_SUBD_UNUSED;
+	}
+
+	/* Initialize the digital output subdevice */
+	s = &dev->subdevices[1];
+	if (this_board->do_nchan) {
+		s->type		= COMEDI_SUBD_DO;
+		s->subdev_flags	= SDF_WRITEABLE;
+		s->n_chan	= this_board->do_nchan;
+		s->maxdata	= 1;
+		s->range_table	= &range_digital;
+		s->insn_bits	= apci1516_do_insn_bits;
+	} else {
+		s->type		= COMEDI_SUBD_UNUSED;
+	}
+
+	/* Initialize the watchdog subdevice */
+	s = &dev->subdevices[2];
+	if (this_board->has_wdog) {
+		s->type		= COMEDI_SUBD_TIMER;
+		s->subdev_flags	= SDF_WRITEABLE;
+		s->n_chan	= 1;
+		s->maxdata	= 0xff;
+		s->insn_write	= apci1516_wdog_insn_write;
+		s->insn_read	= apci1516_wdog_insn_read;
+		s->insn_config	= apci1516_wdog_insn_config;
+	} else {
+		s->type		= COMEDI_SUBD_UNUSED;
+	}
+
+	apci1516_reset(dev);
+	return 0;
+}
+
+static void apci1516_detach(struct comedi_device *dev)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+
+	if (dev->iobase) {
+		apci1516_reset(dev);
+		comedi_pci_disable(pcidev);
+	}
+}
+
+static struct comedi_driver apci1516_driver = {
+	.driver_name	= "addi_apci_1516",
+	.module		= THIS_MODULE,
+	.auto_attach	= apci1516_auto_attach,
+	.detach		= apci1516_detach,
+};
+
+static int apci1516_pci_probe(struct pci_dev *dev,
+					const struct pci_device_id *ent)
+{
+	return comedi_pci_auto_config(dev, &apci1516_driver);
+}
+
+static void apci1516_pci_remove(struct pci_dev *dev)
+{
+	comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(apci1516_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI1016) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI1516) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, PCI_DEVICE_ID_APCI2016) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, apci1516_pci_table);
+
+static struct pci_driver apci1516_pci_driver = {
+	.name		= "addi_apci_1516",
+	.id_table	= apci1516_pci_table,
+	.probe		= apci1516_pci_probe,
+	.remove		= apci1516_pci_remove,
+};
+module_comedi_pci_driver(apci1516_driver, apci1516_pci_driver);
+
+MODULE_DESCRIPTION("ADDI-DATA APCI-1016/1516/2016, 16 channel DIO boards");
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c
index 1b9d598..513e536 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1564.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1564.c
@@ -1,9 +1,74 @@
-#define CONFIG_APCI_1564 1
+#include "../comedidev.h"
+#include "comedi_fc.h"
+#include "amcc_s5933.h"
 
-#define ADDIDATA_DRIVER_NAME	"addi_apci_1564"
+#include "addi-data/addi_common.h"
 
+#include "addi-data/addi_eeprom.c"
+#include "addi-data/hwdrv_apci1564.c"
 #include "addi-data/addi_common.c"
 
+static const struct addi_board apci1564_boardtypes[] = {
+	{
+		.pc_DriverName		= "apci1564",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x1006,
+		.i_IorangeBase0		= 128,
+		.i_IorangeBase1		= APCI1564_ADDRESS_RANGE,
+		.i_PCIEeprom		= ADDIDATA_EEPROM,
+		.pc_EepromChip		= ADDIDATA_93C76,
+		.i_NbrDiChannel		= 32,
+		.i_NbrDoChannel		= 32,
+		.i_DoMaxdata		= 0xffffffff,
+		.i_Timer		= 1,
+		.interrupt		= v_APCI1564_Interrupt,
+		.reset			= i_APCI1564_Reset,
+		.di_config		= i_APCI1564_ConfigDigitalInput,
+		.di_bits		= apci1564_di_insn_bits,
+		.do_config		= i_APCI1564_ConfigDigitalOutput,
+		.do_bits		= apci1564_do_insn_bits,
+		.do_read		= i_APCI1564_ReadInterruptStatus,
+		.timer_config		= i_APCI1564_ConfigTimerCounterWatchdog,
+		.timer_write		= i_APCI1564_StartStopWriteTimerCounterWatchdog,
+		.timer_read		= i_APCI1564_ReadTimerCounterWatchdog,
+	},
+};
+
+static struct comedi_driver apci1564_driver = {
+	.driver_name	= "addi_apci_1564",
+	.module		= THIS_MODULE,
+	.auto_attach	= addi_auto_attach,
+	.detach		= i_ADDI_Detach,
+	.num_names	= ARRAY_SIZE(apci1564_boardtypes),
+	.board_name	= &apci1564_boardtypes[0].pc_DriverName,
+	.offset		= sizeof(struct addi_board),
+};
+
+static int apci1564_pci_probe(struct pci_dev *dev,
+					const struct pci_device_id *ent)
+{
+	return comedi_pci_auto_config(dev, &apci1564_driver);
+}
+
+static void apci1564_pci_remove(struct pci_dev *dev)
+{
+	comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(apci1564_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1006) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, apci1564_pci_table);
+
+static struct pci_driver apci1564_pci_driver = {
+	.name		= "addi_apci_1564",
+	.id_table	= apci1564_pci_table,
+	.probe		= apci1564_pci_probe,
+	.remove		= apci1564_pci_remove,
+};
+module_comedi_pci_driver(apci1564_driver, apci1564_pci_driver);
+
 MODULE_AUTHOR("Comedi http://www.comedi.org");
 MODULE_DESCRIPTION("Comedi low-level driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c
index d54218d..ab9a96a 100644
--- a/drivers/staging/comedi/drivers/addi_apci_16xx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c
@@ -1,9 +1,77 @@
-#define CONFIG_APCI_16XX 1
+#include "../comedidev.h"
+#include "comedi_fc.h"
+#include "amcc_s5933.h"
 
-#define ADDIDATA_DRIVER_NAME	"addi_apci_16xx"
+#include "addi-data/addi_common.h"
 
+#include "addi-data/addi_eeprom.c"
+#include "addi-data/hwdrv_apci16xx.c"
 #include "addi-data/addi_common.c"
 
+static const struct addi_board apci16xx_boardtypes[] = {
+	{
+		.pc_DriverName		= "apci1648",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x1009,
+		.i_IorangeBase0		= 128,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.i_NbrTTLChannel	= 48,
+		.reset			= i_APCI16XX_Reset,
+		.ttl_config		= i_APCI16XX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI16XX_InsnBitsReadTTLIO,
+		.ttl_read		= i_APCI16XX_InsnReadTTLIOAllPortValue,
+		.ttl_write		= i_APCI16XX_InsnBitsWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci1696",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x100A,
+		.i_IorangeBase0		= 128,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.i_NbrTTLChannel	= 96,
+		.reset			= i_APCI16XX_Reset,
+		.ttl_config		= i_APCI16XX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI16XX_InsnBitsReadTTLIO,
+		.ttl_read		= i_APCI16XX_InsnReadTTLIOAllPortValue,
+		.ttl_write		= i_APCI16XX_InsnBitsWriteTTLIO,
+	},
+};
+
+static struct comedi_driver apci16xx_driver = {
+	.driver_name	= "addi_apci_16xx",
+	.module		= THIS_MODULE,
+	.auto_attach	= addi_auto_attach,
+	.detach		= i_ADDI_Detach,
+	.num_names	= ARRAY_SIZE(apci16xx_boardtypes),
+	.board_name	= &apci16xx_boardtypes[0].pc_DriverName,
+	.offset		= sizeof(struct addi_board),
+};
+
+static int apci16xx_pci_probe(struct pci_dev *dev,
+					const struct pci_device_id *ent)
+{
+	return comedi_pci_auto_config(dev, &apci16xx_driver);
+}
+
+static void apci16xx_pci_remove(struct pci_dev *dev)
+{
+	comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(apci16xx_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1009) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x100a) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, apci16xx_pci_table);
+
+static struct pci_driver apci16xx_pci_driver = {
+	.name		= "addi_apci_16xx",
+	.id_table	= apci16xx_pci_table,
+	.probe		= apci16xx_pci_probe,
+	.remove		= apci16xx_pci_remove,
+};
+module_comedi_pci_driver(apci16xx_driver, apci16xx_pci_driver);
+
 MODULE_AUTHOR("Comedi http://www.comedi.org");
 MODULE_DESCRIPTION("Comedi low-level driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c
index df6ba8c..152e7ef 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1710.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1710.c
@@ -1,5 +1,152 @@
-#define CONFIG_APCI_1710 1
+#include <asm/i387.h>
 
-#define ADDIDATA_DRIVER_NAME	"addi_apci_1710"
+#include "../comedidev.h"
+#include "comedi_fc.h"
+#include "amcc_s5933.h"
 
-#include "addi-data/addi_common.c"
+#include "addi-data/addi_common.h"
+
+static void fpu_begin(void)
+{
+	kernel_fpu_begin();
+}
+
+static void fpu_end(void)
+{
+	kernel_fpu_end();
+}
+
+#include "addi-data/addi_eeprom.c"
+#include "addi-data/hwdrv_APCI1710.c"
+
+static const struct addi_board apci1710_boardtypes[] = {
+	{
+		.pc_DriverName		= "apci1710",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA_OLD,
+		.i_DeviceId		= APCI1710_BOARD_DEVICE_ID,
+		.interrupt		= v_APCI1710_Interrupt,
+	},
+};
+
+static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
+{
+	struct comedi_device *dev = d;
+	const struct addi_board *this_board = comedi_board(dev);
+
+	this_board->interrupt(irq, d);
+	return IRQ_RETVAL(1);
+}
+
+static const void *apci1710_find_boardinfo(struct comedi_device *dev,
+					   struct pci_dev *pcidev)
+{
+	const struct addi_board *this_board;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(apci1710_boardtypes); i++) {
+		this_board = &apci1710_boardtypes[i];
+		if (this_board->i_VendorId == pcidev->vendor &&
+		    this_board->i_DeviceId == pcidev->device)
+			return this_board;
+	}
+	return NULL;
+}
+
+static int apci1710_auto_attach(struct comedi_device *dev,
+					  unsigned long context_unused)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	const struct addi_board *this_board;
+	struct addi_private *devpriv;
+	struct comedi_subdevice *s;
+	int ret;
+
+	this_board = apci1710_find_boardinfo(dev, pcidev);
+	if (!this_board)
+		return -ENODEV;
+	dev->board_ptr = this_board;
+	dev->board_name = this_board->pc_DriverName;
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
+	ret = comedi_pci_enable(pcidev, dev->board_name);
+	if (ret)
+		return ret;
+
+	if (this_board->i_IorangeBase1)
+		dev->iobase = pci_resource_start(pcidev, 1);
+	else
+		dev->iobase = pci_resource_start(pcidev, 0);
+
+	devpriv->iobase = dev->iobase;
+	devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
+	devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2);
+	devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3);
+
+	if (pcidev->irq > 0) {
+		ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED,
+				  dev->board_name, dev);
+		if (ret == 0)
+			dev->irq = pcidev->irq;
+	}
+
+	i_ADDI_AttachPCI1710(dev);
+
+	devpriv->s_BoardInfos.ui_Address = pci_resource_start(pcidev, 2);
+
+	i_APCI1710_Reset(dev);
+	return 0;
+}
+
+static void apci1710_detach(struct comedi_device *dev)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+
+	if (dev->iobase)
+		i_APCI1710_Reset(dev);
+	if (dev->irq)
+		free_irq(dev->irq, dev);
+	if (pcidev) {
+		if (dev->iobase)
+			comedi_pci_disable(pcidev);
+	}
+}
+
+static struct comedi_driver apci1710_driver = {
+	.driver_name	= "addi_apci_1710",
+	.module		= THIS_MODULE,
+	.auto_attach	= apci1710_auto_attach,
+	.detach		= apci1710_detach,
+};
+
+static int apci1710_pci_probe(struct pci_dev *dev,
+					const struct pci_device_id *ent)
+{
+	return comedi_pci_auto_config(dev, &apci1710_driver);
+}
+
+static void apci1710_pci_remove(struct pci_dev *dev)
+{
+	comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(apci1710_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA_OLD, APCI1710_BOARD_DEVICE_ID) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, apci1710_pci_table);
+
+static struct pci_driver apci1710_pci_driver = {
+	.name		= "addi_apci_1710",
+	.id_table	= apci1710_pci_table,
+	.probe		= apci1710_pci_probe,
+	.remove		= apci1710_pci_remove,
+};
+module_comedi_pci_driver(apci1710_driver, apci1710_pci_driver);
+
+MODULE_AUTHOR("Comedi http://www.comedi.org");
+MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_2016.c b/drivers/staging/comedi/drivers/addi_apci_2016.c
deleted file mode 100644
index fa50c7b..0000000
--- a/drivers/staging/comedi/drivers/addi_apci_2016.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#define CONFIG_APCI_2016 1
-
-#define ADDIDATA_DRIVER_NAME	"addi_apci_2016"
-
-#include "addi-data/addi_common.c"
-
-MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c
index 073a8a5..459e900 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2032.c
@@ -1,9 +1,71 @@
-#define CONFIG_APCI_2032 1
+#include "../comedidev.h"
+#include "comedi_fc.h"
+#include "amcc_s5933.h"
 
-#define ADDIDATA_DRIVER_NAME	"addi_apci_2032"
+#include "addi-data/addi_common.h"
 
+#include "addi-data/addi_eeprom.c"
+#include "addi-data/hwdrv_apci2032.c"
 #include "addi-data/addi_common.c"
 
+static const struct addi_board apci2032_boardtypes[] = {
+	{
+		.pc_DriverName		= "apci2032",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x1004,
+		.i_IorangeBase0		= 4,
+		.i_IorangeBase1		= APCI2032_ADDRESS_RANGE,
+		.i_PCIEeprom		= ADDIDATA_EEPROM,
+		.pc_EepromChip		= ADDIDATA_93C76,
+		.i_NbrDoChannel		= 32,
+		.i_DoMaxdata		= 0xffffffff,
+		.i_Timer		= 1,
+		.interrupt		= v_APCI2032_Interrupt,
+		.reset			= i_APCI2032_Reset,
+		.do_config		= i_APCI2032_ConfigDigitalOutput,
+		.do_bits		= apci2032_do_insn_bits,
+		.do_read		= i_APCI2032_ReadInterruptStatus,
+		.timer_config		= i_APCI2032_ConfigWatchdog,
+		.timer_write		= i_APCI2032_StartStopWriteWatchdog,
+		.timer_read		= i_APCI2032_ReadWatchdog,
+	},
+};
+
+static struct comedi_driver apci2032_driver = {
+	.driver_name	= "addi_apci_2032",
+	.module		= THIS_MODULE,
+	.auto_attach	= addi_auto_attach,
+	.detach		= i_ADDI_Detach,
+	.num_names	= ARRAY_SIZE(apci2032_boardtypes),
+	.board_name	= &apci2032_boardtypes[0].pc_DriverName,
+	.offset		= sizeof(struct addi_board),
+};
+
+static int apci2032_pci_probe(struct pci_dev *dev,
+					const struct pci_device_id *ent)
+{
+	return comedi_pci_auto_config(dev, &apci2032_driver);
+}
+
+static void apci2032_pci_remove(struct pci_dev *dev)
+{
+	comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(apci2032_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1004) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, apci2032_pci_table);
+
+static struct pci_driver apci2032_pci_driver = {
+	.name		= "addi_apci_2032",
+	.id_table	= apci2032_pci_table,
+	.probe		= apci2032_pci_probe,
+	.remove		= apci2032_pci_remove,
+};
+module_comedi_pci_driver(apci2032_driver, apci2032_pci_driver);
+
 MODULE_AUTHOR("Comedi http://www.comedi.org");
 MODULE_DESCRIPTION("Comedi low-level driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c
index adfbb5d..7c2c5db 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2200.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2200.c
@@ -1,9 +1,69 @@
-#define CONFIG_APCI_2200 1
+#include "../comedidev.h"
+#include "comedi_fc.h"
+#include "amcc_s5933.h"
 
-#define ADDIDATA_DRIVER_NAME	"addi_apci_2200"
+#include "addi-data/addi_common.h"
 
+#include "addi-data/addi_eeprom.c"
+#include "addi-data/hwdrv_apci2200.c"
 #include "addi-data/addi_common.c"
 
+static const struct addi_board apci2200_boardtypes[] = {
+	{
+		.pc_DriverName		= "apci2200",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x1005,
+		.i_IorangeBase0		= 4,
+		.i_IorangeBase1		= APCI2200_ADDRESS_RANGE,
+		.i_PCIEeprom		= ADDIDATA_EEPROM,
+		.pc_EepromChip		= ADDIDATA_93C76,
+		.i_NbrDiChannel		= 8,
+		.i_NbrDoChannel		= 16,
+		.i_Timer		= 1,
+		.reset			= i_APCI2200_Reset,
+		.di_bits		= apci2200_di_insn_bits,
+		.do_bits		= apci2200_do_insn_bits,
+		.timer_config		= i_APCI2200_ConfigWatchdog,
+		.timer_write		= i_APCI2200_StartStopWriteWatchdog,
+		.timer_read		= i_APCI2200_ReadWatchdog,
+	},
+};
+
+static struct comedi_driver apci2200_driver = {
+	.driver_name	= "addi_apci_2200",
+	.module		= THIS_MODULE,
+	.auto_attach	= addi_auto_attach,
+	.detach		= i_ADDI_Detach,
+	.num_names	= ARRAY_SIZE(apci2200_boardtypes),
+	.board_name	= &apci2200_boardtypes[0].pc_DriverName,
+	.offset		= sizeof(struct addi_board),
+};
+
+static int apci2200_pci_probe(struct pci_dev *dev,
+					const struct pci_device_id *ent)
+{
+	return comedi_pci_auto_config(dev, &apci2200_driver);
+}
+
+static void apci2200_pci_remove(struct pci_dev *dev)
+{
+	comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(apci2200_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1005) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, apci2200_pci_table);
+
+static struct pci_driver apci2200_pci_driver = {
+	.name		= "addi_apci_2200",
+	.id_table	= apci2200_pci_table,
+	.probe		= apci2200_pci_probe,
+	.remove		= apci2200_pci_remove,
+};
+module_comedi_pci_driver(apci2200_driver, apci2200_pci_driver);
+
 MODULE_AUTHOR("Comedi http://www.comedi.org");
 MODULE_DESCRIPTION("Comedi low-level driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_3001.c b/drivers/staging/comedi/drivers/addi_apci_3001.c
deleted file mode 100644
index 00ac762..0000000
--- a/drivers/staging/comedi/drivers/addi_apci_3001.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#define CONFIG_APCI_3001 1
-
-#define ADDIDATA_DRIVER_NAME	"addi_apci_3001"
-
-#include "addi-data/addi_common.c"
-
-MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c
index c355158..fec2962 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3120.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3120.c
@@ -1,8 +1,275 @@
-#define CONFIG_APCI_3120 1
+#include "../comedidev.h"
+#include "comedi_fc.h"
+#include "amcc_s5933.h"
 
-#define ADDIDATA_DRIVER_NAME	"addi_apci_3120"
+#include "addi-data/addi_common.h"
 
-#include "addi-data/addi_common.c"
+#include "addi-data/hwdrv_apci3120.c"
+
+static const struct addi_board apci3120_boardtypes[] = {
+	{
+		.pc_DriverName		= "apci3120",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA_OLD,
+		.i_DeviceId		= 0x818D,
+		.i_NbrAiChannel		= 16,
+		.i_NbrAiChannelDiff	= 8,
+		.i_AiChannelList	= 16,
+		.i_NbrAoChannel		= 8,
+		.i_AiMaxdata		= 0xffff,
+		.i_AoMaxdata		= 0x3fff,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.i_DoMaxdata		= 0x0f,
+		.interrupt		= v_APCI3120_Interrupt,
+	}, {
+		.pc_DriverName		= "apci3001",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA_OLD,
+		.i_DeviceId		= 0x828D,
+		.i_NbrAiChannel		= 16,
+		.i_NbrAiChannelDiff	= 8,
+		.i_AiChannelList	= 16,
+		.i_AiMaxdata		= 0xfff,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.i_DoMaxdata		= 0x0f,
+		.interrupt		= v_APCI3120_Interrupt,
+	},
+};
+
+static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
+{
+	struct comedi_device *dev = d;
+	const struct addi_board *this_board = comedi_board(dev);
+
+	this_board->interrupt(irq, d);
+	return IRQ_RETVAL(1);
+}
+
+static const void *apci3120_find_boardinfo(struct comedi_device *dev,
+					   struct pci_dev *pcidev)
+{
+	const struct addi_board *this_board;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(apci3120_boardtypes); i++) {
+		this_board = &apci3120_boardtypes[i];
+		if (this_board->i_VendorId == pcidev->vendor &&
+		    this_board->i_DeviceId == pcidev->device)
+			return this_board;
+	}
+	return NULL;
+}
+
+static int apci3120_auto_attach(struct comedi_device *dev,
+					  unsigned long context_unused)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	const struct addi_board *this_board;
+	struct addi_private *devpriv;
+	struct comedi_subdevice *s;
+	int ret, pages, i;
+
+	this_board = apci3120_find_boardinfo(dev, pcidev);
+	if (!this_board)
+		return -ENODEV;
+	dev->board_ptr = this_board;
+	dev->board_name = this_board->pc_DriverName;
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
+	ret = comedi_pci_enable(pcidev, dev->board_name);
+	if (ret)
+		return ret;
+	pci_set_master(pcidev);
+
+	dev->iobase = pci_resource_start(pcidev, 1);
+	devpriv->iobase = dev->iobase;
+	devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
+	devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2);
+	devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3);
+
+	if (pcidev->irq > 0) {
+		ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED,
+				  dev->board_name, dev);
+		if (ret == 0)
+			dev->irq = pcidev->irq;
+	}
+
+	devpriv->us_UseDma = ADDI_ENABLE;
+
+	/* Allocate DMA buffers */
+	devpriv->b_DmaDoubleBuffer = 0;
+	for (i = 0; i < 2; i++) {
+		for (pages = 4; pages >= 0; pages--) {
+			devpriv->ul_DmaBufferVirtual[i] =
+				(void *) __get_free_pages(GFP_KERNEL, pages);
+
+			if (devpriv->ul_DmaBufferVirtual[i])
+				break;
+		}
+		if (devpriv->ul_DmaBufferVirtual[i]) {
+			devpriv->ui_DmaBufferPages[i] = pages;
+			devpriv->ui_DmaBufferSize[i] = PAGE_SIZE * pages;
+			devpriv->ui_DmaBufferSamples[i] =
+				devpriv->ui_DmaBufferSize[i] >> 1;
+			devpriv->ul_DmaBufferHw[i] =
+				virt_to_bus((void *)devpriv->
+				ul_DmaBufferVirtual[i]);
+		}
+	}
+	if (!devpriv->ul_DmaBufferVirtual[0])
+		devpriv->us_UseDma = ADDI_DISABLE;
+
+	if (devpriv->ul_DmaBufferVirtual[1])
+		devpriv->b_DmaDoubleBuffer = 1;
+
+	ret = comedi_alloc_subdevices(dev, 5);
+	if (ret)
+		return ret;
+
+	/*  Allocate and Initialise AI Subdevice Structures */
+	s = &dev->subdevices[0];
+	dev->read_subdev = s;
+	s->type = COMEDI_SUBD_AI;
+	s->subdev_flags =
+		SDF_READABLE | SDF_COMMON | SDF_GROUND
+		| SDF_DIFF;
+	if (this_board->i_NbrAiChannel) {
+		s->n_chan = this_board->i_NbrAiChannel;
+		devpriv->b_SingelDiff = 0;
+	} else {
+		s->n_chan = this_board->i_NbrAiChannelDiff;
+		devpriv->b_SingelDiff = 1;
+	}
+	s->maxdata = this_board->i_AiMaxdata;
+	s->len_chanlist = this_board->i_AiChannelList;
+	s->range_table = &range_apci3120_ai;
+
+	/* Set the initialisation flag */
+	devpriv->b_AiInitialisation = 1;
+
+	s->insn_config = i_APCI3120_InsnConfigAnalogInput;
+	s->insn_read = i_APCI3120_InsnReadAnalogInput;
+	s->do_cmdtest = i_APCI3120_CommandTestAnalogInput;
+	s->do_cmd = i_APCI3120_CommandAnalogInput;
+	s->cancel = i_APCI3120_StopCyclicAcquisition;
+
+	/*  Allocate and Initialise AO Subdevice Structures */
+	s = &dev->subdevices[1];
+	if (this_board->i_NbrAoChannel) {
+		s->type = COMEDI_SUBD_AO;
+		s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
+		s->n_chan = this_board->i_NbrAoChannel;
+		s->maxdata = this_board->i_AoMaxdata;
+		s->len_chanlist = this_board->i_NbrAoChannel;
+		s->range_table = &range_apci3120_ao;
+		s->insn_write = i_APCI3120_InsnWriteAnalogOutput;
+	} else {
+		s->type = COMEDI_SUBD_UNUSED;
+	}
+
+	/*  Allocate and Initialise DI Subdevice Structures */
+	s = &dev->subdevices[2];
+	s->type = COMEDI_SUBD_DI;
+	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
+	s->n_chan = this_board->i_NbrDiChannel;
+	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 */
+	s = &dev->subdevices[3];
+	s->type = COMEDI_SUBD_DO;
+	s->subdev_flags =
+		SDF_READABLE | SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
+	s->n_chan = this_board->i_NbrDoChannel;
+	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 */
+	s = &dev->subdevices[4];
+	s->type = COMEDI_SUBD_TIMER;
+	s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
+	s->n_chan = 1;
+	s->maxdata = 0;
+	s->len_chanlist = 1;
+	s->range_table = &range_digital;
+
+	s->insn_write = i_APCI3120_InsnWriteTimer;
+	s->insn_read = i_APCI3120_InsnReadTimer;
+	s->insn_config = i_APCI3120_InsnConfigTimer;
+
+	i_APCI3120_Reset(dev);
+	return 0;
+}
+
+static void apci3120_detach(struct comedi_device *dev)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct addi_private *devpriv = dev->private;
+
+	if (devpriv) {
+		if (dev->iobase)
+			i_APCI3120_Reset(dev);
+		if (dev->irq)
+			free_irq(dev->irq, dev);
+		if (devpriv->ul_DmaBufferVirtual[0]) {
+			free_pages((unsigned long)devpriv->
+				ul_DmaBufferVirtual[0],
+				devpriv->ui_DmaBufferPages[0]);
+		}
+		if (devpriv->ul_DmaBufferVirtual[1]) {
+			free_pages((unsigned long)devpriv->
+				ul_DmaBufferVirtual[1],
+				devpriv->ui_DmaBufferPages[1]);
+		}
+	}
+	if (pcidev) {
+		if (dev->iobase)
+			comedi_pci_disable(pcidev);
+	}
+}
+
+static struct comedi_driver apci3120_driver = {
+	.driver_name	= "addi_apci_3120",
+	.module		= THIS_MODULE,
+	.auto_attach	= apci3120_auto_attach,
+	.detach		= apci3120_detach,
+};
+
+static int apci3120_pci_probe(struct pci_dev *dev,
+					const struct pci_device_id *ent)
+{
+	return comedi_pci_auto_config(dev, &apci3120_driver);
+}
+
+static void apci3120_pci_remove(struct pci_dev *dev)
+{
+	comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(apci3120_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA_OLD, 0x818d) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA_OLD, 0x828d) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, apci3120_pci_table);
+
+static struct pci_driver apci3120_pci_driver = {
+	.name		= "addi_apci_3120",
+	.id_table	= apci3120_pci_table,
+	.probe		= apci3120_pci_probe,
+	.remove		= apci3120_pci_remove,
+};
+module_comedi_pci_driver(apci3120_driver, apci3120_pci_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
 MODULE_DESCRIPTION("Comedi low-level driver");
diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c
index 1593139..9085b77 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3200.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3200.c
@@ -1,5 +1,120 @@
-#define CONFIG_APCI_3200 1
+#include <asm/i387.h>
 
-#define ADDIDATA_DRIVER_NAME	"addi_apci_3200"
+#include "../comedidev.h"
+#include "comedi_fc.h"
+#include "amcc_s5933.h"
 
+#include "addi-data/addi_common.h"
+
+static void fpu_begin(void)
+{
+	kernel_fpu_begin();
+}
+
+static void fpu_end(void)
+{
+	kernel_fpu_end();
+}
+
+#include "addi-data/addi_eeprom.c"
+#include "addi-data/hwdrv_apci3200.c"
 #include "addi-data/addi_common.c"
+
+static const struct addi_board apci3200_boardtypes[] = {
+	{
+		.pc_DriverName		= "apci3200",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3000,
+		.i_IorangeBase0		= 128,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 4,
+		.i_IorangeBase3		= 4,
+		.i_PCIEeprom		= ADDIDATA_EEPROM,
+		.pc_EepromChip		= ADDIDATA_S5920,
+		.i_NbrAiChannel		= 16,
+		.i_NbrAiChannelDiff	= 8,
+		.i_AiChannelList	= 16,
+		.i_AiMaxdata		= 0x3ffff,
+		.pr_AiRangelist		= &range_apci3200_ai,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.ui_MinAcquisitiontimeNs = 10000,
+		.ui_MinDelaytimeNs	= 100000,
+		.interrupt		= v_APCI3200_Interrupt,
+		.reset			= i_APCI3200_Reset,
+		.ai_config		= i_APCI3200_ConfigAnalogInput,
+		.ai_read		= i_APCI3200_ReadAnalogInput,
+		.ai_write		= i_APCI3200_InsnWriteReleaseAnalogInput,
+		.ai_bits		= i_APCI3200_InsnBits_AnalogInput_Test,
+		.ai_cmdtest		= i_APCI3200_CommandTestAnalogInput,
+		.ai_cmd			= i_APCI3200_CommandAnalogInput,
+		.ai_cancel		= i_APCI3200_StopCyclicAcquisition,
+		.di_bits		= apci3200_di_insn_bits,
+		.do_bits		= apci3200_do_insn_bits,
+	}, {
+		.pc_DriverName		= "apci3300",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3007,
+		.i_IorangeBase0		= 128,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 4,
+		.i_IorangeBase3		= 4,
+		.i_PCIEeprom		= ADDIDATA_EEPROM,
+		.pc_EepromChip		= ADDIDATA_S5920,
+		.i_NbrAiChannelDiff	= 8,
+		.i_AiChannelList	= 8,
+		.i_AiMaxdata		= 0x3ffff,
+		.pr_AiRangelist		= &range_apci3300_ai,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.ui_MinAcquisitiontimeNs = 10000,
+		.ui_MinDelaytimeNs	= 100000,
+		.interrupt		= v_APCI3200_Interrupt,
+		.reset			= i_APCI3200_Reset,
+		.ai_config		= i_APCI3200_ConfigAnalogInput,
+		.ai_read		= i_APCI3200_ReadAnalogInput,
+		.ai_write		= i_APCI3200_InsnWriteReleaseAnalogInput,
+		.ai_bits		= i_APCI3200_InsnBits_AnalogInput_Test,
+		.ai_cmdtest		= i_APCI3200_CommandTestAnalogInput,
+		.ai_cmd			= i_APCI3200_CommandAnalogInput,
+		.ai_cancel		= i_APCI3200_StopCyclicAcquisition,
+		.di_bits		= apci3200_di_insn_bits,
+		.do_bits		= apci3200_do_insn_bits,
+	},
+};
+
+static DEFINE_PCI_DEVICE_TABLE(apci3200_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3000) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3007) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, apci3200_pci_table);
+
+static struct comedi_driver apci3200_driver = {
+	.driver_name	= "addi_apci_3200",
+	.module		= THIS_MODULE,
+	.auto_attach	= addi_auto_attach,
+	.detach		= i_ADDI_Detach,
+	.num_names	= ARRAY_SIZE(apci3200_boardtypes),
+	.board_name	= &apci3200_boardtypes[0].pc_DriverName,
+	.offset		= sizeof(struct addi_board),
+};
+
+static int apci3200_pci_probe(struct pci_dev *dev,
+					const struct pci_device_id *ent)
+{
+	return comedi_pci_auto_config(dev, &apci3200_driver);
+}
+
+static void apci3200_pci_remove(struct pci_dev *dev)
+{
+	comedi_pci_auto_unconfig(dev);
+}
+
+static struct pci_driver apci3200_pci_driver = {
+	.name		= "addi_apci_3200",
+	.id_table	= apci3200_pci_table,
+	.probe		= apci3200_pci_probe,
+	.remove		= apci3200_pci_remove,
+};
+module_comedi_pci_driver(apci3200_driver, apci3200_pci_driver);
diff --git a/drivers/staging/comedi/drivers/addi_apci_3300.c b/drivers/staging/comedi/drivers/addi_apci_3300.c
deleted file mode 100644
index 733c69a..0000000
--- a/drivers/staging/comedi/drivers/addi_apci_3300.c
+++ /dev/null
@@ -1,5 +0,0 @@
-#define CONFIG_APCI_3300 1
-
-#define ADDIDATA_DRIVER_NAME	"addi_apci_3300"
-
-#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c
index dd2c1d3..ed297de 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3501.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3501.c
@@ -1,9 +1,75 @@
-#define CONFIG_APCI_3501 1
+#include "../comedidev.h"
+#include "comedi_fc.h"
+#include "amcc_s5933.h"
 
-#define ADDIDATA_DRIVER_NAME	"addi_apci_3501"
+#include "addi-data/addi_common.h"
 
+#include "addi-data/addi_eeprom.c"
+#include "addi-data/hwdrv_apci3501.c"
 #include "addi-data/addi_common.c"
 
+static const struct addi_board apci3501_boardtypes[] = {
+	{
+		.pc_DriverName		= "apci3501",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3001,
+		.i_IorangeBase0		= 64,
+		.i_IorangeBase1		= APCI3501_ADDRESS_RANGE,
+		.i_PCIEeprom		= ADDIDATA_EEPROM,
+		.pc_EepromChip		= ADDIDATA_S5933,
+		.i_AoMaxdata		= 16383,
+		.pr_AoRangelist		= &range_apci3501_ao,
+		.i_NbrDiChannel		= 2,
+		.i_NbrDoChannel		= 2,
+		.i_DoMaxdata		= 0x3,
+		.i_Timer		= 1,
+		.interrupt		= v_APCI3501_Interrupt,
+		.reset			= i_APCI3501_Reset,
+		.ao_config		= i_APCI3501_ConfigAnalogOutput,
+		.ao_write		= i_APCI3501_WriteAnalogOutput,
+		.di_bits		= apci3501_di_insn_bits,
+		.do_bits		= apci3501_do_insn_bits,
+		.timer_config		= i_APCI3501_ConfigTimerCounterWatchdog,
+		.timer_write		= i_APCI3501_StartStopWriteTimerCounterWatchdog,
+		.timer_read		= i_APCI3501_ReadTimerCounterWatchdog,
+	},
+};
+
+static DEFINE_PCI_DEVICE_TABLE(apci3501_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3001) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, apci3501_pci_table);
+
+static struct comedi_driver apci3501_driver = {
+	.driver_name	= "addi_apci_3501",
+	.module		= THIS_MODULE,
+	.auto_attach	= addi_auto_attach,
+	.detach		= i_ADDI_Detach,
+	.num_names	= ARRAY_SIZE(apci3501_boardtypes),
+	.board_name	= &apci3501_boardtypes[0].pc_DriverName,
+	.offset		= sizeof(struct addi_board),
+};
+
+static int apci3501_pci_probe(struct pci_dev *dev,
+					const struct pci_device_id *ent)
+{
+	return comedi_pci_auto_config(dev, &apci3501_driver);
+}
+
+static void apci3501_pci_remove(struct pci_dev *dev)
+{
+	comedi_pci_auto_unconfig(dev);
+}
+
+static struct pci_driver apci3501_pci_driver = {
+	.name		= "addi_apci_3501",
+	.id_table	= apci3501_pci_table,
+	.probe		= apci3501_pci_probe,
+	.remove		= apci3501_pci_remove,
+};
+module_comedi_pci_driver(apci3501_driver, apci3501_pci_driver);
+
 MODULE_AUTHOR("Comedi http://www.comedi.org");
 MODULE_DESCRIPTION("Comedi low-level driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
index 03161c8..1562347 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
@@ -1,9 +1,799 @@
-#define CONFIG_APCI_3XXX 1
+#include "../comedidev.h"
+#include "comedi_fc.h"
+#include "amcc_s5933.h"
 
-#define ADDIDATA_DRIVER_NAME	"addi_apci_3xxx"
+#include "addi-data/addi_common.h"
 
+#include "addi-data/addi_eeprom.c"
+#include "addi-data/hwdrv_apci3xxx.c"
 #include "addi-data/addi_common.c"
 
+static const struct addi_board apci3xxx_boardtypes[] = {
+	{
+		.pc_DriverName		= "apci3000-16",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3010,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 16,
+		.i_NbrAiChannelDiff	= 8,
+		.i_AiChannelList	= 16,
+		.i_AiMaxdata		= 4095,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 10000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3000-8",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x300F,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 8,
+		.i_NbrAiChannelDiff	= 4,
+		.i_AiChannelList	= 8,
+		.i_AiMaxdata		= 4095,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 10000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3000-4",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x300E,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 4,
+		.i_NbrAiChannelDiff	= 2,
+		.i_AiChannelList	= 4,
+		.i_AiMaxdata		= 4095,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 10000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3006-16",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3013,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 16,
+		.i_NbrAiChannelDiff	= 8,
+		.i_AiChannelList	= 16,
+		.i_AiMaxdata		= 65535,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 10000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3006-8",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3014,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 8,
+		.i_NbrAiChannelDiff	= 4,
+		.i_AiChannelList	= 8,
+		.i_AiMaxdata		= 65535,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 10000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3006-4",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3015,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 4,
+		.i_NbrAiChannelDiff	= 2,
+		.i_AiChannelList	= 4,
+		.i_AiMaxdata		= 65535,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 10000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3010-16",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3016,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 16,
+		.i_NbrAiChannelDiff	= 8,
+		.i_AiChannelList	= 16,
+		.i_AiMaxdata		= 4095,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.i_DoMaxdata		= 1,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 5000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.di_bits		= apci3xxx_di_insn_bits,
+		.do_bits		= apci3xxx_do_insn_bits,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3010-8",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3017,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 8,
+		.i_NbrAiChannelDiff	= 4,
+		.i_AiChannelList	= 8,
+		.i_AiMaxdata		= 4095,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.i_DoMaxdata		= 1,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 5000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.di_bits		= apci3xxx_di_insn_bits,
+		.do_bits		= apci3xxx_do_insn_bits,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3010-4",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3018,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 4,
+		.i_NbrAiChannelDiff	= 2,
+		.i_AiChannelList	= 4,
+		.i_AiMaxdata		= 4095,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.i_DoMaxdata		= 1,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 5000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.di_bits		= apci3xxx_di_insn_bits,
+		.do_bits		= apci3xxx_do_insn_bits,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3016-16",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3019,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 16,
+		.i_NbrAiChannelDiff	= 8,
+		.i_AiChannelList	= 16,
+		.i_AiMaxdata		= 65535,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.i_DoMaxdata		= 1,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 5000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.di_bits		= apci3xxx_di_insn_bits,
+		.do_bits		= apci3xxx_do_insn_bits,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3016-8",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x301A,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 8,
+		.i_NbrAiChannelDiff	= 4,
+		.i_AiChannelList	= 8,
+		.i_AiMaxdata		= 65535,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.i_DoMaxdata		= 1,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 5000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.di_bits		= apci3xxx_di_insn_bits,
+		.do_bits		= apci3xxx_do_insn_bits,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3016-4",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x301B,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 4,
+		.i_NbrAiChannelDiff	= 2,
+		.i_AiChannelList	= 4,
+		.i_AiMaxdata		= 65535,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.i_DoMaxdata		= 1,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 5000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.di_bits		= apci3xxx_di_insn_bits,
+		.do_bits		= apci3xxx_do_insn_bits,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3100-16-4",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x301C,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 16,
+		.i_NbrAiChannelDiff	= 8,
+		.i_AiChannelList	= 16,
+		.i_NbrAoChannel		= 4,
+		.i_AiMaxdata		= 4095,
+		.i_AoMaxdata		= 4095,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.pr_AoRangelist		= &range_apci3XXX_ao,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 10000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3100-8-4",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x301D,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 8,
+		.i_NbrAiChannelDiff	= 4,
+		.i_AiChannelList	= 8,
+		.i_NbrAoChannel		= 4,
+		.i_AiMaxdata		= 4095,
+		.i_AoMaxdata		= 4095,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.pr_AoRangelist		= &range_apci3XXX_ao,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 10000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3106-16-4",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x301E,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 16,
+		.i_NbrAiChannelDiff	= 8,
+		.i_AiChannelList	= 16,
+		.i_NbrAoChannel		= 4,
+		.i_AiMaxdata		= 65535,
+		.i_AoMaxdata		= 4095,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.pr_AoRangelist		= &range_apci3XXX_ao,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 10000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3106-8-4",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x301F,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 8,
+		.i_NbrAiChannelDiff	= 4,
+		.i_AiChannelList	= 8,
+		.i_NbrAoChannel		= 4,
+		.i_AiMaxdata		= 65535,
+		.i_AoMaxdata		= 4095,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.pr_AoRangelist		= &range_apci3XXX_ao,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 10000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3110-16-4",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3020,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 16,
+		.i_NbrAiChannelDiff	= 8,
+		.i_AiChannelList	= 16,
+		.i_NbrAoChannel		= 4,
+		.i_AiMaxdata		= 4095,
+		.i_AoMaxdata		= 4095,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.pr_AoRangelist		= &range_apci3XXX_ao,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.i_DoMaxdata		= 1,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 5000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
+		.di_bits		= apci3xxx_di_insn_bits,
+		.do_bits		= apci3xxx_do_insn_bits,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3110-8-4",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3021,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 8,
+		.i_NbrAiChannelDiff	= 4,
+		.i_AiChannelList	= 8,
+		.i_NbrAoChannel		= 4,
+		.i_AiMaxdata		= 4095,
+		.i_AoMaxdata		= 4095,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.pr_AoRangelist		= &range_apci3XXX_ao,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.i_DoMaxdata		= 1,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 5000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
+		.di_bits		= apci3xxx_di_insn_bits,
+		.do_bits		= apci3xxx_do_insn_bits,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3116-16-4",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3022,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 16,
+		.i_NbrAiChannelDiff	= 8,
+		.i_AiChannelList	= 16,
+		.i_NbrAoChannel		= 4,
+		.i_AiMaxdata		= 65535,
+		.i_AoMaxdata		= 4095,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.pr_AoRangelist		= &range_apci3XXX_ao,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.i_DoMaxdata		= 1,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 5000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
+		.di_bits		= apci3xxx_di_insn_bits,
+		.do_bits		= apci3xxx_do_insn_bits,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3116-8-4",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3023,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannel		= 8,
+		.i_NbrAiChannelDiff	= 4,
+		.i_AiChannelList	= 8,
+		.i_NbrAoChannel		= 4,
+		.i_AiMaxdata		= 65535,
+		.i_AoMaxdata		= 4095,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.pr_AoRangelist		= &range_apci3XXX_ao,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.i_DoMaxdata		= 1,
+		.i_NbrTTLChannel	= 24,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 5000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
+		.di_bits		= apci3xxx_di_insn_bits,
+		.do_bits		= apci3xxx_do_insn_bits,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	}, {
+		.pc_DriverName		= "apci3003",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x300B,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannelDiff	= 4,
+		.i_AiChannelList	= 4,
+		.i_AiMaxdata		= 65535,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.i_DoMaxdata		= 1,
+		.b_AvailableConvertUnit	= 7,
+		.ui_MinAcquisitiontimeNs = 2500,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.di_bits		= apci3xxx_di_insn_bits,
+		.do_bits		= apci3xxx_do_insn_bits,
+	}, {
+		.pc_DriverName		= "apci3002-16",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3002,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannelDiff	= 16,
+		.i_AiChannelList	= 16,
+		.i_AiMaxdata		= 65535,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.i_DoMaxdata		= 1,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 5000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.di_bits		= apci3xxx_di_insn_bits,
+		.do_bits		= apci3xxx_do_insn_bits,
+	}, {
+		.pc_DriverName		= "apci3002-8",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3003,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannelDiff	= 8,
+		.i_AiChannelList	= 8,
+		.i_AiMaxdata		= 65535,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.i_DoMaxdata		= 1,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 5000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.di_bits		= apci3xxx_di_insn_bits,
+		.do_bits		= apci3xxx_do_insn_bits,
+	}, {
+		.pc_DriverName		= "apci3002-4",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3004,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAiChannelDiff	= 4,
+		.i_AiChannelList	= 4,
+		.i_AiMaxdata		= 65535,
+		.pr_AiRangelist		= &range_apci3XXX_ai,
+		.i_NbrDiChannel		= 4,
+		.i_NbrDoChannel		= 4,
+		.i_DoMaxdata		= 1,
+		.b_AvailableConvertUnit	= 6,
+		.ui_MinAcquisitiontimeNs = 5000,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ai_config		= i_APCI3XXX_InsnConfigAnalogInput,
+		.ai_read		= i_APCI3XXX_InsnReadAnalogInput,
+		.di_bits		= apci3xxx_di_insn_bits,
+		.do_bits		= apci3xxx_do_insn_bits,
+	}, {
+		.pc_DriverName		= "apci3500",
+		.i_VendorId		= PCI_VENDOR_ID_ADDIDATA,
+		.i_DeviceId		= 0x3024,
+		.i_IorangeBase0		= 256,
+		.i_IorangeBase1		= 256,
+		.i_IorangeBase2		= 256,
+		.i_IorangeBase3		= 256,
+		.i_PCIEeprom		= ADDIDATA_NO_EEPROM,
+		.pc_EepromChip		= ADDIDATA_9054,
+		.i_NbrAoChannel		= 4,
+		.i_AoMaxdata		= 4095,
+		.pr_AoRangelist		= &range_apci3XXX_ao,
+		.i_NbrTTLChannel	= 24,
+		.interrupt		= v_APCI3XXX_Interrupt,
+		.reset			= i_APCI3XXX_Reset,
+		.ao_write		= i_APCI3XXX_InsnWriteAnalogOutput,
+		.ttl_config		= i_APCI3XXX_InsnConfigInitTTLIO,
+		.ttl_bits		= i_APCI3XXX_InsnBitsTTLIO,
+		.ttl_read		= i_APCI3XXX_InsnReadTTLIO,
+		.ttl_write		= i_APCI3XXX_InsnWriteTTLIO,
+	},
+};
+
+static struct comedi_driver apci3xxx_driver = {
+	.driver_name	= "addi_apci_3xxx",
+	.module		= THIS_MODULE,
+	.auto_attach	= addi_auto_attach,
+	.detach		= i_ADDI_Detach,
+	.num_names	= ARRAY_SIZE(apci3xxx_boardtypes),
+	.board_name	= &apci3xxx_boardtypes[0].pc_DriverName,
+	.offset		= sizeof(struct addi_board),
+};
+
+static int apci3xxx_pci_probe(struct pci_dev *dev,
+					const struct pci_device_id *ent)
+{
+	return comedi_pci_auto_config(dev, &apci3xxx_driver);
+}
+
+static void apci3xxx_pci_remove(struct pci_dev *dev)
+{
+	comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(apci3xxx_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3010) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x300f) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x300e) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3013) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3014) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3015) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3016) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3017) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3018) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3019) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301a) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301b) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301c) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301d) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301e) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x301f) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3020) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3021) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3022) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3023) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x300B) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3002) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3003) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3004) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3024) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, apci3xxx_pci_table);
+
+static struct pci_driver apci3xxx_pci_driver = {
+	.name		= "addi_apci_3xxx",
+	.id_table	= apci3xxx_pci_table,
+	.probe		= apci3xxx_pci_probe,
+	.remove		= apci3xxx_pci_remove,
+};
+module_comedi_pci_driver(apci3xxx_driver, apci3xxx_pci_driver);
+
 MODULE_AUTHOR("Comedi http://www.comedi.org");
 MODULE_DESCRIPTION("Comedi low-level driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
index 3492ce1..9a56eed 100644
--- a/drivers/staging/comedi/drivers/adl_pci6208.c
+++ b/drivers/staging/comedi/drivers/adl_pci6208.c
@@ -174,27 +174,26 @@ static const void *pci6208_find_boardinfo(struct comedi_device *dev,
 	return NULL;
 }
 
-static int pci6208_attach_pci(struct comedi_device *dev,
-			      struct pci_dev *pcidev)
+static int pci6208_auto_attach(struct comedi_device *dev,
+					 unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	const struct pci6208_board *boardinfo;
 	struct pci6208_private *devpriv;
 	struct comedi_subdevice *s;
 	unsigned int val;
 	int ret;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
-
 	boardinfo = pci6208_find_boardinfo(dev, pcidev);
 	if (!boardinfo)
 		return -ENODEV;
 	dev->board_ptr = boardinfo;
 	dev->board_name = boardinfo->name;
 
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret < 0)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_pci_enable(pcidev, dev->board_name);
 	if (ret)
@@ -261,17 +260,17 @@ static void pci6208_detach(struct comedi_device *dev)
 static struct comedi_driver adl_pci6208_driver = {
 	.driver_name	= "adl_pci6208",
 	.module		= THIS_MODULE,
-	.attach_pci	= pci6208_attach_pci,
+	.auto_attach	= pci6208_auto_attach,
 	.detach		= pci6208_detach,
 };
 
-static int __devinit adl_pci6208_pci_probe(struct pci_dev *dev,
+static int adl_pci6208_pci_probe(struct pci_dev *dev,
 					   const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &adl_pci6208_driver);
 }
 
-static void __devexit adl_pci6208_pci_remove(struct pci_dev *dev)
+static void adl_pci6208_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -287,7 +286,7 @@ static struct pci_driver adl_pci6208_pci_driver = {
 	.name		= "adl_pci6208",
 	.id_table	= adl_pci6208_pci_table,
 	.probe		= adl_pci6208_pci_probe,
-	.remove		= __devexit_p(adl_pci6208_pci_remove),
+	.remove		= adl_pci6208_pci_remove,
 };
 module_comedi_pci_driver(adl_pci6208_driver, adl_pci6208_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c
index 599714e..772edc0 100644
--- a/drivers/staging/comedi/drivers/adl_pci7x3x.c
+++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c
@@ -168,17 +168,16 @@ static const void *adl_pci7x3x_find_boardinfo(struct comedi_device *dev,
 	return NULL;
 }
 
-static int adl_pci7x3x_attach_pci(struct comedi_device *dev,
-				  struct pci_dev *pcidev)
+static int adl_pci7x3x_auto_attach(struct comedi_device *dev,
+					     unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	const struct adl_pci7x3x_boardinfo *board;
 	struct comedi_subdevice *s;
 	int subdev;
 	int nchan;
 	int ret;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
-
 	board = adl_pci7x3x_find_boardinfo(dev, pcidev);
 	if (!board)
 		return -ENODEV;
@@ -293,17 +292,17 @@ static void adl_pci7x3x_detach(struct comedi_device *dev)
 static struct comedi_driver adl_pci7x3x_driver = {
 	.driver_name	= "adl_pci7x3x",
 	.module		= THIS_MODULE,
-	.attach_pci	= adl_pci7x3x_attach_pci,
+	.auto_attach	= adl_pci7x3x_auto_attach,
 	.detach		= adl_pci7x3x_detach,
 };
 
-static int __devinit adl_pci7x3x_pci_probe(struct pci_dev *dev,
+static int adl_pci7x3x_pci_probe(struct pci_dev *dev,
 					   const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &adl_pci7x3x_driver);
 }
 
-static void __devexit adl_pci7x3x_pci_remove(struct pci_dev *dev)
+static void adl_pci7x3x_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -323,7 +322,7 @@ static struct pci_driver adl_pci7x3x_pci_driver = {
 	.name		= "adl_pci7x3x",
 	.id_table	= adl_pci7x3x_pci_table,
 	.probe		= adl_pci7x3x_pci_probe,
-	.remove		= __devexit_p(adl_pci7x3x_pci_remove),
+	.remove		= adl_pci7x3x_pci_remove,
 };
 module_comedi_pci_driver(adl_pci7x3x_driver, adl_pci7x3x_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c
index 05e06e7..4dd9d70 100644
--- a/drivers/staging/comedi/drivers/adl_pci8164.c
+++ b/drivers/staging/comedi/drivers/adl_pci8164.c
@@ -89,9 +89,9 @@ static void adl_pci8164_insn_read(struct comedi_device *dev,
 	}
 
 	data[0] = inw(dev->iobase + axis_reg + offset);
-	printk(KERN_DEBUG "comedi: pci8164 %s read -> "
-						  "%04X:%04X on axis %s\n",
-				action, data[0], data[1], axisname);
+	dev_dbg(dev->class_dev,
+		"pci8164 %s read -> %04X:%04X on axis %s\n",
+		action, data[0], data[1], axisname);
 }
 
 static int adl_pci8164_insn_read_msts(struct comedi_device *dev,
@@ -170,9 +170,9 @@ static void adl_pci8164_insn_out(struct comedi_device *dev,
 
 	outw(data[0], dev->iobase + axis_reg + offset);
 
-	printk(KERN_DEBUG "comedi: pci8164 %s write -> "
-						"%04X:%04X on axis %s\n",
-				action, data[0], data[1], axisname);
+	dev_dbg(dev->class_dev,
+		"pci8164 %s write -> %04X:%04X on axis %s\n",
+		action, data[0], data[1], axisname);
 
 }
 
@@ -212,14 +212,13 @@ static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
 	return 2;
 }
 
-static int adl_pci8164_attach_pci(struct comedi_device *dev,
-				  struct pci_dev *pcidev)
+static int adl_pci8164_auto_attach(struct comedi_device *dev,
+					     unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct comedi_subdevice *s;
 	int ret;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
-
 	dev->board_name = dev->driver->driver_name;
 
 	ret = comedi_pci_enable(pcidev, dev->board_name);
@@ -289,17 +288,17 @@ static void adl_pci8164_detach(struct comedi_device *dev)
 static struct comedi_driver adl_pci8164_driver = {
 	.driver_name	= "adl_pci8164",
 	.module		= THIS_MODULE,
-	.attach_pci	= adl_pci8164_attach_pci,
+	.auto_attach	= adl_pci8164_auto_attach,
 	.detach		= adl_pci8164_detach,
 };
 
-static int __devinit adl_pci8164_pci_probe(struct pci_dev *dev,
+static int adl_pci8164_pci_probe(struct pci_dev *dev,
 					   const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &adl_pci8164_driver);
 }
 
-static void __devexit adl_pci8164_pci_remove(struct pci_dev *dev)
+static void adl_pci8164_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -314,7 +313,7 @@ static struct pci_driver adl_pci8164_pci_driver = {
 	.name		= "adl_pci8164",
 	.id_table	= adl_pci8164_pci_table,
 	.probe		= adl_pci8164_pci_probe,
-	.remove		= __devexit_p(adl_pci8164_pci_remove),
+	.remove		= adl_pci8164_pci_remove,
 };
 module_comedi_pci_driver(adl_pci8164_driver, adl_pci8164_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
index a87192a..a339b9d 100644
--- a/drivers/staging/comedi/drivers/adl_pci9111.c
+++ b/drivers/staging/comedi/drivers/adl_pci9111.c
@@ -366,52 +366,29 @@ static int pci9111_ai_do_cmd_test(struct comedi_device *dev,
 	if (error)
 		return 2;
 
-	/*  Step 3 : make sure arguments are trivialy compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if ((cmd->start_src == TRIG_NOW) && (cmd->start_arg != 0)) {
-		cmd->start_arg = 0;
-		error++;
-	}
+	error |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if ((cmd->convert_src == TRIG_TIMER) &&
-	    (cmd->convert_arg < PCI9111_AI_ACQUISITION_PERIOD_MIN_NS)) {
-		cmd->convert_arg = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS;
-		error++;
-	}
-	if ((cmd->convert_src == TRIG_EXT) && (cmd->convert_arg != 0)) {
-		cmd->convert_arg = 0;
-		error++;
-	}
+	if (cmd->convert_src == TRIG_TIMER)
+		error |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+					PCI9111_AI_ACQUISITION_PERIOD_MIN_NS);
+	else	/* TRIG_EXT */
+		error |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 
-	if ((cmd->scan_begin_src == TRIG_TIMER) &&
-	    (cmd->scan_begin_arg < PCI9111_AI_ACQUISITION_PERIOD_MIN_NS)) {
-		cmd->scan_begin_arg = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS;
-		error++;
-	}
-	if ((cmd->scan_begin_src == TRIG_FOLLOW)
-	    && (cmd->scan_begin_arg != 0)) {
-		cmd->scan_begin_arg = 0;
-		error++;
-	}
-	if ((cmd->scan_begin_src == TRIG_EXT) && (cmd->scan_begin_arg != 0)) {
-		cmd->scan_begin_arg = 0;
-		error++;
-	}
+	if (cmd->scan_begin_src == TRIG_TIMER)
+		error |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+					PCI9111_AI_ACQUISITION_PERIOD_MIN_NS);
+	else	/* TRIG_FOLLOW || TRIG_EXT */
+		error |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
-	if ((cmd->scan_end_src == TRIG_COUNT) &&
-	    (cmd->scan_end_arg != cmd->chanlist_len)) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		error++;
-	}
+	error |= cfc_check_trigger_arg_is(&cmd->scan_end_arg,
+					  cmd->chanlist_len);
 
-	if ((cmd->stop_src == TRIG_COUNT) && (cmd->stop_arg < 1)) {
-		cmd->stop_arg = 1;
-		error++;
-	}
-	if ((cmd->stop_src == TRIG_NONE) && (cmd->stop_arg != 0)) {
-		cmd->stop_arg = 0;
-		error++;
-	}
+	if (cmd->stop_src == TRIG_COUNT)
+		error |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+	else	/* TRIG_NONE */
+		error |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (error)
 		return 3;
@@ -879,20 +856,20 @@ static int pci9111_reset(struct comedi_device *dev)
 	return 0;
 }
 
-static int pci9111_attach_pci(struct comedi_device *dev,
-			      struct pci_dev *pcidev)
+static int pci9111_auto_attach(struct comedi_device *dev,
+					 unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct pci9111_private_data *dev_private;
 	struct comedi_subdevice *s;
 	int ret;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
 	dev->board_name = dev->driver->driver_name;
 
-	ret = alloc_private(dev, sizeof(*dev_private));
-	if (ret)
-		return ret;
-	dev_private = dev->private;
+	dev_private = kzalloc(sizeof(*dev_private), GFP_KERNEL);
+	if (!dev_private)
+		return -ENOMEM;
+	dev->private = dev_private;
 
 	ret = comedi_pci_enable(pcidev, dev->board_name);
 	if (ret)
@@ -976,17 +953,17 @@ static void pci9111_detach(struct comedi_device *dev)
 static struct comedi_driver adl_pci9111_driver = {
 	.driver_name	= "adl_pci9111",
 	.module		= THIS_MODULE,
-	.attach_pci	= pci9111_attach_pci,
+	.auto_attach	= pci9111_auto_attach,
 	.detach		= pci9111_detach,
 };
 
-static int __devinit pci9111_pci_probe(struct pci_dev *dev,
+static int pci9111_pci_probe(struct pci_dev *dev,
 				       const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &adl_pci9111_driver);
 }
 
-static void __devexit pci9111_pci_remove(struct pci_dev *dev)
+static void pci9111_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -1002,7 +979,7 @@ static struct pci_driver adl_pci9111_pci_driver = {
 	.name		= "adl_pci9111",
 	.id_table	= pci9111_pci_table,
 	.probe		= pci9111_pci_probe,
-	.remove		= __devexit_p(pci9111_pci_remove),
+	.remove		= pci9111_pci_remove,
 };
 module_comedi_pci_driver(adl_pci9111_driver, adl_pci9111_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index 06ff65c..b6dda80 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -62,6 +62,20 @@ Configuration options:
 	256|=ignore nFull - A/D FIFO Full status
 
 */
+
+/*
+ * FIXME
+ *
+ * All the supported boards have the same PCI vendor and device IDs, so
+ * auto-attachment of PCI devices will always find the first board type.
+ *
+ * Perhaps the boards have different subdevice IDs that we could use to
+ * distinguish them?
+ *
+ * Need some device attributes so the board type can be corrected after
+ * attachment if necessary, and possibly to set other options supported by
+ * manual attachment.
+ */
 #include "../comedidev.h"
 
 #include <linux/delay.h>
@@ -73,8 +87,6 @@ Configuration options:
 #include "8253.h"
 #include "comedi_fc.h"
 
-#define PCI_VENDOR_ID_AMCC	0x10e8
-
 /* paranoid checks are broken */
 #undef PCI9118_PARANOIDCHECK	/*
 				 * if defined, then is used code which control
@@ -210,8 +222,7 @@ static const struct comedi_lrange range_pci9118hg = { 8, {
 
 struct boardtype {
 	const char *name;		/* board name */
-	int vendor_id;			/* PCI vendor a device ID of card */
-	int device_id;
+	int device_id;			/* PCI device ID of card */
 	int iorange_amcc;		/* iorange for own S5933 region */
 	int iorange_9118;		/* pass thru card region size */
 	int n_aichan;			/* num of A/D chans */
@@ -235,6 +246,61 @@ struct boardtype {
 
 };
 
+static const struct boardtype boardtypes[] = {
+	{
+		.name		= "pci9118dg",
+		.device_id	= 0x80d9,
+		.iorange_amcc	= AMCC_OP_REG_SIZE,
+		.iorange_9118	= IORANGE_9118,
+		.n_aichan	= 16,
+		.n_aichand	= 8,
+		.mux_aichan	= 256,
+		.n_aichanlist	= PCI9118_CHANLEN,
+		.n_aochan	= 2,
+		.ai_maxdata	= 0x0fff,
+		.ao_maxdata	= 0x0fff,
+		.rangelist_ai	= &range_pci9118dg_hr,
+		.rangelist_ao	= &range_bipolar10,
+		.ai_ns_min	= 3000,
+		.ai_pacer_min	= 12,
+		.half_fifo_size	= 512,
+	}, {
+		.name		= "pci9118hg",
+		.device_id	= 0x80d9,
+		.iorange_amcc	= AMCC_OP_REG_SIZE,
+		.iorange_9118	= IORANGE_9118,
+		.n_aichan	= 16,
+		.n_aichand	= 8,
+		.mux_aichan	= 256,
+		.n_aichanlist	= PCI9118_CHANLEN,
+		.n_aochan	= 2,
+		.ai_maxdata	= 0x0fff,
+		.ao_maxdata	= 0x0fff,
+		.rangelist_ai	= &range_pci9118hg,
+		.rangelist_ao	= &range_bipolar10,
+		.ai_ns_min	= 3000,
+		.ai_pacer_min	= 12,
+		.half_fifo_size	= 512,
+	}, {
+		.name		= "pci9118hr",
+		.device_id	= 0x80d9,
+		.iorange_amcc	= AMCC_OP_REG_SIZE,
+		.iorange_9118	= IORANGE_9118,
+		.n_aichan	= 16,
+		.n_aichand	= 8,
+		.mux_aichan	= 256,
+		.n_aichanlist	= PCI9118_CHANLEN,
+		.n_aochan	= 2,
+		.ai_maxdata	= 0xffff,
+		.ao_maxdata	= 0x0fff,
+		.rangelist_ai	= &range_pci9118dg_hr,
+		.rangelist_ao	= &range_bipolar10,
+		.ai_ns_min	= 10000,
+		.ai_pacer_min	= 40,
+		.half_fifo_size	= 512,
+	},
+};
+
 struct pci9118_private {
 	unsigned long iobase_a;	/* base+size for AMCC chip */
 	unsigned int master;	/* master capable */
@@ -358,10 +424,8 @@ static int check_channel_list(struct comedi_device *dev,
 		return 0;
 	}
 	if ((frontadd + n_chan + backadd) > s->len_chanlist) {
-		printk
-		    ("comedi%d: range/channel list is too long for "
-						"actual configuration (%d>%d)!",
-		     dev->minor, n_chan, s->len_chanlist - frontadd - backadd);
+		comedi_error(dev,
+			    "range/channel list is too long for actual configuration!\n");
 		return 0;
 	}
 
@@ -892,11 +956,10 @@ static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
 	if (devpriv->ai16bits == 0) {
 		if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) {
 							/* data dropout! */
-			printk
-			    ("comedi: A/D  SAMPL - data dropout: "
-				"received channel %d, expected %d!\n",
-				sampl & 0x000f,
-				devpriv->chanlist[s->async->cur_chan]);
+			dev_info(dev->class_dev,
+				 "A/D  SAMPL - data dropout: received channel %d, expected %d!\n",
+				 sampl & 0x000f,
+				 devpriv->chanlist[s->async->cur_chan]);
 			s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
 			pci9118_ai_cancel(dev, s);
 			comedi_event(dev, s);
@@ -1153,19 +1216,13 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
 	if (cmd->start_src & (TRIG_NOW | TRIG_EXT))
-		if (cmd->start_arg != 0) {
-			cmd->start_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
 	if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT))
-		if (cmd->scan_begin_arg != 0) {
-			cmd->scan_begin_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
 	if ((cmd->scan_begin_src == TRIG_TIMER) &&
 	    (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) {
@@ -1175,64 +1232,40 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
 	}
 
 	if (cmd->scan_begin_src == TRIG_TIMER)
-		if (cmd->scan_begin_arg < this_board->ai_ns_min) {
-			cmd->scan_begin_arg = this_board->ai_ns_min;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						 this_board->ai_ns_min);
 
 	if (cmd->scan_begin_src == TRIG_EXT)
 		if (cmd->scan_begin_arg) {
 			cmd->scan_begin_arg = 0;
-			err++;
-			if (cmd->scan_end_arg > 65535) {
-				cmd->scan_end_arg = 65535;
-				err++;
-			}
+			err |= -EINVAL;
+			err |= cfc_check_trigger_arg_max(&cmd->scan_end_arg,
+							 65535);
 		}
 
 	if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW))
-		if (cmd->convert_arg < this_board->ai_ns_min) {
-			cmd->convert_arg = this_board->ai_ns_min;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+						 this_board->ai_ns_min);
 
 	if (cmd->convert_src == TRIG_EXT)
-		if (cmd->convert_arg) {
-			cmd->convert_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (!cmd->stop_arg) {
-			cmd->stop_arg = 1;
-			err++;
-		}
-	} else {		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	if (cmd->stop_src == TRIG_COUNT)
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+	else	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
-	if (!cmd->chanlist_len) {
-		cmd->chanlist_len = 1;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
+	err |= cfc_check_trigger_arg_max(&cmd->chanlist_len,
+					 this_board->n_aichanlist);
 
-	if (cmd->chanlist_len > this_board->n_aichanlist) {
-		cmd->chanlist_len = this_board->n_aichanlist;
-		err++;
-	}
-
-	if (cmd->scan_end_arg < cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_min(&cmd->scan_end_arg,
+					 cmd->chanlist_len);
 
 	if ((cmd->scan_end_arg % cmd->chanlist_len)) {
 		cmd->scan_end_arg =
 		    cmd->chanlist_len * (cmd->scan_end_arg / cmd->chanlist_len);
-		err++;
+		err |= -EINVAL;
 	}
 
 	if (err)
@@ -1318,21 +1351,18 @@ static int Compute_and_setup_dma(struct comedi_device *dev)
 		if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) {
 			/* uff, too short DMA buffer, disable EOS support! */
 			devpriv->ai_flags &= (~TRIG_WAKE_EOS);
-			printk
-			    ("comedi%d: WAR: DMA0 buf too short, can't "
-					"support TRIG_WAKE_EOS (%d<%d)\n",
-			     dev->minor, dmalen0,
-			     devpriv->ai_n_realscanlen << 1);
+			dev_info(dev->class_dev,
+				 "WAR: DMA0 buf too short, can't support TRIG_WAKE_EOS (%d<%d)\n",
+				  dmalen0, devpriv->ai_n_realscanlen << 1);
 		} else {
 			/* short first DMA buffer to one scan */
 			dmalen0 = devpriv->ai_n_realscanlen << 1;
 			if (devpriv->useeoshandle)
 				dmalen0 += 2;
 			if (dmalen0 < 4) {
-				printk
-					("comedi%d: ERR: DMA0 buf len bug? "
-								"(%d<4)\n",
-					dev->minor, dmalen0);
+				dev_info(dev->class_dev,
+					 "ERR: DMA0 buf len bug? (%d<4)\n",
+					 dmalen0);
 				dmalen0 = 4;
 			}
 		}
@@ -1341,21 +1371,18 @@ static int Compute_and_setup_dma(struct comedi_device *dev)
 		if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) {
 			/* uff, too short DMA buffer, disable EOS support! */
 			devpriv->ai_flags &= (~TRIG_WAKE_EOS);
-			printk
-			    ("comedi%d: WAR: DMA1 buf too short, "
-					"can't support TRIG_WAKE_EOS (%d<%d)\n",
-			     dev->minor, dmalen1,
-			     devpriv->ai_n_realscanlen << 1);
+			dev_info(dev->class_dev,
+				 "WAR: DMA1 buf too short, can't support TRIG_WAKE_EOS (%d<%d)\n",
+				 dmalen1, devpriv->ai_n_realscanlen << 1);
 		} else {
 			/* short second DMA buffer to one scan */
 			dmalen1 = devpriv->ai_n_realscanlen << 1;
 			if (devpriv->useeoshandle)
 				dmalen1 -= 2;
 			if (dmalen1 < 4) {
-				printk
-					("comedi%d: ERR: DMA1 buf len bug? "
-								"(%d<4)\n",
-					dev->minor, dmalen1);
+				dev_info(dev->class_dev,
+					 "ERR: DMA1 buf len bug? (%d<4)\n",
+					 dmalen1);
 				dmalen1 = 4;
 			}
 		}
@@ -1865,6 +1892,20 @@ static int pci9118_reset(struct comedi_device *dev)
 	return 0;
 }
 
+/*
+ * FIXME - this is pretty ineffective because all the supported board types
+ * have the same device ID!
+ */
+static const struct boardtype *pci9118_find_boardinfo(struct pci_dev *pcidev)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(boardtypes); i++)
+		if (pcidev->device == boardtypes[i].device_id)
+			return &boardtypes[i];
+	return NULL;
+}
+
 static struct pci_dev *pci9118_find_pci(struct comedi_device *dev,
 					struct comedi_devconfig *it)
 {
@@ -1884,85 +1925,63 @@ static struct pci_dev *pci9118_find_pci(struct comedi_device *dev,
 			    PCI_SLOT(pcidev->devfn) != slot)
 				continue;
 		}
-		/*
-		 * Look for device that isn't in use.
-		 * Enable PCI device and request regions.
-		 */
-		if (comedi_pci_enable(pcidev, "adl_pci9118"))
-			continue;
-		printk(KERN_ERR ", b:s:f=%d:%d:%d, io=0x%4lx, 0x%4lx",
-			pcidev->bus->number,
-			PCI_SLOT(pcidev->devfn),
-			PCI_FUNC(pcidev->devfn),
-			(unsigned long)pci_resource_start(pcidev, 2),
-			(unsigned long)pci_resource_start(pcidev, 0));
 		return pcidev;
 	}
-	printk(KERN_ERR
-		"comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
-		dev->minor, bus, slot);
+	dev_err(dev->class_dev,
+		"no supported board found! (req. bus/slot : %d/%d)\n",
+		bus, slot);
 	return NULL;
 }
 
-static int pci9118_attach(struct comedi_device *dev,
-			  struct comedi_devconfig *it)
+static void pci9118_report_attach(struct comedi_device *dev, unsigned int irq)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct pci9118_private *devpriv = dev->private;
+	char irqbuf[30];
+	char muxbuf[30];
+
+	if (irq)
+		snprintf(irqbuf, sizeof(irqbuf), "irq %u%s", irq,
+			 (dev->irq ? "" : " UNAVAILABLE"));
+	else
+		snprintf(irqbuf, sizeof(irqbuf), "irq DISABLED");
+	if (devpriv->usemux)
+		snprintf(muxbuf, sizeof(muxbuf), "ext mux %u chans",
+			 devpriv->usemux);
+	else
+		snprintf(muxbuf, sizeof(muxbuf), "no ext mux");
+	dev_info(dev->class_dev, "%s (pci %s, %s, %sbus master, %s) attached\n",
+		 dev->board_name, pci_name(pcidev), irqbuf,
+		 (devpriv->master ? "" : "no "), muxbuf);
+}
+
+static int pci9118_common_attach(struct comedi_device *dev, int disable_irq,
+				 int master, int ext_mux, int softsshdelay,
+				 int hw_err_mask)
 {
 	const struct boardtype *this_board = comedi_board(dev);
-	struct pci9118_private *devpriv;
-	struct pci_dev *pcidev;
+	struct pci9118_private *devpriv = dev->private;
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct comedi_subdevice *s;
 	int ret, pages, i;
-	unsigned short master;
 	unsigned int irq;
 	u16 u16w;
 
-	printk("comedi%d: adl_pci9118: board=%s", dev->minor, this_board->name);
-
-	if (it->options[3] & 1)
-		master = 0;	/* user don't want use bus master */
-	else
-		master = 1;
-
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret < 0) {
-		printk(" - Allocation failed!\n");
-		return -ENOMEM;
+	dev->board_name = this_board->name;
+	ret = comedi_pci_enable(pcidev, dev->board_name);
+	if (ret) {
+		dev_err(dev->class_dev,
+			"cannot enable PCI device %s\n", pci_name(pcidev));
+		return ret;
 	}
-	devpriv = dev->private;
-
-	pcidev = pci9118_find_pci(dev, it);
-	if (!pcidev)
-		return -EIO;
-	comedi_set_hw_dev(dev, &pcidev->dev);
-
 	if (master)
 		pci_set_master(pcidev);
 
-	irq = pcidev->irq;
 	devpriv->iobase_a = pci_resource_start(pcidev, 0);
 	dev->iobase = pci_resource_start(pcidev, 2);
 
-	dev->board_name = this_board->name;
-
 	pci9118_reset(dev);
 
-	if (it->options[3] & 2)
-		irq = 0;	/* user don't want use IRQ */
-	if (irq > 0) {
-		if (request_irq(irq, interrupt_pci9118, IRQF_SHARED,
-				"ADLink PCI-9118", dev)) {
-			printk(", unable to allocate IRQ %d, DISABLING IT",
-			       irq);
-			irq = 0;	/* Can't use IRQ */
-		} else {
-			printk(", irq=%u", irq);
-		}
-	} else {
-		printk(", IRQ disabled");
-	}
-
-	dev->irq = irq;
-
 	if (master) {		/* alloc DMA buffers */
 		devpriv->dma_doublebuf = 0;
 		for (i = 0; i < 2; i++) {
@@ -1984,47 +2003,37 @@ static int pci9118_attach(struct comedi_device *dev,
 			}
 		}
 		if (!devpriv->dmabuf_virt[0]) {
-			printk(", Can't allocate DMA buffer, DMA disabled!");
+			dev_warn(dev->class_dev,
+				 "Can't allocate DMA buffer, DMA disabled!\n");
 			master = 0;
 		}
-
 		if (devpriv->dmabuf_virt[1])
 			devpriv->dma_doublebuf = 1;
-
 	}
-
 	devpriv->master = master;
-	if (devpriv->master)
-		printk(", bus master");
-	else
-		printk(", no bus master");
-
-	devpriv->usemux = 0;
-	if (it->options[2] > 0) {
-		devpriv->usemux = it->options[2];
-		if (devpriv->usemux > 256)
-			devpriv->usemux = 256;	/* max 256 channels! */
-		if (it->options[4] > 0)
-			if (devpriv->usemux > 128) {
-				devpriv->usemux = 128;
-					/* max 128 channels with softare S&H! */
-			}
-		printk(", ext. mux %d channels", devpriv->usemux);
+
+	if (ext_mux > 0) {
+		if (ext_mux > 256)
+			ext_mux = 256;	/* max 256 channels! */
+		if (softsshdelay > 0)
+			if (ext_mux > 128)
+				ext_mux = 128;
+		devpriv->usemux = ext_mux;
+	} else {
+		devpriv->usemux = 0;
 	}
 
-	devpriv->softsshdelay = it->options[4];
-	if (devpriv->softsshdelay < 0) {
-					/* select sample&hold signal polarity */
-		devpriv->softsshdelay = -devpriv->softsshdelay;
+	if (softsshdelay < 0) {
+		/* select sample&hold signal polarity */
+		devpriv->softsshdelay = -softsshdelay;
 		devpriv->softsshsample = 0x80;
 		devpriv->softsshhold = 0x00;
 	} else {
+		devpriv->softsshdelay = softsshdelay;
 		devpriv->softsshsample = 0x00;
 		devpriv->softsshhold = 0x80;
 	}
 
-	printk(".\n");
-
 	pci_read_config_word(pcidev, PCI_COMMAND, &u16w);
 	pci_write_config_word(pcidev, PCI_COMMAND, u16w | 64);
 				/* Enable parity check for parity error */
@@ -2047,12 +2056,7 @@ static int pci9118_attach(struct comedi_device *dev,
 	s->range_table = this_board->rangelist_ai;
 	s->cancel = pci9118_ai_cancel;
 	s->insn_read = pci9118_insn_read_ai;
-	if (dev->irq) {
-		s->subdev_flags |= SDF_CMD_READ;
-		s->do_cmdtest = pci9118_ai_cmdtest;
-		s->do_cmd = pci9118_ai_cmd;
-		s->munge = pci9118_ai_munge;
-	}
+	s->munge = pci9118_ai_munge;
 
 	s = &dev->subdevices[1];
 	s->type = COMEDI_SUBD_AO;
@@ -2088,8 +2092,8 @@ static int pci9118_attach(struct comedi_device *dev,
 	devpriv->i8254_osc_base = 250;	/* 250ns=4MHz */
 	devpriv->ai_maskharderr = 0x10a;
 					/* default measure crash condition */
-	if (it->options[5])		/* disable some requested */
-		devpriv->ai_maskharderr &= ~it->options[5];
+	if (hw_err_mask)		/* disable some requested */
+		devpriv->ai_maskharderr &= ~hw_err_mask;
 
 	switch (this_board->ai_maxdata) {
 	case 0xffff:
@@ -2099,9 +2103,86 @@ static int pci9118_attach(struct comedi_device *dev,
 		devpriv->ai16bits = 0;
 		break;
 	}
+
+	if (disable_irq)
+		irq = 0;
+	else
+		irq = pcidev->irq;
+	if (irq > 0) {
+		if (request_irq(irq, interrupt_pci9118, IRQF_SHARED,
+				dev->board_name, dev)) {
+			dev_warn(dev->class_dev,
+				 "unable to allocate IRQ %u, DISABLING IT\n",
+				 irq);
+		} else {
+			dev->irq = irq;
+			/* Enable AI commands */
+			s = &dev->subdevices[0];
+			s->subdev_flags |= SDF_CMD_READ;
+			s->do_cmdtest = pci9118_ai_cmdtest;
+			s->do_cmd = pci9118_ai_cmd;
+		}
+	}
+
+	pci9118_report_attach(dev, irq);
 	return 0;
 }
 
+static int pci9118_attach(struct comedi_device *dev,
+			  struct comedi_devconfig *it)
+{
+	struct pci9118_private *devpriv;
+	struct pci_dev *pcidev;
+	int ext_mux, disable_irq, master, softsshdelay, hw_err_mask;
+
+	ext_mux = it->options[2];
+	master = ((it->options[3] & 1) == 0);
+	disable_irq = ((it->options[3] & 2) != 0);
+	softsshdelay = it->options[4];
+	hw_err_mask = it->options[5];
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
+	pcidev = pci9118_find_pci(dev, it);
+	if (!pcidev)
+		return -EIO;
+	comedi_set_hw_dev(dev, &pcidev->dev);
+
+	return pci9118_common_attach(dev, disable_irq, master, ext_mux,
+				     softsshdelay, hw_err_mask);
+}
+
+static int pci9118_auto_attach(struct comedi_device *dev,
+					 unsigned long context_unused)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct pci9118_private *devpriv;
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
+	dev->board_ptr = pci9118_find_boardinfo(pcidev);
+	if (dev->board_ptr == NULL) {
+		dev_err(dev->class_dev,
+			"adl_pci9118: cannot determine board type for pci %s\n",
+			pci_name(pcidev));
+		return -EINVAL;
+	}
+	/*
+	 * Need to 'get' the PCI device to match the 'put' in pci9118_detach().
+	 * (The 'put' also matches the implicit 'get' by pci9118_find_pci().)
+	 */
+	pci_dev_get(pcidev);
+	/* Don't disable irq, use bus master, no external mux,
+	 * no sample-hold delay, no error mask. */
+	return pci9118_common_attach(dev, 0, 1, 0, 0, 0);
+}
+
 static void pci9118_detach(struct comedi_device *dev)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
@@ -2127,81 +2208,24 @@ static void pci9118_detach(struct comedi_device *dev)
 	}
 }
 
-static const struct boardtype boardtypes[] = {
-	{
-		.name		= "pci9118dg",
-		.vendor_id	= PCI_VENDOR_ID_AMCC,
-		.device_id	= 0x80d9,
-		.iorange_amcc	= AMCC_OP_REG_SIZE,
-		.iorange_9118	= IORANGE_9118,
-		.n_aichan	= 16,
-		.n_aichand	= 8,
-		.mux_aichan	= 256,
-		.n_aichanlist	= PCI9118_CHANLEN,
-		.n_aochan	= 2,
-		.ai_maxdata	= 0x0fff,
-		.ao_maxdata	= 0x0fff,
-		.rangelist_ai	= &range_pci9118dg_hr,
-		.rangelist_ao	= &range_bipolar10,
-		.ai_ns_min	= 3000,
-		.ai_pacer_min	= 12,
-		.half_fifo_size	= 512,
-	}, {
-		.name		= "pci9118hg",
-		.vendor_id	= PCI_VENDOR_ID_AMCC,
-		.device_id	= 0x80d9,
-		.iorange_amcc	= AMCC_OP_REG_SIZE,
-		.iorange_9118	= IORANGE_9118,
-		.n_aichan	= 16,
-		.n_aichand	= 8,
-		.mux_aichan	= 256,
-		.n_aichanlist	= PCI9118_CHANLEN,
-		.n_aochan	= 2,
-		.ai_maxdata	= 0x0fff,
-		.ao_maxdata	= 0x0fff,
-		.rangelist_ai	= &range_pci9118hg,
-		.rangelist_ao	= &range_bipolar10,
-		.ai_ns_min	= 3000,
-		.ai_pacer_min	= 12,
-		.half_fifo_size	= 512,
-	}, {
-		.name		= "pci9118hr",
-		.vendor_id	= PCI_VENDOR_ID_AMCC,
-		.device_id	= 0x80d9,
-		.iorange_amcc	= AMCC_OP_REG_SIZE,
-		.iorange_9118	= IORANGE_9118,
-		.n_aichan	= 16,
-		.n_aichand	= 8,
-		.mux_aichan	= 256,
-		.n_aichanlist	= PCI9118_CHANLEN,
-		.n_aochan	= 2,
-		.ai_maxdata	= 0xffff,
-		.ao_maxdata	= 0x0fff,
-		.rangelist_ai	= &range_pci9118dg_hr,
-		.rangelist_ao	= &range_bipolar10,
-		.ai_ns_min	= 10000,
-		.ai_pacer_min	= 40,
-		.half_fifo_size	= 512,
-	},
-};
-
 static struct comedi_driver adl_pci9118_driver = {
 	.driver_name	= "adl_pci9118",
 	.module		= THIS_MODULE,
 	.attach		= pci9118_attach,
+	.auto_attach	= pci9118_auto_attach,
 	.detach		= pci9118_detach,
 	.num_names	= ARRAY_SIZE(boardtypes),
 	.board_name	= &boardtypes[0].name,
 	.offset		= sizeof(struct boardtype),
 };
 
-static int __devinit adl_pci9118_pci_probe(struct pci_dev *dev,
+static int adl_pci9118_pci_probe(struct pci_dev *dev,
 					   const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &adl_pci9118_driver);
 }
 
-static void __devexit adl_pci9118_pci_remove(struct pci_dev *dev)
+static void adl_pci9118_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -2216,7 +2240,7 @@ static struct pci_driver adl_pci9118_pci_driver = {
 	.name		= "adl_pci9118",
 	.id_table	= adl_pci9118_pci_table,
 	.probe		= adl_pci9118_pci_probe,
-	.remove		= __devexit_p(adl_pci9118_pci_remove),
+	.remove		= adl_pci9118_pci_remove,
 };
 module_comedi_pci_driver(adl_pci9118_driver, adl_pci9118_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
index 3a2aa56..f7950df 100644
--- a/drivers/staging/comedi/drivers/adq12b.c
+++ b/drivers/staging/comedi/drivers/adq12b.c
@@ -116,15 +116,6 @@ static const struct comedi_lrange range_adq12b_ai_unipolar = { 4, {
 								   }
 };
 
-struct adq12b_board {
-	const char *name;
-	int ai_se_chans;
-	int ai_diff_chans;
-	int ai_bits;
-	int di_chans;
-	int do_chans;
-};
-
 struct adq12b_private {
 	int unipolar;		/* option 2 of comedi_config (1 is iobase) */
 	int differential;	/* option 3 of comedi_config */
@@ -220,13 +211,14 @@ static int adq12b_do_insn_bits(struct comedi_device *dev,
 
 static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
-	const struct adq12b_board *board = comedi_board(dev);
 	struct adq12b_private *devpriv;
 	struct comedi_subdevice *s;
 	unsigned long iobase;
 	int unipolar, differential;
 	int ret;
 
+	dev->board_name = dev->driver->driver_name;
+
 	iobase = it->options[0];
 	unipolar = it->options[1];
 	differential = it->options[2];
@@ -251,12 +243,10 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	}
 	dev->iobase = iobase;
 
-	dev->board_name = board->name;
-
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	devpriv->unipolar = unipolar;
 	devpriv->differential = differential;
@@ -277,10 +267,10 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	s->type = COMEDI_SUBD_AI;
 	if (differential) {
 		s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
-		s->n_chan = board->ai_diff_chans;
+		s->n_chan = 8;
 	} else {
 		s->subdev_flags = SDF_READABLE | SDF_GROUND;
-		s->n_chan = board->ai_se_chans;
+		s->n_chan = 16;
 	}
 
 	if (unipolar)
@@ -288,7 +278,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	else
 		s->range_table = &range_adq12b_ai_bipolar;
 
-	s->maxdata = (1 << board->ai_bits) - 1;
+	s->maxdata = 0xfff;
 
 	s->len_chanlist = 4;	/* This is the maximum chanlist length that
 				   the board can handle */
@@ -298,7 +288,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	/* digital input subdevice */
 	s->type = COMEDI_SUBD_DI;
 	s->subdev_flags = SDF_READABLE;
-	s->n_chan = board->di_chans;
+	s->n_chan = 5;
 	s->maxdata = 1;
 	s->range_table = &range_digital;
 	s->insn_bits = adq12b_di_insn_bits;
@@ -307,7 +297,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	/* digital output subdevice */
 	s->type = COMEDI_SUBD_DO;
 	s->subdev_flags = SDF_WRITABLE;
-	s->n_chan = board->do_chans;
+	s->n_chan = 8;
 	s->maxdata = 1;
 	s->range_table = &range_digital;
 	s->insn_bits = adq12b_do_insn_bits;
@@ -323,25 +313,11 @@ static void adq12b_detach(struct comedi_device *dev)
 		release_region(dev->iobase, ADQ12B_SIZE);
 }
 
-static const struct adq12b_board adq12b_boards[] = {
-	{
-		.name		= "adq12b",
-		.ai_se_chans	= 16,
-		.ai_diff_chans	= 8,
-		.ai_bits	= 12,
-		.di_chans	= 5,
-		.do_chans	= 8,
-	},
-};
-
 static struct comedi_driver adq12b_driver = {
 	.driver_name	= "adq12b",
 	.module		= THIS_MODULE,
 	.attach		= adq12b_attach,
 	.detach		= adq12b_detach,
-	.board_name	= &adq12b_boards[0].name,
-	.offset		= sizeof(struct adq12b_board),
-	.num_names	= ARRAY_SIZE(adq12b_boards),
 };
 module_comedi_driver(adq12b_driver);
 
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index def37bc..a6fd8c2 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -53,8 +53,6 @@ Configuration options:
 				 * correct channel number on every 12 bit
 				 * sample */
 
-#define PCI_VENDOR_ID_ADVANTECH		0x13fe
-
 /* hardware types of the cards */
 #define TYPE_PCI171X	0
 #define TYPE_PCI1713	2
@@ -1068,45 +1066,23 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
-	if (cmd->scan_begin_arg != 0) {
-		cmd->scan_begin_arg = 0;
-		err++;
-	}
+	if (cmd->convert_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+						 this_board->ai_ns_min);
+	else	/* TRIG_FOLLOW */
+		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < this_board->ai_ns_min) {
-			cmd->convert_arg = this_board->ai_ns_min;
-			err++;
-		}
-	} else {		/* TRIG_FOLLOW */
-		if (cmd->convert_arg != 0) {
-			cmd->convert_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (!cmd->stop_arg) {
-			cmd->stop_arg = 1;
-			err++;
-		}
-	} else {		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	if (cmd->stop_src == TRIG_COUNT)
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+	else	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -1257,26 +1233,25 @@ static const void *pci1710_find_boardinfo(struct comedi_device *dev,
 	return NULL;
 }
 
-static int pci1710_attach_pci(struct comedi_device *dev,
-			      struct pci_dev *pcidev)
+static int pci1710_auto_attach(struct comedi_device *dev,
+					 unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	const struct boardtype *this_board;
 	struct pci1710_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret, subdev, n_subdevices;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
-
 	this_board = pci1710_find_boardinfo(dev, pcidev);
 	if (!this_board)
 		return -ENODEV;
 	dev->board_ptr = this_board;
 	dev->board_name = this_board->name;
 
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret < 0)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_pci_enable(pcidev, dev->board_name);
 	if (ret)
@@ -1417,17 +1392,17 @@ static void pci1710_detach(struct comedi_device *dev)
 static struct comedi_driver adv_pci1710_driver = {
 	.driver_name	= "adv_pci1710",
 	.module		= THIS_MODULE,
-	.attach_pci	= pci1710_attach_pci,
+	.auto_attach	= pci1710_auto_attach,
 	.detach		= pci1710_detach,
 };
 
-static int __devinit adv_pci1710_pci_probe(struct pci_dev *dev,
+static int adv_pci1710_pci_probe(struct pci_dev *dev,
 					   const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &adv_pci1710_driver);
 }
 
-static void __devexit adv_pci1710_pci_remove(struct pci_dev *dev)
+static void adv_pci1710_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -1446,7 +1421,7 @@ static struct pci_driver adv_pci1710_pci_driver = {
 	.name		= "adv_pci1710",
 	.id_table	= adv_pci1710_pci_table,
 	.probe		= adv_pci1710_pci_probe,
-	.remove		= __devexit_p(adv_pci1710_pci_remove),
+	.remove		= adv_pci1710_pci_remove,
 };
 module_comedi_pci_driver(adv_pci1710_driver, adv_pci1710_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
index df4efc0..5af7314 100644
--- a/drivers/staging/comedi/drivers/adv_pci1723.c
+++ b/drivers/staging/comedi/drivers/adv_pci1723.c
@@ -50,8 +50,6 @@ TODO:
 
 #include "../comedidev.h"
 
-#define PCI_VENDOR_ID_ADVANTECH		0x13fe	/* Advantech PCI vendor ID */
-
 /* all the registers for the pci1723 board */
 #define PCI1723_DA(N)   ((N)<<1)	/* W: D/A register N (0 to 7) */
 
@@ -234,20 +232,20 @@ static int pci1723_dio_insn_bits(struct comedi_device *dev,
 	return insn->n;
 }
 
-static int pci1723_attach_pci(struct comedi_device *dev,
-			      struct pci_dev *pcidev)
+static int pci1723_auto_attach(struct comedi_device *dev,
+					 unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct pci1723_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
 	dev->board_name = dev->driver->driver_name;
 
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret < 0)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_pci_enable(pcidev, dev->board_name);
 	if (ret)
@@ -319,17 +317,17 @@ static void pci1723_detach(struct comedi_device *dev)
 static struct comedi_driver adv_pci1723_driver = {
 	.driver_name	= "adv_pci1723",
 	.module		= THIS_MODULE,
-	.attach_pci	= pci1723_attach_pci,
+	.auto_attach	= pci1723_auto_attach,
 	.detach		= pci1723_detach,
 };
 
-static int __devinit adv_pci1723_pci_probe(struct pci_dev *dev,
+static int adv_pci1723_pci_probe(struct pci_dev *dev,
 					   const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &adv_pci1723_driver);
 }
 
-static void __devexit adv_pci1723_pci_remove(struct pci_dev *dev)
+static void adv_pci1723_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -344,7 +342,7 @@ static struct pci_driver adv_pci1723_pci_driver = {
 	.name		= "adv_pci1723",
 	.id_table	= adv_pci1723_pci_table,
 	.probe		= adv_pci1723_pci_probe,
-	.remove		= __devexit_p(adv_pci1723_pci_remove),
+	.remove		= adv_pci1723_pci_remove,
 };
 module_comedi_pci_driver(adv_pci1723_driver, adv_pci1723_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index a3c2241..05a663e 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -36,8 +36,6 @@ Configuration options:
 #include "8255.h"
 #include "8253.h"
 
-#define PCI_VENDOR_ID_ADVANTECH		0x13fe
-
 /* hardware types of the cards */
 enum hw_cards_id {
 	TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1735, TYPE_PCI1736,
@@ -1092,26 +1090,25 @@ static const void *pci_dio_find_boardinfo(struct comedi_device *dev,
 	return NULL;
 }
 
-static int pci_dio_attach_pci(struct comedi_device *dev,
-			      struct pci_dev *pcidev)
+static int pci_dio_auto_attach(struct comedi_device *dev,
+					 unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	const struct dio_boardtype *this_board;
 	struct pci_dio_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret, subdev, i, j;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
-
 	this_board = pci_dio_find_boardinfo(dev, pcidev);
 	if (!this_board)
 		return -ENODEV;
 	dev->board_ptr = this_board;
 	dev->board_name = this_board->name;
 
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret < 0)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_pci_enable(pcidev, dev->board_name);
 	if (ret)
@@ -1199,17 +1196,17 @@ static void pci_dio_detach(struct comedi_device *dev)
 static struct comedi_driver adv_pci_dio_driver = {
 	.driver_name	= "adv_pci_dio",
 	.module		= THIS_MODULE,
-	.attach_pci	= pci_dio_attach_pci,
+	.auto_attach	= pci_dio_auto_attach,
 	.detach		= pci_dio_detach,
 };
 
-static int __devinit adv_pci_dio_pci_probe(struct pci_dev *dev,
+static int adv_pci_dio_pci_probe(struct pci_dev *dev,
 					   const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &adv_pci_dio_driver);
 }
 
-static void __devexit adv_pci_dio_pci_remove(struct pci_dev *dev)
+static void adv_pci_dio_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -1237,7 +1234,7 @@ static struct pci_driver adv_pci_dio_pci_driver = {
 	.name		= "adv_pci_dio",
 	.id_table	= adv_pci_dio_pci_table,
 	.probe		= adv_pci_dio_pci_probe,
-	.remove		= __devexit_p(adv_pci_dio_pci_remove),
+	.remove		= adv_pci_dio_pci_remove,
 };
 module_comedi_pci_driver(adv_pci_dio_driver, adv_pci_dio_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c
index 8acf60d..601f03d 100644
--- a/drivers/staging/comedi/drivers/aio_aio12_8.c
+++ b/drivers/staging/comedi/drivers/aio_aio12_8.c
@@ -212,10 +212,10 @@ static int aio_aio12_8_attach(struct comedi_device *dev,
 	}
 	dev->iobase = iobase;
 
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_alloc_subdevices(dev, 4);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
index b2cb8b0..64c1ae5 100644
--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
+++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
@@ -44,19 +44,6 @@ Configuration Options:
 #define AIO_IIRO_16_RELAY_8_15	0x04
 #define AIO_IIRO_16_INPUT_8_15	0x05
 
-struct aio_iiro_16_board {
-	const char *name;
-	int do_;
-	int di;
-};
-
-static const struct aio_iiro_16_board aio_iiro_16_boards[] = {
-	{
-	 .name = "aio_iiro_16",
-	 .di = 16,
-	 .do_ = 16},
-};
-
 static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev,
 					   struct comedi_subdevice *s,
 					   struct comedi_insn *insn,
@@ -90,14 +77,13 @@ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev,
 static int aio_iiro_16_attach(struct comedi_device *dev,
 			      struct comedi_devconfig *it)
 {
-	const struct aio_iiro_16_board *board = comedi_board(dev);
 	int iobase;
 	struct comedi_subdevice *s;
 	int ret;
 
 	printk(KERN_INFO "comedi%d: aio_iiro_16: ", dev->minor);
 
-	dev->board_name = board->name;
+	dev->board_name = dev->driver->driver_name;
 
 	iobase = it->options[0];
 
@@ -144,9 +130,6 @@ static struct comedi_driver aio_iiro_16_driver = {
 	.module		= THIS_MODULE,
 	.attach		= aio_iiro_16_attach,
 	.detach		= aio_iiro_16_detach,
-	.board_name	= &aio_iiro_16_boards[0].name,
-	.offset		= sizeof(struct aio_iiro_16_board),
-	.num_names	= ARRAY_SIZE(aio_iiro_16_boards),
 };
 module_comedi_driver(aio_iiro_16_driver);
 
diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
index 29eb52d..5f309ba 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200.c
@@ -25,185 +25,238 @@
 
 */
 /*
-Driver: amplc_dio200
-Description: Amplicon 200 Series Digital I/O
-Author: Ian Abbott <abbotti@mev.co.uk>
-Devices: [Amplicon] PC212E (pc212e), PC214E (pc214e), PC215E (pc215e),
-  PCI215 (pci215 or amplc_dio200), PC218E (pc218e), PC272E (pc272e),
-  PCI272 (pci272 or amplc_dio200)
-Updated: Wed, 22 Oct 2008 13:36:02 +0100
-Status: works
-
-Configuration options - PC212E, PC214E, PC215E, PC218E, PC272E:
-  [0] - I/O port base address
-  [1] - IRQ (optional, but commands won't work without it)
-
-Configuration options - PCI215, PCI272:
-  [0] - PCI bus of device (optional)
-  [1] - PCI slot of device (optional)
-  If bus/slot is not specified, the first available PCI device will
-  be used.
-
-Passing a zero for an option is the same as leaving it unspecified.
-
-SUBDEVICES
-
-		    PC218E         PC212E      PC215E/PCI215
-		 -------------  -------------  -------------
-  Subdevices           7              6              5
-   0                 CTR-X1         PPI-X          PPI-X
-   1                 CTR-X2         CTR-Y1         PPI-Y
-   2                 CTR-Y1         CTR-Y2         CTR-Z1
-   3                 CTR-Y2         CTR-Z1         CTR-Z2
-   4                 CTR-Z1         CTR-Z2       INTERRUPT
-   5                 CTR-Z2       INTERRUPT
-   6               INTERRUPT
-
-		    PC214E      PC272E/PCI272
-		 -------------  -------------
-  Subdevices           4              4
-   0                 PPI-X          PPI-X
-   1                 PPI-Y          PPI-Y
-   2                 CTR-Z1*        PPI-Z
-   3               INTERRUPT*     INTERRUPT
-
-Each PPI is a 8255 chip providing 24 DIO channels.  The DIO channels
-are configurable as inputs or outputs in four groups:
-
-  Port A  - channels  0 to  7
-  Port B  - channels  8 to 15
-  Port CL - channels 16 to 19
-  Port CH - channels 20 to 23
-
-Only mode 0 of the 8255 chips is supported.
-
-Each CTR is a 8254 chip providing 3 16-bit counter channels.  Each
-channel is configured individually with INSN_CONFIG instructions.  The
-specific type of configuration instruction is specified in data[0].
-Some configuration instructions expect an additional parameter in
-data[1]; others return a value in data[1].  The following configuration
-instructions are supported:
-
-  INSN_CONFIG_SET_COUNTER_MODE.  Sets the counter channel's mode and
-    BCD/binary setting specified in data[1].
-
-  INSN_CONFIG_8254_READ_STATUS.  Reads the status register value for the
-    counter channel into data[1].
-
-  INSN_CONFIG_SET_CLOCK_SRC.  Sets the counter channel's clock source as
-    specified in data[1] (this is a hardware-specific value).  Not
-    supported on PC214E.  For the other boards, valid clock sources are
-    0 to 7 as follows:
-
-      0.  CLK n, the counter channel's dedicated CLK input from the SK1
-	connector.  (N.B. for other values, the counter channel's CLKn
-	pin on the SK1 connector is an output!)
-      1.  Internal 10 MHz clock.
-      2.  Internal 1 MHz clock.
-      3.  Internal 100 kHz clock.
-      4.  Internal 10 kHz clock.
-      5.  Internal 1 kHz clock.
-      6.  OUT n-1, the output of counter channel n-1 (see note 1 below).
-      7.  Ext Clock, the counter chip's dedicated Ext Clock input from
-	the SK1 connector.  This pin is shared by all three counter
-	channels on the chip.
-
-  INSN_CONFIG_GET_CLOCK_SRC.  Returns the counter channel's current
-    clock source in data[1].  For internal clock sources, data[2] is set
-    to the period in ns.
-
-  INSN_CONFIG_SET_GATE_SRC.  Sets the counter channel's gate source as
-    specified in data[2] (this is a hardware-specific value).  Not
-    supported on PC214E.  For the other boards, valid gate sources are 0
-    to 7 as follows:
-
-      0.  VCC (internal +5V d.c.), i.e. gate permanently enabled.
-      1.  GND (internal 0V d.c.), i.e. gate permanently disabled.
-      2.  GAT n, the counter channel's dedicated GAT input from the SK1
-	connector.  (N.B. for other values, the counter channel's GATn
-	pin on the SK1 connector is an output!)
-      3.  /OUT n-2, the inverted output of counter channel n-2 (see note
-	2 below).
-      4.  Reserved.
-      5.  Reserved.
-      6.  Reserved.
-      7.  Reserved.
-
-  INSN_CONFIG_GET_GATE_SRC.  Returns the counter channel's current gate
-    source in data[2].
-
-Clock and gate interconnection notes:
-
-  1.  Clock source OUT n-1 is the output of the preceding channel on the
-  same counter subdevice if n > 0, or the output of channel 2 on the
-  preceding counter subdevice (see note 3) if n = 0.
-
-  2.  Gate source /OUT n-2 is the inverted output of channel 0 on the
-  same counter subdevice if n = 2, or the inverted output of channel n+1
-  on the preceding counter subdevice (see note 3) if n < 2.
-
-  3.  The counter subdevices are connected in a ring, so the highest
-  counter subdevice precedes the lowest.
-
-The 'INTERRUPT' subdevice pretends to be a digital input subdevice.  The
-digital inputs come from the interrupt status register.  The number of
-channels matches the number of interrupt sources.  The PC214E does not
-have an interrupt status register; see notes on 'INTERRUPT SOURCES'
-below.
-
-INTERRUPT SOURCES
-
-		    PC218E         PC212E      PC215E/PCI215
-		 -------------  -------------  -------------
-  Sources              6              6              6
-   0              CTR-X1-OUT      PPI-X-C0       PPI-X-C0
-   1              CTR-X2-OUT      PPI-X-C3       PPI-X-C3
-   2              CTR-Y1-OUT     CTR-Y1-OUT      PPI-Y-C0
-   3              CTR-Y2-OUT     CTR-Y2-OUT      PPI-Y-C3
-   4              CTR-Z1-OUT     CTR-Z1-OUT     CTR-Z1-OUT
-   5              CTR-Z2-OUT     CTR-Z2-OUT     CTR-Z2-OUT
-
-		    PC214E      PC272E/PCI272
-		 -------------  -------------
-  Sources              1              6
-   0               JUMPER-J5      PPI-X-C0
-   1                              PPI-X-C3
-   2                              PPI-Y-C0
-   3                              PPI-Y-C3
-   4                              PPI-Z-C0
-   5                              PPI-Z-C3
-
-When an interrupt source is enabled in the interrupt source enable
-register, a rising edge on the source signal latches the corresponding
-bit to 1 in the interrupt status register.
-
-When the interrupt status register value as a whole (actually, just the
-6 least significant bits) goes from zero to non-zero, the board will
-generate an interrupt.  For level-triggered hardware interrupts (PCI
-card), the interrupt will remain asserted until the interrupt status
-register is cleared to zero.  For edge-triggered hardware interrupts
-(ISA card), no further interrupts will occur until the interrupt status
-register is cleared to zero.  To clear a bit to zero in the interrupt
-status register, the corresponding interrupt source must be disabled
-in the interrupt source enable register (there is no separate interrupt
-clear register).
-
-The PC214E does not have an interrupt source enable register or an
-interrupt status register; its 'INTERRUPT' subdevice has a single
-channel and its interrupt source is selected by the position of jumper
-J5.
-
-COMMANDS
-
-The driver supports a read streaming acquisition command on the
-'INTERRUPT' subdevice.  The channel list selects the interrupt sources
-to be enabled.  All channels will be sampled together (convert_src ==
-TRIG_NOW).  The scan begins a short time after the hardware interrupt
-occurs, subject to interrupt latencies (scan_begin_src == TRIG_EXT,
-scan_begin_arg == 0).  The value read from the interrupt status register
-is packed into a short value, one bit per requested channel, in the
-order they appear in the channel list.
-*/
+ * Driver: amplc_dio200
+ * Description: Amplicon 200 Series Digital I/O
+ * Author: Ian Abbott <abbotti@mev.co.uk>
+ * Devices: [Amplicon] PC212E (pc212e), PC214E (pc214e), PC215E (pc215e),
+ *   PCI215 (pci215), PCIe215 (pcie215), PC218E (pc218e), PCIe236 (pcie236),
+ *   PC272E (pc272e), PCI272 (pci272), PCIe296 (pcie296)
+ * Updated: Wed, 24 Oct 2012 16:22:34 +0100
+ * Status: works
+ *
+ * Configuration options - PC212E, PC214E, PC215E, PC218E, PC272E:
+ *   [0] - I/O port base address
+ *   [1] - IRQ (optional, but commands won't work without it)
+ *
+ * Manual configuration of PCI(e) cards is not supported; they are configured
+ * automatically.
+ *
+ * Passing a zero for an option is the same as leaving it unspecified.
+ *
+ * SUBDEVICES
+ *
+ *                     PC212E         PC214E      PC215E/PCI215
+ *                  -------------  -------------  -------------
+ *   Subdevices           6              4              5
+ *    0                 PPI-X          PPI-X          PPI-X
+ *    1                 CTR-Y1         PPI-Y          PPI-Y
+ *    2                 CTR-Y2         CTR-Z1*        CTR-Z1
+ *    3                 CTR-Z1       INTERRUPT*       CTR-Z2
+ *    4                 CTR-Z2                      INTERRUPT
+ *    5               INTERRUPT
+ *
+ *                     PCIe215        PC218E         PCIe236
+ *                  -------------  -------------  -------------
+ *   Subdevices           8              7              8
+ *    0                 PPI-X          CTR-X1         PPI-X
+ *    1                 UNUSED         CTR-X2         UNUSED
+ *    2                 PPI-Y          CTR-Y1         UNUSED
+ *    3                 UNUSED         CTR-Y2         UNUSED
+ *    4                 CTR-Z1         CTR-Z1         CTR-Z1
+ *    5                 CTR-Z2         CTR-Z2         CTR-Z2
+ *    6                 TIMER        INTERRUPT        TIMER
+ *    7               INTERRUPT                     INTERRUPT
+ *
+ *                  PC272E/PCI272     PCIe296
+ *                  -------------  -------------
+ *   Subdevices           4              8
+ *    0                 PPI-X          PPI-X1
+ *    1                 PPI-Y          PPI-X2
+ *    2                 PPI-Z          PPI-Y1
+ *    3               INTERRUPT        PPI-Y2
+ *    4                                CTR-Z1
+ *    5                                CTR-Z2
+ *    6                                TIMER
+ *    7                              INTERRUPT
+ *
+ * Each PPI is a 8255 chip providing 24 DIO channels.  The DIO channels
+ * are configurable as inputs or outputs in four groups:
+ *
+ *   Port A  - channels  0 to  7
+ *   Port B  - channels  8 to 15
+ *   Port CL - channels 16 to 19
+ *   Port CH - channels 20 to 23
+ *
+ * Only mode 0 of the 8255 chips is supported.
+ *
+ * Each CTR is a 8254 chip providing 3 16-bit counter channels.  Each
+ * channel is configured individually with INSN_CONFIG instructions.  The
+ * specific type of configuration instruction is specified in data[0].
+ * Some configuration instructions expect an additional parameter in
+ * data[1]; others return a value in data[1].  The following configuration
+ * instructions are supported:
+ *
+ *   INSN_CONFIG_SET_COUNTER_MODE.  Sets the counter channel's mode and
+ *     BCD/binary setting specified in data[1].
+ *
+ *   INSN_CONFIG_8254_READ_STATUS.  Reads the status register value for the
+ *     counter channel into data[1].
+ *
+ *   INSN_CONFIG_SET_CLOCK_SRC.  Sets the counter channel's clock source as
+ *     specified in data[1] (this is a hardware-specific value).  Not
+ *     supported on PC214E.  For the other boards, valid clock sources are
+ *     0 to 7 as follows:
+ *
+ *       0.  CLK n, the counter channel's dedicated CLK input from the SK1
+ *         connector.  (N.B. for other values, the counter channel's CLKn
+ *         pin on the SK1 connector is an output!)
+ *       1.  Internal 10 MHz clock.
+ *       2.  Internal 1 MHz clock.
+ *       3.  Internal 100 kHz clock.
+ *       4.  Internal 10 kHz clock.
+ *       5.  Internal 1 kHz clock.
+ *       6.  OUT n-1, the output of counter channel n-1 (see note 1 below).
+ *       7.  Ext Clock, the counter chip's dedicated Ext Clock input from
+ *         the SK1 connector.  This pin is shared by all three counter
+ *         channels on the chip.
+ *
+ *     For the PCIe boards, clock sources in the range 0 to 31 are allowed
+ *     and the following additional clock sources are defined:
+ *
+ *       8.  HIGH logic level.
+ *       9.  LOW logic level.
+ *      10.  "Pattern present" signal.
+ *      11.  Internal 20 MHz clock.
+ *
+ *   INSN_CONFIG_GET_CLOCK_SRC.  Returns the counter channel's current
+ *     clock source in data[1].  For internal clock sources, data[2] is set
+ *     to the period in ns.
+ *
+ *   INSN_CONFIG_SET_GATE_SRC.  Sets the counter channel's gate source as
+ *     specified in data[2] (this is a hardware-specific value).  Not
+ *     supported on PC214E.  For the other boards, valid gate sources are 0
+ *     to 7 as follows:
+ *
+ *       0.  VCC (internal +5V d.c.), i.e. gate permanently enabled.
+ *       1.  GND (internal 0V d.c.), i.e. gate permanently disabled.
+ *       2.  GAT n, the counter channel's dedicated GAT input from the SK1
+ *         connector.  (N.B. for other values, the counter channel's GATn
+ *         pin on the SK1 connector is an output!)
+ *       3.  /OUT n-2, the inverted output of counter channel n-2 (see note
+ *         2 below).
+ *       4.  Reserved.
+ *       5.  Reserved.
+ *       6.  Reserved.
+ *       7.  Reserved.
+ *
+ *     For the PCIe boards, gate sources in the range 0 to 31 are allowed;
+ *     the following additional clock sources and clock sources 6 and 7 are
+ *     (re)defined:
+ *
+ *       6.  /GAT n, negated version of the counter channel's dedicated
+ *         GAT input (negated version of gate source 2).
+ *       7.  OUT n-2, the non-inverted output of counter channel n-2
+ *         (negated version of gate source 3).
+ *       8.  "Pattern present" signal, HIGH while pattern present.
+ *       9.  "Pattern occurred" latched signal, latches HIGH when pattern
+ *         occurs.
+ *      10.  "Pattern gone away" latched signal, latches LOW when pattern
+ *         goes away after it occurred.
+ *      11.  Negated "pattern present" signal, LOW while pattern present
+ *         (negated version of gate source 8).
+ *      12.  Negated "pattern occurred" latched signal, latches LOW when
+ *         pattern occurs (negated version of gate source 9).
+ *      13.  Negated "pattern gone away" latched signal, latches LOW when
+ *         pattern goes away after it occurred (negated version of gate
+ *         source 10).
+ *
+ *   INSN_CONFIG_GET_GATE_SRC.  Returns the counter channel's current gate
+ *     source in data[2].
+ *
+ * Clock and gate interconnection notes:
+ *
+ *   1.  Clock source OUT n-1 is the output of the preceding channel on the
+ *   same counter subdevice if n > 0, or the output of channel 2 on the
+ *   preceding counter subdevice (see note 3) if n = 0.
+ *
+ *   2.  Gate source /OUT n-2 is the inverted output of channel 0 on the
+ *   same counter subdevice if n = 2, or the inverted output of channel n+1
+ *   on the preceding counter subdevice (see note 3) if n < 2.
+ *
+ *   3.  The counter subdevices are connected in a ring, so the highest
+ *   counter subdevice precedes the lowest.
+ *
+ * The 'TIMER' subdevice is a free-running 32-bit timer subdevice.
+ *
+ * The 'INTERRUPT' subdevice pretends to be a digital input subdevice.  The
+ * digital inputs come from the interrupt status register.  The number of
+ * channels matches the number of interrupt sources.  The PC214E does not
+ * have an interrupt status register; see notes on 'INTERRUPT SOURCES'
+ * below.
+ *
+ * INTERRUPT SOURCES
+ *
+ *                     PC212E         PC214E      PC215E/PCI215
+ *                  -------------  -------------  -------------
+ *   Sources              6              1              6
+ *    0               PPI-X-C0       JUMPER-J5      PPI-X-C0
+ *    1               PPI-X-C3                      PPI-X-C3
+ *    2              CTR-Y1-OUT1                    PPI-Y-C0
+ *    3              CTR-Y2-OUT1                    PPI-Y-C3
+ *    4              CTR-Z1-OUT1                   CTR-Z1-OUT1
+ *    5              CTR-Z2-OUT1                   CTR-Z2-OUT1
+ *
+ *                     PCIe215        PC218E         PCIe236
+ *                  -------------  -------------  -------------
+ *   Sources              6              6              6
+ *    0               PPI-X-C0      CTR-X1-OUT1     PPI-X-C0
+ *    1               PPI-X-C3      CTR-X2-OUT1     PPI-X-C3
+ *    2               PPI-Y-C0      CTR-Y1-OUT1      unused
+ *    3               PPI-Y-C3      CTR-Y2-OUT1      unused
+ *    4              CTR-Z1-OUT1    CTR-Z1-OUT1    CTR-Z1-OUT1
+ *    5              CTR-Z2-OUT1    CTR-Z2-OUT1    CTR-Z2-OUT1
+ *
+ *                  PC272E/PCI272     PCIe296
+ *                  -------------  -------------
+ *   Sources              6              6
+ *    0               PPI-X-C0       PPI-X1-C0
+ *    1               PPI-X-C3       PPI-X1-C3
+ *    2               PPI-Y-C0       PPI-Y1-C0
+ *    3               PPI-Y-C3       PPI-Y1-C3
+ *    4               PPI-Z-C0      CTR-Z1-OUT1
+ *    5               PPI-Z-C3      CTR-Z2-OUT1
+ *
+ * When an interrupt source is enabled in the interrupt source enable
+ * register, a rising edge on the source signal latches the corresponding
+ * bit to 1 in the interrupt status register.
+ *
+ * When the interrupt status register value as a whole (actually, just the
+ * 6 least significant bits) goes from zero to non-zero, the board will
+ * generate an interrupt.  For level-triggered hardware interrupts (PCI
+ * card), the interrupt will remain asserted until the interrupt status
+ * register is cleared to zero.  For edge-triggered hardware interrupts
+ * (ISA card), no further interrupts will occur until the interrupt status
+ * register is cleared to zero.  To clear a bit to zero in the interrupt
+ * status register, the corresponding interrupt source must be disabled
+ * in the interrupt source enable register (there is no separate interrupt
+ * clear register).
+ *
+ * The PC214E does not have an interrupt source enable register or an
+ * interrupt status register; its 'INTERRUPT' subdevice has a single
+ * channel and its interrupt source is selected by the position of jumper
+ * J5.
+ *
+ * COMMANDS
+ *
+ * The driver supports a read streaming acquisition command on the
+ * 'INTERRUPT' subdevice.  The channel list selects the interrupt sources
+ * to be enabled.  All channels will be sampled together (convert_src ==
+ * TRIG_NOW).  The scan begins a short time after the hardware interrupt
+ * occurs, subject to interrupt latencies (scan_begin_src == TRIG_EXT,
+ * scan_begin_arg == 0).  The value read from the interrupt status register
+ * is packed into a short value, one bit per requested channel, in the
+ * order they appear in the channel list.
+ */
 
 #include <linux/interrupt.h>
 #include <linux/slab.h>
@@ -211,7 +264,6 @@ order they appear in the channel list.
 #include "../comedidev.h"
 
 #include "comedi_fc.h"
-#include "8255.h"
 #include "8253.h"
 
 #define DIO200_DRIVER_NAME	"amplc_dio200"
@@ -220,13 +272,24 @@ order they appear in the channel list.
 #define DO_PCI	IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI)
 
 /* PCI IDs */
-#define PCI_VENDOR_ID_AMPLICON 0x14dc
 #define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
 #define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
-#define PCI_DEVICE_ID_INVALID 0xffff
+#define PCI_DEVICE_ID_AMPLICON_PCIE236 0x0011
+#define PCI_DEVICE_ID_AMPLICON_PCIE215 0x0012
+#define PCI_DEVICE_ID_AMPLICON_PCIE296 0x0014
+
+/* 8255 control register bits */
+#define CR_C_LO_IO	0x01
+#define CR_B_IO		0x02
+#define CR_B_MODE	0x04
+#define CR_C_HI_IO	0x08
+#define CR_A_IO		0x10
+#define CR_A_MODE(a)	((a)<<5)
+#define CR_CW		0x80
 
 /* 200 series registers */
 #define DIO200_IO_SIZE		0x20
+#define DIO200_PCIE_IO_SIZE	0x4000
 #define DIO200_XCLK_SCE		0x18	/* Group X clock selection register */
 #define DIO200_YCLK_SCE		0x19	/* Group Y clock selection register */
 #define DIO200_ZCLK_SCE		0x1a	/* Group Z clock selection register */
@@ -234,30 +297,78 @@ order they appear in the channel list.
 #define DIO200_YGAT_SCE		0x1c	/* Group Y gate selection register */
 #define DIO200_ZGAT_SCE		0x1d	/* Group Z gate selection register */
 #define DIO200_INT_SCE		0x1e	/* Interrupt enable/status register */
+/* Extra registers for new PCIe boards */
+#define DIO200_ENHANCE		0x20	/* 1 to enable enhanced features */
+#define DIO200_VERSION		0x24	/* Hardware version register */
+#define DIO200_TS_CONFIG	0x600	/* Timestamp timer config register */
+#define DIO200_TS_COUNT		0x602	/* Timestamp timer count register */
 
 /*
- * Macros for constructing value for DIO_200_?CLK_SCE and
+ * Functions for constructing value for DIO_200_?CLK_SCE and
  * DIO_200_?GAT_SCE registers:
  *
  * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2.
  * 'chan' is the channel: 0, 1 or 2.
- * 'source' is the signal source: 0 to 7.
+ * 'source' is the signal source: 0 to 7, or 0 to 31 for "enhanced" boards.
  */
-#define CLK_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
-#define GAT_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
+static unsigned char clk_gat_sce(unsigned int which, unsigned int chan,
+				 unsigned int source)
+{
+	return (which << 5) | (chan << 3) |
+	       ((source & 030) << 3) | (source & 007);
+}
+
+static unsigned char clk_sce(unsigned int which, unsigned int chan,
+			     unsigned int source)
+{
+	return clk_gat_sce(which, chan, source);
+}
+
+static unsigned char gat_sce(unsigned int which, unsigned int chan,
+			     unsigned int source)
+{
+	return clk_gat_sce(which, chan, source);
+}
 
 /*
  * Periods of the internal clock sources in nanoseconds.
  */
-static const unsigned clock_period[8] = {
-	0,			/* dedicated clock input/output pin */
-	100,			/* 10 MHz */
-	1000,			/* 1 MHz */
-	10000,			/* 100 kHz */
-	100000,			/* 10 kHz */
-	1000000,		/* 1 kHz */
-	0,			/* OUT N-1 */
-	0			/* group clock input pin */
+static const unsigned int clock_period[32] = {
+	[1] = 100,		/* 10 MHz */
+	[2] = 1000,		/* 1 MHz */
+	[3] = 10000,		/* 100 kHz */
+	[4] = 100000,		/* 10 kHz */
+	[5] = 1000000,		/* 1 kHz */
+	[11] = 50,		/* 20 MHz (enhanced boards) */
+	/* clock sources 12 and later reserved for enhanced boards */
+};
+
+/*
+ * Timestamp timer configuration register (for new PCIe boards).
+ */
+#define TS_CONFIG_RESET		0x100	/* Reset counter to zero. */
+#define TS_CONFIG_CLK_SRC_MASK	0x0FF	/* Clock source. */
+#define TS_CONFIG_MAX_CLK_SRC	2	/* Maximum clock source value. */
+
+/*
+ * Periods of the timestamp timer clock sources in nanoseconds.
+ */
+static const unsigned int ts_clock_period[TS_CONFIG_MAX_CLK_SRC + 1] = {
+	1,			/* 1 nanosecond (but with 20 ns granularity). */
+	1000,			/* 1 microsecond. */
+	1000000,		/* 1 millisecond. */
+};
+
+/*
+ * Register region.
+ */
+enum dio200_regtype { no_regtype = 0, io_regtype, mmio_regtype };
+struct dio200_region {
+	union {
+		unsigned long iobase;		/* I/O base address */
+		unsigned char __iomem *membase;	/* mapped MMIO base address */
+	} u;
+	enum dio200_regtype regtype;
 };
 
 /*
@@ -269,13 +380,14 @@ enum dio200_bustype { isa_bustype, pci_bustype };
 enum dio200_model {
 	pc212e_model,
 	pc214e_model,
-	pc215e_model, pci215_model,
+	pc215e_model, pci215_model, pcie215_model,
 	pc218e_model,
+	pcie236_model,
 	pc272e_model, pci272_model,
-	anypci_model
+	pcie296_model,
 };
 
-enum dio200_layout {
+enum dio200_layout_idx {
 #if DO_ISA
 	pc212_layout,
 	pc214_layout,
@@ -284,7 +396,12 @@ enum dio200_layout {
 #if DO_ISA
 	pc218_layout,
 #endif
-	pc272_layout
+	pc272_layout,
+#if DO_PCI
+	pcie215_layout,
+	pcie236_layout,
+	pcie296_layout,
+#endif
 };
 
 struct dio200_board {
@@ -292,7 +409,10 @@ struct dio200_board {
 	unsigned short devid;
 	enum dio200_bustype bustype;
 	enum dio200_model model;
-	enum dio200_layout layout;
+	enum dio200_layout_idx layout;
+	unsigned char mainbar;
+	unsigned char mainshift;
+	unsigned int mainsize;
 };
 
 static const struct dio200_board dio200_boards[] = {
@@ -302,30 +422,35 @@ static const struct dio200_board dio200_boards[] = {
 	 .bustype = isa_bustype,
 	 .model = pc212e_model,
 	 .layout = pc212_layout,
+	 .mainsize = DIO200_IO_SIZE,
 	 },
 	{
 	 .name = "pc214e",
 	 .bustype = isa_bustype,
 	 .model = pc214e_model,
 	 .layout = pc214_layout,
+	 .mainsize = DIO200_IO_SIZE,
 	 },
 	{
 	 .name = "pc215e",
 	 .bustype = isa_bustype,
 	 .model = pc215e_model,
 	 .layout = pc215_layout,
+	 .mainsize = DIO200_IO_SIZE,
 	 },
 	{
 	 .name = "pc218e",
 	 .bustype = isa_bustype,
 	 .model = pc218e_model,
 	 .layout = pc218_layout,
+	 .mainsize = DIO200_IO_SIZE,
 	 },
 	{
 	 .name = "pc272e",
 	 .bustype = isa_bustype,
 	 .model = pc272e_model,
 	 .layout = pc272_layout,
+	 .mainsize = DIO200_IO_SIZE,
 	 },
 #endif
 #if DO_PCI
@@ -335,6 +460,8 @@ static const struct dio200_board dio200_boards[] = {
 	 .bustype = pci_bustype,
 	 .model = pci215_model,
 	 .layout = pc215_layout,
+	 .mainbar = 2,
+	 .mainsize = DIO200_IO_SIZE,
 	 },
 	{
 	 .name = "pci272",
@@ -342,12 +469,38 @@ static const struct dio200_board dio200_boards[] = {
 	 .bustype = pci_bustype,
 	 .model = pci272_model,
 	 .layout = pc272_layout,
+	 .mainbar = 2,
+	 .mainsize = DIO200_IO_SIZE,
+	 },
+	{
+	 .name = "pcie215",
+	 .devid = PCI_DEVICE_ID_AMPLICON_PCIE215,
+	 .bustype = pci_bustype,
+	 .model = pcie215_model,
+	 .layout = pcie215_layout,
+	 .mainbar = 1,
+	 .mainshift = 3,
+	 .mainsize = DIO200_PCIE_IO_SIZE,
 	 },
 	{
-	 .name = DIO200_DRIVER_NAME,
-	 .devid = PCI_DEVICE_ID_INVALID,
+	 .name = "pcie236",
+	 .devid = PCI_DEVICE_ID_AMPLICON_PCIE236,
 	 .bustype = pci_bustype,
-	 .model = anypci_model,	/* wildcard */
+	 .model = pcie236_model,
+	 .layout = pcie236_layout,
+	 .mainbar = 1,
+	 .mainshift = 3,
+	 .mainsize = DIO200_PCIE_IO_SIZE,
+	 },
+	{
+	 .name = "pcie296",
+	 .devid = PCI_DEVICE_ID_AMPLICON_PCIE296,
+	 .bustype = pci_bustype,
+	 .model = pcie296_model,
+	 .layout = pcie296_layout,
+	 .mainbar = 1,
+	 .mainshift = 3,
+	 .mainsize = DIO200_PCIE_IO_SIZE,
 	 },
 #endif
 };
@@ -357,20 +510,21 @@ static const struct dio200_board dio200_boards[] = {
  * layout.
  */
 
-enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254 };
+enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254, sd_timer };
 
-#define DIO200_MAX_SUBDEVS	7
+#define DIO200_MAX_SUBDEVS	8
 #define DIO200_MAX_ISNS		6
 
-struct dio200_layout_struct {
+struct dio200_layout {
 	unsigned short n_subdevs;	/* number of subdevices */
 	unsigned char sdtype[DIO200_MAX_SUBDEVS];	/* enum dio200_sdtype */
 	unsigned char sdinfo[DIO200_MAX_SUBDEVS];	/* depends on sdtype */
 	char has_int_sce;	/* has interrupt enable/status register */
 	char has_clk_gat_sce;	/* has clock/gate selection registers */
+	char has_enhancements;	/* has enhanced features */
 };
 
-static const struct dio200_layout_struct dio200_layouts[] = {
+static const struct dio200_layout dio200_layouts[] = {
 #if DO_ISA
 	[pc212_layout] = {
 			  .n_subdevs = 6,
@@ -421,6 +575,38 @@ static const struct dio200_layout_struct dio200_layouts[] = {
 			  .has_int_sce = 1,
 			  .has_clk_gat_sce = 0,
 			  },
+#if DO_PCI
+	[pcie215_layout] = {
+			  .n_subdevs = 8,
+			  .sdtype = {sd_8255, sd_none, sd_8255, sd_none,
+				     sd_8254, sd_8254, sd_timer, sd_intr},
+			  .sdinfo = {0x00, 0x00, 0x08, 0x00,
+				     0x10, 0x14, 0x00, 0x3F},
+			  .has_int_sce = 1,
+			  .has_clk_gat_sce = 1,
+			  .has_enhancements = 1,
+			  },
+	[pcie236_layout] = {
+			  .n_subdevs = 8,
+			  .sdtype = {sd_8255, sd_none, sd_none, sd_none,
+				     sd_8254, sd_8254, sd_timer, sd_intr},
+			  .sdinfo = {0x00, 0x00, 0x00, 0x00,
+				     0x10, 0x14, 0x00, 0x3F},
+			  .has_int_sce = 1,
+			  .has_clk_gat_sce = 1,
+			  .has_enhancements = 1,
+			  },
+	[pcie296_layout] = {
+			  .n_subdevs = 8,
+			  .sdtype = {sd_8255, sd_8255, sd_8255, sd_8255,
+				     sd_8254, sd_8254, sd_timer, sd_intr},
+			  .sdinfo = {0x00, 0x04, 0x08, 0x0C,
+				     0x10, 0x14, 0x00, 0x3F},
+			  .has_int_sce = 1,
+			  .has_clk_gat_sce = 1,
+			  .has_enhancements = 1,
+			  },
+#endif
 };
 
 /* this structure is for data unique to this hardware driver.  If
@@ -428,31 +614,46 @@ static const struct dio200_layout_struct dio200_layouts[] = {
    feel free to suggest moving the variable to the struct comedi_device struct.
  */
 struct dio200_private {
+	struct dio200_region io;	/* Register region */
 	int intr_sd;
 };
 
 struct dio200_subdev_8254 {
-	unsigned long iobase;	/* Counter base address */
-	unsigned long clk_sce_iobase;	/* CLK_SCE base address */
-	unsigned long gat_sce_iobase;	/* GAT_SCE base address */
-	int which;		/* Bit 5 of CLK_SCE or GAT_SCE */
-	int has_clk_gat_sce;
-	unsigned clock_src[3];	/* Current clock sources */
-	unsigned gate_src[3];	/* Current gate sources */
+	unsigned int ofs;		/* Counter base offset */
+	unsigned int clk_sce_ofs;	/* CLK_SCE base address */
+	unsigned int gat_sce_ofs;	/* GAT_SCE base address */
+	int which;			/* Bit 5 of CLK_SCE or GAT_SCE */
+	unsigned int clock_src[3];	/* Current clock sources */
+	unsigned int gate_src[3];	/* Current gate sources */
 	spinlock_t spinlock;
 };
 
+struct dio200_subdev_8255 {
+	unsigned int ofs;		/* DIO base offset */
+};
+
 struct dio200_subdev_intr {
-	unsigned long iobase;
+	unsigned int ofs;
 	spinlock_t spinlock;
 	int active;
-	int has_int_sce;
 	unsigned int valid_isns;
 	unsigned int enabled_isns;
 	unsigned int stopcount;
 	int continuous;
 };
 
+static inline const struct dio200_layout *
+dio200_board_layout(const struct dio200_board *board)
+{
+	return &dio200_layouts[board->layout];
+}
+
+static inline const struct dio200_layout *
+dio200_dev_layout(struct comedi_device *dev)
+{
+	return dio200_board_layout(comedi_board(dev));
+}
+
 static inline bool is_pci_board(const struct dio200_board *board)
 {
 	return DO_PCI && board->bustype == pci_bustype;
@@ -464,6 +665,70 @@ static inline bool is_isa_board(const struct dio200_board *board)
 }
 
 /*
+ * Read 8-bit register.
+ */
+static unsigned char dio200_read8(struct comedi_device *dev,
+				  unsigned int offset)
+{
+	const struct dio200_board *thisboard = comedi_board(dev);
+	struct dio200_private *devpriv = dev->private;
+
+	offset <<= thisboard->mainshift;
+	if (devpriv->io.regtype == io_regtype)
+		return inb(devpriv->io.u.iobase + offset);
+	else
+		return readb(devpriv->io.u.membase + offset);
+}
+
+/*
+ * Write 8-bit register.
+ */
+static void dio200_write8(struct comedi_device *dev, unsigned int offset,
+			  unsigned char val)
+{
+	const struct dio200_board *thisboard = comedi_board(dev);
+	struct dio200_private *devpriv = dev->private;
+
+	offset <<= thisboard->mainshift;
+	if (devpriv->io.regtype == io_regtype)
+		outb(val, devpriv->io.u.iobase + offset);
+	else
+		writeb(val, devpriv->io.u.membase + offset);
+}
+
+/*
+ * Read 32-bit register.
+ */
+static unsigned int dio200_read32(struct comedi_device *dev,
+				  unsigned int offset)
+{
+	const struct dio200_board *thisboard = comedi_board(dev);
+	struct dio200_private *devpriv = dev->private;
+
+	offset <<= thisboard->mainshift;
+	if (devpriv->io.regtype == io_regtype)
+		return inl(devpriv->io.u.iobase + offset);
+	else
+		return readl(devpriv->io.u.membase + offset);
+}
+
+/*
+ * Write 32-bit register.
+ */
+static void dio200_write32(struct comedi_device *dev, unsigned int offset,
+			   unsigned int val)
+{
+	const struct dio200_board *thisboard = comedi_board(dev);
+	struct dio200_private *devpriv = dev->private;
+
+	offset <<= thisboard->mainshift;
+	if (devpriv->io.regtype == io_regtype)
+		outl(val, devpriv->io.u.iobase + offset);
+	else
+		writel(val, devpriv->io.u.membase + offset);
+}
+
+/*
  * This function looks for a board matching the supplied PCI device.
  */
 static const struct dio200_board *
@@ -479,49 +744,6 @@ dio200_find_pci_board(struct pci_dev *pci_dev)
 }
 
 /*
- * This function looks for a PCI device matching the requested board name,
- * bus and slot.
- */
-static struct pci_dev *dio200_find_pci_dev(struct comedi_device *dev,
-					   struct comedi_devconfig *it)
-{
-	const struct dio200_board *thisboard = comedi_board(dev);
-	struct pci_dev *pci_dev = NULL;
-	int bus = it->options[0];
-	int slot = it->options[1];
-
-	for_each_pci_dev(pci_dev) {
-		if (bus || slot) {
-			if (bus != pci_dev->bus->number ||
-			    slot != PCI_SLOT(pci_dev->devfn))
-				continue;
-		}
-		if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
-			continue;
-
-		if (thisboard->model == anypci_model) {
-			/* Wildcard board matches any supported PCI board. */
-			const struct dio200_board *foundboard;
-
-			foundboard = dio200_find_pci_board(pci_dev);
-			if (foundboard == NULL)
-				continue;
-			/* Replace wildcard board_ptr. */
-			dev->board_ptr = foundboard;
-		} else {
-			/* Match specific model name. */
-			if (pci_dev->device != thisboard->devid)
-				continue;
-		}
-		return pci_dev;
-	}
-	dev_err(dev->class_dev,
-		"No supported board found! (req. bus %d, slot %d)\n",
-		bus, slot);
-	return NULL;
-}
-
-/*
  * This function checks and requests an I/O region, reporting an error
  * if there is a conflict.
  */
@@ -545,11 +767,12 @@ dio200_subdev_intr_insn_bits(struct comedi_device *dev,
 			     struct comedi_subdevice *s,
 			     struct comedi_insn *insn, unsigned int *data)
 {
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
 	struct dio200_subdev_intr *subpriv = s->private;
 
-	if (subpriv->has_int_sce) {
+	if (layout->has_int_sce) {
 		/* Just read the interrupt status register.  */
-		data[1] = inb(subpriv->iobase) & subpriv->valid_isns;
+		data[1] = dio200_read8(dev, subpriv->ofs) & subpriv->valid_isns;
 	} else {
 		/* No interrupt status register. */
 		data[0] = 0;
@@ -564,12 +787,13 @@ dio200_subdev_intr_insn_bits(struct comedi_device *dev,
 static void dio200_stop_intr(struct comedi_device *dev,
 			     struct comedi_subdevice *s)
 {
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
 	struct dio200_subdev_intr *subpriv = s->private;
 
 	subpriv->active = 0;
 	subpriv->enabled_isns = 0;
-	if (subpriv->has_int_sce)
-		outb(0, subpriv->iobase);
+	if (layout->has_int_sce)
+		dio200_write8(dev, subpriv->ofs, 0);
 }
 
 /*
@@ -580,6 +804,7 @@ static int dio200_start_intr(struct comedi_device *dev,
 {
 	unsigned int n;
 	unsigned isn_bits;
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
 	struct dio200_subdev_intr *subpriv = s->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
 	int retval = 0;
@@ -599,8 +824,8 @@ static int dio200_start_intr(struct comedi_device *dev,
 		isn_bits &= subpriv->valid_isns;
 		/* Enable interrupt sources. */
 		subpriv->enabled_isns = isn_bits;
-		if (subpriv->has_int_sce)
-			outb(isn_bits, subpriv->iobase);
+		if (layout->has_int_sce)
+			dio200_write8(dev, subpriv->ofs, isn_bits);
 	}
 
 	return retval;
@@ -642,6 +867,7 @@ dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
 static int dio200_handle_read_intr(struct comedi_device *dev,
 				   struct comedi_subdevice *s)
 {
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
 	struct dio200_subdev_intr *subpriv = s->private;
 	unsigned triggered;
 	unsigned intstat;
@@ -653,7 +879,7 @@ static int dio200_handle_read_intr(struct comedi_device *dev,
 
 	spin_lock_irqsave(&subpriv->spinlock, flags);
 	oldevents = s->async->events;
-	if (subpriv->has_int_sce) {
+	if (layout->has_int_sce) {
 		/*
 		 * Collect interrupt sources that have triggered and disable
 		 * them temporarily.  Loop around until no extra interrupt
@@ -665,11 +891,11 @@ static int dio200_handle_read_intr(struct comedi_device *dev,
 		 * loop in case of misconfiguration.
 		 */
 		cur_enabled = subpriv->enabled_isns;
-		while ((intstat = (inb(subpriv->iobase) & subpriv->valid_isns
-				   & ~triggered)) != 0) {
+		while ((intstat = (dio200_read8(dev, subpriv->ofs) &
+				   subpriv->valid_isns & ~triggered)) != 0) {
 			triggered |= intstat;
 			cur_enabled &= ~triggered;
-			outb(cur_enabled, subpriv->iobase);
+			dio200_write8(dev, subpriv->ofs, cur_enabled);
 		}
 	} else {
 		/*
@@ -687,8 +913,8 @@ static int dio200_handle_read_intr(struct comedi_device *dev,
 		 * Reenable them NOW to minimize the time they are disabled.
 		 */
 		cur_enabled = subpriv->enabled_isns;
-		if (subpriv->has_int_sce)
-			outb(cur_enabled, subpriv->iobase);
+		if (layout->has_int_sce)
+			dio200_write8(dev, subpriv->ofs, cur_enabled);
 
 		if (subpriv->active) {
 			/*
@@ -794,41 +1020,19 @@ dio200_subdev_intr_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	/* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
-
-	/* cmd->scan_begin_src == TRIG_EXT */
-	if (cmd->scan_begin_arg != 0) {
-		cmd->scan_begin_arg = 0;
-		err++;
-	}
-
-	/* cmd->convert_src == TRIG_NOW */
-	if (cmd->convert_arg != 0) {
-		cmd->convert_arg = 0;
-		err++;
-	}
-
-	/* cmd->scan_end_src == TRIG_COUNT */
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	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, cmd->chanlist_len);
 
 	switch (cmd->stop_src) {
 	case TRIG_COUNT:
 		/* any count allowed */
 		break;
 	case TRIG_NONE:
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 		break;
 	default:
 		break;
@@ -894,9 +1098,9 @@ static int dio200_subdev_intr_cmd(struct comedi_device *dev,
  */
 static int
 dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
-			unsigned long iobase, unsigned valid_isns,
-			int has_int_sce)
+			unsigned int offset, unsigned valid_isns)
 {
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
 	struct dio200_subdev_intr *subpriv;
 
 	subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
@@ -904,18 +1108,18 @@ dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
 		dev_err(dev->class_dev, "error! out of memory!\n");
 		return -ENOMEM;
 	}
-	subpriv->iobase = iobase;
-	subpriv->has_int_sce = has_int_sce;
+	subpriv->ofs = offset;
 	subpriv->valid_isns = valid_isns;
 	spin_lock_init(&subpriv->spinlock);
 
-	if (has_int_sce)
-		outb(0, subpriv->iobase);	/* Disable interrupt sources. */
+	if (layout->has_int_sce)
+		/* Disable interrupt sources. */
+		dio200_write8(dev, subpriv->ofs, 0);
 
 	s->private = subpriv;
 	s->type = COMEDI_SUBD_DI;
 	s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
-	if (has_int_sce) {
+	if (layout->has_int_sce) {
 		s->n_chan = DIO200_MAX_ISNS;
 		s->len_chanlist = DIO200_MAX_ISNS;
 	} else {
@@ -968,6 +1172,73 @@ static irqreturn_t dio200_interrupt(int irq, void *d)
 }
 
 /*
+ * Read an '8254' counter subdevice channel.
+ */
+static unsigned int
+dio200_subdev_8254_read_chan(struct comedi_device *dev,
+			     struct comedi_subdevice *s, unsigned int chan)
+{
+	struct dio200_subdev_8254 *subpriv = s->private;
+	unsigned int val;
+
+	/* latch counter */
+	val = chan << 6;
+	dio200_write8(dev, subpriv->ofs + i8254_control_reg, val);
+	/* read lsb, msb */
+	val = dio200_read8(dev, subpriv->ofs + chan);
+	val += dio200_read8(dev, subpriv->ofs + chan) << 8;
+	return val;
+}
+
+/*
+ * Write an '8254' subdevice channel.
+ */
+static void
+dio200_subdev_8254_write_chan(struct comedi_device *dev,
+			      struct comedi_subdevice *s, unsigned int chan,
+			      unsigned int count)
+{
+	struct dio200_subdev_8254 *subpriv = s->private;
+
+	/* write lsb, msb */
+	dio200_write8(dev, subpriv->ofs + chan, count & 0xff);
+	dio200_write8(dev, subpriv->ofs + chan, (count >> 8) & 0xff);
+}
+
+/*
+ * Set mode of an '8254' subdevice channel.
+ */
+static void
+dio200_subdev_8254_set_mode(struct comedi_device *dev,
+			    struct comedi_subdevice *s, unsigned int chan,
+			    unsigned int mode)
+{
+	struct dio200_subdev_8254 *subpriv = s->private;
+	unsigned int byte;
+
+	byte = chan << 6;
+	byte |= 0x30;		/* access order: lsb, msb */
+	byte |= (mode & 0xf);	/* counter mode and BCD|binary */
+	dio200_write8(dev, subpriv->ofs + i8254_control_reg, byte);
+}
+
+/*
+ * Read status byte of an '8254' counter subdevice channel.
+ */
+static unsigned int
+dio200_subdev_8254_status(struct comedi_device *dev,
+			  struct comedi_subdevice *s, unsigned int chan)
+{
+	struct dio200_subdev_8254 *subpriv = s->private;
+
+	/* latch status */
+	dio200_write8(dev, subpriv->ofs + i8254_control_reg,
+		      0xe0 | (2 << chan));
+	/* read status */
+	return dio200_read8(dev, subpriv->ofs + chan);
+}
+
+/*
  * Handle 'insn_read' for an '8254' counter subdevice.
  */
 static int
@@ -976,13 +1247,15 @@ dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
 {
 	struct dio200_subdev_8254 *subpriv = s->private;
 	int chan = CR_CHAN(insn->chanspec);
+	unsigned int n;
 	unsigned long flags;
 
-	spin_lock_irqsave(&subpriv->spinlock, flags);
-	data[0] = i8254_read(subpriv->iobase, 0, chan);
-	spin_unlock_irqrestore(&subpriv->spinlock, flags);
-
-	return 1;
+	for (n = 0; n < insn->n; n++) {
+		spin_lock_irqsave(&subpriv->spinlock, flags);
+		data[n] = dio200_subdev_8254_read_chan(dev, s, chan);
+		spin_unlock_irqrestore(&subpriv->spinlock, flags);
+	}
+	return insn->n;
 }
 
 /*
@@ -994,34 +1267,40 @@ dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
 {
 	struct dio200_subdev_8254 *subpriv = s->private;
 	int chan = CR_CHAN(insn->chanspec);
+	unsigned int n;
 	unsigned long flags;
 
-	spin_lock_irqsave(&subpriv->spinlock, flags);
-	i8254_write(subpriv->iobase, 0, chan, data[0]);
-	spin_unlock_irqrestore(&subpriv->spinlock, flags);
-
-	return 1;
+	for (n = 0; n < insn->n; n++) {
+		spin_lock_irqsave(&subpriv->spinlock, flags);
+		dio200_subdev_8254_write_chan(dev, s, chan, data[n]);
+		spin_unlock_irqrestore(&subpriv->spinlock, flags);
+	}
+	return insn->n;
 }
 
 /*
  * Set gate source for an '8254' counter subdevice channel.
  */
 static int
-dio200_set_gate_src(struct dio200_subdev_8254 *subpriv,
-		    unsigned int counter_number, unsigned int gate_src)
+dio200_subdev_8254_set_gate_src(struct comedi_device *dev,
+				struct comedi_subdevice *s,
+				unsigned int counter_number,
+				unsigned int gate_src)
 {
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
+	struct dio200_subdev_8254 *subpriv = s->private;
 	unsigned char byte;
 
-	if (!subpriv->has_clk_gat_sce)
+	if (!layout->has_clk_gat_sce)
 		return -1;
 	if (counter_number > 2)
 		return -1;
-	if (gate_src > 7)
+	if (gate_src > (layout->has_enhancements ? 31 : 7))
 		return -1;
 
 	subpriv->gate_src[counter_number] = gate_src;
-	byte = GAT_SCE(subpriv->which, counter_number, gate_src);
-	outb(byte, subpriv->gat_sce_iobase);
+	byte = gat_sce(subpriv->which, counter_number, gate_src);
+	dio200_write8(dev, subpriv->gat_sce_ofs, byte);
 
 	return 0;
 }
@@ -1030,10 +1309,14 @@ dio200_set_gate_src(struct dio200_subdev_8254 *subpriv,
  * Get gate source for an '8254' counter subdevice channel.
  */
 static int
-dio200_get_gate_src(struct dio200_subdev_8254 *subpriv,
-		    unsigned int counter_number)
+dio200_subdev_8254_get_gate_src(struct comedi_device *dev,
+				struct comedi_subdevice *s,
+				unsigned int counter_number)
 {
-	if (!subpriv->has_clk_gat_sce)
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
+	struct dio200_subdev_8254 *subpriv = s->private;
+
+	if (!layout->has_clk_gat_sce)
 		return -1;
 	if (counter_number > 2)
 		return -1;
@@ -1045,21 +1328,25 @@ dio200_get_gate_src(struct dio200_subdev_8254 *subpriv,
  * Set clock source for an '8254' counter subdevice channel.
  */
 static int
-dio200_set_clock_src(struct dio200_subdev_8254 *subpriv,
-		     unsigned int counter_number, unsigned int clock_src)
+dio200_subdev_8254_set_clock_src(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 unsigned int counter_number,
+				 unsigned int clock_src)
 {
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
+	struct dio200_subdev_8254 *subpriv = s->private;
 	unsigned char byte;
 
-	if (!subpriv->has_clk_gat_sce)
+	if (!layout->has_clk_gat_sce)
 		return -1;
 	if (counter_number > 2)
 		return -1;
-	if (clock_src > 7)
+	if (clock_src > (layout->has_enhancements ? 31 : 7))
 		return -1;
 
 	subpriv->clock_src[counter_number] = clock_src;
-	byte = CLK_SCE(subpriv->which, counter_number, clock_src);
-	outb(byte, subpriv->clk_sce_iobase);
+	byte = clk_sce(subpriv->which, counter_number, clock_src);
+	dio200_write8(dev, subpriv->clk_sce_ofs, byte);
 
 	return 0;
 }
@@ -1068,12 +1355,16 @@ dio200_set_clock_src(struct dio200_subdev_8254 *subpriv,
  * Get clock source for an '8254' counter subdevice channel.
  */
 static int
-dio200_get_clock_src(struct dio200_subdev_8254 *subpriv,
-		     unsigned int counter_number, unsigned int *period_ns)
+dio200_subdev_8254_get_clock_src(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 unsigned int counter_number,
+				 unsigned int *period_ns)
 {
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
+	struct dio200_subdev_8254 *subpriv = s->private;
 	unsigned clock_src;
 
-	if (!subpriv->has_clk_gat_sce)
+	if (!layout->has_clk_gat_sce)
 		return -1;
 	if (counter_number > 2)
 		return -1;
@@ -1098,20 +1389,21 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
 	spin_lock_irqsave(&subpriv->spinlock, flags);
 	switch (data[0]) {
 	case INSN_CONFIG_SET_COUNTER_MODE:
-		ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
-		if (ret < 0)
+		if (data[1] > (I8254_MODE5 | I8254_BINARY))
 			ret = -EINVAL;
+		else
+			dio200_subdev_8254_set_mode(dev, s, chan, data[1]);
 		break;
 	case INSN_CONFIG_8254_READ_STATUS:
-		data[1] = i8254_status(subpriv->iobase, 0, chan);
+		data[1] = dio200_subdev_8254_status(dev, s, chan);
 		break;
 	case INSN_CONFIG_SET_GATE_SRC:
-		ret = dio200_set_gate_src(subpriv, chan, data[2]);
+		ret = dio200_subdev_8254_set_gate_src(dev, s, chan, data[2]);
 		if (ret < 0)
 			ret = -EINVAL;
 		break;
 	case INSN_CONFIG_GET_GATE_SRC:
-		ret = dio200_get_gate_src(subpriv, chan);
+		ret = dio200_subdev_8254_get_gate_src(dev, s, chan);
 		if (ret < 0) {
 			ret = -EINVAL;
 			break;
@@ -1119,12 +1411,12 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
 		data[2] = ret;
 		break;
 	case INSN_CONFIG_SET_CLOCK_SRC:
-		ret = dio200_set_clock_src(subpriv, chan, data[1]);
+		ret = dio200_subdev_8254_set_clock_src(dev, s, chan, data[1]);
 		if (ret < 0)
 			ret = -EINVAL;
 		break;
 	case INSN_CONFIG_GET_CLOCK_SRC:
-		ret = dio200_get_clock_src(subpriv, chan, &data[2]);
+		ret = dio200_subdev_8254_get_clock_src(dev, s, chan, &data[2]);
 		if (ret < 0) {
 			ret = -EINVAL;
 			break;
@@ -1141,15 +1433,12 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
 
 /*
  * This function initializes an '8254' counter subdevice.
- *
- * Note: iobase is the base address of the board, not the subdevice;
- * offset is the offset to the 8254 chip.
  */
 static int
 dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
-			unsigned long iobase, unsigned offset,
-			int has_clk_gat_sce)
+			unsigned int offset)
 {
+	const struct dio200_layout *layout = dio200_dev_layout(dev);
 	struct dio200_subdev_8254 *subpriv;
 	unsigned int chan;
 
@@ -1169,27 +1458,24 @@ dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
 	s->insn_config = dio200_subdev_8254_config;
 
 	spin_lock_init(&subpriv->spinlock);
-	subpriv->iobase = offset + iobase;
-	subpriv->has_clk_gat_sce = has_clk_gat_sce;
-	if (has_clk_gat_sce) {
+	subpriv->ofs = offset;
+	if (layout->has_clk_gat_sce) {
 		/* Derive CLK_SCE and GAT_SCE register offsets from
 		 * 8254 offset. */
-		subpriv->clk_sce_iobase =
-		    DIO200_XCLK_SCE + (offset >> 3) + iobase;
-		subpriv->gat_sce_iobase =
-		    DIO200_XGAT_SCE + (offset >> 3) + iobase;
+		subpriv->clk_sce_ofs = DIO200_XCLK_SCE + (offset >> 3);
+		subpriv->gat_sce_ofs = DIO200_XGAT_SCE + (offset >> 3);
 		subpriv->which = (offset >> 2) & 1;
 	}
 
 	/* Initialize channels. */
 	for (chan = 0; chan < 3; chan++) {
-		i8254_set_mode(subpriv->iobase, 0, chan,
-			       I8254_MODE0 | I8254_BINARY);
-		if (subpriv->has_clk_gat_sce) {
+		dio200_subdev_8254_set_mode(dev, s, chan,
+					    I8254_MODE0 | I8254_BINARY);
+		if (layout->has_clk_gat_sce) {
 			/* Gate source 0 is VCC (logic 1). */
-			dio200_set_gate_src(subpriv, chan, 0);
+			dio200_subdev_8254_set_gate_src(dev, s, chan, 0);
 			/* Clock source 0 is the dedicated clock input. */
-			dio200_set_clock_src(subpriv, chan, 0);
+			dio200_subdev_8254_set_clock_src(dev, s, chan, 0);
 		}
 	}
 
@@ -1207,16 +1493,294 @@ dio200_subdev_8254_cleanup(struct comedi_device *dev,
 	kfree(subpriv);
 }
 
+/*
+ * This function sets I/O directions for an '8255' DIO subdevice.
+ */
+static void dio200_subdev_8255_set_dir(struct comedi_device *dev,
+				       struct comedi_subdevice *s)
+{
+	struct dio200_subdev_8255 *subpriv = s->private;
+	int config;
+
+	config = CR_CW;
+	/* 1 in io_bits indicates output, 1 in config indicates input */
+	if (!(s->io_bits & 0x0000ff))
+		config |= CR_A_IO;
+	if (!(s->io_bits & 0x00ff00))
+		config |= CR_B_IO;
+	if (!(s->io_bits & 0x0f0000))
+		config |= CR_C_LO_IO;
+	if (!(s->io_bits & 0xf00000))
+		config |= CR_C_HI_IO;
+	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 dio200_subdev_8255 *subpriv = s->private;
+
+	if (data[0]) {
+		s->state &= ~data[0];
+		s->state |= (data[0] & data[1]);
+		if (data[0] & 0xff)
+			dio200_write8(dev, subpriv->ofs, s->state & 0xff);
+		if (data[0] & 0xff00)
+			dio200_write8(dev, subpriv->ofs + 1,
+				      (s->state >> 8) & 0xff);
+		if (data[0] & 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;
+}
+
+/*
+ * Handle 'insn_config' for an '8255' DIO subdevice.
+ */
+static int dio200_subdev_8255_config(struct comedi_device *dev,
+				     struct comedi_subdevice *s,
+				     struct comedi_insn *insn,
+				     unsigned int *data)
+{
+	unsigned int mask;
+	unsigned int bits;
+
+	mask = 1 << CR_CHAN(insn->chanspec);
+	if (mask & 0x0000ff)
+		bits = 0x0000ff;
+	else if (mask & 0x00ff00)
+		bits = 0x00ff00;
+	else if (mask & 0x0f0000)
+		bits = 0x0f0000;
+	else
+		bits = 0xf00000;
+	switch (data[0]) {
+	case INSN_CONFIG_DIO_INPUT:
+		s->io_bits &= ~bits;
+		break;
+	case INSN_CONFIG_DIO_OUTPUT:
+		s->io_bits |= bits;
+		break;
+	case INSN_CONFIG_DIO_QUERY:
+		data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
+		return insn->n;
+		break;
+	default:
+		return -EINVAL;
+	}
+	dio200_subdev_8255_set_dir(dev, s);
+	return 1;
+}
+
+/*
+ * This function initializes an '8255' DIO subdevice.
+ *
+ * offset is the offset to the 8255 chip.
+ */
+static int dio200_subdev_8255_init(struct comedi_device *dev,
+				   struct comedi_subdevice *s,
+				   unsigned int offset)
+{
+	struct dio200_subdev_8255 *subpriv;
+
+	subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
+	if (!subpriv)
+		return -ENOMEM;
+	subpriv->ofs = offset;
+	s->private = subpriv;
+	s->type = COMEDI_SUBD_DIO;
+	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+	s->n_chan = 24;
+	s->range_table = &range_digital;
+	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;
+}
+
+/*
+ * This function cleans up an '8255' DIO subdevice.
+ */
+static void dio200_subdev_8255_cleanup(struct comedi_device *dev,
+				       struct comedi_subdevice *s)
+{
+	struct dio200_subdev_8255 *subpriv = s->private;
+
+	kfree(subpriv);
+}
+
+/*
+ * Handle 'insn_read' for a timer subdevice.
+ */
+static int dio200_subdev_timer_read(struct comedi_device *dev,
+				    struct comedi_subdevice *s,
+				    struct comedi_insn *insn,
+				    unsigned int *data)
+{
+	unsigned int n;
+
+	for (n = 0; n < insn->n; n++)
+		data[n] = dio200_read32(dev, DIO200_TS_COUNT);
+	return n;
+}
+
+/*
+ * Reset timer subdevice.
+ */
+static void dio200_subdev_timer_reset(struct comedi_device *dev,
+				      struct comedi_subdevice *s)
+{
+	unsigned int clock;
+
+	clock = dio200_read32(dev, DIO200_TS_CONFIG) & TS_CONFIG_CLK_SRC_MASK;
+	dio200_write32(dev, DIO200_TS_CONFIG, clock | TS_CONFIG_RESET);
+	dio200_write32(dev, DIO200_TS_CONFIG, clock);
+}
+
+/*
+ * Get timer subdevice clock source and period.
+ */
+static void dio200_subdev_timer_get_clock_src(struct comedi_device *dev,
+					      struct comedi_subdevice *s,
+					      unsigned int *src,
+					      unsigned int *period)
+{
+	unsigned int clk;
+
+	clk = dio200_read32(dev, DIO200_TS_CONFIG) & TS_CONFIG_CLK_SRC_MASK;
+	*src = clk;
+	*period = (clk < ARRAY_SIZE(ts_clock_period)) ?
+		  ts_clock_period[clk] : 0;
+}
+
+/*
+ * Set timer subdevice clock source.
+ */
+static int dio200_subdev_timer_set_clock_src(struct comedi_device *dev,
+					     struct comedi_subdevice *s,
+					     unsigned int src)
+{
+	if (src > TS_CONFIG_MAX_CLK_SRC)
+		return -EINVAL;
+	dio200_write32(dev, DIO200_TS_CONFIG, src);
+	return 0;
+}
+
+/*
+ * Handle 'insn_config' for a timer subdevice.
+ */
+static int dio200_subdev_timer_config(struct comedi_device *dev,
+				      struct comedi_subdevice *s,
+				      struct comedi_insn *insn,
+				      unsigned int *data)
+{
+	int ret = 0;
+
+	switch (data[0]) {
+	case INSN_CONFIG_RESET:
+		dio200_subdev_timer_reset(dev, s);
+		break;
+	case INSN_CONFIG_SET_CLOCK_SRC:
+		ret = dio200_subdev_timer_set_clock_src(dev, s, data[1]);
+		if (ret < 0)
+			ret = -EINVAL;
+		break;
+	case INSN_CONFIG_GET_CLOCK_SRC:
+		dio200_subdev_timer_get_clock_src(dev, s, &data[1], &data[2]);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret < 0 ? ret : insn->n;
+}
+
+/*
+ * This function initializes a timer subdevice.
+ *
+ * Uses the timestamp timer registers.  There is only one timestamp timer.
+ */
+static int dio200_subdev_timer_init(struct comedi_device *dev,
+				    struct comedi_subdevice *s)
+{
+	s->type = COMEDI_SUBD_TIMER;
+	s->subdev_flags = SDF_READABLE | SDF_LSAMPL;
+	s->n_chan = 1;
+	s->maxdata = 0xFFFFFFFF;
+	s->insn_read = dio200_subdev_timer_read;
+	s->insn_config = dio200_subdev_timer_config;
+	return 0;
+}
+
+/*
+ * This function cleans up a timer subdevice.
+ */
+static void dio200_subdev_timer_cleanup(struct comedi_device *dev,
+					struct comedi_subdevice *s)
+{
+	/* Nothing to do. */
+}
+
+/*
+ * This function does some special set-up for the PCIe boards
+ * PCIe215, PCIe236, PCIe296.
+ */
+static int dio200_pcie_board_setup(struct comedi_device *dev)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	void __iomem *brbase;
+	resource_size_t brlen;
+
+	/*
+	 * The board uses Altera Cyclone IV with PCI-Express hard IP.
+	 * The FPGA configuration has the PCI-Express Avalon-MM Bridge
+	 * Control registers in PCI BAR 0, offset 0, and the length of
+	 * these registers is 0x4000.
+	 *
+	 * We need to write 0x80 to the "Avalon-MM to PCI-Express Interrupt
+	 * Enable" register at offset 0x50 to allow generation of PCIe
+	 * interrupts when RXmlrq_i is asserted in the SOPC Builder system.
+	 */
+	brlen = pci_resource_len(pcidev, 0);
+	if (brlen < 0x4000 ||
+			!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) {
+		dev_err(dev->class_dev, "error! bad PCI region!\n");
+		return -EINVAL;
+	}
+	brbase = ioremap_nocache(pci_resource_start(pcidev, 0), brlen);
+	if (!brbase) {
+		dev_err(dev->class_dev, "error! failed to map registers!\n");
+		return -ENOMEM;
+	}
+	writel(0x80, brbase + 0x50);
+	iounmap(brbase);
+	/* Enable "enhanced" features of board. */
+	dio200_write8(dev, DIO200_ENHANCE, 1);
+	return 0;
+}
+
 static void dio200_report_attach(struct comedi_device *dev, unsigned int irq)
 {
 	const struct dio200_board *thisboard = comedi_board(dev);
+	struct dio200_private *devpriv = dev->private;
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	char tmpbuf[60];
 	int tmplen;
 
 	if (is_isa_board(thisboard))
 		tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
-				   "(base %#lx) ", dev->iobase);
+				   "(base %#lx) ", devpriv->io.u.iobase);
 	else if (is_pci_board(thisboard))
 		tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
 				   "(pci %s) ", pci_name(pcidev));
@@ -1232,20 +1796,18 @@ static void dio200_report_attach(struct comedi_device *dev, unsigned int irq)
 	dev_info(dev->class_dev, "%s %sattached\n", dev->board_name, tmpbuf);
 }
 
-static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase,
-				unsigned int irq, unsigned long req_irq_flags)
+static int dio200_common_attach(struct comedi_device *dev, unsigned int irq,
+				unsigned long req_irq_flags)
 {
 	const struct dio200_board *thisboard = comedi_board(dev);
 	struct dio200_private *devpriv = dev->private;
-	const struct dio200_layout_struct *layout =
-		&dio200_layouts[thisboard->layout];
+	const struct dio200_layout *layout = dio200_board_layout(thisboard);
 	struct comedi_subdevice *s;
 	int sdx;
 	unsigned int n;
 	int ret;
 
 	devpriv->intr_sd = -1;
-	dev->iobase = iobase;
 	dev->board_name = thisboard->name;
 
 	ret = comedi_alloc_subdevices(dev, layout->n_subdevs);
@@ -1257,16 +1819,15 @@ static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase,
 		switch (layout->sdtype[n]) {
 		case sd_8254:
 			/* counter subdevice (8254) */
-			ret = dio200_subdev_8254_init(dev, s, iobase,
-						      layout->sdinfo[n],
-						      layout->has_clk_gat_sce);
+			ret = dio200_subdev_8254_init(dev, s,
+						      layout->sdinfo[n]);
 			if (ret < 0)
 				return ret;
 			break;
 		case sd_8255:
 			/* digital i/o subdevice (8255) */
-			ret = subdev_8255_init(dev, s, NULL,
-					       iobase + layout->sdinfo[n]);
+			ret = dio200_subdev_8255_init(dev, s,
+						      layout->sdinfo[n]);
 			if (ret < 0)
 				return ret;
 			break;
@@ -1274,11 +1835,9 @@ static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase,
 			/* 'INTERRUPT' subdevice */
 			if (irq) {
 				ret = dio200_subdev_intr_init(dev, s,
-							      iobase +
 							      DIO200_INT_SCE,
-							      layout->sdinfo[n],
-							      layout->
-							      has_int_sce);
+							      layout->sdinfo[n]
+							     );
 				if (ret < 0)
 					return ret;
 				devpriv->intr_sd = n;
@@ -1286,6 +1845,16 @@ static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase,
 				s->type = COMEDI_SUBD_UNUSED;
 			}
 			break;
+		case sd_timer:
+			/* Only on PCIe boards. */
+			if (DO_PCI) {
+				ret = dio200_subdev_timer_init(dev, s);
+				if (ret < 0)
+					return ret;
+			} else {
+				s->type = COMEDI_SUBD_UNUSED;
+			}
+			break;
 		default:
 			s->type = COMEDI_SUBD_UNUSED;
 			break;
@@ -1307,24 +1876,6 @@ static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase,
 	return 1;
 }
 
-static int dio200_pci_common_attach(struct comedi_device *dev,
-				    struct pci_dev *pci_dev)
-{
-	unsigned long iobase;
-	int ret;
-
-	comedi_set_hw_dev(dev, &pci_dev->dev);
-
-	ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
-	if (ret < 0) {
-		dev_err(dev->class_dev,
-			"error! cannot enable PCI device and request regions!\n");
-		return ret;
-	}
-	iobase = pci_resource_start(pci_dev, 2);
-	return dio200_common_attach(dev, iobase, pci_dev->irq, IRQF_SHARED);
-}
-
 /*
  * Attach is called by the Comedi core to configure the driver
  * for a particular board.  If you specified a board_name array
@@ -1334,15 +1885,15 @@ static int dio200_pci_common_attach(struct comedi_device *dev,
 static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct dio200_board *thisboard = comedi_board(dev);
+	struct dio200_private *devpriv;
 	int ret;
 
 	dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach\n");
 
-	ret = alloc_private(dev, sizeof(struct dio200_private));
-	if (ret < 0) {
-		dev_err(dev->class_dev, "error! out of memory!\n");
-		return ret;
-	}
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	/* Process options and reserve resources according to bus type. */
 	if (is_isa_board(thisboard)) {
@@ -1351,17 +1902,17 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 		iobase = it->options[0];
 		irq = it->options[1];
-		ret = dio200_request_region(dev, iobase, DIO200_IO_SIZE);
+		ret = dio200_request_region(dev, iobase, thisboard->mainsize);
 		if (ret < 0)
 			return ret;
-		return dio200_common_attach(dev, iobase, irq, 0);
+		devpriv->io.u.iobase = iobase;
+		devpriv->io.regtype = io_regtype;
+		return dio200_common_attach(dev, irq, 0);
 	} else if (is_pci_board(thisboard)) {
-		struct pci_dev *pci_dev;
-
-		pci_dev = dio200_find_pci_dev(dev, it);
-		if (!pci_dev)
-			return -EIO;
-		return dio200_pci_common_attach(dev, pci_dev);
+		dev_err(dev->class_dev,
+			"Manual configuration of PCI board '%s' is not supported\n",
+			thisboard->name);
+		return -EIO;
 	} else {
 		dev_err(dev->class_dev, DIO200_DRIVER_NAME
 			": BUG! cannot determine board type!\n");
@@ -1370,13 +1921,18 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 }
 
 /*
- * The attach_pci hook (if non-NULL) is called at PCI probe time in preference
- * to the "manual" attach hook.  dev->board_ptr is NULL on entry.  There should
- * be a board entry matching the supplied PCI device.
+ * The auto_attach hook is called at PCI probe time via
+ * comedi_pci_auto_config().  dev->board_ptr is NULL on entry.
+ * There should be a board entry matching the supplied PCI device.
  */
-static int __devinit dio200_attach_pci(struct comedi_device *dev,
-				       struct pci_dev *pci_dev)
+static int dio200_auto_attach(struct comedi_device *dev,
+					unsigned long context_unused)
 {
+	struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
+	const struct dio200_board *thisboard;
+	struct dio200_private *devpriv;
+	resource_size_t base, len;
+	unsigned int bar;
 	int ret;
 
 	if (!DO_PCI)
@@ -1384,38 +1940,71 @@ static int __devinit dio200_attach_pci(struct comedi_device *dev,
 
 	dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach pci %s\n",
 		 pci_name(pci_dev));
-	ret = alloc_private(dev, sizeof(struct dio200_private));
-	if (ret < 0) {
-		dev_err(dev->class_dev, "error! out of memory!\n");
-		return ret;
-	}
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
 	dev->board_ptr = dio200_find_pci_board(pci_dev);
 	if (dev->board_ptr == NULL) {
 		dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
 		return -EINVAL;
 	}
-	/*
-	 * Need to 'get' the PCI device to match the 'put' in dio200_detach().
-	 * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
-	 * support for manual attachment of PCI devices via dio200_attach()
-	 * has been removed.
-	 */
-	pci_dev_get(pci_dev);
-	return dio200_pci_common_attach(dev, pci_dev);
+	thisboard = comedi_board(dev);
+	ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
+	if (ret < 0) {
+		dev_err(dev->class_dev,
+			"error! cannot enable PCI device and request regions!\n");
+		return ret;
+	}
+	bar = thisboard->mainbar;
+	base = pci_resource_start(pci_dev, bar);
+	len = pci_resource_len(pci_dev, bar);
+	if (len < thisboard->mainsize) {
+		dev_err(dev->class_dev, "error! PCI region size too small!\n");
+		return -EINVAL;
+	}
+	if ((pci_resource_flags(pci_dev, bar) & IORESOURCE_MEM) != 0) {
+		devpriv->io.u.membase = ioremap_nocache(base, len);
+		if (!devpriv->io.u.membase) {
+			dev_err(dev->class_dev,
+				"error! cannot remap registers\n");
+			return -ENOMEM;
+		}
+		devpriv->io.regtype = mmio_regtype;
+	} else {
+		devpriv->io.u.iobase = (unsigned long)base;
+		devpriv->io.regtype = io_regtype;
+	}
+	switch (thisboard->model)
+	{
+	case pcie215_model:
+	case pcie236_model:
+	case pcie296_model:
+		ret = dio200_pcie_board_setup(dev);
+		if (ret < 0)
+			return ret;
+		break;
+	default:
+		break;
+	}
+	return dio200_common_attach(dev, pci_dev->irq, IRQF_SHARED);
 }
 
 static void dio200_detach(struct comedi_device *dev)
 {
 	const struct dio200_board *thisboard = comedi_board(dev);
-	const struct dio200_layout_struct *layout;
+	struct dio200_private *devpriv = dev->private;
+	const struct dio200_layout *layout;
 	unsigned n;
 
-	if (!thisboard)
+	if (!thisboard || !devpriv)
 		return;
 	if (dev->irq)
 		free_irq(dev->irq, dev);
 	if (dev->subdevices) {
-		layout = &dio200_layouts[thisboard->layout];
+		layout = dio200_board_layout(thisboard);
 		for (n = 0; n < dev->n_subdevices; n++) {
 			struct comedi_subdevice *s = &dev->subdevices[n];
 			switch (layout->sdtype[n]) {
@@ -1423,25 +2012,33 @@ static void dio200_detach(struct comedi_device *dev)
 				dio200_subdev_8254_cleanup(dev, s);
 				break;
 			case sd_8255:
-				subdev_8255_cleanup(dev, s);
+				dio200_subdev_8255_cleanup(dev, s);
 				break;
 			case sd_intr:
 				dio200_subdev_intr_cleanup(dev, s);
 				break;
+			case sd_timer:
+				/* Only on PCIe boards. */
+				if (DO_PCI)
+					dio200_subdev_timer_cleanup(dev, s);
+				break;
 			default:
 				break;
 			}
 		}
 	}
 	if (is_isa_board(thisboard)) {
-		if (dev->iobase)
-			release_region(dev->iobase, DIO200_IO_SIZE);
+		if (devpriv->io.regtype == io_regtype)
+			release_region(devpriv->io.u.iobase,
+				       thisboard->mainsize);
 	} else if (is_pci_board(thisboard)) {
 		struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 		if (pcidev) {
-			if (dev->iobase)
+			if (devpriv->io.regtype != no_regtype) {
+				if (devpriv->io.regtype == mmio_regtype)
+					iounmap(devpriv->io.u.membase);
 				comedi_pci_disable(pcidev);
-			pci_dev_put(pcidev);
+			}
 		}
 	}
 }
@@ -1456,7 +2053,7 @@ static struct comedi_driver amplc_dio200_driver = {
 	.driver_name = DIO200_DRIVER_NAME,
 	.module = THIS_MODULE,
 	.attach = dio200_attach,
-	.attach_pci = dio200_attach_pci,
+	.auto_attach = dio200_auto_attach,
 	.detach = dio200_detach,
 	.board_name = &dio200_boards[0].name,
 	.offset = sizeof(struct dio200_board),
@@ -1467,19 +2064,22 @@ static struct comedi_driver amplc_dio200_driver = {
 static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE236) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE215) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE296) },
 	{0}
 };
 
 MODULE_DEVICE_TABLE(pci, dio200_pci_table);
 
-static int __devinit amplc_dio200_pci_probe(struct pci_dev *dev,
+static int amplc_dio200_pci_probe(struct pci_dev *dev,
 						   const struct pci_device_id
 						   *ent)
 {
 	return comedi_pci_auto_config(dev, &amplc_dio200_driver);
 }
 
-static void __devexit amplc_dio200_pci_remove(struct pci_dev *dev)
+static void amplc_dio200_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -1488,7 +2088,7 @@ static struct pci_driver amplc_dio200_pci_driver = {
 	.name = DIO200_DRIVER_NAME,
 	.id_table = dio200_pci_table,
 	.probe = &amplc_dio200_pci_probe,
-	.remove = __devexit_p(&amplc_dio200_pci_remove)
+	.remove = &amplc_dio200_pci_remove
 };
 module_comedi_pci_driver(amplc_dio200_driver, amplc_dio200_pci_driver);
 #else
diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
index 4e4f3c1..2898354 100644
--- a/drivers/staging/comedi/drivers/amplc_pc236.c
+++ b/drivers/staging/comedi/drivers/amplc_pc236.c
@@ -66,7 +66,6 @@ unused.
 #define DO_PCI	IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI)
 
 /* PCI236 PCI configuration register information */
-#define PCI_VENDOR_ID_AMPLICON 0x14dc
 #define PCI_DEVICE_ID_AMPLICON_PCI236 0x0009
 #define PCI_DEVICE_ID_INVALID 0xffff
 
@@ -332,28 +331,13 @@ static int pc236_intr_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: */
+	/* Step 3: check it arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
-	if (cmd->scan_begin_arg != 0) {
-		cmd->scan_begin_arg = 0;
-		err++;
-	}
-	if (cmd->convert_arg != 0) {
-		cmd->convert_arg = 0;
-		err++;
-	}
-	if (cmd->scan_end_arg != 1) {
-		cmd->scan_end_arg = 1;
-		err++;
-	}
-	if (cmd->stop_arg != 0) {
-		cmd->stop_arg = 0;
-		err++;
-	}
+	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;
@@ -505,14 +489,16 @@ static int pc236_pci_common_attach(struct comedi_device *dev,
 static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct pc236_board *thisboard = comedi_board(dev);
+	struct pc236_private *devpriv;
 	int ret;
 
 	dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach\n");
-	ret = alloc_private(dev, sizeof(struct pc236_private));
-	if (ret < 0) {
-		dev_err(dev->class_dev, "error! out of memory!\n");
-		return ret;
-	}
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
 	/* Process options according to bus type. */
 	if (is_isa_board(thisboard)) {
 		unsigned long iobase = it->options[0];
@@ -536,25 +522,27 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 }
 
 /*
- * The attach_pci hook (if non-NULL) is called at PCI probe time in preference
- * to the "manual" attach hook.  dev->board_ptr is NULL on entry.  There should
- * be a board entry matching the supplied PCI device.
+ * The auto_attach hook is called at PCI probe time via
+ * comedi_pci_auto_config().  dev->board_ptr is NULL on entry.
+ * There should be a board entry matching the supplied PCI device.
  */
-static int __devinit pc236_attach_pci(struct comedi_device *dev,
-				      struct pci_dev *pci_dev)
+static int pc236_auto_attach(struct comedi_device *dev,
+				       unsigned long context_unused)
 {
-	int ret;
+	struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
+	struct pc236_private *devpriv;
 
 	if (!DO_PCI)
 		return -EINVAL;
 
 	dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach pci %s\n",
 		 pci_name(pci_dev));
-	ret = alloc_private(dev, sizeof(struct pc236_private));
-	if (ret < 0) {
-		dev_err(dev->class_dev, "error! out of memory!\n");
-		return ret;
-	}
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
 	dev->board_ptr = pc236_find_pci_board(pci_dev);
 	if (dev->board_ptr == NULL) {
 		dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
@@ -605,7 +593,7 @@ static struct comedi_driver amplc_pc236_driver = {
 	.driver_name = PC236_DRIVER_NAME,
 	.module = THIS_MODULE,
 	.attach = pc236_attach,
-	.attach_pci = pc236_attach_pci,
+	.auto_attach = pc236_auto_attach,
 	.detach = pc236_detach,
 	.board_name = &pc236_boards[0].name,
 	.offset = sizeof(struct pc236_board),
@@ -620,13 +608,13 @@ static DEFINE_PCI_DEVICE_TABLE(pc236_pci_table) = {
 
 MODULE_DEVICE_TABLE(pci, pc236_pci_table);
 
-static int __devinit amplc_pc236_pci_probe(struct pci_dev *dev,
+static int amplc_pc236_pci_probe(struct pci_dev *dev,
 					   const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &amplc_pc236_driver);
 }
 
-static void __devexit amplc_pc236_pci_remove(struct pci_dev *dev)
+static void amplc_pc236_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -635,7 +623,7 @@ static struct pci_driver amplc_pc236_pci_driver = {
 	.name = PC236_DRIVER_NAME,
 	.id_table = pc236_pci_table,
 	.probe = &amplc_pc236_pci_probe,
-	.remove = __devexit_p(&amplc_pc236_pci_remove)
+	.remove = &amplc_pc236_pci_remove
 };
 
 module_comedi_pci_driver(amplc_pc236_driver, amplc_pc236_pci_driver);
diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
index d0a4c44..dfbff77 100644
--- a/drivers/staging/comedi/drivers/amplc_pc263.c
+++ b/drivers/staging/comedi/drivers/amplc_pc263.c
@@ -52,7 +52,6 @@ The state of the outputs can be read.
 #define DO_PCI	IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI)
 
 /* PCI263 PCI configuration register information */
-#define PCI_VENDOR_ID_AMPLICON 0x14dc
 #define PCI_DEVICE_ID_AMPLICON_PCI263 0x000c
 #define PCI_DEVICE_ID_INVALID 0xffff
 
@@ -291,17 +290,21 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		return -EINVAL;
 	}
 }
+
 /*
- * The attach_pci hook (if non-NULL) is called at PCI probe time in preference
- * to the "manual" attach hook.  dev->board_ptr is NULL on entry.  There should
- * be a board entry matching the supplied PCI device.
+ * The auto_attach hook is called at PCI probe time via
+ * comedi_pci_auto_config().  dev->board_ptr is NULL on entry.
+ * There should be a board entry matching the supplied PCI device.
  */
-static int __devinit pc263_attach_pci(struct comedi_device *dev,
-				      struct pci_dev *pci_dev)
+static int pc263_auto_attach(struct comedi_device *dev,
+				       unsigned long context_unused)
 {
+	struct pci_dev *pci_dev;
+
 	if (!DO_PCI)
 		return -EINVAL;
 
+	pci_dev = comedi_to_pci_dev(dev);
 	dev_info(dev->class_dev, PC263_DRIVER_NAME ": attach pci %s\n",
 		 pci_name(pci_dev));
 	dev->board_ptr = pc263_find_pci_board(pci_dev);
@@ -348,7 +351,7 @@ static struct comedi_driver amplc_pc263_driver = {
 	.driver_name = PC263_DRIVER_NAME,
 	.module = THIS_MODULE,
 	.attach = pc263_attach,
-	.attach_pci = pc263_attach_pci,
+	.auto_attach = pc263_auto_attach,
 	.detach = pc263_detach,
 	.board_name = &pc263_boards[0].name,
 	.offset = sizeof(struct pc263_board),
@@ -362,14 +365,14 @@ static DEFINE_PCI_DEVICE_TABLE(pc263_pci_table) = {
 };
 MODULE_DEVICE_TABLE(pci, pc263_pci_table);
 
-static int __devinit amplc_pc263_pci_probe(struct pci_dev *dev,
+static int amplc_pc263_pci_probe(struct pci_dev *dev,
 						  const struct pci_device_id
 						  *ent)
 {
 	return comedi_pci_auto_config(dev, &amplc_pc263_driver);
 }
 
-static void __devexit amplc_pc263_pci_remove(struct pci_dev *dev)
+static void amplc_pc263_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -378,7 +381,7 @@ static struct pci_driver amplc_pc263_pci_driver = {
 	.name = PC263_DRIVER_NAME,
 	.id_table = pc263_pci_table,
 	.probe = &amplc_pc263_pci_probe,
-	.remove = __devexit_p(&amplc_pc263_pci_remove)
+	.remove = &amplc_pc263_pci_remove
 };
 module_comedi_pci_driver(amplc_pc263_driver, amplc_pc263_pci_driver);
 #else
diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
index 1f65ec4..6e2566a 100644
--- a/drivers/staging/comedi/drivers/amplc_pci224.c
+++ b/drivers/staging/comedi/drivers/amplc_pci224.c
@@ -116,7 +116,6 @@ Caveats:
 /*
  * PCI IDs.
  */
-#define PCI_VENDOR_ID_AMPLICON 0x14dc
 #define PCI_DEVICE_ID_AMPLICON_PCI224 0x0007
 #define PCI_DEVICE_ID_AMPLICON_PCI234 0x0008
 #define PCI_DEVICE_ID_INVALID 0xffff
@@ -758,76 +757,58 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 	if (err)
 		return 2;
 
-	/* Step 3: make sure arguments are trivially compatible. */
+	/* Step 3: check if arguments are trivially valid */
 
 	switch (cmd->start_src) {
 	case TRIG_INT:
-		if (cmd->start_arg != 0) {
-			cmd->start_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 		break;
 	case TRIG_EXT:
 		/* Force to external trigger 0. */
 		if ((cmd->start_arg & ~CR_FLAGS_MASK) != 0) {
 			cmd->start_arg = COMBINE(cmd->start_arg, 0,
 						 ~CR_FLAGS_MASK);
-			err++;
+			err |= -EINVAL;
 		}
 		/* The only flag allowed is CR_EDGE, which is ignored. */
 		if ((cmd->start_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
 			cmd->start_arg = COMBINE(cmd->start_arg, 0,
 						 CR_FLAGS_MASK & ~CR_EDGE);
-			err++;
+			err |= -EINVAL;
 		}
 		break;
 	}
 
 	switch (cmd->scan_begin_src) {
 	case TRIG_TIMER:
-		if (cmd->scan_begin_arg > MAX_SCAN_PERIOD) {
-			cmd->scan_begin_arg = MAX_SCAN_PERIOD;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
+						 MAX_SCAN_PERIOD);
+
 		tmp = cmd->chanlist_len * CONVERT_PERIOD;
 		if (tmp < MIN_SCAN_PERIOD)
 			tmp = MIN_SCAN_PERIOD;
-
-		if (cmd->scan_begin_arg < tmp) {
-			cmd->scan_begin_arg = tmp;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, tmp);
 		break;
 	case TRIG_EXT:
 		/* Force to external trigger 0. */
 		if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
 			cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
 						      ~CR_FLAGS_MASK);
-			err++;
+			err |= -EINVAL;
 		}
 		/* Only allow flags CR_EDGE and CR_INVERT.  Ignore CR_EDGE. */
 		if ((cmd->scan_begin_arg & CR_FLAGS_MASK &
 		     ~(CR_EDGE | CR_INVERT)) != 0) {
 			cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
-						      CR_FLAGS_MASK & ~(CR_EDGE
-									|
-									CR_INVERT));
-			err++;
+						      CR_FLAGS_MASK &
+						      ~(CR_EDGE | CR_INVERT));
+			err |= -EINVAL;
 		}
 		break;
 	}
 
-	/* cmd->convert_src == TRIG_NOW */
-	if (cmd->convert_arg != 0) {
-		cmd->convert_arg = 0;
-		err++;
-	}
-
-	/* cmd->scan_end_arg == TRIG_COUNT */
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 
 	switch (cmd->stop_src) {
 	case TRIG_COUNT:
@@ -838,7 +819,7 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 		if ((cmd->stop_arg & ~CR_FLAGS_MASK) != 0) {
 			cmd->stop_arg = COMBINE(cmd->stop_arg, 0,
 						~CR_FLAGS_MASK);
-			err++;
+			err |= -EINVAL;
 		}
 		/* The only flag allowed is CR_EDGE, which is ignored. */
 		if ((cmd->stop_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
@@ -847,10 +828,7 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 		}
 		break;
 	case TRIG_NONE:
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 		break;
 	}
 
@@ -1287,7 +1265,7 @@ static void pci224_report_attach(struct comedi_device *dev, unsigned int irq)
 }
 
 /*
- * Common part of attach and attach_pci.
+ * Common part of attach and auto_attach.
  */
 static int pci224_attach_common(struct comedi_device *dev,
 				struct pci_dev *pci_dev, int *options)
@@ -1443,16 +1421,15 @@ static int pci224_attach_common(struct comedi_device *dev,
 
 static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+	struct pci224_private *devpriv;
 	struct pci_dev *pci_dev;
-	int ret;
 
 	dev_info(dev->class_dev, DRIVER_NAME ": attach\n");
 
-	ret = alloc_private(dev, sizeof(struct pci224_private));
-	if (ret < 0) {
-		dev_err(dev->class_dev, "error! out of memory!\n");
-		return ret;
-	}
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	pci_dev = pci224_find_pci_dev(dev, it);
 	if (!pci_dev)
@@ -1461,19 +1438,19 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	return pci224_attach_common(dev, pci_dev, it->options);
 }
 
-static int __devinit
-pci224_attach_pci(struct comedi_device *dev, struct pci_dev *pci_dev)
+static int
+pci224_auto_attach(struct comedi_device *dev, unsigned long context_unused)
 {
-	int ret;
+	struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
+	struct pci224_private *devpriv;
 
-	dev_info(dev->class_dev, DRIVER_NAME ": attach_pci %s\n",
+	dev_info(dev->class_dev, DRIVER_NAME ": attach pci %s\n",
 		 pci_name(pci_dev));
 
-	ret = alloc_private(dev, sizeof(struct pci224_private));
-	if (ret < 0) {
-		dev_err(dev->class_dev, "error! out of memory!\n");
-		return ret;
-	}
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	dev->board_ptr = pci224_find_pci_board(pci_dev);
 	if (dev->board_ptr == NULL) {
@@ -1522,20 +1499,20 @@ static struct comedi_driver amplc_pci224_driver = {
 	.module		= THIS_MODULE,
 	.attach		= pci224_attach,
 	.detach		= pci224_detach,
-	.attach_pci	= pci224_attach_pci,
+	.auto_attach	= pci224_auto_attach,
 	.board_name	= &pci224_boards[0].name,
 	.offset		= sizeof(struct pci224_board),
 	.num_names	= ARRAY_SIZE(pci224_boards),
 };
 
-static int __devinit amplc_pci224_pci_probe(struct pci_dev *dev,
+static int amplc_pci224_pci_probe(struct pci_dev *dev,
 						   const struct pci_device_id
 						   *ent)
 {
 	return comedi_pci_auto_config(dev, &amplc_pci224_driver);
 }
 
-static void __devexit amplc_pci224_pci_remove(struct pci_dev *dev)
+static void amplc_pci224_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -1551,7 +1528,7 @@ static struct pci_driver amplc_pci224_pci_driver = {
 	.name		= "amplc_pci224",
 	.id_table	= amplc_pci224_pci_table,
 	.probe		= amplc_pci224_pci_probe,
-	.remove		= __devexit_p(amplc_pci224_pci_remove),
+	.remove		= amplc_pci224_pci_remove,
 };
 module_comedi_pci_driver(amplc_pci224_driver, amplc_pci224_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
index bd8fb87..366c68b 100644
--- a/drivers/staging/comedi/drivers/amplc_pci230.c
+++ b/drivers/staging/comedi/drivers/amplc_pci230.c
@@ -198,7 +198,6 @@ for (or detection of) various hardware problems added by Ian Abbott.
 #include "8255.h"
 
 /* PCI230 PCI configuration register information */
-#define PCI_VENDOR_ID_AMPLICON 0x14dc
 #define PCI_DEVICE_ID_PCI230 0x0000
 #define PCI_DEVICE_ID_PCI260 0x0006
 #define PCI_DEVICE_ID_INVALID 0xffff
@@ -1000,14 +999,10 @@ static int pci230_ao_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* Step 3: make sure arguments are trivially compatible.
-	 * "invalid argument" returned by comedilib to user mode process
-	 * if this fails. */
+	/* Step 3: check if arguments are trivially valid */
+
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
 #define MAX_SPEED_AO	8000	/* 8000 ns => 125 kHz */
 #define MIN_SPEED_AO	4294967295u	/* 4294967295ns = 4.29s */
 			/*- Comedi limit due to unsigned int cmd.  Driver limit
@@ -1016,14 +1011,10 @@ static int pci230_ao_cmdtest(struct comedi_device *dev,
 
 	switch (cmd->scan_begin_src) {
 	case TRIG_TIMER:
-		if (cmd->scan_begin_arg < MAX_SPEED_AO) {
-			cmd->scan_begin_arg = MAX_SPEED_AO;
-			err++;
-		}
-		if (cmd->scan_begin_arg > MIN_SPEED_AO) {
-			cmd->scan_begin_arg = MIN_SPEED_AO;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						 MAX_SPEED_AO);
+		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
+						 MIN_SPEED_AO);
 		break;
 	case TRIG_EXT:
 		/* External trigger - for PCI230+ hardware version 2 onwards. */
@@ -1031,37 +1022,27 @@ static int pci230_ao_cmdtest(struct comedi_device *dev,
 		if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
 			cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
 						      ~CR_FLAGS_MASK);
-			err++;
+			err |= -EINVAL;
 		}
 		/* The only flags allowed are CR_EDGE and CR_INVERT.  The
 		 * CR_EDGE flag is ignored. */
 		if ((cmd->scan_begin_arg
 		     & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
-			cmd->scan_begin_arg =
-			    COMBINE(cmd->scan_begin_arg, 0,
-				    CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
-			err++;
+			cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
+						      CR_FLAGS_MASK &
+						      ~(CR_EDGE | CR_INVERT));
+			err |= -EINVAL;
 		}
 		break;
 	default:
-		if (cmd->scan_begin_arg != 0) {
-			cmd->scan_begin_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 		break;
 	}
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_NONE) {
-		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+	if (cmd->stop_src == TRIG_NONE)
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -1619,14 +1600,10 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* Step 3: make sure arguments are trivially compatible.
-	 * "invalid argument" returned by comedilib to user mode process
-	 * if this fails. */
+	/* Step 3: check if arguments are trivially valid */
+
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
 #define MAX_SPEED_AI_SE		3200	/* PCI230 SE:   3200 ns => 312.5 kHz */
 #define MAX_SPEED_AI_DIFF	8000	/* PCI230 DIFF: 8000 ns => 125 kHz */
 #define MAX_SPEED_AI_PLUS	4000	/* PCI230+:     4000 ns => 250 kHz */
@@ -1657,14 +1634,10 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
 			max_speed_ai = MAX_SPEED_AI_PLUS;
 		}
 
-		if (cmd->convert_arg < max_speed_ai) {
-			cmd->convert_arg = max_speed_ai;
-			err++;
-		}
-		if (cmd->convert_arg > MIN_SPEED_AI) {
-			cmd->convert_arg = MIN_SPEED_AI;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+						 max_speed_ai);
+		err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
+						 MIN_SPEED_AI);
 	} else if (cmd->convert_src == TRIG_EXT) {
 		/*
 		 * external trigger
@@ -1679,46 +1652,33 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
 			if ((cmd->convert_arg & ~CR_FLAGS_MASK) != 0) {
 				cmd->convert_arg = COMBINE(cmd->convert_arg, 0,
 							   ~CR_FLAGS_MASK);
-				err++;
+				err |= -EINVAL;
 			}
 			/* The only flags allowed are CR_INVERT and CR_EDGE.
 			 * CR_EDGE is required. */
 			if ((cmd->convert_arg & (CR_FLAGS_MASK & ~CR_INVERT))
 			    != CR_EDGE) {
 				/* Set CR_EDGE, preserve CR_INVERT. */
-				cmd->convert_arg =
-				    COMBINE(cmd->start_arg, (CR_EDGE | 0),
-					    CR_FLAGS_MASK & ~CR_INVERT);
-				err++;
+				cmd->convert_arg = COMBINE(cmd->start_arg,
+							   (CR_EDGE | 0),
+							   CR_FLAGS_MASK &
+							   ~CR_INVERT);
+				err |= -EINVAL;
 			}
 		} else {
 			/* Backwards compatibility with previous versions. */
 			/* convert_arg == 0 => trigger on -ve edge. */
 			/* convert_arg == 1 => trigger on +ve edge. */
-			if (cmd->convert_arg > 1) {
-				/* Default to trigger on +ve edge. */
-				cmd->convert_arg = 1;
-				err++;
-			}
+			err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 1);
 		}
 	} else {
-		if (cmd->convert_arg != 0) {
-			cmd->convert_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 	}
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 
-	if (cmd->stop_src == TRIG_NONE) {
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	if (cmd->stop_src == TRIG_NONE)
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (cmd->scan_begin_src == TRIG_EXT) {
 		/* external "trigger" to begin each scan
@@ -1727,24 +1687,21 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
 		if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
 			cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
 						      ~CR_FLAGS_MASK);
-			err++;
+			err |= -EINVAL;
 		}
 		/* The only flag allowed is CR_EDGE, which is ignored. */
 		if ((cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
 			cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
 						      CR_FLAGS_MASK & ~CR_EDGE);
-			err++;
+			err |= -EINVAL;
 		}
 	} else if (cmd->scan_begin_src == TRIG_TIMER) {
 		/* N.B. cmd->convert_arg is also TRIG_TIMER */
 		if (!pci230_ai_check_scan_period(cmd))
-			err++;
+			err |= -EINVAL;
 
 	} else {
-		if (cmd->scan_begin_arg != 0) {
-			cmd->scan_begin_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 	}
 
 	if (err)
@@ -2660,15 +2617,12 @@ static struct pci_dev *pci230_find_pci_dev(struct comedi_device *dev,
 static int pci230_alloc_private(struct comedi_device *dev)
 {
 	struct pci230_private *devpriv;
-	int err;
 
-	/* sets dev->private to allocated memory */
-	err = alloc_private(dev, sizeof(struct pci230_private));
-	if (err) {
-		dev_err(dev->class_dev, "error! out of memory!\n");
-		return err;
-	}
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
 	spin_lock_init(&devpriv->isr_spinlock);
 	spin_lock_init(&devpriv->res_spinlock);
 	spin_lock_init(&devpriv->ai_stop_spinlock);
@@ -2676,7 +2630,7 @@ static int pci230_alloc_private(struct comedi_device *dev)
 	return 0;
 }
 
-/* Common part of attach and attach_pci. */
+/* Common part of attach and auto_attach. */
 static int pci230_attach_common(struct comedi_device *dev,
 				struct pci_dev *pci_dev)
 {
@@ -2836,25 +2790,30 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 	dev_info(dev->class_dev, "amplc_pci230: attach %s %d,%d\n",
 		 thisboard->name, it->options[0], it->options[1]);
-	rc = pci230_alloc_private(dev); /* sets dev->private */
+
+	rc = pci230_alloc_private(dev);
 	if (rc)
 		return rc;
+
 	pci_dev = pci230_find_pci_dev(dev, it);
 	if (!pci_dev)
 		return -EIO;
 	return pci230_attach_common(dev, pci_dev);
 }
 
-static int __devinit pci230_attach_pci(struct comedi_device *dev,
-				       struct pci_dev *pci_dev)
+static int pci230_auto_attach(struct comedi_device *dev,
+					unsigned long context_unused)
 {
+	struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
 	int rc;
 
 	dev_info(dev->class_dev, "amplc_pci230: attach pci %s\n",
 		 pci_name(pci_dev));
-	rc = pci230_alloc_private(dev); /* sets dev->private */
+
+	rc = pci230_alloc_private(dev);
 	if (rc)
 		return rc;
+
 	dev->board_ptr = pci230_find_pci_board(pci_dev);
 	if (dev->board_ptr == NULL) {
 		dev_err(dev->class_dev,
@@ -2891,20 +2850,20 @@ static struct comedi_driver amplc_pci230_driver = {
 	.driver_name	= "amplc_pci230",
 	.module		= THIS_MODULE,
 	.attach		= pci230_attach,
-	.attach_pci	= pci230_attach_pci,
+	.auto_attach	= pci230_auto_attach,
 	.detach		= pci230_detach,
 	.board_name	= &pci230_boards[0].name,
 	.offset		= sizeof(pci230_boards[0]),
 	.num_names	= ARRAY_SIZE(pci230_boards),
 };
 
-static int __devinit amplc_pci230_pci_probe(struct pci_dev *dev,
+static int amplc_pci230_pci_probe(struct pci_dev *dev,
 					    const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &amplc_pci230_driver);
 }
 
-static void __devexit amplc_pci230_pci_remove(struct pci_dev *dev)
+static void amplc_pci230_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -2920,7 +2879,7 @@ static struct pci_driver amplc_pci230_pci_driver = {
 	.name		= "amplc_pci230",
 	.id_table	= amplc_pci230_pci_table,
 	.probe		= amplc_pci230_pci_probe,
-	.remove		= __devexit_p(amplc_pci230_pci_remove)
+	.remove		= amplc_pci230_pci_remove
 };
 module_comedi_pci_driver(amplc_pci230_driver, amplc_pci230_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index 6d81d8b..93731de 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -194,67 +194,41 @@ static int das16cs_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
+
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
 #define MAX_SPEED	10000	/* in nanoseconds */
 #define MIN_SPEED	1000000000	/* in nanoseconds */
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
-		if (cmd->scan_begin_arg < MAX_SPEED) {
-			cmd->scan_begin_arg = MAX_SPEED;
-			err++;
-		}
-		if (cmd->scan_begin_arg > MIN_SPEED) {
-			cmd->scan_begin_arg = MIN_SPEED;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						 MAX_SPEED);
+		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
+						 MIN_SPEED);
 	} else {
 		/* external trigger */
 		/* should be level/edge, hi/lo specification here */
 		/* should specify multiple external triggers */
-		if (cmd->scan_begin_arg > 9) {
-			cmd->scan_begin_arg = 9;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9);
 	}
 	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < MAX_SPEED) {
-			cmd->convert_arg = MAX_SPEED;
-			err++;
-		}
-		if (cmd->convert_arg > MIN_SPEED) {
-			cmd->convert_arg = MIN_SPEED;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+						 MAX_SPEED);
+		err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
+						 MIN_SPEED);
 	} else {
 		/* external trigger */
 		/* see above */
-		if (cmd->convert_arg > 9) {
-			cmd->convert_arg = 9;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 9);
 	}
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (cmd->stop_arg > 0x00ffffff) {
-			cmd->stop_arg = 0x00ffffff;
-			err++;
-		}
-	} else {
-		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+	if (cmd->stop_src == TRIG_COUNT)
+		err |= cfc_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
+	else	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -428,6 +402,7 @@ static int das16cs_attach(struct comedi_device *dev,
 			  struct comedi_devconfig *it)
 {
 	const struct das16cs_board *thisboard;
+	struct das16cs_private *devpriv;
 	struct pcmcia_device *link;
 	struct comedi_subdevice *s;
 	int ret;
@@ -451,8 +426,10 @@ static int das16cs_attach(struct comedi_device *dev,
 		return ret;
 	dev->irq = link->irq;
 
-	if (alloc_private(dev, sizeof(struct das16cs_private)) < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_alloc_subdevices(dev, 3);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index de21a26..aed6863 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -76,9 +76,6 @@ analog triggering on 1602 series
 #include "amcc_s5933.h"
 #include "comedi_fc.h"
 
-/* PCI vendor number of ComputerBoards/MeasurementComputing */
-#define PCI_VENDOR_ID_CB	0x1307
-
 #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 */
@@ -843,49 +840,32 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
 		/* External trigger, only CR_EDGE and CR_INVERT flags allowed */
 		if ((cmd->start_arg
 		     & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
-			cmd->start_arg &=
-			    ~(CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
-			err++;
+			cmd->start_arg &= ~(CR_FLAGS_MASK &
+						~(CR_EDGE | CR_INVERT));
+			err |= -EINVAL;
 		}
 		if (!thisboard->is_1602 && (cmd->start_arg & CR_INVERT)) {
 			cmd->start_arg &= (CR_FLAGS_MASK & ~CR_INVERT);
-			err++;
+			err |= -EINVAL;
 		}
 		break;
 	default:
-		if (cmd->start_arg != 0) {
-			cmd->start_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 		break;
 	}
 
-	if (cmd->scan_begin_src == TRIG_TIMER) {
-		if (cmd->scan_begin_arg <
-		    thisboard->ai_speed * cmd->chanlist_len) {
-			cmd->scan_begin_arg =
-			    thisboard->ai_speed * cmd->chanlist_len;
-			err++;
-		}
-	}
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < thisboard->ai_speed) {
-			cmd->convert_arg = thisboard->ai_speed;
-			err++;
-		}
-	}
+	if (cmd->scan_begin_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+				thisboard->ai_speed * cmd->chanlist_len);
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_NONE) {
-		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	if (cmd->convert_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+						 thisboard->ai_speed);
+
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+	if (cmd->stop_src == TRIG_NONE)
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -1078,31 +1058,18 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->scan_begin_src == TRIG_TIMER) {
-		if (cmd->scan_begin_arg < thisboard->ao_scan_speed) {
-			cmd->scan_begin_arg = thisboard->ao_scan_speed;
-			err++;
-		}
-	}
+	if (cmd->scan_begin_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						 thisboard->ao_scan_speed);
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_NONE) {
-		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+	if (cmd->stop_src == TRIG_NONE)
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -1469,27 +1436,26 @@ static const void *cb_pcidas_find_boardinfo(struct comedi_device *dev,
 	return NULL;
 }
 
-static int cb_pcidas_attach_pci(struct comedi_device *dev,
-				struct pci_dev *pcidev)
+static int cb_pcidas_auto_attach(struct comedi_device *dev,
+					   unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	const struct cb_pcidas_board *thisboard;
 	struct cb_pcidas_private *devpriv;
 	struct comedi_subdevice *s;
 	int i;
 	int ret;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
-
 	thisboard = cb_pcidas_find_boardinfo(dev, pcidev);
 	if (!thisboard)
 		return -ENODEV;
 	dev->board_ptr  = thisboard;
 	dev->board_name = thisboard->name;
 
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_pci_enable(pcidev, dev->board_name);
 	if (ret)
@@ -1656,17 +1622,17 @@ static void cb_pcidas_detach(struct comedi_device *dev)
 static struct comedi_driver cb_pcidas_driver = {
 	.driver_name	= "cb_pcidas",
 	.module		= THIS_MODULE,
-	.attach_pci	= cb_pcidas_attach_pci,
+	.auto_attach	= cb_pcidas_auto_attach,
 	.detach		= cb_pcidas_detach,
 };
 
-static int __devinit cb_pcidas_pci_probe(struct pci_dev *dev,
+static int cb_pcidas_pci_probe(struct pci_dev *dev,
 					 const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &cb_pcidas_driver);
 }
 
-static void __devexit cb_pcidas_pci_remove(struct pci_dev *dev)
+static void cb_pcidas_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -1688,7 +1654,7 @@ static struct pci_driver cb_pcidas_pci_driver = {
 	.name		= "cb_pcidas",
 	.id_table	= cb_pcidas_pci_table,
 	.probe		= cb_pcidas_pci_probe,
-	.remove		= __devexit_p(cb_pcidas_pci_remove)
+	.remove		= cb_pcidas_pci_remove
 };
 module_comedi_pci_driver(cb_pcidas_driver, cb_pcidas_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
index 0472a90..d72b46c 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
@@ -36,53 +36,57 @@
 ************************************************************************/
 
 /*
-
-Driver: cb_pcidas64
-Description: MeasurementComputing PCI-DAS64xx, 60XX, and 4020 series with the PLX 9080 PCI controller
-Author: Frank Mori Hess <fmhess@users.sourceforge.net>
-Status: works
-Updated: 2002-10-09
-Devices: [Measurement Computing] PCI-DAS6402/16 (cb_pcidas64),
-  PCI-DAS6402/12, PCI-DAS64/M1/16, PCI-DAS64/M2/16,
-  PCI-DAS64/M3/16, PCI-DAS6402/16/JR, PCI-DAS64/M1/16/JR,
-  PCI-DAS64/M2/16/JR, PCI-DAS64/M3/16/JR, PCI-DAS64/M1/14,
-  PCI-DAS64/M2/14, PCI-DAS64/M3/14, PCI-DAS6013, PCI-DAS6014,
-  PCI-DAS6023, PCI-DAS6025, PCI-DAS6030,
-  PCI-DAS6031, PCI-DAS6032, PCI-DAS6033, PCI-DAS6034,
-  PCI-DAS6035, PCI-DAS6036, PCI-DAS6040, PCI-DAS6052,
-  PCI-DAS6070, PCI-DAS6071, PCI-DAS4020/12
-
-Configuration options:
-   [0] - PCI bus of device (optional)
-   [1] - PCI slot of device (optional)
-
-These boards may be autocalibrated with the comedi_calibrate utility.
-
-To select the bnc trigger input on the 4020 (instead of the dio input),
-specify a nonzero channel in the chanspec.  If you wish to use an external
-master clock on the 4020, you may do so by setting the scan_begin_src
-to TRIG_OTHER, and using an INSN_CONFIG_TIMER_1 configuration insn
-to configure the divisor to use for the external clock.
-
-Some devices are not identified because the PCI device IDs are not yet
-known. If you have such a board, please file a bug report at
-https://bugs.comedi.org.
-
-*/
+ * Driver: cb_pcidas64
+ * Description: MeasurementComputing PCI-DAS64xx, 60XX, and 4020 series
+ *   with the PLX 9080 PCI controller
+ * Author: Frank Mori Hess <fmhess@users.sourceforge.net>
+ * Status: works
+ * Updated: Fri, 02 Nov 2012 18:58:55 +0000
+ * Devices: [Measurement Computing] PCI-DAS6402/16 (cb_pcidas64),
+ *   PCI-DAS6402/12, PCI-DAS64/M1/16, PCI-DAS64/M2/16,
+ *   PCI-DAS64/M3/16, PCI-DAS6402/16/JR, PCI-DAS64/M1/16/JR,
+ *   PCI-DAS64/M2/16/JR, PCI-DAS64/M3/16/JR, PCI-DAS64/M1/14,
+ *   PCI-DAS64/M2/14, PCI-DAS64/M3/14, PCI-DAS6013, PCI-DAS6014,
+ *   PCI-DAS6023, PCI-DAS6025, PCI-DAS6030,
+ *   PCI-DAS6031, PCI-DAS6032, PCI-DAS6033, PCI-DAS6034,
+ *   PCI-DAS6035, PCI-DAS6036, PCI-DAS6040, PCI-DAS6052,
+ *   PCI-DAS6070, PCI-DAS6071, PCI-DAS4020/12
+ *
+ * Configuration options:
+ *   None.
+ *
+ * Manual attachment of PCI cards with the comedi_config utility is not
+ * supported by this driver; they are attached automatically.
+ *
+ * These boards may be autocalibrated with the comedi_calibrate utility.
+ *
+ * To select the bnc trigger input on the 4020 (instead of the dio input),
+ * specify a nonzero channel in the chanspec.  If you wish to use an external
+ * master clock on the 4020, you may do so by setting the scan_begin_src
+ * to TRIG_OTHER, and using an INSN_CONFIG_TIMER_1 configuration insn
+ * to configure the divisor to use for the external clock.
+ *
+ * Some devices are not identified because the PCI device IDs are not yet
+ * known. If you have such a board, please let the maintainers know.
+ */
 
 /*
 
 TODO:
 	make it return error if user attempts an ai command that uses the
-		external queue, and an ao command simultaneously
-	user counter subdevice
+	external queue, and an ao command simultaneously user counter subdevice
 	there are a number of boards this driver will support when they are
-		fully released, but does not yet since the pci device id numbers
-		are not yet available.
-	support prescaled 100khz clock for slow pacing (not available on 6000 series?)
+	fully released, but does not yet since the pci device id numbers
+	are not yet available.
+
+	support prescaled 100khz clock for slow pacing (not available on 6000
+	series?)
+
 	make ao fifo size adjustable like ai fifo
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "../comedidev.h"
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -96,17 +100,17 @@ TODO:
 /* #define PCIDAS64_DEBUG         enable debugging code */
 
 #ifdef PCIDAS64_DEBUG
-#define DEBUG_PRINT(format, args...)  printk(format , ## args)
+#define DEBUG_PRINT(format, args...)  pr_debug(format, ## args)
 #else
-#define DEBUG_PRINT(format, args...)
+#define DEBUG_PRINT(format, args...)  no_printk(format, ## args)
 #endif
 
 #define TIMER_BASE 25		/*  40MHz master clock */
-#define PRESCALED_TIMER_BASE	10000	/*  100kHz 'prescaled' clock for slow acquisition, maybe I'll support this someday */
+/* 100kHz 'prescaled' clock for slow acquisition,
+ * maybe I'll support this someday */
+#define PRESCALED_TIMER_BASE	10000
 #define DMA_BUFFER_SIZE 0x1000
 
-#define PCI_VENDOR_ID_COMPUTERBOARDS	0x1307
-
 /* maximum value that can be loaded into board's 24-bit counters*/
 static const int max_counter_value = 0xffffff;
 
@@ -119,7 +123,7 @@ enum base_address_regions {
 	DIO_COUNTER_BADDRINDEX = 3,
 };
 
-/* priv(dev)->main_iobase registers */
+/* devpriv->main_iobase registers */
 enum write_only_registers {
 	INTR_ENABLE_REG = 0x0,	/*  interrupt enable register */
 	HW_CONFIG_REG = 0x2,	/*  hardware config register */
@@ -128,26 +132,36 @@ enum write_only_registers {
 	ADC_CONTROL0_REG = 0x10,	/*  adc control register 0 */
 	ADC_CONTROL1_REG = 0x12,	/*  adc control register 1 */
 	CALIBRATION_REG = 0x14,
-	ADC_SAMPLE_INTERVAL_LOWER_REG = 0x16,	/*  lower 16 bits of adc sample interval counter */
-	ADC_SAMPLE_INTERVAL_UPPER_REG = 0x18,	/*  upper 8 bits of adc sample interval counter */
-	ADC_DELAY_INTERVAL_LOWER_REG = 0x1a,	/*  lower 16 bits of delay interval counter */
-	ADC_DELAY_INTERVAL_UPPER_REG = 0x1c,	/*  upper 8 bits of delay interval counter */
-	ADC_COUNT_LOWER_REG = 0x1e,	/*  lower 16 bits of hardware conversion/scan counter */
-	ADC_COUNT_UPPER_REG = 0x20,	/*  upper 8 bits of hardware conversion/scan counter */
+	/*  lower 16 bits of adc sample interval counter */
+	ADC_SAMPLE_INTERVAL_LOWER_REG = 0x16,
+	/*  upper 8 bits of adc sample interval counter */
+	ADC_SAMPLE_INTERVAL_UPPER_REG = 0x18,
+	/*  lower 16 bits of delay interval counter */
+	ADC_DELAY_INTERVAL_LOWER_REG = 0x1a,
+	/*  upper 8 bits of delay interval counter */
+	ADC_DELAY_INTERVAL_UPPER_REG = 0x1c,
+	/*  lower 16 bits of hardware conversion/scan counter */
+	ADC_COUNT_LOWER_REG = 0x1e,
+	/*  upper 8 bits of hardware conversion/scan counter */
+	ADC_COUNT_UPPER_REG = 0x20,
 	ADC_START_REG = 0x22,	/*  software trigger to start acquisition */
 	ADC_CONVERT_REG = 0x24,	/*  initiates single conversion */
 	ADC_QUEUE_CLEAR_REG = 0x26,	/*  clears adc queue */
 	ADC_QUEUE_LOAD_REG = 0x28,	/*  loads adc queue */
 	ADC_BUFFER_CLEAR_REG = 0x2a,
-	ADC_QUEUE_HIGH_REG = 0x2c,	/*  high channel for internal queue, use adc_chan_bits() inline above */
+	/*  high channel for internal queue, use adc_chan_bits() inline above */
+	ADC_QUEUE_HIGH_REG = 0x2c,
 	DAC_CONTROL0_REG = 0x50,	/*  dac control register 0 */
 	DAC_CONTROL1_REG = 0x52,	/*  dac control register 0 */
-	DAC_SAMPLE_INTERVAL_LOWER_REG = 0x54,	/*  lower 16 bits of dac sample interval counter */
-	DAC_SAMPLE_INTERVAL_UPPER_REG = 0x56,	/*  upper 8 bits of dac sample interval counter */
+	/*  lower 16 bits of dac sample interval counter */
+	DAC_SAMPLE_INTERVAL_LOWER_REG = 0x54,
+	/*  upper 8 bits of dac sample interval counter */
+	DAC_SAMPLE_INTERVAL_UPPER_REG = 0x56,
 	DAC_SELECT_REG = 0x60,
 	DAC_START_REG = 0x64,
 	DAC_BUFFER_CLEAR_REG = 0x66,	/*  clear dac buffer */
 };
+
 static inline unsigned int dac_convert_reg(unsigned int channel)
 {
 	return 0x70 + (2 * (channel & 0x1));
@@ -164,7 +178,9 @@ static inline unsigned int dac_msb_4020_reg(unsigned int channel)
 }
 
 enum read_only_registers {
-	HW_STATUS_REG = 0x0,	/*  hardware status register, reading this apparently clears pending interrupts as well */
+	/*  hardware status register,
+	 *  reading this apparently clears pending interrupts as well */
+	HW_STATUS_REG = 0x0,
 	PIPE1_READ_REG = 0x4,
 	ADC_READ_PNTR_REG = 0x8,
 	LOWER_XFER_REG = 0x10,
@@ -174,12 +190,14 @@ enum read_only_registers {
 
 enum read_write_registers {
 	I8255_4020_REG = 0x48,	/*  8255 offset, for 4020 only */
-	ADC_QUEUE_FIFO_REG = 0x100,	/*  external channel/gain queue, uses same bits as ADC_QUEUE_LOAD_REG */
+	/*  external channel/gain queue, uses same bits as ADC_QUEUE_LOAD_REG */
+	ADC_QUEUE_FIFO_REG = 0x100,
 	ADC_FIFO_REG = 0x200,	/* adc data fifo */
-	DAC_FIFO_REG = 0x300,	/* dac data fifo, has weird interactions with external channel queue */
+	/* dac data fifo, has weird interactions with external channel queue */
+	DAC_FIFO_REG = 0x300,
 };
 
-/* priv(dev)->dio_counter_iobase registers */
+/* devpriv->dio_counter_iobase registers */
 enum dio_counter_registers {
 	DIO_8255_OFFSET = 0x0,
 	DO_REG = 0x20,
@@ -191,13 +209,13 @@ enum dio_counter_registers {
 /* bit definitions for write-only registers */
 
 enum intr_enable_contents {
-	ADC_INTR_SRC_MASK = 0x3,	/*  bits that set adc interrupt source */
-	ADC_INTR_QFULL_BITS = 0x0,	/*  interrupt fifo quater full */
+	ADC_INTR_SRC_MASK = 0x3,	/*  adc interrupt source mask */
+	ADC_INTR_QFULL_BITS = 0x0,	/*  interrupt fifo quarter full */
 	ADC_INTR_EOC_BITS = 0x1,	/*  interrupt end of conversion */
 	ADC_INTR_EOSCAN_BITS = 0x2,	/*  interrupt end of scan */
-	ADC_INTR_EOSEQ_BITS = 0x3,	/*  interrupt end of sequence (probably wont use this it's pretty fancy) */
+	ADC_INTR_EOSEQ_BITS = 0x3,	/*  interrupt end of sequence mask */
 	EN_ADC_INTR_SRC_BIT = 0x4,	/*  enable adc interrupt source */
-	EN_ADC_DONE_INTR_BIT = 0x8,	/*  enable adc acquisition done interrupt */
+	EN_ADC_DONE_INTR_BIT = 0x8,	/*  enable adc acquisition done intr */
 	DAC_INTR_SRC_MASK = 0x30,
 	DAC_INTR_QEMPTY_BITS = 0x0,
 	DAC_INTR_HIGH_CHAN_BITS = 0x10,
@@ -211,25 +229,33 @@ enum intr_enable_contents {
 };
 
 enum hw_config_contents {
-	MASTER_CLOCK_4020_MASK = 0x3,	/*  bits that specify master clock source for 4020 */
-	INTERNAL_CLOCK_4020_BITS = 0x1,	/*  use 40 MHz internal master clock for 4020 */
+	MASTER_CLOCK_4020_MASK = 0x3,	/*  master clock source mask for 4020 */
+	INTERNAL_CLOCK_4020_BITS = 0x1,	/*  use 40 MHz internal master clock */
 	BNC_CLOCK_4020_BITS = 0x2,	/*  use BNC input for master clock */
 	EXT_CLOCK_4020_BITS = 0x3,	/*  use dio input for master clock */
-	EXT_QUEUE_BIT = 0x200,	/*  use external channel/gain queue (more versatile than internal queue) */
-	SLOW_DAC_BIT = 0x400,	/*  use 225 nanosec strobe when loading dac instead of 50 nanosec */
-	HW_CONFIG_DUMMY_BITS = 0x2000,	/*  bit with unknown function yet given as default value in pci-das64 manual */
-	DMA_CH_SELECT_BIT = 0x8000,	/*  bit selects channels 1/0 for analog input/output, otherwise 0/1 */
-	FIFO_SIZE_REG = 0x4,	/*  allows adjustment of fifo sizes */
+	EXT_QUEUE_BIT = 0x200,		/*  use external channel/gain queue */
+	/*  use 225 nanosec strobe when loading dac instead of 50 nanosec */
+	SLOW_DAC_BIT = 0x400,
+	/*  bit with unknown function yet given as default value in pci-das64
+	 *  manual */
+	HW_CONFIG_DUMMY_BITS = 0x2000,
+	/*  bit selects channels 1/0 for analog input/output, otherwise 0/1 */
+	DMA_CH_SELECT_BIT = 0x8000,
+	FIFO_SIZE_REG = 0x4,		/*  allows adjustment of fifo sizes */
 	DAC_FIFO_SIZE_MASK = 0xff00,	/*  bits that set dac fifo size */
-	DAC_FIFO_BITS = 0xf800,	/* 8k sample ao fifo */
+	DAC_FIFO_BITS = 0xf800,		/*  8k sample ao fifo */
 };
 #define DAC_FIFO_SIZE 0x2000
 
 enum daq_atrig_low_4020_contents {
-	EXT_AGATE_BNC_BIT = 0x8000,	/*  use trig/ext clk bnc input for analog gate signal */
-	EXT_STOP_TRIG_BNC_BIT = 0x4000,	/*  use trig/ext clk bnc input for external stop trigger signal */
-	EXT_START_TRIG_BNC_BIT = 0x2000,	/*  use trig/ext clk bnc input for external start trigger signal */
+	/*  use trig/ext clk bnc input for analog gate signal */
+	EXT_AGATE_BNC_BIT = 0x8000,
+	/*  use trig/ext clk bnc input for external stop trigger signal */
+	EXT_STOP_TRIG_BNC_BIT = 0x4000,
+	/*  use trig/ext clk bnc input for external start trigger signal */
+	EXT_START_TRIG_BNC_BIT = 0x2000,
 };
+
 static inline uint16_t analog_trig_low_threshold_bits(uint16_t threshold)
 {
 	return threshold & 0xfff;
@@ -247,14 +273,17 @@ enum adc_control0_contents {
 	ADC_START_TRIG_ANALOG_BITS = 0x30,
 	ADC_START_TRIG_MASK = 0x30,
 	ADC_START_TRIG_FALLING_BIT = 0x40,	/*  trig 1 uses falling edge */
-	ADC_EXT_CONV_FALLING_BIT = 0x800,	/*  external pacing uses falling edge */
-	ADC_SAMPLE_COUNTER_EN_BIT = 0x1000,	/*  enable hardware scan counter */
+	/*  external pacing uses falling edge */
+	ADC_EXT_CONV_FALLING_BIT = 0x800,
+	/*  enable hardware scan counter */
+	ADC_SAMPLE_COUNTER_EN_BIT = 0x1000,
 	ADC_DMA_DISABLE_BIT = 0x4000,	/*  disables dma */
 	ADC_ENABLE_BIT = 0x8000,	/*  master adc enable */
 };
 
 enum adc_control1_contents {
-	ADC_QUEUE_CONFIG_BIT = 0x1,	/*  should be set for boards with > 16 channels */
+	/*  should be set for boards with > 16 channels */
+	ADC_QUEUE_CONFIG_BIT = 0x1,
 	CONVERT_POLARITY_BIT = 0x10,
 	EOC_POLARITY_BIT = 0x20,
 	ADC_SW_GATE_BIT = 0x40,	/*  software gate of adc */
@@ -263,10 +292,11 @@ enum adc_control1_contents {
 	ADC_LO_CHANNEL_4020_MASK = 0x300,
 	ADC_HI_CHANNEL_4020_MASK = 0xc00,
 	TWO_CHANNEL_4020_BITS = 0x1000,	/*  two channel mode for 4020 */
-	FOUR_CHANNEL_4020_BITS = 0x2000,	/*  four channel mode for 4020 */
+	FOUR_CHANNEL_4020_BITS = 0x2000, /*  four channel mode for 4020 */
 	CHANNEL_MODE_4020_MASK = 0x3000,
 	ADC_MODE_MASK = 0xf000,
 };
+
 static inline uint16_t adc_lo_chan_4020_bits(unsigned int channel)
 {
 	return (channel & 0x3) << 8;
@@ -289,9 +319,10 @@ enum calibration_contents {
 	CAL_EN_64XX_BIT = 0x40,	/*  calibration enable for 64xx series */
 	SERIAL_DATA_IN_BIT = 0x80,
 	SERIAL_CLOCK_BIT = 0x100,
-	CAL_EN_60XX_BIT = 0x200,	/*  calibration enable for 60xx series */
+	CAL_EN_60XX_BIT = 0x200, /*  calibration enable for 60xx series */
 	CAL_GAIN_BIT = 0x800,
 };
+
 /* calibration sources for 6025 are:
  *  0 : ground
  *  1 : 10V
@@ -302,6 +333,7 @@ enum calibration_contents {
  *  6 : dac channel 0
  *  7 : dac channel 1
  */
+
 static inline uint16_t adc_src_bits(unsigned int source)
 {
 	return (source & 0xf) << 3;
@@ -315,10 +347,12 @@ static inline uint16_t adc_convert_chan_4020_bits(unsigned int channel)
 enum adc_queue_load_contents {
 	UNIP_BIT = 0x800,	/*  unipolar/bipolar bit */
 	ADC_SE_DIFF_BIT = 0x1000,	/*  single-ended/ differential bit */
-	ADC_COMMON_BIT = 0x2000,	/*  non-referenced single-ended (common-mode input) */
+	/*  non-referenced single-ended (common-mode input) */
+	ADC_COMMON_BIT = 0x2000,
 	QUEUE_EOSEQ_BIT = 0x4000,	/*  queue end of sequence */
 	QUEUE_EOSCAN_BIT = 0x8000,	/*  queue end of scan */
 };
+
 static inline uint16_t adc_chan_bits(unsigned int channel)
 {
 	return channel & 0x3f;
@@ -365,6 +399,7 @@ enum hw_status_contents {
 	EXT_INTR_PENDING_BIT = 0x100,
 	ADC_STOP_BIT = 0x200,
 };
+
 static inline uint16_t pipe_full_bits(uint16_t hw_status_bits)
 {
 	return (hw_status_bits >> 10) & 0x3;
@@ -393,9 +428,12 @@ enum i2c_addresses {
 };
 
 enum range_cal_i2c_contents {
-	ADC_SRC_4020_MASK = 0x70,	/*  bits that set what source the adc converter measures */
-	BNC_TRIG_THRESHOLD_0V_BIT = 0x80,	/*  make bnc trig/ext clock threshold 0V instead of 2.5V */
+	/*  bits that set what source the adc converter measures */
+	ADC_SRC_4020_MASK = 0x70,
+	/*  make bnc trig/ext clock threshold 0V instead of 2.5V */
+	BNC_TRIG_THRESHOLD_0V_BIT = 0x80,
 };
+
 static inline uint8_t adc_src_4020_bits(unsigned int source)
 {
 	return (source << 4) & ADC_SRC_4020_MASK;
@@ -562,11 +600,12 @@ struct pcidas64_board {
 	const struct comedi_lrange *ai_range_table;
 	int ao_nchan;		/*  number of analog out channels */
 	int ao_bits;		/*  analog output resolution */
-	int ao_scan_speed;	/*  analog output speed (for a scan, not conversion) */
+	int ao_scan_speed;	/*  analog output scan speed */
 	const struct comedi_lrange *ao_range_table;
 	const int *ao_range_code;
 	const struct hw_fifo_info *const ai_fifo;
-	enum register_layout layout;	/*  different board families have slightly different registers */
+	/*  different board families have slightly different registers */
+	enum register_layout layout;
 	unsigned has_8255:1;
 };
 
@@ -596,7 +635,7 @@ static const struct hw_fifo_info ai_fifo_60xx = {
 #define MAX_AI_DMA_RING_COUNT (0x80000 / DMA_BUFFER_SIZE)
 #define MIN_AI_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE)
 #define AO_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE)
-static inline unsigned int ai_dma_ring_count(struct pcidas64_board *board)
+static inline unsigned int ai_dma_ring_count(const struct pcidas64_board *board)
 {
 	if (board->layout == LAYOUT_4020)
 		return MAX_AI_DMA_RING_COUNT;
@@ -1025,24 +1064,23 @@ static const struct pcidas64_board pcidas64_boards[] = {
 #endif
 };
 
-static inline struct pcidas64_board *board(const struct comedi_device *dev)
-{
-	return (struct pcidas64_board *)dev->board_ptr;
-}
-
 static inline unsigned short se_diff_bit_6xxx(struct comedi_device *dev,
 					      int use_differential)
 {
-	if ((board(dev)->layout == LAYOUT_64XX && !use_differential) ||
-	    (board(dev)->layout == LAYOUT_60XX && use_differential))
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+
+	if ((thisboard->layout == LAYOUT_64XX && !use_differential) ||
+	    (thisboard->layout == LAYOUT_60XX && use_differential))
 		return ADC_SE_DIFF_BIT;
 	else
 		return 0;
 };
 
 struct ext_clock_info {
-	unsigned int divisor;	/*  master clock divisor to use for scans with external master clock */
-	unsigned int chanspec;	/*  chanspec for master clock input when used as scan begin src */
+	/*  master clock divisor to use for scans with external master clock */
+	unsigned int divisor;
+	/*  chanspec for master clock input when used as scan begin src */
+	unsigned int chanspec;
 };
 
 /* this structure is for data unique to this hardware driver. */
@@ -1058,30 +1096,52 @@ struct pcidas64_private {
 	/*  local address (used by dma controller) */
 	uint32_t local0_iobase;
 	uint32_t local1_iobase;
-	volatile unsigned int ai_count;	/*  number of analog input samples remaining */
-	uint16_t *ai_buffer[MAX_AI_DMA_RING_COUNT];	/*  dma buffers for analog input */
-	dma_addr_t ai_buffer_bus_addr[MAX_AI_DMA_RING_COUNT];	/*  physical addresses of ai dma buffers */
-	struct plx_dma_desc *ai_dma_desc;	/*  array of ai dma descriptors read by plx9080, allocated to get proper alignment */
-	dma_addr_t ai_dma_desc_bus_addr;	/*  physical address of ai dma descriptor array */
-	volatile unsigned int ai_dma_index;	/*  index of the ai dma descriptor/buffer that is currently being used */
-	uint16_t *ao_buffer[AO_DMA_RING_COUNT];	/*  dma buffers for analog output */
-	dma_addr_t ao_buffer_bus_addr[AO_DMA_RING_COUNT];	/*  physical addresses of ao dma buffers */
+	/*  number of analog input samples remaining */
+	volatile unsigned int ai_count;
+	/*  dma buffers for analog input */
+	uint16_t *ai_buffer[MAX_AI_DMA_RING_COUNT];
+	/*  physical addresses of ai dma buffers */
+	dma_addr_t ai_buffer_bus_addr[MAX_AI_DMA_RING_COUNT];
+	/*  array of ai dma descriptors read by plx9080,
+	 *  allocated to get proper alignment */
+	struct plx_dma_desc *ai_dma_desc;
+	/*  physical address of ai dma descriptor array */
+	dma_addr_t ai_dma_desc_bus_addr;
+	/*  index of the ai dma descriptor/buffer
+	 *  that is currently being used */
+	volatile unsigned int ai_dma_index;
+	/*  dma buffers for analog output */
+	uint16_t *ao_buffer[AO_DMA_RING_COUNT];
+	/*  physical addresses of ao dma buffers */
+	dma_addr_t ao_buffer_bus_addr[AO_DMA_RING_COUNT];
 	struct plx_dma_desc *ao_dma_desc;
 	dma_addr_t ao_dma_desc_bus_addr;
-	volatile unsigned int ao_dma_index;	/*  keeps track of buffer where the next ao sample should go */
-	volatile unsigned long ao_count;	/*  number of analog output samples remaining */
-	volatile unsigned int ao_value[2];	/*  remember what the analog outputs are set to, to allow readback */
+	/*  keeps track of buffer where the next ao sample should go */
+	volatile unsigned int ao_dma_index;
+	/*  number of analog output samples remaining */
+	volatile unsigned long ao_count;
+	/*  remember what the analog outputs are set to, to allow readback */
+	volatile unsigned int ao_value[2];
 	unsigned int hw_revision;	/*  stc chip hardware revision number */
-	volatile unsigned int intr_enable_bits;	/*  last bits sent to INTR_ENABLE_REG register */
-	volatile uint16_t adc_control1_bits;	/*  last bits sent to ADC_CONTROL1_REG register */
-	volatile uint16_t fifo_size_bits;	/*  last bits sent to FIFO_SIZE_REG register */
-	volatile uint16_t hw_config_bits;	/*  last bits sent to HW_CONFIG_REG register */
+	/*  last bits sent to INTR_ENABLE_REG register */
+	volatile unsigned int intr_enable_bits;
+	/*  last bits sent to ADC_CONTROL1_REG register */
+	volatile uint16_t adc_control1_bits;
+	/*  last bits sent to FIFO_SIZE_REG register */
+	volatile uint16_t fifo_size_bits;
+	/*  last bits sent to HW_CONFIG_REG register */
+	volatile uint16_t hw_config_bits;
 	volatile uint16_t dac_control1_bits;
-	volatile uint32_t plx_control_bits;	/*  last bits written to plx9080 control register */
-	volatile uint32_t plx_intcsr_bits;	/*  last bits written to plx interrupt control and status register */
-	volatile int calibration_source;	/*  index of calibration source readable through ai ch0 */
-	volatile uint8_t i2c_cal_range_bits;	/*  bits written to i2c calibration/range register */
-	volatile unsigned int ext_trig_falling;	/*  configure digital triggers to trigger on falling edge */
+	/*  last bits written to plx9080 control register */
+	volatile uint32_t plx_control_bits;
+	/*  last bits written to plx interrupt control and status register */
+	volatile uint32_t plx_intcsr_bits;
+	/*  index of calibration source readable through ai ch0 */
+	volatile int calibration_source;
+	/*  bits written to i2c calibration/range register */
+	volatile uint8_t i2c_cal_range_bits;
+	/*  configure digital triggers to trigger on falling edge */
+	volatile unsigned int ext_trig_falling;
 	/*  states of various devices stored to enable read-back */
 	unsigned int ad8402_state[2];
 	unsigned int caldac_state[8];
@@ -1091,93 +1151,12 @@ struct pcidas64_private {
 	short ao_bounce_buffer[DAC_FIFO_SIZE];
 };
 
-/* inline function that makes it easier to
- * access the private structure.
- */
-static inline struct pcidas64_private *priv(struct comedi_device *dev)
-{
-	return dev->private;
-}
-
-static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
-		    struct comedi_insn *insn, unsigned int *data);
-static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data);
-static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
-		    struct comedi_insn *insn, unsigned int *data);
-static int ao_readback_insn(struct comedi_device *dev,
-			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data);
-static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
-static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
-		      struct comedi_cmd *cmd);
-static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
-static int ao_inttrig(struct comedi_device *dev,
-		      struct comedi_subdevice *subdev, unsigned int trig_num);
-static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
-		      struct comedi_cmd *cmd);
-static irqreturn_t handle_interrupt(int irq, void *d);
-static int ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
-static int ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
-static int dio_callback(int dir, int port, int data, unsigned long arg);
-static int dio_callback_4020(int dir, int port, int data, unsigned long arg);
-static int di_rbits(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);
-static int dio_60xx_config_insn(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);
-static int calib_read_insn(struct comedi_device *dev,
-			   struct comedi_subdevice *s, struct comedi_insn *insn,
-			   unsigned int *data);
-static int calib_write_insn(struct comedi_device *dev,
-			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data);
-static int ad8402_read_insn(struct comedi_device *dev,
-			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data);
-static void ad8402_write(struct comedi_device *dev, unsigned int channel,
-			 unsigned int value);
-static int ad8402_write_insn(struct comedi_device *dev,
-			     struct comedi_subdevice *s,
-			     struct comedi_insn *insn, unsigned int *data);
-static int eeprom_read_insn(struct comedi_device *dev,
-			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data);
-static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd);
-static unsigned int get_divisor(unsigned int ns, unsigned int flags);
-static void i2c_write(struct comedi_device *dev, unsigned int address,
-		      const uint8_t *data, unsigned int length);
-static void caldac_write(struct comedi_device *dev, unsigned int channel,
-			 unsigned int value);
-static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
-			     uint8_t value);
-/* static int dac_1590_write(struct comedi_device *dev, unsigned int dac_a, unsigned int dac_b); */
-static int caldac_i2c_write(struct comedi_device *dev,
-			    unsigned int caldac_channel, unsigned int value);
-static void abort_dma(struct comedi_device *dev, unsigned int channel);
-static void disable_plx_interrupts(struct comedi_device *dev);
-static int set_ai_fifo_size(struct comedi_device *dev,
-			    unsigned int num_samples);
-static unsigned int ai_fifo_size(struct comedi_device *dev);
-static int set_ai_fifo_segment_length(struct comedi_device *dev,
-				      unsigned int num_entries);
-static void disable_ai_pacing(struct comedi_device *dev);
-static void disable_ai_interrupts(struct comedi_device *dev);
-static void enable_ai_interrupts(struct comedi_device *dev,
-				 const struct comedi_cmd *cmd);
-static unsigned int get_ao_divisor(unsigned int ns, unsigned int flags);
-static void load_ao_dma(struct comedi_device *dev,
-			const struct comedi_cmd *cmd);
-
 static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev,
 				       unsigned int range_index)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
 	const struct comedi_krange *range =
-	    &board(dev)->ai_range_table->range[range_index];
+		&thisboard->ai_range_table->range[range_index];
 	unsigned int bits = 0;
 
 	switch (range->max) {
@@ -1220,7 +1199,9 @@ static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev,
 static unsigned int hw_revision(const struct comedi_device *dev,
 				uint16_t hw_status_bits)
 {
-	if (board(dev)->layout == LAYOUT_4020)
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+
+	if (thisboard->layout == LAYOUT_4020)
 		return (hw_status_bits >> 13) & 0x7;
 
 	return (hw_status_bits >> 12) & 0xf;
@@ -1230,7 +1211,8 @@ static void set_dac_range_bits(struct comedi_device *dev,
 			       volatile uint16_t *bits, unsigned int channel,
 			       unsigned int range)
 {
-	unsigned int code = board(dev)->ao_range_code[range];
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	unsigned int code = thisboard->ao_range_code[range];
 
 	if (channel > 1)
 		comedi_error(dev, "bug! bad channel?");
@@ -1246,20 +1228,86 @@ static inline int ao_cmd_is_supported(const struct pcidas64_board *board)
 	return board->ao_nchan && board->layout != LAYOUT_4020;
 }
 
+static void abort_dma(struct comedi_device *dev, unsigned int channel)
+{
+	struct pcidas64_private *devpriv = dev->private;
+	unsigned long flags;
+
+	/*  spinlock for plx dma control/status reg */
+	spin_lock_irqsave(&dev->spinlock, flags);
+
+	plx9080_abort_dma(devpriv->plx9080_iobase, channel);
+
+	spin_unlock_irqrestore(&dev->spinlock, flags);
+}
+
+static void disable_plx_interrupts(struct comedi_device *dev)
+{
+	struct pcidas64_private *devpriv = dev->private;
+
+	devpriv->plx_intcsr_bits = 0;
+	writel(devpriv->plx_intcsr_bits,
+	       devpriv->plx9080_iobase + PLX_INTRCS_REG);
+}
+
+static void disable_ai_interrupts(struct comedi_device *dev)
+{
+	struct pcidas64_private *devpriv = dev->private;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->spinlock, flags);
+	devpriv->intr_enable_bits &=
+		~EN_ADC_INTR_SRC_BIT & ~EN_ADC_DONE_INTR_BIT &
+		~EN_ADC_ACTIVE_INTR_BIT & ~EN_ADC_STOP_INTR_BIT &
+		~EN_ADC_OVERRUN_BIT & ~ADC_INTR_SRC_MASK;
+	writew(devpriv->intr_enable_bits,
+	       devpriv->main_iobase + INTR_ENABLE_REG);
+	spin_unlock_irqrestore(&dev->spinlock, flags);
+
+	DEBUG_PRINT("intr enable bits 0x%x\n", devpriv->intr_enable_bits);
+}
+
+static void enable_ai_interrupts(struct comedi_device *dev,
+				 const struct comedi_cmd *cmd)
+{
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
+	uint32_t bits;
+	unsigned long flags;
+
+	bits = EN_ADC_OVERRUN_BIT | EN_ADC_DONE_INTR_BIT |
+	       EN_ADC_ACTIVE_INTR_BIT | EN_ADC_STOP_INTR_BIT;
+	/*  Use pio transfer and interrupt on end of conversion
+	 *  if TRIG_WAKE_EOS flag is set. */
+	if (cmd->flags & TRIG_WAKE_EOS) {
+		/*  4020 doesn't support pio transfers except for fifo dregs */
+		if (thisboard->layout != LAYOUT_4020)
+			bits |= ADC_INTR_EOSCAN_BITS | EN_ADC_INTR_SRC_BIT;
+	}
+	spin_lock_irqsave(&dev->spinlock, flags);
+	devpriv->intr_enable_bits |= bits;
+	writew(devpriv->intr_enable_bits,
+	       devpriv->main_iobase + INTR_ENABLE_REG);
+	DEBUG_PRINT("intr enable bits 0x%x\n", devpriv->intr_enable_bits);
+	spin_unlock_irqrestore(&dev->spinlock, flags);
+}
+
 /* initialize plx9080 chip */
 static void init_plx9080(struct comedi_device *dev)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
 	uint32_t bits;
-	void __iomem *plx_iobase = priv(dev)->plx9080_iobase;
+	void __iomem *plx_iobase = devpriv->plx9080_iobase;
 
-	priv(dev)->plx_control_bits =
-	    readl(priv(dev)->plx9080_iobase + PLX_CONTROL_REG);
+	devpriv->plx_control_bits =
+		readl(devpriv->plx9080_iobase + PLX_CONTROL_REG);
 
 	/*  plx9080 dump */
 	DEBUG_PRINT(" plx interrupt status 0x%x\n",
 		    readl(plx_iobase + PLX_INTRCS_REG));
 	DEBUG_PRINT(" plx id bits 0x%x\n", readl(plx_iobase + PLX_ID_REG));
-	DEBUG_PRINT(" plx control reg 0x%x\n", priv(dev)->plx_control_bits);
+	DEBUG_PRINT(" plx control reg 0x%x\n", devpriv->plx_control_bits);
 	DEBUG_PRINT(" plx mode/arbitration reg 0x%x\n",
 		    readl(plx_iobase + PLX_MARB_REG));
 	DEBUG_PRINT(" plx region0 reg 0x%x\n",
@@ -1292,7 +1340,7 @@ static void init_plx9080(struct comedi_device *dev)
 #else
 	bits = 0;
 #endif
-	writel(bits, priv(dev)->plx9080_iobase + PLX_BIGEND_REG);
+	writel(bits, devpriv->plx9080_iobase + PLX_BIGEND_REG);
 
 	disable_plx_interrupts(dev);
 
@@ -1307,9 +1355,11 @@ static void init_plx9080(struct comedi_device *dev)
 	bits |= PLX_EN_BTERM_BIT;
 	/*  enable dma chaining */
 	bits |= PLX_EN_CHAIN_BIT;
-	/*  enable interrupt on dma done (probably don't need this, since chain never finishes) */
+	/*  enable interrupt on dma done
+	 *  (probably don't need this, since chain never finishes) */
 	bits |= PLX_EN_DMA_DONE_INTR_BIT;
-	/*  don't increment local address during transfers (we are transferring from a fixed fifo register) */
+	/*  don't increment local address during transfers
+	 *  (we are transferring from a fixed fifo register) */
 	bits |= PLX_LOCAL_ADDR_CONST_BIT;
 	/*  route dma interrupt to pci bus */
 	bits |= PLX_DMA_INTR_PCI_BIT;
@@ -1318,324 +1368,235 @@ static void init_plx9080(struct comedi_device *dev)
 	/*  enable local burst mode */
 	bits |= PLX_DMA_LOCAL_BURST_EN_BIT;
 	/*  4020 uses 32 bit dma */
-	if (board(dev)->layout == LAYOUT_4020) {
+	if (thisboard->layout == LAYOUT_4020)
 		bits |= PLX_LOCAL_BUS_32_WIDE_BITS;
-	} else {		/*  localspace0 bus is 16 bits wide */
+	else		/*  localspace0 bus is 16 bits wide */
 		bits |= PLX_LOCAL_BUS_16_WIDE_BITS;
-	}
 	writel(bits, plx_iobase + PLX_DMA1_MODE_REG);
-	if (ao_cmd_is_supported(board(dev)))
+	if (ao_cmd_is_supported(thisboard))
 		writel(bits, plx_iobase + PLX_DMA0_MODE_REG);
 
 	/*  enable interrupts on plx 9080 */
-	priv(dev)->plx_intcsr_bits |=
+	devpriv->plx_intcsr_bits |=
 	    ICS_AERR | ICS_PERR | ICS_PIE | ICS_PLIE | ICS_PAIE | ICS_LIE |
 	    ICS_DMA0_E | ICS_DMA1_E;
-	writel(priv(dev)->plx_intcsr_bits,
-	       priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
+	writel(devpriv->plx_intcsr_bits,
+	       devpriv->plx9080_iobase + PLX_INTRCS_REG);
 }
 
-/* Allocate and initialize the subdevice structures.
- */
-static int setup_subdevices(struct comedi_device *dev)
+static void disable_ai_pacing(struct comedi_device *dev)
 {
-	struct comedi_subdevice *s;
-	void __iomem *dio_8255_iobase;
-	int i;
-	int ret;
-
-	ret = comedi_alloc_subdevices(dev, 10);
-	if (ret)
-		return ret;
-
-	s = &dev->subdevices[0];
-	/* analog input subdevice */
-	dev->read_subdev = s;
-	s->type = COMEDI_SUBD_AI;
-	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DITHER | SDF_CMD_READ;
-	if (board(dev)->layout == LAYOUT_60XX)
-		s->subdev_flags |= SDF_COMMON | SDF_DIFF;
-	else if (board(dev)->layout == LAYOUT_64XX)
-		s->subdev_flags |= SDF_DIFF;
-	/* XXX Number of inputs in differential mode is ignored */
-	s->n_chan = board(dev)->ai_se_chans;
-	s->len_chanlist = 0x2000;
-	s->maxdata = (1 << board(dev)->ai_bits) - 1;
-	s->range_table = board(dev)->ai_range_table;
-	s->insn_read = ai_rinsn;
-	s->insn_config = ai_config_insn;
-	s->do_cmd = ai_cmd;
-	s->do_cmdtest = ai_cmdtest;
-	s->cancel = ai_cancel;
-	if (board(dev)->layout == LAYOUT_4020) {
-		uint8_t data;
-		/*  set adc to read from inputs (not internal calibration sources) */
-		priv(dev)->i2c_cal_range_bits = adc_src_4020_bits(4);
-		/*  set channels to +-5 volt input ranges */
-		for (i = 0; i < s->n_chan; i++)
-			priv(dev)->i2c_cal_range_bits |= attenuate_bit(i);
-		data = priv(dev)->i2c_cal_range_bits;
-		i2c_write(dev, RANGE_CAL_I2C_ADDR, &data, sizeof(data));
-	}
-
-	/* analog output subdevice */
-	s = &dev->subdevices[1];
-	if (board(dev)->ao_nchan) {
-		s->type = COMEDI_SUBD_AO;
-		s->subdev_flags =
-		    SDF_READABLE | SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
-		s->n_chan = board(dev)->ao_nchan;
-		s->maxdata = (1 << board(dev)->ao_bits) - 1;
-		s->range_table = board(dev)->ao_range_table;
-		s->insn_read = ao_readback_insn;
-		s->insn_write = ao_winsn;
-		if (ao_cmd_is_supported(board(dev))) {
-			dev->write_subdev = s;
-			s->do_cmdtest = ao_cmdtest;
-			s->do_cmd = ao_cmd;
-			s->len_chanlist = board(dev)->ao_nchan;
-			s->cancel = ao_cancel;
-		}
-	} else {
-		s->type = COMEDI_SUBD_UNUSED;
-	}
+	struct pcidas64_private *devpriv = dev->private;
+	unsigned long flags;
 
-	/*  digital input */
-	s = &dev->subdevices[2];
-	if (board(dev)->layout == LAYOUT_64XX) {
-		s->type = COMEDI_SUBD_DI;
-		s->subdev_flags = SDF_READABLE;
-		s->n_chan = 4;
-		s->maxdata = 1;
-		s->range_table = &range_digital;
-		s->insn_bits = di_rbits;
-	} else
-		s->type = COMEDI_SUBD_UNUSED;
+	disable_ai_interrupts(dev);
 
-	/*  digital output */
-	if (board(dev)->layout == LAYOUT_64XX) {
-		s = &dev->subdevices[3];
-		s->type = COMEDI_SUBD_DO;
-		s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
-		s->n_chan = 4;
-		s->maxdata = 1;
-		s->range_table = &range_digital;
-		s->insn_bits = do_wbits;
-	} else
-		s->type = COMEDI_SUBD_UNUSED;
+	spin_lock_irqsave(&dev->spinlock, flags);
+	devpriv->adc_control1_bits &= ~ADC_SW_GATE_BIT;
+	writew(devpriv->adc_control1_bits,
+	       devpriv->main_iobase + ADC_CONTROL1_REG);
+	spin_unlock_irqrestore(&dev->spinlock, flags);
 
-	/* 8255 */
-	s = &dev->subdevices[4];
-	if (board(dev)->has_8255) {
-		if (board(dev)->layout == LAYOUT_4020) {
-			dio_8255_iobase =
-			    priv(dev)->main_iobase + I8255_4020_REG;
-			subdev_8255_init(dev, s, dio_callback_4020,
-					 (unsigned long)dio_8255_iobase);
-		} else {
-			dio_8255_iobase =
-			    priv(dev)->dio_counter_iobase + DIO_8255_OFFSET;
-			subdev_8255_init(dev, s, dio_callback,
-					 (unsigned long)dio_8255_iobase);
-		}
-	} else
-		s->type = COMEDI_SUBD_UNUSED;
+	/* disable pacing, triggering, etc */
+	writew(ADC_DMA_DISABLE_BIT | ADC_SOFT_GATE_BITS | ADC_GATE_LEVEL_BIT,
+	       devpriv->main_iobase + ADC_CONTROL0_REG);
+}
 
-	/*  8 channel dio for 60xx */
-	s = &dev->subdevices[5];
-	if (board(dev)->layout == LAYOUT_60XX) {
-		s->type = COMEDI_SUBD_DIO;
-		s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
-		s->n_chan = 8;
-		s->maxdata = 1;
-		s->range_table = &range_digital;
-		s->insn_config = dio_60xx_config_insn;
-		s->insn_bits = dio_60xx_wbits;
-	} else
-		s->type = COMEDI_SUBD_UNUSED;
+static int set_ai_fifo_segment_length(struct comedi_device *dev,
+				      unsigned int num_entries)
+{
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
+	static const int increment_size = 0x100;
+	const struct hw_fifo_info *const fifo = thisboard->ai_fifo;
+	unsigned int num_increments;
+	uint16_t bits;
 
-	/*  caldac */
-	s = &dev->subdevices[6];
-	s->type = COMEDI_SUBD_CALIB;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
-	s->n_chan = 8;
-	if (board(dev)->layout == LAYOUT_4020)
-		s->maxdata = 0xfff;
-	else
-		s->maxdata = 0xff;
-	s->insn_read = calib_read_insn;
-	s->insn_write = calib_write_insn;
-	for (i = 0; i < s->n_chan; i++)
-		caldac_write(dev, i, s->maxdata / 2);
+	if (num_entries < increment_size)
+		num_entries = increment_size;
+	if (num_entries > fifo->max_segment_length)
+		num_entries = fifo->max_segment_length;
 
-	/*  2 channel ad8402 potentiometer */
-	s = &dev->subdevices[7];
-	if (board(dev)->layout == LAYOUT_64XX) {
-		s->type = COMEDI_SUBD_CALIB;
-		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
-		s->n_chan = 2;
-		s->insn_read = ad8402_read_insn;
-		s->insn_write = ad8402_write_insn;
-		s->maxdata = 0xff;
-		for (i = 0; i < s->n_chan; i++)
-			ad8402_write(dev, i, s->maxdata / 2);
-	} else
-		s->type = COMEDI_SUBD_UNUSED;
+	/*  1 == 256 entries, 2 == 512 entries, etc */
+	num_increments = (num_entries + increment_size / 2) / increment_size;
 
-	/* serial EEPROM, if present */
-	s = &dev->subdevices[8];
-	if (readl(priv(dev)->plx9080_iobase + PLX_CONTROL_REG) & CTL_EECHK) {
-		s->type = COMEDI_SUBD_MEMORY;
-		s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
-		s->n_chan = 128;
-		s->maxdata = 0xffff;
-		s->insn_read = eeprom_read_insn;
-	} else
-		s->type = COMEDI_SUBD_UNUSED;
+	bits = (~(num_increments - 1)) & fifo->fifo_size_reg_mask;
+	devpriv->fifo_size_bits &= ~fifo->fifo_size_reg_mask;
+	devpriv->fifo_size_bits |= bits;
+	writew(devpriv->fifo_size_bits,
+	       devpriv->main_iobase + FIFO_SIZE_REG);
 
-	/*  user counter subd XXX */
-	s = &dev->subdevices[9];
-	s->type = COMEDI_SUBD_UNUSED;
+	devpriv->ai_fifo_segment_length = num_increments * increment_size;
 
-	return 0;
-}
+	DEBUG_PRINT("set hardware fifo segment length to %i\n",
+		    devpriv->ai_fifo_segment_length);
 
-static void disable_plx_interrupts(struct comedi_device *dev)
-{
-	priv(dev)->plx_intcsr_bits = 0;
-	writel(priv(dev)->plx_intcsr_bits,
-	       priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
+	return devpriv->ai_fifo_segment_length;
 }
 
-static void init_stc_registers(struct comedi_device *dev)
+/* adjusts the size of hardware fifo (which determines block size for dma xfers) */
+static int set_ai_fifo_size(struct comedi_device *dev, unsigned int num_samples)
 {
-	uint16_t bits;
-	unsigned long flags;
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	unsigned int num_fifo_entries;
+	int retval;
+	const struct hw_fifo_info *const fifo = thisboard->ai_fifo;
 
-	spin_lock_irqsave(&dev->spinlock, flags);
+	num_fifo_entries = num_samples / fifo->sample_packing_ratio;
 
-	/*  bit should be set for 6025, although docs say boards with <= 16 chans should be cleared XXX */
+	retval = set_ai_fifo_segment_length(dev,
+					    num_fifo_entries /
+					    fifo->num_segments);
+	if (retval < 0)
+		return retval;
+
+	num_samples = retval * fifo->num_segments * fifo->sample_packing_ratio;
+
+	DEBUG_PRINT("set hardware fifo size to %i\n", num_samples);
+
+	return num_samples;
+}
+
+/* query length of fifo */
+static unsigned int ai_fifo_size(struct comedi_device *dev)
+{
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
+
+	return devpriv->ai_fifo_segment_length *
+	       thisboard->ai_fifo->num_segments *
+	       thisboard->ai_fifo->sample_packing_ratio;
+}
+
+static void init_stc_registers(struct comedi_device *dev)
+{
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
+	uint16_t bits;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->spinlock, flags);
+
+	/*  bit should be set for 6025,
+	 *  although docs say boards with <= 16 chans should be cleared XXX */
 	if (1)
-		priv(dev)->adc_control1_bits |= ADC_QUEUE_CONFIG_BIT;
-	writew(priv(dev)->adc_control1_bits,
-	       priv(dev)->main_iobase + ADC_CONTROL1_REG);
+		devpriv->adc_control1_bits |= ADC_QUEUE_CONFIG_BIT;
+	writew(devpriv->adc_control1_bits,
+	       devpriv->main_iobase + ADC_CONTROL1_REG);
 
 	/*  6402/16 manual says this register must be initialized to 0xff? */
-	writew(0xff, priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG);
+	writew(0xff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG);
 
 	bits = SLOW_DAC_BIT | DMA_CH_SELECT_BIT;
-	if (board(dev)->layout == LAYOUT_4020)
+	if (thisboard->layout == LAYOUT_4020)
 		bits |= INTERNAL_CLOCK_4020_BITS;
-	priv(dev)->hw_config_bits |= bits;
-	writew(priv(dev)->hw_config_bits,
-	       priv(dev)->main_iobase + HW_CONFIG_REG);
+	devpriv->hw_config_bits |= bits;
+	writew(devpriv->hw_config_bits,
+	       devpriv->main_iobase + HW_CONFIG_REG);
 
-	writew(0, priv(dev)->main_iobase + DAQ_SYNC_REG);
-	writew(0, priv(dev)->main_iobase + CALIBRATION_REG);
+	writew(0, devpriv->main_iobase + DAQ_SYNC_REG);
+	writew(0, devpriv->main_iobase + CALIBRATION_REG);
 
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
 	/*  set fifos to maximum size */
-	priv(dev)->fifo_size_bits |= DAC_FIFO_BITS;
+	devpriv->fifo_size_bits |= DAC_FIFO_BITS;
 	set_ai_fifo_segment_length(dev,
-				   board(dev)->ai_fifo->max_segment_length);
+				   thisboard->ai_fifo->max_segment_length);
 
-	priv(dev)->dac_control1_bits = DAC_OUTPUT_ENABLE_BIT;
-	priv(dev)->intr_enable_bits =	/* EN_DAC_INTR_SRC_BIT | DAC_INTR_QEMPTY_BITS | */
-	    EN_DAC_DONE_INTR_BIT | EN_DAC_UNDERRUN_BIT;
-	writew(priv(dev)->intr_enable_bits,
-	       priv(dev)->main_iobase + INTR_ENABLE_REG);
+	devpriv->dac_control1_bits = DAC_OUTPUT_ENABLE_BIT;
+	devpriv->intr_enable_bits =
+		/* EN_DAC_INTR_SRC_BIT | DAC_INTR_QEMPTY_BITS | */
+		EN_DAC_DONE_INTR_BIT | EN_DAC_UNDERRUN_BIT;
+	writew(devpriv->intr_enable_bits,
+	       devpriv->main_iobase + INTR_ENABLE_REG);
 
 	disable_ai_pacing(dev);
 };
 
 static int alloc_and_init_dma_members(struct comedi_device *dev)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct pcidas64_private *devpriv = dev->private;
 	int i;
 
 	/*  alocate pci dma buffers */
-	for (i = 0; i < ai_dma_ring_count(board(dev)); i++) {
-		priv(dev)->ai_buffer[i] =
-		    pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE,
-					 &priv(dev)->ai_buffer_bus_addr[i]);
-		if (priv(dev)->ai_buffer[i] == NULL)
+	for (i = 0; i < ai_dma_ring_count(thisboard); i++) {
+		devpriv->ai_buffer[i] =
+			pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE,
+					     &devpriv->ai_buffer_bus_addr[i]);
+		if (devpriv->ai_buffer[i] == NULL)
 			return -ENOMEM;
 
 	}
 	for (i = 0; i < AO_DMA_RING_COUNT; i++) {
-		if (ao_cmd_is_supported(board(dev))) {
-			priv(dev)->ao_buffer[i] =
-			    pci_alloc_consistent(pcidev,
-						 DMA_BUFFER_SIZE,
-						 &priv(dev)->
-						 ao_buffer_bus_addr[i]);
-			if (priv(dev)->ao_buffer[i] == NULL)
+		if (ao_cmd_is_supported(thisboard)) {
+			devpriv->ao_buffer[i] =
+				pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE,
+						     &devpriv->
+						      ao_buffer_bus_addr[i]);
+			if (devpriv->ao_buffer[i] == NULL)
 				return -ENOMEM;
 
 		}
 	}
 	/*  allocate dma descriptors */
-	priv(dev)->ai_dma_desc =
-	    pci_alloc_consistent(pcidev,
-				 sizeof(struct plx_dma_desc) *
-				 ai_dma_ring_count(board(dev)),
-				 &priv(dev)->ai_dma_desc_bus_addr);
-	if (priv(dev)->ai_dma_desc == NULL)
+	devpriv->ai_dma_desc =
+		pci_alloc_consistent(pcidev, sizeof(struct plx_dma_desc) *
+				     ai_dma_ring_count(thisboard),
+				     &devpriv->ai_dma_desc_bus_addr);
+	if (devpriv->ai_dma_desc == NULL)
 		return -ENOMEM;
 
-	DEBUG_PRINT("ai dma descriptors start at bus addr 0x%x\n",
-		    priv(dev)->ai_dma_desc_bus_addr);
-	if (ao_cmd_is_supported(board(dev))) {
-		priv(dev)->ao_dma_desc =
-		    pci_alloc_consistent(pcidev,
-					 sizeof(struct plx_dma_desc) *
-					 AO_DMA_RING_COUNT,
-					 &priv(dev)->ao_dma_desc_bus_addr);
-		if (priv(dev)->ao_dma_desc == NULL)
+	DEBUG_PRINT("ai dma descriptors start at bus addr 0x%llx\n",
+		    (unsigned long long)devpriv->ai_dma_desc_bus_addr);
+	if (ao_cmd_is_supported(thisboard)) {
+		devpriv->ao_dma_desc =
+			pci_alloc_consistent(pcidev,
+					     sizeof(struct plx_dma_desc) *
+					     AO_DMA_RING_COUNT,
+					     &devpriv->ao_dma_desc_bus_addr);
+		if (devpriv->ao_dma_desc == NULL)
 			return -ENOMEM;
 
-		DEBUG_PRINT("ao dma descriptors start at bus addr 0x%x\n",
-			    priv(dev)->ao_dma_desc_bus_addr);
+		DEBUG_PRINT("ao dma descriptors start at bus addr 0x%llx\n",
+			    (unsigned long long)devpriv->ao_dma_desc_bus_addr);
 	}
 	/*  initialize dma descriptors */
-	for (i = 0; i < ai_dma_ring_count(board(dev)); i++) {
-		priv(dev)->ai_dma_desc[i].pci_start_addr =
-		    cpu_to_le32(priv(dev)->ai_buffer_bus_addr[i]);
-		if (board(dev)->layout == LAYOUT_4020)
-			priv(dev)->ai_dma_desc[i].local_start_addr =
-			    cpu_to_le32(priv(dev)->local1_iobase +
-					ADC_FIFO_REG);
+	for (i = 0; i < ai_dma_ring_count(thisboard); i++) {
+		devpriv->ai_dma_desc[i].pci_start_addr =
+			cpu_to_le32(devpriv->ai_buffer_bus_addr[i]);
+		if (thisboard->layout == LAYOUT_4020)
+			devpriv->ai_dma_desc[i].local_start_addr =
+				cpu_to_le32(devpriv->local1_iobase +
+					    ADC_FIFO_REG);
 		else
-			priv(dev)->ai_dma_desc[i].local_start_addr =
-			    cpu_to_le32(priv(dev)->local0_iobase +
-					ADC_FIFO_REG);
-		priv(dev)->ai_dma_desc[i].transfer_size = cpu_to_le32(0);
-		priv(dev)->ai_dma_desc[i].next =
-		    cpu_to_le32((priv(dev)->ai_dma_desc_bus_addr + ((i +
-								     1) %
-								    ai_dma_ring_count
-								    (board
-								     (dev))) *
-				 sizeof(priv(dev)->ai_dma_desc[0])) |
-				PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT |
-				PLX_XFER_LOCAL_TO_PCI);
+			devpriv->ai_dma_desc[i].local_start_addr =
+				cpu_to_le32(devpriv->local0_iobase +
+					    ADC_FIFO_REG);
+		devpriv->ai_dma_desc[i].transfer_size = cpu_to_le32(0);
+		devpriv->ai_dma_desc[i].next =
+			cpu_to_le32((devpriv->ai_dma_desc_bus_addr +
+				     ((i + 1) % ai_dma_ring_count(thisboard)) *
+				     sizeof(devpriv->ai_dma_desc[0])) |
+				    PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT |
+				    PLX_XFER_LOCAL_TO_PCI);
 	}
-	if (ao_cmd_is_supported(board(dev))) {
+	if (ao_cmd_is_supported(thisboard)) {
 		for (i = 0; i < AO_DMA_RING_COUNT; i++) {
-			priv(dev)->ao_dma_desc[i].pci_start_addr =
-			    cpu_to_le32(priv(dev)->ao_buffer_bus_addr[i]);
-			priv(dev)->ao_dma_desc[i].local_start_addr =
-			    cpu_to_le32(priv(dev)->local0_iobase +
-					DAC_FIFO_REG);
-			priv(dev)->ao_dma_desc[i].transfer_size =
-			    cpu_to_le32(0);
-			priv(dev)->ao_dma_desc[i].next =
-			    cpu_to_le32((priv(dev)->ao_dma_desc_bus_addr +
-					 ((i + 1) % (AO_DMA_RING_COUNT)) *
-					 sizeof(priv(dev)->ao_dma_desc[0])) |
-					PLX_DESC_IN_PCI_BIT |
-					PLX_INTR_TERM_COUNT);
+			devpriv->ao_dma_desc[i].pci_start_addr =
+				cpu_to_le32(devpriv->ao_buffer_bus_addr[i]);
+			devpriv->ao_dma_desc[i].local_start_addr =
+				cpu_to_le32(devpriv->local0_iobase +
+					    DAC_FIFO_REG);
+			devpriv->ao_dma_desc[i].transfer_size = cpu_to_le32(0);
+			devpriv->ao_dma_desc[i].next =
+				cpu_to_le32((devpriv->ao_dma_desc_bus_addr +
+					     ((i + 1) % (AO_DMA_RING_COUNT)) *
+					     sizeof(devpriv->ao_dma_desc[0])) |
+					    PLX_DESC_IN_PCI_BIT |
+					    PLX_INTR_TERM_COUNT);
 		}
 	}
 	return 0;
@@ -1649,216 +1610,140 @@ static inline void warn_external_queue(struct comedi_device *dev)
 		     "Use internal AI channel queue (channels must be consecutive and use same range/aref)");
 }
 
-static struct pci_dev *cb_pcidas64_find_pci_dev(struct comedi_device *dev,
-						struct comedi_devconfig *it)
+/* Their i2c requires a huge delay on setting clock or data high for some reason */
+static const int i2c_high_udelay = 1000;
+static const int i2c_low_udelay = 10;
+
+/* set i2c data line high or low */
+static void i2c_set_sda(struct comedi_device *dev, int state)
 {
-	struct pci_dev *pcidev = NULL;
-	int bus = it->options[0];
-	int slot = it->options[1];
-	int i;
+	struct pcidas64_private *devpriv = dev->private;
+	static const int data_bit = CTL_EE_W;
+	void __iomem *plx_control_addr = devpriv->plx9080_iobase +
+					 PLX_CONTROL_REG;
 
-	for_each_pci_dev(pcidev) {
-		if (bus || slot) {
-			if (bus != pcidev->bus->number ||
-			    slot != PCI_SLOT(pcidev->devfn))
-				continue;
-		}
-		if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
-			continue;
-
-		for (i = 0; i < ARRAY_SIZE(pcidas64_boards); i++) {
-			if (pcidas64_boards[i].device_id != pcidev->device)
-				continue;
-			dev->board_ptr = pcidas64_boards + i;
-			return pcidev;
-		}
+	if (state) {
+		/*  set data line high */
+		devpriv->plx_control_bits &= ~data_bit;
+		writel(devpriv->plx_control_bits, plx_control_addr);
+		udelay(i2c_high_udelay);
+	} else {		/*  set data line low */
+
+		devpriv->plx_control_bits |= data_bit;
+		writel(devpriv->plx_control_bits, plx_control_addr);
+		udelay(i2c_low_udelay);
 	}
-	dev_err(dev->class_dev,
-		"No supported board found! (req. bus %d, slot %d)\n",
-		bus, slot);
-	return NULL;
 }
 
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board.
- */
-static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
+/* set i2c clock line high or low */
+static void i2c_set_scl(struct comedi_device *dev, int state)
 {
-	struct pci_dev *pcidev;
-	uint32_t local_range, local_decode;
-	int retval;
-
-/*
- * Allocate the private structure area.
- */
-	if (alloc_private(dev, sizeof(struct pcidas64_private)) < 0)
-		return -ENOMEM;
+	struct pcidas64_private *devpriv = dev->private;
+	static const int clock_bit = CTL_USERO;
+	void __iomem *plx_control_addr = devpriv->plx9080_iobase +
+					 PLX_CONTROL_REG;
 
-	pcidev = cb_pcidas64_find_pci_dev(dev, it);
-	if (!pcidev)
-		return -EIO;
-	comedi_set_hw_dev(dev, &pcidev->dev);
+	if (state) {
+		/*  set clock line high */
+		devpriv->plx_control_bits &= ~clock_bit;
+		writel(devpriv->plx_control_bits, plx_control_addr);
+		udelay(i2c_high_udelay);
+	} else {		/*  set clock line low */
 
-	if (comedi_pci_enable(pcidev, dev->driver->driver_name)) {
-		dev_warn(dev->class_dev,
-			 "failed to enable PCI device and request regions\n");
-		return -EIO;
+		devpriv->plx_control_bits |= clock_bit;
+		writel(devpriv->plx_control_bits, plx_control_addr);
+		udelay(i2c_low_udelay);
 	}
-	pci_set_master(pcidev);
-
-	/* Initialize dev->board_name */
-	dev->board_name = board(dev)->name;
+}
 
-	dev->iobase = pci_resource_start(pcidev, MAIN_BADDRINDEX);
+static void i2c_write_byte(struct comedi_device *dev, uint8_t byte)
+{
+	uint8_t bit;
+	unsigned int num_bits = 8;
 
-	priv(dev)->plx9080_phys_iobase =
-	    pci_resource_start(pcidev, PLX9080_BADDRINDEX);
-	priv(dev)->main_phys_iobase = dev->iobase;
-	priv(dev)->dio_counter_phys_iobase =
-	    pci_resource_start(pcidev, DIO_COUNTER_BADDRINDEX);
+	DEBUG_PRINT("writing to i2c byte 0x%x\n", byte);
 
-	/*  remap, won't work with 2.0 kernels but who cares */
-	priv(dev)->plx9080_iobase = ioremap(priv(dev)->plx9080_phys_iobase,
-					    pci_resource_len(pcidev,
-							     PLX9080_BADDRINDEX));
-	priv(dev)->main_iobase =
-	    ioremap(priv(dev)->main_phys_iobase,
-		    pci_resource_len(pcidev, MAIN_BADDRINDEX));
-	priv(dev)->dio_counter_iobase =
-	    ioremap(priv(dev)->dio_counter_phys_iobase,
-		    pci_resource_len(pcidev, DIO_COUNTER_BADDRINDEX));
-
-	if (!priv(dev)->plx9080_iobase || !priv(dev)->main_iobase
-	    || !priv(dev)->dio_counter_iobase) {
-		dev_warn(dev->class_dev, "failed to remap io memory\n");
-		return -ENOMEM;
+	for (bit = 1 << (num_bits - 1); bit; bit >>= 1) {
+		i2c_set_scl(dev, 0);
+		if ((byte & bit))
+			i2c_set_sda(dev, 1);
+		else
+			i2c_set_sda(dev, 0);
+		i2c_set_scl(dev, 1);
 	}
+}
 
-	DEBUG_PRINT(" plx9080 remapped to 0x%p\n", priv(dev)->plx9080_iobase);
-	DEBUG_PRINT(" main remapped to 0x%p\n", priv(dev)->main_iobase);
-	DEBUG_PRINT(" diocounter remapped to 0x%p\n",
-		    priv(dev)->dio_counter_iobase);
-
-	/*  figure out what local addresses are */
-	local_range =
-	    readl(priv(dev)->plx9080_iobase + PLX_LAS0RNG_REG) & LRNG_MEM_MASK;
-	local_decode =
-	    readl(priv(dev)->plx9080_iobase +
-		  PLX_LAS0MAP_REG) & local_range & LMAP_MEM_MASK;
-	priv(dev)->local0_iobase =
-	    ((uint32_t) priv(dev)->main_phys_iobase & ~local_range) |
-	    local_decode;
-	local_range =
-	    readl(priv(dev)->plx9080_iobase + PLX_LAS1RNG_REG) & LRNG_MEM_MASK;
-	local_decode =
-	    readl(priv(dev)->plx9080_iobase +
-		  PLX_LAS1MAP_REG) & local_range & LMAP_MEM_MASK;
-	priv(dev)->local1_iobase =
-	    ((uint32_t) priv(dev)->dio_counter_phys_iobase & ~local_range) |
-	    local_decode;
-
-	DEBUG_PRINT(" local 0 io addr 0x%x\n", priv(dev)->local0_iobase);
-	DEBUG_PRINT(" local 1 io addr 0x%x\n", priv(dev)->local1_iobase);
-
-	retval = alloc_and_init_dma_members(dev);
-	if (retval < 0)
-		return retval;
-
-	priv(dev)->hw_revision =
-	    hw_revision(dev, readw(priv(dev)->main_iobase + HW_STATUS_REG));
-	dev_dbg(dev->class_dev, "stc hardware revision %i\n",
-		priv(dev)->hw_revision);
-	init_plx9080(dev);
-	init_stc_registers(dev);
-	/*  get irq */
-	if (request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED,
-			"cb_pcidas64", dev)) {
-		dev_dbg(dev->class_dev, "unable to allocate irq %u\n",
-			pcidev->irq);
-		return -EINVAL;
-	}
-	dev->irq = pcidev->irq;
-	dev_dbg(dev->class_dev, "irq %u\n", dev->irq);
+/* we can't really read the lines, so fake it */
+static int i2c_read_ack(struct comedi_device *dev)
+{
+	i2c_set_scl(dev, 0);
+	i2c_set_sda(dev, 1);
+	i2c_set_scl(dev, 1);
 
-	retval = setup_subdevices(dev);
-	if (retval < 0)
-		return retval;
+	return 0;		/*  return fake acknowledge bit */
+}
 
+/* send start bit */
+static void i2c_start(struct comedi_device *dev)
+{
+	i2c_set_scl(dev, 1);
+	i2c_set_sda(dev, 1);
+	i2c_set_sda(dev, 0);
+}
 
-	return 0;
+/* send stop bit */
+static void i2c_stop(struct comedi_device *dev)
+{
+	i2c_set_scl(dev, 0);
+	i2c_set_sda(dev, 0);
+	i2c_set_scl(dev, 1);
+	i2c_set_sda(dev, 1);
 }
 
-static void detach(struct comedi_device *dev)
+static void i2c_write(struct comedi_device *dev, unsigned int address,
+		      const uint8_t *data, unsigned int length)
 {
-	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int i;
+	uint8_t bitstream;
+	static const int read_bit = 0x1;
 
-	if (dev->irq)
-		free_irq(dev->irq, dev);
-	if (priv(dev)) {
-		if (pcidev) {
-			if (priv(dev)->plx9080_iobase) {
-				disable_plx_interrupts(dev);
-				iounmap(priv(dev)->plx9080_iobase);
-			}
-			if (priv(dev)->main_iobase)
-				iounmap(priv(dev)->main_iobase);
-			if (priv(dev)->dio_counter_iobase)
-				iounmap(priv(dev)->dio_counter_iobase);
-			/*  free pci dma buffers */
-			for (i = 0; i < ai_dma_ring_count(board(dev)); i++) {
-				if (priv(dev)->ai_buffer[i])
-					pci_free_consistent(pcidev,
-							    DMA_BUFFER_SIZE,
-							    priv(dev)->
-							    ai_buffer[i],
-							    priv
-							    (dev)->ai_buffer_bus_addr
-							    [i]);
-			}
-			for (i = 0; i < AO_DMA_RING_COUNT; i++) {
-				if (priv(dev)->ao_buffer[i])
-					pci_free_consistent(pcidev,
-							    DMA_BUFFER_SIZE,
-							    priv(dev)->
-							    ao_buffer[i],
-							    priv
-							    (dev)->ao_buffer_bus_addr
-							    [i]);
-			}
-			/*  free dma descriptors */
-			if (priv(dev)->ai_dma_desc)
-				pci_free_consistent(pcidev,
-						    sizeof(struct plx_dma_desc)
-						    *
-						    ai_dma_ring_count(board
-								      (dev)),
-						    priv(dev)->ai_dma_desc,
-						    priv(dev)->
-						    ai_dma_desc_bus_addr);
-			if (priv(dev)->ao_dma_desc)
-				pci_free_consistent(pcidev,
-						    sizeof(struct plx_dma_desc)
-						    * AO_DMA_RING_COUNT,
-						    priv(dev)->ao_dma_desc,
-						    priv(dev)->
-						    ao_dma_desc_bus_addr);
-		}
-	}
-	if (dev->subdevices)
-		subdev_8255_cleanup(dev, &dev->subdevices[4]);
-	if (pcidev) {
-		if (dev->iobase)
-			comedi_pci_disable(pcidev);
+	/* XXX need mutex to prevent simultaneous attempts to access
+	 * eeprom and i2c bus */
 
-		pci_dev_put(pcidev);
+	/*  make sure we dont send anything to eeprom */
+	devpriv->plx_control_bits &= ~CTL_EE_CS;
+
+	i2c_stop(dev);
+	i2c_start(dev);
+
+	/*  send address and write bit */
+	bitstream = (address << 1) & ~read_bit;
+	i2c_write_byte(dev, bitstream);
+
+	/*  get acknowledge */
+	if (i2c_read_ack(dev) != 0) {
+		comedi_error(dev, "i2c write failed: no acknowledge");
+		i2c_stop(dev);
+		return;
+	}
+	/*  write data bytes */
+	for (i = 0; i < length; i++) {
+		i2c_write_byte(dev, data[i]);
+		if (i2c_read_ack(dev) != 0) {
+			comedi_error(dev, "i2c write failed: no acknowledge");
+			i2c_stop(dev);
+			return;
+		}
 	}
+	i2c_stop(dev);
 }
 
 static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 		    struct comedi_insn *insn, unsigned int *data)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int bits = 0, n, i;
 	unsigned int channel, range, aref;
 	unsigned long flags;
@@ -1875,35 +1760,37 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 
 	spin_lock_irqsave(&dev->spinlock, flags);
 	if (insn->chanspec & CR_ALT_FILTER)
-		priv(dev)->adc_control1_bits |= ADC_DITHER_BIT;
+		devpriv->adc_control1_bits |= ADC_DITHER_BIT;
 	else
-		priv(dev)->adc_control1_bits &= ~ADC_DITHER_BIT;
-	writew(priv(dev)->adc_control1_bits,
-	       priv(dev)->main_iobase + ADC_CONTROL1_REG);
+		devpriv->adc_control1_bits &= ~ADC_DITHER_BIT;
+	writew(devpriv->adc_control1_bits,
+	       devpriv->main_iobase + ADC_CONTROL1_REG);
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
-	if (board(dev)->layout != LAYOUT_4020) {
+	if (thisboard->layout != LAYOUT_4020) {
 		/*  use internal queue */
-		priv(dev)->hw_config_bits &= ~EXT_QUEUE_BIT;
-		writew(priv(dev)->hw_config_bits,
-		       priv(dev)->main_iobase + HW_CONFIG_REG);
+		devpriv->hw_config_bits &= ~EXT_QUEUE_BIT;
+		writew(devpriv->hw_config_bits,
+		       devpriv->main_iobase + HW_CONFIG_REG);
 
 		/*  ALT_SOURCE is internal calibration reference */
 		if (insn->chanspec & CR_ALT_SOURCE) {
 			unsigned int cal_en_bit;
 
 			DEBUG_PRINT("reading calibration source\n");
-			if (board(dev)->layout == LAYOUT_60XX)
+			if (thisboard->layout == LAYOUT_60XX)
 				cal_en_bit = CAL_EN_60XX_BIT;
 			else
 				cal_en_bit = CAL_EN_64XX_BIT;
-			/*  select internal reference source to connect to channel 0 */
+			/*  select internal reference source to connect
+			 *  to channel 0 */
 			writew(cal_en_bit |
-			       adc_src_bits(priv(dev)->calibration_source),
-			       priv(dev)->main_iobase + CALIBRATION_REG);
+			       adc_src_bits(devpriv->calibration_source),
+			       devpriv->main_iobase + CALIBRATION_REG);
 		} else {
-			/*  make sure internal calibration source is turned off */
-			writew(0, priv(dev)->main_iobase + CALIBRATION_REG);
+			/*  make sure internal calibration source
+			 *  is turned off */
+			writew(0, devpriv->main_iobase + CALIBRATION_REG);
 		}
 		/*  load internal queue */
 		bits = 0;
@@ -1916,56 +1803,56 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 		bits |= adc_chan_bits(channel);
 		/*  set stop channel */
 		writew(adc_chan_bits(channel),
-		       priv(dev)->main_iobase + ADC_QUEUE_HIGH_REG);
+		       devpriv->main_iobase + ADC_QUEUE_HIGH_REG);
 		/*  set start channel, and rest of settings */
-		writew(bits, priv(dev)->main_iobase + ADC_QUEUE_LOAD_REG);
+		writew(bits, devpriv->main_iobase + ADC_QUEUE_LOAD_REG);
 	} else {
-		uint8_t old_cal_range_bits = priv(dev)->i2c_cal_range_bits;
+		uint8_t old_cal_range_bits = devpriv->i2c_cal_range_bits;
 
-		priv(dev)->i2c_cal_range_bits &= ~ADC_SRC_4020_MASK;
+		devpriv->i2c_cal_range_bits &= ~ADC_SRC_4020_MASK;
 		if (insn->chanspec & CR_ALT_SOURCE) {
 			DEBUG_PRINT("reading calibration source\n");
-			priv(dev)->i2c_cal_range_bits |=
-			    adc_src_4020_bits(priv(dev)->calibration_source);
+			devpriv->i2c_cal_range_bits |=
+				adc_src_4020_bits(devpriv->calibration_source);
 		} else {	/* select BNC inputs */
-			priv(dev)->i2c_cal_range_bits |= adc_src_4020_bits(4);
+			devpriv->i2c_cal_range_bits |= adc_src_4020_bits(4);
 		}
 		/*  select range */
 		if (range == 0)
-			priv(dev)->i2c_cal_range_bits |= attenuate_bit(channel);
+			devpriv->i2c_cal_range_bits |= attenuate_bit(channel);
 		else
-			priv(dev)->i2c_cal_range_bits &=
-			    ~attenuate_bit(channel);
-		/*  update calibration/range i2c register only if necessary, as it is very slow */
-		if (old_cal_range_bits != priv(dev)->i2c_cal_range_bits) {
-			uint8_t i2c_data = priv(dev)->i2c_cal_range_bits;
+			devpriv->i2c_cal_range_bits &= ~attenuate_bit(channel);
+		/*  update calibration/range i2c register only if necessary,
+		 *  as it is very slow */
+		if (old_cal_range_bits != devpriv->i2c_cal_range_bits) {
+			uint8_t i2c_data = devpriv->i2c_cal_range_bits;
 			i2c_write(dev, RANGE_CAL_I2C_ADDR, &i2c_data,
 				  sizeof(i2c_data));
 		}
 
-		/* 4020 manual asks that sample interval register to be set before writing to convert register.
-		 * Using somewhat arbitrary setting of 4 master clock ticks = 0.1 usec */
-		writew(0,
-		       priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG);
-		writew(2,
-		       priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG);
+		/* 4020 manual asks that sample interval register to be set
+		 * before writing to convert register.
+		 * Using somewhat arbitrary setting of 4 master clock ticks
+		 * = 0.1 usec */
+		writew(0, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG);
+		writew(2, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG);
 	}
 
 	for (n = 0; n < insn->n; n++) {
 
 		/*  clear adc buffer (inside loop for 4020 sake) */
-		writew(0, priv(dev)->main_iobase + ADC_BUFFER_CLEAR_REG);
+		writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG);
 
 		/* trigger conversion, bits sent only matter for 4020 */
 		writew(adc_convert_chan_4020_bits(CR_CHAN(insn->chanspec)),
-		       priv(dev)->main_iobase + ADC_CONVERT_REG);
+		       devpriv->main_iobase + ADC_CONVERT_REG);
 
 		/*  wait for data */
 		for (i = 0; i < timeout; i++) {
-			bits = readw(priv(dev)->main_iobase + HW_STATUS_REG);
+			bits = readw(devpriv->main_iobase + HW_STATUS_REG);
 			DEBUG_PRINT(" pipe bits 0x%x\n", pipe_full_bits(bits));
-			if (board(dev)->layout == LAYOUT_4020) {
-				if (readw(priv(dev)->main_iobase +
+			if (thisboard->layout == LAYOUT_4020) {
+				if (readw(devpriv->main_iobase +
 					  ADC_WRITE_PNTR_REG))
 					break;
 			} else {
@@ -1977,16 +1864,14 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 		DEBUG_PRINT(" looped %i times waiting for data\n", i);
 		if (i == timeout) {
 			comedi_error(dev, " analog input read insn timed out");
-			printk(" status 0x%x\n", bits);
+			dev_info(dev->class_dev, "status 0x%x\n", bits);
 			return -ETIME;
 		}
-		if (board(dev)->layout == LAYOUT_4020)
-			data[n] =
-			    readl(priv(dev)->dio_counter_iobase +
-				  ADC_FIFO_REG) & 0xffff;
+		if (thisboard->layout == LAYOUT_4020)
+			data[n] = readl(devpriv->dio_counter_iobase +
+					ADC_FIFO_REG) & 0xffff;
 		else
-			data[n] =
-			    readw(priv(dev)->main_iobase + PIPE1_READ_REG);
+			data[n] = readw(devpriv->main_iobase + PIPE1_READ_REG);
 	}
 
 	return n;
@@ -1995,10 +1880,12 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int ai_config_calibration_source(struct comedi_device *dev,
 					unsigned int *data)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int source = data[1];
 	int num_calibration_sources;
 
-	if (board(dev)->layout == LAYOUT_60XX)
+	if (thisboard->layout == LAYOUT_60XX)
 		num_calibration_sources = 16;
 	else
 		num_calibration_sources = 8;
@@ -2009,23 +1896,24 @@ static int ai_config_calibration_source(struct comedi_device *dev,
 	}
 
 	DEBUG_PRINT("setting calibration source to %i\n", source);
-	priv(dev)->calibration_source = source;
+	devpriv->calibration_source = source;
 
 	return 2;
 }
 
 static int ai_config_block_size(struct comedi_device *dev, unsigned int *data)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
 	int fifo_size;
-	const struct hw_fifo_info *const fifo = board(dev)->ai_fifo;
+	const struct hw_fifo_info *const fifo = thisboard->ai_fifo;
 	unsigned int block_size, requested_block_size;
 	int retval;
 
 	requested_block_size = data[1];
 
 	if (requested_block_size) {
-		fifo_size =
-		    requested_block_size * fifo->num_segments / bytes_in_sample;
+		fifo_size = requested_block_size * fifo->num_segments /
+			    bytes_in_sample;
 
 		retval = set_ai_fifo_size(dev, fifo_size);
 		if (retval < 0)
@@ -2043,6 +1931,7 @@ static int ai_config_block_size(struct comedi_device *dev, unsigned int *data)
 static int ai_config_master_clock_4020(struct comedi_device *dev,
 				       unsigned int *data)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int divisor = data[4];
 	int retval = 0;
 
@@ -2053,8 +1942,8 @@ static int ai_config_master_clock_4020(struct comedi_device *dev,
 
 	switch (data[1]) {
 	case COMEDI_EV_SCAN_BEGIN:
-		priv(dev)->ext_clock.divisor = divisor;
-		priv(dev)->ext_clock.chanspec = data[2];
+		devpriv->ext_clock.divisor = divisor;
+		devpriv->ext_clock.chanspec = data[2];
 		break;
 	default:
 		return -EINVAL;
@@ -2069,8 +1958,9 @@ static int ai_config_master_clock_4020(struct comedi_device *dev,
 /* XXX could add support for 60xx series */
 static int ai_config_master_clock(struct comedi_device *dev, unsigned int *data)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
 
-	switch (board(dev)->layout) {
+	switch (thisboard->layout) {
 	case LAYOUT_4020:
 		return ai_config_master_clock_4020(dev, data);
 		break;
@@ -2104,9 +1994,84 @@ static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
 	return -EINVAL;
 }
 
+/* Gets nearest achievable timing given master clock speed, does not
+ * take into account possible minimum/maximum divisor values.  Used
+ * by other timing checking functions. */
+static unsigned int get_divisor(unsigned int ns, unsigned int flags)
+{
+	unsigned int divisor;
+
+	switch (flags & TRIG_ROUND_MASK) {
+	case TRIG_ROUND_UP:
+		divisor = (ns + TIMER_BASE - 1) / TIMER_BASE;
+		break;
+	case TRIG_ROUND_DOWN:
+		divisor = ns / TIMER_BASE;
+		break;
+	case TRIG_ROUND_NEAREST:
+	default:
+		divisor = (ns + TIMER_BASE / 2) / TIMER_BASE;
+		break;
+	}
+	return divisor;
+}
+
+/* utility function that rounds desired timing to an achievable time, and
+ * sets cmd members appropriately.
+ * adc paces conversions from master clock by dividing by (x + 3) where x is 24 bit number
+ */
+static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
+{
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	unsigned int convert_divisor = 0, scan_divisor;
+	static const int min_convert_divisor = 3;
+	static const int max_convert_divisor =
+		max_counter_value + min_convert_divisor;
+	static const int min_scan_divisor_4020 = 2;
+	unsigned long long max_scan_divisor, min_scan_divisor;
+
+	if (cmd->convert_src == TRIG_TIMER) {
+		if (thisboard->layout == LAYOUT_4020) {
+			cmd->convert_arg = 0;
+		} else {
+			convert_divisor = get_divisor(cmd->convert_arg,
+						      cmd->flags);
+			if (convert_divisor > max_convert_divisor)
+				convert_divisor = max_convert_divisor;
+			if (convert_divisor < min_convert_divisor)
+				convert_divisor = min_convert_divisor;
+			cmd->convert_arg = convert_divisor * TIMER_BASE;
+		}
+	} else if (cmd->convert_src == TRIG_NOW) {
+		cmd->convert_arg = 0;
+	}
+
+	if (cmd->scan_begin_src == TRIG_TIMER) {
+		scan_divisor = get_divisor(cmd->scan_begin_arg, cmd->flags);
+		if (cmd->convert_src == TRIG_TIMER) {
+			/*  XXX check for integer overflows */
+			min_scan_divisor = convert_divisor * cmd->chanlist_len;
+			max_scan_divisor =
+				(convert_divisor * cmd->chanlist_len - 1) +
+				max_counter_value;
+		} else {
+			min_scan_divisor = min_scan_divisor_4020;
+			max_scan_divisor = max_counter_value + min_scan_divisor;
+		}
+		if (scan_divisor > max_scan_divisor)
+			scan_divisor = max_scan_divisor;
+		if (scan_divisor < min_scan_divisor)
+			scan_divisor = min_scan_divisor;
+		cmd->scan_begin_arg = scan_divisor * TIMER_BASE;
+	}
+
+	return;
+}
+
 static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 		      struct comedi_cmd *cmd)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
 	int err = 0;
 	unsigned int tmp_arg, tmp_arg2;
 	int i;
@@ -2118,22 +2083,21 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
 
 	triggers = TRIG_TIMER;
-	if (board(dev)->layout == LAYOUT_4020)
+	if (thisboard->layout == LAYOUT_4020)
 		triggers |= TRIG_OTHER;
 	else
 		triggers |= TRIG_FOLLOW;
 	err |= cfc_check_trigger_src(&cmd->scan_begin_src, triggers);
 
 	triggers = TRIG_TIMER;
-	if (board(dev)->layout == LAYOUT_4020)
+	if (thisboard->layout == LAYOUT_4020)
 		triggers |= TRIG_NOW;
 	else
 		triggers |= TRIG_EXT;
 	err |= cfc_check_trigger_src(&cmd->convert_src, triggers);
-
 	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 	err |= cfc_check_trigger_src(&cmd->stop_src,
-					TRIG_COUNT | TRIG_EXT | TRIG_NONE);
+				     TRIG_COUNT | TRIG_EXT | TRIG_NONE);
 
 	if (err)
 		return 1;
@@ -2156,55 +2120,34 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
 	if (cmd->convert_src == TRIG_TIMER) {
-		if (board(dev)->layout == LAYOUT_4020) {
-			if (cmd->convert_arg) {
-				cmd->convert_arg = 0;
-				err++;
-			}
+		if (thisboard->layout == LAYOUT_4020) {
+			err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 		} else {
-			if (cmd->convert_arg < board(dev)->ai_speed) {
-				cmd->convert_arg = board(dev)->ai_speed;
-				err++;
-			}
-			if (cmd->scan_begin_src == TRIG_TIMER) {
-				/*  if scans are timed faster than conversion rate allows */
-				if (cmd->convert_arg * cmd->chanlist_len >
-				    cmd->scan_begin_arg) {
-					cmd->scan_begin_arg =
-					    cmd->convert_arg *
-					    cmd->chanlist_len;
-					err++;
-				}
-			}
+			err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+							 thisboard->ai_speed);
+			/* if scans are timed faster than conversion rate allows */
+			if (cmd->scan_begin_src == TRIG_TIMER)
+				err |= cfc_check_trigger_arg_min(
+						&cmd->scan_begin_arg,
+						cmd->convert_arg *
+						cmd->chanlist_len);
 		}
 	}
 
-	if (!cmd->chanlist_len) {
-		cmd->chanlist_len = 1;
-		err++;
-	}
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 
 	switch (cmd->stop_src) {
 	case TRIG_EXT:
 		break;
 	case TRIG_COUNT:
-		if (!cmd->stop_arg) {
-			cmd->stop_arg = 1;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
 		break;
 	case TRIG_NONE:
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 		break;
 	default:
 		break;
@@ -2240,7 +2183,7 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 			}
 		}
 		/*  check 4020 chanlist */
-		if (board(dev)->layout == LAYOUT_4020) {
+		if (thisboard->layout == LAYOUT_4020) {
 			unsigned int first_channel = CR_CHAN(cmd->chanlist[0]);
 			for (i = 1; i < cmd->chanlist_len; i++) {
 				if (CR_CHAN(cmd->chanlist[i]) !=
@@ -2279,89 +2222,37 @@ static int use_hw_sample_counter(struct comedi_cmd *cmd)
 static void setup_sample_counters(struct comedi_device *dev,
 				  struct comedi_cmd *cmd)
 {
+	struct pcidas64_private *devpriv = dev->private;
+
 	if (cmd->stop_src == TRIG_COUNT) {
 		/*  set software count */
-		priv(dev)->ai_count = cmd->stop_arg * cmd->chanlist_len;
+		devpriv->ai_count = cmd->stop_arg * cmd->chanlist_len;
 	}
 	/*  load hardware conversion counter */
 	if (use_hw_sample_counter(cmd)) {
 		writew(cmd->stop_arg & 0xffff,
-		       priv(dev)->main_iobase + ADC_COUNT_LOWER_REG);
+		       devpriv->main_iobase + ADC_COUNT_LOWER_REG);
 		writew((cmd->stop_arg >> 16) & 0xff,
-		       priv(dev)->main_iobase + ADC_COUNT_UPPER_REG);
+		       devpriv->main_iobase + ADC_COUNT_UPPER_REG);
 	} else {
-		writew(1, priv(dev)->main_iobase + ADC_COUNT_LOWER_REG);
+		writew(1, devpriv->main_iobase + ADC_COUNT_LOWER_REG);
 	}
 }
 
 static inline unsigned int dma_transfer_size(struct comedi_device *dev)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int num_samples;
 
-	num_samples =
-	    priv(dev)->ai_fifo_segment_length *
-	    board(dev)->ai_fifo->sample_packing_ratio;
+	num_samples = devpriv->ai_fifo_segment_length *
+		      thisboard->ai_fifo->sample_packing_ratio;
 	if (num_samples > DMA_BUFFER_SIZE / sizeof(uint16_t))
 		num_samples = DMA_BUFFER_SIZE / sizeof(uint16_t);
 
 	return num_samples;
 }
 
-static void disable_ai_pacing(struct comedi_device *dev)
-{
-	unsigned long flags;
-
-	disable_ai_interrupts(dev);
-
-	spin_lock_irqsave(&dev->spinlock, flags);
-	priv(dev)->adc_control1_bits &= ~ADC_SW_GATE_BIT;
-	writew(priv(dev)->adc_control1_bits,
-	       priv(dev)->main_iobase + ADC_CONTROL1_REG);
-	spin_unlock_irqrestore(&dev->spinlock, flags);
-
-	/* disable pacing, triggering, etc */
-	writew(ADC_DMA_DISABLE_BIT | ADC_SOFT_GATE_BITS | ADC_GATE_LEVEL_BIT,
-	       priv(dev)->main_iobase + ADC_CONTROL0_REG);
-}
-
-static void disable_ai_interrupts(struct comedi_device *dev)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev->spinlock, flags);
-	priv(dev)->intr_enable_bits &=
-	    ~EN_ADC_INTR_SRC_BIT & ~EN_ADC_DONE_INTR_BIT &
-	    ~EN_ADC_ACTIVE_INTR_BIT & ~EN_ADC_STOP_INTR_BIT &
-	    ~EN_ADC_OVERRUN_BIT & ~ADC_INTR_SRC_MASK;
-	writew(priv(dev)->intr_enable_bits,
-	       priv(dev)->main_iobase + INTR_ENABLE_REG);
-	spin_unlock_irqrestore(&dev->spinlock, flags);
-
-	DEBUG_PRINT("intr enable bits 0x%x\n", priv(dev)->intr_enable_bits);
-}
-
-static void enable_ai_interrupts(struct comedi_device *dev,
-				 const struct comedi_cmd *cmd)
-{
-	uint32_t bits;
-	unsigned long flags;
-
-	bits = EN_ADC_OVERRUN_BIT | EN_ADC_DONE_INTR_BIT |
-	    EN_ADC_ACTIVE_INTR_BIT | EN_ADC_STOP_INTR_BIT;
-	/*  Use pio transfer and interrupt on end of conversion if TRIG_WAKE_EOS flag is set. */
-	if (cmd->flags & TRIG_WAKE_EOS) {
-		/*  4020 doesn't support pio transfers except for fifo dregs */
-		if (board(dev)->layout != LAYOUT_4020)
-			bits |= ADC_INTR_EOSCAN_BITS | EN_ADC_INTR_SRC_BIT;
-	}
-	spin_lock_irqsave(&dev->spinlock, flags);
-	priv(dev)->intr_enable_bits |= bits;
-	writew(priv(dev)->intr_enable_bits,
-	       priv(dev)->main_iobase + INTR_ENABLE_REG);
-	DEBUG_PRINT("intr enable bits 0x%x\n", priv(dev)->intr_enable_bits);
-	spin_unlock_irqrestore(&dev->spinlock, flags);
-}
-
 static uint32_t ai_convert_counter_6xxx(const struct comedi_device *dev,
 					const struct comedi_cmd *cmd)
 {
@@ -2373,12 +2264,13 @@ static uint32_t ai_scan_counter_6xxx(struct comedi_device *dev,
 				     struct comedi_cmd *cmd)
 {
 	uint32_t count;
+
 	/*  figure out how long we need to delay at end of scan */
 	switch (cmd->scan_begin_src) {
 	case TRIG_TIMER:
 		count = (cmd->scan_begin_arg -
-			 (cmd->convert_arg * (cmd->chanlist_len - 1)))
-		    / TIMER_BASE;
+			 (cmd->convert_arg * (cmd->chanlist_len - 1))) /
+			TIMER_BASE;
 		break;
 	case TRIG_FOLLOW:
 		count = cmd->convert_arg / TIMER_BASE;
@@ -2393,6 +2285,7 @@ static uint32_t ai_scan_counter_6xxx(struct comedi_device *dev,
 static uint32_t ai_convert_counter_4020(struct comedi_device *dev,
 					struct comedi_cmd *cmd)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int divisor;
 
 	switch (cmd->scan_begin_src) {
@@ -2400,7 +2293,7 @@ static uint32_t ai_convert_counter_4020(struct comedi_device *dev,
 		divisor = cmd->scan_begin_arg / TIMER_BASE;
 		break;
 	case TRIG_OTHER:
-		divisor = priv(dev)->ext_clock.divisor;
+		divisor = devpriv->ext_clock.divisor;
 		break;
 	default:		/*  should never happen */
 		comedi_error(dev, "bug! failed to set ai pacing!");
@@ -2415,26 +2308,30 @@ static uint32_t ai_convert_counter_4020(struct comedi_device *dev,
 static void select_master_clock_4020(struct comedi_device *dev,
 				     const struct comedi_cmd *cmd)
 {
+	struct pcidas64_private *devpriv = dev->private;
+
 	/*  select internal/external master clock */
-	priv(dev)->hw_config_bits &= ~MASTER_CLOCK_4020_MASK;
+	devpriv->hw_config_bits &= ~MASTER_CLOCK_4020_MASK;
 	if (cmd->scan_begin_src == TRIG_OTHER) {
-		int chanspec = priv(dev)->ext_clock.chanspec;
+		int chanspec = devpriv->ext_clock.chanspec;
 
 		if (CR_CHAN(chanspec))
-			priv(dev)->hw_config_bits |= BNC_CLOCK_4020_BITS;
+			devpriv->hw_config_bits |= BNC_CLOCK_4020_BITS;
 		else
-			priv(dev)->hw_config_bits |= EXT_CLOCK_4020_BITS;
+			devpriv->hw_config_bits |= EXT_CLOCK_4020_BITS;
 	} else {
-		priv(dev)->hw_config_bits |= INTERNAL_CLOCK_4020_BITS;
+		devpriv->hw_config_bits |= INTERNAL_CLOCK_4020_BITS;
 	}
-	writew(priv(dev)->hw_config_bits,
-	       priv(dev)->main_iobase + HW_CONFIG_REG);
+	writew(devpriv->hw_config_bits,
+	       devpriv->main_iobase + HW_CONFIG_REG);
 }
 
 static void select_master_clock(struct comedi_device *dev,
 				const struct comedi_cmd *cmd)
 {
-	switch (board(dev)->layout) {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+
+	switch (thisboard->layout) {
 	case LAYOUT_4020:
 		select_master_clock_4020(dev, cmd);
 		break;
@@ -2446,6 +2343,7 @@ static void select_master_clock(struct comedi_device *dev,
 static inline void dma_start_sync(struct comedi_device *dev,
 				  unsigned int channel)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned long flags;
 
 	/*  spinlock for plx dma control/status reg */
@@ -2453,23 +2351,25 @@ static inline void dma_start_sync(struct comedi_device *dev,
 	if (channel)
 		writeb(PLX_DMA_EN_BIT | PLX_DMA_START_BIT |
 		       PLX_CLEAR_DMA_INTR_BIT,
-		       priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG);
+		       devpriv->plx9080_iobase + PLX_DMA1_CS_REG);
 	else
 		writeb(PLX_DMA_EN_BIT | PLX_DMA_START_BIT |
 		       PLX_CLEAR_DMA_INTR_BIT,
-		       priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+		       devpriv->plx9080_iobase + PLX_DMA0_CS_REG);
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 }
 
 static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
 	uint32_t convert_counter = 0, scan_counter = 0;
 
 	check_adc_timing(dev, cmd);
 
 	select_master_clock(dev, cmd);
 
-	if (board(dev)->layout == LAYOUT_4020) {
+	if (thisboard->layout == LAYOUT_4020) {
 		convert_counter = ai_convert_counter_4020(dev, cmd);
 	} else {
 		convert_counter = ai_convert_counter_6xxx(dev, cmd);
@@ -2478,23 +2378,24 @@ static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd)
 
 	/*  load lower 16 bits of convert interval */
 	writew(convert_counter & 0xffff,
-	       priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG);
+	       devpriv->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG);
 	DEBUG_PRINT("convert counter 0x%x\n", convert_counter);
 	/*  load upper 8 bits of convert interval */
 	writew((convert_counter >> 16) & 0xff,
-	       priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG);
+	       devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG);
 	/*  load lower 16 bits of scan delay */
 	writew(scan_counter & 0xffff,
-	       priv(dev)->main_iobase + ADC_DELAY_INTERVAL_LOWER_REG);
+	       devpriv->main_iobase + ADC_DELAY_INTERVAL_LOWER_REG);
 	/*  load upper 8 bits of scan delay */
 	writew((scan_counter >> 16) & 0xff,
-	       priv(dev)->main_iobase + ADC_DELAY_INTERVAL_UPPER_REG);
+	       devpriv->main_iobase + ADC_DELAY_INTERVAL_UPPER_REG);
 	DEBUG_PRINT("scan counter 0x%x\n", scan_counter);
 }
 
 static int use_internal_queue_6xxx(const struct comedi_cmd *cmd)
 {
 	int i;
+
 	for (i = 0; i + 1 < cmd->chanlist_len; i++) {
 		if (CR_CHAN(cmd->chanlist[i + 1]) !=
 		    CR_CHAN(cmd->chanlist[i]) + 1)
@@ -2511,14 +2412,16 @@ static int use_internal_queue_6xxx(const struct comedi_cmd *cmd)
 static int setup_channel_queue(struct comedi_device *dev,
 			       const struct comedi_cmd *cmd)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned short bits;
 	int i;
 
-	if (board(dev)->layout != LAYOUT_4020) {
+	if (thisboard->layout != LAYOUT_4020) {
 		if (use_internal_queue_6xxx(cmd)) {
-			priv(dev)->hw_config_bits &= ~EXT_QUEUE_BIT;
-			writew(priv(dev)->hw_config_bits,
-			       priv(dev)->main_iobase + HW_CONFIG_REG);
+			devpriv->hw_config_bits &= ~EXT_QUEUE_BIT;
+			writew(devpriv->hw_config_bits,
+			       devpriv->main_iobase + HW_CONFIG_REG);
 			bits = 0;
 			/*  set channel */
 			bits |= adc_chan_bits(CR_CHAN(cmd->chanlist[0]));
@@ -2534,30 +2437,30 @@ static int setup_channel_queue(struct comedi_device *dev,
 			/*  set stop channel */
 			writew(adc_chan_bits
 			       (CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])),
-			       priv(dev)->main_iobase + ADC_QUEUE_HIGH_REG);
+			       devpriv->main_iobase + ADC_QUEUE_HIGH_REG);
 			/*  set start channel, and rest of settings */
 			writew(bits,
-			       priv(dev)->main_iobase + ADC_QUEUE_LOAD_REG);
+			       devpriv->main_iobase + ADC_QUEUE_LOAD_REG);
 		} else {
 			/*  use external queue */
 			if (dev->write_subdev && dev->write_subdev->busy) {
 				warn_external_queue(dev);
 				return -EBUSY;
 			}
-			priv(dev)->hw_config_bits |= EXT_QUEUE_BIT;
-			writew(priv(dev)->hw_config_bits,
-			       priv(dev)->main_iobase + HW_CONFIG_REG);
+			devpriv->hw_config_bits |= EXT_QUEUE_BIT;
+			writew(devpriv->hw_config_bits,
+			       devpriv->main_iobase + HW_CONFIG_REG);
 			/*  clear DAC buffer to prevent weird interactions */
 			writew(0,
-			       priv(dev)->main_iobase + DAC_BUFFER_CLEAR_REG);
+			       devpriv->main_iobase + DAC_BUFFER_CLEAR_REG);
 			/*  clear queue pointer */
-			writew(0, priv(dev)->main_iobase + ADC_QUEUE_CLEAR_REG);
+			writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG);
 			/*  load external queue */
 			for (i = 0; i < cmd->chanlist_len; i++) {
 				bits = 0;
 				/*  set channel */
-				bits |=
-				    adc_chan_bits(CR_CHAN(cmd->chanlist[i]));
+				bits |= adc_chan_bits(CR_CHAN(cmd->
+							      chanlist[i]));
 				/*  set gain */
 				bits |= ai_range_bits_6xxx(dev,
 							   CR_RANGE(cmd->
@@ -2573,42 +2476,42 @@ static int setup_channel_queue(struct comedi_device *dev,
 				/*  mark end of queue */
 				if (i == cmd->chanlist_len - 1)
 					bits |= QUEUE_EOSCAN_BIT |
-					    QUEUE_EOSEQ_BIT;
+						QUEUE_EOSEQ_BIT;
 				writew(bits,
-				       priv(dev)->main_iobase +
+				       devpriv->main_iobase +
 				       ADC_QUEUE_FIFO_REG);
-				DEBUG_PRINT
-				    ("wrote 0x%x to external channel queue\n",
-				     bits);
+				DEBUG_PRINT(
+					    "wrote 0x%x to external channel queue\n",
+					    bits);
 			}
 			/* doing a queue clear is not specified in board docs,
 			 * but required for reliable operation */
-			writew(0, priv(dev)->main_iobase + ADC_QUEUE_CLEAR_REG);
+			writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG);
 			/*  prime queue holding register */
-			writew(0, priv(dev)->main_iobase + ADC_QUEUE_LOAD_REG);
+			writew(0, devpriv->main_iobase + ADC_QUEUE_LOAD_REG);
 		}
 	} else {
-		unsigned short old_cal_range_bits =
-		    priv(dev)->i2c_cal_range_bits;
+		unsigned short old_cal_range_bits = devpriv->i2c_cal_range_bits;
 
-		priv(dev)->i2c_cal_range_bits &= ~ADC_SRC_4020_MASK;
+		devpriv->i2c_cal_range_bits &= ~ADC_SRC_4020_MASK;
 		/* select BNC inputs */
-		priv(dev)->i2c_cal_range_bits |= adc_src_4020_bits(4);
+		devpriv->i2c_cal_range_bits |= adc_src_4020_bits(4);
 		/*  select ranges */
 		for (i = 0; i < cmd->chanlist_len; i++) {
 			unsigned int channel = CR_CHAN(cmd->chanlist[i]);
 			unsigned int range = CR_RANGE(cmd->chanlist[i]);
 
 			if (range == 0)
-				priv(dev)->i2c_cal_range_bits |=
-				    attenuate_bit(channel);
+				devpriv->i2c_cal_range_bits |=
+					attenuate_bit(channel);
 			else
-				priv(dev)->i2c_cal_range_bits &=
-				    ~attenuate_bit(channel);
+				devpriv->i2c_cal_range_bits &=
+					~attenuate_bit(channel);
 		}
-		/*  update calibration/range i2c register only if necessary, as it is very slow */
-		if (old_cal_range_bits != priv(dev)->i2c_cal_range_bits) {
-			uint8_t i2c_data = priv(dev)->i2c_cal_range_bits;
+		/*  update calibration/range i2c register only if necessary,
+		 *  as it is very slow */
+		if (old_cal_range_bits != devpriv->i2c_cal_range_bits) {
+			uint8_t i2c_data = devpriv->i2c_cal_range_bits;
 			i2c_write(dev, RANGE_CAL_I2C_ADDR, &i2c_data,
 				  sizeof(i2c_data));
 		}
@@ -2620,6 +2523,8 @@ static inline void load_first_dma_descriptor(struct comedi_device *dev,
 					     unsigned int dma_channel,
 					     unsigned int descriptor_bits)
 {
+	struct pcidas64_private *devpriv = dev->private;
+
 	/* The transfer size, pci address, and local address registers
 	 * are supposedly unused during chained dma,
 	 * but I have found that left over values from last operation
@@ -2627,25 +2532,27 @@ static inline void load_first_dma_descriptor(struct comedi_device *dev,
 	 * block.  Initializing them to zero seems to fix the problem. */
 	if (dma_channel) {
 		writel(0,
-		       priv(dev)->plx9080_iobase + PLX_DMA1_TRANSFER_SIZE_REG);
-		writel(0, priv(dev)->plx9080_iobase + PLX_DMA1_PCI_ADDRESS_REG);
+		       devpriv->plx9080_iobase + PLX_DMA1_TRANSFER_SIZE_REG);
+		writel(0, devpriv->plx9080_iobase + PLX_DMA1_PCI_ADDRESS_REG);
 		writel(0,
-		       priv(dev)->plx9080_iobase + PLX_DMA1_LOCAL_ADDRESS_REG);
+		       devpriv->plx9080_iobase + PLX_DMA1_LOCAL_ADDRESS_REG);
 		writel(descriptor_bits,
-		       priv(dev)->plx9080_iobase + PLX_DMA1_DESCRIPTOR_REG);
+		       devpriv->plx9080_iobase + PLX_DMA1_DESCRIPTOR_REG);
 	} else {
 		writel(0,
-		       priv(dev)->plx9080_iobase + PLX_DMA0_TRANSFER_SIZE_REG);
-		writel(0, priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG);
+		       devpriv->plx9080_iobase + PLX_DMA0_TRANSFER_SIZE_REG);
+		writel(0, devpriv->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG);
 		writel(0,
-		       priv(dev)->plx9080_iobase + PLX_DMA0_LOCAL_ADDRESS_REG);
+		       devpriv->plx9080_iobase + PLX_DMA0_LOCAL_ADDRESS_REG);
 		writel(descriptor_bits,
-		       priv(dev)->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG);
+		       devpriv->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG);
 	}
 }
 
 static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
 	uint32_t bits;
@@ -2661,7 +2568,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		return retval;
 
 	/*  make sure internal calibration source is turned off */
-	writew(0, priv(dev)->main_iobase + CALIBRATION_REG);
+	writew(0, devpriv->main_iobase + CALIBRATION_REG);
 
 	set_ai_pacing(dev, cmd);
 
@@ -2671,50 +2578,51 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	spin_lock_irqsave(&dev->spinlock, flags);
 	/* set mode, allow conversions through software gate */
-	priv(dev)->adc_control1_bits |= ADC_SW_GATE_BIT;
-	priv(dev)->adc_control1_bits &= ~ADC_DITHER_BIT;
-	if (board(dev)->layout != LAYOUT_4020) {
-		priv(dev)->adc_control1_bits &= ~ADC_MODE_MASK;
+	devpriv->adc_control1_bits |= ADC_SW_GATE_BIT;
+	devpriv->adc_control1_bits &= ~ADC_DITHER_BIT;
+	if (thisboard->layout != LAYOUT_4020) {
+		devpriv->adc_control1_bits &= ~ADC_MODE_MASK;
 		if (cmd->convert_src == TRIG_EXT)
-			priv(dev)->adc_control1_bits |= adc_mode_bits(13);	/*  good old mode 13 */
+			/*  good old mode 13 */
+			devpriv->adc_control1_bits |= adc_mode_bits(13);
 		else
-			priv(dev)->adc_control1_bits |= adc_mode_bits(8);	/*  mode 8.  What else could you need? */
+			/*  mode 8.  What else could you need? */
+			devpriv->adc_control1_bits |= adc_mode_bits(8);
 	} else {
-		priv(dev)->adc_control1_bits &= ~CHANNEL_MODE_4020_MASK;
+		devpriv->adc_control1_bits &= ~CHANNEL_MODE_4020_MASK;
 		if (cmd->chanlist_len == 4)
-			priv(dev)->adc_control1_bits |= FOUR_CHANNEL_4020_BITS;
+			devpriv->adc_control1_bits |= FOUR_CHANNEL_4020_BITS;
 		else if (cmd->chanlist_len == 2)
-			priv(dev)->adc_control1_bits |= TWO_CHANNEL_4020_BITS;
-		priv(dev)->adc_control1_bits &= ~ADC_LO_CHANNEL_4020_MASK;
-		priv(dev)->adc_control1_bits |=
-		    adc_lo_chan_4020_bits(CR_CHAN(cmd->chanlist[0]));
-		priv(dev)->adc_control1_bits &= ~ADC_HI_CHANNEL_4020_MASK;
-		priv(dev)->adc_control1_bits |=
-		    adc_hi_chan_4020_bits(CR_CHAN
-					  (cmd->
-					   chanlist[cmd->chanlist_len - 1]));
+			devpriv->adc_control1_bits |= TWO_CHANNEL_4020_BITS;
+		devpriv->adc_control1_bits &= ~ADC_LO_CHANNEL_4020_MASK;
+		devpriv->adc_control1_bits |=
+			adc_lo_chan_4020_bits(CR_CHAN(cmd->chanlist[0]));
+		devpriv->adc_control1_bits &= ~ADC_HI_CHANNEL_4020_MASK;
+		devpriv->adc_control1_bits |=
+			adc_hi_chan_4020_bits(CR_CHAN(cmd->chanlist
+						      [cmd->chanlist_len - 1]));
 	}
-	writew(priv(dev)->adc_control1_bits,
-	       priv(dev)->main_iobase + ADC_CONTROL1_REG);
-	DEBUG_PRINT("control1 bits 0x%x\n", priv(dev)->adc_control1_bits);
+	writew(devpriv->adc_control1_bits,
+	       devpriv->main_iobase + ADC_CONTROL1_REG);
+	DEBUG_PRINT("control1 bits 0x%x\n", devpriv->adc_control1_bits);
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
 	/*  clear adc buffer */
-	writew(0, priv(dev)->main_iobase + ADC_BUFFER_CLEAR_REG);
+	writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG);
 
 	if ((cmd->flags & TRIG_WAKE_EOS) == 0 ||
-	    board(dev)->layout == LAYOUT_4020) {
-		priv(dev)->ai_dma_index = 0;
+	    thisboard->layout == LAYOUT_4020) {
+		devpriv->ai_dma_index = 0;
 
 		/*  set dma transfer size */
-		for (i = 0; i < ai_dma_ring_count(board(dev)); i++)
-			priv(dev)->ai_dma_desc[i].transfer_size =
-			    cpu_to_le32(dma_transfer_size(dev) *
-					sizeof(uint16_t));
+		for (i = 0; i < ai_dma_ring_count(thisboard); i++)
+			devpriv->ai_dma_desc[i].transfer_size =
+				cpu_to_le32(dma_transfer_size(dev) *
+					    sizeof(uint16_t));
 
 		/*  give location of first dma descriptor */
 		load_first_dma_descriptor(dev, 1,
-					  priv(dev)->ai_dma_desc_bus_addr |
+					  devpriv->ai_dma_desc_bus_addr |
 					  PLX_DESC_IN_PCI_BIT |
 					  PLX_INTR_TERM_COUNT |
 					  PLX_XFER_LOCAL_TO_PCI);
@@ -2722,14 +2630,14 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		dma_start_sync(dev, 1);
 	}
 
-	if (board(dev)->layout == LAYOUT_4020) {
+	if (thisboard->layout == LAYOUT_4020) {
 		/* set source for external triggers */
 		bits = 0;
 		if (cmd->start_src == TRIG_EXT && CR_CHAN(cmd->start_arg))
 			bits |= EXT_START_TRIG_BNC_BIT;
 		if (cmd->stop_src == TRIG_EXT && CR_CHAN(cmd->stop_arg))
 			bits |= EXT_STOP_TRIG_BNC_BIT;
-		writew(bits, priv(dev)->main_iobase + DAQ_ATRIG_LOW_4020_REG);
+		writew(bits, devpriv->main_iobase + DAQ_ATRIG_LOW_4020_REG);
 	}
 
 	spin_lock_irqsave(&dev->spinlock, flags);
@@ -2747,16 +2655,16 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		bits |= ADC_START_TRIG_SOFT_BITS;
 	if (use_hw_sample_counter(cmd))
 		bits |= ADC_SAMPLE_COUNTER_EN_BIT;
-	writew(bits, priv(dev)->main_iobase + ADC_CONTROL0_REG);
+	writew(bits, devpriv->main_iobase + ADC_CONTROL0_REG);
 	DEBUG_PRINT("control0 bits 0x%x\n", bits);
 
-	priv(dev)->ai_cmd_running = 1;
+	devpriv->ai_cmd_running = 1;
 
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
 	/*  start acquisition */
 	if (cmd->start_src == TRIG_NOW) {
-		writew(0, priv(dev)->main_iobase + ADC_START_REG);
+		writew(0, devpriv->main_iobase + ADC_START_REG);
 		DEBUG_PRINT("soft trig\n");
 	}
 
@@ -2766,6 +2674,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 /* read num_samples from 16 bit wide ai fifo */
 static void pio_drain_ai_fifo_16(struct comedi_device *dev)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
@@ -2776,18 +2685,19 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev)
 
 	do {
 		/*  get least significant 15 bits */
-		read_index =
-		    readw(priv(dev)->main_iobase + ADC_READ_PNTR_REG) & 0x7fff;
-		write_index =
-		    readw(priv(dev)->main_iobase + ADC_WRITE_PNTR_REG) & 0x7fff;
-		/* Get most significant bits (grey code).  Different boards use different code
-		 * so use a scheme that doesn't depend on encoding.  This read must
+		read_index = readw(devpriv->main_iobase + ADC_READ_PNTR_REG) &
+			     0x7fff;
+		write_index = readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG) &
+			      0x7fff;
+		/* Get most significant bits (grey code).
+		 * Different boards use different code so use a scheme
+		 * that doesn't depend on encoding.  This read must
 		 * occur after reading least significant 15 bits to avoid race
 		 * with fifo switching to next segment. */
-		prepost_bits = readw(priv(dev)->main_iobase + PREPOST_REG);
+		prepost_bits = readw(devpriv->main_iobase + PREPOST_REG);
 
-		/* if read and write pointers are not on the same fifo segment, read to the
-		 * end of the read segment */
+		/* if read and write pointers are not on the same fifo segment,
+		 * read to the end of the read segment */
 		read_segment = adc_upper_read_ptr_code(prepost_bits);
 		write_segment = adc_upper_write_ptr_code(prepost_bits);
 
@@ -2797,17 +2707,17 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev)
 
 		if (read_segment != write_segment)
 			num_samples =
-			    priv(dev)->ai_fifo_segment_length - read_index;
+				devpriv->ai_fifo_segment_length - read_index;
 		else
 			num_samples = write_index - read_index;
 
 		if (cmd->stop_src == TRIG_COUNT) {
-			if (priv(dev)->ai_count == 0)
+			if (devpriv->ai_count == 0)
 				break;
-			if (num_samples > priv(dev)->ai_count)
-				num_samples = priv(dev)->ai_count;
+			if (num_samples > devpriv->ai_count)
+				num_samples = devpriv->ai_count;
 
-			priv(dev)->ai_count -= num_samples;
+			devpriv->ai_count -= num_samples;
 		}
 
 		if (num_samples < 0) {
@@ -2820,20 +2730,21 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev)
 
 		for (i = 0; i < num_samples; i++) {
 			cfc_write_to_buffer(s,
-					    readw(priv(dev)->main_iobase +
+					    readw(devpriv->main_iobase +
 						  ADC_FIFO_REG));
 		}
 
 	} while (read_segment != write_segment);
 }
 
-/* Read from 32 bit wide ai fifo of 4020 - deal with insane grey coding of pointers.
- * The pci-4020 hardware only supports
- * dma transfers (it only supports the use of pio for draining the last remaining
- * points from the fifo when a data acquisition operation has completed).
+/* Read from 32 bit wide ai fifo of 4020 - deal with insane grey coding of
+ * pointers.  The pci-4020 hardware only supports dma transfers (it only
+ * supports the use of pio for draining the last remaining points from the
+ * fifo when a data acquisition operation has completed).
  */
 static void pio_drain_ai_fifo_32(struct comedi_device *dev)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
@@ -2841,33 +2752,35 @@ static void pio_drain_ai_fifo_32(struct comedi_device *dev)
 	unsigned int max_transfer = 100000;
 	uint32_t fifo_data;
 	int write_code =
-	    readw(priv(dev)->main_iobase + ADC_WRITE_PNTR_REG) & 0x7fff;
+		readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG) & 0x7fff;
 	int read_code =
-	    readw(priv(dev)->main_iobase + ADC_READ_PNTR_REG) & 0x7fff;
+		readw(devpriv->main_iobase + ADC_READ_PNTR_REG) & 0x7fff;
 
 	if (cmd->stop_src == TRIG_COUNT) {
-		if (max_transfer > priv(dev)->ai_count)
-			max_transfer = priv(dev)->ai_count;
+		if (max_transfer > devpriv->ai_count)
+			max_transfer = devpriv->ai_count;
 
 	}
 	for (i = 0; read_code != write_code && i < max_transfer;) {
-		fifo_data = readl(priv(dev)->dio_counter_iobase + ADC_FIFO_REG);
+		fifo_data = readl(devpriv->dio_counter_iobase + ADC_FIFO_REG);
 		cfc_write_to_buffer(s, fifo_data & 0xffff);
 		i++;
 		if (i < max_transfer) {
 			cfc_write_to_buffer(s, (fifo_data >> 16) & 0xffff);
 			i++;
 		}
-		read_code =
-		    readw(priv(dev)->main_iobase + ADC_READ_PNTR_REG) & 0x7fff;
+		read_code = readw(devpriv->main_iobase + ADC_READ_PNTR_REG) &
+			    0x7fff;
 	}
-	priv(dev)->ai_count -= i;
+	devpriv->ai_count -= i;
 }
 
 /* empty fifo */
 static void pio_drain_ai_fifo(struct comedi_device *dev)
 {
-	if (board(dev)->layout == LAYOUT_4020)
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+
+	if (thisboard->layout == LAYOUT_4020)
 		pio_drain_ai_fifo_32(dev);
 	else
 		pio_drain_ai_fifo_16(dev);
@@ -2875,6 +2788,8 @@ static void pio_drain_ai_fifo(struct comedi_device *dev)
 
 static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
 	struct comedi_async *async = dev->read_subdev->async;
 	uint32_t next_transfer_addr;
 	int j;
@@ -2883,46 +2798,47 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
 
 	if (channel)
 		pci_addr_reg =
-		    priv(dev)->plx9080_iobase + PLX_DMA1_PCI_ADDRESS_REG;
+		    devpriv->plx9080_iobase + PLX_DMA1_PCI_ADDRESS_REG;
 	else
 		pci_addr_reg =
-		    priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG;
+		    devpriv->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG;
 
 	/*  loop until we have read all the full buffers */
 	for (j = 0, next_transfer_addr = readl(pci_addr_reg);
 	     (next_transfer_addr <
-	      priv(dev)->ai_buffer_bus_addr[priv(dev)->ai_dma_index]
-	      || next_transfer_addr >=
-	      priv(dev)->ai_buffer_bus_addr[priv(dev)->ai_dma_index] +
-	      DMA_BUFFER_SIZE) && j < ai_dma_ring_count(board(dev)); j++) {
+	      devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] ||
+	      next_transfer_addr >=
+	      devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] +
+	      DMA_BUFFER_SIZE) && j < ai_dma_ring_count(thisboard); j++) {
 		/*  transfer data from dma buffer to comedi buffer */
 		num_samples = dma_transfer_size(dev);
 		if (async->cmd.stop_src == TRIG_COUNT) {
-			if (num_samples > priv(dev)->ai_count)
-				num_samples = priv(dev)->ai_count;
-			priv(dev)->ai_count -= num_samples;
+			if (num_samples > devpriv->ai_count)
+				num_samples = devpriv->ai_count;
+			devpriv->ai_count -= num_samples;
 		}
 		cfc_write_array_to_buffer(dev->read_subdev,
-					  priv(dev)->ai_buffer[priv(dev)->
-							       ai_dma_index],
+					  devpriv->ai_buffer[devpriv->
+							     ai_dma_index],
 					  num_samples * sizeof(uint16_t));
-		priv(dev)->ai_dma_index =
-		    (priv(dev)->ai_dma_index +
-		     1) % ai_dma_ring_count(board(dev));
+		devpriv->ai_dma_index = (devpriv->ai_dma_index + 1) %
+					ai_dma_ring_count(thisboard);
 
 		DEBUG_PRINT("next buffer addr 0x%lx\n",
-			    (unsigned long)priv(dev)->
-			    ai_buffer_bus_addr[priv(dev)->ai_dma_index]);
+			    (unsigned long)devpriv->
+			    ai_buffer_bus_addr[devpriv->ai_dma_index]);
 		DEBUG_PRINT("pci addr reg 0x%x\n", next_transfer_addr);
 	}
-	/* XXX check for dma ring buffer overrun (use end-of-chain bit to mark last
-	 * unused buffer) */
+	/* XXX check for dma ring buffer overrun
+	 * (use end-of-chain bit to mark last unused buffer) */
 }
 
 static void handle_ai_interrupt(struct comedi_device *dev,
 				unsigned short status,
 				unsigned int plx_status)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
@@ -2936,10 +2852,10 @@ static void handle_ai_interrupt(struct comedi_device *dev,
 	}
 	/*  spin lock makes sure no one else changes plx dma control reg */
 	spin_lock_irqsave(&dev->spinlock, flags);
-	dma1_status = readb(priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG);
+	dma1_status = readb(devpriv->plx9080_iobase + PLX_DMA1_CS_REG);
 	if (plx_status & ICS_DMA1_A) {	/*  dma chan 1 interrupt */
 		writeb((dma1_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT,
-		       priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG);
+		       devpriv->plx9080_iobase + PLX_DMA1_CS_REG);
 		DEBUG_PRINT("dma1 status 0x%x\n", dma1_status);
 
 		if (dma1_status & PLX_DMA_EN_BIT)
@@ -2956,17 +2872,17 @@ static void handle_ai_interrupt(struct comedi_device *dev,
 	if ((status & ADC_DONE_BIT) ||
 	    ((cmd->flags & TRIG_WAKE_EOS) &&
 	     (status & ADC_INTR_PENDING_BIT) &&
-	     (board(dev)->layout != LAYOUT_4020))) {
+	     (thisboard->layout != LAYOUT_4020))) {
 		DEBUG_PRINT("pio fifo drain\n");
 		spin_lock_irqsave(&dev->spinlock, flags);
-		if (priv(dev)->ai_cmd_running) {
+		if (devpriv->ai_cmd_running) {
 			spin_unlock_irqrestore(&dev->spinlock, flags);
 			pio_drain_ai_fifo(dev);
 		} else
 			spin_unlock_irqrestore(&dev->spinlock, flags);
 	}
 	/*  if we are have all the data, then quit */
-	if ((cmd->stop_src == TRIG_COUNT && (int)priv(dev)->ai_count <= 0) ||
+	if ((cmd->stop_src == TRIG_COUNT && (int)devpriv->ai_count <= 0) ||
 	    (cmd->stop_src == TRIG_EXT && (status & ADC_STOP_BIT))) {
 		async->events |= COMEDI_CB_EOA;
 	}
@@ -2976,29 +2892,31 @@ static void handle_ai_interrupt(struct comedi_device *dev,
 
 static inline unsigned int prev_ao_dma_index(struct comedi_device *dev)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int buffer_index;
 
-	if (priv(dev)->ao_dma_index == 0)
+	if (devpriv->ao_dma_index == 0)
 		buffer_index = AO_DMA_RING_COUNT - 1;
 	else
-		buffer_index = priv(dev)->ao_dma_index - 1;
+		buffer_index = devpriv->ao_dma_index - 1;
 	return buffer_index;
 }
 
 static int last_ao_dma_load_completed(struct comedi_device *dev)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int buffer_index;
 	unsigned int transfer_address;
 	unsigned short dma_status;
 
 	buffer_index = prev_ao_dma_index(dev);
-	dma_status = readb(priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+	dma_status = readb(devpriv->plx9080_iobase + PLX_DMA0_CS_REG);
 	if ((dma_status & PLX_DMA_DONE_BIT) == 0)
 		return 0;
 
 	transfer_address =
-	    readl(priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG);
-	if (transfer_address != priv(dev)->ao_buffer_bus_addr[buffer_index])
+		readl(devpriv->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG);
+	if (transfer_address != devpriv->ao_buffer_bus_addr[buffer_index])
 		return 0;
 
 	return 1;
@@ -3007,10 +2925,12 @@ static int last_ao_dma_load_completed(struct comedi_device *dev)
 static int ao_stopped_by_error(struct comedi_device *dev,
 			       const struct comedi_cmd *cmd)
 {
+	struct pcidas64_private *devpriv = dev->private;
+
 	if (cmd->stop_src == TRIG_NONE)
 		return 1;
 	if (cmd->stop_src == TRIG_COUNT) {
-		if (priv(dev)->ao_count)
+		if (devpriv->ao_count)
 			return 1;
 		if (last_ao_dma_load_completed(dev) == 0)
 			return 1;
@@ -3032,10 +2952,11 @@ static inline int ao_dma_needs_restart(struct comedi_device *dev,
 
 static void restart_ao_dma(struct comedi_device *dev)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int dma_desc_bits;
 
 	dma_desc_bits =
-	    readl(priv(dev)->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG);
+		readl(devpriv->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG);
 	dma_desc_bits &= ~PLX_END_OF_CHAIN_BIT;
 	DEBUG_PRINT("restarting ao dma, descriptor reg 0x%x\n", dma_desc_bits);
 	load_first_dma_descriptor(dev, 0, dma_desc_bits);
@@ -3043,9 +2964,81 @@ static void restart_ao_dma(struct comedi_device *dev)
 	dma_start_sync(dev, 0);
 }
 
+static unsigned int load_ao_dma_buffer(struct comedi_device *dev,
+				       const struct comedi_cmd *cmd)
+{
+	struct pcidas64_private *devpriv = dev->private;
+	unsigned int num_bytes, buffer_index, prev_buffer_index;
+	unsigned int next_bits;
+
+	buffer_index = devpriv->ao_dma_index;
+	prev_buffer_index = prev_ao_dma_index(dev);
+
+	DEBUG_PRINT("attempting to load ao buffer %i (0x%llx)\n", buffer_index,
+		    (unsigned long long)devpriv->ao_buffer_bus_addr[
+								buffer_index]);
+
+	num_bytes = comedi_buf_read_n_available(dev->write_subdev->async);
+	if (num_bytes > DMA_BUFFER_SIZE)
+		num_bytes = DMA_BUFFER_SIZE;
+	if (cmd->stop_src == TRIG_COUNT && num_bytes > devpriv->ao_count)
+		num_bytes = devpriv->ao_count;
+	num_bytes -= num_bytes % bytes_in_sample;
+
+	if (num_bytes == 0)
+		return 0;
+
+	DEBUG_PRINT("loading %i bytes\n", num_bytes);
+
+	num_bytes = cfc_read_array_from_buffer(dev->write_subdev,
+					       devpriv->
+					       ao_buffer[buffer_index],
+					       num_bytes);
+	devpriv->ao_dma_desc[buffer_index].transfer_size =
+		cpu_to_le32(num_bytes);
+	/* set end of chain bit so we catch underruns */
+	next_bits = le32_to_cpu(devpriv->ao_dma_desc[buffer_index].next);
+	next_bits |= PLX_END_OF_CHAIN_BIT;
+	devpriv->ao_dma_desc[buffer_index].next = cpu_to_le32(next_bits);
+	/* clear end of chain bit on previous buffer now that we have set it
+	 * for the last buffer */
+	next_bits = le32_to_cpu(devpriv->ao_dma_desc[prev_buffer_index].next);
+	next_bits &= ~PLX_END_OF_CHAIN_BIT;
+	devpriv->ao_dma_desc[prev_buffer_index].next = cpu_to_le32(next_bits);
+
+	devpriv->ao_dma_index = (buffer_index + 1) % AO_DMA_RING_COUNT;
+	devpriv->ao_count -= num_bytes;
+
+	return num_bytes;
+}
+
+static void load_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
+{
+	struct pcidas64_private *devpriv = dev->private;
+	unsigned int num_bytes;
+	unsigned int next_transfer_addr;
+	void __iomem *pci_addr_reg =
+		devpriv->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG;
+	unsigned int buffer_index;
+
+	do {
+		buffer_index = devpriv->ao_dma_index;
+		/* don't overwrite data that hasn't been transferred yet */
+		next_transfer_addr = readl(pci_addr_reg);
+		if (next_transfer_addr >=
+		    devpriv->ao_buffer_bus_addr[buffer_index] &&
+		    next_transfer_addr <
+		    devpriv->ao_buffer_bus_addr[buffer_index] +
+		    DMA_BUFFER_SIZE)
+			return;
+		num_bytes = load_ao_dma_buffer(dev, cmd);
+	} while (num_bytes >= DMA_BUFFER_SIZE);
+}
+
 static void handle_ao_interrupt(struct comedi_device *dev,
 				unsigned short status, unsigned int plx_status)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->write_subdev;
 	struct comedi_async *async;
 	struct comedi_cmd *cmd;
@@ -3060,15 +3053,15 @@ static void handle_ao_interrupt(struct comedi_device *dev,
 
 	/*  spin lock makes sure no one else changes plx dma control reg */
 	spin_lock_irqsave(&dev->spinlock, flags);
-	dma0_status = readb(priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+	dma0_status = readb(devpriv->plx9080_iobase + PLX_DMA0_CS_REG);
 	if (plx_status & ICS_DMA0_A) {	/*  dma chan 0 interrupt */
-		if ((dma0_status & PLX_DMA_EN_BIT)
-		    && !(dma0_status & PLX_DMA_DONE_BIT))
+		if ((dma0_status & PLX_DMA_EN_BIT) &&
+		    !(dma0_status & PLX_DMA_DONE_BIT))
 			writeb(PLX_DMA_EN_BIT | PLX_CLEAR_DMA_INTR_BIT,
-			       priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+			       devpriv->plx9080_iobase + PLX_DMA0_CS_REG);
 		else
 			writeb(PLX_CLEAR_DMA_INTR_BIT,
-			       priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+			       devpriv->plx9080_iobase + PLX_DMA0_CS_REG);
 		spin_unlock_irqrestore(&dev->spinlock, flags);
 		DEBUG_PRINT("dma0 status 0x%x\n", dma0_status);
 		if (dma0_status & PLX_DMA_EN_BIT) {
@@ -3078,18 +3071,19 @@ static void handle_ao_interrupt(struct comedi_device *dev,
 				restart_ao_dma(dev);
 		}
 		DEBUG_PRINT(" cleared dma ch0 interrupt\n");
-	} else
+	} else {
 		spin_unlock_irqrestore(&dev->spinlock, flags);
+	}
 
 	if ((status & DAC_DONE_BIT)) {
 		async->events |= COMEDI_CB_EOA;
 		if (ao_stopped_by_error(dev, cmd))
 			async->events |= COMEDI_CB_ERROR;
 		DEBUG_PRINT("plx dma0 desc reg 0x%x\n",
-			    readl(priv(dev)->plx9080_iobase +
+			    readl(devpriv->plx9080_iobase +
 				  PLX_DMA0_DESCRIPTOR_REG));
 		DEBUG_PRINT("plx dma0 address reg 0x%x\n",
-			    readl(priv(dev)->plx9080_iobase +
+			    readl(devpriv->plx9080_iobase +
 				  PLX_DMA0_PCI_ADDRESS_REG));
 	}
 	cfc_handle_events(dev, s);
@@ -3098,22 +3092,21 @@ static void handle_ao_interrupt(struct comedi_device *dev,
 static irqreturn_t handle_interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned short status;
 	uint32_t plx_status;
 	uint32_t plx_bits;
 
-	plx_status = readl(priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
-	status = readw(priv(dev)->main_iobase + HW_STATUS_REG);
+	plx_status = readl(devpriv->plx9080_iobase + PLX_INTRCS_REG);
+	status = readw(devpriv->main_iobase + HW_STATUS_REG);
 
-	DEBUG_PRINT("cb_pcidas64: hw status 0x%x ", status);
-	DEBUG_PRINT("plx status 0x%x\n", plx_status);
+	DEBUG_PRINT("hw status 0x%x, plx status 0x%x\n", status, plx_status);
 
 	/* an interrupt before all the postconfig stuff gets done could
 	 * cause a NULL dereference if we continue through the
 	 * interrupt handler */
 	if (dev->attached == 0) {
-		DEBUG_PRINT("cb_pcidas64: premature interrupt, ignoring",
-			    status);
+		DEBUG_PRINT("premature interrupt, ignoring\n");
 		return IRQ_HANDLED;
 	}
 	handle_ai_interrupt(dev, status, plx_status);
@@ -3121,8 +3114,8 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 
 	/*  clear possible plx9080 interrupt sources */
 	if (plx_status & ICS_LDIA) {	/*  clear local doorbell interrupt */
-		plx_bits = readl(priv(dev)->plx9080_iobase + PLX_DBR_OUT_REG);
-		writel(plx_bits, priv(dev)->plx9080_iobase + PLX_DBR_OUT_REG);
+		plx_bits = readl(devpriv->plx9080_iobase + PLX_DBR_OUT_REG);
+		writel(plx_bits, devpriv->plx9080_iobase + PLX_DBR_OUT_REG);
 		DEBUG_PRINT(" cleared local doorbell bits 0x%x\n", plx_bits);
 	}
 
@@ -3131,28 +3124,17 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 	return IRQ_HANDLED;
 }
 
-static void abort_dma(struct comedi_device *dev, unsigned int channel)
-{
-	unsigned long flags;
-
-	/*  spinlock for plx dma control/status reg */
-	spin_lock_irqsave(&dev->spinlock, flags);
-
-	plx9080_abort_dma(priv(dev)->plx9080_iobase, channel);
-
-	spin_unlock_irqrestore(&dev->spinlock, flags);
-}
-
 static int ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev->spinlock, flags);
-	if (priv(dev)->ai_cmd_running == 0) {
+	if (devpriv->ai_cmd_running == 0) {
 		spin_unlock_irqrestore(&dev->spinlock, flags);
 		return 0;
 	}
-	priv(dev)->ai_cmd_running = 0;
+	devpriv->ai_cmd_running = 0;
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
 	disable_ai_pacing(dev);
@@ -3166,29 +3148,31 @@ static int ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 		    struct comedi_insn *insn, unsigned int *data)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
 	int chan = CR_CHAN(insn->chanspec);
 	int range = CR_RANGE(insn->chanspec);
 
 	/*  do some initializing */
-	writew(0, priv(dev)->main_iobase + DAC_CONTROL0_REG);
+	writew(0, devpriv->main_iobase + DAC_CONTROL0_REG);
 
 	/*  set range */
-	set_dac_range_bits(dev, &priv(dev)->dac_control1_bits, chan, range);
-	writew(priv(dev)->dac_control1_bits,
-	       priv(dev)->main_iobase + DAC_CONTROL1_REG);
+	set_dac_range_bits(dev, &devpriv->dac_control1_bits, chan, range);
+	writew(devpriv->dac_control1_bits,
+	       devpriv->main_iobase + DAC_CONTROL1_REG);
 
 	/*  write to channel */
-	if (board(dev)->layout == LAYOUT_4020) {
+	if (thisboard->layout == LAYOUT_4020) {
 		writew(data[0] & 0xff,
-		       priv(dev)->main_iobase + dac_lsb_4020_reg(chan));
+		       devpriv->main_iobase + dac_lsb_4020_reg(chan));
 		writew((data[0] >> 8) & 0xf,
-		       priv(dev)->main_iobase + dac_msb_4020_reg(chan));
+		       devpriv->main_iobase + dac_msb_4020_reg(chan));
 	} else {
-		writew(data[0], priv(dev)->main_iobase + dac_convert_reg(chan));
+		writew(data[0], devpriv->main_iobase + dac_convert_reg(chan));
 	}
 
 	/*  remember output value */
-	priv(dev)->ao_value[chan] = data[0];
+	devpriv->ao_value[chan] = data[0];
 
 	return 1;
 }
@@ -3197,7 +3181,9 @@ static int ao_readback_insn(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data)
 {
-	data[0] = priv(dev)->ao_value[CR_CHAN(insn->chanspec)];
+	struct pcidas64_private *devpriv = dev->private;
+
+	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
 
 	return 1;
 }
@@ -3205,8 +3191,9 @@ static int ao_readback_insn(struct comedi_device *dev,
 static void set_dac_control0_reg(struct comedi_device *dev,
 				 const struct comedi_cmd *cmd)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int bits = DAC_ENABLE_BIT | WAVEFORM_GATE_LEVEL_BIT |
-	    WAVEFORM_GATE_ENABLE_BIT | WAVEFORM_GATE_SELECT_BIT;
+			    WAVEFORM_GATE_ENABLE_BIT | WAVEFORM_GATE_SELECT_BIT;
 
 	if (cmd->start_src == TRIG_EXT) {
 		bits |= WAVEFORM_TRIG_EXT_BITS;
@@ -3220,12 +3207,13 @@ static void set_dac_control0_reg(struct comedi_device *dev,
 		if (cmd->scan_begin_arg & CR_INVERT)
 			bits |= DAC_EXT_UPDATE_FALLING_BIT;
 	}
-	writew(bits, priv(dev)->main_iobase + DAC_CONTROL0_REG);
+	writew(bits, devpriv->main_iobase + DAC_CONTROL0_REG);
 }
 
 static void set_dac_control1_reg(struct comedi_device *dev,
 				 const struct comedi_cmd *cmd)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	int i;
 
 	for (i = 0; i < cmd->chanlist_len; i++) {
@@ -3233,17 +3221,18 @@ static void set_dac_control1_reg(struct comedi_device *dev,
 
 		channel = CR_CHAN(cmd->chanlist[i]);
 		range = CR_RANGE(cmd->chanlist[i]);
-		set_dac_range_bits(dev, &priv(dev)->dac_control1_bits, channel,
+		set_dac_range_bits(dev, &devpriv->dac_control1_bits, channel,
 				   range);
 	}
-	priv(dev)->dac_control1_bits |= DAC_SW_GATE_BIT;
-	writew(priv(dev)->dac_control1_bits,
-	       priv(dev)->main_iobase + DAC_CONTROL1_REG);
+	devpriv->dac_control1_bits |= DAC_SW_GATE_BIT;
+	writew(devpriv->dac_control1_bits,
+	       devpriv->main_iobase + DAC_CONTROL1_REG);
 }
 
 static void set_dac_select_reg(struct comedi_device *dev,
 			       const struct comedi_cmd *cmd)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	uint16_t bits;
 	unsigned int first_channel, last_channel;
 
@@ -3254,12 +3243,18 @@ static void set_dac_select_reg(struct comedi_device *dev,
 
 	bits = (first_channel & 0x7) | (last_channel & 0x7) << 3;
 
-	writew(bits, priv(dev)->main_iobase + DAC_SELECT_REG);
+	writew(bits, devpriv->main_iobase + DAC_SELECT_REG);
+}
+
+static unsigned int get_ao_divisor(unsigned int ns, unsigned int flags)
+{
+	return get_divisor(ns, flags) - 2;
 }
 
 static void set_dac_interval_regs(struct comedi_device *dev,
 				  const struct comedi_cmd *cmd)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int divisor;
 
 	if (cmd->scan_begin_src != TRIG_TIMER)
@@ -3271,102 +3266,35 @@ static void set_dac_interval_regs(struct comedi_device *dev,
 		divisor = max_counter_value;
 	}
 	writew(divisor & 0xffff,
-	       priv(dev)->main_iobase + DAC_SAMPLE_INTERVAL_LOWER_REG);
+	       devpriv->main_iobase + DAC_SAMPLE_INTERVAL_LOWER_REG);
 	writew((divisor >> 16) & 0xff,
-	       priv(dev)->main_iobase + DAC_SAMPLE_INTERVAL_UPPER_REG);
-}
-
-static unsigned int load_ao_dma_buffer(struct comedi_device *dev,
-				       const struct comedi_cmd *cmd)
-{
-	unsigned int num_bytes, buffer_index, prev_buffer_index;
-	unsigned int next_bits;
-
-	buffer_index = priv(dev)->ao_dma_index;
-	prev_buffer_index = prev_ao_dma_index(dev);
-
-	DEBUG_PRINT("attempting to load ao buffer %i (0x%x)\n", buffer_index,
-		    priv(dev)->ao_buffer_bus_addr[buffer_index]);
-
-	num_bytes = comedi_buf_read_n_available(dev->write_subdev->async);
-	if (num_bytes > DMA_BUFFER_SIZE)
-		num_bytes = DMA_BUFFER_SIZE;
-	if (cmd->stop_src == TRIG_COUNT && num_bytes > priv(dev)->ao_count)
-		num_bytes = priv(dev)->ao_count;
-	num_bytes -= num_bytes % bytes_in_sample;
-
-	if (num_bytes == 0)
-		return 0;
-
-	DEBUG_PRINT("loading %i bytes\n", num_bytes);
-
-	num_bytes = cfc_read_array_from_buffer(dev->write_subdev,
-					       priv(dev)->
-					       ao_buffer[buffer_index],
-					       num_bytes);
-	priv(dev)->ao_dma_desc[buffer_index].transfer_size =
-	    cpu_to_le32(num_bytes);
-	/* set end of chain bit so we catch underruns */
-	next_bits = le32_to_cpu(priv(dev)->ao_dma_desc[buffer_index].next);
-	next_bits |= PLX_END_OF_CHAIN_BIT;
-	priv(dev)->ao_dma_desc[buffer_index].next = cpu_to_le32(next_bits);
-	/* clear end of chain bit on previous buffer now that we have set it
-	 * for the last buffer */
-	next_bits = le32_to_cpu(priv(dev)->ao_dma_desc[prev_buffer_index].next);
-	next_bits &= ~PLX_END_OF_CHAIN_BIT;
-	priv(dev)->ao_dma_desc[prev_buffer_index].next = cpu_to_le32(next_bits);
-
-	priv(dev)->ao_dma_index = (buffer_index + 1) % AO_DMA_RING_COUNT;
-	priv(dev)->ao_count -= num_bytes;
-
-	return num_bytes;
-}
-
-static void load_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
-{
-	unsigned int num_bytes;
-	unsigned int next_transfer_addr;
-	void __iomem *pci_addr_reg =
-	    priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG;
-	unsigned int buffer_index;
-
-	do {
-		buffer_index = priv(dev)->ao_dma_index;
-		/* don't overwrite data that hasn't been transferred yet */
-		next_transfer_addr = readl(pci_addr_reg);
-		if (next_transfer_addr >=
-		    priv(dev)->ao_buffer_bus_addr[buffer_index]
-		    && next_transfer_addr <
-		    priv(dev)->ao_buffer_bus_addr[buffer_index] +
-		    DMA_BUFFER_SIZE)
-			return;
-		num_bytes = load_ao_dma_buffer(dev, cmd);
-	} while (num_bytes >= DMA_BUFFER_SIZE);
+	       devpriv->main_iobase + DAC_SAMPLE_INTERVAL_UPPER_REG);
 }
 
 static int prep_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int num_bytes;
 	int i;
 
 	/* clear queue pointer too, since external queue has
 	 * weird interactions with ao fifo */
-	writew(0, priv(dev)->main_iobase + ADC_QUEUE_CLEAR_REG);
-	writew(0, priv(dev)->main_iobase + DAC_BUFFER_CLEAR_REG);
+	writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG);
+	writew(0, devpriv->main_iobase + DAC_BUFFER_CLEAR_REG);
 
 	num_bytes = (DAC_FIFO_SIZE / 2) * bytes_in_sample;
 	if (cmd->stop_src == TRIG_COUNT &&
-	    num_bytes / bytes_in_sample > priv(dev)->ao_count)
-		num_bytes = priv(dev)->ao_count * bytes_in_sample;
+	    num_bytes / bytes_in_sample > devpriv->ao_count)
+		num_bytes = devpriv->ao_count * bytes_in_sample;
 	num_bytes = cfc_read_array_from_buffer(dev->write_subdev,
-					       priv(dev)->ao_bounce_buffer,
+					       devpriv->ao_bounce_buffer,
 					       num_bytes);
 	for (i = 0; i < num_bytes / bytes_in_sample; i++) {
-		writew(priv(dev)->ao_bounce_buffer[i],
-		       priv(dev)->main_iobase + DAC_FIFO_REG);
+		writew(devpriv->ao_bounce_buffer[i],
+		       devpriv->main_iobase + DAC_FIFO_REG);
 	}
-	priv(dev)->ao_count -= num_bytes / bytes_in_sample;
-	if (cmd->stop_src == TRIG_COUNT && priv(dev)->ao_count == 0)
+	devpriv->ao_count -= num_bytes / bytes_in_sample;
+	if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count == 0)
 		return 0;
 	num_bytes = load_ao_dma_buffer(dev, cmd);
 	if (num_bytes == 0)
@@ -3381,43 +3309,21 @@ static int prep_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
 
 static inline int external_ai_queue_in_use(struct comedi_device *dev)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+
 	if (dev->read_subdev->busy)
 		return 0;
-	if (board(dev)->layout == LAYOUT_4020)
+	if (thisboard->layout == LAYOUT_4020)
 		return 0;
 	else if (use_internal_queue_6xxx(&dev->read_subdev->async->cmd))
 		return 0;
 	return 1;
 }
 
-static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
-{
-	struct comedi_cmd *cmd = &s->async->cmd;
-
-	if (external_ai_queue_in_use(dev)) {
-		warn_external_queue(dev);
-		return -EBUSY;
-	}
-	/* disable analog output system during setup */
-	writew(0x0, priv(dev)->main_iobase + DAC_CONTROL0_REG);
-
-	priv(dev)->ao_dma_index = 0;
-	priv(dev)->ao_count = cmd->stop_arg * cmd->chanlist_len;
-
-	set_dac_select_reg(dev, cmd);
-	set_dac_interval_regs(dev, cmd);
-	load_first_dma_descriptor(dev, 0, priv(dev)->ao_dma_desc_bus_addr |
-				  PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT);
-
-	set_dac_control1_reg(dev, cmd);
-	s->async->inttrig = ao_inttrig;
-
-	return 0;
-}
-
 static int ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
 		      unsigned int trig_num)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
 	int retval;
 
@@ -3431,16 +3337,43 @@ static int ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
 	set_dac_control0_reg(dev, cmd);
 
 	if (cmd->start_src == TRIG_INT)
-		writew(0, priv(dev)->main_iobase + DAC_START_REG);
+		writew(0, devpriv->main_iobase + DAC_START_REG);
 
 	s->async->inttrig = NULL;
 
 	return 0;
 }
 
+static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+{
+	struct pcidas64_private *devpriv = dev->private;
+	struct comedi_cmd *cmd = &s->async->cmd;
+
+	if (external_ai_queue_in_use(dev)) {
+		warn_external_queue(dev);
+		return -EBUSY;
+	}
+	/* disable analog output system during setup */
+	writew(0x0, devpriv->main_iobase + DAC_CONTROL0_REG);
+
+	devpriv->ao_dma_index = 0;
+	devpriv->ao_count = cmd->stop_arg * cmd->chanlist_len;
+
+	set_dac_select_reg(dev, cmd);
+	set_dac_interval_regs(dev, cmd);
+	load_first_dma_descriptor(dev, 0, devpriv->ao_dma_desc_bus_addr |
+				  PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT);
+
+	set_dac_control1_reg(dev, cmd);
+	s->async->inttrig = ao_inttrig;
+
+	return 0;
+}
+
 static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 		      struct comedi_cmd *cmd)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
 	int err = 0;
 	unsigned int tmp_arg;
 	int i;
@@ -3449,7 +3382,7 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
 	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
 	err |= cfc_check_trigger_src(&cmd->scan_begin_src,
-					TRIG_TIMER | TRIG_EXT);
+				     TRIG_TIMER | TRIG_EXT);
 	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
 	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
@@ -3473,29 +3406,21 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
-		if (cmd->scan_begin_arg < board(dev)->ao_scan_speed) {
-			cmd->scan_begin_arg = board(dev)->ao_scan_speed;
-			err++;
-		}
-		if (get_ao_divisor(cmd->scan_begin_arg,
-				   cmd->flags) > max_counter_value) {
-			cmd->scan_begin_arg =
-			    (max_counter_value + 2) * TIMER_BASE;
-			err++;
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						 thisboard->ao_scan_speed);
+		if (get_ao_divisor(cmd->scan_begin_arg, cmd->flags) >
+		    max_counter_value) {
+			cmd->scan_begin_arg = (max_counter_value + 2) *
+					      TIMER_BASE;
+			err |= -EINVAL;
 		}
 	}
 
-	if (!cmd->chanlist_len) {
-		cmd->chanlist_len = 1;
-		err++;
-	}
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 
 	if (err)
 		return 3;
@@ -3504,8 +3429,8 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		tmp_arg = cmd->scan_begin_arg;
-		cmd->scan_begin_arg =
-		    get_divisor(cmd->scan_begin_arg, cmd->flags) * TIMER_BASE;
+		cmd->scan_begin_arg = get_divisor(cmd->scan_begin_arg,
+						  cmd->flags) * TIMER_BASE;
 		if (tmp_arg != cmd->scan_begin_arg)
 			err++;
 	}
@@ -3533,7 +3458,9 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	writew(0x0, priv(dev)->main_iobase + DAC_CONTROL0_REG);
+	struct pcidas64_private *devpriv = dev->private;
+
+	writew(0x0, devpriv->main_iobase + DAC_CONTROL0_REG);
 	abort_dma(dev, 0);
 	return 0;
 }
@@ -3564,9 +3491,10 @@ static int dio_callback_4020(int dir, int port, int data, unsigned long arg)
 static int di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
 		    struct comedi_insn *insn, unsigned int *data)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int bits;
 
-	bits = readb(priv(dev)->dio_counter_iobase + DI_REG);
+	bits = readb(devpriv->dio_counter_iobase + DI_REG);
 	bits &= 0xf;
 	data[1] = bits;
 	data[0] = 0;
@@ -3577,13 +3505,15 @@ static int di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
 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, priv(dev)->dio_counter_iobase + DO_REG);
+	writeb(s->state, devpriv->dio_counter_iobase + DO_REG);
 
 	data[1] = s->state;
 
@@ -3594,6 +3524,7 @@ static int dio_60xx_config_insn(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int mask;
 
 	mask = 1 << CR_CHAN(insn->chanspec);
@@ -3613,7 +3544,7 @@ static int dio_60xx_config_insn(struct comedi_device *dev,
 	}
 
 	writeb(s->io_bits,
-	       priv(dev)->dio_counter_iobase + DIO_DIRECTION_60XX_REG);
+	       devpriv->dio_counter_iobase + DIO_DIRECTION_60XX_REG);
 
 	return 1;
 }
@@ -3621,28 +3552,147 @@ static int dio_60xx_config_insn(struct comedi_device *dev,
 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]);
 		writeb(s->state,
-		       priv(dev)->dio_counter_iobase + DIO_DATA_60XX_REG);
+		       devpriv->dio_counter_iobase + DIO_DATA_60XX_REG);
 	}
 
-	data[1] = readb(priv(dev)->dio_counter_iobase + DIO_DATA_60XX_REG);
+	data[1] = readb(devpriv->dio_counter_iobase + DIO_DATA_60XX_REG);
 
 	return insn->n;
 }
 
-static void caldac_write(struct comedi_device *dev, unsigned int channel,
-			 unsigned int value)
+/* pci-6025 8800 caldac:
+ * address 0 == dac channel 0 offset
+ * address 1 == dac channel 0 gain
+ * address 2 == dac channel 1 offset
+ * address 3 == dac channel 1 gain
+ * address 4 == fine adc offset
+ * address 5 == coarse adc offset
+ * address 6 == coarse adc gain
+ * address 7 == fine adc gain
+ */
+/* pci-6402/16 uses all 8 channels for dac:
+ * address 0 == dac channel 0 fine gain
+ * address 1 == dac channel 0 coarse gain
+ * address 2 == dac channel 0 coarse offset
+ * address 3 == dac channel 1 coarse offset
+ * address 4 == dac channel 1 fine gain
+ * address 5 == dac channel 1 coarse gain
+ * address 6 == dac channel 0 fine offset
+ * address 7 == dac channel 1 fine offset
+*/
+
+static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
+			     uint8_t value)
 {
-	priv(dev)->caldac_state[channel] = value;
+	struct pcidas64_private *devpriv = dev->private;
+	static const int num_caldac_channels = 8;
+	static const int bitstream_length = 11;
+	unsigned int bitstream = ((address & 0x7) << 8) | value;
+	unsigned int bit, register_bits;
+	static const int caldac_8800_udelay = 1;
 
-	switch (board(dev)->layout) {
-	case LAYOUT_60XX:
-	case LAYOUT_64XX:
-		caldac_8800_write(dev, channel, value);
-		break;
+	if (address >= num_caldac_channels) {
+		comedi_error(dev, "illegal caldac channel");
+		return -1;
+	}
+	for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
+		register_bits = 0;
+		if (bitstream & bit)
+			register_bits |= SERIAL_DATA_IN_BIT;
+		udelay(caldac_8800_udelay);
+		writew(register_bits, devpriv->main_iobase + CALIBRATION_REG);
+		register_bits |= SERIAL_CLOCK_BIT;
+		udelay(caldac_8800_udelay);
+		writew(register_bits, devpriv->main_iobase + CALIBRATION_REG);
+	}
+	udelay(caldac_8800_udelay);
+	writew(SELECT_8800_BIT, devpriv->main_iobase + CALIBRATION_REG);
+	udelay(caldac_8800_udelay);
+	writew(0, devpriv->main_iobase + CALIBRATION_REG);
+	udelay(caldac_8800_udelay);
+	return 0;
+}
+
+/* 4020 caldacs */
+static int caldac_i2c_write(struct comedi_device *dev,
+			    unsigned int caldac_channel, unsigned int value)
+{
+	uint8_t serial_bytes[3];
+	uint8_t i2c_addr;
+	enum pointer_bits {
+		/*  manual has gain and offset bits switched */
+		OFFSET_0_2 = 0x1,
+		GAIN_0_2 = 0x2,
+		OFFSET_1_3 = 0x4,
+		GAIN_1_3 = 0x8,
+	};
+	enum data_bits {
+		NOT_CLEAR_REGISTERS = 0x20,
+	};
+
+	switch (caldac_channel) {
+	case 0:		/*  chan 0 offset */
+		i2c_addr = CALDAC0_I2C_ADDR;
+		serial_bytes[0] = OFFSET_0_2;
+		break;
+	case 1:		/*  chan 1 offset */
+		i2c_addr = CALDAC0_I2C_ADDR;
+		serial_bytes[0] = OFFSET_1_3;
+		break;
+	case 2:		/*  chan 2 offset */
+		i2c_addr = CALDAC1_I2C_ADDR;
+		serial_bytes[0] = OFFSET_0_2;
+		break;
+	case 3:		/*  chan 3 offset */
+		i2c_addr = CALDAC1_I2C_ADDR;
+		serial_bytes[0] = OFFSET_1_3;
+		break;
+	case 4:		/*  chan 0 gain */
+		i2c_addr = CALDAC0_I2C_ADDR;
+		serial_bytes[0] = GAIN_0_2;
+		break;
+	case 5:		/*  chan 1 gain */
+		i2c_addr = CALDAC0_I2C_ADDR;
+		serial_bytes[0] = GAIN_1_3;
+		break;
+	case 6:		/*  chan 2 gain */
+		i2c_addr = CALDAC1_I2C_ADDR;
+		serial_bytes[0] = GAIN_0_2;
+		break;
+	case 7:		/*  chan 3 gain */
+		i2c_addr = CALDAC1_I2C_ADDR;
+		serial_bytes[0] = GAIN_1_3;
+		break;
+	default:
+		comedi_error(dev, "invalid caldac channel\n");
+		return -1;
+		break;
+	}
+	serial_bytes[1] = NOT_CLEAR_REGISTERS | ((value >> 8) & 0xf);
+	serial_bytes[2] = value & 0xff;
+	i2c_write(dev, i2c_addr, serial_bytes, 3);
+	return 0;
+}
+
+static void caldac_write(struct comedi_device *dev, unsigned int channel,
+			 unsigned int value)
+{
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
+
+	devpriv->caldac_state[channel] = value;
+
+	switch (thisboard->layout) {
+	case LAYOUT_60XX:
+	case LAYOUT_64XX:
+		caldac_8800_write(dev, channel, value);
+		break;
 	case LAYOUT_4020:
 		caldac_i2c_write(dev, channel, value);
 		break;
@@ -3655,11 +3705,12 @@ static int calib_write_insn(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	int channel = CR_CHAN(insn->chanspec);
 
 	/* return immediately if setting hasn't changed, since
 	 * programming these things is slow */
-	if (priv(dev)->caldac_state[channel] == data[0])
+	if (devpriv->caldac_state[channel] == data[0])
 		return 1;
 
 	caldac_write(dev, channel, data[0]);
@@ -3671,9 +3722,10 @@ static int calib_read_insn(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
 			   unsigned int *data)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int channel = CR_CHAN(insn->chanspec);
 
-	data[0] = priv(dev)->caldac_state[channel];
+	data[0] = devpriv->caldac_state[channel];
 
 	return 1;
 }
@@ -3681,16 +3733,17 @@ static int calib_read_insn(struct comedi_device *dev,
 static void ad8402_write(struct comedi_device *dev, unsigned int channel,
 			 unsigned int value)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	static const int bitstream_length = 10;
 	unsigned int bit, register_bits;
 	unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff);
 	static const int ad8402_udelay = 1;
 
-	priv(dev)->ad8402_state[channel] = value;
+	devpriv->ad8402_state[channel] = value;
 
 	register_bits = SELECT_8402_64XX_BIT;
 	udelay(ad8402_udelay);
-	writew(register_bits, priv(dev)->main_iobase + CALIBRATION_REG);
+	writew(register_bits, devpriv->main_iobase + CALIBRATION_REG);
 
 	for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
 		if (bitstream & bit)
@@ -3698,14 +3751,14 @@ static void ad8402_write(struct comedi_device *dev, unsigned int channel,
 		else
 			register_bits &= ~SERIAL_DATA_IN_BIT;
 		udelay(ad8402_udelay);
-		writew(register_bits, priv(dev)->main_iobase + CALIBRATION_REG);
+		writew(register_bits, devpriv->main_iobase + CALIBRATION_REG);
 		udelay(ad8402_udelay);
 		writew(register_bits | SERIAL_CLOCK_BIT,
-		       priv(dev)->main_iobase + CALIBRATION_REG);
+		       devpriv->main_iobase + CALIBRATION_REG);
 	}
 
 	udelay(ad8402_udelay);
-	writew(0, priv(dev)->main_iobase + CALIBRATION_REG);
+	writew(0, devpriv->main_iobase + CALIBRATION_REG);
 }
 
 /* for pci-das6402/16, channel 0 is analog input gain and channel 1 is offset */
@@ -3713,14 +3766,15 @@ static int ad8402_write_insn(struct comedi_device *dev,
 			     struct comedi_subdevice *s,
 			     struct comedi_insn *insn, unsigned int *data)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	int channel = CR_CHAN(insn->chanspec);
 
 	/* return immediately if setting hasn't changed, since
 	 * programming these things is slow */
-	if (priv(dev)->ad8402_state[channel] == data[0])
+	if (devpriv->ad8402_state[channel] == data[0])
 		return 1;
 
-	priv(dev)->ad8402_state[channel] = data[0];
+	devpriv->ad8402_state[channel] = data[0];
 
 	ad8402_write(dev, channel, data[0]);
 
@@ -3731,62 +3785,64 @@ static int ad8402_read_insn(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int channel = CR_CHAN(insn->chanspec);
 
-	data[0] = priv(dev)->ad8402_state[channel];
+	data[0] = devpriv->ad8402_state[channel];
 
 	return 1;
 }
 
 static uint16_t read_eeprom(struct comedi_device *dev, uint8_t address)
 {
+	struct pcidas64_private *devpriv = dev->private;
 	static const int bitstream_length = 11;
 	static const int read_command = 0x6;
 	unsigned int bitstream = (read_command << 8) | address;
 	unsigned int bit;
 	void __iomem * const plx_control_addr =
-	    priv(dev)->plx9080_iobase + PLX_CONTROL_REG;
+		devpriv->plx9080_iobase + PLX_CONTROL_REG;
 	uint16_t value;
 	static const int value_length = 16;
 	static const int eeprom_udelay = 1;
 
 	udelay(eeprom_udelay);
-	priv(dev)->plx_control_bits &= ~CTL_EE_CLK & ~CTL_EE_CS;
+	devpriv->plx_control_bits &= ~CTL_EE_CLK & ~CTL_EE_CS;
 	/*  make sure we don't send anything to the i2c bus on 4020 */
-	priv(dev)->plx_control_bits |= CTL_USERO;
-	writel(priv(dev)->plx_control_bits, plx_control_addr);
+	devpriv->plx_control_bits |= CTL_USERO;
+	writel(devpriv->plx_control_bits, plx_control_addr);
 	/*  activate serial eeprom */
 	udelay(eeprom_udelay);
-	priv(dev)->plx_control_bits |= CTL_EE_CS;
-	writel(priv(dev)->plx_control_bits, plx_control_addr);
+	devpriv->plx_control_bits |= CTL_EE_CS;
+	writel(devpriv->plx_control_bits, plx_control_addr);
 
 	/*  write read command and desired memory address */
 	for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
 		/*  set bit to be written */
 		udelay(eeprom_udelay);
 		if (bitstream & bit)
-			priv(dev)->plx_control_bits |= CTL_EE_W;
+			devpriv->plx_control_bits |= CTL_EE_W;
 		else
-			priv(dev)->plx_control_bits &= ~CTL_EE_W;
-		writel(priv(dev)->plx_control_bits, plx_control_addr);
+			devpriv->plx_control_bits &= ~CTL_EE_W;
+		writel(devpriv->plx_control_bits, plx_control_addr);
 		/*  clock in bit */
 		udelay(eeprom_udelay);
-		priv(dev)->plx_control_bits |= CTL_EE_CLK;
-		writel(priv(dev)->plx_control_bits, plx_control_addr);
+		devpriv->plx_control_bits |= CTL_EE_CLK;
+		writel(devpriv->plx_control_bits, plx_control_addr);
 		udelay(eeprom_udelay);
-		priv(dev)->plx_control_bits &= ~CTL_EE_CLK;
-		writel(priv(dev)->plx_control_bits, plx_control_addr);
+		devpriv->plx_control_bits &= ~CTL_EE_CLK;
+		writel(devpriv->plx_control_bits, plx_control_addr);
 	}
 	/*  read back value from eeprom memory location */
 	value = 0;
 	for (bit = 1 << (value_length - 1); bit; bit >>= 1) {
 		/*  clock out bit */
 		udelay(eeprom_udelay);
-		priv(dev)->plx_control_bits |= CTL_EE_CLK;
-		writel(priv(dev)->plx_control_bits, plx_control_addr);
+		devpriv->plx_control_bits |= CTL_EE_CLK;
+		writel(devpriv->plx_control_bits, plx_control_addr);
 		udelay(eeprom_udelay);
-		priv(dev)->plx_control_bits &= ~CTL_EE_CLK;
-		writel(priv(dev)->plx_control_bits, plx_control_addr);
+		devpriv->plx_control_bits &= ~CTL_EE_CLK;
+		writel(devpriv->plx_control_bits, plx_control_addr);
 		udelay(eeprom_udelay);
 		if (readl(plx_control_addr) & CTL_EE_R)
 			value |= bit;
@@ -3794,8 +3850,8 @@ static uint16_t read_eeprom(struct comedi_device *dev, uint8_t address)
 
 	/*  deactivate eeprom serial input */
 	udelay(eeprom_udelay);
-	priv(dev)->plx_control_bits &= ~CTL_EE_CS;
-	writel(priv(dev)->plx_control_bits, plx_control_addr);
+	devpriv->plx_control_bits &= ~CTL_EE_CS;
+	writel(devpriv->plx_control_bits, plx_control_addr);
 
 	return value;
 }
@@ -3809,419 +3865,386 @@ static int eeprom_read_insn(struct comedi_device *dev,
 	return 1;
 }
 
-/* utility function that rounds desired timing to an achievable time, and
- * sets cmd members appropriately.
- * adc paces conversions from master clock by dividing by (x + 3) where x is 24 bit number
+/* Allocate and initialize the subdevice structures.
  */
-static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
+static int setup_subdevices(struct comedi_device *dev)
 {
-	unsigned int convert_divisor = 0, scan_divisor;
-	static const int min_convert_divisor = 3;
-	static const int max_convert_divisor =
-	    max_counter_value + min_convert_divisor;
-	static const int min_scan_divisor_4020 = 2;
-	unsigned long long max_scan_divisor, min_scan_divisor;
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pcidas64_private *devpriv = dev->private;
+	struct comedi_subdevice *s;
+	void __iomem *dio_8255_iobase;
+	int i;
+	int ret;
 
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (board(dev)->layout == LAYOUT_4020) {
-			cmd->convert_arg = 0;
-		} else {
-			convert_divisor =
-			    get_divisor(cmd->convert_arg, cmd->flags);
-			if (convert_divisor > max_convert_divisor)
-				convert_divisor = max_convert_divisor;
-			if (convert_divisor < min_convert_divisor)
-				convert_divisor = min_convert_divisor;
-			cmd->convert_arg = convert_divisor * TIMER_BASE;
-		}
-	} else if (cmd->convert_src == TRIG_NOW)
-		cmd->convert_arg = 0;
+	ret = comedi_alloc_subdevices(dev, 10);
+	if (ret)
+		return ret;
 
-	if (cmd->scan_begin_src == TRIG_TIMER) {
-		scan_divisor = get_divisor(cmd->scan_begin_arg, cmd->flags);
-		if (cmd->convert_src == TRIG_TIMER) {
-			/*  XXX check for integer overflows */
-			min_scan_divisor = convert_divisor * cmd->chanlist_len;
-			max_scan_divisor =
-			    (convert_divisor * cmd->chanlist_len - 1) +
-			    max_counter_value;
-		} else {
-			min_scan_divisor = min_scan_divisor_4020;
-			max_scan_divisor = max_counter_value + min_scan_divisor;
-		}
-		if (scan_divisor > max_scan_divisor)
-			scan_divisor = max_scan_divisor;
-		if (scan_divisor < min_scan_divisor)
-			scan_divisor = min_scan_divisor;
-		cmd->scan_begin_arg = scan_divisor * TIMER_BASE;
+	s = &dev->subdevices[0];
+	/* analog input subdevice */
+	dev->read_subdev = s;
+	s->type = COMEDI_SUBD_AI;
+	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DITHER | SDF_CMD_READ;
+	if (thisboard->layout == LAYOUT_60XX)
+		s->subdev_flags |= SDF_COMMON | SDF_DIFF;
+	else if (thisboard->layout == LAYOUT_64XX)
+		s->subdev_flags |= SDF_DIFF;
+	/* XXX Number of inputs in differential mode is ignored */
+	s->n_chan = thisboard->ai_se_chans;
+	s->len_chanlist = 0x2000;
+	s->maxdata = (1 << thisboard->ai_bits) - 1;
+	s->range_table = thisboard->ai_range_table;
+	s->insn_read = ai_rinsn;
+	s->insn_config = ai_config_insn;
+	s->do_cmd = ai_cmd;
+	s->do_cmdtest = ai_cmdtest;
+	s->cancel = ai_cancel;
+	if (thisboard->layout == LAYOUT_4020) {
+		uint8_t data;
+		/*  set adc to read from inputs
+		 *  (not internal calibration sources) */
+		devpriv->i2c_cal_range_bits = adc_src_4020_bits(4);
+		/*  set channels to +-5 volt input ranges */
+		for (i = 0; i < s->n_chan; i++)
+			devpriv->i2c_cal_range_bits |= attenuate_bit(i);
+		data = devpriv->i2c_cal_range_bits;
+		i2c_write(dev, RANGE_CAL_I2C_ADDR, &data, sizeof(data));
 	}
 
-	return;
-}
-
-/* Gets nearest achievable timing given master clock speed, does not
- * take into account possible minimum/maximum divisor values.  Used
- * by other timing checking functions. */
-static unsigned int get_divisor(unsigned int ns, unsigned int flags)
-{
-	unsigned int divisor;
-
-	switch (flags & TRIG_ROUND_MASK) {
-	case TRIG_ROUND_UP:
-		divisor = (ns + TIMER_BASE - 1) / TIMER_BASE;
-		break;
-	case TRIG_ROUND_DOWN:
-		divisor = ns / TIMER_BASE;
-		break;
-	case TRIG_ROUND_NEAREST:
-	default:
-		divisor = (ns + TIMER_BASE / 2) / TIMER_BASE;
-		break;
+	/* analog output subdevice */
+	s = &dev->subdevices[1];
+	if (thisboard->ao_nchan) {
+		s->type = COMEDI_SUBD_AO;
+		s->subdev_flags = SDF_READABLE | SDF_WRITABLE |
+				  SDF_GROUND | SDF_CMD_WRITE;
+		s->n_chan = thisboard->ao_nchan;
+		s->maxdata = (1 << thisboard->ao_bits) - 1;
+		s->range_table = thisboard->ao_range_table;
+		s->insn_read = ao_readback_insn;
+		s->insn_write = ao_winsn;
+		if (ao_cmd_is_supported(thisboard)) {
+			dev->write_subdev = s;
+			s->do_cmdtest = ao_cmdtest;
+			s->do_cmd = ao_cmd;
+			s->len_chanlist = thisboard->ao_nchan;
+			s->cancel = ao_cancel;
+		}
+	} else {
+		s->type = COMEDI_SUBD_UNUSED;
 	}
-	return divisor;
-}
 
-static unsigned int get_ao_divisor(unsigned int ns, unsigned int flags)
-{
-	return get_divisor(ns, flags) - 2;
-}
-
-/* adjusts the size of hardware fifo (which determines block size for dma xfers) */
-static int set_ai_fifo_size(struct comedi_device *dev, unsigned int num_samples)
-{
-	unsigned int num_fifo_entries;
-	int retval;
-	const struct hw_fifo_info *const fifo = board(dev)->ai_fifo;
+	/*  digital input */
+	s = &dev->subdevices[2];
+	if (thisboard->layout == LAYOUT_64XX) {
+		s->type = COMEDI_SUBD_DI;
+		s->subdev_flags = SDF_READABLE;
+		s->n_chan = 4;
+		s->maxdata = 1;
+		s->range_table = &range_digital;
+		s->insn_bits = di_rbits;
+	} else
+		s->type = COMEDI_SUBD_UNUSED;
 
-	num_fifo_entries = num_samples / fifo->sample_packing_ratio;
+	/*  digital output */
+	if (thisboard->layout == LAYOUT_64XX) {
+		s = &dev->subdevices[3];
+		s->type = COMEDI_SUBD_DO;
+		s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+		s->n_chan = 4;
+		s->maxdata = 1;
+		s->range_table = &range_digital;
+		s->insn_bits = do_wbits;
+	} else
+		s->type = COMEDI_SUBD_UNUSED;
 
-	retval = set_ai_fifo_segment_length(dev,
-					    num_fifo_entries /
-					    fifo->num_segments);
-	if (retval < 0)
-		return retval;
+	/* 8255 */
+	s = &dev->subdevices[4];
+	if (thisboard->has_8255) {
+		if (thisboard->layout == LAYOUT_4020) {
+			dio_8255_iobase = devpriv->main_iobase + I8255_4020_REG;
+			subdev_8255_init(dev, s, dio_callback_4020,
+					 (unsigned long)dio_8255_iobase);
+		} else {
+			dio_8255_iobase =
+				devpriv->dio_counter_iobase + DIO_8255_OFFSET;
+			subdev_8255_init(dev, s, dio_callback,
+					 (unsigned long)dio_8255_iobase);
+		}
+	} else
+		s->type = COMEDI_SUBD_UNUSED;
 
-	num_samples = retval * fifo->num_segments * fifo->sample_packing_ratio;
+	/*  8 channel dio for 60xx */
+	s = &dev->subdevices[5];
+	if (thisboard->layout == LAYOUT_60XX) {
+		s->type = COMEDI_SUBD_DIO;
+		s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+		s->n_chan = 8;
+		s->maxdata = 1;
+		s->range_table = &range_digital;
+		s->insn_config = dio_60xx_config_insn;
+		s->insn_bits = dio_60xx_wbits;
+	} else
+		s->type = COMEDI_SUBD_UNUSED;
 
-	DEBUG_PRINT("set hardware fifo size to %i\n", num_samples);
+	/*  caldac */
+	s = &dev->subdevices[6];
+	s->type = COMEDI_SUBD_CALIB;
+	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
+	s->n_chan = 8;
+	if (thisboard->layout == LAYOUT_4020)
+		s->maxdata = 0xfff;
+	else
+		s->maxdata = 0xff;
+	s->insn_read = calib_read_insn;
+	s->insn_write = calib_write_insn;
+	for (i = 0; i < s->n_chan; i++)
+		caldac_write(dev, i, s->maxdata / 2);
 
-	return num_samples;
-}
-
-/* query length of fifo */
-static unsigned int ai_fifo_size(struct comedi_device *dev)
-{
-	return priv(dev)->ai_fifo_segment_length *
-	    board(dev)->ai_fifo->num_segments *
-	    board(dev)->ai_fifo->sample_packing_ratio;
-}
-
-static int set_ai_fifo_segment_length(struct comedi_device *dev,
-				      unsigned int num_entries)
-{
-	static const int increment_size = 0x100;
-	const struct hw_fifo_info *const fifo = board(dev)->ai_fifo;
-	unsigned int num_increments;
-	uint16_t bits;
-
-	if (num_entries < increment_size)
-		num_entries = increment_size;
-	if (num_entries > fifo->max_segment_length)
-		num_entries = fifo->max_segment_length;
-
-	/*  1 == 256 entries, 2 == 512 entries, etc */
-	num_increments = (num_entries + increment_size / 2) / increment_size;
-
-	bits = (~(num_increments - 1)) & fifo->fifo_size_reg_mask;
-	priv(dev)->fifo_size_bits &= ~fifo->fifo_size_reg_mask;
-	priv(dev)->fifo_size_bits |= bits;
-	writew(priv(dev)->fifo_size_bits,
-	       priv(dev)->main_iobase + FIFO_SIZE_REG);
+	/*  2 channel ad8402 potentiometer */
+	s = &dev->subdevices[7];
+	if (thisboard->layout == LAYOUT_64XX) {
+		s->type = COMEDI_SUBD_CALIB;
+		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
+		s->n_chan = 2;
+		s->insn_read = ad8402_read_insn;
+		s->insn_write = ad8402_write_insn;
+		s->maxdata = 0xff;
+		for (i = 0; i < s->n_chan; i++)
+			ad8402_write(dev, i, s->maxdata / 2);
+	} else
+		s->type = COMEDI_SUBD_UNUSED;
 
-	priv(dev)->ai_fifo_segment_length = num_increments * increment_size;
+	/* serial EEPROM, if present */
+	s = &dev->subdevices[8];
+	if (readl(devpriv->plx9080_iobase + PLX_CONTROL_REG) & CTL_EECHK) {
+		s->type = COMEDI_SUBD_MEMORY;
+		s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
+		s->n_chan = 128;
+		s->maxdata = 0xffff;
+		s->insn_read = eeprom_read_insn;
+	} else
+		s->type = COMEDI_SUBD_UNUSED;
 
-	DEBUG_PRINT("set hardware fifo segment length to %i\n",
-		    priv(dev)->ai_fifo_segment_length);
+	/*  user counter subd XXX */
+	s = &dev->subdevices[9];
+	s->type = COMEDI_SUBD_UNUSED;
 
-	return priv(dev)->ai_fifo_segment_length;
+	return 0;
 }
 
-/* pci-6025 8800 caldac:
- * address 0 == dac channel 0 offset
- * address 1 == dac channel 0 gain
- * address 2 == dac channel 1 offset
- * address 3 == dac channel 1 gain
- * address 4 == fine adc offset
- * address 5 == coarse adc offset
- * address 6 == coarse adc gain
- * address 7 == fine adc gain
- */
-/* pci-6402/16 uses all 8 channels for dac:
- * address 0 == dac channel 0 fine gain
- * address 1 == dac channel 0 coarse gain
- * address 2 == dac channel 0 coarse offset
- * address 3 == dac channel 1 coarse offset
- * address 4 == dac channel 1 fine gain
- * address 5 == dac channel 1 coarse gain
- * address 6 == dac channel 0 fine offset
- * address 7 == dac channel 1 fine offset
-*/
-
-static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
-			     uint8_t value)
+static const struct pcidas64_board
+*cb_pcidas64_find_pci_board(struct pci_dev *pcidev)
 {
-	static const int num_caldac_channels = 8;
-	static const int bitstream_length = 11;
-	unsigned int bitstream = ((address & 0x7) << 8) | value;
-	unsigned int bit, register_bits;
-	static const int caldac_8800_udelay = 1;
+	unsigned int i;
 
-	if (address >= num_caldac_channels) {
-		comedi_error(dev, "illegal caldac channel");
-		return -1;
-	}
-	for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
-		register_bits = 0;
-		if (bitstream & bit)
-			register_bits |= SERIAL_DATA_IN_BIT;
-		udelay(caldac_8800_udelay);
-		writew(register_bits, priv(dev)->main_iobase + CALIBRATION_REG);
-		register_bits |= SERIAL_CLOCK_BIT;
-		udelay(caldac_8800_udelay);
-		writew(register_bits, priv(dev)->main_iobase + CALIBRATION_REG);
-	}
-	udelay(caldac_8800_udelay);
-	writew(SELECT_8800_BIT, priv(dev)->main_iobase + CALIBRATION_REG);
-	udelay(caldac_8800_udelay);
-	writew(0, priv(dev)->main_iobase + CALIBRATION_REG);
-	udelay(caldac_8800_udelay);
-	return 0;
+	for (i = 0; i < ARRAY_SIZE(pcidas64_boards); i++)
+		if (pcidev->device == pcidas64_boards[i].device_id)
+			return &pcidas64_boards[i];
+	return NULL;
 }
 
-/* 4020 caldacs */
-static int caldac_i2c_write(struct comedi_device *dev,
-			    unsigned int caldac_channel, unsigned int value)
+static int auto_attach(struct comedi_device *dev,
+				 unsigned long context_unused)
 {
-	uint8_t serial_bytes[3];
-	uint8_t i2c_addr;
-	enum pointer_bits {
-		/*  manual has gain and offset bits switched */
-		OFFSET_0_2 = 0x1,
-		GAIN_0_2 = 0x2,
-		OFFSET_1_3 = 0x4,
-		GAIN_1_3 = 0x8,
-	};
-	enum data_bits {
-		NOT_CLEAR_REGISTERS = 0x20,
-	};
+	const struct pcidas64_board *thisboard;
+	struct pcidas64_private *devpriv;
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	uint32_t local_range, local_decode;
+	int retval;
 
-	switch (caldac_channel) {
-	case 0:		/*  chan 0 offset */
-		i2c_addr = CALDAC0_I2C_ADDR;
-		serial_bytes[0] = OFFSET_0_2;
-		break;
-	case 1:		/*  chan 1 offset */
-		i2c_addr = CALDAC0_I2C_ADDR;
-		serial_bytes[0] = OFFSET_1_3;
-		break;
-	case 2:		/*  chan 2 offset */
-		i2c_addr = CALDAC1_I2C_ADDR;
-		serial_bytes[0] = OFFSET_0_2;
-		break;
-	case 3:		/*  chan 3 offset */
-		i2c_addr = CALDAC1_I2C_ADDR;
-		serial_bytes[0] = OFFSET_1_3;
-		break;
-	case 4:		/*  chan 0 gain */
-		i2c_addr = CALDAC0_I2C_ADDR;
-		serial_bytes[0] = GAIN_0_2;
-		break;
-	case 5:		/*  chan 1 gain */
-		i2c_addr = CALDAC0_I2C_ADDR;
-		serial_bytes[0] = GAIN_1_3;
-		break;
-	case 6:		/*  chan 2 gain */
-		i2c_addr = CALDAC1_I2C_ADDR;
-		serial_bytes[0] = GAIN_0_2;
-		break;
-	case 7:		/*  chan 3 gain */
-		i2c_addr = CALDAC1_I2C_ADDR;
-		serial_bytes[0] = GAIN_1_3;
-		break;
-	default:
-		comedi_error(dev, "invalid caldac channel\n");
-		return -1;
-		break;
+	dev->board_ptr = cb_pcidas64_find_pci_board(pcidev);
+	if (!dev->board_ptr) {
+		dev_err(dev->class_dev,
+			"cb_pcidas64: does not support pci %s\n",
+			pci_name(pcidev));
+		return -EINVAL;
 	}
-	serial_bytes[1] = NOT_CLEAR_REGISTERS | ((value >> 8) & 0xf);
-	serial_bytes[2] = value & 0xff;
-	i2c_write(dev, i2c_addr, serial_bytes, 3);
-	return 0;
-}
+	thisboard = comedi_board(dev);
 
-/* Their i2c requires a huge delay on setting clock or data high for some reason */
-static const int i2c_high_udelay = 1000;
-static const int i2c_low_udelay = 10;
-
-/* set i2c data line high or low */
-static void i2c_set_sda(struct comedi_device *dev, int state)
-{
-	static const int data_bit = CTL_EE_W;
-	void __iomem *plx_control_addr = priv(dev)->plx9080_iobase +
-					 PLX_CONTROL_REG;
-
-	if (state) {
-		/*  set data line high */
-		priv(dev)->plx_control_bits &= ~data_bit;
-		writel(priv(dev)->plx_control_bits, plx_control_addr);
-		udelay(i2c_high_udelay);
-	} else {		/*  set data line low */
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
-		priv(dev)->plx_control_bits |= data_bit;
-		writel(priv(dev)->plx_control_bits, plx_control_addr);
-		udelay(i2c_low_udelay);
+	if (comedi_pci_enable(pcidev, dev->driver->driver_name)) {
+		dev_warn(dev->class_dev,
+			 "failed to enable PCI device and request regions\n");
+		return -EIO;
 	}
-}
+	pci_set_master(pcidev);
 
-/* set i2c clock line high or low */
-static void i2c_set_scl(struct comedi_device *dev, int state)
-{
-	static const int clock_bit = CTL_USERO;
-	void __iomem *plx_control_addr = priv(dev)->plx9080_iobase +
-					 PLX_CONTROL_REG;
+	/* Initialize dev->board_name */
+	dev->board_name = thisboard->name;
 
-	if (state) {
-		/*  set clock line high */
-		priv(dev)->plx_control_bits &= ~clock_bit;
-		writel(priv(dev)->plx_control_bits, plx_control_addr);
-		udelay(i2c_high_udelay);
-	} else {		/*  set clock line low */
+	dev->iobase = pci_resource_start(pcidev, MAIN_BADDRINDEX);
 
-		priv(dev)->plx_control_bits |= clock_bit;
-		writel(priv(dev)->plx_control_bits, plx_control_addr);
-		udelay(i2c_low_udelay);
-	}
-}
+	devpriv->plx9080_phys_iobase =
+		pci_resource_start(pcidev, PLX9080_BADDRINDEX);
+	devpriv->main_phys_iobase = dev->iobase;
+	devpriv->dio_counter_phys_iobase =
+		pci_resource_start(pcidev, DIO_COUNTER_BADDRINDEX);
 
-static void i2c_write_byte(struct comedi_device *dev, uint8_t byte)
-{
-	uint8_t bit;
-	unsigned int num_bits = 8;
+	/*  remap, won't work with 2.0 kernels but who cares */
+	devpriv->plx9080_iobase =
+		ioremap(devpriv->plx9080_phys_iobase,
+			pci_resource_len(pcidev, PLX9080_BADDRINDEX));
+	devpriv->main_iobase =
+		ioremap(devpriv->main_phys_iobase,
+			pci_resource_len(pcidev, MAIN_BADDRINDEX));
+	devpriv->dio_counter_iobase =
+		ioremap(devpriv->dio_counter_phys_iobase,
+			pci_resource_len(pcidev, DIO_COUNTER_BADDRINDEX));
+
+	if (!devpriv->plx9080_iobase || !devpriv->main_iobase
+	    || !devpriv->dio_counter_iobase) {
+		dev_warn(dev->class_dev, "failed to remap io memory\n");
+		return -ENOMEM;
+	}
 
-	DEBUG_PRINT("writing to i2c byte 0x%x\n", byte);
+	DEBUG_PRINT(" plx9080 remapped to 0x%p\n", devpriv->plx9080_iobase);
+	DEBUG_PRINT(" main remapped to 0x%p\n", devpriv->main_iobase);
+	DEBUG_PRINT(" diocounter remapped to 0x%p\n",
+		    devpriv->dio_counter_iobase);
 
-	for (bit = 1 << (num_bits - 1); bit; bit >>= 1) {
-		i2c_set_scl(dev, 0);
-		if ((byte & bit))
-			i2c_set_sda(dev, 1);
-		else
-			i2c_set_sda(dev, 0);
-		i2c_set_scl(dev, 1);
-	}
-}
+	/*  figure out what local addresses are */
+	local_range = readl(devpriv->plx9080_iobase + PLX_LAS0RNG_REG) &
+		      LRNG_MEM_MASK;
+	local_decode = readl(devpriv->plx9080_iobase + PLX_LAS0MAP_REG) &
+		       local_range & LMAP_MEM_MASK;
+	devpriv->local0_iobase = ((uint32_t)devpriv->main_phys_iobase &
+				  ~local_range) | local_decode;
+	local_range = readl(devpriv->plx9080_iobase + PLX_LAS1RNG_REG) &
+		      LRNG_MEM_MASK;
+	local_decode = readl(devpriv->plx9080_iobase + PLX_LAS1MAP_REG) &
+		       local_range & LMAP_MEM_MASK;
+	devpriv->local1_iobase = ((uint32_t)devpriv->dio_counter_phys_iobase &
+				  ~local_range) | local_decode;
+
+	DEBUG_PRINT(" local 0 io addr 0x%x\n", devpriv->local0_iobase);
+	DEBUG_PRINT(" local 1 io addr 0x%x\n", devpriv->local1_iobase);
 
-/* we can't really read the lines, so fake it */
-static int i2c_read_ack(struct comedi_device *dev)
-{
-	i2c_set_scl(dev, 0);
-	i2c_set_sda(dev, 1);
-	i2c_set_scl(dev, 1);
+	retval = alloc_and_init_dma_members(dev);
+	if (retval < 0)
+		return retval;
 
-	return 0;		/*  return fake acknowledge bit */
-}
+	devpriv->hw_revision =
+		hw_revision(dev, readw(devpriv->main_iobase + HW_STATUS_REG));
+	dev_dbg(dev->class_dev, "stc hardware revision %i\n",
+		devpriv->hw_revision);
+	init_plx9080(dev);
+	init_stc_registers(dev);
+	/*  get irq */
+	if (request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED,
+			"cb_pcidas64", dev)) {
+		dev_dbg(dev->class_dev, "unable to allocate irq %u\n",
+			pcidev->irq);
+		return -EINVAL;
+	}
+	dev->irq = pcidev->irq;
+	dev_dbg(dev->class_dev, "irq %u\n", dev->irq);
 
-/* send start bit */
-static void i2c_start(struct comedi_device *dev)
-{
-	i2c_set_scl(dev, 1);
-	i2c_set_sda(dev, 1);
-	i2c_set_sda(dev, 0);
-}
+	retval = setup_subdevices(dev);
+	if (retval < 0)
+		return retval;
 
-/* send stop bit */
-static void i2c_stop(struct comedi_device *dev)
-{
-	i2c_set_scl(dev, 0);
-	i2c_set_sda(dev, 0);
-	i2c_set_scl(dev, 1);
-	i2c_set_sda(dev, 1);
+	return 0;
 }
 
-static void i2c_write(struct comedi_device *dev, unsigned int address,
-		      const uint8_t *data, unsigned int length)
+static void detach(struct comedi_device *dev)
 {
+	const struct pcidas64_board *thisboard = comedi_board(dev);
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct pcidas64_private *devpriv = dev->private;
 	unsigned int i;
-	uint8_t bitstream;
-	static const int read_bit = 0x1;
-
-/* XXX need mutex to prevent simultaneous attempts to access eeprom and i2c bus */
-
-	/*  make sure we dont send anything to eeprom */
-	priv(dev)->plx_control_bits &= ~CTL_EE_CS;
-
-	i2c_stop(dev);
-	i2c_start(dev);
 
-	/*  send address and write bit */
-	bitstream = (address << 1) & ~read_bit;
-	i2c_write_byte(dev, bitstream);
-
-	/*  get acknowledge */
-	if (i2c_read_ack(dev) != 0) {
-		comedi_error(dev, "i2c write failed: no acknowledge");
-		i2c_stop(dev);
-		return;
-	}
-	/*  write data bytes */
-	for (i = 0; i < length; i++) {
-		i2c_write_byte(dev, data[i]);
-		if (i2c_read_ack(dev) != 0) {
-			comedi_error(dev, "i2c write failed: no acknowledge");
-			i2c_stop(dev);
-			return;
+	if (dev->irq)
+		free_irq(dev->irq, dev);
+	if (devpriv) {
+		if (pcidev) {
+			if (devpriv->plx9080_iobase) {
+				disable_plx_interrupts(dev);
+				iounmap(devpriv->plx9080_iobase);
+			}
+			if (devpriv->main_iobase)
+				iounmap(devpriv->main_iobase);
+			if (devpriv->dio_counter_iobase)
+				iounmap(devpriv->dio_counter_iobase);
+			/*  free pci dma buffers */
+			for (i = 0; i < ai_dma_ring_count(thisboard); i++) {
+				if (devpriv->ai_buffer[i])
+					pci_free_consistent(pcidev,
+						DMA_BUFFER_SIZE,
+						devpriv->ai_buffer[i],
+						devpriv->ai_buffer_bus_addr[i]);
+			}
+			for (i = 0; i < AO_DMA_RING_COUNT; i++) {
+				if (devpriv->ao_buffer[i])
+					pci_free_consistent(pcidev,
+						DMA_BUFFER_SIZE,
+						devpriv->ao_buffer[i],
+						devpriv->ao_buffer_bus_addr[i]);
+			}
+			/*  free dma descriptors */
+			if (devpriv->ai_dma_desc)
+				pci_free_consistent(pcidev,
+					sizeof(struct plx_dma_desc) *
+					ai_dma_ring_count(thisboard),
+					devpriv->ai_dma_desc,
+					devpriv->ai_dma_desc_bus_addr);
+			if (devpriv->ao_dma_desc)
+				pci_free_consistent(pcidev,
+					sizeof(struct plx_dma_desc) *
+					AO_DMA_RING_COUNT,
+					devpriv->ao_dma_desc,
+					devpriv->ao_dma_desc_bus_addr);
 		}
 	}
-	i2c_stop(dev);
+	if (dev->subdevices)
+		subdev_8255_cleanup(dev, &dev->subdevices[4]);
+	if (pcidev) {
+		if (dev->iobase)
+			comedi_pci_disable(pcidev);
+	}
 }
 
 static struct comedi_driver cb_pcidas64_driver = {
 	.driver_name	= "cb_pcidas64",
 	.module		= THIS_MODULE,
-	.attach		= attach,
+	.auto_attach	= auto_attach,
 	.detach		= detach,
 };
 
-static int __devinit cb_pcidas64_pci_probe(struct pci_dev *dev,
+static int cb_pcidas64_pci_probe(struct pci_dev *dev,
 					   const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &cb_pcidas64_driver);
 }
 
-static void __devexit cb_pcidas64_pci_remove(struct pci_dev *dev)
+static void cb_pcidas64_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(cb_pcidas64_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x001d) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x001e) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0035) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0036) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0037) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0052) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x005d) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x005e) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x005f) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0061) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0062) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0063) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0064) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0066) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0067) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0068) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x006f) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0078) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0079) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001d) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001e) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0035) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0036) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0037) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0052) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x005d) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x005e) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x005f) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0061) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0062) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0063) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0064) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0066) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0067) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0068) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x006f) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0078) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0079) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, cb_pcidas64_pci_table);
@@ -4230,7 +4253,7 @@ static struct pci_driver cb_pcidas64_pci_driver = {
 	.name		= "cb_pcidas64",
 	.id_table	= cb_pcidas64_pci_table,
 	.probe		= cb_pcidas64_pci_probe,
-	.remove		= __devexit_p(cb_pcidas64_pci_remove),
+	.remove		= cb_pcidas64_pci_remove,
 };
 module_comedi_pci_driver(cb_pcidas64_driver, cb_pcidas64_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
index aef946d..7c6029a 100644
--- a/drivers/staging/comedi/drivers/cb_pcidda.c
+++ b/drivers/staging/comedi/drivers/cb_pcidda.c
@@ -1,90 +1,78 @@
 /*
-    comedi/drivers/cb_pcidda.c
-    This intends to be a driver for the ComputerBoards / MeasurementComputing
-    PCI-DDA series.
-
-	 Copyright (C) 2001 Ivan Martinez <ivanmr@altavista.com>
-    Copyright (C) 2001 Frank Mori Hess <fmhess@users.sourceforge.net>
-
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 1997-8 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.
-
-    You 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.
+ * comedi/drivers/cb_pcidda.c
+ * Driver for the ComputerBoards / MeasurementComputing PCI-DDA series.
+ *
+ * Copyright (C) 2001 Ivan Martinez <ivanmr@altavista.com>
+ * Copyright (C) 2001 Frank Mori Hess <fmhess@users.sourceforge.net>
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1997-8 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.
+ *
+ * You 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.
+ */
 
-*/
 /*
-Driver: cb_pcidda
-Description: MeasurementComputing PCI-DDA series
-Author: Ivan Martinez <ivanmr@altavista.com>, Frank Mori Hess <fmhess@users.sourceforge.net>
-Status: Supports 08/16, 04/16, 02/16, 08/12, 04/12, and 02/12
-Devices: [Measurement Computing] PCI-DDA08/12 (cb_pcidda), PCI-DDA04/12,
-  PCI-DDA02/12, PCI-DDA08/16, PCI-DDA04/16, PCI-DDA02/16
-
-Configuration options:
-  [0] - PCI bus of device (optional)
-  [1] - PCI slot of device (optional)
-  If bus/slot is not specified, the first available PCI
-  device will be used.
-
-Only simple analog output writing is supported.
-
-So far it has only been tested with:
-  - PCI-DDA08/12
-Please report success/failure with other different cards to
-<comedi@comedi.org>.
-*/
+ * Driver: cb_pcidda
+ * Description: MeasurementComputing PCI-DDA series
+ * Devices: (Measurement Computing) PCI-DDA08/12 [pci-dda08/12]
+ *	    (Measurement Computing) PCI-DDA04/12 [pci-dda04/12]
+ *	    (Measurement Computing) PCI-DDA02/12 [pci-dda02/12]
+ *	    (Measurement Computing) PCI-DDA08/16 [pci-dda08/16]
+ *	    (Measurement Computing) PCI-DDA04/16 [pci-dda04/16]
+ *	    (Measurement Computing) PCI-DDA02/16 [pci-dda02/16]
+ * Author: Ivan Martinez <ivanmr@altavista.com>
+ *	   Frank Mori Hess <fmhess@users.sourceforge.net>
+ * Status: works
+ *
+ * Configuration options: not applicable, uses PCI auto config
+ *
+ * Only simple analog output writing is supported.
+ */
 
 #include "../comedidev.h"
 
 #include "comedi_fc.h"
 #include "8255.h"
 
-/* PCI vendor number of ComputerBoards */
-#define PCI_VENDOR_ID_CB        0x1307
+/*
+ * ComputerBoards PCI Device ID's supported by this driver
+ */
+#define PCI_DEVICE_ID_DDA02_12		0x0020
+#define PCI_DEVICE_ID_DDA04_12		0x0021
+#define PCI_DEVICE_ID_DDA08_12		0x0022
+#define PCI_DEVICE_ID_DDA02_16		0x0023
+#define PCI_DEVICE_ID_DDA04_16		0x0024
+#define PCI_DEVICE_ID_DDA08_16		0x0025
+
 #define EEPROM_SIZE	128	/*  number of entries in eeprom */
 /* maximum number of ao channels for supported boards */
 #define MAX_AO_CHANNELS 8
 
 /* Digital I/O registers */
-#define PORT1A 0		/*  PORT 1A DATA */
-
-#define PORT1B 1		/*  PORT 1B DATA */
-
-#define PORT1C 2		/*  PORT 1C DATA */
-
-#define CONTROL1 3		/*  CONTROL REGISTER 1 */
-
-#define PORT2A 4		/*  PORT 2A DATA */
-
-#define PORT2B 5		/*  PORT 2B DATA */
-
-#define PORT2C 6		/*  PORT 2C DATA */
-
-#define CONTROL2 7		/*  CONTROL REGISTER 2 */
+#define CB_DDA_DIO0_8255_BASE		0x00
+#define CB_DDA_DIO1_8255_BASE		0x04
 
 /* DAC registers */
-#define DACONTROL	0	/*  D/A CONTROL REGISTER */
-#define	SU	0000001		/*  Simultaneous update enabled */
-#define NOSU	0000000		/*  Simultaneous update disabled */
-#define	ENABLEDAC	0000002	/*  Enable specified DAC */
-#define	DISABLEDAC	0000000	/*  Disable specified DAC */
-#define RANGE2V5	0000000	/*  2.5V */
-#define RANGE5V	0000200		/*  5V */
-#define RANGE10V	0000300	/*  10V */
-#define UNIP	0000400		/*  Unipolar outputs */
-#define BIP	0000000		/*  Bipolar outputs */
+#define CB_DDA_DA_CTRL_REG		0x00	   /* D/A Control Register  */
+#define CB_DDA_DA_CTRL_SU		(1 << 0)   /*  Simultaneous update  */
+#define CB_DDA_DA_CTRL_EN		(1 << 1)   /*  Enable specified DAC */
+#define CB_DDA_DA_CTRL_DAC(x)		((x) << 2) /*  Specify DAC channel  */
+#define CB_DDA_DA_CTRL_RANGE2V5		(0 << 6)   /*  2.5V range           */
+#define CB_DDA_DA_CTRL_RANGE5V		(2 << 6)   /*  5V range             */
+#define CB_DDA_DA_CTRL_RANGE10V		(3 << 6)   /*  10V range            */
+#define CB_DDA_DA_CTRL_UNIP		(1 << 8)   /*  Unipolar range       */
 
 #define DACALIBRATION1	4	/*  D/A CALIBRATION REGISTER 1 */
 /* write bits */
@@ -109,107 +97,67 @@ Please report success/failure with other different cards to
 /* manual says to set this bit with no explanation */
 #define DUMMY_BIT       0x40
 
-#define DADATA	8		/*  FIRST D/A DATA REGISTER (0) */
+#define CB_DDA_DA_DATA_REG(x)		(0x08 + ((x) * 2))
+
+/* Offsets for the caldac channels */
+#define CB_DDA_CALDAC_FINE_GAIN		0
+#define CB_DDA_CALDAC_COURSE_GAIN	1
+#define CB_DDA_CALDAC_COURSE_OFFSET	2
+#define CB_DDA_CALDAC_FINE_OFFSET	3
 
 static const struct comedi_lrange cb_pcidda_ranges = {
-	6,
-	{
-	 BIP_RANGE(10),
-	 BIP_RANGE(5),
-	 BIP_RANGE(2.5),
-	 UNI_RANGE(10),
-	 UNI_RANGE(5),
-	 UNI_RANGE(2.5),
-	 }
+	6, {
+		BIP_RANGE(10),
+		BIP_RANGE(5),
+		BIP_RANGE(2.5),
+		UNI_RANGE(10),
+		UNI_RANGE(5),
+		UNI_RANGE(2.5)
+	}
 };
 
-/*
- * 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.
- */
 struct cb_pcidda_board {
 	const char *name;
-	char status;		/*  Driver status: */
-
-	/*
-	 * 0 - tested
-	 * 1 - manual read, not tested
-	 * 2 - manual not read
-	 */
-
 	unsigned short device_id;
 	int ao_chans;
 	int ao_bits;
-	const struct comedi_lrange *ranges;
 };
 
 static const struct cb_pcidda_board cb_pcidda_boards[] = {
 	{
-	 .name = "pci-dda02/12",
-	 .status = 1,
-	 .device_id = 0x20,
-	 .ao_chans = 2,
-	 .ao_bits = 12,
-	 .ranges = &cb_pcidda_ranges,
-	 },
-	{
-	 .name = "pci-dda04/12",
-	 .status = 1,
-	 .device_id = 0x21,
-	 .ao_chans = 4,
-	 .ao_bits = 12,
-	 .ranges = &cb_pcidda_ranges,
-	 },
-	{
-	 .name = "pci-dda08/12",
-	 .status = 0,
-	 .device_id = 0x22,
-	 .ao_chans = 8,
-	 .ao_bits = 12,
-	 .ranges = &cb_pcidda_ranges,
-	 },
-	{
-	 .name = "pci-dda02/16",
-	 .status = 2,
-	 .device_id = 0x23,
-	 .ao_chans = 2,
-	 .ao_bits = 16,
-	 .ranges = &cb_pcidda_ranges,
-	 },
-	{
-	 .name = "pci-dda04/16",
-	 .status = 2,
-	 .device_id = 0x24,
-	 .ao_chans = 4,
-	 .ao_bits = 16,
-	 .ranges = &cb_pcidda_ranges,
-	 },
-	{
-	 .name = "pci-dda08/16",
-	 .status = 0,
-	 .device_id = 0x25,
-	 .ao_chans = 8,
-	 .ao_bits = 16,
-	 .ranges = &cb_pcidda_ranges,
-	 },
+		.name		= "pci-dda02/12",
+		.device_id	= PCI_DEVICE_ID_DDA02_12,
+		.ao_chans	= 2,
+		.ao_bits	= 12,
+	}, {
+		.name		= "pci-dda04/12",
+		.device_id	= PCI_DEVICE_ID_DDA04_12,
+		.ao_chans	= 4,
+		.ao_bits	= 12,
+	}, {
+		.name		= "pci-dda08/12",
+		.device_id	= PCI_DEVICE_ID_DDA08_12,
+		.ao_chans	= 8,
+		.ao_bits	= 12,
+	}, {
+		.name		= "pci-dda02/16",
+		.device_id	= PCI_DEVICE_ID_DDA02_16,
+		.ao_chans	= 2,
+		.ao_bits	= 16,
+	}, {
+		.name		= "pci-dda04/16",
+		.device_id	= PCI_DEVICE_ID_DDA04_16,
+		.ao_chans	= 4,
+		.ao_bits	= 16,
+	}, {
+		.name		= "pci-dda08/16",
+		.device_id	= PCI_DEVICE_ID_DDA08_16,
+		.ao_chans	= 8,
+		.ao_bits	= 16,
+	},
 };
 
-/*
- * this structure is for data unique to this hardware driver.  If
- * several hardware drivers keep similar information in this structure,
- * feel free to suggest moving the variable to the struct comedi_device
- * struct.
- */
 struct cb_pcidda_private {
-	int data;
-
-	unsigned long digitalio;
-	unsigned long dac;
-
-	/* unsigned long control_status; */
-	/* unsigned long adc_fifo; */
-
 	/* bits last written to da calibration register 1 */
 	unsigned int dac_cal1_bits;
 	/* current range settings for output channels */
@@ -217,181 +165,16 @@ struct cb_pcidda_private {
 	u16 eeprom_data[EEPROM_SIZE];	/*  software copy of board's eeprom */
 };
 
-/*
- * I will program this later... ;-)
- */
-#if 0
-static int cb_pcidda_ai_cmd(struct comedi_device *dev,
-			    struct comedi_subdevice *s)
-{
-	printk("cb_pcidda_ai_cmd\n");
-	printk("subdev: %d\n", cmd->subdev);
-	printk("flags: %d\n", cmd->flags);
-	printk("start_src: %d\n", cmd->start_src);
-	printk("start_arg: %d\n", cmd->start_arg);
-	printk("scan_begin_src: %d\n", cmd->scan_begin_src);
-	printk("convert_src: %d\n", cmd->convert_src);
-	printk("convert_arg: %d\n", cmd->convert_arg);
-	printk("scan_end_src: %d\n", cmd->scan_end_src);
-	printk("scan_end_arg: %d\n", cmd->scan_end_arg);
-	printk("stop_src: %d\n", cmd->stop_src);
-	printk("stop_arg: %d\n", cmd->stop_arg);
-	printk("chanlist_len: %d\n", cmd->chanlist_len);
-}
-#endif
-
-#if 0
-static int cb_pcidda_ai_cmdtest(struct comedi_device *dev,
-				struct comedi_subdevice *s,
-				struct comedi_cmd *cmd)
-{
-	int err = 0;
-	int tmp;
-
-	/* 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_TIMER | TRIG_EXT);
-	err |= cfc_check_trigger_src(&cmd->convert_src,
-					TRIG_TIMER | TRIG_EXT);
-	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
-	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
-
-	if (err)
-		return 1;
-
-	/* Step 2a : make sure trigger sources are unique */
-
-	err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
-	err |= cfc_check_trigger_is_unique(cmd->convert_src);
-	err |= cfc_check_trigger_is_unique(cmd->stop_src);
-
-	/* Step 2b : and mutually compatible */
-
-	if (err)
-		return 2;
-
-	/* step 3: make sure arguments are trivially compatible */
-
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
-#define MAX_SPEED	10000	/* in nanoseconds */
-#define MIN_SPEED	1000000000	/* in nanoseconds */
-
-	if (cmd->scan_begin_src == TRIG_TIMER) {
-		if (cmd->scan_begin_arg < MAX_SPEED) {
-			cmd->scan_begin_arg = MAX_SPEED;
-			err++;
-		}
-		if (cmd->scan_begin_arg > MIN_SPEED) {
-			cmd->scan_begin_arg = MIN_SPEED;
-			err++;
-		}
-	} else {
-		/* external trigger */
-		/* should be level/edge, hi/lo specification here */
-		/* should specify multiple external triggers */
-		if (cmd->scan_begin_arg > 9) {
-			cmd->scan_begin_arg = 9;
-			err++;
-		}
-	}
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < MAX_SPEED) {
-			cmd->convert_arg = MAX_SPEED;
-			err++;
-		}
-		if (cmd->convert_arg > MIN_SPEED) {
-			cmd->convert_arg = MIN_SPEED;
-			err++;
-		}
-	} else {
-		/* external trigger */
-		/* see above */
-		if (cmd->convert_arg > 9) {
-			cmd->convert_arg = 9;
-			err++;
-		}
-	}
-
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (cmd->stop_arg > 0x00ffffff) {
-			cmd->stop_arg = 0x00ffffff;
-			err++;
-		}
-	} else {
-		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
-
-	if (err)
-		return 3;
-
-	/* step 4: fix up any arguments */
-
-	if (cmd->scan_begin_src == TRIG_TIMER) {
-		tmp = cmd->scan_begin_arg;
-		cb_pcidda_ns_to_timer(&cmd->scan_begin_arg,
-				      cmd->flags & TRIG_ROUND_MASK);
-		if (tmp != cmd->scan_begin_arg)
-			err++;
-	}
-	if (cmd->convert_src == TRIG_TIMER) {
-		tmp = cmd->convert_arg;
-		cb_pcidda_ns_to_timer(&cmd->convert_arg,
-				      cmd->flags & TRIG_ROUND_MASK);
-		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;
-			err++;
-		}
-	}
-
-	if (err)
-		return 4;
-
-	return 0;
-}
-#endif
-
-/* 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. */
-#if 0
-static int cb_pcidda_ns_to_timer(unsigned int *ns, int round)
-{
-	/* trivial timer */
-	return *ns;
-}
-#endif
-
 /* lowlevel read from eeprom */
 static unsigned int cb_pcidda_serial_in(struct comedi_device *dev)
 {
-	struct cb_pcidda_private *devpriv = dev->private;
 	unsigned int value = 0;
 	int i;
 	const int value_width = 16;	/*  number of bits wide values are */
 
 	for (i = 1; i <= value_width; i++) {
 		/*  read bits most significant bit first */
-		if (inw_p(devpriv->dac + DACALIBRATION1) & SERIAL_OUT_BIT)
+		if (inw_p(dev->iobase + DACALIBRATION1) & SERIAL_OUT_BIT)
 			value |= 1 << (value_width - i);
 	}
 
@@ -411,7 +194,7 @@ static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
 			devpriv->dac_cal1_bits |= SERIAL_IN_BIT;
 		else
 			devpriv->dac_cal1_bits &= ~SERIAL_IN_BIT;
-		outw_p(devpriv->dac_cal1_bits, devpriv->dac + DACALIBRATION1);
+		outw_p(devpriv->dac_cal1_bits, dev->iobase + DACALIBRATION1);
 	}
 }
 
@@ -419,7 +202,6 @@ static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
 static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
 					  unsigned int address)
 {
-	struct cb_pcidda_private *devpriv = dev->private;
 	unsigned int i;
 	unsigned int cal2_bits;
 	unsigned int value;
@@ -435,7 +217,7 @@ static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
 	/*  deactivate caldacs (one caldac for every two channels) */
 	for (i = 0; i < max_num_caldacs; i++)
 		cal2_bits |= DESELECT_CALDAC_BIT(i);
-	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
+	outw_p(cal2_bits, dev->iobase + DACALIBRATION2);
 
 	/*  tell eeprom we want to read */
 	cb_pcidda_serial_out(dev, read_instruction, instruction_length);
@@ -446,7 +228,7 @@ static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
 
 	/*  deactivate eeprom */
 	cal2_bits &= ~SELECT_EEPROM_BIT;
-	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
+	outw_p(cal2_bits, dev->iobase + DACALIBRATION2);
 
 	return value;
 }
@@ -456,7 +238,6 @@ static void cb_pcidda_write_caldac(struct comedi_device *dev,
 				   unsigned int caldac, unsigned int channel,
 				   unsigned int value)
 {
-	struct cb_pcidda_private *devpriv = dev->private;
 	unsigned int cal2_bits;
 	unsigned int i;
 	/* caldacs use 3 bit channel specification */
@@ -479,72 +260,10 @@ static void cb_pcidda_write_caldac(struct comedi_device *dev,
 		cal2_bits |= DESELECT_CALDAC_BIT(i);
 	/*  activate the caldac we want */
 	cal2_bits &= ~DESELECT_CALDAC_BIT(caldac);
-	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
+	outw_p(cal2_bits, dev->iobase + DACALIBRATION2);
 	/*  deactivate caldac */
 	cal2_bits |= DESELECT_CALDAC_BIT(caldac);
-	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
-}
-
-/* returns caldac that calibrates given analog out channel */
-static unsigned int caldac_number(unsigned int channel)
-{
-	return channel / 2;
-}
-
-/* returns caldac channel that provides fine gain for given ao channel */
-static unsigned int fine_gain_channel(unsigned int ao_channel)
-{
-	return 4 * (ao_channel % 2);
-}
-
-/* returns caldac channel that provides coarse gain for given ao channel */
-static unsigned int coarse_gain_channel(unsigned int ao_channel)
-{
-	return 1 + 4 * (ao_channel % 2);
-}
-
-/* returns caldac channel that provides coarse offset for given ao channel */
-static unsigned int coarse_offset_channel(unsigned int ao_channel)
-{
-	return 2 + 4 * (ao_channel % 2);
-}
-
-/* returns caldac channel that provides fine offset for given ao channel */
-static unsigned int fine_offset_channel(unsigned int ao_channel)
-{
-	return 3 + 4 * (ao_channel % 2);
-}
-
-/* returns eeprom address that provides offset for given ao channel and range */
-static unsigned int offset_eeprom_address(unsigned int ao_channel,
-					  unsigned int range)
-{
-	return 0x7 + 2 * range + 12 * ao_channel;
-}
-
-/*
- * returns eeprom address that provides gain calibration for given ao
- * channel and range
- */
-static unsigned int gain_eeprom_address(unsigned int ao_channel,
-					unsigned int range)
-{
-	return 0x8 + 2 * range + 12 * ao_channel;
-}
-
-/*
- * returns upper byte of eeprom entry, which gives the coarse adjustment
- * values
- */
-static unsigned int eeprom_coarse_byte(unsigned int word)
-{
-	return (word >> 8) & 0xff;
-}
-
-/* returns lower byte of eeprom entry, which gives the fine adjustment values */
-static unsigned int eeprom_fine_byte(unsigned int word)
-{
-	return word & 0xff;
+	outw_p(cal2_bits, dev->iobase + DACALIBRATION2);
 }
 
 /* set caldacs to eeprom values for given channel and range */
@@ -552,85 +271,68 @@ static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
 				unsigned int range)
 {
 	struct cb_pcidda_private *devpriv = dev->private;
-	unsigned int coarse_offset, fine_offset, coarse_gain, fine_gain;
+	unsigned int caldac = channel / 2;	/* two caldacs per channel */
+	unsigned int chan = 4 * (channel % 2);	/* caldac channel base */
+	unsigned int index = 2 * range + 12 * channel;
+	unsigned int offset;
+	unsigned int gain;
 
-	/* remember range so we can tell when we need to readjust calibration */
+	/* save range so we can tell when we need to readjust calibration */
 	devpriv->ao_range[channel] = range;
 
-	/*  get values from eeprom data */
-	coarse_offset =
-	    eeprom_coarse_byte(devpriv->eeprom_data
-			       [offset_eeprom_address(channel, range)]);
-	fine_offset =
-	    eeprom_fine_byte(devpriv->eeprom_data
-			     [offset_eeprom_address(channel, range)]);
-	coarse_gain =
-	    eeprom_coarse_byte(devpriv->eeprom_data
-			       [gain_eeprom_address(channel, range)]);
-	fine_gain =
-	    eeprom_fine_byte(devpriv->eeprom_data
-			     [gain_eeprom_address(channel, range)]);
-
-	/*  set caldacs */
-	cb_pcidda_write_caldac(dev, caldac_number(channel),
-			       coarse_offset_channel(channel), coarse_offset);
-	cb_pcidda_write_caldac(dev, caldac_number(channel),
-			       fine_offset_channel(channel), fine_offset);
-	cb_pcidda_write_caldac(dev, caldac_number(channel),
-			       coarse_gain_channel(channel), coarse_gain);
-	cb_pcidda_write_caldac(dev, caldac_number(channel),
-			       fine_gain_channel(channel), fine_gain);
+	/* get values from eeprom data */
+	offset = devpriv->eeprom_data[0x7 + index];
+	gain = devpriv->eeprom_data[0x8 + index];
+
+	/* set caldacs */
+	cb_pcidda_write_caldac(dev, caldac, chan + CB_DDA_CALDAC_COURSE_OFFSET,
+			       (offset >> 8) & 0xff);
+	cb_pcidda_write_caldac(dev, caldac, chan + CB_DDA_CALDAC_FINE_OFFSET,
+			       offset & 0xff);
+	cb_pcidda_write_caldac(dev, caldac, chan + CB_DDA_CALDAC_COURSE_GAIN,
+			       (gain >> 8) & 0xff);
+	cb_pcidda_write_caldac(dev, caldac, chan + CB_DDA_CALDAC_FINE_GAIN,
+			       gain & 0xff);
 }
 
-static int cb_pcidda_ao_winsn(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+static int cb_pcidda_ao_insn_write(struct comedi_device *dev,
+				   struct comedi_subdevice *s,
+				   struct comedi_insn *insn,
+				   unsigned int *data)
 {
 	struct cb_pcidda_private *devpriv = dev->private;
-	unsigned int command;
-	unsigned int channel, range;
-
-	channel = CR_CHAN(insn->chanspec);
-	range = CR_RANGE(insn->chanspec);
+	unsigned int channel = CR_CHAN(insn->chanspec);
+	unsigned int range = CR_RANGE(insn->chanspec);
+	unsigned int ctrl;
 
-	/*  adjust calibration dacs if range has changed */
 	if (range != devpriv->ao_range[channel])
 		cb_pcidda_calibrate(dev, channel, range);
 
-	/* output channel configuration */
-	command = NOSU | ENABLEDAC;
+	ctrl = CB_DDA_DA_CTRL_EN | CB_DDA_DA_CTRL_DAC(channel);
 
-	/* output channel range */
 	switch (range) {
 	case 0:
-		command |= BIP | RANGE10V;
-		break;
-	case 1:
-		command |= BIP | RANGE5V;
-		break;
-	case 2:
-		command |= BIP | RANGE2V5;
-		break;
 	case 3:
-		command |= UNIP | RANGE10V;
+		ctrl |= CB_DDA_DA_CTRL_RANGE10V;
 		break;
+	case 1:
 	case 4:
-		command |= UNIP | RANGE5V;
+		ctrl |= CB_DDA_DA_CTRL_RANGE5V;
 		break;
+	case 2:
 	case 5:
-		command |= UNIP | RANGE2V5;
+		ctrl |= CB_DDA_DA_CTRL_RANGE2V5;
 		break;
 	}
 
-	/* output channel specification */
-	command |= channel << 2;
-	outw(command, devpriv->dac + DACONTROL);
+	if (range > 2)
+		ctrl |= CB_DDA_DA_CTRL_UNIP;
 
-	/* write data */
-	outw(data[0], devpriv->dac + DADATA + channel * 2);
+	outw(ctrl, dev->iobase + CB_DDA_DA_CTRL_REG);
 
-	/* return the number of samples read/written */
-	return 1;
+	outw(data[0], dev->iobase + CB_DDA_DA_DATA_REG(channel));
+
+	return insn->n;
 }
 
 static const void *cb_pcidda_find_boardinfo(struct comedi_device *dev,
@@ -647,41 +349,33 @@ static const void *cb_pcidda_find_boardinfo(struct comedi_device *dev,
 	return NULL;
 }
 
-static int cb_pcidda_attach_pci(struct comedi_device *dev,
-				struct pci_dev *pcidev)
+static int cb_pcidda_auto_attach(struct comedi_device *dev,
+					   unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	const struct cb_pcidda_board *thisboard;
 	struct cb_pcidda_private *devpriv;
 	struct comedi_subdevice *s;
-	int index;
+	unsigned long iobase_8255;
+	int i;
 	int ret;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
-
 	thisboard = cb_pcidda_find_boardinfo(dev, pcidev);
-	if (!pcidev)
+	if (!thisboard)
 		return -ENODEV;
 	dev->board_ptr = thisboard;
 	dev->board_name = thisboard->name;
 
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_pci_enable(pcidev, dev->board_name);
 	if (ret)
 		return ret;
-
-	devpriv->digitalio = pci_resource_start(pcidev, 2);
-	devpriv->dac = pci_resource_start(pcidev, 3);
-	dev->iobase = devpriv->dac;
-
-	if (thisboard->status == 2)
-		printk
-		    ("WARNING: DRIVER FOR THIS BOARD NOT CHECKED WITH MANUAL. "
-		     "WORKS ASSUMING FULL COMPATIBILITY WITH PCI-DDA08/12. "
-		     "PLEASE REPORT USAGE TO <ivanmr@altavista.com>.\n");
+	dev->iobase = pci_resource_start(pcidev, 3);
+	iobase_8255 = pci_resource_start(pcidev, 2);
 
 	ret = comedi_alloc_subdevices(dev, 3);
 	if (ret)
@@ -693,29 +387,24 @@ static int cb_pcidda_attach_pci(struct comedi_device *dev,
 	s->subdev_flags = SDF_WRITABLE;
 	s->n_chan = thisboard->ao_chans;
 	s->maxdata = (1 << thisboard->ao_bits) - 1;
-	s->range_table = thisboard->ranges;
-	s->insn_write = cb_pcidda_ao_winsn;
-
-	/* s->subdev_flags |= SDF_CMD_READ; */
-	/* s->do_cmd = cb_pcidda_ai_cmd; */
-	/* s->do_cmdtest = cb_pcidda_ai_cmdtest; */
-
-	/*  two 8255 digital io subdevices */
-	s = &dev->subdevices[1];
-	subdev_8255_init(dev, s, NULL, devpriv->digitalio);
-	s = &dev->subdevices[2];
-	subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A);
-
-	dev_dbg(dev->class_dev, "eeprom:\n");
-	for (index = 0; index < EEPROM_SIZE; index++) {
-		devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index);
-		dev_dbg(dev->class_dev, "%i:0x%x\n", index,
-			devpriv->eeprom_data[index]);
+	s->range_table = &cb_pcidda_ranges;
+	s->insn_write = cb_pcidda_ao_insn_write;
+
+	/* two 8255 digital io subdevices */
+	for (i = 0; i < 2; i++) {
+		s = &dev->subdevices[1 + i];
+		ret = subdev_8255_init(dev, s, NULL, iobase_8255 + (i * 4));
+		if (ret)
+			return ret;
 	}
 
+	/* Read the caldac eeprom data */
+	for (i = 0; i < EEPROM_SIZE; i++)
+		devpriv->eeprom_data[i] = cb_pcidda_read_eeprom(dev, i);
+
 	/*  set calibrations dacs */
-	for (index = 0; index < thisboard->ao_chans; index++)
-		cb_pcidda_calibrate(dev, index, devpriv->ao_range[index]);
+	for (i = 0; i < thisboard->ao_chans; i++)
+		cb_pcidda_calibrate(dev, i, devpriv->ao_range[i]);
 
 	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
 
@@ -739,28 +428,28 @@ static void cb_pcidda_detach(struct comedi_device *dev)
 static struct comedi_driver cb_pcidda_driver = {
 	.driver_name	= "cb_pcidda",
 	.module		= THIS_MODULE,
-	.attach_pci	= cb_pcidda_attach_pci,
+	.auto_attach	= cb_pcidda_auto_attach,
 	.detach		= cb_pcidda_detach,
 };
 
-static int __devinit cb_pcidda_pci_probe(struct pci_dev *dev,
+static int cb_pcidda_pci_probe(struct pci_dev *dev,
 					 const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &cb_pcidda_driver);
 }
 
-static void __devexit cb_pcidda_pci_remove(struct pci_dev *dev)
+static void cb_pcidda_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(cb_pcidda_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0020) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0021) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0022) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0023) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0024) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0025) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA02_12) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA04_12) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA08_12) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA02_16) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA04_16) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_DDA08_16) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table);
@@ -769,7 +458,7 @@ static struct pci_driver cb_pcidda_pci_driver = {
 	.name		= "cb_pcidda",
 	.id_table	= cb_pcidda_pci_table,
 	.probe		= cb_pcidda_pci_probe,
-	.remove		= __devexit_p(cb_pcidda_pci_remove),
+	.remove		= cb_pcidda_pci_remove,
 };
 module_comedi_pci_driver(cb_pcidda_driver, cb_pcidda_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
index 9515b69..b43a5f8 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
@@ -51,8 +51,6 @@ See http://www.mccdaq.com/PDFs/Manuals/pcim-das1602-16.pdf for more details.
 /* #define CBPCIMDAS_DEBUG */
 #undef CBPCIMDAS_DEBUG
 
-#define PCI_VENDOR_ID_COMPUTERBOARDS	0x1307
-
 /* Registers for the PCIM-DAS1602/16 */
 
 /* sizes of io regions (bytes) */
@@ -80,44 +78,6 @@ See http://www.mccdaq.com/PDFs/Manuals/pcim-das1602-16.pdf for more details.
 #define RESID_COUNT_H 13
 #define RESID_COUNT_L 14
 
-/* Board description */
-struct cb_pcimdas_board {
-	const char *name;
-	unsigned short device_id;
-	int ai_se_chans;	/*  Inputs in single-ended mode */
-	int ai_diff_chans;	/*  Inputs in differential mode */
-	int ai_bits;		/*  analog input resolution */
-	int ai_speed;		/*  fastest conversion period in ns */
-	int ao_nchan;		/*  number of analog out channels */
-	int ao_bits;		/*  analogue output resolution */
-	int has_ao_fifo;	/*  analog output has fifo */
-	int ao_scan_speed;	/*  analog output speed for 1602 series (for a scan, not conversion) */
-	int fifo_size;		/*  number of samples fifo can hold */
-	int dio_bits;		/*  number of dio bits */
-	int has_dio;		/*  has DIO */
-	const struct comedi_lrange *ranges;
-};
-
-static const struct cb_pcimdas_board cb_pcimdas_boards[] = {
-	{
-	 .name = "PCIM-DAS1602/16",
-	 .device_id = 0x56,
-	 .ai_se_chans = 16,
-	 .ai_diff_chans = 8,
-	 .ai_bits = 16,
-	 .ai_speed = 10000,	/* ?? */
-	 .ao_nchan = 2,
-	 .ao_bits = 12,
-	 .has_ao_fifo = 0,	/* ?? */
-	 .ao_scan_speed = 10000,
-	 /* ?? */
-	 .fifo_size = 1024,
-	 .dio_bits = 24,
-	 .has_dio = 1,
-/*	.ranges = &cb_pcimdas_ranges, */
-	 },
-};
-
 /*
  * this structure is for data unique to this hardware driver.  If
  * several hardware drivers keep similar information in this structure,
@@ -140,7 +100,6 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
-	const struct cb_pcimdas_board *thisboard = comedi_board(dev);
 	struct cb_pcimdas_private *devpriv = dev->private;
 	int n, i;
 	unsigned int d;
@@ -153,9 +112,9 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
 
 	/* check channel number */
 	if ((inb(devpriv->BADR3 + 2) & 0x20) == 0)	/* differential mode */
-		maxchans = thisboard->ai_diff_chans;
+		maxchans = s->n_chan / 2;
 	else
-		maxchans = thisboard->ai_se_chans;
+		maxchans = s->n_chan;
 
 	if (chan > (maxchans - 1))
 		return -ETIMEDOUT;	/* *** Wrong error code. Fixme. */
@@ -195,12 +154,7 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
 			return -ETIMEDOUT;
 		}
 		/* read data */
-		d = inw(dev->iobase + 0);
-
-		/* mangle the data as necessary */
-		/* d ^= 1<<(thisboard->ai_bits-1); // 16 bit data from ADC, so no mangle needed. */
-
-		data[n] = d;
+		data[n] = inw(dev->iobase + 0);
 	}
 
 	/* return the number of samples read/written */
@@ -251,51 +205,21 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device *dev,
 	return i;
 }
 
-static const void *cb_pcimdas_find_boardinfo(struct comedi_device *dev,
-					     struct pci_dev *pcidev)
+static int cb_pcimdas_auto_attach(struct comedi_device *dev,
+					    unsigned long context_unused)
 {
-	const struct cb_pcimdas_board *thisboard;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(cb_pcimdas_boards); i++) {
-		thisboard = &cb_pcimdas_boards[i];
-		if (thisboard->device_id == pcidev->device)
-			return thisboard;
-	}
-	return NULL;
-}
-
-static int cb_pcimdas_attach_pci(struct comedi_device *dev,
-				 struct pci_dev *pcidev)
-{
-	const struct cb_pcimdas_board *thisboard;
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct cb_pcimdas_private *devpriv;
 	struct comedi_subdevice *s;
 	unsigned long iobase_8255;
 	int ret;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
+	dev->board_name = dev->driver->driver_name;
 
-	thisboard = cb_pcimdas_find_boardinfo(dev, pcidev);
-	if (!thisboard)
-		return -ENODEV;
-	dev->board_ptr = thisboard;
-	dev->board_name = thisboard->name;
-
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret)
-		return ret;
-	devpriv = dev->private;
-
-	/*  Warn about non-tested features */
-	switch (thisboard->device_id) {
-	case 0x56:
-		break;
-	default:
-		dev_dbg(dev->class_dev, "THIS CARD IS UNSUPPORTED.\n");
-		dev_dbg(dev->class_dev,
-			"PLEASE REPORT USAGE TO <mocelet@sucs.org>\n");
-	}
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_pci_enable(pcidev, dev->board_name);
 	if (ret)
@@ -323,8 +247,8 @@ static int cb_pcimdas_attach_pci(struct comedi_device *dev,
 	/*  analog input subdevice */
 	s->type = COMEDI_SUBD_AI;
 	s->subdev_flags = SDF_READABLE | SDF_GROUND;
-	s->n_chan = thisboard->ai_se_chans;
-	s->maxdata = (1 << thisboard->ai_bits) - 1;
+	s->n_chan = 16;
+	s->maxdata = 0xffff;
 	s->range_table = &range_unknown;
 	s->len_chanlist = 1;	/*  This is the maximum chanlist length that */
 	/*  the board can handle */
@@ -334,8 +258,8 @@ static int cb_pcimdas_attach_pci(struct comedi_device *dev,
 	/*  analog output subdevice */
 	s->type = COMEDI_SUBD_AO;
 	s->subdev_flags = SDF_WRITABLE;
-	s->n_chan = thisboard->ao_nchan;
-	s->maxdata = 1 << thisboard->ao_bits;
+	s->n_chan = 2;
+	s->maxdata = 0xfff;
 	/* ranges are hardware settable, but not software readable. */
 	s->range_table = &range_unknown;
 	s->insn_write = &cb_pcimdas_ao_winsn;
@@ -343,10 +267,7 @@ static int cb_pcimdas_attach_pci(struct comedi_device *dev,
 
 	s = &dev->subdevices[2];
 	/* digital i/o subdevice */
-	if (thisboard->has_dio)
-		subdev_8255_init(dev, s, NULL, iobase_8255);
-	else
-		s->type = COMEDI_SUBD_UNUSED;
+	subdev_8255_init(dev, s, NULL, iobase_8255);
 
 	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
 
@@ -368,23 +289,23 @@ static void cb_pcimdas_detach(struct comedi_device *dev)
 static struct comedi_driver cb_pcimdas_driver = {
 	.driver_name	= "cb_pcimdas",
 	.module		= THIS_MODULE,
-	.attach_pci	= cb_pcimdas_attach_pci,
+	.auto_attach	= cb_pcimdas_auto_attach,
 	.detach		= cb_pcimdas_detach,
 };
 
-static int __devinit cb_pcimdas_pci_probe(struct pci_dev *dev,
+static int cb_pcimdas_pci_probe(struct pci_dev *dev,
 					  const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &cb_pcimdas_driver);
 }
 
-static void __devexit cb_pcimdas_pci_remove(struct pci_dev *dev)
+static void cb_pcimdas_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(cb_pcimdas_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, 0x0056) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0056) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, cb_pcimdas_pci_table);
@@ -393,7 +314,7 @@ static struct pci_driver cb_pcimdas_pci_driver = {
 	.name		= "cb_pcimdas",
 	.id_table	= cb_pcimdas_pci_table,
 	.probe		= cb_pcimdas_pci_probe,
-	.remove		= __devexit_p(cb_pcimdas_pci_remove),
+	.remove		= cb_pcimdas_pci_remove,
 };
 module_comedi_pci_driver(cb_pcimdas_driver, cb_pcimdas_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
index ba9f059..699b84f 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
@@ -84,7 +84,6 @@ Configuration Options: not applicable, uses PCI auto config
 #include "8255.h"
 
 /* device ids of the cards we support -- currently only 1 card supported */
-#define PCI_VENDOR_ID_COMPUTERBOARDS	0x1307
 #define PCI_ID_PCIM_DDA06_16		0x0053
 
 /*
@@ -152,20 +151,20 @@ static int cb_pcimdda_ao_rinsn(struct comedi_device *dev,
 	return insn->n;
 }
 
-static int cb_pcimdda_attach_pci(struct comedi_device *dev,
-				 struct pci_dev *pcidev)
+static int cb_pcimdda_auto_attach(struct comedi_device *dev,
+					    unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct cb_pcimdda_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
 	dev->board_name = dev->driver->driver_name;
 
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_pci_enable(pcidev, dev->board_name);
 	if (ret)
@@ -213,23 +212,23 @@ static void cb_pcimdda_detach(struct comedi_device *dev)
 static struct comedi_driver cb_pcimdda_driver = {
 	.driver_name	= "cb_pcimdda",
 	.module		= THIS_MODULE,
-	.attach_pci	= cb_pcimdda_attach_pci,
+	.auto_attach	= cb_pcimdda_auto_attach,
 	.detach		= cb_pcimdda_detach,
 };
 
-static int __devinit cb_pcimdda_pci_probe(struct pci_dev *dev,
+static int cb_pcimdda_pci_probe(struct pci_dev *dev,
 					  const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &cb_pcimdda_driver);
 }
 
-static void __devexit cb_pcimdda_pci_remove(struct pci_dev *dev)
+static void cb_pcimdda_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(cb_pcimdda_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, PCI_ID_PCIM_DDA06_16) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_ID_PCIM_DDA06_16) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, cb_pcimdda_pci_table);
@@ -238,7 +237,7 @@ static struct pci_driver cb_pcimdda_driver_pci_driver = {
 	.name		= "cb_pcimdda",
 	.id_table	= cb_pcimdda_pci_table,
 	.probe		= cb_pcimdda_pci_probe,
-	.remove		= __devexit_p(cb_pcimdda_pci_remove),
+	.remove		= cb_pcimdda_pci_remove,
 };
 module_comedi_pci_driver(cb_pcimdda_driver, cb_pcimdda_driver_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
index 5c768bc..3151599 100644
--- a/drivers/staging/comedi/drivers/comedi_bond.c
+++ b/drivers/staging/comedi/drivers/comedi_bond.c
@@ -304,10 +304,10 @@ static int bonding_attach(struct comedi_device *dev,
 	struct comedi_subdevice *s;
 	int ret;
 
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	/*
 	 * Setup our bonding from config params.. sets up our private struct..
diff --git a/drivers/staging/comedi/drivers/comedi_fc.c b/drivers/staging/comedi/drivers/comedi_fc.c
index 63be619..8372829 100644
--- a/drivers/staging/comedi/drivers/comedi_fc.c
+++ b/drivers/staging/comedi/drivers/comedi_fc.c
@@ -53,7 +53,7 @@ unsigned int cfc_write_array_to_buffer(struct comedi_subdevice *subd,
 
 	retval = comedi_buf_write_alloc(async, num_bytes);
 	if (retval != num_bytes) {
-		printk(KERN_WARNING "comedi: buffer overrun\n");
+		dev_warn(subd->device->class_dev, "comedi: buffer overrun\n");
 		async->events |= COMEDI_CB_OVERFLOW;
 		return 0;
 	}
diff --git a/drivers/staging/comedi/drivers/comedi_fc.h b/drivers/staging/comedi/drivers/comedi_fc.h
index 94481c6..31afab7 100644
--- a/drivers/staging/comedi/drivers/comedi_fc.h
+++ b/drivers/staging/comedi/drivers/comedi_fc.h
@@ -105,4 +105,48 @@ static inline int cfc_check_trigger_is_unique(unsigned int src)
 	return 0;
 }
 
+/**
+ * cfc_check_trigger_arg_is() - trivially validate a trigger argument
+ * @arg: pointer to the trigger arg to validate
+ * @val: the value the argument should be
+ */
+static inline int cfc_check_trigger_arg_is(unsigned int *arg, unsigned int val)
+{
+	if (*arg != val) {
+		*arg = val;
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/**
+ * cfc_check_trigger_arg_min() - trivially validate a trigger argument
+ * @arg: pointer to the trigger arg to validate
+ * @val: the minimum value the argument should be
+ */
+static inline int cfc_check_trigger_arg_min(unsigned int *arg,
+					    unsigned int val)
+{
+	if (*arg < val) {
+		*arg = val;
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/**
+ * cfc_check_trigger_arg_max() - trivially validate a trigger argument
+ * @arg: pointer to the trigger arg to validate
+ * @val: the maximum value the argument should be
+ */
+static inline int cfc_check_trigger_arg_max(unsigned int *arg,
+					    unsigned int val)
+{
+	if (*arg > val) {
+		*arg = val;
+		return -EINVAL;
+	}
+	return 0;
+}
+
 #endif /* _COMEDI_FC_H */
diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
index 22ef942..76d59dc 100644
--- a/drivers/staging/comedi/drivers/comedi_parport.c
+++ b/drivers/staging/comedi/drivers/comedi_parport.c
@@ -196,28 +196,13 @@ static int parport_intr_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
-	if (cmd->scan_begin_arg != 0) {
-		cmd->scan_begin_arg = 0;
-		err++;
-	}
-	if (cmd->convert_arg != 0) {
-		cmd->convert_arg = 0;
-		err++;
-	}
-	if (cmd->scan_end_arg != 1) {
-		cmd->scan_end_arg = 1;
-		err++;
-	}
-	if (cmd->stop_arg != 0) {
-		cmd->stop_arg = 0;
-		err++;
-	}
+	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;
@@ -305,10 +290,10 @@ static int parport_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret < 0)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	s = &dev->subdevices[0];
 	s->type = COMEDI_SUBD_DIO;
diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
index 7817def..fb3d093 100644
--- a/drivers/staging/comedi/drivers/comedi_test.c
+++ b/drivers/staging/comedi/drivers/comedi_test.c
@@ -252,55 +252,28 @@ static int waveform_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
+
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+
+	if (cmd->convert_src == TRIG_NOW)
+		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
-	if (cmd->convert_src == TRIG_NOW) {
-		if (cmd->convert_arg != 0) {
-			cmd->convert_arg = 0;
-			err++;
-		}
-	}
 	if (cmd->scan_begin_src == TRIG_TIMER) {
-		if (cmd->scan_begin_arg < nano_per_micro) {
-			cmd->scan_begin_arg = nano_per_micro;
-			err++;
-		}
-		if (cmd->convert_src == TRIG_TIMER &&
-		    cmd->scan_begin_arg <
-		    cmd->convert_arg * cmd->chanlist_len) {
-			cmd->scan_begin_arg =
-			    cmd->convert_arg * cmd->chanlist_len;
-			err++;
-		}
-	}
-	/*
-	 * XXX these checks are generic and should go in core if not there
-	 * already
-	 */
-	if (!cmd->chanlist_len) {
-		cmd->chanlist_len = 1;
-		err++;
-	}
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						 nano_per_micro);
+		if (cmd->convert_src == TRIG_TIMER)
+			err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+					cmd->convert_arg * cmd->chanlist_len);
 	}
 
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (!cmd->stop_arg) {
-			cmd->stop_arg = 1;
-			err++;
-		}
-	} else {		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+	if (cmd->stop_src == TRIG_COUNT)
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+	else	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -414,10 +387,10 @@ static int waveform_attach(struct comedi_device *dev,
 
 	dev->board_name = dev->driver->driver_name;
 
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret < 0)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	/* set default amplitude and period */
 	if (amplitude <= 0)
diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
index 178a6a4..1a18fa3 100644
--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
+++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
@@ -68,14 +68,13 @@ static int contec_di_insn_bits(struct comedi_device *dev,
 	return insn->n;
 }
 
-static int contec_attach_pci(struct comedi_device *dev,
-			     struct pci_dev *pcidev)
+static int contec_auto_attach(struct comedi_device *dev,
+					unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct comedi_subdevice *s;
 	int ret;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
-
 	dev->board_name = dev->driver->driver_name;
 
 	ret = comedi_pci_enable(pcidev, dev->board_name);
@@ -121,17 +120,17 @@ static void contec_detach(struct comedi_device *dev)
 static struct comedi_driver contec_pci_dio_driver = {
 	.driver_name	= "contec_pci_dio",
 	.module		= THIS_MODULE,
-	.attach_pci	= contec_attach_pci,
+	.auto_attach	= contec_auto_attach,
 	.detach		= contec_detach,
 };
 
-static int __devinit contec_pci_dio_pci_probe(struct pci_dev *dev,
+static int contec_pci_dio_pci_probe(struct pci_dev *dev,
 					      const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &contec_pci_dio_driver);
 }
 
-static void __devexit contec_pci_dio_pci_remove(struct pci_dev *dev)
+static void contec_pci_dio_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -146,7 +145,7 @@ static struct pci_driver contec_pci_dio_pci_driver = {
 	.name		= "contec_pci_dio",
 	.id_table	= contec_pci_dio_pci_table,
 	.probe		= contec_pci_dio_pci_probe,
-	.remove		= __devexit_p(contec_pci_dio_pci_remove),
+	.remove		= contec_pci_dio_pci_remove,
 };
 module_comedi_pci_driver(contec_pci_dio_driver, contec_pci_dio_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
index d13c8c5..992e557 100644
--- a/drivers/staging/comedi/drivers/daqboard2000.c
+++ b/drivers/staging/comedi/drivers/daqboard2000.c
@@ -117,8 +117,6 @@ Configuration options: not applicable, uses PCI auto config
 
 #define DAQBOARD2000_FIRMWARE		"daqboard2000_firmware.bin"
 
-#define PCI_VENDOR_ID_IOTECH		0x1616
-
 #define DAQBOARD2000_SUBSYSTEM_IDS2 	0x0002	/* Daqboard/2000 - 2 Dacs */
 #define DAQBOARD2000_SUBSYSTEM_IDS4 	0x0004	/* Daqboard/2000 - 4 Dacs */
 
@@ -690,26 +688,25 @@ static const void *daqboard2000_find_boardinfo(struct comedi_device *dev,
 	return NULL;
 }
 
-static int daqboard2000_attach_pci(struct comedi_device *dev,
-				   struct pci_dev *pcidev)
+static int daqboard2000_auto_attach(struct comedi_device *dev,
+					      unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	const struct daq200_boardtype *board;
 	struct daqboard2000_private *devpriv;
 	struct comedi_subdevice *s;
 	int result;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
-
 	board = daqboard2000_find_boardinfo(dev, pcidev);
 	if (!board)
 		return -ENODEV;
 	dev->board_ptr = board;
 	dev->board_name = board->name;
 
-	result = alloc_private(dev, sizeof(*devpriv));
-	if (result < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
-	devpriv = dev->private;
+	dev->private = devpriv;
 
 	result = comedi_pci_enable(pcidev, dev->driver->driver_name);
 	if (result < 0)
@@ -792,17 +789,17 @@ static void daqboard2000_detach(struct comedi_device *dev)
 static struct comedi_driver daqboard2000_driver = {
 	.driver_name	= "daqboard2000",
 	.module		= THIS_MODULE,
-	.attach_pci	= daqboard2000_attach_pci,
+	.auto_attach	= daqboard2000_auto_attach,
 	.detach		= daqboard2000_detach,
 };
 
-static int __devinit daqboard2000_pci_probe(struct pci_dev *dev,
+static int daqboard2000_pci_probe(struct pci_dev *dev,
 					    const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &daqboard2000_driver);
 }
 
-static void __devexit daqboard2000_pci_remove(struct pci_dev *dev)
+static void daqboard2000_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -817,7 +814,7 @@ static struct pci_driver daqboard2000_pci_driver = {
 	.name		= "daqboard2000",
 	.id_table	= daqboard2000_pci_table,
 	.probe		= daqboard2000_pci_probe,
-	.remove		= __devexit_p(daqboard2000_pci_remove),
+	.remove		= daqboard2000_pci_remove,
 };
 module_comedi_pci_driver(daqboard2000_driver, daqboard2000_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
index c304528..b15e058 100644
--- a/drivers/staging/comedi/drivers/das08.c
+++ b/drivers/staging/comedi/drivers/das08.c
@@ -65,7 +65,6 @@
 #define DO_PCI IS_ENABLED(CONFIG_COMEDI_DAS08_PCI)
 #define DO_COMEDI_DRIVER_REGISTER (DO_ISA || DO_PCI)
 
-#define PCI_VENDOR_ID_COMPUTERBOARDS 0x1307
 #define PCI_DEVICE_ID_PCIDAS08 0x29
 #define PCIDAS08_SIZE 0x54
 
@@ -775,24 +774,29 @@ das08_find_pci_board(struct pci_dev *pdev)
 }
 
 /* only called in the PCI probe path, via comedi_pci_auto_config() */
-static int __devinit __maybe_unused
-das08_attach_pci(struct comedi_device *dev, struct pci_dev *pdev)
+static int __maybe_unused
+das08_auto_attach(struct comedi_device *dev, unsigned long context_unused)
 {
+	struct pci_dev *pdev;
+	struct das08_private_struct *devpriv;
 	unsigned long iobase;
-	int ret;
 
 	if (!DO_PCI)
 		return -EINVAL;
-	ret = alloc_private(dev, sizeof(struct das08_private_struct));
-	if (ret < 0)
-		return ret;
+
+	pdev = comedi_to_pci_dev(dev);
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
 	dev_info(dev->class_dev, "attach pci %s\n", pci_name(pdev));
 	dev->board_ptr = das08_find_pci_board(pdev);
 	if (dev->board_ptr == NULL) {
 		dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
 		return -EINVAL;
 	}
-	comedi_set_hw_dev(dev, &pdev->dev);
+
 	/*  enable PCI device and reserve I/O spaces */
 	if (comedi_pci_enable(pdev, dev->driver->driver_name)) {
 		dev_err(dev->class_dev,
@@ -809,13 +813,12 @@ das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct das08_board_struct *thisboard = comedi_board(dev);
 	struct das08_private_struct *devpriv;
-	int ret;
 	unsigned long iobase;
 
-	ret = alloc_private(dev, sizeof(struct das08_private_struct));
-	if (ret < 0)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	dev_info(dev->class_dev, "attach\n");
 	if (is_pci_board(thisboard)) {
@@ -866,7 +869,7 @@ static struct comedi_driver das08_driver = {
 	.driver_name = DRV_NAME,
 	.module = THIS_MODULE,
 	.attach = das08_attach,
-	.attach_pci = das08_attach_pci,
+	.auto_attach = das08_auto_attach,
 	.detach = das08_detach,
 	.board_name = &das08_boards[0].name,
 	.num_names = sizeof(das08_boards) / sizeof(struct das08_board_struct),
@@ -876,19 +879,19 @@ static struct comedi_driver das08_driver = {
 
 #if DO_PCI
 static DEFINE_PCI_DEVICE_TABLE(das08_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, PCI_DEVICE_ID_PCIDAS08) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CB, PCI_DEVICE_ID_PCIDAS08) },
 	{0}
 };
 
 MODULE_DEVICE_TABLE(pci, das08_pci_table);
 
-static int __devinit das08_pci_probe(struct pci_dev *dev,
+static int das08_pci_probe(struct pci_dev *dev,
 					    const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &das08_driver);
 }
 
-static void __devexit das08_pci_remove(struct pci_dev *dev)
+static void das08_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -897,7 +900,7 @@ static struct pci_driver das08_pci_driver = {
 	.id_table = das08_pci_table,
 	.name =  DRV_NAME,
 	.probe = &das08_pci_probe,
-	.remove = __devexit_p(&das08_pci_remove)
+	.remove = &das08_pci_remove
 };
 #endif /* DO_PCI */
 
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index e4c91e6..0242623 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -90,13 +90,14 @@ static int das08_cs_attach(struct comedi_device *dev,
 			   struct comedi_devconfig *it)
 {
 	const struct das08_board_struct *thisboard = comedi_board(dev);
-	int ret;
+	struct das08_private_struct *devpriv;
 	unsigned long iobase;
 	struct pcmcia_device *link = cur_dev;	/*  XXX hack */
 
-	ret = alloc_private(dev, sizeof(struct das08_private_struct));
-	if (ret < 0)
-		return ret;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	dev_info(dev->class_dev, "das08_cs: attach\n");
 	/*  deal with a pci board */
diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
index fcb8a32..b159f44 100644
--- a/drivers/staging/comedi/drivers/das16.c
+++ b/drivers/staging/comedi/drivers/das16.c
@@ -392,12 +392,12 @@ struct das16_private_struct {
 	volatile short timer_running;
 	volatile short timer_mode;	/*  true if using timer mode */
 };
-#define devpriv ((struct das16_private_struct *)(dev->private))
 
 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 			  struct comedi_cmd *cmd)
 {
 	const struct das16_board *board = comedi_board(dev);
+	struct das16_private_struct *devpriv = dev->private;
 	int err = 0, tmp;
 	int gain, start_chan, i;
 	int mask;
@@ -442,46 +442,27 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->scan_begin_src == TRIG_FOLLOW) {
-		/* internal trigger */
-		if (cmd->scan_begin_arg != 0) {
-			cmd->scan_begin_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	/*  check against maximum frequency */
-	if (cmd->scan_begin_src == TRIG_TIMER) {
-		if (cmd->scan_begin_arg <
-		    board->ai_speed * cmd->chanlist_len) {
-			cmd->scan_begin_arg =
-			    board->ai_speed * cmd->chanlist_len;
-			err++;
-		}
-	}
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < board->ai_speed) {
-			cmd->convert_arg = board->ai_speed;
-			err++;
-		}
-	}
+	if (cmd->scan_begin_src == TRIG_FOLLOW)	/* internal trigger */
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+	/* check against maximum frequency */
+	if (cmd->scan_begin_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+					board->ai_speed * cmd->chanlist_len);
+
+	if (cmd->convert_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+						 board->ai_speed);
+
+	if (cmd->stop_src == TRIG_NONE)
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
-	if (cmd->stop_src == TRIG_NONE) {
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
 	if (err)
 		return 3;
 
@@ -540,6 +521,7 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
 						const struct comedi_cmd *cmd)
 {
+	struct das16_private_struct *devpriv = dev->private;
 	unsigned int size;
 	unsigned int freq;
 
@@ -581,6 +563,8 @@ static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
 				    int rounding_flags)
 {
+	struct das16_private_struct *devpriv = dev->private;
+
 	i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
 				       &(devpriv->divisor2), &ns,
 				       rounding_flags & TRIG_ROUND_MASK);
@@ -595,6 +579,7 @@ static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	const struct das16_board *board = comedi_board(dev);
+	struct das16_private_struct *devpriv = dev->private;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
 	unsigned int byte;
@@ -701,6 +686,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	const struct das16_board *board = comedi_board(dev);
+	struct das16_private_struct *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev->spinlock, flags);
@@ -738,6 +724,7 @@ static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			  struct comedi_insn *insn, unsigned int *data)
 {
 	const struct das16_board *board = comedi_board(dev);
+	struct das16_private_struct *devpriv = dev->private;
 	int i, n;
 	int range;
 	int chan;
@@ -848,10 +835,12 @@ static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 */
 static int disable_dma_on_even(struct comedi_device *dev)
 {
+	struct das16_private_struct *devpriv = dev->private;
 	int residue;
 	int i;
 	static const int disable_limit = 100;
 	static const int enable_timeout = 100;
+
 	disable_dma(devpriv->dma_chan);
 	residue = get_dma_residue(devpriv->dma_chan);
 	for (i = 0; i < disable_limit && (residue % 2); ++i) {
@@ -877,6 +866,7 @@ static int disable_dma_on_even(struct comedi_device *dev)
 static void das16_interrupt(struct comedi_device *dev)
 {
 	const struct das16_board *board = comedi_board(dev);
+	struct das16_private_struct *devpriv = dev->private;
 	unsigned long dma_flags, spin_flags;
 	struct comedi_subdevice *s = dev->read_subdev;
 	struct comedi_async *async;
@@ -973,6 +963,7 @@ static irqreturn_t das16_dma_interrupt(int irq, void *d)
 static void das16_timer_interrupt(unsigned long arg)
 {
 	struct comedi_device *dev = (struct comedi_device *)arg;
+	struct das16_private_struct *devpriv = dev->private;
 
 	das16_interrupt(dev);
 
@@ -1001,6 +992,7 @@ static void reg_dump(struct comedi_device *dev)
 static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct das16_board *board = comedi_board(dev);
+	struct das16_private_struct *devpriv = dev->private;
 	int status;
 	int diobits;
 
@@ -1035,6 +1027,7 @@ static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
 
 static int das1600_mode_detect(struct comedi_device *dev)
 {
+	struct das16_private_struct *devpriv = dev->private;
 	int status = 0;
 
 	status = inb(dev->iobase + DAS1600_STATUS_B);
@@ -1080,6 +1073,7 @@ static void das16_ai_munge(struct comedi_device *dev,
 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct das16_board *board = comedi_board(dev);
+	struct das16_private_struct *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 	unsigned int irq;
@@ -1114,9 +1108,10 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		}
 	}
 
-	ret = alloc_private(dev, sizeof(struct das16_private_struct));
-	if (ret < 0)
-		return ret;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	if (board->size < 0x400) {
 		printk(" 0x%04lx-0x%04lx\n", iobase, iobase + board->size);
@@ -1353,6 +1348,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 static void das16_detach(struct comedi_device *dev)
 {
 	const struct das16_board *board = comedi_board(dev);
+	struct das16_private_struct *devpriv = dev->private;
 
 	das16_reset(dev);
 	if (dev->subdevices)
diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
index 3f87d75..b0a861a 100644
--- a/drivers/staging/comedi/drivers/das16m1.c
+++ b/drivers/staging/comedi/drivers/das16m1.c
@@ -28,7 +28,7 @@
 Driver: das16m1
 Description: CIO-DAS16/M1
 Author: Frank Mori Hess <fmhess@users.sourceforge.net>
-Devices: [Measurement Computing] CIO-DAS16/M1 (cio-das16/m1)
+Devices: [Measurement Computing] CIO-DAS16/M1 (das16m1)
 Status: works
 
 This driver supports a single board - the CIO-DAS16/M1.
@@ -132,11 +132,6 @@ static const struct comedi_lrange range_das16m1 = { 9,
 	 }
 };
 
-struct das16m1_board {
-	const char *name;
-	unsigned int ai_speed;
-};
-
 struct das16m1_private_struct {
 	unsigned int control_state;
 	volatile unsigned int adc_count;	/*  number of samples completed */
@@ -149,7 +144,6 @@ struct das16m1_private_struct {
 	unsigned int divisor1;	/*  divides master clock to obtain conversion speed */
 	unsigned int divisor2;	/*  divides master clock to obtain conversion speed */
 };
-#define devpriv ((struct das16m1_private_struct *)(dev->private))
 
 static inline short munge_sample(short data)
 {
@@ -167,7 +161,7 @@ static void munge_sample_array(short *array, unsigned int num_elements)
 static int das16m1_cmd_test(struct comedi_device *dev,
 			    struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
-	const struct das16m1_board *board = comedi_board(dev);
+	struct das16m1_private_struct *devpriv = dev->private;
 	unsigned int err = 0, tmp, i;
 
 	/* Step 1 : check if triggers are trivially valid */
@@ -192,40 +186,23 @@ static int das16m1_cmd_test(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->scan_begin_src == TRIG_FOLLOW) {
-		/* internal trigger */
-		if (cmd->scan_begin_arg != 0) {
-			cmd->scan_begin_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < board->ai_speed) {
-			cmd->convert_arg = board->ai_speed;
-			err++;
-		}
-	}
+	if (cmd->scan_begin_src == TRIG_FOLLOW)	/* internal trigger */
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	if (cmd->convert_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 1000);
+
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 
 	if (cmd->stop_src == TRIG_COUNT) {
 		/* any count is allowed */
 	} else {
 		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 	}
 
 	if (err)
@@ -277,6 +254,8 @@ static int das16m1_cmd_test(struct comedi_device *dev,
 static unsigned int das16m1_set_pacer(struct comedi_device *dev,
 				      unsigned int ns, int rounding_flags)
 {
+	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);
@@ -293,6 +272,7 @@ static unsigned int das16m1_set_pacer(struct comedi_device *dev,
 static int das16m1_cmd_exec(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
+	struct das16m1_private_struct *devpriv = dev->private;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
 	unsigned int byte, i;
@@ -356,6 +336,8 @@ static int das16m1_cmd_exec(struct comedi_device *dev,
 
 static int das16m1_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct das16m1_private_struct *devpriv = dev->private;
+
 	devpriv->control_state &= ~INTE & ~PACER_MASK;
 	outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL);
 
@@ -366,6 +348,7 @@ static int das16m1_ai_rinsn(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data)
 {
+	struct das16m1_private_struct *devpriv = dev->private;
 	int i, n;
 	int byte;
 	const int timeout = 1000;
@@ -417,6 +400,7 @@ static int das16m1_do_wbits(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data)
 {
+	struct das16m1_private_struct *devpriv = dev->private;
 	unsigned int wbits;
 
 	/*  only set bits that have been masked */
@@ -436,6 +420,7 @@ static int das16m1_do_wbits(struct comedi_device *dev,
 
 static void das16m1_handler(struct comedi_device *dev, unsigned int status)
 {
+	struct das16m1_private_struct *devpriv = dev->private;
 	struct comedi_subdevice *s;
 	struct comedi_async *async;
 	struct comedi_cmd *cmd;
@@ -582,26 +567,27 @@ static int das16m1_irq_bits(unsigned int irq)
 static int das16m1_attach(struct comedi_device *dev,
 			  struct comedi_devconfig *it)
 {
-	const struct das16m1_board *board = comedi_board(dev);
+	struct das16m1_private_struct *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 	unsigned int irq;
 	unsigned long iobase;
 
-	iobase = it->options[0];
+	dev->board_name = dev->driver->driver_name;
 
-	ret = alloc_private(dev, sizeof(struct das16m1_private_struct));
-	if (ret < 0)
-		return ret;
+	iobase = it->options[0];
 
-	dev->board_name = board->name;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
-	if (!request_region(iobase, DAS16M1_SIZE, dev->driver->driver_name)) {
+	if (!request_region(iobase, DAS16M1_SIZE, dev->board_name)) {
 		comedi_error(dev, "I/O port conflict\n");
 		return -EIO;
 	}
 	if (!request_region(iobase + DAS16M1_82C55, DAS16M1_SIZE2,
-			    dev->driver->driver_name)) {
+			    dev->board_name)) {
 		release_region(iobase, DAS16M1_SIZE);
 		comedi_error(dev, "I/O port conflict\n");
 		return -EIO;
@@ -698,21 +684,11 @@ static void das16m1_detach(struct comedi_device *dev)
 	}
 }
 
-static const struct das16m1_board das16m1_boards[] = {
-	{
-		.name		= "cio-das16/m1",	/*  CIO-DAS16_M1.pdf */
-		.ai_speed	= 1000,			/*  1MHz max speed */
-	},
-};
-
 static struct comedi_driver das16m1_driver = {
 	.driver_name	= "das16m1",
 	.module		= THIS_MODULE,
 	.attach		= das16m1_attach,
 	.detach		= das16m1_detach,
-	.board_name	= &das16m1_boards[0].name,
-	.num_names	= ARRAY_SIZE(das16m1_boards),
-	.offset		= sizeof(das16m1_boards[0]),
 };
 module_comedi_driver(das16m1_driver);
 
diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
index 2555f32..7900f95 100644
--- a/drivers/staging/comedi/drivers/das1800.c
+++ b/drivers/staging/comedi/drivers/das1800.c
@@ -454,8 +454,6 @@ struct das1800_private {
 	short ao_update_bits;	/* remembers the last write to the 'update' dac */
 };
 
-#define devpriv ((struct das1800_private *)dev->private)
-
 /* analog out range for boards with basic analog out */
 static const struct comedi_lrange range_ao_1 = {
 	1,
@@ -501,6 +499,7 @@ static void munge_data(struct comedi_device *dev, uint16_t * array,
 static void das1800_handle_fifo_half_full(struct comedi_device *dev,
 					  struct comedi_subdevice *s)
 {
+	struct das1800_private *devpriv = dev->private;
 	int numPoints = 0;	/* number of points to read */
 	struct comedi_cmd *cmd = &s->async->cmd;
 
@@ -520,6 +519,7 @@ static void das1800_handle_fifo_half_full(struct comedi_device *dev,
 static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
 					  struct comedi_subdevice *s)
 {
+	struct das1800_private *devpriv = dev->private;
 	short dpnt;
 	int unipolar;
 	struct comedi_cmd *cmd = &s->async->cmd;
@@ -548,6 +548,7 @@ static void das1800_flush_dma_channel(struct comedi_device *dev,
 				      struct comedi_subdevice *s,
 				      unsigned int channel, uint16_t *buffer)
 {
+	struct das1800_private *devpriv = dev->private;
 	unsigned int num_bytes, num_samples;
 	struct comedi_cmd *cmd = &s->async->cmd;
 
@@ -578,6 +579,7 @@ static void das1800_flush_dma_channel(struct comedi_device *dev,
 static void das1800_flush_dma(struct comedi_device *dev,
 			      struct comedi_subdevice *s)
 {
+	struct das1800_private *devpriv = dev->private;
 	unsigned long flags;
 	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
 
@@ -609,6 +611,7 @@ static void das1800_flush_dma(struct comedi_device *dev,
 static void das1800_handle_dma(struct comedi_device *dev,
 			       struct comedi_subdevice *s, unsigned int status)
 {
+	struct das1800_private *devpriv = dev->private;
 	unsigned long flags;
 	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
 
@@ -643,6 +646,8 @@ static void das1800_handle_dma(struct comedi_device *dev,
 
 static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct das1800_private *devpriv = dev->private;
+
 	outb(0x0, dev->iobase + DAS1800_STATUS);	/* disable conversions */
 	outb(0x0, dev->iobase + DAS1800_CONTROL_B);	/* disable interrupts and dma */
 	outb(0x0, dev->iobase + DAS1800_CONTROL_A);	/* disable and clear fifo and stop triggering */
@@ -656,6 +661,7 @@ static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 /* the guts of the interrupt handler, that is shared with das1800_ai_poll */
 static void das1800_ai_handler(struct comedi_device *dev)
 {
+	struct das1800_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[0];
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
@@ -783,6 +789,7 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
 				 struct comedi_cmd *cmd)
 {
+	struct das1800_private *devpriv = dev->private;
 	int err = 0;
 	unsigned int tmp_arg;
 	int i;
@@ -817,39 +824,23 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < thisboard->ai_speed) {
-			cmd->convert_arg = thisboard->ai_speed;
-			err++;
-		}
-	}
-	if (!cmd->chanlist_len) {
-		cmd->chanlist_len = 1;
-		err++;
-	}
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+
+	if (cmd->convert_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+						 thisboard->ai_speed);
+
+	err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 
 	switch (cmd->stop_src) {
 	case TRIG_COUNT:
-		if (!cmd->stop_arg) {
-			cmd->stop_arg = 1;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
 		break;
 	case TRIG_NONE:
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 		break;
 	default:
 		break;
@@ -1006,6 +997,7 @@ static int control_c_bits(const struct comedi_cmd *cmd)
 /* loads counters with divisor1, divisor2 from private structure */
 static int das1800_set_frequency(struct comedi_device *dev)
 {
+	struct das1800_private *devpriv = dev->private;
 	int err = 0;
 
 	/*  counter 1, mode 2 */
@@ -1026,6 +1018,7 @@ static int das1800_set_frequency(struct comedi_device *dev)
 static int setup_counters(struct comedi_device *dev,
 			  const struct comedi_cmd *cmd)
 {
+	struct das1800_private *devpriv = dev->private;
 	unsigned int period;
 
 	/*  setup cascaded counters for conversion/scan frequency */
@@ -1107,6 +1100,7 @@ static unsigned int suggest_transfer_size(const struct comedi_cmd *cmd)
 /* sets up dma */
 static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
 {
+	struct das1800_private *devpriv = dev->private;
 	unsigned long lock_flags;
 	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
 
@@ -1174,6 +1168,7 @@ static void program_chanlist(struct comedi_device *dev,
 static int das1800_ai_do_cmd(struct comedi_device *dev,
 			     struct comedi_subdevice *s)
 {
+	struct das1800_private *devpriv = dev->private;
 	int ret;
 	int control_a, control_c;
 	struct comedi_async *async = s->async;
@@ -1300,6 +1295,7 @@ static int das1800_ao_winsn(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data)
 {
+	struct das1800_private *devpriv = dev->private;
 	int chan = CR_CHAN(insn->chanspec);
 /* int range = CR_RANGE(insn->chanspec); */
 	int update_chan = thisboard->ao_n_chan - 1;
@@ -1342,6 +1338,7 @@ static int das1800_do_wbits(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data)
 {
+	struct das1800_private *devpriv = dev->private;
 	unsigned int wbits;
 
 	/*  only set bits that have been masked */
@@ -1361,6 +1358,7 @@ static int das1800_do_wbits(struct comedi_device *dev,
 static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0,
 			    unsigned int dma1)
 {
+	struct das1800_private *devpriv = dev->private;
 	unsigned long flags;
 
 	/*  need an irq to do dma */
@@ -1518,6 +1516,7 @@ static int das1800_probe(struct comedi_device *dev)
 static int das1800_attach(struct comedi_device *dev,
 			  struct comedi_devconfig *it)
 {
+	struct das1800_private *devpriv;
 	struct comedi_subdevice *s;
 	unsigned long iobase = it->options[0];
 	unsigned int irq = it->options[1];
@@ -1527,9 +1526,10 @@ static int das1800_attach(struct comedi_device *dev,
 	int board;
 	int retval;
 
-	/* allocate and initialize dev->private */
-	if (alloc_private(dev, sizeof(struct das1800_private)) < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
 
 	printk(KERN_DEBUG "comedi%d: %s: io 0x%lx", dev->minor,
 	       dev->driver->driver_name, iobase);
@@ -1699,11 +1699,13 @@ static int das1800_attach(struct comedi_device *dev,
 
 static void das1800_detach(struct comedi_device *dev)
 {
+	struct das1800_private *devpriv = dev->private;
+
 	if (dev->iobase)
 		release_region(dev->iobase, DAS1800_SIZE);
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if (dev->private) {
+	if (devpriv) {
 		if (devpriv->iobase2)
 			release_region(devpriv->iobase2, DAS1800_SIZE);
 		if (devpriv->dma0)
diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
index e134c46..2efddb8 100644
--- a/drivers/staging/comedi/drivers/das6402.c
+++ b/drivers/staging/comedi/drivers/das6402.c
@@ -104,7 +104,6 @@ struct das6402_private {
 
 	int das6402_ignoreirq;
 };
-#define devpriv ((struct das6402_private *)dev->private)
 
 static void das6402_ai_fifo_dregs(struct comedi_device *dev,
 				  struct comedi_subdevice *s)
@@ -152,6 +151,7 @@ static void das6402_setcounter(struct comedi_device *dev)
 static irqreturn_t intr_handler(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct das6402_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[0];
 
 	if (!dev->attached || devpriv->das6402_ignoreirq) {
@@ -196,6 +196,8 @@ static void das6402_ai_fifo_read(struct comedi_device *dev, short *data, int n)
 static int das6402_ai_cancel(struct comedi_device *dev,
 			     struct comedi_subdevice *s)
 {
+	struct das6402_private *devpriv = dev->private;
+
 	/*
 	 *  This function should reset the board from whatever condition it
 	 *  is in (i.e., acquiring data), to a non-active state.
@@ -217,6 +219,8 @@ static int das6402_ai_cancel(struct comedi_device *dev,
 static int das6402_ai_mode2(struct comedi_device *dev,
 			    struct comedi_subdevice *s, comedi_trig * it)
 {
+	struct das6402_private *devpriv = dev->private;
+
 	devpriv->das6402_ignoreirq = 1;
 	dev_dbg(dev->class_dev, "Starting acquisition\n");
 	outb_p(0x03, dev->iobase + 10);	/* enable external trigging */
@@ -236,6 +240,7 @@ static int das6402_ai_mode2(struct comedi_device *dev,
 
 static int board_init(struct comedi_device *dev)
 {
+	struct das6402_private *devpriv = dev->private;
 	BYTE b;
 
 	devpriv->das6402_ignoreirq = 1;
@@ -277,6 +282,7 @@ static int board_init(struct comedi_device *dev)
 static int das6402_attach(struct comedi_device *dev,
 			  struct comedi_devconfig *it)
 {
+	struct das6402_private *devpriv;
 	unsigned int irq;
 	unsigned long iobase;
 	int ret;
@@ -303,9 +309,11 @@ static int das6402_attach(struct comedi_device *dev,
 		return ret;
 
 	dev->irq = irq;
-	ret = alloc_private(dev, sizeof(struct das6402_private));
-	if (ret < 0)
-		return ret;
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_alloc_subdevices(dev, 1);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
index 215deac..38f625b 100644
--- a/drivers/staging/comedi/drivers/das800.c
+++ b/drivers/staging/comedi/drivers/das800.c
@@ -241,8 +241,6 @@ struct das800_private {
 	volatile int do_bits;	/* digital output bits */
 };
 
-#define devpriv ((struct das800_private *)dev->private)
-
 static int das800_attach(struct comedi_device *dev,
 			 struct comedi_devconfig *it);
 static void das800_detach(struct comedi_device *dev);
@@ -344,22 +342,7 @@ static int das800_probe(struct comedi_device *dev)
 	return -1;
 }
 
-/*
- * A convenient macro that defines init_module() and cleanup_module(),
- * as necessary.
- */
-static int __init driver_das800_init_module(void)
-{
-	return comedi_driver_register(&driver_das800);
-}
-
-static void __exit driver_das800_cleanup_module(void)
-{
-	comedi_driver_unregister(&driver_das800);
-}
-
-module_init(driver_das800_init_module);
-module_exit(driver_das800_cleanup_module);
+module_comedi_driver(driver_das800);
 
 /* interrupt service routine */
 static irqreturn_t das800_interrupt(int irq, void *d)
@@ -367,6 +350,7 @@ static irqreturn_t das800_interrupt(int irq, void *d)
 	short i;		/* loop index */
 	short dataPoint = 0;
 	struct comedi_device *dev = d;
+	struct das800_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;	/* analog input subdevice */
 	struct comedi_async *async;
 	int status;
@@ -461,6 +445,7 @@ static irqreturn_t das800_interrupt(int irq, void *d)
 
 static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+	struct das800_private *devpriv;
 	struct comedi_subdevice *s;
 	unsigned long iobase = it->options[0];
 	unsigned int irq = it->options[1];
@@ -472,9 +457,10 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (irq)
 		dev_dbg(dev->class_dev, "irq %u\n", irq);
 
-	/* allocate and initialize dev->private */
-	if (alloc_private(dev, sizeof(struct das800_private)) < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
 
 	if (iobase == 0) {
 		dev_err(dev->class_dev,
@@ -569,6 +555,8 @@ static void das800_detach(struct comedi_device *dev)
 
 static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct das800_private *devpriv = dev->private;
+
 	devpriv->forever = 0;
 	devpriv->count = 0;
 	disable_das800(dev);
@@ -578,7 +566,9 @@ static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 /* enable_das800 makes the card start taking hardware triggered conversions */
 static void enable_das800(struct comedi_device *dev)
 {
+	struct das800_private *devpriv = dev->private;
 	unsigned long irq_flags;
+
 	spin_lock_irqsave(&dev->spinlock, irq_flags);
 	/*  enable fifo-half full interrupts for cio-das802/16 */
 	if (thisboard->resolution == 16)
@@ -604,6 +594,7 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_cmd *cmd)
 {
+	struct das800_private *devpriv = dev->private;
 	int err = 0;
 	int tmp;
 	int gain, startChan;
@@ -631,37 +622,21 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < thisboard->ai_speed) {
-			cmd->convert_arg = thisboard->ai_speed;
-			err++;
-		}
-	}
-	if (!cmd->chanlist_len) {
-		cmd->chanlist_len = 1;
-		err++;
-	}
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (!cmd->stop_arg) {
-			cmd->stop_arg = 1;
-			err++;
-		}
-	} else {		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+
+	if (cmd->convert_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+						 thisboard->ai_speed);
+
+	err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+	if (cmd->stop_src == TRIG_COUNT)
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+	else	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -710,6 +685,7 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev,
 static int das800_ai_do_cmd(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
+	struct das800_private *devpriv = dev->private;
 	int startChan, endChan, scan, gain;
 	int conv_bits;
 	unsigned long irq_flags;
@@ -793,6 +769,7 @@ static int das800_ai_rinsn(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
 			   unsigned int *data)
 {
+	struct das800_private *devpriv = dev->private;
 	int i, n;
 	int chan;
 	int range;
@@ -862,6 +839,7 @@ static int das800_do_wbits(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
 			   unsigned int *data)
 {
+	struct das800_private *devpriv = dev->private;
 	int wbits;
 	unsigned long irq_flags;
 
@@ -885,6 +863,7 @@ static int das800_do_wbits(struct comedi_device *dev,
 /* loads counters with divisor1, divisor2 from private structure */
 static int das800_set_frequency(struct comedi_device *dev)
 {
+	struct das800_private *devpriv = dev->private;
 	int err = 0;
 
 	if (i8254_load(dev->iobase + DAS800_8254, 0, 1, devpriv->divisor1, 2))
diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
index 4d5c33c..9e21241 100644
--- a/drivers/staging/comedi/drivers/dmm32at.c
+++ b/drivers/staging/comedi/drivers/dmm32at.c
@@ -158,10 +158,6 @@ static const struct comedi_lrange dmm32at_aoranges = {
 	 }
 };
 
-struct dmm32at_board {
-	const char *name;
-};
-
 struct dmm32at_private {
 
 	int data;
@@ -284,33 +280,25 @@ static int dmm32at_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
+
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
 #define MAX_SCAN_SPEED	1000000	/* in nanoseconds */
 #define MIN_SCAN_SPEED	1000000000	/* in nanoseconds */
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
-		if (cmd->scan_begin_arg < MAX_SCAN_SPEED) {
-			cmd->scan_begin_arg = MAX_SCAN_SPEED;
-			err++;
-		}
-		if (cmd->scan_begin_arg > MIN_SCAN_SPEED) {
-			cmd->scan_begin_arg = MIN_SCAN_SPEED;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						 MAX_SCAN_SPEED);
+		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
+						 MIN_SCAN_SPEED);
 	} else {
 		/* external trigger */
 		/* should be level/edge, hi/lo specification here */
 		/* should specify multiple external triggers */
-		if (cmd->scan_begin_arg > 9) {
-			cmd->scan_begin_arg = 9;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9);
 	}
+
 	if (cmd->convert_src == TRIG_TIMER) {
 		if (cmd->convert_arg >= 17500)
 			cmd->convert_arg = 20000;
@@ -320,35 +308,20 @@ static int dmm32at_ai_cmdtest(struct comedi_device *dev,
 			cmd->convert_arg = 10000;
 		else
 			cmd->convert_arg = 5000;
-
 	} else {
 		/* external trigger */
 		/* see above */
-		if (cmd->convert_arg > 9) {
-			cmd->convert_arg = 9;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 9);
 	}
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
 	if (cmd->stop_src == TRIG_COUNT) {
-		if (cmd->stop_arg > 0xfffffff0) {
-			cmd->stop_arg = 0xfffffff0;
-			err++;
-		}
-		if (cmd->stop_arg == 0) {
-			cmd->stop_arg = 1;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_max(&cmd->stop_arg, 0xfffffff0);
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
 	} else {
 		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 	}
 
 	if (err)
@@ -718,7 +691,6 @@ static int dmm32at_dio_insn_config(struct comedi_device *dev,
 static int dmm32at_attach(struct comedi_device *dev,
 			  struct comedi_devconfig *it)
 {
-	const struct dmm32at_board *board = comedi_board(dev);
 	struct dmm32at_private *devpriv;
 	int ret;
 	struct comedi_subdevice *s;
@@ -726,6 +698,8 @@ static int dmm32at_attach(struct comedi_device *dev,
 	unsigned long iobase;
 	unsigned int irq;
 
+	dev->board_name = dev->driver->driver_name;
+
 	iobase = it->options[0];
 	irq = it->options[1];
 
@@ -734,7 +708,7 @@ static int dmm32at_attach(struct comedi_device *dev,
 	       iobase, irq);
 
 	/* register address space */
-	if (!request_region(iobase, DMM32AT_MEMSIZE, board->name)) {
+	if (!request_region(iobase, DMM32AT_MEMSIZE, dev->board_name)) {
 		printk(KERN_ERR "comedi%d: dmm32at: I/O port conflict\n",
 		       dev->minor);
 		return -EIO;
@@ -788,7 +762,7 @@ static int dmm32at_attach(struct comedi_device *dev,
 
 	/* board is there, register interrupt */
 	if (irq) {
-		ret = request_irq(irq, dmm32at_isr, 0, board->name, dev);
+		ret = request_irq(irq, dmm32at_isr, 0, dev->board_name, dev);
 		if (ret < 0) {
 			printk(KERN_ERR "dmm32at: irq conflict\n");
 			return ret;
@@ -796,11 +770,10 @@ static int dmm32at_attach(struct comedi_device *dev,
 		dev->irq = irq;
 	}
 
-	dev->board_name = board->name;
-
-	if (alloc_private(dev, sizeof(*devpriv)) < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
-	devpriv = dev->private;
+	dev->private = devpriv;
 
 	ret = comedi_alloc_subdevices(dev, 3);
 	if (ret)
@@ -867,20 +840,11 @@ static void dmm32at_detach(struct comedi_device *dev)
 		release_region(dev->iobase, DMM32AT_MEMSIZE);
 }
 
-static const struct dmm32at_board dmm32at_boards[] = {
-	{
-		.name		= "dmm32at",
-	},
-};
-
 static struct comedi_driver dmm32at_driver = {
 	.driver_name	= "dmm32at",
 	.module		= THIS_MODULE,
 	.attach		= dmm32at_attach,
 	.detach		= dmm32at_detach,
-	.board_name	= &dmm32at_boards[0].name,
-	.offset		= sizeof(struct dmm32at_board),
-	.num_names	= ARRAY_SIZE(dmm32at_boards),
 };
 module_comedi_driver(dmm32at_driver);
 
diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
index c59a652..f6942aa 100644
--- a/drivers/staging/comedi/drivers/dt2801.c
+++ b/drivers/staging/comedi/drivers/dt2801.c
@@ -233,8 +233,6 @@ struct dt2801_private {
 	unsigned int ao_readback[2];
 };
 
-#define devpriv ((struct dt2801_private *)dev->private)
-
 /* These are the low-level routines:
    writecommand: write a command to the board
    writedata: write data byte
@@ -508,6 +506,8 @@ static int dt2801_ao_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct dt2801_private *devpriv = dev->private;
+
 	data[0] = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
 
 	return 1;
@@ -517,6 +517,8 @@ static int dt2801_ao_insn_write(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
 {
+	struct dt2801_private *devpriv = dev->private;
+
 	dt2801_writecmd(dev, DT_C_WRITE_DAIM);
 	dt2801_writedata(dev, CR_CHAN(insn->chanspec));
 	dt2801_writedata2(dev, data[0]);
@@ -590,6 +592,7 @@ static int dt2801_dio_insn_config(struct comedi_device *dev,
 */
 static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+	struct dt2801_private *devpriv;
 	struct comedi_subdevice *s;
 	unsigned long iobase;
 	int board_code, type;
@@ -630,9 +633,10 @@ havetype:
 	if (ret)
 		goto out;
 
-	ret = alloc_private(dev, sizeof(struct dt2801_private));
-	if (ret < 0)
-		return ret;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	dev->board_name = boardtype.name;
 
diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
index d3a8c1a..f90ecf4 100644
--- a/drivers/staging/comedi/drivers/dt2811.c
+++ b/drivers/staging/comedi/drivers/dt2811.c
@@ -226,8 +226,6 @@ struct dt2811_private {
 	unsigned int ao_readback[2];
 };
 
-#define devpriv ((struct dt2811_private *)dev->private)
-
 static const struct comedi_lrange *dac_range_types[] = {
 	&range_bipolar5,
 	&range_bipolar2_5,
@@ -242,6 +240,7 @@ static irqreturn_t dt2811_interrupt(int irq, void *d)
 	int lo, hi;
 	int data;
 	struct comedi_device *dev = d;
+	struct dt2811_private *devpriv = dev->private;
 
 	if (!dev->attached) {
 		comedi_error(dev, "spurious interrupt");
@@ -318,6 +317,7 @@ int dt2811_adtrig(kdev_t minor, comedi_adtrig *adtrig)
 static int dt2811_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
 			  struct comedi_insn *insn, unsigned int *data)
 {
+	struct dt2811_private *devpriv = dev->private;
 	int i;
 	int chan;
 
@@ -337,6 +337,7 @@ static int dt2811_ao_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct dt2811_private *devpriv = dev->private;
 	int i;
 	int chan;
 
@@ -397,6 +398,7 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	/* long flags; */
 
 	const struct dt2811_board *board = comedi_board(dev);
+	struct dt2811_private *devpriv;
 	int ret;
 	struct comedi_subdevice *s;
 	unsigned long iobase;
@@ -463,9 +465,10 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	ret = alloc_private(dev, sizeof(struct dt2811_private));
-	if (ret < 0)
-		return ret;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	switch (it->options[2]) {
 	case 0:
diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c
index 064a8f2..e520dba 100644
--- a/drivers/staging/comedi/drivers/dt2814.c
+++ b/drivers/staging/comedi/drivers/dt2814.c
@@ -68,8 +68,6 @@ struct dt2814_private {
 	int curadchan;
 };
 
-#define devpriv ((struct dt2814_private *)dev->private)
-
 #define DT2814_TIMEOUT 10
 #define DT2814_MAX_SPEED 100000	/* Arbitrary 10 khz limit */
 
@@ -151,36 +149,20 @@ static int dt2814_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
-	if (cmd->scan_begin_arg > 1000000000) {
-		cmd->scan_begin_arg = 1000000000;
-		err++;
-	}
-	if (cmd->scan_begin_arg < DT2814_MAX_SPEED) {
-		cmd->scan_begin_arg = DT2814_MAX_SPEED;
-		err++;
-	}
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (cmd->stop_arg < 2) {
-			cmd->stop_arg = 2;
-			err++;
-		}
-	} else {
-		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+
+	err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 1000000000);
+	err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+					 DT2814_MAX_SPEED);
+
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+	if (cmd->stop_src == TRIG_COUNT)
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 2);
+	else	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -200,6 +182,7 @@ static int dt2814_ai_cmdtest(struct comedi_device *dev,
 
 static int dt2814_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct dt2814_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
 	int chan;
 	int trigvar;
@@ -221,6 +204,7 @@ static irqreturn_t dt2814_interrupt(int irq, void *d)
 {
 	int lo, hi;
 	struct comedi_device *dev = d;
+	struct dt2814_private *devpriv = dev->private;
 	struct comedi_subdevice *s;
 	int data;
 
@@ -258,6 +242,7 @@ static irqreturn_t dt2814_interrupt(int irq, void *d)
 
 static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+	struct dt2814_private *devpriv;
 	int i, irq;
 	int ret;
 	struct comedi_subdevice *s;
@@ -324,9 +309,10 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	ret = alloc_private(dev, sizeof(struct dt2814_private));
-	if (ret < 0)
-		return ret;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	s = &dev->subdevices[0];
 	dev->read_subdev = s;
diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
index b9692ef..1e0cfe4 100644
--- a/drivers/staging/comedi/drivers/dt2815.c
+++ b/drivers/staging/comedi/drivers/dt2815.c
@@ -78,8 +78,6 @@ struct dt2815_private {
 	unsigned int ao_readback[8];
 };
 
-#define devpriv ((struct dt2815_private *)dev->private)
-
 static int dt2815_wait_for_status(struct comedi_device *dev, int status)
 {
 	int i;
@@ -95,6 +93,7 @@ static int dt2815_ao_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct dt2815_private *devpriv = dev->private;
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 
@@ -107,6 +106,7 @@ static int dt2815_ao_insn_read(struct comedi_device *dev,
 static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
 			  struct comedi_insn *insn, unsigned int *data)
 {
+	struct dt2815_private *devpriv = dev->private;
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 	unsigned int status;
@@ -162,6 +162,7 @@ static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+	struct dt2815_private *devpriv;
 	struct comedi_subdevice *s;
 	int i;
 	const struct comedi_lrange *current_range_type, *voltage_range_type;
@@ -182,8 +183,10 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	if (alloc_private(dev, sizeof(struct dt2815_private)) < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
 
 	s = &dev->subdevices[0];
 	/* ao subdevice */
diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
index 78d3407..122d980 100644
--- a/drivers/staging/comedi/drivers/dt282x.c
+++ b/drivers/staging/comedi/drivers/dt282x.c
@@ -248,7 +248,6 @@ struct dt282x_private {
 	int dma_dir;
 };
 
-#define devpriv ((struct dt282x_private *)dev->private)
 #define boardtype (*(const struct dt282x_board *)dev->board_ptr)
 
 /*
@@ -290,6 +289,7 @@ static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2);
 static void dt282x_munge(struct comedi_device *dev, short *buf,
 			 unsigned int nbytes)
 {
+	struct dt282x_private *devpriv = dev->private;
 	unsigned int i;
 	unsigned short mask = (1 << boardtype.adbits) - 1;
 	unsigned short sign = 1 << (boardtype.adbits - 1);
@@ -309,6 +309,7 @@ static void dt282x_munge(struct comedi_device *dev, short *buf,
 
 static void dt282x_ao_dma_interrupt(struct comedi_device *dev)
 {
+	struct dt282x_private *devpriv = dev->private;
 	void *ptr;
 	int size;
 	int i;
@@ -341,6 +342,7 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev)
 
 static void dt282x_ai_dma_interrupt(struct comedi_device *dev)
 {
+	struct dt282x_private *devpriv = dev->private;
 	void *ptr;
 	int size;
 	int i;
@@ -393,6 +395,7 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev)
 
 static int prep_ai_dma(struct comedi_device *dev, int dma_index, int n)
 {
+	struct dt282x_private *devpriv = dev->private;
 	int dma_chan;
 	unsigned long dma_ptr;
 	unsigned long flags;
@@ -424,6 +427,7 @@ static int prep_ai_dma(struct comedi_device *dev, int dma_index, int n)
 
 static int prep_ao_dma(struct comedi_device *dev, int dma_index, int n)
 {
+	struct dt282x_private *devpriv = dev->private;
 	int dma_chan;
 	unsigned long dma_ptr;
 	unsigned long flags;
@@ -447,6 +451,7 @@ static int prep_ao_dma(struct comedi_device *dev, int dma_index, int n)
 static irqreturn_t dt282x_interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct dt282x_private *devpriv = dev->private;
 	struct comedi_subdevice *s;
 	struct comedi_subdevice *s_ao;
 	unsigned int supcsr, adcsr, dacsr;
@@ -525,6 +530,7 @@ static irqreturn_t dt282x_interrupt(int irq, void *d)
 static void dt282x_load_changain(struct comedi_device *dev, int n,
 				 unsigned int *chanlist)
 {
+	struct dt282x_private *devpriv = dev->private;
 	unsigned int i;
 	unsigned int chan, range;
 
@@ -548,6 +554,7 @@ static int dt282x_ai_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct dt282x_private *devpriv = dev->private;
 	int i;
 
 	/* XXX should we really be enabling the ad clock here? */
@@ -604,52 +611,30 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
+
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
 	if (cmd->scan_begin_src == TRIG_FOLLOW) {
 		/* internal trigger */
-		if (cmd->scan_begin_arg != 0) {
-			cmd->scan_begin_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 	} else {
 		/* external trigger */
 		/* should be level/edge, hi/lo specification here */
-		if (cmd->scan_begin_arg != 0) {
-			cmd->scan_begin_arg = 0;
-			err++;
-		}
-	}
-	if (cmd->convert_arg < 4000) {
-		/* XXX board dependent */
-		cmd->convert_arg = 4000;
-		err++;
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 	}
+
+	err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 4000);
+
 #define SLOWEST_TIMER	(250*(1<<15)*255)
-	if (cmd->convert_arg > SLOWEST_TIMER) {
-		cmd->convert_arg = SLOWEST_TIMER;
-		err++;
-	}
-	if (cmd->convert_arg < board->ai_speed) {
-		cmd->convert_arg = board->ai_speed;
-		err++;
-	}
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_max(&cmd->convert_arg, SLOWEST_TIMER);
+	err |= cfc_check_trigger_arg_min(&cmd->convert_arg, board->ai_speed);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
 	if (cmd->stop_src == TRIG_COUNT) {
 		/* any count is allowed */
-	} else {
-		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+	} else {	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 	}
 
 	if (err)
@@ -671,6 +656,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev,
 static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	const struct dt282x_board *board = comedi_board(dev);
+	struct dt282x_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
 	int timer;
 
@@ -733,6 +719,8 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static void dt282x_disable_dma(struct comedi_device *dev)
 {
+	struct dt282x_private *devpriv = dev->private;
+
 	if (devpriv->usedma) {
 		disable_dma(devpriv->dma[0].chan);
 		disable_dma(devpriv->dma[1].chan);
@@ -742,6 +730,8 @@ static void dt282x_disable_dma(struct comedi_device *dev)
 static int dt282x_ai_cancel(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
+	struct dt282x_private *devpriv = dev->private;
+
 	dt282x_disable_dma(dev);
 
 	devpriv->adcsr = 0;
@@ -794,6 +784,8 @@ static int dt282x_ao_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct dt282x_private *devpriv = dev->private;
+
 	data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];
 
 	return 1;
@@ -803,6 +795,7 @@ static int dt282x_ao_insn_write(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
 {
+	struct dt282x_private *devpriv = dev->private;
 	short d;
 	unsigned int chan;
 
@@ -859,33 +852,17 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
+
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+	err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, 5000);
+	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+	err |= cfc_check_trigger_arg_max(&cmd->scan_end_arg, 2);
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
-	if (cmd->scan_begin_arg < 5000 /* XXX unknown */) {
-		cmd->scan_begin_arg = 5000;
-		err++;
-	}
-	if (cmd->convert_arg != 0) {
-		cmd->convert_arg = 0;
-		err++;
-	}
-	if (cmd->scan_end_arg > 2) {
-		/* XXX chanlist stuff? */
-		cmd->scan_end_arg = 2;
-		err++;
-	}
 	if (cmd->stop_src == TRIG_COUNT) {
 		/* any count is allowed */
-	} else {
-		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+	} else {	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 	}
 
 	if (err)
@@ -908,6 +885,7 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev,
 static int dt282x_ao_inttrig(struct comedi_device *dev,
 			     struct comedi_subdevice *s, unsigned int x)
 {
+	struct dt282x_private *devpriv = dev->private;
 	int size;
 
 	if (x != 0)
@@ -937,6 +915,7 @@ static int dt282x_ao_inttrig(struct comedi_device *dev,
 
 static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct dt282x_private *devpriv = dev->private;
 	int timer;
 	struct comedi_cmd *cmd = &s->async->cmd;
 
@@ -973,6 +952,8 @@ static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 static int dt282x_ao_cancel(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
+	struct dt282x_private *devpriv = dev->private;
+
 	dt282x_disable_dma(dev);
 
 	devpriv->dacsr = 0;
@@ -1003,6 +984,7 @@ static int dt282x_dio_insn_config(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
 				  struct comedi_insn *insn, unsigned int *data)
 {
+	struct dt282x_private *devpriv = dev->private;
 	int mask;
 
 	mask = (CR_CHAN(insn->chanspec) < 8) ? 0x00ff : 0xff00;
@@ -1074,6 +1056,7 @@ enum {  /* i/o base, irq, dma channels */
 
 static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2)
 {
+	struct dt282x_private *devpriv = dev->private;
 	int ret;
 
 	devpriv->usedma = 0;
@@ -1135,6 +1118,7 @@ static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2)
 static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct dt282x_board *board = comedi_board(dev);
+	struct dt282x_private *devpriv;
 	int i, irq;
 	int ret;
 	struct comedi_subdevice *s;
@@ -1217,9 +1201,10 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 #endif
 	}
 
-	ret = alloc_private(dev, sizeof(struct dt282x_private));
-	if (ret < 0)
-		return ret;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = dt282x_grab_dma(dev, it->options[opt_dma1],
 			      it->options[opt_dma2]);
@@ -1292,6 +1277,8 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 static void dt282x_detach(struct comedi_device *dev)
 {
+	struct dt282x_private *devpriv = dev->private;
+
 	if (dev->irq)
 		free_irq(dev->irq, dev);
 	if (dev->iobase)
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index 43d05ef..960da8d 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -29,11 +29,7 @@ Devices: [Data Translation] DT3001 (dt3000), DT3001-PGL, DT3002, DT3003,
 Updated: Mon, 14 Apr 2008 15:41:24 +0100
 Status: works
 
-Configuration Options:
-  [0] - PCI bus of device (optional)
-  [1] - PCI slot of device (optional)
-  If bus/slot is not specified, the first supported
-  PCI device found will be used.
+Configuration Options: not applicable, uses PCI auto config
 
 There is code to support AI commands, but it may not work.
 
@@ -65,26 +61,36 @@ AO commands are not supported.
 
 #include "comedi_fc.h"
 
-#define PCI_VENDOR_ID_DT	0x1116
-
-static const struct comedi_lrange range_dt3000_ai = { 4, {
-							  RANGE(-10, 10),
-							  RANGE(-5, 5),
-							  RANGE(-2.5, 2.5),
-							  RANGE(-1.25, 1.25)
-							  }
+/*
+ * PCI device id's supported by this driver
+ */
+#define PCI_DEVICE_ID_DT3001		0x0022
+#define PCI_DEVICE_ID_DT3002		0x0023
+#define PCI_DEVICE_ID_DT3003		0x0024
+#define PCI_DEVICE_ID_DT3004		0x0025
+#define PCI_DEVICE_ID_DT3005		0x0026
+#define PCI_DEVICE_ID_DT3001_PGL	0x0027
+#define PCI_DEVICE_ID_DT3003_PGL	0x0028
+
+static const struct comedi_lrange range_dt3000_ai = {
+	4, {
+		BIP_RANGE(10),
+		BIP_RANGE(5),
+		BIP_RANGE(2.5),
+		BIP_RANGE(1.25)
+	}
 };
 
-static const struct comedi_lrange range_dt3000_ai_pgl = { 4, {
-							      RANGE(-10, 10),
-							      RANGE(-1, 1),
-							      RANGE(-0.1, 0.1),
-							      RANGE(-0.02, 0.02)
-							      }
+static const struct comedi_lrange range_dt3000_ai_pgl = {
+	4, {
+		BIP_RANGE(10),
+		BIP_RANGE(1),
+		BIP_RANGE(0.1),
+		BIP_RANGE(0.02)
+	}
 };
 
 struct dt3k_boardtype {
-
 	const char *name;
 	unsigned int device_id;
 	int adchan;
@@ -96,73 +102,70 @@ struct dt3k_boardtype {
 };
 
 static const struct dt3k_boardtype dt3k_boardtypes[] = {
-	{.name = "dt3001",
-	 .device_id = 0x22,
-	 .adchan = 16,
-	 .adbits = 12,
-	 .adrange = &range_dt3000_ai,
-	 .ai_speed = 3000,
-	 .dachan = 2,
-	 .dabits = 12,
-	 },
-	{.name = "dt3001-pgl",
-	 .device_id = 0x27,
-	 .adchan = 16,
-	 .adbits = 12,
-	 .adrange = &range_dt3000_ai_pgl,
-	 .ai_speed = 3000,
-	 .dachan = 2,
-	 .dabits = 12,
-	 },
-	{.name = "dt3002",
-	 .device_id = 0x23,
-	 .adchan = 32,
-	 .adbits = 12,
-	 .adrange = &range_dt3000_ai,
-	 .ai_speed = 3000,
-	 .dachan = 0,
-	 .dabits = 0,
-	 },
-	{.name = "dt3003",
-	 .device_id = 0x24,
-	 .adchan = 64,
-	 .adbits = 12,
-	 .adrange = &range_dt3000_ai,
-	 .ai_speed = 3000,
-	 .dachan = 2,
-	 .dabits = 12,
-	 },
-	{.name = "dt3003-pgl",
-	 .device_id = 0x28,
-	 .adchan = 64,
-	 .adbits = 12,
-	 .adrange = &range_dt3000_ai_pgl,
-	 .ai_speed = 3000,
-	 .dachan = 2,
-	 .dabits = 12,
-	 },
-	{.name = "dt3004",
-	 .device_id = 0x25,
-	 .adchan = 16,
-	 .adbits = 16,
-	 .adrange = &range_dt3000_ai,
-	 .ai_speed = 10000,
-	 .dachan = 2,
-	 .dabits = 12,
-	 },
-	{.name = "dt3005",	/* a.k.a. 3004-200 */
-	 .device_id = 0x26,
-	 .adchan = 16,
-	 .adbits = 16,
-	 .adrange = &range_dt3000_ai,
-	 .ai_speed = 5000,
-	 .dachan = 2,
-	 .dabits = 12,
-	 },
+	{
+		.name		= "dt3001",
+		.device_id	= PCI_DEVICE_ID_DT3001,
+		.adchan		= 16,
+		.adbits		= 12,
+		.adrange	= &range_dt3000_ai,
+		.ai_speed	= 3000,
+		.dachan		= 2,
+		.dabits		= 12,
+	}, {
+		.name		= "dt3001-pgl",
+		.device_id	= PCI_DEVICE_ID_DT3001_PGL,
+		.adchan		= 16,
+		.adbits		= 12,
+		.adrange	= &range_dt3000_ai_pgl,
+		.ai_speed	= 3000,
+		.dachan		= 2,
+		.dabits		= 12,
+	}, {
+		.name		= "dt3002",
+		.device_id	= PCI_DEVICE_ID_DT3002,
+		.adchan		= 32,
+		.adbits		= 12,
+		.adrange	= &range_dt3000_ai,
+		.ai_speed	= 3000,
+	}, {
+		.name		= "dt3003",
+		.device_id	= PCI_DEVICE_ID_DT3003,
+		.adchan		= 64,
+		.adbits		= 12,
+		.adrange	= &range_dt3000_ai,
+		.ai_speed	= 3000,
+		.dachan		= 2,
+		.dabits		= 12,
+	}, {
+		.name		= "dt3003-pgl",
+		.device_id	= PCI_DEVICE_ID_DT3003_PGL,
+		.adchan		= 64,
+		.adbits		= 12,
+		.adrange	= &range_dt3000_ai_pgl,
+		.ai_speed	= 3000,
+		.dachan		= 2,
+		.dabits		= 12,
+	}, {
+		.name		= "dt3004",
+		.device_id	= PCI_DEVICE_ID_DT3004,
+		.adchan		= 16,
+		.adbits		= 16,
+		.adrange	= &range_dt3000_ai,
+		.ai_speed	= 10000,
+		.dachan		= 2,
+		.dabits		= 12,
+	}, {
+		.name		= "dt3005",	/* a.k.a. 3004-200 */
+		.device_id 	= PCI_DEVICE_ID_DT3005,
+		.adchan		= 16,
+		.adbits		= 16,
+		.adrange	= &range_dt3000_ai,
+		.ai_speed	= 5000,
+		.dachan		= 2,
+		.dabits		= 12,
+	},
 };
 
-#define this_board ((const struct dt3k_boardtype *)dev->board_ptr)
-
 #define DT3000_SIZE		(4*0x1000)
 
 /* dual-ported RAM location definitions */
@@ -257,22 +260,29 @@ struct dt3k_private {
 	unsigned int ai_rear;
 };
 
-#define devpriv ((struct dt3k_private *)dev->private)
-
-static void dt3k_ai_empty_fifo(struct comedi_device *dev,
-			       struct comedi_subdevice *s);
-static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *arg,
-			    unsigned int round_mode);
-static int dt3k_ai_cancel(struct comedi_device *dev,
-			  struct comedi_subdevice *s);
 #ifdef DEBUG
-static void debug_intr_flags(unsigned int flags);
+static char *intr_flags[] = {
+	"AdFull", "AdSwError", "AdHwError", "DaEmpty",
+	"DaSwError", "DaHwError", "CtDone", "CmDone",
+};
+
+static void debug_intr_flags(unsigned int flags)
+{
+	int i;
+	printk(KERN_DEBUG "dt3k: intr_flags:");
+	for (i = 0; i < 8; i++) {
+		if (flags & (1 << i))
+			printk(KERN_CONT " %s", intr_flags[i]);
+	}
+	printk(KERN_CONT "\n");
+}
 #endif
 
 #define TIMEOUT 100
 
-static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
+static void dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
 {
+	struct dt3k_private *devpriv = dev->private;
 	int i;
 	unsigned int status = 0;
 
@@ -284,19 +294,18 @@ static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
 			break;
 		udelay(1);
 	}
-	if ((status & DT3000_COMPLETION_MASK) == DT3000_NOERROR)
-		return 0;
-
-	dev_dbg(dev->class_dev, "dt3k_send_cmd() timeout/error status=0x%04x\n",
-		status);
 
-	return -ETIME;
+	if ((status & DT3000_COMPLETION_MASK) != DT3000_NOERROR)
+		dev_dbg(dev->class_dev, "%s: timeout/error status=0x%04x\n",
+			__func__, status);
 }
 
 static unsigned int dt3k_readsingle(struct comedi_device *dev,
 				    unsigned int subsys, unsigned int chan,
 				    unsigned int gain)
 {
+	struct dt3k_private *devpriv = dev->private;
+
 	writew(subsys, devpriv->io_addr + DPR_SubSys);
 
 	writew(chan, devpriv->io_addr + DPR_Params(0));
@@ -310,6 +319,8 @@ static unsigned int dt3k_readsingle(struct comedi_device *dev,
 static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
 			     unsigned int chan, unsigned int data)
 {
+	struct dt3k_private *devpriv = dev->private;
+
 	writew(subsys, devpriv->io_addr + DPR_SubSys);
 
 	writew(chan, devpriv->io_addr + DPR_Params(0));
@@ -319,6 +330,47 @@ static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
 	dt3k_send_cmd(dev, CMD_WRITESINGLE);
 }
 
+static void dt3k_ai_empty_fifo(struct comedi_device *dev,
+			       struct comedi_subdevice *s)
+{
+	struct dt3k_private *devpriv = dev->private;
+	int front;
+	int rear;
+	int count;
+	int i;
+	short data;
+
+	front = readw(devpriv->io_addr + DPR_AD_Buf_Front);
+	count = front - devpriv->ai_front;
+	if (count < 0)
+		count += AI_FIFO_DEPTH;
+
+	rear = devpriv->ai_rear;
+
+	for (i = 0; i < count; i++) {
+		data = readw(devpriv->io_addr + DPR_ADC_buffer + rear);
+		comedi_buf_put(s->async, data);
+		rear++;
+		if (rear >= AI_FIFO_DEPTH)
+			rear = 0;
+	}
+
+	devpriv->ai_rear = rear;
+	writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear);
+}
+
+static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+{
+	struct dt3k_private *devpriv = dev->private;
+
+	writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
+	dt3k_send_cmd(dev, CMD_STOP);
+
+	writew(0, devpriv->io_addr + DPR_Int_Mask);
+
+	return 0;
+}
+
 static int debug_n_ints;
 
 /* FIXME! Assumes shared interrupt is for this card. */
@@ -326,6 +378,7 @@ static int debug_n_ints;
 static irqreturn_t dt3k_interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct dt3k_private *devpriv = dev->private;
 	struct comedi_subdevice *s;
 	unsigned int status;
 
@@ -356,57 +409,45 @@ static irqreturn_t dt3k_interrupt(int irq, void *d)
 	return IRQ_HANDLED;
 }
 
-#ifdef DEBUG
-static char *intr_flags[] = {
-	"AdFull", "AdSwError", "AdHwError", "DaEmpty",
-	"DaSwError", "DaHwError", "CtDone", "CmDone",
-};
-
-static void debug_intr_flags(unsigned int flags)
-{
-	int i;
-	printk(KERN_DEBUG "dt3k: intr_flags:");
-	for (i = 0; i < 8; i++) {
-		if (flags & (1 << i))
-			printk(KERN_CONT " %s", intr_flags[i]);
-	}
-	printk(KERN_CONT "\n");
-}
-#endif
-
-static void dt3k_ai_empty_fifo(struct comedi_device *dev,
-			       struct comedi_subdevice *s)
+static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
+			    unsigned int round_mode)
 {
-	int front;
-	int rear;
-	int count;
-	int i;
-	short data;
-
-	front = readw(devpriv->io_addr + DPR_AD_Buf_Front);
-	count = front - devpriv->ai_front;
-	if (count < 0)
-		count += AI_FIFO_DEPTH;
-
-	dev_dbg(dev->class_dev, "reading %d samples\n", count);
+	int divider, base, prescale;
 
-	rear = devpriv->ai_rear;
+	/* This function needs improvment */
+	/* Don't know if divider==0 works. */
 
-	for (i = 0; i < count; i++) {
-		data = readw(devpriv->io_addr + DPR_ADC_buffer + rear);
-		comedi_buf_put(s->async, data);
-		rear++;
-		if (rear >= AI_FIFO_DEPTH)
-			rear = 0;
+	for (prescale = 0; prescale < 16; prescale++) {
+		base = timer_base * (prescale + 1);
+		switch (round_mode) {
+		case TRIG_ROUND_NEAREST:
+		default:
+			divider = (*nanosec + base / 2) / base;
+			break;
+		case TRIG_ROUND_DOWN:
+			divider = (*nanosec) / base;
+			break;
+		case TRIG_ROUND_UP:
+			divider = (*nanosec) / base;
+			break;
+		}
+		if (divider < 65536) {
+			*nanosec = divider * base;
+			return (prescale << 16) | (divider);
+		}
 	}
 
-	devpriv->ai_rear = rear;
-	writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear);
+	prescale = 15;
+	base = timer_base * (1 << prescale);
+	divider = 65535;
+	*nanosec = divider * base;
+	return (prescale << 16) | (divider);
 }
 
 static int dt3k_ai_cmdtest(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
+	const struct dt3k_boardtype *this_board = comedi_board(dev);
 	int err = 0;
 	int tmp;
 
@@ -427,54 +468,30 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
-		if (cmd->scan_begin_arg < this_board->ai_speed) {
-			cmd->scan_begin_arg = this_board->ai_speed;
-			err++;
-		}
-		if (cmd->scan_begin_arg > 100 * 16 * 65535) {
-			cmd->scan_begin_arg = 100 * 16 * 65535;
-			err++;
-		}
-	} else {
-		/* not supported */
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						 this_board->ai_speed);
+		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
+						 100 * 16 * 65535);
 	}
+
 	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < this_board->ai_speed) {
-			cmd->convert_arg = this_board->ai_speed;
-			err++;
-		}
-		if (cmd->convert_arg > 50 * 16 * 65535) {
-			cmd->convert_arg = 50 * 16 * 65535;
-			err++;
-		}
-	} else {
-		/* not supported */
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+						 this_board->ai_speed);
+		err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
+						 50 * 16 * 65535);
 	}
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (cmd->stop_arg > 0x00ffffff) {
-			cmd->stop_arg = 0x00ffffff;
-			err++;
-		}
-	} else {
-		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+	if (cmd->stop_src == TRIG_COUNT)
+		err |= cfc_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
+	else	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -487,9 +504,8 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev,
 				 cmd->flags & TRIG_ROUND_MASK);
 		if (tmp != cmd->scan_begin_arg)
 			err++;
-	} else {
-		/* not supported */
 	}
+
 	if (cmd->convert_src == TRIG_TIMER) {
 		tmp = cmd->convert_arg;
 		dt3k_ns_to_timer(50, &cmd->convert_arg,
@@ -503,8 +519,6 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev,
 			    cmd->convert_arg * cmd->scan_end_arg;
 			err++;
 		}
-	} else {
-		/* not supported */
 	}
 
 	if (err)
@@ -513,52 +527,16 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev,
 	return 0;
 }
 
-static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
-			    unsigned int round_mode)
-{
-	int divider, base, prescale;
-
-	/* This function needs improvment */
-	/* Don't know if divider==0 works. */
-
-	for (prescale = 0; prescale < 16; prescale++) {
-		base = timer_base * (prescale + 1);
-		switch (round_mode) {
-		case TRIG_ROUND_NEAREST:
-		default:
-			divider = (*nanosec + base / 2) / base;
-			break;
-		case TRIG_ROUND_DOWN:
-			divider = (*nanosec) / base;
-			break;
-		case TRIG_ROUND_UP:
-			divider = (*nanosec) / base;
-			break;
-		}
-		if (divider < 65536) {
-			*nanosec = divider * base;
-			return (prescale << 16) | (divider);
-		}
-	}
-
-	prescale = 15;
-	base = timer_base * (1 << prescale);
-	divider = 65535;
-	*nanosec = divider * base;
-	return (prescale << 16) | (divider);
-}
-
 static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct dt3k_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
 	int i;
 	unsigned int chan, range, aref;
 	unsigned int divider;
 	unsigned int tscandiv;
-	int ret;
 	unsigned int mode;
 
-	dev_dbg(dev->class_dev, "dt3k_ai_cmd:\n");
 	for (i = 0; i < cmd->chanlist_len; i++) {
 		chan = CR_CHAN(cmd->chanlist[i]);
 		range = CR_RANGE(cmd->chanlist[i]);
@@ -569,41 +547,29 @@ static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	aref = CR_AREF(cmd->chanlist[0]);
 
 	writew(cmd->scan_end_arg, devpriv->io_addr + DPR_Params(0));
-	dev_dbg(dev->class_dev, "param[0]=0x%04x\n", cmd->scan_end_arg);
 
 	if (cmd->convert_src == TRIG_TIMER) {
 		divider = dt3k_ns_to_timer(50, &cmd->convert_arg,
 					   cmd->flags & TRIG_ROUND_MASK);
 		writew((divider >> 16), devpriv->io_addr + DPR_Params(1));
-		dev_dbg(dev->class_dev, "param[1]=0x%04x\n", divider >> 16);
 		writew((divider & 0xffff), devpriv->io_addr + DPR_Params(2));
-		dev_dbg(dev->class_dev, "param[2]=0x%04x\n", divider & 0xffff);
-	} else {
-		/* not supported */
 	}
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
 					    cmd->flags & TRIG_ROUND_MASK);
 		writew((tscandiv >> 16), devpriv->io_addr + DPR_Params(3));
-		dev_dbg(dev->class_dev, "param[3]=0x%04x\n", tscandiv >> 16);
 		writew((tscandiv & 0xffff), devpriv->io_addr + DPR_Params(4));
-		dev_dbg(dev->class_dev, "param[4]=0x%04x\n", tscandiv & 0xffff);
-	} else {
-		/* not supported */
 	}
 
 	mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0;
 	writew(mode, devpriv->io_addr + DPR_Params(5));
-	dev_dbg(dev->class_dev, "param[5]=0x%04x\n", mode);
 	writew(aref == AREF_DIFF, devpriv->io_addr + DPR_Params(6));
-	dev_dbg(dev->class_dev, "param[6]=0x%04x\n", aref == AREF_DIFF);
 
 	writew(AI_FIFO_DEPTH / 2, devpriv->io_addr + DPR_Params(7));
-	dev_dbg(dev->class_dev, "param[7]=0x%04x\n", AI_FIFO_DEPTH / 2);
 
 	writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
-	ret = dt3k_send_cmd(dev, CMD_CONFIG);
+	dt3k_send_cmd(dev, CMD_CONFIG);
 
 	writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR,
 	       devpriv->io_addr + DPR_Int_Mask);
@@ -611,19 +577,7 @@ static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	debug_n_ints = 0;
 
 	writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
-	ret = dt3k_send_cmd(dev, CMD_START);
-
-	return 0;
-}
-
-static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
-{
-	int ret;
-
-	writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
-	ret = dt3k_send_cmd(dev, CMD_STOP);
-
-	writew(0, devpriv->io_addr + DPR_Int_Mask);
+	dt3k_send_cmd(dev, CMD_START);
 
 	return 0;
 }
@@ -648,6 +602,7 @@ static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int dt3k_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
 			struct comedi_insn *insn, unsigned int *data)
 {
+	struct dt3k_private *devpriv = dev->private;
 	int i;
 	unsigned int chan;
 
@@ -664,6 +619,7 @@ static int dt3k_ao_insn_read(struct comedi_device *dev,
 			     struct comedi_subdevice *s,
 			     struct comedi_insn *insn, unsigned int *data)
 {
+	struct dt3k_private *devpriv = dev->private;
 	int i;
 	unsigned int chan;
 
@@ -676,6 +632,8 @@ static int dt3k_ao_insn_read(struct comedi_device *dev,
 
 static void dt3k_dio_config(struct comedi_device *dev, int bits)
 {
+	struct dt3k_private *devpriv = dev->private;
+
 	/* XXX */
 	writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys);
 
@@ -739,6 +697,7 @@ static int dt3k_mem_insn_read(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
 			      struct comedi_insn *insn, unsigned int *data)
 {
+	struct dt3k_private *devpriv = dev->private;
 	unsigned int addr = CR_CHAN(insn->chanspec);
 	int i;
 
@@ -755,54 +714,42 @@ static int dt3k_mem_insn_read(struct comedi_device *dev,
 	return i;
 }
 
-static struct pci_dev *dt3000_find_pci_dev(struct comedi_device *dev,
-					   struct comedi_devconfig *it)
+static const void *dt3000_find_boardinfo(struct comedi_device *dev,
+					 struct pci_dev *pcidev)
 {
-	struct pci_dev *pcidev = NULL;
-	int bus = it->options[0];
-	int slot = it->options[1];
+	const struct dt3k_boardtype *this_board;
 	int i;
 
-	for_each_pci_dev(pcidev) {
-		if (bus || slot) {
-			if (bus != pcidev->bus->number ||
-			    slot != PCI_SLOT(pcidev->devfn))
-				continue;
-		}
-		if (pcidev->vendor != PCI_VENDOR_ID_DT)
-			continue;
-		for (i = 0; i < ARRAY_SIZE(dt3k_boardtypes); i++) {
-			if (dt3k_boardtypes[i].device_id != pcidev->device)
-				continue;
-			dev->board_ptr = dt3k_boardtypes + i;
-			return pcidev;
-		}
+	for (i = 0; i < ARRAY_SIZE(dt3k_boardtypes); i++) {
+		this_board = &dt3k_boardtypes[i];
+		if (this_board->device_id == pcidev->device)
+			return this_board;
 	}
-	dev_err(dev->class_dev,
-		"No supported board found! (req. bus %d, slot %d)\n",
-		bus, slot);
 	return NULL;
 }
 
-static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int dt3000_auto_attach(struct comedi_device *dev,
+					unsigned long context_unused)
 {
-	struct pci_dev *pcidev;
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	const struct dt3k_boardtype *this_board;
+	struct dt3k_private *devpriv;
 	struct comedi_subdevice *s;
 	resource_size_t pci_base;
 	int ret = 0;
 
-	dev_dbg(dev->class_dev, "dt3000:\n");
-
-	ret = alloc_private(dev, sizeof(struct dt3k_private));
-	if (ret < 0)
-		return ret;
+	this_board = dt3000_find_boardinfo(dev, pcidev);
+	if (!this_board)
+		return -ENODEV;
+	dev->board_ptr = this_board;
+	dev->board_name = this_board->name;
 
-	pcidev = dt3000_find_pci_dev(dev, it);
-	if (!pcidev)
-		return -EIO;
-	comedi_set_hw_dev(dev, &pcidev->dev);
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
-	ret = comedi_pci_enable(pcidev, "dt3000");
+	ret = comedi_pci_enable(pcidev, dev->board_name);
 	if (ret < 0)
 		return ret;
 	dev->iobase = 1;	/* the "detach" needs this */
@@ -812,14 +759,10 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (!devpriv->io_addr)
 		return -ENOMEM;
 
-	dev->board_name = this_board->name;
-
-	if (request_irq(pcidev->irq, dt3k_interrupt, IRQF_SHARED,
-			"dt3000", dev)) {
-		dev_err(dev->class_dev, "unable to allocate IRQ %u\n",
-			pcidev->irq);
-		return -EINVAL;
-	}
+	ret = request_irq(pcidev->irq, dt3k_interrupt, IRQF_SHARED,
+			  dev->board_name, dev);
+	if (ret)
+		return ret;
 	dev->irq = pcidev->irq;
 
 	ret = comedi_alloc_subdevices(dev, 4);
@@ -828,50 +771,49 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 	s = &dev->subdevices[0];
 	dev->read_subdev = s;
-
 	/* ai subdevice */
-	s->type = COMEDI_SUBD_AI;
-	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
-	s->n_chan = this_board->adchan;
-	s->insn_read = dt3k_ai_insn;
-	s->maxdata = (1 << this_board->adbits) - 1;
-	s->len_chanlist = 512;
-	s->range_table = &range_dt3000_ai;	/* XXX */
-	s->do_cmd = dt3k_ai_cmd;
-	s->do_cmdtest = dt3k_ai_cmdtest;
-	s->cancel = dt3k_ai_cancel;
+	s->type		= COMEDI_SUBD_AI;
+	s->subdev_flags	= SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
+	s->n_chan	= this_board->adchan;
+	s->insn_read	= dt3k_ai_insn;
+	s->maxdata	= (1 << this_board->adbits) - 1;
+	s->len_chanlist	= 512;
+	s->range_table	= &range_dt3000_ai;	/* XXX */
+	s->do_cmd	= dt3k_ai_cmd;
+	s->do_cmdtest	= dt3k_ai_cmdtest;
+	s->cancel	= dt3k_ai_cancel;
 
 	s = &dev->subdevices[1];
 	/* ao subsystem */
-	s->type = COMEDI_SUBD_AO;
-	s->subdev_flags = SDF_WRITABLE;
-	s->n_chan = 2;
-	s->insn_read = dt3k_ao_insn_read;
-	s->insn_write = dt3k_ao_insn;
-	s->maxdata = (1 << this_board->dabits) - 1;
-	s->len_chanlist = 1;
-	s->range_table = &range_bipolar10;
+	s->type		= COMEDI_SUBD_AO;
+	s->subdev_flags	= SDF_WRITABLE;
+	s->n_chan	= 2;
+	s->insn_read	= dt3k_ao_insn_read;
+	s->insn_write	= dt3k_ao_insn;
+	s->maxdata	= (1 << this_board->dabits) - 1;
+	s->len_chanlist	= 1;
+	s->range_table	= &range_bipolar10;
 
 	s = &dev->subdevices[2];
 	/* dio subsystem */
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-	s->n_chan = 8;
-	s->insn_config = dt3k_dio_insn_config;
-	s->insn_bits = dt3k_dio_insn_bits;
-	s->maxdata = 1;
-	s->len_chanlist = 8;
-	s->range_table = &range_digital;
+	s->type		= COMEDI_SUBD_DIO;
+	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
+	s->n_chan	= 8;
+	s->insn_config	= dt3k_dio_insn_config;
+	s->insn_bits	= dt3k_dio_insn_bits;
+	s->maxdata	= 1;
+	s->len_chanlist	= 8;
+	s->range_table	= &range_digital;
 
 	s = &dev->subdevices[3];
 	/* mem subsystem */
-	s->type = COMEDI_SUBD_MEMORY;
-	s->subdev_flags = SDF_READABLE;
-	s->n_chan = 0x1000;
-	s->insn_read = dt3k_mem_insn_read;
-	s->maxdata = 0xff;
-	s->len_chanlist = 1;
-	s->range_table = &range_unknown;
+	s->type		= COMEDI_SUBD_MEMORY;
+	s->subdev_flags	= SDF_READABLE;
+	s->n_chan	= 0x1000;
+	s->insn_read	= dt3k_mem_insn_read;
+	s->maxdata	= 0xff;
+	s->len_chanlist	= 1;
+	s->range_table	= &range_unknown;
 
 #if 0
 	s = &dev->subdevices[4];
@@ -879,12 +821,15 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	s->type = COMEDI_SUBD_PROC;
 #endif
 
+	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
+
 	return 0;
 }
 
 static void dt3000_detach(struct comedi_device *dev)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct dt3k_private *devpriv = dev->private;
 
 	if (dev->irq)
 		free_irq(dev->irq, dev);
@@ -895,36 +840,35 @@ static void dt3000_detach(struct comedi_device *dev)
 	if (pcidev) {
 		if (dev->iobase)
 			comedi_pci_disable(pcidev);
-		pci_dev_put(pcidev);
 	}
 }
 
 static struct comedi_driver dt3000_driver = {
 	.driver_name	= "dt3000",
 	.module		= THIS_MODULE,
-	.attach		= dt3000_attach,
+	.auto_attach	= dt3000_auto_attach,
 	.detach		= dt3000_detach,
 };
 
-static int __devinit dt3000_pci_probe(struct pci_dev *dev,
+static int dt3000_pci_probe(struct pci_dev *dev,
 				      const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &dt3000_driver);
 }
 
-static void __devexit dt3000_pci_remove(struct pci_dev *dev)
+static void dt3000_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(dt3000_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0022) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0027) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0023) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0024) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0028) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0025) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0026) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3001) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3001_PGL) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3002) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3003) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3003_PGL) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3004) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3005) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, dt3000_pci_table);
@@ -933,7 +877,7 @@ static struct pci_driver dt3000_pci_driver = {
 	.name		= "dt3000",
 	.id_table	= dt3000_pci_table,
 	.probe		= dt3000_pci_probe,
-	.remove		= __devexit_p(dt3000_pci_remove),
+	.remove		= dt3000_pci_remove,
 };
 module_comedi_pci_driver(dt3000_driver, dt3000_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
index bc6f409..1767998 100644
--- a/drivers/staging/comedi/drivers/dt9812.c
+++ b/drivers/staging/comedi/drivers/dt9812.c
@@ -43,6 +43,8 @@ for my needs.
  *      says P1).
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -323,9 +325,6 @@ static const struct comedi_lrange dt9812_2pt5_aout_range = { 1, {
 
 static struct slot_dt9812 dt9812[DT9812_NUM_SLOTS];
 
-/* Useful shorthand access to private data */
-#define devpriv ((struct comedi_dt9812 *)dev->private)
-
 static inline struct usb_dt9812 *to_dt9812_dev(struct kref *d)
 {
 	return container_of(d, struct usb_dt9812, kref);
@@ -893,6 +892,7 @@ static struct usb_driver dt9812_usb_driver = {
 
 static int dt9812_comedi_open(struct comedi_device *dev)
 {
+	struct comedi_dt9812 *devpriv = dev->private;
 	int result = -ENODEV;
 
 	down(&devpriv->slot->mutex);
@@ -947,6 +947,7 @@ static int dt9812_di_rinsn(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
 			   unsigned int *data)
 {
+	struct comedi_dt9812 *devpriv = dev->private;
 	int n;
 	u8 bits = 0;
 
@@ -960,6 +961,7 @@ static int dt9812_do_winsn(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
 			   unsigned int *data)
 {
+	struct comedi_dt9812 *devpriv = dev->private;
 	int n;
 	u8 bits = 0;
 
@@ -979,6 +981,7 @@ static int dt9812_ai_rinsn(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
 			   unsigned int *data)
 {
+	struct comedi_dt9812 *devpriv = dev->private;
 	int n;
 
 	for (n = 0; n < insn->n; n++) {
@@ -995,6 +998,7 @@ static int dt9812_ao_rinsn(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
 			   unsigned int *data)
 {
+	struct comedi_dt9812 *devpriv = dev->private;
 	int n;
 	u16 value;
 
@@ -1010,6 +1014,7 @@ static int dt9812_ao_winsn(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
 			   unsigned int *data)
 {
+	struct comedi_dt9812 *devpriv = dev->private;
 	int n;
 
 	for (n = 0; n < insn->n; n++)
@@ -1019,14 +1024,17 @@ static int dt9812_ao_winsn(struct comedi_device *dev,
 
 static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+	struct comedi_dt9812 *devpriv;
 	int i;
 	struct comedi_subdevice *s;
 	int ret;
 
 	dev->board_name = "dt9812";
 
-	if (alloc_private(dev, sizeof(struct comedi_dt9812)) < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
 
 	/*
 	 * Special open routine, since USB unit may be unattached at
@@ -1077,8 +1085,7 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	s->insn_write = &dt9812_ao_winsn;
 	s->insn_read = &dt9812_ao_rinsn;
 
-	printk(KERN_INFO "comedi%d: successfully attached to dt9812.\n",
-	       dev->minor);
+	dev_info(dev->class_dev, "successfully attached to dt9812.\n");
 
 	down(&dt9812_mutex);
 	/* Find a slot for the comedi device */
@@ -1140,17 +1147,15 @@ static int __init usb_dt9812_init(void)
 	/* register with the USB subsystem */
 	result = usb_register(&dt9812_usb_driver);
 	if (result) {
-		printk(KERN_ERR KBUILD_MODNAME
-		       ": usb_register failed. Error number %d\n", result);
+		pr_err("usb_register failed. Error number %d\n", result);
 		return result;
 	}
 	/* register with comedi */
 	result = comedi_driver_register(&dt9812_comedi_driver);
 	if (result) {
 		usb_deregister(&dt9812_usb_driver);
-		printk(KERN_ERR KBUILD_MODNAME
-			": comedi_driver_register failed. Error number %d\n",
-			result);
+		pr_err("comedi_driver_register failed. Error number %d\n",
+		       result);
 	}
 
 	return result;
diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c
index 6f612be..8497a36 100644
--- a/drivers/staging/comedi/drivers/dyna_pci10xx.c
+++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c
@@ -40,8 +40,6 @@
 #include "../comedidev.h"
 #include <linux/mutex.h>
 
-#define PCI_VENDOR_ID_DYNALOG		0x10b5
-
 #define READ_TIMEOUT 50
 
 static const struct comedi_lrange range_pci1050_ai = { 3, {
@@ -179,21 +177,20 @@ static int dyna_pci10xx_do_insn_bits(struct comedi_device *dev,
 	return insn->n;
 }
 
-static int dyna_pci10xx_attach_pci(struct comedi_device *dev,
-				   struct pci_dev *pcidev)
+static int dyna_pci10xx_auto_attach(struct comedi_device *dev,
+					      unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct dyna_pci10xx_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
-
 	dev->board_name = dev->driver->driver_name;
 
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_pci_enable(pcidev, dev->board_name);
 	if (ret)
@@ -269,23 +266,23 @@ static void dyna_pci10xx_detach(struct comedi_device *dev)
 static struct comedi_driver dyna_pci10xx_driver = {
 	.driver_name	= "dyna_pci10xx",
 	.module		= THIS_MODULE,
-	.attach_pci	= dyna_pci10xx_attach_pci,
+	.auto_attach	= dyna_pci10xx_auto_attach,
 	.detach		= dyna_pci10xx_detach,
 };
 
-static int __devinit dyna_pci10xx_pci_probe(struct pci_dev *dev,
+static int dyna_pci10xx_pci_probe(struct pci_dev *dev,
 					    const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &dyna_pci10xx_driver);
 }
 
-static void __devexit dyna_pci10xx_pci_remove(struct pci_dev *dev)
+static void dyna_pci10xx_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(dyna_pci10xx_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_DYNALOG, 0x1050) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_PLX, 0x1050) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, dyna_pci10xx_pci_table);
@@ -294,7 +291,7 @@ static struct pci_driver dyna_pci10xx_pci_driver = {
 	.name		= "dyna_pci10xx",
 	.id_table	= dyna_pci10xx_pci_table,
 	.probe		= dyna_pci10xx_pci_probe,
-	.remove		= __devexit_p(dyna_pci10xx_pci_remove),
+	.remove		= dyna_pci10xx_pci_remove,
 };
 module_comedi_pci_driver(dyna_pci10xx_driver, dyna_pci10xx_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
index ae8e8f4..019c96e 100644
--- a/drivers/staging/comedi/drivers/fl512.c
+++ b/drivers/staging/comedi/drivers/fl512.c
@@ -29,8 +29,6 @@ struct fl512_private {
 	short ao_readback[2];
 };
 
-#define devpriv ((struct fl512_private *) dev->private)
-
 static const struct comedi_lrange range_fl512 = { 4, {
 						      BIP_RANGE(0.5),
 						      BIP_RANGE(1),
@@ -75,6 +73,7 @@ static int fl512_ao_insn(struct comedi_device *dev,
 			 struct comedi_subdevice *s, struct comedi_insn *insn,
 			 unsigned int *data)
 {
+	struct fl512_private *devpriv = dev->private;
 	int n;
 	int chan = CR_CHAN(insn->chanspec);	/* get chan to write */
 	unsigned long iobase = dev->iobase;	/* get base address  */
@@ -99,6 +98,7 @@ static int fl512_ao_insn_readback(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
 				  struct comedi_insn *insn, unsigned int *data)
 {
+	struct fl512_private *devpriv = dev->private;
 	int n;
 	int chan = CR_CHAN(insn->chanspec);
 
@@ -110,6 +110,7 @@ static int fl512_ao_insn_readback(struct comedi_device *dev,
 
 static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+	struct fl512_private *devpriv;
 	unsigned long iobase;
 	int ret;
 
@@ -125,8 +126,11 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	}
 	dev->iobase = iobase;
 	dev->board_name = "fl512";
-	if (alloc_private(dev, sizeof(struct fl512_private)) < 0)
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
 
 #if DEBUG
 	printk(KERN_DEBUG "malloc ok\n");
diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c
index abff660..154598f 100644
--- a/drivers/staging/comedi/drivers/gsc_hpdi.c
+++ b/drivers/staging/comedi/drivers/gsc_hpdi.c
@@ -26,24 +26,26 @@
 ************************************************************************/
 
 /*
+ * Driver: gsc_hpdi
+ * Description: General Standards Corporation High
+ *    Speed Parallel Digital Interface rs485 boards
+ * Author: Frank Mori Hess <fmhess@users.sourceforge.net>
+ * Status: only receive mode works, transmit not supported
+ * Updated: Thu, 01 Nov 2012 16:17:38 +0000
+ * Devices: [General Standards Corporation] PCI-HPDI32 (gsc_hpdi),
+ *   PMC-HPDI32
+ *
+ * Configuration options:
+ *    None.
+ *
+ * Manual configuration of supported devices is not supported; they are
+ * configured automatically.
+ *
+ * There are some additional hpdi models available from GSC for which
+ * support could be added to this driver.
+ */
 
-Driver: gsc_hpdi
-Description: General Standards Corporation High
-    Speed Parallel Digital Interface rs485 boards
-Author: Frank Mori Hess <fmhess@users.sourceforge.net>
-Status: only receive mode works, transmit not supported
-Updated: 2003-02-20
-Devices: [General Standards Corporation] PCI-HPDI32 (gsc_hpdi),
-  PMC-HPDI32
-
-Configuration options:
-   [0] - PCI bus of device (optional)
-   [1] - PCI slot of device (optional)
-
-There are some additional hpdi models available from GSC for which
-support could be added to this driver.
-
-*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/interrupt.h>
 #include "../comedidev.h"
@@ -64,9 +66,9 @@ static int dio_config_block_size(struct comedi_device *dev, unsigned int *data);
 /* #define HPDI_DEBUG      enable debugging code */
 
 #ifdef HPDI_DEBUG
-#define DEBUG_PRINT(format, args...)  printk(format , ## args)
+#define DEBUG_PRINT(format, args...)  pr_debug(format , ## args)
 #else
-#define DEBUG_PRINT(format, args...)
+#define DEBUG_PRINT(format, args...)  no_printk(pr_fmt(format), ## args)
 #endif
 
 #define TIMER_BASE 50		/*  20MHz master clock */
@@ -104,35 +106,11 @@ enum hpdi_registers {
 	INTERRUPT_POLARITY_REG = 0x54,
 };
 
-int command_channel_valid(unsigned int channel)
-{
-	if (channel == 0 || channel > 6) {
-		printk(KERN_WARNING
-		       "gsc_hpdi: bug! invalid cable command channel\n");
-		return 0;
-	}
-	return 1;
-}
-
 /* bit definitions */
 
 enum firmware_revision_bits {
 	FEATURES_REG_PRESENT_BIT = 0x8000,
 };
-int firmware_revision(uint32_t fwr_bits)
-{
-	return fwr_bits & 0xff;
-}
-
-int pcb_revision(uint32_t fwr_bits)
-{
-	return (fwr_bits >> 8) & 0xff;
-}
-
-int hpdi_subid(uint32_t fwr_bits)
-{
-	return (fwr_bits >> 16) & 0xff;
-}
 
 enum board_control_bits {
 	BOARD_RESET_BIT = 0x1,	/* wait 10usec before accessing fifos */
@@ -147,22 +125,6 @@ enum board_control_bits {
 	CABLE_THROTTLE_ENABLE_BIT = 0x20,
 	TEST_MODE_ENABLE_BIT = 0x80000000,
 };
-uint32_t command_discrete_output_bits(unsigned int channel, int output,
-				      int output_value)
-{
-	uint32_t bits = 0;
-
-	if (command_channel_valid(channel) == 0)
-		return 0;
-	if (output) {
-		bits |= 0x1 << (16 + channel);
-		if (output_value)
-			bits |= 0x1 << (24 + channel);
-	} else
-		bits |= 0x1 << (24 + channel);
-
-	return bits;
-}
 
 enum board_status_bits {
 	COMMAND_LINE_STATUS_MASK = 0x7f,
@@ -182,28 +144,17 @@ enum board_status_bits {
 	RX_OVERRUN_BIT = 0x800000,
 };
 
-uint32_t almost_full_bits(unsigned int num_words)
+static uint32_t almost_full_bits(unsigned int num_words)
 {
-/* XXX need to add or subtract one? */
+	/* XXX need to add or subtract one? */
 	return (num_words << 16) & 0xff0000;
 }
 
-uint32_t almost_empty_bits(unsigned int num_words)
+static uint32_t almost_empty_bits(unsigned int num_words)
 {
 	return num_words & 0xffff;
 }
 
-unsigned int almost_full_num_words(uint32_t bits)
-{
-/* XXX need to add or subtract one? */
-	return (bits >> 16) & 0xffff;
-}
-
-unsigned int almost_empty_num_words(uint32_t bits)
-{
-	return bits & 0xffff;
-}
-
 enum features_bits {
 	FIFO_SIZE_PRESENT_BIT = 0x1,
 	FIFO_WORDS_PRESENT_BIT = 0x2,
@@ -225,46 +176,19 @@ enum interrupt_sources {
 	RX_ALMOST_FULL_INTR = 14,
 	RX_FULL_INTR = 15,
 };
-int command_intr_source(unsigned int channel)
-{
-	if (command_channel_valid(channel) == 0)
-		channel = 1;
-	return channel + 1;
-}
 
-uint32_t intr_bit(int interrupt_source)
+static uint32_t intr_bit(int interrupt_source)
 {
 	return 0x1 << interrupt_source;
 }
 
-uint32_t tx_clock_divisor_bits(unsigned int divisor)
-{
-	return divisor & 0xff;
-}
-
-unsigned int fifo_size(uint32_t fifo_size_bits)
+static unsigned int fifo_size(uint32_t fifo_size_bits)
 {
 	return fifo_size_bits & 0xfffff;
 }
 
-unsigned int fifo_words(uint32_t fifo_words_bits)
-{
-	return fifo_words_bits & 0xfffff;
-}
-
-uint32_t intr_edge_bit(int interrupt_source)
-{
-	return 0x1 << interrupt_source;
-}
-
-uint32_t intr_active_high_bit(int interrupt_source)
-{
-	return 0x1 << interrupt_source;
-}
-
 struct hpdi_board {
-
-	char *name;
+	const char *name;	/*  board name */
 	int device_id;		/*  pci device id */
 	int subdevice_id;	/*  pci subdevice id */
 };
@@ -284,17 +208,7 @@ static const struct hpdi_board hpdi_boards[] = {
 #endif
 };
 
-static inline struct hpdi_board *board(const struct comedi_device *dev)
-{
-	return (struct hpdi_board *)dev->board_ptr;
-}
-
 struct hpdi_private {
-
-	struct pci_dev *hw_dev;	/*  pointer to board's pci_dev struct */
-	/*  base addresses (physical) */
-	resource_size_t plx9080_phys_iobase;
-	resource_size_t hpdi_phys_iobase;
 	/*  base addresses (ioremapped) */
 	void __iomem *plx9080_iobase;
 	void __iomem *hpdi_iobase;
@@ -321,27 +235,24 @@ struct hpdi_private {
 	unsigned dio_config_output:1;
 };
 
-static inline struct hpdi_private *priv(struct comedi_device *dev)
-{
-	return dev->private;
-}
-
 static int dio_config_insn(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
 			   unsigned int *data)
 {
+	struct hpdi_private *devpriv = dev->private;
+
 	switch (data[0]) {
 	case INSN_CONFIG_DIO_OUTPUT:
-		priv(dev)->dio_config_output = 1;
+		devpriv->dio_config_output = 1;
 		return insn->n;
 		break;
 	case INSN_CONFIG_DIO_INPUT:
-		priv(dev)->dio_config_output = 0;
+		devpriv->dio_config_output = 0;
 		return insn->n;
 		break;
 	case INSN_CONFIG_DIO_QUERY:
 		data[1] =
-		    priv(dev)->dio_config_output ? COMEDI_OUTPUT : COMEDI_INPUT;
+		    devpriv->dio_config_output ? COMEDI_OUTPUT : COMEDI_INPUT;
 		return insn->n;
 		break;
 	case INSN_CONFIG_BLOCK_SIZE:
@@ -356,21 +267,24 @@ static int dio_config_insn(struct comedi_device *dev,
 
 static void disable_plx_interrupts(struct comedi_device *dev)
 {
-	writel(0, priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
+	struct hpdi_private *devpriv = dev->private;
+
+	writel(0, devpriv->plx9080_iobase + PLX_INTRCS_REG);
 }
 
 /* initialize plx9080 chip */
 static void init_plx9080(struct comedi_device *dev)
 {
+	struct hpdi_private *devpriv = dev->private;
 	uint32_t bits;
-	void __iomem *plx_iobase = priv(dev)->plx9080_iobase;
+	void __iomem *plx_iobase = devpriv->plx9080_iobase;
 
 	/*  plx9080 dump */
 	DEBUG_PRINT(" plx interrupt status 0x%x\n",
 		    readl(plx_iobase + PLX_INTRCS_REG));
 	DEBUG_PRINT(" plx id bits 0x%x\n", readl(plx_iobase + PLX_ID_REG));
 	DEBUG_PRINT(" plx control reg 0x%x\n",
-		    readl(priv(dev)->plx9080_iobase + PLX_CONTROL_REG));
+		    readl(devpriv->plx9080_iobase + PLX_CONTROL_REG));
 
 	DEBUG_PRINT(" plx revision 0x%x\n",
 		    readl(plx_iobase + PLX_REVISION_REG));
@@ -396,7 +310,7 @@ static void init_plx9080(struct comedi_device *dev)
 #else
 	bits = 0;
 #endif
-	writel(bits, priv(dev)->plx9080_iobase + PLX_BIGEND_REG);
+	writel(bits, devpriv->plx9080_iobase + PLX_BIGEND_REG);
 
 	disable_plx_interrupts(dev);
 
@@ -457,28 +371,29 @@ static int setup_subdevices(struct comedi_device *dev)
 
 static int init_hpdi(struct comedi_device *dev)
 {
+	struct hpdi_private *devpriv = dev->private;
 	uint32_t plx_intcsr_bits;
 
-	writel(BOARD_RESET_BIT, priv(dev)->hpdi_iobase + BOARD_CONTROL_REG);
+	writel(BOARD_RESET_BIT, devpriv->hpdi_iobase + BOARD_CONTROL_REG);
 	udelay(10);
 
 	writel(almost_empty_bits(32) | almost_full_bits(32),
-	       priv(dev)->hpdi_iobase + RX_PROG_ALMOST_REG);
+	       devpriv->hpdi_iobase + RX_PROG_ALMOST_REG);
 	writel(almost_empty_bits(32) | almost_full_bits(32),
-	       priv(dev)->hpdi_iobase + TX_PROG_ALMOST_REG);
+	       devpriv->hpdi_iobase + TX_PROG_ALMOST_REG);
 
-	priv(dev)->tx_fifo_size = fifo_size(readl(priv(dev)->hpdi_iobase +
+	devpriv->tx_fifo_size = fifo_size(readl(devpriv->hpdi_iobase +
 						  TX_FIFO_SIZE_REG));
-	priv(dev)->rx_fifo_size = fifo_size(readl(priv(dev)->hpdi_iobase +
+	devpriv->rx_fifo_size = fifo_size(readl(devpriv->hpdi_iobase +
 						  RX_FIFO_SIZE_REG));
 
-	writel(0, priv(dev)->hpdi_iobase + INTERRUPT_CONTROL_REG);
+	writel(0, devpriv->hpdi_iobase + INTERRUPT_CONTROL_REG);
 
 	/*  enable interrupts */
 	plx_intcsr_bits =
 	    ICS_AERR | ICS_PERR | ICS_PIE | ICS_PLIE | ICS_PAIE | ICS_LIE |
 	    ICS_DMA0_E;
-	writel(plx_intcsr_bits, priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
+	writel(plx_intcsr_bits, devpriv->plx9080_iobase + PLX_INTRCS_REG);
 
 	return 0;
 }
@@ -487,6 +402,7 @@ static int init_hpdi(struct comedi_device *dev)
 static int setup_dma_descriptors(struct comedi_device *dev,
 				 unsigned int transfer_size)
 {
+	struct hpdi_private *devpriv = dev->private;
 	unsigned int buffer_index, buffer_offset;
 	uint32_t next_bits = PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT |
 	    PLX_XFER_LOCAL_TO_PCI;
@@ -500,25 +416,25 @@ static int setup_dma_descriptors(struct comedi_device *dev,
 
 	DEBUG_PRINT(" transfer_size %i\n", transfer_size);
 	DEBUG_PRINT(" descriptors at 0x%lx\n",
-		    (unsigned long)priv(dev)->dma_desc_phys_addr);
+		    (unsigned long)devpriv->dma_desc_phys_addr);
 
 	buffer_offset = 0;
 	buffer_index = 0;
 	for (i = 0; i < NUM_DMA_DESCRIPTORS &&
 	     buffer_index < NUM_DMA_BUFFERS; i++) {
-		priv(dev)->dma_desc[i].pci_start_addr =
-		    cpu_to_le32(priv(dev)->dio_buffer_phys_addr[buffer_index] +
+		devpriv->dma_desc[i].pci_start_addr =
+		    cpu_to_le32(devpriv->dio_buffer_phys_addr[buffer_index] +
 				buffer_offset);
-		priv(dev)->dma_desc[i].local_start_addr = cpu_to_le32(FIFO_REG);
-		priv(dev)->dma_desc[i].transfer_size =
+		devpriv->dma_desc[i].local_start_addr = cpu_to_le32(FIFO_REG);
+		devpriv->dma_desc[i].transfer_size =
 		    cpu_to_le32(transfer_size);
-		priv(dev)->dma_desc[i].next =
-		    cpu_to_le32((priv(dev)->dma_desc_phys_addr + (i +
+		devpriv->dma_desc[i].next =
+		    cpu_to_le32((devpriv->dma_desc_phys_addr + (i +
 								  1) *
-				 sizeof(priv(dev)->dma_desc[0])) | next_bits);
+				 sizeof(devpriv->dma_desc[0])) | next_bits);
 
-		priv(dev)->desc_dio_buffer[i] =
-		    priv(dev)->dio_buffer[buffer_index] +
+		devpriv->desc_dio_buffer[i] =
+		    devpriv->dio_buffer[buffer_index] +
 		    (buffer_offset / sizeof(uint32_t));
 
 		buffer_offset += transfer_size;
@@ -529,128 +445,110 @@ static int setup_dma_descriptors(struct comedi_device *dev,
 
 		DEBUG_PRINT(" desc %i\n", i);
 		DEBUG_PRINT(" start addr virt 0x%p, phys 0x%lx\n",
-			    priv(dev)->desc_dio_buffer[i],
-			    (unsigned long)priv(dev)->dma_desc[i].
+			    devpriv->desc_dio_buffer[i],
+			    (unsigned long)devpriv->dma_desc[i].
 			    pci_start_addr);
 		DEBUG_PRINT(" next 0x%lx\n",
-			    (unsigned long)priv(dev)->dma_desc[i].next);
+			    (unsigned long)devpriv->dma_desc[i].next);
 	}
-	priv(dev)->num_dma_descriptors = i;
+	devpriv->num_dma_descriptors = i;
 	/*  fix last descriptor to point back to first */
-	priv(dev)->dma_desc[i - 1].next =
-	    cpu_to_le32(priv(dev)->dma_desc_phys_addr | next_bits);
+	devpriv->dma_desc[i - 1].next =
+	    cpu_to_le32(devpriv->dma_desc_phys_addr | next_bits);
 	DEBUG_PRINT(" desc %i next fixup 0x%lx\n", i - 1,
-		    (unsigned long)priv(dev)->dma_desc[i - 1].next);
+		    (unsigned long)devpriv->dma_desc[i - 1].next);
 
-	priv(dev)->block_size = transfer_size;
+	devpriv->block_size = transfer_size;
 
 	return transfer_size;
 }
 
-static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static const struct hpdi_board *hpdi_find_board(struct pci_dev *pcidev)
 {
-	struct pci_dev *pcidev;
-	int i;
-	int retval;
+	unsigned int i;
 
-	printk(KERN_WARNING "comedi%d: gsc_hpdi\n", dev->minor);
+	for (i = 0; i < ARRAY_SIZE(hpdi_boards); i++)
+		if (pcidev->device == hpdi_boards[i].device_id &&
+		    pcidev->subsystem_device == hpdi_boards[i].subdevice_id)
+			return &hpdi_boards[i];
+	return NULL;
+}
 
-	if (alloc_private(dev, sizeof(struct hpdi_private)) < 0)
-		return -ENOMEM;
+static int hpdi_auto_attach(struct comedi_device *dev,
+				      unsigned long context_unused)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	const struct hpdi_board *thisboard;
+	struct hpdi_private *devpriv;
+	int i;
+	int retval;
 
-	pcidev = NULL;
-	for (i = 0; i < ARRAY_SIZE(hpdi_boards) &&
-		    dev->board_ptr == NULL; i++) {
-		do {
-			pcidev = pci_get_subsys(PCI_VENDOR_ID_PLX,
-						hpdi_boards[i].device_id,
-						PCI_VENDOR_ID_PLX,
-						hpdi_boards[i].subdevice_id,
-						pcidev);
-			/*  was a particular bus/slot requested? */
-			if (it->options[0] || it->options[1]) {
-				/*  are we on the wrong bus/slot? */
-				if (pcidev->bus->number != it->options[0] ||
-				    PCI_SLOT(pcidev->devfn) != it->options[1])
-					continue;
-			}
-			if (pcidev) {
-				priv(dev)->hw_dev = pcidev;
-				dev->board_ptr = hpdi_boards + i;
-				break;
-			}
-		} while (pcidev != NULL);
-	}
-	if (dev->board_ptr == NULL) {
-		printk(KERN_WARNING "gsc_hpdi: no hpdi card found\n");
-		return -EIO;
+	thisboard = hpdi_find_board(pcidev);
+	if (!thisboard) {
+		dev_err(dev->class_dev, "gsc_hpdi: pci %s not supported\n",
+			pci_name(pcidev));
+		return -EINVAL;
 	}
+	dev->board_ptr = thisboard;
+	dev->board_name = thisboard->name;
 
-	printk(KERN_WARNING
-	       "gsc_hpdi: found %s on bus %i, slot %i\n", board(dev)->name,
-	       pcidev->bus->number, PCI_SLOT(pcidev->devfn));
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
-	if (comedi_pci_enable(pcidev, dev->driver->driver_name)) {
-		printk(KERN_WARNING
-		       " failed enable PCI device and request regions\n");
+	if (comedi_pci_enable(pcidev, dev->board_name)) {
+		dev_warn(dev->class_dev,
+			 "failed enable PCI device and request regions\n");
 		return -EIO;
 	}
+	dev->iobase = 1;	/* the "detach" needs this */
 	pci_set_master(pcidev);
 
-	/* Initialize dev->board_name */
-	dev->board_name = board(dev)->name;
-
-	priv(dev)->plx9080_phys_iobase =
-	    pci_resource_start(pcidev, PLX9080_BADDRINDEX);
-	priv(dev)->hpdi_phys_iobase =
-	    pci_resource_start(pcidev, HPDI_BADDRINDEX);
-
-	/*  remap, won't work with 2.0 kernels but who cares */
-	priv(dev)->plx9080_iobase = ioremap(priv(dev)->plx9080_phys_iobase,
-					    pci_resource_len(pcidev,
-					    PLX9080_BADDRINDEX));
-	priv(dev)->hpdi_iobase =
-	    ioremap(priv(dev)->hpdi_phys_iobase,
-		    pci_resource_len(pcidev, HPDI_BADDRINDEX));
-	if (!priv(dev)->plx9080_iobase || !priv(dev)->hpdi_iobase) {
-		printk(KERN_WARNING " failed to remap io memory\n");
+	devpriv->plx9080_iobase =
+		ioremap(pci_resource_start(pcidev, PLX9080_BADDRINDEX),
+			pci_resource_len(pcidev, PLX9080_BADDRINDEX));
+	devpriv->hpdi_iobase =
+		ioremap(pci_resource_start(pcidev, HPDI_BADDRINDEX),
+			pci_resource_len(pcidev, HPDI_BADDRINDEX));
+	if (!devpriv->plx9080_iobase || !devpriv->hpdi_iobase) {
+		dev_warn(dev->class_dev, "failed to remap io memory\n");
 		return -ENOMEM;
 	}
 
-	DEBUG_PRINT(" plx9080 remapped to 0x%p\n", priv(dev)->plx9080_iobase);
-	DEBUG_PRINT(" hpdi remapped to 0x%p\n", priv(dev)->hpdi_iobase);
+	DEBUG_PRINT(" plx9080 remapped to 0x%p\n", devpriv->plx9080_iobase);
+	DEBUG_PRINT(" hpdi remapped to 0x%p\n", devpriv->hpdi_iobase);
 
 	init_plx9080(dev);
 
 	/*  get irq */
 	if (request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED,
-			dev->driver->driver_name, dev)) {
-		printk(KERN_WARNING
-		       " unable to allocate irq %u\n", pcidev->irq);
+			dev->board_name, dev)) {
+		dev_warn(dev->class_dev,
+			 "unable to allocate irq %u\n", pcidev->irq);
 		return -EINVAL;
 	}
 	dev->irq = pcidev->irq;
 
-	printk(KERN_WARNING " irq %u\n", dev->irq);
+	dev_dbg(dev->class_dev, " irq %u\n", dev->irq);
 
 	/*  allocate pci dma buffers */
 	for (i = 0; i < NUM_DMA_BUFFERS; i++) {
-		priv(dev)->dio_buffer[i] =
-		    pci_alloc_consistent(priv(dev)->hw_dev, DMA_BUFFER_SIZE,
-					 &priv(dev)->dio_buffer_phys_addr[i]);
+		devpriv->dio_buffer[i] =
+		    pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE,
+					 &devpriv->dio_buffer_phys_addr[i]);
 		DEBUG_PRINT("dio_buffer at virt 0x%p, phys 0x%lx\n",
-			    priv(dev)->dio_buffer[i],
-			    (unsigned long)priv(dev)->dio_buffer_phys_addr[i]);
+			    devpriv->dio_buffer[i],
+			    (unsigned long)devpriv->dio_buffer_phys_addr[i]);
 	}
 	/*  allocate dma descriptors */
-	priv(dev)->dma_desc = pci_alloc_consistent(priv(dev)->hw_dev,
-						   sizeof(struct plx_dma_desc) *
-						   NUM_DMA_DESCRIPTORS,
-						   &priv(dev)->
-						   dma_desc_phys_addr);
-	if (priv(dev)->dma_desc_phys_addr & 0xf) {
-		printk(KERN_WARNING
-		       " dma descriptors not quad-word aligned (bug)\n");
+	devpriv->dma_desc = pci_alloc_consistent(pcidev,
+						 sizeof(struct plx_dma_desc) *
+						 NUM_DMA_DESCRIPTORS,
+						 &devpriv->dma_desc_phys_addr);
+	if (devpriv->dma_desc_phys_addr & 0xf) {
+		dev_warn(dev->class_dev,
+			 " dma descriptors not quad-word aligned (bug)\n");
 		return -EIO;
 	}
 
@@ -667,39 +565,37 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 static void hpdi_detach(struct comedi_device *dev)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct hpdi_private *devpriv = dev->private;
 	unsigned int i;
 
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if ((priv(dev)) && (priv(dev)->hw_dev)) {
-		if (priv(dev)->plx9080_iobase) {
+	if (devpriv) {
+		if (devpriv->plx9080_iobase) {
 			disable_plx_interrupts(dev);
-			iounmap(priv(dev)->plx9080_iobase);
+			iounmap(devpriv->plx9080_iobase);
 		}
-		if (priv(dev)->hpdi_iobase)
-			iounmap(priv(dev)->hpdi_iobase);
+		if (devpriv->hpdi_iobase)
+			iounmap(devpriv->hpdi_iobase);
 		/*  free pci dma buffers */
 		for (i = 0; i < NUM_DMA_BUFFERS; i++) {
-			if (priv(dev)->dio_buffer[i])
-				pci_free_consistent(priv(dev)->hw_dev,
+			if (devpriv->dio_buffer[i])
+				pci_free_consistent(pcidev,
 						    DMA_BUFFER_SIZE,
-						    priv(dev)->
-						    dio_buffer[i],
-						    priv
-						    (dev)->dio_buffer_phys_addr
-						    [i]);
+						    devpriv->dio_buffer[i],
+						    devpriv->
+						    dio_buffer_phys_addr[i]);
 		}
 		/*  free dma descriptors */
-		if (priv(dev)->dma_desc)
-			pci_free_consistent(priv(dev)->hw_dev,
-					    sizeof(struct plx_dma_desc)
-					    * NUM_DMA_DESCRIPTORS,
-					    priv(dev)->dma_desc,
-					    priv(dev)->
-					    dma_desc_phys_addr);
-		if (priv(dev)->hpdi_phys_iobase)
-			comedi_pci_disable(priv(dev)->hw_dev);
-		pci_dev_put(priv(dev)->hw_dev);
+		if (devpriv->dma_desc)
+			pci_free_consistent(pcidev,
+					    sizeof(struct plx_dma_desc) *
+					    NUM_DMA_DESCRIPTORS,
+					    devpriv->dma_desc,
+					    devpriv->dma_desc_phys_addr);
+		if (dev->iobase)
+			comedi_pci_disable(pcidev);
 	}
 }
 
@@ -745,29 +641,20 @@ static int di_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
 	if (!cmd->chanlist_len) {
 		cmd->chanlist_len = 32;
-		err++;
-	}
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
+		err |= -EINVAL;
 	}
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 
 	switch (cmd->stop_src) {
 	case TRIG_COUNT:
-		if (!cmd->stop_arg) {
-			cmd->stop_arg = 1;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
 		break;
 	case TRIG_NONE:
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 		break;
 	default:
 		break;
@@ -803,7 +690,9 @@ static int di_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 static int hpdi_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_cmd *cmd)
 {
-	if (priv(dev)->dio_config_output)
+	struct hpdi_private *devpriv = dev->private;
+
+	if (devpriv->dio_config_output)
 		return -EINVAL;
 	else
 		return di_cmd_test(dev, s, cmd);
@@ -812,12 +701,15 @@ static int hpdi_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 static inline void hpdi_writel(struct comedi_device *dev, uint32_t bits,
 			       unsigned int offset)
 {
-	writel(bits | priv(dev)->bits[offset / sizeof(uint32_t)],
-	       priv(dev)->hpdi_iobase + offset);
+	struct hpdi_private *devpriv = dev->private;
+
+	writel(bits | devpriv->bits[offset / sizeof(uint32_t)],
+	       devpriv->hpdi_iobase + offset);
 }
 
 static int di_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct hpdi_private *devpriv = dev->private;
 	uint32_t bits;
 	unsigned long flags;
 	struct comedi_async *async = s->async;
@@ -829,39 +721,39 @@ static int di_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	abort_dma(dev, 0);
 
-	priv(dev)->dma_desc_index = 0;
+	devpriv->dma_desc_index = 0;
 
 	/* These register are supposedly unused during chained dma,
 	 * but I have found that left over values from last operation
 	 * occasionally cause problems with transfer of first dma
 	 * block.  Initializing them to zero seems to fix the problem. */
-	writel(0, priv(dev)->plx9080_iobase + PLX_DMA0_TRANSFER_SIZE_REG);
-	writel(0, priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG);
-	writel(0, priv(dev)->plx9080_iobase + PLX_DMA0_LOCAL_ADDRESS_REG);
+	writel(0, devpriv->plx9080_iobase + PLX_DMA0_TRANSFER_SIZE_REG);
+	writel(0, devpriv->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG);
+	writel(0, devpriv->plx9080_iobase + PLX_DMA0_LOCAL_ADDRESS_REG);
 	/*  give location of first dma descriptor */
 	bits =
-	    priv(dev)->dma_desc_phys_addr | PLX_DESC_IN_PCI_BIT |
+	    devpriv->dma_desc_phys_addr | PLX_DESC_IN_PCI_BIT |
 	    PLX_INTR_TERM_COUNT | PLX_XFER_LOCAL_TO_PCI;
-	writel(bits, priv(dev)->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG);
+	writel(bits, devpriv->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG);
 
 	/*  spinlock for plx dma control/status reg */
 	spin_lock_irqsave(&dev->spinlock, flags);
 	/*  enable dma transfer */
 	writeb(PLX_DMA_EN_BIT | PLX_DMA_START_BIT | PLX_CLEAR_DMA_INTR_BIT,
-	       priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+	       devpriv->plx9080_iobase + PLX_DMA0_CS_REG);
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
 	if (cmd->stop_src == TRIG_COUNT)
-		priv(dev)->dio_count = cmd->stop_arg;
+		devpriv->dio_count = cmd->stop_arg;
 	else
-		priv(dev)->dio_count = 1;
+		devpriv->dio_count = 1;
 
 	/*  clear over/under run status flags */
 	writel(RX_UNDERRUN_BIT | RX_OVERRUN_BIT,
-	       priv(dev)->hpdi_iobase + BOARD_STATUS_REG);
+	       devpriv->hpdi_iobase + BOARD_STATUS_REG);
 	/*  enable interrupts */
 	writel(intr_bit(RX_FULL_INTR),
-	       priv(dev)->hpdi_iobase + INTERRUPT_CONTROL_REG);
+	       devpriv->hpdi_iobase + INTERRUPT_CONTROL_REG);
 
 	DEBUG_PRINT("hpdi: starting rx\n");
 	hpdi_writel(dev, RX_ENABLE_BIT, BOARD_CONTROL_REG);
@@ -871,7 +763,9 @@ static int di_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static int hpdi_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	if (priv(dev)->dio_config_output)
+	struct hpdi_private *devpriv = dev->private;
+
+	if (devpriv->dio_config_output)
 		return -EINVAL;
 	else
 		return di_cmd(dev, s);
@@ -879,6 +773,7 @@ static int hpdi_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
 {
+	struct hpdi_private *devpriv = dev->private;
 	struct comedi_async *async = dev->read_subdev->async;
 	uint32_t next_transfer_addr;
 	int j;
@@ -887,37 +782,37 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
 
 	if (channel)
 		pci_addr_reg =
-		    priv(dev)->plx9080_iobase + PLX_DMA1_PCI_ADDRESS_REG;
+		    devpriv->plx9080_iobase + PLX_DMA1_PCI_ADDRESS_REG;
 	else
 		pci_addr_reg =
-		    priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG;
+		    devpriv->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG;
 
 	/*  loop until we have read all the full buffers */
 	j = 0;
 	for (next_transfer_addr = readl(pci_addr_reg);
 	     (next_transfer_addr <
-	      le32_to_cpu(priv(dev)->dma_desc[priv(dev)->dma_desc_index].
+	      le32_to_cpu(devpriv->dma_desc[devpriv->dma_desc_index].
 			  pci_start_addr)
 	      || next_transfer_addr >=
-	      le32_to_cpu(priv(dev)->dma_desc[priv(dev)->dma_desc_index].
-			  pci_start_addr) + priv(dev)->block_size)
-	     && j < priv(dev)->num_dma_descriptors; j++) {
+	      le32_to_cpu(devpriv->dma_desc[devpriv->dma_desc_index].
+			  pci_start_addr) + devpriv->block_size)
+	     && j < devpriv->num_dma_descriptors; j++) {
 		/*  transfer data from dma buffer to comedi buffer */
-		num_samples = priv(dev)->block_size / sizeof(uint32_t);
+		num_samples = devpriv->block_size / sizeof(uint32_t);
 		if (async->cmd.stop_src == TRIG_COUNT) {
-			if (num_samples > priv(dev)->dio_count)
-				num_samples = priv(dev)->dio_count;
-			priv(dev)->dio_count -= num_samples;
+			if (num_samples > devpriv->dio_count)
+				num_samples = devpriv->dio_count;
+			devpriv->dio_count -= num_samples;
 		}
 		cfc_write_array_to_buffer(dev->read_subdev,
-					  priv(dev)->desc_dio_buffer[priv(dev)->
+					  devpriv->desc_dio_buffer[devpriv->
 								     dma_desc_index],
 					  num_samples * sizeof(uint32_t));
-		priv(dev)->dma_desc_index++;
-		priv(dev)->dma_desc_index %= priv(dev)->num_dma_descriptors;
+		devpriv->dma_desc_index++;
+		devpriv->dma_desc_index %= devpriv->num_dma_descriptors;
 
 		DEBUG_PRINT("next desc addr 0x%lx\n", (unsigned long)
-			    priv(dev)->dma_desc[priv(dev)->dma_desc_index].
+			    devpriv->dma_desc[devpriv->dma_desc_index].
 			    next);
 		DEBUG_PRINT("pci addr reg 0x%x\n", next_transfer_addr);
 	}
@@ -927,6 +822,7 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
 static irqreturn_t handle_interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct hpdi_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
 	struct comedi_async *async = s->async;
 	uint32_t hpdi_intr_status, hpdi_board_status;
@@ -938,26 +834,26 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 	if (!dev->attached)
 		return IRQ_NONE;
 
-	plx_status = readl(priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
+	plx_status = readl(devpriv->plx9080_iobase + PLX_INTRCS_REG);
 	if ((plx_status & (ICS_DMA0_A | ICS_DMA1_A | ICS_LIA)) == 0)
 		return IRQ_NONE;
 
-	hpdi_intr_status = readl(priv(dev)->hpdi_iobase + INTERRUPT_STATUS_REG);
-	hpdi_board_status = readl(priv(dev)->hpdi_iobase + BOARD_STATUS_REG);
+	hpdi_intr_status = readl(devpriv->hpdi_iobase + INTERRUPT_STATUS_REG);
+	hpdi_board_status = readl(devpriv->hpdi_iobase + BOARD_STATUS_REG);
 
 	async->events = 0;
 
 	if (hpdi_intr_status) {
 		DEBUG_PRINT("hpdi: intr status 0x%x, ", hpdi_intr_status);
 		writel(hpdi_intr_status,
-		       priv(dev)->hpdi_iobase + INTERRUPT_STATUS_REG);
+		       devpriv->hpdi_iobase + INTERRUPT_STATUS_REG);
 	}
 	/*  spin lock makes sure no one else changes plx dma control reg */
 	spin_lock_irqsave(&dev->spinlock, flags);
-	dma0_status = readb(priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+	dma0_status = readb(devpriv->plx9080_iobase + PLX_DMA0_CS_REG);
 	if (plx_status & ICS_DMA0_A) {	/*  dma chan 0 interrupt */
 		writeb((dma0_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT,
-		       priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
+		       devpriv->plx9080_iobase + PLX_DMA0_CS_REG);
 
 		DEBUG_PRINT("dma0 status 0x%x\n", dma0_status);
 		if (dma0_status & PLX_DMA_EN_BIT)
@@ -968,10 +864,10 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 
 	/*  spin lock makes sure no one else changes plx dma control reg */
 	spin_lock_irqsave(&dev->spinlock, flags);
-	dma1_status = readb(priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG);
+	dma1_status = readb(devpriv->plx9080_iobase + PLX_DMA1_CS_REG);
 	if (plx_status & ICS_DMA1_A) {	/*  XXX *//*  dma chan 1 interrupt */
 		writeb((dma1_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT,
-		       priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG);
+		       devpriv->plx9080_iobase + PLX_DMA1_CS_REG);
 		DEBUG_PRINT("dma1 status 0x%x\n", dma1_status);
 
 		DEBUG_PRINT(" cleared dma ch1 interrupt\n");
@@ -980,8 +876,8 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 
 	/*  clear possible plx9080 interrupt sources */
 	if (plx_status & ICS_LDIA) {	/*  clear local doorbell interrupt */
-		plx_bits = readl(priv(dev)->plx9080_iobase + PLX_DBR_OUT_REG);
-		writel(plx_bits, priv(dev)->plx9080_iobase + PLX_DBR_OUT_REG);
+		plx_bits = readl(devpriv->plx9080_iobase + PLX_DBR_OUT_REG);
+		writel(plx_bits, devpriv->plx9080_iobase + PLX_DBR_OUT_REG);
 		DEBUG_PRINT(" cleared local doorbell bits 0x%x\n", plx_bits);
 	}
 
@@ -989,7 +885,7 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 		comedi_error(dev, "rx fifo overrun");
 		async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 		DEBUG_PRINT("dma0_status 0x%x\n",
-			    (int)readb(priv(dev)->plx9080_iobase +
+			    (int)readb(devpriv->plx9080_iobase +
 				       PLX_DMA0_CS_REG));
 	}
 
@@ -998,7 +894,7 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 		async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 	}
 
-	if (priv(dev)->dio_count == 0)
+	if (devpriv->dio_count == 0)
 		async->events |= COMEDI_CB_EOA;
 
 	DEBUG_PRINT("board status 0x%x, ", hpdi_board_status);
@@ -1013,21 +909,24 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 
 static void abort_dma(struct comedi_device *dev, unsigned int channel)
 {
+	struct hpdi_private *devpriv = dev->private;
 	unsigned long flags;
 
 	/*  spinlock for plx dma control/status reg */
 	spin_lock_irqsave(&dev->spinlock, flags);
 
-	plx9080_abort_dma(priv(dev)->plx9080_iobase, channel);
+	plx9080_abort_dma(devpriv->plx9080_iobase, channel);
 
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 }
 
 static int hpdi_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct hpdi_private *devpriv = dev->private;
+
 	hpdi_writel(dev, 0, BOARD_CONTROL_REG);
 
-	writel(0, priv(dev)->hpdi_iobase + INTERRUPT_CONTROL_REG);
+	writel(0, devpriv->hpdi_iobase + INTERRUPT_CONTROL_REG);
 
 	abort_dma(dev, 0);
 
@@ -1037,17 +936,17 @@ static int hpdi_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 static struct comedi_driver gsc_hpdi_driver = {
 	.driver_name	= "gsc_hpdi",
 	.module		= THIS_MODULE,
-	.attach		= hpdi_attach,
+	.auto_attach	= hpdi_auto_attach,
 	.detach		= hpdi_detach,
 };
 
-static int __devinit gsc_hpdi_pci_probe(struct pci_dev *dev,
+static int gsc_hpdi_pci_probe(struct pci_dev *dev,
 					const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &gsc_hpdi_driver);
 }
 
-static void __devexit gsc_hpdi_pci_remove(struct pci_dev *dev)
+static void gsc_hpdi_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -1063,7 +962,7 @@ static struct pci_driver gsc_hpdi_pci_driver = {
 	.name		= "gsc_hpdi",
 	.id_table	= gsc_hpdi_pci_table,
 	.probe		= gsc_hpdi_pci_probe,
-	.remove		= __devexit_p(gsc_hpdi_pci_remove)
+	.remove		= gsc_hpdi_pci_remove
 };
 module_comedi_pci_driver(gsc_hpdi_driver, gsc_hpdi_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
index d696d4d..a91a448 100644
--- a/drivers/staging/comedi/drivers/icp_multi.c
+++ b/drivers/staging/comedi/drivers/icp_multi.c
@@ -494,21 +494,21 @@ static int icp_multi_reset(struct comedi_device *dev)
 	return 0;
 }
 
-static int icp_multi_attach_pci(struct comedi_device *dev,
-				struct pci_dev *pcidev)
+static int icp_multi_auto_attach(struct comedi_device *dev,
+					   unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct icp_multi_private *devpriv;
 	struct comedi_subdevice *s;
 	resource_size_t iobase;
 	int ret;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
 	dev->board_name = dev->driver->driver_name;
 
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret < 0)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_pci_enable(pcidev, dev->board_name);
 	if (ret)
@@ -613,17 +613,17 @@ static void icp_multi_detach(struct comedi_device *dev)
 static struct comedi_driver icp_multi_driver = {
 	.driver_name	= "icp_multi",
 	.module		= THIS_MODULE,
-	.attach_pci	= icp_multi_attach_pci,
+	.auto_attach	= icp_multi_auto_attach,
 	.detach		= icp_multi_detach,
 };
 
-static int __devinit icp_multi_pci_probe(struct pci_dev *dev,
+static int icp_multi_pci_probe(struct pci_dev *dev,
 					   const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &icp_multi_driver);
 }
 
-static void __devexit icp_multi_pci_remove(struct pci_dev *dev)
+static void icp_multi_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -638,7 +638,7 @@ static struct pci_driver icp_multi_pci_driver = {
 	.name		= "icp_multi",
 	.id_table	= icp_multi_pci_table,
 	.probe		= icp_multi_pci_probe,
-	.remove		= __devexit_p(icp_multi_pci_remove),
+	.remove		= icp_multi_pci_remove,
 };
 module_comedi_pci_driver(icp_multi_driver, icp_multi_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
index 65ff1c9..93584e2 100644
--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
+++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
@@ -156,7 +156,6 @@ struct pci20xxx_private {
 	union pci20xxx_subdev_private subdev_private[PCI20000_MODULES];
 };
 
-#define devpriv ((struct pci20xxx_private *)dev->private)
 #define CHAN (CR_CHAN(it->chanlist[0]))
 
 static int pci20006_init(struct comedi_device *dev, struct comedi_subdevice *s,
@@ -196,6 +195,7 @@ static int pci20xxx_dio_init(struct comedi_device *dev,
 static int pci20xxx_attach(struct comedi_device *dev,
 			   struct comedi_devconfig *it)
 {
+	struct pci20xxx_private *devpriv;
 	unsigned char i;
 	int ret;
 	int id;
@@ -206,22 +206,23 @@ static int pci20xxx_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
-	ret = alloc_private(dev, sizeof(struct pci20xxx_private));
-	if (ret < 0)
-		return ret;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	devpriv->ioaddr = (void __iomem *)(unsigned long)it->options[0];
 	dev->board_name = "pci20kc";
 
 	/* Check PCI-20001 C-2A Carrier Board ID */
 	if ((readb(devpriv->ioaddr) & PCI20000_ID) != PCI20000_ID) {
-		printk(KERN_WARNING "comedi%d: ii_pci20kc PCI-20001"
-		       " C-2A Carrier Board at base=0x%p not found !\n",
-		       dev->minor, devpriv->ioaddr);
+		dev_warn(dev->class_dev,
+			 "PCI-20001 C-2A Carrier Board at base=0x%p not found !\n",
+			 devpriv->ioaddr);
 		return -EINVAL;
 	}
-	printk(KERN_INFO "comedi%d: ii_pci20kc: PCI-20001 C-2A at base=0x%p\n",
-	       dev->minor, devpriv->ioaddr);
+	dev_info(dev->class_dev, "PCI-20001 C-2A at base=0x%p\n",
+		 devpriv->ioaddr);
 
 	for (i = 0; i < PCI20000_MODULES; i++) {
 		s = &dev->subdevices[i];
@@ -234,23 +235,21 @@ static int pci20xxx_attach(struct comedi_device *dev,
 			    devpriv->ioaddr + (i + 1) * PCI20000_OFFSET;
 			pci20006_init(dev, s, it->options[2 * i + 2],
 				      it->options[2 * i + 3]);
-			printk(KERN_INFO "comedi%d: "
-			       "ii_pci20kc PCI-20006 module in slot %d\n",
-			       dev->minor, i + 1);
+			dev_info(dev->class_dev,
+				 "PCI-20006 module in slot %d\n", i + 1);
 			break;
 		case PCI20341_ID:
 			sdp->pci20341.iobase =
 			    devpriv->ioaddr + (i + 1) * PCI20000_OFFSET;
 			pci20341_init(dev, s, it->options[2 * i + 2],
 				      it->options[2 * i + 3]);
-			printk(KERN_INFO "comedi%d: "
-			       "ii_pci20kc PCI-20341 module in slot %d\n",
-			       dev->minor, i + 1);
+			dev_info(dev->class_dev,
+				 "PCI-20341 module in slot %d\n", i + 1);
 			break;
 		default:
-			printk(KERN_WARNING "ii_pci20kc: unknown module "
-			       "code 0x%02x in slot %d: module disabled\n",
-			       id, i); /* XXX this looks like a bug! i + 1 ?? */
+			dev_warn(dev->class_dev,
+				 "unknown module code 0x%02x in slot %d: module disabled\n",
+				 id, i); /* XXX this looks like a bug! i + 1 ?? */
 			/* fall through */
 		case PCI20xxx_EMPTY_ID:
 			s->type = COMEDI_SUBD_UNUSED;
@@ -346,8 +345,7 @@ static int pci20006_insn_write(struct comedi_device *dev,
 		writeb(0x00, sdp->iobase + PCI20006_STROBE1);
 		break;
 	default:
-		printk(KERN_WARNING
-		       " comedi%d: pci20xxx: ao channel Error!\n", dev->minor);
+		dev_warn(dev->class_dev, "ao channel Error!\n");
 		return -EINVAL;
 	}
 
@@ -462,10 +460,8 @@ static int pci20341_insn_read(struct comedi_device *dev,
 			eoc = readb(sdp->iobase + PCI20341_STATUS_REG);
 		}
 		if (j >= 100) {
-			printk(KERN_WARNING
-			       "comedi%d:  pci20xxx: "
-			       "AI interrupt channel %i polling exit !\n",
-			       dev->minor, i);
+			dev_warn(dev->class_dev,
+				 "AI interrupt channel %i polling exit !\n", i);
 			return -EINVAL;
 		}
 		lo = readb(sdp->iobase + PCI20341_LDATA);
@@ -541,6 +537,7 @@ static int pci20xxx_dio_insn_bits(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
 				  struct comedi_insn *insn, unsigned int *data)
 {
+	struct pci20xxx_private *devpriv = dev->private;
 	unsigned int mask = data[0];
 
 	s->state &= ~mask;
@@ -571,6 +568,7 @@ static int pci20xxx_dio_insn_bits(struct comedi_device *dev,
 static void pci20xxx_dio_config(struct comedi_device *dev,
 				struct comedi_subdevice *s)
 {
+	struct pci20xxx_private *devpriv = dev->private;
 	unsigned char control_01;
 	unsigned char control_23;
 	unsigned char buffer;
@@ -627,6 +625,8 @@ static void pci20xxx_dio_config(struct comedi_device *dev,
 #if 0
 static void pci20xxx_do(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct pci20xxx_private *devpriv = dev->private;
+
 	/* XXX if the channel is configured for input, does this
 	   do bad things? */
 	/* XXX it would be a good idea to only update the registers
@@ -641,9 +641,10 @@ static void pci20xxx_do(struct comedi_device *dev, struct comedi_subdevice *s)
 static unsigned int pci20xxx_di(struct comedi_device *dev,
 				struct comedi_subdevice *s)
 {
-	/* XXX same note as above */
+	struct pci20xxx_private *devpriv = dev->private;
 	unsigned int bits;
 
+	/* XXX same note as above */
 	bits = readb(devpriv->ioaddr + PCI20000_DIO_0);
 	bits |= readb(devpriv->ioaddr + PCI20000_DIO_1) << 8;
 	bits |= readb(devpriv->ioaddr + PCI20000_DIO_2) << 16;
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
index 4a108ea..c756a35 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.c
+++ b/drivers/staging/comedi/drivers/jr3_pci.c
@@ -21,24 +21,26 @@
 
 */
 /*
-Driver: jr3_pci
-Description: JR3/PCI force sensor board
-Author: Anders Blomdell <anders.blomdell@control.lth.se>
-Status: works
-Devices: [JR3] PCI force sensor board (jr3_pci)
-
-  The DSP on the board requires initialization code, which can
-  be loaded by placing it in /lib/firmware/comedi.
-  The initialization code should be somewhere on the media you got
-  with your card. One version is available from http://www.comedi.org
-  in the comedi_nonfree_firmware tarball.
-
-  Configuration options:
-  [0] - PCI bus number - if bus number and slot number are 0,
-                         then driver search for first unused card
-  [1] - PCI slot number
-
-*/
+ * Driver: jr3_pci
+ * Description: JR3/PCI force sensor board
+ * Author: Anders Blomdell <anders.blomdell@control.lth.se>
+ * Updated: Thu, 01 Nov 2012 17:34:55 +0000
+ * Status: works
+ * Devices: [JR3] PCI force sensor board (jr3_pci)
+ *
+ * Configuration options:
+ *   None
+ *
+ * Manual configuration of comedi devices is not supported by this
+ * driver; supported PCI devices are configured as comedi devices
+ * automatically.
+ *
+ * The DSP on the board requires initialization code, which can be
+ * loaded by placing it in /lib/firmware/comedi.  The initialization
+ * code should be somewhere on the media you got with your card.  One
+ * version is available from http://www.comedi.org in the
+ * comedi_nonfree_firmware tarball.  The file is called "jr3pci.idm".
+ */
 
 #include "../comedidev.h"
 
@@ -59,22 +61,18 @@ Devices: [JR3] PCI force sensor board (jr3_pci)
 #define PCI_DEVICE_ID_JR3_4_CHANNEL 0x3114
 
 struct jr3_pci_dev_private {
-
-	struct pci_dev *pci_dev;
-	int pci_enabled;
-	volatile struct jr3_t *iobase;
+	struct jr3_t __iomem *iobase;
 	int n_channels;
 	struct timer_list timer;
 };
 
 struct poll_delay_t {
-
 	int min;
 	int max;
 };
 
 struct jr3_pci_subdev_private {
-	volatile struct jr3_channel *channel;
+	struct jr3_channel __iomem *channel;
 	unsigned long next_time_min;
 	unsigned long next_time_max;
 	enum { state_jr3_poll,
@@ -98,15 +96,15 @@ struct jr3_pci_subdev_private {
 };
 
 /* Hotplug firmware loading stuff */
-static int comedi_load_firmware(struct comedi_device *dev, char *name,
+static int comedi_load_firmware(struct comedi_device *dev, const char *name,
 				int (*cb)(struct comedi_device *dev,
 					const u8 *data, size_t size))
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	int result = 0;
 	const struct firmware *fw;
 	char *firmware_path;
 	static const char *prefix = "comedi/";
-	struct jr3_pci_dev_private *devpriv = dev->private;
 
 	firmware_path = kmalloc(strlen(prefix) + strlen(name) + 1, GFP_KERNEL);
 	if (!firmware_path) {
@@ -115,8 +113,7 @@ static int comedi_load_firmware(struct comedi_device *dev, char *name,
 		firmware_path[0] = '\0';
 		strcat(firmware_path, prefix);
 		strcat(firmware_path, name);
-		result = request_firmware(&fw, firmware_path,
-					  &devpriv->pci_dev->dev);
+		result = request_firmware(&fw, firmware_path, &pcidev->dev);
 		if (result == 0) {
 			if (!cb)
 				result = -EINVAL;
@@ -138,7 +135,7 @@ static struct poll_delay_t poll_delay_min_max(int min, int max)
 	return result;
 }
 
-static int is_complete(volatile struct jr3_channel *channel)
+static int is_complete(struct jr3_channel __iomem *channel)
 {
 	return get_s16(&channel->command_word0) == 0;
 }
@@ -150,14 +147,13 @@ struct transform_t {
 	} link[8];
 };
 
-static void set_transforms(volatile struct jr3_channel *channel,
+static void set_transforms(struct jr3_channel __iomem *channel,
 			   struct transform_t transf, short num)
 {
 	int i;
 
 	num &= 0x000f;		/*  Make sure that 0 <= num <= 15 */
 	for (i = 0; i < 8; i++) {
-
 		set_u16(&channel->transforms[num].link[i].link_type,
 			transf.link[i].link_type);
 		udelay(1);
@@ -169,18 +165,18 @@ static void set_transforms(volatile struct jr3_channel *channel,
 	}
 }
 
-static void use_transform(volatile struct jr3_channel *channel,
+static void use_transform(struct jr3_channel __iomem *channel,
 			  short transf_num)
 {
 	set_s16(&channel->command_word0, 0x0500 + (transf_num & 0x000f));
 }
 
-static void use_offset(volatile struct jr3_channel *channel, short offset_num)
+static void use_offset(struct jr3_channel __iomem *channel, short offset_num)
 {
 	set_s16(&channel->command_word0, 0x0600 + (offset_num & 0x000f));
 }
 
-static void set_offset(volatile struct jr3_channel *channel)
+static void set_offset(struct jr3_channel __iomem *channel)
 {
 	set_s16(&channel->command_word0, 0x0700);
 }
@@ -194,13 +190,9 @@ struct six_axis_t {
 	s16 mz;
 };
 
-static void set_full_scales(volatile struct jr3_channel *channel,
+static void set_full_scales(struct jr3_channel __iomem *channel,
 			    struct six_axis_t full_scale)
 {
-	printk("%d %d %d %d %d %d\n",
-	       full_scale.fx,
-	       full_scale.fy,
-	       full_scale.fz, full_scale.mx, full_scale.my, full_scale.mz);
 	set_s16(&channel->full_scale.fx, full_scale.fx);
 	set_s16(&channel->full_scale.fy, full_scale.fy);
 	set_s16(&channel->full_scale.fz, full_scale.fz);
@@ -210,7 +202,7 @@ static void set_full_scales(volatile struct jr3_channel *channel,
 	set_s16(&channel->command_word0, 0x0a00);
 }
 
-static struct six_axis_t get_min_full_scales(volatile struct jr3_channel
+static struct six_axis_t get_min_full_scales(struct jr3_channel __iomem
 					     *channel)
 {
 	struct six_axis_t result;
@@ -223,7 +215,7 @@ static struct six_axis_t get_min_full_scales(volatile struct jr3_channel
 	return result;
 }
 
-static struct six_axis_t get_max_full_scales(volatile struct jr3_channel
+static struct six_axis_t get_max_full_scales(struct jr3_channel __iomem
 					     *channel)
 {
 	struct six_axis_t result;
@@ -273,71 +265,53 @@ static int jr3_pci_ai_insn_read(struct comedi_device *dev,
 				} else {
 					int F = 0;
 					switch (axis) {
-					case 0:{
-							F = get_s16
-							    (&p->channel->filter
-							     [filter].fx);
-						}
+					case 0:
+						F = get_s16(&p->channel->
+							    filter[filter].fx);
 						break;
-					case 1:{
-							F = get_s16
-							    (&p->channel->filter
-							     [filter].fy);
-						}
+					case 1:
+						F = get_s16(&p->channel->
+							    filter[filter].fy);
 						break;
-					case 2:{
-							F = get_s16
-							    (&p->channel->filter
-							     [filter].fz);
-						}
+					case 2:
+						F = get_s16(&p->channel->
+							    filter[filter].fz);
 						break;
-					case 3:{
-							F = get_s16
-							    (&p->channel->filter
-							     [filter].mx);
-						}
+					case 3:
+						F = get_s16(&p->channel->
+							    filter[filter].mx);
 						break;
-					case 4:{
-							F = get_s16
-							    (&p->channel->filter
-							     [filter].my);
-						}
+					case 4:
+						F = get_s16(&p->channel->
+							    filter[filter].my);
 						break;
-					case 5:{
-							F = get_s16
-							    (&p->channel->filter
-							     [filter].mz);
-						}
+					case 5:
+						F = get_s16(&p->channel->
+							    filter[filter].mz);
 						break;
-					case 6:{
-							F = get_s16
-							    (&p->channel->filter
-							     [filter].v1);
-						}
+					case 6:
+						F = get_s16(&p->channel->
+							    filter[filter].v1);
 						break;
-					case 7:{
-							F = get_s16
-							    (&p->channel->filter
-							     [filter].v2);
-						}
+					case 7:
+						F = get_s16(&p->channel->
+							    filter[filter].v2);
 						break;
 					}
 					data[i] = F + 0x4000;
 				}
 			} else if (channel == 56) {
-				if (p->state != state_jr3_done) {
+				if (p->state != state_jr3_done)
 					data[i] = 0;
-				} else {
+				else
 					data[i] =
-					    get_u16(&p->channel->model_no);
-				}
+					get_u16(&p->channel->model_no);
 			} else if (channel == 57) {
-				if (p->state != state_jr3_done) {
+				if (p->state != state_jr3_done)
 					data[i] = 0;
-				} else {
+				else
 					data[i] =
-					    get_u16(&p->channel->serial_no);
-				}
+					get_u16(&p->channel->serial_no);
 			}
 		}
 	}
@@ -368,8 +342,8 @@ static int read_idm_word(const u8 *data, size_t size, int *pos,
 	int result = 0;
 	if (pos && val) {
 		/*  Skip over non hex */
-		for (; *pos < size && !isxdigit(data[*pos]); (*pos)++) {
-		}
+		for (; *pos < size && !isxdigit(data[*pos]); (*pos)++)
+			;
 		/*  Collect value */
 		*val = 0;
 		for (; *pos < size; (*pos)++) {
@@ -378,14 +352,15 @@ static int read_idm_word(const u8 *data, size_t size, int *pos,
 			if (value >= 0) {
 				result = 1;
 				*val = (*val << 4) + value;
-			} else
+			} else {
 				break;
+			}
 		}
 	}
 	return result;
 }
 
-static int jr3_download_firmware(struct comedi_device *dev, const u8 * data,
+static int jr3_download_firmware(struct comedi_device *dev, const u8 *data,
 				 size_t size)
 {
 	/*
@@ -429,37 +404,38 @@ static int jr3_download_firmware(struct comedi_device *dev, const u8 * data,
 			pos = 0;
 			while (more) {
 				unsigned int count, addr;
-				more = more
-				    && read_idm_word(data, size, &pos, &count);
+				more = more &&
+				       read_idm_word(data, size, &pos, &count);
 				if (more && count == 0xffff)
 					break;
-				more = more
-				    && read_idm_word(data, size, &pos, &addr);
+				more = more &&
+				       read_idm_word(data, size, &pos, &addr);
 				dev_dbg(dev->class_dev,
 					"Loading#%d %4.4x bytes at %4.4x\n",
 					i, count, addr);
 				while (more && count > 0) {
 					if (addr & 0x4000) {
-						/*  16 bit data, never seen in real life!! */
+						/*  16 bit data, never seen
+						 *  in real life!! */
 						unsigned int data1;
 
-						more = more
-						    && read_idm_word(data,
+						more = more &&
+						       read_idm_word(data,
 								     size, &pos,
 								     &data1);
 						count--;
-						/* printk("jr3_data, not tested\n"); */
-						/* jr3[addr + 0x20000 * pnum] = data1; */
+						/* jr3[addr + 0x20000 * pnum] =
+						   data1; */
 					} else {
 						/*   Download 24 bit program */
 						unsigned int data1, data2;
 
-						more = more
-						    && read_idm_word(data,
+						more = more &&
+						       read_idm_word(data,
 								     size, &pos,
 								     &data1);
-						more = more
-						    && read_idm_word(data, size,
+						more = more &&
+						       read_idm_word(data, size,
 								     &pos,
 								     &data2);
 						count -= 2;
@@ -474,7 +450,6 @@ static int jr3_download_firmware(struct comedi_device *dev, const u8 * data,
 								[i].program_high
 								[addr], data2);
 							udelay(1);
-
 						}
 					}
 					addr++;
@@ -492,213 +467,152 @@ static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice *s)
 	int i;
 
 	if (p) {
-		volatile struct jr3_channel *channel = p->channel;
+		struct jr3_channel __iomem *channel = p->channel;
 		int errors = get_u16(&channel->errors);
 
-		if (errors != p->errors) {
-			printk("Errors: %x -> %x\n", p->errors, errors);
+		if (errors != p->errors)
 			p->errors = errors;
-		}
-		if (errors & (watch_dog | watch_dog2 | sensor_change)) {
+
+		if (errors & (watch_dog | watch_dog2 | sensor_change))
 			/*  Sensor communication lost, force poll mode */
 			p->state = state_jr3_poll;
 
-		}
 		switch (p->state) {
-		case state_jr3_poll:{
+		case state_jr3_poll: {
 				u16 model_no = get_u16(&channel->model_no);
 				u16 serial_no = get_u16(&channel->serial_no);
 				if ((errors & (watch_dog | watch_dog2)) ||
 				    model_no == 0 || serial_no == 0) {
-/*
- * Still no sensor, keep on polling. Since it takes up to 10 seconds
- * for offsets to stabilize, polling each second should suffice.
- */
+					/*
+					 * Still no sensor, keep on polling.
+					 * Since it takes up to 10 seconds
+					 * for offsets to stabilize, polling
+					 * each second should suffice.
+					 */
 					result = poll_delay_min_max(1000, 2000);
 				} else {
 					p->retries = 0;
 					p->state =
-					    state_jr3_init_wait_for_offset;
+						state_jr3_init_wait_for_offset;
 					result = poll_delay_min_max(1000, 2000);
 				}
 			}
 			break;
-		case state_jr3_init_wait_for_offset:{
-				p->retries++;
-				if (p->retries < 10) {
-					/*  Wait for offeset to stabilize (< 10 s according to manual) */
-					result = poll_delay_min_max(1000, 2000);
-				} else {
-					struct transform_t transf;
-
-					p->model_no =
-					    get_u16(&channel->model_no);
-					p->serial_no =
-					    get_u16(&channel->serial_no);
-
-					printk
-					    ("Setting transform for channel %d\n",
-					     p->channel_no);
-					printk("Sensor Model     = %i\n",
-					       p->model_no);
-					printk("Sensor Serial    = %i\n",
-					       p->serial_no);
-
-					/*  Transformation all zeros */
-					for (i = 0; i < ARRAY_SIZE(transf.link); i++) {
-						transf.link[i].link_type =
-							(enum link_types)0;
-						transf.link[i].link_amount = 0;
-					}
-
-					set_transforms(channel, transf, 0);
-					use_transform(channel, 0);
-					p->state =
-					    state_jr3_init_transform_complete;
-					result = poll_delay_min_max(20, 100);	/*  Allow 20 ms for completion */
+		case state_jr3_init_wait_for_offset:
+			p->retries++;
+			if (p->retries < 10) {
+				/*  Wait for offeset to stabilize
+				 *  (< 10 s according to manual) */
+				result = poll_delay_min_max(1000, 2000);
+			} else {
+				struct transform_t transf;
+
+				p->model_no = get_u16(&channel->model_no);
+				p->serial_no = get_u16(&channel->serial_no);
+
+				/*  Transformation all zeros */
+				for (i = 0; i < ARRAY_SIZE(transf.link); i++) {
+					transf.link[i].link_type =
+						(enum link_types)0;
+					transf.link[i].link_amount = 0;
 				}
-			} break;
-		case state_jr3_init_transform_complete:{
-				if (!is_complete(channel)) {
-					printk
-					    ("state_jr3_init_transform_complete complete = %d\n",
-					     is_complete(channel));
-					result = poll_delay_min_max(20, 100);
-				} else {
-					/*  Set full scale */
-					struct six_axis_t min_full_scale;
-					struct six_axis_t max_full_scale;
-
-					min_full_scale =
-					    get_min_full_scales(channel);
-					printk("Obtained Min. Full Scales:\n");
-					printk(KERN_DEBUG "%i ", (min_full_scale).fx);
-					printk(KERN_CONT "%i ", (min_full_scale).fy);
-					printk(KERN_CONT "%i ", (min_full_scale).fz);
-					printk(KERN_CONT "%i ", (min_full_scale).mx);
-					printk(KERN_CONT "%i ", (min_full_scale).my);
-					printk(KERN_CONT "%i ", (min_full_scale).mz);
-					printk(KERN_CONT "\n");
-
-					max_full_scale =
-					    get_max_full_scales(channel);
-					printk("Obtained Max. Full Scales:\n");
-					printk(KERN_DEBUG "%i ", (max_full_scale).fx);
-					printk(KERN_CONT "%i ", (max_full_scale).fy);
-					printk(KERN_CONT "%i ", (max_full_scale).fz);
-					printk(KERN_CONT "%i ", (max_full_scale).mx);
-					printk(KERN_CONT "%i ", (max_full_scale).my);
-					printk(KERN_CONT "%i ", (max_full_scale).mz);
-					printk(KERN_CONT "\n");
-
-					set_full_scales(channel,
-							max_full_scale);
 
-					p->state =
-					    state_jr3_init_set_full_scale_complete;
-					result = poll_delay_min_max(20, 100);	/*  Allow 20 ms for completion */
-				}
+				set_transforms(channel, transf, 0);
+				use_transform(channel, 0);
+				p->state = state_jr3_init_transform_complete;
+				/*  Allow 20 ms for completion */
+				result = poll_delay_min_max(20, 100);
 			}
 			break;
-		case state_jr3_init_set_full_scale_complete:{
-				if (!is_complete(channel)) {
-					printk
-					    ("state_jr3_init_set_full_scale_complete complete = %d\n",
-					     is_complete(channel));
-					result = poll_delay_min_max(20, 100);
-				} else {
-					volatile struct force_array *full_scale;
-
-					/*  Use ranges in kN or we will overflow arount 2000N! */
-					full_scale = &channel->full_scale;
-					p->range[0].range.min =
-					    -get_s16(&full_scale->fx) * 1000;
-					p->range[0].range.max =
-					    get_s16(&full_scale->fx) * 1000;
-					p->range[1].range.min =
-					    -get_s16(&full_scale->fy) * 1000;
-					p->range[1].range.max =
-					    get_s16(&full_scale->fy) * 1000;
-					p->range[2].range.min =
-					    -get_s16(&full_scale->fz) * 1000;
-					p->range[2].range.max =
-					    get_s16(&full_scale->fz) * 1000;
-					p->range[3].range.min =
-					    -get_s16(&full_scale->mx) * 100;
-					p->range[3].range.max =
-					    get_s16(&full_scale->mx) * 100;
-					p->range[4].range.min =
-					    -get_s16(&full_scale->my) * 100;
-					p->range[4].range.max =
-					    get_s16(&full_scale->my) * 100;
-					p->range[5].range.min =
-					    -get_s16(&full_scale->mz) * 100;
-					p->range[5].range.max =
-					    get_s16(&full_scale->mz) * 100;
-					p->range[6].range.min = -get_s16(&full_scale->v1) * 100;	/*  ?? */
-					p->range[6].range.max = get_s16(&full_scale->v1) * 100;	/*  ?? */
-					p->range[7].range.min = -get_s16(&full_scale->v2) * 100;	/*  ?? */
-					p->range[7].range.max = get_s16(&full_scale->v2) * 100;	/*  ?? */
-					p->range[8].range.min = 0;
-					p->range[8].range.max = 65535;
-
-					{
-						int i;
-						for (i = 0; i < 9; i++) {
-							printk("%d %d - %d\n",
-							       i,
-							       p->
-							       range[i].range.
-							       min,
-							       p->
-							       range[i].range.
-							       max);
-						}
-					}
-
-					use_offset(channel, 0);
-					p->state =
-					    state_jr3_init_use_offset_complete;
-					result = poll_delay_min_max(40, 100);	/*  Allow 40 ms for completion */
-				}
+		case state_jr3_init_transform_complete:
+			if (!is_complete(channel)) {
+				result = poll_delay_min_max(20, 100);
+			} else {
+				/*  Set full scale */
+				struct six_axis_t min_full_scale;
+				struct six_axis_t max_full_scale;
+
+				min_full_scale = get_min_full_scales(channel);
+				max_full_scale = get_max_full_scales(channel);
+				set_full_scales(channel, max_full_scale);
+
+				p->state =
+					state_jr3_init_set_full_scale_complete;
+				/*  Allow 20 ms for completion */
+				result = poll_delay_min_max(20, 100);
 			}
 			break;
-		case state_jr3_init_use_offset_complete:{
-				if (!is_complete(channel)) {
-					printk
-					    ("state_jr3_init_use_offset_complete complete = %d\n",
-					     is_complete(channel));
-					result = poll_delay_min_max(20, 100);
-				} else {
-					printk
-					    ("Default offsets %d %d %d %d %d %d\n",
-					     get_s16(&channel->offsets.fx),
-					     get_s16(&channel->offsets.fy),
-					     get_s16(&channel->offsets.fz),
-					     get_s16(&channel->offsets.mx),
-					     get_s16(&channel->offsets.my),
-					     get_s16(&channel->offsets.mz));
-
-					set_s16(&channel->offsets.fx, 0);
-					set_s16(&channel->offsets.fy, 0);
-					set_s16(&channel->offsets.fz, 0);
-					set_s16(&channel->offsets.mx, 0);
-					set_s16(&channel->offsets.my, 0);
-					set_s16(&channel->offsets.mz, 0);
-
-					set_offset(channel);
-
-					p->state = state_jr3_done;
-				}
+		case state_jr3_init_set_full_scale_complete:
+			if (!is_complete(channel)) {
+				result = poll_delay_min_max(20, 100);
+			} else {
+				struct force_array __iomem *full_scale;
+
+				/*  Use ranges in kN or we will
+				 *  overflow around 2000N! */
+				full_scale = &channel->full_scale;
+				p->range[0].range.min =
+					-get_s16(&full_scale->fx) * 1000;
+				p->range[0].range.max =
+					get_s16(&full_scale->fx) * 1000;
+				p->range[1].range.min =
+					-get_s16(&full_scale->fy) * 1000;
+				p->range[1].range.max =
+					get_s16(&full_scale->fy) * 1000;
+				p->range[2].range.min =
+					-get_s16(&full_scale->fz) * 1000;
+				p->range[2].range.max =
+					get_s16(&full_scale->fz) * 1000;
+				p->range[3].range.min =
+					-get_s16(&full_scale->mx) * 100;
+				p->range[3].range.max =
+					get_s16(&full_scale->mx) * 100;
+				p->range[4].range.min =
+					-get_s16(&full_scale->my) * 100;
+				p->range[4].range.max =
+					get_s16(&full_scale->my) * 100;
+				p->range[5].range.min =
+					-get_s16(&full_scale->mz) * 100;
+				p->range[5].range.max =
+					get_s16(&full_scale->mz) * 100;	/* ?? */
+				p->range[6].range.min =
+					-get_s16(&full_scale->v1) * 100;/* ?? */
+				p->range[6].range.max =
+					get_s16(&full_scale->v1) * 100;	/* ?? */
+				p->range[7].range.min =
+					-get_s16(&full_scale->v2) * 100;/* ?? */
+				p->range[7].range.max =
+					get_s16(&full_scale->v2) * 100;	/* ?? */
+				p->range[8].range.min = 0;
+				p->range[8].range.max = 65535;
+
+				use_offset(channel, 0);
+				p->state = state_jr3_init_use_offset_complete;
+				/*  Allow 40 ms for completion */
+				result = poll_delay_min_max(40, 100);
 			}
 			break;
-		case state_jr3_done:{
-				poll_delay_min_max(10000, 20000);
+		case state_jr3_init_use_offset_complete:
+			if (!is_complete(channel)) {
+				result = poll_delay_min_max(20, 100);
+			} else {
+				set_s16(&channel->offsets.fx, 0);
+				set_s16(&channel->offsets.fy, 0);
+				set_s16(&channel->offsets.fz, 0);
+				set_s16(&channel->offsets.mx, 0);
+				set_s16(&channel->offsets.my, 0);
+				set_s16(&channel->offsets.mz, 0);
+
+				set_offset(channel);
+
+				p->state = state_jr3_done;
 			}
 			break;
-		default:{
-				poll_delay_min_max(1000, 2000);
-			}
+		case state_jr3_done:
+			poll_delay_min_max(10000, 20000);
+			break;
+		default:
+			poll_delay_min_max(1000, 2000);
 			break;
 		}
 	}
@@ -720,22 +634,21 @@ static void jr3_pci_poll_dev(unsigned long data)
 	/*  Poll all channels that are ready to be polled */
 	for (i = 0; i < devpriv->n_channels; i++) {
 		struct jr3_pci_subdev_private *subdevpriv =
-		    dev->subdevices[i].private;
+			dev->subdevices[i].private;
 		if (now > subdevpriv->next_time_min) {
 			struct poll_delay_t sub_delay;
 
 			sub_delay = jr3_pci_poll_subdevice(&dev->subdevices[i]);
 			subdevpriv->next_time_min =
-			    jiffies + msecs_to_jiffies(sub_delay.min);
+				jiffies + msecs_to_jiffies(sub_delay.min);
 			subdevpriv->next_time_max =
-			    jiffies + msecs_to_jiffies(sub_delay.max);
-			if (sub_delay.max && sub_delay.max < delay) {
-/*
-* Wake up as late as possible -> poll as many channels as possible
-* at once
-*/
+				jiffies + msecs_to_jiffies(sub_delay.max);
+			if (sub_delay.max && sub_delay.max < delay)
+				/*
+				 * Wake up as late as possible ->
+				 * poll as many channels as possible at once.
+				 */
 				delay = sub_delay.max;
-			}
 		}
 	}
 	spin_unlock_irqrestore(&dev->spinlock, flags);
@@ -744,17 +657,14 @@ static void jr3_pci_poll_dev(unsigned long data)
 	add_timer(&devpriv->timer);
 }
 
-static int jr3_pci_attach(struct comedi_device *dev,
-			  struct comedi_devconfig *it)
+static int jr3_pci_auto_attach(struct comedi_device *dev,
+					 unsigned long context_unused)
 {
-	int result = 0;
-	struct pci_dev *card = NULL;
-	int opt_bus, opt_slot, i;
+	int result;
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	int i;
 	struct jr3_pci_dev_private *devpriv;
 
-	opt_bus = it->options[0];
-	opt_slot = it->options[1];
-
 	if (sizeof(struct jr3_channel) != 0xc00) {
 		dev_err(dev->class_dev,
 			"sizeof(struct jr3_channel) = %x [expected %x]\n",
@@ -762,70 +672,42 @@ static int jr3_pci_attach(struct comedi_device *dev,
 		return -EINVAL;
 	}
 
-	result = alloc_private(dev, sizeof(struct jr3_pci_dev_private));
-	if (result < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
-	card = NULL;
-	devpriv = dev->private;
+	dev->private = devpriv;
+
 	init_timer(&devpriv->timer);
-	while (1) {
-		card = pci_get_device(PCI_VENDOR_ID_JR3, PCI_ANY_ID, card);
-		if (card == NULL) {
-			/* No card found */
-			break;
-		} else {
-			switch (card->device) {
-			case PCI_DEVICE_ID_JR3_1_CHANNEL:{
-					devpriv->n_channels = 1;
-				}
-				break;
-			case PCI_DEVICE_ID_JR3_1_CHANNEL_NEW:{
-					devpriv->n_channels = 1;
-				}
-				break;
-			case PCI_DEVICE_ID_JR3_2_CHANNEL:{
-					devpriv->n_channels = 2;
-				}
-				break;
-			case PCI_DEVICE_ID_JR3_3_CHANNEL:{
-					devpriv->n_channels = 3;
-				}
-				break;
-			case PCI_DEVICE_ID_JR3_4_CHANNEL:{
-					devpriv->n_channels = 4;
-				}
-				break;
-			default:{
-					devpriv->n_channels = 0;
-				}
-			}
-			if (devpriv->n_channels >= 1) {
-				if (opt_bus == 0 && opt_slot == 0) {
-					/* Take first available card */
-					break;
-				} else if (opt_bus == card->bus->number &&
-					   opt_slot == PCI_SLOT(card->devfn)) {
-					/* Take requested card */
-					break;
-				}
-			}
-		}
-	}
-	if (!card) {
-		dev_err(dev->class_dev, "no jr3_pci found\n");
-		return -EIO;
-	} else {
-		devpriv->pci_dev = card;
-		dev->board_name = "jr3_pci";
+	switch (pcidev->device) {
+	case PCI_DEVICE_ID_JR3_1_CHANNEL:
+	case PCI_DEVICE_ID_JR3_1_CHANNEL_NEW:
+		devpriv->n_channels = 1;
+		break;
+	case PCI_DEVICE_ID_JR3_2_CHANNEL:
+		devpriv->n_channels = 2;
+		break;
+	case PCI_DEVICE_ID_JR3_3_CHANNEL:
+		devpriv->n_channels = 3;
+		break;
+	case PCI_DEVICE_ID_JR3_4_CHANNEL:
+		devpriv->n_channels = 4;
+		break;
+	default:
+		dev_err(dev->class_dev, "jr3_pci: pci %s not supported\n",
+			pci_name(pcidev));
+		return -EINVAL;
+		break;
 	}
+	dev->board_name = "jr3_pci";
 
-	result = comedi_pci_enable(card, "jr3_pci");
+	result = comedi_pci_enable(pcidev, "jr3_pci");
 	if (result < 0)
-		return -EIO;
+		return result;
 
-	devpriv->pci_enabled = 1;
-	devpriv->iobase = ioremap(pci_resource_start(card, 0),
-			offsetof(struct jr3_t, channel[devpriv->n_channels]));
+	dev->iobase = 1;	/* the "detach" needs this */
+	devpriv->iobase = ioremap(pci_resource_start(pcidev, 0),
+				  offsetof(struct jr3_t,
+					   channel[devpriv->n_channels]));
 	if (!devpriv->iobase)
 		return -ENOMEM;
 
@@ -840,7 +722,8 @@ static int jr3_pci_attach(struct comedi_device *dev,
 		dev->subdevices[i].n_chan = 8 * 7 + 2;
 		dev->subdevices[i].insn_read = jr3_pci_ai_insn_read;
 		dev->subdevices[i].private =
-		    kzalloc(sizeof(struct jr3_pci_subdev_private), GFP_KERNEL);
+			kzalloc(sizeof(struct jr3_pci_subdev_private),
+				GFP_KERNEL);
 		if (dev->subdevices[i].private) {
 			struct jr3_pci_subdev_private *p;
 			int j;
@@ -849,8 +732,8 @@ static int jr3_pci_attach(struct comedi_device *dev,
 			p->channel = &devpriv->iobase->channel[i].data;
 			dev_dbg(dev->class_dev, "p->channel %p %p (%tx)\n",
 				p->channel, devpriv->iobase,
-				((char *)(p->channel) -
-				 (char *)(devpriv->iobase)));
+				((char __iomem *)p->channel -
+				 (char __iomem *)devpriv->iobase));
 			p->channel_no = i;
 			for (j = 0; j < 8; j++) {
 				int k;
@@ -870,15 +753,15 @@ static int jr3_pci_attach(struct comedi_device *dev,
 			p->range[8].range.max = 65536;
 
 			p->range_table_list[56] =
-			    (struct comedi_lrange *)&p->range[8];
+				(struct comedi_lrange *)&p->range[8];
 			p->range_table_list[57] =
-			    (struct comedi_lrange *)&p->range[8];
+				(struct comedi_lrange *)&p->range[8];
 			p->maxdata_list[56] = 0xffff;
 			p->maxdata_list[57] = 0xffff;
 			/*  Channel specific range and maxdata */
 			dev->subdevices[i].range_table = NULL;
 			dev->subdevices[i].range_table_list =
-			    p->range_table_list;
+				p->range_table_list;
 			dev->subdevices[i].maxdata = 0;
 			dev->subdevices[i].maxdata_list = p->maxdata_list;
 		}
@@ -891,19 +774,20 @@ static int jr3_pci_attach(struct comedi_device *dev,
 	dev_dbg(dev->class_dev, "Firmare load %d\n", result);
 
 	if (result < 0)
-		goto out;
-/*
- * TODO: use firmware to load preferred offset tables. Suggested
- * format:
- *     model serial Fx Fy Fz Mx My Mz\n
- *
- *     comedi_load_firmware(dev, "jr3_offsets_table", jr3_download_firmware);
- */
+		return result;
+	/*
+	 * TODO: use firmware to load preferred offset tables. Suggested
+	 * format:
+	 *     model serial Fx Fy Fz Mx My Mz\n
+	 *
+	 *     comedi_load_firmware(dev, "jr3_offsets_table",
+	 *                          jr3_download_firmware);
+	 */
 
-/*
- * It takes a few milliseconds for software to settle as much as we
- * can read firmware version
- */
+	/*
+	 * It takes a few milliseconds for software to settle as much as we
+	 * can read firmware version
+	 */
 	msleep_interruptible(25);
 	for (i = 0; i < 0x18; i++) {
 		dev_dbg(dev->class_dev, "%c\n",
@@ -924,13 +808,13 @@ static int jr3_pci_attach(struct comedi_device *dev,
 	devpriv->timer.expires = jiffies + msecs_to_jiffies(1000);
 	add_timer(&devpriv->timer);
 
-out:
 	return result;
 }
 
 static void jr3_pci_detach(struct comedi_device *dev)
 {
 	int i;
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct jr3_pci_dev_private *devpriv = dev->private;
 
 	if (devpriv) {
@@ -941,28 +825,26 @@ static void jr3_pci_detach(struct comedi_device *dev)
 				kfree(dev->subdevices[i].private);
 		}
 		if (devpriv->iobase)
-			iounmap((void *)devpriv->iobase);
-		if (devpriv->pci_enabled)
-			comedi_pci_disable(devpriv->pci_dev);
-		if (devpriv->pci_dev)
-			pci_dev_put(devpriv->pci_dev);
+			iounmap(devpriv->iobase);
+		if (dev->iobase)
+			comedi_pci_disable(pcidev);
 	}
 }
 
 static struct comedi_driver jr3_pci_driver = {
 	.driver_name	= "jr3_pci",
 	.module		= THIS_MODULE,
-	.attach		= jr3_pci_attach,
+	.auto_attach	= jr3_pci_auto_attach,
 	.detach		= jr3_pci_detach,
 };
 
-static int __devinit jr3_pci_pci_probe(struct pci_dev *dev,
+static int jr3_pci_pci_probe(struct pci_dev *dev,
 				       const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &jr3_pci_driver);
 }
 
-static void __devexit jr3_pci_pci_remove(struct pci_dev *dev)
+static void jr3_pci_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -981,7 +863,7 @@ static struct pci_driver jr3_pci_pci_driver = {
 	.name		= "jr3_pci",
 	.id_table	= jr3_pci_pci_table,
 	.probe		= jr3_pci_pci_probe,
-	.remove		= __devexit_p(jr3_pci_pci_remove),
+	.remove		= jr3_pci_pci_remove,
 };
 module_comedi_pci_driver(jr3_pci_driver, jr3_pci_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h
index 9c42653..3317f7a 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.h
+++ b/drivers/staging/comedi/drivers/jr3_pci.h
@@ -2,22 +2,22 @@
  * is 16 bits, but aligned on a 32 bit PCI boundary
  */
 
-static inline u16 get_u16(volatile const u32 * p)
+static inline u16 get_u16(const u32 __iomem *p)
 {
-	return (u16) readl(p);
+	return (u16)readl(p);
 }
 
-static inline void set_u16(volatile u32 * p, u16 val)
+static inline void set_u16(u32 __iomem *p, u16 val)
 {
 	writel(val, p);
 }
 
-static inline s16 get_s16(volatile const s32 * p)
+static inline s16 get_s16(const s32 __iomem *p)
 {
-	return (s16) readl(p);
+	return (s16)readl(p);
 }
 
-static inline void set_s16(volatile s32 * p, s16 val)
+static inline void set_s16(s32 __iomem *p, s16 val)
 {
 	writel(val, p);
 }
diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c
index e867b72..19c9428 100644
--- a/drivers/staging/comedi/drivers/ke_counter.c
+++ b/drivers/staging/comedi/drivers/ke_counter.c
@@ -36,28 +36,8 @@ Kolter Electronic PCI Counter Card.
 
 #include "../comedidev.h"
 
-#define CNT_DRIVER_NAME         "ke_counter"
-#define PCI_VENDOR_ID_KOLTER    0x1001
 #define CNT_CARD_DEVICE_ID      0x0014
 
-/*-- board specification structure ------------------------------------------*/
-
-struct cnt_board_struct {
-
-	const char *name;
-	int device_id;
-	int cnt_channel_nbr;
-	int cnt_bits;
-};
-
-static const struct cnt_board_struct cnt_boards[] = {
-	{
-	 .name = CNT_DRIVER_NAME,
-	 .device_id = CNT_CARD_DEVICE_ID,
-	 .cnt_channel_nbr = 3,
-	 .cnt_bits = 24}
-};
-
 /*-- counter write ----------------------------------------------------------*/
 
 /* This should be used only for resetting the counters; maybe it is better
@@ -107,34 +87,14 @@ static int cnt_rinsn(struct comedi_device *dev,
 	return 1;
 }
 
-static const void *cnt_find_boardinfo(struct comedi_device *dev,
-				      struct pci_dev *pcidev)
+static int cnt_auto_attach(struct comedi_device *dev,
+				     unsigned long context_unused)
 {
-	const struct cnt_board_struct *board;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(cnt_boards); i++) {
-		board = &cnt_boards[i];
-		if (board->device_id == pcidev->device)
-			return board;
-	}
-	return NULL;
-}
-
-static int cnt_attach_pci(struct comedi_device *dev,
-			  struct pci_dev *pcidev)
-{
-	const struct cnt_board_struct *board;
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	struct comedi_subdevice *s;
 	int ret;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
-
-	board = cnt_find_boardinfo(dev, pcidev);
-	if (!board)
-		return -ENODEV;
-	dev->board_ptr = board;
-	dev->board_name = board->name;
+	dev->board_name = dev->driver->driver_name;
 
 	ret = comedi_pci_enable(pcidev, dev->board_name);
 	if (ret)
@@ -150,8 +110,8 @@ static int cnt_attach_pci(struct comedi_device *dev,
 
 	s->type = COMEDI_SUBD_COUNTER;
 	s->subdev_flags = SDF_READABLE /* | SDF_COMMON */ ;
-	s->n_chan = board->cnt_channel_nbr;
-	s->maxdata = (1 << board->cnt_bits) - 1;
+	s->n_chan = 3;
+	s->maxdata = 0x00ffffff;
 	s->insn_read = cnt_rinsn;
 	s->insn_write = cnt_winsn;
 
@@ -182,17 +142,17 @@ static void cnt_detach(struct comedi_device *dev)
 static struct comedi_driver ke_counter_driver = {
 	.driver_name	= "ke_counter",
 	.module		= THIS_MODULE,
-	.attach_pci	= cnt_attach_pci,
+	.auto_attach	= cnt_auto_attach,
 	.detach		= cnt_detach,
 };
 
-static int __devinit ke_counter_pci_probe(struct pci_dev *dev,
+static int ke_counter_pci_probe(struct pci_dev *dev,
 					  const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &ke_counter_driver);
 }
 
-static void __devexit ke_counter_pci_remove(struct pci_dev *dev)
+static void ke_counter_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -207,7 +167,7 @@ static struct pci_driver ke_counter_pci_driver = {
 	.name		= "ke_counter",
 	.id_table	= ke_counter_pci_table,
 	.probe		= ke_counter_pci_probe,
-	.remove		= __devexit_p(ke_counter_pci_remove),
+	.remove		= ke_counter_pci_remove,
 };
 module_comedi_pci_driver(ke_counter_driver, ke_counter_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
index 22db35d..3c4b022 100644
--- a/drivers/staging/comedi/drivers/me4000.c
+++ b/drivers/staging/comedi/drivers/me4000.c
@@ -60,8 +60,6 @@ broken.
 #include "me4000_fw.h"
 #endif
 
-#define PCI_VENDOR_ID_MEILHAUS		0x1402
-
 #define PCI_DEVICE_ID_MEILHAUS_ME4650	0x4650
 #define PCI_DEVICE_ID_MEILHAUS_ME4660	0x4660
 #define PCI_DEVICE_ID_MEILHAUS_ME4660I	0x4661
@@ -971,28 +969,23 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/*
-	 * Stage 3. Check if arguments are generally valid.
-	 */
+	/* Step 3: check if arguments are trivially valid */
+
 	if (cmd->chanlist_len < 1) {
-		dev_err(dev->class_dev, "No channel list\n");
 		cmd->chanlist_len = 1;
-		err++;
+		err |= -EINVAL;
 	}
 	if (init_ticks < 66) {
-		dev_err(dev->class_dev, "Start arg to low\n");
 		cmd->start_arg = 2000;
-		err++;
+		err |= -EINVAL;
 	}
 	if (scan_ticks && scan_ticks < 67) {
-		dev_err(dev->class_dev, "Scan begin arg to low\n");
 		cmd->scan_begin_arg = 2031;
-		err++;
+		err |= -EINVAL;
 	}
 	if (chan_ticks < 66) {
-		dev_err(dev->class_dev, "Convert arg to low\n");
 		cmd->convert_arg = 2000;
-		err++;
+		err |= -EINVAL;
 	}
 
 	if (err)
@@ -1570,26 +1563,25 @@ static const void *me4000_find_boardinfo(struct comedi_device *dev,
 	return NULL;
 }
 
-static int me4000_attach_pci(struct comedi_device *dev,
-			     struct pci_dev *pcidev)
+static int me4000_auto_attach(struct comedi_device *dev,
+					unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	const struct me4000_board *thisboard;
 	struct me4000_info *info;
 	struct comedi_subdevice *s;
 	int result;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
-
 	thisboard = me4000_find_boardinfo(dev, pcidev);
 	if (!thisboard)
 		return -ENODEV;
 	dev->board_ptr = thisboard;
 	dev->board_name = thisboard->name;
 
-	result = alloc_private(dev, sizeof(*info));
-	if (result)
-		return result;
-	info = dev->private;
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+	dev->private = info;
 
 	result = comedi_pci_enable(pcidev, dev->board_name);
 	if (result)
@@ -1732,17 +1724,17 @@ static void me4000_detach(struct comedi_device *dev)
 static struct comedi_driver me4000_driver = {
 	.driver_name	= "me4000",
 	.module		= THIS_MODULE,
-	.attach_pci	= me4000_attach_pci,
+	.auto_attach	= me4000_auto_attach,
 	.detach		= me4000_detach,
 };
 
-static int __devinit me4000_pci_probe(struct pci_dev *dev,
+static int me4000_pci_probe(struct pci_dev *dev,
 				      const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &me4000_driver);
 }
 
-static void __devexit me4000_pci_remove(struct pci_dev *dev)
+static void me4000_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -1769,7 +1761,7 @@ static struct pci_driver me4000_pci_driver = {
 	.name		= "me4000",
 	.id_table	= me4000_pci_table,
 	.probe		= me4000_pci_probe,
-	.remove		= __devexit_p(me4000_pci_remove),
+	.remove		= me4000_pci_remove,
 };
 module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
index 2ce0b14..ce8e3d3 100644
--- a/drivers/staging/comedi/drivers/me_daq.c
+++ b/drivers/staging/comedi/drivers/me_daq.c
@@ -1,47 +1,38 @@
 /*
-
-   comedi/drivers/me_daq.c
-
-   Hardware driver for Meilhaus data acquisition cards:
-
-     ME-2000i, ME-2600i, ME-3000vm1
-
-   Copyright (C) 2002 Michael Hillmann <hillmann@syscongroup.de>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * comedi/drivers/me_daq.c
+ * Hardware driver for Meilhaus data acquisition cards:
+ *   ME-2000i, ME-2600i, ME-3000vm1
+ *
+ * Copyright (C) 2002 Michael Hillmann <hillmann@syscongroup.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
 
 /*
-Driver: me_daq
-Description: Meilhaus PCI data acquisition cards
-Author: Michael Hillmann <hillmann@syscongroup.de>
-Devices: [Meilhaus] ME-2600i (me_daq), ME-2000i
-Status: experimental
-
-Supports:
-
-    Analog Output
-
-Configuration options:
-
-    [0] - PCI bus number (optional)
-    [1] - PCI slot number (optional)
-
-    If bus/slot is not specified, the first available PCI
-    device will be used.
-*/
+ * Driver: me_daq
+ * Description: Meilhaus PCI data acquisition cards
+ * Devices: (Meilhaus) ME-2600i [me-2600i]
+ *          (Meilhaus) ME-2000i [me-2000i]
+ * Author: Michael Hillmann <hillmann@syscongroup.de>
+ * Status: experimental
+ *
+ * Configuration options: not applicable, uses PCI auto config
+ *
+ * Supports:
+ *    Analog Input, Analog Output, Digital I/O
+ */
 
 #include <linux/interrupt.h>
 #include <linux/sched.h>
@@ -50,7 +41,6 @@ Configuration options:
 
 #define ME2600_FIRMWARE		"me2600_firmware.bin"
 
-#define PCI_VENDOR_ID_MEILHAUS	0x1402
 #define ME2000_DEVICE_ID	0x2000
 #define ME2600_DEVICE_ID	0x2600
 
@@ -136,97 +126,47 @@ Configuration options:
 #define ME_COUNTER_STARTDATA_B		0x0022	/* - | W */
 #define ME_COUNTER_VALUE_B		0x0022	/* R | - */
 
-static const struct comedi_lrange me2000_ai_range = {
-	8,
-	{
-	 BIP_RANGE(10),
-	 BIP_RANGE(5),
-	 BIP_RANGE(2.5),
-	 BIP_RANGE(1.25),
-	 UNI_RANGE(10),
-	 UNI_RANGE(5),
-	 UNI_RANGE(2.5),
-	 UNI_RANGE(1.25)
-	 }
-};
-
-static const struct comedi_lrange me2600_ai_range = {
-	8,
-	{
-	 BIP_RANGE(10),
-	 BIP_RANGE(5),
-	 BIP_RANGE(2.5),
-	 BIP_RANGE(1.25),
-	 UNI_RANGE(10),
-	 UNI_RANGE(5),
-	 UNI_RANGE(2.5),
-	 UNI_RANGE(1.25)
-	 }
+static const struct comedi_lrange me_ai_range = {
+	8, {
+		BIP_RANGE(10),
+		BIP_RANGE(5),
+		BIP_RANGE(2.5),
+		BIP_RANGE(1.25),
+		UNI_RANGE(10),
+		UNI_RANGE(5),
+		UNI_RANGE(2.5),
+		UNI_RANGE(1.25)
+	}
 };
 
-static const struct comedi_lrange me2600_ao_range = {
-	3,
-	{
-	 BIP_RANGE(10),
-	 BIP_RANGE(5),
-	 UNI_RANGE(10)
-	 }
+static const struct comedi_lrange me_ao_range = {
+	3, {
+		BIP_RANGE(10),
+		BIP_RANGE(5),
+		UNI_RANGE(10)
+	}
 };
 
-/* Board specification structure */
 struct me_board {
-	const char *name;	/* driver name */
+	const char *name;
 	int device_id;
-	int ao_channel_nbr;	/* DA config */
-	int ao_resolution;
-	int ao_resolution_mask;
-	const struct comedi_lrange *ao_range_list;
-	int ai_channel_nbr;	/* AD config */
-	int ai_resolution;
-	int ai_resolution_mask;
-	const struct comedi_lrange *ai_range_list;
-	int dio_channel_nbr;	/* DIO config */
+	int has_ao;
 };
 
 static const struct me_board me_boards[] = {
 	{
-	 .name = "me-2600i",
-	 .device_id = ME2600_DEVICE_ID,
-	 /* Analog Output */
-	 .ao_channel_nbr = 4,
-	 .ao_resolution = 12,
-	 .ao_resolution_mask = 0x0fff,
-	 .ao_range_list = &me2600_ao_range,
-	 .ai_channel_nbr = 16,
-	 /* Analog Input */
-	 .ai_resolution = 12,
-	 .ai_resolution_mask = 0x0fff,
-	 .ai_range_list = &me2600_ai_range,
-	 .dio_channel_nbr = 32,
-	 },
-	{
-	 .name = "me-2000i",
-	 .device_id = ME2000_DEVICE_ID,
-	 /* Analog Output */
-	 .ao_channel_nbr = 0,
-	 .ao_resolution = 0,
-	 .ao_resolution_mask = 0,
-	 .ao_range_list = NULL,
-	 .ai_channel_nbr = 16,
-	 /* Analog Input */
-	 .ai_resolution = 12,
-	 .ai_resolution_mask = 0x0fff,
-	 .ai_range_list = &me2000_ai_range,
-	 .dio_channel_nbr = 32,
-	 }
+		.name		= "me-2600i",
+		.device_id	= ME2600_DEVICE_ID,
+		.has_ao		= 1,
+	}, {
+		.name		= "me-2000i",
+		.device_id	= ME2000_DEVICE_ID,
+	}
 };
 
-/* Private data structure */
 struct me_private_data {
 	void __iomem *plx_regbase;	/* PLX configuration base address */
 	void __iomem *me_regbase;	/* Base address of the Meilhaus card */
-	unsigned long plx_regbase_size;	/* Size of PLX configuration space */
-	unsigned long me_regbase_size;	/* Size of Meilhaus space */
 
 	unsigned short control_1;	/* Mirror of CONTROL_1 register */
 	unsigned short control_2;	/* Mirror of CONTROL_2 register */
@@ -234,110 +174,101 @@ struct me_private_data {
 	int ao_readback[4];	/* Mirror of analog output data */
 };
 
-#define dev_private ((struct me_private_data *)dev->private)
-
-/*
- * ------------------------------------------------------------------
- *
- * Helpful functions
- *
- * ------------------------------------------------------------------
- */
 static inline void sleep(unsigned sec)
 {
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(sec * HZ);
 }
 
-/*
- * ------------------------------------------------------------------
- *
- * DIGITAL INPUT/OUTPUT SECTION
- *
- * ------------------------------------------------------------------
- */
 static int me_dio_insn_config(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
-	int bits;
-	int mask = 1 << CR_CHAN(insn->chanspec);
+	struct me_private_data *dev_private = dev->private;
+	unsigned int mask = 1 << CR_CHAN(insn->chanspec);
+	unsigned int bits;
+	unsigned int port;
 
-	/* calculate port */
-	if (mask & 0x0000ffff) {	/* Port A in use */
+	if (mask & 0x0000ffff) {
 		bits = 0x0000ffff;
-
-		/* Enable Port A */
-		dev_private->control_2 |= ENABLE_PORT_A;
-		writew(dev_private->control_2,
-		       dev_private->me_regbase + ME_CONTROL_2);
-	} else {		/* Port B in use */
-
+		port = ENABLE_PORT_A;
+	} else {
 		bits = 0xffff0000;
-
-		/* Enable Port B */
-		dev_private->control_2 |= ENABLE_PORT_B;
-		writew(dev_private->control_2,
-		       dev_private->me_regbase + ME_CONTROL_2);
+		port = ENABLE_PORT_B;
 	}
 
-	if (data[0]) {
-		/* Config port as output */
-		s->io_bits |= bits;
-	} else {
-		/* Config port as input */
+	switch (data[0]) {
+	case INSN_CONFIG_DIO_INPUT:
 		s->io_bits &= ~bits;
+		dev_private->control_2 &= ~port;
+		break;
+	case INSN_CONFIG_DIO_OUTPUT:
+		s->io_bits |= bits;
+		dev_private->control_2 |= port;
+		break;
+	case INSN_CONFIG_DIO_QUERY:
+		data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
+		return insn->n;
+		break;
+	default:
+		return -EINVAL;
 	}
 
-	return 1;
+	/* Update the port configuration */
+	writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
+
+	return insn->n;
 }
 
-/* Digital instant input/outputs */
 static int me_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 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];
-	s->state &= ~mask;
-	s->state |= (mask & data[1]);
-
-	mask &= s->io_bits;
-	if (mask & 0x0000ffff) {	/* Port A */
-		writew((s->state & 0xffff),
-		       dev_private->me_regbase + ME_DIO_PORT_A);
-	} else {
-		data[1] &= ~0x0000ffff;
-		data[1] |= readw(dev_private->me_regbase + ME_DIO_PORT_A);
+	unsigned int bits = data[1];
+	unsigned int val;
+
+	mask &= s->io_bits;	/* only update the COMEDI_OUTPUT channels */
+	if (mask) {
+		s->state &= ~mask;
+		s->state |= (bits & mask);
+
+		if (mask & 0x0000ffff)
+			writew((s->state & 0xffff), mmio_porta);
+		if (mask & 0xffff0000)
+			writew(((s->state >> 16) & 0xffff), mmio_portb);
 	}
 
-	if (mask & 0xffff0000) {	/* Port B */
-		writew(((s->state >> 16) & 0xffff),
-		       dev_private->me_regbase + ME_DIO_PORT_B);
-	} else {
-		data[1] &= ~0xffff0000;
-		data[1] |= readw(dev_private->me_regbase + ME_DIO_PORT_B) << 16;
-	}
+	if (s->io_bits & 0x0000ffff)
+		val = s->state & 0xffff;
+	else
+		val = readw(mmio_porta);
+
+	if (s->io_bits & 0xffff0000)
+		val |= (s->state & 0xffff0000);
+	else
+		val |= (readw(mmio_portb) << 16);
+
+	data[1] = val;
 
 	return insn->n;
 }
 
-/*
- * ------------------------------------------------------------------
- *
- * ANALOG INPUT SECTION
- *
- * ------------------------------------------------------------------
- */
-
-/* Analog instant input */
 static int me_ai_insn_read(struct comedi_device *dev,
 			   struct comedi_subdevice *s,
-			   struct comedi_insn *insn, unsigned int *data)
+			   struct comedi_insn *insn,
+			   unsigned int *data)
 {
-	unsigned short value;
-	int chan = CR_CHAN((&insn->chanspec)[0]);
-	int rang = CR_RANGE((&insn->chanspec)[0]);
-	int aref = CR_AREF((&insn->chanspec)[0]);
+	struct me_private_data *dev_private = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int rang = CR_RANGE(insn->chanspec);
+	unsigned int aref = CR_AREF(insn->chanspec);
+	unsigned short val;
 	int i;
 
 	/* stop any running conversion */
@@ -356,15 +287,11 @@ static int me_ai_insn_read(struct comedi_device *dev,
 	writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
 
 	/* write to channel list fifo */
-	/* b3:b0 are the channel number */
-	value = chan & 0x0f;
-	/* b5:b4 are the channel gain */
-	value |= (rang & 0x03) << 4;
-	/* b6 channel polarity */
-	value |= (rang & 0x04) << 4;
-	/* b7 single or differential */
-	value |= ((aref & AREF_DIFF) ? 0x80 : 0);
-	writew(value & 0xff, dev_private->me_regbase + ME_CHANNEL_LIST);
+	val = chan & 0x0f;			/* b3:b0 channel */
+	val |= (rang & 0x03) << 4;		/* b5:b4 gain */
+	val |= (rang & 0x04) << 4;		/* b6 polarity */
+	val |= ((aref & AREF_DIFF) ? 0x80 : 0);	/* b7 differential */
+	writew(val & 0xff, dev_private->me_regbase + ME_CHANNEL_LIST);
 
 	/* set ADC mode to software trigger */
 	dev_private->control_1 |= SOFTWARE_TRIGGERED_ADC;
@@ -380,12 +307,11 @@ static int me_ai_insn_read(struct comedi_device *dev,
 
 	/* get value from ADC fifo */
 	if (i) {
-		data[0] =
-		    (readw(dev_private->me_regbase +
-			   ME_READ_AD_FIFO) ^ 0x800) & 0x0FFF;
+		val = readw(dev_private->me_regbase + ME_READ_AD_FIFO);
+		val = (val ^ 0x800) & 0x0fff;
+		data[0] = val;
 	} else {
-		printk(KERN_ERR "comedi%d: Cannot get single value\n",
-		       dev->minor);
+		dev_err(dev->class_dev, "Cannot get single value\n");
 		return -EIO;
 	}
 
@@ -396,55 +322,14 @@ static int me_ai_insn_read(struct comedi_device *dev,
 	return 1;
 }
 
-/*
- * ------------------------------------------------------------------
- *
- * HARDWARE TRIGGERED ANALOG INPUT SECTION
- *
- * ------------------------------------------------------------------
- */
-
-/* Cancel analog input autoscan */
-static int me_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
-{
-	/* disable interrupts */
-
-	/* stop any running conversion */
-	dev_private->control_1 &= 0xFFFC;
-	writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);
-
-	return 0;
-}
-
-/* Test analog input command */
-static int me_ai_do_cmd_test(struct comedi_device *dev,
-			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
-{
-	return 0;
-}
-
-/* Analog input command */
-static int me_ai_do_cmd(struct comedi_device *dev,
-			struct comedi_subdevice *s)
-{
-	return 0;
-}
-
-/*
- * ------------------------------------------------------------------
- *
- * ANALOG OUTPUT SECTION
- *
- * ------------------------------------------------------------------
- */
-
-/* Analog instant output */
 static int me_ao_insn_write(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data)
+			    struct comedi_insn *insn,
+			    unsigned int *data)
 {
-	int chan;
-	int rang;
+	struct me_private_data *dev_private = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int rang = CR_RANGE(insn->chanspec);
 	int i;
 
 	/* Enable all DAC */
@@ -457,9 +342,6 @@ static int me_ao_insn_write(struct comedi_device *dev,
 
 	/* Set dac-control register */
 	for (i = 0; i < insn->n; i++) {
-		chan = CR_CHAN((&insn->chanspec)[i]);
-		rang = CR_RANGE((&insn->chanspec)[i]);
-
 		/* clear bits for this channel */
 		dev_private->dac_control &= ~(0x0880 >> chan);
 		if (rang == 0)
@@ -477,7 +359,6 @@ static int me_ao_insn_write(struct comedi_device *dev,
 
 	/* Set data register */
 	for (i = 0; i < insn->n; i++) {
-		chan = CR_CHAN((&insn->chanspec)[i]);
 		writew((data[0] & s->maxdata),
 		       dev_private->me_regbase + ME_DAC_DATA_A + (chan << 1));
 		dev_private->ao_readback[chan] = (data[0] & s->maxdata);
@@ -486,36 +367,28 @@ static int me_ao_insn_write(struct comedi_device *dev,
 	/* Update dac with data registers */
 	readw(dev_private->me_regbase + ME_DAC_UPDATE);
 
-	return i;
+	return insn->n;
 }
 
-/* Analog output readback */
 static int me_ao_insn_read(struct comedi_device *dev,
-			   struct comedi_subdevice *s, struct comedi_insn *insn,
+			   struct comedi_subdevice *s,
+			   struct comedi_insn *insn,
 			   unsigned int *data)
 {
+	struct me_private_data *dev_private = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
 	int i;
 
-	for (i = 0; i < insn->n; i++) {
-		data[i] =
-		    dev_private->ao_readback[CR_CHAN((&insn->chanspec)[i])];
-	}
+	for (i = 0; i < insn->n; i++)
+		data[i] = dev_private->ao_readback[chan];
 
-	return 1;
+	return insn->n;
 }
 
-/*
- * ------------------------------------------------------------------
- *
- * INITIALISATION SECTION
- *
- * ------------------------------------------------------------------
- */
-
-/* Xilinx firmware download for card: ME-2600i */
 static int me2600_xilinx_download(struct comedi_device *dev,
 				  const u8 *data, size_t size)
 {
+	struct me_private_data *dev_private = dev->private;
 	unsigned int value;
 	unsigned int file_length;
 	unsigned int i;
@@ -566,8 +439,7 @@ static int me2600_xilinx_download(struct comedi_device *dev,
 	if (value & 0x20) {
 		/* Disable interrupt */
 		writel(0x00, dev_private->plx_regbase + PLX_INTCSR);
-		printk(KERN_ERR "comedi%d: Xilinx download failed\n",
-		       dev->minor);
+		dev_err(dev->class_dev, "Xilinx download failed\n");
 		return -EIO;
 	}
 
@@ -596,9 +468,10 @@ static int me2600_upload_firmware(struct comedi_device *dev)
 	return ret;
 }
 
-/* Reset device */
 static int me_reset(struct comedi_device *dev)
 {
+	struct me_private_data *dev_private = dev->private;
+
 	/* Reset board */
 	writew(0x00, dev_private->me_regbase + ME_CONTROL_1);
 	writew(0x00, dev_private->me_regbase + ME_CONTROL_2);
@@ -627,20 +500,14 @@ static const void *me_find_boardinfo(struct comedi_device *dev,
 	return NULL;
 }
 
-static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev)
+static int me_auto_attach(struct comedi_device *dev,
+				    unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	const struct me_board *board;
+	struct me_private_data *dev_private;
 	struct comedi_subdevice *s;
-	resource_size_t plx_regbase_tmp;
-	unsigned long plx_regbase_size_tmp;
-	resource_size_t me_regbase_tmp;
-	unsigned long me_regbase_size_tmp;
-	resource_size_t swap_regbase_tmp;
-	unsigned long swap_regbase_size_tmp;
-	resource_size_t regbase_tmp;
-	int result, error;
-
-	comedi_set_hw_dev(dev, &pcidev->dev);
+	int ret;
 
 	board = me_find_boardinfo(dev, pcidev);
 	if (!board)
@@ -648,123 +515,71 @@ static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev)
 	dev->board_ptr = board;
 	dev->board_name = board->name;
 
-	/* Allocate private memory */
-	if (alloc_private(dev, sizeof(struct me_private_data)) < 0)
+	dev_private = kzalloc(sizeof(*dev_private), GFP_KERNEL);
+	if (!dev_private)
 		return -ENOMEM;
+	dev->private = dev_private;
 
-	/* Enable PCI device and request PCI regions */
-	if (comedi_pci_enable(pcidev, dev->board_name) < 0) {
-		printk(KERN_ERR "comedi%d: Failed to enable PCI device and "
-		       "request regions\n", dev->minor);
-		return -EIO;
-	}
+	ret = comedi_pci_enable(pcidev, dev->board_name);
+	if (ret)
+		return ret;
+	dev->iobase = 1;	/* detach needs this */
 
-	/* Read PLX register base address [PCI_BASE_ADDRESS #0]. */
-	plx_regbase_tmp = pci_resource_start(pcidev, 0);
-	plx_regbase_size_tmp = pci_resource_len(pcidev, 0);
-	dev_private->plx_regbase =
-	    ioremap(plx_regbase_tmp, plx_regbase_size_tmp);
-	dev_private->plx_regbase_size = plx_regbase_size_tmp;
-	if (!dev_private->plx_regbase) {
-		printk("comedi%d: Failed to remap I/O memory\n", dev->minor);
+	dev_private->plx_regbase = ioremap(pci_resource_start(pcidev, 0),
+					   pci_resource_len(pcidev, 0));
+	if (!dev_private->plx_regbase)
 		return -ENOMEM;
-	}
-
-	/* Read Swap base address [PCI_BASE_ADDRESS #5]. */
-
-	swap_regbase_tmp = pci_resource_start(pcidev, 5);
-	swap_regbase_size_tmp = pci_resource_len(pcidev, 5);
-
-	if (!swap_regbase_tmp)
-		printk(KERN_ERR "comedi%d: Swap not present\n", dev->minor);
-
-	/*---------------------------------------------- Workaround start ---*/
-	if (plx_regbase_tmp & 0x0080) {
-		printk(KERN_ERR "comedi%d: PLX-Bug detected\n", dev->minor);
-
-		if (swap_regbase_tmp) {
-			regbase_tmp = plx_regbase_tmp;
-			plx_regbase_tmp = swap_regbase_tmp;
-			swap_regbase_tmp = regbase_tmp;
-
-			result = pci_write_config_dword(pcidev,
-							PCI_BASE_ADDRESS_0,
-							plx_regbase_tmp);
-			if (result != PCIBIOS_SUCCESSFUL)
-				return -EIO;
-
-			result = pci_write_config_dword(pcidev,
-							PCI_BASE_ADDRESS_5,
-							swap_regbase_tmp);
-			if (result != PCIBIOS_SUCCESSFUL)
-				return -EIO;
-		} else {
-			plx_regbase_tmp -= 0x80;
-			result = pci_write_config_dword(pcidev,
-							PCI_BASE_ADDRESS_0,
-							plx_regbase_tmp);
-			if (result != PCIBIOS_SUCCESSFUL)
-				return -EIO;
-		}
-	}
-	/*--------------------------------------------- Workaround end -----*/
-
-	/* Read Meilhaus register base address [PCI_BASE_ADDRESS #2]. */
 
-	me_regbase_tmp = pci_resource_start(pcidev, 2);
-	me_regbase_size_tmp = pci_resource_len(pcidev, 2);
-	dev_private->me_regbase_size = me_regbase_size_tmp;
-	dev_private->me_regbase = ioremap(me_regbase_tmp, me_regbase_size_tmp);
-	if (!dev_private->me_regbase) {
-		printk(KERN_ERR "comedi%d: Failed to remap I/O memory\n",
-		       dev->minor);
+	dev_private->me_regbase = ioremap(pci_resource_start(pcidev, 2),
+					  pci_resource_len(pcidev, 2));
+	if (!dev_private->me_regbase)
 		return -ENOMEM;
-	}
 
 	/* Download firmware and reset card */
 	if (board->device_id == ME2600_DEVICE_ID) {
-		result = me2600_upload_firmware(dev);
-		if (result < 0)
-			return result;
+		ret = me2600_upload_firmware(dev);
+		if (ret < 0)
+			return ret;
 	}
 	me_reset(dev);
 
-	error = comedi_alloc_subdevices(dev, 3);
-	if (error)
-		return error;
+	ret = comedi_alloc_subdevices(dev, 3);
+	if (ret)
+		return ret;
 
 	s = &dev->subdevices[0];
-	s->type = COMEDI_SUBD_AI;
-	s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
-	s->n_chan = board->ai_channel_nbr;
-	s->maxdata = board->ai_resolution_mask;
-	s->len_chanlist = board->ai_channel_nbr;
-	s->range_table = board->ai_range_list;
-	s->cancel = me_ai_cancel;
-	s->insn_read = me_ai_insn_read;
-	s->do_cmdtest = me_ai_do_cmd_test;
-	s->do_cmd = me_ai_do_cmd;
+	s->type		= COMEDI_SUBD_AI;
+	s->subdev_flags	= SDF_READABLE | SDF_COMMON;
+	s->n_chan	= 16;
+	s->maxdata	= 0x0fff;
+	s->len_chanlist	= 16;
+	s->range_table	= &me_ai_range;
+	s->insn_read	= me_ai_insn_read;
 
 	s = &dev->subdevices[1];
-	s->type = COMEDI_SUBD_AO;
-	s->subdev_flags = SDF_WRITEABLE | SDF_COMMON;
-	s->n_chan = board->ao_channel_nbr;
-	s->maxdata = board->ao_resolution_mask;
-	s->len_chanlist = board->ao_channel_nbr;
-	s->range_table = board->ao_range_list;
-	s->insn_read = me_ao_insn_read;
-	s->insn_write = me_ao_insn_write;
+	if (board->has_ao) {
+		s->type		= COMEDI_SUBD_AO;
+		s->subdev_flags	= SDF_WRITEABLE | SDF_COMMON;
+		s->n_chan	= 4;
+		s->maxdata	= 0x0fff;
+		s->len_chanlist	= 4;
+		s->range_table	= &me_ao_range;
+		s->insn_read	= me_ao_insn_read;
+		s->insn_write	= me_ao_insn_write;
+	} else {
+		s->type = COMEDI_SUBD_UNUSED;
+	}
 
 	s = &dev->subdevices[2];
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags = SDF_READABLE | SDF_WRITEABLE;
-	s->n_chan = board->dio_channel_nbr;
-	s->maxdata = 1;
-	s->len_chanlist = board->dio_channel_nbr;
-	s->range_table = &range_digital;
-	s->insn_bits = me_dio_insn_bits;
-	s->insn_config = me_dio_insn_config;
-	s->io_bits = 0;
+	s->type		= COMEDI_SUBD_DIO;
+	s->subdev_flags	= SDF_READABLE | SDF_WRITEABLE;
+	s->n_chan	= 32;
+	s->maxdata	= 1;
+	s->len_chanlist	= 32;
+	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);
@@ -775,6 +590,7 @@ static int me_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev)
 static void me_detach(struct comedi_device *dev)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct me_private_data *dev_private = dev->private;
 
 	if (dev_private) {
 		if (dev_private->me_regbase) {
@@ -785,26 +601,25 @@ static void me_detach(struct comedi_device *dev)
 			iounmap(dev_private->plx_regbase);
 	}
 	if (pcidev) {
-		if (dev_private->plx_regbase_size)
+		if (dev->iobase)
 			comedi_pci_disable(pcidev);
-		pci_dev_put(pcidev);
 	}
 }
 
 static struct comedi_driver me_daq_driver = {
 	.driver_name	= "me_daq",
 	.module		= THIS_MODULE,
-	.attach_pci	= me_attach_pci,
+	.auto_attach	= me_auto_attach,
 	.detach		= me_detach,
 };
 
-static int __devinit me_daq_pci_probe(struct pci_dev *dev,
+static int me_daq_pci_probe(struct pci_dev *dev,
 				      const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &me_daq_driver);
 }
 
-static void __devexit me_daq_pci_remove(struct pci_dev *dev)
+static void me_daq_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -820,7 +635,7 @@ static struct pci_driver me_daq_pci_driver = {
 	.name		= "me_daq",
 	.id_table	= me_daq_pci_table,
 	.probe		= me_daq_pci_probe,
-	.remove		= __devexit_p(me_daq_pci_remove),
+	.remove		= me_daq_pci_remove,
 };
 module_comedi_pci_driver(me_daq_driver, me_daq_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
index f8b7fae..67dc5ad 100644
--- a/drivers/staging/comedi/drivers/mpc624.c
+++ b/drivers/staging/comedi/drivers/mpc624.c
@@ -122,13 +122,12 @@ Configuration Options:
 #define MPC624_SPEED_6_875_Hz \
 	(MPC624_OSR4 | MPC624_OSR3 | MPC624_OSR2 | MPC624_OSR1 | MPC624_OSR0)
 /* -------------------------------------------------------------------------- */
-struct skel_private {
+struct mpc624_private {
 
 	/*  set by mpc624_attach() from driver's parameters */
 	unsigned long int ulConvertionRate;
 };
 
-#define devpriv ((struct skel_private *)dev->private)
 /* -------------------------------------------------------------------------- */
 static const struct comedi_lrange range_mpc624_bipolar1 = {
 	1,
@@ -155,6 +154,7 @@ static int mpc624_ai_rinsn(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
 			   unsigned int *data)
 {
+	struct mpc624_private *devpriv = dev->private;
 	int n, i;
 	unsigned long int data_in, data_out;
 	unsigned char ucPort;
@@ -283,6 +283,7 @@ static int mpc624_ai_rinsn(struct comedi_device *dev,
 
 static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+	struct mpc624_private *devpriv;
 	struct comedi_subdevice *s;
 	unsigned long iobase;
 	int ret;
@@ -297,9 +298,10 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	dev->iobase = iobase;
 	dev->board_name = "mpc624";
 
-	/*  Private structure initialization */
-	if (alloc_private(dev, sizeof(struct skel_private)) < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
 
 	switch (it->options[1]) {
 	case 0:
diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c
deleted file mode 100644
index c0c3329..0000000
--- a/drivers/staging/comedi/drivers/mpc8260cpm.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
-    comedi/drivers/mpc8260.c
-    driver for digital I/O pins on the MPC 8260 CPM module
-
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 2000,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.
-
-    You 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.
-
-*/
-/*
-Driver: mpc8260cpm
-Description: MPC8260 CPM module generic digital I/O lines
-Devices: [Motorola] MPC8260 CPM (mpc8260cpm)
-Author: ds
-Status: experimental
-Updated: Sat, 16 Mar 2002 17:34:48 -0800
-
-This driver is specific to the Motorola MPC8260 processor, allowing
-you to access the processor's generic digital I/O lines.
-
-It is apparently missing some code.
-*/
-
-#include "../comedidev.h"
-
-extern unsigned long mpc8260_dio_reserved[4];
-
-struct mpc8260cpm_private {
-
-	int data;
-
-};
-
-#define devpriv ((struct mpc8260cpm_private *)dev->private)
-
-static unsigned long *cpm_pdat(int port)
-{
-	switch (port) {
-	case 0:
-		return &io->iop_pdata;
-	case 1:
-		return &io->iop_pdatb;
-	case 2:
-		return &io->iop_pdatc;
-	case 3:
-		return &io->iop_pdatd;
-	}
-}
-
-static int mpc8260cpm_dio_config(struct comedi_device *dev,
-				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data)
-{
-	int n;
-	unsigned int d;
-	unsigned int mask;
-	int port;
-
-	port = (int)s->private;
-	mask = 1 << CR_CHAN(insn->chanspec);
-	if (mask & cpm_reserved_bits[port]) {
-		return -EINVAL;
-	}
-
-	switch (data[0]) {
-	case INSN_CONFIG_DIO_OUTPUT:
-		s->io_bits |= mask;
-		break;
-	case INSN_CONFIG_DIO_INPUT:
-		s->io_bits &= ~mask;
-		break;
-	case INSN_CONFIG_DIO_QUERY:
-		data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
-		return insn->n;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (port) {
-	case 0:
-		return &io->iop_pdira;
-	case 1:
-		return &io->iop_pdirb;
-	case 2:
-		return &io->iop_pdirc;
-	case 3:
-		return &io->iop_pdird;
-	}
-
-	return 1;
-}
-
-static int mpc8260cpm_dio_bits(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
-{
-	int port;
-	unsigned long *p;
-
-	p = cpm_pdat((int)s->private);
-
-	return insn->n;
-}
-
-static int mpc8260cpm_attach(struct comedi_device *dev,
-			     struct comedi_devconfig *it)
-{
-	struct comedi_subdevice *s;
-	int i;
-	int ret;
-
-	printk("comedi%d: mpc8260cpm: ", dev->minor);
-
-	dev->board_ptr = mpc8260cpm_boards + dev->board;
-
-	dev->board_name = thisboard->name;
-
-	if (alloc_private(dev, sizeof(struct mpc8260cpm_private)) < 0)
-		return -ENOMEM;
-
-	ret =comedi_alloc_subdevices(dev, 4);
-	if (ret)
-		return ret;
-
-	for (i = 0; i < 4; i++) {
-		s = &dev->subdevices[i];
-		s->type = COMEDI_SUBD_DIO;
-		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-		s->n_chan = 32;
-		s->maxdata = 1;
-		s->range_table = &range_digital;
-		s->insn_config = mpc8260cpm_dio_config;
-		s->insn_bits = mpc8260cpm_dio_bits;
-	}
-
-	return 1;
-}
-
-static void mpc8260cpm_detach(struct comedi_device *dev)
-{
-	/* Nothing to cleanup */
-}
-
-static struct comedi_driver mpc8260cpm_driver = {
-	.driver_name	= "mpc8260cpm",
-	.module		= THIS_MODULE,
-	.attach		= mpc8260cpm_attach,
-	.detach		= mpc8260cpm_detach,
-};
-module_comedi_driver(mpc8260cpm_driver);
diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
index 4625cb4..1f5f402 100644
--- a/drivers/staging/comedi/drivers/multiq3.c
+++ b/drivers/staging/comedi/drivers/multiq3.c
@@ -86,7 +86,6 @@ Devices: [Quanser Consulting] MultiQ-3 (multiq3)
 struct multiq3_private {
 	unsigned int ao_readback[2];
 };
-#define devpriv ((struct multiq3_private *)dev->private)
 
 static int multiq3_ai_insn_read(struct comedi_device *dev,
 				struct comedi_subdevice *s,
@@ -129,6 +128,7 @@ static int multiq3_ao_insn_read(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
 {
+	struct multiq3_private *devpriv = dev->private;
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 
@@ -142,6 +142,7 @@ static int multiq3_ao_insn_write(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
 				 struct comedi_insn *insn, unsigned int *data)
 {
+	struct multiq3_private *devpriv = dev->private;
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 
@@ -230,6 +231,7 @@ static void encoder_reset(struct comedi_device *dev)
 static int multiq3_attach(struct comedi_device *dev,
 			  struct comedi_devconfig *it)
 {
+	struct multiq3_private *devpriv;
 	int result = 0;
 	unsigned long iobase;
 	unsigned int irq;
@@ -256,9 +258,10 @@ static int multiq3_attach(struct comedi_device *dev,
 	if (result)
 		return result;
 
-	result = alloc_private(dev, sizeof(struct multiq3_private));
-	if (result < 0)
-		return result;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	s = &dev->subdevices[0];
 	/* ai subdevice */
diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
index 51295f3..5196b460 100644
--- a/drivers/staging/comedi/drivers/ni_6527.c
+++ b/drivers/staging/comedi/drivers/ni_6527.c
@@ -112,12 +112,11 @@ struct ni6527_private {
 	unsigned int filter_enable;
 };
 
-#define devpriv ((struct ni6527_private *)dev->private)
-
 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;
 	int chan = CR_CHAN(insn->chanspec);
 	unsigned int interval;
 
@@ -164,6 +163,8 @@ static int ni6527_di_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni6527_private *devpriv = dev->private;
+
 	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;
@@ -175,6 +176,8 @@ static int ni6527_do_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni6527_private *devpriv = dev->private;
+
 	if (data[0]) {
 		s->state &= ~data[0];
 		s->state |= (data[0] & data[1]);
@@ -202,6 +205,7 @@ static int ni6527_do_insn_bits(struct comedi_device *dev,
 static irqreturn_t ni6527_interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct ni6527_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[2];
 	unsigned int status;
 
@@ -243,29 +247,13 @@ static int ni6527_intr_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
-	if (cmd->scan_begin_arg != 0) {
-		cmd->scan_begin_arg = 0;
-		err++;
-	}
-	if (cmd->convert_arg != 0) {
-		cmd->convert_arg = 0;
-		err++;
-	}
-
-	if (cmd->scan_end_arg != 1) {
-		cmd->scan_end_arg = 1;
-		err++;
-	}
-	if (cmd->stop_arg != 0) {
-		cmd->stop_arg = 0;
-		err++;
-	}
+	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;
@@ -281,6 +269,7 @@ static int ni6527_intr_cmdtest(struct comedi_device *dev,
 static int ni6527_intr_cmd(struct comedi_device *dev,
 			   struct comedi_subdevice *s)
 {
+	struct ni6527_private *devpriv = dev->private;
 	/* struct comedi_cmd *cmd = &s->async->cmd; */
 
 	writeb(ClrEdge | ClrOverflow,
@@ -295,6 +284,8 @@ static int ni6527_intr_cmd(struct comedi_device *dev,
 static int ni6527_intr_cancel(struct comedi_device *dev,
 			      struct comedi_subdevice *s)
 {
+	struct ni6527_private *devpriv = dev->private;
+
 	writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
 
 	return 0;
@@ -312,6 +303,8 @@ static int ni6527_intr_insn_config(struct comedi_device *dev,
 				   struct comedi_subdevice *s,
 				   struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni6527_private *devpriv = dev->private;
+
 	if (insn->n < 1)
 		return -EINVAL;
 	if (data[0] != INSN_CONFIG_CHANGE_NOTIFY)
@@ -348,15 +341,18 @@ ni6527_find_boardinfo(struct pci_dev *pcidev)
 	return NULL;
 }
 
-static int __devinit ni6527_attach_pci(struct comedi_device *dev,
-				       struct pci_dev *pcidev)
+static int ni6527_auto_attach(struct comedi_device *dev,
+					unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct ni6527_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 
-	ret = alloc_private(dev, sizeof(struct ni6527_private));
-	if (ret < 0)
-		return ret;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	dev->board_ptr = ni6527_find_boardinfo(pcidev);
 	if (!dev->board_ptr)
@@ -430,6 +426,8 @@ static int __devinit ni6527_attach_pci(struct comedi_device *dev,
 
 static void ni6527_detach(struct comedi_device *dev)
 {
+	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);
@@ -444,17 +442,17 @@ static void ni6527_detach(struct comedi_device *dev)
 static struct comedi_driver ni6527_driver = {
 	.driver_name = DRIVER_NAME,
 	.module = THIS_MODULE,
-	.attach_pci = ni6527_attach_pci,
+	.auto_attach = ni6527_auto_attach,
 	.detach = ni6527_detach,
 };
 
-static int __devinit ni6527_pci_probe(struct pci_dev *dev,
+static int ni6527_pci_probe(struct pci_dev *dev,
 				      const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &ni6527_driver);
 }
 
-static void __devexit ni6527_pci_remove(struct pci_dev *dev)
+static void ni6527_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -463,7 +461,7 @@ static struct pci_driver ni6527_pci_driver = {
 	.name = DRIVER_NAME,
 	.id_table = ni6527_pci_table,
 	.probe = ni6527_pci_probe,
-	.remove = __devexit_p(ni6527_pci_remove)
+	.remove = ni6527_pci_remove
 };
 module_comedi_pci_driver(ni6527_driver, ni6527_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index 2a73ff5..2fb4b77 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -48,7 +48,6 @@ except maybe the 6514.
 
  */
 
-#define _GNU_SOURCE
 #define DEBUG 1
 #define DEBUG_FLAGS
 #include <linux/interrupt.h>
@@ -291,11 +290,6 @@ struct ni_65xx_private {
 	unsigned short dio_direction[NI_65XX_MAX_NUM_PORTS];
 };
 
-static inline struct ni_65xx_private *private(struct comedi_device *dev)
-{
-	return dev->private;
-}
-
 struct ni_65xx_subdevice_private {
 	unsigned base_port;
 };
@@ -319,6 +313,7 @@ static int ni_65xx_config_filter(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
 				 struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_65xx_private *devpriv = dev->private;
 	const unsigned chan = CR_CHAN(insn->chanspec);
 	const unsigned port =
 	    sprivate(s)->base_port + ni_65xx_port_by_channel(chan);
@@ -335,22 +330,22 @@ static int ni_65xx_config_filter(struct comedi_device *dev,
 			interval = max_filter_interval;
 		data[1] = interval * filter_resolution_ns;
 
-		if (interval != private(dev)->filter_interval) {
+		if (interval != devpriv->filter_interval) {
 			writeb(interval,
-			       private(dev)->mite->daq_io_addr +
+			       devpriv->mite->daq_io_addr +
 			       Filter_Interval);
-			private(dev)->filter_interval = interval;
+			devpriv->filter_interval = interval;
 		}
 
-		private(dev)->filter_enable[port] |=
+		devpriv->filter_enable[port] |=
 		    1 << (chan % ni_65xx_channels_per_port);
 	} else {
-		private(dev)->filter_enable[port] &=
+		devpriv->filter_enable[port] &=
 		    ~(1 << (chan % ni_65xx_channels_per_port));
 	}
 
-	writeb(private(dev)->filter_enable[port],
-	       private(dev)->mite->daq_io_addr + Filter_Enable(port));
+	writeb(devpriv->filter_enable[port],
+	       devpriv->mite->daq_io_addr + Filter_Enable(port));
 
 	return 2;
 }
@@ -359,6 +354,7 @@ static int ni_65xx_dio_insn_config(struct comedi_device *dev,
 				   struct comedi_subdevice *s,
 				   struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_65xx_private *devpriv = dev->private;
 	unsigned port;
 
 	if (insn->n < 1)
@@ -372,21 +368,21 @@ static int ni_65xx_dio_insn_config(struct comedi_device *dev,
 	case INSN_CONFIG_DIO_OUTPUT:
 		if (s->type != COMEDI_SUBD_DIO)
 			return -EINVAL;
-		private(dev)->dio_direction[port] = COMEDI_OUTPUT;
-		writeb(0, private(dev)->mite->daq_io_addr + Port_Select(port));
+		devpriv->dio_direction[port] = COMEDI_OUTPUT;
+		writeb(0, devpriv->mite->daq_io_addr + Port_Select(port));
 		return 1;
 		break;
 	case INSN_CONFIG_DIO_INPUT:
 		if (s->type != COMEDI_SUBD_DIO)
 			return -EINVAL;
-		private(dev)->dio_direction[port] = COMEDI_INPUT;
-		writeb(1, private(dev)->mite->daq_io_addr + Port_Select(port));
+		devpriv->dio_direction[port] = COMEDI_INPUT;
+		writeb(1, devpriv->mite->daq_io_addr + Port_Select(port));
 		return 1;
 		break;
 	case INSN_CONFIG_DIO_QUERY:
 		if (s->type != COMEDI_SUBD_DIO)
 			return -EINVAL;
-		data[1] = private(dev)->dio_direction[port];
+		data[1] = devpriv->dio_direction[port];
 		return insn->n;
 		break;
 	default:
@@ -399,6 +395,7 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
 				 struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_65xx_private *devpriv = dev->private;
 	unsigned base_bitfield_channel;
 	const unsigned max_ports_per_bitfield = 5;
 	unsigned read_bits = 0;
@@ -432,18 +429,18 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
 		port_data &= 0xff;
 		if (port_mask) {
 			unsigned bits;
-			private(dev)->output_bits[port] &= ~port_mask;
-			private(dev)->output_bits[port] |=
+			devpriv->output_bits[port] &= ~port_mask;
+			devpriv->output_bits[port] |=
 			    port_data & port_mask;
-			bits = private(dev)->output_bits[port];
+			bits = devpriv->output_bits[port];
 			if (board(dev)->invert_outputs)
 				bits = ~bits;
 			writeb(bits,
-			       private(dev)->mite->daq_io_addr +
+			       devpriv->mite->daq_io_addr +
 			       Port_Data(port));
 		}
 		port_read_bits =
-		    readb(private(dev)->mite->daq_io_addr + Port_Data(port));
+		    readb(devpriv->mite->daq_io_addr + Port_Data(port));
 		if (s->type == COMEDI_SUBD_DO && board(dev)->invert_outputs) {
 			/* Outputs inverted, so invert value read back from
 			 * DO subdevice.  (Does not apply to boards with DIO
@@ -464,17 +461,18 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
 static irqreturn_t ni_65xx_interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct ni_65xx_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[2];
 	unsigned int status;
 
-	status = readb(private(dev)->mite->daq_io_addr + Change_Status);
+	status = readb(devpriv->mite->daq_io_addr + Change_Status);
 	if ((status & MasterInterruptStatus) == 0)
 		return IRQ_NONE;
 	if ((status & EdgeStatus) == 0)
 		return IRQ_NONE;
 
 	writeb(ClrEdge | ClrOverflow,
-	       private(dev)->mite->daq_io_addr + Clear_Register);
+	       devpriv->mite->daq_io_addr + Clear_Register);
 
 	comedi_buf_put(s->async, 0);
 	s->async->events |= COMEDI_CB_EOS;
@@ -505,29 +503,13 @@ static int ni_65xx_intr_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
-	if (cmd->scan_begin_arg != 0) {
-		cmd->scan_begin_arg = 0;
-		err++;
-	}
-	if (cmd->convert_arg != 0) {
-		cmd->convert_arg = 0;
-		err++;
-	}
-
-	if (cmd->scan_end_arg != 1) {
-		cmd->scan_end_arg = 1;
-		err++;
-	}
-	if (cmd->stop_arg != 0) {
-		cmd->stop_arg = 0;
-		err++;
-	}
+	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;
@@ -543,13 +525,14 @@ static int ni_65xx_intr_cmdtest(struct comedi_device *dev,
 static int ni_65xx_intr_cmd(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
+	struct ni_65xx_private *devpriv = dev->private;
 	/* struct comedi_cmd *cmd = &s->async->cmd; */
 
 	writeb(ClrEdge | ClrOverflow,
-	       private(dev)->mite->daq_io_addr + Clear_Register);
+	       devpriv->mite->daq_io_addr + Clear_Register);
 	writeb(FallingEdgeIntEnable | RisingEdgeIntEnable |
 	       MasterInterruptEnable | EdgeIntEnable,
-	       private(dev)->mite->daq_io_addr + Master_Interrupt_Control);
+	       devpriv->mite->daq_io_addr + Master_Interrupt_Control);
 
 	return 0;
 }
@@ -557,8 +540,9 @@ static int ni_65xx_intr_cmd(struct comedi_device *dev,
 static int ni_65xx_intr_cancel(struct comedi_device *dev,
 			       struct comedi_subdevice *s)
 {
-	writeb(0x00,
-	       private(dev)->mite->daq_io_addr + Master_Interrupt_Control);
+	struct ni_65xx_private *devpriv = dev->private;
+
+	writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
 
 	return 0;
 }
@@ -576,35 +560,37 @@ static int ni_65xx_intr_insn_config(struct comedi_device *dev,
 				    struct comedi_insn *insn,
 				    unsigned int *data)
 {
+	struct ni_65xx_private *devpriv = dev->private;
+
 	if (insn->n < 1)
 		return -EINVAL;
 	if (data[0] != INSN_CONFIG_CHANGE_NOTIFY)
 		return -EINVAL;
 
 	writeb(data[1],
-	       private(dev)->mite->daq_io_addr +
+	       devpriv->mite->daq_io_addr +
 	       Rising_Edge_Detection_Enable(0));
 	writeb(data[1] >> 8,
-	       private(dev)->mite->daq_io_addr +
+	       devpriv->mite->daq_io_addr +
 	       Rising_Edge_Detection_Enable(0x10));
 	writeb(data[1] >> 16,
-	       private(dev)->mite->daq_io_addr +
+	       devpriv->mite->daq_io_addr +
 	       Rising_Edge_Detection_Enable(0x20));
 	writeb(data[1] >> 24,
-	       private(dev)->mite->daq_io_addr +
+	       devpriv->mite->daq_io_addr +
 	       Rising_Edge_Detection_Enable(0x30));
 
 	writeb(data[2],
-	       private(dev)->mite->daq_io_addr +
+	       devpriv->mite->daq_io_addr +
 	       Falling_Edge_Detection_Enable(0));
 	writeb(data[2] >> 8,
-	       private(dev)->mite->daq_io_addr +
+	       devpriv->mite->daq_io_addr +
 	       Falling_Edge_Detection_Enable(0x10));
 	writeb(data[2] >> 16,
-	       private(dev)->mite->daq_io_addr +
+	       devpriv->mite->daq_io_addr +
 	       Falling_Edge_Detection_Enable(0x20));
 	writeb(data[2] >> 24,
-	       private(dev)->mite->daq_io_addr +
+	       devpriv->mite->daq_io_addr +
 	       Falling_Edge_Detection_Enable(0x30));
 
 	return 2;
@@ -624,35 +610,38 @@ ni_65xx_find_boardinfo(struct pci_dev *pcidev)
 	return NULL;
 }
 
-static int __devinit ni_65xx_attach_pci(struct comedi_device *dev,
-					struct pci_dev *pcidev)
+static int ni_65xx_auto_attach(struct comedi_device *dev,
+					 unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct ni_65xx_private *devpriv;
 	struct comedi_subdevice *s;
 	unsigned i;
 	int ret;
 
-	ret = alloc_private(dev, sizeof(struct ni_65xx_private));
-	if (ret < 0)
-		return ret;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	dev->board_ptr = ni_65xx_find_boardinfo(pcidev);
 	if (!dev->board_ptr)
 		return -ENODEV;
 
-	private(dev)->mite = mite_alloc(pcidev);
-	if (!private(dev)->mite)
+	devpriv->mite = mite_alloc(pcidev);
+	if (!devpriv->mite)
 		return -ENOMEM;
 
-	ret = mite_setup(private(dev)->mite);
+	ret = mite_setup(devpriv->mite);
 	if (ret < 0) {
 		dev_warn(dev->class_dev, "error setting up mite\n");
 		return ret;
 	}
 
 	dev->board_name = board(dev)->name;
-	dev->irq = mite_irq(private(dev)->mite);
+	dev->irq = mite_irq(devpriv->mite);
 	dev_info(dev->class_dev, "board: %s, ID=0x%02x", dev->board_name,
-	       readb(private(dev)->mite->daq_io_addr + ID_Register));
+	       readb(devpriv->mite->daq_io_addr + ID_Register));
 
 	ret = comedi_alloc_subdevices(dev, 4);
 	if (ret)
@@ -710,7 +699,7 @@ static int __devinit ni_65xx_attach_pci(struct comedi_device *dev,
 		for (i = 0; i < board(dev)->num_dio_ports; ++i) {
 			/*  configure all ports for input */
 			writeb(0x1,
-			       private(dev)->mite->daq_io_addr +
+			       devpriv->mite->daq_io_addr +
 			       Port_Select(i));
 		}
 	} else {
@@ -732,21 +721,21 @@ static int __devinit ni_65xx_attach_pci(struct comedi_device *dev,
 
 	for (i = 0; i < ni_65xx_total_num_ports(board(dev)); ++i) {
 		writeb(0x00,
-		       private(dev)->mite->daq_io_addr + Filter_Enable(i));
+		       devpriv->mite->daq_io_addr + Filter_Enable(i));
 		if (board(dev)->invert_outputs)
 			writeb(0x01,
-			       private(dev)->mite->daq_io_addr + Port_Data(i));
+			       devpriv->mite->daq_io_addr + Port_Data(i));
 		else
 			writeb(0x00,
-			       private(dev)->mite->daq_io_addr + Port_Data(i));
+			       devpriv->mite->daq_io_addr + Port_Data(i));
 	}
 	writeb(ClrEdge | ClrOverflow,
-	       private(dev)->mite->daq_io_addr + Clear_Register);
+	       devpriv->mite->daq_io_addr + Clear_Register);
 	writeb(0x00,
-	       private(dev)->mite->daq_io_addr + Master_Interrupt_Control);
+	       devpriv->mite->daq_io_addr + Master_Interrupt_Control);
 
 	/* Set filter interval to 0  (32bit reg) */
-	writeb(0x00000000, private(dev)->mite->daq_io_addr + Filter_Interval);
+	writeb(0x00000000, devpriv->mite->daq_io_addr + Filter_Interval);
 
 	ret = request_irq(dev->irq, ni_65xx_interrupt, IRQF_SHARED,
 			  "ni_65xx", dev);
@@ -760,15 +749,16 @@ static int __devinit ni_65xx_attach_pci(struct comedi_device *dev,
 
 static void ni_65xx_detach(struct comedi_device *dev)
 {
-	if (private(dev) && private(dev)->mite
-	    && private(dev)->mite->daq_io_addr) {
+	struct ni_65xx_private *devpriv = dev->private;
+
+	if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr) {
 		writeb(0x00,
-		       private(dev)->mite->daq_io_addr +
+		       devpriv->mite->daq_io_addr +
 		       Master_Interrupt_Control);
 	}
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if (private(dev)) {
+	if (devpriv) {
 		struct comedi_subdevice *s;
 		unsigned i;
 
@@ -777,9 +767,9 @@ static void ni_65xx_detach(struct comedi_device *dev)
 			kfree(s->private);
 			s->private = NULL;
 		}
-		if (private(dev)->mite) {
-			mite_unsetup(private(dev)->mite);
-			mite_free(private(dev)->mite);
+		if (devpriv->mite) {
+			mite_unsetup(devpriv->mite);
+			mite_free(devpriv->mite);
 		}
 	}
 }
@@ -787,17 +777,17 @@ static void ni_65xx_detach(struct comedi_device *dev)
 static struct comedi_driver ni_65xx_driver = {
 	.driver_name = "ni_65xx",
 	.module = THIS_MODULE,
-	.attach_pci = ni_65xx_attach_pci,
+	.auto_attach = ni_65xx_auto_attach,
 	.detach = ni_65xx_detach,
 };
 
-static int __devinit ni_65xx_pci_probe(struct pci_dev *dev,
+static int ni_65xx_pci_probe(struct pci_dev *dev,
 				       const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &ni_65xx_driver);
 }
 
-static void __devexit ni_65xx_pci_remove(struct pci_dev *dev)
+static void ni_65xx_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -806,7 +796,7 @@ static struct pci_driver ni_65xx_pci_driver = {
 	.name = "ni_65xx",
 	.id_table = ni_65xx_pci_table,
 	.probe = ni_65xx_pci_probe,
-	.remove = __devexit_p(ni_65xx_pci_remove)
+	.remove = ni_65xx_pci_remove
 };
 module_comedi_pci_driver(ni_65xx_driver, ni_65xx_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
index df2f3b0..26baf9c 100644
--- a/drivers/staging/comedi/drivers/ni_660x.c
+++ b/drivers/staging/comedi/drivers/ni_660x.c
@@ -419,16 +419,6 @@ static const struct ni_660x_board ni_660x_boards[] = {
 #define NI_660X_MAX_NUM_CHIPS 2
 #define NI_660X_MAX_NUM_COUNTERS (NI_660X_MAX_NUM_CHIPS * counters_per_chip)
 
-static DEFINE_PCI_DEVICE_TABLE(ni_660x_pci_table) = {
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2c60)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1310)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1360)},
-	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2cc0)},
-	{0}
-};
-
-MODULE_DEVICE_TABLE(pci, ni_660x_pci_table);
-
 struct ni_660x_private {
 	struct mite_struct *mite;
 	struct ni_gpct_device *counter_dev;
@@ -443,78 +433,11 @@ struct ni_660x_private {
 	unsigned short pfi_output_selects[NUM_PFI_CHANNELS];
 };
 
-static inline struct ni_660x_private *private(struct comedi_device *dev)
-{
-	return dev->private;
-}
-
-/* initialized in ni_660x_attach_pci() */
-static inline const struct ni_660x_board *board(struct comedi_device *dev)
-{
-	return dev->board_ptr;
-}
-
-static int ni_660x_attach_pci(struct comedi_device *dev,
-			      struct pci_dev *pcidev);
-static void ni_660x_detach(struct comedi_device *dev);
-static void init_tio_chip(struct comedi_device *dev, int chipset);
-static void ni_660x_select_pfi_output(struct comedi_device *dev,
-				      unsigned pfi_channel,
-				      unsigned output_select);
-
-static struct comedi_driver ni_660x_driver = {
-	.driver_name = "ni_660x",
-	.module = THIS_MODULE,
-	.attach_pci = ni_660x_attach_pci,
-	.detach = ni_660x_detach,
-};
-
-static int __devinit ni_660x_pci_probe(struct pci_dev *dev,
-				       const struct pci_device_id *ent)
-{
-	return comedi_pci_auto_config(dev, &ni_660x_driver);
-}
-
-static void __devexit ni_660x_pci_remove(struct pci_dev *dev)
-{
-	comedi_pci_auto_unconfig(dev);
-}
-
-static struct pci_driver ni_660x_pci_driver = {
-	.name = "ni_660x",
-	.id_table = ni_660x_pci_table,
-	.probe = ni_660x_pci_probe,
-	.remove = __devexit_p(ni_660x_pci_remove)
-};
-module_comedi_pci_driver(ni_660x_driver, ni_660x_pci_driver);
-
-static int ni_660x_set_pfi_routing(struct comedi_device *dev, unsigned chan,
-				   unsigned source);
-
-/* Possible instructions for a GPCT */
-static int ni_660x_GPCT_rinsn(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data);
-static int ni_660x_GPCT_insn_config(struct comedi_device *dev,
-				    struct comedi_subdevice *s,
-				    struct comedi_insn *insn,
-				    unsigned int *data);
-static int ni_660x_GPCT_winsn(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data);
-
-/* Possible instructions for Digital IO */
-static int ni_660x_dio_insn_config(struct comedi_device *dev,
-				   struct comedi_subdevice *s,
-				   struct comedi_insn *insn,
-				   unsigned int *data);
-static int ni_660x_dio_insn_bits(struct comedi_device *dev,
-				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data);
-
 static inline unsigned ni_660x_num_counters(struct comedi_device *dev)
 {
-	return board(dev)->n_chips * counters_per_chip;
+	const struct ni_660x_board *board = comedi_board(dev);
+
+	return board->n_chips * counters_per_chip;
 }
 
 static enum NI_660x_Register ni_gpct_to_660x_register(enum ni_gpct_register reg)
@@ -737,8 +660,9 @@ static inline void ni_660x_write_register(struct comedi_device *dev,
 					  unsigned chip_index, unsigned bits,
 					  enum NI_660x_Register reg)
 {
+	struct ni_660x_private *devpriv = dev->private;
 	void __iomem *write_address =
-	    private(dev)->mite->daq_io_addr + GPCT_OFFSET[chip_index] +
+	    devpriv->mite->daq_io_addr + GPCT_OFFSET[chip_index] +
 	    registerData[reg].offset;
 
 	switch (registerData[reg].size) {
@@ -758,8 +682,9 @@ static inline unsigned ni_660x_read_register(struct comedi_device *dev,
 					     unsigned chip_index,
 					     enum NI_660x_Register reg)
 {
+	struct ni_660x_private *devpriv = dev->private;
 	void __iomem *read_address =
-	    private(dev)->mite->daq_io_addr + GPCT_OFFSET[chip_index] +
+	    devpriv->mite->daq_io_addr + GPCT_OFFSET[chip_index] +
 	    registerData[reg].offset;
 
 	switch (registerData[reg].size) {
@@ -806,54 +731,56 @@ static inline void ni_660x_set_dma_channel(struct comedi_device *dev,
 					   unsigned mite_channel,
 					   struct ni_gpct *counter)
 {
+	struct ni_660x_private *devpriv = dev->private;
 	unsigned long flags;
-	spin_lock_irqsave(&private(dev)->soft_reg_copy_lock, flags);
-	private(dev)->dma_configuration_soft_copies[counter->chip_index] &=
+
+	spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags);
+	devpriv->dma_configuration_soft_copies[counter->chip_index] &=
 	    ~dma_select_mask(mite_channel);
-	private(dev)->dma_configuration_soft_copies[counter->chip_index] |=
+	devpriv->dma_configuration_soft_copies[counter->chip_index] |=
 	    dma_select_bits(mite_channel,
 			    dma_selection_counter(counter->counter_index));
 	ni_660x_write_register(dev, counter->chip_index,
-			       private(dev)->
-			       dma_configuration_soft_copies
+			       devpriv->dma_configuration_soft_copies
 			       [counter->chip_index] |
 			       dma_reset_bit(mite_channel), DMAConfigRegister);
 	mmiowb();
-	spin_unlock_irqrestore(&private(dev)->soft_reg_copy_lock, flags);
+	spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags);
 }
 
 static inline void ni_660x_unset_dma_channel(struct comedi_device *dev,
 					     unsigned mite_channel,
 					     struct ni_gpct *counter)
 {
+	struct ni_660x_private *devpriv = dev->private;
 	unsigned long flags;
-	spin_lock_irqsave(&private(dev)->soft_reg_copy_lock, flags);
-	private(dev)->dma_configuration_soft_copies[counter->chip_index] &=
+
+	spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags);
+	devpriv->dma_configuration_soft_copies[counter->chip_index] &=
 	    ~dma_select_mask(mite_channel);
-	private(dev)->dma_configuration_soft_copies[counter->chip_index] |=
+	devpriv->dma_configuration_soft_copies[counter->chip_index] |=
 	    dma_select_bits(mite_channel, dma_selection_none);
 	ni_660x_write_register(dev, counter->chip_index,
-			       private(dev)->
-			       dma_configuration_soft_copies
+			       devpriv->dma_configuration_soft_copies
 			       [counter->chip_index], DMAConfigRegister);
 	mmiowb();
-	spin_unlock_irqrestore(&private(dev)->soft_reg_copy_lock, flags);
+	spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags);
 }
 
 static int ni_660x_request_mite_channel(struct comedi_device *dev,
 					struct ni_gpct *counter,
 					enum comedi_io_direction direction)
 {
+	struct ni_660x_private *devpriv = dev->private;
 	unsigned long flags;
 	struct mite_channel *mite_chan;
 
-	spin_lock_irqsave(&private(dev)->mite_channel_lock, flags);
+	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
 	BUG_ON(counter->mite_chan);
-	mite_chan =
-	    mite_request_channel(private(dev)->mite, mite_ring(private(dev),
-							       counter));
+	mite_chan = mite_request_channel(devpriv->mite,
+					 mite_ring(devpriv, counter));
 	if (mite_chan == NULL) {
-		spin_unlock_irqrestore(&private(dev)->mite_channel_lock, flags);
+		spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 		comedi_error(dev,
 			     "failed to reserve mite dma channel for counter.");
 		return -EBUSY;
@@ -861,16 +788,17 @@ static int ni_660x_request_mite_channel(struct comedi_device *dev,
 	mite_chan->dir = direction;
 	ni_tio_set_mite_channel(counter, mite_chan);
 	ni_660x_set_dma_channel(dev, mite_chan->channel, counter);
-	spin_unlock_irqrestore(&private(dev)->mite_channel_lock, flags);
+	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 	return 0;
 }
 
 static void ni_660x_release_mite_channel(struct comedi_device *dev,
 					 struct ni_gpct *counter)
 {
+	struct ni_660x_private *devpriv = dev->private;
 	unsigned long flags;
 
-	spin_lock_irqsave(&private(dev)->mite_channel_lock, flags);
+	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
 	if (counter->mite_chan) {
 		struct mite_channel *mite_chan = counter->mite_chan;
 
@@ -878,7 +806,7 @@ static void ni_660x_release_mite_channel(struct comedi_device *dev,
 		ni_tio_set_mite_channel(counter, NULL);
 		mite_release_channel(mite_chan);
 	}
-	spin_unlock_irqrestore(&private(dev)->mite_channel_lock, flags);
+	spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 }
 
 static int ni_660x_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
@@ -947,6 +875,7 @@ static void ni_660x_handle_gpct_interrupt(struct comedi_device *dev,
 static irqreturn_t ni_660x_interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct ni_660x_private *devpriv = dev->private;
 	struct comedi_subdevice *s;
 	unsigned i;
 	unsigned long flags;
@@ -954,24 +883,26 @@ static irqreturn_t ni_660x_interrupt(int irq, void *d)
 	if (dev->attached == 0)
 		return IRQ_NONE;
 	/* lock to avoid race with comedi_poll */
-	spin_lock_irqsave(&private(dev)->interrupt_lock, flags);
+	spin_lock_irqsave(&devpriv->interrupt_lock, flags);
 	smp_mb();
 	for (i = 0; i < ni_660x_num_counters(dev); ++i) {
 		s = &dev->subdevices[NI_660X_GPCT_SUBDEV(i)];
 		ni_660x_handle_gpct_interrupt(dev, s);
 	}
-	spin_unlock_irqrestore(&private(dev)->interrupt_lock, flags);
+	spin_unlock_irqrestore(&devpriv->interrupt_lock, flags);
 	return IRQ_HANDLED;
 }
 
 static int ni_660x_input_poll(struct comedi_device *dev,
 			      struct comedi_subdevice *s)
 {
+	struct ni_660x_private *devpriv = dev->private;
 	unsigned long flags;
+
 	/* lock to avoid race with comedi_poll */
-	spin_lock_irqsave(&private(dev)->interrupt_lock, flags);
+	spin_lock_irqsave(&devpriv->interrupt_lock, flags);
 	mite_sync_input_dma(subdev_to_counter(s)->mite_chan, s->async);
-	spin_unlock_irqrestore(&private(dev)->interrupt_lock, flags);
+	spin_unlock_irqrestore(&devpriv->interrupt_lock, flags);
 	return comedi_buf_read_n_available(s->async);
 }
 
@@ -979,9 +910,10 @@ static int ni_660x_buf_change(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
 			      unsigned long new_size)
 {
+	struct ni_660x_private *devpriv = dev->private;
 	int ret;
 
-	ret = mite_buf_change(mite_ring(private(dev), subdev_to_counter(s)),
+	ret = mite_buf_change(mite_ring(devpriv, subdev_to_counter(s)),
 			      s->async);
 	if (ret < 0)
 		return ret;
@@ -991,32 +923,35 @@ static int ni_660x_buf_change(struct comedi_device *dev,
 
 static int ni_660x_allocate_private(struct comedi_device *dev)
 {
-	int retval;
+	struct ni_660x_private *devpriv;
 	unsigned i;
 
-	retval = alloc_private(dev, sizeof(struct ni_660x_private));
-	if (retval < 0)
-		return retval;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
-	spin_lock_init(&private(dev)->mite_channel_lock);
-	spin_lock_init(&private(dev)->interrupt_lock);
-	spin_lock_init(&private(dev)->soft_reg_copy_lock);
+	spin_lock_init(&devpriv->mite_channel_lock);
+	spin_lock_init(&devpriv->interrupt_lock);
+	spin_lock_init(&devpriv->soft_reg_copy_lock);
 	for (i = 0; i < NUM_PFI_CHANNELS; ++i)
-		private(dev)->pfi_output_selects[i] = pfi_output_select_counter;
+		devpriv->pfi_output_selects[i] = pfi_output_select_counter;
 
 	return 0;
 }
 
 static int ni_660x_alloc_mite_rings(struct comedi_device *dev)
 {
+	const struct ni_660x_board *board = comedi_board(dev);
+	struct ni_660x_private *devpriv = dev->private;
 	unsigned i;
 	unsigned j;
 
-	for (i = 0; i < board(dev)->n_chips; ++i) {
+	for (i = 0; i < board->n_chips; ++i) {
 		for (j = 0; j < counters_per_chip; ++j) {
-			private(dev)->mite_rings[i][j] =
-			    mite_alloc_ring(private(dev)->mite);
-			if (private(dev)->mite_rings[i][j] == NULL)
+			devpriv->mite_rings[i][j] =
+			    mite_alloc_ring(devpriv->mite);
+			if (devpriv->mite_rings[i][j] == NULL)
 				return -ENOMEM;
 		}
 	}
@@ -1025,12 +960,14 @@ static int ni_660x_alloc_mite_rings(struct comedi_device *dev)
 
 static void ni_660x_free_mite_rings(struct comedi_device *dev)
 {
+	const struct ni_660x_board *board = comedi_board(dev);
+	struct ni_660x_private *devpriv = dev->private;
 	unsigned i;
 	unsigned j;
 
-	for (i = 0; i < board(dev)->n_chips; ++i) {
+	for (i = 0; i < board->n_chips; ++i) {
 		for (j = 0; j < counters_per_chip; ++j)
-			mite_free_ring(private(dev)->mite_rings[i][j]);
+			mite_free_ring(devpriv->mite_rings[i][j]);
 	}
 }
 
@@ -1048,145 +985,6 @@ ni_660x_find_boardinfo(struct pci_dev *pcidev)
 	return NULL;
 }
 
-static int __devinit ni_660x_attach_pci(struct comedi_device *dev,
-					struct pci_dev *pcidev)
-{
-	struct comedi_subdevice *s;
-	int ret;
-	unsigned i;
-	unsigned global_interrupt_config_bits;
-
-	ret = ni_660x_allocate_private(dev);
-	if (ret < 0)
-		return ret;
-	dev->board_ptr = ni_660x_find_boardinfo(pcidev);
-	if (!dev->board_ptr)
-		return -ENODEV;
-	private(dev)->mite = mite_alloc(pcidev);
-	if (!private(dev)->mite)
-		return -ENOMEM;
-
-	dev->board_name = board(dev)->name;
-
-	ret = mite_setup2(private(dev)->mite, 1);
-	if (ret < 0) {
-		dev_warn(dev->class_dev, "error setting up mite\n");
-		return ret;
-	}
-	comedi_set_hw_dev(dev, &private(dev)->mite->pcidev->dev);
-	ret = ni_660x_alloc_mite_rings(dev);
-	if (ret < 0)
-		return ret;
-
-	ret = comedi_alloc_subdevices(dev, 2 + NI_660X_MAX_NUM_COUNTERS);
-	if (ret)
-		return ret;
-
-	s = &dev->subdevices[0];
-	/* Old GENERAL-PURPOSE COUNTER/TIME (GPCT) subdevice, no longer used */
-	s->type = COMEDI_SUBD_UNUSED;
-
-	s = &dev->subdevices[NI_660X_DIO_SUBDEV];
-	/* DIGITAL I/O SUBDEVICE */
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-	s->n_chan = NUM_PFI_CHANNELS;
-	s->maxdata = 1;
-	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);
-
-	private(dev)->counter_dev = ni_gpct_device_construct(dev,
-						     &ni_gpct_write_register,
-						     &ni_gpct_read_register,
-						     ni_gpct_variant_660x,
-						     ni_660x_num_counters
-						     (dev));
-	if (private(dev)->counter_dev == NULL)
-		return -ENOMEM;
-	for (i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i) {
-		s = &dev->subdevices[NI_660X_GPCT_SUBDEV(i)];
-		if (i < ni_660x_num_counters(dev)) {
-			s->type = COMEDI_SUBD_COUNTER;
-			s->subdev_flags =
-			    SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL |
-			    SDF_CMD_READ /* | SDF_CMD_WRITE */ ;
-			s->n_chan = 3;
-			s->maxdata = 0xffffffff;
-			s->insn_read = ni_660x_GPCT_rinsn;
-			s->insn_write = ni_660x_GPCT_winsn;
-			s->insn_config = ni_660x_GPCT_insn_config;
-			s->do_cmd = &ni_660x_cmd;
-			s->len_chanlist = 1;
-			s->do_cmdtest = &ni_660x_cmdtest;
-			s->cancel = &ni_660x_cancel;
-			s->poll = &ni_660x_input_poll;
-			s->async_dma_dir = DMA_BIDIRECTIONAL;
-			s->buf_change = &ni_660x_buf_change;
-			s->private = &private(dev)->counter_dev->counters[i];
-
-			private(dev)->counter_dev->counters[i].chip_index =
-			    i / counters_per_chip;
-			private(dev)->counter_dev->counters[i].counter_index =
-			    i % counters_per_chip;
-		} else {
-			s->type = COMEDI_SUBD_UNUSED;
-		}
-	}
-	for (i = 0; i < board(dev)->n_chips; ++i)
-		init_tio_chip(dev, i);
-
-	for (i = 0; i < ni_660x_num_counters(dev); ++i)
-		ni_tio_init_counter(&private(dev)->counter_dev->counters[i]);
-
-	for (i = 0; i < NUM_PFI_CHANNELS; ++i) {
-		if (i < min_counter_pfi_chan)
-			ni_660x_set_pfi_routing(dev, i, pfi_output_select_do);
-		else
-			ni_660x_set_pfi_routing(dev, i,
-						pfi_output_select_counter);
-		ni_660x_select_pfi_output(dev, i, pfi_output_select_high_Z);
-	}
-	/* to be safe, set counterswap bits on tio chips after all the counter
-	   outputs have been set to high impedance mode */
-	for (i = 0; i < board(dev)->n_chips; ++i)
-		set_tio_counterswap(dev, i);
-
-	ret = request_irq(mite_irq(private(dev)->mite), ni_660x_interrupt,
-			  IRQF_SHARED, "ni_660x", dev);
-	if (ret < 0) {
-		dev_warn(dev->class_dev, " irq not available\n");
-		return ret;
-	}
-	dev->irq = mite_irq(private(dev)->mite);
-	global_interrupt_config_bits = Global_Int_Enable_Bit;
-	if (board(dev)->n_chips > 1)
-		global_interrupt_config_bits |= Cascade_Int_Enable_Bit;
-	ni_660x_write_register(dev, 0, global_interrupt_config_bits,
-			       GlobalInterruptConfigRegister);
-	dev_info(dev->class_dev, "ni_660x: %s attached\n", dev->board_name);
-	return 0;
-}
-
-static void ni_660x_detach(struct comedi_device *dev)
-{
-	if (dev->irq)
-		free_irq(dev->irq, dev);
-	if (dev->private) {
-		if (private(dev)->counter_dev)
-			ni_gpct_device_destroy(private(dev)->counter_dev);
-		if (private(dev)->mite) {
-			ni_660x_free_mite_rings(dev);
-			mite_unsetup(private(dev)->mite);
-			mite_free(private(dev)->mite);
-		}
-	}
-}
-
 static int
 ni_660x_GPCT_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 		   struct comedi_insn *insn, unsigned int *data)
@@ -1196,17 +994,17 @@ ni_660x_GPCT_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static void init_tio_chip(struct comedi_device *dev, int chipset)
 {
+	struct ni_660x_private *devpriv = dev->private;
 	unsigned i;
 
 	/*  init dma configuration register */
-	private(dev)->dma_configuration_soft_copies[chipset] = 0;
+	devpriv->dma_configuration_soft_copies[chipset] = 0;
 	for (i = 0; i < MAX_DMA_CHANNEL; ++i) {
-		private(dev)->dma_configuration_soft_copies[chipset] |=
+		devpriv->dma_configuration_soft_copies[chipset] |=
 		    dma_select_bits(i, dma_selection_none) & dma_select_mask(i);
 	}
 	ni_660x_write_register(dev, chipset,
-			       private(dev)->
-			       dma_configuration_soft_copies[chipset],
+			       devpriv->dma_configuration_soft_copies[chipset],
 			       DMAConfigRegister);
 	for (i = 0; i < NUM_PFI_CHANNELS; ++i)
 		ni_660x_write_register(dev, chipset, 0, IOConfigReg(i));
@@ -1251,6 +1049,7 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev,
 				      unsigned pfi_channel,
 				      unsigned output_select)
 {
+	const struct ni_660x_board *board = comedi_board(dev);
 	static const unsigned counter_4_7_first_pfi = 8;
 	static const unsigned counter_4_7_last_pfi = 23;
 	unsigned active_chipset = 0;
@@ -1258,7 +1057,7 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev,
 	unsigned active_bits;
 	unsigned idle_bits;
 
-	if (board(dev)->n_chips > 1) {
+	if (board->n_chips > 1) {
 		if (output_select == pfi_output_select_counter &&
 		    pfi_channel >= counter_4_7_first_pfi &&
 		    pfi_channel <= counter_4_7_last_pfi) {
@@ -1294,6 +1093,8 @@ static void ni_660x_select_pfi_output(struct comedi_device *dev,
 static int ni_660x_set_pfi_routing(struct comedi_device *dev, unsigned chan,
 				   unsigned source)
 {
+	struct ni_660x_private *devpriv = dev->private;
+
 	if (source > num_pfi_output_selects)
 		return -EINVAL;
 	if (source == pfi_output_select_high_Z)
@@ -1305,76 +1106,249 @@ static int ni_660x_set_pfi_routing(struct comedi_device *dev, unsigned chan,
 		if (source == pfi_output_select_do)
 			return -EINVAL;
 	}
-	BUG_ON(chan >= NUM_PFI_CHANNELS);
 
-	private(dev)->pfi_output_selects[chan] = source;
-	if (private(dev)->pfi_direction_bits & (((uint64_t) 1) << chan))
+	devpriv->pfi_output_selects[chan] = source;
+	if (devpriv->pfi_direction_bits & (((uint64_t) 1) << chan))
 		ni_660x_select_pfi_output(dev, chan,
-					  private(dev)->
-					  pfi_output_selects[chan]);
+					  devpriv->pfi_output_selects[chan]);
 	return 0;
 }
 
-static unsigned ni_660x_get_pfi_routing(struct comedi_device *dev,
-					unsigned chan)
-{
-	BUG_ON(chan >= NUM_PFI_CHANNELS);
-	return private(dev)->pfi_output_selects[chan];
-}
-
-static void ni660x_config_filter(struct comedi_device *dev,
-				 unsigned pfi_channel,
-				 enum ni_gpct_filter_select filter)
-{
-	unsigned bits = ni_660x_read_register(dev, 0, IOConfigReg(pfi_channel));
-	bits &= ~pfi_input_select_mask(pfi_channel);
-	bits |= pfi_input_select_bits(pfi_channel, filter);
-	ni_660x_write_register(dev, 0, bits, IOConfigReg(pfi_channel));
-}
-
 static int ni_660x_dio_insn_config(struct comedi_device *dev,
 				   struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data)
+				   struct comedi_insn *insn,
+				   unsigned int *data)
 {
-	int chan = CR_CHAN(insn->chanspec);
-
-	/* The input or output configuration of each digital line is
-	 * configured by a special insn_config instruction.  chanspec
-	 * contains the channel to be changed, and data[0] contains the
-	 * value COMEDI_INPUT or COMEDI_OUTPUT. */
+	struct ni_660x_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	uint64_t bit = 1ULL << chan;
+	unsigned int val;
+	int ret;
 
 	switch (data[0]) {
 	case INSN_CONFIG_DIO_OUTPUT:
-		private(dev)->pfi_direction_bits |= ((uint64_t) 1) << chan;
+		devpriv->pfi_direction_bits |= bit;
 		ni_660x_select_pfi_output(dev, chan,
-					  private(dev)->
-					  pfi_output_selects[chan]);
+					  devpriv->pfi_output_selects[chan]);
 		break;
+
 	case INSN_CONFIG_DIO_INPUT:
-		private(dev)->pfi_direction_bits &= ~(((uint64_t) 1) << chan);
+		devpriv->pfi_direction_bits &= ~bit;
 		ni_660x_select_pfi_output(dev, chan, pfi_output_select_high_Z);
 		break;
+
 	case INSN_CONFIG_DIO_QUERY:
-		data[1] =
-		    (private(dev)->pfi_direction_bits &
-		     (((uint64_t) 1) << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
-		return 0;
+		data[1] = (devpriv->pfi_direction_bits & bit) ? COMEDI_OUTPUT
+							      : COMEDI_INPUT;
+		break;
+
 	case INSN_CONFIG_SET_ROUTING:
-		return ni_660x_set_pfi_routing(dev, chan, data[1]);
+		ret = ni_660x_set_pfi_routing(dev, chan, data[1]);
+		if (ret)
+			return ret;
 		break;
+
 	case INSN_CONFIG_GET_ROUTING:
-		data[1] = ni_660x_get_pfi_routing(dev, chan);
+		data[1] = devpriv->pfi_output_selects[chan];
 		break;
+
 	case INSN_CONFIG_FILTER:
-		ni660x_config_filter(dev, chan, data[1]);
+		val = ni_660x_read_register(dev, 0, IOConfigReg(chan));
+		val &= ~pfi_input_select_mask(chan);
+		val |= pfi_input_select_bits(chan, data[1]);
+		ni_660x_write_register(dev, 0, val, IOConfigReg(chan));
 		break;
+
 	default:
 		return -EINVAL;
-		break;
 	}
+
+	return insn->n;
+}
+
+static int ni_660x_auto_attach(struct comedi_device *dev,
+					 unsigned long context_unused)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	const struct ni_660x_board *board;
+	struct ni_660x_private *devpriv;
+	struct comedi_subdevice *s;
+	int ret;
+	unsigned i;
+	unsigned global_interrupt_config_bits;
+
+	ret = ni_660x_allocate_private(dev);
+	if (ret < 0)
+		return ret;
+	devpriv = dev->private;
+
+	dev->board_ptr = ni_660x_find_boardinfo(pcidev);
+	if (!dev->board_ptr)
+		return -ENODEV;
+	board = comedi_board(dev);
+
+	devpriv->mite = mite_alloc(pcidev);
+	if (!devpriv->mite)
+		return -ENOMEM;
+
+	dev->board_name = board->name;
+
+	ret = mite_setup2(devpriv->mite, 1);
+	if (ret < 0) {
+		dev_warn(dev->class_dev, "error setting up mite\n");
+		return ret;
+	}
+
+	ret = ni_660x_alloc_mite_rings(dev);
+	if (ret < 0)
+		return ret;
+
+	ret = comedi_alloc_subdevices(dev, 2 + NI_660X_MAX_NUM_COUNTERS);
+	if (ret)
+		return ret;
+
+	s = &dev->subdevices[0];
+	/* Old GENERAL-PURPOSE COUNTER/TIME (GPCT) subdevice, no longer used */
+	s->type = COMEDI_SUBD_UNUSED;
+
+	s = &dev->subdevices[NI_660X_DIO_SUBDEV];
+	/* DIGITAL I/O SUBDEVICE */
+	s->type = COMEDI_SUBD_DIO;
+	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+	s->n_chan = NUM_PFI_CHANNELS;
+	s->maxdata = 1;
+	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);
+
+	devpriv->counter_dev = ni_gpct_device_construct(dev,
+						     &ni_gpct_write_register,
+						     &ni_gpct_read_register,
+						     ni_gpct_variant_660x,
+						     ni_660x_num_counters
+						     (dev));
+	if (devpriv->counter_dev == NULL)
+		return -ENOMEM;
+	for (i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i) {
+		s = &dev->subdevices[NI_660X_GPCT_SUBDEV(i)];
+		if (i < ni_660x_num_counters(dev)) {
+			s->type = COMEDI_SUBD_COUNTER;
+			s->subdev_flags =
+			    SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL |
+			    SDF_CMD_READ /* | SDF_CMD_WRITE */ ;
+			s->n_chan = 3;
+			s->maxdata = 0xffffffff;
+			s->insn_read = ni_660x_GPCT_rinsn;
+			s->insn_write = ni_660x_GPCT_winsn;
+			s->insn_config = ni_660x_GPCT_insn_config;
+			s->do_cmd = &ni_660x_cmd;
+			s->len_chanlist = 1;
+			s->do_cmdtest = &ni_660x_cmdtest;
+			s->cancel = &ni_660x_cancel;
+			s->poll = &ni_660x_input_poll;
+			s->async_dma_dir = DMA_BIDIRECTIONAL;
+			s->buf_change = &ni_660x_buf_change;
+			s->private = &devpriv->counter_dev->counters[i];
+
+			devpriv->counter_dev->counters[i].chip_index =
+			    i / counters_per_chip;
+			devpriv->counter_dev->counters[i].counter_index =
+			    i % counters_per_chip;
+		} else {
+			s->type = COMEDI_SUBD_UNUSED;
+		}
+	}
+	for (i = 0; i < board->n_chips; ++i)
+		init_tio_chip(dev, i);
+
+	for (i = 0; i < ni_660x_num_counters(dev); ++i)
+		ni_tio_init_counter(&devpriv->counter_dev->counters[i]);
+
+	for (i = 0; i < NUM_PFI_CHANNELS; ++i) {
+		if (i < min_counter_pfi_chan)
+			ni_660x_set_pfi_routing(dev, i, pfi_output_select_do);
+		else
+			ni_660x_set_pfi_routing(dev, i,
+						pfi_output_select_counter);
+		ni_660x_select_pfi_output(dev, i, pfi_output_select_high_Z);
+	}
+	/* to be safe, set counterswap bits on tio chips after all the counter
+	   outputs have been set to high impedance mode */
+	for (i = 0; i < board->n_chips; ++i)
+		set_tio_counterswap(dev, i);
+
+	ret = request_irq(mite_irq(devpriv->mite), ni_660x_interrupt,
+			  IRQF_SHARED, "ni_660x", dev);
+	if (ret < 0) {
+		dev_warn(dev->class_dev, " irq not available\n");
+		return ret;
+	}
+	dev->irq = mite_irq(devpriv->mite);
+	global_interrupt_config_bits = Global_Int_Enable_Bit;
+	if (board->n_chips > 1)
+		global_interrupt_config_bits |= Cascade_Int_Enable_Bit;
+	ni_660x_write_register(dev, 0, global_interrupt_config_bits,
+			       GlobalInterruptConfigRegister);
+	dev_info(dev->class_dev, "ni_660x: %s attached\n", dev->board_name);
 	return 0;
 }
 
+static void ni_660x_detach(struct comedi_device *dev)
+{
+	struct ni_660x_private *devpriv = dev->private;
+
+	if (dev->irq)
+		free_irq(dev->irq, dev);
+	if (devpriv) {
+		if (devpriv->counter_dev)
+			ni_gpct_device_destroy(devpriv->counter_dev);
+		if (devpriv->mite) {
+			ni_660x_free_mite_rings(dev);
+			mite_unsetup(devpriv->mite);
+			mite_free(devpriv->mite);
+		}
+	}
+}
+
+static struct comedi_driver ni_660x_driver = {
+	.driver_name	= "ni_660x",
+	.module		= THIS_MODULE,
+	.auto_attach	= ni_660x_auto_attach,
+	.detach		= ni_660x_detach,
+};
+
+static int ni_660x_pci_probe(struct pci_dev *dev,
+				       const struct pci_device_id *ent)
+{
+	return comedi_pci_auto_config(dev, &ni_660x_driver);
+}
+
+static void ni_660x_pci_remove(struct pci_dev *dev)
+{
+	comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(ni_660x_pci_table) = {
+	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2c60)},
+	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1310)},
+	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x1360)},
+	{PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2cc0)},
+	{0}
+};
+MODULE_DEVICE_TABLE(pci, ni_660x_pci_table);
+
+static struct pci_driver ni_660x_pci_driver = {
+	.name		= "ni_660x",
+	.id_table	= ni_660x_pci_table,
+	.probe		= ni_660x_pci_probe,
+	.remove		= ni_660x_pci_remove,
+};
+module_comedi_pci_driver(ni_660x_driver, ni_660x_pci_driver);
+
 MODULE_AUTHOR("Comedi http://www.comedi.org");
 MODULE_DESCRIPTION("Comedi low-level driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
index eac6dc0..272caeb 100644
--- a/drivers/staging/comedi/drivers/ni_670x.c
+++ b/drivers/staging/comedi/drivers/ni_670x.c
@@ -201,19 +201,21 @@ ni_670x_find_boardinfo(struct pci_dev *pcidev)
 	return NULL;
 }
 
-static int __devinit ni_670x_attach_pci(struct comedi_device *dev,
-					struct pci_dev *pcidev)
+static int ni_670x_auto_attach(struct comedi_device *dev,
+					 unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	const struct ni_670x_board *thisboard;
 	struct ni_670x_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 	int i;
 
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret < 0)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
 	dev->board_ptr = ni_670x_find_boardinfo(pcidev);
 	if (!dev->board_ptr)
 		return -ENODEV;
@@ -297,17 +299,17 @@ static void ni_670x_detach(struct comedi_device *dev)
 static struct comedi_driver ni_670x_driver = {
 	.driver_name	= "ni_670x",
 	.module		= THIS_MODULE,
-	.attach_pci	= ni_670x_attach_pci,
+	.auto_attach	= ni_670x_auto_attach,
 	.detach		= ni_670x_detach,
 };
 
-static int __devinit ni_670x_pci_probe(struct pci_dev *dev,
+static int ni_670x_pci_probe(struct pci_dev *dev,
 				       const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &ni_670x_driver);
 }
 
-static void __devexit ni_670x_pci_remove(struct pci_dev *dev)
+static void ni_670x_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -320,10 +322,10 @@ static DEFINE_PCI_DEVICE_TABLE(ni_670x_pci_table) = {
 MODULE_DEVICE_TABLE(pci, ni_670x_pci_table);
 
 static struct pci_driver ni_670x_pci_driver = {
-	.name		="ni_670x",
+	.name		= "ni_670x",
 	.id_table	= ni_670x_pci_table,
 	.probe		= ni_670x_pci_probe,
-	.remove		= __devexit_p(ni_670x_pci_remove),
+	.remove		= ni_670x_pci_remove,
 };
 module_comedi_pci_driver(ni_670x_driver, ni_670x_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
index 8395080..06de25b 100644
--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
+++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
@@ -169,8 +169,6 @@ struct a2150_private {
 	int config_bits;	/*  config register bits */
 };
 
-#define devpriv ((struct a2150_private *)dev->private)
-
 static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
 
 static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
@@ -182,6 +180,8 @@ static int a2150_set_chanlist(struct comedi_device *dev,
 
 static void ni_dump_regs(struct comedi_device *dev)
 {
+	struct a2150_private *devpriv = dev->private;
+
 	printk("config bits 0x%x\n", devpriv->config_bits);
 	printk("irq dma bits 0x%x\n", devpriv->irq_dma_bits);
 	printk("status bits 0x%x\n", inw(dev->iobase + STATUS_REG));
@@ -196,6 +196,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d)
 	int status;
 	unsigned long flags;
 	struct comedi_device *dev = d;
+	struct a2150_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
 	struct comedi_async *async;
 	struct comedi_cmd *cmd;
@@ -300,6 +301,8 @@ static irqreturn_t a2150_interrupt(int irq, void *d)
 
 static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct a2150_private *devpriv = dev->private;
+
 	/*  disable dma on card */
 	devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;
 	outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
@@ -342,37 +345,21 @@ static int a2150_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < thisboard->ai_speed) {
-			cmd->convert_arg = thisboard->ai_speed;
-			err++;
-		}
-	}
-	if (!cmd->chanlist_len) {
-		cmd->chanlist_len = 1;
-		err++;
-	}
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (!cmd->stop_arg) {
-			cmd->stop_arg = 1;
-			err++;
-		}
-	} else {		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+
+	if (cmd->convert_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+						 thisboard->ai_speed);
+
+	err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+	if (cmd->stop_src == TRIG_COUNT)
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+	else	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -425,6 +412,7 @@ static int a2150_ai_cmdtest(struct comedi_device *dev,
 
 static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct a2150_private *devpriv = dev->private;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
 	unsigned long lock_flags;
@@ -536,6 +524,7 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			  struct comedi_insn *insn, unsigned int *data)
 {
+	struct a2150_private *devpriv = dev->private;
 	unsigned int i, n;
 	static const int timeout = 100000;
 	static const int filter_delay = 36;
@@ -615,6 +604,7 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
 			    int flags)
 {
+	struct a2150_private *devpriv = dev->private;
 	int lub, glb, temp;
 	int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index;
 	int i, j;
@@ -689,6 +679,8 @@ static int a2150_set_chanlist(struct comedi_device *dev,
 			      unsigned int start_channel,
 			      unsigned int num_channels)
 {
+	struct a2150_private *devpriv = dev->private;
+
 	if (start_channel + num_channels > 4)
 		return -1;
 
@@ -727,6 +719,7 @@ static int a2150_probe(struct comedi_device *dev)
 
 static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+	struct a2150_private *devpriv;
 	struct comedi_subdevice *s;
 	unsigned long iobase = it->options[0];
 	unsigned int irq = it->options[1];
@@ -749,9 +742,10 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	}
 	printk("\n");
 
-	/* allocate and initialize dev->private */
-	if (alloc_private(dev, sizeof(struct a2150_private)) < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
 
 	if (iobase == 0) {
 		printk(" io base address required\n");
@@ -855,6 +849,8 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 static void a2150_detach(struct comedi_device *dev)
 {
+	struct a2150_private *devpriv = dev->private;
+
 	if (dev->iobase) {
 		outw(APD_BIT | DPD_BIT, dev->iobase + CONFIG_REG);
 		release_region(dev->iobase, A2150_SIZE);
diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
index 93938ce..907f65c 100644
--- a/drivers/staging/comedi/drivers/ni_at_ao.c
+++ b/drivers/staging/comedi/drivers/ni_at_ao.c
@@ -167,10 +167,10 @@ struct atao_private {
 	unsigned int ao_readback[10];
 };
 
-#define devpriv ((struct atao_private *)dev->private)
-
 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;
@@ -202,6 +202,7 @@ static void atao_reset(struct comedi_device *dev)
 static int atao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_insn *insn, unsigned int *data)
 {
+	struct atao_private *devpriv = dev->private;
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 	short bits;
@@ -226,6 +227,7 @@ static int atao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int atao_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_insn *insn, unsigned int *data)
 {
+	struct atao_private *devpriv = dev->private;
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 
@@ -254,6 +256,7 @@ static int atao_dio_insn_config(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
 {
+	struct atao_private *devpriv = dev->private;
 	int chan = CR_CHAN(insn->chanspec);
 	unsigned int mask, bit;
 
@@ -309,6 +312,7 @@ static int atao_calib_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 bitstring, bit;
 	unsigned int chan = CR_CHAN(insn->chanspec);
 
@@ -331,6 +335,7 @@ static int atao_calib_insn_write(struct comedi_device *dev,
 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;
 	unsigned long iobase;
 	int ao_unipolar;
@@ -351,8 +356,10 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 	dev->board_name = board->name;
 
-	if (alloc_private(dev, sizeof(struct atao_private)) < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_alloc_subdevices(dev, 4);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
index cac2557..2cc2996 100644
--- a/drivers/staging/comedi/drivers/ni_atmio.c
+++ b/drivers/staging/comedi/drivers/ni_atmio.c
@@ -284,8 +284,6 @@ struct ni_private {
 
 };
 
-#define devpriv ((struct ni_private *)dev->private)
-
 /* How we access registers */
 
 #define ni_writel(a, b)		(outl((a), (b)+dev->iobase))
@@ -303,6 +301,7 @@ struct ni_private {
 
 static void ni_atmio_win_out(struct comedi_device *dev, uint16_t data, int addr)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->window_lock, flags);
@@ -317,6 +316,7 @@ static void ni_atmio_win_out(struct comedi_device *dev, uint16_t data, int addr)
 
 static uint16_t ni_atmio_win_in(struct comedi_device *dev, int addr)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 	uint16_t ret;
 
@@ -406,16 +406,17 @@ static int ni_getboardtype(struct comedi_device *dev)
 static int ni_atmio_attach(struct comedi_device *dev,
 			   struct comedi_devconfig *it)
 {
+	struct ni_private *devpriv;
 	struct pnp_dev *isapnp_dev;
 	int ret;
 	unsigned long iobase;
 	int board;
 	unsigned int irq;
 
-	/* allocate private area */
 	ret = ni_alloc_private(dev);
-	if (ret < 0)
+	if (ret)
 		return ret;
+	devpriv = dev->private;
 
 	devpriv->stc_writew = &ni_atmio_win_out;
 	devpriv->stc_readw = &ni_atmio_win_in;
@@ -499,6 +500,8 @@ static int ni_atmio_attach(struct comedi_device *dev,
 
 static void ni_atmio_detach(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
+
 	mio_common_detach(dev);
 	if (dev->iobase)
 		release_region(dev->iobase, NI_SIZE);
diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
index e91a620..4a17494 100644
--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
+++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
@@ -102,7 +102,6 @@ Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d)
 #define CLOCK_100_HZ	0x8F25
 /* Other miscellaneous defines */
 #define ATMIO16D_SIZE	32	/* bus address range */
-#define devpriv ((struct atmio16d_private *)dev->private)
 #define ATMIO16D_TIMEOUT 10
 
 struct atmio16_board_t {
@@ -202,6 +201,7 @@ static void reset_counters(struct comedi_device *dev)
 
 static void reset_atmio16d(struct comedi_device *dev)
 {
+	struct atmio16d_private *devpriv = dev->private;
 	int i;
 
 	/* now we need to initialize the board */
@@ -271,51 +271,32 @@ static int atmio16d_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
+
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
 	if (cmd->scan_begin_src == TRIG_FOLLOW) {
 		/* internal trigger */
-		if (cmd->scan_begin_arg != 0) {
-			cmd->scan_begin_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 	} else {
 #if 0
 		/* external trigger */
 		/* should be level/edge, hi/lo specification here */
-		if (cmd->scan_begin_arg != 0) {
-			cmd->scan_begin_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 #endif
 	}
 
-	if (cmd->convert_arg < 10000) {
-		cmd->convert_arg = 10000;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 10000);
 #if 0
-	if (cmd->convert_arg > SLOWEST_TIMER) {
-		cmd->convert_arg = SLOWEST_TIMER;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_max(&cmd->convert_arg, SLOWEST_TIMER);
 #endif
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
 	if (cmd->stop_src == TRIG_COUNT) {
 		/* any count is allowed */
-	} else {
-		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+	} else {	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 	}
 
 	if (err)
@@ -327,6 +308,7 @@ static int atmio16d_ai_cmdtest(struct comedi_device *dev,
 static int atmio16d_ai_cmd(struct comedi_device *dev,
 			   struct comedi_subdevice *s)
 {
+	struct atmio16d_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
 	unsigned int timer, base_clock;
 	unsigned int sample_count, tmp, chan, gain;
@@ -486,6 +468,7 @@ static int atmio16d_ai_insn_read(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
 				 struct comedi_insn *insn, unsigned int *data)
 {
+	struct atmio16d_private *devpriv = dev->private;
 	int i, t;
 	int chan;
 	int gain;
@@ -539,6 +522,7 @@ static int atmio16d_ao_insn_read(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
 				 struct comedi_insn *insn, unsigned int *data)
 {
+	struct atmio16d_private *devpriv = dev->private;
 	int i;
 
 	for (i = 0; i < insn->n; i++)
@@ -550,6 +534,7 @@ static int atmio16d_ao_insn_write(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
 				  struct comedi_insn *insn, unsigned int *data)
 {
+	struct atmio16d_private *devpriv = dev->private;
 	int i;
 	int chan;
 	int d;
@@ -596,6 +581,7 @@ static int atmio16d_dio_insn_config(struct comedi_device *dev,
 				    struct comedi_insn *insn,
 				    unsigned int *data)
 {
+	struct atmio16d_private *devpriv = dev->private;
 	int i;
 	int mask;
 
@@ -651,6 +637,7 @@ static int atmio16d_attach(struct comedi_device *dev,
 			   struct comedi_devconfig *it)
 {
 	const struct atmio16_board_t *board = comedi_board(dev);
+	struct atmio16d_private *devpriv;
 	unsigned int irq;
 	unsigned long iobase;
 	int ret;
@@ -672,9 +659,10 @@ static int atmio16d_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
-	ret = alloc_private(dev, sizeof(struct atmio16d_private));
-	if (ret < 0)
-		return ret;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	/* reset the atmio16d hardware */
 	reset_atmio16d(dev);
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index 0ca222b..7b33335 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -96,8 +96,6 @@ struct dio24_private {
 	int data;		/* number of data points left to be taken */
 };
 
-#define devpriv ((struct dio24_private *)dev->private)
-
 static struct comedi_driver driver_dio24 = {
 	.driver_name = "ni_daq_dio24",
 	.module = THIS_MODULE,
@@ -110,6 +108,7 @@ static struct comedi_driver driver_dio24 = {
 
 static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+	struct dio24_private *devpriv;
 	struct comedi_subdevice *s;
 	unsigned long iobase = 0;
 #ifdef incomplete
@@ -118,9 +117,10 @@ static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	struct pcmcia_device *link;
 	int ret;
 
-	/* allocate and initialize dev->private */
-	if (alloc_private(dev, sizeof(struct dio24_private)) < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
 
 	/*  get base address, irq etc. based on bustype */
 	switch (thisboard->bustype) {
@@ -202,7 +202,7 @@ static int dio24_cs_attach(struct pcmcia_device *link)
 {
 	struct local_info_t *local;
 
-	printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - CS-attach!\n");
+	dev_info(&link->dev, "ni_daq_dio24: HOLA SOY YO - CS-attach!\n");
 
 	dev_dbg(&link->dev, "dio24_cs_attach()\n");
 
@@ -242,7 +242,7 @@ static void dio24_config(struct pcmcia_device *link)
 {
 	int ret;
 
-	printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO! - config\n");
+	dev_info(&link->dev, "ni_daq_dio24: HOLA SOY YO! - config\n");
 
 	dev_dbg(&link->dev, "dio24_config\n");
 
@@ -265,7 +265,7 @@ static void dio24_config(struct pcmcia_device *link)
 	return;
 
 failed:
-	printk(KERN_INFO "Fallo");
+	dev_info(&link->dev, "Fallo");
 	dio24_release(link);
 
 }				/* dio24_config */
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index b5a19a0..d29c4d7 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -487,8 +487,6 @@ static const int dma_buffer_size = 0xff00;
 /* 2 bytes per sample */
 static const int sample_size = 2;
 
-#define devpriv ((struct labpc_private *)dev->private)
-
 static inline int labpc_counter_load(struct comedi_device *dev,
 				     unsigned long base_address,
 				     unsigned int counter_number,
@@ -504,6 +502,7 @@ static inline int labpc_counter_load(struct comedi_device *dev,
 int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
 			unsigned int irq, unsigned int dma_chan)
 {
+	struct labpc_private *devpriv = dev->private;
 	struct comedi_subdevice *s;
 	int i;
 	unsigned long isr_flags;
@@ -697,18 +696,23 @@ labpc_pci_find_boardinfo(struct pci_dev *pcidev)
 	return NULL;
 }
 
-static int __devinit labpc_attach_pci(struct comedi_device *dev,
-				      struct pci_dev *pcidev)
+static int labpc_auto_attach(struct comedi_device *dev,
+				       unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct labpc_private *devpriv;
 	unsigned long iobase;
 	unsigned int irq;
 	int ret;
 
 	if (!IS_ENABLED(CONFIG_COMEDI_PCI_DRIVERS))
 		return -ENODEV;
-	ret = alloc_private(dev, sizeof(struct labpc_private));
-	if (ret < 0)
-		return ret;
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
 	dev->board_ptr = labpc_pci_find_boardinfo(pcidev);
 	if (!dev->board_ptr)
 		return -ENODEV;
@@ -725,13 +729,15 @@ static int __devinit labpc_attach_pci(struct comedi_device *dev,
 
 static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+	struct labpc_private *devpriv;
 	unsigned long iobase = 0;
 	unsigned int irq = 0;
 	unsigned int dma_chan = 0;
 
-	/* allocate and initialize dev->private */
-	if (alloc_private(dev, sizeof(struct labpc_private)) < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
 
 	/* get base address, irq etc. based on bustype */
 	switch (thisboard->bustype) {
@@ -770,6 +776,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 void labpc_common_detach(struct comedi_device *dev)
 {
+	struct labpc_private *devpriv = dev->private;
 	struct comedi_subdevice *s;
 
 	if (!thisboard)
@@ -799,6 +806,8 @@ EXPORT_SYMBOL_GPL(labpc_common_detach);
 
 static void labpc_clear_adc_fifo(const struct comedi_device *dev)
 {
+	struct labpc_private *devpriv = dev->private;
+
 	devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG);
 	devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
 	devpriv->read_byte(dev->iobase + ADC_FIFO_REG);
@@ -806,6 +815,7 @@ static void labpc_clear_adc_fifo(const struct comedi_device *dev)
 
 static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct labpc_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev->spinlock, flags);
@@ -1016,56 +1026,34 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg == TRIG_NOW && cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	if (cmd->start_arg == TRIG_NOW)
+		err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
 	if (!cmd->chanlist_len)
-		err++;
+		err |= -EINVAL;
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	if (cmd->convert_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+						 thisboard->ai_speed);
 
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < thisboard->ai_speed) {
-			cmd->convert_arg = thisboard->ai_speed;
-			err++;
-		}
-	}
 	/* make sure scan timing is not too fast */
 	if (cmd->scan_begin_src == TRIG_TIMER) {
-		if (cmd->convert_src == TRIG_TIMER &&
-		    cmd->scan_begin_arg <
-		    cmd->convert_arg * cmd->chanlist_len) {
-			cmd->scan_begin_arg =
-			    cmd->convert_arg * cmd->chanlist_len;
-			err++;
-		}
-		if (cmd->scan_begin_arg <
-		    thisboard->ai_speed * cmd->chanlist_len) {
-			cmd->scan_begin_arg =
-			    thisboard->ai_speed * cmd->chanlist_len;
-			err++;
-		}
+		if (cmd->convert_src == TRIG_TIMER)
+			err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+					cmd->convert_arg * cmd->chanlist_len);
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+				thisboard->ai_speed * cmd->chanlist_len);
 	}
-	/* stop source */
+
 	switch (cmd->stop_src) {
 	case TRIG_COUNT:
-		if (!cmd->stop_arg) {
-			cmd->stop_arg = 1;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
 		break;
 	case TRIG_NONE:
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 		break;
 		/*
 		 * TRIG_EXT doesn't care since it doesn't
@@ -1098,6 +1086,7 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
 
 static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct labpc_private *devpriv = dev->private;
 	int channel, range, aref;
 #ifdef CONFIG_ISA_DMA_API
 	unsigned long irq_flags;
@@ -1365,6 +1354,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 static irqreturn_t labpc_interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct labpc_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
 	struct comedi_async *async;
 	struct comedi_cmd *cmd;
@@ -1453,6 +1443,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d)
 /* read all available samples from ai fifo */
 static int labpc_drain_fifo(struct comedi_device *dev)
 {
+	struct labpc_private *devpriv = dev->private;
 	unsigned int lsb, msb;
 	short data;
 	struct comedi_async *async = dev->read_subdev->async;
@@ -1488,6 +1479,7 @@ static int labpc_drain_fifo(struct comedi_device *dev)
 #ifdef CONFIG_ISA_DMA_API
 static void labpc_drain_dma(struct comedi_device *dev)
 {
+	struct labpc_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
 	struct comedi_async *async = s->async;
 	int status;
@@ -1541,6 +1533,8 @@ static void labpc_drain_dma(struct comedi_device *dev)
 
 static void handle_isa_dma(struct comedi_device *dev)
 {
+	struct labpc_private *devpriv = dev->private;
+
 	labpc_drain_dma(dev);
 
 	enable_dma(devpriv->dma_chan);
@@ -1555,6 +1549,8 @@ static void handle_isa_dma(struct comedi_device *dev)
 static void labpc_drain_dregs(struct comedi_device *dev)
 {
 #ifdef CONFIG_ISA_DMA_API
+	struct labpc_private *devpriv = dev->private;
+
 	if (devpriv->current_transfer == isa_dma_transfer)
 		labpc_drain_dma(dev);
 #endif
@@ -1565,6 +1561,7 @@ static void labpc_drain_dregs(struct comedi_device *dev)
 static int labpc_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			  struct comedi_insn *insn, unsigned int *data)
 {
+	struct labpc_private *devpriv = dev->private;
 	int i, n;
 	int chan, range;
 	int lsb, msb;
@@ -1654,6 +1651,7 @@ static int labpc_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			  struct comedi_insn *insn, unsigned int *data)
 {
+	struct labpc_private *devpriv = dev->private;
 	int channel, range;
 	unsigned long flags;
 	int lsb, msb;
@@ -1695,6 +1693,8 @@ static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int labpc_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			  struct comedi_insn *insn, unsigned int *data)
 {
+	struct labpc_private *devpriv = dev->private;
+
 	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
 
 	return 1;
@@ -1704,6 +1704,8 @@ static int labpc_calib_read_insn(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
 				 struct comedi_insn *insn, unsigned int *data)
 {
+	struct labpc_private *devpriv = dev->private;
+
 	data[0] = devpriv->caldac[CR_CHAN(insn->chanspec)];
 
 	return 1;
@@ -1723,6 +1725,8 @@ static int labpc_eeprom_read_insn(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
 				  struct comedi_insn *insn, unsigned int *data)
 {
+	struct labpc_private *devpriv = dev->private;
+
 	data[0] = devpriv->eeprom_data[CR_CHAN(insn->chanspec)];
 
 	return 1;
@@ -1779,6 +1783,7 @@ static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd)
 static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd,
 			     enum scan_mode mode)
 {
+	struct labpc_private *devpriv = dev->private;
 	/* max value for 16 bit counter in mode 2 */
 	const int max_counter_value = 0x10000;
 	/* min value for 16 bit counter in mode 2 */
@@ -1885,6 +1890,7 @@ static int labpc_dio_mem_callback(int dir, int port, int data,
 static void labpc_serial_out(struct comedi_device *dev, unsigned int value,
 			     unsigned int value_width)
 {
+	struct labpc_private *devpriv = dev->private;
 	int i;
 
 	for (i = 1; i <= value_width; i++) {
@@ -1909,6 +1915,7 @@ static void labpc_serial_out(struct comedi_device *dev, unsigned int value,
 /* lowlevel read from eeprom */
 static unsigned int labpc_serial_in(struct comedi_device *dev)
 {
+	struct labpc_private *devpriv = dev->private;
 	unsigned int value = 0;
 	int i;
 	const int value_width = 8;	/*  number of bits wide values are */
@@ -1938,6 +1945,7 @@ static unsigned int labpc_serial_in(struct comedi_device *dev)
 static unsigned int labpc_eeprom_read(struct comedi_device *dev,
 				      unsigned int address)
 {
+	struct labpc_private *devpriv = dev->private;
 	unsigned int value;
 	/*  bits to tell eeprom to expect a read */
 	const int read_instruction = 0x3;
@@ -1970,6 +1978,7 @@ static unsigned int labpc_eeprom_read(struct comedi_device *dev,
 static int labpc_eeprom_write(struct comedi_device *dev,
 				unsigned int address, unsigned int value)
 {
+	struct labpc_private *devpriv = dev->private;
 	const int write_enable_instruction = 0x6;
 	const int write_instruction = 0x2;
 	const int write_length = 8;	/*  8 bit write lengths to eeprom */
@@ -2027,6 +2036,7 @@ static int labpc_eeprom_write(struct comedi_device *dev,
 
 static unsigned int labpc_eeprom_read_status(struct comedi_device *dev)
 {
+	struct labpc_private *devpriv = dev->private;
 	unsigned int value;
 	const int read_status_instruction = 0x5;
 	const int write_length = 8;	/*  8 bit write lengths to eeprom */
@@ -2056,6 +2066,8 @@ static unsigned int labpc_eeprom_read_status(struct comedi_device *dev)
 static void write_caldac(struct comedi_device *dev, unsigned int channel,
 			 unsigned int value)
 {
+	struct labpc_private *devpriv = dev->private;
+
 	if (value == devpriv->caldac[channel])
 		return;
 	devpriv->caldac[channel] = value;
@@ -2084,7 +2096,7 @@ static struct comedi_driver labpc_driver = {
 	.driver_name = DRV_NAME,
 	.module = THIS_MODULE,
 	.attach = labpc_attach,
-	.attach_pci = labpc_attach_pci,
+	.auto_attach = labpc_auto_attach,
 	.detach = labpc_common_detach,
 	.num_names = ARRAY_SIZE(labpc_boards),
 	.board_name = &labpc_boards[0].name,
@@ -2098,13 +2110,13 @@ static DEFINE_PCI_DEVICE_TABLE(labpc_pci_table) = {
 };
 MODULE_DEVICE_TABLE(pci, labpc_pci_table);
 
-static int __devinit labpc_pci_probe(struct pci_dev *dev,
+static int labpc_pci_probe(struct pci_dev *dev,
 				     const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &labpc_driver);
 }
 
-static void __devexit labpc_pci_remove(struct pci_dev *dev)
+static void labpc_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -2113,7 +2125,7 @@ static struct pci_driver labpc_pci_driver = {
 	.name = DRV_NAME,
 	.id_table = labpc_pci_table,
 	.probe = labpc_pci_probe,
-	.remove = __devexit_p(labpc_pci_remove)
+	.remove = labpc_pci_remove
 };
 module_comedi_pci_driver(labpc_driver, labpc_pci_driver);
 #else
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index eb0417e..bfe19fa 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -127,13 +127,15 @@ static struct comedi_driver driver_labpc_cs = {
 
 static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+	struct labpc_private *devpriv;
 	unsigned long iobase = 0;
 	unsigned int irq = 0;
 	struct pcmcia_device *link;
 
-	/* allocate and initialize dev->private */
-	if (alloc_private(dev, sizeof(struct labpc_private)) < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
 
 	/*  get base address, irq etc. based on bustype */
 	switch (thisboard->bustype) {
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index 3e5fdae..56dc599 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -410,6 +410,7 @@ static void get_last_sample_6143(struct comedi_device *dev);
 static inline void ni_set_bitfield(struct comedi_device *dev, int reg,
 				   unsigned bit_mask, unsigned bit_values)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags);
@@ -506,6 +507,7 @@ static inline void ni_set_gpct_dma_channel(struct comedi_device *dev,
 static inline void ni_set_cdo_dma_channel(struct comedi_device *dev,
 					  int mite_channel)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags);
@@ -525,6 +527,7 @@ static inline void ni_set_cdo_dma_channel(struct comedi_device *dev,
 
 static int ni_request_ai_mite_channel(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -545,6 +548,7 @@ static int ni_request_ai_mite_channel(struct comedi_device *dev)
 
 static int ni_request_ao_mite_channel(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -567,6 +571,7 @@ static int ni_request_gpct_mite_channel(struct comedi_device *dev,
 					unsigned gpct_index,
 					enum comedi_io_direction direction)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 	struct mite_channel *mite_chan;
 
@@ -595,6 +600,7 @@ static int ni_request_gpct_mite_channel(struct comedi_device *dev,
 static int ni_request_cdo_mite_channel(struct comedi_device *dev)
 {
 #ifdef PCIDMA
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -617,6 +623,7 @@ static int ni_request_cdo_mite_channel(struct comedi_device *dev)
 static void ni_release_ai_mite_channel(struct comedi_device *dev)
 {
 #ifdef PCIDMA
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -632,6 +639,7 @@ static void ni_release_ai_mite_channel(struct comedi_device *dev)
 static void ni_release_ao_mite_channel(struct comedi_device *dev)
 {
 #ifdef PCIDMA
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -648,6 +656,7 @@ static void ni_release_ao_mite_channel(struct comedi_device *dev)
 static void ni_release_gpct_mite_channel(struct comedi_device *dev,
 					 unsigned gpct_index)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 
 	BUG_ON(gpct_index >= NUM_GPCT);
@@ -669,6 +678,7 @@ static void ni_release_gpct_mite_channel(struct comedi_device *dev,
 static void ni_release_cdo_mite_channel(struct comedi_device *dev)
 {
 #ifdef PCIDMA
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -686,6 +696,8 @@ static void ni_release_cdo_mite_channel(struct comedi_device *dev)
 static void ni_e_series_enable_second_irq(struct comedi_device *dev,
 					  unsigned gpct_index, short enable)
 {
+	struct ni_private *devpriv = dev->private;
+
 	if (boardtype.reg_type & ni_reg_m_series_mask)
 		return;
 	switch (gpct_index) {
@@ -716,6 +728,8 @@ static void ni_e_series_enable_second_irq(struct comedi_device *dev,
 
 static void ni_clear_ai_fifo(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
+
 	if (boardtype.reg_type == ni_reg_6143) {
 		/*  Flush the 6143 data FIFO */
 		ni_writel(0x10, AIFIFO_Control_6143);	/*  Flush fifo */
@@ -742,13 +756,17 @@ static void ni_clear_ai_fifo(struct comedi_device *dev)
 
 static void win_out2(struct comedi_device *dev, uint32_t data, int reg)
 {
+	struct ni_private *devpriv = dev->private;
+
 	devpriv->stc_writew(dev, data >> 16, reg);
 	devpriv->stc_writew(dev, data & 0xffff, reg + 1);
 }
 
 static uint32_t win_in2(struct comedi_device *dev, int reg)
 {
+	struct ni_private *devpriv = dev->private;
 	uint32_t bits;
+
 	bits = devpriv->stc_readw(dev, reg) << 16;
 	bits |= devpriv->stc_readw(dev, reg + 1);
 	return bits;
@@ -758,6 +776,7 @@ static uint32_t win_in2(struct comedi_device *dev, int reg)
 static inline void ni_ao_win_outw(struct comedi_device *dev, uint16_t data,
 				  int addr)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->window_lock, flags);
@@ -769,6 +788,7 @@ static inline void ni_ao_win_outw(struct comedi_device *dev, uint16_t data,
 static inline void ni_ao_win_outl(struct comedi_device *dev, uint32_t data,
 				  int addr)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->window_lock, flags);
@@ -779,6 +799,7 @@ static inline void ni_ao_win_outl(struct comedi_device *dev, uint32_t data,
 
 static inline unsigned short ni_ao_win_inw(struct comedi_device *dev, int addr)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 	unsigned short data;
 
@@ -814,6 +835,7 @@ static inline void ni_set_bits(struct comedi_device *dev, int reg,
 static irqreturn_t ni_E_interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct ni_private *devpriv = dev->private;
 	unsigned short a_status;
 	unsigned short b_status;
 	unsigned int ai_mite_status = 0;
@@ -872,6 +894,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d)
 #ifdef PCIDMA
 static void ni_sync_ai_dma(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
 	unsigned long flags;
 
@@ -884,6 +907,7 @@ static void ni_sync_ai_dma(struct comedi_device *dev)
 static void mite_handle_b_linkc(struct mite_struct *mite,
 				struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV];
 	unsigned long flags;
 
@@ -896,6 +920,7 @@ static void mite_handle_b_linkc(struct mite_struct *mite,
 
 static int ni_ao_wait_for_dma_load(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
 	static const int timeout = 10000;
 	int i;
 	for (i = 0; i < timeout; i++) {
@@ -918,6 +943,8 @@ static int ni_ao_wait_for_dma_load(struct comedi_device *dev)
 #endif /* PCIDMA */
 static void ni_handle_eos(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct ni_private *devpriv = dev->private;
+
 	if (devpriv->aimode == AIMODE_SCAN) {
 #ifdef PCIDMA
 		static const int timeout = 10;
@@ -984,6 +1011,7 @@ static void handle_gpct_interrupt(struct comedi_device *dev,
 				  unsigned short counter_index)
 {
 #ifdef PCIDMA
+	struct ni_private *devpriv = dev->private;
 	struct comedi_subdevice *s;
 
 	s = &dev->subdevices[NI_GPCT_SUBDEV(counter_index)];
@@ -997,6 +1025,7 @@ static void handle_gpct_interrupt(struct comedi_device *dev,
 
 static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned short ack = 0;
 
 	if (a_status & AI_SC_TC_St) {
@@ -1019,6 +1048,7 @@ static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status)
 static void handle_a_interrupt(struct comedi_device *dev, unsigned short status,
 			       unsigned ai_mite_status)
 {
+	struct ni_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
 
 	/* 67xx boards don't have ai subdevice, but their gpct0 might generate an a interrupt */
@@ -1122,7 +1152,9 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status,
 
 static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned short ack = 0;
+
 	if (b_status & AO_BC_TC_St) {
 		ack |= AO_BC_TC_Interrupt_Ack;
 	}
@@ -1151,8 +1183,10 @@ static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status)
 static void handle_b_interrupt(struct comedi_device *dev,
 			       unsigned short b_status, unsigned ao_mite_status)
 {
+	struct ni_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV];
 	/* unsigned short ack=0; */
+
 #ifdef DEBUG_INTERRUPT
 	printk("ni_mio_common: interrupt: b_status=%04x m1_status=%08x\n",
 	       b_status, ao_mite_status);
@@ -1340,6 +1374,7 @@ static int ni_ao_fifo_half_empty(struct comedi_device *dev,
 static int ni_ao_prep_fifo(struct comedi_device *dev,
 			   struct comedi_subdevice *s)
 {
+	struct ni_private *devpriv = dev->private;
 	int n;
 
 	/* reset fifo */
@@ -1364,6 +1399,7 @@ static int ni_ao_prep_fifo(struct comedi_device *dev,
 static void ni_ai_fifo_read(struct comedi_device *dev,
 			    struct comedi_subdevice *s, int n)
 {
+	struct ni_private *devpriv = dev->private;
 	struct comedi_async *async = s->async;
 	int i;
 
@@ -1434,6 +1470,7 @@ static void ni_handle_fifo_half_full(struct comedi_device *dev)
 #ifdef PCIDMA
 static int ni_ai_drain_dma(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
 	int i;
 	static const int timeout = 10000;
 	unsigned long flags;
@@ -1471,6 +1508,7 @@ static int ni_ai_drain_dma(struct comedi_device *dev)
 */
 static void ni_handle_fifo_dregs(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
 	short data[2];
 	u32 dl;
@@ -1535,6 +1573,7 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev)
 
 static void get_last_sample_611x(struct comedi_device *dev)
 {
+	struct ni_private *devpriv __maybe_unused = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
 	short data;
 	u32 dl;
@@ -1552,6 +1591,7 @@ static void get_last_sample_611x(struct comedi_device *dev)
 
 static void get_last_sample_6143(struct comedi_device *dev)
 {
+	struct ni_private *devpriv __maybe_unused = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
 	short data;
 	u32 dl;
@@ -1574,11 +1614,13 @@ static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
 			void *data, unsigned int num_bytes,
 			unsigned int chan_index)
 {
+	struct ni_private *devpriv = dev->private;
 	struct comedi_async *async = s->async;
 	unsigned int i;
 	unsigned int length = num_bytes / bytes_per_sample(s);
 	short *array = data;
 	unsigned int *larray = data;
+
 	for (i = 0; i < length; i++) {
 #ifdef PCIDMA
 		if (s->subdev_flags & SDF_LSAMPL)
@@ -1599,6 +1641,7 @@ static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_ai_setup_MITE_dma(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
 	int retval;
 	unsigned long flags;
@@ -1638,6 +1681,7 @@ static int ni_ai_setup_MITE_dma(struct comedi_device *dev)
 
 static int ni_ao_setup_MITE_dma(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AO_SUBDEV];
 	int retval;
 	unsigned long flags;
@@ -1676,6 +1720,8 @@ static int ni_ao_setup_MITE_dma(struct comedi_device *dev)
 
 static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct ni_private *devpriv = dev->private;
+
 	ni_release_ai_mite_channel(dev);
 	/* ai configuration */
 	devpriv->stc_writew(dev, AI_Configuration_Start | AI_Reset,
@@ -1786,6 +1832,7 @@ static int ni_ai_insn_read(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
 			   unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
 	int i, n;
 	const unsigned int mask = (1 << boardtype.adbits) - 1;
 	unsigned signbits;
@@ -1881,7 +1928,9 @@ static int ni_ai_insn_read(struct comedi_device *dev,
 
 static void ni_prime_channelgain_list(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
 	int i;
+
 	devpriv->stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register);
 	for (i = 0; i < NI_TIMEOUT; ++i) {
 		if (!(devpriv->stc_readw(dev,
@@ -1899,6 +1948,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev,
 					      unsigned int n_chan,
 					      unsigned int *list)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned int chan, range, aref;
 	unsigned int i;
 	unsigned offset;
@@ -2004,6 +2054,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev,
 static void ni_load_channelgain_list(struct comedi_device *dev,
 				     unsigned int n_chan, unsigned int *list)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned int chan, range, aref;
 	unsigned int i;
 	unsigned int hi, lo;
@@ -2122,7 +2173,9 @@ static void ni_load_channelgain_list(struct comedi_device *dev,
 static int ni_ns_to_timer(const struct comedi_device *dev, unsigned nanosec,
 			  int round_mode)
 {
+	struct ni_private *devpriv = dev->private;
 	int divider;
+
 	switch (round_mode) {
 	case TRIG_ROUND_NEAREST:
 	default:
@@ -2140,6 +2193,8 @@ static int ni_ns_to_timer(const struct comedi_device *dev, unsigned nanosec,
 
 static unsigned ni_timer_to_ns(const struct comedi_device *dev, int timer)
 {
+	struct ni_private *devpriv = dev->private;
+
 	return devpriv->clock_ns * (timer + 1);
 }
 
@@ -2162,6 +2217,7 @@ static unsigned ni_min_ai_scan_period_ns(struct comedi_device *dev,
 static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_cmd *cmd)
 {
+	struct ni_private *devpriv = dev->private;
 	int err = 0;
 	int tmp;
 	unsigned int sources;
@@ -2200,7 +2256,7 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
 	if (cmd->start_src == TRIG_EXT) {
 		/* external trigger */
@@ -2209,30 +2265,17 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 		if (tmp > 16)
 			tmp = 16;
 		tmp |= (cmd->start_arg & (CR_INVERT | CR_EDGE));
-		if (cmd->start_arg != tmp) {
-			cmd->start_arg = tmp;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->start_arg, tmp);
 	} else {
-		if (cmd->start_arg != 0) {
-			/* true for both TRIG_NOW and TRIG_INT */
-			cmd->start_arg = 0;
-			err++;
-		}
+		/* true for both TRIG_NOW and TRIG_INT */
+		err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 	}
+
 	if (cmd->scan_begin_src == TRIG_TIMER) {
-		if (cmd->scan_begin_arg < ni_min_ai_scan_period_ns(dev,
-								   cmd->
-								   chanlist_len))
-		{
-			cmd->scan_begin_arg =
-			    ni_min_ai_scan_period_ns(dev, cmd->chanlist_len);
-			err++;
-		}
-		if (cmd->scan_begin_arg > devpriv->clock_ns * 0xffffff) {
-			cmd->scan_begin_arg = devpriv->clock_ns * 0xffffff;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+			ni_min_ai_scan_period_ns(dev, cmd->chanlist_len));
+		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
+						 devpriv->clock_ns * 0xffffff);
 	} else if (cmd->scan_begin_src == TRIG_EXT) {
 		/* external trigger */
 		unsigned int tmp = CR_CHAN(cmd->scan_begin_arg);
@@ -2240,32 +2283,20 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 		if (tmp > 16)
 			tmp = 16;
 		tmp |= (cmd->scan_begin_arg & (CR_INVERT | CR_EDGE));
-		if (cmd->scan_begin_arg != tmp) {
-			cmd->scan_begin_arg = tmp;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, tmp);
 	} else {		/* TRIG_OTHER */
-		if (cmd->scan_begin_arg) {
-			cmd->scan_begin_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 	}
+
 	if (cmd->convert_src == TRIG_TIMER) {
 		if ((boardtype.reg_type == ni_reg_611x)
 		    || (boardtype.reg_type == ni_reg_6143)) {
-			if (cmd->convert_arg != 0) {
-				cmd->convert_arg = 0;
-				err++;
-			}
+			err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 		} else {
-			if (cmd->convert_arg < boardtype.ai_speed) {
-				cmd->convert_arg = boardtype.ai_speed;
-				err++;
-			}
-			if (cmd->convert_arg > devpriv->clock_ns * 0xffff) {
-				cmd->convert_arg = devpriv->clock_ns * 0xffff;
-				err++;
-			}
+			err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+							 boardtype.ai_speed);
+			err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
+						devpriv->clock_ns * 0xffff);
 		}
 	} else if (cmd->convert_src == TRIG_EXT) {
 		/* external trigger */
@@ -2274,40 +2305,23 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 		if (tmp > 16)
 			tmp = 16;
 		tmp |= (cmd->convert_arg & (CR_ALT_FILTER | CR_INVERT));
-		if (cmd->convert_arg != tmp) {
-			cmd->convert_arg = tmp;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, tmp);
 	} else if (cmd->convert_src == TRIG_NOW) {
-		if (cmd->convert_arg != 0) {
-			cmd->convert_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 	}
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
 	if (cmd->stop_src == TRIG_COUNT) {
 		unsigned int max_count = 0x01000000;
 
 		if (boardtype.reg_type == ni_reg_611x)
 			max_count -= num_adc_stages_611x;
-		if (cmd->stop_arg > max_count) {
-			cmd->stop_arg = max_count;
-			err++;
-		}
-		if (cmd->stop_arg < 1) {
-			cmd->stop_arg = 1;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_max(&cmd->stop_arg, max_count);
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
 	} else {
 		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 	}
 
 	if (err)
@@ -2356,6 +2370,7 @@ static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct ni_private *devpriv = dev->private;
 	const struct comedi_cmd *cmd = &s->async->cmd;
 	int timer;
 	int mode1 = 0;		/* mode1 is needed for both stop and convert */
@@ -2662,6 +2677,8 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 static int ni_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
 			 unsigned int trignum)
 {
+	struct ni_private *devpriv = dev->private;
+
 	if (trignum != 0)
 		return -EINVAL;
 
@@ -2681,6 +2698,8 @@ static int ni_ai_insn_config(struct comedi_device *dev,
 			     struct comedi_subdevice *s,
 			     struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
+
 	if (insn->n < 1)
 		return -EINVAL;
 
@@ -2734,6 +2753,7 @@ static int ni_ai_config_analog_trig(struct comedi_device *dev,
 				    struct comedi_insn *insn,
 				    unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned int a, b, modebits;
 	int err = 0;
 
@@ -2857,6 +2877,7 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev,
 					  unsigned int chanspec[],
 					  unsigned int n_chans, int timed)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned int range;
 	unsigned int chan;
 	unsigned int conf;
@@ -2928,6 +2949,7 @@ static int ni_old_ao_config_chanlist(struct comedi_device *dev,
 				     unsigned int chanspec[],
 				     unsigned int n_chans)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned int range;
 	unsigned int chan;
 	unsigned int conf;
@@ -2984,6 +3006,8 @@ static int ni_ao_insn_read(struct comedi_device *dev,
 			   struct comedi_subdevice *s, struct comedi_insn *insn,
 			   unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
+
 	data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];
 
 	return 1;
@@ -2993,6 +3017,7 @@ static int ni_ao_insn_write(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
 	unsigned int invert;
 
@@ -3013,6 +3038,7 @@ static int ni_ao_insn_write_671x(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
 				 struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
 	unsigned int invert;
 
@@ -3031,6 +3057,8 @@ static int ni_ao_insn_config(struct comedi_device *dev,
 			     struct comedi_subdevice *s,
 			     struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
+
 	switch (data[0]) {
 	case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE:
 		switch (data[1]) {
@@ -3057,6 +3085,7 @@ static int ni_ao_insn_config(struct comedi_device *dev,
 static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
 			 unsigned int trignum)
 {
+	struct ni_private *devpriv = dev->private;
 	int ret;
 	int interrupt_b_bits;
 	int i;
@@ -3126,6 +3155,7 @@ static int ni_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct ni_private *devpriv = dev->private;
 	const struct comedi_cmd *cmd = &s->async->cmd;
 	int bits;
 	int i;
@@ -3330,6 +3360,7 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_cmd *cmd)
 {
+	struct ni_private *devpriv = dev->private;
 	int err = 0;
 	int tmp;
 
@@ -3359,7 +3390,7 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
 	if (cmd->start_src == TRIG_EXT) {
 		/* external trigger */
@@ -3368,48 +3399,27 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 		if (tmp > 18)
 			tmp = 18;
 		tmp |= (cmd->start_arg & (CR_INVERT | CR_EDGE));
-		if (cmd->start_arg != tmp) {
-			cmd->start_arg = tmp;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->start_arg, tmp);
 	} else {
-		if (cmd->start_arg != 0) {
-			/* true for both TRIG_NOW and TRIG_INT */
-			cmd->start_arg = 0;
-			err++;
-		}
+		/* true for both TRIG_NOW and TRIG_INT */
+		err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 	}
+
 	if (cmd->scan_begin_src == TRIG_TIMER) {
-		if (cmd->scan_begin_arg < boardtype.ao_speed) {
-			cmd->scan_begin_arg = boardtype.ao_speed;
-			err++;
-		}
-		if (cmd->scan_begin_arg > devpriv->clock_ns * 0xffffff) {	/* XXX check */
-			cmd->scan_begin_arg = devpriv->clock_ns * 0xffffff;
-			err++;
-		}
-	}
-	if (cmd->convert_arg != 0) {
-		cmd->convert_arg = 0;
-		err++;
-	}
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_COUNT) {	/* XXX check */
-		if (cmd->stop_arg > 0x00ffffff) {
-			cmd->stop_arg = 0x00ffffff;
-			err++;
-		}
-	} else {
-		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						 boardtype.ao_speed);
+		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
+						 devpriv->clock_ns * 0xffffff);
 	}
 
+	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+	if (cmd->stop_src == TRIG_COUNT)
+		err |= cfc_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
+	else	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+
 	if (err)
 		return 3;
 
@@ -3438,6 +3448,8 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct ni_private *devpriv = dev->private;
+
 	/* devpriv->ao0p=0x0000; */
 	/* ni_writew(devpriv->ao0p,AO_Configuration); */
 
@@ -3491,6 +3503,8 @@ static int ni_dio_insn_config(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
 			      struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
+
 #ifdef DEBUG_DIO
 	printk("ni_dio_insn_config() chan=%d io=%d\n",
 	       CR_CHAN(insn->chanspec), data[0]);
@@ -3524,6 +3538,8 @@ static int ni_dio_insn_bits(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    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
@@ -3552,6 +3568,8 @@ static int ni_m_series_dio_insn_config(struct comedi_device *dev,
 				       struct comedi_insn *insn,
 				       unsigned int *data)
 {
+	struct ni_private *devpriv __maybe_unused = dev->private;
+
 #ifdef DEBUG_DIO
 	printk("ni_m_series_dio_insn_config() chan=%d io=%d\n",
 	       CR_CHAN(insn->chanspec), data[0]);
@@ -3584,6 +3602,8 @@ static int ni_m_series_dio_insn_bits(struct comedi_device *dev,
 				     struct comedi_insn *insn,
 				     unsigned int *data)
 {
+	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]);
@@ -3623,39 +3643,18 @@ static int ni_cdio_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
-	if (cmd->start_src == TRIG_INT) {
-		if (cmd->start_arg != 0) {
-			cmd->start_arg = 0;
-			err++;
-		}
-	}
-	if (cmd->scan_begin_src == TRIG_EXT) {
-		tmp = cmd->scan_begin_arg;
-		tmp &= CR_PACK_FLAGS(CDO_Sample_Source_Select_Mask, 0, 0,
-				     CR_INVERT);
-		if (tmp != cmd->scan_begin_arg) {
-			err++;
-		}
-	}
-	if (cmd->convert_src == TRIG_NOW) {
-		if (cmd->convert_arg) {
-			cmd->convert_arg = 0;
-			err++;
-		}
-	}
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->stop_src == TRIG_NONE) {
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	tmp = cmd->scan_begin_arg;
+	tmp &= CR_PACK_FLAGS(CDO_Sample_Source_Select_Mask, 0, 0, CR_INVERT);
+	if (tmp != cmd->scan_begin_arg)
+		err |= -EINVAL;
+
+	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+	err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -3680,6 +3679,7 @@ static int ni_cdio_cmdtest(struct comedi_device *dev,
 
 static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct ni_private *devpriv __maybe_unused = dev->private;
 	const struct comedi_cmd *cmd = &s->async->cmd;
 	unsigned cdo_mode_bits = CDO_FIFO_Mode_Bit | CDO_Halt_On_Error_Bit;
 	int retval;
@@ -3719,6 +3719,7 @@ static int ni_cdo_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
 			  unsigned int trignum)
 {
 #ifdef PCIDMA
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 #endif
 	int retval = 0;
@@ -3766,6 +3767,8 @@ static int ni_cdo_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct ni_private *devpriv __maybe_unused = dev->private;
+
 	ni_writel(CDO_Disarm_Bit | CDO_Error_Interrupt_Enable_Clear_Bit |
 		  CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit |
 		  CDO_FIFO_Request_Interrupt_Enable_Clear_Bit,
@@ -3781,6 +3784,7 @@ static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static void handle_cdio_interrupt(struct comedi_device *dev)
 {
+	struct ni_private *devpriv __maybe_unused = dev->private;
 	unsigned cdio_status;
 	struct comedi_subdevice *s = &dev->subdevices[NI_DIO_SUBDEV];
 #ifdef PCIDMA
@@ -3824,6 +3828,7 @@ static int ni_serial_insn_config(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
 				 struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
 	int err = insn->n;
 	unsigned char byte_out, byte_in = 0;
 
@@ -3920,6 +3925,7 @@ static int ni_serial_hw_readwrite8(struct comedi_device *dev,
 				   unsigned char data_out,
 				   unsigned char *data_in)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned int status1;
 	int err = 0, count = 20;
 
@@ -3978,6 +3984,7 @@ static int ni_serial_sw_readwrite8(struct comedi_device *dev,
 				   unsigned char data_out,
 				   unsigned char *data_in)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned char mask, input = 0;
 
 #ifdef DEBUG_DIO
@@ -4031,9 +4038,10 @@ static int ni_serial_sw_readwrite8(struct comedi_device *dev,
 
 static void mio_common_detach(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
 	struct comedi_subdevice *s;
 
-	if (dev->private) {
+	if (devpriv) {
 		if (devpriv->counter_dev) {
 			ni_gpct_device_destroy(devpriv->counter_dev);
 		}
@@ -4151,6 +4159,7 @@ static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits,
 				   enum ni_gpct_register reg)
 {
 	struct comedi_device *dev = counter->counter_dev->dev;
+	struct ni_private *devpriv = dev->private;
 	unsigned stc_register;
 	/* bits in the join reset register which are relevant to counters */
 	static const unsigned gpct_joint_reset_mask = G0_Reset | G1_Reset;
@@ -4219,7 +4228,9 @@ static unsigned ni_gpct_read_register(struct ni_gpct *counter,
 				      enum ni_gpct_register reg)
 {
 	struct comedi_device *dev = counter->counter_dev->dev;
+	struct ni_private *devpriv = dev->private;
 	unsigned stc_register;
+
 	switch (reg) {
 		/* m-series only registers */
 	case NITIO_G0_DMA_Status_Reg:
@@ -4251,6 +4262,8 @@ static int ni_freq_out_insn_read(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
 				 struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
+
 	data[0] = devpriv->clock_and_fout & FOUT_Divider_mask;
 	return 1;
 }
@@ -4259,6 +4272,8 @@ static int ni_freq_out_insn_write(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
 				  struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
+
 	devpriv->clock_and_fout &= ~FOUT_Enable;
 	devpriv->stc_writew(dev, devpriv->clock_and_fout,
 			    Clock_and_FOUT_Register);
@@ -4273,6 +4288,8 @@ static int ni_freq_out_insn_write(struct comedi_device *dev,
 static int ni_set_freq_out_clock(struct comedi_device *dev,
 				 unsigned int clock_source)
 {
+	struct ni_private *devpriv = dev->private;
+
 	switch (clock_source) {
 	case NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC:
 		devpriv->clock_and_fout &= ~FOUT_Timebase_Select;
@@ -4292,6 +4309,8 @@ static void ni_get_freq_out_clock(struct comedi_device *dev,
 				  unsigned int *clock_source,
 				  unsigned int *clock_period_ns)
 {
+	struct ni_private *devpriv = dev->private;
+
 	if (devpriv->clock_and_fout & FOUT_Timebase_Select) {
 		*clock_source = NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC;
 		*clock_period_ns = TIMEBASE_2_NS;
@@ -4320,11 +4339,12 @@ static int ni_freq_out_insn_config(struct comedi_device *dev,
 
 static int ni_alloc_private(struct comedi_device *dev)
 {
-	int ret;
+	struct ni_private *devpriv;
 
-	ret = alloc_private(dev, sizeof(struct ni_private));
-	if (ret < 0)
-		return ret;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	spin_lock_init(&devpriv->window_lock);
 	spin_lock_init(&devpriv->soft_reg_copy_lock);
@@ -4335,6 +4355,7 @@ static int ni_alloc_private(struct comedi_device *dev)
 
 static int ni_E_init(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
 	struct comedi_subdevice *s;
 	unsigned j;
 	enum ni_gpct_variant counter_variant;
@@ -4661,6 +4682,7 @@ static int ni_E_init(struct comedi_device *dev)
 static int ni_8255_callback(int dir, int port, int data, unsigned long arg)
 {
 	struct comedi_device *dev = (struct comedi_device *)arg;
+	struct ni_private *devpriv __maybe_unused = dev->private;
 
 	if (dir) {
 		ni_writeb(data, Port_A + 2 * port);
@@ -4689,6 +4711,7 @@ static int ni_eeprom_insn_read(struct comedi_device *dev,
 
 static int ni_read_eeprom(struct comedi_device *dev, int addr)
 {
+	struct ni_private *devpriv __maybe_unused = dev->private;
 	int bit;
 	int bitstring;
 
@@ -4716,6 +4739,8 @@ static int ni_m_series_eeprom_insn_read(struct comedi_device *dev,
 					struct comedi_insn *insn,
 					unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
+
 	data[0] = devpriv->eeprom_buffer[CR_CHAN(insn->chanspec)];
 
 	return 1;
@@ -4723,6 +4748,8 @@ static int ni_m_series_eeprom_insn_read(struct comedi_device *dev,
 
 static int ni_get_pwm_config(struct comedi_device *dev, unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
+
 	data[1] = devpriv->pwm_up_count * devpriv->clock_ns;
 	data[2] = devpriv->pwm_down_count * devpriv->clock_ns;
 	return 3;
@@ -4732,7 +4759,9 @@ static int ni_m_series_pwm_config(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
 				  struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned up_count, down_count;
+
 	switch (data[0]) {
 	case INSN_CONFIG_PWM_OUTPUT:
 		switch (data[1]) {
@@ -4798,7 +4827,9 @@ static int ni_6143_pwm_config(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
 			      struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned up_count, down_count;
+
 	switch (data[0]) {
 	case INSN_CONFIG_PWM_OUTPUT:
 		switch (data[1]) {
@@ -4875,6 +4906,8 @@ static int ni_calib_insn_read(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
 			      struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
+
 	data[0] = devpriv->caldacs[CR_CHAN(insn->chanspec)];
 
 	return 1;
@@ -4905,6 +4938,7 @@ static struct caldac_struct caldacs[] = {
 
 static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct ni_private *devpriv = dev->private;
 	int i, j;
 	int n_dacs;
 	int n_chans = 0;
@@ -4958,6 +4992,7 @@ static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static void ni_write_caldac(struct comedi_device *dev, int addr, int val)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned int loadbit = 0, bits = 0, bit, bitstring = 0;
 	int i;
 	int type;
@@ -5211,8 +5246,10 @@ static int ni_gpct_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 static int ni_m_series_set_pfi_routing(struct comedi_device *dev, unsigned chan,
 				       unsigned source)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned pfi_reg_index;
 	unsigned array_offset;
+
 	if ((source & 0x1f) != source)
 		return -EINVAL;
 	pfi_reg_index = 1 + chan / 3;
@@ -5247,7 +5284,9 @@ static int ni_set_pfi_routing(struct comedi_device *dev, unsigned chan,
 static unsigned ni_m_series_get_pfi_routing(struct comedi_device *dev,
 					    unsigned chan)
 {
+	struct ni_private *devpriv = dev->private;
 	const unsigned array_offset = chan / 3;
+
 	return MSeries_PFI_Output_Select_Source(chan,
 						devpriv->
 						pfi_output_select_reg
@@ -5306,7 +5345,9 @@ static unsigned ni_get_pfi_routing(struct comedi_device *dev, unsigned chan)
 static int ni_config_filter(struct comedi_device *dev, unsigned pfi_channel,
 			    enum ni_pfi_filter_select filter)
 {
+	struct ni_private *devpriv __maybe_unused = dev->private;
 	unsigned bits;
+
 	if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) {
 		return -ENOTSUPP;
 	}
@@ -5321,6 +5362,8 @@ static int ni_pfi_insn_bits(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_private *devpriv __maybe_unused = dev->private;
+
 	if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) {
 		return -ENOTSUPP;
 	}
@@ -5337,6 +5380,7 @@ static int ni_pfi_insn_config(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
 			      struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned int chan;
 
 	if (insn->n < 1)
@@ -5379,6 +5423,8 @@ static int ni_pfi_insn_config(struct comedi_device *dev,
  */
 static void ni_rtsi_init(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
+
 	/*  Initialises the RTSI bus signal switch to a default state */
 
 	/*  Set clock mode to internal */
@@ -5480,6 +5526,7 @@ static inline unsigned num_configurable_rtsi_channels(struct comedi_device *dev)
 static int ni_mseries_set_pll_master_clock(struct comedi_device *dev,
 					   unsigned source, unsigned period_ns)
 {
+	struct ni_private *devpriv = dev->private;
 	static const unsigned min_period_ns = 50;
 	static const unsigned max_period_ns = 1000;
 	static const unsigned timeout = 1000;
@@ -5488,6 +5535,7 @@ static int ni_mseries_set_pll_master_clock(struct comedi_device *dev,
 	unsigned freq_multiplier;
 	unsigned i;
 	int retval;
+
 	if (source == NI_MIO_PLL_PXI10_CLOCK)
 		period_ns = 100;
 	/*  these limits are somewhat arbitrary, but NI advertises 1 to 20MHz range so we'll use that */
@@ -5581,6 +5629,8 @@ static int ni_mseries_set_pll_master_clock(struct comedi_device *dev,
 static int ni_set_master_clock(struct comedi_device *dev, unsigned source,
 			       unsigned period_ns)
 {
+	struct ni_private *devpriv = dev->private;
+
 	if (source == NI_MIO_INTERNAL_CLOCK) {
 		devpriv->rtsi_trig_direction_reg &= ~Use_RTSI_Clock_Bit;
 		devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg,
@@ -5666,6 +5716,8 @@ static int ni_valid_rtsi_output_source(struct comedi_device *dev, unsigned chan,
 static int ni_set_rtsi_routing(struct comedi_device *dev, unsigned chan,
 			       unsigned source)
 {
+	struct ni_private *devpriv = dev->private;
+
 	if (ni_valid_rtsi_output_source(dev, chan, source) == 0)
 		return -EINVAL;
 	if (chan < 4) {
@@ -5686,6 +5738,8 @@ static int ni_set_rtsi_routing(struct comedi_device *dev, unsigned chan,
 
 static unsigned ni_get_rtsi_routing(struct comedi_device *dev, unsigned chan)
 {
+	struct ni_private *devpriv = dev->private;
+
 	if (chan < 4) {
 		return RTSI_Trig_Output_Source(chan,
 					       devpriv->rtsi_trig_a_output_reg);
@@ -5704,7 +5758,9 @@ static int ni_rtsi_insn_config(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
+
 	switch (data[0]) {
 	case INSN_CONFIG_DIO_OUTPUT:
 		if (chan < num_configurable_rtsi_channels(dev)) {
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index ca4f8e0..76c6a13 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -175,9 +175,7 @@ struct ni_private {
 
 	struct pcmcia_device *link;
 
- NI_PRIVATE_COMMON};
-
-#define devpriv ((struct ni_private *)dev->private)
+NI_PRIVATE_COMMON};
 
 /* How we access registers */
 
@@ -196,6 +194,7 @@ struct ni_private {
 
 static void mio_cs_win_out(struct comedi_device *dev, uint16_t data, int addr)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->window_lock, flags);
@@ -210,6 +209,7 @@ static void mio_cs_win_out(struct comedi_device *dev, uint16_t data, int addr)
 
 static uint16_t mio_cs_win_in(struct comedi_device *dev, int addr)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 	uint16_t ret;
 
@@ -251,7 +251,7 @@ static void mio_cs_config(struct pcmcia_device *link);
 static void cs_release(struct pcmcia_device *link);
 static void cs_detach(struct pcmcia_device *);
 
-static struct pcmcia_device *cur_dev = NULL;
+static struct pcmcia_device *cur_dev;
 
 static int cs_attach(struct pcmcia_device *link)
 {
@@ -324,6 +324,7 @@ static void mio_cs_config(struct pcmcia_device *link)
 
 static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+	struct ni_private *devpriv;
 	struct pcmcia_device *link;
 	unsigned int irq;
 	int ret;
@@ -339,13 +340,15 @@ static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 	irq = link->irq;
 
-	printk("comedi%d: %s: DAQCard: io 0x%04lx, irq %u, ",
-	       dev->minor, dev->driver->driver_name, dev->iobase, irq);
+	dev->board_ptr = ni_boards + ni_getboardtype(dev, link);
 
 #if 0
 	{
 		int i;
 
+		printk("comedi%d: %s: DAQCard: io 0x%04lx, irq %u, ",
+		       dev->minor, dev->driver->driver_name, dev->iobase, irq);
+
 		printk(" board fingerprint:");
 		for (i = 0; i < 32; i += 2) {
 			printk(" %04x %02x", inw(dev->iobase + i),
@@ -356,26 +359,25 @@ static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		for (i = 0; i < 10; i++)
 			printk(" 0x%04x", win_in(i));
 		printk("\n");
+
+		printk("boardtype.name: %s\n", boardtype.name);
 	}
 #endif
 
-	dev->board_ptr = ni_boards + ni_getboardtype(dev, link);
-
-	printk(" %s", boardtype.name);
 	dev->board_name = boardtype.name;
 
 	ret = request_irq(irq, ni_E_interrupt, NI_E_IRQ_FLAGS,
 			  "ni_mio_cs", dev);
 	if (ret < 0) {
-		printk(" irq not available\n");
+		dev_err(dev->class_dev, "irq not available\n");
 		return -EINVAL;
 	}
 	dev->irq = irq;
 
-	/* allocate private area */
 	ret = ni_alloc_private(dev);
-	if (ret < 0)
+	if (ret)
 		return ret;
+	devpriv = dev->private;
 
 	devpriv->stc_writew = &mio_cs_win_out;
 	devpriv->stc_readw = &mio_cs_win_in;
@@ -400,7 +402,8 @@ static int ni_getboardtype(struct comedi_device *dev,
 			return i;
 	}
 
-	printk("unknown board 0x%04x -- pretend it is a ", link->card_id);
+	dev_err(dev->class_dev,
+		"unknown board 0x%04x -- pretend it is a ", link->card_id);
 
 	return 0;
 }
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index bc9313e..084ebea 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -310,7 +310,6 @@ struct nidio96_private {
 	struct mite_dma_descriptor_ring *di_mite_ring;
 	spinlock_t mite_channel_lock;
 };
-#define devpriv ((struct nidio96_private *)dev->private)
 
 static int ni_pcidio_cmdtest(struct comedi_device *dev,
 			     struct comedi_subdevice *s,
@@ -332,6 +331,7 @@ static void ni_pcidio_print_status(unsigned int status);
 
 static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev)
 {
+	struct nidio96_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -355,6 +355,7 @@ static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev)
 
 static void ni_pcidio_release_di_mite_channel(struct comedi_device *dev)
 {
+	struct nidio96_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
@@ -384,6 +385,7 @@ static void ni_pcidio_event(struct comedi_device *dev,
 
 static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct nidio96_private *devpriv = dev->private;
 	unsigned long irq_flags;
 	int count;
 
@@ -400,6 +402,7 @@ static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 static irqreturn_t nidio_interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct nidio96_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[0];
 	struct comedi_async *async = s->async;
 	struct mite_struct *mite = devpriv->mite;
@@ -609,6 +612,7 @@ static void ni_pcidio_print_status(unsigned int flags)
 #ifdef unused
 static void debug_int(struct comedi_device *dev)
 {
+	struct nidio96_private *devpriv = dev->private;
 	int a, b;
 	static int n_int;
 	struct timeval tv;
@@ -640,6 +644,8 @@ static int ni_pcidio_insn_config(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
 				 struct comedi_insn *insn, unsigned int *data)
 {
+	struct nidio96_private *devpriv = dev->private;
+
 	if (insn->n != 1)
 		return -EINVAL;
 	switch (data[0]) {
@@ -668,6 +674,8 @@ static int ni_pcidio_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       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]);
@@ -707,46 +715,32 @@ static int ni_pcidio_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
+
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->start_arg != 0) {
-		/* same for both TRIG_INT and TRIG_NOW */
-		cmd->start_arg = 0;
-		err++;
-	}
 #define MAX_SPEED	(TIMER_BASE)	/* in nanoseconds */
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
-		if (cmd->scan_begin_arg < MAX_SPEED) {
-			cmd->scan_begin_arg = MAX_SPEED;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						 MAX_SPEED);
 		/* no minimum speed */
 	} else {
 		/* TRIG_EXT */
 		/* should be level/edge, hi/lo specification here */
 		if ((cmd->scan_begin_arg & ~(CR_EDGE | CR_INVERT)) != 0) {
 			cmd->scan_begin_arg &= (CR_EDGE | CR_INVERT);
-			err++;
+			err |= -EINVAL;
 		}
 	}
-	if (cmd->convert_arg != 0) {
-		cmd->convert_arg = 0;
-		err++;
-	}
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
 	if (cmd->stop_src == TRIG_COUNT) {
 		/* no limit */
-	} else {
-		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+	} else {	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 	}
 
 	if (err)
@@ -793,6 +787,7 @@ static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode)
 
 static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct nidio96_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
 
 	/* XXX configure ports for input */
@@ -910,6 +905,7 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct nidio96_private *devpriv = dev->private;
 	int retval;
 	unsigned long flags;
 
@@ -934,6 +930,8 @@ static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s)
 static int ni_pcidio_inttrig(struct comedi_device *dev,
 			     struct comedi_subdevice *s, unsigned int trignum)
 {
+	struct nidio96_private *devpriv = dev->private;
+
 	if (trignum != 0)
 		return -EINVAL;
 
@@ -946,6 +944,8 @@ static int ni_pcidio_inttrig(struct comedi_device *dev,
 static int ni_pcidio_cancel(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
+	struct nidio96_private *devpriv = dev->private;
+
 	writeb(0x00,
 	       devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control);
 	ni_pcidio_release_di_mite_channel(dev);
@@ -956,6 +956,7 @@ static int ni_pcidio_cancel(struct comedi_device *dev,
 static int ni_pcidio_change(struct comedi_device *dev,
 			    struct comedi_subdevice *s, unsigned long new_size)
 {
+	struct nidio96_private *devpriv = dev->private;
 	int ret;
 
 	ret = mite_buf_change(devpriv->di_mite_ring, s->async);
@@ -970,6 +971,7 @@ static int ni_pcidio_change(struct comedi_device *dev,
 static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index,
 			      const u8 *data, size_t data_len)
 {
+	struct nidio96_private *devpriv = dev->private;
 	static const int timeout = 1000;
 	int i;
 	size_t j;
@@ -1033,8 +1035,10 @@ static int pci_6534_reset_fpga(struct comedi_device *dev, int fpga_index)
 
 static int pci_6534_reset_fpgas(struct comedi_device *dev)
 {
+	struct nidio96_private *devpriv = dev->private;
 	int ret;
 	int i;
+
 	writew(0x0, devpriv->mite->daq_io_addr + Firmware_Control_Register);
 	for (i = 0; i < 3; ++i) {
 		ret = pci_6534_reset_fpga(dev, i);
@@ -1047,6 +1051,8 @@ static int pci_6534_reset_fpgas(struct comedi_device *dev)
 
 static void pci_6534_init_main_fpga(struct comedi_device *dev)
 {
+	struct nidio96_private *devpriv = dev->private;
+
 	writel(0, devpriv->mite->daq_io_addr + FPGA_Control1_Register);
 	writel(0, devpriv->mite->daq_io_addr + FPGA_Control2_Register);
 	writel(0, devpriv->mite->daq_io_addr + FPGA_SCALS_Counter_Register);
@@ -1057,6 +1063,7 @@ static void pci_6534_init_main_fpga(struct comedi_device *dev)
 
 static int pci_6534_upload_firmware(struct comedi_device *dev)
 {
+	struct nidio96_private *devpriv = dev->private;
 	int ret;
 	const struct firmware *fw;
 	static const char *const fw_file[3] = {
@@ -1099,16 +1106,20 @@ nidio_find_boardinfo(struct pci_dev *pcidev)
 	return NULL;
 }
 
-static int __devinit nidio_attach_pci(struct comedi_device *dev,
-				      struct pci_dev *pcidev)
+static int nidio_auto_attach(struct comedi_device *dev,
+				       unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct nidio96_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 	unsigned int irq;
 
-	ret = alloc_private(dev, sizeof(struct nidio96_private));
-	if (ret < 0)
-		return ret;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
 	spin_lock_init(&devpriv->mite_channel_lock);
 
 	dev->board_ptr = nidio_find_boardinfo(pcidev);
@@ -1123,7 +1134,7 @@ static int __devinit nidio_attach_pci(struct comedi_device *dev,
 		dev_warn(dev->class_dev, "error setting up mite\n");
 		return ret;
 	}
-	comedi_set_hw_dev(dev, &devpriv->mite->pcidev->dev);
+
 	devpriv->di_mite_ring = mite_alloc_ring(devpriv->mite);
 	if (devpriv->di_mite_ring == NULL)
 		return -ENOMEM;
@@ -1184,6 +1195,8 @@ static int __devinit nidio_attach_pci(struct comedi_device *dev,
 
 static void nidio_detach(struct comedi_device *dev)
 {
+	struct nidio96_private *devpriv = dev->private;
+
 	if (dev->irq)
 		free_irq(dev->irq, dev);
 	if (devpriv) {
@@ -1201,17 +1214,17 @@ static void nidio_detach(struct comedi_device *dev)
 static struct comedi_driver ni_pcidio_driver = {
 	.driver_name	= "ni_pcidio",
 	.module		= THIS_MODULE,
-	.attach_pci	= nidio_attach_pci,
+	.auto_attach	= nidio_auto_attach,
 	.detach		= nidio_detach,
 };
 
-static int __devinit ni_pcidio_pci_probe(struct pci_dev *dev,
+static int ni_pcidio_pci_probe(struct pci_dev *dev,
 					 const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &ni_pcidio_driver);
 }
 
-static void __devexit ni_pcidio_pci_remove(struct pci_dev *dev)
+static void ni_pcidio_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -1228,7 +1241,7 @@ static struct pci_driver ni_pcidio_pci_driver = {
 	.name		= "ni_pcidio",
 	.id_table	= ni_pcidio_pci_table,
 	.probe		= ni_pcidio_pci_probe,
-	.remove		= __devexit_p(ni_pcidio_pci_remove),
+	.remove		= ni_pcidio_pci_remove,
 };
 module_comedi_pci_driver(ni_pcidio_driver, ni_pcidio_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
index f284a90..aaac0b2 100644
--- a/drivers/staging/comedi/drivers/ni_pcimio.c
+++ b/drivers/staging/comedi/drivers/ni_pcimio.c
@@ -1190,7 +1190,6 @@ static const struct ni_board_struct ni_boards[] = {
 
 struct ni_private {
 NI_PRIVATE_COMMON};
-#define devpriv ((struct ni_private *)dev->private)
 
 /* How we access registers */
 
@@ -1213,6 +1212,7 @@ NI_PRIVATE_COMMON};
 
 static void e_series_win_out(struct comedi_device *dev, uint16_t data, int reg)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&devpriv->window_lock, flags);
@@ -1223,6 +1223,7 @@ static void e_series_win_out(struct comedi_device *dev, uint16_t data, int reg)
 
 static uint16_t e_series_win_in(struct comedi_device *dev, int reg)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned long flags;
 	uint16_t ret;
 
@@ -1237,7 +1238,9 @@ static uint16_t e_series_win_in(struct comedi_device *dev, int reg)
 static void m_series_stc_writew(struct comedi_device *dev, uint16_t data,
 				int reg)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned offset;
+
 	switch (reg) {
 	case ADC_FIFO_Clear:
 		offset = M_Offset_AI_FIFO_Clear;
@@ -1381,8 +1384,9 @@ static void m_series_stc_writew(struct comedi_device *dev, uint16_t data,
 		/* FIXME: DIO_Output_Register (16 bit reg) is replaced by M_Offset_Static_Digital_Output (32 bit)
 		   and M_Offset_SCXI_Serial_Data_Out (8 bit) */
 	default:
-		printk(KERN_WARNING "%s: bug! unhandled register=0x%x in switch.\n",
-		       __func__, reg);
+		dev_warn(dev->class_dev,
+			 "%s: bug! unhandled register=0x%x in switch.\n",
+			 __func__, reg);
 		BUG();
 		return;
 		break;
@@ -1392,7 +1396,9 @@ static void m_series_stc_writew(struct comedi_device *dev, uint16_t data,
 
 static uint16_t m_series_stc_readw(struct comedi_device *dev, int reg)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned offset;
+
 	switch (reg) {
 	case AI_Status_1_Register:
 		offset = M_Offset_AI_Status_1;
@@ -1416,8 +1422,9 @@ static uint16_t m_series_stc_readw(struct comedi_device *dev, int reg)
 		offset = M_Offset_G01_Status;
 		break;
 	default:
-		printk(KERN_WARNING "%s: bug! unhandled register=0x%x in switch.\n",
-		       __func__, reg);
+		dev_warn(dev->class_dev,
+			 "%s: bug! unhandled register=0x%x in switch.\n",
+			 __func__, reg);
 		BUG();
 		return 0;
 		break;
@@ -1428,7 +1435,9 @@ static uint16_t m_series_stc_readw(struct comedi_device *dev, int reg)
 static void m_series_stc_writel(struct comedi_device *dev, uint32_t data,
 				int reg)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned offset;
+
 	switch (reg) {
 	case AI_SC_Load_A_Registers:
 		offset = M_Offset_AI_SC_Load_A;
@@ -1458,8 +1467,9 @@ static void m_series_stc_writel(struct comedi_device *dev, uint32_t data,
 		offset = M_Offset_G1_Load_B;
 		break;
 	default:
-		printk(KERN_WARNING "%s: bug! unhandled register=0x%x in switch.\n",
-		       __func__, reg);
+		dev_warn(dev->class_dev,
+			 "%s: bug! unhandled register=0x%x in switch.\n",
+			 __func__, reg);
 		BUG();
 		return;
 		break;
@@ -1469,7 +1479,9 @@ static void m_series_stc_writel(struct comedi_device *dev, uint32_t data,
 
 static uint32_t m_series_stc_readl(struct comedi_device *dev, int reg)
 {
+	struct ni_private *devpriv = dev->private;
 	unsigned offset;
+
 	switch (reg) {
 	case G_HW_Save_Register(0):
 		offset = M_Offset_G0_HW_Save;
@@ -1484,8 +1496,9 @@ static uint32_t m_series_stc_readl(struct comedi_device *dev, int reg)
 		offset = M_Offset_G1_Save;
 		break;
 	default:
-		printk(KERN_WARNING "%s: bug! unhandled register=0x%x in switch.\n",
-		       __func__, reg);
+		dev_warn(dev->class_dev,
+			 "%s: bug! unhandled register=0x%x in switch.\n",
+			 __func__, reg);
 		BUG();
 		return 0;
 		break;
@@ -1516,6 +1529,7 @@ static int pcimio_dio_change(struct comedi_device *dev,
 
 static void m_series_init_eeprom_buffer(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
 	static const int Start_Cal_EEPROM = 0x400;
 	static const unsigned window_size = 10;
 	static const int serial_number_eeprom_offset = 0x4;
@@ -1553,6 +1567,8 @@ static void m_series_init_eeprom_buffer(struct comedi_device *dev)
 
 static void init_6143(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
+
 	/*  Disable interrupts */
 	devpriv->stc_writew(dev, 0, Interrupt_Control_Register);
 
@@ -1572,10 +1588,12 @@ static void init_6143(struct comedi_device *dev)
 
 static void pcimio_detach(struct comedi_device *dev)
 {
+	struct ni_private *devpriv = dev->private;
+
 	mio_common_detach(dev);
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if (dev->private) {
+	if (devpriv) {
 		mite_free_ring(devpriv->ai_mite_ring);
 		mite_free_ring(devpriv->ao_mite_ring);
 		mite_free_ring(devpriv->cdo_mite_ring);
@@ -1602,16 +1620,19 @@ pcimio_find_boardinfo(struct pci_dev *pcidev)
 	return NULL;
 }
 
-static int __devinit pcimio_attach_pci(struct comedi_device *dev,
-				       struct pci_dev *pcidev)
+static int pcimio_auto_attach(struct comedi_device *dev,
+					unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct ni_private *devpriv;
 	int ret;
 
 	dev_info(dev->class_dev, "ni_pcimio: attach %s\n", pci_name(pcidev));
 
 	ret = ni_alloc_private(dev);
-	if (ret < 0)
+	if (ret)
 		return ret;
+	devpriv = dev->private;
 
 	dev->board_ptr = pcimio_find_boardinfo(pcidev);
 	if (!dev->board_ptr)
@@ -1641,7 +1662,7 @@ static int __devinit pcimio_attach_pci(struct comedi_device *dev,
 		pr_warn("error setting up mite\n");
 		return ret;
 	}
-	comedi_set_hw_dev(dev, &devpriv->mite->pcidev->dev);
+
 	devpriv->ai_mite_ring = mite_alloc_ring(devpriv->mite);
 	if (devpriv->ai_mite_ring == NULL)
 		return -ENOMEM;
@@ -1693,6 +1714,7 @@ static int __devinit pcimio_attach_pci(struct comedi_device *dev,
 static int pcimio_ai_change(struct comedi_device *dev,
 			    struct comedi_subdevice *s, unsigned long new_size)
 {
+	struct ni_private *devpriv = dev->private;
 	int ret;
 
 	ret = mite_buf_change(devpriv->ai_mite_ring, s->async);
@@ -1705,6 +1727,7 @@ static int pcimio_ai_change(struct comedi_device *dev,
 static int pcimio_ao_change(struct comedi_device *dev,
 			    struct comedi_subdevice *s, unsigned long new_size)
 {
+	struct ni_private *devpriv = dev->private;
 	int ret;
 
 	ret = mite_buf_change(devpriv->ao_mite_ring, s->async);
@@ -1718,6 +1741,7 @@ static int pcimio_gpct0_change(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       unsigned long new_size)
 {
+	struct ni_private *devpriv = dev->private;
 	int ret;
 
 	ret = mite_buf_change(devpriv->gpct_mite_ring[0], s->async);
@@ -1731,6 +1755,7 @@ static int pcimio_gpct1_change(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       unsigned long new_size)
 {
+	struct ni_private *devpriv = dev->private;
 	int ret;
 
 	ret = mite_buf_change(devpriv->gpct_mite_ring[1], s->async);
@@ -1743,6 +1768,7 @@ static int pcimio_gpct1_change(struct comedi_device *dev,
 static int pcimio_dio_change(struct comedi_device *dev,
 			     struct comedi_subdevice *s, unsigned long new_size)
 {
+	struct ni_private *devpriv = dev->private;
 	int ret;
 
 	ret = mite_buf_change(devpriv->cdo_mite_ring, s->async);
@@ -1755,17 +1781,17 @@ static int pcimio_dio_change(struct comedi_device *dev,
 static struct comedi_driver ni_pcimio_driver = {
 	.driver_name	= "ni_pcimio",
 	.module		= THIS_MODULE,
-	.attach_pci	= pcimio_attach_pci,
+	.auto_attach	= pcimio_auto_attach,
 	.detach		= pcimio_detach,
 };
 
-static int __devinit ni_pcimio_pci_probe(struct pci_dev *dev,
+static int ni_pcimio_pci_probe(struct pci_dev *dev,
 					 const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &ni_pcimio_driver);
 }
 
-static void __devexit ni_pcimio_pci_remove(struct pci_dev *dev)
+static void ni_pcimio_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -1832,7 +1858,7 @@ static struct pci_driver ni_pcimio_pci_driver = {
 	.name		= "ni_pcimio",
 	.id_table	= ni_pcimio_pci_table,
 	.probe		= ni_pcimio_pci_probe,
-	.remove		= __devexit_p(ni_pcimio_pci_remove)
+	.remove		= ni_pcimio_pci_remove
 };
 module_comedi_pci_driver(ni_pcimio_driver, ni_pcimio_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h
index b058820..8572996 100644
--- a/drivers/staging/comedi/drivers/ni_tio.h
+++ b/drivers/staging/comedi/drivers/ni_tio.h
@@ -120,9 +120,9 @@ struct ni_gpct {
 
 struct ni_gpct_device {
 	struct comedi_device *dev;
-	void (*write_register) (struct ni_gpct * counter, unsigned bits,
+	void (*write_register) (struct ni_gpct *counter, unsigned bits,
 				enum ni_gpct_register reg);
-	unsigned (*read_register) (struct ni_gpct * counter,
+	unsigned (*read_register) (struct ni_gpct *counter,
 				   enum ni_gpct_register reg);
 	enum ni_gpct_variant variant;
 	struct ni_gpct *counters;
diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c
index 8ee93d3..0c991b9 100644
--- a/drivers/staging/comedi/drivers/ni_tiocmd.c
+++ b/drivers/staging/comedi/drivers/ni_tiocmd.c
@@ -173,7 +173,8 @@ static int ni_tio_input_cmd(struct ni_gpct *counter, struct comedi_async *async)
 static int ni_tio_output_cmd(struct ni_gpct *counter,
 			     struct comedi_async *async)
 {
-	printk(KERN_ERR "ni_tio: output commands not yet implemented.\n");
+	dev_err(counter->counter_dev->dev->class_dev,
+		"output commands not yet implemented.\n");
 	return -ENOTSUPP;
 
 	counter->mite_chan->dir = COMEDI_OUTPUT;
@@ -219,7 +220,10 @@ int ni_tio_cmd(struct ni_gpct *counter, struct comedi_async *async)
 
 	spin_lock_irqsave(&counter->lock, flags);
 	if (counter->mite_chan == NULL) {
-		printk(KERN_ERR "ni_tio: commands only supported with DMA.  Interrupt-driven commands not yet implemented.\n");
+		dev_err(counter->counter_dev->dev->class_dev,
+			"commands only supported with DMA.  ");
+		dev_err(counter->counter_dev->dev->class_dev,
+			"Interrupt-driven commands not yet implemented.\n");
 		retval = -EIO;
 	} else {
 		retval = ni_tio_cmd_setup(counter, async);
@@ -271,37 +275,19 @@ int ni_tio_cmdtest(struct ni_gpct *counter, struct comedi_cmd *cmd)
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
-	if (cmd->start_src != TRIG_EXT) {
-		if (cmd->start_arg != 0) {
-			cmd->start_arg = 0;
-			err++;
-		}
-	}
-	if (cmd->scan_begin_src != TRIG_EXT) {
-		if (cmd->scan_begin_arg) {
-			cmd->scan_begin_arg = 0;
-			err++;
-		}
-	}
-	if (cmd->convert_src != TRIG_EXT) {
-		if (cmd->convert_arg) {
-			cmd->convert_arg = 0;
-			err++;
-		}
-	}
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	if (cmd->start_src != TRIG_EXT)
+		err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->stop_src == TRIG_NONE) {
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	if (cmd->scan_begin_src != TRIG_EXT)
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+
+	if (cmd->convert_src != TRIG_EXT)
+		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+	err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -427,8 +413,9 @@ void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, int *gate_error,
 				  NITIO_Gxx_Joint_Status2_Reg
 				  (counter->counter_index)) &
 		    Gi_Permanent_Stale_Bit(counter->counter_index)) {
-			printk(KERN_INFO "%s: Gi_Permanent_Stale_Data detected.\n",
-			       __func__);
+			dev_info(counter->counter_dev->dev->class_dev,
+				 "%s: Gi_Permanent_Stale_Data detected.\n",
+				 __func__);
 			if (perm_stale_data)
 				*perm_stale_data = 1;
 		}
@@ -448,7 +435,8 @@ void ni_tio_handle_interrupt(struct ni_gpct *counter,
 	ni_tio_acknowledge_and_confirm(counter, &gate_error, &tc_error,
 				       &perm_stale_data, NULL);
 	if (gate_error) {
-		printk(KERN_NOTICE "%s: Gi_Gate_Error detected.\n", __func__);
+		dev_notice(counter->counter_dev->dev->class_dev,
+			   "%s: Gi_Gate_Error detected.\n", __func__);
 		s->async->events |= COMEDI_CB_OVERFLOW;
 	}
 	if (perm_stale_data)
@@ -459,8 +447,8 @@ void ni_tio_handle_interrupt(struct ni_gpct *counter,
 		if (read_register(counter,
 				NITIO_Gi_DMA_Status_Reg
 				(counter->counter_index)) & Gi_DRQ_Error_Bit) {
-			printk(KERN_NOTICE "%s: Gi_DRQ_Error detected.\n",
-							__func__);
+			dev_notice(counter->counter_dev->dev->class_dev,
+				   "%s: Gi_DRQ_Error detected.\n", __func__);
 			s->async->events |= COMEDI_CB_OVERFLOW;
 		}
 		break;
diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
index 89305a1..6ee5da2 100644
--- a/drivers/staging/comedi/drivers/pcl711.c
+++ b/drivers/staging/comedi/drivers/pcl711.c
@@ -161,14 +161,13 @@ struct pcl711_private {
 	unsigned int divisor2;
 };
 
-#define devpriv ((struct pcl711_private *)dev->private)
-
 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];
 
 	if (!dev->attached) {
@@ -264,6 +263,7 @@ ok:
 static int pcl711_ai_cmdtest(struct comedi_device *dev,
 			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
+	struct pcl711_private *devpriv = dev->private;
 	int tmp;
 	int err = 0;
 
@@ -289,38 +289,24 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3 */
+	/* Step 3: check if arguments are trivially valid */
+
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
 	if (cmd->scan_begin_src == TRIG_EXT) {
-		if (cmd->scan_begin_arg != 0) {
-			cmd->scan_begin_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 	} else {
 #define MAX_SPEED 1000
 #define TIMER_BASE 100
-		if (cmd->scan_begin_arg < MAX_SPEED) {
-			cmd->scan_begin_arg = MAX_SPEED;
-			err++;
-		}
-	}
-	if (cmd->convert_arg != 0) {
-		cmd->convert_arg = 0;
-		err++;
-	}
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						 MAX_SPEED);
 	}
+
+	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
 	if (cmd->stop_src == TRIG_NONE) {
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 	} else {
 		/* ignore */
 	}
@@ -349,6 +335,7 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev,
 
 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;
 
@@ -398,6 +385,7 @@ static int pcl711_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 static int pcl711_ao_insn(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);
 
@@ -417,6 +405,7 @@ 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);
 
@@ -460,6 +449,7 @@ static int pcl711_do_insn_bits(struct comedi_device *dev,
 static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct pcl711_board *board = comedi_board(dev);
+	struct pcl711_private *devpriv;
 	int ret;
 	unsigned long iobase;
 	unsigned int irq;
@@ -499,9 +489,10 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	ret = alloc_private(dev, sizeof(struct pcl711_private));
-	if (ret < 0)
-		return ret;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	s = &dev->subdevices[0];
 	/* AI subdevice */
diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
index 07e72de..50e0196 100644
--- a/drivers/staging/comedi/drivers/pcl726.c
+++ b/drivers/staging/comedi/drivers/pcl726.c
@@ -152,11 +152,10 @@ struct pcl726_private {
 	unsigned int ao_readback[12];
 };
 
-#define devpriv ((struct pcl726_private *)dev->private)
-
 static int pcl726_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
 			  struct comedi_insn *insn, unsigned int *data)
 {
+	struct pcl726_private *devpriv = dev->private;
 	int hi, lo;
 	int n;
 	int chan = CR_CHAN(insn->chanspec);
@@ -183,6 +182,7 @@ static int pcl726_ao_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct pcl726_private *devpriv = dev->private;
 	int chan = CR_CHAN(insn->chanspec);
 	int n;
 
@@ -226,6 +226,7 @@ static int pcl726_do_insn_bits(struct comedi_device *dev,
 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;
 	unsigned long iobase;
 	unsigned int iorange;
@@ -247,9 +248,10 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 	dev->board_name = board->name;
 
-	ret = alloc_private(dev, sizeof(struct pcl726_private));
-	if (ret < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
 
 	for (i = 0; i < 12; i++) {
 		devpriv->bipolar[i] = 0;
diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
index 3cf55ff..560930e 100644
--- a/drivers/staging/comedi/drivers/pcl812.c
+++ b/drivers/staging/comedi/drivers/pcl812.c
@@ -369,8 +369,6 @@ struct pcl812_private {
 	unsigned int ao_readback[2];	/*  data for AO readback */
 };
 
-#define devpriv ((struct pcl812_private *)dev->private)
-
 /*
 ==============================================================================
 */
@@ -388,6 +386,7 @@ static int pcl812_ai_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct pcl812_private *devpriv = dev->private;
 	int n;
 	int timeout, hi;
 
@@ -465,6 +464,7 @@ static int pcl812_ao_insn_write(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
 {
+	struct pcl812_private *devpriv = dev->private;
 	int chan = CR_CHAN(insn->chanspec);
 	int i;
 
@@ -486,6 +486,7 @@ static int pcl812_ao_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct pcl812_private *devpriv = dev->private;
 	int chan = CR_CHAN(insn->chanspec);
 	int i;
 
@@ -533,6 +534,7 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev,
 			     struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
 	const struct pcl812_board *board = comedi_board(dev);
+	struct pcl812_private *devpriv = dev->private;
 	int err = 0;
 	unsigned int flags;
 	int tmp, divisor1, divisor2;
@@ -563,53 +565,25 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
-	if (cmd->scan_begin_arg != 0) {
-		cmd->scan_begin_arg = 0;
-		err++;
-	}
+	if (cmd->convert_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+						 board->ai_ns_min);
+	else	/* TRIG_EXT */
+		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < board->ai_ns_min) {
-			cmd->convert_arg = board->ai_ns_min;
-			err++;
-		}
-	} else {		/* TRIG_EXT */
-		if (cmd->convert_arg != 0) {
-			cmd->convert_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
+	err |= cfc_check_trigger_arg_max(&cmd->chanlist_len, MAX_CHANLIST_LEN);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 
-	if (!cmd->chanlist_len) {
-		cmd->chanlist_len = 1;
-		err++;
-	}
-	if (cmd->chanlist_len > MAX_CHANLIST_LEN) {
-		cmd->chanlist_len = board->n_aichan;
-		err++;
-	}
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (!cmd->stop_arg) {
-			cmd->stop_arg = 1;
-			err++;
-		}
-	} else {		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	if (cmd->stop_src == TRIG_COUNT)
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+	else	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -639,6 +613,7 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev,
 static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	const struct pcl812_board *board = comedi_board(dev);
+	struct pcl812_private *devpriv = dev->private;
 	unsigned int divisor1 = 0, divisor2 = 0, i, dma_flags, bytes;
 	struct comedi_cmd *cmd = &s->async->cmd;
 
@@ -789,6 +764,7 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
 	char err = 1;
 	unsigned int mask, timeout;
 	struct comedi_device *dev = d;
+	struct pcl812_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[0];
 	unsigned int next_chan;
 
@@ -862,6 +838,7 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
 				  struct comedi_subdevice *s, short *ptr,
 				  unsigned int bufptr, unsigned int len)
 {
+	struct pcl812_private *devpriv = dev->private;
 	unsigned int i;
 
 	s->async->events = 0;
@@ -892,6 +869,7 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
 static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct pcl812_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[0];
 	unsigned long dma_flags;
 	int len, bufptr;
@@ -938,6 +916,7 @@ static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d)
 static irqreturn_t interrupt_pcl812(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct pcl812_private *devpriv = dev->private;
 
 	if (!dev->attached) {
 		comedi_error(dev, "spurious interrupt");
@@ -954,6 +933,7 @@ static irqreturn_t interrupt_pcl812(int irq, void *d)
 */
 static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct pcl812_private *devpriv = dev->private;
 	unsigned long flags;
 	unsigned int top1, top2, i;
 
@@ -1002,6 +982,7 @@ static void setup_range_channel(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				unsigned int rangechan, char wait)
 {
+	struct pcl812_private *devpriv = dev->private;
 	unsigned char chan_reg = CR_CHAN(rangechan);	/*  normal board */
 							/*  gain index */
 	unsigned char gain_reg = CR_RANGE(rangechan) +
@@ -1063,8 +1044,9 @@ static void start_pacer(struct comedi_device *dev, int mode,
 static void free_resources(struct comedi_device *dev)
 {
 	const struct pcl812_board *board = comedi_board(dev);
+	struct pcl812_private *devpriv = dev->private;
 
-	if (dev->private) {
+	if (devpriv) {
 		if (devpriv->dmabuf[0])
 			free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
 		if (devpriv->dmabuf[1])
@@ -1084,6 +1066,8 @@ static void free_resources(struct comedi_device *dev)
 static int pcl812_ai_cancel(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
+	struct pcl812_private *devpriv = dev->private;
+
 	if (devpriv->ai_dma)
 		disable_dma(devpriv->dma);
 	outb(0, dev->iobase + PCL812_CLRINT);	/* clear INT request */
@@ -1100,6 +1084,7 @@ static int pcl812_ai_cancel(struct comedi_device *dev,
 static void pcl812_reset(struct comedi_device *dev)
 {
 	const struct pcl812_board *board = comedi_board(dev);
+	struct pcl812_private *devpriv = dev->private;
 
 	outb(0, dev->iobase + PCL812_MUX);
 	outb(0 + devpriv->range_correction, dev->iobase + PCL812_GAIN);
@@ -1135,6 +1120,7 @@ static void pcl812_reset(struct comedi_device *dev)
 static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct pcl812_board *board = comedi_board(dev);
+	struct pcl812_private *devpriv;
 	int ret, subdev;
 	unsigned long iobase;
 	unsigned int irq;
@@ -1153,11 +1139,12 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	}
 	dev->iobase = iobase;
 
-	ret = alloc_private(dev, sizeof(struct pcl812_private));
-	if (ret < 0) {
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv) {
 		free_resources(dev);
-		return ret;	/* Can't alloc mem */
+		return -ENOMEM;
 	}
+	dev->private = devpriv;
 
 	dev->board_name = board->name;
 
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index 0822de0..f625fda 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -126,8 +126,6 @@ struct pcl816_board {
 	int i8254_osc_base;	/*  1/frequency of on board oscilator in ns */
 };
 
-#define devpriv ((struct pcl816_private *)dev->private)
-
 #ifdef unused
 static int RTC_lock;	/* RTC lock */
 static int RTC_timer_lock;	/* RTC int lock */
@@ -259,6 +257,7 @@ static int pcl816_ai_insn_read(struct comedi_device *dev,
 static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct pcl816_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[0];
 	int low, hi;
 	int timeout = 50;	/* wait max 50us */
@@ -315,6 +314,7 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
 				  struct comedi_subdevice *s, short *ptr,
 				  unsigned int bufptr, unsigned int len)
 {
+	struct pcl816_private *devpriv = dev->private;
 	int i;
 
 	s->async->events = 0;
@@ -350,6 +350,7 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
 static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct pcl816_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[0];
 	int len, bufptr, this_dma_buf;
 	unsigned long dma_flags;
@@ -398,6 +399,8 @@ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d)
 static irqreturn_t interrupt_pcl816(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct pcl816_private *devpriv = dev->private;
+
 	DPRINTK("<I>");
 
 	if (!dev->attached) {
@@ -481,43 +484,23 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev,
 		return 2;
 
 
-	/* step 3: make sure arguments are trivially compatible */
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->scan_begin_arg != 0) {
-		cmd->scan_begin_arg = 0;
-		err++;
-	}
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < board->ai_ns_min) {
-			cmd->convert_arg = board->ai_ns_min;
-			err++;
-		}
-	} else {		/* TRIG_EXT */
-		if (cmd->convert_arg != 0) {
-			cmd->convert_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (!cmd->stop_arg) {
-			cmd->stop_arg = 1;
-			err++;
-		}
-	} else {		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	if (cmd->convert_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+						 board->ai_ns_min);
+	else	/* TRIG_EXT */
+		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+	if (cmd->stop_src == TRIG_COUNT)
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+	else	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -554,6 +537,7 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev,
 static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	const struct pcl816_board *board = comedi_board(dev);
+	struct pcl816_private *devpriv = dev->private;
 	unsigned int divisor1 = 0, divisor2 = 0, dma_flags, bytes, dmairq;
 	struct comedi_cmd *cmd = &s->async->cmd;
 	unsigned int seglen;
@@ -682,6 +666,7 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct pcl816_private *devpriv = dev->private;
 	unsigned long flags;
 	unsigned int top1, top2, i;
 
@@ -727,6 +712,8 @@ static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 static int pcl816_ai_cancel(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
+	struct pcl816_private *devpriv = dev->private;
+
 /* DEBUG(printk("pcl816_ai_cancel()\n");) */
 
 	if (devpriv->irq_blocked > 0) {
@@ -932,6 +919,7 @@ setup_channel_list(struct comedi_device *dev,
 		   struct comedi_subdevice *s, unsigned int *chanlist,
 		   unsigned int seglen)
 {
+	struct pcl816_private *devpriv = dev->private;
 	unsigned int i;
 
 	devpriv->ai_act_chanlist_len = seglen;
@@ -991,6 +979,7 @@ static int set_rtc_irq_bit(unsigned char bit)
 static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct pcl816_board *board = comedi_board(dev);
+	struct pcl816_private *devpriv;
 	int ret;
 	unsigned long iobase;
 	unsigned int irq, dma;
@@ -1015,9 +1004,10 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		return -EIO;
 	}
 
-	ret = alloc_private(dev, sizeof(struct pcl816_private));
-	if (ret < 0)
-		return ret;	/* Can't alloc mem */
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	dev->board_name = board->name;
 
@@ -1216,6 +1206,7 @@ case COMEDI_SUBD_DO:
 static void pcl816_detach(struct comedi_device *dev)
 {
 	const struct pcl816_board *board = comedi_board(dev);
+	struct pcl816_private *devpriv = dev->private;
 
 	if (dev->private) {
 		pcl816_ai_cancel(dev, devpriv->sub_ai);
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index d4b0859..06127a5 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -326,8 +326,6 @@ static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0
 	0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
 };
 
-#define devpriv ((struct pcl818_private *)dev->private)
-
 /*
 ==============================================================================
 */
@@ -406,6 +404,7 @@ static int pcl818_ao_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct pcl818_private *devpriv = dev->private;
 	int n;
 	int chan = CR_CHAN(insn->chanspec);
 
@@ -419,6 +418,7 @@ static int pcl818_ao_insn_write(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
 {
+	struct pcl818_private *devpriv = dev->private;
 	int n;
 	int chan = CR_CHAN(insn->chanspec);
 
@@ -478,6 +478,7 @@ static int pcl818_do_insn_bits(struct comedi_device *dev,
 static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct pcl818_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[0];
 	int low;
 	int timeout = 50;	/* wait max 50us */
@@ -537,6 +538,7 @@ conv_finish:
 static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct pcl818_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[0];
 	int i, len, bufptr;
 	unsigned long flags;
@@ -616,6 +618,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
 static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct pcl818_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[0];
 	unsigned long tmp;
 	unsigned int top1, top2, i, bufptr;
@@ -721,6 +724,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
 static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct pcl818_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[0];
 	int i, len, lo;
 
@@ -795,6 +799,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
 static irqreturn_t interrupt_pcl818(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct pcl818_private *devpriv = dev->private;
 
 	if (!dev->attached) {
 		comedi_error(dev, "premature interrupt");
@@ -861,6 +866,7 @@ static irqreturn_t interrupt_pcl818(int irq, void *d)
 static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev,
 				    struct comedi_subdevice *s)
 {
+	struct pcl818_private *devpriv = dev->private;
 	unsigned int flags;
 	unsigned int bytes;
 
@@ -902,6 +908,7 @@ static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev,
 static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device *dev,
 				    struct comedi_subdevice *s)
 {
+	struct pcl818_private *devpriv = dev->private;
 	unsigned int flags;
 	short *pole;
 
@@ -943,6 +950,7 @@ static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device *dev,
 static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
 			      struct comedi_subdevice *s)
 {
+	struct pcl818_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
 	int divisor1 = 0, divisor2 = 0;
 	unsigned int seglen;
@@ -1063,6 +1071,7 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
 static int pcl818_ao_mode13(int mode, struct comedi_device *dev,
 			    struct comedi_subdevice *s, comedi_trig * it)
 {
+	struct pcl818_private *devpriv = dev->private;
 	int divisor1 = 0, divisor2 = 0;
 
 	if (!dev->irq) {
@@ -1222,6 +1231,7 @@ static void setup_channel_list(struct comedi_device *dev,
 			       unsigned int *chanlist, unsigned int n_chan,
 			       unsigned int seglen)
 {
+	struct pcl818_private *devpriv = dev->private;
 	int i;
 
 	devpriv->act_chanlist_len = seglen;
@@ -1259,6 +1269,7 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 		      struct comedi_cmd *cmd)
 {
 	const struct pcl818_board *board = comedi_board(dev);
+	struct pcl818_private *devpriv = dev->private;
 	int err = 0;
 	int tmp, divisor1 = 0, divisor2 = 0;
 
@@ -1283,45 +1294,23 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
-	if (cmd->scan_begin_arg != 0) {
-		cmd->scan_begin_arg = 0;
-		err++;
-	}
+	if (cmd->convert_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+						 board->ns_min);
+	else	/* TRIG_EXT */
+		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < board->ns_min) {
-			cmd->convert_arg = board->ns_min;
-			err++;
-		}
-	} else {		/* TRIG_EXT */
-		if (cmd->convert_arg != 0) {
-			cmd->convert_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (!cmd->stop_arg) {
-			cmd->stop_arg = 1;
-			err++;
-		}
-	} else {		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	if (cmd->stop_src == TRIG_COUNT)
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+	else	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -1358,6 +1347,7 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 */
 static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct pcl818_private *devpriv = dev->private;
 	struct comedi_cmd *cmd = &s->async->cmd;
 	int retval;
 
@@ -1397,6 +1387,8 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 static int pcl818_ai_cancel(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
+	struct pcl818_private *devpriv = dev->private;
+
 	if (devpriv->irq_blocked > 0) {
 		dev_dbg(dev->class_dev, "pcl818_ai_cancel()\n");
 		devpriv->irq_was_now_closed = 1;
@@ -1482,6 +1474,7 @@ static int pcl818_check(unsigned long iobase)
 static void pcl818_reset(struct comedi_device *dev)
 {
 	const struct pcl818_board *board = comedi_board(dev);
+	struct pcl818_private *devpriv = dev->private;
 
 	if (devpriv->usefifo) {	/*  FIFO shutdown */
 		outb(0, dev->iobase + PCL818_FI_INTCLR);
@@ -1552,6 +1545,7 @@ static int set_rtc_irq_bit(unsigned char bit)
 static void rtc_dropped_irq(unsigned long data)
 {
 	struct comedi_device *dev = (void *)data;
+	struct pcl818_private *devpriv = dev->private;
 	unsigned long flags, tmp;
 
 	switch (devpriv->int818_mode) {
@@ -1601,6 +1595,7 @@ static int rtc_setfreq_irq(int freq)
 static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct pcl818_board *board = comedi_board(dev);
+	struct pcl818_private *devpriv;
 	int ret;
 	unsigned long iobase;
 	unsigned int irq;
@@ -1608,9 +1603,10 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	unsigned long pages;
 	struct comedi_subdevice *s;
 
-	ret = alloc_private(dev, sizeof(struct pcl818_private));
-	if (ret < 0)
-		return ret;	/* Can't alloc mem */
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	/* claim our I/O space */
 	iobase = it->options[0];
@@ -1892,7 +1888,9 @@ no_dma:
 
 static void pcl818_detach(struct comedi_device *dev)
 {
-	if (dev->private) {
+	struct pcl818_private *devpriv = dev->private;
+
+	if (devpriv) {
 		pcl818_ai_cancel(dev, devpriv->sub_ai);
 		pcl818_reset(dev);
 		if (devpriv->dma)
diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
index 4102547..5f062df 100644
--- a/drivers/staging/comedi/drivers/pcm3724.c
+++ b/drivers/staging/comedi/drivers/pcm3724.c
@@ -62,14 +62,6 @@ Copy/pasted/hacked from pcm724.c
 #define CR_A_MODE(a)	((a)<<5)
 #define CR_CW		0x80
 
-struct pcm3724_board {
-	const char *name;	/*  driver name */
-	int dio;		/*  num of DIO */
-	int numofports;		/*  num of 8255 subdevices */
-	unsigned int IRQbits;	/*  allowed interrupts */
-	unsigned int io_range;	/*  len of IO space */
-};
-
 /* used to track configured dios */
 struct priv_pcm3724 {
 	int dio_1;
@@ -156,13 +148,12 @@ static void do_3724_config(struct comedi_device *dev,
 static void enable_chan(struct comedi_device *dev, struct comedi_subdevice *s,
 			int chanspec)
 {
+	struct priv_pcm3724 *priv = dev->private;
 	struct comedi_subdevice *s_dio1 = &dev->subdevices[0];
 	unsigned int mask;
 	int gatecfg;
-	struct priv_pcm3724 *priv;
 
 	gatecfg = 0;
-	priv = dev->private;
 
 	mask = 1 << CR_CHAN(chanspec);
 	if (s == s_dio1)
@@ -233,36 +224,33 @@ static int subdev_3724_insn_config(struct comedi_device *dev,
 static int pcm3724_attach(struct comedi_device *dev,
 			  struct comedi_devconfig *it)
 {
-	const struct pcm3724_board *board = comedi_board(dev);
+	struct priv_pcm3724 *priv;
 	struct comedi_subdevice *s;
 	unsigned long iobase;
 	unsigned int iorange;
-	int ret, i, n_subdevices;
+	int ret, i;
+
+	dev->board_name = dev->driver->driver_name;
 
 	iobase = it->options[0];
-	iorange = board->io_range;
+	iorange = PCM3724_SIZE;
 
-	ret = alloc_private(dev, sizeof(struct priv_pcm3724));
-	if (ret < 0)
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
 		return -ENOMEM;
-
-	((struct priv_pcm3724 *)(dev->private))->dio_1 = 0;
-	((struct priv_pcm3724 *)(dev->private))->dio_2 = 0;
+	dev->private = priv;
 
 	printk(KERN_INFO "comedi%d: pcm3724: board=%s, 0x%03lx ", dev->minor,
-	       board->name, iobase);
+	       dev->board_name, iobase);
 	if (!iobase || !request_region(iobase, iorange, "pcm3724")) {
 		printk("I/O port conflict\n");
 		return -EIO;
 	}
 
 	dev->iobase = iobase;
-	dev->board_name = board->name;
 	printk(KERN_INFO "\n");
 
-	n_subdevices = board->numofports;
-
-	ret = comedi_alloc_subdevices(dev, n_subdevices);
+	ret = comedi_alloc_subdevices(dev, 2);
 	if (ret)
 		return ret;
 
@@ -277,7 +265,6 @@ static int pcm3724_attach(struct comedi_device *dev,
 
 static void pcm3724_detach(struct comedi_device *dev)
 {
-	const struct pcm3724_board *board = comedi_board(dev);
 	struct comedi_subdevice *s;
 	int i;
 
@@ -288,21 +275,14 @@ static void pcm3724_detach(struct comedi_device *dev)
 		}
 	}
 	if (dev->iobase)
-		release_region(dev->iobase, board->io_range);
+		release_region(dev->iobase, PCM3724_SIZE);
 }
 
-static const struct pcm3724_board boardtypes[] = {
-	{ "pcm3724", 48, 2, 0x00fc, PCM3724_SIZE, },
-};
-
 static struct comedi_driver pcm3724_driver = {
 	.driver_name	= "pcm3724",
 	.module		= THIS_MODULE,
 	.attach		= pcm3724_attach,
 	.detach		= pcm3724_detach,
-	.board_name	= &boardtypes[0].name,
-	.num_names	= ARRAY_SIZE(boardtypes),
-	.offset		= sizeof(struct pcm3724_board),
 };
 module_comedi_driver(pcm3724_driver);
 
diff --git a/drivers/staging/comedi/drivers/pcm_common.c b/drivers/staging/comedi/drivers/pcm_common.c
index 85ee05e..8a718ae 100644
--- a/drivers/staging/comedi/drivers/pcm_common.c
+++ b/drivers/staging/comedi/drivers/pcm_common.c
@@ -29,41 +29,19 @@ int comedi_pcm_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	/* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
-
-	/* cmd->scan_begin_src == TRIG_EXT */
-	if (cmd->scan_begin_arg != 0) {
-		cmd->scan_begin_arg = 0;
-		err++;
-	}
-
-	/* cmd->convert_src == TRIG_NOW */
-	if (cmd->convert_arg != 0) {
-		cmd->convert_arg = 0;
-		err++;
-	}
-
-	/* cmd->scan_end_src == TRIG_COUNT */
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	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, cmd->chanlist_len);
 
 	switch (cmd->stop_src) {
 	case TRIG_COUNT:
 		/* any count allowed */
 		break;
 	case TRIG_NONE:
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 		break;
 	default:
 		break;
diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
index 5efeb92..13e8421 100644
--- a/drivers/staging/comedi/drivers/pcmad.c
+++ b/drivers/staging/comedi/drivers/pcmad.c
@@ -62,7 +62,6 @@ struct pcmad_priv_struct {
 	int differential;
 	int twos_comp;
 };
-#define devpriv ((struct pcmad_priv_struct *)dev->private)
 
 #define TIMEOUT	100
 
@@ -71,6 +70,7 @@ static int pcmad_ai_insn_read(struct comedi_device *dev,
 			      struct comedi_insn *insn, unsigned int *data)
 {
 	const struct pcmad_board_struct *board = comedi_board(dev);
+	struct pcmad_priv_struct *devpriv = dev->private;
 	int i;
 	int chan;
 	int n;
@@ -104,6 +104,7 @@ static int pcmad_ai_insn_read(struct comedi_device *dev,
 static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct pcmad_board_struct *board = comedi_board(dev);
+	struct pcmad_priv_struct *devpriv;
 	int ret;
 	struct comedi_subdevice *s;
 	unsigned long iobase;
@@ -121,9 +122,10 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	ret = alloc_private(dev, sizeof(struct pcmad_priv_struct));
-	if (ret < 0)
-		return ret;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	dev->board_name = board->name;
 
diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c
index 28af8f6..0882daf 100644
--- a/drivers/staging/comedi/drivers/pcmda12.c
+++ b/drivers/staging/comedi/drivers/pcmda12.c
@@ -64,13 +64,6 @@ Configuration Options:
 #define MSB_PORT(chan) (LSB_PORT(chan)+1)
 #define BITS 12
 
-/*
- * Bords
- */
-struct pcmda12_board {
-	const char *name;
-};
-
 /* note these have no effect and are merely here for reference..
    these are configured by jumpering the board! */
 static const struct comedi_lrange pcmda12_ranges = {
@@ -86,8 +79,6 @@ struct pcmda12_private {
 	int simultaneous_xfer_mode;
 };
 
-#define devpriv ((struct pcmda12_private *)(dev->private))
-
 static void zero_chans(struct comedi_device *dev)
 {				/* sets up an
 				   ASIC chip to defaults */
@@ -104,6 +95,7 @@ static void zero_chans(struct comedi_device *dev)
 static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 		    struct comedi_insn *insn, unsigned int *data)
 {
+	struct pcmda12_private *devpriv = dev->private;
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 
@@ -146,6 +138,7 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 		    struct comedi_insn *insn, unsigned int *data)
 {
+	struct pcmda12_private *devpriv = dev->private;
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 
@@ -162,7 +155,7 @@ static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int pcmda12_attach(struct comedi_device *dev,
 			  struct comedi_devconfig *it)
 {
-	const struct pcmda12_board *board = comedi_board(dev);
+	struct pcmda12_private *devpriv;
 	struct comedi_subdevice *s;
 	unsigned long iobase;
 	int ret;
@@ -178,16 +171,12 @@ static int pcmda12_attach(struct comedi_device *dev,
 	}
 	dev->iobase = iobase;
 
-	dev->board_name = board->name;
+	dev->board_name = dev->driver->driver_name;
 
-/*
- * Allocate the private structure area.  alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
-	if (alloc_private(dev, sizeof(struct pcmda12_private)) < 0) {
-		printk(KERN_ERR "cannot allocate private data structure\n");
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
-	}
+	dev->private = devpriv;
 
 	devpriv->simultaneous_xfer_mode = it->options[1];
 
@@ -218,20 +207,11 @@ static void pcmda12_detach(struct comedi_device *dev)
 		release_region(dev->iobase, IOSIZE);
 }
 
-static const struct pcmda12_board pcmda12_boards[] = {
-	{
-		.name	= "pcmda12",
-	},
-};
-
 static struct comedi_driver pcmda12_driver = {
 	.driver_name	= "pcmda12",
 	.module		= THIS_MODULE,
 	.attach		= pcmda12_attach,
 	.detach		= pcmda12_detach,
-	.board_name	= &pcmda12_boards[0].name,
-	.offset		= sizeof(struct pcmda12_board),
-	.num_names	= ARRAY_SIZE(pcmda12_boards),
 };
 module_comedi_driver(pcmda12_driver);
 
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
index a10bf0a..7522bfb 100644
--- a/drivers/staging/comedi/drivers/pcmmio.c
+++ b/drivers/staging/comedi/drivers/pcmmio.c
@@ -145,35 +145,6 @@ Configuration Options:
 #define PAGE_ENAB 2
 #define PAGE_INT_ID 3
 
-/*
- * 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.
- */
-struct pcmmio_board {
-	const char *name;
-	const int dio_num_asics;
-	const int dio_num_ports;
-	const int total_iosize;
-	const int ai_bits;
-	const int ao_bits;
-	const int n_ai_chans;
-	const int n_ao_chans;
-	const struct comedi_lrange *ai_range_table, *ao_range_table;
-	int (*ai_rinsn) (struct comedi_device *dev,
-			struct comedi_subdevice *s,
-			struct comedi_insn *insn,
-			unsigned int *data);
-	int (*ao_rinsn) (struct comedi_device *dev,
-			struct comedi_subdevice *s,
-			struct comedi_insn *insn,
-			unsigned int *data);
-	int (*ao_winsn) (struct comedi_device *dev,
-			struct comedi_subdevice *s,
-			struct comedi_insn *insn,
-			unsigned int *data);
-};
-
 static const struct comedi_lrange ranges_ai = {
 	4, {RANGE(-5., 5.), RANGE(-10., 10.), RANGE(0., 5.), RANGE(0., 10.)}
 };
@@ -258,11 +229,6 @@ struct pcmmio_private {
 	struct pcmmio_subdev_private *sprivs;
 };
 
-/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct pcmmio_private *)dev->private)
 #define subpriv ((struct pcmmio_subdev_private *)s->private)
 
 /* DIO devices are slightly special.  Although it is possible to
@@ -416,9 +382,9 @@ static int pcmmio_dio_insn_config(struct comedi_device *dev,
 
 static void switch_page(struct comedi_device *dev, int asic, int page)
 {
-	const struct pcmmio_board *board = comedi_board(dev);
+	struct pcmmio_private *devpriv = dev->private;
 
-	if (asic < 0 || asic >= board->dio_num_asics)
+	if (asic < 0 || asic >= 1)
 		return;		/* paranoia */
 	if (page < 0 || page >= NUM_PAGES)
 		return;		/* more paranoia */
@@ -434,10 +400,10 @@ static void switch_page(struct comedi_device *dev, int asic, int page)
 static void init_asics(struct comedi_device *dev)
 {				/* sets up an
 				   ASIC chip to defaults */
-	const struct pcmmio_board *board = comedi_board(dev);
+	struct pcmmio_private *devpriv = dev->private;
 	int asic;
 
-	for (asic = 0; asic < board->dio_num_asics; ++asic) {
+	for (asic = 0; asic < 1; ++asic) {
 		int port, page;
 		unsigned long baseaddr = devpriv->asics[asic].iobase;
 
@@ -472,9 +438,9 @@ static void init_asics(struct comedi_device *dev)
 #ifdef notused
 static void lock_port(struct comedi_device *dev, int asic, int port)
 {
-	const struct pcmmio_board *board = comedi_board(dev);
+	struct pcmmio_private *devpriv = dev->private;
 
-	if (asic < 0 || asic >= board->dio_num_asics)
+	if (asic < 0 || asic >= 1)
 		return;		/* paranoia */
 	if (port < 0 || port >= PORTS_PER_ASIC)
 		return;		/* more paranoia */
@@ -488,9 +454,9 @@ static void lock_port(struct comedi_device *dev, int asic, int port)
 
 static void unlock_port(struct comedi_device *dev, int asic, int port)
 {
-	const struct pcmmio_board *board = comedi_board(dev);
+	struct pcmmio_private *devpriv = dev->private;
 
-	if (asic < 0 || asic >= board->dio_num_asics)
+	if (asic < 0 || asic >= 1)
 		return;		/* paranoia */
 	if (port < 0 || port >= PORTS_PER_ASIC)
 		return;		/* more paranoia */
@@ -504,6 +470,7 @@ static void unlock_port(struct comedi_device *dev, int asic, int port)
 static void pcmmio_stop_intr(struct comedi_device *dev,
 			     struct comedi_subdevice *s)
 {
+	struct pcmmio_private *devpriv = dev->private;
 	int nports, firstport, asic, port;
 
 	asic = subpriv->dio.intr.asic;
@@ -526,6 +493,7 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d)
 {
 	int asic, got1 = 0;
 	struct comedi_device *dev = (struct comedi_device *)d;
+	struct pcmmio_private *devpriv = dev->private;
 	int i;
 
 	for (asic = 0; asic < MAX_ASICS; ++asic) {
@@ -685,6 +653,8 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d)
 static int pcmmio_start_intr(struct comedi_device *dev,
 			     struct comedi_subdevice *s)
 {
+	struct pcmmio_private *devpriv = dev->private;
+
 	if (!subpriv->dio.intr.continuous && subpriv->dio.intr.stop_count == 0) {
 		/* An empty acquisition! */
 		s->async->events |= COMEDI_CB_EOA;
@@ -1012,7 +982,7 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 
 static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
-	const struct pcmmio_board *board = comedi_board(dev);
+	struct pcmmio_private *devpriv;
 	struct comedi_subdevice *s;
 	int sdev_no, chans_left, n_dio_subdevs, n_subdevs, port, asic,
 	    thisasic_chanct = 0;
@@ -1020,32 +990,25 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	unsigned int irq[MAX_ASICS];
 	int ret;
 
+	dev->board_name = dev->driver->driver_name;
+
 	iobase = it->options[0];
 	irq[0] = it->options[1];
 
 	printk(KERN_INFO "comedi%d: %s: io: %lx attaching...\n", dev->minor,
-			dev->driver->driver_name, iobase);
+			dev->board_name, iobase);
 
 	dev->iobase = iobase;
 
-	if (!iobase || !request_region(iobase,
-				       board->total_iosize,
-				       dev->driver->driver_name)) {
+	if (!iobase || !request_region(iobase, 32, dev->board_name)) {
 		printk(KERN_ERR "comedi%d: I/O port conflict\n", dev->minor);
 		return -EIO;
 	}
 
-	dev->board_name = board->name;
-
-/*
- * Allocate the private structure area.  alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
-	if (alloc_private(dev, sizeof(struct pcmmio_private)) < 0) {
-		printk(KERN_ERR "comedi%d: cannot allocate private data structure\n",
-				dev->minor);
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
-	}
+	dev->private = devpriv;
 
 	for (asic = 0; asic < MAX_ASICS; ++asic) {
 		devpriv->asics[asic].num = asic;
@@ -1059,7 +1022,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		spin_lock_init(&devpriv->asics[asic].spinlock);
 	}
 
-	chans_left = CHANS_PER_ASIC * board->dio_num_asics;
+	chans_left = CHANS_PER_ASIC * 1;
 	n_dio_subdevs = CALC_N_DIO_SUBDEVS(chans_left);
 	n_subdevs = n_dio_subdevs + 2;
 	devpriv->sprivs =
@@ -1078,13 +1041,13 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	/* First, AI */
 	s = &dev->subdevices[0];
 	s->private = &devpriv->sprivs[0];
-	s->maxdata = (1 << board->ai_bits) - 1;
-	s->range_table = board->ai_range_table;
+	s->maxdata = 0xffff;
+	s->range_table = &ranges_ai;
 	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
 	s->type = COMEDI_SUBD_AI;
-	s->n_chan = board->n_ai_chans;
+	s->n_chan = 16;
 	s->len_chanlist = s->n_chan;
-	s->insn_read = board->ai_rinsn;
+	s->insn_read = ai_rinsn;
 	subpriv->iobase = dev->iobase + 0;
 	/* initialize the resource enable register by clearing it */
 	outb(0, subpriv->iobase + 3);
@@ -1093,14 +1056,14 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	/* Next, AO */
 	s = &dev->subdevices[1];
 	s->private = &devpriv->sprivs[1];
-	s->maxdata = (1 << board->ao_bits) - 1;
-	s->range_table = board->ao_range_table;
+	s->maxdata = 0xffff;
+	s->range_table = &ranges_ao;
 	s->subdev_flags = SDF_READABLE;
 	s->type = COMEDI_SUBD_AO;
-	s->n_chan = board->n_ao_chans;
+	s->n_chan = 8;
 	s->len_chanlist = s->n_chan;
-	s->insn_read = board->ao_rinsn;
-	s->insn_write = board->ao_winsn;
+	s->insn_read = ao_rinsn;
+	s->insn_write = ao_winsn;
 	subpriv->iobase = dev->iobase + 8;
 	/* initialize the resource enable register by clearing it */
 	outb(0, subpriv->iobase + 3);
@@ -1180,7 +1143,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) {
 		if (irq[asic]
 		    && request_irq(irq[asic], interrupt_pcmmio,
-				   IRQF_SHARED, board->name, dev)) {
+				   IRQF_SHARED, dev->board_name, dev)) {
 			int i;
 			/* unroll the allocated irqs.. */
 			for (i = asic - 1; i >= 0; --i) {
@@ -1204,11 +1167,11 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 static void pcmmio_detach(struct comedi_device *dev)
 {
-	const struct pcmmio_board *board = comedi_board(dev);
+	struct pcmmio_private *devpriv = dev->private;
 	int i;
 
 	if (dev->iobase)
-		release_region(dev->iobase, board->total_iosize);
+		release_region(dev->iobase, 32);
 	for (i = 0; i < MAX_ASICS; ++i) {
 		if (devpriv && devpriv->asics[i].irq)
 			free_irq(devpriv->asics[i].irq, dev);
@@ -1217,32 +1180,11 @@ static void pcmmio_detach(struct comedi_device *dev)
 		kfree(devpriv->sprivs);
 }
 
-static const struct pcmmio_board pcmmio_boards[] = {
-	{
-		.name		= "pcmmio",
-		.dio_num_asics	= 1,
-		.dio_num_ports	= 6,
-		.total_iosize	= 32,
-		.ai_bits	= 16,
-		.ao_bits	= 16,
-		.n_ai_chans	= 16,
-		.n_ao_chans	= 8,
-		.ai_range_table	= &ranges_ai,
-		.ao_range_table	= &ranges_ao,
-		.ai_rinsn	= ai_rinsn,
-		.ao_rinsn	= ao_rinsn,
-		.ao_winsn	= ao_winsn
-	},
-};
-
 static struct comedi_driver pcmmio_driver = {
 	.driver_name	= "pcmmio",
 	.module		= THIS_MODULE,
 	.attach		= pcmmio_attach,
 	.detach		= pcmmio_detach,
-	.board_name	= &pcmmio_boards[0].name,
-	.offset		= sizeof(struct pcmmio_board),
-	.num_names	= ARRAY_SIZE(pcmmio_boards),
 };
 module_comedi_driver(pcmmio_driver);
 
diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
index 0e32119..31ea20c 100644
--- a/drivers/staging/comedi/drivers/pcmuio.c
+++ b/drivers/staging/comedi/drivers/pcmuio.c
@@ -194,11 +194,6 @@ struct pcmuio_private {
 	struct pcmuio_subdev_private *sprivs;
 };
 
-/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct pcmuio_private *)dev->private)
 #define subpriv ((struct pcmuio_subdev_private *)s->private)
 
 /* DIO devices are slightly special.  Although it is possible to
@@ -348,6 +343,7 @@ static int pcmuio_dio_insn_config(struct comedi_device *dev,
 static void switch_page(struct comedi_device *dev, int asic, int page)
 {
 	const struct pcmuio_board *board = comedi_board(dev);
+	struct pcmuio_private *devpriv = dev->private;
 
 	if (asic < 0 || asic >= board->num_asics)
 		return;		/* paranoia */
@@ -404,6 +400,7 @@ static void init_asics(struct comedi_device *dev)
 static void lock_port(struct comedi_device *dev, int asic, int port)
 {
 	const struct pcmuio_board *board = comedi_board(dev);
+	struct pcmuio_private *devpriv = dev->private;
 
 	if (asic < 0 || asic >= board->num_asics)
 		return;		/* paranoia */
@@ -419,6 +416,7 @@ static void lock_port(struct comedi_device *dev, int asic, int port)
 static void unlock_port(struct comedi_device *dev, int asic, int port)
 {
 	const struct pcmuio_board *board = comedi_board(dev);
+	struct pcmuio_private *devpriv = dev->private;
 
 	if (asic < 0 || asic >= board->num_asics)
 		return;		/* paranoia */
@@ -435,6 +433,7 @@ static void pcmuio_stop_intr(struct comedi_device *dev,
 			     struct comedi_subdevice *s)
 {
 	int nports, firstport, asic, port;
+	struct pcmuio_private *devpriv = dev->private;
 
 	asic = subpriv->intr.asic;
 	if (asic < 0)
@@ -456,6 +455,7 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d)
 {
 	int asic, got1 = 0;
 	struct comedi_device *dev = (struct comedi_device *)d;
+	struct pcmuio_private *devpriv = dev->private;
 	int i;
 
 	for (asic = 0; asic < MAX_ASICS; ++asic) {
@@ -607,6 +607,8 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d)
 static int pcmuio_start_intr(struct comedi_device *dev,
 			     struct comedi_subdevice *s)
 {
+	struct pcmuio_private *devpriv = dev->private;
+
 	if (!subpriv->intr.continuous && subpriv->intr.stop_count == 0) {
 		/* An empty acquisition! */
 		s->async->events |= COMEDI_CB_EOA;
@@ -748,6 +750,7 @@ pcmuio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct pcmuio_board *board = comedi_board(dev);
+	struct pcmuio_private *devpriv;
 	struct comedi_subdevice *s;
 	int sdev_no, chans_left, n_subdevs, port, asic, thisasic_chanct = 0;
 	unsigned long iobase;
@@ -772,15 +775,10 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 	dev->board_name = board->name;
 
-/*
- * Allocate the private structure area.  alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
-	if (alloc_private(dev, sizeof(struct pcmuio_private)) < 0) {
-		dev_warn(dev->class_dev,
-			 "cannot allocate private data structure\n");
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
-	}
+	dev->private = devpriv;
 
 	for (asic = 0; asic < MAX_ASICS; ++asic) {
 		devpriv->asics[asic].num = asic;
@@ -905,6 +903,7 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 static void pcmuio_detach(struct comedi_device *dev)
 {
 	const struct pcmuio_board *board = comedi_board(dev);
+	struct pcmuio_private *devpriv = dev->private;
 	int i;
 
 	if (dev->iobase)
diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
index 78dfe16..d7842c9 100644
--- a/drivers/staging/comedi/drivers/poc.c
+++ b/drivers/staging/comedi/drivers/poc.c
@@ -57,13 +57,18 @@ struct boarddef_struct {
 	const struct comedi_lrange *range;
 };
 
+struct poc_private {
+	unsigned int ao_readback[32];
+};
+
 static int readback_insn(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_insn *insn, unsigned int *data)
 {
+	struct poc_private *devpriv = dev->private;
 	int chan;
 
 	chan = CR_CHAN(insn->chanspec);
-	data[0] = ((unsigned int *)dev->private)[chan];
+	data[0] = devpriv->ao_readback[chan];
 
 	return 1;
 }
@@ -75,12 +80,13 @@ static int readback_insn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int dac02_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			  struct comedi_insn *insn, unsigned int *data)
 {
+	struct poc_private *devpriv = dev->private;
 	int temp;
 	int chan;
 	int output;
 
 	chan = CR_CHAN(insn->chanspec);
-	((unsigned int *)dev->private)[chan] = data[0];
+	devpriv->ao_readback[chan] = data[0];
 	output = data[0];
 #ifdef wrong
 	/*  convert to complementary binary if range is bipolar */
@@ -131,6 +137,7 @@ static int pcl734_insn_bits(struct comedi_device *dev,
 static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct boarddef_struct *board = comedi_board(dev);
+	struct poc_private *devpriv;
 	struct comedi_subdevice *s;
 	unsigned long iobase;
 	unsigned int iosize;
@@ -160,8 +167,10 @@ static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	if (alloc_private(dev, sizeof(unsigned int) * board->n_chan) < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
 
 	/* analog output subdevice */
 	s = &dev->subdevices[0];
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index 3e276f7..ef0cdaa 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -47,6 +47,8 @@ Status: works
 Devices: [Quatech] DAQP-208 (daqp), DAQP-308
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "../comedidev.h"
 #include <linux/semaphore.h>
 
@@ -195,8 +197,8 @@ static struct comedi_driver driver_daqp = {
 
 static void daqp_dump(struct comedi_device *dev)
 {
-	printk(KERN_INFO "DAQP: status %02x; aux status %02x\n",
-	       inb(dev->iobase + DAQP_STATUS), inb(dev->iobase + DAQP_AUX));
+	dev_info(dev->class_dev, "status %02x; aux status %02x\n",
+		 inb(dev->iobase + DAQP_STATUS), inb(dev->iobase + DAQP_AUX));
 }
 
 static void hex_dump(char *str, void *ptr, int len)
@@ -255,33 +257,29 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id)
 	int status;
 
 	if (local == NULL) {
-		printk(KERN_WARNING
-		       "daqp_interrupt(): irq %d for unknown device.\n", irq);
+		pr_warn("irq %d for unknown device.\n", irq);
 		return IRQ_NONE;
 	}
 
 	dev = local->dev;
 	if (dev == NULL) {
-		printk(KERN_WARNING "daqp_interrupt(): NULL comedi_device.\n");
+		pr_warn("NULL comedi_device.\n");
 		return IRQ_NONE;
 	}
 
 	if (!dev->attached) {
-		printk(KERN_WARNING
-		       "daqp_interrupt(): struct comedi_device not yet attached.\n");
+		pr_warn("struct comedi_device not yet attached.\n");
 		return IRQ_NONE;
 	}
 
 	s = local->s;
 	if (s == NULL) {
-		printk(KERN_WARNING
-		       "daqp_interrupt(): NULL comedi_subdevice.\n");
+		pr_warn("NULL comedi_subdevice.\n");
 		return IRQ_NONE;
 	}
 
 	if ((struct local_info_t *)s->private != local) {
-		printk(KERN_WARNING
-		       "daqp_interrupt(): invalid comedi_subdevice.\n");
+		pr_warn("invalid comedi_subdevice.\n");
 		return IRQ_NONE;
 	}
 
@@ -302,7 +300,7 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id)
 			if (status & DAQP_STATUS_DATA_LOST) {
 				s->async->events |=
 				    COMEDI_CB_EOA | COMEDI_CB_OVERFLOW;
-				printk("daqp: data lost\n");
+				dev_warn(dev->class_dev, "data lost\n");
 				daqp_ai_cancel(dev, s);
 				break;
 			}
@@ -331,8 +329,8 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id)
 		}
 
 		if (loop_limit <= 0) {
-			printk(KERN_WARNING
-			       "loop_limit reached in daqp_interrupt()\n");
+			dev_warn(dev->class_dev,
+				 "loop_limit reached in daqp_interrupt()\n");
 			daqp_ai_cancel(dev, s);
 			s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 		}
@@ -397,9 +395,11 @@ static int daqp_ai_insn_read(struct comedi_device *dev,
 	 */
 
 	while (--counter
-	       && (inb(dev->iobase + DAQP_STATUS) & DAQP_STATUS_EVENTS)) ;
+	       && (inb(dev->iobase + DAQP_STATUS) & DAQP_STATUS_EVENTS))
+		;
 	if (!counter) {
-		printk("daqp: couldn't clear interrupts in status register\n");
+		dev_err(dev->class_dev,
+			"couldn't clear interrupts in status register\n");
 		return -1;
 	}
 
@@ -482,19 +482,15 @@ static int daqp_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
+
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
 #define MAX_SPEED	10000	/* 100 kHz - in nanoseconds */
 
-	if (cmd->scan_begin_src == TRIG_TIMER
-	    && cmd->scan_begin_arg < MAX_SPEED) {
-		cmd->scan_begin_arg = MAX_SPEED;
-		err++;
-	}
+	if (cmd->scan_begin_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						 MAX_SPEED);
 
 	/* If both scan_begin and convert are both timer values, the only
 	 * way that can make sense is if the scan time is the number of
@@ -503,30 +499,18 @@ static int daqp_ai_cmdtest(struct comedi_device *dev,
 
 	if (cmd->scan_begin_src == TRIG_TIMER && cmd->convert_src == TRIG_TIMER
 	    && cmd->scan_begin_arg != cmd->convert_arg * cmd->scan_end_arg) {
-		err++;
+		err |= -EINVAL;
 	}
 
-	if (cmd->convert_src == TRIG_TIMER && cmd->convert_arg < MAX_SPEED) {
-		cmd->convert_arg = MAX_SPEED;
-		err++;
-	}
+	if (cmd->convert_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg, MAX_SPEED);
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (cmd->stop_arg > 0x00ffffff) {
-			cmd->stop_arg = 0x00ffffff;
-			err++;
-		}
-	} else {
-		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+	if (cmd->stop_src == TRIG_COUNT)
+		err |= cfc_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
+	else	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -734,10 +718,11 @@ static int daqp_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	 */
 	counter = 100;
 	while (--counter
-	       && (inb(dev->iobase + DAQP_STATUS) & DAQP_STATUS_EVENTS)) ;
+	       && (inb(dev->iobase + DAQP_STATUS) & DAQP_STATUS_EVENTS))
+		;
 	if (!counter) {
-		printk(KERN_ERR
-		       "daqp: couldn't clear interrupts in status register\n");
+		dev_err(dev->class_dev,
+			"couldn't clear interrupts in status register\n");
 		return -1;
 	}
 
@@ -824,8 +809,8 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	struct comedi_subdevice *s;
 
 	if (it->options[0] < 0 || it->options[0] >= MAX_DEV || !local) {
-		printk("comedi%d: No such daqp device %d\n",
-		       dev->minor, it->options[0]);
+		dev_err(dev->class_dev, "No such daqp device %d\n",
+			it->options[0]);
 		return -EIO;
 	}
 
@@ -852,8 +837,8 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	printk(KERN_INFO "comedi%d: attaching daqp%d (io 0x%04lx)\n",
-	       dev->minor, it->options[0], dev->iobase);
+	dev_info(dev->class_dev, "attaching daqp%d (io 0x%04lx)\n",
+		 it->options[0], dev->iobase);
 
 	s = &dev->subdevices[0];
 	dev->read_subdev = s;
@@ -958,7 +943,7 @@ static int daqp_cs_attach(struct pcmcia_device *link)
 		if (dev_table[i] == NULL)
 			break;
 	if (i == MAX_DEV) {
-		printk(KERN_NOTICE "daqp_cs: no devices available\n");
+		dev_notice(&link->dev, "no devices available\n");
 		return -ENODEV;
 	}
 
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
index 41d24b0..8d7c948 100644
--- a/drivers/staging/comedi/drivers/rtd520.c
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -107,14 +107,12 @@ Configuration options:
 #include "../comedidev.h"
 
 #include "comedi_fc.h"
-
-#define DRV_NAME "rtd520"
+#include "rtd520.h"
+#include "plx9080.h"
 
 /*======================================================================
   Driver specific stuff (tunable)
 ======================================================================*/
-/* Enable this to test the new DMA support. You may get hard lock ups */
-/*#define USE_DMA*/
 
 /* We really only need 2 buffers.  More than that means being much
    smarter about knowing which ones are full. */
@@ -147,20 +145,6 @@ Configuration options:
   Board specific stuff
 ======================================================================*/
 
-/* registers  */
-#define PCI_VENDOR_ID_RTD	0x1435
-/*
-  The board has three memory windows: las0, las1, and lcfg (the PCI chip)
-  Las1 has the data and can be burst DMAed 32bits at a time.
-*/
-#define LCFG_PCIINDEX	0
-/* PCI region 1 is a 256 byte IO space mapping.  Use??? */
-#define LAS0_PCIINDEX	2	/* PCI memory resources */
-#define LAS1_PCIINDEX	3
-#define LCFG_PCISIZE	0x100
-#define LAS0_PCISIZE	0x200
-#define LAS1_PCISIZE	0x10
-
 #define RTD_CLOCK_RATE	8000000	/* 8Mhz onboard clock */
 #define RTD_CLOCK_BASE	125	/* clock period in ns */
 
@@ -173,9 +157,6 @@ Configuration options:
 /* min speed when only 1 channel (no burst counter) */
 #define RTD_MIN_SPEED_1	5000000	/* 200Hz, in nanoseconds */
 
-#include "rtd520.h"
-#include "plx9080.h"
-
 /* Setup continuous ring of 1/2 FIFO transfers.  See RTD manual p91 */
 #define DMA_MODE_BITS (\
 		       PLX_LOCAL_BUS_16_WIDE_BITS \
@@ -270,30 +251,24 @@ static const struct comedi_lrange rtd_ao_range = {
 struct rtdBoard {
 	const char *name;
 	int device_id;
-	int aiChans;
-	int aiBits;
-	int aiMaxGain;
 	int range10Start;	/* start of +-10V range */
 	int rangeUniStart;	/* start of +10V range */
+	const struct comedi_lrange *ai_range;
 };
 
 static const struct rtdBoard rtd520Boards[] = {
 	{
 		.name		= "DM7520",
 		.device_id	= 0x7520,
-		.aiChans	= 16,
-		.aiBits		= 12,
-		.aiMaxGain	= 32,
 		.range10Start	= 6,
 		.rangeUniStart	= 12,
+		.ai_range	= &rtd_ai_7520_range,
 	}, {
 		.name		= "PCI4520",
 		.device_id	= 0x4520,
-		.aiChans	= 16,
-		.aiBits		= 12,
-		.aiMaxGain	= 128,
 		.range10Start	= 8,
 		.rangeUniStart	= 16,
+		.ai_range	= &rtd_ai_4520_range,
 	},
 };
 
@@ -307,7 +282,6 @@ struct rtdPrivate {
 	void __iomem *las1;
 	void __iomem *lcfg;
 
-	unsigned long intCount;	/* interrupt count */
 	long aiCount;		/* total transfer size (samples) */
 	int transCount;		/* # to transfer data. 0->1/2FIFO */
 	int flags;		/* flag event modes */
@@ -328,21 +302,6 @@ struct rtdPrivate {
 	u16 intClearMask;	/* interrupt clear mask */
 	u8 utcCtrl[4];		/* crtl mode for 3 utc + read back */
 	u8 dioStatus;		/* could be read back (dio0Ctrl) */
-#ifdef USE_DMA
-	/*
-	 * Always DMA 1/2 FIFO.  Buffer (dmaBuff?) is (at least) twice that
-	 * size.  After transferring, interrupt processes 1/2 FIFO and
-	 * passes to comedi
-	 */
-	s16 dma0Offset;		/* current processing offset (0, 1/2) */
-	uint16_t *dma0Buff[DMA_CHAIN_COUNT];	/* DMA buffers (for ADC) */
-	dma_addr_t dma0BuffPhysAddr[DMA_CHAIN_COUNT];	/* physical addresses */
-	struct plx_dma_desc *dma0Chain;	/* DMA descriptor ring for dmaBuff */
-	dma_addr_t dma0ChainPhysAddr;	/* physical addresses */
-	/* shadow registers */
-	u8 dma0Control;
-	u8 dma1Control;
-#endif				/* USE_DMA */
 	unsigned fifoLen;
 };
 
@@ -365,9 +324,9 @@ struct rtdPrivate {
   Sets the original period to be the true value.
   Note: you have to check if the value is larger than the counter range!
 */
-static int rtd_ns_to_timer_base(unsigned int *nanosec,	/* desired period (in ns) */
+static int rtd_ns_to_timer_base(unsigned int *nanosec,
 				int round_mode, int base)
-{				/* clock period (in ns) */
+{
 	int divider;
 
 	switch (round_mode) {
@@ -420,18 +379,19 @@ static unsigned short rtdConvertChanGain(struct comedi_device *dev,
 	r |= chan & 0xf;
 
 	/* Note: we also setup the channel list bipolar flag array */
-	if (range < thisboard->range10Start) {	/* first batch are +-5 */
-		r |= 0x000;	/* +-5 range */
-		r |= (range & 0x7) << 4;	/* gain */
+	if (range < thisboard->range10Start) {
+		/* +-5 range */
+		r |= 0x000;
+		r |= (range & 0x7) << 4;
 		CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex);
-	} else if (range < thisboard->rangeUniStart) {	/* second batch are +-10 */
-		r |= 0x100;	/* +-10 range */
-		/* gain */
+	} else if (range < thisboard->rangeUniStart) {
+		/* +-10 range */
+		r |= 0x100;
 		r |= ((range - thisboard->range10Start) & 0x7) << 4;
 		CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex);
-	} else {		/* last batch is +10 */
-		r |= 0x200;	/* +10 range */
-		/* gain */
+	} else {
+		/* +10 range */
+		r |= 0x200;
 		r |= ((range - thisboard->rangeUniStart) & 0x7) << 4;
 		CHAN_ARRAY_CLEAR(devpriv->chanBipolar, chanIndex);
 	}
@@ -507,15 +467,14 @@ static int rtd520_probe_fifo_depth(struct comedi_device *dev)
 		}
 	}
 	if (i == limit) {
-		printk(KERN_INFO "\ncomedi: %s: failed to probe fifo size.\n",
-		       DRV_NAME);
+		dev_info(dev->class_dev, "failed to probe fifo size.\n");
 		return -EIO;
 	}
 	writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
 	if (fifo_size != 0x400 && fifo_size != 0x2000) {
-		printk
-		    (KERN_INFO "\ncomedi: %s: unexpected fifo size of %i, expected 1024 or 8192.\n",
-		     DRV_NAME, fifo_size);
+		dev_info(dev->class_dev,
+			 "unexpected fifo size of %i, expected 1024 or 8192.\n",
+			 fifo_size);
 		return -EIO;
 	}
 	return fifo_size;
@@ -558,12 +517,8 @@ static int rtd_ai_rinsn(struct comedi_device *dev,
 				break;
 			WAIT_QUIETLY;
 		}
-		if (ii >= RTD_ADC_TIMEOUT) {
-			DPRINTK
-			    ("rtd520: Error: ADC never finished! FifoStatus=0x%x\n",
-			     stat ^ 0x6666);
+		if (ii >= RTD_ADC_TIMEOUT)
 			return -ETIMEDOUT;
-		}
 
 		/* read data */
 		d = readw(devpriv->las1 + LAS1_ADC_FIFO);
@@ -600,15 +555,8 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s,
 			d = readw(devpriv->las1 + LAS1_ADC_FIFO);
 			continue;
 		}
-#if 0
-		if (!(readl(devpriv->las0 + LAS0_ADC) & FS_ADC_NOT_EMPTY)) {
-			DPRINTK("comedi: READ OOPS on %d of %d\n", ii + 1,
-				count);
-			break;
-		}
-#endif
-		d = readw(devpriv->las1 + LAS1_ADC_FIFO);
 
+		d = readw(devpriv->las1 + LAS1_ADC_FIFO);
 		d = d >> 3;	/* low 3 bits are marker lines */
 		if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
 			/* convert to comedi unsigned data */
@@ -656,125 +604,6 @@ static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s)
 	return 0;
 }
 
-#ifdef USE_DMA
-/*
-  Terminate a DMA transfer and wait for everything to quiet down
-*/
-void abort_dma(struct comedi_device *dev, unsigned int channel)
-{				/* DMA channel 0, 1 */
-	struct rtdPrivate *devpriv = dev->private;
-	unsigned long dma_cs_addr;	/* the control/status register */
-	uint8_t status;
-	unsigned int ii;
-	/* unsigned long flags; */
-
-	dma_cs_addr = (unsigned long)devpriv->lcfg
-	    + ((channel == 0) ? LCFG_DMACSR0 : LCFG_DMACSR1);
-
-	/*  spinlock for plx dma control/status reg */
-	/* spin_lock_irqsave( &dev->spinlock, flags ); */
-
-	/*  abort dma transfer if necessary */
-	status = readb(dma_cs_addr);
-	if ((status & PLX_DMA_EN_BIT) == 0) {	/* not enabled (Error?) */
-		DPRINTK("rtd520: AbortDma on non-active channel %d (0x%x)\n",
-			channel, status);
-		goto abortDmaExit;
-	}
-
-	/* wait to make sure done bit is zero (needed?) */
-	for (ii = 0; (status & PLX_DMA_DONE_BIT) && ii < RTD_DMA_TIMEOUT; ii++) {
-		WAIT_QUIETLY;
-		status = readb(dma_cs_addr);
-	}
-	if (status & PLX_DMA_DONE_BIT) {
-		printk("rtd520: Timeout waiting for dma %i done clear\n",
-		       channel);
-		goto abortDmaExit;
-	}
-
-	/* disable channel (required) */
-	writeb(0, dma_cs_addr);
-	udelay(1);		/* needed?? */
-	/* set abort bit for channel */
-	writeb(PLX_DMA_ABORT_BIT, dma_cs_addr);
-
-	/*  wait for dma done bit to be set */
-	status = readb(dma_cs_addr);
-	for (ii = 0;
-	     (status & PLX_DMA_DONE_BIT) == 0 && ii < RTD_DMA_TIMEOUT; ii++) {
-		status = readb(dma_cs_addr);
-		WAIT_QUIETLY;
-	}
-	if ((status & PLX_DMA_DONE_BIT) == 0) {
-		printk("rtd520: Timeout waiting for dma %i done set\n",
-		       channel);
-	}
-
-abortDmaExit:
-	/* spin_unlock_irqrestore( &dev->spinlock, flags ); */
-}
-
-/*
-  Process what is in the DMA transfer buffer and pass to comedi
-  Note: this is not re-entrant
-*/
-static int ai_process_dma(struct comedi_device *dev, struct comedi_subdevice *s)
-{
-	struct rtdPrivate *devpriv = dev->private;
-	int ii, n;
-	s16 *dp;
-
-	if (devpriv->aiCount == 0)	/* transfer already complete */
-		return 0;
-
-	dp = devpriv->dma0Buff[devpriv->dma0Offset];
-	for (ii = 0; ii < devpriv->fifoLen / 2;) {	/* convert samples */
-		short sample;
-
-		if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
-			sample = (*dp >> 3) + 2048;	/* convert to comedi unsigned data */
-		else
-			sample = *dp >> 3;	/* low 3 bits are marker lines */
-
-		*dp++ = sample;	/* put processed value back */
-
-		if (++s->async->cur_chan >= s->async->cmd.chanlist_len)
-			s->async->cur_chan = 0;
-
-		++ii;		/* number ready to transfer */
-		if (devpriv->aiCount > 0) {	/* < 0, means read forever */
-			if (--devpriv->aiCount == 0) {	/* done */
-				/*DPRINTK ("rtd520: Final %d samples\n", ii); */
-				break;
-			}
-		}
-	}
-
-	/* now pass the whole array to the comedi buffer */
-	dp = devpriv->dma0Buff[devpriv->dma0Offset];
-	n = comedi_buf_write_alloc(s->async, ii * sizeof(s16));
-	if (n < (ii * sizeof(s16))) {	/* any residual is an error */
-		DPRINTK("rtd520:ai_process_dma buffer overflow %d samples!\n",
-			ii - (n / sizeof(s16)));
-		s->async->events |= COMEDI_CB_ERROR;
-		return -1;
-	}
-	comedi_buf_memcpy_to(s->async, 0, dp, n);
-	comedi_buf_write_free(s->async, n);
-
-	/*
-	 * always at least 1 scan -- 1/2 FIFO is larger than our max scan list
-	 */
-	s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
-
-	if (++devpriv->dma0Offset >= DMA_CHAIN_COUNT) {	/* next buffer */
-		devpriv->dma0Offset = 0;
-	}
-	return 0;
-}
-#endif /* USE_DMA */
-
 /*
   Handle all rtd520 interrupts.
   Runs atomically and is never re-entered.
@@ -794,47 +623,10 @@ static irqreturn_t rtd_interrupt(int irq,	/* interrupt number (ignored) */
 	if (!dev->attached)
 		return IRQ_NONE;
 
-	devpriv->intCount++;	/* DEBUG statistics */
-
 	fifoStatus = readl(devpriv->las0 + LAS0_ADC);
 	/* check for FIFO full, this automatically halts the ADC! */
-	if (!(fifoStatus & FS_ADC_NOT_FULL)) {	/* 0 -> full */
-		DPRINTK("rtd520: FIFO full! fifo_status=0x%x\n", (fifoStatus ^ 0x6666) & 0x7777);	/* should be all 0s */
+	if (!(fifoStatus & FS_ADC_NOT_FULL))	/* 0 -> full */
 		goto abortTransfer;
-	}
-#ifdef USE_DMA
-	if (devpriv->flags & DMA0_ACTIVE) {	/* Check DMA */
-		u32 istatus = readl(devpriv->lcfg + LCFG_ITCSR);
-
-		if (istatus & ICS_DMA0_A) {
-			if (ai_process_dma(dev, s) < 0) {
-				DPRINTK
-				    ("rtd520: comedi read buffer overflow (DMA) with %ld to go!\n",
-				     devpriv->aiCount);
-				devpriv->dma0Control &= ~PLX_DMA_START_BIT;
-				devpriv->dma0Control |= PLX_CLEAR_DMA_INTR_BIT;
-				writeb(devpriv->dma0Control,
-					devpriv->lcfg + LCFG_DMACSR0);
-				goto abortTransfer;
-			}
-
-			/*DPRINTK ("rtd520: DMA transfer: %ld to go, istatus %x\n",
-			   devpriv->aiCount, istatus); */
-			devpriv->dma0Control &= ~PLX_DMA_START_BIT;
-			devpriv->dma0Control |= PLX_CLEAR_DMA_INTR_BIT;
-			writeb(devpriv->dma0Control,
-				devpriv->lcfg + LCFG_DMACSR0);
-			if (0 == devpriv->aiCount) {	/* counted down */
-				DPRINTK("rtd520: Samples Done (DMA).\n");
-				goto transferDone;
-			}
-			comedi_event(dev, s);
-		} else {
-			/*DPRINTK ("rtd520: No DMA ready: istatus %x\n", istatus); */
-		}
-	}
-	/* Fall through and check for other interrupt sources */
-#endif /* USE_DMA */
 
 	status = readw(devpriv->las0 + LAS0_IT);
 	/* if interrupt was not caused by our board, or handled above */
@@ -842,57 +634,38 @@ static irqreturn_t rtd_interrupt(int irq,	/* interrupt number (ignored) */
 		return IRQ_HANDLED;
 
 	if (status & IRQM_ADC_ABOUT_CNT) {	/* sample count -> read FIFO */
-		/* since the priority interrupt controller may have queued a sample
-		   counter interrupt, even though we have already finished,
-		   we must handle the possibility that there is no data here */
-		if (!(fifoStatus & FS_ADC_HEMPTY)) {	/* 0 -> 1/2 full */
-			/*DPRINTK("rtd520: Sample int, reading 1/2FIFO.  fifo_status 0x%x\n",
-			   (fifoStatus ^ 0x6666) & 0x7777); */
-			if (ai_read_n(dev, s, devpriv->fifoLen / 2) < 0) {
-				DPRINTK
-				    ("rtd520: comedi read buffer overflow (1/2FIFO) with %ld to go!\n",
-				     devpriv->aiCount);
+		/*
+		 * since the priority interrupt controller may have queued
+		 * a sample counter interrupt, even though we have already
+		 * finished, we must handle the possibility that there is
+		 * no data here
+		 */
+		if (!(fifoStatus & FS_ADC_HEMPTY)) {
+			/* FIFO half full */
+			if (ai_read_n(dev, s, devpriv->fifoLen / 2) < 0)
 				goto abortTransfer;
-			}
-			if (0 == devpriv->aiCount) {	/* counted down */
-				DPRINTK("rtd520: Samples Done (1/2). fifo_status was 0x%x\n", (fifoStatus ^ 0x6666) & 0x7777);	/* should be all 0s */
+
+			if (0 == devpriv->aiCount)
 				goto transferDone;
-			}
+
 			comedi_event(dev, s);
-		} else if (devpriv->transCount > 0) {	/* read often */
-			/*DPRINTK("rtd520: Sample int, reading %d  fifo_status 0x%x\n",
-			   devpriv->transCount, (fifoStatus ^ 0x6666) & 0x7777); */
-			if (fifoStatus & FS_ADC_NOT_EMPTY) {	/* 1 -> not empty */
-				if (ai_read_n(dev, s, devpriv->transCount) < 0) {
-					DPRINTK
-					    ("rtd520: comedi read buffer overflow (N) with %ld to go!\n",
-					     devpriv->aiCount);
+		} else if (devpriv->transCount > 0) {
+			if (fifoStatus & FS_ADC_NOT_EMPTY) {
+				/* FIFO not empty */
+				if (ai_read_n(dev, s, devpriv->transCount) < 0)
 					goto abortTransfer;
-				}
-				if (0 == devpriv->aiCount) {	/* counted down */
-					DPRINTK
-					    ("rtd520: Samples Done (N). fifo_status was 0x%x\n",
-					     (fifoStatus ^ 0x6666) & 0x7777);
+
+				if (0 == devpriv->aiCount)
 					goto transferDone;
-				}
+
 				comedi_event(dev, s);
 			}
-		} else {	/* wait for 1/2 FIFO (old) */
-			DPRINTK
-			    ("rtd520: Sample int.  Wait for 1/2. fifo_status 0x%x\n",
-			     (fifoStatus ^ 0x6666) & 0x7777);
 		}
-	} else {
-		DPRINTK("rtd520: unknown interrupt source!\n");
 	}
 
 	overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff;
-	if (overrun) {
-		DPRINTK
-		    ("rtd520: Interrupt overrun with %ld to go! over_status=0x%x\n",
-		     devpriv->aiCount, overrun);
+	if (overrun)
 		goto abortTransfer;
-	}
 
 	/* clear the interrupt */
 	devpriv->intClearMask = status;
@@ -913,23 +686,9 @@ transferDone:
 	writel(0, devpriv->las0 + LAS0_ADC_CONVERSION);
 	devpriv->intMask = 0;
 	writew(devpriv->intMask, devpriv->las0 + LAS0_IT);
-#ifdef USE_DMA
-	if (devpriv->flags & DMA0_ACTIVE) {
-		writel(readl(devpriv->lcfg + LCFG_ITCSR) & ~ICS_DMA0_E,
-			devpriv->lcfg + LCFG_ITCSR);
-		abort_dma(dev, 0);
-		devpriv->flags &= ~DMA0_ACTIVE;
-		/* if Using DMA, then we should have read everything by now */
-		if (devpriv->aiCount > 0) {
-			DPRINTK("rtd520: Lost DMA data! %ld remain\n",
-				devpriv->aiCount);
-		}
-	}
-#endif /* USE_DMA */
 
 	if (devpriv->aiCount > 0) {	/* there shouldn't be anything left */
 		fifoStatus = readl(devpriv->las0 + LAS0_ADC);
-		DPRINTK("rtd520: Finishing up. %ld remain, fifoStat=%x\n", devpriv->aiCount, (fifoStatus ^ 0x6666) & 0x7777);	/* should read all 0s */
 		ai_read_dregs(dev, s);	/* read anything left in FIFO */
 	}
 
@@ -944,25 +703,10 @@ transferDone:
 
 	fifoStatus = readl(devpriv->las0 + LAS0_ADC);
 	overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff;
-	DPRINTK
-	    ("rtd520: Acquisition complete. %ld ints, intStat=%x, overStat=%x\n",
-	     devpriv->intCount, status, overrun);
 
 	return IRQ_HANDLED;
 }
 
-#if 0
-/*
-  return the number of samples available
-*/
-static int rtd_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
-{
-	/* TODO: This needs to mask interrupts, read_dregs, and then re-enable */
-	/* Not sure what to do if DMA is active */
-	return s->async->buf_write_count - s->async->buf_read_count;
-}
-#endif
-
 /*
   cmdtest tests a particular command to see if it is valid.
   Using the cmdtest ioctl, a user can create a valid cmd
@@ -1001,103 +745,85 @@ static int rtd_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		/* Note: these are time periods, not actual rates */
 		if (1 == cmd->chanlist_len) {	/* no scanning */
-			if (cmd->scan_begin_arg < RTD_MAX_SPEED_1) {
-				cmd->scan_begin_arg = RTD_MAX_SPEED_1;
+			if (cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						      RTD_MAX_SPEED_1)) {
 				rtd_ns_to_timer(&cmd->scan_begin_arg,
 						TRIG_ROUND_UP);
-				err++;
+				err |= -EINVAL;
 			}
-			if (cmd->scan_begin_arg > RTD_MIN_SPEED_1) {
-				cmd->scan_begin_arg = RTD_MIN_SPEED_1;
+			if (cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
+						      RTD_MIN_SPEED_1)) {
 				rtd_ns_to_timer(&cmd->scan_begin_arg,
 						TRIG_ROUND_DOWN);
-				err++;
+				err |= -EINVAL;
 			}
 		} else {
-			if (cmd->scan_begin_arg < RTD_MAX_SPEED) {
-				cmd->scan_begin_arg = RTD_MAX_SPEED;
+			if (cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						      RTD_MAX_SPEED)) {
 				rtd_ns_to_timer(&cmd->scan_begin_arg,
 						TRIG_ROUND_UP);
-				err++;
+				err |= -EINVAL;
 			}
-			if (cmd->scan_begin_arg > RTD_MIN_SPEED) {
-				cmd->scan_begin_arg = RTD_MIN_SPEED;
+			if (cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
+						      RTD_MIN_SPEED)) {
 				rtd_ns_to_timer(&cmd->scan_begin_arg,
 						TRIG_ROUND_DOWN);
-				err++;
+				err |= -EINVAL;
 			}
 		}
 	} else {
 		/* external trigger */
 		/* should be level/edge, hi/lo specification here */
 		/* should specify multiple external triggers */
-		if (cmd->scan_begin_arg > 9) {
-			cmd->scan_begin_arg = 9;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9);
 	}
+
 	if (cmd->convert_src == TRIG_TIMER) {
 		if (1 == cmd->chanlist_len) {	/* no scanning */
-			if (cmd->convert_arg < RTD_MAX_SPEED_1) {
-				cmd->convert_arg = RTD_MAX_SPEED_1;
+			if (cfc_check_trigger_arg_min(&cmd->convert_arg,
+						      RTD_MAX_SPEED_1)) {
 				rtd_ns_to_timer(&cmd->convert_arg,
 						TRIG_ROUND_UP);
-				err++;
+				err |= -EINVAL;
 			}
-			if (cmd->convert_arg > RTD_MIN_SPEED_1) {
-				cmd->convert_arg = RTD_MIN_SPEED_1;
+			if (cfc_check_trigger_arg_max(&cmd->convert_arg,
+						      RTD_MIN_SPEED_1)) {
 				rtd_ns_to_timer(&cmd->convert_arg,
 						TRIG_ROUND_DOWN);
-				err++;
+				err |= -EINVAL;
 			}
 		} else {
-			if (cmd->convert_arg < RTD_MAX_SPEED) {
-				cmd->convert_arg = RTD_MAX_SPEED;
+			if (cfc_check_trigger_arg_min(&cmd->convert_arg,
+						      RTD_MAX_SPEED)) {
 				rtd_ns_to_timer(&cmd->convert_arg,
 						TRIG_ROUND_UP);
-				err++;
+				err |= -EINVAL;
 			}
-			if (cmd->convert_arg > RTD_MIN_SPEED) {
-				cmd->convert_arg = RTD_MIN_SPEED;
+			if (cfc_check_trigger_arg_max(&cmd->convert_arg,
+						      RTD_MIN_SPEED)) {
 				rtd_ns_to_timer(&cmd->convert_arg,
 						TRIG_ROUND_DOWN);
-				err++;
+				err |= -EINVAL;
 			}
 		}
 	} else {
 		/* external trigger */
 		/* see above */
-		if (cmd->convert_arg > 9) {
-			cmd->convert_arg = 9;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 9);
 	}
 
-#if 0
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-#endif
 	if (cmd->stop_src == TRIG_COUNT) {
 		/* TODO check for rounding error due to counter wrap */
-
 	} else {
 		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 	}
 
 	if (err)
@@ -1159,28 +885,8 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	writel(0, devpriv->las0 + LAS0_ADC_CONVERSION);
 	devpriv->intMask = 0;
 	writew(devpriv->intMask, devpriv->las0 + LAS0_IT);
-#ifdef USE_DMA
-	if (devpriv->flags & DMA0_ACTIVE) {	/* cancel anything running */
-		writel(readl(devpriv->lcfg + LCFG_ITCSR) & ~ICS_DMA0_E,
-			devpriv->lcfg + LCFG_ITCSR);
-		abort_dma(dev, 0);
-		devpriv->flags &= ~DMA0_ACTIVE;
-		if (readl(devpriv->lcfg + LCFG_ITCSR) & ICS_DMA0_A) {
-			devpriv->dma0Control = PLX_CLEAR_DMA_INTR_BIT;
-			writeb(devpriv->dma0Control,
-				devpriv->lcfg + LCFG_DMACSR0);
-		}
-	}
-	writel(0, devpriv->las0 + LAS0_DMA0_RESET);
-#endif /* USE_DMA */
 	writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
 	writel(0, devpriv->las0 + LAS0_OVERRUN);
-	devpriv->intCount = 0;
-
-	if (!dev->irq) {	/* we need interrupts for this */
-		DPRINTK("rtd520: ERROR! No interrupt available!\n");
-		return -ENXIO;
-	}
 
 	/* start configuration */
 	/* load channel list and reset CGT */
@@ -1188,7 +894,6 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 	/* setup the common case and override if needed */
 	if (cmd->chanlist_len > 1) {
-		/*DPRINTK ("rtd520: Multi channel setup\n"); */
 		/* pacer start source: SOFTWARE */
 		writel(0, devpriv->las0 + LAS0_PACER_START);
 		/* burst trigger source: PACER */
@@ -1196,7 +901,6 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		/* ADC conversion trigger source: BURST */
 		writel(2, devpriv->las0 + LAS0_ADC_CONVERSION);
 	} else {		/* single channel */
-		/*DPRINTK ("rtd520: single channel setup\n"); */
 		/* pacer start source: SOFTWARE */
 		writel(0, devpriv->las0 + LAS0_PACER_START);
 		/* ADC conversion trigger source: PACER */
@@ -1208,8 +912,11 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		/* scan_begin_arg is in nanoseconds */
 		/* find out how many samples to wait before transferring */
 		if (cmd->flags & TRIG_WAKE_EOS) {
-			/* this may generate un-sustainable interrupt rates */
-			/* the application is responsible for doing the right thing */
+			/*
+			 * this may generate un-sustainable interrupt rates
+			 * the application is responsible for doing the
+			 * right thing
+			 */
 			devpriv->transCount = cmd->chanlist_len;
 			devpriv->flags |= SEND_EOS;
 		} else {
@@ -1239,11 +946,6 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 			writel((devpriv->transCount - 1) & 0xffff,
 				devpriv->las0 + LAS0_ACNT);
 		}
-
-		DPRINTK
-		    ("rtd520: scanLen=%d transferCount=%d fifoLen=%d\n  scanTime(ns)=%d flags=0x%x\n",
-		     cmd->chanlist_len, devpriv->transCount, devpriv->fifoLen,
-		     cmd->scan_begin_arg, devpriv->flags);
 	} else {		/* unknown timing, just use 1/2 FIFO */
 		devpriv->transCount = 0;
 		devpriv->flags &= ~SEND_EOS;
@@ -1268,10 +970,6 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	case TRIG_NONE:	/* stop when cancel is called */
 		devpriv->aiCount = -1;	/* read forever */
 		break;
-
-	default:
-		DPRINTK("rtd520: Warning! ignoring stop_src mode %d\n",
-			cmd->stop_src);
 	}
 
 	/* Scan timing */
@@ -1280,7 +978,6 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		timer = rtd_ns_to_timer(&cmd->scan_begin_arg,
 					TRIG_ROUND_NEAREST);
 		/* set PACER clock */
-		/*DPRINTK ("rtd520: loading %d into pacer\n", timer); */
 		writel(timer & 0xffffff, devpriv->las0 + LAS0_PCLK);
 
 		break;
@@ -1289,20 +986,16 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		/* pacer start source: EXTERNAL */
 		writel(1, devpriv->las0 + LAS0_PACER_START);
 		break;
-
-	default:
-		DPRINTK("rtd520: Warning! ignoring scan_begin_src mode %d\n",
-			cmd->scan_begin_src);
 	}
 
 	/* Sample timing within a scan */
 	switch (cmd->convert_src) {
 	case TRIG_TIMER:	/* periodic */
-		if (cmd->chanlist_len > 1) {	/* only needed for multi-channel */
+		if (cmd->chanlist_len > 1) {
+			/* only needed for multi-channel */
 			timer = rtd_ns_to_timer(&cmd->convert_arg,
 						TRIG_ROUND_NEAREST);
 			/* setup BURST clock */
-			/*DPRINTK ("rtd520: loading %d into burst\n", timer); */
 			writel(timer & 0x3ff, devpriv->las0 + LAS0_BCLK);
 		}
 
@@ -1312,10 +1005,6 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 		/* burst trigger source: EXTERNAL */
 		writel(2, devpriv->las0 + LAS0_BURST_START);
 		break;
-
-	default:
-		DPRINTK("rtd520: Warning! ignoring convert_src mode %d\n",
-			cmd->convert_src);
 	}
 	/* end configuration */
 
@@ -1329,34 +1018,9 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 	if (devpriv->transCount > 0) {	/* transfer every N samples */
 		devpriv->intMask = IRQM_ADC_ABOUT_CNT;
 		writew(devpriv->intMask, devpriv->las0 + LAS0_IT);
-		DPRINTK("rtd520: Transferring every %d\n", devpriv->transCount);
 	} else {		/* 1/2 FIFO transfers */
-#ifdef USE_DMA
-		devpriv->flags |= DMA0_ACTIVE;
-
-		/* point to first transfer in ring */
-		devpriv->dma0Offset = 0;
-		writel(DMA_MODE_BITS, devpriv->lcfg + LCFG_DMAMODE0);
-		/* point to first block */
-		writel(devpriv->dma0Chain[DMA_CHAIN_COUNT - 1].next,
-			devpriv->lcfg + LCFG_DMADPR0);
-		writel(DMAS_ADFIFO_HALF_FULL, devpriv->las0 + LAS0_DMA0_SRC);
-		writel(readl(devpriv->lcfg + LCFG_ITCSR) | ICS_DMA0_E,
-			devpriv->lcfg + LCFG_ITCSR);
-		/* Must be 2 steps.  See PLX app note about "Starting a DMA transfer" */
-		devpriv->dma0Control = PLX_DMA_EN_BIT;
-		writeb(devpriv->dma0Control,
-			devpriv->lcfg + LCFG_DMACSR0);
-		devpriv->dma0Control |= PLX_DMA_START_BIT;
-		writeb(devpriv->dma0Control,
-			devpriv->lcfg + LCFG_DMACSR0);
-		DPRINTK("rtd520: Using DMA0 transfers. plxInt %x RtdInt %x\n",
-			readl(devpriv->lcfg + LCFG_ITCSR), devpriv->intMask);
-#else /* USE_DMA */
 		devpriv->intMask = IRQM_ADC_ABOUT_CNT;
 		writew(devpriv->intMask, devpriv->las0 + LAS0_IT);
-		DPRINTK("rtd520: Transferring every 1/2 FIFO\n");
-#endif /* USE_DMA */
 	}
 
 	/* BUG: start_src is ASSUMED to be TRIG_NOW */
@@ -1381,19 +1045,8 @@ static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 	devpriv->intMask = 0;
 	writew(devpriv->intMask, devpriv->las0 + LAS0_IT);
 	devpriv->aiCount = 0;	/* stop and don't transfer any more */
-#ifdef USE_DMA
-	if (devpriv->flags & DMA0_ACTIVE) {
-		writel(readl(devpriv->lcfg + LCFG_ITCSR) & ~ICS_DMA0_E,
-			devpriv->lcfg + LCFG_ITCSR);
-		abort_dma(dev, 0);
-		devpriv->flags &= ~DMA0_ACTIVE;
-	}
-#endif /* USE_DMA */
 	status = readw(devpriv->las0 + LAS0_IT);
 	overrun = readl(devpriv->las0 + LAS0_OVERRUN) & 0xffff;
-	DPRINTK
-	    ("rtd520: Acquisition canceled. %ld ints, intStat=%x, overStat=%x\n",
-	     devpriv->intCount, status, overrun);
 	return 0;
 }
 
@@ -1430,14 +1083,11 @@ static int rtd_ao_winsn(struct comedi_device *dev,
 			val = data[i] << 3;
 		}
 
-		DPRINTK
-		    ("comedi: rtd520 DAC chan=%d range=%d writing %d as 0x%x\n",
-		     chan, range, data[i], val);
-
 		/* a typical programming sequence */
 		writew(val, devpriv->las1 +
 			((chan == 0) ? LAS1_DAC1_FIFO : LAS1_DAC2_FIFO));
-		writew(0, devpriv->las0 + ((chan == 0) ? LAS0_DAC1 : LAS0_DAC2));
+		writew(0, devpriv->las0 +
+			((chan == 0) ? LAS0_DAC1 : LAS0_DAC2));
 
 		devpriv->aoValue[chan] = data[i];	/* save for read back */
 
@@ -1449,12 +1099,8 @@ static int rtd_ao_winsn(struct comedi_device *dev,
 				break;
 			WAIT_QUIETLY;
 		}
-		if (ii >= RTD_DAC_TIMEOUT) {
-			DPRINTK
-			    ("rtd520: Error: DAC never finished! FifoStatus=0x%x\n",
-			     stat ^ 0x6666);
+		if (ii >= RTD_DAC_TIMEOUT)
 			return -ETIMEDOUT;
-		}
 	}
 
 	/* return the number of samples read/written */
@@ -1507,8 +1153,6 @@ static int rtd_dio_insn_bits(struct comedi_device *dev,
 	 * input lines. */
 	data[1] = readw(devpriv->las0 + LAS0_DIO0) & 0xff;
 
-	/*DPRINTK("rtd520:port_0 wrote: 0x%x read: 0x%x\n", s->state, data[1]); */
-
 	return insn->n;
 }
 
@@ -1542,7 +1186,6 @@ static int rtd_dio_insn_config(struct comedi_device *dev,
 		return -EINVAL;
 	}
 
-	DPRINTK("rtd520: port_0_direction=0x%x (1 means out)\n", s->io_bits);
 	/* TODO support digital match interrupts and strobes */
 	devpriv->dioStatus = 0x01;	/* set direction */
 	writew(devpriv->dioStatus, devpriv->las0 + LAS0_DIO_STATUS);
@@ -1557,356 +1200,194 @@ static int rtd_dio_insn_config(struct comedi_device *dev,
 	return 1;
 }
 
-static struct pci_dev *rtd_find_pci(struct comedi_device *dev,
-				    struct comedi_devconfig *it)
+static void rtd_reset(struct comedi_device *dev)
+{
+	struct rtdPrivate *devpriv = dev->private;
+
+	writel(0, devpriv->las0 + LAS0_BOARD_RESET);
+	udelay(100);		/* needed? */
+	writel(0, devpriv->lcfg + LCFG_ITCSR);
+	devpriv->intMask = 0;
+	writew(devpriv->intMask, devpriv->las0 + LAS0_IT);
+	devpriv->intClearMask = ~0;
+	writew(devpriv->intClearMask, devpriv->las0 + LAS0_CLEAR);
+	readw(devpriv->las0 + LAS0_CLEAR);
+}
+
+/*
+ * initialize board, per RTD spec
+ * also, initialize shadow registers
+ */
+static void rtd_init_board(struct comedi_device *dev)
+{
+	struct rtdPrivate *devpriv = dev->private;
+
+	rtd_reset(dev);
+
+	writel(0, devpriv->las0 + LAS0_OVERRUN);
+	writel(0, devpriv->las0 + LAS0_CGT_CLEAR);
+	writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
+	writel(0, devpriv->las0 + LAS0_DAC1_RESET);
+	writel(0, devpriv->las0 + LAS0_DAC2_RESET);
+	/* clear digital IO fifo */
+	devpriv->dioStatus = 0;
+	writew(devpriv->dioStatus, devpriv->las0 + LAS0_DIO_STATUS);
+	devpriv->utcCtrl[0] = (0 << 6) | 0x30;
+	devpriv->utcCtrl[1] = (1 << 6) | 0x30;
+	devpriv->utcCtrl[2] = (2 << 6) | 0x30;
+	devpriv->utcCtrl[3] = (3 << 6) | 0x00;
+	writeb(devpriv->utcCtrl[0], devpriv->las0 + LAS0_UTC_CTRL);
+	writeb(devpriv->utcCtrl[1], devpriv->las0 + LAS0_UTC_CTRL);
+	writeb(devpriv->utcCtrl[2], devpriv->las0 + LAS0_UTC_CTRL);
+	writeb(devpriv->utcCtrl[3], devpriv->las0 + LAS0_UTC_CTRL);
+	/* TODO: set user out source ??? */
+}
+
+/* The RTD driver does this */
+static void rtd_pci_latency_quirk(struct comedi_device *dev,
+				  struct pci_dev *pcidev)
+{
+	unsigned char pci_latency;
+
+	pci_read_config_byte(pcidev, PCI_LATENCY_TIMER, &pci_latency);
+	if (pci_latency < 32) {
+		dev_info(dev->class_dev,
+			"PCI latency changed from %d to %d\n",
+			pci_latency, 32);
+		pci_write_config_byte(pcidev, PCI_LATENCY_TIMER, 32);
+	}
+}
+
+static const void *rtd_find_boardinfo(struct comedi_device *dev,
+				      struct pci_dev *pcidev)
 {
 	const struct rtdBoard *thisboard;
-	struct pci_dev *pcidev = NULL;
-	int bus = it->options[0];
-	int slot = it->options[1];
 	int i;
 
-	for_each_pci_dev(pcidev) {
-		if (pcidev->vendor != PCI_VENDOR_ID_RTD)
-			continue;
-		if (bus || slot) {
-			if (pcidev->bus->number != bus ||
-			    PCI_SLOT(pcidev->devfn) != slot)
-				continue;
-		}
-		for (i = 0; i < ARRAY_SIZE(rtd520Boards); i++) {
-			thisboard = &rtd520Boards[i];
-			if (pcidev->device == thisboard->device_id) {
-				dev->board_ptr = thisboard;
-				return pcidev;
-			}
-		}
+	for (i = 0; i < ARRAY_SIZE(rtd520Boards); i++) {
+		thisboard = &rtd520Boards[i];
+		if (pcidev->device == thisboard->device_id)
+			return thisboard;
 	}
-	dev_warn(dev->class_dev,
-		"no supported board found! (req. bus/slot: %d/%d)\n",
-		bus, slot);
 	return NULL;
 }
 
-static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{				/* board name and options flags */
+static int rtd_auto_attach(struct comedi_device *dev,
+				     unsigned long context_unused)
+{
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	const struct rtdBoard *thisboard;
 	struct rtdPrivate *devpriv;
-	struct pci_dev *pcidev;
 	struct comedi_subdevice *s;
-	resource_size_t pci_base;
 	int ret;
-#ifdef USE_DMA
-	int index;
-#endif
 
-	printk(KERN_INFO "comedi%d: rtd520 attaching.\n", dev->minor);
-
-#if defined(CONFIG_COMEDI_DEBUG) && defined(USE_DMA)
-	/* You can set this a load time: modprobe comedi comedi_debug=1 */
-	if (0 == comedi_debug)	/* force DMA debug printks */
-		comedi_debug = 1;
-#endif
+	thisboard = rtd_find_boardinfo(dev, pcidev);
+	if (!thisboard)
+		return -ENODEV;
+	dev->board_ptr = thisboard;
+	dev->board_name = thisboard->name;
 
-	/*
-	 * Allocate the private structure area.  alloc_private() is a
-	 * convenient macro defined in comedidev.h.
-	 */
-	if (alloc_private(dev, sizeof(struct rtdPrivate)) < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
-	devpriv = dev->private;
+	dev->private = devpriv;
 
-	pcidev = rtd_find_pci(dev, it);
-	if (!pcidev)
-		return -EIO;
-	comedi_set_hw_dev(dev, &pcidev->dev);
-	thisboard = comedi_board(dev);
-
-	dev->board_name = thisboard->name;
-
-	ret = comedi_pci_enable(pcidev, DRV_NAME);
-	if (ret < 0) {
-		printk(KERN_INFO "Failed to enable PCI device and request regions.\n");
+	ret = comedi_pci_enable(pcidev, dev->board_name);
+	if (ret)
 		return ret;
-	}
 	dev->iobase = 1;	/* the "detach" needs this */
 
-	/* Initialize the base addresses */
-	pci_base = pci_resource_start(pcidev, LAS0_PCIINDEX);
-	devpriv->las0 = ioremap_nocache(pci_base, LAS0_PCISIZE);
-	pci_base = pci_resource_start(pcidev, LAS1_PCIINDEX);
-	devpriv->las1 = ioremap_nocache(pci_base, LAS1_PCISIZE);
-	pci_base = pci_resource_start(pcidev, LCFG_PCIINDEX);
-	devpriv->lcfg = ioremap_nocache(pci_base, LCFG_PCISIZE);
+	devpriv->las0 = ioremap_nocache(pci_resource_start(pcidev, 2),
+					pci_resource_len(pcidev, 2));
+	devpriv->las1 = ioremap_nocache(pci_resource_start(pcidev, 3),
+					pci_resource_len(pcidev, 3));
+	devpriv->lcfg = ioremap_nocache(pci_resource_start(pcidev, 0),
+					pci_resource_len(pcidev, 0));
 	if (!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg)
 		return -ENOMEM;
 
-	{			/* The RTD driver does this */
-		unsigned char pci_latency;
-		u16 revision;
-		/*uint32_t epld_version; */
-
-		pci_read_config_word(pcidev, PCI_REVISION_ID,
-				     &revision);
-		DPRINTK("%s: PCI revision %d.\n", dev->board_name, revision);
-
-		pci_read_config_byte(pcidev,
-				     PCI_LATENCY_TIMER, &pci_latency);
-		if (pci_latency < 32) {
-			printk(KERN_INFO "%s: PCI latency changed from %d to %d\n",
-			       dev->board_name, pci_latency, 32);
-			pci_write_config_byte(pcidev,
-					      PCI_LATENCY_TIMER, 32);
-		} else {
-			DPRINTK("rtd520: PCI latency = %d\n", pci_latency);
-		}
+	rtd_pci_latency_quirk(dev, pcidev);
 
-		/*
-		 * Undocumented EPLD version (doesn't match RTD driver results)
-		 */
-		/*DPRINTK ("rtd520: Reading epld from %p\n",
-		   devpriv->las0+0);
-		   epld_version = readl (devpriv->las0+0);
-		   if ((epld_version & 0xF0) >> 4 == 0x0F) {
-		   DPRINTK("rtd520: pre-v8 EPLD. (%x)\n", epld_version);
-		   } else {
-		   DPRINTK("rtd520: EPLD version %x.\n", epld_version >> 4);
-		   } */
+	if (pcidev->irq) {
+		ret = request_irq(pcidev->irq, rtd_interrupt, IRQF_SHARED,
+				  dev->board_name, dev);
+		if (ret == 0)
+			dev->irq = pcidev->irq;
 	}
 
-	/* Show board configuration */
-	printk(KERN_INFO "%s:", dev->board_name);
-
 	ret = comedi_alloc_subdevices(dev, 4);
 	if (ret)
 		return ret;
 
 	s = &dev->subdevices[0];
-	dev->read_subdev = s;
 	/* analog input subdevice */
-	s->type = COMEDI_SUBD_AI;
-	s->subdev_flags =
-	    SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF | SDF_CMD_READ;
-	s->n_chan = thisboard->aiChans;
-	s->maxdata = (1 << thisboard->aiBits) - 1;
-	if (thisboard->aiMaxGain <= 32)
-		s->range_table = &rtd_ai_7520_range;
-	else
-		s->range_table = &rtd_ai_4520_range;
-
-	s->len_chanlist = RTD_MAX_CHANLIST;	/* devpriv->fifoLen */
-	s->insn_read = rtd_ai_rinsn;
-	s->do_cmd = rtd_ai_cmd;
-	s->do_cmdtest = rtd_ai_cmdtest;
-	s->cancel = rtd_ai_cancel;
-	/* s->poll = rtd_ai_poll; *//* not ready yet */
+	s->type		= COMEDI_SUBD_AI;
+	s->subdev_flags	= SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF;
+	s->n_chan	= 16;
+	s->maxdata	= 0x0fff;
+	s->range_table	= thisboard->ai_range;
+	s->len_chanlist	= RTD_MAX_CHANLIST;
+	s->insn_read	= rtd_ai_rinsn;
+	if (dev->irq) {
+		dev->read_subdev = s;
+		s->subdev_flags	|= SDF_CMD_READ;
+		s->do_cmd	= rtd_ai_cmd;
+		s->do_cmdtest	= rtd_ai_cmdtest;
+		s->cancel	= rtd_ai_cancel;
+	}
 
 	s = &dev->subdevices[1];
 	/* analog output subdevice */
-	s->type = COMEDI_SUBD_AO;
-	s->subdev_flags = SDF_WRITABLE;
-	s->n_chan = 2;
-	s->maxdata = (1 << thisboard->aiBits) - 1;
-	s->range_table = &rtd_ao_range;
-	s->insn_write = rtd_ao_winsn;
-	s->insn_read = rtd_ao_rinsn;
+	s->type		= COMEDI_SUBD_AO;
+	s->subdev_flags	= SDF_WRITABLE;
+	s->n_chan	= 2;
+	s->maxdata	= 0x0fff;
+	s->range_table	= &rtd_ao_range;
+	s->insn_write	= rtd_ao_winsn;
+	s->insn_read	= rtd_ao_rinsn;
 
 	s = &dev->subdevices[2];
 	/* digital i/o subdevice */
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+	s->type		= COMEDI_SUBD_DIO;
+	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
 	/* we only support port 0 right now.  Ignoring port 1 and user IO */
-	s->n_chan = 8;
-	s->maxdata = 1;
-	s->range_table = &range_digital;
-	s->insn_bits = rtd_dio_insn_bits;
-	s->insn_config = rtd_dio_insn_config;
+	s->n_chan	= 8;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= rtd_dio_insn_bits;
+	s->insn_config	= rtd_dio_insn_config;
 
 	/* timer/counter subdevices (not currently supported) */
 	s = &dev->subdevices[3];
-	s->type = COMEDI_SUBD_COUNTER;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-	s->n_chan = 3;
-	s->maxdata = 0xffff;
+	s->type		= COMEDI_SUBD_COUNTER;
+	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
+	s->n_chan	= 3;
+	s->maxdata	= 0xffff;
 
-	/* initialize board, per RTD spec */
-	/* also, initialize shadow registers */
-	writel(0, devpriv->las0 + LAS0_BOARD_RESET);
-	udelay(100);		/* needed? */
-	writel(0, devpriv->lcfg + LCFG_ITCSR);
-	devpriv->intMask = 0;
-	writew(devpriv->intMask, devpriv->las0 + LAS0_IT);
-	devpriv->intClearMask = ~0;
-	writew(devpriv->intClearMask, devpriv->las0 + LAS0_CLEAR);
-	readw(devpriv->las0 + LAS0_CLEAR);
-	writel(0, devpriv->las0 + LAS0_OVERRUN);
-	writel(0, devpriv->las0 + LAS0_CGT_CLEAR);
-	writel(0, devpriv->las0 + LAS0_ADC_FIFO_CLEAR);
-	writel(0, devpriv->las0 + LAS0_DAC1_RESET);
-	writel(0, devpriv->las0 + LAS0_DAC2_RESET);
-	/* clear digital IO fifo */
-	devpriv->dioStatus = 0;
-	writew(devpriv->dioStatus, devpriv->las0 + LAS0_DIO_STATUS);
-	devpriv->utcCtrl[0] = (0 << 6) | 0x30;
-	devpriv->utcCtrl[1] = (1 << 6) | 0x30;
-	devpriv->utcCtrl[2] = (2 << 6) | 0x30;
-	devpriv->utcCtrl[3] = (3 << 6) | 0x00;
-	writeb(devpriv->utcCtrl[0], devpriv->las0 + LAS0_UTC_CTRL);
-	writeb(devpriv->utcCtrl[1], devpriv->las0 + LAS0_UTC_CTRL);
-	writeb(devpriv->utcCtrl[2], devpriv->las0 + LAS0_UTC_CTRL);
-	writeb(devpriv->utcCtrl[3], devpriv->las0 + LAS0_UTC_CTRL);
-	/* TODO: set user out source ??? */
-
-	/* check if our interrupt is available and get it */
-	ret = request_irq(pcidev->irq, rtd_interrupt,
-			  IRQF_SHARED, DRV_NAME, dev);
-
-	if (ret < 0) {
-		printk("Could not get interrupt! (%u)\n",
-		       pcidev->irq);
-		return ret;
-	}
-	dev->irq = pcidev->irq;
-	printk(KERN_INFO "( irq=%u )", dev->irq);
+	rtd_init_board(dev);
 
 	ret = rtd520_probe_fifo_depth(dev);
 	if (ret < 0)
 		return ret;
-
 	devpriv->fifoLen = ret;
-	printk("( fifoLen=%d )", devpriv->fifoLen);
-
-#ifdef USE_DMA
-	if (dev->irq > 0) {
-		printk("( DMA buff=%d )\n", DMA_CHAIN_COUNT);
-		/*
-		 * The PLX9080 has 2 DMA controllers, but there could be
-		 * 4 sources: ADC, digital, DAC1, and DAC2.  Since only the
-		 * ADC supports cmd mode right now, this isn't an issue (yet)
-		 */
-		devpriv->dma0Offset = 0;
-
-		for (index = 0; index < DMA_CHAIN_COUNT; index++) {
-			devpriv->dma0Buff[index] =
-			    pci_alloc_consistent(pcidev,
-						 sizeof(u16) *
-						 devpriv->fifoLen / 2,
-						 &devpriv->
-						 dma0BuffPhysAddr[index]);
-			if (devpriv->dma0Buff[index] == NULL) {
-				ret = -ENOMEM;
-				goto rtd_attach_die_error;
-			}
-			/*DPRINTK ("buff[%d] @ %p virtual, %x PCI\n",
-			   index,
-			   devpriv->dma0Buff[index],
-			   devpriv->dma0BuffPhysAddr[index]); */
-		}
-
-		/*
-		 * setup DMA descriptor ring (use cpu_to_le32 for byte
-		 * ordering?)
-		 */
-		devpriv->dma0Chain =
-		    pci_alloc_consistent(pcidev,
-					 sizeof(struct plx_dma_desc) *
-					 DMA_CHAIN_COUNT,
-					 &devpriv->dma0ChainPhysAddr);
-		for (index = 0; index < DMA_CHAIN_COUNT; index++) {
-			devpriv->dma0Chain[index].pci_start_addr =
-			    devpriv->dma0BuffPhysAddr[index];
-			devpriv->dma0Chain[index].local_start_addr =
-			    DMALADDR_ADC;
-			devpriv->dma0Chain[index].transfer_size =
-			    sizeof(u16) * devpriv->fifoLen / 2;
-			devpriv->dma0Chain[index].next =
-			    (devpriv->dma0ChainPhysAddr + ((index +
-							    1) %
-							   (DMA_CHAIN_COUNT))
-			     * sizeof(devpriv->dma0Chain[0]))
-			    | DMA_TRANSFER_BITS;
-			/*DPRINTK ("ring[%d] @%lx PCI: %x, local: %x, N: 0x%x, next: %x\n",
-			   index,
-			   ((long)devpriv->dma0ChainPhysAddr
-			   + (index * sizeof(devpriv->dma0Chain[0]))),
-			   devpriv->dma0Chain[index].pci_start_addr,
-			   devpriv->dma0Chain[index].local_start_addr,
-			   devpriv->dma0Chain[index].transfer_size,
-			   devpriv->dma0Chain[index].next); */
-		}
-
-		if (devpriv->dma0Chain == NULL) {
-			ret = -ENOMEM;
-			goto rtd_attach_die_error;
-		}
-
-		writel(DMA_MODE_BITS, devpriv->lcfg + LCFG_DMAMODE0);
-		/* set DMA trigger source */
-		writel(DMAS_ADFIFO_HALF_FULL, devpriv->las0 + LAS0_DMA0_SRC);
-	} else {
-		printk(KERN_INFO "( no IRQ->no DMA )");
-	}
-#endif /* USE_DMA */
 
 	if (dev->irq)
 		writel(ICS_PIE | ICS_PLIE, devpriv->lcfg + LCFG_ITCSR);
 
-	printk("\ncomedi%d: rtd520 driver attached.\n", dev->minor);
+	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
 
-	return 1;
+	return 0;
 }
 
 static void rtd_detach(struct comedi_device *dev)
 {
 	struct rtdPrivate *devpriv = dev->private;
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-#ifdef USE_DMA
-	int index;
-#endif
 
 	if (devpriv) {
 		/* Shut down any board ops by resetting it */
-#ifdef USE_DMA
-		if (devpriv->lcfg) {
-			devpriv->dma0Control = 0;
-			devpriv->dma1Control = 0;
-			writeb(devpriv->dma0Control,
-				devpriv->lcfg + LCFG_DMACSR0);
-			writeb(devpriv->dma1Control,
-				devpriv->lcfg + LCFG_DMACSR1);
-			writel(ICS_PIE | ICS_PLIE, devpriv->lcfg + LCFG_ITCSR);
-		}
-#endif /* USE_DMA */
-		if (devpriv->las0) {
-			writel(0, devpriv->las0 + LAS0_BOARD_RESET);
-			devpriv->intMask = 0;
-			writew(devpriv->intMask, devpriv->las0 + LAS0_IT);
-			devpriv->intClearMask = ~0;
-			writew(devpriv->intClearMask,
-				devpriv->las0 + LAS0_CLEAR);
-			readw(devpriv->las0 + LAS0_CLEAR);
-		}
-#ifdef USE_DMA
-		/* release DMA */
-		for (index = 0; index < DMA_CHAIN_COUNT; index++) {
-			if (NULL != devpriv->dma0Buff[index]) {
-				pci_free_consistent(pcidev,
-						    sizeof(u16) *
-						    devpriv->fifoLen / 2,
-						    devpriv->dma0Buff[index],
-						    devpriv->
-						    dma0BuffPhysAddr[index]);
-				devpriv->dma0Buff[index] = NULL;
-			}
-		}
-		if (NULL != devpriv->dma0Chain) {
-			pci_free_consistent(pcidev,
-					    sizeof(struct plx_dma_desc) *
-					    DMA_CHAIN_COUNT, devpriv->dma0Chain,
-					    devpriv->dma0ChainPhysAddr);
-			devpriv->dma0Chain = NULL;
-		}
-#endif /* USE_DMA */
+		if (devpriv->las0 && devpriv->lcfg)
+			rtd_reset(dev);
 		if (dev->irq) {
 			writel(readl(devpriv->lcfg + LCFG_ITCSR) &
 				~(ICS_PLIE | ICS_DMA0_E | ICS_DMA1_E),
@@ -1923,24 +1404,23 @@ static void rtd_detach(struct comedi_device *dev)
 	if (pcidev) {
 		if (dev->iobase)
 			comedi_pci_disable(pcidev);
-		pci_dev_put(pcidev);
 	}
 }
 
 static struct comedi_driver rtd520_driver = {
 	.driver_name	= "rtd520",
 	.module		= THIS_MODULE,
-	.attach		= rtd_attach,
+	.auto_attach	= rtd_auto_attach,
 	.detach		= rtd_detach,
 };
 
-static int __devinit rtd520_pci_probe(struct pci_dev *dev,
+static int rtd520_pci_probe(struct pci_dev *dev,
 				      const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &rtd520_driver);
 }
 
-static void __devexit rtd520_pci_remove(struct pci_dev *dev)
+static void rtd520_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -1956,7 +1436,7 @@ static struct pci_driver rtd520_pci_driver = {
 	.name		= "rtd520",
 	.id_table	= rtd520_pci_table,
 	.probe		= rtd520_pci_probe,
-	.remove		= __devexit_p(rtd520_pci_remove),
+	.remove		= rtd520_pci_remove,
 };
 module_comedi_pci_driver(rtd520_driver, rtd520_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/rtd520.h b/drivers/staging/comedi/drivers/rtd520.h
index a3ec259..25188a5 100644
--- a/drivers/staging/comedi/drivers/rtd520.h
+++ b/drivers/staging/comedi/drivers/rtd520.h
@@ -26,163 +26,132 @@
 */
 
 /*
-  LAS0 Runtime Area
-  Local Address Space 0 Offset		Read Function	Write Function
-*/
-#define LAS0_SPARE_00    0x0000	/*  -                               - */
-#define LAS0_SPARE_04    0x0004	/*  -                               - */
-#define LAS0_USER_IO     0x0008	/*  Read User Inputs                Write User Outputs */
-#define LAS0_SPARE_0C    0x000C	/*  -                               - */
-#define LAS0_ADC         0x0010	/*  Read FIFO Status                Software A/D Start */
-#define LAS0_DAC1        0x0014	/*  -                               Software D/A1 Update */
-#define LAS0_DAC2        0x0018	/*  -                               Software D/A2 Update */
-#define LAS0_SPARE_1C    0x001C	/*  -                               - */
-#define LAS0_SPARE_20    0x0020	/*  -                               - */
-#define LAS0_DAC         0x0024	/*  -                               Software Simultaneous D/A1 and D/A2 Update */
-#define LAS0_PACER       0x0028	/*  Software Pacer Start            Software Pacer Stop */
-#define LAS0_TIMER       0x002C	/*  Read Timer Counters Status      HDIN Software Trigger */
-#define LAS0_IT          0x0030	/*  Read Interrupt Status           Write Interrupt Enable Mask Register */
-#define LAS0_CLEAR       0x0034	/*  Clear ITs set by Clear Mask     Set Interrupt Clear Mask */
-#define LAS0_OVERRUN     0x0038	/*  Read pending interrupts         Clear Overrun Register */
-#define LAS0_SPARE_3C    0x003C	/*  -                               - */
+ * Local Address Space 0 Offsets
+ */
+#define LAS0_USER_IO		0x0008	/* User I/O */
+#define LAS0_ADC		0x0010	/* FIFO Status/Software A/D Start */
+#define LAS0_DAC1		0x0014	/* Software D/A1 Update (w) */
+#define LAS0_DAC2		0x0018	/* Software D/A2 Update (w) */
+#define LAS0_DAC		0x0024	/* Software Simultaneous Update (w) */
+#define LAS0_PACER		0x0028	/* Software Pacer Start/Stop */
+#define LAS0_TIMER		0x002c	/* Timer Status/HDIN Software Trig. */
+#define LAS0_IT			0x0030	/* Interrupt Status/Enable */
+#define LAS0_CLEAR		0x0034	/* Clear/Set Interrupt Clear Mask */
+#define LAS0_OVERRUN		0x0038	/* Pending interrupts/Clear Overrun */
+#define LAS0_PCLK		0x0040	/* Pacer Clock (24bit) */
+#define LAS0_BCLK		0x0044	/* Burst Clock (10bit) */
+#define LAS0_ADC_SCNT		0x0048	/* A/D Sample counter (10bit) */
+#define LAS0_DAC1_UCNT		0x004c	/* D/A1 Update counter (10 bit) */
+#define LAS0_DAC2_UCNT		0x0050	/* D/A2 Update counter (10 bit) */
+#define LAS0_DCNT		0x0054	/* Delay counter (16 bit) */
+#define LAS0_ACNT		0x0058	/* About counter (16 bit) */
+#define LAS0_DAC_CLK		0x005c	/* DAC clock (16bit) */
+#define LAS0_UTC0		0x0060	/* 8254 TC Counter 0 */
+#define LAS0_UTC1		0x0064	/* 8254 TC Counter 1 */
+#define LAS0_UTC2		0x0068	/* 8254 TC Counter 2 */
+#define LAS0_UTC_CTRL		0x006c	/* 8254 TC Control */
+#define LAS0_DIO0		0x0070	/* Digital I/O Port 0 */
+#define LAS0_DIO1		0x0074	/* Digital I/O Port 1 */
+#define LAS0_DIO0_CTRL		0x0078	/* Digital I/O Control */
+#define LAS0_DIO_STATUS		0x007c	/* Digital I/O Status */
+#define LAS0_BOARD_RESET	0x0100	/* Board reset */
+#define LAS0_DMA0_SRC		0x0104	/* DMA 0 Sources select */
+#define LAS0_DMA1_SRC		0x0108	/* DMA 1 Sources select */
+#define LAS0_ADC_CONVERSION	0x010c	/* A/D Conversion Signal select */
+#define LAS0_BURST_START	0x0110	/* Burst Clock Start Trigger select */
+#define LAS0_PACER_START	0x0114	/* Pacer Clock Start Trigger select */
+#define LAS0_PACER_STOP		0x0118	/* Pacer Clock Stop Trigger select */
+#define LAS0_ACNT_STOP_ENABLE	0x011c	/* About Counter Stop Enable */
+#define LAS0_PACER_REPEAT	0x0120	/* Pacer Start Trigger Mode select */
+#define LAS0_DIN_START		0x0124	/* HiSpd DI Sampling Signal select */
+#define LAS0_DIN_FIFO_CLEAR	0x0128	/* Digital Input FIFO Clear */
+#define LAS0_ADC_FIFO_CLEAR	0x012c	/* A/D FIFO Clear */
+#define LAS0_CGT_WRITE		0x0130	/* Channel Gain Table Write */
+#define LAS0_CGL_WRITE		0x0134	/* Channel Gain Latch Write */
+#define LAS0_CG_DATA		0x0138	/* Digital Table Write */
+#define LAS0_CGT_ENABLE		0x013c	/* Channel Gain Table Enable */
+#define LAS0_CG_ENABLE		0x0140	/* Digital Table Enable */
+#define LAS0_CGT_PAUSE		0x0144	/* Table Pause Enable */
+#define LAS0_CGT_RESET		0x0148	/* Reset Channel Gain Table */
+#define LAS0_CGT_CLEAR		0x014c	/* Clear Channel Gain Table */
+#define LAS0_DAC1_CTRL		0x0150	/* D/A1 output type/range */
+#define LAS0_DAC1_SRC		0x0154	/* D/A1 update source */
+#define LAS0_DAC1_CYCLE		0x0158	/* D/A1 cycle mode */
+#define LAS0_DAC1_RESET		0x015c	/* D/A1 FIFO reset */
+#define LAS0_DAC1_FIFO_CLEAR	0x0160	/* D/A1 FIFO clear */
+#define LAS0_DAC2_CTRL		0x0164	/* D/A2 output type/range */
+#define LAS0_DAC2_SRC		0x0168	/* D/A2 update source */
+#define LAS0_DAC2_CYCLE		0x016c	/* D/A2 cycle mode */
+#define LAS0_DAC2_RESET		0x0170	/* D/A2 FIFO reset */
+#define LAS0_DAC2_FIFO_CLEAR	0x0174	/* D/A2 FIFO clear */
+#define LAS0_ADC_SCNT_SRC	0x0178	/* A/D Sample Counter Source select */
+#define LAS0_PACER_SELECT	0x0180	/* Pacer Clock select */
+#define LAS0_SBUS0_SRC		0x0184	/* SyncBus 0 Source select */
+#define LAS0_SBUS0_ENABLE	0x0188	/* SyncBus 0 enable */
+#define LAS0_SBUS1_SRC		0x018c	/* SyncBus 1 Source select */
+#define LAS0_SBUS1_ENABLE	0x0190	/* SyncBus 1 enable */
+#define LAS0_SBUS2_SRC		0x0198	/* SyncBus 2 Source select */
+#define LAS0_SBUS2_ENABLE	0x019c	/* SyncBus 2 enable */
+#define LAS0_ETRG_POLARITY	0x01a4	/* Ext. Trigger polarity select */
+#define LAS0_EINT_POLARITY	0x01a8	/* Ext. Interrupt polarity select */
+#define LAS0_UTC0_CLOCK		0x01ac	/* UTC0 Clock select */
+#define LAS0_UTC0_GATE		0x01b0	/* UTC0 Gate select */
+#define LAS0_UTC1_CLOCK		0x01b4	/* UTC1 Clock select */
+#define LAS0_UTC1_GATE		0x01b8	/* UTC1 Gate select */
+#define LAS0_UTC2_CLOCK		0x01bc	/* UTC2 Clock select */
+#define LAS0_UTC2_GATE		0x01c0	/* UTC2 Gate select */
+#define LAS0_UOUT0_SELECT	0x01c4	/* User Output 0 source select */
+#define LAS0_UOUT1_SELECT	0x01c8	/* User Output 1 source select */
+#define LAS0_DMA0_RESET		0x01cc	/* DMA0 Request state machine reset */
+#define LAS0_DMA1_RESET		0x01d0	/* DMA1 Request state machine reset */
 
 /*
-  LAS0 Runtime Area Timer/Counter,Dig.IO
-  Name			Local Address			Function
-*/
-#define LAS0_PCLK        0x0040	/*  Pacer Clock value (24bit)             Pacer Clock load (24bit) */
-#define LAS0_BCLK        0x0044	/*  Burst Clock value (10bit)             Burst Clock load (10bit) */
-#define LAS0_ADC_SCNT    0x0048	/*  A/D Sample counter value (10bit)      A/D Sample counter load (10bit) */
-#define LAS0_DAC1_UCNT   0x004C	/*  D/A1 Update counter value (10 bit)    D/A1 Update counter load (10bit) */
-#define LAS0_DAC2_UCNT   0x0050	/*  D/A2 Update counter value (10 bit)    D/A2 Update counter load (10bit) */
-#define LAS0_DCNT        0x0054	/*  Delay counter value (16 bit)          Delay counter load (16bit) */
-#define LAS0_ACNT        0x0058	/*  About counter value (16 bit)          About counter load (16bit) */
-#define LAS0_DAC_CLK     0x005C	/*  DAC clock value (16bit)               DAC clock load (16bit) */
-#define LAS0_UTC0        0x0060	/*  8254 TC Counter 0 User TC 0 value     Load count in TC Counter 0 */
-#define LAS0_UTC1        0x0064	/*  8254 TC Counter 1 User TC 1 value     Load count in TC Counter 1 */
-#define LAS0_UTC2        0x0068	/*  8254 TC Counter 2 User TC 2 value     Load count in TC Counter 2 */
-#define LAS0_UTC_CTRL    0x006C	/*  8254 TC Control Word                  Program counter mode for TC */
-#define LAS0_DIO0        0x0070	/*  Digital I/O Port 0 Read Port          Digital I/O Port 0 Write Port */
-#define LAS0_DIO1        0x0074	/*  Digital I/O Port 1 Read Port          Digital I/O Port 1 Write Port */
-#define LAS0_DIO0_CTRL   0x0078	/*  Clear digital IRQ status flag/read    Clear digital chip/program Port 0 */
-#define LAS0_DIO_STATUS  0x007C	/*  Read Digital I/O Status word          Program digital control register & */
-
-/*
-  LAS0 Setup Area
-  Name			Local Address			Function
-*/
-#define LAS0_BOARD_RESET        0x0100	/*  Board reset */
-#define LAS0_DMA0_SRC           0x0104	/*  DMA 0 Sources select */
-#define LAS0_DMA1_SRC           0x0108	/*  DMA 1 Sources select */
-#define LAS0_ADC_CONVERSION     0x010C	/*  A/D Conversion Signal select */
-#define LAS0_BURST_START        0x0110	/*  Burst Clock Start Trigger select */
-#define LAS0_PACER_START        0x0114	/*  Pacer Clock Start Trigger select */
-#define LAS0_PACER_STOP         0x0118	/*  Pacer Clock Stop Trigger select */
-#define LAS0_ACNT_STOP_ENABLE   0x011C	/*  About Counter Stop Enable */
-#define LAS0_PACER_REPEAT       0x0120	/*  Pacer Start Trigger Mode select */
-#define LAS0_DIN_START          0x0124	/*  High Speed Digital Input Sampling Signal select */
-#define LAS0_DIN_FIFO_CLEAR     0x0128	/*  Digital Input FIFO Clear */
-#define LAS0_ADC_FIFO_CLEAR     0x012C	/*  A/D FIFO Clear */
-#define LAS0_CGT_WRITE          0x0130	/*  Channel Gain Table Write */
-#define LAS0_CGL_WRITE          0x0134	/*  Channel Gain Latch Write */
-#define LAS0_CG_DATA            0x0138	/*  Digital Table Write */
-#define LAS0_CGT_ENABLE		0x013C	/*  Channel Gain Table Enable */
-#define LAS0_CG_ENABLE          0x0140	/*  Digital Table Enable */
-#define LAS0_CGT_PAUSE          0x0144	/*  Table Pause Enable */
-#define LAS0_CGT_RESET          0x0148	/*  Reset Channel Gain Table */
-#define LAS0_CGT_CLEAR          0x014C	/*  Clear Channel Gain Table */
-#define LAS0_DAC1_CTRL          0x0150	/*  D/A1 output type/range */
-#define LAS0_DAC1_SRC           0x0154	/*  D/A1 update source */
-#define LAS0_DAC1_CYCLE         0x0158	/*  D/A1 cycle mode */
-#define LAS0_DAC1_RESET         0x015C	/*  D/A1 FIFO reset */
-#define LAS0_DAC1_FIFO_CLEAR    0x0160	/*  D/A1 FIFO clear */
-#define LAS0_DAC2_CTRL          0x0164	/*  D/A2 output type/range */
-#define LAS0_DAC2_SRC           0x0168	/*  D/A2 update source */
-#define LAS0_DAC2_CYCLE         0x016C	/*  D/A2 cycle mode */
-#define LAS0_DAC2_RESET         0x0170	/*  D/A2 FIFO reset */
-#define LAS0_DAC2_FIFO_CLEAR    0x0174	/*  D/A2 FIFO clear */
-#define LAS0_ADC_SCNT_SRC       0x0178	/*  A/D Sample Counter Source select */
-#define LAS0_PACER_SELECT       0x0180	/*  Pacer Clock select */
-#define LAS0_SBUS0_SRC          0x0184	/*  SyncBus 0 Source select */
-#define LAS0_SBUS0_ENABLE       0x0188	/*  SyncBus 0 enable */
-#define LAS0_SBUS1_SRC          0x018C	/*  SyncBus 1 Source select */
-#define LAS0_SBUS1_ENABLE       0x0190	/*  SyncBus 1 enable */
-#define LAS0_SBUS2_SRC          0x0198	/*  SyncBus 2 Source select */
-#define LAS0_SBUS2_ENABLE       0x019C	/*  SyncBus 2 enable */
-#define LAS0_ETRG_POLARITY      0x01A4	/*  External Trigger polarity select */
-#define LAS0_EINT_POLARITY      0x01A8	/*  External Interrupt polarity select */
-#define LAS0_UTC0_CLOCK         0x01AC	/*  UTC0 Clock select */
-#define LAS0_UTC0_GATE          0x01B0	/*  UTC0 Gate select */
-#define LAS0_UTC1_CLOCK         0x01B4	/*  UTC1 Clock select */
-#define LAS0_UTC1_GATE          0x01B8	/*  UTC1 Gate select */
-#define LAS0_UTC2_CLOCK         0x01BC	/*  UTC2 Clock select */
-#define LAS0_UTC2_GATE          0x01C0	/*  UTC2 Gate select */
-#define LAS0_UOUT0_SELECT       0x01C4	/*  User Output 0 source select */
-#define LAS0_UOUT1_SELECT       0x01C8	/*  User Output 1 source select */
-#define LAS0_DMA0_RESET         0x01CC	/*  DMA0 Request state machine reset */
-#define LAS0_DMA1_RESET         0x01D0	/*  DMA1 Request state machine reset */
+ * Local Address Space 1 Offsets
+ */
+#define LAS1_ADC_FIFO		0x0000	/* A/D FIFO (16bit) */
+#define LAS1_HDIO_FIFO		0x0004	/* HiSpd DI FIFO (16bit) */
+#define LAS1_DAC1_FIFO		0x0008	/* D/A1 FIFO (16bit) */
+#define LAS1_DAC2_FIFO		0x000c	/* D/A2 FIFO (16bit) */
 
 /*
-  LAS1
-  Name			Local Address			Function
-*/
-#define LAS1_ADC_FIFO            0x0000	/*  Read A/D FIFO (16bit) - */
-#define LAS1_HDIO_FIFO           0x0004	/*  Read High Speed Digital Input FIFO (16bit) - */
-#define LAS1_DAC1_FIFO           0x0008	/*  - Write D/A1 FIFO (16bit) */
-#define LAS1_DAC2_FIFO           0x000C	/*  - Write D/A2 FIFO (16bit) */
-
-/*
-  LCFG: PLX 9080 local config & runtime registers
-  Name			Local Address			Function
-*/
-#define LCFG_ITCSR              0x0068	/*  INTCSR, Interrupt Control/Status Register */
-#define LCFG_DMAMODE0           0x0080	/*  DMA Channel 0 Mode Register */
-#define LCFG_DMAPADR0           0x0084	/*  DMA Channel 0 PCI Address Register */
-#define LCFG_DMALADR0           0x0088	/*  DMA Channel 0 Local Address Reg */
-#define LCFG_DMASIZ0            0x008C	/*  DMA Channel 0 Transfer Size (Bytes) Register */
-#define LCFG_DMADPR0            0x0090	/*  DMA Channel 0 Descriptor Pointer Register */
-#define LCFG_DMAMODE1           0x0094	/*  DMA Channel 1 Mode Register */
-#define LCFG_DMAPADR1           0x0098	/*  DMA Channel 1 PCI Address Register */
-#define LCFG_DMALADR1           0x009C	/*  DMA Channel 1 Local Address Register */
-#define LCFG_DMASIZ1            0x00A0	/*  DMA Channel 1 Transfer Size (Bytes) Register */
-#define LCFG_DMADPR1            0x00A4	/*  DMA Channel 1 Descriptor Pointer Register */
-#define LCFG_DMACSR0            0x00A8	/*  DMA Channel 0 Command/Status Register */
-#define LCFG_DMACSR1            0x00A9	/*  DMA Channel 0 Command/Status Register */
-#define LCFG_DMAARB             0x00AC	/*  DMA Arbitration Register */
-#define LCFG_DMATHR             0x00B0	/*  DMA Threshold Register */
-
-/*======================================================================
-  Resister bit definitions
-======================================================================*/
+ * PLX 9080 local config & runtime registers
+ */
+#define LCFG_ITCSR		0x0068	/* Interrupt Control/Status */
+#define LCFG_DMAMODE0		0x0080	/* DMA0 Mode */
+#define LCFG_DMAPADR0		0x0084	/* DMA0 PCI Address */
+#define LCFG_DMALADR0		0x0088	/* DMA0 Local Address */
+#define LCFG_DMASIZ0		0x008c	/* DMA0 Transfer Size (Bytes) */
+#define LCFG_DMADPR0		0x0090	/* DMA0 Descriptor Pointer */
+#define LCFG_DMAMODE1		0x0094	/* DMA1 Mode */
+#define LCFG_DMAPADR1		0x0098	/* DMA1 PCI Address */
+#define LCFG_DMALADR1		0x009c	/* DMA1 Local Address */
+#define LCFG_DMASIZ1		0x00a0	/* DMA1 Transfer Size (Bytes) */
+#define LCFG_DMADPR1		0x00a4	/* DMA1 Descriptor Pointer */
+#define LCFG_DMACSR0		0x00a8	/* DMA0 Command/Status */
+#define LCFG_DMACSR1		0x00a9	/* DMA0 Command/Status */
+#define LCFG_DMAARB		0x00ac	/* DMA Arbitration */
+#define LCFG_DMATHR		0x00b0	/* DMA Threshold */
 
 /*  FIFO Status Word Bits (RtdFifoStatus) */
-#define FS_DAC1_NOT_EMPTY    0x0001	/*  D0  - DAC1 FIFO not empty */
-#define FS_DAC1_HEMPTY   0x0002	/*  D1  - DAC1 FIFO half empty */
-#define FS_DAC1_NOT_FULL     0x0004	/*  D2  - DAC1 FIFO not full */
-#define FS_DAC2_NOT_EMPTY    0x0010	/*  D4  - DAC2 FIFO not empty */
-#define FS_DAC2_HEMPTY   0x0020	/*  D5  - DAC2 FIFO half empty */
-#define FS_DAC2_NOT_FULL     0x0040	/*  D6  - DAC2 FIFO not full */
-#define FS_ADC_NOT_EMPTY     0x0100	/*  D8  - ADC FIFO not empty */
-#define FS_ADC_HEMPTY    0x0200	/*  D9  - ADC FIFO half empty */
-#define FS_ADC_NOT_FULL      0x0400	/*  D10 - ADC FIFO not full */
-#define FS_DIN_NOT_EMPTY     0x1000	/*  D12 - DIN FIFO not empty */
-#define FS_DIN_HEMPTY    0x2000	/*  D13 - DIN FIFO half empty */
-#define FS_DIN_NOT_FULL      0x4000	/*  D14 - DIN FIFO not full */
+#define FS_DAC1_NOT_EMPTY	(1 << 0)  /* DAC1 FIFO not empty */
+#define FS_DAC1_HEMPTY		(1 << 1)  /* DAC1 FIFO half empty */
+#define FS_DAC1_NOT_FULL	(1 << 2)  /* DAC1 FIFO not full */
+#define FS_DAC2_NOT_EMPTY	(1 << 4)  /* DAC2 FIFO not empty */
+#define FS_DAC2_HEMPTY		(1 << 5)  /* DAC2 FIFO half empty */
+#define FS_DAC2_NOT_FULL	(1 << 6)  /* DAC2 FIFO not full */
+#define FS_ADC_NOT_EMPTY	(1 << 8)  /* ADC FIFO not empty */
+#define FS_ADC_HEMPTY		(1 << 9)  /* ADC FIFO half empty */
+#define FS_ADC_NOT_FULL		(1 << 10) /* ADC FIFO not full */
+#define FS_DIN_NOT_EMPTY	(1 << 12) /* DIN FIFO not empty */
+#define FS_DIN_HEMPTY		(1 << 13) /* DIN FIFO half empty */
+#define FS_DIN_NOT_FULL		(1 << 14) /* DIN FIFO not full */
 
 /*  Timer Status Word Bits (GetTimerStatus) */
-#define TS_PCLK_GATE   0x0001
-/*  D0 - Pacer Clock Gate [0 - gated, 1 - enabled] */
-#define TS_BCLK_GATE   0x0002
-/*  D1 - Burst Clock Gate [0 - disabled, 1 - running] */
-#define TS_DCNT_GATE   0x0004
-/*  D2 - Pacer Clock Delayed Start Trigger [0 - delay over, 1 - delay in */
-/*  progress] */
-#define TS_ACNT_GATE   0x0008
-/*  D3 - Pacer Clock About Trigger [0 - completed, 1 - in progress] */
-#define TS_PCLK_RUN    0x0010
-/*  D4 - Pacer Clock Shutdown Flag [0 - Pacer Clock cannot be start */
-/*  triggered only by Software Pacer Start Command, 1 - Pacer Clock can */
-/*  be start triggered] */
+#define TS_PCLK_GATE		(1 << 0)  /* Pacer Clock Gate enabled */
+#define TS_BCLK_GATE		(1 << 1)  /* Burst Clock Gate running */
+#define TS_DCNT_GATE		(1 << 2)  /* Pacer Clock Delayed Start Trig. */
+#define TS_ACNT_GATE		(1 << 3)  /* Pacer Clock About Trig. */
+#define TS_PCLK_RUN		(1 << 4)  /* Pacer Clock Shutdown Flag */
 
 /*  External Trigger polarity select */
 /*  External Interrupt polarity select */
diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
index 137885b..7e577e4 100644
--- a/drivers/staging/comedi/drivers/rti800.c
+++ b/drivers/staging/comedi/drivers/rti800.c
@@ -161,8 +161,6 @@ struct rti800_private {
 	int muxgain_bits;
 };
 
-#define devpriv ((struct rti800_private *)dev->private)
-
 #define RTI800_TIMEOUT 100
 
 static irqreturn_t rti800_interrupt(int irq, void *dev)
@@ -177,6 +175,7 @@ static int rti800_ai_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct rti800_private *devpriv = dev->private;
 	int i, t;
 	int status;
 	int chan = CR_CHAN(insn->chanspec);
@@ -229,6 +228,7 @@ static int rti800_ao_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct rti800_private *devpriv = dev->private;
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 
@@ -242,6 +242,7 @@ static int rti800_ao_insn_write(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
 {
+	struct rti800_private *devpriv = dev->private;
 	int chan = CR_CHAN(insn->chanspec);
 	int d;
 	int i;
@@ -303,6 +304,7 @@ static int rti800_do_insn_bits(struct comedi_device *dev,
 static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct rti800_board *board = comedi_board(dev);
+	struct rti800_private *devpriv;
 	unsigned int irq;
 	unsigned long iobase;
 	int ret;
@@ -347,9 +349,10 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	ret = alloc_private(dev, sizeof(struct rti800_private));
-	if (ret < 0)
-		return ret;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	devpriv->adc_mux = it->options[2];
 	devpriv->adc_range = it->options[3];
diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
index 3f9d027..2185ca1 100644
--- a/drivers/staging/comedi/drivers/rti802.c
+++ b/drivers/staging/comedi/drivers/rti802.c
@@ -55,12 +55,11 @@ struct rti802_private {
 	unsigned int ao_readback[8];
 };
 
-#define devpriv ((struct rti802_private *)dev->private)
-
 static int rti802_ao_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct rti802_private *devpriv = dev->private;
 	int i;
 
 	for (i = 0; i < insn->n; i++)
@@ -73,6 +72,7 @@ static int rti802_ao_insn_write(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
 {
+	struct rti802_private *devpriv = dev->private;
 	int i, d;
 	int chan = CR_CHAN(insn->chanspec);
 
@@ -89,6 +89,7 @@ static int rti802_ao_insn_write(struct comedi_device *dev,
 
 static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
+	struct rti802_private *devpriv;
 	struct comedi_subdevice *s;
 	int i;
 	unsigned long iobase;
@@ -104,8 +105,10 @@ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 	dev->board_name = "rti802";
 
-	if (alloc_private(dev, sizeof(struct rti802_private)))
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_alloc_subdevices(dev, 1);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
index a1e2562..39232b35 100644
--- a/drivers/staging/comedi/drivers/s526.c
+++ b/drivers/staging/comedi/drivers/s526.c
@@ -564,10 +564,10 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	}
 	dev->iobase = iobase;
 
-	ret = alloc_private(dev, sizeof(*devpriv));
-	if (ret)
-		return ret;
-	devpriv = dev->private;
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_alloc_subdevices(dev, 4);
 	if (ret)
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index 551d68b..6dc1d28 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -161,7 +161,6 @@ static struct dio_private *dio_private_word[]={
 };
 */
 
-#define devpriv ((struct s626_private *)dev->private)
 #define diopriv ((struct dio_private *)s->private)
 
 /*  COUNTER OBJECT ------------------------------------------------ */
@@ -232,6 +231,8 @@ static const struct comedi_lrange s626_range_table = { 2, {
 /*  critical section. */
 static void DEBItransfer(struct comedi_device *dev)
 {
+	struct s626_private *devpriv = dev->private;
+
 	/*  Initiate upload of shadow RAM to DEBI control register. */
 	MC_ENABLE(P_MC2, MC2_UPLD_DEBI);
 
@@ -249,6 +250,7 @@ static void DEBItransfer(struct comedi_device *dev)
 
 static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr)
 {
+	struct s626_private *devpriv = dev->private;
 	uint16_t retval;
 
 	/*  Set up DEBI control register value in shadow RAM. */
@@ -267,6 +269,7 @@ static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr)
 /*  Write a value to a gate array register. */
 static void DEBIwrite(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. */
 	WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr);
@@ -283,6 +286,7 @@ static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata)
 static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask,
 			uint16_t wdata)
 {
+	struct s626_private *devpriv = dev->private;
 
 	/*  Copy target gate array register into P_DEBIAD register. */
 	WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr);
@@ -302,6 +306,8 @@ static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask,
 
 static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val)
 {
+	struct s626_private *devpriv = dev->private;
+
 	/*  Write I2C command to I2C Transfer Control shadow register. */
 	WR7146(P_I2CCTRL, val);
 
@@ -324,6 +330,7 @@ static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val)
 /*  Read uint8_t from EEPROM. */
 static uint8_t I2Cread(struct comedi_device *dev, uint8_t addr)
 {
+	struct s626_private *devpriv = dev->private;
 	uint8_t rtnval;
 
 	/*  Send EEPROM target address. */
@@ -375,6 +382,7 @@ static uint8_t trimadrs[] = { 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x
  */
 static void SendDAC(struct comedi_device *dev, uint32_t val)
 {
+	struct s626_private *devpriv = dev->private;
 
 	/* START THE SERIAL CLOCK RUNNING ------------- */
 
@@ -496,6 +504,7 @@ static void SendDAC(struct comedi_device *dev, uint32_t val)
 /*  Private helper function: Write setpoint to an application DAC channel. */
 static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata)
 {
+	struct s626_private *devpriv = dev->private;
 	register uint16_t signmask;
 	register uint32_t WSImage;
 
@@ -553,6 +562,7 @@ static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata)
 static void WriteTrimDAC(struct comedi_device *dev, uint8_t LogicalChan,
 			 uint8_t DacData)
 {
+	struct s626_private *devpriv = dev->private;
 	uint32_t chan;
 
 	/*  Save the new setpoint in case the application needs to read it back later. */
@@ -735,6 +745,7 @@ static int s626_dio_clear_irq(struct comedi_device *dev)
 static irqreturn_t s626_irq_handler(int irq, void *d)
 {
 	struct comedi_device *dev = d;
+	struct s626_private *devpriv = dev->private;
 	struct comedi_subdevice *s;
 	struct comedi_cmd *cmd;
 	struct enc_private *k;
@@ -968,6 +979,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d)
  */
 static void ResetADC(struct comedi_device *dev, uint8_t *ppl)
 {
+	struct s626_private *devpriv = dev->private;
 	register uint32_t *pRPS;
 	uint32_t JmpAdrs;
 	uint16_t i;
@@ -1163,6 +1175,7 @@ static int s626_ai_insn_config(struct comedi_device *dev,
 
 /* static int s626_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) */
 /* { */
+/*   struct s626_private *devpriv = dev->private; */
 /*   register uint8_t	i; */
 /*   register int32_t	*readaddr; */
 
@@ -1191,6 +1204,7 @@ static int s626_ai_insn_read(struct comedi_device *dev,
 			     struct comedi_subdevice *s,
 			     struct comedi_insn *insn, unsigned int *data)
 {
+	struct s626_private *devpriv = dev->private;
 	uint16_t chan = CR_CHAN(insn->chanspec);
 	uint16_t range = CR_RANGE(insn->chanspec);
 	uint16_t AdcSpec = 0;
@@ -1302,6 +1316,8 @@ static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd)
 static int s626_ai_inttrig(struct comedi_device *dev,
 			   struct comedi_subdevice *s, unsigned int trignum)
 {
+	struct s626_private *devpriv = dev->private;
+
 	if (trignum != 0)
 		return -EINVAL;
 
@@ -1378,7 +1394,7 @@ static void s626_timer_load(struct comedi_device *dev, struct enc_private *k,
 /*  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;
@@ -1533,80 +1549,46 @@ static int s626_ai_cmdtest(struct comedi_device *dev,
 
 	/* step 3: make sure arguments are trivially compatible */
 
-	if (cmd->start_src != TRIG_EXT && cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	if (cmd->start_src != TRIG_EXT)
+		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->start_src == TRIG_EXT && cmd->start_arg > 39) {
-		cmd->start_arg = 39;
-		err++;
-	}
+	if (cmd->scan_begin_src == TRIG_EXT)
+		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 39);
 
-	if (cmd->scan_begin_src == TRIG_EXT && cmd->scan_begin_arg > 39) {
-		cmd->scan_begin_arg = 39;
-		err++;
-	}
+	if (cmd->convert_src == TRIG_EXT)
+		err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 39);
 
-	if (cmd->convert_src == TRIG_EXT && cmd->convert_arg > 39) {
-		cmd->convert_arg = 39;
-		err++;
-	}
 #define MAX_SPEED	200000	/* in nanoseconds */
 #define MIN_SPEED	2000000000	/* in nanoseconds */
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
-		if (cmd->scan_begin_arg < MAX_SPEED) {
-			cmd->scan_begin_arg = MAX_SPEED;
-			err++;
-		}
-		if (cmd->scan_begin_arg > MIN_SPEED) {
-			cmd->scan_begin_arg = MIN_SPEED;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						 MAX_SPEED);
+		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
+						 MIN_SPEED);
 	} else {
 		/* external trigger */
 		/* should be level/edge, hi/lo specification here */
 		/* should specify multiple external triggers */
-/*     if(cmd->scan_begin_arg>9){ */
-/*       cmd->scan_begin_arg=9; */
-/*       err++; */
-/*     } */
+/*		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */
 	}
 	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < MAX_SPEED) {
-			cmd->convert_arg = MAX_SPEED;
-			err++;
-		}
-		if (cmd->convert_arg > MIN_SPEED) {
-			cmd->convert_arg = MIN_SPEED;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg, MAX_SPEED);
+		err |= cfc_check_trigger_arg_max(&cmd->convert_arg, MIN_SPEED);
 	} else {
 		/* external trigger */
 		/* see above */
-/*     if(cmd->convert_arg>9){ */
-/*       cmd->convert_arg=9; */
-/*       err++; */
-/*     } */
+/*		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */
 	}
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (cmd->stop_arg > 0x00ffffff) {
-			cmd->stop_arg = 0x00ffffff;
-			err++;
-		}
-	} else {
-		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+	if (cmd->stop_src == TRIG_COUNT)
+		err |= cfc_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
+	else	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -1643,6 +1625,8 @@ static int s626_ai_cmdtest(struct comedi_device *dev,
 
 static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+	struct s626_private *devpriv = dev->private;
+
 	/*  Stop RPS program in case it is currently running. */
 	MC_DISABLE(P_MC1, MC1_ERPS1);
 
@@ -1657,7 +1641,7 @@ static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_insn *insn, unsigned int *data)
 {
-
+	struct s626_private *devpriv = dev->private;
 	int i;
 	uint16_t chan = CR_CHAN(insn->chanspec);
 	int16_t dacdata;
@@ -1676,6 +1660,7 @@ static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int s626_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_insn *insn, unsigned int *data)
 {
+	struct s626_private *devpriv = dev->private;
 	int i;
 
 	for (i = 0; i < insn->n; i++)
@@ -1974,6 +1959,7 @@ static uint16_t GetMode_B(struct comedi_device *dev, struct enc_private *k)
 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. */
@@ -2032,6 +2018,7 @@ static void SetMode_A(struct comedi_device *dev, struct enc_private *k,
 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. */
@@ -2165,6 +2152,8 @@ static uint16_t GetLoadTrig_B(struct comedi_device *dev, struct enc_private *k)
 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, (uint16_t) (~CRBMSK_INTCTRL),
 		    CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A);
@@ -2182,6 +2171,7 @@ static void SetIntSrc_A(struct comedi_device *dev, struct enc_private *k,
 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. */
@@ -2412,6 +2402,7 @@ static void CountersInit(struct comedi_device *dev)
 static int s626_allocate_dma_buffers(struct comedi_device *dev)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct s626_private *devpriv = dev->private;
 	void *addr;
 	dma_addr_t appdma;
 
@@ -2432,6 +2423,7 @@ static int s626_allocate_dma_buffers(struct comedi_device *dev)
 
 static void s626_initialize(struct comedi_device *dev)
 {
+	struct s626_private *devpriv = dev->private;
 	dma_addr_t pPhysBuf;
 	uint16_t chan;
 	int i;
@@ -2665,16 +2657,20 @@ static void s626_initialize(struct comedi_device *dev)
 	/* writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->base_addr + P_IER); */
 }
 
-static int s626_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev)
+static int s626_auto_attach(struct comedi_device *dev,
+				      unsigned long context_unused)
 {
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct s626_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 
-	comedi_set_hw_dev(dev, &pcidev->dev);
 	dev->board_name = dev->driver->driver_name;
 
-	if (alloc_private(dev, sizeof(struct s626_private)) < 0)
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
 
 	ret = comedi_pci_enable(pcidev, dev->board_name);
 	if (ret)
@@ -2794,6 +2790,7 @@ static int s626_attach_pci(struct comedi_device *dev, struct pci_dev *pcidev)
 static void s626_detach(struct comedi_device *dev)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	struct s626_private *devpriv = dev->private;
 
 	if (devpriv) {
 		/* stop ai_command */
@@ -2829,17 +2826,17 @@ static void s626_detach(struct comedi_device *dev)
 static struct comedi_driver s626_driver = {
 	.driver_name	= "s626",
 	.module		= THIS_MODULE,
-	.attach_pci	= s626_attach_pci,
+	.auto_attach	= s626_auto_attach,
 	.detach		= s626_detach,
 };
 
-static int __devinit s626_pci_probe(struct pci_dev *dev,
+static int s626_pci_probe(struct pci_dev *dev,
 				    const struct pci_device_id *ent)
 {
 	return comedi_pci_auto_config(dev, &s626_driver);
 }
 
-static void __devexit s626_pci_remove(struct pci_dev *dev)
+static void s626_pci_remove(struct pci_dev *dev)
 {
 	comedi_pci_auto_unconfig(dev);
 }
@@ -2860,7 +2857,7 @@ static struct pci_driver s626_pci_driver = {
 	.name		= "s626",
 	.id_table	= s626_pci_table,
 	.probe		= s626_pci_probe,
-	.remove		= __devexit_p(s626_pci_remove),
+	.remove		= s626_pci_remove,
 };
 module_comedi_pci_driver(s626_driver, s626_pci_driver);
 
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index 5bf84cf..e6177b4 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -31,6 +31,8 @@ Status: in development
 
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "../comedidev.h"
 
 #include <linux/delay.h>
@@ -43,10 +45,6 @@ Status: in development
 #include <linux/serial.h>
 #include <linux/poll.h>
 
-struct serial2002_board {
-	const char *name;
-};
-
 struct serial2002_range_table_t {
 
 	/*  HACK... */
@@ -68,12 +66,6 @@ struct serial2002_private {
 	struct serial2002_range_table_t in_range[32], out_range[32];
 };
 
-/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct serial2002_private *)dev->private)
-
 struct serial_data {
 	enum { is_invalid, is_digital, is_channel } kind;
 	int index;
@@ -282,7 +274,7 @@ static struct serial_data serial_read(struct file *f, int timeout)
 
 		length++;
 		if (data < 0) {
-			printk(KERN_ERR "serial2002 error\n");
+			pr_err("Failed to read serial.\n");
 			break;
 		} else if (data & 0x80) {
 			result.value = (result.value << 7) | (data & 0x7f);
@@ -348,6 +340,7 @@ static void serial_write(struct file *f, struct serial_data data)
 
 static int serial_2002_open(struct comedi_device *dev)
 {
+	struct serial2002_private *devpriv = dev->private;
 	int result;
 	char port[20];
 
@@ -355,7 +348,7 @@ static int serial_2002_open(struct comedi_device *dev)
 	devpriv->tty = filp_open(port, O_RDWR, 0);
 	if (IS_ERR(devpriv->tty)) {
 		result = (int)PTR_ERR(devpriv->tty);
-		printk(KERN_ERR "serial_2002: file open error = %d\n", result);
+		dev_err(dev->class_dev, "file open error = %d\n", result);
 	} else {
 		struct config_t {
 
@@ -655,6 +648,8 @@ err_alloc_configs:
 
 static void serial_2002_close(struct comedi_device *dev)
 {
+	struct serial2002_private *devpriv = dev->private;
+
 	if (!IS_ERR(devpriv->tty) && devpriv->tty)
 		filp_close(devpriv->tty, NULL);
 }
@@ -663,6 +658,7 @@ static int serial2002_di_rinsn(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct serial2002_private *devpriv = dev->private;
 	int n;
 	int chan;
 
@@ -685,6 +681,7 @@ static int serial2002_do_winsn(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct serial2002_private *devpriv = dev->private;
 	int n;
 	int chan;
 
@@ -704,6 +701,7 @@ static int serial2002_ai_rinsn(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct serial2002_private *devpriv = dev->private;
 	int n;
 	int chan;
 
@@ -726,6 +724,7 @@ static int serial2002_ao_winsn(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct serial2002_private *devpriv = dev->private;
 	int n;
 	int chan;
 
@@ -746,6 +745,7 @@ static int serial2002_ao_rinsn(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct serial2002_private *devpriv = dev->private;
 	int n;
 	int chan = CR_CHAN(insn->chanspec);
 
@@ -759,6 +759,7 @@ static int serial2002_ei_rinsn(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	struct serial2002_private *devpriv = dev->private;
 	int n;
 	int chan;
 
@@ -780,14 +781,18 @@ static int serial2002_ei_rinsn(struct comedi_device *dev,
 static int serial2002_attach(struct comedi_device *dev,
 			     struct comedi_devconfig *it)
 {
-	const struct serial2002_board *board = comedi_board(dev);
+	struct serial2002_private *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 
 	dev_dbg(dev->class_dev, "serial2002: attach\n");
-	dev->board_name = board->name;
-	if (alloc_private(dev, sizeof(struct serial2002_private)) < 0)
+	dev->board_name = dev->driver->driver_name;
+
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
 		return -ENOMEM;
+	dev->private = devpriv;
+
 	dev->open = serial_2002_open;
 	dev->close = serial_2002_close;
 	devpriv->port = it->options[0];
@@ -860,20 +865,11 @@ static void serial2002_detach(struct comedi_device *dev)
 	}
 }
 
-static const struct serial2002_board serial2002_boards[] = {
-	{
-		.name	= "serial2002"
-	},
-};
-
 static struct comedi_driver serial2002_driver = {
 	.driver_name	= "serial2002",
 	.module		= THIS_MODULE,
 	.attach		= serial2002_attach,
 	.detach		= serial2002_detach,
-	.board_name	= &serial2002_boards[0].name,
-	.offset		= sizeof(struct serial2002_board),
-	.num_names	= ARRAY_SIZE(serial2002_boards),
 };
 module_comedi_driver(serial2002_driver);
 
diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
index b70cdf3..e2d7970 100644
--- a/drivers/staging/comedi/drivers/skel.c
+++ b/drivers/staging/comedi/drivers/skel.c
@@ -92,6 +92,7 @@ Configuration Options:
  */
 struct skel_board {
 	const char *name;
+	unsigned int devid;
 	int ai_chans;
 	int ai_bits;
 	int have_dio;
@@ -100,36 +101,20 @@ struct skel_board {
 static const struct skel_board skel_boards[] = {
 	{
 	 .name = "skel-100",
+	 .devid = 0x100,
 	 .ai_chans = 16,
 	 .ai_bits = 12,
 	 .have_dio = 1,
 	 },
 	{
 	 .name = "skel-200",
+	 .devid = 0x200,
 	 .ai_chans = 8,
 	 .ai_bits = 16,
 	 .have_dio = 0,
 	 },
 };
 
-/* This is used by modprobe to translate PCI IDs to drivers.  Should
- * only be used for PCI and ISA-PnP devices */
-/* Please add your PCI vendor ID to comedidev.h, and it will be forwarded
- * upstream. */
-#define PCI_VENDOR_ID_SKEL 0xdafe
-static DEFINE_PCI_DEVICE_TABLE(skel_pci_table) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_SKEL, 0x0100) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_SKEL, 0x0200) },
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, skel_pci_table);
-
-/*
- * Useful for shorthand access to the particular board structure
- */
-#define thisboard ((const struct skel_board *)dev->board_ptr)
-
 /* this structure is for data unique to this hardware driver.  If
    several hardware drivers keep similar information in this structure,
    feel free to suggest moving the variable to the struct comedi_device struct.
@@ -138,165 +123,25 @@ struct skel_private {
 
 	int data;
 
-	/* would be useful for a PCI device */
-	struct pci_dev *pci_dev;
-
 	/* Used for AO readback */
 	unsigned int ao_readback[2];
 };
 
-/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct skel_private *)dev->private)
-
-/*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
-static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it);
-static void skel_detach(struct comedi_device *dev);
-static struct comedi_driver driver_skel = {
-	.driver_name = "dummy",
-	.module = THIS_MODULE,
-	.attach = skel_attach,
-	.detach = skel_detach,
-/* It is not necessary to implement the following members if you are
- * writing a driver for a ISA PnP or PCI card */
-	/* Most drivers will support multiple types of boards by
-	 * having an array of board structures.  These were defined
-	 * in skel_boards[] above.  Note that the element 'name'
-	 * was first in the structure -- Comedi uses this fact to
-	 * extract the name of the board without knowing any details
-	 * about the structure except for its length.
-	 * When a device is attached (by comedi_config), the name
-	 * of the device is given to Comedi, and Comedi tries to
-	 * match it by going through the list of board names.  If
-	 * there is a match, the address of the pointer is put
-	 * into dev->board_ptr and driver->attach() is called.
-	 *
-	 * Note that these are not necessary if you can determine
-	 * the type of board in software.  ISA PnP, PCI, and PCMCIA
-	 * devices are such boards.
-	 */
-	.board_name = &skel_boards[0].name,
-	.offset = sizeof(struct skel_board),
-	.num_names = ARRAY_SIZE(skel_boards),
-};
-
-static int skel_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
-			 struct comedi_insn *insn, unsigned int *data);
-static int skel_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
-			 struct comedi_insn *insn, unsigned int *data);
-static int skel_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
-			 struct comedi_insn *insn, unsigned int *data);
-static int skel_dio_insn_bits(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data);
-static int skel_dio_insn_config(struct comedi_device *dev,
-				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data);
-static int skel_ai_cmdtest(struct comedi_device *dev,
-			   struct comedi_subdevice *s, struct comedi_cmd *cmd);
-static int skel_ns_to_timer(unsigned int *ns, int round);
-
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board.  If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
-static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+/* 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. */
+static int skel_ns_to_timer(unsigned int *ns, int round)
 {
-	struct comedi_subdevice *s;
-	int ret;
-
-	pr_info("comedi%d: skel: ", dev->minor);
-
-/*
- * If you can probe the device to determine what device in a series
- * it is, this is the place to do it.  Otherwise, dev->board_ptr
- * should already be initialized.
- */
-	/* dev->board_ptr = skel_probe(dev, it); */
-
-/*
- * Initialize dev->board_name.  Note that we can use the "thisboard"
- * macro now, since we just initialized it in the last line.
- */
-	dev->board_name = thisboard->name;
-
-/*
- * Allocate the private structure area.  alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
-	if (alloc_private(dev, sizeof(struct skel_private)) < 0)
-		return -ENOMEM;
-
-	ret = comedi_alloc_subdevices(dev, 3);
-	if (ret)
-		return ret;
-
-	s = &dev->subdevices[0];
-	/* dev->read_subdev=s; */
-	/* analog input subdevice */
-	s->type = COMEDI_SUBD_AI;
-	/* we support single-ended (ground) and differential */
-	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
-	s->n_chan = thisboard->ai_chans;
-	s->maxdata = (1 << thisboard->ai_bits) - 1;
-	s->range_table = &range_bipolar10;
-	s->len_chanlist = 16;	/* This is the maximum chanlist length that
-				   the board can handle */
-	s->insn_read = skel_ai_rinsn;
-/*
-*       s->subdev_flags |= SDF_CMD_READ;
-*       s->do_cmd = skel_ai_cmd;
-*/
-	s->do_cmdtest = skel_ai_cmdtest;
-
-	s = &dev->subdevices[1];
-	/* analog output subdevice */
-	s->type = COMEDI_SUBD_AO;
-	s->subdev_flags = SDF_WRITABLE;
-	s->n_chan = 1;
-	s->maxdata = 0xffff;
-	s->range_table = &range_bipolar5;
-	s->insn_write = skel_ao_winsn;
-	s->insn_read = skel_ao_rinsn;
-
-	s = &dev->subdevices[2];
-	/* digital i/o subdevice */
-	if (thisboard->have_dio) {
-		s->type = COMEDI_SUBD_DIO;
-		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-		s->n_chan = 16;
-		s->maxdata = 1;
-		s->range_table = &range_digital;
-		s->insn_bits = skel_dio_insn_bits;
-		s->insn_config = skel_dio_insn_config;
-	} else {
-		s->type = COMEDI_SUBD_UNUSED;
-	}
-
-	pr_info("attached\n");
-
-	return 0;
-}
+	/* trivial timer */
+	/* if your timing is done through two cascaded timers, the
+	 * i8253_cascade_ns_to_timer() function in 8253.h can be
+	 * very helpful.  There are also i8254_load() and i8254_mm_load()
+	 * which can be used to load values into the ubiquitous 8254 counters
+	 */
 
-/*
- * _detach is called to deconfigure a device.  It should deallocate
- * resources.
- * This function is also called when _attach() fails, so it should be
- * careful not to release resources that were not necessarily
- * allocated by _attach().  dev->private and dev->subdevices are
- * deallocated automatically by the core.
- */
-static void skel_detach(struct comedi_device *dev)
-{
+	return *ns;
 }
 
 /*
@@ -306,6 +151,7 @@ static void skel_detach(struct comedi_device *dev)
 static int skel_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_insn *insn, unsigned int *data)
 {
+	const struct skel_board *thisboard = comedi_board(dev);
 	int n, i;
 	unsigned int d;
 	unsigned int status;
@@ -331,9 +177,7 @@ static int skel_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 				break;
 		}
 		if (i == TIMEOUT) {
-			/* printk() should be used instead of printk()
-			 * whenever the code can be called from real-time. */
-			pr_info("timeout\n");
+			dev_warn(dev->class_dev, "ai timeout\n");
 			return -ETIMEDOUT;
 		}
 
@@ -389,67 +233,40 @@ static int skel_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
+
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
 #define MAX_SPEED	10000	/* in nanoseconds */
 #define MIN_SPEED	1000000000	/* in nanoseconds */
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
-		if (cmd->scan_begin_arg < MAX_SPEED) {
-			cmd->scan_begin_arg = MAX_SPEED;
-			err++;
-		}
-		if (cmd->scan_begin_arg > MIN_SPEED) {
-			cmd->scan_begin_arg = MIN_SPEED;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						 MAX_SPEED);
+		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
+						 MIN_SPEED);
 	} else {
 		/* external trigger */
 		/* should be level/edge, hi/lo specification here */
 		/* should specify multiple external triggers */
-		if (cmd->scan_begin_arg > 9) {
-			cmd->scan_begin_arg = 9;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9);
 	}
+
 	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < MAX_SPEED) {
-			cmd->convert_arg = MAX_SPEED;
-			err++;
-		}
-		if (cmd->convert_arg > MIN_SPEED) {
-			cmd->convert_arg = MIN_SPEED;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg, MAX_SPEED);
+		err |= cfc_check_trigger_arg_max(&cmd->convert_arg, MIN_SPEED);
 	} else {
 		/* external trigger */
 		/* see above */
-		if (cmd->convert_arg > 9) {
-			cmd->convert_arg = 9;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9);
 	}
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
-	if (cmd->stop_src == TRIG_COUNT) {
-		if (cmd->stop_arg > 0x00ffffff) {
-			cmd->stop_arg = 0x00ffffff;
-			err++;
-		}
-	} else {
-		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+	if (cmd->stop_src == TRIG_COUNT)
+		err |= cfc_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
+	else	/* TRIG_NONE */
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 
 	if (err)
 		return 3;
@@ -484,30 +301,13 @@ static int skel_ai_cmdtest(struct comedi_device *dev,
 	return 0;
 }
 
-/* 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. */
-static int skel_ns_to_timer(unsigned int *ns, int round)
-{
-	/* trivial timer */
-	/* if your timing is done through two cascaded timers, the
-	 * i8253_cascade_ns_to_timer() function in 8253.h can be
-	 * very helpful.  There are also i8254_load() and i8254_mm_load()
-	 * which can be used to load values into the ubiquitous 8254 counters
-	 */
-
-	return *ns;
-}
-
 static int skel_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_insn *insn, unsigned int *data)
 {
+	struct skel_private *devpriv = dev->private;
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 
-	pr_info("skel_ao_winsn\n");
 	/* Writing a list of values to an AO channel is probably not
 	 * very useful, but that's how the interface is defined. */
 	for (i = 0; i < insn->n; i++) {
@@ -525,6 +325,7 @@ static int skel_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 static int skel_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_insn *insn, unsigned int *data)
 {
+	struct skel_private *devpriv = dev->private;
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 
@@ -593,57 +394,332 @@ static int skel_dio_insn_config(struct comedi_device *dev,
 	return insn->n;
 }
 
-#ifdef CONFIG_COMEDI_PCI_DRIVERS
-static int __devinit driver_skel_pci_probe(struct pci_dev *dev,
-					   const struct pci_device_id *ent)
+static const struct skel_board *skel_find_pci_board(struct pci_dev *pcidev)
 {
-	return comedi_pci_auto_config(dev, &driver_skel);
+	unsigned int i;
+
+/*
+ * This example code assumes all the entries in skel_boards[] are PCI boards
+ * and all use the same PCI vendor ID.  If skel_boards[] contains a mixture
+ * of PCI and non-PCI boards, this loop should skip over the non-PCI boards.
+ */
+	for (i = 0; i < ARRAY_SIZE(skel_boards); i++)
+		if (/* skel_boards[i].bustype == pci_bustype && */
+		    pcidev->device == skel_boards[i].devid)
+			return &skel_boards[i];
+	return NULL;
 }
 
-static void __devexit driver_skel_pci_remove(struct pci_dev *dev)
+/*
+ * Handle common part of skel_attach() and skel_auto_attach().
+ */
+static int skel_common_attach(struct comedi_device *dev)
 {
-	comedi_pci_auto_unconfig(dev);
+	const struct skel_board *thisboard = comedi_board(dev);
+	struct comedi_subdevice *s;
+	int ret;
+
+	ret = comedi_alloc_subdevices(dev, 3);
+	if (ret)
+		return ret;
+
+	s = &dev->subdevices[0];
+	/* dev->read_subdev=s; */
+	/* analog input subdevice */
+	s->type = COMEDI_SUBD_AI;
+	/* we support single-ended (ground) and differential */
+	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
+	s->n_chan = thisboard->ai_chans;
+	s->maxdata = (1 << thisboard->ai_bits) - 1;
+	s->range_table = &range_bipolar10;
+	s->len_chanlist = 16;	/* This is the maximum chanlist length that
+				   the board can handle */
+	s->insn_read = skel_ai_rinsn;
+/*
+*       s->subdev_flags |= SDF_CMD_READ;
+*       s->do_cmd = skel_ai_cmd;
+*/
+	s->do_cmdtest = skel_ai_cmdtest;
+
+	s = &dev->subdevices[1];
+	/* analog output subdevice */
+	s->type = COMEDI_SUBD_AO;
+	s->subdev_flags = SDF_WRITABLE;
+	s->n_chan = 1;
+	s->maxdata = 0xffff;
+	s->range_table = &range_bipolar5;
+	s->insn_write = skel_ao_winsn;
+	s->insn_read = skel_ao_rinsn;
+
+	s = &dev->subdevices[2];
+	/* digital i/o subdevice */
+	if (thisboard->have_dio) {
+		s->type = COMEDI_SUBD_DIO;
+		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+		s->n_chan = 16;
+		s->maxdata = 1;
+		s->range_table = &range_digital;
+		s->insn_bits = skel_dio_insn_bits;
+		s->insn_config = skel_dio_insn_config;
+	} else {
+		s->type = COMEDI_SUBD_UNUSED;
+	}
+
+	dev_info(dev->class_dev, "skel: attached\n");
+
+	return 0;
 }
 
-static struct pci_driver driver_skel_pci_driver = {
-	.id_table = skel_pci_table,
-	.probe = &driver_skel_pci_probe,
-	.remove = __devexit_p(&driver_skel_pci_remove)
-};
+/*
+ * _attach is called by the Comedi core to configure the driver
+ * for a particular board in response to the COMEDI_DEVCONFIG ioctl for
+ * a matching board or driver name.  If you specified a board_name array
+ * in the driver structure, dev->board_ptr contains that address.
+ *
+ * Drivers that handle only PCI or USB devices do not usually support
+ * manual attachment of those devices via the COMEDI_DEVCONFIG ioctl, so
+ * those drivers do not have an _attach function; they just have an
+ * _auto_attach function instead.  (See skel_auto_attach() for an example
+ * of such a function.)
+ */
+static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+{
+	const struct skel_board *thisboard;
+	struct skel_private *devpriv;
+
+/*
+ * If you can probe the device to determine what device in a series
+ * it is, this is the place to do it.  Otherwise, dev->board_ptr
+ * should already be initialized.
+ */
+	/* dev->board_ptr = skel_probe(dev, it); */
+
+	thisboard = comedi_board(dev);
+
+/*
+ * Initialize dev->board_name.
+ */
+	dev->board_name = thisboard->name;
+
+	/* Allocate the private data */
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
+
+/*
+ * Supported boards are usually either auto-attached via the
+ * Comedi driver's _auto_attach routine, or manually attached via the
+ * Comedi driver's _attach routine.  In most cases, attempts to
+ * manual attach boards that are usually auto-attached should be
+ * rejected by this function.
+ */
+/*
+ *	if (thisboard->bustype == pci_bustype) {
+ *		dev_err(dev->class_dev,
+ *			"Manual attachment of PCI board '%s' not supported\n",
+ *			thisboard->name);
+ *	}
+ */
+
+/*
+ * For ISA boards, get the i/o base address from it->options[],
+ * request the i/o region and set dev->iobase * from it->options[].
+ * If using interrupts, get the IRQ number from it->options[].
+ */
+
+	/*
+	 * Call a common function to handle the remaining things to do for
+	 * attaching ISA or PCI boards.  (Extra parameters could be added
+	 * to pass additional information such as IRQ number.)
+	 */
+	return skel_common_attach(dev);
+}
 
-static int __init driver_skel_init_module(void)
+/*
+ * _auto_attach is called via comedi_pci_auto_config() (or
+ * comedi_usb_auto_config(), etc.) to handle devices that can be attached
+ * to the Comedi core automatically without the COMEDI_DEVCONFIG ioctl.
+ *
+ * The context parameter is usually unused, but if the driver called
+ * comedi_auto_config() directly instead of the comedi_pci_auto_config()
+ * wrapper function, this will be a copy of the context passed to
+ * comedi_auto_config().
+ */
+static int skel_auto_attach(struct comedi_device *dev,
+				      unsigned long context)
 {
-	int retval;
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+	const struct skel_board *thisboard;
+	struct skel_private *devpriv;
+	int ret;
+
+	/* Hack to allow unused code to be optimized out. */
+	if (!IS_ENABLED(CONFIG_COMEDI_PCI_DRIVERS))
+		return -EINVAL;
+
+	/* Find a matching board in skel_boards[]. */
+	thisboard = skel_find_pci_board(pcidev);
+	if (!thisboard) {
+		dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Point the struct comedi_device to the matching board info
+	 * and set the board name.
+	 */
+	dev->board_ptr = thisboard;
+	dev->board_name = thisboard->name;
+
+	/* Allocate the private data */
+	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+	if (!devpriv)
+		return -ENOMEM;
+	dev->private = devpriv;
 
-	retval = comedi_driver_register(&driver_skel);
-	if (retval < 0)
-		return retval;
+	/* Enable the PCI device. */
+	ret = comedi_pci_enable(pcidev, dev->board_name);
+	if (ret)
+		return ret;
+
+	/*
+	 * Record the fact that the PCI device is enabled so that it can
+	 * be disabled during _detach().
+	 *
+	 * For this example driver, we assume PCI BAR 0 is the main I/O
+	 * region for the board registers and use dev->iobase to hold the
+	 * I/O base address and to indicate that the PCI device has been
+	 * enabled.
+	 *
+	 * (For boards with memory-mapped registers, dev->iobase is not
+	 * usually needed for register access, so can just be set to 1
+	 * to indicate that the PCI device has been enabled.)
+	 */
+	dev->iobase = pci_resource_start(pcidev, 0);
 
-	driver_skel_pci_driver.name = (char *)driver_skel.driver_name;
-	return pci_register_driver(&driver_skel_pci_driver);
+	/*
+	 * Call a common function to handle the remaining things to do for
+	 * attaching ISA or PCI boards.  (Extra parameters could be added
+	 * to pass additional information such as IRQ number.)
+	 */
+	return skel_common_attach(dev);
 }
 
-static void __exit driver_skel_cleanup_module(void)
+/*
+ * _detach is called to deconfigure a device.  It should deallocate
+ * resources.
+ * This function is also called when _attach() fails, so it should be
+ * careful not to release resources that were not necessarily
+ * allocated by _attach().  dev->private and dev->subdevices are
+ * deallocated automatically by the core.
+ */
+static void skel_detach(struct comedi_device *dev)
 {
-	pci_unregister_driver(&driver_skel_pci_driver);
-	comedi_driver_unregister(&driver_skel);
+	const struct skel_board *thisboard = comedi_board(dev);
+	struct skel_private *devpriv = dev->private;
+	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+
+	if (!thisboard || !devpriv)
+		return;
+
+/*
+ * Do common stuff such as freeing IRQ, unmapping remapped memory
+ * regions, etc., being careful to check that the stuff is valid given
+ * that _detach() is called even when _attach() or _auto_attach() return
+ * an error.
+ */
+
+	if (IS_ENABLED(CONFIG_COMEDI_PCI_DRIVERS) /* &&
+	    thisboard->bustype == pci_bustype */) {
+		/*
+		 * PCI board
+		 *
+		 * If PCI device enabled by _auto_attach() (or _attach()),
+		 * disable it here.
+		 */
+		if (pcidev && dev->iobase)
+			comedi_pci_disable(pcidev);
+	} else {
+		/*
+		 * ISA board
+		 *
+		 * If I/O regions successfully requested by _attach(),
+		 * release them here.
+		 */
+		if (dev->iobase)
+			release_region(dev->iobase, SKEL_SIZE);
+	}
 }
 
-module_init(driver_skel_init_module);
-module_exit(driver_skel_cleanup_module);
-#else
-static int __init driver_skel_init_module(void)
+/*
+ * The struct comedi_driver structure tells the Comedi core module
+ * which functions to call to configure/deconfigure (attach/detach)
+ * the board, and also about the kernel module that contains
+ * the device code.
+ */
+static struct comedi_driver skel_driver = {
+	.driver_name = "dummy",
+	.module = THIS_MODULE,
+	.attach = skel_attach,
+	.auto_attach = skel_auto_attach,
+	.detach = skel_detach,
+/* It is not necessary to implement the following members if you are
+ * writing a driver for a ISA PnP or PCI card */
+	/* Most drivers will support multiple types of boards by
+	 * having an array of board structures.  These were defined
+	 * in skel_boards[] above.  Note that the element 'name'
+	 * was first in the structure -- Comedi uses this fact to
+	 * extract the name of the board without knowing any details
+	 * about the structure except for its length.
+	 * When a device is attached (by comedi_config), the name
+	 * of the device is given to Comedi, and Comedi tries to
+	 * match it by going through the list of board names.  If
+	 * there is a match, the address of the pointer is put
+	 * into dev->board_ptr and driver->attach() is called.
+	 *
+	 * Note that these are not necessary if you can determine
+	 * the type of board in software.  ISA PnP, PCI, and PCMCIA
+	 * devices are such boards.
+	 */
+	.board_name = &skel_boards[0].name,
+	.offset = sizeof(struct skel_board),
+	.num_names = ARRAY_SIZE(skel_boards),
+};
+
+#ifdef CONFIG_COMEDI_PCI_DRIVERS
+
+/* This is used by modprobe to translate PCI IDs to drivers.  Should
+ * only be used for PCI and ISA-PnP devices */
+/* Please add your PCI vendor ID to comedidev.h, and it will be forwarded
+ * upstream. */
+#define PCI_VENDOR_ID_SKEL 0xdafe
+static DEFINE_PCI_DEVICE_TABLE(skel_pci_table) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_SKEL, 0x0100) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_SKEL, 0x0200) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, skel_pci_table);
+
+static int skel_pci_probe(struct pci_dev *dev,
+					   const struct pci_device_id *ent)
 {
-	return comedi_driver_register(&driver_skel);
+	return comedi_pci_auto_config(dev, &skel_driver);
 }
 
-static void __exit driver_skel_cleanup_module(void)
+static void skel_pci_remove(struct pci_dev *dev)
 {
-	comedi_driver_unregister(&driver_skel);
+	comedi_pci_auto_unconfig(dev);
 }
 
-module_init(driver_skel_init_module);
-module_exit(driver_skel_cleanup_module);
+static struct pci_driver skel_pci_driver = {
+	.id_table = skel_pci_table,
+	.probe = &skel_pci_probe,
+	.remove = &skel_pci_remove
+};
+module_comedi_pci_driver(skel_driver, skel_pci_driver);
+#else
+module_comedi_driver(skel_driver);
 #endif
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
index ae3aa1c..afa4016 100644
--- a/drivers/staging/comedi/drivers/ssv_dnp.c
+++ b/drivers/staging/comedi/drivers/ssv_dnp.c
@@ -50,15 +50,6 @@ Status: unknown
 #define PCMR  0xa3		/* Port C Mode Register                      */
 #define PCDR  0xa7		/* Port C Data Register                      */
 
-/* This data structure holds information about the supported boards -------- */
-
-struct dnp_board {
-	const char *name;
-	int ai_chans;
-	int ai_bits;
-	int have_dio;
-};
-
 /* ------------------------------------------------------------------------- */
 /* 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 */
@@ -173,11 +164,10 @@ static int dnp_dio_insn_config(struct comedi_device *dev,
 
 static int dnp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
-	const struct dnp_board *board = comedi_board(dev);
 	struct comedi_subdevice *s;
 	int ret;
 
-	dev->board_name = board->name;
+	dev->board_name = dev->driver->driver_name;
 
 	ret = comedi_alloc_subdevices(dev, 1);
 	if (ret)
@@ -219,23 +209,11 @@ static void dnp_detach(struct comedi_device *dev)
 	outb((inb(CSCDR) & 0xAA), CSCDR);
 }
 
-static const struct dnp_board dnp_boards[] = {
-	{
-		.name		= "dnp-1486",
-		.ai_chans	= 16,
-		.ai_bits	= 12,
-		.have_dio	= 1,
-	},
-};
-
 static struct comedi_driver dnp_driver = {
-	.driver_name	= "ssv_dnp",
+	.driver_name	= "dnp-1486",
 	.module		= THIS_MODULE,
 	.attach		= dnp_attach,
 	.detach		= dnp_detach,
-	.board_name	= &dnp_boards[0].name,
-	.offset		= sizeof(struct dnp_board),
-	.num_names	= ARRAY_SIZE(dnp_boards),
 };
 module_comedi_driver(dnp_driver);
 
diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c
index 9f1fdec..c9ded93 100644
--- a/drivers/staging/comedi/drivers/unioxx5.c
+++ b/drivers/staging/comedi/drivers/unioxx5.c
@@ -42,6 +42,8 @@ Devices: [Fastwel] UNIOxx-5 (unioxx5),
 
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "../comedidev.h"
 #include <linux/ioport.h>
 #include <linux/slab.h>
@@ -144,8 +146,7 @@ static int __unioxx5_digital_read(struct unioxx5_subd_priv *usp,
 
 	channel_offset = __unioxx5_define_chan_offset(channel);
 	if (channel_offset < 0) {
-		printk(KERN_ERR
-		       "comedi%d: undefined channel %d. channel range is 0 .. 23\n",
+		pr_err("comedi%d: undefined channel %d. channel range is 0 .. 23\n",
 		       minor, channel);
 		return 0;
 	}
@@ -171,8 +172,7 @@ static int __unioxx5_analog_read(struct unioxx5_subd_priv *usp,
 
 	/* defining if given module can work on input */
 	if (usp->usp_module_type[module_no] & MODULE_OUTPUT_MASK) {
-		printk(KERN_ERR
-		       "comedi%d: module in position %d with id 0x%02x is for output only",
+		pr_err("comedi%d: module in position %d with id 0x%02x is for output only",
 		       minor, module_no, usp->usp_module_type[module_no]);
 		return 0;
 	}
@@ -209,8 +209,7 @@ static int __unioxx5_digital_write(struct unioxx5_subd_priv *usp,
 
 	channel_offset = __unioxx5_define_chan_offset(channel);
 	if (channel_offset < 0) {
-		printk(KERN_ERR
-		       "comedi%d: undefined channel %d. channel range is 0 .. 23\n",
+		pr_err("comedi%d: undefined channel %d. channel range is 0 .. 23\n",
 		       minor, channel);
 		return 0;
 	}
@@ -240,8 +239,7 @@ static int __unioxx5_analog_write(struct unioxx5_subd_priv *usp,
 
 	/* defining if given module can work on output */
 	if (!(usp->usp_module_type[module] & MODULE_OUTPUT_MASK)) {
-		printk(KERN_ERR
-		       "comedi%d: module in position %d with id 0x%0x is for input only!\n",
+		pr_err("comedi%d: module in position %d with id 0x%0x is for input only!\n",
 		       minor, module, usp->usp_module_type[module]);
 		return 0;
 	}
@@ -323,17 +321,17 @@ static int unioxx5_insn_config(struct comedi_device *dev,
 	type = usp->usp_module_type[channel / 2];
 
 	if (type != MODULE_DIGITAL) {
-		printk(KERN_ERR
-		       "comedi%d: channel configuration accessible only for digital modules\n",
-		       dev->minor);
+		dev_err(dev->class_dev,
+			"comedi%d: channel configuration accessible only for digital modules\n",
+			dev->minor);
 		return -1;
 	}
 
 	channel_offset = __unioxx5_define_chan_offset(channel);
 	if (channel_offset < 0) {
-		printk(KERN_ERR
-		       "comedi%d: undefined channel %d. channel range is 0 .. 23\n",
-		       dev->minor, channel);
+		dev_err(dev->class_dev,
+			"comedi%d: undefined channel %d. channel range is 0 .. 23\n",
+			dev->minor, channel);
 		return -1;
 	}
 
@@ -348,7 +346,8 @@ static int unioxx5_insn_config(struct comedi_device *dev,
 		flags |= mask;
 		break;
 	default:
-		printk(KERN_ERR "comedi%d: unknown flag\n", dev->minor);
+		dev_err(dev->class_dev,
+			"comedi%d: unknown flag\n", dev->minor);
 		return -1;
 	}
 
@@ -375,19 +374,21 @@ static int __unioxx5_subdev_init(struct comedi_subdevice *subdev,
 	int i, to, ndef_flag = 0;
 
 	if (!request_region(subdev_iobase, UNIOXX5_SIZE, DRIVER_NAME)) {
-		printk(KERN_ERR "comedi%d: I/O port conflict\n", minor);
+		dev_err(subdev->class_dev,
+			"comedi%d: I/O port conflict\n", minor);
 		return -EIO;
 	}
 
 	usp = kzalloc(sizeof(*usp), GFP_KERNEL);
 
 	if (usp == NULL) {
-		printk(KERN_ERR "comedi%d: error! --> out of memory!\n", minor);
+		dev_err(subdev->class_dev,
+			"comedi%d: error! --> out of memory!\n", minor);
 		return -1;
 	}
 
 	usp->usp_iobase = subdev_iobase;
-	printk(KERN_INFO "comedi%d: |", minor);
+	dev_info(subdev->class_dev, "comedi%d: |", minor);
 
 	/* defining modules types */
 	for (i = 0; i < 12; i++) {
@@ -433,8 +434,6 @@ static int __unioxx5_subdev_init(struct comedi_subdevice *subdev,
 	/* for digital modules only!!! */
 	subdev->insn_config = unioxx5_insn_config;
 
-	printk(KERN_INFO "subdevice configured\n");
-
 	return 0;
 }
 
@@ -464,8 +463,8 @@ static int unioxx5_attach(struct comedi_device *dev,
 
 	/* unioxx5 can has from two to four subdevices */
 	if (n_subd < 2) {
-		printk(KERN_ERR
-		       "your card must has at least 2 'g01' subdevices\n");
+		dev_err(dev->class_dev,
+			"your card must has at least 2 'g01' subdevices\n");
 		return -1;
 	}
 
@@ -480,7 +479,6 @@ static int unioxx5_attach(struct comedi_device *dev,
 			return -1;
 	}
 
-	printk(KERN_INFO "attached\n");
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index b536bba..17b45eb 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -73,7 +73,7 @@ sampling rate. If you sample two channels you get 4kHz and so on.
  *       And loads of cleaning up, in particular streamlining the
  *       bulk transfers.
  * 1.1:  moved EP4 transfers to EP1 to make space for a PWM output on EP4
- * 1.2:  added PWM suport via EP4
+ * 1.2:  added PWM support via EP4
  * 2.0:  PWM seems to be stable and is not interfering with the other functions
  * 2.1:  changed PWM API
  * 2.2:  added firmware kernel request to fix an udev problem
@@ -938,9 +938,6 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
 	if (!(this_usbduxsub->probed))
 		return -ENODEV;
 
-	dev_dbg(&this_usbduxsub->interface->dev,
-		"comedi%d: usbdux_ai_cmdtest\n", dev->minor);
-
 	/* Step 1 : check if triggers are trivially valid */
 
 	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
@@ -962,19 +959,12 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->scan_begin_src == TRIG_FOLLOW) {
-		/* internal trigger */
-		if (cmd->scan_begin_arg != 0) {
-			cmd->scan_begin_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+
+	if (cmd->scan_begin_src == TRIG_FOLLOW)	/* internal trigger */
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		if (this_usbduxsub->high_speed) {
@@ -989,51 +979,35 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
 			while (i < (cmd->chanlist_len))
 				i = i * 2;
 
-			if (cmd->scan_begin_arg < (1000000 / 8 * i)) {
-				cmd->scan_begin_arg = 1000000 / 8 * i;
-				err++;
-			}
+			err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+							 1000000 / 8 * i);
 			/* now calc the real sampling rate with all the
 			 * rounding errors */
 			tmpTimer =
 			    ((unsigned int)(cmd->scan_begin_arg / 125000)) *
 			    125000;
-			if (cmd->scan_begin_arg != tmpTimer) {
-				cmd->scan_begin_arg = tmpTimer;
-				err++;
-			}
 		} else {
 			/* full speed */
 			/* 1kHz scans every USB frame */
-			if (cmd->scan_begin_arg < 1000000) {
-				cmd->scan_begin_arg = 1000000;
-				err++;
-			}
+			err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+							 1000000);
 			/*
 			 * calc the real sampling rate with the rounding errors
 			 */
 			tmpTimer = ((unsigned int)(cmd->scan_begin_arg /
 						   1000000)) * 1000000;
-			if (cmd->scan_begin_arg != tmpTimer) {
-				cmd->scan_begin_arg = tmpTimer;
-				err++;
-			}
 		}
-	}
-	/* the same argument */
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg,
+						tmpTimer);
 	}
 
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
 	if (cmd->stop_src == TRIG_COUNT) {
 		/* any count is allowed */
 	} else {
 		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 	}
 
 	if (err)
@@ -1472,9 +1446,6 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev,
 	if (!(this_usbduxsub->probed))
 		return -ENODEV;
 
-	dev_dbg(&this_usbduxsub->interface->dev,
-		"comedi%d: usbdux_ao_cmdtest\n", dev->minor);
-
 	/* Step 1 : check if triggers are trivially valid */
 
 	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
@@ -1519,57 +1490,30 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->scan_begin_src == TRIG_FOLLOW) {
-		/* internal trigger */
-		if (cmd->scan_begin_arg != 0) {
-			cmd->scan_begin_arg = 0;
-			err++;
-		}
-	}
+	if (cmd->scan_begin_src == TRIG_FOLLOW)	/* internal trigger */
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+
+	if (cmd->scan_begin_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						 1000000);
 
-	if (cmd->scan_begin_src == TRIG_TIMER) {
-		/* timer */
-		if (cmd->scan_begin_arg < 1000000) {
-			cmd->scan_begin_arg = 1000000;
-			err++;
-		}
-	}
 	/* not used now, is for later use */
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < 125000) {
-			cmd->convert_arg = 125000;
-			err++;
-		}
-	}
+	if (cmd->convert_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 125000);
 
-	/* the same argument */
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 
 	if (cmd->stop_src == TRIG_COUNT) {
 		/* any count is allowed */
 	} else {
 		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 	}
 
-	dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: err=%d, "
-		"scan_begin_src=%d, scan_begin_arg=%d, convert_src=%d, "
-		"convert_arg=%d\n", dev->minor, err, cmd->scan_begin_src,
-		cmd->scan_begin_arg, cmd->convert_src, cmd->convert_arg);
-
 	if (err)
 		return 3;
 
@@ -2375,9 +2319,10 @@ static int usbdux_attach_common(struct comedi_device *dev,
 	return 0;
 }
 
-static int usbdux_attach_usb(struct comedi_device *dev,
-			     struct usb_interface *uinterf)
+static int usbdux_auto_attach(struct comedi_device *dev,
+			      unsigned long context_unused)
 {
+	struct usb_interface *uinterf = comedi_to_usb_interface(dev);
 	int ret;
 	struct usbduxsub *this_usbduxsub;
 
@@ -2386,14 +2331,12 @@ static int usbdux_attach_usb(struct comedi_device *dev,
 	down(&start_stop_sem);
 	this_usbduxsub = usb_get_intfdata(uinterf);
 	if (!this_usbduxsub || !this_usbduxsub->probed) {
-		printk(KERN_ERR
-		       "comedi%d: usbdux: error: attach_usb failed, not connected\n",
-		       dev->minor);
+		dev_err(dev->class_dev,
+			"usbdux: error: auto_attach failed, not connected\n");
 		ret = -ENODEV;
 	} else if (this_usbduxsub->attached) {
-		printk(KERN_ERR
-		       "comedi%d: usbdux: error: attach_usb failed, already attached\n",
-		       dev->minor);
+		dev_err(dev->class_dev,
+			"error: auto_attach failed, already attached\n");
 		ret = -ENODEV;
 	} else
 		ret = usbdux_attach_common(dev, this_usbduxsub);
@@ -2417,7 +2360,7 @@ static void usbdux_detach(struct comedi_device *dev)
 static struct comedi_driver usbdux_driver = {
 	.driver_name	= "usbdux",
 	.module		= THIS_MODULE,
-	.attach_usb	= usbdux_attach_usb,
+	.auto_attach	= usbdux_auto_attach,
 	.detach		= usbdux_detach,
 };
 
diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
index 1154a7e..4e19f61 100644
--- a/drivers/staging/comedi/drivers/usbduxfast.c
+++ b/drivers/staging/comedi/drivers/usbduxfast.c
@@ -37,6 +37,8 @@
  *       udev coldplug problem
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/firmware.h>
 #include <linux/module.h>
@@ -216,8 +218,9 @@ static int send_dux_commands(struct usbduxfastsub_s *udfs, int cmd_type)
 			   usb_sndbulkpipe(udfs->usbdev, CHANNELLISTEP),
 			   udfs->dux_commands, SIZEOFDUXBUFFER, &nsent, 10000);
 	if (tmp < 0)
-		printk(KERN_ERR "comedi%d: could not transmit dux_commands to"
-		       "the usb-device, err=%d\n", udfs->comedidev->minor, tmp);
+		dev_err(&udfs->interface->dev,
+			"could not transmit dux_commands to the usb-device, err=%d\n",
+			tmp);
 	return tmp;
 }
 
@@ -252,7 +255,7 @@ static int usbduxfast_ai_stop(struct usbduxfastsub_s *udfs, int do_unlink)
 	int ret = 0;
 
 	if (!udfs) {
-		printk(KERN_ERR "comedi?: usbduxfast_ai_stop: udfs=NULL!\n");
+		pr_err("%s: udfs=NULL!\n", __func__);
 		return -EFAULT;
 	}
 #ifdef CONFIG_COMEDI_DEBUG
@@ -284,7 +287,7 @@ static int usbduxfast_ai_cancel(struct comedi_device *dev,
 #endif
 	udfs = dev->private;
 	if (!udfs) {
-		printk(KERN_ERR "comedi: usbduxfast_ai_cancel: udfs=NULL\n");
+		dev_err(dev->class_dev, "%s: udfs=NULL\n", __func__);
 		return -EFAULT;
 	}
 	down(&udfs->sem);
@@ -309,26 +312,22 @@ static void usbduxfastsub_ai_Irq(struct urb *urb)
 	struct usbduxfastsub_s *udfs;
 	struct comedi_device *this_comedidev;
 	struct comedi_subdevice *s;
-	uint16_t *p;
 
 	/* sanity checks - is the urb there? */
 	if (!urb) {
-		printk(KERN_ERR "comedi_: usbduxfast_: ao int-handler called "
-		       "with urb=NULL!\n");
+		pr_err("ao int-handler called with urb=NULL!\n");
 		return;
 	}
 	/* the context variable points to the subdevice */
 	this_comedidev = urb->context;
 	if (!this_comedidev) {
-		printk(KERN_ERR "comedi_: usbduxfast_: urb context is a NULL "
-		       "pointer!\n");
+		pr_err("urb context is a NULL pointer!\n");
 		return;
 	}
 	/* the private structure of the subdevice is usbduxfastsub_s */
 	udfs = this_comedidev->private;
 	if (!udfs) {
-		printk(KERN_ERR "comedi_: usbduxfast_: private of comedi "
-		       "subdev is a NULL pointer!\n");
+		pr_err("private of comedi subdev is a NULL pointer!\n");
 		return;
 	}
 	/* are we running a command? */
@@ -370,9 +369,8 @@ static void usbduxfastsub_ai_Irq(struct urb *urb)
 		return;
 
 	default:
-		printk("comedi%d: usbduxfast: non-zero urb status received in "
-		       "ai intr context: %d\n",
-		       udfs->comedidev->minor, urb->status);
+		pr_err("non-zero urb status received in ai intr context: %d\n",
+		       urb->status);
 		s->async->events |= COMEDI_CB_EOA;
 		s->async->events |= COMEDI_CB_ERROR;
 		comedi_event(udfs->comedidev, s);
@@ -380,7 +378,6 @@ static void usbduxfastsub_ai_Irq(struct urb *urb)
 		return;
 	}
 
-	p = urb->transfer_buffer;
 	if (!udfs->ignore) {
 		if (!udfs->ai_continous) {
 			/* not continuous, fixed number of samples */
@@ -427,8 +424,8 @@ static void usbduxfastsub_ai_Irq(struct urb *urb)
 	urb->status = 0;
 	err = usb_submit_urb(urb, GFP_ATOMIC);
 	if (err < 0) {
-		printk(KERN_ERR "comedi%d: usbduxfast: urb resubm failed: %d",
-		       udfs->comedidev->minor, err);
+		dev_err(&urb->dev->dev,
+			"urb resubm failed: %d", err);
 		s->async->events |= COMEDI_CB_EOA;
 		s->async->events |= COMEDI_CB_ERROR;
 		comedi_event(udfs->comedidev, s);
@@ -454,7 +451,8 @@ static int usbduxfastsub_start(struct usbduxfastsub_s *udfs)
 			      1,      /* Length */
 			      EZTIMEOUT);    /* Timeout */
 	if (ret < 0) {
-		printk("comedi_: usbduxfast_: control msg failed (start)\n");
+		dev_err(&udfs->interface->dev,
+			"control msg failed (start)\n");
 		return ret;
 	}
 
@@ -477,8 +475,8 @@ static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs)
 			      local_transfer_buffer, 1,	/* Length */
 			      EZTIMEOUT);	/* Timeout */
 	if (ret < 0) {
-		printk(KERN_ERR "comedi_: usbduxfast: control msg failed "
-		       "(stop)\n");
+		dev_err(&udfs->interface->dev,
+			"control msg failed (stop)\n");
 		return ret;
 	}
 
@@ -512,7 +510,7 @@ static int usbduxfastsub_upload(struct usbduxfastsub_s *udfs,
 #endif
 
 	if (ret < 0) {
-		printk(KERN_ERR "comedi_: usbduxfast: uppload failed\n");
+		dev_err(&udfs->interface->dev, "uppload failed\n");
 		return ret;
 	}
 
@@ -538,8 +536,8 @@ static int usbduxfastsub_submit_InURBs(struct usbduxfastsub_s *udfs)
 #endif
 	ret = usb_submit_urb(udfs->urbIn, GFP_ATOMIC);
 	if (ret) {
-		printk(KERN_ERR "comedi_: usbduxfast: ai: usb_submit_urb error"
-		       " %d\n", ret);
+		dev_err(&udfs->interface->dev,
+			"ai: usb_submit_urb error %d\n", ret);
 		return ret;
 	}
 	return 0;
@@ -557,12 +555,6 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
 	if (!udfs->probed)
 		return -ENODEV;
 
-#ifdef CONFIG_COMEDI_DEBUG
-	printk(KERN_DEBUG "comedi%d: usbduxfast_ai_cmdtest\n", dev->minor);
-	printk(KERN_DEBUG "comedi%d: usbduxfast: convert_arg=%u "
-	       "scan_begin_arg=%u\n",
-	       dev->minor, cmd->convert_arg, cmd->scan_begin_arg);
-#endif
 	/* Step 1 : check if triggers are trivially valid */
 
 	err |= cfc_check_trigger_src(&cmd->start_src,
@@ -592,20 +584,15 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_src == TRIG_NOW && cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	if (cmd->start_src == TRIG_NOW)
+		err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
 	if (!cmd->chanlist_len)
-		err++;
+		err |= -EINVAL;
 
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 
 	if (cmd->chanlist_len == 1)
 		minSamplPer = 1;
@@ -622,28 +609,19 @@ static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
 
 		/* calc arg again */
 		tmp = steps / 30;
-		if (cmd->convert_arg != tmp) {
-			cmd->convert_arg = tmp;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, tmp);
 	}
 
 	if (cmd->scan_begin_src == TRIG_TIMER)
-		err++;
+		err |= -EINVAL;
 
 	/* stop source */
 	switch (cmd->stop_src) {
 	case TRIG_COUNT:
-		if (!cmd->stop_arg) {
-			cmd->stop_arg = 1;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
 		break;
 	case TRIG_NONE:
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 		break;
 		/*
 		 * TRIG_EXT doesn't care since it doesn't trigger
@@ -682,8 +660,7 @@ static int usbduxfast_ai_inttrig(struct comedi_device *dev,
 #endif
 
 	if (trignum != 0) {
-		printk(KERN_ERR "comedi%d: usbduxfast_ai_inttrig: invalid"
-		       " trignum\n", dev->minor);
+		dev_err(dev->class_dev, "%s: invalid trignum\n", __func__);
 		up(&udfs->sem);
 		return -EINVAL;
 	}
@@ -691,16 +668,16 @@ static int usbduxfast_ai_inttrig(struct comedi_device *dev,
 		udfs->ai_cmd_running = 1;
 		ret = usbduxfastsub_submit_InURBs(udfs);
 		if (ret < 0) {
-			printk(KERN_ERR "comedi%d: usbduxfast_ai_inttrig: "
-			       "urbSubmit: err=%d\n", dev->minor, ret);
+			dev_err(dev->class_dev,
+				"%s: urbSubmit: err=%d\n", __func__, ret);
 			udfs->ai_cmd_running = 0;
 			up(&udfs->sem);
 			return ret;
 		}
 		s->async->inttrig = NULL;
 	} else {
-		printk(KERN_ERR "comedi%d: ai_inttrig but acqu is already"
-		       " running\n", dev->minor);
+		dev_err(dev->class_dev,
+			"ai_inttrig but acqu is already running\n");
 	}
 	up(&udfs->sem);
 	return 1;
@@ -738,8 +715,8 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 		return -ENODEV;
 	}
 	if (udfs->ai_cmd_running) {
-		printk(KERN_ERR "comedi%d: ai_cmd not possible. Another ai_cmd"
-		       " is running.\n", dev->minor);
+		dev_err(dev->class_dev,
+			"ai_cmd not possible. Another ai_cmd is running.\n");
 		up(&udfs->sem);
 		return -EBUSY;
 	}
@@ -757,31 +734,29 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 		for (i = 0; i < cmd->chanlist_len; ++i) {
 			chan = CR_CHAN(cmd->chanlist[i]);
 			if (chan != i) {
-				printk(KERN_ERR "comedi%d: cmd is accepting "
-				       "only consecutive channels.\n",
-				       dev->minor);
+				dev_err(dev->class_dev,
+					"cmd is accepting only consecutive channels.\n");
 				up(&udfs->sem);
 				return -EINVAL;
 			}
 			if ((gain != CR_RANGE(cmd->chanlist[i]))
 			    && (cmd->chanlist_len > 3)) {
-				printk(KERN_ERR "comedi%d: the gain must be"
-				       " the same for all channels.\n",
-				       dev->minor);
+				dev_err(dev->class_dev,
+					"the gain must be the same for all channels.\n");
 				up(&udfs->sem);
 				return -EINVAL;
 			}
 			if (i >= NUMCHANNELS) {
-				printk(KERN_ERR "comedi%d: channel list too"
-				       " long\n", dev->minor);
+				dev_err(dev->class_dev,
+					"channel list too long\n");
 				break;
 			}
 		}
 	}
 	steps = 0;
 	if (cmd->scan_begin_src == TRIG_TIMER) {
-		printk(KERN_ERR "comedi%d: usbduxfast: "
-		       "scan_begin_src==TRIG_TIMER not valid.\n", dev->minor);
+		dev_err(dev->class_dev,
+			"scan_begin_src==TRIG_TIMER not valid.\n");
 		up(&udfs->sem);
 		return -EINVAL;
 	}
@@ -789,22 +764,21 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 		steps = (cmd->convert_arg * 30) / 1000;
 
 	if ((steps < MIN_SAMPLING_PERIOD) && (cmd->chanlist_len != 1)) {
-		printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: steps=%ld, "
-		       "scan_begin_arg=%d. Not properly tested by cmdtest?\n",
-		       dev->minor, steps, cmd->scan_begin_arg);
+		dev_err(dev->class_dev,
+			"ai_cmd: steps=%ld, scan_begin_arg=%d. Not properly tested by cmdtest?\n",
+			steps, cmd->scan_begin_arg);
 		up(&udfs->sem);
 		return -EINVAL;
 	}
 	if (steps > MAX_SAMPLING_PERIOD) {
-		printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: sampling rate "
-		       "too low.\n", dev->minor);
+		dev_err(dev->class_dev, "ai_cmd: sampling rate too low.\n");
 		up(&udfs->sem);
 		return -EINVAL;
 	}
 	if ((cmd->start_src == TRIG_EXT) && (cmd->chanlist_len != 1)
 	    && (cmd->chanlist_len != 16)) {
-		printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: TRIG_EXT only"
-		       " with 1 or 16 channels possible.\n", dev->minor);
+		dev_err(dev->class_dev,
+			"ai_cmd: TRIG_EXT only with 1 or 16 channels possible.\n");
 		up(&udfs->sem);
 		return -EINVAL;
 	}
@@ -1121,8 +1095,7 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 		break;
 
 	default:
-		printk(KERN_ERR "comedi %d: unsupported combination of "
-		       "channels\n", dev->minor);
+		dev_err(dev->class_dev, "unsupported combination of channels\n");
 		up(&udfs->sem);
 		return -EFAULT;
 	}
@@ -1134,17 +1107,16 @@ static int usbduxfast_ai_cmd(struct comedi_device *dev,
 	/* 0 means that the AD commands are sent */
 	result = send_dux_commands(udfs, SENDADCOMMANDS);
 	if (result < 0) {
-		printk(KERN_ERR "comedi%d: adc command could not be submitted."
-		       "Aborting...\n", dev->minor);
+		dev_err(dev->class_dev,
+			"adc command could not be submitted. Aborting...\n");
 		up(&udfs->sem);
 		return result;
 	}
 	if (cmd->stop_src == TRIG_COUNT) {
 		udfs->ai_sample_count = cmd->stop_arg * cmd->scan_end_arg;
 		if (udfs->ai_sample_count < 1) {
-			printk(KERN_ERR "comedi%d: "
-			       "(cmd->stop_arg)*(cmd->scan_end_arg)<1, "
-			       "aborting.\n", dev->minor);
+			dev_err(dev->class_dev,
+				"(cmd->stop_arg)*(cmd->scan_end_arg)<1, aborting.\n");
 			up(&udfs->sem);
 			return -EFAULT;
 		}
@@ -1193,8 +1165,7 @@ static int usbduxfast_ai_insn_read(struct comedi_device *dev,
 
 	udfs = dev->private;
 	if (!udfs) {
-		printk(KERN_ERR "comedi%d: ai_insn_read: no usb dev.\n",
-		       dev->minor);
+		dev_err(dev->class_dev, "%s: no usb dev.\n", __func__);
 		return -ENODEV;
 	}
 #ifdef CONFIG_COMEDI_DEBUG
@@ -1207,8 +1178,8 @@ static int usbduxfast_ai_insn_read(struct comedi_device *dev,
 		return -ENODEV;
 	}
 	if (udfs->ai_cmd_running) {
-		printk(KERN_ERR "comedi%d: ai_insn_read not possible. Async "
-		       "Command is running.\n", dev->minor);
+		dev_err(dev->class_dev,
+			"ai_insn_read not possible. Async Command is running.\n");
 		up(&udfs->sem);
 		return -EBUSY;
 	}
@@ -1268,8 +1239,8 @@ static int usbduxfast_ai_insn_read(struct comedi_device *dev,
 	/* 0 means that the AD commands are sent */
 	err = send_dux_commands(udfs, SENDADCOMMANDS);
 	if (err < 0) {
-		printk(KERN_ERR "comedi%d: adc command could not be submitted."
-		       "Aborting...\n", dev->minor);
+		dev_err(dev->class_dev,
+			"adc command could not be submitted. Aborting...\n");
 		up(&udfs->sem);
 		return err;
 	}
@@ -1284,8 +1255,7 @@ static int usbduxfast_ai_insn_read(struct comedi_device *dev,
 				   udfs->transfer_buffer, SIZEINBUF,
 				   &actual_length, 10000);
 		if (err < 0) {
-			printk(KERN_ERR "comedi%d: insn timeout. No data.\n",
-			       dev->minor);
+			dev_err(dev->class_dev, "insn timeout. No data.\n");
 			up(&udfs->sem);
 			return err;
 		}
@@ -1297,15 +1267,13 @@ static int usbduxfast_ai_insn_read(struct comedi_device *dev,
 				   udfs->transfer_buffer, SIZEINBUF,
 				   &actual_length, 10000);
 		if (err < 0) {
-			printk(KERN_ERR "comedi%d: insn data error: %d\n",
-			       dev->minor, err);
+			dev_err(dev->class_dev, "insn data error: %d\n", err);
 			up(&udfs->sem);
 			return err;
 		}
 		n = actual_length / sizeof(uint16_t);
 		if ((n % 16) != 0) {
-			printk(KERN_ERR "comedi%d: insn data packet "
-			       "corrupted.\n", dev->minor);
+			dev_err(dev->class_dev, "insn data packet corrupted.\n");
 			up(&udfs->sem);
 			return -EINVAL;
 		}
@@ -1454,9 +1422,10 @@ static int usbduxfast_attach_common(struct comedi_device *dev,
 	return 0;
 }
 
-static int usbduxfast_attach_usb(struct comedi_device *dev,
-				 struct usb_interface *uinterf)
+static int usbduxfast_auto_attach(struct comedi_device *dev,
+				  unsigned long context_unused)
 {
+	struct usb_interface *uinterf = comedi_to_usb_interface(dev);
 	int ret;
 	struct usbduxfastsub_s *udfs;
 
@@ -1465,11 +1434,11 @@ static int usbduxfast_attach_usb(struct comedi_device *dev,
 	udfs = usb_get_intfdata(uinterf);
 	if (!udfs || !udfs->probed) {
 		dev_err(dev->class_dev,
-			"usbduxfast: error: attach_usb failed, not connected\n");
+			"usbduxfast: error: auto_attach failed, not connected\n");
 		ret = -ENODEV;
 	} else if (udfs->attached) {
 		dev_err(dev->class_dev,
-		       "usbduxfast: error: attach_usb failed, already attached\n");
+		       "usbduxfast: error: auto_attach failed, already attached\n");
 		ret = -ENODEV;
 	} else
 		ret = usbduxfast_attach_common(dev, udfs);
@@ -1495,7 +1464,7 @@ static void usbduxfast_detach(struct comedi_device *dev)
 static struct comedi_driver usbduxfast_driver = {
 	.driver_name	= "usbduxfast",
 	.module		= THIS_MODULE,
-	.attach_usb	= usbduxfast_attach_usb,
+	.auto_attach	= usbduxfast_auto_attach,
 	.detach		= usbduxfast_detach,
 };
 
@@ -1535,8 +1504,8 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf,
 	int ret;
 
 	if (udev->speed != USB_SPEED_HIGH) {
-		printk(KERN_ERR "comedi_: usbduxfast_: This driver needs"
-		       "USB 2.0 to operate. Aborting...\n");
+		dev_err(&uinterf->dev,
+			"This driver needs USB 2.0 to operate. Aborting...\n");
 		return -ENODEV;
 	}
 #ifdef CONFIG_COMEDI_DEBUG
@@ -1555,7 +1524,8 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf,
 
 	/* no more space */
 	if (index == -1) {
-		printk(KERN_ERR "Too many usbduxfast-devices connected.\n");
+		dev_err(&uinterf->dev,
+			"Too many usbduxfast-devices connected.\n");
 		up(&start_stop_sem);
 		return -EMFILE;
 	}
@@ -1586,8 +1556,8 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf,
 	usbduxfastsub[index].dux_commands = kmalloc(SIZEOFDUXBUFFER,
 						    GFP_KERNEL);
 	if (!usbduxfastsub[index].dux_commands) {
-		printk(KERN_ERR "comedi_: usbduxfast: error alloc space for "
-		       "dac commands\n");
+		dev_err(&uinterf->dev,
+			"error alloc space for dac commands\n");
 		tidy_up(&(usbduxfastsub[index]));
 		up(&start_stop_sem);
 		return -ENOMEM;
@@ -1595,8 +1565,8 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf,
 	/* create space of the instruction buffer */
 	usbduxfastsub[index].insnBuffer = kmalloc(SIZEINSNBUF, GFP_KERNEL);
 	if (!usbduxfastsub[index].insnBuffer) {
-		printk(KERN_ERR "comedi_: usbduxfast: could not alloc space "
-		       "for insnBuffer\n");
+		dev_err(&uinterf->dev,
+			"could not alloc space for insnBuffer\n");
 		tidy_up(&(usbduxfastsub[index]));
 		up(&start_stop_sem);
 		return -ENOMEM;
@@ -1605,24 +1575,25 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf,
 	i = usb_set_interface(usbduxfastsub[index].usbdev,
 			      usbduxfastsub[index].ifnum, 1);
 	if (i < 0) {
-		printk(KERN_ERR "comedi_: usbduxfast%d: could not switch to "
-		       "alternate setting 1.\n", index);
+		dev_err(&uinterf->dev,
+			"usbduxfast%d: could not switch to alternate setting 1.\n",
+			index);
 		tidy_up(&(usbduxfastsub[index]));
 		up(&start_stop_sem);
 		return -ENODEV;
 	}
 	usbduxfastsub[index].urbIn = usb_alloc_urb(0, GFP_KERNEL);
 	if (!usbduxfastsub[index].urbIn) {
-		printk(KERN_ERR "comedi_: usbduxfast%d: Could not alloc."
-		       "urb\n", index);
+		dev_err(&uinterf->dev,
+			"usbduxfast%d: Could not alloc. urb\n", index);
 		tidy_up(&(usbduxfastsub[index]));
 		up(&start_stop_sem);
 		return -ENOMEM;
 	}
 	usbduxfastsub[index].transfer_buffer = kmalloc(SIZEINBUF, GFP_KERNEL);
 	if (!usbduxfastsub[index].transfer_buffer) {
-		printk(KERN_ERR "comedi_: usbduxfast%d: could not alloc. "
-		       "transb.\n", index);
+		dev_err(&uinterf->dev,
+			"usbduxfast%d: could not alloc. transb.\n", index);
 		tidy_up(&(usbduxfastsub[index]));
 		up(&start_stop_sem);
 		return -ENOMEM;
@@ -1640,12 +1611,12 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf,
 				      usbduxfast_firmware_request_complete_handler);
 
 	if (ret) {
-		dev_err(&udev->dev, "could not load firmware (err=%d)\n", ret);
+		dev_err(&uinterf->dev, "could not load firmware (err=%d)\n", ret);
 		return ret;
 	}
 
-	printk(KERN_INFO "comedi_: usbduxfast%d has been successfully "
-	       "initialized.\n", index);
+	dev_info(&uinterf->dev,
+		 "usbduxfast%d has been successfully initialized.\n", index);
 	/* success */
 	return 0;
 }
@@ -1656,13 +1627,11 @@ static void usbduxfast_usb_disconnect(struct usb_interface *intf)
 	struct usb_device *udev = interface_to_usbdev(intf);
 
 	if (!udfs) {
-		printk(KERN_ERR "comedi_: usbduxfast: disconnect called with "
-		       "null pointer.\n");
+		dev_err(&intf->dev, "disconnect called with null pointer.\n");
 		return;
 	}
 	if (udfs->usbdev != udev) {
-		printk(KERN_ERR "comedi_: usbduxfast: BUG! called with wrong "
-		       "ptr!!!\n");
+		dev_err(&intf->dev, "BUG! called with wrong ptr!!!\n");
 		return;
 	}
 
diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c
index b169412..cdd279b 100644
--- a/drivers/staging/comedi/drivers/usbduxsigma.c
+++ b/drivers/staging/comedi/drivers/usbduxsigma.c
@@ -904,9 +904,6 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
 	if (!(this_usbduxsub->probed))
 		return -ENODEV;
 
-	dev_dbg(&this_usbduxsub->interface->dev,
-		"comedi%d: usbdux_ai_cmdtest\n", dev->minor);
-
 	/* Step 1 : check if triggers are trivially valid */
 
 	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
@@ -928,19 +925,12 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->scan_begin_src == TRIG_FOLLOW) {
-		/* internal trigger */
-		if (cmd->scan_begin_arg != 0) {
-			cmd->scan_begin_arg = 0;
-			err++;
-		}
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+
+	if (cmd->scan_begin_src == TRIG_FOLLOW)	/* internal trigger */
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		if (this_usbduxsub->high_speed) {
@@ -951,51 +941,35 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev,
 			 * are in the channel list the more time we need.
 			 */
 			i = chanToInterval(cmd->chanlist_len);
-			if (cmd->scan_begin_arg < (1000000 / 8 * i)) {
-				cmd->scan_begin_arg = 1000000 / 8 * i;
-				err++;
-			}
+			err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+							 (1000000 / 8 * i));
 			/* now calc the real sampling rate with all the
 			 * rounding errors */
 			tmpTimer =
 			    ((unsigned int)(cmd->scan_begin_arg / 125000)) *
 			    125000;
-			if (cmd->scan_begin_arg != tmpTimer) {
-				cmd->scan_begin_arg = tmpTimer;
-				err++;
-			}
 		} else {
 			/* full speed */
 			/* 1kHz scans every USB frame */
-			if (cmd->scan_begin_arg < 1000000) {
-				cmd->scan_begin_arg = 1000000;
-				err++;
-			}
+			err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+							 1000000);
 			/*
 			 * calc the real sampling rate with the rounding errors
 			 */
 			tmpTimer = ((unsigned int)(cmd->scan_begin_arg /
 						   1000000)) * 1000000;
-			if (cmd->scan_begin_arg != tmpTimer) {
-				cmd->scan_begin_arg = tmpTimer;
-				err++;
-			}
 		}
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg,
+						tmpTimer);
 	}
-	/* the same argument */
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 
 	if (cmd->stop_src == TRIG_COUNT) {
 		/* any count is allowed */
 	} else {
 		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 	}
 
 	if (err)
@@ -1576,57 +1550,30 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 2;
 
-	/* step 3: make sure arguments are trivially compatible */
+	/* Step 3: check if arguments are trivially valid */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 
-	if (cmd->scan_begin_src == TRIG_FOLLOW) {
-		/* internal trigger */
-		if (cmd->scan_begin_arg != 0) {
-			cmd->scan_begin_arg = 0;
-			err++;
-		}
-	}
+	if (cmd->scan_begin_src == TRIG_FOLLOW)	/* internal trigger */
+		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+
+	if (cmd->scan_begin_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+						 1000000);
 
-	if (cmd->scan_begin_src == TRIG_TIMER) {
-		/* timer */
-		if (cmd->scan_begin_arg < 1000000) {
-			cmd->scan_begin_arg = 1000000;
-			err++;
-		}
-	}
 	/* not used now, is for later use */
-	if (cmd->convert_src == TRIG_TIMER) {
-		if (cmd->convert_arg < 125000) {
-			cmd->convert_arg = 125000;
-			err++;
-		}
-	}
+	if (cmd->convert_src == TRIG_TIMER)
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 125000);
 
-	/* the same argument */
-	if (cmd->scan_end_arg != cmd->chanlist_len) {
-		cmd->scan_end_arg = cmd->chanlist_len;
-		err++;
-	}
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 
 	if (cmd->stop_src == TRIG_COUNT) {
 		/* any count is allowed */
 	} else {
 		/* TRIG_NONE */
-		if (cmd->stop_arg != 0) {
-			cmd->stop_arg = 0;
-			err++;
-		}
+		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 	}
 
-	dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: err=%d, "
-		"scan_begin_src=%d, scan_begin_arg=%d, convert_src=%d, "
-		"convert_arg=%d\n", dev->minor, err, cmd->scan_begin_src,
-		cmd->scan_begin_arg, cmd->convert_src, cmd->convert_arg);
-
 	if (err)
 		return 3;
 
@@ -2359,9 +2306,10 @@ static int usbduxsigma_attach_common(struct comedi_device *dev,
 	return 0;
 }
 
-static int usbduxsigma_attach_usb(struct comedi_device *dev,
-				  struct usb_interface *uinterf)
+static int usbduxsigma_auto_attach(struct comedi_device *dev,
+				   unsigned long context_unused)
 {
+	struct usb_interface *uinterf = comedi_to_usb_interface(dev);
 	int ret;
 	struct usbduxsub *uds;
 
@@ -2370,11 +2318,11 @@ static int usbduxsigma_attach_usb(struct comedi_device *dev,
 	uds = usb_get_intfdata(uinterf);
 	if (!uds || !uds->probed) {
 		dev_err(dev->class_dev,
-			"usbduxsigma: error: attach_usb failed, not connected\n");
+			"usbduxsigma: error: auto_attach failed, not connected\n");
 		ret = -ENODEV;
 	} else if (uds->attached) {
 		dev_err(dev->class_dev,
-		       "usbduxsigma: error: attach_usb failed, already attached\n");
+		       "usbduxsigma: error: auto_attach failed, already attached\n");
 		ret = -ENODEV;
 	} else
 		ret = usbduxsigma_attach_common(dev, uds);
@@ -2398,7 +2346,7 @@ static void usbduxsigma_detach(struct comedi_device *dev)
 static struct comedi_driver usbduxsigma_driver = {
 	.driver_name	= "usbduxsigma",
 	.module		= THIS_MODULE,
-	.attach_usb	= usbduxsigma_attach_usb,
+	.auto_attach	= usbduxsigma_auto_attach,
 	.detach		= usbduxsigma_detach,
 };
 
diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c
index df277aa..609dc69 100644
--- a/drivers/staging/comedi/drivers/vmk80xx.c
+++ b/drivers/staging/comedi/drivers/vmk80xx.c
@@ -1209,9 +1209,10 @@ static int vmk80xx_attach(struct comedi_device *cdev,
 }
 
 /* called via comedi_usb_auto_config() */
-static int vmk80xx_attach_usb(struct comedi_device *cdev,
-			      struct usb_interface *intf)
+static int vmk80xx_auto_attach(struct comedi_device *cdev,
+			       unsigned long context_unused)
 {
+	struct usb_interface *intf = comedi_to_usb_interface(cdev);
 	int i;
 	int ret;
 
@@ -1246,7 +1247,7 @@ static struct comedi_driver vmk80xx_driver = {
 	.driver_name	= "vmk80xx",
 	.attach		= vmk80xx_attach,
 	.detach		= vmk80xx_detach,
-	.attach_usb	= vmk80xx_attach_usb,
+	.auto_attach	= vmk80xx_auto_attach,
 };
 
 static int vmk80xx_usb_probe(struct usb_interface *intf,
@@ -1371,12 +1372,11 @@ static int vmk80xx_usb_probe(struct usb_interface *intf,
 
 	if (dev->board.model == VMK8061_MODEL) {
 		vmk80xx_read_eeprom(dev, IC3_VERSION);
-		printk(KERN_INFO "comedi#: vmk80xx: %s\n", dev->fw.ic3_vers);
+		dev_info(&intf->dev, "%s\n", dev->fw.ic3_vers);
 
 		if (vmk80xx_check_data_link(dev)) {
 			vmk80xx_read_eeprom(dev, IC6_VERSION);
-			printk(KERN_INFO "comedi#: vmk80xx: %s\n",
-			       dev->fw.ic6_vers);
+			dev_info(&intf->dev, "%s\n", dev->fw.ic6_vers);
 		} else {
 			dbgcm("comedi#: vmk80xx: no conn. to CPU\n");
 		}
@@ -1387,8 +1387,8 @@ static int vmk80xx_usb_probe(struct usb_interface *intf,
 
 	dev->probed = 1;
 
-	printk(KERN_INFO "comedi#: vmk80xx: board #%d [%s] now attached\n",
-	       dev->count, dev->board.name);
+	dev_info(&intf->dev, "board #%d [%s] now attached\n",
+		 dev->count, dev->board.name);
 
 	mutex_unlock(&glb_mutex);
 
@@ -1422,8 +1422,8 @@ static void vmk80xx_usb_disconnect(struct usb_interface *intf)
 	kfree(dev->usb_rx_buf);
 	kfree(dev->usb_tx_buf);
 
-	printk(KERN_INFO "comedi#: vmk80xx: board #%d [%s] now detached\n",
-	       dev->count, dev->board.name);
+	dev_info(&intf->dev, "board #%d [%s] now detached\n",
+		 dev->count, dev->board.name);
 
 	up(&dev->limit_sem);
 	mutex_unlock(&glb_mutex);
diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
index 3f20ea5..4dc09a2 100644
--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
@@ -21,7 +21,6 @@
 
 */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include <linux/errno.h>
@@ -95,7 +94,8 @@ static int comedi_do_insn(struct comedi_device *dev,
 	s = &dev->subdevices[insn->subdev];
 
 	if (s->type == COMEDI_SUBD_UNUSED) {
-		printk(KERN_ERR "%d not useable subdevice\n", insn->subdev);
+		dev_err(dev->class_dev,
+			"%d not useable subdevice\n", insn->subdev);
 		ret = -EIO;
 		goto error;
 	}
@@ -104,7 +104,7 @@ static int comedi_do_insn(struct comedi_device *dev,
 
 	ret = comedi_check_chanlist(s, 1, &insn->chanspec);
 	if (ret < 0) {
-		printk(KERN_ERR "bad chanspec\n");
+		dev_err(dev->class_dev, "bad chanspec\n");
 		ret = -EINVAL;
 		goto error;
 	}
diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c
index bb7e70e..01acbe9 100644
--- a/drivers/staging/comedi/proc.c
+++ b/drivers/staging/comedi/proc.c
@@ -28,7 +28,6 @@
 	was cool.
 */
 
-#define __NO_VERSION__
 #include "comedidev.h"
 #include "comedi_internal.h"
 #include <linux/proc_fs.h>
diff --git a/drivers/staging/crystalhd/crystalhd_cmds.c b/drivers/staging/crystalhd/crystalhd_cmds.c
index 05fe787..ed99daa6 100644
--- a/drivers/staging/crystalhd/crystalhd_cmds.c
+++ b/drivers/staging/crystalhd/crystalhd_cmds.c
@@ -308,9 +308,9 @@ static enum BC_STATUS bc_cproc_download_fw(struct crystalhd_cmd *ctx,
 	sts = crystalhd_download_fw(ctx->adp, (uint8_t *)idata->add_cdata,
 				  idata->add_cdata_sz);
 
-	if (sts != BC_STS_SUCCESS) {
+	if (sts != BC_STS_SUCCESS)
 		BCMLOG_ERR("Firmware Download Failure!! - %d\n", sts);
-	} else
+	else
 		ctx->state |= BC_LINK_INIT;
 
 	return sts;
@@ -951,7 +951,7 @@ enum BC_STATUS crystalhd_user_close(struct crystalhd_cmd *ctx, struct crystalhd_
  *
  * Called at the time of driver load.
  */
-enum BC_STATUS __devinit crystalhd_setup_cmd_context(struct crystalhd_cmd *ctx,
+enum BC_STATUS crystalhd_setup_cmd_context(struct crystalhd_cmd *ctx,
 				    struct crystalhd_adp *adp)
 {
 	int i = 0;
@@ -986,7 +986,7 @@ enum BC_STATUS __devinit crystalhd_setup_cmd_context(struct crystalhd_cmd *ctx,
  *
  * Called at the time of driver un-load.
  */
-enum BC_STATUS __devexit crystalhd_delete_cmd_context(struct crystalhd_cmd *ctx)
+enum BC_STATUS crystalhd_delete_cmd_context(struct crystalhd_cmd *ctx)
 {
 	BCMLOG(BCMLOG_DBG, "Deleting Command context..\n");
 
diff --git a/drivers/staging/crystalhd/crystalhd_lnx.c b/drivers/staging/crystalhd/crystalhd_lnx.c
index 166203a..85f51fb 100644
--- a/drivers/staging/crystalhd/crystalhd_lnx.c
+++ b/drivers/staging/crystalhd/crystalhd_lnx.c
@@ -353,7 +353,7 @@ static const struct file_operations chd_dec_fops = {
 	.llseek = noop_llseek,
 };
 
-static int __devinit chd_dec_init_chdev(struct crystalhd_adp *adp)
+static int chd_dec_init_chdev(struct crystalhd_adp *adp)
 {
 	struct crystalhd_ioctl_data *temp;
 	struct device *dev;
@@ -418,7 +418,7 @@ fail:
 	return rc;
 }
 
-static void __devexit chd_dec_release_chdev(struct crystalhd_adp *adp)
+static void chd_dec_release_chdev(struct crystalhd_adp *adp)
 {
 	struct crystalhd_ioctl_data *temp = NULL;
 	if (!adp)
@@ -443,7 +443,7 @@ static void __devexit chd_dec_release_chdev(struct crystalhd_adp *adp)
 	crystalhd_delete_elem_pool(adp);
 }
 
-static int __devinit chd_pci_reserve_mem(struct crystalhd_adp *pinfo)
+static int chd_pci_reserve_mem(struct crystalhd_adp *pinfo)
 {
 	int rc;
 	unsigned long bar2 = pci_resource_start(pinfo->pdev, 2);
@@ -496,7 +496,7 @@ static int __devinit chd_pci_reserve_mem(struct crystalhd_adp *pinfo)
 	return 0;
 }
 
-static void __devexit chd_pci_release_mem(struct crystalhd_adp *pinfo)
+static void chd_pci_release_mem(struct crystalhd_adp *pinfo)
 {
 	if (!pinfo)
 		return;
@@ -511,7 +511,7 @@ static void __devexit chd_pci_release_mem(struct crystalhd_adp *pinfo)
 }
 
 
-static void __devexit chd_dec_pci_remove(struct pci_dev *pdev)
+static void chd_dec_pci_remove(struct pci_dev *pdev)
 {
 	struct crystalhd_adp *pinfo;
 	enum BC_STATUS sts = BC_STS_SUCCESS;
@@ -537,7 +537,7 @@ static void __devexit chd_dec_pci_remove(struct pci_dev *pdev)
 	g_adp_info = NULL;
 }
 
-static int __devinit chd_dec_pci_probe(struct pci_dev *pdev,
+static int chd_dec_pci_probe(struct pci_dev *pdev,
 			     const struct pci_device_id *entry)
 {
 	struct crystalhd_adp *pinfo;
@@ -711,7 +711,7 @@ MODULE_DEVICE_TABLE(pci, chd_dec_pci_id_table);
 static struct pci_driver bc_chd_70012_driver = {
 	.name     = "Broadcom 70012 Decoder",
 	.probe    = chd_dec_pci_probe,
-	.remove   = __devexit_p(chd_dec_pci_remove),
+	.remove   = chd_dec_pci_remove,
 	.id_table = chd_dec_pci_id_table,
 #ifdef CONFIG_PM
 	.suspend  = chd_dec_pci_suspend,
diff --git a/drivers/staging/crystalhd/crystalhd_misc.c b/drivers/staging/crystalhd/crystalhd_misc.c
index b3a6378..a5f109c 100644
--- a/drivers/staging/crystalhd/crystalhd_misc.c
+++ b/drivers/staging/crystalhd/crystalhd_misc.c
@@ -960,7 +960,7 @@ void crystalhd_destroy_dio_pool(struct crystalhd_adp *adp)
  * Create general purpose list element pool to hold pending,
  * and active requests.
  */
-int __devinit crystalhd_create_elem_pool(struct crystalhd_adp *adp,
+int crystalhd_create_elem_pool(struct crystalhd_adp *adp,
 		uint32_t pool_size)
 {
 	uint32_t i;
diff --git a/drivers/staging/csr/Makefile b/drivers/staging/csr/Makefile
index ab626ed..dbd135a 100644
--- a/drivers/staging/csr/Makefile
+++ b/drivers/staging/csr/Makefile
@@ -70,5 +70,4 @@ csr_helper-y :=	csr_time.o			\
 		csr_framework_ext.o		\
 		csr_wifi_serialize_primitive_types.o	\
 		csr_serialize_primitive_types.o	\
-		csr_msgconv.o			\
-		csr_panic.o
+		csr_msgconv.o
diff --git a/drivers/staging/csr/bh.c b/drivers/staging/csr/bh.c
index addee05..1a1f5c7 100644
--- a/drivers/staging/csr/bh.c
+++ b/drivers/staging/csr/bh.c
@@ -228,20 +228,19 @@ handle_bh_error(unifi_priv_t *priv)
  *
  * ---------------------------------------------------------------------------
  */
-static int
-bh_thread_function(void *arg)
+static int bh_thread_function(void *arg)
 {
-    unifi_priv_t *priv = (unifi_priv_t*)arg;
-    CsrResult csrResult;
-    long ret;
-    u32 timeout, t;
-    struct uf_thread *this_thread;
+	unifi_priv_t *priv = (unifi_priv_t *)arg;
+	CsrResult csrResult;
+	long ret;
+	u32 timeout, t;
+	struct uf_thread *this_thread;
 
-    unifi_trace(priv, UDBG2, "bh_thread_function starting\n");
+	unifi_trace(priv, UDBG2, "bh_thread_function starting\n");
 
-    this_thread = &priv->bh_thread;
+	this_thread = &priv->bh_thread;
 
-    t = timeout = 0;
+	t = timeout = 0;
     while (!kthread_should_stop()) {
         /* wait until an error occurs, or we need to process something. */
         unifi_trace(priv, UDBG3, "bh_thread goes to sleep.\n");
diff --git a/drivers/staging/csr/csr_framework_ext.c b/drivers/staging/csr/csr_framework_ext.c
index f91a4bf..2aabb6c 100644
--- a/drivers/staging/csr/csr_framework_ext.c
+++ b/drivers/staging/csr/csr_framework_ext.c
@@ -9,7 +9,6 @@
 *****************************************************************************/
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
 #include <linux/freezer.h>
@@ -18,102 +17,6 @@
 #include <linux/bitops.h>
 
 #include "csr_framework_ext.h"
-#include "csr_panic.h"
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrMutexCreate
- *
- *  DESCRIPTION
- *      Create a mutex and return a handle to the created mutex.
- *
- *  RETURNS
- *      Possible values:
- *          CSR_RESULT_SUCCESS           in case of success
- *          CSR_FE_RESULT_NO_MORE_MUTEXES   in case of out of mutex resources
- *          CSR_FE_RESULT_INVALID_POINTER   in case the mutexHandle pointer is invalid
- *
- *----------------------------------------------------------------------------*/
-CsrResult CsrMutexCreate(CsrMutexHandle *mutexHandle)
-{
-    if (mutexHandle == NULL)
-    {
-        return CSR_FE_RESULT_INVALID_POINTER;
-    }
-
-    sema_init(mutexHandle, 1);
-
-    return CSR_RESULT_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrMutexDestroy
- *
- *  DESCRIPTION
- *      Destroy the previously created mutex.
- *
- *  RETURNS
- *      void
- *
- *----------------------------------------------------------------------------*/
-void CsrMutexDestroy(CsrMutexHandle *mutexHandle)
-{
-}
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrMutexLock
- *
- *  DESCRIPTION
- *      Lock the mutex refered to by the provided handle.
- *
- *  RETURNS
- *      Possible values:
- *          CSR_RESULT_SUCCESS           in case of success
- *          CSR_FE_RESULT_INVALID_HANDLE    in case the mutexHandle is invalid
- *
- *----------------------------------------------------------------------------*/
-CsrResult CsrMutexLock(CsrMutexHandle *mutexHandle)
-{
-    if (mutexHandle == NULL)
-    {
-        return CSR_FE_RESULT_INVALID_POINTER;
-    }
-
-    if (down_interruptible(mutexHandle))
-    {
-        CsrPanic(CSR_TECH_FW, CSR_PANIC_FW_UNEXPECTED_VALUE, "CsrMutexLock Failed");
-        return CSR_FE_RESULT_INVALID_POINTER;
-    }
-
-    return CSR_RESULT_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrMutexUnlock
- *
- *  DESCRIPTION
- *      Unlock the mutex refered to by the provided handle.
- *
- *  RETURNS
- *      Possible values:
- *          CSR_RESULT_SUCCESS           in case of success
- *          CSR_FE_RESULT_INVALID_HANDLE    in case the mutexHandle is invalid
- *
- *----------------------------------------------------------------------------*/
-CsrResult CsrMutexUnlock(CsrMutexHandle *mutexHandle)
-{
-    if (mutexHandle == NULL)
-    {
-        return CSR_FE_RESULT_INVALID_POINTER;
-    }
-
-    up(mutexHandle);
-
-    return CSR_RESULT_SUCCESS;
-}
 
 /*----------------------------------------------------------------------------*
  *  NAME
diff --git a/drivers/staging/csr/csr_framework_ext.h b/drivers/staging/csr/csr_framework_ext.h
index 66973e9..e8ae490 100644
--- a/drivers/staging/csr/csr_framework_ext.h
+++ b/drivers/staging/csr/csr_framework_ext.h
@@ -13,10 +13,6 @@
 #include "csr_result.h"
 #include "csr_framework_ext_types.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* Result codes */
 #define CSR_FE_RESULT_NO_MORE_EVENTS    ((CsrResult) 0x0001)
 #define CSR_FE_RESULT_INVALID_POINTER   ((CsrResult) 0x0002)
@@ -34,215 +30,6 @@ extern "C" {
 
 #define CSR_EVENT_WAIT_INFINITE         ((u16) 0xFFFF)
 
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrEventCreate
- *
- *  DESCRIPTION
- *      Creates an event and returns a handle to the created event.
- *
- *  RETURNS
- *      Possible values:
- *          CSR_RESULT_SUCCESS          in case of success
- *          CSR_FE_RESULT_NO_MORE_EVENTS   in case of out of event resources
- *          CSR_FE_RESULT_INVALID_POINTER  in case the eventHandle pointer is invalid
- *
- *----------------------------------------------------------------------------*/
-CsrResult CsrEventCreate(CsrEventHandle *eventHandle);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrEventWait
- *
- *  DESCRIPTION
- *      Wait fore one or more of the event bits to be set.
- *
- *  RETURNS
- *      Possible values:
- *          CSR_RESULT_SUCCESS              in case of success
- *          CSR_FE_RESULT_TIMEOUT              in case of timeout
- *          CSR_FE_RESULT_INVALID_HANDLE       in case the eventHandle is invalid
- *          CSR_FE_RESULT_INVALID_POINTER      in case the eventBits pointer is invalid
- *
- *----------------------------------------------------------------------------*/
-CsrResult CsrEventWait(CsrEventHandle *eventHandle, u16 timeoutInMs, u32 *eventBits);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrEventSet
- *
- *  DESCRIPTION
- *      Set an event.
- *
- *  RETURNS
- *      Possible values:
- *          CSR_RESULT_SUCCESS              in case of success
- *          CSR_FE_RESULT_INVALID_HANDLE       in case the eventHandle is invalid
- *
- *----------------------------------------------------------------------------*/
-CsrResult CsrEventSet(CsrEventHandle *eventHandle, u32 eventBits);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrEventDestroy
- *
- *  DESCRIPTION
- *      Destroy the event associated.
- *
- *  RETURNS
- *      void
- *
- *----------------------------------------------------------------------------*/
-void CsrEventDestroy(CsrEventHandle *eventHandle);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrMutexCreate
- *
- *  DESCRIPTION
- *      Create a mutex and return a handle to the created mutex.
- *
- *  RETURNS
- *      Possible values:
- *          CSR_RESULT_SUCCESS           in case of success
- *          CSR_FE_RESULT_NO_MORE_MUTEXES   in case of out of mutex resources
- *          CSR_FE_RESULT_INVALID_POINTER   in case the mutexHandle pointer is invalid
- *
- *----------------------------------------------------------------------------*/
-CsrResult CsrMutexCreate(CsrMutexHandle *mutexHandle);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrMutexLock
- *
- *  DESCRIPTION
- *      Lock the mutex refered to by the provided handle.
- *
- *  RETURNS
- *      Possible values:
- *          CSR_RESULT_SUCCESS           in case of success
- *          CSR_FE_RESULT_INVALID_HANDLE    in case the mutexHandle is invalid
- *
- *----------------------------------------------------------------------------*/
-CsrResult CsrMutexLock(CsrMutexHandle *mutexHandle);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrMutexUnlock
- *
- *  DESCRIPTION
- *      Unlock the mutex refered to by the provided handle.
- *
- *  RETURNS
- *      Possible values:
- *          CSR_RESULT_SUCCESS           in case of success
- *          CSR_FE_RESULT_INVALID_HANDLE    in case the mutexHandle is invalid
- *
- *----------------------------------------------------------------------------*/
-CsrResult CsrMutexUnlock(CsrMutexHandle *mutexHandle);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrMutexDestroy
- *
- *  DESCRIPTION
- *      Destroy the previously created mutex.
- *
- *  RETURNS
- *      void
- *
- *----------------------------------------------------------------------------*/
-void CsrMutexDestroy(CsrMutexHandle *mutexHandle);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrGlobalMutexLock
- *
- *  DESCRIPTION
- *      Lock the global mutex. The global mutex is a single pre-initialised
- *      shared mutex, spinlock or similar that does not need to be created prior
- *      to use. The limitation is that there is only one single lock shared
- *      between all code. Consequently, it must only be used very briefly to
- *      either protect simple one-time initialisation or to protect the creation
- *      of a dedicated mutex by calling CsrMutexCreate.
- *
- *----------------------------------------------------------------------------*/
-void CsrGlobalMutexLock(void);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrGlobalMutexUnlock
- *
- *  DESCRIPTION
- *      Unlock the global mutex.
- *
- *----------------------------------------------------------------------------*/
-void CsrGlobalMutexUnlock(void);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrThreadCreate
- *
- *  DESCRIPTION
- *      Create thread function and return a handle to the created thread.
- *
- *  RETURNS
- *      Possible values:
- *          CSR_RESULT_SUCCESS           in case of success
- *          CSR_FE_RESULT_NO_MORE_THREADS   in case of out of thread resources
- *          CSR_FE_RESULT_INVALID_POINTER   in case one of the supplied pointers is invalid
- *
- *----------------------------------------------------------------------------*/
-CsrResult CsrThreadCreate(void (*threadFunction)(void *pointer), void *pointer,
-    u32 stackSize, u16 priority,
-    const char *threadName, CsrThreadHandle *threadHandle);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrThreadGetHandle
- *
- *  DESCRIPTION
- *      Return thread handle of calling thread.
- *
- *  RETURNS
- *      Possible values:
- *          CSR_RESULT_SUCCESS             in case of success
- *          CSR_FE_RESULT_INVALID_POINTER  in case the threadHandle pointer is invalid
- *
- *----------------------------------------------------------------------------*/
-CsrResult CsrThreadGetHandle(CsrThreadHandle *threadHandle);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrThreadEqual
- *
- *  DESCRIPTION
- *      Compare thread handles
- *
- *  RETURNS
- *      Possible values:
- *          CSR_RESULT_SUCCESS             in case thread handles are identical
- *          CSR_FE_RESULT_INVALID_POINTER  in case either threadHandle pointer is invalid
- *          CSR_RESULT_FAILURE             otherwise
- *
- *----------------------------------------------------------------------------*/
-CsrResult CsrThreadEqual(CsrThreadHandle *threadHandle1, CsrThreadHandle *threadHandle2);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrThreadSleep
- *
- *  DESCRIPTION
- *      Sleep for a given period.
- *
- *  RETURNS
- *      void
- *
- *----------------------------------------------------------------------------*/
 void CsrThreadSleep(u16 sleepTimeInMs);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/drivers/staging/csr/csr_framework_ext_types.h b/drivers/staging/csr/csr_framework_ext_types.h
index 57194ee..575598c 100644
--- a/drivers/staging/csr/csr_framework_ext_types.h
+++ b/drivers/staging/csr/csr_framework_ext_types.h
@@ -2,11 +2,11 @@
 #define CSR_FRAMEWORK_EXT_TYPES_H__
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2010
-            All rights reserved and confidential information of CSR
+	(c) Cambridge Silicon Radio Limited 2010
+	All rights reserved and confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+	Refer to LICENSE.txt included with this source for details
+	on the license terms.
 
 *****************************************************************************/
 
@@ -17,47 +17,14 @@
 #include <pthread.h>
 #endif
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
 #ifdef __KERNEL__
 
-struct CsrThread
-{
-    struct task_struct *thread_task;
-    char                name[16];
-};
-
-struct CsrEvent
-{
-    /* wait_queue for waking the kernel thread */
-    wait_queue_head_t wakeup_q;
-    unsigned int      wakeup_flag;
-};
-
-typedef struct CsrEvent CsrEventHandle;
 typedef struct semaphore CsrMutexHandle;
-typedef struct CsrThread CsrThreadHandle;
 
 #else /* __KERNEL __ */
 
-struct CsrEvent
-{
-    pthread_cond_t  event;
-    pthread_mutex_t mutex;
-    u32       eventBits;
-};
-
-typedef struct CsrEvent CsrEventHandle;
 typedef pthread_mutex_t CsrMutexHandle;
-typedef pthread_t CsrThreadHandle;
 
 #endif /* __KERNEL__ */
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/drivers/staging/csr/csr_lib.h b/drivers/staging/csr/csr_lib.h
deleted file mode 100644
index b1a57d5..0000000
--- a/drivers/staging/csr/csr_lib.h
+++ /dev/null
@@ -1,188 +0,0 @@
-#ifndef CSR_LIB_H__
-#define CSR_LIB_H__
-/*****************************************************************************
-
-            (c) Cambridge Silicon Radio Limited 2010
-            All rights reserved and confidential information of CSR
-
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
-
-*****************************************************************************/
-
-#include "csr_prim_defs.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct
-{
-    CsrPrim type;
-} CsrEvent;
-
-/*----------------------------------------------------------------------------*
- *  CsrEvent_struct
- *
- *  DESCRIPTION
- *      Generic message creator.
- *      Allocates and fills in a message with the signature CsrEvent
- *
- *----------------------------------------------------------------------------*/
-CsrEvent *CsrEvent_struct(u16 primtype, u16 msgtype);
-
-typedef struct
-{
-    CsrPrim  type;
-    u8 value;
-} CsrEventCsrUint8;
-
-/*----------------------------------------------------------------------------*
- *  CsrEventCsrUint8_struct
- *
- *  DESCRIPTION
- *      Generic message creator.
- *      Allocates and fills in a message with the signature CsrEventCsrUint8
- *
- *----------------------------------------------------------------------------*/
-CsrEventCsrUint8 *CsrEventCsrUint8_struct(u16 primtype, u16 msgtype, u8 value);
-
-typedef struct
-{
-    CsrPrim   type;
-    u16 value;
-} CsrEventCsrUint16;
-
-/*----------------------------------------------------------------------------*
- *  CsrEventCsrUint16_struct
- *
- *  DESCRIPTION
- *      Generic message creator.
- *      Allocates and fills in a message with the signature CsrEventCsrUint16
- *
- *----------------------------------------------------------------------------*/
-CsrEventCsrUint16 *CsrEventCsrUint16_struct(u16 primtype, u16 msgtype, u16 value);
-
-typedef struct
-{
-    CsrPrim   type;
-    u16 value1;
-    u8  value2;
-} CsrEventCsrUint16CsrUint8;
-
-/*----------------------------------------------------------------------------*
- *  CsrEventCsrUint16CsrUint8_struct
- *
- *  DESCRIPTION
- *      Generic message creator.
- *      Allocates and fills in a message with the signature CsrEventCsrUint16CsrUint8
- *
- *----------------------------------------------------------------------------*/
-CsrEventCsrUint16CsrUint8 *CsrEventCsrUint16CsrUint8_struct(u16 primtype, u16 msgtype, u16 value1, u8 value2);
-
-typedef struct
-{
-    CsrPrim   type;
-    u16 value1;
-    u16 value2;
-} CsrEventCsrUint16CsrUint16;
-
-/*----------------------------------------------------------------------------*
- *  CsrEventCsrUint16CsrUint16_struct
- *
- *  DESCRIPTION
- *      Generic message creator.
- *      Allocates and fills in a message with the signature CsrEventCsrUint16CsrUint16
- *
- *----------------------------------------------------------------------------*/
-CsrEventCsrUint16CsrUint16 *CsrEventCsrUint16CsrUint16_struct(u16 primtype, u16 msgtype, u16 value1, u16 value2);
-
-typedef struct
-{
-    CsrPrim   type;
-    u16 value1;
-    u32 value2;
-} CsrEventCsrUint16CsrUint32;
-
-/*----------------------------------------------------------------------------*
- *  CsrEventCsrUint16_struct
- *
- *  DESCRIPTION
- *      Generic message creator.
- *      Allocates and fills in a message with the signature CsrEventCsrUint16
- *
- *----------------------------------------------------------------------------*/
-CsrEventCsrUint16CsrUint32 *CsrEventCsrUint16CsrUint32_struct(u16 primtype, u16 msgtype, u16 value1, u32 value2);
-
-typedef struct
-{
-    CsrPrim        type;
-    u16      value1;
-    char *value2;
-} CsrEventCsrUint16CsrCharString;
-
-/*----------------------------------------------------------------------------*
- *  CsrEventCsrUint16CsrCharString_struct
- *
- *  DESCRIPTION
- *      Generic message creator.
- *      Allocates and fills in a message with the signature CsrEventCsrUint16CsrCharString
- *
- *----------------------------------------------------------------------------*/
-CsrEventCsrUint16CsrCharString *CsrEventCsrUint16CsrCharString_struct(u16 primtype, u16 msgtype, u16 value1, char *value2);
-
-typedef struct
-{
-    CsrPrim   type;
-    u32 value;
-} CsrEventCsrUint32;
-
-/*----------------------------------------------------------------------------*
- *  CsrEventCsrUint32_struct
- *
- *  DESCRIPTION
- *      Generic message creator.
- *      Allocates and fills in a message with the signature CsrEventCsrUint32
- *
- *----------------------------------------------------------------------------*/
-CsrEventCsrUint32 *CsrEventCsrUint32_struct(u16 primtype, u16 msgtype, u32 value);
-
-typedef struct
-{
-    CsrPrim   type;
-    u32 value1;
-    u16 value2;
-} CsrEventCsrUint32CsrUint16;
-
-/*----------------------------------------------------------------------------*
- *  CsrEventCsrUint32CsrUint16_struct
- *
- *  DESCRIPTION
- *      Generic message creator.
- *      Allocates and fills in a message with the signature CsrEventCsrUint32CsrUint16
- *
- *----------------------------------------------------------------------------*/
-CsrEventCsrUint32CsrUint16 *CsrEventCsrUint32CsrUint16_struct(u16 primtype, u16 msgtype, u32 value1, u32 value2);
-
-typedef struct
-{
-    CsrPrim        type;
-    u32      value1;
-    char *value2;
-} CsrEventCsrUint32CsrCharString;
-
-/*----------------------------------------------------------------------------*
- *  CsrEventCsrUint32CsrCharString_struct
- *
- *  DESCRIPTION
- *      Generic message creator.
- *      Allocates and fills in a message with the signature CsrEventCsrUint32CsrCharString
- *
- *----------------------------------------------------------------------------*/
-CsrEventCsrUint32CsrCharString *CsrEventCsrUint32CsrCharString_struct(u16 primtype, u16 msgtype, u32 value1, char *value2);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* CSR_LIB_H__ */
diff --git a/drivers/staging/csr/csr_log.h b/drivers/staging/csr/csr_log.h
index b280856..5de5650 100644
--- a/drivers/staging/csr/csr_log.h
+++ b/drivers/staging/csr/csr_log.h
@@ -2,23 +2,18 @@
 #define CSR_LOG_H__
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2010
-            All rights reserved and confidential information of CSR
+	(c) Cambridge Silicon Radio Limited 2010
+	All rights reserved and confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+	Refer to LICENSE.txt included with this source for details
+	on the license terms.
 
 *****************************************************************************/
 
 #include "csr_sched.h"
-#include "csr_panic.h"
 #include "csr_prim_defs.h"
 #include "csr_msgconv.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /*
  * Log filtering
  */
@@ -77,34 +72,19 @@ u8 CsrLogTaskIsFiltered(CsrSchedQid taskId, CsrLogLevelTask level);
 /*
  * Logging stuff
  */
-#define CSR_LOG_STRINGIFY_REAL(a) #a
+#define CSR_LOG_STRINGIFY_REAL(a) (#a)
 #define CSR_LOG_STRINGIFY(a) CSR_LOG_STRINGIFY_REAL(a)
 
-#ifdef CSR_LOG_ASSERT_ENABLE
-#define CSR_LOG_ASSERT(cond)                        \
-    do {                                                \
-        if (!(cond))                                    \
-        {                                               \
-            char *panic_arg = "[" __FILE__ ":" CSR_LOG_STRINGIFY(__LINE__) "] - " CSR_LOG_STRINGIFY(cond); \
-            CsrPanic(CSR_TECH_FW, CSR_PANIC_FW_ASSERTION_FAIL, panic_arg); \
-        }                                               \
-    } while (0)
-#else
-#define CSR_LOG_ASSERT(cond)
-#endif
-
-typedef struct
-{
-    u16            primitiveType;
-    const char *primitiveName;
-    CsrMsgConvMsgEntry  *messageConv; /* Private - do not use */
+typedef struct {
+	u16            primitiveType;
+	const char *primitiveName;
+	CsrMsgConvMsgEntry  *messageConv; /* Private - do not use */
 } CsrLogPrimitiveInformation;
 
-typedef struct
-{
-    const char        *techVer;
-    u32                   primitiveInfoCount;
-    CsrLogPrimitiveInformation *primitiveInfo;
+typedef struct {
+	const char        *techVer;
+	u32                   primitiveInfoCount;
+	CsrLogPrimitiveInformation *primitiveInfo;
 } CsrLogTechInformation;
 
 /*---------------------------------*/
@@ -118,21 +98,19 @@ typedef u32 bitmask32_t;
 #ifdef CSR_LOG_INCLUDE_FILE_NAME_AND_LINE_NUMBER
 /* DEPRECATED - replaced by csr_log_text.h */
 #define CSR_LOG_TEXT(text) \
-    do { \
-        if (!CsrLogTaskIsFiltered(CsrSchedTaskQueueGet(), CSR_LOG_LEVEL_TASK_TEXT)) \
-        { \
-            CsrLogTaskText(text, __LINE__, __FILE__); \
-        } \
-    } while (0)
+	do { \
+		if (!CsrLogTaskIsFiltered(CsrSchedTaskQueueGet(), CSR_LOG_LEVEL_TASK_TEXT)) { \
+			CsrLogTaskText(text, __LINE__, __FILE__); \
+		} \
+	} while (0)
 #else
 /* DEPRECATED - replaced by csr_log_text.h */
 #define CSR_LOG_TEXT(text) \
-    do { \
-        if (!CsrLogTaskIsFiltered(CsrSchedTaskQueueGet(), CSR_LOG_LEVEL_TASK_TEXT)) \
-        { \
-            CsrLogTaskText(text, 0, NULL); \
-        } \
-    } while (0)
+	do { \
+		if (!CsrLogTaskIsFiltered(CsrSchedTaskQueueGet(), CSR_LOG_LEVEL_TASK_TEXT)) { \
+			CsrLogTaskText(text, 0, NULL); \
+		} \
+	} while (0)
 #endif
 #else
 #define CSR_LOG_TEXT(text)
@@ -140,8 +118,8 @@ typedef u32 bitmask32_t;
 
 /* DEPRECATED - replaced by csr_log_text.h */
 void CsrLogTaskText(const char *text,
-    u32 line,
-    const char *file);
+	u32 line,
+	const char *file);
 
 #define CSR_LOG_STATE_TRANSITION_MASK_FSM_NAME          (0x001)
 #define CSR_LOG_STATE_TRANSITION_MASK_NEXT_STATE        (0x002)
@@ -153,16 +131,16 @@ void CsrLogTaskText(const char *text,
 
 /* DEPRECATED - replaced by csr_log_text.h */
 void CsrLogStateTransition(bitmask16_t mask,
-    u32 identifier,
-    const char *fsm_name,
-    u32 prev_state,
-    const char *prev_state_str,
-    u32 in_event,
-    const char *in_event_str,
-    u32 next_state,
-    const char *next_state_str,
-    u32 line,
-    const char *file);
+	u32 identifier,
+	const char *fsm_name,
+	u32 prev_state,
+	const char *prev_state_str,
+	u32 in_event,
+	const char *in_event_str,
+	u32 next_state,
+	const char *next_state_str,
+	u32 line,
+	const char *file);
 
 /*---------------------------------*/
 /*  BSP logging */
@@ -183,67 +161,63 @@ void CsrLogDeactivate(CsrSchedQid tskid);
 #define SYNERGY_SERIALIZER_TYPE_SER     (0x001)
 
 void CsrLogMessagePut(u32 line,
-    const char *file,
-    CsrSchedQid src_task_id,
-    CsrSchedQid dst_taskid,
-    CsrSchedMsgId msg_id,
-    u16 prim_type,
-    const void *msg);
+	const char *file,
+	CsrSchedQid src_task_id,
+	CsrSchedQid dst_taskid,
+	CsrSchedMsgId msg_id,
+	u16 prim_type,
+	const void *msg);
 
 void CsrLogMessageGet(CsrSchedQid src_task_id,
-    CsrSchedQid dst_taskid,
-    u8 get_res,
-    CsrSchedMsgId msg_id,
-    u16 prim_type,
-    const void *msg);
+	CsrSchedQid dst_taskid,
+	u8 get_res,
+	CsrSchedMsgId msg_id,
+	u16 prim_type,
+	const void *msg);
 
 void CsrLogTimedEventIn(u32 line,
-    const char *file,
-    CsrSchedQid task_id,
-    CsrSchedTid tid,
-    CsrTime requested_delay,
-    u16 fniarg,
-    const void *fnvarg);
+	const char *file,
+	CsrSchedQid task_id,
+	CsrSchedTid tid,
+	u32 requested_delay,
+	u16 fniarg,
+	const void *fnvarg);
 
 void CsrLogTimedEventFire(CsrSchedQid task_id,
-    CsrSchedTid tid);
+	CsrSchedTid tid);
 
 void CsrLogTimedEventDone(CsrSchedQid task_id,
-    CsrSchedTid tid);
+	CsrSchedTid tid);
 
 void CsrLogTimedEventCancel(u32 line,
-    const char *file,
-    CsrSchedQid task_id,
-    CsrSchedTid tid,
-    u8 cancel_res);
+	const char *file,
+	CsrSchedQid task_id,
+	CsrSchedTid tid,
+	u8 cancel_res);
 
 void CsrLogBgintRegister(u8 thread_id,
-    CsrSchedBgint irq,
-    const char *callback,
-    const void *ptr);
+	CsrSchedBgint irq,
+	const char *callback,
+	const void *ptr);
 void CsrLogBgintUnregister(CsrSchedBgint irq);
 void CsrLogBgintSet(CsrSchedBgint irq);
 void CsrLogBgintServiceStart(CsrSchedBgint irq);
 void CsrLogBgintServiceDone(CsrSchedBgint irq);
 
 void CsrLogExceptionStateEvent(u16 prim_type,
-    CsrPrim msg_type,
-    u16 state,
-    u32 line,
-    const char *file);
+	CsrPrim msg_type,
+	u16 state,
+	u32 line,
+	const char *file);
 void CsrLogExceptionGeneral(u16 prim_type,
-    u16 state,
-    const char *text,
-    u32 line,
-    const char *file);
+	u16 state,
+	const char *text,
+	u32 line,
+	const char *file);
 void CsrLogExceptionWarning(u16 prim_type,
-    u16 state,
-    const char *text,
-    u32 line,
-    const char *file);
-
-#ifdef __cplusplus
-}
-#endif
+	u16 state,
+	const char *text,
+	u32 line,
+	const char *file);
 
 #endif
diff --git a/drivers/staging/csr/csr_log_configure.h b/drivers/staging/csr/csr_log_configure.h
index 8842e4b..283647c 100644
--- a/drivers/staging/csr/csr_log_configure.h
+++ b/drivers/staging/csr/csr_log_configure.h
@@ -2,45 +2,16 @@
 #define CSR_LOG_CONFIGURE_H__
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2010
-            All rights reserved and confidential information of CSR
+  (c) Cambridge Silicon Radio Limited 2010
+  All rights reserved and confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+  Refer to LICENSE.txt included with this source for details
+  on the license terms.
 
-*****************************************************************************/
+ *****************************************************************************/
 
 #include "csr_log.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*---------------------------------*/
-/* Log init/deinit                 */
-/*---------------------------------*/
-void CsrLogInit(u8 size);
-void CsrLogDeinit(void);
-
-/*---------------------------------*/
-/* Log Framework Tech info         */
-/*---------------------------------*/
-void CsrLogTechInfoRegister(void);
-
-/* Set the logging level for the environment outside the scheduler context */
-void CsrLogLevelEnvironmentSet(CsrLogLevelEnvironment environmentLogLevel);
-
-
-/* Set the logging level for all scheduler tasks */
-/* This function call takes precedence over all previous calls to CsrLogLevelTaskSetSpecific() */
-void CsrLogLevelTaskSetAll(CsrLogLevelTask tasksLogLevelMask);
-
-/* Set the logging level for a given Task */
-/* This function can be used as a complement to CsrLogLevelTaskSetAll() to add more _or_ less log from a given task than what is set
-generally with CsrLogLevelTaskSetAll(). */
-void CsrLogLevelTaskSetSpecific(CsrSchedQid taskId, CsrLogLevelTask taskLogLevelMask);
-
-
 /*--------------------------------------------*/
 /*  Filtering on log text warning levels      */
 /*--------------------------------------------*/
@@ -65,70 +36,4 @@ typedef u32 CsrLogLevelText;
  * taskId's in the range 0x0600xxxx to 0x06FFxxxx. And so on for other technologies. */
 typedef u32 CsrLogTextTaskId;
 
-/* Set the text logging level for all Tasks */
-/* This function call takes precedence over all previous calls to CsrLogLevelTextSetTask() and CsrLogLevelTextSetTaskSubOrigin() */
-void CsrLogLevelTextSetAll(CsrLogLevelText warningLevelMask);
-
-/* Set the text logging level for a given Task */
-/* This function call takes precedence over all previous calls to CsrLogLevelTextSetTaskSubOrigin(), but it can be used as a complement to
- * CsrLogLevelTextSetAll() to add more _or_ less log from a given task than what is set generally with CsrLogLevelTextSetAll(). */
-void CsrLogLevelTextSetTask(CsrLogTextTaskId taskId, CsrLogLevelText warningLevelMask);
-
-/* Set the text logging level for a given tasks subOrigin */
-/* This function can be used as a complement to CsrLogLevelTextSetAll() and CsrLogLevelTextSetTask() to add more _or_ less log from a given
- * subOrigin within a task than what is set generally with CsrLogLevelTextSetAll() _or_ CsrLogLevelTextSetTask(). */
-void CsrLogLevelTextSetTaskSubOrigin(CsrLogTextTaskId taskId, u16 subOrigin, CsrLogLevelText warningLevelMask);
-
-/*******************************************************************************
-
-    NAME
-        CsrLogLevelTextSet
-
-    DESCRIPTION
-        Set the text logging level for a given origin and optionally sub origin
-        by name. If either string is NULL or zero length, it is interpreted as
-        all origins and/or all sub origins respectively. If originName is NULL
-        or zero length, subOriginName is ignored.
-
-        Passing NULL or zero length strings in both originName and subOriginName
-        is equivalent to calling CsrLogLevelTextSetAll, and overrides all
-        previous filter configurations for all origins and sub origins.
-
-        Passing NULL or a zero length string in subOriginName overrides all
-        previous filter configurations for all sub origins of the specified
-        origin.
-
-        Note: the supplied strings may be accessed after the function returns
-        and must remain valid and constant until CsrLogDeinit is called.
-
-        Note: when specifying an origin (originName is not NULL and not zero
-        length), this function can only be used for origins that use the
-        csr_log_text_2.h interface for registration and logging. Filtering for
-        origins that use the legacy csr_log_text.h interface must be be
-        configured using the legacy filter configuration functions that accept
-        a CsrLogTextTaskId as origin specifier. However, when not specifying an
-        origin this function also affects origins that have been registered with
-        the legacy csr_log_text.h interface. Furthermore, using this function
-        and the legacy filter configuration functions on the same origin is not
-        allowed.
-
-    PARAMETERS
-        originName - a string containing the name of the origin. Can be NULL or
-            zero length to set the log level for all origins. In this case, the
-            subOriginName parameter will be ignored.
-        subOriginName - a string containing the name of the sub origin. Can be
-            NULL or zero length to set the log level for all sub origins of the
-            specified origin.
-        warningLevelMask - The desired log level for the specified origin(s) and
-            sub origin(s).
-
-*******************************************************************************/
-void CsrLogLevelTextSet(const char *originName,
-    const char *subOriginName,
-    CsrLogLevelText warningLevelMask);
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/drivers/staging/csr/csr_log_text.h b/drivers/staging/csr/csr_log_text.h
index 9fe6c90..cfcf64a 100644
--- a/drivers/staging/csr/csr_log_text.h
+++ b/drivers/staging/csr/csr_log_text.h
@@ -12,10 +12,6 @@
 
 #include "csr_log_configure.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 typedef struct CsrLogSubOrigin
 {
     u16            subOriginNumber;  /* Id of the given SubOrigin */
@@ -125,8 +121,4 @@ void CsrLogTextBufferDebug(CsrLogTextTaskId taskId, u16 subOrigin, size_t buffer
 #define CSR_LOG_TEXT_UNHANDLED_PRIMITIVE(origin, suborigin, primClass, primType)
 #endif
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/drivers/staging/csr/csr_macro.h b/drivers/staging/csr/csr_macro.h
index 57cbfcb..c47f1d9 100644
--- a/drivers/staging/csr/csr_macro.h
+++ b/drivers/staging/csr/csr_macro.h
@@ -12,26 +12,10 @@
 
 #include <linux/types.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define FALSE	(0)
 #define TRUE	(1)
 
 /*------------------------------------------------------------------*/
-/* Bits - intended to operate on u32 values */
-/*------------------------------------------------------------------*/
-#define CSR_MASK_IS_SET(val, mask) (((val) & (mask)) == (mask))
-#define CSR_MASK_IS_UNSET(val, mask) ((((val) & (mask)) ^ mask) == (mask))
-#define CSR_MASK_SET(val, mask)    ((val) |= (mask))
-#define CSR_MASK_UNSET(val, mask)  ((val) = ((val) ^ (mask)) & (val)) /* Unsets the bits in val that are set in mask */
-#define CSR_BIT_IS_SET(val, bit)   ((u8) ((((val) & (1UL << (bit))) != 0)))
-#define CSR_BIT_SET(val, bit)      ((val) |= (1UL << (bit)))
-#define CSR_BIT_UNSET(val, bit)    ((val) &= ~(1UL << (bit)))
-#define CSR_BIT_TOGGLE(val, bit)   ((val) ^= (1UL << (bit)))
-
-/*------------------------------------------------------------------*/
 /* Endian conversion */
 /*------------------------------------------------------------------*/
 #define CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr)        (((u16) ((u8 *) (ptr))[0]) | ((u16) ((u8 *) (ptr))[1]) << 8)
@@ -43,72 +27,13 @@ extern "C" {
     ((u8 *) (ptr))[1] = ((u8) (((uint) >> 8) & 0x000000FF)); \
     ((u8 *) (ptr))[2] = ((u8) (((uint) >> 16) & 0x000000FF)); \
     ((u8 *) (ptr))[3] = ((u8) (((uint) >> 24) & 0x000000FF))
-#define CSR_GET_UINT16_FROM_BIG_ENDIAN(ptr) (((u16) ((u8 *) (ptr))[1]) | ((u16) ((u8 *) (ptr))[0]) << 8)
-#define CSR_GET_UINT24_FROM_BIG_ENDIAN(ptr) (((u32) ((u8 *) (ptr))[2]) | \
-                                             ((u32) ((u8 *) (ptr))[1]) << 8 | ((u32) ((u8 *) (ptr))[0]) << 16)
-#define CSR_GET_UINT32_FROM_BIG_ENDIAN(ptr) (((u32) ((u8 *) (ptr))[3]) | ((u32) ((u8 *) (ptr))[2]) << 8 | \
-                                             ((u32) ((u8 *) (ptr))[1]) << 16 | ((u32) ((u8 *) (ptr))[0]) << 24)
-#define CSR_COPY_UINT16_TO_BIG_ENDIAN(uint, ptr)    ((u8 *) (ptr))[1] = ((u8) ((uint) & 0x00FF)); \
-    ((u8 *) (ptr))[0] = ((u8) ((uint) >> 8))
-#define CSR_COPY_UINT24_TO_BIG_ENDIAN(uint, ptr)    ((u8 *) (ptr))[2] = ((u8) ((uint) & 0x000000FF)); \
-    ((u8 *) (ptr))[1] = ((u8) (((uint) >> 8) & 0x000000FF)); \
-    ((u8 *) (ptr))[0] = ((u8) (((uint) >> 16) & 0x000000FF))
-#define CSR_COPY_UINT32_TO_BIG_ENDIAN(uint, ptr)    ((u8 *) (ptr))[3] = ((u8) ((uint) & 0x000000FF)); \
-    ((u8 *) (ptr))[2] = ((u8) (((uint) >> 8) & 0x000000FF)); \
-    ((u8 *) (ptr))[1] = ((u8) (((uint) >> 16) & 0x000000FF)); \
-    ((u8 *) (ptr))[0] = ((u8) (((uint) >> 24) & 0x000000FF))
-
-/*------------------------------------------------------------------*/
-/* XAP conversion macros */
-/*------------------------------------------------------------------*/
-
-#define CSR_LSB16(a) ((u8) ((a) & 0x00ff))
-#define CSR_MSB16(b) ((u8) ((b) >> 8))
-
-#define CSR_CONVERT_8_FROM_XAP(output, input) \
-    (output) = ((u8) (input));(input) += 2
-
-#define CSR_CONVERT_16_FROM_XAP(output, input) \
-    (output) = (u16) ((((u16) (input)[1]) << 8) | \
-                            ((u16) (input)[0]));(input) += 2
-
-#define CSR_CONVERT_32_FROM_XAP(output, input) \
-    (output) = (((u32) (input)[1]) << 24) | \
-               (((u32) (input)[0]) << 16) | \
-               (((u32) (input)[3]) << 8) | \
-               ((u32) (input)[2]);input += 4
-
-#define CSR_ADD_UINT8_TO_XAP(output, input) \
-    (output)[0] = (input);  \
-    (output)[1] = 0;(output) += 2
-
-#define CSR_ADD_UINT16_TO_XAP(output, input) \
-    (output)[0] = ((u8) ((input) & 0x00FF));  \
-    (output)[1] = ((u8) ((input) >> 8));(output) += 2
-
-#define CSR_ADD_UINT32_TO_XAP(output, input) \
-    (output)[0] = ((u8) (((input) >> 16) & 0x00FF)); \
-    (output)[1] = ((u8) ((input) >> 24)); \
-    (output)[2] = ((u8) ((input) & 0x00FF)); \
-    (output)[3] = ((u8) (((input) >> 8) & 0x00FF));(output) += 4
 
 /*------------------------------------------------------------------*/
 /* Misc */
 /*------------------------------------------------------------------*/
-#define CSRMAX(a, b)    (((a) > (b)) ? (a) : (b))
-#define CSRMIN(a, b)    (((a) < (b)) ? (a) : (b))
-
 /* Use this macro on unused local variables that cannot be removed (such as
    unused function parameters). This will quell warnings from certain compilers
    and static code analysis tools like Lint and Valgrind. */
 #define CSR_UNUSED(x) ((void) (x))
 
-#define CSR_TOUPPER(character)  (((character) >= 'a') && ((character) <= 'z') ? ((character) - 0x20) : (character))
-#define CSR_TOLOWER(character)  (((character) >= 'A') && ((character) <= 'Z') ? ((character) + 0x20) : (character))
-#define CSR_ARRAY_SIZE(x)       (sizeof(x) / sizeof(*(x)))
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/drivers/staging/csr/csr_msg_transport.h b/drivers/staging/csr/csr_msg_transport.h
index b0095b0..8d88e78 100644
--- a/drivers/staging/csr/csr_msg_transport.h
+++ b/drivers/staging/csr/csr_msg_transport.h
@@ -10,16 +10,8 @@
 
 *****************************************************************************/
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef CsrMsgTransport
 #define CsrMsgTransport CsrSchedMessagePut
 #endif
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_MSG_TRANSPORT */
diff --git a/drivers/staging/csr/csr_msgconv.c b/drivers/staging/csr/csr_msgconv.c
index 0081a25..db5e845 100644
--- a/drivers/staging/csr/csr_msgconv.c
+++ b/drivers/staging/csr/csr_msgconv.c
@@ -11,7 +11,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/slab.h>
-#include "csr_panic.h"
 #include "csr_sched.h"
 #include "csr_msgconv.h"
 #include "csr_macro.h"
diff --git a/drivers/staging/csr/csr_msgconv.h b/drivers/staging/csr/csr_msgconv.h
index 09489f3..7e4dd38 100644
--- a/drivers/staging/csr/csr_msgconv.h
+++ b/drivers/staging/csr/csr_msgconv.h
@@ -15,10 +15,6 @@
 #include "csr_prim_defs.h"
 #include "csr_sched.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 typedef size_t (CsrMsgSizeofFunc)(void *msg);
 typedef u8 *(CsrMsgSerializeFunc)(u8 *buffer, size_t *length, void *msg);
 typedef void (CsrMsgFreeFunc)(void *msg);
@@ -79,9 +75,4 @@ void CsrUint32Des(u32 *value, u8 *buffer, size_t *offset);
 void CsrMemCpyDes(void *value, u8 *buffer, size_t *offset, size_t length);
 void CsrCharStringDes(char **value, u8 *buffer, size_t *offset);
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/drivers/staging/csr/csr_panic.c b/drivers/staging/csr/csr_panic.c
deleted file mode 100644
index 095f7fa..0000000
--- a/drivers/staging/csr/csr_panic.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*****************************************************************************
-
-            (c) Cambridge Silicon Radio Limited 2010
-            All rights reserved and confidential information of CSR
-
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
-
-*****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include "csr_panic.h"
-
-void CsrPanic(u8 tech, u16 reason, const char *p)
-{
-    BUG_ON(1);
-}
-EXPORT_SYMBOL_GPL(CsrPanic);
diff --git a/drivers/staging/csr/csr_panic.h b/drivers/staging/csr/csr_panic.h
deleted file mode 100644
index 37989fc..0000000
--- a/drivers/staging/csr/csr_panic.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef CSR_PANIC_H__
-#define CSR_PANIC_H__
-/*****************************************************************************
-
-            (c) Cambridge Silicon Radio Limited 2010
-            All rights reserved and confidential information of CSR
-
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
-
-*****************************************************************************/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Synergy techonology ID definitions */
-#define CSR_TECH_FW     0
-#define CSR_TECH_BT     1
-#define CSR_TECH_WIFI   2
-#define CSR_TECH_GPS    3
-#define CSR_TECH_NFC    4
-
-/* Panic type ID definitions for technology type CSR_TECH_FW */
-#define CSR_PANIC_FW_UNEXPECTED_VALUE        0
-#define CSR_PANIC_FW_HEAP_EXHAUSTION         1
-#define CSR_PANIC_FW_INVALID_PFREE_POINTER   2
-#define CSR_PANIC_FW_EXCEPTION               3
-#define CSR_PANIC_FW_ASSERTION_FAIL          4
-#define CSR_PANIC_FW_NULL_TASK_HANDLER       5
-#define CSR_PANIC_FW_UNKNOWN_TASK            6
-#define CSR_PANIC_FW_QUEUE_ACCESS_VIOLATION  7
-#define CSR_PANIC_FW_TOO_MANY_MESSAGES       8
-#define CSR_PANIC_FW_TOO_MANY_TIMED_EVENTS   9
-#define CSR_PANIC_FW_ABCSP_SYNC_LOST        10
-#define CSR_PANIC_FW_OVERSIZE_ABCSP_PRIM    11
-#define CSR_PANIC_FW_H4_CORRUPTION          12
-#define CSR_PANIC_FW_H4_SYNC_LOST           13
-#define CSR_PANIC_FW_H4_RX_OVERRUN          14
-#define CSR_PANIC_FW_H4_TX_OVERRUN          15
-#define CSR_PANIC_FW_TM_BC_RESTART_FAIL     16
-#define CSR_PANIC_FW_TM_BC_START_FAIL       17
-#define CSR_PANIC_FW_TM_BC_BAD_STATE        18
-#define CSR_PANIC_FW_TM_BC_TRANSPORT_LOST   19
-
-/* Panic interface used by technologies */
-/* DEPRECATED - replaced by csr_log_text.h */
-void CsrPanic(u8 tech, u16 reason, const char *p);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* CSR_PANIC_H__ */
diff --git a/drivers/staging/csr/csr_prim_defs.h b/drivers/staging/csr/csr_prim_defs.h
index 6a7f73d..81a1eaa 100644
--- a/drivers/staging/csr/csr_prim_defs.h
+++ b/drivers/staging/csr/csr_prim_defs.h
@@ -9,9 +9,6 @@
             on the license terms.
 
 *****************************************************************************/
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 /************************************************************************************
  * Segmentation of primitives in upstream and downstream segment
@@ -55,8 +52,4 @@ typedef u16 CsrPrim;
 
 #define CSR_ENV_PRIM                        ((u16) (0x00FF | CSR_SYNERGY_EVENT_CLASS_MISC_BASE))
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_PRIM_DEFS_H__ */
diff --git a/drivers/staging/csr/csr_result.h b/drivers/staging/csr/csr_result.h
index c7c36d6..cbb607d 100644
--- a/drivers/staging/csr/csr_result.h
+++ b/drivers/staging/csr/csr_result.h
@@ -10,16 +10,8 @@
 
 *****************************************************************************/
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 typedef u16 CsrResult;
 #define CSR_RESULT_SUCCESS  ((CsrResult) 0x0000)
 #define CSR_RESULT_FAILURE  ((CsrResult) 0xFFFF)
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/drivers/staging/csr/csr_sched.h b/drivers/staging/csr/csr_sched.h
index cc1b8bf..c7d672c 100644
--- a/drivers/staging/csr/csr_sched.h
+++ b/drivers/staging/csr/csr_sched.h
@@ -12,10 +12,6 @@
 #include <linux/types.h>
 #include "csr_time.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* An identifier issued by the scheduler. */
 typedef u32 CsrSchedIdentifier;
 
@@ -24,7 +20,6 @@ typedef u16 CsrSchedTaskId;
 
 /* A queue identifier */
 typedef u16 CsrSchedQid;
-#define CSR_SCHED_QID_INVALID     ((CsrSchedQid) 0xFFFF)
 
 /* A message identifier */
 typedef CsrSchedIdentifier CsrSchedMsgId;
@@ -33,14 +28,11 @@ typedef CsrSchedIdentifier CsrSchedMsgId;
 typedef CsrSchedIdentifier CsrSchedTid;
 #define CSR_SCHED_TID_INVALID     ((CsrSchedTid) 0)
 
-/* Scheduler entry functions share this structure */
-typedef void (*schedEntryFunction_t)(void **inst);
-
 /* Time constants. */
-#define CSR_SCHED_TIME_MAX                ((CsrTime) 0xFFFFFFFF)
-#define CSR_SCHED_MILLISECOND             ((CsrTime) (1000))
-#define CSR_SCHED_SECOND                  ((CsrTime) (1000 * CSR_SCHED_MILLISECOND))
-#define CSR_SCHED_MINUTE                  ((CsrTime) (60 * CSR_SCHED_SECOND))
+#define CSR_SCHED_TIME_MAX                (0xFFFFFFFF)
+#define CSR_SCHED_MILLISECOND             (1000)
+#define CSR_SCHED_SECOND                  (1000 * CSR_SCHED_MILLISECOND)
+#define CSR_SCHED_MINUTE                  (60 * CSR_SCHED_SECOND)
 
 /* Queue and primitive that identifies the environment */
 #define CSR_SCHED_TASK_ID        0xFFFF
@@ -53,60 +45,6 @@ typedef void (*schedEntryFunction_t)(void **inst);
 typedef u16 CsrSchedBgint;
 #define CSR_SCHED_BGINT_INVALID ((CsrSchedBgint) 0xFFFF)
 
-typedef void (*CsrSchedBgintHandler)(void *);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrSchedBgintReg
- *
- *  DESCRIPTION
- *      Register a background interrupt handler function with the scheduler.
- *        When CsrSchedBgint() is called from the foreground (e.g. an interrupt
- *        routine) the registered function is called.
- *
- *        If "cb" is null then the interrupt is effectively disabled. If a
- *        no bgints are available, CSR_SCHED_BGINT_INVALID is returned, otherwise
- *        a CsrSchedBgint value is returned to be used in subsequent calls to
- *        CsrSchedBgint().  id is a possibly NULL identifier used for logging
- *        purposes only.
- *
- *  RETURNS
- *      CsrSchedBgint -- CSR_SCHED_BGINT_INVALID denotes failure to obtain a CsrSchedBgintSet.
- *
- *----------------------------------------------------------------------------*/
-CsrSchedBgint CsrSchedBgintReg(CsrSchedBgintHandler cb,
-    void *context,
-    const char *id);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrSchedBgintUnreg
- *
- *  DESCRIPTION
- *      Unregister a background interrupt handler function.
- *
- *      ``irq'' is a background interrupt handle previously obtained
- *      from a call to CsrSchedBgintReg().
- *
- *  RETURNS
- *      void.
- *
- *----------------------------------------------------------------------------*/
-void CsrSchedBgintUnreg(CsrSchedBgint bgint);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrSchedBgintSet
- *
- *  DESCRIPTION
- *      Set background interrupt.
- *
- *  RETURNS
- *      void.
- *
- *----------------------------------------------------------------------------*/
-void CsrSchedBgintSet(CsrSchedBgint bgint);
-
 /*----------------------------------------------------------------------------*
  *  NAME
  *      CsrSchedMessagePut
@@ -144,149 +82,4 @@ void CsrSchedMessagePut(CsrSchedQid q,
     void *mv);
 #endif
 
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrSchedMessageBroadcast
- *
- *  DESCRIPTION
- *      Sends a message to all tasks.
- *
- *      The user must supply a "factory function" that is called once
- *      for every task that exists. The "factory function", msg_build_func,
- *      must allocate and initialise the message and set the msg_build_ptr
- *      to point to the message when done.
- *
- *  NOTE
- *      N/A
- *
- *  RETURNS
- *      void
- *
- *----------------------------------------------------------------------------*/
-#if defined(CSR_LOG_ENABLE) && defined(CSR_LOG_INCLUDE_FILE_NAME_AND_LINE_NUMBER)
-void CsrSchedMessageBroadcastStringLog(u16 mi,
-    void *(*msg_build_func)(void *),
-    void *msg_build_ptr,
-    u32 line,
-    const char *file);
-#define CsrSchedMessageBroadcast(mi, fn, ptr) CsrSchedMessageBroadcastStringLog((mi), (fn), (ptr), __LINE__, __FILE__)
-#else
-void CsrSchedMessageBroadcast(u16 mi,
-    void *(*msg_build_func)(void *),
-    void *msg_build_ptr);
-#endif
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrSchedMessageGet
- *
- *  DESCRIPTION
- *      Obtains a message from the message queue belonging to the calling task.
- *      The message consists of one or both of a u16 and a void *.
- *
- *  RETURNS
- *      u8 - TRUE if a message has been obtained from the queue, else FALSE.
- *      If a message is taken from the queue, then "*pmi" and "*pmv" are set to
- *      the "mi" and "mv" passed to CsrSchedMessagePut() respectively.
- *
- *      "pmi" and "pmv" can be null, in which case the corresponding value from
- *      them message is discarded.
- *
- *----------------------------------------------------------------------------*/
-u8 CsrSchedMessageGet(u16 *pmi, void **pmv);
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrSchedTimerSet
- *
- *  DESCRIPTION
- *      Causes the void function "fn" to be called with the arguments
- *      "fniarg" and "fnvarg" after "delay" has elapsed.
- *
- *      "delay" must be less than half the range of a CsrTime.
- *
- *      CsrSchedTimerSet() does nothing with "fniarg" and "fnvarg" except
- *      deliver them via a call to "fn()".   (Unless CsrSchedTimerCancel()
- *      is used to prevent delivery.)
- *
- *  NOTE
- *      The function will be called at or after "delay"; the actual delay will
- *      depend on the timing behaviour of the scheduler's tasks.
- *
- *  RETURNS
- *      CsrSchedTid - A timed event identifier, can be used in CsrSchedTimerCancel().
- *
- *----------------------------------------------------------------------------*/
-#if defined(CSR_LOG_ENABLE) && defined(CSR_LOG_INCLUDE_FILE_NAME_AND_LINE_NUMBER)
-CsrSchedTid CsrSchedTimerSetStringLog(CsrTime delay,
-    void (*fn)(u16 mi, void *mv),
-    u16 fniarg,
-    void *fnvarg,
-    u32 line,
-    const char *file);
-#define CsrSchedTimerSet(d, fn, fni, fnv) CsrSchedTimerSetStringLog((d), (fn), (fni), (fnv), __LINE__, __FILE__)
-#else
-CsrSchedTid CsrSchedTimerSet(CsrTime delay,
-    void (*fn)(u16 mi, void *mv),
-    u16 fniarg,
-    void *fnvarg);
-#endif
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrSchedTimerCancel
- *
- *  DESCRIPTION
- *      Attempts to prevent the timed event with identifier "eventid" from
- *      occurring.
- *
- *  RETURNS
- *      u8 - TRUE if cancelled, FALSE if the event has already occurred.
- *
- *----------------------------------------------------------------------------*/
-#if defined(CSR_LOG_ENABLE) && defined(CSR_LOG_INCLUDE_FILE_NAME_AND_LINE_NUMBER)
-u8 CsrSchedTimerCancelStringLog(CsrSchedTid eventid,
-    u16 *pmi,
-    void **pmv,
-    u32 line,
-    const char *file);
-#define CsrSchedTimerCancel(e, pmi, pmv) CsrSchedTimerCancelStringLog((e), (pmi), (pmv), __LINE__, __FILE__)
-#else
-u8 CsrSchedTimerCancel(CsrSchedTid eventid,
-    u16 *pmi,
-    void **pmv);
-#endif
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrSchedTaskQueueGet
- *
- *  DESCRIPTION
- *      Return the queue identifier for the currently running queue
- *
- *  RETURNS
- *      CsrSchedQid - The current task queue identifier, or 0xFFFF if not available.
- *
- *----------------------------------------------------------------------------*/
-CsrSchedQid CsrSchedTaskQueueGet(void);
-
-
-/*----------------------------------------------------------------------------*
- *  NAME
- *      CsrSchedTaskQueueGet
- *
- *  DESCRIPTION
- *      Return the queue identifier for the currently running queue
- *
- *  RETURNS
- *      char - The current task queue identifier, or 0xFFFF if not available.
- *
- *----------------------------------------------------------------------------*/
-char* CsrSchedTaskNameGet(CsrSchedQid );
-
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/drivers/staging/csr/csr_sdio.h b/drivers/staging/csr/csr_sdio.h
index f0cda84..624a53f 100644
--- a/drivers/staging/csr/csr_sdio.h
+++ b/drivers/staging/csr/csr_sdio.h
@@ -12,10 +12,6 @@
 
 #include "csr_result.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* Result Codes */
 #define CSR_SDIO_RESULT_INVALID_VALUE   ((CsrResult) 1) /* Invalid argument value */
 #define CSR_SDIO_RESULT_NO_DEVICE       ((CsrResult) 2) /* The specified device is no longer present */
@@ -724,8 +720,4 @@ CsrResult CsrSdioHardReset(CsrSdioFunction *function);
 void CsrSdioFunctionActive(CsrSdioFunction *function);
 void CsrSdioFunctionIdle(CsrSdioFunction *function);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/drivers/staging/csr/csr_serialize_primitive_types.c b/drivers/staging/csr/csr_serialize_primitive_types.c
index bf5e4ab..9713b9a 100644
--- a/drivers/staging/csr/csr_serialize_primitive_types.c
+++ b/drivers/staging/csr/csr_serialize_primitive_types.c
@@ -13,7 +13,6 @@
 #include "csr_prim_defs.h"
 #include "csr_msgconv.h"
 #include "csr_macro.h"
-#include "csr_lib.h"
 
 void CsrUint8Des(u8 *value, u8 *buffer, size_t *offset)
 {
diff --git a/drivers/staging/csr/csr_time.c b/drivers/staging/csr/csr_time.c
index 7b597f7..f3f4a9c 100644
--- a/drivers/staging/csr/csr_time.c
+++ b/drivers/staging/csr/csr_time.c
@@ -9,25 +9,24 @@
 *****************************************************************************/
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/time.h>
 #include <linux/module.h>
 
 #include "csr_time.h"
 
-CsrTime CsrTimeGet(CsrTime *high)
+u32 CsrTimeGet(u32 *high)
 {
 	struct timespec ts;
 	u64 time;
-	CsrTime low;
+	u32 low;
 
 	ts = current_kernel_time();
 	time = (u64) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
 
 	if (high != NULL)
-		*high = (CsrTime) ((time >> 32) & 0xFFFFFFFF);
+		*high = (u32) ((time >> 32) & 0xFFFFFFFF);
 
-	low = (CsrTime) (time & 0xFFFFFFFF);
+	low = (u32) (time & 0xFFFFFFFF);
 
 	return low;
 }
diff --git a/drivers/staging/csr/csr_time.h b/drivers/staging/csr/csr_time.h
index 2a45f3e..fc29e8e 100644
--- a/drivers/staging/csr/csr_time.h
+++ b/drivers/staging/csr/csr_time.h
@@ -2,77 +2,43 @@
 #define CSR_TIME_H__
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2010
-            All rights reserved and confidential information of CSR
+(c) Cambridge Silicon Radio Limited 2010
+All rights reserved and confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+Refer to LICENSE.txt included with this source for details
+on the license terms.
 
 *****************************************************************************/
 
 #include <linux/types.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*******************************************************************************
-
-    NAME
-        CsrTime
-
-    DESCRIPTION
-        Type to hold a value describing the current system time, which is a
-        measure of time elapsed since some arbitrarily defined fixed time
-        reference, usually associated with system startup.
-
-*******************************************************************************/
-typedef u32 CsrTime;
-
-
 /*******************************************************************************
 
-    NAME
-        CsrTimeUtc
+NAME
+	CsrTimeGet
 
-    DESCRIPTION
-        Type to hold a value describing a UTC wallclock time expressed in
-        seconds and milliseconds elapsed since midnight January 1st 1970.
+DESCRIPTION
+	Returns the current system time in a low and a high part. The low part
+	is expressed in microseconds. The high part is incremented when the low
+	part wraps to provide an extended range.
 
-*******************************************************************************/
-typedef struct
-{
-    u32 sec;
-    u16 msec;
-} CsrTimeUtc;
-
-
-/*******************************************************************************
-
-    NAME
-        CsrTimeGet
+	The caller may provide a NULL pointer as the high parameter.
+	In this case the function just returns the low part and ignores the
+	high parameter.
 
-    DESCRIPTION
-        Returns the current system time in a low and a high part. The low part
-        is expressed in microseconds. The high part is incremented when the low
-        part wraps to provide an extended range.
+	Although the time is expressed in microseconds the actual resolution is
+	platform dependent and can be less. It is recommended that the
+	resolution is at least 10 milliseconds.
 
-        The caller may provide a NULL pointer as the high parameter. In this case
-        the function just returns the low part and ignores the high parameter.
+PARAMETERS
+	high - Pointer to variable that will receive the high part of the
+	       current system time. Passing NULL is valid.
 
-        Although the time is expressed in microseconds the actual resolution is
-        platform dependent and can be less. It is recommended that the
-        resolution is at least 10 milliseconds.
-
-    PARAMETERS
-        high - Pointer to variable that will receive the high part of the
-               current system time. Passing NULL is valid.
-
-    RETURNS
-        Low part of current system time in microseconds.
+RETURNS
+	Low part of current system time in microseconds.
 
 *******************************************************************************/
-CsrTime CsrTimeGet(CsrTime *high);
+u32 CsrTimeGet(u32 *high);
 
 
 /*------------------------------------------------------------------*/
@@ -107,8 +73,4 @@ CsrTime CsrTimeGet(CsrTime *high);
  *----------------------------------------------------------------------------*/
 #define CsrTimeSub(t1, t2)    ((s32) (t1) - (s32) (t2))
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/drivers/staging/csr/csr_wifi_common.h b/drivers/staging/csr/csr_wifi_common.h
index cc41a94..efc43a5 100644
--- a/drivers/staging/csr/csr_wifi_common.h
+++ b/drivers/staging/csr/csr_wifi_common.h
@@ -14,10 +14,6 @@
 #include <linux/types.h>
 #include "csr_result.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* MAC address */
 typedef struct
 {
@@ -101,9 +97,5 @@ typedef struct
 
 #define CSR_WIFI_VERSION	"5.1.0.0"
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
 
diff --git a/drivers/staging/csr/csr_wifi_fsm.h b/drivers/staging/csr/csr_wifi_fsm.h
index 073e2f8..fde1508 100644
--- a/drivers/staging/csr/csr_wifi_fsm.h
+++ b/drivers/staging/csr/csr_wifi_fsm.h
@@ -11,10 +11,6 @@
 #ifndef CSR_WIFI_FSM_H
 #define CSR_WIFI_FSM_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "csr_prim_defs.h"
 #include "csr_log_text.h"
 #include "csr_wifi_fsm_event.h"
@@ -240,9 +236,5 @@ extern u8 CsrWifiFsmHasEvents(CsrWifiFsmContext *context);
  */
 extern void CsrWifiFsmInstallWakeupCallback(CsrWifiFsmContext *context, CsrWifiFsmExternalWakupCallbackPtr callback);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_FSM_H */
 
diff --git a/drivers/staging/csr/csr_wifi_fsm_event.h b/drivers/staging/csr/csr_wifi_fsm_event.h
index 57a5caf..0690ca9 100644
--- a/drivers/staging/csr/csr_wifi_fsm_event.h
+++ b/drivers/staging/csr/csr_wifi_fsm_event.h
@@ -11,10 +11,6 @@
 #ifndef CSR_WIFI_FSM_EVENT_H
 #define CSR_WIFI_FSM_EVENT_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "csr_prim_defs.h"
 #include "csr_sched.h"
 
@@ -42,9 +38,5 @@ typedef struct CsrWifiFsmEvent
     struct CsrWifiFsmEvent *next;
 } CsrWifiFsmEvent;
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_FSM_EVENT_H */
 
diff --git a/drivers/staging/csr/csr_wifi_fsm_types.h b/drivers/staging/csr/csr_wifi_fsm_types.h
index 26752bf..d21c60a 100644
--- a/drivers/staging/csr/csr_wifi_fsm_types.h
+++ b/drivers/staging/csr/csr_wifi_fsm_types.h
@@ -11,13 +11,8 @@
 #ifndef CSR_WIFI_FSM_TYPES_H
 #define CSR_WIFI_FSM_TYPES_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include <linux/types.h>
 #include "csr_macro.h"
-#include "csr_panic.h"
 #include "csr_sched.h"
 
 #ifdef CSR_WIFI_FSM_MUTEX_ENABLE
@@ -432,9 +427,4 @@ struct CsrWifiFsmContext
 #endif
 };
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_FSM_TYPES_H */
diff --git a/drivers/staging/csr/csr_wifi_hip_card.h b/drivers/staging/csr/csr_wifi_hip_card.h
index 9caf88c..bd47f60 100644
--- a/drivers/staging/csr/csr_wifi_hip_card.h
+++ b/drivers/staging/csr/csr_wifi_hip_card.h
@@ -21,10 +21,6 @@
 #ifndef __CARD_H__
 #define __CARD_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "csr_wifi_hip_card_sdio.h"
 #include "csr_wifi_hip_signals.h"
 #include "csr_wifi_hip_unifi_udi.h"
@@ -115,9 +111,4 @@ void unifi_debug_string_to_buf(const char *str);
 void unifi_debug_hex_to_buf(const char *buff, u16 length);
 #endif
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* __CARD_H__ */
diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio.c b/drivers/staging/csr/csr_wifi_hip_card_sdio.c
index cf148a0..25cabf32 100644
--- a/drivers/staging/csr/csr_wifi_hip_card_sdio.c
+++ b/drivers/staging/csr/csr_wifi_hip_card_sdio.c
@@ -70,8 +70,6 @@ card_t* unifi_alloc_card(CsrSdioFunction *sdio, void *ospriv)
     card_t *card;
     u32 i;
 
-    func_enter();
-
 
     card = kzalloc(sizeof(card_t), GFP_KERNEL);
     if (card == NULL)
@@ -148,7 +146,6 @@ card_t* unifi_alloc_card(CsrSdioFunction *sdio, void *ospriv)
         }
     }
 #endif
-    func_exit();
     return card;
 } /* unifi_alloc_card() */
 
@@ -171,35 +168,29 @@ CsrResult unifi_init_card(card_t *card, s32 led_mask)
 {
     CsrResult r;
 
-    func_enter();
 
     if (card == NULL)
     {
-        func_exit_r(CSR_WIFI_HIP_RESULT_INVALID_VALUE);
         return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
     }
 
     r = unifi_init(card);
     if (r != CSR_RESULT_SUCCESS)
     {
-        func_exit_r(r);
         return r;
     }
 
     r = unifi_hip_init(card);
     if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
     {
-        func_exit_r(r);
         return r;
     }
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_error(card->ospriv, "Failed to start host protocol.\n");
-        func_exit_r(r);
         return r;
     }
 
-    func_exit();
     return CSR_RESULT_SUCCESS;
 }
 
@@ -223,11 +214,8 @@ CsrResult unifi_init(card_t *card)
     CsrResult r;
     CsrResult csrResult;
 
-    func_enter();
-
     if (card == NULL)
     {
-        func_exit_r(CSR_WIFI_HIP_RESULT_INVALID_VALUE);
         return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
     }
 
@@ -250,7 +238,6 @@ CsrResult unifi_init(card_t *card)
     if (csrResult != CSR_RESULT_SUCCESS)
     {
         r = ConvertCsrSdioToCsrHipResult(card, csrResult);
-        func_exit_r(r);
         return r;
     }
     card->sdio_clock_speed = UNIFI_SDIO_CLOCK_SAFE_HZ;
@@ -268,7 +255,6 @@ CsrResult unifi_init(card_t *card)
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_error(card->ospriv, "Failed to reset UniFi\n");
-        func_exit_r(r);
         return r;
     }
 
@@ -278,7 +264,6 @@ CsrResult unifi_init(card_t *card)
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_error(card->ospriv, "Failed to set power save mode\n");
-        func_exit_r(r);
         return r;
     }
 
@@ -298,7 +283,6 @@ CsrResult unifi_init(card_t *card)
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_error(card->ospriv, "Failed to write SHARED_DMEM_PAGE\n");
-        func_exit_r(r);
         return r;
     }
     r = unifi_write_direct16(card, ChipHelper_HOST_WINDOW2_PAGE(card->helper) * 2, 0);
@@ -309,7 +293,6 @@ CsrResult unifi_init(card_t *card)
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_error(card->ospriv, "Failed to write PROG_MEM2_PAGE\n");
-        func_exit_r(r);
         return r;
     }
 
@@ -338,7 +321,6 @@ CsrResult unifi_init(card_t *card)
         unifi_error(card->ospriv, "Probe for Flash failed\n");
     }
 
-    func_exit_r(r);
     return r;
 } /* unifi_init() */
 
@@ -363,11 +345,8 @@ CsrResult unifi_download(card_t *card, s32 led_mask)
     CsrResult r;
     void *dlpriv;
 
-    func_enter();
-
     if (card == NULL)
     {
-        func_exit_r(CSR_WIFI_HIP_RESULT_INVALID_VALUE);
         return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
     }
 
@@ -380,7 +359,6 @@ CsrResult unifi_download(card_t *card, s32 led_mask)
     dlpriv = unifi_dl_fw_read_start(card, UNIFI_FW_STA);
     if (dlpriv == NULL)
     {
-        func_exit_r(CSR_WIFI_HIP_RESULT_NOT_FOUND);
         return CSR_WIFI_HIP_RESULT_NOT_FOUND;
     }
 
@@ -389,15 +367,12 @@ CsrResult unifi_download(card_t *card, s32 led_mask)
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_error(card->ospriv, "Failed to download firmware\n");
-        func_exit_r(r);
         return r;
     }
 
     /* Free the firmware file information. */
     unifi_fw_read_stop(card->ospriv, dlpriv);
 
-    func_exit();
-
     return CSR_RESULT_SUCCESS;
 } /* unifi_download() */
 
@@ -425,8 +400,6 @@ static CsrResult unifi_hip_init(card_t *card)
     CsrResult r;
     CsrResult csrResult;
 
-    func_enter();
-
     r = card_hw_init(card);
     if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
     {
@@ -435,7 +408,6 @@ static CsrResult unifi_hip_init(card_t *card)
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_error(card->ospriv, "Failed to establish communication with UniFi\n");
-        func_exit_r(r);
         return r;
     }
 #ifdef CSR_PRE_ALLOC_NET_DATA
@@ -455,7 +427,6 @@ static CsrResult unifi_hip_init(card_t *card)
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_error(card->ospriv, "Init slots failed: %d\n", r);
-        func_exit_r(r);
         return r;
     }
 
@@ -464,7 +435,6 @@ static CsrResult unifi_hip_init(card_t *card)
     r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE);
     if (r != CSR_RESULT_SUCCESS)
     {
-        func_exit_r(r);
         return r;
     }
 
@@ -479,12 +449,9 @@ static CsrResult unifi_hip_init(card_t *card)
     r = CardGenInt(card);
     if (r != CSR_RESULT_SUCCESS)
     {
-        func_exit_r(r);
         return r;
     }
 
-    func_exit();
-
     return CSR_RESULT_SUCCESS;
 } /* unifi_hip_init() */
 
@@ -609,8 +576,6 @@ static CsrResult card_hw_init(card_t *card)
     s16 search_4slut_again;
     CsrResult csrResult;
 
-    func_enter();
-
     /*
      * The device revision from the TPLMID_MANF and TPLMID_CARD fields
      * of the CIS are available as
@@ -635,7 +600,6 @@ static CsrResult card_hw_init(card_t *card)
         if (r != CSR_RESULT_SUCCESS)
         {
             unifi_error(card->ospriv, "Firmware hasn't started\n");
-            func_exit_r(r);
             return r;
         }
         unifi_trace(card->ospriv, UDBG4, "SLUT addr 0x%lX\n", slut_address);
@@ -652,7 +616,6 @@ static CsrResult card_hw_init(card_t *card)
         if (csrResult != CSR_RESULT_SUCCESS)
         {
             r = ConvertCsrSdioToCsrHipResult(card, csrResult);
-            func_exit_r(r);
             return r;
         }
         card->sdio_clock_speed = UNIFI_SDIO_CLOCK_INIT_HZ;
@@ -671,14 +634,12 @@ static CsrResult card_hw_init(card_t *card)
         if (r != CSR_RESULT_SUCCESS)
         {
             unifi_error(card->ospriv, "Failed to read SLUT finger print\n");
-            func_exit_r(r);
             return r;
         }
 
         if (finger_print != SLUT_FINGERPRINT)
         {
             unifi_error(card->ospriv, "Failed to find Symbol lookup table fingerprint\n");
-            func_exit_r(CSR_RESULT_FAILURE);
             return CSR_RESULT_FAILURE;
         }
 
@@ -696,7 +657,6 @@ static CsrResult card_hw_init(card_t *card)
             r = unifi_card_read16(card, slut_address, &s);
             if (r != CSR_RESULT_SUCCESS)
             {
-                func_exit_r(r);
                 return r;
             }
             slut_address += 2;
@@ -710,7 +670,6 @@ static CsrResult card_hw_init(card_t *card)
             r = unifi_read32(card, slut_address, &l);
             if (r != CSR_RESULT_SUCCESS)
             {
-                func_exit_r(r);
                 return r;
             }
             slut_address += 4;
@@ -739,7 +698,6 @@ static CsrResult card_hw_init(card_t *card)
                     if (r != CSR_RESULT_SUCCESS)
                     {
                         unifi_error(card->ospriv, "Failed to read config data\n");
-                        func_exit_r(r);
                         return r;
                     }
                     /* .. and then we copy the data to the host structure */
@@ -753,7 +711,6 @@ static CsrResult card_hw_init(card_t *card)
                     {
                         unifi_error(card->ospriv, "From host data slots %d\n", cfg_data->num_fromhost_data_slots);
                         unifi_error(card->ospriv, "need to be (queues * x + 2) (UNIFI_RESERVED_COMMAND_SLOTS for commands)\n");
-                        func_exit_r(CSR_RESULT_FAILURE);
                         return CSR_RESULT_FAILURE;
                     }
 
@@ -781,7 +738,6 @@ static CsrResult card_hw_init(card_t *card)
                         if ((card->sdio_io_block_size % cfg_data->sig_frag_size) != 0)
                         {
                             unifi_error(card->ospriv, "Configuration error: Can not pad to-host signals.\n");
-                            func_exit_r(CSR_WIFI_HIP_RESULT_INVALID_VALUE);
                             return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
                         }
                         cfg_data->tohost_signal_padding = (u16) (card->sdio_io_block_size / cfg_data->sig_frag_size);
@@ -795,7 +751,6 @@ static CsrResult card_hw_init(card_t *card)
                         if (r != CSR_RESULT_SUCCESS)
                         {
                             unifi_error(card->ospriv, "Failed to write To-Host Signal Padding Fragments\n");
-                            func_exit_r(r);
                             return r;
                         }
                     }
@@ -818,7 +773,6 @@ static CsrResult card_hw_init(card_t *card)
                     if (r != CSR_RESULT_SUCCESS)
                     {
                         unifi_error(card->ospriv, "Failed to read build id\n");
-                        func_exit_r(r);
                         return r;
                     }
                     card->build_id = n;
@@ -835,7 +789,6 @@ static CsrResult card_hw_init(card_t *card)
                     if (r != CSR_RESULT_SUCCESS)
                     {
                         unifi_error(card->ospriv, "Failed to read build string\n");
-                        func_exit_r(r);
                         return r;
                     }
                     break;
@@ -853,7 +806,6 @@ static CsrResult card_hw_init(card_t *card)
                     if (r != CSR_RESULT_SUCCESS)
                     {
                         unifi_error(card->ospriv, "Failed to write loader load image command\n");
-                        func_exit_r(r);
                         return r;
                     }
 
@@ -871,7 +823,6 @@ static CsrResult card_hw_init(card_t *card)
                         if (r != CSR_RESULT_SUCCESS)
                         {
                             unifi_error(card->ospriv, "Failed to patch firmware\n");
-                            func_exit_r(r);
                             return r;
                         }
                     }
@@ -882,7 +833,6 @@ static CsrResult card_hw_init(card_t *card)
                     if (r != CSR_RESULT_SUCCESS)
                     {
                         unifi_error(card->ospriv, "Failed to write loader restart command\n");
-                        func_exit_r(r);
                         return r;
                     }
 
@@ -913,7 +863,6 @@ static CsrResult card_hw_init(card_t *card)
     if (cfg_data == NULL)
     {
         unifi_error(card->ospriv, "Failed to find SDIO_SLOT_CONFIG Symbol\n");
-        func_exit_r(CSR_RESULT_FAILURE);
         return CSR_RESULT_FAILURE;
     }
 
@@ -930,12 +879,10 @@ static CsrResult card_hw_init(card_t *card)
     {
         unifi_error(card->ospriv, "Failed to read init flag at %08lx\n",
                     card->init_flag_addr);
-        func_exit_r(r);
         return r;
     }
     if (initialised != 0)
     {
-        func_exit_r(CSR_RESULT_FAILURE);
         return CSR_RESULT_FAILURE;
     }
 
@@ -957,7 +904,6 @@ static CsrResult card_hw_init(card_t *card)
         unifi_error(card->ospriv, "UniFi f/w protocol major version (%d) is different from driver (v%d.%d)\n",
                     major, UNIFI_HIP_MAJOR_VERSION, UNIFI_HIP_MINOR_VERSION);
 #ifndef CSR_WIFI_DISABLE_HIP_VERSION_CHECK
-        func_exit_r(CSR_RESULT_FAILURE);
         return CSR_RESULT_FAILURE;
 #endif
     }
@@ -967,7 +913,6 @@ static CsrResult card_hw_init(card_t *card)
                     major, minor,
                     UNIFI_HIP_MAJOR_VERSION, UNIFI_HIP_MINOR_VERSION);
 #ifndef CSR_WIFI_DISABLE_HIP_VERSION_CHECK
-        func_exit_r(CSR_RESULT_FAILURE);
         return CSR_RESULT_FAILURE;
 #endif
     }
@@ -978,7 +923,6 @@ static CsrResult card_hw_init(card_t *card)
      */
     unifi_read_panic(card);
 
-    func_exit();
     return CSR_RESULT_SUCCESS;
 } /* card_hw_init() */
 
@@ -1004,8 +948,6 @@ static CsrResult card_wait_for_unifi_to_reset(card_t *card)
     u8 io_enable;
     CsrResult csrResult;
 
-    func_enter();
-
     r = CSR_RESULT_SUCCESS;
     for (i = 0; i < MAILBOX2_ATTEMPTS; i++)
     {
@@ -1107,7 +1049,6 @@ static CsrResult card_wait_for_unifi_to_reset(card_t *card)
         r = CSR_RESULT_FAILURE;
     }
 
-    func_exit();
     return r;
 } /* card_wait_for_unifi_to_reset() */
 
@@ -1136,14 +1077,11 @@ static CsrResult card_wait_for_unifi_to_disable(card_t *card)
     u8 io_enable;
     CsrResult csrResult;
 
-    func_enter();
-
     if (card->chip_id <= SDIO_CARD_ID_UNIFI_2)
     {
         unifi_error(card->ospriv,
                     "Function reset method not supported for chip_id=%d\n",
                     card->chip_id);
-        func_exit();
         return CSR_RESULT_FAILURE;
     }
 
@@ -1210,7 +1148,6 @@ static CsrResult card_wait_for_unifi_to_disable(card_t *card)
         r = CSR_RESULT_FAILURE;
     }
 
-    func_exit();
     return r;
 } /* card_wait_for_unifi_to_reset() */
 
@@ -1238,8 +1175,6 @@ CsrResult card_wait_for_firmware_to_start(card_t *card, u32 *paddr)
     u16 mbox0, mbox1;
     CsrResult r;
 
-    func_enter();
-
     /*
      * Wait for UniFi to initialise its data structures by polling
      * the SHARED_MAILBOX1 register.
@@ -1277,7 +1212,6 @@ CsrResult card_wait_for_firmware_to_start(card_t *card, u32 *paddr)
             if (r != CSR_RESULT_SUCCESS)
             {
                 unifi_error(card->ospriv, "Failed to read UniFi Mailbox1 register for second time\n");
-                func_exit_r(r);
                 return r;
             }
             unifi_trace(card->ospriv, UDBG1, "MAILBOX1 value=0x%04X\n", mbox1);
@@ -1296,7 +1230,6 @@ CsrResult card_wait_for_firmware_to_start(card_t *card, u32 *paddr)
     {
         unifi_trace(card->ospriv, UDBG1, "Timeout waiting for firmware to start, Mailbox1 still 0 after %d ms\n",
                     MAILBOX1_ATTEMPTS * MAILBOX1_TIMEOUT);
-        func_exit_r(CSR_RESULT_FAILURE);
         return CSR_RESULT_FAILURE;
     }
 
@@ -1312,7 +1245,6 @@ CsrResult card_wait_for_firmware_to_start(card_t *card, u32 *paddr)
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_error(card->ospriv, "Failed to write f/w startup handshake to MAILBOX2\n");
-        func_exit_r(r);
         return r;
     }
 
@@ -1330,13 +1262,11 @@ CsrResult card_wait_for_firmware_to_start(card_t *card, u32 *paddr)
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_error(card->ospriv, "Failed to read UniFi Mailbox0 register\n");
-        func_exit_r(r);
         return r;
     }
 
     *paddr = (((u32)mbox1 << 16) | mbox0);
 
-    func_exit();
     return CSR_RESULT_SUCCESS;
 } /* card_wait_for_firmware_to_start() */
 
@@ -1358,14 +1288,12 @@ CsrResult card_wait_for_firmware_to_start(card_t *card, u32 *paddr)
  */
 CsrResult unifi_capture_panic(card_t *card)
 {
-    func_enter();
 
     /* The firmware must have previously initialised to read the panic addresses
      * from the SLUT
      */
     if (!card->panic_data_phy_addr || !card->panic_data_mac_addr)
     {
-        func_exit();
         return CSR_RESULT_SUCCESS;
     }
 
@@ -1380,7 +1308,6 @@ CsrResult unifi_capture_panic(card_t *card)
         unifi_info(card->ospriv, "Unable to read panic codes");
     }
 
-    func_exit();
     return CSR_RESULT_SUCCESS;
 }
 
@@ -1405,8 +1332,6 @@ static CsrResult card_access_panic(card_t *card)
     s32 i;
     CsrResult r, sr;
 
-    func_enter();
-
     /* A chip version of zero means that the version never got succesfully read
      * during reset. In this case give up because it will not be possible to
      * verify the chip version.
@@ -1513,7 +1438,6 @@ static CsrResult card_access_panic(card_t *card)
     }
 
     r = ConvertCsrSdioToCsrHipResult(card, sr);
-    func_exit_r(r);
     return r;
 }
 
@@ -1536,8 +1460,6 @@ void unifi_read_panic(card_t *card)
     CsrResult r;
     u16 p_code, p_arg;
 
-    func_enter();
-
     /* The firmware must have previously initialised to read the panic addresses
      * from the SLUT
      */
@@ -1584,7 +1506,6 @@ void unifi_read_panic(card_t *card)
         card->last_mac_panic_arg = p_arg;
     }
 
-    func_exit();
 }
 
 
@@ -1607,8 +1528,6 @@ static CsrResult card_allocate_memory_resources(card_t *card)
     s16 n, i, k, r;
     sdio_config_data_t *cfg_data;
 
-    func_enter();
-
     /* Reset any state carried forward from a previous life */
     card->fh_command_queue.q_rd_ptr = 0;
     card->fh_command_queue.q_wr_ptr = 0;
@@ -1634,7 +1553,6 @@ static CsrResult card_allocate_memory_resources(card_t *card)
     if (card->fh_buffer.buf == NULL)
     {
         unifi_error(card->ospriv, "Failed to allocate memory for F-H signals\n");
-        func_exit_r(CSR_WIFI_HIP_RESULT_NO_MEMORY);
         return CSR_WIFI_HIP_RESULT_NO_MEMORY;
     }
     card->fh_buffer.bufsize = UNIFI_FH_BUF_SIZE;
@@ -1645,7 +1563,6 @@ static CsrResult card_allocate_memory_resources(card_t *card)
     if (card->th_buffer.buf == NULL)
     {
         unifi_error(card->ospriv, "Failed to allocate memory for T-H signals\n");
-        func_exit_r(CSR_WIFI_HIP_RESULT_NO_MEMORY);
         return CSR_WIFI_HIP_RESULT_NO_MEMORY;
     }
     card->th_buffer.bufsize = UNIFI_FH_BUF_SIZE;
@@ -1667,7 +1584,6 @@ static CsrResult card_allocate_memory_resources(card_t *card)
     if (card->from_host_data == NULL)
     {
         unifi_error(card->ospriv, "Failed to allocate memory for F-H bulk data array\n");
-        func_exit_r(CSR_WIFI_HIP_RESULT_NO_MEMORY);
         return CSR_WIFI_HIP_RESULT_NO_MEMORY;
     }
 
@@ -1683,7 +1599,6 @@ static CsrResult card_allocate_memory_resources(card_t *card)
     if (card->fh_slot_host_tag_record == NULL)
     {
         unifi_error(card->ospriv, "Failed to allocate memory for F-H slot host tag mapping array\n");
-        func_exit_r(CSR_WIFI_HIP_RESULT_NO_MEMORY);
         return CSR_WIFI_HIP_RESULT_NO_MEMORY;
     }
 
@@ -1702,7 +1617,6 @@ static CsrResult card_allocate_memory_resources(card_t *card)
     if (card->to_host_data == NULL)
     {
         unifi_error(card->ospriv, "Failed to allocate memory for T-H bulk data array\n");
-        func_exit_r(CSR_WIFI_HIP_RESULT_NO_MEMORY);
         return CSR_WIFI_HIP_RESULT_NO_MEMORY;
     }
 
@@ -1736,7 +1650,6 @@ static CsrResult card_allocate_memory_resources(card_t *card)
 
     card->memory_resources_allocated = 1;
 
-    func_exit();
     return CSR_RESULT_SUCCESS;
 } /* card_allocate_memory_resources() */
 
@@ -1781,7 +1694,6 @@ static void unifi_free_bulk_data(card_t *card, bulk_data_desc_t *bulk_data_slot)
  */
 static void card_free_memory_resources(card_t *card)
 {
-    func_enter();
 
     unifi_trace(card->ospriv, UDBG1, "Freeing card memory resources.\n");
 
@@ -1812,7 +1724,6 @@ static void card_free_memory_resources(card_t *card)
 
     card->memory_resources_allocated = 0;
 
-    func_exit();
 } /* card_free_memory_resources() */
 
 
@@ -1820,8 +1731,6 @@ static void card_init_soft_queues(card_t *card)
 {
     s16 i;
 
-    func_enter();
-
     unifi_trace(card->ospriv, UDBG1, "Initialising internal signal queues.\n");
     /* Reset any state carried forward from a previous life */
     card->fh_command_queue.q_rd_ptr = 0;
@@ -1838,7 +1747,6 @@ static void card_init_soft_queues(card_t *card)
 #ifndef CSR_WIFI_HIP_TA_DISABLE
     unifi_ta_sampling_init(card);
 #endif
-    func_exit();
 }
 
 
@@ -1858,7 +1766,6 @@ static void card_init_soft_queues(card_t *card)
 void unifi_cancel_pending_signals(card_t *card)
 {
     s16 i, n, r;
-    func_enter();
 
     unifi_trace(card->ospriv, UDBG1, "Canceling pending signals.\n");
 
@@ -1927,7 +1834,6 @@ void unifi_cancel_pending_signals(card_t *card)
 
     card_init_soft_queues(card);
 
-    func_exit();
 } /* unifi_cancel_pending_signals() */
 
 
@@ -1951,7 +1857,6 @@ void unifi_cancel_pending_signals(card_t *card)
  */
 void unifi_free_card(card_t *card)
 {
-    func_enter();
 #ifdef CSR_PRE_ALLOC_NET_DATA
     prealloc_netdata_free(card);
 #endif
@@ -1967,7 +1872,6 @@ void unifi_free_card(card_t *card)
 
     kfree(card);
 
-    func_exit();
 } /* unifi_free_card() */
 
 
@@ -1989,8 +1893,6 @@ static CsrResult card_init_slots(card_t *card)
     CsrResult r;
     u8 i;
 
-    func_enter();
-
     /* Allocate the buffers we need, only once. */
     if (card->memory_resources_allocated == 1)
     {
@@ -2007,14 +1909,12 @@ static CsrResult card_init_slots(card_t *card)
     {
         unifi_error(card->ospriv, "Failed to allocate card memory resources.\n");
         card_free_memory_resources(card);
-        func_exit_r(r);
         return r;
     }
 
     if (card->sdio_ctrl_addr == 0)
     {
         unifi_error(card->ospriv, "Failed to find config struct!\n");
-        func_exit_r(CSR_WIFI_HIP_RESULT_INVALID_VALUE);
         return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
     }
 
@@ -2037,7 +1937,6 @@ static CsrResult card_init_slots(card_t *card)
         if (r != CSR_RESULT_SUCCESS)
         {
             unifi_error(card->ospriv, "Failed to read from-host sig written count\n");
-            func_exit_r(r);
             return r;
         }
         card->from_host_signals_w = (s16)s;
@@ -2051,7 +1950,6 @@ static CsrResult card_init_slots(card_t *card)
         if (r != CSR_RESULT_SUCCESS)
         {
             unifi_error(card->ospriv, "Failed to read to-host sig read count\n");
-            func_exit_r(r);
             return r;
         }
         card->to_host_signals_r = (s16)s;
@@ -2066,7 +1964,6 @@ static CsrResult card_init_slots(card_t *card)
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_error(card->ospriv, "Failed to write initialised flag\n");
-        func_exit_r(r);
         return r;
     }
 
@@ -2082,7 +1979,6 @@ static CsrResult card_init_slots(card_t *card)
 
     card->dynamic_slot_data.packets_interval = UNIFI_PACKETS_INTERVAL;
 
-    func_exit();
     return CSR_RESULT_SUCCESS;
 } /* card_init_slots() */
 
@@ -2153,8 +2049,6 @@ static void CardReassignDynamicReservation(card_t *card)
 {
     u8 i;
 
-    func_enter();
-
     unifi_trace(card->ospriv, UDBG5, "Packets Txed %d %d %d %d\n",
                 card->dynamic_slot_data.packets_txed[0],
                 card->dynamic_slot_data.packets_txed[1],
@@ -2176,7 +2070,6 @@ static void CardReassignDynamicReservation(card_t *card)
     }
 
     card->dynamic_slot_data.total_packets_txed = 0;
-    func_exit();
 }
 
 
@@ -2206,8 +2099,6 @@ static void CardCheckDynamicReservation(card_t *card, unifi_TrafficQueue queue)
     q_t *sigq;
     u16 num_data_slots = card->config_data.num_fromhost_data_slots - UNIFI_RESERVED_COMMAND_SLOTS;
 
-    func_enter();
-
     /* Calculate the pending queue length */
     sigq = &card->fh_traffic_queue[queue];
     q_len = CSR_WIFI_HIP_Q_SLOTS_USED(sigq);
@@ -2215,7 +2106,6 @@ static void CardCheckDynamicReservation(card_t *card, unifi_TrafficQueue queue)
     if (q_len <= card->dynamic_slot_data.from_host_reserved_slots[queue])
     {
         unifi_trace(card->ospriv, UDBG5, "queue %d q_len %d already has that many reserved slots, exiting\n", queue, q_len);
-        func_exit();
         return;
     }
 
@@ -2313,7 +2203,6 @@ static void CardCheckDynamicReservation(card_t *card, unifi_TrafficQueue queue)
                     card->dynamic_slot_data.from_host_max_slots[i]);
     }
 
-    func_exit();
 }
 
 
@@ -2336,14 +2225,11 @@ void CardClearFromHostDataSlot(card_t *card, const s16 slot)
     u8 queue = card->from_host_data[slot].queue;
     const void *os_data_ptr = card->from_host_data[slot].bd.os_data_ptr;
 
-    func_enter();
-
     if (card->from_host_data[slot].bd.data_length == 0)
     {
         unifi_warning(card->ospriv,
                       "Surprise: request to clear an already free FH data slot: %d\n",
                       slot);
-        func_exit();
         return;
     }
 
@@ -2379,7 +2265,6 @@ void CardClearFromHostDataSlot(card_t *card, const s16 slot)
 
     unifi_trace(card->ospriv, UDBG4, "CardClearFromHostDataSlot: slot %d recycled %p\n", slot, os_data_ptr);
 
-    func_exit();
 } /* CardClearFromHostDataSlot() */
 
 
@@ -2457,8 +2342,6 @@ u16 CardGetFreeFromHostDataSlots(card_t *card)
 {
     u16 i, n = 0;
 
-    func_enter();
-
     /* First two slots reserved for MLME */
     for (i = 0; i < card->config_data.num_fromhost_data_slots; i++)
     {
@@ -2469,7 +2352,6 @@ u16 CardGetFreeFromHostDataSlots(card_t *card)
         }
     }
 
-    func_exit();
     return n;
 } /* CardGetFreeFromHostDataSlots() */
 
@@ -2506,7 +2388,6 @@ u16 CardAreAllFromHostDataSlotsEmpty(card_t *card)
 
 static CsrResult unifi_identify_hw(card_t *card)
 {
-    func_enter();
 
     card->chip_id = card->sdio_if->sdioId.cardId;
     card->function = card->sdio_if->sdioId.sdioFunction;
@@ -2530,7 +2411,6 @@ static CsrResult unifi_identify_hw(card_t *card)
                ChipHelper_MarketingName(card->helper),
                ChipHelper_FriendlyName(card->helper));
 
-    func_exit();
     return CSR_RESULT_SUCCESS;
 } /* unifi_identify_hw() */
 
@@ -2541,8 +2421,6 @@ static CsrResult unifi_prepare_hw(card_t *card)
     CsrResult csrResult;
     enum unifi_host_state old_state = card->host_state;
 
-    func_enter();
-
     r = unifi_identify_hw(card);
     if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
     {
@@ -2551,7 +2429,6 @@ static CsrResult unifi_prepare_hw(card_t *card)
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_error(card->ospriv, "Failed to identify hw\n");
-        func_exit_r(r);
         return r;
     }
 
@@ -2576,7 +2453,6 @@ static CsrResult unifi_prepare_hw(card_t *card)
         if (csrResult != CSR_RESULT_SUCCESS)
         {
             r = ConvertCsrSdioToCsrHipResult(card, csrResult);
-            func_exit_r(r);
             return r;
         }
         card->sdio_clock_speed = UNIFI_SDIO_CLOCK_INIT_HZ;
@@ -2596,7 +2472,6 @@ static CsrResult unifi_prepare_hw(card_t *card)
         r = ConvertCsrSdioToCsrHipResult(card, csrResult);
         /* Can't enable WLAN function. Try resetting the SDIO block. */
         unifi_error(card->ospriv, "Failed to re-enable function %d.\n", card->function);
-        func_exit_r(r);
         return r;
     }
 
@@ -2610,11 +2485,9 @@ static CsrResult unifi_prepare_hw(card_t *card)
     r = unifi_read_chip_version(card);
     if (r != CSR_RESULT_SUCCESS)
     {
-        func_exit_r(r);
         return r;
     }
 
-    func_exit();
     return CSR_RESULT_SUCCESS;
 } /* unifi_prepare_hw() */
 
@@ -2625,8 +2498,6 @@ static CsrResult unifi_read_chip_version(card_t *card)
     CsrResult r;
     u16 ver;
 
-    func_enter();
-
     gbl_chip_version = ChipHelper_GBL_CHIP_VERSION(card->helper);
 
     /* Try to read the chip version from register. */
@@ -2640,7 +2511,6 @@ static CsrResult unifi_read_chip_version(card_t *card)
         if (r != CSR_RESULT_SUCCESS)
         {
             unifi_error(card->ospriv, "Failed to read GBL_CHIP_VERSION\n");
-            func_exit_r(r);
             return r;
         }
         card->chip_version = ver;
@@ -2653,7 +2523,6 @@ static CsrResult unifi_read_chip_version(card_t *card)
 
     unifi_info(card->ospriv, "Chip Version 0x%04X\n", card->chip_version);
 
-    func_exit_r(r);
     return r;
 } /* unifi_read_chip_version() */
 
@@ -2684,8 +2553,6 @@ static CsrResult unifi_reset_hardware(card_t *card)
     u16 new_block_size = UNIFI_IO_BLOCK_SIZE;
     CsrResult csrResult;
 
-    func_enter();
-
     /* Errors returned by unifi_prepare_hw() are not critical at this point */
     r = unifi_prepare_hw(card);
     if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
@@ -2709,7 +2576,6 @@ static CsrResult unifi_reset_hardware(card_t *card)
         if (r != CSR_RESULT_SUCCESS)
         {
             unifi_error(card->ospriv, "unifi_prepare_hw failed after hard reset\n");
-            func_exit_r(r);
             return r;
         }
     }
@@ -2729,7 +2595,6 @@ static CsrResult unifi_reset_hardware(card_t *card)
         if (r != CSR_RESULT_SUCCESS)
         {
             unifi_error(card->ospriv, "software hard reset failed\n");
-            func_exit_r(r);
             return r;
         }
 
@@ -2742,7 +2607,6 @@ static CsrResult unifi_reset_hardware(card_t *card)
             r = unifi_read_chip_version(card);
             if (r != CSR_RESULT_SUCCESS)
             {
-                func_exit_r(r);
                 return r;
             }
         }
@@ -2792,7 +2656,6 @@ static CsrResult unifi_reset_hardware(card_t *card)
     }
 
 
-    func_exit_r(r);
     return r;
 } /* unifi_reset_hardware() */
 
@@ -2818,8 +2681,6 @@ static CsrResult card_reset_method_io_enable(card_t *card)
     CsrResult r;
     CsrResult csrResult;
 
-    func_enter();
-
     /*
      * This resets only function 1, so should be used in
      * preference to the method below (CSR_FUNC_EN)
@@ -2869,7 +2730,6 @@ static CsrResult card_reset_method_io_enable(card_t *card)
         if (r != CSR_RESULT_SUCCESS)
         {
             unifi_warning(card->ospriv, "SDIO error writing SDIO_CSR_FUNC_EN: %d\n", r);
-            func_exit_r(r);
             return r;
         }
         else
@@ -2890,7 +2750,6 @@ static CsrResult card_reset_method_io_enable(card_t *card)
         unifi_warning(card->ospriv, "card_reset_method_io_enable failed to reset UniFi\n");
     }
 
-    func_exit();
     return r;
 } /* card_reset_method_io_enable() */
 
@@ -2915,8 +2774,6 @@ static CsrResult card_reset_method_dbg_reset(card_t *card)
 {
     CsrResult r;
 
-    func_enter();
-
     /*
      * Prepare UniFi for h/w reset
      */
@@ -2930,7 +2787,6 @@ static CsrResult card_reset_method_dbg_reset(card_t *card)
         if (r != CSR_RESULT_SUCCESS)
         {
             unifi_error(card->ospriv, "Failed to set UNIFI_HOST_STATE_DROWSY\n");
-            func_exit_r(r);
             return r;
         }
         CsrThreadSleep(5);
@@ -2944,7 +2800,6 @@ static CsrResult card_reset_method_dbg_reset(card_t *card)
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_error(card->ospriv, "Can't stop processors\n");
-        func_exit();
         return r;
     }
 
@@ -2963,7 +2818,6 @@ static CsrResult card_reset_method_dbg_reset(card_t *card)
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_warning(card->ospriv, "SDIO error writing DBG_RESET: %d\n", r);
-        func_exit_r(r);
         return r;
     }
 
@@ -2980,7 +2834,6 @@ static CsrResult card_reset_method_dbg_reset(card_t *card)
         unifi_warning(card->ospriv, "card_reset_method_dbg_reset failed to reset UniFi\n");
     }
 
-    func_exit();
     return r;
 } /* card_reset_method_dbg_reset() */
 
@@ -3008,8 +2861,6 @@ CsrResult unifi_card_hard_reset(card_t *card)
     const struct chip_helper_reset_values *init_data;
     u32 chunks;
 
-    func_enter();
-
     /* Clear cache of page registers */
     card->proc_select = (u32)(-1);
     card->dmem_page = (u32)(-1);
@@ -3028,7 +2879,6 @@ CsrResult unifi_card_hard_reset(card_t *card)
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_error(card->ospriv, "unifi_card_hard_reset failed to identify h/w\n");
-        func_exit();
         return r;
     }
 
@@ -3039,7 +2889,6 @@ CsrResult unifi_card_hard_reset(card_t *card)
         unifi_error(card->ospriv,
                     "Hard reset (Code download) is unsupported\n");
 
-        func_exit_r(CSR_RESULT_FAILURE);
         return CSR_RESULT_FAILURE;
     }
 
@@ -3058,7 +2907,6 @@ CsrResult unifi_card_hard_reset(card_t *card)
         }
         if (r == CSR_RESULT_SUCCESS)
         {
-            func_exit();
             return r;
         }
     }
@@ -3066,7 +2914,6 @@ CsrResult unifi_card_hard_reset(card_t *card)
     /* Software hard reset */
     r = card_reset_method_dbg_reset(card);
 
-    func_exit_r(r);
     return r;
 } /* unifi_card_hard_reset() */
 
@@ -3097,8 +2944,6 @@ CsrResult CardGenInt(card_t *card)
 {
     CsrResult r;
 
-    func_enter();
-
     if (card->chip_id > SDIO_CARD_ID_UNIFI_2)
     {
         r = sdio_write_f0(card, SDIO_CSR_FROM_HOST_SCRATCH0,
@@ -3117,13 +2962,11 @@ CsrResult CardGenInt(card_t *card)
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_error(card->ospriv, "SDIO error writing UNIFI_SHARED_IO_INTERRUPT: %d\n", r);
-        func_exit_r(r);
         return r;
     }
 
     card->unifi_interrupt_seq++;
 
-    func_exit();
     return CSR_RESULT_SUCCESS;
 } /* CardGenInt() */
 
@@ -3388,8 +3231,6 @@ CsrResult CardWriteBulkData(card_t *card, card_signal_t *csptr, unifi_TrafficQue
     bulk_data_desc_t *bulkdata = csptr->bulkdata;
     s16 h, nslots;
 
-    func_enter();
-
     /* Count the number of slots required */
     for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++)
     {
@@ -3470,7 +3311,6 @@ CsrResult CardWriteBulkData(card_t *card, card_signal_t *csptr, unifi_TrafficQue
             {
                 unifi_trace(card->ospriv, UDBG5, "fh data slot %d: %d\n", i, card->from_host_data[i].bd.data_length);
             }
-            func_exit();
             return CSR_RESULT_FAILURE;
         }
     }
@@ -3523,8 +3363,6 @@ CsrResult CardWriteBulkData(card_t *card, card_signal_t *csptr, unifi_TrafficQue
         }
     }
 
-    func_exit();
-
     return CSR_RESULT_SUCCESS;
 } /*  CardWriteBulkData() */
 
diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio.h b/drivers/staging/csr/csr_wifi_hip_card_sdio.h
index dc2ed70..a9b9ec4 100644
--- a/drivers/staging/csr/csr_wifi_hip_card_sdio.h
+++ b/drivers/staging/csr/csr_wifi_hip_card_sdio.h
@@ -20,10 +20,6 @@
 #ifndef __CARD_SDIO_H__
 #define __CARD_SDIO_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_unifi_udi.h"
 #include "csr_wifi_hip_unifihw.h"
@@ -695,8 +691,4 @@ CsrResult prealloc_netdata_alloc(card_t *card);
 void dump(void *mem, u16 len);
 void dump16(void *mem, u16 len);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* __CARD_SDIO_H__ */
diff --git a/drivers/staging/csr/csr_wifi_hip_chiphelper.h b/drivers/staging/csr/csr_wifi_hip_chiphelper.h
index 24737ae..b6b67ee 100644
--- a/drivers/staging/csr/csr_wifi_hip_chiphelper.h
+++ b/drivers/staging/csr/csr_wifi_hip_chiphelper.h
@@ -14,10 +14,6 @@
 
 #include <linux/types.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* The age of the BlueCore chip.  This is probably not useful, if
    you know the age then you can probably work out the version directly. */
 enum chip_helper_bluecore_age
@@ -408,64 +404,4 @@ s32 ChipHelper_DecodeWindow(ChipDescript *chip_help,
                                  u32 offset,
                                  u16 *page, u16 *addr, u32 *len);
 
-#ifdef __cplusplus
-/* Close the extern "C" */
-}
-
-/*
- * This is the C++ API.
- */
-
-class ChipHelper
-{
-public:
-    /* If this constructor is used then a GetVersionXXX function
-       should be called next. */
-    ChipHelper();
-
-    /* copy constructor */
-    ChipHelper(ChipDescript * desc);
-
-    /* The default constructor assume a BC7 / UF105x series chip
-       and that the number given is the value of UNIFI_GBL_CHIP_VERSION
-       (0xFE81) */
-    ChipHelper(u16 version);
-
-    /* This returns the C interface magic token from a C++ instance. */
-    ChipDescript* GetDescript() const
-    {
-        return m_desc;
-    }
-
-
-    /* Clear out theis class (set it to the null token). */
-    void ClearVersion();
-
-    /* Load this class with data for a specific chip. */
-    void GetVersionAny(u16 from_FF9A, u16 from_FE81);
-    void GetVersionUniFi(u16 version);
-    void GetVersionBlueCore(chip_helper_bluecore_age age, u16 version);
-    void GetVersionSdio(u8 sdio_version);
-
-    /* Helpers to build the definitions of the member functions. */
-#define CHIP_HELPER_DEF0_CPP_DEC(ret_type, name, info)    \
-    ret_type name() const;
-#define CHIP_HELPER_DEF1_CPP_DEC(ret_type, name, type1, name1)   \
-    ret_type name(type1 name1) const;
-
-    CHIP_HELPER_LIST(CPP_DEC)
-
-
-    /* The DecodeWindow function, see the description of the C version. */
-    s32 DecodeWindow(chip_helper_window_index window,
-                          chip_helper_window_type type,
-                          u32 offset,
-                          u16 &page, u16 &addr, u32 &len) const;
-
-private:
-    ChipDescript *m_desc;
-};
-
-#endif /* __cplusplus */
-
 #endif
diff --git a/drivers/staging/csr/csr_wifi_hip_chiphelper_private.h b/drivers/staging/csr/csr_wifi_hip_chiphelper_private.h
index cb0ea4b..e5e5799 100644
--- a/drivers/staging/csr/csr_wifi_hip_chiphelper_private.h
+++ b/drivers/staging/csr/csr_wifi_hip_chiphelper_private.h
@@ -14,10 +14,6 @@
 
 #include "csr_wifi_hip_chiphelper.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 /* This GP stuff should be somewhere else? */
 
 /* Memory spaces encoded in top byte of Generic Pointer type */
@@ -201,8 +197,4 @@ struct chip_device_desc_t
     const struct window_info_t *windows[CHIP_HELPER_WINDOW_COUNT];
 };
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif /* CSR_WIFI_HIP_CHIPHELPER_PRIVATE_H__ */
diff --git a/drivers/staging/csr/csr_wifi_hip_conversions.h b/drivers/staging/csr/csr_wifi_hip_conversions.h
index 7d045c0..bf7a52e 100644
--- a/drivers/staging/csr/csr_wifi_hip_conversions.h
+++ b/drivers/staging/csr/csr_wifi_hip_conversions.h
@@ -23,10 +23,6 @@
 #ifndef __CSR_WIFI_HIP_CONVERSIONS_H__
 #define __CSR_WIFI_HIP_CONVERSIONS_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define SIZEOF_UINT16           2
 #define SIZEOF_UINT32           4
 #define SIZEOF_UINT64           8
@@ -73,9 +69,5 @@ s32 get_packed_struct_size(const u8 *buf);
 CsrResult read_unpack_signal(const u8 *ptr, CSR_SIGNAL *sig);
 CsrResult write_pack(const CSR_SIGNAL *sig, u8 *ptr, u16 *sig_len);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* __CSR_WIFI_HIP_CONVERSIONS_H__ */
 
diff --git a/drivers/staging/csr/csr_wifi_hip_download.c b/drivers/staging/csr/csr_wifi_hip_download.c
index 6db672c..2f44a38 100644
--- a/drivers/staging/csr/csr_wifi_hip_download.c
+++ b/drivers/staging/csr/csr_wifi_hip_download.c
@@ -68,7 +68,6 @@ static CsrResult _find_in_slut(card_t *card, symbol_t *psym, u32 *pslut)
         if (r != CSR_RESULT_SUCCESS)
         {
             unifi_error(card->ospriv, "Firmware hasn't started\n");
-            func_exit_r(r);
             return r;
         }
         *pslut = slut_address;
@@ -81,7 +80,6 @@ static CsrResult _find_in_slut(card_t *card, symbol_t *psym, u32 *pslut)
         if (csrResult != CSR_RESULT_SUCCESS)
         {
             r = ConvertCsrSdioToCsrHipResult(card, csrResult);
-            func_exit_r(r);
             return r;
         }
         card->sdio_clock_speed = UNIFI_SDIO_CLOCK_INIT_HZ;
@@ -106,14 +104,12 @@ static CsrResult _find_in_slut(card_t *card, symbol_t *psym, u32 *pslut)
     if (r != CSR_RESULT_SUCCESS)
     {
         unifi_error(card->ospriv, "Failed to read SLUT finger print\n");
-        func_exit_r(r);
         return r;
     }
 
     if (finger_print != SLUT_FINGERPRINT)
     {
         unifi_error(card->ospriv, "Failed to find SLUT fingerprint\n");
-        func_exit_r(CSR_RESULT_FAILURE);
         return CSR_RESULT_FAILURE;
     }
 
@@ -128,7 +124,6 @@ static CsrResult _find_in_slut(card_t *card, symbol_t *psym, u32 *pslut)
         r = unifi_card_read16(card, slut_address, &id);
         if (r != CSR_RESULT_SUCCESS)
         {
-            func_exit_r(r);
             return r;
         }
         slut_address += 2;
@@ -143,7 +138,6 @@ static CsrResult _find_in_slut(card_t *card, symbol_t *psym, u32 *pslut)
         r = unifi_read32(card, slut_address, &obj);
         if (r != CSR_RESULT_SUCCESS)
         {
-            func_exit_r(r);
             return r;
         }
         slut_address += 4;
@@ -161,7 +155,6 @@ static CsrResult _find_in_slut(card_t *card, symbol_t *psym, u32 *pslut)
         }
     }
 
-    func_exit_r(r);
     return r;
 }
 
@@ -279,7 +272,6 @@ static CsrResult do_patch_convert_download(card_t *card, void *dlpriv, xbv1_t *p
         if (r != CSR_RESULT_SUCCESS)
         {
             unifi_error(card->ospriv, "Converted patch download failed\n");
-            func_exit_r(r);
             return r;
         }
         else
@@ -294,7 +286,6 @@ static CsrResult do_patch_convert_download(card_t *card, void *dlpriv, xbv1_t *p
             unifi_error(card->ospriv, "Failed to write loader restart cmd\n");
         }
 
-        func_exit_r(r);
         return r;
     }
 }
@@ -327,8 +318,6 @@ CsrResult unifi_dl_firmware(card_t *card, void *dlpriv)
     xbv1_t *fwinfo;
     CsrResult r;
 
-    func_enter();
-
     fwinfo = kmalloc(sizeof(xbv1_t), GFP_KERNEL);
     if (fwinfo == NULL)
     {
@@ -376,7 +365,6 @@ CsrResult unifi_dl_firmware(card_t *card, void *dlpriv)
     }
 
     kfree(fwinfo);
-    func_exit_r(r);
     return r;
 } /* unifi_dl_firmware() */
 
@@ -407,15 +395,12 @@ CsrResult unifi_dl_patch(card_t *card, void *dlpriv, u32 boot_ctrl)
     xbv1_t *fwinfo;
     CsrResult r;
 
-    func_enter();
-
     unifi_info(card->ospriv, "unifi_dl_patch %p %08x\n", dlpriv, boot_ctrl);
 
     fwinfo = kmalloc(sizeof(xbv1_t), GFP_KERNEL);
     if (fwinfo == NULL)
     {
         unifi_error(card->ospriv, "Failed to allocate memory for patches\n");
-        func_exit();
         return CSR_WIFI_HIP_RESULT_NO_MEMORY;
     }
 
@@ -431,7 +416,6 @@ CsrResult unifi_dl_patch(card_t *card, void *dlpriv, u32 boot_ctrl)
     {
         kfree(fwinfo);
         unifi_error(card->ospriv, "Failed to read in patch file\n");
-        func_exit();
         return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
     }
 
@@ -446,7 +430,6 @@ CsrResult unifi_dl_patch(card_t *card, void *dlpriv, u32 boot_ctrl)
                     card->build_id, fwinfo->build_id);
         kfree(fwinfo);
 #ifndef CSR_WIFI_IGNORE_PATCH_VERSION_MISMATCH
-        func_exit();
         return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
 #else
         fwinfo = NULL;
@@ -463,7 +446,6 @@ CsrResult unifi_dl_patch(card_t *card, void *dlpriv, u32 boot_ctrl)
 
     kfree(fwinfo);
 
-    func_exit_r(r);
     return r;
 } /* unifi_dl_patch() */
 
diff --git a/drivers/staging/csr/csr_wifi_hip_dump.c b/drivers/staging/csr/csr_wifi_hip_dump.c
index d67b460..7b7eec4 100644
--- a/drivers/staging/csr/csr_wifi_hip_dump.c
+++ b/drivers/staging/csr/csr_wifi_hip_dump.c
@@ -40,7 +40,7 @@
 typedef struct coredump_buf
 {
     u16  count;                       /* serial number of dump */
-    CsrTime    timestamp;                   /* host's system time at capture */
+    u32  timestamp;                   /* host's system time at capture */
     s16   requestor;                   /* request: 0=auto dump, 1=manual */
     u16  chip_ver;
     u32  fw_ver;
@@ -104,8 +104,6 @@ CsrResult unifi_coredump_request_at_next_reset(card_t *card, s8 enable)
 {
     CsrResult r;
 
-    func_enter();
-
     if (enable)
     {
         unifi_trace(card->ospriv, UDBG2, "Mini-coredump requested after reset\n");
@@ -121,7 +119,6 @@ CsrResult unifi_coredump_request_at_next_reset(card_t *card, s8 enable)
         r = CSR_RESULT_SUCCESS;
     }
 
-    func_exit_r(r);
     return r;
 }
 
@@ -145,8 +142,6 @@ CsrResult unifi_coredump_handle_request(card_t *card)
 {
     CsrResult r = CSR_RESULT_SUCCESS;
 
-    func_enter();
-
     if (card == NULL)
     {
         r = CSR_WIFI_HIP_RESULT_INVALID_VALUE;
@@ -160,7 +155,6 @@ CsrResult unifi_coredump_handle_request(card_t *card)
         }
     }
 
-    func_exit_r(r);
     return r;
 }
 
@@ -192,9 +186,7 @@ CsrResult unifi_coredump_capture(card_t *card, struct unifi_coredump_req *req)
 {
     CsrResult r = CSR_RESULT_SUCCESS;
     static u16 dump_seq_no = 1;
-    CsrTime time_of_capture;
-
-    func_enter();
+    u32 time_of_capture;
 
     if (card->dump_next_write == NULL)
     {
@@ -269,7 +261,6 @@ CsrResult unifi_coredump_capture(card_t *card, struct unifi_coredump_req *req)
     }
 
 done:
-    func_exit_r(r);
     return r;
 } /* unifi_coredump_capture() */
 
@@ -358,8 +349,6 @@ CsrResult unifi_coredump_get_value(card_t *card, struct unifi_coredump_req *req)
     s32 i = 0;
     coredump_buffer *find_dump = NULL;
 
-    func_enter();
-
     if (req == NULL || card == NULL)
     {
         r = CSR_WIFI_HIP_RESULT_INVALID_VALUE;
@@ -452,7 +441,6 @@ CsrResult unifi_coredump_get_value(card_t *card, struct unifi_coredump_req *req)
     req->serial = find_dump->count;
 
 done:
-    func_exit_r(r);
     return r;
 } /* unifi_coredump_get_value() */
 
@@ -481,8 +469,6 @@ static CsrResult unifi_coredump_read_zone(card_t *card, u16 *zonebuf, const stru
 {
     CsrResult r;
 
-    func_enter();
-
     if (zonebuf == NULL || def == NULL)
     {
         r = CSR_WIFI_HIP_RESULT_INVALID_VALUE;
@@ -521,7 +507,6 @@ static CsrResult unifi_coredump_read_zone(card_t *card, u16 *zonebuf, const stru
     }
 
 done:
-    func_exit_r(r);
     return r;
 }
 
@@ -551,8 +536,6 @@ static CsrResult unifi_coredump_read_zones(card_t *card, coredump_buffer *dump_b
     CsrResult r = CSR_RESULT_SUCCESS;
     s32 i;
 
-    func_enter();
-
     /* Walk the table of coredump zone definitions and read them from the chip */
     for (i = 0;
          (i < HIP_CDUMP_NUM_ZONES) && (r == 0);
@@ -561,7 +544,6 @@ static CsrResult unifi_coredump_read_zones(card_t *card, coredump_buffer *dump_b
         r = unifi_coredump_read_zone(card, dump_buf->zone[i], &zonedef_table[i]);
     }
 
-    func_exit_r(r);
     return r;
 }
 
@@ -590,8 +572,6 @@ static CsrResult unifi_coredump_from_sdio(card_t *card, coredump_buffer *dump_bu
     CsrResult r;
     u32 sdio_addr;
 
-    func_enter();
-
     if (dump_buf == NULL)
     {
         r = CSR_WIFI_HIP_RESULT_INVALID_VALUE;
@@ -634,7 +614,6 @@ static CsrResult unifi_coredump_from_sdio(card_t *card, coredump_buffer *dump_bu
     }
 
 done:
-    func_exit_r(r);
     return r;
 } /* unifi_coredump_from_sdio() */
 
@@ -743,8 +722,6 @@ CsrResult unifi_coredump_init(card_t *card, u16 num_dump_buffers)
     u32 i = 0;
 #endif
 
-    func_enter();
-
     card->request_coredump_on_reset = 0;
     card->dump_next_write = NULL;
     card->dump_cur_read = NULL;
@@ -790,7 +767,6 @@ CsrResult unifi_coredump_init(card_t *card, u16 num_dump_buffers)
 
 done:
 #endif
-    func_exit();
     return CSR_RESULT_SUCCESS;
 
 #ifndef UNIFI_DISABLE_COREDUMP
@@ -798,7 +774,6 @@ fail:
     /* Unwind what we allocated so far */
     unifi_error(ospriv, "Out of memory allocating core dump node %d\n", i);
     unifi_coredump_free(card);
-    func_exit();
     return CSR_WIFI_HIP_RESULT_NO_MEMORY;
 #endif
 } /* unifi_coreump_init() */
@@ -826,7 +801,6 @@ void unifi_coredump_free(card_t *card)
     s16 i = 0;
     s16 j;
 
-    func_enter();
     unifi_trace(ospriv, UDBG2, "Core dump de-configured\n");
 
     if (card->dump_buf == NULL)
@@ -858,8 +832,6 @@ void unifi_coredump_free(card_t *card)
     card->dump_buf = NULL;
     card->dump_next_write = NULL;
     card->dump_cur_read = NULL;
-
-    func_exit();
 } /* unifi_coredump_free() */
 
 
diff --git a/drivers/staging/csr/csr_wifi_hip_send.c b/drivers/staging/csr/csr_wifi_hip_send.c
index 86aa23c..76429e5 100644
--- a/drivers/staging/csr/csr_wifi_hip_send.c
+++ b/drivers/staging/csr/csr_wifi_hip_send.c
@@ -270,8 +270,6 @@ static CsrResult send_signal(card_t *card, const u8 *sigptr, u32 siglen,
         }
     }
 
-    func_exit();
-
     return CSR_RESULT_SUCCESS;
 } /*  send_signal() */
 
diff --git a/drivers/staging/csr/csr_wifi_hip_signals.h b/drivers/staging/csr/csr_wifi_hip_signals.h
index 5f84155..ca4d077 100644
--- a/drivers/staging/csr/csr_wifi_hip_signals.h
+++ b/drivers/staging/csr/csr_wifi_hip_signals.h
@@ -1,10 +1,10 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
-            All rights reserved and confidential information of CSR
+	(c) Cambridge Silicon Radio Limited 2011
+	All rights reserved and confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+	Refer to LICENSE.txt included with this source for details
+	on the license terms.
 
 *****************************************************************************/
 
@@ -101,10 +101,6 @@
 /* FUNCTION DECLARATIONS */
 /******************************************************************************/
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 /******************************************************************************
  * SigGetNumDataRefs - Retrieve pointers to data-refs from a signal.
  *
@@ -129,9 +125,4 @@ s32 SigGetDataRefs(CSR_SIGNAL *aSignal, CSR_DATAREF **aDataRef);
  */
 s32 SigGetSize(const CSR_SIGNAL *aSignal);
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-
 #endif /* __CSR_WIFI_HIP_SIGNALS_H__ */
diff --git a/drivers/staging/csr/csr_wifi_hip_sigs.h b/drivers/staging/csr/csr_wifi_hip_sigs.h
index 2b9f51d..6112cc3 100644
--- a/drivers/staging/csr/csr_wifi_hip_sigs.h
+++ b/drivers/staging/csr/csr_wifi_hip_sigs.h
@@ -16,10 +16,6 @@
 #ifndef CSR_WIFI_HIP_SIGS_H
 #define CSR_WIFI_HIP_SIGS_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 typedef s16 csr_place_holding_type;
 
 typedef u16 CSR_ASSOCIATION_ID;
@@ -1418,8 +1414,4 @@ typedef struct CSR_SIGNAL_PRIMITIVE
 
 u32 SigGetFilterPos(u16 aSigID);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/drivers/staging/csr/csr_wifi_hip_ta_sampling.h b/drivers/staging/csr/csr_wifi_hip_ta_sampling.h
index 46c630b..aa684c6 100644
--- a/drivers/staging/csr/csr_wifi_hip_ta_sampling.h
+++ b/drivers/staging/csr/csr_wifi_hip_ta_sampling.h
@@ -21,10 +21,6 @@
 #ifndef __TA_SAMPLING_H__
 #define __TA_SAMPLING_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "csr_wifi_hip_unifi.h"
 
 typedef struct ta_l4stats
@@ -67,9 +63,4 @@ typedef struct ta_data
 
 void unifi_ta_sampling_init(card_t *card);
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* __TA_SAMPLING_H__ */
diff --git a/drivers/staging/csr/csr_wifi_hip_unifi.h b/drivers/staging/csr/csr_wifi_hip_unifi.h
index 2923e2ef..c2a2231 100644
--- a/drivers/staging/csr/csr_wifi_hip_unifi.h
+++ b/drivers/staging/csr/csr_wifi_hip_unifi.h
@@ -20,10 +20,6 @@
 #ifndef __CSR_WIFI_HIP_UNIFI_H__
 #define __CSR_WIFI_HIP_UNIFI_H__ 1
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef CSR_WIFI_HIP_TA_DISABLE
 #include "csr_wifi_router_ctrl_prim.h"
 #include "csr_wifi_router_prim.h"
@@ -228,7 +224,7 @@ typedef struct unifi_coredump_req
     u32 chip_ver;                 /* Chip version */
     u32 fw_ver;                   /* Firmware version */
     s32  requestor;                /* Requestor: 0=auto dump, 1=manual */
-    CsrTime   timestamp;                /* time of capture by driver */
+    u32 timestamp;                /* time of capture by driver */
     u32 serial;                   /* capture serial number */
     s32  value;                    /* register value */
 } unifi_coredump_req_t;                 /* mini-coredumped reg value request */
@@ -872,8 +868,4 @@ CsrResult unifi_coredump_request_at_next_reset(card_t *card, s8 enable);
 CsrResult unifi_coredump_init(card_t *card, u16 num_dump_buffers);
 void unifi_coredump_free(card_t *card);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* __CSR_WIFI_HIP_UNIFI_H__ */
diff --git a/drivers/staging/csr/csr_wifi_hip_unifi_signal_names.c b/drivers/staging/csr/csr_wifi_hip_unifi_signal_names.c
index 7c13df2..9a35285 100644
--- a/drivers/staging/csr/csr_wifi_hip_unifi_signal_names.c
+++ b/drivers/staging/csr/csr_wifi_hip_unifi_signal_names.c
@@ -10,37 +10,32 @@
 
 #include "csr_wifi_hip_unifi.h"
 
-struct sig_name
-{
-    s16             id;
-    const char *name;
+struct sig_name {
+	s16 id;
+	const char *name;
 };
 
 static const struct sig_name Unifi_bulkcmd_names[] = {
-    {  0, "SignalCmd" },
-    {  1, "CopyToHost" },
-    {  2, "CopyToHostAck" },
-    {  3, "CopyFromHost" },
-    {  4, "CopyFromHostAck" },
-    {  5, "ClearSlot" },
-    {  6, "CopyOverlay" },
-    {  7, "CopyOverlayAck" },
-    {  8, "CopyFromHostAndClearSlot" },
-    {  15, "Padding" }
+	{ 0, "SignalCmd" },
+	{ 1, "CopyToHost" },
+	{ 2, "CopyToHostAck" },
+	{ 3, "CopyFromHost" },
+	{ 4, "CopyFromHostAck" },
+	{ 5, "ClearSlot" },
+	{ 6, "CopyOverlay" },
+	{ 7, "CopyOverlayAck" },
+	{ 8, "CopyFromHostAndClearSlot" },
+	{ 15, "Padding" }
 };
 
-const char* lookup_bulkcmd_name(u16 id)
+const char *lookup_bulkcmd_name(u16 id)
 {
-    if (id < 9)
-    {
-        return Unifi_bulkcmd_names[id].name;
-    }
-    if (id == 15)
-    {
-        return "Padding";
-    }
-
-    return "UNKNOWN";
+	if (id < 9)
+		return Unifi_bulkcmd_names[id].name;
+	if (id == 15)
+		return "Padding";
+
+	return "UNKNOWN";
 }
 
 
diff --git a/drivers/staging/csr/csr_wifi_hip_unifi_udi.h b/drivers/staging/csr/csr_wifi_hip_unifi_udi.h
index 83032d0..9d85cfd 100644
--- a/drivers/staging/csr/csr_wifi_hip_unifi_udi.h
+++ b/drivers/staging/csr/csr_wifi_hip_unifi_udi.h
@@ -20,10 +20,6 @@
 #ifndef __CSR_WIFI_HIP_UNIFI_UDI_H__
 #define __CSR_WIFI_HIP_UNIFI_UDI_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_signals.h"
 
@@ -68,9 +64,4 @@ s32 unifi_print_status(card_t *card, char *str, s32 *remain);
         }                                                           \
     } while (0)
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* __CSR_WIFI_HIP_UNIFI_UDI_H__ */
diff --git a/drivers/staging/csr/csr_wifi_hip_unifihw.h b/drivers/staging/csr/csr_wifi_hip_unifihw.h
index 5ffd6ba..3f9fcbd 100644
--- a/drivers/staging/csr/csr_wifi_hip_unifihw.h
+++ b/drivers/staging/csr/csr_wifi_hip_unifihw.h
@@ -20,10 +20,6 @@
 #ifndef __UNIFIHW_H__
 #define __UNIFIHW_H__ 1
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* Symbol Look Up Table fingerprint. IDs are in sigs.h */
 #define SLUT_FINGERPRINT        0xD397
 
@@ -60,8 +56,4 @@ extern "C" {
 #define UNIFI_GP_OFFSET(GP)  ((GP) & 0xFFFFFF)
 #define UNIFI_GP_SPACE(GP)   (((GP) >> 24) & 0xFF)
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* __UNIFIHW_H__ */
diff --git a/drivers/staging/csr/csr_wifi_hip_unifiversion.h b/drivers/staging/csr/csr_wifi_hip_unifiversion.h
index e1fdbb2..d1c6678 100644
--- a/drivers/staging/csr/csr_wifi_hip_unifiversion.h
+++ b/drivers/staging/csr/csr_wifi_hip_unifiversion.h
@@ -21,18 +21,10 @@
 #ifndef __UNIFIVERSION_H__
 #define __UNIFIVERSION_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /*
  * The minimum version of Host Interface Protocol required by the driver.
  */
 #define UNIFI_HIP_MAJOR_VERSION 9
 #define UNIFI_HIP_MINOR_VERSION 1
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* __UNIFIVERSION_H__ */
diff --git a/drivers/staging/csr/csr_wifi_hip_xbv.c b/drivers/staging/csr/csr_wifi_hip_xbv.c
index 071f80a..050a15f 100644
--- a/drivers/staging/csr/csr_wifi_hip_xbv.c
+++ b/drivers/staging/csr/csr_wifi_hip_xbv.c
@@ -758,7 +758,7 @@ static u32 write_fwdl_to_ptdl(void *buf, const u32 offset, fwreadfn_t readfn,
     while (left)
     {
         /* Calculate amount to be transferred */
-        sec_data_len = CSRMIN(left, PTDL_MAX_SIZE - PTDL_HDR_SIZE);
+        sec_data_len = min_t(u32, left, PTDL_MAX_SIZE - PTDL_HDR_SIZE);
         sec_len = sec_data_len + PTDL_HDR_SIZE;
 
         /* Write PTDL header + entire PTDL size */
diff --git a/drivers/staging/csr/csr_wifi_hip_xbv.h b/drivers/staging/csr/csr_wifi_hip_xbv.h
index 9b60a7e..3c50723 100644
--- a/drivers/staging/csr/csr_wifi_hip_xbv.h
+++ b/drivers/staging/csr/csr_wifi_hip_xbv.h
@@ -21,10 +21,6 @@
 #ifndef __XBV_H__
 #define __XBV_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef CSR_WIFI_XBV_TEST
 /* Driver includes */
 #include "csr_wifi_hip_unifi.h"
@@ -120,8 +116,4 @@ s32 xbv1_read_slut(card_t *card, fwreadfn_t readfn, void *dlpriv, xbv1_t *fwinfo
 void* xbv_to_patch(card_t *card, fwreadfn_t readfn, const void *fw_buf, const xbv1_t *fwinfo,
                    u32 *size);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* __XBV_H__ */
diff --git a/drivers/staging/csr/csr_wifi_hostio_prim.h b/drivers/staging/csr/csr_wifi_hostio_prim.h
index bf7c55c..cfb3e27 100644
--- a/drivers/staging/csr/csr_wifi_hostio_prim.h
+++ b/drivers/staging/csr/csr_wifi_hostio_prim.h
@@ -12,16 +12,7 @@
 #ifndef CSR_WIFI_HOSTIO_H
 #define CSR_WIFI_HOSTIO_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
 #define CSR_WIFI_HOSTIO_PRIM 0x0453
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_HOSTIO_H */
 
diff --git a/drivers/staging/csr/csr_wifi_lib.h b/drivers/staging/csr/csr_wifi_lib.h
index eb56f62..5fde0ef 100644
--- a/drivers/staging/csr/csr_wifi_lib.h
+++ b/drivers/staging/csr/csr_wifi_lib.h
@@ -12,11 +12,6 @@
 
 #include "csr_wifi_fsm_event.h"
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /*----------------------------------------------------------------------------*
  *  CsrWifiFsmEventInit
  *
@@ -105,8 +100,4 @@ typedef struct
  *----------------------------------------------------------------------------*/
 CsrWifiEventCsrUint16CsrUint8* CsrWifiEventCsrUint16CsrUint8_struct(u16 primtype, u16 msgtype, CsrSchedQid dst, CsrSchedQid src, u16 value16, u8 value8);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_LIB_H__ */
diff --git a/drivers/staging/csr/csr_wifi_msgconv.h b/drivers/staging/csr/csr_wifi_msgconv.h
index 7ec35d7..f8b4029 100644
--- a/drivers/staging/csr/csr_wifi_msgconv.h
+++ b/drivers/staging/csr/csr_wifi_msgconv.h
@@ -14,11 +14,6 @@
 #include "csr_prim_defs.h"
 #include "csr_sched.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
 void CsrUint16SerBigEndian(u8 *ptr, size_t *len, u16 v);
 void CsrUint24SerBigEndian(u8 *ptr, size_t *len, u32 v);
 void CsrUint32SerBigEndian(u8 *ptr, size_t *len, u32 v);
@@ -51,8 +46,4 @@ size_t CsrWifiEventCsrUint16CsrUint8Sizeof(void *msg);
 u8* CsrWifiEventCsrUint16CsrUint8Ser(u8 *ptr, size_t *len, void *msg);
 void* CsrWifiEventCsrUint16CsrUint8Des(u8 *buffer, size_t length);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_MSGCONV_H__ */
diff --git a/drivers/staging/csr/csr_wifi_nme_ap_converter_init.h b/drivers/staging/csr/csr_wifi_nme_ap_converter_init.h
index 4072c06..b89d7c7 100644
--- a/drivers/staging/csr/csr_wifi_nme_ap_converter_init.h
+++ b/drivers/staging/csr/csr_wifi_nme_ap_converter_init.h
@@ -13,10 +13,6 @@
 #ifndef CSR_WIFI_NME_AP_CONVERTER_INIT_H__
 #define CSR_WIFI_NME_AP_CONVERTER_INIT_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef CSR_WIFI_NME_ENABLE
 #error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_converter_init.h
 #endif
@@ -42,8 +38,4 @@ extern void CsrWifiNmeApConverterInit(void);
 
 #endif /* EXCLUDE_CSR_WIFI_NME_AP_MODULE */
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_NME_AP_CONVERTER_INIT_H__ */
diff --git a/drivers/staging/csr/csr_wifi_nme_ap_lib.h b/drivers/staging/csr/csr_wifi_nme_ap_lib.h
index d401470..6d8df83 100644
--- a/drivers/staging/csr/csr_wifi_nme_ap_lib.h
+++ b/drivers/staging/csr/csr_wifi_nme_ap_lib.h
@@ -22,11 +22,6 @@
 #include "csr_wifi_nme_ap_prim.h"
 #include "csr_wifi_nme_task.h"
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef CSR_WIFI_NME_ENABLE
 #error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_lib.h
 #endif
@@ -58,24 +53,6 @@ void CsrWifiNmeApFreeUpstreamMessageContents(u16 eventClass, void *message);
  *----------------------------------------------------------------------------*/
 void CsrWifiNmeApFreeDownstreamMessageContents(u16 eventClass, void *message);
 
-/*----------------------------------------------------------------------------*
- * Enum to string functions
- *----------------------------------------------------------------------------*/
-const char* CsrWifiNmeApPersCredentialTypeToString(CsrWifiNmeApPersCredentialType value);
-
-
-/*----------------------------------------------------------------------------*
- * CsrPrim Type toString function.
- * Converts a message type to the String name of the Message
- *----------------------------------------------------------------------------*/
-const char* CsrWifiNmeApPrimTypeToString(CsrPrim msgType);
-
-/*----------------------------------------------------------------------------*
- * Lookup arrays for PrimType name Strings
- *----------------------------------------------------------------------------*/
-extern const char *CsrWifiNmeApUpstreamPrimNames[CSR_WIFI_NME_AP_PRIM_UPSTREAM_COUNT];
-extern const char *CsrWifiNmeApDownstreamPrimNames[CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_COUNT];
-
 /*******************************************************************************
 
   NAME
@@ -515,9 +492,4 @@ extern const char *CsrWifiNmeApDownstreamPrimNames[CSR_WIFI_NME_AP_PRIM_DOWNSTRE
 #define CsrWifiNmeApWpsRegisterCfmSend(dst__, interfaceTag__, status__) \
     CsrWifiNmeApWpsRegisterCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__)
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_NME_AP_LIB_H__ */
diff --git a/drivers/staging/csr/csr_wifi_nme_ap_prim.h b/drivers/staging/csr/csr_wifi_nme_ap_prim.h
index fc44560..b32bdbc 100644
--- a/drivers/staging/csr/csr_wifi_nme_ap_prim.h
+++ b/drivers/staging/csr/csr_wifi_nme_ap_prim.h
@@ -22,10 +22,6 @@
 #include "csr_wifi_sme_ap_prim.h"
 #include "csr_wifi_nme_prim.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef CSR_WIFI_NME_ENABLE
 #error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_prim.h
 #endif
@@ -494,10 +490,5 @@ typedef struct
     CsrWifiMacAddress     peerDeviceAddress;
 } CsrWifiNmeApStationInd;
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_NME_AP_PRIM_H__ */
 
diff --git a/drivers/staging/csr/csr_wifi_nme_ap_sef.h b/drivers/staging/csr/csr_wifi_nme_ap_sef.h
index 3f35363..3daaa09 100644
--- a/drivers/staging/csr/csr_wifi_nme_ap_sef.h
+++ b/drivers/staging/csr/csr_wifi_nme_ap_sef.h
@@ -11,11 +11,6 @@
 
 #include "csr_wifi_nme_prim.h"
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 void CsrWifiNmeApUpstreamStateHandlers(void* drvpriv, CsrWifiFsmEvent* msg);
 
 
@@ -23,9 +18,4 @@ extern void CsrWifiNmeApConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg)
 extern void CsrWifiNmeApStartCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
 extern void CsrWifiNmeApStopCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_ROUTER_SEF_CSR_WIFI_NME_H__ */
diff --git a/drivers/staging/csr/csr_wifi_nme_ap_serialize.h b/drivers/staging/csr/csr_wifi_nme_ap_serialize.h
index 0f57829..c04585e 100644
--- a/drivers/staging/csr/csr_wifi_nme_ap_serialize.h
+++ b/drivers/staging/csr/csr_wifi_nme_ap_serialize.h
@@ -17,10 +17,6 @@
 
 #include "csr_wifi_nme_ap_prim.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef CSR_WIFI_NME_ENABLE
 #error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_serialize.h
 #endif
@@ -95,9 +91,4 @@ extern void* CsrWifiNmeApStationIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiNmeApStationIndSizeof(void *msg);
 #define CsrWifiNmeApStationIndSerFree CsrWifiNmeApPfree
 
-
-#ifdef __cplusplus
-}
-#endif
 #endif /* CSR_WIFI_NME_AP_SERIALIZE_H__ */
-
diff --git a/drivers/staging/csr/csr_wifi_nme_converter_init.h b/drivers/staging/csr/csr_wifi_nme_converter_init.h
index 6661914..85e6f5f 100644
--- a/drivers/staging/csr/csr_wifi_nme_converter_init.h
+++ b/drivers/staging/csr/csr_wifi_nme_converter_init.h
@@ -13,10 +13,6 @@
 #ifndef CSR_WIFI_NME_CONVERTER_INIT_H__
 #define CSR_WIFI_NME_CONVERTER_INIT_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef CSR_WIFI_NME_ENABLE
 #error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_converter_init.h
 #endif
@@ -39,8 +35,4 @@ extern void CsrWifiNmeConverterInit(void);
 
 #endif /* EXCLUDE_CSR_WIFI_NME_MODULE */
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_NME_CONVERTER_INIT_H__ */
diff --git a/drivers/staging/csr/csr_wifi_nme_lib.h b/drivers/staging/csr/csr_wifi_nme_lib.h
index 709ece4..5a1f132 100644
--- a/drivers/staging/csr/csr_wifi_nme_lib.h
+++ b/drivers/staging/csr/csr_wifi_nme_lib.h
@@ -23,68 +23,10 @@
 #include "csr_wifi_nme_task.h"
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef CSR_WIFI_NME_ENABLE
 #error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_lib.h
 #endif
 
-/*----------------------------------------------------------------------------*
- *  CsrWifiNmeFreeUpstreamMessageContents
- *
- *  DESCRIPTION
- *      Free the allocated memory in a CSR_WIFI_NME upstream message. Does not
- *      free the message itself, and can only be used for upstream messages.
- *
- *  PARAMETERS
- *      Deallocates the resources in a CSR_WIFI_NME upstream message
- *----------------------------------------------------------------------------*/
-void CsrWifiNmeFreeUpstreamMessageContents(u16 eventClass, void *message);
-
-/*----------------------------------------------------------------------------*
- *  CsrWifiNmeFreeDownstreamMessageContents
- *
- *  DESCRIPTION
- *      Free the allocated memory in a CSR_WIFI_NME downstream message. Does not
- *      free the message itself, and can only be used for downstream messages.
- *
- *  PARAMETERS
- *      Deallocates the resources in a CSR_WIFI_NME downstream message
- *----------------------------------------------------------------------------*/
-void CsrWifiNmeFreeDownstreamMessageContents(u16 eventClass, void *message);
-
-/*----------------------------------------------------------------------------*
- * Enum to string functions
- *----------------------------------------------------------------------------*/
-const char* CsrWifiNmeAuthModeToString(CsrWifiNmeAuthMode value);
-const char* CsrWifiNmeBssTypeToString(CsrWifiNmeBssType value);
-const char* CsrWifiNmeCcxOptionsMaskToString(CsrWifiNmeCcxOptionsMask value);
-const char* CsrWifiNmeConfigActionToString(CsrWifiNmeConfigAction value);
-const char* CsrWifiNmeConnectionStatusToString(CsrWifiNmeConnectionStatus value);
-const char* CsrWifiNmeCredentialTypeToString(CsrWifiNmeCredentialType value);
-const char* CsrWifiNmeEapMethodToString(CsrWifiNmeEapMethod value);
-const char* CsrWifiNmeEncryptionToString(CsrWifiNmeEncryption value);
-const char* CsrWifiNmeIndicationsToString(CsrWifiNmeIndications value);
-const char* CsrWifiNmeSecErrorToString(CsrWifiNmeSecError value);
-const char* CsrWifiNmeSimCardTypeToString(CsrWifiNmeSimCardType value);
-const char* CsrWifiNmeUmtsAuthResultToString(CsrWifiNmeUmtsAuthResult value);
-const char* CsrWifiNmeWmmQosInfoToString(CsrWifiNmeWmmQosInfo value);
-
-
-/*----------------------------------------------------------------------------*
- * CsrPrim Type toString function.
- * Converts a message type to the String name of the Message
- *----------------------------------------------------------------------------*/
-const char* CsrWifiNmePrimTypeToString(CsrPrim msgType);
-
-/*----------------------------------------------------------------------------*
- * Lookup arrays for PrimType name Strings
- *----------------------------------------------------------------------------*/
-extern const char *CsrWifiNmeUpstreamPrimNames[CSR_WIFI_NME_PRIM_UPSTREAM_COUNT];
-extern const char *CsrWifiNmeDownstreamPrimNames[CSR_WIFI_NME_PRIM_DOWNSTREAM_COUNT];
-
 /*******************************************************************************
 
   NAME
@@ -1046,9 +988,4 @@ extern const char *CsrWifiNmeDownstreamPrimNames[CSR_WIFI_NME_PRIM_DOWNSTREAM_CO
 #define CsrWifiNmeWpsReqSend(src__, interfaceTag__, pin__, ssid__, bssid__) \
     CsrWifiNmeWpsReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__, pin__, ssid__, bssid__)
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_NME_LIB_H__ */
diff --git a/drivers/staging/csr/csr_wifi_nme_prim.h b/drivers/staging/csr/csr_wifi_nme_prim.h
index 20dc779..9a7927a 100644
--- a/drivers/staging/csr/csr_wifi_nme_prim.h
+++ b/drivers/staging/csr/csr_wifi_nme_prim.h
@@ -21,10 +21,6 @@
 #include "csr_wifi_fsm_event.h"
 #include "csr_wifi_sme_prim.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef CSR_WIFI_NME_ENABLE
 #error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_prim.h
 #endif
@@ -1657,10 +1653,5 @@ typedef struct
     CsrResult       status;
 } CsrWifiNmeEventMaskSetCfm;
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_NME_PRIM_H__ */
 
diff --git a/drivers/staging/csr/csr_wifi_nme_serialize.h b/drivers/staging/csr/csr_wifi_nme_serialize.h
index c6b1636..ebac484 100644
--- a/drivers/staging/csr/csr_wifi_nme_serialize.h
+++ b/drivers/staging/csr/csr_wifi_nme_serialize.h
@@ -16,10 +16,6 @@
 #include "csr_wifi_msgconv.h"
 #include "csr_wifi_nme_prim.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef CSR_WIFI_NME_ENABLE
 #error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_serialize.h
 #endif
@@ -166,9 +162,5 @@ extern size_t CsrWifiNmeSimUmtsAuthIndSizeof(void *msg);
 #define CsrWifiNmeEventMaskSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiNmeEventMaskSetCfmSerFree CsrWifiNmePfree
 
-
-#ifdef __cplusplus
-}
-#endif
 #endif /* CSR_WIFI_NME_SERIALIZE_H__ */
 
diff --git a/drivers/staging/csr/csr_wifi_nme_task.h b/drivers/staging/csr/csr_wifi_nme_task.h
index 76f44db..84e973a 100644
--- a/drivers/staging/csr/csr_wifi_nme_task.h
+++ b/drivers/staging/csr/csr_wifi_nme_task.h
@@ -16,23 +16,12 @@
 #include <linux/types.h>
 #include "csr_sched.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef CSR_WIFI_NME_ENABLE
 #error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_task.h
 #endif
 
 #define CSR_WIFI_NME_LOG_ID 0x1203FFFF
 extern CsrSchedQid CSR_WIFI_NME_IFACEQUEUE;
-void CsrWifiNmeInit(void **gash);
-void CsrWifiNmeDeinit(void **gash);
-void CsrWifiNmeHandler(void **gash);
-
-#ifdef __cplusplus
-}
-#endif
 
 #endif /* CSR_WIFI_NME_TASK_H__ */
 
diff --git a/drivers/staging/csr/csr_wifi_private_common.h b/drivers/staging/csr/csr_wifi_private_common.h
index 4730998..ee3bd51 100644
--- a/drivers/staging/csr/csr_wifi_private_common.h
+++ b/drivers/staging/csr/csr_wifi_private_common.h
@@ -11,10 +11,6 @@
 #ifndef CSR_WIFI_PRIVATE_COMMON_H__
 #define CSR_WIFI_PRIVATE_COMMON_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * @brief maximum number of STAs allowed to be connected
  *
@@ -81,9 +77,5 @@ typedef u8 CsrWifiInterfaceMode;
 #define  CSR_WIFI_MODE_WPS_ENROLLEE                     ((CsrWifiInterfaceMode) 0x06)
 #define  CSR_WIFI_MODE_IBSS                             ((CsrWifiInterfaceMode) 0x07)
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
 
diff --git a/drivers/staging/csr/csr_wifi_result.h b/drivers/staging/csr/csr_wifi_result.h
index 2f87cda..3c394c7 100644
--- a/drivers/staging/csr/csr_wifi_result.h
+++ b/drivers/staging/csr/csr_wifi_result.h
@@ -13,10 +13,6 @@
 
 #include "csr_result.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* THIS FILE SHOULD CONTAIN ONLY RESULT CODES */
 
 /* Result Codes */
@@ -27,9 +23,5 @@ extern "C" {
 #define CSR_WIFI_HIP_RESULT_RANGE            ((CsrResult) 5) /* Request exceeds the range of a file or a buffer */
 #define CSR_WIFI_HIP_RESULT_NOT_FOUND        ((CsrResult) 6) /* A file (typically a f/w patch) is not found */
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_RESULT_H__ */
 
diff --git a/drivers/staging/csr/csr_wifi_router_converter_init.h b/drivers/staging/csr/csr_wifi_router_converter_init.h
index 2a293e4..478327b 100644
--- a/drivers/staging/csr/csr_wifi_router_converter_init.h
+++ b/drivers/staging/csr/csr_wifi_router_converter_init.h
@@ -13,10 +13,6 @@
 #ifndef CSR_WIFI_ROUTER_CONVERTER_INIT_H__
 #define CSR_WIFI_ROUTER_CONVERTER_INIT_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef EXCLUDE_CSR_WIFI_ROUTER_MODULE
 
 #include "csr_msgconv.h"
@@ -35,8 +31,4 @@ extern void CsrWifiRouterConverterInit(void);
 
 #endif /* EXCLUDE_CSR_WIFI_ROUTER_MODULE */
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_ROUTER_CONVERTER_INIT_H__ */
diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.h b/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.h
index 0c9d26b..c984589 100644
--- a/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.h
+++ b/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.h
@@ -13,10 +13,6 @@
 #ifndef CSR_WIFI_ROUTER_CTRL_CONVERTER_INIT_H__
 #define CSR_WIFI_ROUTER_CTRL_CONVERTER_INIT_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef EXCLUDE_CSR_WIFI_ROUTER_CTRL_MODULE
 
 #include "csr_msgconv.h"
@@ -35,8 +31,4 @@ extern void CsrWifiRouterCtrlConverterInit(void);
 
 #endif /* EXCLUDE_CSR_WIFI_ROUTER_CTRL_MODULE */
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_ROUTER_CTRL_CONVERTER_INIT_H__ */
diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_lib.h b/drivers/staging/csr/csr_wifi_router_ctrl_lib.h
index 93d0fad..f235153 100644
--- a/drivers/staging/csr/csr_wifi_router_ctrl_lib.h
+++ b/drivers/staging/csr/csr_wifi_router_ctrl_lib.h
@@ -22,11 +22,6 @@
 #include "csr_wifi_router_ctrl_prim.h"
 #include "csr_wifi_router_task.h"
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /*----------------------------------------------------------------------------*
  *  CsrWifiRouterCtrlFreeUpstreamMessageContents
  *
@@ -2084,9 +2079,4 @@ extern const char *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER_CTRL_PRI
 #define CsrWifiRouterCtrlWifiOnCfmSend(dst__, clientData__, status__) \
     CsrWifiRouterCtrlWifiOnCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, status__)
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_ROUTER_CTRL_LIB_H__ */
diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_prim.h b/drivers/staging/csr/csr_wifi_router_ctrl_prim.h
index ec972ac..1312a33 100644
--- a/drivers/staging/csr/csr_wifi_router_ctrl_prim.h
+++ b/drivers/staging/csr/csr_wifi_router_ctrl_prim.h
@@ -20,10 +20,6 @@
 #include "csr_result.h"
 #include "csr_wifi_fsm_event.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define CSR_WIFI_ROUTER_CTRL_PRIM                                       (0x0401)
 
 typedef CsrPrim CsrWifiRouterCtrlPrim;
@@ -2113,10 +2109,5 @@ typedef struct
     u8                      *data;
 } CsrWifiRouterCtrlWapiUnicastTxEncryptInd;
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_ROUTER_CTRL_PRIM_H__ */
 
diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_sef.c b/drivers/staging/csr/csr_wifi_router_ctrl_sef.c
index 33d92b6..99cf930 100644
--- a/drivers/staging/csr/csr_wifi_router_ctrl_sef.c
+++ b/drivers/staging/csr/csr_wifi_router_ctrl_sef.c
@@ -9,37 +9,38 @@
  *****************************************************************************/
 #include "csr_wifi_router_ctrl_sef.h"
 
-const CsrWifiRouterCtrlStateHandlerType CsrWifiRouterCtrlDownstreamStateHandlers[CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT] =
-{
-    /* 0x0000 */ CsrWifiRouterCtrlConfigurePowerModeReqHandler,
-    /* 0x0001 */ CsrWifiRouterCtrlHipReqHandler,
-    /* 0x0002 */ CsrWifiRouterCtrlMediaStatusReqHandler,
-    /* 0x0003 */ CsrWifiRouterCtrlMulticastAddressResHandler,
-    /* 0x0004 */ CsrWifiRouterCtrlPortConfigureReqHandler,
-    /* 0x0005 */ CsrWifiRouterCtrlQosControlReqHandler,
-    /* 0x0006 */ CsrWifiRouterCtrlSuspendResHandler,
-    /* 0x0007 */ CsrWifiRouterCtrlTclasAddReqHandler,
-    /* 0x0008 */ CsrWifiRouterCtrlResumeResHandler,
-    /* 0x0009 */ CsrWifiRouterCtrlRawSdioDeinitialiseReqHandler,
-    /* 0x000A */ CsrWifiRouterCtrlRawSdioInitialiseReqHandler,
-    /* 0x000B */ CsrWifiRouterCtrlTclasDelReqHandler,
-    /* 0x000C */ CsrWifiRouterCtrlTrafficClassificationReqHandler,
-    /* 0x000D */ CsrWifiRouterCtrlTrafficConfigReqHandler,
-    /* 0x000E */ CsrWifiRouterCtrlWifiOffReqHandler,
-    /* 0x000F */ CsrWifiRouterCtrlWifiOffResHandler,
-    /* 0x0010 */ CsrWifiRouterCtrlWifiOnReqHandler,
-    /* 0x0011 */ CsrWifiRouterCtrlWifiOnResHandler,
-    /* 0x0012 */ CsrWifiRouterCtrlM4TransmitReqHandler,
-    /* 0x0013 */ CsrWifiRouterCtrlModeSetReqHandler,
-    /* 0x0014 */ CsrWifiRouterCtrlPeerAddReqHandler,
-    /* 0x0015 */ CsrWifiRouterCtrlPeerDelReqHandler,
-    /* 0x0016 */ CsrWifiRouterCtrlPeerUpdateReqHandler,
-    /* 0x0017 */ CsrWifiRouterCtrlCapabilitiesReqHandler,
-    /* 0x0018 */ CsrWifiRouterCtrlBlockAckEnableReqHandler,
-    /* 0x0019 */ CsrWifiRouterCtrlBlockAckDisableReqHandler,
-    /* 0x001A */ CsrWifiRouterCtrlWapiRxPktReqHandler,
-    /* 0x001B */ CsrWifiRouterCtrlWapiMulticastFilterReqHandler,
-    /* 0x001C */ CsrWifiRouterCtrlWapiUnicastFilterReqHandler,
-    /* 0x001D */ CsrWifiRouterCtrlWapiUnicastTxPktReqHandler,
-    /* 0x001E */ CsrWifiRouterCtrlWapiFilterReqHandler,
+const CsrWifiRouterCtrlStateHandlerType
+	CsrWifiRouterCtrlDownstreamStateHandlers
+	[CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT] = {
+		/* 0x0000 */ CsrWifiRouterCtrlConfigurePowerModeReqHandler,
+		/* 0x0001 */ CsrWifiRouterCtrlHipReqHandler,
+		/* 0x0002 */ CsrWifiRouterCtrlMediaStatusReqHandler,
+		/* 0x0003 */ CsrWifiRouterCtrlMulticastAddressResHandler,
+		/* 0x0004 */ CsrWifiRouterCtrlPortConfigureReqHandler,
+		/* 0x0005 */ CsrWifiRouterCtrlQosControlReqHandler,
+		/* 0x0006 */ CsrWifiRouterCtrlSuspendResHandler,
+		/* 0x0007 */ CsrWifiRouterCtrlTclasAddReqHandler,
+		/* 0x0008 */ CsrWifiRouterCtrlResumeResHandler,
+		/* 0x0009 */ CsrWifiRouterCtrlRawSdioDeinitialiseReqHandler,
+		/* 0x000A */ CsrWifiRouterCtrlRawSdioInitialiseReqHandler,
+		/* 0x000B */ CsrWifiRouterCtrlTclasDelReqHandler,
+		/* 0x000C */ CsrWifiRouterCtrlTrafficClassificationReqHandler,
+		/* 0x000D */ CsrWifiRouterCtrlTrafficConfigReqHandler,
+		/* 0x000E */ CsrWifiRouterCtrlWifiOffReqHandler,
+		/* 0x000F */ CsrWifiRouterCtrlWifiOffResHandler,
+		/* 0x0010 */ CsrWifiRouterCtrlWifiOnReqHandler,
+		/* 0x0011 */ CsrWifiRouterCtrlWifiOnResHandler,
+		/* 0x0012 */ CsrWifiRouterCtrlM4TransmitReqHandler,
+		/* 0x0013 */ CsrWifiRouterCtrlModeSetReqHandler,
+		/* 0x0014 */ CsrWifiRouterCtrlPeerAddReqHandler,
+		/* 0x0015 */ CsrWifiRouterCtrlPeerDelReqHandler,
+		/* 0x0016 */ CsrWifiRouterCtrlPeerUpdateReqHandler,
+		/* 0x0017 */ CsrWifiRouterCtrlCapabilitiesReqHandler,
+		/* 0x0018 */ CsrWifiRouterCtrlBlockAckEnableReqHandler,
+		/* 0x0019 */ CsrWifiRouterCtrlBlockAckDisableReqHandler,
+		/* 0x001A */ CsrWifiRouterCtrlWapiRxPktReqHandler,
+		/* 0x001B */ CsrWifiRouterCtrlWapiMulticastFilterReqHandler,
+		/* 0x001C */ CsrWifiRouterCtrlWapiUnicastFilterReqHandler,
+		/* 0x001D */ CsrWifiRouterCtrlWapiUnicastTxPktReqHandler,
+		/* 0x001E */ CsrWifiRouterCtrlWapiFilterReqHandler,
 };
diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_sef.h b/drivers/staging/csr/csr_wifi_router_ctrl_sef.h
index e0ee5cf..2fb4937 100644
--- a/drivers/staging/csr/csr_wifi_router_ctrl_sef.h
+++ b/drivers/staging/csr/csr_wifi_router_ctrl_sef.h
@@ -12,10 +12,6 @@
 
 #include "csr_wifi_router_ctrl_prim.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
     typedef void (*CsrWifiRouterCtrlStateHandlerType)(void* drvpriv, CsrWifiFsmEvent* msg);
 
     extern const CsrWifiRouterCtrlStateHandlerType CsrWifiRouterCtrlDownstreamStateHandlers[CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT];
@@ -51,8 +47,5 @@ extern "C" {
     extern void CsrWifiRouterCtrlWapiUnicastTxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
     extern void CsrWifiRouterCtrlWapiUnicastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
     extern void CsrWifiRouterCtrlWapiFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-#ifdef __cplusplus
-}
-#endif
 
 #endif /* CSR_WIFI_ROUTER_SEF_CSR_WIFI_ROUTER_CTRL_H__ */
diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_serialize.h b/drivers/staging/csr/csr_wifi_router_ctrl_serialize.h
index 2c2a229..c904838 100644
--- a/drivers/staging/csr/csr_wifi_router_ctrl_serialize.h
+++ b/drivers/staging/csr/csr_wifi_router_ctrl_serialize.h
@@ -17,10 +17,6 @@
 
 #include "csr_wifi_router_ctrl_prim.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 extern void CsrWifiRouterCtrlPfree(void *ptr);
 
 extern u8* CsrWifiRouterCtrlConfigurePowerModeReqSer(u8 *ptr, size_t *len, void *msg);
@@ -333,9 +329,5 @@ extern void* CsrWifiRouterCtrlWapiUnicastTxEncryptIndDes(u8 *buffer, size_t len)
 extern size_t CsrWifiRouterCtrlWapiUnicastTxEncryptIndSizeof(void *msg);
 extern void CsrWifiRouterCtrlWapiUnicastTxEncryptIndSerFree(void *msg);
 
-
-#ifdef __cplusplus
-}
-#endif
 #endif /* CSR_WIFI_ROUTER_CTRL_SERIALIZE_H__ */
 
diff --git a/drivers/staging/csr/csr_wifi_router_free_upstream_contents.c b/drivers/staging/csr/csr_wifi_router_free_upstream_contents.c
index de1086d..4cd1263 100644
--- a/drivers/staging/csr/csr_wifi_router_free_upstream_contents.c
+++ b/drivers/staging/csr/csr_wifi_router_free_upstream_contents.c
@@ -1,10 +1,10 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
-            All rights reserved and confidential information of CSR
+	(c) Cambridge Silicon Radio Limited 2011
+	All rights reserved and confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+	Refer to LICENSE.txt included with this source for details
+	on the license terms.
 
 *****************************************************************************/
 
@@ -26,28 +26,22 @@
  *----------------------------------------------------------------------------*/
 void CsrWifiRouterFreeUpstreamMessageContents(u16 eventClass, void *message)
 {
-    if (eventClass != CSR_WIFI_ROUTER_PRIM)
-    {
-        return;
-    }
-    if (NULL == message)
-    {
-        return;
-    }
-
-    switch (*((CsrWifiRouterPrim *) message))
-    {
-        case CSR_WIFI_ROUTER_MA_PACKET_IND:
-        {
-            CsrWifiRouterMaPacketInd *p = (CsrWifiRouterMaPacketInd *)message;
-            kfree(p->frame);
-            p->frame = NULL;
-            break;
-        }
-
-        default:
-            break;
-    }
+	if (eventClass != CSR_WIFI_ROUTER_PRIM)
+		return;
+	if (NULL == message)
+		return;
+	switch (*((CsrWifiRouterPrim *) message)) {
+	case CSR_WIFI_ROUTER_MA_PACKET_IND:
+	{
+		CsrWifiRouterMaPacketInd *p =
+			(CsrWifiRouterMaPacketInd *) message;
+		kfree(p->frame);
+		p->frame = NULL;
+		break;
+	}
+	default:
+		break;
+	}
 }
 
 
diff --git a/drivers/staging/csr/csr_wifi_router_lib.h b/drivers/staging/csr/csr_wifi_router_lib.h
index 06a2214..b0477c4 100644
--- a/drivers/staging/csr/csr_wifi_router_lib.h
+++ b/drivers/staging/csr/csr_wifi_router_lib.h
@@ -22,11 +22,6 @@
 #include "csr_wifi_router_prim.h"
 #include "csr_wifi_router_task.h"
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /*----------------------------------------------------------------------------*
  *  CsrWifiRouterFreeUpstreamMessageContents
  *
@@ -419,9 +414,4 @@ extern const char *CsrWifiRouterDownstreamPrimNames[CSR_WIFI_ROUTER_PRIM_DOWNSTR
 #define CsrWifiRouterMaPacketUnsubscribeCfmSend(dst__, interfaceTag__, status__) \
     CsrWifiRouterMaPacketUnsubscribeCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, interfaceTag__, status__)
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_ROUTER_LIB_H__ */
diff --git a/drivers/staging/csr/csr_wifi_router_prim.h b/drivers/staging/csr/csr_wifi_router_prim.h
index c61486f..c52344b 100644
--- a/drivers/staging/csr/csr_wifi_router_prim.h
+++ b/drivers/staging/csr/csr_wifi_router_prim.h
@@ -20,10 +20,6 @@
 #include "csr_result.h"
 #include "csr_wifi_fsm_event.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define CSR_WIFI_ROUTER_PRIM                                            (0x0400)
 
 typedef CsrPrim CsrWifiRouterPrim;
@@ -421,10 +417,5 @@ typedef struct
     u16                      rate;
 } CsrWifiRouterMaPacketInd;
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_ROUTER_PRIM_H__ */
 
diff --git a/drivers/staging/csr/csr_wifi_router_sef.h b/drivers/staging/csr/csr_wifi_router_sef.h
index 49dd158..86692c7 100644
--- a/drivers/staging/csr/csr_wifi_router_sef.h
+++ b/drivers/staging/csr/csr_wifi_router_sef.h
@@ -12,10 +12,6 @@
 
 #include "csr_wifi_router_prim.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
     typedef void (*CsrWifiRouterStateHandlerType)(void* drvpriv, CsrWifiFsmEvent* msg);
 
     extern const CsrWifiRouterStateHandlerType CsrWifiRouterDownstreamStateHandlers[CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT];
@@ -26,8 +22,4 @@ extern "C" {
     extern void CsrWifiRouterMaPacketResHandler(void* drvpriv, CsrWifiFsmEvent* msg);
     extern void CsrWifiRouterMaPacketCancelReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_ROUTER_SEF_CSR_WIFI_ROUTER_H__ */
diff --git a/drivers/staging/csr/csr_wifi_router_serialize.h b/drivers/staging/csr/csr_wifi_router_serialize.h
index 07e21b2..94ccdac 100644
--- a/drivers/staging/csr/csr_wifi_router_serialize.h
+++ b/drivers/staging/csr/csr_wifi_router_serialize.h
@@ -16,10 +16,6 @@
 #include "csr_wifi_msgconv.h"
 #include "csr_wifi_router_prim.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 extern void CsrWifiRouterPfree(void *ptr);
 
 extern u8* CsrWifiRouterMaPacketSubscribeReqSer(u8 *ptr, size_t *len, void *msg);
@@ -67,9 +63,5 @@ extern void* CsrWifiRouterMaPacketIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiRouterMaPacketIndSizeof(void *msg);
 extern void CsrWifiRouterMaPacketIndSerFree(void *msg);
 
-
-#ifdef __cplusplus
-}
-#endif
 #endif /* CSR_WIFI_ROUTER_SERIALIZE_H__ */
 
diff --git a/drivers/staging/csr/csr_wifi_router_task.h b/drivers/staging/csr/csr_wifi_router_task.h
index 4e51fae..9ba892f 100644
--- a/drivers/staging/csr/csr_wifi_router_task.h
+++ b/drivers/staging/csr/csr_wifi_router_task.h
@@ -15,19 +15,11 @@
 
 #include "csr_sched.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define CSR_WIFI_ROUTER_LOG_ID 0x1201FFFF
 extern CsrSchedQid CSR_WIFI_ROUTER_IFACEQUEUE;
 void CsrWifiRouterInit(void **gash);
 void CsrWifiRouterDeinit(void **gash);
 void CsrWifiRouterHandler(void **gash);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_ROUTER_TASK_H__ */
 
diff --git a/drivers/staging/csr/csr_wifi_sme_ap_lib.h b/drivers/staging/csr/csr_wifi_sme_ap_lib.h
index 350cb9e..48ea914 100644
--- a/drivers/staging/csr/csr_wifi_sme_ap_lib.h
+++ b/drivers/staging/csr/csr_wifi_sme_ap_lib.h
@@ -22,11 +22,6 @@
 #include "csr_wifi_sme_ap_prim.h"
 #include "csr_wifi_sme_task.h"
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef CSR_WIFI_AP_ENABLE
 #error CSR_WIFI_AP_ENABLE MUST be defined inorder to use csr_wifi_sme_ap_lib.h
 #endif
@@ -776,8 +771,4 @@ extern const char *CsrWifiSmeApDownstreamPrimNames[CSR_WIFI_SME_AP_PRIM_DOWNSTRE
     CsrWifiSmeApWpsRegistrationStartedCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__)
 
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_SME_AP_LIB_H__ */
diff --git a/drivers/staging/csr/csr_wifi_sme_ap_prim.h b/drivers/staging/csr/csr_wifi_sme_ap_prim.h
index 93b64e9..3c4bcbc 100644
--- a/drivers/staging/csr/csr_wifi_sme_ap_prim.h
+++ b/drivers/staging/csr/csr_wifi_sme_ap_prim.h
@@ -20,10 +20,6 @@
 #include "csr_wifi_fsm_event.h"
 #include "csr_wifi_sme_prim.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef CSR_WIFI_AP_ENABLE
 #error CSR_WIFI_AP_ENABLE MUST be defined inorder to use csr_wifi_sme_ap_prim.h
 #endif
@@ -1030,9 +1026,5 @@ typedef struct
 } CsrWifiSmeApBaDeleteCfm;
 
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_SME_AP_PRIM_H__ */
 
diff --git a/drivers/staging/csr/csr_wifi_sme_converter_init.h b/drivers/staging/csr/csr_wifi_sme_converter_init.h
index fb895de..ba5e4b4 100644
--- a/drivers/staging/csr/csr_wifi_sme_converter_init.h
+++ b/drivers/staging/csr/csr_wifi_sme_converter_init.h
@@ -13,10 +13,6 @@
 #ifndef CSR_WIFI_SME_CONVERTER_INIT_H__
 #define CSR_WIFI_SME_CONVERTER_INIT_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifndef EXCLUDE_CSR_WIFI_SME_MODULE
 
 #include "csr_msgconv.h"
@@ -35,8 +31,4 @@ extern void CsrWifiSmeConverterInit(void);
 
 #endif /* EXCLUDE_CSR_WIFI_SME_MODULE */
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_SME_CONVERTER_INIT_H__ */
diff --git a/drivers/staging/csr/csr_wifi_sme_lib.h b/drivers/staging/csr/csr_wifi_sme_lib.h
index 3ca7456..53cf126 100644
--- a/drivers/staging/csr/csr_wifi_sme_lib.h
+++ b/drivers/staging/csr/csr_wifi_sme_lib.h
@@ -32,11 +32,6 @@
 # endif
 #endif
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /*----------------------------------------------------------------------------*
  *  CsrWifiSmeFreeUpstreamMessageContents
  *
@@ -4305,9 +4300,4 @@ extern const char *CsrWifiSmeDownstreamPrimNames[CSR_WIFI_SME_PRIM_DOWNSTREAM_CO
 #define CsrWifiSmeWpsConfigurationCfmSend(dst__, status__) \
     CsrWifiSmeWpsConfigurationCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__)
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_SME_LIB_H__ */
diff --git a/drivers/staging/csr/csr_wifi_sme_prim.h b/drivers/staging/csr/csr_wifi_sme_prim.h
index 55cac50..17ec79c 100644
--- a/drivers/staging/csr/csr_wifi_sme_prim.h
+++ b/drivers/staging/csr/csr_wifi_sme_prim.h
@@ -20,10 +20,6 @@
 #include "csr_result.h"
 #include "csr_wifi_fsm_event.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define CSR_WIFI_SME_PRIM                                               (0x0404)
 
 typedef CsrPrim CsrWifiSmePrim;
@@ -6510,10 +6506,5 @@ typedef struct
     CsrResult       status;
 } CsrWifiSmeWpsConfigurationCfm;
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_SME_PRIM_H__ */
 
diff --git a/drivers/staging/csr/csr_wifi_sme_sef.h b/drivers/staging/csr/csr_wifi_sme_sef.h
index c874181..78b88c0 100644
--- a/drivers/staging/csr/csr_wifi_sme_sef.h
+++ b/drivers/staging/csr/csr_wifi_sme_sef.h
@@ -1,10 +1,10 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2010
-            Confidential information of CSR
+	(c) Cambridge Silicon Radio Limited 2010
+	Confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+	Refer to LICENSE.txt included with this source for details
+	on the license terms.
 
 *****************************************************************************/
 #ifndef CSR_WIFI_ROUTER_SEF_CSR_WIFI_SME_H__
@@ -12,90 +12,131 @@
 
 #include "csr_wifi_sme_prim.h"
 
+typedef void (*CsrWifiSmeStateHandlerType)(void *drvpriv, CsrWifiFsmEvent *msg);
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+extern const CsrWifiSmeStateHandlerType
+	CsrWifiSmeUpstreamStateHandlers[CSR_WIFI_SME_PRIM_UPSTREAM_COUNT];
 
-typedef void (*CsrWifiSmeStateHandlerType)(void* drvpriv, CsrWifiFsmEvent* msg);
 
-extern const CsrWifiSmeStateHandlerType CsrWifiSmeUpstreamStateHandlers[CSR_WIFI_SME_PRIM_UPSTREAM_COUNT];
-
-
-extern void CsrWifiSmeActivateCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeAdhocConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeAdhocConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeAssociationCompleteIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeAssociationStartIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeBlacklistCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCalibrationDataGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCalibrationDataSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCcxConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCcxConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCoexConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCoexConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCoexInfoGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeConnectCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeConnectionConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeConnectionInfoGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeConnectionQualityIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeConnectionStatsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeDeactivateCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeDisconnectCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeEventMaskSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeHostConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeHostConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeIbssStationIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeKeyCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeLinkQualityGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeMediaStatusIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeMibConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeMibConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeMibGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeMibGetNextCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeMibSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeMicFailureIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeMulticastAddressCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmePacketFilterSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmePermanentMacAddressGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmePmkidCandidateListIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmePmkidCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmePowerConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmePowerConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeRegulatoryDomainInfoGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeRoamCompleteIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeRoamStartIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeRoamingConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeRoamingConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeScanConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeScanConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeScanFullCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeScanResultIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeScanResultsFlushCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeScanResultsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeSmeStaConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeSmeStaConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeStationMacAddressGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeTspecIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeTspecCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeVersionsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeWifiFlightmodeCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeWifiOffIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeWifiOffCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeWifiOnCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCloakedSsidsSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCloakedSsidsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeWifiOnIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeSmeCommonConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeSmeCommonConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeGetInterfaceCapabilityCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeErrorIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeInfoIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeCoreDumpIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-extern void CsrWifiSmeAmpStatusChangeIndHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-
-#ifdef __cplusplus
-}
-#endif
+extern void CsrWifiSmeActivateCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeAdhocConfigGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeAdhocConfigSetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeAssociationCompleteIndHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeAssociationStartIndHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeBlacklistCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCalibrationDataGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCalibrationDataSetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCcxConfigGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCcxConfigSetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCoexConfigGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCoexConfigSetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCoexInfoGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeConnectCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeConnectionConfigGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeConnectionInfoGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeConnectionQualityIndHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeConnectionStatsGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeDeactivateCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeDisconnectCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeEventMaskSetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeHostConfigGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeHostConfigSetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeIbssStationIndHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeKeyCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeLinkQualityGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeMediaStatusIndHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeMibConfigGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeMibConfigSetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeMibGetCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeMibGetNextCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeMibSetCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeMicFailureIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeMulticastAddressCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmePacketFilterSetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmePermanentMacAddressGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmePmkidCandidateListIndHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmePmkidCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmePowerConfigGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmePowerConfigSetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeRegulatoryDomainInfoGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeRoamCompleteIndHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeRoamStartIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeRoamingConfigGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeRoamingConfigSetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeScanConfigGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeScanConfigSetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeScanFullCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeScanResultIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeScanResultsFlushCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeScanResultsGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeSmeStaConfigGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeSmeStaConfigSetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeStationMacAddressGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeTspecIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeTspecCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeVersionsGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeWifiFlightmodeCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeWifiOffIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeWifiOffCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeWifiOnCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCloakedSsidsSetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCloakedSsidsGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeWifiOnIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeSmeCommonConfigGetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeSmeCommonConfigSetCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeGetInterfaceCapabilityCfmHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeErrorIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeInfoIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeCoreDumpIndHandler(void *drvpriv, CsrWifiFsmEvent *msg);
+extern void CsrWifiSmeAmpStatusChangeIndHandler(void *drvpriv,
+	CsrWifiFsmEvent *msg);
 
 #endif /* CSR_WIFI_ROUTER_SEF_CSR_WIFI_SME_H__ */
diff --git a/drivers/staging/csr/csr_wifi_sme_serialize.h b/drivers/staging/csr/csr_wifi_sme_serialize.h
index 4f3af0a..f852626 100644
--- a/drivers/staging/csr/csr_wifi_sme_serialize.h
+++ b/drivers/staging/csr/csr_wifi_sme_serialize.h
@@ -1,10 +1,10 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2012
-            All rights reserved and confidential information of CSR
+	(c) Cambridge Silicon Radio Limited 2012
+	All rights reserved and confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+	Refer to LICENSE.txt included with this source for details
+	on the license terms.
 
 *****************************************************************************/
 
@@ -16,10 +16,6 @@
 #include "csr_wifi_msgconv.h"
 #include "csr_wifi_sme_prim.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 extern void CsrWifiSmePfree(void *ptr);
 
 #define CsrWifiSmeActivateReqSer CsrWifiEventSer
@@ -32,13 +28,13 @@ extern void CsrWifiSmePfree(void *ptr);
 #define CsrWifiSmeAdhocConfigGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeAdhocConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeAdhocConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeAdhocConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeAdhocConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeAdhocConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeAdhocConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeAdhocConfigSetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeBlacklistReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeBlacklistReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeBlacklistReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeBlacklistReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeBlacklistReqSizeof(void *msg);
 extern void CsrWifiSmeBlacklistReqSerFree(void *msg);
 
@@ -47,8 +43,8 @@ extern void CsrWifiSmeBlacklistReqSerFree(void *msg);
 #define CsrWifiSmeCalibrationDataGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeCalibrationDataGetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeCalibrationDataSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeCalibrationDataSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCalibrationDataSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCalibrationDataSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCalibrationDataSetReqSizeof(void *msg);
 extern void CsrWifiSmeCalibrationDataSetReqSerFree(void *msg);
 
@@ -57,8 +53,8 @@ extern void CsrWifiSmeCalibrationDataSetReqSerFree(void *msg);
 #define CsrWifiSmeCcxConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeCcxConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeCcxConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeCcxConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCcxConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCcxConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCcxConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeCcxConfigSetReqSerFree CsrWifiSmePfree
 
@@ -67,8 +63,8 @@ extern size_t CsrWifiSmeCcxConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeCoexConfigGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeCoexConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeCoexConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeCoexConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCoexConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCoexConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCoexConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeCoexConfigSetReqSerFree CsrWifiSmePfree
 
@@ -77,8 +73,8 @@ extern size_t CsrWifiSmeCoexConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeCoexInfoGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeCoexInfoGetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeConnectReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeConnectReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeConnectReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeConnectReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeConnectReqSizeof(void *msg);
 extern void CsrWifiSmeConnectReqSerFree(void *msg);
 
@@ -117,13 +113,13 @@ extern void CsrWifiSmeConnectReqSerFree(void *msg);
 #define CsrWifiSmeHostConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeHostConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeHostConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeHostConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeHostConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeHostConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeHostConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeHostConfigSetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeKeyReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeKeyReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeKeyReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeKeyReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeKeyReqSizeof(void *msg);
 #define CsrWifiSmeKeyReqSerFree CsrWifiSmePfree
 
@@ -137,33 +133,33 @@ extern size_t CsrWifiSmeKeyReqSizeof(void *msg);
 #define CsrWifiSmeMibConfigGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeMibConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeMibConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeMibConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMibConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMibConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMibConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeMibConfigSetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeMibGetNextReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeMibGetNextReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMibGetNextReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMibGetNextReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMibGetNextReqSizeof(void *msg);
 extern void CsrWifiSmeMibGetNextReqSerFree(void *msg);
 
-extern u8* CsrWifiSmeMibGetReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeMibGetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMibGetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMibGetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMibGetReqSizeof(void *msg);
 extern void CsrWifiSmeMibGetReqSerFree(void *msg);
 
-extern u8* CsrWifiSmeMibSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeMibSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMibSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMibSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMibSetReqSizeof(void *msg);
 extern void CsrWifiSmeMibSetReqSerFree(void *msg);
 
-extern u8* CsrWifiSmeMulticastAddressReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeMulticastAddressReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMulticastAddressReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMulticastAddressReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMulticastAddressReqSizeof(void *msg);
 extern void CsrWifiSmeMulticastAddressReqSerFree(void *msg);
 
-extern u8* CsrWifiSmePacketFilterSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmePacketFilterSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmePacketFilterSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmePacketFilterSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmePacketFilterSetReqSizeof(void *msg);
 extern void CsrWifiSmePacketFilterSetReqSerFree(void *msg);
 
@@ -172,8 +168,8 @@ extern void CsrWifiSmePacketFilterSetReqSerFree(void *msg);
 #define CsrWifiSmePermanentMacAddressGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmePermanentMacAddressGetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmePmkidReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmePmkidReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmePmkidReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmePmkidReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmePmkidReqSizeof(void *msg);
 extern void CsrWifiSmePmkidReqSerFree(void *msg);
 
@@ -182,8 +178,8 @@ extern void CsrWifiSmePmkidReqSerFree(void *msg);
 #define CsrWifiSmePowerConfigGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmePowerConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmePowerConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmePowerConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmePowerConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmePowerConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmePowerConfigSetReqSizeof(void *msg);
 #define CsrWifiSmePowerConfigSetReqSerFree CsrWifiSmePfree
 
@@ -197,8 +193,8 @@ extern size_t CsrWifiSmePowerConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeRoamingConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeRoamingConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeRoamingConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeRoamingConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeRoamingConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeRoamingConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeRoamingConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeRoamingConfigSetReqSerFree CsrWifiSmePfree
 
@@ -207,13 +203,13 @@ extern size_t CsrWifiSmeRoamingConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeScanConfigGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeScanConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeScanConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeScanConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeScanConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeScanConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeScanConfigSetReqSizeof(void *msg);
 extern void CsrWifiSmeScanConfigSetReqSerFree(void *msg);
 
-extern u8* CsrWifiSmeScanFullReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeScanFullReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeScanFullReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeScanFullReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeScanFullReqSizeof(void *msg);
 extern void CsrWifiSmeScanFullReqSerFree(void *msg);
 
@@ -232,8 +228,8 @@ extern void CsrWifiSmeScanFullReqSerFree(void *msg);
 #define CsrWifiSmeSmeStaConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeSmeStaConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeSmeStaConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeSmeStaConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeSmeStaConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeSmeStaConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeSmeStaConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeSmeStaConfigSetReqSerFree CsrWifiSmePfree
 
@@ -242,8 +238,8 @@ extern size_t CsrWifiSmeSmeStaConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeStationMacAddressGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeStationMacAddressGetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeTspecReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeTspecReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeTspecReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeTspecReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeTspecReqSizeof(void *msg);
 extern void CsrWifiSmeTspecReqSerFree(void *msg);
 
@@ -252,8 +248,8 @@ extern void CsrWifiSmeTspecReqSerFree(void *msg);
 #define CsrWifiSmeVersionsGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeVersionsGetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeWifiFlightmodeReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeWifiFlightmodeReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeWifiFlightmodeReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeWifiFlightmodeReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeWifiFlightmodeReqSizeof(void *msg);
 extern void CsrWifiSmeWifiFlightmodeReqSerFree(void *msg);
 
@@ -262,13 +258,13 @@ extern void CsrWifiSmeWifiFlightmodeReqSerFree(void *msg);
 #define CsrWifiSmeWifiOffReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeWifiOffReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeWifiOnReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeWifiOnReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeWifiOnReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeWifiOnReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeWifiOnReqSizeof(void *msg);
 extern void CsrWifiSmeWifiOnReqSerFree(void *msg);
 
-extern u8* CsrWifiSmeCloakedSsidsSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeCloakedSsidsSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCloakedSsidsSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCloakedSsidsSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCloakedSsidsSetReqSizeof(void *msg);
 extern void CsrWifiSmeCloakedSsidsSetReqSerFree(void *msg);
 
@@ -282,8 +278,8 @@ extern void CsrWifiSmeCloakedSsidsSetReqSerFree(void *msg);
 #define CsrWifiSmeSmeCommonConfigGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeSmeCommonConfigGetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeSmeCommonConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeSmeCommonConfigSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeSmeCommonConfigSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeSmeCommonConfigSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeSmeCommonConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeSmeCommonConfigSetReqSerFree CsrWifiSmePfree
 
@@ -292,13 +288,13 @@ extern size_t CsrWifiSmeSmeCommonConfigSetReqSizeof(void *msg);
 #define CsrWifiSmeInterfaceCapabilityGetReqSizeof CsrWifiEventSizeof
 #define CsrWifiSmeInterfaceCapabilityGetReqSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeWpsConfigurationReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeWpsConfigurationReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeWpsConfigurationReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeWpsConfigurationReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeWpsConfigurationReqSizeof(void *msg);
 extern void CsrWifiSmeWpsConfigurationReqSerFree(void *msg);
 
-extern u8* CsrWifiSmeSetReqSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeSetReqDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeSetReqSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeSetReqDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeSetReqSizeof(void *msg);
 extern void CsrWifiSmeSetReqSerFree(void *msg);
 
@@ -307,8 +303,8 @@ extern void CsrWifiSmeSetReqSerFree(void *msg);
 #define CsrWifiSmeActivateCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeActivateCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeAdhocConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeAdhocConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeAdhocConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeAdhocConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeAdhocConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeAdhocConfigGetCfmSerFree CsrWifiSmePfree
 
@@ -317,23 +313,23 @@ extern size_t CsrWifiSmeAdhocConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeAdhocConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeAdhocConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeAssociationCompleteIndSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeAssociationCompleteIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeAssociationCompleteIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeAssociationCompleteIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeAssociationCompleteIndSizeof(void *msg);
 extern void CsrWifiSmeAssociationCompleteIndSerFree(void *msg);
 
-extern u8* CsrWifiSmeAssociationStartIndSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeAssociationStartIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeAssociationStartIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeAssociationStartIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeAssociationStartIndSizeof(void *msg);
 #define CsrWifiSmeAssociationStartIndSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeBlacklistCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeBlacklistCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeBlacklistCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeBlacklistCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeBlacklistCfmSizeof(void *msg);
 extern void CsrWifiSmeBlacklistCfmSerFree(void *msg);
 
-extern u8* CsrWifiSmeCalibrationDataGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeCalibrationDataGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCalibrationDataGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCalibrationDataGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCalibrationDataGetCfmSizeof(void *msg);
 extern void CsrWifiSmeCalibrationDataGetCfmSerFree(void *msg);
 
@@ -342,18 +338,18 @@ extern void CsrWifiSmeCalibrationDataGetCfmSerFree(void *msg);
 #define CsrWifiSmeCalibrationDataSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeCalibrationDataSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeCcxConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeCcxConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCcxConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCcxConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCcxConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeCcxConfigGetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeCcxConfigSetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeCcxConfigSetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCcxConfigSetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCcxConfigSetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCcxConfigSetCfmSizeof(void *msg);
 #define CsrWifiSmeCcxConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeCoexConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeCoexConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCoexConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCoexConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCoexConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeCoexConfigGetCfmSerFree CsrWifiSmePfree
 
@@ -362,33 +358,33 @@ extern size_t CsrWifiSmeCoexConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeCoexConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeCoexConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeCoexInfoGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeCoexInfoGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCoexInfoGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCoexInfoGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCoexInfoGetCfmSizeof(void *msg);
 #define CsrWifiSmeCoexInfoGetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeConnectCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeConnectCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeConnectCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeConnectCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeConnectCfmSizeof(void *msg);
 #define CsrWifiSmeConnectCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeConnectionConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeConnectionConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeConnectionConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeConnectionConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeConnectionConfigGetCfmSizeof(void *msg);
 extern void CsrWifiSmeConnectionConfigGetCfmSerFree(void *msg);
 
-extern u8* CsrWifiSmeConnectionInfoGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeConnectionInfoGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeConnectionInfoGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeConnectionInfoGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeConnectionInfoGetCfmSizeof(void *msg);
 extern void CsrWifiSmeConnectionInfoGetCfmSerFree(void *msg);
 
-extern u8* CsrWifiSmeConnectionQualityIndSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeConnectionQualityIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeConnectionQualityIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeConnectionQualityIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeConnectionQualityIndSizeof(void *msg);
 #define CsrWifiSmeConnectionQualityIndSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeConnectionStatsGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeConnectionStatsGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeConnectionStatsGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeConnectionStatsGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeConnectionStatsGetCfmSizeof(void *msg);
 #define CsrWifiSmeConnectionStatsGetCfmSerFree CsrWifiSmePfree
 
@@ -397,8 +393,8 @@ extern size_t CsrWifiSmeConnectionStatsGetCfmSizeof(void *msg);
 #define CsrWifiSmeDeactivateCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeDeactivateCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeDisconnectCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeDisconnectCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeDisconnectCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeDisconnectCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeDisconnectCfmSizeof(void *msg);
 #define CsrWifiSmeDisconnectCfmSerFree CsrWifiSmePfree
 
@@ -407,38 +403,38 @@ extern size_t CsrWifiSmeDisconnectCfmSizeof(void *msg);
 #define CsrWifiSmeEventMaskSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeEventMaskSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeHostConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeHostConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeHostConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeHostConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeHostConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeHostConfigGetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeHostConfigSetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeHostConfigSetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeHostConfigSetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeHostConfigSetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeHostConfigSetCfmSizeof(void *msg);
 #define CsrWifiSmeHostConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeIbssStationIndSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeIbssStationIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeIbssStationIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeIbssStationIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeIbssStationIndSizeof(void *msg);
 #define CsrWifiSmeIbssStationIndSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeKeyCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeKeyCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeKeyCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeKeyCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeKeyCfmSizeof(void *msg);
 #define CsrWifiSmeKeyCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeLinkQualityGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeLinkQualityGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeLinkQualityGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeLinkQualityGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeLinkQualityGetCfmSizeof(void *msg);
 #define CsrWifiSmeLinkQualityGetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeMediaStatusIndSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeMediaStatusIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMediaStatusIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMediaStatusIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMediaStatusIndSizeof(void *msg);
 extern void CsrWifiSmeMediaStatusIndSerFree(void *msg);
 
-extern u8* CsrWifiSmeMibConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeMibConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMibConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMibConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMibConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeMibConfigGetCfmSerFree CsrWifiSmePfree
 
@@ -447,13 +443,13 @@ extern size_t CsrWifiSmeMibConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeMibConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeMibConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeMibGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeMibGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMibGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMibGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMibGetCfmSizeof(void *msg);
 extern void CsrWifiSmeMibGetCfmSerFree(void *msg);
 
-extern u8* CsrWifiSmeMibGetNextCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeMibGetNextCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMibGetNextCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMibGetNextCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMibGetNextCfmSizeof(void *msg);
 extern void CsrWifiSmeMibGetNextCfmSerFree(void *msg);
 
@@ -462,38 +458,39 @@ extern void CsrWifiSmeMibGetNextCfmSerFree(void *msg);
 #define CsrWifiSmeMibSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeMibSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeMicFailureIndSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeMicFailureIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMicFailureIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMicFailureIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMicFailureIndSizeof(void *msg);
 #define CsrWifiSmeMicFailureIndSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeMulticastAddressCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeMulticastAddressCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeMulticastAddressCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeMulticastAddressCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeMulticastAddressCfmSizeof(void *msg);
 extern void CsrWifiSmeMulticastAddressCfmSerFree(void *msg);
 
-extern u8* CsrWifiSmePacketFilterSetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmePacketFilterSetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmePacketFilterSetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmePacketFilterSetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmePacketFilterSetCfmSizeof(void *msg);
 #define CsrWifiSmePacketFilterSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmePermanentMacAddressGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmePermanentMacAddressGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmePermanentMacAddressGetCfmSer(u8 *ptr, size_t *len,
+	void *msg);
+extern void *CsrWifiSmePermanentMacAddressGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmePermanentMacAddressGetCfmSizeof(void *msg);
 #define CsrWifiSmePermanentMacAddressGetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmePmkidCandidateListIndSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmePmkidCandidateListIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmePmkidCandidateListIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmePmkidCandidateListIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmePmkidCandidateListIndSizeof(void *msg);
 extern void CsrWifiSmePmkidCandidateListIndSerFree(void *msg);
 
-extern u8* CsrWifiSmePmkidCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmePmkidCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmePmkidCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmePmkidCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmePmkidCfmSizeof(void *msg);
 extern void CsrWifiSmePmkidCfmSerFree(void *msg);
 
-extern u8* CsrWifiSmePowerConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmePowerConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmePowerConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmePowerConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmePowerConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmePowerConfigGetCfmSerFree CsrWifiSmePfree
 
@@ -502,33 +499,34 @@ extern size_t CsrWifiSmePowerConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmePowerConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmePowerConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeRegulatoryDomainInfoGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeRegulatoryDomainInfoGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeRegulatoryDomainInfoGetCfmSer(u8 *ptr, size_t *len,
+	void *msg);
+extern void *CsrWifiSmeRegulatoryDomainInfoGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeRegulatoryDomainInfoGetCfmSizeof(void *msg);
 #define CsrWifiSmeRegulatoryDomainInfoGetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeRoamCompleteIndSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeRoamCompleteIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeRoamCompleteIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeRoamCompleteIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeRoamCompleteIndSizeof(void *msg);
 #define CsrWifiSmeRoamCompleteIndSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeRoamStartIndSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeRoamStartIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeRoamStartIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeRoamStartIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeRoamStartIndSizeof(void *msg);
 #define CsrWifiSmeRoamStartIndSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeRoamingConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeRoamingConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeRoamingConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeRoamingConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeRoamingConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeRoamingConfigGetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeRoamingConfigSetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeRoamingConfigSetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeRoamingConfigSetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeRoamingConfigSetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeRoamingConfigSetCfmSizeof(void *msg);
 #define CsrWifiSmeRoamingConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeScanConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeScanConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeScanConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeScanConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeScanConfigGetCfmSizeof(void *msg);
 extern void CsrWifiSmeScanConfigGetCfmSerFree(void *msg);
 
@@ -542,8 +540,8 @@ extern void CsrWifiSmeScanConfigGetCfmSerFree(void *msg);
 #define CsrWifiSmeScanFullCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeScanFullCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeScanResultIndSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeScanResultIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeScanResultIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeScanResultIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeScanResultIndSizeof(void *msg);
 extern void CsrWifiSmeScanResultIndSerFree(void *msg);
 
@@ -552,38 +550,39 @@ extern void CsrWifiSmeScanResultIndSerFree(void *msg);
 #define CsrWifiSmeScanResultsFlushCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeScanResultsFlushCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeScanResultsGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeScanResultsGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeScanResultsGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeScanResultsGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeScanResultsGetCfmSizeof(void *msg);
 extern void CsrWifiSmeScanResultsGetCfmSerFree(void *msg);
 
-extern u8* CsrWifiSmeSmeStaConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeSmeStaConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeSmeStaConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeSmeStaConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeSmeStaConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeSmeStaConfigGetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeSmeStaConfigSetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeSmeStaConfigSetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeSmeStaConfigSetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeSmeStaConfigSetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeSmeStaConfigSetCfmSizeof(void *msg);
 #define CsrWifiSmeSmeStaConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeStationMacAddressGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeStationMacAddressGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeStationMacAddressGetCfmSer(u8 *ptr, size_t *len,
+	void *msg);
+extern void *CsrWifiSmeStationMacAddressGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeStationMacAddressGetCfmSizeof(void *msg);
 #define CsrWifiSmeStationMacAddressGetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeTspecIndSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeTspecIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeTspecIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeTspecIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeTspecIndSizeof(void *msg);
 extern void CsrWifiSmeTspecIndSerFree(void *msg);
 
-extern u8* CsrWifiSmeTspecCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeTspecCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeTspecCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeTspecCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeTspecCfmSizeof(void *msg);
 extern void CsrWifiSmeTspecCfmSerFree(void *msg);
 
-extern u8* CsrWifiSmeVersionsGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeVersionsGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeVersionsGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeVersionsGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeVersionsGetCfmSizeof(void *msg);
 extern void CsrWifiSmeVersionsGetCfmSerFree(void *msg);
 
@@ -612,18 +611,18 @@ extern void CsrWifiSmeVersionsGetCfmSerFree(void *msg);
 #define CsrWifiSmeCloakedSsidsSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeCloakedSsidsSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeCloakedSsidsGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeCloakedSsidsGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCloakedSsidsGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCloakedSsidsGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCloakedSsidsGetCfmSizeof(void *msg);
 extern void CsrWifiSmeCloakedSsidsGetCfmSerFree(void *msg);
 
-extern u8* CsrWifiSmeWifiOnIndSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeWifiOnIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeWifiOnIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeWifiOnIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeWifiOnIndSizeof(void *msg);
 #define CsrWifiSmeWifiOnIndSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeSmeCommonConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeSmeCommonConfigGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeSmeCommonConfigGetCfmSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeSmeCommonConfigGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeSmeCommonConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeSmeCommonConfigGetCfmSerFree CsrWifiSmePfree
 
@@ -632,23 +631,24 @@ extern size_t CsrWifiSmeSmeCommonConfigGetCfmSizeof(void *msg);
 #define CsrWifiSmeSmeCommonConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeSmeCommonConfigSetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeInterfaceCapabilityGetCfmSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeInterfaceCapabilityGetCfmDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeInterfaceCapabilityGetCfmSer(u8 *ptr, size_t *len,
+	void *msg);
+extern void *CsrWifiSmeInterfaceCapabilityGetCfmDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeInterfaceCapabilityGetCfmSizeof(void *msg);
 #define CsrWifiSmeInterfaceCapabilityGetCfmSerFree CsrWifiSmePfree
 
-extern u8* CsrWifiSmeErrorIndSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeErrorIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeErrorIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeErrorIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeErrorIndSizeof(void *msg);
 extern void CsrWifiSmeErrorIndSerFree(void *msg);
 
-extern u8* CsrWifiSmeInfoIndSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeInfoIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeInfoIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeInfoIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeInfoIndSizeof(void *msg);
 extern void CsrWifiSmeInfoIndSerFree(void *msg);
 
-extern u8* CsrWifiSmeCoreDumpIndSer(u8 *ptr, size_t *len, void *msg);
-extern void* CsrWifiSmeCoreDumpIndDes(u8 *buffer, size_t len);
+extern u8 *CsrWifiSmeCoreDumpIndSer(u8 *ptr, size_t *len, void *msg);
+extern void *CsrWifiSmeCoreDumpIndDes(u8 *buffer, size_t len);
 extern size_t CsrWifiSmeCoreDumpIndSizeof(void *msg);
 extern void CsrWifiSmeCoreDumpIndSerFree(void *msg);
 
@@ -662,9 +662,5 @@ extern void CsrWifiSmeCoreDumpIndSerFree(void *msg);
 #define CsrWifiSmeWpsConfigurationCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeWpsConfigurationCfmSerFree CsrWifiSmePfree
 
-
-#ifdef __cplusplus
-}
-#endif
 #endif /* CSR_WIFI_SME_SERIALIZE_H__ */
 
diff --git a/drivers/staging/csr/csr_wifi_sme_task.h b/drivers/staging/csr/csr_wifi_sme_task.h
index 0f725e4..1e938c1 100644
--- a/drivers/staging/csr/csr_wifi_sme_task.h
+++ b/drivers/staging/csr/csr_wifi_sme_task.h
@@ -1,10 +1,10 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
-            All rights reserved and confidential information of CSR
+	(c) Cambridge Silicon Radio Limited 2011
+	All rights reserved and confidential information of CSR
 
-            Refer to LICENSE.txt included with this source for details
-            on the license terms.
+	Refer to LICENSE.txt included with this source for details
+	on the license terms.
 
 *****************************************************************************/
 
@@ -15,19 +15,11 @@
 
 #include "csr_sched.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define CSR_WIFI_SME_LOG_ID 0x1202FFFF
 extern CsrSchedQid CSR_WIFI_SME_IFACEQUEUE;
 void CsrWifiSmeInit(void **gash);
 void CsrWifiSmeDeinit(void **gash);
 void CsrWifiSmeHandler(void **gash);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_SME_TASK_H__ */
 
diff --git a/drivers/staging/csr/csr_wifi_vif_utils.h b/drivers/staging/csr/csr_wifi_vif_utils.h
index 523172d..8ff9788 100644
--- a/drivers/staging/csr/csr_wifi_vif_utils.h
+++ b/drivers/staging/csr/csr_wifi_vif_utils.h
@@ -11,10 +11,6 @@
 #ifndef CSR_WIFI_VIF_UTILS_H
 #define CSR_WIFI_VIF_UTILS_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* STANDARD INCLUDES ********************************************************/
 
 /* PROJECT INCLUDES *********************************************************/
@@ -27,82 +23,5 @@ extern "C" {
 #define CSR_WIFI_NUM_INTERFACES        (u8)0x1
 #define CSR_WIFI_INTERFACE_IN_USE      (u16)0x0
 
-/* This is used at places where interface Id isn't available*/
-#define CSR_WIFI_INTERFACE_ZERO        0
-#define CSR_WIFI_INTERFACE_STA         0
-#define CSR_WIFI_INTERFACE_AMP         0
-
-
-#define CSR_WIFI_VIF_UTILS_UNDEFINED_TAG 0xFFFF
-
-/* Extract the Interface Id from the event */
-#define CsrWifiVifUtilsGetVifTagFromEvent(msg) \
-    ((u16) * ((u16 *) ((u8 *) (msg) + sizeof(CsrWifiFsmEvent))))
-
-/* The HPI Vif combines the type and the interface id */
-#define CsrWifiVifUtilsGetVifTagFromHipEvent(msg) \
-    ((msg)->virtualInterfaceIdentifier & 0x00FF)
-
-#define CsrWifiVifUtilsPackHipEventVif(type, interfaceId) \
-    ((u16)((interfaceId) | ((type) << 8)))
-
-
-/* TYPES DEFINITIONS ********************************************************/
-
-/* GLOBAL VARIABLE DECLARATIONS *********************************************/
-
-/* PUBLIC FUNCTION PROTOTYPES ***********************************************/
-
-/**
- * @brief
- *     First checks if the mode is supported capability bitmap of the interface.
- *     If this succeeds, then checks if running this mode on this interface is allowed.
- *
- * @param[in] u8 : interface capability bitmap
- * @param[in] u8* : pointer to the array of current interface modes
- * @param[in] u16 : interfaceTag
- * @param[in] CsrWifiInterfaceMode : mode
- *
- * @return
- *     u8 : returns true if the interface is allowed to operate in the mode otherwise false.
- */
-extern u8 CsrWifiVifUtilsCheckCompatibility(u8             interfaceCapability,
-                                                 u8            *currentInterfaceModes,
-                                                 u16            interfaceTag,
-                                                 CsrWifiInterfaceMode mode);
-
-/**
- * @brief
- *     Checks if the specified interface is supported.
- *     NOTE: Only checks that the interface is supported, no checks are made to
- *     determine whether a supported interface may be made active.
- *
- * @param[in] u16 : interfaceTag
- *
- * @return
- *     u8 : returns true if the interface is supported, otherwise false.
- */
-extern u8 CsrWifiVifUtilsIsSupported(u16 interfaceTag);
-
-#ifdef CSR_LOG_ENABLE
-/**
- * @brief
- *     Registers the virtual interface utils logging details.
- *     Should only be called once at initialisation.
- *
- * @param[in/out] None
- *
- * @return
- *     None
- */
-void CsrWifiVifUtilsLogTextRegister(void);
-#else
-#define CsrWifiVifUtilsLogTextRegister()
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* CSR_WIFI_VIF_UTILS_H */
 
diff --git a/drivers/staging/csr/data_tx.c b/drivers/staging/csr/data_tx.c
index 8ed7a78..9e3d8b8 100644
--- a/drivers/staging/csr/data_tx.c
+++ b/drivers/staging/csr/data_tx.c
@@ -18,33 +18,30 @@
 int
 uf_verify_m4(unifi_priv_t *priv, const unsigned char *packet, unsigned int length)
 {
-    const unsigned char *p = packet;
-    u16 keyinfo;
+	const unsigned char *p = packet;
+	u16 keyinfo;
 
 
-    if (length < (4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 1 + 8)) {
-        return 1;
-    }
+	if (length < (4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 1 + 8))
+		return 1;
 
-    p += 8;
-    keyinfo = p[5] << 8 | p[6]; /* big-endian */
-    if (
-          (p[0] == 1 || p[0] == 2) /* protocol version 802.1X-2001 (WPA) or -2004 (WPA2) */ &&
-          p[1] == 3 /* EAPOL-Key */ &&
-          /* don't bother checking p[2] p[3] (hh ll, packet body length) */
-          (p[4] == 254 || p[4] == 2) /* descriptor type P802.1i-D3.0 (WPA) or 802.11i-2004 (WPA2) */ &&
-          ((keyinfo & 0x0007) == 1 || (keyinfo & 0x0007) == 2) /* key descriptor version */ &&
-         (keyinfo & ~0x0207U) == 0x0108 && /* key info for 4/4 or 4/2 -- ignore key desc version and sec bit (since varies in WPA 4/4) */
-          (p[4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 0] == 0 && /* key data length (2 octets) 0 for 4/4 only */
-           p[4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 1] == 0)
-        ) {
-        unifi_trace(priv, UDBG1, "uf_verify_m4: M4 detected \n");
-        return 0;
-    }
-    else
-    {
-        return 1;
-    }
+	p += 8;
+	keyinfo = p[5] << 8 | p[6]; /* big-endian */
+	if (
+	  (p[0] == 1 || p[0] == 2) /* protocol version 802.1X-2001 (WPA) or -2004 (WPA2) */ &&
+	  p[1] == 3 /* EAPOL-Key */ &&
+	  /* don't bother checking p[2] p[3] (hh ll, packet body length) */
+	  (p[4] == 254 || p[4] == 2) /* descriptor type P802.1i-D3.0 (WPA) or 802.11i-2004 (WPA2) */ &&
+	  ((keyinfo & 0x0007) == 1 || (keyinfo & 0x0007) == 2) /* key descriptor version */ &&
+	 (keyinfo & ~0x0207U) == 0x0108 && /* key info for 4/4 or 4/2 -- ignore key desc version and sec bit (since varies in WPA 4/4) */
+	  (p[4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 0] == 0 && /* key data length (2 octets) 0 for 4/4 only */
+	   p[4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 1] == 0)
+	) {
+		unifi_trace(priv, UDBG1, "uf_verify_m4: M4 detected\n");
+		return 0;
+	} else {
+		return 1;
+	}
 }
 
 /*
diff --git a/drivers/staging/csr/drv.c b/drivers/staging/csr/drv.c
index 2497580..4780c32 100644
--- a/drivers/staging/csr/drv.c
+++ b/drivers/staging/csr/drv.c
@@ -166,33 +166,32 @@ s32 CsrHipResultToStatus(CsrResult csrResult)
 static const char*
 trace_putest_cmdid(unifi_putest_command_t putest_cmd)
 {
-    switch (putest_cmd)
-    {
-        case UNIFI_PUTEST_START:
-            return "START";
-        case UNIFI_PUTEST_STOP:
-            return "STOP";
-        case UNIFI_PUTEST_SET_SDIO_CLOCK:
-            return "SET CLOCK";
-        case UNIFI_PUTEST_CMD52_READ:
-            return "CMD52R";
-        case UNIFI_PUTEST_CMD52_BLOCK_READ:
-            return "CMD52BR";
-        case UNIFI_PUTEST_CMD52_WRITE:
-            return "CMD52W";
-        case UNIFI_PUTEST_DL_FW:
-            return "D/L FW";
-        case UNIFI_PUTEST_DL_FW_BUFF:
-            return "D/L FW BUFFER";
-        case UNIFI_PUTEST_COREDUMP_PREPARE:
-            return "PREPARE COREDUMP";
-        case UNIFI_PUTEST_GP_READ16:
-            return "GP16R";
-        case UNIFI_PUTEST_GP_WRITE16:
-            return "GP16W";
-        default:
-            return "ERROR: unrecognised command";
-    }
+	switch (putest_cmd) {
+	case UNIFI_PUTEST_START:
+		return "START";
+	case UNIFI_PUTEST_STOP:
+		return "STOP";
+	case UNIFI_PUTEST_SET_SDIO_CLOCK:
+		return "SET CLOCK";
+	case UNIFI_PUTEST_CMD52_READ:
+		return "CMD52R";
+	case UNIFI_PUTEST_CMD52_BLOCK_READ:
+		return "CMD52BR";
+	case UNIFI_PUTEST_CMD52_WRITE:
+		return "CMD52W";
+	case UNIFI_PUTEST_DL_FW:
+		return "D/L FW";
+	case UNIFI_PUTEST_DL_FW_BUFF:
+		return "D/L FW BUFFER";
+	case UNIFI_PUTEST_COREDUMP_PREPARE:
+		return "PREPARE COREDUMP";
+	case UNIFI_PUTEST_GP_READ16:
+		return "GP16R";
+	case UNIFI_PUTEST_GP_WRITE16:
+		return "GP16W";
+	default:
+		return "ERROR: unrecognised command";
+	}
  }
 
 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
@@ -266,8 +265,6 @@ unifi_open(struct inode *inode, struct file *file)
     unifi_priv_t *priv;
     ul_client_t *udi_cli;
 
-    func_enter();
-
     devno = MINOR(inode->i_rdev) >> 1;
 
     /*
@@ -278,7 +275,6 @@ unifi_open(struct inode *inode, struct file *file)
     priv = uf_get_instance(devno);
     if (priv == NULL) {
         unifi_error(NULL, "unifi_open: No device present\n");
-        func_exit();
         return -ENODEV;
     }
 
@@ -290,7 +286,6 @@ unifi_open(struct inode *inode, struct file *file)
             /* Too many clients already using this device */
             unifi_error(priv, "Too many clients already open\n");
             uf_put_instance(devno);
-            func_exit();
             return -ENOSPC;
         }
         unifi_trace(priv, UDBG1, "Client is registered to /dev/unifiudi%d\n", devno);
@@ -310,7 +305,6 @@ unifi_open(struct inode *inode, struct file *file)
             uf_put_instance(devno);
 
             unifi_info(priv, "There is already a configuration client using the character device\n");
-            func_exit();
             return -EBUSY;
         }
 #endif /* CSR_SME_USERSPACE */
@@ -331,7 +325,6 @@ unifi_open(struct inode *inode, struct file *file)
             uf_put_instance(devno);
 
             unifi_error(priv, "Too many clients already open\n");
-            func_exit();
             return -ENOSPC;
         }
 
@@ -357,7 +350,6 @@ unifi_open(struct inode *inode, struct file *file)
      */
     file->private_data = udi_cli;
 
-    func_exit();
     return 0;
 } /* unifi_open() */
 
@@ -369,8 +361,6 @@ unifi_release(struct inode *inode, struct file *filp)
     int devno;
     unifi_priv_t *priv;
 
-    func_enter();
-
     priv = uf_find_instance(udi_cli->instance);
     if (!priv) {
         unifi_error(priv, "unifi_close: instance for device not found\n");
@@ -465,8 +455,6 @@ unifi_read(struct file *filp, char *p, size_t len, loff_t *poff)
     struct list_head *l;
     int msglen;
 
-    func_enter();
-
     priv = uf_find_instance(pcli->instance);
     if (!priv) {
         unifi_error(priv, "invalid priv\n");
@@ -527,7 +515,6 @@ unifi_read(struct file *filp, char *p, size_t len, loff_t *poff)
     /* It is our resposibility to free the message buffer. */
     kfree(logptr);
 
-    func_exit_r(msglen);
     return msglen;
 
 } /* unifi_read() */
@@ -615,7 +602,6 @@ udi_send_signal_unpacked(unifi_priv_t *priv, unsigned char* data, uint data_len)
                 unifi_net_data_free(priv, &bulk_data.d[i]);
             }
         }
-        func_exit();
         return -EIO;
     }
 
@@ -654,8 +640,6 @@ udi_send_signal_raw(unifi_priv_t *priv, unsigned char *buf, int buflen)
     int bytecount;
     CsrResult csrResult;
 
-    func_enter();
-
     /*
      * The signal is the first thing in buf, the signal id is the
      * first 16 bits of the signal.
@@ -668,7 +652,6 @@ udi_send_signal_raw(unifi_priv_t *priv, unsigned char *buf, int buflen)
     if ((signal_size <= 0) || (signal_size > buflen)) {
         unifi_error(priv, "udi_send_signal_raw - Couldn't find length of signal 0x%x\n",
                     sig_id);
-        func_exit();
         return -EINVAL;
     }
     unifi_trace(priv, UDBG2, "udi_send_signal_raw: signal 0x%.4X len:%d\n",
@@ -713,7 +696,6 @@ udi_send_signal_raw(unifi_priv_t *priv, unsigned char *buf, int buflen)
 
     if (bytecount > buflen) {
         unifi_error(priv, "udi_send_signal_raw: Not enough data (%d instead of %d)\n", buflen, bytecount);
-        func_exit();
         return -EINVAL;
     }
 
@@ -721,7 +703,6 @@ udi_send_signal_raw(unifi_priv_t *priv, unsigned char *buf, int buflen)
     r = ul_send_signal_raw(priv, buf, signal_size, &data_ptrs);
     if (r < 0) {
         unifi_error(priv, "udi_send_signal_raw: send failed (%d)\n", r);
-        func_exit();
         return -EIO;
     }
 
@@ -746,8 +727,6 @@ udi_send_signal_raw(unifi_priv_t *priv, unsigned char *buf, int buflen)
     }
 #endif
 
-    func_exit_r(bytecount);
-
     return bytecount;
 } /* udi_send_signal_raw */
 
@@ -784,8 +763,6 @@ unifi_write(struct file *filp, const char *p, size_t len, loff_t *poff)
     bulk_data_param_t bulkdata;
     CsrResult csrResult;
 
-    func_enter();
-
     priv = uf_find_instance(pcli->instance);
     if (!priv) {
         unifi_error(priv, "invalid priv\n");
@@ -812,7 +789,6 @@ unifi_write(struct file *filp, const char *p, size_t len, loff_t *poff)
         csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], len);
         if (csrResult != CSR_RESULT_SUCCESS) {
             unifi_error(priv, "unifi_write: failed to allocate request_data.\n");
-            func_exit();
             return -ENOMEM;
         }
 
@@ -822,7 +798,6 @@ unifi_write(struct file *filp, const char *p, size_t len, loff_t *poff)
         if (copy_from_user((void*)user_data_buf, p, len)) {
             unifi_error(priv, "unifi_write: copy from user failed\n");
             unifi_net_data_free(priv, &bulkdata.d[0]);
-            func_exit();
             return -EFAULT;
         }
 
@@ -838,7 +813,6 @@ unifi_write(struct file *filp, const char *p, size_t len, loff_t *poff)
             unifi_error(priv, "unifi_write - Couldn't find length of signal 0x%x\n",
                         sig_id);
             unifi_net_data_free(priv, &bulkdata.d[0]);
-            func_exit();
             return -EINVAL;
         }
 
@@ -849,7 +823,6 @@ unifi_write(struct file *filp, const char *p, size_t len, loff_t *poff)
         signal_buf = kmalloc(signal_size, GFP_KERNEL);
         if (!signal_buf) {
             unifi_net_data_free(priv, &bulkdata.d[0]);
-            func_exit();
             return -ENOMEM;
         }
 
@@ -948,8 +921,6 @@ unifi_write(struct file *filp, const char *p, size_t len, loff_t *poff)
 
     kfree(buf);
 
-    func_exit_r(bytes_written);
-
     return bytes_written;
 } /* unifi_write() */
 
@@ -1657,8 +1628,6 @@ unifi_poll(struct file *filp, poll_table *wait)
     unsigned int mask = 0;
     int ready;
 
-    func_enter();
-
     ready = !list_empty(&pcli->udi_log);
 
     poll_wait(filp, &pcli->udi_wq, wait);
@@ -1667,8 +1636,6 @@ unifi_poll(struct file *filp, poll_table *wait)
         mask |= POLLIN | POLLRDNORM;    /* readable */
     }
 
-    func_exit();
-
     return mask;
 } /* unifi_poll() */
 
@@ -1784,8 +1751,6 @@ udi_log_event(ul_client_t *pcli,
     unsigned long n_1000;
 #endif
 
-    func_enter();
-
     /* Just a sanity check */
     if ((signal == NULL) || (signal_len <= 0)) {
         return;
@@ -1901,7 +1866,6 @@ udi_log_event(ul_client_t *pcli,
     if (down_interruptible(&pcli->udi_sem)) {
         printk(KERN_WARNING "udi_log_event_q: Failed to get udi sem\n");
         kfree(logptr);
-        func_exit();
         return;
     }
     list_add_tail(&logptr->q, &pcli->udi_log);
@@ -1910,7 +1874,6 @@ udi_log_event(ul_client_t *pcli,
     /* Wake any waiting user process */
     wake_up_interruptible(&pcli->udi_wq);
 
-    func_exit();
 } /* udi_log_event() */
 
 #ifdef CSR_SME_USERSPACE
@@ -1921,8 +1884,6 @@ uf_sme_queue_message(unifi_priv_t *priv, u8 *buffer, int length)
     udi_msg_t *msgptr;
     u8 *p;
 
-    func_enter();
-
     /* Just a sanity check */
     if ((buffer == NULL) || (length <= 0)) {
         return -EINVAL;
@@ -1968,8 +1929,6 @@ uf_sme_queue_message(unifi_priv_t *priv, u8 *buffer, int length)
     /* It is our responsibility to free the buffer allocated in build_packed_*() */
     kfree(buffer);
 
-    func_exit();
-
     return 0;
 
 } /* uf_sme_queue_message() */
@@ -2059,10 +2018,10 @@ int uf_create_device_nodes(unifi_priv_t *priv, int bus_id)
 
 void uf_destroy_device_nodes(unifi_priv_t *priv)
 {
-    device_destroy(unifi_class, priv->unifiudi_cdev.dev);
-    device_destroy(unifi_class, priv->unifi_cdev.dev);
-    cdev_del(&priv->unifiudi_cdev);
-    cdev_del(&priv->unifi_cdev);
+	device_destroy(unifi_class, priv->unifiudi_cdev.dev);
+	device_destroy(unifi_class, priv->unifi_cdev.dev);
+	cdev_del(&priv->unifiudi_cdev);
+	cdev_del(&priv->unifi_cdev);
 }
 
 
diff --git a/drivers/staging/csr/firmware.c b/drivers/staging/csr/firmware.c
index b6d8a6e..b42a4d6 100644
--- a/drivers/staging/csr/firmware.c
+++ b/drivers/staging/csr/firmware.c
@@ -62,8 +62,6 @@ unifi_fw_read_start(void *ospriv, s8 is_fw, const card_info_t *info)
     unifi_priv_t *priv = (unifi_priv_t*)ospriv;
     CSR_UNUSED(info);
 
-    func_enter();
-
     if (is_fw == UNIFI_FW_STA) {
         /* F/w may have been released after a previous successful download. */
         if (priv->fw_sta.dl_data == NULL) {
@@ -72,7 +70,6 @@ unifi_fw_read_start(void *ospriv, s8 is_fw, const card_info_t *info)
         }
         /* Set up callback struct for readfunc() */
         if (priv->fw_sta.dl_data != NULL) {
-            func_exit();
             return &priv->fw_sta;
         }
 
@@ -80,7 +77,6 @@ unifi_fw_read_start(void *ospriv, s8 is_fw, const card_info_t *info)
         unifi_error(priv, "downloading firmware... unknown request: %d\n", is_fw);
     }
 
-    func_exit();
     return NULL;
 } /* unifi_fw_read_start() */
 
@@ -105,7 +101,6 @@ unifi_fw_read_stop(void *ospriv, void *dlpriv)
 {
     unifi_priv_t *priv = (unifi_priv_t*)ospriv;
     struct dlpriv *dl_struct = (struct dlpriv *)dlpriv;
-    func_enter();
 
     if (dl_struct != NULL) {
         if (dl_struct->dl_data != NULL) {
@@ -115,7 +110,6 @@ unifi_fw_read_stop(void *ospriv, void *dlpriv)
         uf_release_firmware(priv, dl_struct);
     }
 
-    func_exit();
 } /* unifi_fw_read_stop() */
 
 
@@ -143,17 +137,14 @@ void *
 unifi_fw_open_buffer(void *ospriv, void *fwbuf, u32 len)
 {
     unifi_priv_t *priv = (unifi_priv_t*)ospriv;
-    func_enter();
 
     if (fwbuf == NULL) {
-        func_exit();
         return NULL;
     }
     priv->fw_conv.dl_data = fwbuf;
     priv->fw_conv.dl_len = len;
     priv->fw_conv.fw_desc = NULL;   /* No OS f/w resource is associated */
 
-    func_exit();
     return &priv->fw_conv;
 }
 
@@ -242,8 +233,6 @@ unifi_fw_read(void *ospriv, void *arg, u32 offset, void *buf, u32 len)
 int
 uf_run_unifihelper(unifi_priv_t *priv)
 {
-#ifdef CONFIG_HOTPLUG
-
 #ifdef ANDROID_BUILD
     char *prog = "/system/bin/unififw";
 #else
@@ -289,10 +278,6 @@ uf_run_unifihelper(unifi_priv_t *priv)
     r = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
 
     return r;
-#else
-    unifi_trace(priv, UDBG1, "Can't automatically download firmware because kernel does not have HOTPLUG\n");
-    return -1;
-#endif
 } /* uf_run_unifihelper() */
 
 #ifdef CSR_WIFI_SPLIT_PATCH
diff --git a/drivers/staging/csr/inet.c b/drivers/staging/csr/inet.c
index b4acb54..b3ef818 100644
--- a/drivers/staging/csr/inet.c
+++ b/drivers/staging/csr/inet.c
@@ -93,14 +93,12 @@ static struct notifier_block uf_inetaddr_notifier = {
 
 void uf_register_inet_notifier(void)
 {
-    if (atomic_inc_return(&inet_notif_refs) == 1) {
-        register_inetaddr_notifier(&uf_inetaddr_notifier);
-    }
+	if (atomic_inc_return(&inet_notif_refs) == 1)
+		register_inetaddr_notifier(&uf_inetaddr_notifier);
 }
 
 void uf_unregister_inet_notifier(void)
 {
-    if (atomic_dec_return(&inet_notif_refs) == 0) {
-        unregister_inetaddr_notifier(&uf_inetaddr_notifier);
-    }
+	if (atomic_dec_return(&inet_notif_refs) == 0)
+		unregister_inetaddr_notifier(&uf_inetaddr_notifier);
 }
diff --git a/drivers/staging/csr/io.c b/drivers/staging/csr/io.c
index caf48e3..af9c28f 100644
--- a/drivers/staging/csr/io.c
+++ b/drivers/staging/csr/io.c
@@ -31,7 +31,6 @@
  * ---------------------------------------------------------------------------
  */
 #include <linux/proc_fs.h>
-#include <linux/version.h>
 
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_unifiversion.h"
@@ -86,7 +85,6 @@ static int uf_read_proc(char *page, char **start, off_t offset, int count,
 static CsrResult signal_buffer_init(unifi_priv_t * priv, int size)
 {
     int i;
-    func_enter();
 
     priv->rxSignalBuffer.writePointer =
     priv->rxSignalBuffer.readPointer = 0;
@@ -106,11 +104,9 @@ static CsrResult signal_buffer_init(unifi_priv_t * priv, int size)
                  kfree(priv->rxSignalBuffer.rx_buff[j].bufptr);
                  priv->rxSignalBuffer.rx_buff[j].bufptr = NULL;
              }
-             func_exit();
              return -1;
          }
     }
-    func_exit();
     return 0;
 }
 
@@ -265,8 +261,6 @@ register_unifi_sdio(CsrSdioFunction *sdio_dev, int bus_id, struct device *dev)
     int r = -1;
     CsrResult csrResult;
 
-    func_enter();
-
     if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) {
         unifi_error(priv, "register_unifi_sdio: invalid device %d\n",
                 bus_id);
@@ -415,7 +409,6 @@ register_unifi_sdio(CsrSdioFunction *sdio_dev, int bus_id, struct device *dev)
 
     up(&Unifi_instance_mutex);
 
-    func_exit();
     return priv;
 
 failed4:
@@ -449,7 +442,6 @@ failed0:
 
     up(&Unifi_instance_mutex);
 
-    func_exit();
     return NULL;
 } /* register_unifi_sdio() */
 
@@ -473,7 +465,6 @@ failed0:
 static void
 ask_unifi_sdio_cleanup(unifi_priv_t *priv)
 {
-    func_enter();
 
     /*
      * Now clear the flag that says the old instance is in use.
@@ -486,8 +477,6 @@ ask_unifi_sdio_cleanup(unifi_priv_t *priv)
     unifi_trace(NULL, UDBG5, "ask_unifi_sdio_cleanup: wake up cleanup workqueue.\n");
     wake_up(&Unifi_cleanup_wq);
 
-    func_exit();
-
 } /* ask_unifi_sdio_cleanup() */
 
 
@@ -511,8 +500,6 @@ cleanup_unifi_sdio(unifi_priv_t *priv)
     int i;
     static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
 
-    func_enter();
-
     /* Remove the device nodes */
     uf_destroy_device_nodes(priv);
 
@@ -604,8 +591,6 @@ cleanup_unifi_sdio(unifi_priv_t *priv)
 
     unifi_trace(NULL, UDBG5, "cleanup_unifi_sdio: DONE.\n");
 
-    func_exit();
-
 } /* cleanup_unifi_sdio() */
 
 
@@ -639,7 +624,6 @@ unregister_unifi_sdio(int bus_id)
     if (priv == NULL) {
         unifi_error(priv, "unregister_unifi_sdio: device %d is not registered\n",
                 bus_id);
-        func_exit();
         return;
     }
 
@@ -1016,37 +1000,37 @@ uf_remove_os_device(int bus_id)
 static void
 uf_sdio_inserted(CsrSdioFunction *sdio_ctx)
 {
-    unifi_priv_t *priv;
+	unifi_priv_t *priv;
 
-    unifi_trace(NULL, UDBG5, "uf_sdio_inserted(0x%p), slot_id=%d, dev=%p\n",
-            sdio_ctx, active_slot, os_devices[active_slot]);
+	unifi_trace(NULL, UDBG5, "uf_sdio_inserted(0x%p), slot_id=%d, dev=%p\n",
+		      sdio_ctx, active_slot, os_devices[active_slot]);
 
-    priv = register_unifi_sdio(sdio_ctx, active_slot, os_devices[active_slot]);
-    if (priv == NULL) {
-        CsrSdioInsertedAcknowledge(sdio_ctx, CSR_RESULT_FAILURE);
-        return;
-    }
+	priv = register_unifi_sdio(sdio_ctx, active_slot, os_devices[active_slot]);
+	if (priv == NULL) {
+		CsrSdioInsertedAcknowledge(sdio_ctx, CSR_RESULT_FAILURE);
+		return;
+	}
 
-    sdio_ctx->driverData = priv;
+	sdio_ctx->driverData = priv;
 
-    CsrSdioInsertedAcknowledge(sdio_ctx, CSR_RESULT_SUCCESS);
+	CsrSdioInsertedAcknowledge(sdio_ctx, CSR_RESULT_SUCCESS);
 } /* uf_sdio_inserted() */
 
 
 static void
 uf_sdio_removed(CsrSdioFunction *sdio_ctx)
 {
-    unregister_unifi_sdio(active_slot);
-    CsrSdioRemovedAcknowledge(sdio_ctx);
+	unregister_unifi_sdio(active_slot);
+	CsrSdioRemovedAcknowledge(sdio_ctx);
 } /* uf_sdio_removed() */
 
 
 static void
 uf_sdio_dsr_handler(CsrSdioFunction *sdio_ctx)
 {
-    unifi_priv_t *priv = sdio_ctx->driverData;
+	unifi_priv_t *priv = sdio_ctx->driverData;
 
-    unifi_sdio_interrupt_handler(priv->card);
+	unifi_sdio_interrupt_handler(priv->card);
 } /* uf_sdio_dsr_handler() */
 
 /*
@@ -1068,7 +1052,7 @@ uf_sdio_dsr_handler(CsrSdioFunction *sdio_ctx)
 static CsrSdioInterruptDsrCallback
 uf_sdio_int_handler(CsrSdioFunction *sdio_ctx)
 {
-    return uf_sdio_dsr_handler;
+	return uf_sdio_dsr_handler;
 } /* uf_sdio_int_handler() */
 
 
@@ -1076,18 +1060,18 @@ uf_sdio_int_handler(CsrSdioFunction *sdio_ctx)
 
 static CsrSdioFunctionId unifi_ids[] =
 {
-    {
-        .manfId = SDIO_MANF_ID_CSR,
-        .cardId = SDIO_CARD_ID_UNIFI_3,
-        .sdioFunction = SDIO_WLAN_FUNC_ID_UNIFI_3,
-        .sdioInterface = CSR_SDIO_ANY_SDIO_INTERFACE,
-    },
-    {
-        .manfId = SDIO_MANF_ID_CSR,
-        .cardId = SDIO_CARD_ID_UNIFI_4,
-        .sdioFunction = SDIO_WLAN_FUNC_ID_UNIFI_4,
-        .sdioInterface = CSR_SDIO_ANY_SDIO_INTERFACE,
-    }
+	{
+		.manfId = SDIO_MANF_ID_CSR,
+		.cardId = SDIO_CARD_ID_UNIFI_3,
+		.sdioFunction = SDIO_WLAN_FUNC_ID_UNIFI_3,
+		.sdioInterface = CSR_SDIO_ANY_SDIO_INTERFACE,
+	},
+	{
+		.manfId = SDIO_MANF_ID_CSR,
+		.cardId = SDIO_CARD_ID_UNIFI_4,
+		.sdioFunction = SDIO_WLAN_FUNC_ID_UNIFI_4,
+		.sdioInterface = CSR_SDIO_ANY_SDIO_INTERFACE,
+	}
 };
 
 
@@ -1096,14 +1080,14 @@ static CsrSdioFunctionId unifi_ids[] =
  */
 static CsrSdioFunctionDriver unifi_sdioFunction_drv =
 {
-    .inserted = uf_sdio_inserted,
-    .removed = uf_sdio_removed,
-    .intr = uf_sdio_int_handler,
-    .suspend = uf_lx_suspend,
-    .resume = uf_lx_resume,
-
-    .ids = unifi_ids,
-    .idsCount = sizeof(unifi_ids) / sizeof(unifi_ids[0])
+	.inserted = uf_sdio_inserted,
+	.removed = uf_sdio_removed,
+	.intr = uf_sdio_int_handler,
+	.suspend = uf_lx_suspend,
+	.resume = uf_lx_resume,
+
+	.ids = unifi_ids,
+	.idsCount = sizeof(unifi_ids) / sizeof(unifi_ids[0])
 };
 
 
@@ -1126,15 +1110,15 @@ static CsrSdioFunctionDriver unifi_sdioFunction_drv =
 int __init
 uf_sdio_load(void)
 {
-    CsrResult csrResult;
+	CsrResult csrResult;
 
-    csrResult = CsrSdioFunctionDriverRegister(&unifi_sdioFunction_drv);
-    if (csrResult != CSR_RESULT_SUCCESS) {
-        unifi_error(NULL, "Failed to register UniFi SDIO driver: csrResult=%d\n", csrResult);
-        return -EIO;
-    }
+	csrResult = CsrSdioFunctionDriverRegister(&unifi_sdioFunction_drv);
+	if (csrResult != CSR_RESULT_SUCCESS) {
+		unifi_error(NULL, "Failed to register UniFi SDIO driver: csrResult=%d\n", csrResult);
+		return -EIO;
+	}
 
-    return 0;
+	return 0;
 } /* uf_sdio_load() */
 
 
@@ -1142,6 +1126,6 @@ uf_sdio_load(void)
 void __exit
 uf_sdio_unload(void)
 {
-    CsrSdioFunctionDriverUnregister(&unifi_sdioFunction_drv);
+	CsrSdioFunctionDriverUnregister(&unifi_sdioFunction_drv);
 } /* uf_sdio_unload() */
 
diff --git a/drivers/staging/csr/mlme.c b/drivers/staging/csr/mlme.c
index ed767ec..861d6b7 100644
--- a/drivers/staging/csr/mlme.c
+++ b/drivers/staging/csr/mlme.c
@@ -154,8 +154,6 @@ unifi_mlme_blocking_request(unifi_priv_t *priv, ul_client_t *pcli,
 {
     int r;
 
-    func_enter();
-
     if (sig->SignalPrimitiveHeader.SignalId == 0) {
         unifi_error(priv, "unifi_mlme_blocking_request: Invalid Signal Id (0x%x)\n",
                     sig->SignalPrimitiveHeader.SignalId);
@@ -199,7 +197,6 @@ unifi_mlme_blocking_request(unifi_priv_t *priv, ul_client_t *pcli,
         return r;
     }
 
-    func_exit();
     return 0;
 } /* unifi_mlme_blocking_request() */
 
diff --git a/drivers/staging/csr/monitor.c b/drivers/staging/csr/monitor.c
index 7c524a1..c8e20e4 100644
--- a/drivers/staging/csr/monitor.c
+++ b/drivers/staging/csr/monitor.c
@@ -10,7 +10,6 @@
  * ---------------------------------------------------------------------------
  */
 
-#include <linux/version.h>
 #include "unifi_priv.h"
 
 #ifdef UNIFI_SNIFF_ARPHRD
@@ -122,8 +121,6 @@ netrx_radiotap(unifi_priv_t *priv,
     struct unifi_rx_radiotap_header *unifi_rt;
     int signal, noise, snr;
 
-    func_enter();
-
     if (ind_data_len <= 0) {
         unifi_error(priv, "Invalid length in CSR_MA_SNIFFDATA_INDICATION.\n");
         return;
@@ -205,7 +202,6 @@ netrx_radiotap(unifi_priv_t *priv,
     priv->stats.rx_packets++;
     priv->stats.rx_bytes += ind_data_len;
 
-    func_exit();
 } /* netrx_radiotap() */
 #endif /* RADIOTAP */
 
@@ -256,8 +252,6 @@ netrx_prism(unifi_priv_t *priv,
     } *avs;
     int signal, noise, snr;
 
-    func_enter();
-
     if (ind_data_len <= 0) {
         unifi_error(priv, "Invalid length in CSR_MA_SNIFFDATA_INDICATION.\n");
         return;
@@ -319,7 +313,6 @@ netrx_prism(unifi_priv_t *priv,
     priv->stats.rx_packets++;
     priv->stats.rx_bytes += ind_data_len;
 
-    func_exit();
 } /* netrx_prism() */
 #endif /* PRISM */
 
@@ -351,11 +344,8 @@ ma_sniffdata_ind(void *ospriv,
     struct net_device *dev = priv->netdev;
     struct sk_buff *skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr;
 
-    func_enter();
-
     if (bulkdata->d[0].data_length == 0) {
         unifi_warning(priv, "rx: MA-SNIFFDATA indication with zero bulk data\n");
-        func_exit();
         return;
     }
 
diff --git a/drivers/staging/csr/netdev.c b/drivers/staging/csr/netdev.c
index 9a52ab4..7dad26f 100644
--- a/drivers/staging/csr/netdev.c
+++ b/drivers/staging/csr/netdev.c
@@ -47,7 +47,6 @@
 #include <linux/etherdevice.h>
 #include <linux/mutex.h>
 #include <linux/semaphore.h>
-#include <linux/version.h>
 #include <linux/vmalloc.h>
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_conversions.h"
@@ -55,7 +54,7 @@
 #include <net/pkt_sched.h>
 
 
-/* Wext handler is suported only if CSR_SUPPORT_WEXT is defined */
+/* Wext handler is supported only if CSR_SUPPORT_WEXT is defined */
 #ifdef CSR_SUPPORT_WEXT
 extern struct iw_handler_def unifi_iw_handler_def;
 #endif /* CSR_SUPPORT_WEXT */
@@ -89,7 +88,7 @@ typedef int (*tx_signal_handler)(unifi_priv_t *priv, struct sk_buff *skb, const
 /*
  * The driver uses the qdisc interface to buffer and control all
  * outgoing traffic. We create a root qdisc, register our qdisc operations
- * and later we create two subsiduary pfifo queues for the uncontrolled
+ * and later we create two subsidiary pfifo queues for the uncontrolled
  * and controlled ports.
  *
  * The network stack delivers all outgoing packets in our enqueue handler.
@@ -478,8 +477,6 @@ uf_free_netdevice(unifi_priv_t *priv)
     int i;
     unsigned long flags;
 
-    func_enter();
-
     unifi_trace(priv, UDBG1, "uf_free_netdevice\n");
 
     if (!priv) {
@@ -554,7 +551,6 @@ uf_free_netdevice(unifi_priv_t *priv)
         }
     }
 
-    func_exit();
     return 0;
 } /* uf_free_netdevice() */
 
@@ -578,8 +574,6 @@ uf_net_open(struct net_device *dev)
     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
     unifi_priv_t *priv = interfacePriv->privPtr;
 
-    func_enter();
-
     /* If we haven't finished UniFi initialisation, we can't start */
     if (priv->init_progress != UNIFI_INIT_COMPLETED) {
         unifi_warning(priv, "%s: unifi not ready, failing net_open\n", __FUNCTION__);
@@ -615,7 +609,6 @@ uf_net_open(struct net_device *dev)
 
     netif_tx_start_all_queues(dev);
 
-    func_exit();
     return 0;
 } /* uf_net_open() */
 
@@ -627,8 +620,6 @@ uf_net_stop(struct net_device *dev)
     netInterface_priv_t *interfacePriv = (netInterface_priv_t*)netdev_priv(dev);
     unifi_priv_t *priv = interfacePriv->privPtr;
 
-    func_enter();
-
     /* Stop sniffing if in Monitor mode */
     if (priv->wext_conf.mode == IW_MODE_MONITOR) {
         if (priv->card) {
@@ -639,13 +630,10 @@ uf_net_stop(struct net_device *dev)
             }
         }
     }
-#else
-    func_enter();
 #endif
 
     netif_tx_stop_all_queues(dev);
 
-    func_exit();
     return 0;
 } /* uf_net_stop() */
 
@@ -675,7 +663,6 @@ static CSR_PRIORITY uf_get_packet_priority(unifi_priv_t *priv, netInterface_priv
 {
     CSR_PRIORITY priority = CSR_CONTENTION;
 
-    func_enter();
     priority = (CSR_PRIORITY) (skb->priority >> 5);
 
     if (priority == CSR_QOS_UP0) { /* 0 */
@@ -721,7 +708,6 @@ static CSR_PRIORITY uf_get_packet_priority(unifi_priv_t *priv, netInterface_priv
 
     unifi_trace(priv, UDBG5, "Packet priority = %d\n", priority);
 
-    func_exit();
     return priority;
 }
 
@@ -750,8 +736,6 @@ get_packet_priority(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr
 
     u8 interfaceMode = interfacePriv->interfaceMode;
 
-    func_enter();
-
     /* Priority Mapping for all the Modes */
     switch(interfaceMode)
     {
@@ -788,7 +772,6 @@ get_packet_priority(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr
     }
     unifi_trace(priv, UDBG5, "priority = %x\n", priority);
 
-    func_exit();
     return priority;
 }
 
@@ -816,8 +799,6 @@ uf_net_select_queue(struct net_device *dev, struct sk_buff *skb)
     int proto;
     CSR_PRIORITY priority;
 
-    func_enter();
-
     memcpy(&ehdr, skb->data, ETH_HLEN);
     proto = ntohs(ehdr.h_proto);
 
@@ -836,7 +817,6 @@ uf_net_select_queue(struct net_device *dev, struct sk_buff *skb)
     }
 
 
-    func_exit();
     return (u16)queue;
 } /* uf_net_select_queue() */
 
@@ -1582,7 +1562,7 @@ send_ma_pkt_request(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr
         return -1;
     }
 
-    /* RA adrress must contain the immediate destination MAC address that is similiar to
+    /* RA address must contain the immediate destination MAC address that is similar to
      * the Address 1 field of 802.11 Mac header here 4 is: (sizeof(framecontrol) + sizeof (durationID))
      * which is address 1 field
      */
@@ -1760,8 +1740,6 @@ uf_net_xmit(struct sk_buff *skb, struct net_device *dev)
     CSR_PRIORITY priority;
     CsrWifiRouterCtrlPortAction port_action;
 
-    func_enter();
-
     unifi_trace(priv, UDBG5, "unifi_net_xmit: skb = %x\n", skb);
 
     memcpy(&ehdr, skb->data, ETH_HLEN);
@@ -1805,7 +1783,6 @@ uf_net_xmit(struct sk_buff *skb, struct net_device *dev)
         interfacePriv->stats.tx_dropped++;
         kfree_skb(skb);
 
-        func_exit();
         return NETDEV_TX_OK;
     }
 
@@ -1848,7 +1825,6 @@ uf_net_xmit(struct sk_buff *skb, struct net_device *dev)
 
     /* The skb will have been freed by send_XXX_request() */
 
-    func_exit();
     return result;
 } /* uf_net_xmit() */
 
@@ -1877,7 +1853,6 @@ unifi_pause_xmit(void *ospriv, unifi_TrafficQueue queue)
     unifi_priv_t *priv = ospriv;
     int i; /* used as a loop counter */
 
-    func_enter();
     unifi_trace(priv, UDBG2, "Stopping queue %d\n", queue);
 
     for(i=0;i<CSR_WIFI_NUM_INTERFACES;i++)
@@ -1897,7 +1872,6 @@ unifi_pause_xmit(void *ospriv, unifi_TrafficQueue queue)
         unifi_error(priv, "Start buffering %d defaulting to 0\n", queue);
      }
 #endif
-    func_exit();
 
 } /* unifi_pause_xmit() */
 
@@ -1907,7 +1881,6 @@ unifi_restart_xmit(void *ospriv, unifi_TrafficQueue queue)
     unifi_priv_t *priv = ospriv;
     int i=0; /* used as a loop counter */
 
-    func_enter();
     unifi_trace(priv, UDBG2, "Waking queue %d\n", queue);
 
     for(i=0;i<CSR_WIFI_NUM_INTERFACES;i++)
@@ -1927,7 +1900,6 @@ unifi_restart_xmit(void *ospriv, unifi_TrafficQueue queue)
         uf_send_buffered_frames(priv,0);
     }
 #endif
-    func_exit();
 } /* unifi_restart_xmit() */
 
 
@@ -1963,7 +1935,6 @@ indicate_rx_skb(unifi_priv_t *priv, u16 ifTag, u8* dst_a, u8* src_a, struct sk_b
         priv->interfacePriv[ifTag]->stats.rx_frame_errors++;
         unifi_net_data_free(priv, &bulkdata->d[0]);
         unifi_notice(priv, "indicate_rx_skb: Discard unknown frame.\n");
-        func_exit();
         return;
     }
 
@@ -1975,7 +1946,6 @@ indicate_rx_skb(unifi_priv_t *priv, u16 ifTag, u8* dst_a, u8* src_a, struct sk_b
         unifi_net_data_free(priv, &bulkdata->d[0]);
         unifi_trace(priv, UDBG5, "indicate_rx_skb: Data given to subscription"
                 "API, not being given to kernel\n");
-        func_exit();
         return;
     }
 
@@ -1998,7 +1968,6 @@ indicate_rx_skb(unifi_priv_t *priv, u16 ifTag, u8* dst_a, u8* src_a, struct sk_b
         priv->interfacePriv[ifTag]->stats.rx_errors++;
         priv->interfacePriv[ifTag]->stats.rx_length_errors++;
         unifi_net_data_free(priv, &bulkdata->d[0]);
-        func_exit();
         return;
     }
 
@@ -2025,7 +1994,6 @@ indicate_rx_skb(unifi_priv_t *priv, u16 ifTag, u8* dst_a, u8* src_a, struct sk_b
     priv->interfacePriv[ifTag]->stats.rx_packets++;
     priv->interfacePriv[ifTag]->stats.rx_bytes += bulkdata->d[0].data_length;
 
-    func_exit();
     return;
 }
 
@@ -2178,8 +2146,6 @@ unifi_rx(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata)
     netInterface_priv_t *interfacePriv;
     struct ethhdr ehdr;
 
-    func_enter();
-
     interfaceTag = (pkt_ind->VirtualInterfaceIdentifier & 0xff);
     interfacePriv = priv->interfacePriv[interfaceTag];
 
@@ -2188,7 +2154,6 @@ unifi_rx(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata)
     {
         unifi_error(priv, "%s: MA-PACKET indication with bad interfaceTag %d\n", __FUNCTION__, interfaceTag);
         unifi_net_data_free(priv,&bulkdata->d[0]);
-        func_exit();
         return;
     }
 
@@ -2197,14 +2162,12 @@ unifi_rx(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata)
     {
         unifi_error(priv, "%s: MA-PACKET indication with unallocated interfaceTag %d\n", __FUNCTION__, interfaceTag);
         unifi_net_data_free(priv, &bulkdata->d[0]);
-        func_exit();
         return;
     }
 
     if (bulkdata->d[0].data_length == 0) {
         unifi_warning(priv, "%s: MA-PACKET indication with zero bulk data\n", __FUNCTION__);
         unifi_net_data_free(priv,&bulkdata->d[0]);
-        func_exit();
         return;
     }
 
@@ -2326,7 +2289,6 @@ unifi_rx(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata)
             sa[0], sa[1],sa[2], sa[3], sa[4],sa[5]);
             CsrWifiRouterCtrlUnexpectedFrameIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,interfaceTag,peerMacAddress);
             unifi_net_data_free(priv, &bulkdata->d[0]);
-            func_exit();
             return;
         }
 
@@ -2343,7 +2305,6 @@ unifi_rx(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata)
             unifi_net_data_free(priv, &bulkdata->d[0]);
             unifi_notice(priv, "%s: Dropping packet, proto=0x%04x, %s port\n", __FUNCTION__,
                          proto, queue ? "Controlled" : "Un-controlled");
-            func_exit();
             return;
         }
 
@@ -2351,7 +2312,6 @@ unifi_rx(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata)
         if((dataFrameType == QOS_DATA_NULL) || (dataFrameType == DATA_NULL)){
             unifi_trace(priv, UDBG5, "%s: Null Frame Received and Freed\n", __FUNCTION__);
             unifi_net_data_free(priv, &bulkdata->d[0]);
-            func_exit();
             return;
         }
 
@@ -2366,7 +2326,6 @@ unifi_rx(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata)
              bulkdata,
              macHeaderLengthInBytes)))
         {
-            func_exit();
             return;
         }
         unifi_trace(priv, UDBG5, "unifi_rx: no specific AP handling process as normal frame, MAC Header len %d\n",macHeaderLengthInBytes);
@@ -2389,7 +2348,6 @@ unifi_rx(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata)
             unifi_trace(priv, UDBG1, "Zero length frame, but not null-data %04x\n", frameControl);
         }
         unifi_net_data_free(priv, &bulkdata->d[0]);
-        func_exit();
         return;
     }
 
@@ -2399,7 +2357,6 @@ unifi_rx(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata)
         unifi_net_data_free(priv, &bulkdata->d[0]);
         unifi_notice(priv, "%s: Dropping packet, proto=0x%04x, %s port\n",
                      __FUNCTION__, proto, queue ? "controlled" : "uncontrolled");
-        func_exit();
         return;
     } else if ( (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_BLOCK) ||
                    (interfacePriv->connected != UnifiConnected) ) {
@@ -2415,7 +2372,6 @@ unifi_rx(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata)
                         __FUNCTION__, sizeof(rx_buffered_packets_t));
             interfacePriv->stats.rx_dropped++;
             unifi_net_data_free(priv, &bulkdata->d[0]);
-            func_exit();
             return;
         }
 
@@ -2439,15 +2395,12 @@ unifi_rx(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata)
         list_add_tail(&rx_q_item->q, rx_list);
         up(&priv->rx_q_sem);
 
-        func_exit();
         return;
 
     }
 
     indicate_rx_skb(priv, interfaceTag, da, sa, skb, signal, bulkdata);
 
-    func_exit();
-
 } /* unifi_rx() */
 
 static void process_ma_packet_cfm(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata)
@@ -2456,7 +2409,6 @@ static void process_ma_packet_cfm(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
     const CSR_MA_PACKET_CONFIRM *pkt_cfm = &signal->u.MaPacketConfirm;
     netInterface_priv_t *interfacePriv;
 
-    func_enter();
     interfaceTag = (pkt_cfm->VirtualInterfaceIdentifier & 0xff);
     interfacePriv = priv->interfacePriv[interfaceTag];
 
@@ -2464,7 +2416,6 @@ static void process_ma_packet_cfm(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
     if (interfaceTag >= CSR_WIFI_NUM_INTERFACES)
     {
         unifi_error(priv, "%s: MA-PACKET confirm with bad interfaceTag %d\n", __FUNCTION__, interfaceTag);
-        func_exit();
         return;
     }
 #ifdef CSR_SUPPORT_SME
@@ -2487,7 +2438,6 @@ static void process_ma_packet_cfm(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
         interfacePriv->m4_hostTag = 0xffffffff;
     }
 #endif
-    func_exit();
     return;
 }
 
@@ -2528,8 +2478,6 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
 
 #endif
 
-    func_enter();
-
     interfaceTag = (pkt_ind->VirtualInterfaceIdentifier & 0xff);
     interfacePriv = priv->interfacePriv[interfaceTag];
 
@@ -2539,7 +2487,6 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
     {
         unifi_error(priv, "%s: MA-PACKET indication with bad interfaceTag %d\n", __FUNCTION__, interfaceTag);
         unifi_net_data_free(priv,&bulkdata->d[0]);
-        func_exit();
         return;
     }
 
@@ -2548,24 +2495,21 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
     {
         unifi_error(priv, "%s: MA-PACKET indication with unallocated interfaceTag %d\n", __FUNCTION__, interfaceTag);
         unifi_net_data_free(priv, &bulkdata->d[0]);
-        func_exit();
         return;
     }
 
     if (bulkdata->d[0].data_length == 0) {
         unifi_warning(priv, "%s: MA-PACKET indication with zero bulk data\n", __FUNCTION__);
         unifi_net_data_free(priv,&bulkdata->d[0]);
-        func_exit();
         return;
     }
     /* For monitor mode we need to pass this indication to the registered application
-    handle this seperately*/
+    handle this separately*/
     /* MIC failure is already taken care of so no need to send the PDUs which are not successfully received in non-monitor mode*/
     if(pkt_ind->ReceptionStatus != CSR_RX_SUCCESS)
     {
         unifi_warning(priv, "%s: MA-PACKET indication with status = %d\n",__FUNCTION__, pkt_ind->ReceptionStatus);
         unifi_net_data_free(priv,&bulkdata->d[0]);
-        func_exit();
         return;
     }
 
@@ -2613,13 +2557,11 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
         }
 #endif
         unifi_net_data_free(priv,&bulkdata->d[0]);
-        func_exit();
         return;
     }
     if(frameType != IEEE802_11_FRAMETYPE_DATA) {
         unifi_warning(priv, "%s: Non control Non Data frame is received\n",__FUNCTION__);
         unifi_net_data_free(priv,&bulkdata->d[0]);
-        func_exit();
         return;
     }
 
@@ -2637,7 +2579,6 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
             sa[0], sa[1],sa[2], sa[3], sa[4],sa[5]);
             CsrWifiRouterCtrlUnexpectedFrameIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,interfaceTag,peerMacAddress);
             unifi_net_data_free(priv, &bulkdata->d[0]);
-            func_exit();
             return;
         }
 
@@ -2743,7 +2684,6 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
     up(&priv->ba_mutex);
     process_ba_complete(priv, interfacePriv);
 
-    func_exit();
 }
 /*
  * ---------------------------------------------------------------------------
@@ -2836,8 +2776,6 @@ netdev_mlme_event_handler(ul_client_t *pcli, const u8 *sig_packed, int sig_len,
     int id, r;
     bulk_data_param_t bulkdata;
 
-    func_enter();
-
     /* Just a sanity check */
     if (sig_packed == NULL) {
         return;
@@ -2902,7 +2840,6 @@ netdev_mlme_event_handler(ul_client_t *pcli, const u8 *sig_packed, int sig_len,
             break;
     }
 
-    func_exit();
 } /* netdev_mlme_event_handler() */
 
 
@@ -3100,13 +3037,13 @@ static void update_expected_sn(unifi_priv_t *priv,
     u16 gap;
 
     gap = (sn - ba_session->expected_sn) & 0xFFF;
-    unifi_trace(priv, UDBG6, "%s: proccess the frames up to new_expected_sn = %d gap = %d\n", __FUNCTION__, sn, gap);
+    unifi_trace(priv, UDBG6, "%s: process the frames up to new_expected_sn = %d gap = %d\n", __FUNCTION__, sn, gap);
     for(j = 0; j < gap && j < ba_session->wind_size; j++) {
         i = SN_TO_INDEX(ba_session, ba_session->expected_sn);
-        unifi_trace(priv, UDBG6, "%s: proccess the slot index = %d\n", __FUNCTION__, i);
+        unifi_trace(priv, UDBG6, "%s: process the slot index = %d\n", __FUNCTION__, i);
         if(ba_session->buffer[i].active) {
             add_frame_to_ba_complete(priv, interfacePriv, &ba_session->buffer[i]);
-            unifi_trace(priv, UDBG6, "%s: proccess the frame at index = %d expected_sn = %d\n", __FUNCTION__, i, ba_session->expected_sn);
+            unifi_trace(priv, UDBG6, "%s: process the frame at index = %d expected_sn = %d\n", __FUNCTION__, i, ba_session->expected_sn);
             FREE_BUFFER_SLOT(ba_session, i);
         } else {
             unifi_trace(priv, UDBG6, "%s: empty slot at index = %d\n", __FUNCTION__, i);
@@ -3247,8 +3184,8 @@ static void check_ba_frame_age_timeout( unifi_priv_t *priv,
                                         netInterface_priv_t *interfacePriv,
                                         ba_session_rx_struct *ba_session)
 {
-    CsrTime now;
-    CsrTime age;
+    u32 now;
+    u32 age;
     u8 i, j;
     u16 sn_temp;
 
@@ -3283,11 +3220,11 @@ static void check_ba_frame_age_timeout( unifi_priv_t *priv,
                 if (ba_session->buffer[i].recv_time > now)
                 {
                     /* timer wrap */
-                    age = CsrTimeAdd((CsrTime)CsrTimeSub(CSR_SCHED_TIME_MAX, ba_session->buffer[i].recv_time), now);
+                    age = CsrTimeAdd((u32)CsrTimeSub(CSR_SCHED_TIME_MAX, ba_session->buffer[i].recv_time), now);
                 }
                 else
                 {
-                    age = (CsrTime)CsrTimeSub(now, ba_session->buffer[i].recv_time);
+                    age = (u32)CsrTimeSub(now, ba_session->buffer[i].recv_time);
                 }
 
                 if (age >= CSR_WIFI_BA_MPDU_FRAME_AGE_TIMEOUT)
@@ -3331,8 +3268,6 @@ static void process_ma_packet_error_ind(unifi_priv_t *priv, CSR_SIGNAL *signal,
     CSR_PRIORITY        UserPriority;
     CSR_SEQUENCE_NUMBER sn;
 
-    func_enter();
-
     interfaceTag = (pkt_err_ind->VirtualInterfaceIdentifier & 0xff);
 
 
@@ -3340,7 +3275,6 @@ static void process_ma_packet_error_ind(unifi_priv_t *priv, CSR_SIGNAL *signal,
     if (interfaceTag >= CSR_WIFI_NUM_INTERFACES)
     {
         unifi_error(priv, "%s: MaPacketErrorIndication indication with bad interfaceTag %d\n", __FUNCTION__, interfaceTag);
-        func_exit();
         return;
     }
 
@@ -3348,7 +3282,6 @@ static void process_ma_packet_error_ind(unifi_priv_t *priv, CSR_SIGNAL *signal,
     UserPriority = pkt_err_ind->UserPriority;
     if(UserPriority > 15) {
         unifi_error(priv, "%s: MaPacketErrorIndication indication with bad UserPriority=%d\n", __FUNCTION__, UserPriority);
-        func_exit();
     }
     sn = pkt_err_ind->SequenceNumber;
 
@@ -3369,7 +3302,6 @@ static void process_ma_packet_error_ind(unifi_priv_t *priv, CSR_SIGNAL *signal,
 
     up(&priv->ba_mutex);
     process_ba_complete(priv, interfacePriv);
-    func_exit();
 }
 
 
diff --git a/drivers/staging/csr/os.c b/drivers/staging/csr/os.c
index 35dc908..37ec59d 100644
--- a/drivers/staging/csr/os.c
+++ b/drivers/staging/csr/os.c
@@ -412,9 +412,8 @@ dump(void *mem, u16 len)
         return;
     }
     for (i = 0; i < len; i++) {
-        if (col == 0) {
+        if (col == 0)
             printk("0x%02X: ", i);
-        }
 
         printk(" %02X", pdata[i]);
 
@@ -423,9 +422,8 @@ dump(void *mem, u16 len)
             col = 0;
         }
     }
-    if (col) {
+    if (col)
         printk("\n");
-    }
 } /* dump() */
 
 
@@ -438,9 +436,8 @@ dump16(void *mem, u16 len)
     printk("timestamp %s \n", print_time());
 #endif /* ANDROID_TIMESTAMP */
     for (i = 0; i < len; i+=2) {
-        if (col == 0) {
+        if (col == 0)
             printk("0x%02X: ", i);
-        }
 
         printk(" %04X", *p++);
 
@@ -449,9 +446,8 @@ dump16(void *mem, u16 len)
             col = 0;
         }
     }
-    if (col) {
+    if (col)
         printk("\n");
-    }
 }
 
 
@@ -459,7 +455,7 @@ dump16(void *mem, u16 len)
 void
 dump_str(void *mem, u16 len)
 {
-    int i, col = 0;
+    int i;
     unsigned char *pdata = (unsigned char *)mem;
 #ifdef ANDROID_TIMESTAMP
     printk("timestamp %s \n", print_time());
@@ -467,9 +463,7 @@ dump_str(void *mem, u16 len)
     for (i = 0; i < len; i++) {
         printk("%c", pdata[i]);
     }
-    if (col) {
-        printk("\n");
-    }
+	printk("\n");
 
 } /* dump_str() */
 #endif /* CSR_ONLY_NOTES */
diff --git a/drivers/staging/csr/sdio_mmc.c b/drivers/staging/csr/sdio_mmc.c
index af3e40b..b6a16de 100644
--- a/drivers/staging/csr/sdio_mmc.c
+++ b/drivers/staging/csr/sdio_mmc.c
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/mutex.h>
 #include <linux/gfp.h>
-#include <linux/version.h>
 #include <linux/mmc/core.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -152,7 +151,6 @@ CsrSdioRead8(CsrSdioFunction *function, u32 address, u8 *data)
     _sdio_release_host(func);
 
     if (err) {
-        func_exit_r(err);
         return ConvertSdioToCsrSdioResult(err);
     }
 
@@ -170,7 +168,6 @@ CsrSdioWrite8(CsrSdioFunction *function, u32 address, u8 data)
     _sdio_release_host(func);
 
     if (err) {
-        func_exit_r(err);
         return ConvertSdioToCsrSdioResult(err);
     }
 
@@ -246,7 +243,6 @@ CsrSdioF0Read8(CsrSdioFunction *function, u32 address, u8 *data)
     _sdio_release_host(func);
 
     if (err) {
-        func_exit_r(err);
         return ConvertSdioToCsrSdioResult(err);
     }
 
@@ -268,7 +264,6 @@ CsrSdioF0Write8(CsrSdioFunction *function, u32 address, u8 data)
     _sdio_release_host(func);
 
     if (err) {
-        func_exit_r(err);
         return ConvertSdioToCsrSdioResult(err);
     }
 
@@ -287,7 +282,6 @@ CsrSdioRead(CsrSdioFunction *function, u32 address, void *data, u32 length)
     _sdio_release_host(func);
 
     if (err) {
-        func_exit_r(err);
         return ConvertSdioToCsrSdioResult(err);
     }
 
@@ -305,7 +299,6 @@ CsrSdioWrite(CsrSdioFunction *function, u32 address, const void *data, u32 lengt
     _sdio_release_host(func);
 
     if (err) {
-        func_exit_r(err);
         return ConvertSdioToCsrSdioResult(err);
     }
 
@@ -480,7 +473,6 @@ CsrSdioInterruptEnable(CsrSdioFunction *function)
 #endif
     _sdio_release_host(func);
 
-    func_exit();
     if (err) {
         printk(KERN_ERR "unifi: %s: error %d writing IENx\n", __FUNCTION__, err);
         return ConvertSdioToCsrSdioResult(err);
@@ -507,7 +499,6 @@ CsrSdioInterruptDisable(CsrSdioFunction *function)
 #endif
     _sdio_release_host(func);
 
-    func_exit();
     if (err) {
         printk(KERN_ERR "unifi: %s: error %d writing IENx\n", __FUNCTION__, err);
         return ConvertSdioToCsrSdioResult(err);
@@ -541,8 +532,6 @@ CsrSdioFunctionEnable(CsrSdioFunction *function)
     struct sdio_func *func = (struct sdio_func *)function->priv;
     int err;
 
-    func_enter();
-
     /* Enable UniFi function 1 (the 802.11 part). */
     _sdio_claim_host(func);
     err = sdio_enable_func(func);
@@ -551,7 +540,6 @@ CsrSdioFunctionEnable(CsrSdioFunction *function)
         unifi_error(NULL, "Failed to enable SDIO function %d\n", func->num);
     }
 
-    func_exit();
     return ConvertSdioToCsrSdioResult(err);
 } /* CsrSdioFunctionEnable() */
 
@@ -575,8 +563,6 @@ CsrSdioFunctionDisable(CsrSdioFunction *function)
     struct sdio_func *func = (struct sdio_func *)function->priv;
     int err;
 
-    func_enter();
-
     /* Disable UniFi function 1 (the 802.11 part). */
     _sdio_claim_host(func);
     err = sdio_disable_func(func);
@@ -585,7 +571,6 @@ CsrSdioFunctionDisable(CsrSdioFunction *function)
         unifi_error(NULL, "Failed to disable SDIO function %d\n", func->num);
     }
 
-    func_exit();
     return ConvertSdioToCsrSdioResult(err);
 } /* CsrSdioFunctionDisable() */
 
@@ -1034,8 +1019,6 @@ uf_glue_sdio_probe(struct sdio_func *func,
     int instance;
     CsrSdioFunction *sdio_ctx;
 
-    func_enter();
-
     /* First of all claim the SDIO driver */
     sdio_claim_host(func);
 
@@ -1103,7 +1086,6 @@ uf_glue_sdio_probe(struct sdio_func *func,
     wake_lock(&unifi_sdio_wake_lock);
 #endif
 
-    func_exit();
     return 0;
 } /* uf_glue_sdio_probe() */
 
@@ -1131,8 +1113,6 @@ uf_glue_sdio_remove(struct sdio_func *func)
         return;
     }
 
-    func_enter();
-
     unifi_info(NULL, "UniFi card removed\n");
 
     /* Clean up the SDIO function driver */
@@ -1148,8 +1128,6 @@ uf_glue_sdio_remove(struct sdio_func *func)
 
     kfree(sdio_ctx);
 
-    func_exit();
-
 } /* uf_glue_sdio_remove */
 
 
@@ -1183,11 +1161,8 @@ MODULE_DEVICE_TABLE(sdio, unifi_ids);
 static int
 uf_glue_sdio_suspend(struct device *dev)
 {
-    func_enter();
-
     unifi_trace(NULL, UDBG1, "uf_glue_sdio_suspend");
 
-    func_exit();
     return 0;
 } /* uf_glue_sdio_suspend */
 
@@ -1208,8 +1183,6 @@ uf_glue_sdio_suspend(struct device *dev)
 static int
 uf_glue_sdio_resume(struct device *dev)
 {
-    func_enter();
-
     unifi_trace(NULL, UDBG1, "uf_glue_sdio_resume");
 
 #ifdef ANDROID_BUILD
@@ -1217,7 +1190,6 @@ uf_glue_sdio_resume(struct device *dev)
     wake_lock(&unifi_sdio_wake_lock);
 #endif
 
-    func_exit();
     return 0;
 
 } /* uf_glue_sdio_resume */
diff --git a/drivers/staging/csr/sme_blocking.c b/drivers/staging/csr/sme_blocking.c
index 543e8f2..d88ccd5 100644
--- a/drivers/staging/csr/sme_blocking.c
+++ b/drivers/staging/csr/sme_blocking.c
@@ -270,17 +270,15 @@ int sme_mgt_wifi_off(unifi_priv_t *priv)
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     /* Stop the SME */
     CsrWifiSmeWifiOffReqSend(0);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     unifi_trace(priv, UDBG4,
                 "sme_mgt_wifi_off: unifi_mgt_wifi_off_req <-- (r=%d, status=%d)\n",
@@ -300,16 +298,14 @@ int sme_mgt_key(unifi_priv_t *priv, CsrWifiSmeKey *sme_key,
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeKeyReqSend(0, CSR_WIFI_INTERFACE_IN_USE, action, *sme_key);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     return convert_sme_error(priv->sme_reply.reply_status);
 }
@@ -332,9 +328,8 @@ int sme_mgt_scan_full(unifi_priv_t *priv,
     unifi_trace(priv, UDBG4, "sme_mgt_scan_full: -->\n");
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     /* If a channel list is provided, do an active scan */
     if (is_active) {
@@ -354,16 +349,14 @@ int sme_mgt_scan_full(unifi_priv_t *priv,
                               0, NULL);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     unifi_trace(priv, UDBG4, "sme_mgt_scan_full: <-- (status=%d)\n", priv->sme_reply.reply_status);
-    if (priv->sme_reply.reply_status == CSR_WIFI_RESULT_UNAVAILABLE) {
+    if (priv->sme_reply.reply_status == CSR_WIFI_RESULT_UNAVAILABLE)
         return 0; /* initial scan already underway */
-    } else {
+    else
         return convert_sme_error(priv->sme_reply.reply_status);
-    }
 }
 
 
@@ -385,15 +378,13 @@ int sme_mgt_scan_results_get_async(unifi_priv_t *priv,
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeScanResultsGetReqSend(0);
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     scan_result_list_count = priv->sme_reply.reply_scan_results_count;
     scan_result_list = priv->sme_reply.reply_scan_results;
@@ -454,20 +445,17 @@ int sme_mgt_connect(unifi_priv_t *priv)
                 priv->connection_config.ssid.ssid);
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeConnectReqSend(0, CSR_WIFI_INTERFACE_IN_USE, priv->connection_config);
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
-    if (priv->sme_reply.reply_status) {
+    if (priv->sme_reply.reply_status)
         unifi_trace(priv, UDBG1, "sme_mgt_connect: failed with SME status %d\n",
                     priv->sme_reply.reply_status);
-    }
 
     return convert_sme_error(priv->sme_reply.reply_status);
 }
@@ -483,15 +471,13 @@ int sme_mgt_disconnect(unifi_priv_t *priv)
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeDisconnectReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     unifi_trace(priv, UDBG4, "sme_mgt_disconnect: <-- (status=%d)\n", priv->sme_reply.reply_status);
     return convert_sme_error(priv->sme_reply.reply_status);
@@ -510,16 +496,14 @@ int sme_mgt_pmkid(unifi_priv_t *priv,
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmePmkidReqSend(0, CSR_WIFI_INTERFACE_IN_USE, action,
                         pmkid_list->pmkidsCount, pmkid_list->pmkids);
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     unifi_trace(priv, UDBG4, "sme_mgt_pmkid: <-- (status=%d)\n", priv->sme_reply.reply_status);
     return convert_sme_error(priv->sme_reply.reply_status);
@@ -537,9 +521,8 @@ int sme_mgt_mib_get(unifi_priv_t *priv,
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     priv->mib_cfm_buffer = varbind;
     priv->mib_cfm_buffer_length = MAX_VARBIND_LENGTH;
@@ -571,15 +554,13 @@ int sme_mgt_mib_set(unifi_priv_t *priv,
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeMibSetReqSend(0, length, varbind);
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     unifi_trace(priv, UDBG4, "sme_mgt_mib_set: <-- (status=%d)\n", priv->sme_reply.reply_status);
     return convert_sme_error(priv->sme_reply.reply_status);
@@ -598,16 +579,14 @@ int sme_mgt_power_config_set(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerCon
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmePowerConfigSetReqSend(0, *powerConfig);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     unifi_trace(priv, UDBG4,
                 "sme_mgt_set_value_async: unifi_mgt_set_value_req <-- (r=%d status=%d)\n",
@@ -637,29 +616,26 @@ int sme_mgt_sme_config_set(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, C
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeSmeStaConfigSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE, *staConfig);
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
+
     unifi_trace(priv, UDBG4,
                 "sme_mgt_sme_config_set: CsrWifiSmeSmeStaConfigSetReq <-- (r=%d status=%d)\n",
                 r, priv->sme_reply.reply_status);
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeSmeCommonConfigSetReqSend(0, *deviceConfig);
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     unifi_trace(priv, UDBG4,
                 "sme_mgt_sme_config_set: CsrWifiSmeSmeCommonConfigSetReq <-- (r=%d status=%d)\n",
@@ -693,16 +669,14 @@ int sme_mgt_mib_config_set(unifi_priv_t *priv, CsrWifiSmeMibConfig *mibConfig)
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeMibConfigSetReqSend(0, *mibConfig);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     unifi_trace(priv, UDBG4,
                 "sme_mgt_mib_config_set: unifi_mgt_set_mib_config_req <-- (r=%d status=%d)\n",
@@ -732,16 +706,14 @@ int sme_mgt_coex_config_set(unifi_priv_t *priv, CsrWifiSmeCoexConfig *coexConfig
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeCoexConfigSetReqSend(0, *coexConfig);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     unifi_trace(priv, UDBG4,
                 "sme_mgt_coex_config_set: unifi_mgt_set_mib_config_req <-- (r=%d status=%d)\n",
@@ -773,16 +745,14 @@ int sme_mgt_host_config_set(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeHostConfigSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE, *hostConfig);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     unifi_trace(priv, UDBG4,
                 "sme_mgt_host_config_set: unifi_mgt_set_host_config_req <-- (r=%d status=%d)\n",
@@ -815,16 +785,14 @@ int sme_mgt_versions_get(unifi_priv_t *priv, CsrWifiSmeVersions *versions)
 
     unifi_trace(priv, UDBG4, "sme_mgt_versions_get: unifi_mgt_versions_get_req -->\n");
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeVersionsGetReqSend(0);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     /* store the reply */
     if (versions != NULL) {
@@ -861,16 +829,14 @@ int sme_mgt_power_config_get(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerCon
 
     unifi_trace(priv, UDBG4, "sme_mgt_power_config_get: unifi_mgt_power_config_req -->\n");
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmePowerConfigGetReqSend(0);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     /* store the reply */
     if (powerConfig != NULL) {
@@ -905,23 +871,20 @@ int sme_mgt_host_config_get(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig
 
     unifi_trace(priv, UDBG4, "sme_mgt_host_config_get: unifi_mgt_host_config_get_req -->\n");
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeHostConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     /* store the reply */
-    if (hostConfig != NULL) {
+    if (hostConfig != NULL)
         memcpy((unsigned char*)hostConfig,
                (unsigned char*)&priv->sme_reply.hostConfig,
                sizeof(CsrWifiSmeHostConfig));
-    }
 
     unifi_trace(priv, UDBG4,
                 "sme_mgt_host_config_get: unifi_mgt_host_config_get_req <-- (r=%d status=%d)\n",
@@ -951,41 +914,35 @@ int sme_mgt_sme_config_get(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, C
 
     /* Common device config */
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeSmeCommonConfigGetReqSend(0);
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     /* store the reply */
-    if (deviceConfig != NULL) {
+    if (deviceConfig != NULL)
         memcpy((unsigned char*)deviceConfig,
                (unsigned char*)&priv->sme_reply.deviceConfig,
                sizeof(CsrWifiSmeDeviceConfig));
-    }
 
     /* STA config */
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeSmeStaConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     /* store the reply */
-    if (staConfig != NULL) {
+    if (staConfig != NULL)
         memcpy((unsigned char*)staConfig,
                (unsigned char*)&priv->sme_reply.staConfig,
                sizeof(CsrWifiSmeStaConfig));
-    }
 
     unifi_trace(priv, UDBG4,
                 "sme_mgt_sme_config_get: unifi_mgt_sme_config_get_req <-- (r=%d status=%d)\n",
@@ -1014,23 +971,20 @@ int sme_mgt_coex_info_get(unifi_priv_t *priv, CsrWifiSmeCoexInfo *coexInfo)
 
     unifi_trace(priv, UDBG4, "sme_mgt_coex_info_get: unifi_mgt_coex_info_get_req -->\n");
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeCoexInfoGetReqSend(0);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     /* store the reply */
-    if (coexInfo != NULL) {
+    if (coexInfo != NULL)
         memcpy((unsigned char*)coexInfo,
                (unsigned char*)&priv->sme_reply.coexInfo,
                sizeof(CsrWifiSmeCoexInfo));
-    }
 
     unifi_trace(priv, UDBG4,
                 "sme_mgt_coex_info_get: unifi_mgt_coex_info_get_req <-- (r=%d status=%d)\n",
@@ -1060,23 +1014,20 @@ int sme_mgt_coex_config_get(unifi_priv_t *priv, CsrWifiSmeCoexConfig *coexConfig
 
     unifi_trace(priv, UDBG4, "sme_mgt_coex_config_get: unifi_mgt_coex_config_get_req -->\n");
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeCoexConfigGetReqSend(0);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     /* store the reply */
-    if (coexConfig != NULL) {
+    if (coexConfig != NULL)
         memcpy((unsigned char*)coexConfig,
                (unsigned char*)&priv->sme_reply.coexConfig,
                sizeof(CsrWifiSmeCoexConfig));
-    }
 
     unifi_trace(priv, UDBG4,
                 "sme_mgt_coex_config_get: unifi_mgt_coex_config_get_req <-- (r=%d status=%d)\n",
@@ -1104,23 +1055,20 @@ int sme_mgt_mib_config_get(unifi_priv_t *priv, CsrWifiSmeMibConfig *mibConfig)
 
     unifi_trace(priv, UDBG4, "sme_mgt_mib_config_get: unifi_mgt_mib_config_get_req -->\n");
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeMibConfigGetReqSend(0);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     /* store the reply */
-    if (mibConfig != NULL) {
+    if (mibConfig != NULL)
         memcpy((unsigned char*)mibConfig,
                (unsigned char*)&priv->sme_reply.mibConfig,
                sizeof(CsrWifiSmeMibConfig));
-    }
 
     unifi_trace(priv, UDBG4,
                 "sme_mgt_mib_config_get: unifi_mgt_mib_config_get_req <-- (r=%d status=%d)\n",
@@ -1148,23 +1096,20 @@ int sme_mgt_connection_info_get(unifi_priv_t *priv, CsrWifiSmeConnectionInfo *co
 
     unifi_trace(priv, UDBG4, "sme_mgt_connection_info_get: unifi_mgt_connection_info_get_req -->\n");
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeConnectionInfoGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     /* store the reply */
-    if (connectionInfo != NULL) {
+    if (connectionInfo != NULL)
         memcpy((unsigned char*)connectionInfo,
                (unsigned char*)&priv->sme_reply.connectionInfo,
                sizeof(CsrWifiSmeConnectionInfo));
-    }
 
     unifi_trace(priv, UDBG4,
                 "sme_mgt_connection_info_get: unifi_mgt_connection_info_get_req <-- (r=%d status=%d)\n",
@@ -1192,23 +1137,20 @@ int sme_mgt_connection_config_get(unifi_priv_t *priv, CsrWifiSmeConnectionConfig
 
     unifi_trace(priv, UDBG4, "sme_mgt_connection_config_get: unifi_mgt_connection_config_get_req -->\n");
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeConnectionConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     /* store the reply */
-    if (connectionConfig != NULL) {
+    if (connectionConfig != NULL)
         memcpy((unsigned char*)connectionConfig,
                (unsigned char*)&priv->sme_reply.connectionConfig,
                sizeof(CsrWifiSmeConnectionConfig));
-    }
 
     unifi_trace(priv, UDBG4,
                 "sme_mgt_connection_config_get: unifi_mgt_connection_config_get_req <-- (r=%d status=%d)\n",
@@ -1236,23 +1178,20 @@ int sme_mgt_connection_stats_get(unifi_priv_t *priv, CsrWifiSmeConnectionStats *
 
     unifi_trace(priv, UDBG4, "sme_mgt_connection_stats_get: unifi_mgt_connection_stats_get_req -->\n");
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiSmeConnectionStatsGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     /* store the reply */
-    if (connectionStats != NULL) {
+    if (connectionStats != NULL)
         memcpy((unsigned char*)connectionStats,
                (unsigned char*)&priv->sme_reply.connectionStats,
                sizeof(CsrWifiSmeConnectionStats));
-    }
 
     unifi_trace(priv, UDBG4,
                 "sme_mgt_connection_stats_get: unifi_mgt_connection_stats_get_req <-- (r=%d status=%d)\n",
@@ -1272,58 +1211,56 @@ int sme_mgt_connection_stats_get(unifi_priv_t *priv, CsrWifiSmeConnectionStats *
 
 int sme_mgt_packet_filter_set(unifi_priv_t *priv)
 {
-    CsrWifiIp4Address ipAddress = {{0xFF, 0xFF, 0xFF, 0xFF }};
-    if (priv->smepriv == NULL) {
-        unifi_error(priv, "sme_mgt_packet_filter_set: invalid smepriv\n");
-        return -EIO;
-    }
-    if (priv->packet_filters.arp_filter) {
-        ipAddress.a[0] = (priv->sta_ip_address      ) & 0xFF;
-        ipAddress.a[1] = (priv->sta_ip_address >>  8) & 0xFF;
-        ipAddress.a[2] = (priv->sta_ip_address >> 16) & 0xFF;
-        ipAddress.a[3] = (priv->sta_ip_address >> 24) & 0xFF;
-    }
-
-    unifi_trace(priv, UDBG5,
-                "sme_mgt_packet_filter_set: IP address %d.%d.%d.%d\n",
-                ipAddress.a[0], ipAddress.a[1],
-                ipAddress.a[2], ipAddress.a[3]);
-
-    /* Doesn't block for a confirm */
-    CsrWifiSmePacketFilterSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE,
-                                     priv->packet_filters.tclas_ies_length,
-                                     priv->filter_tclas_ies,
-                                     priv->packet_filters.filter_mode,
-                                     ipAddress);
-    return 0;
+	CsrWifiIp4Address ipAddress = {{0xFF, 0xFF, 0xFF, 0xFF }};
+	if (priv->smepriv == NULL) {
+		unifi_error(priv, "sme_mgt_packet_filter_set: invalid smepriv\n");
+		return -EIO;
+	}
+	if (priv->packet_filters.arp_filter) {
+		ipAddress.a[0] = (priv->sta_ip_address      ) & 0xFF;
+		ipAddress.a[1] = (priv->sta_ip_address >>  8) & 0xFF;
+		ipAddress.a[2] = (priv->sta_ip_address >> 16) & 0xFF;
+		ipAddress.a[3] = (priv->sta_ip_address >> 24) & 0xFF;
+	}
+
+	unifi_trace(priv, UDBG5,
+		"sme_mgt_packet_filter_set: IP address %d.%d.%d.%d\n",
+		ipAddress.a[0], ipAddress.a[1],
+		ipAddress.a[2], ipAddress.a[3]);
+
+	/* Doesn't block for a confirm */
+	CsrWifiSmePacketFilterSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE,
+				     priv->packet_filters.tclas_ies_length,
+				     priv->filter_tclas_ies,
+				     priv->packet_filters.filter_mode,
+				     ipAddress);
+	return 0;
 }
 
 int sme_mgt_tspec(unifi_priv_t *priv, CsrWifiSmeListAction action,
         u32 tid, CsrWifiSmeDataBlock *tspec, CsrWifiSmeDataBlock *tclas)
 {
-    int r;
-
-    if (priv->smepriv == NULL) {
-        unifi_error(priv, "sme_mgt_tspec: invalid smepriv\n");
-        return -EIO;
-    }
-
-    r = sme_init_request(priv);
-    if (r) {
-        return -EIO;
-    }
-
-    CsrWifiSmeTspecReqSend(0, CSR_WIFI_INTERFACE_IN_USE,
-                           action, tid, TRUE, 0,
-                           tspec->length, tspec->data,
-                           tclas->length, tclas->data);
-    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
-        return r;
-    }
-
-    unifi_trace(priv, UDBG4, "sme_mgt_tspec: <-- (status=%d)\n", priv->sme_reply.reply_status);
-    return convert_sme_error(priv->sme_reply.reply_status);
+	int r;
+
+	if (priv->smepriv == NULL) {
+		unifi_error(priv, "sme_mgt_tspec: invalid smepriv\n");
+		return -EIO;
+	}
+
+	r = sme_init_request(priv);
+	if (r)
+		return -EIO;
+
+	CsrWifiSmeTspecReqSend(0, CSR_WIFI_INTERFACE_IN_USE,
+			      action, tid, TRUE, 0,
+			      tspec->length, tspec->data,
+			      tclas->length, tclas->data);
+	r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
+	if (r)
+		return r;
+
+	unifi_trace(priv, UDBG4, "sme_mgt_tspec: <-- (status=%d)\n", priv->sme_reply.reply_status);
+	return convert_sme_error(priv->sme_reply.reply_status);
 }
 
 
@@ -1339,9 +1276,8 @@ int sme_sys_suspend(unifi_priv_t *priv)
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     /* Suspend the SME, which MAY cause it to power down UniFi */
     CsrWifiRouterCtrlSuspendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, 0, priv->wol_suspend);
@@ -1427,17 +1363,15 @@ int sme_sys_resume(unifi_priv_t *priv)
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiRouterCtrlResumeIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, priv->wol_suspend);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT);
-    if (r) {
+    if (r)
         unifi_notice(priv,
                 "resume: SME did not reply, return success anyway\n");
-    }
 
     return 0;
 }
@@ -1453,16 +1387,14 @@ int sme_ap_stop(unifi_priv_t *priv,u16 interface_tag)
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiNmeApStopReqSend(0,interface_tag);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     unifi_trace(priv, UDBG4,
                 "sme_ap_stop <-- (r=%d status=%d)\n",
@@ -1484,9 +1416,8 @@ int sme_ap_start(unifi_priv_t *priv,u16 interface_tag,
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiNmeApStartReqSend(0,interface_tag,CSR_WIFI_AP_TYPE_LEGACY,FALSE,
                              ap_config->ssid,1,ap_config->channel,
@@ -1494,9 +1425,8 @@ int sme_ap_start(unifi_priv_t *priv,u16 interface_tag,
                              p2p_go_param,FALSE);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
-    if (r) {
+    if (r)
         return r;
-    }
 
     unifi_trace(priv, UDBG4,
                 "sme_ap_start <-- (r=%d status=%d)\n",
@@ -1518,14 +1448,15 @@ int sme_ap_config(unifi_priv_t *priv,
     }
 
     r = sme_init_request(priv);
-    if (r) {
+    if (r)
         return -EIO;
-    }
 
     CsrWifiNmeApConfigSetReqSend(0,*group_security_config,
                                  *ap_mac_config);
 
     r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
+	if (r)
+		return r;
 
     unifi_trace(priv, UDBG4,
                 "sme_ap_config <-- (r=%d status=%d)\n",
diff --git a/drivers/staging/csr/sme_native.c b/drivers/staging/csr/sme_native.c
index d7a5125..525fe1b 100644
--- a/drivers/staging/csr/sme_native.c
+++ b/drivers/staging/csr/sme_native.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/netdevice.h>
-#include <linux/version.h>
 #include "unifi_priv.h"
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_conversions.h"
@@ -22,23 +21,17 @@ static const unsigned char wildcard_address[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00,
 int
 uf_sme_init(unifi_priv_t *priv)
 {
-    func_enter();
-
     sema_init(&priv->mlme_blocking_mutex, 1);
 
 #ifdef CSR_SUPPORT_WEXT
     {
         int r = uf_init_wext_interface(priv);
         if (r != 0) {
-            func_exit();
             return r;
         }
     }
 #endif
 
-
-
-    func_exit();
     return 0;
 } /* uf_sme_init() */
 
@@ -47,8 +40,6 @@ void
 uf_sme_deinit(unifi_priv_t *priv)
 {
 
-    func_enter();
-
     /* Free memory allocated for the scan table */
 /*    unifi_clear_scan_table(priv); */
 
@@ -59,8 +50,6 @@ uf_sme_deinit(unifi_priv_t *priv)
     uf_deinit_wext_interface(priv);
 #endif
 
-
-    func_exit();
 } /* uf_sme_deinit() */
 
 
@@ -222,8 +211,6 @@ sme_native_log_event(ul_client_t *pcli,
     CSR_SIGNAL signal;
     ul_client_t *client = pcli;
 
-    func_enter();
-
     if (client == NULL) {
         unifi_error(NULL, "sme_native_log_event: client has exited\n");
         return;
@@ -334,8 +321,6 @@ sme_native_log_event(ul_client_t *pcli,
     /* Wake any waiting user process */
     wake_up_interruptible(&client->udi_wq);
 
-    func_exit();
-
 } /* sme_native_log_event() */
 
 
@@ -461,8 +446,6 @@ sme_native_mlme_event_handler(ul_client_t *pcli,
     unifi_priv_t *priv = uf_find_instance(pcli->instance);
     int id, r;
 
-    func_enter();
-
     /* Just a sanity check */
     if ((sig_packed == NULL) || (sig_len <= 0)) {
         return;
@@ -542,7 +525,6 @@ sme_native_mlme_event_handler(ul_client_t *pcli,
             break;
     }
 
-    func_exit();
 } /* sme_native_mlme_event_handler() */
 
 
@@ -574,14 +556,11 @@ unifi_reset_state(unifi_priv_t *priv, unsigned char *macaddr,
 {
     int r = 0;
 
-    func_enter();
-
 #ifdef CSR_SUPPORT_WEXT
     /* The reset clears any 802.11 association. */
     priv->wext_conf.flag_associated = 0;
 #endif
 
-    func_exit();
     return r;
 } /* unifi_reset_state() */
 
diff --git a/drivers/staging/csr/sme_sys.c b/drivers/staging/csr/sme_sys.c
index 5b26c41..2b06819 100644
--- a/drivers/staging/csr/sme_sys.c
+++ b/drivers/staging/csr/sme_sys.c
@@ -14,7 +14,6 @@
  * ---------------------------------------------------------------------------
  */
 
-#include <linux/version.h>
 #include "csr_wifi_hip_unifiversion.h"
 #include "unifi_priv.h"
 #include "csr_wifi_hip_conversions.h"
@@ -413,8 +412,6 @@ uf_send_gratuitous_arp(unifi_priv_t *priv, u16 interfaceTag)
                                          0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                                          0xc0, 0xa8, 0x00, 0x02};
 
-    func_enter();
-
     csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], sizeof(arp_req));
     if (csrResult != CSR_RESULT_SUCCESS)
     {
@@ -480,8 +477,6 @@ uf_send_gratuitous_arp(unifi_priv_t *priv, u16 interfaceTag)
         return;
     }
 
-    func_exit();
-
 }
 #endif /* CSR_WIFI_SEND_GRATUITOUS_ARP */
 
@@ -2102,7 +2097,7 @@ static int peer_add_new_record(unifi_priv_t *priv,CsrWifiRouterCtrlPeerAddReq *r
     u8 freeSlotFound = FALSE;
     CsrWifiRouterCtrlStaInfo_t *newRecord = NULL;
     netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag];
-    CsrTime currentTime, currentTimeHi;
+    u32 currentTime, currentTimeHi;
     unsigned long lock_flags;
 
     if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) {
@@ -2296,8 +2291,8 @@ static void check_inactivity_timer_expire_func(unsigned long data)
     struct unifi_priv *priv;
     CsrWifiRouterCtrlStaInfo_t *sta_record = NULL;
     u8 i = 0;
-    CsrTime now;
-    CsrTime inactive_time;
+    u32 now;
+    u32 inactive_time;
     netInterface_priv_t *interfacePriv = (netInterface_priv_t *) data;
 
     if (!interfacePriv)
@@ -2329,11 +2324,11 @@ static void check_inactivity_timer_expire_func(unsigned long data)
             if (sta_record->lastActivity > now)
             {
                 /* simple timer wrap (for 1 wrap) */
-                inactive_time = CsrTimeAdd((CsrTime)CsrTimeSub(CSR_SCHED_TIME_MAX, sta_record->lastActivity), now);
+                inactive_time = CsrTimeAdd((u32)CsrTimeSub(CSR_SCHED_TIME_MAX, sta_record->lastActivity), now);
             }
             else
             {
-                inactive_time = (CsrTime)CsrTimeSub(now, sta_record->lastActivity);
+                inactive_time = (u32)CsrTimeSub(now, sta_record->lastActivity);
             }
 
             if (inactive_time >= STA_INACTIVE_TIMEOUT_VAL)
@@ -2411,8 +2406,6 @@ void uf_send_disconnected_ind_wq(struct work_struct *work)
     struct list_head send_cfm_list;
     u8 j;
 
-    func_enter();
-
     if(!staInfo) {
         return;
     }
diff --git a/drivers/staging/csr/sme_userspace.h b/drivers/staging/csr/sme_userspace.h
index 7816b15..ebe371c 100644
--- a/drivers/staging/csr/sme_userspace.h
+++ b/drivers/staging/csr/sme_userspace.h
@@ -32,7 +32,7 @@ int uf_sme_queue_message(unifi_priv_t *priv, u8 *buffer, int length);
 #include "csr_wifi_sme_lib.h"
 
 void CsrWifiRouterTransportInit(unifi_priv_t *priv);
-void CsrWifiRouterTransportRecv(unifi_priv_t *priv, u8* buffer, size_t bufferLength);
+void CsrWifiRouterTransportRecv(unifi_priv_t *priv, u8 *buffer, size_t bufferLength);
 void CsrWifiRouterTransportDeInit(unifi_priv_t *priv);
 
 #endif /* __LINUX_SME_USERSPACE_H__ */
diff --git a/drivers/staging/csr/sme_wext.c b/drivers/staging/csr/sme_wext.c
index b58c0c6..5e06a38 100644
--- a/drivers/staging/csr/sme_wext.c
+++ b/drivers/staging/csr/sme_wext.c
@@ -800,7 +800,6 @@ iwprivsconfwapi(struct net_device *dev, struct iw_request_info *info,
     u8 enable;
     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
     unifi_priv_t *priv = interfacePriv->privPtr;
-    func_enter();
 
     unifi_trace(priv, UDBG1, "iwprivsconfwapi\n" );
 
@@ -824,7 +823,6 @@ iwprivsconfwapi(struct net_device *dev, struct iw_request_info *info,
             ~(CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4);
     }
 
-    func_exit();
     return 0;
 }
 
@@ -837,7 +835,6 @@ iwprivswpikey(struct net_device *dev, struct iw_request_info *info,
     unifiio_wapi_key_t inKey;
     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
     unifi_priv_t *priv = interfacePriv->privPtr;
-    func_enter();
 
     unifi_trace(priv, UDBG1, "iwprivswpikey\n" );
 
@@ -882,7 +879,6 @@ iwprivswpikey(struct net_device *dev, struct iw_request_info *info,
         return convert_sme_error(r);
     }
 
-    func_exit();
     return r;
 }
 #endif
@@ -914,7 +910,6 @@ unifi_siwfreq(struct net_device *dev, struct iw_request_info *info,
     unifi_priv_t *priv = interfacePriv->privPtr;
     struct iw_freq *freq = (struct iw_freq *)wrqu;
 
-    func_enter();
     unifi_trace(priv, UDBG2, "unifi_siwfreq\n");
 
     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
@@ -935,7 +930,6 @@ unifi_siwfreq(struct net_device *dev, struct iw_request_info *info,
         priv->connection_config.adhocChannel = wext_freq_to_channel(freq->m, freq->e);
     }
 
-    func_exit();
     return 0;
 } /* unifi_siwfreq() */
 
@@ -950,7 +944,6 @@ unifi_giwfreq(struct net_device *dev, struct iw_request_info *info,
     int err = 0;
     CsrWifiSmeConnectionInfo connectionInfo;
 
-    func_enter();
     unifi_trace(priv, UDBG2, "unifi_giwfreq\n");
     CHECK_INITED(priv);
 
@@ -970,7 +963,6 @@ unifi_giwfreq(struct net_device *dev, struct iw_request_info *info,
             (connectionInfo.networkType80211 == CSR_WIFI_SME_RADIO_IF_GHZ_5_0));
     freq->e = 6;
 
-    func_exit();
     return convert_sme_error(err);
 } /* unifi_giwfreq() */
 
@@ -982,7 +974,6 @@ unifi_siwmode(struct net_device *dev, struct iw_request_info *info,
     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
     unifi_priv_t *priv = interfacePriv->privPtr;
 
-    func_enter();
     unifi_trace(priv, UDBG2, "unifi_siwmode\n");
 
     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
@@ -1011,7 +1002,6 @@ unifi_siwmode(struct net_device *dev, struct iw_request_info *info,
     priv->connection_config.ssid.length = 0;
     memset(priv->connection_config.bssid.a, 0xFF, ETH_ALEN);
 
-    func_exit();
     return 0;
 } /* unifi_siwmode() */
 
@@ -1026,7 +1016,6 @@ unifi_giwmode(struct net_device *dev, struct iw_request_info *info,
     unifi_priv_t *priv = interfacePriv->privPtr;
     CsrWifiSmeConnectionConfig connectionConfig;
 
-    func_enter();
     unifi_trace(priv, UDBG2, "unifi_giwmode\n");
     CHECK_INITED(priv);
 
@@ -1069,7 +1058,6 @@ unifi_giwmode(struct net_device *dev, struct iw_request_info *info,
 
     }
     unifi_trace(priv, UDBG4, "unifi_giwmode: mode = 0x%x\n", wrqu->mode);
-    func_exit();
     return r;
 } /* unifi_giwmode() */
 
@@ -1192,8 +1180,6 @@ unifi_siwap(struct net_device *dev, struct iw_request_info *info,
     unifi_priv_t *priv = interfacePriv->privPtr;
     int err = 0;
 
-    func_enter();
-
     CHECK_INITED(priv);
 
     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
@@ -1235,11 +1221,9 @@ unifi_siwap(struct net_device *dev, struct iw_request_info *info,
         err = sme_mgt_connect(priv);
         if (err) {
             unifi_error(priv, "unifi_siwap: Join failed, status %d\n", err);
-            func_exit();
             return convert_sme_error(err);
         }
     }
-    func_exit();
 
     return 0;
 } /* unifi_siwap() */
@@ -1255,8 +1239,6 @@ unifi_giwap(struct net_device *dev, struct iw_request_info *info,
     int r = 0;
     u8 *bssid;
 
-    func_enter();
-
     CHECK_INITED(priv);
     unifi_trace(priv, UDBG2, "unifi_giwap\n");
 
@@ -1281,7 +1263,6 @@ unifi_giwap(struct net_device *dev, struct iw_request_info *info,
         memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
     }
 
-    func_exit();
     return 0;
 } /* unifi_giwap() */
 
@@ -1302,8 +1283,6 @@ unifi_siwscan(struct net_device *dev, struct iw_request_info *info,
     struct iw_scan_req *req = (struct iw_scan_req *) extra;
 #endif
 
-    func_enter();
-
     CHECK_INITED(priv);
 
     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
@@ -1366,7 +1345,6 @@ unifi_siwscan(struct net_device *dev, struct iw_request_info *info,
         kfree(channel_list);
     }
 
-    func_exit();
     return r;
 
 } /* unifi_siwscan() */
@@ -1707,7 +1685,6 @@ unifi_siwessid(struct net_device *dev, struct iw_request_info *info,
     int len;
     int err = 0;
 
-    func_enter();
     CHECK_INITED(priv);
 
     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
@@ -1760,11 +1737,9 @@ unifi_siwessid(struct net_device *dev, struct iw_request_info *info,
     UF_RTNL_LOCK();
     if (err) {
         unifi_error(priv, "unifi_siwessid: Join failed, status %d\n", err);
-        func_exit();
         return convert_sme_error(err);
     }
 
-    func_exit();
     return 0;
 } /* unifi_siwessid() */
 
@@ -1779,7 +1754,6 @@ unifi_giwessid(struct net_device *dev, struct iw_request_info *info,
     CsrWifiSmeConnectionInfo connectionInfo;
     int r = 0;
 
-    func_enter();
     unifi_trace(priv, UDBG2, "unifi_giwessid\n");
     CHECK_INITED(priv);
 
@@ -1805,7 +1779,6 @@ unifi_giwessid(struct net_device *dev, struct iw_request_info *info,
                 data->length, essid);
     }
 
-    func_exit();
 
     return 0;
 } /* unifi_giwessid() */
@@ -1821,8 +1794,6 @@ unifi_siwrate(struct net_device *dev, struct iw_request_info *info,
     CsrWifiSmeMibConfig mibConfig;
     int r;
 
-    func_enter();
-
     CHECK_INITED(priv);
     unifi_trace(priv, UDBG2, "unifi_siwrate\n");
 
@@ -1863,7 +1834,6 @@ unifi_siwrate(struct net_device *dev, struct iw_request_info *info,
         return r;
     }
 
-    func_exit();
 
     return 0;
 } /* unifi_siwrate() */
@@ -1882,7 +1852,6 @@ unifi_giwrate(struct net_device *dev, struct iw_request_info *info,
     CsrWifiSmeMibConfig mibConfig;
     CsrWifiSmeConnectionStats connectionStats;
 
-    func_enter();
     unifi_trace(priv, UDBG2, "unifi_giwrate\n");
     CHECK_INITED(priv);
 
@@ -1913,8 +1882,6 @@ unifi_giwrate(struct net_device *dev, struct iw_request_info *info,
     args->value = bitrate * 500000;
     args->fixed = !flag;
 
-    func_exit();
-
     return 0;
 } /* unifi_giwrate() */
 
@@ -2081,7 +2048,6 @@ unifi_siwencode(struct net_device *dev, struct iw_request_info *info,
     int privacy = -1;
     CsrWifiSmeKey sme_key;
 
-    func_enter();
     unifi_trace(priv, UDBG2, "unifi_siwencode\n");
 
     CHECK_INITED(priv);
@@ -2236,7 +2202,6 @@ unifi_siwencode(struct net_device *dev, struct iw_request_info *info,
             CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE;
     }
 
-    func_exit_r(rc);
     return convert_sme_error(rc);
 
 } /* unifi_siwencode() */
@@ -2467,7 +2432,6 @@ unifi_siwmlme(struct net_device *dev, struct iw_request_info *info,
     netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev);
     unifi_priv_t *priv = interfacePriv->privPtr;
     struct iw_mlme *mlme = (struct iw_mlme *)extra;
-    func_enter();
 
     unifi_trace(priv, UDBG2, "unifi_siwmlme\n");
     CHECK_INITED(priv);
@@ -2488,11 +2452,9 @@ unifi_siwmlme(struct net_device *dev, struct iw_request_info *info,
             UF_RTNL_LOCK();
             break;
         default:
-            func_exit_r(-EOPNOTSUPP);
             return -EOPNOTSUPP;
     }
 
-    func_exit();
     return 0;
 } /* unifi_siwmlme() */
 
@@ -2529,7 +2491,6 @@ unifi_siwgenie(struct net_device *dev, struct iw_request_info *info,
     unifi_priv_t *priv = interfacePriv->privPtr;
     int len;
 
-    func_enter();
     unifi_trace(priv, UDBG2, "unifi_siwgenie\n");
 
     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
@@ -2548,20 +2509,17 @@ unifi_siwgenie(struct net_device *dev, struct iw_request_info *info,
 
     len = wrqu->data.length;
     if (len == 0) {
-        func_exit();
         return 0;
     }
 
     priv->connection_config.mlmeAssociateReqInformationElements = kmalloc(len, GFP_KERNEL);
     if (priv->connection_config.mlmeAssociateReqInformationElements == NULL) {
-        func_exit();
         return -ENOMEM;
     }
 
     priv->connection_config.mlmeAssociateReqInformationElementsLength = len;
     memcpy( priv->connection_config.mlmeAssociateReqInformationElements, extra, len);
 
-    func_exit();
     return 0;
 } /* unifi_siwgenie() */
 
@@ -2574,7 +2532,6 @@ unifi_giwgenie(struct net_device *dev, struct iw_request_info *info,
     unifi_priv_t *priv = interfacePriv->privPtr;
     int len;
 
-    func_enter();
     unifi_trace(priv, UDBG2, "unifi_giwgenie\n");
 
     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
@@ -2599,7 +2556,6 @@ unifi_giwgenie(struct net_device *dev, struct iw_request_info *info,
     wrqu->data.length = len;
     memcpy(extra, priv->connection_config.mlmeAssociateReqInformationElements, len);
 
-    func_exit();
     return 0;
 } /* unifi_giwgenie() */
 
@@ -2627,7 +2583,6 @@ _unifi_siwauth(struct net_device *dev, struct iw_request_info *info,
     unifi_priv_t *priv = interfacePriv->privPtr;
     CsrWifiSmeAuthModeMask new_auth;
 
-    func_enter();
     unifi_trace(priv, UDBG2, "unifi_siwauth\n");
 
     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
@@ -2848,7 +2803,6 @@ _unifi_siwauth(struct net_device *dev, struct iw_request_info *info,
     }
 
     unifi_trace(priv, UDBG2, "authModeMask = %d", priv->connection_config.authModeMask);
-    func_exit();
 
     return 0;
 } /* _unifi_siwauth() */
@@ -2911,8 +2865,6 @@ _unifi_siwencodeext(struct net_device *dev, struct iw_request_info *info,
     CsrWifiSmeKey sme_key;
     CsrWifiSmeKeyType key_type;
 
-    func_enter();
-
     CHECK_INITED(priv);
 
     if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
@@ -3061,7 +3013,6 @@ _unifi_siwencodeext(struct net_device *dev, struct iw_request_info *info,
         return convert_sme_error(r);
     }
 
-    func_exit();
     return r;
 } /* _unifi_siwencodeext() */
 
diff --git a/drivers/staging/csr/ul_int.c b/drivers/staging/csr/ul_int.c
index 4013d02..0fae6f4 100644
--- a/drivers/staging/csr/ul_int.c
+++ b/drivers/staging/csr/ul_int.c
@@ -12,7 +12,6 @@
  *
  * ***************************************************************************
  */
-#include <linux/version.h>
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_conversions.h"
 #include "unifi_priv.h"
diff --git a/drivers/staging/csr/unifi_event.c b/drivers/staging/csr/unifi_event.c
index c27b23d..e81a998 100644
--- a/drivers/staging/csr/unifi_event.c
+++ b/drivers/staging/csr/unifi_event.c
@@ -376,8 +376,6 @@ unifi_process_receive_event(void *ospriv,
     s16 signal_id;
     u8 pktIndToSme = FALSE, freeBulkData = FALSE;
 
-    func_enter();
-
     unifi_trace(priv, UDBG5, "unifi_process_receive_event: "
                 "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n",
                 CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*0) & 0xFFFF,
@@ -523,7 +521,6 @@ unifi_process_receive_event(void *ospriv,
                                     unifi_net_data_free(priv, (void *)&bulkdata->d[i]);
                                 }
                            }
-                           func_exit();
                            return;
                        }
                    } /* CSR_MA_PACKET_INDICATION_ID */
@@ -573,7 +570,6 @@ unifi_process_receive_event(void *ospriv,
             }
     }
 
-    func_exit();
 } /* unifi_process_receive_event() */
 
 
@@ -587,7 +583,6 @@ void unifi_rx_queue_flush(void *ospriv)
 {
     unifi_priv_t *priv = (unifi_priv_t*)ospriv;
 
-    func_enter();
     unifi_trace(priv, UDBG4, "rx_wq_handler: RdPtr = %d WritePtr =  %d\n",
                 priv->rxSignalBuffer.readPointer,priv->rxSignalBuffer.writePointer);
     if(priv != NULL) {
@@ -605,7 +600,6 @@ void unifi_rx_queue_flush(void *ospriv)
         }
         priv->rxSignalBuffer.readPointer = readPointer;
     }
-    func_exit();
 }
 
 void rx_wq_handler(struct work_struct *work)
@@ -655,7 +649,6 @@ unifi_receive_event(void *ospriv,
     u8 writePointer;
     int i;
     rx_buff_struct_t * rx_buff;
-    func_enter();
 
     unifi_trace(priv, UDBG5, "unifi_receive_event: "
             "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n",
@@ -695,6 +688,5 @@ unifi_receive_event(void *ospriv,
 #else
     unifi_process_receive_event(ospriv, sigdata, siglen, bulkdata);
 #endif
-    func_exit();
 } /* unifi_receive_event() */
 
diff --git a/drivers/staging/csr/unifi_os.h b/drivers/staging/csr/unifi_os.h
index 4e63a94..56a2698 100644
--- a/drivers/staging/csr/unifi_os.h
+++ b/drivers/staging/csr/unifi_os.h
@@ -61,26 +61,6 @@ extern int unifi_debug;
  * etc.
  */
 
-#define func_enter()                                    \
-    do {                                                \
-        if (unifi_debug >= 5) {                         \
-            printk("unifi: => %s\n", __FUNCTION__);     \
-        }                                               \
-    } while (0)
-#define func_exit()                                     \
-    do {                                                \
-        if (unifi_debug >= 5) {                         \
-            printk("unifi: <= %s\n", __FUNCTION__);     \
-        }                                               \
-    } while (0)
-#define func_exit_r(_rc)                                        \
-    do {                                                        \
-        if (unifi_debug >= 5) {                                 \
-            printk("unifi: <= %s %d\n", __FUNCTION__, (int)(_rc));   \
-        }                                                       \
-    } while (0)
-
-
 #define ASSERT(cond)                                            \
     do {                                                            \
         if (!(cond)) {                                              \
@@ -107,9 +87,6 @@ void unifi_trace(void* ospriv, int level, const char *fmt, ...);
 #else
 
 /* Stubs */
-#define func_enter()
-#define func_exit()
-#define func_exit_r(_rc)
 
 #define ASSERT(cond)
 
diff --git a/drivers/staging/csr/unifi_pdu_processing.c b/drivers/staging/csr/unifi_pdu_processing.c
index ae7c8fc..95efc36 100644
--- a/drivers/staging/csr/unifi_pdu_processing.c
+++ b/drivers/staging/csr/unifi_pdu_processing.c
@@ -14,7 +14,6 @@
  * ---------------------------------------------------------------------------
  */
 
-#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/etherdevice.h>
 #include <linux/vmalloc.h>
@@ -409,7 +408,6 @@ CsrResult enque_tx_data_pdu(unifi_priv_t *priv, bulk_data_param_t *bulkdata,
         unifi_error(priv,
                 "Failed to allocate %d bytes for tx packet record\n",
                 sizeof(tx_buffered_packets_t));
-        func_exit();
         return CSR_RESULT_FAILURE;
     }
 
@@ -1117,8 +1115,8 @@ void uf_process_ma_pkt_cfm_for_ap(unifi_priv_t *priv,u16 interfaceTag, const CSR
             staRecord->nullDataHostTag = INVALID_HOST_TAG;
 
             if(pkt_cfm->TransmissionStatus == CSR_TX_RETRY_LIMIT){
-                CsrTime now;
-                CsrTime inactive_time;
+                u32 now;
+                u32 inactive_time;
 
                 unifi_trace(priv, UDBG1, "Nulldata to probe STA ALIVE Failed with retry limit\n");
                 /* Recheck if there is some activity after null data is sent.
@@ -1134,12 +1132,12 @@ void uf_process_ma_pkt_cfm_for_ap(unifi_priv_t *priv,u16 interfaceTag, const CSR
                 if (staRecord->lastActivity > now)
                 {
                     /* simple timer wrap (for 1 wrap) */
-                    inactive_time = CsrTimeAdd((CsrTime)CsrTimeSub(CSR_SCHED_TIME_MAX, staRecord->lastActivity),
+                    inactive_time = CsrTimeAdd((u32)CsrTimeSub(CSR_SCHED_TIME_MAX, staRecord->lastActivity),
                                                now);
                 }
                 else
                 {
-                    inactive_time = (CsrTime)CsrTimeSub(now, staRecord->lastActivity);
+                    inactive_time = (u32)CsrTimeSub(now, staRecord->lastActivity);
                 }
 
                 if (inactive_time >= STA_INACTIVE_TIMEOUT_VAL)
@@ -2024,7 +2022,6 @@ u8 send_multicast_frames(unifi_priv_t *priv, u16 interfaceTag)
     netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
     u32 hostTag = 0xffffffff;
 
-    func_enter();
     if(!isRouterBufferEnabled(priv,UNIFI_TRAFFIC_Q_VO)) {
         while((interfacePriv->dtimActive)&& (buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMulticastOrBroadCastMgtFrames))) {
             buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK);
@@ -2124,7 +2121,6 @@ void uf_process_ma_vif_availibility_ind(unifi_priv_t *priv,u8 *sigdata,
     CSR_RESULT_CODE resultCode = CSR_RC_SUCCESS;
     netInterface_priv_t *interfacePriv;
 
-    func_enter();
     unifi_trace(priv, UDBG3,
             "uf_process_ma_vif_availibility_ind: Process signal 0x%.4X\n",
             *((u16*)sigdata));
@@ -2134,7 +2130,6 @@ void uf_process_ma_vif_availibility_ind(unifi_priv_t *priv,u8 *sigdata,
         unifi_error(priv,
                     "uf_process_ma_vif_availibility_ind: Received unknown signal 0x%.4X.\n",
                     CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata));
-        func_exit();
         return;
     }
     ind = &signal.u.MaVifAvailabilityIndication;
@@ -2369,8 +2364,6 @@ void uf_send_buffered_data_from_ac(unifi_priv_t *priv,
     u8 moreData = FALSE;
     s8 r =0;
 
-    func_enter();
-
     unifi_trace(priv,UDBG2,"uf_send_buffered_data_from_ac :\n");
 
     while(!isRouterBufferEnabled(priv,queue) &&
@@ -2399,8 +2392,6 @@ void uf_send_buffered_data_from_ac(unifi_priv_t *priv,
       }
   }
 
-  func_exit();
-
 }
 
 void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue q)
@@ -2416,7 +2407,6 @@ void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue q)
     if(!((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP) ||
         (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO)))
         return;
-    func_enter();
 
     queue = (q<=3)?q:0;
 
@@ -2451,7 +2441,6 @@ void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue q)
                interfacePriv->dtimActive = FALSE;
            }
         }
-        func_exit();
         return;
     }
     if(priv->pausedStaHandle[queue] > 7) {
@@ -2542,7 +2531,6 @@ void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue q)
      */
     unifi_trace(priv, UDBG4, "csrWifiHipSendBufferedFrames: UAPSD Resume Q=%x\n", queue);
     resume_suspended_uapsd(priv, interfaceTag);
-    func_exit();
 }
 
 
@@ -2770,7 +2758,6 @@ void uf_send_qos_null(unifi_priv_t * priv,u16 interfaceTag, const u8 *da,CSR_PRI
     CSR_RATE transmitRate = 0;
 
 
-    func_enter();
     /* Send a Null Frame to Peer,
      * 32= size of mac header  */
     csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], MAC_HEADER_SIZE + QOS_CONTROL_HEADER_SIZE);
@@ -2823,7 +2810,6 @@ void uf_send_qos_null(unifi_priv_t * priv,u16 interfaceTag, const u8 *da,CSR_PRI
         unifi_net_data_free(priv, &bulkdata.d[0]);
     }
 
-    func_exit();
     return;
 
 }
@@ -2842,7 +2828,6 @@ void uf_send_nulldata(unifi_priv_t * priv,u16 interfaceTag, const u8 *da,CSR_PRI
     CSR_MA_PACKET_REQUEST *req = &signal.u.MaPacketRequest;
     unsigned long lock_flags;
 
-    func_enter();
     /* Send a Null Frame to Peer, size = 24 for MAC header */
     csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], MAC_HEADER_SIZE);
 
@@ -2909,7 +2894,6 @@ void uf_send_nulldata(unifi_priv_t * priv,u16 interfaceTag, const u8 *da,CSR_PRI
         srcStaInfo->nullDataHostTag = INVALID_HOST_TAG;
     }
 
-    func_exit();
     return;
 }
 
@@ -3327,8 +3311,6 @@ void uf_prepare_send_cfm_list_for_queued_pkts(unifi_priv_t * priv,
     struct list_head *placeHolder;
     unsigned long lock_flags;
 
-    func_enter();
-
     spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
 
     /* Search through the list and if confirmation required for any frames,
@@ -3357,7 +3339,6 @@ void uf_prepare_send_cfm_list_for_queued_pkts(unifi_priv_t * priv,
 
     spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags);
 
-    func_exit();
 }
 
 
@@ -3492,11 +3473,11 @@ CsrWifiRouterCtrlStaInfo_t * CsrWifiRouterCtrlGetStationRecordFromHandle(unifi_p
 }
 
 /* Function to do inactivity */
-void uf_check_inactivity(unifi_priv_t *priv, u16 interfaceTag, CsrTime currentTime)
+void uf_check_inactivity(unifi_priv_t *priv, u16 interfaceTag, u32 currentTime)
 {
     u32 i;
     CsrWifiRouterCtrlStaInfo_t *staInfo;
-    CsrTime elapsedTime;    /* Time in microseconds */
+    u32 elapsedTime;    /* Time in microseconds */
     netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
     CsrWifiMacAddress peerMacAddress;
     unsigned long lock_flags;
@@ -3543,8 +3524,8 @@ void uf_check_inactivity(unifi_priv_t *priv, u16 interfaceTag, CsrTime currentTi
 /* Function to update activity of a station */
 void uf_update_sta_activity(unifi_priv_t *priv, u16 interfaceTag, const u8 *peerMacAddress)
 {
-    CsrTime elapsedTime, currentTime;    /* Time in microseconds */
-    CsrTime timeHi;         /* Not used - Time in microseconds */
+    u32 elapsedTime, currentTime;    /* Time in microseconds */
+    u32 timeHi;         /* Not used - Time in microseconds */
     CsrWifiRouterCtrlStaInfo_t *staInfo;
     netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
     unsigned long lock_flags;
@@ -3595,7 +3576,6 @@ void resume_unicast_buffered_frames(unifi_priv_t *priv, u16 interfaceTag)
    int r;
    unsigned long lock_flags;
 
-   func_enter();
    while(!isRouterBufferEnabled(priv,3) &&
                             ((buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMgtFrames))!=NULL)) {
         buffered_pkt->transmissionControl &=
@@ -3672,7 +3652,6 @@ void resume_unicast_buffered_frames(unifi_priv_t *priv, u16 interfaceTag)
           }
        }
     }
-    func_exit();
 }
 void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv,u16 interfaceTag)
 {
@@ -3683,7 +3662,6 @@ void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv,u16 interface
     struct list_head *placeHolder;
     tx_buffered_packets_t *tx_q_item;
 
-    func_enter();
     if (interfacePriv->noOfbroadcastPktQueued) {
 
         /* Update the EOSP to the HEAD of b/c list
@@ -3700,7 +3678,6 @@ void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv,u16 interface
         }
         spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags);
     }
-    func_exit();
 }
 
 /*
diff --git a/drivers/staging/csr/unifi_priv.h b/drivers/staging/csr/unifi_priv.h
index aec8e28..d20d74c 100644
--- a/drivers/staging/csr/unifi_priv.h
+++ b/drivers/staging/csr/unifi_priv.h
@@ -17,7 +17,6 @@
 #ifndef __LINUX_UNIFI_PRIV_H__
 #define __LINUX_UNIFI_PRIV_H__ 1
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -313,7 +312,7 @@ typedef struct CsrWifiRouterCtrlStaInfo_t {
     CSR_CLIENT_TAG nullDataHostTag;
 
     /* Activity timestamps for the station */
-    CsrTime lastActivity;
+    u32 lastActivity;
 
     /* during m/c transmission sp suspended */
     u8 uspSuspend;
@@ -653,7 +652,7 @@ typedef struct {
     bulk_data_param_t bulkdata;
     CSR_SIGNAL signal;
     u16 sn;
-    CsrTime recv_time;
+    u32 recv_time;
 } frame_desc_struct;
 
 typedef struct {
@@ -736,7 +735,7 @@ typedef struct netInterface_priv
     u8 sta_activity_check_enabled;
 
     /* Timestamp when the last inactivity check was done */
-    CsrTime last_inactivity_check;
+    u32 last_inactivity_check;
 
     /*number of multicast or borad cast packets  queued*/
     u16 noOfbroadcastPktQueued;
diff --git a/drivers/staging/csr/unifi_sme.c b/drivers/staging/csr/unifi_sme.c
index ff639d4..7c6c413 100644
--- a/drivers/staging/csr/unifi_sme.c
+++ b/drivers/staging/csr/unifi_sme.c
@@ -78,23 +78,19 @@ sme_log_event(ul_client_t *pcli,
     CsrResult result = CSR_RESULT_SUCCESS;
     int r;
 
-    func_enter();
     /* Just a sanity check */
     if ((signal == NULL) || (signal_len <= 0)) {
-        func_exit();
         return;
     }
 
     priv = uf_find_instance(pcli->instance);
     if (!priv) {
         unifi_error(priv, "sme_log_event: invalid priv\n");
-        func_exit();
         return;
     }
 
     if (priv->smepriv == NULL) {
         unifi_error(priv, "sme_log_event: invalid smepriv\n");
-        func_exit();
         return;
     }
 
@@ -109,7 +105,6 @@ sme_log_event(ul_client_t *pcli,
         if ((unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_DEBUG_STRING_INDICATION_ID) ||
             (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_DEBUG_WORD16_INDICATION_ID))
         {
-            func_exit();
             return;
         }
         if (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_INDICATION_ID)
@@ -171,7 +166,6 @@ sme_log_event(ul_client_t *pcli,
             if (interfaceTag >= CSR_WIFI_NUM_INTERFACES)
             {
                 unifi_error(priv, "Bad MA_PACKET_CONFIRM interfaceTag %d\n", interfaceTag);
-                func_exit();
                 return;
             }
 
@@ -219,7 +213,6 @@ sme_log_event(ul_client_t *pcli,
                 } else {
                     unifi_trace(priv, UDBG1, "%s: M4 received from netdevice\n", __FUNCTION__);
                 }
-                func_exit();
                 return;
             }
         }
@@ -248,7 +241,6 @@ sme_log_event(ul_client_t *pcli,
             dataref1.length, dataref1.data,
             dataref2.length, dataref2.data);
 
-    func_exit();
 } /* sme_log_event() */
 
 
@@ -1158,8 +1150,6 @@ uf_send_m4_ready_wq(struct work_struct *work)
     CsrWifiMacAddress peer;
     unsigned long flags;
 
-    func_enter();
-
     /* The peer address was stored in the signal */
     spin_lock_irqsave(&priv->m4_lock, flags);
     memcpy(peer.a, req->Ra.x, sizeof(peer.a));
@@ -1171,8 +1161,6 @@ uf_send_m4_ready_wq(struct work_struct *work)
 	unifi_trace(priv, UDBG1, "M4ReadyToSendInd sent for peer %pMF\n",
 		peer.a);
 
-    func_exit();
-
 } /* uf_send_m4_ready_wq() */
 
 #if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
@@ -1204,8 +1192,6 @@ void uf_send_pkt_to_encrypt(struct work_struct *work)
 
     if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) {
 
-        func_enter();
-
         pktBulkDataLength = interfacePriv->wapi_unicast_bulk_data.data_length;
 
         if (pktBulkDataLength > 0) {
@@ -1231,7 +1217,6 @@ void uf_send_pkt_to_encrypt(struct work_struct *work)
 
         kfree(pktBulkData); /* Would have been copied over by the SME Handler */
 
-        func_exit();
     } else {
 	    unifi_warning(priv, "uf_send_pkt_to_encrypt() is NOT applicable for interface mode - %d\n",interfacePriv->interfaceMode);
     }
diff --git a/drivers/staging/csr/unifi_wext.h b/drivers/staging/csr/unifi_wext.h
index 6834c43..beba089 100644
--- a/drivers/staging/csr/unifi_wext.h
+++ b/drivers/staging/csr/unifi_wext.h
@@ -16,7 +16,6 @@
 #define __LINUX_UNIFI_WEXT_H__ 1
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <net/iw_handler.h>
 #include "csr_wifi_sme_prim.h"
 
diff --git a/drivers/staging/cxt1e1/musycc.c b/drivers/staging/cxt1e1/musycc.c
index ba721c6..b2cc68a 100644
--- a/drivers/staging/cxt1e1/musycc.c
+++ b/drivers/staging/cxt1e1/musycc.c
@@ -55,26 +55,26 @@ extern int  cxt1e1_max_mtu;
 extern int  max_rxdesc_used;
 extern int  max_txdesc_used;
 extern ci_t *CI;                /* dummy pointr to board ZEROE's data - DEBUG
-                                 * USAGE */
+				 * USAGE */
 
 
 /*******************************************************************/
 /* forward references */
-void        c4_fifo_free (mpi_t *, int);
-void        c4_wk_chan_restart (mch_t *);
-void        musycc_bh_tx_eom (mpi_t *, int);
-int         musycc_chan_up (ci_t *, int);
-status_t __init musycc_init (ci_t *);
-STATIC void __init musycc_init_port (mpi_t *);
-void        musycc_intr_bh_tasklet (ci_t *);
-void        musycc_serv_req (mpi_t *, u_int32_t);
-void        musycc_update_timeslots (mpi_t *);
+void        c4_fifo_free(mpi_t *, int);
+void        c4_wk_chan_restart(mch_t *);
+void        musycc_bh_tx_eom(mpi_t *, int);
+int         musycc_chan_up(ci_t *, int);
+status_t __init musycc_init(ci_t *);
+STATIC void __init musycc_init_port(mpi_t *);
+void        musycc_intr_bh_tasklet(ci_t *);
+void        musycc_serv_req(mpi_t *, u_int32_t);
+void        musycc_update_timeslots(mpi_t *);
 
 /*******************************************************************/
 
 #if 1
 STATIC int
-musycc_dump_rxbuffer_ring (mch_t * ch, int lockit)
+musycc_dump_rxbuffer_ring(mch_t * ch, int lockit)
 {
     struct mdesc *m;
     unsigned long flags = 0;
@@ -83,71 +83,64 @@ musycc_dump_rxbuffer_ring (mch_t * ch, int lockit)
     int         n;
 
     if (lockit)
-    {
-        spin_lock_irqsave (&ch->ch_rxlock, flags);
-    }
+	spin_lock_irqsave(&ch->ch_rxlock, flags);
     if (ch->rxd_num == 0)
-    {
-        pr_info("  ZERO receive buffers allocated for this channel.");
-    } else
-    {
-        FLUSH_MEM_READ ();
-        m = &ch->mdr[ch->rxix_irq_srv];
-        for (n = ch->rxd_num; n; n--)
-        {
-            status = le32_to_cpu (m->status);
-            {
-                pr_info("%c  %08lx[%2d]: sts %08x (%c%c%c%c:%d.) Data [%08x] Next [%08x]\n",
-                        (m == &ch->mdr[ch->rxix_irq_srv]) ? 'F' : ' ',
-                        (unsigned long) m, n,
-                        status,
-                        m->data ? (status & HOST_RX_OWNED ? 'H' : 'M') : '-',
-                        status & POLL_DISABLED ? 'P' : '-',
-                        status & EOBIRQ_ENABLE ? 'b' : '-',
-                        status & EOMIRQ_ENABLE ? 'm' : '-',
-                        status & LENGTH_MASK,
-                        le32_to_cpu (m->data), le32_to_cpu (m->next));
+	pr_info("  ZERO receive buffers allocated for this channel.");
+    else {
+	FLUSH_MEM_READ();
+	m = &ch->mdr[ch->rxix_irq_srv];
+	for (n = ch->rxd_num; n; n--) {
+	    status = le32_to_cpu(m->status);
+	    {
+		pr_info("%c  %08lx[%2d]: sts %08x (%c%c%c%c:%d.) Data [%08x] Next [%08x]\n",
+			(m == &ch->mdr[ch->rxix_irq_srv]) ? 'F' : ' ',
+			(unsigned long) m, n,
+			status,
+			m->data ? (status & HOST_RX_OWNED ? 'H' : 'M') : '-',
+			status & POLL_DISABLED ? 'P' : '-',
+			status & EOBIRQ_ENABLE ? 'b' : '-',
+			status & EOMIRQ_ENABLE ? 'm' : '-',
+			status & LENGTH_MASK,
+			le32_to_cpu(m->data), le32_to_cpu(m->next));
 #ifdef RLD_DUMP_BUFDATA
-                {
-                    u_int32_t  *dp;
-                    int         len = status & LENGTH_MASK;
+		{
+		    u_int32_t  *dp;
+		    int         len = status & LENGTH_MASK;
 
 #if 1
-                    if (m->data && (status & HOST_RX_OWNED))
+		    if (m->data && (status & HOST_RX_OWNED))
 #else
-                    if (m->data)    /* always dump regardless of valid RX
-                                     * data */
+		    if (m->data)    /* always dump regardless of valid RX
+				     * data */
 #endif
-                    {
-                        dp = (u_int32_t *) OS_phystov ((void *) (le32_to_cpu (m->data)));
-                        if (len >= 0x10)
-                            pr_info("    %x[%x]: %08X %08X %08X %08x\n", (u_int32_t) dp, len,
-                                    *dp, *(dp + 1), *(dp + 2), *(dp + 3));
-                        else if (len >= 0x08)
-                            pr_info("    %x[%x]: %08X %08X\n", (u_int32_t) dp, len,
-                                    *dp, *(dp + 1));
-                        else
-                            pr_info("    %x[%x]: %08X\n", (u_int32_t) dp, len, *dp);
-                    }
-                }
+		    {
+			dp = (u_int32_t *) OS_phystov((void *) (le32_to_cpu(m->data)));
+			if (len >= 0x10)
+			    pr_info("    %x[%x]: %08X %08X %08X %08x\n", (u_int32_t) dp, len,
+				    *dp, *(dp + 1), *(dp + 2), *(dp + 3));
+			else if (len >= 0x08)
+			    pr_info("    %x[%x]: %08X %08X\n", (u_int32_t) dp, len,
+				    *dp, *(dp + 1));
+			else
+			    pr_info("    %x[%x]: %08X\n", (u_int32_t) dp, len, *dp);
+		    }
+		}
 #endif
-            }
-            m = m->snext;
-        }
+	    }
+	    m = m->snext;
+	}
     }                               /* -for- */
     pr_info("\n");
 
     if (lockit)
-    {
-        spin_unlock_irqrestore (&ch->ch_rxlock, flags);
-    }
+	spin_unlock_irqrestore(&ch->ch_rxlock, flags);
     return 0;
 }
 #endif
 
 #if 1
 STATIC int
-musycc_dump_txbuffer_ring (mch_t * ch, int lockit)
+musycc_dump_txbuffer_ring(mch_t * ch, int lockit)
 {
     struct mdesc *m;
     unsigned long flags = 0;
@@ -155,60 +148,52 @@ musycc_dump_txbuffer_ring (mch_t * ch, int lockit)
     int         n;
 
     if (lockit)
-    {
-        spin_lock_irqsave (&ch->ch_txlock, flags);
-    }
+	spin_lock_irqsave(&ch->ch_txlock, flags);
     if (ch->txd_num == 0)
-    {
-        pr_info("  ZERO transmit buffers allocated for this channel.");
-    } else
-    {
-        FLUSH_MEM_READ ();
-        m = ch->txd_irq_srv;
-        for (n = ch->txd_num; n; n--)
-        {
-            status = le32_to_cpu (m->status);
-            {
-                pr_info("%c%c %08lx[%2d]: sts %08x (%c%c%c%c:%d.) Data [%08x] Next [%08x]\n",
-                        (m == ch->txd_usr_add) ? 'F' : ' ',
-                        (m == ch->txd_irq_srv) ? 'L' : ' ',
-                        (unsigned long) m, n,
-                        status,
-                     m->data ? (status & MUSYCC_TX_OWNED ? 'M' : 'H') : '-',
-                        status & POLL_DISABLED ? 'P' : '-',
-                        status & EOBIRQ_ENABLE ? 'b' : '-',
-                        status & EOMIRQ_ENABLE ? 'm' : '-',
-                        status & LENGTH_MASK,
-                        le32_to_cpu (m->data), le32_to_cpu (m->next));
+	pr_info("  ZERO transmit buffers allocated for this channel.");
+    else {
+	FLUSH_MEM_READ();
+	m = ch->txd_irq_srv;
+	for (n = ch->txd_num; n; n--) {
+	    status = le32_to_cpu(m->status);
+	    {
+		pr_info("%c%c %08lx[%2d]: sts %08x (%c%c%c%c:%d.) Data [%08x] Next [%08x]\n",
+			(m == ch->txd_usr_add) ? 'F' : ' ',
+			(m == ch->txd_irq_srv) ? 'L' : ' ',
+			(unsigned long) m, n,
+			status,
+		     m->data ? (status & MUSYCC_TX_OWNED ? 'M' : 'H') : '-',
+			status & POLL_DISABLED ? 'P' : '-',
+			status & EOBIRQ_ENABLE ? 'b' : '-',
+			status & EOMIRQ_ENABLE ? 'm' : '-',
+			status & LENGTH_MASK,
+			le32_to_cpu(m->data), le32_to_cpu(m->next));
 #ifdef RLD_DUMP_BUFDATA
-                {
-                    u_int32_t  *dp;
-                    int         len = status & LENGTH_MASK;
-
-                    if (m->data)
-                    {
-                        dp = (u_int32_t *) OS_phystov ((void *) (le32_to_cpu (m->data)));
-                        if (len >= 0x10)
-                            pr_info("    %x[%x]: %08X %08X %08X %08x\n", (u_int32_t) dp, len,
-                                    *dp, *(dp + 1), *(dp + 2), *(dp + 3));
-                        else if (len >= 0x08)
-                            pr_info("    %x[%x]: %08X %08X\n", (u_int32_t) dp, len,
-                                    *dp, *(dp + 1));
-                        else
-                            pr_info("    %x[%x]: %08X\n", (u_int32_t) dp, len, *dp);
-                    }
-                }
+		{
+		    u_int32_t  *dp;
+		    int         len = status & LENGTH_MASK;
+
+		    if (m->data) {
+			dp = (u_int32_t *) OS_phystov((void *) (le32_to_cpu(m->data)));
+			if (len >= 0x10)
+			    pr_info("    %x[%x]: %08X %08X %08X %08x\n", (u_int32_t) dp, len,
+				    *dp, *(dp + 1), *(dp + 2), *(dp + 3));
+			else if (len >= 0x08)
+			    pr_info("    %x[%x]: %08X %08X\n", (u_int32_t) dp, len,
+				    *dp, *(dp + 1));
+			else
+			    pr_info("    %x[%x]: %08X\n", (u_int32_t) dp, len, *dp);
+		    }
+		}
 #endif
-            }
-            m = m->snext;
-        }
+	    }
+	    m = m->snext;
+	}
     }                               /* -for- */
     pr_info("\n");
 
     if (lockit)
-    {
-        spin_unlock_irqrestore (&ch->ch_txlock, flags);
-    }
+	spin_unlock_irqrestore(&ch->ch_txlock, flags);
     return 0;
 }
 #endif
@@ -220,58 +205,55 @@ musycc_dump_txbuffer_ring (mch_t * ch, int lockit)
  */
 
 status_t
-musycc_dump_ring (ci_t * ci, unsigned int chan)
+musycc_dump_ring(ci_t * ci, unsigned int chan)
 {
     mch_t      *ch;
 
     if (chan >= MAX_CHANS_USED)
+	return SBE_DRVR_FAIL;       /* E2BIG */
     {
-        return SBE_DRVR_FAIL;       /* E2BIG */
-    }
-    {
-        int         bh;
-
-        bh = atomic_read (&ci->bh_pending);
-        pr_info(">> bh_pend %d [%d] ihead %d itail %d [%d] th_cnt %d bh_cnt %d wdcnt %d note %d\n",
-                bh, max_bh, ci->iqp_headx, ci->iqp_tailx, max_intcnt,
-                ci->intlog.drvr_intr_thcount,
-                ci->intlog.drvr_intr_bhcount,
-                ci->wdcount, ci->wd_notify);
-        max_bh = 0;                 /* reset counter */
-        max_intcnt = 0;             /* reset counter */
+	int         bh;
+
+	bh = atomic_read(&ci->bh_pending);
+	pr_info(">> bh_pend %d [%d] ihead %d itail %d [%d] th_cnt %d bh_cnt %d wdcnt %d note %d\n",
+		bh, max_bh, ci->iqp_headx, ci->iqp_tailx, max_intcnt,
+		ci->intlog.drvr_intr_thcount,
+		ci->intlog.drvr_intr_bhcount,
+		ci->wdcount, ci->wd_notify);
+	max_bh = 0;                 /* reset counter */
+	max_intcnt = 0;             /* reset counter */
     }
 
-    if (!(ch = sd_find_chan (dummy, chan)))
-    {
-        pr_info(">> musycc_dump_ring: channel %d not up.\n", chan);
-        return ENOENT;
+    if (!(ch = sd_find_chan(dummy, chan))) {
+	pr_info(">> musycc_dump_ring: channel %d not up.\n", chan);
+	return ENOENT;
     }
     pr_info(">> CI %p CHANNEL %3d @ %p: state %x status/p %x/%x\n", ci, chan, ch, ch->state,
-            ch->status, ch->p.status);
+	    ch->status, ch->p.status);
     pr_info("--------------------------------\nTX Buffer Ring - Channel %d, txd_num %d. (bd/ch pend %d %d), TXD required %d, txpkt %lu\n",
-            chan, ch->txd_num,
-            (u_int32_t) atomic_read (&ci->tx_pending), (u_int32_t) atomic_read (&ch->tx_pending), ch->txd_required, ch->s.tx_packets);
+	    chan, ch->txd_num,
+	    (u_int32_t) atomic_read(&ci->tx_pending), (u_int32_t) atomic_read(&ch->tx_pending), ch->txd_required, ch->s.tx_packets);
     pr_info("++ User 0x%p IRQ_SRV 0x%p USR_ADD 0x%p QStopped %x, start_tx %x tx_full %d txd_free %d mode %x\n",
-            ch->user, ch->txd_irq_srv, ch->txd_usr_add,
-            sd_queue_stopped (ch->user),
-            ch->ch_start_tx, ch->tx_full, ch->txd_free, ch->p.chan_mode);
-    musycc_dump_txbuffer_ring (ch, 1);
+	    ch->user, ch->txd_irq_srv, ch->txd_usr_add,
+	    sd_queue_stopped(ch->user),
+	    ch->ch_start_tx, ch->tx_full, ch->txd_free, ch->p.chan_mode);
+    musycc_dump_txbuffer_ring(ch, 1);
     pr_info("RX Buffer Ring - Channel %d, rxd_num %d. IRQ_SRV[%d] 0x%p, start_rx %x rxpkt %lu\n",
-            chan, ch->rxd_num, ch->rxix_irq_srv,
-            &ch->mdr[ch->rxix_irq_srv], ch->ch_start_rx, ch->s.rx_packets);
-    musycc_dump_rxbuffer_ring (ch, 1);
+	    chan, ch->rxd_num, ch->rxix_irq_srv,
+	    &ch->mdr[ch->rxix_irq_srv], ch->ch_start_rx, ch->s.rx_packets);
+    musycc_dump_rxbuffer_ring(ch, 1);
 
     return SBE_DRVR_SUCCESS;
 }
 
 
 status_t
-musycc_dump_rings (ci_t * ci, unsigned int start_chan)
+musycc_dump_rings(ci_t * ci, unsigned int start_chan)
 {
     unsigned int chan;
 
     for (chan = start_chan; chan < (start_chan + 5); chan++)
-        musycc_dump_ring (ci, chan);
+	musycc_dump_ring(ci, chan);
     return SBE_DRVR_SUCCESS;
 }
 
@@ -282,7 +264,7 @@ musycc_dump_rings (ci_t * ci, unsigned int start_chan)
  */
 
 void
-musycc_init_mdt (mpi_t * pi)
+musycc_init_mdt(mpi_t * pi)
 {
     u_int32_t  *addr, cfg;
     int         i;
@@ -299,56 +281,50 @@ musycc_init_mdt (mpi_t * pi)
     cfg = CFG_CH_FLAG_7E << IDLE_CODE;
 
     for (i = 0; i < 32; addr++, i++)
-    {
-        pci_write_32 (addr, cfg);
-    }
+	pci_write_32(addr, cfg);
 }
 
 
 /* Set TX thp to the next unprocessed md */
 
 void
-musycc_update_tx_thp (mch_t * ch)
+musycc_update_tx_thp(mch_t * ch)
 {
     struct mdesc *md;
     unsigned long flags;
 
-    spin_lock_irqsave (&ch->ch_txlock, flags);
-    while (1)
-    {
-        md = ch->txd_irq_srv;
-        FLUSH_MEM_READ ();
-        if (!md->data)
-        {
-            /* No MDs with buffers to process */
-            spin_unlock_irqrestore (&ch->ch_txlock, flags);
-            return;
-        }
-        if ((le32_to_cpu (md->status)) & MUSYCC_TX_OWNED)
-        {
-            /* this is the MD to restart TX with */
-            break;
-        }
-        /*
-         * Otherwise, we have a valid, host-owned message descriptor which
-         * has been successfully transmitted and whose buffer can be freed,
-         * so... process this MD, it's owned by the host.  (This might give
-         * as a new, updated txd_irq_srv.)
-         */
-        musycc_bh_tx_eom (ch->up, ch->gchan);
+    spin_lock_irqsave(&ch->ch_txlock, flags);
+    while (1) {
+	md = ch->txd_irq_srv;
+	FLUSH_MEM_READ();
+	if (!md->data) {
+	    /* No MDs with buffers to process */
+	    spin_unlock_irqrestore(&ch->ch_txlock, flags);
+	    return;
+	}
+	if ((le32_to_cpu(md->status)) & MUSYCC_TX_OWNED) {
+	    /* this is the MD to restart TX with */
+	    break;
+	}
+	/*
+	 * Otherwise, we have a valid, host-owned message descriptor which
+	 * has been successfully transmitted and whose buffer can be freed,
+	 * so... process this MD, it's owned by the host.  (This might give
+	 * as a new, updated txd_irq_srv.)
+	 */
+	musycc_bh_tx_eom(ch->up, ch->gchan);
     }
     md = ch->txd_irq_srv;
-    ch->up->regram->thp[ch->gchan] = cpu_to_le32 (OS_vtophys (md));
-    FLUSH_MEM_WRITE ();
-
-    if (ch->tx_full)
-    {
-        ch->tx_full = 0;
-        ch->txd_required = 0;
-        sd_enable_xmit (ch->user);  /* re-enable to catch flow controlled
-                                     * channel */
+    ch->up->regram->thp[ch->gchan] = cpu_to_le32(OS_vtophys(md));
+    FLUSH_MEM_WRITE();
+
+    if (ch->tx_full) {
+	ch->tx_full = 0;
+	ch->txd_required = 0;
+	sd_enable_xmit(ch->user);  /* re-enable to catch flow controlled
+				     * channel */
     }
-    spin_unlock_irqrestore (&ch->ch_txlock, flags);
+    spin_unlock_irqrestore(&ch->ch_txlock, flags);
 
 #ifdef RLD_TRANS_DEBUG
     pr_info("++ musycc_update_tx_thp[%d]: setting thp = %p, sts %x\n", ch->channum, md, md->status);
@@ -366,7 +342,7 @@ musycc_update_tx_thp (mch_t * ch)
  */
 
 void
-musycc_wq_chan_restart (void *arg)      /* channel private structure */
+musycc_wq_chan_restart(void *arg)      /* channel private structure */
 {
     mch_t      *ch;
     mpi_t      *pi;
@@ -380,7 +356,7 @@ musycc_wq_chan_restart (void *arg)      /* channel private structure */
 
 #ifdef RLD_TRANS_DEBUG
     pr_info("wq_chan_restart[%d]: start_RT[%d/%d] status %x\n",
-            ch->channum, ch->ch_start_rx, ch->ch_start_tx, ch->status);
+	    ch->channum, ch->ch_start_rx, ch->ch_start_tx, ch->status);
 
 #endif
 
@@ -388,80 +364,74 @@ musycc_wq_chan_restart (void *arg)      /* channel private structure */
     /** check for RX restart request **/
     /**********************************/
 
-    if ((ch->ch_start_rx) && (ch->status & RX_ENABLED))
-    {
+    if ((ch->ch_start_rx) && (ch->status & RX_ENABLED)) {
 
-        ch->ch_start_rx = 0;
+	ch->ch_start_rx = 0;
 #if defined(RLD_TRANS_DEBUG) || defined(RLD_RXACT_DEBUG)
-        {
-            static int  hereb4 = 7;
+	{
+	    static int  hereb4 = 7;
 
-            if (hereb4)             /* RLD DEBUG */
-            {
-                hereb4--;
+	    if (hereb4) {            /* RLD DEBUG */
+		hereb4--;
 #ifdef RLD_TRANS_DEBUG
-                md = &ch->mdr[ch->rxix_irq_srv];
-                pr_info("++ musycc_wq_chan_restart[%d] CHAN RX ACTIVATE: rxix_irq_srv %d, md %p sts %x, rxpkt %lu\n",
-                ch->channum, ch->rxix_irq_srv, md, le32_to_cpu (md->status),
-                        ch->s.rx_packets);
+		md = &ch->mdr[ch->rxix_irq_srv];
+		pr_info("++ musycc_wq_chan_restart[%d] CHAN RX ACTIVATE: rxix_irq_srv %d, md %p sts %x, rxpkt %lu\n",
+		ch->channum, ch->rxix_irq_srv, md, le32_to_cpu(md->status),
+			ch->s.rx_packets);
 #elif defined(RLD_RXACT_DEBUG)
-                md = &ch->mdr[ch->rxix_irq_srv];
-                pr_info("++ musycc_wq_chan_restart[%d] CHAN RX ACTIVATE: rxix_irq_srv %d, md %p sts %x, rxpkt %lu\n",
-                ch->channum, ch->rxix_irq_srv, md, le32_to_cpu (md->status),
-                        ch->s.rx_packets);
-                musycc_dump_rxbuffer_ring (ch, 1);      /* RLD DEBUG */
+		md = &ch->mdr[ch->rxix_irq_srv];
+		pr_info("++ musycc_wq_chan_restart[%d] CHAN RX ACTIVATE: rxix_irq_srv %d, md %p sts %x, rxpkt %lu\n",
+		ch->channum, ch->rxix_irq_srv, md, le32_to_cpu(md->status),
+			ch->s.rx_packets);
+		musycc_dump_rxbuffer_ring(ch, 1);      /* RLD DEBUG */
 #endif
-            }
-        }
+	    }
+	}
 #endif
-        musycc_serv_req (pi, SR_CHANNEL_ACTIVATE | SR_RX_DIRECTION | ch->gchan);
+	musycc_serv_req(pi, SR_CHANNEL_ACTIVATE | SR_RX_DIRECTION | ch->gchan);
     }
     /**********************************/
     /** check for TX restart request **/
     /**********************************/
 
-    if ((ch->ch_start_tx) && (ch->status & TX_ENABLED))
-    {
-        /* find next unprocessed message, then set TX thp to it */
-        musycc_update_tx_thp (ch);
+    if ((ch->ch_start_tx) && (ch->status & TX_ENABLED)) {
+	/* find next unprocessed message, then set TX thp to it */
+	musycc_update_tx_thp(ch);
 
 #if 0
-        spin_lock_irqsave (&ch->ch_txlock, flags);
+	spin_lock_irqsave(&ch->ch_txlock, flags);
 #endif
-        md = ch->txd_irq_srv;
-        if (!md)
-        {
+	md = ch->txd_irq_srv;
+	if (!md) {
 #ifdef RLD_TRANS_DEBUG
-            pr_info("-- musycc_wq_chan_restart[%d]: WARNING, starting NULL md\n", ch->channum);
+	    pr_info("-- musycc_wq_chan_restart[%d]: WARNING, starting NULL md\n", ch->channum);
 #endif
 #if 0
-            spin_unlock_irqrestore (&ch->ch_txlock, flags);
+	    spin_unlock_irqrestore(&ch->ch_txlock, flags);
 #endif
-        } else if (md->data && ((le32_to_cpu (md->status)) & MUSYCC_TX_OWNED))
-        {
-            ch->ch_start_tx = 0;
+	} else if (md->data && ((le32_to_cpu(md->status)) & MUSYCC_TX_OWNED)) {
+	    ch->ch_start_tx = 0;
 #if 0
-            spin_unlock_irqrestore (&ch->ch_txlock, flags);   /* allow interrupts for service request */
+	    spin_unlock_irqrestore(&ch->ch_txlock, flags);   /* allow interrupts for service request */
 #endif
 #ifdef RLD_TRANS_DEBUG
-            pr_info("++ musycc_wq_chan_restart() CHAN TX ACTIVATE: chan %d txd_irq_srv %p = sts %x, txpkt %lu\n",
-                    ch->channum, ch->txd_irq_srv, ch->txd_irq_srv->status, ch->s.tx_packets);
+	    pr_info("++ musycc_wq_chan_restart() CHAN TX ACTIVATE: chan %d txd_irq_srv %p = sts %x, txpkt %lu\n",
+		    ch->channum, ch->txd_irq_srv, ch->txd_irq_srv->status, ch->s.tx_packets);
 #endif
-            musycc_serv_req (pi, SR_CHANNEL_ACTIVATE | SR_TX_DIRECTION | ch->gchan);
-        }
+	    musycc_serv_req(pi, SR_CHANNEL_ACTIVATE | SR_TX_DIRECTION | ch->gchan);
+	}
 #ifdef RLD_RESTART_DEBUG
-        else
-        {
-            /* retain request to start until retried and we have data to xmit */
-            pr_info("-- musycc_wq_chan_restart[%d]: DELAYED due to md %p sts %x data %x, start_tx %x\n",
-                    ch->channum, md,
-                    le32_to_cpu (md->status),
-                    le32_to_cpu (md->data), ch->ch_start_tx);
-            musycc_dump_txbuffer_ring (ch, 0);
+	else {
+	    /* retain request to start until retried and we have data to xmit */
+	    pr_info("-- musycc_wq_chan_restart[%d]: DELAYED due to md %p sts %x data %x, start_tx %x\n",
+		    ch->channum, md,
+		    le32_to_cpu(md->status),
+		    le32_to_cpu(md->data), ch->ch_start_tx);
+	    musycc_dump_txbuffer_ring(ch, 0);
 #if 0
-            spin_unlock_irqrestore (&ch->ch_txlock, flags);   /* allow interrupts for service request */
+	    spin_unlock_irqrestore(&ch->ch_txlock, flags);   /* allow interrupts for service request */
 #endif
-        }
+	}
 #endif
     }
 }
@@ -473,41 +443,41 @@ musycc_wq_chan_restart (void *arg)      /* channel private structure */
   */
 
 void
-musycc_chan_restart (mch_t * ch)
+musycc_chan_restart(mch_t * ch)
 {
 #ifdef RLD_RESTART_DEBUG
     pr_info("++ musycc_chan_restart[%d]: txd_irq_srv @ %p = sts %x\n",
-            ch->channum, ch->txd_irq_srv, ch->txd_irq_srv->status);
+	    ch->channum, ch->txd_irq_srv, ch->txd_irq_srv->status);
 #endif
 
     /* 2.6 - find next unprocessed message, then set TX thp to it */
 #ifdef RLD_RESTART_DEBUG
     pr_info(">> musycc_chan_restart: scheduling Chan %x workQ @ %p\n", ch->channum, &ch->ch_work);
 #endif
-    c4_wk_chan_restart (ch);        /* work queue mechanism fires off: Ref:
-                                     * musycc_wq_chan_restart () */
+    c4_wk_chan_restart(ch);        /* work queue mechanism fires off: Ref:
+				     * musycc_wq_chan_restart () */
 
 }
 
 
 void
-rld_put_led (mpi_t * pi, u_int32_t ledval)
+rld_put_led(mpi_t * pi, u_int32_t ledval)
 {
     static u_int32_t led = 0;
 
     if (ledval == 0)
-        led = 0;
+	led = 0;
     else
-        led |= ledval;
+	led |= ledval;
 
-    pci_write_32 ((u_int32_t *) &pi->up->cpldbase->leds, led);  /* RLD DEBUG TRANHANG */
+    pci_write_32((u_int32_t *) &pi->up->cpldbase->leds, led);  /* RLD DEBUG TRANHANG */
 }
 
 
 #define MUSYCC_SR_RETRY_CNT  9
 
 void
-musycc_serv_req (mpi_t * pi, u_int32_t req)
+musycc_serv_req(mpi_t * pi, u_int32_t req)
 {
     volatile u_int32_t r;
     int         rcnt;
@@ -520,49 +490,46 @@ musycc_serv_req (mpi_t * pi, u_int32_t req)
      * acknowledged."
      */
 
-    SD_SEM_TAKE (&pi->sr_sem_busy, "serv");     /* only 1 thru here, per
-                                                 * group */
+    SD_SEM_TAKE(&pi->sr_sem_busy, "serv");     /* only 1 thru here, per
+						 * group */
 
-    if (pi->sr_last == req)
-    {
+    if (pi->sr_last == req) {
 #ifdef RLD_TRANS_DEBUG
-        pr_info(">> same SR, Port %d Req %x\n", pi->portnum, req);
+	pr_info(">> same SR, Port %d Req %x\n", pi->portnum, req);
 #endif
 
-        /*
-         * The most likely repeated request is the channel activation command
-         * which follows the occurrence of a Transparent mode TX ONR or a
-         * BUFF error.  If the previous command was a CHANNEL ACTIVATE,
-         * precede it with a NOOP command in order maintain coherent control
-         * of this current (re)ACTIVATE.
-         */
-
-        r = (pi->sr_last & ~SR_GCHANNEL_MASK);
-        if ((r == (SR_CHANNEL_ACTIVATE | SR_TX_DIRECTION)) ||
-            (r == (SR_CHANNEL_ACTIVATE | SR_RX_DIRECTION)))
-        {
+	/*
+	 * The most likely repeated request is the channel activation command
+	 * which follows the occurrence of a Transparent mode TX ONR or a
+	 * BUFF error.  If the previous command was a CHANNEL ACTIVATE,
+	 * precede it with a NOOP command in order maintain coherent control
+	 * of this current (re)ACTIVATE.
+	 */
+
+	r = (pi->sr_last & ~SR_GCHANNEL_MASK);
+	if ((r == (SR_CHANNEL_ACTIVATE | SR_TX_DIRECTION)) ||
+	    (r == (SR_CHANNEL_ACTIVATE | SR_RX_DIRECTION))) {
 #ifdef RLD_TRANS_DEBUG
-            pr_info(">> same CHAN ACT SR, Port %d Req %x => issue SR_NOOP CMD\n", pi->portnum, req);
+	    pr_info(">> same CHAN ACT SR, Port %d Req %x => issue SR_NOOP CMD\n", pi->portnum, req);
 #endif
-            SD_SEM_GIVE (&pi->sr_sem_busy);     /* allow this next request */
-            musycc_serv_req (pi, SR_NOOP);
-            SD_SEM_TAKE (&pi->sr_sem_busy, "serv");     /* relock & continue w/
-                                                         * original req */
-        } else if (req == SR_NOOP)
-        {
-            /* no need to issue back-to-back SR_NOOP commands at this time */
+	    SD_SEM_GIVE(&pi->sr_sem_busy);     /* allow this next request */
+	    musycc_serv_req(pi, SR_NOOP);
+	    SD_SEM_TAKE(&pi->sr_sem_busy, "serv");     /* relock & continue w/
+							 * original req */
+	} else if (req == SR_NOOP) {
+	    /* no need to issue back-to-back SR_NOOP commands at this time */
 #ifdef RLD_TRANS_DEBUG
-            pr_info(">> same Port SR_NOOP skipped, Port %d\n", pi->portnum);
+	    pr_info(">> same Port SR_NOOP skipped, Port %d\n", pi->portnum);
 #endif
-            SD_SEM_GIVE (&pi->sr_sem_busy);     /* allow this next request */
-            return;
-        }
+	    SD_SEM_GIVE(&pi->sr_sem_busy);     /* allow this next request */
+	    return;
+	}
     }
     rcnt = 0;
     pi->sr_last = req;
 rewrite:
-    pci_write_32 ((u_int32_t *) &pi->reg->srd, req);
-    FLUSH_MEM_WRITE ();
+    pci_write_32((u_int32_t *) &pi->reg->srd, req);
+    FLUSH_MEM_WRITE();
 
     /*
      * Per MUSYCC Manual, Section 6.1,2 - "When writing an SCR service
@@ -572,120 +539,108 @@ rewrite:
      * the host follow any SCR write with another operation which reads from
      * the same address."
      */
-    r = pci_read_32 ((u_int32_t *) &pi->reg->srd);      /* adhere to write
-                                                         * timing imposition */
-
-
-    if ((r != req) && (req != SR_CHIP_RESET) && (++rcnt <= MUSYCC_SR_RETRY_CNT))
-    {
-        if (cxt1e1_log_level >= LOG_MONITOR)
-            pr_info("%s: %d - reissue srv req/last %x/%x (hdw reads %x), Chan %d.\n",
-                    pi->up->devname, rcnt, req, pi->sr_last, r,
-                    (pi->portnum * MUSYCC_NCHANS) + (req & 0x1f));
-        OS_uwait_dummy ();          /* this delay helps reduce reissue counts
-                                     * (reason not yet researched) */
-        goto rewrite;
+    r = pci_read_32((u_int32_t *) &pi->reg->srd);      /* adhere to write
+							 * timing imposition */
+
+
+    if ((r != req) && (req != SR_CHIP_RESET) && (++rcnt <= MUSYCC_SR_RETRY_CNT)) {
+	if (cxt1e1_log_level >= LOG_MONITOR)
+	    pr_info("%s: %d - reissue srv req/last %x/%x (hdw reads %x), Chan %d.\n",
+		    pi->up->devname, rcnt, req, pi->sr_last, r,
+		    (pi->portnum * MUSYCC_NCHANS) + (req & 0x1f));
+	OS_uwait_dummy();          /* this delay helps reduce reissue counts
+				     * (reason not yet researched) */
+	goto rewrite;
     }
-    if (rcnt > MUSYCC_SR_RETRY_CNT)
-    {
-        pr_warning("%s: failed service request (#%d)= %x, group %d.\n",
-                   pi->up->devname, MUSYCC_SR_RETRY_CNT, req, pi->portnum);
-        SD_SEM_GIVE (&pi->sr_sem_busy); /* allow any next request */
-        return;
+    if (rcnt > MUSYCC_SR_RETRY_CNT) {
+	pr_warning("%s: failed service request (#%d)= %x, group %d.\n",
+		   pi->up->devname, MUSYCC_SR_RETRY_CNT, req, pi->portnum);
+	SD_SEM_GIVE(&pi->sr_sem_busy); /* allow any next request */
+	return;
     }
-    if (req == SR_CHIP_RESET)
-    {
-        /*
-         * PORT NOTE: the CHIP_RESET command is NOT ack'd by the MUSYCC, thus
-         * the upcoming delay is used.  Though the MUSYCC documentation
-         * suggests a read-after-write would supply the required delay, it's
-         * unclear what CPU/BUS clock speeds might have been assumed when
-         * suggesting this 'lack of ACK' workaround.  Thus the use of uwait.
-         */
-        OS_uwait (100000, "icard"); /* 100ms */
-    } else
-    {
-        FLUSH_MEM_READ ();
-        SD_SEM_TAKE (&pi->sr_sem_wait, "sakack");       /* sleep until SACK
-                                                         * interrupt occurs */
+    if (req == SR_CHIP_RESET) {
+	/*
+	 * PORT NOTE: the CHIP_RESET command is NOT ack'd by the MUSYCC, thus
+	 * the upcoming delay is used.  Though the MUSYCC documentation
+	 * suggests a read-after-write would supply the required delay, it's
+	 * unclear what CPU/BUS clock speeds might have been assumed when
+	 * suggesting this 'lack of ACK' workaround.  Thus the use of uwait.
+	 */
+	OS_uwait(100000, "icard"); /* 100ms */
+    } else {
+	FLUSH_MEM_READ();
+	SD_SEM_TAKE(&pi->sr_sem_wait, "sakack");       /* sleep until SACK
+							 * interrupt occurs */
     }
-    SD_SEM_GIVE (&pi->sr_sem_busy); /* allow any next request */
+    SD_SEM_GIVE(&pi->sr_sem_busy); /* allow any next request */
 }
 
 
 #ifdef  SBE_PMCC4_ENABLE
 void
-musycc_update_timeslots (mpi_t * pi)
+musycc_update_timeslots(mpi_t * pi)
 {
     int         i, ch;
-    char        e1mode = IS_FRAME_ANY_E1 (pi->p.port_mode);
-
-    for (i = 0; i < 32; i++)
-    {
-        int         usedby = 0, last = 0, ts, j, bits[8];
-
-        u_int8_t lastval = 0;
-
-        if (((i == 0) && e1mode) || /* disable if  E1 mode */
-            ((i == 16) && ((pi->p.port_mode == CFG_FRAME_E1CRC_CAS) || (pi->p.port_mode == CFG_FRAME_E1CRC_CAS_AMI)))
-            || ((i > 23) && (!e1mode))) /* disable if T1 mode */
-        {
-            pi->tsm[i] = 0xff;      /* make tslot unavailable for this mode */
-        } else
-        {
-            pi->tsm[i] = 0x00;      /* make tslot available for assignment */
-        }
-        for (j = 0; j < 8; j++)
-            bits[j] = -1;
-        for (ch = 0; ch < MUSYCC_NCHANS; ch++)
-        {
-            if ((pi->chan[ch]->state == UP) && (pi->chan[ch]->p.bitmask[i]))
-            {
-                usedby++;
-                last = ch;
-                lastval = pi->chan[ch]->p.bitmask[i];
-                for (j = 0; j < 8; j++)
-                    if (lastval & (1 << j))
-                        bits[j] = ch;
-                pi->tsm[i] |= lastval;
-            }
-        }
-        if (!usedby)
-            ts = 0;
-        else if ((usedby == 1) && (lastval == 0xff))
-            ts = (4 << 5) | last;
-        else if ((usedby == 1) && (lastval == 0x7f))
-            ts = (5 << 5) | last;
-        else
-        {
-            int         idx;
-
-            if (bits[0] < 0)
-                ts = (6 << 5) | (idx = last);
-            else
-                ts = (7 << 5) | (idx = bits[0]);
-            for (j = 1; j < 8; j++)
-            {
-                pi->regram->rscm[idx * 8 + j] = (bits[j] < 0) ? 0 : (0x80 | bits[j]);
-                pi->regram->tscm[idx * 8 + j] = (bits[j] < 0) ? 0 : (0x80 | bits[j]);
-            }
-        }
-        pi->regram->rtsm[i] = ts;
-        pi->regram->ttsm[i] = ts;
+    char        e1mode = IS_FRAME_ANY_E1(pi->p.port_mode);
+
+    for (i = 0; i < 32; i++) {
+	int         usedby = 0, last = 0, ts, j, bits[8];
+
+	u_int8_t lastval = 0;
+
+	if (((i == 0) && e1mode) || /* disable if  E1 mode */
+	    ((i == 16) && ((pi->p.port_mode == CFG_FRAME_E1CRC_CAS) || (pi->p.port_mode == CFG_FRAME_E1CRC_CAS_AMI)))
+	    || ((i > 23) && (!e1mode))) /* disable if T1 mode */
+	    pi->tsm[i] = 0xff;      /* make tslot unavailable for this mode */
+	else
+	    pi->tsm[i] = 0x00;      /* make tslot available for assignment */
+	for (j = 0; j < 8; j++)
+	    bits[j] = -1;
+	for (ch = 0; ch < MUSYCC_NCHANS; ch++) {
+	    if ((pi->chan[ch]->state == UP) && (pi->chan[ch]->p.bitmask[i])) {
+		usedby++;
+		last = ch;
+		lastval = pi->chan[ch]->p.bitmask[i];
+		for (j = 0; j < 8; j++)
+		    if (lastval & (1 << j))
+			bits[j] = ch;
+		pi->tsm[i] |= lastval;
+	    }
+	}
+	if (!usedby)
+	    ts = 0;
+	else if ((usedby == 1) && (lastval == 0xff))
+	    ts = (4 << 5) | last;
+	else if ((usedby == 1) && (lastval == 0x7f))
+	    ts = (5 << 5) | last;
+	else {
+	    int         idx;
+
+	    if (bits[0] < 0)
+		ts = (6 << 5) | (idx = last);
+	    else
+		ts = (7 << 5) | (idx = bits[0]);
+	    for (j = 1; j < 8; j++) {
+		pi->regram->rscm[idx * 8 + j] = (bits[j] < 0) ? 0 : (0x80 | bits[j]);
+		pi->regram->tscm[idx * 8 + j] = (bits[j] < 0) ? 0 : (0x80 | bits[j]);
+	    }
+	}
+	pi->regram->rtsm[i] = ts;
+	pi->regram->ttsm[i] = ts;
     }
-    FLUSH_MEM_WRITE ();
+    FLUSH_MEM_WRITE();
 
-    musycc_serv_req (pi, SR_TIMESLOT_MAP | SR_RX_DIRECTION);
-    musycc_serv_req (pi, SR_TIMESLOT_MAP | SR_TX_DIRECTION);
-    musycc_serv_req (pi, SR_SUBCHANNEL_MAP | SR_RX_DIRECTION);
-    musycc_serv_req (pi, SR_SUBCHANNEL_MAP | SR_TX_DIRECTION);
+    musycc_serv_req(pi, SR_TIMESLOT_MAP | SR_RX_DIRECTION);
+    musycc_serv_req(pi, SR_TIMESLOT_MAP | SR_TX_DIRECTION);
+    musycc_serv_req(pi, SR_SUBCHANNEL_MAP | SR_RX_DIRECTION);
+    musycc_serv_req(pi, SR_SUBCHANNEL_MAP | SR_TX_DIRECTION);
 }
 #endif
 
 
 #ifdef SBE_WAN256T3_ENABLE
 void
-musycc_update_timeslots (mpi_t * pi)
+musycc_update_timeslots(mpi_t * pi)
 {
     mch_t      *ch;
 
@@ -699,21 +654,20 @@ musycc_update_timeslots (mpi_t * pi)
 #ifdef SBE_WAN256T3_ENABLE
     hmask = (0x1f << hyperdummy) & 0x1f;
 #endif
-    for (i = 0; i < 128; i++)
-    {
-        gchan = ((pi->portnum * MUSYCC_NCHANS) + (i & hmask)) % MUSYCC_NCHANS;
-        ch = pi->chan[gchan];
-        if (ch->p.mode_56k)
-            tsen = MODE_56KBPS;
-        else
-            tsen = MODE_64KBPS;     /* also the default */
-        ts = ((pi->portnum % 4) == (i / 32)) ? (tsen << 5) | (i & hmask) : 0;
-        pi->regram->rtsm[i] = ts;
-        pi->regram->ttsm[i] = ts;
+    for (i = 0; i < 128; i++) {
+	gchan = ((pi->portnum * MUSYCC_NCHANS) + (i & hmask)) % MUSYCC_NCHANS;
+	ch = pi->chan[gchan];
+	if (ch->p.mode_56k)
+	    tsen = MODE_56KBPS;
+	else
+	    tsen = MODE_64KBPS;     /* also the default */
+	ts = ((pi->portnum % 4) == (i / 32)) ? (tsen << 5) | (i & hmask) : 0;
+	pi->regram->rtsm[i] = ts;
+	pi->regram->ttsm[i] = ts;
     }
-    FLUSH_MEM_WRITE ();
-    musycc_serv_req (pi, SR_TIMESLOT_MAP | SR_RX_DIRECTION);
-    musycc_serv_req (pi, SR_TIMESLOT_MAP | SR_TX_DIRECTION);
+    FLUSH_MEM_WRITE();
+    musycc_serv_req(pi, SR_TIMESLOT_MAP | SR_RX_DIRECTION);
+    musycc_serv_req(pi, SR_TIMESLOT_MAP | SR_TX_DIRECTION);
 }
 #endif
 
@@ -723,26 +677,25 @@ musycc_update_timeslots (mpi_t * pi)
   * into a hardware specific register value (IE. MUSYCC CCD Register).
   */
 u_int32_t
-musycc_chan_proto (int proto)
+musycc_chan_proto(int proto)
 {
     int         reg;
 
-    switch (proto)
-    {
+    switch (proto) {
     case CFG_CH_PROTO_TRANS:        /* 0 */
-        reg = MUSYCC_CCD_TRANS;
-        break;
+	reg = MUSYCC_CCD_TRANS;
+	break;
     case CFG_CH_PROTO_SS7:          /* 1 */
-        reg = MUSYCC_CCD_SS7;
-        break;
+	reg = MUSYCC_CCD_SS7;
+	break;
     default:
     case CFG_CH_PROTO_ISLP_MODE:   /* 4 */
     case CFG_CH_PROTO_HDLC_FCS16:  /* 2 */
-        reg = MUSYCC_CCD_HDLC_FCS16;
-        break;
+	reg = MUSYCC_CCD_HDLC_FCS16;
+	break;
     case CFG_CH_PROTO_HDLC_FCS32:  /* 3 */
-        reg = MUSYCC_CCD_HDLC_FCS32;
-        break;
+	reg = MUSYCC_CCD_HDLC_FCS32;
+	break;
     }
 
     return reg;
@@ -750,46 +703,46 @@ musycc_chan_proto (int proto)
 
 #ifdef SBE_WAN256T3_ENABLE
 STATIC void __init
-musycc_init_port (mpi_t * pi)
+musycc_init_port(mpi_t * pi)
 {
-    pci_write_32 ((u_int32_t *) &pi->reg->gbp, OS_vtophys (pi->regram));
+    pci_write_32((u_int32_t *) &pi->reg->gbp, OS_vtophys(pi->regram));
 
     pi->regram->grcd =
-        __constant_cpu_to_le32 (MUSYCC_GRCD_RX_ENABLE |
-                                MUSYCC_GRCD_TX_ENABLE |
-                                MUSYCC_GRCD_SF_ALIGN |
-                                MUSYCC_GRCD_SUBCHAN_DISABLE |
-                                MUSYCC_GRCD_OOFMP_DISABLE |
-                                MUSYCC_GRCD_COFAIRQ_DISABLE |
-                                MUSYCC_GRCD_MC_ENABLE |
-                       (MUSYCC_GRCD_POLLTH_32 << MUSYCC_GRCD_POLLTH_SHIFT));
+	__constant_cpu_to_le32(MUSYCC_GRCD_RX_ENABLE |
+				MUSYCC_GRCD_TX_ENABLE |
+				MUSYCC_GRCD_SF_ALIGN |
+				MUSYCC_GRCD_SUBCHAN_DISABLE |
+				MUSYCC_GRCD_OOFMP_DISABLE |
+				MUSYCC_GRCD_COFAIRQ_DISABLE |
+				MUSYCC_GRCD_MC_ENABLE |
+		       (MUSYCC_GRCD_POLLTH_32 << MUSYCC_GRCD_POLLTH_SHIFT));
 
     pi->regram->pcd =
-        __constant_cpu_to_le32 (MUSYCC_PCD_E1X4_MODE |
-                                MUSYCC_PCD_TXDATA_RISING |
-                                MUSYCC_PCD_TX_DRIVEN);
+	__constant_cpu_to_le32(MUSYCC_PCD_E1X4_MODE |
+				MUSYCC_PCD_TXDATA_RISING |
+				MUSYCC_PCD_TX_DRIVEN);
 
     /* Message length descriptor */
-       pi->regram->mld = __constant_cpu_to_le32 (cxt1e1_max_mru | (cxt1e1_max_mru << 16));
-    FLUSH_MEM_WRITE ();
+       pi->regram->mld = __constant_cpu_to_le32(cxt1e1_max_mru | (cxt1e1_max_mru << 16));
+    FLUSH_MEM_WRITE();
 
-    musycc_serv_req (pi, SR_GROUP_INIT | SR_RX_DIRECTION);
-    musycc_serv_req (pi, SR_GROUP_INIT | SR_TX_DIRECTION);
+    musycc_serv_req(pi, SR_GROUP_INIT | SR_RX_DIRECTION);
+    musycc_serv_req(pi, SR_GROUP_INIT | SR_TX_DIRECTION);
 
-    musycc_init_mdt (pi);
+    musycc_init_mdt(pi);
 
-    musycc_update_timeslots (pi);
+    musycc_update_timeslots(pi);
 }
 #endif
 
 
 status_t    __init
-musycc_init (ci_t * ci)
+musycc_init(ci_t * ci)
 {
     char       *regaddr;        /* temp for address boundary calculations */
     int         i, gchan;
 
-    OS_sem_init (&ci->sem_wdbusy, SEM_AVAILABLE);       /* watchdog exclusion */
+    OS_sem_init(&ci->sem_wdbusy, SEM_AVAILABLE);       /* watchdog exclusion */
 
     /*
      * Per MUSYCC manual, Section 6.3.4 - "The host must allocate a dword
@@ -798,87 +751,80 @@ musycc_init (ci_t * ci)
 
 #define INT_QUEUE_BOUNDARY  4
 
-    regaddr = OS_kmalloc ((INT_QUEUE_SIZE + 1) * sizeof (u_int32_t));
+    regaddr = OS_kmalloc((INT_QUEUE_SIZE + 1) * sizeof(u_int32_t));
     if (regaddr == 0)
-        return ENOMEM;
+	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
-                                                                 * closest boundary */
+			       (~(INT_QUEUE_BOUNDARY - 1)));    /* this calculates
+								 * closest boundary */
 
     for (i = 0; i < INT_QUEUE_SIZE; i++)
-    {
-        ci->iqd_p[i] = __constant_cpu_to_le32 (INT_EMPTY_ENTRY);
-    }
+	ci->iqd_p[i] = __constant_cpu_to_le32(INT_EMPTY_ENTRY);
 
-    for (i = 0; i < ci->max_port; i++)
-    {
-        mpi_t      *pi = &ci->port[i];
+    for (i = 0; i < ci->max_port; i++) {
+	mpi_t      *pi = &ci->port[i];
 
-        /*
-         * Per MUSYCC manual, Section 6.3.2 - "The host must allocate a 2KB
-         * bound memory segment for Channel Group 0."
-         */
+	/*
+	 * Per MUSYCC manual, Section 6.3.2 - "The host must allocate a 2KB
+	 * bound memory segment for Channel Group 0."
+	 */
 
 #define GROUP_BOUNDARY   0x800
 
-        regaddr = OS_kmalloc (sizeof (struct musycc_groupr) + GROUP_BOUNDARY);
-        if (regaddr == 0)
-        {
-            for (gchan = 0; gchan < i; gchan++)
-            {
-                pi = &ci->port[gchan];
-                OS_kfree (pi->reg);
-                pi->reg = 0;
-            }
-            return ENOMEM;
-        }
-        pi->regram_saved = regaddr; /* save orig value for free's usage */
-        pi->regram = (struct musycc_groupr *) ((unsigned long) (regaddr + GROUP_BOUNDARY - 1) &
-                                               (~(GROUP_BOUNDARY - 1)));        /* this calculates
-                                                                                 * closest boundary */
+	regaddr = OS_kmalloc(sizeof(struct musycc_groupr) + GROUP_BOUNDARY);
+	if (regaddr == 0) {
+	    for (gchan = 0; gchan < i; gchan++) {
+		pi = &ci->port[gchan];
+		OS_kfree(pi->reg);
+		pi->reg = 0;
+	    }
+	    return ENOMEM;
+	}
+	pi->regram_saved = regaddr; /* save orig value for free's usage */
+	pi->regram = (struct musycc_groupr *) ((unsigned long) (regaddr + GROUP_BOUNDARY - 1) &
+					       (~(GROUP_BOUNDARY - 1)));        /* this calculates
+										 * closest boundary */
     }
 
     /* any board centric MUSYCC commands will use group ZERO as its "home" */
     ci->regram = ci->port[0].regram;
-    musycc_serv_req (&ci->port[0], SR_CHIP_RESET);
+    musycc_serv_req(&ci->port[0], SR_CHIP_RESET);
 
-    pci_write_32 ((u_int32_t *) &ci->reg->gbp, OS_vtophys (ci->regram));
-    pci_flush_write (ci);
+    pci_write_32((u_int32_t *) &ci->reg->gbp, OS_vtophys(ci->regram));
+    pci_flush_write(ci);
 #ifdef CONFIG_SBE_PMCC4_NCOMM
-    ci->regram->__glcd = __constant_cpu_to_le32 (GCD_MAGIC);
+    ci->regram->__glcd = __constant_cpu_to_le32(GCD_MAGIC);
 #else
     /* standard driver POLLS for INTB via CPLD register */
-    ci->regram->__glcd = __constant_cpu_to_le32 (GCD_MAGIC | MUSYCC_GCD_INTB_DISABLE);
+    ci->regram->__glcd = __constant_cpu_to_le32(GCD_MAGIC | MUSYCC_GCD_INTB_DISABLE);
 #endif
 
-    ci->regram->__iqp = cpu_to_le32 (OS_vtophys (&ci->iqd_p[0]));
-    ci->regram->__iql = __constant_cpu_to_le32 (INT_QUEUE_SIZE - 1);
-    pci_write_32 ((u_int32_t *) &ci->reg->dacbp, 0);
-    FLUSH_MEM_WRITE ();
+    ci->regram->__iqp = cpu_to_le32(OS_vtophys(&ci->iqd_p[0]));
+    ci->regram->__iql = __constant_cpu_to_le32(INT_QUEUE_SIZE - 1);
+    pci_write_32((u_int32_t *) &ci->reg->dacbp, 0);
+    FLUSH_MEM_WRITE();
 
     ci->state = C_RUNNING;          /* mark as full interrupt processing
-                                     * available */
+				     * available */
 
-    musycc_serv_req (&ci->port[0], SR_GLOBAL_INIT);     /* FIRST INTERRUPT ! */
+    musycc_serv_req(&ci->port[0], SR_GLOBAL_INIT);     /* FIRST INTERRUPT ! */
 
     /* sanity check settable parameters */
 
-       if (cxt1e1_max_mru > 0xffe)
-    {
-        pr_warning("Maximum allowed MRU exceeded, resetting %d to %d.\n",
-                                  cxt1e1_max_mru, 0xffe);
-               cxt1e1_max_mru = 0xffe;
+       if (cxt1e1_max_mru > 0xffe) {
+	pr_warning("Maximum allowed MRU exceeded, resetting %d to %d.\n",
+				  cxt1e1_max_mru, 0xffe);
+	       cxt1e1_max_mru = 0xffe;
     }
-       if (cxt1e1_max_mtu > 0xffe)
-    {
-        pr_warning("Maximum allowed MTU exceeded, resetting %d to %d.\n",
-                                  cxt1e1_max_mtu, 0xffe);
-               cxt1e1_max_mtu = 0xffe;
+       if (cxt1e1_max_mtu > 0xffe) {
+	pr_warning("Maximum allowed MTU exceeded, resetting %d to %d.\n",
+				  cxt1e1_max_mtu, 0xffe);
+	       cxt1e1_max_mtu = 0xffe;
     }
 #ifdef SBE_WAN256T3_ENABLE
     for (i = 0; i < MUSYCC_NPORTS; i++)
-        musycc_init_port (&ci->port[i]);
+	musycc_init_port(&ci->port[i]);
 #endif
 
     return SBE_DRVR_SUCCESS;        /* no error */
@@ -886,7 +832,7 @@ musycc_init (ci_t * ci)
 
 
 void
-musycc_bh_tx_eom (mpi_t * pi, int gchan)
+musycc_bh_tx_eom(mpi_t * pi, int gchan)
 {
     mch_t      *ch;
     struct mdesc *md;
@@ -900,128 +846,117 @@ musycc_bh_tx_eom (mpi_t * pi, int gchan)
     volatile u_int32_t status;
 
     ch = pi->chan[gchan];
-    if (ch == 0 || 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->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)
-        return;                     /* note: mdt==0 implies a malloc()
-                                     * failure w/in chan_up() routine */
+	return;                     /* note: mdt==0 implies a malloc()
+				     * failure w/in chan_up() routine */
 
 #if 0
 #ifdef SBE_ISR_INLINE
-    spin_lock_irq (&ch->ch_txlock);
+    spin_lock_irq(&ch->ch_txlock);
 #else
-    spin_lock_irqsave (&ch->ch_txlock, flags);
+    spin_lock_irqsave(&ch->ch_txlock, flags);
 #endif
 #endif
-    do
-    {
-        FLUSH_MEM_READ ();
-        md = ch->txd_irq_srv;
-        status = le32_to_cpu (md->status);
-
-        /*
-         * Note: Per MUSYCC Ref 6.4.9, the host does not poll a host-owned
-         * Transmit Buffer Descriptor during Transparent Mode.
-         */
-        if (status & MUSYCC_TX_OWNED)
-        {
-            int         readCount, loopCount;
-
-            /***********************************************************/
-            /* HW Bug Fix                                              */
-            /* ----------                                              */
-            /* Under certain PCI Bus loading conditions, the data      */
-            /* associated with an update of Shared Memory is delayed   */
-            /* relative to its PCI Interrupt.  This is caught when     */
-            /* the host determines it does not yet OWN the descriptor. */
-            /***********************************************************/
-
-            readCount = 0;
-            while (status & MUSYCC_TX_OWNED)
-            {
-                for (loopCount = 0; loopCount < 0x30; loopCount++)
-                    OS_uwait_dummy ();  /* use call to avoid optimization
-                                         * removal of dummy delay */
-                FLUSH_MEM_READ ();
-                status = le32_to_cpu (md->status);
-                if (readCount++ > 40)
-                    break;          /* don't wait any longer */
-            }
-            if (status & MUSYCC_TX_OWNED)
-            {
-                if (cxt1e1_log_level >= LOG_MONITOR)
-                {
-                    pr_info("%s: Port %d Chan %2d - unexpected TX msg ownership intr (md %p sts %x)\n",
-                            pi->up->devname, pi->portnum, ch->channum,
-                            md, status);
-                    pr_info("++ User 0x%p IRQ_SRV 0x%p USR_ADD 0x%p QStopped %x, start_tx %x tx_full %d txd_free %d mode %x\n",
-                            ch->user, ch->txd_irq_srv, ch->txd_usr_add,
-                            sd_queue_stopped (ch->user),
-                            ch->ch_start_tx, ch->tx_full, ch->txd_free, ch->p.chan_mode);
-                    musycc_dump_txbuffer_ring (ch, 0);
-                }
-                break;              /* Not our mdesc, done */
-            } else
-            {
-                if (cxt1e1_log_level >= LOG_MONITOR)
-                    pr_info("%s: Port %d Chan %2d - recovered TX msg ownership [%d] (md %p sts %x)\n",
-                            pi->up->devname, pi->portnum, ch->channum, readCount, md, status);
-            }
-        }
-        ch->txd_irq_srv = md->snext;
-
-        md->data = 0;
-        if (md->mem_token != 0)
-        {
-            /* upcount channel */
-            atomic_sub (OS_mem_token_tlen (md->mem_token), &ch->tx_pending);
-            /* upcount card */
-            atomic_sub (OS_mem_token_tlen (md->mem_token), &pi->up->tx_pending);
+    do {
+	FLUSH_MEM_READ();
+	md = ch->txd_irq_srv;
+	status = le32_to_cpu(md->status);
+
+	/*
+	 * Note: Per MUSYCC Ref 6.4.9, the host does not poll a host-owned
+	 * Transmit Buffer Descriptor during Transparent Mode.
+	 */
+	if (status & MUSYCC_TX_OWNED) {
+	    int         readCount, loopCount;
+
+	    /***********************************************************/
+	    /* HW Bug Fix                                              */
+	    /* ----------                                              */
+	    /* Under certain PCI Bus loading conditions, the data      */
+	    /* associated with an update of Shared Memory is delayed   */
+	    /* relative to its PCI Interrupt.  This is caught when     */
+	    /* the host determines it does not yet OWN the descriptor. */
+	    /***********************************************************/
+
+	    readCount = 0;
+	    while (status & MUSYCC_TX_OWNED) {
+		for (loopCount = 0; loopCount < 0x30; loopCount++)
+		    OS_uwait_dummy();  /* use call to avoid optimization
+					 * removal of dummy delay */
+		FLUSH_MEM_READ();
+		status = le32_to_cpu(md->status);
+		if (readCount++ > 40)
+		    break;          /* don't wait any longer */
+	    }
+	    if (status & MUSYCC_TX_OWNED) {
+		if (cxt1e1_log_level >= LOG_MONITOR) {
+		    pr_info("%s: Port %d Chan %2d - unexpected TX msg ownership intr (md %p sts %x)\n",
+			    pi->up->devname, pi->portnum, ch->channum,
+			    md, status);
+		    pr_info("++ User 0x%p IRQ_SRV 0x%p USR_ADD 0x%p QStopped %x, start_tx %x tx_full %d txd_free %d mode %x\n",
+			    ch->user, ch->txd_irq_srv, ch->txd_usr_add,
+			    sd_queue_stopped(ch->user),
+			    ch->ch_start_tx, ch->tx_full, ch->txd_free, ch->p.chan_mode);
+		    musycc_dump_txbuffer_ring(ch, 0);
+		}
+		break;              /* Not our mdesc, done */
+	    } else {
+		if (cxt1e1_log_level >= LOG_MONITOR)
+		    pr_info("%s: Port %d Chan %2d - recovered TX msg ownership [%d] (md %p sts %x)\n",
+			    pi->up->devname, pi->portnum, ch->channum, readCount, md, status);
+	    }
+	}
+	ch->txd_irq_srv = md->snext;
+
+	md->data = 0;
+	if (md->mem_token != 0)	{
+	    /* upcount channel */
+	    atomic_sub(OS_mem_token_tlen(md->mem_token), &ch->tx_pending);
+	    /* upcount card */
+	    atomic_sub(OS_mem_token_tlen(md->mem_token), &pi->up->tx_pending);
 #ifdef SBE_WAN256T3_ENABLE
-            if (!atomic_read (&pi->up->tx_pending))
-                wan256t3_led (pi->up, LED_TX, 0);
+	    if (!atomic_read(&pi->up->tx_pending))
+		wan256t3_led(pi->up, LED_TX, 0);
 #endif
 
 #ifdef CONFIG_SBE_WAN256T3_NCOMM
-            /* callback that our packet was sent */
-            {
-                int         hdlcnum = (pi->portnum * 32 + gchan);
-
-                if (hdlcnum >= 228)
-                {
-                    if (nciProcess_TX_complete)
-                        (*nciProcess_TX_complete) (hdlcnum,
-                                                   getuserbychan (gchan));
-                }
-            }
+	    /* callback that our packet was sent */
+	    {
+		int         hdlcnum = (pi->portnum * 32 + gchan);
+
+		if (hdlcnum >= 228) {
+		    if (nciProcess_TX_complete)
+			(*nciProcess_TX_complete) (hdlcnum,
+						   getuserbychan(gchan));
+		}
+	    }
 #endif                              /*** CONFIG_SBE_WAN256T3_NCOMM ***/
 
-            OS_mem_token_free_irq (md->mem_token);
-            md->mem_token = 0;
-        }
-        md->status = 0;
+	    OS_mem_token_free_irq(md->mem_token);
+	    md->mem_token = 0;
+	}
+	md->status = 0;
 #ifdef RLD_TXFULL_DEBUG
-        if (cxt1e1_log_level >= LOG_MONITOR2)
-            pr_info("~~ tx_eom: tx_full %x  txd_free %d -> %d\n",
-                    ch->tx_full, ch->txd_free, ch->txd_free + 1);
+	if (cxt1e1_log_level >= LOG_MONITOR2)
+	    pr_info("~~ tx_eom: tx_full %x  txd_free %d -> %d\n",
+		    ch->tx_full, ch->txd_free, ch->txd_free + 1);
 #endif
-        ++ch->txd_free;
-        FLUSH_MEM_WRITE ();
-
-        if ((ch->p.chan_mode != CFG_CH_PROTO_TRANS) && (status & EOBIRQ_ENABLE))
-        {
-            if (cxt1e1_log_level >= LOG_MONITOR)
-                pr_info("%s: Mode (%x) incorrect EOB status (%x)\n",
-                        pi->up->devname, ch->p.chan_mode, status);
-            if ((status & EOMIRQ_ENABLE) == 0)
-                break;
-        }
-    }
-    while ((ch->p.chan_mode != CFG_CH_PROTO_TRANS) && ((status & EOMIRQ_ENABLE) == 0));
+	++ch->txd_free;
+	FLUSH_MEM_WRITE();
+
+	if ((ch->p.chan_mode != CFG_CH_PROTO_TRANS) && (status & EOBIRQ_ENABLE)) {
+	    if (cxt1e1_log_level >= LOG_MONITOR)
+		pr_info("%s: Mode (%x) incorrect EOB status (%x)\n",
+			pi->up->devname, ch->p.chan_mode, status);
+	    if ((status & EOMIRQ_ENABLE) == 0)
+		break;
+	}
+    } while ((ch->p.chan_mode != CFG_CH_PROTO_TRANS) && ((status & EOMIRQ_ENABLE) == 0));
     /*
      * NOTE: (The above 'while' is coupled w/ previous 'do', way above.) Each
      * Transparent data buffer has the EOB bit, and NOT the EOM bit, set and
@@ -1029,56 +964,53 @@ musycc_bh_tx_eom (mpi_t * pi, int gchan)
      * buffer.
      */
 
-    FLUSH_MEM_READ ();
+    FLUSH_MEM_READ();
     /*
      * Smooth flow control hysterisis by maintaining task stoppage until half
      * the available write buffers are available.
      */
-    if (ch->tx_full && (ch->txd_free >= (ch->txd_num / 2)))
-    {
-        /*
-         * Then, only releave task stoppage if we actually have enough
-         * buffers to service the last requested packet.  It may require MORE
-         * than half the available!
-         */
-        if (ch->txd_free >= ch->txd_required)
-        {
+    if (ch->tx_full && (ch->txd_free >= (ch->txd_num / 2))) {
+	/*
+	 * Then, only releave task stoppage if we actually have enough
+	 * buffers to service the last requested packet.  It may require MORE
+	 * than half the available!
+	 */
+	if (ch->txd_free >= ch->txd_required) {
 
 #ifdef RLD_TXFULL_DEBUG
-            if (cxt1e1_log_level >= LOG_MONITOR2)
-                pr_info("tx_eom[%d]: enable xmit tx_full no more, txd_free %d txd_num/2 %d\n",
-                        ch->channum,
-                        ch->txd_free, ch->txd_num / 2);
+	    if (cxt1e1_log_level >= LOG_MONITOR2)
+		pr_info("tx_eom[%d]: enable xmit tx_full no more, txd_free %d txd_num/2 %d\n",
+			ch->channum,
+			ch->txd_free, ch->txd_num / 2);
 #endif
-            ch->tx_full = 0;
-            ch->txd_required = 0;
-            sd_enable_xmit (ch->user);  /* re-enable to catch flow controlled
-                                         * channel */
-        }
+	    ch->tx_full = 0;
+	    ch->txd_required = 0;
+	    sd_enable_xmit(ch->user);  /* re-enable to catch flow controlled
+					 * channel */
+	}
     }
 #ifdef RLD_TXFULL_DEBUG
-    else if (ch->tx_full)
-    {
-        if (cxt1e1_log_level >= LOG_MONITOR2)
-            pr_info("tx_eom[%d]: bypass TX enable though room available? (txd_free %d txd_num/2 %d)\n",
-                    ch->channum,
-                    ch->txd_free, ch->txd_num / 2);
+    else if (ch->tx_full) {
+	if (cxt1e1_log_level >= LOG_MONITOR2)
+	    pr_info("tx_eom[%d]: bypass TX enable though room available? (txd_free %d txd_num/2 %d)\n",
+		    ch->channum,
+		    ch->txd_free, ch->txd_num / 2);
     }
 #endif
 
-    FLUSH_MEM_WRITE ();
+    FLUSH_MEM_WRITE();
 #if 0
 #ifdef SBE_ISR_INLINE
-    spin_unlock_irq (&ch->ch_txlock);
+    spin_unlock_irq(&ch->ch_txlock);
 #else
-    spin_unlock_irqrestore (&ch->ch_txlock, flags);
+    spin_unlock_irqrestore(&ch->ch_txlock, flags);
 #endif
 #endif
 }
 
 
 STATIC void
-musycc_bh_rx_eom (mpi_t * pi, int gchan)
+musycc_bh_rx_eom(mpi_t * pi, int gchan)
 {
     mch_t      *ch;
     void       *m, *m2;
@@ -1087,89 +1019,76 @@ musycc_bh_rx_eom (mpi_t * pi, int gchan)
     u_int32_t   error;
 
     ch = pi->chan[gchan];
-    if (ch == 0 || 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 == 0 || 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)
-        return;                     /* can this happen ? */
-
-    for (;;)
-    {
-        FLUSH_MEM_READ ();
-        md = &ch->mdr[ch->rxix_irq_srv];
-        status = le32_to_cpu (md->status);
-        if (!(status & HOST_RX_OWNED))
-            break;                  /* Not our mdesc, done */
-        m = md->mem_token;
-        error = (status >> 16) & 0xf;
-        if (error == 0)
-        {
+	return;                     /* can this happen ? */
+
+    for (;;) {
+	FLUSH_MEM_READ();
+	md = &ch->mdr[ch->rxix_irq_srv];
+	status = le32_to_cpu(md->status);
+	if (!(status & HOST_RX_OWNED))
+	    break;                  /* Not our mdesc, done */
+	m = md->mem_token;
+	error = (status >> 16) & 0xf;
+	if (error == 0) {
 #ifdef CONFIG_SBE_WAN256T3_NCOMM
-            int         hdlcnum = (pi->portnum * 32 + gchan);
-
-            /*
-             * if the packet number belongs to NCOMM, then send it to the TMS
-             * driver
-             */
-            if (hdlcnum >= 228)
-            {
-                if (nciProcess_RX_packet)
-                    (*nciProcess_RX_packet) (hdlcnum, status & 0x3fff, m, ch->user);
-            } else
+	    int         hdlcnum = (pi->portnum * 32 + gchan);
+
+	    /*
+	     * if the packet number belongs to NCOMM, then send it to the TMS
+	     * driver
+	     */
+	    if (hdlcnum >= 228) {
+		if (nciProcess_RX_packet)
+		    (*nciProcess_RX_packet) (hdlcnum, status & 0x3fff, m, ch->user);
+	    } else
 #endif                              /*** CONFIG_SBE_WAN256T3_NCOMM ***/
 
-            {
-                               if ((m2 = OS_mem_token_alloc (cxt1e1_max_mru)))
-                {
-                    /* substitute the mbuf+cluster */
-                    md->mem_token = m2;
-                    md->data = cpu_to_le32 (OS_vtophys (OS_mem_token_data (m2)));
-
-                    /* pass the received mbuf upward */
-                    sd_recv_consume (m, status & LENGTH_MASK, ch->user);
-                    ch->s.rx_packets++;
-                    ch->s.rx_bytes += status & LENGTH_MASK;
-                } else
-                {
-                    ch->s.rx_dropped++;
-                }
-            }
-        } else if (error == ERR_FCS)
-        {
-            ch->s.rx_crc_errors++;
-        } else if (error == ERR_ALIGN)
-        {
-            ch->s.rx_missed_errors++;
-        } else if (error == ERR_ABT)
-        {
-            ch->s.rx_missed_errors++;
-        } else if (error == ERR_LNG)
-        {
-            ch->s.rx_length_errors++;
-        } else if (error == ERR_SHT)
-        {
-            ch->s.rx_length_errors++;
-        }
-        FLUSH_MEM_WRITE ();
-               status = cxt1e1_max_mru;
-        if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
-            status |= EOBIRQ_ENABLE;
-        md->status = cpu_to_le32 (status);
-
-        /* Check next mdesc in the ring */
-        if (++ch->rxix_irq_srv >= ch->rxd_num)
-            ch->rxix_irq_srv = 0;
-        FLUSH_MEM_WRITE ();
+	    {
+		if ((m2 = OS_mem_token_alloc(cxt1e1_max_mru))) {
+		    /* substitute the mbuf+cluster */
+		    md->mem_token = m2;
+		    md->data = cpu_to_le32(OS_vtophys(OS_mem_token_data(m2)));
+
+		    /* pass the received mbuf upward */
+		    sd_recv_consume(m, status & LENGTH_MASK, ch->user);
+		    ch->s.rx_packets++;
+		    ch->s.rx_bytes += status & LENGTH_MASK;
+		} else
+		    ch->s.rx_dropped++;
+	    }
+	} else if (error == ERR_FCS)
+	    ch->s.rx_crc_errors++;
+	else if (error == ERR_ALIGN)
+	    ch->s.rx_missed_errors++;
+	else if (error == ERR_ABT)
+	    ch->s.rx_missed_errors++;
+	else if (error == ERR_LNG)
+	    ch->s.rx_length_errors++;
+	else if (error == ERR_SHT)
+	    ch->s.rx_length_errors++;
+	FLUSH_MEM_WRITE();
+	       status = cxt1e1_max_mru;
+	if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
+	    status |= EOBIRQ_ENABLE;
+	md->status = cpu_to_le32(status);
+
+	/* Check next mdesc in the ring */
+	if (++ch->rxix_irq_srv >= ch->rxd_num)
+	    ch->rxix_irq_srv = 0;
+	FLUSH_MEM_WRITE();
     }
 }
 
 
 irqreturn_t
-musycc_intr_th_handler (void *devp)
+musycc_intr_th_handler(void *devp)
 {
     ci_t       *ci = (ci_t *) devp;
     volatile u_int32_t status, currInt = 0;
@@ -1180,28 +1099,25 @@ musycc_intr_th_handler (void *devp)
      * might be shared, just return.
      */
     if (ci->state == C_INIT)
-    {
-        return IRQ_NONE;
-    }
+	return IRQ_NONE;
     /*
      * Marked as hardware available. Don't service interrupts, just clear the
      * event.
      */
 
-    if (ci->state == C_IDLE)
-    {
-        status = pci_read_32 ((u_int32_t *) &ci->reg->isd);
+    if (ci->state == C_IDLE) {
+	status = pci_read_32((u_int32_t *) &ci->reg->isd);
 
-        /* clear the interrupt but process nothing else */
-        pci_write_32 ((u_int32_t *) &ci->reg->isd, status);
-        return IRQ_HANDLED;
+	/* clear the interrupt but process nothing else */
+	pci_write_32((u_int32_t *) &ci->reg->isd, status);
+	return IRQ_HANDLED;
     }
-    FLUSH_PCI_READ ();
-    FLUSH_MEM_READ ();
+    FLUSH_PCI_READ();
+    FLUSH_MEM_READ();
 
-    status = pci_read_32 ((u_int32_t *) &ci->reg->isd);
-    nextInt = INTRPTS_NEXTINT (status);
-    intCnt = INTRPTS_INTCNT (status);
+    status = pci_read_32((u_int32_t *) &ci->reg->isd);
+    nextInt = INTRPTS_NEXTINT(status);
+    intCnt = INTRPTS_INTCNT(status);
     ci->intlog.drvr_intr_thcount++;
 
     /*********************************************************/
@@ -1218,22 +1134,20 @@ musycc_intr_th_handler (void *devp)
     /* incorrect ISD's are encountered.                      */
     /*********************************************************/
 
-    if (nextInt != INTRPTS_NEXTINT (ci->intlog.this_status_new))
-    {
-        if (cxt1e1_log_level >= LOG_MONITOR)
-        {
-            pr_info("%s: note - updated ISD from %08x to %08x\n",
-                    ci->devname, status,
-              (status & (~INTRPTS_NEXTINT_M)) | ci->intlog.this_status_new);
-        }
-        /*
-         * Replace bogus status with software corrected value.
-         *
-         * It's not known whether, during this problem occurrence, if the
-         * INTFULL bit is correctly reported or not.
-         */
-        status = (status & (~INTRPTS_NEXTINT_M)) | (ci->intlog.this_status_new);
-        nextInt = INTRPTS_NEXTINT (status);
+    if (nextInt != INTRPTS_NEXTINT(ci->intlog.this_status_new)) {
+	if (cxt1e1_log_level >= LOG_MONITOR) {
+	    pr_info("%s: note - updated ISD from %08x to %08x\n",
+		    ci->devname, status,
+	      (status & (~INTRPTS_NEXTINT_M)) | ci->intlog.this_status_new);
+	}
+	/*
+	 * Replace bogus status with software corrected value.
+	 *
+	 * It's not known whether, during this problem occurrence, if the
+	 * INTFULL bit is correctly reported or not.
+	 */
+	status = (status & (~INTRPTS_NEXTINT_M)) | (ci->intlog.this_status_new);
+	nextInt = INTRPTS_NEXTINT(status);
     }
     /**********************************************/
     /* Cn847x Bug Fix                             */
@@ -1243,43 +1157,40 @@ musycc_intr_th_handler (void *devp)
     /**********************************************/
 
     if (intCnt == INT_QUEUE_SIZE)
-    {
-        currInt = ((intCnt - 1) + nextInt) & (INT_QUEUE_SIZE - 1);
-    } else
-        /************************************************/
-        /* Interrupt Write Location Issues              */
-        /* -------------------------------              */
-        /* When the interrupt status descriptor is      */
-        /* written, the interrupt line is de-asserted   */
-        /* by the Cn847x.  In the case of MIPS          */
-        /* microprocessors, this must occur at the      */
-        /* beginning of the interrupt handler so that   */
-        /* the interrupt handle is not re-entered due   */
-        /* to interrupt dis-assertion latency.          */
-        /* In the case of all other processors, this    */
-        /* action should occur at the end of the        */
-        /* interrupt handler to avoid overwriting the   */
-        /* interrupt queue.                             */
-        /************************************************/
+	currInt = ((intCnt - 1) + nextInt) & (INT_QUEUE_SIZE - 1);
+    else
+	/************************************************/
+	/* Interrupt Write Location Issues              */
+	/* -------------------------------              */
+	/* When the interrupt status descriptor is      */
+	/* written, the interrupt line is de-asserted   */
+	/* by the Cn847x.  In the case of MIPS          */
+	/* microprocessors, this must occur at the      */
+	/* beginning of the interrupt handler so that   */
+	/* the interrupt handle is not re-entered due   */
+	/* to interrupt dis-assertion latency.          */
+	/* In the case of all other processors, this    */
+	/* action should occur at the end of the        */
+	/* interrupt handler to avoid overwriting the   */
+	/* interrupt queue.                             */
+	/************************************************/
 
     if (intCnt)
-    {
-        currInt = (intCnt + nextInt) & (INT_QUEUE_SIZE - 1);
-    } else
-    {
-        /*
-         * NOTE: Servicing an interrupt whose ISD contains a count of ZERO
-         * can be indicative of a Shared Interrupt chain.  Our driver can be
-         * called from the system's interrupt handler as a matter of the OS
-         * walking the chain.  As the chain is walked, the interrupt will
-         * eventually be serviced by the correct driver/handler.
-         */
+	currInt = (intCnt + nextInt) & (INT_QUEUE_SIZE - 1);
+    else {
+	/*
+	 * NOTE: Servicing an interrupt whose ISD contains a count of ZERO
+	 * can be indicative of a Shared Interrupt chain.  Our driver can be
+	 * called from the system's interrupt handler as a matter of the OS
+	 * walking the chain.  As the chain is walked, the interrupt will
+	 * eventually be serviced by the correct driver/handler.
+	 */
 #if 0
-        /* chained interrupt = not ours */
-        pr_info(">> %s: intCnt NULL, sts %x, possibly a chained interrupt!\n",
-                ci->devname, status);
+	/* chained interrupt = not ours */
+	pr_info(">> %s: intCnt NULL, sts %x, possibly a chained interrupt!\n",
+		ci->devname, status);
 #endif
-        return IRQ_NONE;
+	return IRQ_NONE;
     }
 
     ci->iqp_tailx = currInt;
@@ -1289,27 +1200,25 @@ musycc_intr_th_handler (void *devp)
     ci->intlog.this_status_new = currInt;
 
     if ((cxt1e1_log_level >= LOG_WARN) && (status & INTRPTS_INTFULL_M))
-    {
-        pr_info("%s: Interrupt queue full condition occurred\n", ci->devname);
-    }
+	pr_info("%s: Interrupt queue full condition occurred\n", ci->devname);
     if (cxt1e1_log_level >= LOG_DEBUG)
-        pr_info("%s: interrupts pending, isd @ 0x%p: %x curr %d cnt %d NEXT %d\n",
-                ci->devname, &ci->reg->isd,
-        status, nextInt, intCnt, (intCnt + nextInt) & (INT_QUEUE_SIZE - 1));
+	pr_info("%s: interrupts pending, isd @ 0x%p: %x curr %d cnt %d NEXT %d\n",
+		ci->devname, &ci->reg->isd,
+	status, nextInt, intCnt, (intCnt + nextInt) & (INT_QUEUE_SIZE - 1));
 
-    FLUSH_MEM_WRITE ();
+    FLUSH_MEM_WRITE();
 #if defined(SBE_ISR_TASKLET)
-    pci_write_32 ((u_int32_t *) &ci->reg->isd, currInt);
-    atomic_inc (&ci->bh_pending);
-    tasklet_schedule (&ci->ci_musycc_isr_tasklet);
+    pci_write_32((u_int32_t *) &ci->reg->isd, currInt);
+    atomic_inc(&ci->bh_pending);
+    tasklet_schedule(&ci->ci_musycc_isr_tasklet);
 #elif defined(SBE_ISR_IMMEDIATE)
-    pci_write_32 ((u_int32_t *) &ci->reg->isd, currInt);
-    atomic_inc (&ci->bh_pending);
-    queue_task (&ci->ci_musycc_isr_tq, &tq_immediate);
-    mark_bh (IMMEDIATE_BH);
+    pci_write_32((u_int32_t *) &ci->reg->isd, currInt);
+    atomic_inc(&ci->bh_pending);
+    queue_task(&ci->ci_musycc_isr_tq, &tq_immediate);
+    mark_bh(IMMEDIATE_BH);
 #elif defined(SBE_ISR_INLINE)
-    (void) musycc_intr_bh_tasklet (ci);
-    pci_write_32 ((u_int32_t *) &ci->reg->isd, currInt);
+    (void) musycc_intr_bh_tasklet(ci);
+    pci_write_32((u_int32_t *) &ci->reg->isd, currInt);
 #endif
     return IRQ_HANDLED;
 }
@@ -1320,7 +1229,7 @@ unsigned long
 #else
 void
 #endif
-musycc_intr_bh_tasklet (ci_t * ci)
+musycc_intr_bh_tasklet(ci_t * ci)
 {
     mpi_t      *pi;
     mch_t      *ch;
@@ -1336,21 +1245,19 @@ musycc_intr_bh_tasklet (ci_t * ci)
      * Hardware not available, potential interrupt hang.  But since interrupt
      * might be shared, just return.
      */
-    if ((drvr_state != SBE_DRVR_AVAILABLE) || (ci->state == C_INIT))
-    {
+    if ((drvr_state != SBE_DRVR_AVAILABLE) || (ci->state == C_INIT)) {
 #if defined(SBE_ISR_IMMEDIATE)
-        return 0L;
+	return 0L;
 #else
-        return;
+	return;
 #endif
     }
 #if defined(SBE_ISR_TASKLET) || defined(SBE_ISR_IMMEDIATE)
-    if (drvr_state != SBE_DRVR_AVAILABLE)
-    {
+    if (drvr_state != SBE_DRVR_AVAILABLE) {
 #if defined(SBE_ISR_TASKLET)
-        return;
+	return;
 #elif defined(SBE_ISR_IMMEDIATE)
-        return 0L;
+	return 0L;
 #endif
     }
 #elif defined(SBE_ISR_INLINE)
@@ -1358,273 +1265,249 @@ musycc_intr_bh_tasklet (ci_t * ci)
 #endif
 
     ci->intlog.drvr_intr_bhcount++;
-    FLUSH_MEM_READ ();
+    FLUSH_MEM_READ();
     {
-        unsigned int bh = atomic_read (&ci->bh_pending);
+	unsigned int bh = atomic_read(&ci->bh_pending);
 
-        max_bh = max (bh, max_bh);
+	max_bh = max(bh, max_bh);
     }
-    atomic_set (&ci->bh_pending, 0);/* if here, no longer pending */
-    while ((headx = ci->iqp_headx) != (tailx = ci->iqp_tailx))
-    {
-        intCnt = (tailx >= headx) ? (tailx - headx) : (tailx - headx + INT_QUEUE_SIZE);
-        currInt = le32_to_cpu (ci->iqd_p[headx]);
-
-        max_intcnt = max (intCnt, max_intcnt);  /* RLD DEBUG */
-
-        /**************************************************/
-        /* HW Bug Fix                                     */
-        /* ----------                                     */
-        /* The following code checks for the condition    */
-        /* of interrupt assertion before interrupt        */
-        /* queue update.  This is a problem on several    */
-        /* PCI-Local bridge chips found on some products. */
-        /**************************************************/
-
-        readCount = 0;
-        if ((currInt == badInt) || (currInt == badInt2))
-            ci->intlog.drvr_int_failure++;
-
-        while ((currInt == badInt) || (currInt == badInt2))
-        {
-            for (loopCount = 0; loopCount < 0x30; loopCount++)
-                OS_uwait_dummy ();  /* use call to avoid optimization removal
-                                     * of dummy delay */
-            FLUSH_MEM_READ ();
-            currInt = le32_to_cpu (ci->iqd_p[headx]);
-            if (readCount++ > 20)
-                break;
-        }
-
-        if ((currInt == badInt) || (currInt == badInt2))        /* catch failure of Bug
-                                                                 * Fix checking */
-        {
-            if (cxt1e1_log_level >= LOG_WARN)
-                pr_info("%s: Illegal Interrupt Detected @ 0x%p, mod %d.)\n",
-                        ci->devname, &ci->iqd_p[headx], headx);
-
-            /*
-             * If the descriptor has not recovered, then leaving the EMPTY
-             * entry set will not signal to the MUSYCC that this descriptor
-             * has been serviced. The Interrupt Queue can then start losing
-             * available descriptors and MUSYCC eventually encounters and
-             * reports the INTFULL condition.  Per manual, changing any bit
-             * marks descriptor as available, thus the use of different
-             * EMPTY_ENTRY values.
-             */
-
-            if (currInt == badInt)
-            {
-                ci->iqd_p[headx] = __constant_cpu_to_le32 (INT_EMPTY_ENTRY2);
-            } else
-            {
-                ci->iqd_p[headx] = __constant_cpu_to_le32 (INT_EMPTY_ENTRY);
-            }
-            ci->iqp_headx = (headx + 1) & (INT_QUEUE_SIZE - 1); /* insure wrapness */
-            FLUSH_MEM_WRITE ();
-            FLUSH_MEM_READ ();
-            continue;
-        }
-        group = INTRPT_GRP (currInt);
-        gchan = INTRPT_CH (currInt);
-        event = INTRPT_EVENT (currInt);
-        err = INTRPT_ERROR (currInt);
-        tx = currInt & INTRPT_DIR_M;
-
-        ci->iqd_p[headx] = __constant_cpu_to_le32 (INT_EMPTY_ENTRY);
-        FLUSH_MEM_WRITE ();
-
-        if (cxt1e1_log_level >= LOG_DEBUG)
-        {
-            if (err != 0)
-                pr_info(" %08x -> err: %2d,", currInt, err);
-
-            pr_info("+ interrupt event: %d, grp: %d, chan: %2d, side: %cX\n",
-                    event, group, gchan, tx ? 'T' : 'R');
-        }
-        pi = &ci->port[group];      /* notice that here we assume 1-1 group -
-                                     * port mapping */
-        ch = pi->chan[gchan];
-        switch (event)
-        {
-        case EVE_SACK:              /* Service Request Acknowledge */
-            if (cxt1e1_log_level >= LOG_DEBUG)
-            {
-                volatile u_int32_t r;
-
-                r = pci_read_32 ((u_int32_t *) &pi->reg->srd);
-                pr_info("- SACK cmd: %08x (hdw= %08x)\n", pi->sr_last, r);
-            }
-            SD_SEM_GIVE (&pi->sr_sem_wait);     /* wake up waiting process */
-            break;
-        case EVE_CHABT:     /* Change To Abort Code (0x7e -> 0xff) */
-        case EVE_CHIC:              /* Change To Idle Code (0xff -> 0x7e) */
-            break;
-        case EVE_EOM:               /* End Of Message */
-        case EVE_EOB:               /* End Of Buffer (Transparent mode) */
-            if (tx)
-            {
-                musycc_bh_tx_eom (pi, gchan);
-            } else
-            {
-                musycc_bh_rx_eom (pi, gchan);
-            }
+    atomic_set(&ci->bh_pending, 0);/* if here, no longer pending */
+    while ((headx = ci->iqp_headx) != (tailx = ci->iqp_tailx)) {
+	intCnt = (tailx >= headx) ? (tailx - headx) : (tailx - headx + INT_QUEUE_SIZE);
+	currInt = le32_to_cpu(ci->iqd_p[headx]);
+
+	max_intcnt = max(intCnt, max_intcnt);  /* RLD DEBUG */
+
+	/**************************************************/
+	/* HW Bug Fix                                     */
+	/* ----------                                     */
+	/* The following code checks for the condition    */
+	/* of interrupt assertion before interrupt        */
+	/* queue update.  This is a problem on several    */
+	/* PCI-Local bridge chips found on some products. */
+	/**************************************************/
+
+	readCount = 0;
+	if ((currInt == badInt) || (currInt == badInt2))
+	    ci->intlog.drvr_int_failure++;
+
+	while ((currInt == badInt) || (currInt == badInt2)) {
+	    for (loopCount = 0; loopCount < 0x30; loopCount++)
+		OS_uwait_dummy();  /* use call to avoid optimization removal
+				     * of dummy delay */
+	    FLUSH_MEM_READ();
+	    currInt = le32_to_cpu(ci->iqd_p[headx]);
+	    if (readCount++ > 20)
+		break;
+	}
+
+	if ((currInt == badInt) || (currInt == badInt2)) {      /* catch failure of Bug
+								 * Fix checking */
+	    if (cxt1e1_log_level >= LOG_WARN)
+		pr_info("%s: Illegal Interrupt Detected @ 0x%p, mod %d.)\n",
+			ci->devname, &ci->iqd_p[headx], headx);
+
+	    /*
+	     * If the descriptor has not recovered, then leaving the EMPTY
+	     * entry set will not signal to the MUSYCC that this descriptor
+	     * has been serviced. The Interrupt Queue can then start losing
+	     * available descriptors and MUSYCC eventually encounters and
+	     * reports the INTFULL condition.  Per manual, changing any bit
+	     * marks descriptor as available, thus the use of different
+	     * EMPTY_ENTRY values.
+	     */
+
+	    if (currInt == badInt)
+		ci->iqd_p[headx] = __constant_cpu_to_le32(INT_EMPTY_ENTRY2);
+	    else
+		ci->iqd_p[headx] = __constant_cpu_to_le32(INT_EMPTY_ENTRY);
+	    ci->iqp_headx = (headx + 1) & (INT_QUEUE_SIZE - 1); /* insure wrapness */
+	    FLUSH_MEM_WRITE();
+	    FLUSH_MEM_READ();
+	    continue;
+	}
+	group = INTRPT_GRP(currInt);
+	gchan = INTRPT_CH(currInt);
+	event = INTRPT_EVENT(currInt);
+	err = INTRPT_ERROR(currInt);
+	tx = currInt & INTRPT_DIR_M;
+
+	ci->iqd_p[headx] = __constant_cpu_to_le32(INT_EMPTY_ENTRY);
+	FLUSH_MEM_WRITE();
+
+	if (cxt1e1_log_level >= LOG_DEBUG) {
+	    if (err != 0)
+		pr_info(" %08x -> err: %2d,", currInt, err);
+
+	    pr_info("+ interrupt event: %d, grp: %d, chan: %2d, side: %cX\n",
+		    event, group, gchan, tx ? 'T' : 'R');
+	}
+	pi = &ci->port[group];      /* notice that here we assume 1-1 group -
+				     * port mapping */
+	ch = pi->chan[gchan];
+	switch (event) {
+	case EVE_SACK:              /* Service Request Acknowledge */
+	    if (cxt1e1_log_level >= LOG_DEBUG) {
+		volatile u_int32_t r;
+
+		r = pci_read_32((u_int32_t *) &pi->reg->srd);
+		pr_info("- SACK cmd: %08x (hdw= %08x)\n", pi->sr_last, r);
+	    }
+	    SD_SEM_GIVE(&pi->sr_sem_wait);     /* wake up waiting process */
+	    break;
+	case EVE_CHABT:     /* Change To Abort Code (0x7e -> 0xff) */
+	case EVE_CHIC:              /* Change To Idle Code (0xff -> 0x7e) */
+	    break;
+	case EVE_EOM:               /* End Of Message */
+	case EVE_EOB:               /* End Of Buffer (Transparent mode) */
+	    if (tx)
+		musycc_bh_tx_eom(pi, gchan);
+	    else
+		musycc_bh_rx_eom(pi, gchan);
 #if 0
-            break;
+	    break;
 #else
-            /*
-             * MUSYCC Interrupt Descriptor section states that EOB and EOM
-             * can be combined with the NONE error (as well as others).  So
-             * drop thru to catch this...
-             */
+	    /*
+	     * MUSYCC Interrupt Descriptor section states that EOB and EOM
+	     * can be combined with the NONE error (as well as others).  So
+	     * drop thru to catch this...
+	     */
 #endif
-        case EVE_NONE:
-            if (err == ERR_SHT)
-            {
-                ch->s.rx_length_errors++;
-            }
-            break;
-        default:
-            if (cxt1e1_log_level >= LOG_WARN)
-                pr_info("%s: unexpected interrupt event: %d, iqd[%d]: %08x, port: %d\n", ci->devname,
-                        event, headx, currInt, group);
-            break;
-        }                           /* switch on event */
-
-
-        /*
-         * Per MUSYCC Manual, Section 6.4.8.3 [Transmit Errors], TX errors
-         * are service-affecting and require action to resume normal
-         * bit-level processing.
-         */
-
-        switch (err)
-        {
-        case ERR_ONR:
-            /*
-             * Per MUSYCC manual, Section  6.4.8.3 [Transmit Errors], this
-             * error requires Transmit channel reactivation.
-             *
-             * Per MUSYCC manual, Section  6.4.8.4 [Receive Errors], this error
-             * requires Receive channel reactivation.
-             */
-            if (tx)
-            {
-
-                /*
-                 * TX ONR Error only occurs when channel is configured for
-                 * Transparent Mode.  However, this code will catch and
-                 * re-activate on ANY TX ONR error.
-                 */
-
-                /*
-                 * Set flag to re-enable on any next transmit attempt.
-                 */
-                ch->ch_start_tx = CH_START_TX_ONR;
-
-                {
+	case EVE_NONE:
+	    if (err == ERR_SHT)
+		ch->s.rx_length_errors++;
+	    break;
+	default:
+	    if (cxt1e1_log_level >= LOG_WARN)
+		pr_info("%s: unexpected interrupt event: %d, iqd[%d]: %08x, port: %d\n", ci->devname,
+			event, headx, currInt, group);
+	    break;
+	}                           /* switch on event */
+
+
+	/*
+	 * Per MUSYCC Manual, Section 6.4.8.3 [Transmit Errors], TX errors
+	 * are service-affecting and require action to resume normal
+	 * bit-level processing.
+	 */
+
+	switch (err) {
+	case ERR_ONR:
+	    /*
+	     * Per MUSYCC manual, Section  6.4.8.3 [Transmit Errors], this
+	     * error requires Transmit channel reactivation.
+	     *
+	     * Per MUSYCC manual, Section  6.4.8.4 [Receive Errors], this error
+	     * requires Receive channel reactivation.
+	     */
+	    if (tx) {
+
+		/*
+		 * TX ONR Error only occurs when channel is configured for
+		 * Transparent Mode.  However, this code will catch and
+		 * re-activate on ANY TX ONR error.
+		 */
+
+		/*
+		 * Set flag to re-enable on any next transmit attempt.
+		 */
+		ch->ch_start_tx = CH_START_TX_ONR;
+
+		{
 #ifdef RLD_TRANS_DEBUG
-                    if (1 || cxt1e1_log_level >= LOG_MONITOR)
+		    if (1 || cxt1e1_log_level >= LOG_MONITOR)
 #else
-                    if (cxt1e1_log_level >= LOG_MONITOR)
+		    if (cxt1e1_log_level >= LOG_MONITOR)
 #endif
-                    {
-                        pr_info("%s: TX buffer underflow [ONR] on channel %d, mode %x QStopped %x free %d\n",
-                                ci->devname, ch->channum, ch->p.chan_mode, sd_queue_stopped (ch->user), ch->txd_free);
+		    {
+			pr_info("%s: TX buffer underflow [ONR] on channel %d, mode %x QStopped %x free %d\n",
+				ci->devname, ch->channum, ch->p.chan_mode, sd_queue_stopped(ch->user), ch->txd_free);
 #ifdef RLD_DEBUG
-                        if (ch->p.chan_mode == 2)       /* problem = ONR on HDLC
-                                                         * mode */
-                        {
-                            pr_info("++ Failed Last %x Next %x QStopped %x, start_tx %x tx_full %d txd_free %d mode %x\n",
-                                    (u_int32_t) ch->txd_irq_srv, (u_int32_t) ch->txd_usr_add,
-                                    sd_queue_stopped (ch->user),
-                                    ch->ch_start_tx, ch->tx_full, ch->txd_free, ch->p.chan_mode);
-                            musycc_dump_txbuffer_ring (ch, 0);
-                        }
+			if (ch->p.chan_mode == 2) {     /* problem = ONR on HDLC
+							 * mode */
+			    pr_info("++ Failed Last %x Next %x QStopped %x, start_tx %x tx_full %d txd_free %d mode %x\n",
+				    (u_int32_t) ch->txd_irq_srv, (u_int32_t) ch->txd_usr_add,
+				    sd_queue_stopped(ch->user),
+				    ch->ch_start_tx, ch->tx_full, ch->txd_free, ch->p.chan_mode);
+			    musycc_dump_txbuffer_ring(ch, 0);
+			}
 #endif
-                    }
-                }
-            } else                  /* RX buffer overrun */
-            {
-                /*
-                 * Per MUSYCC manual, Section 6.4.8.4 [Receive Errors],
-                 * channel recovery for this RX ONR error IS required.  It is
-                 * also suggested to increase the number of receive buffers
-                 * for this channel.  Receive channel reactivation IS
-                 * required, and data has been lost.
-                 */
-                ch->s.rx_over_errors++;
-                ch->ch_start_rx = CH_START_RX_ONR;
-
-                if (cxt1e1_log_level >= LOG_WARN)
-                {
-                    pr_info("%s: RX buffer overflow [ONR] on channel %d, mode %x\n",
-                            ci->devname, ch->channum, ch->p.chan_mode);
-                    //musycc_dump_rxbuffer_ring (ch, 0);        /* RLD DEBUG */
-                }
-            }
-            musycc_chan_restart (ch);
-            break;
-        case ERR_BUF:
-            if (tx)
-            {
-                ch->s.tx_fifo_errors++;
-                ch->ch_start_tx = CH_START_TX_BUF;
-                /*
-                 * Per MUSYCC manual, Section  6.4.8.3 [Transmit Errors],
-                 * this BUFF error requires Transmit channel reactivation.
-                 */
-                if (cxt1e1_log_level >= LOG_MONITOR)
-                    pr_info("%s: TX buffer underrun [BUFF] on channel %d, mode %x\n",
-                            ci->devname, ch->channum, ch->p.chan_mode);
-            } else                  /* RX buffer overrun */
-            {
-                ch->s.rx_over_errors++;
-                /*
-                 * Per MUSYCC manual, Section 6.4.8.4 [Receive Errors], HDLC
-                 * mode requires NO recovery for this RX BUFF error is
-                 * required.  It is suggested to increase the FIFO buffer
-                 * space for this channel.  Receive channel reactivation is
-                 * not required, but data has been lost.
-                 */
-                if (cxt1e1_log_level >= LOG_WARN)
-                    pr_info("%s: RX buffer overrun [BUFF] on channel %d, mode %x\n",
-                            ci->devname, ch->channum, ch->p.chan_mode);
-                /*
-                 * Per MUSYCC manual, Section 6.4.9.4 [Receive Errors],
-                 * Transparent mode DOES require recovery for the RX BUFF
-                 * error.  It is suggested to increase the FIFO buffer space
-                 * for this channel.  Receive channel reactivation IS
-                 * required and data has been lost.
-                 */
-                if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
-                    ch->ch_start_rx = CH_START_RX_BUF;
-            }
-
-            if (tx || (ch->p.chan_mode == CFG_CH_PROTO_TRANS))
-                musycc_chan_restart (ch);
-            break;
-        default:
-            break;
-        }                           /* switch on err */
-
-        /* Check for interrupt lost condition */
-        if ((currInt & INTRPT_ILOST_M) && (cxt1e1_log_level >= LOG_ERROR))
-        {
-            pr_info("%s: Interrupt queue overflow - ILOST asserted\n",
-                    ci->devname);
-        }
-        ci->iqp_headx = (headx + 1) & (INT_QUEUE_SIZE - 1);     /* insure wrapness */
-        FLUSH_MEM_WRITE ();
-        FLUSH_MEM_READ ();
+		    }
+		}
+	    } else {                 /* RX buffer overrun */
+		/*
+		 * Per MUSYCC manual, Section 6.4.8.4 [Receive Errors],
+		 * channel recovery for this RX ONR error IS required.  It is
+		 * also suggested to increase the number of receive buffers
+		 * for this channel.  Receive channel reactivation IS
+		 * required, and data has been lost.
+		 */
+		ch->s.rx_over_errors++;
+		ch->ch_start_rx = CH_START_RX_ONR;
+
+		if (cxt1e1_log_level >= LOG_WARN) {
+		    pr_info("%s: RX buffer overflow [ONR] on channel %d, mode %x\n",
+			    ci->devname, ch->channum, ch->p.chan_mode);
+		    //musycc_dump_rxbuffer_ring (ch, 0);        /* RLD DEBUG */
+		}
+	    }
+	    musycc_chan_restart(ch);
+	    break;
+	case ERR_BUF:
+	    if (tx) {
+		ch->s.tx_fifo_errors++;
+		ch->ch_start_tx = CH_START_TX_BUF;
+		/*
+		 * Per MUSYCC manual, Section  6.4.8.3 [Transmit Errors],
+		 * this BUFF error requires Transmit channel reactivation.
+		 */
+		if (cxt1e1_log_level >= LOG_MONITOR)
+		    pr_info("%s: TX buffer underrun [BUFF] on channel %d, mode %x\n",
+			    ci->devname, ch->channum, ch->p.chan_mode);
+	    } else {                 /* RX buffer overrun */
+		ch->s.rx_over_errors++;
+		/*
+		 * Per MUSYCC manual, Section 6.4.8.4 [Receive Errors], HDLC
+		 * mode requires NO recovery for this RX BUFF error is
+		 * required.  It is suggested to increase the FIFO buffer
+		 * space for this channel.  Receive channel reactivation is
+		 * not required, but data has been lost.
+		 */
+		if (cxt1e1_log_level >= LOG_WARN)
+		    pr_info("%s: RX buffer overrun [BUFF] on channel %d, mode %x\n",
+			    ci->devname, ch->channum, ch->p.chan_mode);
+		/*
+		 * Per MUSYCC manual, Section 6.4.9.4 [Receive Errors],
+		 * Transparent mode DOES require recovery for the RX BUFF
+		 * error.  It is suggested to increase the FIFO buffer space
+		 * for this channel.  Receive channel reactivation IS
+		 * required and data has been lost.
+		 */
+		if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
+		    ch->ch_start_rx = CH_START_RX_BUF;
+	    }
+
+	    if (tx || (ch->p.chan_mode == CFG_CH_PROTO_TRANS))
+		musycc_chan_restart(ch);
+	    break;
+	default:
+	    break;
+	}                           /* switch on err */
+
+	/* Check for interrupt lost condition */
+	if ((currInt & INTRPT_ILOST_M) && (cxt1e1_log_level >= LOG_ERROR))
+	    pr_info("%s: Interrupt queue overflow - ILOST asserted\n",
+		    ci->devname);
+	ci->iqp_headx = (headx + 1) & (INT_QUEUE_SIZE - 1);     /* insure wrapness */
+	FLUSH_MEM_WRITE();
+	FLUSH_MEM_READ();
     }                               /* while */
-    if ((cxt1e1_log_level >= LOG_MONITOR2) && (ci->iqp_headx != ci->iqp_tailx))
-    {
-        int         bh;
+    if ((cxt1e1_log_level >= LOG_MONITOR2) && (ci->iqp_headx != ci->iqp_tailx)) {
+	int         bh;
 
-        bh = atomic_read (&CI->bh_pending);
-        pr_info("_bh_: late arrivals, head %d != tail %d, pending %d\n",
-                ci->iqp_headx, ci->iqp_tailx, bh);
+	bh = atomic_read(&CI->bh_pending);
+	pr_info("_bh_: late arrivals, head %d != tail %d, pending %d\n",
+		ci->iqp_headx, ci->iqp_tailx, bh);
     }
 #if defined(SBE_ISR_IMMEDIATE)
     return 0L;
@@ -1634,14 +1517,14 @@ musycc_intr_bh_tasklet (ci_t * ci)
 
 #if 0
 int         __init
-musycc_new_chan (ci_t * ci, int channum, void *user)
+musycc_new_chan(ci_t * ci, int channum, void *user)
 {
     mch_t      *ch;
 
     ch = ci->port[channum / MUSYCC_NCHANS].chan[channum % MUSYCC_NCHANS];
 
     if (ch->state != UNASSIGNED)
-        return EEXIST;
+	return EEXIST;
     /* NOTE: mch_t already cleared during OS_kmalloc() */
     ch->state = DOWN;
     ch->user = user;
@@ -1653,8 +1536,8 @@ musycc_new_chan (ci_t * ci, int channum, void *user)
     ch->p.chan_mode = CFG_CH_PROTO_HDLC_FCS16;
     ch->p.idlecode = CFG_CH_FLAG_7E;
     ch->p.pad_fill_count = 2;
-    spin_lock_init (&ch->ch_rxlock);
-    spin_lock_init (&ch->ch_txlock);
+    spin_lock_init(&ch->ch_rxlock);
+    spin_lock_init(&ch->ch_txlock);
 
     return 0;
 }
@@ -1663,53 +1546,49 @@ musycc_new_chan (ci_t * ci, int channum, void *user)
 
 #ifdef SBE_PMCC4_ENABLE
 status_t
-musycc_chan_down (ci_t * dummy, int channum)
+musycc_chan_down(ci_t * dummy, int channum)
 {
     mpi_t      *pi;
     mch_t      *ch;
     int         i, gchan;
 
-    if (!(ch = sd_find_chan (dummy, channum)))
-        return EINVAL;
+    if (!(ch = sd_find_chan(dummy, channum)))
+	return EINVAL;
     pi = ch->up;
     gchan = ch->gchan;
 
     /* Deactivate the channel */
-    musycc_serv_req (pi, SR_CHANNEL_DEACTIVATE | SR_RX_DIRECTION | gchan);
+    musycc_serv_req(pi, SR_CHANNEL_DEACTIVATE | SR_RX_DIRECTION | gchan);
     ch->ch_start_rx = 0;
-    musycc_serv_req (pi, SR_CHANNEL_DEACTIVATE | SR_TX_DIRECTION | gchan);
+    musycc_serv_req(pi, SR_CHANNEL_DEACTIVATE | SR_TX_DIRECTION | gchan);
     ch->ch_start_tx = 0;
 
     if (ch->state == DOWN)
-        return 0;
+	return 0;
     ch->state = DOWN;
 
     pi->regram->thp[gchan] = 0;
     pi->regram->tmp[gchan] = 0;
     pi->regram->rhp[gchan] = 0;
     pi->regram->rmp[gchan] = 0;
-    FLUSH_MEM_WRITE ();
+    FLUSH_MEM_WRITE();
     for (i = 0; i < ch->txd_num; i++)
-    {
-        if (ch->mdt[i].mem_token != 0)
-            OS_mem_token_free (ch->mdt[i].mem_token);
-    }
+	if (ch->mdt[i].mem_token != 0)
+	    OS_mem_token_free(ch->mdt[i].mem_token);
 
     for (i = 0; i < ch->rxd_num; i++)
-    {
-        if (ch->mdr[i].mem_token != 0)
-            OS_mem_token_free (ch->mdr[i].mem_token);
-    }
+	if (ch->mdr[i].mem_token != 0)
+	    OS_mem_token_free(ch->mdr[i].mem_token);
 
-    OS_kfree (ch->mdr);
+    OS_kfree(ch->mdr);
     ch->mdr = 0;
     ch->rxd_num = 0;
-    OS_kfree (ch->mdt);
+    OS_kfree(ch->mdt);
     ch->mdt = 0;
     ch->txd_num = 0;
 
-    musycc_update_timeslots (pi);
-    c4_fifo_free (pi, ch->gchan);
+    musycc_update_timeslots(pi);
+    c4_fifo_free(pi, ch->gchan);
 
     pi->openchans--;
     return 0;
@@ -1718,38 +1597,38 @@ musycc_chan_down (ci_t * dummy, int channum)
 
 
 int
-musycc_del_chan (ci_t * ci, int channum)
+musycc_del_chan(ci_t * ci, int channum)
 {
     mch_t      *ch;
 
     if ((channum < 0) || (channum >= (MUSYCC_NPORTS * MUSYCC_NCHANS)))  /* sanity chk param */
-        return ECHRNG;
-    if (!(ch = sd_find_chan (ci, channum)))
-        return ENOENT;
+	return ECHRNG;
+    if (!(ch = sd_find_chan(ci, channum)))
+	return ENOENT;
     if (ch->state == UP)
-        musycc_chan_down (ci, channum);
+	musycc_chan_down(ci, channum);
     ch->state = UNASSIGNED;
     return 0;
 }
 
 
 int
-musycc_del_chan_stats (ci_t * ci, int channum)
+musycc_del_chan_stats(ci_t * ci, int channum)
 {
     mch_t      *ch;
 
     if (channum < 0 || channum >= (MUSYCC_NPORTS * MUSYCC_NCHANS))      /* sanity chk param */
-        return ECHRNG;
-    if (!(ch = sd_find_chan (ci, channum)))
-        return ENOENT;
+	return ECHRNG;
+    if (!(ch = sd_find_chan(ci, channum)))
+	return ENOENT;
 
-    memset (&ch->s, 0, sizeof (struct sbecom_chan_stats));
+    memset(&ch->s, 0, sizeof(struct sbecom_chan_stats));
     return 0;
 }
 
 
 int
-musycc_start_xmit (ci_t * ci, int channum, void *mem_token)
+musycc_start_xmit(ci_t * ci, int channum, void *mem_token)
 {
     mch_t      *ch;
     struct mdesc *md;
@@ -1760,16 +1639,16 @@ musycc_start_xmit (ci_t * ci, int channum, void *mem_token)
     int         txd_need_cnt;
     u_int32_t   len;
 
-    if (!(ch = sd_find_chan (ci, channum)))
-        return -ENOENT;
+    if (!(ch = sd_find_chan(ci, channum)))
+	return -ENOENT;
 
     if (ci->state != C_RUNNING)     /* full interrupt processing available */
-        return -EINVAL;
+	return -EINVAL;
     if (ch->state != UP)
-        return -EINVAL;
+	return -EINVAL;
 
     if (!(ch->status & TX_ENABLED))
-        return -EROFS;               /* how else to flag unwritable state ? */
+	return -EROFS;               /* how else to flag unwritable state ? */
 
 #ifdef RLD_TRANS_DEBUGx
     if (1 || cxt1e1_log_level >= LOG_MONITOR2)
@@ -1777,66 +1656,58 @@ musycc_start_xmit (ci_t * ci, int channum, void *mem_token)
     if (cxt1e1_log_level >= LOG_MONITOR2)
 #endif
     {
-        pr_info("++ start_xmt[%d]: state %x start %x full %d free %d required %d stopped %x\n",
-                channum, ch->state, ch->ch_start_tx, ch->tx_full,
-                ch->txd_free, ch->txd_required, sd_queue_stopped (ch->user));
+	pr_info("++ start_xmt[%d]: state %x start %x full %d free %d required %d stopped %x\n",
+		channum, ch->state, ch->ch_start_tx, ch->tx_full,
+		ch->txd_free, ch->txd_required, sd_queue_stopped(ch->user));
     }
     /***********************************************/
     /** Determine total amount of data to be sent **/
     /***********************************************/
     m2 = mem_token;
     txd_need_cnt = 0;
-    for (len = OS_mem_token_tlen (m2); len > 0;
-         m2 = (void *) OS_mem_token_next (m2))
-    {
-        if (!OS_mem_token_len (m2))
-            continue;
-        txd_need_cnt++;
-        len -= OS_mem_token_len (m2);
+    for (len = OS_mem_token_tlen(m2); len > 0;
+	 m2 = (void *) OS_mem_token_next(m2)) {
+	if (!OS_mem_token_len(m2))
+	    continue;
+	txd_need_cnt++;
+	len -= OS_mem_token_len(m2);
     }
 
-    if (txd_need_cnt == 0)
-    {
-        if (cxt1e1_log_level >= LOG_MONITOR2)
-            pr_info("%s channel %d: no TX data in User buffer\n", ci->devname, channum);
-        OS_mem_token_free (mem_token);
-        return 0;                   /* no data to send */
+    if (txd_need_cnt == 0) {
+	if (cxt1e1_log_level >= LOG_MONITOR2)
+	    pr_info("%s channel %d: no TX data in User buffer\n", ci->devname, channum);
+	OS_mem_token_free(mem_token);
+	return 0;                   /* no data to send */
     }
     /*************************************************/
     /** Are there sufficient descriptors available? **/
     /*************************************************/
-    if (txd_need_cnt > ch->txd_num) /* never enough descriptors for this
-                                     * large a buffer */
-    {
-        if (cxt1e1_log_level >= LOG_DEBUG)
-        {
-            pr_info("start_xmit: discarding buffer, insufficient descriptor cnt %d, need %d.\n",
-                    ch->txd_num, txd_need_cnt + 1);
-        }
-        ch->s.tx_dropped++;
-        OS_mem_token_free (mem_token);
-        return 0;
+    if (txd_need_cnt > ch->txd_num) { /* never enough descriptors for this
+				       * large a buffer */
+	if (cxt1e1_log_level >= LOG_DEBUG)
+	    pr_info("start_xmit: discarding buffer, insufficient descriptor cnt %d, need %d.\n",
+		    ch->txd_num, txd_need_cnt + 1);
+	ch->s.tx_dropped++;
+	OS_mem_token_free(mem_token);
+	return 0;
     }
 #if 0
-    spin_lock_irqsave (&ch->ch_txlock, flags);
+    spin_lock_irqsave(&ch->ch_txlock, flags);
 #endif
     /************************************************************/
     /** flow control the line if not enough descriptors remain **/
     /************************************************************/
-    if (txd_need_cnt > ch->txd_free)
-    {
-        if (cxt1e1_log_level >= LOG_MONITOR2)
-        {
-            pr_info("start_xmit[%d]: EBUSY - need more descriptors, have %d of %d need %d\n",
-                    channum, ch->txd_free, ch->txd_num, txd_need_cnt);
-        }
-        ch->tx_full = 1;
-        ch->txd_required = txd_need_cnt;
-        sd_disable_xmit (ch->user);
+    if (txd_need_cnt > ch->txd_free) {
+	if (cxt1e1_log_level >= LOG_MONITOR2)
+	    pr_info("start_xmit[%d]: EBUSY - need more descriptors, have %d of %d need %d\n",
+		    channum, ch->txd_free, ch->txd_num, txd_need_cnt);
+	ch->tx_full = 1;
+	ch->txd_required = txd_need_cnt;
+	sd_disable_xmit(ch->user);
 #if 0
-        spin_unlock_irqrestore (&ch->ch_txlock, flags);
+	spin_unlock_irqrestore(&ch->ch_txlock, flags);
 #endif
-        return -EBUSY;               /* tell user to try again later */
+	return -EBUSY;               /* tell user to try again later */
     }
     /**************************************************/
     /** Put the user data into MUSYCC data buffer(s) **/
@@ -1844,74 +1715,71 @@ musycc_start_xmit (ci_t * ci, int channum, void *mem_token)
     m2 = mem_token;
     md = ch->txd_usr_add;           /* get current available descriptor */
 
-    for (len = OS_mem_token_tlen (m2); len > 0; m2 = OS_mem_token_next (m2))
-    {
-        int         u = OS_mem_token_len (m2);
-
-        if (!u)
-            continue;
-        len -= u;
-
-        /*
-         * Enable following chunks, yet wait to enable the FIRST chunk until
-         * after ALL subsequent chunks are setup.
-         */
-        if (md != ch->txd_usr_add)  /* not first chunk */
-            u |= MUSYCC_TX_OWNED;   /* transfer ownership from HOST to MUSYCC */
-
-        if (len)                    /* not last chunk */
-            u |= EOBIRQ_ENABLE;
-        else if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
-        {
-            /*
-             * Per MUSYCC Ref 6.4.9 for Transparent Mode, the host must
-             * always clear EOMIRQ_ENABLE in every Transmit Buffer Descriptor
-             * (IE. don't set herein).
-             */
-            u |= EOBIRQ_ENABLE;
-        } else
-            u |= EOMIRQ_ENABLE;     /* EOM, last HDLC chunk */
-
-
-        /* last chunk in hdlc mode */
-        u |= (ch->p.idlecode << IDLE_CODE);
-        if (ch->p.pad_fill_count)
-        {
+    for (len = OS_mem_token_tlen(m2); len > 0; m2 = OS_mem_token_next(m2)) {
+	int         u = OS_mem_token_len(m2);
+
+	if (!u)
+	    continue;
+	len -= u;
+
+	/*
+	 * Enable following chunks, yet wait to enable the FIRST chunk until
+	 * after ALL subsequent chunks are setup.
+	 */
+	if (md != ch->txd_usr_add)  /* not first chunk */
+	    u |= MUSYCC_TX_OWNED;   /* transfer ownership from HOST to MUSYCC */
+
+	if (len)                    /* not last chunk */
+	    u |= EOBIRQ_ENABLE;
+	else if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)	{
+	    /*
+	     * Per MUSYCC Ref 6.4.9 for Transparent Mode, the host must
+	     * always clear EOMIRQ_ENABLE in every Transmit Buffer Descriptor
+	     * (IE. don't set herein).
+	     */
+	    u |= EOBIRQ_ENABLE;
+	} else
+	    u |= EOMIRQ_ENABLE;     /* EOM, last HDLC chunk */
+
+
+	/* last chunk in hdlc mode */
+	u |= (ch->p.idlecode << IDLE_CODE);
+	if (ch->p.pad_fill_count) {
 #if 0
-            /* NOOP NOTE: u_int8_t cannot be > 0xFF */
-            /* sanitize pad_fill_count for maximums allowed by hardware */
-            if (ch->p.pad_fill_count > EXTRA_FLAGS_MASK)
-                ch->p.pad_fill_count = EXTRA_FLAGS_MASK;
+	    /* NOOP NOTE: u_int8_t cannot be > 0xFF */
+	    /* sanitize pad_fill_count for maximums allowed by hardware */
+	    if (ch->p.pad_fill_count > EXTRA_FLAGS_MASK)
+		ch->p.pad_fill_count = EXTRA_FLAGS_MASK;
 #endif
-            u |= (PADFILL_ENABLE | (ch->p.pad_fill_count << EXTRA_FLAGS));
-        }
-        md->mem_token = len ? 0 : mem_token;    /* Fill in mds on last
-                                                 * segment, others set ZERO
-                                                 * so that entire token is
-                                                 * removed ONLY when ALL
-                                                 * segments have been
-                                                 * transmitted. */
-
-        md->data = cpu_to_le32 (OS_vtophys (OS_mem_token_data (m2)));
-        FLUSH_MEM_WRITE ();
-        md->status = cpu_to_le32 (u);
-        --ch->txd_free;
-        md = md->snext;
+	    u |= (PADFILL_ENABLE | (ch->p.pad_fill_count << EXTRA_FLAGS));
+	}
+	md->mem_token = len ? 0 : mem_token;    /* Fill in mds on last
+						 * segment, others set ZERO
+						 * so that entire token is
+						 * removed ONLY when ALL
+						 * segments have been
+						 * transmitted. */
+
+	md->data = cpu_to_le32(OS_vtophys(OS_mem_token_data(m2)));
+	FLUSH_MEM_WRITE();
+	md->status = cpu_to_le32(u);
+	--ch->txd_free;
+	md = md->snext;
     }
-    FLUSH_MEM_WRITE ();
+    FLUSH_MEM_WRITE();
 
 
     /*
      * Now transfer ownership of first chunk from HOST to MUSYCC in order to
      * fire-off this XMIT.
      */
-    ch->txd_usr_add->status |= __constant_cpu_to_le32 (MUSYCC_TX_OWNED);
-    FLUSH_MEM_WRITE ();
+    ch->txd_usr_add->status |= __constant_cpu_to_le32(MUSYCC_TX_OWNED);
+    FLUSH_MEM_WRITE();
     ch->txd_usr_add = md;
 
-    len = OS_mem_token_tlen (mem_token);
-    atomic_add (len, &ch->tx_pending);
-    atomic_add (len, &ci->tx_pending);
+    len = OS_mem_token_tlen(mem_token);
+    atomic_add(len, &ch->tx_pending);
+    atomic_add(len, &ci->tx_pending);
     ch->s.tx_packets++;
     ch->s.tx_bytes += len;
     /*
@@ -1919,11 +1787,9 @@ musycc_start_xmit (ci_t * ci, int channum, void *mem_token)
      * transmission.
      */
     if (ch->ch_start_tx)
-    {
-        musycc_chan_restart (ch);
-    }
+	musycc_chan_restart(ch);
 #ifdef SBE_WAN256T3_ENABLE
-    wan256t3_led (ci, LED_TX, LEDV_G);
+    wan256t3_led(ci, LED_TX, LEDV_G);
 #endif
     return 0;
 }
diff --git a/drivers/staging/cxt1e1/musycc.h b/drivers/staging/cxt1e1/musycc.h
index cf6b54e..56fb42f 100644
--- a/drivers/staging/cxt1e1/musycc.h
+++ b/drivers/staging/cxt1e1/musycc.h
@@ -48,59 +48,57 @@
 #define INT_QUEUE_SIZE    MUSYCC_NIQD
 
 /* RAM image of MUSYCC registers laid out as a C structure */
-    struct musycc_groupr
-    {
-        VINT32      thp[32];    /* Transmit Head Pointer [5-29]           */
-        VINT32      tmp[32];    /* Transmit Message Pointer [5-30]        */
-        VINT32      rhp[32];    /* Receive Head Pointer [5-29]            */
-        VINT32      rmp[32];    /* Receive Message Pointer [5-30]         */
-        VINT8       ttsm[128];  /* Time Slot Map [5-22]                   */
-        VINT8       tscm[256];  /* Subchannel Map [5-24]                  */
-        VINT32      tcct[32];   /* Channel Configuration [5-26]           */
-        VINT8       rtsm[128];  /* Time Slot Map [5-22]                   */
-        VINT8       rscm[256];  /* Subchannel Map [5-24]                  */
-        VINT32      rcct[32];   /* Channel Configuration [5-26]           */
-        VINT32      __glcd;     /* Global Configuration Descriptor [5-10] */
-        VINT32      __iqp;      /* Interrupt Queue Pointer [5-36]         */
-        VINT32      __iql;      /* Interrupt Queue Length [5-36]          */
-        VINT32      grcd;       /* Group Configuration Descriptor [5-16]  */
-        VINT32      mpd;        /* Memory Protection Descriptor [5-18]    */
-        VINT32      mld;        /* Message Length Descriptor [5-20]       */
-        VINT32      pcd;        /* Port Configuration Descriptor [5-19]   */
-    };
+struct musycc_groupr {
+	VINT32      thp[32];    /* Transmit Head Pointer [5-29]           */
+	VINT32      tmp[32];    /* Transmit Message Pointer [5-30]        */
+	VINT32      rhp[32];    /* Receive Head Pointer [5-29]            */
+	VINT32      rmp[32];    /* Receive Message Pointer [5-30]         */
+	VINT8       ttsm[128];  /* Time Slot Map [5-22]                   */
+	VINT8       tscm[256];  /* Subchannel Map [5-24]                  */
+	VINT32      tcct[32];   /* Channel Configuration [5-26]           */
+	VINT8       rtsm[128];  /* Time Slot Map [5-22]                   */
+	VINT8       rscm[256];  /* Subchannel Map [5-24]                  */
+	VINT32      rcct[32];   /* Channel Configuration [5-26]           */
+	VINT32      __glcd;     /* Global Configuration Descriptor [5-10] */
+	VINT32      __iqp;      /* Interrupt Queue Pointer [5-36]         */
+	VINT32      __iql;      /* Interrupt Queue Length [5-36]          */
+	VINT32      grcd;       /* Group Configuration Descriptor [5-16]  */
+	VINT32      mpd;        /* Memory Protection Descriptor [5-18]    */
+	VINT32      mld;        /* Message Length Descriptor [5-20]       */
+	VINT32      pcd;        /* Port Configuration Descriptor [5-19]   */
+};
 
 /* hardware MUSYCC registers laid out as a C structure */
-    struct musycc_globalr
-    {
-        VINT32      gbp;        /* Group Base Pointer                     */
-        VINT32      dacbp;      /* Dual Address Cycle Base Pointer        */
-        VINT32      srd;        /* Service Request Descriptor             */
-        VINT32      isd;        /* Interrupt Service Descriptor           */
-        /*
-         * adjust __thp due to above 4 registers, which are not contained
-         * within musycc_groupr[]. All __XXX[] are just place holders,
-         * anyhow.
-         */
-        VINT32      __thp[32 - 4];      /* Transmit Head Pointer [5-29]           */
-        VINT32      __tmp[32];  /* Transmit Message Pointer [5-30]        */
-        VINT32      __rhp[32];  /* Receive Head Pointer [5-29]            */
-        VINT32      __rmp[32];  /* Receive Message Pointer [5-30]         */
-        VINT8       ttsm[128];  /* Time Slot Map [5-22]                   */
-        VINT8       tscm[256];  /* Subchannel Map [5-24]                  */
-        VINT32      tcct[32];   /* Channel Configuration [5-26]           */
-        VINT8       rtsm[128];  /* Time Slot Map [5-22]                   */
-        VINT8       rscm[256];  /* Subchannel Map [5-24]                  */
-        VINT32      rcct[32];   /* Channel Configuration [5-26]           */
-        VINT32      glcd;       /* Global Configuration Descriptor [5-10] */
-        VINT32      iqp;        /* Interrupt Queue Pointer [5-36]         */
-        VINT32      iql;        /* Interrupt Queue Length [5-36]          */
-        VINT32      grcd;       /* Group Configuration Descriptor [5-16]  */
-        VINT32      mpd;        /* Memory Protection Descriptor [5-18]    */
-        VINT32      mld;        /* Message Length Descriptor [5-20]       */
-        VINT32      pcd;        /* Port Configuration Descriptor [5-19]   */
-        VINT32      rbist;      /* Receive BIST status [5-4]              */
-        VINT32      tbist;      /* Receive BIST status [5-4]              */
-    };
+struct musycc_globalr {
+	VINT32      gbp;        /* Group Base Pointer                     */
+	VINT32      dacbp;      /* Dual Address Cycle Base Pointer        */
+	VINT32      srd;        /* Service Request Descriptor             */
+	VINT32      isd;        /* Interrupt Service Descriptor           */
+	/*
+	 * adjust __thp due to above 4 registers, which are not contained
+	 * within musycc_groupr[]. All __XXX[] are just place holders,
+	 * anyhow.
+	 */
+	VINT32      __thp[32 - 4];      /* Transmit Head Pointer [5-29]           */
+	VINT32      __tmp[32];  /* Transmit Message Pointer [5-30]        */
+	VINT32      __rhp[32];  /* Receive Head Pointer [5-29]            */
+	VINT32      __rmp[32];  /* Receive Message Pointer [5-30]         */
+	VINT8       ttsm[128];  /* Time Slot Map [5-22]                   */
+	VINT8       tscm[256];  /* Subchannel Map [5-24]                  */
+	VINT32      tcct[32];   /* Channel Configuration [5-26]           */
+	VINT8       rtsm[128];  /* Time Slot Map [5-22]                   */
+	VINT8       rscm[256];  /* Subchannel Map [5-24]                  */
+	VINT32      rcct[32];   /* Channel Configuration [5-26]           */
+	VINT32      glcd;       /* Global Configuration Descriptor [5-10] */
+	VINT32      iqp;        /* Interrupt Queue Pointer [5-36]         */
+	VINT32      iql;        /* Interrupt Queue Length [5-36]          */
+	VINT32      grcd;       /* Group Configuration Descriptor [5-16]  */
+	VINT32      mpd;        /* Memory Protection Descriptor [5-18]    */
+	VINT32      mld;        /* Message Length Descriptor [5-20]       */
+	VINT32      pcd;        /* Port Configuration Descriptor [5-19]   */
+	VINT32      rbist;      /* Receive BIST status [5-4]              */
+	VINT32      tbist;      /* Receive BIST status [5-4]              */
+};
 
 /* Global Config Descriptor bit macros */
 #define MUSYCC_GCD_ECLK_ENABLE  0x00000800      /* EBUS clock enable */
@@ -108,18 +106,18 @@
 #define MUSYCC_GCD_INTA_DISABLE 0x00000008      /* PCI INTA disable */
 #define MUSYCC_GCD_INTB_DISABLE 0x00000004      /* PCI INTB disable */
 #define MUSYCC_GCD_BLAPSE       12      /* Position index for BLAPSE bit
-                                         * field */
+					 * field */
 #define MUSYCC_GCD_ALAPSE       8       /* Position index for ALAPSE bit
-                                         * field */
+					 * field */
 #define MUSYCC_GCD_ELAPSE       4       /* Position index for ELAPSE bit
-                                         * field */
+					 * field */
 #define MUSYCC_GCD_PORTMAP_3    3       /* Reserved */
 #define MUSYCC_GCD_PORTMAP_2    2       /* Port 0=>Grp 0,1,2,3; Port 1=>Grp
-                                         * 4,5,6,7 */
+					 * 4,5,6,7 */
 #define MUSYCC_GCD_PORTMAP_1    1       /* Port 0=>Grp 0,1; Port 1=>Grp 2,3,
-                                         * etc... */
+					 * etc... */
 #define MUSYCC_GCD_PORTMAP_0    0       /* Port 0=>Grp 0; Port 1=>Grp 2,
-                                         * etc... */
+					 * etc... */
 
 /* and board specific assignments... */
 #ifdef SBE_WAN256T3_ENABLE
@@ -137,57 +135,57 @@
 #endif
 
 #define GCD_MAGIC   (((BLAPSE_VAL)<<(MUSYCC_GCD_BLAPSE)) | \
-                     ((ALAPSE_VAL)<<(MUSYCC_GCD_ALAPSE)) | \
-                     ((ELAPSE_VAL)<<(MUSYCC_GCD_ELAPSE)) | \
-                     (MUSYCC_GCD_ECLK_ENABLE) | PORTMAP_VAL)
+		     ((ALAPSE_VAL)<<(MUSYCC_GCD_ALAPSE)) | \
+		     ((ELAPSE_VAL)<<(MUSYCC_GCD_ELAPSE)) | \
+		     (MUSYCC_GCD_ECLK_ENABLE) | PORTMAP_VAL)
 
 /* Group Config Descriptor bit macros */
 #define MUSYCC_GRCD_RX_ENABLE       0x00000001  /* Enable receive processing */
 #define MUSYCC_GRCD_TX_ENABLE       0x00000002  /* Enable transmit processing */
 #define MUSYCC_GRCD_SUBCHAN_DISABLE 0x00000004  /* Master disable for
-                                                 * subchanneling */
+						 * subchanneling */
 #define MUSYCC_GRCD_OOFMP_DISABLE   0x00000008  /* Out of Frame message
-                                                 * processing disabled all
-                                                 * channels */
+						 * processing disabled all
+						 * channels */
 #define MUSYCC_GRCD_OOFIRQ_DISABLE  0x00000010  /* Out of Frame/In Frame irqs
-                                                 * disabled */
+						 * disabled */
 #define MUSYCC_GRCD_COFAIRQ_DISABLE 0x00000020  /* Change of Frame Alignment
-                                                 * irq disabled */
+						 * irq disabled */
 #define MUSYCC_GRCD_INHRBSD         0x00000100  /* Receive Buffer Status
-                                                 * overwrite disabled */
+						 * overwrite disabled */
 #define MUSYCC_GRCD_INHTBSD         0x00000200  /* Transmit Buffer Status
-                                                 * overwrite disabled */
+						 * overwrite disabled */
 #define MUSYCC_GRCD_SF_ALIGN        0x00008000  /* External frame sync */
 #define MUSYCC_GRCD_MC_ENABLE       0x00000040  /* Message configuration bits
-                                                 * copy enable. Conexant sez
-                                                 * turn this on */
+						 * copy enable. Conexant sez
+						 * turn this on */
 #define MUSYCC_GRCD_POLLTH_16       0x00000001  /* Poll every 16th frame */
 #define MUSYCC_GRCD_POLLTH_32       0x00000002  /* Poll every 32nd frame */
 #define MUSYCC_GRCD_POLLTH_64       0x00000003  /* Poll every 64th frame */
 #define MUSYCC_GRCD_POLLTH_SHIFT    10  /* Position index for poll throttle
-                                         * bit field */
+					 * bit field */
 #define MUSYCC_GRCD_SUERM_THRESH_SHIFT 16       /* Position index for SUERM
-                                                 * count threshold */
+						 * count threshold */
 
 /* Port Config Descriptor bit macros */
 #define MUSYCC_PCD_E1X2_MODE       2    /* Port mode in bits 0-2. T1 and E1 */
 #define MUSYCC_PCD_E1X4_MODE       3    /* are defined in cn847x.h */
 #define MUSYCC_PCD_NX64_MODE       4
 #define MUSYCC_PCD_TXDATA_RISING   0x00000010   /* Sample Tx data on TCLK
-                                                 * rising edge */
+						 * rising edge */
 #define MUSYCC_PCD_TXSYNC_RISING   0x00000020   /* Sample Tx frame sync on
-                                                 * TCLK rising edge */
+						 * TCLK rising edge */
 #define MUSYCC_PCD_RXDATA_RISING   0x00000040   /* Sample Rx data on RCLK
-                                                 * rising edge */
+						 * rising edge */
 #define MUSYCC_PCD_RXSYNC_RISING   0x00000080   /* Sample Rx frame sync on
-                                                 * RCLK rising edge */
+						 * RCLK rising edge */
 #define MUSYCC_PCD_ROOF_RISING     0x00000100   /* Sample Rx Out Of Frame
-                                                 * signal on RCLK rising edge */
+						 * signal on RCLK rising edge */
 #define MUSYCC_PCD_TX_DRIVEN       0x00000200   /* No mapped timeslots causes
-                                                 * logic 1 on output, else
-                                                 * tristate */
+						 * logic 1 on output, else
+						 * tristate */
 #define MUSYCC_PCD_PORTMODE_MASK   0xfffffff8   /* For changing the port mode
-                                                 * between E1 and T1 */
+						 * between E1 and T1 */
 
 /* Time Slot Descriptor bit macros */
 #define MUSYCC_TSD_MODE_64KBPS              4
@@ -202,17 +200,17 @@
 #define MUSYCC_CCD_BUFIRQ_DISABLE  0x00000002   /* BUFF and ONR irqs disabled */
 #define MUSYCC_CCD_EOMIRQ_DISABLE  0x00000004   /* EOM irq disabled */
 #define MUSYCC_CCD_MSGIRQ_DISABLE  0x00000008   /* LNG, FCS, ALIGN, and ABT
-                                                 * irqs disabled */
+						 * irqs disabled */
 #define MUSYCC_CCD_IDLEIRQ_DISABLE 0x00000010   /* CHABT, CHIC, and SHT irqs
-                                                 * disabled */
+						 * disabled */
 #define MUSYCC_CCD_FILTIRQ_DISABLE 0x00000020   /* SFILT irq disabled */
 #define MUSYCC_CCD_SDECIRQ_DISABLE 0x00000040   /* SDEC irq disabled */
 #define MUSYCC_CCD_SINCIRQ_DISABLE 0x00000080   /* SINC irq disabled */
 #define MUSYCC_CCD_SUERIRQ_DISABLE 0x00000100   /* SUERR irq disabled */
 #define MUSYCC_CCD_FCS_XFER        0x00000200   /* Propagate FCS along with
-                                                 * received data */
+						 * received data */
 #define MUSYCC_CCD_PROTO_SHIFT     12   /* Position index for protocol bit
-                                         * field */
+					 * field */
 #define MUSYCC_CCD_TRANS           0    /* Protocol mode in bits 12-14 */
 #define MUSYCC_CCD_SS7             1
 #define MUSYCC_CCD_HDLC_FCS16      2
@@ -220,11 +218,11 @@
 #define MUSYCC_CCD_EOPIRQ_DISABLE  0x00008000   /* EOP irq disabled */
 #define MUSYCC_CCD_INVERT_DATA     0x00800000   /* Invert data */
 #define MUSYCC_CCD_MAX_LENGTH      10   /* Position index for max length bit
-                                         * field */
+					 * field */
 #define MUSYCC_CCD_BUFFER_LENGTH   16   /* Position index for internal data
-                                         * buffer length */
+					 * buffer length */
 #define MUSYCC_CCD_BUFFER_LOC      24   /* Position index for internal data
-                                         * buffer starting location */
+					 * buffer starting location */
 
 /****************************************************************************
  * Interrupt Descriptor Information */
@@ -266,7 +264,7 @@
 #define INTRPT_GRP_S           29
 #define INTRPT_GRP_MSB_S       12
 #define INTRPT_GRP(x)          (((x & INTRPT_GRP_M) >> INTRPT_GRP_S) | \
-                               ((x & INTRPT_GRP_MSB_M) >> INTRPT_GRP_MSB_S))
+			       ((x & INTRPT_GRP_MSB_M) >> INTRPT_GRP_MSB_S))
 
 #define INTRPT_CH_M            0x1F000000
 #define INTRPT_CH_S            24
@@ -295,82 +293,82 @@
 
 /* Buffer Descriptor bit macros */
 #define OWNER_BIT       0x80000000      /* Set for MUSYCC owner on xmit, host
-                                         * owner on receive */
+					 * owner on receive */
 #define HOST_TX_OWNED   0x00000000      /* Host owns descriptor */
 #define MUSYCC_TX_OWNED 0x80000000      /* MUSYCC owns descriptor */
 #define HOST_RX_OWNED   0x80000000      /* Host owns descriptor */
 #define MUSYCC_RX_OWNED 0x00000000      /* MUSYCC owns descriptor */
 
 #define POLL_DISABLED   0x40000000      /* MUSYCC not allowed to poll buffer
-                                         * for ownership */
+					 * for ownership */
 #define EOMIRQ_ENABLE   0x20000000      /* This buffer contains the end of
-                                         * the message */
+					 * the message */
 #define EOBIRQ_ENABLE   0x10000000      /* EOB irq enabled */
 #define PADFILL_ENABLE  0x01000000      /* Enable padfill */
 #define REPEAT_BIT      0x00008000      /* Bit on for FISU descriptor */
 #define LENGTH_MASK         0X3fff      /* This part of status descriptor is
-                                         * length */
+					 * length */
 #define IDLE_CODE               25      /* Position index for idle code (2
-                                         * bits) */
+					 * bits) */
 #define EXTRA_FLAGS             16      /* Position index for minimum flags
-                                         * between messages (8 bits) */
+					 * between messages (8 bits) */
 #define IDLE_CODE_MASK        0x03      /* Gets rid of garbage before the
-                                         * pattern is OR'd in */
+					 * pattern is OR'd in */
 #define EXTRA_FLAGS_MASK      0xff      /* Gets rid of garbage before the
-                                         * pattern is OR'd in */
+					 * pattern is OR'd in */
 #define PCI_PERMUTED_OWNER_BIT  0x00000080      /* For flipping the bit on
-                                                 * the polled mode descriptor */
+						 * the polled mode descriptor */
 
 /* Service Request Descriptor bit macros */
 #define SREQ  8                 /* Position index for service request bit
-                                 * field */
+				 * field */
 #define SR_NOOP                 (0<<(SREQ))     /* No Operation. Generates SACK */
 #define SR_CHIP_RESET           (1<<(SREQ))     /* Soft chip reset */
 #define SR_GROUP_RESET          (2<<(SREQ))     /* Group reset */
 #define SR_GLOBAL_INIT          (4<<(SREQ))     /* Global init: read global
-                                                 * config deswc and interrupt
-                                                 * queue desc */
+						 * config deswc and interrupt
+						 * queue desc */
 #define SR_GROUP_INIT           (5<<(SREQ))     /* Group init: read Timeslot
-                                                 * and Subchannel maps,
-                                                 * Channel Config, */
+						 * and Subchannel maps,
+						 * Channel Config, */
     /*
      * Group Config, Memory Protect, Message Length, and Port Config
      * Descriptors
      */
 #define SR_CHANNEL_ACTIVATE     (8<<(SREQ))     /* Init channel, read Head
-                                                 * Pointer, process first
-                                                 * Message Descriptor */
+						 * Pointer, process first
+						 * Message Descriptor */
 #define SR_GCHANNEL_MASK        0x001F          /* channel portion (gchan) */
 #define SR_CHANNEL_DEACTIVATE   (9<<(SREQ))     /* Stop channel processing */
 #define SR_JUMP                 (10<<(SREQ))    /* a: Process new Message
-                                                 * List */
+						 * List */
 #define SR_CHANNEL_CONFIG       (11<<(SREQ))    /* b: Read channel
-                                                 * Configuration Descriptor */
+						 * Configuration Descriptor */
 #define SR_GLOBAL_CONFIG        (16<<(SREQ))    /* 10: Read Global
-                                                 * Configuration Descriptor */
+						 * Configuration Descriptor */
 #define SR_INTERRUPT_Q          (17<<(SREQ))    /* 11: Read Interrupt Queue
-                                                 * Descriptor */
+						 * Descriptor */
 #define SR_GROUP_CONFIG         (18<<(SREQ))    /* 12: Read Group
-                                                 * Configuration Descriptor */
+						 * Configuration Descriptor */
 #define SR_MEMORY_PROTECT       (19<<(SREQ))    /* 13: Read Memory Protection
-                                                 * Descriptor */
+						 * Descriptor */
 #define SR_MESSAGE_LENGTH       (20<<(SREQ))    /* 14: Read Message Length
-                                                 * Descriptor */
+						 * Descriptor */
 #define SR_PORT_CONFIG          (21<<(SREQ))    /* 15: Read Port
-                                                 * Configuration Descriptor */
+						 * Configuration Descriptor */
 #define SR_TIMESLOT_MAP         (24<<(SREQ))    /* 18: Read Timeslot Map */
 #define SR_SUBCHANNEL_MAP       (25<<(SREQ))    /* 19: Read Subchannel Map */
 #define SR_CHAN_CONFIG_TABLE    (26<<(SREQ))    /* 20: Read Channel
-                                                 * Configuration Table for
-                                                 * the group */
+						 * Configuration Table for
+						 * the group */
 #define SR_TX_DIRECTION         0x00000020      /* Transmit direction bit.
-                                                 * Bit off indicates receive
-                                                 * direction */
+						 * Bit off indicates receive
+						 * direction */
 #define SR_RX_DIRECTION         0x00000000
 
 /* Interrupt Descriptor bit macros */
 #define GROUP10                     29  /* Position index for the 2 LS group
-                                         * bits */
+					 * bits */
 #define CHANNEL                     24  /* Position index for channel bits */
 #define INT_IQD_TX          0x80000000
 #define INT_IQD_GRP         0x60000000
@@ -384,7 +382,7 @@
 /* Interrupt Descriptor Events */
 #define EVE_EVENT               20      /* Position index for event bits */
 #define EVE_NONE                0       /* No event to report in this
-                                         * interrupt */
+					 * interrupt */
 #define EVE_SACK                1       /* Service Request acknowledge */
 #define EVE_EOB                 2       /* End of Buffer */
 #define EVE_EOM                 3       /* End of Message */
@@ -411,12 +409,12 @@
 #define ERR_PERR                15      /* PCI Parity Error */
 /* Other Stuff */
 #define TRANSMIT_DIRECTION  0x80000000  /* Transmit direction bit. Bit off
-                                         * indicates receive direction */
+					 * indicates receive direction */
 #define ILOST               0x00008000  /* Interrupt Lost */
 #define GROUPMSB            0x00004000  /* Group number MSB */
 #define SACK_IMAGE          0x00100000  /* Used in IRQ for semaphore test */
 #define INITIAL_STATUS      0x10000     /* IRQ status should be this after
-                                         * reset */
+					 * reset */
 
 /*  This must be defined on an entire channel group (Port) basis */
 #define SUERM_THRESHOLD     0x1f
diff --git a/drivers/staging/cxt1e1/sbecrc.c b/drivers/staging/cxt1e1/sbecrc.c
index 3f3cd60..87512a5 100644
--- a/drivers/staging/cxt1e1/sbecrc.c
+++ b/drivers/staging/cxt1e1/sbecrc.c
@@ -44,25 +44,23 @@ static u_int32_t CRCTable[CRC_TABLE_ENTRIES];
 ***************************************************************************/
 
 static void
-genCrcTable (u_int32_t *CRCTable)
+genCrcTable(u_int32_t *CRCTable)
 {
-    int         ii, jj;
-    u_int32_t      crc;
-
-    for (ii = 0; ii < CRC_TABLE_ENTRIES; ii++)
-    {
-        crc = ii;
-        for (jj = 8; jj > 0; jj--)
-        {
-            if (crc & 1)
-                crc = (crc >> 1) ^ CRC32_POLYNOMIAL;
-            else
-                crc >>= 1;
-        }
-        CRCTable[ii] = crc;
-    }
-
-    crcTableInit++;
+	int         ii, jj;
+	u_int32_t      crc;
+
+	for (ii = 0; ii < CRC_TABLE_ENTRIES; ii++) {
+		crc = ii;
+		for (jj = 8; jj > 0; jj--) {
+			if (crc & 1)
+				crc = (crc >> 1) ^ CRC32_POLYNOMIAL;
+			else
+				crc >>= 1;
+		}
+		CRCTable[ii] = crc;
+	}
+
+	crcTableInit++;
 }
 
 
@@ -85,52 +83,49 @@ genCrcTable (u_int32_t *CRCTable)
 */
 
 void
-sbeCrc (u_int8_t *buffer,          /* data buffer to crc */
-        u_int32_t count,           /* length of block in bytes */
-        u_int32_t initialCrc,      /* starting CRC */
-        u_int32_t *result)
+sbeCrc(u_int8_t *buffer,          /* data buffer to crc */
+	u_int32_t count,           /* length of block in bytes */
+	u_int32_t initialCrc,      /* starting CRC */
+	u_int32_t *result)
 {
-    u_int32_t     *tbl = 0;
-    u_int32_t      temp1, temp2, crc;
-
-    /*
-     * if table not yet created, do so. Don't care about "extra" time
-     * checking this every time sbeCrc() is called, since CRC calculations are
-     * already time consuming
-     */
-    if (!crcTableInit)
-    {
+	u_int32_t     *tbl = 0;
+	u_int32_t      temp1, temp2, crc;
+
+	/*
+	* if table not yet created, do so. Don't care about "extra" time
+	* checking this every time sbeCrc() is called, since CRC calculations
+	* are already time consuming
+	*/
+	if (!crcTableInit) {
 #ifdef STATIC_CRC_TABLE
-        tbl = &CRCTable;
-        genCrcTable (tbl);
+		tbl = &CRCTable;
+		genCrcTable(tbl);
 #else
-        tbl = (u_int32_t *) OS_kmalloc (CRC_TABLE_ENTRIES * sizeof (u_int32_t));
-        if (tbl == 0)
-        {
-            *result = 0;            /* dummy up return value due to malloc
-                                     * failure */
-            return;
-        }
-        genCrcTable (tbl);
+		tbl = (u_int32_t *) OS_kmalloc(CRC_TABLE_ENTRIES * sizeof(u_int32_t));
+		if (tbl == 0) {
+			*result = 0;   /* dummy up return value due to malloc
+					* failure */
+			return;
+		}
+		genCrcTable(tbl);
 #endif
-    }
-    /* inverting bits makes ZMODEM & PKZIP compatible */
-    crc = initialCrc ^ 0xFFFFFFFFL;
+	}
+	/* inverting bits makes ZMODEM & PKZIP compatible */
+	crc = initialCrc ^ 0xFFFFFFFFL;
 
-    while (count-- != 0)
-    {
-        temp1 = (crc >> 8) & 0x00FFFFFFL;
-        temp2 = tbl[((int) crc ^ *buffer++) & 0xff];
-        crc = temp1 ^ temp2;
-    }
+	while (count-- != 0) {
+		temp1 = (crc >> 8) & 0x00FFFFFFL;
+		temp2 = tbl[((int) crc ^ *buffer++) & 0xff];
+		crc = temp1 ^ temp2;
+	}
 
-    crc ^= 0xFFFFFFFFL;
+	crc ^= 0xFFFFFFFFL;
 
-    *result = crc;
+	*result = crc;
 
 #ifndef STATIC_CRC_TABLE
-    crcTableInit = 0;
-    OS_kfree (tbl);
+	crcTableInit = 0;
+	OS_kfree(tbl);
 #endif
 }
 
diff --git a/drivers/staging/dgrp/dgrp_common.h b/drivers/staging/dgrp/dgrp_common.h
index 05ff338..0583fe9 100644
--- a/drivers/staging/dgrp/dgrp_common.h
+++ b/drivers/staging/dgrp/dgrp_common.h
@@ -31,7 +31,6 @@
  * All global storage allocation.
  ************************************************************************/
 
-extern int dgrp_rawreadok;  /* Allow raw writing of input */
 extern int dgrp_register_cudevices; /* enable legacy cu devices */
 extern int dgrp_register_prdevices; /* enable transparent print devices */
 extern int dgrp_poll_tick;          /* Poll interval - in ms */
diff --git a/drivers/staging/dgrp/dgrp_dpa_ops.c b/drivers/staging/dgrp/dgrp_dpa_ops.c
index 49e6709..021cca4 100644
--- a/drivers/staging/dgrp/dgrp_dpa_ops.c
+++ b/drivers/staging/dgrp/dgrp_dpa_ops.c
@@ -387,7 +387,7 @@ static long dgrp_dpa_ioctl(struct file *file, unsigned int cmd,
 
 		port = getchan.ch_port;
 
-		if (port < 0 || port > nd->nd_chan_count)
+		if (port > nd->nd_chan_count)
 			return -EINVAL;
 
 		ch = nd->nd_chan + port;
diff --git a/drivers/staging/dgrp/dgrp_driver.c b/drivers/staging/dgrp/dgrp_driver.c
index 6e4a0eb..aa26258 100644
--- a/drivers/staging/dgrp/dgrp_driver.c
+++ b/drivers/staging/dgrp/dgrp_driver.c
@@ -39,14 +39,10 @@ MODULE_VERSION(DIGI_VERSION);
 struct list_head nd_struct_list;
 struct dgrp_poll_data dgrp_poll_data;
 
-int dgrp_rawreadok = 1;		/* Bypass flipbuf on input */
 int dgrp_register_cudevices = 1;/* Turn on/off registering legacy cu devices */
 int dgrp_register_prdevices = 1;/* Turn on/off registering transparent print */
 int dgrp_poll_tick = 20;	/* Poll interval - in ms */
 
-module_param_named(rawreadok, dgrp_rawreadok, int, 0644);
-MODULE_PARM_DESC(rawreadok, "Bypass flip buffers on input");
-
 module_param_named(register_cudevices, dgrp_register_cudevices, int, 0644);
 MODULE_PARM_DESC(register_cudevices, "Turn on/off registering legacy cu devices");
 
diff --git a/drivers/staging/dgrp/dgrp_net_ops.c b/drivers/staging/dgrp/dgrp_net_ops.c
index ab839ea..2d1bbfd 100644
--- a/drivers/staging/dgrp/dgrp_net_ops.c
+++ b/drivers/staging/dgrp/dgrp_net_ops.c
@@ -151,20 +151,15 @@ static void dgrp_read_data_block(struct ch_struct *ch, u8 *flipbuf,
  * Copys the rbuf to the flipbuf and sends to line discipline.
  * Sends input buffer data to the line discipline.
  *
- * There are several modes to consider here:
- *    rawreadok, tty->real_raw, and IF_PARMRK
  */
 static void dgrp_input(struct ch_struct *ch)
 {
 	struct nd_struct *nd;
 	struct tty_struct *tty;
-	int remain;
 	int data_len;
 	int len;
-	int flip_len;
 	int tty_count;
 	ulong lock_flags;
-	struct tty_ldisc *ld;
 	u8  *myflipbuf;
 	u8  *myflipflagbuf;
 
@@ -212,37 +207,11 @@ static void dgrp_input(struct ch_struct *ch)
 
 	spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
 
-	/* Decide how much data we can send into the tty layer */
-	if (dgrp_rawreadok && tty->real_raw)
-		flip_len = MYFLIPLEN;
-	else
-		flip_len = TTY_FLIPBUF_SIZE;
-
 	/* data_len should be the number of chars that we read in */
 	data_len = (ch->ch_rin - ch->ch_rout) & RBUF_MASK;
-	remain = data_len;
 
 	/* len is the amount of data we are going to transfer here */
-	len = min(data_len, flip_len);
-
-	/* take into consideration length of ldisc */
-	len = min(len, (N_TTY_BUF_SIZE - 1) - tty->read_cnt);
-
-	ld = tty_ldisc_ref(tty);
-
-	/*
-	 * If we were unable to get a reference to the ld,
-	 * don't flush our buffer, and act like the ld doesn't
-	 * have any space to put the data right now.
-	 */
-	if (!ld) {
-		len = 0;
-	} else if (!ld->ops->receive_buf) {
-		spin_lock_irqsave(&nd->nd_lock, lock_flags);
-		ch->ch_rout = ch->ch_rin;
-		spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
-		len = 0;
-	}
+	len = tty_buffer_request_room(tty, data_len);
 
 	/* Check DPA flow control */
 	if ((nd->nd_dpa_debug) &&
@@ -254,42 +223,22 @@ static void dgrp_input(struct ch_struct *ch)
 
 		dgrp_read_data_block(ch, myflipbuf, len);
 
-		/*
-		 * In high performance mode, we don't have to update
-		 * flag_buf or any of the counts or pointers into flip buf.
-		 */
-		if (!dgrp_rawreadok || !tty->real_raw) {
-			if (I_PARMRK(tty) || I_BRKINT(tty) || I_INPCK(tty))
-				parity_scan(ch, myflipbuf, myflipflagbuf, &len);
-			else
-				memset(myflipflagbuf, TTY_NORMAL, len);
-		}
+		if (I_PARMRK(tty) || I_BRKINT(tty) || I_INPCK(tty))
+			parity_scan(ch, myflipbuf, myflipflagbuf, &len);
+		else
+			memset(myflipflagbuf, TTY_NORMAL, len);
 
 		if ((nd->nd_dpa_debug) &&
 		    (nd->nd_dpa_port == PORT_NUM(MINOR(tty_devnum(tty)))))
 			dgrp_dpa_data(nd, 1, myflipbuf, len);
 
-		/*
-		 * If we're doing raw reads, jam it right into the
-		 * line disc bypassing the flip buffers.
-		 */
-		if (dgrp_rawreadok && tty->real_raw)
-			ld->ops->receive_buf(tty, myflipbuf, NULL, len);
-		else {
-			len = tty_buffer_request_room(tty, len);
-			tty_insert_flip_string_flags(tty, myflipbuf,
-						     myflipflagbuf, len);
-
-			/* Tell the tty layer its okay to "eat" the data now */
-			tty_flip_buffer_push(tty);
-		}
+		tty_insert_flip_string_flags(tty, myflipbuf,
+					     myflipflagbuf, len);
+		tty_flip_buffer_push(tty);
 
 		ch->ch_rxcount += len;
 	}
 
-	if (ld)
-		tty_ldisc_deref(ld);
-
 	/*
 	 * Wake up any sleepers (maybe dgrp close) that might be waiting
 	 * for a channel flag state change.
@@ -1057,13 +1006,13 @@ static int dgrp_net_release(struct inode *inode, struct file *file)
 
 	spin_unlock_irqrestore(&dgrp_poll_data.poll_lock, lock_flags);
 
-done:
 	down(&nd->nd_net_semaphore);
 
 	dgrp_monitor_message(nd, "Net Close");
 
 	up(&nd->nd_net_semaphore);
 
+done:
 	module_put(THIS_MODULE);
 	file->private_data = NULL;
 	return 0;
@@ -1671,6 +1620,9 @@ static int dgrp_send(struct nd_struct *nd, long tmax)
 				 * do the job.
 				 */
 
+				/* FIXME: jiffies - ch->ch_waketime can never
+				   be < 0. Someone needs to work out what is
+				   actually intended here */
 				if (ch->ch_pun.un_open_count &&
 				    (ch->ch_pun.un_flag &
 				    (UN_EMPTY|UN_TIME|UN_LOW|UN_PWAIT)) != 0) {
@@ -2546,7 +2498,7 @@ data:
 
 			/*
 			 *  Fabricate and insert a data packet header to
-			 *  preceed the remaining data when it comes in.
+			 *  preced the remaining data when it comes in.
 			 */
 
 			if (remain < plen) {
@@ -2715,7 +2667,7 @@ data:
 						}
 
 						/*
-						 *  Handle delayed response arrival preceeding
+						 *  Handle delayed response arrival preceding
 						 *  the open response we are waiting for.
 						 */
 
@@ -3553,7 +3505,7 @@ void dgrp_poll_handler(unsigned long arg)
 		/*
 		 * Decrement statistics.  These are only for use with
 		 * KME, so don't worry that the operations are done
-		 * unlocked, and so the results are occassionally wrong.
+		 * unlocked, and so the results are occasionally wrong.
 		 */
 
 		nd->nd_read_count -= (nd->nd_read_count +
diff --git a/drivers/staging/dgrp/dgrp_specproc.c b/drivers/staging/dgrp/dgrp_specproc.c
index 24327c3..c214078 100644
--- a/drivers/staging/dgrp/dgrp_specproc.c
+++ b/drivers/staging/dgrp/dgrp_specproc.c
@@ -629,8 +629,6 @@ static int info_proc_show(struct seq_file *m, void *v)
 {
 	seq_printf(m, "version: %s\n", DIGI_VERSION);
 	seq_puts(m, "register_with_sysfs: 1\n");
-	seq_printf(m, "rawreadok: 0x%08x\t(%d)\n",
-		   dgrp_rawreadok, dgrp_rawreadok);
 	seq_printf(m, "pollrate: 0x%08x\t(%d)\n",
 		   dgrp_poll_tick, dgrp_poll_tick);
 
@@ -754,6 +752,8 @@ static int dgrp_add_id(long id)
 
 	return 0;
 
+	/* FIXME this guy should free the tty driver stored in nd and destroy
+	 * all channel ports */
 error_out:
 	kfree(nd);
 	return ret;
diff --git a/drivers/staging/dgrp/dgrp_sysfs.c b/drivers/staging/dgrp/dgrp_sysfs.c
index e5a3c88..be179ad 100644
--- a/drivers/staging/dgrp/dgrp_sysfs.c
+++ b/drivers/staging/dgrp/dgrp_sysfs.c
@@ -17,7 +17,6 @@
 #include "dgrp_common.h"
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/ctype.h>
 #include <linux/string.h>
@@ -55,23 +54,6 @@ static DEVICE_ATTR(register_with_sysfs, 0400,
 		   dgrp_class_register_with_sysfs_show, NULL);
 
 
-static ssize_t dgrp_class_rawreadok_show(struct device *c,
-					 struct device_attribute *attr,
-					 char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", dgrp_rawreadok);
-}
-static ssize_t dgrp_class_rawreadok_store(struct device *c,
-					  struct device_attribute *attr,
-					  const char *buf, size_t count)
-{
-	sscanf(buf, "0x%x\n", &dgrp_rawreadok);
-	return count;
-}
-static DEVICE_ATTR(rawreadok, 0600, dgrp_class_rawreadok_show,
-		   dgrp_class_rawreadok_store);
-
-
 static ssize_t dgrp_class_pollrate_show(struct device *c,
 					struct device_attribute *attr,
 					char *buf)
@@ -91,7 +73,6 @@ static DEVICE_ATTR(pollrate, 0600, dgrp_class_pollrate_show,
 
 static struct attribute *dgrp_sysfs_global_settings_entries[] = {
 	&dev_attr_pollrate.attr,
-	&dev_attr_rawreadok.attr,
 	&dev_attr_register_with_sysfs.attr,
 	NULL
 };
@@ -177,7 +158,7 @@ static ssize_t dgrp_node_description_show(struct device *c,
 	if (!nd)
 		return 0;
 
-	if (nd->nd_state == NS_READY && nd->nd_ps_desc)
+	if (nd->nd_state == NS_READY)
 		return snprintf(buf, PAGE_SIZE, "%s\n", nd->nd_ps_desc);
 	return 0;
 }
diff --git a/drivers/staging/dgrp/dgrp_tty.c b/drivers/staging/dgrp/dgrp_tty.c
index e125b03..51d3ed3 100644
--- a/drivers/staging/dgrp/dgrp_tty.c
+++ b/drivers/staging/dgrp/dgrp_tty.c
@@ -432,7 +432,7 @@ static void drp_param(struct ch_struct *ch)
 	/*
 	 * From the POSIX.1 spec (7.1.2.6): "If {_POSIX_VDISABLE}
 	 * is defined for the terminal device file, and the value
-	 * of one of the changable special control characters (see
+	 * of one of the changeable special control characters (see
 	 * 7.1.1.9) is {_POSIX_VDISABLE}, that function shall be
 	 * disabled, that is, no input data shall be recognized as
 	 * the disabled special character."
@@ -2265,9 +2265,7 @@ static int get_modem_info(struct ch_struct *ch, unsigned int *value)
 		| ((mlast & DM_RI)  ? TIOCM_RNG : 0)
 		| ((mlast & DM_DSR) ? TIOCM_DSR : 0)
 		| ((mlast & DM_CTS) ? TIOCM_CTS : 0);
-	put_user(mlast, (unsigned int __user *) value);
-
-	return 0;
+	return put_user(mlast, (unsigned int __user *) value);
 }
 
 /*
@@ -2285,7 +2283,8 @@ static int set_modem_info(struct ch_struct *ch, unsigned int command,
 	if (error == 0)
 		return -EFAULT;
 
-	get_user(arg, (unsigned int __user *) value);
+	if (get_user(arg, (unsigned int __user *) value))
+		return -EFAULT;
 	mval |= ((arg & TIOCM_RTS) ? DM_RTS : 0)
 		| ((arg & TIOCM_DTR) ? DM_DTR : 0);
 
@@ -2615,21 +2614,6 @@ static int dgrp_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
 		 */
 		return 0;
 
-	case TIOCGSOFTCAR:
-		rc = access_ok(VERIFY_WRITE, (void __user *) arg,
-			       sizeof(long));
-		if (rc == 0)
-			return -EFAULT;
-		put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) arg);
-		return 0;
-
-	case TIOCSSOFTCAR:
-		get_user(arg, (unsigned long __user *) arg);
-		tty->termios.c_cflag =
-			((tty->termios.c_cflag & ~CLOCAL) |
-			 (arg ? CLOCAL : 0));
-		return 0;
-
 	case TIOCMGET:
 		rc = access_ok(VERIFY_WRITE, (void __user *) arg,
 				 sizeof(unsigned int));
@@ -2699,7 +2683,7 @@ static int dgrp_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
 	- looking at the tty_ioctl code, these command all call our
 	tty_set_termios at the driver's end, when a TCSETA* is sent,
 	it is expecting the tty to have a termio structure,
-	NOT a termios stucture.  These two structures differ in size
+	NOT a termios structure.  These two structures differ in size
 	and the tty_ioctl code does a conversion before processing them both.
 	- we should treat the TCSETAW TCSETAF ioctls the same, and let
 	the tty_ioctl code do the conversion stuff.
@@ -2851,17 +2835,16 @@ static int dgrp_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
 		break;
 
 	case DIGI_GETCUSTOMBAUD:
-		rc = access_ok(VERIFY_WRITE, (void __user *) arg, sizeof(int));
-		if (rc == 0)
+		if (put_user(ch->ch_custom_speed, (unsigned int __user *) arg))
 			return -EFAULT;
-		put_user(ch->ch_custom_speed, (unsigned int __user *) arg);
 		break;
 
 	case DIGI_SETCUSTOMBAUD:
 	{
 		int new_rate;
 
-		get_user(new_rate, (unsigned int __user *) arg);
+		if (get_user(new_rate, (unsigned int __user *) arg))
+			return -EFAULT;
 		dgrp_set_custom_speed(ch, new_rate);
 
 		break;
@@ -2996,7 +2979,7 @@ static void dgrp_tty_start(struct tty_struct *tty)
 }
 
 /*
- *	Stop the reciever
+ *	Stop the receiver
  */
 static void dgrp_tty_input_stop(struct tty_struct *tty)
 {
@@ -3119,6 +3102,7 @@ static void dgrp_tty_hangup(struct tty_struct *tty)
 void
 dgrp_tty_uninit(struct nd_struct *nd)
 {
+	unsigned int i;
 	char id[3];
 
 	ID_TO_CHAR(nd->nd_ID, id);
@@ -3152,6 +3136,8 @@ dgrp_tty_uninit(struct nd_struct *nd)
 		put_tty_driver(nd->nd_xprint_ttdriver);
 		nd->nd_ttdriver_flags &= ~XPRINT_TTDRV_REG;
 	}
+	for (i = 0; i < CHAN_MAX; i++)
+		tty_port_destroy(&nd->nd_chan[i].port);
 }
 
 
@@ -3335,7 +3321,6 @@ dgrp_tty_init(struct nd_struct *nd)
 		init_waitqueue_head(&(ch->ch_pun.un_open_wait));
 		init_waitqueue_head(&(ch->ch_pun.un_close_wait));
 		tty_port_init(&ch->port);
-		tty_port_init(&ch->port);
 	}
 	return 0;
 }
diff --git a/drivers/staging/et131x/README b/drivers/staging/et131x/README
index 8265723..38537d4 100644
--- a/drivers/staging/et131x/README
+++ b/drivers/staging/et131x/README
@@ -8,7 +8,7 @@ Note, the powermanagement options were removed from the vendor provided
 driver as they did not build properly at the time.
 
 TODO:
-	- Use of kmem_cache seems a bit unusual
+	- some rx packets have CRC/code/frame errors
 
 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 413da0d..84bbcd4 100644
--- a/drivers/staging/et131x/et131x.c
+++ b/drivers/staging/et131x/et131x.c
@@ -143,7 +143,6 @@ MODULE_DESCRIPTION("10/100/1000 Base-T Ethernet Driver for the ET1310 by Agere S
 #define fMP_DEST_BROAD			0x00000002
 
 /* MP_ADAPTER flags */
-#define fMP_ADAPTER_RECV_LOOKASIDE	0x00000004
 #define fMP_ADAPTER_INTERRUPT_IN_USE	0x00000008
 
 /* MP_SHARED flags */
@@ -176,22 +175,14 @@ MODULE_DESCRIPTION("10/100/1000 Base-T Ethernet Driver for the ET1310 by Agere S
 #define PARM_DMA_CACHE_DEF      0
 
 /* RX defines */
-#define USE_FBR0 1
-#define FBR_CHUNKS 32
-#define MAX_DESC_PER_RING_RX         1024
+#define FBR_CHUNKS		32
+#define MAX_DESC_PER_RING_RX	1024
 
 /* number of RFDs - default and min */
-#ifdef USE_FBR0
 #define RFD_LOW_WATER_MARK	40
 #define NIC_DEFAULT_NUM_RFD	1024
 #define NUM_FBRS		2
-#else
-#define RFD_LOW_WATER_MARK	20
-#define NIC_DEFAULT_NUM_RFD	256
-#define NUM_FBRS		1
-#endif
 
-#define NIC_MIN_NUM_RFD		64
 #define NUM_PACKETS_HANDLED	256
 
 #define ALCATEL_MULTICAST_PKT	0x01000000
@@ -291,29 +282,20 @@ struct rx_status_block {
  */
 struct fbr_lookup {
 	void		*virt[MAX_DESC_PER_RING_RX];
-	void		*buffer1[MAX_DESC_PER_RING_RX];
-	void		*buffer2[MAX_DESC_PER_RING_RX];
 	u32		 bus_high[MAX_DESC_PER_RING_RX];
 	u32		 bus_low[MAX_DESC_PER_RING_RX];
 	void		*ring_virtaddr;
 	dma_addr_t	 ring_physaddr;
 	void		*mem_virtaddrs[MAX_DESC_PER_RING_RX / FBR_CHUNKS];
 	dma_addr_t	 mem_physaddrs[MAX_DESC_PER_RING_RX / FBR_CHUNKS];
-	u64		 real_physaddr;
-	u64		 offset;
 	u32		 local_full;
 	u32		 num_entries;
-	u32		 buffsize;
+	dma_addr_t	 buffsize;
 };
 
 /*
  * struct rx_ring is the sructure representing the adaptor's local
  * reference(s) to the rings
- *
- ******************************************************************************
- * IMPORTANT NOTE :- fbr_lookup *fbr[NUM_FBRS] uses index 0 to refer to FBR1
- *			and index 1 to refer to FRB0
- ******************************************************************************
  */
 struct rx_ring {
 	struct fbr_lookup *fbr[NUM_FBRS];
@@ -332,9 +314,6 @@ struct rx_ring {
 	u32 num_rfd;
 
 	bool unfinished_receives;
-
-	/* lookaside lists */
-	struct kmem_cache *recv_lookaside;
 };
 
 /* TX defines */
@@ -866,28 +845,27 @@ static void et131x_rx_dma_enable(struct et131x_adapter *adapter)
 	/* Setup the receive dma configuration register for normal operation */
 	u32 csr =  0x2000;	/* FBR1 enable */
 
-	if (adapter->rx_ring.fbr[0]->buffsize == 4096)
+	if (adapter->rx_ring.fbr[1]->buffsize == 4096)
 		csr |= 0x0800;
-	else if (adapter->rx_ring.fbr[0]->buffsize == 8192)
+	else if (adapter->rx_ring.fbr[1]->buffsize == 8192)
 		csr |= 0x1000;
-	else if (adapter->rx_ring.fbr[0]->buffsize == 16384)
+	else if (adapter->rx_ring.fbr[1]->buffsize == 16384)
 		csr |= 0x1800;
-#ifdef USE_FBR0
+
 	csr |= 0x0400;		/* FBR0 enable */
-	if (adapter->rx_ring.fbr[1]->buffsize == 256)
+	if (adapter->rx_ring.fbr[0]->buffsize == 256)
 		csr |= 0x0100;
-	else if (adapter->rx_ring.fbr[1]->buffsize == 512)
+	else if (adapter->rx_ring.fbr[0]->buffsize == 512)
 		csr |= 0x0200;
-	else if (adapter->rx_ring.fbr[1]->buffsize == 1024)
+	else if (adapter->rx_ring.fbr[0]->buffsize == 1024)
 		csr |= 0x0300;
-#endif
 	writel(csr, &adapter->regs->rxdma.csr);
 
 	csr = readl(&adapter->regs->rxdma.csr);
-	if ((csr & 0x00020000) != 0) {
+	if (csr & 0x00020000) {
 		udelay(5);
 		csr = readl(&adapter->regs->rxdma.csr);
-		if ((csr & 0x00020000) != 0) {
+		if (csr & 0x00020000) {
 			dev_err(&adapter->pdev->dev,
 			    "RX Dma failed to exit halt state.  CSR 0x%08x\n",
 				csr);
@@ -1758,22 +1736,8 @@ static void et1310_phy_power_down(struct et131x_adapter *adapter, bool down)
  */
 static void et131x_xcvr_init(struct et131x_adapter *adapter)
 {
-	u16 imr;
-	u16 isr;
 	u16 lcr2;
 
-	et131x_mii_read(adapter, PHY_INTERRUPT_STATUS, &isr);
-	et131x_mii_read(adapter, PHY_INTERRUPT_MASK, &imr);
-
-	/* Set the link status interrupt only.  Bad behavior when link status
-	 * and auto neg are set, we run into a nested interrupt problem
-	 */
-	imr |= (ET_PHY_INT_MASK_AUTONEGSTAT |
-		ET_PHY_INT_MASK_LINKSTAT |
-		ET_PHY_INT_MASK_ENABLE);
-
-	et131x_mii_write(adapter, PHY_INTERRUPT_MASK, imr);
-
 	/* Set the LED behavior such that LED 1 indicates speed (off =
 	 * 10Mbits, blink = 100Mbits, on = 1000Mbits) and LED 2 indicates
 	 * link and activity (on for link, blink off for activity).
@@ -1798,7 +1762,7 @@ static void et131x_xcvr_init(struct et131x_adapter *adapter)
 }
 
 /**
- * et131x_configure_global_regs	-	configure JAGCore global regs
+ * et131x_configure_global_regs	- configure JAGCore global regs
  * @adapter: pointer to our adapter structure
  *
  * Used to configure the global registers on the JAGCore
@@ -1856,29 +1820,22 @@ static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter)
 	u32 entry;
 	u32 psr_num_des;
 	unsigned long flags;
+	u8 id;
 
 	/* Halt RXDMA to perform the reconfigure.  */
 	et131x_rx_dma_disable(adapter);
 
-	/* Load the completion writeback physical address
-	 *
-	 * NOTE : dma_alloc_coherent(), used above to alloc DMA regions,
-	 * ALWAYS returns SAC (32-bit) addresses. If DAC (64-bit) addresses
-	 * are ever returned, make sure the high part is retrieved here
-	 * before storing the adjusted address.
-	 */
-	writel((u32) ((u64)rx_local->rx_status_bus >> 32),
-	       &rx_dma->dma_wb_base_hi);
-	writel((u32) rx_local->rx_status_bus, &rx_dma->dma_wb_base_lo);
+	/* Load the completion writeback physical address */
+	writel(upper_32_bits(rx_local->rx_status_bus), &rx_dma->dma_wb_base_hi);
+	writel(lower_32_bits(rx_local->rx_status_bus), &rx_dma->dma_wb_base_lo);
 
 	memset(rx_local->rx_status_block, 0, sizeof(struct rx_status_block));
 
 	/* Set the address and parameters of the packet status ring into the
 	 * 1310's registers
 	 */
-	writel((u32) ((u64)rx_local->ps_ring_physaddr >> 32),
-	       &rx_dma->psr_base_hi);
-	writel((u32) rx_local->ps_ring_physaddr, &rx_dma->psr_base_lo);
+	writel(upper_32_bits(rx_local->ps_ring_physaddr), &rx_dma->psr_base_hi);
+	writel(lower_32_bits(rx_local->ps_ring_physaddr), &rx_dma->psr_base_lo);
 	writel(rx_local->psr_num_entries - 1, &rx_dma->psr_num_des);
 	writel(0, &rx_dma->psr_full_offset);
 
@@ -1891,56 +1848,56 @@ static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter)
 	/* These local variables track the PSR in the adapter structure */
 	rx_local->local_psr_full = 0;
 
-	/* Now's the best time to initialize FBR1 contents */
-	fbr_entry = (struct fbr_desc *) rx_local->fbr[0]->ring_virtaddr;
-	for (entry = 0; entry < rx_local->fbr[0]->num_entries; entry++) {
-		fbr_entry->addr_hi = rx_local->fbr[0]->bus_high[entry];
-		fbr_entry->addr_lo = rx_local->fbr[0]->bus_low[entry];
-		fbr_entry->word2 = entry;
-		fbr_entry++;
-	}
-
-	/* Set the address and parameters of Free buffer ring 1 (and 0 if
-	 * required) into the 1310's registers
-	 */
-	writel((u32) (rx_local->fbr[0]->real_physaddr >> 32),
-	       &rx_dma->fbr1_base_hi);
-	writel((u32) rx_local->fbr[0]->real_physaddr, &rx_dma->fbr1_base_lo);
-	writel(rx_local->fbr[0]->num_entries - 1, &rx_dma->fbr1_num_des);
-	writel(ET_DMA10_WRAP, &rx_dma->fbr1_full_offset);
-
-	/* This variable tracks the free buffer ring 1 full position, so it
-	 * has to match the above.
-	 */
-	rx_local->fbr[0]->local_full = ET_DMA10_WRAP;
-	writel(
-	   ((rx_local->fbr[0]->num_entries * LO_MARK_PERCENT_FOR_RX) / 100) - 1,
-	   &rx_dma->fbr1_min_des);
-
-#ifdef USE_FBR0
-	/* Now's the best time to initialize FBR0 contents */
-	fbr_entry = (struct fbr_desc *) rx_local->fbr[1]->ring_virtaddr;
-	for (entry = 0; entry < rx_local->fbr[1]->num_entries; entry++) {
-		fbr_entry->addr_hi = rx_local->fbr[1]->bus_high[entry];
-		fbr_entry->addr_lo = rx_local->fbr[1]->bus_low[entry];
-		fbr_entry->word2 = entry;
-		fbr_entry++;
-	}
+	for (id = 0; id < NUM_FBRS; id++) {
+		u32 *num_des;
+		u32 *full_offset;
+		u32 *min_des;
+		u32 *base_hi;
+		u32 *base_lo;
+
+		if (id == 0) {
+			num_des = &rx_dma->fbr0_num_des;
+			full_offset = &rx_dma->fbr0_full_offset;
+			min_des = &rx_dma->fbr0_min_des;
+			base_hi = &rx_dma->fbr0_base_hi;
+			base_lo = &rx_dma->fbr0_base_lo;
+		} else {
+			num_des = &rx_dma->fbr1_num_des;
+			full_offset = &rx_dma->fbr1_full_offset;
+			min_des = &rx_dma->fbr1_min_des;
+			base_hi = &rx_dma->fbr1_base_hi;
+			base_lo = &rx_dma->fbr1_base_lo;
+		}
 
-	writel((u32) (rx_local->fbr[1]->real_physaddr >> 32),
-	       &rx_dma->fbr0_base_hi);
-	writel((u32) rx_local->fbr[1]->real_physaddr, &rx_dma->fbr0_base_lo);
-	writel(rx_local->fbr[1]->num_entries - 1, &rx_dma->fbr0_num_des);
-	writel(ET_DMA10_WRAP, &rx_dma->fbr0_full_offset);
+		/* Now's the best time to initialize FBR contents */
+		fbr_entry =
+		    (struct fbr_desc *) rx_local->fbr[id]->ring_virtaddr;
+		for (entry = 0;
+		     entry < rx_local->fbr[id]->num_entries; entry++) {
+			fbr_entry->addr_hi = rx_local->fbr[id]->bus_high[entry];
+			fbr_entry->addr_lo = rx_local->fbr[id]->bus_low[entry];
+			fbr_entry->word2 = entry;
+			fbr_entry++;
+		}
 
-	/* This variable tracks the free buffer ring 0 full position, so it
-	 * has to match the above.
-	 */
-	rx_local->fbr[1]->local_full = ET_DMA10_WRAP;
-	writel(
-	   ((rx_local->fbr[1]->num_entries * LO_MARK_PERCENT_FOR_RX) / 100) - 1,
-	   &rx_dma->fbr0_min_des);
-#endif
+		/* Set the address and parameters of Free buffer ring 1 and 0
+		 * into the 1310's registers
+		 */
+		writel(upper_32_bits(rx_local->fbr[id]->ring_physaddr),
+		       base_hi);
+		writel(lower_32_bits(rx_local->fbr[id]->ring_physaddr),
+		       base_lo);
+		writel(rx_local->fbr[id]->num_entries - 1, num_des);
+		writel(ET_DMA10_WRAP, full_offset);
+
+		/* This variable tracks the free buffer ring 1 full position,
+		 * so it has to match the above.
+		 */
+		rx_local->fbr[id]->local_full = ET_DMA10_WRAP;
+		writel(((rx_local->fbr[id]->num_entries *
+					LO_MARK_PERCENT_FOR_RX) / 100) - 1,
+		       min_des);
+	}
 
 	/* Program the number of packets we will receive before generating an
 	 * interrupt.
@@ -1971,18 +1928,19 @@ static void et131x_config_tx_dma_regs(struct et131x_adapter *adapter)
 	struct txdma_regs __iomem *txdma = &adapter->regs->txdma;
 
 	/* Load the hardware with the start of the transmit descriptor ring. */
-	writel((u32) ((u64)adapter->tx_ring.tx_desc_ring_pa >> 32),
+	writel(upper_32_bits(adapter->tx_ring.tx_desc_ring_pa),
 	       &txdma->pr_base_hi);
-	writel((u32) adapter->tx_ring.tx_desc_ring_pa,
+	writel(lower_32_bits(adapter->tx_ring.tx_desc_ring_pa),
 	       &txdma->pr_base_lo);
 
 	/* Initialise the transmit DMA engine */
 	writel(NUM_DESC_PER_RING_TX - 1, &txdma->pr_num_des);
 
 	/* Load the completion writeback physical address */
-	writel((u32)((u64)adapter->tx_ring.tx_status_pa >> 32),
-						&txdma->dma_wb_base_hi);
-	writel((u32)adapter->tx_ring.tx_status_pa, &txdma->dma_wb_base_lo);
+	writel(upper_32_bits(adapter->tx_ring.tx_status_pa),
+	       &txdma->dma_wb_base_hi);
+	writel(lower_32_bits(adapter->tx_ring.tx_status_pa),
+	       &txdma->dma_wb_base_lo);
 
 	*adapter->tx_ring.tx_status = 0;
 
@@ -2267,31 +2225,6 @@ static inline u32 bump_free_buff_ring(u32 *free_buff_ring, u32 limit)
 }
 
 /**
- * et131x_align_allocated_memory - Align allocated memory on a given boundary
- * @adapter: pointer to our adapter structure
- * @phys_addr: pointer to Physical address
- * @offset: pointer to the offset variable
- * @mask: correct mask
- */
-static void et131x_align_allocated_memory(struct et131x_adapter *adapter,
-					  u64 *phys_addr, u64 *offset,
-					  u64 mask)
-{
-	u64 new_addr = *phys_addr & ~mask;
-
-	*offset = 0;
-
-	if (new_addr != *phys_addr) {
-		/* Move to next aligned block */
-		new_addr += mask + 1;
-		/* Return offset for adjusting virt addr */
-		*offset = new_addr - *phys_addr;
-		/* Return new physical address */
-		*phys_addr = new_addr;
-	}
-}
-
-/**
  * et131x_rx_dma_memory_alloc
  * @adapter: pointer to our private adapter structure
  *
@@ -2302,19 +2235,19 @@ static void et131x_align_allocated_memory(struct et131x_adapter *adapter,
  */
 static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
 {
+	u8 id;
 	u32 i, j;
 	u32 bufsize;
-	u32 pktstat_ringsize, fbr_chunksize;
+	u32 pktstat_ringsize;
+	u32 fbr_chunksize;
 	struct rx_ring *rx_ring;
 
 	/* Setup some convenience pointers */
 	rx_ring = &adapter->rx_ring;
 
 	/* Alloc memory for the lookup table */
-#ifdef USE_FBR0
-	rx_ring->fbr[1] = kmalloc(sizeof(struct fbr_lookup), GFP_KERNEL);
-#endif
 	rx_ring->fbr[0] = kmalloc(sizeof(struct fbr_lookup), GFP_KERNEL);
+	rx_ring->fbr[1] = kmalloc(sizeof(struct fbr_lookup), GFP_KERNEL);
 
 	/* The first thing we will do is configure the sizes of the buffer
 	 * rings. These will change based on jumbo packet support.  Larger
@@ -2335,211 +2268,85 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
 	 */
 
 	if (adapter->registry_jumbo_packet < 2048) {
-#ifdef USE_FBR0
-		rx_ring->fbr[1]->buffsize = 256;
-		rx_ring->fbr[1]->num_entries = 512;
-#endif
-		rx_ring->fbr[0]->buffsize = 2048;
+		rx_ring->fbr[0]->buffsize = 256;
 		rx_ring->fbr[0]->num_entries = 512;
+		rx_ring->fbr[1]->buffsize = 2048;
+		rx_ring->fbr[1]->num_entries = 512;
 	} else if (adapter->registry_jumbo_packet < 4096) {
-#ifdef USE_FBR0
-		rx_ring->fbr[1]->buffsize = 512;
-		rx_ring->fbr[1]->num_entries = 1024;
-#endif
-		rx_ring->fbr[0]->buffsize = 4096;
-		rx_ring->fbr[0]->num_entries = 512;
+		rx_ring->fbr[0]->buffsize = 512;
+		rx_ring->fbr[0]->num_entries = 1024;
+		rx_ring->fbr[1]->buffsize = 4096;
+		rx_ring->fbr[1]->num_entries = 512;
 	} else {
-#ifdef USE_FBR0
-		rx_ring->fbr[1]->buffsize = 1024;
-		rx_ring->fbr[1]->num_entries = 768;
-#endif
-		rx_ring->fbr[0]->buffsize = 16384;
-		rx_ring->fbr[0]->num_entries = 128;
+		rx_ring->fbr[0]->buffsize = 1024;
+		rx_ring->fbr[0]->num_entries = 768;
+		rx_ring->fbr[1]->buffsize = 16384;
+		rx_ring->fbr[1]->num_entries = 128;
 	}
 
-#ifdef USE_FBR0
 	adapter->rx_ring.psr_num_entries =
-				adapter->rx_ring.fbr[1]->num_entries +
-				adapter->rx_ring.fbr[0]->num_entries;
-#else
-	adapter->rx_ring.psr_num_entries = adapter->rx_ring.fbr[0]->num_entries;
-#endif
+				adapter->rx_ring.fbr[0]->num_entries +
+				adapter->rx_ring.fbr[1]->num_entries;
 
-	/* Allocate an area of memory for Free Buffer Ring 1 */
-	bufsize = (sizeof(struct fbr_desc) * rx_ring->fbr[0]->num_entries) +
-									0xfff;
-	rx_ring->fbr[0]->ring_virtaddr = dma_alloc_coherent(&adapter->pdev->dev,
+	for (id = 0; id < NUM_FBRS; id++) {
+		/* Allocate an area of memory for Free Buffer Ring */
+		bufsize =
+		    (sizeof(struct fbr_desc) * rx_ring->fbr[id]->num_entries);
+		rx_ring->fbr[id]->ring_virtaddr =
+				dma_alloc_coherent(&adapter->pdev->dev,
 					bufsize,
-					&rx_ring->fbr[0]->ring_physaddr,
+					&rx_ring->fbr[id]->ring_physaddr,
 					GFP_KERNEL);
-	if (!rx_ring->fbr[0]->ring_virtaddr) {
-		dev_err(&adapter->pdev->dev,
-			  "Cannot alloc memory for Free Buffer Ring 1\n");
-		return -ENOMEM;
-	}
-
-	/* Save physical address
-	 *
-	 * NOTE: dma_alloc_coherent(), used above to alloc DMA regions,
-	 * ALWAYS returns SAC (32-bit) addresses. If DAC (64-bit) addresses
-	 * are ever returned, make sure the high part is retrieved here
-	 * before storing the adjusted address.
-	 */
-	rx_ring->fbr[0]->real_physaddr = rx_ring->fbr[0]->ring_physaddr;
-
-	/* Align Free Buffer Ring 1 on a 4K boundary */
-	et131x_align_allocated_memory(adapter,
-				      &rx_ring->fbr[0]->real_physaddr,
-				      &rx_ring->fbr[0]->offset, 0x0FFF);
-
-	rx_ring->fbr[0]->ring_virtaddr =
-			(void *)((u8 *) rx_ring->fbr[0]->ring_virtaddr +
-			rx_ring->fbr[0]->offset);
-
-#ifdef USE_FBR0
-	/* Allocate an area of memory for Free Buffer Ring 0 */
-	bufsize = (sizeof(struct fbr_desc) * rx_ring->fbr[1]->num_entries) +
-									0xfff;
-	rx_ring->fbr[1]->ring_virtaddr = dma_alloc_coherent(&adapter->pdev->dev,
-						bufsize,
-						&rx_ring->fbr[1]->ring_physaddr,
-						GFP_KERNEL);
-	if (!rx_ring->fbr[1]->ring_virtaddr) {
-		dev_err(&adapter->pdev->dev,
-			  "Cannot alloc memory for Free Buffer Ring 0\n");
-		return -ENOMEM;
-	}
-
-	/* Save physical address
-	 *
-	 * NOTE: dma_alloc_coherent(), used above to alloc DMA regions,
-	 * ALWAYS returns SAC (32-bit) addresses. If DAC (64-bit) addresses
-	 * are ever returned, make sure the high part is retrieved here before
-	 * storing the adjusted address.
-	 */
-	rx_ring->fbr[1]->real_physaddr = rx_ring->fbr[1]->ring_physaddr;
-
-	/* Align Free Buffer Ring 0 on a 4K boundary */
-	et131x_align_allocated_memory(adapter,
-				      &rx_ring->fbr[1]->real_physaddr,
-				      &rx_ring->fbr[1]->offset, 0x0FFF);
-
-	rx_ring->fbr[1]->ring_virtaddr =
-			(void *)((u8 *) rx_ring->fbr[1]->ring_virtaddr +
-			rx_ring->fbr[1]->offset);
-#endif
-	for (i = 0; i < (rx_ring->fbr[0]->num_entries / FBR_CHUNKS); i++) {
-		u64 fbr1_tmp_physaddr;
-		u64 fbr1_offset;
-		u32 fbr1_align;
-
-		/* This code allocates an area of memory big enough for N
-		 * free buffers + (buffer_size - 1) so that the buffers can
-		 * be aligned on 4k boundaries.  If each buffer were aligned
-		 * to a buffer_size boundary, the effect would be to double
-		 * the size of FBR0.  By allocating N buffers at once, we
-		 * reduce this overhead.
-		 */
-		if (rx_ring->fbr[0]->buffsize > 4096)
-			fbr1_align = 4096;
-		else
-			fbr1_align = rx_ring->fbr[0]->buffsize;
-
-		fbr_chunksize =
-		    (FBR_CHUNKS * rx_ring->fbr[0]->buffsize) + fbr1_align - 1;
-		rx_ring->fbr[0]->mem_virtaddrs[i] =
-		    dma_alloc_coherent(&adapter->pdev->dev, fbr_chunksize,
-				       &rx_ring->fbr[0]->mem_physaddrs[i],
-				       GFP_KERNEL);
-
-		if (!rx_ring->fbr[0]->mem_virtaddrs[i]) {
+		if (!rx_ring->fbr[id]->ring_virtaddr) {
 			dev_err(&adapter->pdev->dev,
-				"Could not alloc memory\n");
+			   "Cannot alloc memory for Free Buffer Ring %d\n", id);
 			return -ENOMEM;
 		}
-
-		/* See NOTE in "Save Physical Address" comment above */
-		fbr1_tmp_physaddr = rx_ring->fbr[0]->mem_physaddrs[i];
-
-		et131x_align_allocated_memory(adapter,
-					      &fbr1_tmp_physaddr,
-					      &fbr1_offset, (fbr1_align - 1));
-
-		for (j = 0; j < FBR_CHUNKS; j++) {
-			u32 index = (i * FBR_CHUNKS) + j;
-
-			/* Save the Virtual address of this index for quick
-			 * access later
-			 */
-			rx_ring->fbr[0]->virt[index] =
-			    (u8 *) rx_ring->fbr[0]->mem_virtaddrs[i] +
-			    (j * rx_ring->fbr[0]->buffsize) + fbr1_offset;
-
-			/* now store the physical address in the descriptor
-			 * so the device can access it
-			 */
-			rx_ring->fbr[0]->bus_high[index] =
-			    (u32) (fbr1_tmp_physaddr >> 32);
-			rx_ring->fbr[0]->bus_low[index] =
-			    (u32) fbr1_tmp_physaddr;
-
-			fbr1_tmp_physaddr += rx_ring->fbr[0]->buffsize;
-
-			rx_ring->fbr[0]->buffer1[index] =
-			    rx_ring->fbr[0]->virt[index];
-			rx_ring->fbr[0]->buffer2[index] =
-			    rx_ring->fbr[0]->virt[index] - 4;
-		}
 	}
 
-#ifdef USE_FBR0
-	/* Same for FBR0 (if in use) */
-	for (i = 0; i < (rx_ring->fbr[1]->num_entries / FBR_CHUNKS); i++) {
-		u64 fbr0_tmp_physaddr;
-		u64 fbr0_offset;
+	for (id = 0; id < NUM_FBRS; id++) {
+		fbr_chunksize = (FBR_CHUNKS * rx_ring->fbr[id]->buffsize);
 
-		fbr_chunksize =
-		    ((FBR_CHUNKS + 1) * rx_ring->fbr[1]->buffsize) - 1;
-		rx_ring->fbr[1]->mem_virtaddrs[i] =
-		    dma_alloc_coherent(&adapter->pdev->dev, fbr_chunksize,
-				       &rx_ring->fbr[1]->mem_physaddrs[i],
-				       GFP_KERNEL);
+		for (i = 0;
+		     i < (rx_ring->fbr[id]->num_entries / FBR_CHUNKS); i++) {
+			dma_addr_t fbr_tmp_physaddr;
 
-		if (!rx_ring->fbr[1]->mem_virtaddrs[i]) {
-			dev_err(&adapter->pdev->dev,
-				"Could not alloc memory\n");
-			return -ENOMEM;
-		}
-
-		/* See NOTE in "Save Physical Address" comment above */
-		fbr0_tmp_physaddr = rx_ring->fbr[1]->mem_physaddrs[i];
+			rx_ring->fbr[id]->mem_virtaddrs[i] = dma_alloc_coherent(
+					&adapter->pdev->dev, fbr_chunksize,
+					&rx_ring->fbr[id]->mem_physaddrs[i],
+					GFP_KERNEL);
 
-		et131x_align_allocated_memory(adapter,
-					      &fbr0_tmp_physaddr,
-					      &fbr0_offset,
-					      rx_ring->fbr[1]->buffsize - 1);
+			if (!rx_ring->fbr[id]->mem_virtaddrs[i]) {
+				dev_err(&adapter->pdev->dev,
+					"Could not alloc memory\n");
+				return -ENOMEM;
+			}
 
-		for (j = 0; j < FBR_CHUNKS; j++) {
-			u32 index = (i * FBR_CHUNKS) + j;
+			/* See NOTE in "Save Physical Address" comment above */
+			fbr_tmp_physaddr = rx_ring->fbr[id]->mem_physaddrs[i];
 
-			rx_ring->fbr[1]->virt[index] =
-			    (u8 *) rx_ring->fbr[1]->mem_virtaddrs[i] +
-			    (j * rx_ring->fbr[1]->buffsize) + fbr0_offset;
+			for (j = 0; j < FBR_CHUNKS; j++) {
+				u32 index = (i * FBR_CHUNKS) + j;
 
-			rx_ring->fbr[1]->bus_high[index] =
-			    (u32) (fbr0_tmp_physaddr >> 32);
-			rx_ring->fbr[1]->bus_low[index] =
-			    (u32) fbr0_tmp_physaddr;
+				/* Save the Virtual address of this index for
+				 * quick access later
+				 */
+				rx_ring->fbr[id]->virt[index] =
+				  (u8 *) rx_ring->fbr[id]->mem_virtaddrs[i] +
+				  (j * rx_ring->fbr[id]->buffsize);
 
-			fbr0_tmp_physaddr += rx_ring->fbr[1]->buffsize;
+				/* now store the physical address in the
+				 * descriptor so the device can access it
+				 */
+				rx_ring->fbr[id]->bus_high[index] =
+						upper_32_bits(fbr_tmp_physaddr);
+				rx_ring->fbr[id]->bus_low[index] =
+						lower_32_bits(fbr_tmp_physaddr);
 
-			rx_ring->fbr[1]->buffer1[index] =
-			    rx_ring->fbr[1]->virt[index];
-			rx_ring->fbr[1]->buffer2[index] =
-			    rx_ring->fbr[1]->virt[index] - 4;
+				fbr_tmp_physaddr += rx_ring->fbr[id]->buffsize;
+			}
 		}
 	}
-#endif
 
 	/* Allocate an area of memory for FIFO of Packet Status ring entries */
 	pktstat_ringsize =
@@ -2578,21 +2385,6 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
 	rx_ring->num_rfd = NIC_DEFAULT_NUM_RFD;
 	pr_info("PRS %llx\n", (unsigned long long)rx_ring->rx_status_bus);
 
-	/* Recv
-	 * kmem_cache_create initializes a lookaside list. After successful
-	 * creation, nonpaged fixed-size blocks can be allocated from and
-	 * freed to the lookaside list.
-	 * RFDs will be allocated from this pool.
-	 */
-	rx_ring->recv_lookaside = kmem_cache_create(adapter->netdev->name,
-						   sizeof(struct rfd),
-						   0,
-						   SLAB_CACHE_DMA |
-						   SLAB_HWCACHE_ALIGN,
-						   NULL);
-
-	adapter->flags |= fMP_ADAPTER_RECV_LOOKASIDE;
-
 	/* The RFDs are going to be put on lists later on, so initialize the
 	 * lists now.
 	 */
@@ -2606,6 +2398,7 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
  */
 static void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
 {
+	u8 id;
 	u32 index;
 	u32 bufsize;
 	u32 pktstat_ringsize;
@@ -2624,92 +2417,45 @@ static void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
 
 		list_del(&rfd->list_node);
 		rfd->skb = NULL;
-		kmem_cache_free(adapter->rx_ring.recv_lookaside, rfd);
+		kfree(rfd);
 	}
 
-	/* Free Free Buffer Ring 1 */
-	if (rx_ring->fbr[0]->ring_virtaddr) {
-		/* First the packet memory */
-		for (index = 0; index <
-		     (rx_ring->fbr[0]->num_entries / FBR_CHUNKS); index++) {
-			if (rx_ring->fbr[0]->mem_virtaddrs[index]) {
-				u32 fbr1_align;
-
-				if (rx_ring->fbr[0]->buffsize > 4096)
-					fbr1_align = 4096;
-				else
-					fbr1_align = rx_ring->fbr[0]->buffsize;
-
-				bufsize =
-				    (rx_ring->fbr[0]->buffsize * FBR_CHUNKS) +
-				    fbr1_align - 1;
-
-				dma_free_coherent(&adapter->pdev->dev,
-					bufsize,
-					rx_ring->fbr[0]->mem_virtaddrs[index],
-					rx_ring->fbr[0]->mem_physaddrs[index]);
-
-				rx_ring->fbr[0]->mem_virtaddrs[index] = NULL;
-			}
-		}
-
-		/* Now the FIFO itself */
-		rx_ring->fbr[0]->ring_virtaddr = (void *)((u8 *)
-		    rx_ring->fbr[0]->ring_virtaddr - rx_ring->fbr[0]->offset);
-
-		bufsize =
-		    (sizeof(struct fbr_desc) * rx_ring->fbr[0]->num_entries) +
-									0xfff;
-
-		dma_free_coherent(&adapter->pdev->dev, bufsize,
-				    rx_ring->fbr[0]->ring_virtaddr,
-				    rx_ring->fbr[0]->ring_physaddr);
-
-		rx_ring->fbr[0]->ring_virtaddr = NULL;
-	}
+	/* Free Free Buffer Rings */
+	for (id = 0; id < NUM_FBRS; id++) {
+		if (!rx_ring->fbr[id]->ring_virtaddr)
+			continue;
 
-#ifdef USE_FBR0
-	/* Now the same for Free Buffer Ring 0 */
-	if (rx_ring->fbr[1]->ring_virtaddr) {
 		/* First the packet memory */
-		for (index = 0; index <
-		     (rx_ring->fbr[1]->num_entries / FBR_CHUNKS); index++) {
-			if (rx_ring->fbr[1]->mem_virtaddrs[index]) {
+		for (index = 0;
+		     index < (rx_ring->fbr[id]->num_entries / FBR_CHUNKS);
+		     index++) {
+			if (rx_ring->fbr[id]->mem_virtaddrs[index]) {
 				bufsize =
-				    (rx_ring->fbr[1]->buffsize *
-				     (FBR_CHUNKS + 1)) - 1;
+				    rx_ring->fbr[id]->buffsize * FBR_CHUNKS;
 
 				dma_free_coherent(&adapter->pdev->dev,
 					bufsize,
-					rx_ring->fbr[1]->mem_virtaddrs[index],
-					rx_ring->fbr[1]->mem_physaddrs[index]);
+					rx_ring->fbr[id]->mem_virtaddrs[index],
+					rx_ring->fbr[id]->mem_physaddrs[index]);
 
-				rx_ring->fbr[1]->mem_virtaddrs[index] = NULL;
+				rx_ring->fbr[id]->mem_virtaddrs[index] = NULL;
 			}
 		}
 
-		/* Now the FIFO itself */
-		rx_ring->fbr[1]->ring_virtaddr = (void *)((u8 *)
-		    rx_ring->fbr[1]->ring_virtaddr - rx_ring->fbr[1]->offset);
-
 		bufsize =
-		    (sizeof(struct fbr_desc) * rx_ring->fbr[1]->num_entries) +
-									0xfff;
+		    sizeof(struct fbr_desc) * rx_ring->fbr[id]->num_entries;
 
-		dma_free_coherent(&adapter->pdev->dev,
-				  bufsize,
-				  rx_ring->fbr[1]->ring_virtaddr,
-				  rx_ring->fbr[1]->ring_physaddr);
+		dma_free_coherent(&adapter->pdev->dev, bufsize,
+				    rx_ring->fbr[id]->ring_virtaddr,
+				    rx_ring->fbr[id]->ring_physaddr);
 
-		rx_ring->fbr[1]->ring_virtaddr = NULL;
+		rx_ring->fbr[id]->ring_virtaddr = NULL;
 	}
-#endif
 
 	/* Free Packet Status Ring */
 	if (rx_ring->ps_ring_virtaddr) {
-		pktstat_ringsize =
-		    sizeof(struct pkt_stat_desc) *
-		    adapter->rx_ring.psr_num_entries;
+		pktstat_ringsize = sizeof(struct pkt_stat_desc) *
+					adapter->rx_ring.psr_num_entries;
 
 		dma_free_coherent(&adapter->pdev->dev, pktstat_ringsize,
 				    rx_ring->ps_ring_virtaddr,
@@ -2726,18 +2472,9 @@ static void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
 		rx_ring->rx_status_block = NULL;
 	}
 
-	/* Destroy the lookaside (RFD) pool */
-	if (adapter->flags & fMP_ADAPTER_RECV_LOOKASIDE) {
-		kmem_cache_destroy(rx_ring->recv_lookaside);
-		adapter->flags &= ~fMP_ADAPTER_RECV_LOOKASIDE;
-	}
-
 	/* Free the FBR Lookup Table */
-#ifdef USE_FBR0
-	kfree(rx_ring->fbr[1]);
-#endif
-
 	kfree(rx_ring->fbr[0]);
+	kfree(rx_ring->fbr[1]);
 
 	/* Reset Counters */
 	rx_ring->num_ready_recv = 0;
@@ -2751,8 +2488,7 @@ static void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
  */
 static int et131x_init_recv(struct et131x_adapter *adapter)
 {
-	int status = -ENOMEM;
-	struct rfd *rfd = NULL;
+	struct rfd *rfd;
 	u32 rfdct;
 	u32 numrfd = 0;
 	struct rx_ring *rx_ring;
@@ -2762,14 +2498,11 @@ static int et131x_init_recv(struct et131x_adapter *adapter)
 
 	/* Setup each RFD */
 	for (rfdct = 0; rfdct < rx_ring->num_rfd; rfdct++) {
-		rfd = kmem_cache_alloc(rx_ring->recv_lookaside,
-						     GFP_ATOMIC | GFP_DMA);
+		rfd = kzalloc(sizeof(struct rfd), GFP_ATOMIC | GFP_DMA);
 
 		if (!rfd) {
-			dev_err(&adapter->pdev->dev,
-				  "Couldn't alloc RFD out of kmem_cache\n");
-			status = -ENOMEM;
-			continue;
+			dev_err(&adapter->pdev->dev, "Couldn't alloc RFD\n");
+			return -ENOMEM;
 		}
 
 		rfd->skb = NULL;
@@ -2782,17 +2515,7 @@ static int et131x_init_recv(struct et131x_adapter *adapter)
 		numrfd++;
 	}
 
-	if (numrfd > NIC_MIN_NUM_RFD)
-		status = 0;
-
-	rx_ring->num_rfd = numrfd;
-
-	if (status != 0) {
-		kmem_cache_free(rx_ring->recv_lookaside, rfd);
-		dev_err(&adapter->pdev->dev,
-			  "Allocation problems in et131x_init_recv\n");
-	}
-	return status;
+	return 0;
 }
 
 /**
@@ -2831,51 +2554,34 @@ static void nic_return_rfd(struct et131x_adapter *adapter, struct rfd *rfd)
 	/* We don't use any of the OOB data besides status. Otherwise, we
 	 * need to clean up OOB data
 	 */
-	if (
-#ifdef USE_FBR0
-	    (ring_index == 0 && buff_index < rx_local->fbr[1]->num_entries) ||
-#endif
-	    (ring_index == 1 && buff_index < rx_local->fbr[0]->num_entries)) {
+	if (buff_index < rx_local->fbr[ring_index]->num_entries) {
+		u32 *offset;
+		struct fbr_desc *next;
+
 		spin_lock_irqsave(&adapter->fbr_lock, flags);
 
-		if (ring_index == 1) {
-			struct fbr_desc *next = (struct fbr_desc *)
-					(rx_local->fbr[0]->ring_virtaddr) +
-					INDEX10(rx_local->fbr[0]->local_full);
+		if (ring_index == 0)
+			offset = &rx_dma->fbr0_full_offset;
+		else
+			offset = &rx_dma->fbr1_full_offset;
 
-			/* Handle the Free Buffer Ring advancement here. Write
-			 * the PA / Buffer Index for the returned buffer into
-			 * the oldest (next to be freed)FBR entry
-			 */
-			next->addr_hi = rx_local->fbr[0]->bus_high[buff_index];
-			next->addr_lo = rx_local->fbr[0]->bus_low[buff_index];
-			next->word2 = buff_index;
-
-			writel(bump_free_buff_ring(
-					&rx_local->fbr[0]->local_full,
-					rx_local->fbr[0]->num_entries - 1),
-					&rx_dma->fbr1_full_offset);
-		}
-#ifdef USE_FBR0
-		else {
-			struct fbr_desc *next = (struct fbr_desc *)
-				rx_local->fbr[1]->ring_virtaddr +
-				    INDEX10(rx_local->fbr[1]->local_full);
+		next = (struct fbr_desc *)
+			   (rx_local->fbr[ring_index]->ring_virtaddr) +
+				INDEX10(rx_local->fbr[ring_index]->local_full);
+
+		/* Handle the Free Buffer Ring advancement here. Write
+		 * the PA / Buffer Index for the returned buffer into
+		 * the oldest (next to be freed)FBR entry
+		 */
+		next->addr_hi = rx_local->fbr[ring_index]->bus_high[buff_index];
+		next->addr_lo = rx_local->fbr[ring_index]->bus_low[buff_index];
+		next->word2 = buff_index;
+
+		writel(bump_free_buff_ring(
+				  &rx_local->fbr[ring_index]->local_full,
+				  rx_local->fbr[ring_index]->num_entries - 1),
+		       offset);
 
-			/* Handle the Free Buffer Ring advancement here. Write
-			 * the PA / Buffer Index for the returned buffer into
-			 * the oldest (next to be freed) FBR entry
-			 */
-			next->addr_hi = rx_local->fbr[1]->bus_high[buff_index];
-			next->addr_lo = rx_local->fbr[1]->bus_low[buff_index];
-			next->word2 = buff_index;
-
-			writel(bump_free_buff_ring(
-					&rx_local->fbr[1]->local_full,
-					rx_local->fbr[1]->num_entries - 1),
-			       &rx_dma->fbr0_full_offset);
-		}
-#endif
 		spin_unlock_irqrestore(&adapter->fbr_lock, flags);
 	} else {
 		dev_err(&adapter->pdev->dev,
@@ -2919,6 +2625,7 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter)
 	u32 len;
 	u32 word0;
 	u32 word1;
+	struct sk_buff *skb;
 
 	/* RX Status block is written by the DMA engine prior to every
 	 * interrupt. It contains the next to be used entry in the Packet
@@ -2929,16 +2636,14 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter)
 
 	/* Check the PSR and wrap bits do not match */
 	if ((word1 & 0x1FFF) == (rx_local->local_psr_full & 0x1FFF))
-		/* Looks like this ring is not updated yet */
-		return NULL;
+		return NULL; /* Looks like this ring is not updated yet */
 
 	/* The packet status ring indicates that data is available. */
 	psr = (struct pkt_stat_desc *) (rx_local->ps_ring_virtaddr) +
 			(rx_local->local_psr_full & 0xFFF);
 
-	/* Grab any information that is required once the PSR is
-	 * advanced, since we can no longer rely on the memory being
-	 * accurate
+	/* Grab any information that is required once the PSR is advanced,
+	 * since we can no longer rely on the memory being accurate
 	 */
 	len = psr->word1 & 0xFFFF;
 	ring_index = (psr->word1 >> 26) & 0x03;
@@ -2955,40 +2660,24 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter)
 		rx_local->local_psr_full ^= 0x1000;
 	}
 
-	writel(rx_local->local_psr_full,
-	       &adapter->regs->rxdma.psr_full_offset);
-
-#ifndef USE_FBR0
-	if (ring_index != 1)
-		return NULL;
-#endif
+	writel(rx_local->local_psr_full, &adapter->regs->rxdma.psr_full_offset);
 
-#ifdef USE_FBR0
 	if (ring_index > 1 ||
-		(ring_index == 0 &&
-		buff_index > rx_local->fbr[1]->num_entries - 1) ||
-		(ring_index == 1 &&
-		buff_index > rx_local->fbr[0]->num_entries - 1)) {
-#else
-	if (ring_index != 1 || buff_index > rx_local->fbr[0]->num_entries - 1) {
-#endif
+		    buff_index > rx_local->fbr[ring_index]->num_entries - 1) {
 		/* Illegal buffer or ring index cannot be used by S/W*/
 		dev_err(&adapter->pdev->dev,
-			  "NICRxPkts PSR Entry %d indicates "
-			  "length of %d and/or bad bi(%d)\n",
-			  rx_local->local_psr_full & 0xFFF,
-			  len, buff_index);
+			"NICRxPkts PSR Entry %d indicates length of %d and/or bad bi(%d)\n",
+			rx_local->local_psr_full & 0xFFF, len, buff_index);
 		return NULL;
 	}
 
 	/* Get and fill the RFD. */
 	spin_lock_irqsave(&adapter->rcv_lock, flags);
 
-	rfd = NULL;
 	element = rx_local->recv_list.next;
 	rfd = (struct rfd *) list_entry(element, struct rfd, list_node);
 
-	if (rfd == NULL) {
+	if (!rfd) {
 		spin_unlock_irqrestore(&adapter->rcv_lock, flags);
 		return NULL;
 	}
@@ -3001,119 +2690,95 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter)
 	rfd->bufferindex = buff_index;
 	rfd->ringindex = ring_index;
 
-	/* In V1 silicon, there is a bug which screws up filtering of
-	 * runt packets.  Therefore runt packet filtering is disabled
-	 * in the MAC and the packets are dropped here.  They are
-	 * also counted here.
+	/* In V1 silicon, there is a bug which screws up filtering of runt
+	 * packets. Therefore runt packet filtering is disabled in the MAC and
+	 * the packets are dropped here. They are also counted here.
 	 */
 	if (len < (NIC_MIN_PACKET_SIZE + 4)) {
 		adapter->stats.rx_other_errs++;
 		len = 0;
 	}
 
-	if (len) {
-		/* Determine if this is a multicast packet coming in */
-		if ((word0 & ALCATEL_MULTICAST_PKT) &&
-		    !(word0 & ALCATEL_BROADCAST_PKT)) {
-			/* Promiscuous mode and Multicast mode are
-			 * not mutually exclusive as was first
-			 * thought.  I guess Promiscuous is just
-			 * considered a super-set of the other
-			 * filters. Generally filter is 0x2b when in
-			 * promiscuous mode.
-			 */
-			if ((adapter->packet_filter &
-					ET131X_PACKET_TYPE_MULTICAST)
-			    && !(adapter->packet_filter &
-					ET131X_PACKET_TYPE_PROMISCUOUS)
-			    && !(adapter->packet_filter &
+	if (len == 0) {
+		rfd->len = 0;
+		goto out;
+	}
+
+	/* Determine if this is a multicast packet coming in */
+	if ((word0 & ALCATEL_MULTICAST_PKT) &&
+	    !(word0 & ALCATEL_BROADCAST_PKT)) {
+		/* Promiscuous mode and Multicast mode are not mutually
+		 * exclusive as was first thought. I guess Promiscuous is just
+		 * considered a super-set of the other filters. Generally filter
+		 * is 0x2b when in promiscuous mode.
+		 */
+		if ((adapter->packet_filter & ET131X_PACKET_TYPE_MULTICAST)
+		   && !(adapter->packet_filter & ET131X_PACKET_TYPE_PROMISCUOUS)
+		   && !(adapter->packet_filter &
 					ET131X_PACKET_TYPE_ALL_MULTICAST)) {
-				/*
-				 * Note - ring_index for fbr[] array is reversed
-				 * 1 for FBR0 etc
-				 */
-				buf = rx_local->fbr[(ring_index == 0 ? 1 : 0)]->
-						virt[buff_index];
+			buf = rx_local->fbr[ring_index]->virt[buff_index];
 
-				/* Loop through our list to see if the
-				 * destination address of this packet
-				 * matches one in our list.
-				 */
-				for (i = 0; i < adapter->multicast_addr_count;
-				     i++) {
-					if (buf[0] ==
-						adapter->multicast_list[i][0]
-					    && buf[1] ==
-						adapter->multicast_list[i][1]
-					    && buf[2] ==
-						adapter->multicast_list[i][2]
-					    && buf[3] ==
-						adapter->multicast_list[i][3]
-					    && buf[4] ==
-						adapter->multicast_list[i][4]
-					    && buf[5] ==
-						adapter->multicast_list[i][5]) {
-						break;
-					}
+			/* Loop through our list to see if the destination
+			 * address of this packet matches one in our list.
+			 */
+			for (i = 0; i < adapter->multicast_addr_count; i++) {
+				if (buf[0] == adapter->multicast_list[i][0]
+				 && buf[1] == adapter->multicast_list[i][1]
+				 && buf[2] == adapter->multicast_list[i][2]
+				 && buf[3] == adapter->multicast_list[i][3]
+				 && buf[4] == adapter->multicast_list[i][4]
+				 && buf[5] == adapter->multicast_list[i][5]) {
+					break;
 				}
-
-				/* If our index is equal to the number
-				 * of Multicast address we have, then
-				 * this means we did not find this
-				 * packet's matching address in our
-				 * list.  Set the len to zero,
-				 * so we free our RFD when we return
-				 * from this function.
-				 */
-				if (i == adapter->multicast_addr_count)
-					len = 0;
 			}
 
-			if (len > 0)
-				adapter->stats.multicast_pkts_rcvd++;
-		} else if (word0 & ALCATEL_BROADCAST_PKT)
-			adapter->stats.broadcast_pkts_rcvd++;
-		else
-			/* Not sure what this counter measures in
-			 * promiscuous mode. Perhaps we should check
-			 * the MAC address to see if it is directed
-			 * to us in promiscuous mode.
+			/* If our index is equal to the number of Multicast
+			 * address we have, then this means we did not find this
+			 * packet's matching address in our list. Set the len to
+			 * zero, so we free our RFD when we return from this
+			 * function.
 			 */
-			adapter->stats.unicast_pkts_rcvd++;
-	}
+			if (i == adapter->multicast_addr_count)
+				len = 0;
+		}
 
-	if (len > 0) {
-		struct sk_buff *skb = NULL;
+		if (len > 0)
+			adapter->stats.multicast_pkts_rcvd++;
+	} else if (word0 & ALCATEL_BROADCAST_PKT) {
+		adapter->stats.broadcast_pkts_rcvd++;
+	} else {
+		/* Not sure what this counter measures in promiscuous mode.
+		 * Perhaps we should check the MAC address to see if it is
+		 * directed to us in promiscuous mode.
+		 */
+		adapter->stats.unicast_pkts_rcvd++;
+	}
 
-		/*rfd->len = len - 4; */
-		rfd->len = len;
+	if (len == 0) {
+		rfd->len = 0;
+		goto out;
+	}
 
-		skb = dev_alloc_skb(rfd->len + 2);
-		if (!skb) {
-			dev_err(&adapter->pdev->dev,
-				  "Couldn't alloc an SKB for Rx\n");
-			return NULL;
-		}
+	rfd->len = len;
 
-		adapter->net_stats.rx_bytes += rfd->len;
+	skb = dev_alloc_skb(rfd->len + 2);
+	if (!skb) {
+		dev_err(&adapter->pdev->dev, "Couldn't alloc an SKB for Rx\n");
+		return NULL;
+	}
 
-		/*
-		 * Note - ring_index for fbr[] array is reversed,
-		 * 1 for FBR0 etc
-		 */
-		memcpy(skb_put(skb, rfd->len),
-		    rx_local->fbr[(ring_index == 0 ? 1 : 0)]->virt[buff_index],
-		    rfd->len);
+	adapter->net_stats.rx_bytes += rfd->len;
 
-		skb->dev = adapter->netdev;
-		skb->protocol = eth_type_trans(skb, adapter->netdev);
-		skb->ip_summed = CHECKSUM_NONE;
+	memcpy(skb_put(skb, rfd->len),
+	       rx_local->fbr[ring_index]->virt[buff_index],
+	       rfd->len);
 
-		netif_rx_ni(skb);
-	} else {
-		rfd->len = 0;
-	}
+	skb->dev = adapter->netdev;
+	skb->protocol = eth_type_trans(skb, adapter->netdev);
+	skb->ip_summed = CHECKSUM_NONE;
+	netif_rx_ni(skb);
 
+out:
 	nic_return_rfd(adapter, rfd);
 	return rfd;
 }
@@ -3198,10 +2863,7 @@ static int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter)
 		return -ENOMEM;
 	}
 
-	/* Allocate enough memory for the Tx descriptor ring, and allocate
-	 * some extra so that the ring can be aligned on a 4k boundary.
-	 */
-	desc_size = (sizeof(struct tx_desc) * NUM_DESC_PER_RING_TX) + 4096 - 1;
+	desc_size = (sizeof(struct tx_desc) * NUM_DESC_PER_RING_TX);
 	tx_ring->tx_desc_ring =
 	    (struct tx_desc *) dma_alloc_coherent(&adapter->pdev->dev,
 						  desc_size,
@@ -3245,8 +2907,7 @@ static void et131x_tx_dma_memory_free(struct et131x_adapter *adapter)
 
 	if (adapter->tx_ring.tx_desc_ring) {
 		/* Free memory relating to Tx rings here */
-		desc_size = (sizeof(struct tx_desc) * NUM_DESC_PER_RING_TX)
-								+ 4096 - 1;
+		desc_size = (sizeof(struct tx_desc) * NUM_DESC_PER_RING_TX);
 		dma_free_coherent(&adapter->pdev->dev,
 				    desc_size,
 				    adapter->tx_ring.tx_desc_ring,
@@ -3285,6 +2946,7 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb)
 	struct skb_frag_struct *frags = &skb_shinfo(skb)->frags[0];
 	unsigned long flags;
 	struct phy_device *phydev = adapter->phydev;
+	dma_addr_t dma_addr;
 
 	/* Part of the optimizations of this send routine restrict us to
 	 * sending 24 fragments at a pass.  In practice we should never see
@@ -3313,85 +2975,47 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb)
 			 * This will work until we determine why the hardware
 			 * doesn't seem to like large fragments.
 			 */
-			if ((skb->len - skb->data_len) <= 1514) {
-				desc[frag].addr_hi = 0;
+			if (skb_headlen(skb) <= 1514) {
 				/* Low 16bits are length, high is vlan and
 				   unused currently so zero */
-				desc[frag].len_vlan =
-					skb->len - skb->data_len;
-
-				/* NOTE: Here, the dma_addr_t returned from
-				 * dma_map_single() is implicitly cast as a
-				 * u32. Although dma_addr_t can be
-				 * 64-bit, the address returned by
-				 * dma_map_single() is always 32-bit
-				 * addressable (as defined by the pci/dma
-				 * subsystem)
-				 */
-				desc[frag++].addr_lo =
-				    dma_map_single(&adapter->pdev->dev,
-						   skb->data,
-						   skb->len -
-						   skb->data_len,
-						   DMA_TO_DEVICE);
+				desc[frag].len_vlan = skb_headlen(skb);
+				dma_addr = dma_map_single(&adapter->pdev->dev,
+							  skb->data,
+							  skb_headlen(skb),
+							  DMA_TO_DEVICE);
+				desc[frag].addr_lo = lower_32_bits(dma_addr);
+				desc[frag].addr_hi = upper_32_bits(dma_addr);
+				frag++;
 			} else {
-				desc[frag].addr_hi = 0;
-				desc[frag].len_vlan =
-				    (skb->len - skb->data_len) / 2;
-
-				/* NOTE: Here, the dma_addr_t returned from
-				 * dma_map_single() is implicitly cast as a
-				 * u32. Although dma_addr_t can be
-				 * 64-bit, the address returned by
-				 * dma_map_single() is always 32-bit
-				 * addressable (as defined by the pci/dma
-				 * subsystem)
-				 */
-				desc[frag++].addr_lo =
-				    dma_map_single(&adapter->pdev->dev,
-						   skb->data,
-						   ((skb->len -
-						     skb->data_len) / 2),
-						   DMA_TO_DEVICE);
-				desc[frag].addr_hi = 0;
-
-				desc[frag].len_vlan =
-				    (skb->len - skb->data_len) / 2;
-
-				/* NOTE: Here, the dma_addr_t returned from
-				 * dma_map_single() is implicitly cast as a
-				 * u32. Although dma_addr_t can be
-				 * 64-bit, the address returned by
-				 * dma_map_single() is always 32-bit
-				 * addressable (as defined by the pci/dma
-				 * subsystem)
-				 */
-				desc[frag++].addr_lo =
-				    dma_map_single(&adapter->pdev->dev,
-						   skb->data +
-						   ((skb->len -
-						     skb->data_len) / 2),
-						   ((skb->len -
-						     skb->data_len) / 2),
-						   DMA_TO_DEVICE);
+				desc[frag].len_vlan = skb_headlen(skb) / 2;
+				dma_addr = dma_map_single(&adapter->pdev->dev,
+							 skb->data,
+							 (skb_headlen(skb) / 2),
+							 DMA_TO_DEVICE);
+				desc[frag].addr_lo = lower_32_bits(dma_addr);
+				desc[frag].addr_hi = upper_32_bits(dma_addr);
+				frag++;
+
+				desc[frag].len_vlan = skb_headlen(skb) / 2;
+				dma_addr = dma_map_single(&adapter->pdev->dev,
+							 skb->data +
+							 (skb_headlen(skb) / 2),
+							 (skb_headlen(skb) / 2),
+							 DMA_TO_DEVICE);
+				desc[frag].addr_lo = lower_32_bits(dma_addr);
+				desc[frag].addr_hi = upper_32_bits(dma_addr);
+				frag++;
 			}
 		} else {
-			desc[frag].addr_hi = 0;
-			desc[frag].len_vlan =
-					frags[i - 1].size;
-
-			/* NOTE: Here, the dma_addr_t returned from
-			 * dma_map_page() is implicitly cast as a u32.
-			 * Although dma_addr_t can be 64-bit, the address
-			 * returned by dma_map_page() is always 32-bit
-			 * addressable (as defined by the pci/dma subsystem)
-			 */
-			desc[frag++].addr_lo = skb_frag_dma_map(
-							&adapter->pdev->dev,
-							&frags[i - 1],
-							0,
-							frags[i - 1].size,
-							DMA_TO_DEVICE);
+			desc[frag].len_vlan = frags[i - 1].size;
+			dma_addr = skb_frag_dma_map(&adapter->pdev->dev,
+						    &frags[i - 1],
+						    0,
+						    frags[i - 1].size,
+						    DMA_TO_DEVICE);
+			desc[frag].addr_lo = lower_32_bits(dma_addr);
+			desc[frag].addr_hi = upper_32_bits(dma_addr);
+			frag++;
 		}
 	}
 
@@ -3521,7 +3145,7 @@ static int send_packet(struct sk_buff *skb, struct et131x_adapter *adapter)
 
 	tcb->skb = skb;
 
-	if (skb->data != NULL && skb->len - skb->data_len >= 6) {
+	if (skb->data != NULL && skb_headlen(skb) >= 6) {
 		shbufva = (u16 *) skb->data;
 
 		if ((shbufva[0] == 0xffff) &&
@@ -3618,6 +3242,7 @@ static inline void free_send_packet(struct et131x_adapter *adapter,
 	unsigned long flags;
 	struct tx_desc *desc = NULL;
 	struct net_device_stats *stats = &adapter->net_stats;
+	u64  dma_addr;
 
 	if (tcb->flags & fMP_DEST_BROAD)
 		atomic_inc(&adapter->stats.broadcast_pkts_xmtd);
@@ -3638,8 +3263,11 @@ static inline void free_send_packet(struct et131x_adapter *adapter,
 				    (adapter->tx_ring.tx_desc_ring +
 						INDEX10(tcb->index_start));
 
+			dma_addr = desc->addr_lo;
+			dma_addr |= (u64)desc->addr_hi << 32;
+
 			dma_unmap_single(&adapter->pdev->dev,
-					 desc->addr_lo,
+					 dma_addr,
 					 desc->len_vlan, DMA_TO_DEVICE);
 
 			add_10bit(&tcb->index_start, 1);
@@ -3830,7 +3458,12 @@ static void et131x_get_regs(struct net_device *netdev,
 	et131x_mii_read(adapter, 0x08, (u16 *)&regs_buff[num++]);
 	et131x_mii_read(adapter, MII_CTRL1000, (u16 *)&regs_buff[num++]);
 	et131x_mii_read(adapter, MII_STAT1000, (u16 *)&regs_buff[num++]);
+	et131x_mii_read(adapter, 0x0b, (u16 *)&regs_buff[num++]);
+	et131x_mii_read(adapter, 0x0c, (u16 *)&regs_buff[num++]);
+	et131x_mii_read(adapter, MII_MMD_CTRL, (u16 *)&regs_buff[num++]);
+	et131x_mii_read(adapter, MII_MMD_DATA, (u16 *)&regs_buff[num++]);
 	et131x_mii_read(adapter, MII_ESTATUS, (u16 *)&regs_buff[num++]);
+
 	et131x_mii_read(adapter, PHY_INDEX_REG, (u16 *)&regs_buff[num++]);
 	et131x_mii_read(adapter, PHY_DATA_REG, (u16 *)&regs_buff[num++]);
 	et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG,
@@ -3839,6 +3472,7 @@ static void et131x_get_regs(struct net_device *netdev,
 			(u16 *)&regs_buff[num++]);
 	et131x_mii_read(adapter, PHY_LOOPBACK_CONTROL+1,
 			(u16 *)&regs_buff[num++]);
+
 	et131x_mii_read(adapter, PHY_REGISTER_MGMT_CONTROL,
 			(u16 *)&regs_buff[num++]);
 	et131x_mii_read(adapter, PHY_CONFIG, (u16 *)&regs_buff[num++]);
@@ -3943,7 +3577,7 @@ static struct ethtool_ops et131x_ethtool_ops = {
 	.get_drvinfo	= et131x_get_drvinfo,
 	.get_regs_len	= et131x_get_regs_len,
 	.get_regs	= et131x_get_regs,
-	.get_link = ethtool_op_get_link,
+	.get_link	= ethtool_op_get_link,
 };
 /**
  * et131x_hwaddr_init - set up the MAC Address on the ET1310
@@ -4110,8 +3744,18 @@ static void et131x_error_timer_handler(unsigned long data)
 	}
 
 	/* This is a periodic timer, so reschedule */
-	mod_timer(&adapter->error_timer, jiffies +
-					  TX_ERROR_PERIOD * HZ / 1000);
+	mod_timer(&adapter->error_timer, jiffies + TX_ERROR_PERIOD * HZ / 1000);
+}
+
+/**
+ * et131x_adapter_memory_free - Free all memory allocated for use by Tx & Rx
+ * @adapter: pointer to our private adapter structure
+ */
+static void et131x_adapter_memory_free(struct et131x_adapter *adapter)
+{
+	/* Free DMA memory */
+	et131x_tx_dma_memory_free(adapter);
+	et131x_rx_dma_memory_free(adapter);
 }
 
 /**
@@ -4144,26 +3788,14 @@ static int et131x_adapter_memory_alloc(struct et131x_adapter *adapter)
 
 	/* Init receive data structures */
 	status = et131x_init_recv(adapter);
-	if (status != 0) {
+	if (status) {
 		dev_err(&adapter->pdev->dev,
 			"et131x_init_recv FAILED\n");
-		et131x_tx_dma_memory_free(adapter);
-		et131x_rx_dma_memory_free(adapter);
+		et131x_adapter_memory_free(adapter);
 	}
 	return status;
 }
 
-/**
- * et131x_adapter_memory_free - Free all memory allocated for use by Tx & Rx
- * @adapter: pointer to our private adapter structure
- */
-static void et131x_adapter_memory_free(struct et131x_adapter *adapter)
-{
-	/* Free DMA memory */
-	et131x_tx_dma_memory_free(adapter);
-	et131x_rx_dma_memory_free(adapter);
-}
-
 static void et131x_adjust_link(struct net_device *netdev)
 {
 	struct et131x_adapter *adapter = netdev_priv(netdev);
@@ -4358,7 +3990,7 @@ static struct et131x_adapter *et131x_adapter_init(struct net_device *netdev,
  * PCI subsystem detects that a PCI device which matches the information
  * contained in the pci_device_id table has been removed.
  */
-static void __devexit et131x_pci_remove(struct pci_dev *pdev)
+static void et131x_pci_remove(struct pci_dev *pdev)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct et131x_adapter *adapter = netdev_priv(netdev);
@@ -4558,182 +4190,169 @@ static void et131x_isr_handler(struct work_struct *work)
 
 	status &= 0xffffffd7;
 
-	if (status) {
-		/* Handle the TXDMA Error interrupt */
-		if (status & ET_INTR_TXDMA_ERR) {
-			u32 txdma_err;
-
-			/* Following read also clears the register (COR) */
-			txdma_err = readl(&iomem->txdma.tx_dma_error);
+	if (!status)
+		goto out;
 
-			dev_warn(&adapter->pdev->dev,
-				    "TXDMA_ERR interrupt, error = %d\n",
-				    txdma_err);
-		}
+	/* Handle the TXDMA Error interrupt */
+	if (status & ET_INTR_TXDMA_ERR) {
+		u32 txdma_err;
 
-		/* Handle Free Buffer Ring 0 and 1 Low interrupt */
-		if (status &
-		    (ET_INTR_RXDMA_FB_R0_LOW | ET_INTR_RXDMA_FB_R1_LOW)) {
-			/*
-			 * This indicates the number of unused buffers in
-			 * RXDMA free buffer ring 0 is <= the limit you
-			 * programmed. Free buffer resources need to be
-			 * returned.  Free buffers are consumed as packets
-			 * are passed from the network to the host. The host
-			 * becomes aware of the packets from the contents of
-			 * the packet status ring. This ring is queried when
-			 * the packet done interrupt occurs. Packets are then
-			 * passed to the OS. When the OS is done with the
-			 * packets the resources can be returned to the
-			 * ET1310 for re-use. This interrupt is one method of
-			 * returning resources.
-			 */
+		/* Following read also clears the register (COR) */
+		txdma_err = readl(&iomem->txdma.tx_dma_error);
 
-			/* If the user has flow control on, then we will
-			 * send a pause packet, otherwise just exit
-			 */
-			if (adapter->flowcontrol == FLOW_TXONLY ||
-			    adapter->flowcontrol == FLOW_BOTH) {
-				u32 pm_csr;
+		dev_warn(&adapter->pdev->dev,
+			    "TXDMA_ERR interrupt, error = %d\n",
+			    txdma_err);
+	}
 
-				/* Tell the device to send a pause packet via
-				 * the back pressure register (bp req  and
-				 * bp xon/xoff)
-				 */
-				pm_csr = readl(&iomem->global.pm_csr);
-				if (!et1310_in_phy_coma(adapter))
-					writel(3, &iomem->txmac.bp_ctrl);
-			}
-		}
+	/* Handle Free Buffer Ring 0 and 1 Low interrupt */
+	if (status & (ET_INTR_RXDMA_FB_R0_LOW | ET_INTR_RXDMA_FB_R1_LOW)) {
+		/*
+		 * This indicates the number of unused buffers in RXDMA free
+		 * buffer ring 0 is <= the limit you programmed. Free buffer
+		 * resources need to be returned.  Free buffers are consumed as
+		 * packets are passed from the network to the host. The host
+		 * becomes aware of the packets from the contents of the packet
+		 * status ring. This ring is queried when the packet done
+		 * interrupt occurs. Packets are then passed to the OS. When
+		 * the OS is done with the packets the resources can be
+		 * returned to the ET1310 for re-use. This interrupt is one
+		 * method of returning resources.
+		 */
 
-		/* Handle Packet Status Ring Low Interrupt */
-		if (status & ET_INTR_RXDMA_STAT_LOW) {
+		/*
+		 *  If the user has flow control on, then we will
+		 * send a pause packet, otherwise just exit
+		 */
+		if (adapter->flowcontrol == FLOW_TXONLY ||
+		    adapter->flowcontrol == FLOW_BOTH) {
+			u32 pm_csr;
 
 			/*
-			 * Same idea as with the two Free Buffer Rings.
-			 * Packets going from the network to the host each
-			 * consume a free buffer resource and a packet status
-			 * resource.  These resoures are passed to the OS.
-			 * When the OS is done with the resources, they need
-			 * to be returned to the ET1310. This is one method
-			 * of returning the resources.
+			 * Tell the device to send a pause packet via the back
+			 * pressure register (bp req and bp xon/xoff)
 			 */
+			pm_csr = readl(&iomem->global.pm_csr);
+			if (!et1310_in_phy_coma(adapter))
+				writel(3, &iomem->txmac.bp_ctrl);
 		}
+	}
 
-		/* Handle RXDMA Error Interrupt */
-		if (status & ET_INTR_RXDMA_ERR) {
-			/*
-			 * The rxdma_error interrupt is sent when a time-out
-			 * on a request issued by the JAGCore has occurred or
-			 * a completion is returned with an un-successful
-			 * status.  In both cases the request is considered
-			 * complete. The JAGCore will automatically re-try the
-			 * request in question. Normally information on events
-			 * like these are sent to the host using the "Advanced
-			 * Error Reporting" capability. This interrupt is
-			 * another way of getting similar information. The
-			 * only thing required is to clear the interrupt by
-			 * reading the ISR in the global resources. The
-			 * JAGCore will do a re-try on the request.  Normally
-			 * you should never see this interrupt. If you start
-			 * to see this interrupt occurring frequently then
-			 * something bad has occurred. A reset might be the
-			 * thing to do.
-			 */
-			/* TRAP();*/
+	/* Handle Packet Status Ring Low Interrupt */
+	if (status & ET_INTR_RXDMA_STAT_LOW) {
+		/*
+		 * Same idea as with the two Free Buffer Rings. Packets going
+		 * from the network to the host each consume a free buffer
+		 * resource and a packet status resource. These resoures are
+		 * passed to the OS. When the OS is done with the resources,
+		 * they need to be returned to the ET1310. This is one method
+		 * of returning the resources.
+		 */
+	}
 
-			dev_warn(&adapter->pdev->dev,
-				    "RxDMA_ERR interrupt, error %x\n",
-				    readl(&iomem->txmac.tx_test));
-		}
+	/* Handle RXDMA Error Interrupt */
+	if (status & ET_INTR_RXDMA_ERR) {
+		/*
+		 * The rxdma_error interrupt is sent when a time-out on a
+		 * request issued by the JAGCore has occurred or a completion is
+		 * returned with an un-successful status. In both cases the
+		 * request is considered complete. The JAGCore will
+		 * automatically re-try the request in question. Normally
+		 * information on events like these are sent to the host using
+		 * the "Advanced Error Reporting" capability. This interrupt is
+		 * another way of getting similar information. The only thing
+		 * required is to clear the interrupt by reading the ISR in the
+		 * global resources. The JAGCore will do a re-try on the
+		 * request. Normally you should never see this interrupt. If
+		 * you start to see this interrupt occurring frequently then
+		 * something bad has occurred. A reset might be the thing to do.
+		 */
+		/* TRAP();*/
 
-		/* Handle the Wake on LAN Event */
-		if (status & ET_INTR_WOL) {
-			/*
-			 * This is a secondary interrupt for wake on LAN.
-			 * The driver should never see this, if it does,
-			 * something serious is wrong. We will TRAP the
-			 * message when we are in DBG mode, otherwise we
-			 * will ignore it.
-			 */
-			dev_err(&adapter->pdev->dev, "WAKE_ON_LAN interrupt\n");
-		}
+		dev_warn(&adapter->pdev->dev,
+			    "RxDMA_ERR interrupt, error %x\n",
+			    readl(&iomem->txmac.tx_test));
+	}
 
-		/* Let's move on to the TxMac */
-		if (status & ET_INTR_TXMAC) {
-			u32 err = readl(&iomem->txmac.err);
+	/* Handle the Wake on LAN Event */
+	if (status & ET_INTR_WOL) {
+		/*
+		 * This is a secondary interrupt for wake on LAN. The driver
+		 * should never see this, if it does, something serious is
+		 * wrong. We will TRAP the message when we are in DBG mode,
+		 * otherwise we will ignore it.
+		 */
+		dev_err(&adapter->pdev->dev, "WAKE_ON_LAN interrupt\n");
+	}
 
-			/*
-			 * When any of the errors occur and TXMAC generates
-			 * an interrupt to report these errors, it usually
-			 * means that TXMAC has detected an error in the data
-			 * stream retrieved from the on-chip Tx Q. All of
-			 * these errors are catastrophic and TXMAC won't be
-			 * able to recover data when these errors occur.  In
-			 * a nutshell, the whole Tx path will have to be reset
-			 * and re-configured afterwards.
-			 */
-			dev_warn(&adapter->pdev->dev,
-				    "TXMAC interrupt, error 0x%08x\n",
-				    err);
+	/* Let's move on to the TxMac */
+	if (status & ET_INTR_TXMAC) {
+		u32 err = readl(&iomem->txmac.err);
 
-			/* If we are debugging, we want to see this error,
-			 * otherwise we just want the device to be reset and
-			 * continue
-			 */
-		}
+		/*
+		 * When any of the errors occur and TXMAC generates an
+		 * interrupt to report these errors, it usually means that
+		 * TXMAC has detected an error in the data stream retrieved
+		 * from the on-chip Tx Q. All of these errors are catastrophic
+		 * and TXMAC won't be able to recover data when these errors
+		 * occur. In a nutshell, the whole Tx path will have to be reset
+		 * and re-configured afterwards.
+		 */
+		dev_warn(&adapter->pdev->dev,
+			 "TXMAC interrupt, error 0x%08x\n",
+			 err);
 
-		/* Handle RXMAC Interrupt */
-		if (status & ET_INTR_RXMAC) {
-			/*
-			 * These interrupts are catastrophic to the device,
-			 * what we need to do is disable the interrupts and
-			 * set the flag to cause us to reset so we can solve
-			 * this issue.
-			 */
-			/* MP_SET_FLAG( adapter,
-						fMP_ADAPTER_HARDWARE_ERROR); */
+		/*
+		 * If we are debugging, we want to see this error, otherwise we
+		 * just want the device to be reset and continue
+		 */
+	}
 
-			dev_warn(&adapter->pdev->dev,
-			  "RXMAC interrupt, error 0x%08x.  Requesting reset\n",
-				    readl(&iomem->rxmac.err_reg));
+	/* Handle RXMAC Interrupt */
+	if (status & ET_INTR_RXMAC) {
+		/*
+		 * These interrupts are catastrophic to the device, what we need
+		 * to do is disable the interrupts and set the flag to cause us
+		 * to reset so we can solve this issue.
+		 */
+		/* MP_SET_FLAG( adapter, fMP_ADAPTER_HARDWARE_ERROR); */
 
-			dev_warn(&adapter->pdev->dev,
-				    "Enable 0x%08x, Diag 0x%08x\n",
-				    readl(&iomem->rxmac.ctrl),
-				    readl(&iomem->rxmac.rxq_diag));
+		dev_warn(&adapter->pdev->dev,
+			 "RXMAC interrupt, error 0x%08x.  Requesting reset\n",
+			 readl(&iomem->rxmac.err_reg));
 
-			/*
-			 * If we are debugging, we want to see this error,
-			 * otherwise we just want the device to be reset and
-			 * continue
-			 */
-		}
+		dev_warn(&adapter->pdev->dev,
+			 "Enable 0x%08x, Diag 0x%08x\n",
+			 readl(&iomem->rxmac.ctrl),
+			 readl(&iomem->rxmac.rxq_diag));
 
-		/* Handle MAC_STAT Interrupt */
-		if (status & ET_INTR_MAC_STAT) {
-			/*
-			 * This means at least one of the un-masked counters
-			 * in the MAC_STAT block has rolled over.  Use this
-			 * to maintain the top, software managed bits of the
-			 * counter(s).
-			 */
-			et1310_handle_macstat_interrupt(adapter);
-		}
+		/*
+		 * If we are debugging, we want to see this error, otherwise we
+		 * just want the device to be reset and continue
+		 */
+	}
 
-		/* Handle SLV Timeout Interrupt */
-		if (status & ET_INTR_SLV_TIMEOUT) {
-			/*
-			 * This means a timeout has occurred on a read or
-			 * write request to one of the JAGCore registers. The
-			 * Global Resources block has terminated the request
-			 * and on a read request, returned a "fake" value.
-			 * The most likely reasons are: Bad Address or the
-			 * addressed module is in a power-down state and
-			 * can't respond.
-			 */
-		}
+	/* Handle MAC_STAT Interrupt */
+	if (status & ET_INTR_MAC_STAT) {
+		/*
+		 * This means at least one of the un-masked counters in the
+		 * MAC_STAT block has rolled over. Use this to maintain the top,
+		 * software managed bits of the counter(s).
+		 */
+		et1310_handle_macstat_interrupt(adapter);
 	}
+
+	/* Handle SLV Timeout Interrupt */
+	if (status & ET_INTR_SLV_TIMEOUT) {
+		/*
+		 * This means a timeout has occurred on a read or write request
+		 * to one of the JAGCore registers. The Global Resources block
+		 * has terminated the request and on a read request, returned a
+		 * "fake" value. The most likely reasons are: Bad Address or the
+		 * addressed module is in a power-down state and can't respond.
+		 */
+	}
+out:
 	et131x_enable_interrupts(adapter);
 }
 
@@ -5221,7 +4840,7 @@ static const struct net_device_ops et131x_netdev_ops = {
  * contained in the pci_device_id table. This routine is the equivalent to
  * a device insertion routine.
  */
-static int __devinit et131x_pci_setup(struct pci_dev *pdev,
+static int et131x_pci_setup(struct pci_dev *pdev,
 			       const struct pci_device_id *ent)
 {
 	struct net_device *netdev;
@@ -5423,7 +5042,7 @@ static struct pci_driver et131x_driver = {
 	.name		= DRIVER_NAME,
 	.id_table	= et131x_pci_table,
 	.probe		= et131x_pci_setup,
-	.remove		= __devexit_p(et131x_pci_remove),
+	.remove		= et131x_pci_remove,
 	.driver.pm	= ET131X_PM_OPS,
 };
 
diff --git a/drivers/staging/et131x/et131x.h b/drivers/staging/et131x/et131x.h
index 864379b..347e63d 100644
--- a/drivers/staging/et131x/et131x.h
+++ b/drivers/staging/et131x/et131x.h
@@ -1538,10 +1538,6 @@ struct address_map {
  *	0:	int_en
  */
 
-#define ET_PHY_INT_MASK_AUTONEGSTAT	0x0100
-#define ET_PHY_INT_MASK_LINKSTAT	0x0004
-#define ET_PHY_INT_MASK_ENABLE		0x0001
-
 /* MI Register 25: Interrupt Status Reg(0x19)
  *	15-10:	reserved
  *	9:	mdio_sync_lost
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c b/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c
index 5ae3967..1edaddb 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c
@@ -205,7 +205,7 @@ int ft1000_init_proc(struct net_device *dev)
 {
 	struct ft1000_info *info;
 	struct proc_dir_entry *ft1000_proc_file;
-	int ret = 0;
+	int ret = -EINVAL;
 
 	info = netdev_priv(dev);
 
@@ -213,7 +213,6 @@ int ft1000_init_proc(struct net_device *dev)
 	if (info->ft1000_proc_dir == NULL) {
 		printk(KERN_WARNING "Unable to create %s dir.\n",
 			FT1000_PROC_DIR);
-		ret = -EINVAL;
 		goto fail;
 	}
 
@@ -223,7 +222,6 @@ int ft1000_init_proc(struct net_device *dev)
 
 	if (ft1000_proc_file == NULL) {
 		printk(KERN_WARNING "Unable to create /proc entry.\n");
-		ret = -EINVAL;
 		goto fail_entry;
 	}
 
diff --git a/drivers/staging/fwserial/Kconfig b/drivers/staging/fwserial/Kconfig
new file mode 100644
index 0000000..580406c
--- /dev/null
+++ b/drivers/staging/fwserial/Kconfig
@@ -0,0 +1,9 @@
+config FIREWIRE_SERIAL
+       tristate "TTY over Firewire"
+       depends on FIREWIRE
+       help
+          This enables TTY over IEEE 1394, providing high-speed serial
+	  connectivity to cabled peers.
+
+	  To compile this driver as a module, say M here:  the module will
+	  be called firewire-serial.
diff --git a/drivers/staging/fwserial/Makefile b/drivers/staging/fwserial/Makefile
new file mode 100644
index 0000000..2170869
--- /dev/null
+++ b/drivers/staging/fwserial/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_FIREWIRE_SERIAL) += firewire-serial.o
+firewire-serial-objs := fwserial.o dma_fifo.o
diff --git a/drivers/staging/fwserial/TODO b/drivers/staging/fwserial/TODO
new file mode 100644
index 0000000..7269005
--- /dev/null
+++ b/drivers/staging/fwserial/TODO
@@ -0,0 +1,37 @@
+TODOs
+-----
+1. Implement retries for RCODE_BUSY, RCODE_NO_ACK and RCODE_SEND_ERROR
+   - I/O is handled asynchronously which presents some issues when error
+     conditions occur.
+2. Implement _robust_ console on top of this. The existing prototype console
+   driver is not ready for the big leagues yet.
+3. Expose means of controlling attach/detach of peers via sysfs. Include
+   GUID-to-port matching/whitelist/blacklist.
+
+-- Issues with firewire stack --
+1. This driver uses the same unregistered vendor id that the firewire core does
+     (0xd00d1e). Perhaps this could be exposed as a define in
+     firewire-constants.h?
+2. MAX_ASYNC_PAYLOAD needs to be publicly exposed by core/ohci
+   - otherwise how will this driver know the max size of address window to
+     open for one packet write?
+3. Maybe device_max_receive() and link_speed_to_max_payload() should be
+     taken up by the firewire core?
+4. To avoid dropping rx data while still limiting the maximum buffering,
+     the size of the AR context must be known. How to expose this to drivers?
+5. Explore if bigger AR context will reduce RCODE_BUSY responses
+   (or auto-grow to certain max size -- but this would require major surgery
+    as the current AR is contiguously mapped)
+
+-- Issues with TTY core --
+  1. Hack for alternate device name scheme
+     - because udev no longer allows device renaming, devices should have
+       their proper names on creation. This is an issue for creating the
+       fwloop<n> device with the fwtty<n> devices because although duplicating
+       roughly the same operations as tty_port_register_device() isn't difficult,
+       access to the tty_class & tty_fops is restricted in scope.
+
+       This is currently being worked around in create_loop_device() by
+       extracting the tty_class ptr and tty_fops ptr from the previously created
+       tty devices. Perhaps an add'l api can be added -- eg.,
+       tty_{port_}register_named_device().
diff --git a/drivers/staging/fwserial/dma_fifo.c b/drivers/staging/fwserial/dma_fifo.c
new file mode 100644
index 0000000..5e84634
--- /dev/null
+++ b/drivers/staging/fwserial/dma_fifo.c
@@ -0,0 +1,307 @@
+/*
+ * DMA-able FIFO implementation
+ *
+ * Copyright (C) 2012 Peter Hurley <peter@hurleysoftware.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/bug.h>
+
+#include "dma_fifo.h"
+
+#ifdef DEBUG_TRACING
+#define df_trace(s, args...) pr_debug(s, ##args)
+#else
+#define df_trace(s, args...)
+#endif
+
+#define FAIL(fifo, condition, format...) ({				\
+	fifo->corrupt = !!(condition);					\
+	WARN(fifo->corrupt, format);					\
+})
+
+/*
+ * private helper fn to determine if check is in open interval (lo,hi)
+ */
+static bool addr_check(unsigned check, unsigned lo, unsigned hi)
+{
+	return check - (lo + 1) < (hi - 1) - lo;
+}
+
+/**
+ * dma_fifo_init: initialize the fifo to a valid but inoperative state
+ * @fifo: address of in-place "struct dma_fifo" object
+ */
+void dma_fifo_init(struct dma_fifo *fifo)
+{
+	memset(fifo, 0, sizeof(*fifo));
+	INIT_LIST_HEAD(&fifo->pending);
+}
+
+/**
+ * dma_fifo_alloc - initialize and allocate dma_fifo
+ * @fifo: address of in-place "struct dma_fifo" object
+ * @size: 'apparent' size, in bytes, of fifo
+ * @align: dma alignment to maintain (should be at least cpu cache alignment),
+ *         must be power of 2
+ * @tx_limit: maximum # of bytes transmissable per dma (rounded down to
+ *            multiple of alignment, but at least align size)
+ * @open_limit: maximum # of outstanding dma transactions allowed
+ * @gfp_mask: get_free_pages mask, passed to kmalloc()
+ *
+ * The 'apparent' size will be rounded up to next greater aligned size.
+ * Returns 0 if no error, otherwise an error code
+ */
+int dma_fifo_alloc(struct dma_fifo *fifo, int size, unsigned align,
+		   int tx_limit, int open_limit, gfp_t gfp_mask)
+{
+	int capacity;
+
+	if (!is_power_of_2(align) || size < 0)
+		return -EINVAL;
+
+	size = round_up(size, align);
+	capacity = size + align * open_limit + align * DMA_FIFO_GUARD;
+	fifo->data = kmalloc(capacity, gfp_mask);
+	if (!fifo->data)
+		return -ENOMEM;
+
+	fifo->in = 0;
+	fifo->out = 0;
+	fifo->done = 0;
+	fifo->size = size;
+	fifo->avail = size;
+	fifo->align = align;
+	fifo->tx_limit = max_t(int, round_down(tx_limit, align), align);
+	fifo->open = 0;
+	fifo->open_limit = open_limit;
+	fifo->guard = size + align * open_limit;
+	fifo->capacity = capacity;
+	fifo->corrupt = 0;
+
+	return 0;
+}
+
+/**
+ * dma_fifo_free - frees the fifo
+ * @fifo: address of in-place "struct dma_fifo" to free
+ *
+ * Also reinits the fifo to a valid but inoperative state. This
+ * allows the fifo to be reused with a different target requiring
+ * different fifo parameters.
+ */
+void dma_fifo_free(struct dma_fifo *fifo)
+{
+	struct dma_pending *pending, *next;
+
+	if (fifo->data == NULL)
+		return;
+
+	list_for_each_entry_safe(pending, next, &fifo->pending, link)
+		list_del_init(&pending->link);
+	kfree(fifo->data);
+	fifo->data = NULL;
+}
+
+/**
+ * dma_fifo_reset - dumps the fifo contents and reinits for reuse
+ * @fifo: address of in-place "struct dma_fifo" to reset
+ */
+void dma_fifo_reset(struct dma_fifo *fifo)
+{
+	struct dma_pending *pending, *next;
+
+	if (fifo->data == NULL)
+		return;
+
+	list_for_each_entry_safe(pending, next, &fifo->pending, link)
+		list_del_init(&pending->link);
+	fifo->in = 0;
+	fifo->out = 0;
+	fifo->done = 0;
+	fifo->avail = fifo->size;
+	fifo->open = 0;
+	fifo->corrupt = 0;
+}
+
+/**
+ * dma_fifo_in - copies data into the fifo
+ * @fifo: address of in-place "struct dma_fifo" to write to
+ * @src: buffer to copy from
+ * @n: # of bytes to copy
+ *
+ * Returns the # of bytes actually copied, which can be less than requested if
+ * the fifo becomes full. If < 0, return is error code.
+ */
+int dma_fifo_in(struct dma_fifo *fifo, const void *src, int n)
+{
+	int ofs, l;
+
+	if (fifo->data == NULL)
+		return -ENOENT;
+	if (fifo->corrupt)
+		return -ENXIO;
+
+	if (n > fifo->avail)
+		n = fifo->avail;
+	if (n <= 0)
+		return 0;
+
+	ofs = fifo->in % fifo->capacity;
+	l = min(n, fifo->capacity - ofs);
+	memcpy(fifo->data + ofs, src, l);
+	memcpy(fifo->data, src + l, n - l);
+
+	if (FAIL(fifo, addr_check(fifo->done, fifo->in, fifo->in + n) ||
+			fifo->avail < n,
+			"fifo corrupt: in:%u out:%u done:%u n:%d avail:%d",
+			fifo->in, fifo->out, fifo->done, n, fifo->avail))
+		return -ENXIO;
+
+	fifo->in += n;
+	fifo->avail -= n;
+
+	df_trace("in:%u out:%u done:%u n:%d avail:%d", fifo->in, fifo->out,
+		 fifo->done, n, fifo->avail);
+
+	return n;
+}
+
+/**
+ * dma_fifo_out_pend - gets address/len of next avail read and marks as pended
+ * @fifo: address of in-place "struct dma_fifo" to read from
+ * @pended: address of structure to fill with read address/len
+ *          The data/len fields will be NULL/0 if no dma is pended.
+ *
+ * Returns the # of used bytes remaining in fifo (ie, if > 0, more data
+ * remains in the fifo that was not pended). If < 0, return is error code.
+ */
+int dma_fifo_out_pend(struct dma_fifo *fifo, struct dma_pending *pended)
+{
+	unsigned len, n, ofs, l, limit;
+
+	if (fifo->data == NULL)
+		return -ENOENT;
+	if (fifo->corrupt)
+		return -ENXIO;
+
+	pended->len = 0;
+	pended->data = NULL;
+	pended->out = fifo->out;
+
+	len = fifo->in - fifo->out;
+	if (!len)
+		return -ENODATA;
+	if (fifo->open == fifo->open_limit)
+		return -EAGAIN;
+
+	n = len;
+	ofs = fifo->out % fifo->capacity;
+	l = fifo->capacity - ofs;
+	limit = min_t(unsigned, l, fifo->tx_limit);
+	if (n > limit) {
+		n = limit;
+		fifo->out += limit;
+	} else if (ofs + n > fifo->guard) {
+		fifo->out += l;
+		fifo->in = fifo->out;
+	} else {
+		fifo->out += round_up(n, fifo->align);
+		fifo->in = fifo->out;
+	}
+
+	df_trace("in: %u out: %u done: %u n: %d len: %u avail: %d", fifo->in,
+		 fifo->out, fifo->done, n, len, fifo->avail);
+
+	pended->len = n;
+	pended->data = fifo->data + ofs;
+	pended->next = fifo->out;
+	list_add_tail(&pended->link, &fifo->pending);
+	++fifo->open;
+
+	if (FAIL(fifo, fifo->open > fifo->open_limit,
+			"past open limit:%d (limit:%d)",
+			fifo->open, fifo->open_limit))
+		return -ENXIO;
+	if (FAIL(fifo, fifo->out & (fifo->align - 1),
+			"fifo out unaligned:%u (align:%u)",
+			fifo->out, fifo->align))
+		return -ENXIO;
+
+	return len - n;
+}
+
+/**
+ * dma_fifo_out_complete - marks pended dma as completed
+ * @fifo: address of in-place "struct dma_fifo" which was read from
+ * @complete: address of structure for previously pended dma to mark completed
+ */
+int dma_fifo_out_complete(struct dma_fifo *fifo, struct dma_pending *complete)
+{
+	struct dma_pending *pending, *next, *tmp;
+
+	if (fifo->data == NULL)
+		return -ENOENT;
+	if (fifo->corrupt)
+		return -ENXIO;
+	if (list_empty(&fifo->pending) && fifo->open == 0)
+		return -EINVAL;
+
+	if (FAIL(fifo, list_empty(&fifo->pending) != (fifo->open == 0),
+			"pending list disagrees with open count:%d",
+			fifo->open))
+		return -ENXIO;
+
+	tmp = complete->data;
+	*tmp = *complete;
+	list_replace(&complete->link, &tmp->link);
+	dp_mark_completed(tmp);
+
+	/* Only update the fifo in the original pended order */
+	list_for_each_entry_safe(pending, next, &fifo->pending, link) {
+		if (!dp_is_completed(pending)) {
+			df_trace("still pending: saved out: %u len: %d",
+				 pending->out, pending->len);
+			break;
+		}
+
+		if (FAIL(fifo, pending->out != fifo->done ||
+				addr_check(fifo->in, fifo->done, pending->next),
+				"in:%u out:%u done:%u saved:%u next:%u",
+				fifo->in, fifo->out, fifo->done, pending->out,
+				pending->next))
+			return -ENXIO;
+
+		list_del_init(&pending->link);
+		fifo->done = pending->next;
+		fifo->avail += pending->len;
+		--fifo->open;
+
+		df_trace("in: %u out: %u done: %u len: %u avail: %d", fifo->in,
+			 fifo->out, fifo->done, pending->len, fifo->avail);
+	}
+
+	if (FAIL(fifo, fifo->open < 0, "open dma:%d < 0", fifo->open))
+		return -ENXIO;
+	if (FAIL(fifo, fifo->avail > fifo->size, "fifo avail:%d > size:%d",
+			fifo->avail, fifo->size))
+		return -ENXIO;
+
+	return 0;
+}
diff --git a/drivers/staging/fwserial/dma_fifo.h b/drivers/staging/fwserial/dma_fifo.h
new file mode 100644
index 0000000..a113fe1
--- /dev/null
+++ b/drivers/staging/fwserial/dma_fifo.h
@@ -0,0 +1,130 @@
+/*
+ * DMA-able FIFO interface
+ *
+ * Copyright (C) 2012 Peter Hurley <peter@hurleysoftware.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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 _DMA_FIFO_H_
+#define _DMA_FIFO_H_
+
+/**
+ * The design basis for the DMA FIFO is to provide an output side that
+ * complies with the streaming DMA API design that can be DMA'd from directly
+ * (without additional copying), coupled with an input side that maintains a
+ * logically consistent 'apparent' size (ie, bytes in + bytes avail is static
+ * for the lifetime of the FIFO).
+ *
+ * DMA output transactions originate on a cache line boundary and can be
+ * variably-sized. DMA output transactions can be retired out-of-order but
+ * the FIFO will only advance the output in the original input sequence.
+ * This means the FIFO will eventually stall if a transaction is never retired.
+ *
+ * Chunking the output side into cache line multiples means that some FIFO
+ * memory is unused. For example, if all the avail input has been pended out,
+ * then the in and out markers are re-aligned to the next cache line.
+ * The maximum possible waste is
+ *     (cache line alignment - 1) * (max outstanding dma transactions)
+ * This potential waste requires additional hidden capacity within the FIFO
+ * to be able to accept input while the 'apparent' size has not been reached.
+ *
+ * Additional cache lines (ie, guard area) are used to minimize DMA
+ * fragmentation when wrapping at the end of the FIFO. Input is allowed into the
+ * guard area, but the in and out FIFO markers are wrapped when DMA is pended.
+ */
+
+#define DMA_FIFO_GUARD 3   /* # of cache lines to reserve for the guard area */
+
+struct dma_fifo {
+	unsigned	 in;
+	unsigned	 out;		/* updated when dma is pended         */
+	unsigned	 done;		/* updated upon dma completion        */
+	struct {
+		unsigned corrupt:1;
+	};
+	int		 size;		/* 'apparent' size of fifo	      */
+	int		 guard;		/* ofs of guard area		      */
+	int		 capacity;	/* size + reserved                    */
+	int		 avail;		/* # of unused bytes in fifo          */
+	unsigned	 align;		/* must be power of 2                 */
+	int		 tx_limit;	/* max # of bytes per dma transaction */
+	int		 open_limit;	/* max # of outstanding allowed       */
+	int		 open;		/* # of outstanding dma transactions  */
+	struct list_head pending;	/* fifo markers for outstanding dma   */
+	void		 *data;
+};
+
+struct dma_pending {
+	struct list_head link;
+	void		 *data;
+	unsigned	 len;
+	unsigned         next;
+	unsigned         out;
+};
+
+static inline void dp_mark_completed(struct dma_pending *dp)
+{
+	dp->data += 1;
+}
+
+static inline bool dp_is_completed(struct dma_pending *dp)
+{
+	return (unsigned long)dp->data & 1UL;
+}
+
+extern void dma_fifo_init(struct dma_fifo *fifo);
+extern int dma_fifo_alloc(struct dma_fifo *fifo, int size, unsigned align,
+			  int tx_limit, int open_limit, gfp_t gfp_mask);
+extern void dma_fifo_free(struct dma_fifo *fifo);
+extern void dma_fifo_reset(struct dma_fifo *fifo);
+extern int dma_fifo_in(struct dma_fifo *fifo, const void *src, int n);
+extern int dma_fifo_out_pend(struct dma_fifo *fifo, struct dma_pending *pended);
+extern int dma_fifo_out_complete(struct dma_fifo *fifo,
+				 struct dma_pending *complete);
+
+/* returns the # of used bytes in the fifo */
+static inline int dma_fifo_level(struct dma_fifo *fifo)
+{
+	return fifo->size - fifo->avail;
+}
+
+/* returns the # of bytes ready for output in the fifo */
+static inline int dma_fifo_out_level(struct dma_fifo *fifo)
+{
+	return fifo->in - fifo->out;
+}
+
+/* returns the # of unused bytes in the fifo */
+static inline int dma_fifo_avail(struct dma_fifo *fifo)
+{
+	return fifo->avail;
+}
+
+/* returns true if fifo has max # of outstanding dmas */
+static inline bool dma_fifo_busy(struct dma_fifo *fifo)
+{
+	return fifo->open == fifo->open_limit;
+}
+
+/* changes the max size of dma returned from dma_fifo_out_pend() */
+static inline int dma_fifo_change_tx_limit(struct dma_fifo *fifo, int tx_limit)
+{
+	tx_limit = round_down(tx_limit, fifo->align);
+	fifo->tx_limit = max_t(int, tx_limit, fifo->align);
+	return 0;
+}
+
+#endif /* _DMA_FIFO_H_ */
diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c
new file mode 100644
index 0000000..61ee290
--- /dev/null
+++ b/drivers/staging/fwserial/fwserial.c
@@ -0,0 +1,2943 @@
+/*
+ * FireWire Serial driver
+ *
+ * Copyright (C) 2012 Peter Hurley <peter@hurleysoftware.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/sched.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/rculist.h>
+#include <linux/workqueue.h>
+#include <linux/ratelimit.h>
+#include <linux/bug.h>
+#include <linux/uaccess.h>
+
+#include "fwserial.h"
+
+#define be32_to_u64(hi, lo)  ((u64)be32_to_cpu(hi) << 32 | be32_to_cpu(lo))
+
+#define LINUX_VENDOR_ID   0xd00d1eU  /* same id used in card root directory   */
+#define FWSERIAL_VERSION  0x00e81cU  /* must be unique within LINUX_VENDOR_ID */
+
+/* configurable options */
+static int num_ttys = 4;	    /* # of std ttys to create per fw_card    */
+				    /* - doubles as loopback port index       */
+static bool auto_connect = true;    /* try to VIRT_CABLE to every peer        */
+static bool create_loop_dev = true; /* create a loopback device for each card */
+bool limit_bw;			    /* limit async bandwidth to 20% of max    */
+
+module_param_named(ttys, num_ttys, int, S_IRUGO | S_IWUSR);
+module_param_named(auto, auto_connect, bool, S_IRUGO | S_IWUSR);
+module_param_named(loop, create_loop_dev, bool, S_IRUGO | S_IWUSR);
+module_param(limit_bw, bool, S_IRUGO | S_IWUSR);
+
+/*
+ * Threshold below which the tty is woken for writing
+ * - should be equal to WAKEUP_CHARS in drivers/tty/n_tty.c because
+ *   even if the writer is woken, n_tty_poll() won't set POLLOUT until
+ *   our fifo is below this level
+ */
+#define WAKEUP_CHARS             256
+
+/**
+ * fwserial_list: list of every fw_serial created for each fw_card
+ * See discussion in fwserial_probe.
+ */
+static LIST_HEAD(fwserial_list);
+static DEFINE_MUTEX(fwserial_list_mutex);
+
+/**
+ * port_table: array of tty ports allocated to each fw_card
+ *
+ * tty ports are allocated during probe when an fw_serial is first
+ * created for a given fw_card. Ports are allocated in a contiguous block,
+ * each block consisting of 'num_ports' ports.
+ */
+static struct fwtty_port *port_table[MAX_TOTAL_PORTS];
+static DEFINE_MUTEX(port_table_lock);
+static bool port_table_corrupt;
+#define FWTTY_INVALID_INDEX  MAX_TOTAL_PORTS
+
+/* total # of tty ports created per fw_card */
+static int num_ports;
+
+/* slab used as pool for struct fwtty_transactions */
+static struct kmem_cache *fwtty_txn_cache;
+
+struct fwtty_transaction;
+typedef void (*fwtty_transaction_cb)(struct fw_card *card, int rcode,
+				     void *data, size_t length,
+				     struct fwtty_transaction *txn);
+
+struct fwtty_transaction {
+	struct fw_transaction      fw_txn;
+	fwtty_transaction_cb       callback;
+	struct fwtty_port	   *port;
+	union {
+		struct dma_pending dma_pended;
+	};
+};
+
+#define to_device(a, b)			(a->b)
+#define fwtty_err(p, s, v...)		dev_err(to_device(p, device), s, ##v)
+#define fwtty_info(p, s, v...)		dev_info(to_device(p, device), s, ##v)
+#define fwtty_notice(p, s, v...)	dev_notice(to_device(p, device), s, ##v)
+#define fwtty_dbg(p, s, v...)		\
+		dev_dbg(to_device(p, device), "%s: " s, __func__, ##v)
+#define fwtty_err_ratelimited(p, s, v...) \
+		dev_err_ratelimited(to_device(p, device), s, ##v)
+
+#ifdef DEBUG
+static inline void debug_short_write(struct fwtty_port *port, int c, int n)
+{
+	int avail;
+
+	if (n < c) {
+		spin_lock_bh(&port->lock);
+		avail = dma_fifo_avail(&port->tx_fifo);
+		spin_unlock_bh(&port->lock);
+		fwtty_dbg(port, "short write: avail:%d req:%d wrote:%d",
+			  avail, c, n);
+	}
+}
+#else
+#define debug_short_write(port, c, n)
+#endif
+
+static struct fwtty_peer *__fwserial_peer_by_node_id(struct fw_card *card,
+						     int generation, int id);
+
+#ifdef FWTTY_PROFILING
+
+static void profile_fifo_avail(struct fwtty_port *port, unsigned *stat)
+{
+	spin_lock_bh(&port->lock);
+	profile_size_distrib(stat, dma_fifo_avail(&port->tx_fifo));
+	spin_unlock_bh(&port->lock);
+}
+
+static void dump_profile(struct seq_file *m, struct stats *stats)
+{
+	/* for each stat, print sum of 0 to 2^k, then individually */
+	int k = 4;
+	unsigned sum;
+	int j;
+	char t[10];
+
+	snprintf(t, 10, "< %d", 1 << k);
+	seq_printf(m, "\n%14s  %6s", " ", t);
+	for (j = k + 1; j < DISTRIBUTION_MAX_INDEX; ++j)
+		seq_printf(m, "%6d", 1 << j);
+
+	++k;
+	for (j = 0, sum = 0; j <= k; ++j)
+		sum += stats->reads[j];
+	seq_printf(m, "\n%14s: %6d", "reads", sum);
+	for (j = k + 1; j <= DISTRIBUTION_MAX_INDEX; ++j)
+		seq_printf(m, "%6d", stats->reads[j]);
+
+	for (j = 0, sum = 0; j <= k; ++j)
+		sum += stats->writes[j];
+	seq_printf(m, "\n%14s: %6d", "writes", sum);
+	for (j = k + 1; j <= DISTRIBUTION_MAX_INDEX; ++j)
+		seq_printf(m, "%6d", stats->writes[j]);
+
+	for (j = 0, sum = 0; j <= k; ++j)
+		sum += stats->txns[j];
+	seq_printf(m, "\n%14s: %6d", "txns", sum);
+	for (j = k + 1; j <= DISTRIBUTION_MAX_INDEX; ++j)
+		seq_printf(m, "%6d", stats->txns[j]);
+
+	for (j = 0, sum = 0; j <= k; ++j)
+		sum += stats->unthrottle[j];
+	seq_printf(m, "\n%14s: %6d", "avail @ unthr", sum);
+	for (j = k + 1; j <= DISTRIBUTION_MAX_INDEX; ++j)
+		seq_printf(m, "%6d", stats->unthrottle[j]);
+}
+
+#else
+#define profile_fifo_avail(port, stat)
+#define dump_profile(m, stats)
+#endif
+
+/* Returns the max receive packet size for the given card */
+static inline int device_max_receive(struct fw_device *fw_device)
+{
+	return 1 <<  (clamp_t(int, fw_device->max_rec, 8U, 13U) + 1);
+}
+
+static void fwtty_log_tx_error(struct fwtty_port *port, int rcode)
+{
+	switch (rcode) {
+	case RCODE_SEND_ERROR:
+		fwtty_err_ratelimited(port, "card busy");
+		break;
+	case RCODE_ADDRESS_ERROR:
+		fwtty_err_ratelimited(port, "bad unit addr or write length");
+		break;
+	case RCODE_DATA_ERROR:
+		fwtty_err_ratelimited(port, "failed rx");
+		break;
+	case RCODE_NO_ACK:
+		fwtty_err_ratelimited(port, "missing ack");
+		break;
+	case RCODE_BUSY:
+		fwtty_err_ratelimited(port, "remote busy");
+		break;
+	default:
+		fwtty_err_ratelimited(port, "failed tx: %d", rcode);
+	}
+}
+
+static void fwtty_txn_constructor(void *this)
+{
+	struct fwtty_transaction *txn = this;
+
+	init_timer(&txn->fw_txn.split_timeout_timer);
+}
+
+static void fwtty_common_callback(struct fw_card *card, int rcode,
+				  void *payload, size_t len, void *cb_data)
+{
+	struct fwtty_transaction *txn = cb_data;
+	struct fwtty_port *port = txn->port;
+
+	if (port && rcode != RCODE_COMPLETE)
+		fwtty_log_tx_error(port, rcode);
+	if (txn->callback)
+		txn->callback(card, rcode, payload, len, txn);
+	kmem_cache_free(fwtty_txn_cache, txn);
+}
+
+static int fwtty_send_data_async(struct fwtty_peer *peer, int tcode,
+				 unsigned long long addr, void *payload,
+				 size_t len, fwtty_transaction_cb callback,
+				 struct fwtty_port *port)
+{
+	struct fwtty_transaction *txn;
+	int generation;
+
+	txn = kmem_cache_alloc(fwtty_txn_cache, GFP_ATOMIC);
+	if (!txn)
+		return -ENOMEM;
+
+	txn->callback = callback;
+	txn->port = port;
+
+	generation = peer->generation;
+	smp_rmb();
+	fw_send_request(peer->serial->card, &txn->fw_txn, tcode,
+			peer->node_id, generation, peer->speed, addr, payload,
+			len, fwtty_common_callback, txn);
+	return 0;
+}
+
+static void fwtty_send_txn_async(struct fwtty_peer *peer,
+				 struct fwtty_transaction *txn, int tcode,
+				 unsigned long long addr, void *payload,
+				 size_t len, fwtty_transaction_cb callback,
+				 struct fwtty_port *port)
+{
+	int generation;
+
+	txn->callback = callback;
+	txn->port = port;
+
+	generation = peer->generation;
+	smp_rmb();
+	fw_send_request(peer->serial->card, &txn->fw_txn, tcode,
+			peer->node_id, generation, peer->speed, addr, payload,
+			len, fwtty_common_callback, txn);
+}
+
+
+static void __fwtty_restart_tx(struct fwtty_port *port)
+{
+	int len, avail;
+
+	len = dma_fifo_out_level(&port->tx_fifo);
+	if (len)
+		schedule_delayed_work(&port->drain, 0);
+	avail = dma_fifo_avail(&port->tx_fifo);
+
+	fwtty_dbg(port, "fifo len: %d avail: %d", len, avail);
+}
+
+static void fwtty_restart_tx(struct fwtty_port *port)
+{
+	spin_lock_bh(&port->lock);
+	__fwtty_restart_tx(port);
+	spin_unlock_bh(&port->lock);
+}
+
+/**
+ * fwtty_update_port_status - decodes & dispatches line status changes
+ *
+ * Note: in loopback, the port->lock is being held. Only use functions that
+ * don't attempt to reclaim the port->lock.
+ */
+static void fwtty_update_port_status(struct fwtty_port *port, unsigned status)
+{
+	unsigned delta;
+	struct tty_struct *tty;
+
+	/* simulated LSR/MSR status from remote */
+	status &= ~MCTRL_MASK;
+	delta = (port->mstatus ^ status) & ~MCTRL_MASK;
+	delta &= ~(status & TIOCM_RNG);
+	port->mstatus = status;
+
+	if (delta & TIOCM_RNG)
+		++port->icount.rng;
+	if (delta & TIOCM_DSR)
+		++port->icount.dsr;
+	if (delta & TIOCM_CAR)
+		++port->icount.dcd;
+	if (delta & TIOCM_CTS)
+		++port->icount.cts;
+
+	fwtty_dbg(port, "status: %x delta: %x", status, delta);
+
+	if (delta & TIOCM_CAR) {
+		tty = tty_port_tty_get(&port->port);
+		if (tty && !C_CLOCAL(tty)) {
+			if (status & TIOCM_CAR)
+				wake_up_interruptible(&port->port.open_wait);
+			else
+				schedule_work(&port->hangup);
+		}
+		tty_kref_put(tty);
+	}
+
+	if (delta & TIOCM_CTS) {
+		tty = tty_port_tty_get(&port->port);
+		if (tty && C_CRTSCTS(tty)) {
+			if (tty->hw_stopped) {
+				if (status & TIOCM_CTS) {
+					tty->hw_stopped = 0;
+					if (port->loopback)
+						__fwtty_restart_tx(port);
+					else
+						fwtty_restart_tx(port);
+				}
+			} else {
+				if (~status & TIOCM_CTS)
+					tty->hw_stopped = 1;
+			}
+		}
+		tty_kref_put(tty);
+
+	} else if (delta & OOB_TX_THROTTLE) {
+		tty = tty_port_tty_get(&port->port);
+		if (tty) {
+			if (tty->hw_stopped) {
+				if (~status & OOB_TX_THROTTLE) {
+					tty->hw_stopped = 0;
+					if (port->loopback)
+						__fwtty_restart_tx(port);
+					else
+						fwtty_restart_tx(port);
+				}
+			} else {
+				if (status & OOB_TX_THROTTLE)
+					tty->hw_stopped = 1;
+			}
+		}
+		tty_kref_put(tty);
+	}
+
+	if (delta & (UART_LSR_BI << 24)) {
+		if (status & (UART_LSR_BI << 24)) {
+			port->break_last = jiffies;
+			schedule_delayed_work(&port->emit_breaks, 0);
+		} else {
+			/* run emit_breaks one last time (if pending) */
+			mod_delayed_work(system_wq, &port->emit_breaks, 0);
+		}
+	}
+
+	if (delta & (TIOCM_DSR | TIOCM_CAR | TIOCM_CTS | TIOCM_RNG))
+		wake_up_interruptible(&port->port.delta_msr_wait);
+}
+
+/**
+ * __fwtty_port_line_status - generate 'line status' for indicated port
+ *
+ * This function returns a remote 'MSR' state based on the local 'MCR' state,
+ * as if a null modem cable was attached. The actual status is a mangling
+ * of TIOCM_* bits suitable for sending to a peer's status_addr.
+ *
+ * Note: caller must be holding port lock
+ */
+static unsigned __fwtty_port_line_status(struct fwtty_port *port)
+{
+	unsigned status = 0;
+
+	/* TODO: add module param to tie RNG to DTR as well */
+
+	if (port->mctrl & TIOCM_DTR)
+		status |= TIOCM_DSR | TIOCM_CAR;
+	if (port->mctrl & TIOCM_RTS)
+		status |= TIOCM_CTS;
+	if (port->mctrl & OOB_RX_THROTTLE)
+		status |= OOB_TX_THROTTLE;
+	/* emulate BRK as add'l line status */
+	if (port->break_ctl)
+		status |= UART_LSR_BI << 24;
+
+	return status;
+}
+
+/**
+ * __fwtty_write_port_status - send the port line status to peer
+ *
+ * Note: caller must be holding the port lock.
+ */
+static int __fwtty_write_port_status(struct fwtty_port *port)
+{
+	struct fwtty_peer *peer;
+	int err = -ENOENT;
+	unsigned status = __fwtty_port_line_status(port);
+
+	rcu_read_lock();
+	peer = rcu_dereference(port->peer);
+	if (peer) {
+		err = fwtty_send_data_async(peer, TCODE_WRITE_QUADLET_REQUEST,
+					    peer->status_addr, &status,
+					    sizeof(status), NULL, port);
+	}
+	rcu_read_unlock();
+
+	return err;
+}
+
+/**
+ * fwtty_write_port_status - same as above but locked by port lock
+ */
+static int fwtty_write_port_status(struct fwtty_port *port)
+{
+	int err;
+
+	spin_lock_bh(&port->lock);
+	err = __fwtty_write_port_status(port);
+	spin_unlock_bh(&port->lock);
+	return err;
+}
+
+static void __fwtty_throttle(struct fwtty_port *port, struct tty_struct *tty)
+{
+	unsigned old;
+
+	old = port->mctrl;
+	port->mctrl |= OOB_RX_THROTTLE;
+	if (C_CRTSCTS(tty))
+		port->mctrl &= ~TIOCM_RTS;
+	if (~old & OOB_RX_THROTTLE)
+		__fwtty_write_port_status(port);
+}
+
+/**
+ * fwtty_do_hangup - wait for ldisc to deliver all pending rx; only then hangup
+ *
+ * When the remote has finished tx, and all in-flight rx has been received and
+ * and pushed to the flip buffer, the remote may close its device. This will
+ * drop DTR on the remote which will drop carrier here. Typically, the tty is
+ * hung up when carrier is dropped or lost.
+ *
+ * However, there is a race between the hang up and the line discipline
+ * delivering its data to the reader. A hangup will cause the ldisc to flush
+ * (ie., clear) the read buffer and flip buffer. Because of firewire's
+ * relatively high throughput, the ldisc frequently lags well behind the driver,
+ * resulting in lost data (which has already been received and written to
+ * the flip buffer) when the remote closes its end.
+ *
+ * Unfortunately, since the flip buffer offers no direct method for determining
+ * if it holds data, ensuring the ldisc has delivered all data is problematic.
+ */
+
+/* FIXME: drop this workaround when __tty_hangup waits for ldisc completion */
+static void fwtty_do_hangup(struct work_struct *work)
+{
+	struct fwtty_port *port = to_port(work, hangup);
+	struct tty_struct *tty;
+
+	schedule_timeout_uninterruptible(msecs_to_jiffies(50));
+
+	tty = tty_port_tty_get(&port->port);
+	if (tty)
+		tty_vhangup(tty);
+	tty_kref_put(tty);
+}
+
+
+static void fwtty_emit_breaks(struct work_struct *work)
+{
+	struct fwtty_port *port = to_port(to_delayed_work(work), emit_breaks);
+	struct tty_struct *tty;
+	static const char buf[16];
+	unsigned long now = jiffies;
+	unsigned long elapsed = now - port->break_last;
+	int n, t, c, brk = 0;
+
+	tty = tty_port_tty_get(&port->port);
+	if (!tty)
+		return;
+
+	/* generate breaks at the line rate (but at least 1) */
+	n = (elapsed * port->cps) / HZ + 1;
+	port->break_last = now;
+
+	fwtty_dbg(port, "sending %d brks", n);
+
+	while (n) {
+		t = min(n, 16);
+		c = tty_insert_flip_string_fixed_flag(tty, buf, TTY_BREAK, t);
+		n -= c;
+		brk += c;
+		if (c < t)
+			break;
+	}
+	tty_flip_buffer_push(tty);
+
+	tty_kref_put(tty);
+
+	if (port->mstatus & (UART_LSR_BI << 24))
+		schedule_delayed_work(&port->emit_breaks, FREQ_BREAKS);
+	port->icount.brk += brk;
+}
+
+static void fwtty_pushrx(struct work_struct *work)
+{
+	struct fwtty_port *port = to_port(work, push);
+	struct tty_struct *tty;
+	struct buffered_rx *buf, *next;
+	int n, c = 0;
+
+	tty = tty_port_tty_get(&port->port);
+	if (!tty)
+		return;
+
+	spin_lock_bh(&port->lock);
+	list_for_each_entry_safe(buf, next, &port->buf_list, list) {
+		n = tty_insert_flip_string_fixed_flag(tty, buf->data,
+						      TTY_NORMAL, buf->n);
+		c += n;
+		port->buffered -= n;
+		if (n < buf->n) {
+			if (n > 0) {
+				memmove(buf->data, buf->data + n, buf->n - n);
+				buf->n -= n;
+			}
+			__fwtty_throttle(port, tty);
+			break;
+		} else {
+			list_del(&buf->list);
+			kfree(buf);
+		}
+	}
+	if (c > 0)
+		tty_flip_buffer_push(tty);
+
+	if (list_empty(&port->buf_list))
+		clear_bit(BUFFERING_RX, &port->flags);
+	spin_unlock_bh(&port->lock);
+
+	tty_kref_put(tty);
+}
+
+static int fwtty_buffer_rx(struct fwtty_port *port, unsigned char *d, size_t n)
+{
+	struct buffered_rx *buf;
+	size_t size = (n + sizeof(struct buffered_rx) + 0xFF) & ~0xFF;
+
+	if (port->buffered + n > HIGH_WATERMARK)
+		return 0;
+	buf = kmalloc(size, GFP_ATOMIC);
+	if (!buf)
+		return 0;
+	INIT_LIST_HEAD(&buf->list);
+	buf->n = n;
+	memcpy(buf->data, d, n);
+
+	spin_lock_bh(&port->lock);
+	list_add_tail(&buf->list, &port->buf_list);
+	port->buffered += n;
+	if (port->buffered > port->stats.watermark)
+		port->stats.watermark = port->buffered;
+	set_bit(BUFFERING_RX, &port->flags);
+	spin_unlock_bh(&port->lock);
+
+	return n;
+}
+
+static int fwtty_rx(struct fwtty_port *port, unsigned char *data, size_t len)
+{
+	struct tty_struct *tty;
+	int c, n = len;
+	unsigned lsr;
+	int err = 0;
+
+	tty = tty_port_tty_get(&port->port);
+	if (!tty)
+		return -ENOENT;
+
+	fwtty_dbg(port, "%d", n);
+	profile_size_distrib(port->stats.reads, n);
+
+	if (port->write_only) {
+		n = 0;
+		goto out;
+	}
+
+	/* disregard break status; breaks are generated by emit_breaks work */
+	lsr = (port->mstatus >> 24) & ~UART_LSR_BI;
+
+	if (port->overrun)
+		lsr |= UART_LSR_OE;
+
+	if (lsr & UART_LSR_OE)
+		++port->icount.overrun;
+
+	lsr &= port->status_mask;
+	if (lsr & ~port->ignore_mask & UART_LSR_OE) {
+		if (!tty_insert_flip_char(tty, 0, TTY_OVERRUN)) {
+			err = -EIO;
+			goto out;
+		}
+	}
+	port->overrun = false;
+
+	if (lsr & port->ignore_mask & ~UART_LSR_OE) {
+		/* TODO: don't drop SAK and Magic SysRq here */
+		n = 0;
+		goto out;
+	}
+
+	if (!test_bit(BUFFERING_RX, &port->flags)) {
+		c = tty_insert_flip_string_fixed_flag(tty, data, TTY_NORMAL, n);
+		if (c > 0)
+			tty_flip_buffer_push(tty);
+		n -= c;
+
+		if (n) {
+			/* start buffering and throttling */
+			n -= fwtty_buffer_rx(port, &data[c], n);
+
+			spin_lock_bh(&port->lock);
+			__fwtty_throttle(port, tty);
+			spin_unlock_bh(&port->lock);
+		}
+	} else
+		n -= fwtty_buffer_rx(port, data, n);
+
+	if (n) {
+		port->overrun = true;
+		err = -EIO;
+	}
+
+out:
+	tty_kref_put(tty);
+
+	port->icount.rx += len;
+	port->stats.lost += n;
+	return err;
+}
+
+/**
+ * fwtty_port_handler - bus address handler for port reads/writes
+ * @parameters: fw_address_callback_t as specified by firewire core interface
+ *
+ * This handler is responsible for handling inbound read/write dma from remotes.
+ */
+static void fwtty_port_handler(struct fw_card *card,
+			       struct fw_request *request,
+			       int tcode, int destination, int source,
+			       int generation,
+			       unsigned long long addr,
+			       void *data, size_t len,
+			       void *callback_data)
+{
+	struct fwtty_port *port = callback_data;
+	struct fwtty_peer *peer;
+	int err;
+	int rcode;
+
+	/* Only accept rx from the peer virtual-cabled to this port */
+	rcu_read_lock();
+	peer = __fwserial_peer_by_node_id(card, generation, source);
+	rcu_read_unlock();
+	if (!peer || peer != rcu_access_pointer(port->peer)) {
+		rcode = RCODE_ADDRESS_ERROR;
+		fwtty_err_ratelimited(port, "ignoring unauthenticated data");
+		goto respond;
+	}
+
+	switch (tcode) {
+	case TCODE_WRITE_QUADLET_REQUEST:
+		if (addr != port->rx_handler.offset || len != 4)
+			rcode = RCODE_ADDRESS_ERROR;
+		else {
+			fwtty_update_port_status(port, *(unsigned *)data);
+			rcode = RCODE_COMPLETE;
+		}
+		break;
+
+	case TCODE_WRITE_BLOCK_REQUEST:
+		if (addr != port->rx_handler.offset + 4 ||
+		    len > port->rx_handler.length - 4) {
+			rcode = RCODE_ADDRESS_ERROR;
+		} else {
+			err = fwtty_rx(port, data, len);
+			switch (err) {
+			case 0:
+				rcode = RCODE_COMPLETE;
+				break;
+			case -EIO:
+				rcode = RCODE_DATA_ERROR;
+				break;
+			default:
+				rcode = RCODE_CONFLICT_ERROR;
+				break;
+			}
+		}
+		break;
+
+	default:
+		rcode = RCODE_TYPE_ERROR;
+	}
+
+respond:
+	fw_send_response(card, request, rcode);
+}
+
+/**
+ * fwtty_tx_complete - callback for tx dma
+ * @data: ignored, has no meaning for write txns
+ * @length: ignored, has no meaning for write txns
+ *
+ * The writer must be woken here if the fifo has been emptied because it
+ * may have slept if chars_in_buffer was != 0
+ */
+static void fwtty_tx_complete(struct fw_card *card, int rcode,
+			      void *data, size_t length,
+			      struct fwtty_transaction *txn)
+{
+	struct fwtty_port *port = txn->port;
+	struct tty_struct *tty;
+	int len;
+
+	fwtty_dbg(port, "rcode: %d", rcode);
+
+	switch (rcode) {
+	case RCODE_COMPLETE:
+		spin_lock_bh(&port->lock);
+		dma_fifo_out_complete(&port->tx_fifo, &txn->dma_pended);
+		len = dma_fifo_level(&port->tx_fifo);
+		spin_unlock_bh(&port->lock);
+
+		port->icount.tx += txn->dma_pended.len;
+		break;
+
+	default:
+		/* TODO: implement retries */
+		spin_lock_bh(&port->lock);
+		dma_fifo_out_complete(&port->tx_fifo, &txn->dma_pended);
+		len = dma_fifo_level(&port->tx_fifo);
+		spin_unlock_bh(&port->lock);
+
+		port->stats.dropped += txn->dma_pended.len;
+	}
+
+	if (len < WAKEUP_CHARS) {
+		tty = tty_port_tty_get(&port->port);
+		if (tty) {
+			tty_wakeup(tty);
+			tty_kref_put(tty);
+		}
+	}
+}
+
+static int fwtty_tx(struct fwtty_port *port, bool drain)
+{
+	struct fwtty_peer *peer;
+	struct fwtty_transaction *txn;
+	struct tty_struct *tty;
+	int n, len;
+
+	tty = tty_port_tty_get(&port->port);
+	if (!tty)
+		return -ENOENT;
+
+	rcu_read_lock();
+	peer = rcu_dereference(port->peer);
+	if (!peer) {
+		n = -EIO;
+		goto out;
+	}
+
+	if (test_and_set_bit(IN_TX, &port->flags)) {
+		n = -EALREADY;
+		goto out;
+	}
+
+	/* try to write as many dma transactions out as possible */
+	n = -EAGAIN;
+	while (!tty->stopped && !tty->hw_stopped &&
+			!test_bit(STOP_TX, &port->flags)) {
+		txn = kmem_cache_alloc(fwtty_txn_cache, GFP_ATOMIC);
+		if (!txn) {
+			n = -ENOMEM;
+			break;
+		}
+
+		spin_lock_bh(&port->lock);
+		n = dma_fifo_out_pend(&port->tx_fifo, &txn->dma_pended);
+		spin_unlock_bh(&port->lock);
+
+		fwtty_dbg(port, "out: %u rem: %d", txn->dma_pended.len, n);
+
+		if (n < 0) {
+			kmem_cache_free(fwtty_txn_cache, txn);
+			if (n == -EAGAIN)
+				++port->stats.tx_stall;
+			else if (n == -ENODATA)
+				profile_size_distrib(port->stats.txns, 0);
+			else {
+				++port->stats.fifo_errs;
+				fwtty_err_ratelimited(port, "fifo err: %d", n);
+			}
+			break;
+		}
+
+		profile_size_distrib(port->stats.txns, txn->dma_pended.len);
+
+		fwtty_send_txn_async(peer, txn, TCODE_WRITE_BLOCK_REQUEST,
+				     peer->fifo_addr, txn->dma_pended.data,
+				     txn->dma_pended.len, fwtty_tx_complete,
+				     port);
+		++port->stats.sent;
+
+		/*
+		 * Stop tx if the 'last view' of the fifo is empty or if
+		 * this is the writer and there's not enough data to bother
+		 */
+		if (n == 0 || (!drain && n < WRITER_MINIMUM))
+			break;
+	}
+
+	if (n >= 0 || n == -EAGAIN || n == -ENOMEM || n == -ENODATA) {
+		spin_lock_bh(&port->lock);
+		len = dma_fifo_out_level(&port->tx_fifo);
+		if (len) {
+			unsigned long delay = (n == -ENOMEM) ? HZ : 1;
+			schedule_delayed_work(&port->drain, delay);
+		}
+		len = dma_fifo_level(&port->tx_fifo);
+		spin_unlock_bh(&port->lock);
+
+		/* wakeup the writer */
+		if (drain && len < WAKEUP_CHARS)
+			tty_wakeup(tty);
+	}
+
+	clear_bit(IN_TX, &port->flags);
+	wake_up_interruptible(&port->wait_tx);
+
+out:
+	rcu_read_unlock();
+	tty_kref_put(tty);
+	return n;
+}
+
+static void fwtty_drain_tx(struct work_struct *work)
+{
+	struct fwtty_port *port = to_port(to_delayed_work(work), drain);
+
+	fwtty_tx(port, true);
+}
+
+static void fwtty_write_xchar(struct fwtty_port *port, char ch)
+{
+	struct fwtty_peer *peer;
+
+	++port->stats.xchars;
+
+	fwtty_dbg(port, "%02x", ch);
+
+	rcu_read_lock();
+	peer = rcu_dereference(port->peer);
+	if (peer) {
+		fwtty_send_data_async(peer, TCODE_WRITE_BLOCK_REQUEST,
+				      peer->fifo_addr, &ch, sizeof(ch),
+				      NULL, port);
+	}
+	rcu_read_unlock();
+}
+
+struct fwtty_port *fwtty_port_get(unsigned index)
+{
+	struct fwtty_port *port;
+
+	if (index >= MAX_TOTAL_PORTS)
+		return NULL;
+
+	mutex_lock(&port_table_lock);
+	port = port_table[index];
+	if (port)
+		kref_get(&port->serial->kref);
+	mutex_unlock(&port_table_lock);
+	return port;
+}
+EXPORT_SYMBOL(fwtty_port_get);
+
+static int fwtty_ports_add(struct fw_serial *serial)
+{
+	int err = -EBUSY;
+	int i, j;
+
+	if (port_table_corrupt)
+		return err;
+
+	mutex_lock(&port_table_lock);
+	for (i = 0; i + num_ports <= MAX_TOTAL_PORTS; i += num_ports) {
+		if (!port_table[i]) {
+			for (j = 0; j < num_ports; ++i, ++j) {
+				serial->ports[j]->index = i;
+				port_table[i] = serial->ports[j];
+			}
+			err = 0;
+			break;
+		}
+	}
+	mutex_unlock(&port_table_lock);
+	return err;
+}
+
+static void fwserial_destroy(struct kref *kref)
+{
+	struct fw_serial *serial = to_serial(kref, kref);
+	struct fwtty_port **ports = serial->ports;
+	int j, i = ports[0]->index;
+
+	synchronize_rcu();
+
+	mutex_lock(&port_table_lock);
+	for (j = 0; j < num_ports; ++i, ++j) {
+		port_table_corrupt |= port_table[i] != ports[j];
+		WARN_ONCE(port_table_corrupt, "port_table[%d]: %p != ports[%d]: %p",
+		     i, port_table[i], j, ports[j]);
+
+		port_table[i] = NULL;
+	}
+	mutex_unlock(&port_table_lock);
+
+	for (j = 0; j < num_ports; ++j) {
+		fw_core_remove_address_handler(&ports[j]->rx_handler);
+		tty_port_destroy(&ports[j]->port);
+		kfree(ports[j]);
+	}
+	kfree(serial);
+}
+
+void fwtty_port_put(struct fwtty_port *port)
+{
+	kref_put(&port->serial->kref, fwserial_destroy);
+}
+EXPORT_SYMBOL(fwtty_port_put);
+
+static void fwtty_port_dtr_rts(struct tty_port *tty_port, int on)
+{
+	struct fwtty_port *port = to_port(tty_port, port);
+
+	fwtty_dbg(port, "on/off: %d", on);
+
+	spin_lock_bh(&port->lock);
+	/* Don't change carrier state if this is a console */
+	if (!port->port.console) {
+		if (on)
+			port->mctrl |= TIOCM_DTR | TIOCM_RTS;
+		else
+			port->mctrl &= ~(TIOCM_DTR | TIOCM_RTS);
+	}
+
+	__fwtty_write_port_status(port);
+	spin_unlock_bh(&port->lock);
+}
+
+/**
+ * fwtty_port_carrier_raised: required tty_port operation
+ *
+ * This port operation is polled after a tty has been opened and is waiting for
+ * carrier detect -- see drivers/tty/tty_port:tty_port_block_til_ready().
+ */
+static int fwtty_port_carrier_raised(struct tty_port *tty_port)
+{
+	struct fwtty_port *port = to_port(tty_port, port);
+	int rc;
+
+	rc = (port->mstatus & TIOCM_CAR);
+
+	fwtty_dbg(port, "%d", rc);
+
+	return rc;
+}
+
+static unsigned set_termios(struct fwtty_port *port, struct tty_struct *tty)
+{
+	unsigned baud, frame;
+
+	baud = tty_termios_baud_rate(&tty->termios);
+	tty_termios_encode_baud_rate(&tty->termios, baud, baud);
+
+	/* compute bit count of 2 frames */
+	frame = 12 + ((C_CSTOPB(tty)) ? 4 : 2) + ((C_PARENB(tty)) ? 2 : 0);
+
+	switch (C_CSIZE(tty)) {
+	case CS5:
+		frame -= (C_CSTOPB(tty)) ? 1 : 0;
+		break;
+	case CS6:
+		frame += 2;
+		break;
+	case CS7:
+		frame += 4;
+		break;
+	case CS8:
+		frame += 6;
+		break;
+	}
+
+	port->cps = (baud << 1) / frame;
+
+	port->status_mask = UART_LSR_OE;
+	if (_I_FLAG(tty, BRKINT | PARMRK))
+		port->status_mask |= UART_LSR_BI;
+
+	port->ignore_mask = 0;
+	if (I_IGNBRK(tty)) {
+		port->ignore_mask |= UART_LSR_BI;
+		if (I_IGNPAR(tty))
+			port->ignore_mask |= UART_LSR_OE;
+	}
+
+	port->write_only = !C_CREAD(tty);
+
+	/* turn off echo and newline xlat if loopback */
+	if (port->loopback) {
+		tty->termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHOKE |
+					  ECHONL | ECHOPRT | ECHOCTL);
+		tty->termios.c_oflag &= ~ONLCR;
+	}
+
+	return baud;
+}
+
+static int fwtty_port_activate(struct tty_port *tty_port,
+			       struct tty_struct *tty)
+{
+	struct fwtty_port *port = to_port(tty_port, port);
+	unsigned baud;
+	int err;
+
+	set_bit(TTY_IO_ERROR, &tty->flags);
+
+	err = dma_fifo_alloc(&port->tx_fifo, FWTTY_PORT_TXFIFO_LEN,
+			     cache_line_size(),
+			     port->max_payload,
+			     FWTTY_PORT_MAX_PEND_DMA,
+			     GFP_KERNEL);
+	if (err)
+		return err;
+
+	spin_lock_bh(&port->lock);
+
+	baud = set_termios(port, tty);
+
+	/* if console, don't change carrier state */
+	if (!port->port.console) {
+		port->mctrl = 0;
+		if (baud != 0)
+			port->mctrl = TIOCM_DTR | TIOCM_RTS;
+	}
+
+	if (C_CRTSCTS(tty) && ~port->mstatus & TIOCM_CTS)
+		tty->hw_stopped = 1;
+
+	__fwtty_write_port_status(port);
+	spin_unlock_bh(&port->lock);
+
+	clear_bit(TTY_IO_ERROR, &tty->flags);
+
+	return 0;
+}
+
+/**
+ * fwtty_port_shutdown
+ *
+ * Note: the tty port core ensures this is not the console and
+ * manages TTY_IO_ERROR properly
+ */
+static void fwtty_port_shutdown(struct tty_port *tty_port)
+{
+	struct fwtty_port *port = to_port(tty_port, port);
+	struct buffered_rx *buf, *next;
+
+	/* TODO: cancel outstanding transactions */
+
+	cancel_delayed_work_sync(&port->emit_breaks);
+	cancel_delayed_work_sync(&port->drain);
+	cancel_work_sync(&port->push);
+
+	spin_lock_bh(&port->lock);
+	list_for_each_entry_safe(buf, next, &port->buf_list, list) {
+		list_del(&buf->list);
+		kfree(buf);
+	}
+	port->buffered = 0;
+	port->flags = 0;
+	port->break_ctl = 0;
+	port->overrun = 0;
+	__fwtty_write_port_status(port);
+	dma_fifo_free(&port->tx_fifo);
+	spin_unlock_bh(&port->lock);
+}
+
+static int fwtty_open(struct tty_struct *tty, struct file *fp)
+{
+	struct fwtty_port *port = tty->driver_data;
+
+	return tty_port_open(&port->port, tty, fp);
+}
+
+static void fwtty_close(struct tty_struct *tty, struct file *fp)
+{
+	struct fwtty_port *port = tty->driver_data;
+
+	tty_port_close(&port->port, tty, fp);
+}
+
+static void fwtty_hangup(struct tty_struct *tty)
+{
+	struct fwtty_port *port = tty->driver_data;
+
+	tty_port_hangup(&port->port);
+}
+
+static void fwtty_cleanup(struct tty_struct *tty)
+{
+	struct fwtty_port *port = tty->driver_data;
+
+	tty->driver_data = NULL;
+	fwtty_port_put(port);
+}
+
+static int fwtty_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+	struct fwtty_port *port = fwtty_port_get(tty->index);
+	int err;
+
+	err = tty_standard_install(driver, tty);
+	if (!err)
+		tty->driver_data = port;
+	else
+		fwtty_port_put(port);
+	return err;
+}
+
+static int fwtty_write(struct tty_struct *tty, const unsigned char *buf, int c)
+{
+	struct fwtty_port *port = tty->driver_data;
+	int n, len;
+
+	fwtty_dbg(port, "%d", c);
+	profile_size_distrib(port->stats.writes, c);
+
+	spin_lock_bh(&port->lock);
+	n = dma_fifo_in(&port->tx_fifo, buf, c);
+	len = dma_fifo_out_level(&port->tx_fifo);
+	if (len < DRAIN_THRESHOLD)
+		schedule_delayed_work(&port->drain, 1);
+	spin_unlock_bh(&port->lock);
+
+	if (len >= DRAIN_THRESHOLD)
+		fwtty_tx(port, false);
+
+	debug_short_write(port, c, n);
+
+	return (n < 0) ? 0 : n;
+}
+
+static int fwtty_write_room(struct tty_struct *tty)
+{
+	struct fwtty_port *port = tty->driver_data;
+	int n;
+
+	spin_lock_bh(&port->lock);
+	n = dma_fifo_avail(&port->tx_fifo);
+	spin_unlock_bh(&port->lock);
+
+	fwtty_dbg(port, "%d", n);
+
+	return n;
+}
+
+static int fwtty_chars_in_buffer(struct tty_struct *tty)
+{
+	struct fwtty_port *port = tty->driver_data;
+	int n;
+
+	spin_lock_bh(&port->lock);
+	n = dma_fifo_level(&port->tx_fifo);
+	spin_unlock_bh(&port->lock);
+
+	fwtty_dbg(port, "%d", n);
+
+	return n;
+}
+
+static void fwtty_send_xchar(struct tty_struct *tty, char ch)
+{
+	struct fwtty_port *port = tty->driver_data;
+
+	fwtty_dbg(port, "%02x", ch);
+
+	fwtty_write_xchar(port, ch);
+}
+
+static void fwtty_throttle(struct tty_struct *tty)
+{
+	struct fwtty_port *port = tty->driver_data;
+
+	/*
+	 * Ignore throttling (but not unthrottling).
+	 * It only makes sense to throttle when data will no longer be
+	 * accepted by the tty flip buffer. For example, it is
+	 * possible for received data to overflow the tty buffer long
+	 * before the line discipline ever has a chance to throttle the driver.
+	 * Additionally, the driver may have already completed the I/O
+	 * but the tty buffer is still emptying, so the line discipline is
+	 * throttling and unthrottling nothing.
+	 */
+
+	++port->stats.throttled;
+}
+
+static void fwtty_unthrottle(struct tty_struct *tty)
+{
+	struct fwtty_port *port = tty->driver_data;
+
+	fwtty_dbg(port, "CRTSCTS: %d", (C_CRTSCTS(tty) != 0));
+
+	profile_fifo_avail(port, port->stats.unthrottle);
+
+	schedule_work(&port->push);
+
+	spin_lock_bh(&port->lock);
+	port->mctrl &= ~OOB_RX_THROTTLE;
+	if (C_CRTSCTS(tty))
+		port->mctrl |= TIOCM_RTS;
+	__fwtty_write_port_status(port);
+	spin_unlock_bh(&port->lock);
+}
+
+static int check_msr_delta(struct fwtty_port *port, unsigned long mask,
+			   struct async_icount *prev)
+{
+	struct async_icount now;
+	int delta;
+
+	now = port->icount;
+
+	delta = ((mask & TIOCM_RNG && prev->rng != now.rng) ||
+		 (mask & TIOCM_DSR && prev->dsr != now.dsr) ||
+		 (mask & TIOCM_CAR && prev->dcd != now.dcd) ||
+		 (mask & TIOCM_CTS && prev->cts != now.cts));
+
+	*prev = now;
+
+	return delta;
+}
+
+static int wait_msr_change(struct fwtty_port *port, unsigned long mask)
+{
+	struct async_icount prev;
+
+	prev = port->icount;
+
+	return wait_event_interruptible(port->port.delta_msr_wait,
+					check_msr_delta(port, mask, &prev));
+}
+
+static int get_serial_info(struct fwtty_port *port,
+			   struct serial_struct __user *info)
+{
+	struct serial_struct tmp;
+
+	memset(&tmp, 0, sizeof(tmp));
+
+	tmp.type =  PORT_UNKNOWN;
+	tmp.line =  port->port.tty->index;
+	tmp.flags = port->port.flags;
+	tmp.xmit_fifo_size = FWTTY_PORT_TXFIFO_LEN;
+	tmp.baud_base = 400000000;
+	tmp.close_delay = port->port.close_delay;
+
+	return (copy_to_user(info, &tmp, sizeof(*info))) ? -EFAULT : 0;
+}
+
+static int set_serial_info(struct fwtty_port *port,
+			   struct serial_struct __user *info)
+{
+	struct serial_struct tmp;
+
+	if (copy_from_user(&tmp, info, sizeof(tmp)))
+		return -EFAULT;
+
+	if (tmp.irq != 0 || tmp.port != 0 || tmp.custom_divisor != 0 ||
+			tmp.baud_base != 400000000)
+		return -EPERM;
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		if (((tmp.flags & ~ASYNC_USR_MASK) !=
+		     (port->port.flags & ~ASYNC_USR_MASK)))
+			return -EPERM;
+	} else
+		port->port.close_delay = tmp.close_delay * HZ / 100;
+
+	return 0;
+}
+
+static int fwtty_ioctl(struct tty_struct *tty, unsigned cmd,
+		       unsigned long arg)
+{
+	struct fwtty_port *port = tty->driver_data;
+	int err;
+
+	switch (cmd) {
+	case TIOCGSERIAL:
+		mutex_lock(&port->port.mutex);
+		err = get_serial_info(port, (void __user *)arg);
+		mutex_unlock(&port->port.mutex);
+		break;
+
+	case TIOCSSERIAL:
+		mutex_lock(&port->port.mutex);
+		err = set_serial_info(port, (void __user *)arg);
+		mutex_unlock(&port->port.mutex);
+		break;
+
+	case TIOCMIWAIT:
+		err = wait_msr_change(port, arg);
+		break;
+
+	default:
+		err = -ENOIOCTLCMD;
+	}
+
+	return err;
+}
+
+static void fwtty_set_termios(struct tty_struct *tty, struct ktermios *old)
+{
+	struct fwtty_port *port = tty->driver_data;
+	unsigned baud;
+
+	spin_lock_bh(&port->lock);
+	baud = set_termios(port, tty);
+
+	if ((baud == 0) && (old->c_cflag & CBAUD))
+		port->mctrl &= ~(TIOCM_DTR | TIOCM_RTS);
+	else if ((baud != 0) && !(old->c_cflag & CBAUD)) {
+		if (C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags))
+			port->mctrl |= TIOCM_DTR | TIOCM_RTS;
+		else
+			port->mctrl |= TIOCM_DTR;
+	}
+	__fwtty_write_port_status(port);
+	spin_unlock_bh(&port->lock);
+
+	if (old->c_cflag & CRTSCTS) {
+		if (!C_CRTSCTS(tty)) {
+			tty->hw_stopped = 0;
+			fwtty_restart_tx(port);
+		}
+	} else if (C_CRTSCTS(tty) && ~port->mstatus & TIOCM_CTS) {
+		tty->hw_stopped = 1;
+	}
+}
+
+/**
+ * fwtty_break_ctl - start/stop sending breaks
+ *
+ * Signals the remote to start or stop generating simulated breaks.
+ * First, stop dequeueing from the fifo and wait for writer/drain to leave tx
+ * before signalling the break line status. This guarantees any pending rx will
+ * be queued to the line discipline before break is simulated on the remote.
+ * Conversely, turning off break_ctl requires signalling the line status change,
+ * then enabling tx.
+ */
+static int fwtty_break_ctl(struct tty_struct *tty, int state)
+{
+	struct fwtty_port *port = tty->driver_data;
+	long ret;
+
+	fwtty_dbg(port, "%d", state);
+
+	if (state == -1) {
+		set_bit(STOP_TX, &port->flags);
+		ret = wait_event_interruptible_timeout(port->wait_tx,
+					       !test_bit(IN_TX, &port->flags),
+					       10);
+		if (ret == 0 || ret == -ERESTARTSYS) {
+			clear_bit(STOP_TX, &port->flags);
+			fwtty_restart_tx(port);
+			return -EINTR;
+		}
+	}
+
+	spin_lock_bh(&port->lock);
+	port->break_ctl = (state == -1);
+	__fwtty_write_port_status(port);
+	spin_unlock_bh(&port->lock);
+
+	if (state == 0) {
+		spin_lock_bh(&port->lock);
+		dma_fifo_reset(&port->tx_fifo);
+		clear_bit(STOP_TX, &port->flags);
+		spin_unlock_bh(&port->lock);
+	}
+	return 0;
+}
+
+static int fwtty_tiocmget(struct tty_struct *tty)
+{
+	struct fwtty_port *port = tty->driver_data;
+	unsigned tiocm;
+
+	spin_lock_bh(&port->lock);
+	tiocm = (port->mctrl & MCTRL_MASK) | (port->mstatus & ~MCTRL_MASK);
+	spin_unlock_bh(&port->lock);
+
+	fwtty_dbg(port, "%x", tiocm);
+
+	return tiocm;
+}
+
+static int fwtty_tiocmset(struct tty_struct *tty, unsigned set, unsigned clear)
+{
+	struct fwtty_port *port = tty->driver_data;
+
+	fwtty_dbg(port, "set: %x clear: %x", set, clear);
+
+	/* TODO: simulate loopback if TIOCM_LOOP set */
+
+	spin_lock_bh(&port->lock);
+	port->mctrl &= ~(clear & MCTRL_MASK & 0xffff);
+	port->mctrl |= set & MCTRL_MASK & 0xffff;
+	__fwtty_write_port_status(port);
+	spin_unlock_bh(&port->lock);
+	return 0;
+}
+
+static int fwtty_get_icount(struct tty_struct *tty,
+			    struct serial_icounter_struct *icount)
+{
+	struct fwtty_port *port = tty->driver_data;
+	struct stats stats;
+
+	memcpy(&stats, &port->stats, sizeof(stats));
+	if (port->port.console)
+		(*port->fwcon_ops->stats)(&stats, port->con_data);
+
+	icount->cts = port->icount.cts;
+	icount->dsr = port->icount.dsr;
+	icount->rng = port->icount.rng;
+	icount->dcd = port->icount.dcd;
+	icount->rx  = port->icount.rx;
+	icount->tx  = port->icount.tx + stats.xchars;
+	icount->frame   = port->icount.frame;
+	icount->overrun = port->icount.overrun;
+	icount->parity  = port->icount.parity;
+	icount->brk     = port->icount.brk;
+	icount->buf_overrun = port->icount.overrun;
+	return 0;
+}
+
+static void fwtty_proc_show_port(struct seq_file *m, struct fwtty_port *port)
+{
+	struct stats stats;
+
+	memcpy(&stats, &port->stats, sizeof(stats));
+	if (port->port.console)
+		(*port->fwcon_ops->stats)(&stats, port->con_data);
+
+	seq_printf(m, " tx:%d rx:%d", port->icount.tx + stats.xchars,
+		   port->icount.rx);
+	seq_printf(m, " cts:%d dsr:%d rng:%d dcd:%d", port->icount.cts,
+		   port->icount.dsr, port->icount.rng, port->icount.dcd);
+	seq_printf(m, " fe:%d oe:%d pe:%d brk:%d", port->icount.frame,
+		   port->icount.overrun, port->icount.parity, port->icount.brk);
+	seq_printf(m, " dr:%d st:%d err:%d lost:%d", stats.dropped,
+		   stats.tx_stall, stats.fifo_errs, stats.lost);
+	seq_printf(m, " pkts:%d thr:%d wtrmk:%d", stats.sent, stats.throttled,
+		   stats.watermark);
+	seq_printf(m, " addr:%012llx", port->rx_handler.offset);
+
+	if (port->port.console) {
+		seq_printf(m, "\n    ");
+		(*port->fwcon_ops->proc_show)(m, port->con_data);
+	}
+
+	dump_profile(m, &port->stats);
+}
+
+static void fwtty_proc_show_peer(struct seq_file *m, struct fwtty_peer *peer)
+{
+	int generation = peer->generation;
+
+	smp_rmb();
+	seq_printf(m, " %s:", dev_name(&peer->unit->device));
+	seq_printf(m, " node:%04x gen:%d", peer->node_id, generation);
+	seq_printf(m, " sp:%d max:%d guid:%016llx", peer->speed,
+		   peer->max_payload, (unsigned long long) peer->guid);
+
+	if (capable(CAP_SYS_ADMIN)) {
+		seq_printf(m, " mgmt:%012llx",
+			   (unsigned long long) peer->mgmt_addr);
+		seq_printf(m, " addr:%012llx",
+			   (unsigned long long) peer->status_addr);
+	}
+	seq_putc(m, '\n');
+}
+
+static int fwtty_proc_show(struct seq_file *m, void *v)
+{
+	struct fwtty_port *port;
+	struct fw_serial *serial;
+	struct fwtty_peer *peer;
+	int i;
+
+	seq_puts(m, "fwserinfo: 1.0 driver: 1.0\n");
+	for (i = 0; i < MAX_TOTAL_PORTS && (port = fwtty_port_get(i)); ++i) {
+		seq_printf(m, "%2d:", i);
+		if (capable(CAP_SYS_ADMIN))
+			fwtty_proc_show_port(m, port);
+		fwtty_port_put(port);
+		seq_printf(m, "\n");
+	}
+	seq_putc(m, '\n');
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(serial, &fwserial_list, list) {
+		seq_printf(m, "card: %s  guid: %016llx\n",
+			   dev_name(serial->card->device),
+			   (unsigned long long) serial->card->guid);
+		list_for_each_entry_rcu(peer, &serial->peer_list, list)
+			fwtty_proc_show_peer(m, peer);
+	}
+	rcu_read_unlock();
+	return 0;
+}
+
+static int fwtty_proc_open(struct inode *inode, struct file *fp)
+{
+	return single_open(fp, fwtty_proc_show, NULL);
+}
+
+static const struct file_operations fwtty_proc_fops = {
+	.owner =        THIS_MODULE,
+	.open =         fwtty_proc_open,
+	.read =         seq_read,
+	.llseek =       seq_lseek,
+	.release =      single_release,
+};
+
+static const struct tty_port_operations fwtty_port_ops = {
+	.dtr_rts =		fwtty_port_dtr_rts,
+	.carrier_raised =	fwtty_port_carrier_raised,
+	.shutdown =		fwtty_port_shutdown,
+	.activate =		fwtty_port_activate,
+};
+
+static const struct tty_operations fwtty_ops = {
+	.open =			fwtty_open,
+	.close =		fwtty_close,
+	.hangup =		fwtty_hangup,
+	.cleanup =		fwtty_cleanup,
+	.install =		fwtty_install,
+	.write =		fwtty_write,
+	.write_room =		fwtty_write_room,
+	.chars_in_buffer =	fwtty_chars_in_buffer,
+	.send_xchar =           fwtty_send_xchar,
+	.throttle =             fwtty_throttle,
+	.unthrottle =           fwtty_unthrottle,
+	.ioctl =		fwtty_ioctl,
+	.set_termios =		fwtty_set_termios,
+	.break_ctl =		fwtty_break_ctl,
+	.tiocmget =		fwtty_tiocmget,
+	.tiocmset =		fwtty_tiocmset,
+	.get_icount =		fwtty_get_icount,
+	.proc_fops =		&fwtty_proc_fops,
+};
+
+static inline int mgmt_pkt_expected_len(__be16 code)
+{
+	static const struct fwserial_mgmt_pkt pkt;
+
+	switch (be16_to_cpu(code)) {
+	case FWSC_VIRT_CABLE_PLUG:
+		return sizeof(pkt.hdr) + sizeof(pkt.plug_req);
+
+	case FWSC_VIRT_CABLE_PLUG_RSP:  /* | FWSC_RSP_OK */
+		return sizeof(pkt.hdr) + sizeof(pkt.plug_rsp);
+
+
+	case FWSC_VIRT_CABLE_UNPLUG:
+	case FWSC_VIRT_CABLE_UNPLUG_RSP:
+	case FWSC_VIRT_CABLE_PLUG_RSP | FWSC_RSP_NACK:
+	case FWSC_VIRT_CABLE_UNPLUG_RSP | FWSC_RSP_NACK:
+		return sizeof(pkt.hdr);
+
+	default:
+		return -1;
+	}
+}
+
+static inline void fill_plug_params(struct virt_plug_params *params,
+				    struct fwtty_port *port)
+{
+	u64 status_addr = port->rx_handler.offset;
+	u64 fifo_addr = port->rx_handler.offset + 4;
+	size_t fifo_len = port->rx_handler.length - 4;
+
+	params->status_hi = cpu_to_be32(status_addr >> 32);
+	params->status_lo = cpu_to_be32(status_addr);
+	params->fifo_hi = cpu_to_be32(fifo_addr >> 32);
+	params->fifo_lo = cpu_to_be32(fifo_addr);
+	params->fifo_len = cpu_to_be32(fifo_len);
+}
+
+static inline void fill_plug_req(struct fwserial_mgmt_pkt *pkt,
+				 struct fwtty_port *port)
+{
+	pkt->hdr.code = cpu_to_be16(FWSC_VIRT_CABLE_PLUG);
+	pkt->hdr.len = cpu_to_be16(mgmt_pkt_expected_len(pkt->hdr.code));
+	fill_plug_params(&pkt->plug_req, port);
+}
+
+static inline void fill_plug_rsp_ok(struct fwserial_mgmt_pkt *pkt,
+				    struct fwtty_port *port)
+{
+	pkt->hdr.code = cpu_to_be16(FWSC_VIRT_CABLE_PLUG_RSP);
+	pkt->hdr.len = cpu_to_be16(mgmt_pkt_expected_len(pkt->hdr.code));
+	fill_plug_params(&pkt->plug_rsp, port);
+}
+
+static inline void fill_plug_rsp_nack(struct fwserial_mgmt_pkt *pkt)
+{
+	pkt->hdr.code = cpu_to_be16(FWSC_VIRT_CABLE_PLUG_RSP | FWSC_RSP_NACK);
+	pkt->hdr.len = cpu_to_be16(mgmt_pkt_expected_len(pkt->hdr.code));
+}
+
+static inline void fill_unplug_req(struct fwserial_mgmt_pkt *pkt)
+{
+	pkt->hdr.code = cpu_to_be16(FWSC_VIRT_CABLE_UNPLUG);
+	pkt->hdr.len = cpu_to_be16(mgmt_pkt_expected_len(pkt->hdr.code));
+}
+
+static inline void fill_unplug_rsp_nack(struct fwserial_mgmt_pkt *pkt)
+{
+	pkt->hdr.code = cpu_to_be16(FWSC_VIRT_CABLE_UNPLUG_RSP | FWSC_RSP_NACK);
+	pkt->hdr.len = cpu_to_be16(mgmt_pkt_expected_len(pkt->hdr.code));
+}
+
+static inline void fill_unplug_rsp_ok(struct fwserial_mgmt_pkt *pkt)
+{
+	pkt->hdr.code = cpu_to_be16(FWSC_VIRT_CABLE_UNPLUG_RSP);
+	pkt->hdr.len = cpu_to_be16(mgmt_pkt_expected_len(pkt->hdr.code));
+}
+
+static void fwserial_virt_plug_complete(struct fwtty_peer *peer,
+					struct virt_plug_params *params)
+{
+	struct fwtty_port *port = peer->port;
+
+	peer->status_addr = be32_to_u64(params->status_hi, params->status_lo);
+	peer->fifo_addr = be32_to_u64(params->fifo_hi, params->fifo_lo);
+	peer->fifo_len = be32_to_cpu(params->fifo_len);
+	peer_set_state(peer, FWPS_ATTACHED);
+
+	/* reconfigure tx_fifo optimally for this peer */
+	spin_lock_bh(&port->lock);
+	port->max_payload = min3(peer->max_payload, peer->fifo_len,
+				 MAX_ASYNC_PAYLOAD);
+	dma_fifo_change_tx_limit(&port->tx_fifo, port->max_payload);
+	spin_unlock_bh(&peer->port->lock);
+
+	if (port->port.console && port->fwcon_ops->notify != NULL)
+		(*port->fwcon_ops->notify)(FWCON_NOTIFY_ATTACH, port->con_data);
+
+	fwtty_info(&peer->unit, "peer (guid:%016llx) connected on %s",
+		   (unsigned long long)peer->guid, dev_name(port->device));
+}
+
+static inline int fwserial_send_mgmt_sync(struct fwtty_peer *peer,
+					  struct fwserial_mgmt_pkt *pkt)
+{
+	int generation;
+	int rcode, tries = 5;
+
+	do {
+		generation = peer->generation;
+		smp_rmb();
+
+		rcode = fw_run_transaction(peer->serial->card,
+					   TCODE_WRITE_BLOCK_REQUEST,
+					   peer->node_id,
+					   generation, peer->speed,
+					   peer->mgmt_addr,
+					   pkt, be16_to_cpu(pkt->hdr.len));
+		if (rcode == RCODE_BUSY || rcode == RCODE_SEND_ERROR ||
+		    rcode == RCODE_GENERATION) {
+			fwtty_dbg(&peer->unit, "mgmt write error: %d", rcode);
+			continue;
+		} else
+			break;
+	} while (--tries > 0);
+	return rcode;
+}
+
+/**
+ * fwserial_claim_port - attempt to claim port @ index for peer
+ *
+ * Returns ptr to claimed port or error code (as ERR_PTR())
+ * Can sleep - must be called from process context
+ */
+static struct fwtty_port *fwserial_claim_port(struct fwtty_peer *peer,
+					      int index)
+{
+	struct fwtty_port *port;
+
+	if (index < 0 || index >= num_ports)
+		return ERR_PTR(-EINVAL);
+
+	/* must guarantee that previous port releases have completed */
+	synchronize_rcu();
+
+	port = peer->serial->ports[index];
+	spin_lock_bh(&port->lock);
+	if (!rcu_access_pointer(port->peer))
+		rcu_assign_pointer(port->peer, peer);
+	else
+		port = ERR_PTR(-EBUSY);
+	spin_unlock_bh(&port->lock);
+
+	return port;
+}
+
+/**
+ * fwserial_find_port - find avail port and claim for peer
+ *
+ * Returns ptr to claimed port or NULL if none avail
+ * Can sleep - must be called from process context
+ */
+static struct fwtty_port *fwserial_find_port(struct fwtty_peer *peer)
+{
+	struct fwtty_port **ports = peer->serial->ports;
+	int i;
+
+	/* must guarantee that previous port releases have completed */
+	synchronize_rcu();
+
+	/* TODO: implement optional GUID-to-specific port # matching */
+
+	/* find an unattached port (but not the loopback port, if present) */
+	for (i = 0; i < num_ttys; ++i) {
+		spin_lock_bh(&ports[i]->lock);
+		if (!ports[i]->peer) {
+			/* claim port */
+			rcu_assign_pointer(ports[i]->peer, peer);
+			spin_unlock_bh(&ports[i]->lock);
+			return ports[i];
+		}
+		spin_unlock_bh(&ports[i]->lock);
+	}
+	return NULL;
+}
+
+static void fwserial_release_port(struct fwtty_port *port)
+{
+	/* drop carrier (and all other line status) */
+	fwtty_update_port_status(port, 0);
+
+	spin_lock_bh(&port->lock);
+
+	/* reset dma fifo max transmission size back to S100 */
+	port->max_payload = link_speed_to_max_payload(SCODE_100);
+	dma_fifo_change_tx_limit(&port->tx_fifo, port->max_payload);
+
+	rcu_assign_pointer(port->peer, NULL);
+	spin_unlock_bh(&port->lock);
+
+	if (port->port.console && port->fwcon_ops->notify != NULL)
+		(*port->fwcon_ops->notify)(FWCON_NOTIFY_DETACH, port->con_data);
+}
+
+static void fwserial_plug_timeout(unsigned long data)
+{
+	struct fwtty_peer *peer = (struct fwtty_peer *) data;
+	struct fwtty_port *port;
+
+	spin_lock_bh(&peer->lock);
+	if (peer->state != FWPS_PLUG_PENDING) {
+		spin_unlock_bh(&peer->lock);
+		return;
+	}
+
+	port = peer_revert_state(peer);
+	spin_unlock_bh(&peer->lock);
+
+	if (port)
+		fwserial_release_port(port);
+}
+
+/**
+ * fwserial_connect_peer - initiate virtual cable with peer
+ *
+ * Returns 0 if VIRT_CABLE_PLUG request was successfully sent,
+ * otherwise error code.  Must be called from process context.
+ */
+static int fwserial_connect_peer(struct fwtty_peer *peer)
+{
+	struct fwtty_port *port;
+	struct fwserial_mgmt_pkt *pkt;
+	int err, rcode;
+
+	pkt = kmalloc(sizeof(*pkt), GFP_KERNEL);
+	if (!pkt)
+		return -ENOMEM;
+
+	port = fwserial_find_port(peer);
+	if (!port) {
+		fwtty_err(&peer->unit, "avail ports in use");
+		err = -EBUSY;
+		goto free_pkt;
+	}
+
+	spin_lock_bh(&peer->lock);
+
+	/* only initiate VIRT_CABLE_PLUG if peer is currently not attached */
+	if (peer->state != FWPS_NOT_ATTACHED) {
+		err = -EBUSY;
+		goto release_port;
+	}
+
+	peer->port = port;
+	peer_set_state(peer, FWPS_PLUG_PENDING);
+
+	fill_plug_req(pkt, peer->port);
+
+	setup_timer(&peer->timer, fwserial_plug_timeout, (unsigned long)peer);
+	mod_timer(&peer->timer, jiffies + VIRT_CABLE_PLUG_TIMEOUT);
+	spin_unlock_bh(&peer->lock);
+
+	rcode = fwserial_send_mgmt_sync(peer, pkt);
+
+	spin_lock_bh(&peer->lock);
+	if (peer->state == FWPS_PLUG_PENDING && rcode != RCODE_COMPLETE) {
+		if (rcode == RCODE_CONFLICT_ERROR)
+			err = -EAGAIN;
+		else
+			err = -EIO;
+		goto cancel_timer;
+	}
+	spin_unlock_bh(&peer->lock);
+
+	kfree(pkt);
+	return 0;
+
+cancel_timer:
+	del_timer(&peer->timer);
+	peer_revert_state(peer);
+release_port:
+	spin_unlock_bh(&peer->lock);
+	fwserial_release_port(port);
+free_pkt:
+	kfree(pkt);
+	return err;
+}
+
+/**
+ * fwserial_close_port -
+ * HUP the tty (if the tty exists) and unregister the tty device.
+ * Only used by the unit driver upon unit removal to disconnect and
+ * cleanup all attached ports
+ *
+ * The port reference is put by fwtty_cleanup (if a reference was
+ * ever taken).
+ */
+static void fwserial_close_port(struct fwtty_port *port)
+{
+	struct tty_struct *tty;
+
+	mutex_lock(&port->port.mutex);
+	tty = tty_port_tty_get(&port->port);
+	if (tty) {
+		tty_vhangup(tty);
+		tty_kref_put(tty);
+	}
+	mutex_unlock(&port->port.mutex);
+
+	tty_unregister_device(fwtty_driver, port->index);
+}
+
+/**
+ * fwserial_lookup - finds first fw_serial associated with card
+ * @card: fw_card to match
+ *
+ * NB: caller must be holding fwserial_list_mutex
+ */
+static struct fw_serial *fwserial_lookup(struct fw_card *card)
+{
+	struct fw_serial *serial;
+
+	list_for_each_entry(serial, &fwserial_list, list) {
+		if (card == serial->card)
+			return serial;
+	}
+
+	return NULL;
+}
+
+/**
+ * __fwserial_lookup_rcu - finds first fw_serial associated with card
+ * @card: fw_card to match
+ *
+ * NB: caller must be inside rcu_read_lock() section
+ */
+static struct fw_serial *__fwserial_lookup_rcu(struct fw_card *card)
+{
+	struct fw_serial *serial;
+
+	list_for_each_entry_rcu(serial, &fwserial_list, list) {
+		if (card == serial->card)
+			return serial;
+	}
+
+	return NULL;
+}
+
+/**
+ * __fwserial_peer_by_node_id - finds a peer matching the given generation + id
+ *
+ * If a matching peer could not be found for the specified generation/node id,
+ * this could be because:
+ * a) the generation has changed and one of the nodes hasn't updated yet
+ * b) the remote node has created its remote unit device before this
+ *    local node has created its corresponding remote unit device
+ * In either case, the remote node should retry
+ *
+ * Note: caller must be in rcu_read_lock() section
+ */
+static struct fwtty_peer *__fwserial_peer_by_node_id(struct fw_card *card,
+						     int generation, int id)
+{
+	struct fw_serial *serial;
+	struct fwtty_peer *peer;
+
+	serial = __fwserial_lookup_rcu(card);
+	if (!serial) {
+		/*
+		 * Something is very wrong - there should be a matching
+		 * fw_serial structure for every fw_card. Maybe the remote node
+		 * has created its remote unit device before this driver has
+		 * been probed for any unit devices...
+		 */
+		fwtty_err(card, "unknown card (guid %016llx)",
+			  (unsigned long long) card->guid);
+		return NULL;
+	}
+
+	list_for_each_entry_rcu(peer, &serial->peer_list, list) {
+		int g = peer->generation;
+		smp_rmb();
+		if (generation == g && id == peer->node_id)
+			return peer;
+	}
+
+	return NULL;
+}
+
+#ifdef DEBUG
+static void __dump_peer_list(struct fw_card *card)
+{
+	struct fw_serial *serial;
+	struct fwtty_peer *peer;
+
+	serial = __fwserial_lookup_rcu(card);
+	if (!serial)
+		return;
+
+	list_for_each_entry_rcu(peer, &serial->peer_list, list) {
+		int g = peer->generation;
+		smp_rmb();
+		fwtty_dbg(card, "peer(%d:%x) guid: %016llx\n", g,
+			  peer->node_id, (unsigned long long) peer->guid);
+	}
+}
+#else
+#define __dump_peer_list(s)
+#endif
+
+static void fwserial_auto_connect(struct work_struct *work)
+{
+	struct fwtty_peer *peer = to_peer(to_delayed_work(work), connect);
+	int err;
+
+	err = fwserial_connect_peer(peer);
+	if (err == -EAGAIN && ++peer->connect_retries < MAX_CONNECT_RETRIES)
+		schedule_delayed_work(&peer->connect, CONNECT_RETRY_DELAY);
+}
+
+/**
+ * fwserial_add_peer - add a newly probed 'serial' unit device as a 'peer'
+ * @serial: aggregate representing the specific fw_card to add the peer to
+ * @unit: 'peer' to create and add to peer_list of serial
+ *
+ * Adds a 'peer' (ie, a local or remote 'serial' unit device) to the list of
+ * peers for a specific fw_card. Optionally, auto-attach this peer to an
+ * available tty port. This function is called either directly or indirectly
+ * as a result of a 'serial' unit device being created & probed.
+ *
+ * Note: this function is serialized with fwserial_remove_peer() by the
+ * fwserial_list_mutex held in fwserial_probe().
+ *
+ * A 1:1 correspondence between an fw_unit and an fwtty_peer is maintained
+ * via the dev_set_drvdata() for the device of the fw_unit.
+ */
+static int fwserial_add_peer(struct fw_serial *serial, struct fw_unit *unit)
+{
+	struct device *dev = &unit->device;
+	struct fw_device  *parent = fw_parent_device(unit);
+	struct fwtty_peer *peer;
+	struct fw_csr_iterator ci;
+	int key, val;
+	int generation;
+
+	peer = kzalloc(sizeof(*peer), GFP_KERNEL);
+	if (!peer)
+		return -ENOMEM;
+
+	peer_set_state(peer, FWPS_NOT_ATTACHED);
+
+	dev_set_drvdata(dev, peer);
+	peer->unit = unit;
+	peer->guid = (u64)parent->config_rom[3] << 32 | parent->config_rom[4];
+	peer->speed = parent->max_speed;
+	peer->max_payload = min(device_max_receive(parent),
+				link_speed_to_max_payload(peer->speed));
+
+	generation = parent->generation;
+	smp_rmb();
+	peer->node_id = parent->node_id;
+	smp_wmb();
+	peer->generation = generation;
+
+	/* retrieve the mgmt bus addr from the unit directory */
+	fw_csr_iterator_init(&ci, unit->directory);
+	while (fw_csr_iterator_next(&ci, &key, &val)) {
+		if (key == (CSR_OFFSET | CSR_DEPENDENT_INFO)) {
+			peer->mgmt_addr = CSR_REGISTER_BASE + 4 * val;
+			break;
+		}
+	}
+	if (peer->mgmt_addr == 0ULL) {
+		/*
+		 * No mgmt address effectively disables VIRT_CABLE_PLUG -
+		 * this peer will not be able to attach to a remote
+		 */
+		peer_set_state(peer, FWPS_NO_MGMT_ADDR);
+	}
+
+	spin_lock_init(&peer->lock);
+	peer->port = NULL;
+
+	init_timer(&peer->timer);
+	INIT_WORK(&peer->work, NULL);
+	INIT_DELAYED_WORK(&peer->connect, fwserial_auto_connect);
+
+	/* associate peer with specific fw_card */
+	peer->serial = serial;
+	list_add_rcu(&peer->list, &serial->peer_list);
+
+	fwtty_info(&peer->unit, "peer added (guid:%016llx)",
+		   (unsigned long long)peer->guid);
+
+	/* identify the local unit & virt cable to loopback port */
+	if (parent->is_local) {
+		serial->self = peer;
+		if (create_loop_dev) {
+			struct fwtty_port *port;
+			port = fwserial_claim_port(peer, num_ttys);
+			if (!IS_ERR(port)) {
+				struct virt_plug_params params;
+
+				spin_lock_bh(&peer->lock);
+				peer->port = port;
+				fill_plug_params(&params, port);
+				fwserial_virt_plug_complete(peer, &params);
+				spin_unlock_bh(&peer->lock);
+
+				fwtty_write_port_status(port);
+			}
+		}
+
+	} else if (auto_connect) {
+		/* auto-attach to remote units only (if policy allows) */
+		schedule_delayed_work(&peer->connect, 1);
+	}
+
+	return 0;
+}
+
+/**
+ * fwserial_remove_peer - remove a 'serial' unit device as a 'peer'
+ *
+ * Remove a 'peer' from its list of peers. This function is only
+ * called by fwserial_remove() on bus removal of the unit device.
+ *
+ * Note: this function is serialized with fwserial_add_peer() by the
+ * fwserial_list_mutex held in fwserial_remove().
+ */
+static void fwserial_remove_peer(struct fwtty_peer *peer)
+{
+	struct fwtty_port *port;
+
+	spin_lock_bh(&peer->lock);
+	peer_set_state(peer, FWPS_GONE);
+	spin_unlock_bh(&peer->lock);
+
+	cancel_delayed_work_sync(&peer->connect);
+	cancel_work_sync(&peer->work);
+
+	spin_lock_bh(&peer->lock);
+	/* if this unit is the local unit, clear link */
+	if (peer == peer->serial->self)
+		peer->serial->self = NULL;
+
+	/* cancel the request timeout timer (if running) */
+	del_timer(&peer->timer);
+
+	port = peer->port;
+	peer->port = NULL;
+
+	list_del_rcu(&peer->list);
+
+	fwtty_info(&peer->unit, "peer removed (guid:%016llx)",
+		   (unsigned long long)peer->guid);
+
+	spin_unlock_bh(&peer->lock);
+
+	if (port)
+		fwserial_release_port(port);
+
+	synchronize_rcu();
+	kfree(peer);
+}
+
+/**
+ * create_loop_device - create a loopback tty device
+ * @tty_driver: tty_driver to own loopback device
+ * @prototype: ptr to already-assigned 'prototype' tty port
+ * @index: index to associate this device with the tty port
+ * @parent: device to child to
+ *
+ * HACK - this is basically tty_port_register_device() with an
+ * alternate naming scheme. Suggest tty_port_register_named_device()
+ * helper api.
+ *
+ * Creates a loopback tty device named 'fwloop<n>' which is attached to
+ * the local unit in fwserial_add_peer(). Note that <n> in the device
+ * name advances in increments of port allocation blocks, ie., for port
+ * indices 0..3, the device name will be 'fwloop0'; for 4..7, 'fwloop1',
+ * and so on.
+ *
+ * Only one loopback device should be created per fw_card.
+ */
+static void release_loop_device(struct device *dev)
+{
+	kfree(dev);
+}
+
+static struct device *create_loop_device(struct tty_driver *driver,
+					 struct fwtty_port *prototype,
+					 struct fwtty_port *port,
+					 struct device *parent)
+{
+	char name[64];
+	int index = port->index;
+	dev_t devt = MKDEV(driver->major, driver->minor_start) + index;
+	struct device *dev = NULL;
+	int err;
+
+	if (index >= fwtty_driver->num)
+		return ERR_PTR(-EINVAL);
+
+	snprintf(name, 64, "%s%d", loop_dev_name, index / num_ports);
+
+	tty_port_link_device(&port->port, driver, index);
+
+	cdev_init(&driver->cdevs[index], driver->cdevs[prototype->index].ops);
+	driver->cdevs[index].owner = driver->owner;
+	err = cdev_add(&driver->cdevs[index], devt, 1);
+	if (err)
+		return ERR_PTR(err);
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		cdev_del(&driver->cdevs[index]);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	dev->devt = devt;
+	dev->class = prototype->device->class;
+	dev->parent = parent;
+	dev->release = release_loop_device;
+	dev_set_name(dev, "%s", name);
+	dev->groups = NULL;
+	dev_set_drvdata(dev, NULL);
+
+	err = device_register(dev);
+	if (err) {
+		put_device(dev);
+		cdev_del(&driver->cdevs[index]);
+		return ERR_PTR(err);
+	}
+
+	return dev;
+}
+
+/**
+ * fwserial_create - init everything to create TTYs for a specific fw_card
+ * @unit: fw_unit for first 'serial' unit device probed for this fw_card
+ *
+ * This function inits the aggregate structure (an fw_serial instance)
+ * used to manage the TTY ports registered by a specific fw_card. Also, the
+ * unit device is added as the first 'peer'.
+ *
+ * This unit device may represent a local unit device (as specified by the
+ * config ROM unit directory) or it may represent a remote unit device
+ * (as specified by the reading of the remote node's config ROM).
+ *
+ * Returns 0 to indicate "ownership" of the unit device, or a negative errno
+ * value to indicate which error.
+ */
+static int fwserial_create(struct fw_unit *unit)
+{
+	struct fw_device *parent = fw_parent_device(unit);
+	struct fw_card *card = parent->card;
+	struct fw_serial *serial;
+	struct fwtty_port *port;
+	struct device *tty_dev;
+	int i, j;
+	int err;
+
+	serial = kzalloc(sizeof(*serial), GFP_KERNEL);
+	if (!serial)
+		return -ENOMEM;
+
+	kref_init(&serial->kref);
+	serial->card = card;
+	INIT_LIST_HEAD(&serial->peer_list);
+
+	for (i = 0; i < num_ports; ++i) {
+		port = kzalloc(sizeof(*port), GFP_KERNEL);
+		if (!port) {
+			err = -ENOMEM;
+			goto free_ports;
+		}
+		tty_port_init(&port->port);
+		port->index = FWTTY_INVALID_INDEX;
+		port->port.ops = &fwtty_port_ops;
+		port->serial = serial;
+
+		spin_lock_init(&port->lock);
+		INIT_DELAYED_WORK(&port->drain, fwtty_drain_tx);
+		INIT_DELAYED_WORK(&port->emit_breaks, fwtty_emit_breaks);
+		INIT_WORK(&port->hangup, fwtty_do_hangup);
+		INIT_WORK(&port->push, fwtty_pushrx);
+		INIT_LIST_HEAD(&port->buf_list);
+		init_waitqueue_head(&port->wait_tx);
+		port->max_payload = link_speed_to_max_payload(SCODE_100);
+		dma_fifo_init(&port->tx_fifo);
+
+		rcu_assign_pointer(port->peer, NULL);
+		serial->ports[i] = port;
+
+		/* get unique bus addr region for port's status & recv fifo */
+		port->rx_handler.length = FWTTY_PORT_RXFIFO_LEN + 4;
+		port->rx_handler.address_callback = fwtty_port_handler;
+		port->rx_handler.callback_data = port;
+		/*
+		 * XXX: use custom memory region above cpu physical memory addrs
+		 * this will ease porting to 64-bit firewire adapters
+		 */
+		err = fw_core_add_address_handler(&port->rx_handler,
+						  &fw_high_memory_region);
+		if (err) {
+			kfree(port);
+			goto free_ports;
+		}
+	}
+	/* preserve i for error cleanup */
+
+	err = fwtty_ports_add(serial);
+	if (err) {
+		fwtty_err(&unit, "no space in port table");
+		goto free_ports;
+	}
+
+	for (j = 0; j < num_ttys; ++j) {
+		tty_dev = tty_port_register_device(&serial->ports[j]->port,
+						   fwtty_driver,
+						   serial->ports[j]->index,
+						   card->device);
+		if (IS_ERR(tty_dev)) {
+			err = PTR_ERR(tty_dev);
+			fwtty_err(&unit, "register tty device error (%d)", err);
+			goto unregister_ttys;
+		}
+
+		serial->ports[j]->device = tty_dev;
+	}
+	/* preserve j for error cleanup */
+
+	if (create_loop_dev) {
+		struct device *loop_dev;
+
+		loop_dev = create_loop_device(fwtty_driver,
+					      serial->ports[0],
+					      serial->ports[num_ttys],
+					      card->device);
+		if (IS_ERR(loop_dev)) {
+			err = PTR_ERR(loop_dev);
+			fwtty_err(&unit, "create loop device failed (%d)", err);
+			goto unregister_ttys;
+		}
+		serial->ports[num_ttys]->device = loop_dev;
+		serial->ports[num_ttys]->loopback = true;
+	}
+
+	list_add_rcu(&serial->list, &fwserial_list);
+
+	fwtty_notice(&unit, "TTY over FireWire on device %s (guid %016llx)",
+		     dev_name(card->device), (unsigned long long) card->guid);
+
+	err = fwserial_add_peer(serial, unit);
+	if (!err)
+		return 0;
+
+	fwtty_err(&unit, "unable to add peer unit device (%d)", err);
+
+	/* fall-through to error processing */
+	list_del_rcu(&serial->list);
+unregister_ttys:
+	for (--j; j >= 0; --j)
+		tty_unregister_device(fwtty_driver, serial->ports[j]->index);
+	kref_put(&serial->kref, fwserial_destroy);
+	return err;
+
+free_ports:
+	for (--i; i >= 0; --i) {
+		tty_port_destroy(&serial->ports[i]->port);
+		kfree(serial->ports[i]);
+	}
+	kfree(serial);
+	return err;
+}
+
+/**
+ * fwserial_probe: bus probe function for firewire 'serial' unit devices
+ *
+ * A 'serial' unit device is created and probed as a result of:
+ * - declaring a ieee1394 bus id table for 'devices' matching a fabricated
+ *   'serial' unit specifier id
+ * - adding a unit directory to the config ROM(s) for a 'serial' unit
+ *
+ * The firewire core registers unit devices by enumerating unit directories
+ * of a node's config ROM after reading the config ROM when a new node is
+ * added to the bus topology after a bus reset.
+ *
+ * The practical implications of this are:
+ * - this probe is called for both local and remote nodes that have a 'serial'
+ *   unit directory in their config ROM (that matches the specifiers in
+ *   fwserial_id_table).
+ * - no specific order is enforced for local vs. remote unit devices
+ *
+ * This unit driver copes with the lack of specific order in the same way the
+ * firewire net driver does -- each probe, for either a local or remote unit
+ * device, is treated as a 'peer' (has a struct fwtty_peer instance) and the
+ * first peer created for a given fw_card (tracked by the global fwserial_list)
+ * creates the underlying TTYs (aggregated in a fw_serial instance).
+ *
+ * NB: an early attempt to differentiate local & remote unit devices by creating
+ *     peers only for remote units and fw_serial instances (with their
+ *     associated TTY devices) only for local units was discarded. Managing
+ *     the peer lifetimes on device removal proved too complicated.
+ *
+ * fwserial_probe/fwserial_remove are effectively serialized by the
+ * fwserial_list_mutex. This is necessary because the addition of the first peer
+ * for a given fw_card will trigger the creation of the fw_serial for that
+ * fw_card, which must not simultaneously contend with the removal of the
+ * last peer for a given fw_card triggering the destruction of the same
+ * fw_serial for the same fw_card.
+ */
+static int fwserial_probe(struct device *dev)
+{
+	struct fw_unit *unit = fw_unit(dev);
+	struct fw_serial *serial;
+	int err;
+
+	mutex_lock(&fwserial_list_mutex);
+	serial = fwserial_lookup(fw_parent_device(unit)->card);
+	if (!serial)
+		err = fwserial_create(unit);
+	else
+		err = fwserial_add_peer(serial, unit);
+	mutex_unlock(&fwserial_list_mutex);
+	return err;
+}
+
+/**
+ * fwserial_remove: bus removal function for firewire 'serial' unit devices
+ *
+ * The corresponding 'peer' for this unit device is removed from the list of
+ * peers for the associated fw_serial (which has a 1:1 correspondence with a
+ * specific fw_card). If this is the last peer being removed, then trigger
+ * the destruction of the underlying TTYs.
+ */
+static int fwserial_remove(struct device *dev)
+{
+	struct fwtty_peer *peer = dev_get_drvdata(dev);
+	struct fw_serial *serial = peer->serial;
+	int i;
+
+	mutex_lock(&fwserial_list_mutex);
+	fwserial_remove_peer(peer);
+
+	if (list_empty(&serial->peer_list)) {
+		/* unlink from the fwserial_list here */
+		list_del_rcu(&serial->list);
+
+		for (i = 0; i < num_ports; ++i)
+			fwserial_close_port(serial->ports[i]);
+		kref_put(&serial->kref, fwserial_destroy);
+	}
+	mutex_unlock(&fwserial_list_mutex);
+
+	return 0;
+}
+
+/**
+ * fwserial_update: bus update function for 'firewire' serial unit devices
+ *
+ * Updates the new node_id and bus generation for this peer. Note that locking
+ * is unnecessary; but careful memory barrier usage is important to enforce the
+ * load and store order of generation & node_id.
+ *
+ * The fw-core orders the write of node_id before generation in the parent
+ * fw_device to ensure that a stale node_id cannot be used with a current
+ * bus generation. So the generation value must be read before the node_id.
+ *
+ * In turn, this orders the write of node_id before generation in the peer to
+ * also ensure a stale node_id cannot be used with a current bus generation.
+ */
+static void fwserial_update(struct fw_unit *unit)
+{
+	struct fw_device *parent = fw_parent_device(unit);
+	struct fwtty_peer *peer = dev_get_drvdata(&unit->device);
+	int generation;
+
+	generation = parent->generation;
+	smp_rmb();
+	peer->node_id = parent->node_id;
+	smp_wmb();
+	peer->generation = generation;
+}
+
+static const struct ieee1394_device_id fwserial_id_table[] = {
+	{
+		.match_flags  = IEEE1394_MATCH_SPECIFIER_ID |
+				IEEE1394_MATCH_VERSION,
+		.specifier_id = LINUX_VENDOR_ID,
+		.version      = FWSERIAL_VERSION,
+	},
+	{ }
+};
+
+static struct fw_driver fwserial_driver = {
+	.driver = {
+		.owner  = THIS_MODULE,
+		.name   = KBUILD_MODNAME,
+		.bus    = &fw_bus_type,
+		.probe  = fwserial_probe,
+		.remove = fwserial_remove,
+	},
+	.update   = fwserial_update,
+	.id_table = fwserial_id_table,
+};
+
+#define FW_UNIT_SPECIFIER(id)	((CSR_SPECIFIER_ID << 24) | (id))
+#define FW_UNIT_VERSION(ver)	((CSR_VERSION << 24) | (ver))
+#define FW_UNIT_ADDRESS(ofs)	(((CSR_OFFSET | CSR_DEPENDENT_INFO) << 24)  \
+				 | (((ofs) - CSR_REGISTER_BASE) >> 2))
+/* XXX: config ROM definitons could be improved with semi-automated offset
+ * and length calculation
+ */
+#define FW_ROM_DESCRIPTOR(ofs)	(((CSR_LEAF | CSR_DESCRIPTOR) << 24) | (ofs))
+
+struct fwserial_unit_directory_data {
+	u16	crc;
+	u16	len;
+	u32	unit_specifier;
+	u32	unit_sw_version;
+	u32	unit_addr_offset;
+	u32	desc1_ofs;
+	u16	desc1_crc;
+	u16	desc1_len;
+	u32	desc1_data[5];
+} __packed;
+
+static struct fwserial_unit_directory_data fwserial_unit_directory_data = {
+	.len = 4,
+	.unit_specifier = FW_UNIT_SPECIFIER(LINUX_VENDOR_ID),
+	.unit_sw_version = FW_UNIT_VERSION(FWSERIAL_VERSION),
+	.desc1_ofs = FW_ROM_DESCRIPTOR(1),
+	.desc1_len = 5,
+	.desc1_data = {
+		0x00000000,			/*   type = text            */
+		0x00000000,			/*   enc = ASCII, lang EN   */
+		0x4c696e75,			/* 'Linux TTY'              */
+		0x78205454,
+		0x59000000,
+	},
+};
+
+static struct fw_descriptor fwserial_unit_directory = {
+	.length = sizeof(fwserial_unit_directory_data) / sizeof(u32),
+	.key    = (CSR_DIRECTORY | CSR_UNIT) << 24,
+	.data   = (u32 *)&fwserial_unit_directory_data,
+};
+
+/*
+ * The management address is in the unit space region but above other known
+ * address users (to keep wild writes from causing havoc)
+ */
+const struct fw_address_region fwserial_mgmt_addr_region = {
+	.start = CSR_REGISTER_BASE + 0x1e0000ULL,
+	.end = 0x1000000000000ULL,
+};
+
+static struct fw_address_handler fwserial_mgmt_addr_handler;
+
+/**
+ * fwserial_handle_plug_req - handle VIRT_CABLE_PLUG request work
+ * @work: ptr to peer->work
+ *
+ * Attempts to complete the VIRT_CABLE_PLUG handshake sequence for this peer.
+ *
+ * This checks for a collided request-- ie, that a VIRT_CABLE_PLUG request was
+ * already sent to this peer. If so, the collision is resolved by comparing
+ * guid values; the loser sends the plug response.
+ *
+ * Note: if an error prevents a response, don't do anything -- the
+ * remote will timeout its request.
+ */
+static void fwserial_handle_plug_req(struct work_struct *work)
+{
+	struct fwtty_peer *peer = to_peer(work, work);
+	struct virt_plug_params *plug_req = &peer->work_params.plug_req;
+	struct fwtty_port *port;
+	struct fwserial_mgmt_pkt *pkt;
+	int rcode;
+
+	pkt = kmalloc(sizeof(*pkt), GFP_KERNEL);
+	if (!pkt)
+		return;
+
+	port = fwserial_find_port(peer);
+
+	spin_lock_bh(&peer->lock);
+
+	switch (peer->state) {
+	case FWPS_NOT_ATTACHED:
+		if (!port) {
+			fwtty_err(&peer->unit, "no more ports avail");
+			fill_plug_rsp_nack(pkt);
+		} else {
+			peer->port = port;
+			fill_plug_rsp_ok(pkt, peer->port);
+			peer_set_state(peer, FWPS_PLUG_RESPONDING);
+			/* don't release claimed port */
+			port = NULL;
+		}
+		break;
+
+	case FWPS_PLUG_PENDING:
+		if (peer->serial->card->guid > peer->guid)
+			goto cleanup;
+
+		/* We lost - hijack the already-claimed port and send ok */
+		del_timer(&peer->timer);
+		fill_plug_rsp_ok(pkt, peer->port);
+		peer_set_state(peer, FWPS_PLUG_RESPONDING);
+		break;
+
+	default:
+		fill_plug_rsp_nack(pkt);
+	}
+
+	spin_unlock_bh(&peer->lock);
+	if (port)
+		fwserial_release_port(port);
+
+	rcode = fwserial_send_mgmt_sync(peer, pkt);
+
+	spin_lock_bh(&peer->lock);
+	if (peer->state == FWPS_PLUG_RESPONDING) {
+		if (rcode == RCODE_COMPLETE) {
+			struct fwtty_port *tmp = peer->port;
+
+			fwserial_virt_plug_complete(peer, plug_req);
+			spin_unlock_bh(&peer->lock);
+
+			fwtty_write_port_status(tmp);
+			spin_lock_bh(&peer->lock);
+		} else {
+			fwtty_err(&peer->unit, "PLUG_RSP error (%d)", rcode);
+			port = peer_revert_state(peer);
+		}
+	}
+cleanup:
+	spin_unlock_bh(&peer->lock);
+	if (port)
+		fwserial_release_port(port);
+	kfree(pkt);
+	return;
+}
+
+static void fwserial_handle_unplug_req(struct work_struct *work)
+{
+	struct fwtty_peer *peer = to_peer(work, work);
+	struct fwtty_port *port = NULL;
+	struct fwserial_mgmt_pkt *pkt;
+	int rcode;
+
+	pkt = kmalloc(sizeof(*pkt), GFP_KERNEL);
+	if (!pkt)
+		return;
+
+	spin_lock_bh(&peer->lock);
+
+	switch (peer->state) {
+	case FWPS_ATTACHED:
+		fill_unplug_rsp_ok(pkt);
+		peer_set_state(peer, FWPS_UNPLUG_RESPONDING);
+		break;
+
+	case FWPS_UNPLUG_PENDING:
+		if (peer->serial->card->guid > peer->guid)
+			goto cleanup;
+
+		/* We lost - send unplug rsp */
+		del_timer(&peer->timer);
+		fill_unplug_rsp_ok(pkt);
+		peer_set_state(peer, FWPS_UNPLUG_RESPONDING);
+		break;
+
+	default:
+		fill_unplug_rsp_nack(pkt);
+	}
+
+	spin_unlock_bh(&peer->lock);
+
+	rcode = fwserial_send_mgmt_sync(peer, pkt);
+
+	spin_lock_bh(&peer->lock);
+	if (peer->state == FWPS_UNPLUG_RESPONDING) {
+		if (rcode == RCODE_COMPLETE)
+			port = peer_revert_state(peer);
+		else
+			fwtty_err(&peer->unit, "UNPLUG_RSP error (%d)", rcode);
+	}
+cleanup:
+	spin_unlock_bh(&peer->lock);
+	if (port)
+		fwserial_release_port(port);
+	kfree(pkt);
+	return;
+}
+
+static int fwserial_parse_mgmt_write(struct fwtty_peer *peer,
+				     struct fwserial_mgmt_pkt *pkt,
+				     unsigned long long addr,
+				     size_t len)
+{
+	struct fwtty_port *port = NULL;
+	int rcode;
+
+	if (addr != fwserial_mgmt_addr_handler.offset || len < sizeof(pkt->hdr))
+		return RCODE_ADDRESS_ERROR;
+
+	if (len != be16_to_cpu(pkt->hdr.len) ||
+	    len != mgmt_pkt_expected_len(pkt->hdr.code))
+		return RCODE_DATA_ERROR;
+
+	spin_lock_bh(&peer->lock);
+	if (peer->state == FWPS_GONE) {
+		/*
+		 * This should never happen - it would mean that the
+		 * remote unit that just wrote this transaction was
+		 * already removed from the bus -- and the removal was
+		 * processed before we rec'd this transaction
+		 */
+		fwtty_err(&peer->unit, "peer already removed");
+		spin_unlock_bh(&peer->lock);
+		return RCODE_ADDRESS_ERROR;
+	}
+
+	rcode = RCODE_COMPLETE;
+
+	fwtty_dbg(&peer->unit, "mgmt: hdr.code: %04hx", pkt->hdr.code);
+
+	switch (be16_to_cpu(pkt->hdr.code) & FWSC_CODE_MASK) {
+	case FWSC_VIRT_CABLE_PLUG:
+		if (work_pending(&peer->work)) {
+			fwtty_err(&peer->unit, "plug req: busy");
+			rcode = RCODE_CONFLICT_ERROR;
+
+		} else {
+			peer->work_params.plug_req = pkt->plug_req;
+			PREPARE_WORK(&peer->work, fwserial_handle_plug_req);
+			queue_work(system_unbound_wq, &peer->work);
+		}
+		break;
+
+	case FWSC_VIRT_CABLE_PLUG_RSP:
+		if (peer->state != FWPS_PLUG_PENDING) {
+			rcode = RCODE_CONFLICT_ERROR;
+
+		} else if (be16_to_cpu(pkt->hdr.code) & FWSC_RSP_NACK) {
+			fwtty_notice(&peer->unit, "NACK plug rsp");
+			port = peer_revert_state(peer);
+
+		} else {
+			struct fwtty_port *tmp = peer->port;
+
+			fwserial_virt_plug_complete(peer, &pkt->plug_rsp);
+			spin_unlock_bh(&peer->lock);
+
+			fwtty_write_port_status(tmp);
+			spin_lock_bh(&peer->lock);
+		}
+		break;
+
+	case FWSC_VIRT_CABLE_UNPLUG:
+		if (work_pending(&peer->work)) {
+			fwtty_err(&peer->unit, "unplug req: busy");
+			rcode = RCODE_CONFLICT_ERROR;
+		} else {
+			PREPARE_WORK(&peer->work, fwserial_handle_unplug_req);
+			queue_work(system_unbound_wq, &peer->work);
+		}
+		break;
+
+	case FWSC_VIRT_CABLE_UNPLUG_RSP:
+		if (peer->state != FWPS_UNPLUG_PENDING)
+			rcode = RCODE_CONFLICT_ERROR;
+		else {
+			if (be16_to_cpu(pkt->hdr.code) & FWSC_RSP_NACK)
+				fwtty_notice(&peer->unit, "NACK unplug?");
+			port = peer_revert_state(peer);
+		}
+		break;
+
+	default:
+		fwtty_err(&peer->unit, "unknown mgmt code %d",
+			  be16_to_cpu(pkt->hdr.code));
+		rcode = RCODE_DATA_ERROR;
+	}
+	spin_unlock_bh(&peer->lock);
+
+	if (port)
+		fwserial_release_port(port);
+
+	return rcode;
+}
+
+/**
+ * fwserial_mgmt_handler: bus address handler for mgmt requests
+ * @parameters: fw_address_callback_t as specified by firewire core interface
+ *
+ * This handler is responsible for handling virtual cable requests from remotes
+ * for all cards.
+ */
+static void fwserial_mgmt_handler(struct fw_card *card,
+				  struct fw_request *request,
+				  int tcode, int destination, int source,
+				  int generation,
+				  unsigned long long addr,
+				  void *data, size_t len,
+				  void *callback_data)
+{
+	struct fwserial_mgmt_pkt *pkt = data;
+	struct fwtty_peer *peer;
+	int rcode;
+
+	rcu_read_lock();
+	peer = __fwserial_peer_by_node_id(card, generation, source);
+	if (!peer) {
+		fwtty_dbg(card, "peer(%d:%x) not found", generation, source);
+		__dump_peer_list(card);
+		rcode = RCODE_CONFLICT_ERROR;
+
+	} else {
+		switch (tcode) {
+		case TCODE_WRITE_BLOCK_REQUEST:
+			rcode = fwserial_parse_mgmt_write(peer, pkt, addr, len);
+			break;
+
+		default:
+			rcode = RCODE_TYPE_ERROR;
+		}
+	}
+
+	rcu_read_unlock();
+	fw_send_response(card, request, rcode);
+}
+
+static int __init fwserial_init(void)
+{
+	int err, num_loops = !!(create_loop_dev);
+
+	/* num_ttys/num_ports must not be set above the static alloc avail */
+	if (num_ttys + num_loops > MAX_CARD_PORTS)
+		num_ttys = MAX_CARD_PORTS - num_loops;
+	num_ports = num_ttys + num_loops;
+
+	fwtty_driver = alloc_tty_driver(MAX_TOTAL_PORTS);
+	if (!fwtty_driver) {
+		err = -ENOMEM;
+		return err;
+	}
+
+	fwtty_driver->driver_name	= KBUILD_MODNAME;
+	fwtty_driver->name		= tty_dev_name;
+	fwtty_driver->major		= 0;
+	fwtty_driver->minor_start	= 0;
+	fwtty_driver->type		= TTY_DRIVER_TYPE_SERIAL;
+	fwtty_driver->subtype		= SERIAL_TYPE_NORMAL;
+	fwtty_driver->flags		= TTY_DRIVER_REAL_RAW |
+						TTY_DRIVER_DYNAMIC_DEV;
+
+	fwtty_driver->init_termios	    = tty_std_termios;
+	fwtty_driver->init_termios.c_cflag  |= CLOCAL;
+	tty_set_operations(fwtty_driver, &fwtty_ops);
+
+	err = tty_register_driver(fwtty_driver);
+	if (err) {
+		driver_err("register tty driver failed (%d)", err);
+		goto put_tty;
+	}
+
+	fwtty_txn_cache = kmem_cache_create("fwtty_txn_cache",
+					    sizeof(struct fwtty_transaction),
+					    0, 0, fwtty_txn_constructor);
+	if (!fwtty_txn_cache) {
+		err = -ENOMEM;
+		goto unregister_driver;
+	}
+
+	/*
+	 * Ideally, this address handler would be registered per local node
+	 * (rather than the same handler for all local nodes). However,
+	 * since the firewire core requires the config rom descriptor *before*
+	 * the local unit device(s) are created, a single management handler
+	 * must suffice for all local serial units.
+	 */
+	fwserial_mgmt_addr_handler.length = sizeof(struct fwserial_mgmt_pkt);
+	fwserial_mgmt_addr_handler.address_callback = fwserial_mgmt_handler;
+
+	err = fw_core_add_address_handler(&fwserial_mgmt_addr_handler,
+					  &fwserial_mgmt_addr_region);
+	if (err) {
+		driver_err("add management handler failed (%d)", err);
+		goto destroy_cache;
+	}
+
+	fwserial_unit_directory_data.unit_addr_offset =
+		FW_UNIT_ADDRESS(fwserial_mgmt_addr_handler.offset);
+	err = fw_core_add_descriptor(&fwserial_unit_directory);
+	if (err) {
+		driver_err("add unit descriptor failed (%d)", err);
+		goto remove_handler;
+	}
+
+	err = driver_register(&fwserial_driver.driver);
+	if (err) {
+		driver_err("register fwserial driver failed (%d)", err);
+		goto remove_descriptor;
+	}
+
+	return 0;
+
+remove_descriptor:
+	fw_core_remove_descriptor(&fwserial_unit_directory);
+remove_handler:
+	fw_core_remove_address_handler(&fwserial_mgmt_addr_handler);
+destroy_cache:
+	kmem_cache_destroy(fwtty_txn_cache);
+unregister_driver:
+	tty_unregister_driver(fwtty_driver);
+put_tty:
+	put_tty_driver(fwtty_driver);
+	return err;
+}
+
+static void __exit fwserial_exit(void)
+{
+	driver_unregister(&fwserial_driver.driver);
+	fw_core_remove_descriptor(&fwserial_unit_directory);
+	fw_core_remove_address_handler(&fwserial_mgmt_addr_handler);
+	kmem_cache_destroy(fwtty_txn_cache);
+	tty_unregister_driver(fwtty_driver);
+	put_tty_driver(fwtty_driver);
+}
+
+module_init(fwserial_init);
+module_exit(fwserial_exit);
+
+MODULE_AUTHOR("Peter Hurley (peter@hurleysoftware.com)");
+MODULE_DESCRIPTION("FireWire Serial TTY Driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(ieee1394, fwserial_id_table);
+MODULE_PARM_DESC(ttys, "Number of ttys to create for each local firewire node");
+MODULE_PARM_DESC(auto, "Auto-connect a tty to each firewire node discovered");
+MODULE_PARM_DESC(loop, "Create a loopback device, fwloop<n>, with ttys");
+MODULE_PARM_DESC(limit_bw, "Limit bandwidth utilization to 20%.");
diff --git a/drivers/staging/fwserial/fwserial.h b/drivers/staging/fwserial/fwserial.h
new file mode 100644
index 0000000..8b572ed
--- /dev/null
+++ b/drivers/staging/fwserial/fwserial.h
@@ -0,0 +1,387 @@
+#ifndef _FIREWIRE_FWSERIAL_H
+#define _FIREWIRE_FWSERIAL_H
+
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/list.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/spinlock.h>
+#include <linux/rcupdate.h>
+#include <linux/mutex.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+
+#include "dma_fifo.h"
+
+#ifdef FWTTY_PROFILING
+#define DISTRIBUTION_MAX_SIZE     8192
+#define DISTRIBUTION_MAX_INDEX    (ilog2(DISTRIBUTION_MAX_SIZE) + 1)
+static inline void profile_size_distrib(unsigned stat[], unsigned val)
+{
+	int n = (val) ? min(ilog2(val) + 1, DISTRIBUTION_MAX_INDEX) : 0;
+	++stat[n];
+}
+#else
+#define DISTRIBUTION_MAX_INDEX    0
+#define profile_size_distrib(st, n)
+#endif
+
+/* Parameters for both VIRT_CABLE_PLUG & VIRT_CABLE_PLUG_RSP mgmt codes */
+struct virt_plug_params {
+	__be32  status_hi;
+	__be32  status_lo;
+	__be32	fifo_hi;
+	__be32	fifo_lo;
+	__be32	fifo_len;
+};
+
+struct peer_work_params {
+	union {
+		struct virt_plug_params plug_req;
+	};
+};
+
+/**
+ * fwtty_peer: structure representing local & remote unit devices
+ * @unit: unit child device of fw_device node
+ * @serial: back pointer to associated fw_serial aggregate
+ * @guid: unique 64-bit guid for this unit device
+ * @generation: most recent bus generation
+ * @node_id: most recent node_id
+ * @speed: link speed of peer (0 = S100, 2 = S400, ... 5 = S3200)
+ * @mgmt_addr: bus addr region to write mgmt packets to
+ * @status_addr: bus addr register to write line status to
+ * @fifo_addr: bus addr region to write serial output to
+ * @fifo_len:  max length for single write to fifo_addr
+ * @list: link for insertion into fw_serial's peer_list
+ * @rcu: for deferring peer reclamation
+ * @lock: spinlock to synchonize changes to state & port fields
+ * @work: only one work item can be queued at any one time
+ *        Note: pending work is canceled prior to removal, so this
+ *        peer is valid for at least the lifetime of the work function
+ * @work_params: parameter block for work functions
+ * @timer: timer for resetting peer state if remote request times out
+ * @state: current state
+ * @connect: work item for auto-connecting
+ * @connect_retries: # of connections already attempted
+ * @port: associated tty_port (usable if state == FWSC_ATTACHED)
+ */
+struct fwtty_peer {
+	struct fw_unit		*unit;
+	struct fw_serial	*serial;
+	u64			guid;
+	int			generation;
+	int			node_id;
+	unsigned		speed;
+	int			max_payload;
+	u64			mgmt_addr;
+
+	/* these are usable only if state == FWSC_ATTACHED */
+	u64			status_addr;
+	u64			fifo_addr;
+	int			fifo_len;
+
+	struct list_head	list;
+	struct rcu_head		rcu;
+
+	spinlock_t		lock;
+	struct work_struct	work;
+	struct peer_work_params work_params;
+	struct timer_list	timer;
+	int			state;
+	struct delayed_work	connect;
+	int			connect_retries;
+
+	struct fwtty_port	*port;
+};
+
+#define to_peer(ptr, field)	(container_of(ptr, struct fwtty_peer, field))
+
+/* state values for fwtty_peer.state field */
+enum fwtty_peer_state {
+	FWPS_GONE,
+	FWPS_NOT_ATTACHED,
+	FWPS_ATTACHED,
+	FWPS_PLUG_PENDING,
+	FWPS_PLUG_RESPONDING,
+	FWPS_UNPLUG_PENDING,
+	FWPS_UNPLUG_RESPONDING,
+
+	FWPS_NO_MGMT_ADDR = -1,
+};
+
+#define CONNECT_RETRY_DELAY	HZ
+#define MAX_CONNECT_RETRIES	10
+
+/* must be holding peer lock for these state funclets */
+static inline void peer_set_state(struct fwtty_peer *peer, int new)
+{
+	peer->state = new;
+}
+
+static inline struct fwtty_port *peer_revert_state(struct fwtty_peer *peer)
+{
+	struct fwtty_port *port = peer->port;
+
+	peer->port = NULL;
+	peer_set_state(peer, FWPS_NOT_ATTACHED);
+	return port;
+}
+
+struct fwserial_mgmt_pkt {
+	struct {
+		__be16		len;
+		__be16		code;
+	} hdr;
+	union {
+		struct virt_plug_params plug_req;
+		struct virt_plug_params plug_rsp;
+	};
+} __packed;
+
+/* fwserial_mgmt_packet codes */
+#define FWSC_RSP_OK			0x0000
+#define FWSC_RSP_NACK			0x8000
+#define FWSC_CODE_MASK			0x0fff
+
+#define FWSC_VIRT_CABLE_PLUG		1
+#define FWSC_VIRT_CABLE_UNPLUG		2
+#define FWSC_VIRT_CABLE_PLUG_RSP	3
+#define FWSC_VIRT_CABLE_UNPLUG_RSP	4
+
+/* 1 min. plug timeout -- suitable for userland authorization */
+#define VIRT_CABLE_PLUG_TIMEOUT		(60 * HZ)
+
+struct stats {
+	unsigned	xchars;
+	unsigned	dropped;
+	unsigned	tx_stall;
+	unsigned	fifo_errs;
+	unsigned	sent;
+	unsigned	lost;
+	unsigned	throttled;
+	unsigned	watermark;
+	unsigned	reads[DISTRIBUTION_MAX_INDEX + 1];
+	unsigned	writes[DISTRIBUTION_MAX_INDEX + 1];
+	unsigned	txns[DISTRIBUTION_MAX_INDEX + 1];
+	unsigned	unthrottle[DISTRIBUTION_MAX_INDEX + 1];
+};
+
+struct fwconsole_ops {
+	void (*notify)(int code, void *data);
+	void (*stats)(struct stats *stats, void *data);
+	void (*proc_show)(struct seq_file *m, void *data);
+};
+
+/* codes for console ops notify */
+#define FWCON_NOTIFY_ATTACH		1
+#define FWCON_NOTIFY_DETACH		2
+
+struct buffered_rx {
+	struct list_head	list;
+	size_t			n;
+	unsigned char		data[0];
+};
+
+/**
+ * fwtty_port: structure used to track/represent underlying tty_port
+ * @port: underlying tty_port
+ * @device: tty device
+ * @index: index into port_table for this particular port
+ *    note: minor = index + FWSERIAL_TTY_START_MINOR
+ * @serial: back pointer to the containing fw_serial
+ * @rx_handler: bus address handler for unique addr region used by remotes
+ *              to communicate with this port. Every port uses
+ *		fwtty_port_handler() for per port transactions.
+ * @fwcon_ops: ops for attached fw_console (if any)
+ * @con_data: private data for fw_console
+ * @wait_tx: waitqueue for sleeping until writer/drain completes tx
+ * @emit_breaks: delayed work responsible for generating breaks when the
+ *               break line status is active
+ * @cps : characters per second computed from the termios settings
+ * @break_last: timestamp in jiffies from last emit_breaks
+ * @hangup: work responsible for HUPing when carrier is dropped/lost
+ * @mstatus: loose virtualization of LSR/MSR
+ *         bits 15..0  correspond to TIOCM_* bits
+ *         bits 19..16 reserved for mctrl
+ *         bit 20      OOB_TX_THROTTLE
+ *	   bits 23..21 reserved
+ *         bits 31..24 correspond to UART_LSR_* bits
+ * @lock: spinlock for protecting concurrent access to fields below it
+ * @mctrl: loose virtualization of MCR
+ *         bits 15..0  correspond to TIOCM_* bits
+ *         bit 16      OOB_RX_THROTTLE
+ *         bits 19..17 reserved
+ *	   bits 31..20 reserved for mstatus
+ * @drain: delayed work scheduled to ensure that writes are flushed.
+ *         The work can race with the writer but concurrent sending is
+ *         prevented with the IN_TX flag. Scheduled under lock to
+ *         limit scheduling when fifo has just been drained.
+ * @push: work responsible for pushing buffered rx to the ldisc.
+ *	  rx can become buffered if the tty buffer is filled before the
+ *	  ldisc throttles the sender.
+ * @buf_list: list of buffered rx yet to be sent to ldisc
+ * @buffered: byte count of buffered rx
+ * @tx_fifo: fifo used to store & block-up writes for dma to remote
+ * @max_payload: max bytes transmissable per dma (based on peer's max_payload)
+ * @status_mask: UART_LSR_* bitmask significant to rx (based on termios)
+ * @ignore_mask: UART_LSR_* bitmask of states to ignore (also based on termios)
+ * @break_ctl: if set, port is 'sending break' to remote
+ * @write_only: self-explanatory
+ * @overrun: previous rx was lost (partially or completely)
+ * @loopback: if set, port is in loopback mode
+ * @flags: atomic bit flags
+ *         bit 0: IN_TX - gate to allow only one cpu to send from the dma fifo
+ *                        at a time.
+ *         bit 1: STOP_TX - force tx to exit while sending
+ * @peer: rcu-pointer to associated fwtty_peer (if attached)
+ *        NULL if no peer attached
+ * @icount: predefined statistics reported by the TIOCGICOUNT ioctl
+ * @stats: additional statistics reported in /proc/tty/driver/firewire_serial
+ */
+struct fwtty_port {
+	struct tty_port		   port;
+	struct device		   *device;
+	unsigned		   index;
+	struct fw_serial	   *serial;
+	struct fw_address_handler  rx_handler;
+
+	struct fwconsole_ops	   *fwcon_ops;
+	void			   *con_data;
+
+	wait_queue_head_t	   wait_tx;
+	struct delayed_work	   emit_breaks;
+	unsigned		   cps;
+	unsigned long		   break_last;
+
+	struct work_struct	   hangup;
+
+	unsigned		   mstatus;
+
+	spinlock_t		   lock;
+	unsigned		   mctrl;
+	struct delayed_work	   drain;
+	struct work_struct	   push;
+	struct list_head	   buf_list;
+	int			   buffered;
+	struct dma_fifo		   tx_fifo;
+	int			   max_payload;
+	unsigned		   status_mask;
+	unsigned		   ignore_mask;
+	unsigned		   break_ctl:1,
+				   write_only:1,
+				   overrun:1,
+				   loopback:1;
+	unsigned long		   flags;
+
+	struct fwtty_peer	   *peer;
+
+	struct async_icount	   icount;
+	struct stats		   stats;
+};
+
+#define to_port(ptr, field)	(container_of(ptr, struct fwtty_port, field))
+
+/* bit #s for flags field */
+#define IN_TX                      0
+#define STOP_TX                    1
+#define BUFFERING_RX		   2
+
+/* bitmasks for special mctrl/mstatus bits */
+#define OOB_RX_THROTTLE   0x00010000
+#define MCTRL_RSRVD       0x000e0000
+#define OOB_TX_THROTTLE   0x00100000
+#define MSTATUS_RSRVD     0x00e00000
+
+#define MCTRL_MASK        (TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 | TIOCM_OUT2 | \
+			   TIOCM_LOOP | OOB_RX_THROTTLE | MCTRL_RSRVD)
+
+/* XXX even every 1/50th secs. may be unnecessarily accurate */
+/* delay in jiffies between brk emits */
+#define FREQ_BREAKS        (HZ / 50)
+
+/* Ports are allocated in blocks of num_ports for each fw_card */
+#define MAX_CARD_PORTS           32	/* max # of ports per card */
+#define MAX_TOTAL_PORTS          64	/* max # of ports total    */
+
+/* tuning parameters */
+#define FWTTY_PORT_TXFIFO_LEN	4096
+#define FWTTY_PORT_MAX_PEND_DMA    8    /* costs a cache line per pend */
+#define DRAIN_THRESHOLD         1024
+#define MAX_ASYNC_PAYLOAD       4096    /* ohci-defined limit          */
+#define WRITER_MINIMUM           128
+/* TODO: how to set watermark to AR context size? see fwtty_rx() */
+#define HIGH_WATERMARK         32768	/* AR context is 32K	       */
+
+/*
+ * Size of bus addr region above 4GB used per port as the recv addr
+ * - must be at least as big as the MAX_ASYNC_PAYLOAD
+ */
+#define FWTTY_PORT_RXFIFO_LEN	MAX_ASYNC_PAYLOAD
+
+/**
+ * fw_serial: aggregate used to associate tty ports with specific fw_card
+ * @card: fw_card associated with this fw_serial device (1:1 association)
+ * @kref: reference-counted multi-port management allows delayed destroy
+ * @self: local unit device as 'peer'. Not valid until local unit device
+ *         is enumerated.
+ * @list: link for insertion into fwserial_list
+ * @peer_list: list of local & remote unit devices attached to this card
+ * @ports: fixed array of tty_ports provided by this serial device
+ */
+struct fw_serial {
+	struct fw_card	  *card;
+	struct kref	  kref;
+
+	struct fwtty_peer *self;
+
+	struct list_head  list;
+	struct list_head  peer_list;
+
+	struct fwtty_port *ports[MAX_CARD_PORTS];
+};
+
+#define to_serial(ptr, field)	(container_of(ptr, struct fw_serial, field))
+
+#define TTY_DEV_NAME		    "fwtty"	/* ttyFW was taken           */
+static const char tty_dev_name[] =  TTY_DEV_NAME;
+static const char loop_dev_name[] = "fwloop";
+extern bool limit_bw;
+
+struct tty_driver *fwtty_driver;
+
+#define driver_err(s, v...)	pr_err(KBUILD_MODNAME ": " s, ##v)
+
+struct fwtty_port *fwtty_port_get(unsigned index);
+void fwtty_port_put(struct fwtty_port *port);
+
+static inline void fwtty_bind_console(struct fwtty_port *port,
+				      struct fwconsole_ops *fwcon_ops,
+				      void *data)
+{
+	port->con_data = data;
+	port->fwcon_ops = fwcon_ops;
+}
+
+/*
+ * Returns the max send async payload size in bytes based on the unit device
+ * link speed - if set to limit bandwidth to max 20%, use lookup table
+ */
+static inline int link_speed_to_max_payload(unsigned speed)
+{
+	static const int max_async[] = { 307, 614, 1229, 2458, 4916, 9832, };
+	BUILD_BUG_ON(ARRAY_SIZE(max_async) - 1 != SCODE_3200);
+
+	speed = clamp(speed, (unsigned) SCODE_100, (unsigned) SCODE_3200);
+	if (limit_bw)
+		return max_async[speed];
+	else
+		return 1 << (speed + 9);
+}
+
+#endif /* _FIREWIRE_FWSERIAL_H */
diff --git a/drivers/staging/gdm72xx/gdm_qos.c b/drivers/staging/gdm72xx/gdm_qos.c
index e26c6a8..1e63031 100644
--- a/drivers/staging/gdm72xx/gdm_qos.c
+++ b/drivers/staging/gdm72xx/gdm_qos.c
@@ -11,6 +11,8 @@
  * GNU General Public License for more details.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/etherdevice.h>
 #include <asm/byteorder.h>
 
@@ -24,15 +26,6 @@
 
 #define B2H(x)		__be16_to_cpu(x)
 
-#undef dprintk
-#define dprintk(fmt, args ...) printk(KERN_DEBUG "[QoS] " fmt, ## args)
-#undef wprintk
-#define wprintk(fmt, args ...) \
-	printk(KERN_WARNING "[QoS WARNING] " fmt, ## args)
-#undef eprintk
-#define eprintk(fmt, args ...) printk(KERN_ERR "[QoS ERROR] " fmt, ## args)
-
-
 #define MAX_FREE_LIST_CNT		32
 static struct {
 	struct list_head head;
@@ -95,7 +88,7 @@ static void free_qos_entry_list(struct list_head *free_list)
 		total_free++;
 	}
 
-	dprintk("%s: total_free_cnt=%d\n", __func__, total_free);
+	pr_debug("%s: total_free_cnt=%d\n", __func__, total_free);
 }
 
 void gdm_qos_init(void *nic_ptr)
@@ -240,7 +233,9 @@ static u32 extract_qos_list(struct nic *nic, struct list_head *head)
 					qcb->csr[i].qos_buf_count++;
 
 					if (!list_empty(&qcb->qos_list[i]))
-						wprintk("QoS Index(%d) is piled!!\n", i);
+						netdev_warn(nic->netdev,
+							    "Index(%d) is piled!!\n",
+							    i);
 				}
 			}
 		}
@@ -280,7 +275,8 @@ int gdm_qos_send_hci_pkt(struct sk_buff *skb, struct net_device *dev)
 			entry = alloc_qos_entry();
 			entry->skb = skb;
 			entry->dev = dev;
-			dprintk("qcb->qos_list_cnt=%d\n", qcb->qos_list_cnt);
+			netdev_dbg(dev, "qcb->qos_list_cnt=%d\n",
+				   qcb->qos_list_cnt);
 		}
 
 		spin_lock_irqsave(&qcb->qos_lock, flags);
@@ -362,7 +358,7 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size)
 			index = get_csr(qcb, SFID, 0);
 			if (index == -1) {
 				spin_unlock_irqrestore(&qcb->qos_lock, flags);
-				eprintk("QoS ERROR: No SF\n");
+				netdev_err(nic->netdev, "QoS ERROR: No SF\n");
 				return;
 			}
 			qcb->csr[index].qos_buf_count = buf[(i*5)+10];
@@ -383,11 +379,12 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size)
 
 		index = get_csr(qcb, SFID, 1);
 		if (index == -1) {
-			eprintk("QoS ERROR: csr Update Error\n");
+			netdev_err(nic->netdev, "QoS ERROR: csr Update Error\n");
 			return;
 		}
 
-		dprintk("QOS_ADD SFID = 0x%x, index=%d\n", SFID, index);
+		netdev_dbg(nic->netdev, "QOS_ADD SFID = 0x%x, index=%d\n",
+			   SFID, index);
 
 		spin_lock_irqsave(&qcb->qos_lock, flags);
 		qcb->csr[index].SFID = SFID;
@@ -435,11 +432,13 @@ void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size)
 		SFID += (buf[pos++]);
 		index = get_csr(qcb, SFID, 1);
 		if (index == -1) {
-			eprintk("QoS ERROR: Wrong index(%d)\n", index);
+			netdev_err(nic->netdev, "QoS ERROR: Wrong index(%d)\n",
+				   index);
 			return;
 		}
 
-		dprintk("QOS_CHANGE_DEL SFID = 0x%x, index=%d\n", SFID, index);
+		netdev_dbg(nic->netdev, "QOS_CHANGE_DEL SFID = 0x%x, index=%d\n",
+			   SFID, index);
 
 		INIT_LIST_HEAD(&free_list);
 
diff --git a/drivers/staging/gdm72xx/gdm_sdio.c b/drivers/staging/gdm72xx/gdm_sdio.c
index ca38d71..8b8ed98 100644
--- a/drivers/staging/gdm72xx/gdm_sdio.c
+++ b/drivers/staging/gdm72xx/gdm_sdio.c
@@ -157,7 +157,7 @@ static int init_sdio(struct sdiowm_dev *sdev)
 
 	tx->sdu_buf = kmalloc(SDU_TX_BUF_SIZE, GFP_KERNEL);
 	if (tx->sdu_buf == NULL) {
-		printk(KERN_ERR "Failed to allocate SDU tx buffer.\n");
+		dev_err(&sdev->func->dev, "Failed to allocate SDU tx buffer.\n");
 		goto fail;
 	}
 
@@ -186,7 +186,7 @@ static int init_sdio(struct sdiowm_dev *sdev)
 
 	rx->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL);
 	if (rx->rx_buf == NULL) {
-		printk(KERN_ERR "Failed to allocate rx buffer.\n");
+		dev_err(&sdev->func->dev, "Failed to allocate rx buffer.\n");
 		goto fail;
 	}
 
@@ -246,7 +246,8 @@ static void send_sdio_pkt(struct sdio_func *func, u8 *data, int len)
 		ret = sdio_memcpy_toio(func, 0, data, n);
 		if (ret < 0) {
 			if (ret != -ENOMEDIUM)
-				printk(KERN_ERR "gdmwms: %s error: ret = %d\n",
+				dev_err(&func->dev,
+					"gdmwms: %s error: ret = %d\n",
 					__func__, ret);
 			goto end_io;
 		}
@@ -259,7 +260,8 @@ static void send_sdio_pkt(struct sdio_func *func, u8 *data, int len)
 		ret = sdio_memcpy_toio(func, 0, data + n, remain);
 		if (ret < 0) {
 			if (ret != -ENOMEDIUM)
-				printk(KERN_ERR "gdmwms: %s error: ret = %d\n",
+				dev_err(&func->dev,
+					"gdmwms: %s error: ret = %d\n",
 					__func__, ret);
 			goto end_io;
 		}
@@ -522,13 +524,14 @@ static void gdm_sdio_irq(struct sdio_func *func)
 
 	ret = sdio_memcpy_fromio(func, hdr, 0x0, TYPE_A_LOOKAHEAD_SIZE);
 	if (ret) {
-		printk(KERN_ERR "Cannot read from function %d\n", func->num);
+		dev_err(&func->dev,
+			"Cannot read from function %d\n", func->num);
 		goto done;
 	}
 
 	len = (hdr[2] << 16) | (hdr[1] << 8) | hdr[0];
 	if (len > (RX_BUF_SIZE - TYPE_A_HEADER_SIZE)) {
-		printk(KERN_ERR "Too big Type-A size: %d\n", len);
+		dev_err(&func->dev, "Too big Type-A size: %d\n", len);
 		goto done;
 	}
 
@@ -562,8 +565,8 @@ static void gdm_sdio_irq(struct sdio_func *func)
 		n = blocks * func->cur_blksize;
 		ret = sdio_memcpy_fromio(func, buf, 0x0, n);
 		if (ret) {
-			printk(KERN_ERR "Cannot read from function %d\n",
-				func->num);
+			dev_err(&func->dev,
+				"Cannot read from function %d\n", func->num);
 			goto done;
 		}
 		buf += n;
@@ -573,8 +576,8 @@ static void gdm_sdio_irq(struct sdio_func *func)
 	if (remain) {
 		ret = sdio_memcpy_fromio(func, buf, 0x0, remain);
 		if (ret) {
-			printk(KERN_ERR "Cannot read from function %d\n",
-				func->num);
+			dev_err(&func->dev,
+				"Cannot read from function %d\n", func->num);
 			goto done;
 		}
 	}
@@ -637,9 +640,9 @@ static int sdio_wimax_probe(struct sdio_func *func,
 	struct phy_dev *phy_dev = NULL;
 	struct sdiowm_dev *sdev = NULL;
 
-	printk(KERN_INFO "Found GDM SDIO VID = 0x%04x PID = 0x%04x...\n",
-			func->vendor, func->device);
-	printk(KERN_INFO "GCT WiMax driver version %s\n", DRIVER_VERSION);
+	dev_info(&func->dev, "Found GDM SDIO VID = 0x%04x PID = 0x%04x...\n",
+		 func->vendor, func->device);
+	dev_info(&func->dev, "GCT WiMax driver version %s\n", DRIVER_VERSION);
 
 	sdio_claim_host(func);
 	sdio_enable_func(func);
diff --git a/drivers/staging/gdm72xx/gdm_usb.c b/drivers/staging/gdm72xx/gdm_usb.c
index 0c9e895..e434764 100644
--- a/drivers/staging/gdm72xx/gdm_usb.c
+++ b/drivers/staging/gdm72xx/gdm_usb.c
@@ -186,6 +186,7 @@ static int init_usb(struct usbwm_dev *udev)
 	struct rx_cxt	*rx = &udev->rx;
 	struct usb_tx	*t;
 	struct usb_rx	*r;
+	unsigned long flags;
 
 	INIT_LIST_HEAD(&tx->free_list);
 	INIT_LIST_HEAD(&tx->sdu_list);
@@ -200,6 +201,7 @@ static int init_usb(struct usbwm_dev *udev)
 	spin_lock_init(&tx->lock);
 	spin_lock_init(&rx->lock);
 
+	spin_lock_irqsave(&tx->lock, flags);
 	for (i = 0; i < MAX_NR_SDU_BUF; i++) {
 		t = alloc_tx_struct(tx);
 		if (t == NULL) {
@@ -208,6 +210,7 @@ static int init_usb(struct usbwm_dev *udev)
 		}
 		list_add(&t->list, &tx->free_list);
 	}
+	spin_unlock_irqrestore(&tx->lock, flags);
 
 	r = alloc_rx_struct(rx);
 	if (r == NULL) {
@@ -215,7 +218,9 @@ static int init_usb(struct usbwm_dev *udev)
 		goto fail;
 	}
 
+	spin_lock_irqsave(&rx->lock, flags);
 	list_add(&r->list, &rx->free_list);
+	spin_unlock_irqrestore(&rx->lock, flags);
 	return ret;
 
 fail:
@@ -229,6 +234,9 @@ static void release_usb(struct usbwm_dev *udev)
 	struct rx_cxt	*rx = &udev->rx;
 	struct usb_tx	*t, *t_next;
 	struct usb_rx	*r, *r_next;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tx->lock, flags);
 
 	list_for_each_entry_safe(t, t_next, &tx->sdu_list, list) {
 		list_del(&t->list);
@@ -245,6 +253,10 @@ static void release_usb(struct usbwm_dev *udev)
 		free_tx_struct(t);
 	}
 
+	spin_unlock_irqrestore(&tx->lock, flags);
+
+	spin_lock_irqsave(&rx->lock, flags);
+
 	list_for_each_entry_safe(r, r_next, &rx->free_list, list) {
 		list_del(&r->list);
 		free_rx_struct(r);
@@ -254,6 +266,8 @@ static void release_usb(struct usbwm_dev *udev)
 		list_del(&r->list);
 		free_rx_struct(r);
 	}
+
+	spin_unlock_irqrestore(&rx->lock, flags);
 }
 
 static void __gdm_usb_send_complete(struct urb *urb)
@@ -303,9 +317,12 @@ static int gdm_usb_send(void *priv_dev, void *data, int len,
 	u8 *pkt = data;
 	u16 cmd_evt;
 	unsigned long flags;
+#ifdef CONFIG_WIMAX_GDM72XX_K_MODE
+	unsigned long flags2;
+#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
 
 	if (!udev->usbdev) {
-		printk(KERN_ERR "%s: No such device\n", __func__);
+		dev_err(&usbdev->dev, "%s: No such device\n", __func__);
 		return -ENODEV;
 	}
 
@@ -371,13 +388,16 @@ static int gdm_usb_send(void *priv_dev, void *data, int len,
 
 		rx = &udev->rx;
 
+		spin_lock_irqsave(&rx->lock, flags2);
 		list_for_each_entry(r, &rx->used_list, list)
 			usb_unlink_urb(r->urb);
+		spin_unlock_irqrestore(&rx->lock, flags2);
+
 		udev->bw_switch = 1;
 
-		spin_lock(&k_lock);
+		spin_lock_irqsave(&k_lock, flags2);
 		list_add_tail(&udev->list, &k_list);
-		spin_unlock(&k_lock);
+		spin_unlock_irqrestore(&k_lock, flags2);
 
 		wake_up(&k_wait);
 	}
@@ -416,7 +436,7 @@ static void gdm_usb_rcv_complete(struct urb *urb)
 	struct tx_cxt *tx = &udev->tx;
 	struct usb_tx *t;
 	u16 cmd_evt;
-	unsigned long flags;
+	unsigned long flags, flags2;
 
 #ifdef CONFIG_WIMAX_GDM72XX_USB_PM
 	struct usb_device *dev = urb->dev;
@@ -462,9 +482,9 @@ static void gdm_usb_rcv_complete(struct urb *urb)
 	if (!urb->status && r->callback)
 		r->callback(r->cb_data, r->buf, urb->actual_length);
 
-	spin_lock(&rx->lock);
+	spin_lock_irqsave(&rx->lock, flags2);
 	put_rx_struct(rx, r);
-	spin_unlock(&rx->lock);
+	spin_unlock_irqrestore(&rx->lock, flags2);
 
 	spin_unlock_irqrestore(&tx->lock, flags);
 
@@ -484,7 +504,7 @@ static int gdm_usb_receive(void *priv_dev,
 	unsigned long flags;
 
 	if (!udev->usbdev) {
-		printk(KERN_ERR "%s: No such device\n", __func__);
+		dev_err(&usbdev->dev, "%s: No such device\n", __func__);
 		return -ENODEV;
 	}
 
@@ -559,9 +579,9 @@ static int gdm_usb_probe(struct usb_interface *intf,
 	idProduct = L2H(usbdev->descriptor.idProduct);
 	bcdDevice = L2H(usbdev->descriptor.bcdDevice);
 
-	printk(KERN_INFO "Found GDM USB VID = 0x%04x PID = 0x%04x...\n",
-		idVendor, idProduct);
-	printk(KERN_INFO "GCT WiMax driver version %s\n", DRIVER_VERSION);
+	dev_info(&intf->dev, "Found GDM USB VID = 0x%04x PID = 0x%04x...\n",
+		 idVendor, idProduct);
+	dev_info(&intf->dev, "GCT WiMax driver version %s\n", DRIVER_VERSION);
 
 
 	if (idProduct == EMERGENCY_PID) {
@@ -619,8 +639,9 @@ out:
 	if (ret) {
 		kfree(phy_dev);
 		kfree(udev);
+	} else {
+		usb_set_intfdata(intf, phy_dev);
 	}
-	usb_set_intfdata(intf, phy_dev);
 	return ret;
 }
 
@@ -660,14 +681,22 @@ static int gdm_suspend(struct usb_interface *intf, pm_message_t pm_msg)
 	struct usbwm_dev *udev;
 	struct rx_cxt *rx;
 	struct usb_rx *r;
+	unsigned long flags;
 
 	phy_dev = usb_get_intfdata(intf);
+	if (!phy_dev)
+		return 0;
+
 	udev = phy_dev->priv_dev;
 	rx = &udev->rx;
 
+	spin_lock_irqsave(&rx->lock, flags);
+
 	list_for_each_entry(r, &rx->used_list, list)
 		usb_unlink_urb(r->urb);
 
+	spin_unlock_irqrestore(&rx->lock, flags);
+
 	return 0;
 }
 
@@ -677,14 +706,22 @@ static int gdm_resume(struct usb_interface *intf)
 	struct usbwm_dev *udev;
 	struct rx_cxt *rx;
 	struct usb_rx *r;
+	unsigned long flags;
 
 	phy_dev = usb_get_intfdata(intf);
+	if (!phy_dev)
+		return 0;
+
 	udev = phy_dev->priv_dev;
 	rx = &udev->rx;
 
+	spin_lock_irqsave(&rx->lock, flags);
+
 	list_for_each_entry(r, &rx->used_list, list)
 		usb_submit_urb(r->urb, GFP_ATOMIC);
 
+	spin_unlock_irqrestore(&rx->lock, flags);
+
 	return 0;
 }
 
@@ -701,8 +738,6 @@ static int k_mode_thread(void *arg)
 	unsigned long flags, flags2, expire;
 	int ret;
 
-	daemonize("k_mode_wimax");
-
 	while (!k_mode_stop) {
 
 		spin_lock_irqsave(&k_lock, flags2);
@@ -719,9 +754,13 @@ static int k_mode_thread(void *arg)
 			while (jiffies < expire)
 				schedule_timeout(K_WAIT_TIME);
 
+			spin_lock_irqsave(&rx->lock, flags);
+
 			list_for_each_entry(r, &rx->used_list, list)
 				usb_submit_urb(r->urb, GFP_ATOMIC);
 
+			spin_unlock_irqrestore(&rx->lock, flags);
+
 			spin_lock_irqsave(&tx->lock, flags);
 
 			list_for_each_entry_safe(t, temp, &tx->pending_list,
@@ -764,7 +803,7 @@ static struct usb_driver gdm_usb_driver = {
 static int __init usb_gdm_wimax_init(void)
 {
 #ifdef CONFIG_WIMAX_GDM72XX_K_MODE
-	kthread_run(k_mode_thread, NULL, "WiMax_thread");
+	kthread_run(k_mode_thread, NULL, "k_mode_wimax");
 #endif /* CONFIG_WIMAX_GDM72XX_K_MODE */
 	return usb_register(&gdm_usb_driver);
 }
diff --git a/drivers/staging/gdm72xx/gdm_wimax.c b/drivers/staging/gdm72xx/gdm_wimax.c
index 6cb8107..41efbee 100644
--- a/drivers/staging/gdm72xx/gdm_wimax.c
+++ b/drivers/staging/gdm72xx/gdm_wimax.c
@@ -11,6 +11,8 @@
  * GNU General Public License for more details.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/etherdevice.h>
 #include <asm/byteorder.h>
 #include <linux/ip.h>
@@ -166,21 +168,13 @@ static void dump_eth_packet(const char *title, u8 *data, int len)
 		get_ip_protocol_name(ip_protocol),
 		get_port_name(port));
 
-	#if 1
 	if (!(data[0] == 0xff && data[1] == 0xff)) {
 		if (protocol == ETH_P_IP) {
-			printk(KERN_DEBUG "     src=%u.%u.%u.%u\n",
-				NIPQUAD(ih->saddr));
+			printk(KERN_DEBUG "     src=%pI4\n", &ih->saddr);
 		} else if (protocol == ETH_P_IPV6) {
-			#ifdef NIP6
-			printk(KERN_DEBUG "     src=%x:%x:%x:%x:%x:%x:%x:%x\n",
-				NIP6(ih->saddr));
-			#else
 			printk(KERN_DEBUG "     src=%pI6\n", &ih->saddr);
-			#endif
 		}
 	}
-	#endif
 
 	#if (DUMP_PACKET & DUMP_SDU_ALL)
 	printk_hex(data, len);
@@ -271,7 +265,7 @@ static int gdm_wimax_event_init(void)
 		return 0;
 	}
 
-	printk(KERN_ERR "Creating WiMax Event netlink is failed\n");
+	pr_err("Creating WiMax Event netlink is failed\n");
 	return -1;
 }
 
@@ -367,7 +361,7 @@ static int gdm_wimax_event_send(struct net_device *dev, char *buf, int size)
 
 	e = get_event_entry();
 	if (!e) {
-		printk(KERN_ERR "%s: No memory for event\n", __func__);
+		netdev_err(dev, "%s: No memory for event\n", __func__);
 		spin_unlock_irqrestore(&wm_event.evt_lock, flags);
 		return -ENOMEM;
 	}
@@ -433,10 +427,10 @@ static int gdm_wimax_tx(struct sk_buff *skb, struct net_device *dev)
 
 	#if !defined(LOOPBACK_TEST)
 	if (!fsm)
-		printk(KERN_ERR "ASSERTION ERROR: fsm is NULL!!\n");
+		netdev_err(dev, "ASSERTION ERROR: fsm is NULL!!\n");
 	else if (fsm->m_status != M_CONNECTED) {
-		printk(KERN_EMERG "ASSERTION ERROR: Device is NOT ready. status=%d\n",
-			fsm->m_status);
+		netdev_emerg(dev, "ASSERTION ERROR: Device is NOT ready. status=%d\n",
+			     fsm->m_status);
 		kfree_skb(skb);
 		return 0;
 	}
@@ -622,9 +616,8 @@ static int gdm_wimax_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	case SIOCG_DATA:
 	case SIOCS_DATA:
 		if (req->data_id >= SIOC_DATA_MAX) {
-			printk(KERN_ERR
-				"%s error: data-index(%d) is invalid!!\n",
-				__func__, req->data_id);
+			netdev_err(dev, "%s error: data-index(%d) is invalid!!\n",
+				   __func__, req->data_id);
 			return -EOPNOTSUPP;
 		}
 		if (req->cmd == SIOCG_DATA) {
@@ -646,7 +639,7 @@ static int gdm_wimax_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 		}
 		break;
 	default:
-		printk(KERN_ERR "%s: %x unknown ioctl\n", __func__, cmd);
+		netdev_err(dev, "%s: %x unknown ioctl\n", __func__, cmd);
 		return -EOPNOTSUPP;
 	}
 
@@ -692,7 +685,7 @@ static void gdm_wimax_prepare_device(struct net_device *dev)
 	hci->length = H2B(len);
 	gdm_wimax_send(nic, hci, HCI_HEADER_SIZE+len);
 
-	printk(KERN_INFO "GDM WiMax Set CAPABILITY: 0x%08X\n", DB2H(val));
+	netdev_info(dev, "GDM WiMax Set CAPABILITY: 0x%08X\n", DB2H(val));
 }
 
 static int gdm_wimax_hci_get_tlv(u8 *buf, u8 *T, u16 *L, u8 **V)
@@ -726,28 +719,28 @@ static int gdm_wimax_get_prepared_info(struct net_device *dev, char *buf,
 	cmd_len = B2H(*(u16 *)&buf[2]);
 
 	if (len < cmd_len + HCI_HEADER_SIZE) {
-		printk(KERN_ERR "%s: invalid length [%d/%d]\n", __func__,
-			cmd_len + HCI_HEADER_SIZE, len);
+		netdev_err(dev, "%s: invalid length [%d/%d]\n", __func__,
+			   cmd_len + HCI_HEADER_SIZE, len);
 		return -1;
 	}
 
 	if (cmd_evt == WIMAX_GET_INFO_RESULT) {
 		if (cmd_len < 2) {
-			printk(KERN_ERR "%s: len is too short [%x/%d]\n",
-				__func__, cmd_evt, len);
+			netdev_err(dev, "%s: len is too short [%x/%d]\n",
+				   __func__, cmd_evt, len);
 			return -1;
 		}
 
 		pos += gdm_wimax_hci_get_tlv(&buf[pos], &T, &L, &V);
 		if (T == TLV_T(T_MAC_ADDRESS)) {
 			if (L != dev->addr_len) {
-				printk(KERN_ERR
-					"%s Invalid inofrmation result T/L "
-					"[%x/%d]\n", __func__, T, L);
+				netdev_err(dev,
+					   "%s Invalid inofrmation result T/L [%x/%d]\n",
+					   __func__, T, L);
 				return -1;
 			}
-			printk(KERN_INFO "MAC change [%pM]->[%pM]\n",
-				dev->dev_addr, V);
+			netdev_info(dev, "MAC change [%pM]->[%pM]\n",
+				    dev->dev_addr, V);
 			memcpy(dev->dev_addr, V, dev->addr_len);
 			return 1;
 		}
@@ -769,7 +762,7 @@ static void gdm_wimax_netif_rx(struct net_device *dev, char *buf, int len)
 
 	skb = dev_alloc_skb(len + 2);
 	if (!skb) {
-		printk(KERN_ERR "%s: dev_alloc_skb failed!\n", __func__);
+		netdev_err(dev, "%s: dev_alloc_skb failed!\n", __func__);
 		return;
 	}
 	skb_reserve(skb, 2);
@@ -784,7 +777,7 @@ static void gdm_wimax_netif_rx(struct net_device *dev, char *buf, int len)
 
 	ret = in_interrupt() ? netif_rx(skb) : netif_rx_ni(skb);
 	if (ret == NET_RX_DROP)
-		printk(KERN_ERR "%s skb dropped\n", __func__);
+		netdev_err(dev, "%s skb dropped\n", __func__);
 }
 
 static void gdm_wimax_transmit_aggr_pkt(struct net_device *dev, char *buf,
@@ -799,8 +792,8 @@ static void gdm_wimax_transmit_aggr_pkt(struct net_device *dev, char *buf,
 		hci = (struct hci_s *) buf;
 
 		if (B2H(hci->cmd_evt) != WIMAX_RX_SDU) {
-			printk(KERN_ERR "Wrong cmd_evt(0x%04X)\n",
-				B2H(hci->cmd_evt));
+			netdev_err(dev, "Wrong cmd_evt(0x%04X)\n",
+				   B2H(hci->cmd_evt));
 			break;
 		}
 
@@ -834,8 +827,8 @@ static void gdm_wimax_transmit_pkt(struct net_device *dev, char *buf, int len)
 
 	if (len < cmd_len + HCI_HEADER_SIZE) {
 		if (len)
-			printk(KERN_ERR "%s: invalid length [%d/%d]\n",
-				__func__, cmd_len + HCI_HEADER_SIZE, len);
+			netdev_err(dev, "%s: invalid length [%d/%d]\n",
+				   __func__, cmd_len + HCI_HEADER_SIZE, len);
 		return;
 	}
 
@@ -915,7 +908,8 @@ static void prepare_rx_complete(void *arg, void *data, int len)
 		gdm_wimax_rcv_with_cb(nic, rx_complete, nic);
 	else {
 		if (ret < 0)
-			printk(KERN_ERR "get_prepared_info failed(%d)\n", ret);
+			netdev_err(nic->netdev,
+				   "get_prepared_info failed(%d)\n", ret);
 		gdm_wimax_rcv_with_cb(nic, prepare_rx_complete, nic);
 		#if 0
 		/* Re-prepare WiMax device */
@@ -949,7 +943,7 @@ int register_wimax_device(struct phy_dev *phy_dev, struct device *pdev)
 						"wm%d", ether_setup);
 
 	if (dev == NULL) {
-		printk(KERN_ERR "alloc_etherdev failed\n");
+		pr_err("alloc_etherdev failed\n");
 		return -ENOMEM;
 	}
 
@@ -969,7 +963,7 @@ int register_wimax_device(struct phy_dev *phy_dev, struct device *pdev)
 	/* event socket init */
 	ret = gdm_wimax_event_init();
 	if (ret < 0) {
-		printk(KERN_ERR "Cannot create event.\n");
+		pr_err("Cannot create event.\n");
 		goto cleanup;
 	}
 
@@ -996,7 +990,7 @@ int register_wimax_device(struct phy_dev *phy_dev, struct device *pdev)
 	return 0;
 
 cleanup:
-	printk(KERN_ERR "register_netdev failed\n");
+	pr_err("register_netdev failed\n");
 	free_netdev(dev);
 	return ret;
 }
diff --git a/drivers/staging/gdm72xx/netlink_k.c b/drivers/staging/gdm72xx/netlink_k.c
index 20d0aec..52c25ba 100644
--- a/drivers/staging/gdm72xx/netlink_k.c
+++ b/drivers/staging/gdm72xx/netlink_k.c
@@ -11,6 +11,8 @@
  * GNU General Public License for more details.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/etherdevice.h>
 #include <linux/netlink.h>
@@ -54,8 +56,8 @@ static void netlink_rcv_cb(struct sk_buff *skb)
 
 		if (skb->len < nlh->nlmsg_len ||
 		nlh->nlmsg_len > ND_MAX_MSG_LEN) {
-			printk(KERN_ERR "Invalid length (%d,%d)\n", skb->len,
-				nlh->nlmsg_len);
+			netdev_err(skb->dev, "Invalid length (%d,%d)\n",
+				   skb->len, nlh->nlmsg_len);
 			return;
 		}
 
@@ -69,10 +71,11 @@ static void netlink_rcv_cb(struct sk_buff *skb)
 				rcv_cb(dev, nlh->nlmsg_type, msg, mlen);
 				dev_put(dev);
 			} else
-				printk(KERN_ERR "dev_get_by_index(%d) "
-					"is not found.\n", ifindex);
+				netdev_err(skb->dev,
+					   "dev_get_by_index(%d) is not found.\n",
+					   ifindex);
 		} else
-			printk(KERN_ERR "Unregistered Callback\n");
+			netdev_err(skb->dev, "Unregistered Callback\n");
 	}
 }
 
@@ -116,14 +119,14 @@ int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len)
 	int ret = 0;
 
 	if (group > ND_MAX_GROUP) {
-		printk(KERN_ERR "Group %d is invalied.\n", group);
-		printk(KERN_ERR "Valid group is 0 ~ %d.\n", ND_MAX_GROUP);
+		pr_err("Group %d is invalied.\n", group);
+		pr_err("Valid group is 0 ~ %d.\n", ND_MAX_GROUP);
 		return -EINVAL;
 	}
 
 	skb = alloc_skb(NLMSG_SPACE(len), GFP_ATOMIC);
 	if (!skb) {
-		printk(KERN_ERR "netlink_broadcast ret=%d\n", ret);
+		pr_err("netlink_broadcast ret=%d\n", ret);
 		return -ENOMEM;
 	}
 
@@ -144,8 +147,8 @@ int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len)
 		return len;
 	else {
 		if (ret != -ESRCH) {
-			printk(KERN_ERR "netlink_broadcast g=%d, t=%d, l=%d, r=%d\n",
-				group, type, len, ret);
+			pr_err("netlink_broadcast g=%d, t=%d, l=%d, r=%d\n",
+			       group, type, len, ret);
 		}
 		ret = 0;
 	}
diff --git a/drivers/staging/gdm72xx/sdio_boot.c b/drivers/staging/gdm72xx/sdio_boot.c
index 65624bc..6291829 100644
--- a/drivers/staging/gdm72xx/sdio_boot.c
+++ b/drivers/staging/gdm72xx/sdio_boot.c
@@ -24,15 +24,18 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/sdio_func.h>
 
+#include <linux/firmware.h>
+
 #include "gdm_sdio.h"
 
 #define TYPE_A_HEADER_SIZE	4
 #define TYPE_A_LOOKAHEAD_SIZE   16
-#define YMEM0_SIZE			0x8000	/* 32kbytes */
+#define YMEM0_SIZE		0x8000	/* 32kbytes */
 #define DOWNLOAD_SIZE		(YMEM0_SIZE - TYPE_A_HEADER_SIZE)
 
-#define KRN_PATH	"/lib/firmware/gdm72xx/gdmskrn.bin"
-#define RFS_PATH	"/lib/firmware/gdm72xx/gdmsrfs.bin"
+#define FW_DIR			"gdm72xx/"
+#define FW_KRN			"gdmskrn.bin"
+#define FW_RFS			"gdmsrfs.bin"
 
 static u8 *tx_buf;
 
@@ -52,106 +55,109 @@ static int ack_ready(struct sdio_func *func)
 	return 0;
 }
 
-static int download_image(struct sdio_func *func, char *img_name)
+static int download_image(struct sdio_func *func, const char *img_name)
 {
-	int ret = 0, len, size, pno;
-	struct file *filp = NULL;
-	struct inode *inode = NULL;
+	int ret = 0, len, pno;
 	u8 *buf = tx_buf;
 	loff_t pos = 0;
-
-	filp = filp_open(img_name, O_RDONLY | O_LARGEFILE, 0);
-	if (IS_ERR(filp)) {
-		printk(KERN_ERR "Can't find %s.\n", img_name);
-		return -ENOENT;
+	int img_len;
+	const struct firmware *firm;
+
+	ret = request_firmware(&firm, img_name, &func->dev);
+	if (ret < 0) {
+		dev_err(&func->dev,
+			"requesting firmware %s failed with error %d\n",
+			img_name, ret);
+		return ret;
 	}
 
-	inode = filp->f_dentry->d_inode;
-	if (!S_ISREG(inode->i_mode)) {
-		printk(KERN_ERR "Invalid file type: %s\n", img_name);
-		ret = -EINVAL;
-		goto out;
+	buf = kmalloc(DOWNLOAD_SIZE + TYPE_A_HEADER_SIZE, GFP_KERNEL);
+	if (buf == NULL) {
+		dev_err(&func->dev, "Error: kmalloc\n");
+		return -ENOMEM;
 	}
 
-	size = i_size_read(inode->i_mapping->host);
-	if (size <= 0) {
-		printk(KERN_ERR "Unable to find file size: %s\n", img_name);
-		ret = size;
+	img_len = firm->size;
+
+	if (img_len <= 0) {
+		ret = -1;
 		goto out;
 	}
 
 	pno = 0;
-	while ((len = filp->f_op->read(filp, buf + TYPE_A_HEADER_SIZE,
-					DOWNLOAD_SIZE, &pos))) {
-		if (len < 0) {
-			ret = -1;
-			goto out;
+	while (img_len > 0) {
+		if (img_len > DOWNLOAD_SIZE) {
+			len = DOWNLOAD_SIZE;
+			buf[3] = 0;
+		} else {
+			len = img_len; /* the last packet */
+			buf[3] = 2;
 		}
 
 		buf[0] = len & 0xff;
 		buf[1] = (len >> 8) & 0xff;
 		buf[2] = (len >> 16) & 0xff;
 
-		if (pos >= size)	/* The last packet */
-			buf[3] = 2;
-		else
-			buf[3] = 0;
-
+		memcpy(buf+TYPE_A_HEADER_SIZE, firm->data + pos, len);
 		ret = sdio_memcpy_toio(func, 0, buf, len + TYPE_A_HEADER_SIZE);
 		if (ret < 0) {
-			printk(KERN_ERR "gdmwm: send image error: "
-				"packet number = %d ret = %d\n", pno, ret);
+			dev_err(&func->dev,
+				"send image error: packet number = %d ret = %d\n",
+				pno, ret);
 			goto out;
 		}
+
 		if (buf[3] == 2)	/* The last packet */
 			break;
 		if (!ack_ready(func)) {
 			ret = -EIO;
-			printk(KERN_ERR "gdmwm: Ack is not ready.\n");
+			dev_err(&func->dev, "Ack is not ready.\n");
 			goto out;
 		}
 		ret = sdio_memcpy_fromio(func, buf, 0, TYPE_A_LOOKAHEAD_SIZE);
 		if (ret < 0) {
-			printk(KERN_ERR "gdmwm: receive ack error: "
-				"packet number = %d ret = %d\n", pno, ret);
+			dev_err(&func->dev,
+				"receive ack error: packet number = %d ret = %d\n",
+				pno, ret);
 			goto out;
 		}
 		sdio_writeb(func, 0x01, 0x13, &ret);
 		sdio_writeb(func, 0x00, 0x10, &ret);	/* PCRRT */
 
+		img_len -= DOWNLOAD_SIZE;
+		pos += DOWNLOAD_SIZE;
 		pno++;
 	}
+
 out:
-	filp_close(filp, NULL);
+	kfree(buf);
 	return ret;
 }
 
 int sdio_boot(struct sdio_func *func)
 {
-	static mm_segment_t fs;
 	int ret;
+	const char *krn_name = FW_DIR FW_KRN;
+	const char *rfs_name = FW_DIR FW_RFS;
 
 	tx_buf = kmalloc(YMEM0_SIZE, GFP_KERNEL);
 	if (tx_buf == NULL) {
-		printk(KERN_ERR "Error: kmalloc: %s %d\n", __func__, __LINE__);
+		dev_err(&func->dev, "Error: kmalloc: %s %d\n",
+			__func__, __LINE__);
 		return -ENOMEM;
 	}
 
-	fs = get_fs();
-	set_fs(get_ds());
-
-	ret = download_image(func, KRN_PATH);
+	ret = download_image(func, krn_name);
 	if (ret)
 		goto restore_fs;
-	printk(KERN_INFO "GCT: Kernel download success.\n");
+	dev_info(&func->dev, "GCT: Kernel download success.\n");
 
-	ret = download_image(func, RFS_PATH);
+	ret = download_image(func, rfs_name);
 	if (ret)
 		goto restore_fs;
-	printk(KERN_INFO "GCT: Filesystem download success.\n");
+	dev_info(&func->dev, "GCT: Filesystem download success.\n");
 
 restore_fs:
-	set_fs(fs);
 	kfree(tx_buf);
 	return ret;
 }
diff --git a/drivers/staging/gdm72xx/usb_boot.c b/drivers/staging/gdm72xx/usb_boot.c
index 0787188..3e2103a 100644
--- a/drivers/staging/gdm72xx/usb_boot.c
+++ b/drivers/staging/gdm72xx/usb_boot.c
@@ -82,7 +82,8 @@ static int gdm_wibro_send(struct usb_device *usbdev, void *data, int len)
 			&actual, 1000);
 
 	if (ret < 0) {
-		printk(KERN_ERR "Error : usb_bulk_msg ( result = %d )\n", ret);
+		dev_err(&usbdev->dev, "Error : usb_bulk_msg ( result = %d )\n",
+			ret);
 		return ret;
 	}
 	return 0;
@@ -97,8 +98,8 @@ static int gdm_wibro_recv(struct usb_device *usbdev, void *data, int len)
 			&actual, 5000);
 
 	if (ret < 0) {
-		printk(KERN_ERR "Error : usb_bulk_msg(recv) ( result = %d )\n",
-			ret);
+		dev_err(&usbdev->dev,
+			"Error : usb_bulk_msg(recv) ( result = %d )\n", ret);
 		return ret;
 	}
 	return 0;
@@ -150,20 +151,20 @@ int usb_boot(struct usb_device *usbdev, u16 pid)
 
 	ret = request_firmware(&firm, img_name, &usbdev->dev);
 	if (ret < 0) {
-		printk(KERN_ERR
-		       "requesting firmware %s failed with error %d\n",
+		dev_err(&usbdev->dev,
+			"requesting firmware %s failed with error %d\n",
 			img_name, ret);
 		return ret;
 	}
 
 	tx_buf = kmalloc(DOWNLOAD_SIZE, GFP_KERNEL);
 	if (tx_buf == NULL) {
-		printk(KERN_ERR "Error: kmalloc\n");
+		dev_err(&usbdev->dev, "Error: kmalloc\n");
 		return -ENOMEM;
 	}
 
 	if (firm->size < sizeof(hdr)) {
-		printk(KERN_ERR "gdmwm: Cannot read the image info.\n");
+		dev_err(&usbdev->dev, "Cannot read the image info.\n");
 		ret = -EIO;
 		goto out;
 	}
@@ -172,23 +173,22 @@ int usb_boot(struct usb_device *usbdev, u16 pid)
 	array_le32_to_cpu((u32 *)&hdr, 19);
 #if 0
 	if (hdr.magic_code != 0x10767fff) {
-		printk(KERN_ERR "gdmwm: Invalid magic code 0x%08x\n",
+		dev_err(&usbdev->dev, "Invalid magic code 0x%08x\n",
 			hdr.magic_code);
 		ret = -EINVAL;
 		goto out;
 	}
 #endif
 	if (hdr.count > MAX_IMG_CNT) {
-		printk(KERN_ERR "gdmwm: Too many images. %d\n", hdr.count);
+		dev_err(&usbdev->dev, "Too many images. %d\n", hdr.count);
 		ret = -EINVAL;
 		goto out;
 	}
 
 	for (i = 0; i < hdr.count; i++) {
 		if (hdr.offset[i] > hdr.len) {
-			printk(KERN_ERR "gdmwm: Invalid offset. "
-				"Entry = %d Offset = 0x%08x "
-				"Image length = 0x%08x\n",
+			dev_err(&usbdev->dev,
+				"Invalid offset. Entry = %d Offset = 0x%08x Image length = 0x%08x\n",
 				i, hdr.offset[i], hdr.len);
 			ret = -EINVAL;
 			goto out;
@@ -196,7 +196,7 @@ int usb_boot(struct usb_device *usbdev, u16 pid)
 
 		pos = hdr.offset[i];
 		if (firm->size < sizeof(fw_info) + pos) {
-			printk(KERN_ERR "gdmwm: Cannot read the FW info.\n");
+			dev_err(&usbdev->dev, "Cannot read the FW info.\n");
 			ret = -EIO;
 			goto out;
 		}
@@ -205,7 +205,7 @@ int usb_boot(struct usb_device *usbdev, u16 pid)
 		array_le32_to_cpu((u32 *)&fw_info, 8);
 #if 0
 		if ((fw_info.id & 0xfffff000) != 0x10767000) {
-			printk(KERN_ERR "gdmwm: Invalid FW id. 0x%08x\n",
+			dev_err(&usbdev->dev, "Invalid FW id. 0x%08x\n",
 				fw_info.id);
 			ret = -EIO;
 			goto out;
@@ -217,7 +217,7 @@ int usb_boot(struct usb_device *usbdev, u16 pid)
 
 		pos = hdr.offset[i] + fw_info.kernel_offset;
 		if (firm->size < fw_info.kernel_len + pos) {
-			printk(KERN_ERR "gdmwm: Kernel FW is too small.\n");
+			dev_err(&usbdev->dev, "Kernel FW is too small.\n");
 			goto out;
 		}
 
@@ -225,24 +225,25 @@ int usb_boot(struct usb_device *usbdev, u16 pid)
 				fw_info.kernel_len, DN_KERNEL_MAGIC_NUMBER);
 		if (ret < 0)
 			goto out;
-		printk(KERN_INFO "GCT: Kernel download success.\n");
+		dev_info(&usbdev->dev, "GCT: Kernel download success.\n");
 
 		pos = hdr.offset[i] + fw_info.rootfs_offset;
 		if (firm->size < fw_info.rootfs_len + pos) {
-			printk(KERN_ERR "gdmwm: Filesystem FW is too small.\n");
+			dev_err(&usbdev->dev, "Filesystem FW is too small.\n");
 			goto out;
 		}
 		ret = download_image(usbdev, firm, pos, fw_info.rootfs_len,
 				DN_ROOTFS_MAGIC_NUMBER);
 		if (ret < 0)
 			goto out;
-		printk(KERN_INFO "GCT: Filesystem download success.\n");
+		dev_info(&usbdev->dev, "GCT: Filesystem download success.\n");
 
 		break;
 	}
 
 	if (i == hdr.count) {
-		printk(KERN_ERR "Firmware for gsk%x is not installed.\n", pid);
+		dev_err(&usbdev->dev, "Firmware for gsk%x is not installed.\n",
+			pid);
 		ret = -EINVAL;
 	}
 out:
@@ -293,15 +294,15 @@ static int em_download_image(struct usb_device *usbdev, const char *img_name,
 
 	ret = request_firmware(&firm, img_name, &usbdev->dev);
 	if (ret < 0) {
-		printk(KERN_ERR
-		       "requesting firmware %s failed with error %d\n",
+		dev_err(&usbdev->dev,
+			"requesting firmware %s failed with error %d\n",
 			img_name, ret);
 		return ret;
 	}
 
 	buf = kmalloc(DOWNLOAD_CHUCK + pad_size, GFP_KERNEL);
 	if (buf == NULL) {
-		printk(KERN_ERR "Error: kmalloc\n");
+		dev_err(&usbdev->dev, "Error: kmalloc\n");
 		return -ENOMEM;
 	}
 
@@ -366,12 +367,12 @@ int usb_emergency(struct usb_device *usbdev)
 	ret = em_download_image(usbdev, kern_name, KERNEL_TYPE_STRING);
 	if (ret < 0)
 		return ret;
-	printk(KERN_INFO "GCT Emergency: Kernel download success.\n");
+	dev_err(&usbdev->dev, "GCT Emergency: Kernel download success.\n");
 
 	ret = em_download_image(usbdev, fs_name, FS_TYPE_STRING);
 	if (ret < 0)
 		return ret;
-	printk(KERN_INFO "GCT Emergency: Filesystem download success.\n");
+	dev_info(&usbdev->dev, "GCT Emergency: Filesystem download success.\n");
 
 	ret = em_fw_reset(usbdev);
 
diff --git a/drivers/staging/iio/accel/Kconfig b/drivers/staging/iio/accel/Kconfig
index 5ab7167..2b54430 100644
--- a/drivers/staging/iio/accel/Kconfig
+++ b/drivers/staging/iio/accel/Kconfig
@@ -6,8 +6,8 @@ menu "Accelerometers"
 config ADIS16201
 	tristate "Analog Devices ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer"
 	depends on SPI
-	select IIO_TRIGGER if IIO_BUFFER
-	select IIO_SW_RING if IIO_BUFFER
+	select IIO_ADIS_LIB
+	select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
 	help
 	  Say yes here to build support for Analog Devices adis16201 dual-axis
 	  digital inclinometer and accelerometer.
@@ -15,8 +15,8 @@ config ADIS16201
 config ADIS16203
 	tristate "Analog Devices ADIS16203 Programmable 360 Degrees Inclinometer"
 	depends on SPI
-	select IIO_TRIGGER if IIO_BUFFER
-	select IIO_SW_RING if IIO_BUFFER
+	select IIO_ADIS_LIB
+	select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
 	help
 	  Say yes here to build support for Analog Devices adis16203 Programmable
 	  360 Degrees Inclinometer.
@@ -24,8 +24,8 @@ config ADIS16203
 config ADIS16204
 	tristate "Analog Devices ADIS16204 Programmable High-g Digital Impact Sensor and Recorder"
 	depends on SPI
-	select IIO_TRIGGER if IIO_BUFFER
-	select IIO_SW_RING if IIO_BUFFER
+	select IIO_ADIS_LIB
+	select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
 	help
 	  Say yes here to build support for Analog Devices adis16204 Programmable
 	  High-g Digital Impact Sensor and Recorder.
@@ -33,8 +33,8 @@ config ADIS16204
 config ADIS16209
 	tristate "Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer"
 	depends on SPI
-	select IIO_TRIGGER if IIO_BUFFER
-	select IIO_SW_RING if IIO_BUFFER
+	select IIO_ADIS_LIB
+	select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
 	help
 	  Say yes here to build support for Analog Devices adis16209 dual-axis digital inclinometer
 	  and accelerometer.
@@ -42,6 +42,7 @@ config ADIS16209
 config ADIS16220
 	tristate "Analog Devices ADIS16220 Programmable Digital Vibration Sensor"
 	depends on SPI
+	select IIO_ADIS_LIB
 	help
 	  Say yes here to build support for Analog Devices adis16220 programmable
 	  digital vibration sensor.
@@ -49,8 +50,8 @@ config ADIS16220
 config ADIS16240
 	tristate "Analog Devices ADIS16240 Programmable Impact Sensor and Recorder"
 	depends on SPI
-	select IIO_TRIGGER if IIO_BUFFER
-	select IIO_SW_RING if IIO_BUFFER
+	select IIO_ADIS_LIB
+	select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
 	help
 	  Say yes here to build support for Analog Devices adis16240 programmable
 	  impact Sensor and recorder.
diff --git a/drivers/staging/iio/accel/Makefile b/drivers/staging/iio/accel/Makefile
index 95c6666..8e7ee03 100644
--- a/drivers/staging/iio/accel/Makefile
+++ b/drivers/staging/iio/accel/Makefile
@@ -3,26 +3,21 @@
 #
 
 adis16201-y             := adis16201_core.o
-adis16201-$(CONFIG_IIO_BUFFER) += adis16201_ring.o adis16201_trigger.o
 obj-$(CONFIG_ADIS16201) += adis16201.o
 
 adis16203-y             := adis16203_core.o
-adis16203-$(CONFIG_IIO_BUFFER) += adis16203_ring.o adis16203_trigger.o
 obj-$(CONFIG_ADIS16203) += adis16203.o
 
 adis16204-y             := adis16204_core.o
-adis16204-$(CONFIG_IIO_BUFFER) += adis16204_ring.o adis16204_trigger.o
 obj-$(CONFIG_ADIS16204) += adis16204.o
 
 adis16209-y             := adis16209_core.o
-adis16209-$(CONFIG_IIO_BUFFER) += adis16209_ring.o adis16209_trigger.o
 obj-$(CONFIG_ADIS16209) += adis16209.o
 
 adis16220-y             := adis16220_core.o
 obj-$(CONFIG_ADIS16220) += adis16220.o
 
 adis16240-y             := adis16240_core.o
-adis16240-$(CONFIG_IIO_BUFFER) += adis16240_ring.o adis16240_trigger.o
 obj-$(CONFIG_ADIS16240) += adis16240.o
 
 obj-$(CONFIG_KXSD9)	+= kxsd9.o
diff --git a/drivers/staging/iio/accel/adis16201.h b/drivers/staging/iio/accel/adis16201.h
index 72750f7..8747de5 100644
--- a/drivers/staging/iio/accel/adis16201.h
+++ b/drivers/staging/iio/accel/adis16201.h
@@ -3,9 +3,6 @@
 
 #define ADIS16201_STARTUP_DELAY	220 /* ms */
 
-#define ADIS16201_READ_REG(a)    a
-#define ADIS16201_WRITE_REG(a) ((a) | 0x80)
-
 #define ADIS16201_FLASH_CNT      0x00 /* Flash memory write count */
 #define ADIS16201_SUPPLY_OUT     0x02 /* Output, power supply */
 #define ADIS16201_XACCL_OUT      0x04 /* Output, x-axis accelerometer */
@@ -36,8 +33,6 @@
 #define ADIS16201_DIAG_STAT      0x3C /* Diagnostics, system status register */
 #define ADIS16201_GLOB_CMD       0x3E /* Operation, system command register */
 
-#define ADIS16201_OUTPUTS        7
-
 /* MSC_CTRL */
 #define ADIS16201_MSC_CTRL_SELF_TEST_EN	        (1 << 8)  /* Self-test enable */
 #define ADIS16201_MSC_CTRL_DATA_RDY_EN	        (1 << 2)  /* Data-ready enable: 1 = enabled, 0 = disabled */
@@ -47,95 +42,25 @@
 /* DIAG_STAT */
 #define ADIS16201_DIAG_STAT_ALARM2        (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
 #define ADIS16201_DIAG_STAT_ALARM1        (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
-#define ADIS16201_DIAG_STAT_SPI_FAIL	  (1<<3) /* SPI communications failure */
-#define ADIS16201_DIAG_STAT_FLASH_UPT	  (1<<2) /* Flash update failure */
-#define ADIS16201_DIAG_STAT_POWER_HIGH	  (1<<1) /* Power supply above 3.625 V */
-#define ADIS16201_DIAG_STAT_POWER_LOW	  (1<<0) /* Power supply below 3.15 V */
+#define ADIS16201_DIAG_STAT_SPI_FAIL_BIT   3 /* SPI communications failure */
+#define ADIS16201_DIAG_STAT_FLASH_UPT_BIT  2 /* Flash update failure */
+#define ADIS16201_DIAG_STAT_POWER_HIGH_BIT 1 /* Power supply above 3.625 V */
+#define ADIS16201_DIAG_STAT_POWER_LOW_BIT  0 /* Power supply below 3.15 V */
 
 /* GLOB_CMD */
 #define ADIS16201_GLOB_CMD_SW_RESET	(1<<7)
 #define ADIS16201_GLOB_CMD_FACTORY_CAL	(1<<1)
 
-#define ADIS16201_MAX_TX 14
-#define ADIS16201_MAX_RX 14
-
 #define ADIS16201_ERROR_ACTIVE          (1<<14)
 
-/**
- * struct adis16201_state - device instance specific data
- * @us:			actual spi_device
- * @trig:		data ready trigger registered with iio
- * @tx:			transmit buffer
- * @rx:			receive buffer
- * @buf_lock:		mutex to protect tx and rx
- **/
-struct adis16201_state {
-	struct spi_device	*us;
-	struct iio_trigger	*trig;
-	struct mutex		buf_lock;
-	u8			tx[14] ____cacheline_aligned;
-	u8			rx[14];
-};
-
-int adis16201_set_irq(struct iio_dev *indio_dev, bool enable);
-
 enum adis16201_scan {
-	ADIS16201_SCAN_SUPPLY,
 	ADIS16201_SCAN_ACC_X,
 	ADIS16201_SCAN_ACC_Y,
-	ADIS16201_SCAN_AUX_ADC,
-	ADIS16201_SCAN_TEMP,
 	ADIS16201_SCAN_INCLI_X,
 	ADIS16201_SCAN_INCLI_Y,
+	ADIS16201_SCAN_SUPPLY,
+	ADIS16201_SCAN_AUX_ADC,
+	ADIS16201_SCAN_TEMP,
 };
 
-#ifdef CONFIG_IIO_BUFFER
-void adis16201_remove_trigger(struct iio_dev *indio_dev);
-int adis16201_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16201_read_data_from_ring(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf);
-
-int adis16201_configure_ring(struct iio_dev *indio_dev);
-void adis16201_unconfigure_ring(struct iio_dev *indio_dev);
-
-#else /* CONFIG_IIO_BUFFER */
-
-static inline void adis16201_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16201_probe_trigger(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline ssize_t
-adis16201_read_data_from_ring(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	return 0;
-}
-
-static int adis16201_configure_ring(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline void adis16201_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16201_initialize_ring(struct iio_ring_buffer *ring)
-{
-	return 0;
-}
-
-static inline void adis16201_uninitialize_ring(struct iio_ring_buffer *ring)
-{
-}
-
-#endif /* CONFIG_IIO_BUFFER */
 #endif /* SPI_ADIS16201_H_ */
diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c
index b12ca68..9e5791f 100644
--- a/drivers/staging/iio/accel/adis16201_core.c
+++ b/drivers/staging/iio/accel/adis16201_core.c
@@ -18,258 +18,15 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
 
 #include "adis16201.h"
 
-enum adis16201_chan {
-	in_supply,
-	temp,
-	accel_x,
-	accel_y,
-	incli_x,
-	incli_y,
-	in_aux,
-};
-
-/**
- * adis16201_spi_write_reg_8() - write single byte to a register
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-static int adis16201_spi_write_reg_8(struct iio_dev *indio_dev,
-		u8 reg_address,
-		u8 val)
-{
-	int ret;
-	struct adis16201_state *st = iio_priv(indio_dev);
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16201_WRITE_REG(reg_address);
-	st->tx[1] = val;
-
-	ret = spi_write(st->us, st->tx, 2);
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/**
- * adis16201_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16201_spi_write_reg_16(struct iio_dev *indio_dev,
-				      u8 lower_reg_address,
-				      u16 value)
-{
-	int ret;
-	struct spi_message msg;
-	struct adis16201_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-		}, {
-			.tx_buf = st->tx + 2,
-			.bits_per_word = 8,
-			.len = 2,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16201_WRITE_REG(lower_reg_address);
-	st->tx[1] = value & 0xFF;
-	st->tx[2] = ADIS16201_WRITE_REG(lower_reg_address + 1);
-	st->tx[3] = (value >> 8) & 0xFF;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/**
- * adis16201_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16201_spi_read_reg_16(struct iio_dev *indio_dev,
-		u8 lower_reg_address,
-		u16 *val)
-{
-	struct spi_message msg;
-	struct adis16201_state *st = iio_priv(indio_dev);
-	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-			.delay_usecs = 20,
-		}, {
-			.rx_buf = st->rx,
-			.bits_per_word = 8,
-			.len = 2,
-			.delay_usecs = 20,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16201_READ_REG(lower_reg_address);
-	st->tx[1] = 0;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
-	if (ret) {
-		dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
-				lower_reg_address);
-		goto error_ret;
-	}
-	*val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
-}
-
-static int adis16201_reset(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct adis16201_state *st = iio_priv(indio_dev);
-
-	ret = adis16201_spi_write_reg_8(indio_dev,
-			ADIS16201_GLOB_CMD,
-			ADIS16201_GLOB_CMD_SW_RESET);
-	if (ret)
-		dev_err(&st->us->dev, "problem resetting device");
-
-	return ret;
-}
-
-int adis16201_set_irq(struct iio_dev *indio_dev, bool enable)
-{
-	int ret = 0;
-	u16 msc;
-
-	ret = adis16201_spi_read_reg_16(indio_dev, ADIS16201_MSC_CTRL, &msc);
-	if (ret)
-		goto error_ret;
-
-	msc |= ADIS16201_MSC_CTRL_ACTIVE_HIGH;
-	msc &= ~ADIS16201_MSC_CTRL_DATA_RDY_DIO1;
-	if (enable)
-		msc |= ADIS16201_MSC_CTRL_DATA_RDY_EN;
-	else
-		msc &= ~ADIS16201_MSC_CTRL_DATA_RDY_EN;
-
-	ret = adis16201_spi_write_reg_16(indio_dev, ADIS16201_MSC_CTRL, msc);
-
-error_ret:
-	return ret;
-}
-
-static int adis16201_check_status(struct iio_dev *indio_dev)
-{
-	u16 status;
-	int ret;
-
-	ret = adis16201_spi_read_reg_16(indio_dev,
-					ADIS16201_DIAG_STAT, &status);
-	if (ret < 0) {
-		dev_err(&indio_dev->dev, "Reading status failed\n");
-		goto error_ret;
-	}
-	ret = status & 0xF;
-	if (ret)
-		ret = -EFAULT;
-
-	if (status & ADIS16201_DIAG_STAT_SPI_FAIL)
-		dev_err(&indio_dev->dev, "SPI failure\n");
-	if (status & ADIS16201_DIAG_STAT_FLASH_UPT)
-		dev_err(&indio_dev->dev, "Flash update failed\n");
-	if (status & ADIS16201_DIAG_STAT_POWER_HIGH)
-		dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
-	if (status & ADIS16201_DIAG_STAT_POWER_LOW)
-		dev_err(&indio_dev->dev, "Power supply below 3.15V\n");
-
-error_ret:
-	return ret;
-}
-
-static int adis16201_self_test(struct iio_dev *indio_dev)
-{
-	int ret;
-	ret = adis16201_spi_write_reg_16(indio_dev,
-			ADIS16201_MSC_CTRL,
-			ADIS16201_MSC_CTRL_SELF_TEST_EN);
-	if (ret) {
-		dev_err(&indio_dev->dev, "problem starting self test");
-		goto err_ret;
-	}
-
-	ret = adis16201_check_status(indio_dev);
-
-err_ret:
-	return ret;
-}
-
-static int adis16201_initial_setup(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct device *dev = &indio_dev->dev;
-
-	/* Disable IRQ */
-	ret = adis16201_set_irq(indio_dev, false);
-	if (ret) {
-		dev_err(dev, "disable irq failed");
-		goto err_ret;
-	}
-
-	/* Do self test */
-	ret = adis16201_self_test(indio_dev);
-	if (ret) {
-		dev_err(dev, "self test failure");
-		goto err_ret;
-	}
-
-	/* Read status register to check the result */
-	ret = adis16201_check_status(indio_dev);
-	if (ret) {
-		adis16201_reset(indio_dev);
-		dev_err(dev, "device not playing ball -> reset");
-		msleep(ADIS16201_STARTUP_DELAY);
-		ret = adis16201_check_status(indio_dev);
-		if (ret) {
-			dev_err(dev, "giving up");
-			goto err_ret;
-		}
-	}
-
-err_ret:
-	return ret;
-}
-
-static u8 adis16201_addresses[7][2] = {
-	[in_supply] = { ADIS16201_SUPPLY_OUT, },
-	[temp] = { ADIS16201_TEMP_OUT },
-	[accel_x] = { ADIS16201_XACCL_OUT, ADIS16201_XACCL_OFFS },
-	[accel_y] = { ADIS16201_YACCL_OUT, ADIS16201_YACCL_OFFS },
-	[in_aux] = { ADIS16201_AUX_ADC },
-	[incli_x] = { ADIS16201_XINCL_OUT },
-	[incli_y] = { ADIS16201_YINCL_OUT },
+static const u8 adis16201_addresses[] = {
+	[ADIS16201_SCAN_ACC_X] = ADIS16201_XACCL_OFFS,
+	[ADIS16201_SCAN_ACC_Y] = ADIS16201_YACCL_OFFS,
+	[ADIS16201_SCAN_INCLI_X] = ADIS16201_XINCL_OFFS,
+	[ADIS16201_SCAN_INCLI_Y] = ADIS16201_YINCL_OFFS,
 };
 
 static int adis16201_read_raw(struct iio_dev *indio_dev,
@@ -277,6 +34,7 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,
 			      int *val, int *val2,
 			      long mask)
 {
+	struct adis *st = iio_priv(indio_dev);
 	int ret;
 	int bits;
 	u8 addr;
@@ -284,29 +42,8 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
-		mutex_lock(&indio_dev->mlock);
-		addr = adis16201_addresses[chan->address][0];
-		ret = adis16201_spi_read_reg_16(indio_dev, addr, &val16);
-		if (ret) {
-			mutex_unlock(&indio_dev->mlock);
-			return ret;
-		}
-
-		if (val16 & ADIS16201_ERROR_ACTIVE) {
-			ret = adis16201_check_status(indio_dev);
-			if (ret) {
-				mutex_unlock(&indio_dev->mlock);
-				return ret;
-			}
-		}
-		val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
-		if (chan->scan_type.sign == 's')
-			val16 = (s16)(val16 <<
-				      (16 - chan->scan_type.realbits)) >>
-				(16 - chan->scan_type.realbits);
-		*val = val16;
-		mutex_unlock(&indio_dev->mlock);
-		return IIO_VAL_INT;
+		return adis_single_conversion(indio_dev, chan,
+				ADIS16201_ERROR_ACTIVE, val);
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->type) {
 		case IIO_VOLTAGE:
@@ -347,10 +84,10 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,
 			break;
 		default:
 			return -EINVAL;
-		};
+		}
 		mutex_lock(&indio_dev->mlock);
-		addr = adis16201_addresses[chan->address][1];
-		ret = adis16201_spi_read_reg_16(indio_dev, addr, &val16);
+		addr = adis16201_addresses[chan->scan_index];
+		ret = adis_read_reg_16(st, addr, &val16);
 		if (ret) {
 			mutex_unlock(&indio_dev->mlock);
 			return ret;
@@ -370,6 +107,7 @@ static int adis16201_write_raw(struct iio_dev *indio_dev,
 			       int val2,
 			       long mask)
 {
+	struct adis *st = iio_priv(indio_dev);
 	int bits;
 	s16 val16;
 	u8 addr;
@@ -384,126 +122,63 @@ static int adis16201_write_raw(struct iio_dev *indio_dev,
 			break;
 		default:
 			return -EINVAL;
-		};
+		}
 		val16 = val & ((1 << bits) - 1);
-		addr = adis16201_addresses[chan->address][1];
-		return adis16201_spi_write_reg_16(indio_dev, addr, val16);
+		addr = adis16201_addresses[chan->scan_index];
+		return adis_write_reg_16(st, addr, val16);
 	}
 	return -EINVAL;
 }
 
 static const struct iio_chan_spec adis16201_channels[] = {
-	{
-		.type = IIO_VOLTAGE,
-		.indexed = 1,
-		.channel = 0,
-		.extend_name = "supply",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		 IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-		.address = in_supply,
-		.scan_index = ADIS16201_SCAN_SUPPLY,
-		.scan_type = {
-			.sign = 'u',
-			.realbits = 12,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_TEMP,
-		.indexed = 1,
-		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		 IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-		 IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
-		.address = temp,
-		.scan_index = ADIS16201_SCAN_TEMP,
-		.scan_type = {
-			.sign = 'u',
-			.realbits = 12,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_ACCEL,
-		.modified = 1,
-		.channel2 = IIO_MOD_X,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		 IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
-		.address = accel_x,
-		.scan_index = ADIS16201_SCAN_ACC_X,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 14,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_ACCEL,
-		.modified = 1,
-		.channel2 = IIO_MOD_Y,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		 IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
-		.address = accel_y,
-		.scan_index = ADIS16201_SCAN_ACC_Y,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 14,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_VOLTAGE,
-		.indexed = 1,
-		.channel = 1,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		 IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-		.address = in_aux,
-		.scan_index = ADIS16201_SCAN_AUX_ADC,
-		.scan_type = {
-			.sign = 'u',
-			.realbits = 12,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_INCLI,
-		.modified = 1,
-		.channel2 = IIO_MOD_X,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		 IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
-		.address = incli_x,
-		.scan_index = ADIS16201_SCAN_INCLI_X,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 14,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_INCLI,
-		.modified = 1,
-		.channel2 = IIO_MOD_Y,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		 IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		 IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
-		.address = incli_y,
-		.scan_index = ADIS16201_SCAN_INCLI_Y,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 14,
-			.storagebits = 16,
-		},
-	},
+	ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 12),
+	ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 12),
+	ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT, ADIS16201_SCAN_ACC_X,
+		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+	ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT, ADIS16201_SCAN_ACC_Y,
+		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+	ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 12),
+	ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT, ADIS16201_SCAN_INCLI_X,
+		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+	ADIS_INCLI_CHAN(X, ADIS16201_YINCL_OUT, ADIS16201_SCAN_INCLI_Y,
+		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
 	IIO_CHAN_SOFT_TIMESTAMP(7)
 };
 
 static const struct iio_info adis16201_info = {
 	.read_raw = &adis16201_read_raw,
 	.write_raw = &adis16201_write_raw,
+	.update_scan_mode = adis_update_scan_mode,
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit adis16201_probe(struct spi_device *spi)
+static const char * const adis16201_status_error_msgs[] = {
+	[ADIS16201_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
+	[ADIS16201_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
+	[ADIS16201_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
+	[ADIS16201_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V",
+};
+
+static const struct adis_data adis16201_data = {
+	.read_delay = 20,
+	.msc_ctrl_reg = ADIS16201_MSC_CTRL,
+	.glob_cmd_reg = ADIS16201_GLOB_CMD,
+	.diag_stat_reg = ADIS16201_DIAG_STAT,
+
+	.self_test_mask = ADIS16201_MSC_CTRL_SELF_TEST_EN,
+	.startup_delay = ADIS16201_STARTUP_DELAY,
+
+	.status_error_msgs = adis16201_status_error_msgs,
+	.status_error_mask = BIT(ADIS16201_DIAG_STAT_SPI_FAIL_BIT) |
+		BIT(ADIS16201_DIAG_STAT_FLASH_UPT_BIT) |
+		BIT(ADIS16201_DIAG_STAT_POWER_HIGH_BIT) |
+		BIT(ADIS16201_DIAG_STAT_POWER_LOW_BIT),
+};
+
+static int adis16201_probe(struct spi_device *spi)
 {
 	int ret;
-	struct adis16201_state *st;
+	struct adis *st;
 	struct iio_dev *indio_dev;
 
 	/* setup the industrialio driver allocated elements */
@@ -516,9 +191,6 @@ static int __devinit adis16201_probe(struct spi_device *spi)
 	/* this is only used for removal purposes */
 	spi_set_drvdata(spi, indio_dev);
 
-	st->us = spi;
-	mutex_init(&st->buf_lock);
-
 	indio_dev->name = spi->dev.driver->name;
 	indio_dev->dev.parent = &spi->dev;
 	indio_dev->info = &adis16201_info;
@@ -527,54 +199,38 @@ static int __devinit adis16201_probe(struct spi_device *spi)
 	indio_dev->num_channels = ARRAY_SIZE(adis16201_channels);
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = adis16201_configure_ring(indio_dev);
+	ret = adis_init(st, indio_dev, spi, &adis16201_data);
+	if (ret)
+		goto error_free_dev;
+	ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL);
 	if (ret)
 		goto error_free_dev;
-
-	ret = iio_buffer_register(indio_dev,
-				  adis16201_channels,
-				  ARRAY_SIZE(adis16201_channels));
-	if (ret) {
-		printk(KERN_ERR "failed to initialize the ring\n");
-		goto error_unreg_ring_funcs;
-	}
-
-	if (spi->irq) {
-		ret = adis16201_probe_trigger(indio_dev);
-		if (ret)
-			goto error_uninitialize_ring;
-	}
 
 	/* Get the device into a sane initial state */
-	ret = adis16201_initial_setup(indio_dev);
+	ret = adis_initial_startup(st);
 	if (ret)
-		goto error_remove_trigger;
+		goto error_cleanup_buffer_trigger;
 
 	ret = iio_device_register(indio_dev);
 	if (ret < 0)
-		goto error_remove_trigger;
+		goto error_cleanup_buffer_trigger;
 	return 0;
 
-error_remove_trigger:
-	adis16201_remove_trigger(indio_dev);
-error_uninitialize_ring:
-	iio_buffer_unregister(indio_dev);
-error_unreg_ring_funcs:
-	adis16201_unconfigure_ring(indio_dev);
+error_cleanup_buffer_trigger:
+	adis_cleanup_buffer_and_trigger(st, indio_dev);
 error_free_dev:
 	iio_device_free(indio_dev);
 error_ret:
 	return ret;
 }
 
-static int __devexit adis16201_remove(struct spi_device *spi)
+static int adis16201_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct adis *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	adis16201_remove_trigger(indio_dev);
-	iio_buffer_unregister(indio_dev);
-	adis16201_unconfigure_ring(indio_dev);
+	adis_cleanup_buffer_and_trigger(st, indio_dev);
 	iio_device_free(indio_dev);
 
 	return 0;
@@ -586,7 +242,7 @@ static struct spi_driver adis16201_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = adis16201_probe,
-	.remove = __devexit_p(adis16201_remove),
+	.remove = adis16201_remove,
 };
 module_spi_driver(adis16201_driver);
 
diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c
deleted file mode 100644
index 97c09f0..0000000
--- a/drivers/staging/iio/accel/adis16201_ring.c
+++ /dev/null
@@ -1,136 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16201.h"
-
-
-/**
- * adis16201_read_ring_data() read data registers which will be placed into ring
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @rx: somewhere to pass back the value read
- **/
-static int adis16201_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-	struct spi_message msg;
-	struct adis16201_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[ADIS16201_OUTPUTS + 1];
-	int ret;
-	int i;
-
-	mutex_lock(&st->buf_lock);
-
-	spi_message_init(&msg);
-
-	memset(xfers, 0, sizeof(xfers));
-	for (i = 0; i <= ADIS16201_OUTPUTS; i++) {
-		xfers[i].bits_per_word = 8;
-		xfers[i].cs_change = 1;
-		xfers[i].len = 2;
-		xfers[i].delay_usecs = 20;
-		if (i < ADIS16201_OUTPUTS) {
-			xfers[i].tx_buf = st->tx + 2 * i;
-			st->tx[2 * i] = ADIS16201_READ_REG(ADIS16201_SUPPLY_OUT +
-							   2 * i);
-			st->tx[2 * i + 1] = 0;
-		}
-		if (i >= 1)
-			xfers[i].rx_buf = rx + 2 * (i - 1);
-		spi_message_add_tail(&xfers[i], &msg);
-	}
-
-	ret = spi_sync(st->us, &msg);
-	if (ret)
-		dev_err(&st->us->dev, "problem when burst reading");
-
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
- * specific to be rolled into the core.
- */
-static irqreturn_t adis16201_trigger_handler(int irq, void *p)
-{
-	struct iio_poll_func *pf = p;
-	struct iio_dev *indio_dev = pf->indio_dev;
-	struct adis16201_state *st = iio_priv(indio_dev);
-
-	int i = 0;
-	s16 *data;
-
-	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(&st->us->dev, "memory alloc failed in ring bh");
-		goto done;
-	}
-
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)
-	    && adis16201_read_ring_data(indio_dev, st->rx) >= 0)
-		for (; i < bitmap_weight(indio_dev->active_scan_mask,
-					 indio_dev->masklength); i++)
-			data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp)
-		*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-	iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
-
-	kfree(data);
-done:
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-void adis16201_unconfigure_ring(struct iio_dev *indio_dev)
-{
-	iio_dealloc_pollfunc(indio_dev->pollfunc);
-	iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16201_ring_setup_ops = {
-	.preenable = &iio_sw_buffer_preenable,
-	.postenable = &iio_triggered_buffer_postenable,
-	.predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16201_configure_ring(struct iio_dev *indio_dev)
-{
-	int ret = 0;
-	struct iio_buffer *ring;
-
-	ring = iio_sw_rb_allocate(indio_dev);
-	if (!ring) {
-		ret = -ENOMEM;
-		return ret;
-	}
-	indio_dev->buffer = ring;
-	ring->scan_timestamp = true;
-	indio_dev->setup_ops = &adis16201_ring_setup_ops;
-
-	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-						 &adis16201_trigger_handler,
-						 IRQF_ONESHOT,
-						 indio_dev,
-						 "adis16201_consumer%d",
-						 indio_dev->id);
-	if (indio_dev->pollfunc == NULL) {
-		ret = -ENOMEM;
-		goto error_iio_sw_rb_free;
-	}
-
-	indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-	return 0;
-error_iio_sw_rb_free:
-	iio_sw_rb_free(indio_dev->buffer);
-	return ret;
-}
diff --git a/drivers/staging/iio/accel/adis16201_trigger.c b/drivers/staging/iio/accel/adis16201_trigger.c
deleted file mode 100644
index 96fdabb..0000000
--- a/drivers/staging/iio/accel/adis16201_trigger.c
+++ /dev/null
@@ -1,71 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16201.h"
-
-/**
- * adis16201_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16201_data_rdy_trigger_set_state(struct iio_trigger *trig,
-						bool state)
-{
-	struct iio_dev *indio_dev = trig->private_data;
-
-	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16201_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16201_trigger_ops = {
-	.owner = THIS_MODULE,
-	.set_trigger_state = &adis16201_data_rdy_trigger_set_state,
-};
-
-int adis16201_probe_trigger(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct adis16201_state *st = iio_priv(indio_dev);
-
-	st->trig = iio_trigger_alloc("adis16201-dev%d", indio_dev->id);
-	if (st->trig == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-	ret = request_irq(st->us->irq,
-			  &iio_trigger_generic_data_rdy_poll,
-			  IRQF_TRIGGER_RISING,
-			  "adis16201",
-			  st->trig);
-	if (ret)
-		goto error_free_trig;
-	st->trig->dev.parent = &st->us->dev;
-	st->trig->ops = &adis16201_trigger_ops;
-	st->trig->private_data = indio_dev;
-	ret = iio_trigger_register(st->trig);
-
-	/* select default trigger */
-	indio_dev->trig = st->trig;
-	if (ret)
-		goto error_free_irq;
-
-	return 0;
-
-error_free_irq:
-	free_irq(st->us->irq, st->trig);
-error_free_trig:
-	iio_trigger_free(st->trig);
-error_ret:
-	return ret;
-}
-
-void adis16201_remove_trigger(struct iio_dev *indio_dev)
-{
-	struct adis16201_state *state = iio_priv(indio_dev);
-
-	iio_trigger_unregister(state->trig);
-	free_irq(state->us->irq, state->trig);
-	iio_trigger_free(state->trig);
-}
diff --git a/drivers/staging/iio/accel/adis16203.h b/drivers/staging/iio/accel/adis16203.h
index 3f96ad3..acc688d 100644
--- a/drivers/staging/iio/accel/adis16203.h
+++ b/drivers/staging/iio/accel/adis16203.h
@@ -3,9 +3,6 @@
 
 #define ADIS16203_STARTUP_DELAY	220 /* ms */
 
-#define ADIS16203_READ_REG(a)    a
-#define ADIS16203_WRITE_REG(a) ((a) | 0x80)
-
 #define ADIS16203_FLASH_CNT      0x00 /* Flash memory write count */
 #define ADIS16203_SUPPLY_OUT     0x02 /* Output, power supply */
 #define ADIS16203_AUX_ADC        0x08 /* Output, auxiliary ADC input */
@@ -27,8 +24,6 @@
 #define ADIS16203_DIAG_STAT      0x3C /* Diagnostics, system status register */
 #define ADIS16203_GLOB_CMD       0x3E /* Operation, system command register */
 
-#define ADIS16203_OUTPUTS        5
-
 /* MSC_CTRL */
 #define ADIS16203_MSC_CTRL_PWRUP_SELF_TEST	(1 << 10) /* Self-test at power-on: 1 = disabled, 0 = enabled */
 #define ADIS16203_MSC_CTRL_REVERSE_ROT_EN	(1 << 9)  /* Reverses rotation of both inclination outputs */
@@ -40,86 +35,25 @@
 /* DIAG_STAT */
 #define ADIS16203_DIAG_STAT_ALARM2        (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
 #define ADIS16203_DIAG_STAT_ALARM1        (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
-#define ADIS16203_DIAG_STAT_SELFTEST_FAIL (1<<5) /* Self-test diagnostic error flag */
-#define ADIS16203_DIAG_STAT_SPI_FAIL	  (1<<3) /* SPI communications failure */
-#define ADIS16203_DIAG_STAT_FLASH_UPT	  (1<<2) /* Flash update failure */
-#define ADIS16203_DIAG_STAT_POWER_HIGH	  (1<<1) /* Power supply above 3.625 V */
-#define ADIS16203_DIAG_STAT_POWER_LOW	  (1<<0) /* Power supply below 3.15 V */
+#define ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT 5 /* Self-test diagnostic error flag */
+#define ADIS16203_DIAG_STAT_SPI_FAIL_BIT      3 /* SPI communications failure */
+#define ADIS16203_DIAG_STAT_FLASH_UPT_BIT     2 /* Flash update failure */
+#define ADIS16203_DIAG_STAT_POWER_HIGH_BIT    1 /* Power supply above 3.625 V */
+#define ADIS16203_DIAG_STAT_POWER_LOW_BIT     0 /* Power supply below 3.15 V */
 
 /* GLOB_CMD */
 #define ADIS16203_GLOB_CMD_SW_RESET	(1<<7)
 #define ADIS16203_GLOB_CMD_CLEAR_STAT	(1<<4)
 #define ADIS16203_GLOB_CMD_FACTORY_CAL	(1<<1)
 
-#define ADIS16203_MAX_TX 12
-#define ADIS16203_MAX_RX 10
-
 #define ADIS16203_ERROR_ACTIVE          (1<<14)
 
-/**
- * struct adis16203_state - device instance specific data
- * @us:			actual spi_device
- * @trig:		data ready trigger registered with iio
- * @tx:			transmit buffer
- * @rx:			receive buffer
- * @buf_lock:		mutex to protect tx and rx
- **/
-struct adis16203_state {
-	struct spi_device	*us;
-	struct iio_trigger	*trig;
-	struct mutex		buf_lock;
-	u8			tx[ADIS16203_MAX_TX] ____cacheline_aligned;
-	u8			rx[ADIS16203_MAX_RX];
-};
-
-int adis16203_set_irq(struct iio_dev *indio_dev, bool enable);
-
 enum adis16203_scan {
+	ADIS16203_SCAN_INCLI_X,
+	ADIS16203_SCAN_INCLI_Y,
 	ADIS16203_SCAN_SUPPLY,
 	ADIS16203_SCAN_AUX_ADC,
 	ADIS16203_SCAN_TEMP,
-	ADIS16203_SCAN_INCLI_X,
-	ADIS16203_SCAN_INCLI_Y,
 };
 
-#ifdef CONFIG_IIO_BUFFER
-void adis16203_remove_trigger(struct iio_dev *indio_dev);
-int adis16203_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16203_read_data_from_ring(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf);
-
-int adis16203_configure_ring(struct iio_dev *indio_dev);
-void adis16203_unconfigure_ring(struct iio_dev *indio_dev);
-
-#else /* CONFIG_IIO_BUFFER */
-
-static inline void adis16203_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16203_probe_trigger(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline ssize_t
-adis16203_read_data_from_ring(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	return 0;
-}
-
-static int adis16203_configure_ring(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline void adis16203_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-#endif /* CONFIG_IIO_BUFFER */
 #endif /* SPI_ADIS16203_H_ */
diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c
index e7b3441..8c23527 100644
--- a/drivers/staging/iio/accel/adis16203_core.c
+++ b/drivers/staging/iio/accel/adis16203_core.c
@@ -1,7 +1,7 @@
 /*
  * ADIS16203 Programmable Digital Vibration Sensor driver
  *
- * Copyright 2010 Analog Devices Inc.
+ * Copyright 2030 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -18,254 +18,14 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
 
 #include "adis16203.h"
 
 #define DRIVER_NAME		"adis16203"
 
-/**
- * adis16203_spi_write_reg_8() - write single byte to a register
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-static int adis16203_spi_write_reg_8(struct iio_dev *indio_dev,
-				     u8 reg_address,
-				     u8 val)
-{
-	int ret;
-	struct adis16203_state *st = iio_priv(indio_dev);
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16203_WRITE_REG(reg_address);
-	st->tx[1] = val;
-
-	ret = spi_write(st->us, st->tx, 2);
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/**
- * adis16203_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16203_spi_write_reg_16(struct iio_dev *indio_dev,
-				      u8 lower_reg_address,
-				      u16 value)
-{
-	int ret;
-	struct spi_message msg;
-	struct adis16203_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-		}, {
-			.tx_buf = st->tx + 2,
-			.bits_per_word = 8,
-			.len = 2,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16203_WRITE_REG(lower_reg_address);
-	st->tx[1] = value & 0xFF;
-	st->tx[2] = ADIS16203_WRITE_REG(lower_reg_address + 1);
-	st->tx[3] = (value >> 8) & 0xFF;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/**
- * adis16203_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16203_spi_read_reg_16(struct iio_dev *indio_dev,
-		u8 lower_reg_address,
-		u16 *val)
-{
-	struct spi_message msg;
-	struct adis16203_state *st = iio_priv(indio_dev);
-	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-			.delay_usecs = 20,
-		}, {
-			.rx_buf = st->rx,
-			.bits_per_word = 8,
-			.len = 2,
-			.delay_usecs = 20,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16203_READ_REG(lower_reg_address);
-	st->tx[1] = 0;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
-	if (ret) {
-		dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
-				lower_reg_address);
-		goto error_ret;
-	}
-	*val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
-}
-
-static int adis16203_check_status(struct iio_dev *indio_dev)
-{
-	u16 status;
-	int ret;
-
-	ret = adis16203_spi_read_reg_16(indio_dev,
-					ADIS16203_DIAG_STAT,
-					&status);
-	if (ret < 0) {
-		dev_err(&indio_dev->dev, "Reading status failed\n");
-		goto error_ret;
-	}
-	ret = status & 0x1F;
-
-	if (status & ADIS16203_DIAG_STAT_SELFTEST_FAIL)
-		dev_err(&indio_dev->dev, "Self test failure\n");
-	if (status & ADIS16203_DIAG_STAT_SPI_FAIL)
-		dev_err(&indio_dev->dev, "SPI failure\n");
-	if (status & ADIS16203_DIAG_STAT_FLASH_UPT)
-		dev_err(&indio_dev->dev, "Flash update failed\n");
-	if (status & ADIS16203_DIAG_STAT_POWER_HIGH)
-		dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
-	if (status & ADIS16203_DIAG_STAT_POWER_LOW)
-		dev_err(&indio_dev->dev, "Power supply below 3.15V\n");
-
-error_ret:
-	return ret;
-}
-
-static int adis16203_reset(struct iio_dev *indio_dev)
-{
-	int ret;
-	ret = adis16203_spi_write_reg_8(indio_dev,
-			ADIS16203_GLOB_CMD,
-			ADIS16203_GLOB_CMD_SW_RESET);
-	if (ret)
-		dev_err(&indio_dev->dev, "problem resetting device");
-
-	return ret;
-}
-
-int adis16203_set_irq(struct iio_dev *indio_dev, bool enable)
-{
-	int ret = 0;
-	u16 msc;
-
-	ret = adis16203_spi_read_reg_16(indio_dev, ADIS16203_MSC_CTRL, &msc);
-	if (ret)
-		goto error_ret;
-
-	msc |= ADIS16203_MSC_CTRL_ACTIVE_HIGH;
-	msc &= ~ADIS16203_MSC_CTRL_DATA_RDY_DIO1;
-	if (enable)
-		msc |= ADIS16203_MSC_CTRL_DATA_RDY_EN;
-	else
-		msc &= ~ADIS16203_MSC_CTRL_DATA_RDY_EN;
-
-	ret = adis16203_spi_write_reg_16(indio_dev, ADIS16203_MSC_CTRL, msc);
-
-error_ret:
-	return ret;
-}
-
-static int adis16203_self_test(struct iio_dev *indio_dev)
-{
-	int ret;
-	ret = adis16203_spi_write_reg_16(indio_dev,
-			ADIS16203_MSC_CTRL,
-			ADIS16203_MSC_CTRL_SELF_TEST_EN);
-	if (ret) {
-		dev_err(&indio_dev->dev, "problem starting self test");
-		goto err_ret;
-	}
-
-	adis16203_check_status(indio_dev);
-
-err_ret:
-	return ret;
-}
-
-static int adis16203_initial_setup(struct iio_dev *indio_dev)
-{
-	int ret;
-
-	/* Disable IRQ */
-	ret = adis16203_set_irq(indio_dev, false);
-	if (ret) {
-		dev_err(&indio_dev->dev, "disable irq failed");
-		goto err_ret;
-	}
-
-	/* Do self test */
-	ret = adis16203_self_test(indio_dev);
-	if (ret) {
-		dev_err(&indio_dev->dev, "self test failure");
-		goto err_ret;
-	}
-
-	/* Read status register to check the result */
-	ret = adis16203_check_status(indio_dev);
-	if (ret) {
-		adis16203_reset(indio_dev);
-		dev_err(&indio_dev->dev, "device not playing ball -> reset");
-		msleep(ADIS16203_STARTUP_DELAY);
-		ret = adis16203_check_status(indio_dev);
-		if (ret) {
-			dev_err(&indio_dev->dev, "giving up");
-			goto err_ret;
-		}
-	}
-
-err_ret:
-	return ret;
-}
-
-enum adis16203_chan {
-	in_supply,
-	in_aux,
-	incli_x,
-	incli_y,
-	temp,
-};
-
-static u8 adis16203_addresses[5][2] = {
-	[in_supply] = { ADIS16203_SUPPLY_OUT },
-	[in_aux] = { ADIS16203_AUX_ADC },
-	[incli_x] = { ADIS16203_XINCL_OUT, ADIS16203_INCL_NULL},
-	[incli_y] = { ADIS16203_YINCL_OUT },
-	[temp] = { ADIS16203_TEMP_OUT }
+static const u8 adis16203_addresses[] = {
+	[ADIS16203_SCAN_INCLI_X] = ADIS16203_INCL_NULL,
 };
 
 static int adis16203_write_raw(struct iio_dev *indio_dev,
@@ -274,9 +34,10 @@ static int adis16203_write_raw(struct iio_dev *indio_dev,
 			       int val2,
 			       long mask)
 {
+	struct adis *st = iio_priv(indio_dev);
 	/* currently only one writable parameter which keeps this simple */
-	u8 addr = adis16203_addresses[chan->address][1];
-	return adis16203_spi_write_reg_16(indio_dev, addr, val & 0x3FFF);
+	u8 addr = adis16203_addresses[chan->scan_index];
+	return adis_write_reg_16(st, addr, val & 0x3FFF);
 }
 
 static int adis16203_read_raw(struct iio_dev *indio_dev,
@@ -284,35 +45,15 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
 			      int *val, int *val2,
 			      long mask)
 {
+	struct adis *st = iio_priv(indio_dev);
 	int ret;
 	int bits;
 	u8 addr;
 	s16 val16;
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
-		mutex_lock(&indio_dev->mlock);
-		addr = adis16203_addresses[chan->address][0];
-		ret = adis16203_spi_read_reg_16(indio_dev, addr, &val16);
-		if (ret) {
-			mutex_unlock(&indio_dev->mlock);
-			return ret;
-		}
-
-		if (val16 & ADIS16203_ERROR_ACTIVE) {
-			ret = adis16203_check_status(indio_dev);
-			if (ret) {
-				mutex_unlock(&indio_dev->mlock);
-				return ret;
-			}
-		}
-		val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
-		if (chan->scan_type.sign == 's')
-			val16 = (s16)(val16 <<
-				      (16 - chan->scan_type.realbits)) >>
-				(16 - chan->scan_type.realbits);
-		*val = val16;
-		mutex_unlock(&indio_dev->mlock);
-		return IIO_VAL_INT;
+		return adis_single_conversion(indio_dev, chan,
+				ADIS16203_ERROR_ACTIVE, val);
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->type) {
 		case IIO_VOLTAGE:
@@ -341,8 +82,8 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
 	case IIO_CHAN_INFO_CALIBBIAS:
 		bits = 14;
 		mutex_lock(&indio_dev->mlock);
-		addr = adis16203_addresses[chan->address][1];
-		ret = adis16203_spi_read_reg_16(indio_dev, addr, &val16);
+		addr = adis16203_addresses[chan->scan_index];
+		ret = adis_read_reg_16(st, addr, &val16);
 		if (ret) {
 			mutex_unlock(&indio_dev->mlock);
 			return ret;
@@ -358,89 +99,53 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
 }
 
 static const struct iio_chan_spec adis16203_channels[] = {
-	{
-		.type = IIO_VOLTAGE,
-		.indexed = 1,
-		.channel = 0,
-		.extend_name = "supply",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-		.address = in_supply,
-		.scan_index = ADIS16203_SCAN_SUPPLY,
-		.scan_type = {
-			.sign = 'u',
-			.realbits = 12,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_VOLTAGE,
-		.indexed = 1,
-		.channel = 1,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-		.address = in_aux,
-		.scan_index = ADIS16203_SCAN_AUX_ADC,
-		.scan_type = {
-			.sign = 'u',
-			.realbits = 12,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_INCLI,
-		.modified = 1,
-		.channel2 = IIO_MOD_X,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
-		.address = incli_x,
-		.scan_index = ADIS16203_SCAN_INCLI_X,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 14,
-			.storagebits = 16,
-		},
-	}, { /* Fixme: Not what it appears to be - see data sheet */
-		.type = IIO_INCLI,
-		.modified = 1,
-		.channel2 = IIO_MOD_Y,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT,
-		.address = incli_y,
-		.scan_index = ADIS16203_SCAN_INCLI_Y,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 14,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_TEMP,
-		.indexed = 1,
-		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
-		.address = temp,
-		.scan_index = ADIS16203_SCAN_TEMP,
-		.scan_type = {
-			.sign = 'u',
-			.realbits = 12,
-			.storagebits = 16,
-		},
-	},
+	ADIS_SUPPLY_CHAN(ADIS16203_SUPPLY_OUT, ADIS16203_SCAN_SUPPLY, 12),
+	ADIS_AUX_ADC_CHAN(ADIS16203_AUX_ADC, ADIS16203_SCAN_AUX_ADC, 12),
+	ADIS_INCLI_CHAN(X, ADIS16203_XINCL_OUT, ADIS16203_SCAN_INCLI_X,
+		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+	/* Fixme: Not what it appears to be - see data sheet */
+	ADIS_INCLI_CHAN(Y, ADIS16203_YINCL_OUT, ADIS16203_SCAN_INCLI_Y, 0, 14),
+	ADIS_TEMP_CHAN(ADIS16203_TEMP_OUT, ADIS16203_SCAN_TEMP, 12),
 	IIO_CHAN_SOFT_TIMESTAMP(5),
 };
 
 static const struct iio_info adis16203_info = {
 	.read_raw = &adis16203_read_raw,
 	.write_raw = &adis16203_write_raw,
+	.update_scan_mode = adis_update_scan_mode,
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit adis16203_probe(struct spi_device *spi)
+static const char * const adis16203_status_error_msgs[] = {
+	[ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT] = "Self test failure",
+	[ADIS16203_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
+	[ADIS16203_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
+	[ADIS16203_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
+	[ADIS16203_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V",
+};
+
+static const struct adis_data adis16203_data = {
+	.read_delay = 20,
+	.msc_ctrl_reg = ADIS16203_MSC_CTRL,
+	.glob_cmd_reg = ADIS16203_GLOB_CMD,
+	.diag_stat_reg = ADIS16203_DIAG_STAT,
+
+	.self_test_mask = ADIS16203_MSC_CTRL_SELF_TEST_EN,
+	.startup_delay = ADIS16203_STARTUP_DELAY,
+
+	.status_error_msgs = adis16203_status_error_msgs,
+	.status_error_mask = BIT(ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT) |
+		BIT(ADIS16203_DIAG_STAT_SPI_FAIL_BIT) |
+		BIT(ADIS16203_DIAG_STAT_FLASH_UPT_BIT) |
+		BIT(ADIS16203_DIAG_STAT_POWER_HIGH_BIT) |
+		BIT(ADIS16203_DIAG_STAT_POWER_LOW_BIT),
+};
+
+static int adis16203_probe(struct spi_device *spi)
 {
 	int ret;
 	struct iio_dev *indio_dev;
-	struct adis16203_state *st;
+	struct adis *st;
 
 	/* setup the industrialio driver allocated elements */
 	indio_dev = iio_device_alloc(sizeof(*st));
@@ -451,8 +156,6 @@ static int __devinit adis16203_probe(struct spi_device *spi)
 	st = iio_priv(indio_dev);
 	/* this is only used for removal purposes */
 	spi_set_drvdata(spi, indio_dev);
-	st->us = spi;
-	mutex_init(&st->buf_lock);
 
 	indio_dev->name = spi->dev.driver->name;
 	indio_dev->dev.parent = &spi->dev;
@@ -461,55 +164,40 @@ static int __devinit adis16203_probe(struct spi_device *spi)
 	indio_dev->info = &adis16203_info;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = adis16203_configure_ring(indio_dev);
+	ret = adis_init(st, indio_dev, spi, &adis16203_data);
 	if (ret)
 		goto error_free_dev;
 
-	ret = iio_buffer_register(indio_dev,
-				  adis16203_channels,
-				  ARRAY_SIZE(adis16203_channels));
-	if (ret) {
-		printk(KERN_ERR "failed to initialize the ring\n");
-		goto error_unreg_ring_funcs;
-	}
-
-	if (spi->irq) {
-		ret = adis16203_probe_trigger(indio_dev);
-		if (ret)
-			goto error_uninitialize_ring;
-	}
+	ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL);
+	if (ret)
+		goto error_free_dev;
 
 	/* Get the device into a sane initial state */
-	ret = adis16203_initial_setup(indio_dev);
+	ret = adis_initial_startup(st);
 	if (ret)
-		goto error_remove_trigger;
+		goto error_cleanup_buffer_trigger;
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_remove_trigger;
+		goto error_cleanup_buffer_trigger;
 
 	return 0;
 
-error_remove_trigger:
-	adis16203_remove_trigger(indio_dev);
-error_uninitialize_ring:
-	iio_buffer_unregister(indio_dev);
-error_unreg_ring_funcs:
-	adis16203_unconfigure_ring(indio_dev);
+error_cleanup_buffer_trigger:
+	adis_cleanup_buffer_and_trigger(st, indio_dev);
 error_free_dev:
 	iio_device_free(indio_dev);
 error_ret:
 	return ret;
 }
 
-static int __devexit adis16203_remove(struct spi_device *spi)
+static int adis16203_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct adis *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	adis16203_remove_trigger(indio_dev);
-	iio_buffer_unregister(indio_dev);
-	adis16203_unconfigure_ring(indio_dev);
+	adis_cleanup_buffer_and_trigger(st, indio_dev);
 	iio_device_free(indio_dev);
 
 	return 0;
@@ -521,7 +209,7 @@ static struct spi_driver adis16203_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = adis16203_probe,
-	.remove = __devexit_p(adis16203_remove),
+	.remove = adis16203_remove,
 };
 module_spi_driver(adis16203_driver);
 
diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c
deleted file mode 100644
index 7507e1a..0000000
--- a/drivers/staging/iio/accel/adis16203_ring.c
+++ /dev/null
@@ -1,136 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16203.h"
-
-/**
- * adis16203_read_ring_data() read data registers which will be placed into ring
- * @indio_dev: the IIO device
- * @rx: somewhere to pass back the value read
- **/
-static int adis16203_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-	struct spi_message msg;
-	struct adis16203_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[ADIS16203_OUTPUTS + 1];
-	int ret;
-	int i;
-
-	mutex_lock(&st->buf_lock);
-
-	spi_message_init(&msg);
-
-	memset(xfers, 0, sizeof(xfers));
-	for (i = 0; i <= ADIS16203_OUTPUTS; i++) {
-		xfers[i].bits_per_word = 8;
-		xfers[i].cs_change = 1;
-		xfers[i].len = 2;
-		xfers[i].delay_usecs = 20;
-		xfers[i].tx_buf = st->tx + 2 * i;
-		if (i < 1) /* SUPPLY_OUT: 0x02, AUX_ADC: 0x08 */
-			st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i);
-		else
-			st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i + 6);
-		st->tx[2 * i + 1] = 0;
-		if (i >= 1)
-			xfers[i].rx_buf = rx + 2 * (i - 1);
-		spi_message_add_tail(&xfers[i], &msg);
-	}
-
-	ret = spi_sync(st->us, &msg);
-	if (ret)
-		dev_err(&st->us->dev, "problem when burst reading");
-
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
- * specific to be rolled into the core.
- */
-static irqreturn_t adis16203_trigger_handler(int irq, void *p)
-{
-	struct iio_poll_func *pf = p;
-	struct iio_dev *indio_dev = pf->indio_dev;
-	struct adis16203_state *st = iio_priv(indio_dev);
-
-	int i = 0;
-	s16 *data;
-
-	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(&st->us->dev, "memory alloc failed in ring bh");
-		goto done;
-	}
-
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
-	    adis16203_read_ring_data(indio_dev, st->rx) >= 0)
-		for (; i < bitmap_weight(indio_dev->active_scan_mask,
-					 indio_dev->masklength); i++)
-			data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp)
-		*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-	iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
-
-	kfree(data);
-done:
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-void adis16203_unconfigure_ring(struct iio_dev *indio_dev)
-{
-	iio_dealloc_pollfunc(indio_dev->pollfunc);
-	iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16203_ring_setup_ops = {
-	.preenable = &iio_sw_buffer_preenable,
-	.postenable = &iio_triggered_buffer_postenable,
-	.predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16203_configure_ring(struct iio_dev *indio_dev)
-{
-	int ret = 0;
-	struct iio_buffer *ring;
-
-	ring = iio_sw_rb_allocate(indio_dev);
-	if (!ring) {
-		ret = -ENOMEM;
-		return ret;
-	}
-	indio_dev->buffer = ring;
-	ring->scan_timestamp = true;
-	indio_dev->setup_ops = &adis16203_ring_setup_ops;
-
-	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-						 &adis16203_trigger_handler,
-						 IRQF_ONESHOT,
-						 indio_dev,
-						 "adis16203_consumer%d",
-						 indio_dev->id);
-	if (indio_dev->pollfunc == NULL) {
-		ret = -ENOMEM;
-		goto error_iio_sw_rb_free;
-	}
-
-	indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-	return 0;
-
-error_iio_sw_rb_free:
-	iio_sw_rb_free(indio_dev->buffer);
-	return ret;
-}
diff --git a/drivers/staging/iio/accel/adis16203_trigger.c b/drivers/staging/iio/accel/adis16203_trigger.c
deleted file mode 100644
index b8a0407..0000000
--- a/drivers/staging/iio/accel/adis16203_trigger.c
+++ /dev/null
@@ -1,73 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16203.h"
-
-/**
- * adis16203_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16203_data_rdy_trigger_set_state(struct iio_trigger *trig,
-						bool state)
-{
-	struct iio_dev *indio_dev = trig->private_data;
-
-	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16203_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16203_trigger_ops = {
-	.owner = THIS_MODULE,
-	.set_trigger_state = &adis16203_data_rdy_trigger_set_state,
-};
-
-int adis16203_probe_trigger(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct adis16203_state *st = iio_priv(indio_dev);
-
-	st->trig = iio_trigger_alloc("adis16203-dev%d", indio_dev->id);
-	if (st->trig == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-
-	ret = request_irq(st->us->irq,
-			  &iio_trigger_generic_data_rdy_poll,
-			  IRQF_TRIGGER_RISING,
-			  "adis16203",
-			  st->trig);
-	if (ret)
-		goto error_free_trig;
-
-	st->trig->dev.parent = &st->us->dev;
-	st->trig->ops = &adis16203_trigger_ops;
-	st->trig->private_data = indio_dev;
-	ret = iio_trigger_register(st->trig);
-
-	/* select default trigger */
-	indio_dev->trig = st->trig;
-	if (ret)
-		goto error_free_irq;
-
-	return 0;
-
-error_free_irq:
-	free_irq(st->us->irq, st->trig);
-error_free_trig:
-	iio_trigger_free(st->trig);
-error_ret:
-	return ret;
-}
-
-void adis16203_remove_trigger(struct iio_dev *indio_dev)
-{
-	struct adis16203_state *st = iio_priv(indio_dev);
-
-	iio_trigger_unregister(st->trig);
-	free_irq(st->us->irq, st->trig);
-	iio_trigger_free(st->trig);
-}
diff --git a/drivers/staging/iio/accel/adis16204.h b/drivers/staging/iio/accel/adis16204.h
index 7cf4e91..9ff950c 100644
--- a/drivers/staging/iio/accel/adis16204.h
+++ b/drivers/staging/iio/accel/adis16204.h
@@ -3,9 +3,6 @@
 
 #define ADIS16204_STARTUP_DELAY	220 /* ms */
 
-#define ADIS16204_READ_REG(a)    a
-#define ADIS16204_WRITE_REG(a) ((a) | 0x80)
-
 #define ADIS16204_FLASH_CNT      0x00 /* Flash memory write count */
 #define ADIS16204_SUPPLY_OUT     0x02 /* Output, power supply */
 #define ADIS16204_XACCL_OUT      0x04 /* Output, x-axis accelerometer */
@@ -35,8 +32,6 @@
 #define ADIS16204_DIAG_STAT      0x3C /* Diagnostics, system status register */
 #define ADIS16204_GLOB_CMD       0x3E /* Operation, system command register */
 
-#define ADIS16204_OUTPUTS        5
-
 /* MSC_CTRL */
 #define ADIS16204_MSC_CTRL_PWRUP_SELF_TEST	(1 << 10) /* Self-test at power-on: 1 = disabled, 0 = enabled */
 #define ADIS16204_MSC_CTRL_SELF_TEST_EN	        (1 << 8)  /* Self-test enable */
@@ -47,87 +42,27 @@
 /* DIAG_STAT */
 #define ADIS16204_DIAG_STAT_ALARM2        (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
 #define ADIS16204_DIAG_STAT_ALARM1        (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
-#define ADIS16204_DIAG_STAT_SELFTEST_FAIL (1<<5) /* Self-test diagnostic error flag: 1 = error condition,
+#define ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT 5 /* Self-test diagnostic error flag: 1 = error condition,
 						0 = normal operation */
-#define ADIS16204_DIAG_STAT_SPI_FAIL	  (1<<3) /* SPI communications failure */
-#define ADIS16204_DIAG_STAT_FLASH_UPT	  (1<<2) /* Flash update failure */
-#define ADIS16204_DIAG_STAT_POWER_HIGH	  (1<<1) /* Power supply above 3.625 V */
-#define ADIS16204_DIAG_STAT_POWER_LOW	  (1<<0) /* Power supply below 2.975 V */
+#define ADIS16204_DIAG_STAT_SPI_FAIL_BIT      3 /* SPI communications failure */
+#define ADIS16204_DIAG_STAT_FLASH_UPT_BIT     2 /* Flash update failure */
+#define ADIS16204_DIAG_STAT_POWER_HIGH_BIT    1 /* Power supply above 3.625 V */
+#define ADIS16204_DIAG_STAT_POWER_LOW_BIT     0 /* Power supply below 2.975 V */
 
 /* GLOB_CMD */
 #define ADIS16204_GLOB_CMD_SW_RESET	(1<<7)
 #define ADIS16204_GLOB_CMD_CLEAR_STAT	(1<<4)
 #define ADIS16204_GLOB_CMD_FACTORY_CAL	(1<<1)
 
-#define ADIS16204_MAX_TX 24
-#define ADIS16204_MAX_RX 24
-
 #define ADIS16204_ERROR_ACTIVE          (1<<14)
 
-/**
- * struct adis16204_state - device instance specific data
- * @us:			actual spi_device
- * @trig:		data ready trigger registered with iio
- * @tx:			transmit buffer
- * @rx:			receive buffer
- * @buf_lock:		mutex to protect tx and rx
- **/
-struct adis16204_state {
-	struct spi_device	*us;
-	struct iio_trigger	*trig;
-	struct mutex		buf_lock;
-	u8			tx[ADIS16204_MAX_TX] ____cacheline_aligned;
-	u8			rx[ADIS16204_MAX_RX];
-};
-
-int adis16204_set_irq(struct iio_dev *indio_dev, bool enable);
-
 enum adis16204_scan {
-	ADIS16204_SCAN_SUPPLY,
 	ADIS16204_SCAN_ACC_X,
 	ADIS16204_SCAN_ACC_Y,
+	ADIS16204_SCAN_ACC_XY,
+	ADIS16204_SCAN_SUPPLY,
 	ADIS16204_SCAN_AUX_ADC,
 	ADIS16204_SCAN_TEMP,
 };
 
-#ifdef CONFIG_IIO_BUFFER
-void adis16204_remove_trigger(struct iio_dev *indio_dev);
-int adis16204_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16204_read_data_from_ring(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf);
-
-int adis16204_configure_ring(struct iio_dev *indio_dev);
-void adis16204_unconfigure_ring(struct iio_dev *indio_dev);
-
-#else /* CONFIG_IIO_BUFFER */
-
-static inline void adis16204_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16204_probe_trigger(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline ssize_t
-adis16204_read_data_from_ring(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	return 0;
-}
-
-static int adis16204_configure_ring(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline void adis16204_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-#endif /* CONFIG_IIO_BUFFER */
 #endif /* SPI_ADIS16204_H_ */
diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
index c6234c2..f359266 100644
--- a/drivers/staging/iio/accel/adis16204_core.c
+++ b/drivers/staging/iio/accel/adis16204_core.c
@@ -21,261 +21,16 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
 
 #include "adis16204.h"
 
-#define DRIVER_NAME		"adis16204"
-
-/**
- * adis16204_spi_write_reg_8() - write single byte to a register
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-static int adis16204_spi_write_reg_8(struct iio_dev *indio_dev,
-		u8 reg_address,
-		u8 val)
-{
-	int ret;
-	struct adis16204_state *st = iio_priv(indio_dev);
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16204_WRITE_REG(reg_address);
-	st->tx[1] = val;
-
-	ret = spi_write(st->us, st->tx, 2);
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/**
- * adis16204_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16204_spi_write_reg_16(struct iio_dev *indio_dev,
-		u8 lower_reg_address,
-		u16 value)
-{
-	int ret;
-	struct spi_message msg;
-	struct adis16204_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-		}, {
-			.tx_buf = st->tx + 2,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16204_WRITE_REG(lower_reg_address);
-	st->tx[1] = value & 0xFF;
-	st->tx[2] = ADIS16204_WRITE_REG(lower_reg_address + 1);
-	st->tx[3] = (value >> 8) & 0xFF;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/**
- * adis16204_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16204_spi_read_reg_16(struct iio_dev *indio_dev,
-				     u8 lower_reg_address,
-				     u16 *val)
-{
-	struct spi_message msg;
-	struct adis16204_state *st = iio_priv(indio_dev);
-	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-			.delay_usecs = 20,
-		}, {
-			.rx_buf = st->rx,
-			.bits_per_word = 8,
-			.len = 2,
-			.delay_usecs = 20,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16204_READ_REG(lower_reg_address);
-	st->tx[1] = 0;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
-	if (ret) {
-		dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
-				lower_reg_address);
-		goto error_ret;
-	}
-	*val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
-}
-
-static int adis16204_check_status(struct iio_dev *indio_dev)
-{
-	u16 status;
-	int ret;
-
-	ret = adis16204_spi_read_reg_16(indio_dev,
-					ADIS16204_DIAG_STAT, &status);
-	if (ret < 0) {
-		dev_err(&indio_dev->dev, "Reading status failed\n");
-		goto error_ret;
-	}
-	ret = status & 0x1F;
-
-	if (status & ADIS16204_DIAG_STAT_SELFTEST_FAIL)
-		dev_err(&indio_dev->dev, "Self test failure\n");
-	if (status & ADIS16204_DIAG_STAT_SPI_FAIL)
-		dev_err(&indio_dev->dev, "SPI failure\n");
-	if (status & ADIS16204_DIAG_STAT_FLASH_UPT)
-		dev_err(&indio_dev->dev, "Flash update failed\n");
-	if (status & ADIS16204_DIAG_STAT_POWER_HIGH)
-		dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
-	if (status & ADIS16204_DIAG_STAT_POWER_LOW)
-		dev_err(&indio_dev->dev, "Power supply below 2.975V\n");
-
-error_ret:
-	return ret;
-}
-
-static int adis16204_reset(struct iio_dev *indio_dev)
-{
-	int ret;
-	ret = adis16204_spi_write_reg_8(indio_dev,
-			ADIS16204_GLOB_CMD,
-			ADIS16204_GLOB_CMD_SW_RESET);
-	if (ret)
-		dev_err(&indio_dev->dev, "problem resetting device");
-
-	return ret;
-}
-
-int adis16204_set_irq(struct iio_dev *indio_dev, bool enable)
-{
-	int ret = 0;
-	u16 msc;
-
-	ret = adis16204_spi_read_reg_16(indio_dev, ADIS16204_MSC_CTRL, &msc);
-	if (ret)
-		goto error_ret;
-
-	msc |= ADIS16204_MSC_CTRL_ACTIVE_HIGH;
-	msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_DIO2;
-	if (enable)
-		msc |= ADIS16204_MSC_CTRL_DATA_RDY_EN;
-	else
-		msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_EN;
-
-	ret = adis16204_spi_write_reg_16(indio_dev, ADIS16204_MSC_CTRL, msc);
-
-error_ret:
-	return ret;
-}
-
-static int adis16204_self_test(struct iio_dev *indio_dev)
-{
-	int ret;
-	ret = adis16204_spi_write_reg_16(indio_dev,
-			ADIS16204_MSC_CTRL,
-			ADIS16204_MSC_CTRL_SELF_TEST_EN);
-	if (ret) {
-		dev_err(&indio_dev->dev, "problem starting self test");
-		goto err_ret;
-	}
-
-	adis16204_check_status(indio_dev);
-
-err_ret:
-	return ret;
-}
-
-static int adis16204_initial_setup(struct iio_dev *indio_dev)
-{
-	int ret;
-
-	/* Disable IRQ */
-	ret = adis16204_set_irq(indio_dev, false);
-	if (ret) {
-		dev_err(&indio_dev->dev, "disable irq failed");
-		goto err_ret;
-	}
-
-	/* Do self test */
-	ret = adis16204_self_test(indio_dev);
-	if (ret) {
-		dev_err(&indio_dev->dev, "self test failure");
-		goto err_ret;
-	}
-
-	/* Read status register to check the result */
-	ret = adis16204_check_status(indio_dev);
-	if (ret) {
-		adis16204_reset(indio_dev);
-		dev_err(&indio_dev->dev, "device not playing ball -> reset");
-		msleep(ADIS16204_STARTUP_DELAY);
-		ret = adis16204_check_status(indio_dev);
-		if (ret) {
-			dev_err(&indio_dev->dev, "giving up");
-			goto err_ret;
-		}
-	}
-
-err_ret:
-	return ret;
-}
-
 /* Unique to this driver currently */
 
-enum adis16204_channel {
-	in_supply,
-	in_aux,
-	temp,
-	accel_x,
-	accel_y,
-	accel_xy,
-};
-
-static u8 adis16204_addresses[6][3] = {
-	[in_supply] = { ADIS16204_SUPPLY_OUT },
-	[in_aux] = { ADIS16204_AUX_ADC },
-	[temp] = { ADIS16204_TEMP_OUT },
-	[accel_x] = { ADIS16204_XACCL_OUT, ADIS16204_XACCL_NULL,
-		      ADIS16204_X_PEAK_OUT },
-	[accel_y] = { ADIS16204_XACCL_OUT, ADIS16204_YACCL_NULL,
-		      ADIS16204_Y_PEAK_OUT },
-	[accel_xy] = { ADIS16204_XY_RSS_OUT, 0,
-		       ADIS16204_XY_PEAK_OUT },
+static const u8 adis16204_addresses[][2] = {
+	[ADIS16204_SCAN_ACC_X] = { ADIS16204_XACCL_NULL, ADIS16204_X_PEAK_OUT },
+	[ADIS16204_SCAN_ACC_Y] = { ADIS16204_YACCL_NULL, ADIS16204_Y_PEAK_OUT },
+	[ADIS16204_SCAN_ACC_XY] = { 0, ADIS16204_XY_PEAK_OUT },
 };
 
 static int adis16204_read_raw(struct iio_dev *indio_dev,
@@ -283,6 +38,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
 			      int *val, int *val2,
 			      long mask)
 {
+	struct adis *st = iio_priv(indio_dev);
 	int ret;
 	int bits;
 	u8 addr;
@@ -291,29 +47,8 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
-		mutex_lock(&indio_dev->mlock);
-		addr = adis16204_addresses[chan->address][0];
-		ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16);
-		if (ret) {
-			mutex_unlock(&indio_dev->mlock);
-			return ret;
-		}
-
-		if (val16 & ADIS16204_ERROR_ACTIVE) {
-			ret = adis16204_check_status(indio_dev);
-			if (ret) {
-				mutex_unlock(&indio_dev->mlock);
-				return ret;
-			}
-		}
-		val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
-		if (chan->scan_type.sign == 's')
-			val16 = (s16)(val16 <<
-				      (16 - chan->scan_type.realbits)) >>
-				(16 - chan->scan_type.realbits);
-		*val = val16;
-		mutex_unlock(&indio_dev->mlock);
-		return IIO_VAL_INT;
+		return adis_single_conversion(indio_dev, chan,
+				ADIS16204_ERROR_ACTIVE, val);
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->type) {
 		case IIO_VOLTAGE:
@@ -353,14 +88,14 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
 	case IIO_CHAN_INFO_PEAK:
 		if (mask == IIO_CHAN_INFO_CALIBBIAS) {
 			bits = 12;
-			addrind = 1;
+			addrind = 0;
 		} else { /* PEAK_SEPARATE */
 			bits = 14;
-			addrind = 2;
+			addrind = 1;
 		}
 		mutex_lock(&indio_dev->mlock);
-		addr = adis16204_addresses[chan->address][addrind];
-		ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16);
+		addr = adis16204_addresses[chan->scan_index][addrind];
+		ret = adis_read_reg_16(st, addr, &val16);
 		if (ret) {
 			mutex_unlock(&indio_dev->mlock);
 			return ret;
@@ -380,6 +115,7 @@ static int adis16204_write_raw(struct iio_dev *indio_dev,
 			       int val2,
 			       long mask)
 {
+	struct adis *st = iio_priv(indio_dev);
 	int bits;
 	s16 val16;
 	u8 addr;
@@ -391,114 +127,65 @@ static int adis16204_write_raw(struct iio_dev *indio_dev,
 			break;
 		default:
 			return -EINVAL;
-		};
+		}
 		val16 = val & ((1 << bits) - 1);
-		addr = adis16204_addresses[chan->address][1];
-		return adis16204_spi_write_reg_16(indio_dev, addr, val16);
+		addr = adis16204_addresses[chan->scan_index][1];
+		return adis_write_reg_16(st, addr, val16);
 	}
 	return -EINVAL;
 }
 
 static const struct iio_chan_spec adis16204_channels[] = {
-	{
-		.type = IIO_VOLTAGE,
-		.indexed = 1, /* Note was not previously indexed */
-		.channel = 0,
-		.extend_name = "supply",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-		.address = in_supply,
-		.scan_index = ADIS16204_SCAN_SUPPLY,
-		.scan_type = {
-			.sign = 'u',
-			.realbits = 12,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_VOLTAGE,
-		.indexed = 1,
-		.channel = 1,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-		.address = in_aux,
-		.scan_index = ADIS16204_SCAN_AUX_ADC,
-		.scan_type = {
-			.sign = 'u',
-			.realbits = 12,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_TEMP,
-		.indexed = 1,
-		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
-		.address = temp,
-		.scan_index = ADIS16204_SCAN_TEMP,
-		.scan_type = {
-			.sign = 'u',
-			.realbits = 12,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_ACCEL,
-		.modified = 1,
-		.channel2 = IIO_MOD_X,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+	ADIS_SUPPLY_CHAN(ADIS16204_SUPPLY_OUT, ADIS16204_SCAN_SUPPLY, 12),
+	ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 12),
+	ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 12),
+	ADIS_ACCEL_CHAN(X, ADIS16204_XACCL_OUT, ADIS16204_SCAN_ACC_X,
 		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-		IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
-		.address = accel_x,
-		.scan_index = ADIS16204_SCAN_ACC_X,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 14,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_ACCEL,
-		.modified = 1,
-		.channel2 = IIO_MOD_Y,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+		IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 14),
+	ADIS_ACCEL_CHAN(Y, ADIS16204_YACCL_OUT, ADIS16204_SCAN_ACC_Y,
 		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-		IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
-		.address = accel_y,
-		.scan_index = ADIS16204_SCAN_ACC_Y,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 14,
-			.storagebits = 16,
-		},
-	},
+		IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 14),
+	ADIS_ACCEL_CHAN(ROOT_SUM_SQUARED_X_Y, ADIS16204_XY_RSS_OUT,
+		ADIS16204_SCAN_ACC_XY, IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 14),
 	IIO_CHAN_SOFT_TIMESTAMP(5),
-	{
-		.type = IIO_ACCEL,
-		.modified = 1,
-		.channel2 = IIO_MOD_ROOT_SUM_SQUARED_X_Y,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-		IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
-		.address = accel_xy,
-		.scan_type = {
-			.sign = 'u',
-			.realbits = 14,
-			.storagebits = 16,
-		},
-	}
 };
 
 static const struct iio_info adis16204_info = {
 	.read_raw = &adis16204_read_raw,
 	.write_raw = &adis16204_write_raw,
+	.update_scan_mode = adis_update_scan_mode,
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit adis16204_probe(struct spi_device *spi)
+static const char * const adis16204_status_error_msgs[] = {
+	[ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT] = "Self test failure",
+	[ADIS16204_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
+	[ADIS16204_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
+	[ADIS16204_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
+	[ADIS16204_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.975V",
+};
+
+static const struct adis_data adis16204_data = {
+	.read_delay = 20,
+	.msc_ctrl_reg = ADIS16204_MSC_CTRL,
+	.glob_cmd_reg = ADIS16204_GLOB_CMD,
+	.diag_stat_reg = ADIS16204_DIAG_STAT,
+
+	.self_test_mask = ADIS16204_MSC_CTRL_SELF_TEST_EN,
+	.startup_delay = ADIS16204_STARTUP_DELAY,
+
+	.status_error_msgs = adis16204_status_error_msgs,
+	.status_error_mask = BIT(ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT) |
+		BIT(ADIS16204_DIAG_STAT_SPI_FAIL_BIT) |
+		BIT(ADIS16204_DIAG_STAT_FLASH_UPT_BIT) |
+		BIT(ADIS16204_DIAG_STAT_POWER_HIGH_BIT) |
+		BIT(ADIS16204_DIAG_STAT_POWER_LOW_BIT),
+};
+
+static int adis16204_probe(struct spi_device *spi)
 {
 	int ret;
-	struct adis16204_state *st;
+	struct adis *st;
 	struct iio_dev *indio_dev;
 
 	/* setup the industrialio driver allocated elements */
@@ -510,8 +197,6 @@ static int __devinit adis16204_probe(struct spi_device *spi)
 	st = iio_priv(indio_dev);
 	/* this is only used for removal purposes */
 	spi_set_drvdata(spi, indio_dev);
-	st->us = spi;
-	mutex_init(&st->buf_lock);
 
 	indio_dev->name = spi->dev.driver->name;
 	indio_dev->dev.parent = &spi->dev;
@@ -520,54 +205,39 @@ static int __devinit adis16204_probe(struct spi_device *spi)
 	indio_dev->num_channels = ARRAY_SIZE(adis16204_channels);
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = adis16204_configure_ring(indio_dev);
+	ret = adis_init(st, indio_dev, spi, &adis16204_data);
 	if (ret)
 		goto error_free_dev;
 
-	ret = iio_buffer_register(indio_dev,
-				  adis16204_channels,
-				  6);
-	if (ret) {
-		printk(KERN_ERR "failed to initialize the ring\n");
-		goto error_unreg_ring_funcs;
-	}
-
-	if (spi->irq) {
-		ret = adis16204_probe_trigger(indio_dev);
-		if (ret)
-			goto error_uninitialize_ring;
-	}
+	ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL);
+	if (ret)
+		goto error_free_dev;
 
 	/* Get the device into a sane initial state */
-	ret = adis16204_initial_setup(indio_dev);
+	ret = adis_initial_startup(st);
 	if (ret)
-		goto error_remove_trigger;
+		goto error_cleanup_buffer_trigger;
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_remove_trigger;
+		goto error_cleanup_buffer_trigger;
 
 	return 0;
 
-error_remove_trigger:
-	adis16204_remove_trigger(indio_dev);
-error_uninitialize_ring:
-	iio_buffer_unregister(indio_dev);
-error_unreg_ring_funcs:
-	adis16204_unconfigure_ring(indio_dev);
+error_cleanup_buffer_trigger:
+	adis_cleanup_buffer_and_trigger(st, indio_dev);
 error_free_dev:
 	iio_device_free(indio_dev);
 error_ret:
 	return ret;
 }
 
-static int __devexit adis16204_remove(struct spi_device *spi)
+static int adis16204_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct adis *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	adis16204_remove_trigger(indio_dev);
-	iio_buffer_unregister(indio_dev);
-	adis16204_unconfigure_ring(indio_dev);
+	adis_cleanup_buffer_and_trigger(st, indio_dev);
 	iio_device_free(indio_dev);
 
 	return 0;
@@ -579,7 +249,7 @@ static struct spi_driver adis16204_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = adis16204_probe,
-	.remove = __devexit_p(adis16204_remove),
+	.remove = adis16204_remove,
 };
 module_spi_driver(adis16204_driver);
 
diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c
deleted file mode 100644
index 4c976be..0000000
--- a/drivers/staging/iio/accel/adis16204_ring.c
+++ /dev/null
@@ -1,134 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16204.h"
-
-/**
- * adis16204_read_ring_data() read data registers which will be placed into ring
- * @indio_dev: the IIO device
- * @rx: somewhere to pass back the value read
- **/
-static int adis16204_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-	struct spi_message msg;
-	struct adis16204_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[ADIS16204_OUTPUTS + 1];
-	int ret;
-	int i;
-
-	mutex_lock(&st->buf_lock);
-
-	spi_message_init(&msg);
-
-	memset(xfers, 0, sizeof(xfers));
-	for (i = 0; i <= ADIS16204_OUTPUTS; i++) {
-		xfers[i].bits_per_word = 8;
-		xfers[i].cs_change = 1;
-		xfers[i].len = 2;
-		xfers[i].delay_usecs = 20;
-		xfers[i].tx_buf = st->tx + 2 * i;
-		st->tx[2 * i]
-			= ADIS16204_READ_REG(ADIS16204_SUPPLY_OUT + 2 * i);
-		st->tx[2 * i + 1] = 0;
-		if (i >= 1)
-			xfers[i].rx_buf = rx + 2 * (i - 1);
-		spi_message_add_tail(&xfers[i], &msg);
-	}
-
-	ret = spi_sync(st->us, &msg);
-	if (ret)
-		dev_err(&st->us->dev, "problem when burst reading");
-
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
- * specific to be rolled into the core.
- */
-static irqreturn_t adis16204_trigger_handler(int irq, void *p)
-{
-	struct iio_poll_func *pf = p;
-	struct iio_dev *indio_dev = pf->indio_dev;
-	struct adis16204_state *st = iio_priv(indio_dev);
-	int i = 0;
-	s16 *data;
-
-	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(&st->us->dev, "memory alloc failed in ring bh");
-		goto done;
-	}
-
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
-	    adis16204_read_ring_data(indio_dev, st->rx) >= 0)
-		for (; i < bitmap_weight(indio_dev->active_scan_mask,
-					 indio_dev->masklength); i++)
-			data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp)
-		*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-	iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
-
-	kfree(data);
-done:
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-void adis16204_unconfigure_ring(struct iio_dev *indio_dev)
-{
-	iio_dealloc_pollfunc(indio_dev->pollfunc);
-	iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16204_ring_setup_ops = {
-	.preenable = &iio_sw_buffer_preenable,
-	.postenable = &iio_triggered_buffer_postenable,
-	.predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16204_configure_ring(struct iio_dev *indio_dev)
-{
-	int ret = 0;
-	struct iio_buffer *ring;
-
-	ring = iio_sw_rb_allocate(indio_dev);
-	if (!ring) {
-		ret = -ENOMEM;
-		return ret;
-	}
-	indio_dev->buffer = ring;
-	ring->scan_timestamp = true;
-	indio_dev->setup_ops = &adis16204_ring_setup_ops;
-
-	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-						 &adis16204_trigger_handler,
-						 IRQF_ONESHOT,
-						 indio_dev,
-						 "%s_consumer%d",
-						 indio_dev->name,
-						 indio_dev->id);
-	if (indio_dev->pollfunc == NULL) {
-		ret = -ENOMEM;
-		goto error_iio_sw_rb_free;
-	}
-
-	indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-	return 0;
-
-error_iio_sw_rb_free:
-	iio_sw_rb_free(indio_dev->buffer);
-	return ret;
-}
diff --git a/drivers/staging/iio/accel/adis16204_trigger.c b/drivers/staging/iio/accel/adis16204_trigger.c
deleted file mode 100644
index 408a168..0000000
--- a/drivers/staging/iio/accel/adis16204_trigger.c
+++ /dev/null
@@ -1,73 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16204.h"
-
-/**
- * adis16204_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16204_data_rdy_trigger_set_state(struct iio_trigger *trig,
-						bool state)
-{
-	struct iio_dev *indio_dev = trig->private_data;
-
-	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16204_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16204_trigger_ops = {
-	.owner = THIS_MODULE,
-	.set_trigger_state = &adis16204_data_rdy_trigger_set_state,
-};
-
-int adis16204_probe_trigger(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct adis16204_state *st = iio_priv(indio_dev);
-
-	st->trig = iio_trigger_alloc("adis16204-dev%d", indio_dev->id);
-	if (st->trig == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-
-	ret = request_irq(st->us->irq,
-			  &iio_trigger_generic_data_rdy_poll,
-			  IRQF_TRIGGER_RISING,
-			  "adis16204",
-			  st->trig);
-	if (ret)
-		goto error_free_trig;
-
-	st->trig->dev.parent = &st->us->dev;
-	st->trig->ops = &adis16204_trigger_ops;
-	st->trig->private_data = indio_dev;
-	ret = iio_trigger_register(st->trig);
-
-	/* select default trigger */
-	indio_dev->trig = st->trig;
-	if (ret)
-		goto error_free_irq;
-
-	return 0;
-
-error_free_irq:
-	free_irq(st->us->irq, st->trig);
-error_free_trig:
-	iio_trigger_free(st->trig);
-error_ret:
-	return ret;
-}
-
-void adis16204_remove_trigger(struct iio_dev *indio_dev)
-{
-	struct adis16204_state *state = iio_priv(indio_dev);
-
-	iio_trigger_unregister(state->trig);
-	free_irq(state->us->irq, state->trig);
-	iio_trigger_free(state->trig);
-}
diff --git a/drivers/staging/iio/accel/adis16209.h b/drivers/staging/iio/accel/adis16209.h
index 3c88b86..ad3945a 100644
--- a/drivers/staging/iio/accel/adis16209.h
+++ b/drivers/staging/iio/accel/adis16209.h
@@ -3,9 +3,6 @@
 
 #define ADIS16209_STARTUP_DELAY	220 /* ms */
 
-#define ADIS16209_READ_REG(a)    a
-#define ADIS16209_WRITE_REG(a) ((a) | 0x80)
-
 /* Flash memory write count */
 #define ADIS16209_FLASH_CNT      0x00
 /* Output, power supply */
@@ -61,8 +58,6 @@
 /* Operation, system command register */
 #define ADIS16209_GLOB_CMD       0x3E
 
-#define ADIS16209_OUTPUTS        8
-
 /* MSC_CTRL */
 /* Self-test at power-on: 1 = disabled, 0 = enabled */
 #define ADIS16209_MSC_CTRL_PWRUP_SELF_TEST	(1 << 10)
@@ -81,44 +76,23 @@
 /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
 #define ADIS16209_DIAG_STAT_ALARM1        (1<<8)
 /* Self-test diagnostic error flag: 1 = error condition, 0 = normal operation */
-#define ADIS16209_DIAG_STAT_SELFTEST_FAIL (1<<5)
+#define ADIS16209_DIAG_STAT_SELFTEST_FAIL_BIT	5
 /* SPI communications failure */
-#define ADIS16209_DIAG_STAT_SPI_FAIL	  (1<<3)
+#define ADIS16209_DIAG_STAT_SPI_FAIL_BIT	3
 /* Flash update failure */
-#define ADIS16209_DIAG_STAT_FLASH_UPT	  (1<<2)
+#define ADIS16209_DIAG_STAT_FLASH_UPT_BIT	2
 /* Power supply above 3.625 V */
-#define ADIS16209_DIAG_STAT_POWER_HIGH	  (1<<1)
+#define ADIS16209_DIAG_STAT_POWER_HIGH_BIT	1
 /* Power supply below 3.15 V */
-#define ADIS16209_DIAG_STAT_POWER_LOW	  (1<<0)
+#define ADIS16209_DIAG_STAT_POWER_LOW_BIT	0
 
 /* GLOB_CMD */
 #define ADIS16209_GLOB_CMD_SW_RESET	(1<<7)
 #define ADIS16209_GLOB_CMD_CLEAR_STAT	(1<<4)
 #define ADIS16209_GLOB_CMD_FACTORY_CAL	(1<<1)
 
-#define ADIS16209_MAX_TX 24
-#define ADIS16209_MAX_RX 24
-
 #define ADIS16209_ERROR_ACTIVE          (1<<14)
 
-/**
- * struct adis16209_state - device instance specific data
- * @us:			actual spi_device
- * @trig:		data ready trigger registered with iio
- * @tx:			transmit buffer
- * @rx:			receive buffer
- * @buf_lock:		mutex to protect tx and rx
- **/
-struct adis16209_state {
-	struct spi_device	*us;
-	struct iio_trigger	*trig;
-	struct mutex		buf_lock;
-	u8			tx[ADIS16209_MAX_TX] ____cacheline_aligned;
-	u8			rx[ADIS16209_MAX_RX];
-};
-
-int adis16209_set_irq(struct iio_dev *indio_dev, bool enable);
-
 #define ADIS16209_SCAN_SUPPLY	0
 #define ADIS16209_SCAN_ACC_X	1
 #define ADIS16209_SCAN_ACC_Y	2
@@ -128,45 +102,4 @@ int adis16209_set_irq(struct iio_dev *indio_dev, bool enable);
 #define ADIS16209_SCAN_INCLI_Y	6
 #define ADIS16209_SCAN_ROT	7
 
-#ifdef CONFIG_IIO_BUFFER
-
-void adis16209_remove_trigger(struct iio_dev *indio_dev);
-int adis16209_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16209_read_data_from_ring(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf);
-
-int adis16209_configure_ring(struct iio_dev *indio_dev);
-void adis16209_unconfigure_ring(struct iio_dev *indio_dev);
-
-#else /* CONFIG_IIO_BUFFER */
-
-static inline void adis16209_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16209_probe_trigger(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline ssize_t
-adis16209_read_data_from_ring(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	return 0;
-}
-
-static int adis16209_configure_ring(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline void adis16209_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-#endif /* CONFIG_IIO_BUFFER */
 #endif /* SPI_ADIS16209_H_ */
diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
index 7ee974b..69c50ee 100644
--- a/drivers/staging/iio/accel/adis16209_core.c
+++ b/drivers/staging/iio/accel/adis16209_core.c
@@ -19,262 +19,19 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
 
 #include "adis16209.h"
 
-#define DRIVER_NAME		"adis16209"
-
-/**
- * adis16209_spi_write_reg_8() - write single byte to a register
- * @indio_dev: iio device associated with actual device
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-static int adis16209_spi_write_reg_8(struct iio_dev *indio_dev,
-				     u8 reg_address,
-				     u8 val)
-{
-	int ret;
-	struct adis16209_state *st = iio_priv(indio_dev);
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16209_WRITE_REG(reg_address);
-	st->tx[1] = val;
-
-	ret = spi_write(st->us, st->tx, 2);
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/**
- * adis16209_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @indio_dev: iio device associated actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16209_spi_write_reg_16(struct iio_dev *indio_dev,
-				      u8 lower_reg_address,
-				      u16 value)
-{
-	int ret;
-	struct spi_message msg;
-	struct adis16209_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-			.delay_usecs = 30,
-		}, {
-			.tx_buf = st->tx + 2,
-			.bits_per_word = 8,
-			.len = 2,
-			.delay_usecs = 30,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16209_WRITE_REG(lower_reg_address);
-	st->tx[1] = value & 0xFF;
-	st->tx[2] = ADIS16209_WRITE_REG(lower_reg_address + 1);
-	st->tx[3] = (value >> 8) & 0xFF;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/**
- * adis16209_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @indio_dev: iio device associated with device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16209_spi_read_reg_16(struct iio_dev *indio_dev,
-				     u8 lower_reg_address,
-				     u16 *val)
-{
-	struct spi_message msg;
-	struct adis16209_state *st = iio_priv(indio_dev);
-	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-			.delay_usecs = 30,
-		}, {
-			.rx_buf = st->rx,
-			.bits_per_word = 8,
-			.len = 2,
-			.delay_usecs = 30,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16209_READ_REG(lower_reg_address);
-	st->tx[1] = 0;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
-	if (ret) {
-		dev_err(&st->us->dev,
-			"problem when reading 16 bit register 0x%02X",
-			lower_reg_address);
-		goto error_ret;
-	}
-	*val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
-}
-
-static int adis16209_reset(struct iio_dev *indio_dev)
-{
-	int ret;
-	ret = adis16209_spi_write_reg_8(indio_dev,
-			ADIS16209_GLOB_CMD,
-			ADIS16209_GLOB_CMD_SW_RESET);
-	if (ret)
-		dev_err(&indio_dev->dev, "problem resetting device");
-
-	return ret;
-}
-
-int adis16209_set_irq(struct iio_dev *indio_dev, bool enable)
-{
-	int ret = 0;
-	u16 msc;
-
-	ret = adis16209_spi_read_reg_16(indio_dev, ADIS16209_MSC_CTRL, &msc);
-	if (ret)
-		goto error_ret;
-
-	msc |= ADIS16209_MSC_CTRL_ACTIVE_HIGH;
-	msc &= ~ADIS16209_MSC_CTRL_DATA_RDY_DIO2;
-	if (enable)
-		msc |= ADIS16209_MSC_CTRL_DATA_RDY_EN;
-	else
-		msc &= ~ADIS16209_MSC_CTRL_DATA_RDY_EN;
-
-	ret = adis16209_spi_write_reg_16(indio_dev, ADIS16209_MSC_CTRL, msc);
-
-error_ret:
-	return ret;
-}
-
-static int adis16209_check_status(struct iio_dev *indio_dev)
-{
-	u16 status;
-	int ret;
-
-	ret = adis16209_spi_read_reg_16(indio_dev,
-					ADIS16209_DIAG_STAT, &status);
-	if (ret < 0) {
-		dev_err(&indio_dev->dev, "Reading status failed\n");
-		goto error_ret;
-	}
-	ret = status & 0x1F;
-
-	if (status & ADIS16209_DIAG_STAT_SELFTEST_FAIL)
-		dev_err(&indio_dev->dev, "Self test failure\n");
-	if (status & ADIS16209_DIAG_STAT_SPI_FAIL)
-		dev_err(&indio_dev->dev, "SPI failure\n");
-	if (status & ADIS16209_DIAG_STAT_FLASH_UPT)
-		dev_err(&indio_dev->dev, "Flash update failed\n");
-	if (status & ADIS16209_DIAG_STAT_POWER_HIGH)
-		dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
-	if (status & ADIS16209_DIAG_STAT_POWER_LOW)
-		dev_err(&indio_dev->dev, "Power supply below 3.15V\n");
-
-error_ret:
-	return ret;
-}
-
-static int adis16209_self_test(struct iio_dev *indio_dev)
-{
-	int ret;
-	ret = adis16209_spi_write_reg_16(indio_dev,
-			ADIS16209_MSC_CTRL,
-			ADIS16209_MSC_CTRL_SELF_TEST_EN);
-	if (ret) {
-		dev_err(&indio_dev->dev, "problem starting self test");
-		goto err_ret;
-	}
-
-	adis16209_check_status(indio_dev);
-
-err_ret:
-	return ret;
-}
-
-static int adis16209_initial_setup(struct iio_dev *indio_dev)
-{
-	int ret;
-
-	/* Disable IRQ */
-	ret = adis16209_set_irq(indio_dev, false);
-	if (ret) {
-		dev_err(&indio_dev->dev, "disable irq failed");
-		goto err_ret;
-	}
-
-	/* Do self test */
-	ret = adis16209_self_test(indio_dev);
-	if (ret) {
-		dev_err(&indio_dev->dev, "self test failure");
-		goto err_ret;
-	}
-
-	/* Read status register to check the result */
-	ret = adis16209_check_status(indio_dev);
-	if (ret) {
-		adis16209_reset(indio_dev);
-		dev_err(&indio_dev->dev, "device not playing ball -> reset");
-		msleep(ADIS16209_STARTUP_DELAY);
-		ret = adis16209_check_status(indio_dev);
-		if (ret) {
-			dev_err(&indio_dev->dev, "giving up");
-			goto err_ret;
-		}
-	}
-
-err_ret:
-	return ret;
-}
-
-enum adis16209_chan {
-	in_supply,
-	temp,
-	accel_x,
-	accel_y,
-	incli_x,
-	incli_y,
-	in_aux,
-	rot,
-};
-
-static const u8 adis16209_addresses[8][2] = {
-	[in_supply] = { ADIS16209_SUPPLY_OUT },
-	[in_aux] = { ADIS16209_AUX_ADC },
-	[accel_x] = { ADIS16209_XACCL_OUT, ADIS16209_XACCL_NULL },
-	[accel_y] = { ADIS16209_YACCL_OUT, ADIS16209_YACCL_NULL },
-	[incli_x] = { ADIS16209_XINCL_OUT, ADIS16209_XINCL_NULL },
-	[incli_y] = { ADIS16209_YINCL_OUT, ADIS16209_YINCL_NULL },
-	[rot] = { ADIS16209_ROT_OUT },
-	[temp] = { ADIS16209_TEMP_OUT },
+static const u8 adis16209_addresses[8][1] = {
+	[ADIS16209_SCAN_SUPPLY] = { },
+	[ADIS16209_SCAN_AUX_ADC] = { },
+	[ADIS16209_SCAN_ACC_X] = { ADIS16209_XACCL_NULL },
+	[ADIS16209_SCAN_ACC_Y] = { ADIS16209_YACCL_NULL },
+	[ADIS16209_SCAN_INCLI_X] = { ADIS16209_XINCL_NULL },
+	[ADIS16209_SCAN_INCLI_Y] = { ADIS16209_YINCL_NULL },
+	[ADIS16209_SCAN_ROT] = { },
+	[ADIS16209_SCAN_TEMP] = { },
 };
 
 static int adis16209_write_raw(struct iio_dev *indio_dev,
@@ -283,6 +40,7 @@ static int adis16209_write_raw(struct iio_dev *indio_dev,
 			       int val2,
 			       long mask)
 {
+	struct adis *st = iio_priv(indio_dev);
 	int bits;
 	s16 val16;
 	u8 addr;
@@ -295,10 +53,10 @@ static int adis16209_write_raw(struct iio_dev *indio_dev,
 			break;
 		default:
 			return -EINVAL;
-		};
+		}
 		val16 = val & ((1 << bits) - 1);
-		addr = adis16209_addresses[chan->address][1];
-		return adis16209_spi_write_reg_16(indio_dev, addr, val16);
+		addr = adis16209_addresses[chan->scan_index][0];
+		return adis_write_reg_16(st, addr, val16);
 	}
 	return -EINVAL;
 }
@@ -308,6 +66,7 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
 			      int *val, int *val2,
 			      long mask)
 {
+	struct adis *st = iio_priv(indio_dev);
 	int ret;
 	int bits;
 	u8 addr;
@@ -315,29 +74,8 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
-		mutex_lock(&indio_dev->mlock);
-		addr = adis16209_addresses[chan->address][0];
-		ret = adis16209_spi_read_reg_16(indio_dev, addr, &val16);
-		if (ret) {
-			mutex_unlock(&indio_dev->mlock);
-			return ret;
-		}
-
-		if (val16 & ADIS16209_ERROR_ACTIVE) {
-			ret = adis16209_check_status(indio_dev);
-			if (ret) {
-				mutex_unlock(&indio_dev->mlock);
-				return ret;
-			}
-		}
-		val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
-		if (chan->scan_type.sign == 's')
-			val16 = (s16)(val16 <<
-				      (16 - chan->scan_type.realbits)) >>
-				(16 - chan->scan_type.realbits);
-		*val = val16;
-		mutex_unlock(&indio_dev->mlock);
-		return IIO_VAL_INT;
+		return adis_single_conversion(indio_dev, chan,
+			ADIS16209_ERROR_ACTIVE, val);
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->type) {
 		case IIO_VOLTAGE:
@@ -374,10 +112,10 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
 			break;
 		default:
 			return -EINVAL;
-		};
+		}
 		mutex_lock(&indio_dev->mlock);
-		addr = adis16209_addresses[chan->address][1];
-		ret = adis16209_spi_read_reg_16(indio_dev, addr, &val16);
+		addr = adis16209_addresses[chan->scan_index][0];
+		ret = adis_read_reg_16(st, addr, &val16);
 		if (ret) {
 			mutex_unlock(&indio_dev->mlock);
 			return ret;
@@ -392,128 +130,56 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
 }
 
 static const struct iio_chan_spec adis16209_channels[] = {
-	{
-		.type = IIO_VOLTAGE,
-		.indexed = 1,
-		.channel = 0,
-		.extend_name = "supply",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-		.address = in_supply,
-		.scan_index = ADIS16209_SCAN_SUPPLY,
-		.scan_type = {
-			.sign = 'u',
-			.realbits = 14,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_TEMP,
-		.indexed = 0,
-		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
-		.address = temp,
-		.scan_index = ADIS16209_SCAN_TEMP,
-		.scan_type = {
-			.sign = 'u',
-			.realbits = 12,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_ACCEL,
-		.modified = 1,
-		.channel2 = IIO_MOD_X,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
-		.address = accel_x,
-		.scan_index = ADIS16209_SCAN_ACC_X,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 14,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_ACCEL,
-		.modified = 1,
-		.channel2 = IIO_MOD_Y,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |
-		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,
-		.address = accel_y,
-		.scan_index = ADIS16209_SCAN_ACC_Y,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 14,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_VOLTAGE,
-		.indexed = 1,
-		.channel = 1,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-		.address = in_aux,
-		.scan_index = ADIS16209_SCAN_AUX_ADC,
-		.scan_type = {
-			.sign = 'u',
-			.realbits = 12,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_INCLI,
-		.modified = 1,
-		.channel2 = IIO_MOD_X,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT,
-		.address = incli_x,
-		.scan_index = ADIS16209_SCAN_INCLI_X,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 14,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_INCLI,
-		.modified = 1,
-		.channel2 = IIO_MOD_Y,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT,
-		.address = incli_y,
-		.scan_index = ADIS16209_SCAN_INCLI_Y,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 14,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_ROT,
-		.modified = 1,
-		.channel2 = IIO_MOD_X,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-		IIO_CHAN_INFO_SCALE_SHARED_BIT,
-		.address = rot,
-		.scan_index = ADIS16209_SCAN_ROT,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 14,
-			.storagebits = 16,
-		},
-	},
+	ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT, ADIS16209_SCAN_SUPPLY, 14),
+	ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT, ADIS16209_SCAN_TEMP, 12),
+	ADIS_ACCEL_CHAN(X, ADIS16209_XACCL_OUT, ADIS16209_SCAN_ACC_X,
+		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+	ADIS_ACCEL_CHAN(Y, ADIS16209_YACCL_OUT, ADIS16209_SCAN_ACC_Y,
+		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, 14),
+	ADIS_AUX_ADC_CHAN(ADIS16209_AUX_ADC, ADIS16209_SCAN_AUX_ADC, 12),
+	ADIS_INCLI_CHAN(X, ADIS16209_XINCL_OUT, ADIS16209_SCAN_INCLI_X, 0, 14),
+	ADIS_INCLI_CHAN(Y, ADIS16209_YINCL_OUT, ADIS16209_SCAN_INCLI_Y, 0, 14),
+	ADIS_ROT_CHAN(X, ADIS16209_ROT_OUT, ADIS16209_SCAN_ROT, 0, 14),
 	IIO_CHAN_SOFT_TIMESTAMP(8)
 };
 
 static const struct iio_info adis16209_info = {
 	.read_raw = &adis16209_read_raw,
 	.write_raw = &adis16209_write_raw,
+	.update_scan_mode = adis_update_scan_mode,
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit adis16209_probe(struct spi_device *spi)
+static const char * const adis16209_status_error_msgs[] = {
+	[ADIS16209_DIAG_STAT_SELFTEST_FAIL_BIT] = "Self test failure",
+	[ADIS16209_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
+	[ADIS16209_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
+	[ADIS16209_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
+	[ADIS16209_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V",
+};
+
+static const struct adis_data adis16209_data = {
+	.read_delay = 30,
+	.msc_ctrl_reg = ADIS16209_MSC_CTRL,
+	.glob_cmd_reg = ADIS16209_GLOB_CMD,
+	.diag_stat_reg = ADIS16209_DIAG_STAT,
+
+	.self_test_mask = ADIS16209_MSC_CTRL_SELF_TEST_EN,
+	.startup_delay = ADIS16209_STARTUP_DELAY,
+
+	.status_error_msgs = adis16209_status_error_msgs,
+	.status_error_mask = BIT(ADIS16209_DIAG_STAT_SELFTEST_FAIL_BIT) |
+		BIT(ADIS16209_DIAG_STAT_SPI_FAIL_BIT) |
+		BIT(ADIS16209_DIAG_STAT_FLASH_UPT_BIT) |
+		BIT(ADIS16209_DIAG_STAT_POWER_HIGH_BIT) |
+		BIT(ADIS16209_DIAG_STAT_POWER_LOW_BIT),
+};
+
+
+static int adis16209_probe(struct spi_device *spi)
 {
 	int ret;
-	struct adis16209_state *st;
+	struct adis *st;
 	struct iio_dev *indio_dev;
 
 	/* setup the industrialio driver allocated elements */
@@ -525,8 +191,6 @@ static int __devinit adis16209_probe(struct spi_device *spi)
 	st = iio_priv(indio_dev);
 	/* this is only used for removal purposes */
 	spi_set_drvdata(spi, indio_dev);
-	st->us = spi;
-	mutex_init(&st->buf_lock);
 
 	indio_dev->name = spi->dev.driver->name;
 	indio_dev->dev.parent = &spi->dev;
@@ -535,54 +199,38 @@ static int __devinit adis16209_probe(struct spi_device *spi)
 	indio_dev->num_channels = ARRAY_SIZE(adis16209_channels);
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = adis16209_configure_ring(indio_dev);
+	ret = adis_init(st, indio_dev, spi, &adis16209_data);
+	if (ret)
+		goto error_free_dev;
+	ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL);
 	if (ret)
 		goto error_free_dev;
-
-	ret = iio_buffer_register(indio_dev,
-				  adis16209_channels,
-				  ARRAY_SIZE(adis16209_channels));
-	if (ret) {
-		printk(KERN_ERR "failed to initialize the ring\n");
-		goto error_unreg_ring_funcs;
-	}
-
-	if (spi->irq) {
-		ret = adis16209_probe_trigger(indio_dev);
-		if (ret)
-			goto error_uninitialize_ring;
-	}
 
 	/* Get the device into a sane initial state */
-	ret = adis16209_initial_setup(indio_dev);
+	ret = adis_initial_startup(st);
 	if (ret)
-		goto error_remove_trigger;
+		goto error_cleanup_buffer_trigger;
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_remove_trigger;
+		goto error_cleanup_buffer_trigger;
 
 	return 0;
 
-error_remove_trigger:
-	adis16209_remove_trigger(indio_dev);
-error_uninitialize_ring:
-	iio_buffer_unregister(indio_dev);
-error_unreg_ring_funcs:
-	adis16209_unconfigure_ring(indio_dev);
+error_cleanup_buffer_trigger:
+	adis_cleanup_buffer_and_trigger(st, indio_dev);
 error_free_dev:
 	iio_device_free(indio_dev);
 error_ret:
 	return ret;
 }
 
-static int __devexit adis16209_remove(struct spi_device *spi)
+static int adis16209_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct adis *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	adis16209_remove_trigger(indio_dev);
-	iio_buffer_unregister(indio_dev);
-	adis16209_unconfigure_ring(indio_dev);
+	adis_cleanup_buffer_and_trigger(st, indio_dev);
 	iio_device_free(indio_dev);
 
 	return 0;
@@ -594,7 +242,7 @@ static struct spi_driver adis16209_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = adis16209_probe,
-	.remove = __devexit_p(adis16209_remove),
+	.remove = adis16209_remove,
 };
 module_spi_driver(adis16209_driver);
 
diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c
deleted file mode 100644
index f939e29..0000000
--- a/drivers/staging/iio/accel/adis16209_ring.c
+++ /dev/null
@@ -1,134 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16209.h"
-
-/**
- * adis16209_read_ring_data() read data registers which will be placed into ring
- * @indio_dev: the IIO device
- * @rx: somewhere to pass back the value read
- **/
-static int adis16209_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-	struct spi_message msg;
-	struct adis16209_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[ADIS16209_OUTPUTS + 1];
-	int ret;
-	int i;
-
-	mutex_lock(&st->buf_lock);
-
-	spi_message_init(&msg);
-
-	memset(xfers, 0, sizeof(xfers));
-	for (i = 0; i <= ADIS16209_OUTPUTS; i++) {
-		xfers[i].bits_per_word = 8;
-		xfers[i].cs_change = 1;
-		xfers[i].len = 2;
-		xfers[i].delay_usecs = 30;
-		xfers[i].tx_buf = st->tx + 2 * i;
-		st->tx[2 * i]
-			= ADIS16209_READ_REG(ADIS16209_SUPPLY_OUT + 2 * i);
-		st->tx[2 * i + 1] = 0;
-		if (i >= 1)
-			xfers[i].rx_buf = rx + 2 * (i - 1);
-		spi_message_add_tail(&xfers[i], &msg);
-	}
-
-	ret = spi_sync(st->us, &msg);
-	if (ret)
-		dev_err(&st->us->dev, "problem when burst reading");
-
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
- * specific to be rolled into the core.
- */
-static irqreturn_t adis16209_trigger_handler(int irq, void *p)
-{
-	struct iio_poll_func *pf = p;
-	struct iio_dev *indio_dev = pf->indio_dev;
-	struct adis16209_state *st = iio_priv(indio_dev);
-	int i = 0;
-	s16 *data;
-
-	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(&st->us->dev, "memory alloc failed in ring bh");
-		goto done;
-	}
-
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
-	    adis16209_read_ring_data(indio_dev, st->rx) >= 0)
-		for (; i < bitmap_weight(indio_dev->active_scan_mask,
-					 indio_dev->masklength); i++)
-			data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp)
-		*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-	iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
-
-	kfree(data);
-done:
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-void adis16209_unconfigure_ring(struct iio_dev *indio_dev)
-{
-	iio_dealloc_pollfunc(indio_dev->pollfunc);
-	iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16209_ring_setup_ops = {
-	.preenable = &iio_sw_buffer_preenable,
-	.postenable = &iio_triggered_buffer_postenable,
-	.predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16209_configure_ring(struct iio_dev *indio_dev)
-{
-	int ret = 0;
-	struct iio_buffer *ring;
-
-	ring = iio_sw_rb_allocate(indio_dev);
-	if (!ring) {
-		ret = -ENOMEM;
-		return ret;
-	}
-	indio_dev->buffer = ring;
-	ring->scan_timestamp = true;
-	indio_dev->setup_ops = &adis16209_ring_setup_ops;
-
-	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-						 &adis16209_trigger_handler,
-						 IRQF_ONESHOT,
-						 indio_dev,
-						 "%s_consumer%d",
-						 indio_dev->name,
-						 indio_dev->id);
-	if (indio_dev->pollfunc == NULL) {
-		ret = -ENOMEM;
-		goto error_iio_sw_rb_free;
-	}
-
-	indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-	return 0;
-
-error_iio_sw_rb_free:
-	iio_sw_rb_free(indio_dev->buffer);
-	return ret;
-}
diff --git a/drivers/staging/iio/accel/adis16209_trigger.c b/drivers/staging/iio/accel/adis16209_trigger.c
deleted file mode 100644
index 2ad93dc..0000000
--- a/drivers/staging/iio/accel/adis16209_trigger.c
+++ /dev/null
@@ -1,81 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16209.h"
-
-/**
- * adis16209_data_rdy_trig_poll() the event handler for the data rdy trig
- **/
-static irqreturn_t adis16209_data_rdy_trig_poll(int irq, void *trig)
-{
-	iio_trigger_poll(trig, iio_get_time_ns());
-	return IRQ_HANDLED;
-}
-
-/**
- * adis16209_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16209_data_rdy_trigger_set_state(struct iio_trigger *trig,
-						bool state)
-{
-	struct iio_dev *indio_dev = trig->private_data;
-
-	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16209_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16209_trigger_ops = {
-	.owner = THIS_MODULE,
-	.set_trigger_state = &adis16209_data_rdy_trigger_set_state,
-};
-
-int adis16209_probe_trigger(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct adis16209_state *st = iio_priv(indio_dev);
-
-	st->trig = iio_trigger_alloc("adis16209-dev%d", indio_dev->id);
-	if (st->trig == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-
-	ret = request_irq(st->us->irq,
-			  adis16209_data_rdy_trig_poll,
-			  IRQF_TRIGGER_RISING,
-			  "adis16209",
-			  st->trig);
-	if (ret)
-		goto error_free_trig;
-	st->trig->dev.parent = &st->us->dev;
-	st->trig->ops = &adis16209_trigger_ops;
-	st->trig->private_data = indio_dev;
-	ret = iio_trigger_register(st->trig);
-
-	/* select default trigger */
-	indio_dev->trig = st->trig;
-	if (ret)
-		goto error_free_irq;
-
-	return 0;
-
-error_free_irq:
-	free_irq(st->us->irq, st->trig);
-error_free_trig:
-	iio_trigger_free(st->trig);
-error_ret:
-	return ret;
-}
-
-void adis16209_remove_trigger(struct iio_dev *indio_dev)
-{
-	struct adis16209_state *st = iio_priv(indio_dev);
-
-	iio_trigger_unregister(st->trig);
-	free_irq(st->us->irq, st->trig);
-	iio_trigger_free(st->trig);
-}
diff --git a/drivers/staging/iio/accel/adis16220.h b/drivers/staging/iio/accel/adis16220.h
index 024313c..a894ad7 100644
--- a/drivers/staging/iio/accel/adis16220.h
+++ b/drivers/staging/iio/accel/adis16220.h
@@ -1,10 +1,9 @@
 #ifndef SPI_ADIS16220_H_
 #define SPI_ADIS16220_H_
 
-#define ADIS16220_STARTUP_DELAY	220 /* ms */
+#include <linux/iio/imu/adis.h>
 
-#define ADIS16220_READ_REG(a)    a
-#define ADIS16220_WRITE_REG(a) ((a) | 0x80)
+#define ADIS16220_STARTUP_DELAY	220 /* ms */
 
 /* Flash memory write count */
 #define ADIS16220_FLASH_CNT     0x00
@@ -102,15 +101,15 @@
 #define ADIS16220_DIAG_STAT_FLASH_CHK	(1<<6)
 #define ADIS16220_DIAG_STAT_SELF_TEST	(1<<5)
 /* Capture period violation/interruption */
-#define ADIS16220_DIAG_STAT_VIOLATION	(1<<4)
+#define ADIS16220_DIAG_STAT_VIOLATION_BIT	4
 /* SPI communications failure */
-#define ADIS16220_DIAG_STAT_SPI_FAIL	(1<<3)
+#define ADIS16220_DIAG_STAT_SPI_FAIL_BIT	3
 /* Flash update failure */
-#define ADIS16220_DIAG_STAT_FLASH_UPT	(1<<2)
+#define ADIS16220_DIAG_STAT_FLASH_UPT_BIT	2
 /* Power supply above 3.625 V */
-#define ADIS16220_DIAG_STAT_POWER_HIGH	(1<<1)
+#define ADIS16220_DIAG_STAT_POWER_HIGH_BIT	1
 /* Power supply below 3.15 V */
-#define ADIS16220_DIAG_STAT_POWER_LOW	(1<<0)
+#define ADIS16220_DIAG_STAT_POWER_LOW_BIT	0
 
 /* GLOB_CMD */
 #define ADIS16220_GLOB_CMD_SW_RESET	(1<<7)
@@ -125,13 +124,14 @@
 
 /**
  * struct adis16220_state - device instance specific data
- * @us:			actual spi_device
+ * @adis:		adis device
  * @tx:			transmit buffer
  * @rx:			receive buffer
  * @buf_lock:		mutex to protect tx and rx
  **/
 struct adis16220_state {
-	struct spi_device	*us;
+	struct adis adis;
+
 	struct mutex		buf_lock;
 	u8			tx[ADIS16220_MAX_TX] ____cacheline_aligned;
 	u8			rx[ADIS16220_MAX_RX];
diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c
index eaadd9d..370b01a 100644
--- a/drivers/staging/iio/accel/adis16220_core.c
+++ b/drivers/staging/iio/accel/adis16220_core.c
@@ -20,138 +20,19 @@
 
 #include "adis16220.h"
 
-#define DRIVER_NAME		"adis16220"
-
-/**
- * adis16220_spi_write_reg_8() - write single byte to a register
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-static int adis16220_spi_write_reg_8(struct iio_dev *indio_dev,
-		u8 reg_address,
-		u8 val)
-{
-	int ret;
-	struct adis16220_state *st = iio_priv(indio_dev);
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16220_WRITE_REG(reg_address);
-	st->tx[1] = val;
-
-	ret = spi_write(st->us, st->tx, 2);
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/**
- * adis16220_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @indio_dev:  iio device associated with child of actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16220_spi_write_reg_16(struct iio_dev *indio_dev,
-		u8 lower_reg_address,
-		u16 value)
-{
-	int ret;
-	struct spi_message msg;
-	struct adis16220_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-			.delay_usecs = 35,
-		}, {
-			.tx_buf = st->tx + 2,
-			.bits_per_word = 8,
-			.len = 2,
-			.delay_usecs = 35,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16220_WRITE_REG(lower_reg_address);
-	st->tx[1] = value & 0xFF;
-	st->tx[2] = ADIS16220_WRITE_REG(lower_reg_address + 1);
-	st->tx[3] = (value >> 8) & 0xFF;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/**
- * adis16220_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @indio_dev: iio device associated with child of actual device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16220_spi_read_reg_16(struct iio_dev *indio_dev,
-				     u8 lower_reg_address,
-				     u16 *val)
-{
-	struct spi_message msg;
-	struct adis16220_state *st = iio_priv(indio_dev);
-	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-			.delay_usecs = 35,
-		}, {
-			.rx_buf = st->rx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-			.delay_usecs = 35,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16220_READ_REG(lower_reg_address);
-	st->tx[1] = 0;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
-	if (ret) {
-		dev_err(&st->us->dev,
-			"problem when reading 16 bit register 0x%02X",
-			lower_reg_address);
-		goto error_ret;
-	}
-	*val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
-}
-
 static ssize_t adis16220_read_16bit(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct adis16220_state *st = iio_priv(indio_dev);
 	ssize_t ret;
 	s16 val = 0;
 
 	/* Take the iio_dev status lock */
 	mutex_lock(&indio_dev->mlock);
-	ret = adis16220_spi_read_reg_16(indio_dev, this_attr->address,
+	ret = adis_read_reg_16(&st->adis, this_attr->address,
 					(u16 *)&val);
 	mutex_unlock(&indio_dev->mlock);
 	if (ret)
@@ -166,13 +47,14 @@ static ssize_t adis16220_write_16bit(struct device *dev,
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	struct adis16220_state *st = iio_priv(indio_dev);
 	int ret;
 	u16 val;
 
 	ret = kstrtou16(buf, 10, &val);
 	if (ret)
 		goto error_ret;
-	ret = adis16220_spi_write_reg_16(indio_dev, this_attr->address, val);
+	ret = adis_write_reg_16(&st->adis, this_attr->address, val);
 
 error_ret:
 	return ret ? ret : len;
@@ -180,10 +62,11 @@ error_ret:
 
 static int adis16220_capture(struct iio_dev *indio_dev)
 {
+	struct adis16220_state *st = iio_priv(indio_dev);
 	int ret;
-	ret = adis16220_spi_write_reg_16(indio_dev,
-			ADIS16220_GLOB_CMD,
-			0xBF08); /* initiates a manual data capture */
+
+	 /* initiates a manual data capture */
+	ret = adis_write_reg_16(&st->adis, ADIS16220_GLOB_CMD, 0xBF08);
 	if (ret)
 		dev_err(&indio_dev->dev, "problem beginning capture");
 
@@ -192,18 +75,6 @@ static int adis16220_capture(struct iio_dev *indio_dev)
 	return ret;
 }
 
-static int adis16220_reset(struct iio_dev *indio_dev)
-{
-	int ret;
-	ret = adis16220_spi_write_reg_8(indio_dev,
-			ADIS16220_GLOB_CMD,
-			ADIS16220_GLOB_CMD_SW_RESET);
-	if (ret)
-		dev_err(&indio_dev->dev, "problem resetting device");
-
-	return ret;
-}
-
 static ssize_t adis16220_write_capture(struct device *dev,
 		struct device_attribute *attr,
 		const char *buf, size_t len)
@@ -224,81 +95,6 @@ static ssize_t adis16220_write_capture(struct device *dev,
 	return len;
 }
 
-static int adis16220_check_status(struct iio_dev *indio_dev)
-{
-	u16 status;
-	int ret;
-
-	ret = adis16220_spi_read_reg_16(indio_dev, ADIS16220_DIAG_STAT,
-					&status);
-
-	if (ret < 0) {
-		dev_err(&indio_dev->dev, "Reading status failed\n");
-		goto error_ret;
-	}
-	ret = status & 0x7F;
-
-	if (status & ADIS16220_DIAG_STAT_VIOLATION)
-		dev_err(&indio_dev->dev,
-			"Capture period violation/interruption\n");
-	if (status & ADIS16220_DIAG_STAT_SPI_FAIL)
-		dev_err(&indio_dev->dev, "SPI failure\n");
-	if (status & ADIS16220_DIAG_STAT_FLASH_UPT)
-		dev_err(&indio_dev->dev, "Flash update failed\n");
-	if (status & ADIS16220_DIAG_STAT_POWER_HIGH)
-		dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
-	if (status & ADIS16220_DIAG_STAT_POWER_LOW)
-		dev_err(&indio_dev->dev, "Power supply below 3.15V\n");
-
-error_ret:
-	return ret;
-}
-
-static int adis16220_self_test(struct iio_dev *indio_dev)
-{
-	int ret;
-	ret = adis16220_spi_write_reg_16(indio_dev,
-			ADIS16220_MSC_CTRL,
-			ADIS16220_MSC_CTRL_SELF_TEST_EN);
-	if (ret) {
-		dev_err(&indio_dev->dev, "problem starting self test");
-		goto err_ret;
-	}
-
-	adis16220_check_status(indio_dev);
-
-err_ret:
-	return ret;
-}
-
-static int adis16220_initial_setup(struct iio_dev *indio_dev)
-{
-	int ret;
-
-	/* Do self test */
-	ret = adis16220_self_test(indio_dev);
-	if (ret) {
-		dev_err(&indio_dev->dev, "self test failure");
-		goto err_ret;
-	}
-
-	/* Read status register to check the result */
-	ret = adis16220_check_status(indio_dev);
-	if (ret) {
-		adis16220_reset(indio_dev);
-		dev_err(&indio_dev->dev, "device not playing ball -> reset");
-		msleep(ADIS16220_STARTUP_DELAY);
-		ret = adis16220_check_status(indio_dev);
-		if (ret) {
-			dev_err(&indio_dev->dev, "giving up");
-			goto err_ret;
-		}
-	}
-
-err_ret:
-	return ret;
-}
-
 static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
 					char *buf,
 					loff_t off,
@@ -335,7 +131,7 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
 		count = ADIS16220_CAPTURE_SIZE - off;
 
 	/* write the begin position of capture buffer */
-	ret = adis16220_spi_write_reg_16(indio_dev,
+	ret = adis_write_reg_16(&st->adis,
 					ADIS16220_CAPT_PNTR,
 					off > 1);
 	if (ret)
@@ -344,8 +140,9 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
 	/* read count/2 values from capture buffer */
 	mutex_lock(&st->buf_lock);
 
+
 	for (i = 0; i < count; i += 2) {
-		st->tx[i] = ADIS16220_READ_REG(addr);
+		st->tx[i] = ADIS_READ_REG(addr);
 		st->tx[i + 1] = 0;
 	}
 	xfers[1].len = count;
@@ -353,7 +150,7 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
 	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(st->adis.spi, &msg);
 	if (ret) {
 
 		mutex_unlock(&st->buf_lock);
@@ -474,6 +271,8 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
 			      int *val, int *val2,
 			      long mask)
 {
+	struct adis16220_state *st = iio_priv(indio_dev);
+	const struct adis16220_address_spec *addr;
 	int ret = -EINVAL;
 	int addrind = 0;
 	u16 uval;
@@ -518,28 +317,21 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
 	default:
 		return -EINVAL;
 	}
-	if (adis16220_addresses[chan->address][addrind].sign) {
-		ret = adis16220_spi_read_reg_16(indio_dev,
-						adis16220_addresses[chan
-								    ->address]
-						[addrind].addr,
-						&sval);
+	addr = &adis16220_addresses[chan->address][addrind];
+	if (addr->sign) {
+		ret = adis_read_reg_16(&st->adis, addr->addr, &sval);
 		if (ret)
 			return ret;
-		bits = adis16220_addresses[chan->address][addrind].bits;
+		bits = addr->bits;
 		sval &= (1 << bits) - 1;
 		sval = (s16)(sval << (16 - bits)) >> (16 - bits);
 		*val = sval;
 		return IIO_VAL_INT;
 	} else {
-		ret = adis16220_spi_read_reg_16(indio_dev,
-						adis16220_addresses[chan
-								    ->address]
-						[addrind].addr,
-						&uval);
+		ret = adis_read_reg_16(&st->adis, addr->addr, &uval);
 		if (ret)
 			return ret;
-		bits = adis16220_addresses[chan->address][addrind].bits;
+		bits = addr->bits;
 		uval &= (1 << bits) - 1;
 		*val = uval;
 		return IIO_VAL_INT;
@@ -603,7 +395,33 @@ static const struct iio_info adis16220_info = {
 	.read_raw = &adis16220_read_raw,
 };
 
-static int __devinit adis16220_probe(struct spi_device *spi)
+static const char * const adis16220_status_error_msgs[] = {
+	[ADIS16220_DIAG_STAT_VIOLATION_BIT] = "Capture period violation/interruption",
+	[ADIS16220_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
+	[ADIS16220_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
+	[ADIS16220_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
+	[ADIS16220_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V",
+};
+
+static const struct adis_data adis16220_data = {
+	.read_delay = 35,
+	.write_delay = 35,
+	.msc_ctrl_reg = ADIS16220_MSC_CTRL,
+	.glob_cmd_reg = ADIS16220_GLOB_CMD,
+	.diag_stat_reg = ADIS16220_DIAG_STAT,
+
+	.self_test_mask = ADIS16220_MSC_CTRL_SELF_TEST_EN,
+	.startup_delay = ADIS16220_STARTUP_DELAY,
+
+	.status_error_msgs = adis16220_status_error_msgs,
+	.status_error_mask = BIT(ADIS16220_DIAG_STAT_VIOLATION_BIT) |
+		BIT(ADIS16220_DIAG_STAT_SPI_FAIL_BIT) |
+		BIT(ADIS16220_DIAG_STAT_FLASH_UPT_BIT) |
+		BIT(ADIS16220_DIAG_STAT_POWER_HIGH_BIT) |
+		BIT(ADIS16220_DIAG_STAT_POWER_LOW_BIT),
+};
+
+static int adis16220_probe(struct spi_device *spi)
 {
 	int ret;
 	struct adis16220_state *st;
@@ -620,9 +438,6 @@ static int __devinit adis16220_probe(struct spi_device *spi)
 	/* this is only used for removal purposes */
 	spi_set_drvdata(spi, indio_dev);
 
-	st->us = spi;
-	mutex_init(&st->buf_lock);
-
 	indio_dev->name = spi->dev.driver->name;
 	indio_dev->dev.parent = &spi->dev;
 	indio_dev->info = &adis16220_info;
@@ -646,8 +461,11 @@ static int __devinit adis16220_probe(struct spi_device *spi)
 	if (ret)
 		goto error_rm_adc1_bin;
 
+	ret = adis_init(&st->adis, indio_dev, spi, &adis16220_data);
+	if (ret)
+		goto error_rm_adc2_bin;
 	/* Get the device into a sane initial state */
-	ret = adis16220_initial_setup(indio_dev);
+	ret = adis_initial_startup(&st->adis);
 	if (ret)
 		goto error_rm_adc2_bin;
 	return 0;
@@ -666,7 +484,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit adis16220_remove(struct spi_device *spi)
+static int adis16220_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
@@ -685,7 +503,7 @@ static struct spi_driver adis16220_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = adis16220_probe,
-	.remove = __devexit_p(adis16220_remove),
+	.remove = adis16220_remove,
 };
 module_spi_driver(adis16220_driver);
 
diff --git a/drivers/staging/iio/accel/adis16240.h b/drivers/staging/iio/accel/adis16240.h
index 3fabcc0..d442d49 100644
--- a/drivers/staging/iio/accel/adis16240.h
+++ b/drivers/staging/iio/accel/adis16240.h
@@ -3,9 +3,6 @@
 
 #define ADIS16240_STARTUP_DELAY	220 /* ms */
 
-#define ADIS16240_READ_REG(a)    a
-#define ADIS16240_WRITE_REG(a) ((a) | 0x80)
-
 /* Flash memory write count */
 #define ADIS16240_FLASH_CNT      0x00
 /* Output, power supply */
@@ -75,8 +72,6 @@
 /* System command */
 #define ADIS16240_GLOB_CMD       0x4A
 
-#define ADIS16240_OUTPUTS        6
-
 /* MSC_CTRL */
 /* Enables sum-of-squares output (XYZPEAK_OUT) */
 #define ADIS16240_MSC_CTRL_XYZPEAK_OUT_EN	(1 << 15)
@@ -101,17 +96,17 @@
 /* Flash test, checksum flag: 1 = mismatch, 0 = match */
 #define ADIS16240_DIAG_STAT_CHKSUM      (1<<6)
 /* Power-on, self-test flag: 1 = failure, 0 = pass */
-#define ADIS16240_DIAG_STAT_PWRON_FAIL  (1<<5)
+#define ADIS16240_DIAG_STAT_PWRON_FAIL_BIT  5
 /* Power-on self-test: 1 = in-progress, 0 = complete */
 #define ADIS16240_DIAG_STAT_PWRON_BUSY  (1<<4)
 /* SPI communications failure */
-#define ADIS16240_DIAG_STAT_SPI_FAIL	(1<<3)
+#define ADIS16240_DIAG_STAT_SPI_FAIL_BIT	3
 /* Flash update failure */
-#define ADIS16240_DIAG_STAT_FLASH_UPT	(1<<2)
+#define ADIS16240_DIAG_STAT_FLASH_UPT_BIT	2
 /* Power supply above 3.625 V */
-#define ADIS16240_DIAG_STAT_POWER_HIGH	(1<<1)
+#define ADIS16240_DIAG_STAT_POWER_HIGH_BIT	1
  /* Power supply below 3.15 V */
-#define ADIS16240_DIAG_STAT_POWER_LOW	(1<<0)
+#define ADIS16240_DIAG_STAT_POWER_LOW_BIT	0
 
 /* GLOB_CMD */
 #define ADIS16240_GLOB_CMD_RESUME	(1<<8)
@@ -120,77 +115,15 @@
 
 #define ADIS16240_ERROR_ACTIVE          (1<<14)
 
-#define ADIS16240_MAX_TX 24
-#define ADIS16240_MAX_RX 24
-
-/**
- * struct adis16240_state - device instance specific data
- * @us:			actual spi_device
- * @trig:		data ready trigger registered with iio
- * @tx:			transmit buffer
- * @rx:			receive buffer
- * @buf_lock:		mutex to protect tx and rx
- **/
-struct adis16240_state {
-	struct spi_device	*us;
-	struct iio_trigger	*trig;
-	struct mutex		buf_lock;
-	u8			tx[ADIS16240_MAX_TX] ____cacheline_aligned;
-	u8			rx[ADIS16240_MAX_RX];
-};
-
-int adis16240_set_irq(struct iio_dev *indio_dev, bool enable);
-
 /* At the moment triggers are only used for ring buffer
  * filling. This may change!
  */
 
-#define ADIS16240_SCAN_SUPPLY	0
-#define ADIS16240_SCAN_ACC_X	1
-#define ADIS16240_SCAN_ACC_Y	2
-#define ADIS16240_SCAN_ACC_Z	3
+#define ADIS16240_SCAN_ACC_X	0
+#define ADIS16240_SCAN_ACC_Y	1
+#define ADIS16240_SCAN_ACC_Z	2
+#define ADIS16240_SCAN_SUPPLY	3
 #define ADIS16240_SCAN_AUX_ADC	4
 #define ADIS16240_SCAN_TEMP	5
 
-#ifdef CONFIG_IIO_BUFFER
-void adis16240_remove_trigger(struct iio_dev *indio_dev);
-int adis16240_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16240_read_data_from_ring(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf);
-
-
-int adis16240_configure_ring(struct iio_dev *indio_dev);
-void adis16240_unconfigure_ring(struct iio_dev *indio_dev);
-
-#else /* CONFIG_IIO_BUFFER */
-
-static inline void adis16240_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16240_probe_trigger(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline ssize_t
-adis16240_read_data_from_ring(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	return 0;
-}
-
-static int adis16240_configure_ring(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline void adis16240_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-#endif /* CONFIG_IIO_BUFFER */
 #endif /* SPI_ADIS16240_H_ */
diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
index 35e0939..e97fa0b 100644
--- a/drivers/staging/iio/accel/adis16240_core.c
+++ b/drivers/staging/iio/accel/adis16240_core.c
@@ -22,151 +22,29 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/imu/adis.h>
 
 #include "adis16240.h"
 
-#define DRIVER_NAME		"adis16240"
-
-static int adis16240_check_status(struct iio_dev *indio_dev);
-
-/**
- * adis16240_spi_write_reg_8() - write single byte to a register
- * @indio_dev: iio_dev associated with device
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-static int adis16240_spi_write_reg_8(struct iio_dev *indio_dev,
-				     u8 reg_address,
-				     u8 val)
-{
-	int ret;
-	struct adis16240_state *st = iio_priv(indio_dev);
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16240_WRITE_REG(reg_address);
-	st->tx[1] = val;
-
-	ret = spi_write(st->us, st->tx, 2);
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/**
- * adis16240_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @indio_dev: iio_dev for this device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16240_spi_write_reg_16(struct iio_dev *indio_dev,
-				      u8 lower_reg_address,
-				      u16 value)
-{
-	int ret;
-	struct spi_message msg;
-	struct adis16240_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-			.delay_usecs = 35,
-		}, {
-			.tx_buf = st->tx + 2,
-			.bits_per_word = 8,
-			.len = 2,
-			.delay_usecs = 35,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16240_WRITE_REG(lower_reg_address);
-	st->tx[1] = value & 0xFF;
-	st->tx[2] = ADIS16240_WRITE_REG(lower_reg_address + 1);
-	st->tx[3] = (value >> 8) & 0xFF;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/**
- * adis16240_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @indio_dev: iio_dev for this device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16240_spi_read_reg_16(struct iio_dev *indio_dev,
-		u8 lower_reg_address,
-		u16 *val)
-{
-	struct spi_message msg;
-	struct adis16240_state *st = iio_priv(indio_dev);
-	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-			.delay_usecs = 35,
-		}, {
-			.rx_buf = st->rx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-			.delay_usecs = 35,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16240_READ_REG(lower_reg_address);
-	st->tx[1] = 0;
-	st->tx[2] = 0;
-	st->tx[3] = 0;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
-	if (ret) {
-		dev_err(&st->us->dev,
-			"problem when reading 16 bit register 0x%02X",
-			lower_reg_address);
-		goto error_ret;
-	}
-	*val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
-}
-
 static ssize_t adis16240_spi_read_signed(struct device *dev,
 		struct device_attribute *attr,
 		char *buf,
 		unsigned bits)
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct adis *st = iio_priv(indio_dev);
 	int ret;
 	s16 val = 0;
 	unsigned shift = 16 - bits;
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
-	ret = adis16240_spi_read_reg_16(indio_dev,
+	ret = adis_read_reg_16(st,
 					this_attr->address, (u16 *)&val);
 	if (ret)
 		return ret;
 
 	if (val & ADIS16240_ERROR_ACTIVE)
-		adis16240_check_status(indio_dev);
+		adis_check_status(st);
 
 	val = ((s16)(val << shift) >> shift);
 	return sprintf(buf, "%d\n", val);
@@ -187,152 +65,16 @@ static ssize_t adis16240_read_12bit_signed(struct device *dev,
 	return ret;
 }
 
-static int adis16240_reset(struct iio_dev *indio_dev)
-{
-	int ret;
-	ret = adis16240_spi_write_reg_8(indio_dev,
-			ADIS16240_GLOB_CMD,
-			ADIS16240_GLOB_CMD_SW_RESET);
-	if (ret)
-		dev_err(&indio_dev->dev, "problem resetting device");
-
-	return ret;
-}
-
-int adis16240_set_irq(struct iio_dev *indio_dev, bool enable)
-{
-	int ret = 0;
-	u16 msc;
-
-	ret = adis16240_spi_read_reg_16(indio_dev,
-					ADIS16240_MSC_CTRL, &msc);
-	if (ret)
-		goto error_ret;
-
-	msc |= ADIS16240_MSC_CTRL_ACTIVE_HIGH;
-	msc &= ~ADIS16240_MSC_CTRL_DATA_RDY_DIO2;
-	if (enable)
-		msc |= ADIS16240_MSC_CTRL_DATA_RDY_EN;
-	else
-		msc &= ~ADIS16240_MSC_CTRL_DATA_RDY_EN;
-
-	ret = adis16240_spi_write_reg_16(indio_dev,
-					 ADIS16240_MSC_CTRL, msc);
-
-error_ret:
-	return ret;
-}
-
-static int adis16240_self_test(struct iio_dev *indio_dev)
-{
-	int ret;
-	ret = adis16240_spi_write_reg_16(indio_dev,
-			ADIS16240_MSC_CTRL,
-			ADIS16240_MSC_CTRL_SELF_TEST_EN);
-	if (ret) {
-		dev_err(&indio_dev->dev, "problem starting self test");
-		goto err_ret;
-	}
-
-	msleep(ADIS16240_STARTUP_DELAY);
-
-	adis16240_check_status(indio_dev);
-
-err_ret:
-	return ret;
-}
-
-static int adis16240_check_status(struct iio_dev *indio_dev)
-{
-	u16 status;
-	int ret;
-	struct device *dev = &indio_dev->dev;
-
-	ret = adis16240_spi_read_reg_16(indio_dev,
-					ADIS16240_DIAG_STAT, &status);
-
-	if (ret < 0) {
-		dev_err(dev, "Reading status failed\n");
-		goto error_ret;
-	}
-
-	ret = status & 0x2F;
-	if (status & ADIS16240_DIAG_STAT_PWRON_FAIL)
-		dev_err(dev, "Power-on, self-test fail\n");
-	if (status & ADIS16240_DIAG_STAT_SPI_FAIL)
-		dev_err(dev, "SPI failure\n");
-	if (status & ADIS16240_DIAG_STAT_FLASH_UPT)
-		dev_err(dev, "Flash update failed\n");
-	if (status & ADIS16240_DIAG_STAT_POWER_HIGH)
-		dev_err(dev, "Power supply above 3.625V\n");
-	if (status & ADIS16240_DIAG_STAT_POWER_LOW)
-		dev_err(dev, "Power supply below 2.225V\n");
-
-error_ret:
-	return ret;
-}
-
-static int adis16240_initial_setup(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct device *dev = &indio_dev->dev;
-
-	/* Disable IRQ */
-	ret = adis16240_set_irq(indio_dev, false);
-	if (ret) {
-		dev_err(dev, "disable irq failed");
-		goto err_ret;
-	}
-
-	/* Do self test */
-	ret = adis16240_self_test(indio_dev);
-	if (ret) {
-		dev_err(dev, "self test failure");
-		goto err_ret;
-	}
-
-	/* Read status register to check the result */
-	ret = adis16240_check_status(indio_dev);
-	if (ret) {
-		adis16240_reset(indio_dev);
-		dev_err(dev, "device not playing ball -> reset");
-		msleep(ADIS16240_STARTUP_DELAY);
-		ret = adis16240_check_status(indio_dev);
-		if (ret) {
-			dev_err(dev, "giving up");
-			goto err_ret;
-		}
-	}
-
-err_ret:
-	return ret;
-}
-
 static IIO_DEVICE_ATTR(in_accel_xyz_squared_peak_raw, S_IRUGO,
 		       adis16240_read_12bit_signed, NULL,
 		       ADIS16240_XYZPEAK_OUT);
 
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("4096");
 
-enum adis16240_chan {
-	in_supply,
-	in_aux,
-	accel_x,
-	accel_y,
-	accel_z,
-	temp,
-};
-
-static const u8 adis16240_addresses[6][3] = {
-	[in_supply] = { ADIS16240_SUPPLY_OUT },
-	[in_aux] = { ADIS16240_AUX_ADC },
-	[accel_x] = { ADIS16240_XACCL_OUT, ADIS16240_XACCL_OFF,
-		      ADIS16240_XPEAK_OUT },
-	[accel_y] = { ADIS16240_YACCL_OUT, ADIS16240_YACCL_OFF,
-		      ADIS16240_YPEAK_OUT },
-	[accel_z] = { ADIS16240_ZACCL_OUT, ADIS16240_ZACCL_OFF,
-		      ADIS16240_ZPEAK_OUT },
-	[temp] = { ADIS16240_TEMP_OUT },
+static const u8 adis16240_addresses[][2] = {
+	[ADIS16240_SCAN_ACC_X] = { ADIS16240_XACCL_OFF, ADIS16240_XPEAK_OUT },
+	[ADIS16240_SCAN_ACC_Y] = { ADIS16240_YACCL_OFF, ADIS16240_YPEAK_OUT },
+	[ADIS16240_SCAN_ACC_Z] = { ADIS16240_ZACCL_OFF, ADIS16240_ZPEAK_OUT },
 };
 
 static int adis16240_read_raw(struct iio_dev *indio_dev,
@@ -340,6 +82,7 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
 			      int *val, int *val2,
 			      long mask)
 {
+	struct adis *st = iio_priv(indio_dev);
 	int ret;
 	int bits;
 	u8 addr;
@@ -347,29 +90,8 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
-		mutex_lock(&indio_dev->mlock);
-		addr = adis16240_addresses[chan->address][0];
-		ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16);
-		if (ret) {
-			mutex_unlock(&indio_dev->mlock);
-			return ret;
-		}
-
-		if (val16 & ADIS16240_ERROR_ACTIVE) {
-			ret = adis16240_check_status(indio_dev);
-			if (ret) {
-				mutex_unlock(&indio_dev->mlock);
-				return ret;
-			}
-		}
-		val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
-		if (chan->scan_type.sign == 's')
-			val16 = (s16)(val16 <<
-				      (16 - chan->scan_type.realbits)) >>
-				(16 - chan->scan_type.realbits);
-		*val = val16;
-		mutex_unlock(&indio_dev->mlock);
-		return IIO_VAL_INT;
+		return adis_single_conversion(indio_dev, chan,
+				ADIS16240_ERROR_ACTIVE, val);
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->type) {
 		case IIO_VOLTAGE:
@@ -402,8 +124,8 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
 	case IIO_CHAN_INFO_CALIBBIAS:
 		bits = 10;
 		mutex_lock(&indio_dev->mlock);
-		addr = adis16240_addresses[chan->address][1];
-		ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16);
+		addr = adis16240_addresses[chan->scan_index][0];
+		ret = adis_read_reg_16(st, addr, &val16);
 		if (ret) {
 			mutex_unlock(&indio_dev->mlock);
 			return ret;
@@ -416,8 +138,8 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
 	case IIO_CHAN_INFO_PEAK:
 		bits = 10;
 		mutex_lock(&indio_dev->mlock);
-		addr = adis16240_addresses[chan->address][2];
-		ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16);
+		addr = adis16240_addresses[chan->scan_index][1];
+		ret = adis_read_reg_16(st, addr, &val16);
 		if (ret) {
 			mutex_unlock(&indio_dev->mlock);
 			return ret;
@@ -437,104 +159,32 @@ static int adis16240_write_raw(struct iio_dev *indio_dev,
 			       int val2,
 			       long mask)
 {
+	struct adis *st = iio_priv(indio_dev);
 	int bits = 10;
 	s16 val16;
 	u8 addr;
 	switch (mask) {
 	case IIO_CHAN_INFO_CALIBBIAS:
 		val16 = val & ((1 << bits) - 1);
-		addr = adis16240_addresses[chan->address][1];
-		return adis16240_spi_write_reg_16(indio_dev, addr, val16);
+		addr = adis16240_addresses[chan->scan_index][0];
+		return adis_write_reg_16(st, addr, val16);
 	}
 	return -EINVAL;
 }
 
 static const struct iio_chan_spec adis16240_channels[] = {
-	{
-		.type = IIO_VOLTAGE,
-		.indexed = 1,
-		.channel = 0,
-		.extend_name = "supply",
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-		.address = in_supply,
-		.scan_index = ADIS16240_SCAN_SUPPLY,
-		.scan_type = {
-			.sign = 'u',
-			.realbits = 10,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_VOLTAGE,
-		.indexed = 1,
-		.channel = 1,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
-		.address = in_aux,
-		.scan_index = ADIS16240_SCAN_AUX_ADC,
-		.scan_type = {
-			.sign = 'u',
-			.realbits = 10,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_ACCEL,
-		.modified = 1,
-		.channel2 = IIO_MOD_X,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |
+	ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 10),
+	ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 10),
+	ADIS_ACCEL_CHAN(X, ADIS16240_XACCL_OUT, ADIS16240_SCAN_ACC_X,
 		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-		IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
-		.address = accel_x,
-		.scan_index = ADIS16240_SCAN_ACC_X,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 10,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_ACCEL,
-		.modified = 1,
-		.channel2 = IIO_MOD_Y,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |
+		IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 10),
+	ADIS_ACCEL_CHAN(Y, ADIS16240_YACCL_OUT, ADIS16240_SCAN_ACC_Y,
 		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-		IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
-		.address = accel_y,
-		.scan_index = ADIS16240_SCAN_ACC_Y,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 10,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_ACCEL,
-		.modified = 1,
-		.channel2 = IIO_MOD_Z,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SHARED_BIT |
+		IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 10),
+	ADIS_ACCEL_CHAN(Z, ADIS16240_ZACCL_OUT, ADIS16240_SCAN_ACC_Z,
 		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-		IIO_CHAN_INFO_PEAK_SEPARATE_BIT,
-		.address = accel_z,
-		.scan_index = ADIS16240_SCAN_ACC_Z,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 10,
-			.storagebits = 16,
-		},
-	}, {
-		.type = IIO_TEMP,
-		.indexed = 1,
-		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-		.address = temp,
-		.scan_index = ADIS16240_SCAN_TEMP,
-		.scan_type = {
-			.sign = 'u',
-			.realbits = 10,
-			.storagebits = 16,
-		},
-	},
+		IIO_CHAN_INFO_PEAK_SEPARATE_BIT, 10),
+	ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 10),
 	IIO_CHAN_SOFT_TIMESTAMP(6)
 };
 
@@ -552,13 +202,40 @@ static const struct iio_info adis16240_info = {
 	.attrs = &adis16240_attribute_group,
 	.read_raw = &adis16240_read_raw,
 	.write_raw = &adis16240_write_raw,
+	.update_scan_mode = adis_update_scan_mode,
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit adis16240_probe(struct spi_device *spi)
+static const char * const adis16240_status_error_msgs[] = {
+	[ADIS16240_DIAG_STAT_PWRON_FAIL_BIT] = "Power on, self-test failed",
+	[ADIS16240_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
+	[ADIS16240_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
+	[ADIS16240_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
+	[ADIS16240_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.225V",
+};
+
+static const struct adis_data adis16240_data = {
+	.write_delay = 35,
+	.read_delay = 35,
+	.msc_ctrl_reg = ADIS16240_MSC_CTRL,
+	.glob_cmd_reg = ADIS16240_GLOB_CMD,
+	.diag_stat_reg = ADIS16240_DIAG_STAT,
+
+	.self_test_mask = ADIS16240_MSC_CTRL_SELF_TEST_EN,
+	.startup_delay = ADIS16240_STARTUP_DELAY,
+
+	.status_error_msgs = adis16240_status_error_msgs,
+	.status_error_mask = BIT(ADIS16240_DIAG_STAT_PWRON_FAIL_BIT) |
+		BIT(ADIS16240_DIAG_STAT_SPI_FAIL_BIT) |
+		BIT(ADIS16240_DIAG_STAT_FLASH_UPT_BIT) |
+		BIT(ADIS16240_DIAG_STAT_POWER_HIGH_BIT) |
+		BIT(ADIS16240_DIAG_STAT_POWER_LOW_BIT),
+};
+
+static int adis16240_probe(struct spi_device *spi)
 {
 	int ret;
-	struct adis16240_state *st;
+	struct adis *st;
 	struct iio_dev *indio_dev;
 
 	/* setup the industrialio driver allocated elements */
@@ -571,9 +248,6 @@ static int __devinit adis16240_probe(struct spi_device *spi)
 	/* this is only used for removal purposes */
 	spi_set_drvdata(spi, indio_dev);
 
-	st->us = spi;
-	mutex_init(&st->buf_lock);
-
 	indio_dev->name = spi->dev.driver->name;
 	indio_dev->dev.parent = &spi->dev;
 	indio_dev->info = &adis16240_info;
@@ -581,54 +255,37 @@ static int __devinit adis16240_probe(struct spi_device *spi)
 	indio_dev->num_channels = ARRAY_SIZE(adis16240_channels);
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = adis16240_configure_ring(indio_dev);
+	ret = adis_init(st, indio_dev, spi, &adis16240_data);
+	if (ret)
+		goto error_free_dev;
+	ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL);
 	if (ret)
 		goto error_free_dev;
-
-	ret = iio_buffer_register(indio_dev,
-				  adis16240_channels,
-				  ARRAY_SIZE(adis16240_channels));
-	if (ret) {
-		printk(KERN_ERR "failed to initialize the ring\n");
-		goto error_unreg_ring_funcs;
-	}
-
-	if (spi->irq) {
-		ret = adis16240_probe_trigger(indio_dev);
-		if (ret)
-			goto error_uninitialize_ring;
-	}
 
 	/* Get the device into a sane initial state */
-	ret = adis16240_initial_setup(indio_dev);
+	ret = adis_initial_startup(st);
 	if (ret)
-		goto error_remove_trigger;
+		goto error_cleanup_buffer_trigger;
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_remove_trigger;
+		goto error_cleanup_buffer_trigger;
 	return 0;
 
-error_remove_trigger:
-	adis16240_remove_trigger(indio_dev);
-error_uninitialize_ring:
-	iio_buffer_unregister(indio_dev);
-error_unreg_ring_funcs:
-	adis16240_unconfigure_ring(indio_dev);
+error_cleanup_buffer_trigger:
+	adis_cleanup_buffer_and_trigger(st, indio_dev);
 error_free_dev:
 	iio_device_free(indio_dev);
 error_ret:
 	return ret;
 }
 
-static int __devexit adis16240_remove(struct spi_device *spi)
+static int adis16240_remove(struct spi_device *spi)
 {
-
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct adis *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	adis16240_remove_trigger(indio_dev);
-	iio_buffer_unregister(indio_dev);
-	adis16240_unconfigure_ring(indio_dev);
+	adis_cleanup_buffer_and_trigger(st, indio_dev);
 	iio_device_free(indio_dev);
 
 	return 0;
@@ -640,7 +297,7 @@ static struct spi_driver adis16240_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = adis16240_probe,
-	.remove = __devexit_p(adis16240_remove),
+	.remove = adis16240_remove,
 };
 module_spi_driver(adis16240_driver);
 
diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c
deleted file mode 100644
index caff8e2..0000000
--- a/drivers/staging/iio/accel/adis16240_ring.c
+++ /dev/null
@@ -1,132 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16240.h"
-
-/**
- * adis16240_read_ring_data() read data registers which will be placed into ring
- * @indio_dev: the IIO device
- * @rx: somewhere to pass back the value read
- **/
-static int adis16240_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-	struct spi_message msg;
-	struct adis16240_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[ADIS16240_OUTPUTS + 1];
-	int ret;
-	int i;
-
-	mutex_lock(&st->buf_lock);
-
-	spi_message_init(&msg);
-
-	memset(xfers, 0, sizeof(xfers));
-	for (i = 0; i <= ADIS16240_OUTPUTS; i++) {
-		xfers[i].bits_per_word = 8;
-		xfers[i].cs_change = 1;
-		xfers[i].len = 2;
-		xfers[i].delay_usecs = 30;
-		xfers[i].tx_buf = st->tx + 2 * i;
-		st->tx[2 * i]
-			= ADIS16240_READ_REG(ADIS16240_SUPPLY_OUT + 2 * i);
-		st->tx[2 * i + 1] = 0;
-		if (i >= 1)
-			xfers[i].rx_buf = rx + 2 * (i - 1);
-		spi_message_add_tail(&xfers[i], &msg);
-	}
-
-	ret = spi_sync(st->us, &msg);
-	if (ret)
-		dev_err(&st->us->dev, "problem when burst reading");
-
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-static irqreturn_t adis16240_trigger_handler(int irq, void *p)
-{
-	struct iio_poll_func *pf = p;
-	struct iio_dev *indio_dev = pf->indio_dev;
-	struct adis16240_state *st = iio_priv(indio_dev);
-
-	int i = 0;
-	s16 *data;
-
-	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(&st->us->dev, "memory alloc failed in ring bh");
-		goto done;
-	}
-
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
-	    adis16240_read_ring_data(indio_dev, st->rx) >= 0)
-		for (; i < bitmap_weight(indio_dev->active_scan_mask,
-					 indio_dev->masklength); i++)
-			data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp)
-		*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-	iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
-
-	kfree(data);
-done:
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-void adis16240_unconfigure_ring(struct iio_dev *indio_dev)
-{
-	iio_dealloc_pollfunc(indio_dev->pollfunc);
-	iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16240_ring_setup_ops = {
-	.preenable = &iio_sw_buffer_preenable,
-	.postenable = &iio_triggered_buffer_postenable,
-	.predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16240_configure_ring(struct iio_dev *indio_dev)
-{
-	int ret = 0;
-	struct iio_buffer *ring;
-
-	ring = iio_sw_rb_allocate(indio_dev);
-	if (!ring) {
-		ret = -ENOMEM;
-		return ret;
-	}
-	indio_dev->buffer = ring;
-	ring->scan_timestamp = true;
-	indio_dev->setup_ops = &adis16240_ring_setup_ops;
-
-	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-						 &adis16240_trigger_handler,
-						 IRQF_ONESHOT,
-						 indio_dev,
-						 "%s_consumer%d",
-						 indio_dev->name,
-						 indio_dev->id);
-	if (indio_dev->pollfunc == NULL) {
-		ret = -ENOMEM;
-		goto error_iio_sw_rb_free;
-	}
-
-	indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-	return 0;
-
-error_iio_sw_rb_free:
-	iio_sw_rb_free(indio_dev->buffer);
-	return ret;
-}
diff --git a/drivers/staging/iio/accel/adis16240_trigger.c b/drivers/staging/iio/accel/adis16240_trigger.c
deleted file mode 100644
index fa90a22..0000000
--- a/drivers/staging/iio/accel/adis16240_trigger.c
+++ /dev/null
@@ -1,82 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16240.h"
-
-/**
- * adis16240_data_rdy_trig_poll() the event handler for the data rdy trig
- **/
-static irqreturn_t adis16240_data_rdy_trig_poll(int irq, void *trig)
-{
-	iio_trigger_poll(trig, iio_get_time_ns());
-	return IRQ_HANDLED;
-}
-
-/**
- * adis16240_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16240_data_rdy_trigger_set_state(struct iio_trigger *trig,
-						bool state)
-{
-	struct iio_dev *indio_dev = trig->private_data;
-
-	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16240_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16240_trigger_ops = {
-	.owner = THIS_MODULE,
-	.set_trigger_state = &adis16240_data_rdy_trigger_set_state,
-};
-
-int adis16240_probe_trigger(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct adis16240_state *st = iio_priv(indio_dev);
-
-	st->trig = iio_trigger_alloc("adis16240-dev%d", indio_dev->id);
-	if (st->trig == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-
-	ret = request_irq(st->us->irq,
-			  adis16240_data_rdy_trig_poll,
-			  IRQF_TRIGGER_RISING,
-			  "adis16240",
-			  st->trig);
-	if (ret)
-		goto error_free_trig;
-
-	st->trig->dev.parent = &st->us->dev;
-	st->trig->ops = &adis16240_trigger_ops;
-	st->trig->private_data = indio_dev;
-	ret = iio_trigger_register(st->trig);
-
-	/* select default trigger */
-	indio_dev->trig = st->trig;
-	if (ret)
-		goto error_free_irq;
-
-	return 0;
-
-error_free_irq:
-	free_irq(st->us->irq, st->trig);
-error_free_trig:
-	iio_trigger_free(st->trig);
-error_ret:
-	return ret;
-}
-
-void adis16240_remove_trigger(struct iio_dev *indio_dev)
-{
-	struct adis16240_state *st = iio_priv(indio_dev);
-
-	iio_trigger_unregister(st->trig);
-	free_irq(st->us->irq, st->trig);
-	iio_trigger_free(st->trig);
-}
diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c
index fdd5fbd..318331f 100644
--- a/drivers/staging/iio/accel/kxsd9.c
+++ b/drivers/staging/iio/accel/kxsd9.c
@@ -171,7 +171,7 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev,
 		*val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK];
 		ret = IIO_VAL_INT_PLUS_MICRO;
 		break;
-	};
+	}
 
 error_ret:
 	return ret;
@@ -200,7 +200,7 @@ static const struct attribute_group kxsd9_attribute_group = {
 	.attrs = kxsd9_attributes,
 };
 
-static int __devinit kxsd9_power_up(struct kxsd9_state *st)
+static int kxsd9_power_up(struct kxsd9_state *st)
 {
 	int ret;
 
@@ -222,7 +222,7 @@ static const struct iio_info kxsd9_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit kxsd9_probe(struct spi_device *spi)
+static int kxsd9_probe(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev;
 	struct kxsd9_state *st;
@@ -261,7 +261,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit kxsd9_remove(struct spi_device *spi)
+static int kxsd9_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
 	iio_device_free(spi_get_drvdata(spi));
@@ -281,7 +281,7 @@ static struct spi_driver kxsd9_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = kxsd9_probe,
-	.remove = __devexit_p(kxsd9_remove),
+	.remove = kxsd9_remove,
 	.id_table = kxsd9_id,
 };
 module_spi_driver(kxsd9_driver);
diff --git a/drivers/staging/iio/accel/lis3l02dq.h b/drivers/staging/iio/accel/lis3l02dq.h
index f9bcd41..2bac722 100644
--- a/drivers/staging/iio/accel/lis3l02dq.h
+++ b/drivers/staging/iio/accel/lis3l02dq.h
@@ -158,6 +158,7 @@ struct lis3l02dq_state {
 	struct spi_device		*us;
 	struct iio_trigger		*trig;
 	struct mutex			buf_lock;
+	int				gpio;
 	bool				trigger_on;
 
 	u8	tx[LIS3L02DQ_MAX_RX] ____cacheline_aligned;
diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c
index 21b0469..37ed1b8 100644
--- a/drivers/staging/iio/accel/lis3l02dq_core.c
+++ b/drivers/staging/iio/accel/lis3l02dq_core.c
@@ -15,6 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
+#include <linux/of_gpio.h>
 #include <linux/mutex.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
@@ -674,7 +675,7 @@ static const struct iio_info lis3l02dq_info = {
 	.attrs = &lis3l02dq_attribute_group,
 };
 
-static int __devinit lis3l02dq_probe(struct spi_device *spi)
+static int lis3l02dq_probe(struct spi_device *spi)
 {
 	int ret;
 	struct lis3l02dq_state *st;
@@ -690,6 +691,7 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi)
 	spi_set_drvdata(spi, indio_dev);
 
 	st->us = spi;
+	st->gpio = of_get_gpio(spi->dev.of_node, 0);
 	mutex_init(&st->buf_lock);
 	indio_dev->name = spi->dev.driver->name;
 	indio_dev->dev.parent = &spi->dev;
@@ -711,7 +713,7 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi)
 		goto error_unreg_buffer_funcs;
 	}
 
-	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) {
+	if (spi->irq) {
 		ret = request_threaded_irq(st->us->irq,
 					   &lis3l02dq_th,
 					   &lis3l02dq_event_handler,
@@ -738,10 +740,10 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi)
 	return 0;
 
 error_remove_trigger:
-	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)))
+	if (spi->irq)
 		lis3l02dq_remove_trigger(indio_dev);
 error_free_interrupt:
-	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
+	if (spi->irq)
 		free_irq(st->us->irq, indio_dev);
 error_uninitialize_buffer:
 	iio_buffer_unregister(indio_dev);
@@ -780,7 +782,7 @@ err_ret:
 }
 
 /* fixme, confirm ordering in this function */
-static int __devexit lis3l02dq_remove(struct spi_device *spi)
+static int lis3l02dq_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 	struct lis3l02dq_state *st = iio_priv(indio_dev);
@@ -790,7 +792,7 @@ static int __devexit lis3l02dq_remove(struct spi_device *spi)
 	lis3l02dq_disable_all_events(indio_dev);
 	lis3l02dq_stop_device(indio_dev);
 
-	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
+	if (spi->irq)
 		free_irq(st->us->irq, indio_dev);
 
 	lis3l02dq_remove_trigger(indio_dev);
@@ -808,7 +810,7 @@ static struct spi_driver lis3l02dq_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = lis3l02dq_probe,
-	.remove = __devexit_p(lis3l02dq_remove),
+	.remove = lis3l02dq_remove,
 };
 module_spi_driver(lis3l02dq_driver);
 
diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c
index fa4190d..bc38651 100644
--- a/drivers/staging/iio/accel/lis3l02dq_ring.c
+++ b/drivers/staging/iio/accel/lis3l02dq_ring.c
@@ -154,7 +154,7 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p)
 	if (indio_dev->scan_timestamp)
 		*(s64 *)((u8 *)data + ALIGN(len, sizeof(s64)))
 			= pf->timestamp;
-	iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
+	iio_push_to_buffers(indio_dev, (u8 *)data);
 
 	kfree(data);
 done:
@@ -237,7 +237,7 @@ static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig,
 	u8 t;
 
 	__lis3l02dq_write_data_ready_config(indio_dev, state);
-	if (state == false) {
+	if (!state) {
 		/*
 		 * A possible quirk with the handler is currently worked around
 		 * by ensuring outstanding read events are cleared.
@@ -263,7 +263,7 @@ static int lis3l02dq_trig_try_reen(struct iio_trigger *trig)
 	/* If gpio still high (or high again)
 	 * In theory possible we will need to do this several times */
 	for (i = 0; i < 5; i++)
-		if (gpio_get_value(irq_to_gpio(st->us->irq)))
+		if (gpio_get_value(st->gpio))
 			lis3l02dq_read_all(indio_dev, NULL);
 		else
 			break;
diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
index ffd1697..414d3ca 100644
--- a/drivers/staging/iio/accel/sca3000_core.c
+++ b/drivers/staging/iio/accel/sca3000_core.c
@@ -1139,7 +1139,7 @@ static const struct iio_info sca3000_info_with_temp = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit sca3000_probe(struct spi_device *spi)
+static int sca3000_probe(struct spi_device *spi)
 {
 	int ret;
 	struct sca3000_state *st;
@@ -1233,7 +1233,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit sca3000_remove(struct spi_device *spi)
+static int sca3000_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 	struct sca3000_state *st = iio_priv(indio_dev);
@@ -1265,7 +1265,7 @@ static struct spi_driver sca3000_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = sca3000_probe,
-	.remove = __devexit_p(sca3000_remove),
+	.remove = sca3000_remove,
 	.id_table = sca3000_id,
 };
 module_spi_driver(sca3000_driver);
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index a525143..dc8582b 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -10,17 +10,6 @@ config AD7291
 	  Say yes here to build support for Analog Devices AD7291
 	  8 Channel ADC with temperature sensor.
 
-config AD7298
-	tristate "Analog Devices AD7298 ADC driver"
-	depends on SPI
-	select IIO_TRIGGERED_BUFFER if IIO_BUFFER
-	help
-	  Say yes here to build support for Analog Devices AD7298
-	  8 Channel ADC with temperature sensor.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called ad7298.
-
 config AD7606
 	tristate "Analog Devices AD7606 ADC driver"
 	depends on GPIOLIB
@@ -68,19 +57,6 @@ config AD799X_RING_BUFFER
 	  Say yes here to include ring buffer support in the AD799X
 	  ADC driver.
 
-config AD7887
-	tristate "Analog Devices AD7887 ADC driver"
-	depends on SPI
-	select IIO_BUFFER
-	select IIO_TRIGGERED_BUFFER
-	help
-	  Say yes here to build support for Analog Devices
-	  AD7887 SPI analog to digital converter (ADC).
-	  If unsure, say N (but it's safe to say "Y").
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called ad7887.
-
 config AD7780
 	tristate "Analog Devices AD7780 and similar ADCs driver"
 	depends on SPI
@@ -126,18 +102,11 @@ config AD7192
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad7192.
 
-config ADT7310
-	tristate "Analog Devices ADT7310 temperature sensor driver"
-	depends on SPI
-	help
-	  Say yes here to build support for Analog Devices ADT7310
-	  temperature sensors.
-
 config ADT7410
-	tristate "Analog Devices ADT7410 temperature sensor driver"
-	depends on I2C
+	tristate "Analog Devices ADT7310/ADT7410 temperature sensor driver"
+	depends on I2C || SPI_MASTER
 	help
-	  Say yes here to build support for Analog Devices ADT7410
+	  Say yes here to build support for Analog Devices ADT7310/ADT7410
 	  temperature sensors.
 
 config AD7280
@@ -150,30 +119,6 @@ config AD7280
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad7280a
 
-config MAX1363
-	tristate "Maxim max1363 ADC driver"
-	depends on I2C
-	select IIO_TRIGGER if IIO_BUFFER
-	select MAX1363_RING_BUFFER
-	help
-	  Say yes here to build support for many Maxim i2c analog to digital
-	  converters (ADC). (max1361, max1362, max1363, max1364, max1036,
-	  max1037, max1038, max1039, max1136, max1136, max1137, max1138,
-	  max1139, max1236, max1237, max11238, max1239, max11600, max11601,
-	  max11602, max11603, max11604, max11605, max11606, max11607,
-	  max11608, max11609, max11610, max11611, max11612, max11613,
-	  max11614, max11615, max11616, max11617, max11644, max11645,
-	  max11646, max11647) Provides direct access via sysfs.
-
-config MAX1363_RING_BUFFER
-	bool "Maxim max1363: use ring buffer"
-	depends on MAX1363
-	select IIO_BUFFER
-	select IIO_SW_RING
-	help
-	  Say yes here to include ring buffer support in the MAX1363
-	  ADC driver.
-
 config LPC32XX_ADC
 	tristate "NXP LPC32XX ADC"
 	depends on ARCH_LPC32XX
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
index 62ee02e..7281451 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
@@ -2,11 +2,6 @@
 # Makefile for industrial I/O ADC drivers
 #
 
-max1363-y := max1363_core.o
-max1363-y += max1363_ring.o
-
-obj-$(CONFIG_MAX1363) += max1363.o
-
 ad7606-y := ad7606_core.o
 ad7606-$(CONFIG_IIO_BUFFER) += ad7606_ring.o
 ad7606-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o
@@ -17,20 +12,11 @@ ad799x-y := ad799x_core.o
 ad799x-$(CONFIG_AD799X_RING_BUFFER) += ad799x_ring.o
 obj-$(CONFIG_AD799X) += ad799x.o
 
-ad7887-y := ad7887_core.o
-ad7887-$(CONFIG_IIO_BUFFER) += ad7887_ring.o
-obj-$(CONFIG_AD7887) += ad7887.o
-
-ad7298-y := ad7298_core.o
-ad7298-$(CONFIG_IIO_BUFFER) += ad7298_ring.o
-obj-$(CONFIG_AD7298) += ad7298.o
-
 obj-$(CONFIG_AD7291) += ad7291.o
 obj-$(CONFIG_AD7780) += ad7780.o
 obj-$(CONFIG_AD7793) += ad7793.o
 obj-$(CONFIG_AD7816) += ad7816.o
 obj-$(CONFIG_AD7192) += ad7192.o
-obj-$(CONFIG_ADT7310) += adt7310.o
 obj-$(CONFIG_ADT7410) += adt7410.o
 obj-$(CONFIG_AD7280) += ad7280a.o
 obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
index aeaa61d..5047019 100644
--- a/drivers/staging/iio/adc/ad7192.c
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -606,7 +606,7 @@ static const struct iio_chan_spec ad7192_channels[] = {
 	IIO_CHAN_SOFT_TIMESTAMP(8),
 };
 
-static int __devinit ad7192_probe(struct spi_device *spi)
+static int ad7192_probe(struct spi_device *spi)
 {
 	const struct ad7192_platform_data *pdata = spi->dev.platform_data;
 	struct ad7192_state *st;
@@ -686,7 +686,7 @@ error_put_reg:
 	return ret;
 }
 
-static int __devexit ad7192_remove(struct spi_device *spi)
+static int ad7192_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 	struct ad7192_state *st = iio_priv(indio_dev);
@@ -716,7 +716,7 @@ static struct spi_driver ad7192_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= ad7192_probe,
-	.remove		= __devexit_p(ad7192_remove),
+	.remove		= ad7192_remove,
 	.id_table	= ad7192_id,
 };
 module_spi_driver(ad7192_driver);
diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c
index cfc39a7..fa81a49 100644
--- a/drivers/staging/iio/adc/ad7280a.c
+++ b/drivers/staging/iio/adc/ad7280a.c
@@ -117,7 +117,7 @@
  */
 #define POLYNOM		0x2F
 #define POLYNOM_ORDER	8
-#define HIGHBIT		1 << (POLYNOM_ORDER - 1);
+#define HIGHBIT		(1 << (POLYNOM_ORDER - 1))
 
 struct ad7280_state {
 	struct spi_device		*spi;
@@ -832,7 +832,7 @@ static const struct ad7280_platform_data ad7793_default_pdata = {
 	.thermistor_term_en = true,
 };
 
-static int __devinit ad7280_probe(struct spi_device *spi)
+static int ad7280_probe(struct spi_device *spi)
 {
 	const struct ad7280_platform_data *pdata = spi->dev.platform_data;
 	struct ad7280_state *st;
@@ -950,7 +950,7 @@ error_free_device:
 	return ret;
 }
 
-static int __devexit ad7280_remove(struct spi_device *spi)
+static int ad7280_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 	struct ad7280_state *st = iio_priv(indio_dev);
@@ -981,7 +981,7 @@ static struct spi_driver ad7280_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= ad7280_probe,
-	.remove		= __devexit_p(ad7280_remove),
+	.remove		= ad7280_remove,
 	.id_table	= ad7280_id,
 };
 module_spi_driver(ad7280_driver);
diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c
index 029b39c..6e58e36 100644
--- a/drivers/staging/iio/adc/ad7291.c
+++ b/drivers/staging/iio/adc/ad7291.c
@@ -580,7 +580,7 @@ static const struct iio_info ad7291_info = {
 	.event_attrs = &ad7291_event_attribute_group,
 };
 
-static int __devinit ad7291_probe(struct i2c_client *client,
+static int ad7291_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	struct ad7291_chip_info *chip;
@@ -674,7 +674,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit ad7291_remove(struct i2c_client *client)
+static int ad7291_remove(struct i2c_client *client)
 {
 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 	struct ad7291_chip_info *chip = iio_priv(indio_dev);
@@ -706,7 +706,7 @@ static struct i2c_driver ad7291_driver = {
 		.name = KBUILD_MODNAME,
 	},
 	.probe = ad7291_probe,
-	.remove = __devexit_p(ad7291_remove),
+	.remove = ad7291_remove,
 	.id_table = ad7291_id,
 };
 module_i2c_driver(ad7291_driver);
diff --git a/drivers/staging/iio/adc/ad7298.h b/drivers/staging/iio/adc/ad7298.h
deleted file mode 100644
index 18f2787..0000000
--- a/drivers/staging/iio/adc/ad7298.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * AD7298 SPI ADC driver
- *
- * Copyright 2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
- */
-
-#ifndef IIO_ADC_AD7298_H_
-#define IIO_ADC_AD7298_H_
-
-#define AD7298_WRITE	(1 << 15) /* write to the control register */
-#define AD7298_REPEAT	(1 << 14) /* repeated conversion enable */
-#define AD7298_CH(x)	(1 << (13 - (x))) /* channel select */
-#define AD7298_TSENSE	(1 << 5) /* temperature conversion enable */
-#define AD7298_EXTREF	(1 << 2) /* external reference enable */
-#define AD7298_TAVG	(1 << 1) /* temperature sensor averaging enable */
-#define AD7298_PDD	(1 << 0) /* partial power down enable */
-
-#define AD7298_MAX_CHAN		8
-#define AD7298_BITS		12
-#define AD7298_STORAGE_BITS	16
-#define AD7298_INTREF_mV	2500
-
-#define AD7298_CH_TEMP		9
-
-#define RES_MASK(bits)	((1 << (bits)) - 1)
-
-/*
- * TODO: struct ad7298_platform_data needs to go into include/linux/iio
- */
-
-struct ad7298_platform_data {
-	/* External Vref voltage applied */
-	u16				vref_mv;
-};
-
-struct ad7298_state {
-	struct spi_device		*spi;
-	struct regulator		*reg;
-	u16				int_vref_mv;
-	unsigned			ext_ref;
-	struct spi_transfer		ring_xfer[10];
-	struct spi_transfer		scan_single_xfer[3];
-	struct spi_message		ring_msg;
-	struct spi_message		scan_single_msg;
-	/*
-	 * DMA (thus cache coherency maintenance) requires the
-	 * transfer buffers to live in their own cache lines.
-	 */
-	unsigned short			rx_buf[8] ____cacheline_aligned;
-	unsigned short			tx_buf[2];
-};
-
-#ifdef CONFIG_IIO_BUFFER
-int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev);
-void ad7298_ring_cleanup(struct iio_dev *indio_dev);
-int ad7298_update_scan_mode(struct iio_dev *indio_dev,
-	const unsigned long *active_scan_mask);
-#else /* CONFIG_IIO_BUFFER */
-
-static inline int
-ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline void ad7298_ring_cleanup(struct iio_dev *indio_dev)
-{
-}
-
-#define ad7298_update_scan_mode NULL
-
-#endif /* CONFIG_IIO_BUFFER */
-#endif /* IIO_ADC_AD7298_H_ */
diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c
deleted file mode 100644
index 4c75114..0000000
--- a/drivers/staging/iio/adc/ad7298_core.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * AD7298 SPI ADC driver
- *
- * Copyright 2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
- */
-
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/spi/spi.h>
-#include <linux/regulator/consumer.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/buffer.h>
-
-#include "ad7298.h"
-
-#define AD7298_V_CHAN(index)						\
-	{								\
-		.type = IIO_VOLTAGE,					\
-		.indexed = 1,						\
-		.channel = index,					\
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |		\
-		IIO_CHAN_INFO_SCALE_SHARED_BIT,				\
-		.address = index,					\
-		.scan_index = index,					\
-		.scan_type = {						\
-			.sign = 'u',					\
-			.realbits = 12,					\
-			.storagebits = 16,				\
-		},							\
-	}
-
-static const struct iio_chan_spec ad7298_channels[] = {
-	{
-		.type = IIO_TEMP,
-		.indexed = 1,
-		.channel = 0,
-		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-		.address = AD7298_CH_TEMP,
-		.scan_index = -1,
-		.scan_type = {
-			.sign = 's',
-			.realbits = 32,
-			.storagebits = 32,
-		},
-	},
-	AD7298_V_CHAN(0),
-	AD7298_V_CHAN(1),
-	AD7298_V_CHAN(2),
-	AD7298_V_CHAN(3),
-	AD7298_V_CHAN(4),
-	AD7298_V_CHAN(5),
-	AD7298_V_CHAN(6),
-	AD7298_V_CHAN(7),
-	IIO_CHAN_SOFT_TIMESTAMP(8),
-};
-
-static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch)
-{
-	int ret;
-	st->tx_buf[0] = cpu_to_be16(AD7298_WRITE | st->ext_ref |
-				   (AD7298_CH(0) >> ch));
-
-	ret = spi_sync(st->spi, &st->scan_single_msg);
-	if (ret)
-		return ret;
-
-	return be16_to_cpu(st->rx_buf[0]);
-}
-
-static int ad7298_scan_temp(struct ad7298_state *st, int *val)
-{
-	int tmp, ret;
-	__be16 buf;
-
-	buf = cpu_to_be16(AD7298_WRITE | AD7298_TSENSE |
-			  AD7298_TAVG | st->ext_ref);
-
-	ret = spi_write(st->spi, (u8 *)&buf, 2);
-	if (ret)
-		return ret;
-
-	buf = cpu_to_be16(0);
-
-	ret = spi_write(st->spi, (u8 *)&buf, 2);
-	if (ret)
-		return ret;
-
-	usleep_range(101, 1000); /* sleep > 100us */
-
-	ret = spi_read(st->spi, (u8 *)&buf, 2);
-	if (ret)
-		return ret;
-
-	tmp = be16_to_cpu(buf) & RES_MASK(AD7298_BITS);
-
-	/*
-	 * One LSB of the ADC corresponds to 0.25 deg C.
-	 * The temperature reading is in 12-bit twos complement format
-	 */
-
-	if (tmp & (1 << (AD7298_BITS - 1))) {
-		tmp = (4096 - tmp) * 250;
-		tmp -= (2 * tmp);
-
-	} else {
-		tmp *= 250; /* temperature in milli degrees Celsius */
-	}
-
-	*val = tmp;
-
-	return 0;
-}
-
-static int ad7298_read_raw(struct iio_dev *indio_dev,
-			   struct iio_chan_spec const *chan,
-			   int *val,
-			   int *val2,
-			   long m)
-{
-	int ret;
-	struct ad7298_state *st = iio_priv(indio_dev);
-	unsigned int scale_uv;
-
-	switch (m) {
-	case IIO_CHAN_INFO_RAW:
-		mutex_lock(&indio_dev->mlock);
-		if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
-			ret = -EBUSY;
-		} else {
-			if (chan->address == AD7298_CH_TEMP)
-				ret = ad7298_scan_temp(st, val);
-			else
-				ret = ad7298_scan_direct(st, chan->address);
-		}
-		mutex_unlock(&indio_dev->mlock);
-
-		if (ret < 0)
-			return ret;
-
-		if (chan->address != AD7298_CH_TEMP)
-			*val = ret & RES_MASK(AD7298_BITS);
-
-		return IIO_VAL_INT;
-	case IIO_CHAN_INFO_SCALE:
-		switch (chan->type) {
-		case IIO_VOLTAGE:
-			scale_uv = (st->int_vref_mv * 1000) >> AD7298_BITS;
-			*val =  scale_uv / 1000;
-			*val2 = (scale_uv % 1000) * 1000;
-			return IIO_VAL_INT_PLUS_MICRO;
-		case IIO_TEMP:
-			*val =  1;
-			*val2 = 0;
-			return IIO_VAL_INT_PLUS_MICRO;
-		default:
-			return -EINVAL;
-		}
-	}
-	return -EINVAL;
-}
-
-static const struct iio_info ad7298_info = {
-	.read_raw = &ad7298_read_raw,
-	.update_scan_mode = ad7298_update_scan_mode,
-	.driver_module = THIS_MODULE,
-};
-
-static int __devinit ad7298_probe(struct spi_device *spi)
-{
-	struct ad7298_platform_data *pdata = spi->dev.platform_data;
-	struct ad7298_state *st;
-	int ret;
-	struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
-
-	if (indio_dev == NULL)
-		return -ENOMEM;
-
-	st = iio_priv(indio_dev);
-
-	st->reg = regulator_get(&spi->dev, "vcc");
-	if (!IS_ERR(st->reg)) {
-		ret = regulator_enable(st->reg);
-		if (ret)
-			goto error_put_reg;
-	}
-
-	spi_set_drvdata(spi, indio_dev);
-
-	st->spi = spi;
-
-	indio_dev->name = spi_get_device_id(spi)->name;
-	indio_dev->dev.parent = &spi->dev;
-	indio_dev->modes = INDIO_DIRECT_MODE;
-	indio_dev->channels = ad7298_channels;
-	indio_dev->num_channels = ARRAY_SIZE(ad7298_channels);
-	indio_dev->info = &ad7298_info;
-
-	/* Setup default message */
-
-	st->scan_single_xfer[0].tx_buf = &st->tx_buf[0];
-	st->scan_single_xfer[0].len = 2;
-	st->scan_single_xfer[0].cs_change = 1;
-	st->scan_single_xfer[1].tx_buf = &st->tx_buf[1];
-	st->scan_single_xfer[1].len = 2;
-	st->scan_single_xfer[1].cs_change = 1;
-	st->scan_single_xfer[2].rx_buf = &st->rx_buf[0];
-	st->scan_single_xfer[2].len = 2;
-
-	spi_message_init(&st->scan_single_msg);
-	spi_message_add_tail(&st->scan_single_xfer[0], &st->scan_single_msg);
-	spi_message_add_tail(&st->scan_single_xfer[1], &st->scan_single_msg);
-	spi_message_add_tail(&st->scan_single_xfer[2], &st->scan_single_msg);
-
-	if (pdata && pdata->vref_mv) {
-		st->int_vref_mv = pdata->vref_mv;
-		st->ext_ref = AD7298_EXTREF;
-	} else {
-		st->int_vref_mv = AD7298_INTREF_mV;
-	}
-
-	ret = ad7298_register_ring_funcs_and_init(indio_dev);
-	if (ret)
-		goto error_disable_reg;
-
-	ret = iio_device_register(indio_dev);
-	if (ret)
-		goto error_cleanup_ring;
-
-	return 0;
-
-error_cleanup_ring:
-	ad7298_ring_cleanup(indio_dev);
-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;
-}
-
-static int __devexit ad7298_remove(struct spi_device *spi)
-{
-	struct iio_dev *indio_dev = spi_get_drvdata(spi);
-	struct ad7298_state *st = iio_priv(indio_dev);
-
-	iio_device_unregister(indio_dev);
-	ad7298_ring_cleanup(indio_dev);
-	if (!IS_ERR(st->reg)) {
-		regulator_disable(st->reg);
-		regulator_put(st->reg);
-	}
-	iio_device_free(indio_dev);
-
-	return 0;
-}
-
-static const struct spi_device_id ad7298_id[] = {
-	{"ad7298", 0},
-	{}
-};
-MODULE_DEVICE_TABLE(spi, ad7298_id);
-
-static struct spi_driver ad7298_driver = {
-	.driver = {
-		.name	= "ad7298",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= ad7298_probe,
-	.remove		= __devexit_p(ad7298_remove),
-	.id_table	= ad7298_id,
-};
-module_spi_driver(ad7298_driver);
-
-MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("Analog Devices AD7298 ADC");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c
deleted file mode 100644
index c2906a8..0000000
--- a/drivers/staging/iio/adc/ad7298_ring.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * AD7298 SPI ADC driver
- *
- * Copyright 2011-2012 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
- */
-
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/triggered_buffer.h>
-
-#include "ad7298.h"
-
-/**
- * ad7298_update_scan_mode() setup the spi transfer buffer for the new scan mask
- **/
-int ad7298_update_scan_mode(struct iio_dev *indio_dev,
-	const unsigned long *active_scan_mask)
-{
-	struct ad7298_state *st = iio_priv(indio_dev);
-	int i, m;
-	unsigned short command;
-	int scan_count;
-
-	/* Now compute overall size */
-	scan_count = bitmap_weight(active_scan_mask, indio_dev->masklength);
-
-	command = AD7298_WRITE | st->ext_ref;
-
-	for (i = 0, m = AD7298_CH(0); i < AD7298_MAX_CHAN; i++, m >>= 1)
-		if (test_bit(i, active_scan_mask))
-			command |= m;
-
-	st->tx_buf[0] = cpu_to_be16(command);
-
-	/* build spi ring message */
-	st->ring_xfer[0].tx_buf = &st->tx_buf[0];
-	st->ring_xfer[0].len = 2;
-	st->ring_xfer[0].cs_change = 1;
-	st->ring_xfer[1].tx_buf = &st->tx_buf[1];
-	st->ring_xfer[1].len = 2;
-	st->ring_xfer[1].cs_change = 1;
-
-	spi_message_init(&st->ring_msg);
-	spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg);
-	spi_message_add_tail(&st->ring_xfer[1], &st->ring_msg);
-
-	for (i = 0; i < scan_count; i++) {
-		st->ring_xfer[i + 2].rx_buf = &st->rx_buf[i];
-		st->ring_xfer[i + 2].len = 2;
-		st->ring_xfer[i + 2].cs_change = 1;
-		spi_message_add_tail(&st->ring_xfer[i + 2], &st->ring_msg);
-	}
-	/* make sure last transfer cs_change is not set */
-	st->ring_xfer[i + 1].cs_change = 0;
-
-	return 0;
-}
-
-/**
- * ad7298_trigger_handler() bh of trigger launched polling to ring buffer
- *
- * Currently there is no option in this driver to disable the saving of
- * timestamps within the ring.
- **/
-static irqreturn_t ad7298_trigger_handler(int irq, void *p)
-{
-	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;
-	__u16 buf[16];
-	int b_sent, i;
-
-	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 *)buf + indio_dev->scan_bytes - sizeof(s64),
-			&time_ns, sizeof(time_ns));
-	}
-
-	for (i = 0; i < bitmap_weight(indio_dev->active_scan_mask,
-						 indio_dev->masklength); i++)
-		buf[i] = be16_to_cpu(st->rx_buf[i]);
-
-	iio_push_to_buffer(indio_dev->buffer, (u8 *)buf);
-
-done:
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
-	return iio_triggered_buffer_setup(indio_dev, NULL,
-			&ad7298_trigger_handler, NULL);
-}
-
-void ad7298_ring_cleanup(struct iio_dev *indio_dev)
-{
-	iio_triggered_buffer_cleanup(indio_dev);
-}
diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c
index a53faaf..58cfdde 100644
--- a/drivers/staging/iio/adc/ad7606_par.c
+++ b/drivers/staging/iio/adc/ad7606_par.c
@@ -47,7 +47,7 @@ static const struct ad7606_bus_ops ad7606_par8_bops = {
 	.read_block	= ad7606_par8_read_block,
 };
 
-static int __devinit ad7606_par_probe(struct platform_device *pdev)
+static int ad7606_par_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	struct iio_dev *indio_dev;
@@ -100,7 +100,7 @@ out1:
 	return ret;
 }
 
-static int __devexit ad7606_par_remove(struct platform_device *pdev)
+static int ad7606_par_remove(struct platform_device *pdev)
 {
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -164,7 +164,7 @@ MODULE_DEVICE_TABLE(platform, ad7606_driver_ids);
 
 static struct platform_driver ad7606_driver = {
 	.probe = ad7606_par_probe,
-	.remove	= __devexit_p(ad7606_par_remove),
+	.remove	= ad7606_par_remove,
 	.id_table = ad7606_driver_ids,
 	.driver = {
 		.name	 = "ad7606",
diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c
index ba04d0f..2b25cb0 100644
--- a/drivers/staging/iio/adc/ad7606_ring.c
+++ b/drivers/staging/iio/adc/ad7606_ring.c
@@ -83,7 +83,7 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s)
 	if (indio_dev->scan_timestamp)
 		*((s64 *)(buf + indio_dev->scan_bytes - sizeof(s64))) = time_ns;
 
-	iio_push_to_buffer(indio_dev->buffer, buf);
+	iio_push_to_buffers(indio_dev, buf);
 done:
 	gpio_set_value(st->pdata->gpio_convst, 0);
 	iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c
index 099d347..6a8ecd7 100644
--- a/drivers/staging/iio/adc/ad7606_spi.c
+++ b/drivers/staging/iio/adc/ad7606_spi.c
@@ -39,7 +39,7 @@ static const struct ad7606_bus_ops ad7606_spi_bops = {
 	.read_block	= ad7606_spi_read_block,
 };
 
-static int __devinit ad7606_spi_probe(struct spi_device *spi)
+static int ad7606_spi_probe(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev;
 
@@ -55,7 +55,7 @@ static int __devinit ad7606_spi_probe(struct spi_device *spi)
 	return 0;
 }
 
-static int __devexit ad7606_spi_remove(struct spi_device *spi)
+static int ad7606_spi_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev);
 
@@ -106,7 +106,7 @@ static struct spi_driver ad7606_driver = {
 		.pm    = AD7606_SPI_PM_OPS,
 	},
 	.probe = ad7606_spi_probe,
-	.remove = __devexit_p(ad7606_spi_remove),
+	.remove = ad7606_spi_remove,
 	.id_table = ad7606_id,
 };
 module_spi_driver(ad7606_driver);
diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c
index 0a1328b..e1f8860 100644
--- a/drivers/staging/iio/adc/ad7780.c
+++ b/drivers/staging/iio/adc/ad7780.c
@@ -164,7 +164,7 @@ static const struct iio_info ad7780_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit ad7780_probe(struct spi_device *spi)
+static int ad7780_probe(struct spi_device *spi)
 {
 	struct ad7780_platform_data *pdata = spi->dev.platform_data;
 	struct ad7780_state *st;
@@ -248,7 +248,7 @@ error_put_reg:
 	return ret;
 }
 
-static int __devexit ad7780_remove(struct spi_device *spi)
+static int ad7780_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 	struct ad7780_state *st = iio_priv(indio_dev);
@@ -283,7 +283,7 @@ static struct spi_driver ad7780_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= ad7780_probe,
-	.remove		= __devexit_p(ad7780_remove),
+	.remove		= ad7780_remove,
 	.id_table	= ad7780_id,
 };
 module_spi_driver(ad7780_driver);
diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
index 691a7be..b0a57e4 100644
--- a/drivers/staging/iio/adc/ad7793.c
+++ b/drivers/staging/iio/adc/ad7793.c
@@ -441,7 +441,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
 	},
 };
 
-static int __devinit ad7793_probe(struct spi_device *spi)
+static int ad7793_probe(struct spi_device *spi)
 {
 	const struct ad7793_platform_data *pdata = spi->dev.platform_data;
 	struct ad7793_state *st;
@@ -522,7 +522,7 @@ error_put_reg:
 	return ret;
 }
 
-static int __devexit ad7793_remove(struct spi_device *spi)
+static int ad7793_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 	struct ad7793_state *st = iio_priv(indio_dev);
@@ -556,7 +556,7 @@ static struct spi_driver ad7793_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= ad7793_probe,
-	.remove		= __devexit_p(ad7793_remove),
+	.remove		= ad7793_remove,
 	.id_table	= ad7793_id,
 };
 module_spi_driver(ad7793_driver);
diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c
index c5fb947..9284771 100644
--- a/drivers/staging/iio/adc/ad7816.c
+++ b/drivers/staging/iio/adc/ad7816.c
@@ -341,7 +341,7 @@ static const struct iio_info ad7816_info = {
  * device probe and remove
  */
 
-static int __devinit ad7816_probe(struct spi_device *spi_dev)
+static int ad7816_probe(struct spi_device *spi_dev)
 {
 	struct ad7816_chip_info *chip;
 	struct iio_dev *indio_dev;
@@ -431,7 +431,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit ad7816_remove(struct spi_device *spi_dev)
+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);
@@ -463,7 +463,7 @@ static struct spi_driver ad7816_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ad7816_probe,
-	.remove = __devexit_p(ad7816_remove),
+	.remove = ad7816_remove,
 	.id_table = ad7816_id,
 };
 module_spi_driver(ad7816_driver);
diff --git a/drivers/staging/iio/adc/ad7887.h b/drivers/staging/iio/adc/ad7887.h
deleted file mode 100644
index 2e09e54..0000000
--- a/drivers/staging/iio/adc/ad7887.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * AD7887 SPI ADC driver
- *
- * Copyright 2010 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-#ifndef IIO_ADC_AD7887_H_
-#define IIO_ADC_AD7887_H_
-
-#define AD7887_REF_DIS		(1 << 5) /* on-chip reference disable */
-#define AD7887_DUAL		(1 << 4) /* dual-channel mode */
-#define AD7887_CH_AIN1		(1 << 3) /* convert on channel 1, DUAL=1 */
-#define AD7887_CH_AIN0		(0 << 3) /* convert on channel 0, DUAL=0,1 */
-#define AD7887_PM_MODE1		(0)	 /* CS based shutdown */
-#define AD7887_PM_MODE2		(1)	 /* full on */
-#define AD7887_PM_MODE3		(2)	 /* auto shutdown after conversion */
-#define AD7887_PM_MODE4		(3)	 /* standby mode */
-
-enum ad7887_channels {
-	AD7887_CH0,
-	AD7887_CH0_CH1,
-	AD7887_CH1,
-};
-
-#define RES_MASK(bits)	((1 << (bits)) - 1) /* TODO: move this into a common header */
-
-/*
- * TODO: struct ad7887_platform_data needs to go into include/linux/iio
- */
-
-struct ad7887_platform_data {
-	/* External Vref voltage applied */
-	u16				vref_mv;
-	/*
-	 * AD7887:
-	 * In single channel mode en_dual = flase, AIN1/Vref pins assumes its
-	 * Vref function. In dual channel mode en_dual = true, AIN1 becomes the
-	 * second input channel, and Vref is internally connected to Vdd.
-	 */
-	bool				en_dual;
-	/*
-	 * AD7887:
-	 * use_onchip_ref = true, the Vref is internally connected to the 2.500V
-	 * Voltage reference. If use_onchip_ref = false, the reference voltage
-	 * is supplied by AIN1/Vref
-	 */
-	bool				use_onchip_ref;
-};
-
-/**
- * struct ad7887_chip_info - chip specifc information
- * @int_vref_mv:	the internal reference voltage
- * @channel:		channel specification
- */
-
-struct ad7887_chip_info {
-	u16				int_vref_mv;
-	struct iio_chan_spec		channel[3];
-};
-
-struct ad7887_state {
-	struct spi_device		*spi;
-	const struct ad7887_chip_info	*chip_info;
-	struct regulator		*reg;
-	u16				int_vref_mv;
-	struct spi_transfer		xfer[4];
-	struct spi_message		msg[3];
-	struct spi_message		*ring_msg;
-	unsigned char			tx_cmd_buf[8];
-
-	/*
-	 * DMA (thus cache coherency maintenance) requires the
-	 * transfer buffers to live in their own cache lines.
-	 */
-
-	unsigned char			data[4] ____cacheline_aligned;
-};
-
-enum ad7887_supported_device_ids {
-	ID_AD7887
-};
-
-#ifdef CONFIG_IIO_BUFFER
-int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev);
-void ad7887_ring_cleanup(struct iio_dev *indio_dev);
-#else /* CONFIG_IIO_BUFFER */
-
-static inline int
-ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline void ad7887_ring_cleanup(struct iio_dev *indio_dev)
-{
-}
-#endif /* CONFIG_IIO_BUFFER */
-#endif /* IIO_ADC_AD7887_H_ */
diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c
deleted file mode 100644
index 5517905..0000000
--- a/drivers/staging/iio/adc/ad7887_core.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * AD7887 SPI ADC driver
- *
- * Copyright 2010-2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
- */
-
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/spi/spi.h>
-#include <linux/regulator/consumer.h>
-#include <linux/err.h>
-#include <linux/module.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/buffer.h>
-
-
-#include "ad7887.h"
-
-static int ad7887_scan_direct(struct ad7887_state *st, unsigned ch)
-{
-	int ret = spi_sync(st->spi, &st->msg[ch]);
-	if (ret)
-		return ret;
-
-	return (st->data[(ch * 2)] << 8) | st->data[(ch * 2) + 1];
-}
-
-static int ad7887_read_raw(struct iio_dev *indio_dev,
-			   struct iio_chan_spec const *chan,
-			   int *val,
-			   int *val2,
-			   long m)
-{
-	int ret;
-	struct ad7887_state *st = iio_priv(indio_dev);
-	unsigned int scale_uv;
-
-	switch (m) {
-	case IIO_CHAN_INFO_RAW:
-		mutex_lock(&indio_dev->mlock);
-		if (iio_buffer_enabled(indio_dev))
-			ret = -EBUSY;
-		else
-			ret = ad7887_scan_direct(st, chan->address);
-		mutex_unlock(&indio_dev->mlock);
-
-		if (ret < 0)
-			return ret;
-		*val = (ret >> st->chip_info->channel[0].scan_type.shift) &
-			RES_MASK(st->chip_info->channel[0].scan_type.realbits);
-		return IIO_VAL_INT;
-	case IIO_CHAN_INFO_SCALE:
-		scale_uv = (st->int_vref_mv * 1000)
-			>> st->chip_info->channel[0].scan_type.realbits;
-		*val =  scale_uv/1000;
-		*val2 = (scale_uv%1000)*1000;
-		return IIO_VAL_INT_PLUS_MICRO;
-	}
-	return -EINVAL;
-}
-
-
-static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
-	/*
-	 * More devices added in future
-	 */
-	[ID_AD7887] = {
-		.channel[0] = {
-			.type = IIO_VOLTAGE,
-			.indexed = 1,
-			.channel = 1,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SHARED_BIT,
-			.address = 1,
-			.scan_index = 1,
-			.scan_type = IIO_ST('u', 12, 16, 0),
-		},
-		.channel[1] = {
-			.type = IIO_VOLTAGE,
-			.indexed = 1,
-			.channel = 0,
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-			IIO_CHAN_INFO_SCALE_SHARED_BIT,
-			.address = 0,
-			.scan_index = 0,
-			.scan_type = IIO_ST('u', 12, 16, 0),
-		},
-		.channel[2] = IIO_CHAN_SOFT_TIMESTAMP(2),
-		.int_vref_mv = 2500,
-	},
-};
-
-static const struct iio_info ad7887_info = {
-	.read_raw = &ad7887_read_raw,
-	.driver_module = THIS_MODULE,
-};
-
-static int __devinit ad7887_probe(struct spi_device *spi)
-{
-	struct ad7887_platform_data *pdata = spi->dev.platform_data;
-	struct ad7887_state *st;
-	int ret, voltage_uv = 0;
-	struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
-
-	if (indio_dev == NULL)
-		return -ENOMEM;
-
-	st = iio_priv(indio_dev);
-
-	st->reg = regulator_get(&spi->dev, "vcc");
-	if (!IS_ERR(st->reg)) {
-		ret = regulator_enable(st->reg);
-		if (ret)
-			goto error_put_reg;
-
-		voltage_uv = regulator_get_voltage(st->reg);
-	}
-
-	st->chip_info =
-		&ad7887_chip_info_tbl[spi_get_device_id(spi)->driver_data];
-
-	spi_set_drvdata(spi, indio_dev);
-	st->spi = spi;
-
-	/* Estabilish that the iio_dev is a child of the spi device */
-	indio_dev->dev.parent = &spi->dev;
-	indio_dev->name = spi_get_device_id(spi)->name;
-	indio_dev->info = &ad7887_info;
-	indio_dev->modes = INDIO_DIRECT_MODE;
-
-	/* Setup default message */
-
-	st->tx_cmd_buf[0] = AD7887_CH_AIN0 | AD7887_PM_MODE4 |
-			    ((pdata && pdata->use_onchip_ref) ?
-			    0 : AD7887_REF_DIS);
-
-	st->xfer[0].rx_buf = &st->data[0];
-	st->xfer[0].tx_buf = &st->tx_cmd_buf[0];
-	st->xfer[0].len = 2;
-
-	spi_message_init(&st->msg[AD7887_CH0]);
-	spi_message_add_tail(&st->xfer[0], &st->msg[AD7887_CH0]);
-
-	if (pdata && pdata->en_dual) {
-		st->tx_cmd_buf[0] |= AD7887_DUAL | AD7887_REF_DIS;
-
-		st->tx_cmd_buf[2] = AD7887_CH_AIN1 | AD7887_DUAL |
-				    AD7887_REF_DIS | AD7887_PM_MODE4;
-		st->tx_cmd_buf[4] = AD7887_CH_AIN0 | AD7887_DUAL |
-				    AD7887_REF_DIS | AD7887_PM_MODE4;
-		st->tx_cmd_buf[6] = AD7887_CH_AIN1 | AD7887_DUAL |
-				    AD7887_REF_DIS | AD7887_PM_MODE4;
-
-		st->xfer[1].rx_buf = &st->data[0];
-		st->xfer[1].tx_buf = &st->tx_cmd_buf[2];
-		st->xfer[1].len = 2;
-
-		st->xfer[2].rx_buf = &st->data[2];
-		st->xfer[2].tx_buf = &st->tx_cmd_buf[4];
-		st->xfer[2].len = 2;
-
-		spi_message_init(&st->msg[AD7887_CH0_CH1]);
-		spi_message_add_tail(&st->xfer[1], &st->msg[AD7887_CH0_CH1]);
-		spi_message_add_tail(&st->xfer[2], &st->msg[AD7887_CH0_CH1]);
-
-		st->xfer[3].rx_buf = &st->data[0];
-		st->xfer[3].tx_buf = &st->tx_cmd_buf[6];
-		st->xfer[3].len = 2;
-
-		spi_message_init(&st->msg[AD7887_CH1]);
-		spi_message_add_tail(&st->xfer[3], &st->msg[AD7887_CH1]);
-
-		if (pdata && pdata->vref_mv)
-			st->int_vref_mv = pdata->vref_mv;
-		else if (voltage_uv)
-			st->int_vref_mv = voltage_uv / 1000;
-		else
-			dev_warn(&spi->dev, "reference voltage unspecified\n");
-
-		indio_dev->channels = st->chip_info->channel;
-		indio_dev->num_channels = 3;
-	} else {
-		if (pdata && pdata->vref_mv)
-			st->int_vref_mv = pdata->vref_mv;
-		else if (pdata && pdata->use_onchip_ref)
-			st->int_vref_mv = st->chip_info->int_vref_mv;
-		else
-			dev_warn(&spi->dev, "reference voltage unspecified\n");
-
-		indio_dev->channels = &st->chip_info->channel[1];
-		indio_dev->num_channels = 2;
-	}
-
-	ret = ad7887_register_ring_funcs_and_init(indio_dev);
-	if (ret)
-		goto error_disable_reg;
-
-	ret = iio_device_register(indio_dev);
-	if (ret)
-		goto error_unregister_ring;
-
-	return 0;
-error_unregister_ring:
-	ad7887_ring_cleanup(indio_dev);
-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;
-}
-
-static int __devexit ad7887_remove(struct spi_device *spi)
-{
-	struct iio_dev *indio_dev = spi_get_drvdata(spi);
-	struct ad7887_state *st = iio_priv(indio_dev);
-
-	iio_device_unregister(indio_dev);
-	ad7887_ring_cleanup(indio_dev);
-	if (!IS_ERR(st->reg)) {
-		regulator_disable(st->reg);
-		regulator_put(st->reg);
-	}
-	iio_device_free(indio_dev);
-
-	return 0;
-}
-
-static const struct spi_device_id ad7887_id[] = {
-	{"ad7887", ID_AD7887},
-	{}
-};
-MODULE_DEVICE_TABLE(spi, ad7887_id);
-
-static struct spi_driver ad7887_driver = {
-	.driver = {
-		.name	= "ad7887",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= ad7887_probe,
-	.remove		= __devexit_p(ad7887_remove),
-	.id_table	= ad7887_id,
-};
-module_spi_driver(ad7887_driver);
-
-MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("Analog Devices AD7887 ADC");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c
deleted file mode 100644
index b39923b..0000000
--- a/drivers/staging/iio/adc/ad7887_ring.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2010-2012 Analog Devices Inc.
- * Copyright (C) 2008 Jonathan Cameron
- *
- * Licensed under the GPL-2.
- *
- * ad7887_ring.c
- */
-
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/triggered_buffer.h>
-
-#include "ad7887.h"
-
-/**
- * ad7887_ring_preenable() setup the parameters of the ring before enabling
- *
- * The complex nature of the setting of the nuber of bytes per datum is due
- * to this driver currently ensuring that the timestamp is stored at an 8
- * byte boundary.
- **/
-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) {
-	case (1 << 0):
-		st->ring_msg = &st->msg[AD7887_CH0];
-		break;
-	case (1 << 1):
-		st->ring_msg = &st->msg[AD7887_CH1];
-		/* Dummy read: push CH1 setting down to hardware */
-		spi_sync(st->spi, st->ring_msg);
-		break;
-	case ((1 << 1) | (1 << 0)):
-		st->ring_msg = &st->msg[AD7887_CH0_CH1];
-		break;
-	}
-
-	return 0;
-}
-
-static int ad7887_ring_postdisable(struct iio_dev *indio_dev)
-{
-	struct ad7887_state *st = iio_priv(indio_dev);
-
-	/* dummy read: restore default CH0 settin */
-	return spi_sync(st->spi, &st->msg[AD7887_CH0]);
-}
-
-/**
- * ad7887_trigger_handler() bh of trigger launched polling to ring buffer
- *
- * Currently there is no option in this driver to disable the saving of
- * timestamps within the ring.
- **/
-static irqreturn_t ad7887_trigger_handler(int irq, void *p)
-{
-	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;
-	__u8 *buf;
-	int b_sent;
-
-	unsigned int bytes = bitmap_weight(indio_dev->active_scan_mask,
-					   indio_dev->masklength) *
-		st->chip_info->channel[0].scan_type.storagebits / 8;
-
-	buf = kzalloc(indio_dev->scan_bytes, GFP_KERNEL);
-	if (buf == NULL)
-		goto done;
-
-	b_sent = spi_sync(st->spi, st->ring_msg);
-	if (b_sent)
-		goto done;
-
-	time_ns = iio_get_time_ns();
-
-	memcpy(buf, st->data, bytes);
-	if (indio_dev->scan_timestamp)
-		memcpy(buf + indio_dev->scan_bytes - sizeof(s64),
-		       &time_ns, sizeof(time_ns));
-
-	iio_push_to_buffer(indio_dev->buffer, buf);
-done:
-	kfree(buf);
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-static const struct iio_buffer_setup_ops ad7887_ring_setup_ops = {
-	.preenable = &ad7887_ring_preenable,
-	.postenable = &iio_triggered_buffer_postenable,
-	.predisable = &iio_triggered_buffer_predisable,
-	.postdisable = &ad7887_ring_postdisable,
-};
-
-int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
-	return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
-			&ad7887_trigger_handler, &ad7887_ring_setup_ops);
-}
-
-void ad7887_ring_cleanup(struct iio_dev *indio_dev)
-{
-	iio_triggered_buffer_cleanup(indio_dev);
-}
diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c
index 9900507..077eedb 100644
--- a/drivers/staging/iio/adc/ad799x_core.c
+++ b/drivers/staging/iio/adc/ad799x_core.c
@@ -854,7 +854,7 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
 	},
 };
 
-static int __devinit ad799x_probe(struct i2c_client *client,
+static int ad799x_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
 	int ret;
@@ -932,7 +932,7 @@ error_put_reg:
 	return ret;
 }
 
-static __devexit int ad799x_remove(struct i2c_client *client)
+static int ad799x_remove(struct i2c_client *client)
 {
 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 	struct ad799x_state *st = iio_priv(indio_dev);
@@ -970,7 +970,7 @@ static struct i2c_driver ad799x_driver = {
 		.name = "ad799x",
 	},
 	.probe = ad799x_probe,
-	.remove = __devexit_p(ad799x_remove),
+	.remove = ad799x_remove,
 	.id_table = ad799x_id,
 };
 module_i2c_driver(ad799x_driver);
diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c
index 86026d9..2c5f384 100644
--- a/drivers/staging/iio/adc/ad799x_ring.c
+++ b/drivers/staging/iio/adc/ad799x_ring.c
@@ -77,7 +77,7 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p)
 		memcpy(rxbuf + indio_dev->scan_bytes - sizeof(s64),
 			&time_ns, sizeof(time_ns));
 
-	iio_push_to_buffer(indio_dev->buffer, rxbuf);
+	iio_push_to_buffers(indio_dev, rxbuf);
 done:
 	kfree(rxbuf);
 out:
diff --git a/drivers/staging/iio/adc/adt7310.c b/drivers/staging/iio/adc/adt7310.c
deleted file mode 100644
index 72460b6..0000000
--- a/drivers/staging/iio/adc/adt7310.c
+++ /dev/null
@@ -1,881 +0,0 @@
-/*
- * ADT7310 digital temperature sensor driver supporting ADT7310
- *
- * Copyright 2010 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
-#include <linux/spi/spi.h>
-#include <linux/module.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/events.h>
-/*
- * ADT7310 registers definition
- */
-
-#define ADT7310_STATUS			0
-#define ADT7310_CONFIG			1
-#define ADT7310_TEMPERATURE		2
-#define ADT7310_ID			3
-#define ADT7310_T_CRIT			4
-#define ADT7310_T_HYST			5
-#define ADT7310_T_ALARM_HIGH		6
-#define ADT7310_T_ALARM_LOW		7
-
-/*
- * ADT7310 status
- */
-#define ADT7310_STAT_T_LOW		0x10
-#define ADT7310_STAT_T_HIGH		0x20
-#define ADT7310_STAT_T_CRIT		0x40
-#define ADT7310_STAT_NOT_RDY		0x80
-
-/*
- * ADT7310 config
- */
-#define ADT7310_FAULT_QUEUE_MASK	0x3
-#define ADT7310_CT_POLARITY		0x4
-#define ADT7310_INT_POLARITY		0x8
-#define ADT7310_EVENT_MODE		0x10
-#define ADT7310_MODE_MASK		0x60
-#define ADT7310_ONESHOT			0x20
-#define ADT7310_SPS			0x40
-#define ADT7310_PD			0x60
-#define ADT7310_RESOLUTION		0x80
-
-/*
- * ADT7310 masks
- */
-#define ADT7310_T16_VALUE_SIGN			0x8000
-#define ADT7310_T16_VALUE_FLOAT_OFFSET		7
-#define ADT7310_T16_VALUE_FLOAT_MASK		0x7F
-#define ADT7310_T13_VALUE_SIGN			0x1000
-#define ADT7310_T13_VALUE_OFFSET		3
-#define ADT7310_T13_VALUE_FLOAT_OFFSET		4
-#define ADT7310_T13_VALUE_FLOAT_MASK		0xF
-#define ADT7310_T_HYST_MASK			0xF
-#define ADT7310_DEVICE_ID_MASK			0x7
-#define ADT7310_MANUFACTORY_ID_MASK		0xF8
-#define ADT7310_MANUFACTORY_ID_OFFSET		3
-
-
-#define ADT7310_CMD_REG_MASK			0x28
-#define ADT7310_CMD_REG_OFFSET			3
-#define ADT7310_CMD_READ			0x40
-#define ADT7310_CMD_CON_READ			0x4
-
-#define ADT7310_IRQS				2
-
-/*
- * struct adt7310_chip_info - chip specifc information
- */
-
-struct adt7310_chip_info {
-	struct spi_device *spi_dev;
-	u8  config;
-};
-
-/*
- * adt7310 register access by SPI
- */
-
-static int adt7310_spi_read_word(struct adt7310_chip_info *chip, u8 reg, u16 *data)
-{
-	struct spi_device *spi_dev = chip->spi_dev;
-	u8 command = (reg << ADT7310_CMD_REG_OFFSET) & ADT7310_CMD_REG_MASK;
-	int ret = 0;
-
-	command |= ADT7310_CMD_READ;
-	ret = spi_write(spi_dev, &command, sizeof(command));
-	if (ret < 0) {
-		dev_err(&spi_dev->dev, "SPI write command error\n");
-		return ret;
-	}
-
-	ret = spi_read(spi_dev, (u8 *)data, sizeof(*data));
-	if (ret < 0) {
-		dev_err(&spi_dev->dev, "SPI read word error\n");
-		return ret;
-	}
-
-	*data = be16_to_cpu(*data);
-
-	return 0;
-}
-
-static int adt7310_spi_write_word(struct adt7310_chip_info *chip, u8 reg, u16 data)
-{
-	struct spi_device *spi_dev = chip->spi_dev;
-	u8 buf[3];
-	int ret = 0;
-
-	buf[0] = (reg << ADT7310_CMD_REG_OFFSET) & ADT7310_CMD_REG_MASK;
-	buf[1] = (u8)(data >> 8);
-	buf[2] = (u8)(data & 0xFF);
-
-	ret = spi_write(spi_dev, buf, 3);
-	if (ret < 0) {
-		dev_err(&spi_dev->dev, "SPI write word error\n");
-		return ret;
-	}
-
-	return ret;
-}
-
-static int adt7310_spi_read_byte(struct adt7310_chip_info *chip, u8 reg, u8 *data)
-{
-	struct spi_device *spi_dev = chip->spi_dev;
-	u8 command = (reg << ADT7310_CMD_REG_OFFSET) & ADT7310_CMD_REG_MASK;
-	int ret = 0;
-
-	command |= ADT7310_CMD_READ;
-	ret = spi_write(spi_dev, &command, sizeof(command));
-	if (ret < 0) {
-		dev_err(&spi_dev->dev, "SPI write command error\n");
-		return ret;
-	}
-
-	ret = spi_read(spi_dev, data, sizeof(*data));
-	if (ret < 0) {
-		dev_err(&spi_dev->dev, "SPI read byte error\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static int adt7310_spi_write_byte(struct adt7310_chip_info *chip, u8 reg, u8 data)
-{
-	struct spi_device *spi_dev = chip->spi_dev;
-	u8 buf[2];
-	int ret = 0;
-
-	buf[0] = (reg << ADT7310_CMD_REG_OFFSET) & ADT7310_CMD_REG_MASK;
-	buf[1] = data;
-
-	ret = spi_write(spi_dev, buf, 2);
-	if (ret < 0) {
-		dev_err(&spi_dev->dev, "SPI write byte error\n");
-		return ret;
-	}
-
-	return ret;
-}
-
-static ssize_t adt7310_show_mode(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7310_chip_info *chip = iio_priv(dev_info);
-	u8 config;
-
-	config = chip->config & ADT7310_MODE_MASK;
-
-	switch (config) {
-	case ADT7310_PD:
-		return sprintf(buf, "power-down\n");
-	case ADT7310_ONESHOT:
-		return sprintf(buf, "one-shot\n");
-	case ADT7310_SPS:
-		return sprintf(buf, "sps\n");
-	default:
-		return sprintf(buf, "full\n");
-	}
-}
-
-static ssize_t adt7310_store_mode(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7310_chip_info *chip = iio_priv(dev_info);
-	u16 config;
-	int ret;
-
-	ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config);
-	if (ret)
-		return -EIO;
-
-	config = chip->config & (~ADT7310_MODE_MASK);
-	if (strcmp(buf, "power-down"))
-		config |= ADT7310_PD;
-	else if (strcmp(buf, "one-shot"))
-		config |= ADT7310_ONESHOT;
-	else if (strcmp(buf, "sps"))
-		config |= ADT7310_SPS;
-
-	ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, config);
-	if (ret)
-		return -EIO;
-
-	chip->config = config;
-
-	return len;
-}
-
-static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
-		adt7310_show_mode,
-		adt7310_store_mode,
-		0);
-
-static ssize_t adt7310_show_available_modes(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	return sprintf(buf, "full\none-shot\nsps\npower-down\n");
-}
-
-static IIO_DEVICE_ATTR(available_modes, S_IRUGO, adt7310_show_available_modes, NULL, 0);
-
-static ssize_t adt7310_show_resolution(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7310_chip_info *chip = iio_priv(dev_info);
-	int ret;
-	int bits;
-
-	ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config);
-	if (ret)
-		return -EIO;
-
-	if (chip->config & ADT7310_RESOLUTION)
-		bits = 16;
-	else
-		bits = 13;
-
-	return sprintf(buf, "%d bits\n", bits);
-}
-
-static ssize_t adt7310_store_resolution(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7310_chip_info *chip = iio_priv(dev_info);
-	unsigned long data;
-	u16 config;
-	int ret;
-
-	ret = strict_strtoul(buf, 10, &data);
-	if (ret)
-		return -EINVAL;
-
-	ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config);
-	if (ret)
-		return -EIO;
-
-	config = chip->config & (~ADT7310_RESOLUTION);
-	if (data)
-		config |= ADT7310_RESOLUTION;
-
-	ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, config);
-	if (ret)
-		return -EIO;
-
-	chip->config = config;
-
-	return len;
-}
-
-static IIO_DEVICE_ATTR(resolution, S_IRUGO | S_IWUSR,
-		adt7310_show_resolution,
-		adt7310_store_resolution,
-		0);
-
-static ssize_t adt7310_show_id(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7310_chip_info *chip = iio_priv(dev_info);
-	u8 id;
-	int ret;
-
-	ret = adt7310_spi_read_byte(chip, ADT7310_ID, &id);
-	if (ret)
-		return -EIO;
-
-	return sprintf(buf, "device id: 0x%x\nmanufactory id: 0x%x\n",
-			id & ADT7310_DEVICE_ID_MASK,
-			(id & ADT7310_MANUFACTORY_ID_MASK) >> ADT7310_MANUFACTORY_ID_OFFSET);
-}
-
-static IIO_DEVICE_ATTR(id, S_IRUGO | S_IWUSR,
-		adt7310_show_id,
-		NULL,
-		0);
-
-static ssize_t adt7310_convert_temperature(struct adt7310_chip_info *chip,
-		u16 data, char *buf)
-{
-	char sign = ' ';
-
-	if (chip->config & ADT7310_RESOLUTION) {
-		if (data & ADT7310_T16_VALUE_SIGN) {
-			/* convert supplement to positive value */
-			data = (u16)((ADT7310_T16_VALUE_SIGN << 1) - (u32)data);
-			sign = '-';
-		}
-		return sprintf(buf, "%c%d.%.7d\n", sign,
-				(data >> ADT7310_T16_VALUE_FLOAT_OFFSET),
-				(data & ADT7310_T16_VALUE_FLOAT_MASK) * 78125);
-	} else {
-		if (data & ADT7310_T13_VALUE_SIGN) {
-			/* convert supplement to positive value */
-			data >>= ADT7310_T13_VALUE_OFFSET;
-			data = (ADT7310_T13_VALUE_SIGN << 1) - data;
-			sign = '-';
-		}
-		return sprintf(buf, "%c%d.%.4d\n", sign,
-				(data >> ADT7310_T13_VALUE_FLOAT_OFFSET),
-				(data & ADT7310_T13_VALUE_FLOAT_MASK) * 625);
-	}
-}
-
-static ssize_t adt7310_show_value(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7310_chip_info *chip = iio_priv(dev_info);
-	u8 status;
-	u16 data;
-	int ret, i = 0;
-
-	do {
-		ret = adt7310_spi_read_byte(chip, ADT7310_STATUS, &status);
-		if (ret)
-			return -EIO;
-		i++;
-		if (i == 10000)
-			return -EIO;
-	} while (status & ADT7310_STAT_NOT_RDY);
-
-	ret = adt7310_spi_read_word(chip, ADT7310_TEMPERATURE, &data);
-	if (ret)
-		return -EIO;
-
-	return adt7310_convert_temperature(chip, data, buf);
-}
-
-static IIO_DEVICE_ATTR(value, S_IRUGO, adt7310_show_value, NULL, 0);
-
-static struct attribute *adt7310_attributes[] = {
-	&iio_dev_attr_available_modes.dev_attr.attr,
-	&iio_dev_attr_mode.dev_attr.attr,
-	&iio_dev_attr_resolution.dev_attr.attr,
-	&iio_dev_attr_id.dev_attr.attr,
-	&iio_dev_attr_value.dev_attr.attr,
-	NULL,
-};
-
-static const struct attribute_group adt7310_attribute_group = {
-	.attrs = adt7310_attributes,
-};
-
-static irqreturn_t adt7310_event_handler(int irq, void *private)
-{
-	struct iio_dev *indio_dev = private;
-	struct adt7310_chip_info *chip = iio_priv(indio_dev);
-	s64 timestamp = iio_get_time_ns();
-	u8 status;
-	int ret;
-
-	ret = adt7310_spi_read_byte(chip, ADT7310_STATUS, &status);
-	if (ret)
-		goto done;
-
-	if (status & ADT7310_STAT_T_HIGH)
-		iio_push_event(indio_dev,
-			       IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
-						    IIO_EV_TYPE_THRESH,
-						    IIO_EV_DIR_RISING),
-			       timestamp);
-	if (status & ADT7310_STAT_T_LOW)
-		iio_push_event(indio_dev,
-			       IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
-						    IIO_EV_TYPE_THRESH,
-						    IIO_EV_DIR_FALLING),
-			       timestamp);
-	if (status & ADT7310_STAT_T_CRIT)
-		iio_push_event(indio_dev,
-			       IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
-						    IIO_EV_TYPE_THRESH,
-						    IIO_EV_DIR_RISING),
-			timestamp);
-
-done:
-	return IRQ_HANDLED;
-}
-
-static ssize_t adt7310_show_event_mode(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7310_chip_info *chip = iio_priv(dev_info);
-	int ret;
-
-	ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config);
-	if (ret)
-		return -EIO;
-
-	if (chip->config & ADT7310_EVENT_MODE)
-		return sprintf(buf, "interrupt\n");
-	else
-		return sprintf(buf, "comparator\n");
-}
-
-static ssize_t adt7310_set_event_mode(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7310_chip_info *chip = iio_priv(dev_info);
-	u16 config;
-	int ret;
-
-	ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config);
-	if (ret)
-		return -EIO;
-
-	config = chip->config &= ~ADT7310_EVENT_MODE;
-	if (strcmp(buf, "comparator") != 0)
-		config |= ADT7310_EVENT_MODE;
-
-	ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, config);
-	if (ret)
-		return -EIO;
-
-	chip->config = config;
-
-	return len;
-}
-
-static ssize_t adt7310_show_available_event_modes(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	return sprintf(buf, "comparator\ninterrupt\n");
-}
-
-static ssize_t adt7310_show_fault_queue(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7310_chip_info *chip = iio_priv(dev_info);
-	int ret;
-
-	ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config);
-	if (ret)
-		return -EIO;
-
-	return sprintf(buf, "%d\n", chip->config & ADT7310_FAULT_QUEUE_MASK);
-}
-
-static ssize_t adt7310_set_fault_queue(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7310_chip_info *chip = iio_priv(dev_info);
-	unsigned long data;
-	int ret;
-	u8 config;
-
-	ret = strict_strtoul(buf, 10, &data);
-	if (ret || data > 3)
-		return -EINVAL;
-
-	ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config);
-	if (ret)
-		return -EIO;
-
-	config = chip->config & ~ADT7310_FAULT_QUEUE_MASK;
-	config |= data;
-	ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, config);
-	if (ret)
-		return -EIO;
-
-	chip->config = config;
-
-	return len;
-}
-
-static inline ssize_t adt7310_show_t_bound(struct device *dev,
-		struct device_attribute *attr,
-		u8 bound_reg,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7310_chip_info *chip = iio_priv(dev_info);
-	u16 data;
-	int ret;
-
-	ret = adt7310_spi_read_word(chip, bound_reg, &data);
-	if (ret)
-		return -EIO;
-
-	return adt7310_convert_temperature(chip, data, buf);
-}
-
-static inline ssize_t adt7310_set_t_bound(struct device *dev,
-		struct device_attribute *attr,
-		u8 bound_reg,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7310_chip_info *chip = iio_priv(dev_info);
-	long tmp1, tmp2;
-	u16 data;
-	char *pos;
-	int ret;
-
-	pos = strchr(buf, '.');
-
-	ret = strict_strtol(buf, 10, &tmp1);
-
-	if (ret || tmp1 > 127 || tmp1 < -128)
-		return -EINVAL;
-
-	if (pos) {
-		len = strlen(pos);
-
-		if (chip->config & ADT7310_RESOLUTION) {
-			if (len > ADT7310_T16_VALUE_FLOAT_OFFSET)
-				len = ADT7310_T16_VALUE_FLOAT_OFFSET;
-			pos[len] = 0;
-			ret = strict_strtol(pos, 10, &tmp2);
-
-			if (!ret)
-				tmp2 = (tmp2 / 78125) * 78125;
-		} else {
-			if (len > ADT7310_T13_VALUE_FLOAT_OFFSET)
-				len = ADT7310_T13_VALUE_FLOAT_OFFSET;
-			pos[len] = 0;
-			ret = strict_strtol(pos, 10, &tmp2);
-
-			if (!ret)
-				tmp2 = (tmp2 / 625) * 625;
-		}
-	}
-
-	if (tmp1 < 0)
-		data = (u16)(-tmp1);
-	else
-		data = (u16)tmp1;
-
-	if (chip->config & ADT7310_RESOLUTION) {
-		data = (data << ADT7310_T16_VALUE_FLOAT_OFFSET) |
-			(tmp2 & ADT7310_T16_VALUE_FLOAT_MASK);
-
-		if (tmp1 < 0)
-			/* convert positive value to supplyment */
-			data = (u16)((ADT7310_T16_VALUE_SIGN << 1) - (u32)data);
-	} else {
-		data = (data << ADT7310_T13_VALUE_FLOAT_OFFSET) |
-			(tmp2 & ADT7310_T13_VALUE_FLOAT_MASK);
-
-		if (tmp1 < 0)
-			/* convert positive value to supplyment */
-			data = (ADT7310_T13_VALUE_SIGN << 1) - data;
-		data <<= ADT7310_T13_VALUE_OFFSET;
-	}
-
-	ret = adt7310_spi_write_word(chip, bound_reg, data);
-	if (ret)
-		return -EIO;
-
-	return len;
-}
-
-static ssize_t adt7310_show_t_alarm_high(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	return adt7310_show_t_bound(dev, attr,
-			ADT7310_T_ALARM_HIGH, buf);
-}
-
-static inline ssize_t adt7310_set_t_alarm_high(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	return adt7310_set_t_bound(dev, attr,
-			ADT7310_T_ALARM_HIGH, buf, len);
-}
-
-static ssize_t adt7310_show_t_alarm_low(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	return adt7310_show_t_bound(dev, attr,
-			ADT7310_T_ALARM_LOW, buf);
-}
-
-static inline ssize_t adt7310_set_t_alarm_low(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	return adt7310_set_t_bound(dev, attr,
-			ADT7310_T_ALARM_LOW, buf, len);
-}
-
-static ssize_t adt7310_show_t_crit(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	return adt7310_show_t_bound(dev, attr,
-			ADT7310_T_CRIT, buf);
-}
-
-static inline ssize_t adt7310_set_t_crit(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	return adt7310_set_t_bound(dev, attr,
-			ADT7310_T_CRIT, buf, len);
-}
-
-static ssize_t adt7310_show_t_hyst(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7310_chip_info *chip = iio_priv(dev_info);
-	int ret;
-	u8 t_hyst;
-
-	ret = adt7310_spi_read_byte(chip, ADT7310_T_HYST, &t_hyst);
-	if (ret)
-		return -EIO;
-
-	return sprintf(buf, "%d\n", t_hyst & ADT7310_T_HYST_MASK);
-}
-
-static inline ssize_t adt7310_set_t_hyst(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_to_iio_dev(dev);
-	struct adt7310_chip_info *chip = iio_priv(dev_info);
-	int ret;
-	unsigned long data;
-	u8 t_hyst;
-
-	ret = strict_strtol(buf, 10, &data);
-
-	if (ret || data > ADT7310_T_HYST_MASK)
-		return -EINVAL;
-
-	t_hyst = (u8)data;
-
-	ret = adt7310_spi_write_byte(chip, ADT7310_T_HYST, t_hyst);
-	if (ret)
-		return -EIO;
-
-	return len;
-}
-
-static IIO_DEVICE_ATTR(event_mode,
-		       S_IRUGO | S_IWUSR,
-		       adt7310_show_event_mode, adt7310_set_event_mode, 0);
-static IIO_DEVICE_ATTR(available_event_modes,
-		       S_IRUGO | S_IWUSR,
-		       adt7310_show_available_event_modes, NULL, 0);
-static IIO_DEVICE_ATTR(fault_queue,
-		       S_IRUGO | S_IWUSR,
-		       adt7310_show_fault_queue, adt7310_set_fault_queue, 0);
-static IIO_DEVICE_ATTR(t_alarm_high,
-		       S_IRUGO | S_IWUSR,
-		       adt7310_show_t_alarm_high, adt7310_set_t_alarm_high, 0);
-static IIO_DEVICE_ATTR(t_alarm_low,
-		       S_IRUGO | S_IWUSR,
-		       adt7310_show_t_alarm_low, adt7310_set_t_alarm_low, 0);
-static IIO_DEVICE_ATTR(t_crit,
-		       S_IRUGO | S_IWUSR,
-		       adt7310_show_t_crit, adt7310_set_t_crit, 0);
-static IIO_DEVICE_ATTR(t_hyst,
-		       S_IRUGO | S_IWUSR,
-		       adt7310_show_t_hyst, adt7310_set_t_hyst, 0);
-
-static struct attribute *adt7310_event_int_attributes[] = {
-	&iio_dev_attr_event_mode.dev_attr.attr,
-	&iio_dev_attr_available_event_modes.dev_attr.attr,
-	&iio_dev_attr_fault_queue.dev_attr.attr,
-	&iio_dev_attr_t_alarm_high.dev_attr.attr,
-	&iio_dev_attr_t_alarm_low.dev_attr.attr,
-	&iio_dev_attr_t_crit.dev_attr.attr,
-	&iio_dev_attr_t_hyst.dev_attr.attr,
-	NULL,
-};
-
-static struct attribute_group adt7310_event_attribute_group = {
-	.attrs = adt7310_event_int_attributes,
-	.name = "events",
-};
-
-static const struct iio_info adt7310_info = {
-	.attrs = &adt7310_attribute_group,
-	.event_attrs = &adt7310_event_attribute_group,
-	.driver_module = THIS_MODULE,
-};
-
-/*
- * device probe and remove
- */
-
-static int __devinit adt7310_probe(struct spi_device *spi_dev)
-{
-	struct adt7310_chip_info *chip;
-	struct iio_dev *indio_dev;
-	int ret = 0;
-	unsigned long *adt7310_platform_data = spi_dev->dev.platform_data;
-	unsigned long irq_flags;
-
-	indio_dev = iio_device_alloc(sizeof(*chip));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-	chip = iio_priv(indio_dev);
-	/* this is only used for device removal purposes */
-	dev_set_drvdata(&spi_dev->dev, indio_dev);
-
-	chip->spi_dev = spi_dev;
-
-	indio_dev->dev.parent = &spi_dev->dev;
-	indio_dev->name = spi_get_device_id(spi_dev)->name;
-	indio_dev->info = &adt7310_info;
-	indio_dev->modes = INDIO_DIRECT_MODE;
-
-	/* CT critcal temperature event. line 0 */
-	if (spi_dev->irq) {
-		if (adt7310_platform_data[2])
-			irq_flags = adt7310_platform_data[2];
-		else
-			irq_flags = IRQF_TRIGGER_LOW;
-		ret = request_threaded_irq(spi_dev->irq,
-					   NULL,
-					   &adt7310_event_handler,
-					   irq_flags | IRQF_ONESHOT,
-					   indio_dev->name,
-					   indio_dev);
-		if (ret)
-			goto error_free_dev;
-	}
-
-	/* INT bound temperature alarm event. line 1 */
-	if (adt7310_platform_data[0]) {
-		ret = request_threaded_irq(adt7310_platform_data[0],
-					   NULL,
-					   &adt7310_event_handler,
-					   adt7310_platform_data[1] |
-					   IRQF_ONESHOT,
-					   indio_dev->name,
-					   indio_dev);
-		if (ret)
-			goto error_unreg_ct_irq;
-	}
-
-	if (spi_dev->irq && adt7310_platform_data[0]) {
-		ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config);
-		if (ret) {
-			ret = -EIO;
-			goto error_unreg_int_irq;
-		}
-
-		/* set irq polarity low level */
-		chip->config &= ~ADT7310_CT_POLARITY;
-
-		if (adt7310_platform_data[1] & IRQF_TRIGGER_HIGH)
-			chip->config |= ADT7310_INT_POLARITY;
-		else
-			chip->config &= ~ADT7310_INT_POLARITY;
-
-		ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, chip->config);
-		if (ret) {
-			ret = -EIO;
-			goto error_unreg_int_irq;
-		}
-	}
-
-	ret = iio_device_register(indio_dev);
-	if (ret)
-		goto error_unreg_int_irq;
-
-	dev_info(&spi_dev->dev, "%s temperature sensor registered.\n",
-			indio_dev->name);
-
-	return 0;
-
-error_unreg_int_irq:
-	free_irq(adt7310_platform_data[0], indio_dev);
-error_unreg_ct_irq:
-	free_irq(spi_dev->irq, indio_dev);
-error_free_dev:
-	iio_device_free(indio_dev);
-error_ret:
-	return ret;
-}
-
-static int __devexit adt7310_remove(struct spi_device *spi_dev)
-{
-	struct iio_dev *indio_dev = dev_get_drvdata(&spi_dev->dev);
-	unsigned long *adt7310_platform_data = spi_dev->dev.platform_data;
-
-	iio_device_unregister(indio_dev);
-	dev_set_drvdata(&spi_dev->dev, NULL);
-	if (adt7310_platform_data[0])
-		free_irq(adt7310_platform_data[0], indio_dev);
-	if (spi_dev->irq)
-		free_irq(spi_dev->irq, indio_dev);
-	iio_device_free(indio_dev);
-
-	return 0;
-}
-
-static const struct spi_device_id adt7310_id[] = {
-	{ "adt7310", 0 },
-	{}
-};
-
-MODULE_DEVICE_TABLE(spi, adt7310_id);
-
-static struct spi_driver adt7310_driver = {
-	.driver = {
-		.name = "adt7310",
-		.owner = THIS_MODULE,
-	},
-	.probe = adt7310_probe,
-	.remove = __devexit_p(adt7310_remove),
-	.id_table = adt7310_id,
-};
-module_spi_driver(adt7310_driver);
-
-MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
-MODULE_DESCRIPTION("Analog Devices ADT7310 digital"
-			" temperature sensor driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c
index 4157596..35455e1 100644
--- a/drivers/staging/iio/adc/adt7410.c
+++ b/drivers/staging/iio/adc/adt7410.c
@@ -1,5 +1,5 @@
 /*
- * ADT7410 digital temperature sensor driver supporting ADT7410
+ * ADT7410 digital temperature sensor driver supporting ADT7310/ADT7410
  *
  * Copyright 2010 Analog Devices Inc.
  *
@@ -13,6 +13,7 @@
 #include <linux/sysfs.h>
 #include <linux/list.h>
 #include <linux/i2c.h>
+#include <linux/spi/spi.h>
 #include <linux/module.h>
 
 #include <linux/iio/iio.h>
@@ -34,6 +35,19 @@
 #define ADT7410_RESET			0x2F
 
 /*
+ * ADT7310 registers definition
+ */
+
+#define ADT7310_STATUS			0
+#define ADT7310_CONFIG			1
+#define ADT7310_TEMPERATURE		2
+#define ADT7310_ID			3
+#define ADT7310_T_CRIT			4
+#define ADT7310_T_HYST			5
+#define ADT7310_T_ALARM_HIGH		6
+#define ADT7310_T_ALARM_LOW		7
+
+/*
  * ADT7410 status
  */
 #define ADT7410_STAT_T_LOW		0x10
@@ -69,75 +83,52 @@
 #define ADT7410_MANUFACTORY_ID_MASK		0xF0
 #define ADT7410_MANUFACTORY_ID_OFFSET		4
 
+
+#define ADT7310_CMD_REG_MASK			0x28
+#define ADT7310_CMD_REG_OFFSET			3
+#define ADT7310_CMD_READ			0x40
+#define ADT7310_CMD_CON_READ			0x4
+
 #define ADT7410_IRQS				2
 
 /*
  * struct adt7410_chip_info - chip specifc information
  */
 
+struct adt7410_chip_info;
+
+struct adt7410_ops {
+	int (*read_word)(struct adt7410_chip_info *, u8 reg, u16 *data);
+	int (*write_word)(struct adt7410_chip_info *, u8 reg, u16 data);
+	int (*read_byte)(struct adt7410_chip_info *, u8 reg, u8 *data);
+	int (*write_byte)(struct adt7410_chip_info *, u8 reg, u8 data);
+};
+
 struct adt7410_chip_info {
-	struct i2c_client *client;
+	struct device *dev;
 	u8  config;
-};
 
-/*
- * adt7410 register access by I2C
- */
+	const struct adt7410_ops *ops;
+};
 
-static int adt7410_i2c_read_word(struct adt7410_chip_info *chip, u8 reg, u16 *data)
+static int adt7410_read_word(struct adt7410_chip_info *chip, u8 reg, u16 *data)
 {
-	struct i2c_client *client = chip->client;
-	int ret = 0;
-
-	ret = i2c_smbus_read_word_data(client, reg);
-	if (ret < 0) {
-		dev_err(&client->dev, "I2C read error\n");
-		return ret;
-	}
-
-	*data = swab16((u16)ret);
-
-	return 0;
+	return chip->ops->read_word(chip, reg, data);
 }
 
-static int adt7410_i2c_write_word(struct adt7410_chip_info *chip, u8 reg, u16 data)
+static int adt7410_write_word(struct adt7410_chip_info *chip, u8 reg, u16 data)
 {
-	struct i2c_client *client = chip->client;
-	int ret = 0;
-
-	ret = i2c_smbus_write_word_data(client, reg, swab16(data));
-	if (ret < 0)
-		dev_err(&client->dev, "I2C write error\n");
-
-	return ret;
+	return chip->ops->write_word(chip, reg, data);
 }
 
-static int adt7410_i2c_read_byte(struct adt7410_chip_info *chip, u8 reg, u8 *data)
+static int adt7410_read_byte(struct adt7410_chip_info *chip, u8 reg, u8 *data)
 {
-	struct i2c_client *client = chip->client;
-	int ret = 0;
-
-	ret = i2c_smbus_read_byte_data(client, reg);
-	if (ret < 0) {
-		dev_err(&client->dev, "I2C read error\n");
-		return ret;
-	}
-
-	*data = (u8)ret;
-
-	return 0;
+	return chip->ops->read_byte(chip, reg, data);
 }
 
-static int adt7410_i2c_write_byte(struct adt7410_chip_info *chip, u8 reg, u8 data)
+static int adt7410_write_byte(struct adt7410_chip_info *chip, u8 reg, u8 data)
 {
-	struct i2c_client *client = chip->client;
-	int ret = 0;
-
-	ret = i2c_smbus_write_byte_data(client, reg, data);
-	if (ret < 0)
-		dev_err(&client->dev, "I2C write error\n");
-
-	return ret;
+	return chip->ops->write_byte(chip, reg, data);
 }
 
 static ssize_t adt7410_show_mode(struct device *dev,
@@ -172,7 +163,7 @@ static ssize_t adt7410_store_mode(struct device *dev,
 	u16 config;
 	int ret;
 
-	ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
+	ret = adt7410_read_byte(chip, ADT7410_CONFIG, &chip->config);
 	if (ret)
 		return -EIO;
 
@@ -184,13 +175,13 @@ static ssize_t adt7410_store_mode(struct device *dev,
 	else if (strcmp(buf, "sps"))
 		config |= ADT7410_SPS;
 
-	ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, config);
+	ret = adt7410_write_byte(chip, ADT7410_CONFIG, config);
 	if (ret)
 		return -EIO;
 
 	chip->config = config;
 
-	return ret;
+	return len;
 }
 
 static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
@@ -216,7 +207,7 @@ static ssize_t adt7410_show_resolution(struct device *dev,
 	int ret;
 	int bits;
 
-	ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
+	ret = adt7410_read_byte(chip, ADT7410_CONFIG, &chip->config);
 	if (ret)
 		return -EIO;
 
@@ -243,7 +234,7 @@ static ssize_t adt7410_store_resolution(struct device *dev,
 	if (ret)
 		return -EINVAL;
 
-	ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
+	ret = adt7410_read_byte(chip, ADT7410_CONFIG, &chip->config);
 	if (ret)
 		return -EIO;
 
@@ -251,7 +242,7 @@ static ssize_t adt7410_store_resolution(struct device *dev,
 	if (data)
 		config |= ADT7410_RESOLUTION;
 
-	ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, config);
+	ret = adt7410_write_byte(chip, ADT7410_CONFIG, config);
 	if (ret)
 		return -EIO;
 
@@ -274,7 +265,7 @@ static ssize_t adt7410_show_id(struct device *dev,
 	u8 id;
 	int ret;
 
-	ret = adt7410_i2c_read_byte(chip, ADT7410_ID, &id);
+	ret = adt7410_read_byte(chip, ADT7410_ID, &id);
 	if (ret)
 		return -EIO;
 
@@ -317,7 +308,7 @@ static ssize_t adt7410_show_value(struct device *dev,
 	int ret, i = 0;
 
 	do {
-		ret = adt7410_i2c_read_byte(chip, ADT7410_STATUS, &status);
+		ret = adt7410_read_byte(chip, ADT7410_STATUS, &status);
 		if (ret)
 			return -EIO;
 		i++;
@@ -325,7 +316,7 @@ static ssize_t adt7410_show_value(struct device *dev,
 			return -EIO;
 	} while (status & ADT7410_STAT_NOT_RDY);
 
-	ret = adt7410_i2c_read_word(chip, ADT7410_TEMPERATURE, &data);
+	ret = adt7410_read_word(chip, ADT7410_TEMPERATURE, &data);
 	if (ret)
 		return -EIO;
 
@@ -354,7 +345,7 @@ static irqreturn_t adt7410_event_handler(int irq, void *private)
 	s64 timestamp = iio_get_time_ns();
 	u8 status;
 
-	if (adt7410_i2c_read_byte(chip, ADT7410_STATUS, &status))
+	if (adt7410_read_byte(chip, ADT7410_STATUS, &status))
 		return IRQ_HANDLED;
 
 	if (status & ADT7410_STAT_T_HIGH)
@@ -387,7 +378,7 @@ static ssize_t adt7410_show_event_mode(struct device *dev,
 	struct adt7410_chip_info *chip = iio_priv(dev_info);
 	int ret;
 
-	ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
+	ret = adt7410_read_byte(chip, ADT7410_CONFIG, &chip->config);
 	if (ret)
 		return -EIO;
 
@@ -407,7 +398,7 @@ static ssize_t adt7410_set_event_mode(struct device *dev,
 	u16 config;
 	int ret;
 
-	ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
+	ret = adt7410_read_byte(chip, ADT7410_CONFIG, &chip->config);
 	if (ret)
 		return -EIO;
 
@@ -415,7 +406,7 @@ static ssize_t adt7410_set_event_mode(struct device *dev,
 	if (strcmp(buf, "comparator") != 0)
 		config |= ADT7410_EVENT_MODE;
 
-	ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, config);
+	ret = adt7410_write_byte(chip, ADT7410_CONFIG, config);
 	if (ret)
 		return -EIO;
 
@@ -439,7 +430,7 @@ static ssize_t adt7410_show_fault_queue(struct device *dev,
 	struct adt7410_chip_info *chip = iio_priv(dev_info);
 	int ret;
 
-	ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
+	ret = adt7410_read_byte(chip, ADT7410_CONFIG, &chip->config);
 	if (ret)
 		return -EIO;
 
@@ -461,13 +452,13 @@ static ssize_t adt7410_set_fault_queue(struct device *dev,
 	if (ret || data > 3)
 		return -EINVAL;
 
-	ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
+	ret = adt7410_read_byte(chip, ADT7410_CONFIG, &chip->config);
 	if (ret)
 		return -EIO;
 
 	config = chip->config & ~ADT7410_FAULT_QUEUE_MASK;
 	config |= data;
-	ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, config);
+	ret = adt7410_write_byte(chip, ADT7410_CONFIG, config);
 	if (ret)
 		return -EIO;
 
@@ -486,7 +477,7 @@ static inline ssize_t adt7410_show_t_bound(struct device *dev,
 	u16 data;
 	int ret;
 
-	ret = adt7410_i2c_read_word(chip, bound_reg, &data);
+	ret = adt7410_read_word(chip, bound_reg, &data);
 	if (ret)
 		return -EIO;
 
@@ -557,7 +548,7 @@ static inline ssize_t adt7410_set_t_bound(struct device *dev,
 		data <<= ADT7410_T13_VALUE_OFFSET;
 	}
 
-	ret = adt7410_i2c_write_word(chip, bound_reg, data);
+	ret = adt7410_write_word(chip, bound_reg, data);
 	if (ret)
 		return -EIO;
 
@@ -624,7 +615,7 @@ static ssize_t adt7410_show_t_hyst(struct device *dev,
 	int ret;
 	u8 t_hyst;
 
-	ret = adt7410_i2c_read_byte(chip, ADT7410_T_HYST, &t_hyst);
+	ret = adt7410_read_byte(chip, ADT7410_T_HYST, &t_hyst);
 	if (ret)
 		return -EIO;
 
@@ -649,7 +640,7 @@ static inline ssize_t adt7410_set_t_hyst(struct device *dev,
 
 	t_hyst = (u8)data;
 
-	ret = adt7410_i2c_write_byte(chip, ADT7410_T_HYST, t_hyst);
+	ret = adt7410_write_byte(chip, ADT7410_T_HYST, t_hyst);
 	if (ret)
 		return -EIO;
 
@@ -704,14 +695,14 @@ static const struct iio_info adt7410_info = {
  * device probe and remove
  */
 
-static int __devinit adt7410_probe(struct i2c_client *client,
-		const struct i2c_device_id *id)
+static int adt7410_probe(struct device *dev, int irq,
+	const char *name, const struct adt7410_ops *ops)
 {
+	unsigned long *adt7410_platform_data = dev->platform_data;
+	unsigned long local_pdata[] = {0, 0};
 	struct adt7410_chip_info *chip;
 	struct iio_dev *indio_dev;
 	int ret = 0;
-	unsigned long *adt7410_platform_data = client->dev.platform_data;
-	unsigned long local_pdata[] = {0, 0};
 
 	indio_dev = iio_device_alloc(sizeof(*chip));
 	if (indio_dev == NULL) {
@@ -720,12 +711,13 @@ static int __devinit adt7410_probe(struct i2c_client *client,
 	}
 	chip = iio_priv(indio_dev);
 	/* this is only used for device removal purposes */
-	i2c_set_clientdata(client, indio_dev);
+	dev_set_drvdata(dev, indio_dev);
 
-	chip->client = client;
+	chip->dev = dev;
+	chip->ops = ops;
 
-	indio_dev->name = id->name;
-	indio_dev->dev.parent = &client->dev;
+	indio_dev->name = name;
+	indio_dev->dev.parent = dev;
 	indio_dev->info = &adt7410_info;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
@@ -733,12 +725,12 @@ static int __devinit adt7410_probe(struct i2c_client *client,
 		adt7410_platform_data = local_pdata;
 
 	/* CT critcal temperature event. line 0 */
-	if (client->irq) {
-		ret = request_threaded_irq(client->irq,
+	if (irq) {
+		ret = request_threaded_irq(irq,
 					   NULL,
 					   &adt7410_event_handler,
 					   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-					   id->name,
+					   name,
 					   indio_dev);
 		if (ret)
 			goto error_free_dev;
@@ -751,13 +743,13 @@ static int __devinit adt7410_probe(struct i2c_client *client,
 					   &adt7410_event_handler,
 					   adt7410_platform_data[1] |
 					   IRQF_ONESHOT,
-					   id->name,
+					   name,
 					   indio_dev);
 		if (ret)
 			goto error_unreg_ct_irq;
 	}
 
-	ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
+	ret = adt7410_read_byte(chip, ADT7410_CONFIG, &chip->config);
 	if (ret) {
 		ret = -EIO;
 		goto error_unreg_int_irq;
@@ -765,7 +757,7 @@ static int __devinit adt7410_probe(struct i2c_client *client,
 
 	chip->config |= ADT7410_RESOLUTION;
 
-	if (client->irq && adt7410_platform_data[0]) {
+	if (irq && adt7410_platform_data[0]) {
 
 		/* set irq polarity low level */
 		chip->config &= ~ADT7410_CT_POLARITY;
@@ -776,7 +768,7 @@ static int __devinit adt7410_probe(struct i2c_client *client,
 			chip->config &= ~ADT7410_INT_POLARITY;
 	}
 
-	ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, chip->config);
+	ret = adt7410_write_byte(chip, ADT7410_CONFIG, chip->config);
 	if (ret) {
 		ret = -EIO;
 		goto error_unreg_int_irq;
@@ -785,36 +777,117 @@ static int __devinit adt7410_probe(struct i2c_client *client,
 	if (ret)
 		goto error_unreg_int_irq;
 
-	dev_info(&client->dev, "%s temperature sensor registered.\n",
-			 id->name);
+	dev_info(dev, "%s temperature sensor registered.\n",
+			 name);
 
 	return 0;
 
 error_unreg_int_irq:
 	free_irq(adt7410_platform_data[0], indio_dev);
 error_unreg_ct_irq:
-	free_irq(client->irq, indio_dev);
+	free_irq(irq, indio_dev);
 error_free_dev:
 	iio_device_free(indio_dev);
 error_ret:
 	return ret;
 }
 
-static int __devexit adt7410_remove(struct i2c_client *client)
+static int adt7410_remove(struct device *dev, int irq)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
-	unsigned long *adt7410_platform_data = client->dev.platform_data;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	unsigned long *adt7410_platform_data = dev->platform_data;
 
 	iio_device_unregister(indio_dev);
 	if (adt7410_platform_data[0])
 		free_irq(adt7410_platform_data[0], indio_dev);
-	if (client->irq)
-		free_irq(client->irq, indio_dev);
+	if (irq)
+		free_irq(irq, indio_dev);
 	iio_device_free(indio_dev);
 
 	return 0;
 }
 
+#if IS_ENABLED(CONFIG_I2C)
+
+static int adt7410_i2c_read_word(struct adt7410_chip_info *chip, u8 reg,
+	u16 *data)
+{
+	struct i2c_client *client = to_i2c_client(chip->dev);
+	int ret = 0;
+
+	ret = i2c_smbus_read_word_data(client, reg);
+	if (ret < 0) {
+		dev_err(&client->dev, "I2C read error\n");
+		return ret;
+	}
+
+	*data = swab16((u16)ret);
+
+	return 0;
+}
+
+static int adt7410_i2c_write_word(struct adt7410_chip_info *chip, u8 reg,
+	u16 data)
+{
+	struct i2c_client *client = to_i2c_client(chip->dev);
+	int ret = 0;
+
+	ret = i2c_smbus_write_word_data(client, reg, swab16(data));
+	if (ret < 0)
+		dev_err(&client->dev, "I2C write error\n");
+
+	return ret;
+}
+
+static int adt7410_i2c_read_byte(struct adt7410_chip_info *chip, u8 reg,
+	u8 *data)
+{
+	struct i2c_client *client = to_i2c_client(chip->dev);
+	int ret = 0;
+
+	ret = i2c_smbus_read_byte_data(client, reg);
+	if (ret < 0) {
+		dev_err(&client->dev, "I2C read error\n");
+		return ret;
+	}
+
+	*data = (u8)ret;
+
+	return 0;
+}
+
+static int adt7410_i2c_write_byte(struct adt7410_chip_info *chip, u8 reg,
+	u8 data)
+{
+	struct i2c_client *client = to_i2c_client(chip->dev);
+	int ret = 0;
+
+	ret = i2c_smbus_write_byte_data(client, reg, data);
+	if (ret < 0)
+		dev_err(&client->dev, "I2C write error\n");
+
+	return ret;
+}
+
+static const struct adt7410_ops adt7410_i2c_ops = {
+	.read_word = adt7410_i2c_read_word,
+	.write_word = adt7410_i2c_write_word,
+	.read_byte = adt7410_i2c_read_byte,
+	.write_byte = adt7410_i2c_write_byte,
+};
+
+static int adt7410_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	return adt7410_probe(&client->dev, client->irq, id->name,
+		&adt7410_i2c_ops);
+}
+
+static int adt7410_i2c_remove(struct i2c_client *client)
+{
+	return adt7410_remove(&client->dev, client->irq);
+}
+
 static const struct i2c_device_id adt7410_id[] = {
 	{ "adt7410", 0 },
 	{}
@@ -826,13 +899,204 @@ static struct i2c_driver adt7410_driver = {
 	.driver = {
 		.name = "adt7410",
 	},
-	.probe = adt7410_probe,
-	.remove = __devexit_p(adt7410_remove),
+	.probe = adt7410_i2c_probe,
+	.remove = adt7410_i2c_remove,
 	.id_table = adt7410_id,
 };
-module_i2c_driver(adt7410_driver);
+
+static int __init adt7410_i2c_init(void)
+{
+	return i2c_add_driver(&adt7410_driver);
+}
+
+static void __exit adt7410_i2c_exit(void)
+{
+	i2c_del_driver(&adt7410_driver);
+}
+
+#else
+
+static int  __init adt7410_i2c_init(void) { return 0; };
+static void __exit adt7410_i2c_exit(void) {};
+
+#endif
+
+#if IS_ENABLED(CONFIG_SPI_MASTER)
+
+static const u8 adt7371_reg_table[] = {
+	[ADT7410_TEMPERATURE]   = ADT7310_TEMPERATURE,
+	[ADT7410_STATUS]	= ADT7310_STATUS,
+	[ADT7410_CONFIG]	= ADT7310_CONFIG,
+	[ADT7410_T_ALARM_HIGH]	= ADT7310_T_ALARM_HIGH,
+	[ADT7410_T_ALARM_LOW]	= ADT7310_T_ALARM_LOW,
+	[ADT7410_T_CRIT]	= ADT7310_T_CRIT,
+	[ADT7410_T_HYST]	= ADT7310_T_HYST,
+	[ADT7410_ID]		= ADT7310_ID,
+};
+
+#define AD7310_COMMAND(reg) (adt7371_reg_table[(reg)] << ADT7310_CMD_REG_OFFSET)
+
+static int adt7310_spi_read_word(struct adt7410_chip_info *chip,
+	u8 reg, u16 *data)
+{
+	struct spi_device *spi = to_spi_device(chip->dev);
+	u8 command = AD7310_COMMAND(reg);
+	int ret = 0;
+
+	command |= ADT7310_CMD_READ;
+	ret = spi_write(spi, &command, sizeof(command));
+	if (ret < 0) {
+		dev_err(&spi->dev, "SPI write command error\n");
+		return ret;
+	}
+
+	ret = spi_read(spi, (u8 *)data, sizeof(*data));
+	if (ret < 0) {
+		dev_err(&spi->dev, "SPI read word error\n");
+		return ret;
+	}
+
+	*data = be16_to_cpu(*data);
+
+	return 0;
+}
+
+static int adt7310_spi_write_word(struct adt7410_chip_info *chip, u8 reg,
+	u16 data)
+{
+	struct spi_device *spi = to_spi_device(chip->dev);
+	u8 buf[3];
+	int ret = 0;
+
+	buf[0] = AD7310_COMMAND(reg);
+	buf[1] = (u8)(data >> 8);
+	buf[2] = (u8)(data & 0xFF);
+
+	ret = spi_write(spi, buf, 3);
+	if (ret < 0) {
+		dev_err(&spi->dev, "SPI write word error\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static int adt7310_spi_read_byte(struct adt7410_chip_info *chip, u8 reg,
+	u8 *data)
+{
+	struct spi_device *spi = to_spi_device(chip->dev);
+	u8 command = AD7310_COMMAND(reg);
+	int ret = 0;
+
+	command |= ADT7310_CMD_READ;
+	ret = spi_write(spi, &command, sizeof(command));
+	if (ret < 0) {
+		dev_err(&spi->dev, "SPI write command error\n");
+		return ret;
+	}
+
+	ret = spi_read(spi, data, sizeof(*data));
+	if (ret < 0) {
+		dev_err(&spi->dev, "SPI read byte error\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int adt7310_spi_write_byte(struct adt7410_chip_info *chip, u8 reg,
+	u8 data)
+{
+	struct spi_device *spi = to_spi_device(chip->dev);
+	u8 buf[2];
+	int ret = 0;
+
+	buf[0] = AD7310_COMMAND(reg);
+	buf[1] = data;
+
+	ret = spi_write(spi, buf, 2);
+	if (ret < 0) {
+		dev_err(&spi->dev, "SPI write byte error\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static const struct adt7410_ops adt7310_spi_ops = {
+	.read_word = adt7310_spi_read_word,
+	.write_word = adt7310_spi_write_word,
+	.read_byte = adt7310_spi_read_byte,
+	.write_byte = adt7310_spi_write_byte,
+};
+
+static int adt7310_spi_probe(struct spi_device *spi)
+{
+	return adt7410_probe(&spi->dev, spi->irq,
+		spi_get_device_id(spi)->name, &adt7310_spi_ops);
+}
+
+static int adt7310_spi_remove(struct spi_device *spi)
+{
+	return adt7410_remove(&spi->dev, spi->irq);
+}
+
+static const struct spi_device_id adt7310_id[] = {
+	{ "adt7310", 0 },
+	{}
+};
+MODULE_DEVICE_TABLE(spi, adt7310_id);
+
+static struct spi_driver adt7310_driver = {
+	.driver = {
+		.name = "adt7310",
+		.owner = THIS_MODULE,
+	},
+	.probe = adt7310_spi_probe,
+	.remove = adt7310_spi_remove,
+	.id_table = adt7310_id,
+};
+
+static int __init adt7310_spi_init(void)
+{
+	return spi_register_driver(&adt7310_driver);
+}
+
+static void adt7310_spi_exit(void)
+{
+	spi_unregister_driver(&adt7310_driver);
+}
+
+#else
+
+static int __init adt7310_spi_init(void) { return 0; };
+static void adt7310_spi_exit(void) {};
+
+#endif
+
+static int __init adt7410_init(void)
+{
+	int ret;
+
+	ret = adt7310_spi_init();
+	if (ret)
+		return ret;
+
+	ret = adt7410_i2c_init();
+	if (ret)
+		adt7310_spi_exit();
+
+	return ret;
+}
+module_init(adt7410_init);
+
+static void __exit adt7410_exit(void)
+{
+	adt7410_i2c_exit();
+	adt7310_spi_exit();
+}
+module_exit(adt7410_exit);
 
 MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
-MODULE_DESCRIPTION("Analog Devices ADT7410 digital"
-			" temperature sensor driver");
+MODULE_DESCRIPTION("Analog Devices ADT7310/ADT7410 digital temperature sensor driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c
index 7e9bd00..0bf2a6c 100644
--- a/drivers/staging/iio/adc/lpc32xx_adc.c
+++ b/drivers/staging/iio/adc/lpc32xx_adc.c
@@ -126,7 +126,7 @@ static irqreturn_t lpc32xx_adc_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit lpc32xx_adc_probe(struct platform_device *pdev)
+static int lpc32xx_adc_probe(struct platform_device *pdev)
 {
 	struct lpc32xx_adc_info *info = NULL;
 	struct resource *res;
@@ -150,7 +150,7 @@ static int __devinit lpc32xx_adc_probe(struct platform_device *pdev)
 
 	info = iio_priv(iodev);
 
-	info->adc_base = ioremap(res->start, res->end - res->start + 1);
+	info->adc_base = ioremap(res->start, resource_size(res));
 	if (!info->adc_base) {
 		dev_err(&pdev->dev, "failed mapping memory\n");
 		retval = -EBUSY;
@@ -207,7 +207,7 @@ errout1:
 	return retval;
 }
 
-static int __devexit lpc32xx_adc_remove(struct platform_device *pdev)
+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);
@@ -233,7 +233,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_adc_match);
 
 static struct platform_driver lpc32xx_adc_driver = {
 	.probe		= lpc32xx_adc_probe,
-	.remove		= __devexit_p(lpc32xx_adc_remove),
+	.remove		= lpc32xx_adc_remove,
 	.driver		= {
 		.name	= MOD_NAME,
 		.owner	= THIS_MODULE,
diff --git a/drivers/staging/iio/adc/max1363.h b/drivers/staging/iio/adc/max1363.h
deleted file mode 100644
index c746918..0000000
--- a/drivers/staging/iio/adc/max1363.h
+++ /dev/null
@@ -1,177 +0,0 @@
-#ifndef _MAX1363_H_
-#define  _MAX1363_H_
-
-#define MAX1363_SETUP_BYTE(a) ((a) | 0x80)
-
-/* There is a fair bit more defined here than currently
- * used, but the intention is to support everything these
- * chips do in the long run */
-
-/* see data sheets */
-/* max1363 and max1236, max1237, max1238, max1239 */
-#define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD	0x00
-#define MAX1363_SETUP_AIN3_IS_REF_EXT_TO_REF	0x20
-#define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_INT	0x40
-#define MAX1363_SETUP_AIN3_IS_REF_REF_IS_INT	0x60
-#define MAX1363_SETUP_POWER_UP_INT_REF		0x10
-#define MAX1363_SETUP_POWER_DOWN_INT_REF	0x00
-
-/* think about includeing max11600 etc - more settings */
-#define MAX1363_SETUP_EXT_CLOCK			0x08
-#define MAX1363_SETUP_INT_CLOCK			0x00
-#define MAX1363_SETUP_UNIPOLAR			0x00
-#define MAX1363_SETUP_BIPOLAR			0x04
-#define MAX1363_SETUP_RESET			0x00
-#define MAX1363_SETUP_NORESET			0x02
-/* max1363 only - though don't care on others.
- * For now monitor modes are not implemented as the relevant
- * line is not connected on my test board.
- * The definitions are here as I intend to add this soon.
- */
-#define MAX1363_SETUP_MONITOR_SETUP		0x01
-
-/* Specific to the max1363 */
-#define MAX1363_MON_RESET_CHAN(a) (1 << ((a) + 4))
-#define MAX1363_MON_INT_ENABLE			0x01
-
-/* defined for readability reasons */
-/* All chips */
-#define MAX1363_CONFIG_BYTE(a) ((a))
-
-#define MAX1363_CONFIG_SE			0x01
-#define MAX1363_CONFIG_DE			0x00
-#define MAX1363_CONFIG_SCAN_TO_CS		0x00
-#define MAX1363_CONFIG_SCAN_SINGLE_8		0x20
-#define MAX1363_CONFIG_SCAN_MONITOR_MODE	0x40
-#define MAX1363_CONFIG_SCAN_SINGLE_1		0x60
-/* max123{6-9} only */
-#define MAX1236_SCAN_MID_TO_CHANNEL		0x40
-
-/* max1363 only - merely part of channel selects or don't care for others*/
-#define MAX1363_CONFIG_EN_MON_MODE_READ 0x18
-
-#define MAX1363_CHANNEL_SEL(a) ((a) << 1)
-
-/* max1363 strictly 0x06 - but doesn't matter */
-#define MAX1363_CHANNEL_SEL_MASK		0x1E
-#define MAX1363_SCAN_MASK			0x60
-#define MAX1363_SE_DE_MASK			0x01
-
-#define MAX1363_MAX_CHANNELS 25
-/**
- * struct max1363_mode - scan mode information
- * @conf:	The corresponding value of the configuration register
- * @modemask:	Bit mask corresponding to channels enabled in this mode
- */
-struct max1363_mode {
-	int8_t		conf;
-	DECLARE_BITMAP(modemask, MAX1363_MAX_CHANNELS);
-};
-
-/* This must be maintained along side the max1363_mode_table in max1363_core */
-enum max1363_modes {
-	/* Single read of a single channel */
-	_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11,
-	/* Differential single read */
-	d0m1, d2m3, d4m5, d6m7, d8m9, d10m11,
-	d1m0, d3m2, d5m4, d7m6, d9m8, d11m10,
-	/* Scan to channel and mid to channel where overlapping */
-	s0to1, s0to2, s2to3, s0to3, s0to4, s0to5, s0to6,
-	s6to7, s0to7, s6to8, s0to8, s6to9,
-	s0to9, s6to10, s0to10, s6to11, s0to11,
-	/* Differential scan to channel and mid to channel where overlapping */
-	d0m1to2m3, d0m1to4m5, d0m1to6m7, d6m7to8m9,
-	d0m1to8m9, d6m7to10m11, d0m1to10m11, d1m0to3m2,
-	d1m0to5m4, d1m0to7m6, d7m6to9m8, d1m0to9m8,
-	d7m6to11m10, d1m0to11m10,
-};
-
-/**
- * struct max1363_chip_info - chip specifc information
- * @name:		indentification string for chip
- * @bits:		accuracy of the adc in bits
- * @int_vref_mv:	the internal reference voltage
- * @info:		iio core function callbacks structure
- * @mode_list:		array of available scan modes
- * @num_modes:		the number of scan modes available
- * @default_mode:	the scan mode in which the chip starts up
- * @channel:		channel specification
- * @num_channels:	number of channels
- */
-struct max1363_chip_info {
-	const struct iio_info		*info;
-	const struct iio_chan_spec *channels;
-	int num_channels;
-	const enum max1363_modes	*mode_list;
-	enum max1363_modes		default_mode;
-	u16				int_vref_mv;
-	u8				num_modes;
-	u8				bits;
-};
-
-/**
- * struct max1363_state - driver instance specific data
- * @client:		i2c_client
- * @setupbyte:		cache of current device setup byte
- * @configbyte:		cache of current device config byte
- * @chip_info:		chip model specific constants, available modes etc
- * @current_mode:	the scan mode of this chip
- * @requestedmask:	a valid requested set of channels
- * @reg:		supply regulator
- * @monitor_on:		whether monitor mode is enabled
- * @monitor_speed:	parameter corresponding to device monitor speed setting
- * @mask_high:		bitmask for enabled high thresholds
- * @mask_low:		bitmask for enabled low thresholds
- * @thresh_high:	high threshold values
- * @thresh_low:		low threshold values
- */
-struct max1363_state {
-	struct i2c_client		*client;
-	u8				setupbyte;
-	u8				configbyte;
-	const struct max1363_chip_info	*chip_info;
-	const struct max1363_mode	*current_mode;
-	u32				requestedmask;
-	struct regulator		*reg;
-
-	/* Using monitor modes and buffer at the same time is
-	   currently not supported */
-	bool				monitor_on;
-	unsigned int			monitor_speed:3;
-	u8				mask_high;
-	u8				mask_low;
-	/* 4x unipolar first then the fours bipolar ones */
-	s16				thresh_high[8];
-	s16				thresh_low[8];
-};
-
-const struct max1363_mode
-*max1363_match_mode(const unsigned long *mask,
-		    const struct max1363_chip_info *ci);
-
-int max1363_set_scan_mode(struct max1363_state *st);
-
-#ifdef CONFIG_MAX1363_RING_BUFFER
-int max1363_update_scan_mode(struct iio_dev *indio_dev,
-			     const unsigned long *scan_mask);
-int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev);
-void max1363_ring_cleanup(struct iio_dev *indio_dev);
-
-#else /* CONFIG_MAX1363_RING_BUFFER */
-int max1363_update_scan_mode(struct iio_dev *indio_dev,
-			     const long *scan_mask)
-{
-	return 0;
-}
-
-static inline int
-max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline void max1363_ring_cleanup(struct iio_dev *indio_dev)
-{
-}
-#endif /* CONFIG_MAX1363_RING_BUFFER */
-#endif /* _MAX1363_H_ */
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
deleted file mode 100644
index d7b4ffc..0000000
--- a/drivers/staging/iio/adc/max1363_core.c
+++ /dev/null
@@ -1,1444 +0,0 @@
- /*
-  * iio/adc/max1363.c
-  * Copyright (C) 2008-2010 Jonathan Cameron
-  *
-  * based on linux/drivers/i2c/chips/max123x
-  * Copyright (C) 2002-2004 Stefan Eletzhofer
-  *
-  * based on linux/drivers/acron/char/pcf8583.c
-  * Copyright (C) 2000 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.
-  *
-  * max1363.c
-  *
-  * Partial support for max1363 and similar chips.
-  *
-  * Not currently implemented.
-  *
-  * - Control of internal reference.
-  */
-
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
-#include <linux/i2c.h>
-#include <linux/regulator/consumer.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/module.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/events.h>
-#include <linux/iio/buffer.h>
-#include <linux/iio/driver.h>
-
-#include "max1363.h"
-
-#define MAX1363_MODE_SINGLE(_num, _mask) {				\
-		.conf = MAX1363_CHANNEL_SEL(_num)			\
-			| MAX1363_CONFIG_SCAN_SINGLE_1			\
-			| MAX1363_CONFIG_SE,				\
-			.modemask[0] = _mask,				\
-			}
-
-#define MAX1363_MODE_SCAN_TO_CHANNEL(_num, _mask) {			\
-		.conf = MAX1363_CHANNEL_SEL(_num)			\
-			| MAX1363_CONFIG_SCAN_TO_CS			\
-			| MAX1363_CONFIG_SE,				\
-			.modemask[0] = _mask,				\
-			}
-
-/* note not available for max1363 hence naming */
-#define MAX1236_MODE_SCAN_MID_TO_CHANNEL(_mid, _num, _mask) {		\
-		.conf = MAX1363_CHANNEL_SEL(_num)			\
-			| MAX1236_SCAN_MID_TO_CHANNEL			\
-			| MAX1363_CONFIG_SE,				\
-			.modemask[0] = _mask				\
-}
-
-#define MAX1363_MODE_DIFF_SINGLE(_nump, _numm, _mask) {			\
-		.conf = MAX1363_CHANNEL_SEL(_nump)			\
-			| MAX1363_CONFIG_SCAN_SINGLE_1			\
-			| MAX1363_CONFIG_DE,				\
-			.modemask[0] = _mask				\
-			}
-
-/* Can't think how to automate naming so specify for now */
-#define MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(_num, _numvals, _mask) {	\
-		.conf = MAX1363_CHANNEL_SEL(_num)			\
-			| MAX1363_CONFIG_SCAN_TO_CS			\
-			| MAX1363_CONFIG_DE,				\
-			.modemask[0] = _mask				\
-			}
-
-/* note only available for max1363 hence naming */
-#define MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(_num, _numvals, _mask) {	\
-		.conf = MAX1363_CHANNEL_SEL(_num)			\
-			| MAX1236_SCAN_MID_TO_CHANNEL			\
-			| MAX1363_CONFIG_SE,				\
-			.modemask[0] = _mask				\
-}
-
-static const struct max1363_mode max1363_mode_table[] = {
-	/* All of the single channel options first */
-	MAX1363_MODE_SINGLE(0, 1 << 0),
-	MAX1363_MODE_SINGLE(1, 1 << 1),
-	MAX1363_MODE_SINGLE(2, 1 << 2),
-	MAX1363_MODE_SINGLE(3, 1 << 3),
-	MAX1363_MODE_SINGLE(4, 1 << 4),
-	MAX1363_MODE_SINGLE(5, 1 << 5),
-	MAX1363_MODE_SINGLE(6, 1 << 6),
-	MAX1363_MODE_SINGLE(7, 1 << 7),
-	MAX1363_MODE_SINGLE(8, 1 << 8),
-	MAX1363_MODE_SINGLE(9, 1 << 9),
-	MAX1363_MODE_SINGLE(10, 1 << 10),
-	MAX1363_MODE_SINGLE(11, 1 << 11),
-
-	MAX1363_MODE_DIFF_SINGLE(0, 1, 1 << 12),
-	MAX1363_MODE_DIFF_SINGLE(2, 3, 1 << 13),
-	MAX1363_MODE_DIFF_SINGLE(4, 5, 1 << 14),
-	MAX1363_MODE_DIFF_SINGLE(6, 7, 1 << 15),
-	MAX1363_MODE_DIFF_SINGLE(8, 9, 1 << 16),
-	MAX1363_MODE_DIFF_SINGLE(10, 11, 1 << 17),
-	MAX1363_MODE_DIFF_SINGLE(1, 0, 1 << 18),
-	MAX1363_MODE_DIFF_SINGLE(3, 2, 1 << 19),
-	MAX1363_MODE_DIFF_SINGLE(5, 4, 1 << 20),
-	MAX1363_MODE_DIFF_SINGLE(7, 6, 1 << 21),
-	MAX1363_MODE_DIFF_SINGLE(9, 8, 1 << 22),
-	MAX1363_MODE_DIFF_SINGLE(11, 10, 1 << 23),
-
-	/* The multichannel scans next */
-	MAX1363_MODE_SCAN_TO_CHANNEL(1, 0x003),
-	MAX1363_MODE_SCAN_TO_CHANNEL(2, 0x007),
-	MAX1236_MODE_SCAN_MID_TO_CHANNEL(2, 3, 0x00C),
-	MAX1363_MODE_SCAN_TO_CHANNEL(3, 0x00F),
-	MAX1363_MODE_SCAN_TO_CHANNEL(4, 0x01F),
-	MAX1363_MODE_SCAN_TO_CHANNEL(5, 0x03F),
-	MAX1363_MODE_SCAN_TO_CHANNEL(6, 0x07F),
-	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 7, 0x0C0),
-	MAX1363_MODE_SCAN_TO_CHANNEL(7, 0x0FF),
-	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 8, 0x1C0),
-	MAX1363_MODE_SCAN_TO_CHANNEL(8, 0x1FF),
-	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 9, 0x3C0),
-	MAX1363_MODE_SCAN_TO_CHANNEL(9, 0x3FF),
-	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 10, 0x7C0),
-	MAX1363_MODE_SCAN_TO_CHANNEL(10, 0x7FF),
-	MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 11, 0xFC0),
-	MAX1363_MODE_SCAN_TO_CHANNEL(11, 0xFFF),
-
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(2, 2, 0x003000),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(4, 3, 0x007000),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(6, 4, 0x00F000),
-	MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(8, 2, 0x018000),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(8, 5, 0x01F000),
-	MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(10, 3, 0x038000),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(10, 6, 0x3F000),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(3, 2, 0x0C0000),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(5, 3, 0x1C0000),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(7, 4, 0x3C0000),
-	MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(9, 2, 0x600000),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(9, 5, 0x7C0000),
-	MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(11, 3, 0xE00000),
-	MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(11, 6, 0xFC0000),
-};
-
-const struct max1363_mode
-*max1363_match_mode(const unsigned long *mask,
-const struct max1363_chip_info *ci)
-{
-	int i;
-	if (mask)
-		for (i = 0; i < ci->num_modes; i++)
-			if (bitmap_subset(mask,
-					  max1363_mode_table[ci->mode_list[i]].
-					  modemask,
-					  MAX1363_MAX_CHANNELS))
-				return &max1363_mode_table[ci->mode_list[i]];
-	return NULL;
-}
-
-static int max1363_write_basic_config(struct i2c_client *client,
-				      unsigned char d1,
-				      unsigned char d2)
-{
-	u8 tx_buf[2] = {d1, d2};
-
-	return i2c_master_send(client, tx_buf, 2);
-}
-
-int max1363_set_scan_mode(struct max1363_state *st)
-{
-	st->configbyte &= ~(MAX1363_CHANNEL_SEL_MASK
-			    | MAX1363_SCAN_MASK
-			    | MAX1363_SE_DE_MASK);
-	st->configbyte |= st->current_mode->conf;
-
-	return max1363_write_basic_config(st->client,
-					  st->setupbyte,
-					  st->configbyte);
-}
-
-static int max1363_read_single_chan(struct iio_dev *indio_dev,
-				    struct iio_chan_spec const *chan,
-				    int *val,
-				    long m)
-{
-	int ret = 0;
-	s32 data;
-	char rxbuf[2];
-	struct max1363_state *st = iio_priv(indio_dev);
-	struct i2c_client *client = st->client;
-
-	mutex_lock(&indio_dev->mlock);
-	/*
-	 * If monitor mode is enabled, the method for reading a single
-	 * channel will have to be rather different and has not yet
-	 * been implemented.
-	 *
-	 * Also, cannot read directly if buffered capture enabled.
-	 */
-	if (st->monitor_on || iio_buffer_enabled(indio_dev)) {
-		ret = -EBUSY;
-		goto error_ret;
-	}
-
-	/* Check to see if current scan mode is correct */
-	if (st->current_mode != &max1363_mode_table[chan->address]) {
-		/* Update scan mode if needed */
-		st->current_mode = &max1363_mode_table[chan->address];
-		ret = max1363_set_scan_mode(st);
-		if (ret < 0)
-			goto error_ret;
-	}
-	if (st->chip_info->bits != 8) {
-		/* Get reading */
-		data = i2c_master_recv(client, rxbuf, 2);
-		if (data < 0) {
-			ret = data;
-			goto error_ret;
-		}
-		data = (s32)(rxbuf[1]) | ((s32)(rxbuf[0] & 0x0F)) << 8;
-	} else {
-		/* Get reading */
-		data = i2c_master_recv(client, rxbuf, 1);
-		if (data < 0) {
-			ret = data;
-			goto error_ret;
-		}
-		data = rxbuf[0];
-	}
-	*val = data;
-error_ret:
-	mutex_unlock(&indio_dev->mlock);
-	return ret;
-
-}
-
-static int max1363_read_raw(struct iio_dev *indio_dev,
-			    struct iio_chan_spec const *chan,
-			    int *val,
-			    int *val2,
-			    long m)
-{
-	struct max1363_state *st = iio_priv(indio_dev);
-	int ret;
-	switch (m) {
-	case IIO_CHAN_INFO_RAW:
-		ret = max1363_read_single_chan(indio_dev, chan, val, m);
-		if (ret < 0)
-			return ret;
-		return IIO_VAL_INT;
-	case IIO_CHAN_INFO_SCALE:
-		if ((1 << (st->chip_info->bits + 1)) >
-		    st->chip_info->int_vref_mv) {
-			*val = 0;
-			*val2 = 500000;
-			return IIO_VAL_INT_PLUS_MICRO;
-		} else {
-			*val = (st->chip_info->int_vref_mv)
-				>> st->chip_info->bits;
-			return IIO_VAL_INT;
-		}
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-/* Applies to max1363 */
-static const enum max1363_modes max1363_mode_list[] = {
-	_s0, _s1, _s2, _s3,
-	s0to1, s0to2, s0to3,
-	d0m1, d2m3, d1m0, d3m2,
-	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))
-#define MAX1363_INFO_MASK (IIO_CHAN_INFO_RAW_SEPARATE_BIT |	\
-			   IIO_CHAN_INFO_SCALE_SHARED_BIT)
-#define MAX1363_CHAN_U(num, addr, si, bits, evmask)			\
-	{								\
-		.type = IIO_VOLTAGE,					\
-		.indexed = 1,						\
-		.channel = num,						\
-		.address = addr,					\
-		.info_mask = MAX1363_INFO_MASK,				\
-		.datasheet_name = "AIN"#num,				\
-		.scan_type = {						\
-			.sign = 'u',					\
-			.realbits = bits,				\
-			.storagebits = (bits > 8) ? 16 : 8,		\
-			.endianness = IIO_BE,				\
-		},							\
-		.scan_index = si,					\
-		.event_mask = evmask,					\
-	}
-
-/* bipolar channel */
-#define MAX1363_CHAN_B(num, num2, addr, si, bits, evmask)		\
-	{								\
-		.type = IIO_VOLTAGE,					\
-		.differential = 1,					\
-		.indexed = 1,						\
-		.channel = num,						\
-		.channel2 = num2,					\
-		.address = addr,					\
-		.info_mask = MAX1363_INFO_MASK,				\
-		.datasheet_name = "AIN"#num"-AIN"#num2,			\
-		.scan_type = {						\
-			.sign = 's',					\
-			.realbits = bits,				\
-			.storagebits = (bits > 8) ? 16 : 8,		\
-			.endianness = IIO_BE,				\
-		},							\
-		.scan_index = si,					\
-		.event_mask = evmask,					\
-	}
-
-#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)			\
-	}
-
-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 max1361_channels[] =
-	MAX1363_4X_CHANS(10, MAX1363_EV_M);
-static const struct iio_chan_spec max1363_channels[] =
-	MAX1363_4X_CHANS(12, MAX1363_EV_M);
-
-/* Applies to max1236, max1237 */
-static const enum max1363_modes max1236_mode_list[] = {
-	_s0, _s1, _s2, _s3,
-	s0to1, s0to2, s0to3,
-	d0m1, d2m3, d1m0, d3m2,
-	d0m1to2m3, d1m0to3m2,
-	s2to3,
-};
-
-/* Applies to max1238, max1239 */
-static const enum max1363_modes max1238_mode_list[] = {
-	_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11,
-	s0to1, s0to2, s0to3, s0to4, s0to5, s0to6,
-	s0to7, s0to8, s0to9, s0to10, s0to11,
-	d0m1, d2m3, d4m5, d6m7, d8m9, d10m11,
-	d1m0, d3m2, d5m4, d7m6, d9m8, d11m10,
-	d0m1to2m3, d0m1to4m5, d0m1to6m7, d0m1to8m9, d0m1to10m11,
-	d1m0to3m2, d1m0to5m4, d1m0to7m6, d1m0to9m8, d1m0to11m10,
-	s6to7, s6to8, s6to9, s6to10, s6to11,
-	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)			\
-	}
-static const struct iio_chan_spec max1038_channels[] = MAX1363_12X_CHANS(8);
-static const struct iio_chan_spec max1138_channels[] = MAX1363_12X_CHANS(10);
-static const struct iio_chan_spec max1238_channels[] = MAX1363_12X_CHANS(12);
-
-static const enum max1363_modes max11607_mode_list[] = {
-	_s0, _s1, _s2, _s3,
-	s0to1, s0to2, s0to3,
-	s2to3,
-	d0m1, d2m3, d1m0, d3m2,
-	d0m1to2m3, d1m0to3m2,
-};
-
-static const enum max1363_modes max11608_mode_list[] = {
-	_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7,
-	s0to1, s0to2, s0to3, s0to4, s0to5, s0to6, s0to7,
-	s6to7,
-	d0m1, d2m3, d4m5, d6m7,
-	d1m0, d3m2, d5m4, d7m6,
-	d0m1to2m3, d0m1to4m5, d0m1to6m7,
-	d1m0to3m2, d1m0to5m4, d1m0to7m6,
-};
-
-#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),	\
-	IIO_CHAN_SOFT_TIMESTAMP(16)			\
-}
-static const struct iio_chan_spec max11602_channels[] = MAX1363_8X_CHANS(8);
-static const struct iio_chan_spec max11608_channels[] = MAX1363_8X_CHANS(10);
-static const struct iio_chan_spec max11614_channels[] = MAX1363_8X_CHANS(12);
-
-static const enum max1363_modes max11644_mode_list[] = {
-	_s0, _s1, s0to1, d0m1, d1m0,
-};
-
-#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),	\
-	IIO_CHAN_SOFT_TIMESTAMP(4)			\
-	}
-
-static const struct iio_chan_spec max11646_channels[] = MAX1363_2X_CHANS(10);
-static const struct iio_chan_spec max11644_channels[] = MAX1363_2X_CHANS(12);
-
-enum { max1361,
-       max1362,
-       max1363,
-       max1364,
-       max1036,
-       max1037,
-       max1038,
-       max1039,
-       max1136,
-       max1137,
-       max1138,
-       max1139,
-       max1236,
-       max1237,
-       max1238,
-       max1239,
-       max11600,
-       max11601,
-       max11602,
-       max11603,
-       max11604,
-       max11605,
-       max11606,
-       max11607,
-       max11608,
-       max11609,
-       max11610,
-       max11611,
-       max11612,
-       max11613,
-       max11614,
-       max11615,
-       max11616,
-       max11617,
-       max11644,
-       max11645,
-       max11646,
-       max11647
-};
-
-static const int max1363_monitor_speeds[] = { 133000, 665000, 33300, 16600,
-					      8300, 4200, 2000, 1000 };
-
-static ssize_t max1363_monitor_show_freq(struct device *dev,
-					struct device_attribute *attr,
-					char *buf)
-{
-	struct max1363_state *st = iio_priv(dev_to_iio_dev(dev));
-	return sprintf(buf, "%d\n", max1363_monitor_speeds[st->monitor_speed]);
-}
-
-static ssize_t max1363_monitor_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 max1363_state *st = iio_priv(indio_dev);
-	int i, ret;
-	unsigned long val;
-	bool found = false;
-
-	ret = strict_strtoul(buf, 10, &val);
-	if (ret)
-		return -EINVAL;
-	for (i = 0; i < ARRAY_SIZE(max1363_monitor_speeds); i++)
-		if (val == max1363_monitor_speeds[i]) {
-			found = true;
-			break;
-		}
-	if (!found)
-		return -EINVAL;
-
-	mutex_lock(&indio_dev->mlock);
-	st->monitor_speed = i;
-	mutex_unlock(&indio_dev->mlock);
-
-	return 0;
-}
-
-static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR,
-			max1363_monitor_show_freq,
-			max1363_monitor_store_freq);
-
-static IIO_CONST_ATTR(sampling_frequency_available,
-		"133000 665000 33300 16600 8300 4200 2000 1000");
-
-static int max1363_read_thresh(struct iio_dev *indio_dev,
-			       u64 event_code,
-			       int *val)
-{
-	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)];
-	else
-		*val = st->thresh_high[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)];
-	return 0;
-}
-
-static int max1363_write_thresh(struct iio_dev *indio_dev,
-				u64 event_code,
-				int val)
-{
-	struct max1363_state *st = iio_priv(indio_dev);
-	/* make it handle signed correctly as well */
-	switch (st->chip_info->bits) {
-	case 10:
-		if (val > 0x3FF)
-			return -EINVAL;
-		break;
-	case 12:
-		if (val > 0xFFF)
-			return -EINVAL;
-		break;
-	}
-
-	switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
-	case IIO_EV_DIR_FALLING:
-		st->thresh_low[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)] = val;
-		break;
-	case IIO_EV_DIR_RISING:
-		st->thresh_high[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)] = val;
-		break;
-	}
-
-	return 0;
-}
-
-static const u64 max1363_event_codes[] = {
-	IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0,
-			     IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
-	IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 1,
-			     IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
-	IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 2,
-			     IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
-	IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 3,
-			     IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
-	IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0,
-			     IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
-	IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 1,
-			     IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
-	IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 2,
-			     IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
-	IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 3,
-			     IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
-};
-
-static irqreturn_t max1363_event_handler(int irq, void *private)
-{
-	struct iio_dev *indio_dev = private;
-	struct max1363_state *st = iio_priv(indio_dev);
-	s64 timestamp = iio_get_time_ns();
-	unsigned long mask, loc;
-	u8 rx;
-	u8 tx[2] = { st->setupbyte,
-		     MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0 };
-
-	i2c_master_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);
-
-	return IRQ_HANDLED;
-}
-
-static int max1363_read_event_config(struct iio_dev *indio_dev,
-				     u64 event_code)
-{
-	struct max1363_state *st = iio_priv(indio_dev);
-
-	int val;
-	int number = IIO_EVENT_CODE_EXTRACT_CHAN(event_code);
-	mutex_lock(&indio_dev->mlock);
-	if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING)
-		val = (1 << number) & st->mask_low;
-	else
-		val = (1 << number) & st->mask_high;
-	mutex_unlock(&indio_dev->mlock);
-
-	return val;
-}
-
-static int max1363_monitor_mode_update(struct max1363_state *st, int enabled)
-{
-	u8 *tx_buf;
-	int ret, i = 3, j;
-	unsigned long numelements;
-	int len;
-	const long *modemask;
-
-	if (!enabled) {
-		/* transition to ring capture is not currently supported */
-		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);
-	}
-
-	/* Ensure we are in the relevant mode */
-	st->setupbyte |= MAX1363_SETUP_MONITOR_SETUP;
-	st->configbyte &= ~(MAX1363_CHANNEL_SEL_MASK
-			    | MAX1363_SCAN_MASK
-			| MAX1363_SE_DE_MASK);
-	st->configbyte |= MAX1363_CONFIG_SCAN_MONITOR_MODE;
-	if ((st->mask_low | st->mask_high) & 0x0F) {
-		st->configbyte |= max1363_mode_table[s0to3].conf;
-		modemask = max1363_mode_table[s0to3].modemask;
-	} else if ((st->mask_low | st->mask_high) & 0x30) {
-		st->configbyte |= max1363_mode_table[d0m1to2m3].conf;
-		modemask = max1363_mode_table[d0m1to2m3].modemask;
-	} else {
-		st->configbyte |= max1363_mode_table[d1m0to3m2].conf;
-		modemask = max1363_mode_table[d1m0to3m2].modemask;
-	}
-	numelements = bitmap_weight(modemask, MAX1363_MAX_CHANNELS);
-	len = 3 * numelements + 3;
-	tx_buf = kmalloc(len, GFP_KERNEL);
-	if (!tx_buf) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-	tx_buf[0] = st->configbyte;
-	tx_buf[1] = st->setupbyte;
-	tx_buf[2] = (st->monitor_speed << 1);
-
-	/*
-	 * So we need to do yet another bit of nefarious scan mode
-	 * setup to match what we need.
-	 */
-	for (j = 0; j < 8; j++)
-		if (test_bit(j, modemask)) {
-			/* Establish the mode is in the scan */
-			if (st->mask_low & (1 << j)) {
-				tx_buf[i] = (st->thresh_low[j] >> 4) & 0xFF;
-				tx_buf[i + 1] = (st->thresh_low[j] << 4) & 0xF0;
-			} else if (j < 4) {
-				tx_buf[i] = 0;
-				tx_buf[i + 1] = 0;
-			} else {
-				tx_buf[i] = 0x80;
-				tx_buf[i + 1] = 0;
-			}
-			if (st->mask_high & (1 << j)) {
-				tx_buf[i + 1] |=
-					(st->thresh_high[j] >> 8) & 0x0F;
-				tx_buf[i + 2] = st->thresh_high[j] & 0xFF;
-			} else if (j < 4) {
-				tx_buf[i + 1] |= 0x0F;
-				tx_buf[i + 2] = 0xFF;
-			} else {
-				tx_buf[i + 1] |= 0x07;
-				tx_buf[i + 2] = 0xFF;
-			}
-			i += 3;
-		}
-
-
-	ret = i2c_master_send(st->client, tx_buf, len);
-	if (ret < 0)
-		goto error_ret;
-	if (ret != len) {
-		ret = -EIO;
-		goto error_ret;
-	}
-
-	/*
-	 * Now that we hopefully have sensible thresholds in place it is
-	 * time to turn the interrupts on.
-	 * It is unclear from the data sheet if this should be necessary
-	 * (i.e. whether monitor mode setup is atomic) but it appears to
-	 * be in practice.
-	 */
-	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);
-	if (ret < 0)
-		goto error_ret;
-	if (ret != 2) {
-		ret = -EIO;
-		goto error_ret;
-	}
-	ret = 0;
-	st->monitor_on = true;
-error_ret:
-
-	kfree(tx_buf);
-
-	return ret;
-}
-
-/*
- * To keep this manageable we always use one of 3 scan modes.
- * Scan 0...3, 0-1,2-3 and 1-0,3-2
- */
-
-static inline int __max1363_check_event_mask(int thismask, int checkmask)
-{
-	int ret = 0;
-	/* Is it unipolar */
-	if (thismask < 4) {
-		if (checkmask & ~0x0F) {
-			ret = -EBUSY;
-			goto error_ret;
-		}
-	} else if (thismask < 6) {
-		if (checkmask & ~0x30) {
-			ret = -EBUSY;
-			goto error_ret;
-		}
-	} else if (checkmask & ~0xC0)
-		ret = -EBUSY;
-error_ret:
-	return ret;
-}
-
-static int max1363_write_event_config(struct iio_dev *indio_dev,
-				      u64 event_code,
-				      int state)
-{
-	int ret = 0;
-	struct max1363_state *st = iio_priv(indio_dev);
-	u16 unifiedmask;
-	int number = IIO_EVENT_CODE_EXTRACT_CHAN(event_code);
-
-	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 (state == 0)
-			st->mask_low &= ~(1 << number);
-		else {
-			ret = __max1363_check_event_mask((1 << number),
-							 unifiedmask);
-			if (ret)
-				goto error_ret;
-			st->mask_low |= (1 << number);
-		}
-	} else {
-		if (state == 0)
-			st->mask_high &= ~(1 << number);
-		else {
-			ret = __max1363_check_event_mask((1 << number),
-							 unifiedmask);
-			if (ret)
-				goto error_ret;
-			st->mask_high |= (1 << number);
-		}
-	}
-
-	max1363_monitor_mode_update(st, !!(st->mask_high | st->mask_low));
-error_ret:
-	mutex_unlock(&indio_dev->mlock);
-
-	return ret;
-}
-
-/*
- * As with scan_elements, only certain sets of these can
- * be combined.
- */
-static struct attribute *max1363_event_attributes[] = {
-	&iio_dev_attr_sampling_frequency.dev_attr.attr,
-	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
-	NULL,
-};
-
-static struct attribute_group max1363_event_attribute_group = {
-	.attrs = max1363_event_attributes,
-	.name = "events",
-};
-
-#define MAX1363_EVENT_FUNCS						\
-
-
-static const struct iio_info max1238_info = {
-	.read_raw = &max1363_read_raw,
-	.driver_module = THIS_MODULE,
-	.update_scan_mode = &max1363_update_scan_mode,
-};
-
-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_raw = &max1363_read_raw,
-	.update_scan_mode = &max1363_update_scan_mode,
-	.driver_module = THIS_MODULE,
-	.event_attrs = &max1363_event_attribute_group,
-};
-
-/* max1363 and max1368 tested - rest from data sheet */
-static const struct max1363_chip_info max1363_chip_info_tbl[] = {
-	[max1361] = {
-		.bits = 10,
-		.int_vref_mv = 2048,
-		.mode_list = max1363_mode_list,
-		.num_modes = ARRAY_SIZE(max1363_mode_list),
-		.default_mode = s0to3,
-		.channels = max1361_channels,
-		.num_channels = ARRAY_SIZE(max1361_channels),
-		.info = &max1363_info,
-	},
-	[max1362] = {
-		.bits = 10,
-		.int_vref_mv = 4096,
-		.mode_list = max1363_mode_list,
-		.num_modes = ARRAY_SIZE(max1363_mode_list),
-		.default_mode = s0to3,
-		.channels = max1361_channels,
-		.num_channels = ARRAY_SIZE(max1361_channels),
-		.info = &max1363_info,
-	},
-	[max1363] = {
-		.bits = 12,
-		.int_vref_mv = 2048,
-		.mode_list = max1363_mode_list,
-		.num_modes = ARRAY_SIZE(max1363_mode_list),
-		.default_mode = s0to3,
-		.channels = max1363_channels,
-		.num_channels = ARRAY_SIZE(max1363_channels),
-		.info = &max1363_info,
-	},
-	[max1364] = {
-		.bits = 12,
-		.int_vref_mv = 4096,
-		.mode_list = max1363_mode_list,
-		.num_modes = ARRAY_SIZE(max1363_mode_list),
-		.default_mode = s0to3,
-		.channels = max1363_channels,
-		.num_channels = ARRAY_SIZE(max1363_channels),
-		.info = &max1363_info,
-	},
-	[max1036] = {
-		.bits = 8,
-		.int_vref_mv = 4096,
-		.mode_list = max1236_mode_list,
-		.num_modes = ARRAY_SIZE(max1236_mode_list),
-		.default_mode = s0to3,
-		.info = &max1238_info,
-		.channels = max1036_channels,
-		.num_channels = ARRAY_SIZE(max1036_channels),
-	},
-	[max1037] = {
-		.bits = 8,
-		.int_vref_mv = 2048,
-		.mode_list = max1236_mode_list,
-		.num_modes = ARRAY_SIZE(max1236_mode_list),
-		.default_mode = s0to3,
-		.info = &max1238_info,
-		.channels = max1036_channels,
-		.num_channels = ARRAY_SIZE(max1036_channels),
-	},
-	[max1038] = {
-		.bits = 8,
-		.int_vref_mv = 4096,
-		.mode_list = max1238_mode_list,
-		.num_modes = ARRAY_SIZE(max1238_mode_list),
-		.default_mode = s0to11,
-		.info = &max1238_info,
-		.channels = max1038_channels,
-		.num_channels = ARRAY_SIZE(max1038_channels),
-	},
-	[max1039] = {
-		.bits = 8,
-		.int_vref_mv = 2048,
-		.mode_list = max1238_mode_list,
-		.num_modes = ARRAY_SIZE(max1238_mode_list),
-		.default_mode = s0to11,
-		.info = &max1238_info,
-		.channels = max1038_channels,
-		.num_channels = ARRAY_SIZE(max1038_channels),
-	},
-	[max1136] = {
-		.bits = 10,
-		.int_vref_mv = 4096,
-		.mode_list = max1236_mode_list,
-		.num_modes = ARRAY_SIZE(max1236_mode_list),
-		.default_mode = s0to3,
-		.info = &max1238_info,
-		.channels = max1136_channels,
-		.num_channels = ARRAY_SIZE(max1136_channels),
-	},
-	[max1137] = {
-		.bits = 10,
-		.int_vref_mv = 2048,
-		.mode_list = max1236_mode_list,
-		.num_modes = ARRAY_SIZE(max1236_mode_list),
-		.default_mode = s0to3,
-		.info = &max1238_info,
-		.channels = max1136_channels,
-		.num_channels = ARRAY_SIZE(max1136_channels),
-	},
-	[max1138] = {
-		.bits = 10,
-		.int_vref_mv = 4096,
-		.mode_list = max1238_mode_list,
-		.num_modes = ARRAY_SIZE(max1238_mode_list),
-		.default_mode = s0to11,
-		.info = &max1238_info,
-		.channels = max1138_channels,
-		.num_channels = ARRAY_SIZE(max1138_channels),
-	},
-	[max1139] = {
-		.bits = 10,
-		.int_vref_mv = 2048,
-		.mode_list = max1238_mode_list,
-		.num_modes = ARRAY_SIZE(max1238_mode_list),
-		.default_mode = s0to11,
-		.info = &max1238_info,
-		.channels = max1138_channels,
-		.num_channels = ARRAY_SIZE(max1138_channels),
-	},
-	[max1236] = {
-		.bits = 12,
-		.int_vref_mv = 4096,
-		.mode_list = max1236_mode_list,
-		.num_modes = ARRAY_SIZE(max1236_mode_list),
-		.default_mode = s0to3,
-		.info = &max1238_info,
-		.channels = max1236_channels,
-		.num_channels = ARRAY_SIZE(max1236_channels),
-	},
-	[max1237] = {
-		.bits = 12,
-		.int_vref_mv = 2048,
-		.mode_list = max1236_mode_list,
-		.num_modes = ARRAY_SIZE(max1236_mode_list),
-		.default_mode = s0to3,
-		.info = &max1238_info,
-		.channels = max1236_channels,
-		.num_channels = ARRAY_SIZE(max1236_channels),
-	},
-	[max1238] = {
-		.bits = 12,
-		.int_vref_mv = 4096,
-		.mode_list = max1238_mode_list,
-		.num_modes = ARRAY_SIZE(max1238_mode_list),
-		.default_mode = s0to11,
-		.info = &max1238_info,
-		.channels = max1238_channels,
-		.num_channels = ARRAY_SIZE(max1238_channels),
-	},
-	[max1239] = {
-		.bits = 12,
-		.int_vref_mv = 2048,
-		.mode_list = max1238_mode_list,
-		.num_modes = ARRAY_SIZE(max1238_mode_list),
-		.default_mode = s0to11,
-		.info = &max1238_info,
-		.channels = max1238_channels,
-		.num_channels = ARRAY_SIZE(max1238_channels),
-	},
-	[max11600] = {
-		.bits = 8,
-		.int_vref_mv = 4096,
-		.mode_list = max11607_mode_list,
-		.num_modes = ARRAY_SIZE(max11607_mode_list),
-		.default_mode = s0to3,
-		.info = &max1238_info,
-		.channels = max1036_channels,
-		.num_channels = ARRAY_SIZE(max1036_channels),
-	},
-	[max11601] = {
-		.bits = 8,
-		.int_vref_mv = 2048,
-		.mode_list = max11607_mode_list,
-		.num_modes = ARRAY_SIZE(max11607_mode_list),
-		.default_mode = s0to3,
-		.info = &max1238_info,
-		.channels = max1036_channels,
-		.num_channels = ARRAY_SIZE(max1036_channels),
-	},
-	[max11602] = {
-		.bits = 8,
-		.int_vref_mv = 4096,
-		.mode_list = max11608_mode_list,
-		.num_modes = ARRAY_SIZE(max11608_mode_list),
-		.default_mode = s0to7,
-		.info = &max1238_info,
-		.channels = max11602_channels,
-		.num_channels = ARRAY_SIZE(max11602_channels),
-	},
-	[max11603] = {
-		.bits = 8,
-		.int_vref_mv = 2048,
-		.mode_list = max11608_mode_list,
-		.num_modes = ARRAY_SIZE(max11608_mode_list),
-		.default_mode = s0to7,
-		.info = &max1238_info,
-		.channels = max11602_channels,
-		.num_channels = ARRAY_SIZE(max11602_channels),
-	},
-	[max11604] = {
-		.bits = 8,
-		.int_vref_mv = 4098,
-		.mode_list = max1238_mode_list,
-		.num_modes = ARRAY_SIZE(max1238_mode_list),
-		.default_mode = s0to11,
-		.info = &max1238_info,
-		.channels = max1238_channels,
-		.num_channels = ARRAY_SIZE(max1238_channels),
-	},
-	[max11605] = {
-		.bits = 8,
-		.int_vref_mv = 2048,
-		.mode_list = max1238_mode_list,
-		.num_modes = ARRAY_SIZE(max1238_mode_list),
-		.default_mode = s0to11,
-		.info = &max1238_info,
-		.channels = max1238_channels,
-		.num_channels = ARRAY_SIZE(max1238_channels),
-	},
-	[max11606] = {
-		.bits = 10,
-		.int_vref_mv = 4096,
-		.mode_list = max11607_mode_list,
-		.num_modes = ARRAY_SIZE(max11607_mode_list),
-		.default_mode = s0to3,
-		.info = &max1238_info,
-		.channels = max1136_channels,
-		.num_channels = ARRAY_SIZE(max1136_channels),
-	},
-	[max11607] = {
-		.bits = 10,
-		.int_vref_mv = 2048,
-		.mode_list = max11607_mode_list,
-		.num_modes = ARRAY_SIZE(max11607_mode_list),
-		.default_mode = s0to3,
-		.info = &max1238_info,
-		.channels = max1136_channels,
-		.num_channels = ARRAY_SIZE(max1136_channels),
-	},
-	[max11608] = {
-		.bits = 10,
-		.int_vref_mv = 4096,
-		.mode_list = max11608_mode_list,
-		.num_modes = ARRAY_SIZE(max11608_mode_list),
-		.default_mode = s0to7,
-		.info = &max1238_info,
-		.channels = max11608_channels,
-		.num_channels = ARRAY_SIZE(max11608_channels),
-	},
-	[max11609] = {
-		.bits = 10,
-		.int_vref_mv = 2048,
-		.mode_list = max11608_mode_list,
-		.num_modes = ARRAY_SIZE(max11608_mode_list),
-		.default_mode = s0to7,
-		.info = &max1238_info,
-		.channels = max11608_channels,
-		.num_channels = ARRAY_SIZE(max11608_channels),
-	},
-	[max11610] = {
-		.bits = 10,
-		.int_vref_mv = 4098,
-		.mode_list = max1238_mode_list,
-		.num_modes = ARRAY_SIZE(max1238_mode_list),
-		.default_mode = s0to11,
-		.info = &max1238_info,
-		.channels = max1238_channels,
-		.num_channels = ARRAY_SIZE(max1238_channels),
-	},
-	[max11611] = {
-		.bits = 10,
-		.int_vref_mv = 2048,
-		.mode_list = max1238_mode_list,
-		.num_modes = ARRAY_SIZE(max1238_mode_list),
-		.default_mode = s0to11,
-		.info = &max1238_info,
-		.channels = max1238_channels,
-		.num_channels = ARRAY_SIZE(max1238_channels),
-	},
-	[max11612] = {
-		.bits = 12,
-		.int_vref_mv = 4096,
-		.mode_list = max11607_mode_list,
-		.num_modes = ARRAY_SIZE(max11607_mode_list),
-		.default_mode = s0to3,
-		.info = &max1238_info,
-		.channels = max1363_channels,
-		.num_channels = ARRAY_SIZE(max1363_channels),
-	},
-	[max11613] = {
-		.bits = 12,
-		.int_vref_mv = 2048,
-		.mode_list = max11607_mode_list,
-		.num_modes = ARRAY_SIZE(max11607_mode_list),
-		.default_mode = s0to3,
-		.info = &max1238_info,
-		.channels = max1363_channels,
-		.num_channels = ARRAY_SIZE(max1363_channels),
-	},
-	[max11614] = {
-		.bits = 12,
-		.int_vref_mv = 4096,
-		.mode_list = max11608_mode_list,
-		.num_modes = ARRAY_SIZE(max11608_mode_list),
-		.default_mode = s0to7,
-		.info = &max1238_info,
-		.channels = max11614_channels,
-		.num_channels = ARRAY_SIZE(max11614_channels),
-	},
-	[max11615] = {
-		.bits = 12,
-		.int_vref_mv = 2048,
-		.mode_list = max11608_mode_list,
-		.num_modes = ARRAY_SIZE(max11608_mode_list),
-		.default_mode = s0to7,
-		.info = &max1238_info,
-		.channels = max11614_channels,
-		.num_channels = ARRAY_SIZE(max11614_channels),
-	},
-	[max11616] = {
-		.bits = 12,
-		.int_vref_mv = 4098,
-		.mode_list = max1238_mode_list,
-		.num_modes = ARRAY_SIZE(max1238_mode_list),
-		.default_mode = s0to11,
-		.info = &max1238_info,
-		.channels = max1238_channels,
-		.num_channels = ARRAY_SIZE(max1238_channels),
-	},
-	[max11617] = {
-		.bits = 12,
-		.int_vref_mv = 2048,
-		.mode_list = max1238_mode_list,
-		.num_modes = ARRAY_SIZE(max1238_mode_list),
-		.default_mode = s0to11,
-		.info = &max1238_info,
-		.channels = max1238_channels,
-		.num_channels = ARRAY_SIZE(max1238_channels),
-	},
-	[max11644] = {
-		.bits = 12,
-		.int_vref_mv = 2048,
-		.mode_list = max11644_mode_list,
-		.num_modes = ARRAY_SIZE(max11644_mode_list),
-		.default_mode = s0to1,
-		.info = &max1238_info,
-		.channels = max11644_channels,
-		.num_channels = ARRAY_SIZE(max11644_channels),
-	},
-	[max11645] = {
-		.bits = 12,
-		.int_vref_mv = 4096,
-		.mode_list = max11644_mode_list,
-		.num_modes = ARRAY_SIZE(max11644_mode_list),
-		.default_mode = s0to1,
-		.info = &max1238_info,
-		.channels = max11644_channels,
-		.num_channels = ARRAY_SIZE(max11644_channels),
-	},
-	[max11646] = {
-		.bits = 10,
-		.int_vref_mv = 2048,
-		.mode_list = max11644_mode_list,
-		.num_modes = ARRAY_SIZE(max11644_mode_list),
-		.default_mode = s0to1,
-		.info = &max1238_info,
-		.channels = max11646_channels,
-		.num_channels = ARRAY_SIZE(max11646_channels),
-	},
-	[max11647] = {
-		.bits = 10,
-		.int_vref_mv = 4096,
-		.mode_list = max11644_mode_list,
-		.num_modes = ARRAY_SIZE(max11644_mode_list),
-		.default_mode = s0to1,
-		.info = &max1238_info,
-		.channels = max11646_channels,
-		.num_channels = ARRAY_SIZE(max11646_channels),
-	},
-};
-
-
-
-static int max1363_initial_setup(struct max1363_state *st)
-{
-	st->setupbyte = MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD
-		| MAX1363_SETUP_POWER_UP_INT_REF
-		| MAX1363_SETUP_INT_CLOCK
-		| MAX1363_SETUP_UNIPOLAR
-		| MAX1363_SETUP_NORESET;
-
-	/* Set scan mode writes the config anyway so wait until then*/
-	st->setupbyte = MAX1363_SETUP_BYTE(st->setupbyte);
-	st->current_mode = &max1363_mode_table[st->chip_info->default_mode];
-	st->configbyte = MAX1363_CONFIG_BYTE(st->configbyte);
-
-	return max1363_set_scan_mode(st);
-}
-
-static int __devinit max1363_alloc_scan_masks(struct iio_dev *indio_dev)
-{
-	struct max1363_state *st = iio_priv(indio_dev);
-	unsigned long *masks;
-	int i;
-
-	masks = kzalloc(BITS_TO_LONGS(MAX1363_MAX_CHANNELS)*sizeof(long)*
-			  (st->chip_info->num_modes + 1), GFP_KERNEL);
-	if (!masks)
-		return -ENOMEM;
-
-	for (i = 0; i < st->chip_info->num_modes; i++)
-		bitmap_copy(masks + BITS_TO_LONGS(MAX1363_MAX_CHANNELS)*i,
-			    max1363_mode_table[st->chip_info->mode_list[i]]
-			    .modemask, MAX1363_MAX_CHANNELS);
-
-	indio_dev->available_scan_masks = masks;
-
-	return 0;
-}
-
-static int __devinit max1363_probe(struct i2c_client *client,
-				   const struct i2c_device_id *id)
-{
-	int ret;
-	struct max1363_state *st;
-	struct iio_dev *indio_dev;
-	struct regulator *reg;
-
-	reg = regulator_get(&client->dev, "vcc");
-	if (IS_ERR(reg)) {
-		ret = PTR_ERR(reg);
-		goto error_out;
-	}
-
-	ret = regulator_enable(reg);
-	if (ret)
-		goto error_put_reg;
-
-	indio_dev = iio_device_alloc(sizeof(struct max1363_state));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_disable_reg;
-	}
-	ret = iio_map_array_register(indio_dev, client->dev.platform_data);
-	if (ret < 0)
-		goto error_free_device;
-	st = iio_priv(indio_dev);
-	st->reg = reg;
-	/* this is only used for device removal purposes */
-	i2c_set_clientdata(client, indio_dev);
-
-	st->chip_info = &max1363_chip_info_tbl[id->driver_data];
-	st->client = client;
-
-	ret = max1363_alloc_scan_masks(indio_dev);
-	if (ret)
-		goto error_unregister_map;
-
-	/* Estabilish that the iio_dev is a child of the i2c device */
-	indio_dev->dev.parent = &client->dev;
-	indio_dev->name = id->name;
-	indio_dev->channels = st->chip_info->channels;
-	indio_dev->num_channels = st->chip_info->num_channels;
-	indio_dev->info = st->chip_info->info;
-	indio_dev->modes = INDIO_DIRECT_MODE;
-	indio_dev->channels = st->chip_info->channels;
-	indio_dev->num_channels = st->chip_info->num_channels;
-	ret = max1363_initial_setup(st);
-	if (ret < 0)
-		goto error_free_available_scan_masks;
-
-	ret = max1363_register_ring_funcs_and_init(indio_dev);
-	if (ret)
-		goto error_free_available_scan_masks;
-
-	ret = iio_buffer_register(indio_dev,
-				  st->chip_info->channels,
-				  st->chip_info->num_channels);
-	if (ret)
-		goto error_cleanup_ring;
-
-	if (client->irq) {
-		ret = request_threaded_irq(st->client->irq,
-					   NULL,
-					   &max1363_event_handler,
-					   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
-					   "max1363_event",
-					   indio_dev);
-
-		if (ret)
-			goto error_uninit_ring;
-	}
-
-	ret = iio_device_register(indio_dev);
-	if (ret < 0)
-		goto error_free_irq;
-
-	return 0;
-error_free_irq:
-	free_irq(st->client->irq, indio_dev);
-error_uninit_ring:
-	iio_buffer_unregister(indio_dev);
-error_cleanup_ring:
-	max1363_ring_cleanup(indio_dev);
-error_free_available_scan_masks:
-	kfree(indio_dev->available_scan_masks);
-error_unregister_map:
-	iio_map_array_unregister(indio_dev, client->dev.platform_data);
-error_free_device:
-	iio_device_free(indio_dev);
-error_disable_reg:
-	regulator_disable(reg);
-error_put_reg:
-	regulator_put(reg);
-error_out:
-	return ret;
-}
-
-static int __devexit max1363_remove(struct i2c_client *client)
-{
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
-	struct max1363_state *st = iio_priv(indio_dev);
-	struct regulator *reg = st->reg;
-
-	iio_device_unregister(indio_dev);
-	if (client->irq)
-		free_irq(st->client->irq, indio_dev);
-	iio_buffer_unregister(indio_dev);
-	max1363_ring_cleanup(indio_dev);
-	kfree(indio_dev->available_scan_masks);
-	if (!IS_ERR(reg)) {
-		regulator_disable(reg);
-		regulator_put(reg);
-	}
-	iio_map_array_unregister(indio_dev, client->dev.platform_data);
-	iio_device_free(indio_dev);
-
-	return 0;
-}
-
-static const struct i2c_device_id max1363_id[] = {
-	{ "max1361", max1361 },
-	{ "max1362", max1362 },
-	{ "max1363", max1363 },
-	{ "max1364", max1364 },
-	{ "max1036", max1036 },
-	{ "max1037", max1037 },
-	{ "max1038", max1038 },
-	{ "max1039", max1039 },
-	{ "max1136", max1136 },
-	{ "max1137", max1137 },
-	{ "max1138", max1138 },
-	{ "max1139", max1139 },
-	{ "max1236", max1236 },
-	{ "max1237", max1237 },
-	{ "max1238", max1238 },
-	{ "max1239", max1239 },
-	{ "max11600", max11600 },
-	{ "max11601", max11601 },
-	{ "max11602", max11602 },
-	{ "max11603", max11603 },
-	{ "max11604", max11604 },
-	{ "max11605", max11605 },
-	{ "max11606", max11606 },
-	{ "max11607", max11607 },
-	{ "max11608", max11608 },
-	{ "max11609", max11609 },
-	{ "max11610", max11610 },
-	{ "max11611", max11611 },
-	{ "max11612", max11612 },
-	{ "max11613", max11613 },
-	{ "max11614", max11614 },
-	{ "max11615", max11615 },
-	{ "max11616", max11616 },
-	{ "max11617", max11617 },
-	{}
-};
-
-MODULE_DEVICE_TABLE(i2c, max1363_id);
-
-static struct i2c_driver max1363_driver = {
-	.driver = {
-		.name = "max1363",
-	},
-	.probe = max1363_probe,
-	.remove = __devexit_p(max1363_remove),
-	.id_table = max1363_id,
-};
-module_i2c_driver(max1363_driver);
-
-MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
-MODULE_DESCRIPTION("Maxim 1363 ADC");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c
deleted file mode 100644
index 5f74f3b..0000000
--- a/drivers/staging/iio/adc/max1363_ring.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2008 Jonathan Cameron
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * max1363_ring.c
- */
-
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/bitops.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/buffer.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-
-#include "max1363.h"
-
-int max1363_update_scan_mode(struct iio_dev *indio_dev,
-			     const unsigned long *scan_mask)
-{
-	struct max1363_state *st = iio_priv(indio_dev);
-
-	/*
-	 * Need to figure out the current mode based upon the requested
-	 * scan mask in iio_dev
-	 */
-	st->current_mode = max1363_match_mode(scan_mask, st->chip_info);
-	if (!st->current_mode)
-		return -EINVAL;
-	max1363_set_scan_mode(st);
-	return 0;
-}
-
-static irqreturn_t max1363_trigger_handler(int irq, void *p)
-{
-	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;
-	unsigned long numvals = bitmap_weight(st->current_mode->modemask,
-					      MAX1363_MAX_CHANNELS);
-
-	/* Ensure the timestamp is 8 byte aligned */
-	if (st->chip_info->bits != 8)
-		d_size = numvals*2;
-	else
-		d_size = numvals;
-	if (indio_dev->scan_timestamp) {
-		d_size += sizeof(s64);
-		if (d_size % sizeof(s64))
-			d_size += sizeof(s64) - (d_size % sizeof(s64));
-	}
-	/* Monitor mode prevents reading. Whilst not currently implemented
-	 * might as well have this test in here in the meantime as it does
-	 * no harm.
-	 */
-	if (numvals == 0)
-		goto done;
-
-	rxbuf = kmalloc(d_size,	GFP_KERNEL);
-	if (rxbuf == NULL)
-		goto done;
-	if (st->chip_info->bits != 8)
-		b_sent = i2c_master_recv(st->client, rxbuf, numvals*2);
-	else
-		b_sent = i2c_master_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_buffer(indio_dev->buffer, rxbuf);
-
-done_free:
-	kfree(rxbuf);
-done:
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-static const struct iio_buffer_setup_ops max1363_ring_setup_ops = {
-	.postenable = &iio_triggered_buffer_postenable,
-	.preenable = &iio_sw_buffer_preenable,
-	.predisable = &iio_triggered_buffer_predisable,
-};
-
-int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
-	struct max1363_state *st = iio_priv(indio_dev);
-	int ret = 0;
-
-	indio_dev->buffer = iio_sw_rb_allocate(indio_dev);
-	if (!indio_dev->buffer) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-	indio_dev->pollfunc = iio_alloc_pollfunc(NULL,
-						 &max1363_trigger_handler,
-						 IRQF_ONESHOT,
-						 indio_dev,
-						 "%s_consumer%d",
-						 st->client->name,
-						 indio_dev->id);
-	if (indio_dev->pollfunc == NULL) {
-		ret = -ENOMEM;
-		goto error_deallocate_sw_rb;
-	}
-	/* Ring buffer functions - here trigger setup related */
-	indio_dev->setup_ops = &max1363_ring_setup_ops;
-
-	/* Flag that polled ring buffering is possible */
-	indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-
-	return 0;
-
-error_deallocate_sw_rb:
-	iio_sw_rb_free(indio_dev->buffer);
-error_ret:
-	return ret;
-}
-
-void max1363_ring_cleanup(struct iio_dev *indio_dev)
-{
-	/* ensure that the trigger has been detached */
-	iio_dealloc_pollfunc(indio_dev->pollfunc);
-	iio_sw_rb_free(indio_dev->buffer);
-}
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index ca7c1fa..fb31b45 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -237,7 +237,6 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
 	struct iio_poll_func *pf = p;
 	struct iio_dev *iio = pf->indio_dev;
 	struct mxs_lradc *lradc = iio_priv(iio);
-	struct iio_buffer *buffer = iio->buffer;
 	const uint32_t chan_value = LRADC_CH_ACCUMULATE |
 		((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET);
 	int i, j = 0;
@@ -256,7 +255,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
 		*timestamp = pf->timestamp;
 	}
 
-	iio_push_to_buffer(buffer, (u8 *)lradc->buffer);
+	iio_push_to_buffers(iio, (u8 *)lradc->buffer);
 
 	iio_trigger_notify_done(iio->trig);
 
@@ -351,7 +350,7 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
 		writel(chan_value, lradc->base + LRADC_CH(ofs));
 		enable |= 1 << ofs;
 		ofs++;
-	};
+	}
 
 	writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK,
 		lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR);
@@ -467,7 +466,7 @@ static void mxs_lradc_hw_stop(struct mxs_lradc *lradc)
 		writel(0, lradc->base + LRADC_DELAY(i));
 }
 
-static int __devinit mxs_lradc_probe(struct platform_device *pdev)
+static int mxs_lradc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct mxs_lradc *lradc;
@@ -552,7 +551,7 @@ err_addr:
 	return ret;
 }
 
-static int __devexit mxs_lradc_remove(struct platform_device *pdev)
+static int mxs_lradc_remove(struct platform_device *pdev)
 {
 	struct iio_dev *iio = platform_get_drvdata(pdev);
 	struct mxs_lradc *lradc = iio_priv(iio);
@@ -580,7 +579,7 @@ static struct platform_driver mxs_lradc_driver = {
 		.of_match_table = mxs_lradc_dt_ids,
 	},
 	.probe	= mxs_lradc_probe,
-	.remove	= __devexit_p(mxs_lradc_remove),
+	.remove	= mxs_lradc_remove,
 };
 
 module_platform_driver(mxs_lradc_driver);
diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c
index 0b83e2e..13052ce 100644
--- a/drivers/staging/iio/adc/spear_adc.c
+++ b/drivers/staging/iio/adc/spear_adc.c
@@ -291,7 +291,7 @@ static const struct iio_info spear_adc_iio_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit spear_adc_probe(struct platform_device *pdev)
+static int spear_adc_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct device *dev = &pdev->dev;
@@ -401,7 +401,7 @@ errout1:
 	return ret;
 }
 
-static int __devexit spear_adc_remove(struct platform_device *pdev)
+static int spear_adc_remove(struct platform_device *pdev)
 {
 	struct iio_dev *iodev = platform_get_drvdata(pdev);
 	struct spear_adc_info *info = iio_priv(iodev);
@@ -424,7 +424,7 @@ MODULE_DEVICE_TABLE(of, spear_adc_dt_ids);
 
 static struct platform_driver spear_adc_driver = {
 	.probe		= spear_adc_probe,
-	.remove		= __devexit_p(spear_adc_remove),
+	.remove		= spear_adc_remove,
 	.driver		= {
 		.name	= MOD_NAME,
 		.owner	= THIS_MODULE,
diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c
index 9e128dd..ce7d91c 100644
--- a/drivers/staging/iio/addac/adt7316-i2c.c
+++ b/drivers/staging/iio/addac/adt7316-i2c.c
@@ -92,7 +92,7 @@ static int adt7316_i2c_multi_write(void *client, u8 reg, u8 count, u8 *data)
  * device probe and remove
  */
 
-static int __devinit adt7316_i2c_probe(struct i2c_client *client,
+static int adt7316_i2c_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	struct adt7316_bus bus = {
@@ -108,7 +108,7 @@ static int __devinit adt7316_i2c_probe(struct i2c_client *client,
 	return adt7316_probe(&client->dev, &bus, id->name);
 }
 
-static int __devexit adt7316_i2c_remove(struct i2c_client *client)
+static int adt7316_i2c_remove(struct i2c_client *client)
 {
 	return adt7316_remove(&client->dev);
 }
@@ -132,7 +132,7 @@ static struct i2c_driver adt7316_driver = {
 		.owner  = THIS_MODULE,
 	},
 	.probe = adt7316_i2c_probe,
-	.remove = __devexit_p(adt7316_i2c_remove),
+	.remove = adt7316_i2c_remove,
 	.id_table = adt7316_i2c_id,
 };
 module_i2c_driver(adt7316_driver);
diff --git a/drivers/staging/iio/addac/adt7316-spi.c b/drivers/staging/iio/addac/adt7316-spi.c
index 985f7d8..0db8ef5 100644
--- a/drivers/staging/iio/addac/adt7316-spi.c
+++ b/drivers/staging/iio/addac/adt7316-spi.c
@@ -89,7 +89,7 @@ static int adt7316_spi_write(void *client, u8 reg, u8 val)
  * device probe and remove
  */
 
-static int __devinit adt7316_spi_probe(struct spi_device *spi_dev)
+static int adt7316_spi_probe(struct spi_device *spi_dev)
 {
 	struct adt7316_bus bus = {
 		.client = spi_dev,
@@ -116,7 +116,7 @@ static int __devinit adt7316_spi_probe(struct spi_device *spi_dev)
 	return adt7316_probe(&spi_dev->dev, &bus, spi_dev->modalias);
 }
 
-static int __devexit adt7316_spi_remove(struct spi_device *spi_dev)
+static int adt7316_spi_remove(struct spi_device *spi_dev)
 {
 	return adt7316_remove(&spi_dev->dev);
 }
@@ -140,7 +140,7 @@ static struct spi_driver adt7316_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = adt7316_spi_probe,
-	.remove = __devexit_p(adt7316_spi_remove),
+	.remove = adt7316_spi_remove,
 	.id_table = adt7316_spi_id,
 };
 module_spi_driver(adt7316_driver);
diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c
index 8fb014a..0b431bc 100644
--- a/drivers/staging/iio/addac/adt7316.c
+++ b/drivers/staging/iio/addac/adt7316.c
@@ -2125,7 +2125,7 @@ static const struct iio_info adt7516_info = {
 /*
  * device probe and remove
  */
-int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
+int adt7316_probe(struct device *dev, struct adt7316_bus *bus,
 		const char *name)
 {
 	struct adt7316_chip_info *chip;
@@ -2216,7 +2216,7 @@ error_ret:
 }
 EXPORT_SYMBOL(adt7316_probe);
 
-int __devexit adt7316_remove(struct device *dev)
+int adt7316_remove(struct device *dev)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct adt7316_chip_info *chip = iio_priv(indio_dev);
diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c
index 6a40414..3c608c1 100644
--- a/drivers/staging/iio/cdc/ad7150.c
+++ b/drivers/staging/iio/cdc/ad7150.c
@@ -156,7 +156,7 @@ static int ad7150_read_event_config(struct iio_dev *indio_dev, u64 event_code)
 			return !adaptive && (threshtype == 0x1);
 		else
 			return !adaptive && (threshtype == 0x0);
-	};
+	}
 	return -EINVAL;
 }
 
@@ -194,7 +194,7 @@ static int ad7150_write_event_params(struct iio_dev *indio_dev, u64 event_code)
 		break;
 	default:
 		return -EINVAL;
-	};
+	}
 	ret = i2c_smbus_write_byte_data(chip->client,
 					ad7150_addresses[chan][4],
 					sens);
@@ -257,7 +257,7 @@ static int ad7150_write_event_config(struct iio_dev *indio_dev,
 	default:
 		ret = -EINVAL;
 		goto error_ret;
-	};
+	}
 
 	cfg |= (!adaptive << 7) | (thresh_type << 5);
 
@@ -327,7 +327,7 @@ static int ad7150_write_event_value(struct iio_dev *indio_dev,
 	default:
 		ret = -EINVAL;
 		goto error_ret;
-	};
+	}
 
 	/* write back if active */
 	ret = ad7150_write_event_params(indio_dev, event_code);
@@ -360,7 +360,7 @@ static ssize_t ad7150_show_timeout(struct device *dev,
 		break;
 	default:
 		return -EINVAL;
-	};
+	}
 
 	return sprintf(buf, "%d\n", value);
 }
@@ -394,7 +394,7 @@ static ssize_t ad7150_store_timeout(struct device *dev,
 	default:
 		ret = -EINVAL;
 		goto error_ret;
-	};
+	}
 
 	ret = ad7150_write_event_params(indio_dev, this_attr->address);
 error_ret:
@@ -551,7 +551,7 @@ static const struct iio_info ad7150_info = {
  * device probe and remove
  */
 
-static int __devinit ad7150_probe(struct i2c_client *client,
+static int ad7150_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	int ret;
@@ -628,7 +628,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit ad7150_remove(struct i2c_client *client)
+static int ad7150_remove(struct i2c_client *client)
 {
 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
@@ -658,7 +658,7 @@ static struct i2c_driver ad7150_driver = {
 		.name = "ad7150",
 	},
 	.probe = ad7150_probe,
-	.remove = __devexit_p(ad7150_remove),
+	.remove = ad7150_remove,
 	.id_table = ad7150_id,
 };
 module_i2c_driver(ad7150_driver);
diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c
index 98c3015..3c92ba3 100644
--- a/drivers/staging/iio/cdc/ad7152.c
+++ b/drivers/staging/iio/cdc/ad7152.c
@@ -405,7 +405,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev,
 		break;
 	default:
 		ret = -EINVAL;
-	};
+	}
 out:
 	mutex_unlock(&indio_dev->mlock);
 	return ret;
@@ -474,7 +474,7 @@ static const struct iio_chan_spec ad7152_channels[] = {
  * device probe and remove
  */
 
-static int __devinit ad7152_probe(struct i2c_client *client,
+static int ad7152_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	int ret = 0;
@@ -518,7 +518,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit ad7152_remove(struct i2c_client *client)
+static int ad7152_remove(struct i2c_client *client)
 {
 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
@@ -541,7 +541,7 @@ static struct i2c_driver ad7152_driver = {
 		.name = KBUILD_MODNAME,
 	},
 	.probe = ad7152_probe,
-	.remove = __devexit_p(ad7152_remove),
+	.remove = ad7152_remove,
 	.id_table = ad7152_id,
 };
 module_i2c_driver(ad7152_driver);
diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c
index 754e11e..466b82e 100644
--- a/drivers/staging/iio/cdc/ad7746.c
+++ b/drivers/staging/iio/cdc/ad7746.c
@@ -677,7 +677,7 @@ static int ad7746_read_raw(struct iio_dev *indio_dev,
 		break;
 	default:
 		ret = -EINVAL;
-	};
+	}
 out:
 	mutex_unlock(&indio_dev->mlock);
 	return ret;
@@ -694,7 +694,7 @@ static const struct iio_info ad7746_info = {
  * device probe and remove
  */
 
-static int __devinit ad7746_probe(struct i2c_client *client,
+static int ad7746_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	struct ad7746_platform_data *pdata = client->dev.platform_data;
@@ -768,7 +768,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit ad7746_remove(struct i2c_client *client)
+static int ad7746_remove(struct i2c_client *client)
 {
 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
@@ -792,7 +792,7 @@ static struct i2c_driver ad7746_driver = {
 		.name = KBUILD_MODNAME,
 	},
 	.probe = ad7746_probe,
-	.remove = __devexit_p(ad7746_remove),
+	.remove = ad7746_remove,
 	.id_table = ad7746_id,
 };
 module_i2c_driver(ad7746_driver);
diff --git a/drivers/staging/iio/frequency/ad5930.c b/drivers/staging/iio/frequency/ad5930.c
index 2d541d0..23777be 100644
--- a/drivers/staging/iio/frequency/ad5930.c
+++ b/drivers/staging/iio/frequency/ad5930.c
@@ -91,7 +91,7 @@ static const struct iio_info ad5930_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit ad5930_probe(struct spi_device *spi)
+static int ad5930_probe(struct spi_device *spi)
 {
 	struct ad5930_state *st;
 	struct iio_dev *idev;
@@ -127,7 +127,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit ad5930_remove(struct spi_device *spi)
+static int ad5930_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
 	iio_device_free(spi_get_drvdata(spi));
@@ -141,7 +141,7 @@ static struct spi_driver ad5930_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ad5930_probe,
-	.remove = __devexit_p(ad5930_remove),
+	.remove = ad5930_remove,
 };
 module_spi_driver(ad5930_driver);
 
diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c
index fed3940..4e18380 100644
--- a/drivers/staging/iio/frequency/ad9832.c
+++ b/drivers/staging/iio/frequency/ad9832.c
@@ -201,7 +201,7 @@ static const struct iio_info ad9832_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit ad9832_probe(struct spi_device *spi)
+static int ad9832_probe(struct spi_device *spi)
 {
 	struct ad9832_platform_data *pdata = spi->dev.platform_data;
 	struct iio_dev *indio_dev;
@@ -324,7 +324,7 @@ error_put_reg:
 	return ret;
 }
 
-static int __devexit ad9832_remove(struct spi_device *spi)
+static int ad9832_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 	struct ad9832_state *st = iio_priv(indio_dev);
@@ -352,7 +352,7 @@ static struct spi_driver ad9832_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= ad9832_probe,
-	.remove		= __devexit_p(ad9832_remove),
+	.remove		= ad9832_remove,
 	.id_table	= ad9832_id,
 };
 module_spi_driver(ad9832_driver);
diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c
index 1b2dc74..5cba3c0 100644
--- a/drivers/staging/iio/frequency/ad9834.c
+++ b/drivers/staging/iio/frequency/ad9834.c
@@ -314,7 +314,7 @@ static const struct iio_info ad9833_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit ad9834_probe(struct spi_device *spi)
+static int ad9834_probe(struct spi_device *spi)
 {
 	struct ad9834_platform_data *pdata = spi->dev.platform_data;
 	struct ad9834_state *st;
@@ -424,7 +424,7 @@ error_put_reg:
 	return ret;
 }
 
-static int __devexit ad9834_remove(struct spi_device *spi)
+static int ad9834_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 	struct ad9834_state *st = iio_priv(indio_dev);
@@ -454,7 +454,7 @@ static struct spi_driver ad9834_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= ad9834_probe,
-	.remove		= __devexit_p(ad9834_remove),
+	.remove		= ad9834_remove,
 	.id_table	= ad9834_id,
 };
 module_spi_driver(ad9834_driver);
diff --git a/drivers/staging/iio/frequency/ad9850.c b/drivers/staging/iio/frequency/ad9850.c
index 74abee0..104f7a4 100644
--- a/drivers/staging/iio/frequency/ad9850.c
+++ b/drivers/staging/iio/frequency/ad9850.c
@@ -77,7 +77,7 @@ static const struct iio_info ad9850_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit ad9850_probe(struct spi_device *spi)
+static int ad9850_probe(struct spi_device *spi)
 {
 	struct ad9850_state *st;
 	struct iio_dev *idev;
@@ -113,7 +113,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit ad9850_remove(struct spi_device *spi)
+static int ad9850_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
 	iio_device_free(spi_get_drvdata(spi));
@@ -127,7 +127,7 @@ static struct spi_driver ad9850_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ad9850_probe,
-	.remove = __devexit_p(ad9850_remove),
+	.remove = ad9850_remove,
 };
 module_spi_driver(ad9850_driver);
 
diff --git a/drivers/staging/iio/frequency/ad9852.c b/drivers/staging/iio/frequency/ad9852.c
index fd9d14a..17ac825 100644
--- a/drivers/staging/iio/frequency/ad9852.c
+++ b/drivers/staging/iio/frequency/ad9852.c
@@ -226,7 +226,7 @@ static const struct iio_info ad9852_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit ad9852_probe(struct spi_device *spi)
+static int ad9852_probe(struct spi_device *spi)
 {
 	struct ad9852_state *st;
 	struct iio_dev *idev;
@@ -264,7 +264,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit ad9852_remove(struct spi_device *spi)
+static int ad9852_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
 	iio_device_free(spi_get_drvdata(spi));
@@ -278,7 +278,7 @@ static struct spi_driver ad9852_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ad9852_probe,
-	.remove = __devexit_p(ad9852_remove),
+	.remove = ad9852_remove,
 };
 module_spi_driver(ad9852_driver);
 
diff --git a/drivers/staging/iio/frequency/ad9910.c b/drivers/staging/iio/frequency/ad9910.c
index 5a7ba30..e48f874 100644
--- a/drivers/staging/iio/frequency/ad9910.c
+++ b/drivers/staging/iio/frequency/ad9910.c
@@ -361,7 +361,7 @@ static const struct iio_info ad9910_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit ad9910_probe(struct spi_device *spi)
+static int ad9910_probe(struct spi_device *spi)
 {
 	struct ad9910_state *st;
 	struct iio_dev *idev;
@@ -397,7 +397,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit ad9910_remove(struct spi_device *spi)
+static int ad9910_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
 	iio_device_free(spi_get_drvdata(spi));
@@ -411,7 +411,7 @@ static struct spi_driver ad9910_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ad9910_probe,
-	.remove = __devexit_p(ad9910_remove),
+	.remove = ad9910_remove,
 };
 module_spi_driver(ad9910_driver);
 
diff --git a/drivers/staging/iio/frequency/ad9951.c b/drivers/staging/iio/frequency/ad9951.c
index ba6f49f..8234e3c 100644
--- a/drivers/staging/iio/frequency/ad9951.c
+++ b/drivers/staging/iio/frequency/ad9951.c
@@ -170,7 +170,7 @@ static const struct iio_info ad9951_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit ad9951_probe(struct spi_device *spi)
+static int ad9951_probe(struct spi_device *spi)
 {
 	struct ad9951_state *st;
 	struct iio_dev *idev;
@@ -208,7 +208,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit ad9951_remove(struct spi_device *spi)
+static int ad9951_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
 	iio_device_free(spi_get_drvdata(spi));
@@ -222,7 +222,7 @@ static struct spi_driver ad9951_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ad9951_probe,
-	.remove = __devexit_p(ad9951_remove),
+	.remove = ad9951_remove,
 };
 module_spi_driver(ad9951_driver);
 
diff --git a/drivers/staging/iio/gyro/Makefile b/drivers/staging/iio/gyro/Makefile
index 9ba5ec1..1303569 100644
--- a/drivers/staging/iio/gyro/Makefile
+++ b/drivers/staging/iio/gyro/Makefile
@@ -12,7 +12,6 @@ adis16130-y             := adis16130_core.o
 obj-$(CONFIG_ADIS16130) += adis16130.o
 
 adis16260-y             := adis16260_core.o
-adis16260-$(CONFIG_IIO_BUFFER) += adis16260_ring.o adis16260_trigger.o
 obj-$(CONFIG_ADIS16260) += adis16260.o
 
 adis16251-y             := adis16251_core.o
diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c
index 87151a7..687c151 100644
--- a/drivers/staging/iio/gyro/adis16060_core.c
+++ b/drivers/staging/iio/gyro/adis16060_core.c
@@ -145,7 +145,7 @@ static const struct iio_chan_spec adis16060_channels[] = {
 	}
 };
 
-static int __devinit adis16060_r_probe(struct spi_device *spi)
+static int adis16060_r_probe(struct spi_device *spi)
 {
 	int ret;
 	struct adis16060_state *st;
@@ -184,7 +184,7 @@ error_ret:
 }
 
 /* fixme, confirm ordering in this function */
-static int __devexit adis16060_r_remove(struct spi_device *spi)
+static int adis16060_r_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
 	iio_device_free(spi_get_drvdata(spi));
@@ -192,7 +192,7 @@ static int __devexit adis16060_r_remove(struct spi_device *spi)
 	return 0;
 }
 
-static int __devinit adis16060_w_probe(struct spi_device *spi)
+static int adis16060_w_probe(struct spi_device *spi)
 {
 	int ret;
 	struct iio_dev *indio_dev = adis16060_iio_dev;
@@ -210,7 +210,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit adis16060_w_remove(struct spi_device *spi)
+static int adis16060_w_remove(struct spi_device *spi)
 {
 	return 0;
 }
@@ -221,7 +221,7 @@ static struct spi_driver adis16060_r_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = adis16060_r_probe,
-	.remove = __devexit_p(adis16060_r_remove),
+	.remove = adis16060_r_remove,
 };
 
 static struct spi_driver adis16060_w_driver = {
@@ -230,7 +230,7 @@ static struct spi_driver adis16060_w_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = adis16060_w_probe,
-	.remove = __devexit_p(adis16060_w_remove),
+	.remove = adis16060_w_remove,
 };
 
 static __init int adis16060_init(void)
diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c
index a739025..3525a68 100644
--- a/drivers/staging/iio/gyro/adis16080_core.c
+++ b/drivers/staging/iio/gyro/adis16080_core.c
@@ -138,7 +138,7 @@ static const struct iio_info adis16080_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit adis16080_probe(struct spi_device *spi)
+static int adis16080_probe(struct spi_device *spi)
 {
 	int ret;
 	struct adis16080_state *st;
@@ -177,7 +177,7 @@ error_ret:
 }
 
 /* fixme, confirm ordering in this function */
-static int __devexit adis16080_remove(struct spi_device *spi)
+static int adis16080_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
 	iio_device_free(spi_get_drvdata(spi));
@@ -191,7 +191,7 @@ static struct spi_driver adis16080_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = adis16080_probe,
-	.remove = __devexit_p(adis16080_remove),
+	.remove = adis16080_remove,
 };
 module_spi_driver(adis16080_driver);
 
diff --git a/drivers/staging/iio/gyro/adis16130_core.c b/drivers/staging/iio/gyro/adis16130_core.c
index fbf96b0..835801e 100644
--- a/drivers/staging/iio/gyro/adis16130_core.c
+++ b/drivers/staging/iio/gyro/adis16130_core.c
@@ -116,7 +116,7 @@ static const struct iio_info adis16130_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit adis16130_probe(struct spi_device *spi)
+static int adis16130_probe(struct spi_device *spi)
 {
 	int ret;
 	struct adis16130_state *st;
@@ -154,7 +154,7 @@ error_ret:
 }
 
 /* fixme, confirm ordering in this function */
-static int __devexit adis16130_remove(struct spi_device *spi)
+static int adis16130_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
 	iio_device_free(spi_get_drvdata(spi));
@@ -168,7 +168,7 @@ static struct spi_driver adis16130_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = adis16130_probe,
-	.remove = __devexit_p(adis16130_remove),
+	.remove = adis16130_remove,
 };
 module_spi_driver(adis16130_driver);
 
diff --git a/drivers/staging/iio/gyro/adis16260.h b/drivers/staging/iio/gyro/adis16260.h
index 4c4b251..df3c0b7 100644
--- a/drivers/staging/iio/gyro/adis16260.h
+++ b/drivers/staging/iio/gyro/adis16260.h
@@ -1,12 +1,11 @@
 #ifndef SPI_ADIS16260_H_
 #define SPI_ADIS16260_H_
+
 #include "adis16260_platform_data.h"
+#include <linux/iio/imu/adis.h>
 
 #define ADIS16260_STARTUP_DELAY	220 /* ms */
 
-#define ADIS16260_READ_REG(a)    a
-#define ADIS16260_WRITE_REG(a) ((a) | 0x80)
-
 #define ADIS16260_FLASH_CNT  0x00 /* Flash memory write count */
 #define ADIS16260_SUPPLY_OUT 0x02 /* Power supply measurement */
 #define ADIS16260_GYRO_OUT   0x04 /* X-axis gyroscope output */
@@ -34,8 +33,6 @@
 				   * convert to decimal = 16,265/16,260 */
 #define ADIS16260_SERIAL_NUM 0x58 /* Serial number */
 
-#define ADIS16260_OUTPUTS    5
-
 #define ADIS16260_ERROR_ACTIVE			(1<<14)
 #define ADIS16260_NEW_DATA			(1<<15)
 
@@ -60,13 +57,13 @@
 /* DIAG_STAT */
 #define ADIS16260_DIAG_STAT_ALARM2	(1<<9)
 #define ADIS16260_DIAG_STAT_ALARM1	(1<<8)
-#define ADIS16260_DIAG_STAT_FLASH_CHK	(1<<6)
-#define ADIS16260_DIAG_STAT_SELF_TEST	(1<<5)
-#define ADIS16260_DIAG_STAT_OVERFLOW	(1<<4)
-#define ADIS16260_DIAG_STAT_SPI_FAIL	(1<<3)
-#define ADIS16260_DIAG_STAT_FLASH_UPT	(1<<2)
-#define ADIS16260_DIAG_STAT_POWER_HIGH	(1<<1)
-#define ADIS16260_DIAG_STAT_POWER_LOW	(1<<0)
+#define ADIS16260_DIAG_STAT_FLASH_CHK_BIT	6
+#define ADIS16260_DIAG_STAT_SELF_TEST_BIT	5
+#define ADIS16260_DIAG_STAT_OVERFLOW_BIT	4
+#define ADIS16260_DIAG_STAT_SPI_FAIL_BIT	3
+#define ADIS16260_DIAG_STAT_FLASH_UPT_BIT	2
+#define ADIS16260_DIAG_STAT_POWER_HIGH_BIT	1
+#define ADIS16260_DIAG_STAT_POWER_LOW_BIT	0
 
 /* GLOB_CMD */
 #define ADIS16260_GLOB_CMD_SW_RESET	(1<<7)
@@ -75,82 +72,27 @@
 #define ADIS16260_GLOB_CMD_FAC_CALIB	(1<<1)
 #define ADIS16260_GLOB_CMD_AUTO_NULL	(1<<0)
 
-#define ADIS16260_MAX_TX 24
-#define ADIS16260_MAX_RX 24
-
 #define ADIS16260_SPI_SLOW	(u32)(300 * 1000)
 #define ADIS16260_SPI_BURST	(u32)(1000 * 1000)
 #define ADIS16260_SPI_FAST	(u32)(2000 * 1000)
 
 /**
  * struct adis16260_state - device instance specific data
- * @us:			actual spi_device
- * @trig:		data ready trigger registered with iio
- * @buf_lock:		mutex to protect tx and rx
  * @negate:		negate the scale parameter
- * @tx:			transmit buffer
- * @rx:			receive buffer
  **/
 struct adis16260_state {
-	struct spi_device	*us;
-	struct iio_trigger	*trig;
-	struct mutex		buf_lock;
-	unsigned		negate:1;
-	u8			tx[ADIS16260_MAX_TX] ____cacheline_aligned;
-	u8			rx[ADIS16260_MAX_RX];
+	unsigned	negate:1;
+	struct adis	adis;
 };
 
-int adis16260_set_irq(struct iio_dev *indio_dev, bool enable);
-
 /* At the moment triggers are only used for ring buffer
  * filling. This may change!
  */
 
-#define ADIS16260_SCAN_SUPPLY	0
-#define ADIS16260_SCAN_GYRO	1
+#define ADIS16260_SCAN_GYRO	0
+#define ADIS16260_SCAN_SUPPLY	1
 #define ADIS16260_SCAN_AUX_ADC	2
 #define ADIS16260_SCAN_TEMP	3
 #define ADIS16260_SCAN_ANGL	4
 
-#ifdef CONFIG_IIO_BUFFER
-void adis16260_remove_trigger(struct iio_dev *indio_dev);
-int adis16260_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16260_read_data_from_ring(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf);
-
-
-int adis16260_configure_ring(struct iio_dev *indio_dev);
-void adis16260_unconfigure_ring(struct iio_dev *indio_dev);
-
-#else /* CONFIG_IIO_BUFFER */
-
-static inline void adis16260_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16260_probe_trigger(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline ssize_t
-adis16260_read_data_from_ring(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	return 0;
-}
-
-static int adis16260_configure_ring(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline void adis16260_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-#endif /* CONFIG_IIO_BUFFER */
 #endif /* SPI_ADIS16260_H_ */
diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c
index aa964a2..6e80b8c 100644
--- a/drivers/staging/iio/gyro/adis16260_core.c
+++ b/drivers/staging/iio/gyro/adis16260_core.c
@@ -24,134 +24,13 @@
 
 #include "adis16260.h"
 
-#define DRIVER_NAME		"adis16260"
-
-static int adis16260_check_status(struct iio_dev *indio_dev);
-
-/**
- * adis16260_spi_write_reg_8() - write single byte to a register
- * @indio_dev: iio_dev for the device
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-static int adis16260_spi_write_reg_8(struct iio_dev *indio_dev,
-		u8 reg_address,
-		u8 val)
-{
-	int ret;
-	struct adis16260_state *st = iio_priv(indio_dev);
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16260_WRITE_REG(reg_address);
-	st->tx[1] = val;
-
-	ret = spi_write(st->us, st->tx, 2);
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/**
- * adis16260_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @indio_dev: iio_dev for the device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16260_spi_write_reg_16(struct iio_dev *indio_dev,
-		u8 lower_reg_address,
-		u16 value)
-{
-	int ret;
-	struct spi_message msg;
-	struct adis16260_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-			.delay_usecs = 20,
-		}, {
-			.tx_buf = st->tx + 2,
-			.bits_per_word = 8,
-			.len = 2,
-			.delay_usecs = 20,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16260_WRITE_REG(lower_reg_address);
-	st->tx[1] = value & 0xFF;
-	st->tx[2] = ADIS16260_WRITE_REG(lower_reg_address + 1);
-	st->tx[3] = (value >> 8) & 0xFF;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/**
- * adis16260_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @indio_dev: iio_dev for the device
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16260_spi_read_reg_16(struct iio_dev *indio_dev,
-		u8 lower_reg_address,
-		u16 *val)
-{
-	struct spi_message msg;
-	struct adis16260_state *st = iio_priv(indio_dev);
-	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-			.delay_usecs = 30,
-		}, {
-			.rx_buf = st->rx,
-			.bits_per_word = 8,
-			.len = 2,
-			.delay_usecs = 30,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16260_READ_REG(lower_reg_address);
-	st->tx[1] = 0;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
-	if (ret) {
-		dev_err(&st->us->dev,
-			"problem when reading 16 bit register 0x%02X",
-			lower_reg_address);
-		goto error_ret;
-	}
-	*val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
-}
-
 static ssize_t adis16260_read_frequency_available(struct device *dev,
 						  struct device_attribute *attr,
 						  char *buf)
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct adis16260_state *st = iio_priv(indio_dev);
-	if (spi_get_device_id(st->us)->driver_data)
+	if (spi_get_device_id(st->adis.spi)->driver_data)
 		return sprintf(buf, "%s\n", "0.129 ~ 256");
 	else
 		return sprintf(buf, "%s\n", "256 2048");
@@ -166,13 +45,11 @@ static ssize_t adis16260_read_frequency(struct device *dev,
 	int ret, len = 0;
 	u16 t;
 	int sps;
-	ret = adis16260_spi_read_reg_16(indio_dev,
-			ADIS16260_SMPL_PRD,
-			&t);
+	ret = adis_read_reg_16(&st->adis, ADIS16260_SMPL_PRD, &t);
 	if (ret)
 		return ret;
 
-	if (spi_get_device_id(st->us)->driver_data) /* If an adis16251 */
+	if (spi_get_device_id(st->adis.spi)->driver_data) /* If an adis16251 */
 		sps =  (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 8 : 256;
 	else
 		sps =  (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 66 : 2048;
@@ -199,7 +76,7 @@ static ssize_t adis16260_write_frequency(struct device *dev,
 		return -EINVAL;
 
 	mutex_lock(&indio_dev->mlock);
-	if (spi_get_device_id(st->us)) {
+	if (spi_get_device_id(st->adis.spi)->driver_data) {
 		t = (256 / val);
 		if (t > 0)
 			t--;
@@ -211,10 +88,10 @@ static ssize_t adis16260_write_frequency(struct device *dev,
 		t &= ADIS16260_SMPL_PRD_DIV_MASK;
 	}
 	if ((t & ADIS16260_SMPL_PRD_DIV_MASK) >= 0x0A)
-		st->us->max_speed_hz = ADIS16260_SPI_SLOW;
+		st->adis.spi->max_speed_hz = ADIS16260_SPI_SLOW;
 	else
-		st->us->max_speed_hz = ADIS16260_SPI_FAST;
-	ret = adis16260_spi_write_reg_8(indio_dev,
+		st->adis.spi->max_speed_hz = ADIS16260_SPI_FAST;
+	ret = adis_write_reg_8(&st->adis,
 			ADIS16260_SMPL_PRD,
 			t);
 
@@ -223,140 +100,20 @@ static ssize_t adis16260_write_frequency(struct device *dev,
 	return ret ? ret : len;
 }
 
-static int adis16260_reset(struct iio_dev *indio_dev)
-{
-	int ret;
-	ret = adis16260_spi_write_reg_8(indio_dev,
-			ADIS16260_GLOB_CMD,
-			ADIS16260_GLOB_CMD_SW_RESET);
-	if (ret)
-		dev_err(&indio_dev->dev, "problem resetting device");
-
-	return ret;
-}
-
-int adis16260_set_irq(struct iio_dev *indio_dev, bool enable)
-{
-	int ret;
-	u16 msc;
-	ret = adis16260_spi_read_reg_16(indio_dev, ADIS16260_MSC_CTRL, &msc);
-	if (ret)
-		goto error_ret;
-
-	msc |= ADIS16260_MSC_CTRL_DATA_RDY_POL_HIGH;
-	if (enable)
-		msc |= ADIS16260_MSC_CTRL_DATA_RDY_EN;
-	else
-		msc &= ~ADIS16260_MSC_CTRL_DATA_RDY_EN;
-
-	ret = adis16260_spi_write_reg_16(indio_dev, ADIS16260_MSC_CTRL, msc);
-	if (ret)
-		goto error_ret;
-
-error_ret:
-	return ret;
-}
-
 /* Power down the device */
 static int adis16260_stop_device(struct iio_dev *indio_dev)
 {
+	struct adis16260_state *st = iio_priv(indio_dev);
 	int ret;
 	u16 val = ADIS16260_SLP_CNT_POWER_OFF;
 
-	ret = adis16260_spi_write_reg_16(indio_dev, ADIS16260_SLP_CNT, val);
+	ret = adis_write_reg_16(&st->adis, ADIS16260_SLP_CNT, val);
 	if (ret)
 		dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
 
 	return ret;
 }
 
-static int adis16260_self_test(struct iio_dev *indio_dev)
-{
-	int ret;
-	ret = adis16260_spi_write_reg_16(indio_dev,
-			ADIS16260_MSC_CTRL,
-			ADIS16260_MSC_CTRL_MEM_TEST);
-	if (ret) {
-		dev_err(&indio_dev->dev, "problem starting self test");
-		goto err_ret;
-	}
-
-	adis16260_check_status(indio_dev);
-
-err_ret:
-	return ret;
-}
-
-static int adis16260_check_status(struct iio_dev *indio_dev)
-{
-	u16 status;
-	int ret;
-	struct device *dev = &indio_dev->dev;
-
-	ret = adis16260_spi_read_reg_16(indio_dev,
-					ADIS16260_DIAG_STAT,
-					&status);
-
-	if (ret < 0) {
-		dev_err(dev, "Reading status failed\n");
-		goto error_ret;
-	}
-	ret = status & 0x7F;
-	if (status & ADIS16260_DIAG_STAT_FLASH_CHK)
-		dev_err(dev, "Flash checksum error\n");
-	if (status & ADIS16260_DIAG_STAT_SELF_TEST)
-		dev_err(dev, "Self test error\n");
-	if (status & ADIS16260_DIAG_STAT_OVERFLOW)
-		dev_err(dev, "Sensor overrange\n");
-	if (status & ADIS16260_DIAG_STAT_SPI_FAIL)
-		dev_err(dev, "SPI failure\n");
-	if (status & ADIS16260_DIAG_STAT_FLASH_UPT)
-		dev_err(dev, "Flash update failed\n");
-	if (status & ADIS16260_DIAG_STAT_POWER_HIGH)
-		dev_err(dev, "Power supply above 5.25V\n");
-	if (status & ADIS16260_DIAG_STAT_POWER_LOW)
-		dev_err(dev, "Power supply below 4.75V\n");
-
-error_ret:
-	return ret;
-}
-
-static int adis16260_initial_setup(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct device *dev = &indio_dev->dev;
-
-	/* Disable IRQ */
-	ret = adis16260_set_irq(indio_dev, false);
-	if (ret) {
-		dev_err(dev, "disable irq failed");
-		goto err_ret;
-	}
-
-	/* Do self test */
-	ret = adis16260_self_test(indio_dev);
-	if (ret) {
-		dev_err(dev, "self test failure");
-		goto err_ret;
-	}
-
-	/* Read status register to check the result */
-	ret = adis16260_check_status(indio_dev);
-	if (ret) {
-		adis16260_reset(indio_dev);
-		dev_err(dev, "device not playing ball -> reset");
-		msleep(ADIS16260_STARTUP_DELAY);
-		ret = adis16260_check_status(indio_dev);
-		if (ret) {
-			dev_err(dev, "giving up");
-			goto err_ret;
-		}
-	}
-
-err_ret:
-	return ret;
-}
-
 static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
 		adis16260_read_frequency,
 		adis16260_write_frequency);
@@ -364,100 +121,26 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
 static IIO_DEVICE_ATTR(sampling_frequency_available,
 		       S_IRUGO, adis16260_read_frequency_available, NULL, 0);
 
-enum adis16260_channel {
-	gyro,
-	temp,
-	in_supply,
-	in_aux,
-	angle,
-};
 #define ADIS16260_GYRO_CHANNEL_SET(axis, mod)				\
-	struct iio_chan_spec adis16260_channels_##axis[] = {		\
-		{							\
-			.type = IIO_ANGL_VEL,				\
-			.modified = 1,					\
-			.channel2 = mod,				\
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |	\
-			IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |		\
-			IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |		\
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT,		\
-			.address = gyro,				\
-			.scan_index = ADIS16260_SCAN_GYRO,		\
-			.scan_type = {					\
-				.sign = 's',				\
-				.realbits = 14,				\
-				.storagebits = 16,			\
-			},						\
-		}, {							\
-			.type = IIO_ANGL,				\
-			.modified = 1,					\
-			.channel2 = mod,				\
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,	\
-			.address = angle,				\
-			.scan_index = ADIS16260_SCAN_ANGL,		\
-			.scan_type = {					\
-				.sign = 'u',				\
-				.realbits = 14,				\
-				.storagebits = 16,			\
-			},						\
-		}, {							\
-			.type = IIO_TEMP,				\
-			.indexed = 1,					\
-			.channel = 0,					\
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |	\
-			IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |		\
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT,		\
-			.address = temp,				\
-			.scan_index = ADIS16260_SCAN_TEMP,		\
-			.scan_type = {					\
-				.sign = 'u',				\
-				.realbits = 12,				\
-				.storagebits = 16,			\
-			},						\
-		}, {							\
-			.type = IIO_VOLTAGE,				\
-			.indexed = 1,					\
-			.channel = 0,					\
-			.extend_name = "supply",			\
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |	\
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT,		\
-			.address = in_supply,				\
-			.scan_index = ADIS16260_SCAN_SUPPLY,		\
-			.scan_type = {					\
-				.sign = 'u',				\
-				.realbits = 12,				\
-				.storagebits = 16,			\
-			},						\
-		}, {							\
-			.type = IIO_VOLTAGE,				\
-			.indexed = 1,					\
-			.channel = 1,					\
-			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |	\
-			IIO_CHAN_INFO_SCALE_SEPARATE_BIT,		\
-			.address = in_aux,				\
-			.scan_index = ADIS16260_SCAN_AUX_ADC,		\
-			.scan_type = {					\
-				.sign = 'u',				\
-				.realbits = 12,				\
-				.storagebits = 16,			\
-			},						\
-		},							\
-		IIO_CHAN_SOFT_TIMESTAMP(5),				\
-	}
+struct iio_chan_spec adis16260_channels_##axis[] = {		\
+	ADIS_GYRO_CHAN(mod, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO, \
+		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \
+		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, 14), \
+	ADIS_INCLI_CHAN(mod, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0, 14), \
+	ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP, 12), \
+	ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY, 12), \
+	ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC, 12), \
+	IIO_CHAN_SOFT_TIMESTAMP(5),				\
+}
+
+static const ADIS16260_GYRO_CHANNEL_SET(x, X);
+static const ADIS16260_GYRO_CHANNEL_SET(y, Y);
+static const ADIS16260_GYRO_CHANNEL_SET(z, Z);
 
-static const ADIS16260_GYRO_CHANNEL_SET(x, IIO_MOD_X);
-static const ADIS16260_GYRO_CHANNEL_SET(y, IIO_MOD_Y);
-static const ADIS16260_GYRO_CHANNEL_SET(z, IIO_MOD_Z);
-
-static const u8 adis16260_addresses[5][3] = {
-	[gyro] = { ADIS16260_GYRO_OUT,
-		   ADIS16260_GYRO_OFF,
-		   ADIS16260_GYRO_SCALE },
-	[angle] = { ADIS16260_ANGL_OUT },
-	[in_supply] = { ADIS16260_SUPPLY_OUT },
-	[in_aux] = { ADIS16260_AUX_ADC },
-	[temp] = { ADIS16260_TEMP_OUT },
+static const u8 adis16260_addresses[][2] = {
+	[ADIS16260_SCAN_GYRO] = { ADIS16260_GYRO_OFF, ADIS16260_GYRO_SCALE },
 };
+
 static int adis16260_read_raw(struct iio_dev *indio_dev,
 			      struct iio_chan_spec const *chan,
 			      int *val, int *val2,
@@ -471,34 +154,13 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
-		mutex_lock(&indio_dev->mlock);
-		addr = adis16260_addresses[chan->address][0];
-		ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16);
-		if (ret) {
-			mutex_unlock(&indio_dev->mlock);
-			return ret;
-		}
-
-		if (val16 & ADIS16260_ERROR_ACTIVE) {
-			ret = adis16260_check_status(indio_dev);
-			if (ret) {
-				mutex_unlock(&indio_dev->mlock);
-				return ret;
-			}
-		}
-		val16 = val16 & ((1 << chan->scan_type.realbits) - 1);
-		if (chan->scan_type.sign == 's')
-			val16 = (s16)(val16 <<
-				      (16 - chan->scan_type.realbits)) >>
-				(16 - chan->scan_type.realbits);
-		*val = val16;
-		mutex_unlock(&indio_dev->mlock);
-		return IIO_VAL_INT;
+		return adis_single_conversion(indio_dev, chan,
+				ADIS16260_ERROR_ACTIVE, val);
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->type) {
 		case IIO_ANGL_VEL:
 			*val = 0;
-			if (spi_get_device_id(st->us)->driver_data) {
+			if (spi_get_device_id(st->adis.spi)->driver_data) {
 				/* 0.01832 degree / sec */
 				*val2 = IIO_DEGREE_TO_RAD(18320);
 			} else {
@@ -533,10 +195,10 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
 			break;
 		default:
 			return -EINVAL;
-		};
+		}
 		mutex_lock(&indio_dev->mlock);
-		addr = adis16260_addresses[chan->address][1];
-		ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16);
+		addr = adis16260_addresses[chan->scan_index][0];
+		ret = adis_read_reg_16(&st->adis, addr, &val16);
 		if (ret) {
 			mutex_unlock(&indio_dev->mlock);
 			return ret;
@@ -553,10 +215,10 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
 			break;
 		default:
 			return -EINVAL;
-		};
+		}
 		mutex_lock(&indio_dev->mlock);
-		addr = adis16260_addresses[chan->address][2];
-		ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16);
+		addr = adis16260_addresses[chan->scan_index][1];
+		ret = adis_read_reg_16(&st->adis, addr, &val16);
 		if (ret) {
 			mutex_unlock(&indio_dev->mlock);
 			return ret;
@@ -574,18 +236,19 @@ static int adis16260_write_raw(struct iio_dev *indio_dev,
 			       int val2,
 			       long mask)
 {
+	struct adis16260_state *st = iio_priv(indio_dev);
 	int bits = 12;
 	s16 val16;
 	u8 addr;
 	switch (mask) {
 	case IIO_CHAN_INFO_CALIBBIAS:
 		val16 = val & ((1 << bits) - 1);
-		addr = adis16260_addresses[chan->address][1];
-		return adis16260_spi_write_reg_16(indio_dev, addr, val16);
+		addr = adis16260_addresses[chan->scan_index][0];
+		return adis_write_reg_16(&st->adis, addr, val16);
 	case IIO_CHAN_INFO_CALIBSCALE:
 		val16 = val & ((1 << bits) - 1);
-		addr = adis16260_addresses[chan->address][2];
-		return adis16260_spi_write_reg_16(indio_dev, addr, val16);
+		addr = adis16260_addresses[chan->scan_index][1];
+		return adis_write_reg_16(&st->adis, addr, val16);
 	}
 	return -EINVAL;
 }
@@ -604,10 +267,41 @@ static const struct iio_info adis16260_info = {
 	.attrs = &adis16260_attribute_group,
 	.read_raw = &adis16260_read_raw,
 	.write_raw = &adis16260_write_raw,
+	.update_scan_mode = adis_update_scan_mode,
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit adis16260_probe(struct spi_device *spi)
+static const char * const adis1620_status_error_msgs[] = {
+	[ADIS16260_DIAG_STAT_FLASH_CHK_BIT] = "Flash checksum error",
+	[ADIS16260_DIAG_STAT_SELF_TEST_BIT] = "Self test error",
+	[ADIS16260_DIAG_STAT_OVERFLOW_BIT] = "Sensor overrange",
+	[ADIS16260_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
+	[ADIS16260_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
+	[ADIS16260_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 5.25",
+	[ADIS16260_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 4.75",
+};
+
+static const struct adis_data adis16260_data = {
+	.write_delay = 30,
+	.read_delay = 30,
+	.msc_ctrl_reg = ADIS16260_MSC_CTRL,
+	.glob_cmd_reg = ADIS16260_GLOB_CMD,
+	.diag_stat_reg = ADIS16260_DIAG_STAT,
+
+	.self_test_mask = ADIS16260_MSC_CTRL_MEM_TEST,
+	.startup_delay = ADIS16260_STARTUP_DELAY,
+
+	.status_error_msgs = adis1620_status_error_msgs,
+	.status_error_mask = BIT(ADIS16260_DIAG_STAT_FLASH_CHK_BIT) |
+		BIT(ADIS16260_DIAG_STAT_SELF_TEST_BIT) |
+		BIT(ADIS16260_DIAG_STAT_OVERFLOW_BIT) |
+		BIT(ADIS16260_DIAG_STAT_SPI_FAIL_BIT) |
+		BIT(ADIS16260_DIAG_STAT_FLASH_UPT_BIT) |
+		BIT(ADIS16260_DIAG_STAT_POWER_HIGH_BIT) |
+		BIT(ADIS16260_DIAG_STAT_POWER_LOW_BIT),
+};
+
+static int adis16260_probe(struct spi_device *spi)
 {
 	int ret;
 	struct adis16260_platform_data *pd = spi->dev.platform_data;
@@ -626,10 +320,7 @@ static int __devinit adis16260_probe(struct spi_device *spi)
 	/* this is only used for removal purposes */
 	spi_set_drvdata(spi, indio_dev);
 
-	st->us = spi;
-	mutex_init(&st->buf_lock);
-
-	indio_dev->name = spi_get_device_id(st->us)->name;
+	indio_dev->name = spi_get_device_id(spi)->name;
 	indio_dev->dev.parent = &spi->dev;
 	indio_dev->info = &adis16260_info;
 	indio_dev->num_channels
@@ -653,17 +344,14 @@ static int __devinit adis16260_probe(struct spi_device *spi)
 	indio_dev->num_channels = ARRAY_SIZE(adis16260_channels_x);
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = adis16260_configure_ring(indio_dev);
+	ret = adis_init(&st->adis, indio_dev, spi, &adis16260_data);
+	if (ret)
+		goto error_free_dev;
+
+	ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL);
 	if (ret)
 		goto error_free_dev;
 
-	ret = iio_buffer_register(indio_dev,
-				  indio_dev->channels,
-				  ARRAY_SIZE(adis16260_channels_x));
-	if (ret) {
-		printk(KERN_ERR "failed to initialize the ring\n");
-		goto error_unreg_ring_funcs;
-	}
 	if (indio_dev->buffer) {
 		/* Set default scan mode */
 		iio_scan_mask_set(indio_dev, indio_dev->buffer,
@@ -677,43 +365,33 @@ static int __devinit adis16260_probe(struct spi_device *spi)
 		iio_scan_mask_set(indio_dev, indio_dev->buffer,
 				  ADIS16260_SCAN_ANGL);
 	}
-	if (spi->irq) {
-		ret = adis16260_probe_trigger(indio_dev);
-		if (ret)
-			goto error_uninitialize_ring;
-	}
 
 	/* Get the device into a sane initial state */
-	ret = adis16260_initial_setup(indio_dev);
+	ret = adis_initial_startup(&st->adis);
 	if (ret)
-		goto error_remove_trigger;
+		goto error_cleanup_buffer_trigger;
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_remove_trigger;
+		goto error_cleanup_buffer_trigger;
 
 	return 0;
 
-error_remove_trigger:
-	adis16260_remove_trigger(indio_dev);
-error_uninitialize_ring:
-	iio_buffer_unregister(indio_dev);
-error_unreg_ring_funcs:
-	adis16260_unconfigure_ring(indio_dev);
+error_cleanup_buffer_trigger:
+	adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
 error_free_dev:
 	iio_device_free(indio_dev);
 error_ret:
 	return ret;
 }
 
-static int __devexit adis16260_remove(struct spi_device *spi)
+static int adis16260_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct adis16260_state *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
 	adis16260_stop_device(indio_dev);
-	adis16260_remove_trigger(indio_dev);
-	iio_buffer_unregister(indio_dev);
-	adis16260_unconfigure_ring(indio_dev);
+	adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
 	iio_device_free(indio_dev);
 
 	return 0;
@@ -739,7 +417,7 @@ static struct spi_driver adis16260_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = adis16260_probe,
-	.remove = __devexit_p(adis16260_remove),
+	.remove = adis16260_remove,
 	.id_table = adis16260_id,
 };
 module_spi_driver(adis16260_driver);
diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c
deleted file mode 100644
index e294cb4..0000000
--- a/drivers/staging/iio/gyro/adis16260_ring.c
+++ /dev/null
@@ -1,136 +0,0 @@
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-
-#include <linux/iio/iio.h>
-#include "../ring_sw.h"
-#include <linux/iio/trigger_consumer.h>
-#include "adis16260.h"
-
-/**
- * adis16260_read_ring_data() read data registers which will be placed into ring
- * @indio_dev: the IIO device
- * @rx: somewhere to pass back the value read
- **/
-static int adis16260_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
-{
-	struct spi_message msg;
-	struct adis16260_state *st = iio_priv(indio_dev);
-	struct spi_transfer xfers[ADIS16260_OUTPUTS + 1];
-	int ret;
-	int i;
-
-	mutex_lock(&st->buf_lock);
-
-	spi_message_init(&msg);
-
-	memset(xfers, 0, sizeof(xfers));
-	for (i = 0; i <= ADIS16260_OUTPUTS; i++) {
-		xfers[i].bits_per_word = 8;
-		xfers[i].cs_change = 1;
-		xfers[i].len = 2;
-		xfers[i].delay_usecs = 30;
-		xfers[i].tx_buf = st->tx + 2 * i;
-		if (i < 2) /* SUPPLY_OUT:0x02 GYRO_OUT:0x04 */
-			st->tx[2 * i]
-				= ADIS16260_READ_REG(ADIS16260_SUPPLY_OUT
-						+ 2 * i);
-		else /* 0x06 to 0x09 is reserved */
-			st->tx[2 * i]
-				= ADIS16260_READ_REG(ADIS16260_SUPPLY_OUT
-						+ 2 * i + 4);
-		st->tx[2 * i + 1] = 0;
-		if (i >= 1)
-			xfers[i].rx_buf = rx + 2 * (i - 1);
-		spi_message_add_tail(&xfers[i], &msg);
-	}
-
-	ret = spi_sync(st->us, &msg);
-	if (ret)
-		dev_err(&st->us->dev, "problem when burst reading");
-
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-static irqreturn_t adis16260_trigger_handler(int irq, void *p)
-{
-	struct iio_poll_func *pf = p;
-	struct iio_dev *indio_dev = pf->indio_dev;
-	struct adis16260_state *st = iio_priv(indio_dev);
-	int i = 0;
-	s16 *data;
-
-	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(&st->us->dev, "memory alloc failed in ring bh");
-		goto done;
-	}
-
-	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
-	    adis16260_read_ring_data(indio_dev, st->rx) >= 0)
-		for (; i < bitmap_weight(indio_dev->active_scan_mask,
-					 indio_dev->masklength); i++)
-			data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
-
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp)
-		*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-
-	iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
-
-	kfree(data);
-done:
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-void adis16260_unconfigure_ring(struct iio_dev *indio_dev)
-{
-	iio_dealloc_pollfunc(indio_dev->pollfunc);
-	iio_sw_rb_free(indio_dev->buffer);
-}
-
-static const struct iio_buffer_setup_ops adis16260_ring_setup_ops = {
-	.preenable = &iio_sw_buffer_preenable,
-	.postenable = &iio_triggered_buffer_postenable,
-	.predisable = &iio_triggered_buffer_predisable,
-};
-
-int adis16260_configure_ring(struct iio_dev *indio_dev)
-{
-	int ret = 0;
-	struct iio_buffer *ring;
-
-	ring = iio_sw_rb_allocate(indio_dev);
-	if (!ring) {
-		ret = -ENOMEM;
-		return ret;
-	}
-	indio_dev->buffer = ring;
-	ring->scan_timestamp = true;
-	indio_dev->setup_ops = &adis16260_ring_setup_ops;
-
-	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
-						 &adis16260_trigger_handler,
-						 IRQF_ONESHOT,
-						 indio_dev,
-						 "adis16260_consumer%d",
-						 indio_dev->id);
-	if (indio_dev->pollfunc == NULL) {
-		ret = -ENOMEM;
-		goto error_iio_sw_rb_free;
-	}
-
-	indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
-	return 0;
-
-error_iio_sw_rb_free:
-	iio_sw_rb_free(indio_dev->buffer);
-	return ret;
-}
diff --git a/drivers/staging/iio/gyro/adis16260_trigger.c b/drivers/staging/iio/gyro/adis16260_trigger.c
deleted file mode 100644
index 034559e..0000000
--- a/drivers/staging/iio/gyro/adis16260_trigger.c
+++ /dev/null
@@ -1,75 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/export.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger.h>
-#include "adis16260.h"
-
-/**
- * adis16260_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16260_data_rdy_trigger_set_state(struct iio_trigger *trig,
-						bool state)
-{
-	struct iio_dev *indio_dev = trig->private_data;
-
-	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	return adis16260_set_irq(indio_dev, state);
-}
-
-static const struct iio_trigger_ops adis16260_trigger_ops = {
-	.owner = THIS_MODULE,
-	.set_trigger_state = &adis16260_data_rdy_trigger_set_state,
-};
-
-int adis16260_probe_trigger(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct adis16260_state *st = iio_priv(indio_dev);
-
-	st->trig = iio_trigger_alloc("%s-dev%d",
-					spi_get_device_id(st->us)->name,
-					indio_dev->id);
-	if (st->trig == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-
-	ret = request_irq(st->us->irq,
-			  &iio_trigger_generic_data_rdy_poll,
-			  IRQF_TRIGGER_RISING,
-			  "adis16260",
-			  st->trig);
-	if (ret)
-		goto error_free_trig;
-
-	st->trig->dev.parent = &st->us->dev;
-	st->trig->ops = &adis16260_trigger_ops;
-	st->trig->private_data = indio_dev;
-	ret = iio_trigger_register(st->trig);
-
-	/* select default trigger */
-	indio_dev->trig = st->trig;
-	if (ret)
-		goto error_free_irq;
-
-	return 0;
-
-error_free_irq:
-	free_irq(st->us->irq, st->trig);
-error_free_trig:
-	iio_trigger_free(st->trig);
-error_ret:
-	return ret;
-}
-
-void adis16260_remove_trigger(struct iio_dev *indio_dev)
-{
-	struct adis16260_state *st = iio_priv(indio_dev);
-
-	iio_trigger_unregister(st->trig);
-	free_irq(st->us->irq, st->trig);
-	iio_trigger_free(st->trig);
-}
diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c
index d93527d..f0ce81d 100644
--- a/drivers/staging/iio/gyro/adxrs450_core.c
+++ b/drivers/staging/iio/gyro/adxrs450_core.c
@@ -365,7 +365,7 @@ static const struct iio_info adxrs450_info = {
 	.write_raw = &adxrs450_write_raw,
 };
 
-static int __devinit adxrs450_probe(struct spi_device *spi)
+static int adxrs450_probe(struct spi_device *spi)
 {
 	int ret;
 	struct adxrs450_state *st;
@@ -409,7 +409,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit adxrs450_remove(struct spi_device *spi)
+static int adxrs450_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
 	iio_device_free(spi_get_drvdata(spi));
@@ -430,7 +430,7 @@ static struct spi_driver adxrs450_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = adxrs450_probe,
-	.remove = __devexit_p(adxrs450_remove),
+	.remove = adxrs450_remove,
 	.id_table	= adxrs450_id,
 };
 module_spi_driver(adxrs450_driver);
diff --git a/drivers/staging/iio/iio_dummy_evgen.c b/drivers/staging/iio/iio_dummy_evgen.c
index 74e24e8..132d278 100644
--- a/drivers/staging/iio/iio_dummy_evgen.c
+++ b/drivers/staging/iio/iio_dummy_evgen.c
@@ -108,7 +108,7 @@ int iio_dummy_evgen_get_irq(void)
 
 	mutex_lock(&iio_evgen->lock);
 	for (i = 0; i < IIO_EVENTGEN_NO; i++)
-		if (iio_evgen->inuse[i] == false) {
+		if (!iio_evgen->inuse[i]) {
 			ret = iio_evgen->base + i;
 			iio_evgen->inuse[i] = true;
 			break;
diff --git a/drivers/staging/iio/iio_hwmon.c b/drivers/staging/iio/iio_hwmon.c
index 5d49122..c7a5f97 100644
--- a/drivers/staging/iio/iio_hwmon.c
+++ b/drivers/staging/iio/iio_hwmon.c
@@ -69,7 +69,7 @@ static void iio_hwmon_free_attrs(struct iio_hwmon_state *st)
 		}
 }
 
-static int __devinit iio_hwmon_probe(struct platform_device *pdev)
+static int iio_hwmon_probe(struct platform_device *pdev)
 {
 	struct iio_hwmon_state *st;
 	struct sensor_device_attribute *a;
@@ -170,7 +170,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit iio_hwmon_remove(struct platform_device *pdev)
+static int iio_hwmon_remove(struct platform_device *pdev)
 {
 	struct iio_hwmon_state *st = platform_get_drvdata(pdev);
 
@@ -189,7 +189,7 @@ static struct platform_driver __refdata iio_hwmon_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = iio_hwmon_probe,
-	.remove = __devexit_p(iio_hwmon_remove),
+	.remove = iio_hwmon_remove,
 };
 
 module_platform_driver(iio_hwmon_driver);
diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c
index dc6c728..a865adf 100644
--- a/drivers/staging/iio/iio_simple_dummy.c
+++ b/drivers/staging/iio/iio_simple_dummy.c
@@ -378,7 +378,7 @@ static int iio_dummy_init_device(struct iio_dev *indio_dev)
  *                      const struct i2c_device_id *id)
  * SPI: iio_dummy_probe(struct spi_device *spi)
  */
-static int __devinit iio_dummy_probe(int index)
+static int iio_dummy_probe(int index)
 {
 	int ret;
 	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 697d970..dee16f0 100644
--- a/drivers/staging/iio/iio_simple_dummy_buffer.c
+++ b/drivers/staging/iio/iio_simple_dummy_buffer.c
@@ -46,7 +46,6 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
-	struct iio_buffer *buffer = indio_dev->buffer;
 	int len = 0;
 	u16 *data;
 
@@ -76,7 +75,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
 		     i < bitmap_weight(indio_dev->active_scan_mask,
 				       indio_dev->masklength);
 		     i++, j++) {
-			j = find_next_bit(buffer->scan_mask,
+			j = find_next_bit(indio_dev->active_scan_mask,
 					  indio_dev->masklength, j);
 			/* random access read from the 'device' */
 			data[i] = fakedata[j];
@@ -87,7 +86,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
 	if (indio_dev->scan_timestamp)
 		*(s64 *)((u8 *)data + ALIGN(len, sizeof(s64)))
 			= iio_get_time_ns();
-	iio_push_to_buffer(buffer, (u8 *)data);
+	iio_push_to_buffers(indio_dev, (u8 *)data);
 
 	kfree(data);
 
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index de21d47..779243d 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -647,7 +647,6 @@ static void ad5933_work(struct work_struct *work)
 	struct ad5933_state *st = container_of(work,
 		struct ad5933_state, work.work);
 	struct iio_dev *indio_dev = i2c_get_clientdata(st->client);
-	struct iio_buffer *ring = indio_dev->buffer;
 	signed short buf[2];
 	unsigned char status;
 
@@ -677,8 +676,7 @@ static void ad5933_work(struct work_struct *work)
 		} else {
 			buf[0] = be16_to_cpu(buf[0]);
 		}
-		/* save datum to the ring */
-		iio_push_to_buffer(ring, (u8 *)buf);
+		iio_push_to_buffers(indio_dev, (u8 *)buf);
 	} else {
 		/* no data available - try again later */
 		schedule_delayed_work(&st->work, st->poll_time_jiffies);
@@ -699,7 +697,7 @@ static void ad5933_work(struct work_struct *work)
 	mutex_unlock(&indio_dev->mlock);
 }
 
-static int __devinit ad5933_probe(struct i2c_client *client,
+static int ad5933_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
 	int ret, voltage_uv = 0;
@@ -789,7 +787,7 @@ error_put_reg:
 	return ret;
 }
 
-static __devexit int ad5933_remove(struct i2c_client *client)
+static int ad5933_remove(struct i2c_client *client)
 {
 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 	struct ad5933_state *st = iio_priv(indio_dev);
@@ -819,7 +817,7 @@ static struct i2c_driver ad5933_driver = {
 		.name = "ad5933",
 	},
 	.probe = ad5933_probe,
-	.remove = __devexit_p(ad5933_remove),
+	.remove = ad5933_remove,
 	.id_table = ad5933_id,
 };
 module_i2c_driver(ad5933_driver);
diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h
index 77c601d..7a105e9 100644
--- a/drivers/staging/iio/imu/adis16400.h
+++ b/drivers/staging/iio/imu/adis16400.h
@@ -123,6 +123,9 @@
 /* SLP_CNT */
 #define ADIS16400_SLP_CNT_POWER_OFF	(1<<8)
 
+#define ADIS16334_RATE_DIV_SHIFT 8
+#define ADIS16334_RATE_INT_CLK BIT(0)
+
 #define ADIS16400_MAX_TX 24
 #define ADIS16400_MAX_RX 24
 
@@ -130,18 +133,21 @@
 #define ADIS16400_SPI_BURST	(u32)(1000 * 1000)
 #define ADIS16400_SPI_FAST	(u32)(2000 * 1000)
 
-#define ADIS16400_HAS_PROD_ID 1
-#define ADIS16400_NO_BURST 2
+#define ADIS16400_HAS_PROD_ID		BIT(0)
+#define ADIS16400_NO_BURST		BIT(1)
+#define ADIS16400_HAS_SLOW_MODE		BIT(2)
+
 struct adis16400_chip_info {
 	const struct iio_chan_spec *channels;
 	const int num_channels;
-	const int product_id;
 	const long flags;
 	unsigned int gyro_scale_micro;
 	unsigned int accel_scale_micro;
 	int temp_scale_nano;
 	int temp_offset;
 	unsigned long default_scan_mask;
+	int (*set_freq)(struct iio_dev *indio_dev, unsigned int freq);
+	int (*get_freq)(struct iio_dev *indio_dev);
 };
 
 /**
diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
index 3144a7b..9c8f5ab 100644
--- a/drivers/staging/iio/imu/adis16400_core.c
+++ b/drivers/staging/iio/imu/adis16400_core.c
@@ -38,7 +38,6 @@ enum adis16400_chip_variant {
 	ADIS16360,
 	ADIS16362,
 	ADIS16364,
-	ADIS16365,
 	ADIS16400,
 };
 
@@ -161,10 +160,39 @@ error_ret:
 	return ret;
 }
 
-static int adis16400_get_freq(struct iio_dev *indio_dev)
+static int adis16334_get_freq(struct iio_dev *indio_dev)
 {
+	int ret;
 	u16 t;
+
+	ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_SMPL_PRD, &t);
+	if (ret < 0)
+		return ret;
+
+	t >>= ADIS16334_RATE_DIV_SHIFT;
+
+	return (8192 >> t) / 10;
+}
+
+static int adis16334_set_freq(struct iio_dev *indio_dev, unsigned int freq)
+{
+	unsigned int t;
+
+	t = ilog2(8192 / (freq * 10));
+
+	if (t > 0x31)
+		t = 0x31;
+
+	t <<= ADIS16334_RATE_DIV_SHIFT;
+	t |= ADIS16334_RATE_INT_CLK;
+
+	return adis16400_spi_write_reg_16(indio_dev, ADIS16400_SMPL_PRD, t);
+}
+
+static int adis16400_get_freq(struct iio_dev *indio_dev)
+{
 	int sps, ret;
+	u16 t;
 
 	ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_SMPL_PRD, &t);
 	if (ret < 0)
@@ -175,13 +203,33 @@ static int adis16400_get_freq(struct iio_dev *indio_dev)
 	return sps;
 }
 
+static int adis16400_set_freq(struct iio_dev *indio_dev, unsigned int freq)
+{
+	struct adis16400_state *st = iio_priv(indio_dev);
+	unsigned int t;
+
+	t = 1638 / freq;
+	if (t > 0)
+		t--;
+	t &= ADIS16400_SMPL_PRD_DIV_MASK;
+	if ((t & ADIS16400_SMPL_PRD_DIV_MASK) >= 0x0A)
+		st->us->max_speed_hz = ADIS16400_SPI_SLOW;
+	else
+		st->us->max_speed_hz = ADIS16400_SPI_FAST;
+
+	return adis16400_spi_write_reg_8(indio_dev,
+			ADIS16400_SMPL_PRD, t);
+}
+
 static ssize_t adis16400_read_frequency(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct adis16400_state *st = iio_priv(indio_dev);
 	int ret, len = 0;
-	ret = adis16400_get_freq(indio_dev);
+
+	ret = st->variant->get_freq(indio_dev);
 	if (ret < 0)
 		return ret;
 	len = sprintf(buf, "%d SPS\n", ret);
@@ -229,7 +277,6 @@ static ssize_t adis16400_write_frequency(struct device *dev,
 	struct adis16400_state *st = iio_priv(indio_dev);
 	long val;
 	int ret;
-	u8 t;
 
 	ret = strict_strtol(buf, 10, &val);
 	if (ret)
@@ -239,18 +286,7 @@ static ssize_t adis16400_write_frequency(struct device *dev,
 
 	mutex_lock(&indio_dev->mlock);
 
-	t = (1638 / val);
-	if (t > 0)
-		t--;
-	t &= ADIS16400_SMPL_PRD_DIV_MASK;
-	if ((t & ADIS16400_SMPL_PRD_DIV_MASK) >= 0x0A)
-		st->us->max_speed_hz = ADIS16400_SPI_SLOW;
-	else
-		st->us->max_speed_hz = ADIS16400_SPI_FAST;
-
-	ret = adis16400_spi_write_reg_8(indio_dev,
-			ADIS16400_SMPL_PRD,
-			t);
+	st->variant->set_freq(indio_dev, val);
 
 	/* Also update the filter */
 	mutex_unlock(&indio_dev->mlock);
@@ -378,10 +414,14 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev)
 {
 	int ret;
 	u16 prod_id, smp_prd;
+	unsigned int device_id;
 	struct adis16400_state *st = iio_priv(indio_dev);
 
-	/* use low spi speed for init */
-	st->us->max_speed_hz = ADIS16400_SPI_SLOW;
+	/* use low spi speed for init if the device has a slow mode */
+	if (st->variant->flags & ADIS16400_HAS_SLOW_MODE)
+		st->us->max_speed_hz = ADIS16400_SPI_SLOW;
+	else
+		st->us->max_speed_hz = ADIS16400_SPI_FAST;
 	st->us->mode = SPI_MODE_3;
 	spi_setup(st->us);
 
@@ -414,19 +454,27 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev)
 		if (ret)
 			goto err_ret;
 
-		if ((prod_id & 0xF000) != st->variant->product_id)
-			dev_warn(&indio_dev->dev, "incorrect id");
+		sscanf(indio_dev->name, "adis%u\n", &device_id);
+
+		if (prod_id != device_id)
+			dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.",
+					device_id, prod_id);
 
 		dev_info(&indio_dev->dev, "%s: prod_id 0x%04x at CS%d (irq %d)\n",
 		       indio_dev->name, prod_id,
 		       st->us->chip_select, st->us->irq);
 	}
 	/* use high spi speed if possible */
-	ret = adis16400_spi_read_reg_16(indio_dev,
-					ADIS16400_SMPL_PRD, &smp_prd);
-	if (!ret && (smp_prd & ADIS16400_SMPL_PRD_DIV_MASK) < 0x0A) {
-		st->us->max_speed_hz = ADIS16400_SPI_SLOW;
-		spi_setup(st->us);
+	if (st->variant->flags & ADIS16400_HAS_SLOW_MODE) {
+		ret = adis16400_spi_read_reg_16(indio_dev,
+						ADIS16400_SMPL_PRD, &smp_prd);
+		if (ret)
+			goto err_ret;
+
+		if ((smp_prd & ADIS16400_SMPL_PRD_DIV_MASK) < 0x0A) {
+			st->us->max_speed_hz = ADIS16400_SPI_FAST;
+			spi_setup(st->us);
+		}
 	}
 
 err_ret:
@@ -503,7 +551,7 @@ static int adis16400_write_raw(struct iio_dev *indio_dev,
 		mutex_lock(&indio_dev->mlock);
 		st->filt_int = val;
 		/* Work out update to current value */
-		sps = adis16400_get_freq(indio_dev);
+		sps = st->variant->get_freq(indio_dev);
 		if (sps < 0) {
 			mutex_unlock(&indio_dev->mlock);
 			return sps;
@@ -601,7 +649,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
 			mutex_unlock(&indio_dev->mlock);
 			return ret;
 		}
-		ret = adis16400_get_freq(indio_dev);
+		val16 = st->variant->get_freq(indio_dev);
 		if (ret > 0)
 			*val = ret/adis16400_3db_divisors[val16 & 0x03];
 		*val2 = 0;
@@ -624,7 +672,7 @@ static const struct iio_chan_spec adis16400_channels[] = {
 		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
 		.address = in_supply,
 		.scan_index = ADIS16400_SCAN_SUPPLY,
-		.scan_type = IIO_ST('u', 14, 16, 0)
+		.scan_type = IIO_ST('u', 14, 16, 0),
 	}, {
 		.type = IIO_ANGL_VEL,
 		.modified = 1,
@@ -635,7 +683,7 @@ static const struct iio_chan_spec adis16400_channels[] = {
 		IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
 		.address = gyro_x,
 		.scan_index = ADIS16400_SCAN_GYRO_X,
-		.scan_type = IIO_ST('s', 14, 16, 0)
+		.scan_type = IIO_ST('s', 14, 16, 0),
 	}, {
 		.type = IIO_ANGL_VEL,
 		.modified = 1,
@@ -754,7 +802,7 @@ static const struct iio_chan_spec adis16350_channels[] = {
 		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
 		.address = in_supply,
 		.scan_index = ADIS16400_SCAN_SUPPLY,
-		.scan_type = IIO_ST('u', 12, 16, 0)
+		.scan_type = IIO_ST('u', 12, 16, 0),
 	}, {
 		.type = IIO_ANGL_VEL,
 		.modified = 1,
@@ -765,7 +813,7 @@ static const struct iio_chan_spec adis16350_channels[] = {
 		IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
 		.address = gyro_x,
 		.scan_index = ADIS16400_SCAN_GYRO_X,
-		.scan_type = IIO_ST('s', 14, 16, 0)
+		.scan_type = IIO_ST('s', 14, 16, 0),
 	}, {
 		.type = IIO_ANGL_VEL,
 		.modified = 1,
@@ -879,7 +927,7 @@ static const struct iio_chan_spec adis16300_channels[] = {
 		IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
 		.address = in_supply,
 		.scan_index = ADIS16400_SCAN_SUPPLY,
-		.scan_type = IIO_ST('u', 12, 16, 0)
+		.scan_type = IIO_ST('u', 12, 16, 0),
 	}, {
 		.type = IIO_ANGL_VEL,
 		.modified = 1,
@@ -1060,6 +1108,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
 	[ADIS16300] = {
 		.channels = adis16300_channels,
 		.num_channels = ARRAY_SIZE(adis16300_channels),
+		.flags = ADIS16400_HAS_SLOW_MODE,
 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
 		.accel_scale_micro = 5884,
 		.temp_scale_nano = 140000000, /* 0.14 C */
@@ -1070,10 +1119,13 @@ static struct adis16400_chip_info adis16400_chips[] = {
 		(1 << ADIS16400_SCAN_TEMP) | (1 << ADIS16400_SCAN_ADC_0) |
 		(1 << ADIS16300_SCAN_INCLI_X) | (1 << ADIS16300_SCAN_INCLI_Y) |
 		(1 << 14),
+		.set_freq = adis16400_set_freq,
+		.get_freq = adis16400_get_freq,
 	},
 	[ADIS16334] = {
 		.channels = adis16334_channels,
 		.num_channels = ARRAY_SIZE(adis16334_channels),
+		.flags = ADIS16400_HAS_PROD_ID,
 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
 		.accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
 		.temp_scale_nano = 67850000, /* 0.06785 C */
@@ -1082,6 +1134,8 @@ static struct adis16400_chip_info adis16400_chips[] = {
 		(1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) |
 		(1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) |
 		(1 << ADIS16400_SCAN_ACC_Z),
+		.set_freq = adis16334_set_freq,
+		.get_freq = adis16334_get_freq,
 	},
 	[ADIS16350] = {
 		.channels = adis16350_channels,
@@ -1091,62 +1145,57 @@ static struct adis16400_chip_info adis16400_chips[] = {
 		.temp_scale_nano = 145300000, /* 0.1453 C */
 		.temp_offset = 25000000 / 145300, /* 25 C = 0x00 */
 		.default_scan_mask = 0x7FF,
-		.flags = ADIS16400_NO_BURST,
+		.flags = ADIS16400_NO_BURST | ADIS16400_HAS_SLOW_MODE,
+		.set_freq = adis16400_set_freq,
+		.get_freq = adis16400_get_freq,
 	},
 	[ADIS16360] = {
 		.channels = adis16350_channels,
 		.num_channels = ARRAY_SIZE(adis16350_channels),
-		.flags = ADIS16400_HAS_PROD_ID,
-		.product_id = 0x3FE8,
+		.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
 		.accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
 		.temp_scale_nano = 136000000, /* 0.136 C */
 		.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
 		.default_scan_mask = 0x7FF,
+		.set_freq = adis16400_set_freq,
+		.get_freq = adis16400_get_freq,
 	},
 	[ADIS16362] = {
 		.channels = adis16350_channels,
 		.num_channels = ARRAY_SIZE(adis16350_channels),
-		.flags = ADIS16400_HAS_PROD_ID,
-		.product_id = 0x3FEA,
+		.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
 		.accel_scale_micro = IIO_G_TO_M_S_2(333), /* 0.333 mg */
 		.temp_scale_nano = 136000000, /* 0.136 C */
 		.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
 		.default_scan_mask = 0x7FF,
+		.set_freq = adis16400_set_freq,
+		.get_freq = adis16400_get_freq,
 	},
 	[ADIS16364] = {
 		.channels = adis16350_channels,
 		.num_channels = ARRAY_SIZE(adis16350_channels),
-		.flags = ADIS16400_HAS_PROD_ID,
-		.product_id = 0x3FEC,
-		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
-		.accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
-		.temp_scale_nano = 136000000, /* 0.136 C */
-		.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
-		.default_scan_mask = 0x7FF,
-	},
-	[ADIS16365] = {
-		.channels = adis16350_channels,
-		.num_channels = ARRAY_SIZE(adis16350_channels),
-		.flags = ADIS16400_HAS_PROD_ID,
-		.product_id = 0x3FED,
+		.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
 		.accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
 		.temp_scale_nano = 136000000, /* 0.136 C */
 		.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
 		.default_scan_mask = 0x7FF,
+		.set_freq = adis16400_set_freq,
+		.get_freq = adis16400_get_freq,
 	},
 	[ADIS16400] = {
 		.channels = adis16400_channels,
 		.num_channels = ARRAY_SIZE(adis16400_channels),
-		.flags = ADIS16400_HAS_PROD_ID,
-		.product_id = 0x4015,
+		.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
 		.accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
 		.default_scan_mask = 0xFFF,
 		.temp_scale_nano = 140000000, /* 0.14 C */
 		.temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
+		.set_freq = adis16400_set_freq,
+		.get_freq = adis16400_get_freq,
 	}
 };
 
@@ -1157,7 +1206,7 @@ static const struct iio_info adis16400_info = {
 	.attrs = &adis16400_attribute_group,
 };
 
-static int __devinit adis16400_probe(struct spi_device *spi)
+static int adis16400_probe(struct spi_device *spi)
 {
 	int ret;
 	struct adis16400_state *st;
@@ -1224,7 +1273,7 @@ error_ret:
 }
 
 /* fixme, confirm ordering in this function */
-static int __devexit adis16400_remove(struct spi_device *spi)
+static int adis16400_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev =  spi_get_drvdata(spi);
 
@@ -1248,7 +1297,7 @@ static const struct spi_device_id adis16400_id[] = {
 	{"adis16360", ADIS16360},
 	{"adis16362", ADIS16362},
 	{"adis16364", ADIS16364},
-	{"adis16365", ADIS16365},
+	{"adis16365", ADIS16360},
 	{"adis16400", ADIS16400},
 	{"adis16405", ADIS16400},
 	{}
@@ -1262,7 +1311,7 @@ static struct spi_driver adis16400_driver = {
 	},
 	.id_table = adis16400_id,
 	.probe = adis16400_probe,
-	.remove = __devexit_p(adis16400_remove),
+	.remove = adis16400_remove,
 };
 module_spi_driver(adis16400_driver);
 
diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c
index 260bdd1..d46c1e3 100644
--- a/drivers/staging/iio/imu/adis16400_ring.c
+++ b/drivers/staging/iio/imu/adis16400_ring.c
@@ -114,7 +114,6 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct adis16400_state *st = iio_priv(indio_dev);
-	struct iio_buffer *ring = indio_dev->buffer;
 	int i = 0, j, ret = 0;
 	s16 *data;
 
@@ -148,9 +147,9 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
 		}
 	}
 	/* Guaranteed to be aligned with 8 byte boundary */
-	if (ring->scan_timestamp)
+	if (indio_dev->scan_timestamp)
 		*((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-	iio_push_to_buffer(ring, (u8 *) data);
+	iio_push_to_buffers(indio_dev, (u8 *) data);
 
 done:
 	kfree(data);
diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
index 6ee5567..b0adac0 100644
--- a/drivers/staging/iio/light/isl29018.c
+++ b/drivers/staging/iio/light/isl29018.c
@@ -67,6 +67,7 @@ struct isl29018_chip {
 	unsigned int		range;
 	unsigned int		adc_bit;
 	int			prox_scheme;
+	bool			suspended;
 };
 
 static int isl29018_set_range(struct isl29018_chip *chip, unsigned long range,
@@ -355,7 +356,7 @@ static int isl29018_write_raw(struct iio_dev *indio_dev,
 	}
 	mutex_unlock(&chip->lock);
 
-	return 0;
+	return ret;
 }
 
 static int isl29018_read_raw(struct iio_dev *indio_dev,
@@ -368,6 +369,10 @@ static int isl29018_read_raw(struct iio_dev *indio_dev,
 	struct isl29018_chip *chip = iio_priv(indio_dev);
 
 	mutex_lock(&chip->lock);
+	if (chip->suspended) {
+		mutex_unlock(&chip->lock);
+		return -EBUSY;
+	}
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
 	case IIO_CHAN_INFO_PROCESSED:
@@ -538,7 +543,7 @@ static const struct regmap_config isl29018_regmap_config = {
 	.cache_type = REGCACHE_RBTREE,
 };
 
-static int __devinit isl29018_probe(struct i2c_client *client,
+static int isl29018_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct isl29018_chip *chip;
@@ -561,6 +566,7 @@ static int __devinit isl29018_probe(struct i2c_client *client,
 	chip->lux_scale = 1;
 	chip->range = 1000;
 	chip->adc_bit = 16;
+	chip->suspended = false;
 
 	chip->regmap = devm_regmap_init_i2c(client, &isl29018_regmap_config);
 	if (IS_ERR(chip->regmap)) {
@@ -592,7 +598,7 @@ exit:
 	return err;
 }
 
-static int __devexit isl29018_remove(struct i2c_client *client)
+static int isl29018_remove(struct i2c_client *client)
 {
 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
@@ -603,6 +609,44 @@ static int __devexit isl29018_remove(struct i2c_client *client)
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int isl29018_suspend(struct device *dev)
+{
+	struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev));
+
+	mutex_lock(&chip->lock);
+
+	/* Since this driver uses only polling commands, we are by default in
+	 * auto shutdown (ie, power-down) mode.
+	 * So we do not have much to do here.
+	 */
+	chip->suspended = true;
+
+	mutex_unlock(&chip->lock);
+	return 0;
+}
+
+static int isl29018_resume(struct device *dev)
+{
+	struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev));
+	int err;
+
+	mutex_lock(&chip->lock);
+
+	err = isl29018_chip_init(chip);
+	if (!err)
+		chip->suspended = false;
+
+	mutex_unlock(&chip->lock);
+	return err;
+}
+
+static SIMPLE_DEV_PM_OPS(isl29018_pm_ops, isl29018_suspend, isl29018_resume);
+#define ISL29018_PM_OPS (&isl29018_pm_ops)
+#else
+#define ISL29018_PM_OPS NULL
+#endif
+
 static const struct i2c_device_id isl29018_id[] = {
 	{"isl29018", 0},
 	{}
@@ -620,11 +664,12 @@ static struct i2c_driver isl29018_driver = {
 	.class	= I2C_CLASS_HWMON,
 	.driver	 = {
 			.name = "isl29018",
+			.pm = ISL29018_PM_OPS,
 			.owner = THIS_MODULE,
 			.of_match_table = isl29018_of_match,
 		    },
 	.probe	 = isl29018_probe,
-	.remove	 = __devexit_p(isl29018_remove),
+	.remove	 = isl29018_remove,
 	.id_table = isl29018_id,
 };
 module_i2c_driver(isl29018_driver);
diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c
index 33a4c3f..e52af77 100644
--- a/drivers/staging/iio/light/isl29028.c
+++ b/drivers/staging/iio/light/isl29028.c
@@ -475,7 +475,7 @@ static const struct regmap_config isl29028_regmap_config = {
 	.cache_type = REGCACHE_RBTREE,
 };
 
-static int __devinit isl29028_probe(struct i2c_client *client,
+static int isl29028_probe(struct i2c_client *client,
 	const struct i2c_device_id *id)
 {
 	struct isl29028_chip *chip;
@@ -526,7 +526,7 @@ exit_iio_free:
 	return ret;
 }
 
-static int __devexit isl29028_remove(struct i2c_client *client)
+static int isl29028_remove(struct i2c_client *client)
 {
 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
@@ -555,7 +555,7 @@ static struct i2c_driver isl29028_driver = {
 		.of_match_table = isl29028_of_match,
 	},
 	.probe	 = isl29028_probe,
-	.remove  = __devexit_p(isl29028_remove),
+	.remove  = isl29028_remove,
 	.id_table = isl29028_id,
 };
 
diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
index 954ca2c..1a9adc0 100644
--- a/drivers/staging/iio/light/tsl2563.c
+++ b/drivers/staging/iio/light/tsl2563.c
@@ -652,7 +652,7 @@ static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev,
 	}
 
 	if (!state && (chip->intr & 0x30)) {
-		chip->intr |= ~0x30;
+		chip->intr &= ~0x30;
 		ret = i2c_smbus_write_byte_data(chip->client,
 						TSL2563_CMD | TSL2563_REG_INT,
 						chip->intr);
@@ -705,7 +705,7 @@ static const struct iio_info tsl2563_info = {
 	.write_event_config = &tsl2563_write_interrupt_config,
 };
 
-static int __devinit tsl2563_probe(struct i2c_client *client,
+static int tsl2563_probe(struct i2c_client *client,
 				const struct i2c_device_id *device_id)
 {
 	struct iio_dev *indio_dev;
@@ -805,7 +805,7 @@ fail1:
 	return err;
 }
 
-static int __devexit tsl2563_remove(struct i2c_client *client)
+static int tsl2563_remove(struct i2c_client *client)
 {
 	struct tsl2563_chip *chip = i2c_get_clientdata(client);
 	struct iio_dev *indio_dev = iio_priv_to_dev(chip);
@@ -814,7 +814,7 @@ static int __devexit tsl2563_remove(struct i2c_client *client)
 	if (!chip->int_enabled)
 		cancel_delayed_work(&chip->poweroff_work);
 	/* Ensure that interrupts are disabled - then flush any bottom halves */
-	chip->intr |= ~0x30;
+	chip->intr &= ~0x30;
 	i2c_smbus_write_byte_data(chip->client, TSL2563_CMD | TSL2563_REG_INT,
 				  chip->intr);
 	flush_scheduled_work();
@@ -889,7 +889,7 @@ static struct i2c_driver tsl2563_i2c_driver = {
 		.pm	= TSL2563_PM_OPS,
 	},
 	.probe		= tsl2563_probe,
-	.remove		= __devexit_p(tsl2563_remove),
+	.remove		= tsl2563_remove,
 	.id_table	= tsl2563_id,
 };
 module_i2c_driver(tsl2563_i2c_driver);
diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c
index 6d2f4c6..b377dd3 100644
--- a/drivers/staging/iio/light/tsl2583.c
+++ b/drivers/staging/iio/light/tsl2583.c
@@ -799,7 +799,7 @@ static const struct iio_info tsl2583_info = {
  * Client probe function - When a valid device is found, the driver's device
  * data structure is updated, and initialization completes successfully.
  */
-static int __devinit taos_probe(struct i2c_client *clientp,
+static int taos_probe(struct i2c_client *clientp,
 		      const struct i2c_device_id *idp)
 {
 	int i, ret;
@@ -923,7 +923,7 @@ static SIMPLE_DEV_PM_OPS(taos_pm_ops, taos_suspend, taos_resume);
 #define TAOS_PM_OPS NULL
 #endif
 
-static int __devexit taos_remove(struct i2c_client *client)
+static int taos_remove(struct i2c_client *client)
 {
 	iio_device_unregister(i2c_get_clientdata(client));
 	iio_device_free(i2c_get_clientdata(client));
@@ -947,7 +947,7 @@ static struct i2c_driver taos_driver = {
 	},
 	.id_table = taos_idtable,
 	.probe = taos_probe,
-	.remove = __devexit_p(taos_remove),
+	.remove = taos_remove,
 };
 module_i2c_driver(taos_driver);
 
diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c
index 497a977..9e50fbb 100644
--- a/drivers/staging/iio/light/tsl2x7x_core.c
+++ b/drivers/staging/iio/light/tsl2x7x_core.c
@@ -1897,7 +1897,7 @@ static const struct tsl2x7x_chip_info tsl2x7x_chip_info_tbl[] = {
 	},
 };
 
-static int __devinit tsl2x7x_probe(struct i2c_client *clientp,
+static int tsl2x7x_probe(struct i2c_client *clientp,
 	const struct i2c_device_id *id)
 {
 	int ret;
@@ -2026,7 +2026,7 @@ static int tsl2x7x_resume(struct device *dev)
 	return ret;
 }
 
-static int __devexit tsl2x7x_remove(struct i2c_client *client)
+static int tsl2x7x_remove(struct i2c_client *client)
 {
 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
@@ -2070,7 +2070,7 @@ static struct i2c_driver tsl2x7x_driver = {
 	},
 	.id_table = tsl2x7x_idtable,
 	.probe = tsl2x7x_probe,
-	.remove = __devexit_p(tsl2x7x_remove),
+	.remove = tsl2x7x_remove,
 };
 
 module_i2c_driver(tsl2x7x_driver);
diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c
index 01b4b07..28f080e 100644
--- a/drivers/staging/iio/magnetometer/ak8975.c
+++ b/drivers/staging/iio/magnetometer/ak8975.c
@@ -409,7 +409,7 @@ static const struct iio_info ak8975_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit ak8975_probe(struct i2c_client *client,
+static int ak8975_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct ak8975_data *data;
@@ -475,7 +475,7 @@ exit:
 	return err;
 }
 
-static int __devexit ak8975_remove(struct i2c_client *client)
+static int ak8975_remove(struct i2c_client *client)
 {
 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 	struct ak8975_data *data = iio_priv(indio_dev);
@@ -510,7 +510,7 @@ static struct i2c_driver ak8975_driver = {
 		.of_match_table = ak8975_of_match,
 	},
 	.probe		= ak8975_probe,
-	.remove		= __devexit_p(ak8975_remove),
+	.remove		= ak8975_remove,
 	.id_table	= ak8975_id,
 };
 module_i2c_driver(ak8975_driver);
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
index 10e0954..1a520ec 100644
--- a/drivers/staging/iio/magnetometer/hmc5843.c
+++ b/drivers/staging/iio/magnetometer/hmc5843.c
@@ -555,7 +555,7 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev,
 		*val = 0;
 		*val2 = data->variant->regval_to_nanoscale[data->range];
 		return IIO_VAL_INT_PLUS_NANO;
-	};
+	}
 	return -EINVAL;
 }
 
@@ -665,7 +665,7 @@ static const struct iio_info hmc5843_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit hmc5843_probe(struct i2c_client *client,
+static int hmc5843_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct hmc5843_data *data;
@@ -704,7 +704,7 @@ exit:
 	return err;
 }
 
-static int __devexit hmc5843_remove(struct i2c_client *client)
+static int hmc5843_remove(struct i2c_client *client)
 {
 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
@@ -755,7 +755,7 @@ static struct i2c_driver hmc5843_driver = {
 	},
 	.id_table	= hmc5843_id,
 	.probe		= hmc5843_probe,
-	.remove		= __devexit_p(hmc5843_remove),
+	.remove		= hmc5843_remove,
 	.detect		= hmc5843_detect,
 	.address_list	= normal_i2c,
 };
diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
index 8b9eceb..51c3bde 100644
--- a/drivers/staging/iio/meter/ade7753.c
+++ b/drivers/staging/iio/meter/ade7753.c
@@ -512,7 +512,7 @@ static const struct iio_info ade7753_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit ade7753_probe(struct spi_device *spi)
+static int ade7753_probe(struct spi_device *spi)
 {
 	int ret;
 	struct ade7753_state *st;
@@ -555,7 +555,7 @@ error_ret:
 }
 
 /* fixme, confirm ordering in this function */
-static int __devexit ade7753_remove(struct spi_device *spi)
+static int ade7753_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
@@ -572,7 +572,7 @@ static struct spi_driver ade7753_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ade7753_probe,
-	.remove = __devexit_p(ade7753_remove),
+	.remove = ade7753_remove,
 };
 module_spi_driver(ade7753_driver);
 
diff --git a/drivers/staging/iio/meter/ade7753.h b/drivers/staging/iio/meter/ade7753.h
index 3f059d3..a9d93cc 100644
--- a/drivers/staging/iio/meter/ade7753.h
+++ b/drivers/staging/iio/meter/ade7753.h
@@ -55,8 +55,6 @@
 #define ADE7753_SPI_BURST	(u32)(1000 * 1000)
 #define ADE7753_SPI_FAST	(u32)(2000 * 1000)
 
-#define DRIVER_NAME		"ade7753"
-
 /**
  * struct ade7753_state - device instance specific data
  * @us:			actual spi_device
diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c
index 76e0ade..b50c89e 100644
--- a/drivers/staging/iio/meter/ade7754.c
+++ b/drivers/staging/iio/meter/ade7754.c
@@ -535,7 +535,7 @@ static const struct iio_info ade7754_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit ade7754_probe(struct spi_device *spi)
+static int ade7754_probe(struct spi_device *spi)
 {
 	int ret;
 	struct ade7754_state *st;
@@ -577,7 +577,7 @@ error_ret:
 }
 
 /* fixme, confirm ordering in this function */
-static int __devexit ade7754_remove(struct spi_device *spi)
+static int ade7754_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
@@ -594,7 +594,7 @@ static struct spi_driver ade7754_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ade7754_probe,
-	.remove = __devexit_p(ade7754_remove),
+	.remove = ade7754_remove,
 };
 module_spi_driver(ade7754_driver);
 
diff --git a/drivers/staging/iio/meter/ade7754.h b/drivers/staging/iio/meter/ade7754.h
index 6121125..e42ffc3 100644
--- a/drivers/staging/iio/meter/ade7754.h
+++ b/drivers/staging/iio/meter/ade7754.h
@@ -73,8 +73,6 @@
 #define ADE7754_SPI_BURST	(u32)(1000 * 1000)
 #define ADE7754_SPI_FAST	(u32)(2000 * 1000)
 
-#define DRIVER_NAME		"ade7754"
-
 /**
  * struct ade7754_state - device instance specific data
  * @us:			actual spi_device
diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h
index 1e11ad5..0731820 100644
--- a/drivers/staging/iio/meter/ade7758.h
+++ b/drivers/staging/iio/meter/ade7758.h
@@ -105,9 +105,6 @@
 #define AD7758_APP_PWR		4
 #define AD7758_WT(p, w)		(((w) << 2) | (p))
 
-#define DRIVER_NAME		"ade7758"
-
-
 /**
  * struct ade7758_state - device instance specific data
  * @us:			actual spi_device
diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c
index a0fef77..3454e51 100644
--- a/drivers/staging/iio/meter/ade7758_core.c
+++ b/drivers/staging/iio/meter/ade7758_core.c
@@ -881,7 +881,7 @@ static const struct iio_info ade7758_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit ade7758_probe(struct spi_device *spi)
+static int ade7758_probe(struct spi_device *spi)
 {
 	int ret;
 	struct ade7758_state *st;
@@ -962,7 +962,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit ade7758_remove(struct spi_device *spi)
+static int ade7758_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 	struct ade7758_state *st = iio_priv(indio_dev);
@@ -992,7 +992,7 @@ static struct spi_driver ade7758_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ade7758_probe,
-	.remove = __devexit_p(ade7758_remove),
+	.remove = ade7758_remove,
 	.id_table = ade7758_id,
 };
 module_spi_driver(ade7758_driver);
diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c
index 9e49bac..4552a4c 100644
--- a/drivers/staging/iio/meter/ade7758_ring.c
+++ b/drivers/staging/iio/meter/ade7758_ring.c
@@ -73,7 +73,7 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p)
 	if (indio_dev->scan_timestamp)
 		dat64[1] = pf->timestamp;
 
-	iio_push_to_buffer(indio_dev->buffer, (u8 *)dat64);
+	iio_push_to_buffers(indio_dev, (u8 *)dat64);
 
 	iio_trigger_notify_done(indio_dev->trig);
 
diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c
index cb0707c..10b911b 100644
--- a/drivers/staging/iio/meter/ade7759.c
+++ b/drivers/staging/iio/meter/ade7759.c
@@ -458,7 +458,7 @@ static const struct iio_info ade7759_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit ade7759_probe(struct spi_device *spi)
+static int ade7759_probe(struct spi_device *spi)
 {
 	int ret;
 	struct ade7759_state *st;
@@ -499,7 +499,7 @@ error_ret:
 }
 
 /* fixme, confirm ordering in this function */
-static int __devexit ade7759_remove(struct spi_device *spi)
+static int ade7759_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
@@ -516,7 +516,7 @@ static struct spi_driver ade7759_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ade7759_probe,
-	.remove = __devexit_p(ade7759_remove),
+	.remove = ade7759_remove,
 };
 module_spi_driver(ade7759_driver);
 
diff --git a/drivers/staging/iio/meter/ade7759.h b/drivers/staging/iio/meter/ade7759.h
index c81d23d..f9ff1f8 100644
--- a/drivers/staging/iio/meter/ade7759.h
+++ b/drivers/staging/iio/meter/ade7759.h
@@ -36,8 +36,6 @@
 #define ADE7759_SPI_BURST	(u32)(1000 * 1000)
 #define ADE7759_SPI_FAST	(u32)(2000 * 1000)
 
-#define DRIVER_NAME		"ade7759"
-
 /**
  * struct ade7759_state - device instance specific data
  * @us:			actual spi_device
diff --git a/drivers/staging/iio/meter/ade7854-i2c.c b/drivers/staging/iio/meter/ade7854-i2c.c
index 0609046..db9ef6c 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -201,7 +201,7 @@ out:
 	return ret;
 }
 
-static int __devinit ade7854_i2c_probe(struct i2c_client *client,
+static int ade7854_i2c_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	int ret;
@@ -231,7 +231,7 @@ static int __devinit ade7854_i2c_probe(struct i2c_client *client,
 	return ret;
 }
 
-static int __devexit ade7854_i2c_remove(struct i2c_client *client)
+static int ade7854_i2c_remove(struct i2c_client *client)
 {
 	return ade7854_remove(i2c_get_clientdata(client));
 }
@@ -250,7 +250,7 @@ static struct i2c_driver ade7854_i2c_driver = {
 		.name = "ade7854",
 	},
 	.probe    = ade7854_i2c_probe,
-	.remove   = __devexit_p(ade7854_i2c_remove),
+	.remove   = ade7854_i2c_remove,
 	.id_table = ade7854_id,
 };
 module_i2c_driver(ade7854_i2c_driver);
diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c
index 7dae035..f0984fa 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -300,7 +300,7 @@ error_ret:
 	return ret;
 }
 
-static int __devinit ade7854_spi_probe(struct spi_device *spi)
+static int ade7854_spi_probe(struct spi_device *spi)
 {
 	int ret;
 	struct ade7854_state *st;
@@ -330,7 +330,7 @@ static int __devinit ade7854_spi_probe(struct spi_device *spi)
 	return 0;
 }
 
-static int __devexit ade7854_spi_remove(struct spi_device *spi)
+static int ade7854_spi_remove(struct spi_device *spi)
 {
 	ade7854_remove(spi_get_drvdata(spi));
 
@@ -351,7 +351,7 @@ static struct spi_driver ade7854_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ade7854_spi_probe,
-	.remove = __devexit_p(ade7854_spi_remove),
+	.remove = ade7854_spi_remove,
 	.id_table = ade7854_id,
 };
 module_spi_driver(ade7854_driver);
diff --git a/drivers/staging/iio/meter/ade7854.h b/drivers/staging/iio/meter/ade7854.h
index 2c96e86..0653457 100644
--- a/drivers/staging/iio/meter/ade7854.h
+++ b/drivers/staging/iio/meter/ade7854.h
@@ -142,8 +142,6 @@
 #define ADE7854_SPI_BURST	(u32)(1000 * 1000)
 #define ADE7854_SPI_FAST	(u32)(2000 * 1000)
 
-#define DRIVER_NAME		"ade7854"
-
 /**
  * struct ade7854_state - device instance specific data
  * @spi:			actual spi_device
diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c
index 8b71eb0..4fe3499 100644
--- a/drivers/staging/iio/resolver/ad2s1200.c
+++ b/drivers/staging/iio/resolver/ad2s1200.c
@@ -99,7 +99,7 @@ static const struct iio_info ad2s1200_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit ad2s1200_probe(struct spi_device *spi)
+static int ad2s1200_probe(struct spi_device *spi)
 {
 	struct ad2s1200_state *st;
 	struct iio_dev *indio_dev;
@@ -149,7 +149,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit ad2s1200_remove(struct spi_device *spi)
+static int ad2s1200_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
 	iio_device_free(spi_get_drvdata(spi));
@@ -170,7 +170,7 @@ static struct spi_driver ad2s1200_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ad2s1200_probe,
-	.remove = __devexit_p(ad2s1200_remove),
+	.remove = ad2s1200_remove,
 	.id_table = ad2s1200_id,
 };
 module_spi_driver(ad2s1200_driver);
diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
index 4ba4d05..ed07a34 100644
--- a/drivers/staging/iio/resolver/ad2s1210.c
+++ b/drivers/staging/iio/resolver/ad2s1210.c
@@ -610,7 +610,7 @@ static const struct attribute_group ad2s1210_attribute_group = {
 	.attrs = ad2s1210_attributes,
 };
 
-static int __devinit ad2s1210_initial(struct ad2s1210_state *st)
+static int ad2s1210_initial(struct ad2s1210_state *st)
 {
 	unsigned char data;
 	int ret;
@@ -681,7 +681,7 @@ static void ad2s1210_free_gpios(struct ad2s1210_state *st)
 	gpio_free_array(ad2s1210_gpios, ARRAY_SIZE(ad2s1210_gpios));
 }
 
-static int __devinit ad2s1210_probe(struct spi_device *spi)
+static int ad2s1210_probe(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev;
 	struct ad2s1210_state *st;
@@ -736,7 +736,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit ad2s1210_remove(struct spi_device *spi)
+static int ad2s1210_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 
@@ -759,7 +759,7 @@ static struct spi_driver ad2s1210_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ad2s1210_probe,
-	.remove = __devexit_p(ad2s1210_remove),
+	.remove = ad2s1210_remove,
 	.id_table = ad2s1210_id,
 };
 module_spi_driver(ad2s1210_driver);
diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c
index a805722..0aecfbc 100644
--- a/drivers/staging/iio/resolver/ad2s90.c
+++ b/drivers/staging/iio/resolver/ad2s90.c
@@ -58,7 +58,7 @@ static const struct iio_chan_spec ad2s90_chan = {
 	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
 };
 
-static int __devinit ad2s90_probe(struct spi_device *spi)
+static int ad2s90_probe(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev;
 	struct ad2s90_state *st;
@@ -98,7 +98,7 @@ error_ret:
 	return ret;
 }
 
-static int __devexit ad2s90_remove(struct spi_device *spi)
+static int ad2s90_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
 	iio_device_free(spi_get_drvdata(spi));
@@ -118,7 +118,7 @@ static struct spi_driver ad2s90_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ad2s90_probe,
-	.remove = __devexit_p(ad2s90_remove),
+	.remove = ad2s90_remove,
 	.id_table = ad2s90_id,
 };
 module_spi_driver(ad2s90_driver);
diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
index 52062d7..42798da 100644
--- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
@@ -180,7 +180,7 @@ static const struct iio_trigger_ops iio_bfin_tmr_trigger_ops = {
 	.set_trigger_state = iio_bfin_tmr_set_state,
 };
 
-static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
+static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
 {
 	struct iio_bfin_timer_trigger_pdata *pdata = pdev->dev.platform_data;
 	struct bfin_tmr_state *st;
@@ -275,7 +275,7 @@ out:
 	return ret;
 }
 
-static int __devexit iio_bfin_tmr_trigger_remove(struct platform_device *pdev)
+static int iio_bfin_tmr_trigger_remove(struct platform_device *pdev)
 {
 	struct bfin_tmr_state *st = platform_get_drvdata(pdev);
 
@@ -296,7 +296,7 @@ static struct platform_driver iio_bfin_tmr_trigger_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = iio_bfin_tmr_trigger_probe,
-	.remove = __devexit_p(iio_bfin_tmr_trigger_remove),
+	.remove = iio_bfin_tmr_trigger_remove,
 };
 
 module_platform_driver(iio_bfin_tmr_trigger_driver);
diff --git a/drivers/staging/iio/trigger/iio-trig-gpio.c b/drivers/staging/iio/trigger/iio-trig-gpio.c
index 5ff4d7f..fcc4cb0 100644
--- a/drivers/staging/iio/trigger/iio-trig-gpio.c
+++ b/drivers/staging/iio/trigger/iio-trig-gpio.c
@@ -51,7 +51,7 @@ static const struct iio_trigger_ops iio_gpio_trigger_ops = {
 	.owner = THIS_MODULE,
 };
 
-static int __devinit iio_gpio_trigger_probe(struct platform_device *pdev)
+static int iio_gpio_trigger_probe(struct platform_device *pdev)
 {
 	struct iio_gpio_trigger_info *trig_info;
 	struct iio_trigger *trig, *trig2;
@@ -130,7 +130,7 @@ error_free_completed_registrations:
 	return ret;
 }
 
-static int __devexit iio_gpio_trigger_remove(struct platform_device *pdev)
+static int iio_gpio_trigger_remove(struct platform_device *pdev)
 {
 	struct iio_trigger *trig, *trig2;
 	struct iio_gpio_trigger_info *trig_info;
@@ -153,7 +153,7 @@ static int __devexit iio_gpio_trigger_remove(struct platform_device *pdev)
 
 static struct platform_driver iio_gpio_trigger_driver = {
 	.probe = iio_gpio_trigger_probe,
-	.remove = __devexit_p(iio_gpio_trigger_remove),
+	.remove = iio_gpio_trigger_remove,
 	.driver = {
 		.name = "iio_gpio_trigger",
 		.owner = THIS_MODULE,
diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
index a3de76d..9102b1b 100644
--- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
@@ -101,7 +101,7 @@ static const struct iio_trigger_ops iio_prtc_trigger_ops = {
 	.set_trigger_state = &iio_trig_periodic_rtc_set_state,
 };
 
-static int __devinit iio_trig_periodic_rtc_probe(struct platform_device *dev)
+static int iio_trig_periodic_rtc_probe(struct platform_device *dev)
 {
 	char **pdata = dev->dev.platform_data;
 	struct iio_prtc_trigger_info *trig_info;
@@ -167,7 +167,7 @@ error_free_completed_registrations:
 	return ret;
 }
 
-static int __devexit iio_trig_periodic_rtc_remove(struct platform_device *dev)
+static int iio_trig_periodic_rtc_remove(struct platform_device *dev)
 {
 	struct iio_trigger *trig, *trig2;
 	struct iio_prtc_trigger_info *trig_info;
@@ -188,7 +188,7 @@ static int __devexit iio_trig_periodic_rtc_remove(struct platform_device *dev)
 
 static struct platform_driver iio_trig_periodic_rtc_driver = {
 	.probe = iio_trig_periodic_rtc_probe,
-	.remove = __devexit_p(iio_trig_periodic_rtc_remove),
+	.remove = iio_trig_periodic_rtc_remove,
 	.driver = {
 		.name = "iio_prtc_trigger",
 		.owner = THIS_MODULE,
diff --git a/drivers/staging/imx-drm/Kconfig b/drivers/staging/imx-drm/Kconfig
index 14b4449..be7e2e3 100644
--- a/drivers/staging/imx-drm/Kconfig
+++ b/drivers/staging/imx-drm/Kconfig
@@ -3,7 +3,7 @@ config DRM_IMX
 	select DRM_KMS_HELPER
 	select DRM_GEM_CMA_HELPER
 	select DRM_KMS_CMA_HELPER
-	depends on DRM && ARCH_MXC
+	depends on DRM && (ARCH_MXC || ARCH_MULTIPLATFORM)
 	help
 	  enable i.MX graphics support
 
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index 1913199..ecf0f44 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -824,7 +824,7 @@ static int imx_drm_platform_remove(struct platform_device *pdev)
 
 static struct platform_driver imx_drm_pdrv = {
 	.probe		= imx_drm_platform_probe,
-	.remove		= __devexit_p(imx_drm_platform_remove),
+	.remove		= imx_drm_platform_remove,
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= "imx-drm",
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 74158dd..99d1cce 100644
--- a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
+++ b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
@@ -16,7 +16,6 @@
 #include <linux/videodev2.h>
 #include <linux/bitmap.h>
 #include <linux/fb.h>
-#include <linux/videodev2.h>
 
 struct ipu_soc;
 
@@ -293,6 +292,7 @@ static inline void ipu_cpmem_interlaced_scan(struct ipu_ch_param *p,
 
 void ipu_cpmem_set_yuv_planar(struct ipu_ch_param __iomem *p, u32 pixel_format,
 			int stride, int height);
+void ipu_cpmem_set_yuv_interleaved(struct ipu_ch_param *p, u32 pixel_format);
 void ipu_cpmem_set_yuv_planar_full(struct ipu_ch_param __iomem *p,
 		u32 pixel_format, int stride, int u_offset, int v_offset);
 int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat);
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
index f381960..677e665 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
@@ -225,6 +225,23 @@ int ipu_cpmem_set_format_passthrough(struct ipu_ch_param __iomem *p,
 }
 EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough);
 
+void ipu_cpmem_set_yuv_interleaved(struct ipu_ch_param *p, u32 pixel_format)
+{
+	switch (pixel_format) {
+	case V4L2_PIX_FMT_UYVY:
+		ipu_ch_param_write_field(p, IPU_FIELD_BPP, 3);    /* bits/pixel */
+		ipu_ch_param_write_field(p, IPU_FIELD_PFS, 0xA);  /* pix format */
+		ipu_ch_param_write_field(p, IPU_FIELD_NPB, 31);   /* burst size */
+		break;
+	case V4L2_PIX_FMT_YUYV:
+		ipu_ch_param_write_field(p, IPU_FIELD_BPP, 3);    /* bits/pixel */
+		ipu_ch_param_write_field(p, IPU_FIELD_PFS, 0x8);  /* pix format */
+		ipu_ch_param_write_field(p, IPU_FIELD_NPB, 31);   /* burst size */
+		break;
+	}
+}
+EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_interleaved);
+
 void ipu_cpmem_set_yuv_planar_full(struct ipu_ch_param __iomem *p,
 		u32 pixel_format, int stride, int u_offset, int v_offset)
 {
@@ -234,6 +251,11 @@ void ipu_cpmem_set_yuv_planar_full(struct ipu_ch_param __iomem *p,
 		ipu_ch_param_write_field(p, IPU_FIELD_UBO, u_offset / 8);
 		ipu_ch_param_write_field(p, IPU_FIELD_VBO, v_offset / 8);
 		break;
+	case V4L2_PIX_FMT_YVU420:
+		ipu_ch_param_write_field(p, IPU_FIELD_SLUV, (stride / 2) - 1);
+		ipu_ch_param_write_field(p, IPU_FIELD_UBO, v_offset / 8);
+		ipu_ch_param_write_field(p, IPU_FIELD_VBO, u_offset / 8);
+		break;
 	}
 }
 EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
@@ -246,10 +268,11 @@ void ipu_cpmem_set_yuv_planar(struct ipu_ch_param __iomem *p, u32 pixel_format,
 
 	switch (pixel_format) {
 	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
 		uv_stride = stride / 2;
 		u_offset = stride * height;
 		v_offset = u_offset + (uv_stride * height / 2);
-		ipu_cpmem_set_yuv_planar_full(p, V4L2_PIX_FMT_YUV420, stride,
+		ipu_cpmem_set_yuv_planar_full(p, pixel_format, stride,
 				u_offset, v_offset);
 		break;
 	}
@@ -307,6 +330,7 @@ int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat)
 {
 	switch (pixelformat) {
 	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
 		/* pix format */
 		ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 2);
 		/* burst size */
@@ -369,6 +393,7 @@ int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem,
 
 	switch (pix->pixelformat) {
 	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
 		y_offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
 		u_offset = U_OFFSET(pix, image->rect.left,
 				image->rect.top) - y_offset;
@@ -380,6 +405,7 @@ int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem,
 		ipu_cpmem_set_buffer(cpmem, 0, image->phys + y_offset);
 		break;
 	case V4L2_PIX_FMT_UYVY:
+	case V4L2_PIX_FMT_YUYV:
 		ipu_cpmem_set_buffer(cpmem, 0, image->phys +
 				image->rect.left * 2 +
 				image->rect.top * image->pix.bytesperline);
@@ -413,8 +439,9 @@ enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat)
 {
 	switch (pixelformat) {
 	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
 	case V4L2_PIX_FMT_UYVY:
-	case V4L2_PIX_FMT_YVYU:
+	case V4L2_PIX_FMT_YUYV:
 		return IPUV3_COLORSPACE_YUV;
 	case V4L2_PIX_FMT_RGB32:
 	case V4L2_PIX_FMT_BGR32:
@@ -646,8 +673,6 @@ static int ipu_reset(struct ipu_soc *ipu)
 		cpu_relax();
 	}
 
-	mdelay(300);
-
 	return 0;
 }
 
@@ -988,7 +1013,7 @@ static void ipu_irq_exit(struct ipu_soc *ipu)
 	irq_free_descs(ipu->irq_start, IPU_NUM_IRQS);
 }
 
-static int __devinit ipu_probe(struct platform_device *pdev)
+static int ipu_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id =
 			of_match_device(imx_ipu_dt_ids, &pdev->dev);
@@ -1000,13 +1025,11 @@ static int __devinit ipu_probe(struct platform_device *pdev)
 
 	devtype = of_id->data;
 
-	dev_info(&pdev->dev, "Initializing %s\n", devtype->name);
-
 	irq_sync = platform_get_irq(pdev, 0);
 	irq_err = platform_get_irq(pdev, 1);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	dev_info(&pdev->dev, "irq_sync: %d irq_err: %d\n",
+	dev_dbg(&pdev->dev, "irq_sync: %d irq_err: %d\n",
 			irq_sync, irq_err);
 
 	if (!res || irq_sync < 0 || irq_err < 0)
@@ -1026,27 +1049,27 @@ static int __devinit ipu_probe(struct platform_device *pdev)
 	spin_lock_init(&ipu->lock);
 	mutex_init(&ipu->channel_lock);
 
-	dev_info(&pdev->dev, "cm_reg:   0x%08lx\n",
+	dev_dbg(&pdev->dev, "cm_reg:   0x%08lx\n",
 			ipu_base + devtype->cm_ofs);
-	dev_info(&pdev->dev, "idmac:    0x%08lx\n",
+	dev_dbg(&pdev->dev, "idmac:    0x%08lx\n",
 			ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS);
-	dev_info(&pdev->dev, "cpmem:    0x%08lx\n",
+	dev_dbg(&pdev->dev, "cpmem:    0x%08lx\n",
 			ipu_base + devtype->cpmem_ofs);
-	dev_info(&pdev->dev, "disp0:    0x%08lx\n",
+	dev_dbg(&pdev->dev, "disp0:    0x%08lx\n",
 			ipu_base + devtype->disp0_ofs);
-	dev_info(&pdev->dev, "disp1:    0x%08lx\n",
+	dev_dbg(&pdev->dev, "disp1:    0x%08lx\n",
 			ipu_base + devtype->disp1_ofs);
-	dev_info(&pdev->dev, "srm:      0x%08lx\n",
+	dev_dbg(&pdev->dev, "srm:      0x%08lx\n",
 			ipu_base + devtype->srm_ofs);
-	dev_info(&pdev->dev, "tpm:      0x%08lx\n",
+	dev_dbg(&pdev->dev, "tpm:      0x%08lx\n",
 			ipu_base + devtype->tpm_ofs);
-	dev_info(&pdev->dev, "dc:       0x%08lx\n",
+	dev_dbg(&pdev->dev, "dc:       0x%08lx\n",
 			ipu_base + devtype->cm_ofs + IPU_CM_DC_REG_OFS);
-	dev_info(&pdev->dev, "ic:       0x%08lx\n",
+	dev_dbg(&pdev->dev, "ic:       0x%08lx\n",
 			ipu_base + devtype->cm_ofs + IPU_CM_IC_REG_OFS);
-	dev_info(&pdev->dev, "dmfc:     0x%08lx\n",
+	dev_dbg(&pdev->dev, "dmfc:     0x%08lx\n",
 			ipu_base + devtype->cm_ofs + IPU_CM_DMFC_REG_OFS);
-	dev_info(&pdev->dev, "vdi:      0x%08lx\n",
+	dev_dbg(&pdev->dev, "vdi:      0x%08lx\n",
 			ipu_base + devtype->vdi_ofs);
 
 	ipu->cm_reg = devm_ioremap(&pdev->dev,
@@ -1098,6 +1121,8 @@ static int __devinit ipu_probe(struct platform_device *pdev)
 		goto failed_add_clients;
 	}
 
+	dev_info(&pdev->dev, "%s probed\n", devtype->name);
+
 	return 0;
 
 failed_add_clients:
@@ -1111,7 +1136,7 @@ failed_ioremap:
 	return ret;
 }
 
-static int __devexit ipu_remove(struct platform_device *pdev)
+static int ipu_remove(struct platform_device *pdev)
 {
 	struct ipu_soc *ipu = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -1133,7 +1158,7 @@ static struct platform_driver imx_ipu_driver = {
 		.of_match_table = imx_ipu_dt_ids,
 	},
 	.probe = ipu_probe,
-	.remove = __devexit_p(ipu_remove),
+	.remove = ipu_remove,
 };
 
 module_platform_driver(imx_ipu_driver);
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
index 78d3eda..1892006 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -116,7 +116,7 @@ static void ipu_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
 	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
 
-	dev_info(ipu_crtc->dev, "%s mode: %d\n", __func__, mode);
+	dev_dbg(ipu_crtc->dev, "%s mode: %d\n", __func__, mode);
 
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
@@ -530,7 +530,7 @@ err_put_resources:
 	return ret;
 }
 
-static int __devinit ipu_drm_probe(struct platform_device *pdev)
+static int ipu_drm_probe(struct platform_device *pdev)
 {
 	struct ipu_client_platformdata *pdata = pdev->dev.platform_data;
 	struct ipu_crtc *ipu_crtc;
@@ -554,7 +554,7 @@ static int __devinit ipu_drm_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit ipu_drm_remove(struct platform_device *pdev)
+static int ipu_drm_remove(struct platform_device *pdev)
 {
 	struct ipu_crtc *ipu_crtc = platform_get_drvdata(pdev);
 
@@ -570,7 +570,7 @@ static struct platform_driver ipu_drm_driver = {
 		.name = "imx-ipuv3-crtc",
 	},
 	.probe = ipu_drm_probe,
-	.remove = __devexit_p(ipu_drm_remove),
+	.remove = ipu_drm_remove,
 };
 module_platform_driver(ipu_drm_driver);
 
diff --git a/drivers/staging/imx-drm/parallel-display.c b/drivers/staging/imx-drm/parallel-display.c
index 9b51d73..a8064fc 100644
--- a/drivers/staging/imx-drm/parallel-display.c
+++ b/drivers/staging/imx-drm/parallel-display.c
@@ -23,6 +23,7 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <linux/videodev2.h>
+#include <linux/pinctrl/consumer.h>
 
 #include "imx-drm.h"
 
@@ -188,18 +189,27 @@ static int imx_pd_register(struct imx_parallel_display *imxpd)
 	return 0;
 }
 
-static int __devinit imx_pd_probe(struct platform_device *pdev)
+static int imx_pd_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	const u8 *edidp;
 	struct imx_parallel_display *imxpd;
 	int ret;
 	const char *fmt;
+	struct pinctrl *pinctrl;
 
 	imxpd = devm_kzalloc(&pdev->dev, sizeof(*imxpd), GFP_KERNEL);
 	if (!imxpd)
 		return -ENOMEM;
 
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl)) {
+		ret = PTR_ERR(pinctrl);
+		dev_warn(&pdev->dev, "pinctrl_get_select_default failed with %d",
+				ret);
+		return ret;
+	}
+
 	edidp = of_get_property(np, "edid", &imxpd->edid_len);
 	if (edidp)
 		imxpd->edid = kmemdup(edidp, imxpd->edid_len, GFP_KERNEL);
@@ -225,7 +235,7 @@ static int __devinit imx_pd_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit imx_pd_remove(struct platform_device *pdev)
+static int imx_pd_remove(struct platform_device *pdev)
 {
 	struct imx_parallel_display *imxpd = platform_get_drvdata(pdev);
 	struct drm_connector *connector = &imxpd->connector;
@@ -246,7 +256,7 @@ static const struct of_device_id imx_pd_dt_ids[] = {
 
 static struct platform_driver imx_pd_driver = {
 	.probe		= imx_pd_probe,
-	.remove		= __devexit_p(imx_pd_remove),
+	.remove		= imx_pd_remove,
 	.driver		= {
 		.of_match_table = imx_pd_dt_ids,
 		.name	= "imx-parallel-display",
diff --git a/drivers/staging/ipack/Kconfig b/drivers/staging/ipack/Kconfig
deleted file mode 100644
index 4cf4706..0000000
--- a/drivers/staging/ipack/Kconfig
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# IPACK configuration.
-#
-
-menuconfig IPACK_BUS
-	tristate "IndustryPack bus support"
-	depends on HAS_IOMEM
-	---help---
-	  If you say Y here you get support for the IndustryPack Framework
-	  for drivers for many types of boards that support this industrial
-	  bus. The IndustryPack Framework is a virtual bus allowing to
-	  communicate between carrier and mezzanine cards connected through
-	  this bus.
-
-if IPACK_BUS
-
-source "drivers/staging/ipack/bridges/Kconfig"
-
-source "drivers/staging/ipack/devices/Kconfig"
-
-endif # IPACK
diff --git a/drivers/staging/ipack/Makefile b/drivers/staging/ipack/Makefile
deleted file mode 100644
index 85ff223..0000000
--- a/drivers/staging/ipack/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the IPACK bridge device drivers.
-#
-obj-$(CONFIG_IPACK_BUS)		+= ipack.o
-obj-y				+= devices/
-obj-y				+= bridges/
diff --git a/drivers/staging/ipack/TODO b/drivers/staging/ipack/TODO
deleted file mode 100644
index ffafe69..0000000
--- a/drivers/staging/ipack/TODO
+++ /dev/null
@@ -1,22 +0,0 @@
-				TODO
-				====
-Introduction
-============
-
-These drivers add support for IndustryPack devices: carrier and IP module
-boards.
-
-The ipack driver is just an abstraction of the bus providing the common
-operations between the two kind of boards.
-
-TODO
-====
-
-checkpatch.pl warnings
-cleanup
-
-Contact
-=======
-
-Contact: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
-Mailing List: industrypack-devel@lists.sourceforge.net
diff --git a/drivers/staging/ipack/bridges/Kconfig b/drivers/staging/ipack/bridges/Kconfig
deleted file mode 100644
index 97c837e..0000000
--- a/drivers/staging/ipack/bridges/Kconfig
+++ /dev/null
@@ -1,8 +0,0 @@
-config BOARD_TPCI200
-	tristate "TEWS TPCI-200 support for IndustryPack bus"
-	depends on IPACK_BUS
-	depends on PCI
-	help
-	  This driver supports the TEWS TPCI200 device for the IndustryPack bus.
-	default n
-
diff --git a/drivers/staging/ipack/bridges/Makefile b/drivers/staging/ipack/bridges/Makefile
deleted file mode 100644
index d8b7645..0000000
--- a/drivers/staging/ipack/bridges/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_BOARD_TPCI200) += tpci200.o
diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c
deleted file mode 100644
index 46d6657..0000000
--- a/drivers/staging/ipack/bridges/tpci200.c
+++ /dev/null
@@ -1,780 +0,0 @@
-/**
- * tpci200.c
- *
- * driver for the TEWS TPCI-200 device
- * Copyright (c) 2009 Nicolas Serafini, EIC2 SA
- * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN
- * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia
- *
- * This program is free software; 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/module.h>
-#include <linux/slab.h>
-#include "tpci200.h"
-
-static u16 tpci200_status_timeout[] = {
-	TPCI200_A_TIMEOUT,
-	TPCI200_B_TIMEOUT,
-	TPCI200_C_TIMEOUT,
-	TPCI200_D_TIMEOUT,
-};
-
-static u16 tpci200_status_error[] = {
-	TPCI200_A_ERROR,
-	TPCI200_B_ERROR,
-	TPCI200_C_ERROR,
-	TPCI200_D_ERROR,
-};
-
-static struct tpci200_board *check_slot(struct ipack_device *dev)
-{
-	struct tpci200_board *tpci200;
-
-	if (dev == NULL)
-		return NULL;
-
-
-	tpci200 = dev_get_drvdata(dev->bus->parent);
-
-	if (tpci200 == NULL) {
-		dev_info(&dev->dev, "carrier board not found\n");
-		return NULL;
-	}
-
-	if (dev->slot >= TPCI200_NB_SLOT) {
-		dev_info(&dev->dev,
-			 "Slot [%d:%d] doesn't exist! Last tpci200 slot is %d.\n",
-			 dev->bus_nr, dev->slot, TPCI200_NB_SLOT-1);
-		return NULL;
-	}
-
-	return tpci200;
-}
-
-static void tpci200_clear_mask(struct tpci200_board *tpci200,
-			       __le16 __iomem *addr, u16 mask)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&tpci200->regs_lock, flags);
-	iowrite16(ioread16(addr) & (~mask), addr);
-	spin_unlock_irqrestore(&tpci200->regs_lock, flags);
-}
-
-static void tpci200_set_mask(struct tpci200_board *tpci200,
-			     __le16 __iomem *addr, u16 mask)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&tpci200->regs_lock, flags);
-	iowrite16(ioread16(addr) | mask, addr);
-	spin_unlock_irqrestore(&tpci200->regs_lock, flags);
-}
-
-static void tpci200_unregister(struct tpci200_board *tpci200)
-{
-	int i;
-
-	free_irq(tpci200->info->pdev->irq, (void *) tpci200);
-
-	pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs);
-	pci_iounmap(tpci200->info->pdev, tpci200->info->ioidint_space);
-	pci_iounmap(tpci200->info->pdev, tpci200->info->mem8_space);
-	pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
-
-	pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
-	pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
-	pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
-	pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR);
-
-	pci_disable_device(tpci200->info->pdev);
-	pci_dev_put(tpci200->info->pdev);
-
-	for (i = 0; i < TPCI200_NB_SLOT; i++) {
-		tpci200->slots[i].io_phys.address = NULL;
-		tpci200->slots[i].io_phys.size = 0;
-		tpci200->slots[i].id_phys.address = NULL;
-		tpci200->slots[i].id_phys.size = 0;
-		tpci200->slots[i].int_phys.address = NULL;
-		tpci200->slots[i].int_phys.size = 0;
-		tpci200->slots[i].mem_phys.address = NULL;
-		tpci200->slots[i].mem_phys.size = 0;
-	}
-}
-
-static void tpci200_enable_irq(struct tpci200_board *tpci200,
-			       int islot)
-{
-	tpci200_set_mask(tpci200,
-			&tpci200->info->interface_regs->control[islot],
-			TPCI200_INT0_EN | TPCI200_INT1_EN);
-}
-
-static void tpci200_disable_irq(struct tpci200_board *tpci200,
-				int islot)
-{
-	tpci200_clear_mask(tpci200,
-			&tpci200->info->interface_regs->control[islot],
-			TPCI200_INT0_EN | TPCI200_INT1_EN);
-}
-
-static irqreturn_t tpci200_slot_irq(struct slot_irq *slot_irq)
-{
-	irqreturn_t ret;
-
-	if (!slot_irq)
-		return -ENODEV;
-	ret = slot_irq->handler(slot_irq->arg);
-
-	return ret;
-}
-
-static irqreturn_t tpci200_interrupt(int irq, void *dev_id)
-{
-	struct tpci200_board *tpci200 = (struct tpci200_board *) dev_id;
-	struct slot_irq *slot_irq;
-	irqreturn_t ret;
-	u16 status_reg;
-	int i;
-
-	/* Read status register */
-	status_reg = ioread16(&tpci200->info->interface_regs->status);
-
-	/* Did we cause the interrupt? */
-	if (!(status_reg & TPCI200_SLOT_INT_MASK))
-		return IRQ_NONE;
-
-	/* callback to the IRQ handler for the corresponding slot */
-	rcu_read_lock();
-	for (i = 0; i < TPCI200_NB_SLOT; i++) {
-		if (!(status_reg & ((TPCI200_A_INT0 | TPCI200_A_INT1) << (2 * i))))
-			continue;
-		slot_irq = rcu_dereference(tpci200->slots[i].irq);
-		ret = tpci200_slot_irq(slot_irq);
-		if (ret == -ENODEV) {
-			dev_info(&tpci200->info->pdev->dev,
-				 "No registered ISR for slot [%d:%d]!. IRQ will be disabled.\n",
-				 tpci200->number, i);
-			tpci200_disable_irq(tpci200, i);
-		}
-	}
-	rcu_read_unlock();
-
-	return IRQ_HANDLED;
-}
-
-static int tpci200_free_irq(struct ipack_device *dev)
-{
-	struct slot_irq *slot_irq;
-	struct tpci200_board *tpci200;
-
-	tpci200 = check_slot(dev);
-	if (tpci200 == NULL)
-		return -EINVAL;
-
-	if (mutex_lock_interruptible(&tpci200->mutex))
-		return -ERESTARTSYS;
-
-	if (tpci200->slots[dev->slot].irq == NULL) {
-		mutex_unlock(&tpci200->mutex);
-		return -EINVAL;
-	}
-
-	tpci200_disable_irq(tpci200, dev->slot);
-	slot_irq = tpci200->slots[dev->slot].irq;
-	/* uninstall handler */
-	RCU_INIT_POINTER(tpci200->slots[dev->slot].irq, NULL);
-	synchronize_rcu();
-	kfree(slot_irq);
-	mutex_unlock(&tpci200->mutex);
-	return 0;
-}
-
-static int tpci200_request_irq(struct ipack_device *dev,
-			       irqreturn_t (*handler)(void *), void *arg)
-{
-	int res = 0;
-	struct slot_irq *slot_irq;
-	struct tpci200_board *tpci200;
-
-	tpci200 = check_slot(dev);
-	if (tpci200 == NULL)
-		return -EINVAL;
-
-	if (mutex_lock_interruptible(&tpci200->mutex))
-		return -ERESTARTSYS;
-
-	if (tpci200->slots[dev->slot].irq != NULL) {
-		dev_err(&dev->dev,
-			"Slot [%d:%d] IRQ already registered !\n", dev->bus_nr,
-			dev->slot);
-		res = -EINVAL;
-		goto out_unlock;
-	}
-
-	slot_irq = kzalloc(sizeof(struct slot_irq), GFP_KERNEL);
-	if (slot_irq == NULL) {
-		dev_err(&dev->dev,
-			"Slot [%d:%d] unable to allocate memory for IRQ !\n",
-			dev->bus_nr, dev->slot);
-		res = -ENOMEM;
-		goto out_unlock;
-	}
-
-	/*
-	 * WARNING: Setup Interrupt Vector in the IndustryPack device
-	 * before an IRQ request.
-	 * Read the User Manual of your IndustryPack device to know
-	 * where to write the vector in memory.
-	 */
-	slot_irq->handler = handler;
-	slot_irq->arg = arg;
-	slot_irq->holder = dev;
-
-	rcu_assign_pointer(tpci200->slots[dev->slot].irq, slot_irq);
-	tpci200_enable_irq(tpci200, dev->slot);
-
-out_unlock:
-	mutex_unlock(&tpci200->mutex);
-	return res;
-}
-
-static int tpci200_register(struct tpci200_board *tpci200)
-{
-	int i;
-	int res;
-	unsigned long ioidint_base;
-	unsigned long mem_base;
-	unsigned short slot_ctrl;
-
-	if (pci_enable_device(tpci200->info->pdev) < 0)
-		return -ENODEV;
-
-	/* Request IP interface register (Bar 2) */
-	res = pci_request_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR,
-				 "Carrier IP interface registers");
-	if (res) {
-		dev_err(&tpci200->info->pdev->dev,
-			"(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 !",
-			tpci200->info->pdev->bus->number,
-			tpci200->info->pdev->devfn);
-		goto out_disable_pci;
-	}
-
-	/* Request IO ID INT space (Bar 3) */
-	res = pci_request_region(tpci200->info->pdev,
-				 TPCI200_IO_ID_INT_SPACES_BAR,
-				 "Carrier IO ID INT space");
-	if (res) {
-		dev_err(&tpci200->info->pdev->dev,
-			"(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 3 !",
-			tpci200->info->pdev->bus->number,
-			tpci200->info->pdev->devfn);
-		goto out_release_ip_space;
-	}
-
-	/* Request MEM space (Bar 4) */
-	res = pci_request_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR,
-				 "Carrier MEM space");
-	if (res) {
-		dev_err(&tpci200->info->pdev->dev,
-			"(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!",
-			tpci200->info->pdev->bus->number,
-			tpci200->info->pdev->devfn);
-		goto out_release_ioid_int_space;
-	}
-
-	/* Map internal tpci200 driver user space */
-	tpci200->info->interface_regs =
-		ioremap_nocache(pci_resource_start(tpci200->info->pdev,
-					   TPCI200_IP_INTERFACE_BAR),
-			TPCI200_IFACE_SIZE);
-	tpci200->info->ioidint_space =
-		ioremap_nocache(pci_resource_start(tpci200->info->pdev,
-					   TPCI200_IO_ID_INT_SPACES_BAR),
-			TPCI200_IOIDINT_SIZE);
-	tpci200->info->mem8_space =
-		ioremap_nocache(pci_resource_start(tpci200->info->pdev,
-					   TPCI200_MEM8_SPACE_BAR),
-			TPCI200_MEM8_SIZE);
-
-	/* Initialize lock that protects interface_regs */
-	spin_lock_init(&tpci200->regs_lock);
-
-	ioidint_base = pci_resource_start(tpci200->info->pdev,
-					  TPCI200_IO_ID_INT_SPACES_BAR);
-	mem_base = pci_resource_start(tpci200->info->pdev,
-				      TPCI200_MEM8_SPACE_BAR);
-
-	/* Set the default parameters of the slot
-	 * INT0 disabled, level sensitive
-	 * INT1 disabled, level sensitive
-	 * error interrupt disabled
-	 * timeout interrupt disabled
-	 * recover time disabled
-	 * clock rate 8 MHz
-	 */
-	slot_ctrl = 0;
-
-	/* Set all slot physical address space */
-	for (i = 0; i < TPCI200_NB_SLOT; i++) {
-		tpci200->slots[i].io_phys.address =
-			(void __iomem *)ioidint_base +
-			TPCI200_IO_SPACE_OFF + TPCI200_IO_SPACE_GAP*i;
-		tpci200->slots[i].io_phys.size = TPCI200_IO_SPACE_SIZE;
-
-		tpci200->slots[i].id_phys.address =
-			(void __iomem *)ioidint_base +
-			TPCI200_ID_SPACE_OFF + TPCI200_ID_SPACE_GAP*i;
-		tpci200->slots[i].id_phys.size = TPCI200_ID_SPACE_SIZE;
-
-		tpci200->slots[i].int_phys.address =
-			(void __iomem *)ioidint_base +
-			TPCI200_INT_SPACE_OFF + TPCI200_INT_SPACE_GAP * i;
-		tpci200->slots[i].int_phys.size = TPCI200_INT_SPACE_SIZE;
-
-		tpci200->slots[i].mem_phys.address =
-			(void __iomem *)mem_base + TPCI200_MEM8_GAP*i;
-		tpci200->slots[i].mem_phys.size = TPCI200_MEM8_SIZE;
-
-		writew(slot_ctrl, &tpci200->info->interface_regs->control[i]);
-	}
-
-	res = request_irq(tpci200->info->pdev->irq,
-			  tpci200_interrupt, IRQF_SHARED,
-			  KBUILD_MODNAME, (void *) tpci200);
-	if (res) {
-		dev_err(&tpci200->info->pdev->dev,
-			"(bn 0x%X, sn 0x%X) unable to register IRQ !",
-			tpci200->info->pdev->bus->number,
-			tpci200->info->pdev->devfn);
-		goto out_release_ioid_int_space;
-	}
-
-	return 0;
-
-out_release_ioid_int_space:
-	pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
-out_release_ip_space:
-	pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
-out_disable_pci:
-	pci_disable_device(tpci200->info->pdev);
-	return res;
-}
-
-static int tpci200_slot_unmap_space(struct ipack_device *dev, int space)
-{
-	struct ipack_addr_space *virt_addr_space;
-	struct tpci200_board *tpci200;
-
-	tpci200 = check_slot(dev);
-	if (tpci200 == NULL)
-		return -EINVAL;
-
-	if (mutex_lock_interruptible(&tpci200->mutex))
-		return -ERESTARTSYS;
-
-	switch (space) {
-	case IPACK_IO_SPACE:
-		if (dev->io_space.address == NULL) {
-			dev_info(&dev->dev,
-				 "Slot [%d:%d] IO space not mapped !\n",
-				 dev->bus_nr, dev->slot);
-			goto out_unlock;
-		}
-		virt_addr_space = &dev->io_space;
-		break;
-	case IPACK_ID_SPACE:
-		if (dev->id_space.address == NULL) {
-			dev_info(&dev->dev,
-				 "Slot [%d:%d] ID space not mapped !\n",
-				 dev->bus_nr, dev->slot);
-			goto out_unlock;
-		}
-		virt_addr_space = &dev->id_space;
-		break;
-	case IPACK_INT_SPACE:
-		if (dev->int_space.address == NULL) {
-			dev_info(&dev->dev,
-				 "Slot [%d:%d] INT space not mapped !\n",
-				 dev->bus_nr, dev->slot);
-			goto out_unlock;
-		}
-		virt_addr_space = &dev->int_space;
-		break;
-	case IPACK_MEM_SPACE:
-		if (dev->mem_space.address == NULL) {
-			dev_info(&dev->dev,
-				 "Slot [%d:%d] MEM space not mapped !\n",
-				 dev->bus_nr, dev->slot);
-			goto out_unlock;
-		}
-		virt_addr_space = &dev->mem_space;
-		break;
-	default:
-		dev_err(&dev->dev,
-			"Slot [%d:%d] space number %d doesn't exist !\n",
-			dev->bus_nr, dev->slot, space);
-		mutex_unlock(&tpci200->mutex);
-		return -EINVAL;
-	}
-
-	iounmap(virt_addr_space->address);
-
-	virt_addr_space->address = NULL;
-	virt_addr_space->size = 0;
-out_unlock:
-	mutex_unlock(&tpci200->mutex);
-	return 0;
-}
-
-static int tpci200_slot_map_space(struct ipack_device *dev,
-				  unsigned int memory_size, int space)
-{
-	int res = 0;
-	unsigned int size_to_map;
-	void __iomem *phys_address;
-	struct ipack_addr_space *virt_addr_space;
-	struct tpci200_board *tpci200;
-
-	tpci200 = check_slot(dev);
-	if (tpci200 == NULL)
-		return -EINVAL;
-
-	if (mutex_lock_interruptible(&tpci200->mutex))
-		return -ERESTARTSYS;
-
-	switch (space) {
-	case IPACK_IO_SPACE:
-		if (dev->io_space.address != NULL) {
-			dev_err(&dev->dev,
-				"Slot [%d:%d] IO space already mapped !\n",
-				tpci200->number, dev->slot);
-			res = -EINVAL;
-			goto out_unlock;
-		}
-		virt_addr_space = &dev->io_space;
-
-		phys_address = tpci200->slots[dev->slot].io_phys.address;
-		size_to_map = tpci200->slots[dev->slot].io_phys.size;
-		break;
-	case IPACK_ID_SPACE:
-		if (dev->id_space.address != NULL) {
-			dev_err(&dev->dev,
-				"Slot [%d:%d] ID space already mapped !\n",
-				tpci200->number, dev->slot);
-			res = -EINVAL;
-			goto out_unlock;
-		}
-		virt_addr_space = &dev->id_space;
-
-		phys_address = tpci200->slots[dev->slot].id_phys.address;
-		size_to_map = tpci200->slots[dev->slot].id_phys.size;
-		break;
-	case IPACK_INT_SPACE:
-		if (dev->int_space.address != NULL) {
-			dev_err(&dev->dev,
-				"Slot [%d:%d] INT space already mapped !\n",
-				tpci200->number, dev->slot);
-			res = -EINVAL;
-			goto out_unlock;
-		}
-		virt_addr_space = &dev->int_space;
-
-		phys_address = tpci200->slots[dev->slot].int_phys.address;
-		size_to_map = tpci200->slots[dev->slot].int_phys.size;
-		break;
-	case IPACK_MEM_SPACE:
-		if (dev->mem_space.address != NULL) {
-			dev_err(&dev->dev,
-				"Slot [%d:%d] MEM space already mapped !\n",
-				tpci200->number, dev->slot);
-			res = -EINVAL;
-			goto out_unlock;
-		}
-		virt_addr_space = &dev->mem_space;
-
-		if (memory_size > tpci200->slots[dev->slot].mem_phys.size) {
-			dev_err(&dev->dev,
-				"Slot [%d:%d] request is 0x%X memory, only 0x%X available !\n",
-				dev->bus_nr, dev->slot, memory_size,
-				tpci200->slots[dev->slot].mem_phys.size);
-			res = -EINVAL;
-			goto out_unlock;
-		}
-
-		phys_address = tpci200->slots[dev->slot].mem_phys.address;
-		size_to_map = memory_size;
-		break;
-	default:
-		dev_err(&dev->dev, "Slot [%d:%d] space %d doesn't exist !\n",
-			tpci200->number, dev->slot, space);
-		res = -EINVAL;
-		goto out_unlock;
-	}
-
-	virt_addr_space->size = size_to_map;
-	virt_addr_space->address =
-		ioremap_nocache((unsigned long)phys_address, size_to_map);
-
-out_unlock:
-	mutex_unlock(&tpci200->mutex);
-	return res;
-}
-
-static int tpci200_get_clockrate(struct ipack_device *dev)
-{
-	struct tpci200_board *tpci200 = check_slot(dev);
-	__le16 __iomem *addr;
-
-	if (!tpci200)
-		return -ENODEV;
-
-	addr = &tpci200->info->interface_regs->control[dev->slot];
-	return (ioread16(addr) & TPCI200_CLK32) ? 32 : 8;
-}
-
-static int tpci200_set_clockrate(struct ipack_device *dev, int mherz)
-{
-	struct tpci200_board *tpci200 = check_slot(dev);
-	__le16 __iomem *addr;
-
-	if (!tpci200)
-		return -ENODEV;
-
-	addr = &tpci200->info->interface_regs->control[dev->slot];
-
-	switch (mherz) {
-	case 8:
-		tpci200_clear_mask(tpci200, addr, TPCI200_CLK32);
-		break;
-	case 32:
-		tpci200_set_mask(tpci200, addr, TPCI200_CLK32);
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int tpci200_get_error(struct ipack_device *dev)
-{
-	struct tpci200_board *tpci200 = check_slot(dev);
-	__le16 __iomem *addr;
-	u16 mask;
-
-	if (!tpci200)
-		return -ENODEV;
-
-	addr = &tpci200->info->interface_regs->status;
-	mask = tpci200_status_error[dev->slot];
-	return (ioread16(addr) & mask) ? 1 : 0;
-}
-
-static int tpci200_get_timeout(struct ipack_device *dev)
-{
-	struct tpci200_board *tpci200 = check_slot(dev);
-	__le16 __iomem *addr;
-	u16 mask;
-
-	if (!tpci200)
-		return -ENODEV;
-
-	addr = &tpci200->info->interface_regs->status;
-	mask = tpci200_status_timeout[dev->slot];
-
-	return (ioread16(addr) & mask) ? 1 : 0;
-}
-
-static int tpci200_reset_timeout(struct ipack_device *dev)
-{
-	struct tpci200_board *tpci200 = check_slot(dev);
-	__le16 __iomem *addr;
-	u16 mask;
-
-	if (!tpci200)
-		return -ENODEV;
-
-	addr = &tpci200->info->interface_regs->status;
-	mask = tpci200_status_timeout[dev->slot];
-
-	iowrite16(mask, addr);
-	return 0;
-}
-
-static void tpci200_uninstall(struct tpci200_board *tpci200)
-{
-	tpci200_unregister(tpci200);
-	kfree(tpci200->slots);
-}
-
-static const struct ipack_bus_ops tpci200_bus_ops = {
-	.map_space = tpci200_slot_map_space,
-	.unmap_space = tpci200_slot_unmap_space,
-	.request_irq = tpci200_request_irq,
-	.free_irq = tpci200_free_irq,
-	.get_clockrate = tpci200_get_clockrate,
-	.set_clockrate = tpci200_set_clockrate,
-	.get_error     = tpci200_get_error,
-	.get_timeout   = tpci200_get_timeout,
-	.reset_timeout = tpci200_reset_timeout,
-};
-
-static int tpci200_install(struct tpci200_board *tpci200)
-{
-	int res;
-
-	tpci200->slots = kzalloc(
-		TPCI200_NB_SLOT * sizeof(struct tpci200_slot), GFP_KERNEL);
-	if (tpci200->slots == NULL)
-		return -ENOMEM;
-
-	res = tpci200_register(tpci200);
-	if (res) {
-		kfree(tpci200->slots);
-		tpci200->slots = NULL;
-		return res;
-	}
-
-	mutex_init(&tpci200->mutex);
-	return 0;
-}
-
-static int tpci200_pci_probe(struct pci_dev *pdev,
-			     const struct pci_device_id *id)
-{
-	int ret, i;
-	struct tpci200_board *tpci200;
-	u32 reg32;
-
-	tpci200 = kzalloc(sizeof(struct tpci200_board), GFP_KERNEL);
-	if (!tpci200)
-		return -ENOMEM;
-
-	tpci200->info = kzalloc(sizeof(struct tpci200_infos), GFP_KERNEL);
-	if (!tpci200->info) {
-		ret = -ENOMEM;
-		goto out_err_info;
-	}
-
-	pci_dev_get(pdev);
-
-	/* Obtain a mapping of the carrier's PCI configuration registers */
-	ret = pci_request_region(pdev, TPCI200_CFG_MEM_BAR,
-				 KBUILD_MODNAME " Configuration Memory");
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to allocate PCI Configuration Memory");
-		ret = -EBUSY;
-		goto out_err_pci_request;
-	}
-	tpci200->info->cfg_regs = ioremap_nocache(
-			pci_resource_start(pdev, TPCI200_CFG_MEM_BAR),
-			pci_resource_len(pdev, TPCI200_CFG_MEM_BAR));
-	if (!tpci200->info->cfg_regs) {
-		dev_err(&pdev->dev, "Failed to map PCI Configuration Memory");
-		ret = -EFAULT;
-		goto out_err_ioremap;
-	}
-
-	/* Disable byte swapping for 16 bit IP module access. This will ensure
-	 * that the Industrypack big endian byte order is preserved by the
-	 * carrier. */
-	reg32 = ioread32(tpci200->info->cfg_regs + LAS1_DESC);
-	reg32 |= 1 << LAS_BIT_BIGENDIAN;
-	iowrite32(reg32, tpci200->info->cfg_regs + LAS1_DESC);
-
-	reg32 = ioread32(tpci200->info->cfg_regs + LAS2_DESC);
-	reg32 |= 1 << LAS_BIT_BIGENDIAN;
-	iowrite32(reg32, tpci200->info->cfg_regs + LAS2_DESC);
-
-	/* Save struct pci_dev pointer */
-	tpci200->info->pdev = pdev;
-	tpci200->info->id_table = (struct pci_device_id *)id;
-
-	/* register the device and initialize it */
-	ret = tpci200_install(tpci200);
-	if (ret) {
-		dev_err(&pdev->dev, "error during tpci200 install\n");
-		ret = -ENODEV;
-		goto out_err_install;
-	}
-
-	/* Register the carrier in the industry pack bus driver */
-	tpci200->info->ipack_bus = ipack_bus_register(&pdev->dev,
-						      TPCI200_NB_SLOT,
-						      &tpci200_bus_ops);
-	if (!tpci200->info->ipack_bus) {
-		dev_err(&pdev->dev,
-			"error registering the carrier on ipack driver\n");
-		ret = -EFAULT;
-		goto out_err_bus_register;
-	}
-
-	/* save the bus number given by ipack to logging purpose */
-	tpci200->number = tpci200->info->ipack_bus->bus_nr;
-	dev_set_drvdata(&pdev->dev, tpci200);
-
-	for (i = 0; i < TPCI200_NB_SLOT; i++)
-		ipack_device_register(tpci200->info->ipack_bus, i);
-	return 0;
-
-out_err_bus_register:
-	tpci200_uninstall(tpci200);
-out_err_install:
-	iounmap(tpci200->info->cfg_regs);
-out_err_ioremap:
-	pci_release_region(pdev, TPCI200_CFG_MEM_BAR);
-out_err_pci_request:
-	pci_dev_put(pdev);
-	kfree(tpci200->info);
-out_err_info:
-	kfree(tpci200);
-	return ret;
-}
-
-static void __tpci200_pci_remove(struct tpci200_board *tpci200)
-{
-	ipack_bus_unregister(tpci200->info->ipack_bus);
-	tpci200_uninstall(tpci200);
-
-	kfree(tpci200->info);
-	kfree(tpci200);
-}
-
-static void __devexit tpci200_pci_remove(struct pci_dev *dev)
-{
-	struct tpci200_board *tpci200 = pci_get_drvdata(dev);
-
-	__tpci200_pci_remove(tpci200);
-}
-
-static DEFINE_PCI_DEVICE_TABLE(tpci200_idtable) = {
-	{ TPCI200_VENDOR_ID, TPCI200_DEVICE_ID, TPCI200_SUBVENDOR_ID,
-	  TPCI200_SUBDEVICE_ID },
-	{ 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, tpci200_idtable);
-
-static struct pci_driver tpci200_pci_drv = {
-	.name = "tpci200",
-	.id_table = tpci200_idtable,
-	.probe = tpci200_pci_probe,
-	.remove = __devexit_p(tpci200_pci_remove),
-};
-
-static int __init tpci200_drvr_init_module(void)
-{
-	return pci_register_driver(&tpci200_pci_drv);
-}
-
-static void __exit tpci200_drvr_exit_module(void)
-{
-	pci_unregister_driver(&tpci200_pci_drv);
-}
-
-MODULE_DESCRIPTION("TEWS TPCI-200 device driver");
-MODULE_LICENSE("GPL");
-module_init(tpci200_drvr_init_module);
-module_exit(tpci200_drvr_exit_module);
diff --git a/drivers/staging/ipack/bridges/tpci200.h b/drivers/staging/ipack/bridges/tpci200.h
deleted file mode 100644
index 235d1fe..0000000
--- a/drivers/staging/ipack/bridges/tpci200.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/**
- * tpci200.h
- *
- * driver for the carrier TEWS TPCI-200
- * Copyright (c) 2009 Nicolas Serafini, EIC2 SA
- * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN
- * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia
- *
- * This program is free software; 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 _TPCI200_H_
-#define _TPCI200_H_
-
-#include <linux/limits.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/swab.h>
-#include <linux/io.h>
-
-#include "../ipack.h"
-
-#define TPCI200_NB_SLOT               0x4
-#define TPCI200_NB_BAR                0x6
-
-#define TPCI200_VENDOR_ID             0x1498
-#define TPCI200_DEVICE_ID             0x30C8
-#define TPCI200_SUBVENDOR_ID          0x1498
-#define TPCI200_SUBDEVICE_ID          0x300A
-
-#define TPCI200_CFG_MEM_BAR           0
-#define TPCI200_IP_INTERFACE_BAR      2
-#define TPCI200_IO_ID_INT_SPACES_BAR  3
-#define TPCI200_MEM16_SPACE_BAR       4
-#define TPCI200_MEM8_SPACE_BAR        5
-
-struct tpci200_regs {
-	__le16	revision;
-	/* writes to control should occur with the mutex held to protect
-	 * read-modify-write operations */
-	__le16  control[4];
-	__le16	reset;
-	__le16	status;
-	u8	reserved[242];
-} __packed;
-
-#define TPCI200_IFACE_SIZE            0x100
-
-#define TPCI200_IO_SPACE_OFF          0x0000
-#define TPCI200_IO_SPACE_GAP          0x0100
-#define TPCI200_IO_SPACE_SIZE         0x0080
-#define TPCI200_ID_SPACE_OFF          0x0080
-#define TPCI200_ID_SPACE_GAP          0x0100
-#define TPCI200_ID_SPACE_SIZE         0x0040
-#define TPCI200_INT_SPACE_OFF         0x00C0
-#define TPCI200_INT_SPACE_GAP         0x0100
-#define TPCI200_INT_SPACE_SIZE        0x0040
-#define TPCI200_IOIDINT_SIZE          0x0400
-
-#define TPCI200_MEM8_GAP              0x00400000
-#define TPCI200_MEM8_SIZE             0x00400000
-#define TPCI200_MEM16_GAP             0x00800000
-#define TPCI200_MEM16_SIZE            0x00800000
-
-/* control field in tpci200_regs */
-#define TPCI200_INT0_EN               0x0040
-#define TPCI200_INT1_EN               0x0080
-#define TPCI200_INT0_EDGE             0x0010
-#define TPCI200_INT1_EDGE             0x0020
-#define TPCI200_ERR_INT_EN            0x0008
-#define TPCI200_TIME_INT_EN           0x0004
-#define TPCI200_RECOVER_EN            0x0002
-#define TPCI200_CLK32                 0x0001
-
-/* reset field in tpci200_regs */
-#define TPCI200_A_RESET               0x0001
-#define TPCI200_B_RESET               0x0002
-#define TPCI200_C_RESET               0x0004
-#define TPCI200_D_RESET               0x0008
-
-/* status field in tpci200_regs */
-#define TPCI200_A_TIMEOUT             0x1000
-#define TPCI200_B_TIMEOUT             0x2000
-#define TPCI200_C_TIMEOUT             0x4000
-#define TPCI200_D_TIMEOUT             0x8000
-
-#define TPCI200_A_ERROR               0x0100
-#define TPCI200_B_ERROR               0x0200
-#define TPCI200_C_ERROR               0x0400
-#define TPCI200_D_ERROR               0x0800
-
-#define TPCI200_A_INT0                0x0001
-#define TPCI200_A_INT1                0x0002
-#define TPCI200_B_INT0                0x0004
-#define TPCI200_B_INT1                0x0008
-#define TPCI200_C_INT0                0x0010
-#define TPCI200_C_INT1                0x0020
-#define TPCI200_D_INT0                0x0040
-#define TPCI200_D_INT1                0x0080
-
-#define TPCI200_SLOT_INT_MASK         0x00FF
-
-/* PCI Configuration registers. The PCI bridge is a PLX Technology PCI9030. */
-#define LAS1_DESC		      0x2C
-#define LAS2_DESC		      0x30
-
-/* Bits in the LAS?_DESC registers */
-#define LAS_BIT_BIGENDIAN	      24
-
-#define VME_IOID_SPACE  "IOID"
-#define VME_MEM_SPACE  "MEM"
-
-/**
- * struct slot_irq - slot IRQ definition.
- * @vector	Vector number
- * @handler	Handler called when IRQ arrives
- * @arg		Handler argument
- *
- */
-struct slot_irq {
-	struct ipack_device *holder;
-	int		vector;
-	irqreturn_t	(*handler)(void *);
-	void		*arg;
-};
-
-/**
- * struct tpci200_slot - data specific to the tpci200 slot.
- * @slot_id	Slot identification gived to external interface
- * @irq		Slot IRQ infos
- * @io_phys	IO physical base address register of the slot
- * @id_phys	ID physical base address register of the slot
- * @int_phys	INT physical base address register of the slot
- * @mem_phys	MEM physical base address register of the slot
- *
- */
-struct tpci200_slot {
-	struct slot_irq		*irq;
-	struct ipack_addr_space io_phys;
-	struct ipack_addr_space id_phys;
-	struct ipack_addr_space int_phys;
-	struct ipack_addr_space mem_phys;
-};
-
-/**
- * struct tpci200_infos - informations specific of the TPCI200 tpci200.
- * @pci_dev		PCI device
- * @interface_regs	Pointer to IP interface space (Bar 2)
- * @ioidint_space	Pointer to IP ID, IO and INT space (Bar 3)
- * @mem8_space		Pointer to MEM space (Bar 4)
- *
- */
-struct tpci200_infos {
-	struct pci_dev			*pdev;
-	struct pci_device_id		*id_table;
-	struct tpci200_regs __iomem	*interface_regs;
-	void __iomem			*ioidint_space;
-	void __iomem			*mem8_space;
-	void __iomem			*cfg_regs;
-	struct ipack_bus_device		*ipack_bus;
-};
-struct tpci200_board {
-	unsigned int		number;
-	struct mutex		mutex;
-	spinlock_t		regs_lock;
-	struct tpci200_slot	*slots;
-	struct tpci200_infos	*info;
-};
-
-#endif /* _TPCI200_H_ */
diff --git a/drivers/staging/ipack/devices/Kconfig b/drivers/staging/ipack/devices/Kconfig
deleted file mode 100644
index 39f7188..0000000
--- a/drivers/staging/ipack/devices/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-config SERIAL_IPOCTAL
-	tristate "IndustryPack IP-OCTAL uart support"
-	depends on IPACK_BUS
-	help
-	  This driver supports the IPOCTAL serial port device for the IndustryPack bus.
-	default n
-
diff --git a/drivers/staging/ipack/devices/Makefile b/drivers/staging/ipack/devices/Makefile
deleted file mode 100644
index 6de18bd..0000000
--- a/drivers/staging/ipack/devices/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_SERIAL_IPOCTAL) += ipoctal.o
diff --git a/drivers/staging/ipack/devices/ipoctal.c b/drivers/staging/ipack/devices/ipoctal.c
deleted file mode 100644
index d751edf..0000000
--- a/drivers/staging/ipack/devices/ipoctal.c
+++ /dev/null
@@ -1,796 +0,0 @@
-/**
- * ipoctal.c
- *
- * driver for the GE IP-OCTAL boards
- * Copyright (c) 2009 Nicolas Serafini, EIC2 SA
- * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN
- * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia
- *
- * This program is free software; 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/device.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/tty_flip.h>
-#include <linux/slab.h>
-#include <linux/atomic.h>
-#include <linux/io.h>
-#include "../ipack.h"
-#include "ipoctal.h"
-#include "scc2698.h"
-
-#define IP_OCTAL_ID_SPACE_VECTOR    0x41
-#define IP_OCTAL_NB_BLOCKS          4
-
-static const struct tty_operations ipoctal_fops;
-
-struct ipoctal_channel {
-	struct ipoctal_stats		stats;
-	unsigned int			nb_bytes;
-	wait_queue_head_t		queue;
-	spinlock_t			lock;
-	unsigned int			pointer_read;
-	unsigned int			pointer_write;
-	atomic_t			open;
-	struct tty_port			tty_port;
-	union scc2698_channel __iomem	*regs;
-	union scc2698_block __iomem	*block_regs;
-	unsigned int			board_id;
-	unsigned char			*board_write;
-	u8				isr_rx_rdy_mask;
-	u8				isr_tx_rdy_mask;
-};
-
-struct ipoctal {
-	struct ipack_device		*dev;
-	unsigned int			board_id;
-	struct ipoctal_channel		channel[NR_CHANNELS];
-	unsigned char			write;
-	struct tty_driver		*tty_drv;
-};
-
-static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty)
-{
-	struct ipoctal_channel *channel;
-
-	channel = dev_get_drvdata(tty->dev);
-
-	iowrite8(CR_ENABLE_RX, &channel->regs->w.cr);
-	return 0;
-}
-
-static int ipoctal_open(struct tty_struct *tty, struct file *file)
-{
-	int res;
-	struct ipoctal_channel *channel;
-
-	channel = dev_get_drvdata(tty->dev);
-
-	if (atomic_read(&channel->open))
-		return -EBUSY;
-
-	tty->driver_data = channel;
-
-	res = tty_port_open(&channel->tty_port, tty, file);
-	if (res)
-		return res;
-
-	atomic_inc(&channel->open);
-	return 0;
-}
-
-static void ipoctal_reset_stats(struct ipoctal_stats *stats)
-{
-	stats->tx = 0;
-	stats->rx = 0;
-	stats->rcv_break = 0;
-	stats->framing_err = 0;
-	stats->overrun_err = 0;
-	stats->parity_err = 0;
-}
-
-static void ipoctal_free_channel(struct ipoctal_channel *channel)
-{
-	ipoctal_reset_stats(&channel->stats);
-	channel->pointer_read = 0;
-	channel->pointer_write = 0;
-	channel->nb_bytes = 0;
-}
-
-static void ipoctal_close(struct tty_struct *tty, struct file *filp)
-{
-	struct ipoctal_channel *channel = tty->driver_data;
-
-	tty_port_close(&channel->tty_port, tty, filp);
-
-	if (atomic_dec_and_test(&channel->open))
-		ipoctal_free_channel(channel);
-}
-
-static int ipoctal_get_icount(struct tty_struct *tty,
-			      struct serial_icounter_struct *icount)
-{
-	struct ipoctal_channel *channel = tty->driver_data;
-
-	icount->cts = 0;
-	icount->dsr = 0;
-	icount->rng = 0;
-	icount->dcd = 0;
-	icount->rx = channel->stats.rx;
-	icount->tx = channel->stats.tx;
-	icount->frame = channel->stats.framing_err;
-	icount->parity = channel->stats.parity_err;
-	icount->brk = channel->stats.rcv_break;
-	return 0;
-}
-
-static void ipoctal_irq_rx(struct ipoctal_channel *channel,
-			   struct tty_struct *tty, u8 sr)
-{
-	unsigned char value;
-	unsigned char flag = TTY_NORMAL;
-	u8 isr;
-
-	do {
-		value = ioread8(&channel->regs->r.rhr);
-		/* Error: count statistics */
-		if (sr & SR_ERROR) {
-			iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr);
-
-			if (sr & SR_OVERRUN_ERROR) {
-				channel->stats.overrun_err++;
-				/* Overrun doesn't affect the current character*/
-				tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-			}
-			if (sr & SR_PARITY_ERROR) {
-				channel->stats.parity_err++;
-				flag = TTY_PARITY;
-			}
-			if (sr & SR_FRAMING_ERROR) {
-				channel->stats.framing_err++;
-				flag = TTY_FRAME;
-			}
-			if (sr & SR_RECEIVED_BREAK) {
-				iowrite8(CR_CMD_RESET_BREAK_CHANGE, &channel->regs->w.cr);
-				channel->stats.rcv_break++;
-				flag = TTY_BREAK;
-			}
-		}
-		tty_insert_flip_char(tty, value, flag);
-
-		/* Check if there are more characters in RX FIFO
-		 * If there are more, the isr register for this channel
-		 * has enabled the RxRDY|FFULL bit.
-		 */
-		isr = ioread8(&channel->block_regs->r.isr);
-		sr = ioread8(&channel->regs->r.sr);
-	} while (isr & channel->isr_rx_rdy_mask);
-
-	tty_flip_buffer_push(tty);
-}
-
-static void ipoctal_irq_tx(struct ipoctal_channel *channel)
-{
-	unsigned char value;
-	unsigned int *pointer_write = &channel->pointer_write;
-
-	if (channel->nb_bytes <= 0) {
-		channel->nb_bytes = 0;
-		return;
-	}
-
-	value = channel->tty_port.xmit_buf[*pointer_write];
-	iowrite8(value, &channel->regs->w.thr);
-	channel->stats.tx++;
-	(*pointer_write)++;
-	*pointer_write = *pointer_write % PAGE_SIZE;
-	channel->nb_bytes--;
-
-	if ((channel->nb_bytes == 0) &&
-	    (waitqueue_active(&channel->queue))) {
-
-		if (channel->board_id != IPACK1_DEVICE_ID_SBS_OCTAL_485) {
-			*channel->board_write = 1;
-			wake_up_interruptible(&channel->queue);
-		}
-	}
-}
-
-static void ipoctal_irq_channel(struct ipoctal_channel *channel)
-{
-	u8 isr, sr;
-	struct tty_struct *tty;
-
-	/* If there is no client, skip the check */
-	if (!atomic_read(&channel->open))
-		return;
-
-	tty = tty_port_tty_get(&channel->tty_port);
-	if (!tty)
-		return;
-	/* The HW is organized in pair of channels.  See which register we need
-	 * to read from */
-	isr = ioread8(&channel->block_regs->r.isr);
-	sr = ioread8(&channel->regs->r.sr);
-
-	/* In case of RS-485, change from TX to RX when finishing TX.
-	 * Half-duplex. */
-	if ((channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) &&
-	    (sr & SR_TX_EMPTY) && (channel->nb_bytes == 0)) {
-		iowrite8(CR_DISABLE_TX, &channel->regs->w.cr);
-		iowrite8(CR_CMD_NEGATE_RTSN, &channel->regs->w.cr);
-		iowrite8(CR_ENABLE_RX, &channel->regs->w.cr);
-		*channel->board_write = 1;
-		wake_up_interruptible(&channel->queue);
-	}
-
-	/* RX data */
-	if ((isr & channel->isr_rx_rdy_mask) && (sr & SR_RX_READY))
-		ipoctal_irq_rx(channel, tty, sr);
-
-	/* TX of each character */
-	if ((isr & channel->isr_tx_rdy_mask) && (sr & SR_TX_READY))
-		ipoctal_irq_tx(channel);
-
-	tty_flip_buffer_push(tty);
-	tty_kref_put(tty);
-}
-
-static irqreturn_t ipoctal_irq_handler(void *arg)
-{
-	unsigned int i;
-	struct ipoctal *ipoctal = (struct ipoctal *) arg;
-
-	/* Check all channels */
-	for (i = 0; i < NR_CHANNELS; i++)
-		ipoctal_irq_channel(&ipoctal->channel[i]);
-
-	/* Clear the IPack device interrupt */
-	readw(ipoctal->dev->int_space.address + ACK_INT_REQ0);
-	readw(ipoctal->dev->int_space.address + ACK_INT_REQ1);
-
-	return IRQ_HANDLED;
-}
-
-static int ipoctal_check_model(struct ipack_device *dev, unsigned char *id)
-{
-	unsigned char manufacturerID;
-	unsigned char board_id;
-
-
-	manufacturerID = ioread8(dev->id_space.address + IPACK_IDPROM_OFFSET_MANUFACTURER_ID);
-	if (manufacturerID != IPACK1_VENDOR_ID_SBS)
-		return -ENODEV;
-	board_id = ioread8(dev->id_space.address + IPACK_IDPROM_OFFSET_MODEL);
-	switch (board_id) {
-	case IPACK1_DEVICE_ID_SBS_OCTAL_232:
-	case IPACK1_DEVICE_ID_SBS_OCTAL_422:
-	case IPACK1_DEVICE_ID_SBS_OCTAL_485:
-		*id = board_id;
-		break;
-	default:
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static const struct tty_port_operations ipoctal_tty_port_ops = {
-	.dtr_rts = NULL,
-	.activate = ipoctal_port_activate,
-};
-
-static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
-			     unsigned int slot)
-{
-	int res = 0;
-	int i;
-	struct tty_driver *tty;
-	char name[20];
-	unsigned char board_id;
-	struct ipoctal_channel *channel;
-	union scc2698_channel __iomem *chan_regs;
-	union scc2698_block __iomem *block_regs;
-
-	res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0,
-						IPACK_ID_SPACE);
-	if (res) {
-		dev_err(&ipoctal->dev->dev,
-			"Unable to map slot [%d:%d] ID space!\n",
-			bus_nr, slot);
-		return res;
-	}
-
-	res = ipoctal_check_model(ipoctal->dev, &board_id);
-	if (res) {
-		ipoctal->dev->bus->ops->unmap_space(ipoctal->dev,
-						    IPACK_ID_SPACE);
-		goto out_unregister_id_space;
-	}
-	ipoctal->board_id = board_id;
-
-	res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0,
-						IPACK_IO_SPACE);
-	if (res) {
-		dev_err(&ipoctal->dev->dev,
-			"Unable to map slot [%d:%d] IO space!\n",
-			bus_nr, slot);
-		goto out_unregister_id_space;
-	}
-
-	res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0,
-						IPACK_INT_SPACE);
-	if (res) {
-		dev_err(&ipoctal->dev->dev,
-			"Unable to map slot [%d:%d] INT space!\n",
-			bus_nr, slot);
-		goto out_unregister_io_space;
-	}
-
-	res = ipoctal->dev->bus->ops->map_space(ipoctal->dev,
-					   0x8000, IPACK_MEM_SPACE);
-	if (res) {
-		dev_err(&ipoctal->dev->dev,
-			"Unable to map slot [%d:%d] MEM space!\n",
-			bus_nr, slot);
-		goto out_unregister_int_space;
-	}
-
-	/* Save the virtual address to access the registers easily */
-	chan_regs =
-		(union scc2698_channel __iomem *) ipoctal->dev->io_space.address;
-	block_regs =
-		(union scc2698_block __iomem *) ipoctal->dev->io_space.address;
-
-	/* Disable RX and TX before touching anything */
-	for (i = 0; i < NR_CHANNELS ; i++) {
-		struct ipoctal_channel *channel = &ipoctal->channel[i];
-		channel->regs = chan_regs + i;
-		channel->block_regs = block_regs + (i >> 1);
-		channel->board_write = &ipoctal->write;
-		channel->board_id = ipoctal->board_id;
-		if (i & 1) {
-			channel->isr_tx_rdy_mask = ISR_TxRDY_B;
-			channel->isr_rx_rdy_mask = ISR_RxRDY_FFULL_B;
-		} else {
-			channel->isr_tx_rdy_mask = ISR_TxRDY_A;
-			channel->isr_rx_rdy_mask = ISR_RxRDY_FFULL_A;
-		}
-
-		iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr);
-		iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
-		iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
-		iowrite8(MR1_CHRL_8_BITS | MR1_ERROR_CHAR | MR1_RxINT_RxRDY,
-			 &channel->regs->w.mr); /* mr1 */
-		iowrite8(0, &channel->regs->w.mr); /* mr2 */
-		iowrite8(TX_CLK_9600  | RX_CLK_9600, &channel->regs->w.csr);
-	}
-
-	for (i = 0; i < IP_OCTAL_NB_BLOCKS; i++) {
-		iowrite8(ACR_BRG_SET2, &block_regs[i].w.acr);
-		iowrite8(OPCR_MPP_OUTPUT | OPCR_MPOa_RTSN | OPCR_MPOb_RTSN,
-			 &block_regs[i].w.opcr);
-		iowrite8(IMR_TxRDY_A | IMR_RxRDY_FFULL_A | IMR_DELTA_BREAK_A |
-			 IMR_TxRDY_B | IMR_RxRDY_FFULL_B | IMR_DELTA_BREAK_B,
-			 &block_regs[i].w.imr);
-	}
-
-	/*
-	 * IP-OCTAL has different addresses to copy its IRQ vector.
-	 * Depending of the carrier these addresses are accesible or not.
-	 * More info in the datasheet.
-	 */
-	ipoctal->dev->bus->ops->request_irq(ipoctal->dev,
-				       ipoctal_irq_handler, ipoctal);
-	/* Dummy write */
-	iowrite8(1, ipoctal->dev->mem_space.address + 1);
-
-	/* Register the TTY device */
-
-	/* Each IP-OCTAL channel is a TTY port */
-	tty = alloc_tty_driver(NR_CHANNELS);
-
-	if (!tty) {
-		res = -ENOMEM;
-		goto out_unregister_slot_unmap;
-	}
-
-	/* Fill struct tty_driver with ipoctal data */
-	tty->owner = THIS_MODULE;
-	tty->driver_name = KBUILD_MODNAME;
-	sprintf(name, KBUILD_MODNAME ".%d.%d.", bus_nr, slot);
-	tty->name = name;
-	tty->major = 0;
-
-	tty->minor_start = 0;
-	tty->type = TTY_DRIVER_TYPE_SERIAL;
-	tty->subtype = SERIAL_TYPE_NORMAL;
-	tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	tty->init_termios = tty_std_termios;
-	tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	tty->init_termios.c_ispeed = 9600;
-	tty->init_termios.c_ospeed = 9600;
-
-	tty_set_operations(tty, &ipoctal_fops);
-	res = tty_register_driver(tty);
-	if (res) {
-		dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n");
-		put_tty_driver(tty);
-		goto out_unregister_slot_unmap;
-	}
-
-	/* Save struct tty_driver for use it when uninstalling the device */
-	ipoctal->tty_drv = tty;
-
-	for (i = 0; i < NR_CHANNELS; i++) {
-		struct device *tty_dev;
-
-		channel = &ipoctal->channel[i];
-		tty_port_init(&channel->tty_port);
-		tty_port_alloc_xmit_buf(&channel->tty_port);
-		channel->tty_port.ops = &ipoctal_tty_port_ops;
-
-		ipoctal_reset_stats(&channel->stats);
-		channel->nb_bytes = 0;
-		init_waitqueue_head(&channel->queue);
-
-		spin_lock_init(&channel->lock);
-		channel->pointer_read = 0;
-		channel->pointer_write = 0;
-		tty_dev = tty_port_register_device(&channel->tty_port, tty, i, NULL);
-		if (IS_ERR(tty_dev)) {
-			dev_err(&ipoctal->dev->dev, "Failed to register tty device.\n");
-			continue;
-		}
-		dev_set_drvdata(tty_dev, channel);
-
-		/*
-		 * Enable again the RX. TX will be enabled when
-		 * there is something to send
-		 */
-		iowrite8(CR_ENABLE_RX, &channel->regs->w.cr);
-	}
-
-	return 0;
-
-out_unregister_slot_unmap:
-	ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_ID_SPACE);
-out_unregister_int_space:
-	ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_INT_SPACE);
-out_unregister_io_space:
-	ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_IO_SPACE);
-out_unregister_id_space:
-	ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_MEM_SPACE);
-	return res;
-}
-
-static inline int ipoctal_copy_write_buffer(struct ipoctal_channel *channel,
-					    const unsigned char *buf,
-					    int count)
-{
-	unsigned long flags;
-	int i;
-	unsigned int *pointer_read = &channel->pointer_read;
-
-	/* Copy the bytes from the user buffer to the internal one */
-	for (i = 0; i < count; i++) {
-		if (i <= (PAGE_SIZE - channel->nb_bytes)) {
-			spin_lock_irqsave(&channel->lock, flags);
-			channel->tty_port.xmit_buf[*pointer_read] = buf[i];
-			*pointer_read = (*pointer_read + 1) % PAGE_SIZE;
-			channel->nb_bytes++;
-			spin_unlock_irqrestore(&channel->lock, flags);
-		} else {
-			break;
-		}
-	}
-	return i;
-}
-
-static int ipoctal_write_tty(struct tty_struct *tty,
-			     const unsigned char *buf, int count)
-{
-	struct ipoctal_channel *channel = tty->driver_data;
-	unsigned int char_copied;
-
-	char_copied = ipoctal_copy_write_buffer(channel, buf, count);
-
-	/* As the IP-OCTAL 485 only supports half duplex, do it manually */
-	if (channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) {
-		iowrite8(CR_DISABLE_RX, &channel->regs->w.cr);
-		iowrite8(CR_CMD_ASSERT_RTSN, &channel->regs->w.cr);
-	}
-
-	/*
-	 * Send a packet and then disable TX to avoid failure after several send
-	 * operations
-	 */
-	iowrite8(CR_ENABLE_TX, &channel->regs->w.cr);
-	wait_event_interruptible(channel->queue, *channel->board_write);
-	iowrite8(CR_DISABLE_TX, &channel->regs->w.cr);
-
-	*channel->board_write = 0;
-	return char_copied;
-}
-
-static int ipoctal_write_room(struct tty_struct *tty)
-{
-	struct ipoctal_channel *channel = tty->driver_data;
-
-	return PAGE_SIZE - channel->nb_bytes;
-}
-
-static int ipoctal_chars_in_buffer(struct tty_struct *tty)
-{
-	struct ipoctal_channel *channel = tty->driver_data;
-
-	return channel->nb_bytes;
-}
-
-static void ipoctal_set_termios(struct tty_struct *tty,
-				struct ktermios *old_termios)
-{
-	unsigned int cflag;
-	unsigned char mr1 = 0;
-	unsigned char mr2 = 0;
-	unsigned char csr = 0;
-	struct ipoctal_channel *channel = tty->driver_data;
-	speed_t baud;
-
-	cflag = tty->termios.c_cflag;
-
-	/* Disable and reset everything before change the setup */
-	iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_MR, &channel->regs->w.cr);
-
-	/* Set Bits per chars */
-	switch (cflag & CSIZE) {
-	case CS6:
-		mr1 |= MR1_CHRL_6_BITS;
-		break;
-	case CS7:
-		mr1 |= MR1_CHRL_7_BITS;
-		break;
-	case CS8:
-	default:
-		mr1 |= MR1_CHRL_8_BITS;
-		/* By default, select CS8 */
-		tty->termios.c_cflag = (cflag & ~CSIZE) | CS8;
-		break;
-	}
-
-	/* Set Parity */
-	if (cflag & PARENB)
-		if (cflag & PARODD)
-			mr1 |= MR1_PARITY_ON | MR1_PARITY_ODD;
-		else
-			mr1 |= MR1_PARITY_ON | MR1_PARITY_EVEN;
-	else
-		mr1 |= MR1_PARITY_OFF;
-
-	/* Mark or space parity is not supported */
-	tty->termios.c_cflag &= ~CMSPAR;
-
-	/* Set stop bits */
-	if (cflag & CSTOPB)
-		mr2 |= MR2_STOP_BITS_LENGTH_2;
-	else
-		mr2 |= MR2_STOP_BITS_LENGTH_1;
-
-	/* Set the flow control */
-	switch (channel->board_id) {
-	case IPACK1_DEVICE_ID_SBS_OCTAL_232:
-		if (cflag & CRTSCTS) {
-			mr1 |= MR1_RxRTS_CONTROL_ON;
-			mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_ON;
-		} else {
-			mr1 |= MR1_RxRTS_CONTROL_OFF;
-			mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF;
-		}
-		break;
-	case IPACK1_DEVICE_ID_SBS_OCTAL_422:
-		mr1 |= MR1_RxRTS_CONTROL_OFF;
-		mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF;
-		break;
-	case IPACK1_DEVICE_ID_SBS_OCTAL_485:
-		mr1 |= MR1_RxRTS_CONTROL_OFF;
-		mr2 |= MR2_TxRTS_CONTROL_ON | MR2_CTS_ENABLE_TX_OFF;
-		break;
-	default:
-		return;
-		break;
-	}
-
-	baud = tty_get_baud_rate(tty);
-	tty_termios_encode_baud_rate(&tty->termios, baud, baud);
-
-	/* Set baud rate */
-	switch (baud) {
-	case 75:
-		csr |= TX_CLK_75 | RX_CLK_75;
-		break;
-	case 110:
-		csr |= TX_CLK_110 | RX_CLK_110;
-		break;
-	case 150:
-		csr |= TX_CLK_150 | RX_CLK_150;
-		break;
-	case 300:
-		csr |= TX_CLK_300 | RX_CLK_300;
-		break;
-	case 600:
-		csr |= TX_CLK_600 | RX_CLK_600;
-		break;
-	case 1200:
-		csr |= TX_CLK_1200 | RX_CLK_1200;
-		break;
-	case 1800:
-		csr |= TX_CLK_1800 | RX_CLK_1800;
-		break;
-	case 2000:
-		csr |= TX_CLK_2000 | RX_CLK_2000;
-		break;
-	case 2400:
-		csr |= TX_CLK_2400 | RX_CLK_2400;
-		break;
-	case 4800:
-		csr |= TX_CLK_4800  | RX_CLK_4800;
-		break;
-	case 9600:
-		csr |= TX_CLK_9600  | RX_CLK_9600;
-		break;
-	case 19200:
-		csr |= TX_CLK_19200 | RX_CLK_19200;
-		break;
-	case 38400:
-	default:
-		csr |= TX_CLK_38400 | RX_CLK_38400;
-		/* In case of default, we establish 38400 bps */
-		tty_termios_encode_baud_rate(&tty->termios, 38400, 38400);
-		break;
-	}
-
-	mr1 |= MR1_ERROR_CHAR;
-	mr1 |= MR1_RxINT_RxRDY;
-
-	/* Write the control registers */
-	iowrite8(mr1, &channel->regs->w.mr);
-	iowrite8(mr2, &channel->regs->w.mr);
-	iowrite8(csr, &channel->regs->w.csr);
-
-	/* Enable again the RX */
-	iowrite8(CR_ENABLE_RX, &channel->regs->w.cr);
-}
-
-static void ipoctal_hangup(struct tty_struct *tty)
-{
-	unsigned long flags;
-	struct ipoctal_channel *channel = tty->driver_data;
-
-	if (channel == NULL)
-		return;
-
-	spin_lock_irqsave(&channel->lock, flags);
-	channel->nb_bytes = 0;
-	channel->pointer_read = 0;
-	channel->pointer_write = 0;
-	spin_unlock_irqrestore(&channel->lock, flags);
-
-	tty_port_hangup(&channel->tty_port);
-
-	iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_MR, &channel->regs->w.cr);
-
-	clear_bit(ASYNCB_INITIALIZED, &channel->tty_port.flags);
-	wake_up_interruptible(&channel->tty_port.open_wait);
-}
-
-static const struct tty_operations ipoctal_fops = {
-	.ioctl =		NULL,
-	.open =			ipoctal_open,
-	.close =		ipoctal_close,
-	.write =		ipoctal_write_tty,
-	.set_termios =		ipoctal_set_termios,
-	.write_room =		ipoctal_write_room,
-	.chars_in_buffer =	ipoctal_chars_in_buffer,
-	.get_icount =		ipoctal_get_icount,
-	.hangup =		ipoctal_hangup,
-};
-
-static int ipoctal_probe(struct ipack_device *dev)
-{
-	int res;
-	struct ipoctal *ipoctal;
-
-	ipoctal = kzalloc(sizeof(struct ipoctal), GFP_KERNEL);
-	if (ipoctal == NULL)
-		return -ENOMEM;
-
-	ipoctal->dev = dev;
-	res = ipoctal_inst_slot(ipoctal, dev->bus_nr, dev->slot);
-	if (res)
-		goto out_uninst;
-
-	dev_set_drvdata(&dev->dev, ipoctal);
-	return 0;
-
-out_uninst:
-	kfree(ipoctal);
-	return res;
-}
-
-static void __ipoctal_remove(struct ipoctal *ipoctal)
-{
-	int i;
-
-	ipoctal->dev->bus->ops->free_irq(ipoctal->dev);
-
-	for (i = 0; i < NR_CHANNELS; i++) {
-		struct ipoctal_channel *channel = &ipoctal->channel[i];
-		tty_unregister_device(ipoctal->tty_drv, i);
-		tty_port_free_xmit_buf(&channel->tty_port);
-	}
-
-	tty_unregister_driver(ipoctal->tty_drv);
-	put_tty_driver(ipoctal->tty_drv);
-	ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_MEM_SPACE);
-	ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_INT_SPACE);
-	ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_IO_SPACE);
-	ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_ID_SPACE);
-	kfree(ipoctal);
-}
-
-static void ipoctal_remove(struct ipack_device *idev)
-{
-	__ipoctal_remove(dev_get_drvdata(&idev->dev));
-}
-
-static DEFINE_IPACK_DEVICE_TABLE(ipoctal_ids) = {
-	{ IPACK_DEVICE(IPACK_ID_VERSION_1, IPACK1_VENDOR_ID_SBS,
-			IPACK1_DEVICE_ID_SBS_OCTAL_232) },
-	{ IPACK_DEVICE(IPACK_ID_VERSION_1, IPACK1_VENDOR_ID_SBS,
-			IPACK1_DEVICE_ID_SBS_OCTAL_422) },
-	{ IPACK_DEVICE(IPACK_ID_VERSION_1, IPACK1_VENDOR_ID_SBS,
-			IPACK1_DEVICE_ID_SBS_OCTAL_485) },
-	{ 0, },
-};
-
-MODULE_DEVICE_TABLE(ipack, ipoctal_ids);
-
-static const struct ipack_driver_ops ipoctal_drv_ops = {
-	.probe  = ipoctal_probe,
-	.remove = ipoctal_remove,
-};
-
-static struct ipack_driver driver = {
-	.ops      = &ipoctal_drv_ops,
-	.id_table = ipoctal_ids,
-};
-
-static int __init ipoctal_init(void)
-{
-	return ipack_driver_register(&driver, THIS_MODULE, KBUILD_MODNAME);
-}
-
-static void __exit ipoctal_exit(void)
-{
-	ipack_driver_unregister(&driver);
-}
-
-MODULE_DESCRIPTION("IP-Octal 232, 422 and 485 device driver");
-MODULE_LICENSE("GPL");
-
-module_init(ipoctal_init);
-module_exit(ipoctal_exit);
diff --git a/drivers/staging/ipack/devices/ipoctal.h b/drivers/staging/ipack/devices/ipoctal.h
deleted file mode 100644
index c5b4ed4..0000000
--- a/drivers/staging/ipack/devices/ipoctal.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * ipoctal.h
- *
- * driver for the IPOCTAL boards
- * Copyright (c) 2009 Nicolas Serafini, EIC2 SA
- * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN
- * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia
- *
- * This program is free software; 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 _IPOCTAL_H
-#define _IPOCTAL_H_
-
-#define NR_CHANNELS		8
-#define IPOCTAL_MAX_BOARDS	16
-#define MAX_DEVICES		(NR_CHANNELS * IPOCTAL_MAX_BOARDS)
-#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
-/**
- * struct ipoctal_stats -- Stats since last reset
- *
- * @tx: Number of transmitted bytes
- * @rx: Number of received bytes
- * @overrun: Number of overrun errors
- * @parity_err: Number of parity errors
- * @framing_err: Number of framing errors
- * @rcv_break: Number of break received
- */
-struct ipoctal_stats {
-	unsigned long tx;
-	unsigned long rx;
-	unsigned long overrun_err;
-	unsigned long parity_err;
-	unsigned long framing_err;
-	unsigned long rcv_break;
-};
-
-#endif /* _IPOCTAL_H_ */
diff --git a/drivers/staging/ipack/devices/scc2698.h b/drivers/staging/ipack/devices/scc2698.h
deleted file mode 100644
index 96e8d8c..0000000
--- a/drivers/staging/ipack/devices/scc2698.h
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * scc2698.h
- *
- * driver for the IPOCTAL boards
- * Copyright (c) 2009 Nicolas Serafini, EIC2 SA
- * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN
- * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia
- *
- * This program is free software; 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 SCC2698_H_
-#define SCC2698_H_
-
-/*
- * union scc2698_channel - Channel access to scc2698 IO
- *
- * dn value are only spacer.
- *
- */
-union scc2698_channel {
-	struct {
-		u8 d0, mr;  /* Mode register 1/2*/
-		u8 d1, sr;  /* Status register */
-		u8 d2, r1;  /* reserved */
-		u8 d3, rhr; /* Receive holding register (R) */
-		u8 junk[8]; /* other crap for block control */
-	} __packed r; /* Read access */
-	struct {
-		u8 d0, mr;  /* Mode register 1/2 */
-		u8 d1, csr; /* Clock select register */
-		u8 d2, cr;  /* Command register */
-		u8 d3, thr; /* Transmit holding register */
-		u8 junk[8]; /* other crap for block control */
-	} __packed w; /* Write access */
-};
-
-/*
- * union scc2698_block - Block access to scc2698 IO
- *
- * The scc2698 contain 4 block.
- * Each block containt two channel a and b.
- * dn value are only spacer.
- *
- */
-union scc2698_block {
-	struct {
-		u8 d0, mra;  /* Mode register 1/2 (a) */
-		u8 d1, sra;  /* Status register (a) */
-		u8 d2, r1;   /* reserved */
-		u8 d3, rhra; /* Receive holding register (a) */
-		u8 d4, ipcr; /* Input port change register of block */
-		u8 d5, isr;  /* Interrupt status register of block */
-		u8 d6, ctur; /* Counter timer upper register of block */
-		u8 d7, ctlr; /* Counter timer lower register of block */
-		u8 d8, mrb;  /* Mode register 1/2 (b) */
-		u8 d9, srb;  /* Status register (b) */
-		u8 da, r2;   /* reserved */
-		u8 db, rhrb; /* Receive holding register (b) */
-		u8 dc, r3;   /* reserved */
-		u8 dd, ip;   /* Input port register of block */
-		u8 de, ctg;  /* Start counter timer of block */
-		u8 df, cts;  /* Stop counter timer of block */
-	} __packed r; /* Read access */
-	struct {
-		u8 d0, mra;  /* Mode register 1/2 (a) */
-		u8 d1, csra; /* Clock select register (a) */
-		u8 d2, cra;  /* Command register (a) */
-		u8 d3, thra; /* Transmit holding register (a) */
-		u8 d4, acr;  /* Auxiliary control register of block */
-		u8 d5, imr;  /* Interrupt mask register of block  */
-		u8 d6, ctu;  /* Counter timer upper register of block */
-		u8 d7, ctl;  /* Counter timer lower register of block */
-		u8 d8, mrb;  /* Mode register 1/2 (b) */
-		u8 d9, csrb; /* Clock select register (a) */
-		u8 da, crb;  /* Command register (b) */
-		u8 db, thrb; /* Transmit holding register (b) */
-		u8 dc, r1;   /* reserved */
-		u8 dd, opcr; /* Output port configuration register of block */
-		u8 de, r2;   /* reserved */
-		u8 df, r3;   /* reserved */
-	} __packed w; /* Write access */
-};
-
-#define MR1_CHRL_5_BITS             (0x0 << 0)
-#define MR1_CHRL_6_BITS             (0x1 << 0)
-#define MR1_CHRL_7_BITS             (0x2 << 0)
-#define MR1_CHRL_8_BITS             (0x3 << 0)
-#define MR1_PARITY_EVEN             (0x1 << 2)
-#define MR1_PARITY_ODD              (0x0 << 2)
-#define MR1_PARITY_ON               (0x0 << 3)
-#define MR1_PARITY_FORCE            (0x1 << 3)
-#define MR1_PARITY_OFF              (0x2 << 3)
-#define MR1_PARITY_SPECIAL          (0x3 << 3)
-#define MR1_ERROR_CHAR              (0x0 << 5)
-#define MR1_ERROR_BLOCK             (0x1 << 5)
-#define MR1_RxINT_RxRDY             (0x0 << 6)
-#define MR1_RxINT_FFULL             (0x1 << 6)
-#define MR1_RxRTS_CONTROL_ON        (0x1 << 7)
-#define MR1_RxRTS_CONTROL_OFF       (0x0 << 7)
-
-#define MR2_STOP_BITS_LENGTH_1      (0x7 << 0)
-#define MR2_STOP_BITS_LENGTH_2      (0xF << 0)
-#define MR2_CTS_ENABLE_TX_ON        (0x1 << 4)
-#define MR2_CTS_ENABLE_TX_OFF       (0x0 << 4)
-#define MR2_TxRTS_CONTROL_ON        (0x1 << 5)
-#define MR2_TxRTS_CONTROL_OFF       (0x0 << 5)
-#define MR2_CH_MODE_NORMAL          (0x0 << 6)
-#define MR2_CH_MODE_ECHO            (0x1 << 6)
-#define MR2_CH_MODE_LOCAL           (0x2 << 6)
-#define MR2_CH_MODE_REMOTE          (0x3 << 6)
-
-#define CR_ENABLE_RX                (0x1 << 0)
-#define CR_DISABLE_RX               (0x1 << 1)
-#define CR_ENABLE_TX                (0x1 << 2)
-#define CR_DISABLE_TX               (0x1 << 3)
-#define CR_CMD_RESET_MR             (0x1 << 4)
-#define CR_CMD_RESET_RX             (0x2 << 4)
-#define CR_CMD_RESET_TX             (0x3 << 4)
-#define CR_CMD_RESET_ERR_STATUS     (0x4 << 4)
-#define CR_CMD_RESET_BREAK_CHANGE   (0x5 << 4)
-#define CR_CMD_START_BREAK          (0x6 << 4)
-#define CR_CMD_STOP_BREAK           (0x7 << 4)
-#define CR_CMD_ASSERT_RTSN          (0x8 << 4)
-#define CR_CMD_NEGATE_RTSN          (0x9 << 4)
-#define CR_CMD_SET_TIMEOUT_MODE     (0xA << 4)
-#define CR_CMD_DISABLE_TIMEOUT_MODE (0xC << 4)
-
-#define SR_RX_READY                 (0x1 << 0)
-#define SR_FIFO_FULL                (0x1 << 1)
-#define SR_TX_READY                 (0x1 << 2)
-#define SR_TX_EMPTY                 (0x1 << 3)
-#define SR_OVERRUN_ERROR            (0x1 << 4)
-#define SR_PARITY_ERROR             (0x1 << 5)
-#define SR_FRAMING_ERROR            (0x1 << 6)
-#define SR_RECEIVED_BREAK           (0x1 << 7)
-
-#define SR_ERROR                    (0xF0)
-
-#define ACR_DELTA_IP0_IRQ_EN        (0x1 << 0)
-#define ACR_DELTA_IP1_IRQ_EN        (0x1 << 1)
-#define ACR_DELTA_IP2_IRQ_EN        (0x1 << 2)
-#define ACR_DELTA_IP3_IRQ_EN        (0x1 << 3)
-#define ACR_CT_Mask                 (0x7 << 4)
-#define ACR_CExt                    (0x0 << 4)
-#define ACR_CTxCA                   (0x1 << 4)
-#define ACR_CTxCB                   (0x2 << 4)
-#define ACR_CClk16                  (0x3 << 4)
-#define ACR_TExt                    (0x4 << 4)
-#define ACR_TExt16                  (0x5 << 4)
-#define ACR_TClk                    (0x6 << 4)
-#define ACR_TClk16                  (0x7 << 4)
-#define ACR_BRG_SET1                (0x0 << 7)
-#define ACR_BRG_SET2                (0x1 << 7)
-
-#define TX_CLK_75                   (0x0 << 0)
-#define TX_CLK_110                  (0x1 << 0)
-#define TX_CLK_38400                (0x2 << 0)
-#define TX_CLK_150                  (0x3 << 0)
-#define TX_CLK_300                  (0x4 << 0)
-#define TX_CLK_600                  (0x5 << 0)
-#define TX_CLK_1200                 (0x6 << 0)
-#define TX_CLK_2000                 (0x7 << 0)
-#define TX_CLK_2400                 (0x8 << 0)
-#define TX_CLK_4800                 (0x9 << 0)
-#define TX_CLK_1800                 (0xA << 0)
-#define TX_CLK_9600                 (0xB << 0)
-#define TX_CLK_19200                (0xC << 0)
-#define RX_CLK_75                   (0x0 << 4)
-#define RX_CLK_110                  (0x1 << 4)
-#define RX_CLK_38400                (0x2 << 4)
-#define RX_CLK_150                  (0x3 << 4)
-#define RX_CLK_300                  (0x4 << 4)
-#define RX_CLK_600                  (0x5 << 4)
-#define RX_CLK_1200                 (0x6 << 4)
-#define RX_CLK_2000                 (0x7 << 4)
-#define RX_CLK_2400                 (0x8 << 4)
-#define RX_CLK_4800                 (0x9 << 4)
-#define RX_CLK_1800                 (0xA << 4)
-#define RX_CLK_9600                 (0xB << 4)
-#define RX_CLK_19200                (0xC << 4)
-
-#define OPCR_MPOa_RTSN              (0x0 << 0)
-#define OPCR_MPOa_C_TO              (0x1 << 0)
-#define OPCR_MPOa_TxC1X             (0x2 << 0)
-#define OPCR_MPOa_TxC16X            (0x3 << 0)
-#define OPCR_MPOa_RxC1X             (0x4 << 0)
-#define OPCR_MPOa_RxC16X            (0x5 << 0)
-#define OPCR_MPOa_TxRDY             (0x6 << 0)
-#define OPCR_MPOa_RxRDY_FF          (0x7 << 0)
-
-#define OPCR_MPOb_RTSN              (0x0 << 4)
-#define OPCR_MPOb_C_TO              (0x1 << 4)
-#define OPCR_MPOb_TxC1X             (0x2 << 4)
-#define OPCR_MPOb_TxC16X            (0x3 << 4)
-#define OPCR_MPOb_RxC1X             (0x4 << 4)
-#define OPCR_MPOb_RxC16X            (0x5 << 4)
-#define OPCR_MPOb_TxRDY             (0x6 << 4)
-#define OPCR_MPOb_RxRDY_FF          (0x7 << 4)
-
-#define OPCR_MPP_INPUT              (0x0 << 7)
-#define OPCR_MPP_OUTPUT             (0x1 << 7)
-
-#define IMR_TxRDY_A                 (0x1 << 0)
-#define IMR_RxRDY_FFULL_A           (0x1 << 1)
-#define IMR_DELTA_BREAK_A           (0x1 << 2)
-#define IMR_COUNTER_READY           (0x1 << 3)
-#define IMR_TxRDY_B                 (0x1 << 4)
-#define IMR_RxRDY_FFULL_B           (0x1 << 5)
-#define IMR_DELTA_BREAK_B           (0x1 << 6)
-#define IMR_INPUT_PORT_CHANGE       (0x1 << 7)
-
-#define ISR_TxRDY_A                 (0x1 << 0)
-#define ISR_RxRDY_FFULL_A           (0x1 << 1)
-#define ISR_DELTA_BREAK_A           (0x1 << 2)
-#define ISR_COUNTER_READY           (0x1 << 3)
-#define ISR_TxRDY_B                 (0x1 << 4)
-#define ISR_RxRDY_FFULL_B           (0x1 << 5)
-#define ISR_DELTA_BREAK_B           (0x1 << 6)
-#define ISR_INPUT_PORT_CHANGE       (0x1 << 7)
-
-#define ACK_INT_REQ0			0
-#define ACK_INT_REQ1			2
-
-#endif /* SCC2698_H_ */
diff --git a/drivers/staging/ipack/ipack.c b/drivers/staging/ipack/ipack.c
deleted file mode 100644
index d1e0651..0000000
--- a/drivers/staging/ipack/ipack.c
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
- * Industry-pack bus support functions.
- *
- * (C) 2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN
- * (C) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia
- *
- * This program is free software; 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/module.h>
-#include <linux/slab.h>
-#include <linux/idr.h>
-#include <asm/io.h>
-#include "ipack.h"
-
-#define to_ipack_dev(device) container_of(device, struct ipack_device, dev)
-#define to_ipack_driver(drv) container_of(drv, struct ipack_driver, driver)
-
-static DEFINE_IDA(ipack_ida);
-
-static void ipack_device_release(struct device *dev)
-{
-	struct ipack_device *device = to_ipack_dev(dev);
-	kfree(device->id);
-	kfree(device);
-}
-
-static inline const struct ipack_device_id *
-ipack_match_one_device(const struct ipack_device_id *id,
-		       const struct ipack_device *device)
-{
-	if ((id->format == IPACK_ANY_FORMAT ||
-				id->format == device->id_format) &&
-	    (id->vendor == IPACK_ANY_ID || id->vendor == device->id_vendor) &&
-	    (id->device == IPACK_ANY_ID || id->device == device->id_device))
-		return id;
-	return NULL;
-}
-
-static const struct ipack_device_id *
-ipack_match_id(const struct ipack_device_id *ids, struct ipack_device *idev)
-{
-	if (ids) {
-		while (ids->vendor || ids->device) {
-			if (ipack_match_one_device(ids, idev))
-				return ids;
-			ids++;
-		}
-	}
-	return NULL;
-}
-
-static int ipack_bus_match(struct device *dev, struct device_driver *drv)
-{
-	struct ipack_device *idev = to_ipack_dev(dev);
-	struct ipack_driver *idrv = to_ipack_driver(drv);
-	const struct ipack_device_id *found_id;
-
-	found_id = ipack_match_id(idrv->id_table, idev);
-	return found_id ? 1 : 0;
-}
-
-static int ipack_bus_probe(struct device *device)
-{
-	struct ipack_device *dev = to_ipack_dev(device);
-	struct ipack_driver *drv = to_ipack_driver(device->driver);
-
-	if (!drv->ops->probe)
-		return -EINVAL;
-
-	return drv->ops->probe(dev);
-}
-
-static int ipack_bus_remove(struct device *device)
-{
-	struct ipack_device *dev = to_ipack_dev(device);
-	struct ipack_driver *drv = to_ipack_driver(device->driver);
-
-	if (!drv->ops->remove)
-		return -EINVAL;
-
-	drv->ops->remove(dev);
-	return 0;
-}
-
-#ifdef CONFIG_HOTPLUG
-
-static int ipack_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-	struct ipack_device *idev;
-
-	if (!dev)
-		return -ENODEV;
-
-	idev = to_ipack_dev(dev);
-
-	if (add_uevent_var(env,
-			   "MODALIAS=ipack:f%02Xv%08Xd%08X", idev->id_format,
-			   idev->id_vendor, idev->id_device))
-		return -ENOMEM;
-
-	return 0;
-}
-
-#else /* !CONFIG_HOTPLUG */
-
-#define ipack_uevent NULL
-
-#endif /* !CONFIG_HOTPLUG */
-
-#define ipack_device_attr(field, format_string)				\
-static ssize_t								\
-field##_show(struct device *dev, struct device_attribute *attr,		\
-		char *buf)						\
-{									\
-	struct ipack_device *idev = to_ipack_dev(dev);			\
-	return sprintf(buf, format_string, idev->field);		\
-}
-
-static ssize_t id_show(struct device *dev,
-		       struct device_attribute *attr, char *buf)
-{
-	unsigned int i, c, l, s;
-	struct ipack_device *idev = to_ipack_dev(dev);
-
-
-	switch (idev->id_format) {
-	case IPACK_ID_VERSION_1:
-		l = 0x7; s = 1; break;
-	case IPACK_ID_VERSION_2:
-		l = 0xf; s = 2; break;
-	default:
-		return -EIO;
-	}
-	c = 0;
-	for (i = 0; i < idev->id_avail; i++) {
-		if (i > 0) {
-			if ((i & l) == 0)
-				buf[c++] = '\n';
-			else if ((i & s) == 0)
-				buf[c++] = ' ';
-		}
-		sprintf(&buf[c], "%02x", idev->id[i]);
-		c += 2;
-	}
-	buf[c++] = '\n';
-	return c;
-}
-
-static ssize_t
-id_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct ipack_device *idev = to_ipack_dev(dev);
-	switch (idev->id_format) {
-	case IPACK_ID_VERSION_1:
-		return sprintf(buf, "0x%02x\n", idev->id_vendor);
-	case IPACK_ID_VERSION_2:
-		return sprintf(buf, "0x%06x\n", idev->id_vendor);
-	default:
-		return -EIO;
-	}
-}
-
-static ssize_t
-id_device_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct ipack_device *idev = to_ipack_dev(dev);
-	switch (idev->id_format) {
-	case IPACK_ID_VERSION_1:
-		return sprintf(buf, "0x%02x\n", idev->id_device);
-	case IPACK_ID_VERSION_2:
-		return sprintf(buf, "0x%04x\n", idev->id_device);
-	default:
-		return -EIO;
-	}
-}
-
-static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
-			     char *buf)
-{
-	struct ipack_device *idev = to_ipack_dev(dev);
-
-	return sprintf(buf, "ipac:f%02Xv%08Xd%08X", idev->id_format,
-		       idev->id_vendor, idev->id_device);
-}
-
-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 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,
-	.uevent	   = ipack_uevent,
-};
-
-struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots,
-					    const struct ipack_bus_ops *ops)
-{
-	int bus_nr;
-	struct ipack_bus_device *bus;
-
-	bus = kzalloc(sizeof(struct ipack_bus_device), GFP_KERNEL);
-	if (!bus)
-		return NULL;
-
-	bus_nr = ida_simple_get(&ipack_ida, 0, 0, GFP_KERNEL);
-	if (bus_nr < 0) {
-		kfree(bus);
-		return NULL;
-	}
-
-	bus->bus_nr = bus_nr;
-	bus->parent = parent;
-	bus->slots = slots;
-	bus->ops = ops;
-	return bus;
-}
-EXPORT_SYMBOL_GPL(ipack_bus_register);
-
-static int ipack_unregister_bus_member(struct device *dev, void *data)
-{
-	struct ipack_device *idev = to_ipack_dev(dev);
-	struct ipack_bus_device *bus = data;
-
-	if (idev->bus_nr == bus->bus_nr)
-		ipack_device_unregister(idev);
-
-	return 1;
-}
-
-int ipack_bus_unregister(struct ipack_bus_device *bus)
-{
-	bus_for_each_dev(&ipack_bus_type, NULL, bus, ipack_unregister_bus_member);
-	ida_simple_remove(&ipack_ida, bus->bus_nr);
-	kfree(bus);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(ipack_bus_unregister);
-
-int ipack_driver_register(struct ipack_driver *edrv, struct module *owner,
-			  const char *name)
-{
-	edrv->driver.owner = owner;
-	edrv->driver.name = name;
-	edrv->driver.bus = &ipack_bus_type;
-	return driver_register(&edrv->driver);
-}
-EXPORT_SYMBOL_GPL(ipack_driver_register);
-
-void ipack_driver_unregister(struct ipack_driver *edrv)
-{
-	driver_unregister(&edrv->driver);
-}
-EXPORT_SYMBOL_GPL(ipack_driver_unregister);
-
-static u16 ipack_crc_byte(u16 crc, u8 c)
-{
-	int i;
-
-	crc ^= c << 8;
-	for (i = 0; i < 8; i++)
-		crc = (crc << 1) ^ ((crc & 0x8000) ? 0x1021 : 0);
-	return crc;
-}
-
-/*
- * The algorithm in lib/crc-ccitt.c does not seem to apply since it uses the
- * opposite bit ordering.
- */
-static u8 ipack_calc_crc1(struct ipack_device *dev)
-{
-	u8 c;
-	u16 crc;
-	unsigned int i;
-
-	crc = 0xffff;
-	for (i = 0; i < dev->id_avail; i++) {
-		c = (i != 11) ? dev->id[i] : 0;
-		crc = ipack_crc_byte(crc, c);
-	}
-	crc = ~crc;
-	return crc & 0xff;
-}
-
-static u16 ipack_calc_crc2(struct ipack_device *dev)
-{
-	u8 c;
-	u16 crc;
-	unsigned int i;
-
-	crc = 0xffff;
-	for (i = 0; i < dev->id_avail; i++) {
-		c = ((i != 0x18) && (i != 0x19)) ? dev->id[i] : 0;
-		crc = ipack_crc_byte(crc, c);
-	}
-	crc = ~crc;
-	return crc;
-}
-
-static void ipack_parse_id1(struct ipack_device *dev)
-{
-	u8 *id = dev->id;
-	u8 crc;
-
-	dev->id_vendor = id[4];
-	dev->id_device = id[5];
-	dev->speed_8mhz = 1;
-	dev->speed_32mhz = (id[7] == 'H');
-	crc = ipack_calc_crc1(dev);
-	dev->id_crc_correct = (crc == id[11]);
-	if (!dev->id_crc_correct) {
-		dev_warn(&dev->dev, "ID CRC invalid found 0x%x, expected 0x%x.\n",
-				id[11], crc);
-	}
-}
-
-static void ipack_parse_id2(struct ipack_device *dev)
-{
-	__be16 *id = (__be16 *) dev->id;
-	u16 flags, crc;
-
-	dev->id_vendor = ((be16_to_cpu(id[3]) & 0xff) << 16)
-			 + be16_to_cpu(id[4]);
-	dev->id_device = be16_to_cpu(id[5]);
-	flags = be16_to_cpu(id[10]);
-	dev->speed_8mhz = !!(flags & 2);
-	dev->speed_32mhz = !!(flags & 4);
-	crc = ipack_calc_crc2(dev);
-	dev->id_crc_correct = (crc == be16_to_cpu(id[12]));
-	if (!dev->id_crc_correct) {
-		dev_warn(&dev->dev, "ID CRC invalid found 0x%x, expected 0x%x.\n",
-				id[11], crc);
-	}
-}
-
-static int ipack_device_read_id(struct ipack_device *dev)
-{
-	u8 __iomem *idmem;
-	int i;
-	int ret = 0;
-
-	ret = dev->bus->ops->map_space(dev, 0, IPACK_ID_SPACE);
-	if (ret) {
-		dev_err(&dev->dev, "error mapping memory\n");
-		return ret;
-	}
-	idmem = dev->id_space.address;
-
-	/* Determine ID PROM Data Format.  If we find the ids "IPAC" or "IPAH"
-	 * we are dealing with a IndustryPack  format 1 device.  If we detect
-	 * "VITA4 " (16 bit big endian formatted) we are dealing with a
-	 * IndustryPack format 2 device */
-	if ((ioread8(idmem + 1) == 'I') &&
-			(ioread8(idmem + 3) == 'P') &&
-			(ioread8(idmem + 5) == 'A') &&
-			((ioread8(idmem + 7) == 'C') ||
-			 (ioread8(idmem + 7) == 'H'))) {
-		dev->id_format = IPACK_ID_VERSION_1;
-		dev->id_avail = ioread8(idmem + 0x15);
-		if ((dev->id_avail < 0x0c) || (dev->id_avail > 0x40)) {
-			dev_warn(&dev->dev, "invalid id size");
-			dev->id_avail = 0x0c;
-		}
-	} else if ((ioread8(idmem + 0) == 'I') &&
-			(ioread8(idmem + 1) == 'V') &&
-			(ioread8(idmem + 2) == 'A') &&
-			(ioread8(idmem + 3) == 'T') &&
-			(ioread8(idmem + 4) == ' ') &&
-			(ioread8(idmem + 5) == '4')) {
-		dev->id_format = IPACK_ID_VERSION_2;
-		dev->id_avail = ioread16be(idmem + 0x16);
-		if ((dev->id_avail < 0x1a) || (dev->id_avail > 0x40)) {
-			dev_warn(&dev->dev, "invalid id size");
-			dev->id_avail = 0x1a;
-		}
-	} else {
-		dev->id_format = IPACK_ID_VERSION_INVALID;
-		dev->id_avail = 0;
-	}
-
-	if (!dev->id_avail) {
-		ret = -ENODEV;
-		goto out;
-	}
-
-	/* Obtain the amount of memory required to store a copy of the complete
-	 * ID ROM contents */
-	dev->id = kmalloc(dev->id_avail, GFP_KERNEL);
-	if (!dev->id) {
-		dev_err(&dev->dev, "dev->id alloc failed.\n");
-		ret = -ENOMEM;
-		goto out;
-	}
-	for (i = 0; i < dev->id_avail; i++) {
-		if (dev->id_format == IPACK_ID_VERSION_1)
-			dev->id[i] = ioread8(idmem + (i << 1) + 1);
-		else
-			dev->id[i] = ioread8(idmem + i);
-	}
-
-	/* now we can finally work with the copy */
-	switch (dev->id_format) {
-	case IPACK_ID_VERSION_1:
-		ipack_parse_id1(dev);
-		break;
-	case IPACK_ID_VERSION_2:
-		ipack_parse_id2(dev);
-		break;
-	}
-
-out:
-	dev->bus->ops->unmap_space(dev, IPACK_ID_SPACE);
-
-	return ret;
-}
-
-struct ipack_device *ipack_device_register(struct ipack_bus_device *bus,
-					   int slot)
-{
-	int ret;
-	struct ipack_device *dev;
-
-	dev = kzalloc(sizeof(struct ipack_device), GFP_KERNEL);
-	if (!dev)
-		return NULL;
-
-	dev->dev.bus = &ipack_bus_type;
-	dev->dev.release = ipack_device_release;
-	dev->dev.parent = bus->parent;
-	dev->slot = slot;
-	dev->bus_nr = bus->bus_nr;
-	dev->bus = bus;
-	dev_set_name(&dev->dev,
-		     "ipack-dev.%u.%u", dev->bus_nr, dev->slot);
-
-	if (bus->ops->set_clockrate(dev, 8))
-		dev_warn(&dev->dev, "failed to switch to 8 MHz operation for reading of device ID.\n");
-	if (bus->ops->reset_timeout(dev))
-		dev_warn(&dev->dev, "failed to reset potential timeout.");
-
-	ret = ipack_device_read_id(dev);
-	if (ret < 0) {
-		dev_err(&dev->dev, "error reading device id section.\n");
-		kfree(dev);
-		return NULL;
-	}
-
-	/* if the device supports 32 MHz operation, use it. */
-	if (dev->speed_32mhz) {
-		ret = bus->ops->set_clockrate(dev, 32);
-		if (ret < 0)
-			dev_err(&dev->dev, "failed to switch to 32 MHz operation.\n");
-	}
-
-	ret = device_register(&dev->dev);
-	if (ret < 0) {
-		kfree(dev->id);
-		kfree(dev);
-		return NULL;
-	}
-
-	return dev;
-}
-EXPORT_SYMBOL_GPL(ipack_device_register);
-
-void ipack_device_unregister(struct ipack_device *dev)
-{
-	device_unregister(&dev->dev);
-}
-EXPORT_SYMBOL_GPL(ipack_device_unregister);
-
-static int __init ipack_init(void)
-{
-	ida_init(&ipack_ida);
-	return bus_register(&ipack_bus_type);
-}
-
-static void __exit ipack_exit(void)
-{
-	bus_unregister(&ipack_bus_type);
-	ida_destroy(&ipack_ida);
-}
-
-module_init(ipack_init);
-module_exit(ipack_exit);
-
-MODULE_AUTHOR("Samuel Iglesias Gonsalvez <siglesias@igalia.com>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Industry-pack bus core");
diff --git a/drivers/staging/ipack/ipack.h b/drivers/staging/ipack/ipack.h
deleted file mode 100644
index d8e3bb6..0000000
--- a/drivers/staging/ipack/ipack.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Industry-pack bus.
- *
- * (C) 2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN
- * (C) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia
- *
- * This program is free software; 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/mod_devicetable.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-
-#include "ipack_ids.h"
-
-#define IPACK_IDPROM_OFFSET_I			0x01
-#define IPACK_IDPROM_OFFSET_P			0x03
-#define IPACK_IDPROM_OFFSET_A			0x05
-#define IPACK_IDPROM_OFFSET_C			0x07
-#define IPACK_IDPROM_OFFSET_MANUFACTURER_ID	0x09
-#define IPACK_IDPROM_OFFSET_MODEL		0x0B
-#define IPACK_IDPROM_OFFSET_REVISION		0x0D
-#define IPACK_IDPROM_OFFSET_RESERVED		0x0F
-#define IPACK_IDPROM_OFFSET_DRIVER_ID_L		0x11
-#define IPACK_IDPROM_OFFSET_DRIVER_ID_H		0x13
-#define IPACK_IDPROM_OFFSET_NUM_BYTES		0x15
-#define IPACK_IDPROM_OFFSET_CRC			0x17
-
-struct ipack_bus_ops;
-struct ipack_driver;
-
-enum ipack_space {
-	IPACK_IO_SPACE    = 0,
-	IPACK_ID_SPACE    = 1,
-	IPACK_MEM_SPACE   = 2,
-	IPACK_INT_SPACE,
-};
-
-/**
- *	struct ipack_addr_space - Virtual address space mapped for a specified type.
- *
- *	@address: virtual address
- *	@size: size of the mapped space
- */
-struct ipack_addr_space {
-	void __iomem *address;
-	unsigned int size;
-};
-
-/**
- *	struct ipack_device
- *
- *	@bus_nr: IP bus number where the device is plugged
- *	@slot: Slot where the device is plugged in the carrier board
- *	@bus: ipack_bus_device where the device is plugged to.
- *	@id_space: Virtual address to ID space.
- *	@io_space: Virtual address to IO space.
- *	@mem_space: Virtual address to MEM space.
- *	@dev: device in kernel representation.
- *
- * Warning: Direct access to mapped memory is possible but the endianness
- * is not the same with PCI carrier or VME carrier. The endianness is managed
- * by the carrier board throught bus->ops.
- */
-struct ipack_device {
-	unsigned int bus_nr;
-	unsigned int slot;
-	struct ipack_bus_device *bus;
-	struct ipack_addr_space id_space;
-	struct ipack_addr_space io_space;
-	struct ipack_addr_space int_space;
-	struct ipack_addr_space mem_space;
-	struct device dev;
-	u8                      *id;
-	size_t			 id_avail;
-	u32			 id_vendor;
-	u32			 id_device;
-	u8			 id_format;
-	unsigned int		 id_crc_correct:1;
-	unsigned int		 speed_8mhz:1;
-	unsigned int		 speed_32mhz:1;
-};
-
-/**
- *	struct ipack_driver_ops -- callbacks to mezzanine driver for installing/removing one device
- *
- *	@probe: Probe function
- *	@remove: tell the driver that the carrier board wants to remove one device
- */
-
-struct ipack_driver_ops {
-	int (*probe) (struct ipack_device *dev);
-	void (*remove) (struct ipack_device *dev);
-};
-
-/**
- *	struct ipack_driver -- Specific data to each ipack board driver
- *
- *	@driver: Device driver kernel representation
- *	@ops: Mezzanine driver operations specific for the ipack bus.
- */
-struct ipack_driver {
-	struct device_driver driver;
-	const struct ipack_device_id *id_table;
-	const struct ipack_driver_ops *ops;
-};
-
-/**
- *	struct ipack_bus_ops - available operations on a bridge module
- *
- *	@map_space: map IP address space
- *	@unmap_space: unmap IP address space
- *	@request_irq: request IRQ
- *	@free_irq: free IRQ
- *	@get_clockrate: Returns the clockrate the carrier is currently
- *		communicating with the device at.
- *	@set_clockrate: Sets the clock-rate for carrier / module communication.
- *		Should return -EINVAL if the requested speed is not supported.
- *	@get_error: Returns the error state for the slot the device is attached
- *		to.
- *	@get_timeout: Returns 1 if the communication with the device has
- *		previously timed out.
- *	@reset_timeout: Resets the state returned by get_timeout.
- */
-struct ipack_bus_ops {
-	int (*map_space) (struct ipack_device *dev, unsigned int memory_size, int space);
-	int (*unmap_space) (struct ipack_device *dev, int space);
-	int (*request_irq) (struct ipack_device *dev,
-			    irqreturn_t (*handler)(void *), void *arg);
-	int (*free_irq) (struct ipack_device *dev);
-	int (*get_clockrate) (struct ipack_device *dev);
-	int (*set_clockrate) (struct ipack_device *dev, int mherz);
-	int (*get_error) (struct ipack_device *dev);
-	int (*get_timeout) (struct ipack_device *dev);
-	int (*reset_timeout) (struct ipack_device *dev);
-};
-
-/**
- *	struct ipack_bus_device
- *
- *	@dev: pointer to carrier device
- *	@slots: number of slots available
- *	@bus_nr: ipack bus number
- *	@ops: bus operations for the mezzanine drivers
- */
-struct ipack_bus_device {
-	struct device *parent;
-	int slots;
-	int bus_nr;
-	const struct ipack_bus_ops *ops;
-};
-
-/**
- *	ipack_bus_register -- register a new ipack bus
- *
- * @parent: pointer to the parent device, if any.
- * @slots: number of slots available in the bus device.
- * @ops: bus operations for the mezzanine drivers.
- *
- * The carrier board device should call this function to register itself as
- * available bus device in ipack.
- */
-struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots,
-					    const struct ipack_bus_ops *ops);
-
-/**
- *	ipack_bus_unregister -- unregister an ipack bus
- */
-int ipack_bus_unregister(struct ipack_bus_device *bus);
-
-/**
- *	ipack_driver_register -- Register a new driver
- *
- * Called by a ipack driver to register itself as a driver
- * that can manage ipack devices.
- */
-int ipack_driver_register(struct ipack_driver *edrv, struct module *owner,
-			  const char *name);
-void ipack_driver_unregister(struct ipack_driver *edrv);
-
-/**
- *	ipack_device_register -- register a new mezzanine device
- *
- * @bus: ipack bus device it is plugged to.
- * @slot: slot position in the bus device.
- *
- * Register a new ipack device (mezzanine device). The call is done by
- * the carrier device driver.
- */
-struct ipack_device *ipack_device_register(struct ipack_bus_device *bus, int slot);
-void ipack_device_unregister(struct ipack_device *dev);
-
-/**
- * DEFINE_IPACK_DEVICE_TABLE - macro used to describe a IndustryPack table
- * @_table: device table name
- *
- * This macro is used to create a struct ipack_device_id array (a device table)
- * in a generic manner.
- */
-#define DEFINE_IPACK_DEVICE_TABLE(_table) \
-	const struct ipack_device_id _table[] __devinitconst
-
-/**
- * IPACK_DEVICE - macro used to describe a specific IndustryPack device
- * @_format: the format version (currently either 1 or 2, 8 bit value)
- * @vend:    the 8 or 24 bit IndustryPack Vendor ID
- * @dev:     the 8 or 16  bit IndustryPack Device ID
- *
- * This macro is used to create a struct ipack_device_id that matches a specific
- * device.
- */
-#define IPACK_DEVICE(_format, vend, dev) \
-	 .format = (_format), \
-	 .vendor = (vend), \
-	 .device = (dev)
diff --git a/drivers/staging/ipack/ipack_ids.h b/drivers/staging/ipack/ipack_ids.h
deleted file mode 100644
index 8153fee..0000000
--- a/drivers/staging/ipack/ipack_ids.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * IndustryPack Fromat, Vendor and Device IDs.
- */
-
-/* ID section format versions */
-#define IPACK_ID_VERSION_INVALID	0x00
-#define IPACK_ID_VERSION_1		0x01
-#define IPACK_ID_VERSION_2		0x02
-
-/* Vendors and devices. Sort key: vendor first, device next. */
-#define IPACK1_VENDOR_ID_RESERVED1	0x00
-#define IPACK1_VENDOR_ID_RESERVED2	0xFF
-#define IPACK1_VENDOR_ID_UNREGISTRED01	0x01
-#define IPACK1_VENDOR_ID_UNREGISTRED02	0x02
-#define IPACK1_VENDOR_ID_UNREGISTRED03	0x03
-#define IPACK1_VENDOR_ID_UNREGISTRED04	0x04
-#define IPACK1_VENDOR_ID_UNREGISTRED05	0x05
-#define IPACK1_VENDOR_ID_UNREGISTRED06	0x06
-#define IPACK1_VENDOR_ID_UNREGISTRED07	0x07
-#define IPACK1_VENDOR_ID_UNREGISTRED08	0x08
-#define IPACK1_VENDOR_ID_UNREGISTRED09	0x09
-#define IPACK1_VENDOR_ID_UNREGISTRED10	0x0A
-#define IPACK1_VENDOR_ID_UNREGISTRED11	0x0B
-#define IPACK1_VENDOR_ID_UNREGISTRED12	0x0C
-#define IPACK1_VENDOR_ID_UNREGISTRED13	0x0D
-#define IPACK1_VENDOR_ID_UNREGISTRED14	0x0E
-#define IPACK1_VENDOR_ID_UNREGISTRED15	0x0F
-
-#define IPACK1_VENDOR_ID_SBS            0xF0
-#define IPACK1_DEVICE_ID_SBS_OCTAL_232  0x22
-#define IPACK1_DEVICE_ID_SBS_OCTAL_422  0x2A
-#define IPACK1_DEVICE_ID_SBS_OCTAL_485  0x48
diff --git a/drivers/staging/line6/Kconfig b/drivers/staging/line6/Kconfig
index 43120ff..b635436 100644
--- a/drivers/staging/line6/Kconfig
+++ b/drivers/staging/line6/Kconfig
@@ -23,32 +23,6 @@ menuconfig LINE6_USB
 
 if LINE6_USB
 
-config LINE6_USB_DEBUG
-	bool "print debug messages"
-	default n
-	help
-	  Say Y here to write debug messages to the syslog.
-
-	  If unsure, say N.
-
-config LINE6_USB_DUMP_CTRL
-	bool "dump control messages"
-	default n
-	help
-	  Say Y here to write control messages sent to and received from
-	  Line6 devices to the syslog.
-
-	  If unsure, say N.
-
-config LINE6_USB_DUMP_MIDI
-	bool "dump MIDI messages"
-	default n
-	help
-	  Say Y here to write MIDI messages sent to and received from
-	  Line6 devices to the syslog.
-
-	  If unsure, say N.
-
 config LINE6_USB_DUMP_PCM
 	bool "dump PCM data"
 	default n
@@ -59,17 +33,6 @@ config LINE6_USB_DUMP_PCM
 
 	  If unsure, say N.
 
-config LINE6_USB_RAW
-	bool "raw data communication"
-	default n
-	help
-	  Say Y here to create special files which allow to send raw data
-	  to the device. This bypasses any sanity checks, so if you discover
-	  the code to erase the firmware, feel free to render your device
-	  useless, but only after reading the GPL section "NO WARRANTY".
-
-	  If unsure, say N.
-
 config LINE6_USB_IMPULSE_RESPONSE
 	bool "measure impulse response"
 	default n
diff --git a/drivers/staging/line6/Makefile b/drivers/staging/line6/Makefile
index 34a2dda..ae5c374 100644
--- a/drivers/staging/line6/Makefile
+++ b/drivers/staging/line6/Makefile
@@ -3,9 +3,7 @@ obj-$(CONFIG_LINE6_USB)		+= line6usb.o
 line6usb-y := 		\
 		audio.o		\
 		capture.o	\
-		control.o	\
 		driver.o	\
-		dumprequest.o	\
 		midi.o		\
 		midibuf.o	\
 		pcm.o		\
diff --git a/drivers/staging/line6/audio.c b/drivers/staging/line6/audio.c
index 8e73983..a92e21f 100644
--- a/drivers/staging/line6/audio.c
+++ b/drivers/staging/line6/audio.c
@@ -16,20 +16,16 @@
 #include "driver.h"
 #include "audio.h"
 
-static int line6_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
-static char *line6_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-
 /*
 	Initialize the Line6 USB audio system.
 */
 int line6_init_audio(struct usb_line6 *line6)
 {
-	static int dev;
 	struct snd_card *card;
 	int err;
 
-	err = snd_card_create(line6_index[dev], line6_id[dev], THIS_MODULE, 0,
-			      &card);
+	err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			      THIS_MODULE, 0, &card);
 	if (err < 0)
 		return err;
 
diff --git a/drivers/staging/line6/capture.c b/drivers/staging/line6/capture.c
index c85c5b6..389c41f 100644
--- a/drivers/staging/line6/capture.c
+++ b/drivers/staging/line6/capture.c
@@ -256,8 +256,8 @@ static void audio_in_callback(struct urb *urb)
 #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
 		if (!(line6pcm->flags & LINE6_BITS_PCM_IMPULSE))
 #endif
-			if (test_bit(LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM, &line6pcm->flags)
-			    && (fsize > 0))
+			if (test_bit(LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM,
+				     &line6pcm->flags) && (fsize > 0))
 				line6_capture_copy(line6pcm, fbuf, fsize);
 	}
 
@@ -274,7 +274,8 @@ static void audio_in_callback(struct urb *urb)
 #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
 		if (!(line6pcm->flags & LINE6_BITS_PCM_IMPULSE))
 #endif
-			if (test_bit(LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM, &line6pcm->flags))
+			if (test_bit(LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM,
+				     &line6pcm->flags))
 				line6_capture_check_period(line6pcm, length);
 	}
 }
@@ -356,7 +357,8 @@ int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd)
 #ifdef CONFIG_PM
 	case SNDRV_PCM_TRIGGER_RESUME:
 #endif
-		err = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_STREAM);
+		err = line6_pcm_acquire(line6pcm,
+					LINE6_BIT_PCM_ALSA_CAPTURE_STREAM);
 
 		if (err < 0)
 			return err;
@@ -367,7 +369,8 @@ int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd)
 #ifdef CONFIG_PM
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 #endif
-		err = line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_STREAM);
+		err = line6_pcm_release(line6pcm,
+					LINE6_BIT_PCM_ALSA_CAPTURE_STREAM);
 
 		if (err < 0)
 			return err;
diff --git a/drivers/staging/line6/control.c b/drivers/staging/line6/control.c
deleted file mode 100644
index f8326f5..0000000
--- a/drivers/staging/line6/control.c
+++ /dev/null
@@ -1,995 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	This program is free software; 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.
- *
- */
-
-#include <linux/usb.h>
-
-#include "control.h"
-#include "driver.h"
-#include "pod.h"
-#include "usbdefs.h"
-#include "variax.h"
-
-#define DEVICE_ATTR2(_name1, _name2, _mode, _show, _store) \
-struct device_attribute dev_attr_##_name1 = __ATTR(_name2, _mode, _show, _store)
-
-#define LINE6_PARAM_R(PREFIX, prefix, type, param) \
-static ssize_t prefix##_get_##param(struct device *dev, \
-			struct device_attribute *attr, char *buf) \
-{ \
-	return prefix##_get_param_##type(dev, buf, PREFIX##_##param); \
-}
-
-#define LINE6_PARAM_RW(PREFIX, prefix, type, param) \
-LINE6_PARAM_R(PREFIX, prefix, type, param); \
-static ssize_t prefix##_set_##param(struct device *dev, \
-		struct device_attribute *attr, const char *buf, size_t count) \
-{ \
-	return prefix##_set_param_##type(dev, buf, count, PREFIX##_##param); \
-}
-
-#define POD_PARAM_R(type, param) LINE6_PARAM_R(POD, pod, type, param)
-#define POD_PARAM_RW(type, param) LINE6_PARAM_RW(POD, pod, type, param)
-#define VARIAX_PARAM_R(type, param) LINE6_PARAM_R(VARIAX, variax, type, param)
-#define VARIAX_PARAM_RW(type, param) LINE6_PARAM_RW(VARIAX, variax, type, param)
-
-static ssize_t pod_get_param_int(struct device *dev, char *buf, int param)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-	int retval = line6_dump_wait_interruptible(&pod->dumpreq);
-	if (retval < 0)
-		return retval;
-	return sprintf(buf, "%d\n", pod->prog_data.control[param]);
-}
-
-static ssize_t pod_set_param_int(struct device *dev, const char *buf,
-				 size_t count, int param)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-	u8 value;
-	int retval;
-
-	retval = kstrtou8(buf, 10, &value);
-	if (retval)
-		return retval;
-
-	line6_pod_transmit_parameter(pod, param, value);
-	return count;
-}
-
-static ssize_t variax_get_param_int(struct device *dev, char *buf, int param)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_variax *variax = usb_get_intfdata(interface);
-	int retval = line6_dump_wait_interruptible(&variax->dumpreq);
-	if (retval < 0)
-		return retval;
-	return sprintf(buf, "%d\n", variax->model_data.control[param]);
-}
-
-static ssize_t variax_get_param_float(struct device *dev, char *buf, int param)
-{
-	/*
-	   We do our own floating point handling here since at the time
-	   this code was written (Jan 2006) it was highly discouraged to
-	   use floating point arithmetic in the kernel. If you think that
-	   this no longer applies, feel free to replace this by generic
-	   floating point code.
-	 */
-
-	static const int BIAS = 0x7f;
-	static const int OFFSET = 0xf;
-	static const int PRECISION = 1000;
-
-	int len = 0;
-	unsigned part_int, part_frac;
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_variax *variax = usb_get_intfdata(interface);
-	const unsigned char *p = variax->model_data.control + param;
-	int retval = line6_dump_wait_interruptible(&variax->dumpreq);
-	if (retval < 0)
-		return retval;
-
-	if ((p[0] == 0) && (p[1] == 0) && (p[2] == 0))
-		part_int = part_frac = 0;
-	else {
-		int exponent = (((p[0] & 0x7f) << 1) | (p[1] >> 7)) - BIAS;
-		unsigned mantissa = (p[1] << 8) | p[2] | 0x8000;
-		exponent -= OFFSET;
-
-		if (exponent >= 0) {
-			part_int = mantissa << exponent;
-			part_frac = 0;
-		} else {
-			part_int = mantissa >> -exponent;
-			part_frac = (mantissa << (32 + exponent)) & 0xffffffff;
-		}
-
-		part_frac =
-		    (part_frac / ((1UL << 31) / (PRECISION / 2 * 10)) + 5) / 10;
-	}
-
-	len +=
-	    sprintf(buf + len, "%s%d.%03d\n", ((p[0] & 0x80) ? "-" : ""),
-		    part_int, part_frac);
-	return len;
-}
-
-POD_PARAM_RW(int, tweak);
-POD_PARAM_RW(int, wah_position);
-POD_PARAM_RW(int, compression_gain);
-POD_PARAM_RW(int, vol_pedal_position);
-POD_PARAM_RW(int, compression_threshold);
-POD_PARAM_RW(int, pan);
-POD_PARAM_RW(int, amp_model_setup);
-POD_PARAM_RW(int, amp_model);
-POD_PARAM_RW(int, drive);
-POD_PARAM_RW(int, bass);
-POD_PARAM_RW(int, mid);
-POD_PARAM_RW(int, lowmid);
-POD_PARAM_RW(int, treble);
-POD_PARAM_RW(int, highmid);
-POD_PARAM_RW(int, chan_vol);
-POD_PARAM_RW(int, reverb_mix);
-POD_PARAM_RW(int, effect_setup);
-POD_PARAM_RW(int, band_1_frequency);
-POD_PARAM_RW(int, presence);
-POD_PARAM_RW(int, treble__bass);
-POD_PARAM_RW(int, noise_gate_enable);
-POD_PARAM_RW(int, gate_threshold);
-POD_PARAM_RW(int, gate_decay_time);
-POD_PARAM_RW(int, stomp_enable);
-POD_PARAM_RW(int, comp_enable);
-POD_PARAM_RW(int, stomp_time);
-POD_PARAM_RW(int, delay_enable);
-POD_PARAM_RW(int, mod_param_1);
-POD_PARAM_RW(int, delay_param_1);
-POD_PARAM_RW(int, delay_param_1_note_value);
-POD_PARAM_RW(int, band_2_frequency__bass);
-POD_PARAM_RW(int, delay_param_2);
-POD_PARAM_RW(int, delay_volume_mix);
-POD_PARAM_RW(int, delay_param_3);
-POD_PARAM_RW(int, reverb_enable);
-POD_PARAM_RW(int, reverb_type);
-POD_PARAM_RW(int, reverb_decay);
-POD_PARAM_RW(int, reverb_tone);
-POD_PARAM_RW(int, reverb_pre_delay);
-POD_PARAM_RW(int, reverb_pre_post);
-POD_PARAM_RW(int, band_2_frequency);
-POD_PARAM_RW(int, band_3_frequency__bass);
-POD_PARAM_RW(int, wah_enable);
-POD_PARAM_RW(int, modulation_lo_cut);
-POD_PARAM_RW(int, delay_reverb_lo_cut);
-POD_PARAM_RW(int, volume_pedal_minimum);
-POD_PARAM_RW(int, eq_pre_post);
-POD_PARAM_RW(int, volume_pre_post);
-POD_PARAM_RW(int, di_model);
-POD_PARAM_RW(int, di_delay);
-POD_PARAM_RW(int, mod_enable);
-POD_PARAM_RW(int, mod_param_1_note_value);
-POD_PARAM_RW(int, mod_param_2);
-POD_PARAM_RW(int, mod_param_3);
-POD_PARAM_RW(int, mod_param_4);
-POD_PARAM_RW(int, mod_param_5);
-POD_PARAM_RW(int, mod_volume_mix);
-POD_PARAM_RW(int, mod_pre_post);
-POD_PARAM_RW(int, modulation_model);
-POD_PARAM_RW(int, band_3_frequency);
-POD_PARAM_RW(int, band_4_frequency__bass);
-POD_PARAM_RW(int, mod_param_1_double_precision);
-POD_PARAM_RW(int, delay_param_1_double_precision);
-POD_PARAM_RW(int, eq_enable);
-POD_PARAM_RW(int, tap);
-POD_PARAM_RW(int, volume_tweak_pedal_assign);
-POD_PARAM_RW(int, band_5_frequency);
-POD_PARAM_RW(int, tuner);
-POD_PARAM_RW(int, mic_selection);
-POD_PARAM_RW(int, cabinet_model);
-POD_PARAM_RW(int, stomp_model);
-POD_PARAM_RW(int, roomlevel);
-POD_PARAM_RW(int, band_4_frequency);
-POD_PARAM_RW(int, band_6_frequency);
-POD_PARAM_RW(int, stomp_param_1_note_value);
-POD_PARAM_RW(int, stomp_param_2);
-POD_PARAM_RW(int, stomp_param_3);
-POD_PARAM_RW(int, stomp_param_4);
-POD_PARAM_RW(int, stomp_param_5);
-POD_PARAM_RW(int, stomp_param_6);
-POD_PARAM_RW(int, amp_switch_select);
-POD_PARAM_RW(int, delay_param_4);
-POD_PARAM_RW(int, delay_param_5);
-POD_PARAM_RW(int, delay_pre_post);
-POD_PARAM_RW(int, delay_model);
-POD_PARAM_RW(int, delay_verb_model);
-POD_PARAM_RW(int, tempo_msb);
-POD_PARAM_RW(int, tempo_lsb);
-POD_PARAM_RW(int, wah_model);
-POD_PARAM_RW(int, bypass_volume);
-POD_PARAM_RW(int, fx_loop_on_off);
-POD_PARAM_RW(int, tweak_param_select);
-POD_PARAM_RW(int, amp1_engage);
-POD_PARAM_RW(int, band_1_gain);
-POD_PARAM_RW(int, band_2_gain__bass);
-POD_PARAM_RW(int, band_2_gain);
-POD_PARAM_RW(int, band_3_gain__bass);
-POD_PARAM_RW(int, band_3_gain);
-POD_PARAM_RW(int, band_4_gain__bass);
-POD_PARAM_RW(int, band_5_gain__bass);
-POD_PARAM_RW(int, band_4_gain);
-POD_PARAM_RW(int, band_6_gain__bass);
-VARIAX_PARAM_R(int, body);
-VARIAX_PARAM_R(int, pickup1_enable);
-VARIAX_PARAM_R(int, pickup1_type);
-VARIAX_PARAM_R(float, pickup1_position);
-VARIAX_PARAM_R(float, pickup1_angle);
-VARIAX_PARAM_R(float, pickup1_level);
-VARIAX_PARAM_R(int, pickup2_enable);
-VARIAX_PARAM_R(int, pickup2_type);
-VARIAX_PARAM_R(float, pickup2_position);
-VARIAX_PARAM_R(float, pickup2_angle);
-VARIAX_PARAM_R(float, pickup2_level);
-VARIAX_PARAM_R(int, pickup_phase);
-VARIAX_PARAM_R(float, capacitance);
-VARIAX_PARAM_R(float, tone_resistance);
-VARIAX_PARAM_R(float, volume_resistance);
-VARIAX_PARAM_R(int, taper);
-VARIAX_PARAM_R(float, tone_dump);
-VARIAX_PARAM_R(int, save_tone);
-VARIAX_PARAM_R(float, volume_dump);
-VARIAX_PARAM_R(int, tuning_enable);
-VARIAX_PARAM_R(int, tuning6);
-VARIAX_PARAM_R(int, tuning5);
-VARIAX_PARAM_R(int, tuning4);
-VARIAX_PARAM_R(int, tuning3);
-VARIAX_PARAM_R(int, tuning2);
-VARIAX_PARAM_R(int, tuning1);
-VARIAX_PARAM_R(float, detune6);
-VARIAX_PARAM_R(float, detune5);
-VARIAX_PARAM_R(float, detune4);
-VARIAX_PARAM_R(float, detune3);
-VARIAX_PARAM_R(float, detune2);
-VARIAX_PARAM_R(float, detune1);
-VARIAX_PARAM_R(float, mix6);
-VARIAX_PARAM_R(float, mix5);
-VARIAX_PARAM_R(float, mix4);
-VARIAX_PARAM_R(float, mix3);
-VARIAX_PARAM_R(float, mix2);
-VARIAX_PARAM_R(float, mix1);
-VARIAX_PARAM_R(int, pickup_wiring);
-
-static DEVICE_ATTR(tweak, S_IWUSR | S_IRUGO, pod_get_tweak, pod_set_tweak);
-static DEVICE_ATTR(wah_position, S_IWUSR | S_IRUGO, pod_get_wah_position,
-		   pod_set_wah_position);
-static DEVICE_ATTR(compression_gain, S_IWUSR | S_IRUGO,
-		   pod_get_compression_gain, pod_set_compression_gain);
-static DEVICE_ATTR(vol_pedal_position, S_IWUSR | S_IRUGO,
-		   pod_get_vol_pedal_position, pod_set_vol_pedal_position);
-static DEVICE_ATTR(compression_threshold, S_IWUSR | S_IRUGO,
-		   pod_get_compression_threshold,
-		   pod_set_compression_threshold);
-static DEVICE_ATTR(pan, S_IWUSR | S_IRUGO, pod_get_pan, pod_set_pan);
-static DEVICE_ATTR(amp_model_setup, S_IWUSR | S_IRUGO, pod_get_amp_model_setup,
-		   pod_set_amp_model_setup);
-static DEVICE_ATTR(amp_model, S_IWUSR | S_IRUGO, pod_get_amp_model,
-		   pod_set_amp_model);
-static DEVICE_ATTR(drive, S_IWUSR | S_IRUGO, pod_get_drive, pod_set_drive);
-static DEVICE_ATTR(bass, S_IWUSR | S_IRUGO, pod_get_bass, pod_set_bass);
-static DEVICE_ATTR(mid, S_IWUSR | S_IRUGO, pod_get_mid, pod_set_mid);
-static DEVICE_ATTR(lowmid, S_IWUSR | S_IRUGO, pod_get_lowmid, pod_set_lowmid);
-static DEVICE_ATTR(treble, S_IWUSR | S_IRUGO, pod_get_treble, pod_set_treble);
-static DEVICE_ATTR(highmid, S_IWUSR | S_IRUGO, pod_get_highmid,
-		   pod_set_highmid);
-static DEVICE_ATTR(chan_vol, S_IWUSR | S_IRUGO, pod_get_chan_vol,
-		   pod_set_chan_vol);
-static DEVICE_ATTR(reverb_mix, S_IWUSR | S_IRUGO, pod_get_reverb_mix,
-		   pod_set_reverb_mix);
-static DEVICE_ATTR(effect_setup, S_IWUSR | S_IRUGO, pod_get_effect_setup,
-		   pod_set_effect_setup);
-static DEVICE_ATTR(band_1_frequency, S_IWUSR | S_IRUGO,
-		   pod_get_band_1_frequency, pod_set_band_1_frequency);
-static DEVICE_ATTR(presence, S_IWUSR | S_IRUGO, pod_get_presence,
-		   pod_set_presence);
-static DEVICE_ATTR2(treble__bass, treble, S_IWUSR | S_IRUGO,
-		    pod_get_treble__bass, pod_set_treble__bass);
-static DEVICE_ATTR(noise_gate_enable, S_IWUSR | S_IRUGO,
-		   pod_get_noise_gate_enable, pod_set_noise_gate_enable);
-static DEVICE_ATTR(gate_threshold, S_IWUSR | S_IRUGO, pod_get_gate_threshold,
-		   pod_set_gate_threshold);
-static DEVICE_ATTR(gate_decay_time, S_IWUSR | S_IRUGO, pod_get_gate_decay_time,
-		   pod_set_gate_decay_time);
-static DEVICE_ATTR(stomp_enable, S_IWUSR | S_IRUGO, pod_get_stomp_enable,
-		   pod_set_stomp_enable);
-static DEVICE_ATTR(comp_enable, S_IWUSR | S_IRUGO, pod_get_comp_enable,
-		   pod_set_comp_enable);
-static DEVICE_ATTR(stomp_time, S_IWUSR | S_IRUGO, pod_get_stomp_time,
-		   pod_set_stomp_time);
-static DEVICE_ATTR(delay_enable, S_IWUSR | S_IRUGO, pod_get_delay_enable,
-		   pod_set_delay_enable);
-static DEVICE_ATTR(mod_param_1, S_IWUSR | S_IRUGO, pod_get_mod_param_1,
-		   pod_set_mod_param_1);
-static DEVICE_ATTR(delay_param_1, S_IWUSR | S_IRUGO, pod_get_delay_param_1,
-		   pod_set_delay_param_1);
-static DEVICE_ATTR(delay_param_1_note_value, S_IWUSR | S_IRUGO,
-		   pod_get_delay_param_1_note_value,
-		   pod_set_delay_param_1_note_value);
-static DEVICE_ATTR2(band_2_frequency__bass, band_2_frequency, S_IWUSR | S_IRUGO,
-		    pod_get_band_2_frequency__bass,
-		    pod_set_band_2_frequency__bass);
-static DEVICE_ATTR(delay_param_2, S_IWUSR | S_IRUGO, pod_get_delay_param_2,
-		   pod_set_delay_param_2);
-static DEVICE_ATTR(delay_volume_mix, S_IWUSR | S_IRUGO,
-		   pod_get_delay_volume_mix, pod_set_delay_volume_mix);
-static DEVICE_ATTR(delay_param_3, S_IWUSR | S_IRUGO, pod_get_delay_param_3,
-		   pod_set_delay_param_3);
-static DEVICE_ATTR(reverb_enable, S_IWUSR | S_IRUGO, pod_get_reverb_enable,
-		   pod_set_reverb_enable);
-static DEVICE_ATTR(reverb_type, S_IWUSR | S_IRUGO, pod_get_reverb_type,
-		   pod_set_reverb_type);
-static DEVICE_ATTR(reverb_decay, S_IWUSR | S_IRUGO, pod_get_reverb_decay,
-		   pod_set_reverb_decay);
-static DEVICE_ATTR(reverb_tone, S_IWUSR | S_IRUGO, pod_get_reverb_tone,
-		   pod_set_reverb_tone);
-static DEVICE_ATTR(reverb_pre_delay, S_IWUSR | S_IRUGO,
-		   pod_get_reverb_pre_delay, pod_set_reverb_pre_delay);
-static DEVICE_ATTR(reverb_pre_post, S_IWUSR | S_IRUGO, pod_get_reverb_pre_post,
-		   pod_set_reverb_pre_post);
-static DEVICE_ATTR(band_2_frequency, S_IWUSR | S_IRUGO,
-		   pod_get_band_2_frequency, pod_set_band_2_frequency);
-static DEVICE_ATTR2(band_3_frequency__bass, band_3_frequency, S_IWUSR | S_IRUGO,
-		    pod_get_band_3_frequency__bass,
-		    pod_set_band_3_frequency__bass);
-static DEVICE_ATTR(wah_enable, S_IWUSR | S_IRUGO, pod_get_wah_enable,
-		   pod_set_wah_enable);
-static DEVICE_ATTR(modulation_lo_cut, S_IWUSR | S_IRUGO,
-		   pod_get_modulation_lo_cut, pod_set_modulation_lo_cut);
-static DEVICE_ATTR(delay_reverb_lo_cut, S_IWUSR | S_IRUGO,
-		   pod_get_delay_reverb_lo_cut, pod_set_delay_reverb_lo_cut);
-static DEVICE_ATTR(volume_pedal_minimum, S_IWUSR | S_IRUGO,
-		   pod_get_volume_pedal_minimum, pod_set_volume_pedal_minimum);
-static DEVICE_ATTR(eq_pre_post, S_IWUSR | S_IRUGO, pod_get_eq_pre_post,
-		   pod_set_eq_pre_post);
-static DEVICE_ATTR(volume_pre_post, S_IWUSR | S_IRUGO, pod_get_volume_pre_post,
-		   pod_set_volume_pre_post);
-static DEVICE_ATTR(di_model, S_IWUSR | S_IRUGO, pod_get_di_model,
-		   pod_set_di_model);
-static DEVICE_ATTR(di_delay, S_IWUSR | S_IRUGO, pod_get_di_delay,
-		   pod_set_di_delay);
-static DEVICE_ATTR(mod_enable, S_IWUSR | S_IRUGO, pod_get_mod_enable,
-		   pod_set_mod_enable);
-static DEVICE_ATTR(mod_param_1_note_value, S_IWUSR | S_IRUGO,
-		   pod_get_mod_param_1_note_value,
-		   pod_set_mod_param_1_note_value);
-static DEVICE_ATTR(mod_param_2, S_IWUSR | S_IRUGO, pod_get_mod_param_2,
-		   pod_set_mod_param_2);
-static DEVICE_ATTR(mod_param_3, S_IWUSR | S_IRUGO, pod_get_mod_param_3,
-		   pod_set_mod_param_3);
-static DEVICE_ATTR(mod_param_4, S_IWUSR | S_IRUGO, pod_get_mod_param_4,
-		   pod_set_mod_param_4);
-static DEVICE_ATTR(mod_param_5, S_IWUSR | S_IRUGO, pod_get_mod_param_5,
-		   pod_set_mod_param_5);
-static DEVICE_ATTR(mod_volume_mix, S_IWUSR | S_IRUGO, pod_get_mod_volume_mix,
-		   pod_set_mod_volume_mix);
-static DEVICE_ATTR(mod_pre_post, S_IWUSR | S_IRUGO, pod_get_mod_pre_post,
-		   pod_set_mod_pre_post);
-static DEVICE_ATTR(modulation_model, S_IWUSR | S_IRUGO,
-		   pod_get_modulation_model, pod_set_modulation_model);
-static DEVICE_ATTR(band_3_frequency, S_IWUSR | S_IRUGO,
-		   pod_get_band_3_frequency, pod_set_band_3_frequency);
-static DEVICE_ATTR2(band_4_frequency__bass, band_4_frequency, S_IWUSR | S_IRUGO,
-		    pod_get_band_4_frequency__bass,
-		    pod_set_band_4_frequency__bass);
-static DEVICE_ATTR(mod_param_1_double_precision, S_IWUSR | S_IRUGO,
-		   pod_get_mod_param_1_double_precision,
-		   pod_set_mod_param_1_double_precision);
-static DEVICE_ATTR(delay_param_1_double_precision, S_IWUSR | S_IRUGO,
-		   pod_get_delay_param_1_double_precision,
-		   pod_set_delay_param_1_double_precision);
-static DEVICE_ATTR(eq_enable, S_IWUSR | S_IRUGO, pod_get_eq_enable,
-		   pod_set_eq_enable);
-static DEVICE_ATTR(tap, S_IWUSR | S_IRUGO, pod_get_tap, pod_set_tap);
-static DEVICE_ATTR(volume_tweak_pedal_assign, S_IWUSR | S_IRUGO,
-		   pod_get_volume_tweak_pedal_assign,
-		   pod_set_volume_tweak_pedal_assign);
-static DEVICE_ATTR(band_5_frequency, S_IWUSR | S_IRUGO,
-		   pod_get_band_5_frequency, pod_set_band_5_frequency);
-static DEVICE_ATTR(tuner, S_IWUSR | S_IRUGO, pod_get_tuner, pod_set_tuner);
-static DEVICE_ATTR(mic_selection, S_IWUSR | S_IRUGO, pod_get_mic_selection,
-		   pod_set_mic_selection);
-static DEVICE_ATTR(cabinet_model, S_IWUSR | S_IRUGO, pod_get_cabinet_model,
-		   pod_set_cabinet_model);
-static DEVICE_ATTR(stomp_model, S_IWUSR | S_IRUGO, pod_get_stomp_model,
-		   pod_set_stomp_model);
-static DEVICE_ATTR(roomlevel, S_IWUSR | S_IRUGO, pod_get_roomlevel,
-		   pod_set_roomlevel);
-static DEVICE_ATTR(band_4_frequency, S_IWUSR | S_IRUGO,
-		   pod_get_band_4_frequency, pod_set_band_4_frequency);
-static DEVICE_ATTR(band_6_frequency, S_IWUSR | S_IRUGO,
-		   pod_get_band_6_frequency, pod_set_band_6_frequency);
-static DEVICE_ATTR(stomp_param_1_note_value, S_IWUSR | S_IRUGO,
-		   pod_get_stomp_param_1_note_value,
-		   pod_set_stomp_param_1_note_value);
-static DEVICE_ATTR(stomp_param_2, S_IWUSR | S_IRUGO, pod_get_stomp_param_2,
-		   pod_set_stomp_param_2);
-static DEVICE_ATTR(stomp_param_3, S_IWUSR | S_IRUGO, pod_get_stomp_param_3,
-		   pod_set_stomp_param_3);
-static DEVICE_ATTR(stomp_param_4, S_IWUSR | S_IRUGO, pod_get_stomp_param_4,
-		   pod_set_stomp_param_4);
-static DEVICE_ATTR(stomp_param_5, S_IWUSR | S_IRUGO, pod_get_stomp_param_5,
-		   pod_set_stomp_param_5);
-static DEVICE_ATTR(stomp_param_6, S_IWUSR | S_IRUGO, pod_get_stomp_param_6,
-		   pod_set_stomp_param_6);
-static DEVICE_ATTR(amp_switch_select, S_IWUSR | S_IRUGO,
-		   pod_get_amp_switch_select, pod_set_amp_switch_select);
-static DEVICE_ATTR(delay_param_4, S_IWUSR | S_IRUGO, pod_get_delay_param_4,
-		   pod_set_delay_param_4);
-static DEVICE_ATTR(delay_param_5, S_IWUSR | S_IRUGO, pod_get_delay_param_5,
-		   pod_set_delay_param_5);
-static DEVICE_ATTR(delay_pre_post, S_IWUSR | S_IRUGO, pod_get_delay_pre_post,
-		   pod_set_delay_pre_post);
-static DEVICE_ATTR(delay_model, S_IWUSR | S_IRUGO, pod_get_delay_model,
-		   pod_set_delay_model);
-static DEVICE_ATTR(delay_verb_model, S_IWUSR | S_IRUGO,
-		   pod_get_delay_verb_model, pod_set_delay_verb_model);
-static DEVICE_ATTR(tempo_msb, S_IWUSR | S_IRUGO, pod_get_tempo_msb,
-		   pod_set_tempo_msb);
-static DEVICE_ATTR(tempo_lsb, S_IWUSR | S_IRUGO, pod_get_tempo_lsb,
-		   pod_set_tempo_lsb);
-static DEVICE_ATTR(wah_model, S_IWUSR | S_IRUGO, pod_get_wah_model,
-		   pod_set_wah_model);
-static DEVICE_ATTR(bypass_volume, S_IWUSR | S_IRUGO, pod_get_bypass_volume,
-		   pod_set_bypass_volume);
-static DEVICE_ATTR(fx_loop_on_off, S_IWUSR | S_IRUGO, pod_get_fx_loop_on_off,
-		   pod_set_fx_loop_on_off);
-static DEVICE_ATTR(tweak_param_select, S_IWUSR | S_IRUGO,
-		   pod_get_tweak_param_select, pod_set_tweak_param_select);
-static DEVICE_ATTR(amp1_engage, S_IWUSR | S_IRUGO, pod_get_amp1_engage,
-		   pod_set_amp1_engage);
-static DEVICE_ATTR(band_1_gain, S_IWUSR | S_IRUGO, pod_get_band_1_gain,
-		   pod_set_band_1_gain);
-static DEVICE_ATTR2(band_2_gain__bass, band_2_gain, S_IWUSR | S_IRUGO,
-		    pod_get_band_2_gain__bass, pod_set_band_2_gain__bass);
-static DEVICE_ATTR(band_2_gain, S_IWUSR | S_IRUGO, pod_get_band_2_gain,
-		   pod_set_band_2_gain);
-static DEVICE_ATTR2(band_3_gain__bass, band_3_gain, S_IWUSR | S_IRUGO,
-		    pod_get_band_3_gain__bass, pod_set_band_3_gain__bass);
-static DEVICE_ATTR(band_3_gain, S_IWUSR | S_IRUGO, pod_get_band_3_gain,
-		   pod_set_band_3_gain);
-static DEVICE_ATTR2(band_4_gain__bass, band_4_gain, S_IWUSR | S_IRUGO,
-		    pod_get_band_4_gain__bass, pod_set_band_4_gain__bass);
-static DEVICE_ATTR2(band_5_gain__bass, band_5_gain, S_IWUSR | S_IRUGO,
-		    pod_get_band_5_gain__bass, pod_set_band_5_gain__bass);
-static DEVICE_ATTR(band_4_gain, S_IWUSR | S_IRUGO, pod_get_band_4_gain,
-		   pod_set_band_4_gain);
-static DEVICE_ATTR2(band_6_gain__bass, band_6_gain, S_IWUSR | S_IRUGO,
-		    pod_get_band_6_gain__bass, pod_set_band_6_gain__bass);
-static DEVICE_ATTR(body, S_IRUGO, variax_get_body, line6_nop_write);
-static DEVICE_ATTR(pickup1_enable, S_IRUGO, variax_get_pickup1_enable,
-		   line6_nop_write);
-static DEVICE_ATTR(pickup1_type, S_IRUGO, variax_get_pickup1_type,
-		   line6_nop_write);
-static DEVICE_ATTR(pickup1_position, S_IRUGO, variax_get_pickup1_position,
-		   line6_nop_write);
-static DEVICE_ATTR(pickup1_angle, S_IRUGO, variax_get_pickup1_angle,
-		   line6_nop_write);
-static DEVICE_ATTR(pickup1_level, S_IRUGO, variax_get_pickup1_level,
-		   line6_nop_write);
-static DEVICE_ATTR(pickup2_enable, S_IRUGO, variax_get_pickup2_enable,
-		   line6_nop_write);
-static DEVICE_ATTR(pickup2_type, S_IRUGO, variax_get_pickup2_type,
-		   line6_nop_write);
-static DEVICE_ATTR(pickup2_position, S_IRUGO, variax_get_pickup2_position,
-		   line6_nop_write);
-static DEVICE_ATTR(pickup2_angle, S_IRUGO, variax_get_pickup2_angle,
-		   line6_nop_write);
-static DEVICE_ATTR(pickup2_level, S_IRUGO, variax_get_pickup2_level,
-		   line6_nop_write);
-static DEVICE_ATTR(pickup_phase, S_IRUGO, variax_get_pickup_phase,
-		   line6_nop_write);
-static DEVICE_ATTR(capacitance, S_IRUGO, variax_get_capacitance,
-		   line6_nop_write);
-static DEVICE_ATTR(tone_resistance, S_IRUGO, variax_get_tone_resistance,
-		   line6_nop_write);
-static DEVICE_ATTR(volume_resistance, S_IRUGO, variax_get_volume_resistance,
-		   line6_nop_write);
-static DEVICE_ATTR(taper, S_IRUGO, variax_get_taper, line6_nop_write);
-static DEVICE_ATTR(tone_dump, S_IRUGO, variax_get_tone_dump, line6_nop_write);
-static DEVICE_ATTR(save_tone, S_IRUGO, variax_get_save_tone, line6_nop_write);
-static DEVICE_ATTR(volume_dump, S_IRUGO, variax_get_volume_dump,
-		   line6_nop_write);
-static DEVICE_ATTR(tuning_enable, S_IRUGO, variax_get_tuning_enable,
-		   line6_nop_write);
-static DEVICE_ATTR(tuning6, S_IRUGO, variax_get_tuning6, line6_nop_write);
-static DEVICE_ATTR(tuning5, S_IRUGO, variax_get_tuning5, line6_nop_write);
-static DEVICE_ATTR(tuning4, S_IRUGO, variax_get_tuning4, line6_nop_write);
-static DEVICE_ATTR(tuning3, S_IRUGO, variax_get_tuning3, line6_nop_write);
-static DEVICE_ATTR(tuning2, S_IRUGO, variax_get_tuning2, line6_nop_write);
-static DEVICE_ATTR(tuning1, S_IRUGO, variax_get_tuning1, line6_nop_write);
-static DEVICE_ATTR(detune6, S_IRUGO, variax_get_detune6, line6_nop_write);
-static DEVICE_ATTR(detune5, S_IRUGO, variax_get_detune5, line6_nop_write);
-static DEVICE_ATTR(detune4, S_IRUGO, variax_get_detune4, line6_nop_write);
-static DEVICE_ATTR(detune3, S_IRUGO, variax_get_detune3, line6_nop_write);
-static DEVICE_ATTR(detune2, S_IRUGO, variax_get_detune2, line6_nop_write);
-static DEVICE_ATTR(detune1, S_IRUGO, variax_get_detune1, line6_nop_write);
-static DEVICE_ATTR(mix6, S_IRUGO, variax_get_mix6, line6_nop_write);
-static DEVICE_ATTR(mix5, S_IRUGO, variax_get_mix5, line6_nop_write);
-static DEVICE_ATTR(mix4, S_IRUGO, variax_get_mix4, line6_nop_write);
-static DEVICE_ATTR(mix3, S_IRUGO, variax_get_mix3, line6_nop_write);
-static DEVICE_ATTR(mix2, S_IRUGO, variax_get_mix2, line6_nop_write);
-static DEVICE_ATTR(mix1, S_IRUGO, variax_get_mix1, line6_nop_write);
-static DEVICE_ATTR(pickup_wiring, S_IRUGO, variax_get_pickup_wiring,
-		   line6_nop_write);
-
-int line6_pod_create_files(int firmware, int type, struct device *dev)
-{
-	int err;
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tweak));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_wah_position));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		CHECK_RETURN(device_create_file
-			     (dev, &dev_attr_compression_gain));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_vol_pedal_position));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_compression_threshold));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_pan));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_amp_model_setup));
-	if (firmware >= 200)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_amp_model));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_drive));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_bass));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_mid));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_lowmid));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_treble));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_highmid));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_chan_vol));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_mix));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_effect_setup));
-	if (firmware >= 200)
-		CHECK_RETURN(device_create_file
-			     (dev, &dev_attr_band_1_frequency));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_presence));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_treble__bass));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_noise_gate_enable));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_gate_threshold));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_gate_decay_time));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_enable));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_comp_enable));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_time));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_delay_enable));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_1));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_1));
-	CHECK_RETURN(device_create_file
-		     (dev, &dev_attr_delay_param_1_note_value));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_band_2_frequency__bass));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_2));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_delay_volume_mix));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_3));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_enable));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_type));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_decay));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_tone));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		CHECK_RETURN(device_create_file
-			     (dev, &dev_attr_reverb_pre_delay));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		CHECK_RETURN(device_create_file
-			     (dev, &dev_attr_reverb_pre_post));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_band_2_frequency));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_band_3_frequency__bass));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_wah_enable));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		CHECK_RETURN(device_create_file
-			     (dev, &dev_attr_modulation_lo_cut));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		CHECK_RETURN(device_create_file
-			     (dev, &dev_attr_delay_reverb_lo_cut));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_volume_pedal_minimum));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_eq_pre_post));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_volume_pre_post));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_di_model));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_di_delay));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_mod_enable));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_1_note_value));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_2));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_3));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_4));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_5));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_mod_volume_mix));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_mod_pre_post));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_modulation_model));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_band_3_frequency));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_band_4_frequency__bass));
-	CHECK_RETURN(device_create_file
-		     (dev, &dev_attr_mod_param_1_double_precision));
-	CHECK_RETURN(device_create_file
-		     (dev, &dev_attr_delay_param_1_double_precision));
-	if (firmware >= 200)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_eq_enable));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tap));
-	CHECK_RETURN(device_create_file
-		     (dev, &dev_attr_volume_tweak_pedal_assign));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_band_5_frequency));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tuner));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_mic_selection));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_cabinet_model));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_model));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_roomlevel));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_band_4_frequency));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_band_6_frequency));
-	CHECK_RETURN(device_create_file
-		     (dev, &dev_attr_stomp_param_1_note_value));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_2));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_3));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_4));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_5));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_6));
-	if ((type & (LINE6_BITS_LIVE)) != 0)
-		CHECK_RETURN(device_create_file
-			     (dev, &dev_attr_amp_switch_select));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_4));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_5));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_delay_pre_post));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_delay_model));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		CHECK_RETURN(device_create_file
-			     (dev, &dev_attr_delay_verb_model));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tempo_msb));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tempo_lsb));
-	if (firmware >= 300)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_wah_model));
-	if (firmware >= 214)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_bypass_volume));
-	if ((type & (LINE6_BITS_PRO)) != 0)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_fx_loop_on_off));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tweak_param_select));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_amp1_engage));
-	if (firmware >= 200)
-		CHECK_RETURN(device_create_file(dev, &dev_attr_band_1_gain));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_band_2_gain__bass));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_band_2_gain));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_band_3_gain__bass));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_band_3_gain));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_band_4_gain__bass));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_band_5_gain__bass));
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_band_4_gain));
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			CHECK_RETURN(device_create_file
-				     (dev, &dev_attr_band_6_gain__bass));
-	return 0;
-}
-
-void line6_pod_remove_files(int firmware, int type, struct device *dev)
-{
-	device_remove_file(dev, &dev_attr_tweak);
-	device_remove_file(dev, &dev_attr_wah_position);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_compression_gain);
-	device_remove_file(dev, &dev_attr_vol_pedal_position);
-	device_remove_file(dev, &dev_attr_compression_threshold);
-	device_remove_file(dev, &dev_attr_pan);
-	device_remove_file(dev, &dev_attr_amp_model_setup);
-	if (firmware >= 200)
-		device_remove_file(dev, &dev_attr_amp_model);
-	device_remove_file(dev, &dev_attr_drive);
-	device_remove_file(dev, &dev_attr_bass);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_mid);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_lowmid);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_treble);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_highmid);
-	device_remove_file(dev, &dev_attr_chan_vol);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_reverb_mix);
-	device_remove_file(dev, &dev_attr_effect_setup);
-	if (firmware >= 200)
-		device_remove_file(dev, &dev_attr_band_1_frequency);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_presence);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_treble__bass);
-	device_remove_file(dev, &dev_attr_noise_gate_enable);
-	device_remove_file(dev, &dev_attr_gate_threshold);
-	device_remove_file(dev, &dev_attr_gate_decay_time);
-	device_remove_file(dev, &dev_attr_stomp_enable);
-	device_remove_file(dev, &dev_attr_comp_enable);
-	device_remove_file(dev, &dev_attr_stomp_time);
-	device_remove_file(dev, &dev_attr_delay_enable);
-	device_remove_file(dev, &dev_attr_mod_param_1);
-	device_remove_file(dev, &dev_attr_delay_param_1);
-	device_remove_file(dev, &dev_attr_delay_param_1_note_value);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev,
-					   &dev_attr_band_2_frequency__bass);
-	device_remove_file(dev, &dev_attr_delay_param_2);
-	device_remove_file(dev, &dev_attr_delay_volume_mix);
-	device_remove_file(dev, &dev_attr_delay_param_3);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_reverb_enable);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_reverb_type);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_reverb_decay);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_reverb_tone);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_reverb_pre_delay);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_reverb_pre_post);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev, &dev_attr_band_2_frequency);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev,
-					   &dev_attr_band_3_frequency__bass);
-	device_remove_file(dev, &dev_attr_wah_enable);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_modulation_lo_cut);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_delay_reverb_lo_cut);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev, &dev_attr_volume_pedal_minimum);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev, &dev_attr_eq_pre_post);
-	device_remove_file(dev, &dev_attr_volume_pre_post);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_di_model);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_di_delay);
-	device_remove_file(dev, &dev_attr_mod_enable);
-	device_remove_file(dev, &dev_attr_mod_param_1_note_value);
-	device_remove_file(dev, &dev_attr_mod_param_2);
-	device_remove_file(dev, &dev_attr_mod_param_3);
-	device_remove_file(dev, &dev_attr_mod_param_4);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_mod_param_5);
-	device_remove_file(dev, &dev_attr_mod_volume_mix);
-	device_remove_file(dev, &dev_attr_mod_pre_post);
-	device_remove_file(dev, &dev_attr_modulation_model);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev, &dev_attr_band_3_frequency);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev,
-					   &dev_attr_band_4_frequency__bass);
-	device_remove_file(dev, &dev_attr_mod_param_1_double_precision);
-	device_remove_file(dev, &dev_attr_delay_param_1_double_precision);
-	if (firmware >= 200)
-		device_remove_file(dev, &dev_attr_eq_enable);
-	device_remove_file(dev, &dev_attr_tap);
-	device_remove_file(dev, &dev_attr_volume_tweak_pedal_assign);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev, &dev_attr_band_5_frequency);
-	device_remove_file(dev, &dev_attr_tuner);
-	device_remove_file(dev, &dev_attr_mic_selection);
-	device_remove_file(dev, &dev_attr_cabinet_model);
-	device_remove_file(dev, &dev_attr_stomp_model);
-	device_remove_file(dev, &dev_attr_roomlevel);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev, &dev_attr_band_4_frequency);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev, &dev_attr_band_6_frequency);
-	device_remove_file(dev, &dev_attr_stomp_param_1_note_value);
-	device_remove_file(dev, &dev_attr_stomp_param_2);
-	device_remove_file(dev, &dev_attr_stomp_param_3);
-	device_remove_file(dev, &dev_attr_stomp_param_4);
-	device_remove_file(dev, &dev_attr_stomp_param_5);
-	device_remove_file(dev, &dev_attr_stomp_param_6);
-	if ((type & (LINE6_BITS_LIVE)) != 0)
-		device_remove_file(dev, &dev_attr_amp_switch_select);
-	device_remove_file(dev, &dev_attr_delay_param_4);
-	device_remove_file(dev, &dev_attr_delay_param_5);
-	device_remove_file(dev, &dev_attr_delay_pre_post);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_delay_model);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		device_remove_file(dev, &dev_attr_delay_verb_model);
-	device_remove_file(dev, &dev_attr_tempo_msb);
-	device_remove_file(dev, &dev_attr_tempo_lsb);
-	if (firmware >= 300)
-		device_remove_file(dev, &dev_attr_wah_model);
-	if (firmware >= 214)
-		device_remove_file(dev, &dev_attr_bypass_volume);
-	if ((type & (LINE6_BITS_PRO)) != 0)
-		device_remove_file(dev, &dev_attr_fx_loop_on_off);
-	device_remove_file(dev, &dev_attr_tweak_param_select);
-	device_remove_file(dev, &dev_attr_amp1_engage);
-	if (firmware >= 200)
-		device_remove_file(dev, &dev_attr_band_1_gain);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev, &dev_attr_band_2_gain__bass);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev, &dev_attr_band_2_gain);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev, &dev_attr_band_3_gain__bass);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev, &dev_attr_band_3_gain);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev, &dev_attr_band_4_gain__bass);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev, &dev_attr_band_5_gain__bass);
-	if ((type & (LINE6_BITS_PODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev, &dev_attr_band_4_gain);
-	if ((type & (LINE6_BITS_BASSPODXTALL)) != 0)
-		if (firmware >= 200)
-			device_remove_file(dev, &dev_attr_band_6_gain__bass);
-}
-
-int line6_variax_create_files(int firmware, int type, struct device *dev)
-{
-	int err;
-	CHECK_RETURN(device_create_file(dev, &dev_attr_body));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_pickup1_enable));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_pickup1_type));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_pickup1_position));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_pickup1_angle));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_pickup1_level));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_pickup2_enable));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_pickup2_type));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_pickup2_position));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_pickup2_angle));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_pickup2_level));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_pickup_phase));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_capacitance));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tone_resistance));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_volume_resistance));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_taper));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tone_dump));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_save_tone));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_volume_dump));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tuning_enable));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tuning6));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tuning5));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tuning4));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tuning3));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tuning2));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tuning1));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_detune6));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_detune5));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_detune4));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_detune3));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_detune2));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_detune1));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_mix6));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_mix5));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_mix4));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_mix3));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_mix2));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_mix1));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_pickup_wiring));
-	return 0;
-}
-
-void line6_variax_remove_files(int firmware, int type, struct device *dev)
-{
-	device_remove_file(dev, &dev_attr_body);
-	device_remove_file(dev, &dev_attr_pickup1_enable);
-	device_remove_file(dev, &dev_attr_pickup1_type);
-	device_remove_file(dev, &dev_attr_pickup1_position);
-	device_remove_file(dev, &dev_attr_pickup1_angle);
-	device_remove_file(dev, &dev_attr_pickup1_level);
-	device_remove_file(dev, &dev_attr_pickup2_enable);
-	device_remove_file(dev, &dev_attr_pickup2_type);
-	device_remove_file(dev, &dev_attr_pickup2_position);
-	device_remove_file(dev, &dev_attr_pickup2_angle);
-	device_remove_file(dev, &dev_attr_pickup2_level);
-	device_remove_file(dev, &dev_attr_pickup_phase);
-	device_remove_file(dev, &dev_attr_capacitance);
-	device_remove_file(dev, &dev_attr_tone_resistance);
-	device_remove_file(dev, &dev_attr_volume_resistance);
-	device_remove_file(dev, &dev_attr_taper);
-	device_remove_file(dev, &dev_attr_tone_dump);
-	device_remove_file(dev, &dev_attr_save_tone);
-	device_remove_file(dev, &dev_attr_volume_dump);
-	device_remove_file(dev, &dev_attr_tuning_enable);
-	device_remove_file(dev, &dev_attr_tuning6);
-	device_remove_file(dev, &dev_attr_tuning5);
-	device_remove_file(dev, &dev_attr_tuning4);
-	device_remove_file(dev, &dev_attr_tuning3);
-	device_remove_file(dev, &dev_attr_tuning2);
-	device_remove_file(dev, &dev_attr_tuning1);
-	device_remove_file(dev, &dev_attr_detune6);
-	device_remove_file(dev, &dev_attr_detune5);
-	device_remove_file(dev, &dev_attr_detune4);
-	device_remove_file(dev, &dev_attr_detune3);
-	device_remove_file(dev, &dev_attr_detune2);
-	device_remove_file(dev, &dev_attr_detune1);
-	device_remove_file(dev, &dev_attr_mix6);
-	device_remove_file(dev, &dev_attr_mix5);
-	device_remove_file(dev, &dev_attr_mix4);
-	device_remove_file(dev, &dev_attr_mix3);
-	device_remove_file(dev, &dev_attr_mix2);
-	device_remove_file(dev, &dev_attr_mix1);
-	device_remove_file(dev, &dev_attr_pickup_wiring);
-}
diff --git a/drivers/staging/line6/control.h b/drivers/staging/line6/control.h
deleted file mode 100644
index e4c5d2c..0000000
--- a/drivers/staging/line6/control.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	This program is free software; 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.
- *
- */
-
-#ifndef LINE6_CONTROL_H
-#define LINE6_CONTROL_H
-
-/**
-   List of PODxt Pro controls.
-   See Appendix C of the "PODxt (Pro) Pilot's Handbook" by Line6.
-   Comments after the number refer to the PODxt Pro firmware version required
-   for this feature.
-
-   Please *don't* reformat this file since "control.c" is created automatically
-   from "control.h", and this process depends on the exact formatting of the
-   code and the comments below!
-*/
-
-/* *INDENT-OFF* */
-
-enum {
-	POD_tweak                          =   1,
-	POD_wah_position                   =   4,
-	POD_compression_gain               =   5,  /* device: LINE6_BITS_PODXTALL */
-	POD_vol_pedal_position             =   7,
-	POD_compression_threshold          =   9,
-	POD_pan                            =  10,
-	POD_amp_model_setup                =  11,
-	POD_amp_model                      =  12,  /* firmware: 2.0 */
-	POD_drive                          =  13,
-	POD_bass                           =  14,
-	POD_mid                            =  15,  /* device: LINE6_BITS_PODXTALL */
-	POD_lowmid                         =  15,  /* device: LINE6_BITS_BASSPODXTALL */
-	POD_treble                         =  16,  /* device: LINE6_BITS_PODXTALL */
-	POD_highmid                        =  16,  /* device: LINE6_BITS_BASSPODXTALL */
-	POD_chan_vol                       =  17,
-	POD_reverb_mix                     =  18,  /* device: LINE6_BITS_PODXTALL */
-	POD_effect_setup                   =  19,
-	POD_band_1_frequency               =  20,  /* firmware: 2.0 */
-	POD_presence                       =  21,  /* device: LINE6_BITS_PODXTALL */
-	POD_treble__bass                   =  21,  /* device: LINE6_BITS_BASSPODXTALL */
-	POD_noise_gate_enable              =  22,
-	POD_gate_threshold                 =  23,
-	POD_gate_decay_time                =  24,
-	POD_stomp_enable                   =  25,
-	POD_comp_enable                    =  26,
-	POD_stomp_time                     =  27,
-	POD_delay_enable                   =  28,
-	POD_mod_param_1                    =  29,
-	POD_delay_param_1                  =  30,
-	POD_delay_param_1_note_value       =  31,
-	POD_band_2_frequency__bass         =  32,  /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */
-	POD_delay_param_2                  =  33,
-	POD_delay_volume_mix               =  34,
-	POD_delay_param_3                  =  35,
-	POD_reverb_enable                  =  36,  /* device: LINE6_BITS_PODXTALL */
-	POD_reverb_type                    =  37,  /* device: LINE6_BITS_PODXTALL */
-	POD_reverb_decay                   =  38,  /* device: LINE6_BITS_PODXTALL */
-	POD_reverb_tone                    =  39,  /* device: LINE6_BITS_PODXTALL */
-	POD_reverb_pre_delay               =  40,  /* device: LINE6_BITS_PODXTALL */
-	POD_reverb_pre_post                =  41,  /* device: LINE6_BITS_PODXTALL */
-	POD_band_2_frequency               =  42,  /* device: LINE6_BITS_PODXTALL */     /* firmware: 2.0 */
-	POD_band_3_frequency__bass         =  42,  /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */
-	POD_wah_enable                     =  43,
-	POD_modulation_lo_cut              =  44,  /* device: LINE6_BITS_BASSPODXTALL */
-	POD_delay_reverb_lo_cut            =  45,  /* device: LINE6_BITS_BASSPODXTALL */
-	POD_volume_pedal_minimum           =  46,  /* device: LINE6_BITS_PODXTALL */     /* firmware: 2.0 */
-	POD_eq_pre_post                    =  46,  /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */
-	POD_volume_pre_post                =  47,
-	POD_di_model                       =  48,  /* device: LINE6_BITS_BASSPODXTALL */
-	POD_di_delay                       =  49,  /* device: LINE6_BITS_BASSPODXTALL */
-	POD_mod_enable                     =  50,
-	POD_mod_param_1_note_value         =  51,
-	POD_mod_param_2                    =  52,
-	POD_mod_param_3                    =  53,
-	POD_mod_param_4                    =  54,
-	POD_mod_param_5                    =  55,  /* device: LINE6_BITS_BASSPODXTALL */
-	POD_mod_volume_mix                 =  56,
-	POD_mod_pre_post                   =  57,
-	POD_modulation_model               =  58,
-	POD_band_3_frequency               =  60,  /* device: LINE6_BITS_PODXTALL */     /* firmware: 2.0 */
-	POD_band_4_frequency__bass         =  60,  /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */
-	POD_mod_param_1_double_precision   =  61,
-	POD_delay_param_1_double_precision =  62,
-	POD_eq_enable                      =  63,  /* firmware: 2.0 */
-	POD_tap                            =  64,
-	POD_volume_tweak_pedal_assign      =  65,
-	POD_band_5_frequency               =  68,  /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */
-	POD_tuner                          =  69,
-	POD_mic_selection                  =  70,
-	POD_cabinet_model                  =  71,
-	POD_stomp_model                    =  75,
-	POD_roomlevel                      =  76,
-	POD_band_4_frequency               =  77,  /* device: LINE6_BITS_PODXTALL */     /* firmware: 2.0 */
-	POD_band_6_frequency               =  77,  /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */
-	POD_stomp_param_1_note_value       =  78,
-	POD_stomp_param_2                  =  79,
-	POD_stomp_param_3                  =  80,
-	POD_stomp_param_4                  =  81,
-	POD_stomp_param_5                  =  82,
-	POD_stomp_param_6                  =  83,
-	POD_amp_switch_select              =  84,  /* device: LINE6_BITS_LIVE */
-	POD_delay_param_4                  =  85,
-	POD_delay_param_5                  =  86,
-	POD_delay_pre_post                 =  87,
-	POD_delay_model                    =  88,  /* device: LINE6_BITS_PODXTALL */
-	POD_delay_verb_model               =  88,  /* device: LINE6_BITS_BASSPODXTALL */
-	POD_tempo_msb                      =  89,
-	POD_tempo_lsb                      =  90,
-	POD_wah_model                      =  91,  /* firmware: 3.0 */
-	POD_bypass_volume                  = 105,  /* firmware: 2.14 */
-	POD_fx_loop_on_off                 = 107,  /* device: LINE6_BITS_PRO */
-	POD_tweak_param_select             = 108,
-	POD_amp1_engage                    = 111,
-	POD_band_1_gain                    = 114,  /* firmware: 2.0 */
-	POD_band_2_gain__bass              = 115,  /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */
-	POD_band_2_gain                    = 116,  /* device: LINE6_BITS_PODXTALL */     /* firmware: 2.0 */
-	POD_band_3_gain__bass              = 116,  /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */
-	POD_band_3_gain                    = 117,  /* device: LINE6_BITS_PODXTALL */     /* firmware: 2.0 */
-	POD_band_4_gain__bass              = 117,  /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */
-	POD_band_5_gain__bass              = 118,  /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */
-	POD_band_4_gain                    = 119,  /* device: LINE6_BITS_PODXTALL */     /* firmware: 2.0 */
-	POD_band_6_gain__bass              = 119   /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */
-};
-
-/**
-   List of Variax workbench controls (dump).
-*/
-enum {
-	VARIAX_body                        =   3,
-	VARIAX_pickup1_enable              =   4,  /* 0: enabled, 1: disabled */
-	VARIAX_pickup1_type                =   8,
-	VARIAX_pickup1_position            =   9,  /* type: 24 bit float */
-	VARIAX_pickup1_angle               =  12,  /* type: 24 bit float */
-	VARIAX_pickup1_level               =  15,  /* type: 24 bit float */
-	VARIAX_pickup2_enable              =  18,  /* 0: enabled, 1: disabled */
-	VARIAX_pickup2_type                =  22,
-	VARIAX_pickup2_position            =  23,  /* type: 24 bit float */
-	VARIAX_pickup2_angle               =  26,  /* type: 24 bit float */
-	VARIAX_pickup2_level               =  29,  /* type: 24 bit float */
-	VARIAX_pickup_phase                =  32,  /* 0: in phase, 1: out of phase */
-	VARIAX_capacitance                 =  33,  /* type: 24 bit float */
-	VARIAX_tone_resistance             =  36,  /* type: 24 bit float */
-	VARIAX_volume_resistance           =  39,  /* type: 24 bit float */
-	VARIAX_taper                       =  42,  /* 0: Linear, 1: Audio */
-	VARIAX_tone_dump                   =  43,  /* type: 24 bit float */
-	VARIAX_save_tone                   =  46,
-	VARIAX_volume_dump                 =  47,  /* type: 24 bit float */
-	VARIAX_tuning_enable               =  50,
-	VARIAX_tuning6                     =  51,
-	VARIAX_tuning5                     =  52,
-	VARIAX_tuning4                     =  53,
-	VARIAX_tuning3                     =  54,
-	VARIAX_tuning2                     =  55,
-	VARIAX_tuning1                     =  56,
-	VARIAX_detune6                     =  57,  /* type: 24 bit float */
-	VARIAX_detune5                     =  60,  /* type: 24 bit float */
-	VARIAX_detune4                     =  63,  /* type: 24 bit float */
-	VARIAX_detune3                     =  66,  /* type: 24 bit float */
-	VARIAX_detune2                     =  69,  /* type: 24 bit float */
-	VARIAX_detune1                     =  72,  /* type: 24 bit float */
-	VARIAX_mix6                        =  75,  /* type: 24 bit float */
-	VARIAX_mix5                        =  78,  /* type: 24 bit float */
-	VARIAX_mix4                        =  81,  /* type: 24 bit float */
-	VARIAX_mix3                        =  84,  /* type: 24 bit float */
-	VARIAX_mix2                        =  87,  /* type: 24 bit float */
-	VARIAX_mix1                        =  90,  /* type: 24 bit float */
-	VARIAX_pickup_wiring               =  96   /* 0: parallel, 1: series */
-};
-
-/**
-   List of Variax workbench controls (MIDI).
-*/
-enum {
-	VARIAXMIDI_volume                  =   7,
-	VARIAXMIDI_tone                    =  79,
-};
-
-/* *INDENT-ON* */
-
-extern int line6_pod_create_files(int firmware, int type, struct device *dev);
-extern void line6_pod_remove_files(int firmware, int type, struct device *dev);
-extern int line6_variax_create_files(int firmware, int type,
-				     struct device *dev);
-extern void line6_variax_remove_files(int firmware, int type,
-				      struct device *dev);
-
-#endif
diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c
index b8358ca..1e4ce500 100644
--- a/drivers/staging/line6/driver.c
+++ b/drivers/staging/line6/driver.c
@@ -16,7 +16,6 @@
 
 #include "audio.h"
 #include "capture.h"
-#include "control.h"
 #include "driver.h"
 #include "midi.h"
 #include "playback.h"
@@ -96,8 +95,6 @@ static const char line6_request_version[] = {
 	0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7
 };
 
-struct usb_line6 *line6_devices[LINE6_MAX_DEVICES];
-
 /**
 	 Class for asynchronous messages.
 */
@@ -179,22 +176,6 @@ void line6_write_hexdump(struct usb_line6 *line6, char dir,
 }
 #endif
 
-#ifdef CONFIG_LINE6_USB_DUMP_CTRL
-/*
-	Dump URB data to syslog.
-*/
-static void line6_dump_urb(struct urb *urb)
-{
-	struct usb_line6 *line6 = (struct usb_line6 *)urb->context;
-
-	if (urb->status < 0)
-		return;
-
-	line6_write_hexdump(line6, 'R', (unsigned char *)urb->transfer_buffer,
-			    urb->actual_length);
-}
-#endif
-
 /*
 	Send raw message in pieces of wMaxPacketSize bytes.
 */
@@ -203,10 +184,6 @@ int line6_send_raw_message(struct usb_line6 *line6, const char *buffer,
 {
 	int i, done = 0;
 
-#ifdef CONFIG_LINE6_USB_DUMP_CTRL
-	line6_write_hexdump(line6, 'S', buffer, size);
-#endif
-
 	for (i = 0; i < size; i += line6->max_packet_size) {
 		int partial;
 		const char *frag_buf = buffer + i;
@@ -261,10 +238,6 @@ static int line6_send_raw_message_async_part(struct message *msg,
 			 (char *)msg->buffer + done, bytes,
 			 line6_async_request_sent, msg, line6->interval);
 
-#ifdef CONFIG_LINE6_USB_DUMP_CTRL
-	line6_write_hexdump(line6, 'S', (char *)msg->buffer + done, bytes);
-#endif
-
 	msg->done += bytes;
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
 
@@ -405,19 +378,13 @@ static void line6_data_received(struct urb *urb)
 	if (urb->status == -ESHUTDOWN)
 		return;
 
-#ifdef CONFIG_LINE6_USB_DUMP_CTRL
-	line6_dump_urb(urb);
-#endif
-
 	done =
 	    line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length);
 
 	if (done < urb->actual_length) {
 		line6_midibuf_ignore(mb, done);
-		DEBUG_MESSAGES(dev_err
-			       (line6->ifcdev,
-				"%d %d buffer overflow - message skipped\n",
-				done, urb->actual_length));
+		dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n",
+			done, urb->actual_length);
 	}
 
 	for (;;) {
@@ -428,15 +395,7 @@ static void line6_data_received(struct urb *urb)
 		if (done == 0)
 			break;
 
-		/* MIDI input filter */
-		if (line6_midibuf_skip_message
-		    (mb, line6->line6midi->midi_mask_receive))
-			continue;
-
 		line6->message_length = done;
-#ifdef CONFIG_LINE6_USB_DUMP_MIDI
-		line6_write_hexdump(line6, 'r', line6->buffer_message, done);
-#endif
 		line6_midi_receive(line6, line6->buffer_message, done);
 
 		switch (line6->usbdev->descriptor.idProduct) {
@@ -506,10 +465,6 @@ int line6_send_program(struct usb_line6 *line6, u8 value)
 	buffer[0] = LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST;
 	buffer[1] = value;
 
-#ifdef CONFIG_LINE6_USB_DUMP_CTRL
-	line6_write_hexdump(line6, 'S', buffer, 2);
-#endif
-
 	retval = usb_interrupt_msg(line6->usbdev,
 				   usb_sndintpipe(line6->usbdev,
 						  line6->ep_control_write),
@@ -543,10 +498,6 @@ int line6_transmit_parameter(struct usb_line6 *line6, int param, u8 value)
 	buffer[1] = param;
 	buffer[2] = value;
 
-#ifdef CONFIG_LINE6_USB_DUMP_CTRL
-	line6_write_hexdump(line6, 'S', buffer, 3);
-#endif
-
 	retval = usb_interrupt_msg(line6->usbdev,
 				   usb_sndintpipe(line6->usbdev,
 						  line6->ep_control_write),
@@ -690,20 +641,6 @@ ssize_t line6_nop_write(struct device *dev, struct device_attribute *attr,
 }
 
 /*
-	"write" request on "raw" special file.
-*/
-#ifdef CONFIG_LINE6_USB_RAW
-ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,
-		      const char *buf, size_t count)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6 *line6 = usb_get_intfdata(interface);
-	line6_send_raw_message(line6, buf, count);
-	return count;
-}
-#endif
-
-/*
 	Generic destructor.
 */
 static void line6_destruct(struct usb_interface *interface)
@@ -740,7 +677,6 @@ static int line6_probe(struct usb_interface *interface,
 	struct usb_device *usbdev;
 	struct usb_line6 *line6;
 	const struct line6_properties *properties;
-	int devnum;
 	int interface_number, alternate = 0;
 	int product;
 	int size = 0;
@@ -774,16 +710,6 @@ static int line6_probe(struct usb_interface *interface,
 		goto err_put;
 	}
 
-	/* find free slot in device table: */
-	for (devnum = 0; devnum < LINE6_MAX_DEVICES; ++devnum)
-		if (line6_devices[devnum] == NULL)
-			break;
-
-	if (devnum == LINE6_MAX_DEVICES) {
-		ret = -ENODEV;
-		goto err_put;
-	}
-
 	/* initialize device info: */
 	properties = &line6_properties_table[devtype];
 	dev_info(&interface->dev, "Line6 %s found\n", properties->name);
@@ -1112,7 +1038,6 @@ static int line6_probe(struct usb_interface *interface,
 
 	dev_info(&interface->dev, "Line6 %s now attached\n",
 		 line6->properties->name);
-	line6_devices[devnum] = line6;
 
 	switch (product) {
 	case LINE6_DEVID_PODX3:
@@ -1141,7 +1066,7 @@ static void line6_disconnect(struct usb_interface *interface)
 {
 	struct usb_line6 *line6;
 	struct usb_device *usbdev;
-	int interface_number, i;
+	int interface_number;
 
 	if (interface == NULL)
 		return;
@@ -1214,10 +1139,6 @@ static void line6_disconnect(struct usb_interface *interface)
 
 		dev_info(&interface->dev, "Line6 %s now disconnected\n",
 			 line6->properties->name);
-
-		for (i = LINE6_MAX_DEVICES; i--;)
-			if (line6_devices[i] == line6)
-				line6_devices[i] = NULL;
 	}
 
 	line6_destruct(interface);
diff --git a/drivers/staging/line6/driver.h b/drivers/staging/line6/driver.h
index a3029eb..f0be5a2 100644
--- a/drivers/staging/line6/driver.h
+++ b/drivers/staging/line6/driver.h
@@ -20,12 +20,11 @@
 
 #define DRIVER_NAME "line6usb"
 
-#if defined(CONFIG_LINE6_USB_DUMP_CTRL) || defined(CONFIG_LINE6_USB_DUMP_MIDI) || defined(CONFIG_LINE6_USB_DUMP_PCM)
+#if defined(CONFIG_LINE6_USB_DUMP_PCM)
 #define CONFIG_LINE6_USB_DUMP_ANY
 #endif
 
 #define LINE6_TIMEOUT 1
-#define LINE6_MAX_DEVICES 8
 #define LINE6_BUFSIZE_LISTEN 32
 #define LINE6_MESSAGE_MAXLEN 256
 
@@ -53,12 +52,6 @@
 
 #define LINE6_CHANNEL_MASK 0x0f
 
-#ifdef CONFIG_LINE6_USB_DEBUG
-#define DEBUG_MESSAGES(x) (x)
-#else
-#define DEBUG_MESSAGES(x)
-#endif
-
 #define MISSING_CASE	\
 	printk(KERN_ERR "line6usb driver bug: missing case in %s:%d\n", \
 		__FILE__, __LINE__)
@@ -78,7 +71,6 @@ do {					\
 } while (0)
 
 extern const unsigned char line6_midi_id[3];
-extern struct usb_line6 *line6_devices[LINE6_MAX_DEVICES];
 
 static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3;
 static const int SYSEX_EXTRA_SIZE = sizeof(line6_midi_id) + 4;
diff --git a/drivers/staging/line6/dumprequest.c b/drivers/staging/line6/dumprequest.c
deleted file mode 100644
index 60c7bae..0000000
--- a/drivers/staging/line6/dumprequest.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	This program is free software; 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.
- *
- */
-
-#include <linux/slab.h>
-
-#include "driver.h"
-#include "dumprequest.h"
-
-/*
-	Set "dump in progress" flag.
-*/
-void line6_dump_started(struct line6_dump_request *l6dr, int dest)
-{
-	l6dr->in_progress = dest;
-}
-
-/*
-	Invalidate current channel, i.e., set "dump in progress" flag.
-	Reading from the "dump" special file blocks until dump is completed.
-*/
-void line6_invalidate_current(struct line6_dump_request *l6dr)
-{
-	line6_dump_started(l6dr, LINE6_DUMP_CURRENT);
-}
-
-/*
-	Clear "dump in progress" flag and notify waiting processes.
-*/
-void line6_dump_finished(struct line6_dump_request *l6dr)
-{
-	l6dr->in_progress = LINE6_DUMP_NONE;
-	wake_up(&l6dr->wait);
-}
-
-/*
-	Send an asynchronous channel dump request.
-*/
-int line6_dump_request_async(struct line6_dump_request *l6dr,
-			     struct usb_line6 *line6, int num, int dest)
-{
-	int ret;
-	line6_dump_started(l6dr, dest);
-	ret = line6_send_raw_message_async(line6, l6dr->reqbufs[num].buffer,
-					   l6dr->reqbufs[num].length);
-
-	if (ret < 0)
-		line6_dump_finished(l6dr);
-
-	return ret;
-}
-
-/*
-	Wait for completion (interruptible).
-*/
-int line6_dump_wait_interruptible(struct line6_dump_request *l6dr)
-{
-	return wait_event_interruptible(l6dr->wait,
-					l6dr->in_progress == LINE6_DUMP_NONE);
-}
-
-/*
-	Wait for completion.
-*/
-void line6_dump_wait(struct line6_dump_request *l6dr)
-{
-	wait_event(l6dr->wait, l6dr->in_progress == LINE6_DUMP_NONE);
-}
-
-/*
-	Wait for completion (with timeout).
-*/
-int line6_dump_wait_timeout(struct line6_dump_request *l6dr, long timeout)
-{
-	return wait_event_timeout(l6dr->wait,
-				  l6dr->in_progress == LINE6_DUMP_NONE,
-				  timeout);
-}
-
-/*
-	Initialize dump request buffer.
-*/
-int line6_dumpreq_initbuf(struct line6_dump_request *l6dr, const void *buf,
-			  size_t len, int num)
-{
-	l6dr->reqbufs[num].buffer = kmemdup(buf, len, GFP_KERNEL);
-	if (l6dr->reqbufs[num].buffer == NULL)
-		return -ENOMEM;
-	l6dr->reqbufs[num].length = len;
-	return 0;
-}
-
-/*
-	Initialize dump request data structure (including one buffer).
-*/
-int line6_dumpreq_init(struct line6_dump_request *l6dr, const void *buf,
-		       size_t len)
-{
-	int ret;
-	ret = line6_dumpreq_initbuf(l6dr, buf, len, 0);
-	if (ret < 0)
-		return ret;
-	init_waitqueue_head(&l6dr->wait);
-	return 0;
-}
-
-/*
-	Destruct dump request data structure.
-*/
-void line6_dumpreq_destructbuf(struct line6_dump_request *l6dr, int num)
-{
-	if (l6dr == NULL)
-		return;
-	if (l6dr->reqbufs[num].buffer == NULL)
-		return;
-	kfree(l6dr->reqbufs[num].buffer);
-	l6dr->reqbufs[num].buffer = NULL;
-}
-
-/*
-	Destruct dump request data structure.
-*/
-void line6_dumpreq_destruct(struct line6_dump_request *l6dr)
-{
-	if (l6dr->reqbufs[0].buffer == NULL)
-		return;
-	line6_dumpreq_destructbuf(l6dr, 0);
-}
diff --git a/drivers/staging/line6/dumprequest.h b/drivers/staging/line6/dumprequest.h
deleted file mode 100644
index c17a262..0000000
--- a/drivers/staging/line6/dumprequest.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	This program is free software; 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.
- *
- */
-
-#ifndef DUMPREQUEST_H
-#define DUMPREQUEST_H
-
-#include <linux/usb.h>
-#include <linux/wait.h>
-#include <sound/core.h>
-
-enum {
-	LINE6_DUMP_NONE,
-	LINE6_DUMP_CURRENT
-};
-
-struct line6_dump_reqbuf {
-	/**
-		 Buffer for dump requests.
-	*/
-	unsigned char *buffer;
-
-	/**
-		 Size of dump request.
-	*/
-	size_t length;
-};
-
-/**
-	 Provides the functionality to request channel/model/... dump data from a
-	 Line6 device.
-*/
-struct line6_dump_request {
-	/**
-		 Wait queue for access to program dump data.
-	*/
-	wait_queue_head_t wait;
-
-	/**
-		 Indicates an unfinished program dump request.
-		 0: no dump
-		 1: dump current settings
-		 Other device-specific values are also allowed.
-	*/
-	int in_progress;
-
-	/**
-		 Dump request buffers
-	*/
-	struct line6_dump_reqbuf reqbufs[1];
-};
-
-extern void line6_dump_finished(struct line6_dump_request *l6dr);
-extern int line6_dump_request_async(struct line6_dump_request *l6dr,
-				    struct usb_line6 *line6, int num, int dest);
-extern void line6_dump_started(struct line6_dump_request *l6dr, int dest);
-extern void line6_dumpreq_destruct(struct line6_dump_request *l6dr);
-extern void line6_dumpreq_destructbuf(struct line6_dump_request *l6dr, int num);
-extern int line6_dumpreq_init(struct line6_dump_request *l6dr, const void *buf,
-			      size_t len);
-extern int line6_dumpreq_initbuf(struct line6_dump_request *l6dr,
-				 const void *buf, size_t len, int num);
-extern void line6_invalidate_current(struct line6_dump_request *l6dr);
-extern void line6_dump_wait(struct line6_dump_request *l6dr);
-extern int line6_dump_wait_interruptible(struct line6_dump_request *l6dr);
-extern int line6_dump_wait_timeout(struct line6_dump_request *l6dr,
-				   long timeout);
-
-#endif
diff --git a/drivers/staging/line6/midi.c b/drivers/staging/line6/midi.c
index 5040729..6982eca 100644
--- a/drivers/staging/line6/midi.c
+++ b/drivers/staging/line6/midi.c
@@ -59,9 +59,6 @@ static void line6_midi_transmit(struct snd_rawmidi_substream *substream)
 		if (done == 0)
 			break;
 
-#ifdef CONFIG_LINE6_USB_DUMP_MIDI
-		line6_write_hexdump(line6, 's', chunk, done);
-#endif
 		line6_midibuf_write(mb, chunk, done);
 		snd_rawmidi_transmit_ack(substream, done);
 	}
@@ -72,10 +69,6 @@ static void line6_midi_transmit(struct snd_rawmidi_substream *substream)
 		if (done == 0)
 			break;
 
-		if (line6_midibuf_skip_message
-		    (mb, line6midi->midi_mask_transmit))
-			continue;
-
 		send_midi_async(line6, chunk, done);
 	}
 
@@ -131,9 +124,6 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
 		dev_err(line6->ifcdev, "Out of memory\n");
 		return -ENOMEM;
 	}
-#ifdef CONFIG_LINE6_USB_DUMP_CTRL
-	line6_write_hexdump(line6, 'S', data, length);
-#endif
 
 	transfer_buffer = kmemdup(data, length, GFP_ATOMIC);
 
@@ -158,28 +148,6 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
 	}
 
 	++line6->line6midi->num_active_send_urbs;
-
-	switch (line6->usbdev->descriptor.idProduct) {
-	case LINE6_DEVID_BASSPODXT:
-	case LINE6_DEVID_BASSPODXTLIVE:
-	case LINE6_DEVID_BASSPODXTPRO:
-	case LINE6_DEVID_PODXT:
-	case LINE6_DEVID_PODXTLIVE:
-	case LINE6_DEVID_PODXTPRO:
-	case LINE6_DEVID_POCKETPOD:
-		line6_pod_midi_postprocess((struct usb_line6_pod *)line6, data,
-					   length);
-		break;
-
-	case LINE6_DEVID_VARIAX:
-	case LINE6_DEVID_PODHD300:
-	case LINE6_DEVID_PODHD500:
-		break;
-
-	default:
-		MISSING_CASE;
-	}
-
 	return 0;
 }
 
@@ -287,83 +255,10 @@ static int snd_line6_new_midi(struct snd_line6_midi *line6midi)
 	return 0;
 }
 
-/*
-	"read" request on "midi_mask_transmit" special file.
-*/
-static ssize_t midi_get_midi_mask_transmit(struct device *dev,
-					   struct device_attribute *attr,
-					   char *buf)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6 *line6 = usb_get_intfdata(interface);
-	return sprintf(buf, "%d\n", line6->line6midi->midi_mask_transmit);
-}
-
-/*
-	"write" request on "midi_mask" special file.
-*/
-static ssize_t midi_set_midi_mask_transmit(struct device *dev,
-					   struct device_attribute *attr,
-					   const char *buf, size_t count)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6 *line6 = usb_get_intfdata(interface);
-	unsigned short value;
-	int ret;
-
-	ret = kstrtou16(buf, 10, &value);
-	if (ret)
-		return ret;
-
-	line6->line6midi->midi_mask_transmit = value;
-	return count;
-}
-
-/*
-	"read" request on "midi_mask_receive" special file.
-*/
-static ssize_t midi_get_midi_mask_receive(struct device *dev,
-					  struct device_attribute *attr,
-					  char *buf)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6 *line6 = usb_get_intfdata(interface);
-	return sprintf(buf, "%d\n", line6->line6midi->midi_mask_receive);
-}
-
-/*
-	"write" request on "midi_mask" special file.
-*/
-static ssize_t midi_set_midi_mask_receive(struct device *dev,
-					  struct device_attribute *attr,
-					  const char *buf, size_t count)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6 *line6 = usb_get_intfdata(interface);
-	unsigned short value;
-	int ret;
-
-	ret = kstrtou16(buf, 10, &value);
-	if (ret)
-		return ret;
-
-	line6->line6midi->midi_mask_receive = value;
-	return count;
-}
-
-static DEVICE_ATTR(midi_mask_transmit, S_IWUSR | S_IRUGO,
-		   midi_get_midi_mask_transmit, midi_set_midi_mask_transmit);
-static DEVICE_ATTR(midi_mask_receive, S_IWUSR | S_IRUGO,
-		   midi_get_midi_mask_receive, midi_set_midi_mask_receive);
-
 /* MIDI device destructor */
 static int snd_line6_midi_free(struct snd_device *device)
 {
 	struct snd_line6_midi *line6midi = device->device_data;
-	device_remove_file(line6midi->line6->ifcdev,
-			   &dev_attr_midi_mask_transmit);
-	device_remove_file(line6midi->line6->ifcdev,
-			   &dev_attr_midi_mask_receive);
 	line6_midibuf_destroy(&line6midi->midibuf_in);
 	line6_midibuf_destroy(&line6midi->midibuf_out);
 	return 0;
@@ -405,19 +300,6 @@ int line6_init_midi(struct usb_line6 *line6)
 	}
 
 	line6midi->line6 = line6;
-
-	switch (line6->product) {
-	case LINE6_DEVID_PODHD300:
-	case LINE6_DEVID_PODHD500:
-		line6midi->midi_mask_transmit = 1;
-		line6midi->midi_mask_receive = 1;
-		break;
-
-	default:
-		line6midi->midi_mask_transmit = 1;
-		line6midi->midi_mask_receive = 4;
-	}
-
 	line6->line6midi = line6midi;
 
 	err = snd_device_new(line6->card, SNDRV_DEV_RAWMIDI, line6midi,
@@ -431,14 +313,6 @@ int line6_init_midi(struct usb_line6 *line6)
 	if (err < 0)
 		return err;
 
-	err = device_create_file(line6->ifcdev, &dev_attr_midi_mask_transmit);
-	if (err < 0)
-		return err;
-
-	err = device_create_file(line6->ifcdev, &dev_attr_midi_mask_receive);
-	if (err < 0)
-		return err;
-
 	init_waitqueue_head(&line6midi->send_wait);
 	spin_lock_init(&line6midi->send_urb_lock);
 	spin_lock_init(&line6midi->midi_transmit_lock);
diff --git a/drivers/staging/line6/midi.h b/drivers/staging/line6/midi.h
index 4a9e9f9..19dabd5 100644
--- a/drivers/staging/line6/midi.h
+++ b/drivers/staging/line6/midi.h
@@ -55,16 +55,6 @@ struct snd_line6_midi {
 	wait_queue_head_t send_wait;
 
 	/**
-		 Bit mask for output MIDI channels.
-	*/
-	unsigned short midi_mask_transmit;
-
-	/**
-		 Bit mask for input MIDI channels.
-	*/
-	unsigned short midi_mask_receive;
-
-	/**
 		 Buffer for incoming MIDI stream.
 	*/
 	struct MidiBuffer midibuf_in;
diff --git a/drivers/staging/line6/midibuf.c b/drivers/staging/line6/midibuf.c
index 836e8c8..968e0de 100644
--- a/drivers/staging/line6/midibuf.c
+++ b/drivers/staging/line6/midibuf.c
@@ -64,9 +64,9 @@ int line6_midibuf_init(struct MidiBuffer *this, int size, int split)
 
 void line6_midibuf_status(struct MidiBuffer *this)
 {
-	pr_debug("midibuf size=%d split=%d pos_read=%d pos_write=%d "
-	       "full=%d command_prev=%02x\n", this->size, this->split,
-	       this->pos_read, this->pos_write, this->full, this->command_prev);
+	pr_debug("midibuf size=%d split=%d pos_read=%d pos_write=%d full=%d command_prev=%02x\n",
+		 this->size, this->split, this->pos_read, this->pos_write,
+		 this->full, this->command_prev);
 }
 
 int line6_midibuf_bytes_free(struct MidiBuffer *this)
diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c
index 7fe44a6..6c1e313 100644
--- a/drivers/staging/line6/pcm.c
+++ b/drivers/staging/line6/pcm.c
@@ -109,7 +109,7 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels)
 	line6pcm->prev_fbuf = NULL;
 
 	if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_BUFFER)) {
-		/* We may be invoked multiple times in a row so allocate once only */
+		/* Invoked multiple times in a row so allocate once only */
 		if (!line6pcm->buffer_in) {
 			line6pcm->buffer_in =
 				kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
@@ -148,7 +148,7 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels)
 	}
 
 	if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_BUFFER)) {
-		/* We may be invoked multiple times in a row so allocate once only */
+		/* Invoked multiple times in a row so allocate once only */
 		if (!line6pcm->buffer_out) {
 			line6pcm->buffer_out =
 				kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
diff --git a/drivers/staging/line6/pcm.h b/drivers/staging/line6/pcm.h
index 5210ec8..6aa0d46 100644
--- a/drivers/staging/line6/pcm.h
+++ b/drivers/staging/line6/pcm.h
@@ -167,7 +167,7 @@ enum {
 #endif
 	    LINE6_BIT_PCM_ALSA_CAPTURE_STREAM |
 	    LINE6_BIT_PCM_MONITOR_CAPTURE_STREAM,
-	
+
 	LINE6_BITS_STREAM =
 	    LINE6_BITS_PLAYBACK_STREAM |
 	    LINE6_BITS_CAPTURE_STREAM
diff --git a/drivers/staging/line6/playback.c b/drivers/staging/line6/playback.c
index a0ab9d0..4cf23af 100644
--- a/drivers/staging/line6/playback.c
+++ b/drivers/staging/line6/playback.c
@@ -185,7 +185,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
 	if (urb_size == 0) {
 		/* can't determine URB size */
 		spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);
-		dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n");	/* this is somewhat paranoid */
+		dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n");
 		return -EINVAL;
 	}
 
@@ -218,7 +218,8 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
 				       len * bytes_per_frame, runtime->dma_area,
 				       (urb_frames - len) * bytes_per_frame);
 			} else
-				dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n", len);	/* this is somewhat paranoid */
+				dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n",
+					len);
 		} else {
 			memcpy(urb_out->transfer_buffer,
 			       runtime->dma_area +
@@ -319,7 +320,8 @@ void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm)
 }
 
 /*
-	Wait until unlinking of all currently active playback URBs has been finished.
+	Wait until unlinking of all currently active playback URBs has been
+	finished.
 */
 void line6_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm)
 {
@@ -413,7 +415,8 @@ static void audio_out_callback(struct urb *urb)
 	if (!shutdown) {
 		submit_audio_out_urb(line6pcm);
 
-		if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags)) {
+		if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM,
+			     &line6pcm->flags)) {
 			line6pcm->bytes_out += length;
 			if (line6pcm->bytes_out >= line6pcm->period_out) {
 				line6pcm->bytes_out %= line6pcm->period_out;
@@ -499,7 +502,8 @@ int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd)
 #ifdef CONFIG_PM
 	case SNDRV_PCM_TRIGGER_RESUME:
 #endif
-		err = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM);
+		err = line6_pcm_acquire(line6pcm,
+					LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM);
 
 		if (err < 0)
 			return err;
@@ -510,7 +514,8 @@ int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd)
 #ifdef CONFIG_PM
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 #endif
-		err = line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM);
+		err = line6_pcm_release(line6pcm,
+					LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM);
 
 		if (err < 0)
 			return err;
diff --git a/drivers/staging/line6/pod.c b/drivers/staging/line6/pod.c
index 9edd053..e542540 100644
--- a/drivers/staging/line6/pod.c
+++ b/drivers/staging/line6/pod.c
@@ -15,7 +15,6 @@
 
 #include "audio.h"
 #include "capture.h"
-#include "control.h"
 #include "driver.h"
 #include "playback.h"
 #include "pod.h"
@@ -26,7 +25,6 @@
 /* *INDENT-OFF* */
 
 enum {
-	POD_SYSEX_CLIP      = 0x0f,
 	POD_SYSEX_SAVE      = 0x24,
 	POD_SYSEX_SYSTEM    = 0x56,
 	POD_SYSEX_SYSTEMREQ = 0x57,
@@ -41,11 +39,6 @@ enum {
 
 enum {
 	POD_monitor_level  = 0x04,
-	POD_routing        = 0x05,
-	POD_tuner_mute     = 0x13,
-	POD_tuner_freq     = 0x15,
-	POD_tuner_note     = 0x16,
-	POD_tuner_pitch    = 0x17,
 	POD_system_invalid = 0x10000
 };
 
@@ -118,10 +111,6 @@ static struct line6_pcm_properties pod_pcm_properties = {
 	.bytes_per_frame = POD_BYTES_PER_FRAME
 };
 
-static const char pod_request_channel[] = {
-	0xf0, 0x00, 0x01, 0x0c, 0x03, 0x75, 0xf7
-};
-
 static const char pod_version_header[] = {
 	0xf2, 0x7e, 0x7f, 0x06, 0x02
 };
@@ -129,18 +118,6 @@ static const char pod_version_header[] = {
 /* forward declarations: */
 static void pod_startup2(unsigned long data);
 static void pod_startup3(struct usb_line6_pod *pod);
-static void pod_startup4(struct usb_line6_pod *pod);
-
-/*
-	Mark all parameters as dirty and notify waiting processes.
-*/
-static void pod_mark_batch_all_dirty(struct usb_line6_pod *pod)
-{
-	int i;
-
-	for (i = 0; i < POD_CONTROL_SIZE; i++)
-		set_bit(i, pod->param_dirty);
-}
 
 static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
 				    int size)
@@ -150,45 +127,6 @@ static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
 }
 
 /*
-	Send channel dump data to the PODxt Pro.
-*/
-static void pod_dump(struct usb_line6_pod *pod, const unsigned char *data)
-{
-	int size = 1 + sizeof(pod->prog_data);
-	char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_DUMP, size);
-	if (!sysex)
-		return;
-	/* Don't know what this is good for, but PODxt Pro transmits it, so we
-	 * also do... */
-	sysex[SYSEX_DATA_OFS] = 5;
-	memcpy(sysex + SYSEX_DATA_OFS + 1, data, sizeof(pod->prog_data));
-	line6_send_sysex_message(&pod->line6, sysex, size);
-	memcpy(&pod->prog_data, data, sizeof(pod->prog_data));
-	pod_mark_batch_all_dirty(pod);
-	kfree(sysex);
-}
-
-/*
-	Store parameter value in driver memory and mark it as dirty.
-*/
-static void pod_store_parameter(struct usb_line6_pod *pod, int param, int value)
-{
-	pod->prog_data.control[param] = value;
-	set_bit(param, pod->param_dirty);
-	pod->dirty = 1;
-}
-
-/*
-	Handle SAVE button.
-*/
-static void pod_save_button_pressed(struct usb_line6_pod *pod, int type,
-				    int index)
-{
-	pod->dirty = 0;
-	set_bit(POD_SAVE_PRESSED, &pod->atomic_flags);
-}
-
-/*
 	Process a completely received message.
 */
 void line6_pod_process_message(struct usb_line6_pod *pod)
@@ -209,25 +147,11 @@ void line6_pod_process_message(struct usb_line6_pod *pod)
 	/* process all remaining messages */
 	switch (buf[0]) {
 	case LINE6_PARAM_CHANGE | LINE6_CHANNEL_DEVICE:
-		pod_store_parameter(pod, buf[1], buf[2]);
-		/* intentionally no break here! */
-
 	case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST:
-		if ((buf[1] == POD_amp_model_setup) ||
-		    (buf[1] == POD_effect_setup))
-			/* these also affect other settings */
-			line6_dump_request_async(&pod->dumpreq, &pod->line6, 0,
-						 LINE6_DUMP_CURRENT);
-
 		break;
 
 	case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE:
 	case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST:
-		pod->channel_num = buf[1];
-		pod->dirty = 0;
-		set_bit(POD_CHANNEL_DIRTY, &pod->atomic_flags);
-		line6_dump_request_async(&pod->dumpreq, &pod->line6, 0,
-					 LINE6_DUMP_CURRENT);
 		break;
 
 	case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE:
@@ -235,43 +159,6 @@ void line6_pod_process_message(struct usb_line6_pod *pod)
 		if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) == 0) {
 			switch (buf[5]) {
 			case POD_SYSEX_DUMP:
-				if (pod->line6.message_length ==
-				    sizeof(pod->prog_data) + 7) {
-					switch (pod->dumpreq.in_progress) {
-					case LINE6_DUMP_CURRENT:
-						memcpy(&pod->prog_data, buf + 7,
-						       sizeof(pod->prog_data));
-						pod_mark_batch_all_dirty(pod);
-						break;
-
-					case POD_DUMP_MEMORY:
-						memcpy(&pod->prog_data_buf,
-						       buf + 7,
-						       sizeof
-						       (pod->prog_data_buf));
-						break;
-
-					default:
-						DEBUG_MESSAGES(dev_err
-							       (pod->
-								line6.ifcdev,
-								"unknown dump code %02X\n",
-								pod->
-								dumpreq.in_progress));
-					}
-
-					line6_dump_finished(&pod->dumpreq);
-					pod_startup3(pod);
-				} else
-					DEBUG_MESSAGES(dev_err
-						       (pod->line6.ifcdev,
-							"wrong size of channel dump message (%d instead of %d)\n",
-							pod->
-							line6.message_length,
-							(int)
-							sizeof(pod->prog_data) +
-							7));
-
 				break;
 
 			case POD_SYSEX_SYSTEM:{
@@ -280,35 +167,8 @@ void line6_pod_process_message(struct usb_line6_pod *pod)
 								   << 8) |
 					    ((int)buf[9] << 4) | (int)buf[10];
 
-#define PROCESS_SYSTEM_PARAM(x) \
-					case POD_ ## x: \
-						pod->x.value = value; \
-						wake_up(&pod->x.wait); \
-						break;
-
-					switch (buf[6]) {
-						PROCESS_SYSTEM_PARAM
-						    (monitor_level);
-						PROCESS_SYSTEM_PARAM(routing);
-						PROCESS_SYSTEM_PARAM
-						    (tuner_mute);
-						PROCESS_SYSTEM_PARAM
-						    (tuner_freq);
-						PROCESS_SYSTEM_PARAM
-						    (tuner_note);
-						PROCESS_SYSTEM_PARAM
-						    (tuner_pitch);
-
-#undef PROCESS_SYSTEM_PARAM
-
-					default:
-						DEBUG_MESSAGES(dev_err
-							       (pod->
-								line6.ifcdev,
-								"unknown tuner/system response %02X\n",
-								buf[6]));
-					}
-
+					if (buf[6] == POD_monitor_level)
+						pod->monitor_level = value;
 					break;
 				}
 
@@ -317,29 +177,18 @@ void line6_pod_process_message(struct usb_line6_pod *pod)
 				break;
 
 			case POD_SYSEX_SAVE:
-				pod_save_button_pressed(pod, buf[6], buf[7]);
-				break;
-
-			case POD_SYSEX_CLIP:
-				DEBUG_MESSAGES(dev_err
-					       (pod->line6.ifcdev,
-						"audio clipped\n"));
-				pod->clipping.value = 1;
-				wake_up(&pod->clipping.wait);
 				break;
 
 			case POD_SYSEX_STORE:
-				DEBUG_MESSAGES(dev_err
-					       (pod->line6.ifcdev,
-						"message %02X not yet implemented\n",
-						buf[5]));
+				dev_dbg(pod->line6.ifcdev,
+					"message %02X not yet implemented\n",
+					buf[5]);
 				break;
 
 			default:
-				DEBUG_MESSAGES(dev_err
-					       (pod->line6.ifcdev,
-						"unknown sysex message %02X\n",
-						buf[5]));
+				dev_dbg(pod->line6.ifcdev,
+					"unknown sysex message %02X\n",
+					buf[5]);
 			}
 		} else
 		    if (memcmp
@@ -350,11 +199,9 @@ void line6_pod_process_message(struct usb_line6_pod *pod)
 			pod->device_id =
 			    ((int)buf[8] << 16) | ((int)buf[9] << 8) | (int)
 			    buf[10];
-			pod_startup4(pod);
+			pod_startup3(pod);
 		} else
-			DEBUG_MESSAGES(dev_err
-				       (pod->line6.ifcdev,
-					"unknown sysex header\n"));
+			dev_dbg(pod->line6.ifcdev, "unknown sysex header\n");
 
 		break;
 
@@ -362,349 +209,22 @@ void line6_pod_process_message(struct usb_line6_pod *pod)
 		break;
 
 	default:
-		DEBUG_MESSAGES(dev_err
-			       (pod->line6.ifcdev,
-				"POD: unknown message %02X\n", buf[0]));
+		dev_dbg(pod->line6.ifcdev, "POD: unknown message %02X\n",
+			buf[0]);
 	}
 }
 
 /*
-	Detect some cases that require a channel dump after sending a command to the
-	device. Important notes:
-	*) The actual dump request can not be sent here since we are not allowed to
-	wait for the completion of the first message in this context, and sending
-	the dump request before completion of the previous message leaves the POD
-	in an undefined state. The dump request will be sent when the echoed
-	commands are received.
-	*) This method fails if a param change message is "chopped" after the first
-	byte.
-*/
-void line6_pod_midi_postprocess(struct usb_line6_pod *pod, unsigned char *data,
-				int length)
-{
-	int i;
-
-	if (!pod->midi_postprocess)
-		return;
-
-	for (i = 0; i < length; ++i) {
-		if (data[i] == (LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST)) {
-			line6_invalidate_current(&pod->dumpreq);
-			break;
-		} else
-		    if ((data[i] == (LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST))
-			&& (i < length - 1))
-			if ((data[i + 1] == POD_amp_model_setup)
-			    || (data[i + 1] == POD_effect_setup)) {
-				line6_invalidate_current(&pod->dumpreq);
-				break;
-			}
-	}
-}
-
-/*
-	Send channel number (i.e., switch to a different sound).
-*/
-static void pod_send_channel(struct usb_line6_pod *pod, u8 value)
-{
-	line6_invalidate_current(&pod->dumpreq);
-
-	if (line6_send_program(&pod->line6, value) == 0)
-		pod->channel_num = value;
-	else
-		line6_dump_finished(&pod->dumpreq);
-}
-
-/*
 	Transmit PODxt Pro control parameter.
 */
 void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
 				  u8 value)
 {
-	if (line6_transmit_parameter(&pod->line6, param, value) == 0)
-		pod_store_parameter(pod, param, value);
-
-	if ((param == POD_amp_model_setup) || (param == POD_effect_setup))	/* these also affect other settings */
-		line6_invalidate_current(&pod->dumpreq);
-}
-
-/*
-	Resolve value to memory location.
-*/
-static int pod_resolve(const char *buf, short block0, short block1,
-		       unsigned char *location)
-{
-	u8 value;
-	short block;
-	int ret;
-
-	ret = kstrtou8(buf, 10, &value);
-	if (ret)
-		return ret;
-
-	block = (value < 0x40) ? block0 : block1;
-	value &= 0x3f;
-	location[0] = block >> 7;
-	location[1] = value | (block & 0x7f);
-	return 0;
-}
-
-/*
-	Send command to store channel/effects setup/amp setup to PODxt Pro.
-*/
-static ssize_t pod_send_store_command(struct device *dev, const char *buf,
-				      size_t count, short block0, short block1)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-	int ret;
-	int size = 3 + sizeof(pod->prog_data_buf);
-	char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_STORE, size);
-
-	if (!sysex)
-		return 0;
-
-	sysex[SYSEX_DATA_OFS] = 5;	/* see pod_dump() */
-	ret = pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS + 1);
-	if (ret) {
-		kfree(sysex);
-		return ret;
-	}
-
-	memcpy(sysex + SYSEX_DATA_OFS + 3, &pod->prog_data_buf,
-	       sizeof(pod->prog_data_buf));
-
-	line6_send_sysex_message(&pod->line6, sysex, size);
-	kfree(sysex);
-	/* needs some delay here on AMD64 platform */
-	return count;
-}
-
-/*
-	Send command to retrieve channel/effects setup/amp setup to PODxt Pro.
-*/
-static ssize_t pod_send_retrieve_command(struct device *dev, const char *buf,
-					 size_t count, short block0,
-					 short block1)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-	int ret;
-	int size = 4;
-	char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_DUMPMEM, size);
-
-	if (!sysex)
-		return 0;
-
-	ret = pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS);
-	if (ret) {
-		kfree(sysex);
-		return ret;
-	}
-	sysex[SYSEX_DATA_OFS + 2] = 0;
-	sysex[SYSEX_DATA_OFS + 3] = 0;
-	line6_dump_started(&pod->dumpreq, POD_DUMP_MEMORY);
-
-	if (line6_send_sysex_message(&pod->line6, sysex, size) < size)
-		line6_dump_finished(&pod->dumpreq);
-
-	kfree(sysex);
-	/* needs some delay here on AMD64 platform */
-	return count;
-}
-
-/*
-	Generic get name function.
-*/
-static ssize_t get_name_generic(struct usb_line6_pod *pod, const char *str,
-				char *buf)
-{
-	int length = 0;
-	const char *p1;
-	char *p2;
-	char *last_non_space = buf;
-
-	int retval = line6_dump_wait_interruptible(&pod->dumpreq);
-	if (retval < 0)
-		return retval;
-
-	for (p1 = str, p2 = buf; *p1; ++p1, ++p2) {
-		*p2 = *p1;
-		if (*p2 != ' ')
-			last_non_space = p2;
-		if (++length == POD_NAME_LENGTH)
-			break;
-	}
-
-	*(last_non_space + 1) = '\n';
-	return last_non_space - buf + 2;
-}
-
-/*
-	"read" request on "channel" special file.
-*/
-static ssize_t pod_get_channel(struct device *dev,
-			       struct device_attribute *attr, char *buf)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-	return sprintf(buf, "%d\n", pod->channel_num);
-}
-
-/*
-	"write" request on "channel" special file.
-*/
-static ssize_t pod_set_channel(struct device *dev,
-			       struct device_attribute *attr,
-			       const char *buf, size_t count)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-	u8 value;
-	int ret;
-
-	ret = kstrtou8(buf, 10, &value);
-	if (ret)
-		return ret;
-
-	pod_send_channel(pod, value);
-	return count;
-}
-
-/*
-	"read" request on "name" special file.
-*/
-static ssize_t pod_get_name(struct device *dev, struct device_attribute *attr,
-			    char *buf)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-	return get_name_generic(pod, pod->prog_data.header + POD_NAME_OFFSET,
-				buf);
-}
-
-/*
-	"read" request on "name" special file.
-*/
-static ssize_t pod_get_name_buf(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-	return get_name_generic(pod,
-				pod->prog_data_buf.header + POD_NAME_OFFSET,
-				buf);
-}
-
-/*
-	"read" request on "dump" special file.
-*/
-static ssize_t pod_get_dump(struct device *dev, struct device_attribute *attr,
-			    char *buf)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-	int retval = line6_dump_wait_interruptible(&pod->dumpreq);
-	if (retval < 0)
-		return retval;
-	memcpy(buf, &pod->prog_data, sizeof(pod->prog_data));
-	return sizeof(pod->prog_data);
-}
-
-/*
-	"write" request on "dump" special file.
-*/
-static ssize_t pod_set_dump(struct device *dev, struct device_attribute *attr,
-			    const char *buf, size_t count)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-
-	if (count != sizeof(pod->prog_data)) {
-		dev_err(pod->line6.ifcdev,
-			"data block must be exactly %d bytes\n",
-			(int)sizeof(pod->prog_data));
-		return -EINVAL;
-	}
-
-	pod_dump(pod, buf);
-	return sizeof(pod->prog_data);
-}
-
-/*
-	Identify system parameters related to the tuner.
-*/
-static bool pod_is_tuner(int code)
-{
-	return
-	    (code == POD_tuner_mute) ||
-	    (code == POD_tuner_freq) ||
-	    (code == POD_tuner_note) || (code == POD_tuner_pitch);
-}
-
-/*
-	Get system parameter (as integer).
-	@param tuner non-zero, if code refers to a tuner parameter
-*/
-static int pod_get_system_param_int(struct usb_line6_pod *pod, int *value,
-				    int code, struct ValueWait *param, int sign)
-{
-	char *sysex;
-	static const int size = 1;
-	int retval = 0;
-
-	if (((pod->prog_data.control[POD_tuner] & 0x40) == 0)
-	    && pod_is_tuner(code))
-		return -ENODEV;
-
-	/* send value request to device: */
-	param->value = POD_system_invalid;
-	sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEMREQ, size);
-
-	if (!sysex)
-		return -ENOMEM;
-
-	sysex[SYSEX_DATA_OFS] = code;
-	line6_send_sysex_message(&pod->line6, sysex, size);
-	kfree(sysex);
-
-	/* wait for device to respond: */
-	retval =
-	    wait_event_interruptible(param->wait,
-				     param->value != POD_system_invalid);
-
-	if (retval < 0)
-		return retval;
-
-	*value = sign ? (int)(signed short)param->value : (int)(unsigned short)
-	    param->value;
-
-	if (*value == POD_system_invalid)
-		*value = 0;	/* don't report uninitialized values */
-
-	return 0;
-}
-
-/*
-	Get system parameter (as string).
-	@param tuner non-zero, if code refers to a tuner parameter
-*/
-static ssize_t pod_get_system_param_string(struct usb_line6_pod *pod, char *buf,
-					   int code, struct ValueWait *param,
-					   int sign)
-{
-	int retval, value = 0;
-	retval = pod_get_system_param_int(pod, &value, code, param, sign);
-
-	if (retval < 0)
-		return retval;
-
-	return sprintf(buf, "%d\n", value);
+	line6_transmit_parameter(&pod->line6, param, value);
 }
 
 /*
 	Send system parameter (from integer).
-	@param tuner non-zero, if code refers to a tuner parameter
 */
 static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
 				    int code)
@@ -712,11 +232,6 @@ static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
 	char *sysex;
 	static const int size = 5;
 
-	if (((pod->prog_data.control[POD_tuner] & 0x40) == 0)
-	    && pod_is_tuner(code))
-		return -EINVAL;
-
-	/* send value to tuner: */
 	sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
 	if (!sysex)
 		return -ENOMEM;
@@ -731,179 +246,6 @@ static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
 }
 
 /*
-	Send system parameter (from string).
-	@param tuner non-zero, if code refers to a tuner parameter
-*/
-static ssize_t pod_set_system_param_string(struct usb_line6_pod *pod,
-					   const char *buf, int count, int code,
-					   unsigned short mask)
-{
-	int retval;
-	unsigned short value = simple_strtoul(buf, NULL, 10) & mask;
-	retval = pod_set_system_param_int(pod, value, code);
-	return (retval < 0) ? retval : count;
-}
-
-/*
-	"read" request on "dump_buf" special file.
-*/
-static ssize_t pod_get_dump_buf(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-	int retval = line6_dump_wait_interruptible(&pod->dumpreq);
-	if (retval < 0)
-		return retval;
-	memcpy(buf, &pod->prog_data_buf, sizeof(pod->prog_data_buf));
-	return sizeof(pod->prog_data_buf);
-}
-
-/*
-	"write" request on "dump_buf" special file.
-*/
-static ssize_t pod_set_dump_buf(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t count)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-
-	if (count != sizeof(pod->prog_data)) {
-		dev_err(pod->line6.ifcdev,
-			"data block must be exactly %d bytes\n",
-			(int)sizeof(pod->prog_data));
-		return -EINVAL;
-	}
-
-	memcpy(&pod->prog_data_buf, buf, sizeof(pod->prog_data));
-	return sizeof(pod->prog_data);
-}
-
-/*
-	"write" request on "finish" special file.
-*/
-static ssize_t pod_set_finish(struct device *dev,
-			      struct device_attribute *attr,
-			      const char *buf, size_t count)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-	int size = 0;
-	char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_FINISH, size);
-	if (!sysex)
-		return 0;
-	line6_send_sysex_message(&pod->line6, sysex, size);
-	kfree(sysex);
-	return count;
-}
-
-/*
-	"write" request on "store_channel" special file.
-*/
-static ssize_t pod_set_store_channel(struct device *dev,
-				     struct device_attribute *attr,
-				     const char *buf, size_t count)
-{
-	return pod_send_store_command(dev, buf, count, 0x0000, 0x00c0);
-}
-
-/*
-	"write" request on "store_effects_setup" special file.
-*/
-static ssize_t pod_set_store_effects_setup(struct device *dev,
-					   struct device_attribute *attr,
-					   const char *buf, size_t count)
-{
-	return pod_send_store_command(dev, buf, count, 0x0080, 0x0080);
-}
-
-/*
-	"write" request on "store_amp_setup" special file.
-*/
-static ssize_t pod_set_store_amp_setup(struct device *dev,
-				       struct device_attribute *attr,
-				       const char *buf, size_t count)
-{
-	return pod_send_store_command(dev, buf, count, 0x0040, 0x0100);
-}
-
-/*
-	"write" request on "retrieve_channel" special file.
-*/
-static ssize_t pod_set_retrieve_channel(struct device *dev,
-					struct device_attribute *attr,
-					const char *buf, size_t count)
-{
-	return pod_send_retrieve_command(dev, buf, count, 0x0000, 0x00c0);
-}
-
-/*
-	"write" request on "retrieve_effects_setup" special file.
-*/
-static ssize_t pod_set_retrieve_effects_setup(struct device *dev,
-					      struct device_attribute *attr,
-					      const char *buf, size_t count)
-{
-	return pod_send_retrieve_command(dev, buf, count, 0x0080, 0x0080);
-}
-
-/*
-	"write" request on "retrieve_amp_setup" special file.
-*/
-static ssize_t pod_set_retrieve_amp_setup(struct device *dev,
-					  struct device_attribute *attr,
-					  const char *buf, size_t count)
-{
-	return pod_send_retrieve_command(dev, buf, count, 0x0040, 0x0100);
-}
-
-/*
-	"read" request on "dirty" special file.
-*/
-static ssize_t pod_get_dirty(struct device *dev, struct device_attribute *attr,
-			     char *buf)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-	buf[0] = pod->dirty ? '1' : '0';
-	buf[1] = '\n';
-	return 2;
-}
-
-/*
-	"read" request on "midi_postprocess" special file.
-*/
-static ssize_t pod_get_midi_postprocess(struct device *dev,
-					struct device_attribute *attr,
-					char *buf)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-	return sprintf(buf, "%d\n", pod->midi_postprocess);
-}
-
-/*
-	"write" request on "midi_postprocess" special file.
-*/
-static ssize_t pod_set_midi_postprocess(struct device *dev,
-					struct device_attribute *attr,
-					const char *buf, size_t count)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-	u8 value;
-	int ret;
-
-	ret = kstrtou8(buf, 10, &value);
-	if (ret)
-		return ret;
-
-	pod->midi_postprocess = value ? 1 : 0;
-	return count;
-}
-
-/*
 	"read" request on "serial_number" special file.
 */
 static ssize_t pod_get_serial_number(struct device *dev,
@@ -939,18 +281,6 @@ static ssize_t pod_get_device_id(struct device *dev,
 }
 
 /*
-	"read" request on "clip" special file.
-*/
-static ssize_t pod_wait_for_clip(struct device *dev,
-				 struct device_attribute *attr, char *buf)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
-	return wait_event_interruptible(pod->clipping.wait,
-					pod->clipping.value != 0);
-}
-
-/*
 	POD startup procedure.
 	This is a sequence of functions with special requirements (e.g., must
 	not run immediately after initialization, must not run in interrupt
@@ -969,22 +299,6 @@ static void pod_startup1(struct usb_line6_pod *pod)
 static void pod_startup2(unsigned long data)
 {
 	struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
-
-	/* schedule another startup procedure until startup is complete: */
-	if (pod->startup_progress >= POD_STARTUP_LAST)
-		return;
-
-	pod->startup_progress = POD_STARTUP_DUMPREQ;
-	line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
-			  (unsigned long)pod);
-
-	/* current channel dump: */
-	line6_dump_request_async(&pod->dumpreq, &pod->line6, 0,
-				 LINE6_DUMP_CURRENT);
-}
-
-static void pod_startup3(struct usb_line6_pod *pod)
-{
 	struct usb_line6 *line6 = &pod->line6;
 	CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
 
@@ -992,7 +306,7 @@ static void pod_startup3(struct usb_line6_pod *pod)
 	line6_version_request_async(line6);
 }
 
-static void pod_startup4(struct usb_line6_pod *pod)
+static void pod_startup3(struct usb_line6_pod *pod)
 {
 	CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
 
@@ -1000,7 +314,7 @@ static void pod_startup4(struct usb_line6_pod *pod)
 	schedule_work(&pod->startup_work);
 }
 
-static void pod_startup5(struct work_struct *work)
+static void pod_startup4(struct work_struct *work)
 {
 	struct usb_line6_pod *pod =
 	    container_of(work, struct usb_line6_pod, startup_work);
@@ -1013,87 +327,14 @@ static void pod_startup5(struct work_struct *work)
 
 	/* ALSA audio interface: */
 	line6_register_audio(line6);
-
-	/* device files: */
-	line6_pod_create_files(pod->firmware_version,
-			       line6->properties->device_bit, line6->ifcdev);
-}
-
-#define POD_GET_SYSTEM_PARAM(code, sign) \
-static ssize_t pod_get_ ## code(struct device *dev, \
-				struct device_attribute *attr, char *buf) \
-{ \
-	struct usb_interface *interface = to_usb_interface(dev); \
-	struct usb_line6_pod *pod = usb_get_intfdata(interface); \
-	return pod_get_system_param_string(pod, buf, POD_ ## code,	\
-					   &pod->code, sign);		\
-}
-
-#define POD_GET_SET_SYSTEM_PARAM(code, mask, sign) \
-POD_GET_SYSTEM_PARAM(code, sign) \
-static ssize_t pod_set_ ## code(struct device *dev, \
-				struct device_attribute *attr, \
-				const char *buf, size_t count) \
-{ \
-	struct usb_interface *interface = to_usb_interface(dev); \
-	struct usb_line6_pod *pod = usb_get_intfdata(interface); \
-	return pod_set_system_param_string(pod, buf, count, POD_ ## code, mask); \
 }
 
-POD_GET_SET_SYSTEM_PARAM(monitor_level, 0xffff, 0);
-POD_GET_SET_SYSTEM_PARAM(routing, 0x0003, 0);
-POD_GET_SET_SYSTEM_PARAM(tuner_mute, 0x0001, 0);
-POD_GET_SET_SYSTEM_PARAM(tuner_freq, 0xffff, 0);
-POD_GET_SYSTEM_PARAM(tuner_note, 1);
-POD_GET_SYSTEM_PARAM(tuner_pitch, 1);
-
-#undef GET_SET_SYSTEM_PARAM
-#undef GET_SYSTEM_PARAM
-
 /* POD special files: */
-static DEVICE_ATTR(channel, S_IWUSR | S_IRUGO, pod_get_channel,
-		   pod_set_channel);
-static DEVICE_ATTR(clip, S_IRUGO, pod_wait_for_clip, line6_nop_write);
 static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write);
-static DEVICE_ATTR(dirty, S_IRUGO, pod_get_dirty, line6_nop_write);
-static DEVICE_ATTR(dump, S_IWUSR | S_IRUGO, pod_get_dump, pod_set_dump);
-static DEVICE_ATTR(dump_buf, S_IWUSR | S_IRUGO, pod_get_dump_buf,
-		   pod_set_dump_buf);
-static DEVICE_ATTR(finish, S_IWUSR, line6_nop_read, pod_set_finish);
 static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version,
 		   line6_nop_write);
-static DEVICE_ATTR(midi_postprocess, S_IWUSR | S_IRUGO,
-		   pod_get_midi_postprocess, pod_set_midi_postprocess);
-static DEVICE_ATTR(monitor_level, S_IWUSR | S_IRUGO, pod_get_monitor_level,
-		   pod_set_monitor_level);
-static DEVICE_ATTR(name, S_IRUGO, pod_get_name, line6_nop_write);
-static DEVICE_ATTR(name_buf, S_IRUGO, pod_get_name_buf, line6_nop_write);
-static DEVICE_ATTR(retrieve_amp_setup, S_IWUSR, line6_nop_read,
-		   pod_set_retrieve_amp_setup);
-static DEVICE_ATTR(retrieve_channel, S_IWUSR, line6_nop_read,
-		   pod_set_retrieve_channel);
-static DEVICE_ATTR(retrieve_effects_setup, S_IWUSR, line6_nop_read,
-		   pod_set_retrieve_effects_setup);
-static DEVICE_ATTR(routing, S_IWUSR | S_IRUGO, pod_get_routing,
-		   pod_set_routing);
 static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number,
 		   line6_nop_write);
-static DEVICE_ATTR(store_amp_setup, S_IWUSR, line6_nop_read,
-		   pod_set_store_amp_setup);
-static DEVICE_ATTR(store_channel, S_IWUSR, line6_nop_read,
-		   pod_set_store_channel);
-static DEVICE_ATTR(store_effects_setup, S_IWUSR, line6_nop_read,
-		   pod_set_store_effects_setup);
-static DEVICE_ATTR(tuner_freq, S_IWUSR | S_IRUGO, pod_get_tuner_freq,
-		   pod_set_tuner_freq);
-static DEVICE_ATTR(tuner_mute, S_IWUSR | S_IRUGO, pod_get_tuner_mute,
-		   pod_set_tuner_mute);
-static DEVICE_ATTR(tuner_note, S_IRUGO, pod_get_tuner_note, line6_nop_write);
-static DEVICE_ATTR(tuner_pitch, S_IRUGO, pod_get_tuner_pitch, line6_nop_write);
-
-#ifdef CONFIG_LINE6_USB_RAW
-static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw);
-#endif
 
 /* control info callback */
 static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
@@ -1112,7 +353,7 @@ static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
 {
 	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
 	struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
-	ucontrol->value.integer.value[0] = pod->monitor_level.value;
+	ucontrol->value.integer.value[0] = pod->monitor_level;
 	return 0;
 }
 
@@ -1123,10 +364,10 @@ static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
 	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
 	struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
 
-	if (ucontrol->value.integer.value[0] == pod->monitor_level.value)
+	if (ucontrol->value.integer.value[0] == pod->monitor_level)
 		return 0;
 
-	pod->monitor_level.value = ucontrol->value.integer.value[0];
+	pod->monitor_level = ucontrol->value.integer.value[0];
 	pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
 				 POD_monitor_level);
 	return 1;
@@ -1156,9 +397,6 @@ static void pod_destruct(struct usb_interface *interface)
 
 	del_timer(&pod->startup_timer);
 	cancel_work_sync(&pod->startup_work);
-
-	/* free dump request data: */
-	line6_dumpreq_destruct(&pod->dumpreq);
 }
 
 /*
@@ -1168,35 +406,9 @@ static int pod_create_files2(struct device *dev)
 {
 	int err;
 
-	CHECK_RETURN(device_create_file(dev, &dev_attr_channel));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_clip));
 	CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_dirty));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_dump));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_dump_buf));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_finish));
 	CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_midi_postprocess));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_monitor_level));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_name));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_name_buf));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_amp_setup));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_channel));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_effects_setup));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_routing));
 	CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_store_amp_setup));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_store_channel));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_store_effects_setup));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_freq));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_mute));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_note));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_pitch));
-
-#ifdef CONFIG_LINE6_USB_RAW
-	CHECK_RETURN(device_create_file(dev, &dev_attr_raw));
-#endif
-
 	return 0;
 }
 
@@ -1210,32 +422,11 @@ static int pod_try_init(struct usb_interface *interface,
 	struct usb_line6 *line6 = &pod->line6;
 
 	init_timer(&pod->startup_timer);
-	INIT_WORK(&pod->startup_work, pod_startup5);
+	INIT_WORK(&pod->startup_work, pod_startup4);
 
 	if ((interface == NULL) || (pod == NULL))
 		return -ENODEV;
 
-	pod->channel_num = 255;
-
-	/* initialize wait queues: */
-	init_waitqueue_head(&pod->monitor_level.wait);
-	init_waitqueue_head(&pod->routing.wait);
-	init_waitqueue_head(&pod->tuner_mute.wait);
-	init_waitqueue_head(&pod->tuner_freq.wait);
-	init_waitqueue_head(&pod->tuner_note.wait);
-	init_waitqueue_head(&pod->tuner_pitch.wait);
-	init_waitqueue_head(&pod->clipping.wait);
-
-	memset(pod->param_dirty, 0xff, sizeof(pod->param_dirty));
-
-	/* initialize USB buffers: */
-	err = line6_dumpreq_init(&pod->dumpreq, pod_request_channel,
-				 sizeof(pod_request_channel));
-	if (err < 0) {
-		dev_err(&interface->dev, "Out of memory\n");
-		return -ENOMEM;
-	}
-
 	/* create sysfs entries: */
 	err = pod_create_files2(&interface->dev);
 	if (err < 0)
@@ -1269,7 +460,7 @@ static int pod_try_init(struct usb_interface *interface,
 	 */
 
 	if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
-		pod->monitor_level.value = POD_system_invalid;
+		pod->monitor_level = POD_system_invalid;
 
 		/* initiate startup procedure: */
 		pod_startup1(pod);
@@ -1311,39 +502,9 @@ void line6_pod_disconnect(struct usb_interface *interface)
 
 		if (dev != NULL) {
 			/* remove sysfs entries: */
-			line6_pod_remove_files(pod->firmware_version,
-					       pod->line6.
-					       properties->device_bit, dev);
-
-			device_remove_file(dev, &dev_attr_channel);
-			device_remove_file(dev, &dev_attr_clip);
 			device_remove_file(dev, &dev_attr_device_id);
-			device_remove_file(dev, &dev_attr_dirty);
-			device_remove_file(dev, &dev_attr_dump);
-			device_remove_file(dev, &dev_attr_dump_buf);
-			device_remove_file(dev, &dev_attr_finish);
 			device_remove_file(dev, &dev_attr_firmware_version);
-			device_remove_file(dev, &dev_attr_midi_postprocess);
-			device_remove_file(dev, &dev_attr_monitor_level);
-			device_remove_file(dev, &dev_attr_name);
-			device_remove_file(dev, &dev_attr_name_buf);
-			device_remove_file(dev, &dev_attr_retrieve_amp_setup);
-			device_remove_file(dev, &dev_attr_retrieve_channel);
-			device_remove_file(dev,
-					   &dev_attr_retrieve_effects_setup);
-			device_remove_file(dev, &dev_attr_routing);
 			device_remove_file(dev, &dev_attr_serial_number);
-			device_remove_file(dev, &dev_attr_store_amp_setup);
-			device_remove_file(dev, &dev_attr_store_channel);
-			device_remove_file(dev, &dev_attr_store_effects_setup);
-			device_remove_file(dev, &dev_attr_tuner_freq);
-			device_remove_file(dev, &dev_attr_tuner_mute);
-			device_remove_file(dev, &dev_attr_tuner_note);
-			device_remove_file(dev, &dev_attr_tuner_pitch);
-
-#ifdef CONFIG_LINE6_USB_RAW
-			device_remove_file(dev, &dev_attr_raw);
-#endif
 		}
 	}
 
diff --git a/drivers/staging/line6/pod.h b/drivers/staging/line6/pod.h
index 47e0d1a..3e3f167 100644
--- a/drivers/staging/line6/pod.h
+++ b/drivers/staging/line6/pod.h
@@ -15,12 +15,10 @@
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/usb.h>
-#include <linux/wait.h>
 
 #include <sound/core.h>
 
 #include "driver.h"
-#include "dumprequest.h"
 
 /*
 	PODxt Live interfaces
@@ -46,37 +44,12 @@
 */
 enum {
 	POD_STARTUP_INIT = 1,
-	POD_STARTUP_DUMPREQ,
 	POD_STARTUP_VERSIONREQ,
 	POD_STARTUP_WORKQUEUE,
 	POD_STARTUP_SETUP,
 	POD_STARTUP_LAST = POD_STARTUP_SETUP - 1
 };
 
-/**
-	Data structure for values that need to be requested explicitly.
-	This is the case for system and tuner settings.
-*/
-struct ValueWait {
-	int value;
-	wait_queue_head_t wait;
-};
-
-/**
-	Binary PODxt Pro program dump
-*/
-struct pod_program {
-	/**
-		Header information (including program name).
-	*/
-	unsigned char header[0x20];
-
-	/**
-		Program parameters.
-	*/
-	unsigned char control[POD_CONTROL_SIZE];
-};
-
 struct usb_line6_pod {
 	/**
 		Generic Line6 USB data.
@@ -84,63 +57,9 @@ struct usb_line6_pod {
 	struct usb_line6 line6;
 
 	/**
-		Dump request structure.
-	*/
-	struct line6_dump_request dumpreq;
-
-	/**
-		Current program number.
-	*/
-	unsigned char channel_num;
-
-	/**
-		Current program settings.
-	*/
-	struct pod_program prog_data;
-
-	/**
-		Buffer for data retrieved from or to be stored on PODxt Pro.
-	*/
-	struct pod_program prog_data_buf;
-
-	/**
-		Tuner mute mode.
-	*/
-	struct ValueWait tuner_mute;
-
-	/**
-		Tuner base frequency (typically 440Hz).
-	*/
-	struct ValueWait tuner_freq;
-
-	/**
-		Note received from tuner.
-	*/
-	struct ValueWait tuner_note;
-
-	/**
-		Pitch value received from tuner.
-	*/
-	struct ValueWait tuner_pitch;
-
-	/**
 		Instrument monitor level.
 	*/
-	struct ValueWait monitor_level;
-
-	/**
-		Audio routing mode.
-		0: send processed guitar
-		1: send clean guitar
-		2: send clean guitar re-amp playback
-		3: send re-amp playback
-	*/
-	struct ValueWait routing;
-
-	/**
-		Wait for audio clipping event.
-	*/
-	struct ValueWait clipping;
+	int monitor_level;
 
 	/**
 		Timer for device initializaton.
@@ -158,16 +77,6 @@ struct usb_line6_pod {
 	int startup_progress;
 
 	/**
-		Dirty flags for access to parameter data.
-	*/
-	unsigned long param_dirty[POD_CONTROL_SIZE / sizeof(unsigned long)];
-
-	/**
-		Some atomic flags.
-	*/
-	unsigned long atomic_flags;
-
-	/**
 		Serial number of device.
 	*/
 	int serial_number;
@@ -181,23 +90,11 @@ struct usb_line6_pod {
 		Device ID.
 	*/
 	int device_id;
-
-	/**
-		Flag to indicate modification of current program settings.
-	*/
-	char dirty;
-
-	/**
-		Flag to enable MIDI postprocessing.
-	*/
-	char midi_postprocess;
 };
 
 extern void line6_pod_disconnect(struct usb_interface *interface);
 extern int line6_pod_init(struct usb_interface *interface,
 			  struct usb_line6_pod *pod);
-extern void line6_pod_midi_postprocess(struct usb_line6_pod *pod,
-				       unsigned char *data, int length);
 extern void line6_pod_process_message(struct usb_line6_pod *pod);
 extern void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
 					 u8 value);
diff --git a/drivers/staging/line6/toneport.c b/drivers/staging/line6/toneport.c
index 31b624b..a529dd3 100644
--- a/drivers/staging/line6/toneport.c
+++ b/drivers/staging/line6/toneport.c
@@ -127,13 +127,11 @@ static ssize_t toneport_set_led_red(struct device *dev,
 				    const char *buf, size_t count)
 {
 	int retval;
-	long value;
 
-	retval = strict_strtol(buf, 10, &value);
+	retval = kstrtoint(buf, 10, &led_red);
 	if (retval)
 		return retval;
 
-	led_red = value;
 	toneport_update_led(dev);
 	return count;
 }
@@ -143,13 +141,11 @@ static ssize_t toneport_set_led_green(struct device *dev,
 				      const char *buf, size_t count)
 {
 	int retval;
-	long value;
 
-	retval = strict_strtol(buf, 10, &value);
+	retval = kstrtoint(buf, 10, &led_green);
 	if (retval)
 		return retval;
 
-	led_green = value;
 	toneport_update_led(dev);
 	return count;
 }
diff --git a/drivers/staging/line6/usbdefs.h b/drivers/staging/line6/usbdefs.h
index 353d59d..43eb540 100644
--- a/drivers/staging/line6/usbdefs.h
+++ b/drivers/staging/line6/usbdefs.h
@@ -83,11 +83,15 @@ enum {
 	LINE6_BIT(VARIAX),
 
 	LINE6_BITS_PRO = LINE6_BIT_BASSPODXTPRO | LINE6_BIT_PODXTPRO,
-	LINE6_BITS_LIVE = LINE6_BIT_BASSPODXTLIVE | LINE6_BIT_PODXTLIVE | LINE6_BIT_PODX3LIVE,
-	LINE6_BITS_PODXTALL = LINE6_BIT_PODXT | LINE6_BIT_PODXTLIVE | LINE6_BIT_PODXTPRO,
+	LINE6_BITS_LIVE = LINE6_BIT_BASSPODXTLIVE | LINE6_BIT_PODXTLIVE |
+			  LINE6_BIT_PODX3LIVE,
+	LINE6_BITS_PODXTALL = LINE6_BIT_PODXT | LINE6_BIT_PODXTLIVE |
+			      LINE6_BIT_PODXTPRO,
 	LINE6_BITS_PODX3ALL = LINE6_BIT_PODX3 | LINE6_BIT_PODX3LIVE,
 	LINE6_BITS_PODHDALL = LINE6_BIT_PODHD300 | LINE6_BIT_PODHD500,
-	LINE6_BITS_BASSPODXTALL	= LINE6_BIT_BASSPODXT |	LINE6_BIT_BASSPODXTLIVE | LINE6_BIT_BASSPODXTPRO
+	LINE6_BITS_BASSPODXTALL	= LINE6_BIT_BASSPODXT |
+				  LINE6_BIT_BASSPODXTLIVE |
+				  LINE6_BIT_BASSPODXTPRO
 };
 
 /* device supports settings parameter via USB */
diff --git a/drivers/staging/line6/variax.c b/drivers/staging/line6/variax.c
index f97416b..4fca58f 100644
--- a/drivers/staging/line6/variax.c
+++ b/drivers/staging/line6/variax.c
@@ -12,28 +12,13 @@
 #include <linux/slab.h>
 
 #include "audio.h"
-#include "control.h"
 #include "driver.h"
 #include "variax.h"
 
-#define VARIAX_SYSEX_CODE 7
-#define VARIAX_SYSEX_PARAM 0x3b
-#define VARIAX_SYSEX_ACTIVATE 0x2a
-#define VARIAX_MODEL_HEADER_LENGTH 7
-#define VARIAX_MODEL_MESSAGE_LENGTH 199
 #define VARIAX_OFFSET_ACTIVATE 7
 
 /*
 	This message is sent by the device during initialization and identifies
-	the connected guitar model.
-*/
-static const char variax_init_model[] = {
-	0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x69, 0x02,
-	0x00
-};
-
-/*
-	This message is sent by the device during initialization and identifies
 	the connected guitar version.
 */
 static const char variax_init_version[] = {
@@ -53,43 +38,11 @@ static const char variax_activate[] = {
 	0xf7
 };
 
-static const char variax_request_bank[] = {
-	0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6d, 0xf7
-};
-
-static const char variax_request_model1[] = {
-	0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x3c, 0x00,
-	0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x05, 0x03,
-	0x00, 0x00, 0x00, 0xf7
-};
-
-static const char variax_request_model2[] = {
-	0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x3c, 0x00,
-	0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x03,
-	0x00, 0x00, 0x00, 0xf7
-};
-
 /* forward declarations: */
-static int variax_create_files2(struct device *dev);
 static void variax_startup2(unsigned long data);
 static void variax_startup4(unsigned long data);
 static void variax_startup5(unsigned long data);
 
-/*
-	Decode data transmitted by workbench.
-*/
-static void variax_decode(const unsigned char *raw_data, unsigned char *data,
-			  int raw_size)
-{
-	for (; raw_size > 0; raw_size -= 6) {
-		data[2] = raw_data[0] | (raw_data[1] << 4);
-		data[1] = raw_data[2] | (raw_data[3] << 4);
-		data[0] = raw_data[4] | (raw_data[5] << 4);
-		raw_data += 6;
-		data += 3;
-	}
-}
-
 static void variax_activate_async(struct usb_line6_variax *variax, int a)
 {
 	variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a;
@@ -155,37 +108,21 @@ static void variax_startup5(unsigned long data)
 {
 	struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
 	CHECK_STARTUP_PROGRESS(variax->startup_progress,
-			       VARIAX_STARTUP_DUMPREQ);
-
-	/* current model dump: */
-	line6_dump_request_async(&variax->dumpreq, &variax->line6, 0,
-				 VARIAX_DUMP_PASS1);
-	/* passes 2 and 3 are performed implicitly before entering variax_startup6 */
-}
-
-static void variax_startup6(struct usb_line6_variax *variax)
-{
-	CHECK_STARTUP_PROGRESS(variax->startup_progress,
 			       VARIAX_STARTUP_WORKQUEUE);
 
 	/* schedule work for global work queue: */
 	schedule_work(&variax->startup_work);
 }
 
-static void variax_startup7(struct work_struct *work)
+static void variax_startup6(struct work_struct *work)
 {
 	struct usb_line6_variax *variax =
 	    container_of(work, struct usb_line6_variax, startup_work);
-	struct usb_line6 *line6 = &variax->line6;
 
 	CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP);
 
 	/* ALSA audio interface: */
 	line6_register_audio(&variax->line6);
-
-	/* device files: */
-	line6_variax_create_files(0, 0, line6->ifcdev);
-	variax_create_files2(line6->ifcdev);
 }
 
 /*
@@ -197,22 +134,10 @@ void line6_variax_process_message(struct usb_line6_variax *variax)
 
 	switch (buf[0]) {
 	case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST:
-		switch (buf[1]) {
-		case VARIAXMIDI_volume:
-			variax->volume = buf[2];
-			break;
-
-		case VARIAXMIDI_tone:
-			variax->tone = buf[2];
-		}
-
 		break;
 
 	case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE:
 	case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST:
-		variax->model = buf[1];
-		line6_dump_request_async(&variax->dumpreq, &variax->line6, 0,
-					 VARIAX_DUMP_PASS1);
 		break;
 
 	case LINE6_RESET:
@@ -220,352 +145,25 @@ void line6_variax_process_message(struct usb_line6_variax *variax)
 		break;
 
 	case LINE6_SYSEX_BEGIN:
-		if (memcmp(buf + 1, variax_request_model1 + 1,
-			   VARIAX_MODEL_HEADER_LENGTH - 1) == 0) {
-			if (variax->line6.message_length ==
-			    VARIAX_MODEL_MESSAGE_LENGTH) {
-				switch (variax->dumpreq.in_progress) {
-				case VARIAX_DUMP_PASS1:
-					variax_decode(buf +
-						      VARIAX_MODEL_HEADER_LENGTH,
-						      (unsigned char *)
-						      &variax->model_data,
-						      (sizeof
-						       (variax->model_data.
-							name) +
-						       sizeof(variax->
-							      model_data.
-							      control)
-						       / 2) * 2);
-					line6_dump_request_async
-					    (&variax->dumpreq, &variax->line6,
-					     1, VARIAX_DUMP_PASS2);
-					break;
-
-				case VARIAX_DUMP_PASS2:
-					/* model name is transmitted twice, so skip it here: */
-					variax_decode(buf +
-						      VARIAX_MODEL_HEADER_LENGTH,
-						      (unsigned char *)
-						      &variax->
-						      model_data.control +
-						      sizeof(variax->model_data.
-							     control)
-						      / 2,
-						      sizeof(variax->model_data.
-							     control)
-						      / 2 * 2);
-					line6_dump_request_async
-					    (&variax->dumpreq, &variax->line6,
-					     2, VARIAX_DUMP_PASS3);
-				}
-			} else {
-				DEBUG_MESSAGES(dev_err
-					       (variax->line6.ifcdev,
-						"illegal length %d of model data\n",
-						variax->line6.message_length));
-				line6_dump_finished(&variax->dumpreq);
-			}
-		} else if (memcmp(buf + 1, variax_request_bank + 1,
-				  sizeof(variax_request_bank) - 2) == 0) {
-			memcpy(variax->bank,
-			       buf + sizeof(variax_request_bank) - 1,
-			       sizeof(variax->bank));
-			line6_dump_finished(&variax->dumpreq);
-			variax_startup6(variax);
-		} else if (memcmp(buf + 1, variax_init_model + 1,
-				  sizeof(variax_init_model) - 1) == 0) {
-			memcpy(variax->guitar,
-			       buf + sizeof(variax_init_model),
-			       sizeof(variax->guitar));
-		} else if (memcmp(buf + 1, variax_init_version + 1,
-				  sizeof(variax_init_version) - 1) == 0) {
+		if (memcmp(buf + 1, variax_init_version + 1,
+			   sizeof(variax_init_version) - 1) == 0) {
 			variax_startup3(variax);
 		} else if (memcmp(buf + 1, variax_init_done + 1,
 				  sizeof(variax_init_done) - 1) == 0) {
 			/* notify of complete initialization: */
 			variax_startup4((unsigned long)variax);
 		}
-
 		break;
 
 	case LINE6_SYSEX_END:
 		break;
 
 	default:
-		DEBUG_MESSAGES(dev_err
-			       (variax->line6.ifcdev,
-				"Variax: unknown message %02X\n", buf[0]));
-	}
-}
-
-/*
-	"read" request on "volume" special file.
-*/
-static ssize_t variax_get_volume(struct device *dev,
-				 struct device_attribute *attr, char *buf)
-{
-	struct usb_line6_variax *variax =
-	    usb_get_intfdata(to_usb_interface(dev));
-	return sprintf(buf, "%d\n", variax->volume);
-}
-
-/*
-	"write" request on "volume" special file.
-*/
-static ssize_t variax_set_volume(struct device *dev,
-				 struct device_attribute *attr,
-				 const char *buf, size_t count)
-{
-	struct usb_line6_variax *variax =
-	    usb_get_intfdata(to_usb_interface(dev));
-	u8 value;
-	int ret;
-
-	ret = kstrtou8(buf, 10, &value);
-	if (ret)
-		return ret;
-
-	if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_volume,
-				     value) == 0)
-		variax->volume = value;
-
-	return count;
-}
-
-/*
-	"read" request on "model" special file.
-*/
-static ssize_t variax_get_model(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct usb_line6_variax *variax =
-	    usb_get_intfdata(to_usb_interface(dev));
-	return sprintf(buf, "%d\n", variax->model);
-}
-
-/*
-	"write" request on "model" special file.
-*/
-static ssize_t variax_set_model(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t count)
-{
-	struct usb_line6_variax *variax =
-	    usb_get_intfdata(to_usb_interface(dev));
-	u8 value;
-	int ret;
-
-	ret = kstrtou8(buf, 10, &value);
-	if (ret)
-		return ret;
-
-	if (line6_send_program(&variax->line6, value) == 0)
-		variax->model = value;
-
-	return count;
-}
-
-/*
-	"read" request on "active" special file.
-*/
-static ssize_t variax_get_active(struct device *dev,
-				 struct device_attribute *attr, char *buf)
-{
-	struct usb_line6_variax *variax =
-	    usb_get_intfdata(to_usb_interface(dev));
-	return sprintf(buf, "%d\n",
-		       variax->buffer_activate[VARIAX_OFFSET_ACTIVATE]);
-}
-
-/*
-	"write" request on "active" special file.
-*/
-static ssize_t variax_set_active(struct device *dev,
-				 struct device_attribute *attr,
-				 const char *buf, size_t count)
-{
-	struct usb_line6_variax *variax =
-	    usb_get_intfdata(to_usb_interface(dev));
-	u8 value;
-	int ret;
-
-	ret = kstrtou8(buf, 10, &value);
-	if (ret)
-		return ret;
-
-	variax_activate_async(variax, value ? 1 : 0);
-	return count;
-}
-
-/*
-	"read" request on "tone" special file.
-*/
-static ssize_t variax_get_tone(struct device *dev,
-			       struct device_attribute *attr, char *buf)
-{
-	struct usb_line6_variax *variax =
-	    usb_get_intfdata(to_usb_interface(dev));
-	return sprintf(buf, "%d\n", variax->tone);
-}
-
-/*
-	"write" request on "tone" special file.
-*/
-static ssize_t variax_set_tone(struct device *dev,
-			       struct device_attribute *attr,
-			       const char *buf, size_t count)
-{
-	struct usb_line6_variax *variax =
-	    usb_get_intfdata(to_usb_interface(dev));
-	u8 value;
-	int ret;
-
-	ret = kstrtou8(buf, 10, &value);
-	if (ret)
-		return ret;
-
-	if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_tone,
-				     value) == 0)
-		variax->tone = value;
-
-	return count;
-}
-
-static ssize_t get_string(char *buf, const char *data, int length)
-{
-	int i;
-	memcpy(buf, data, length);
-
-	for (i = length; i--;) {
-		char c = buf[i];
-
-		if ((c != 0) && (c != ' '))
-			break;
-	}
-
-	buf[i + 1] = '\n';
-	return i + 2;
-}
-
-/*
-	"read" request on "name" special file.
-*/
-static ssize_t variax_get_name(struct device *dev,
-			       struct device_attribute *attr, char *buf)
-{
-	struct usb_line6_variax *variax =
-	    usb_get_intfdata(to_usb_interface(dev));
-	line6_dump_wait_interruptible(&variax->dumpreq);
-	return get_string(buf, variax->model_data.name,
-			  sizeof(variax->model_data.name));
-}
-
-/*
-	"read" request on "bank" special file.
-*/
-static ssize_t variax_get_bank(struct device *dev,
-			       struct device_attribute *attr, char *buf)
-{
-	struct usb_line6_variax *variax =
-	    usb_get_intfdata(to_usb_interface(dev));
-	line6_dump_wait_interruptible(&variax->dumpreq);
-	return get_string(buf, variax->bank, sizeof(variax->bank));
-}
-
-/*
-	"read" request on "dump" special file.
-*/
-static ssize_t variax_get_dump(struct device *dev,
-			       struct device_attribute *attr, char *buf)
-{
-	struct usb_line6_variax *variax =
-	    usb_get_intfdata(to_usb_interface(dev));
-	int retval;
-	retval = line6_dump_wait_interruptible(&variax->dumpreq);
-	if (retval < 0)
-		return retval;
-	memcpy(buf, &variax->model_data.control,
-	       sizeof(variax->model_data.control));
-	return sizeof(variax->model_data.control);
-}
-
-/*
-	"read" request on "guitar" special file.
-*/
-static ssize_t variax_get_guitar(struct device *dev,
-				 struct device_attribute *attr, char *buf)
-{
-	struct usb_line6_variax *variax =
-	    usb_get_intfdata(to_usb_interface(dev));
-	return sprintf(buf, "%s\n", variax->guitar);
-}
-
-#ifdef CONFIG_LINE6_USB_RAW
-
-static char *variax_alloc_sysex_buffer(struct usb_line6_variax *variax,
-				       int code, int size)
-{
-	return line6_alloc_sysex_buffer(&variax->line6, VARIAX_SYSEX_CODE, code,
-					size);
-}
-
-/*
-	"write" request on "raw" special file.
-*/
-static ssize_t variax_set_raw2(struct device *dev,
-			       struct device_attribute *attr,
-			       const char *buf, size_t count)
-{
-	struct usb_line6_variax *variax =
-	    usb_get_intfdata(to_usb_interface(dev));
-	int size;
-	int i;
-	char *sysex;
-
-	count -= count % 3;
-	size = count * 2;
-	sysex = variax_alloc_sysex_buffer(variax, VARIAX_SYSEX_PARAM, size);
-
-	if (!sysex)
-		return 0;
-
-	for (i = 0; i < count; i += 3) {
-		const unsigned char *p1 = buf + i;
-		char *p2 = sysex + SYSEX_DATA_OFS + i * 2;
-		p2[0] = p1[2] & 0x0f;
-		p2[1] = p1[2] >> 4;
-		p2[2] = p1[1] & 0x0f;
-		p2[3] = p1[1] >> 4;
-		p2[4] = p1[0] & 0x0f;
-		p2[5] = p1[0] >> 4;
+		dev_dbg(variax->line6.ifcdev,
+			"Variax: unknown message %02X\n", buf[0]);
 	}
-
-	line6_send_sysex_message(&variax->line6, sysex, size);
-	kfree(sysex);
-	return count;
 }
 
-#endif
-
-/* Variax workbench special files: */
-static DEVICE_ATTR(model, S_IWUSR | S_IRUGO, variax_get_model,
-		   variax_set_model);
-static DEVICE_ATTR(volume, S_IWUSR | S_IRUGO, variax_get_volume,
-		   variax_set_volume);
-static DEVICE_ATTR(tone, S_IWUSR | S_IRUGO, variax_get_tone, variax_set_tone);
-static DEVICE_ATTR(name, S_IRUGO, variax_get_name, line6_nop_write);
-static DEVICE_ATTR(bank, S_IRUGO, variax_get_bank, line6_nop_write);
-static DEVICE_ATTR(dump, S_IRUGO, variax_get_dump, line6_nop_write);
-static DEVICE_ATTR(active, S_IWUSR | S_IRUGO, variax_get_active,
-		   variax_set_active);
-static DEVICE_ATTR(guitar, S_IRUGO, variax_get_guitar, line6_nop_write);
-
-#ifdef CONFIG_LINE6_USB_RAW
-static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw);
-static DEVICE_ATTR(raw2, S_IWUSR, line6_nop_read, variax_set_raw2);
-#endif
-
 /*
 	Variax destructor.
 */
@@ -581,36 +179,10 @@ static void variax_destruct(struct usb_interface *interface)
 	del_timer(&variax->startup_timer2);
 	cancel_work_sync(&variax->startup_work);
 
-	/* free dump request data: */
-	line6_dumpreq_destructbuf(&variax->dumpreq, 2);
-	line6_dumpreq_destructbuf(&variax->dumpreq, 1);
-	line6_dumpreq_destruct(&variax->dumpreq);
-
 	kfree(variax->buffer_activate);
 }
 
 /*
-	Create sysfs entries.
-*/
-static int variax_create_files2(struct device *dev)
-{
-	int err;
-	CHECK_RETURN(device_create_file(dev, &dev_attr_model));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_volume));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_tone));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_name));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_bank));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_dump));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_active));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_guitar));
-#ifdef CONFIG_LINE6_USB_RAW
-	CHECK_RETURN(device_create_file(dev, &dev_attr_raw));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_raw2));
-#endif
-	return 0;
-}
-
-/*
 	 Try to init workbench device.
 */
 static int variax_try_init(struct usb_interface *interface,
@@ -620,36 +192,12 @@ static int variax_try_init(struct usb_interface *interface,
 
 	init_timer(&variax->startup_timer1);
 	init_timer(&variax->startup_timer2);
-	INIT_WORK(&variax->startup_work, variax_startup7);
+	INIT_WORK(&variax->startup_work, variax_startup6);
 
 	if ((interface == NULL) || (variax == NULL))
 		return -ENODEV;
 
 	/* initialize USB buffers: */
-	err = line6_dumpreq_init(&variax->dumpreq, variax_request_model1,
-				 sizeof(variax_request_model1));
-
-	if (err < 0) {
-		dev_err(&interface->dev, "Out of memory\n");
-		return err;
-	}
-
-	err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_model2,
-				    sizeof(variax_request_model2), 1);
-
-	if (err < 0) {
-		dev_err(&interface->dev, "Out of memory\n");
-		return err;
-	}
-
-	err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_bank,
-				    sizeof(variax_request_bank), 2);
-
-	if (err < 0) {
-		dev_err(&interface->dev, "Out of memory\n");
-		return err;
-	}
-
 	variax->buffer_activate = kmemdup(variax_activate,
 					  sizeof(variax_activate), GFP_KERNEL);
 
@@ -692,28 +240,8 @@ int line6_variax_init(struct usb_interface *interface,
 */
 void line6_variax_disconnect(struct usb_interface *interface)
 {
-	struct device *dev;
-
 	if (interface == NULL)
 		return;
-	dev = &interface->dev;
-
-	if (dev != NULL) {
-		/* remove sysfs entries: */
-		line6_variax_remove_files(0, 0, dev);
-		device_remove_file(dev, &dev_attr_model);
-		device_remove_file(dev, &dev_attr_volume);
-		device_remove_file(dev, &dev_attr_tone);
-		device_remove_file(dev, &dev_attr_name);
-		device_remove_file(dev, &dev_attr_bank);
-		device_remove_file(dev, &dev_attr_dump);
-		device_remove_file(dev, &dev_attr_active);
-		device_remove_file(dev, &dev_attr_guitar);
-#ifdef CONFIG_LINE6_USB_RAW
-		device_remove_file(dev, &dev_attr_raw);
-		device_remove_file(dev, &dev_attr_raw2);
-#endif
-	}
 
 	variax_destruct(interface);
 }
diff --git a/drivers/staging/line6/variax.h b/drivers/staging/line6/variax.h
index e2999ab..24de796 100644
--- a/drivers/staging/line6/variax.h
+++ b/drivers/staging/line6/variax.h
@@ -18,7 +18,6 @@
 #include <sound/core.h>
 
 #include "driver.h"
-#include "dumprequest.h"
 
 #define VARIAX_STARTUP_DELAY1 1000
 #define VARIAX_STARTUP_DELAY3 100
@@ -32,33 +31,11 @@ enum {
 	VARIAX_STARTUP_VERSIONREQ,
 	VARIAX_STARTUP_WAIT,
 	VARIAX_STARTUP_ACTIVATE,
-	VARIAX_STARTUP_DUMPREQ,
 	VARIAX_STARTUP_WORKQUEUE,
 	VARIAX_STARTUP_SETUP,
 	VARIAX_STARTUP_LAST = VARIAX_STARTUP_SETUP - 1
 };
 
-enum {
-	VARIAX_DUMP_PASS1 = LINE6_DUMP_CURRENT,
-	VARIAX_DUMP_PASS2,
-	VARIAX_DUMP_PASS3
-};
-
-/**
-	Binary Variax model dump
-*/
-struct variax_model {
-	/**
-		Header information (including program name).
-	*/
-	unsigned char name[18];
-
-	/**
-		Model parameters.
-	*/
-	unsigned char control[78 * 2];
-};
-
 struct usb_line6_variax {
 	/**
 		Generic Line6 USB data.
@@ -66,48 +43,11 @@ struct usb_line6_variax {
 	struct usb_line6 line6;
 
 	/**
-		Dump request structure.
-		Append two extra buffers for 3-pass data query.
-	*/
-	struct line6_dump_request dumpreq;
-	struct line6_dump_reqbuf extrabuf[2];
-
-	/**
 		Buffer for activation code.
 	*/
 	unsigned char *buffer_activate;
 
 	/**
-		Model number.
-	*/
-	int model;
-
-	/**
-		Current model settings.
-	*/
-	struct variax_model model_data;
-
-	/**
-		Name of connected guitar.
-	*/
-	unsigned char guitar[18];
-
-	/**
-		Name of current model bank.
-	*/
-	unsigned char bank[18];
-
-	/**
-		Position of volume dial.
-	*/
-	int volume;
-
-	/**
-		Position of tone control dial.
-	*/
-	int tone;
-
-	/**
 		Handler for device initializaton.
 	*/
 	struct work_struct startup_work;
diff --git a/drivers/staging/media/dt3155v4l/dt3155v4l.c b/drivers/staging/media/dt3155v4l/dt3155v4l.c
index 2e7b711..479c643 100644
--- a/drivers/staging/media/dt3155v4l/dt3155v4l.c
+++ b/drivers/staging/media/dt3155v4l/dt3155v4l.c
@@ -396,7 +396,9 @@ dt3155_open(struct file *filp)
 		pd->q->drv_priv = pd;
 		pd->curr_buf = NULL;
 		pd->field_count = 0;
-		vb2_queue_init(pd->q); /* cannot fail */
+		ret = vb2_queue_init(pd->q);
+		if (ret < 0)
+			return ret;
 		INIT_LIST_HEAD(&pd->dmaq);
 		spin_lock_init(&pd->lock);
 		/* disable all irqs, clear all irq flags */
@@ -718,7 +720,7 @@ static const struct v4l2_ioctl_ops dt3155_ioctl_ops = {
 */
 };
 
-static int __devinit
+static int
 dt3155_init_board(struct pci_dev *pdev)
 {
 	struct dt3155_priv *pd = pci_get_drvdata(pdev);
@@ -836,7 +838,7 @@ struct dma_coherent_mem {
 	unsigned long	*bitmap;
 };
 
-static int __devinit
+static int
 dt3155_alloc_coherent(struct device *dev, size_t size, int flags)
 {
 	struct dma_coherent_mem *mem;
@@ -877,7 +879,7 @@ out:
 	return 0;
 }
 
-static void __devexit
+static void
 dt3155_free_coherent(struct device *dev)
 {
 	struct dma_coherent_mem *mem = dev->dma_mem;
@@ -891,7 +893,7 @@ dt3155_free_coherent(struct device *dev)
 	kfree(mem);
 }
 
-static int __devinit
+static int
 dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	int err;
@@ -956,7 +958,7 @@ err_video_device_alloc:
 	return err;
 }
 
-static void __devexit
+static void
 dt3155_remove(struct pci_dev *pdev)
 {
 	struct dt3155_priv *pd = pci_get_drvdata(pdev);
@@ -983,7 +985,7 @@ static struct pci_driver pci_driver = {
 	.name = DT3155_NAME,
 	.id_table = pci_ids,
 	.probe = dt3155_probe,
-	.remove = __devexit_p(dt3155_remove),
+	.remove = dt3155_remove,
 };
 
 module_pci_driver(pci_driver);
diff --git a/drivers/staging/media/go7007/go7007-fw.c b/drivers/staging/media/go7007/go7007-fw.c
index c9a6409..f99c05b 100644
--- a/drivers/staging/media/go7007/go7007-fw.c
+++ b/drivers/staging/media/go7007/go7007-fw.c
@@ -382,8 +382,8 @@ static int gen_mjpeghdr_to_package(struct go7007 *go, __le16 *code, int space)
 
 	buf = kzalloc(4096, GFP_KERNEL);
 	if (buf == NULL) {
-		printk(KERN_ERR "go7007: unable to allocate 4096 bytes for "
-				"firmware construction\n");
+		dev_err(go->dev,
+			"unable to allocate 4096 bytes for firmware construction\n");
 		return -1;
 	}
 
@@ -652,8 +652,8 @@ static int gen_mpeg1hdr_to_package(struct go7007 *go,
 
 	buf = kzalloc(5120, GFP_KERNEL);
 	if (buf == NULL) {
-		printk(KERN_ERR "go7007: unable to allocate 5120 bytes for "
-				"firmware construction\n");
+		dev_err(go->dev,
+			"unable to allocate 5120 bytes for firmware construction\n");
 		return -1;
 	}
 	framelen[0] = mpeg1_frame_header(go, buf, 0, 1, PFRAME);
@@ -839,8 +839,8 @@ static int gen_mpeg4hdr_to_package(struct go7007 *go,
 
 	buf = kzalloc(5120, GFP_KERNEL);
 	if (buf == NULL) {
-		printk(KERN_ERR "go7007: unable to allocate 5120 bytes for "
-				"firmware construction\n");
+		dev_err(go->dev,
+			"unable to allocate 5120 bytes for firmware construction\n");
 		return -1;
 	}
 	framelen[0] = mpeg4_frame_header(go, buf, 0, PFRAME);
@@ -1545,9 +1545,8 @@ static int do_special(struct go7007 *go, u16 type, __le16 *code, int space,
 	case SPECIAL_MODET:
 		return modet_to_package(go, code, space);
 	}
-	printk(KERN_ERR
-		"go7007: firmware file contains unsupported feature %04x\n",
-		type);
+	dev_err(go->dev,
+		"firmware file contains unsupported feature %04x\n", type);
 	return -1;
 }
 
@@ -1577,15 +1576,16 @@ int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen)
 		return -1;
 	}
 	if (request_firmware(&fw_entry, go->board_info->firmware, go->dev)) {
-		printk(KERN_ERR
-			"go7007: unable to load firmware from file \"%s\"\n",
+		dev_err(go->dev,
+			"unable to load firmware from file \"%s\"\n",
 			go->board_info->firmware);
 		return -1;
 	}
 	code = kzalloc(codespace * 2, GFP_KERNEL);
 	if (code == NULL) {
-		printk(KERN_ERR "go7007: unable to allocate %d bytes for "
-				"firmware construction\n", codespace * 2);
+		dev_err(go->dev,
+			"unable to allocate %d bytes for firmware construction\n",
+			codespace * 2);
 		goto fw_failed;
 	}
 	src = (__le16 *)fw_entry->data;
@@ -1594,9 +1594,9 @@ int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen)
 		chunk_flags = __le16_to_cpu(src[0]);
 		chunk_len = __le16_to_cpu(src[1]);
 		if (chunk_len + 2 > srclen) {
-			printk(KERN_ERR "go7007: firmware file \"%s\" "
-					"appears to be corrupted\n",
-					go->board_info->firmware);
+			dev_err(go->dev,
+				"firmware file \"%s\" appears to be corrupted\n",
+				go->board_info->firmware);
 			goto fw_failed;
 		}
 		if (chunk_flags & mode_flag) {
@@ -1604,17 +1604,15 @@ int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen)
 				ret = do_special(go, __le16_to_cpu(src[2]),
 					&code[i], codespace - i, framelen);
 				if (ret < 0) {
-					printk(KERN_ERR "go7007: insufficient "
-							"memory for firmware "
-							"construction\n");
+					dev_err(go->dev,
+						"insufficient memory for firmware construction\n");
 					goto fw_failed;
 				}
 				i += ret;
 			} else {
 				if (codespace - i < chunk_len) {
-					printk(KERN_ERR "go7007: insufficient "
-							"memory for firmware "
-							"construction\n");
+					dev_err(go->dev,
+						"insufficient memory for firmware construction\n");
 					goto fw_failed;
 				}
 				memcpy(&code[i], &src[2], chunk_len * 2);
diff --git a/drivers/staging/media/go7007/go7007-v4l2.c b/drivers/staging/media/go7007/go7007-v4l2.c
index 980371b..a78133b 100644
--- a/drivers/staging/media/go7007/go7007-v4l2.c
+++ b/drivers/staging/media/go7007/go7007-v4l2.c
@@ -812,7 +812,7 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 		return retval;
 
 	mutex_lock(&gofh->lock);
-	if (buf->index < 0 || buf->index >= gofh->buf_count)
+	if (buf->index >= gofh->buf_count)
 		goto unlock_and_return;
 
 	gobuf = &gofh->bufs[buf->index];
diff --git a/drivers/staging/media/go7007/s2250-board.c b/drivers/staging/media/go7007/s2250-board.c
index 014d384..b397410 100644
--- a/drivers/staging/media/go7007/s2250-board.c
+++ b/drivers/staging/media/go7007/s2250-board.c
@@ -688,15 +688,4 @@ static struct i2c_driver s2250_driver = {
 	.id_table	= s2250_id,
 };
 
-static __init int init_s2250(void)
-{
-	return i2c_add_driver(&s2250_driver);
-}
-
-static __exit void exit_s2250(void)
-{
-	i2c_del_driver(&s2250_driver);
-}
-
-module_init(init_s2250);
-module_exit(exit_s2250);
+module_i2c_driver(s2250_driver);
diff --git a/drivers/staging/media/go7007/wis-ov7640.c b/drivers/staging/media/go7007/wis-ov7640.c
index 6bc9470..9f01657 100644
--- a/drivers/staging/media/go7007/wis-ov7640.c
+++ b/drivers/staging/media/go7007/wis-ov7640.c
@@ -29,8 +29,7 @@ struct wis_ov7640 {
 	int hue;
 };
 
-static u8 initial_registers[] =
-{
+static u8 initial_registers[] = {
 	0x12, 0x80,
 	0x12, 0x54,
 	0x14, 0x24,
@@ -60,12 +59,12 @@ static int wis_ov7640_probe(struct i2c_client *client,
 
 	client->flags = I2C_CLIENT_SCCB;
 
-	printk(KERN_DEBUG
+	dev_dbg(&client->dev,
 		"wis-ov7640: initializing OV7640 at address %d on %s\n",
 		client->addr, adapter->name);
 
 	if (write_regs(client, initial_registers) < 0) {
-		printk(KERN_ERR "wis-ov7640: error initializing OV7640\n");
+		dev_err(&client->dev, "wis-ov7640: error initializing OV7640\n");
 		return -ENODEV;
 	}
 
@@ -92,17 +91,6 @@ static struct i2c_driver wis_ov7640_driver = {
 	.id_table	= wis_ov7640_id,
 };
 
-static int __init wis_ov7640_init(void)
-{
-	return i2c_add_driver(&wis_ov7640_driver);
-}
-
-static void __exit wis_ov7640_cleanup(void)
-{
-	i2c_del_driver(&wis_ov7640_driver);
-}
-
-module_init(wis_ov7640_init);
-module_exit(wis_ov7640_cleanup);
+module_i2c_driver(wis_ov7640_driver);
 
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/go7007/wis-saa7113.c b/drivers/staging/media/go7007/wis-saa7113.c
index 05e0e10..8810c1e 100644
--- a/drivers/staging/media/go7007/wis-saa7113.c
+++ b/drivers/staging/media/go7007/wis-saa7113.c
@@ -32,8 +32,7 @@ struct wis_saa7113 {
 	int hue;
 };
 
-static u8 initial_registers[] =
-{
+static u8 initial_registers[] = {
 	0x01, 0x08,
 	0x02, 0xc0,
 	0x03, 0x33,
@@ -282,12 +281,12 @@ static int wis_saa7113_probe(struct i2c_client *client,
 	dec->hue = 0;
 	i2c_set_clientdata(client, dec);
 
-	printk(KERN_DEBUG
+	dev_dbg(&client->dev,
 		"wis-saa7113: initializing SAA7113 at address %d on %s\n",
 		client->addr, adapter->name);
 
 	if (write_regs(client, initial_registers) < 0) {
-		printk(KERN_ERR
+		dev_err(&client->dev,
 			"wis-saa7113: error initializing SAA7113\n");
 		kfree(dec);
 		return -ENODEV;
@@ -320,17 +319,6 @@ static struct i2c_driver wis_saa7113_driver = {
 	.id_table	= wis_saa7113_id,
 };
 
-static int __init wis_saa7113_init(void)
-{
-	return i2c_add_driver(&wis_saa7113_driver);
-}
-
-static void __exit wis_saa7113_cleanup(void)
-{
-	i2c_del_driver(&wis_saa7113_driver);
-}
-
-module_init(wis_saa7113_init);
-module_exit(wis_saa7113_cleanup);
+module_i2c_driver(wis_saa7113_driver);
 
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/go7007/wis-saa7115.c b/drivers/staging/media/go7007/wis-saa7115.c
index 46cff59..fa86acd 100644
--- a/drivers/staging/media/go7007/wis-saa7115.c
+++ b/drivers/staging/media/go7007/wis-saa7115.c
@@ -32,8 +32,7 @@ struct wis_saa7115 {
 	int hue;
 };
 
-static u8 initial_registers[] =
-{
+static u8 initial_registers[] = {
 	0x01, 0x08,
 	0x02, 0xc0,
 	0x03, 0x20,
@@ -415,12 +414,12 @@ static int wis_saa7115_probe(struct i2c_client *client,
 	dec->hue = 0;
 	i2c_set_clientdata(client, dec);
 
-	printk(KERN_DEBUG
+	dev_dbg(&client->dev,
 		"wis-saa7115: initializing SAA7115 at address %d on %s\n",
 		client->addr, adapter->name);
 
 	if (write_regs(client, initial_registers) < 0) {
-		printk(KERN_ERR
+		dev_err(&client->dev,
 			"wis-saa7115: error initializing SAA7115\n");
 		kfree(dec);
 		return -ENODEV;
@@ -453,17 +452,6 @@ static struct i2c_driver wis_saa7115_driver = {
 	.id_table	= wis_saa7115_id,
 };
 
-static int __init wis_saa7115_init(void)
-{
-	return i2c_add_driver(&wis_saa7115_driver);
-}
-
-static void __exit wis_saa7115_cleanup(void)
-{
-	i2c_del_driver(&wis_saa7115_driver);
-}
-
-module_init(wis_saa7115_init);
-module_exit(wis_saa7115_cleanup);
+module_i2c_driver(wis_saa7115_driver);
 
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/go7007/wis-sony-tuner.c b/drivers/staging/media/go7007/wis-sony-tuner.c
index 8f1b7d4..1291ab7 100644
--- a/drivers/staging/media/go7007/wis-sony-tuner.c
+++ b/drivers/staging/media/go7007/wis-sony-tuner.c
@@ -704,17 +704,6 @@ static struct i2c_driver wis_sony_tuner_driver = {
 	.id_table	= wis_sony_tuner_id,
 };
 
-static int __init wis_sony_tuner_init(void)
-{
-	return i2c_add_driver(&wis_sony_tuner_driver);
-}
-
-static void __exit wis_sony_tuner_cleanup(void)
-{
-	i2c_del_driver(&wis_sony_tuner_driver);
-}
-
-module_init(wis_sony_tuner_init);
-module_exit(wis_sony_tuner_cleanup);
+module_i2c_driver(wis_sony_tuner_driver);
 
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/go7007/wis-tw2804.c b/drivers/staging/media/go7007/wis-tw2804.c
index 9134f03..d6410ee 100644
--- a/drivers/staging/media/go7007/wis-tw2804.c
+++ b/drivers/staging/media/go7007/wis-tw2804.c
@@ -341,17 +341,6 @@ static struct i2c_driver wis_tw2804_driver = {
 	.id_table	= wis_tw2804_id,
 };
 
-static int __init wis_tw2804_init(void)
-{
-	return i2c_add_driver(&wis_tw2804_driver);
-}
-
-static void __exit wis_tw2804_cleanup(void)
-{
-	i2c_del_driver(&wis_tw2804_driver);
-}
-
-module_init(wis_tw2804_init);
-module_exit(wis_tw2804_cleanup);
+module_i2c_driver(wis_tw2804_driver);
 
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/go7007/wis-tw9903.c b/drivers/staging/media/go7007/wis-tw9903.c
index 9230f4a..94071de 100644
--- a/drivers/staging/media/go7007/wis-tw9903.c
+++ b/drivers/staging/media/go7007/wis-tw9903.c
@@ -325,17 +325,6 @@ static struct i2c_driver wis_tw9903_driver = {
 	.id_table	= wis_tw9903_id,
 };
 
-static int __init wis_tw9903_init(void)
-{
-	return i2c_add_driver(&wis_tw9903_driver);
-}
-
-static void __exit wis_tw9903_cleanup(void)
-{
-	i2c_del_driver(&wis_tw9903_driver);
-}
-
-module_init(wis_tw9903_init);
-module_exit(wis_tw9903_cleanup);
+module_i2c_driver(wis_tw9903_driver);
 
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/go7007/wis-uda1342.c b/drivers/staging/media/go7007/wis-uda1342.c
index 0127be2..05ac798 100644
--- a/drivers/staging/media/go7007/wis-uda1342.c
+++ b/drivers/staging/media/go7007/wis-uda1342.c
@@ -98,17 +98,6 @@ static struct i2c_driver wis_uda1342_driver = {
 	.id_table	= wis_uda1342_id,
 };
 
-static int __init wis_uda1342_init(void)
-{
-	return i2c_add_driver(&wis_uda1342_driver);
-}
-
-static void __exit wis_uda1342_cleanup(void)
-{
-	i2c_del_driver(&wis_uda1342_driver);
-}
-
-module_init(wis_uda1342_init);
-module_exit(wis_uda1342_cleanup);
+module_i2c_driver(wis_uda1342_driver);
 
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c
index dd2bca7..ec14bc8 100644
--- a/drivers/staging/media/lirc/lirc_parallel.c
+++ b/drivers/staging/media/lirc/lirc_parallel.c
@@ -583,12 +583,12 @@ static struct lirc_driver driver = {
 
 static struct platform_device *lirc_parallel_dev;
 
-static int __devinit lirc_parallel_probe(struct platform_device *dev)
+static int lirc_parallel_probe(struct platform_device *dev)
 {
 	return 0;
 }
 
-static int __devexit lirc_parallel_remove(struct platform_device *dev)
+static int lirc_parallel_remove(struct platform_device *dev)
 {
 	return 0;
 }
@@ -606,7 +606,7 @@ static int lirc_parallel_resume(struct platform_device *dev)
 
 static struct platform_driver lirc_parallel_driver = {
 	.probe	= lirc_parallel_probe,
-	.remove	= __devexit_p(lirc_parallel_remove),
+	.remove	= lirc_parallel_remove,
 	.suspend	= lirc_parallel_suspend,
 	.resume	= lirc_parallel_resume,
 	.driver	= {
diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c
index 97ef670..b5d0088 100644
--- a/drivers/staging/media/lirc/lirc_serial.c
+++ b/drivers/staging/media/lirc/lirc_serial.c
@@ -841,7 +841,7 @@ static int hardware_init_port(void)
 	return 0;
 }
 
-static int __devinit lirc_serial_probe(struct platform_device *dev)
+static int lirc_serial_probe(struct platform_device *dev)
 {
 	int i, nlow, nhigh, result;
 
@@ -927,7 +927,7 @@ exit_free_irq:
 	return result;
 }
 
-static int __devexit lirc_serial_remove(struct platform_device *dev)
+static int lirc_serial_remove(struct platform_device *dev)
 {
 	free_irq(irq, (void *)&hardware);
 
@@ -1148,7 +1148,7 @@ static int lirc_serial_resume(struct platform_device *dev)
 
 static struct platform_driver lirc_serial_driver = {
 	.probe		= lirc_serial_probe,
-	.remove		= __devexit_p(lirc_serial_remove),
+	.remove		= lirc_serial_remove,
 	.suspend	= lirc_serial_suspend,
 	.resume		= lirc_serial_resume,
 	.driver		= {
@@ -1239,6 +1239,10 @@ static int __init lirc_serial_init_module(void)
 		}
 	}
 
+	/* make sure sense is either -1, 0, or 1 */
+	if (sense != -1)
+		sense = !!sense;
+
 	result = lirc_serial_init();
 	if (result)
 		return result;
@@ -1298,7 +1302,7 @@ MODULE_PARM_DESC(irq, "Interrupt (4 or 3)");
 module_param(share_irq, bool, S_IRUGO);
 MODULE_PARM_DESC(share_irq, "Share interrupts (0 = off, 1 = on)");
 
-module_param(sense, bool, S_IRUGO);
+module_param(sense, int, S_IRUGO);
 MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit"
 		 " (0 = active high, 1 = active low )");
 
diff --git a/drivers/staging/media/lirc/lirc_sir.c b/drivers/staging/media/lirc/lirc_sir.c
index 4afc3b4..a457998 100644
--- a/drivers/staging/media/lirc/lirc_sir.c
+++ b/drivers/staging/media/lirc/lirc_sir.c
@@ -1218,19 +1218,19 @@ static int init_lirc_sir(void)
 	return 0;
 }
 
-static int __devinit lirc_sir_probe(struct platform_device *dev)
+static int lirc_sir_probe(struct platform_device *dev)
 {
 	return 0;
 }
 
-static int __devexit lirc_sir_remove(struct platform_device *dev)
+static int lirc_sir_remove(struct platform_device *dev)
 {
 	return 0;
 }
 
 static struct platform_driver lirc_sir_driver = {
 	.probe		= lirc_sir_probe,
-	.remove		= __devexit_p(lirc_sir_remove),
+	.remove		= lirc_sir_remove,
 	.driver		= {
 		.name	= "lirc_sir",
 		.owner	= THIS_MODULE,
diff --git a/drivers/staging/media/solo6x10/core.c b/drivers/staging/media/solo6x10/core.c
index 3ee9b12..fd83d6d 100644
--- a/drivers/staging/media/solo6x10/core.c
+++ b/drivers/staging/media/solo6x10/core.c
@@ -129,7 +129,7 @@ static void free_solo_dev(struct solo_dev *solo_dev)
 	kfree(solo_dev);
 }
 
-static int __devinit solo_pci_probe(struct pci_dev *pdev,
+static int solo_pci_probe(struct pci_dev *pdev,
 				    const struct pci_device_id *id)
 {
 	struct solo_dev *solo_dev;
@@ -284,7 +284,7 @@ fail_probe:
 	return ret;
 }
 
-static void __devexit solo_pci_remove(struct pci_dev *pdev)
+static void solo_pci_remove(struct pci_dev *pdev)
 {
 	struct solo_dev *solo_dev = pci_get_drvdata(pdev);
 
diff --git a/drivers/staging/net/pc300_drv.c b/drivers/staging/net/pc300_drv.c
index cb0f8d9..7281797 100644
--- a/drivers/staging/net/pc300_drv.c
+++ b/drivers/staging/net/pc300_drv.c
@@ -3409,7 +3409,7 @@ static void cpc_init_card(pc300_t * card)
 	board_nbr++;
 }
 
-static int __devinit
+static int
 cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	int err, eeprom_outdated = 0;
@@ -3607,7 +3607,7 @@ err_disable_dev:
 	return err;
 }
 
-static void __devexit cpc_remove_one(struct pci_dev *pdev)
+static void cpc_remove_one(struct pci_dev *pdev)
 {
 	pc300_t *card = pci_get_drvdata(pdev);
 
@@ -3646,7 +3646,7 @@ static struct pci_driver cpc_driver = {
 	.name           = "pc300",
 	.id_table       = cpc_pci_dev_id,
 	.probe          = cpc_init_one,
-	.remove         = __devexit_p(cpc_remove_one),
+	.remove         = cpc_remove_one,
 };
 
 static int __init cpc_init(void)
diff --git a/drivers/staging/nvec/Kconfig b/drivers/staging/nvec/Kconfig
index 1235a78..f779fdc 100644
--- a/drivers/staging/nvec/Kconfig
+++ b/drivers/staging/nvec/Kconfig
@@ -1,6 +1,7 @@
 config MFD_NVEC
 	bool "NV Tegra Embedded Controller SMBus Interface"
 	depends on I2C && GPIOLIB && ARCH_TEGRA
+	select MFD_CORE
 	help
 	    Say Y here to enable support for a nVidia compliant embedded
 	    controller.
diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index 094fdc3..2830946 100644
--- a/drivers/staging/nvec/nvec.c
+++ b/drivers/staging/nvec/nvec.c
@@ -39,7 +39,6 @@
 #include <linux/workqueue.h>
 
 #include <mach/clk.h>
-#include <mach/iomap.h>
 
 #include "nvec.h"
 
@@ -716,7 +715,7 @@ static void nvec_power_off(void)
 	nvec_write_async(nvec_power_handle, "\x04\x01", 2);
 }
 
-static int __devinit tegra_nvec_probe(struct platform_device *pdev)
+static int tegra_nvec_probe(struct platform_device *pdev)
 {
 	int err, ret;
 	struct clk *i2c_clk;
@@ -853,7 +852,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit tegra_nvec_remove(struct platform_device *pdev)
+static int tegra_nvec_remove(struct platform_device *pdev)
 {
 	struct nvec_chip *nvec = platform_get_drvdata(pdev);
 
@@ -901,7 +900,7 @@ static int nvec_resume(struct device *dev)
 static const SIMPLE_DEV_PM_OPS(nvec_pm_ops, nvec_suspend, nvec_resume);
 
 /* Match table for of_platform binding */
-static const struct of_device_id nvidia_nvec_of_match[] __devinitconst = {
+static const struct of_device_id nvidia_nvec_of_match[] = {
 	{ .compatible = "nvidia,nvec", },
 	{},
 };
@@ -909,7 +908,7 @@ MODULE_DEVICE_TABLE(of, nvidia_nvec_of_match);
 
 static struct platform_driver nvec_device_driver = {
 	.probe   = tegra_nvec_probe,
-	.remove  = __devexit_p(tegra_nvec_remove),
+	.remove  = tegra_nvec_remove,
 	.driver  = {
 		.name = "nvec",
 		.owner = THIS_MODULE,
diff --git a/drivers/staging/nvec/nvec_kbd.c b/drivers/staging/nvec/nvec_kbd.c
index 6cc30dc..7cb149b 100644
--- a/drivers/staging/nvec/nvec_kbd.c
+++ b/drivers/staging/nvec/nvec_kbd.c
@@ -100,7 +100,7 @@ static int nvec_kbd_event(struct input_dev *dev, unsigned int type,
 	return 0;
 }
 
-static int __devinit nvec_kbd_probe(struct platform_device *pdev)
+static int nvec_kbd_probe(struct platform_device *pdev)
 {
 	struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
 	int i, j, err;
@@ -159,7 +159,7 @@ fail:
 	return err;
 }
 
-static int __devexit nvec_kbd_remove(struct platform_device *pdev)
+static int nvec_kbd_remove(struct platform_device *pdev)
 {
 	input_unregister_device(keys_dev.input);
 	input_free_device(keys_dev.input);
@@ -169,7 +169,7 @@ static int __devexit nvec_kbd_remove(struct platform_device *pdev)
 
 static struct platform_driver nvec_kbd_driver = {
 	.probe  = nvec_kbd_probe,
-	.remove = __devexit_p(nvec_kbd_remove),
+	.remove = nvec_kbd_remove,
 	.driver = {
 		.name = "nvec-kbd",
 		.owner = THIS_MODULE,
diff --git a/drivers/staging/nvec/nvec_paz00.c b/drivers/staging/nvec/nvec_paz00.c
index b747e39..934b796 100644
--- a/drivers/staging/nvec/nvec_paz00.c
+++ b/drivers/staging/nvec/nvec_paz00.c
@@ -43,7 +43,7 @@ static void nvec_led_brightness_set(struct led_classdev *led_cdev,
 
 }
 
-static int __devinit nvec_paz00_probe(struct platform_device *pdev)
+static int nvec_paz00_probe(struct platform_device *pdev)
 {
 	struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
 	struct nvec_led *led;
@@ -72,7 +72,7 @@ static int __devinit nvec_paz00_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit nvec_paz00_remove(struct platform_device *pdev)
+static int nvec_paz00_remove(struct platform_device *pdev)
 {
 	struct nvec_led *led = platform_get_drvdata(pdev);
 
@@ -83,7 +83,7 @@ static int __devexit nvec_paz00_remove(struct platform_device *pdev)
 
 static struct platform_driver nvec_paz00_driver = {
 	.probe  = nvec_paz00_probe,
-	.remove = __devexit_p(nvec_paz00_remove),
+	.remove = nvec_paz00_remove,
 	.driver = {
 		.name  = "nvec-paz00",
 		.owner = THIS_MODULE,
diff --git a/drivers/staging/nvec/nvec_power.c b/drivers/staging/nvec/nvec_power.c
index cc8ccd7..b7b6d54 100644
--- a/drivers/staging/nvec/nvec_power.c
+++ b/drivers/staging/nvec/nvec_power.c
@@ -368,7 +368,7 @@ static void nvec_power_poll(struct work_struct *work)
 	schedule_delayed_work(to_delayed_work(work), msecs_to_jiffies(5000));
 };
 
-static int __devinit nvec_power_probe(struct platform_device *pdev)
+static int nvec_power_probe(struct platform_device *pdev)
 {
 	struct power_supply *psy;
 	struct nvec_power *power;
@@ -407,7 +407,7 @@ static int __devinit nvec_power_probe(struct platform_device *pdev)
 	return power_supply_register(&pdev->dev, psy);
 }
 
-static int __devexit nvec_power_remove(struct platform_device *pdev)
+static int nvec_power_remove(struct platform_device *pdev)
 {
 	struct nvec_power *power = platform_get_drvdata(pdev);
 
@@ -425,7 +425,7 @@ static int __devexit nvec_power_remove(struct platform_device *pdev)
 
 static struct platform_driver nvec_power_driver = {
 	.probe = nvec_power_probe,
-	.remove = __devexit_p(nvec_power_remove),
+	.remove = nvec_power_remove,
 	.driver = {
 		   .name = "nvec-power",
 		   .owner = THIS_MODULE,
diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c
index d7c6511..88dd288 100644
--- a/drivers/staging/nvec/nvec_ps2.c
+++ b/drivers/staging/nvec/nvec_ps2.c
@@ -93,7 +93,7 @@ static int nvec_ps2_notifier(struct notifier_block *nb,
 	return NOTIFY_DONE;
 }
 
-static int __devinit nvec_mouse_probe(struct platform_device *pdev)
+static int nvec_mouse_probe(struct platform_device *pdev)
 {
 	struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
 	struct serio *ser_dev;
@@ -123,7 +123,7 @@ static int __devinit nvec_mouse_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit nvec_mouse_remove(struct platform_device *pdev)
+static int nvec_mouse_remove(struct platform_device *pdev)
 {
 	serio_unregister_port(ps2_dev.ser_dev);
 
@@ -164,7 +164,7 @@ static const SIMPLE_DEV_PM_OPS(nvec_mouse_pm_ops, nvec_mouse_suspend,
 
 static struct platform_driver nvec_mouse_driver = {
 	.probe  = nvec_mouse_probe,
-	.remove = __devexit_p(nvec_mouse_remove),
+	.remove = nvec_mouse_remove,
 	.driver = {
 		.name = "nvec-mouse",
 		.owner = THIS_MODULE,
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index 683bedc..ef32dc1 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -169,7 +169,7 @@ static void cvm_oct_periodic_worker(struct work_struct *work)
 		queue_delayed_work(cvm_oct_poll_queue, &priv->port_periodic_work, HZ);
  }
 
-static __devinit void cvm_oct_configure_common_hw(void)
+static void cvm_oct_configure_common_hw(void)
 {
 	/* Setup the FPA */
 	cvmx_fpa_enable();
@@ -586,7 +586,7 @@ static const struct net_device_ops cvm_oct_pow_netdev_ops = {
 
 extern void octeon_mdiobus_force_mod_depencency(void);
 
-static struct device_node * __devinit cvm_oct_of_get_child(const struct device_node *parent,
+static struct device_node *cvm_oct_of_get_child(const struct device_node *parent,
 							   int reg_val)
 {
 	struct device_node *node = NULL;
@@ -604,7 +604,7 @@ static struct device_node * __devinit cvm_oct_of_get_child(const struct device_n
 	return node;
 }
 
-static struct device_node * __devinit cvm_oct_node_for_port(struct device_node *pip,
+static struct device_node *cvm_oct_node_for_port(struct device_node *pip,
 							    int interface, int port)
 {
 	struct device_node *ni, *np;
@@ -619,7 +619,7 @@ static struct device_node * __devinit cvm_oct_node_for_port(struct device_node *
 	return np;
 }
 
-static int __devinit cvm_oct_probe(struct platform_device *pdev)
+static int cvm_oct_probe(struct platform_device *pdev)
 {
 	int num_interfaces;
 	int interface;
@@ -813,7 +813,7 @@ static int __devinit cvm_oct_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit cvm_oct_remove(struct platform_device *pdev)
+static int cvm_oct_remove(struct platform_device *pdev)
 {
 	int port;
 
@@ -874,7 +874,7 @@ MODULE_DEVICE_TABLE(of, cvm_oct_match);
 
 static struct platform_driver cvm_oct_driver = {
 	.probe		= cvm_oct_probe,
-	.remove		= __devexit_p(cvm_oct_remove),
+	.remove		= cvm_oct_remove,
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= KBUILD_MODNAME,
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c
index d49c32a..54ed6f6 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon.c
@@ -39,10 +39,6 @@
 static ushort resumeline = 898;
 module_param(resumeline, ushort, 0444);
 
-/* Default off since it doesn't work on DCON ASIC in B-test OLPC board */
-static int useaa = 1;
-module_param(useaa, int, 0444);
-
 static struct dcon_platform_data *pdata;
 
 /* I2C structures */
@@ -50,8 +46,6 @@ static struct dcon_platform_data *pdata;
 /* Platform devices */
 static struct platform_device *dcon_device;
 
-static DECLARE_WAIT_QUEUE_HEAD(dcon_wait_queue);
-
 static unsigned short normal_i2c[] = { 0x0d, I2C_CLIENT_END };
 
 static s32 dcon_write(struct dcon_priv *dcon, u8 reg, u16 val)
@@ -103,9 +97,7 @@ static int dcon_hw_init(struct dcon_priv *dcon, int is_init)
 	/* Colour swizzle, AA, no passthrough, backlight */
 	if (is_init) {
 		dcon->disp_mode = MODE_PASSTHRU | MODE_BL_ENABLE |
-				MODE_CSWIZZLE;
-		if (useaa)
-			dcon->disp_mode |= MODE_COL_AA;
+				MODE_CSWIZZLE | MODE_COL_AA;
 	}
 	dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
 
@@ -191,9 +183,7 @@ static int dcon_set_mono_mode(struct dcon_priv *dcon, bool enable_mono)
 		dcon->disp_mode |= MODE_MONO_LUMA;
 	} else {
 		dcon->disp_mode &= ~(MODE_MONO_LUMA);
-		dcon->disp_mode |= MODE_CSWIZZLE;
-		if (useaa)
-			dcon->disp_mode |= MODE_COL_AA;
+		dcon->disp_mode |= MODE_CSWIZZLE | MODE_COL_AA;
 	}
 
 	dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
@@ -288,7 +278,6 @@ static void dcon_source_switch(struct work_struct *work)
 {
 	struct dcon_priv *dcon = container_of(work, struct dcon_priv,
 			switch_source);
-	DECLARE_WAITQUEUE(wait, current);
 	int source = dcon->pending_src;
 
 	if (dcon->curr_src == source)
@@ -305,11 +294,9 @@ static void dcon_source_switch(struct work_struct *work)
 		if (dcon_write(dcon, DCON_REG_MODE,
 				dcon->disp_mode | MODE_SCAN_INT))
 			pr_err("couldn't enable scanline interrupt!\n");
-		else {
+		else
 			/* Wait up to one second for the scanline interrupt */
-			wait_event_timeout(dcon_wait_queue,
-					   dcon->switched == true, HZ);
-		}
+			wait_event_timeout(dcon->waitq, dcon->switched, HZ);
 
 		if (!dcon->switched)
 			pr_err("Timeout entering CPU mode; expect a screen glitch.\n");
@@ -340,21 +327,15 @@ static void dcon_source_switch(struct work_struct *work)
 		break;
 	case DCON_SOURCE_DCON:
 	{
-		int t;
 		struct timespec delta_t;
 
 		pr_info("dcon_source_switch to DCON\n");
 
-		add_wait_queue(&dcon_wait_queue, &wait);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-
 		/* Clear DCONLOAD - this implies that the DCON is in control */
 		pdata->set_dconload(0);
 		getnstimeofday(&dcon->load_time);
 
-		t = schedule_timeout(HZ/2);
-		remove_wait_queue(&dcon_wait_queue, &wait);
-		set_current_state(TASK_RUNNING);
+		wait_event_timeout(dcon->waitq, dcon->switched, HZ/2);
 
 		if (!dcon->switched) {
 			pr_err("Timeout entering DCON mode; expect a screen glitch.\n");
@@ -539,6 +520,10 @@ static int dcon_bl_update(struct backlight_device *dev)
 	if (level != dcon->bl_val)
 		dcon_set_backlight(dcon, level);
 
+	/* power down the DCON when the screen is blanked */
+	if (!dcon->ignore_fb_events)
+		dcon_sleep(dcon, !!(dev->props.state & BL_CORE_FBBLANK));
+
 	return 0;
 }
 
@@ -584,24 +569,6 @@ static struct notifier_block dcon_panic_nb = {
 	.notifier_call = unfreeze_on_panic,
 };
 
-/*
- * When the framebuffer sleeps due to external sources (e.g. user idle), power
- * down the DCON as well.  Power it back up when the fb comes back to life.
- */
-static int dcon_fb_notifier(struct notifier_block *self,
-				unsigned long event, void *data)
-{
-	struct fb_event *evdata = data;
-	struct dcon_priv *dcon = container_of(self, struct dcon_priv,
-			fbevent_nb);
-	int *blank = (int *)evdata->data;
-	if (((event != FB_EVENT_BLANK) && (event != FB_EVENT_CONBLANK)) ||
-			dcon->ignore_fb_events)
-		return 0;
-	dcon_sleep(dcon, *blank ? true : false);
-	return 0;
-}
-
 static int dcon_detect(struct i2c_client *client, struct i2c_board_info *info)
 {
 	strlcpy(info->type, "olpc_dcon", I2C_NAME_SIZE);
@@ -622,10 +589,10 @@ static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		return -ENOMEM;
 
 	dcon->client = client;
+	init_waitqueue_head(&dcon->waitq);
 	INIT_WORK(&dcon->switch_source, dcon_source_switch);
 	dcon->reboot_nb.notifier_call = dcon_reboot_notify;
 	dcon->reboot_nb.priority = -1;
-	dcon->fbevent_nb.notifier_call = dcon_fb_notifier;
 
 	i2c_set_clientdata(client, dcon);
 
@@ -680,7 +647,6 @@ static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 	register_reboot_notifier(&dcon->reboot_nb);
 	atomic_notifier_chain_register(&panic_notifier_list, &dcon_panic_nb);
-	fb_register_client(&dcon->fbevent_nb);
 
 	return 0;
 
@@ -701,7 +667,6 @@ static int dcon_remove(struct i2c_client *client)
 {
 	struct dcon_priv *dcon = i2c_get_clientdata(client);
 
-	fb_unregister_client(&dcon->fbevent_nb);
 	unregister_reboot_notifier(&dcon->reboot_nb);
 	atomic_notifier_chain_unregister(&panic_notifier_list, &dcon_panic_nb);
 
@@ -720,8 +685,9 @@ static int dcon_remove(struct i2c_client *client)
 }
 
 #ifdef CONFIG_PM
-static int dcon_suspend(struct i2c_client *client, pm_message_t state)
+static int dcon_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct dcon_priv *dcon = i2c_get_clientdata(client);
 
 	if (!dcon->asleep) {
@@ -732,8 +698,9 @@ static int dcon_suspend(struct i2c_client *client, pm_message_t state)
 	return 0;
 }
 
-static int dcon_resume(struct i2c_client *client)
+static int dcon_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct dcon_priv *dcon = i2c_get_clientdata(client);
 
 	if (!dcon->asleep) {
@@ -744,7 +711,12 @@ static int dcon_resume(struct i2c_client *client)
 	return 0;
 }
 
-#endif
+#else
+
+#define dcon_suspend NULL
+#define dcon_resume NULL
+
+#endif /* CONFIG_PM */
 
 
 irqreturn_t dcon_interrupt(int irq, void *id)
@@ -764,7 +736,7 @@ irqreturn_t dcon_interrupt(int irq, void *id)
 	case 1: /* switch to CPU mode */
 		dcon->switched = true;
 		getnstimeofday(&dcon->irq_time);
-		wake_up(&dcon_wait_queue);
+		wake_up(&dcon->waitq);
 		break;
 
 	case 0:
@@ -778,7 +750,7 @@ irqreturn_t dcon_interrupt(int irq, void *id)
 		if (dcon->curr_src != dcon->pending_src && !dcon->switched) {
 			dcon->switched = true;
 			getnstimeofday(&dcon->irq_time);
-			wake_up(&dcon_wait_queue);
+			wake_up(&dcon->waitq);
 			pr_debug("switching w/ status 0/0\n");
 		} else {
 			pr_debug("scanline interrupt w/CPU\n");
@@ -788,27 +760,28 @@ irqreturn_t dcon_interrupt(int irq, void *id)
 	return IRQ_HANDLED;
 }
 
+static const struct dev_pm_ops dcon_pm_ops = {
+	.suspend = dcon_suspend,
+	.resume = dcon_resume,
+};
+
 static const struct i2c_device_id dcon_idtable[] = {
 	{ "olpc_dcon",  0 },
 	{ }
 };
-
 MODULE_DEVICE_TABLE(i2c, dcon_idtable);
 
 struct i2c_driver dcon_driver = {
 	.driver = {
 		.name	= "olpc_dcon",
+		.pm = &dcon_pm_ops,
 	},
 	.class = I2C_CLASS_DDC | I2C_CLASS_HWMON,
 	.id_table = dcon_idtable,
 	.probe = dcon_probe,
-	.remove = __devexit_p(dcon_remove),
+	.remove = dcon_remove,
 	.detect = dcon_detect,
 	.address_list = normal_i2c,
-#ifdef CONFIG_PM
-	.suspend = dcon_suspend,
-	.resume = dcon_resume,
-#endif
 };
 
 static int __init olpc_dcon_init(void)
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.h b/drivers/staging/olpc_dcon/olpc_dcon.h
index 167a417..997bded 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.h
+++ b/drivers/staging/olpc_dcon/olpc_dcon.h
@@ -52,9 +52,9 @@ struct dcon_priv {
 	struct fb_info *fbinfo;
 	struct backlight_device *bl_dev;
 
+	wait_queue_head_t waitq;
 	struct work_struct switch_source;
 	struct notifier_block reboot_nb;
-	struct notifier_block fbevent_nb;
 
 	/* Shadow register for the DCON_REG_MODE register */
 	u8 disp_mode;
diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c
index 352dd3d..6a4d379 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c
@@ -10,7 +10,6 @@
 
 #include <linux/acpi.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
 #include <linux/gpio.h>
 #include <asm/olpc.h>
 
@@ -62,33 +61,6 @@ static int dcon_was_irq(void)
 static int dcon_init_xo_1_5(struct dcon_priv *dcon)
 {
 	unsigned int irq;
-	u_int8_t tmp;
-	struct pci_dev *pdev;
-
-	pdev = pci_get_device(PCI_VENDOR_ID_VIA,
-			      PCI_DEVICE_ID_VIA_VX855, NULL);
-	if (!pdev) {
-		pr_err("cannot find VX855 PCI ID\n");
-		return 1;
-	}
-
-	pci_read_config_byte(pdev, 0x95, &tmp);
-	pci_write_config_byte(pdev, 0x95, tmp|0x0c);
-
-	/* Set GPIO8 to GPIO mode, not SSPICLK */
-	pci_read_config_byte(pdev, 0xe3, &tmp);
-	pci_write_config_byte(pdev, 0xe3, tmp | 0x04);
-
-	/* Set GPI10/GPI11 to GPI mode, not SSPISDI/SSPISS */
-	pci_read_config_byte(pdev, 0xe4, &tmp);
-	pci_write_config_byte(pdev, 0xe4, tmp|0x08);
-
-	/* clear PMU_RxE1[6] to select SCI on GPIO12 */
-	/* clear PMU_RxE0[6] to choose falling edge */
-	pci_read_config_byte(pdev, 0xe1, &tmp);
-	pci_write_config_byte(pdev, 0xe1, tmp & ~BIT_GPIO12);
-	pci_read_config_byte(pdev, 0xe0, &tmp);
-	pci_write_config_byte(pdev, 0xe0, tmp & ~BIT_GPIO12);
 
 	dcon_clear_irq();
 
@@ -101,8 +73,6 @@ static int dcon_init_xo_1_5(struct dcon_priv *dcon)
 			DCON_SOURCE_CPU : DCON_SOURCE_DCON;
 	dcon->pending_src = dcon->curr_src;
 
-	pci_dev_put(pdev);
-
 	/* we're sharing the IRQ with ACPI */
 	irq = acpi_gbl_FADT.sci_interrupt;
 	if (request_irq(irq, &dcon_interrupt, IRQF_SHARED, "DCON", dcon)) {
diff --git a/drivers/staging/omap-thermal/omap-bandgap.c b/drivers/staging/omap-thermal/omap-bandgap.c
index 368a2e1..8346e345 100644
--- a/drivers/staging/omap-thermal/omap-bandgap.c
+++ b/drivers/staging/omap-thermal/omap-bandgap.c
@@ -38,6 +38,7 @@
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 #include <linux/of_irq.h>
+#include <linux/io.h>
 
 #include "omap-bandgap.h"
 
@@ -112,6 +113,11 @@ static irqreturn_t talert_irq_handler(int irq, void *data)
 
 		omap_bandgap_writel(bg_ptr, ctrl, tsr->bgap_mask_ctrl);
 
+		dev_dbg(bg_ptr->dev,
+			"%s: IRQ from %s sensor: hotevent %d coldevent %d\n",
+			__func__, bg_ptr->conf->sensors[i].domain,
+			t_hot, t_cold);
+
 		/* read temperature */
 		temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
 		temp &= tsr->bgap_dtemp_mask;
@@ -843,7 +849,7 @@ static struct omap_bandgap *omap_bandgap_build(struct platform_device *pdev)
 }
 
 static
-int __devinit omap_bandgap_probe(struct platform_device *pdev)
+int omap_bandgap_probe(struct platform_device *pdev)
 {
 	struct omap_bandgap *bg_ptr;
 	int clk_rate, ret = 0, i;
@@ -992,7 +998,7 @@ free_irqs:
 }
 
 static
-int __devexit omap_bandgap_remove(struct platform_device *pdev)
+int omap_bandgap_remove(struct platform_device *pdev)
 {
 	struct omap_bandgap *bg_ptr = platform_get_drvdata(pdev);
 	int i;
@@ -1059,7 +1065,6 @@ static int omap_bandgap_save_ctxt(struct omap_bandgap *bg_ptr)
 static int omap_bandgap_restore_ctxt(struct omap_bandgap *bg_ptr)
 {
 	int i;
-	u32 temp = 0;
 
 	for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
 		struct temp_sensor_registers *tsr;
@@ -1072,41 +1077,27 @@ static int omap_bandgap_restore_ctxt(struct omap_bandgap *bg_ptr)
 		if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
 			val = omap_bandgap_readl(bg_ptr, tsr->bgap_counter);
 
-		if (val == 0) {
-			if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG))
-				omap_bandgap_writel(bg_ptr,
-					rval->tshut_threshold,
-						   tsr->tshut_threshold);
-			/* Force immediate temperature measurement and update
-			 * of the DTEMP field
-			 */
-			omap_bandgap_force_single_read(bg_ptr, i);
-
-			if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
-				omap_bandgap_writel(bg_ptr, rval->bg_counter,
-							   tsr->bgap_counter);
-			if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
-				omap_bandgap_writel(bg_ptr, rval->bg_mode_ctrl,
-							   tsr->bgap_mode_ctrl);
-			if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
-				omap_bandgap_writel(bg_ptr,
-							   rval->bg_threshold,
-							   tsr->bgap_threshold);
-				omap_bandgap_writel(bg_ptr, rval->bg_ctrl,
-							   tsr->bgap_mask_ctrl);
-			}
-		} else {
-			temp = omap_bandgap_readl(bg_ptr,
-						  tsr->temp_sensor_ctrl);
-			temp &= (tsr->bgap_dtemp_mask);
-			omap_bandgap_force_single_read(bg_ptr, i);
-			if (temp == 0 && OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
-				temp = omap_bandgap_readl(bg_ptr,
-							  tsr->bgap_mask_ctrl);
-				temp |= 1 << __ffs(tsr->mode_ctrl_mask);
-				omap_bandgap_writel(bg_ptr, temp,
-							   tsr->bgap_mask_ctrl);
-			}
+		if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG))
+			omap_bandgap_writel(bg_ptr,
+				rval->tshut_threshold,
+					   tsr->tshut_threshold);
+		/* Force immediate temperature measurement and update
+		 * of the DTEMP field
+		 */
+		omap_bandgap_force_single_read(bg_ptr, i);
+
+		if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
+			omap_bandgap_writel(bg_ptr, rval->bg_counter,
+						   tsr->bgap_counter);
+		if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
+			omap_bandgap_writel(bg_ptr, rval->bg_mode_ctrl,
+						   tsr->bgap_mode_ctrl);
+		if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
+			omap_bandgap_writel(bg_ptr,
+						   rval->bg_threshold,
+						   tsr->bgap_threshold);
+			omap_bandgap_writel(bg_ptr, rval->bg_ctrl,
+						   tsr->bgap_mask_ctrl);
 		}
 	}
 
diff --git a/drivers/staging/omap-thermal/omap-bandgap.h b/drivers/staging/omap-thermal/omap-bandgap.h
index 78aed75..2bb14bd 100644
--- a/drivers/staging/omap-thermal/omap-bandgap.h
+++ b/drivers/staging/omap-thermal/omap-bandgap.h
@@ -336,14 +336,6 @@ struct temp_sensor_regval {
 };
 
 /**
- * struct thermal_cooling_conf - description on how to cool a thermal zone
- * @freq_clip_count: size of freq_data
- */
-struct thermal_cooling_conf {
-	int freq_clip_count;
-};
-
-/**
  * struct omap_temp_sensor - bandgap temperature sensor platform data
  * @ts_data: pointer to struct with thresholds, limits of temperature sensor
  * @registers: pointer to the list of register offsets and bitfields
@@ -365,7 +357,6 @@ struct omap_temp_sensor {
 	struct temp_sensor_registers	*registers;
 	struct temp_sensor_regval	regval;
 	char				*domain;
-	struct thermal_cooling_conf	cooling_data;
 	/* for hotspot extrapolation */
 	const int			slope;
 	const int			constant;
diff --git a/drivers/staging/omap-thermal/omap-thermal-common.c b/drivers/staging/omap-thermal/omap-thermal-common.c
index 5c0c203b..61f1070 100644
--- a/drivers/staging/omap-thermal/omap-thermal-common.c
+++ b/drivers/staging/omap-thermal/omap-thermal-common.c
@@ -29,6 +29,7 @@
 #include <linux/workqueue.h>
 #include <linux/thermal.h>
 #include <linux/cpufreq.h>
+#include <linux/cpumask.h>
 #include <linux/cpu_cooling.h>
 
 #include "omap-thermal.h"
@@ -112,7 +113,7 @@ static int omap_thermal_bind(struct thermal_zone_device *thermal,
 			      struct thermal_cooling_device *cdev)
 {
 	struct omap_thermal_data *data = thermal->devdata;
-	int max, id;
+	int id;
 
 	if (IS_ERR_OR_NULL(data))
 		return -ENODEV;
@@ -122,7 +123,6 @@ static int omap_thermal_bind(struct thermal_zone_device *thermal,
 		return 0;
 
 	id = data->sensor_id;
-	max = data->bg_ptr->conf->sensors[id].cooling_data.freq_clip_count;
 
 	/* TODO: bind with min and max states */
 	/* Simple thing, two trips, one passive another critical */
@@ -256,12 +256,12 @@ static struct omap_thermal_data
 int omap_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id,
 			       char *domain)
 {
-	struct omap_thermal_pdata pdata;
+	struct omap_thermal_data *data;
 
 	data = omap_bandgap_get_sensor_data(bg_ptr, id);
 
 	if (!data)
-		data = omap_thermal_build_pdata(bg_ptr, id);
+		data = omap_thermal_build_data(bg_ptr, id);
 
 	if (!data)
 		return -EINVAL;
@@ -270,7 +270,7 @@ int omap_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id,
 	/* Create thermal zone */
 	data->omap_thermal = thermal_zone_device_register(domain,
 				OMAP_TRIP_NUMBER, 0, data, &omap_thermal_ops,
-				FAST_TEMP_MONITORING_RATE,
+				NULL, FAST_TEMP_MONITORING_RATE,
 				FAST_TEMP_MONITORING_RATE);
 	if (IS_ERR_OR_NULL(data->omap_thermal)) {
 		dev_err(bg_ptr->dev, "thermal zone device is NULL\n");
@@ -304,81 +304,24 @@ int omap_thermal_report_sensor_temperature(struct omap_bandgap *bg_ptr, int id)
 	return 0;
 }
 
-static int omap_thermal_build_cpufreq_clip(struct omap_bandgap *bg_ptr,
-					   struct freq_clip_table **tab_ptr,
-					   int *tab_size)
-{
-	struct cpufreq_frequency_table *freq_table;
-	struct freq_clip_table *tab;
-	int i, count = 0;
-
-	freq_table = cpufreq_frequency_get_table(0);
-	if (IS_ERR_OR_NULL(freq_table)) {
-		dev_err(bg_ptr->dev,
-			"%s: failed to get cpufreq table (%p)\n",
-			__func__, freq_table);
-		return -EINVAL;
-	}
-
-	for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
-		unsigned int freq = freq_table[i].frequency;
-		if (freq == CPUFREQ_ENTRY_INVALID)
-			continue;
-		count++;
-	}
-
-	tab = devm_kzalloc(bg_ptr->dev, sizeof(*tab) * count, GFP_KERNEL);
-	if (!tab) {
-		dev_err(bg_ptr->dev,
-			"%s: no memory available\n", __func__);
-		return -ENOMEM;
-	}
-
-	for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
-		unsigned int freq = freq_table[i].frequency;
-
-		if (freq == CPUFREQ_ENTRY_INVALID)
-			continue;
-
-		tab[count - i - 1].freq_clip_max = freq;
-		tab[count - i - 1].temp_level = OMAP_TRIP_HOT;
-		tab[count - i - 1].mask_val = cpumask_of(0);
-	}
-
-	*tab_ptr = tab;
-	*tab_size = count;
-
-	return 0;
-}
-
 int omap_thermal_register_cpu_cooling(struct omap_bandgap *bg_ptr, int id)
 {
 	struct omap_thermal_data *data;
-	struct freq_clip_table *tab_ptr;
-	int tab_size, ret;
 
 	data = omap_bandgap_get_sensor_data(bg_ptr, id);
 	if (!data)
-		data = omap_thermal_build_pdata(bg_ptr, id);
+		data = omap_thermal_build_data(bg_ptr, id);
 
 	if (!data)
 		return -EINVAL;
 
-	ret = omap_thermal_build_cpufreq_clip(bg_ptr, &tab_ptr, &tab_size);
-	if (ret < 0) {
-		dev_err(bg_ptr->dev,
-			"%s: failed to build cpufreq clip table\n", __func__);
-		return ret;
-	}
-
 	/* Register cooling device */
-	data->cool_dev = cpufreq_cooling_register(tab_ptr, tab_size);
+	data->cool_dev = cpufreq_cooling_register(cpu_present_mask);
 	if (IS_ERR_OR_NULL(data->cool_dev)) {
 		dev_err(bg_ptr->dev,
 			"Failed to register cpufreq cooling device\n");
 		return PTR_ERR(data->cool_dev);
 	}
-	bg_ptr->conf->sensors[id].cooling_data.freq_clip_count = tab_size;
 	omap_bandgap_set_sensor_data(bg_ptr, id, data);
 
 	return 0;
diff --git a/drivers/staging/omapdrm/Kconfig b/drivers/staging/omapdrm/Kconfig
index 81a7cba..b724a41 100644
--- a/drivers/staging/omapdrm/Kconfig
+++ b/drivers/staging/omapdrm/Kconfig
@@ -2,7 +2,7 @@
 config DRM_OMAP
 	tristate "OMAP DRM"
 	depends on DRM && !CONFIG_FB_OMAP2
-	depends on ARCH_OMAP2PLUS
+	depends on ARCH_OMAP2PLUS || ARCH_MULTIPLATFORM
 	select DRM_KMS_HELPER
 	select OMAP2_DSS
 	select FB_SYS_FILLRECT
diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c
index 38be186..91edb3f 100644
--- a/drivers/staging/omapdrm/omap_connector.c
+++ b/drivers/staging/omapdrm/omap_connector.c
@@ -146,11 +146,10 @@ enum drm_connector_status omap_connector_detect(
 	enum drm_connector_status ret;
 
 	if (dssdrv->detect) {
-		if (dssdrv->detect(dssdev)) {
+		if (dssdrv->detect(dssdev))
 			ret = connector_status_connected;
-		} else {
+		else
 			ret = connector_status_disconnected;
-		}
 	} else {
 		ret = connector_status_unknown;
 	}
@@ -383,9 +382,8 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
 	return connector;
 
 fail:
-	if (connector) {
+	if (connector)
 		omap_connector_destroy(connector);
-	}
 
 	return NULL;
 }
diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c
index 732f2ad..d87bd84 100644
--- a/drivers/staging/omapdrm/omap_crtc.c
+++ b/drivers/staging/omapdrm/omap_crtc.c
@@ -19,7 +19,7 @@
 
 #include "omap_drv.h"
 
-#include "drm_mode.h"
+#include <drm/drm_mode.h>
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
 
@@ -114,7 +114,7 @@ static void omap_crtc_load_lut(struct drm_crtc *crtc)
 
 static void vblank_cb(void *arg)
 {
-	static uint32_t sequence = 0;
+	static uint32_t sequence;
 	struct drm_crtc *crtc = arg;
 	struct drm_device *dev = crtc->dev;
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
@@ -263,8 +263,8 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 	return crtc;
 
 fail:
-	if (crtc) {
+	if (crtc)
 		omap_crtc_destroy(crtc);
-	}
+
 	return NULL;
 }
diff --git a/drivers/staging/omapdrm/omap_dmm_priv.h b/drivers/staging/omapdrm/omap_dmm_priv.h
index 08b22e9..273ec12 100644
--- a/drivers/staging/omapdrm/omap_dmm_priv.h
+++ b/drivers/staging/omapdrm/omap_dmm_priv.h
@@ -141,8 +141,7 @@ struct refill_engine {
 	/* only one trans per engine for now */
 	struct dmm_txn txn;
 
-	/* offset to lut associated with container */
-	u32 *lut_offset;
+	bool async;
 
 	wait_queue_head_t wait_for_refill;
 
@@ -161,10 +160,11 @@ struct dmm {
 	dma_addr_t refill_pa;
 
 	/* refill engines */
-	struct semaphore engine_sem;
+	wait_queue_head_t engine_queue;
 	struct list_head idle_head;
 	struct refill_engine *engines;
 	int num_engines;
+	atomic_t engine_counter;
 
 	/* container information */
 	int container_width;
@@ -176,9 +176,6 @@ struct dmm {
 	/* array of LUT - TCM containers */
 	struct tcm **tcm;
 
-	/* LUT table storage */
-	u32 *lut;
-
 	/* allocation list and lock */
 	struct list_head alloc_head;
 };
diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c
index 3ae3955..59bf438 100644
--- a/drivers/staging/omapdrm/omap_dmm_tiler.c
+++ b/drivers/staging/omapdrm/omap_dmm_tiler.c
@@ -29,7 +29,6 @@
 #include <linux/mm.h>
 #include <linux/time.h>
 #include <linux/list.h>
-#include <linux/semaphore.h>
 
 #include "omap_dmm_tiler.h"
 #include "omap_dmm_priv.h"
@@ -120,6 +119,18 @@ static int wait_status(struct refill_engine *engine, uint32_t wait_mask)
 	return 0;
 }
 
+static void release_engine(struct refill_engine *engine)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&list_lock, flags);
+	list_add(&engine->idle_node, &omap_dmm->idle_head);
+	spin_unlock_irqrestore(&list_lock, flags);
+
+	atomic_inc(&omap_dmm->engine_counter);
+	wake_up_interruptible(&omap_dmm->engine_queue);
+}
+
 static irqreturn_t omap_dmm_irq_handler(int irq, void *arg)
 {
 	struct dmm *dmm = arg;
@@ -130,9 +141,13 @@ static irqreturn_t omap_dmm_irq_handler(int irq, void *arg)
 	writel(status, dmm->base + DMM_PAT_IRQSTATUS);
 
 	for (i = 0; i < dmm->num_engines; i++) {
-		if (status & DMM_IRQSTAT_LST)
+		if (status & DMM_IRQSTAT_LST) {
 			wake_up_interruptible(&dmm->engines[i].wait_for_refill);
 
+			if (dmm->engines[i].async)
+				release_engine(&dmm->engines[i]);
+		}
+
 		status >>= 8;
 	}
 
@@ -146,17 +161,24 @@ static struct dmm_txn *dmm_txn_init(struct dmm *dmm, struct tcm *tcm)
 {
 	struct dmm_txn *txn = NULL;
 	struct refill_engine *engine = NULL;
+	int ret;
+	unsigned long flags;
 
-	down(&dmm->engine_sem);
+
+	/* wait until an engine is available */
+	ret = wait_event_interruptible(omap_dmm->engine_queue,
+		atomic_add_unless(&omap_dmm->engine_counter, -1, 0));
+	if (ret)
+		return ERR_PTR(ret);
 
 	/* grab an idle engine */
-	spin_lock(&list_lock);
+	spin_lock_irqsave(&list_lock, flags);
 	if (!list_empty(&dmm->idle_head)) {
 		engine = list_entry(dmm->idle_head.next, struct refill_engine,
 					idle_node);
 		list_del(&engine->idle_node);
 	}
-	spin_unlock(&list_lock);
+	spin_unlock_irqrestore(&list_lock, flags);
 
 	BUG_ON(!engine);
 
@@ -174,7 +196,7 @@ static struct dmm_txn *dmm_txn_init(struct dmm *dmm, struct tcm *tcm)
  * Add region to DMM transaction.  If pages or pages[i] is NULL, then the
  * corresponding slot is cleared (ie. dummy_pa is programmed)
  */
-static int dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
+static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
 		struct page **pages, uint32_t npages, uint32_t roll)
 {
 	dma_addr_t pat_pa = 0;
@@ -184,9 +206,6 @@ static int dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
 	int columns = (1 + area->x1 - area->x0);
 	int rows = (1 + area->y1 - area->y0);
 	int i = columns*rows;
-	u32 *lut = omap_dmm->lut + (engine->tcm->lut_id * omap_dmm->lut_width *
-			omap_dmm->lut_height) +
-			(area->y0 * omap_dmm->lut_width) + area->x0;
 
 	pat = alloc_dma(txn, sizeof(struct pat), &pat_pa);
 
@@ -209,13 +228,9 @@ static int dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
 			page_to_phys(pages[n]) : engine->dmm->dummy_pa;
 	}
 
-	/* fill in lut with new addresses */
-	for (i = 0; i < rows; i++, lut += omap_dmm->lut_width)
-		memcpy(lut, &data[i*columns], columns * sizeof(u32));
-
 	txn->last_pat = pat;
 
-	return 0;
+	return;
 }
 
 /**
@@ -245,6 +260,9 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait)
 		goto cleanup;
 	}
 
+	/* mark whether it is async to denote list management in IRQ handler */
+	engine->async = wait ? false : true;
+
 	/* kick reload */
 	writel(engine->refill_pa,
 		dmm->base + reg[PAT_DESCR][engine->id]);
@@ -259,11 +277,10 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait)
 	}
 
 cleanup:
-	spin_lock(&list_lock);
-	list_add(&engine->idle_node, &dmm->idle_head);
-	spin_unlock(&list_lock);
+	/* only place engine back on list if we are done with it */
+	if (ret || wait)
+		release_engine(engine);
 
-	up(&omap_dmm->engine_sem);
 	return ret;
 }
 
@@ -279,7 +296,7 @@ static int fill(struct tcm_area *area, struct page **pages,
 
 	txn = dmm_txn_init(omap_dmm, area->tcm);
 	if (IS_ERR_OR_NULL(txn))
-		return PTR_ERR(txn);
+		return -ENOMEM;
 
 	tcm_for_each_slice(slice, *area, area_s) {
 		struct pat_area p_area = {
@@ -287,16 +304,13 @@ static int fill(struct tcm_area *area, struct page **pages,
 				.x1 = slice.p1.x,  .y1 = slice.p1.y,
 		};
 
-		ret = dmm_txn_append(txn, &p_area, pages, npages, roll);
-		if (ret)
-			goto fail;
+		dmm_txn_append(txn, &p_area, pages, npages, roll);
 
 		roll += tcm_sizeof(slice);
 	}
 
 	ret = dmm_txn_commit(txn, wait);
 
-fail:
 	return ret;
 }
 
@@ -333,6 +347,7 @@ struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, uint16_t w,
 	struct tiler_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
 	u32 min_align = 128;
 	int ret;
+	unsigned long flags;
 
 	BUG_ON(!validfmt(fmt));
 
@@ -354,9 +369,9 @@ struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, uint16_t w,
 	}
 
 	/* add to allocation list */
-	spin_lock(&list_lock);
+	spin_lock_irqsave(&list_lock, flags);
 	list_add(&block->alloc_node, &omap_dmm->alloc_head);
-	spin_unlock(&list_lock);
+	spin_unlock_irqrestore(&list_lock, flags);
 
 	return block;
 }
@@ -365,6 +380,7 @@ struct tiler_block *tiler_reserve_1d(size_t size)
 {
 	struct tiler_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
 	int num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	unsigned long flags;
 
 	if (!block)
 		return ERR_PTR(-ENOMEM);
@@ -377,9 +393,9 @@ struct tiler_block *tiler_reserve_1d(size_t size)
 		return ERR_PTR(-ENOMEM);
 	}
 
-	spin_lock(&list_lock);
+	spin_lock_irqsave(&list_lock, flags);
 	list_add(&block->alloc_node, &omap_dmm->alloc_head);
-	spin_unlock(&list_lock);
+	spin_unlock_irqrestore(&list_lock, flags);
 
 	return block;
 }
@@ -388,13 +404,14 @@ struct tiler_block *tiler_reserve_1d(size_t size)
 int tiler_release(struct tiler_block *block)
 {
 	int ret = tcm_free(&block->area);
+	unsigned long flags;
 
 	if (block->area.tcm)
 		dev_err(omap_dmm->dev, "failed to release block\n");
 
-	spin_lock(&list_lock);
+	spin_lock_irqsave(&list_lock, flags);
 	list_del(&block->alloc_node);
-	spin_unlock(&list_lock);
+	spin_unlock_irqrestore(&list_lock, flags);
 
 	kfree(block);
 	return ret;
@@ -505,7 +522,7 @@ size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h)
 	return round_up(geom[fmt].cpp * w, PAGE_SIZE) * h;
 }
 
-bool dmm_is_initialized(void)
+bool dmm_is_available(void)
 {
 	return omap_dmm ? true : false;
 }
@@ -514,16 +531,17 @@ static int omap_dmm_remove(struct platform_device *dev)
 {
 	struct tiler_block *block, *_block;
 	int i;
+	unsigned long flags;
 
 	if (omap_dmm) {
 		/* free all area regions */
-		spin_lock(&list_lock);
+		spin_lock_irqsave(&list_lock, flags);
 		list_for_each_entry_safe(block, _block, &omap_dmm->alloc_head,
 					alloc_node) {
 			list_del(&block->alloc_node);
 			kfree(block);
 		}
-		spin_unlock(&list_lock);
+		spin_unlock_irqrestore(&list_lock, flags);
 
 		for (i = 0; i < omap_dmm->num_lut; i++)
 			if (omap_dmm->tcm && omap_dmm->tcm[i])
@@ -532,15 +550,13 @@ static int omap_dmm_remove(struct platform_device *dev)
 
 		kfree(omap_dmm->engines);
 		if (omap_dmm->refill_va)
-			dma_free_coherent(omap_dmm->dev,
+			dma_free_writecombine(omap_dmm->dev,
 				REFILL_BUFFER_SIZE * omap_dmm->num_engines,
 				omap_dmm->refill_va,
 				omap_dmm->refill_pa);
 		if (omap_dmm->dummy_page)
 			__free_page(omap_dmm->dummy_page);
 
-		vfree(omap_dmm->lut);
-
 		if (omap_dmm->irq > 0)
 			free_irq(omap_dmm->irq, omap_dmm);
 
@@ -556,7 +572,7 @@ static int omap_dmm_probe(struct platform_device *dev)
 {
 	int ret = -EFAULT, i;
 	struct tcm_area area = {0};
-	u32 hwinfo, pat_geom, lut_table_size;
+	u32 hwinfo, pat_geom;
 	struct resource *mem;
 
 	omap_dmm = kzalloc(sizeof(*omap_dmm), GFP_KERNEL);
@@ -569,6 +585,8 @@ static int omap_dmm_probe(struct platform_device *dev)
 	INIT_LIST_HEAD(&omap_dmm->alloc_head);
 	INIT_LIST_HEAD(&omap_dmm->idle_head);
 
+	init_waitqueue_head(&omap_dmm->engine_queue);
+
 	/* lookup hwmod data - base address and irq */
 	mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
 	if (!mem) {
@@ -597,6 +615,8 @@ static int omap_dmm_probe(struct platform_device *dev)
 	omap_dmm->container_width = 256;
 	omap_dmm->container_height = 128;
 
+	atomic_set(&omap_dmm->engine_counter, omap_dmm->num_engines);
+
 	/* read out actual LUT width and height */
 	pat_geom = readl(omap_dmm->base + DMM_PAT_GEOMETRY);
 	omap_dmm->lut_width = ((pat_geom >> 16) & 0xF) << 5;
@@ -628,16 +648,6 @@ static int omap_dmm_probe(struct platform_device *dev)
 	 */
 	writel(0x7e7e7e7e, omap_dmm->base + DMM_PAT_IRQENABLE_SET);
 
-	lut_table_size = omap_dmm->lut_width * omap_dmm->lut_height *
-			omap_dmm->num_lut;
-
-	omap_dmm->lut = vmalloc(lut_table_size * sizeof(*omap_dmm->lut));
-	if (!omap_dmm->lut) {
-		dev_err(&dev->dev, "could not allocate lut table\n");
-		ret = -ENOMEM;
-		goto fail;
-	}
-
 	omap_dmm->dummy_page = alloc_page(GFP_KERNEL | __GFP_DMA32);
 	if (!omap_dmm->dummy_page) {
 		dev_err(&dev->dev, "could not allocate dummy page\n");
@@ -652,7 +662,7 @@ static int omap_dmm_probe(struct platform_device *dev)
 	omap_dmm->dummy_pa = page_to_phys(omap_dmm->dummy_page);
 
 	/* alloc refill memory */
-	omap_dmm->refill_va = dma_alloc_coherent(&dev->dev,
+	omap_dmm->refill_va = dma_alloc_writecombine(&dev->dev,
 				REFILL_BUFFER_SIZE * omap_dmm->num_engines,
 				&omap_dmm->refill_pa, GFP_KERNEL);
 	if (!omap_dmm->refill_va) {
@@ -670,7 +680,6 @@ static int omap_dmm_probe(struct platform_device *dev)
 		goto fail;
 	}
 
-	sema_init(&omap_dmm->engine_sem, omap_dmm->num_engines);
 	for (i = 0; i < omap_dmm->num_engines; i++) {
 		omap_dmm->engines[i].id = i;
 		omap_dmm->engines[i].dmm = omap_dmm;
@@ -720,9 +729,6 @@ static int omap_dmm_probe(struct platform_device *dev)
 		.p1.y = omap_dmm->container_height - 1,
 	};
 
-	for (i = 0; i < lut_table_size; i++)
-		omap_dmm->lut[i] = omap_dmm->dummy_pa;
-
 	/* initialize all LUTs to dummy page entries */
 	for (i = 0; i < omap_dmm->num_lut; i++) {
 		area.tcm = omap_dmm->tcm[i];
diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.h b/drivers/staging/omapdrm/omap_dmm_tiler.h
index 740911d..4fdd61e 100644
--- a/drivers/staging/omapdrm/omap_dmm_tiler.h
+++ b/drivers/staging/omapdrm/omap_dmm_tiler.h
@@ -16,7 +16,6 @@
 #ifndef OMAP_DMM_TILER_H
 #define OMAP_DMM_TILER_H
 
-#include <plat/cpu.h>
 #include "omap_drv.h"
 #include "tcm.h"
 
@@ -107,7 +106,7 @@ uint32_t tiler_stride(enum tiler_fmt fmt, uint32_t orient);
 size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h);
 size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h);
 void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h);
-bool dmm_is_initialized(void);
+bool dmm_is_available(void);
 
 extern struct platform_driver omap_dmm_driver;
 
@@ -139,9 +138,4 @@ static inline bool validfmt(enum tiler_fmt fmt)
 	}
 }
 
-static inline int dmm_is_available(void)
-{
-	return cpu_is_omap44xx();
-}
-
 #endif
diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c
index ebdb0b6..d4823fd 100644
--- a/drivers/staging/omapdrm/omap_drv.c
+++ b/drivers/staging/omapdrm/omap_drv.c
@@ -30,8 +30,6 @@
 #define DRIVER_MINOR		0
 #define DRIVER_PATCHLEVEL	0
 
-struct drm_device *drm_device;
-
 static int num_crtc = CONFIG_DRM_OMAP_NUM_CRTCS;
 
 MODULE_PARM_DESC(num_crtc, "Number of overlays to use as CRTCs");
@@ -53,9 +51,8 @@ static void omap_fb_output_poll_changed(struct drm_device *dev)
 {
 	struct omap_drm_private *priv = dev->dev_private;
 	DBG("dev=%p", dev);
-	if (priv->fbdev) {
+	if (priv->fbdev)
 		drm_fb_helper_hotplug_event(priv->fbdev);
-	}
 }
 
 static const struct drm_mode_config_funcs omap_mode_config_funcs = {
@@ -87,9 +84,9 @@ static int omap_drm_notifier(struct notifier_block *nb,
 	case OMAP_DSS_HOTPLUG_DISCONNECT: {
 		struct drm_device *dev = drm_device;
 		DBG("hotplug event: evt=%d, dev=%p", evt, dev);
-		if (dev) {
+		if (dev)
 			drm_sysfs_hotplug_event(dev);
-		}
+
 		return NOTIFY_OK;
 	}
 	default:  /* don't care about other events for now */
@@ -213,9 +210,9 @@ static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl,
 			struct drm_encoder *encoder =
 				omap_connector_attached_encoder(
 						priv->connectors[*j]);
-			if (encoder) {
+			if (encoder)
 				mgr = omap_encoder_get_manager(encoder);
-			}
+
 		}
 		(*j)++;
 	}
@@ -234,9 +231,9 @@ static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl,
 			struct drm_encoder *encoder =
 				omap_connector_attached_encoder(
 						priv->connectors[idx]);
-			if (encoder) {
+			if (encoder)
 				mgr = omap_encoder_get_manager(encoder);
-			}
+
 		}
 		(*j)++;
 	}
@@ -355,9 +352,8 @@ static int omap_modeset_init(struct drm_device *dev)
 		 */
 		int max_overlays = min(omap_dss_get_num_overlays(), num_crtc);
 
-		for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
+		for (i = 0; i < omap_dss_get_num_overlay_managers(); i++)
 			create_encoder(dev, omap_dss_get_overlay_manager(i));
-		}
 
 		for_each_dss_dev(dssdev) {
 			create_connector(dev, dssdev);
@@ -419,13 +415,14 @@ static void omap_modeset_free(struct drm_device *dev)
 static int ioctl_get_param(struct drm_device *dev, void *data,
 		struct drm_file *file_priv)
 {
+	struct omap_drm_private *priv = dev->dev_private;
 	struct drm_omap_param *args = data;
 
 	DBG("%p: param=%llu", dev, args->param);
 
 	switch (args->param) {
 	case OMAP_PARAM_CHIPSET_ID:
-		args->value = GET_OMAP_TYPE;
+		args->value = priv->omaprev;
 		break;
 	default:
 		DBG("unknown parameter %lld", args->param);
@@ -469,15 +466,13 @@ static int ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
 	VERB("%p:%p: handle=%d, op=%x", dev, file_priv, args->handle, args->op);
 
 	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-	if (!obj) {
+	if (!obj)
 		return -ENOENT;
-	}
 
 	ret = omap_gem_op_sync(obj, args->op);
 
-	if (!ret) {
+	if (!ret)
 		ret = omap_gem_op_start(obj, args->op);
-	}
 
 	drm_gem_object_unreference_unlocked(obj);
 
@@ -494,16 +489,14 @@ static int ioctl_gem_cpu_fini(struct drm_device *dev, void *data,
 	VERB("%p:%p: handle=%d", dev, file_priv, args->handle);
 
 	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-	if (!obj) {
+	if (!obj)
 		return -ENOENT;
-	}
 
 	/* XXX flushy, flushy */
 	ret = 0;
 
-	if (!ret) {
+	if (!ret)
 		ret = omap_gem_op_finish(obj, args->op);
-	}
 
 	drm_gem_object_unreference_unlocked(obj);
 
@@ -520,9 +513,8 @@ static int ioctl_gem_info(struct drm_device *dev, void *data,
 	DBG("%p:%p: handle=%d", dev, file_priv, args->handle);
 
 	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-	if (!obj) {
+	if (!obj)
 		return -ENOENT;
-	}
 
 	args->size = omap_gem_mmap_size(obj);
 	args->offset = omap_gem_mmap_offset(obj);
@@ -557,19 +549,20 @@ struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
  */
 static int dev_load(struct drm_device *dev, unsigned long flags)
 {
+	struct omap_drm_platform_data *pdata = dev->dev->platform_data;
 	struct omap_drm_private *priv;
 	int ret;
 
 	DBG("load: dev=%p", dev);
 
-	drm_device = dev;
-
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv) {
 		dev_err(dev->dev, "could not allocate priv\n");
 		return -ENOMEM;
 	}
 
+	priv->omaprev = pdata->omaprev;
+
 	dev->dev_private = priv;
 
 	priv->wq = alloc_ordered_workqueue("omapdrm", 0);
@@ -595,9 +588,8 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
 	drm_kms_helper_poll_init(dev);
 
 	ret = drm_vblank_init(dev, priv->num_crtcs);
-	if (ret) {
+	if (ret)
 		dev_warn(dev->dev, "could not init vblank\n");
-	}
 
 	return 0;
 }
@@ -659,19 +651,22 @@ static void dev_lastclose(struct drm_device *dev)
 
 	DBG("lastclose: dev=%p", dev);
 
-	/* need to restore default rotation state.. not sure if there is
-	 * a cleaner way to restore properties to default state?  Maybe
-	 * a flag that properties should automatically be restored to
-	 * default state on lastclose?
-	 */
-	for (i = 0; i < priv->num_crtcs; i++) {
-		drm_object_property_set_value(&priv->crtcs[i]->base,
-				priv->rotation_prop, 0);
-	}
+	if (priv->rotation_prop) {
+		/* need to restore default rotation state.. not sure
+		 * if there is a cleaner way to restore properties to
+		 * default state?  Maybe a flag that properties should
+		 * automatically be restored to default state on
+		 * lastclose?
+		 */
+		for (i = 0; i < priv->num_crtcs; i++) {
+			drm_object_property_set_value(&priv->crtcs[i]->base,
+					priv->rotation_prop, 0);
+		}
 
-	for (i = 0; i < priv->num_planes; i++) {
-		drm_object_property_set_value(&priv->planes[i]->base,
-				priv->rotation_prop, 0);
+		for (i = 0; i < priv->num_planes; i++) {
+			drm_object_property_set_value(&priv->planes[i]->base,
+					priv->rotation_prop, 0);
+		}
 	}
 
 	ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev);
diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h
index 9dc72d1..1d4aea5 100644
--- a/drivers/staging/omapdrm/omap_drv.h
+++ b/drivers/staging/omapdrm/omap_drv.h
@@ -40,6 +40,8 @@
 #define MAX_MAPPERS 2
 
 struct omap_drm_private {
+	uint32_t omaprev;
+
 	unsigned int num_crtcs;
 	struct drm_crtc *crtcs[8];
 
@@ -189,9 +191,9 @@ size_t omap_gem_mmap_size(struct drm_gem_object *obj);
 int omap_gem_tiled_size(struct drm_gem_object *obj, uint16_t *w, uint16_t *h);
 int omap_gem_tiled_stride(struct drm_gem_object *obj, uint32_t orient);
 
-struct dma_buf * omap_gem_prime_export(struct drm_device *dev,
+struct dma_buf *omap_gem_prime_export(struct drm_device *dev,
 		struct drm_gem_object *obj, int flags);
-struct drm_gem_object * omap_gem_prime_import(struct drm_device *dev,
+struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
 		struct dma_buf *buffer);
 
 static inline int align_pitch(int pitch, int width, int bpp)
@@ -216,17 +218,17 @@ static inline int objects_lookup(struct drm_device *dev,
 
 	for (i = 0; i < n; i++) {
 		bos[i] = drm_gem_object_lookup(dev, filp, handles[i]);
-		if (!bos[i]) {
+		if (!bos[i])
 			goto fail;
-		}
+
 	}
 
 	return 0;
 
 fail:
-	while (--i > 0) {
+	while (--i > 0)
 		drm_gem_object_unreference_unlocked(bos[i]);
-	}
+
 	return -ENOENT;
 }
 
diff --git a/drivers/staging/omapdrm/omap_encoder.c b/drivers/staging/omapdrm/omap_encoder.c
index 31c735d..5341d5e 100644
--- a/drivers/staging/omapdrm/omap_encoder.c
+++ b/drivers/staging/omapdrm/omap_encoder.c
@@ -72,9 +72,9 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
 
 	for (i = 0; i < priv->num_connectors; i++) {
 		struct drm_connector *connector = priv->connectors[i];
-		if (connector->encoder == encoder) {
+		if (connector->encoder == encoder)
 			omap_connector_mode_set(connector, mode);
-		}
+
 	}
 }
 
@@ -163,9 +163,8 @@ struct drm_encoder *omap_encoder_init(struct drm_device *dev,
 	return encoder;
 
 fail:
-	if (encoder) {
+	if (encoder)
 		omap_encoder_destroy(encoder);
-	}
 
 	return NULL;
 }
diff --git a/drivers/staging/omapdrm/omap_fb.c b/drivers/staging/omapdrm/omap_fb.c
index 446801d..09028e9 100644
--- a/drivers/staging/omapdrm/omap_fb.c
+++ b/drivers/staging/omapdrm/omap_fb.c
@@ -253,6 +253,7 @@ int omap_framebuffer_replace(struct drm_framebuffer *a,
 	int ret = 0, i, na, nb;
 	struct omap_framebuffer *ofba = to_omap_framebuffer(a);
 	struct omap_framebuffer *ofbb = to_omap_framebuffer(b);
+	uint32_t pinned_mask = 0;
 
 	na = a ? drm_format_num_planes(a->pixel_format) : 0;
 	nb = b ? drm_format_num_planes(b->pixel_format) : 0;
@@ -263,25 +264,24 @@ int omap_framebuffer_replace(struct drm_framebuffer *a,
 		pa = (i < na) ? &ofba->planes[i] : NULL;
 		pb = (i < nb) ? &ofbb->planes[i] : NULL;
 
-		if (pa) {
+		if (pa)
 			unpin(arg, pa->bo);
-			pa->paddr = 0;
-		}
 
 		if (pb && !ret) {
 			ret = omap_gem_get_paddr(pb->bo, &pb->paddr, true);
-			if (!ret)
+			if (!ret) {
 				omap_gem_dma_sync(pb->bo, DMA_TO_DEVICE);
+				pinned_mask |= (1 << i);
+			}
 		}
 	}
 
 	if (ret) {
 		/* something went wrong.. unpin what has been pinned */
 		for (i = 0; i < nb; i++) {
-			struct plane *pb = &ofba->planes[i];
-			if (pb->paddr) {
+			if (pinned_mask & (1 << i)) {
+				struct plane *pb = &ofba->planes[i];
 				unpin(arg, pb->bo);
-				pb->paddr = 0;
 			}
 		}
 	}
@@ -307,17 +307,16 @@ struct drm_connector *omap_framebuffer_get_next_connector(
 	struct list_head *connector_list = &dev->mode_config.connector_list;
 	struct drm_connector *connector = from;
 
-	if (!from) {
+	if (!from)
 		return list_first_entry(connector_list, typeof(*from), head);
-	}
 
 	list_for_each_entry_from(connector, connector_list, head) {
 		if (connector != from) {
 			struct drm_encoder *encoder = connector->encoder;
 			struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
-			if (crtc && crtc->fb == fb) {
+			if (crtc && crtc->fb == fb)
 				return connector;
-			}
+
 		}
 	}
 
@@ -466,8 +465,8 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 	return fb;
 
 fail:
-	if (fb) {
+	if (fb)
 		omap_framebuffer_destroy(fb);
-	}
+
 	return ERR_PTR(ret);
 }
diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c
index 66e2c2f..c38992b 100644
--- a/drivers/staging/omapdrm/omap_gem.c
+++ b/drivers/staging/omapdrm/omap_gem.c
@@ -25,7 +25,7 @@
 #include "omap_dmm_tiler.h"
 
 /* remove these once drm core helpers are merged */
-struct page ** _drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
+struct page **_drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
 void _drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
 		bool dirty, bool accessed);
 int _drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size);
@@ -521,9 +521,8 @@ int omap_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
 	/* if a shmem backed object, make sure we have pages attached now */
 	ret = get_pages(obj, &pages);
-	if (ret) {
+	if (ret)
 		goto fail;
-	}
 
 	/* where should we do corresponding put_pages().. we are mapping
 	 * the original page, rather than thru a GART, so we can't rely
@@ -953,7 +952,7 @@ int omap_gem_put_pages(struct drm_gem_object *obj)
 void *omap_gem_vaddr(struct drm_gem_object *obj)
 {
 	struct omap_gem_object *omap_obj = to_omap_bo(obj);
-	WARN_ON(! mutex_is_locked(&obj->dev->struct_mutex));
+	WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
 	if (!omap_obj->vaddr) {
 		struct page **pages;
 		int ret = get_pages(obj, &pages);
@@ -972,7 +971,7 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
 	struct omap_gem_object *omap_obj = to_omap_bo(obj);
 	uint64_t off = 0;
 
-	WARN_ON(! mutex_is_locked(&dev->struct_mutex));
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
 	if (obj->map_list.map)
 		off = (uint64_t)obj->map_list.hash.key;
@@ -1146,9 +1145,8 @@ int omap_gem_op_sync(struct drm_gem_object *obj, enum omap_gem_op op)
 		struct omap_gem_sync_waiter *waiter =
 				kzalloc(sizeof(*waiter), GFP_KERNEL);
 
-		if (!waiter) {
+		if (!waiter)
 			return -ENOMEM;
-		}
 
 		waiter->omap_obj = omap_obj;
 		waiter->op = op;
@@ -1177,9 +1175,8 @@ int omap_gem_op_sync(struct drm_gem_object *obj, enum omap_gem_op op)
 		}
 		spin_unlock(&sync_lock);
 
-		if (waiter) {
+		if (waiter)
 			kfree(waiter);
-		}
 	}
 	return ret;
 }
@@ -1201,9 +1198,8 @@ int omap_gem_op_async(struct drm_gem_object *obj, enum omap_gem_op op,
 		struct omap_gem_sync_waiter *waiter =
 				kzalloc(sizeof(*waiter), GFP_ATOMIC);
 
-		if (!waiter) {
+		if (!waiter)
 			return -ENOMEM;
-		}
 
 		waiter->omap_obj = omap_obj;
 		waiter->op = op;
@@ -1285,9 +1281,8 @@ void omap_gem_free_object(struct drm_gem_object *obj)
 
 	list_del(&omap_obj->mm_list);
 
-	if (obj->map_list.map) {
+	if (obj->map_list.map)
 		drm_gem_free_mmap_offset(obj);
-	}
 
 	/* this means the object is still pinned.. which really should
 	 * not happen.  I think..
@@ -1296,9 +1291,9 @@ void omap_gem_free_object(struct drm_gem_object *obj)
 
 	/* don't free externally allocated backing memory */
 	if (!(omap_obj->flags & OMAP_BO_EXT_MEM)) {
-		if (omap_obj->pages) {
+		if (omap_obj->pages)
 			omap_gem_detach_pages(obj);
-		}
+
 		if (!is_shmem(obj)) {
 			dma_free_writecombine(dev->dev, obj->size,
 					omap_obj->vaddr, omap_obj->paddr);
@@ -1308,9 +1303,8 @@ void omap_gem_free_object(struct drm_gem_object *obj)
 	}
 
 	/* don't free externally allocated syncobj */
-	if (!(omap_obj->flags & OMAP_BO_EXT_SYNC)) {
+	if (!(omap_obj->flags & OMAP_BO_EXT_SYNC))
 		kfree(omap_obj->sync);
-	}
 
 	drm_gem_object_release(obj);
 
@@ -1395,9 +1389,9 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev,
 		 */
 		omap_obj->vaddr =  dma_alloc_writecombine(dev->dev, size,
 				&omap_obj->paddr, GFP_KERNEL);
-		if (omap_obj->vaddr) {
+		if (omap_obj->vaddr)
 			flags |= OMAP_BO_DMA;
-		}
+
 	}
 
 	omap_obj->flags = flags;
@@ -1407,22 +1401,20 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev,
 		omap_obj->height = gsize.tiled.height;
 	}
 
-	if (flags & (OMAP_BO_DMA|OMAP_BO_EXT_MEM)) {
+	if (flags & (OMAP_BO_DMA|OMAP_BO_EXT_MEM))
 		ret = drm_gem_private_object_init(dev, obj, size);
-	} else {
+	else
 		ret = drm_gem_object_init(dev, obj, size);
-	}
 
-	if (ret) {
+	if (ret)
 		goto fail;
-	}
 
 	return obj;
 
 fail:
-	if (obj) {
+	if (obj)
 		omap_gem_free_object(obj);
-	}
+
 	return NULL;
 }
 
@@ -1435,7 +1427,7 @@ void omap_gem_init(struct drm_device *dev)
 	};
 	int i, j;
 
-	if (!dmm_is_initialized()) {
+	if (!dmm_is_available()) {
 		/* DMM only supported on OMAP4 and later, so this isn't fatal */
 		dev_warn(dev->dev, "DMM not available, disable DMM support\n");
 		return;
diff --git a/drivers/staging/omapdrm/omap_gem_dmabuf.c b/drivers/staging/omapdrm/omap_gem_dmabuf.c
index c6f3ef6..9a30206 100644
--- a/drivers/staging/omapdrm/omap_gem_dmabuf.c
+++ b/drivers/staging/omapdrm/omap_gem_dmabuf.c
@@ -191,13 +191,13 @@ struct dma_buf_ops omap_dmabuf_ops = {
 		.mmap = omap_gem_dmabuf_mmap,
 };
 
-struct dma_buf * omap_gem_prime_export(struct drm_device *dev,
+struct dma_buf *omap_gem_prime_export(struct drm_device *dev,
 		struct drm_gem_object *obj, int flags)
 {
 	return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, 0600);
 }
 
-struct drm_gem_object * omap_gem_prime_import(struct drm_device *dev,
+struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
 		struct dma_buf *buffer)
 {
 	struct drm_gem_object *obj;
diff --git a/drivers/staging/omapdrm/omap_gem_helpers.c b/drivers/staging/omapdrm/omap_gem_helpers.c
index f895363..ffb8cce 100644
--- a/drivers/staging/omapdrm/omap_gem_helpers.c
+++ b/drivers/staging/omapdrm/omap_gem_helpers.c
@@ -32,7 +32,7 @@
  * @obj: obj in question
  * @gfpmask: gfp mask of requested pages
  */
-struct page ** _drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask)
+struct page **_drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask)
 {
 	struct inode *inode;
 	struct address_space *mapping;
@@ -80,9 +80,9 @@ struct page ** _drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask)
 	return pages;
 
 fail:
-	while (i--) {
+	while (i--)
 		page_cache_release(pages[i]);
-	}
+
 	drm_free_large(pages);
 	return ERR_CAST(p);
 }
diff --git a/drivers/staging/omapdrm/omap_plane.c b/drivers/staging/omapdrm/omap_plane.c
index 4bde639..2a8e5ba 100644
--- a/drivers/staging/omapdrm/omap_plane.c
+++ b/drivers/staging/omapdrm/omap_plane.c
@@ -416,26 +416,28 @@ void omap_plane_install_properties(struct drm_plane *plane,
 	struct omap_drm_private *priv = dev->dev_private;
 	struct drm_property *prop;
 
-	prop = priv->rotation_prop;
-	if (!prop) {
-		const struct drm_prop_enum_list props[] = {
-				{ DRM_ROTATE_0,   "rotate-0" },
-				{ DRM_ROTATE_90,  "rotate-90" },
-				{ DRM_ROTATE_180, "rotate-180" },
-				{ DRM_ROTATE_270, "rotate-270" },
-				{ DRM_REFLECT_X,  "reflect-x" },
-				{ DRM_REFLECT_Y,  "reflect-y" },
-		};
-		prop = drm_property_create_bitmask(dev, 0, "rotation",
-				props, ARRAY_SIZE(props));
-		if (prop == NULL)
-			return;
-		priv->rotation_prop = prop;
+	if (priv->has_dmm) {
+		prop = priv->rotation_prop;
+		if (!prop) {
+			const struct drm_prop_enum_list props[] = {
+					{ DRM_ROTATE_0,   "rotate-0" },
+					{ DRM_ROTATE_90,  "rotate-90" },
+					{ DRM_ROTATE_180, "rotate-180" },
+					{ DRM_ROTATE_270, "rotate-270" },
+					{ DRM_REFLECT_X,  "reflect-x" },
+					{ DRM_REFLECT_Y,  "reflect-y" },
+			};
+			prop = drm_property_create_bitmask(dev, 0, "rotation",
+					props, ARRAY_SIZE(props));
+			if (prop == NULL)
+				return;
+			priv->rotation_prop = prop;
+		}
+		drm_object_attach_property(obj, prop, 0);
 	}
-	drm_object_attach_property(obj, prop, 0);
 
-        prop = priv->zorder_prop;
-        if (!prop) {
+	prop = priv->zorder_prop;
+	if (!prop) {
 		prop = drm_property_create_range(dev, 0, "zorder", 0, 3);
 		if (prop == NULL)
 			return;
@@ -549,8 +551,8 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 	return plane;
 
 fail:
-	if (plane) {
+	if (plane)
 		omap_plane_destroy(plane);
-	}
+
 	return NULL;
 }
diff --git a/drivers/staging/ozwpan/ozevent.c b/drivers/staging/ozwpan/ozevent.c
index a48498b..50578ba 100644
--- a/drivers/staging/ozwpan/ozevent.c
+++ b/drivers/staging/ozwpan/ozevent.c
@@ -79,6 +79,7 @@ void oz_event_log2(u8 evt, u8 ctx1, u16 ctx2, void *ctx3, unsigned ctx4)
 /*------------------------------------------------------------------------------
  * Context: process
  */
+#ifdef CONFIG_DEBUG_FS
 static void oz_events_clear(struct oz_evtdev *dev)
 {
 	unsigned long irqstate;
@@ -88,7 +89,6 @@ static void oz_events_clear(struct oz_evtdev *dev)
 	dev->missed_events = 0;
 	spin_unlock_irqrestore(&dev->lock, irqstate);
 }
-#ifdef CONFIG_DEBUG_FS
 /*------------------------------------------------------------------------------
  * Context: process
  */
diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c
index 2e087ac..b2d77df 100644
--- a/drivers/staging/ozwpan/ozhcd.c
+++ b/drivers/staging/ozwpan/ozhcd.c
@@ -278,8 +278,7 @@ static void oz_free_urb_link(struct oz_urb_link *urbl)
 			g_link_pool_size++;
 		}
 		spin_unlock_irqrestore(&g_link_lock, irq_state);
-		if (urbl)
-			kfree(urbl);
+		kfree(urbl);
 	}
 }
 /*------------------------------------------------------------------------------
@@ -2304,8 +2303,8 @@ error:
  */
 void oz_hcd_term(void)
 {
-	tasklet_disable(&g_urb_process_tasklet);
-	tasklet_disable(&g_urb_cancel_tasklet);
+	tasklet_kill(&g_urb_process_tasklet);
+	tasklet_kill(&g_urb_cancel_tasklet);
 	platform_device_unregister(g_plat_dev);
 	platform_driver_unregister(&g_oz_plat_drv);
 	oz_trace("Pending urbs:%d\n", atomic_read(&g_pending_urbs));
diff --git a/drivers/staging/ozwpan/ozpd.c b/drivers/staging/ozwpan/ozpd.c
index 0b3648c..118a4db 100644
--- a/drivers/staging/ozwpan/ozpd.c
+++ b/drivers/staging/ozwpan/ozpd.c
@@ -402,8 +402,7 @@ static void oz_tx_frame_free(struct oz_pd *pd, struct oz_tx_frame *f)
 		f = 0;
 	}
 	spin_unlock_bh(&pd->tx_frame_lock);
-	if (f)
-		kfree(f);
+	kfree(f);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq-serialized
@@ -737,8 +736,7 @@ int oz_isoc_stream_create(struct oz_pd *pd, u8 ep_num)
 		st = 0;
 	}
 	spin_unlock_bh(&pd->stream_lock);
-	if (st)
-		kfree(st);
+	kfree(st);
 	return 0;
 }
 /*------------------------------------------------------------------------------
diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c
index cfb5160..e00a539 100644
--- a/drivers/staging/ozwpan/ozproto.c
+++ b/drivers/staging/ozwpan/ozproto.c
@@ -566,8 +566,7 @@ static void oz_protocol_timer(unsigned long arg)
 		}
 		spin_unlock_bh(&g_polling_lock);
 		oz_pd_put(pd);
-		if (t)
-			kfree(t);
+		kfree(t);
 		t = t2;
 	} while (t);
 	g_timer_state = OZ_TIMER_IDLE;
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
index 5f5a302..8fc9f58 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
@@ -1221,7 +1221,7 @@ static inline void *ieee80211_priv(struct net_device *dev)
 	return ((struct ieee80211_device *)netdev_priv(dev))->priv;
 }
 
-extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
+static inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
 {
 	/* Single white space is for Linksys APs */
 	if (essid_len == 1 && essid[0] == ' ')
@@ -1237,7 +1237,7 @@ extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
 	return 1;
 }
 
-extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode)
+static inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode)
 {
 	/*
 	 * It is possible for both access points and our device to support
@@ -1263,7 +1263,7 @@ extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mod
 	return 0;
 }
 
-extern inline int ieee80211_get_hdrlen(u16 fc)
+static inline int ieee80211_get_hdrlen(u16 fc)
 {
 	int hdrlen = 24;
 
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
index b3882ae..694eae3 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
@@ -11,12 +11,14 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 //#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <asm/string.h>
-#include <asm/errno.h>
+#include <linux/string.h>
+#include <linux/errno.h>
 
 #include "ieee80211.h"
 
@@ -66,8 +68,7 @@ void ieee80211_crypt_deinit_handler(unsigned long data)
 	spin_lock_irqsave(&ieee->lock, flags);
 	ieee80211_crypt_deinit_entries(ieee, 0);
 	if (!list_empty(&ieee->crypt_deinit_list)) {
-		printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
-		       "deletion list\n", ieee->dev->name);
+		pr_debug("entries remaining in delayed crypt deletion list\n");
 		ieee->crypt_deinit_timer.expires = jiffies + HZ;
 		add_timer(&ieee->crypt_deinit_timer);
 	}
@@ -118,8 +119,7 @@ int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
 	list_add(&alg->list, &hcrypt->algs);
 	spin_unlock_irqrestore(&hcrypt->lock, flags);
 
-	printk(KERN_DEBUG "ieee80211_crypt: registered algorithm '%s'\n",
-	       ops->name);
+	pr_debug("registered algorithm '%s'\n", ops->name);
 
 	return 0;
 }
@@ -146,8 +146,7 @@ int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
 	spin_unlock_irqrestore(&hcrypt->lock, flags);
 
 	if (del_alg) {
-		printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
-		       "'%s'\n", ops->name);
+		pr_debug("unregistered algorithm '%s'\n", ops->name);
 		kfree(del_alg);
 	}
 
@@ -155,7 +154,7 @@ int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
 }
 
 
-struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name)
+struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name)
 {
 	unsigned long flags;
 	struct list_head *ptr;
@@ -182,7 +181,7 @@ struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name)
 }
 
 
-static void * ieee80211_crypt_null_init(int keyidx) { return (void *) 1; }
+static void *ieee80211_crypt_null_init(int keyidx) { return (void *) 1; }
 static void ieee80211_crypt_null_deinit(void *priv) {}
 
 static struct ieee80211_crypto_ops ieee80211_crypt_null = {
@@ -234,9 +233,8 @@ void ieee80211_crypto_deinit(void)
 		alg = list_entry(ptr, struct ieee80211_crypto_alg, list);
 		if (alg) {
 			list_del(ptr);
-			printk(KERN_DEBUG
-			       "ieee80211_crypt: unregistered algorithm '%s' (deinit)\n",
-			       alg->ops->name);
+			pr_debug("unregistered algorithm '%s' (deinit)\n",
+				 alg->ops->name);
 			kfree(alg);
 		}
 	}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h
index b58a3bc..0b4ea43 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h
@@ -77,7 +77,7 @@ struct ieee80211_crypt_data {
 
 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);
+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,
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
index 6aaaa2f..f5949e8 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
@@ -9,6 +9,8 @@
  * more details.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 //#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -18,7 +20,7 @@
 #include <linux/netdevice.h>
 #include <linux/if_ether.h>
 #include <linux/if_arp.h>
-#include <asm/string.h>
+#include <linux/string.h>
 #include <linux/wireless.h>
 
 #include "ieee80211.h"
@@ -64,7 +66,7 @@ void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm,
 	crypto_cipher_encrypt_one((void *)tfm, ct, pt);
 }
 
-static void * ieee80211_ccmp_init(int key_idx)
+static void *ieee80211_ccmp_init(int key_idx)
 {
 	struct ieee80211_ccmp_data *priv;
 
@@ -75,8 +77,7 @@ static void * ieee80211_ccmp_init(int key_idx)
 
 	priv->tfm = (void *)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(priv->tfm)) {
-		printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate "
-		       "crypto API aes\n");
+		pr_debug("could not allocate crypto API aes\n");
 		priv->tfm = NULL;
 		goto fail;
 	}
@@ -128,7 +129,7 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm,
 	/*
 	qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
 		       (WLAN_FC_GET_STYPE(fc) & 0x08));
-        */
+	*/
 	// fixed by David :2006.9.6
 	qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
 		       (WLAN_FC_GET_STYPE(fc) & 0x80));
@@ -282,23 +283,22 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 	keyidx = pos[3];
 	if (!(keyidx & (1 << 5))) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "CCMP: received packet without ExtIV"
-			       " flag from %pM\n", hdr->addr2);
+			pr_debug("received packet without ExtIV flag from %pM\n",
+				 hdr->addr2);
 		}
 		key->dot11RSNAStatsCCMPFormatErrors++;
 		return -2;
 	}
 	keyidx >>= 6;
 	if (key->key_idx != keyidx) {
-		printk(KERN_DEBUG "CCMP: RX tkey->key_idx=%d frame "
-		       "keyidx=%d priv=%p\n", key->key_idx, keyidx, priv);
+		pr_debug("RX tkey->key_idx=%d frame keyidx=%d priv=%p\n",
+			 key->key_idx, keyidx, priv);
 		return -6;
 	}
 	if (!key->key_set) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "CCMP: received packet from %pM"
-			       " with keyid=%d that does not have a configured"
-			       " key\n", hdr->addr2, keyidx);
+			pr_debug("received packet from %pM with keyid=%d that does not have a configured key\n",
+				 hdr->addr2, keyidx);
 		}
 		return -3;
 	}
@@ -313,9 +313,8 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 
 	if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "CCMP: replay detected: STA=%pM"
-			       " previous PN %pm received PN %pm\n",
-			       hdr->addr2, key->rx_pn, pn);
+			pr_debug("replay detected: STA=%pM previous PN %pm received PN %pm\n",
+				 hdr->addr2, key->rx_pn, pn);
 		}
 		key->dot11RSNAStatsCCMPReplays++;
 		return -4;
@@ -341,10 +340,9 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 	}
 
 	if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
-		if (net_ratelimit()) {
-			printk(KERN_DEBUG "CCMP: decrypt failed: STA="
-			       "%pM\n", hdr->addr2);
-		}
+		if (net_ratelimit())
+			pr_debug("decrypt failed: STA=%pM\n", hdr->addr2);
+
 		key->dot11RSNAStatsCCMPDecryptErrors++;
 		return -5;
 	}
@@ -415,7 +413,7 @@ static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv)
 }
 
 
-static char * ieee80211_ccmp_print_stats(char *p, void *priv)
+static char *ieee80211_ccmp_print_stats(char *p, void *priv)
 {
 	struct ieee80211_ccmp_data *ccmp = priv;
 	p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c
index 58f3eeb..bba7714 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c
@@ -9,13 +9,15 @@
  * more details.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 //#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/skbuff.h>
-#include <asm/string.h>
+#include <linux/string.h>
 
 #include "ieee80211.h"
 
@@ -40,7 +42,7 @@ struct prism2_wep_data {
 };
 
 
-static void * prism2_wep_init(int keyidx)
+static void *prism2_wep_init(int keyidx)
 {
 	struct prism2_wep_data *priv;
 
@@ -50,15 +52,13 @@ static void * prism2_wep_init(int keyidx)
 	priv->key_idx = keyidx;
 	priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(priv->tx_tfm)) {
-		printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
-		       "crypto API arc4\n");
+		pr_debug("could not allocate crypto API arc4\n");
 		priv->tx_tfm = NULL;
 		goto fail;
 	}
 	priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(priv->rx_tfm)) {
-		printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
-		       "crypto API arc4\n");
+		pr_debug("could not allocate crypto API arc4\n");
 		priv->rx_tfm = NULL;
 		goto fail;
 	}
@@ -217,7 +217,7 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 	memmove(skb->data + 4, skb->data, hdr_len);
 	skb_pull(skb, 4);
 	skb_trim(skb, skb->len - 4);
-        return 0;
+	return 0;
 }
 
 
@@ -248,7 +248,7 @@ static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv)
 }
 
 
-static char * prism2_wep_print_stats(char *p, void *priv)
+static char *prism2_wep_print_stats(char *p, void *priv)
 {
 	struct prism2_wep_data *wep = priv;
 	p += sprintf(p, "key[%d] alg=WEP len=%d\n",
@@ -289,5 +289,5 @@ void ieee80211_crypto_wep_exit(void)
 void ieee80211_wep_null(void)
 {
 //	printk("============>%s()\n", __func__);
-        return;
+	return;
 }
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
index 9422573..4358c4b 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
@@ -48,7 +48,7 @@
 #include <linux/types.h>
 #include <linux/wireless.h>
 #include <linux/etherdevice.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <net/arp.h>
 #include <net/net_namespace.h>
 
@@ -69,8 +69,7 @@ static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
 		MAX_NETWORK_COUNT, sizeof(struct ieee80211_network),
 		GFP_KERNEL);
 	if (!ieee->networks) {
-		printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
-		       ieee->dev->name);
+		netdev_warn(ieee->dev,  "Out of memory allocating beacons\n");
 		return -ENOMEM;
 	}
 
@@ -100,7 +99,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
 {
 	struct ieee80211_device *ieee;
 	struct net_device *dev;
-	int i,err;
+	int i, err;
 
 	IEEE80211_DEBUG_INFO("Initializing...\n");
 
@@ -140,11 +139,11 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
 	spin_lock_init(&ieee->wpax_suitlist_lock);
 
 	ieee->wpax_type_set = 0;
- 	ieee->wpa_enabled = 0;
- 	ieee->tkip_countermeasures = 0;
- 	ieee->drop_unencrypted = 0;
- 	ieee->privacy_invoked = 0;
- 	ieee->ieee802_1x = 1;
+	ieee->wpa_enabled = 0;
+	ieee->tkip_countermeasures = 0;
+	ieee->drop_unencrypted = 0;
+	ieee->privacy_invoked = 0;
+	ieee->ieee802_1x = 1;
 	ieee->raw_tx = 0;
 
 	ieee80211_softmac_init(ieee);
@@ -153,9 +152,9 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
 		INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]);
 
 	for (i = 0; i < 17; i++) {
-	  ieee->last_rxseq_num[i] = -1;
-	  ieee->last_rxfrag_num[i] = -1;
-	  ieee->last_packet_time[i] = 0;
+		ieee->last_rxseq_num[i] = -1;
+		ieee->last_rxfrag_num[i] = -1;
+		ieee->last_packet_time[i] = 0;
 	}
 //These function were added to load crypte module autoly
 	ieee80211_tkip_null();
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
index 3a72449..446f15e 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
@@ -39,7 +39,7 @@
 #include <linux/types.h>
 #include <linux/wireless.h>
 #include <linux/etherdevice.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/ctype.h>
 
 #include "ieee80211.h"
@@ -65,7 +65,7 @@ static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee,
 /* Called only as a tasklet (software IRQ) */
 static struct ieee80211_frag_entry *
 ieee80211_frag_cache_find(struct ieee80211_device *ieee, unsigned int seq,
-			  unsigned int frag, u8 tid,u8 *src, u8 *dst)
+			  unsigned int frag, u8 tid, u8 *src, u8 *dst)
 {
 	struct ieee80211_frag_entry *entry;
 	int i;
@@ -107,18 +107,18 @@ ieee80211_frag_cache_get(struct ieee80211_device *ieee,
 	struct ieee80211_hdr_4addrqos *hdr_4addrqos;
 	u8 tid;
 
-	if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
-	  hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
-	  tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
-	  tid = UP2AC(tid);
-	  tid ++;
+	if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) {
+		hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
+		tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
+		tid = UP2AC(tid);
+		tid++;
 	} else if (IEEE80211_QOS_HAS_SEQ(fc)) {
-	  hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
-	  tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
-	  tid = UP2AC(tid);
-	  tid ++;
+		hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
+		tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
+		tid = UP2AC(tid);
+		tid++;
 	} else {
-	  tid = 0;
+		tid = 0;
 	}
 
 	if (frag == 0) {
@@ -129,7 +129,7 @@ ieee80211_frag_cache_get(struct ieee80211_device *ieee,
 				    2 /* alignment */ +
 				    8 /* WEP */ +
 				    ETH_ALEN /* WDS */ +
-				    (IEEE80211_QOS_HAS_SEQ(fc)?2:0) /* QOS Control */);
+				    (IEEE80211_QOS_HAS_SEQ(fc) ? 2 : 0) /* QOS Control */);
 		if (skb == NULL)
 			return NULL;
 
@@ -150,7 +150,7 @@ ieee80211_frag_cache_get(struct ieee80211_device *ieee,
 	} else {
 		/* received a fragment of a frame for which the head fragment
 		 * should have already been received */
-		entry = ieee80211_frag_cache_find(ieee, seq, frag, tid,hdr->addr2,
+		entry = ieee80211_frag_cache_find(ieee, seq, frag, tid, hdr->addr2,
 						  hdr->addr1);
 		if (entry != NULL) {
 			entry->last_frag = frag;
@@ -174,21 +174,21 @@ static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
 	struct ieee80211_hdr_4addrqos *hdr_4addrqos;
 	u8 tid;
 
-	if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
-	  hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
-	  tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
-	  tid = UP2AC(tid);
-	  tid ++;
+	if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) {
+		hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
+		tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
+		tid = UP2AC(tid);
+		tid++;
 	} else if (IEEE80211_QOS_HAS_SEQ(fc)) {
-	  hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
-	  tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
-	  tid = UP2AC(tid);
-	  tid ++;
+		hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
+		tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
+		tid = UP2AC(tid);
+		tid++;
 	} else {
-	  tid = 0;
+		tid = 0;
 	}
 
-	entry = ieee80211_frag_cache_find(ieee, seq, -1, tid,hdr->addr2,
+	entry = ieee80211_frag_cache_find(ieee, seq, -1, tid, hdr->addr2,
 					  hdr->addr1);
 
 	if (entry == NULL) {
@@ -227,7 +227,7 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
 	ieee80211_rx_mgt(ieee, (struct ieee80211_hdr_4addr *)skb->data,
 			 rx_stats);
 
-	if((ieee->state == IEEE80211_LINKED)&&(memcmp(hdr->addr3,ieee->current_network.bssid,ETH_ALEN))) {
+	if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN))) {
 		dev_kfree_skb_any(skb);
 		return 0;
 	}
@@ -244,11 +244,9 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
 
 /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
 /* Ethernet-II snap header (RFC1042 for most EtherTypes) */
-static unsigned char rfc1042_header[] =
-{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+static unsigned char rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
 /* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
-static unsigned char bridge_tunnel_header[] =
-{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+static unsigned char bridge_tunnel_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
 /* No encapsulation header if EtherType < 0x600 (=length) */
 
 /* Called by ieee80211_rx_frame_decrypt */
@@ -294,7 +292,7 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
 
 /* Called only as a tasklet (software IRQ), by ieee80211_rx */
 static inline int
-ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
+ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
 			   struct ieee80211_crypt_data *crypt)
 {
 	struct ieee80211_hdr_4addr *hdr;
@@ -310,9 +308,9 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
 	if (ieee->tkip_countermeasures &&
 	    strcmp(crypt->ops->name, "TKIP") == 0) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "received packet from %pM\n",
-			       ieee->dev->name, hdr->addr2);
+			netdev_dbg(ieee->dev,
+				   "TKIP countermeasures: dropped received packet from %pM\n",
+				   ieee->dev->name, hdr->addr2);
 		}
 		return -1;
 	}
@@ -339,7 +337,7 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
 
 /* Called only as a tasklet (software IRQ), by ieee80211_rx */
 static inline int
-ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *skb,
+ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, struct sk_buff *skb,
 			     int keyidx, struct ieee80211_crypt_data *crypt)
 {
 	struct ieee80211_hdr_4addr *hdr;
@@ -355,9 +353,9 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *s
 	res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
 	atomic_dec(&crypt->refcnt);
 	if (res < 0) {
-		printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
-		       " (SA=%pM keyidx=%d)\n",
-		       ieee->dev->name, hdr->addr2, keyidx);
+		netdev_dbg(ieee->dev,
+			   "MSDU decryption/MIC verification failed (SA=%pM keyidx=%d)\n",
+			   hdr->addr2, keyidx);
 		return -1;
 	}
 
@@ -381,18 +379,18 @@ static int is_duplicate_packet(struct ieee80211_device *ieee,
 	u8 tid;
 
 	//TO2DS and QoS
-	if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
-	  hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)header;
-	  tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
-	  tid = UP2AC(tid);
-	  tid ++;
-	} else if(IEEE80211_QOS_HAS_SEQ(fc)) { //QoS
-	  hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)header;
-	  tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
-	  tid = UP2AC(tid);
-	  tid ++;
+	if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) {
+		hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)header;
+		tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
+		tid = UP2AC(tid);
+		tid++;
+	} else if (IEEE80211_QOS_HAS_SEQ(fc)) { //QoS
+		hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)header;
+		tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
+		tid = UP2AC(tid);
+		tid++;
 	} else { // no QoS
-	  tid = 0;
+		tid = 0;
 	}
 	switch (ieee->iw_mode) {
 	case IW_MODE_ADHOC:
@@ -411,7 +409,8 @@ static int is_duplicate_packet(struct ieee80211_device *ieee,
 		if (p == &ieee->ibss_mac_hash[index]) {
 			entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC);
 			if (!entry) {
-				printk(KERN_WARNING "Cannot malloc new mac entry\n");
+				netdev_warn(ieee->dev,
+					    "Cannot malloc new mac entry\n");
 				return 0;
 			}
 			memcpy(entry->mac, mac, ETH_ALEN);
@@ -442,7 +441,7 @@ static int is_duplicate_packet(struct ieee80211_device *ieee,
 //	}
 	if ((*last_seq == seq) &&
 	    time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) {
-		if (*last_frag == frag){
+		if (*last_frag == frag) {
 			//printk(KERN_WARNING "[1] go drop!\n");
 			goto drop;
 
@@ -493,8 +492,7 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 	stats = &ieee->stats;
 
 	if (skb->len < 10) {
-		printk(KERN_INFO "%s: SKB length < 10\n",
-		       dev->name);
+		netdev_info(ieee->dev, "SKB length < 10\n");
 		goto rx_dropped;
 	}
 
@@ -506,19 +504,12 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 	frag = WLAN_GET_SEQ_FRAG(sc);
 
 //YJ,add,080828,for keep alive
-	if((fc & IEEE80211_FCTL_TODS) != IEEE80211_FCTL_TODS)
-	{
-		if(!memcmp(hdr->addr1,dev->dev_addr, ETH_ALEN))
-		{
+	if ((fc & IEEE80211_FCTL_TODS) != IEEE80211_FCTL_TODS) {
+		if (!memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN))
 			ieee->NumRxUnicast++;
-		}
-	}
-	else
-	{
-		if(!memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN))
-		{
+	} else {
+		if (!memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN))
 			ieee->NumRxUnicast++;
-		}
 	}
 //YJ,add,080828,for keep alive,end
 
@@ -577,12 +568,12 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 	case IEEE80211_FCTL_FROMDS:
 		memcpy(dst, hdr->addr1, ETH_ALEN);
 		memcpy(src, hdr->addr3, ETH_ALEN);
-		memcpy(bssid,hdr->addr2,ETH_ALEN);
+		memcpy(bssid, hdr->addr2, ETH_ALEN);
 		break;
 	case IEEE80211_FCTL_TODS:
 		memcpy(dst, hdr->addr3, ETH_ALEN);
 		memcpy(src, hdr->addr2, ETH_ALEN);
-		memcpy(bssid,hdr->addr1,ETH_ALEN);
+		memcpy(bssid, hdr->addr1, ETH_ALEN);
 		break;
 	case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
 		if (skb->len < IEEE80211_DATA_HDR4_LEN)
@@ -594,7 +585,7 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 	case 0:
 		memcpy(dst, hdr->addr1, ETH_ALEN);
 		memcpy(src, hdr->addr2, ETH_ALEN);
-		memcpy(bssid,hdr->addr3,ETH_ALEN);
+		memcpy(bssid, hdr->addr3, ETH_ALEN);
 		break;
 	}
 
@@ -607,7 +598,7 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 	if (stype != IEEE80211_STYPE_DATA &&
 	    stype != IEEE80211_STYPE_DATA_CFACK &&
 	    stype != IEEE80211_STYPE_DATA_CFPOLL &&
-	    stype != IEEE80211_STYPE_DATA_CFACKPOLL&&
+	    stype != IEEE80211_STYPE_DATA_CFACKPOLL &&
 	    stype != IEEE80211_STYPE_QOS_DATA//add by David,2006.8.4
 	    ) {
 		if (stype != IEEE80211_STYPE_NULLFUNC)
@@ -618,9 +609,8 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 				type, stype, skb->len);
 		goto rx_dropped;
 	}
-	if(memcmp(bssid,ieee->current_network.bssid,ETH_ALEN)) {
+	if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN))
 		goto rx_dropped;
-	}
 
 	ieee->NumRxDataInPeriod++;
 	ieee->NumRxOkTotal++;
@@ -653,9 +643,8 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 			flen -= hdrlen;
 
 		if (frag_skb->tail + flen > frag_skb->end) {
-			printk(KERN_WARNING "%s: host decrypted and "
-			       "reassembled frame did not fit skb\n",
-			       dev->name);
+			netdev_warn(ieee->dev,
+				    "host decrypted and reassembled frame did not fit skb\n");
 			ieee80211_frag_cache_invalidate(ieee, hdr);
 			goto rx_dropped;
 		}
@@ -804,7 +793,7 @@ static inline int ieee80211_is_ofdm_rate(u8 rate)
 	case IEEE80211_OFDM_RATE_54MB:
 		return 1;
 	}
-        return 0;
+	return 0;
 }
 
 static inline int ieee80211_SignalStrengthTranslate(
@@ -814,46 +803,27 @@ static inline int ieee80211_SignalStrengthTranslate(
 	int RetSS;
 
 	// Step 1. Scale mapping.
-	if(CurrSS >= 71 && CurrSS <= 100)
-	{
+	if (CurrSS >= 71 && CurrSS <= 100)
 		RetSS = 90 + ((CurrSS - 70) / 3);
-	}
-	else if(CurrSS >= 41 && CurrSS <= 70)
-	{
+	else if (CurrSS >= 41 && CurrSS <= 70)
 		RetSS = 78 + ((CurrSS - 40) / 3);
-	}
-	else if(CurrSS >= 31 && CurrSS <= 40)
-	{
+	else if (CurrSS >= 31 && CurrSS <= 40)
 		RetSS = 66 + (CurrSS - 30);
-	}
-	else if(CurrSS >= 21 && CurrSS <= 30)
-	{
+	else if (CurrSS >= 21 && CurrSS <= 30)
 		RetSS = 54 + (CurrSS - 20);
-	}
-	else if(CurrSS >= 5 && CurrSS <= 20)
-	{
+	else if (CurrSS >= 5 && CurrSS <= 20)
 		RetSS = 42 + (((CurrSS - 5) * 2) / 3);
-	}
-	else if(CurrSS == 4)
-	{
+	else if (CurrSS == 4)
 		RetSS = 36;
-	}
-	else if(CurrSS == 3)
-	{
+	else if (CurrSS == 3)
 		RetSS = 27;
-	}
-	else if(CurrSS == 2)
-	{
+	else if (CurrSS == 2)
 		RetSS = 18;
-	}
-	else if(CurrSS == 1)
-	{
+	else if (CurrSS == 1)
 		RetSS = 9;
-	}
 	else
-	{
 		RetSS = CurrSS;
-	}
+
 	//RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping:  LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
 
 	// Step 2. Smoothing.
@@ -867,20 +837,16 @@ static inline void ieee80211_extract_country_ie(
 	struct ieee80211_device *ieee,
 	struct ieee80211_info_element *info_element,
 	struct ieee80211_network *network,
-	u8 * addr2
+	u8 *addr2
 )
 {
-	if(IS_DOT11D_ENABLE(ieee))
-	{
-		if(info_element->len!= 0)
-		{
+	if (IS_DOT11D_ENABLE(ieee)) {
+		if (info_element->len != 0) {
 			memcpy(network->CountryIeBuf, info_element->data, info_element->len);
 			network->CountryIeLen = info_element->len;
 
-			if(!IS_COUNTRY_IE_VALID(ieee))
-			{
+			if (!IS_COUNTRY_IE_VALID(ieee))
 				Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data);
-			}
 		}
 
 		//
@@ -888,10 +854,8 @@ static inline void ieee80211_extract_country_ie(
 		// some AP (e.g. Cisco 1242) don't include country IE in their
 		// probe response frame.
 		//
-		if(IS_EQUAL_CIE_SRC(ieee, addr2) )
-		{
+		if (IS_EQUAL_CIE_SRC(ieee, addr2))
 			UPDATE_CIE_WATCHDOG(ieee);
-		}
 	}
 
 }
@@ -920,10 +884,10 @@ inline int ieee80211_network_init(
 	char *p;
 #endif
 	struct ieee80211_info_element *info_element;
- 	u16 left;
+	u16 left;
 	u8 i;
 	short offset;
-	u8 curRate = 0,hOpRate = 0,curRate_ex = 0;
+	u8 curRate = 0, hOpRate = 0, curRate_ex = 0;
 
 	/* Pull out fixed field data */
 	memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
@@ -953,10 +917,10 @@ inline int ieee80211_network_init(
 	} else
 		network->flags |= NETWORK_HAS_CCK;
 
- 	network->wpa_ie_len = 0;
- 	network->rsn_ie_len = 0;
+	network->wpa_ie_len = 0;
+	network->rsn_ie_len = 0;
 
- 	info_element = &beacon->info_element;
+	info_element = &beacon->info_element;
 	left = stats->len - ((void *)info_element - (void *)beacon);
 	while (left >= sizeof(struct ieee80211_info_element_hdr)) {
 		if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) {
@@ -964,7 +928,7 @@ inline int ieee80211_network_init(
 					     info_element->len + sizeof(struct ieee80211_info_element),
 					     left);
 			return 1;
-               	}
+		}
 
 		switch (info_element->id) {
 		case MFIE_TYPE_SSID:
@@ -977,8 +941,8 @@ inline int ieee80211_network_init(
 			network->ssid_len = min(info_element->len,
 						(u8)IW_ESSID_MAX_SIZE);
 			memcpy(network->ssid, info_element->data, network->ssid_len);
-        		if (network->ssid_len < IW_ESSID_MAX_SIZE)
-                		memset(network->ssid + network->ssid_len, 0,
+			if (network->ssid_len < IW_ESSID_MAX_SIZE)
+				memset(network->ssid + network->ssid_len, 0,
 				       IW_ESSID_MAX_SIZE - network->ssid_len);
 
 			IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n",
@@ -993,7 +957,7 @@ inline int ieee80211_network_init(
 			for (i = 0; i < network->rates_len; i++) {
 				network->rates[i] = info_element->data[i];
 				curRate = network->rates[i] & 0x7f;
-				if( hOpRate < curRate )
+				if (hOpRate < curRate)
 					hOpRate = curRate;
 #ifdef CONFIG_IEEE80211_DEBUG
 				p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]);
@@ -1019,7 +983,7 @@ inline int ieee80211_network_init(
 			for (i = 0; i < network->rates_ex_len; i++) {
 				network->rates_ex[i] = info_element->data[i];
 				curRate_ex = network->rates_ex[i] & 0x7f;
-				if( hOpRate < curRate_ex )
+				if (hOpRate < curRate_ex)
 					hOpRate = curRate_ex;
 #ifdef CONFIG_IEEE80211_DEBUG
 				p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]);
@@ -1038,14 +1002,14 @@ inline int ieee80211_network_init(
 			break;
 
 		case MFIE_TYPE_DS_SET:
-  			IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n",
+			IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n",
 					     info_element->data[0]);
 			if (stats->freq == IEEE80211_24GHZ_BAND)
 				network->channel = info_element->data[0];
 			break;
 
-	 	case MFIE_TYPE_FH_SET:
-  			IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n");
+		case MFIE_TYPE_FH_SET:
+			IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n");
 			break;
 
 		case MFIE_TYPE_CF_SET:
@@ -1054,12 +1018,12 @@ inline int ieee80211_network_init(
 
 		case MFIE_TYPE_TIM:
 
-			if(info_element->len < 4)
+			if (info_element->len < 4)
 				break;
 
 			network->dtim_period = info_element->data[1];
 
-			if(ieee->state != IEEE80211_LINKED)
+			if (ieee->state != IEEE80211_LINKED)
 				break;
 
 			network->last_dtim_sta_time[0] = jiffies;
@@ -1067,10 +1031,10 @@ inline int ieee80211_network_init(
 
 			network->dtim_data = IEEE80211_DTIM_VALID;
 
-			if(info_element->data[0] != 0)
+			if (info_element->data[0] != 0)
 				break;
 
-			if(info_element->data[2] & 1)
+			if (info_element->data[2] & 1)
 				network->dtim_data |= IEEE80211_DTIM_MBCAST;
 
 			offset = (info_element->data[2] >> 1)*2;
@@ -1078,8 +1042,8 @@ inline int ieee80211_network_init(
 			//printk("offset1:%x aid:%x\n",offset, ieee->assoc_id);
 
 			/* add and modified for ps 2008.1.22 */
-			if(ieee->assoc_id < 8*offset ||
-				ieee->assoc_id > 8*(offset + info_element->len -3)) {
+			if (ieee->assoc_id < 8*offset ||
+				ieee->assoc_id > 8*(offset + info_element->len - 3)) {
 				break;
 			}
 
@@ -1089,9 +1053,9 @@ inline int ieee80211_network_init(
 			//	info_element->data[3+offset] ,
 			//	info_element->data[3+offset] & (1<<(ieee->assoc_id%8)));
 
-			if(info_element->data[3+offset] & (1<<(ieee->assoc_id%8))) {
+			if (info_element->data[3+offset] & (1<<(ieee->assoc_id%8)))
 				network->dtim_data |= IEEE80211_DTIM_UCAST;
-			}
+
 			break;
 
 		case MFIE_TYPE_IBSS_SET:
@@ -1125,9 +1089,8 @@ inline int ieee80211_network_init(
 			    info_element->data[4] == 0x02) {
 				network->Turbo_Enable = 1;
 			}
-			if (1 == stats->nic_type) {//nic 87
+			if (1 == stats->nic_type) //nic 87
 				break;
-			}
 
 			if (info_element->len >= 5  &&
 			    info_element->data[0] == 0x00 &&
@@ -1152,7 +1115,7 @@ inline int ieee80211_network_init(
 				//printk(KERN_WARNING "wmm info&param updated: %x\n", info_element->data[6]);
 				network->wmm_info = info_element->data[6];
 				//WMM Parameter Element
-				memcpy(network->wmm_param, (u8 *)(info_element->data + 8),(info_element->len - 8));
+				memcpy(network->wmm_param, (u8 *)(info_element->data + 8), (info_element->len - 8));
 				network->QoS_Enable = 1;
 			}
 			break;
@@ -1174,14 +1137,14 @@ inline int ieee80211_network_init(
 		default:
 			IEEE80211_DEBUG_SCAN("unsupported IE %d\n",
 					     info_element->id);
-                        break;
-  		}
+			break;
+		}
 
 		left -= sizeof(struct ieee80211_info_element_hdr) +
 			info_element->len;
 		info_element = (struct ieee80211_info_element *)
-                	&info_element->data[info_element->len];
-  	}
+			&info_element->data[info_element->len];
+	}
 //by amy 080312
 	network->HighestOperaRate = hOpRate;
 //by amy 080312
@@ -1217,7 +1180,7 @@ inline int ieee80211_network_init(
 
 static inline int is_same_network(struct ieee80211_network *src,
 				  struct ieee80211_network *dst,
-				  struct ieee80211_device * ieee)
+				  struct ieee80211_device *ieee)
 {
 	/* A network is only a duplicate if the channel, BSSID, ESSID
 	 * and the capability field (in particular IBSS and BSS) all match.
@@ -1241,12 +1204,11 @@ inline void update_network(struct ieee80211_network *dst,
 	unsigned char quality = src->stats.signalstrength;
 	unsigned char signal = 0;
 	unsigned char noise = 0;
-        if(dst->stats.signalstrength > 0) {
-                quality = (dst->stats.signalstrength * 5 + src->stats.signalstrength + 5)/6;
-        }
+	if (dst->stats.signalstrength > 0)
+		quality = (dst->stats.signalstrength * 5 + src->stats.signalstrength + 5)/6;
 	signal = ieee80211_TranslateToDbm(quality);
 	//noise = signal - src->stats.noise;
-	if(dst->stats.noise > 0)
+	if (dst->stats.noise > 0)
 		noise = (dst->stats.noise * 5 + src->stats.noise)/6;
         //if(strcmp(dst->ssid, "linksys_lzm000") == 0)
 //	printk("ssid:%s, quality:%d, signal:%d\n", dst->ssid, quality, signal);
@@ -1262,12 +1224,11 @@ inline void update_network(struct ieee80211_network *dst,
 	dst->rates_len = src->rates_len;
 	memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
 	dst->rates_ex_len = src->rates_ex_len;
-	dst->HighestOperaRate= src->HighestOperaRate;
+	dst->HighestOperaRate = src->HighestOperaRate;
 	//printk("==========>in %s: src->ssid is %s,chan is %d\n",__func__,src->ssid,src->channel);
 
 	//YJ,add,080819,for hidden ap
-	if(src->ssid_len > 0)
-	{
+	if (src->ssid_len > 0) {
 		//if(src->ssid_len == 13)
 		//	printk("=====================>>>>>>>> Dst ssid: %s Src ssid: %s\n", dst->ssid, src->ssid);
 		memset(dst->ssid, 0, dst->ssid_len);
@@ -1305,11 +1266,11 @@ inline void update_network(struct ieee80211_network *dst,
 	  memcpy(dst->wmm_param, src->wmm_param, IEEE80211_AC_PRAM_LEN);
 	}
 */
-	if(src->wmm_param[0].ac_aci_acm_aifsn|| \
-	   src->wmm_param[1].ac_aci_acm_aifsn|| \
-	   src->wmm_param[2].ac_aci_acm_aifsn|| \
+	if (src->wmm_param[0].ac_aci_acm_aifsn || \
+	   src->wmm_param[1].ac_aci_acm_aifsn || \
+	   src->wmm_param[2].ac_aci_acm_aifsn || \
 	   src->wmm_param[3].ac_aci_acm_aifsn) {
-	  memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN);
+		memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN);
 	}
 	dst->QoS_Enable = src->QoS_Enable;
 #else
@@ -1336,7 +1297,7 @@ inline void ieee80211_process_probe_response(
 	unsigned long flags;
 	short renew;
 	u8 wmm_info;
-	u8 is_beacon = (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_BEACON)? 1:0;  //YJ,add,080819,for hidden ap
+	u8 is_beacon = (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_BEACON) ? 1 : 0;  //YJ,add,080819,for hidden ap
 
 	memset(&network, 0, sizeof(struct ieee80211_network));
 
@@ -1378,48 +1339,36 @@ inline void ieee80211_process_probe_response(
 	// (2)  If there is no any country code in beacon,
 	//       then wireless adapter should do active scan from ch1~11 and
 	//       passive scan from ch12~14
-	if(ieee->bGlobalDomain)
-	{
-		if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP)
-		{
+	if (ieee->bGlobalDomain) {
+		if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP) {
 			// Case 1: Country code
-			if(IS_COUNTRY_IE_VALID(ieee) )
-			{
-				if( !IsLegalChannel(ieee, network.channel) )
-				{
+			if (IS_COUNTRY_IE_VALID(ieee)) {
+				if (!IsLegalChannel(ieee, network.channel)) {
 					printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network.channel);
 					return;
 				}
 			}
 			// Case 2: No any country code.
-			else
-			{
+			else {
 				// Filter over channel ch12~14
-				if(network.channel > 11)
-				{
+				if (network.channel > 11) {
 					printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network.channel);
 					return;
 				}
 			}
-		}
-		else
-		{
+		} else {
 			// Case 1: Country code
-			if(IS_COUNTRY_IE_VALID(ieee) )
-			{
-				if( !IsLegalChannel(ieee, network.channel) )
-				{
-					printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n",network.channel);
+			if (IS_COUNTRY_IE_VALID(ieee)) {
+				if (!IsLegalChannel(ieee, network.channel)) {
+					printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n", network.channel);
 					return;
 				}
 			}
 			// Case 2: No any country code.
-			else
-			{
+			else {
 				// Filter over channel ch12~14
-				if(network.channel > 14)
-				{
-					printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n",network.channel);
+				if (network.channel > 14) {
+					printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n", network.channel);
 					return;
 				}
 			}
@@ -1437,12 +1386,12 @@ inline void ieee80211_process_probe_response(
 
 	spin_lock_irqsave(&ieee->lock, flags);
 
-	if(is_same_network(&ieee->current_network, &network, ieee)) {
+	if (is_same_network(&ieee->current_network, &network, ieee)) {
 		wmm_info = ieee->current_network.wmm_info;
 		//YJ,add,080819,for hidden ap
-		if(is_beacon == 0)
+		if (is_beacon == 0)
 			network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags);
-		else if(ieee->state == IEEE80211_LINKED)
+		else if (ieee->state == IEEE80211_LINKED)
 			ieee->NumRxBcnInPeriod++;
 		//YJ,add,080819,for hidden ap,end
 		//printk("====>network.ssid=%s cur_ssid=%s\n", network.ssid, ieee->current_network.ssid);
@@ -1504,13 +1453,13 @@ inline void ieee80211_process_probe_response(
 		 */
 		renew = !time_after(target->last_scanned + ieee->scan_age, jiffies);
 		//YJ,add,080819,for hidden ap
-		if(is_beacon == 0)
+		if (is_beacon == 0)
 			network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags);
 		//if(strncmp(network.ssid, "linksys-c",9) == 0)
 		//	printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags);
-		if(((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \
+		if (((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \
 		    && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\
-		    ||((ieee->current_network.ssid_len == network.ssid_len)&&(strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0)&&(ieee->state == IEEE80211_NOLINK))))
+		    || ((ieee->current_network.ssid_len == network.ssid_len) && (strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0) && (ieee->state == IEEE80211_NOLINK))))
 			renew = 1;
 		//YJ,add,080819,for hidden ap,end
 		update_network(target, &network);
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
index 1ef8fd6..d9add53 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
@@ -32,11 +32,11 @@ int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info
 			     union iwreq_data *wrqu, char *b)
 {
 	int ret;
-	struct iw_freq *fwrq = & wrqu->freq;
+	struct iw_freq *fwrq = &wrqu->freq;
 //	printk("in %s\n",__func__);
 	down(&ieee->wx_sem);
 
-	if(ieee->iw_mode == IW_MODE_INFRA){
+	if (ieee->iw_mode == IW_MODE_INFRA) {
 		ret = -EOPNOTSUPP;
 		goto out;
 	}
@@ -57,21 +57,20 @@ int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info
 		}
 	}
 
-	if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1 ){
+	if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1) {
 		ret = -EOPNOTSUPP;
 		goto out;
 
-	}else { /* Set the channel */
+	} else { /* Set the channel */
 
 
 		ieee->current_network.channel = fwrq->m;
 		ieee->set_chan(ieee->dev, ieee->current_network.channel);
 
-		if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
-			if(ieee->state == IEEE80211_LINKED){
-
-			ieee80211_stop_send_beacons(ieee);
-			ieee80211_start_send_beacons(ieee);
+		if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
+			if (ieee->state == IEEE80211_LINKED) {
+				ieee80211_stop_send_beacons(ieee);
+				ieee80211_start_send_beacons(ieee);
 			}
 	}
 
@@ -86,7 +85,7 @@ int ieee80211_wx_get_freq(struct ieee80211_device *ieee,
 			     struct iw_request_info *a,
 			     union iwreq_data *wrqu, char *b)
 {
-	struct iw_freq *fwrq = & wrqu->freq;
+	struct iw_freq *fwrq = &wrqu->freq;
 
 	if (ieee->current_network.channel == 0)
 		return -1;
@@ -143,12 +142,12 @@ int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
 
 	down(&ieee->wx_sem);
 	/* use ifconfig hw ether */
-	if (ieee->iw_mode == IW_MODE_MASTER){
+	if (ieee->iw_mode == IW_MODE_MASTER) {
 		ret = -1;
 		goto out;
 	}
 
-	if (temp->sa_family != ARPHRD_ETHER){
+	if (temp->sa_family != ARPHRD_ETHER) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -175,9 +174,10 @@ out:
 	return ret;
 }
 
- int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b)
+int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,
+			    union iwreq_data *wrqu, char *b)
 {
-	int len,ret = 0;
+	int len, ret = 0;
 	unsigned long flags;
 
 	if (ieee->iw_mode == IW_MODE_MONITOR)
@@ -200,7 +200,7 @@ out:
 	}
 	len = ieee->current_network.ssid_len;
 	wrqu->essid.length = len;
-	strncpy(b,ieee->current_network.ssid,len);
+	strncpy(b, ieee->current_network.ssid, len);
 	wrqu->essid.flags = 1;
 
 out:
@@ -218,11 +218,11 @@ int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
 	u32 target_rate = wrqu->bitrate.value;
 
 	//added by lizhaoming for auto mode
-	if(target_rate == -1){
-	ieee->rate = 110;
-	} else {
-	ieee->rate = target_rate/100000;
-	}
+	if (target_rate == -1)
+		ieee->rate = 110;
+	else
+		ieee->rate = target_rate/100000;
+
 	//FIXME: we might want to limit rate also in management protocols.
 	return 0;
 }
@@ -250,16 +250,14 @@ int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info
 	if (wrqu->mode == ieee->iw_mode)
 		goto out;
 
-	if (wrqu->mode == IW_MODE_MONITOR){
-
+	if (wrqu->mode == IW_MODE_MONITOR)
 		ieee->dev->type = ARPHRD_IEEE80211;
-	}else{
+	else
 		ieee->dev->type = ARPHRD_ETHER;
-	}
 
-	if (!ieee->proto_started){
+	if (!ieee->proto_started) {
 		ieee->iw_mode = wrqu->mode;
-	}else{
+	} else {
 		ieee80211_stop_protocol(ieee);
 		ieee->iw_mode = wrqu->mode;
 		ieee80211_start_protocol(ieee);
@@ -296,7 +294,7 @@ void ieee80211_wx_sync_scan_wq(struct work_struct *work)
 	if (ieee->data_hard_resume)
 		ieee->data_hard_resume(ieee->dev);
 
-	if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
+	if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
 		ieee80211_start_send_beacons(ieee);
 
 	//YJ,add,080828, In prevent of lossing ping packet during scanning
@@ -314,7 +312,7 @@ int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info
 
 	down(&ieee->wx_sem);
 
-	if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)){
+	if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) {
 		ret = -1;
 		goto out;
 	}
@@ -323,7 +321,7 @@ int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info
 	//ieee80211_sta_ps_send_null_frame(ieee, true);
 	//YJ,add,080828,end
 
-	if ( ieee->state == IEEE80211_LINKED){
+	if (ieee->state == IEEE80211_LINKED) {
 		queue_work(ieee->wq, &ieee->wx_sync_scan_wq);
 		/* intentionally forget to up sem */
 		return 0;
@@ -339,7 +337,7 @@ int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
 			      union iwreq_data *wrqu, char *extra)
 {
 
-	int ret=0,len;
+	int ret = 0, len;
 	short proto_started;
 	unsigned long flags;
 
@@ -349,17 +347,17 @@ int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
 
 	proto_started = ieee->proto_started;
 
-	if (wrqu->essid.length > IW_ESSID_MAX_SIZE){
-		ret= -E2BIG;
+	if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
+		ret = -E2BIG;
 		goto out;
 	}
 
-	if (ieee->iw_mode == IW_MODE_MONITOR){
-		ret= -1;
+	if (ieee->iw_mode == IW_MODE_MONITOR) {
+		ret = -1;
 		goto out;
 	}
 
-	if(proto_started)
+	if (proto_started)
 		ieee80211_stop_protocol(ieee);
 
 	/* this is just to be sure that the GET wx callback
@@ -377,13 +375,12 @@ int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
 //YJ,modified,080819,end
 
 		//YJ,add,080819,for hidden ap
-		if(len == 0){
+		if (len == 0) {
 			memset(ieee->current_network.bssid, 0, ETH_ALEN);
 			ieee->current_network.capability = 0;
 		}
 		//YJ,add,080819,for hidden ap,end
-	}
-	else{
+	} else {
 		ieee->ssid_set = 0;
 		ieee->current_network.ssid[0] = '\0';
 		ieee->current_network.ssid_len = 0;
@@ -398,7 +395,7 @@ out:
 	return ret;
 }
 
- int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
+int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
 			     union iwreq_data *wrqu, char *b)
 {
 
@@ -406,7 +403,7 @@ out:
 	return 0;
 }
 
- int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
+int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
 			       struct iw_request_info *info,
 			       union iwreq_data *wrqu, char *extra)
 {
@@ -417,24 +414,23 @@ out:
 
 	down(&ieee->wx_sem);
 
-	if(enable)
+	if (enable)
 		ieee->raw_tx = 1;
 	else
 		ieee->raw_tx = 0;
 
-	printk(KERN_INFO"raw TX is %s\n",
-	      ieee->raw_tx ? "enabled" : "disabled");
+	netdev_info(ieee->dev, "raw TX is %s\n",
+		    ieee->raw_tx ? "enabled" : "disabled");
 
-	if(ieee->iw_mode == IW_MODE_MONITOR)
-	{
-		if(prev == 0 && ieee->raw_tx){
+	if (ieee->iw_mode == IW_MODE_MONITOR) {
+		if (prev == 0 && ieee->raw_tx) {
 			if (ieee->data_hard_resume)
 				ieee->data_hard_resume(ieee->dev);
 
 			netif_carrier_on(ieee->dev);
 		}
 
-		if(prev && ieee->raw_tx == 1)
+		if (prev && ieee->raw_tx == 1)
 			netif_carrier_off(ieee->dev);
 	}
 
@@ -448,18 +444,18 @@ int ieee80211_wx_get_name(struct ieee80211_device *ieee,
 			     union iwreq_data *wrqu, char *extra)
 {
 	strlcpy(wrqu->name, "802.11", IFNAMSIZ);
-	if(ieee->modulation & IEEE80211_CCK_MODULATION){
+	if (ieee->modulation & IEEE80211_CCK_MODULATION) {
 		strlcat(wrqu->name, "b", IFNAMSIZ);
-		if(ieee->modulation & IEEE80211_OFDM_MODULATION)
+		if (ieee->modulation & IEEE80211_OFDM_MODULATION)
 			strlcat(wrqu->name, "/g", IFNAMSIZ);
-	}else if(ieee->modulation & IEEE80211_OFDM_MODULATION)
+	} else if (ieee->modulation & IEEE80211_OFDM_MODULATION)
 		strlcat(wrqu->name, "g", IFNAMSIZ);
 
-	if((ieee->state == IEEE80211_LINKED) ||
+	if ((ieee->state == IEEE80211_LINKED) ||
 		(ieee->state == IEEE80211_LINKED_SCANNING))
-		strlcat(wrqu->name,"  link", IFNAMSIZ);
-	else if(ieee->state != IEEE80211_NOLINK)
-		strlcat(wrqu->name," .....", IFNAMSIZ);
+		strlcat(wrqu->name, "  link", IFNAMSIZ);
+	else if (ieee->state != IEEE80211_NOLINK)
+		strlcat(wrqu->name, " .....", IFNAMSIZ);
 
 
 	return 0;
@@ -473,11 +469,10 @@ int ieee80211_wx_set_power(struct ieee80211_device *ieee,
 {
 	int ret = 0;
 
-	if(
-		(!ieee->sta_wake_up) ||
-		(!ieee->ps_request_tx_ack) ||
-		(!ieee->enter_sleep_state) ||
-		(!ieee->ps_is_queue_empty)){
+	if ((!ieee->sta_wake_up) ||
+	    (!ieee->ps_request_tx_ack) ||
+	    (!ieee->enter_sleep_state) ||
+	    (!ieee->ps_is_queue_empty)) {
 
 		printk("ERROR. PS mode tried to be use but driver missed a callback\n\n");
 
@@ -486,7 +481,7 @@ int ieee80211_wx_set_power(struct ieee80211_device *ieee,
 
 	down(&ieee->wx_sem);
 
-	if (wrqu->power.disabled){
+	if (wrqu->power.disabled) {
 		ieee->ps = IEEE80211_PS_DISABLED;
 
 		goto exit;
@@ -512,7 +507,7 @@ int ieee80211_wx_set_power(struct ieee80211_device *ieee,
 	if (wrqu->power.flags & IW_POWER_TIMEOUT) {
 
 		ieee->ps_timeout = wrqu->power.value / 1000;
-		printk("Timeout %d\n",ieee->ps_timeout);
+		printk("Timeout %d\n", ieee->ps_timeout);
 	}
 
 	if (wrqu->power.flags & IW_POWER_PERIOD) {
@@ -533,11 +528,11 @@ int ieee80211_wx_get_power(struct ieee80211_device *ieee,
 				 struct iw_request_info *info,
 				 union iwreq_data *wrqu, char *extra)
 {
-	int ret =0;
+	int ret = 0;
 
 	down(&ieee->wx_sem);
 
-	if(ieee->ps == IEEE80211_PS_DISABLED){
+	if (ieee->ps == IEEE80211_PS_DISABLED) {
 		wrqu->power.disabled = 1;
 		goto exit;
 	}
diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h
index 2682afb..70ea414 100644
--- a/drivers/staging/rtl8187se/r8180.h
+++ b/drivers/staging/rtl8187se/r8180.h
@@ -327,12 +327,8 @@ typedef struct r8180_priv
 	int irq;
 	struct ieee80211_device *ieee80211;
 
-	short phy_ver; /* meaningful for rtl8225 1:A 2:B 3:C */
-	short enable_gpio0;
-	short hw_plcp_len;
 	short plcp_preamble_mode; // 0:auto 1:short 2:long
 
-	spinlock_t irq_lock;
 	spinlock_t irq_th_lock;
 	spinlock_t tx_lock;
 	spinlock_t ps_lock;
@@ -350,7 +346,6 @@ typedef struct r8180_priv
 	u8 channel_plan;  // it's the channel plan index
 	short up;
 	short crcmon; //if 1 allow bad crc frame reception in monitor mode
-	short prism_hdr;
 
 	struct timer_list scan_timer;
 	/*short scanpending;
@@ -359,14 +354,11 @@ typedef struct r8180_priv
 	u8 active_probe;
 	//u8 active_scan_num;
 	struct semaphore wx_sem;
-	struct semaphore rf_state;
 	short hw_wep;
 
 	short digphy;
 	short antb;
 	short diversity;
-	u8 cs_treshold;
-	short rcr_csense;
 	u32 key0[4];
 	short (*rf_set_sens)(struct net_device *dev,short sens);
 	void (*rf_set_chan)(struct net_device *dev,short ch);
@@ -491,7 +483,6 @@ typedef struct r8180_priv
 	RT_RF_POWER_STATE eRFPowerState;
 	u32 RfOffReason;
 	bool RFChangeInProgress;
-	bool bInHctTest;
 	bool SetRFPowerStateInProgress;
 	u8   RFProgType;
 	bool bLeisurePs;
@@ -618,17 +609,11 @@ typedef struct r8180_priv
 //	struct workqueue_struct *workqueue;
 	struct work_struct reset_wq;
 	struct work_struct watch_dog_wq;
-	struct work_struct tx_irq_wq;
 	short ack_tx_to_ieee;
 
-	u8 PowerProfile;
-	u32 CSMethod;
-	u8 cck_txpwr_base;
-	u8 ofdm_txpwr_base;
 	u8 dma_poll_stop_mask;
 
 	//u8 RegThreeWireMode;
-	u8 MWIEnable;
 	u16 ShortRetryLimit;
 	u16 LongRetryLimit;
 	u16 EarlyRxThreshold;
@@ -667,35 +652,22 @@ void write_nic_dword(struct net_device *dev, int x,u32 y);
 void force_pci_posting(struct net_device *dev);
 
 void rtl8180_rtx_disable(struct net_device *);
-void rtl8180_rx_enable(struct net_device *);
-void rtl8180_tx_enable(struct net_device *);
-void rtl8180_start_scanning(struct net_device *dev);
-void rtl8180_start_scanning_s(struct net_device *dev);
-void rtl8180_stop_scanning(struct net_device *dev);
-void rtl8180_disassociate(struct net_device *dev);
-//void fix_rx_fifo(struct net_device *dev);
 void rtl8180_set_anaparam(struct net_device *dev,u32 a);
 void rtl8185_set_anaparam2(struct net_device *dev,u32 a);
 void rtl8180_set_hw_wep(struct net_device *dev);
 void rtl8180_no_hw_wep(struct net_device *dev);
 void rtl8180_update_msr(struct net_device *dev);
-//void rtl8180_BSS_create(struct net_device *dev);
 void rtl8180_beacon_tx_disable(struct net_device *dev);
 void rtl8180_beacon_rx_disable(struct net_device *dev);
-void rtl8180_conttx_enable(struct net_device *dev);
-void rtl8180_conttx_disable(struct net_device *dev);
 int rtl8180_down(struct net_device *dev);
 int rtl8180_up(struct net_device *dev);
 void rtl8180_commit(struct net_device *dev);
 void rtl8180_set_chan(struct net_device *dev,short ch);
-void rtl8180_set_master_essid(struct net_device *dev,char *essid);
-void rtl8180_update_beacon_security(struct net_device *dev);
 void write_phy(struct net_device *dev, u8 adr, u8 data);
 void write_phy_cck(struct net_device *dev, u8 adr, u32 data);
 void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data);
 void rtl8185_tx_antenna(struct net_device *dev, u8 ant);
 void rtl8185_rf_pins_enable(struct net_device *dev);
-void IBSS_randomize_cell(struct net_device *dev);
 void IPSEnter(struct net_device *dev);
 void IPSLeave(struct net_device *dev);
 int get_curr_tx_free_desc(struct net_device *dev, int priority);
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index 20e5fb5..ae38475 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -27,6 +27,8 @@
    Written by Mariusz Matuszek.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #undef RX_DONT_PASS_UL
 #undef DUMMY_RX
 
@@ -44,7 +46,7 @@
 
 #include "ieee80211/dot11d.h"
 
-static struct pci_device_id rtl8180_pci_id_tbl[] __devinitdata = {
+static struct pci_device_id rtl8180_pci_id_tbl[] = {
 	{
 		.vendor = PCI_VENDOR_ID_REALTEK,
 		.device = 0x8199,
@@ -61,33 +63,23 @@ static struct pci_device_id rtl8180_pci_id_tbl[] __devinitdata = {
 	}
 };
 
-
 static char ifname[IFNAMSIZ] = "wlan%d";
-static int hwseqnum = 0;
-static int hwwep = 0;
-static int channels = 0x3fff;
+static int hwwep;
 
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, rtl8180_pci_id_tbl);
 MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
-MODULE_DESCRIPTION("Linux driver for Realtek RTL8180 / RTL8185 WiFi cards");
-
+MODULE_DESCRIPTION("Linux driver for Realtek RTL8187SE WiFi cards");
 
 module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR);
-module_param(hwseqnum, int, S_IRUGO|S_IWUSR);
 module_param(hwwep, int, S_IRUGO|S_IWUSR);
-module_param(channels, int, S_IRUGO|S_IWUSR);
 
-MODULE_PARM_DESC(devname, " Net interface name, wlan%d=default");
-MODULE_PARM_DESC(hwseqnum, " Try to use hardware 802.11 header sequence numbers. Zero=default");
 MODULE_PARM_DESC(hwwep, " Try to use hardware WEP support. Still broken and not available on all cards");
-MODULE_PARM_DESC(channels, " Channel bitmask for specific locales. NYI");
 
-
-static int __devinit rtl8180_pci_probe(struct pci_dev *pdev,
+static int rtl8180_pci_probe(struct pci_dev *pdev,
 				       const struct pci_device_id *id);
 
-static void __devexit rtl8180_pci_remove(struct pci_dev *pdev);
+static void rtl8180_pci_remove(struct pci_dev *pdev);
 
 static void rtl8180_shutdown(struct pci_dev *pdev)
 {
@@ -126,8 +118,7 @@ static int rtl8180_resume(struct pci_dev *pdev)
 
 	err = pci_enable_device(pdev);
 	if (err) {
-		printk(KERN_ERR "%s: pci_enable_device failed on resume\n",
-				dev->name);
+		dev_err(&pdev->dev, "pci_enable_device failed on resume\n");
 
 		return err;
 	}
@@ -159,7 +150,7 @@ static struct pci_driver rtl8180_pci_driver = {
 	.name		= RTL8180_MODULE_NAME,
 	.id_table	= rtl8180_pci_id_tbl,
 	.probe		= rtl8180_pci_probe,
-	.remove		= __devexit_p(rtl8180_pci_remove),
+	.remove		= rtl8180_pci_remove,
 	.suspend	= rtl8180_suspend,
 	.resume		= rtl8180_resume,
 	.shutdown	= rtl8180_shutdown,
@@ -211,7 +202,7 @@ static struct net_device_stats *rtl8180_stats(struct net_device *dev);
 void rtl8180_commit(struct net_device *dev);
 void rtl8180_start_tx_beacon(struct net_device *dev);
 
-static struct proc_dir_entry *rtl8180_proc = NULL;
+static struct proc_dir_entry *rtl8180_proc;
 
 static int proc_get_registers(char *page, char **start,
 			  off_t offset, int count,
@@ -323,7 +314,6 @@ void rtl8180_proc_remove_one(struct net_device *dev)
 		remove_proc_entry("stats-tx", priv->dir_dev);
 		remove_proc_entry("stats-rx", priv->dir_dev);
 		remove_proc_entry("registers", priv->dir_dev);
-		remove_proc_entry(dev->name, rtl8180_proc);
 		priv->dir_dev = NULL;
 	}
 }
@@ -444,24 +434,6 @@ void buffer_free(struct net_device *dev, struct buffer **buffer, int len, short
 	*buffer = NULL;
 }
 
-void print_buffer(u32 *buffer, int len)
-{
-	int i;
-	u8 *buf = (u8 *)buffer;
-
-	printk("ASCII BUFFER DUMP (len: %x):\n", len);
-
-	for (i = 0; i < len; i++)
-		printk("%c", buf[i]);
-
-	printk("\nBINARY BUFFER DUMP (len: %x):\n", len);
-
-	for (i = 0; i < len; i++)
-		printk("%02x", buf[i]);
-
-	printk("\n");
-}
-
 int get_curr_tx_free_desc(struct net_device *dev, int priority)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
@@ -635,74 +607,6 @@ void fix_rx_fifo(struct net_device *dev)
 	set_nic_rxring(dev);
 }
 
-unsigned char QUALITY_MAP[] = {
-	0x64, 0x64, 0x64, 0x63, 0x63, 0x62, 0x62, 0x61,
-	0x61, 0x60, 0x60, 0x5f, 0x5f, 0x5e, 0x5d, 0x5c,
-	0x5b, 0x5a, 0x59, 0x57, 0x56, 0x54, 0x52, 0x4f,
-	0x4c, 0x49, 0x45, 0x41, 0x3c, 0x37, 0x31, 0x29,
-	0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-	0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x21, 0x20,
-	0x20, 0x20, 0x20, 0x1f, 0x1f, 0x1e, 0x1e, 0x1e,
-	0x1d, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a, 0x19, 0x19,
-	0x18, 0x17, 0x16, 0x15, 0x14, 0x12, 0x11, 0x0f,
-	0x0e, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x01, 0x00
-};
-
-unsigned char STRENGTH_MAP[] = {
-	0x64, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e,
-	0x5d, 0x5c, 0x5b, 0x5a, 0x57, 0x54, 0x52, 0x50,
-	0x4e, 0x4c, 0x4a, 0x48, 0x46, 0x44, 0x41, 0x3f,
-	0x3c, 0x3a, 0x37, 0x36, 0x36, 0x1c, 0x1c, 0x1b,
-	0x1b, 0x1a, 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17,
-	0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13,
-	0x13, 0x12, 0x12, 0x11, 0x11, 0x10, 0x10, 0x0f,
-	0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b,
-	0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07,
-	0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x02, 0x00
-};
-
-void rtl8180_RSSI_calc(struct net_device *dev, u8 *rssi, u8 *qual)
-{
-	u32 temp;
-	u32 temp2;
-	u32 q;
-	u32 orig_qual;
-	u8  _rssi;
-
-	q = *qual;
-	orig_qual = *qual;
-	_rssi = 0; /* avoid gcc complains.. */
-
-	if (q <= 0x4e) {
-		temp = QUALITY_MAP[q];
-	} else {
-		if (q & 0x80)
-			temp = 0x32;
-		else
-			temp = 1;
-	}
-
-	*qual = temp;
-	temp2 = *rssi;
-
-	if (_rssi < 0x64) {
-		if (_rssi == 0)
-			*rssi = 1;
-	} else {
-		*rssi = 0x64;
-	}
-
-	return;
-}
-
-void rtl8180_irq_enable(struct net_device *dev)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	priv->irq_enabled = 1;
-	write_nic_word(dev, INTA_MASK, priv->irq_mask);
-}
-
 void rtl8180_irq_disable(struct net_device *dev)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
@@ -724,7 +628,6 @@ void rtl8180_set_mode(struct net_device *dev, int mode)
 	write_nic_byte(dev, EPROM_CMD, ecmd);
 }
 
-void rtl8180_adapter_start(struct net_device *dev);
 void rtl8180_beacon_tx_enable(struct net_device *dev);
 
 void rtl8180_update_msr(struct net_device *dev)
@@ -771,57 +674,6 @@ void rtl8180_set_chan(struct net_device *dev, short ch)
 	priv->rf_set_chan(dev, priv->chan);
 }
 
-void rtl8180_rx_enable(struct net_device *dev)
-{
-	u8 cmd;
-	u32 rxconf;
-	/* for now we accept data, management & ctl frame*/
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	rxconf = read_nic_dword(dev, RX_CONF);
-	rxconf = rxconf & ~MAC_FILTER_MASK;
-	rxconf = rxconf | (1<<ACCEPT_MNG_FRAME_SHIFT);
-	rxconf = rxconf | (1<<ACCEPT_DATA_FRAME_SHIFT);
-	rxconf = rxconf | (1<<ACCEPT_BCAST_FRAME_SHIFT);
-	rxconf = rxconf | (1<<ACCEPT_MCAST_FRAME_SHIFT);
-	if (dev->flags & IFF_PROMISC)
-		DMESG("NIC in promisc mode");
-
-	if (priv->ieee80211->iw_mode == IW_MODE_MONITOR || \
-	   dev->flags & IFF_PROMISC) {
-		rxconf = rxconf | (1<<ACCEPT_ALLMAC_FRAME_SHIFT);
-	} else {
-		rxconf = rxconf | (1<<ACCEPT_NICMAC_FRAME_SHIFT);
-	}
-
-	if (priv->ieee80211->iw_mode == IW_MODE_MONITOR) {
-		rxconf = rxconf | (1<<ACCEPT_CTL_FRAME_SHIFT);
-		rxconf = rxconf | (1<<ACCEPT_ICVERR_FRAME_SHIFT);
-		rxconf = rxconf | (1<<ACCEPT_PWR_FRAME_SHIFT);
-	}
-
-	if (priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
-		rxconf = rxconf | (1<<ACCEPT_CRCERR_FRAME_SHIFT);
-
-	rxconf = rxconf & ~RX_FIFO_THRESHOLD_MASK;
-	rxconf = rxconf | (RX_FIFO_THRESHOLD_NONE << RX_FIFO_THRESHOLD_SHIFT);
-
-	rxconf = rxconf | (1<<RX_AUTORESETPHY_SHIFT);
-	rxconf = rxconf & ~MAX_RX_DMA_MASK;
-	rxconf = rxconf | (MAX_RX_DMA_2048<<MAX_RX_DMA_SHIFT);
-
-	rxconf = rxconf | RCR_ONLYERLPKT;
-
-	rxconf = rxconf & ~RCR_CS_MASK;
-
-	write_nic_dword(dev, RX_CONF, rxconf);
-
-	fix_rx_fifo(dev);
-
-	cmd = read_nic_byte(dev, CMD);
-	write_nic_byte(dev, CMD, cmd | (1<<CMD_RX_ENABLE_SHIFT));
-}
-
 void set_nic_txring(struct net_device *dev)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
@@ -835,80 +687,6 @@ void set_nic_txring(struct net_device *dev)
 	write_nic_dword(dev, TX_BEACON_RING_ADDR, priv->txbeaconringdma);
 }
 
-void rtl8180_conttx_enable(struct net_device *dev)
-{
-	u32 txconf;
-
-	txconf = read_nic_dword(dev, TX_CONF);
-	txconf = txconf & ~TX_LOOPBACK_MASK;
-	txconf = txconf | (TX_LOOPBACK_CONTINUE<<TX_LOOPBACK_SHIFT);
-	write_nic_dword(dev, TX_CONF, txconf);
-}
-
-void rtl8180_conttx_disable(struct net_device *dev)
-{
-	u32 txconf;
-
-	txconf = read_nic_dword(dev, TX_CONF);
-	txconf = txconf & ~TX_LOOPBACK_MASK;
-	txconf = txconf | (TX_LOOPBACK_NONE<<TX_LOOPBACK_SHIFT);
-	write_nic_dword(dev, TX_CONF, txconf);
-}
-
-void rtl8180_tx_enable(struct net_device *dev)
-{
-	u8 cmd;
-	u8 tx_agc_ctl;
-	u8 byte;
-	u32 txconf;
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	txconf = read_nic_dword(dev, TX_CONF);
-
-	byte = read_nic_byte(dev, CW_CONF);
-	byte &= ~(1<<CW_CONF_PERPACKET_CW_SHIFT);
-	byte &= ~(1<<CW_CONF_PERPACKET_RETRY_SHIFT);
-	write_nic_byte(dev, CW_CONF, byte);
-
-	tx_agc_ctl = read_nic_byte(dev, TX_AGC_CTL);
-	tx_agc_ctl &= ~(1<<TX_AGC_CTL_PERPACKET_GAIN_SHIFT);
-	tx_agc_ctl &= ~(1<<TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT);
-	tx_agc_ctl |= (1<<TX_AGC_CTL_FEEDBACK_ANT);
-	write_nic_byte(dev, TX_AGC_CTL, tx_agc_ctl);
-	write_nic_byte(dev, 0xec, 0x3f); /* Disable early TX */
-
-	txconf = txconf & ~(1<<TCR_PROBE_NOTIMESTAMP_SHIFT);
-
-	txconf = txconf & ~TX_LOOPBACK_MASK;
-	txconf = txconf | (TX_LOOPBACK_NONE<<TX_LOOPBACK_SHIFT);
-	txconf = txconf & ~TCR_DPRETRY_MASK;
-	txconf = txconf & ~TCR_RTSRETRY_MASK;
-	txconf = txconf | (priv->retry_data<<TX_DPRETRY_SHIFT);
-	txconf = txconf | (priv->retry_rts<<TX_RTSRETRY_SHIFT);
-	txconf = txconf & ~(1<<TX_NOCRC_SHIFT);
-
-	if (priv->hw_plcp_len)
-		txconf = txconf & ~TCR_PLCP_LEN;
-	else
-		txconf = txconf | TCR_PLCP_LEN;
-
-	txconf = txconf & ~TCR_MXDMA_MASK;
-	txconf = txconf | (TCR_MXDMA_2048<<TCR_MXDMA_SHIFT);
-	txconf = txconf | TCR_CWMIN;
-	txconf = txconf | TCR_DISCW;
-
-	txconf = txconf | (1 << TX_NOICV_SHIFT);
-
-	write_nic_dword(dev, TX_CONF, txconf);
-
-	fix_tx_fifo(dev);
-
-	cmd = read_nic_byte(dev, CMD);
-	write_nic_byte(dev, CMD, cmd | (1<<CMD_TX_ENABLE_SHIFT));
-
-	write_nic_dword(dev, TX_CONF, txconf);
-}
-
 void rtl8180_beacon_tx_enable(struct net_device *dev)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
@@ -936,8 +714,8 @@ void rtl8180_rtx_disable(struct net_device *dev)
 	struct r8180_priv *priv = ieee80211_priv(dev);
 
 	cmd = read_nic_byte(dev, CMD);
-	write_nic_byte(dev, CMD, cmd & ~\
-		       ((1<<CMD_RX_ENABLE_SHIFT)|(1<<CMD_TX_ENABLE_SHIFT)));
+	write_nic_byte(dev, CMD, cmd &
+		       ~((1<<CMD_RX_ENABLE_SHIFT)|(1<<CMD_TX_ENABLE_SHIFT)));
 	force_pci_posting(dev);
 	mdelay(10);
 
@@ -1481,8 +1259,7 @@ void rtl8180_rx(struct net_device *dev)
 
 		pci_dma_sync_single_for_cpu(priv->pdev,
 				    priv->rxbuffer->dma,
-				    priv->rxbuffersize * \
-				    sizeof(u8),
+				    priv->rxbuffersize * sizeof(u8),
 				    PCI_DMA_FROMDEVICE);
 
 		first = *(priv->rxringtail) & (1<<29) ? 1 : 0;
@@ -1660,14 +1437,9 @@ void rtl8180_rx(struct net_device *dev)
 				dev_kfree_skb_any(priv->rx_skb);
 				priv->stats.rxnolast++;
 			}
-			/* support for prism header has been originally added by Christian */
-			if (priv->prism_hdr && priv->ieee80211->iw_mode == IW_MODE_MONITOR) {
-
-			} else {
-				priv->rx_skb = dev_alloc_skb(len+2);
-				if (!priv->rx_skb)
-					goto drop;
-			}
+			priv->rx_skb = dev_alloc_skb(len+2);
+			if (!priv->rx_skb)
+				goto drop;
 
 			priv->rx_skb_complete = 0;
 			priv->rx_skb->dev = dev;
@@ -1718,8 +1490,7 @@ void rtl8180_rx(struct net_device *dev)
 
 		pci_dma_sync_single_for_device(priv->pdev,
 				    priv->rxbuffer->dma,
-				    priv->rxbuffersize * \
-				    sizeof(u8),
+				    priv->rxbuffersize * sizeof(u8),
 				    PCI_DMA_FROMDEVICE);
 
 drop: /* this is used when we have not enough mem */
@@ -1929,7 +1700,7 @@ void rtl8180_prepare_beacon(struct net_device *dev)
  * descriptor in the ring buffer, copyes the frame in a TX buffer
  * and kicks the NIC to ensure it does the DMA transfer.
  */
-short rtl8180_tx(struct net_device *dev, u8* txbuf, int len, int priority,
+short rtl8180_tx(struct net_device *dev, u8 *txbuf, int len, int priority,
 		 short morefrag, short descfrag, int rate)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
@@ -1940,8 +1711,6 @@ short rtl8180_tx(struct net_device *dev, u8* txbuf, int len, int priority,
 	int remain;
 	int buflen;
 	int count;
-	u16 duration;
-	short ext;
 	struct buffer *buflist;
 	struct ieee80211_hdr_3addr *frag_hdr = (struct ieee80211_hdr_3addr *)txbuf;
 	u8 dest[ETH_ALEN];
@@ -2137,15 +1906,6 @@ short rtl8180_tx(struct net_device *dev, u8* txbuf, int len, int priority,
 
 		*tail = *tail | ((rate&0xf) << 24);
 
-		/* hw_plcp_len is not used for rtl8180 chip */
-		/* FIXME */
-		if (!priv->hw_plcp_len) {
-			duration = rtl8180_len2duration(len, rate, &ext);
-			*(tail+1) = *(tail+1) | ((duration & 0x7fff)<<16);
-			if (ext)
-				*(tail+1) = *(tail+1) | (1<<31); /* plcp length extension */
-		}
-
 		if (morefrag)
 			*tail = (*tail) | (1<<17); /* more fragment */
 		if (!remain)
@@ -2223,10 +1983,10 @@ void rtl8180_link_change(struct net_device *dev)
 	write_nic_dword(dev, BSSID, ((u32 *)net->bssid)[0]);
 	write_nic_word(dev, BSSID+4, ((u16 *)net->bssid)[2]);
 
-	beacon_interval  = read_nic_dword(dev, BEACON_INTERVAL);
+	beacon_interval  = read_nic_word(dev, BEACON_INTERVAL);
 	beacon_interval &= ~BEACON_INTERVAL_MASK;
 	beacon_interval |= net->beacon_interval;
-	write_nic_dword(dev, BEACON_INTERVAL, beacon_interval);
+	write_nic_word(dev, BEACON_INTERVAL, beacon_interval);
 
 	rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
 
@@ -2279,8 +2039,6 @@ short rtl8180_is_tx_queue_empty(struct net_device *dev)
 				return 0;
 	return 1;
 }
-/* FIXME FIXME 5msecs is random */
-#define HW_WAKE_DELAY 5
 
 void rtl8180_hw_wakeup(struct net_device *dev)
 {
@@ -2397,7 +2155,8 @@ void rtl8180_wmm_param_update(struct work_struct *work)
 					write_nic_dword(dev, AC_VO_PARAM, u4bAcParam);
 					break;
 				default:
-					printk(KERN_WARNING "SetHwReg8185():invalid ACI: %d!\n", eACI);
+					pr_warn("SetHwReg8185():invalid ACI: %d!\n",
+						eACI);
 					break;
 				}
 			}
@@ -2436,7 +2195,8 @@ void rtl8180_wmm_param_update(struct work_struct *work)
 				write_nic_dword(dev, AC_VO_PARAM, u4bAcParam);
 				break;
 			default:
-				printk(KERN_WARNING "SetHwReg8185(): invalid ACI: %d !\n", eACI);
+				pr_warn("SetHwReg8185(): invalid ACI: %d !\n",
+					eACI);
 				break;
 			}
 		}
@@ -2444,7 +2204,6 @@ void rtl8180_wmm_param_update(struct work_struct *work)
 	}
 }
 
-void rtl8180_tx_irq_wq(struct work_struct *work);
 void rtl8180_restart_wq(struct work_struct *work);
 /* void rtl8180_rq_tx_ack(struct work_struct *work); */
 void rtl8180_watch_dog_wq(struct work_struct *work);
@@ -2455,7 +2214,7 @@ void rtl8180_watch_dog(struct net_device *dev);
 
 void watch_dog_adaptive(unsigned long data)
 {
-	struct r8180_priv* priv = ieee80211_priv((struct net_device *)data);
+	struct r8180_priv *priv = ieee80211_priv((struct net_device *)data);
 
 	if (!priv->up) {
 		DMESG("<----watch_dog_adaptive():driver is not up!\n");
@@ -2601,8 +2360,7 @@ short rtl8180_init(struct net_device *dev)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
 	u16 word;
-	u16 version;
-	u32 usValue;
+	u16 usValue;
 	u16 tmpu16;
 	int i, j;
 	struct eeprom_93cx6 eeprom;
@@ -2634,7 +2392,6 @@ short rtl8180_init(struct net_device *dev)
 	priv->RFChangeInProgress = false;
 	priv->SetRFPowerStateInProgress = false;
 	priv->RFProgType = 0;
-	priv->bInHctTest = false;
 
 	priv->irq_enabled = 0;
 
@@ -2658,14 +2415,12 @@ short rtl8180_init(struct net_device *dev)
 	priv->ieee80211->ps_is_queue_empty = rtl8180_is_tx_queue_empty;
 
 	priv->hw_wep = hwwep;
-	priv->prism_hdr = 0;
 	priv->dev = dev;
 	priv->retry_rts = DEFAULT_RETRY_RTS;
 	priv->retry_data = DEFAULT_RETRY_DATA;
 	priv->RFChangeInProgress = false;
 	priv->SetRFPowerStateInProgress = false;
 	priv->RFProgType = 0;
-	priv->bInHctTest = false;
 	priv->bInactivePs = true; /* false; */
 	priv->ieee80211->bInactivePs = priv->bInactivePs;
 	priv->bSwRfProcessing = false;
@@ -2726,7 +2481,6 @@ short rtl8180_init(struct net_device *dev)
 	priv->NumTxOkTotal = 0;
 	priv->NumTxUnicast = 0;
 	priv->keepAliveLevel = DEFAULT_KEEP_ALIVE_LEVEL;
-	priv->PowerProfile = POWER_PROFILE_AC;
 	priv->CurrRetryCnt = 0;
 	priv->LastRetryCnt = 0;
 	priv->LastTxokCnt = 0;
@@ -2748,15 +2502,12 @@ short rtl8180_init(struct net_device *dev)
 	priv->RegBModeGainStage = 1;
 
 	priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
-	spin_lock_init(&priv->irq_lock);
 	spin_lock_init(&priv->irq_th_lock);
 	spin_lock_init(&priv->tx_lock);
 	spin_lock_init(&priv->ps_lock);
 	spin_lock_init(&priv->rf_ps_lock);
 	sema_init(&priv->wx_sem, 1);
-	sema_init(&priv->rf_state, 1);
 	INIT_WORK(&priv->reset_wq, (void *)rtl8180_restart_wq);
-	INIT_WORK(&priv->tx_irq_wq, (void *)rtl8180_tx_irq_wq);
 	INIT_DELAYED_WORK(&priv->ieee80211->hw_wakeup_wq,
 			  (void *)rtl8180_hw_wakeup_wq);
 	INIT_DELAYED_WORK(&priv->ieee80211->hw_sleep_wq,
@@ -2798,19 +2549,14 @@ short rtl8180_init(struct net_device *dev)
 	priv->ieee80211->stop_send_beacons = rtl8180_beacon_tx_disable;
 	priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
 
-	priv->MWIEnable = 0;
-
 	priv->ShortRetryLimit = 7;
 	priv->LongRetryLimit = 7;
 	priv->EarlyRxThreshold = 7;
 
-	priv->CSMethod = (0x01 << 29);
-
-	priv->TransmitConfig =	TCR_DurProcMode_OFFSET |
+	priv->TransmitConfig =	(1<<TCR_DurProcMode_OFFSET) |
 				(7<<TCR_MXDMA_OFFSET) |
 				(priv->ShortRetryLimit<<TCR_SRL_OFFSET) |
-				(priv->LongRetryLimit<<TCR_LRL_OFFSET) |
-				(0 ? TCR_SAT : 0);
+				(priv->LongRetryLimit<<TCR_LRL_OFFSET);
 
 	priv->ReceiveConfig =	RCR_AMF | RCR_ADF | RCR_ACF |
 				RCR_AB | RCR_AM | RCR_APM |
@@ -2832,47 +2578,35 @@ short rtl8180_init(struct net_device *dev)
 	priv->InitialGain = 6;
 
 	DMESG("MAC controller is a RTL8187SE b/g");
-	priv->phy_ver = 2;
 
 	priv->ieee80211->modulation |= IEEE80211_OFDM_MODULATION;
 	priv->ieee80211->short_slot = 1;
 
-	/* just for sync 85 */
-	priv->enable_gpio0 = 0;
-
-	eeprom_93cx6_read(&eeprom, EEPROM_SW_REVD_OFFSET, &eeprom_val);
-	usValue = eeprom_val;
-	DMESG("usValue is 0x%x\n", usValue);
+	eeprom_93cx6_read(&eeprom, EEPROM_SW_REVD_OFFSET, &usValue);
+	DMESG("usValue is %#hx\n", usValue);
 	/* 3Read AntennaDiversity */
 
 	/* SW Antenna Diversity. */
-	if ((usValue & EEPROM_SW_AD_MASK) != EEPROM_SW_AD_ENABLE)
-		priv->EEPROMSwAntennaDiversity = false;
-	else
-		priv->EEPROMSwAntennaDiversity = true;
+	priv->EEPROMSwAntennaDiversity = (usValue & EEPROM_SW_AD_MASK) ==
+		EEPROM_SW_AD_ENABLE;
 
 	/* Default Antenna to use. */
-	if ((usValue & EEPROM_DEF_ANT_MASK) != EEPROM_DEF_ANT_1)
-		priv->EEPROMDefaultAntenna1 = false;
-	else
-		priv->EEPROMDefaultAntenna1 = true;
+	priv->EEPROMDefaultAntenna1 = (usValue & EEPROM_DEF_ANT_MASK) ==
+		EEPROM_DEF_ANT_1;
 
 	if (priv->RegSwAntennaDiversityMechanism == 0) /* Auto */
 		/* 0: default from EEPROM. */
 		priv->bSwAntennaDiverity = priv->EEPROMSwAntennaDiversity;
 	else
 		/* 1:disable antenna diversity, 2: enable antenna diversity. */
-		priv->bSwAntennaDiverity = ((priv->RegSwAntennaDiversityMechanism == 1) ? false : true);
+		priv->bSwAntennaDiverity = priv->RegSwAntennaDiversityMechanism == 2;
 
 	if (priv->RegDefaultAntenna == 0)
 		/* 0: default from EEPROM. */
 		priv->bDefaultAntenna1 = priv->EEPROMDefaultAntenna1;
 	else
 		/* 1: main, 2: aux. */
-		priv->bDefaultAntenna1 = ((priv->RegDefaultAntenna == 2) ? true : false);
-
-	/* rtl8185 can calc plcp len in HW. */
-	priv->hw_plcp_len = 1;
+		priv->bDefaultAntenna1 = priv->RegDefaultAntenna == 2;
 
 	priv->plcp_preamble_mode = 2;
 	/* the eeprom type is stored in RCR register bit #6 */
@@ -2909,18 +2643,6 @@ short rtl8180_init(struct net_device *dev)
 	if ((tmpu16 & EEPROM_THERMAL_METER_ENABLE) >> 13)
 		priv->bTxPowerTrack = true;
 
-	eeprom_93cx6_read(&eeprom, EPROM_TXPW_BASE, &word);
-	priv->cck_txpwr_base = word & 0xf;
-	priv->ofdm_txpwr_base = (word>>4) & 0xf;
-
-	eeprom_93cx6_read(&eeprom, EPROM_VERSION, &version);
-	DMESG("EEPROM version %x", version);
-	priv->rcr_csense = 3;
-
-	eeprom_93cx6_read(&eeprom, ENERGY_TRESHOLD, &eeprom_val);
-	priv->cs_treshold = (eeprom_val & 0xff00) >> 8;
-
-	eeprom_93cx6_read(&eeprom, RFCHIPID, &eeprom_val);
 	priv->rf_sleep = rtl8225z4_rf_sleep;
 	priv->rf_wakeup = rtl8225z4_rf_wakeup;
 	DMESGW("**PLEASE** REPORT SUCCESSFUL/UNSUCCESSFUL TO Realtek!");
@@ -3084,100 +2806,6 @@ void write_phy_cck(struct net_device *dev, u8 adr, u32 data)
 	rtl8185_write_phy(dev, adr, data | 0x10000);
 }
 
-void rtl8185_set_rate(struct net_device *dev)
-{
-	int i;
-	u16 word;
-	int basic_rate, min_rr_rate, max_rr_rate;
-
-	basic_rate = ieeerate2rtlrate(240);
-	min_rr_rate = ieeerate2rtlrate(60);
-	max_rr_rate = ieeerate2rtlrate(240);
-
-	write_nic_byte(dev, RESP_RATE,
-		       max_rr_rate<<MAX_RESP_RATE_SHIFT |
-		       min_rr_rate<<MIN_RESP_RATE_SHIFT);
-
-	word  = read_nic_word(dev, BRSR);
-	word &= ~BRSR_MBR_8185;
-
-	for (i = 0; i <= basic_rate; i++)
-		word |= (1<<i);
-
-	write_nic_word(dev, BRSR, word);
-}
-
-void rtl8180_adapter_start(struct net_device *dev)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	rtl8180_rtx_disable(dev);
-	rtl8180_reset(dev);
-
-	/* enable beacon timeout, beacon TX ok and err
-	 * LP tx ok and err, HP TX ok and err, NP TX ok and err,
-	 * RX ok and ERR, and GP timer
-	 */
-	priv->irq_mask = 0x6fcf;
-
-	priv->dma_poll_mask = 0;
-
-	rtl8180_beacon_tx_disable(dev);
-
-	rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
-	write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
-	write_nic_word(dev, MAC4, ((u32 *)dev->dev_addr)[1] & 0xffff);
-	rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-
-	rtl8180_update_msr(dev);
-
-	/* These might be unnecessary since we do in rx_enable / tx_enable */
-	fix_rx_fifo(dev);
-	fix_tx_fifo(dev);
-
-	rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
-
-	/*
-	 * The following is very strange. seems to be that 1 means test mode,
-	 * but we need to acknowledges the nic when a packet is ready
-	 * although we set it to 0
-	 */
-
-	write_nic_byte(dev,
-		       CONFIG2, read_nic_byte(dev, CONFIG2) & ~\
-		       (1<<CONFIG2_DMA_POLLING_MODE_SHIFT));
-	/* ^the nic isn't in test mode */
-	write_nic_byte(dev,
-		       CONFIG2, read_nic_byte(dev, CONFIG2)|(1<<4));
-
-	rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-
-	write_nic_dword(dev, INT_TIMEOUT, 0);
-
-	write_nic_byte(dev, WPA_CONFIG, 0);
-
-	rtl8180_no_hw_wep(dev);
-
-	rtl8185_set_rate(dev);
-	write_nic_byte(dev, RATE_FALLBACK, 0x81);
-
-	write_nic_byte(dev, GP_ENABLE, read_nic_byte(dev, GP_ENABLE) & ~(1<<6));
-
-	/* FIXME cfg 3 ClkRun enable - isn't it ReadOnly ? */
-	rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
-	write_nic_byte(dev, CONFIG3, read_nic_byte(dev, CONFIG3)
-		       | (1 << CONFIG3_CLKRUN_SHIFT));
-	rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
-
-	priv->rf_init(dev);
-
-	if (priv->rf_set_sens != NULL)
-		priv->rf_set_sens(dev, priv->sens);
-	rtl8180_irq_enable(dev);
-
-	netif_start_queue(dev);
-}
-
 /*
  * This configures registers for beacon tx and enables it via
  * rtl8180_beacon_tx_enable(). rtl8180_beacon_tx_disable() might
@@ -3299,8 +2927,6 @@ static void MgntLinkKeepAlive(struct r8180_priv *priv)
 	}
 }
 
-static u8 read_acadapter_file(char *filename);
-
 void rtl8180_watch_dog(struct net_device *dev)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
@@ -3333,12 +2959,7 @@ void rtl8180_watch_dog(struct net_device *dev)
 	MgntLinkKeepAlive(priv);
 
 	/* YJ,add,080828,for LPS */
-	if (priv->PowerProfile == POWER_PROFILE_BATTERY)
-		priv->bLeisurePs = true;
-	else if (priv->PowerProfile == POWER_PROFILE_AC) {
-		LeisurePSLeave(priv);
-		priv->bLeisurePs = false;
-	}
+	LeisurePSLeave(priv);
 
 	if (priv->ieee80211->state == IEEE80211_LINKED) {
 		priv->link_detect.NumRxOkInPeriod = priv->ieee80211->NumRxDataInPeriod;
@@ -3555,7 +3176,7 @@ static const struct net_device_ops rtl8180_netdev_ops = {
 	.ndo_start_xmit		= ieee80211_rtl_xmit,
 };
 
-static int __devinit rtl8180_pci_probe(struct pci_dev *pdev,
+static int rtl8180_pci_probe(struct pci_dev *pdev,
 				       const struct pci_device_id *id)
 {
 	unsigned long ioaddr = 0;
@@ -3638,7 +3259,8 @@ static int __devinit rtl8180_pci_probe(struct pci_dev *pdev,
 
 	netif_carrier_off(dev);
 
-	register_netdev(dev);
+	if (register_netdev(dev))
+		goto fail1;
 
 	rtl8180_proc_init_one(dev);
 
@@ -3667,7 +3289,7 @@ fail_free:
 	return ret;
 }
 
-static void __devexit rtl8180_pci_remove(struct pci_dev *pdev)
+static void rtl8180_pci_remove(struct pci_dev *pdev)
 {
 	struct r8180_priv *priv;
 	struct net_device *dev = pci_get_drvdata(pdev);
@@ -3721,27 +3343,27 @@ static int __init rtl8180_pci_module_init(void)
 
 	ret = ieee80211_crypto_init();
 	if (ret) {
-		printk(KERN_ERR "ieee80211_crypto_init() failed %d\n", ret);
+		pr_err("ieee80211_crypto_init() failed %d\n", ret);
 		return ret;
 	}
 	ret = ieee80211_crypto_tkip_init();
 	if (ret) {
-		printk(KERN_ERR "ieee80211_crypto_tkip_init() failed %d\n", ret);
+		pr_err("ieee80211_crypto_tkip_init() failed %d\n", ret);
 		return ret;
 	}
 	ret = ieee80211_crypto_ccmp_init();
 	if (ret) {
-		printk(KERN_ERR "ieee80211_crypto_ccmp_init() failed %d\n", ret);
+		pr_err("ieee80211_crypto_ccmp_init() failed %d\n", ret);
 		return ret;
 	}
 	ret = ieee80211_crypto_wep_init();
 	if (ret) {
-		printk(KERN_ERR "ieee80211_crypto_wep_init() failed %d\n", ret);
+		pr_err("ieee80211_crypto_wep_init() failed %d\n", ret);
 		return ret;
 	}
 
-	printk(KERN_INFO "\nLinux kernel driver for RTL8180 / RTL8185 based WLAN cards\n");
-	printk(KERN_INFO "Copyright (c) 2004-2005, Andrea Merello\n");
+	pr_info("\nLinux kernel driver for RTL8180 / RTL8185 based WLAN cards\n");
+	pr_info("Copyright (c) 2004-2005, Andrea Merello\n");
 	DMESG("Initializing module");
 	DMESG("Wireless extensions version %d", WIRELESS_EXT);
 	rtl8180_proc_module_init();
@@ -3844,7 +3466,7 @@ void rtl8180_tx_isr(struct net_device *dev, int pri, short error)
 		return ;
 	}
 
-	nicv = (u32 *)((nic - nicbegin) + (u8*)begin);
+	nicv = (u32 *)((nic - nicbegin) + (u8 *)begin);
 	if ((head <= tail && (nicv > tail || nicv < head)) ||
 		(head > tail && (nicv > tail && nicv < head))) {
 			DMESGW("nic has lost pointer");
@@ -3932,15 +3554,6 @@ void rtl8180_tx_isr(struct net_device *dev, int pri, short error)
 	spin_unlock_irqrestore(&priv->tx_lock, flag);
 }
 
-void rtl8180_tx_irq_wq(struct work_struct *work)
-{
-	struct delayed_work *dwork = to_delayed_work(work);
-	struct ieee80211_device * ieee = (struct ieee80211_device *)
-		container_of(dwork, struct ieee80211_device, watch_dog_wq);
-	struct net_device *dev = ieee->dev;
-
-	rtl8180_tx_isr(dev, MANAGE_PRIORITY, 0);
-}
 irqreturn_t rtl8180_interrupt(int irq, void *netdev, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) netdev;
@@ -4013,7 +3626,7 @@ irqreturn_t rtl8180_interrupt(int irq, void *netdev, struct pt_regs *regs)
 		priv->stats.txbkperr++;
 		priv->ieee80211->stats.tx_errors++;
 		rtl8180_tx_isr(dev, BK_PRIORITY, 1);
-		rtl8180_try_wake_queue(dev, BE_PRIORITY);
+		rtl8180_try_wake_queue(dev, BK_PRIORITY);
 	}
 
 	if (inta & ISR_TBEDER) { /* corresponding to BE_PRIORITY */
@@ -4067,6 +3680,7 @@ irqreturn_t rtl8180_interrupt(int irq, void *netdev, struct pt_regs *regs)
 		priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
 		priv->stats.txnpokint++;
 		rtl8180_tx_isr(dev, NORM_PRIORITY, 0);
+		rtl8180_try_wake_queue(dev, NORM_PRIORITY);
 	}
 
 	if (inta & ISR_TLPDOK) { /* Low priority tx ok */
@@ -4113,10 +3727,7 @@ void GPIOChangeRFWorkItemCallBack(struct work_struct *work)
 	char *argv[3];
 	static char *RadioPowerPath = "/etc/acpi/events/RadioPower.sh";
 	static char *envp[] = {"HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL};
-	static int readf_count = 0;
-
-	if (readf_count % 10 == 0)
-		priv->PowerProfile = read_acadapter_file("/proc/acpi/ac_adapter/AC0/state");
+	static int readf_count;
 
 	readf_count = (readf_count+1)%0xffff;
 	/* We should turn off LED before polling FF51[4]. */
@@ -4162,10 +3773,5 @@ void GPIOChangeRFWorkItemCallBack(struct work_struct *work)
 	}
 }
 
-static u8 read_acadapter_file(char *filename)
-{
-	return 0;
-}
-
 module_init(rtl8180_pci_module_init);
 module_exit(rtl8180_pci_module_exit);
diff --git a/drivers/staging/rtl8187se/r8180_dm.h b/drivers/staging/rtl8187se/r8180_dm.h
index b775825..732c06a 100644
--- a/drivers/staging/rtl8187se/r8180_dm.h
+++ b/drivers/staging/rtl8187se/r8180_dm.h
@@ -13,10 +13,10 @@ bool CheckDig(struct net_device *dev);
 bool CheckHighPower(struct net_device *dev);
 void rtl8180_hw_dig_wq(struct work_struct *work);
 void rtl8180_tx_pw_wq(struct work_struct *work);
-void rtl8180_rate_adapter(struct work_struct * work);
+void rtl8180_rate_adapter(struct work_struct *work);
 void TxPwrTracking87SE(struct net_device *dev);
 bool CheckTxPwrTracking(struct net_device *dev);
-void rtl8180_rate_adapter(struct work_struct * work);
+void rtl8180_rate_adapter(struct work_struct *work);
 void timer_rate_adaptive(unsigned long data);
 
 
diff --git a/drivers/staging/rtl8187se/r8180_rtl8225.h b/drivers/staging/rtl8187se/r8180_rtl8225.h
index 494ea86..c6f2128 100644
--- a/drivers/staging/rtl8187se/r8180_rtl8225.h
+++ b/drivers/staging/rtl8187se/r8180_rtl8225.h
@@ -23,8 +23,8 @@ void rtl8225z2_rf_init(struct net_device *dev);
 void rtl8225z2_rf_set_chan(struct net_device *dev, short ch);
 void rtl8225z2_rf_close(struct net_device *dev);
 
-void RF_WriteReg(struct net_device *dev, u8 offset, u32	data);
-u32 RF_ReadReg(struct net_device *dev, u8 offset);
+void RF_WriteReg(struct net_device *dev, u8 offset, u16 data);
+u16 RF_ReadReg(struct net_device *dev, u8 offset);
 
 void rtl8180_set_mode(struct net_device *dev, int mode);
 void rtl8180_set_mode(struct net_device *dev, int mode);
diff --git a/drivers/staging/rtl8187se/r8180_rtl8225z2.c b/drivers/staging/rtl8187se/r8180_rtl8225z2.c
index d28c1d9..c592f79 100644
--- a/drivers/staging/rtl8187se/r8180_rtl8225z2.c
+++ b/drivers/staging/rtl8187se/r8180_rtl8225z2.c
@@ -15,7 +15,6 @@
 
 #include "ieee80211/dot11d.h"
 
-
 static void write_rtl8225(struct net_device *dev, u8 adr, u16 data)
 {
 	int i;
@@ -76,22 +75,6 @@ static void write_rtl8225(struct net_device *dev, u8 adr, u16 data)
 	rtl8185_rf_pins_enable(dev);
 }
 
-static const u16 rtl8225bcd_rxgain[] = {
-	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
-	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
-	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
-	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
-	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
-	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
-	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
-	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
-	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
-	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
-	0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
-	0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
-
-};
-
 static const u8 rtl8225_agc[] = {
 	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
 	0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
@@ -111,122 +94,12 @@ static const u8 rtl8225_agc[] = {
 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
 };
 
-static const u8 rtl8225_gain[] = {
-	0x23, 0x88, 0x7c, 0xa5,	/* -82dBm */
-	0x23, 0x88, 0x7c, 0xb5,	/* -82dBm */
-	0x23, 0x88, 0x7c, 0xc5,	/* -82dBm */
-	0x33, 0x80, 0x79, 0xc5,	/* -78dBm */
-	0x43, 0x78, 0x76, 0xc5,	/* -74dBm */
-	0x53, 0x60, 0x73, 0xc5,	/* -70dBm */
-	0x63, 0x58, 0x70, 0xc5,	/* -66dBm */
-};
-
-static const u8 rtl8225_tx_gain_cck_ofdm[] = {
-	0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
-};
-
-static const u8 rtl8225_tx_power_cck[] = {
-	0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
-	0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
-	0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
-	0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
-	0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
-	0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
-};
-
-static const u8 rtl8225_tx_power_cck_ch14[] = {
-	0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
-	0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
-	0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
-	0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
-	0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
-	0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
-};
-
-static const u8 rtl8225_tx_power_ofdm[] = {
-	0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
-};
-
 static const u32 rtl8225_chan[] = {
 	0,
 	0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380,
 	0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A,
 };
 
-static void rtl8225_SetTXPowerLevel(struct net_device *dev, short ch)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	int GainIdx;
-	int GainSetting;
-	int i;
-	u8 power;
-	const u8 *cck_power_table;
-	u8 max_cck_power_level;
-	u8 max_ofdm_power_level;
-	u8 min_ofdm_power_level;
-	u8 cck_power_level = 0xff & priv->chtxpwr[ch];
-	u8 ofdm_power_level = 0xff & priv->chtxpwr_ofdm[ch];
-
-	max_cck_power_level = 35;
-	max_ofdm_power_level = 35;
-	min_ofdm_power_level = 0;
-
-	if (cck_power_level > max_cck_power_level)
-		cck_power_level = max_cck_power_level;
-
-	GainIdx = cck_power_level % 6;
-	GainSetting = cck_power_level / 6;
-
-	if (ch == 14)
-		cck_power_table = rtl8225_tx_power_cck_ch14;
-	else
-		cck_power_table = rtl8225_tx_power_cck;
-
-	write_nic_byte(dev, TX_GAIN_CCK,
-		       rtl8225_tx_gain_cck_ofdm[GainSetting] >> 1);
-
-	for (i = 0; i < 8; i++) {
-		power = cck_power_table[GainIdx * 8 + i];
-		write_phy_cck(dev, 0x44 + i, power);
-	}
-
-	/* FIXME Is this delay really needed ? */
-	force_pci_posting(dev);
-	mdelay(1);
-
-	if (ofdm_power_level > (max_ofdm_power_level - min_ofdm_power_level))
-		ofdm_power_level = max_ofdm_power_level;
-	else
-		ofdm_power_level += min_ofdm_power_level;
-
-	if (ofdm_power_level > 35)
-		ofdm_power_level = 35;
-
-	GainIdx = ofdm_power_level % 6;
-	GainSetting = ofdm_power_level / 6;
-
-	rtl8185_set_anaparam2(dev, RTL8225_ANAPARAM2_ON);
-
-	write_phy_ofdm(dev, 2, 0x42);
-	write_phy_ofdm(dev, 6, 0x00);
-	write_phy_ofdm(dev, 8, 0x00);
-
-	write_nic_byte(dev, TX_GAIN_OFDM,
-		       rtl8225_tx_gain_cck_ofdm[GainSetting] >> 1);
-
-	power = rtl8225_tx_power_ofdm[GainIdx];
-
-	write_phy_ofdm(dev, 5, power);
-	write_phy_ofdm(dev, 7, power);
-
-	force_pci_posting(dev);
-	mdelay(1);
-}
-
-static const u8 rtl8225z2_threshold[] = {
-	0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd,
-};
-
 static const u8 rtl8225z2_gain_bg[] = {
 	0x23, 0x15, 0xa5, /* -82-1dBm */
 	0x23, 0x15, 0xb5, /* -82-2dBm */
@@ -259,29 +132,8 @@ static const u16 rtl8225z2_rxgain[] = {
 	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
 	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
 	0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
-	0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
-
-};
+	0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb
 
-static const u8 ZEBRA2_CCK_OFDM_GAIN_SETTING[] = {
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
-	0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
-	0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
-	0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
-	0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
-};
-
-static const u8 rtl8225z2_tx_power_ofdm[] = {
-	0x42, 0x00, 0x40, 0x00, 0x40
-};
-
-static const u8 rtl8225z2_tx_power_cck_ch14[] = {
-	0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
-};
-
-static const u8 rtl8225z2_tx_power_cck[] = {
-	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
 };
 
 void rtl8225z2_set_gain(struct net_device *dev, short gain)
@@ -412,22 +264,6 @@ static u32 read_rtl8225(struct net_device *dev, u8 adr)
 	return dataRead;
 }
 
-short rtl8225_is_V_z2(struct net_device *dev)
-{
-	short vz2 = 1;
-
-	if (read_rtl8225(dev, 8) != 0x588)
-		vz2 = 0;
-	else	/* reg 9 pg 1 = 24 */
-		if (read_rtl8225(dev, 9) != 0x700)
-			vz2 = 0;
-
-	/* sw back to pg 0 */
-	write_rtl8225(dev, 0, 0xb7);
-
-	return vz2;
-}
-
 void rtl8225z2_rf_close(struct net_device *dev)
 {
 	RF_WriteReg(dev, 0x4, 0x1f);
@@ -524,8 +360,7 @@ void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch)
 	if (cck_power_level > 35)
 		cck_power_level = 35;
 
-	write_nic_byte(dev, CCK_TXAGC,
-		       (ZEBRA2_CCK_OFDM_GAIN_SETTING[(u8)cck_power_level]));
+	write_nic_byte(dev, CCK_TXAGC, cck_power_level);
 	force_pci_posting(dev);
 	mdelay(1);
 
@@ -540,8 +375,7 @@ void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch)
 		write_phy_ofdm(dev, 8, 0x40);
 	}
 
-	write_nic_byte(dev, OFDM_TXAGC,
-		       ZEBRA2_CCK_OFDM_GAIN_SETTING[(u8)ofdm_power_level]);
+	write_nic_byte(dev, OFDM_TXAGC, ofdm_power_level);
 
 	if (ofdm_power_level <= 11) {
 		write_phy_ofdm(dev, 0x07, 0x5c);
@@ -592,50 +426,13 @@ static void rtl8225_host_pci_init(struct net_device *dev)
 	write_nic_word(dev, GP_ENABLE, 0xff & (~(1 << 6)));
 }
 
-static void rtl8225_rf_set_chan(struct net_device *dev, short ch)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	short gset = (priv->ieee80211->state == IEEE80211_LINKED &&
-		ieee80211_is_54g(&priv->ieee80211->current_network)) ||
-		priv->ieee80211->iw_mode == IW_MODE_MONITOR;
-
-	rtl8225_SetTXPowerLevel(dev, ch);
-
-	write_rtl8225(dev, 0x7, rtl8225_chan[ch]);
-
-	force_pci_posting(dev);
-	mdelay(10);
-
-	if (gset) {
-		write_nic_byte(dev, SIFS, 0x22);
-		write_nic_byte(dev, DIFS, 0x14);
-	} else {
-		write_nic_byte(dev, SIFS, 0x44);
-		write_nic_byte(dev, DIFS, 0x24);
-	}
-
-	if (priv->ieee80211->state == IEEE80211_LINKED &&
-	    ieee80211_is_shortslot(&priv->ieee80211->current_network))
-		write_nic_byte(dev, SLOT, 0x9);
-	else
-		write_nic_byte(dev, SLOT, 0x14);
-
-	if (gset) {
-		write_nic_byte(dev, EIFS, 81);
-		write_nic_byte(dev, CW_VAL, 0x73);
-	} else {
-		write_nic_byte(dev, EIFS, 81);
-		write_nic_byte(dev, CW_VAL, 0xa5);
-	}
-}
-
 void rtl8225z2_rf_init(struct net_device *dev)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
 	int i;
 	short channel = 1;
-	u16	brsr;
-	u32	data, addr;
+	u16 brsr;
+	u32 data;
 
 	priv->chan = channel;
 
@@ -676,8 +473,8 @@ void rtl8225z2_rf_init(struct net_device *dev)
 
 	write_rtl8225(dev, 0x0, 0x1b7);
 
-	for (i = 0; i < 95; i++) {
-		write_rtl8225(dev, 0x1, (u8)(i + 1));
+	for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
+		write_rtl8225(dev, 0x1, i + 1);
 		write_rtl8225(dev, 0x2, rtl8225z2_rxgain[i]);
 	}
 
@@ -707,14 +504,12 @@ void rtl8225z2_rf_init(struct net_device *dev)
 
 	write_rtl8225(dev, 0x0, 0x2bf);
 
-	for (i = 0; i < 128; i++) {
-		data = rtl8225_agc[i];
-
-		addr = i + 0x80; /* enable writing AGC table */
-		write_phy_ofdm(dev, 0xb, data);
+	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+		write_phy_ofdm(dev, 0xb, rtl8225_agc[i]);
 		mdelay(1);
 
-		write_phy_ofdm(dev, 0xa, addr);
+		/* enable writing AGC table */
+		write_phy_ofdm(dev, 0xa, i + 0x80);
 		mdelay(1);
 	}
 
@@ -808,7 +603,7 @@ void rtl8225z2_rf_init(struct net_device *dev)
 	write_nic_dword(dev, 0x94, 0x15c00002);
 	rtl8185_rf_pins_enable(dev);
 
-	rtl8225_rf_set_chan(dev, priv->chan);
+	rtl8225z2_rf_set_chan(dev, priv->chan);
 }
 
 void rtl8225z2_rf_set_mode(struct net_device *dev)
diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c
index 52f63d7..156b758 100644
--- a/drivers/staging/rtl8187se/r8180_wx.c
+++ b/drivers/staging/rtl8187se/r8180_wx.c
@@ -59,8 +59,6 @@ int r8180_wx_set_key(struct net_device *dev, struct iw_request_info *info,
 	if (priv->ieee80211->bHwRadioOff)
 		return 0;
 
-	if (erq->flags & IW_ENCODE_DISABLED)
-
 	if (erq->length > 0) {
 		u32* tkey = (u32*) key;
 		priv->key0[0] = tkey[0];
diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c
index bf34319..f1db9e4 100644
--- a/drivers/staging/rtl8187se/r8185b_init.c
+++ b/drivers/staging/rtl8187se/r8185b_init.c
@@ -207,156 +207,84 @@ void SetOutputEnableOfRfPins(struct net_device *dev)
 	write_nic_word(dev, RFPinsEnable, 0x1bff);
 }
 
-static int HwHSSIThreeWire(struct net_device *dev,
-			   u8 *pDataBuf,
-			   u8 nDataBufBitCnt,
-			   int bSI,
-			   int bWrite)
+static bool HwHSSIThreeWire(struct net_device *dev,
+			    u8 *pDataBuf,
+			    bool write)
 {
-	int	bResult = 1;
 	u8	TryCnt;
 	u8	u1bTmp;
 
-	do {
-		/* Check if WE and RE are cleared. */
-		for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) {
-			u1bTmp = read_nic_byte(dev, SW_3W_CMD1);
-			if ((u1bTmp & (SW_3W_CMD1_RE|SW_3W_CMD1_WE)) == 0)
-				break;
-
-			udelay(10);
-		}
-		if (TryCnt == TC_3W_POLL_MAX_TRY_CNT) {
-			printk(KERN_ERR "rtl8187se: HwThreeWire(): CmdReg:"
-			       " %#X RE|WE bits are not clear!!\n", u1bTmp);
-			dump_stack();
-			return 0;
-		}
-
-		/* RTL8187S HSSI Read/Write Function */
-		u1bTmp = read_nic_byte(dev, RF_SW_CONFIG);
-
-		if (bSI)
-			u1bTmp |=   RF_SW_CFG_SI; /* reg08[1]=1 Serial Interface(SI) */
-
-		else
-			u1bTmp &= ~RF_SW_CFG_SI; /* reg08[1]=0 Parallel Interface(PI) */
-
-
-		write_nic_byte(dev, RF_SW_CONFIG, u1bTmp);
-
-		if (bSI) {
-			/* jong: HW SI read must set reg84[3]=0. */
-			u1bTmp = read_nic_byte(dev, RFPinsSelect);
-			u1bTmp &= ~BIT3;
-			write_nic_byte(dev, RFPinsSelect, u1bTmp);
-		}
-		/*  Fill up data buffer for write operation. */
-
-		if (bWrite) {
-			if (nDataBufBitCnt == 16) {
-				write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf));
-			} else if (nDataBufBitCnt == 64) {
-			/* RTL8187S shouldn't enter this case */
-				write_nic_dword(dev, SW_3W_DB0, *((u32 *)pDataBuf));
-				write_nic_dword(dev, SW_3W_DB1, *((u32 *)(pDataBuf + 4)));
-			} else {
-				int idx;
-				int ByteCnt = nDataBufBitCnt / 8;
-								/* printk("%d\n",nDataBufBitCnt); */
-				if ((nDataBufBitCnt % 8) != 0) {
-					printk(KERN_ERR "rtl8187se: "
-					       "HwThreeWire(): nDataBufBitCnt(%d)"
-					       " should be multiple of 8!!!\n",
-					       nDataBufBitCnt);
-					dump_stack();
-					nDataBufBitCnt += 8;
-					nDataBufBitCnt &= ~7;
-				}
-
-			       if (nDataBufBitCnt > 64) {
-					printk(KERN_ERR "rtl8187se: HwThreeWire():"
-					       " nDataBufBitCnt(%d) should <= 64!!!\n",
-					       nDataBufBitCnt);
-					dump_stack();
-					nDataBufBitCnt = 64;
-				}
+	/* Check if WE and RE are cleared. */
+	for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) {
+		u1bTmp = read_nic_byte(dev, SW_3W_CMD1);
+		if ((u1bTmp & (SW_3W_CMD1_RE|SW_3W_CMD1_WE)) == 0)
+			break;
 
-				for (idx = 0; idx < ByteCnt; idx++)
-					write_nic_byte(dev, (SW_3W_DB0+idx), *(pDataBuf+idx));
+		udelay(10);
+	}
+	if (TryCnt == TC_3W_POLL_MAX_TRY_CNT) {
+		netdev_err(dev,
+			   "HwThreeWire(): CmdReg: %#X RE|WE bits are not clear!!\n",
+			   u1bTmp);
+	return false;
+	}
 
-			}
-		} else {	/* read */
-			if (bSI) {
-				/* SI - reg274[3:0] : RF register's Address */
-				write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf));
-			} else {
-				/*  PI - reg274[15:12] : RF register's Address */
-				write_nic_word(dev, SW_3W_DB0, (*((u16 *)pDataBuf)) << 12);
-			}
-		}
+	/* RTL8187S HSSI Read/Write Function */
+	u1bTmp = read_nic_byte(dev, RF_SW_CONFIG);
+	u1bTmp |= RF_SW_CFG_SI; /* reg08[1]=1 Serial Interface(SI) */
+	write_nic_byte(dev, RF_SW_CONFIG, u1bTmp);
 
-		/* Set up command: WE or RE. */
-		if (bWrite)
-			write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_WE);
+	/* jong: HW SI read must set reg84[3]=0. */
+	u1bTmp = read_nic_byte(dev, RFPinsSelect);
+	u1bTmp &= ~BIT3;
+	write_nic_byte(dev, RFPinsSelect, u1bTmp);
+	/*  Fill up data buffer for write operation. */
 
-		else
-			write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_RE);
+	/* SI - reg274[3:0] : RF register's Address */
+	if (write)
+		write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf));
+	else
+		write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf));
 
+	/* Set up command: WE or RE. */
+	if (write)
+		write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_WE);
+	else
+		write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_RE);
 
-		/* Check if DONE is set. */
-		for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) {
-			u1bTmp = read_nic_byte(dev, SW_3W_CMD1);
-			if ((u1bTmp & SW_3W_CMD1_DONE) != 0)
-				break;
 
-			udelay(10);
-		}
+	/* Check if DONE is set. */
+	for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) {
+		u1bTmp = read_nic_byte(dev, SW_3W_CMD1);
+		if (u1bTmp & SW_3W_CMD1_DONE)
+			break;
 
-		write_nic_byte(dev, SW_3W_CMD1, 0);
+		udelay(10);
+	}
 
-		/* Read back data for read operation. */
-		if (bWrite == 0) {
-			if (bSI) {
-				/* Serial Interface : reg363_362[11:0] */
-				*((u16 *)pDataBuf) = read_nic_word(dev, SI_DATA_READ) ;
-			} else {
-				/* Parallel Interface : reg361_360[11:0] */
-				*((u16 *)pDataBuf) = read_nic_word(dev, PI_DATA_READ);
-			}
+	write_nic_byte(dev, SW_3W_CMD1, 0);
 
-			*((u16 *)pDataBuf) &= 0x0FFF;
-		}
-
-	} while (0);
+	/* Read back data for read operation. */
+	if (!write) {
+		/* Serial Interface : reg363_362[11:0] */
+		*((u16 *)pDataBuf) = read_nic_word(dev, SI_DATA_READ);
+		*((u16 *)pDataBuf) &= 0x0FFF;
+	}
 
-	return bResult;
+	return true;
 }
 
-void RF_WriteReg(struct net_device *dev, u8 offset, u32 data)
+void RF_WriteReg(struct net_device *dev, u8 offset, u16 data)
 {
-	u32 data2Write;
-	u8 len;
-
-	/* Pure HW 3-wire. */
-	data2Write = (data << 4) | (u32)(offset & 0x0f);
-	len = 16;
-
-	HwHSSIThreeWire(dev, (u8 *)(&data2Write), len, 1, 1);
+	u16 reg = (data << 4) | (offset & 0x0f);
+	HwHSSIThreeWire(dev, (u8 *)&reg, true);
 }
 
-u32 RF_ReadReg(struct net_device *dev, u8 offset)
+u16 RF_ReadReg(struct net_device *dev, u8 offset)
 {
-	u32 data2Write;
-	u8 wlen;
-	u32 dataRead;
-
-	data2Write = ((u32)(offset & 0x0f));
-	wlen = 16;
-	HwHSSIThreeWire(dev, (u8 *)(&data2Write), wlen, 1, 0);
-	dataRead = data2Write;
-
-	return dataRead;
+	u16 reg = offset & 0x0f;
+	HwHSSIThreeWire(dev, (u8 *)&reg, false);
+	return reg;
 }
 
 
@@ -472,7 +400,8 @@ void ZEBRA_Config_85BASIC_HardCode(struct net_device *dev)
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	u32			i;
 	u32	addr, data;
-	u32	u4bRegOffset, u4bRegValue, u4bRF23, u4bRF24;
+	u32 u4bRegOffset, u4bRegValue;
+	u16 u4bRF23, u4bRF24;
 	u8			u1b24E;
 	int d_cut = 0;
 
@@ -491,7 +420,7 @@ void ZEBRA_Config_85BASIC_HardCode(struct net_device *dev)
 
 	if (u4bRF23 == 0x818 && u4bRF24 == 0x70C) {
 		d_cut = 1;
-		printk(KERN_INFO "rtl8187se: card type changed from C- to D-cut\n");
+		netdev_info(dev, "card type changed from C- to D-cut\n");
 	}
 
 	/* Page0 : reg0-reg15 */
@@ -930,10 +859,7 @@ static void MacConfig_85BASIC(struct net_device *dev)
 
 u8 GetSupportedWirelessMode8185(struct net_device *dev)
 {
-	u8 btSupportedWirelessMode = 0;
-
-	btSupportedWirelessMode = (WIRELESS_MODE_B | WIRELESS_MODE_G);
-	return btSupportedWirelessMode;
+	return WIRELESS_MODE_B | WIRELESS_MODE_G;
 }
 
 void ActUpdateChannelAccessSetting(struct net_device *dev,
@@ -1130,13 +1056,13 @@ void ActSetWirelessMode8185(struct net_device *dev, u8 btWirelessMode)
 	ieee->mode = (WIRELESS_MODE)btWirelessMode;
 
 	/* 3. Change related setting. */
-	if( ieee->mode == WIRELESS_MODE_A ) {
+	if (ieee->mode == WIRELESS_MODE_A)
 		DMESG("WIRELESS_MODE_A\n");
-	} else if( ieee->mode == WIRELESS_MODE_B ) {
+	else if (ieee->mode == WIRELESS_MODE_B)
 		DMESG("WIRELESS_MODE_B\n");
-	} else if( ieee->mode == WIRELESS_MODE_G ) {
+	else if (ieee->mode == WIRELESS_MODE_G)
 		DMESG("WIRELESS_MODE_G\n");
-	}
+
 	ActUpdateChannelAccessSetting( dev, ieee->mode, &priv->ChannelAccessSetting);
 }
 
@@ -1148,18 +1074,11 @@ void rtl8185b_irq_enable(struct net_device *dev)
 	write_nic_dword(dev, IMR, priv->IntrMask);
 }
 
-void DrvIFIndicateDisassociation(struct net_device *dev, u16 reason)
-{
-		/* nothing is needed after disassociation request. */
-}
-
 void MgntDisconnectIBSS(struct net_device *dev)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	u8 i;
 
-	DrvIFIndicateDisassociation(dev, unspec_reason);
-
 	for (i = 0; i < 6 ; i++)
 		priv->ieee80211->current_network.bssid[i] = 0x55;
 
@@ -1190,8 +1109,6 @@ void MlmeDisassociateRequest(struct net_device *dev, u8 *asSta, u8 asRsn)
 
 	if (memcmp(priv->ieee80211->current_network.bssid, asSta, 6) == 0) {
 		/* ShuChen TODO: change media status. */
-		/* ShuChen TODO: What to do when disassociate. */
-		DrvIFIndicateDisassociation(dev, unspec_reason);
 
 		for (i = 0; i < 6; i++)
 			priv->ieee80211->current_network.bssid[i] = 0x22;
@@ -1267,14 +1184,6 @@ bool SetRFPowerState(struct net_device *dev, RT_RF_POWER_STATE eRFPowerState)
 	return bResult;
 }
 
-void HalEnableRx8185Dummy(struct net_device *dev)
-{
-}
-
-void HalDisableRx8185Dummy(struct net_device *dev)
-{
-}
-
 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);
@@ -1323,11 +1232,9 @@ bool MgntActSet_RF_State(struct net_device *dev, RT_RF_POWER_STATE StateToSet, u
 			priv->RfOffReason = 0;
 			bActionAllowed = true;
 
-			if (rtState == eRfOff && ChangeSource >= RF_CHANGE_BY_HW && !priv->bInHctTest)
+			if (rtState == eRfOff && ChangeSource >= RF_CHANGE_BY_HW)
 				bConnectBySSID = true;
-
-		} else
-			;
+		}
 		break;
 
 	case eRfOff:
@@ -1359,18 +1266,6 @@ bool MgntActSet_RF_State(struct net_device *dev, RT_RF_POWER_STATE StateToSet, u
 	if (bActionAllowed) {
 		/* Config HW to the specified mode. */
 		SetRFPowerState(dev, StateToSet);
-
-		/* Turn on RF.	*/
-		if (StateToSet == eRfOn) {
-			HalEnableRx8185Dummy(dev);
-			if (bConnectBySSID) {
-				/* by amy not supported	*/
-			}
-		}
-		/* Turn off RF.	*/
-		else if (StateToSet == eRfOff)
-			HalDisableRx8185Dummy(dev);
-
 	}
 
 	/* Release RF spinlock	*/
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
index 81134d3..1a70f32 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
@@ -82,7 +82,7 @@ static struct rtl819x_ops rtl819xp_ops = {
 	.RxCheckStuckHandler		= rtl8192_HalRxCheckStuck,
 };
 
-static struct pci_device_id rtl8192_pci_id_tbl[] __devinitdata = {
+static struct pci_device_id rtl8192_pci_id_tbl[] = {
 	{RTL_PCI_DEVICE(0x10ec, 0x8192, rtl819xp_ops)},
 	{RTL_PCI_DEVICE(0x07aa, 0x0044, rtl819xp_ops)},
 	{RTL_PCI_DEVICE(0x07aa, 0x0047, rtl819xp_ops)},
@@ -91,15 +91,15 @@ static struct pci_device_id rtl8192_pci_id_tbl[] __devinitdata = {
 
 MODULE_DEVICE_TABLE(pci, rtl8192_pci_id_tbl);
 
-static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
+static int rtl8192_pci_probe(struct pci_dev *pdev,
 			const struct pci_device_id *id);
-static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev);
+static void rtl8192_pci_disconnect(struct pci_dev *pdev);
 
 static struct pci_driver rtl8192_pci_driver = {
 	.name = DRV_NAME,	/* Driver name   */
 	.id_table = rtl8192_pci_id_tbl,	/* PCI_ID table  */
 	.probe	= rtl8192_pci_probe,	/* probe fn      */
-	.remove	 = __devexit_p(rtl8192_pci_disconnect),	/* remove fn */
+	.remove	 = rtl8192_pci_disconnect,	/* remove fn */
 	.suspend = rtl8192E_suspend,	/* PM suspend fn */
 	.resume = rtl8192E_resume,                 /* PM resume fn  */
 };
@@ -2846,7 +2846,7 @@ static const struct net_device_ops rtl8192_netdev_ops = {
 	.ndo_start_xmit = rtllib_xmit,
 };
 
-static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
+static int rtl8192_pci_probe(struct pci_dev *pdev,
 			const struct pci_device_id *id)
 {
 	unsigned long ioaddr = 0;
@@ -2955,7 +2955,8 @@ static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
 	netif_carrier_off(dev);
 	netif_stop_queue(dev);
 
-	register_netdev(dev);
+	if (register_netdev(dev))
+		goto err_free_irq;
 	RT_TRACE(COMP_INIT, "dev name: %s\n", dev->name);
 
 	rtl8192_proc_init_one(dev);
@@ -2981,7 +2982,7 @@ err_pci_disable:
 	return err;
 }
 
-static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev)
+static void rtl8192_pci_disconnect(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct r8192_priv *priv ;
diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h
index 9ac8d8e..3485ef1 100644
--- a/drivers/staging/rtl8192e/rtllib.h
+++ b/drivers/staging/rtl8192e/rtllib.h
@@ -2567,7 +2567,7 @@ static inline void *rtllib_priv(struct net_device *dev)
 	return ((struct rtllib_device *)netdev_priv(dev))->priv;
 }
 
-extern inline int rtllib_is_empty_essid(const char *essid, int essid_len)
+static inline int rtllib_is_empty_essid(const char *essid, int essid_len)
 {
 	/* Single white space is for Linksys APs */
 	if (essid_len == 1 && essid[0] == ' ')
@@ -2583,7 +2583,7 @@ extern inline int rtllib_is_empty_essid(const char *essid, int essid_len)
 	return 1;
 }
 
-extern inline int rtllib_is_valid_mode(struct rtllib_device *ieee, int mode)
+static inline int rtllib_is_valid_mode(struct rtllib_device *ieee, int mode)
 {
 	/*
 	 * It is possible for both access points and our device to support
@@ -2609,7 +2609,7 @@ extern inline int rtllib_is_valid_mode(struct rtllib_device *ieee, int mode)
 	return 0;
 }
 
-extern inline int rtllib_get_hdrlen(u16 fc)
+static inline int rtllib_get_hdrlen(u16 fc)
 {
 	int hdrlen = RTLLIB_3ADDR_LEN;
 
diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c
index 42900ee..759d7c7 100644
--- a/drivers/staging/rtl8192e/rtllib_tx.c
+++ b/drivers/staging/rtl8192e/rtllib_tx.c
@@ -287,7 +287,7 @@ static void rtllib_tx_query_agg_cap(struct rtllib_device *ieee,
 {
 	struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
 	struct tx_ts_record *pTxTs = NULL;
-	struct rtllib_hdr_1addr* hdr = (struct rtllib_hdr_1addr *)skb->data;
+	struct rtllib_hdr_1addr *hdr = (struct rtllib_hdr_1addr *)skb->data;
 
 	if (rtllib_act_scanning(ieee, false))
 		return;
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
index 13f45c3..502bfdb 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
@@ -235,7 +235,10 @@ enum	_ReasonCode{
 
 
 
-#define aSifsTime	 ((priv->ieee80211->current_network.mode == IEEE_A)||(priv->ieee80211->current_network.mode == IEEE_N_24G)||(priv->ieee80211->current_network.mode == IEEE_N_5G))? 16 : 10
+#define aSifsTime ((priv->ieee80211->current_network.mode == IEEE_A || \
+		    priv->ieee80211->current_network.mode == IEEE_N_24G || \
+		    priv->ieee80211->current_network.mode == IEEE_N_5G) ? \
+		   16 : 10)
 
 #define MGMT_QUEUE_NUM 5
 
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index 5a2fab9..56367f2 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -144,9 +144,9 @@ MODULE_PARM_DESC(ifname," Net interface name, wlan%d=default");
 MODULE_PARM_DESC(hwwep," Try to use hardware security support. ");
 MODULE_PARM_DESC(channels," Channel bitmask for specific locales. NYI");
 
-static int __devinit rtl8192_usb_probe(struct usb_interface *intf,
+static int rtl8192_usb_probe(struct usb_interface *intf,
 			 const struct usb_device_id *id);
-static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf);
+static void rtl8192_usb_disconnect(struct usb_interface *intf);
 
 
 static struct usb_driver rtl8192_usb_driver = {
@@ -5739,7 +5739,7 @@ static const struct net_device_ops rtl8192_netdev_ops = {
      ---------------------------- USB_STUFF---------------------------
 *****************************************************************************/
 
-static int __devinit rtl8192_usb_probe(struct usb_interface *intf,
+static int rtl8192_usb_probe(struct usb_interface *intf,
 			 const struct usb_device_id *id)
 {
 //	unsigned long ioaddr = 0;
@@ -5826,7 +5826,7 @@ void rtl8192_cancel_deferred_work(struct r8192_priv* priv)
 }
 
 
-static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf)
+static void rtl8192_usb_disconnect(struct usb_interface *intf)
 {
 	struct net_device *dev = usb_get_intfdata(intf);
 
diff --git a/drivers/staging/rtl8712/mlme_linux.c b/drivers/staging/rtl8712/mlme_linux.c
index abf96c1..7279854 100644
--- a/drivers/staging/rtl8712/mlme_linux.c
+++ b/drivers/staging/rtl8712/mlme_linux.c
@@ -156,7 +156,7 @@ void r8712_report_sec_ie(struct _adapter *adapter, u8 authmode, u8 *sec_ie)
 		p = buff;
 		p += sprintf(p, "ASSOCINFO(ReqIEs=");
 		len = sec_ie[1] + 2;
-		len =  (len < IW_CUSTOM_MAX) ? len : IW_CUSTOM_MAX;
+		len =  (len < IW_CUSTOM_MAX) ? len : IW_CUSTOM_MAX - 1;
 		for (i = 0; i < len; i++)
 			p += sprintf(p, "%02x", sec_ie[i]);
 		p += sprintf(p, ")");
diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c
index 659683e..31f31dbf 100644
--- a/drivers/staging/rtl8712/rtl871x_cmd.c
+++ b/drivers/staging/rtl8712/rtl871x_cmd.c
@@ -814,7 +814,7 @@ u8 r8712_setassocsta_cmd(struct _adapter *padapter, u8 *mac_addr)
 	struct cmd_priv			*pcmdpriv = &padapter->cmdpriv;
 	struct cmd_obj			*ph2c;
 	struct set_assocsta_parm	*psetassocsta_para;
-	struct set_stakey_rsp		*psetassocsta_rsp = NULL;
+	struct set_assocsta_rsp		*psetassocsta_rsp = NULL;
 
 	ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 	if (ph2c == NULL)
@@ -825,7 +825,7 @@ u8 r8712_setassocsta_cmd(struct _adapter *padapter, u8 *mac_addr)
 		kfree((u8 *) ph2c);
 		return _FAIL;
 	}
-	psetassocsta_rsp = (struct set_stakey_rsp *)_malloc(
+	psetassocsta_rsp = (struct set_assocsta_rsp *)_malloc(
 			    sizeof(struct set_assocsta_rsp));
 	if (psetassocsta_rsp == NULL) {
 		kfree((u8 *)ph2c);
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
index c9a6a7f..3a64790 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
@@ -2110,10 +2110,10 @@ static int r871x_wps_start(struct net_device *dev,
 	struct iw_point *pdata = &wrqu->data;
 	u32   u32wps_start = 0;
 
-	if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
-		return -EFAULT;
 	if ((padapter->bDriverStopped) || (pdata == NULL))
 		return -EINVAL;
+	if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
+		return -EFAULT;
 	if (u32wps_start == 0)
 		u32wps_start = *extra;
 	if (u32wps_start == 1) /* WPS Start */
diff --git a/drivers/staging/rts5139/Makefile b/drivers/staging/rts5139/Makefile
index 82b8958..75dd312 100644
--- a/drivers/staging/rts5139/Makefile
+++ b/drivers/staging/rts5139/Makefile
@@ -25,13 +25,19 @@
 # Makefile for the RTS51xx USB Card Reader drivers.
 #
 
-TARGET_MODULE := rts5139
+obj-$(CONFIG_RTS5139) := rts5139.o
 
-EXTRA_CFLAGS := -Idrivers/scsi -I$(PWD)
+ccflags-y := -Idrivers/scsi
 
-obj-m += $(TARGET_MODULE).o
-
-common-obj := rts51x_transport.o rts51x_scsi.o rts51x_fop.o
-
-$(TARGET_MODULE)-objs := $(common-obj) rts51x.o rts51x_chip.o rts51x_card.o \
-		xd.o sd.o ms.o sd_cprm.o ms_mg.o
+rts5139-y :=				\
+		rts51x_transport.o 	\
+		rts51x_scsi.o		\
+		rts51x_fop.o		\
+		rts51x.o		\
+		rts51x_chip.o		\
+		rts51x_card.o		\
+		xd.o			\
+		sd.o			\
+		ms.o			\
+		sd_cprm.o		\
+		ms_mg.o
diff --git a/drivers/staging/rts5139/ms.c b/drivers/staging/rts5139/ms.c
index 6eef33b..a27f7e2 100644
--- a/drivers/staging/rts5139/ms.c
+++ b/drivers/staging/rts5139/ms.c
@@ -160,7 +160,7 @@ int ms_transfer_data(struct rts51x_chip *chip, u8 trans_mode, u8 tpc,
 		rts51x_add_cmd(chip, WRITE_REG_CMD, MS_CFG, MS_2K_SECTOR_MODE,
 			       0);
 
-	trans_dma_enable(dir, chip, sec_cnt * 512, DMA_512);
+	rts51x_trans_dma_enable(dir, chip, sec_cnt * 512, DMA_512);
 
 	rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
 		       MS_TRANSFER_START | trans_mode);
@@ -602,7 +602,7 @@ static int ms_prepare_reset(struct rts51x_chip *chip)
 	if (!chip->option.FT2_fast_mode) {
 		wait_timeout(250);
 
-		card_power_on(chip, MS_CARD);
+		rts51x_card_power_on(chip, MS_CARD);
 		wait_timeout(150);
 
 #ifdef SUPPORT_OCP
@@ -872,7 +872,7 @@ static int msxc_change_power(struct rts51x_chip *chip, u8 mode)
 	int retval;
 	u8 buf[6];
 
-	ms_cleanup_work(chip);
+	rts51x_ms_cleanup_work(chip);
 
 	/* Set Parameter Register */
 	retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6);
@@ -2600,14 +2600,14 @@ BUILD_FAIL:
 	return STATUS_FAIL;
 }
 
-int reset_ms_card(struct rts51x_chip *chip)
+int rts51x_reset_ms_card(struct rts51x_chip *chip)
 {
 	struct ms_info *ms_card = &(chip->ms_card);
 	int retval;
 
 	memset(ms_card, 0, sizeof(struct ms_info));
 
-	enable_card_clock(chip, MS_CARD);
+	rts51x_enable_card_clock(chip, MS_CARD);
 
 	retval = rts51x_select_card(chip, MS_CARD);
 	if (retval != STATUS_SUCCESS)
@@ -2936,7 +2936,7 @@ static int mspro_read_format_progress(struct rts51x_chip *chip,
 	return STATUS_SUCCESS;
 }
 
-void mspro_polling_format_status(struct rts51x_chip *chip)
+void rts51x_mspro_polling_format_status(struct rts51x_chip *chip)
 {
 	struct ms_info *ms_card = &(chip->ms_card);
 	int i;
@@ -2952,25 +2952,25 @@ void mspro_polling_format_status(struct rts51x_chip *chip)
 	return;
 }
 
-void mspro_format_sense(struct rts51x_chip *chip, unsigned int lun)
+void rts51x_mspro_format_sense(struct rts51x_chip *chip, unsigned int lun)
 {
 	struct ms_info *ms_card = &(chip->ms_card);
 
 	if (CHK_FORMAT_STATUS(ms_card, FORMAT_SUCCESS)) {
-		set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
 		ms_card->pro_under_formatting = 0;
 		ms_card->progress = 0;
 	} else if (CHK_FORMAT_STATUS(ms_card, FORMAT_IN_PROGRESS)) {
-		set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
+		rts51x_set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
 			       0, (u16) (ms_card->progress));
 	} else {
-		set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
 		ms_card->pro_under_formatting = 0;
 		ms_card->progress = 0;
 	}
 }
 
-int mspro_format(struct scsi_cmnd *srb, struct rts51x_chip *chip,
+int rts51x_mspro_format(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 		 int short_data_len, int quick_format)
 {
 	struct ms_info *ms_card = &(chip->ms_card);
@@ -3035,7 +3035,7 @@ int mspro_format(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 		ms_card->pro_under_formatting = 0;
 		ms_card->progress = 0;
 		ms_card->format_status = FORMAT_SUCCESS;
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_NO_SENSE);
+		rts51x_set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_NO_SENSE);
 		return STATUS_SUCCESS;
 	}
 
@@ -3103,7 +3103,7 @@ static int ms_read_multiple_pages(struct rts51x_chip *chip, u16 phy_blk,
 	rts51x_add_cmd(chip, WRITE_REG_CMD, MS_SECTOR_CNT_H, 0xFF, 0);
 	rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, READ_PAGE_DATA);
 
-	trans_dma_enable(DMA_FROM_DEVICE, chip, 512 * page_cnt, DMA_512);
+	rts51x_trans_dma_enable(DMA_FROM_DEVICE, chip, 512 * page_cnt, DMA_512);
 
 	rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
 		       MS_TRANSFER_START | MS_TM_MULTI_READ);
@@ -3307,7 +3307,7 @@ static int ms_write_multiple_pages(struct rts51x_chip *chip, u16 old_blk,
 	rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
 		       RING_BUFFER);
 
-	trans_dma_enable(DMA_TO_DEVICE, chip, 512 * page_cnt, DMA_512);
+	rts51x_trans_dma_enable(DMA_TO_DEVICE, chip, 512 * page_cnt, DMA_512);
 
 	rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
 		       MS_TRANSFER_START | MS_TM_MULTI_WRITE);
@@ -3467,7 +3467,7 @@ static int ms_read_multiple_pages(struct rts51x_chip *chip, u16 phy_blk,
 		rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF,
 			       trans_cfg);
 
-		trans_dma_enable(DMA_FROM_DEVICE, chip, 512, DMA_512);
+		rts51x_trans_dma_enable(DMA_FROM_DEVICE, chip, 512, DMA_512);
 
 		rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
 			       MS_TRANSFER_START | MS_TM_NORMAL_READ);
@@ -3670,7 +3670,7 @@ static int ms_write_multiple_pages(struct rts51x_chip *chip, u16 old_blk,
 		rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF,
 			       WAIT_INT);
 
-		trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
+		rts51x_trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
 
 		rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
 			       MS_TRANSFER_START | MS_TM_NORMAL_WRITE);
@@ -3803,10 +3803,10 @@ static int ms_prepare_write(struct rts51x_chip *chip, u16 old_blk, u16 new_blk,
 	return STATUS_SUCCESS;
 }
 
-int ms_delay_write(struct rts51x_chip *chip)
+int rts51x_ms_delay_write(struct rts51x_chip *chip)
 {
 	struct ms_info *ms_card = &(chip->ms_card);
-	struct ms_delay_write_tag *delay_write = &(ms_card->delay_write);
+	struct rts51x_ms_delay_write_tag *delay_write = &(ms_card->delay_write);
 	int retval;
 
 	if (delay_write->delay_write_flag) {
@@ -3827,16 +3827,16 @@ int ms_delay_write(struct rts51x_chip *chip)
 	return STATUS_SUCCESS;
 }
 
-static inline void ms_rw_fail(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+static inline void rts51x_ms_rw_fail(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
 	if (srb->sc_data_direction == DMA_FROM_DEVICE)
-		set_sense_type(chip, SCSI_LUN(srb),
+		rts51x_set_sense_type(chip, SCSI_LUN(srb),
 			       SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 	else
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+		rts51x_set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
 }
 
-static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
+static int rts51x_ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 			      u32 start_sector, u16 sector_cnt)
 {
 	struct ms_info *ms_card = &(chip->ms_card);
@@ -3847,7 +3847,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 	u8 start_page, end_page = 0, page_cnt;
 	u8 *buf;
 	void *ptr = NULL;
-	struct ms_delay_write_tag *delay_write = &(ms_card->delay_write);
+	struct rts51x_ms_delay_write_tag *delay_write = &(ms_card->delay_write);
 
 	ms_set_err_code(chip, MS_NO_ERROR);
 
@@ -3857,7 +3857,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 
 	retval = ms_switch_clock(chip);
 	if (retval != STATUS_SUCCESS) {
-		ms_rw_fail(srb, chip);
+		rts51x_ms_rw_fail(srb, chip);
 		TRACE_RET(chip, retval);
 	}
 
@@ -3873,7 +3873,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 		retval = ms_build_l2p_tbl(chip, seg_no);
 		if (retval != STATUS_SUCCESS) {
 			chip->card_fail |= MS_CARD;
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+			rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 			TRACE_RET(chip, retval);
 		}
 	}
@@ -3898,7 +3898,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 					      start_page);
 #endif
 			if (retval != STATUS_SUCCESS) {
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MEDIA_WRITE_ERR);
 				TRACE_RET(chip, retval);
 			}
@@ -3911,9 +3911,9 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 			old_blk = delay_write->old_phyblock;
 			new_blk = delay_write->new_phyblock;
 		} else {
-			retval = ms_delay_write(chip);
+			retval = rts51x_ms_delay_write(chip);
 			if (retval != STATUS_SUCCESS) {
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MEDIA_WRITE_ERR);
 				TRACE_RET(chip, retval);
 			}
@@ -3922,7 +3922,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 					   log_blk - ms_start_idx[seg_no]);
 			new_blk = ms_get_unused_block(chip, seg_no);
 			if ((old_blk == 0xFFFF) || (new_blk == 0xFFFF)) {
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MEDIA_WRITE_ERR);
 				TRACE_RET(chip, STATUS_FAIL);
 			}
@@ -3933,26 +3933,26 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 			if (retval != STATUS_SUCCESS) {
 				if (monitor_card_cd(chip, MS_CARD) ==
 				    CD_NOT_EXIST) {
-					set_sense_type(chip, lun,
+					rts51x_set_sense_type(chip, lun,
 						SENSE_TYPE_MEDIA_NOT_PRESENT);
 					TRACE_RET(chip, STATUS_FAIL);
 				}
 
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MEDIA_WRITE_ERR);
 				TRACE_RET(chip, retval);
 			}
 		}
 	} else {
-		retval = ms_delay_write(chip);
+		retval = rts51x_ms_delay_write(chip);
 		if (retval != STATUS_SUCCESS) {
 			if (monitor_card_cd(chip, MS_CARD) == CD_NOT_EXIST) {
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MEDIA_NOT_PRESENT);
 				TRACE_RET(chip, STATUS_FAIL);
 			}
 
-			set_sense_type(chip, lun,
+			rts51x_set_sense_type(chip, lun,
 				       SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 			TRACE_RET(chip, retval);
 		}
@@ -3960,7 +3960,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 		    ms_get_l2p_tbl(chip, seg_no,
 				   log_blk - ms_start_idx[seg_no]);
 		if (old_blk == 0xFFFF) {
-			set_sense_type(chip, lun,
+			rts51x_set_sense_type(chip, lun,
 				       SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 			TRACE_RET(chip, STATUS_FAIL);
 		}
@@ -3993,12 +3993,12 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 
 		if (retval != STATUS_SUCCESS) {
 			if (monitor_card_cd(chip, MS_CARD) == CD_NOT_EXIST) {
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MEDIA_NOT_PRESENT);
 				TRACE_RET(chip, STATUS_FAIL);
 			}
 
-			ms_rw_fail(srb, chip);
+			rts51x_ms_rw_fail(srb, chip);
 			TRACE_RET(chip, retval);
 		}
 		/* Update L2P table if need */
@@ -4030,7 +4030,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 			retval = ms_build_l2p_tbl(chip, seg_no);
 			if (retval != STATUS_SUCCESS) {
 				chip->card_fail |= MS_CARD;
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MEDIA_NOT_PRESENT);
 				TRACE_RET(chip, retval);
 			}
@@ -4040,14 +4040,14 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 		    ms_get_l2p_tbl(chip, seg_no,
 				   log_blk - ms_start_idx[seg_no]);
 		if (old_blk == 0xFFFF) {
-			ms_rw_fail(srb, chip);
+			rts51x_ms_rw_fail(srb, chip);
 			TRACE_RET(chip, STATUS_FAIL);
 		}
 
 		if (srb->sc_data_direction == DMA_TO_DEVICE) {
 			new_blk = ms_get_unused_block(chip, seg_no);
 			if (new_blk == 0xFFFF) {
-				ms_rw_fail(srb, chip);
+				rts51x_ms_rw_fail(srb, chip);
 				TRACE_RET(chip, STATUS_FAIL);
 			}
 		}
@@ -4073,7 +4073,7 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 	return STATUS_SUCCESS;
 }
 
-int ms_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
+int rts51x_ms_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 	  u16 sector_cnt)
 {
 	struct ms_info *ms_card = &(chip->ms_card);
@@ -4084,12 +4084,12 @@ int ms_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 		    mspro_rw_multi_sector(srb, chip, start_sector, sector_cnt);
 	else
 		retval =
-		    ms_rw_multi_sector(srb, chip, start_sector, sector_cnt);
+		    rts51x_ms_rw_multi_sector(srb, chip, start_sector, sector_cnt);
 
 	return retval;
 }
 
-void ms_free_l2p_tbl(struct rts51x_chip *chip)
+void rts51x_ms_free_l2p_tbl(struct rts51x_chip *chip)
 {
 	struct ms_info *ms_card = &(chip->ms_card);
 	int i = 0;
@@ -4110,7 +4110,7 @@ void ms_free_l2p_tbl(struct rts51x_chip *chip)
 	}
 }
 
-void ms_cleanup_work(struct rts51x_chip *chip)
+void rts51x_ms_cleanup_work(struct rts51x_chip *chip)
 {
 	struct ms_info *ms_card = &(chip->ms_card);
 
@@ -4130,7 +4130,7 @@ void ms_cleanup_work(struct rts51x_chip *chip)
 	} else if ((!CHK_MSPRO(ms_card))
 		   && ms_card->delay_write.delay_write_flag) {
 		RTS51X_DEBUGP("MS: delay write\n");
-		ms_delay_write(chip);
+		rts51x_ms_delay_write(chip);
 		ms_card->counter = 0;
 	}
 }
@@ -4161,12 +4161,12 @@ static int ms_power_off_card3v3(struct rts51x_chip *chip)
 	return STATUS_SUCCESS;
 }
 
-int release_ms_card(struct rts51x_chip *chip)
+int rts51x_release_ms_card(struct rts51x_chip *chip)
 {
 	struct ms_info *ms_card = &(chip->ms_card);
 	int retval;
 
-	RTS51X_DEBUGP("release_ms_card\n");
+	RTS51X_DEBUGP("rts51x_release_ms_card\n");
 
 	ms_card->delay_write.delay_write_flag = 0;
 	ms_card->pro_under_formatting = 0;
@@ -4175,7 +4175,7 @@ int release_ms_card(struct rts51x_chip *chip)
 	chip->card_fail &= ~MS_CARD;
 	chip->card_wp &= ~MS_CARD;
 
-	ms_free_l2p_tbl(chip);
+	rts51x_ms_free_l2p_tbl(chip);
 
 	rts51x_write_register(chip, SFSM_ED, HW_CMD_STOP, HW_CMD_STOP);
 
diff --git a/drivers/staging/rts5139/ms.h b/drivers/staging/rts5139/ms.h
index 0321d06..857c197 100644
--- a/drivers/staging/rts5139/ms.h
+++ b/drivers/staging/rts5139/ms.h
@@ -231,18 +231,18 @@
 	(((retval) != STATUS_SUCCESS) || \
 	(chip->rsp_buf[0] & MS_TRANSFER_ERR))
 
-void mspro_polling_format_status(struct rts51x_chip *chip);
-void mspro_format_sense(struct rts51x_chip *chip, unsigned int lun);
+void rts51x_mspro_polling_format_status(struct rts51x_chip *chip);
+void rts51x_mspro_format_sense(struct rts51x_chip *chip, unsigned int lun);
 
-int reset_ms_card(struct rts51x_chip *chip);
-int ms_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
+int rts51x_reset_ms_card(struct rts51x_chip *chip);
+int rts51x_ms_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 	  u16 sector_cnt);
-int mspro_format(struct scsi_cmnd *srb, struct rts51x_chip *chip,
+int rts51x_mspro_format(struct scsi_cmnd *srb, struct rts51x_chip *chip,
 		 int short_data_len, int quick_format);
-void ms_free_l2p_tbl(struct rts51x_chip *chip);
-void ms_cleanup_work(struct rts51x_chip *chip);
-int release_ms_card(struct rts51x_chip *chip);
-int ms_delay_write(struct rts51x_chip *chip);
+void rts51x_ms_free_l2p_tbl(struct rts51x_chip *chip);
+void rts51x_ms_cleanup_work(struct rts51x_chip *chip);
+int rts51x_release_ms_card(struct rts51x_chip *chip);
+int rts51x_ms_delay_write(struct rts51x_chip *chip);
 
 #ifdef SUPPORT_MAGIC_GATE
 
diff --git a/drivers/staging/rts5139/ms_mg.c b/drivers/staging/rts5139/ms_mg.c
index 057d96c..54cfd85 100644
--- a/drivers/staging/rts5139/ms_mg.c
+++ b/drivers/staging/rts5139/ms_mg.c
@@ -119,7 +119,7 @@ int mg_set_tpc_para_sub(struct rts51x_chip *chip, int type, u8 mg_entry_num)
   * 2. send SET_ID TPC command to medium with Leaf ID released by host
   * in this SCSI CMD.
   */
-int mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
 	int retval;
 	int i;
@@ -129,10 +129,10 @@ int mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	RTS51X_DEBUGP("--%s--\n", __func__);
 
 	if (scsi_bufflen(srb) < 12) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, STATUS_FAIL);
 	}
-	ms_cleanup_work(chip);
+	rts51x_ms_cleanup_work(chip);
 
 	retval = ms_switch_clock(chip);
 	if (retval != STATUS_SUCCESS)
@@ -140,7 +140,7 @@ int mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
 	retval = mg_send_ex_cmd(chip, MG_SET_LID, 0);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
 		TRACE_RET(chip, retval);
 	}
 
@@ -151,12 +151,12 @@ int mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	retval =
 	    ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf1, 32);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
 		TRACE_RET(chip, retval);
 	}
 	retval = mg_check_int_error(chip);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
 		TRACE_RET(chip, retval);
 	}
 
@@ -170,7 +170,7 @@ int mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip)
   * data(1536 bytes totally) from medium by using READ_LONG_DATA TPC
   * for 3 times, and report data to host with data-length is 1052 bytes.
   */
-int mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
 	int retval = STATUS_FAIL;
 	int bufflen;
@@ -179,7 +179,7 @@ int mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
 	RTS51X_DEBUGP("--%s--\n", __func__);
 
-	ms_cleanup_work(chip);
+	rts51x_ms_cleanup_work(chip);
 
 	retval = ms_switch_clock(chip);
 	if (retval != STATUS_SUCCESS)
@@ -196,21 +196,21 @@ int mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
 	retval = mg_send_ex_cmd(chip, MG_GET_LEKB, 0);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
 		TRACE_GOTO(chip, GetEKBFinish);
 	}
 
 	retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
 				  3, WAIT_INT, 0, 0, buf + 4, 1536);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
 		rts51x_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR,
 				      MS_STOP | MS_CLR_ERR);
 		TRACE_GOTO(chip, GetEKBFinish);
 	}
 	retval = mg_check_int_error(chip);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
 		TRACE_GOTO(chip, GetEKBFinish);
 	}
 
@@ -229,7 +229,7 @@ GetEKBFinish:
   * TPC commands to the medium for writing 8-bytes data as challenge
   * by host within a short data packet.
   */
-int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
 	struct ms_info *ms_card = &(chip->ms_card);
 	int retval;
@@ -240,7 +240,7 @@ int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
 	RTS51X_DEBUGP("--%s--\n", __func__);
 
-	ms_cleanup_work(chip);
+	rts51x_ms_cleanup_work(chip);
 
 	retval = ms_switch_clock(chip);
 	if (retval != STATUS_SUCCESS)
@@ -248,19 +248,19 @@ int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
 	retval = mg_send_ex_cmd(chip, MG_GET_ID, 0);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
 		TRACE_RET(chip, retval);
 	}
 
 	retval =
 	    ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, buf, 32);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
 		TRACE_RET(chip, retval);
 	}
 	retval = mg_check_int_error(chip);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
 		TRACE_RET(chip, retval);
 	}
 
@@ -276,13 +276,13 @@ int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	}
 
 	if (i == 2500) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
 		TRACE_RET(chip, STATUS_FAIL);
 	}
 
 	retval = mg_send_ex_cmd(chip, MG_SET_RD, 0);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
 		TRACE_RET(chip, retval);
 	}
 
@@ -296,12 +296,12 @@ int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	retval =
 	    ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf, 32);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
 		TRACE_RET(chip, retval);
 	}
 	retval = mg_check_int_error(chip);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
 		TRACE_RET(chip, retval);
 	}
 
@@ -320,7 +320,7 @@ int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
   * The paremeter MagicGateID is the one that adapter has obtained from
   * the medium by TPC commands in Set Leaf ID command phase previously.
   */
-int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
 	struct ms_info *ms_card = &(chip->ms_card);
 	int retval, i;
@@ -330,7 +330,7 @@ int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
 	RTS51X_DEBUGP("--%s--\n", __func__);
 
-	ms_cleanup_work(chip);
+	rts51x_ms_cleanup_work(chip);
 
 	retval = ms_switch_clock(chip);
 	if (retval != STATUS_SUCCESS)
@@ -338,19 +338,19 @@ int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
 	retval = mg_send_ex_cmd(chip, MG_MAKE_RMS, 0);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
 		TRACE_RET(chip, retval);
 	}
 
 	retval =
 	    ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, buf1, 32);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
 		TRACE_RET(chip, retval);
 	}
 	retval = mg_check_int_error(chip);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
 		TRACE_RET(chip, retval);
 	}
 
@@ -375,7 +375,7 @@ int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	}
 
 	if (i == 2500) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
 		TRACE_RET(chip, STATUS_FAIL);
 	}
 
@@ -389,7 +389,7 @@ int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip)
   * issues TPC commands to the medium for writing 8-bytes data as
   * challenge by host within a short data packet.
   */
-int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
 	struct ms_info *ms_card = &(chip->ms_card);
 	int retval;
@@ -400,7 +400,7 @@ int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
 	RTS51X_DEBUGP("--%s--\n", __func__);
 
-	ms_cleanup_work(chip);
+	rts51x_ms_cleanup_work(chip);
 
 	retval = ms_switch_clock(chip);
 	if (retval != STATUS_SUCCESS)
@@ -408,7 +408,7 @@ int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
 	retval = mg_send_ex_cmd(chip, MG_MAKE_KSE, 0);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
 		TRACE_RET(chip, retval);
 	}
 
@@ -422,12 +422,12 @@ int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	retval =
 	    ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf, 32);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
 		TRACE_RET(chip, retval);
 	}
 	retval = mg_check_int_error(chip);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
 		TRACE_RET(chip, retval);
 	}
 
@@ -447,7 +447,7 @@ int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
   * precedes data transmission from medium to Ring buffer by DMA mechanism
   * in order to get maximum performance and minimum code size simultaneously.
   */
-int mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
 	struct ms_info *ms_card = &(chip->ms_card);
 	int retval;
@@ -457,7 +457,7 @@ int mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
 	RTS51X_DEBUGP("--%s--\n", __func__);
 
-	ms_cleanup_work(chip);
+	rts51x_ms_cleanup_work(chip);
 
 	retval = ms_switch_clock(chip);
 	if (retval != STATUS_SUCCESS)
@@ -474,21 +474,21 @@ int mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
 	retval = mg_send_ex_cmd(chip, MG_GET_IBD, ms_card->mg_entry_num);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 		TRACE_GOTO(chip, GetICVFinish);
 	}
 
 	retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
 				  2, WAIT_INT, 0, 0, buf + 4, 1024);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 		rts51x_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR,
 				      MS_STOP | MS_CLR_ERR);
 		TRACE_GOTO(chip, GetICVFinish);
 	}
 	retval = mg_check_int_error(chip);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 		TRACE_GOTO(chip, GetICVFinish);
 	}
 
@@ -511,7 +511,7 @@ GetICVFinish:
   * that sent by host, and it should be skipped by shifting DMA pointer
   * before writing 1024 bytes to medium.
   */
-int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
 	struct ms_info *ms_card = &(chip->ms_card);
 	int retval;
@@ -524,7 +524,7 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
 	RTS51X_DEBUGP("--%s--\n", __func__);
 
-	ms_cleanup_work(chip);
+	rts51x_ms_cleanup_work(chip);
 
 	retval = ms_switch_clock(chip);
 	if (retval != STATUS_SUCCESS)
@@ -541,13 +541,13 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	if (retval != STATUS_SUCCESS) {
 		if (ms_card->mg_auth == 0) {
 			if ((buf[5] & 0xC0) != 0)
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
 			else
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					SENSE_TYPE_MG_WRITE_ERR);
 		} else {
-			set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
+			rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
 		}
 		TRACE_GOTO(chip, SetICVFinish);
 	}
@@ -563,7 +563,7 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 		rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF,
 			       WAIT_INT);
 
-		trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
+		rts51x_trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
 
 		rts51x_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
 			       MS_TRANSFER_START | MS_TM_NORMAL_WRITE);
@@ -572,7 +572,7 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
 		retval = rts51x_send_cmd(chip, MODE_CDOR, 100);
 		if (retval != STATUS_SUCCESS) {
-			set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
+			rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
 			TRACE_GOTO(chip, SetICVFinish);
 		}
 
@@ -583,13 +583,13 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 			rts51x_clear_ms_error(chip);
 			if (ms_card->mg_auth == 0) {
 				if ((buf[5] & 0xC0) != 0)
-					set_sense_type(chip, lun,
+					rts51x_set_sense_type(chip, lun,
 						SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
 				else
-					set_sense_type(chip, lun,
+					rts51x_set_sense_type(chip, lun,
 						SENSE_TYPE_MG_WRITE_ERR);
 			} else {
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MG_WRITE_ERR);
 			}
 			retval = STATUS_FAIL;
@@ -602,13 +602,13 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 			rts51x_clear_ms_error(chip);
 			if (ms_card->mg_auth == 0) {
 				if ((buf[5] & 0xC0) != 0)
-					set_sense_type(chip, lun,
+					rts51x_set_sense_type(chip, lun,
 						SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
 				else
-					set_sense_type(chip, lun,
+					rts51x_set_sense_type(chip, lun,
 						SENSE_TYPE_MG_WRITE_ERR);
 			} else {
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MG_WRITE_ERR);
 			}
 			retval = STATUS_FAIL;
@@ -622,13 +622,13 @@ int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 		rts51x_clear_ms_error(chip);
 		if (ms_card->mg_auth == 0) {
 			if ((buf[5] & 0xC0) != 0)
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
 			else
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					SENSE_TYPE_MG_WRITE_ERR);
 		} else {
-			set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
+			rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
 		}
 		TRACE_GOTO(chip, SetICVFinish);
 	}
diff --git a/drivers/staging/rts5139/ms_mg.h b/drivers/staging/rts5139/ms_mg.h
index e2ca550..d15733a 100644
--- a/drivers/staging/rts5139/ms_mg.h
+++ b/drivers/staging/rts5139/ms_mg.h
@@ -30,12 +30,12 @@
 #include "rts51x_chip.h"
 #include "ms.h"
 
-int mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_mg_set_leaf_id(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_mg_get_local_EKB(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_mg_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_mg_get_rsp_chg(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_mg_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_mg_get_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_mg_set_ICV(struct scsi_cmnd *srb, struct rts51x_chip *chip);
 
 #endif /* __RTS51X_MS_MG_H */
diff --git a/drivers/staging/rts5139/rts51x.c b/drivers/staging/rts5139/rts51x.c
index c3fe7dd..0421346 100644
--- a/drivers/staging/rts5139/rts51x.c
+++ b/drivers/staging/rts5139/rts51x.c
@@ -306,7 +306,7 @@ static int rts51x_control_thread(void *__chip)
 
 		/* we've got a command, let's do it! */
 		else {
-			RTS51X_DEBUG(scsi_show_command(chip->srb));
+			RTS51X_DEBUG(rts51x_scsi_show_command(chip->srb));
 			rts51x_invoke_transport(chip->srb, chip);
 		}
 
@@ -397,7 +397,7 @@ static int rts51x_polling_thread(void *__chip)
 		}
 #endif
 
-		mspro_polling_format_status(chip);
+		rts51x_mspro_polling_format_status(chip);
 
 		/* lock the device pointers */
 		mutex_lock(&(chip->usb->dev_mutex));
@@ -478,7 +478,7 @@ static void rts51x_init_options(struct rts51x_chip *chip)
 {
 	struct rts51x_option *option = &(chip->option);
 
-	option->mspro_formatter_enable = 1;
+	option->rts51x_mspro_formatter_enable = 1;
 
 	option->fpga_sd_sdr104_clk = CLK_100;
 	option->fpga_sd_sdr50_clk = CLK_100;
@@ -510,7 +510,7 @@ static void rts51x_init_options(struct rts51x_chip *chip)
 
 	option->FT2_fast_mode = 0;
 	option->pwr_delay = 800;
-	option->xd_rw_step = 0;
+	option->rts51x_xd_rw_step = 0;
 	option->D3318_off_delay = 50;
 	option->delink_delay = 100;
 	option->rts5129_D3318_off_enable = 0;
@@ -518,7 +518,7 @@ static void rts51x_init_options(struct rts51x_chip *chip)
 	option->reset_or_rw_fail_set_pad_drive = 1;
 	option->debounce_num = 2;
 	option->led_toggle_interval = 6;
-	option->xd_rwn_step = 0;
+	option->rts51x_xd_rwn_step = 0;
 	option->sd_send_status_en = 0;
 	option->sdr50_tx_phase = 0x01;
 	option->sdr50_rx_phase = 0x05;
diff --git a/drivers/staging/rts5139/rts51x_card.c b/drivers/staging/rts5139/rts51x_card.c
index 50be42a..509d83e 100644
--- a/drivers/staging/rts5139/rts51x_card.c
+++ b/drivers/staging/rts5139/rts51x_card.c
@@ -41,7 +41,7 @@
 #include "sd.h"
 #include "ms.h"
 
-void do_remaining_work(struct rts51x_chip *chip)
+void rts51x_do_remaining_work(struct rts51x_chip *chip)
 {
 	struct sd_info *sd_card = &(chip->sd_card);
 	struct xd_info *xd_card = &(chip->xd_card);
@@ -84,27 +84,27 @@ void do_remaining_work(struct rts51x_chip *chip)
 	}
 
 	if (sd_card->counter > POLLING_WAIT_CNT)
-		sd_cleanup_work(chip);
+		rts51x_sd_cleanup_work(chip);
 
 	if (xd_card->counter > POLLING_WAIT_CNT)
-		xd_cleanup_work(chip);
+		rts51x_xd_cleanup_work(chip);
 
 	if (ms_card->counter > POLLING_WAIT_CNT)
-		ms_cleanup_work(chip);
+		rts51x_ms_cleanup_work(chip);
 }
 
-static void do_reset_xd_card(struct rts51x_chip *chip)
+static void do_rts51x_reset_xd_card(struct rts51x_chip *chip)
 {
 	int retval;
 
 	if (chip->card2lun[XD_CARD] >= MAX_ALLOWED_LUN_CNT)
 		return;
 
-	retval = reset_xd_card(chip);
+	retval = rts51x_reset_xd_card(chip);
 	if (retval == STATUS_SUCCESS) {
 		chip->card_ready |= XD_CARD;
 		chip->card_fail &= ~XD_CARD;
-		chip->rw_card[chip->card2lun[XD_CARD]] = xd_rw;
+		chip->rw_card[chip->card2lun[XD_CARD]] = rts51x_xd_rw;
 	} else {
 		chip->card_ready &= ~XD_CARD;
 		chip->card_fail |= XD_CARD;
@@ -120,18 +120,18 @@ static void do_reset_xd_card(struct rts51x_chip *chip)
 	}
 }
 
-void do_reset_sd_card(struct rts51x_chip *chip)
+void rts51x_do_rts51x_reset_sd_card(struct rts51x_chip *chip)
 {
 	int retval;
 
 	if (chip->card2lun[SD_CARD] >= MAX_ALLOWED_LUN_CNT)
 		return;
 
-	retval = reset_sd_card(chip);
+	retval = rts51x_reset_sd_card(chip);
 	if (retval == STATUS_SUCCESS) {
 		chip->card_ready |= SD_CARD;
 		chip->card_fail &= ~SD_CARD;
-		chip->rw_card[chip->card2lun[SD_CARD]] = sd_rw;
+		chip->rw_card[chip->card2lun[SD_CARD]] = rts51x_sd_rw;
 	} else {
 		chip->card_ready &= ~SD_CARD;
 		chip->card_fail |= SD_CARD;
@@ -147,18 +147,18 @@ void do_reset_sd_card(struct rts51x_chip *chip)
 	}
 }
 
-static void do_reset_ms_card(struct rts51x_chip *chip)
+static void do_rts51x_reset_ms_card(struct rts51x_chip *chip)
 {
 	int retval;
 
 	if (chip->card2lun[MS_CARD] >= MAX_ALLOWED_LUN_CNT)
 		return;
 
-	retval = reset_ms_card(chip);
+	retval = rts51x_reset_ms_card(chip);
 	if (retval == STATUS_SUCCESS) {
 		chip->card_ready |= MS_CARD;
 		chip->card_fail &= ~MS_CARD;
-		chip->rw_card[chip->card2lun[MS_CARD]] = ms_rw;
+		chip->rw_card[chip->card2lun[MS_CARD]] = rts51x_ms_rw;
 	} else {
 		chip->card_ready &= ~MS_CARD;
 		chip->card_fail |= MS_CARD;
@@ -301,7 +301,7 @@ void rts51x_init_cards(struct rts51x_chip *chip)
 			chip->card_exist &= ~XD_CARD;
 			chip->card_ejected = 0;
 			if (chip->card_ready & XD_CARD) {
-				release_xd_card(chip);
+				rts51x_release_xd_card(chip);
 				chip->rw_card[chip->card2lun[XD_CARD]] = NULL;
 				clear_bit(chip->card2lun[XD_CARD],
 					  &(chip->lun_mc));
@@ -312,7 +312,7 @@ void rts51x_init_cards(struct rts51x_chip *chip)
 			chip->card_exist &= ~SD_CARD;
 			chip->card_ejected = 0;
 			if (chip->card_ready & SD_CARD) {
-				release_sd_card(chip);
+				rts51x_release_sd_card(chip);
 				chip->rw_card[chip->card2lun[SD_CARD]] = NULL;
 				clear_bit(chip->card2lun[SD_CARD],
 					  &(chip->lun_mc));
@@ -323,7 +323,7 @@ void rts51x_init_cards(struct rts51x_chip *chip)
 			chip->card_exist &= ~MS_CARD;
 			chip->card_ejected = 0;
 			if (chip->card_ready & MS_CARD) {
-				release_ms_card(chip);
+				rts51x_release_ms_card(chip);
 				chip->rw_card[chip->card2lun[MS_CARD]] = NULL;
 				clear_bit(chip->card2lun[MS_CARD],
 					  &(chip->lun_mc));
@@ -339,13 +339,13 @@ void rts51x_init_cards(struct rts51x_chip *chip)
 
 		if (need_reset & XD_CARD) {
 			chip->card_exist |= XD_CARD;
-			do_reset_xd_card(chip);
+			do_rts51x_reset_xd_card(chip);
 		} else if (need_reset & SD_CARD) {
 			chip->card_exist |= SD_CARD;
-			do_reset_sd_card(chip);
+			rts51x_do_rts51x_reset_sd_card(chip);
 		} else if (need_reset & MS_CARD) {
 			chip->card_exist |= MS_CARD;
-			do_reset_ms_card(chip);
+			do_rts51x_reset_ms_card(chip);
 		}
 	}
 }
@@ -353,20 +353,20 @@ void rts51x_init_cards(struct rts51x_chip *chip)
 void rts51x_release_cards(struct rts51x_chip *chip)
 {
 	if (chip->card_ready & SD_CARD) {
-		sd_cleanup_work(chip);
-		release_sd_card(chip);
+		rts51x_sd_cleanup_work(chip);
+		rts51x_release_sd_card(chip);
 		chip->card_ready &= ~SD_CARD;
 	}
 
 	if (chip->card_ready & XD_CARD) {
-		xd_cleanup_work(chip);
-		release_xd_card(chip);
+		rts51x_xd_cleanup_work(chip);
+		rts51x_release_xd_card(chip);
 		chip->card_ready &= ~XD_CARD;
 	}
 
 	if (chip->card_ready & MS_CARD) {
-		ms_cleanup_work(chip);
-		release_ms_card(chip);
+		rts51x_ms_cleanup_work(chip);
+		rts51x_release_ms_card(chip);
 		chip->card_ready &= ~MS_CARD;
 	}
 }
@@ -376,7 +376,7 @@ static inline u8 double_depth(u8 depth)
 	return ((depth > 1) ? (depth - 1) : depth);
 }
 
-int switch_ssc_clock(struct rts51x_chip *chip, int clk)
+int rts51x_switch_ssc_clock(struct rts51x_chip *chip, int clk)
 {
 	struct sd_info *sd_card = &(chip->sd_card);
 	struct ms_info *ms_card = &(chip->ms_card);
@@ -513,7 +513,7 @@ int switch_ssc_clock(struct rts51x_chip *chip, int clk)
 	return STATUS_SUCCESS;
 }
 
-int switch_normal_clock(struct rts51x_chip *chip, int clk)
+int rts51x_switch_normal_clock(struct rts51x_chip *chip, int clk)
 {
 	int retval;
 	u8 sel, div, mcu_cnt;
@@ -653,7 +653,7 @@ int switch_normal_clock(struct rts51x_chip *chip, int clk)
 	return STATUS_SUCCESS;
 }
 
-int card_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 sec_addr,
+int rts51x_card_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 sec_addr,
 	    u16 sec_cnt)
 {
 	int retval;
@@ -688,7 +688,7 @@ int card_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 sec_addr,
 	return retval;
 }
 
-u8 get_lun_card(struct rts51x_chip *chip, unsigned int lun)
+u8 rts51x_get_lun_card(struct rts51x_chip *chip, unsigned int lun)
 {
 	if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD)
 		return (u8) XD_CARD;
@@ -744,24 +744,24 @@ int rts51x_select_card(struct rts51x_chip *chip, int card)
 	return STATUS_SUCCESS;
 }
 
-void eject_card(struct rts51x_chip *chip, unsigned int lun)
+void rts51x_eject_card(struct rts51x_chip *chip, unsigned int lun)
 {
 	RTS51X_DEBUGP("eject card\n");
 	RTS51X_SET_STAT(chip, STAT_RUN);
-	do_remaining_work(chip);
+	rts51x_do_remaining_work(chip);
 
 	if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD) {
-		release_sd_card(chip);
+		rts51x_release_sd_card(chip);
 		chip->card_ejected |= SD_CARD;
 		chip->card_ready &= ~SD_CARD;
 		chip->capacity[lun] = 0;
 	} else if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) {
-		release_xd_card(chip);
+		rts51x_release_xd_card(chip);
 		chip->card_ejected |= XD_CARD;
 		chip->card_ready &= ~XD_CARD;
 		chip->capacity[lun] = 0;
 	} else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD) {
-		release_ms_card(chip);
+		rts51x_release_ms_card(chip);
 		chip->card_ejected |= MS_CARD;
 		chip->card_ready &= ~MS_CARD;
 		chip->capacity[lun] = 0;
@@ -770,7 +770,7 @@ void eject_card(struct rts51x_chip *chip, unsigned int lun)
 			      XD_INT | MS_INT | SD_INT);
 }
 
-void trans_dma_enable(enum dma_data_direction dir, struct rts51x_chip *chip,
+void rts51x_trans_dma_enable(enum dma_data_direction dir, struct rts51x_chip *chip,
 		      u32 byte_cnt, u8 pack_size)
 {
 	if (pack_size > DMA_1024)
@@ -798,7 +798,7 @@ void trans_dma_enable(enum dma_data_direction dir, struct rts51x_chip *chip,
 	}
 }
 
-int enable_card_clock(struct rts51x_chip *chip, u8 card)
+int rts51x_enable_card_clock(struct rts51x_chip *chip, u8 card)
 {
 	u8 clk_en = 0;
 
@@ -814,7 +814,7 @@ int enable_card_clock(struct rts51x_chip *chip, u8 card)
 	return STATUS_SUCCESS;
 }
 
-int card_power_on(struct rts51x_chip *chip, u8 card)
+int rts51x_card_power_on(struct rts51x_chip *chip, u8 card)
 {
 	u8 mask, val1, val2;
 
@@ -863,7 +863,7 @@ int monitor_card_cd(struct rts51x_chip *chip, u8 card)
 	return CD_NOT_EXIST;
 }
 
-int toggle_gpio(struct rts51x_chip *chip, u8 gpio)
+int rts51x_toggle_gpio(struct rts51x_chip *chip, u8 gpio)
 {
 	int retval;
 	u8 temp_reg;
@@ -898,7 +898,7 @@ int toggle_gpio(struct rts51x_chip *chip, u8 gpio)
 	return STATUS_SUCCESS;
 }
 
-int turn_on_led(struct rts51x_chip *chip, u8 gpio)
+int rts51x_turn_on_led(struct rts51x_chip *chip, u8 gpio)
 {
 	int retval;
 	u8 gpio_oe[4] = {
@@ -917,7 +917,7 @@ int turn_on_led(struct rts51x_chip *chip, u8 gpio)
 	return STATUS_SUCCESS;
 }
 
-int turn_off_led(struct rts51x_chip *chip, u8 gpio)
+int rts51x_turn_off_led(struct rts51x_chip *chip, u8 gpio)
 {
 	int retval;
 	u8 gpio_output[4] = {
diff --git a/drivers/staging/rts5139/rts51x_card.h b/drivers/staging/rts5139/rts51x_card.h
index c5c03cc..e62b25c 100644
--- a/drivers/staging/rts5139/rts51x_card.h
+++ b/drivers/staging/rts5139/rts51x_card.h
@@ -737,24 +737,24 @@
 
 int monitor_card_cd(struct rts51x_chip *chip, u8 card);
 
-void do_remaining_work(struct rts51x_chip *chip);
-void do_reset_sd_card(struct rts51x_chip *chip);
+void rts51x_do_remaining_work(struct rts51x_chip *chip);
+void rts51x_do_rts51x_reset_sd_card(struct rts51x_chip *chip);
 void rts51x_init_cards(struct rts51x_chip *chip);
 void rts51x_release_cards(struct rts51x_chip *chip);
-int switch_ssc_clock(struct rts51x_chip *chip, int clk);
-int switch_normal_clock(struct rts51x_chip *chip, int clk);
-int card_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 sec_addr,
+int rts51x_switch_ssc_clock(struct rts51x_chip *chip, int clk);
+int rts51x_switch_normal_clock(struct rts51x_chip *chip, int clk);
+int rts51x_card_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 sec_addr,
 	    u16 sec_cnt);
-u8 get_lun_card(struct rts51x_chip *chip, unsigned int lun);
+u8 rts51x_get_lun_card(struct rts51x_chip *chip, unsigned int lun);
 int rts51x_select_card(struct rts51x_chip *chip, int card);
-void eject_card(struct rts51x_chip *chip, unsigned int lun);
-void trans_dma_enable(enum dma_data_direction dir, struct rts51x_chip *chip,
+void rts51x_eject_card(struct rts51x_chip *chip, unsigned int lun);
+void rts51x_trans_dma_enable(enum dma_data_direction dir, struct rts51x_chip *chip,
 		      u32 byte_cnt, u8 pack_size);
-int enable_card_clock(struct rts51x_chip *chip, u8 card);
-int card_power_on(struct rts51x_chip *chip, u8 card);
-int toggle_gpio(struct rts51x_chip *chip, u8 gpio);
-int turn_on_led(struct rts51x_chip *chip, u8 gpio);
-int turn_off_led(struct rts51x_chip *chip, u8 gpio);
+int rts51x_enable_card_clock(struct rts51x_chip *chip, u8 card);
+int rts51x_card_power_on(struct rts51x_chip *chip, u8 card);
+int rts51x_toggle_gpio(struct rts51x_chip *chip, u8 gpio);
+int rts51x_turn_on_led(struct rts51x_chip *chip, u8 gpio);
+int rts51x_turn_off_led(struct rts51x_chip *chip, u8 gpio);
 
 static inline int check_card_ready(struct rts51x_chip *chip, unsigned int lun)
 {
@@ -830,9 +830,9 @@ static inline int switch_clock(struct rts51x_chip *chip, int clk)
 	int retval = 0;
 
 	if (chip->asic_code)
-		retval = switch_ssc_clock(chip, clk);
+		retval = rts51x_switch_ssc_clock(chip, clk);
 	else
-		retval = switch_normal_clock(chip, clk);
+		retval = rts51x_switch_normal_clock(chip, clk);
 
 	return retval;
 }
diff --git a/drivers/staging/rts5139/rts51x_chip.c b/drivers/staging/rts5139/rts51x_chip.c
index 08dcae8..7d7510d 100644
--- a/drivers/staging/rts5139/rts51x_chip.c
+++ b/drivers/staging/rts5139/rts51x_chip.c
@@ -132,7 +132,7 @@ int rts51x_reset_chip(struct rts51x_chip *chip)
 	}
 #endif
 	if (chip->option.FT2_fast_mode) {
-		card_power_on(chip, SD_CARD | MS_CARD | XD_CARD);
+		rts51x_card_power_on(chip, SD_CARD | MS_CARD | XD_CARD);
 		wait_timeout(10);
 	}
 
@@ -212,8 +212,8 @@ int rts51x_init_chip(struct rts51x_chip *chip)
 
 int rts51x_release_chip(struct rts51x_chip *chip)
 {
-	xd_free_l2p_tbl(chip);
-	ms_free_l2p_tbl(chip);
+	rts51x_xd_free_l2p_tbl(chip);
+	rts51x_ms_free_l2p_tbl(chip);
 	chip->card_ready = 0;
 	return STATUS_SUCCESS;
 }
@@ -227,7 +227,7 @@ static inline void rts51x_blink_led(struct rts51x_chip *chip)
 			chip->led_toggle_counter++;
 		} else {
 			chip->led_toggle_counter = 0;
-			toggle_gpio(chip, LED_GPIO);
+			rts51x_toggle_gpio(chip, LED_GPIO);
 		}
 	}
 }
@@ -325,14 +325,14 @@ void rts51x_polling_func(struct rts51x_chip *chip)
 			    && (chip->card_exist &
 				(SD_CARD | MS_CARD | XD_CARD))
 			    && (!chip->card_ejected)) {
-				turn_on_led(chip, LED_GPIO);
+				rts51x_turn_on_led(chip, LED_GPIO);
 			} else {
 				if (chip->rts5179) {
 					rts51x_ep0_write_register(chip,
 								  CARD_GPIO,
 								  0x03, 0x00);
 				} else {
-					turn_off_led(chip, LED_GPIO);
+					rts51x_turn_off_led(chip, LED_GPIO);
 				}
 
 			}
@@ -353,7 +353,7 @@ void rts51x_polling_func(struct rts51x_chip *chip)
 	switch (RTS51X_GET_STAT(chip)) {
 	case STAT_RUN:
 		rts51x_blink_led(chip);
-		do_remaining_work(chip);
+		rts51x_do_remaining_work(chip);
 		break;
 
 	case STAT_IDLE:
@@ -707,7 +707,7 @@ void rts51x_do_before_power_down(struct rts51x_chip *chip)
 	if (chip->rts5179)
 		rts51x_ep0_write_register(chip, CARD_GPIO, 0x03, 0x00);
 	else
-		turn_off_led(chip, LED_GPIO);
+		rts51x_turn_off_led(chip, LED_GPIO);
 
 	chip->cur_clk = 0;
 	chip->card_exist = 0;
@@ -797,7 +797,7 @@ void rts51x_pp_status(struct rts51x_chip *chip, unsigned int lun, u8 *status,
 {
 	struct sd_info *sd_card = &(chip->sd_card);
 	struct ms_info *ms_card = &(chip->ms_card);
-	u8 card = get_lun_card(chip, lun);
+	u8 card = rts51x_get_lun_card(chip, lun);
 #ifdef SUPPORT_OC
 	u8 oc_now_mask = 0, oc_ever_mask = 0;
 #endif
@@ -958,9 +958,9 @@ void rts51x_read_status(struct rts51x_chip *chip, unsigned int lun,
 		rts51x_status[12] = 0;
 
 	/* Detailed Type */
-	if (get_lun_card(chip, lun) == XD_CARD) {
+	if (rts51x_get_lun_card(chip, lun) == XD_CARD) {
 		rts51x_status[13] = 0x40;
-	} else if (get_lun_card(chip, lun) == SD_CARD) {
+	} else if (rts51x_get_lun_card(chip, lun) == SD_CARD) {
 		struct sd_info *sd_card = &(chip->sd_card);
 
 		rts51x_status[13] = 0x20;
@@ -976,7 +976,7 @@ void rts51x_read_status(struct rts51x_chip *chip, unsigned int lun,
 			if (CHK_MMC_SECTOR_MODE(sd_card))
 				rts51x_status[13] |= 0x04; /* Hi capacity */
 		}
-	} else if (get_lun_card(chip, lun) == MS_CARD) {
+	} else if (rts51x_get_lun_card(chip, lun) == MS_CARD) {
 		struct ms_info *ms_card = &(chip->ms_card);
 
 		if (CHK_MSPRO(ms_card)) {
diff --git a/drivers/staging/rts5139/rts51x_chip.h b/drivers/staging/rts5139/rts51x_chip.h
index 64257ca..12deb24 100644
--- a/drivers/staging/rts5139/rts51x_chip.h
+++ b/drivers/staging/rts5139/rts51x_chip.h
@@ -253,7 +253,7 @@ struct sense_data_t {
 #define SUPPORT_UHS50_MMC44		0x40
 
 struct rts51x_option {
-	int mspro_formatter_enable;
+	int rts51x_mspro_formatter_enable;
 
 	/* card clock expected by user for fpga platform */
 	int fpga_sd_sdr104_clk;
@@ -308,7 +308,7 @@ struct rts51x_option {
 	 * add for config delay between 1/4 PMOS and 3/4 PMOS */
 	int pwr_delay;
 
-	int xd_rw_step;		/* add to tune xd tRP */
+	int rts51x_xd_rw_step;		/* add to tune xd tRP */
 	int D3318_off_delay;	/* add to tune D3318 off delay time */
 	int delink_delay;	/* add to tune delink delay time */
 	/* add for rts5129 to enable/disable D3318 off */
@@ -320,7 +320,7 @@ struct rts51x_option {
 
 	u8 debounce_num;	/* debounce number */
 	u8 led_toggle_interval;	/* used to control led toggle speed */
-	int xd_rwn_step;
+	int rts51x_xd_rwn_step;
 	u8 sd_send_status_en;
 	/* used to store default phase which is
 	 * used when phase tune all pass. */
@@ -337,11 +337,11 @@ struct rts51x_option {
 	u8 dv18_voltage;	/* add to tune dv18 voltage */
 };
 
-#define MS_FORMATTER_ENABLED(chip)	((chip)->option.mspro_formatter_enable)
+#define MS_FORMATTER_ENABLED(chip)	((chip)->option.rts51x_mspro_formatter_enable)
 
 struct rts51x_chip;
 
-typedef int (*card_rw_func) (struct scsi_cmnd *srb, struct rts51x_chip *chip,
+typedef int (*rts51x_card_rw_func) (struct scsi_cmnd *srb, struct rts51x_chip *chip,
 			     u32 sec_addr, u16 sec_cnt);
 
 /* For MS Card */
@@ -564,7 +564,7 @@ struct sd_info {
 #define CHK_MS8BIT(ms_card)	(((ms_card)->ms_type & MS_8BIT))
 #define CHK_MS4BIT(ms_card)	(((ms_card)->ms_type & MS_4BIT))
 
-struct ms_delay_write_tag {
+struct rts51x_ms_delay_write_tag {
 	u16 old_phyblock;
 	u16 new_phyblock;
 	u16 logblock;
@@ -605,7 +605,7 @@ struct ms_info {
 	u32 total_sec_cnt;
 	u8 last_rw_int;
 
-	struct ms_delay_write_tag delay_write;
+	struct rts51x_ms_delay_write_tag delay_write;
 
 	int counter;
 
@@ -671,7 +671,7 @@ struct rts51x_chip {
 	u32 capacity[MAX_ALLOWED_LUN_CNT];
 
 	/* read/write card function pointer */
-	card_rw_func rw_card[MAX_ALLOWED_LUN_CNT];
+	rts51x_card_rw_func rw_card[MAX_ALLOWED_LUN_CNT];
 	/* read/write capacity, used for GPIO Toggle */
 	u32 rw_cap[MAX_ALLOWED_LUN_CNT];
 	/* card to lun mapping table */
diff --git a/drivers/staging/rts5139/rts51x_fop.c b/drivers/staging/rts5139/rts51x_fop.c
index bf1a9e6..dee7d8a 100644
--- a/drivers/staging/rts5139/rts51x_fop.c
+++ b/drivers/staging/rts5139/rts51x_fop.c
@@ -70,7 +70,7 @@ static int rts51x_sd_direct_cmnd(struct rts51x_chip *chip,
 	switch (dir) {
 	case 0:
 		/* No data */
-		retval = ext_sd_execute_no_data(chip, chip->card2lun[SD_CARD],
+		retval = ext_rts51x_sd_execute_no_data(chip, chip->card2lun[SD_CARD],
 						cmd_idx, standby, acmd,
 						rsp_code, arg);
 		if (retval != TRANSPORT_GOOD)
@@ -83,7 +83,7 @@ static int rts51x_sd_direct_cmnd(struct rts51x_chip *chip,
 		if (!buf)
 			TRACE_RET(chip, STATUS_NOMEM);
 
-		retval = ext_sd_execute_read_data(chip, chip->card2lun[SD_CARD],
+		retval = ext_rts51x_sd_execute_read_data(chip, chip->card2lun[SD_CARD],
 						  cmd_idx, cmd12, standby, acmd,
 						  rsp_code, arg, len, buf,
 						  cmnd->buf_len, 0);
@@ -117,7 +117,7 @@ static int rts51x_sd_direct_cmnd(struct rts51x_chip *chip,
 		}
 
 		retval =
-		    ext_sd_execute_write_data(chip, chip->card2lun[SD_CARD],
+		    ext_rts51x_sd_execute_write_data(chip, chip->card2lun[SD_CARD],
 					      cmd_idx, cmd12, standby, acmd,
 					      rsp_code, arg, len, buf,
 					      cmnd->buf_len, 0);
diff --git a/drivers/staging/rts5139/rts51x_scsi.c b/drivers/staging/rts5139/rts51x_scsi.c
index e07a1f4..052911c 100644
--- a/drivers/staging/rts5139/rts51x_scsi.c
+++ b/drivers/staging/rts5139/rts51x_scsi.c
@@ -44,7 +44,7 @@
 #include "ms_mg.h"
 #include "trace.h"
 
-void scsi_show_command(struct scsi_cmnd *srb)
+void rts51x_scsi_show_command(struct scsi_cmnd *srb)
 {
 	char *what = NULL;
 	int i, unknown_cmd = 0;
@@ -333,72 +333,72 @@ void scsi_show_command(struct scsi_cmnd *srb)
 	}
 }
 
-void set_sense_type(struct rts51x_chip *chip, unsigned int lun, int sense_type)
+void rts51x_set_sense_type(struct rts51x_chip *chip, unsigned int lun, int sense_type)
 {
 	switch (sense_type) {
 	case SENSE_TYPE_MEDIA_CHANGE:
-		set_sense_data(chip, lun, CUR_ERR, 0x06, 0, 0x28, 0, 0, 0);
+		rts51x_set_sense_data(chip, lun, CUR_ERR, 0x06, 0, 0x28, 0, 0, 0);
 		break;
 
 	case SENSE_TYPE_MEDIA_NOT_PRESENT:
-		set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x3A, 0, 0, 0);
+		rts51x_set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x3A, 0, 0, 0);
 		break;
 
 	case SENSE_TYPE_MEDIA_LBA_OVER_RANGE:
-		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x21, 0, 0, 0);
+		rts51x_set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x21, 0, 0, 0);
 		break;
 
 	case SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT:
-		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x25, 0, 0, 0);
+		rts51x_set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x25, 0, 0, 0);
 		break;
 
 	case SENSE_TYPE_MEDIA_WRITE_PROTECT:
-		set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x27, 0, 0, 0);
+		rts51x_set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x27, 0, 0, 0);
 		break;
 
 	case SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR:
-		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x11, 0, 0, 0);
+		rts51x_set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x11, 0, 0, 0);
 		break;
 
 	case SENSE_TYPE_MEDIA_WRITE_ERR:
-		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x02, 0, 0);
+		rts51x_set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x02, 0, 0);
 		break;
 
 	case SENSE_TYPE_MEDIA_INVALID_CMD_FIELD:
-		set_sense_data(chip, lun, CUR_ERR, ILGAL_REQ, 0,
+		rts51x_set_sense_data(chip, lun, CUR_ERR, ILGAL_REQ, 0,
 			       ASC_INVLD_CDB, ASCQ_INVLD_CDB, CDB_ILLEGAL, 1);
 		break;
 
 	case SENSE_TYPE_FORMAT_CMD_FAILED:
-		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x31, 0x01, 0, 0);
+		rts51x_set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x31, 0x01, 0, 0);
 		break;
 
 #ifdef SUPPORT_MAGIC_GATE
 	case SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB:
-		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x02, 0, 0);
+		rts51x_set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x02, 0, 0);
 		break;
 
 	case SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN:
-		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x00, 0, 0);
+		rts51x_set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x00, 0, 0);
 		break;
 
 	case SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM:
-		set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x30, 0x00, 0, 0);
+		rts51x_set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x30, 0x00, 0, 0);
 		break;
 
 	case SENSE_TYPE_MG_WRITE_ERR:
-		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x00, 0, 0);
+		rts51x_set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x00, 0, 0);
 		break;
 #endif
 
 	case SENSE_TYPE_NO_SENSE:
 	default:
-		set_sense_data(chip, lun, CUR_ERR, 0, 0, 0, 0, 0, 0);
+		rts51x_set_sense_data(chip, lun, CUR_ERR, 0, 0, 0, 0, 0, 0);
 		break;
 	}
 }
 
-void set_sense_data(struct rts51x_chip *chip, unsigned int lun, u8 err_code,
+void rts51x_set_sense_data(struct rts51x_chip *chip, unsigned int lun, u8 err_code,
 		    u8 sense_key, u32 info, u8 asc, u8 ascq, u8 sns_key_info0,
 		    u16 sns_key_info1)
 {
@@ -428,13 +428,13 @@ static int test_unit_ready(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	rts51x_init_cards(chip);
 
 	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 		return TRANSPORT_FAILED;
 	}
 
 	if (!check_lun_mc(chip, lun)) {
 		set_lun_mc(chip, lun);
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
 		return TRANSPORT_FAILED;
 	}
 
@@ -457,7 +457,7 @@ static int inquiry(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	char *inquiry_string;
 	unsigned char sendbytes;
 	unsigned char *buf;
-	u8 card = get_lun_card(chip, lun);
+	u8 card = rts51x_get_lun_card(chip, lun);
 	int pro_formatter_flag = 0;
 	unsigned char inquiry_buf[] = {
 		QULIFIRE | DRCT_ACCESS_DEV,
@@ -532,7 +532,7 @@ static int start_stop_unit(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	case UNLOAD_MEDIUM:
 		/* Media shall be unload */
 		if (check_card_ready(chip, lun))
-			eject_card(chip, lun);
+			rts51x_eject_card(chip, lun);
 		return TRANSPORT_GOOD;
 
 	case MAKE_MEDIUM_READY:
@@ -540,7 +540,7 @@ static int start_stop_unit(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 		if (check_card_ready(chip, lun)) {
 			return TRANSPORT_GOOD;
 		} else {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+			rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
 
@@ -559,7 +559,7 @@ static int allow_medium_removal(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	scsi_set_resid(srb, 0);
 
 	if (prevent) {
-		set_sense_type(chip, SCSI_LUN(srb),
+		rts51x_set_sense_type(chip, SCSI_LUN(srb),
 			       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
@@ -663,10 +663,10 @@ static int mode_sense(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	int status;
 	int pro_formatter_flag;
 	unsigned char pageCode, *buf;
-	u8 card = get_lun_card(chip, lun);
+	u8 card = rts51x_get_lun_card(chip, lun);
 
 	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 		scsi_set_resid(srb, scsi_bufflen(srb));
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
@@ -678,7 +678,7 @@ static int mode_sense(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	if ((get_lun2card(chip, lun) & MS_CARD)) {
 		if (!card || (card == MS_CARD)) {
 			dataSize = 108;
-			if (chip->option.mspro_formatter_enable)
+			if (chip->option.rts51x_mspro_formatter_enable)
 				pro_formatter_flag = 1;
 		}
 	}
@@ -725,7 +725,7 @@ static int mode_sense(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 		}
 		status = TRANSPORT_GOOD;
 	} else {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		scsi_set_resid(srb, scsi_bufflen(srb));
 		status = TRANSPORT_FAILED;
 	}
@@ -749,9 +749,9 @@ static int request_sense(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
 	sense = &(chip->sense_buffer[lun]);
 
-	if ((get_lun_card(chip, lun) == MS_CARD)
+	if ((rts51x_get_lun_card(chip, lun) == MS_CARD)
 	    && PRO_UNDER_FORMATTING(ms_card)) {
-		mspro_format_sense(chip, lun);
+		rts51x_mspro_format_sense(chip, lun);
 	}
 
 	buf = vmalloc(scsi_bufflen(srb));
@@ -766,7 +766,7 @@ static int request_sense(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
 	scsi_set_resid(srb, 0);
 	/* Reset Sense Data */
-	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
+	rts51x_set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
 	return TRANSPORT_GOOD;
 }
 
@@ -778,13 +778,13 @@ static int read_write(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	u16 sec_cnt;
 
 	if (!check_card_ready(chip, lun) || (chip->capacity[lun] == 0)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	if (!check_lun_mc(chip, lun)) {
 		set_lun_mc(chip, lun);
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
 		return TRANSPORT_FAILED;
 	}
 
@@ -812,13 +812,13 @@ static int read_write(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 			((u32) srb->cmnd[7]);
 		sec_cnt = ((u16) (srb->cmnd[9]) << 8) | srb->cmnd[10];
 	} else {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	if ((start_sec > chip->capacity[lun]) ||
 	    ((start_sec + sec_cnt) > chip->capacity[lun])) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LBA_OVER_RANGE);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LBA_OVER_RANGE);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -830,17 +830,17 @@ static int read_write(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	if ((srb->sc_data_direction == DMA_TO_DEVICE)
 	    && check_card_wp(chip, lun)) {
 		RTS51X_DEBUGP("Write protected card!\n");
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
-	retval = card_rw(srb, chip, start_sec, sec_cnt);
+	retval = rts51x_card_rw(srb, chip, start_sec, sec_cnt);
 	if (retval != STATUS_SUCCESS) {
 		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
-			set_sense_type(chip, lun,
+			rts51x_set_sense_type(chip, lun,
 				       SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 		} else {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+			rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
 		}
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
@@ -855,13 +855,13 @@ static int read_format_capacity(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	unsigned char *buf;
 	unsigned int lun = SCSI_LUN(srb);
 	unsigned int buf_len;
-	u8 card = get_lun_card(chip, lun);
+	u8 card = rts51x_get_lun_card(chip, lun);
 	int desc_cnt;
 	int i = 0;
 
 	if (!check_card_ready(chip, lun)) {
-		if (!chip->option.mspro_formatter_enable) {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		if (!chip->option.rts51x_mspro_formatter_enable) {
+			rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
 	}
@@ -877,7 +877,7 @@ static int read_format_capacity(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	buf[i++] = 0;
 
 	/* Capacity List Length */
-	if ((buf_len > 12) && chip->option.mspro_formatter_enable &&
+	if ((buf_len > 12) && chip->option.rts51x_mspro_formatter_enable &&
 	    (chip->lun2card[lun] & MS_CARD) && (!card || (card == MS_CARD))) {
 		buf[i++] = 0x10;
 		desc_cnt = 2;
@@ -933,13 +933,13 @@ static int read_capacity(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	unsigned int lun = SCSI_LUN(srb);
 
 	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	if (!check_lun_mc(chip, lun)) {
 		set_lun_mc(chip, lun);
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
 		return TRANSPORT_FAILED;
 	}
 
@@ -1021,7 +1021,7 @@ static int read_mem(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 		retval = rts51x_ep0_read_register(chip, addr + i, buf + i);
 		if (retval != STATUS_SUCCESS) {
 			vfree(buf);
-			set_sense_type(chip, lun,
+			rts51x_set_sense_type(chip, lun,
 				       SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
@@ -1066,7 +1066,7 @@ static int write_mem(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 		    rts51x_ep0_write_register(chip, addr + i, 0xFF, buf[i]);
 		if (retval != STATUS_SUCCESS) {
 			vfree(buf);
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+			rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
 	}
@@ -1083,12 +1083,12 @@ static int get_sd_csd(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	unsigned int lun = SCSI_LUN(srb);
 
 	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
-	if (get_lun_card(chip, lun) != SD_CARD) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+	if (rts51x_get_lun_card(chip, lun) != SD_CARD) {
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -1120,7 +1120,7 @@ static int read_phy_register(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 			    rts51x_read_phy_register(chip, addr + i, buf + i);
 			if (retval != STATUS_SUCCESS) {
 				vfree(buf);
-				set_sense_type(chip, SCSI_LUN(srb),
+				rts51x_set_sense_type(chip, SCSI_LUN(srb),
 					SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 				TRACE_RET(chip, TRANSPORT_FAILED);
 			}
@@ -1163,7 +1163,7 @@ static int write_phy_register(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 			    rts51x_write_phy_register(chip, addr + i, buf[i]);
 			if (retval != STATUS_SUCCESS) {
 				vfree(buf);
-				set_sense_type(chip, SCSI_LUN(srb),
+				rts51x_set_sense_type(chip, SCSI_LUN(srb),
 					       SENSE_TYPE_MEDIA_WRITE_ERR);
 				TRACE_RET(chip, TRANSPORT_FAILED);
 			}
@@ -1181,15 +1181,15 @@ static int get_card_bus_width(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	u8 card, bus_width;
 
 	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
-	card = get_lun_card(chip, lun);
+	card = rts51x_get_lun_card(chip, lun);
 	if ((card == SD_CARD) || (card == MS_CARD)) {
 		bus_width = chip->card_bus_width[lun];
 	} else {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -1211,7 +1211,7 @@ static int trace_msg_cmd(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	    ((2 + MSG_FUNC_LEN + MSG_FILE_LEN + TIME_VAL_LEN) * TRACE_ITEM_CNT);
 
 	if ((scsi_bufflen(srb) < buf_len) || (scsi_sglist(srb) == NULL)) {
-		set_sense_type(chip, SCSI_LUN(srb),
+		rts51x_set_sense_type(chip, SCSI_LUN(srb),
 			       SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
@@ -1251,7 +1251,7 @@ static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	case ADD_BATCHCMD:
 		cmd_type = srb->cmnd[4];
 		if (cmd_type > 2) {
-			set_sense_type(chip, lun,
+			rts51x_set_sense_type(chip, lun,
 				       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
@@ -1274,13 +1274,13 @@ static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 									  [9]);
 		retval = rts51x_send_cmd(chip, mode, 1000);
 		if (retval != STATUS_SUCCESS) {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+			rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
 		if (mode & STAGE_R) {
 			retval = rts51x_get_rsp(chip, len, timeout);
 			if (retval != STATUS_SUCCESS) {
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 				TRACE_RET(chip, TRANSPORT_FAILED);
 			}
@@ -1291,7 +1291,7 @@ static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 		idx = srb->cmnd[4];
 		value = chip->rsp_buf[idx];
 		if (scsi_bufflen(srb) < 1) {
-			set_sense_type(chip, lun,
+			rts51x_set_sense_type(chip, lun,
 				       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
@@ -1300,12 +1300,12 @@ static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 		break;
 
 	default:
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -1357,7 +1357,7 @@ static int app_cmd(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 		break;
 
 	default:
-		set_sense_type(chip, SCSI_LUN(srb),
+		rts51x_set_sense_type(chip, SCSI_LUN(srb),
 			       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
@@ -1401,7 +1401,7 @@ static int vendor_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 		break;
 
 	default:
-		set_sense_type(chip, SCSI_LUN(srb),
+		rts51x_set_sense_type(chip, SCSI_LUN(srb),
 			       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
@@ -1415,15 +1415,15 @@ static int ms_format_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	unsigned int lun = SCSI_LUN(srb);
 	int retval, quick_format;
 
-	if (get_lun_card(chip, lun) != MS_CARD) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+	if (rts51x_get_lun_card(chip, lun) != MS_CARD) {
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	if ((srb->cmnd[3] != 0x4D) || (srb->cmnd[4] != 0x47)
 	    || (srb->cmnd[5] != 0x66) || (srb->cmnd[6] != 0x6D)
 	    || (srb->cmnd[7] != 0x74)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -1433,26 +1433,26 @@ static int ms_format_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 		quick_format = 1;
 
 	if (!(chip->card_ready & MS_CARD)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	if (chip->card_wp & MS_CARD) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	if (!CHK_MSPRO(ms_card)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	rts51x_prepare_run(chip);
 	RTS51X_SET_STAT(chip, STAT_RUN);
 
-	retval = mspro_format(srb, chip, MS_SHORT_DATA_LEN, quick_format);
+	retval = rts51x_mspro_format(srb, chip, MS_SHORT_DATA_LEN, quick_format);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -1471,18 +1471,18 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	int i;
 
 	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
-	if ((get_lun_card(chip, lun) != MS_CARD)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+	if ((rts51x_get_lun_card(chip, lun) != MS_CARD)) {
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	if ((srb->cmnd[2] != 0xB0) || (srb->cmnd[4] != 0x4D) ||
 	    (srb->cmnd[5] != 0x53) || (srb->cmnd[6] != 0x49) ||
 	    (srb->cmnd[7] != 0x44)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -1490,7 +1490,7 @@ static int get_ms_information(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	if ((CHK_MSXC(ms_card) && (dev_info_id == 0x10)) ||
 	    (!CHK_MSXC(ms_card) && (dev_info_id == 0x13)) ||
 	    !CHK_MSPRO(ms_card)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -1576,44 +1576,44 @@ static int sd_extention_cmnd(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	rts51x_prepare_run(chip);
 	RTS51X_SET_STAT(chip, STAT_RUN);
 
-	sd_cleanup_work(chip);
+	rts51x_sd_cleanup_work(chip);
 
 	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
-	if ((get_lun_card(chip, lun) != SD_CARD)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+	if ((rts51x_get_lun_card(chip, lun) != SD_CARD)) {
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	switch (srb->cmnd[0]) {
 	case SD_PASS_THRU_MODE:
-		result = sd_pass_thru_mode(srb, chip);
+		result = rts51x_sd_pass_thru_mode(srb, chip);
 		break;
 
 	case SD_EXECUTE_NO_DATA:
-		result = sd_execute_no_data(srb, chip);
+		result = rts51x_sd_execute_no_data(srb, chip);
 		break;
 
 	case SD_EXECUTE_READ:
-		result = sd_execute_read_data(srb, chip);
+		result = rts51x_sd_execute_read_data(srb, chip);
 		break;
 
 	case SD_EXECUTE_WRITE:
-		result = sd_execute_write_data(srb, chip);
+		result = rts51x_sd_execute_write_data(srb, chip);
 		break;
 
 	case SD_GET_RSP:
-		result = sd_get_cmd_rsp(srb, chip);
+		result = rts51x_sd_get_cmd_rsp(srb, chip);
 		break;
 
 	case SD_HW_RST:
-		result = sd_hw_rst(srb, chip);
+		result = rts51x_sd_hw_rst(srb, chip);
 		break;
 
 	default:
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -1632,24 +1632,24 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	rts51x_prepare_run(chip);
 	RTS51X_SET_STAT(chip, STAT_RUN);
 
-	ms_cleanup_work(chip);
+	rts51x_ms_cleanup_work(chip);
 
 	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
-	if ((get_lun_card(chip, lun) != MS_CARD)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+	if ((rts51x_get_lun_card(chip, lun) != MS_CARD)) {
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	if (srb->cmnd[7] != KC_MG_R_PRO) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	if (!CHK_MSPRO(ms_card)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -1659,11 +1659,11 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	case KF_GET_LOC_EKB:
 		if ((scsi_bufflen(srb) == 0x41C) &&
 		    (srb->cmnd[8] == 0x04) && (srb->cmnd[9] == 0x1C)) {
-			retval = mg_get_local_EKB(srb, chip);
+			retval = rts51x_mg_get_local_EKB(srb, chip);
 			if (retval != STATUS_SUCCESS)
 				TRACE_RET(chip, TRANSPORT_FAILED);
 		} else {
-			set_sense_type(chip, lun,
+			rts51x_set_sense_type(chip, lun,
 				       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
@@ -1672,11 +1672,11 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	case KF_RSP_CHG:
 		if ((scsi_bufflen(srb) == 0x24) &&
 		    (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x24)) {
-			retval = mg_get_rsp_chg(srb, chip);
+			retval = rts51x_mg_get_rsp_chg(srb, chip);
 			if (retval != STATUS_SUCCESS)
 				TRACE_RET(chip, TRANSPORT_FAILED);
 		} else {
-			set_sense_type(chip, lun,
+			rts51x_set_sense_type(chip, lun,
 				       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
@@ -1690,18 +1690,18 @@ static int mg_report_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 		    (srb->cmnd[2] == 0x00) &&
 		    (srb->cmnd[3] == 0x00) &&
 		    (srb->cmnd[4] == 0x00) && (srb->cmnd[5] < 32)) {
-			retval = mg_get_ICV(srb, chip);
+			retval = rts51x_mg_get_ICV(srb, chip);
 			if (retval != STATUS_SUCCESS)
 				TRACE_RET(chip, TRANSPORT_FAILED);
 		} else {
-			set_sense_type(chip, lun,
+			rts51x_set_sense_type(chip, lun,
 				       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
 		break;
 
 	default:
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -1719,28 +1719,28 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	rts51x_prepare_run(chip);
 	RTS51X_SET_STAT(chip, STAT_RUN);
 
-	ms_cleanup_work(chip);
+	rts51x_ms_cleanup_work(chip);
 
 	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 	if (check_card_wp(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
-	if ((get_lun_card(chip, lun) != MS_CARD)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+	if ((rts51x_get_lun_card(chip, lun) != MS_CARD)) {
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	if (srb->cmnd[7] != KC_MG_R_PRO) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	if (!CHK_MSPRO(ms_card)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -1750,11 +1750,11 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	case KF_SET_LEAF_ID:
 		if ((scsi_bufflen(srb) == 0x0C) &&
 		    (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x0C)) {
-			retval = mg_set_leaf_id(srb, chip);
+			retval = rts51x_mg_set_leaf_id(srb, chip);
 			if (retval != STATUS_SUCCESS)
 				TRACE_RET(chip, TRANSPORT_FAILED);
 		} else {
-			set_sense_type(chip, lun,
+			rts51x_set_sense_type(chip, lun,
 				       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
@@ -1763,11 +1763,11 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	case KF_CHG_HOST:
 		if ((scsi_bufflen(srb) == 0x0C) &&
 		    (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x0C)) {
-			retval = mg_chg(srb, chip);
+			retval = rts51x_mg_chg(srb, chip);
 			if (retval != STATUS_SUCCESS)
 				TRACE_RET(chip, TRANSPORT_FAILED);
 		} else {
-			set_sense_type(chip, lun,
+			rts51x_set_sense_type(chip, lun,
 				       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
@@ -1776,11 +1776,11 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	case KF_RSP_HOST:
 		if ((scsi_bufflen(srb) == 0x0C) &&
 		    (srb->cmnd[8] == 0x00) && (srb->cmnd[9] == 0x0C)) {
-			retval = mg_rsp(srb, chip);
+			retval = rts51x_mg_rsp(srb, chip);
 			if (retval != STATUS_SUCCESS)
 				TRACE_RET(chip, TRANSPORT_FAILED);
 		} else {
-			set_sense_type(chip, lun,
+			rts51x_set_sense_type(chip, lun,
 				       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
@@ -1794,18 +1794,18 @@ static int mg_send_key(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 		    (srb->cmnd[2] == 0x00) &&
 		    (srb->cmnd[3] == 0x00) &&
 		    (srb->cmnd[4] == 0x00) && (srb->cmnd[5] < 32)) {
-			retval = mg_set_ICV(srb, chip);
+			retval = rts51x_mg_set_ICV(srb, chip);
 			if (retval != STATUS_SUCCESS)
 				TRACE_RET(chip, TRANSPORT_FAILED);
 		} else {
-			set_sense_type(chip, lun,
+			rts51x_set_sense_type(chip, lun,
 				       SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
 		break;
 
 	default:
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -1820,12 +1820,12 @@ int rts51x_scsi_handler(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	unsigned int lun = SCSI_LUN(srb);
 	int result = TRANSPORT_GOOD;
 
-	if ((get_lun_card(chip, lun) == MS_CARD) &&
+	if ((rts51x_get_lun_card(chip, lun) == MS_CARD) &&
 	    (ms_card->format_status == FORMAT_IN_PROGRESS)) {
 		if ((srb->cmnd[0] != REQUEST_SENSE)
 		    && (srb->cmnd[0] != INQUIRY)) {
 			/* Logical Unit Not Ready Format in Progress */
-			set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
+			rts51x_set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
 				       0, (u16) (ms_card->progress));
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
@@ -1908,7 +1908,7 @@ int rts51x_scsi_handler(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 		break;
 
 	default:
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		result = TRANSPORT_FAILED;
 	}
 
diff --git a/drivers/staging/rts5139/rts51x_scsi.h b/drivers/staging/rts5139/rts51x_scsi.h
index 9042bc9..cdfe550 100644
--- a/drivers/staging/rts5139/rts51x_scsi.h
+++ b/drivers/staging/rts5139/rts51x_scsi.h
@@ -133,9 +133,9 @@ struct rts51x_chip;
 
 #define SCSI                    0x00	/* Interface ID                     */
 
-void scsi_show_command(struct scsi_cmnd *srb);
-void set_sense_type(struct rts51x_chip *chip, unsigned int lun, int sense_type);
-void set_sense_data(struct rts51x_chip *chip, unsigned int lun, u8 err_code,
+void rts51x_scsi_show_command(struct scsi_cmnd *srb);
+void rts51x_set_sense_type(struct rts51x_chip *chip, unsigned int lun, int sense_type);
+void rts51x_set_sense_data(struct rts51x_chip *chip, unsigned int lun, u8 err_code,
 		    u8 sense_key, u32 info, u8 asc, u8 ascq, u8 sns_key_info0,
 		    u16 sns_key_info1);
 
diff --git a/drivers/staging/rts5139/sd.c b/drivers/staging/rts5139/sd.c
index b739f26..4283b09 100644
--- a/drivers/staging/rts5139/sd.c
+++ b/drivers/staging/rts5139/sd.c
@@ -680,7 +680,7 @@ static int sd_set_init_para(struct rts51x_chip *chip)
 	return STATUS_SUCCESS;
 }
 
-int sd_select_card(struct rts51x_chip *chip, int select)
+int rts51x_sd_select_card(struct rts51x_chip *chip, int select)
 {
 	struct sd_info *sd_card = &(chip->sd_card);
 	int retval;
@@ -1747,7 +1747,7 @@ static int mmc_ddr_tuning(struct rts51x_chip *chip)
 	return STATUS_SUCCESS;
 }
 
-int sd_switch_clock(struct rts51x_chip *chip)
+int rts51x_sd_switch_clock(struct rts51x_chip *chip)
 {
 	struct sd_info *sd_card = &(chip->sd_card);
 	int retval;
@@ -1913,7 +1913,7 @@ static int sd_init_power(struct rts51x_chip *chip)
 #endif
 
 		/* Power on card */
-		retval = card_power_on(chip, SD_CARD);
+		retval = rts51x_card_power_on(chip, SD_CARD);
 		if (retval != STATUS_SUCCESS)
 			TRACE_RET(chip, retval);
 
@@ -2139,7 +2139,7 @@ RTY_CMD55:
 	if (retval != STATUS_SUCCESS)
 		TRACE_RET(chip, retval);
 	/* Select SD card */
-	retval = sd_select_card(chip, 1);
+	retval = rts51x_sd_select_card(chip, 1);
 	if (retval != STATUS_SUCCESS)
 		TRACE_RET(chip, retval);
 
@@ -2656,7 +2656,7 @@ RTY_MMC_RST:
 	spec_ver = (sd_card->raw_csd[0] & 0x3C) >> 2;
 
 	/* Select MMC card */
-	retval = sd_select_card(chip, 1);
+	retval = rts51x_sd_select_card(chip, 1);
 	if (retval != STATUS_SUCCESS)
 		TRACE_RET(chip, retval);
 
@@ -2748,7 +2748,7 @@ RTY_MMC_RST:
 	return STATUS_SUCCESS;
 }
 
-int reset_sd_card(struct rts51x_chip *chip)
+int rts51x_reset_sd_card(struct rts51x_chip *chip)
 {
 	struct sd_info *sd_card = &(chip->sd_card);
 	int retval;
@@ -2764,7 +2764,7 @@ int reset_sd_card(struct rts51x_chip *chip)
 	sd_card->sd_switch_fail = 0;
 
 	sd_clear_reset_fail(chip);
-	enable_card_clock(chip, SD_CARD);
+	rts51x_enable_card_clock(chip, SD_CARD);
 
 	sd_init_power(chip);
 
@@ -2891,7 +2891,7 @@ static void sd_stop_seq_mode(struct rts51x_chip *chip)
 	int retval;
 
 	if (sd_card->seq_mode) {
-		retval = sd_switch_clock(chip);
+		retval = rts51x_sd_switch_clock(chip);
 		if (retval != STATUS_SUCCESS)
 			return;
 
@@ -2923,14 +2923,14 @@ static inline int sd_auto_tune_clock(struct rts51x_chip *chip)
 			sd_card->sd_clock = CLK_50;
 	}
 
-	retval = sd_switch_clock(chip);
+	retval = rts51x_sd_switch_clock(chip);
 	if (retval != STATUS_SUCCESS)
 		TRACE_RET(chip, retval);
 
 	return STATUS_SUCCESS;
 }
 
-int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
+int rts51x_sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 	  u16 sector_cnt)
 {
 	struct sd_info *sd_card = &(chip->sd_card);
@@ -2947,11 +2947,11 @@ int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 	else
 		data_addr = start_sector;
 
-	RTS51X_DEBUGP("sd_rw, data_addr = 0x%x\n", data_addr);
+	RTS51X_DEBUGP("rts51x_sd_rw, data_addr = 0x%x\n", data_addr);
 
 	sd_clr_err_code(chip);
 
-	retval = sd_switch_clock(chip);
+	retval = rts51x_sd_switch_clock(chip);
 	if (retval != STATUS_SUCCESS)
 		TRACE_RET(chip, retval);
 
@@ -3020,7 +3020,7 @@ int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 			       SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 |
 			       SD_RSP_LEN_0);
 
-		trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512,
+		rts51x_trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512,
 				 DMA_512);
 
 		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
@@ -3058,7 +3058,7 @@ int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 				       SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 |
 				       SD_RSP_LEN_6);
 
-			trans_dma_enable(srb->sc_data_direction, chip,
+			rts51x_trans_dma_enable(srb->sc_data_direction, chip,
 					 sector_cnt * 512, DMA_512);
 
 			rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
@@ -3099,7 +3099,7 @@ int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 				       SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 |
 				       SD_RSP_LEN_0);
 
-			trans_dma_enable(srb->sc_data_direction, chip,
+			rts51x_trans_dma_enable(srb->sc_data_direction, chip,
 					 sector_cnt * 512, DMA_512);
 
 			rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
@@ -3168,7 +3168,7 @@ int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 	return STATUS_SUCCESS;
 }
 
-void sd_cleanup_work(struct rts51x_chip *chip)
+void rts51x_sd_cleanup_work(struct rts51x_chip *chip)
 {
 	struct sd_info *sd_card = &(chip->sd_card);
 
@@ -3220,12 +3220,12 @@ static int sd_power_off_card3v3(struct rts51x_chip *chip)
 	return STATUS_SUCCESS;
 }
 
-int release_sd_card(struct rts51x_chip *chip)
+int rts51x_release_sd_card(struct rts51x_chip *chip)
 {
 	struct sd_info *sd_card = &(chip->sd_card);
 	int retval;
 
-	RTS51X_DEBUGP("release_sd_card\n");
+	RTS51X_DEBUGP("rts51x_release_sd_card\n");
 
 	chip->card_ready &= ~SD_CARD;
 	chip->card_fail &= ~SD_CARD;
diff --git a/drivers/staging/rts5139/sd.h b/drivers/staging/rts5139/sd.h
index de155d8..7dd943f 100644
--- a/drivers/staging/rts5139/sd.h
+++ b/drivers/staging/rts5139/sd.h
@@ -256,13 +256,13 @@ struct timing_phase_path {
 	int len;
 };
 
-int sd_select_card(struct rts51x_chip *chip, int select);
-int reset_sd_card(struct rts51x_chip *chip);
-int sd_switch_clock(struct rts51x_chip *chip);
-int sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
+int rts51x_sd_select_card(struct rts51x_chip *chip, int select);
+int rts51x_reset_sd_card(struct rts51x_chip *chip);
+int rts51x_sd_switch_clock(struct rts51x_chip *chip);
+int rts51x_sd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 	  u16 sector_cnt);
-void sd_cleanup_work(struct rts51x_chip *chip);
-int release_sd_card(struct rts51x_chip *chip);
+void rts51x_sd_cleanup_work(struct rts51x_chip *chip);
+int rts51x_release_sd_card(struct rts51x_chip *chip);
 
 #ifdef SUPPORT_CPRM
 extern int reset_sd(struct rts51x_chip *chip);
diff --git a/drivers/staging/rts5139/sd_cprm.c b/drivers/staging/rts5139/sd_cprm.c
index 0167f7f..d468983 100644
--- a/drivers/staging/rts5139/sd_cprm.c
+++ b/drivers/staging/rts5139/sd_cprm.c
@@ -269,7 +269,7 @@ static int ext_sd_get_rsp(struct rts51x_chip *chip, int len,
 	return STATUS_SUCCESS;
 }
 
-int ext_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
+int ext_rts51x_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
 			   u8 cmd_idx, u8 standby, u8 acmd, u8 rsp_code,
 			   u32 arg)
 {
@@ -277,30 +277,30 @@ int ext_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
 	int retval, rsp_len;
 	u8 rsp_type;
 
-	retval = sd_switch_clock(chip);
+	retval = rts51x_sd_switch_clock(chip);
 	if (retval != STATUS_SUCCESS)
 		TRACE_RET(chip, TRANSPORT_FAILED);
 
 	if (sd_card->pre_cmd_err) {
 		sd_card->pre_cmd_err = 0;
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 	retval = get_rsp_type(rsp_code, &rsp_type, &rsp_len);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 	sd_card->last_rsp_type = rsp_type;
 
-	retval = sd_switch_clock(chip);
+	retval = rts51x_sd_switch_clock(chip);
 	if (retval != STATUS_SUCCESS)
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	/* Set H/W SD/MMC Bus Width */
 	rts51x_write_register(chip, SD_CFG1, 0x03, SD_BUS_WIDTH_4);
 
 	if (standby) {
-		retval = sd_select_card(chip, 0);
+		retval = rts51x_sd_select_card(chip, 0);
 		if (retval != STATUS_SUCCESS)
 			TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
 	}
@@ -319,7 +319,7 @@ int ext_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
 		TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
 
 	if (standby) {
-		retval = sd_select_card(chip, 1);
+		retval = rts51x_sd_select_card(chip, 1);
 		if (retval != STATUS_SUCCESS)
 			TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
 	}
@@ -328,16 +328,16 @@ int ext_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
 
 SD_Execute_Cmd_Failed:
 	sd_card->pre_cmd_err = 1;
-	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
-	release_sd_card(chip);
-	do_reset_sd_card(chip);
+	rts51x_set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
+	rts51x_release_sd_card(chip);
+	rts51x_do_rts51x_reset_sd_card(chip);
 	if (!(chip->card_ready & SD_CARD))
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 
 	TRACE_RET(chip, TRANSPORT_FAILED);
 }
 
-int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
+int ext_rts51x_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
 			     u8 cmd_idx, u8 cmd12, u8 standby,
 			     u8 acmd, u8 rsp_code, u32 arg, u32 data_len,
 			     void *data_buf, unsigned int buf_len, int use_sg)
@@ -349,21 +349,21 @@ int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
 
 	if (sd_card->pre_cmd_err) {
 		sd_card->pre_cmd_err = 0;
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
-	retval = sd_switch_clock(chip);
+	retval = rts51x_sd_switch_clock(chip);
 	if (retval != STATUS_SUCCESS)
 		TRACE_RET(chip, STATUS_FAIL);
 	retval = get_rsp_type(rsp_code, &rsp_type, &rsp_len);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 	sd_card->last_rsp_type = rsp_type;
 
-	retval = sd_switch_clock(chip);
+	retval = rts51x_sd_switch_clock(chip);
 	if (retval != STATUS_SUCCESS)
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	bus_width = SD_BUS_WIDTH_4;
@@ -376,7 +376,7 @@ int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
 	}
 
 	if (standby) {
-		retval = sd_select_card(chip, 0);
+		retval = rts51x_sd_select_card(chip, 0);
 		if (retval != STATUS_SUCCESS)
 			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
 	}
@@ -448,7 +448,7 @@ int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
 		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8) arg);
 		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, 0x03, bus_width);
 		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type);
-		trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512);
+		rts51x_trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512);
 		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
 			       SD_TM_AUTO_READ_2 | SD_TRANSFER_START);
 		rts51x_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER,
@@ -490,7 +490,7 @@ int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
 		TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
 
 	if (standby) {
-		retval = sd_select_card(chip, 1);
+		retval = rts51x_sd_select_card(chip, 1);
 		if (retval != STATUS_SUCCESS)
 			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
 	}
@@ -531,18 +531,18 @@ int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
 
 SD_Execute_Read_Cmd_Failed:
 	sd_card->pre_cmd_err = 1;
-	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
+	rts51x_set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
 	if (read_err)
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-	release_sd_card(chip);
-	do_reset_sd_card(chip);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+	rts51x_release_sd_card(chip);
+	rts51x_do_rts51x_reset_sd_card(chip);
 	if (!(chip->card_ready & SD_CARD))
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 
 	TRACE_RET(chip, TRANSPORT_FAILED);
 }
 
-int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
+int ext_rts51x_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
 			      u8 cmd_idx, u8 cmd12, u8 standby, u8 acmd,
 			      u8 rsp_code, u32 arg, u32 data_len,
 			      void *data_buf, unsigned int buf_len, int use_sg)
@@ -555,22 +555,22 @@ int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
 
 	if (sd_card->pre_cmd_err) {
 		sd_card->pre_cmd_err = 0;
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
-	retval = sd_switch_clock(chip);
+	retval = rts51x_sd_switch_clock(chip);
 	if (retval != STATUS_SUCCESS)
 		TRACE_RET(chip, STATUS_FAIL);
 
 	retval = get_rsp_type(rsp_code, &rsp_type, &rsp_len);
 	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 	sd_card->last_rsp_type = rsp_type;
 
-	retval = sd_switch_clock(chip);
+	retval = rts51x_sd_switch_clock(chip);
 	if (retval != STATUS_SUCCESS)
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	rts51x_write_register(chip, SD_CFG1, 0x03, SD_BUS_WIDTH_4);
@@ -583,7 +583,7 @@ int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
 	}
 
 	if (standby) {
-		retval = sd_select_card(chip, 0);
+		retval = rts51x_sd_select_card(chip, 0);
 		if (retval != STATUS_SUCCESS)
 			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
 	}
@@ -690,7 +690,7 @@ int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
 		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L,
 			       0xFF, (u8) ((data_len & 0x0001FE00) >> 9));
 
-		trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512);
+		rts51x_trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512);
 
 		rts51x_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
 			       SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
@@ -724,7 +724,7 @@ int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
 	}
 
 	if (standby) {
-		retval = sd_select_card(chip, 1);
+		retval = rts51x_sd_select_card(chip, 1);
 		if (retval != STATUS_SUCCESS)
 			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
 	}
@@ -767,18 +767,18 @@ int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
 
 SD_Execute_Write_Cmd_Failed:
 	sd_card->pre_cmd_err = 1;
-	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
+	rts51x_set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
 	if (write_err)
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-	release_sd_card(chip);
-	do_reset_sd_card(chip);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+	rts51x_release_sd_card(chip);
+	rts51x_do_rts51x_reset_sd_card(chip);
 	if (!(chip->card_ready & SD_CARD))
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 
 	TRACE_RET(chip, TRANSPORT_FAILED);
 }
 
-int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
 	struct sd_info *sd_card = &(chip->sd_card);
 	unsigned int lun = SCSI_LUN(srb);
@@ -808,7 +808,7 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 
 	if (!(CHK_BIT(chip->lun_mc, lun))) {
 		SET_BIT(chip->lun_mc, lun);
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -816,7 +816,7 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	    || (0x20 != srb->cmnd[4]) || (0x43 != srb->cmnd[5])
 	    || (0x61 != srb->cmnd[6]) || (0x72 != srb->cmnd[7])
 	    || (0x64 != srb->cmnd[8])) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -830,7 +830,7 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 		break;
 
 	default:
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -850,7 +850,7 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	return TRANSPORT_GOOD;
 }
 
-int sd_execute_no_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_sd_execute_no_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
 	struct sd_info *sd_card = &(chip->sd_card);
 	unsigned int lun = SCSI_LUN(srb);
@@ -860,7 +860,7 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	u32 arg;
 
 	if (!sd_card->sd_pass_thru_en) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -876,13 +876,13 @@ int sd_execute_no_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	rsp_code = srb->cmnd[10];
 
 	retval =
-	    ext_sd_execute_no_data(chip, lun, cmd_idx, standby, acmd, rsp_code,
+	    ext_rts51x_sd_execute_no_data(chip, lun, cmd_idx, standby, acmd, rsp_code,
 				   arg);
 	scsi_set_resid(srb, 0);
 	return retval;
 }
 
-int sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
 	struct sd_info *sd_card = &(chip->sd_card);
 	int retval;
@@ -891,7 +891,7 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	u32 arg, data_len;
 
 	if (!sd_card->sd_pass_thru_en) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -912,7 +912,7 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	rsp_code = srb->cmnd[10];
 
 	retval =
-	    ext_sd_execute_read_data(chip, lun, cmd_idx, send_cmd12, standby,
+	    ext_rts51x_sd_execute_read_data(chip, lun, cmd_idx, send_cmd12, standby,
 				     acmd, rsp_code, arg, data_len,
 				     scsi_sglist(srb), scsi_bufflen(srb),
 				     scsi_sg_count(srb));
@@ -920,7 +920,7 @@ int sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	return retval;
 }
 
-int sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
 	struct sd_info *sd_card = &(chip->sd_card);
 	int retval;
@@ -929,7 +929,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	u32 data_len, arg;
 
 	if (!sd_card->sd_pass_thru_en) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -950,7 +950,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	rsp_code = srb->cmnd[10];
 
 	retval =
-	    ext_sd_execute_write_data(chip, lun, cmd_idx, send_cmd12, standby,
+	    ext_rts51x_sd_execute_write_data(chip, lun, cmd_idx, send_cmd12, standby,
 				      acmd, rsp_code, arg, data_len,
 				      scsi_sglist(srb), scsi_bufflen(srb),
 				      scsi_sg_count(srb));
@@ -958,7 +958,7 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	return retval;
 }
 
-int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
 	struct sd_info *sd_card = &(chip->sd_card);
 	unsigned int lun = SCSI_LUN(srb);
@@ -966,20 +966,20 @@ int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	u16 data_len;
 
 	if (!sd_card->sd_pass_thru_en) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	if (sd_card->pre_cmd_err) {
 		sd_card->pre_cmd_err = 0;
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	data_len = ((u16) srb->cmnd[7] << 8) | srb->cmnd[8];
 
 	if (sd_card->last_rsp_type == SD_RSP_TYPE_R0) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	} else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2) {
 		count = (data_len < 17) ? data_len : 17;
@@ -997,20 +997,20 @@ int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	return TRANSPORT_GOOD;
 }
 
-int sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip)
+int rts51x_sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 {
 	struct sd_info *sd_card = &(chip->sd_card);
 	unsigned int lun = SCSI_LUN(srb);
 	int retval;
 
 	if (!sd_card->sd_pass_thru_en) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	if (sd_card->pre_cmd_err) {
 		sd_card->pre_cmd_err = 0;
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
@@ -1018,16 +1018,16 @@ int sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 	    || (0x20 != srb->cmnd[4]) || (0x43 != srb->cmnd[5])
 	    || (0x61 != srb->cmnd[6]) || (0x72 != srb->cmnd[7])
 	    || (0x64 != srb->cmnd[8])) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
 	switch (srb->cmnd[1] & 0x0F) {
 	case 0:
 		/* SD Card Power Off -> ON and Initialization */
-		retval = reset_sd_card(chip);
+		retval = rts51x_reset_sd_card(chip);
 		if (retval != STATUS_SUCCESS) {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+			rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 			sd_card->pre_cmd_err = 1;
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
@@ -1038,14 +1038,14 @@ int sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip)
 		 * (without SD Card Power Off -> ON) */
 		retval = reset_sd(chip);
 		if (retval != STATUS_SUCCESS) {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+			rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 			sd_card->pre_cmd_err = 1;
 			TRACE_RET(chip, TRANSPORT_FAILED);
 		}
 		break;
 
 	default:
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
 		TRACE_RET(chip, TRANSPORT_FAILED);
 	}
 
diff --git a/drivers/staging/rts5139/sd_cprm.h b/drivers/staging/rts5139/sd_cprm.h
index 75e263b..79dfd27 100644
--- a/drivers/staging/rts5139/sd_cprm.h
+++ b/drivers/staging/rts5139/sd_cprm.h
@@ -31,24 +31,24 @@
 #include "sd.h"
 
 #ifdef SUPPORT_CPRM
-int ext_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
+int ext_rts51x_sd_execute_no_data(struct rts51x_chip *chip, unsigned int lun,
 			   u8 cmd_idx, u8 standby, u8 acmd, u8 rsp_code,
 			   u32 arg);
-int ext_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
+int ext_rts51x_sd_execute_read_data(struct rts51x_chip *chip, unsigned int lun,
 			     u8 cmd_idx, u8 cmd12, u8 standby, u8 acmd,
 			     u8 rsp_code, u32 arg, u32 data_len, void *data_buf,
 			     unsigned int buf_len, int use_sg);
-int ext_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
+int ext_rts51x_sd_execute_write_data(struct rts51x_chip *chip, unsigned int lun,
 			      u8 cmd_idx, u8 cmd12, u8 standby, u8 acmd,
 			      u8 rsp_code, u32 arg, u32 data_len,
 			      void *data_buf, unsigned int buf_len, int use_sg);
 
-int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int sd_execute_no_data(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip);
-int sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_sd_pass_thru_mode(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_sd_execute_no_data(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_sd_execute_read_data(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_sd_execute_write_data(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rts51x_chip *chip);
+int rts51x_sd_hw_rst(struct scsi_cmnd *srb, struct rts51x_chip *chip);
 #endif
 
 #endif /* __RTS51X_SD_CPRM_H */
diff --git a/drivers/staging/rts5139/xd.c b/drivers/staging/rts5139/xd.c
index 58f8ba2..10fea7e 100644
--- a/drivers/staging/rts5139/xd.c
+++ b/drivers/staging/rts5139/xd.c
@@ -425,7 +425,7 @@ static int reset_xd(struct rts51x_chip *chip)
 		}
 #endif
 
-		retval = card_power_on(chip, XD_CARD);
+		retval = rts51x_card_power_on(chip, XD_CARD);
 		if (retval != STATUS_SUCCESS)
 			TRACE_RET(chip, retval);
 #ifdef SUPPORT_OCP
@@ -472,8 +472,8 @@ static int reset_xd(struct rts51x_chip *chip)
 		rts51x_init_cmd(chip);
 		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_DTCTL, 0xFF,
 			XD_TIME_SETUP_STEP * 3 + XD_TIME_RW_STEP *
-			(2 + i + chip->option.xd_rw_step)
-			+ XD_TIME_RWN_STEP * (i + chip->option.xd_rwn_step));
+			(2 + i + chip->option.rts51x_xd_rw_step)
+			+ XD_TIME_RWN_STEP * (i + chip->option.rts51x_xd_rwn_step));
 		rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CATCTL, 0xFF,
 			XD_TIME_SETUP_STEP * 3 + XD_TIME_RW_STEP * (4 +
 			i) + XD_TIME_RWN_STEP * (3 + i));
@@ -905,7 +905,7 @@ static u32 xd_get_l2p_tbl(struct rts51x_chip *chip, int zone_no, u16 log_off)
 	return (u32) zone->l2p_table[log_off] + ((u32) (zone_no) << 10);
 }
 
-int reset_xd_card(struct rts51x_chip *chip)
+int rts51x_reset_xd_card(struct rts51x_chip *chip)
 {
 	struct xd_info *xd_card = &(chip->xd_card);
 	int retval;
@@ -920,7 +920,7 @@ int reset_xd_card(struct rts51x_chip *chip)
 	xd_card->cis_block = 0xFFFF;
 	xd_card->delay_write.delay_write_flag = 0;
 
-	enable_card_clock(chip, XD_CARD);
+	rts51x_enable_card_clock(chip, XD_CARD);
 
 	retval = reset_xd(chip);
 	if (retval != STATUS_SUCCESS) {
@@ -1526,7 +1526,7 @@ static int xd_read_multiple_pages(struct rts51x_chip *chip, u32 phy_blk,
 	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS,
 		       XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS);
 
-	trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512,
+	rts51x_trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512,
 			 DMA_512);
 
 	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
@@ -1745,7 +1745,7 @@ static int xd_write_multiple_pages(struct rts51x_chip *chip, u32 old_blk,
 	rts51x_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
 		       RING_BUFFER);
 
-	trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512,
+	rts51x_trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512,
 			 DMA_512);
 
 	rts51x_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
@@ -1842,7 +1842,7 @@ static int xd_delay_write(struct rts51x_chip *chip)
 	return STATUS_SUCCESS;
 }
 
-int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
+int rts51x_xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 	  u16 sector_cnt)
 {
 	struct xd_info *xd_card = &(chip->xd_card);
@@ -1860,7 +1860,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 
 	xd_card->counter = 0;
 
-	RTS51X_DEBUGP("xd_rw: scsi_bufflen = %d, scsi_sg_count = %d\n",
+	RTS51X_DEBUGP("rts51x_xd_rw: scsi_bufflen = %d, scsi_sg_count = %d\n",
 		       scsi_bufflen(srb), scsi_sg_count(srb));
 	RTS51X_DEBUGP("Data direction: %s\n",
 		       (srb->sc_data_direction ==
@@ -1883,7 +1883,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 		retval = xd_build_l2p_tbl(chip, zone_no);
 		if (retval != STATUS_SUCCESS) {
 			chip->card_fail |= XD_CARD;
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+			rts51x_set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
 			TRACE_RET(chip, retval);
 		}
 	}
@@ -1900,7 +1900,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 						      delay_write->pageoff,
 						      start_page);
 				if (retval != STATUS_SUCCESS) {
-					set_sense_type(chip, lun,
+					rts51x_set_sense_type(chip, lun,
 						SENSE_TYPE_MEDIA_WRITE_ERR);
 					TRACE_RET(chip, retval);
 				}
@@ -1916,7 +1916,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 		} else {
 			retval = xd_delay_write(chip);
 			if (retval != STATUS_SUCCESS) {
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MEDIA_WRITE_ERR);
 				TRACE_RET(chip, retval);
 			}
@@ -1924,7 +1924,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 			new_blk = xd_get_unused_block(chip, zone_no);
 			if ((old_blk == BLK_NOT_FOUND)
 			    || (new_blk == BLK_NOT_FOUND)) {
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MEDIA_WRITE_ERR);
 				TRACE_RET(chip, retval);
 			}
@@ -1935,11 +1935,11 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 			if (retval != STATUS_SUCCESS) {
 				if (monitor_card_cd(chip, XD_CARD) ==
 				    CD_NOT_EXIST) {
-					set_sense_type(chip, lun,
+					rts51x_set_sense_type(chip, lun,
 						SENSE_TYPE_MEDIA_NOT_PRESENT);
 					TRACE_RET(chip, STATUS_FAIL);
 				}
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MEDIA_WRITE_ERR);
 				TRACE_RET(chip, retval);
 			}
@@ -1948,18 +1948,18 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 		retval = xd_delay_write(chip);
 		if (retval != STATUS_SUCCESS) {
 			if (monitor_card_cd(chip, XD_CARD) == CD_NOT_EXIST) {
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MEDIA_NOT_PRESENT);
 				TRACE_RET(chip, STATUS_FAIL);
 			}
-			set_sense_type(chip, lun,
+			rts51x_set_sense_type(chip, lun,
 				       SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 			TRACE_RET(chip, retval);
 		}
 
 		old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
 		if (old_blk == BLK_NOT_FOUND) {
-			set_sense_type(chip, lun,
+			rts51x_set_sense_type(chip, lun,
 				       SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 			TRACE_RET(chip, STATUS_FAIL);
 		}
@@ -1980,7 +1980,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 							start_page, end_page,
 							buf, &ptr, &offset);
 			if (retval != STATUS_SUCCESS) {
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 				TRACE_RET(chip, STATUS_FAIL);
 			}
@@ -1991,7 +1991,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 						    end_page, buf, &ptr,
 						    &offset);
 			if (retval != STATUS_SUCCESS) {
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MEDIA_WRITE_ERR);
 				TRACE_RET(chip, STATUS_FAIL);
 			}
@@ -2010,7 +2010,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 			retval = xd_build_l2p_tbl(chip, zone_no);
 			if (retval != STATUS_SUCCESS) {
 				chip->card_fail |= XD_CARD;
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MEDIA_NOT_PRESENT);
 				TRACE_RET(chip, retval);
 			}
@@ -2019,10 +2019,10 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 		old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
 		if (old_blk == BLK_NOT_FOUND) {
 			if (srb->sc_data_direction == DMA_FROM_DEVICE) {
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
 			} else {
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MEDIA_WRITE_ERR);
 			}
 			TRACE_RET(chip, STATUS_FAIL);
@@ -2031,7 +2031,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 		if (srb->sc_data_direction == DMA_TO_DEVICE) {
 			new_blk = xd_get_unused_block(chip, zone_no);
 			if (new_blk == BLK_NOT_FOUND) {
-				set_sense_type(chip, lun,
+				rts51x_set_sense_type(chip, lun,
 					       SENSE_TYPE_MEDIA_WRITE_ERR);
 				TRACE_RET(chip, STATUS_FAIL);
 			}
@@ -2054,7 +2054,7 @@ int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 	return STATUS_SUCCESS;
 }
 
-void xd_free_l2p_tbl(struct rts51x_chip *chip)
+void rts51x_xd_free_l2p_tbl(struct rts51x_chip *chip)
 {
 	struct xd_info *xd_card = &(chip->xd_card);
 	int i = 0;
@@ -2075,7 +2075,7 @@ void xd_free_l2p_tbl(struct rts51x_chip *chip)
 	}
 }
 
-void xd_cleanup_work(struct rts51x_chip *chip)
+void rts51x_xd_cleanup_work(struct rts51x_chip *chip)
 {
 	struct xd_info *xd_card = &(chip->xd_card);
 
@@ -2115,12 +2115,12 @@ static int xd_power_off_card3v3(struct rts51x_chip *chip)
 	return STATUS_SUCCESS;
 }
 
-int release_xd_card(struct rts51x_chip *chip)
+int rts51x_release_xd_card(struct rts51x_chip *chip)
 {
 	struct xd_info *xd_card = &(chip->xd_card);
 	int retval;
 
-	RTS51X_DEBUGP("release_xd_card\n");
+	RTS51X_DEBUGP("rts51x_release_xd_card\n");
 
 	chip->card_ready &= ~XD_CARD;
 	chip->card_fail &= ~XD_CARD;
@@ -2128,7 +2128,7 @@ int release_xd_card(struct rts51x_chip *chip)
 
 	xd_card->delay_write.delay_write_flag = 0;
 
-	xd_free_l2p_tbl(chip);
+	rts51x_xd_free_l2p_tbl(chip);
 
 	rts51x_write_register(chip, SFSM_ED, HW_CMD_STOP, HW_CMD_STOP);
 
diff --git a/drivers/staging/rts5139/xd.h b/drivers/staging/rts5139/xd.h
index 55e4205..695a0b4 100644
--- a/drivers/staging/rts5139/xd.h
+++ b/drivers/staging/rts5139/xd.h
@@ -181,11 +181,11 @@
 #define	CIS1_8			(256 + 8)
 #define	CIS1_9			(256 + 9)
 
-int reset_xd_card(struct rts51x_chip *chip);
-int xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
+int rts51x_reset_xd_card(struct rts51x_chip *chip);
+int rts51x_xd_rw(struct scsi_cmnd *srb, struct rts51x_chip *chip, u32 start_sector,
 	  u16 sector_cnt);
-void xd_free_l2p_tbl(struct rts51x_chip *chip);
-void xd_cleanup_work(struct rts51x_chip *chip);
-int release_xd_card(struct rts51x_chip *chip);
+void rts51x_xd_free_l2p_tbl(struct rts51x_chip *chip);
+void rts51x_xd_cleanup_work(struct rts51x_chip *chip);
+int rts51x_release_xd_card(struct rts51x_chip *chip);
 
 #endif /* __RTS51X_XD_H */
diff --git a/drivers/staging/rts_pstor/Kconfig b/drivers/staging/rts_pstor/Kconfig
deleted file mode 100644
index 4d66a99..0000000
--- a/drivers/staging/rts_pstor/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-config RTS_PSTOR
-	tristate "RealTek PCI-E Card Reader support"
-	depends on PCI && SCSI
-	help
-	  Say Y here to include driver code to support the Realtek
-	  PCI-E card readers.
-
-	  If this driver is compiled as a module, it will be named rts_pstor.
-
-config RTS_PSTOR_DEBUG
-	bool "Realtek PCI-E Card Reader verbose debug"
-	depends on RTS_PSTOR
-	help
-	  Say Y here in order to have the rts_pstor code generate
-	  verbose debugging messages.
-
diff --git a/drivers/staging/rts_pstor/Makefile b/drivers/staging/rts_pstor/Makefile
deleted file mode 100644
index 42533d3..0000000
--- a/drivers/staging/rts_pstor/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-ccflags := -Idrivers/scsi
-
-obj-$(CONFIG_RTS_PSTOR)	:= rts_pstor.o
-
-rts_pstor-y :=				\
-		rtsx.o			\
-		rtsx_chip.o		\
-		rtsx_transport.o	\
-		rtsx_scsi.o		\
-		rtsx_card.o		\
-		general.o		\
-		sd.o			\
-		xd.o			\
-		ms.o			\
-		spi.o
-
diff --git a/drivers/staging/rts_pstor/TODO b/drivers/staging/rts_pstor/TODO
deleted file mode 100644
index becb95e..0000000
--- a/drivers/staging/rts_pstor/TODO
+++ /dev/null
@@ -1,9 +0,0 @@
-TODO:
-- support more pcie card reader of Realtek family
-- use kernel coding style
-- checkpatch.pl fixes
-- stop having thousands of lines of code duplicated with staging/rts5139
-- This driver contains an entire SD/MMC stack -- it should use the stack in
-  drivers/mmc instead, as a host driver e.g. drivers/mmc/host/realtek-pci.c;
-  see drivers/mmc/host/via-sdmmc.c as an example.
-- This driver presents cards as SCSI devices, but they should be MMC devices.
diff --git a/drivers/staging/rts_pstor/debug.h b/drivers/staging/rts_pstor/debug.h
deleted file mode 100644
index ab305be..0000000
--- a/drivers/staging/rts_pstor/debug.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- * Header file
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#ifndef __REALTEK_RTSX_DEBUG_H
-#define __REALTEK_RTSX_DEBUG_H
-
-#include <linux/kernel.h>
-
-#define RTSX_STOR "rts_pstor: "
-
-#ifdef CONFIG_RTS_PSTOR_DEBUG
-#define RTSX_DEBUGP(x...) printk(KERN_DEBUG RTSX_STOR x)
-#define RTSX_DEBUGPN(x...) printk(KERN_DEBUG x)
-#define RTSX_DEBUGPX(x...) printk(x)
-#define RTSX_DEBUG(x) x
-#else
-#define RTSX_DEBUGP(x...)
-#define RTSX_DEBUGPN(x...)
-#define RTSX_DEBUGPX(x...)
-#define RTSX_DEBUG(x)
-#endif
-
-#endif   /* __REALTEK_RTSX_DEBUG_H */
diff --git a/drivers/staging/rts_pstor/general.c b/drivers/staging/rts_pstor/general.c
deleted file mode 100644
index 056e98d..0000000
--- a/drivers/staging/rts_pstor/general.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#include "general.h"
-
-int bit1cnt_long(u32 data)
-{
-	int i, cnt = 0;
-	for (i = 0; i < 32; i++) {
-		if (data & 0x01)
-			cnt++;
-		data >>= 1;
-	}
-	return cnt;
-}
-
diff --git a/drivers/staging/rts_pstor/general.h b/drivers/staging/rts_pstor/general.h
deleted file mode 100644
index f17930d..0000000
--- a/drivers/staging/rts_pstor/general.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- * Header file
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#ifndef __RTSX_GENERAL_H
-#define __RTSX_GENERAL_H
-
-#include "rtsx.h"
-
-int bit1cnt_long(u32 data);
-
-#endif /* __RTSX_GENERAL_H */
diff --git a/drivers/staging/rts_pstor/ms.c b/drivers/staging/rts_pstor/ms.c
deleted file mode 100644
index 16a5c16..0000000
--- a/drivers/staging/rts_pstor/ms.c
+++ /dev/null
@@ -1,4051 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/vmalloc.h>
-
-#include "rtsx.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
-#include "ms.h"
-
-static inline void ms_set_err_code(struct rtsx_chip *chip, u8 err_code)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-
-	ms_card->err_code = err_code;
-}
-
-static inline int ms_check_err_code(struct rtsx_chip *chip, u8 err_code)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-
-	return (ms_card->err_code == err_code);
-}
-
-static int ms_parse_err_code(struct rtsx_chip *chip)
-{
-	TRACE_RET(chip, STATUS_FAIL);
-}
-
-static int ms_transfer_tpc(struct rtsx_chip *chip, u8 trans_mode, u8 tpc, u8 cnt, u8 cfg)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-	u8 *ptr;
-
-	RTSX_DEBUGP("ms_transfer_tpc: tpc = 0x%x\n", tpc);
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, MS_TRANSFER_START | trans_mode);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
-
-	rtsx_add_cmd(chip, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
-
-	retval = rtsx_send_cmd(chip, MS_CARD, 5000);
-	if (retval < 0) {
-		rtsx_clear_ms_error(chip);
-		ms_set_err_code(chip, MS_TO_ERROR);
-		TRACE_RET(chip, ms_parse_err_code(chip));
-	}
-
-	ptr = rtsx_get_cmd_data(chip) + 1;
-
-	if (!(tpc & 0x08)) {		/* Read Packet */
-		if (*ptr & MS_CRC16_ERR) {
-			ms_set_err_code(chip, MS_CRC16_ERROR);
-			TRACE_RET(chip, ms_parse_err_code(chip));
-		}
-	} else {			/* Write Packet */
-		if (CHK_MSPRO(ms_card) && !(*ptr & 0x80)) {
-			if (*ptr & (MS_INT_ERR | MS_INT_CMDNK)) {
-				ms_set_err_code(chip, MS_CMD_NK);
-				TRACE_RET(chip, ms_parse_err_code(chip));
-			}
-		}
-	}
-
-	if (*ptr & MS_RDY_TIMEOUT) {
-		rtsx_clear_ms_error(chip);
-		ms_set_err_code(chip, MS_TO_ERROR);
-		TRACE_RET(chip, ms_parse_err_code(chip));
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_transfer_data(struct rtsx_chip *chip, u8 trans_mode, u8 tpc, u16 sec_cnt,
-		u8 cfg, int mode_2k, int use_sg, void *buf, int buf_len)
-{
-	int retval;
-	u8 val, err_code = 0;
-	enum dma_data_direction dir;
-
-	if (!buf || !buf_len)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (trans_mode == MS_TM_AUTO_READ) {
-		dir = DMA_FROM_DEVICE;
-		err_code = MS_FLASH_READ_ERROR;
-	} else if (trans_mode == MS_TM_AUTO_WRITE) {
-		dir = DMA_TO_DEVICE;
-		err_code = MS_FLASH_WRITE_ERROR;
-	} else {
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
-	rtsx_add_cmd(chip, WRITE_REG_CMD,
-		     MS_SECTOR_CNT_H, 0xFF, (u8)(sec_cnt >> 8));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_SECTOR_CNT_L, 0xFF, (u8)sec_cnt);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
-
-	if (mode_2k) {
-		rtsx_add_cmd(chip, WRITE_REG_CMD,
-			     MS_CFG, MS_2K_SECTOR_MODE, MS_2K_SECTOR_MODE);
-	} else {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_CFG, MS_2K_SECTOR_MODE, 0);
-	}
-
-	trans_dma_enable(dir, chip, sec_cnt * 512, DMA_512);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD,
-		     MS_TRANSFER, 0xFF, MS_TRANSFER_START | trans_mode);
-	rtsx_add_cmd(chip, CHECK_REG_CMD,
-		     MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
-
-	rtsx_send_cmd_no_wait(chip);
-
-	retval = rtsx_transfer_data(chip, MS_CARD, buf, buf_len,
-				    use_sg, dir, chip->mspro_timeout);
-	if (retval < 0) {
-		ms_set_err_code(chip, err_code);
-		if (retval == -ETIMEDOUT)
-			retval = STATUS_TIMEDOUT;
-		else
-			retval = STATUS_FAIL;
-
-		TRACE_RET(chip, retval);
-	}
-
-	RTSX_READ_REG(chip, MS_TRANS_CFG, &val);
-	if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT))
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_write_bytes(struct rtsx_chip *chip,
-			  u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval, i;
-
-	if (!data || (data_len < cnt))
-		TRACE_RET(chip, STATUS_ERROR);
-
-	rtsx_init_cmd(chip);
-
-	for (i = 0; i < cnt; i++) {
-		rtsx_add_cmd(chip, WRITE_REG_CMD,
-			     PPBUF_BASE2 + i, 0xFF, data[i]);
-	}
-	if (cnt % 2)
-		rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2 + i, 0xFF, 0xFF);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD,
-		     MS_TRANSFER, 0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES);
-	rtsx_add_cmd(chip, CHECK_REG_CMD,
-		     MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
-
-	retval = rtsx_send_cmd(chip, MS_CARD, 5000);
-	if (retval < 0) {
-		u8 val = 0;
-
-		rtsx_read_register(chip, MS_TRANS_CFG, &val);
-		RTSX_DEBUGP("MS_TRANS_CFG: 0x%02x\n", val);
-
-		rtsx_clear_ms_error(chip);
-
-		if (!(tpc & 0x08)) {
-			if (val & MS_CRC16_ERR) {
-				ms_set_err_code(chip, MS_CRC16_ERROR);
-				TRACE_RET(chip, ms_parse_err_code(chip));
-			}
-		} else {
-			if (CHK_MSPRO(ms_card) && !(val & 0x80)) {
-				if (val & (MS_INT_ERR | MS_INT_CMDNK)) {
-					ms_set_err_code(chip, MS_CMD_NK);
-					TRACE_RET(chip, ms_parse_err_code(chip));
-				}
-			}
-		}
-
-		if (val & MS_RDY_TIMEOUT) {
-			ms_set_err_code(chip, MS_TO_ERROR);
-			TRACE_RET(chip, ms_parse_err_code(chip));
-		}
-
-		ms_set_err_code(chip, MS_TO_ERROR);
-		TRACE_RET(chip, ms_parse_err_code(chip));
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_read_bytes(struct rtsx_chip *chip, u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval, i;
-	u8 *ptr;
-
-	if (!data)
-		TRACE_RET(chip, STATUS_ERROR);
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, MS_TRANSFER_START | MS_TM_READ_BYTES);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
-
-	for (i = 0; i < data_len - 1; i++)
-	       rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
-
-	if (data_len % 2)
-		rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len, 0, 0);
-	else
-		rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len - 1, 0, 0);
-
-	retval = rtsx_send_cmd(chip, MS_CARD, 5000);
-	if (retval < 0) {
-		u8 val = 0;
-
-		rtsx_read_register(chip, MS_TRANS_CFG, &val);
-		rtsx_clear_ms_error(chip);
-
-		if (!(tpc & 0x08)) {
-			if (val & MS_CRC16_ERR) {
-				ms_set_err_code(chip, MS_CRC16_ERROR);
-				TRACE_RET(chip, ms_parse_err_code(chip));
-			}
-		} else {
-			if (CHK_MSPRO(ms_card) && !(val & 0x80)) {
-				if (val & (MS_INT_ERR | MS_INT_CMDNK)) {
-					ms_set_err_code(chip, MS_CMD_NK);
-					TRACE_RET(chip, ms_parse_err_code(chip));
-				}
-			}
-		}
-
-		if (val & MS_RDY_TIMEOUT) {
-			ms_set_err_code(chip, MS_TO_ERROR);
-			TRACE_RET(chip, ms_parse_err_code(chip));
-		}
-
-		ms_set_err_code(chip, MS_TO_ERROR);
-		TRACE_RET(chip, ms_parse_err_code(chip));
-	}
-
-	ptr = rtsx_get_cmd_data(chip) + 1;
-
-	for (i = 0; i < data_len; i++)
-		data[i] = ptr[i];
-
-	if ((tpc == PRO_READ_SHORT_DATA) && (data_len == 8)) {
-		RTSX_DEBUGP("Read format progress:\n");
-		RTSX_DUMP(ptr, cnt);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_set_rw_reg_addr(struct rtsx_chip *chip,
-		u8 read_start, u8 read_cnt, u8 write_start, u8 write_cnt)
-{
-	int retval, i;
-	u8 data[4];
-
-	data[0] = read_start;
-	data[1] = read_cnt;
-	data[2] = write_start;
-	data[3] = write_cnt;
-
-	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-		retval = ms_write_bytes(chip, SET_RW_REG_ADRS, 4,
-					NO_WAIT_INT, data, 4);
-		if (retval == STATUS_SUCCESS)
-			return STATUS_SUCCESS;
-		rtsx_clear_ms_error(chip);
-	}
-
-	TRACE_RET(chip, STATUS_FAIL);
-}
-
-static int ms_send_cmd(struct rtsx_chip *chip, u8 cmd, u8 cfg)
-{
-	u8 data[2];
-
-	data[0] = cmd;
-	data[1] = 0;
-
-	return ms_write_bytes(chip, PRO_SET_CMD, 1, cfg, data, 1);
-}
-
-static int ms_set_init_para(struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-
-	if (CHK_HG8BIT(ms_card)) {
-		if (chip->asic_code)
-			ms_card->ms_clock = chip->asic_ms_hg_clk;
-		else
-			ms_card->ms_clock = chip->fpga_ms_hg_clk;
-
-	} else if (CHK_MSPRO(ms_card) || CHK_MS4BIT(ms_card)) {
-		if (chip->asic_code)
-			ms_card->ms_clock = chip->asic_ms_4bit_clk;
-		else
-			ms_card->ms_clock = chip->fpga_ms_4bit_clk;
-
-	} else {
-		if (chip->asic_code)
-			ms_card->ms_clock = chip->asic_ms_1bit_clk;
-		else
-			ms_card->ms_clock = chip->fpga_ms_1bit_clk;
-	}
-
-	retval = switch_clock(chip, ms_card->ms_clock);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = select_card(chip, MS_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_switch_clock(struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-
-	retval = select_card(chip, MS_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = switch_clock(chip, ms_card->ms_clock);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_pull_ctl_disable(struct rtsx_chip *chip)
-{
-	if (CHECK_PID(chip, 0x5209)) {
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x55);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF, 0x55);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF, 0x15);
-	} else if (CHECK_PID(chip, 0x5208)) {
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF,
-			MS_D1_PD | MS_D2_PD | MS_CLK_PD | MS_D6_PD);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF,
-			MS_D3_PD | MS_D0_PD | MS_BS_PD | XD_D4_PD);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF,
-			MS_D7_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF,
-			XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF,
-			MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF,
-			MS_D5_PD | MS_D4_PD);
-	} else if (CHECK_PID(chip, 0x5288)) {
-		if (CHECK_BARO_PKG(chip, QFN)) {
-			RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55);
-			RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55);
-			RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0x4B);
-			RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x69);
-		}
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_pull_ctl_enable(struct rtsx_chip *chip)
-{
-	int retval;
-
-	rtsx_init_cmd(chip);
-
-	if (CHECK_PID(chip, 0x5209)) {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x15);
-	} else if (CHECK_PID(chip, 0x5208)) {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
-			MS_D1_PD | MS_D2_PD | MS_CLK_NP | MS_D6_PD);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
-			MS_D3_PD | MS_D0_PD | MS_BS_NP | XD_D4_PD);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
-			MS_D7_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
-			XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
-			MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF,
-			MS_D5_PD | MS_D4_PD);
-	} else if (CHECK_PID(chip, 0x5288)) {
-		if (CHECK_BARO_PKG(chip, QFN)) {
-			rtsx_add_cmd(chip, WRITE_REG_CMD,
-				     CARD_PULL_CTL1, 0xFF, 0x55);
-			rtsx_add_cmd(chip, WRITE_REG_CMD,
-				     CARD_PULL_CTL2, 0xFF, 0x45);
-			rtsx_add_cmd(chip, WRITE_REG_CMD,
-				     CARD_PULL_CTL3, 0xFF, 0x4B);
-			rtsx_add_cmd(chip, WRITE_REG_CMD,
-				     CARD_PULL_CTL4, 0xFF, 0x29);
-		}
-	}
-
-	retval = rtsx_send_cmd(chip, MS_CARD, 100);
-	if (retval < 0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_prepare_reset(struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-	u8 oc_mask = 0;
-
-	ms_card->ms_type = 0;
-	ms_card->check_ms_flow = 0;
-	ms_card->switch_8bit_fail = 0;
-	ms_card->delay_write.delay_write_flag = 0;
-
-	ms_card->pro_under_formatting = 0;
-
-	retval = ms_power_off_card3v3(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (!chip->ft2_fast_mode)
-		wait_timeout(250);
-
-	retval = enable_card_clock(chip, MS_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (chip->asic_code) {
-		retval = ms_pull_ctl_enable(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	} else {
-		RTSX_WRITE_REG(chip, FPGA_PULL_CTL, FPGA_MS_PULL_CTL_BIT | 0x20, 0);
-	}
-
-	if (!chip->ft2_fast_mode) {
-		retval = card_power_on(chip, MS_CARD);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		wait_timeout(150);
-
-#ifdef SUPPORT_OCP
-		if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
-			oc_mask = MS_OC_NOW | MS_OC_EVER;
-		else
-			oc_mask = SD_OC_NOW | SD_OC_EVER;
-
-		if (chip->ocp_stat & oc_mask) {
-			RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n",
-				     chip->ocp_stat);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-#endif
-	}
-
-	RTSX_WRITE_REG(chip, CARD_OE, MS_OUTPUT_EN, MS_OUTPUT_EN);
-
-	if (chip->asic_code) {
-		RTSX_WRITE_REG(chip, MS_CFG, 0xFF,
-			SAMPLE_TIME_RISING | PUSH_TIME_DEFAULT |
-			NO_EXTEND_TOGGLE | MS_BUS_WIDTH_1);
-	} else {
-		RTSX_WRITE_REG(chip, MS_CFG, 0xFF,
-			SAMPLE_TIME_FALLING | PUSH_TIME_DEFAULT |
-			NO_EXTEND_TOGGLE | MS_BUS_WIDTH_1);
-	}
-	RTSX_WRITE_REG(chip, MS_TRANS_CFG, 0xFF, NO_WAIT_INT | NO_AUTO_READ_INT_REG);
-	RTSX_WRITE_REG(chip, CARD_STOP, MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR);
-
-	retval = ms_set_init_para(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_identify_media_type(struct rtsx_chip *chip, int switch_8bit_bus)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval, i;
-	u8 val;
-
-	retval = ms_set_rw_reg_addr(chip, Pro_StatusReg, 6, SystemParm, 1);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-		retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, READ_REG, 6, NO_WAIT_INT);
-		if (retval == STATUS_SUCCESS)
-			break;
-	}
-	if (i == MS_MAX_RETRY_COUNT)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_READ_REG(chip, PPBUF_BASE2 + 2, &val);
-	RTSX_DEBUGP("Type register: 0x%x\n", val);
-	if (val != 0x01) {
-		if (val != 0x02)
-			ms_card->check_ms_flow = 1;
-
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	RTSX_READ_REG(chip, PPBUF_BASE2 + 4, &val);
-	RTSX_DEBUGP("Category register: 0x%x\n", val);
-	if (val != 0) {
-		ms_card->check_ms_flow = 1;
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	RTSX_READ_REG(chip, PPBUF_BASE2 + 5, &val);
-	RTSX_DEBUGP("Class register: 0x%x\n", val);
-	if (val == 0) {
-		RTSX_READ_REG(chip, PPBUF_BASE2, &val);
-		if (val & WRT_PRTCT)
-			chip->card_wp |= MS_CARD;
-		else
-			chip->card_wp &= ~MS_CARD;
-
-	} else if ((val == 0x01) || (val == 0x02) || (val == 0x03)) {
-		chip->card_wp |= MS_CARD;
-	} else {
-		ms_card->check_ms_flow = 1;
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	ms_card->ms_type |= TYPE_MSPRO;
-
-	RTSX_READ_REG(chip, PPBUF_BASE2 + 3, &val);
-	RTSX_DEBUGP("IF Mode register: 0x%x\n", val);
-	if (val == 0) {
-		ms_card->ms_type &= 0x0F;
-	} else if (val == 7) {
-		if (switch_8bit_bus)
-			ms_card->ms_type |= MS_HG;
-		else
-			ms_card->ms_type &= 0x0F;
-
-	} else {
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_confirm_cpu_startup(struct rtsx_chip *chip)
-{
-	int retval, i, k;
-	u8 val;
-
-	/* Confirm CPU StartUp */
-	k = 0;
-	do {
-		if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
-			ms_set_err_code(chip, MS_NO_CARD);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-			retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-			if (retval == STATUS_SUCCESS)
-				break;
-		}
-		if (i == MS_MAX_RETRY_COUNT)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		if (k > 100)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		k++;
-		wait_timeout(100);
-	} while (!(val & INT_REG_CED));
-
-	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-		retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-		if (retval == STATUS_SUCCESS)
-			break;
-	}
-	if (i == MS_MAX_RETRY_COUNT)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (val & INT_REG_ERR) {
-		if (val & INT_REG_CMDNK)
-			chip->card_wp |= (MS_CARD);
-		else
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-	/* --  end confirm CPU startup */
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_switch_parallel_bus(struct rtsx_chip *chip)
-{
-	int retval, i;
-	u8 data[2];
-
-	data[0] = PARALLEL_4BIT_IF;
-	data[1] = 0;
-	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-		retval = ms_write_bytes(chip, WRITE_REG, 1, NO_WAIT_INT, data, 2);
-		if (retval == STATUS_SUCCESS)
-			break;
-	}
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_switch_8bit_bus(struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval, i;
-	u8 data[2];
-
-	data[0] = PARALLEL_8BIT_IF;
-	data[1] = 0;
-	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-		retval = ms_write_bytes(chip, WRITE_REG, 1, NO_WAIT_INT, data, 2);
-		if (retval == STATUS_SUCCESS)
-			break;
-	}
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_WRITE_REG(chip, MS_CFG, 0x98, MS_BUS_WIDTH_8 | SAMPLE_TIME_FALLING);
-	ms_card->ms_type |= MS_8BIT;
-	retval = ms_set_init_para(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-		retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, 1, NO_WAIT_INT);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_pro_reset_flow(struct rtsx_chip *chip, int switch_8bit_bus)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval, i;
-
-	for (i = 0; i < 3; i++) {
-		retval = ms_prepare_reset(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = ms_identify_media_type(chip, switch_8bit_bus);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = ms_confirm_cpu_startup(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = ms_switch_parallel_bus(chip);
-		if (retval != STATUS_SUCCESS) {
-			if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
-				ms_set_err_code(chip, MS_NO_CARD);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			continue;
-		} else {
-			break;
-		}
-	}
-
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	/* Switch MS-PRO into Parallel mode */
-	RTSX_WRITE_REG(chip, MS_CFG, 0x18, MS_BUS_WIDTH_4);
-	RTSX_WRITE_REG(chip, MS_CFG, PUSH_TIME_ODD, PUSH_TIME_ODD);
-
-	retval = ms_set_init_para(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	/* If MSPro HG Card, We shall try to switch to 8-bit bus */
-	if (CHK_MSHG(ms_card) && chip->support_ms_8bit && switch_8bit_bus) {
-		retval = ms_switch_8bit_bus(chip);
-		if (retval != STATUS_SUCCESS) {
-			ms_card->switch_8bit_fail = 1;
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	return STATUS_SUCCESS;
-}
-
-#ifdef XC_POWERCLASS
-static int msxc_change_power(struct rtsx_chip *chip, u8 mode)
-{
-	int retval;
-	u8 buf[6];
-
-	ms_cleanup_work(chip);
-
-	retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	buf[0] = 0;
-	buf[1] = mode;
-	buf[2] = 0;
-	buf[3] = 0;
-	buf[4] = 0;
-	buf[5] = 0;
-
-	retval = ms_write_bytes(chip, PRO_WRITE_REG , 6, NO_WAIT_INT, buf, 6);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = ms_send_cmd(chip, XC_CHG_POWER, WAIT_INT);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_READ_REG(chip, MS_TRANS_CFG, buf);
-	if (buf[0] & (MS_INT_CMDNK | MS_INT_ERR))
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-#endif
-
-static int ms_read_attribute_info(struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval, i;
-	u8 val, *buf, class_code, device_type, sub_class, data[16];
-	u16 total_blk = 0, blk_size = 0;
-#ifdef SUPPORT_MSXC
-	u32 xc_total_blk = 0, xc_blk_size = 0;
-#endif
-	u32 sys_info_addr = 0, sys_info_size;
-#ifdef SUPPORT_PCGL_1P18
-	u32 model_name_addr = 0, model_name_size;
-	int found_sys_info = 0, found_model_name = 0;
-#endif
-
-	retval = ms_set_rw_reg_addr(chip, Pro_IntReg, 2, Pro_SystemParm, 7);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (CHK_MS8BIT(ms_card))
-		data[0] = PARALLEL_8BIT_IF;
-	else
-		data[0] = PARALLEL_4BIT_IF;
-
-	data[1] = 0;
-
-	data[2] = 0x40;
-	data[3] = 0;
-	data[4] = 0;
-	data[5] = 0;
-	data[6] = 0;
-	data[7] = 0;
-
-	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-		retval = ms_write_bytes(chip, PRO_WRITE_REG, 7, NO_WAIT_INT, data, 8);
-		if (retval == STATUS_SUCCESS)
-			break;
-	}
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	buf = kmalloc(64 * 512, GFP_KERNEL);
-	if (buf == NULL)
-		TRACE_RET(chip, STATUS_ERROR);
-
-	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-		retval = ms_send_cmd(chip, PRO_READ_ATRB, WAIT_INT);
-		if (retval != STATUS_SUCCESS)
-			continue;
-
-		retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
-		if (retval != STATUS_SUCCESS) {
-			kfree(buf);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-		if (!(val & MS_INT_BREQ)) {
-			kfree(buf);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-		retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
-				0x40, WAIT_INT, 0, 0, buf, 64 * 512);
-		if (retval == STATUS_SUCCESS)
-			break;
-		else
-			rtsx_clear_ms_error(chip);
-	}
-	if (retval != STATUS_SUCCESS) {
-		kfree(buf);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	i = 0;
-	do {
-		retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
-		if (retval != STATUS_SUCCESS) {
-			kfree(buf);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		if ((val & MS_INT_CED) || !(val & MS_INT_BREQ))
-			break;
-
-		retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, PRO_READ_LONG_DATA, 0, WAIT_INT);
-		if (retval != STATUS_SUCCESS) {
-			kfree(buf);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		i++;
-	} while (i < 1024);
-
-	if (retval != STATUS_SUCCESS) {
-		kfree(buf);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if ((buf[0] != 0xa5) && (buf[1] != 0xc3)) {
-		/* Signature code is wrong */
-		kfree(buf);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if ((buf[4] < 1) || (buf[4] > 12)) {
-		kfree(buf);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	for (i = 0; i < buf[4]; i++) {
-		int cur_addr_off = 16 + i * 12;
-
-#ifdef SUPPORT_MSXC
-		if ((buf[cur_addr_off + 8] == 0x10) || (buf[cur_addr_off + 8] == 0x13))
-#else
-		if (buf[cur_addr_off + 8] == 0x10)
-#endif
-		{
-			sys_info_addr = ((u32)buf[cur_addr_off + 0] << 24) |
-				((u32)buf[cur_addr_off + 1] << 16) |
-				((u32)buf[cur_addr_off + 2] << 8) | buf[cur_addr_off + 3];
-			sys_info_size = ((u32)buf[cur_addr_off + 4] << 24) |
-				((u32)buf[cur_addr_off + 5] << 16) |
-				((u32)buf[cur_addr_off + 6] << 8) | buf[cur_addr_off + 7];
-			RTSX_DEBUGP("sys_info_addr = 0x%x, sys_info_size = 0x%x\n",
-					sys_info_addr, sys_info_size);
-			if (sys_info_size != 96)  {
-				kfree(buf);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			if (sys_info_addr < 0x1A0) {
-				kfree(buf);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			if ((sys_info_size + sys_info_addr) > 0x8000) {
-				kfree(buf);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-#ifdef SUPPORT_MSXC
-			if (buf[cur_addr_off + 8] == 0x13)
-				ms_card->ms_type |= MS_XC;
-#endif
-#ifdef SUPPORT_PCGL_1P18
-			found_sys_info = 1;
-#else
-			break;
-#endif
-		}
-#ifdef SUPPORT_PCGL_1P18
-		if (buf[cur_addr_off + 8] == 0x15) {
-			model_name_addr = ((u32)buf[cur_addr_off + 0] << 24) |
-				((u32)buf[cur_addr_off + 1] << 16) |
-				((u32)buf[cur_addr_off + 2] << 8) | buf[cur_addr_off + 3];
-			model_name_size = ((u32)buf[cur_addr_off + 4] << 24) |
-				((u32)buf[cur_addr_off + 5] << 16) |
-				((u32)buf[cur_addr_off + 6] << 8) | buf[cur_addr_off + 7];
-			RTSX_DEBUGP("model_name_addr = 0x%x, model_name_size = 0x%x\n",
-					model_name_addr, model_name_size);
-			if (model_name_size != 48)  {
-				kfree(buf);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			if (model_name_addr < 0x1A0) {
-				kfree(buf);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			if ((model_name_size + model_name_addr) > 0x8000) {
-				kfree(buf);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			found_model_name = 1;
-		}
-
-		if (found_sys_info && found_model_name)
-			break;
-#endif
-	}
-
-	if (i == buf[4]) {
-		kfree(buf);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	class_code =  buf[sys_info_addr + 0];
-	device_type = buf[sys_info_addr + 56];
-	sub_class = buf[sys_info_addr + 46];
-#ifdef SUPPORT_MSXC
-	if (CHK_MSXC(ms_card)) {
-		xc_total_blk = ((u32)buf[sys_info_addr + 6] << 24) |
-				((u32)buf[sys_info_addr + 7] << 16) |
-				((u32)buf[sys_info_addr + 8] << 8) |
-				buf[sys_info_addr + 9];
-		xc_blk_size = ((u32)buf[sys_info_addr + 32] << 24) |
-				((u32)buf[sys_info_addr + 33] << 16) |
-				((u32)buf[sys_info_addr + 34] << 8) |
-				buf[sys_info_addr + 35];
-		RTSX_DEBUGP("xc_total_blk = 0x%x, xc_blk_size = 0x%x\n", xc_total_blk, xc_blk_size);
-	} else {
-		total_blk = ((u16)buf[sys_info_addr + 6] << 8) | buf[sys_info_addr + 7];
-		blk_size = ((u16)buf[sys_info_addr + 2] << 8) | buf[sys_info_addr + 3];
-		RTSX_DEBUGP("total_blk = 0x%x, blk_size = 0x%x\n", total_blk, blk_size);
-	}
-#else
-	total_blk = ((u16)buf[sys_info_addr + 6] << 8) | buf[sys_info_addr + 7];
-	blk_size = ((u16)buf[sys_info_addr + 2] << 8) | buf[sys_info_addr + 3];
-	RTSX_DEBUGP("total_blk = 0x%x, blk_size = 0x%x\n", total_blk, blk_size);
-#endif
-
-	RTSX_DEBUGP("class_code = 0x%x, device_type = 0x%x, sub_class = 0x%x\n",
-			class_code, device_type, sub_class);
-
-	memcpy(ms_card->raw_sys_info, buf + sys_info_addr, 96);
-#ifdef SUPPORT_PCGL_1P18
-	memcpy(ms_card->raw_model_name, buf + model_name_addr, 48);
-#endif
-
-	kfree(buf);
-
-#ifdef SUPPORT_MSXC
-	if (CHK_MSXC(ms_card)) {
-		if (class_code != 0x03)
-			TRACE_RET(chip, STATUS_FAIL);
-	} else {
-		if (class_code != 0x02)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-#else
-	if (class_code != 0x02)
-		TRACE_RET(chip, STATUS_FAIL);
-#endif
-
-	if (device_type != 0x00) {
-		if ((device_type == 0x01) || (device_type == 0x02) ||
-				(device_type == 0x03)) {
-			chip->card_wp |= MS_CARD;
-		} else {
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	if (sub_class & 0xC0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_DEBUGP("class_code: 0x%x, device_type: 0x%x, sub_class: 0x%x\n",
-		class_code, device_type, sub_class);
-
-#ifdef SUPPORT_MSXC
-	if (CHK_MSXC(ms_card)) {
-		chip->capacity[chip->card2lun[MS_CARD]] =
-			ms_card->capacity = xc_total_blk * xc_blk_size;
-	} else {
-		chip->capacity[chip->card2lun[MS_CARD]] =
-			ms_card->capacity = total_blk * blk_size;
-	}
-#else
-	chip->capacity[chip->card2lun[MS_CARD]] = ms_card->capacity = total_blk * blk_size;
-#endif
-
-	return STATUS_SUCCESS;
-}
-
-#ifdef SUPPORT_MAGIC_GATE
-static int mg_set_tpc_para_sub(struct rtsx_chip *chip, int type, u8 mg_entry_num);
-#endif
-
-static int reset_ms_pro(struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-#ifdef XC_POWERCLASS
-	u8 change_power_class;
-
-	if (chip->ms_power_class_en & 0x02)
-		change_power_class = 2;
-	else if (chip->ms_power_class_en & 0x01)
-		change_power_class = 1;
-	else
-		change_power_class = 0;
-#endif
-
-#ifdef XC_POWERCLASS
-Retry:
-#endif
-	retval = ms_pro_reset_flow(chip, 1);
-	if (retval != STATUS_SUCCESS) {
-		if (ms_card->switch_8bit_fail) {
-			retval = ms_pro_reset_flow(chip, 0);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-		} else {
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	retval = ms_read_attribute_info(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-#ifdef XC_POWERCLASS
-	if (CHK_HG8BIT(ms_card))
-		change_power_class = 0;
-
-	if (change_power_class && CHK_MSXC(ms_card)) {
-		u8 power_class_en = chip->ms_power_class_en;
-
-		RTSX_DEBUGP("power_class_en = 0x%x\n", power_class_en);
-		RTSX_DEBUGP("change_power_class = %d\n", change_power_class);
-
-		if (change_power_class)
-			power_class_en &= (1 << (change_power_class - 1));
-		else
-			power_class_en = 0;
-
-		if (power_class_en) {
-			u8 power_class_mode = (ms_card->raw_sys_info[46] & 0x18) >> 3;
-			RTSX_DEBUGP("power_class_mode = 0x%x", power_class_mode);
-			if (change_power_class > power_class_mode)
-				change_power_class = power_class_mode;
-			if (change_power_class) {
-				retval = msxc_change_power(chip, change_power_class);
-				if (retval != STATUS_SUCCESS) {
-					change_power_class--;
-					goto Retry;
-				}
-			}
-		}
-	}
-#endif
-
-#ifdef SUPPORT_MAGIC_GATE
-	retval = mg_set_tpc_para_sub(chip, 0, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-#endif
-
-	if (CHK_HG8BIT(ms_card))
-		chip->card_bus_width[chip->card2lun[MS_CARD]] = 8;
-	else
-		chip->card_bus_width[chip->card2lun[MS_CARD]] = 4;
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_read_status_reg(struct rtsx_chip *chip)
-{
-	int retval;
-	u8 val[2];
-
-	retval = ms_set_rw_reg_addr(chip, StatusReg0, 2, 0, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = ms_read_bytes(chip, READ_REG, 2, NO_WAIT_INT, val, 2);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (val[1] & (STS_UCDT | STS_UCEX | STS_UCFG)) {
-		ms_set_err_code(chip, MS_FLASH_READ_ERROR);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-
-static int ms_read_extra_data(struct rtsx_chip *chip,
-		u16 block_addr, u8 page_num, u8 *buf, int buf_len)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval, i;
-	u8 val, data[10];
-
-	retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (CHK_MS4BIT(ms_card)) {
-		/* Parallel interface */
-		data[0] = 0x88;
-	} else {
-		/* Serial interface */
-		data[0] = 0x80;
-	}
-	data[1] = 0;
-	data[2] = (u8)(block_addr >> 8);
-	data[3] = (u8)block_addr;
-	data[4] = 0x40;
-	data[5] = page_num;
-
-	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-		retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6);
-		if (retval == STATUS_SUCCESS)
-			break;
-	}
-	if (i == MS_MAX_RETRY_COUNT)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ms_set_err_code(chip, MS_NO_ERROR);
-
-	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-		retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
-		if (retval == STATUS_SUCCESS)
-			break;
-	}
-	if (i == MS_MAX_RETRY_COUNT)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ms_set_err_code(chip, MS_NO_ERROR);
-	retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (val & INT_REG_CMDNK) {
-		ms_set_err_code(chip, MS_CMD_NK);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-	if (val & INT_REG_CED) {
-		if (val & INT_REG_ERR) {
-			retval = ms_read_status_reg(chip);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-
-			retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	retval = ms_read_bytes(chip, READ_REG, MS_EXTRA_SIZE, NO_WAIT_INT, data, MS_EXTRA_SIZE);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (buf && buf_len) {
-		if (buf_len > MS_EXTRA_SIZE)
-			buf_len = MS_EXTRA_SIZE;
-		memcpy(buf, data, buf_len);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_write_extra_data(struct rtsx_chip *chip,
-		u16 block_addr, u8 page_num, u8 *buf, int buf_len)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval, i;
-	u8 val, data[16];
-
-	if (!buf || (buf_len < MS_EXTRA_SIZE))
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6 + MS_EXTRA_SIZE);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (CHK_MS4BIT(ms_card))
-		data[0] = 0x88;
-	else
-		data[0] = 0x80;
-
-	data[1] = 0;
-	data[2] = (u8)(block_addr >> 8);
-	data[3] = (u8)block_addr;
-	data[4] = 0x40;
-	data[5] = page_num;
-
-	for (i = 6; i < MS_EXTRA_SIZE + 6; i++)
-		data[i] = buf[i - 6];
-
-	retval = ms_write_bytes(chip, WRITE_REG , (6+MS_EXTRA_SIZE), NO_WAIT_INT, data, 16);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ms_set_err_code(chip, MS_NO_ERROR);
-	retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (val & INT_REG_CMDNK) {
-		ms_set_err_code(chip, MS_CMD_NK);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-	if (val & INT_REG_CED) {
-		if (val & INT_REG_ERR) {
-			ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	return STATUS_SUCCESS;
-}
-
-
-static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-	u8 val, data[6];
-
-	retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (CHK_MS4BIT(ms_card))
-		data[0] = 0x88;
-	else
-		data[0] = 0x80;
-
-	data[1] = 0;
-	data[2] = (u8)(block_addr >> 8);
-	data[3] = (u8)block_addr;
-	data[4] = 0x20;
-	data[5] = page_num;
-
-	retval = ms_write_bytes(chip, WRITE_REG , 6, NO_WAIT_INT, data, 6);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ms_set_err_code(chip, MS_NO_ERROR);
-	retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (val & INT_REG_CMDNK) {
-		ms_set_err_code(chip, MS_CMD_NK);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (val & INT_REG_CED) {
-		if (val & INT_REG_ERR) {
-			if (!(val & INT_REG_BREQ)) {
-				ms_set_err_code(chip,  MS_FLASH_READ_ERROR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			retval = ms_read_status_reg(chip);
-			if (retval != STATUS_SUCCESS)
-				ms_set_err_code(chip,  MS_FLASH_WRITE_ERROR);
-
-		} else {
-			if (!(val & INT_REG_BREQ)) {
-				ms_set_err_code(chip, MS_BREQ_ERROR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-	}
-
-	retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, READ_PAGE_DATA, 0, NO_WAIT_INT);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR))
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-
-static int ms_set_bad_block(struct rtsx_chip *chip, u16 phy_blk)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-	u8 val, data[8], extra[MS_EXTRA_SIZE];
-
-	retval = ms_read_extra_data(chip, phy_blk, 0, extra, MS_EXTRA_SIZE);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 7);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ms_set_err_code(chip, MS_NO_ERROR);
-
-	if (CHK_MS4BIT(ms_card))
-		data[0] = 0x88;
-	else
-		data[0] = 0x80;
-
-	data[1] = 0;
-	data[2] = (u8)(phy_blk >> 8);
-	data[3] = (u8)phy_blk;
-	data[4] = 0x80;
-	data[5] = 0;
-	data[6] = extra[0] & 0x7F;
-	data[7] = 0xFF;
-
-	retval = ms_write_bytes(chip, WRITE_REG , 7, NO_WAIT_INT, data, 7);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ms_set_err_code(chip, MS_NO_ERROR);
-	retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (val & INT_REG_CMDNK) {
-		ms_set_err_code(chip, MS_CMD_NK);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (val & INT_REG_CED) {
-		if (val & INT_REG_ERR) {
-			ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	return STATUS_SUCCESS;
-}
-
-
-static int ms_erase_block(struct rtsx_chip *chip, u16 phy_blk)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval, i = 0;
-	u8 val, data[6];
-
-	retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ms_set_err_code(chip, MS_NO_ERROR);
-
-	if (CHK_MS4BIT(ms_card))
-		data[0] = 0x88;
-	else
-		data[0] = 0x80;
-
-	data[1] = 0;
-	data[2] = (u8)(phy_blk >> 8);
-	data[3] = (u8)phy_blk;
-	data[4] = 0;
-	data[5] = 0;
-
-	retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-ERASE_RTY:
-	retval = ms_send_cmd(chip, BLOCK_ERASE, WAIT_INT);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ms_set_err_code(chip, MS_NO_ERROR);
-	retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (val & INT_REG_CMDNK) {
-		if (i < 3) {
-			i++;
-			goto ERASE_RTY;
-		}
-
-		ms_set_err_code(chip, MS_CMD_NK);
-		ms_set_bad_block(chip, phy_blk);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (val & INT_REG_CED) {
-		if (val & INT_REG_ERR) {
-			ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	return STATUS_SUCCESS;
-}
-
-
-static void ms_set_page_status(u16 log_blk, u8 type, u8 *extra, int extra_len)
-{
-	if (!extra || (extra_len < MS_EXTRA_SIZE))
-		return;
-
-	memset(extra, 0xFF, MS_EXTRA_SIZE);
-
-	if (type == setPS_NG) {
-		/* set page status as 1:NG,and block status keep 1:OK */
-		extra[0] = 0xB8;
-	} else {
-		/* set page status as 0:Data Error,and block status keep 1:OK */
-		extra[0] = 0x98;
-	}
-
-	extra[2] = (u8)(log_blk >> 8);
-	extra[3] = (u8)log_blk;
-}
-
-static int ms_init_page(struct rtsx_chip *chip, u16 phy_blk, u16 log_blk, u8 start_page, u8 end_page)
-{
-	int retval;
-	u8 extra[MS_EXTRA_SIZE], i;
-
-	memset(extra, 0xff, MS_EXTRA_SIZE);
-
-	extra[0] = 0xf8;	/* Block, page OK, data erased */
-	extra[1] = 0xff;
-	extra[2] = (u8)(log_blk >> 8);
-	extra[3] = (u8)log_blk;
-
-	for (i = start_page; i < end_page; i++) {
-		if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
-			ms_set_err_code(chip, MS_NO_CARD);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		retval = ms_write_extra_data(chip, phy_blk, i, extra, MS_EXTRA_SIZE);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
-		u16 log_blk, u8 start_page, u8 end_page)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval, rty_cnt, uncorrect_flag = 0;
-	u8 extra[MS_EXTRA_SIZE], val, i, j, data[16];
-
-	RTSX_DEBUGP("Copy page from 0x%x to 0x%x, logical block is 0x%x\n",
-		old_blk, new_blk, log_blk);
-	RTSX_DEBUGP("start_page = %d, end_page = %d\n", start_page, end_page);
-
-	retval = ms_read_extra_data(chip, new_blk, 0, extra, MS_EXTRA_SIZE);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = ms_read_status_reg(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_READ_REG(chip, PPBUF_BASE2, &val);
-
-	if (val & BUF_FULL) {
-		retval = ms_send_cmd(chip, CLEAR_BUF, WAIT_INT);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		if (!(val & INT_REG_CED)) {
-			ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	for (i = start_page; i < end_page; i++) {
-		if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
-			ms_set_err_code(chip, MS_NO_CARD);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		ms_read_extra_data(chip, old_blk, i, extra, MS_EXTRA_SIZE);
-
-		retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		ms_set_err_code(chip, MS_NO_ERROR);
-
-		if (CHK_MS4BIT(ms_card))
-			data[0] = 0x88;
-		else
-			data[0] = 0x80;
-
-		data[1] = 0;
-		data[2] = (u8)(old_blk >> 8);
-		data[3] = (u8)old_blk;
-		data[4] = 0x20;
-		data[5] = i;
-
-		retval = ms_write_bytes(chip, WRITE_REG , 6, NO_WAIT_INT, data, 6);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		ms_set_err_code(chip, MS_NO_ERROR);
-		retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		if (val & INT_REG_CMDNK) {
-			ms_set_err_code(chip, MS_CMD_NK);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		if (val & INT_REG_CED) {
-			if (val & INT_REG_ERR) {
-				retval = ms_read_status_reg(chip);
-				if (retval != STATUS_SUCCESS) {
-					uncorrect_flag = 1;
-					RTSX_DEBUGP("Uncorrectable error\n");
-				} else {
-					uncorrect_flag = 0;
-				}
-
-				retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, READ_PAGE_DATA, 0, NO_WAIT_INT);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-
-				if (uncorrect_flag) {
-					ms_set_page_status(log_blk, setPS_NG, extra, MS_EXTRA_SIZE);
-					if (i == 0)
-						extra[0] &= 0xEF;
-
-					ms_write_extra_data(chip, old_blk, i, extra, MS_EXTRA_SIZE);
-					RTSX_DEBUGP("page %d : extra[0] = 0x%x\n", i, extra[0]);
-					MS_SET_BAD_BLOCK_FLG(ms_card);
-
-					ms_set_page_status(log_blk, setPS_Error, extra, MS_EXTRA_SIZE);
-					ms_write_extra_data(chip, new_blk, i, extra, MS_EXTRA_SIZE);
-					continue;
-				}
-
-				for (rty_cnt = 0; rty_cnt < MS_MAX_RETRY_COUNT; rty_cnt++) {
-					retval = ms_transfer_tpc(chip, MS_TM_NORMAL_WRITE,
-							WRITE_PAGE_DATA, 0, NO_WAIT_INT);
-					if (retval == STATUS_SUCCESS)
-						break;
-				}
-				if (rty_cnt == MS_MAX_RETRY_COUNT)
-					TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			if (!(val & INT_REG_BREQ)) {
-				ms_set_err_code(chip, MS_BREQ_ERROR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-
-		retval = ms_set_rw_reg_addr(chip, OverwriteFlag,
-				MS_EXTRA_SIZE, SystemParm, (6+MS_EXTRA_SIZE));
-
-		ms_set_err_code(chip, MS_NO_ERROR);
-
-		if (CHK_MS4BIT(ms_card))
-			data[0] = 0x88;
-		else
-			data[0] = 0x80;
-
-		data[1] = 0;
-		data[2] = (u8)(new_blk >> 8);
-		data[3] = (u8)new_blk;
-		data[4] = 0x20;
-		data[5] = i;
-
-		if ((extra[0] & 0x60) != 0x60)
-			data[6] = extra[0];
-		else
-			data[6] = 0xF8;
-
-		data[6 + 1] = 0xFF;
-		data[6 + 2] = (u8)(log_blk >> 8);
-		data[6 + 3] = (u8)log_blk;
-
-		for (j = 4; j <= MS_EXTRA_SIZE; j++)
-			data[6 + j] = 0xFF;
-
-		retval = ms_write_bytes(chip, WRITE_REG, (6 + MS_EXTRA_SIZE), NO_WAIT_INT, data, 16);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		ms_set_err_code(chip, MS_NO_ERROR);
-		retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		if (val & INT_REG_CMDNK) {
-			ms_set_err_code(chip, MS_CMD_NK);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		if (val & INT_REG_CED) {
-			if (val & INT_REG_ERR) {
-				ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-
-		if (i == 0) {
-			retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 7);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-
-			ms_set_err_code(chip, MS_NO_ERROR);
-
-			if (CHK_MS4BIT(ms_card))
-				data[0] = 0x88;
-			else
-				data[0] = 0x80;
-
-			data[1] = 0;
-			data[2] = (u8)(old_blk >> 8);
-			data[3] = (u8)old_blk;
-			data[4] = 0x80;
-			data[5] = 0;
-			data[6] = 0xEF;
-			data[7] = 0xFF;
-
-			retval = ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT, data, 8);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-
-			retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-
-			ms_set_err_code(chip, MS_NO_ERROR);
-			retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-
-			if (val & INT_REG_CMDNK) {
-				ms_set_err_code(chip, MS_CMD_NK);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			if (val & INT_REG_CED) {
-				if (val & INT_REG_ERR) {
-					ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-					TRACE_RET(chip, STATUS_FAIL);
-				}
-			}
-		}
-	}
-
-	return STATUS_SUCCESS;
-}
-
-
-static int reset_ms(struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-	u16 i, reg_addr, block_size;
-	u8 val, extra[MS_EXTRA_SIZE], j, *ptr;
-#ifndef SUPPORT_MAGIC_GATE
-	u16 eblock_cnt;
-#endif
-
-	retval = ms_prepare_reset(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ms_card->ms_type |= TYPE_MS;
-
-	retval = ms_send_cmd(chip, MS_RESET, NO_WAIT_INT);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = ms_read_status_reg(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_READ_REG(chip, PPBUF_BASE2, &val);
-	if (val & WRT_PRTCT)
-		chip->card_wp |= MS_CARD;
-	else
-		chip->card_wp &= ~MS_CARD;
-
-	i = 0;
-
-RE_SEARCH:
-	/* Search Boot Block */
-	while (i < (MAX_DEFECTIVE_BLOCK + 2)) {
-		if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
-			ms_set_err_code(chip, MS_NO_CARD);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		retval = ms_read_extra_data(chip, i, 0, extra, MS_EXTRA_SIZE);
-		if (retval != STATUS_SUCCESS) {
-			i++;
-			continue;
-		}
-
-		if (extra[0] & BLOCK_OK) {
-			if (!(extra[1] & NOT_BOOT_BLOCK)) {
-				ms_card->boot_block = i;
-				break;
-			}
-		}
-		i++;
-	}
-
-	if (i == (MAX_DEFECTIVE_BLOCK + 2)) {
-		RTSX_DEBUGP("No boot block found!");
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	for (j = 0; j < 3; j++) {
-		retval = ms_read_page(chip, ms_card->boot_block, j);
-		if (retval != STATUS_SUCCESS) {
-			if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR)) {
-				i = ms_card->boot_block + 1;
-				ms_set_err_code(chip, MS_NO_ERROR);
-				goto RE_SEARCH;
-			}
-		}
-	}
-
-	retval = ms_read_page(chip, ms_card->boot_block, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	/* Read MS system information as sys_info */
-	rtsx_init_cmd(chip);
-
-	for (i = 0; i < 96; i++)
-		rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 0x1A0 + i, 0, 0);
-
-	retval = rtsx_send_cmd(chip, MS_CARD, 100);
-	if (retval < 0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ptr = rtsx_get_cmd_data(chip);
-	memcpy(ms_card->raw_sys_info, ptr, 96);
-
-	/* Read useful block contents */
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, READ_REG_CMD, HEADER_ID0, 0, 0);
-	rtsx_add_cmd(chip, READ_REG_CMD, HEADER_ID1, 0, 0);
-
-	for (reg_addr = DISABLED_BLOCK0; reg_addr <= DISABLED_BLOCK3; reg_addr++)
-		rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
-	for (reg_addr = BLOCK_SIZE_0; reg_addr <= PAGE_SIZE_1; reg_addr++)
-		rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
-	rtsx_add_cmd(chip, READ_REG_CMD, MS_Device_Type, 0, 0);
-	rtsx_add_cmd(chip, READ_REG_CMD, MS_4bit_Support, 0, 0);
-
-	retval = rtsx_send_cmd(chip, MS_CARD, 100);
-	if (retval < 0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ptr = rtsx_get_cmd_data(chip);
-
-	RTSX_DEBUGP("Boot block data:\n");
-	RTSX_DUMP(ptr, 16);
-
-	/* Block ID error
-	 * HEADER_ID0, HEADER_ID1
-	 */
-	if (ptr[0] != 0x00 || ptr[1] != 0x01) {
-		i = ms_card->boot_block + 1;
-		goto RE_SEARCH;
-	}
-
-	/* Page size error
-	 * PAGE_SIZE_0, PAGE_SIZE_1
-	 */
-	if (ptr[12] != 0x02 || ptr[13] != 0x00) {
-		i = ms_card->boot_block + 1;
-		goto RE_SEARCH;
-	}
-
-	if ((ptr[14] == 1) || (ptr[14] == 3))
-		chip->card_wp |= MS_CARD;
-
-	/* BLOCK_SIZE_0, BLOCK_SIZE_1 */
-	block_size = ((u16)ptr[6] << 8) | ptr[7];
-	if (block_size == 0x0010) {
-		/* Block size 16KB */
-		ms_card->block_shift = 5;
-		ms_card->page_off = 0x1F;
-	} else if (block_size == 0x0008) {
-		/* Block size 8KB */
-		ms_card->block_shift = 4;
-		ms_card->page_off = 0x0F;
-	}
-
-	/* BLOCK_COUNT_0, BLOCK_COUNT_1 */
-	ms_card->total_block = ((u16)ptr[8] << 8) | ptr[9];
-
-#ifdef SUPPORT_MAGIC_GATE
-	j = ptr[10];
-
-	if (ms_card->block_shift == 4)  { /* 4MB or 8MB */
-		if (j < 2)  { /* Effective block for 4MB: 0x1F0 */
-			ms_card->capacity = 0x1EE0;
-		} else { /* Effective block for 8MB: 0x3E0 */
-			ms_card->capacity = 0x3DE0;
-		}
-	} else  { /* 16MB, 32MB, 64MB or 128MB */
-		if (j < 5)  { /* Effective block for 16MB: 0x3E0 */
-			ms_card->capacity = 0x7BC0;
-		} else if (j < 0xA) { /* Effective block for 32MB: 0x7C0 */
-			ms_card->capacity = 0xF7C0;
-		} else if (j < 0x11) { /* Effective block for 64MB: 0xF80 */
-			ms_card->capacity = 0x1EF80;
-		} else { /* Effective block for 128MB: 0x1F00 */
-			ms_card->capacity = 0x3DF00;
-		}
-	}
-#else
-	/* EBLOCK_COUNT_0, EBLOCK_COUNT_1 */
-	eblock_cnt = ((u16)ptr[10] << 8) | ptr[11];
-
-	ms_card->capacity = ((u32)eblock_cnt - 2) << ms_card->block_shift;
-#endif
-
-	chip->capacity[chip->card2lun[MS_CARD]] = ms_card->capacity;
-
-	/* Switch I/F Mode */
-	if (ptr[15]) {
-		retval = ms_set_rw_reg_addr(chip, 0, 0, SystemParm, 1);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		RTSX_WRITE_REG(chip, PPBUF_BASE2, 0xFF, 0x88);
-		RTSX_WRITE_REG(chip, PPBUF_BASE2 + 1, 0xFF, 0);
-
-		retval = ms_transfer_tpc(chip, MS_TM_WRITE_BYTES, WRITE_REG , 1, NO_WAIT_INT);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		RTSX_WRITE_REG(chip, MS_CFG, 0x58 | MS_NO_CHECK_INT,
-				MS_BUS_WIDTH_4 | PUSH_TIME_ODD | MS_NO_CHECK_INT);
-
-		ms_card->ms_type |= MS_4BIT;
-	}
-
-	if (CHK_MS4BIT(ms_card))
-		chip->card_bus_width[chip->card2lun[MS_CARD]] = 4;
-	else
-		chip->card_bus_width[chip->card2lun[MS_CARD]] = 1;
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_init_l2p_tbl(struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int size, i, seg_no, retval;
-	u16 defect_block, reg_addr;
-	u8 val1, val2;
-
-	ms_card->segment_cnt = ms_card->total_block >> 9;
-	RTSX_DEBUGP("ms_card->segment_cnt = %d\n", ms_card->segment_cnt);
-
-	size = ms_card->segment_cnt * sizeof(struct zone_entry);
-	ms_card->segment = vzalloc(size);
-	if (ms_card->segment == NULL)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = ms_read_page(chip, ms_card->boot_block, 1);
-	if (retval != STATUS_SUCCESS)
-		TRACE_GOTO(chip, INIT_FAIL);
-
-	reg_addr = PPBUF_BASE2;
-	for (i = 0; i < (((ms_card->total_block >> 9) * 10) + 1); i++) {
-		retval = rtsx_read_register(chip, reg_addr++, &val1);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, INIT_FAIL);
-
-		retval = rtsx_read_register(chip, reg_addr++, &val2);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, INIT_FAIL);
-
-		defect_block = ((u16)val1 << 8) | val2;
-		if (defect_block == 0xFFFF)
-			break;
-
-		seg_no = defect_block / 512;
-		ms_card->segment[seg_no].defect_list[ms_card->segment[seg_no].disable_count++] = defect_block;
-	}
-
-	for (i = 0; i < ms_card->segment_cnt; i++) {
-		ms_card->segment[i].build_flag = 0;
-		ms_card->segment[i].l2p_table = NULL;
-		ms_card->segment[i].free_table = NULL;
-		ms_card->segment[i].get_index = 0;
-		ms_card->segment[i].set_index = 0;
-		ms_card->segment[i].unused_blk_cnt = 0;
-
-		RTSX_DEBUGP("defective block count of segment %d is %d\n",
-					i, ms_card->segment[i].disable_count);
-	}
-
-	return STATUS_SUCCESS;
-
-INIT_FAIL:
-	if (ms_card->segment) {
-		vfree(ms_card->segment);
-		ms_card->segment = NULL;
-	}
-
-	return STATUS_FAIL;
-}
-
-static u16 ms_get_l2p_tbl(struct rtsx_chip *chip, int seg_no, u16 log_off)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	struct zone_entry *segment;
-
-	if (ms_card->segment == NULL)
-		return 0xFFFF;
-
-	segment = &(ms_card->segment[seg_no]);
-
-	if (segment->l2p_table)
-		return segment->l2p_table[log_off];
-
-	return 0xFFFF;
-}
-
-static void ms_set_l2p_tbl(struct rtsx_chip *chip, int seg_no, u16 log_off, u16 phy_blk)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	struct zone_entry *segment;
-
-	if (ms_card->segment == NULL)
-		return;
-
-	segment = &(ms_card->segment[seg_no]);
-	if (segment->l2p_table)
-		segment->l2p_table[log_off] = phy_blk;
-}
-
-static void ms_set_unused_block(struct rtsx_chip *chip, u16 phy_blk)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	struct zone_entry *segment;
-	int seg_no;
-
-	seg_no = (int)phy_blk >> 9;
-	segment = &(ms_card->segment[seg_no]);
-
-	segment->free_table[segment->set_index++] = phy_blk;
-	if (segment->set_index >= MS_FREE_TABLE_CNT)
-		segment->set_index = 0;
-
-	segment->unused_blk_cnt++;
-}
-
-static u16 ms_get_unused_block(struct rtsx_chip *chip, int seg_no)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	struct zone_entry *segment;
-	u16 phy_blk;
-
-	segment = &(ms_card->segment[seg_no]);
-
-	if (segment->unused_blk_cnt <= 0)
-		return 0xFFFF;
-
-	phy_blk = segment->free_table[segment->get_index];
-	segment->free_table[segment->get_index++] = 0xFFFF;
-	if (segment->get_index >= MS_FREE_TABLE_CNT)
-		segment->get_index = 0;
-
-	segment->unused_blk_cnt--;
-
-	return phy_blk;
-}
-
-static const unsigned short ms_start_idx[] = {0, 494, 990, 1486, 1982, 2478, 2974, 3470,
-	3966, 4462, 4958, 5454, 5950, 6446, 6942, 7438, 7934};
-
-static int ms_arbitrate_l2p(struct rtsx_chip *chip, u16 phy_blk, u16 log_off, u8 us1, u8 us2)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	struct zone_entry *segment;
-	int seg_no;
-	u16 tmp_blk;
-
-	seg_no = (int)phy_blk >> 9;
-	segment = &(ms_card->segment[seg_no]);
-	tmp_blk = segment->l2p_table[log_off];
-
-	if (us1 != us2) {
-		if (us1 == 0) {
-			if (!(chip->card_wp & MS_CARD))
-				ms_erase_block(chip, tmp_blk);
-
-			ms_set_unused_block(chip, tmp_blk);
-			segment->l2p_table[log_off] = phy_blk;
-		} else {
-			if (!(chip->card_wp & MS_CARD))
-				ms_erase_block(chip, phy_blk);
-
-			ms_set_unused_block(chip, phy_blk);
-		}
-	} else {
-		if (phy_blk < tmp_blk) {
-			if (!(chip->card_wp & MS_CARD))
-				ms_erase_block(chip, phy_blk);
-
-			ms_set_unused_block(chip, phy_blk);
-		} else {
-			if (!(chip->card_wp & MS_CARD))
-				ms_erase_block(chip, tmp_blk);
-
-			ms_set_unused_block(chip, tmp_blk);
-			segment->l2p_table[log_off] = phy_blk;
-		}
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	struct zone_entry *segment;
-	int retval, table_size, disable_cnt, defect_flag, i;
-	u16 start, end, phy_blk, log_blk, tmp_blk;
-	u8 extra[MS_EXTRA_SIZE], us1, us2;
-
-	RTSX_DEBUGP("ms_build_l2p_tbl: %d\n", seg_no);
-
-	if (ms_card->segment == NULL) {
-		retval = ms_init_l2p_tbl(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, retval);
-	}
-
-	if (ms_card->segment[seg_no].build_flag) {
-		RTSX_DEBUGP("l2p table of segment %d has been built\n", seg_no);
-		return STATUS_SUCCESS;
-	}
-
-	if (seg_no == 0)
-		table_size = 494;
-	else
-		table_size = 496;
-
-	segment = &(ms_card->segment[seg_no]);
-
-	if (segment->l2p_table == NULL) {
-		segment->l2p_table = (u16 *)vmalloc(table_size * 2);
-		if (segment->l2p_table == NULL)
-			TRACE_GOTO(chip, BUILD_FAIL);
-	}
-	memset((u8 *)(segment->l2p_table), 0xff, table_size * 2);
-
-	if (segment->free_table == NULL) {
-		segment->free_table = (u16 *)vmalloc(MS_FREE_TABLE_CNT * 2);
-		if (segment->free_table == NULL)
-			TRACE_GOTO(chip, BUILD_FAIL);
-	}
-	memset((u8 *)(segment->free_table), 0xff, MS_FREE_TABLE_CNT * 2);
-
-	start = (u16)seg_no << 9;
-	end = (u16)(seg_no + 1) << 9;
-
-	disable_cnt = segment->disable_count;
-
-	segment->get_index = segment->set_index = 0;
-	segment->unused_blk_cnt = 0;
-
-	for (phy_blk = start; phy_blk < end; phy_blk++) {
-		if (disable_cnt) {
-			defect_flag = 0;
-			for (i = 0; i < segment->disable_count; i++) {
-				if (phy_blk == segment->defect_list[i]) {
-					defect_flag = 1;
-					break;
-				}
-			}
-			if (defect_flag) {
-				disable_cnt--;
-				continue;
-			}
-		}
-
-		retval = ms_read_extra_data(chip, phy_blk, 0, extra, MS_EXTRA_SIZE);
-		if (retval != STATUS_SUCCESS) {
-			RTSX_DEBUGP("read extra data fail\n");
-			ms_set_bad_block(chip, phy_blk);
-			continue;
-		}
-
-		if (seg_no == ms_card->segment_cnt - 1) {
-			if (!(extra[1] & NOT_TRANSLATION_TABLE)) {
-				if (!(chip->card_wp & MS_CARD)) {
-					retval = ms_erase_block(chip, phy_blk);
-					if (retval != STATUS_SUCCESS)
-						continue;
-					extra[2] = 0xff;
-					extra[3] = 0xff;
-				}
-			}
-		}
-
-		if (!(extra[0] & BLOCK_OK))
-			continue;
-		if (!(extra[1] & NOT_BOOT_BLOCK))
-			continue;
-		if ((extra[0] & PAGE_OK) != PAGE_OK)
-			continue;
-
-		log_blk = ((u16)extra[2] << 8) | extra[3];
-
-		if (log_blk == 0xFFFF) {
-			if (!(chip->card_wp & MS_CARD)) {
-				retval = ms_erase_block(chip, phy_blk);
-				if (retval != STATUS_SUCCESS)
-					continue;
-			}
-			ms_set_unused_block(chip, phy_blk);
-			continue;
-		}
-
-		if ((log_blk < ms_start_idx[seg_no]) ||
-				(log_blk >= ms_start_idx[seg_no+1])) {
-			if (!(chip->card_wp & MS_CARD)) {
-				retval = ms_erase_block(chip, phy_blk);
-				if (retval != STATUS_SUCCESS)
-					continue;
-			}
-			ms_set_unused_block(chip, phy_blk);
-			continue;
-		}
-
-		if (segment->l2p_table[log_blk - ms_start_idx[seg_no]] == 0xFFFF) {
-			segment->l2p_table[log_blk - ms_start_idx[seg_no]] = phy_blk;
-			continue;
-		}
-
-		us1 = extra[0] & 0x10;
-		tmp_blk = segment->l2p_table[log_blk - ms_start_idx[seg_no]];
-		retval = ms_read_extra_data(chip, tmp_blk, 0, extra, MS_EXTRA_SIZE);
-		if (retval != STATUS_SUCCESS)
-			continue;
-		us2 = extra[0] & 0x10;
-
-		(void)ms_arbitrate_l2p(chip, phy_blk, log_blk-ms_start_idx[seg_no], us1, us2);
-		continue;
-	}
-
-	segment->build_flag = 1;
-
-	RTSX_DEBUGP("unused block count: %d\n", segment->unused_blk_cnt);
-
-	/* Logical Address Confirmation Process */
-	if (seg_no == ms_card->segment_cnt - 1) {
-		if (segment->unused_blk_cnt < 2)
-			chip->card_wp |= MS_CARD;
-	} else {
-		if (segment->unused_blk_cnt < 1)
-			chip->card_wp |= MS_CARD;
-	}
-
-	if (chip->card_wp & MS_CARD)
-		return STATUS_SUCCESS;
-
-	for (log_blk = ms_start_idx[seg_no]; log_blk < ms_start_idx[seg_no + 1]; log_blk++) {
-		if (segment->l2p_table[log_blk-ms_start_idx[seg_no]] == 0xFFFF) {
-			phy_blk = ms_get_unused_block(chip, seg_no);
-			if (phy_blk == 0xFFFF) {
-				chip->card_wp |= MS_CARD;
-				return STATUS_SUCCESS;
-			}
-			retval = ms_init_page(chip, phy_blk, log_blk, 0, 1);
-			if (retval != STATUS_SUCCESS)
-				TRACE_GOTO(chip, BUILD_FAIL);
-
-			segment->l2p_table[log_blk-ms_start_idx[seg_no]] = phy_blk;
-			if (seg_no == ms_card->segment_cnt - 1) {
-				if (segment->unused_blk_cnt < 2) {
-					chip->card_wp |= MS_CARD;
-					return STATUS_SUCCESS;
-				}
-			} else {
-				if (segment->unused_blk_cnt < 1) {
-					chip->card_wp |= MS_CARD;
-					return STATUS_SUCCESS;
-				}
-			}
-		}
-	}
-
-	/* Make boot block be the first normal block */
-	if (seg_no == 0) {
-		for (log_blk = 0; log_blk < 494; log_blk++) {
-			tmp_blk = segment->l2p_table[log_blk];
-			if (tmp_blk < ms_card->boot_block) {
-				RTSX_DEBUGP("Boot block is not the first normal block.\n");
-
-				if (chip->card_wp & MS_CARD)
-					break;
-
-				phy_blk = ms_get_unused_block(chip, 0);
-				retval = ms_copy_page(chip, tmp_blk, phy_blk,
-						log_blk, 0, ms_card->page_off + 1);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-
-				segment->l2p_table[log_blk] = phy_blk;
-
-				retval = ms_set_bad_block(chip, tmp_blk);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-	}
-
-	return STATUS_SUCCESS;
-
-BUILD_FAIL:
-	segment->build_flag = 0;
-	if (segment->l2p_table) {
-		vfree(segment->l2p_table);
-		segment->l2p_table = NULL;
-	}
-	if (segment->free_table) {
-		vfree(segment->free_table);
-		segment->free_table = NULL;
-	}
-
-	return STATUS_FAIL;
-}
-
-
-int reset_ms_card(struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-
-	memset(ms_card, 0, sizeof(struct ms_info));
-
-	retval = enable_card_clock(chip, MS_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = select_card(chip, MS_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ms_card->ms_type = 0;
-
-	retval = reset_ms_pro(chip);
-	if (retval != STATUS_SUCCESS) {
-		if (ms_card->check_ms_flow) {
-			retval = reset_ms(chip);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-		} else {
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	retval = ms_set_init_para(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (!CHK_MSPRO(ms_card)) {
-		/* Build table for the last segment,
-		 * to check if L2P table block exists, erasing it
-		 */
-		retval = ms_build_l2p_tbl(chip, ms_card->total_block / 512 - 1);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	RTSX_DEBUGP("ms_card->ms_type = 0x%x\n", ms_card->ms_type);
-
-	return STATUS_SUCCESS;
-}
-
-static int mspro_set_rw_cmd(struct rtsx_chip *chip, u32 start_sec, u16 sec_cnt, u8 cmd)
-{
-	int retval, i;
-	u8 data[8];
-
-	data[0] = cmd;
-	data[1] = (u8)(sec_cnt >> 8);
-	data[2] = (u8)sec_cnt;
-	data[3] = (u8)(start_sec >> 24);
-	data[4] = (u8)(start_sec >> 16);
-	data[5] = (u8)(start_sec >> 8);
-	data[6] = (u8)start_sec;
-	data[7] = 0;
-
-	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-		retval = ms_write_bytes(chip, PRO_EX_SET_CMD, 7, WAIT_INT, data, 8);
-		if (retval == STATUS_SUCCESS)
-			break;
-	}
-	if (i == MS_MAX_RETRY_COUNT)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-
-void mspro_stop_seq_mode(struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-
-	RTSX_DEBUGP("--%s--\n", __func__);
-
-	if (ms_card->seq_mode) {
-		retval = ms_switch_clock(chip);
-		if (retval != STATUS_SUCCESS)
-			return;
-
-		ms_card->seq_mode = 0;
-		ms_card->total_sec_cnt = 0;
-		ms_send_cmd(chip, PRO_STOP, WAIT_INT);
-
-		rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
-	}
-}
-
-static inline int ms_auto_tune_clock(struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-
-	RTSX_DEBUGP("--%s--\n", __func__);
-
-	if (chip->asic_code) {
-		if (ms_card->ms_clock > 30)
-			ms_card->ms_clock -= 20;
-	} else {
-		if (ms_card->ms_clock == CLK_80)
-			ms_card->ms_clock = CLK_60;
-		else if (ms_card->ms_clock == CLK_60)
-			ms_card->ms_clock = CLK_40;
-	}
-
-	retval = ms_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int mspro_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval, mode_2k = 0;
-	u16 count;
-	u8 val, trans_mode, rw_tpc, rw_cmd;
-
-	ms_set_err_code(chip, MS_NO_ERROR);
-
-	ms_card->cleanup_counter = 0;
-
-	if (CHK_MSHG(ms_card)) {
-		if ((start_sector % 4) || (sector_cnt % 4)) {
-			if (srb->sc_data_direction == DMA_FROM_DEVICE) {
-				rw_tpc = PRO_READ_LONG_DATA;
-				rw_cmd = PRO_READ_DATA;
-			} else {
-				rw_tpc = PRO_WRITE_LONG_DATA;
-				rw_cmd = PRO_WRITE_DATA;
-			}
-		} else {
-			if (srb->sc_data_direction == DMA_FROM_DEVICE) {
-				rw_tpc = PRO_READ_QUAD_DATA;
-				rw_cmd = PRO_READ_2K_DATA;
-			} else {
-				rw_tpc = PRO_WRITE_QUAD_DATA;
-				rw_cmd = PRO_WRITE_2K_DATA;
-			}
-			mode_2k = 1;
-		}
-	} else {
-		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
-			rw_tpc = PRO_READ_LONG_DATA;
-			rw_cmd = PRO_READ_DATA;
-		} else {
-			rw_tpc = PRO_WRITE_LONG_DATA;
-			rw_cmd = PRO_WRITE_DATA;
-		}
-	}
-
-	retval = ms_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (srb->sc_data_direction == DMA_FROM_DEVICE)
-		trans_mode = MS_TM_AUTO_READ;
-	else
-		trans_mode = MS_TM_AUTO_WRITE;
-
-	RTSX_READ_REG(chip, MS_TRANS_CFG, &val);
-
-	if (ms_card->seq_mode) {
-		if ((ms_card->pre_dir != srb->sc_data_direction)
-				|| ((ms_card->pre_sec_addr + ms_card->pre_sec_cnt) != start_sector)
-				|| (mode_2k && (ms_card->seq_mode & MODE_512_SEQ))
-				|| (!mode_2k && (ms_card->seq_mode & MODE_2K_SEQ))
-				|| !(val & MS_INT_BREQ)
-				|| ((ms_card->total_sec_cnt + sector_cnt) > 0xFE00)) {
-			ms_card->seq_mode = 0;
-			ms_card->total_sec_cnt = 0;
-			if (val & MS_INT_BREQ) {
-				retval = ms_send_cmd(chip, PRO_STOP, WAIT_INT);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-
-				rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
-			}
-		}
-	}
-
-	if (!ms_card->seq_mode) {
-		ms_card->total_sec_cnt = 0;
-		if (sector_cnt >= SEQ_START_CRITERIA) {
-			if ((ms_card->capacity - start_sector) > 0xFE00)
-				count = 0xFE00;
-			else
-				count = (u16)(ms_card->capacity - start_sector);
-
-			if (count > sector_cnt) {
-				if (mode_2k)
-					ms_card->seq_mode |= MODE_2K_SEQ;
-				else
-					ms_card->seq_mode |= MODE_512_SEQ;
-			}
-		} else {
-			count = sector_cnt;
-		}
-		retval = mspro_set_rw_cmd(chip, start_sector, count, rw_cmd);
-		if (retval != STATUS_SUCCESS) {
-			ms_card->seq_mode = 0;
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	retval = ms_transfer_data(chip, trans_mode, rw_tpc, sector_cnt, WAIT_INT, mode_2k,
-			scsi_sg_count(srb), scsi_sglist(srb), scsi_bufflen(srb));
-	if (retval != STATUS_SUCCESS) {
-		ms_card->seq_mode = 0;
-		rtsx_read_register(chip, MS_TRANS_CFG, &val);
-		rtsx_clear_ms_error(chip);
-
-		if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
-			chip->rw_need_retry = 0;
-			RTSX_DEBUGP("No card exist, exit mspro_rw_multi_sector\n");
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		if (val & MS_INT_BREQ)
-			ms_send_cmd(chip, PRO_STOP, WAIT_INT);
-
-		if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) {
-			RTSX_DEBUGP("MSPro CRC error, tune clock!\n");
-			chip->rw_need_retry = 1;
-			ms_auto_tune_clock(chip);
-		}
-
-		TRACE_RET(chip, retval);
-	}
-
-	if (ms_card->seq_mode) {
-		ms_card->pre_sec_addr = start_sector;
-		ms_card->pre_sec_cnt = sector_cnt;
-		ms_card->pre_dir = srb->sc_data_direction;
-		ms_card->total_sec_cnt += sector_cnt;
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int mspro_read_format_progress(struct rtsx_chip *chip, const int short_data_len)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval, i;
-	u32 total_progress, cur_progress;
-	u8 cnt, tmp;
-	u8 data[8];
-
-	RTSX_DEBUGP("mspro_read_format_progress, short_data_len = %d\n", short_data_len);
-
-	retval = ms_switch_clock(chip);
-	if (retval != STATUS_SUCCESS) {
-		ms_card->format_status = FORMAT_FAIL;
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp);
-	if (retval != STATUS_SUCCESS) {
-		ms_card->format_status = FORMAT_FAIL;
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (!(tmp & MS_INT_BREQ)) {
-		if ((tmp &  (MS_INT_CED | MS_INT_BREQ | MS_INT_CMDNK | MS_INT_ERR)) == MS_INT_CED) {
-			ms_card->format_status = FORMAT_SUCCESS;
-			return STATUS_SUCCESS;
-		}
-		ms_card->format_status = FORMAT_FAIL;
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (short_data_len >= 256)
-		cnt = 0;
-	else
-		cnt = (u8)short_data_len;
-
-	retval = rtsx_write_register(chip, MS_CFG, MS_NO_CHECK_INT, MS_NO_CHECK_INT);
-	if (retval != STATUS_SUCCESS) {
-		ms_card->format_status = FORMAT_FAIL;
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, cnt, WAIT_INT, data, 8);
-	if (retval != STATUS_SUCCESS) {
-		ms_card->format_status = FORMAT_FAIL;
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	total_progress = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
-	cur_progress = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7];
-
-	RTSX_DEBUGP("total_progress = %d, cur_progress = %d\n",
-				total_progress, cur_progress);
-
-	if (total_progress == 0) {
-		ms_card->progress = 0;
-	} else {
-		u64 ulltmp = (u64)cur_progress * (u64)65535;
-		do_div(ulltmp, total_progress);
-		ms_card->progress = (u16)ulltmp;
-	}
-	RTSX_DEBUGP("progress = %d\n", ms_card->progress);
-
-	for (i = 0; i < 5000; i++) {
-		retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp);
-		if (retval != STATUS_SUCCESS) {
-			ms_card->format_status = FORMAT_FAIL;
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-		if (tmp & (MS_INT_CED | MS_INT_CMDNK | MS_INT_BREQ | MS_INT_ERR))
-			break;
-
-		wait_timeout(1);
-	}
-
-	retval = rtsx_write_register(chip, MS_CFG, MS_NO_CHECK_INT, 0);
-	if (retval != STATUS_SUCCESS) {
-		ms_card->format_status = FORMAT_FAIL;
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (i == 5000) {
-		ms_card->format_status = FORMAT_FAIL;
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (tmp & (MS_INT_CMDNK | MS_INT_ERR)) {
-		ms_card->format_status = FORMAT_FAIL;
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (tmp & MS_INT_CED) {
-		ms_card->format_status = FORMAT_SUCCESS;
-		ms_card->pro_under_formatting = 0;
-	} else if (tmp & MS_INT_BREQ) {
-		ms_card->format_status = FORMAT_IN_PROGRESS;
-	} else {
-		ms_card->format_status = FORMAT_FAIL;
-		ms_card->pro_under_formatting = 0;
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-void mspro_polling_format_status(struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int i;
-
-	if (ms_card->pro_under_formatting && (rtsx_get_stat(chip) != RTSX_STAT_SS)) {
-		rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-		for (i = 0; i < 65535; i++) {
-			mspro_read_format_progress(chip, MS_SHORT_DATA_LEN);
-			if (ms_card->format_status != FORMAT_IN_PROGRESS)
-				break;
-		}
-	}
-
-	return;
-}
-
-int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip, int short_data_len, int quick_format)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval, i;
-	u8 buf[8], tmp;
-	u16 para;
-
-	RTSX_DEBUGP("--%s--\n", __func__);
-
-	retval = ms_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = ms_set_rw_reg_addr(chip, 0x00, 0x00, Pro_TPCParm, 0x01);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	memset(buf, 0, 2);
-	switch (short_data_len) {
-	case 32:
-		buf[0] = 0;
-		break;
-	case 64:
-		buf[0] = 1;
-		break;
-	case 128:
-		buf[0] = 2;
-		break;
-	case 256:
-	default:
-		buf[0] = 3;
-		break;
-	}
-
-	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-		retval = ms_write_bytes(chip, PRO_WRITE_REG, 1, NO_WAIT_INT, buf, 2);
-		if (retval == STATUS_SUCCESS)
-			break;
-	}
-	if (i == MS_MAX_RETRY_COUNT)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (quick_format)
-		para = 0x0000;
-	else
-		para = 0x0001;
-
-	retval = mspro_set_rw_cmd(chip, 0, para, PRO_FORMAT);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_READ_REG(chip, MS_TRANS_CFG, &tmp);
-
-	if (tmp & (MS_INT_CMDNK | MS_INT_ERR))
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if ((tmp & (MS_INT_BREQ | MS_INT_CED)) == MS_INT_BREQ) {
-		ms_card->pro_under_formatting = 1;
-		ms_card->progress = 0;
-		ms_card->format_status = FORMAT_IN_PROGRESS;
-		return STATUS_SUCCESS;
-	}
-
-	if (tmp & MS_INT_CED) {
-		ms_card->pro_under_formatting = 0;
-		ms_card->progress = 0;
-		ms_card->format_status = FORMAT_SUCCESS;
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_NO_SENSE);
-		return STATUS_SUCCESS;
-	}
-
-	TRACE_RET(chip, STATUS_FAIL);
-}
-
-
-static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, u16 log_blk,
-		u8 start_page, u8 end_page, u8 *buf, unsigned int *index, unsigned int *offset)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval, i;
-	u8 extra[MS_EXTRA_SIZE], page_addr, val, trans_cfg, data[6];
-	u8 *ptr;
-
-	retval = ms_read_extra_data(chip, phy_blk, start_page, extra, MS_EXTRA_SIZE);
-	if (retval == STATUS_SUCCESS) {
-		if ((extra[1] & 0x30) != 0x30) {
-			ms_set_err_code(chip, MS_FLASH_READ_ERROR);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (CHK_MS4BIT(ms_card))
-		data[0] = 0x88;
-	else
-		data[0] = 0x80;
-
-	data[1] = 0;
-	data[2] = (u8)(phy_blk >> 8);
-	data[3] = (u8)phy_blk;
-	data[4] = 0;
-	data[5] = start_page;
-
-	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-		retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6);
-		if (retval == STATUS_SUCCESS)
-			break;
-	}
-	if (i == MS_MAX_RETRY_COUNT)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ms_set_err_code(chip, MS_NO_ERROR);
-
-	retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ptr = buf;
-
-	for (page_addr = start_page; page_addr < end_page; page_addr++) {
-		ms_set_err_code(chip, MS_NO_ERROR);
-
-		if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
-			ms_set_err_code(chip, MS_NO_CARD);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		if (val & INT_REG_CMDNK) {
-			ms_set_err_code(chip, MS_CMD_NK);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-		if (val & INT_REG_ERR) {
-			if (val & INT_REG_BREQ) {
-				retval = ms_read_status_reg(chip);
-				if (retval != STATUS_SUCCESS) {
-					if (!(chip->card_wp & MS_CARD)) {
-						reset_ms(chip);
-						ms_set_page_status(log_blk, setPS_NG, extra, MS_EXTRA_SIZE);
-						ms_write_extra_data(chip, phy_blk,
-								page_addr, extra, MS_EXTRA_SIZE);
-					}
-					ms_set_err_code(chip, MS_FLASH_READ_ERROR);
-					TRACE_RET(chip, STATUS_FAIL);
-				}
-			} else {
-				ms_set_err_code(chip, MS_FLASH_READ_ERROR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		} else {
-			if (!(val & INT_REG_BREQ)) {
-				ms_set_err_code(chip, MS_BREQ_ERROR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-
-		if (page_addr == (end_page - 1)) {
-			if (!(val & INT_REG_CED)) {
-				retval = ms_send_cmd(chip, BLOCK_END, WAIT_INT);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-
-			if (!(val & INT_REG_CED)) {
-				ms_set_err_code(chip, MS_FLASH_READ_ERROR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			trans_cfg = NO_WAIT_INT;
-		} else {
-			trans_cfg = WAIT_INT;
-		}
-
-		rtsx_init_cmd(chip);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, READ_PAGE_DATA);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, trans_cfg);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-
-		trans_dma_enable(DMA_FROM_DEVICE, chip, 512, DMA_512);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
-				MS_TRANSFER_START |  MS_TM_NORMAL_READ);
-		rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
-
-		rtsx_send_cmd_no_wait(chip);
-
-		retval = rtsx_transfer_data_partial(chip, MS_CARD, ptr, 512, scsi_sg_count(chip->srb),
-				index, offset, DMA_FROM_DEVICE, chip->ms_timeout);
-		if (retval < 0) {
-			if (retval == -ETIMEDOUT) {
-				ms_set_err_code(chip, MS_TO_ERROR);
-				rtsx_clear_ms_error(chip);
-				TRACE_RET(chip, STATUS_TIMEDOUT);
-			}
-
-			retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
-			if (retval != STATUS_SUCCESS) {
-				ms_set_err_code(chip, MS_TO_ERROR);
-				rtsx_clear_ms_error(chip);
-				TRACE_RET(chip, STATUS_TIMEDOUT);
-			}
-			if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) {
-				ms_set_err_code(chip, MS_CRC16_ERROR);
-				rtsx_clear_ms_error(chip);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-
-		if (scsi_sg_count(chip->srb) == 0)
-			ptr += 512;
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
-		u16 log_blk, u8 start_page, u8 end_page, u8 *buf,
-		unsigned int *index, unsigned int *offset)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval, i;
-	u8 page_addr, val, data[16];
-	u8 *ptr;
-
-	if (!start_page) {
-		retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 7);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		if (CHK_MS4BIT(ms_card))
-			data[0] = 0x88;
-		else
-			data[0] = 0x80;
-
-		data[1] = 0;
-		data[2] = (u8)(old_blk >> 8);
-		data[3] = (u8)old_blk;
-		data[4] = 0x80;
-		data[5] = 0;
-		data[6] = 0xEF;
-		data[7] = 0xFF;
-
-		retval = ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT, data, 8);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		ms_set_err_code(chip, MS_NO_ERROR);
-		retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, 1, NO_WAIT_INT);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, (6 + MS_EXTRA_SIZE));
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ms_set_err_code(chip, MS_NO_ERROR);
-
-	if (CHK_MS4BIT(ms_card))
-		data[0] = 0x88;
-	else
-		data[0] = 0x80;
-
-	data[1] = 0;
-	data[2] = (u8)(new_blk >> 8);
-	data[3] = (u8)new_blk;
-	if ((end_page - start_page) == 1)
-		data[4] = 0x20;
-	else
-		data[4] = 0;
-
-	data[5] = start_page;
-	data[6] = 0xF8;
-	data[7] = 0xFF;
-	data[8] = (u8)(log_blk >> 8);
-	data[9] = (u8)log_blk;
-
-	for (i = 0x0A; i < 0x10; i++)
-		data[i] = 0xFF;
-
-	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-		retval = ms_write_bytes(chip, WRITE_REG, 6 + MS_EXTRA_SIZE, NO_WAIT_INT, data, 16);
-		if (retval == STATUS_SUCCESS)
-			break;
-	}
-	if (i == MS_MAX_RETRY_COUNT)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-		retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
-		if (retval == STATUS_SUCCESS)
-			break;
-	}
-	if (i == MS_MAX_RETRY_COUNT)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ptr = buf;
-	for (page_addr = start_page; page_addr < end_page; page_addr++) {
-		ms_set_err_code(chip, MS_NO_ERROR);
-
-		if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
-			ms_set_err_code(chip, MS_NO_CARD);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		if (val & INT_REG_CMDNK) {
-			ms_set_err_code(chip, MS_CMD_NK);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-		if (val & INT_REG_ERR) {
-			ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-		if (!(val & INT_REG_BREQ)) {
-			ms_set_err_code(chip, MS_BREQ_ERROR);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		udelay(30);
-
-		rtsx_init_cmd(chip);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, WRITE_PAGE_DATA);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, WAIT_INT);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-
-		trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
-				MS_TRANSFER_START |  MS_TM_NORMAL_WRITE);
-		rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
-
-		rtsx_send_cmd_no_wait(chip);
-
-		retval = rtsx_transfer_data_partial(chip, MS_CARD, ptr, 512, scsi_sg_count(chip->srb),
-				index, offset, DMA_TO_DEVICE, chip->ms_timeout);
-		if (retval < 0) {
-			ms_set_err_code(chip, MS_TO_ERROR);
-			rtsx_clear_ms_error(chip);
-
-			if (retval == -ETIMEDOUT)
-				TRACE_RET(chip, STATUS_TIMEDOUT);
-			else
-				TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		if ((end_page - start_page) == 1) {
-			if (!(val & INT_REG_CED)) {
-				ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		} else {
-			if (page_addr == (end_page - 1)) {
-				if (!(val & INT_REG_CED)) {
-					retval = ms_send_cmd(chip, BLOCK_END, WAIT_INT);
-					if (retval != STATUS_SUCCESS)
-						TRACE_RET(chip, STATUS_FAIL);
-				}
-
-				retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			if ((page_addr == (end_page - 1)) || (page_addr == ms_card->page_off)) {
-				if (!(val & INT_REG_CED)) {
-					ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-					TRACE_RET(chip, STATUS_FAIL);
-				}
-			}
-		}
-
-		if (scsi_sg_count(chip->srb) == 0)
-			ptr += 512;
-	}
-
-	return STATUS_SUCCESS;
-}
-
-
-static int ms_finish_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
-		u16 log_blk, u8 page_off)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval, seg_no;
-
-	retval = ms_copy_page(chip, old_blk, new_blk, log_blk,
-			page_off, ms_card->page_off + 1);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	seg_no = old_blk >> 9;
-
-	if (MS_TST_BAD_BLOCK_FLG(ms_card)) {
-		MS_CLR_BAD_BLOCK_FLG(ms_card);
-		ms_set_bad_block(chip, old_blk);
-	} else {
-		retval = ms_erase_block(chip, old_blk);
-		if (retval == STATUS_SUCCESS)
-			ms_set_unused_block(chip, old_blk);
-	}
-
-	ms_set_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no], new_blk);
-
-	return STATUS_SUCCESS;
-}
-
-static int ms_prepare_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
-		u16 log_blk, u8 start_page)
-{
-	int retval;
-
-	if (start_page) {
-		retval = ms_copy_page(chip, old_blk, new_blk, log_blk, 0, start_page);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-#ifdef MS_DELAY_WRITE
-int ms_delay_write(struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	struct ms_delay_write_tag *delay_write = &(ms_card->delay_write);
-	int retval;
-
-	if (delay_write->delay_write_flag) {
-		retval = ms_set_init_para(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		delay_write->delay_write_flag = 0;
-		retval = ms_finish_write(chip,
-				delay_write->old_phyblock, delay_write->new_phyblock,
-				delay_write->logblock, delay_write->pageoff);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-#endif
-
-static inline void ms_rw_fail(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	if (srb->sc_data_direction == DMA_FROM_DEVICE)
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-	else
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-}
-
-static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	unsigned int lun = SCSI_LUN(srb);
-	int retval, seg_no;
-	unsigned int index = 0, offset = 0;
-	u16 old_blk = 0, new_blk = 0, log_blk, total_sec_cnt = sector_cnt;
-	u8 start_page, end_page = 0, page_cnt;
-	u8 *ptr;
-#ifdef MS_DELAY_WRITE
-	struct ms_delay_write_tag *delay_write = &(ms_card->delay_write);
-#endif
-
-	ms_set_err_code(chip, MS_NO_ERROR);
-
-	ms_card->cleanup_counter = 0;
-
-	ptr = (u8 *)scsi_sglist(srb);
-
-	retval = ms_switch_clock(chip);
-	if (retval != STATUS_SUCCESS) {
-		ms_rw_fail(srb, chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	log_blk = (u16)(start_sector >> ms_card->block_shift);
-	start_page = (u8)(start_sector & ms_card->page_off);
-
-	for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1; seg_no++) {
-		if (log_blk < ms_start_idx[seg_no+1])
-			break;
-	}
-
-	if (ms_card->segment[seg_no].build_flag == 0) {
-		retval = ms_build_l2p_tbl(chip, seg_no);
-		if (retval != STATUS_SUCCESS) {
-			chip->card_fail |= MS_CARD;
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	if (srb->sc_data_direction == DMA_TO_DEVICE) {
-#ifdef MS_DELAY_WRITE
-		if (delay_write->delay_write_flag &&
-				(delay_write->logblock == log_blk) &&
-				(start_page > delay_write->pageoff)) {
-			delay_write->delay_write_flag = 0;
-			retval = ms_copy_page(chip,
-				delay_write->old_phyblock,
-				delay_write->new_phyblock, log_blk,
-				delay_write->pageoff, start_page);
-			if (retval != STATUS_SUCCESS) {
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			old_blk = delay_write->old_phyblock;
-			new_blk = delay_write->new_phyblock;
-		} else if (delay_write->delay_write_flag &&
-				(delay_write->logblock == log_blk) &&
-				(start_page == delay_write->pageoff)) {
-			delay_write->delay_write_flag = 0;
-			old_blk = delay_write->old_phyblock;
-			new_blk = delay_write->new_phyblock;
-		} else {
-			retval = ms_delay_write(chip);
-			if (retval != STATUS_SUCCESS) {
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-#endif
-			old_blk = ms_get_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no]);
-			new_blk  = ms_get_unused_block(chip, seg_no);
-			if ((old_blk == 0xFFFF) || (new_blk == 0xFFFF)) {
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			retval = ms_prepare_write(chip, old_blk, new_blk, log_blk, start_page);
-			if (retval != STATUS_SUCCESS) {
-				if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
-					set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-					TRACE_RET(chip, STATUS_FAIL);
-				}
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-#ifdef MS_DELAY_WRITE
-		}
-#endif
-	} else {
-#ifdef MS_DELAY_WRITE
-		retval = ms_delay_write(chip);
-		if (retval != STATUS_SUCCESS) {
-			if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-#endif
-		old_blk = ms_get_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no]);
-		if (old_blk == 0xFFFF) {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	RTSX_DEBUGP("seg_no = %d, old_blk = 0x%x, new_blk = 0x%x\n", seg_no, old_blk, new_blk);
-
-	while (total_sec_cnt) {
-		if ((start_page + total_sec_cnt) > (ms_card->page_off + 1))
-			end_page = ms_card->page_off + 1;
-		else
-			end_page = start_page + (u8)total_sec_cnt;
-
-		page_cnt = end_page - start_page;
-
-		RTSX_DEBUGP("start_page = %d, end_page = %d, page_cnt = %d\n",
-				start_page, end_page, page_cnt);
-
-		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
-			retval = ms_read_multiple_pages(chip,
-				old_blk, log_blk, start_page, end_page,
-				ptr, &index, &offset);
-		} else {
-			retval = ms_write_multiple_pages(chip, old_blk,
-				new_blk, log_blk, start_page, end_page,
-				ptr, &index, &offset);
-		}
-
-		if (retval != STATUS_SUCCESS) {
-			toggle_gpio(chip, 1);
-			if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			ms_rw_fail(srb, chip);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		if (srb->sc_data_direction == DMA_TO_DEVICE) {
-			if (end_page == (ms_card->page_off + 1)) {
-				retval = ms_erase_block(chip, old_blk);
-				if (retval == STATUS_SUCCESS)
-					ms_set_unused_block(chip, old_blk);
-
-				ms_set_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no], new_blk);
-			}
-		}
-
-		total_sec_cnt -= page_cnt;
-		if (scsi_sg_count(srb) == 0)
-			ptr += page_cnt * 512;
-
-		if (total_sec_cnt == 0)
-			break;
-
-		log_blk++;
-
-		for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1;
-				seg_no++) {
-			if (log_blk < ms_start_idx[seg_no+1])
-				break;
-		}
-
-		if (ms_card->segment[seg_no].build_flag == 0) {
-			retval = ms_build_l2p_tbl(chip, seg_no);
-			if (retval != STATUS_SUCCESS) {
-				chip->card_fail |= MS_CARD;
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-
-		old_blk = ms_get_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no]);
-		if (old_blk == 0xFFFF) {
-			ms_rw_fail(srb, chip);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		if (srb->sc_data_direction == DMA_TO_DEVICE) {
-			new_blk = ms_get_unused_block(chip, seg_no);
-			if (new_blk == 0xFFFF) {
-				ms_rw_fail(srb, chip);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-
-		RTSX_DEBUGP("seg_no = %d, old_blk = 0x%x, new_blk = 0x%x\n", seg_no, old_blk, new_blk);
-
-		start_page = 0;
-	}
-
-	if (srb->sc_data_direction == DMA_TO_DEVICE) {
-		if (end_page < (ms_card->page_off + 1)) {
-#ifdef MS_DELAY_WRITE
-			delay_write->delay_write_flag = 1;
-			delay_write->old_phyblock = old_blk;
-			delay_write->new_phyblock = new_blk;
-			delay_write->logblock = log_blk;
-			delay_write->pageoff = end_page;
-#else
-			retval = ms_finish_write(chip, old_blk, new_blk, log_blk, end_page);
-			if (retval != STATUS_SUCCESS) {
-				if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
-					set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-					TRACE_RET(chip, STATUS_FAIL);
-				}
-
-				ms_rw_fail(srb, chip);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-#endif
-		}
-	}
-
-	scsi_set_resid(srb, 0);
-
-	return STATUS_SUCCESS;
-}
-
-int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-
-	if (CHK_MSPRO(ms_card))
-		retval = mspro_rw_multi_sector(srb, chip, start_sector, sector_cnt);
-	else
-		retval = ms_rw_multi_sector(srb, chip, start_sector, sector_cnt);
-
-	return retval;
-}
-
-
-void ms_free_l2p_tbl(struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int i = 0;
-
-	if (ms_card->segment != NULL) {
-		for (i = 0; i < ms_card->segment_cnt; i++) {
-			if (ms_card->segment[i].l2p_table != NULL) {
-				vfree(ms_card->segment[i].l2p_table);
-				ms_card->segment[i].l2p_table = NULL;
-			}
-			if (ms_card->segment[i].free_table != NULL) {
-				vfree(ms_card->segment[i].free_table);
-				ms_card->segment[i].free_table = NULL;
-			}
-		}
-		vfree(ms_card->segment);
-		ms_card->segment = NULL;
-	}
-}
-
-#ifdef SUPPORT_MAGIC_GATE
-
-#ifdef READ_BYTES_WAIT_INT
-static int ms_poll_int(struct rtsx_chip *chip)
-{
-	int retval;
-	u8 val;
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANS_CFG, MS_INT_CED, MS_INT_CED);
-
-	retval = rtsx_send_cmd(chip, MS_CARD, 5000);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	val = *rtsx_get_cmd_data(chip);
-	if (val & MS_INT_ERR)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-#endif
-
-#ifdef MS_SAMPLE_INT_ERR
-static int check_ms_err(struct rtsx_chip *chip)
-{
-	int retval;
-	u8 val;
-
-	retval = rtsx_read_register(chip, MS_TRANSFER, &val);
-	if (retval != STATUS_SUCCESS)
-		return 1;
-	if (val & MS_TRANSFER_ERR)
-		return 1;
-
-	retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
-	if (retval != STATUS_SUCCESS)
-		return 1;
-
-	if (val & (MS_INT_ERR | MS_INT_CMDNK))
-		return 1;
-
-	return 0;
-}
-#else
-static int check_ms_err(struct rtsx_chip *chip)
-{
-	int retval;
-	u8 val;
-
-	retval = rtsx_read_register(chip, MS_TRANSFER, &val);
-	if (retval != STATUS_SUCCESS)
-		return 1;
-	if (val & MS_TRANSFER_ERR)
-		return 1;
-
-	return 0;
-}
-#endif
-
-static int mg_send_ex_cmd(struct rtsx_chip *chip, u8 cmd, u8 entry_num)
-{
-	int retval, i;
-	u8 data[8];
-
-	data[0] = cmd;
-	data[1] = 0;
-	data[2] = 0;
-	data[3] = 0;
-	data[4] = 0;
-	data[5] = 0;
-	data[6] = entry_num;
-	data[7] = 0;
-
-	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
-		retval = ms_write_bytes(chip, PRO_EX_SET_CMD, 7, WAIT_INT, data, 8);
-		if (retval == STATUS_SUCCESS)
-			break;
-	}
-	if (i == MS_MAX_RETRY_COUNT)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (check_ms_err(chip)) {
-		rtsx_clear_ms_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int mg_set_tpc_para_sub(struct rtsx_chip *chip, int type, u8 mg_entry_num)
-{
-	int retval;
-	u8 buf[6];
-
-	RTSX_DEBUGP("--%s--\n", __func__);
-
-	if (type == 0)
-		retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_TPCParm, 1);
-	else
-		retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6);
-
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	buf[0] = 0;
-	buf[1] = 0;
-	if (type == 1) {
-		buf[2] = 0;
-		buf[3] = 0;
-		buf[4] = 0;
-		buf[5] = mg_entry_num;
-	}
-	retval = ms_write_bytes(chip, PRO_WRITE_REG, (type == 0) ? 1 : 6, NO_WAIT_INT, buf, 6);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int retval;
-	int i;
-	unsigned int lun = SCSI_LUN(srb);
-	u8 buf1[32], buf2[12];
-
-	RTSX_DEBUGP("--%s--\n", __func__);
-
-	if (scsi_bufflen(srb) < 12) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	ms_cleanup_work(chip);
-
-	retval = ms_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = mg_send_ex_cmd(chip, MG_SET_LID, 0);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	memset(buf1, 0, 32);
-	rtsx_stor_get_xfer_buf(buf2, min(12, (int)scsi_bufflen(srb)), srb);
-	for (i = 0; i < 8; i++)
-		buf1[8+i] = buf2[4+i];
-
-	retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf1, 32);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-	if (check_ms_err(chip)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
-		rtsx_clear_ms_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int retval = STATUS_FAIL;
-	int bufflen;
-	unsigned int lun = SCSI_LUN(srb);
-	u8 *buf = NULL;
-
-	RTSX_DEBUGP("--%s--\n", __func__);
-
-	ms_cleanup_work(chip);
-
-	retval = ms_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	buf = kmalloc(1540, GFP_KERNEL);
-	if (!buf)
-		TRACE_RET(chip, STATUS_ERROR);
-
-	buf[0] = 0x04;
-	buf[1] = 0x1A;
-	buf[2] = 0x00;
-	buf[3] = 0x00;
-
-	retval = mg_send_ex_cmd(chip, MG_GET_LEKB, 0);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
-		TRACE_GOTO(chip, GetEKBFinish);
-	}
-
-	retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
-				3, WAIT_INT, 0, 0, buf + 4, 1536);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
-		rtsx_clear_ms_error(chip);
-		TRACE_GOTO(chip, GetEKBFinish);
-	}
-	if (check_ms_err(chip)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
-		rtsx_clear_ms_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	bufflen = min(1052, (int)scsi_bufflen(srb));
-	rtsx_stor_set_xfer_buf(buf, bufflen, srb);
-
-GetEKBFinish:
-	kfree(buf);
-	return retval;
-}
-
-int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-	int bufflen;
-	int i;
-	unsigned int lun = SCSI_LUN(srb);
-	u8 buf[32];
-
-	RTSX_DEBUGP("--%s--\n", __func__);
-
-	ms_cleanup_work(chip);
-
-	retval = ms_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = mg_send_ex_cmd(chip, MG_GET_ID, 0);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, buf, 32);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-	if (check_ms_err(chip)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
-		rtsx_clear_ms_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	memcpy(ms_card->magic_gate_id, buf, 16);
-
-#ifdef READ_BYTES_WAIT_INT
-	retval = ms_poll_int(chip);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-#endif
-
-	retval = mg_send_ex_cmd(chip, MG_SET_RD, 0);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	bufflen = min(12, (int)scsi_bufflen(srb));
-	rtsx_stor_get_xfer_buf(buf, bufflen, srb);
-
-	for (i = 0; i < 8; i++)
-		buf[i] = buf[4+i];
-
-	for (i = 0; i < 24; i++)
-		buf[8+i] = 0;
-
-	retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA,
-				32, WAIT_INT, buf, 32);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-	if (check_ms_err(chip)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
-		rtsx_clear_ms_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	ms_card->mg_auth = 0;
-
-	return STATUS_SUCCESS;
-}
-
-int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-	int bufflen;
-	unsigned int lun = SCSI_LUN(srb);
-	u8 buf1[32], buf2[36];
-
-	RTSX_DEBUGP("--%s--\n", __func__);
-
-	ms_cleanup_work(chip);
-
-	retval = ms_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = mg_send_ex_cmd(chip, MG_MAKE_RMS, 0);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, buf1, 32);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-	if (check_ms_err(chip)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
-		rtsx_clear_ms_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	buf2[0] = 0x00;
-	buf2[1] = 0x22;
-	buf2[2] = 0x00;
-	buf2[3] = 0x00;
-
-	memcpy(buf2 + 4, ms_card->magic_gate_id, 16);
-	memcpy(buf2 + 20, buf1, 16);
-
-	bufflen = min(36, (int)scsi_bufflen(srb));
-	rtsx_stor_set_xfer_buf(buf2, bufflen, srb);
-
-#ifdef READ_BYTES_WAIT_INT
-	retval = ms_poll_int(chip);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-#endif
-
-	return STATUS_SUCCESS;
-}
-
-int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-	int i;
-	int bufflen;
-	unsigned int lun = SCSI_LUN(srb);
-	u8 buf[32];
-
-	RTSX_DEBUGP("--%s--\n", __func__);
-
-	ms_cleanup_work(chip);
-
-	retval = ms_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = mg_send_ex_cmd(chip, MG_MAKE_KSE, 0);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	bufflen = min(12, (int)scsi_bufflen(srb));
-	rtsx_stor_get_xfer_buf(buf, bufflen, srb);
-
-	for (i = 0; i < 8; i++)
-		buf[i] = buf[4+i];
-
-	for (i = 0; i < 24; i++)
-		buf[8+i] = 0;
-
-	retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf, 32);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-	if (check_ms_err(chip)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
-		rtsx_clear_ms_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	ms_card->mg_auth = 1;
-
-	return STATUS_SUCCESS;
-}
-
-int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-	int bufflen;
-	unsigned int lun = SCSI_LUN(srb);
-	u8 *buf = NULL;
-
-	RTSX_DEBUGP("--%s--\n", __func__);
-
-	ms_cleanup_work(chip);
-
-	retval = ms_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	buf = kmalloc(1028, GFP_KERNEL);
-	if (!buf)
-		TRACE_RET(chip, STATUS_ERROR);
-
-	buf[0] = 0x04;
-	buf[1] = 0x02;
-	buf[2] = 0x00;
-	buf[3] = 0x00;
-
-	retval = mg_send_ex_cmd(chip, MG_GET_IBD, ms_card->mg_entry_num);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-		TRACE_GOTO(chip, GetICVFinish);
-	}
-
-	retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
-				2, WAIT_INT, 0, 0, buf + 4, 1024);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-		rtsx_clear_ms_error(chip);
-		TRACE_GOTO(chip, GetICVFinish);
-	}
-	if (check_ms_err(chip)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-		rtsx_clear_ms_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	bufflen = min(1028, (int)scsi_bufflen(srb));
-	rtsx_stor_set_xfer_buf(buf, bufflen, srb);
-
-GetICVFinish:
-	kfree(buf);
-	return retval;
-}
-
-int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-	int bufflen;
-#ifdef MG_SET_ICV_SLOW
-	int i;
-#endif
-	unsigned int lun = SCSI_LUN(srb);
-	u8 *buf = NULL;
-
-	RTSX_DEBUGP("--%s--\n", __func__);
-
-	ms_cleanup_work(chip);
-
-	retval = ms_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	buf = kmalloc(1028, GFP_KERNEL);
-	if (!buf)
-		TRACE_RET(chip, STATUS_ERROR);
-
-	bufflen = min(1028, (int)scsi_bufflen(srb));
-	rtsx_stor_get_xfer_buf(buf, bufflen, srb);
-
-	retval = mg_send_ex_cmd(chip, MG_SET_IBD, ms_card->mg_entry_num);
-	if (retval != STATUS_SUCCESS) {
-		if (ms_card->mg_auth == 0) {
-			if ((buf[5] & 0xC0) != 0)
-				set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
-			else
-				set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
-		} else {
-			set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
-		}
-		TRACE_GOTO(chip, SetICVFinish);
-	}
-
-#ifdef MG_SET_ICV_SLOW
-	for (i = 0; i < 2; i++) {
-		udelay(50);
-
-		rtsx_init_cmd(chip);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, PRO_WRITE_LONG_DATA);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, WAIT_INT);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-
-		trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
-				MS_TRANSFER_START |  MS_TM_NORMAL_WRITE);
-		rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
-
-		rtsx_send_cmd_no_wait(chip);
-
-		retval = rtsx_transfer_data(chip, MS_CARD, buf + 4 + i*512, 512, 0, DMA_TO_DEVICE, 3000);
-		if ((retval < 0) || check_ms_err(chip)) {
-			rtsx_clear_ms_error(chip);
-			if (ms_card->mg_auth == 0) {
-				if ((buf[5] & 0xC0) != 0)
-					set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
-				else
-					set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
-			} else {
-				set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
-			}
-			retval = STATUS_FAIL;
-			TRACE_GOTO(chip, SetICVFinish);
-		}
-	}
-#else
-	retval = ms_transfer_data(chip, MS_TM_AUTO_WRITE, PRO_WRITE_LONG_DATA,
-				2, WAIT_INT, 0, 0, buf + 4, 1024);
-	if ((retval != STATUS_SUCCESS) || check_ms_err(chip)) {
-		rtsx_clear_ms_error(chip);
-		if (ms_card->mg_auth == 0) {
-			if ((buf[5] & 0xC0) != 0)
-				set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
-			else
-				set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
-		} else {
-			set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
-		}
-		TRACE_GOTO(chip, SetICVFinish);
-	}
-#endif
-
-SetICVFinish:
-	kfree(buf);
-	return retval;
-}
-
-#endif /* SUPPORT_MAGIC_GATE */
-
-void ms_cleanup_work(struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-
-	if (CHK_MSPRO(ms_card)) {
-		if (ms_card->seq_mode) {
-			RTSX_DEBUGP("MS Pro: stop transmission\n");
-			mspro_stop_seq_mode(chip);
-			ms_card->cleanup_counter = 0;
-		}
-		if (CHK_MSHG(ms_card)) {
-			rtsx_write_register(chip, MS_CFG,
-				MS_2K_SECTOR_MODE, 0x00);
-		}
-	}
-#ifdef MS_DELAY_WRITE
-	else if ((!CHK_MSPRO(ms_card)) && ms_card->delay_write.delay_write_flag) {
-		RTSX_DEBUGP("MS: delay write\n");
-		ms_delay_write(chip);
-		ms_card->cleanup_counter = 0;
-	}
-#endif
-}
-
-int ms_power_off_card3v3(struct rtsx_chip *chip)
-{
-	int retval;
-
-	retval = disable_card_clock(chip, MS_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (chip->asic_code) {
-		retval = ms_pull_ctl_disable(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	} else {
-		RTSX_WRITE_REG(chip, FPGA_PULL_CTL,
-			FPGA_MS_PULL_CTL_BIT | 0x20, FPGA_MS_PULL_CTL_BIT);
-	}
-	RTSX_WRITE_REG(chip, CARD_OE, MS_OUTPUT_EN, 0);
-	if (!chip->ft2_fast_mode) {
-		retval = card_power_off(chip, MS_CARD);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int release_ms_card(struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-
-	RTSX_DEBUGP("release_ms_card\n");
-
-#ifdef MS_DELAY_WRITE
-	ms_card->delay_write.delay_write_flag = 0;
-#endif
-	ms_card->pro_under_formatting = 0;
-
-	chip->card_ready &= ~MS_CARD;
-	chip->card_fail &= ~MS_CARD;
-	chip->card_wp &= ~MS_CARD;
-
-	ms_free_l2p_tbl(chip);
-
-	memset(ms_card->raw_sys_info, 0, 96);
-#ifdef SUPPORT_PCGL_1P18
-	memset(ms_card->raw_model_name, 0, 48);
-#endif
-
-	retval = ms_power_off_card3v3(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
diff --git a/drivers/staging/rts_pstor/ms.h b/drivers/staging/rts_pstor/ms.h
deleted file mode 100644
index 5370198..0000000
--- a/drivers/staging/rts_pstor/ms.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- * Header file
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#ifndef __REALTEK_RTSX_MS_H
-#define __REALTEK_RTSX_MS_H
-
-#define MS_DELAY_WRITE
-
-#define	MS_MAX_RETRY_COUNT	3
-
-#define	MS_EXTRA_SIZE		0x9
-
-#define	WRT_PRTCT		0x01
-
-/* Error Code */
-#define	MS_NO_ERROR				0x00
-#define	MS_CRC16_ERROR				0x80
-#define	MS_TO_ERROR				0x40
-#define	MS_NO_CARD				0x20
-#define	MS_NO_MEMORY				0x10
-#define	MS_CMD_NK				0x08
-#define	MS_FLASH_READ_ERROR			0x04
-#define	MS_FLASH_WRITE_ERROR			0x02
-#define	MS_BREQ_ERROR				0x01
-#define	MS_NOT_FOUND				0x03
-
-/* Transfer Protocol Command */
-#define READ_PAGE_DATA				0x02
-#define READ_REG				0x04
-#define	GET_INT					0x07
-#define WRITE_PAGE_DATA				0x0D
-#define WRITE_REG				0x0B
-#define SET_RW_REG_ADRS				0x08
-#define SET_CMD					0x0E
-
-#define	PRO_READ_LONG_DATA			0x02
-#define	PRO_READ_SHORT_DATA			0x03
-#define PRO_READ_REG				0x04
-#define	PRO_READ_QUAD_DATA			0x05
-#define PRO_GET_INT				0x07
-#define	PRO_WRITE_LONG_DATA			0x0D
-#define	PRO_WRITE_SHORT_DATA			0x0C
-#define	PRO_WRITE_QUAD_DATA			0x0A
-#define PRO_WRITE_REG				0x0B
-#define PRO_SET_RW_REG_ADRS			0x08
-#define PRO_SET_CMD				0x0E
-#define PRO_EX_SET_CMD				0x09
-
-#ifdef SUPPORT_MAGIC_GATE
-
-#define MG_GET_ID		0x40
-#define MG_SET_LID		0x41
-#define MG_GET_LEKB		0x42
-#define MG_SET_RD		0x43
-#define MG_MAKE_RMS		0x44
-#define MG_MAKE_KSE		0x45
-#define MG_SET_IBD		0x46
-#define MG_GET_IBD		0x47
-
-#endif
-
-#ifdef XC_POWERCLASS
-#define XC_CHG_POWER		0x16
-#endif
-
-#define BLOCK_READ	0xAA
-#define	BLOCK_WRITE	0x55
-#define BLOCK_END	0x33
-#define BLOCK_ERASE	0x99
-#define FLASH_STOP	0xCC
-
-#define SLEEP		0x5A
-#define CLEAR_BUF	0xC3
-#define MS_RESET	0x3C
-
-#define PRO_READ_DATA		0x20
-#define	PRO_WRITE_DATA		0x21
-#define PRO_READ_ATRB		0x24
-#define PRO_STOP		0x25
-#define PRO_ERASE		0x26
-#define	PRO_READ_2K_DATA	0x27
-#define	PRO_WRITE_2K_DATA	0x28
-
-#define PRO_FORMAT		0x10
-#define PRO_SLEEP		0x11
-
-#define	IntReg			0x01
-#define StatusReg0		0x02
-#define StatusReg1		0x03
-
-#define SystemParm		0x10
-#define BlockAdrs		0x11
-#define CMDParm			0x14
-#define PageAdrs		0x15
-
-#define OverwriteFlag		0x16
-#define ManagemenFlag		0x17
-#define LogicalAdrs		0x18
-#define ReserveArea		0x1A
-
-#define	Pro_IntReg		0x01
-#define Pro_StatusReg		0x02
-#define Pro_TypeReg		0x04
-#define	Pro_IFModeReg		0x05
-#define Pro_CatagoryReg		0x06
-#define Pro_ClassReg		0x07
-
-
-#define Pro_SystemParm		0x10
-#define Pro_DataCount1		0x11
-#define Pro_DataCount0		0x12
-#define Pro_DataAddr3		0x13
-#define Pro_DataAddr2		0x14
-#define Pro_DataAddr1		0x15
-#define Pro_DataAddr0		0x16
-
-#define Pro_TPCParm		0x17
-#define Pro_CMDParm		0x18
-
-#define	INT_REG_CED		0x80
-#define	INT_REG_ERR		0x40
-#define	INT_REG_BREQ		0x20
-#define	INT_REG_CMDNK		0x01
-
-#define	BLOCK_BOOT		0xC0
-#define	BLOCK_OK		0x80
-#define	PAGE_OK			0x60
-#define	DATA_COMPL		0x10
-
-#define	NOT_BOOT_BLOCK		0x4
-#define	NOT_TRANSLATION_TABLE	0x8
-
-#define	HEADER_ID0		PPBUF_BASE2
-#define	HEADER_ID1		(PPBUF_BASE2 + 1)
-#define	DISABLED_BLOCK0		(PPBUF_BASE2 + 0x170 + 4)
-#define	DISABLED_BLOCK1		(PPBUF_BASE2 + 0x170 + 5)
-#define	DISABLED_BLOCK2		(PPBUF_BASE2 + 0x170 + 6)
-#define	DISABLED_BLOCK3		(PPBUF_BASE2 + 0x170 + 7)
-#define	BLOCK_SIZE_0		(PPBUF_BASE2 + 0x1a0 + 2)
-#define	BLOCK_SIZE_1		(PPBUF_BASE2 + 0x1a0 + 3)
-#define	BLOCK_COUNT_0		(PPBUF_BASE2 + 0x1a0 + 4)
-#define	BLOCK_COUNT_1		(PPBUF_BASE2 + 0x1a0 + 5)
-#define	EBLOCK_COUNT_0		(PPBUF_BASE2 + 0x1a0 + 6)
-#define	EBLOCK_COUNT_1		(PPBUF_BASE2 + 0x1a0 + 7)
-#define	PAGE_SIZE_0		(PPBUF_BASE2 + 0x1a0 + 8)
-#define	PAGE_SIZE_1		(PPBUF_BASE2 + 0x1a0 + 9)
-
-#define MS_Device_Type		(PPBUF_BASE2 + 0x1D8)
-
-#define	MS_4bit_Support		(PPBUF_BASE2 + 0x1D3)
-
-#define setPS_NG	1
-#define setPS_Error	0
-
-#define	PARALLEL_8BIT_IF	0x40
-#define	PARALLEL_4BIT_IF	0x00
-#define	SERIAL_IF		0x80
-
-#define BUF_FULL	0x10
-#define BUF_EMPTY	0x20
-
-#define	MEDIA_BUSY	0x80
-#define	FLASH_BUSY	0x40
-#define	DATA_ERROR	0x20
-#define	STS_UCDT	0x10
-#define	EXTRA_ERROR	0x08
-#define	STS_UCEX	0x04
-#define	FLAG_ERROR	0x02
-#define	STS_UCFG	0x01
-
-#define MS_SHORT_DATA_LEN	32
-
-#define FORMAT_SUCCESS		0
-#define FORMAT_FAIL		1
-#define FORMAT_IN_PROGRESS	2
-
-#define	MS_SET_BAD_BLOCK_FLG(ms_card)	((ms_card)->multi_flag |= 0x80)
-#define MS_CLR_BAD_BLOCK_FLG(ms_card)	((ms_card)->multi_flag &= 0x7F)
-#define MS_TST_BAD_BLOCK_FLG(ms_card)	((ms_card)->multi_flag & 0x80)
-
-void mspro_polling_format_status(struct rtsx_chip *chip);
-
-void mspro_stop_seq_mode(struct rtsx_chip *chip);
-int reset_ms_card(struct rtsx_chip *chip);
-int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt);
-int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip, int short_data_len, int quick_format);
-void ms_free_l2p_tbl(struct rtsx_chip *chip);
-void ms_cleanup_work(struct rtsx_chip *chip);
-int ms_power_off_card3v3(struct rtsx_chip *chip);
-int release_ms_card(struct rtsx_chip *chip);
-#ifdef MS_DELAY_WRITE
-int ms_delay_write(struct rtsx_chip *chip);
-#endif
-
-#ifdef SUPPORT_MAGIC_GATE
-int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-#endif
-
-#endif  /* __REALTEK_RTSX_MS_H */
diff --git a/drivers/staging/rts_pstor/rtsx.c b/drivers/staging/rts_pstor/rtsx.c
deleted file mode 100644
index afe9c2e..0000000
--- a/drivers/staging/rts_pstor/rtsx.c
+++ /dev/null
@@ -1,1105 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-
-#include "rtsx.h"
-#include "rtsx_chip.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
-#include "general.h"
-
-#include "ms.h"
-#include "sd.h"
-#include "xd.h"
-
-#define DRIVER_VERSION "v1.10"
-
-MODULE_DESCRIPTION("Realtek PCI-Express card reader driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRIVER_VERSION);
-
-static unsigned int delay_use = 1;
-module_param(delay_use, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
-
-static int ss_en;
-module_param(ss_en, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(ss_en, "enable selective suspend");
-
-static int ss_interval = 50;
-module_param(ss_interval, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(ss_interval, "Interval to enter ss state in seconds");
-
-static int auto_delink_en;
-module_param(auto_delink_en, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(auto_delink_en, "enable auto delink");
-
-static unsigned char aspm_l0s_l1_en;
-module_param(aspm_l0s_l1_en, byte, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(aspm_l0s_l1_en, "enable device aspm");
-
-static int msi_en;
-module_param(msi_en, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(msi_en, "enable msi");
-
-static irqreturn_t rtsx_interrupt(int irq, void *dev_id);
-
-/***********************************************************************
- * Host functions
- ***********************************************************************/
-
-static const char *host_info(struct Scsi_Host *host)
-{
-	return "SCSI emulation for PCI-Express Mass Storage devices";
-}
-
-static int slave_alloc(struct scsi_device *sdev)
-{
-	/*
-	 * Set the INQUIRY transfer length to 36.  We don't use any of
-	 * the extra data and many devices choke if asked for more or
-	 * less than 36 bytes.
-	 */
-	sdev->inquiry_len = 36;
-	return 0;
-}
-
-static int slave_configure(struct scsi_device *sdev)
-{
-	/* Scatter-gather buffers (all but the last) must have a length
-	 * divisible by the bulk maxpacket size.  Otherwise a data packet
-	 * would end up being short, causing a premature end to the data
-	 * transfer.  Since high-speed bulk pipes have a maxpacket size
-	 * of 512, we'll use that as the scsi device queue's DMA alignment
-	 * mask.  Guaranteeing proper alignment of the first buffer will
-	 * have the desired effect because, except at the beginning and
-	 * the end, scatter-gather buffers follow page boundaries. */
-	blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
-
-	/* Set the SCSI level to at least 2.  We'll leave it at 3 if that's
-	 * what is originally reported.  We need this to avoid confusing
-	 * the SCSI layer with devices that report 0 or 1, but need 10-byte
-	 * commands (ala ATAPI devices behind certain bridges, or devices
-	 * which simply have broken INQUIRY data).
-	 *
-	 * NOTE: This means /dev/sg programs (ala cdrecord) will get the
-	 * actual information.  This seems to be the preference for
-	 * programs like that.
-	 *
-	 * NOTE: This also means that /proc/scsi/scsi and sysfs may report
-	 * the actual value or the modified one, depending on where the
-	 * data comes from.
-	 */
-	if (sdev->scsi_level < SCSI_2)
-		sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2;
-
-	return 0;
-}
-
-
-/***********************************************************************
- * /proc/scsi/ functions
- ***********************************************************************/
-
-/* we use this macro to help us write into the buffer */
-#undef SPRINTF
-#define SPRINTF(args...) \
-	do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
-
-static int proc_info(struct Scsi_Host *host, char *buffer,
-		char **start, off_t offset, int length, int inout)
-{
-	char *pos = buffer;
-
-	/* if someone is sending us data, just throw it away */
-	if (inout)
-		return length;
-
-	/* print the controller name */
-	SPRINTF("   Host scsi%d: %s\n", host->host_no, CR_DRIVER_NAME);
-
-	/* print product, vendor, and driver version strings */
-	SPRINTF("       Vendor: Realtek Corp.\n");
-	SPRINTF("      Product: PCIE Card Reader\n");
-	SPRINTF("      Version: %s\n", DRIVER_VERSION);
-
-	/*
-	 * Calculate start of next buffer, and return value.
-	 */
-	*start = buffer + offset;
-
-	if ((pos - buffer) < offset)
-		return 0;
-	else if ((pos - buffer - offset) < length)
-		return pos - buffer - offset;
-	else
-		return length;
-}
-
-/* queue a command */
-/* This is always called with scsi_lock(host) held */
-static int queuecommand_lck(struct scsi_cmnd *srb,
-			void (*done)(struct scsi_cmnd *))
-{
-	struct rtsx_dev *dev = host_to_rtsx(srb->device->host);
-	struct rtsx_chip *chip = dev->chip;
-
-	/* check for state-transition errors */
-	if (chip->srb != NULL) {
-		dev_err(&dev->pci->dev, "Error in %s: chip->srb = %p\n",
-			__func__, chip->srb);
-		return SCSI_MLQUEUE_HOST_BUSY;
-	}
-
-	/* fail the command if we are disconnecting */
-	if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) {
-		dev_info(&dev->pci->dev, "Fail command during disconnect\n");
-		srb->result = DID_NO_CONNECT << 16;
-		done(srb);
-		return 0;
-	}
-
-	/* enqueue the command and wake up the control thread */
-	srb->scsi_done = done;
-	chip->srb = srb;
-	complete(&dev->cmnd_ready);
-
-	return 0;
-}
-
-static DEF_SCSI_QCMD(queuecommand)
-
-/***********************************************************************
- * Error handling functions
- ***********************************************************************/
-
-/* Command timeout and abort */
-static int command_abort(struct scsi_cmnd *srb)
-{
-	struct Scsi_Host *host = srb->device->host;
-	struct rtsx_dev *dev = host_to_rtsx(host);
-	struct rtsx_chip *chip = dev->chip;
-
-	dev_info(&dev->pci->dev, "%s called\n", __func__);
-
-	scsi_lock(host);
-
-	/* Is this command still active? */
-	if (chip->srb != srb) {
-		scsi_unlock(host);
-		dev_info(&dev->pci->dev, "-- nothing to abort\n");
-		return FAILED;
-	}
-
-	rtsx_set_stat(chip, RTSX_STAT_ABORT);
-
-	scsi_unlock(host);
-
-	/* Wait for the aborted command to finish */
-	wait_for_completion(&dev->notify);
-
-	return SUCCESS;
-}
-
-/* This invokes the transport reset mechanism to reset the state of the
- * device */
-static int device_reset(struct scsi_cmnd *srb)
-{
-	int result = 0;
-	struct rtsx_dev *dev = host_to_rtsx(srb->device->host);
-
-	dev_info(&dev->pci->dev, "%s called\n", __func__);
-
-	return result < 0 ? FAILED : SUCCESS;
-}
-
-/* Simulate a SCSI bus reset by resetting the device's USB port. */
-static int bus_reset(struct scsi_cmnd *srb)
-{
-	int result = 0;
-	struct rtsx_dev *dev = host_to_rtsx(srb->device->host);
-
-	dev_info(&dev->pci->dev, "%s called\n", __func__);
-
-	return result < 0 ? FAILED : SUCCESS;
-}
-
-
-/*
- * this defines our host template, with which we'll allocate hosts
- */
-
-static struct scsi_host_template rtsx_host_template = {
-	/* basic userland interface stuff */
-	.name =				CR_DRIVER_NAME,
-	.proc_name =			CR_DRIVER_NAME,
-	.proc_info =			proc_info,
-	.info =				host_info,
-
-	/* command interface -- queued only */
-	.queuecommand =			queuecommand,
-
-	/* error and abort handlers */
-	.eh_abort_handler =		command_abort,
-	.eh_device_reset_handler =	device_reset,
-	.eh_bus_reset_handler =		bus_reset,
-
-	/* queue commands only, only one command per LUN */
-	.can_queue =			1,
-	.cmd_per_lun =			1,
-
-	/* unknown initiator id */
-	.this_id =			-1,
-
-	.slave_alloc =			slave_alloc,
-	.slave_configure =		slave_configure,
-
-	/* lots of sg segments can be handled */
-	.sg_tablesize =			SG_ALL,
-
-	/* limit the total size of a transfer to 120 KB */
-	.max_sectors =                  240,
-
-	/* merge commands... this seems to help performance, but
-	 * periodically someone should test to see which setting is more
-	 * optimal.
-	 */
-	.use_clustering =		1,
-
-	/* emulated HBA */
-	.emulated =			1,
-
-	/* we do our own delay after a device or bus reset */
-	.skip_settle_delay =		1,
-
-	/* module management */
-	.module =			THIS_MODULE
-};
-
-
-static int rtsx_acquire_irq(struct rtsx_dev *dev)
-{
-	struct rtsx_chip *chip = dev->chip;
-
-	dev_info(&dev->pci->dev, "%s: chip->msi_en = %d, pci->irq = %d\n",
-		 __func__, chip->msi_en, dev->pci->irq);
-
-	if (request_irq(dev->pci->irq, rtsx_interrupt,
-			chip->msi_en ? 0 : IRQF_SHARED,
-			CR_DRIVER_NAME, dev)) {
-		dev_err(&dev->pci->dev,
-			"rtsx: unable to grab IRQ %d, disabling device\n",
-			dev->pci->irq);
-		return -1;
-	}
-
-	dev->irq = dev->pci->irq;
-	pci_intx(dev->pci, !chip->msi_en);
-
-	return 0;
-}
-
-
-int rtsx_read_pci_cfg_byte(u8 bus, u8 dev, u8 func, u8 offset, u8 *val)
-{
-	struct pci_dev *pdev;
-	u8 data;
-	u8 devfn = (dev << 3) | func;
-
-	pdev = pci_get_bus_and_slot(bus, devfn);
-	if (!pdev)
-		return -1;
-
-	pci_read_config_byte(pdev, offset, &data);
-	if (val)
-		*val = data;
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-/*
- * power management
- */
-static int rtsx_suspend(struct pci_dev *pci, pm_message_t state)
-{
-	struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci);
-	struct rtsx_chip *chip;
-
-	if (!dev)
-		return 0;
-
-	/* lock the device pointers */
-	mutex_lock(&(dev->dev_mutex));
-
-	chip = dev->chip;
-
-	rtsx_do_before_power_down(chip, PM_S3);
-
-	if (dev->irq >= 0) {
-		synchronize_irq(dev->irq);
-		free_irq(dev->irq, (void *)dev);
-		dev->irq = -1;
-	}
-
-	if (chip->msi_en)
-		pci_disable_msi(pci);
-
-	pci_save_state(pci);
-	pci_enable_wake(pci, pci_choose_state(pci, state), 1);
-	pci_disable_device(pci);
-	pci_set_power_state(pci, pci_choose_state(pci, state));
-
-	/* unlock the device pointers */
-	mutex_unlock(&dev->dev_mutex);
-
-	return 0;
-}
-
-static int rtsx_resume(struct pci_dev *pci)
-{
-	struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci);
-	struct rtsx_chip *chip;
-
-	if (!dev)
-		return 0;
-
-	chip = dev->chip;
-
-	/* lock the device pointers */
-	mutex_lock(&(dev->dev_mutex));
-
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(&dev->pci->dev,
-			"%s: pci_enable_device failed, disabling device\n",
-			CR_DRIVER_NAME);
-		/* unlock the device pointers */
-		mutex_unlock(&dev->dev_mutex);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
-	if (chip->msi_en) {
-		if (pci_enable_msi(pci) < 0)
-			chip->msi_en = 0;
-	}
-
-	if (rtsx_acquire_irq(dev) < 0) {
-		/* unlock the device pointers */
-		mutex_unlock(&dev->dev_mutex);
-		return -EIO;
-	}
-
-	rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 0x00);
-	rtsx_init_chip(chip);
-
-	/* unlock the device pointers */
-	mutex_unlock(&dev->dev_mutex);
-
-	return 0;
-}
-#endif /* CONFIG_PM */
-
-static void rtsx_shutdown(struct pci_dev *pci)
-{
-	struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci);
-	struct rtsx_chip *chip;
-
-	if (!dev)
-		return;
-
-	chip = dev->chip;
-
-	rtsx_do_before_power_down(chip, PM_S1);
-
-	if (dev->irq >= 0) {
-		synchronize_irq(dev->irq);
-		free_irq(dev->irq, (void *)dev);
-		dev->irq = -1;
-	}
-
-	if (chip->msi_en)
-		pci_disable_msi(pci);
-
-	pci_disable_device(pci);
-
-	return;
-}
-
-static int rtsx_control_thread(void *__dev)
-{
-	struct rtsx_dev *dev = (struct rtsx_dev *)__dev;
-	struct rtsx_chip *chip = dev->chip;
-	struct Scsi_Host *host = rtsx_to_host(dev);
-
-	for (;;) {
-		if (wait_for_completion_interruptible(&dev->cmnd_ready))
-			break;
-
-		/* lock the device pointers */
-		mutex_lock(&(dev->dev_mutex));
-
-		/* if the device has disconnected, we are free to exit */
-		if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) {
-			dev_info(&dev->pci->dev, "-- rtsx-control exiting\n");
-			mutex_unlock(&dev->dev_mutex);
-			break;
-		}
-
-		/* lock access to the state */
-		scsi_lock(host);
-
-		/* has the command aborted ? */
-		if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) {
-			chip->srb->result = DID_ABORT << 16;
-			goto SkipForAbort;
-		}
-
-		scsi_unlock(host);
-
-		/* reject the command if the direction indicator
-		 * is UNKNOWN
-		 */
-		if (chip->srb->sc_data_direction == DMA_BIDIRECTIONAL) {
-			dev_err(&dev->pci->dev, "UNKNOWN data direction\n");
-			chip->srb->result = DID_ERROR << 16;
-		}
-
-		/* reject if target != 0 or if LUN is higher than
-		 * the maximum known LUN
-		 */
-		else if (chip->srb->device->id) {
-			dev_err(&dev->pci->dev, "Bad target number (%d:%d)\n",
-				chip->srb->device->id,
-				chip->srb->device->lun);
-			chip->srb->result = DID_BAD_TARGET << 16;
-		}
-
-		else if (chip->srb->device->lun > chip->max_lun) {
-			dev_err(&dev->pci->dev, "Bad LUN (%d:%d)\n",
-				chip->srb->device->id,
-				chip->srb->device->lun);
-			chip->srb->result = DID_BAD_TARGET << 16;
-		}
-
-		/* we've got a command, let's do it! */
-		else {
-			RTSX_DEBUG(scsi_show_command(chip->srb));
-			rtsx_invoke_transport(chip->srb, chip);
-		}
-
-		/* lock access to the state */
-		scsi_lock(host);
-
-		/* did the command already complete because of a disconnect? */
-		if (!chip->srb)
-			;		/* nothing to do */
-
-		/* indicate that the command is done */
-		else if (chip->srb->result != DID_ABORT << 16) {
-			chip->srb->scsi_done(chip->srb);
-		} else {
-SkipForAbort:
-			dev_err(&dev->pci->dev, "scsi command aborted\n");
-		}
-
-		if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) {
-			complete(&(dev->notify));
-
-			rtsx_set_stat(chip, RTSX_STAT_IDLE);
-		}
-
-		/* finished working on this command */
-		chip->srb = NULL;
-		scsi_unlock(host);
-
-		/* unlock the device pointers */
-		mutex_unlock(&dev->dev_mutex);
-	} /* for (;;) */
-
-	/* notify the exit routine that we're actually exiting now
-	 *
-	 * complete()/wait_for_completion() is similar to up()/down(),
-	 * except that complete() is safe in the case where the structure
-	 * is getting deleted in a parallel mode of execution (i.e. just
-	 * after the down() -- that's necessary for the thread-shutdown
-	 * case.
-	 *
-	 * complete_and_exit() goes even further than this -- it is safe in
-	 * the case that the thread of the caller is going away (not just
-	 * the structure) -- this is necessary for the module-remove case.
-	 * This is important in preemption kernels, which transfer the flow
-	 * of execution immediately upon a complete().
-	 */
-	complete_and_exit(&dev->control_exit, 0);
-}
-
-
-static int rtsx_polling_thread(void *__dev)
-{
-	struct rtsx_dev *dev = (struct rtsx_dev *)__dev;
-	struct rtsx_chip *chip = dev->chip;
-	struct sd_info *sd_card = &(chip->sd_card);
-	struct xd_info *xd_card = &(chip->xd_card);
-	struct ms_info *ms_card = &(chip->ms_card);
-
-	sd_card->cleanup_counter = 0;
-	xd_card->cleanup_counter = 0;
-	ms_card->cleanup_counter = 0;
-
-	/* Wait until SCSI scan finished */
-	wait_timeout((delay_use + 5) * 1000);
-
-	for (;;) {
-
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(POLLING_INTERVAL);
-
-		/* lock the device pointers */
-		mutex_lock(&(dev->dev_mutex));
-
-		/* if the device has disconnected, we are free to exit */
-		if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) {
-			dev_info(&dev->pci->dev, "-- rtsx-polling exiting\n");
-			mutex_unlock(&dev->dev_mutex);
-			break;
-		}
-
-		mutex_unlock(&dev->dev_mutex);
-
-		mspro_polling_format_status(chip);
-
-		/* lock the device pointers */
-		mutex_lock(&(dev->dev_mutex));
-
-		rtsx_polling_func(chip);
-
-		/* unlock the device pointers */
-		mutex_unlock(&dev->dev_mutex);
-	}
-
-	complete_and_exit(&dev->polling_exit, 0);
-}
-
-/*
- * interrupt handler
- */
-static irqreturn_t rtsx_interrupt(int irq, void *dev_id)
-{
-	struct rtsx_dev *dev = dev_id;
-	struct rtsx_chip *chip;
-	int retval;
-	u32 status;
-
-	if (dev)
-		chip = dev->chip;
-	else
-		return IRQ_NONE;
-
-	if (!chip)
-		return IRQ_NONE;
-
-	spin_lock(&dev->reg_lock);
-
-	retval = rtsx_pre_handle_interrupt(chip);
-	if (retval == STATUS_FAIL) {
-		spin_unlock(&dev->reg_lock);
-		if (chip->int_reg == 0xFFFFFFFF)
-			return IRQ_HANDLED;
-		else
-			return IRQ_NONE;
-	}
-
-	status = chip->int_reg;
-
-	if (dev->check_card_cd) {
-		if (!(dev->check_card_cd & status)) {
-			/* card not exist, return TRANS_RESULT_FAIL */
-			dev->trans_result = TRANS_RESULT_FAIL;
-			if (dev->done)
-				complete(dev->done);
-			goto Exit;
-		}
-	}
-
-	if (status & (NEED_COMPLETE_INT | DELINK_INT)) {
-		if (status & (TRANS_FAIL_INT | DELINK_INT)) {
-			if (status & DELINK_INT)
-				RTSX_SET_DELINK(chip);
-			dev->trans_result = TRANS_RESULT_FAIL;
-			if (dev->done)
-				complete(dev->done);
-		} else if (status & TRANS_OK_INT) {
-			dev->trans_result = TRANS_RESULT_OK;
-			if (dev->done)
-				complete(dev->done);
-		} else if (status & DATA_DONE_INT) {
-			dev->trans_result = TRANS_NOT_READY;
-			if (dev->done && (dev->trans_state == STATE_TRANS_SG))
-				complete(dev->done);
-		}
-	}
-
-Exit:
-	spin_unlock(&dev->reg_lock);
-	return IRQ_HANDLED;
-}
-
-
-/* Release all our dynamic resources */
-static void rtsx_release_resources(struct rtsx_dev *dev)
-{
-	dev_info(&dev->pci->dev, "-- %s\n", __func__);
-
-	/* Tell the control thread to exit.  The SCSI host must
-	 * already have been removed so it won't try to queue
-	 * any more commands.
-	 */
-	dev_info(&dev->pci->dev, "-- sending exit command to thread\n");
-	complete(&dev->cmnd_ready);
-	if (dev->ctl_thread)
-		wait_for_completion(&dev->control_exit);
-	if (dev->polling_thread)
-		wait_for_completion(&dev->polling_exit);
-
-	wait_timeout(200);
-
-	if (dev->rtsx_resv_buf) {
-		dma_free_coherent(&(dev->pci->dev), RTSX_RESV_BUF_LEN,
-				dev->rtsx_resv_buf, dev->rtsx_resv_buf_addr);
-		dev->chip->host_cmds_ptr = NULL;
-		dev->chip->host_sg_tbl_ptr = NULL;
-	}
-
-	if (dev->irq > 0)
-		free_irq(dev->irq, (void *)dev);
-	if (dev->chip->msi_en)
-		pci_disable_msi(dev->pci);
-	if (dev->remap_addr)
-		iounmap(dev->remap_addr);
-
-	pci_disable_device(dev->pci);
-	pci_release_regions(dev->pci);
-
-	rtsx_release_chip(dev->chip);
-	kfree(dev->chip);
-}
-
-/* First stage of disconnect processing: stop all commands and remove
- * the host */
-static void quiesce_and_remove_host(struct rtsx_dev *dev)
-{
-	struct Scsi_Host *host = rtsx_to_host(dev);
-	struct rtsx_chip *chip = dev->chip;
-
-	/* Prevent new transfers, stop the current command, and
-	 * interrupt a SCSI-scan or device-reset delay */
-	mutex_lock(&dev->dev_mutex);
-	scsi_lock(host);
-	rtsx_set_stat(chip, RTSX_STAT_DISCONNECT);
-	scsi_unlock(host);
-	mutex_unlock(&dev->dev_mutex);
-	wake_up(&dev->delay_wait);
-	wait_for_completion(&dev->scanning_done);
-
-	/* Wait some time to let other threads exist */
-	wait_timeout(100);
-
-	/* queuecommand won't accept any new commands and the control
-	 * thread won't execute a previously-queued command.  If there
-	 * is such a command pending, complete it with an error. */
-	mutex_lock(&dev->dev_mutex);
-	if (chip->srb) {
-		chip->srb->result = DID_NO_CONNECT << 16;
-		scsi_lock(host);
-		chip->srb->scsi_done(dev->chip->srb);
-		chip->srb = NULL;
-		scsi_unlock(host);
-	}
-	mutex_unlock(&dev->dev_mutex);
-
-	/* Now we own no commands so it's safe to remove the SCSI host */
-	scsi_remove_host(host);
-}
-
-/* Second stage of disconnect processing: deallocate all resources */
-static void release_everything(struct rtsx_dev *dev)
-{
-	rtsx_release_resources(dev);
-
-	/* Drop our reference to the host; the SCSI core will free it
-	 * when the refcount becomes 0. */
-	scsi_host_put(rtsx_to_host(dev));
-}
-
-/* Thread to carry out delayed SCSI-device scanning */
-static int rtsx_scan_thread(void *__dev)
-{
-	struct rtsx_dev *dev = (struct rtsx_dev *)__dev;
-	struct rtsx_chip *chip = dev->chip;
-
-	/* Wait for the timeout to expire or for a disconnect */
-	if (delay_use > 0) {
-		dev_info(&dev->pci->dev,
-			 "%s: waiting for device to settle before scanning\n",
-			 CR_DRIVER_NAME);
-		wait_event_interruptible_timeout(dev->delay_wait,
-				rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT),
-				delay_use * HZ);
-	}
-
-	/* If the device is still connected, perform the scanning */
-	if (!rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) {
-		scsi_scan_host(rtsx_to_host(dev));
-		dev_info(&dev->pci->dev, "%s: device scan complete\n",
-			 CR_DRIVER_NAME);
-
-		/* Should we unbind if no devices were detected? */
-	}
-
-	complete_and_exit(&dev->scanning_done, 0);
-}
-
-static void rtsx_init_options(struct rtsx_chip *chip)
-{
-	chip->vendor_id = chip->rtsx->pci->vendor;
-	chip->product_id = chip->rtsx->pci->device;
-	chip->adma_mode = 1;
-	chip->lun_mc = 0;
-	chip->driver_first_load = 1;
-#ifdef HW_AUTO_SWITCH_SD_BUS
-	chip->sdio_in_charge = 0;
-#endif
-
-	chip->mspro_formatter_enable = 1;
-	chip->ignore_sd = 0;
-	chip->use_hw_setting = 0;
-	chip->lun_mode = DEFAULT_SINGLE;
-	chip->auto_delink_en = auto_delink_en;
-	chip->ss_en = ss_en;
-	chip->ss_idle_period = ss_interval * 1000;
-	chip->remote_wakeup_en = 0;
-	chip->aspm_l0s_l1_en = aspm_l0s_l1_en;
-	chip->dynamic_aspm = 1;
-	chip->fpga_sd_sdr104_clk = CLK_200;
-	chip->fpga_sd_ddr50_clk = CLK_100;
-	chip->fpga_sd_sdr50_clk = CLK_100;
-	chip->fpga_sd_hs_clk = CLK_100;
-	chip->fpga_mmc_52m_clk = CLK_80;
-	chip->fpga_ms_hg_clk = CLK_80;
-	chip->fpga_ms_4bit_clk = CLK_80;
-	chip->fpga_ms_1bit_clk = CLK_40;
-	chip->asic_sd_sdr104_clk = 203;
-	chip->asic_sd_sdr50_clk = 98;
-	chip->asic_sd_ddr50_clk = 98;
-	chip->asic_sd_hs_clk = 98;
-	chip->asic_mmc_52m_clk = 98;
-	chip->asic_ms_hg_clk = 117;
-	chip->asic_ms_4bit_clk = 78;
-	chip->asic_ms_1bit_clk = 39;
-	chip->ssc_depth_sd_sdr104 = SSC_DEPTH_2M;
-	chip->ssc_depth_sd_sdr50 = SSC_DEPTH_2M;
-	chip->ssc_depth_sd_ddr50 = SSC_DEPTH_1M;
-	chip->ssc_depth_sd_hs = SSC_DEPTH_1M;
-	chip->ssc_depth_mmc_52m = SSC_DEPTH_1M;
-	chip->ssc_depth_ms_hg = SSC_DEPTH_1M;
-	chip->ssc_depth_ms_4bit = SSC_DEPTH_512K;
-	chip->ssc_depth_low_speed = SSC_DEPTH_512K;
-	chip->ssc_en = 1;
-	chip->sd_speed_prior = 0x01040203;
-	chip->sd_current_prior = 0x00010203;
-	chip->sd_ctl = SD_PUSH_POINT_AUTO |
-		       SD_SAMPLE_POINT_AUTO |
-		       SUPPORT_MMC_DDR_MODE;
-	chip->sd_ddr_tx_phase = 0;
-	chip->mmc_ddr_tx_phase = 1;
-	chip->sd_default_tx_phase = 15;
-	chip->sd_default_rx_phase = 15;
-	chip->pmos_pwr_on_interval = 200;
-	chip->sd_voltage_switch_delay = 1000;
-	chip->ms_power_class_en = 3;
-
-	chip->sd_400mA_ocp_thd = 1;
-	chip->sd_800mA_ocp_thd = 5;
-	chip->ms_ocp_thd = 2;
-
-	chip->card_drive_sel = 0x55;
-	chip->sd30_drive_sel_1v8 = 0x03;
-	chip->sd30_drive_sel_3v3 = 0x01;
-
-	chip->do_delink_before_power_down = 1;
-	chip->auto_power_down = 1;
-	chip->polling_config = 0;
-
-	chip->force_clkreq_0 = 1;
-	chip->ft2_fast_mode = 0;
-
-	chip->sdio_retry_cnt = 1;
-
-	chip->xd_timeout = 2000;
-	chip->sd_timeout = 10000;
-	chip->ms_timeout = 2000;
-	chip->mspro_timeout = 15000;
-
-	chip->power_down_in_ss = 1;
-
-	chip->sdr104_en = 1;
-	chip->sdr50_en = 1;
-	chip->ddr50_en = 1;
-
-	chip->delink_stage1_step = 100;
-	chip->delink_stage2_step = 40;
-	chip->delink_stage3_step = 20;
-
-	chip->auto_delink_in_L1 = 1;
-	chip->blink_led = 1;
-	chip->msi_en = msi_en;
-	chip->hp_watch_bios_hotplug = 0;
-	chip->max_payload = 0;
-	chip->phy_voltage = 0;
-
-	chip->support_ms_8bit = 1;
-	chip->s3_pwr_off_delay = 1000;
-}
-
-static int __devinit rtsx_probe(struct pci_dev *pci,
-				const struct pci_device_id *pci_id)
-{
-	struct Scsi_Host *host;
-	struct rtsx_dev *dev;
-	int err = 0;
-	struct task_struct *th;
-
-	RTSX_DEBUGP("Realtek PCI-E card reader detected\n");
-
-	err = pci_enable_device(pci);
-	if (err < 0) {
-		dev_err(&pci->dev, "PCI enable device failed!\n");
-		return err;
-	}
-
-	err = pci_request_regions(pci, CR_DRIVER_NAME);
-	if (err < 0) {
-		dev_err(&pci->dev, "PCI request regions for %s failed!\n",
-			CR_DRIVER_NAME);
-		pci_disable_device(pci);
-		return err;
-	}
-
-	/*
-	 * Ask the SCSI layer to allocate a host structure, with extra
-	 * space at the end for our private rtsx_dev structure.
-	 */
-	host = scsi_host_alloc(&rtsx_host_template, sizeof(*dev));
-	if (!host) {
-		dev_err(&pci->dev, "Unable to allocate the scsi host\n");
-		pci_release_regions(pci);
-		pci_disable_device(pci);
-		return -ENOMEM;
-	}
-
-	dev = host_to_rtsx(host);
-	memset(dev, 0, sizeof(struct rtsx_dev));
-
-	dev->chip = kzalloc(sizeof(struct rtsx_chip), GFP_KERNEL);
-	if (dev->chip == NULL)
-		goto errout;
-
-	spin_lock_init(&dev->reg_lock);
-	mutex_init(&(dev->dev_mutex));
-	init_completion(&dev->cmnd_ready);
-	init_completion(&dev->control_exit);
-	init_completion(&dev->polling_exit);
-	init_completion(&(dev->notify));
-	init_completion(&dev->scanning_done);
-	init_waitqueue_head(&dev->delay_wait);
-
-	dev->pci = pci;
-	dev->irq = -1;
-
-	dev_info(&pci->dev, "Resource length: 0x%x\n",
-		 (unsigned int)pci_resource_len(pci, 0));
-	dev->addr = pci_resource_start(pci, 0);
-	dev->remap_addr = ioremap_nocache(dev->addr, pci_resource_len(pci, 0));
-	if (dev->remap_addr == NULL) {
-		dev_err(&pci->dev, "ioremap error\n");
-		err = -ENXIO;
-		goto errout;
-	}
-
-	/*
-	 * Using "unsigned long" cast here to eliminate gcc warning in
-	 * 64-bit system
-	 */
-	dev_info(&pci->dev, "Original address: 0x%lx, remapped address: 0x%lx\n",
-		 (unsigned long)(dev->addr), (unsigned long)(dev->remap_addr));
-
-	dev->rtsx_resv_buf = dma_alloc_coherent(&(pci->dev), RTSX_RESV_BUF_LEN,
-			&(dev->rtsx_resv_buf_addr), GFP_KERNEL);
-	if (dev->rtsx_resv_buf == NULL) {
-		dev_err(&pci->dev, "alloc dma buffer fail\n");
-		err = -ENXIO;
-		goto errout;
-	}
-	dev->chip->host_cmds_ptr = dev->rtsx_resv_buf;
-	dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr;
-	dev->chip->host_sg_tbl_ptr = dev->rtsx_resv_buf + HOST_CMDS_BUF_LEN;
-	dev->chip->host_sg_tbl_addr = dev->rtsx_resv_buf_addr +
-				      HOST_CMDS_BUF_LEN;
-
-	dev->chip->rtsx = dev;
-
-	rtsx_init_options(dev->chip);
-
-	dev_info(&pci->dev, "pci->irq = %d\n", pci->irq);
-
-	if (dev->chip->msi_en) {
-		if (pci_enable_msi(pci) < 0)
-			dev->chip->msi_en = 0;
-	}
-
-	if (rtsx_acquire_irq(dev) < 0) {
-		err = -EBUSY;
-		goto errout;
-	}
-
-	pci_set_master(pci);
-	synchronize_irq(dev->irq);
-
-	rtsx_init_chip(dev->chip);
-
-	/* set the supported max_lun and max_id for the scsi host
-	 * NOTE: the minimal value of max_id is 1 */
-	host->max_id = 1;
-	host->max_lun = dev->chip->max_lun;
-
-	/* Start up our control thread */
-	th = kthread_run(rtsx_control_thread, dev, CR_DRIVER_NAME);
-	if (IS_ERR(th)) {
-		dev_err(&pci->dev, "Unable to start control thread\n");
-		err = PTR_ERR(th);
-		goto errout;
-	}
-	dev->ctl_thread = th;
-
-	err = scsi_add_host(host, &pci->dev);
-	if (err) {
-		dev_err(&pci->dev, "Unable to add the scsi host\n");
-		goto errout;
-	}
-
-	/* Start up the thread for delayed SCSI-device scanning */
-	th = kthread_run(rtsx_scan_thread, dev, "rtsx-scan");
-	if (IS_ERR(th)) {
-		dev_err(&pci->dev, "Unable to start the device-scanning thread\n");
-		complete(&dev->scanning_done);
-		quiesce_and_remove_host(dev);
-		err = PTR_ERR(th);
-		goto errout;
-	}
-
-	/* Start up the thread for polling thread */
-	th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling");
-	if (IS_ERR(th)) {
-		dev_err(&pci->dev, "Unable to start the device-polling thread\n");
-		quiesce_and_remove_host(dev);
-		err = PTR_ERR(th);
-		goto errout;
-	}
-	dev->polling_thread = th;
-
-	pci_set_drvdata(pci, dev);
-
-	return 0;
-
-	/* We come here if there are any problems */
-errout:
-	dev_err(&pci->dev, "rtsx_probe() failed\n");
-	release_everything(dev);
-
-	return err;
-}
-
-
-static void __devexit rtsx_remove(struct pci_dev *pci)
-{
-	struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci);
-
-	dev_info(&pci->dev, "rtsx_remove() called\n");
-
-	quiesce_and_remove_host(dev);
-	release_everything(dev);
-
-	pci_set_drvdata(pci, NULL);
-}
-
-/* PCI IDs */
-static DEFINE_PCI_DEVICE_TABLE(rtsx_ids) = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x5208), PCI_CLASS_OTHERS << 16, 0xFF0000 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x5209), PCI_CLASS_OTHERS << 16, 0xFF0000 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x5288), PCI_CLASS_OTHERS << 16, 0xFF0000 },
-	{ 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, rtsx_ids);
-
-/* pci_driver definition */
-static struct pci_driver driver = {
-	.name = CR_DRIVER_NAME,
-	.id_table = rtsx_ids,
-	.probe = rtsx_probe,
-	.remove = __devexit_p(rtsx_remove),
-#ifdef CONFIG_PM
-	.suspend = rtsx_suspend,
-	.resume = rtsx_resume,
-#endif
-	.shutdown = rtsx_shutdown,
-};
-
-static int __init rtsx_init(void)
-{
-	pr_info("Initializing Realtek PCIE storage driver...\n");
-
-	return pci_register_driver(&driver);
-}
-
-static void __exit rtsx_exit(void)
-{
-	pr_info("rtsx_exit() called\n");
-
-	pci_unregister_driver(&driver);
-
-	pr_info("%s module exit\n", CR_DRIVER_NAME);
-}
-
-module_init(rtsx_init)
-module_exit(rtsx_exit)
-
diff --git a/drivers/staging/rts_pstor/rtsx.h b/drivers/staging/rts_pstor/rtsx.h
deleted file mode 100644
index 1ab42fc..0000000
--- a/drivers/staging/rts_pstor/rtsx.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- * Header file
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#ifndef __REALTEK_RTSX_H
-#define __REALTEK_RTSX_H
-
-#include <linux/io.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/mutex.h>
-#include <linux/cdrom.h>
-#include <linux/workqueue.h>
-#include <linux/timer.h>
-#include <linux/time.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_devinfo.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_host.h>
-
-#include "debug.h"
-#include "trace.h"
-#include "general.h"
-
-#define CR_DRIVER_NAME		"rts_pstor"
-
-#define pci_get_bus_and_slot(bus, devfn)	\
-	pci_get_domain_bus_and_slot(0, (bus), (devfn))
-
-/*
- * macros for easy use
- */
-#define rtsx_writel(chip, reg, value) \
-	iowrite32(value, (chip)->rtsx->remap_addr + reg)
-#define rtsx_readl(chip, reg) \
-	ioread32((chip)->rtsx->remap_addr + reg)
-#define rtsx_writew(chip, reg, value) \
-	iowrite16(value, (chip)->rtsx->remap_addr + reg)
-#define rtsx_readw(chip, reg) \
-	ioread16((chip)->rtsx->remap_addr + reg)
-#define rtsx_writeb(chip, reg, value) \
-	iowrite8(value, (chip)->rtsx->remap_addr + reg)
-#define rtsx_readb(chip, reg) \
-	ioread8((chip)->rtsx->remap_addr + reg)
-
-#define rtsx_read_config_byte(chip, where, val) \
-	pci_read_config_byte((chip)->rtsx->pci, where, val)
-
-#define rtsx_write_config_byte(chip, where, val) \
-	pci_write_config_byte((chip)->rtsx->pci, where, val)
-
-#define wait_timeout_x(task_state, msecs)		\
-do {							\
-		set_current_state((task_state));	\
-		schedule_timeout((msecs) * HZ / 1000);	\
-} while (0)
-#define wait_timeout(msecs)	wait_timeout_x(TASK_INTERRUPTIBLE, (msecs))
-
-
-#define STATE_TRANS_NONE	0
-#define STATE_TRANS_CMD		1
-#define STATE_TRANS_BUF		2
-#define STATE_TRANS_SG		3
-
-#define TRANS_NOT_READY		0
-#define TRANS_RESULT_OK		1
-#define TRANS_RESULT_FAIL	2
-
-#define SCSI_LUN(srb)		((srb)->device->lun)
-
-typedef unsigned long DELAY_PARA_T;
-
-struct rtsx_chip;
-
-struct rtsx_dev {
-	struct pci_dev *pci;
-
-	/* pci resources */
-	unsigned long 		addr;
-	void __iomem 		*remap_addr;
-	int irq;
-
-	/* locks */
-	spinlock_t 		reg_lock;
-
-	struct task_struct	*ctl_thread;	 /* the control thread   */
-	struct task_struct	*polling_thread; /* the polling thread   */
-
-	/* mutual exclusion and synchronization structures */
-	struct completion	cmnd_ready;	 /* to sleep thread on	    */
-	struct completion	control_exit;	 /* control thread exit	    */
-	struct completion	polling_exit;	 /* polling thread exit	    */
-	struct completion	notify;		 /* thread begin/end	    */
-	struct completion	scanning_done;	 /* wait for scan thread    */
-
-	wait_queue_head_t	delay_wait;	 /* wait during scan, reset */
-	struct mutex		dev_mutex;
-
-	/* host reserved buffer */
-	void 			*rtsx_resv_buf;
-	dma_addr_t 		rtsx_resv_buf_addr;
-
-	char			trans_result;
-	char			trans_state;
-
-	struct completion 	*done;
-	/* Whether interrupt handler should care card cd info */
-	u32 			check_card_cd;
-
-	struct rtsx_chip 	*chip;
-};
-
-typedef struct rtsx_dev rtsx_dev_t;
-
-/* Convert between rtsx_dev and the corresponding Scsi_Host */
-static inline struct Scsi_Host *rtsx_to_host(struct rtsx_dev *dev)
-{
-	return container_of((void *) dev, struct Scsi_Host, hostdata);
-}
-static inline struct rtsx_dev *host_to_rtsx(struct Scsi_Host *host)
-{
-	return (struct rtsx_dev *) host->hostdata;
-}
-
-static inline void get_current_time(u8 *timeval_buf, int buf_len)
-{
-	struct timeval tv;
-
-	if (!timeval_buf || (buf_len < 8))
-		return;
-
-	do_gettimeofday(&tv);
-
-	timeval_buf[0] = (u8)(tv.tv_sec >> 24);
-	timeval_buf[1] = (u8)(tv.tv_sec >> 16);
-	timeval_buf[2] = (u8)(tv.tv_sec >> 8);
-	timeval_buf[3] = (u8)(tv.tv_sec);
-	timeval_buf[4] = (u8)(tv.tv_usec >> 24);
-	timeval_buf[5] = (u8)(tv.tv_usec >> 16);
-	timeval_buf[6] = (u8)(tv.tv_usec >> 8);
-	timeval_buf[7] = (u8)(tv.tv_usec);
-}
-
-/* The scsi_lock() and scsi_unlock() macros protect the sm_state and the
- * single queue element srb for write access */
-#define scsi_unlock(host)	spin_unlock_irq(host->host_lock)
-#define scsi_lock(host)		spin_lock_irq(host->host_lock)
-
-#define lock_state(chip)	spin_lock_irq(&((chip)->rtsx->reg_lock))
-#define unlock_state(chip)	spin_unlock_irq(&((chip)->rtsx->reg_lock))
-
-/* struct scsi_cmnd transfer buffer access utilities */
-enum xfer_buf_dir	{TO_XFER_BUF, FROM_XFER_BUF};
-
-int rtsx_read_pci_cfg_byte(u8 bus, u8 dev, u8 func, u8 offset, u8 *val);
-
-#endif  /* __REALTEK_RTSX_H */
diff --git a/drivers/staging/rts_pstor/rtsx_card.c b/drivers/staging/rts_pstor/rtsx_card.c
deleted file mode 100644
index 539aa6a..0000000
--- a/drivers/staging/rts_pstor/rtsx_card.c
+++ /dev/null
@@ -1,1233 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/kernel.h>
-
-#include "rtsx.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
-
-#include "rtsx_sys.h"
-#include "general.h"
-
-#include "sd.h"
-#include "xd.h"
-#include "ms.h"
-
-void do_remaining_work(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-#ifdef XD_DELAY_WRITE
-	struct xd_info *xd_card = &(chip->xd_card);
-#endif
-	struct ms_info *ms_card = &(chip->ms_card);
-
-	if (chip->card_ready & SD_CARD) {
-		if (sd_card->seq_mode) {
-			rtsx_set_stat(chip, RTSX_STAT_RUN);
-			sd_card->cleanup_counter++;
-		} else {
-			sd_card->cleanup_counter = 0;
-		}
-	}
-
-#ifdef XD_DELAY_WRITE
-	if (chip->card_ready & XD_CARD) {
-		if (xd_card->delay_write.delay_write_flag) {
-			rtsx_set_stat(chip, RTSX_STAT_RUN);
-			xd_card->cleanup_counter++;
-		} else {
-			xd_card->cleanup_counter = 0;
-		}
-	}
-#endif
-
-	if (chip->card_ready & MS_CARD) {
-		if (CHK_MSPRO(ms_card)) {
-			if (ms_card->seq_mode) {
-				rtsx_set_stat(chip, RTSX_STAT_RUN);
-				ms_card->cleanup_counter++;
-			} else {
-				ms_card->cleanup_counter = 0;
-			}
-		} else {
-#ifdef MS_DELAY_WRITE
-			if (ms_card->delay_write.delay_write_flag) {
-				rtsx_set_stat(chip, RTSX_STAT_RUN);
-				ms_card->cleanup_counter++;
-			} else {
-				ms_card->cleanup_counter = 0;
-			}
-#endif
-		}
-	}
-
-	if (sd_card->cleanup_counter > POLLING_WAIT_CNT)
-		sd_cleanup_work(chip);
-
-	if (xd_card->cleanup_counter > POLLING_WAIT_CNT)
-		xd_cleanup_work(chip);
-
-	if (ms_card->cleanup_counter > POLLING_WAIT_CNT)
-		ms_cleanup_work(chip);
-}
-
-void try_to_switch_sdio_ctrl(struct rtsx_chip *chip)
-{
-	u8 reg1 = 0, reg2 = 0;
-
-	rtsx_read_register(chip, 0xFF34, &reg1);
-	rtsx_read_register(chip, 0xFF38, &reg2);
-	RTSX_DEBUGP("reg 0xFF34: 0x%x, reg 0xFF38: 0x%x\n", reg1, reg2);
-	if ((reg1 & 0xC0) && (reg2 & 0xC0)) {
-		chip->sd_int = 1;
-		rtsx_write_register(chip, SDIO_CTRL, 0xFF, SDIO_BUS_CTRL | SDIO_CD_CTRL);
-		rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON);
-	}
-}
-
-#ifdef SUPPORT_SDIO_ASPM
-void dynamic_configure_sdio_aspm(struct rtsx_chip *chip)
-{
-	u8 buf[12], reg;
-	int i;
-
-	for (i = 0; i < 12; i++)
-		rtsx_read_register(chip, 0xFF08 + i, &buf[i]);
-	rtsx_read_register(chip, 0xFF25, &reg);
-	if ((memcmp(buf, chip->sdio_raw_data, 12) != 0) || (reg & 0x03)) {
-		chip->sdio_counter = 0;
-		chip->sdio_idle = 0;
-	} else {
-		if (!chip->sdio_idle) {
-			chip->sdio_counter++;
-			if (chip->sdio_counter >= SDIO_IDLE_COUNT) {
-				chip->sdio_counter = 0;
-				chip->sdio_idle = 1;
-			}
-		}
-	}
-	memcpy(chip->sdio_raw_data, buf, 12);
-
-	if (chip->sdio_idle) {
-		if (!chip->sdio_aspm) {
-			RTSX_DEBUGP("SDIO enter ASPM!\n");
-			rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC,
-					0x30 | (chip->aspm_level[1] << 2));
-			chip->sdio_aspm = 1;
-		}
-	} else {
-		if (chip->sdio_aspm) {
-			RTSX_DEBUGP("SDIO exit ASPM!\n");
-			rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC, 0x30);
-			chip->sdio_aspm = 0;
-		}
-	}
-}
-#endif
-
-void do_reset_sd_card(struct rtsx_chip *chip)
-{
-	int retval;
-
-	RTSX_DEBUGP("%s: %d, card2lun = 0x%x\n", __func__,
-		     chip->sd_reset_counter, chip->card2lun[SD_CARD]);
-
-	if (chip->card2lun[SD_CARD] >= MAX_ALLOWED_LUN_CNT) {
-		clear_bit(SD_NR, &(chip->need_reset));
-		chip->sd_reset_counter = 0;
-		chip->sd_show_cnt = 0;
-		return;
-	}
-
-	chip->rw_fail_cnt[chip->card2lun[SD_CARD]] = 0;
-
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-	rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0);
-
-	retval = reset_sd_card(chip);
-	if (chip->need_release & SD_CARD)
-		return;
-	if (retval == STATUS_SUCCESS) {
-		clear_bit(SD_NR, &(chip->need_reset));
-		chip->sd_reset_counter = 0;
-		chip->sd_show_cnt = 0;
-		chip->card_ready |= SD_CARD;
-		chip->card_fail &= ~SD_CARD;
-		chip->rw_card[chip->card2lun[SD_CARD]] = sd_rw;
-	} else {
-		if (chip->sd_io || (chip->sd_reset_counter >= MAX_RESET_CNT)) {
-			clear_bit(SD_NR, &(chip->need_reset));
-			chip->sd_reset_counter = 0;
-			chip->sd_show_cnt = 0;
-		} else {
-			chip->sd_reset_counter++;
-		}
-		chip->card_ready &= ~SD_CARD;
-		chip->card_fail |= SD_CARD;
-		chip->capacity[chip->card2lun[SD_CARD]] = 0;
-		chip->rw_card[chip->card2lun[SD_CARD]] = NULL;
-
-		rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
-		if (!chip->ft2_fast_mode)
-			card_power_off(chip, SD_CARD);
-		if (chip->sd_io) {
-			chip->sd_int = 0;
-			try_to_switch_sdio_ctrl(chip);
-		} else {
-			disable_card_clock(chip, SD_CARD);
-		}
-	}
-}
-
-void do_reset_xd_card(struct rtsx_chip *chip)
-{
-	int retval;
-
-	RTSX_DEBUGP("%s: %d, card2lun = 0x%x\n", __func__,
-		     chip->xd_reset_counter, chip->card2lun[XD_CARD]);
-
-	if (chip->card2lun[XD_CARD] >= MAX_ALLOWED_LUN_CNT) {
-		clear_bit(XD_NR, &(chip->need_reset));
-		chip->xd_reset_counter = 0;
-		chip->xd_show_cnt = 0;
-		return;
-	}
-
-	chip->rw_fail_cnt[chip->card2lun[XD_CARD]] = 0;
-
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-	rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0);
-
-	retval = reset_xd_card(chip);
-	if (chip->need_release & XD_CARD)
-		return;
-	if (retval == STATUS_SUCCESS) {
-		clear_bit(XD_NR, &(chip->need_reset));
-		chip->xd_reset_counter = 0;
-		chip->card_ready |= XD_CARD;
-		chip->card_fail &= ~XD_CARD;
-		chip->rw_card[chip->card2lun[XD_CARD]] = xd_rw;
-	} else {
-		if (chip->xd_reset_counter >= MAX_RESET_CNT) {
-			clear_bit(XD_NR, &(chip->need_reset));
-			chip->xd_reset_counter = 0;
-			chip->xd_show_cnt = 0;
-		} else {
-			chip->xd_reset_counter++;
-		}
-		chip->card_ready &= ~XD_CARD;
-		chip->card_fail |= XD_CARD;
-		chip->capacity[chip->card2lun[XD_CARD]] = 0;
-		chip->rw_card[chip->card2lun[XD_CARD]] = NULL;
-
-		rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0);
-		if (!chip->ft2_fast_mode)
-			card_power_off(chip, XD_CARD);
-		disable_card_clock(chip, XD_CARD);
-	}
-}
-
-void do_reset_ms_card(struct rtsx_chip *chip)
-{
-	int retval;
-
-	RTSX_DEBUGP("%s: %d, card2lun = 0x%x\n", __func__,
-		     chip->ms_reset_counter, chip->card2lun[MS_CARD]);
-
-	if (chip->card2lun[MS_CARD] >= MAX_ALLOWED_LUN_CNT) {
-		clear_bit(MS_NR, &(chip->need_reset));
-		chip->ms_reset_counter = 0;
-		chip->ms_show_cnt = 0;
-		return;
-	}
-
-	chip->rw_fail_cnt[chip->card2lun[MS_CARD]] = 0;
-
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-	rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0);
-
-	retval = reset_ms_card(chip);
-	if (chip->need_release & MS_CARD)
-		return;
-	if (retval == STATUS_SUCCESS) {
-		clear_bit(MS_NR, &(chip->need_reset));
-		chip->ms_reset_counter = 0;
-		chip->card_ready |= MS_CARD;
-		chip->card_fail &= ~MS_CARD;
-		chip->rw_card[chip->card2lun[MS_CARD]] = ms_rw;
-	} else {
-		if (chip->ms_reset_counter >= MAX_RESET_CNT) {
-			clear_bit(MS_NR, &(chip->need_reset));
-			chip->ms_reset_counter = 0;
-			chip->ms_show_cnt = 0;
-		} else {
-			chip->ms_reset_counter++;
-		}
-		chip->card_ready &= ~MS_CARD;
-		chip->card_fail |= MS_CARD;
-		chip->capacity[chip->card2lun[MS_CARD]] = 0;
-		chip->rw_card[chip->card2lun[MS_CARD]] = NULL;
-
-		rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
-		if (!chip->ft2_fast_mode)
-			card_power_off(chip, MS_CARD);
-		disable_card_clock(chip, MS_CARD);
-	}
-}
-
-static void release_sdio(struct rtsx_chip *chip)
-{
-	if (chip->sd_io) {
-		rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR,
-				SD_STOP | SD_CLR_ERR);
-
-		if (chip->chip_insert_with_sdio) {
-			chip->chip_insert_with_sdio = 0;
-
-			if (CHECK_PID(chip, 0x5288))
-				rtsx_write_register(chip, 0xFE5A, 0x08, 0x00);
-			else
-				rtsx_write_register(chip, 0xFE70, 0x80, 0x00);
-		}
-
-		rtsx_write_register(chip, SDIO_CTRL, SDIO_CD_CTRL, 0);
-		chip->sd_io = 0;
-	}
-}
-
-void rtsx_power_off_card(struct rtsx_chip *chip)
-{
-	if ((chip->card_ready & SD_CARD) || chip->sd_io) {
-		sd_cleanup_work(chip);
-		sd_power_off_card3v3(chip);
-	}
-
-	if (chip->card_ready & XD_CARD) {
-		xd_cleanup_work(chip);
-		xd_power_off_card3v3(chip);
-	}
-
-	if (chip->card_ready & MS_CARD) {
-		ms_cleanup_work(chip);
-		ms_power_off_card3v3(chip);
-	}
-}
-
-void rtsx_release_cards(struct rtsx_chip *chip)
-{
-	chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
-	if ((chip->card_ready & SD_CARD) || chip->sd_io) {
-		if (chip->int_reg & SD_EXIST)
-			sd_cleanup_work(chip);
-		release_sd_card(chip);
-	}
-
-	if (chip->card_ready & XD_CARD) {
-		if (chip->int_reg & XD_EXIST)
-			xd_cleanup_work(chip);
-		release_xd_card(chip);
-	}
-
-	if (chip->card_ready & MS_CARD) {
-		if (chip->int_reg & MS_EXIST)
-			ms_cleanup_work(chip);
-		release_ms_card(chip);
-	}
-}
-
-void rtsx_reset_cards(struct rtsx_chip *chip)
-{
-	if (!chip->need_reset)
-		return;
-
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
-
-	rtsx_disable_aspm(chip);
-
-	if ((chip->need_reset & SD_CARD) && chip->chip_insert_with_sdio)
-		clear_bit(SD_NR, &(chip->need_reset));
-
-	if (chip->need_reset & XD_CARD) {
-		chip->card_exist |= XD_CARD;
-
-		if (chip->xd_show_cnt >= MAX_SHOW_CNT)
-			do_reset_xd_card(chip);
-		else
-			chip->xd_show_cnt++;
-	}
-	if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) {
-		if (chip->card_exist & XD_CARD) {
-			clear_bit(SD_NR, &(chip->need_reset));
-			clear_bit(MS_NR, &(chip->need_reset));
-		}
-	}
-	if (chip->need_reset & SD_CARD) {
-		chip->card_exist |= SD_CARD;
-
-		if (chip->sd_show_cnt >= MAX_SHOW_CNT) {
-			rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
-			do_reset_sd_card(chip);
-		} else {
-			chip->sd_show_cnt++;
-		}
-	}
-	if (chip->need_reset & MS_CARD) {
-		chip->card_exist |= MS_CARD;
-
-		if (chip->ms_show_cnt >= MAX_SHOW_CNT)
-			do_reset_ms_card(chip);
-		else
-			chip->ms_show_cnt++;
-	}
-}
-
-void rtsx_reinit_cards(struct rtsx_chip *chip, int reset_chip)
-{
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
-
-	if (reset_chip)
-		rtsx_reset_chip(chip);
-
-	chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
-	if ((chip->int_reg & SD_EXIST) && (chip->need_reinit & SD_CARD)) {
-		release_sdio(chip);
-		release_sd_card(chip);
-
-		wait_timeout(100);
-
-		chip->card_exist |= SD_CARD;
-		do_reset_sd_card(chip);
-	}
-
-	if ((chip->int_reg & XD_EXIST) && (chip->need_reinit & XD_CARD)) {
-		release_xd_card(chip);
-
-		wait_timeout(100);
-
-		chip->card_exist |= XD_CARD;
-		do_reset_xd_card(chip);
-	}
-
-	if ((chip->int_reg & MS_EXIST) && (chip->need_reinit & MS_CARD)) {
-		release_ms_card(chip);
-
-		wait_timeout(100);
-
-		chip->card_exist |= MS_CARD;
-		do_reset_ms_card(chip);
-	}
-
-	chip->need_reinit = 0;
-}
-
-#ifdef DISABLE_CARD_INT
-void card_cd_debounce(struct rtsx_chip *chip, unsigned long *need_reset, unsigned long *need_release)
-{
-	u8 release_map = 0, reset_map = 0;
-
-	chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
-	if (chip->card_exist) {
-		if (chip->card_exist & XD_CARD) {
-			if (!(chip->int_reg & XD_EXIST))
-				release_map |= XD_CARD;
-		} else if (chip->card_exist & SD_CARD) {
-			if (!(chip->int_reg & SD_EXIST))
-				release_map |= SD_CARD;
-		} else if (chip->card_exist & MS_CARD) {
-			if (!(chip->int_reg & MS_EXIST))
-				release_map |= MS_CARD;
-		}
-	} else {
-		if (chip->int_reg & XD_EXIST)
-			reset_map |= XD_CARD;
-		else if (chip->int_reg & SD_EXIST)
-			reset_map |= SD_CARD;
-		else if (chip->int_reg & MS_EXIST)
-			reset_map |= MS_CARD;
-	}
-
-	if (reset_map) {
-		int xd_cnt = 0, sd_cnt = 0, ms_cnt = 0;
-		int i;
-
-		for (i = 0; i < (DEBOUNCE_CNT); i++) {
-			chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
-			if (chip->int_reg & XD_EXIST)
-				xd_cnt++;
-			else
-				xd_cnt = 0;
-
-			if (chip->int_reg & SD_EXIST)
-				sd_cnt++;
-			else
-				sd_cnt = 0;
-
-			if (chip->int_reg & MS_EXIST)
-				ms_cnt++;
-			else
-				ms_cnt = 0;
-
-			wait_timeout(30);
-		}
-
-		reset_map = 0;
-		if (!(chip->card_exist & XD_CARD) && (xd_cnt > (DEBOUNCE_CNT-1)))
-			reset_map |= XD_CARD;
-		if (!(chip->card_exist & SD_CARD) && (sd_cnt > (DEBOUNCE_CNT-1)))
-			reset_map |= SD_CARD;
-		if (!(chip->card_exist & MS_CARD) && (ms_cnt > (DEBOUNCE_CNT-1)))
-			reset_map |= MS_CARD;
-	}
-
-	if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN))
-		rtsx_write_register(chip, HOST_SLEEP_STATE, 0xC0, 0x00);
-
-	if (need_reset)
-		*need_reset = reset_map;
-	if (need_release)
-		*need_release = release_map;
-}
-#endif
-
-void rtsx_init_cards(struct rtsx_chip *chip)
-{
-	if (RTSX_TST_DELINK(chip) && (rtsx_get_stat(chip) != RTSX_STAT_SS)) {
-		RTSX_DEBUGP("Reset chip in polling thread!\n");
-		rtsx_reset_chip(chip);
-		RTSX_CLR_DELINK(chip);
-	}
-
-#ifdef DISABLE_CARD_INT
-	card_cd_debounce(chip, &(chip->need_reset), &(chip->need_release));
-#endif
-
-	if (chip->need_release) {
-		if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) {
-			if (chip->int_reg & XD_EXIST) {
-				clear_bit(SD_NR, &(chip->need_release));
-				clear_bit(MS_NR, &(chip->need_release));
-			}
-		}
-
-		if (!(chip->card_exist & SD_CARD) && !chip->sd_io)
-			clear_bit(SD_NR, &(chip->need_release));
-		if (!(chip->card_exist & XD_CARD))
-			clear_bit(XD_NR, &(chip->need_release));
-		if (!(chip->card_exist & MS_CARD))
-			clear_bit(MS_NR, &(chip->need_release));
-
-		RTSX_DEBUGP("chip->need_release = 0x%x\n", (unsigned int)(chip->need_release));
-
-#ifdef SUPPORT_OCP
-		if (chip->need_release) {
-			if (CHECK_PID(chip, 0x5209)) {
-				u8 mask = 0, val = 0;
-				if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
-					if (chip->ocp_stat & (MS_OC_NOW | MS_OC_EVER)) {
-						mask |= MS_OCP_INT_CLR | MS_OC_CLR;
-						val |= MS_OCP_INT_CLR | MS_OC_CLR;
-					}
-				}
-				if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
-					mask |= SD_OCP_INT_CLR | SD_OC_CLR;
-					val |= SD_OCP_INT_CLR | SD_OC_CLR;
-				}
-				if (mask)
-					rtsx_write_register(chip, OCPCTL, mask, val);
-			} else {
-				if (chip->ocp_stat & (CARD_OC_NOW | CARD_OC_EVER))
-					rtsx_write_register(chip, OCPCLR,
-							    CARD_OC_INT_CLR | CARD_OC_CLR,
-							    CARD_OC_INT_CLR | CARD_OC_CLR);
-			}
-			chip->ocp_stat = 0;
-		}
-#endif
-		if (chip->need_release) {
-			rtsx_set_stat(chip, RTSX_STAT_RUN);
-			rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
-		}
-
-		if (chip->need_release & SD_CARD) {
-			clear_bit(SD_NR, &(chip->need_release));
-			chip->card_exist &= ~SD_CARD;
-			chip->card_ejected &= ~SD_CARD;
-			chip->card_fail &= ~SD_CARD;
-			CLR_BIT(chip->lun_mc, chip->card2lun[SD_CARD]);
-			chip->rw_fail_cnt[chip->card2lun[SD_CARD]] = 0;
-			rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
-
-			release_sdio(chip);
-			release_sd_card(chip);
-		}
-
-		if (chip->need_release & XD_CARD) {
-			clear_bit(XD_NR, &(chip->need_release));
-			chip->card_exist &= ~XD_CARD;
-			chip->card_ejected &= ~XD_CARD;
-			chip->card_fail &= ~XD_CARD;
-			CLR_BIT(chip->lun_mc, chip->card2lun[XD_CARD]);
-			chip->rw_fail_cnt[chip->card2lun[XD_CARD]] = 0;
-
-			release_xd_card(chip);
-
-			if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN))
-				rtsx_write_register(chip, HOST_SLEEP_STATE, 0xC0, 0xC0);
-		}
-
-		if (chip->need_release & MS_CARD) {
-			clear_bit(MS_NR, &(chip->need_release));
-			chip->card_exist &= ~MS_CARD;
-			chip->card_ejected &= ~MS_CARD;
-			chip->card_fail &= ~MS_CARD;
-			CLR_BIT(chip->lun_mc, chip->card2lun[MS_CARD]);
-			chip->rw_fail_cnt[chip->card2lun[MS_CARD]] = 0;
-
-			release_ms_card(chip);
-		}
-
-		RTSX_DEBUGP("chip->card_exist = 0x%x\n", chip->card_exist);
-
-		if (!chip->card_exist)
-			turn_off_led(chip, LED_GPIO);
-	}
-
-	if (chip->need_reset) {
-		RTSX_DEBUGP("chip->need_reset = 0x%x\n", (unsigned int)(chip->need_reset));
-
-		rtsx_reset_cards(chip);
-	}
-
-	if (chip->need_reinit) {
-		RTSX_DEBUGP("chip->need_reinit = 0x%x\n", (unsigned int)(chip->need_reinit));
-
-		rtsx_reinit_cards(chip, 0);
-	}
-}
-
-static inline u8 double_depth(u8 depth)
-{
-	return ((depth > 1) ? (depth - 1) : depth);
-}
-
-int switch_ssc_clock(struct rtsx_chip *chip, int clk)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-	u8 N = (u8)(clk - 2), min_N, max_N;
-	u8 mcu_cnt, div, max_div, ssc_depth, ssc_depth_mask;
-	int sd_vpclk_phase_reset = 0;
-
-	if (chip->cur_clk == clk)
-		return STATUS_SUCCESS;
-
-	if (CHECK_PID(chip, 0x5209)) {
-		min_N = 80;
-		max_N = 208;
-		max_div = CLK_DIV_8;
-	} else {
-		min_N = 60;
-		max_N = 120;
-		max_div = CLK_DIV_4;
-	}
-
-	if (CHECK_PID(chip, 0x5209) && (chip->cur_card == SD_CARD)) {
-		struct sd_info *sd_card = &(chip->sd_card);
-		if (CHK_SD30_SPEED(sd_card) || CHK_MMC_DDR52(sd_card))
-			sd_vpclk_phase_reset = 1;
-	}
-
-	RTSX_DEBUGP("Switch SSC clock to %dMHz (cur_clk = %d)\n", clk, chip->cur_clk);
-
-	if ((clk <= 2) || (N > max_N))
-		TRACE_RET(chip, STATUS_FAIL);
-
-	mcu_cnt = (u8)(125/clk + 3);
-	if (CHECK_PID(chip, 0x5209)) {
-		if (mcu_cnt > 15)
-			mcu_cnt = 15;
-	} else {
-		if (mcu_cnt > 7)
-			mcu_cnt = 7;
-	}
-
-	div = CLK_DIV_1;
-	while ((N < min_N) && (div < max_div)) {
-		N = (N + 2) * 2 - 2;
-		div++;
-	}
-	RTSX_DEBUGP("N = %d, div = %d\n", N, div);
-
-	if (chip->ssc_en) {
-		if (CHECK_PID(chip, 0x5209)) {
-			if (chip->cur_card == SD_CARD) {
-				if (CHK_SD_SDR104(sd_card))
-					ssc_depth = chip->ssc_depth_sd_sdr104;
-				else if (CHK_SD_SDR50(sd_card))
-					ssc_depth = chip->ssc_depth_sd_sdr50;
-				else if (CHK_SD_DDR50(sd_card))
-					ssc_depth = double_depth(chip->ssc_depth_sd_ddr50);
-				else if (CHK_SD_HS(sd_card))
-					ssc_depth = double_depth(chip->ssc_depth_sd_hs);
-				else if (CHK_MMC_52M(sd_card) || CHK_MMC_DDR52(sd_card))
-					ssc_depth = double_depth(chip->ssc_depth_mmc_52m);
-				else
-					ssc_depth = double_depth(chip->ssc_depth_low_speed);
-			} else if (chip->cur_card == MS_CARD) {
-				if (CHK_MSPRO(ms_card)) {
-					if (CHK_HG8BIT(ms_card))
-						ssc_depth = double_depth(chip->ssc_depth_ms_hg);
-					else
-						ssc_depth = double_depth(chip->ssc_depth_ms_4bit);
-				} else {
-					if (CHK_MS4BIT(ms_card))
-						ssc_depth = double_depth(chip->ssc_depth_ms_4bit);
-					else
-						ssc_depth = double_depth(chip->ssc_depth_low_speed);
-				}
-			} else {
-				ssc_depth = double_depth(chip->ssc_depth_low_speed);
-			}
-
-			if (ssc_depth) {
-				if (div == CLK_DIV_2) {
-					if (ssc_depth > 1)
-						ssc_depth -= 1;
-					else
-						ssc_depth = SSC_DEPTH_4M;
-
-				} else if (div == CLK_DIV_4) {
-					if (ssc_depth > 2)
-						ssc_depth -= 2;
-					else
-						ssc_depth = SSC_DEPTH_4M;
-
-				} else if (div == CLK_DIV_8) {
-					if (ssc_depth > 3)
-						ssc_depth -= 3;
-					else
-						ssc_depth = SSC_DEPTH_4M;
-
-				}
-			}
-		} else {
-			ssc_depth = 0x01;
-			N -= 2;
-		}
-	} else {
-		ssc_depth = 0;
-	}
-
-	if (CHECK_PID(chip, 0x5209))
-		ssc_depth_mask = SSC_DEPTH_MASK;
-	else
-		ssc_depth_mask = 0x03;
-
-	RTSX_DEBUGP("ssc_depth = %d\n", ssc_depth);
-
-	rtsx_init_cmd(chip);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, 0xFF, (div << 4) | mcu_cnt);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL2, ssc_depth_mask, ssc_depth);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, N);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB);
-	if (sd_vpclk_phase_reset) {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET);
-	}
-
-	retval = rtsx_send_cmd(chip, 0, WAIT_TIME);
-	if (retval < 0)
-		TRACE_RET(chip, STATUS_ERROR);
-
-	udelay(10);
-	RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0);
-
-	chip->cur_clk = clk;
-
-	return STATUS_SUCCESS;
-}
-
-int switch_normal_clock(struct rtsx_chip *chip, int clk)
-{
-	u8 sel, div, mcu_cnt;
-	int sd_vpclk_phase_reset = 0;
-
-	if (chip->cur_clk == clk)
-		return STATUS_SUCCESS;
-
-	if (CHECK_PID(chip, 0x5209) && (chip->cur_card == SD_CARD)) {
-		struct sd_info *sd_card = &(chip->sd_card);
-		if (CHK_SD30_SPEED(sd_card) || CHK_MMC_DDR52(sd_card))
-			sd_vpclk_phase_reset = 1;
-	}
-
-	switch (clk) {
-	case CLK_20:
-		RTSX_DEBUGP("Switch clock to 20MHz\n");
-		sel = SSC_80;
-		div = CLK_DIV_4;
-		mcu_cnt = 7;
-		break;
-
-	case CLK_30:
-		RTSX_DEBUGP("Switch clock to 30MHz\n");
-		sel = SSC_120;
-		div = CLK_DIV_4;
-		mcu_cnt = 7;
-		break;
-
-	case CLK_40:
-		RTSX_DEBUGP("Switch clock to 40MHz\n");
-		sel = SSC_80;
-		div = CLK_DIV_2;
-		mcu_cnt = 7;
-		break;
-
-	case CLK_50:
-		RTSX_DEBUGP("Switch clock to 50MHz\n");
-		sel = SSC_100;
-		div = CLK_DIV_2;
-		mcu_cnt = 6;
-		break;
-
-	case CLK_60:
-		RTSX_DEBUGP("Switch clock to 60MHz\n");
-		sel = SSC_120;
-		div = CLK_DIV_2;
-		mcu_cnt = 6;
-		break;
-
-	case CLK_80:
-		RTSX_DEBUGP("Switch clock to 80MHz\n");
-		sel = SSC_80;
-		div = CLK_DIV_1;
-		mcu_cnt = 5;
-		break;
-
-	case CLK_100:
-		RTSX_DEBUGP("Switch clock to 100MHz\n");
-		sel = SSC_100;
-		div = CLK_DIV_1;
-		mcu_cnt = 5;
-		break;
-
-	case CLK_120:
-		RTSX_DEBUGP("Switch clock to 120MHz\n");
-		sel = SSC_120;
-		div = CLK_DIV_1;
-		mcu_cnt = 5;
-		break;
-
-	case CLK_150:
-		RTSX_DEBUGP("Switch clock to 150MHz\n");
-		sel = SSC_150;
-		div = CLK_DIV_1;
-		mcu_cnt = 4;
-		break;
-
-	case CLK_200:
-		RTSX_DEBUGP("Switch clock to 200MHz\n");
-		sel = SSC_200;
-		div = CLK_DIV_1;
-		mcu_cnt = 4;
-		break;
-
-	default:
-		RTSX_DEBUGP("Try to switch to an illegal clock (%d)\n", clk);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	RTSX_WRITE_REG(chip, CLK_CTL, 0xFF, CLK_LOW_FREQ);
-	if (sd_vpclk_phase_reset) {
-		RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
-		RTSX_WRITE_REG(chip, SD_VPCLK1_CTL, PHASE_NOT_RESET, 0);
-	}
-	RTSX_WRITE_REG(chip, CLK_DIV, 0xFF, (div << 4) | mcu_cnt);
-	RTSX_WRITE_REG(chip, CLK_SEL, 0xFF, sel);
-
-	if (sd_vpclk_phase_reset) {
-		udelay(200);
-		RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET);
-		RTSX_WRITE_REG(chip, SD_VPCLK1_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET);
-		udelay(200);
-	}
-	RTSX_WRITE_REG(chip, CLK_CTL, 0xFF, 0);
-
-	chip->cur_clk = clk;
-
-	return STATUS_SUCCESS;
-}
-
-void trans_dma_enable(enum dma_data_direction dir, struct rtsx_chip *chip, u32 byte_cnt, u8 pack_size)
-{
-	if (pack_size > DMA_1024)
-		pack_size = DMA_512;
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, IRQSTAT0, DMA_DONE_INT, DMA_DONE_INT);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(byte_cnt >> 24));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(byte_cnt >> 16));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(byte_cnt >> 8));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC0, 0xFF, (u8)byte_cnt);
-
-	if (dir == DMA_FROM_DEVICE) {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, DMACTL, 0x03 | DMA_PACK_SIZE_MASK,
-			     DMA_DIR_FROM_CARD | DMA_EN | pack_size);
-	} else {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, DMACTL, 0x03 | DMA_PACK_SIZE_MASK,
-			     DMA_DIR_TO_CARD | DMA_EN | pack_size);
-	}
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-}
-
-int enable_card_clock(struct rtsx_chip *chip, u8 card)
-{
-	u8 clk_en = 0;
-
-	if (card & XD_CARD)
-		clk_en |= XD_CLK_EN;
-	if (card & SD_CARD)
-		clk_en |= SD_CLK_EN;
-	if (card & MS_CARD)
-		clk_en |= MS_CLK_EN;
-
-	RTSX_WRITE_REG(chip, CARD_CLK_EN, clk_en, clk_en);
-
-	return STATUS_SUCCESS;
-}
-
-int disable_card_clock(struct rtsx_chip *chip, u8 card)
-{
-	u8 clk_en = 0;
-
-	if (card & XD_CARD)
-		clk_en |= XD_CLK_EN;
-	if (card & SD_CARD)
-		clk_en |= SD_CLK_EN;
-	if (card & MS_CARD)
-		clk_en |= MS_CLK_EN;
-
-	RTSX_WRITE_REG(chip, CARD_CLK_EN, clk_en, 0);
-
-	return STATUS_SUCCESS;
-}
-
-int card_power_on(struct rtsx_chip *chip, u8 card)
-{
-	int retval;
-	u8 mask, val1, val2;
-
-	if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && (card == MS_CARD)) {
-		mask = MS_POWER_MASK;
-		val1 = MS_PARTIAL_POWER_ON;
-		val2 = MS_POWER_ON;
-	} else {
-		mask = SD_POWER_MASK;
-		val1 = SD_PARTIAL_POWER_ON;
-		val2 = SD_POWER_ON;
-	}
-
-	rtsx_init_cmd(chip);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val1);
-	if (CHECK_PID(chip, 0x5209) && (card == SD_CARD))
-		rtsx_add_cmd(chip, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_SUSPEND);
-
-	retval = rtsx_send_cmd(chip, 0, 100);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	udelay(chip->pmos_pwr_on_interval);
-
-	rtsx_init_cmd(chip);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val2);
-	if (CHECK_PID(chip, 0x5209) && (card == SD_CARD))
-		rtsx_add_cmd(chip, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON);
-
-	retval = rtsx_send_cmd(chip, 0, 100);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-int card_power_off(struct rtsx_chip *chip, u8 card)
-{
-	u8 mask, val;
-
-	if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && (card == MS_CARD)) {
-		mask = MS_POWER_MASK;
-		val = MS_POWER_OFF;
-	} else {
-		mask = SD_POWER_MASK;
-		val = SD_POWER_OFF;
-	}
-	if (CHECK_PID(chip, 0x5209)) {
-		mask |= PMOS_STRG_MASK;
-		val |= PMOS_STRG_400mA;
-	}
-
-	RTSX_WRITE_REG(chip, CARD_PWR_CTL, mask, val);
-	if (CHECK_PID(chip, 0x5209) && (card == SD_CARD))
-		RTSX_WRITE_REG(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_OFF);
-
-	return STATUS_SUCCESS;
-}
-
-int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 sec_addr, u16 sec_cnt)
-{
-	int retval;
-	unsigned int lun = SCSI_LUN(srb);
-	int i;
-
-	if (chip->rw_card[lun] == NULL)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	for (i = 0; i < 3; i++) {
-		chip->rw_need_retry = 0;
-
-		retval = chip->rw_card[lun](srb, chip, sec_addr, sec_cnt);
-		if (retval != STATUS_SUCCESS) {
-			if (rtsx_check_chip_exist(chip) != STATUS_SUCCESS) {
-				rtsx_release_chip(chip);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			if (detect_card_cd(chip, chip->cur_card) != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-
-			if (!chip->rw_need_retry) {
-				RTSX_DEBUGP("RW fail, but no need to retry\n");
-				break;
-			}
-		} else {
-			chip->rw_need_retry = 0;
-			break;
-		}
-
-		RTSX_DEBUGP("Retry RW, (i = %d)\n", i);
-	}
-
-	return retval;
-}
-
-int card_share_mode(struct rtsx_chip *chip, int card)
-{
-	u8 mask, value;
-
-	if (CHECK_PID(chip, 0x5209) || CHECK_PID(chip, 0x5208)) {
-		mask = CARD_SHARE_MASK;
-		if (card == SD_CARD)
-			value = CARD_SHARE_48_SD;
-		else if (card == MS_CARD)
-			value = CARD_SHARE_48_MS;
-		else if (card == XD_CARD)
-			value = CARD_SHARE_48_XD;
-		else
-			TRACE_RET(chip, STATUS_FAIL);
-
-	} else if (CHECK_PID(chip, 0x5288)) {
-		mask = 0x03;
-		if (card == SD_CARD)
-			value = CARD_SHARE_BAROSSA_SD;
-		else if (card == MS_CARD)
-			value = CARD_SHARE_BAROSSA_MS;
-		else if (card == XD_CARD)
-			value = CARD_SHARE_BAROSSA_XD;
-		else
-			TRACE_RET(chip, STATUS_FAIL);
-
-	} else {
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	RTSX_WRITE_REG(chip, CARD_SHARE_MODE, mask, value);
-
-	return STATUS_SUCCESS;
-}
-
-
-int select_card(struct rtsx_chip *chip, int card)
-{
-	int retval;
-
-	if (chip->cur_card != card) {
-		u8 mod;
-
-		if (card == SD_CARD)
-			mod = SD_MOD_SEL;
-		else if (card == MS_CARD)
-			mod = MS_MOD_SEL;
-		else if (card == XD_CARD)
-			mod = XD_MOD_SEL;
-		else if (card == SPI_CARD)
-			mod = SPI_MOD_SEL;
-		else
-			TRACE_RET(chip, STATUS_FAIL);
-
-		RTSX_WRITE_REG(chip, CARD_SELECT, 0x07, mod);
-		chip->cur_card = card;
-
-		retval =  card_share_mode(chip, card);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-void toggle_gpio(struct rtsx_chip *chip, u8 gpio)
-{
-	u8 temp_reg;
-
-	rtsx_read_register(chip, CARD_GPIO, &temp_reg);
-	temp_reg ^= (0x01 << gpio);
-	rtsx_write_register(chip, CARD_GPIO, 0xFF, temp_reg);
-}
-
-void turn_on_led(struct rtsx_chip *chip, u8 gpio)
-{
-	if (CHECK_PID(chip, 0x5288))
-		rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), (u8)(1 << gpio));
-	else
-		rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0);
-}
-
-void turn_off_led(struct rtsx_chip *chip, u8 gpio)
-{
-	if (CHECK_PID(chip, 0x5288))
-		rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0);
-	else
-		rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), (u8)(1 << gpio));
-}
-
-int detect_card_cd(struct rtsx_chip *chip, int card)
-{
-	u32 card_cd, status;
-
-	if (card == SD_CARD) {
-		card_cd = SD_EXIST;
-	} else if (card == MS_CARD) {
-		card_cd = MS_EXIST;
-	} else if (card == XD_CARD) {
-		card_cd = XD_EXIST;
-	} else {
-		RTSX_DEBUGP("Wrong card type: 0x%x\n", card);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	status = rtsx_readl(chip, RTSX_BIPR);
-	if (!(status & card_cd))
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-int check_card_exist(struct rtsx_chip *chip, unsigned int lun)
-{
-	if (chip->card_exist & chip->lun2card[lun])
-		return 1;
-
-	return 0;
-}
-
-int check_card_ready(struct rtsx_chip *chip, unsigned int lun)
-{
-	if (chip->card_ready & chip->lun2card[lun])
-		return 1;
-
-	return 0;
-}
-
-int check_card_wp(struct rtsx_chip *chip, unsigned int lun)
-{
-	if (chip->card_wp & chip->lun2card[lun])
-		return 1;
-
-	return 0;
-}
-
-int check_card_fail(struct rtsx_chip *chip, unsigned int lun)
-{
-	if (chip->card_fail & chip->lun2card[lun])
-		return 1;
-
-	return 0;
-}
-
-int check_card_ejected(struct rtsx_chip *chip, unsigned int lun)
-{
-	if (chip->card_ejected & chip->lun2card[lun])
-		return 1;
-
-	return 0;
-}
-
-u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun)
-{
-	if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD)
-		return (u8)XD_CARD;
-	else if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD)
-		return (u8)SD_CARD;
-	else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD)
-		return (u8)MS_CARD;
-
-	return 0;
-}
-
-void eject_card(struct rtsx_chip *chip, unsigned int lun)
-{
-	do_remaining_work(chip);
-
-	if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD) {
-		release_sd_card(chip);
-		chip->card_ejected |= SD_CARD;
-		chip->card_ready &= ~SD_CARD;
-		chip->capacity[lun] = 0;
-	} else if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) {
-		release_xd_card(chip);
-		chip->card_ejected |= XD_CARD;
-		chip->card_ready &= ~XD_CARD;
-		chip->capacity[lun] = 0;
-	} else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD) {
-		release_ms_card(chip);
-		chip->card_ejected |= MS_CARD;
-		chip->card_ready &= ~MS_CARD;
-		chip->capacity[lun] = 0;
-	}
-}
diff --git a/drivers/staging/rts_pstor/rtsx_card.h b/drivers/staging/rts_pstor/rtsx_card.h
deleted file mode 100644
index 3f72776..0000000
--- a/drivers/staging/rts_pstor/rtsx_card.h
+++ /dev/null
@@ -1,1093 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- * Header file
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#ifndef __REALTEK_RTSX_CARD_H
-#define __REALTEK_RTSX_CARD_H
-
-#include "debug.h"
-#include "rtsx.h"
-#include "rtsx_chip.h"
-#include "rtsx_transport.h"
-#include "sd.h"
-
-#define SSC_POWER_DOWN		0x01
-#define SD_OC_POWER_DOWN	0x02
-#define MS_OC_POWER_DOWN	0x04
-#define ALL_POWER_DOWN		0x07
-#define OC_POWER_DOWN		0x06
-
-#define PMOS_STRG_MASK		0x10
-#define PMOS_STRG_800mA		0x10
-#define PMOS_STRG_400mA		0x00
-
-#define POWER_OFF		0x03
-#define PARTIAL_POWER_ON	0x01
-#define POWER_ON		0x00
-
-#define MS_POWER_OFF		0x0C
-#define MS_PARTIAL_POWER_ON	0x04
-#define MS_POWER_ON		0x00
-#define MS_POWER_MASK		0x0C
-
-#define SD_POWER_OFF		0x03
-#define SD_PARTIAL_POWER_ON	0x01
-#define SD_POWER_ON		0x00
-#define SD_POWER_MASK		0x03
-
-#define XD_OUTPUT_EN		0x02
-#define SD_OUTPUT_EN		0x04
-#define MS_OUTPUT_EN		0x08
-#define SPI_OUTPUT_EN		0x10
-
-#define CLK_LOW_FREQ		0x01
-
-#define CLK_DIV_1		0x01
-#define CLK_DIV_2		0x02
-#define CLK_DIV_4		0x03
-#define CLK_DIV_8		0x04
-
-#define SSC_80			0
-#define SSC_100			1
-#define SSC_120			2
-#define SSC_150			3
-#define SSC_200			4
-
-#define XD_CLK_EN		0x02
-#define SD_CLK_EN		0x04
-#define MS_CLK_EN		0x08
-#define SPI_CLK_EN		0x10
-
-#define XD_MOD_SEL		1
-#define SD_MOD_SEL		2
-#define MS_MOD_SEL		3
-#define SPI_MOD_SEL		4
-
-#define CHANGE_CLK		0x01
-
-#define	SD_CRC7_ERR			0x80
-#define	SD_CRC16_ERR			0x40
-#define	SD_CRC_WRITE_ERR		0x20
-#define	SD_CRC_WRITE_ERR_MASK	    	0x1C
-#define	GET_CRC_TIME_OUT		0x02
-#define	SD_TUNING_COMPARE_ERR		0x01
-
-#define	SD_RSP_80CLK_TIMEOUT		0x01
-
-#define	SD_CLK_TOGGLE_EN		0x80
-#define	SD_CLK_FORCE_STOP	        0x40
-#define	SD_DAT3_STATUS		        0x10
-#define	SD_DAT2_STATUS		        0x08
-#define	SD_DAT1_STATUS		        0x04
-#define	SD_DAT0_STATUS		        0x02
-#define	SD_CMD_STATUS			0x01
-
-#define	SD_IO_USING_1V8		        0x80
-#define	SD_IO_USING_3V3		        0x7F
-#define	TYPE_A_DRIVING		        0x00
-#define	TYPE_B_DRIVING			0x01
-#define	TYPE_C_DRIVING			0x02
-#define	TYPE_D_DRIVING		        0x03
-
-#define	DDR_FIX_RX_DAT			0x00
-#define	DDR_VAR_RX_DAT			0x80
-#define	DDR_FIX_RX_DAT_EDGE		0x00
-#define	DDR_FIX_RX_DAT_14_DELAY		0x40
-#define	DDR_FIX_RX_CMD			0x00
-#define	DDR_VAR_RX_CMD			0x20
-#define	DDR_FIX_RX_CMD_POS_EDGE		0x00
-#define	DDR_FIX_RX_CMD_14_DELAY		0x10
-#define	SD20_RX_POS_EDGE		0x00
-#define	SD20_RX_14_DELAY		0x08
-#define SD20_RX_SEL_MASK		0x08
-
-#define	DDR_FIX_TX_CMD_DAT		0x00
-#define	DDR_VAR_TX_CMD_DAT		0x80
-#define	DDR_FIX_TX_DAT_14_TSU		0x00
-#define	DDR_FIX_TX_DAT_12_TSU		0x40
-#define	DDR_FIX_TX_CMD_NEG_EDGE		0x00
-#define	DDR_FIX_TX_CMD_14_AHEAD		0x20
-#define	SD20_TX_NEG_EDGE		0x00
-#define	SD20_TX_14_AHEAD		0x10
-#define SD20_TX_SEL_MASK		0x10
-#define	DDR_VAR_SDCLK_POL_SWAP		0x01
-
-#define	SD_TRANSFER_START		0x80
-#define	SD_TRANSFER_END			0x40
-#define SD_STAT_IDLE			0x20
-#define	SD_TRANSFER_ERR			0x10
-#define	SD_TM_NORMAL_WRITE		0x00
-#define	SD_TM_AUTO_WRITE_3		0x01
-#define	SD_TM_AUTO_WRITE_4		0x02
-#define	SD_TM_AUTO_READ_3		0x05
-#define	SD_TM_AUTO_READ_4		0x06
-#define	SD_TM_CMD_RSP			0x08
-#define	SD_TM_AUTO_WRITE_1		0x09
-#define	SD_TM_AUTO_WRITE_2		0x0A
-#define	SD_TM_NORMAL_READ		0x0C
-#define	SD_TM_AUTO_READ_1		0x0D
-#define	SD_TM_AUTO_READ_2		0x0E
-#define	SD_TM_AUTO_TUNING		0x0F
-
-#define PHASE_CHANGE			0x80
-#define PHASE_NOT_RESET			0x40
-
-#define DCMPS_CHANGE			0x80
-#define DCMPS_CHANGE_DONE	   	0x40
-#define DCMPS_ERROR			0x20
-#define DCMPS_CURRENT_PHASE     	0x1F
-
-#define SD_CLK_DIVIDE_0			0x00
-#define	SD_CLK_DIVIDE_256		0xC0
-#define	SD_CLK_DIVIDE_128		0x80
-#define	SD_BUS_WIDTH_1			0x00
-#define	SD_BUS_WIDTH_4			0x01
-#define	SD_BUS_WIDTH_8			0x02
-#define	SD_ASYNC_FIFO_NOT_RST		0x10
-#define	SD_20_MODE			0x00
-#define	SD_DDR_MODE			0x04
-#define	SD_30_MODE			0x08
-
-#define SD_CLK_DIVIDE_MASK		0xC0
-
-#define SD_CMD_IDLE			0x80
-
-#define SD_DATA_IDLE			0x80
-
-#define DCM_RESET			0x08
-#define DCM_LOCKED			0x04
-#define DCM_208M			0x00
-#define DCM_TX			        0x01
-#define DCM_RX			        0x02
-
-#define DRP_START			0x80
-#define DRP_DONE			0x40
-
-#define DRP_WRITE			0x80
-#define DRP_READ			0x00
-#define DCM_WRITE_ADDRESS_50		0x50
-#define DCM_WRITE_ADDRESS_51		0x51
-#define DCM_READ_ADDRESS_00		0x00
-#define DCM_READ_ADDRESS_51		0x51
-
-#define	SD_CALCULATE_CRC7		0x00
-#define	SD_NO_CALCULATE_CRC7		0x80
-#define	SD_CHECK_CRC16			0x00
-#define	SD_NO_CHECK_CRC16		0x40
-#define SD_NO_CHECK_WAIT_CRC_TO		0x20
-#define	SD_WAIT_BUSY_END		0x08
-#define	SD_NO_WAIT_BUSY_END		0x00
-#define	SD_CHECK_CRC7			0x00
-#define	SD_NO_CHECK_CRC7		0x04
-#define	SD_RSP_LEN_0			0x00
-#define	SD_RSP_LEN_6			0x01
-#define	SD_RSP_LEN_17			0x02
-#define	SD_RSP_TYPE_R0			0x04
-#define	SD_RSP_TYPE_R1			0x01
-#define	SD_RSP_TYPE_R1b			0x09
-#define	SD_RSP_TYPE_R2			0x02
-#define	SD_RSP_TYPE_R3			0x05
-#define	SD_RSP_TYPE_R4			0x05
-#define	SD_RSP_TYPE_R5			0x01
-#define	SD_RSP_TYPE_R6			0x01
-#define	SD_RSP_TYPE_R7			0x01
-
-#define	SD_RSP_80CLK_TIMEOUT_EN	   	0x01
-
-#define	SAMPLE_TIME_RISING		0x00
-#define	SAMPLE_TIME_FALLING		0x80
-#define	PUSH_TIME_DEFAULT		0x00
-#define	PUSH_TIME_ODD			0x40
-#define	NO_EXTEND_TOGGLE		0x00
-#define	EXTEND_TOGGLE_CHK		0x20
-#define	MS_BUS_WIDTH_1			0x00
-#define	MS_BUS_WIDTH_4			0x10
-#define	MS_BUS_WIDTH_8			0x18
-#define	MS_2K_SECTOR_MODE		0x04
-#define	MS_512_SECTOR_MODE		0x00
-#define	MS_TOGGLE_TIMEOUT_EN		0x00
-#define	MS_TOGGLE_TIMEOUT_DISEN		0x01
-#define MS_NO_CHECK_INT			0x02
-
-#define	WAIT_INT			0x80
-#define	NO_WAIT_INT			0x00
-#define	NO_AUTO_READ_INT_REG		0x00
-#define	AUTO_READ_INT_REG		0x40
-#define	MS_CRC16_ERR			0x20
-#define	MS_RDY_TIMEOUT			0x10
-#define	MS_INT_CMDNK			0x08
-#define	MS_INT_BREQ			0x04
-#define	MS_INT_ERR			0x02
-#define	MS_INT_CED			0x01
-
-#define	MS_TRANSFER_START		0x80
-#define	MS_TRANSFER_END			0x40
-#define	MS_TRANSFER_ERR			0x20
-#define	MS_BS_STATE			0x10
-#define	MS_TM_READ_BYTES		0x00
-#define	MS_TM_NORMAL_READ		0x01
-#define	MS_TM_WRITE_BYTES		0x04
-#define	MS_TM_NORMAL_WRITE		0x05
-#define	MS_TM_AUTO_READ			0x08
-#define	MS_TM_AUTO_WRITE		0x0C
-
-#define CARD_SHARE_MASK			0x0F
-#define CARD_SHARE_MULTI_LUN		0x00
-#define	CARD_SHARE_NORMAL		0x00
-#define	CARD_SHARE_48_XD		0x02
-#define	CARD_SHARE_48_SD		0x04
-#define	CARD_SHARE_48_MS		0x08
-#define CARD_SHARE_BAROSSA_XD		0x00
-#define CARD_SHARE_BAROSSA_SD		0x01
-#define CARD_SHARE_BAROSSA_MS		0x02
-
-#define	MS_DRIVE_8			0x00
-#define	MS_DRIVE_4			0x40
-#define	MS_DRIVE_12			0x80
-#define	SD_DRIVE_8			0x00
-#define	SD_DRIVE_4			0x10
-#define	SD_DRIVE_12			0x20
-#define	XD_DRIVE_8			0x00
-#define	XD_DRIVE_4			0x04
-#define	XD_DRIVE_12			0x08
-
-#define SPI_STOP		0x01
-#define XD_STOP			0x02
-#define SD_STOP			0x04
-#define MS_STOP			0x08
-#define SPI_CLR_ERR		0x10
-#define XD_CLR_ERR		0x20
-#define SD_CLR_ERR		0x40
-#define MS_CLR_ERR		0x80
-
-#define CRC_FIX_CLK		(0x00 << 0)
-#define CRC_VAR_CLK0		(0x01 << 0)
-#define CRC_VAR_CLK1		(0x02 << 0)
-#define SD30_FIX_CLK		(0x00 << 2)
-#define SD30_VAR_CLK0		(0x01 << 2)
-#define SD30_VAR_CLK1		(0x02 << 2)
-#define SAMPLE_FIX_CLK		(0x00 << 4)
-#define SAMPLE_VAR_CLK0		(0x01 << 4)
-#define SAMPLE_VAR_CLK1		(0x02 << 4)
-
-#define SDIO_VER_20		0x80
-#define SDIO_VER_10		0x00
-#define SDIO_VER_CHG		0x40
-#define SDIO_BUS_AUTO_SWITCH	0x10
-
-#define PINGPONG_BUFFER		0x01
-#define RING_BUFFER		0x00
-
-#define RB_FLUSH		0x80
-
-#define DMA_DONE_INT_EN			0x80
-#define SUSPEND_INT_EN			0x40
-#define LINK_RDY_INT_EN			0x20
-#define LINK_DOWN_INT_EN		0x10
-
-#define DMA_DONE_INT			0x80
-#define SUSPEND_INT			0x40
-#define LINK_RDY_INT			0x20
-#define LINK_DOWN_INT			0x10
-
-#define MRD_ERR_INT_EN			0x40
-#define MWR_ERR_INT_EN			0x20
-#define SCSI_CMD_INT_EN			0x10
-#define TLP_RCV_INT_EN			0x08
-#define TLP_TRSMT_INT_EN		0x04
-#define MRD_COMPLETE_INT_EN		0x02
-#define MWR_COMPLETE_INT_EN		0x01
-
-#define MRD_ERR_INT			0x40
-#define MWR_ERR_INT			0x20
-#define SCSI_CMD_INT			0x10
-#define TLP_RX_INT			0x08
-#define TLP_TX_INT			0x04
-#define MRD_COMPLETE_INT		0x02
-#define MWR_COMPLETE_INT		0x01
-
-#define MSG_RX_INT_EN			0x08
-#define MRD_RX_INT_EN			0x04
-#define MWR_RX_INT_EN			0x02
-#define CPLD_RX_INT_EN			0x01
-
-#define MSG_RX_INT			0x08
-#define MRD_RX_INT			0x04
-#define MWR_RX_INT			0x02
-#define CPLD_RX_INT			0x01
-
-#define MSG_TX_INT_EN			0x08
-#define MRD_TX_INT_EN			0x04
-#define MWR_TX_INT_EN			0x02
-#define CPLD_TX_INT_EN			0x01
-
-#define MSG_TX_INT			0x08
-#define MRD_TX_INT			0x04
-#define MWR_TX_INT			0x02
-#define CPLD_TX_INT			0x01
-
-#define DMA_RST				0x80
-#define DMA_BUSY			0x04
-#define DMA_DIR_TO_CARD			0x00
-#define DMA_DIR_FROM_CARD		0x02
-#define DMA_EN				0x01
-#define DMA_128				(0 << 4)
-#define DMA_256				(1 << 4)
-#define DMA_512				(2 << 4)
-#define DMA_1024			(3 << 4)
-#define DMA_PACK_SIZE_MASK		0x30
-
-#define	XD_PWR_OFF_DELAY0		0x00
-#define	XD_PWR_OFF_DELAY1		0x02
-#define	XD_PWR_OFF_DELAY2		0x04
-#define	XD_PWR_OFF_DELAY3		0x06
-#define	XD_AUTO_PWR_OFF_EN		0xF7
-#define	XD_NO_AUTO_PWR_OFF		0x08
-
-#define	XD_TIME_RWN_1			0x00
-#define	XD_TIME_RWN_STEP		0x20
-#define	XD_TIME_RW_1			0x00
-#define	XD_TIME_RW_STEP			0x04
-#define	XD_TIME_SETUP_1			0x00
-#define	XD_TIME_SETUP_STEP		0x01
-
-#define	XD_ECC2_UNCORRECTABLE		0x80
-#define	XD_ECC2_ERROR			0x40
-#define	XD_ECC1_UNCORRECTABLE		0x20
-#define	XD_ECC1_ERROR			0x10
-#define	XD_RDY				0x04
-#define	XD_CE_EN			0xFD
-#define	XD_CE_DISEN			0x02
-#define	XD_WP_EN			0xFE
-#define	XD_WP_DISEN			0x01
-
-#define	XD_TRANSFER_START		0x80
-#define	XD_TRANSFER_END			0x40
-#define	XD_PPB_EMPTY			0x20
-#define	XD_RESET			0x00
-#define	XD_ERASE			0x01
-#define	XD_READ_STATUS			0x02
-#define	XD_READ_ID			0x03
-#define	XD_READ_REDUNDANT		0x04
-#define	XD_READ_PAGES			0x05
-#define	XD_SET_CMD			0x06
-#define	XD_NORMAL_READ			0x07
-#define	XD_WRITE_PAGES			0x08
-#define	XD_NORMAL_WRITE			0x09
-#define	XD_WRITE_REDUNDANT		0x0A
-#define	XD_SET_ADDR			0x0B
-
-#define	XD_PPB_TO_SIE			0x80
-#define	XD_TO_PPB_ONLY			0x00
-#define	XD_BA_TRANSFORM			0x40
-#define	XD_BA_NO_TRANSFORM		0x00
-#define	XD_NO_CALC_ECC			0x20
-#define	XD_CALC_ECC			0x00
-#define	XD_IGNORE_ECC			0x10
-#define	XD_CHECK_ECC			0x00
-#define	XD_DIRECT_TO_RB			0x08
-#define	XD_ADDR_LENGTH_0		0x00
-#define	XD_ADDR_LENGTH_1		0x01
-#define	XD_ADDR_LENGTH_2		0x02
-#define	XD_ADDR_LENGTH_3		0x03
-#define	XD_ADDR_LENGTH_4		0x04
-
-#define	XD_GPG				0xFF
-#define	XD_BPG				0x00
-
-#define	XD_GBLK				0xFF
-#define	XD_LATER_BBLK			0xF0
-
-#define	XD_ECC2_ALL1			0x80
-#define	XD_ECC1_ALL1			0x40
-#define	XD_BA2_ALL0			0x20
-#define	XD_BA1_ALL0			0x10
-#define	XD_BA1_BA2_EQL			0x04
-#define	XD_BA2_VALID			0x02
-#define	XD_BA1_VALID			0x01
-
-#define	XD_PGSTS_ZEROBIT_OVER4		0x00
-#define	XD_PGSTS_NOT_FF			0x02
-#define	XD_AUTO_CHK_DATA_STATUS		0x01
-
-#define	RSTB_MODE_DETECT		0x80
-#define	MODE_OUT_VLD			0x40
-#define	MODE_OUT_0_NONE			0x00
-#define	MODE_OUT_10_NONE		0x04
-#define	MODE_OUT_10_47			0x05
-#define	MODE_OUT_10_180			0x06
-#define	MODE_OUT_10_680			0x07
-#define	MODE_OUT_16_NONE		0x08
-#define	MODE_OUT_16_47			0x09
-#define	MODE_OUT_16_180			0x0A
-#define	MODE_OUT_16_680			0x0B
-#define	MODE_OUT_NONE_NONE		0x0C
-#define	MODE_OUT_NONE_47		0x0D
-#define	MODE_OUT_NONE_180		0x0E
-#define	MODE_OUT_NONE_680		0x0F
-
-#define	CARD_OC_INT_EN			0x20
-#define	CARD_DETECT_EN			0x08
-
-#define MS_DETECT_EN			0x80
-#define MS_OCP_INT_EN			0x40
-#define MS_OCP_INT_CLR			0x20
-#define MS_OC_CLR			0x10
-#define SD_DETECT_EN			0x08
-#define SD_OCP_INT_EN			0x04
-#define SD_OCP_INT_CLR			0x02
-#define SD_OC_CLR			0x01
-
-#define	CARD_OCP_DETECT			0x80
-#define	CARD_OC_NOW			0x08
-#define	CARD_OC_EVER			0x04
-
-#define MS_OCP_DETECT			0x80
-#define MS_OC_NOW			0x40
-#define MS_OC_EVER			0x20
-#define SD_OCP_DETECT			0x08
-#define SD_OC_NOW			0x04
-#define SD_OC_EVER			0x02
-
-#define	CARD_OC_INT_CLR			0x08
-#define	CARD_OC_CLR			0x02
-
-#define SD_OCP_GLITCH_MASK		0x07
-#define SD_OCP_GLITCH_6_4		0x00
-#define SD_OCP_GLITCH_64		0x01
-#define SD_OCP_GLITCH_640		0x02
-#define SD_OCP_GLITCH_1000		0x03
-#define SD_OCP_GLITCH_2000		0x04
-#define SD_OCP_GLITCH_4000		0x05
-#define SD_OCP_GLITCH_8000		0x06
-#define SD_OCP_GLITCH_10000		0x07
-
-#define MS_OCP_GLITCH_MASK		0x70
-#define MS_OCP_GLITCH_6_4		(0x00 << 4)
-#define MS_OCP_GLITCH_64		(0x01 << 4)
-#define MS_OCP_GLITCH_640		(0x02 << 4)
-#define MS_OCP_GLITCH_1000		(0x03 << 4)
-#define MS_OCP_GLITCH_2000		(0x04 << 4)
-#define MS_OCP_GLITCH_4000		(0x05 << 4)
-#define MS_OCP_GLITCH_8000		(0x06 << 4)
-#define MS_OCP_GLITCH_10000		(0x07 << 4)
-
-#define OCP_TIME_60			0x00
-#define OCP_TIME_100			(0x01 << 3)
-#define OCP_TIME_200			(0x02 << 3)
-#define OCP_TIME_400			(0x03 << 3)
-#define OCP_TIME_600			(0x04 << 3)
-#define OCP_TIME_800			(0x05 << 3)
-#define OCP_TIME_1100			(0x06 << 3)
-#define OCP_TIME_MASK			0x38
-
-#define MS_OCP_TIME_60			0x00
-#define MS_OCP_TIME_100			(0x01 << 4)
-#define MS_OCP_TIME_200			(0x02 << 4)
-#define MS_OCP_TIME_400			(0x03 << 4)
-#define MS_OCP_TIME_600			(0x04 << 4)
-#define MS_OCP_TIME_800			(0x05 << 4)
-#define MS_OCP_TIME_1100		(0x06 << 4)
-#define MS_OCP_TIME_MASK		0x70
-
-#define SD_OCP_TIME_60			0x00
-#define SD_OCP_TIME_100			0x01
-#define SD_OCP_TIME_200			0x02
-#define SD_OCP_TIME_400			0x03
-#define SD_OCP_TIME_600			0x04
-#define SD_OCP_TIME_800			0x05
-#define SD_OCP_TIME_1100		0x06
-#define SD_OCP_TIME_MASK		0x07
-
-#define OCP_THD_315_417			0x00
-#define OCP_THD_283_783			(0x01 << 6)
-#define OCP_THD_244_946			(0x02 << 6)
-#define OCP_THD_191_1080		(0x03 << 6)
-#define OCP_THD_MASK			0xC0
-
-#define MS_OCP_THD_450			0x00
-#define MS_OCP_THD_550			(0x01 << 4)
-#define MS_OCP_THD_650			(0x02 << 4)
-#define MS_OCP_THD_750			(0x03 << 4)
-#define MS_OCP_THD_850			(0x04 << 4)
-#define MS_OCP_THD_950			(0x05 << 4)
-#define MS_OCP_THD_1050			(0x06 << 4)
-#define MS_OCP_THD_1150			(0x07 << 4)
-#define MS_OCP_THD_MASK			0x70
-
-#define SD_OCP_THD_450			0x00
-#define SD_OCP_THD_550			0x01
-#define SD_OCP_THD_650			0x02
-#define SD_OCP_THD_750			0x03
-#define SD_OCP_THD_850			0x04
-#define SD_OCP_THD_950			0x05
-#define SD_OCP_THD_1050			0x06
-#define SD_OCP_THD_1150			0x07
-#define SD_OCP_THD_MASK			0x07
-
-#define FPGA_MS_PULL_CTL_EN		0xEF
-#define FPGA_SD_PULL_CTL_EN		0xF7
-#define FPGA_XD_PULL_CTL_EN1		0xFE
-#define FPGA_XD_PULL_CTL_EN2		0xFD
-#define FPGA_XD_PULL_CTL_EN3		0xFB
-
-#define FPGA_MS_PULL_CTL_BIT		0x10
-#define FPGA_SD_PULL_CTL_BIT		0x08
-
-#define BLINK_EN			0x08
-#define LED_GPIO0			(0 << 4)
-#define LED_GPIO1			(1 << 4)
-#define LED_GPIO2			(2 << 4)
-
-#define SDIO_BUS_CTRL		0x01
-#define SDIO_CD_CTRL		0x02
-
-#define SSC_RSTB		0x80
-#define SSC_8X_EN		0x40
-#define SSC_FIX_FRAC		0x20
-#define SSC_SEL_1M		0x00
-#define SSC_SEL_2M		0x08
-#define SSC_SEL_4M		0x10
-#define SSC_SEL_8M		0x18
-
-#define SSC_DEPTH_MASK		0x07
-#define SSC_DEPTH_DISALBE	0x00
-#define SSC_DEPTH_4M		0x01
-#define SSC_DEPTH_2M		0x02
-#define SSC_DEPTH_1M		0x03
-#define SSC_DEPTH_512K		0x04
-#define SSC_DEPTH_256K		0x05
-#define SSC_DEPTH_128K		0x06
-#define SSC_DEPTH_64K		0x07
-
-#define XD_D3_NP		0x00
-#define XD_D3_PD		(0x01 << 6)
-#define XD_D3_PU		(0x02 << 6)
-#define XD_D2_NP		0x00
-#define XD_D2_PD		(0x01 << 4)
-#define XD_D2_PU		(0x02 << 4)
-#define XD_D1_NP		0x00
-#define XD_D1_PD		(0x01 << 2)
-#define XD_D1_PU		(0x02 << 2)
-#define XD_D0_NP		0x00
-#define XD_D0_PD		0x01
-#define XD_D0_PU		0x02
-
-#define SD_D7_NP		0x00
-#define SD_D7_PD		(0x01 << 4)
-#define SD_DAT7_PU		(0x02 << 4)
-#define SD_CLK_NP		0x00
-#define SD_CLK_PD		(0x01 << 2)
-#define SD_CLK_PU		(0x02 << 2)
-#define SD_D5_NP		0x00
-#define SD_D5_PD		0x01
-#define SD_D5_PU		0x02
-
-#define MS_D1_NP		0x00
-#define MS_D1_PD		(0x01 << 6)
-#define MS_D1_PU		(0x02 << 6)
-#define MS_D2_NP		0x00
-#define MS_D2_PD		(0x01 << 4)
-#define MS_D2_PU		(0x02 << 4)
-#define MS_CLK_NP		0x00
-#define MS_CLK_PD		(0x01 << 2)
-#define MS_CLK_PU		(0x02 << 2)
-#define MS_D6_NP		0x00
-#define MS_D6_PD		0x01
-#define MS_D6_PU		0x02
-
-#define XD_D7_NP		0x00
-#define XD_D7_PD		(0x01 << 6)
-#define XD_D7_PU		(0x02 << 6)
-#define XD_D6_NP		0x00
-#define XD_D6_PD		(0x01 << 4)
-#define XD_D6_PU		(0x02 << 4)
-#define XD_D5_NP		0x00
-#define XD_D5_PD		(0x01 << 2)
-#define XD_D5_PU		(0x02 << 2)
-#define XD_D4_NP		0x00
-#define XD_D4_PD		0x01
-#define XD_D4_PU		0x02
-
-#define SD_D6_NP		0x00
-#define SD_D6_PD		(0x01 << 6)
-#define SD_D6_PU		(0x02 << 6)
-#define SD_D0_NP		0x00
-#define SD_D0_PD		(0x01 << 4)
-#define SD_D0_PU		(0x02 << 4)
-#define SD_D1_NP		0x00
-#define SD_D1_PD		0x01
-#define SD_D1_PU		0x02
-
-#define MS_D3_NP		0x00
-#define MS_D3_PD		(0x01 << 6)
-#define MS_D3_PU		(0x02 << 6)
-#define MS_D0_NP		0x00
-#define MS_D0_PD		(0x01 << 4)
-#define MS_D0_PU		(0x02 << 4)
-#define MS_BS_NP		0x00
-#define MS_BS_PD		(0x01 << 2)
-#define MS_BS_PU		(0x02 << 2)
-
-#define XD_WP_NP		0x00
-#define XD_WP_PD		(0x01 << 6)
-#define XD_WP_PU		(0x02 << 6)
-#define XD_CE_NP		0x00
-#define XD_CE_PD		(0x01 << 3)
-#define XD_CE_PU		(0x02 << 3)
-#define XD_CLE_NP		0x00
-#define XD_CLE_PD		(0x01 << 1)
-#define XD_CLE_PU		(0x02 << 1)
-#define XD_CD_PD		0x00
-#define XD_CD_PU		0x01
-
-#define SD_D4_NP		0x00
-#define SD_D4_PD		(0x01 << 6)
-#define SD_D4_PU		(0x02 << 6)
-
-#define MS_D7_NP		0x00
-#define MS_D7_PD		(0x01 << 6)
-#define MS_D7_PU		(0x02 << 6)
-
-#define XD_RDY_NP		0x00
-#define XD_RDY_PD		(0x01 << 6)
-#define XD_RDY_PU		(0x02 << 6)
-#define XD_WE_NP		0x00
-#define XD_WE_PD		(0x01 << 4)
-#define XD_WE_PU		(0x02 << 4)
-#define XD_RE_NP		0x00
-#define XD_RE_PD		(0x01 << 2)
-#define XD_RE_PU		(0x02 << 2)
-#define XD_ALE_NP		0x00
-#define XD_ALE_PD		0x01
-#define XD_ALE_PU		0x02
-
-#define SD_D3_NP		0x00
-#define SD_D3_PD		(0x01 << 4)
-#define SD_D3_PU		(0x02 << 4)
-#define SD_D2_NP		0x00
-#define SD_D2_PD		(0x01 << 2)
-#define SD_D2_PU		(0x02 << 2)
-
-#define MS_INS_PD		0x00
-#define MS_INS_PU		(0x01 << 7)
-#define SD_WP_NP		0x00
-#define SD_WP_PD		(0x01 << 5)
-#define SD_WP_PU		(0x02 << 5)
-#define SD_CD_PD		0x00
-#define SD_CD_PU		(0x01 << 4)
-#define SD_CMD_NP		0x00
-#define SD_CMD_PD		(0x01 << 2)
-#define SD_CMD_PU		(0x02 << 2)
-
-#define MS_D5_NP		0x00
-#define MS_D5_PD		(0x01 << 2)
-#define MS_D5_PU		(0x02 << 2)
-#define MS_D4_NP		0x00
-#define MS_D4_PD		0x01
-#define MS_D4_PU		0x02
-
-#define FORCE_PM_CLOCK		0x10
-#define EN_CLOCK_PM		0x01
-
-#define HOST_ENTER_S3		0x02
-#define HOST_ENTER_S1		0x01
-
-#define AUX_PWR_DETECTED	0x01
-
-#define PHY_DEBUG_MODE		0x01
-
-#define SPI_COMMAND_BIT_8	0xE0
-#define SPI_ADDRESS_BIT_24	0x17
-#define SPI_ADDRESS_BIT_32	0x1F
-
-#define SPI_TRANSFER0_START	0x80
-#define SPI_TRANSFER0_END	0x40
-#define SPI_C_MODE0		0x00
-#define SPI_CA_MODE0		0x01
-#define SPI_CDO_MODE0		0x02
-#define SPI_CDI_MODE0		0x03
-#define SPI_CADO_MODE0		0x04
-#define SPI_CADI_MODE0		0x05
-#define SPI_POLLING_MODE0	0x06
-
-#define SPI_TRANSFER1_START	0x80
-#define SPI_TRANSFER1_END	0x40
-#define SPI_DO_MODE1		0x00
-#define SPI_DI_MODE1		0x01
-
-#define CS_POLARITY_HIGH	0x40
-#define CS_POLARITY_LOW		0x00
-#define DTO_MSB_FIRST		0x00
-#define DTO_LSB_FIRST		0x20
-#define SPI_MASTER		0x00
-#define SPI_SLAVE		0x10
-#define SPI_MODE0		0x00
-#define SPI_MODE1		0x04
-#define SPI_MODE2		0x08
-#define SPI_MODE3		0x0C
-#define SPI_MANUAL		0x00
-#define SPI_HALF_AUTO		0x01
-#define SPI_AUTO		0x02
-#define SPI_EEPROM_AUTO		0x03
-
-#define EDO_TIMING_MASK		0x03
-#define SAMPLE_RISING		0x00
-#define SAMPLE_DELAY_HALF	0x01
-#define SAMPLE_DELAY_ONE	0x02
-#define SAPMLE_DELAY_ONE_HALF	0x03
-#define TCS_MASK		0x0C
-
-#define NOT_BYPASS_SD		0x02
-#define DISABLE_SDIO_FUNC	0x04
-#define SELECT_1LUN		0x08
-
-#define PWR_GATE_EN		0x01
-#define LDO3318_PWR_MASK	0x06
-#define LDO_ON			0x00
-#define LDO_SUSPEND		0x04
-#define LDO_OFF			0x06
-
-#define SD_CFG1			0xFDA0
-#define SD_CFG2			0xFDA1
-#define SD_CFG3			0xFDA2
-#define SD_STAT1		0xFDA3
-#define SD_STAT2		0xFDA4
-#define SD_BUS_STAT		0xFDA5
-#define SD_PAD_CTL		0xFDA6
-#define SD_SAMPLE_POINT_CTL	0xFDA7
-#define SD_PUSH_POINT_CTL	0xFDA8
-#define SD_CMD0			0xFDA9
-#define SD_CMD1			0xFDAA
-#define SD_CMD2			0xFDAB
-#define SD_CMD3			0xFDAC
-#define SD_CMD4			0xFDAD
-#define SD_CMD5			0xFDAE
-#define SD_BYTE_CNT_L		0xFDAF
-#define SD_BYTE_CNT_H		0xFDB0
-#define SD_BLOCK_CNT_L		0xFDB1
-#define SD_BLOCK_CNT_H		0xFDB2
-#define SD_TRANSFER		0xFDB3
-#define SD_CMD_STATE		0xFDB5
-#define SD_DATA_STATE		0xFDB6
-
-#define	DCM_DRP_CTL         	0xFC23
-#define	DCM_DRP_TRIG		0xFC24
-#define	DCM_DRP_CFG         	0xFC25
-#define	DCM_DRP_WR_DATA_L   	0xFC26
-#define	DCM_DRP_WR_DATA_H   	0xFC27
-#define	DCM_DRP_RD_DATA_L   	0xFC28
-#define	DCM_DRP_RD_DATA_H   	0xFC29
-#define SD_VPCLK0_CTL		0xFC2A
-#define SD_VPCLK1_CTL		0xFC2B
-#define SD_DCMPS0_CTL		0xFC2C
-#define SD_DCMPS1_CTL		0xFC2D
-#define SD_VPTX_CTL		SD_VPCLK0_CTL
-#define SD_VPRX_CTL		SD_VPCLK1_CTL
-#define SD_DCMPS_TX_CTL		SD_DCMPS0_CTL
-#define SD_DCMPS_RX_CTL		SD_DCMPS1_CTL
-
-#define CARD_CLK_SOURCE		0xFC2E
-
-#define CARD_PWR_CTL		0xFD50
-#define CARD_CLK_SWITCH		0xFD51
-#define CARD_SHARE_MODE		0xFD52
-#define CARD_DRIVE_SEL		0xFD53
-#define CARD_STOP		0xFD54
-#define CARD_OE			0xFD55
-#define CARD_AUTO_BLINK		0xFD56
-#define CARD_GPIO_DIR		0xFD57
-#define CARD_GPIO		0xFD58
-
-#define CARD_DATA_SOURCE	0xFD5B
-#define CARD_SELECT		0xFD5C
-#define SD30_DRIVE_SEL		0xFD5E
-
-#define CARD_CLK_EN		0xFD69
-
-#define SDIO_CTRL		0xFD6B
-
-#define FPDCTL			0xFC00
-#define PDINFO			0xFC01
-
-#define CLK_CTL			0xFC02
-#define CLK_DIV			0xFC03
-#define CLK_SEL			0xFC04
-
-#define SSC_DIV_N_0		0xFC0F
-#define SSC_DIV_N_1		0xFC10
-
-#define RCCTL			0xFC14
-
-#define FPGA_PULL_CTL		0xFC1D
-
-#define CARD_PULL_CTL1		0xFD60
-#define CARD_PULL_CTL2		0xFD61
-#define CARD_PULL_CTL3		0xFD62
-#define CARD_PULL_CTL4		0xFD63
-#define CARD_PULL_CTL5		0xFD64
-#define CARD_PULL_CTL6		0xFD65
-
-#define IRQEN0				0xFE20
-#define IRQSTAT0			0xFE21
-#define IRQEN1				0xFE22
-#define IRQSTAT1			0xFE23
-#define TLPRIEN				0xFE24
-#define TLPRISTAT			0xFE25
-#define TLPTIEN				0xFE26
-#define TLPTISTAT			0xFE27
-#define DMATC0				0xFE28
-#define DMATC1				0xFE29
-#define DMATC2				0xFE2A
-#define DMATC3				0xFE2B
-#define DMACTL				0xFE2C
-#define BCTL				0xFE2D
-#define RBBC0				0xFE2E
-#define RBBC1				0xFE2F
-#define RBDAT				0xFE30
-#define RBCTL				0xFE34
-#define CFGADDR0			0xFE35
-#define CFGADDR1			0xFE36
-#define CFGDATA0			0xFE37
-#define CFGDATA1			0xFE38
-#define CFGDATA2			0xFE39
-#define CFGDATA3			0xFE3A
-#define CFGRWCTL			0xFE3B
-#define PHYRWCTL			0xFE3C
-#define PHYDATA0			0xFE3D
-#define PHYDATA1			0xFE3E
-#define PHYADDR				0xFE3F
-#define MSGRXDATA0			0xFE40
-#define MSGRXDATA1			0xFE41
-#define MSGRXDATA2			0xFE42
-#define MSGRXDATA3			0xFE43
-#define MSGTXDATA0			0xFE44
-#define MSGTXDATA1			0xFE45
-#define MSGTXDATA2			0xFE46
-#define MSGTXDATA3			0xFE47
-#define MSGTXCTL			0xFE48
-#define PETXCFG				0xFE49
-
-#define CDRESUMECTL			0xFE52
-#define WAKE_SEL_CTL			0xFE54
-#define PME_FORCE_CTL			0xFE56
-#define ASPM_FORCE_CTL			0xFE57
-#define PM_CLK_FORCE_CTL		0xFE58
-#define PERST_GLITCH_WIDTH		0xFE5C
-#define CHANGE_LINK_STATE		0xFE5B
-#define RESET_LOAD_REG			0xFE5E
-#define HOST_SLEEP_STATE		0xFE60
-#define MAIN_PWR_OFF_CTL		0xFE70	/* RTS5208 */
-#define SDIO_CFG			0xFE70	/* RTS5209 */
-
-#define NFTS_TX_CTRL			0xFE72
-
-#define PWR_GATE_CTRL			0xFE75
-#define PWD_SUSPEND_EN			0xFE76
-
-#define EFUSE_CONTENT			0xFE5F
-
-#define XD_INIT				0xFD10
-#define XD_DTCTL			0xFD11
-#define XD_CTL				0xFD12
-#define XD_TRANSFER			0xFD13
-#define XD_CFG				0xFD14
-#define XD_ADDRESS0			0xFD15
-#define XD_ADDRESS1			0xFD16
-#define XD_ADDRESS2			0xFD17
-#define XD_ADDRESS3			0xFD18
-#define XD_ADDRESS4			0xFD19
-#define XD_DAT				0xFD1A
-#define XD_PAGE_CNT			0xFD1B
-#define XD_PAGE_STATUS			0xFD1C
-#define XD_BLOCK_STATUS			0xFD1D
-#define XD_BLOCK_ADDR1_L		0xFD1E
-#define XD_BLOCK_ADDR1_H		0xFD1F
-#define XD_BLOCK_ADDR2_L		0xFD20
-#define XD_BLOCK_ADDR2_H		0xFD21
-#define XD_BYTE_CNT_L			0xFD22
-#define XD_BYTE_CNT_H			0xFD23
-#define	XD_PARITY			0xFD24
-#define XD_ECC_BIT1			0xFD25
-#define XD_ECC_BYTE1			0xFD26
-#define XD_ECC_BIT2			0xFD27
-#define XD_ECC_BYTE2			0xFD28
-#define XD_RESERVED0			0xFD29
-#define XD_RESERVED1			0xFD2A
-#define XD_RESERVED2			0xFD2B
-#define XD_RESERVED3			0xFD2C
-#define XD_CHK_DATA_STATUS		0xFD2D
-#define XD_CATCTL			0xFD2E
-
-#define MS_CFG				0xFD40
-#define MS_TPC				0xFD41
-#define MS_TRANS_CFG			0xFD42
-#define MS_TRANSFER			0xFD43
-#define MS_INT_REG			0xFD44
-#define MS_BYTE_CNT			0xFD45
-#define MS_SECTOR_CNT_L			0xFD46
-#define MS_SECTOR_CNT_H			0xFD47
-#define MS_DBUS_H			0xFD48
-
-#define SSC_CTL1			0xFC11
-#define SSC_CTL2			0xFC12
-
-#define OCPCTL				0xFC15
-#define OCPSTAT				0xFC16
-#define OCPCLR				0xFC17	/* 5208 */
-#define OCPGLITCH			0xFC17	/* 5209 */
-#define OCPPARA1			0xFC18
-#define OCPPARA2			0xFC19
-
-#define EFUSE_OP			0xFC20
-#define EFUSE_CTRL			0xFC21
-#define EFUSE_DATA			0xFC22
-
-#define	SPI_COMMAND			0xFD80
-#define	SPI_ADDR0			0xFD81
-#define	SPI_ADDR1			0xFD82
-#define	SPI_ADDR2			0xFD83
-#define	SPI_ADDR3			0xFD84
-#define	SPI_CA_NUMBER			0xFD85
-#define	SPI_LENGTH0			0xFD86
-#define	SPI_LENGTH1			0xFD87
-#define	SPI_DATA			0xFD88
-#define SPI_DATA_NUMBER			0xFD89
-#define	SPI_TRANSFER0			0xFD90
-#define	SPI_TRANSFER1			0xFD91
-#define	SPI_CONTROL			0xFD92
-#define	SPI_SIG				0xFD93
-#define	SPI_TCTL			0xFD94
-#define	SPI_SLAVE_NUM			0xFD95
-#define	SPI_CLK_DIVIDER0		0xFD96
-#define	SPI_CLK_DIVIDER1		0xFD97
-
-#define SRAM_BASE			0xE600
-#define RBUF_BASE			0xF400
-#define PPBUF_BASE1			0xF800
-#define PPBUF_BASE2			0xFA00
-#define IMAGE_FLAG_ADDR0		0xCE80
-#define IMAGE_FLAG_ADDR1		0xCE81
-
-#define READ_OP			1
-#define WRITE_OP		2
-
-#define LCTLR		0x80
-
-#define POLLING_WAIT_CNT	1
-#define IDLE_MAX_COUNT		10
-#define SDIO_IDLE_COUNT		10
-
-#define DEBOUNCE_CNT			5
-
-void do_remaining_work(struct rtsx_chip *chip);
-void try_to_switch_sdio_ctrl(struct rtsx_chip *chip);
-void do_reset_sd_card(struct rtsx_chip *chip);
-void do_reset_xd_card(struct rtsx_chip *chip);
-void do_reset_ms_card(struct rtsx_chip *chip);
-void rtsx_power_off_card(struct rtsx_chip *chip);
-void rtsx_release_cards(struct rtsx_chip *chip);
-void rtsx_reset_cards(struct rtsx_chip *chip);
-void rtsx_reinit_cards(struct rtsx_chip *chip, int reset_chip);
-void rtsx_init_cards(struct rtsx_chip *chip);
-int switch_ssc_clock(struct rtsx_chip *chip, int clk);
-int switch_normal_clock(struct rtsx_chip *chip, int clk);
-int enable_card_clock(struct rtsx_chip *chip, u8 card);
-int disable_card_clock(struct rtsx_chip *chip, u8 card);
-int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 sec_addr, u16 sec_cnt);
-void trans_dma_enable(enum dma_data_direction dir, struct rtsx_chip *chip, u32 byte_cnt, u8 pack_size);
-void toggle_gpio(struct rtsx_chip *chip, u8 gpio);
-void turn_on_led(struct rtsx_chip *chip, u8 gpio);
-void turn_off_led(struct rtsx_chip *chip, u8 gpio);
-
-int card_share_mode(struct rtsx_chip *chip, int card);
-int select_card(struct rtsx_chip *chip, int card);
-int detect_card_cd(struct rtsx_chip *chip, int card);
-int check_card_exist(struct rtsx_chip *chip, unsigned int lun);
-int check_card_ready(struct rtsx_chip *chip, unsigned int lun);
-int check_card_wp(struct rtsx_chip *chip, unsigned int lun);
-int check_card_fail(struct rtsx_chip *chip, unsigned int lun);
-int check_card_ejected(struct rtsx_chip *chip, unsigned int lun);
-void eject_card(struct rtsx_chip *chip, unsigned int lun);
-u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun);
-
-static inline u32 get_card_size(struct rtsx_chip *chip, unsigned int lun)
-{
-#ifdef SUPPORT_SD_LOCK
-	struct sd_info *sd_card = &(chip->sd_card);
-
-	if ((get_lun_card(chip, lun) == SD_CARD) && (sd_card->sd_lock_status & SD_LOCKED))
-		return 0;
-	else
-		return chip->capacity[lun];
-#else
-	return chip->capacity[lun];
-#endif
-}
-
-static inline int switch_clock(struct rtsx_chip *chip, int clk)
-{
-	int retval = 0;
-
-	if (chip->asic_code)
-		retval = switch_ssc_clock(chip, clk);
-	else
-		retval = switch_normal_clock(chip, clk);
-
-	return retval;
-}
-
-int card_power_on(struct rtsx_chip *chip, u8 card);
-int card_power_off(struct rtsx_chip *chip, u8 card);
-
-static inline int card_power_off_all(struct rtsx_chip *chip)
-{
-	RTSX_WRITE_REG(chip, CARD_PWR_CTL, 0x0F, 0x0F);
-
-	return STATUS_SUCCESS;
-}
-
-static inline void rtsx_clear_xd_error(struct rtsx_chip *chip)
-{
-	rtsx_write_register(chip, CARD_STOP, XD_STOP | XD_CLR_ERR, XD_STOP | XD_CLR_ERR);
-}
-
-static inline void rtsx_clear_sd_error(struct rtsx_chip *chip)
-{
-	rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, SD_STOP | SD_CLR_ERR);
-}
-
-static inline void rtsx_clear_ms_error(struct rtsx_chip *chip)
-{
-	rtsx_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR);
-}
-
-static inline void rtsx_clear_spi_error(struct rtsx_chip *chip)
-{
-	rtsx_write_register(chip, CARD_STOP, SPI_STOP | SPI_CLR_ERR, SPI_STOP | SPI_CLR_ERR);
-}
-
-#ifdef SUPPORT_SDIO_ASPM
-void dynamic_configure_sdio_aspm(struct rtsx_chip *chip);
-#endif
-
-#endif  /* __REALTEK_RTSX_CARD_H */
diff --git a/drivers/staging/rts_pstor/rtsx_chip.c b/drivers/staging/rts_pstor/rtsx_chip.c
deleted file mode 100644
index d8e691b..0000000
--- a/drivers/staging/rts_pstor/rtsx_chip.c
+++ /dev/null
@@ -1,2264 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/vmalloc.h>
-
-#include "rtsx.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
-#include "rtsx_chip.h"
-#include "rtsx_sys.h"
-#include "general.h"
-
-#include "sd.h"
-#include "xd.h"
-#include "ms.h"
-
-static void rtsx_calibration(struct rtsx_chip *chip)
-{
-	rtsx_write_phy_register(chip, 0x1B, 0x135E);
-	wait_timeout(10);
-	rtsx_write_phy_register(chip, 0x00, 0x0280);
-	rtsx_write_phy_register(chip, 0x01, 0x7112);
-	rtsx_write_phy_register(chip, 0x01, 0x7110);
-	rtsx_write_phy_register(chip, 0x01, 0x7112);
-	rtsx_write_phy_register(chip, 0x01, 0x7113);
-	rtsx_write_phy_register(chip, 0x00, 0x0288);
-}
-
-void rtsx_disable_card_int(struct rtsx_chip *chip)
-{
-	u32 reg = rtsx_readl(chip, RTSX_BIER);
-
-	reg &= ~(XD_INT_EN | SD_INT_EN | MS_INT_EN);
-	rtsx_writel(chip, RTSX_BIER, reg);
-}
-
-void rtsx_enable_card_int(struct rtsx_chip *chip)
-{
-	u32 reg = rtsx_readl(chip, RTSX_BIER);
-	int i;
-
-	for (i = 0; i <= chip->max_lun; i++) {
-		if (chip->lun2card[i] & XD_CARD)
-			reg |= XD_INT_EN;
-		if (chip->lun2card[i] & SD_CARD)
-			reg |= SD_INT_EN;
-		if (chip->lun2card[i] & MS_CARD)
-			reg |= MS_INT_EN;
-	}
-	if (chip->hw_bypass_sd)
-		reg &= ~((u32)SD_INT_EN);
-
-	rtsx_writel(chip, RTSX_BIER, reg);
-}
-
-void rtsx_enable_bus_int(struct rtsx_chip *chip)
-{
-	u32 reg = 0;
-#ifndef DISABLE_CARD_INT
-	int i;
-#endif
-
-	reg = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN;
-
-#ifndef DISABLE_CARD_INT
-	for (i = 0; i <= chip->max_lun; i++) {
-		RTSX_DEBUGP("lun2card[%d] = 0x%02x\n", i, chip->lun2card[i]);
-
-		if (chip->lun2card[i] & XD_CARD)
-			reg |= XD_INT_EN;
-		if (chip->lun2card[i] & SD_CARD)
-			reg |= SD_INT_EN;
-		if (chip->lun2card[i] & MS_CARD)
-			reg |= MS_INT_EN;
-	}
-	if (chip->hw_bypass_sd)
-		reg &= ~((u32)SD_INT_EN);
-#endif
-
-	if (chip->ic_version >= IC_VER_C)
-		reg |= DELINK_INT_EN;
-#ifdef SUPPORT_OCP
-	if (CHECK_PID(chip, 0x5209)) {
-		if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
-			reg |= MS_OC_INT_EN | SD_OC_INT_EN;
-		else
-			reg |= SD_OC_INT_EN;
-	} else {
-		reg |= OC_INT_EN;
-	}
-#endif
-	if (!chip->adma_mode)
-		reg |= DATA_DONE_INT_EN;
-
-	/* Enable Bus Interrupt */
-	rtsx_writel(chip, RTSX_BIER, reg);
-
-	RTSX_DEBUGP("RTSX_BIER: 0x%08x\n", reg);
-}
-
-void rtsx_disable_bus_int(struct rtsx_chip *chip)
-{
-	rtsx_writel(chip, RTSX_BIER, 0);
-}
-
-static int rtsx_pre_handle_sdio_old(struct rtsx_chip *chip)
-{
-	if (chip->ignore_sd && CHK_SDIO_EXIST(chip)) {
-		if (chip->asic_code) {
-			RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF,
-				MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU);
-		} else {
-			RTSX_WRITE_REG(chip, FPGA_PULL_CTL, 0xFF, FPGA_SD_PULL_CTL_EN);
-		}
-		RTSX_WRITE_REG(chip, CARD_SHARE_MODE, 0xFF, CARD_SHARE_48_SD);
-
-		/* Enable SDIO internal clock */
-		RTSX_WRITE_REG(chip, 0xFF2C, 0x01, 0x01);
-
-		RTSX_WRITE_REG(chip, SDIO_CTRL, 0xFF, SDIO_BUS_CTRL | SDIO_CD_CTRL);
-
-		chip->sd_int = 1;
-		chip->sd_io = 1;
-	} else {
-		chip->need_reset |= SD_CARD;
-	}
-
-	return STATUS_SUCCESS;
-}
-
-#ifdef HW_AUTO_SWITCH_SD_BUS
-static int rtsx_pre_handle_sdio_new(struct rtsx_chip *chip)
-{
-	u8 tmp;
-	int sw_bypass_sd = 0;
-	int retval;
-
-	if (chip->driver_first_load) {
-		if (CHECK_PID(chip, 0x5288)) {
-			RTSX_READ_REG(chip, 0xFE5A, &tmp);
-			if (tmp & 0x08)
-				sw_bypass_sd = 1;
-		} else if (CHECK_PID(chip, 0x5208)) {
-			RTSX_READ_REG(chip, 0xFE70, &tmp);
-			if (tmp & 0x80)
-				sw_bypass_sd = 1;
-		} else if (CHECK_PID(chip, 0x5209)) {
-			RTSX_READ_REG(chip, SDIO_CFG, &tmp);
-			if (tmp & SDIO_BUS_AUTO_SWITCH)
-				sw_bypass_sd = 1;
-		}
-	} else {
-		if (chip->sdio_in_charge)
-			sw_bypass_sd = 1;
-	}
-	RTSX_DEBUGP("chip->sdio_in_charge = %d\n", chip->sdio_in_charge);
-	RTSX_DEBUGP("chip->driver_first_load = %d\n", chip->driver_first_load);
-	RTSX_DEBUGP("sw_bypass_sd = %d\n", sw_bypass_sd);
-
-	if (sw_bypass_sd) {
-		u8 cd_toggle_mask = 0;
-
-		RTSX_READ_REG(chip, TLPTISTAT, &tmp);
-		if (CHECK_PID(chip, 0x5209))
-			cd_toggle_mask = 0x10;
-		else
-			cd_toggle_mask = 0x08;
-
-		if (tmp & cd_toggle_mask) {
-			/* Disable sdio_bus_auto_switch */
-			if (CHECK_PID(chip, 0x5288))
-				RTSX_WRITE_REG(chip, 0xFE5A, 0x08, 0x00);
-			else if (CHECK_PID(chip, 0x5208))
-				RTSX_WRITE_REG(chip, 0xFE70, 0x80, 0x00);
-			else
-				RTSX_WRITE_REG(chip, SDIO_CFG, SDIO_BUS_AUTO_SWITCH, 0);
-
-			RTSX_WRITE_REG(chip, TLPTISTAT, 0xFF, tmp);
-
-			chip->need_reset |= SD_CARD;
-		} else {
-			RTSX_DEBUGP("Chip inserted with SDIO!\n");
-
-			if (chip->asic_code) {
-				retval = sd_pull_ctl_enable(chip);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-			} else {
-				RTSX_WRITE_REG(chip, FPGA_PULL_CTL, FPGA_SD_PULL_CTL_BIT | 0x20, 0);
-			}
-			retval = card_share_mode(chip, SD_CARD);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-
-			/* Enable sdio_bus_auto_switch */
-			if (CHECK_PID(chip, 0x5288)) {
-				RTSX_WRITE_REG(chip, 0xFE5A, 0x08, 0x08);
-			} else if (CHECK_PID(chip, 0x5208)) {
-				RTSX_WRITE_REG(chip, 0xFE70, 0x80, 0x80);
-			} else {
-				RTSX_WRITE_REG(chip, SDIO_CFG,
-					SDIO_BUS_AUTO_SWITCH, SDIO_BUS_AUTO_SWITCH);
-			}
-			chip->chip_insert_with_sdio = 1;
-			chip->sd_io = 1;
-		}
-	} else {
-		if (CHECK_PID(chip, 0x5209))
-			RTSX_WRITE_REG(chip, TLPTISTAT, 0x10, 0x10);
-		else
-			RTSX_WRITE_REG(chip, TLPTISTAT, 0x08, 0x08);
-
-		chip->need_reset |= SD_CARD;
-	}
-
-	return STATUS_SUCCESS;
-}
-#endif
-
-int rtsx_reset_chip(struct rtsx_chip *chip)
-{
-	int retval;
-
-	rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr);
-
-	rtsx_disable_aspm(chip);
-
-	if (CHECK_PID(chip, 0x5209) && chip->asic_code) {
-		u16 val;
-
-		/* optimize PHY */
-		retval = rtsx_write_phy_register(chip, 0x00, 0xB966);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = rtsx_write_phy_register(chip, 0x01, 0x713F);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = rtsx_write_phy_register(chip, 0x03, 0xA549);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = rtsx_write_phy_register(chip, 0x06, 0xB235);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = rtsx_write_phy_register(chip, 0x07, 0xEF40);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = rtsx_write_phy_register(chip, 0x1E, 0xF8EB);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = rtsx_write_phy_register(chip, 0x19, 0xFE6C);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		wait_timeout(1);
-		retval = rtsx_write_phy_register(chip, 0x0A, 0x05C0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-
-		retval = rtsx_write_cfg_dw(chip, 1, 0x110, 0xFFFF, 0xFFFF);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = rtsx_read_phy_register(chip, 0x08, &val);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		RTSX_DEBUGP("Read from phy 0x08: 0x%04x\n", val);
-
-		if (chip->phy_voltage) {
-			chip->phy_voltage &= 0x3F;
-			RTSX_DEBUGP("chip->phy_voltage = 0x%x\n", chip->phy_voltage);
-			val &= ~0x3F;
-			val |= chip->phy_voltage;
-			RTSX_DEBUGP("Write to phy 0x08: 0x%04x\n", val);
-			retval = rtsx_write_phy_register(chip, 0x08, val);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-
-		} else {
-			chip->phy_voltage = (u8)(val & 0x3F);
-			RTSX_DEBUGP("Default, chip->phy_voltage = 0x%x\n", chip->phy_voltage);
-		}
-	}
-
-	RTSX_WRITE_REG(chip, HOST_SLEEP_STATE, 0x03, 0x00);
-
-	/* Disable card clock */
-	RTSX_WRITE_REG(chip, CARD_CLK_EN, 0x1E, 0);
-
-#ifdef SUPPORT_OCP
-	/* SSC power on, OCD power on */
-	if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
-		RTSX_WRITE_REG(chip, FPDCTL, OC_POWER_DOWN, 0);
-	else
-		RTSX_WRITE_REG(chip, FPDCTL, OC_POWER_DOWN, MS_OC_POWER_DOWN);
-
-	if (CHECK_PID(chip, 0x5209)) {
-		RTSX_WRITE_REG(chip, OCPPARA1, SD_OCP_TIME_MASK | MS_OCP_TIME_MASK,
-				    SD_OCP_TIME_800 | MS_OCP_TIME_800);
-		RTSX_WRITE_REG(chip, OCPPARA2, SD_OCP_THD_MASK | MS_OCP_THD_MASK,
-				    chip->sd_400mA_ocp_thd | (chip->ms_ocp_thd << 4));
-		if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
-			RTSX_WRITE_REG(chip, OCPGLITCH, SD_OCP_GLITCH_MASK | MS_OCP_GLITCH_MASK,
-				       SD_OCP_GLITCH_10000 | MS_OCP_GLITCH_10000);
-		} else {
-			RTSX_WRITE_REG(chip, OCPGLITCH, SD_OCP_GLITCH_MASK, SD_OCP_GLITCH_10000);
-		}
-		RTSX_WRITE_REG(chip, OCPCTL, 0xFF,
-				    SD_OCP_INT_EN | SD_DETECT_EN | MS_OCP_INT_EN | MS_DETECT_EN);
-	} else {
-		RTSX_WRITE_REG(chip, OCPPARA1, OCP_TIME_MASK, OCP_TIME_800);
-		RTSX_WRITE_REG(chip, OCPPARA2, OCP_THD_MASK, OCP_THD_244_946);
-		RTSX_WRITE_REG(chip, OCPCTL, 0xFF, CARD_OC_INT_EN | CARD_DETECT_EN);
-	}
-#else
-	/* OC power down */
-	RTSX_WRITE_REG(chip, FPDCTL, OC_POWER_DOWN, OC_POWER_DOWN);
-#endif
-
-	if (!CHECK_PID(chip, 0x5288))
-		RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0xFF, 0x03);
-
-	/* Turn off LED */
-	RTSX_WRITE_REG(chip, CARD_GPIO, 0xFF, 0x03);
-
-	/* Reset delink mode */
-	RTSX_WRITE_REG(chip, CHANGE_LINK_STATE, 0x0A, 0);
-
-	/* Card driving select */
-	RTSX_WRITE_REG(chip, CARD_DRIVE_SEL, 0xFF, chip->card_drive_sel);
-	if (CHECK_PID(chip, 0x5209))
-		RTSX_WRITE_REG(chip, SD30_DRIVE_SEL, 0x07, chip->sd30_drive_sel_3v3);
-
-#ifdef LED_AUTO_BLINK
-	RTSX_WRITE_REG(chip, CARD_AUTO_BLINK, 0xFF,
-			LED_BLINK_SPEED | BLINK_EN | LED_GPIO0);
-#endif
-
-	if (chip->asic_code) {
-		/* Enable SSC Clock */
-		RTSX_WRITE_REG(chip, SSC_CTL1, 0xFF, SSC_8X_EN | SSC_SEL_4M);
-		RTSX_WRITE_REG(chip, SSC_CTL2, 0xFF, 0x12);
-	}
-
-	/* Disable cd_pwr_save (u_force_rst_core_en=0, u_cd_rst_core_en=0)
-	      0xFE5B
-	      bit[1]    u_cd_rst_core_en    	rst_value = 0
-	      bit[2]    u_force_rst_core_en 	rst_value = 0
-	      bit[5]    u_mac_phy_rst_n_dbg 	rst_value = 1
-	      bit[4]	u_non_sticky_rst_n_dbg	rst_value = 0
-	*/
-	RTSX_WRITE_REG(chip, CHANGE_LINK_STATE, 0x16, 0x10);
-
-	/* Enable ASPM */
-	if (chip->aspm_l0s_l1_en) {
-		if (chip->dynamic_aspm) {
-			if (CHK_SDIO_EXIST(chip)) {
-				if (CHECK_PID(chip, 0x5209)) {
-					retval = rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFF, chip->aspm_l0s_l1_en);
-					if (retval != STATUS_SUCCESS)
-						TRACE_RET(chip, STATUS_FAIL);
-
-				} else if (CHECK_PID(chip, 0x5288)) {
-					retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF, chip->aspm_l0s_l1_en);
-					if (retval != STATUS_SUCCESS)
-						TRACE_RET(chip, STATUS_FAIL);
-				}
-			}
-		} else {
-			if (CHECK_PID(chip, 0x5208))
-				RTSX_WRITE_REG(chip, ASPM_FORCE_CTL, 0xFF, 0x3F);
-
-			retval = rtsx_write_config_byte(chip, LCTLR, chip->aspm_l0s_l1_en);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-
-			chip->aspm_level[0] = chip->aspm_l0s_l1_en;
-			if (CHK_SDIO_EXIST(chip)) {
-				chip->aspm_level[1] = chip->aspm_l0s_l1_en;
-				if (CHECK_PID(chip, 0x5288))
-					retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF, chip->aspm_l0s_l1_en);
-				else
-					retval = rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFF, chip->aspm_l0s_l1_en);
-
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-
-			}
-
-			chip->aspm_enabled = 1;
-		}
-	} else {
-		if (chip->asic_code && CHECK_PID(chip, 0x5208)) {
-			retval = rtsx_write_phy_register(chip, 0x07, 0x0129);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-		}
-		retval = rtsx_write_config_byte(chip, LCTLR, chip->aspm_l0s_l1_en);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	retval = rtsx_write_config_byte(chip, 0x81, 1);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (CHK_SDIO_EXIST(chip)) {
-		if (CHECK_PID(chip, 0x5288))
-			retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF00, 0x0100);
-		else
-			retval = rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFF00, 0x0100);
-
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-	}
-
-	if (CHECK_PID(chip, 0x5209)) {
-		retval = rtsx_write_cfg_dw(chip, 0, 0x70C, 0xFF000000, 0x5B);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (CHECK_PID(chip, 0x5288)) {
-		if (!CHK_SDIO_EXIST(chip)) {
-			retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFFFF, 0x0103);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-
-			retval = rtsx_write_cfg_dw(chip, 2, 0x84, 0xFF, 0x03);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-
-		}
-	}
-
-	RTSX_WRITE_REG(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT);
-
-	RTSX_WRITE_REG(chip, PERST_GLITCH_WIDTH, 0xFF, 0x80);
-
-	if (CHECK_PID(chip, 0x5209)) {
-		RTSX_WRITE_REG(chip, PWD_SUSPEND_EN, 0xFF, 0xFF);
-		RTSX_WRITE_REG(chip, PWR_GATE_CTRL, PWR_GATE_EN, PWR_GATE_EN);
-	}
-
-	/* Enable PCIE interrupt */
-	if (chip->asic_code) {
-		if (CHECK_PID(chip, 0x5208)) {
-			if (chip->phy_debug_mode) {
-				RTSX_WRITE_REG(chip, CDRESUMECTL, 0x77, 0);
-				rtsx_disable_bus_int(chip);
-			} else {
-				rtsx_enable_bus_int(chip);
-			}
-
-			if (chip->ic_version >= IC_VER_D) {
-				u16 reg;
-				retval = rtsx_read_phy_register(chip, 0x00, &reg);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-
-				reg &= 0xFE7F;
-				reg |= 0x80;
-				retval = rtsx_write_phy_register(chip, 0x00, reg);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-
-				retval = rtsx_read_phy_register(chip, 0x1C, &reg);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-
-				reg &= 0xFFF7;
-				retval = rtsx_write_phy_register(chip, 0x1C, reg);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-
-			}
-
-			if (chip->driver_first_load && (chip->ic_version < IC_VER_C))
-				rtsx_calibration(chip);
-
-		} else {
-			rtsx_enable_bus_int(chip);
-		}
-	} else {
-		rtsx_enable_bus_int(chip);
-	}
-
-#ifdef HW_INT_WRITE_CLR
-	if (CHECK_PID(chip, 0x5209)) {
-		/* Set interrupt write clear */
-		RTSX_WRITE_REG(chip, NFTS_TX_CTRL, 0x02, 0);
-	}
-#endif
-
-	chip->need_reset = 0;
-
-	chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-#ifdef HW_INT_WRITE_CLR
-	if (CHECK_PID(chip, 0x5209)) {
-		/* Clear interrupt flag */
-		rtsx_writel(chip, RTSX_BIPR, chip->int_reg);
-	}
-#endif
-	if (chip->hw_bypass_sd)
-		goto NextCard;
-	RTSX_DEBUGP("In rtsx_reset_chip, chip->int_reg = 0x%x\n", chip->int_reg);
-	if (chip->int_reg & SD_EXIST) {
-#ifdef HW_AUTO_SWITCH_SD_BUS
-		if (CHECK_PID(chip, 0x5208) && (chip->ic_version < IC_VER_C))
-			retval = rtsx_pre_handle_sdio_old(chip);
-		else
-			retval = rtsx_pre_handle_sdio_new(chip);
-
-		RTSX_DEBUGP("chip->need_reset = 0x%x (rtsx_reset_chip)\n", (unsigned int)(chip->need_reset));
-#else  /* HW_AUTO_SWITCH_SD_BUS */
-		retval = rtsx_pre_handle_sdio_old(chip);
-#endif  /* HW_AUTO_SWITCH_SD_BUS */
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-	} else {
-		chip->sd_io = 0;
-		RTSX_WRITE_REG(chip, SDIO_CTRL, SDIO_BUS_CTRL | SDIO_CD_CTRL, 0);
-	}
-
-NextCard:
-	if (chip->int_reg & XD_EXIST)
-		chip->need_reset |= XD_CARD;
-	if (chip->int_reg & MS_EXIST)
-		chip->need_reset |= MS_CARD;
-	if (chip->int_reg & CARD_EXIST)
-		RTSX_WRITE_REG(chip, SSC_CTL1, SSC_RSTB, SSC_RSTB);
-
-	RTSX_DEBUGP("In rtsx_init_chip, chip->need_reset = 0x%x\n", (unsigned int)(chip->need_reset));
-
-	RTSX_WRITE_REG(chip, RCCTL, 0x01, 0x00);
-
-	if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) {
-		/* Turn off main power when entering S3/S4 state */
-		RTSX_WRITE_REG(chip, MAIN_PWR_OFF_CTL, 0x03, 0x03);
-	}
-
-	if (chip->remote_wakeup_en && !chip->auto_delink_en) {
-		RTSX_WRITE_REG(chip, WAKE_SEL_CTL, 0x07, 0x07);
-		if (chip->aux_pwr_exist)
-			RTSX_WRITE_REG(chip, PME_FORCE_CTL, 0xFF, 0x33);
-	} else {
-		RTSX_WRITE_REG(chip, WAKE_SEL_CTL, 0x07, 0x04);
-		RTSX_WRITE_REG(chip, PME_FORCE_CTL, 0xFF, 0x30);
-	}
-
-	if (CHECK_PID(chip, 0x5208) && (chip->ic_version >= IC_VER_D)) {
-		RTSX_WRITE_REG(chip, PETXCFG, 0x1C, 0x14);
-	} else if (CHECK_PID(chip, 0x5209)) {
-		if (chip->force_clkreq_0)
-			RTSX_WRITE_REG(chip, PETXCFG, 0x08, 0x08);
-		else
-			RTSX_WRITE_REG(chip, PETXCFG, 0x08, 0x00);
-	}
-
-	if (chip->asic_code && CHECK_PID(chip, 0x5208)) {
-		retval = rtsx_clr_phy_reg_bit(chip, 0x1C, 2);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (chip->ft2_fast_mode) {
-		RTSX_WRITE_REG(chip, CARD_PWR_CTL, 0xFF, MS_PARTIAL_POWER_ON | SD_PARTIAL_POWER_ON);
-		udelay(chip->pmos_pwr_on_interval);
-		RTSX_WRITE_REG(chip, CARD_PWR_CTL, 0xFF, MS_POWER_ON | SD_POWER_ON);
-
-		wait_timeout(200);
-	}
-
-	/* Reset card */
-	rtsx_reset_detected_cards(chip, 0);
-
-	chip->driver_first_load = 0;
-
-	return STATUS_SUCCESS;
-}
-
-static inline int check_sd_speed_prior(u32 sd_speed_prior)
-{
-	int i, fake_para = 0;
-
-	for (i = 0; i < 4; i++) {
-		u8 tmp = (u8)(sd_speed_prior >> (i*8));
-		if ((tmp < 0x01) || (tmp > 0x04)) {
-			fake_para = 1;
-			break;
-		}
-	}
-
-	return !fake_para;
-}
-
-static inline int check_sd_current_prior(u32 sd_current_prior)
-{
-	int i, fake_para = 0;
-
-	for (i = 0; i < 4; i++) {
-		u8 tmp = (u8)(sd_current_prior >> (i*8));
-		if (tmp > 0x03) {
-			fake_para = 1;
-			break;
-		}
-	}
-
-	return !fake_para;
-}
-
-static int rts5209_init(struct rtsx_chip *chip)
-{
-	int retval;
-	u32 lval = 0;
-	u8 val = 0;
-
-	val = rtsx_readb(chip, 0x1C);
-	if ((val & 0x10) == 0)
-		chip->asic_code = 1;
-	else
-		chip->asic_code = 0;
-
-	chip->ic_version = val & 0x0F;
-	chip->phy_debug_mode = 0;
-
-	chip->aux_pwr_exist = 0;
-
-	chip->ms_power_class_en = 0x03;
-
-	retval = rtsx_read_cfg_dw(chip, 0, 0x724, &lval);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_DEBUGP("dw in 0x724: 0x%x\n", lval);
-	val = (u8)lval;
-	if (!(val & 0x80)) {
-		if (val & 0x08)
-			chip->lun_mode = DEFAULT_SINGLE;
-		else
-			chip->lun_mode = SD_MS_2LUN;
-
-		if (val & 0x04)
-			SET_SDIO_EXIST(chip);
-		else
-			CLR_SDIO_EXIST(chip);
-
-		if (val & 0x02)
-			chip->hw_bypass_sd = 0;
-		else
-			chip->hw_bypass_sd = 1;
-
-	} else {
-		SET_SDIO_EXIST(chip);
-		chip->hw_bypass_sd = 0;
-	}
-
-	if (chip->use_hw_setting) {
-		u8 clk;
-
-		chip->aspm_l0s_l1_en = (val >> 5) & 0x03;
-
-		val = (u8)(lval >> 8);
-
-		clk = (val >> 5) & 0x07;
-		if (clk != 0x07)
-			chip->asic_sd_sdr50_clk = 98 - clk * 2;
-
-		if (val & 0x10)
-			chip->auto_delink_en = 1;
-		else
-			chip->auto_delink_en = 0;
-
-		if (chip->ss_en == 2) {
-			chip->ss_en = 0;
-		} else {
-			if (val & 0x08)
-				chip->ss_en = 1;
-			else
-				chip->ss_en = 0;
-		}
-
-		clk = val & 0x07;
-		if (clk != 0x07)
-			chip->asic_ms_hg_clk = (59 - clk) * 2;
-
-		val = (u8)(lval >> 16);
-
-		clk = (val >> 6) & 0x03;
-		if (clk != 0x03) {
-			chip->asic_sd_hs_clk = (49 - clk * 2) * 2;
-			chip->asic_mmc_52m_clk = (49 - clk * 2) * 2;
-		}
-
-		clk = (val >> 4) & 0x03;
-		if (clk != 0x03)
-			chip->asic_sd_ddr50_clk = (48 - clk * 2) * 2;
-
-		if (val & 0x01)
-			chip->sdr104_en = 1;
-		else
-			chip->sdr104_en = 0;
-
-		if (val & 0x02)
-			chip->ddr50_en = 1;
-		else
-			chip->ddr50_en = 0;
-
-		if (val & 0x04)
-			chip->sdr50_en = 1;
-		else
-			chip->sdr50_en = 0;
-
-
-		val = (u8)(lval >> 24);
-
-		clk = (val >> 5) & 0x07;
-		if (clk != 0x07)
-			chip->asic_sd_sdr104_clk = 206 - clk * 3;
-
-		if (val & 0x10)
-			chip->power_down_in_ss = 1;
-		else
-			chip->power_down_in_ss = 0;
-
-		chip->ms_power_class_en = val & 0x03;
-	}
-
-	if (chip->hp_watch_bios_hotplug && chip->auto_delink_en) {
-		u8 reg58, reg5b;
-
-		retval = rtsx_read_pci_cfg_byte(0x00,
-						0x1C, 0x02, 0x58, &reg58);
-		if (retval < 0)
-			return STATUS_SUCCESS;
-
-		retval = rtsx_read_pci_cfg_byte(0x00,
-						0x1C, 0x02, 0x5B, &reg5b);
-		if (retval < 0)
-			return STATUS_SUCCESS;
-
-		RTSX_DEBUGP("reg58 = 0x%x, reg5b = 0x%x\n", reg58, reg5b);
-
-		if ((reg58 == 0x00) && (reg5b == 0x01))
-			chip->auto_delink_en = 0;
-
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int rts5208_init(struct rtsx_chip *chip)
-{
-	int retval;
-	u16 reg = 0;
-	u8 val = 0;
-
-	RTSX_WRITE_REG(chip, CLK_SEL, 0x03, 0x03);
-	RTSX_READ_REG(chip, CLK_SEL, &val);
-	if (val == 0)
-		chip->asic_code = 1;
-	else
-		chip->asic_code = 0;
-
-	if (chip->asic_code) {
-		retval = rtsx_read_phy_register(chip, 0x1C, &reg);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		RTSX_DEBUGP("Value of phy register 0x1C is 0x%x\n", reg);
-		chip->ic_version = (reg >> 4) & 0x07;
-		if (reg & PHY_DEBUG_MODE)
-			chip->phy_debug_mode = 1;
-		else
-			chip->phy_debug_mode = 0;
-
-	} else {
-		RTSX_READ_REG(chip, 0xFE80, &val);
-		chip->ic_version = val;
-		chip->phy_debug_mode = 0;
-	}
-
-	RTSX_READ_REG(chip, PDINFO, &val);
-	RTSX_DEBUGP("PDINFO: 0x%x\n", val);
-	if (val & AUX_PWR_DETECTED)
-		chip->aux_pwr_exist = 1;
-	else
-		chip->aux_pwr_exist = 0;
-
-	RTSX_READ_REG(chip, 0xFE50, &val);
-	if (val & 0x01)
-		chip->hw_bypass_sd = 1;
-	else
-		chip->hw_bypass_sd = 0;
-
-	rtsx_read_config_byte(chip, 0x0E, &val);
-	if (val & 0x80)
-		SET_SDIO_EXIST(chip);
-	else
-		CLR_SDIO_EXIST(chip);
-
-	if (chip->use_hw_setting) {
-		RTSX_READ_REG(chip, CHANGE_LINK_STATE, &val);
-		if (val & 0x80)
-			chip->auto_delink_en = 1;
-		else
-			chip->auto_delink_en = 0;
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int rts5288_init(struct rtsx_chip *chip)
-{
-	int retval;
-	u8 val = 0, max_func;
-	u32 lval = 0;
-
-	RTSX_WRITE_REG(chip, CLK_SEL, 0x03, 0x03);
-	RTSX_READ_REG(chip, CLK_SEL, &val);
-	if (val == 0)
-		chip->asic_code = 1;
-	else
-		chip->asic_code = 0;
-
-	chip->ic_version = 0;
-	chip->phy_debug_mode = 0;
-
-	RTSX_READ_REG(chip, PDINFO, &val);
-	RTSX_DEBUGP("PDINFO: 0x%x\n", val);
-	if (val & AUX_PWR_DETECTED)
-		chip->aux_pwr_exist = 1;
-	else
-		chip->aux_pwr_exist = 0;
-
-	RTSX_READ_REG(chip, CARD_SHARE_MODE, &val);
-	RTSX_DEBUGP("CARD_SHARE_MODE: 0x%x\n", val);
-	if (val & 0x04)
-		chip->baro_pkg = QFN;
-	else
-		chip->baro_pkg = LQFP;
-
-	RTSX_READ_REG(chip, 0xFE5A, &val);
-	if (val & 0x10)
-		chip->hw_bypass_sd = 1;
-	else
-		chip->hw_bypass_sd = 0;
-
-	retval = rtsx_read_cfg_dw(chip, 0, 0x718, &lval);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	max_func = (u8)((lval >> 29) & 0x07);
-	RTSX_DEBUGP("Max function number: %d\n", max_func);
-	if (max_func == 0x02)
-		SET_SDIO_EXIST(chip);
-	else
-		CLR_SDIO_EXIST(chip);
-
-	if (chip->use_hw_setting) {
-		RTSX_READ_REG(chip, CHANGE_LINK_STATE, &val);
-		if (val & 0x80)
-			chip->auto_delink_en = 1;
-		else
-			chip->auto_delink_en = 0;
-
-		if (CHECK_BARO_PKG(chip, LQFP))
-			chip->lun_mode = SD_MS_1LUN;
-		else
-			chip->lun_mode = DEFAULT_SINGLE;
-
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int rtsx_init_chip(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	struct xd_info *xd_card = &(chip->xd_card);
-	struct ms_info *ms_card = &(chip->ms_card);
-	int retval;
-	unsigned int i;
-
-	RTSX_DEBUGP("Vendor ID: 0x%04x, Product ID: 0x%04x\n",
-		     chip->vendor_id, chip->product_id);
-
-	chip->ic_version = 0;
-
-#ifdef _MSG_TRACE
-	chip->msg_idx = 0;
-#endif
-
-	memset(xd_card, 0, sizeof(struct xd_info));
-	memset(sd_card, 0, sizeof(struct sd_info));
-	memset(ms_card, 0, sizeof(struct ms_info));
-
-	chip->xd_reset_counter = 0;
-	chip->sd_reset_counter = 0;
-	chip->ms_reset_counter = 0;
-
-	chip->xd_show_cnt = MAX_SHOW_CNT;
-	chip->sd_show_cnt = MAX_SHOW_CNT;
-	chip->ms_show_cnt = MAX_SHOW_CNT;
-
-	chip->sd_io = 0;
-	chip->auto_delink_cnt = 0;
-	chip->auto_delink_allowed = 1;
-	rtsx_set_stat(chip, RTSX_STAT_INIT);
-
-	chip->aspm_enabled = 0;
-	chip->chip_insert_with_sdio = 0;
-	chip->sdio_aspm = 0;
-	chip->sdio_idle = 0;
-	chip->sdio_counter = 0;
-	chip->cur_card = 0;
-	chip->phy_debug_mode = 0;
-	chip->sdio_func_exist = 0;
-	memset(chip->sdio_raw_data, 0, 12);
-
-	for (i = 0; i < MAX_ALLOWED_LUN_CNT; i++) {
-		set_sense_type(chip, i, SENSE_TYPE_NO_SENSE);
-		chip->rw_fail_cnt[i] = 0;
-	}
-
-	if (!check_sd_speed_prior(chip->sd_speed_prior))
-		chip->sd_speed_prior = 0x01040203;
-
-	RTSX_DEBUGP("sd_speed_prior = 0x%08x\n", chip->sd_speed_prior);
-
-	if (!check_sd_current_prior(chip->sd_current_prior))
-		chip->sd_current_prior = 0x00010203;
-
-	RTSX_DEBUGP("sd_current_prior = 0x%08x\n", chip->sd_current_prior);
-
-	if ((chip->sd_ddr_tx_phase > 31) || (chip->sd_ddr_tx_phase < 0))
-		chip->sd_ddr_tx_phase = 0;
-
-	if ((chip->mmc_ddr_tx_phase > 31) || (chip->mmc_ddr_tx_phase < 0))
-		chip->mmc_ddr_tx_phase = 0;
-
-	RTSX_WRITE_REG(chip, FPDCTL, SSC_POWER_DOWN, 0);
-	wait_timeout(200);
-	RTSX_WRITE_REG(chip, CLK_DIV, 0x07, 0x07);
-	RTSX_DEBUGP("chip->use_hw_setting = %d\n", chip->use_hw_setting);
-
-	if (CHECK_PID(chip, 0x5209)) {
-		retval = rts5209_init(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-	} else if (CHECK_PID(chip, 0x5208)) {
-		retval = rts5208_init(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-	} else if (CHECK_PID(chip, 0x5288)) {
-		retval = rts5288_init(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-	}
-
-	if (chip->ss_en == 2)
-		chip->ss_en = 0;
-
-	RTSX_DEBUGP("chip->asic_code = %d\n", chip->asic_code);
-	RTSX_DEBUGP("chip->ic_version = 0x%x\n", chip->ic_version);
-	RTSX_DEBUGP("chip->phy_debug_mode = %d\n", chip->phy_debug_mode);
-	RTSX_DEBUGP("chip->aux_pwr_exist = %d\n", chip->aux_pwr_exist);
-	RTSX_DEBUGP("chip->sdio_func_exist = %d\n", chip->sdio_func_exist);
-	RTSX_DEBUGP("chip->hw_bypass_sd = %d\n", chip->hw_bypass_sd);
-	RTSX_DEBUGP("chip->aspm_l0s_l1_en = %d\n", chip->aspm_l0s_l1_en);
-	RTSX_DEBUGP("chip->lun_mode = %d\n", chip->lun_mode);
-	RTSX_DEBUGP("chip->auto_delink_en = %d\n", chip->auto_delink_en);
-	RTSX_DEBUGP("chip->ss_en = %d\n", chip->ss_en);
-	RTSX_DEBUGP("chip->baro_pkg = %d\n", chip->baro_pkg);
-
-	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
-		chip->card2lun[SD_CARD] = 0;
-		chip->card2lun[MS_CARD] = 1;
-		chip->card2lun[XD_CARD] = 0xFF;
-		chip->lun2card[0] = SD_CARD;
-		chip->lun2card[1] = MS_CARD;
-		chip->max_lun = 1;
-		SET_SDIO_IGNORED(chip);
-	} else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) {
-		chip->card2lun[SD_CARD] = 0;
-		chip->card2lun[MS_CARD] = 0;
-		chip->card2lun[XD_CARD] = 0xFF;
-		chip->lun2card[0] = SD_CARD | MS_CARD;
-		chip->max_lun = 0;
-	} else {
-		chip->card2lun[XD_CARD] = 0;
-		chip->card2lun[SD_CARD] = 0;
-		chip->card2lun[MS_CARD] = 0;
-		chip->lun2card[0] = XD_CARD | SD_CARD | MS_CARD;
-		chip->max_lun = 0;
-	}
-
-	retval = rtsx_reset_chip(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-void rtsx_release_chip(struct rtsx_chip *chip)
-{
-	xd_free_l2p_tbl(chip);
-	ms_free_l2p_tbl(chip);
-	chip->card_exist = 0;
-	chip->card_ready = 0;
-}
-
-#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
-static inline void rtsx_blink_led(struct rtsx_chip *chip)
-{
-	if (chip->card_exist && chip->blink_led) {
-		if (chip->led_toggle_counter < LED_TOGGLE_INTERVAL) {
-			chip->led_toggle_counter++;
-		} else {
-			chip->led_toggle_counter = 0;
-			toggle_gpio(chip, LED_GPIO);
-		}
-	}
-}
-#endif
-
-static void rtsx_monitor_aspm_config(struct rtsx_chip *chip)
-{
-	int maybe_support_aspm, reg_changed;
-	u32 tmp = 0;
-	u8 reg0 = 0, reg1 = 0;
-
-	maybe_support_aspm = 0;
-	reg_changed = 0;
-	rtsx_read_config_byte(chip, LCTLR, &reg0);
-	if (chip->aspm_level[0] != reg0) {
-		reg_changed = 1;
-		chip->aspm_level[0] = reg0;
-	}
-	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
-		rtsx_read_cfg_dw(chip, 1, 0xC0, &tmp);
-		reg1 = (u8)tmp;
-		if (chip->aspm_level[1] != reg1) {
-			reg_changed = 1;
-			chip->aspm_level[1] = reg1;
-		}
-
-		if ((reg0 & 0x03) && (reg1 & 0x03))
-			maybe_support_aspm = 1;
-
-	} else {
-		if (reg0 & 0x03)
-			maybe_support_aspm = 1;
-
-	}
-
-	if (reg_changed) {
-		if (maybe_support_aspm)
-			chip->aspm_l0s_l1_en = 0x03;
-
-		RTSX_DEBUGP("aspm_level[0] = 0x%02x, aspm_level[1] = 0x%02x\n",
-			      chip->aspm_level[0], chip->aspm_level[1]);
-
-		if (chip->aspm_l0s_l1_en) {
-			chip->aspm_enabled = 1;
-		} else {
-			chip->aspm_enabled = 0;
-			chip->sdio_aspm = 0;
-		}
-		rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFF,
-			0x30 | chip->aspm_level[0] | (chip->aspm_level[1] << 2));
-	}
-}
-
-void rtsx_polling_func(struct rtsx_chip *chip)
-{
-#ifdef SUPPORT_SD_LOCK
-	struct sd_info *sd_card = &(chip->sd_card);
-#endif
-	int ss_allowed;
-
-	if (rtsx_chk_stat(chip, RTSX_STAT_SUSPEND))
-		return;
-
-	if (rtsx_chk_stat(chip, RTSX_STAT_DELINK))
-		goto Delink_Stage;
-
-	if (chip->polling_config) {
-		u8 val;
-		rtsx_read_config_byte(chip, 0, &val);
-	}
-
-	if (rtsx_chk_stat(chip, RTSX_STAT_SS))
-		return;
-
-#ifdef SUPPORT_OCP
-	if (chip->ocp_int) {
-		rtsx_read_register(chip, OCPSTAT, &(chip->ocp_stat));
-
-		if (CHECK_PID(chip, 0x5209) &&
-				CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
-			if (chip->ocp_int & SD_OC_INT)
-				sd_power_off_card3v3(chip);
-			if (chip->ocp_int & MS_OC_INT)
-				ms_power_off_card3v3(chip);
-		} else {
-			if (chip->card_exist & SD_CARD)
-				sd_power_off_card3v3(chip);
-			else if (chip->card_exist & MS_CARD)
-				ms_power_off_card3v3(chip);
-			else if (chip->card_exist & XD_CARD)
-				xd_power_off_card3v3(chip);
-
-		}
-
-		chip->ocp_int = 0;
-	}
-#endif
-
-#ifdef SUPPORT_SD_LOCK
-	if (sd_card->sd_erase_status) {
-		if (chip->card_exist & SD_CARD) {
-			u8 val;
-			if (CHECK_PID(chip, 0x5209)) {
-				rtsx_read_register(chip, SD_BUS_STAT, &val);
-				if (val & SD_DAT0_STATUS) {
-					sd_card->sd_erase_status = SD_NOT_ERASE;
-					sd_card->sd_lock_notify = 1;
-					chip->need_reinit |= SD_CARD;
-				}
-			} else {
-				rtsx_read_register(chip, 0xFD30, &val);
-				if (val & 0x02) {
-					sd_card->sd_erase_status = SD_NOT_ERASE;
-					sd_card->sd_lock_notify = 1;
-					chip->need_reinit |= SD_CARD;
-				}
-			}
-		} else {
-			sd_card->sd_erase_status = SD_NOT_ERASE;
-		}
-	}
-#endif
-
-	rtsx_init_cards(chip);
-
-	if (chip->ss_en) {
-		ss_allowed = 1;
-
-		if (CHECK_PID(chip, 0x5288)) {
-			ss_allowed = 0;
-		} else {
-			if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
-				u32 val;
-				rtsx_read_cfg_dw(chip, 1, 0x04, &val);
-				if (val & 0x07)
-					ss_allowed = 0;
-
-			}
-		}
-	} else {
-		ss_allowed = 0;
-	}
-
-	if (ss_allowed && !chip->sd_io) {
-		if (rtsx_get_stat(chip) != RTSX_STAT_IDLE) {
-			chip->ss_counter = 0;
-		} else {
-			if (chip->ss_counter <
-				(chip->ss_idle_period / POLLING_INTERVAL)) {
-				chip->ss_counter++;
-			} else {
-				rtsx_exclusive_enter_ss(chip);
-				return;
-			}
-		}
-	}
-
-	if (CHECK_PID(chip, 0x5208)) {
-		rtsx_monitor_aspm_config(chip);
-
-#ifdef SUPPORT_SDIO_ASPM
-		if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) &&
-				chip->aspm_l0s_l1_en && chip->dynamic_aspm) {
-			if (chip->sd_io) {
-				dynamic_configure_sdio_aspm(chip);
-			} else {
-				if (!chip->sdio_aspm) {
-					RTSX_DEBUGP("SDIO enter ASPM!\n");
-					rtsx_write_register(chip,
-						ASPM_FORCE_CTL, 0xFC,
-						0x30 | (chip->aspm_level[1] << 2));
-					chip->sdio_aspm = 1;
-				}
-			}
-		}
-#endif
-	}
-
-	if (chip->idle_counter < IDLE_MAX_COUNT) {
-		chip->idle_counter++;
-	} else {
-		if (rtsx_get_stat(chip) != RTSX_STAT_IDLE) {
-			RTSX_DEBUGP("Idle state!\n");
-			rtsx_set_stat(chip, RTSX_STAT_IDLE);
-
-#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
-			chip->led_toggle_counter = 0;
-#endif
-			rtsx_force_power_on(chip, SSC_PDCTL);
-
-			turn_off_led(chip, LED_GPIO);
-
-			if (chip->auto_power_down && !chip->card_ready && !chip->sd_io)
-				rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
-
-		}
-	}
-
-	switch (rtsx_get_stat(chip)) {
-	case RTSX_STAT_RUN:
-#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
-		rtsx_blink_led(chip);
-#endif
-		do_remaining_work(chip);
-		break;
-
-	case RTSX_STAT_IDLE:
-		if (chip->sd_io && !chip->sd_int)
-			try_to_switch_sdio_ctrl(chip);
-
-		rtsx_enable_aspm(chip);
-		break;
-
-	default:
-		break;
-	}
-
-
-#ifdef SUPPORT_OCP
-	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
-#ifdef CONFIG_RTS_PSTOR_DEBUG
-		if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER | MS_OC_NOW | MS_OC_EVER))
-			RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", chip->ocp_stat);
-#endif
-
-		if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
-			if (chip->card_exist & SD_CARD) {
-				rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
-				card_power_off(chip, SD_CARD);
-				chip->card_fail |= SD_CARD;
-			}
-		}
-		if (chip->ocp_stat & (MS_OC_NOW | MS_OC_EVER)) {
-			if (chip->card_exist & MS_CARD) {
-				rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
-				card_power_off(chip, MS_CARD);
-				chip->card_fail |= MS_CARD;
-			}
-		}
-	} else {
-		if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
-			RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", chip->ocp_stat);
-			if (chip->card_exist & SD_CARD) {
-				rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
-				chip->card_fail |= SD_CARD;
-			} else if (chip->card_exist & MS_CARD) {
-				rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
-				chip->card_fail |= MS_CARD;
-			} else if (chip->card_exist & XD_CARD) {
-				rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0);
-				chip->card_fail |= XD_CARD;
-			}
-			card_power_off(chip, SD_CARD);
-		}
-	}
-#endif
-
-Delink_Stage:
-	if (chip->auto_delink_en && chip->auto_delink_allowed &&
-			!chip->card_ready && !chip->card_ejected && !chip->sd_io) {
-		int enter_L1 = chip->auto_delink_in_L1 && (chip->aspm_l0s_l1_en || chip->ss_en);
-		int delink_stage1_cnt = chip->delink_stage1_step;
-		int delink_stage2_cnt = delink_stage1_cnt + chip->delink_stage2_step;
-		int delink_stage3_cnt = delink_stage2_cnt + chip->delink_stage3_step;
-
-		if (chip->auto_delink_cnt <= delink_stage3_cnt) {
-			if (chip->auto_delink_cnt == delink_stage1_cnt) {
-				rtsx_set_stat(chip, RTSX_STAT_DELINK);
-
-				if (chip->asic_code && CHECK_PID(chip, 0x5208))
-					rtsx_set_phy_reg_bit(chip, 0x1C, 2);
-
-				if (chip->card_exist) {
-					RTSX_DEBUGP("False card inserted, do force delink\n");
-
-					if (enter_L1)
-						rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 1);
-
-					rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0x0A);
-
-					if (enter_L1)
-						rtsx_enter_L1(chip);
-
-					chip->auto_delink_cnt = delink_stage3_cnt + 1;
-				} else {
-					RTSX_DEBUGP("No card inserted, do delink\n");
-
-					if (enter_L1)
-						rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 1);
-
-#ifdef HW_INT_WRITE_CLR
-					if (CHECK_PID(chip, 0x5209)) {
-						rtsx_writel(chip, RTSX_BIPR, 0xFFFFFFFF);
-						RTSX_DEBUGP("RTSX_BIPR: 0x%x\n", rtsx_readl(chip, RTSX_BIPR));
-					}
-#endif
-					rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 0x02);
-
-					if (enter_L1)
-						rtsx_enter_L1(chip);
-
-				}
-			}
-
-			if (chip->auto_delink_cnt == delink_stage2_cnt) {
-				RTSX_DEBUGP("Try to do force delink\n");
-
-				if (enter_L1)
-					rtsx_exit_L1(chip);
-
-				if (chip->asic_code && CHECK_PID(chip, 0x5208))
-					rtsx_set_phy_reg_bit(chip, 0x1C, 2);
-
-				rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0x0A);
-			}
-
-			chip->auto_delink_cnt++;
-		}
-	} else {
-		chip->auto_delink_cnt = 0;
-	}
-}
-
-void rtsx_undo_delink(struct rtsx_chip *chip)
-{
-	chip->auto_delink_allowed = 0;
-	rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0x00);
-}
-
-/**
- * rtsx_stop_cmd - stop command transfer and DMA transfer
- * @chip: Realtek's card reader chip
- * @card: flash card type
- *
- * Stop command transfer and DMA transfer.
- * This function is called in error handler.
- */
-void rtsx_stop_cmd(struct rtsx_chip *chip, int card)
-{
-	int i;
-
-	for (i = 0; i <= 8; i++) {
-		int addr = RTSX_HCBAR + i * 4;
-		u32 reg;
-		reg = rtsx_readl(chip, addr);
-		RTSX_DEBUGP("BAR (0x%02x): 0x%08x\n", addr, reg);
-	}
-	rtsx_writel(chip, RTSX_HCBCTLR, STOP_CMD);
-	rtsx_writel(chip, RTSX_HDBCTLR, STOP_DMA);
-
-	for (i = 0; i < 16; i++) {
-		u16 addr = 0xFE20 + (u16)i;
-		u8 val;
-		rtsx_read_register(chip, addr, &val);
-		RTSX_DEBUGP("0x%04X: 0x%02x\n", addr, val);
-	}
-
-	rtsx_write_register(chip, DMACTL, 0x80, 0x80);
-	rtsx_write_register(chip, RBCTL, 0x80, 0x80);
-}
-
-#define MAX_RW_REG_CNT		1024
-
-int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data)
-{
-	int i;
-	u32 val = 3 << 30;
-
-	val |= (u32)(addr & 0x3FFF) << 16;
-	val |= (u32)mask << 8;
-	val |= (u32)data;
-
-	rtsx_writel(chip, RTSX_HAIMR, val);
-
-	for (i = 0; i < MAX_RW_REG_CNT; i++) {
-		val = rtsx_readl(chip, RTSX_HAIMR);
-		if ((val & (1 << 31)) == 0) {
-			if (data != (u8)val)
-				TRACE_RET(chip, STATUS_FAIL);
-
-			return STATUS_SUCCESS;
-		}
-	}
-
-	TRACE_RET(chip, STATUS_TIMEDOUT);
-}
-
-int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data)
-{
-	u32 val = 2 << 30;
-	int i;
-
-	if (data)
-		*data = 0;
-
-	val |= (u32)(addr & 0x3FFF) << 16;
-
-	rtsx_writel(chip, RTSX_HAIMR, val);
-
-	for (i = 0; i < MAX_RW_REG_CNT; i++) {
-		val = rtsx_readl(chip, RTSX_HAIMR);
-		if ((val & (1 << 31)) == 0)
-			break;
-	}
-
-	if (i >= MAX_RW_REG_CNT)
-		TRACE_RET(chip, STATUS_TIMEDOUT);
-
-	if (data)
-		*data = (u8)(val & 0xFF);
-
-	return STATUS_SUCCESS;
-}
-
-int rtsx_write_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 mask, u32 val)
-{
-	u8 mode = 0, tmp;
-	int i;
-
-	for (i = 0; i < 4; i++) {
-		if (mask & 0xFF) {
-			RTSX_WRITE_REG(chip, CFGDATA0 + i,
-				       0xFF, (u8)(val & mask & 0xFF));
-			mode |= (1 << i);
-		}
-		mask >>= 8;
-		val >>= 8;
-	}
-
-	if (mode) {
-		RTSX_WRITE_REG(chip, CFGADDR0, 0xFF, (u8)addr);
-		RTSX_WRITE_REG(chip, CFGADDR1, 0xFF, (u8)(addr >> 8));
-
-		RTSX_WRITE_REG(chip, CFGRWCTL, 0xFF,
-			       0x80 | mode | ((func_no & 0x03) << 4));
-
-		for (i = 0; i < MAX_RW_REG_CNT; i++) {
-			RTSX_READ_REG(chip, CFGRWCTL, &tmp);
-			if ((tmp & 0x80) == 0)
-				break;
-		}
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val)
-{
-	int i;
-	u8 tmp;
-	u32 data = 0;
-
-	RTSX_WRITE_REG(chip, CFGADDR0, 0xFF, (u8)addr);
-	RTSX_WRITE_REG(chip, CFGADDR1, 0xFF, (u8)(addr >> 8));
-	RTSX_WRITE_REG(chip, CFGRWCTL, 0xFF, 0x80 | ((func_no & 0x03) << 4));
-
-	for (i = 0; i < MAX_RW_REG_CNT; i++) {
-		RTSX_READ_REG(chip, CFGRWCTL, &tmp);
-		if ((tmp & 0x80) == 0)
-			break;
-	}
-
-	for (i = 0; i < 4; i++) {
-		RTSX_READ_REG(chip, CFGDATA0 + i, &tmp);
-		data |= (u32)tmp << (i * 8);
-	}
-
-	if (val)
-		*val = data;
-
-	return STATUS_SUCCESS;
-}
-
-int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, int len)
-{
-	u32 *data, *mask;
-	u16 offset = addr % 4;
-	u16 aligned_addr = addr - offset;
-	int dw_len, i, j;
-	int retval;
-
-	RTSX_DEBUGP("%s\n", __func__);
-
-	if (!buf)
-		TRACE_RET(chip, STATUS_NOMEM);
-
-	if ((len + offset) % 4)
-		dw_len = (len + offset) / 4 + 1;
-	else
-		dw_len = (len + offset) / 4;
-
-	RTSX_DEBUGP("dw_len = %d\n", dw_len);
-
-	data = vzalloc(dw_len * 4);
-	if (!data)
-		TRACE_RET(chip, STATUS_NOMEM);
-
-	mask = vzalloc(dw_len * 4);
-	if (!mask) {
-		vfree(data);
-		TRACE_RET(chip, STATUS_NOMEM);
-	}
-
-	j = 0;
-	for (i = 0; i < len; i++) {
-		mask[j] |= 0xFF << (offset * 8);
-		data[j] |= buf[i] << (offset * 8);
-		if (++offset == 4) {
-			j++;
-			offset = 0;
-		}
-	}
-
-	RTSX_DUMP(mask, dw_len * 4);
-	RTSX_DUMP(data, dw_len * 4);
-
-	for (i = 0; i < dw_len; i++) {
-		retval = rtsx_write_cfg_dw(chip, func, aligned_addr + i * 4, mask[i], data[i]);
-		if (retval != STATUS_SUCCESS) {
-			vfree(data);
-			vfree(mask);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	vfree(data);
-	vfree(mask);
-
-	return STATUS_SUCCESS;
-}
-
-int rtsx_read_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, int len)
-{
-	u32 *data;
-	u16 offset = addr % 4;
-	u16 aligned_addr = addr - offset;
-	int dw_len, i, j;
-	int retval;
-
-	RTSX_DEBUGP("%s\n", __func__);
-
-	if ((len + offset) % 4)
-		dw_len = (len + offset) / 4 + 1;
-	else
-		dw_len = (len + offset) / 4;
-
-	RTSX_DEBUGP("dw_len = %d\n", dw_len);
-
-	data = (u32 *)vmalloc(dw_len * 4);
-	if (!data)
-		TRACE_RET(chip, STATUS_NOMEM);
-
-	for (i = 0; i < dw_len; i++) {
-		retval = rtsx_read_cfg_dw(chip, func, aligned_addr + i * 4, data + i);
-		if (retval != STATUS_SUCCESS) {
-			vfree(data);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	if (buf) {
-		j = 0;
-
-		for (i = 0; i < len; i++) {
-			buf[i] = (u8)(data[j] >> (offset * 8));
-			if (++offset == 4) {
-				j++;
-				offset = 0;
-			}
-		}
-	}
-
-	vfree(data);
-
-	return STATUS_SUCCESS;
-}
-
-int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val)
-{
-	int i, finished = 0;
-	u8 tmp;
-
-	RTSX_WRITE_REG(chip, PHYDATA0, 0xFF, (u8)val);
-	RTSX_WRITE_REG(chip, PHYDATA1, 0xFF, (u8)(val >> 8));
-	RTSX_WRITE_REG(chip, PHYADDR, 0xFF, addr);
-	RTSX_WRITE_REG(chip, PHYRWCTL, 0xFF, 0x81);
-
-	for (i = 0; i < 100000; i++) {
-		RTSX_READ_REG(chip, PHYRWCTL, &tmp);
-		if (!(tmp & 0x80)) {
-			finished = 1;
-			break;
-		}
-	}
-
-	if (!finished)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val)
-{
-	int i, finished = 0;
-	u16 data = 0;
-	u8 tmp;
-
-	RTSX_WRITE_REG(chip, PHYADDR, 0xFF, addr);
-	RTSX_WRITE_REG(chip, PHYRWCTL, 0xFF, 0x80);
-
-	for (i = 0; i < 100000; i++) {
-		RTSX_READ_REG(chip, PHYRWCTL, &tmp);
-		if (!(tmp & 0x80)) {
-			finished = 1;
-			break;
-		}
-	}
-
-	if (!finished)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_READ_REG(chip, PHYDATA0, &tmp);
-	data = tmp;
-	RTSX_READ_REG(chip, PHYDATA1, &tmp);
-	data |= (u16)tmp << 8;
-
-	if (val)
-		*val = data;
-
-	return STATUS_SUCCESS;
-}
-
-int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val)
-{
-	int i;
-	u8 data = 0;
-
-	RTSX_WRITE_REG(chip, EFUSE_CTRL, 0xFF, 0x80|addr);
-
-	for (i = 0; i < 100; i++) {
-		RTSX_READ_REG(chip, EFUSE_CTRL, &data);
-		if (!(data & 0x80))
-			break;
-		udelay(1);
-	}
-
-	if (data & 0x80)
-		TRACE_RET(chip, STATUS_TIMEDOUT);
-
-	RTSX_READ_REG(chip, EFUSE_DATA, &data);
-	if (val)
-		*val = data;
-
-	return STATUS_SUCCESS;
-}
-
-int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val)
-{
-	int i, j;
-	u8 data = 0, tmp = 0xFF;
-
-	for (i = 0; i < 8; i++) {
-		if (val & (u8)(1 << i))
-			continue;
-
-		tmp &= (~(u8)(1 << i));
-		RTSX_DEBUGP("Write 0x%x to 0x%x\n", tmp, addr);
-
-		RTSX_WRITE_REG(chip, EFUSE_DATA, 0xFF, tmp);
-		RTSX_WRITE_REG(chip, EFUSE_CTRL, 0xFF, 0xA0|addr);
-
-		for (j = 0; j < 100; j++) {
-			RTSX_READ_REG(chip, EFUSE_CTRL, &data);
-			if (!(data & 0x80))
-				break;
-			wait_timeout(3);
-		}
-
-		if (data & 0x80)
-			TRACE_RET(chip, STATUS_TIMEDOUT);
-
-		wait_timeout(5);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit)
-{
-	int retval;
-	u16 value;
-
-	retval = rtsx_read_phy_register(chip, reg, &value);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (value & (1 << bit)) {
-		value &= ~(1 << bit);
-		retval = rtsx_write_phy_register(chip, reg, value);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit)
-{
-	int retval;
-	u16 value;
-
-	retval = rtsx_read_phy_register(chip, reg, &value);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (0 == (value & (1 << bit))) {
-		value |= (1 << bit);
-		retval = rtsx_write_phy_register(chip, reg, value);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int rtsx_check_link_ready(struct rtsx_chip *chip)
-{
-	u8 val;
-
-	RTSX_READ_REG(chip, IRQSTAT0, &val);
-
-	RTSX_DEBUGP("IRQSTAT0: 0x%x\n", val);
-	if (val & LINK_RDY_INT) {
-		RTSX_DEBUGP("Delinked!\n");
-		rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT);
-		return STATUS_FAIL;
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static void rtsx_handle_pm_dstate(struct rtsx_chip *chip, u8 dstate)
-{
-	u32 ultmp;
-
-	RTSX_DEBUGP("%04x set pm_dstate to %d\n", chip->product_id, dstate);
-
-	if (CHK_SDIO_EXIST(chip)) {
-		u8 func_no;
-
-		if (CHECK_PID(chip, 0x5288))
-			func_no = 2;
-		else
-			func_no = 1;
-
-		rtsx_read_cfg_dw(chip, func_no, 0x84, &ultmp);
-		RTSX_DEBUGP("pm_dstate of function %d: 0x%x\n", (int)func_no, ultmp);
-		rtsx_write_cfg_dw(chip, func_no, 0x84, 0xFF, dstate);
-	}
-
-	rtsx_write_config_byte(chip, 0x44, dstate);
-	rtsx_write_config_byte(chip, 0x45, 0);
-}
-
-void rtsx_enter_L1(struct rtsx_chip *chip)
-{
-	rtsx_handle_pm_dstate(chip, 2);
-}
-
-void rtsx_exit_L1(struct rtsx_chip *chip)
-{
-	rtsx_write_config_byte(chip, 0x44, 0);
-	rtsx_write_config_byte(chip, 0x45, 0);
-}
-
-void rtsx_enter_ss(struct rtsx_chip *chip)
-{
-	RTSX_DEBUGP("Enter Selective Suspend State!\n");
-
-	rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT);
-
-	if (chip->power_down_in_ss) {
-		rtsx_power_off_card(chip);
-		rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
-	}
-
-	if (CHK_SDIO_EXIST(chip)) {
-		if (CHECK_PID(chip, 0x5288))
-			rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF00, 0x0100);
-		else
-			rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFF00, 0x0100);
-	}
-
-	if (chip->auto_delink_en) {
-		rtsx_write_register(chip, HOST_SLEEP_STATE, 0x01, 0x01);
-	} else {
-		if (!chip->phy_debug_mode) {
-			u32 tmp;
-			tmp = rtsx_readl(chip, RTSX_BIER);
-			tmp |= CARD_INT;
-			rtsx_writel(chip, RTSX_BIER, tmp);
-		}
-
-		rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 0);
-	}
-
-	rtsx_enter_L1(chip);
-
-	RTSX_CLR_DELINK(chip);
-	rtsx_set_stat(chip, RTSX_STAT_SS);
-}
-
-void rtsx_exit_ss(struct rtsx_chip *chip)
-{
-	RTSX_DEBUGP("Exit Selective Suspend State!\n");
-
-	rtsx_exit_L1(chip);
-
-	if (chip->power_down_in_ss) {
-		rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
-		udelay(1000);
-	}
-
-	if (RTSX_TST_DELINK(chip)) {
-		chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
-		rtsx_reinit_cards(chip, 1);
-		RTSX_CLR_DELINK(chip);
-	} else if (chip->power_down_in_ss) {
-		chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
-		rtsx_reinit_cards(chip, 0);
-	}
-}
-
-int rtsx_pre_handle_interrupt(struct rtsx_chip *chip)
-{
-	u32 status, int_enable;
-	int exit_ss = 0;
-#ifdef SUPPORT_OCP
-	u32 ocp_int = 0;
-
-	if (CHECK_PID(chip, 0x5209)) {
-		if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
-			ocp_int = MS_OC_INT | SD_OC_INT;
-		else
-			ocp_int = SD_OC_INT;
-
-	} else {
-		ocp_int = OC_INT;
-	}
-#endif
-
-	if (chip->ss_en) {
-		chip->ss_counter = 0;
-		if (rtsx_get_stat(chip) == RTSX_STAT_SS) {
-			exit_ss = 1;
-			rtsx_exit_L1(chip);
-			rtsx_set_stat(chip, RTSX_STAT_RUN);
-		}
-	}
-
-	int_enable = rtsx_readl(chip, RTSX_BIER);
-	chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
-#ifdef HW_INT_WRITE_CLR
-	if (CHECK_PID(chip, 0x5209))
-		rtsx_writel(chip, RTSX_BIPR, chip->int_reg);
-#endif
-
-	if (((chip->int_reg & int_enable) == 0) || (chip->int_reg == 0xFFFFFFFF))
-		return STATUS_FAIL;
-
-	if (!chip->msi_en) {
-		if (CHECK_PID(chip, 0x5209)) {
-			u8 val;
-			rtsx_read_config_byte(chip, 0x05, &val);
-			if (val & 0x04)
-				return STATUS_FAIL;
-		}
-	}
-
-	status = chip->int_reg &= (int_enable | 0x7FFFFF);
-
-	if (status & CARD_INT) {
-		chip->auto_delink_cnt = 0;
-
-		if (status & SD_INT) {
-			if (status & SD_EXIST) {
-				set_bit(SD_NR, &(chip->need_reset));
-			} else {
-				set_bit(SD_NR, &(chip->need_release));
-				chip->sd_reset_counter = 0;
-				chip->sd_show_cnt = 0;
-				clear_bit(SD_NR, &(chip->need_reset));
-			}
-		} else {
-			/* If multi-luns, it's possible that
-			   when plugging/unplugging one card
-			   there is another card which still
-			   exists in the slot. In this case,
-			   all existed cards should be reset.
-			*/
-			if (exit_ss && (status & SD_EXIST))
-				set_bit(SD_NR, &(chip->need_reinit));
-		}
-		if (!CHECK_PID(chip, 0x5288) || CHECK_BARO_PKG(chip, QFN)) {
-			if (status & XD_INT) {
-				if (status & XD_EXIST) {
-					set_bit(XD_NR, &(chip->need_reset));
-				} else {
-					set_bit(XD_NR, &(chip->need_release));
-					chip->xd_reset_counter = 0;
-					chip->xd_show_cnt = 0;
-					clear_bit(XD_NR, &(chip->need_reset));
-				}
-			} else {
-				if (exit_ss && (status & XD_EXIST))
-					set_bit(XD_NR, &(chip->need_reinit));
-			}
-		}
-		if (status & MS_INT) {
-			if (status & MS_EXIST) {
-				set_bit(MS_NR, &(chip->need_reset));
-			} else {
-				set_bit(MS_NR, &(chip->need_release));
-				chip->ms_reset_counter = 0;
-				chip->ms_show_cnt = 0;
-				clear_bit(MS_NR, &(chip->need_reset));
-			}
-		} else {
-			if (exit_ss && (status & MS_EXIST))
-				set_bit(MS_NR, &(chip->need_reinit));
-		}
-	}
-
-#ifdef SUPPORT_OCP
-	chip->ocp_int = ocp_int & status;
-#endif
-
-	if (chip->sd_io) {
-		if (chip->int_reg & DATA_DONE_INT)
-			chip->int_reg &= ~(u32)DATA_DONE_INT;
-	}
-
-	return STATUS_SUCCESS;
-}
-
-void rtsx_do_before_power_down(struct rtsx_chip *chip, int pm_stat)
-{
-	int retval;
-
-	RTSX_DEBUGP("rtsx_do_before_power_down, pm_stat = %d\n", pm_stat);
-
-	rtsx_set_stat(chip, RTSX_STAT_SUSPEND);
-
-	retval = rtsx_force_power_on(chip, SSC_PDCTL);
-	if (retval != STATUS_SUCCESS)
-		return;
-
-	rtsx_release_cards(chip);
-	rtsx_disable_bus_int(chip);
-	turn_off_led(chip, LED_GPIO);
-
-#ifdef HW_AUTO_SWITCH_SD_BUS
-	if (chip->sd_io) {
-		chip->sdio_in_charge = 1;
-		if (CHECK_PID(chip, 0x5208)) {
-			rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08);
-			/* Enable sdio_bus_auto_switch */
-			rtsx_write_register(chip, 0xFE70, 0x80, 0x80);
-		} else if (CHECK_PID(chip, 0x5288)) {
-			rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08);
-			/* Enable sdio_bus_auto_switch */
-			rtsx_write_register(chip, 0xFE5A, 0x08, 0x08);
-		} else if (CHECK_PID(chip, 0x5209)) {
-			rtsx_write_register(chip, TLPTISTAT, 0x10, 0x10);
-			/* Enable sdio_bus_auto_switch */
-			rtsx_write_register(chip, SDIO_CFG, SDIO_BUS_AUTO_SWITCH, SDIO_BUS_AUTO_SWITCH);
-		}
-	}
-#endif
-
-	if (CHECK_PID(chip, 0x5208) && (chip->ic_version >= IC_VER_D)) {
-		/* u_force_clkreq_0 */
-		rtsx_write_register(chip, PETXCFG, 0x08, 0x08);
-	} else if (CHECK_PID(chip, 0x5209)) {
-		/* u_force_clkreq_0 */
-		rtsx_write_register(chip, PETXCFG, 0x08, 0x08);
-	}
-
-	if (pm_stat == PM_S1) {
-		RTSX_DEBUGP("Host enter S1\n");
-		rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, HOST_ENTER_S1);
-	} else if (pm_stat == PM_S3) {
-		if (chip->s3_pwr_off_delay > 0)
-			wait_timeout(chip->s3_pwr_off_delay);
-
-		RTSX_DEBUGP("Host enter S3\n");
-		rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, HOST_ENTER_S3);
-	}
-
-	if (chip->do_delink_before_power_down && chip->auto_delink_en)
-		rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 2);
-
-	rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
-
-	chip->cur_clk = 0;
-	chip->cur_card = 0;
-	chip->card_exist = 0;
-}
-
-void rtsx_enable_aspm(struct rtsx_chip *chip)
-{
-	if (chip->aspm_l0s_l1_en && chip->dynamic_aspm) {
-		if (!chip->aspm_enabled) {
-			RTSX_DEBUGP("Try to enable ASPM\n");
-			chip->aspm_enabled = 1;
-
-			if (chip->asic_code && CHECK_PID(chip, 0x5208))
-				rtsx_write_phy_register(chip, 0x07, 0);
-			if (CHECK_PID(chip, 0x5208)) {
-				rtsx_write_register(chip, ASPM_FORCE_CTL, 0xF3,
-					0x30 | chip->aspm_level[0]);
-			} else {
-				rtsx_write_config_byte(chip, LCTLR, chip->aspm_l0s_l1_en);
-			}
-
-			if (CHK_SDIO_EXIST(chip)) {
-				u16 val = chip->aspm_l0s_l1_en | 0x0100;
-				if (CHECK_PID(chip, 0x5288))
-					rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFFFF, val);
-				else
-					rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFFFF, val);
-			}
-		}
-	}
-
-	return;
-}
-
-void rtsx_disable_aspm(struct rtsx_chip *chip)
-{
-	if (CHECK_PID(chip, 0x5208))
-		rtsx_monitor_aspm_config(chip);
-
-	if (chip->aspm_l0s_l1_en && chip->dynamic_aspm) {
-		if (chip->aspm_enabled) {
-			RTSX_DEBUGP("Try to disable ASPM\n");
-			chip->aspm_enabled = 0;
-
-			if (chip->asic_code && CHECK_PID(chip, 0x5208))
-				rtsx_write_phy_register(chip, 0x07, 0x0129);
-			if (CHECK_PID(chip, 0x5208))
-				rtsx_write_register(chip, ASPM_FORCE_CTL, 0xF3, 0x30);
-			else
-				rtsx_write_config_byte(chip, LCTLR, 0x00);
-
-			wait_timeout(1);
-		}
-	}
-
-	return;
-}
-
-int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
-{
-	int retval;
-	int i, j;
-	u16 reg_addr;
-	u8 *ptr;
-
-	if (!buf)
-		TRACE_RET(chip, STATUS_ERROR);
-
-	ptr = buf;
-	reg_addr = PPBUF_BASE2;
-	for (i = 0; i < buf_len/256; i++) {
-		rtsx_init_cmd(chip);
-
-		for (j = 0; j < 256; j++)
-			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0);
-
-		retval = rtsx_send_cmd(chip, 0, 250);
-		if (retval < 0)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		memcpy(ptr, rtsx_get_cmd_data(chip), 256);
-		ptr += 256;
-	}
-
-	if (buf_len%256) {
-		rtsx_init_cmd(chip);
-
-		for (j = 0; j < buf_len%256; j++)
-			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0);
-
-		retval = rtsx_send_cmd(chip, 0, 250);
-		if (retval < 0)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	memcpy(ptr, rtsx_get_cmd_data(chip), buf_len%256);
-
-	return STATUS_SUCCESS;
-}
-
-int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
-{
-	int retval;
-	int i, j;
-	u16 reg_addr;
-	u8 *ptr;
-
-	if (!buf)
-		TRACE_RET(chip, STATUS_ERROR);
-
-	ptr = buf;
-	reg_addr = PPBUF_BASE2;
-	for (i = 0; i < buf_len/256; i++) {
-		rtsx_init_cmd(chip);
-
-		for (j = 0; j < 256; j++) {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF, *ptr);
-			ptr++;
-		}
-
-		retval = rtsx_send_cmd(chip, 0, 250);
-		if (retval < 0)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (buf_len%256) {
-		rtsx_init_cmd(chip);
-
-		for (j = 0; j < buf_len%256; j++) {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF, *ptr);
-			ptr++;
-		}
-
-		retval = rtsx_send_cmd(chip, 0, 250);
-		if (retval < 0)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int rtsx_check_chip_exist(struct rtsx_chip *chip)
-{
-	if (rtsx_readl(chip, 0) == 0xFFFFFFFF)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl)
-{
-	int retval;
-	u8 mask = 0;
-
-	if (ctl & SSC_PDCTL)
-		mask |= SSC_POWER_DOWN;
-
-#ifdef SUPPORT_OCP
-	if (ctl & OC_PDCTL) {
-		mask |= SD_OC_POWER_DOWN;
-		if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
-			mask |= MS_OC_POWER_DOWN;
-	}
-#endif
-
-	if (mask) {
-		retval = rtsx_write_register(chip, FPDCTL, mask, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		if (CHECK_PID(chip, 0x5288))
-			wait_timeout(200);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl)
-{
-	int retval;
-	u8 mask = 0, val = 0;
-
-	if (ctl & SSC_PDCTL)
-		mask |= SSC_POWER_DOWN;
-
-#ifdef SUPPORT_OCP
-	if (ctl & OC_PDCTL) {
-		mask |= SD_OC_POWER_DOWN;
-		if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
-			mask |= MS_OC_POWER_DOWN;
-	}
-#endif
-
-	if (mask) {
-		val = mask;
-		retval = rtsx_write_register(chip, FPDCTL, mask, val);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rts_pstor/rtsx_chip.h b/drivers/staging/rts_pstor/rtsx_chip.h
deleted file mode 100644
index 9f7cd82a..0000000
--- a/drivers/staging/rts_pstor/rtsx_chip.h
+++ /dev/null
@@ -1,989 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- * Header file
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#ifndef __REALTEK_RTSX_CHIP_H
-#define __REALTEK_RTSX_CHIP_H
-
-#include "rtsx.h"
-
-#define SUPPORT_CPRM
-#define SUPPORT_OCP
-#define SUPPORT_SDIO_ASPM
-#define SUPPORT_MAGIC_GATE
-#define SUPPORT_MSXC
-#define SUPPORT_SD_LOCK
-/* Hardware switch bus_ctl and cd_ctl automatically */
-#define HW_AUTO_SWITCH_SD_BUS
-/* Enable hardware interrupt write clear */
-#define HW_INT_WRITE_CLR
-/* #define LED_AUTO_BLINK */
-/* #define DISABLE_CARD_INT */
-
-#ifdef SUPPORT_MAGIC_GATE
-	/* Using NORMAL_WRITE instead of AUTO_WRITE to set ICV */
-	#define MG_SET_ICV_SLOW
-	/* HW may miss ERR/CMDNK signal when sampling INT status. */
-	#define MS_SAMPLE_INT_ERR
-	/* HW DO NOT support Wait_INT function during READ_BYTES transfer mode */
-	#define READ_BYTES_WAIT_INT
-#endif
-
-#ifdef SUPPORT_MSXC
-#define XC_POWERCLASS
-#define SUPPORT_PCGL_1P18
-#endif
-
-#ifndef LED_AUTO_BLINK
-#define REGULAR_BLINK
-#endif
-
-#define LED_BLINK_SPEED		5
-#define LED_TOGGLE_INTERVAL	6
-#define	GPIO_TOGGLE_THRESHOLD   1024
-#define LED_GPIO		0
-
-#define POLLING_INTERVAL	30
-
-#define TRACE_ITEM_CNT		64
-
-#ifndef STATUS_SUCCESS
-#define STATUS_SUCCESS		0
-#endif
-#ifndef STATUS_FAIL
-#define STATUS_FAIL		1
-#endif
-#ifndef STATUS_TIMEDOUT
-#define STATUS_TIMEDOUT		2
-#endif
-#ifndef STATUS_NOMEM
-#define STATUS_NOMEM		3
-#endif
-#ifndef STATUS_READ_FAIL
-#define STATUS_READ_FAIL	4
-#endif
-#ifndef STATUS_WRITE_FAIL
-#define STATUS_WRITE_FAIL	5
-#endif
-#ifndef STATUS_ERROR
-#define STATUS_ERROR		10
-#endif
-
-#define PM_S1			1
-#define PM_S3			3
-
-/*
- * Transport return codes
- */
-
-#define TRANSPORT_GOOD	   	0   /* Transport good, command good	   */
-#define TRANSPORT_FAILED  	1   /* Transport good, command failed   */
-#define TRANSPORT_NO_SENSE 	2  /* Command failed, no auto-sense    */
-#define TRANSPORT_ERROR   	3   /* Transport bad (i.e. device dead) */
-
-
-/*-----------------------------------
-    Start-Stop-Unit
------------------------------------*/
-#define STOP_MEDIUM			0x00    /* access disable         */
-#define MAKE_MEDIUM_READY		0x01    /* access enable          */
-#define UNLOAD_MEDIUM			0x02    /* unload                 */
-#define LOAD_MEDIUM			0x03    /* load                   */
-
-/*-----------------------------------
-    STANDARD_INQUIRY
------------------------------------*/
-#define QULIFIRE                0x00
-#define AENC_FNC                0x00
-#define TRML_IOP                0x00
-#define REL_ADR                 0x00
-#define WBUS_32                 0x00
-#define WBUS_16                 0x00
-#define SYNC                    0x00
-#define LINKED                  0x00
-#define CMD_QUE                 0x00
-#define SFT_RE                  0x00
-
-#define VEN_ID_LEN              8               /* Vendor ID Length         */
-#define PRDCT_ID_LEN            16              /* Product ID Length        */
-#define PRDCT_REV_LEN           4               /* Product LOT Length       */
-
-/* Dynamic flag definitions: used in set_bit() etc. */
-#define RTSX_FLIDX_TRANS_ACTIVE		18  /* 0x00040000  transfer is active */
-#define RTSX_FLIDX_ABORTING		20  /* 0x00100000  abort is in progress */
-#define RTSX_FLIDX_DISCONNECTING	21  /* 0x00200000  disconnect in progress */
-#define ABORTING_OR_DISCONNECTING	((1UL << US_FLIDX_ABORTING) | \
-					 (1UL << US_FLIDX_DISCONNECTING))
-#define RTSX_FLIDX_RESETTING		22  /* 0x00400000  device reset in progress */
-#define RTSX_FLIDX_TIMED_OUT		23  /* 0x00800000  SCSI midlayer timed out  */
-
-#define DRCT_ACCESS_DEV         0x00    /* Direct Access Device      */
-#define RMB_DISC                0x80    /* The Device is Removable   */
-#define ANSI_SCSI2              0x02    /* Based on ANSI-SCSI2       */
-
-#define SCSI                    0x00    /* Interface ID              */
-
-#define	WRITE_PROTECTED_MEDIA 0x07
-
-/*---- sense key ----*/
-#define ILI                     0x20    /* ILI bit is on                    */
-
-#define NO_SENSE                0x00    /* not exist sense key              */
-#define RECOVER_ERR             0x01    /* Target/Logical unit is recoverd  */
-#define NOT_READY               0x02    /* Logical unit is not ready        */
-#define MEDIA_ERR               0x03    /* medium/data error                */
-#define HARDWARE_ERR            0x04    /* hardware error                   */
-#define ILGAL_REQ               0x05    /* CDB/parameter/identify msg error */
-#define UNIT_ATTENTION          0x06    /* unit attention condition occur   */
-#define DAT_PRTCT               0x07    /* read/write is desable            */
-#define BLNC_CHK                0x08    /* find blank/DOF in read           */
-					/* write to unblank area            */
-#define CPY_ABRT                0x0a    /* Copy/Compare/Copy&Verify illgal  */
-#define ABRT_CMD                0x0b    /* Target make the command in error */
-#define EQUAL                   0x0c    /* Search Data end with Equal       */
-#define VLM_OVRFLW              0x0d    /* Some data are left in buffer     */
-#define MISCMP                  0x0e    /* find inequality                  */
-
-#define READ_ERR                -1
-#define WRITE_ERR               -2
-
-#define	FIRST_RESET		0x01
-#define	USED_EXIST		0x02
-
-/*-----------------------------------
-    SENSE_DATA
------------------------------------*/
-/*---- valid ----*/
-#define SENSE_VALID             0x80    /* Sense data is valid as SCSI2     */
-#define SENSE_INVALID           0x00    /* Sense data is invalid as SCSI2   */
-
-/*---- error code ----*/
-#define CUR_ERR                 0x70    /* current error                    */
-#define DEF_ERR                 0x71    /* specific command error           */
-
-/*---- sense key Information ----*/
-#define SNSKEYINFO_LEN          3       /* length of sense key information   */
-
-#define SKSV                    0x80
-#define CDB_ILLEGAL             0x40
-#define DAT_ILLEGAL             0x00
-#define BPV                     0x08
-#define BIT_ILLEGAL0            0       /* bit0 is illegal                  */
-#define BIT_ILLEGAL1            1       /* bit1 is illegal                  */
-#define BIT_ILLEGAL2            2       /* bit2 is illegal                  */
-#define BIT_ILLEGAL3            3       /* bit3 is illegal                  */
-#define BIT_ILLEGAL4            4       /* bit4 is illegal                  */
-#define BIT_ILLEGAL5            5       /* bit5 is illegal                  */
-#define BIT_ILLEGAL6            6       /* bit6 is illegal                  */
-#define BIT_ILLEGAL7            7       /* bit7 is illegal                  */
-
-/*---- ASC ----*/
-#define ASC_NO_INFO             0x00
-#define ASC_MISCMP              0x1d
-#define ASC_INVLD_CDB           0x24
-#define ASC_INVLD_PARA          0x26
-#define ASC_LU_NOT_READY	0x04
-#define ASC_WRITE_ERR           0x0c
-#define ASC_READ_ERR            0x11
-#define ASC_LOAD_EJCT_ERR       0x53
-#define	ASC_MEDIA_NOT_PRESENT	0x3A
-#define	ASC_MEDIA_CHANGED	0x28
-#define	ASC_MEDIA_IN_PROCESS	0x04
-#define	ASC_WRITE_PROTECT	0x27
-#define ASC_LUN_NOT_SUPPORTED	0x25
-
-/*---- ASQC ----*/
-#define ASCQ_NO_INFO            0x00
-#define	ASCQ_MEDIA_IN_PROCESS	0x01
-#define ASCQ_MISCMP             0x00
-#define ASCQ_INVLD_CDB          0x00
-#define ASCQ_INVLD_PARA         0x02
-#define ASCQ_LU_NOT_READY	0x02
-#define ASCQ_WRITE_ERR          0x02
-#define ASCQ_READ_ERR           0x00
-#define ASCQ_LOAD_EJCT_ERR      0x00
-#define	ASCQ_WRITE_PROTECT	0x00
-
-
-struct sense_data_t {
-    unsigned char   err_code;		/* error code */
-						/* bit7 : valid                    */
-						/*   (1 : SCSI2)                    */
-						/*   (0 : Vendor specific)          */
-						/* bit6-0 : error code             */
-						/*  (0x70 : current error)          */
-						/*  (0x71 : specific command error) */
-    unsigned char   seg_no;		/* segment No.                      */
-    unsigned char   sense_key;		/* byte5 : ILI                      */
-						/* bit3-0 : sense key              */
-    unsigned char   info[4];		/* information                       */
-    unsigned char   ad_sense_len;	/* additional sense data length     */
-    unsigned char   cmd_info[4];	/* command specific information      */
-    unsigned char   asc;		/* ASC                              */
-    unsigned char   ascq;		/* ASCQ                             */
-    unsigned char   rfu;		/* FRU                              */
-    unsigned char   sns_key_info[3];	/* sense key specific information    */
-};
-
-/* PCI Operation Register Address */
-#define RTSX_HCBAR		0x00
-#define RTSX_HCBCTLR		0x04
-#define RTSX_HDBAR		0x08
-#define RTSX_HDBCTLR		0x0C
-#define RTSX_HAIMR		0x10
-#define RTSX_BIPR		0x14
-#define RTSX_BIER		0x18
-
-/* Host command buffer control register */
-#define STOP_CMD		(0x01 << 28)
-
-/* Host data buffer control register */
-#define SDMA_MODE		0x00
-#define ADMA_MODE		(0x02 << 26)
-#define STOP_DMA		(0x01 << 28)
-#define TRIG_DMA		(0x01 << 31)
-
-/* Bus interrupt pending register */
-#define CMD_DONE_INT		(1 << 31)
-#define DATA_DONE_INT		(1 << 30)
-#define TRANS_OK_INT		(1 << 29)
-#define TRANS_FAIL_INT		(1 << 28)
-#define XD_INT			(1 << 27)
-#define MS_INT			(1 << 26)
-#define SD_INT			(1 << 25)
-#define GPIO0_INT		(1 << 24)
-#define OC_INT			(1 << 23)
-#define SD_WRITE_PROTECT	(1 << 19)
-#define XD_EXIST		(1 << 18)
-#define MS_EXIST		(1 << 17)
-#define SD_EXIST		(1 << 16)
-#define DELINK_INT		GPIO0_INT
-#define MS_OC_INT		(1 << 23)
-#define SD_OC_INT		(1 << 22)
-
-#define CARD_INT		(XD_INT | MS_INT | SD_INT)
-#define NEED_COMPLETE_INT	(DATA_DONE_INT | TRANS_OK_INT | TRANS_FAIL_INT)
-#define RTSX_INT		(CMD_DONE_INT | NEED_COMPLETE_INT | CARD_INT | GPIO0_INT | OC_INT)
-
-#define CARD_EXIST		(XD_EXIST | MS_EXIST | SD_EXIST)
-
-/* Bus interrupt enable register */
-#define CMD_DONE_INT_EN		(1 << 31)
-#define DATA_DONE_INT_EN	(1 << 30)
-#define TRANS_OK_INT_EN		(1 << 29)
-#define TRANS_FAIL_INT_EN	(1 << 28)
-#define XD_INT_EN		(1 << 27)
-#define MS_INT_EN		(1 << 26)
-#define SD_INT_EN		(1 << 25)
-#define GPIO0_INT_EN		(1 << 24)
-#define OC_INT_EN		(1 << 23)
-#define DELINK_INT_EN		GPIO0_INT_EN
-#define MS_OC_INT_EN		(1 << 23)
-#define SD_OC_INT_EN		(1 << 22)
-
-
-#define READ_REG_CMD		0
-#define WRITE_REG_CMD		1
-#define CHECK_REG_CMD		2
-
-#define HOST_TO_DEVICE		0
-#define DEVICE_TO_HOST		1
-
-
-#define RTSX_RESV_BUF_LEN	4096
-#define HOST_CMDS_BUF_LEN	1024
-#define HOST_SG_TBL_BUF_LEN	(RTSX_RESV_BUF_LEN - HOST_CMDS_BUF_LEN)
-
-#define SD_NR		2
-#define MS_NR		3
-#define XD_NR		4
-#define SPI_NR		7
-#define SD_CARD		(1 << SD_NR)
-#define MS_CARD		(1 << MS_NR)
-#define XD_CARD		(1 << XD_NR)
-#define SPI_CARD	(1 << SPI_NR)
-
-#define MAX_ALLOWED_LUN_CNT	8
-
-#define XD_FREE_TABLE_CNT	1200
-#define MS_FREE_TABLE_CNT	512
-
-
-/* Bit Operation */
-#define SET_BIT(data, idx)	((data) |= 1 << (idx))
-#define CLR_BIT(data, idx)	((data) &= ~(1 << (idx)))
-#define CHK_BIT(data, idx)	((data) & (1 << (idx)))
-
-/* SG descriptor */
-#define SG_INT			0x04
-#define SG_END			0x02
-#define SG_VALID		0x01
-
-#define SG_NO_OP		0x00
-#define SG_TRANS_DATA		(0x02 << 4)
-#define SG_LINK_DESC		(0x03 << 4)
-
-struct rtsx_chip;
-
-typedef int (*card_rw_func)(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 sec_addr, u16 sec_cnt);
-
-/* Supported Clock */
-enum card_clock	{CLK_20 = 1, CLK_30, CLK_40, CLK_50, CLK_60, CLK_80, CLK_100, CLK_120, CLK_150, CLK_200};
-
-enum RTSX_STAT	{RTSX_STAT_INIT, RTSX_STAT_IDLE, RTSX_STAT_RUN, RTSX_STAT_SS,
-		RTSX_STAT_DELINK, RTSX_STAT_SUSPEND, RTSX_STAT_ABORT, RTSX_STAT_DISCONNECT};
-enum IC_VER	{IC_VER_AB, IC_VER_C = 2, IC_VER_D = 3};
-
-#define MAX_RESET_CNT		3
-
-/* For MS Card */
-#define MAX_DEFECTIVE_BLOCK     10
-
-struct zone_entry {
-	u16 *l2p_table;
-	u16 *free_table;
-	u16 defect_list[MAX_DEFECTIVE_BLOCK];  /* For MS card only */
-	int set_index;
-	int get_index;
-	int unused_blk_cnt;
-	int disable_count;
-	/* To indicate whether the L2P table of this zone has been built. */
-	int build_flag;
-};
-
-#define TYPE_SD			0x0000
-#define TYPE_MMC		0x0001
-
-/* TYPE_SD */
-#define SD_HS			0x0100
-#define SD_SDR50		0x0200
-#define SD_DDR50		0x0400
-#define SD_SDR104		0x0800
-#define SD_HCXC			0x1000
-
-/* TYPE_MMC */
-#define MMC_26M			0x0100
-#define MMC_52M			0x0200
-#define MMC_4BIT		0x0400
-#define MMC_8BIT		0x0800
-#define MMC_SECTOR_MODE		0x1000
-#define MMC_DDR52		0x2000
-
-/* SD card */
-#define CHK_SD(sd_card)			(((sd_card)->sd_type & 0xFF) == TYPE_SD)
-#define CHK_SD_HS(sd_card)		(CHK_SD(sd_card) && ((sd_card)->sd_type & SD_HS))
-#define CHK_SD_SDR50(sd_card)		(CHK_SD(sd_card) && ((sd_card)->sd_type & SD_SDR50))
-#define CHK_SD_DDR50(sd_card)		(CHK_SD(sd_card) && ((sd_card)->sd_type & SD_DDR50))
-#define CHK_SD_SDR104(sd_card)		(CHK_SD(sd_card) && ((sd_card)->sd_type & SD_SDR104))
-#define CHK_SD_HCXC(sd_card)		(CHK_SD(sd_card) && ((sd_card)->sd_type & SD_HCXC))
-#define CHK_SD_HC(sd_card)		(CHK_SD_HCXC(sd_card) && ((sd_card)->capacity <= 0x4000000))
-#define CHK_SD_XC(sd_card)		(CHK_SD_HCXC(sd_card) && ((sd_card)->capacity > 0x4000000))
-#define CHK_SD30_SPEED(sd_card)		(CHK_SD_SDR50(sd_card) || CHK_SD_DDR50(sd_card) || CHK_SD_SDR104(sd_card))
-
-#define SET_SD(sd_card)			((sd_card)->sd_type = TYPE_SD)
-#define SET_SD_HS(sd_card)		((sd_card)->sd_type |= SD_HS)
-#define SET_SD_SDR50(sd_card)		((sd_card)->sd_type |= SD_SDR50)
-#define SET_SD_DDR50(sd_card)		((sd_card)->sd_type |= SD_DDR50)
-#define SET_SD_SDR104(sd_card)		((sd_card)->sd_type |= SD_SDR104)
-#define SET_SD_HCXC(sd_card)		((sd_card)->sd_type |= SD_HCXC)
-
-#define CLR_SD_HS(sd_card)		((sd_card)->sd_type &= ~SD_HS)
-#define CLR_SD_SDR50(sd_card)		((sd_card)->sd_type &= ~SD_SDR50)
-#define CLR_SD_DDR50(sd_card)		((sd_card)->sd_type &= ~SD_DDR50)
-#define CLR_SD_SDR104(sd_card)		((sd_card)->sd_type &= ~SD_SDR104)
-#define CLR_SD_HCXC(sd_card)		((sd_card)->sd_type &= ~SD_HCXC)
-
-/* MMC card */
-#define CHK_MMC(sd_card)		(((sd_card)->sd_type & 0xFF) == TYPE_MMC)
-#define CHK_MMC_26M(sd_card)		(CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_26M))
-#define CHK_MMC_52M(sd_card)		(CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_52M))
-#define CHK_MMC_4BIT(sd_card)		(CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_4BIT))
-#define CHK_MMC_8BIT(sd_card)		(CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_8BIT))
-#define CHK_MMC_SECTOR_MODE(sd_card)	(CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_SECTOR_MODE))
-#define CHK_MMC_DDR52(sd_card)		(CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_DDR52))
-
-#define SET_MMC(sd_card)		((sd_card)->sd_type = TYPE_MMC)
-#define SET_MMC_26M(sd_card)		((sd_card)->sd_type |= MMC_26M)
-#define SET_MMC_52M(sd_card)		((sd_card)->sd_type |= MMC_52M)
-#define SET_MMC_4BIT(sd_card)		((sd_card)->sd_type |= MMC_4BIT)
-#define SET_MMC_8BIT(sd_card)		((sd_card)->sd_type |= MMC_8BIT)
-#define SET_MMC_SECTOR_MODE(sd_card)	((sd_card)->sd_type |= MMC_SECTOR_MODE)
-#define SET_MMC_DDR52(sd_card)		((sd_card)->sd_type |= MMC_DDR52)
-
-#define CLR_MMC_26M(sd_card)		((sd_card)->sd_type &= ~MMC_26M)
-#define CLR_MMC_52M(sd_card)		((sd_card)->sd_type &= ~MMC_52M)
-#define CLR_MMC_4BIT(sd_card)		((sd_card)->sd_type &= ~MMC_4BIT)
-#define CLR_MMC_8BIT(sd_card)		((sd_card)->sd_type &= ~MMC_8BIT)
-#define CLR_MMC_SECTOR_MODE(sd_card)	((sd_card)->sd_type &= ~MMC_SECTOR_MODE)
-#define CLR_MMC_DDR52(sd_card)		((sd_card)->sd_type &= ~MMC_DDR52)
-
-#define CHK_MMC_HS(sd_card)		(CHK_MMC_52M(sd_card) && CHK_MMC_26M(sd_card))
-#define CLR_MMC_HS(sd_card)			\
-do {						\
-	CLR_MMC_DDR52(sd_card);			\
-	CLR_MMC_52M(sd_card);			\
-	CLR_MMC_26M(sd_card);			\
-} while (0)
-
-#define SD_SUPPORT_CLASS_TEN		0x01
-#define SD_SUPPORT_1V8			0x02
-
-#define SD_SET_CLASS_TEN(sd_card)	((sd_card)->sd_setting |= SD_SUPPORT_CLASS_TEN)
-#define SD_CHK_CLASS_TEN(sd_card)	((sd_card)->sd_setting & SD_SUPPORT_CLASS_TEN)
-#define SD_CLR_CLASS_TEN(sd_card)	((sd_card)->sd_setting &= ~SD_SUPPORT_CLASS_TEN)
-#define SD_SET_1V8(sd_card)		((sd_card)->sd_setting |= SD_SUPPORT_1V8)
-#define SD_CHK_1V8(sd_card)		((sd_card)->sd_setting & SD_SUPPORT_1V8)
-#define SD_CLR_1V8(sd_card)		((sd_card)->sd_setting &= ~SD_SUPPORT_1V8)
-
-struct sd_info {
-	u16 sd_type;
-	u8 err_code;
-	u8 sd_data_buf_ready;
-	u32 sd_addr;
-	u32 capacity;
-
-	u8 raw_csd[16];
-	u8 raw_scr[8];
-
-	/* Sequential RW */
-	int seq_mode;
-	enum dma_data_direction pre_dir;
-	u32 pre_sec_addr;
-	u16 pre_sec_cnt;
-
-	int cleanup_counter;
-
-	int sd_clock;
-
-	int mmc_dont_switch_bus;
-
-#ifdef SUPPORT_CPRM
-	int sd_pass_thru_en;
-	int pre_cmd_err;
-	u8 last_rsp_type;
-	u8 rsp[17];
-#endif
-
-	u8 func_group1_mask;
-	u8 func_group2_mask;
-	u8 func_group3_mask;
-	u8 func_group4_mask;
-
-	u8 sd_switch_fail;
-	u8 sd_read_phase;
-
-#ifdef SUPPORT_SD_LOCK
-	u8 sd_lock_status;
-	u8 sd_erase_status;
-	u8 sd_lock_notify;
-#endif
-	int need_retune;
-};
-
-struct xd_delay_write_tag {
-	u32 old_phyblock;
-	u32 new_phyblock;
-	u32 logblock;
-	u8 pageoff;
-	u8 delay_write_flag;
-};
-
-struct xd_info {
-	u8 maker_code;
-	u8 device_code;
-	u8 block_shift;
-	u8 page_off;
-	u8 addr_cycle;
-	u16 cis_block;
-	u8 multi_flag;
-	u8 err_code;
-	u32 capacity;
-
-	struct zone_entry *zone;
-	int zone_cnt;
-
-	struct xd_delay_write_tag delay_write;
-	int cleanup_counter;
-
-	int xd_clock;
-};
-
-#define MODE_512_SEQ		0x01
-#define MODE_2K_SEQ		0x02
-
-#define TYPE_MS			0x0000
-#define TYPE_MSPRO		0x0001
-
-#define MS_4BIT			0x0100
-#define MS_8BIT			0x0200
-#define MS_HG			0x0400
-#define MS_XC			0x0800
-
-#define HG8BIT			(MS_HG | MS_8BIT)
-
-#define CHK_MSPRO(ms_card)	(((ms_card)->ms_type & 0xFF) == TYPE_MSPRO)
-#define CHK_HG8BIT(ms_card)	(CHK_MSPRO(ms_card) && (((ms_card)->ms_type & HG8BIT) == HG8BIT))
-#define CHK_MSXC(ms_card)	(CHK_MSPRO(ms_card) && ((ms_card)->ms_type & MS_XC))
-#define CHK_MSHG(ms_card)	(CHK_MSPRO(ms_card) && ((ms_card)->ms_type & MS_HG))
-
-#define CHK_MS8BIT(ms_card)	(((ms_card)->ms_type & MS_8BIT))
-#define CHK_MS4BIT(ms_card)	(((ms_card)->ms_type & MS_4BIT))
-
-struct ms_delay_write_tag {
-	u16 old_phyblock;
-	u16 new_phyblock;
-	u16 logblock;
-	u8 pageoff;
-	u8 delay_write_flag;
-};
-
-struct ms_info {
-	u16 ms_type;
-	u8 block_shift;
-	u8 page_off;
-	u16 total_block;
-	u16 boot_block;
-	u32 capacity;
-
-	u8 check_ms_flow;
-	u8 switch_8bit_fail;
-	u8 err_code;
-
-	struct zone_entry *segment;
-	int segment_cnt;
-
-	int pro_under_formatting;
-	int format_status;
-	u16 progress;
-	u8 raw_sys_info[96];
-#ifdef SUPPORT_PCGL_1P18
-	u8 raw_model_name[48];
-#endif
-
-	u8 multi_flag;
-
-	/* Sequential RW */
-	u8 seq_mode;
-	enum dma_data_direction pre_dir;
-	u32 pre_sec_addr;
-	u16 pre_sec_cnt;
-	u32 total_sec_cnt;
-
-	struct ms_delay_write_tag delay_write;
-
-	int cleanup_counter;
-
-	int ms_clock;
-
-#ifdef SUPPORT_MAGIC_GATE
-	u8 magic_gate_id[16];
-	u8 mg_entry_num;
-	int mg_auth;    /* flag to indicate authentication process */
-#endif
-};
-
-struct spi_info {
-	u8 use_clk;
-	u8 write_en;
-	u16 clk_div;
-	u8 err_code;
-
-	int spi_clock;
-};
-
-
-#ifdef _MSG_TRACE
-struct trace_msg_t {
-	u16 line;
-#define MSG_FUNC_LEN 64
-	char func[MSG_FUNC_LEN];
-#define MSG_FILE_LEN 32
-	char file[MSG_FILE_LEN];
-#define TIME_VAL_LEN 16
-	u8 timeval_buf[TIME_VAL_LEN];
-	u8 valid;
-};
-#endif
-
-/************/
-/* LUN mode */
-/************/
-/* Single LUN, support xD/SD/MS */
-#define DEFAULT_SINGLE		0
-/* 2 LUN mode, support SD/MS */
-#define SD_MS_2LUN		1
-/* Single LUN, but only support SD/MS, for Barossa LQFP */
-#define SD_MS_1LUN		2
-
-#define LAST_LUN_MODE		2
-
-/* Barossa package */
-#define QFN		0
-#define LQFP		1
-
-/******************/
-/* sd_ctl bit map */
-/******************/
-/* SD push point control, bit 0, 1 */
-#define SD_PUSH_POINT_CTL_MASK		0x03
-#define SD_PUSH_POINT_DELAY		0x01
-#define SD_PUSH_POINT_AUTO		0x02
-/* SD sample point control, bit 2, 3 */
-#define SD_SAMPLE_POINT_CTL_MASK	0x0C
-#define SD_SAMPLE_POINT_DELAY		0x04
-#define SD_SAMPLE_POINT_AUTO		0x08
-/* SD DDR Tx phase set by user, bit 4 */
-#define SD_DDR_TX_PHASE_SET_BY_USER	0x10
-/* MMC DDR Tx phase set by user, bit 5 */
-#define MMC_DDR_TX_PHASE_SET_BY_USER	0x20
-/* Support MMC DDR mode, bit 6 */
-#define SUPPORT_MMC_DDR_MODE		0x40
-/* Reset MMC at first */
-#define RESET_MMC_FIRST			0x80
-
-#define SEQ_START_CRITERIA		0x20
-
-/* MS Power Class En */
-#define POWER_CLASS_2_EN		0x02
-#define POWER_CLASS_1_EN		0x01
-
-#define MAX_SHOW_CNT			10
-#define MAX_RESET_CNT			3
-
-#define SDIO_EXIST			0x01
-#define SDIO_IGNORED			0x02
-
-#define CHK_SDIO_EXIST(chip)		((chip)->sdio_func_exist & SDIO_EXIST)
-#define SET_SDIO_EXIST(chip)		((chip)->sdio_func_exist |= SDIO_EXIST)
-#define CLR_SDIO_EXIST(chip)		((chip)->sdio_func_exist &= ~SDIO_EXIST)
-
-#define CHK_SDIO_IGNORED(chip)		((chip)->sdio_func_exist & SDIO_IGNORED)
-#define SET_SDIO_IGNORED(chip)		((chip)->sdio_func_exist |= SDIO_IGNORED)
-#define CLR_SDIO_IGNORED(chip)		((chip)->sdio_func_exist &= ~SDIO_IGNORED)
-
-struct rtsx_chip {
-	rtsx_dev_t 		*rtsx;
-
-	u32 			int_reg;		/* Bus interrupt pending register */
-	char 			max_lun;
-	void 			*context;
-
-	void 			*host_cmds_ptr;		/* host commands buffer pointer */
-	dma_addr_t		host_cmds_addr;
-	int 			ci;			/* Command Index */
-
-	void			*host_sg_tbl_ptr;	/* SG descriptor table */
-	dma_addr_t		host_sg_tbl_addr;
-	int			sgi;			/* SG entry index */
-
-	struct scsi_cmnd	*srb;		 	/* current srb */
-	struct sense_data_t 	sense_buffer[MAX_ALLOWED_LUN_CNT];
-
-	int			cur_clk;		/* current card clock */
-
-	/* Current accessed card */
-	int 			cur_card;
-
-	unsigned long 		need_release;		/* need release bit map */
-	unsigned long 		need_reset;		/* need reset bit map */
-	/* Flag to indicate that this card is just resumed from SS state,
-	 * and need released before being resetted
-	 */
-	unsigned long 		need_reinit;
-
-	int 			rw_need_retry;
-
-#ifdef SUPPORT_OCP
-	u32 			ocp_int;
-	u8 			ocp_stat;
-#endif
-
-	u8 			card_exist;		/* card exist bit map (physical exist) */
-	u8 			card_ready;		/* card ready bit map (reset successfully) */
-	u8 			card_fail;		/* card reset fail bit map */
-	u8 			card_ejected;		/* card ejected bit map */
-	u8 			card_wp;		/* card write protected bit map */
-
-	u8 			lun_mc;			/* flag to indicate whether to answer MediaChange */
-
-#ifndef LED_AUTO_BLINK
-	int 			led_toggle_counter;
-#endif
-
-	int 			sd_reset_counter;
-	int 			xd_reset_counter;
-	int 			ms_reset_counter;
-
-	/* card bus width */
-	u8			card_bus_width[MAX_ALLOWED_LUN_CNT];
-	/* card capacity */
-	u32 			capacity[MAX_ALLOWED_LUN_CNT];
-	/* read/write card function pointer */
-	card_rw_func 		rw_card[MAX_ALLOWED_LUN_CNT];
-	/* read/write capacity, used for GPIO Toggle */
-	u32			rw_cap[MAX_ALLOWED_LUN_CNT];
-	/* card to lun mapping table */
-	u8			card2lun[32];
-	/* lun to card mapping table */
-	u8			lun2card[MAX_ALLOWED_LUN_CNT];
-
-	int 			rw_fail_cnt[MAX_ALLOWED_LUN_CNT];
-
-	int 			sd_show_cnt;
-	int 			xd_show_cnt;
-	int 			ms_show_cnt;
-
-	/* card information */
-	struct sd_info		sd_card;
-	struct xd_info		xd_card;
-	struct ms_info		ms_card;
-
-	struct spi_info		spi;
-
-#ifdef _MSG_TRACE
-	struct trace_msg_t	trace_msg[TRACE_ITEM_CNT];
-	int 			msg_idx;
-#endif
-
-	int 			auto_delink_cnt;
-	int 			auto_delink_allowed;
-
-	int 			aspm_enabled;
-
-	int 			sdio_aspm;
-	int 			sdio_idle;
-	int 			sdio_counter;
-	u8 			sdio_raw_data[12];
-
-	u8 			sd_io;
-	u8 			sd_int;
-
-	u8 			rtsx_flag;
-
-	int 			ss_counter;
-	int 			idle_counter;
-	enum RTSX_STAT 		rtsx_stat;
-
-	u16 			vendor_id;
-	u16			product_id;
-	u8 			ic_version;
-
-	int			driver_first_load;
-
-#ifdef HW_AUTO_SWITCH_SD_BUS
-	int 			sdio_in_charge;
-#endif
-
-	u8 			aspm_level[2];
-
-	int 			chip_insert_with_sdio;
-
-	/* Options */
-
-	int adma_mode;
-
-	int auto_delink_en;
-	int ss_en;
-	u8 lun_mode;
-	u8 aspm_l0s_l1_en;
-
-	int power_down_in_ss;
-
-	int sdr104_en;
-	int ddr50_en;
-	int sdr50_en;
-
-	int baro_pkg;
-
-	int asic_code;
-	int phy_debug_mode;
-	int hw_bypass_sd;
-	int sdio_func_exist;
-	int aux_pwr_exist;
-	u8 ms_power_class_en;
-
-	int mspro_formatter_enable;
-
-	int remote_wakeup_en;
-
-	int ignore_sd;
-	int use_hw_setting;
-
-	int ss_idle_period;
-
-	int dynamic_aspm;
-
-	int fpga_sd_sdr104_clk;
-	int fpga_sd_ddr50_clk;
-	int fpga_sd_sdr50_clk;
-	int fpga_sd_hs_clk;
-	int fpga_mmc_52m_clk;
-	int fpga_ms_hg_clk;
-	int fpga_ms_4bit_clk;
-	int fpga_ms_1bit_clk;
-
-	int asic_sd_sdr104_clk;
-	int asic_sd_ddr50_clk;
-	int asic_sd_sdr50_clk;
-	int asic_sd_hs_clk;
-	int asic_mmc_52m_clk;
-	int asic_ms_hg_clk;
-	int asic_ms_4bit_clk;
-	int asic_ms_1bit_clk;
-
-	u8 ssc_depth_sd_sdr104;
-	u8 ssc_depth_sd_ddr50;
-	u8 ssc_depth_sd_sdr50;
-	u8 ssc_depth_sd_hs;
-	u8 ssc_depth_mmc_52m;
-	u8 ssc_depth_ms_hg;
-	u8 ssc_depth_ms_4bit;
-	u8 ssc_depth_low_speed;
-
-	u8 card_drive_sel;
-	u8 sd30_drive_sel_1v8;
-	u8 sd30_drive_sel_3v3;
-
-	u8 sd_400mA_ocp_thd;
-	u8 sd_800mA_ocp_thd;
-	u8 ms_ocp_thd;
-
-	int ssc_en;
-	int msi_en;
-
-	int xd_timeout;
-	int sd_timeout;
-	int ms_timeout;
-	int mspro_timeout;
-
-	int auto_power_down;
-
-	int sd_ddr_tx_phase;
-	int mmc_ddr_tx_phase;
-	int sd_default_tx_phase;
-	int sd_default_rx_phase;
-
-	int pmos_pwr_on_interval;
-	int sd_voltage_switch_delay;
-	int s3_pwr_off_delay;
-
-	int force_clkreq_0;
-	int ft2_fast_mode;
-
-	int do_delink_before_power_down;
-	int polling_config;
-	int sdio_retry_cnt;
-
-	int delink_stage1_step;
-	int delink_stage2_step;
-	int delink_stage3_step;
-
-	int auto_delink_in_L1;
-	int hp_watch_bios_hotplug;
-	int support_ms_8bit;
-
-	u8 blink_led;
-	u8 phy_voltage;
-	u8 max_payload;
-
-	u32 sd_speed_prior;
-	u32 sd_current_prior;
-	u32 sd_ctl;
-};
-
-#define rtsx_set_stat(chip, stat)				\
-do {								\
-	if ((stat) != RTSX_STAT_IDLE) {				\
-		(chip)->idle_counter = 0;			\
-	}							\
-	(chip)->rtsx_stat = (enum RTSX_STAT)(stat);		\
-} while (0)
-#define rtsx_get_stat(chip)		((chip)->rtsx_stat)
-#define rtsx_chk_stat(chip, stat)	((chip)->rtsx_stat == (stat))
-
-#define RTSX_SET_DELINK(chip)	((chip)->rtsx_flag |= 0x01)
-#define RTSX_CLR_DELINK(chip)	((chip)->rtsx_flag &= 0xFE)
-#define RTSX_TST_DELINK(chip)	((chip)->rtsx_flag & 0x01)
-
-#define CHECK_PID(chip, pid)		((chip)->product_id == (pid))
-#define CHECK_BARO_PKG(chip, pkg)	((chip)->baro_pkg == (pkg))
-#define CHECK_LUN_MODE(chip, mode)	((chip)->lun_mode == (mode))
-
-/* Power down control */
-#define SSC_PDCTL		0x01
-#define OC_PDCTL		0x02
-
-int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl);
-int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl);
-
-void rtsx_disable_card_int(struct rtsx_chip *chip);
-void rtsx_enable_card_int(struct rtsx_chip *chip);
-void rtsx_enable_bus_int(struct rtsx_chip *chip);
-void rtsx_disable_bus_int(struct rtsx_chip *chip);
-int rtsx_reset_chip(struct rtsx_chip *chip);
-int rtsx_init_chip(struct rtsx_chip *chip);
-void rtsx_release_chip(struct rtsx_chip *chip);
-void rtsx_polling_func(struct rtsx_chip *chip);
-void rtsx_undo_delink(struct rtsx_chip *chip);
-void rtsx_stop_cmd(struct rtsx_chip *chip, int card);
-int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data);
-int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data);
-int rtsx_write_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 mask, u32 val);
-int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val);
-int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, int len);
-int rtsx_read_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, int len);
-int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val);
-int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val);
-int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val);
-int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val);
-int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit);
-int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit);
-int rtsx_check_link_ready(struct rtsx_chip *chip);
-void rtsx_enter_ss(struct rtsx_chip *chip);
-void rtsx_exit_ss(struct rtsx_chip *chip);
-int rtsx_pre_handle_interrupt(struct rtsx_chip *chip);
-void rtsx_enter_L1(struct rtsx_chip *chip);
-void rtsx_exit_L1(struct rtsx_chip *chip);
-void rtsx_do_before_power_down(struct rtsx_chip *chip, int pm_stat);
-void rtsx_enable_aspm(struct rtsx_chip *chip);
-void rtsx_disable_aspm(struct rtsx_chip *chip);
-int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len);
-int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len);
-int rtsx_check_chip_exist(struct rtsx_chip *chip);
-
-#define RTSX_WRITE_REG(chip, addr, mask, data)					\
-do {										\
-	int retval = rtsx_write_register((chip), (addr), (mask), (data));	\
-	if (retval != STATUS_SUCCESS) {						\
-		TRACE_RET((chip), retval);					\
-	}									\
-} while (0)
-
-#define RTSX_READ_REG(chip, addr, data)						\
-do {										\
-	int retval = rtsx_read_register((chip), (addr), (data));		\
-	if (retval != STATUS_SUCCESS) {						\
-		TRACE_RET((chip), retval);					\
-	}									\
-} while (0)
-
-#endif  /* __REALTEK_RTSX_CHIP_H */
diff --git a/drivers/staging/rts_pstor/rtsx_scsi.c b/drivers/staging/rts_pstor/rtsx_scsi.c
deleted file mode 100644
index 86c41b3..0000000
--- a/drivers/staging/rts_pstor/rtsx_scsi.c
+++ /dev/null
@@ -1,3137 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/vmalloc.h>
-
-#include "rtsx.h"
-#include "rtsx_transport.h"
-#include "rtsx_sys.h"
-#include "rtsx_card.h"
-#include "rtsx_chip.h"
-#include "rtsx_scsi.h"
-#include "sd.h"
-#include "ms.h"
-#include "spi.h"
-
-void scsi_show_command(struct scsi_cmnd *srb)
-{
-	char *what = NULL;
-	int i, unknown_cmd = 0;
-
-	switch (srb->cmnd[0]) {
-	case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break;
-	case REZERO_UNIT: what = "REZERO_UNIT"; break;
-	case REQUEST_SENSE: what = "REQUEST_SENSE"; break;
-	case FORMAT_UNIT: what = "FORMAT_UNIT"; break;
-	case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break;
-	case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break;
-	case READ_6: what = "READ_6"; break;
-	case WRITE_6: what = "WRITE_6"; break;
-	case SEEK_6: what = "SEEK_6"; break;
-	case READ_REVERSE: what = "READ_REVERSE"; break;
-	case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break;
-	case SPACE: what = "SPACE"; break;
-	case INQUIRY: what = "INQUIRY"; break;
-	case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break;
-	case MODE_SELECT: what = "MODE_SELECT"; break;
-	case RESERVE: what = "RESERVE"; break;
-	case RELEASE: what = "RELEASE"; break;
-	case COPY: what = "COPY"; break;
-	case ERASE: what = "ERASE"; break;
-	case MODE_SENSE: what = "MODE_SENSE"; break;
-	case START_STOP: what = "START_STOP"; break;
-	case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break;
-	case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break;
-	case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break;
-	case SET_WINDOW: what = "SET_WINDOW"; break;
-	case READ_CAPACITY: what = "READ_CAPACITY"; break;
-	case READ_10: what = "READ_10"; break;
-	case WRITE_10: what = "WRITE_10"; break;
-	case SEEK_10: what = "SEEK_10"; break;
-	case WRITE_VERIFY: what = "WRITE_VERIFY"; break;
-	case VERIFY: what = "VERIFY"; break;
-	case SEARCH_HIGH: what = "SEARCH_HIGH"; break;
-	case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break;
-	case SEARCH_LOW: what = "SEARCH_LOW"; break;
-	case SET_LIMITS: what = "SET_LIMITS"; break;
-	case READ_POSITION: what = "READ_POSITION"; break;
-	case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break;
-	case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break;
-	case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break;
-	case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break;
-	case COMPARE: what = "COMPARE"; break;
-	case COPY_VERIFY: what = "COPY_VERIFY"; break;
-	case WRITE_BUFFER: what = "WRITE_BUFFER"; break;
-	case READ_BUFFER: what = "READ_BUFFER"; break;
-	case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break;
-	case READ_LONG: what = "READ_LONG"; break;
-	case WRITE_LONG: what = "WRITE_LONG"; break;
-	case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break;
-	case WRITE_SAME: what = "WRITE_SAME"; break;
-	case GPCMD_READ_SUBCHANNEL: what = "READ SUBCHANNEL"; break;
-	case READ_TOC: what = "READ_TOC"; break;
-	case GPCMD_READ_HEADER: what = "READ HEADER"; break;
-	case GPCMD_PLAY_AUDIO_10: what = "PLAY AUDIO (10)"; break;
-	case GPCMD_PLAY_AUDIO_MSF: what = "PLAY AUDIO MSF"; break;
-	case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
-		what = "GET EVENT/STATUS NOTIFICATION"; break;
-	case GPCMD_PAUSE_RESUME: what = "PAUSE/RESUME"; break;
-	case LOG_SELECT: what = "LOG_SELECT"; break;
-	case LOG_SENSE: what = "LOG_SENSE"; break;
-	case GPCMD_STOP_PLAY_SCAN: what = "STOP PLAY/SCAN"; break;
-	case GPCMD_READ_DISC_INFO: what = "READ DISC INFORMATION"; break;
-	case GPCMD_READ_TRACK_RZONE_INFO:
-		what = "READ TRACK INFORMATION"; break;
-	case GPCMD_RESERVE_RZONE_TRACK: what = "RESERVE TRACK"; break;
-	case GPCMD_SEND_OPC: what = "SEND OPC"; break;
-	case MODE_SELECT_10: what = "MODE_SELECT_10"; break;
-	case GPCMD_REPAIR_RZONE_TRACK: what = "REPAIR TRACK"; break;
-	case 0x59: what = "READ MASTER CUE"; break;
-	case MODE_SENSE_10: what = "MODE_SENSE_10"; break;
-	case GPCMD_CLOSE_TRACK: what = "CLOSE TRACK/SESSION"; break;
-	case 0x5C: what = "READ BUFFER CAPACITY"; break;
-	case 0x5D: what = "SEND CUE SHEET"; break;
-	case GPCMD_BLANK: what = "BLANK"; break;
-	case REPORT_LUNS: what = "REPORT LUNS"; break;
-	case MOVE_MEDIUM: what = "MOVE_MEDIUM or PLAY AUDIO (12)"; break;
-	case READ_12: what = "READ_12"; break;
-	case WRITE_12: what = "WRITE_12"; break;
-	case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break;
-	case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break;
-	case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break;
-	case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break;
-	case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break;
-	case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break;
-	case GPCMD_READ_CD_MSF: what = "READ CD MSF"; break;
-	case GPCMD_SCAN: what = "SCAN"; break;
-	case GPCMD_SET_SPEED: what = "SET CD SPEED"; break;
-	case GPCMD_MECHANISM_STATUS: what = "MECHANISM STATUS"; break;
-	case GPCMD_READ_CD: what = "READ CD"; break;
-	case 0xE1: what = "WRITE CONTINUE"; break;
-	case WRITE_LONG_2: what = "WRITE_LONG_2"; break;
-	case VENDOR_CMND: what = "Realtek's vendor command"; break;
-	default: what = "(unknown command)"; unknown_cmd = 1; break;
-	}
-
-	if (srb->cmnd[0] != TEST_UNIT_READY)
-		RTSX_DEBUGP("Command %s (%d bytes)\n", what, srb->cmd_len);
-
-	if (unknown_cmd) {
-		RTSX_DEBUGP("");
-		for (i = 0; i < srb->cmd_len && i < 16; i++)
-			RTSX_DEBUGPN(" %02x", srb->cmnd[i]);
-		RTSX_DEBUGPN("\n");
-	}
-}
-
-void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type)
-{
-	switch (sense_type) {
-	case SENSE_TYPE_MEDIA_CHANGE:
-		set_sense_data(chip, lun, CUR_ERR, 0x06, 0, 0x28, 0, 0, 0);
-		break;
-
-	case SENSE_TYPE_MEDIA_NOT_PRESENT:
-		set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x3A, 0, 0, 0);
-		break;
-
-	case SENSE_TYPE_MEDIA_LBA_OVER_RANGE:
-		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x21, 0, 0, 0);
-		break;
-
-	case SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT:
-		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x25, 0, 0, 0);
-		break;
-
-	case SENSE_TYPE_MEDIA_WRITE_PROTECT:
-		set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x27, 0, 0, 0);
-		break;
-
-	case SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR:
-		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x11, 0, 0, 0);
-		break;
-
-	case SENSE_TYPE_MEDIA_WRITE_ERR:
-		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x02, 0, 0);
-		break;
-
-	case SENSE_TYPE_MEDIA_INVALID_CMD_FIELD:
-		set_sense_data(chip, lun, CUR_ERR, ILGAL_REQ, 0,
-				ASC_INVLD_CDB, ASCQ_INVLD_CDB, CDB_ILLEGAL, 1);
-		break;
-
-	case SENSE_TYPE_FORMAT_IN_PROGRESS:
-		set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, 0, 0);
-		break;
-
-	case SENSE_TYPE_FORMAT_CMD_FAILED:
-		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x31, 0x01, 0, 0);
-		break;
-
-#ifdef SUPPORT_MAGIC_GATE
-	case SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB:
-		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x02, 0, 0);
-		break;
-
-	case SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN:
-		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x00, 0, 0);
-		break;
-
-	case SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM:
-		set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x30, 0x00, 0, 0);
-		break;
-
-	case SENSE_TYPE_MG_WRITE_ERR:
-		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x00, 0, 0);
-		break;
-#endif
-
-#ifdef SUPPORT_SD_LOCK
-	case SENSE_TYPE_MEDIA_READ_FORBIDDEN:
-		set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x11, 0x13, 0, 0);
-		break;
-#endif
-
-	case SENSE_TYPE_NO_SENSE:
-	default:
-		set_sense_data(chip, lun, CUR_ERR, 0, 0, 0, 0, 0, 0);
-		break;
-	}
-}
-
-void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code, u8 sense_key,
-		u32 info, u8 asc, u8 ascq, u8 sns_key_info0, u16 sns_key_info1)
-{
-	struct sense_data_t *sense = &(chip->sense_buffer[lun]);
-
-	sense->err_code = err_code;
-	sense->sense_key = sense_key;
-	sense->info[0] = (u8)(info >> 24);
-	sense->info[1] = (u8)(info >> 16);
-	sense->info[2] = (u8)(info >> 8);
-	sense->info[3] = (u8)info;
-
-	sense->ad_sense_len = sizeof(struct sense_data_t) - 8;
-	sense->asc = asc;
-	sense->ascq = ascq;
-	if (sns_key_info0 != 0) {
-		sense->sns_key_info[0] = SKSV | sns_key_info0;
-		sense->sns_key_info[1] = (sns_key_info1 & 0xf0) >> 8;
-		sense->sns_key_info[2] = sns_key_info1 & 0x0f;
-	}
-}
-
-static int test_unit_ready(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned int lun = SCSI_LUN(srb);
-
-	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-		return TRANSPORT_FAILED;
-	}
-
-	if (!(CHK_BIT(chip->lun_mc, lun))) {
-		SET_BIT(chip->lun_mc, lun);
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
-		return TRANSPORT_FAILED;
-	}
-
-#ifdef SUPPORT_SD_LOCK
-	if (get_lun_card(chip, SCSI_LUN(srb)) == SD_CARD) {
-		struct sd_info *sd_card = &(chip->sd_card);
-		if (sd_card->sd_lock_notify) {
-			sd_card->sd_lock_notify = 0;
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
-			return TRANSPORT_FAILED;
-		} else if (sd_card->sd_lock_status & SD_LOCKED) {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN);
-			return TRANSPORT_FAILED;
-		}
-	}
-#endif
-
-	return TRANSPORT_GOOD;
-}
-
-static unsigned char formatter_inquiry_str[20] = {
-	'M', 'E', 'M', 'O', 'R', 'Y', 'S', 'T', 'I', 'C', 'K',
-#ifdef SUPPORT_MAGIC_GATE
-	'-', 'M', 'G', /* Byte[47:49] */
-#else
-	0x20, 0x20, 0x20,  /* Byte[47:49] */
-#endif
-
-#ifdef SUPPORT_MAGIC_GATE
-	0x0B,  /* Byte[50]: MG, MS, MSPro, MSXC */
-#else
-	0x09,  /* Byte[50]: MS, MSPro, MSXC */
-#endif
-	0x00,  /* Byte[51]: Category Specific Commands */
-	0x00,  /* Byte[52]: Access Control and feature */
-	0x20, 0x20, 0x20, /* Byte[53:55] */
-};
-
-static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned int lun = SCSI_LUN(srb);
-	char *inquiry_default = (char *)"Generic-xD/SD/M.S.      1.00 ";
-	char *inquiry_sdms =    (char *)"Generic-SD/MemoryStick  1.00 ";
-	char *inquiry_sd =      (char *)"Generic-SD/MMC          1.00 ";
-	char *inquiry_ms =      (char *)"Generic-MemoryStick     1.00 ";
-	char *inquiry_string;
-	unsigned char sendbytes;
-	unsigned char *buf;
-	u8 card = get_lun_card(chip, lun);
-	int pro_formatter_flag = 0;
-	unsigned char inquiry_buf[] = {
-		QULIFIRE|DRCT_ACCESS_DEV,
-		RMB_DISC|0x0D,
-		0x00,
-		0x01,
-		0x1f,
-		0x02,
-		0,
-		REL_ADR|WBUS_32|WBUS_16|SYNC|LINKED|CMD_QUE|SFT_RE,
-	};
-
-	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
-		if (chip->lun2card[lun] == SD_CARD)
-			inquiry_string = inquiry_sd;
-		else
-			inquiry_string = inquiry_ms;
-
-	} else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) {
-		inquiry_string = inquiry_sdms;
-	} else {
-		inquiry_string = inquiry_default;
-	}
-
-	buf = vmalloc(scsi_bufflen(srb));
-	if (buf == NULL)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-
-#ifdef SUPPORT_MAGIC_GATE
-	if ((chip->mspro_formatter_enable) &&
-			(chip->lun2card[lun] & MS_CARD))
-#else
-	if (chip->mspro_formatter_enable)
-#endif
-	{
-		if (!card || (card == MS_CARD))
-			pro_formatter_flag = 1;
-	}
-
-	if (pro_formatter_flag) {
-		if (scsi_bufflen(srb) < 56)
-			sendbytes = (unsigned char)(scsi_bufflen(srb));
-		else
-			sendbytes = 56;
-
-	} else {
-		if (scsi_bufflen(srb) < 36)
-			sendbytes = (unsigned char)(scsi_bufflen(srb));
-		else
-			sendbytes = 36;
-	}
-
-	if (sendbytes > 8) {
-		memcpy(buf, inquiry_buf, 8);
-		memcpy(buf + 8, inquiry_string,	sendbytes - 8);
-		if (pro_formatter_flag) {
-			/* Additional Length */
-			buf[4] = 0x33;
-		}
-	} else {
-		memcpy(buf, inquiry_buf, sendbytes);
-	}
-
-	if (pro_formatter_flag) {
-		if (sendbytes > 36)
-			memcpy(buf + 36, formatter_inquiry_str, sendbytes - 36);
-	}
-
-	scsi_set_resid(srb, 0);
-
-	rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
-	vfree(buf);
-
-	return TRANSPORT_GOOD;
-}
-
-
-static int start_stop_unit(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned int lun = SCSI_LUN(srb);
-
-	scsi_set_resid(srb, scsi_bufflen(srb));
-
-	if (srb->cmnd[1] == 1)
-		return TRANSPORT_GOOD;
-
-	switch (srb->cmnd[0x4]) {
-	case STOP_MEDIUM:
-		/* Media disabled */
-		return TRANSPORT_GOOD;
-
-	case UNLOAD_MEDIUM:
-		/* Media shall be unload */
-		if (check_card_ready(chip, lun))
-			eject_card(chip, lun);
-		return TRANSPORT_GOOD;
-
-	case MAKE_MEDIUM_READY:
-	case LOAD_MEDIUM:
-		if (check_card_ready(chip, lun)) {
-			return TRANSPORT_GOOD;
-		} else {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-
-		break;
-	}
-
-	TRACE_RET(chip, TRANSPORT_ERROR);
-}
-
-
-static int allow_medium_removal(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int prevent;
-
-	prevent = srb->cmnd[4] & 0x1;
-
-	scsi_set_resid(srb, 0);
-
-	if (prevent) {
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	return TRANSPORT_GOOD;
-}
-
-
-static int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct sense_data_t *sense;
-	unsigned int lun = SCSI_LUN(srb);
-	struct ms_info *ms_card = &(chip->ms_card);
-	unsigned char *tmp, *buf;
-
-	sense = &(chip->sense_buffer[lun]);
-
-	if ((get_lun_card(chip, lun) == MS_CARD) && ms_card->pro_under_formatting) {
-		if (ms_card->format_status == FORMAT_SUCCESS) {
-			set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
-			ms_card->pro_under_formatting = 0;
-			ms_card->progress = 0;
-		} else if (ms_card->format_status == FORMAT_IN_PROGRESS) {
-			/* Logical Unit Not Ready Format in Progress */
-			set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
-					0, (u16)(ms_card->progress));
-		} else {
-			/* Format Command Failed */
-			set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
-			ms_card->pro_under_formatting = 0;
-			ms_card->progress = 0;
-		}
-
-		rtsx_set_stat(chip, RTSX_STAT_RUN);
-	}
-
-	buf = vmalloc(scsi_bufflen(srb));
-	if (buf == NULL)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-
-	tmp = (unsigned char *)sense;
-	memcpy(buf, tmp, scsi_bufflen(srb));
-
-	rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
-	vfree(buf);
-
-	scsi_set_resid(srb, 0);
-	/* Reset Sense Data */
-	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
-	return TRANSPORT_GOOD;
-}
-
-static void ms_mode_sense(struct rtsx_chip *chip, u8 cmd,
-		int lun, u8 *buf, int buf_len)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	int sys_info_offset;
-	int data_size = buf_len;
-	int support_format = 0;
-	int i = 0;
-
-	if (cmd == MODE_SENSE) {
-		sys_info_offset = 8;
-		if (data_size > 0x68)
-			data_size = 0x68;
-
-		buf[i++] = 0x67;  /* Mode Data Length */
-	} else {
-		sys_info_offset = 12;
-		if (data_size > 0x6C)
-			data_size = 0x6C;
-
-		buf[i++] = 0x00;  /* Mode Data Length (MSB) */
-		buf[i++] = 0x6A;  /* Mode Data Length (LSB) */
-	}
-
-	/* Medium Type Code */
-	if (check_card_ready(chip, lun)) {
-		if (CHK_MSXC(ms_card)) {
-			support_format = 1;
-			buf[i++] = 0x40;
-		} else if (CHK_MSPRO(ms_card)) {
-			support_format = 1;
-			buf[i++] = 0x20;
-		} else {
-			buf[i++] = 0x10;
-		}
-
-		/* WP */
-		if (check_card_wp(chip, lun))
-			buf[i++] = 0x80;
-		else
-			buf[i++] = 0x00;
-
-	} else {
-		buf[i++] = 0x00;	/* MediaType */
-		buf[i++] = 0x00;	/* WP */
-	}
-
-	buf[i++] = 0x00;		/* Reserved */
-
-	if (cmd == MODE_SENSE_10) {
-		buf[i++] = 0x00;  /* Reserved */
-		buf[i++] = 0x00;  /* Block descriptor length(MSB) */
-		buf[i++] = 0x00;  /* Block descriptor length(LSB) */
-
-		/* The Following Data is the content of "Page 0x20" */
-		if (data_size >= 9)
-			buf[i++] = 0x20;		/* Page Code */
-		if (data_size >= 10)
-			buf[i++] = 0x62;		/* Page Length */
-		if (data_size >= 11)
-			buf[i++] = 0x00;		/* No Access Control */
-		if (data_size >= 12) {
-			if (support_format)
-				buf[i++] = 0xC0;	/* SF, SGM */
-			else
-				buf[i++] = 0x00;
-		}
-	} else {
-		/* The Following Data is the content of "Page 0x20" */
-		if (data_size >= 5)
-			buf[i++] = 0x20;		/* Page Code */
-		if (data_size >= 6)
-			buf[i++] = 0x62;		/* Page Length */
-		if (data_size >= 7)
-			buf[i++] = 0x00;		/* No Access Control */
-		if (data_size >= 8) {
-			if (support_format)
-				buf[i++] = 0xC0;	/* SF, SGM */
-			else
-				buf[i++] = 0x00;
-		}
-	}
-
-	if (data_size > sys_info_offset) {
-		/* 96 Bytes Attribute Data */
-		int len = data_size - sys_info_offset;
-		len = (len < 96) ? len : 96;
-
-		memcpy(buf + sys_info_offset, ms_card->raw_sys_info, len);
-	}
-}
-
-static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned int lun = SCSI_LUN(srb);
-	unsigned int dataSize;
-	int status;
-	int pro_formatter_flag;
-	unsigned char pageCode, *buf;
-	u8 card = get_lun_card(chip, lun);
-
-#ifndef SUPPORT_MAGIC_GATE
-	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-		scsi_set_resid(srb, scsi_bufflen(srb));
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-#endif
-
-	pro_formatter_flag = 0;
-	dataSize = 8;
-#ifdef SUPPORT_MAGIC_GATE
-	if ((chip->lun2card[lun] & MS_CARD)) {
-		if (!card || (card == MS_CARD)) {
-			dataSize = 108;
-			if (chip->mspro_formatter_enable)
-				pro_formatter_flag = 1;
-		}
-	}
-#else
-	if (card == MS_CARD) {
-		if (chip->mspro_formatter_enable) {
-			pro_formatter_flag = 1;
-			dataSize = 108;
-		}
-	}
-#endif
-
-	buf = kmalloc(dataSize, GFP_KERNEL);
-	if (buf == NULL)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-
-	pageCode = srb->cmnd[2] & 0x3f;
-
-	if ((pageCode == 0x3F) || (pageCode == 0x1C) ||
-		(pageCode == 0x00) ||
-		(pro_formatter_flag && (pageCode == 0x20))) {
-		if (srb->cmnd[0] == MODE_SENSE) {
-			if ((pageCode == 0x3F) || (pageCode == 0x20)) {
-				ms_mode_sense(chip, srb->cmnd[0],
-					      lun, buf, dataSize);
-			} else {
-				dataSize = 4;
-				buf[0] = 0x03;
-				buf[1] = 0x00;
-				if (check_card_wp(chip, lun))
-					buf[2] = 0x80;
-				else
-					buf[2] = 0x00;
-
-				buf[3] = 0x00;
-			}
-		} else {
-			if ((pageCode == 0x3F) || (pageCode == 0x20)) {
-				ms_mode_sense(chip, srb->cmnd[0],
-					      lun, buf, dataSize);
-			} else {
-				dataSize = 8;
-				buf[0] = 0x00;
-				buf[1] = 0x06;
-				buf[2] = 0x00;
-				if (check_card_wp(chip, lun))
-					buf[3] = 0x80;
-				else
-					buf[3] = 0x00;
-				buf[4] = 0x00;
-				buf[5] = 0x00;
-				buf[6] = 0x00;
-				buf[7] = 0x00;
-			}
-		}
-		status = TRANSPORT_GOOD;
-	} else {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		scsi_set_resid(srb, scsi_bufflen(srb));
-		status = TRANSPORT_FAILED;
-	}
-
-	if (status == TRANSPORT_GOOD) {
-		unsigned int len = min(scsi_bufflen(srb), dataSize);
-		rtsx_stor_set_xfer_buf(buf, len, srb);
-		scsi_set_resid(srb, scsi_bufflen(srb) - len);
-	}
-	kfree(buf);
-
-	return status;
-}
-
-static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-#ifdef SUPPORT_SD_LOCK
-	struct sd_info *sd_card = &(chip->sd_card);
-#endif
-	unsigned int lun = SCSI_LUN(srb);
-	int retval;
-	u32 start_sec;
-	u16 sec_cnt;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	if (!check_card_ready(chip, lun) || (get_card_size(chip, lun) == 0)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (!(CHK_BIT(chip->lun_mc, lun))) {
-		SET_BIT(chip->lun_mc, lun);
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
-		return TRANSPORT_FAILED;
-	}
-
-#ifdef SUPPORT_SD_LOCK
-	if (sd_card->sd_erase_status) {
-		/* Accessing to any card is forbidden
-		 * until the erase procedure of SD is completed
-		 */
-		RTSX_DEBUGP("SD card being erased!\n");
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (get_lun_card(chip, lun) == SD_CARD) {
-		if (sd_card->sd_lock_status & SD_LOCKED) {
-			RTSX_DEBUGP("SD card locked!\n");
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	}
-#endif
-
-	if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10)) {
-		start_sec = ((u32)srb->cmnd[2] << 24) | ((u32)srb->cmnd[3] << 16) |
-			((u32)srb->cmnd[4] << 8) | ((u32)srb->cmnd[5]);
-		sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
-	} else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) {
-		start_sec = ((u32)(srb->cmnd[1] & 0x1F) << 16) |
-			((u32)srb->cmnd[2] << 8) | ((u32)srb->cmnd[3]);
-		sec_cnt = srb->cmnd[4];
-	} else if ((srb->cmnd[0] == VENDOR_CMND) && (srb->cmnd[1] == SCSI_APP_CMD) &&
-			((srb->cmnd[2] == PP_READ10) || (srb->cmnd[2] == PP_WRITE10))) {
-		start_sec = ((u32)srb->cmnd[4] << 24) | ((u32)srb->cmnd[5] << 16) |
-			((u32)srb->cmnd[6] << 8) | ((u32)srb->cmnd[7]);
-		sec_cnt = ((u16)(srb->cmnd[9]) << 8) | srb->cmnd[10];
-	} else {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	/* In some test, we will receive a start_sec like 0xFFFFFFFF.
-	 * In this situation, start_sec + sec_cnt will overflow, so we
-	 * need to judge start_sec at first
-	 */
-	if ((start_sec > get_card_size(chip, lun)) ||
-			((start_sec + sec_cnt) > get_card_size(chip, lun))) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LBA_OVER_RANGE);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (sec_cnt == 0) {
-		scsi_set_resid(srb, 0);
-		return TRANSPORT_GOOD;
-	}
-
-	if (chip->rw_fail_cnt[lun] == 3) {
-		RTSX_DEBUGP("read/write fail three times in succession\n");
-		if (srb->sc_data_direction == DMA_FROM_DEVICE)
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-		else
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (srb->sc_data_direction == DMA_TO_DEVICE) {
-		if (check_card_wp(chip, lun)) {
-			RTSX_DEBUGP("Write protected card!\n");
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-		if (CHECK_PID(chip, 0x5209) && chip->max_payload) {
-			u8 val = 0x10 | (chip->max_payload << 5);
-			retval = rtsx_write_cfg_dw(chip, 0, 0x78, 0xFF, val);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, TRANSPORT_ERROR);
-		}
-	}
-
-	retval = card_rw(srb, chip, start_sec, sec_cnt);
-	if (retval != STATUS_SUCCESS) {
-		if (chip->need_release & chip->lun2card[lun]) {
-			chip->rw_fail_cnt[lun] = 0;
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-		} else {
-			chip->rw_fail_cnt[lun]++;
-			if (srb->sc_data_direction == DMA_FROM_DEVICE)
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-			else
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-		}
-		retval = TRANSPORT_FAILED;
-		TRACE_GOTO(chip, Exit);
-	} else {
-		chip->rw_fail_cnt[lun] = 0;
-		retval = TRANSPORT_GOOD;
-	}
-
-	scsi_set_resid(srb, 0);
-
-Exit:
-	if (srb->sc_data_direction == DMA_TO_DEVICE) {
-		if (CHECK_PID(chip, 0x5209) && chip->max_payload) {
-			retval = rtsx_write_cfg_dw(chip, 0, 0x78, 0xFF, 0x10);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, TRANSPORT_ERROR);
-		}
-	}
-
-	return retval;
-}
-
-static int read_format_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned char *buf;
-	unsigned int lun = SCSI_LUN(srb);
-	unsigned int buf_len;
-	u8 card = get_lun_card(chip, lun);
-	u32 card_size;
-	int desc_cnt;
-	int i = 0;
-
-	if (!check_card_ready(chip, lun)) {
-		if (!chip->mspro_formatter_enable) {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	}
-
-	buf_len = (scsi_bufflen(srb) > 12) ? 0x14 : 12;
-
-	buf = kmalloc(buf_len, GFP_KERNEL);
-	if (buf == NULL)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-
-	buf[i++] = 0;
-	buf[i++] = 0;
-	buf[i++] = 0;
-
-	/* Capacity List Length */
-	if ((buf_len > 12) && chip->mspro_formatter_enable &&
-			(chip->lun2card[lun] & MS_CARD) &&
-			(!card || (card == MS_CARD))) {
-		buf[i++] = 0x10;
-		desc_cnt = 2;
-	} else {
-		buf[i++] = 0x08;
-		desc_cnt = 1;
-	}
-
-	while (desc_cnt) {
-		if (check_card_ready(chip, lun)) {
-			card_size = get_card_size(chip, lun);
-			buf[i++] = (unsigned char)(card_size >> 24);
-			buf[i++] = (unsigned char)(card_size >> 16);
-			buf[i++] = (unsigned char)(card_size >> 8);
-			buf[i++] = (unsigned char)card_size;
-
-			if (desc_cnt == 2)
-				buf[i++] = 2;
-			else
-				buf[i++] = 0;
-		} else {
-			buf[i++] = 0xFF;
-			buf[i++] = 0xFF;
-			buf[i++] = 0xFF;
-			buf[i++] = 0xFF;
-
-			if (desc_cnt == 2)
-				buf[i++] = 3;
-			else
-				buf[i++] = 0;
-		}
-
-		buf[i++] = 0x00;
-		buf[i++] = 0x02;
-		buf[i++] = 0x00;
-
-		desc_cnt--;
-	}
-
-	buf_len = min(scsi_bufflen(srb), buf_len);
-	rtsx_stor_set_xfer_buf(buf, buf_len, srb);
-	kfree(buf);
-
-	scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
-
-	return TRANSPORT_GOOD;
-}
-
-static int read_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned char *buf;
-	unsigned int lun = SCSI_LUN(srb);
-	u32 card_size;
-
-	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (!(CHK_BIT(chip->lun_mc, lun))) {
-		SET_BIT(chip->lun_mc, lun);
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
-		return TRANSPORT_FAILED;
-	}
-
-	buf = kmalloc(8, GFP_KERNEL);
-	if (buf == NULL)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-
-	card_size = get_card_size(chip, lun);
-	buf[0] = (unsigned char)((card_size - 1) >> 24);
-	buf[1] = (unsigned char)((card_size - 1) >> 16);
-	buf[2] = (unsigned char)((card_size - 1) >> 8);
-	buf[3] = (unsigned char)(card_size - 1);
-
-	buf[4] = 0x00;
-	buf[5] = 0x00;
-	buf[6] = 0x02;
-	buf[7] = 0x00;
-
-	rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
-	kfree(buf);
-
-	scsi_set_resid(srb, 0);
-
-	return TRANSPORT_GOOD;
-}
-
-static int read_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned short len, i;
-	int retval;
-	u8 *buf;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-
-	buf = (u8 *)vmalloc(len);
-	if (!buf)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-
-	retval = rtsx_force_power_on(chip, SSC_PDCTL);
-	if (retval != STATUS_SUCCESS) {
-		vfree(buf);
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	for (i = 0; i < len; i++) {
-		retval = spi_read_eeprom(chip, i, buf + i);
-		if (retval != STATUS_SUCCESS) {
-			vfree(buf);
-			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	}
-
-	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
-	rtsx_stor_set_xfer_buf(buf, len, srb);
-	scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
-	vfree(buf);
-
-	return TRANSPORT_GOOD;
-}
-
-static int write_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned short len, i;
-	int retval;
-	u8 *buf;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-
-	retval = rtsx_force_power_on(chip, SSC_PDCTL);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (len == 511) {
-		retval = spi_erase_eeprom_chip(chip);
-		if (retval != STATUS_SUCCESS) {
-			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	} else {
-		len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
-		buf = (u8 *)vmalloc(len);
-		if (buf == NULL)
-			TRACE_RET(chip, TRANSPORT_ERROR);
-
-		rtsx_stor_get_xfer_buf(buf, len, srb);
-		scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
-		for (i = 0; i < len; i++) {
-			retval = spi_write_eeprom(chip, i, buf[i]);
-			if (retval != STATUS_SUCCESS) {
-				vfree(buf);
-				set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-				TRACE_RET(chip, TRANSPORT_FAILED);
-			}
-		}
-
-		vfree(buf);
-	}
-
-	return TRANSPORT_GOOD;
-}
-
-static int read_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned short addr, len, i;
-	int retval;
-	u8 *buf;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	addr = ((u16)srb->cmnd[2] << 8) | srb->cmnd[3];
-	len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-
-	if (addr < 0xFC00) {
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	buf = (u8 *)vmalloc(len);
-	if (!buf)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-
-	retval = rtsx_force_power_on(chip, SSC_PDCTL);
-	if (retval != STATUS_SUCCESS) {
-		vfree(buf);
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	for (i = 0; i < len; i++) {
-		retval = rtsx_read_register(chip, addr + i, buf + i);
-		if (retval != STATUS_SUCCESS) {
-			vfree(buf);
-			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	}
-
-	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
-	rtsx_stor_set_xfer_buf(buf, len, srb);
-	scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
-	vfree(buf);
-
-	return TRANSPORT_GOOD;
-}
-
-static int write_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned short addr, len, i;
-	int retval;
-	u8 *buf;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	addr = ((u16)srb->cmnd[2] << 8) | srb->cmnd[3];
-	len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-
-	if (addr < 0xFC00) {
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
-	buf = (u8 *)vmalloc(len);
-	if (buf == NULL)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-
-	rtsx_stor_get_xfer_buf(buf, len, srb);
-	scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
-	retval = rtsx_force_power_on(chip, SSC_PDCTL);
-	if (retval != STATUS_SUCCESS) {
-		vfree(buf);
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	for (i = 0; i < len; i++) {
-		retval = rtsx_write_register(chip, addr + i, 0xFF, buf[i]);
-		if (retval != STATUS_SUCCESS) {
-			vfree(buf);
-			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	}
-
-	vfree(buf);
-
-	return TRANSPORT_GOOD;
-}
-
-static int get_sd_csd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	unsigned int lun = SCSI_LUN(srb);
-
-	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (get_lun_card(chip, lun) != SD_CARD) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	scsi_set_resid(srb, 0);
-	rtsx_stor_set_xfer_buf(sd_card->raw_csd, scsi_bufflen(srb), srb);
-
-	return TRANSPORT_GOOD;
-}
-
-static int toggle_gpio_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	u8 gpio = srb->cmnd[2];
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	if (gpio > 3)
-		gpio = 1;
-	toggle_gpio(chip, gpio);
-
-	return TRANSPORT_GOOD;
-}
-
-#ifdef _MSG_TRACE
-static int trace_msg_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned char *ptr, *buf = NULL;
-	int i, msg_cnt;
-	u8 clear;
-	unsigned int buf_len;
-
-	buf_len = 4 + ((2 + MSG_FUNC_LEN + MSG_FILE_LEN + TIME_VAL_LEN) * TRACE_ITEM_CNT);
-
-	if ((scsi_bufflen(srb) < buf_len) || (scsi_sglist(srb) == NULL)) {
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	clear = srb->cmnd[2];
-
-	buf = (unsigned char *)vmalloc(scsi_bufflen(srb));
-	if (buf == NULL)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-	ptr = buf;
-
-	if (chip->trace_msg[chip->msg_idx].valid)
-		msg_cnt = TRACE_ITEM_CNT;
-	else
-		msg_cnt = chip->msg_idx;
-
-	*(ptr++) = (u8)(msg_cnt >> 24);
-	*(ptr++) = (u8)(msg_cnt >> 16);
-	*(ptr++) = (u8)(msg_cnt >> 8);
-	*(ptr++) = (u8)msg_cnt;
-	RTSX_DEBUGP("Trace message count is %d\n", msg_cnt);
-
-	for (i = 1; i <= msg_cnt; i++) {
-		int j, idx;
-
-		idx = chip->msg_idx - i;
-		if (idx < 0)
-			idx += TRACE_ITEM_CNT;
-
-		*(ptr++) = (u8)(chip->trace_msg[idx].line >> 8);
-		*(ptr++) = (u8)(chip->trace_msg[idx].line);
-		for (j = 0; j < MSG_FUNC_LEN; j++)
-			*(ptr++) = chip->trace_msg[idx].func[j];
-
-		for (j = 0; j < MSG_FILE_LEN; j++)
-			*(ptr++) = chip->trace_msg[idx].file[j];
-
-		for (j = 0; j < TIME_VAL_LEN; j++)
-			*(ptr++) = chip->trace_msg[idx].timeval_buf[j];
-	}
-
-	rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
-	vfree(buf);
-
-	if (clear) {
-		chip->msg_idx = 0;
-		for (i = 0; i < TRACE_ITEM_CNT; i++)
-			chip->trace_msg[i].valid = 0;
-	}
-
-	scsi_set_resid(srb, 0);
-	return TRANSPORT_GOOD;
-}
-#endif
-
-static int read_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	u8 addr, buf[4];
-	u32 val;
-	unsigned int len;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	addr = srb->cmnd[4];
-
-	val = rtsx_readl(chip, addr);
-	RTSX_DEBUGP("Host register (0x%x): 0x%x\n", addr, val);
-
-	buf[0] = (u8)(val >> 24);
-	buf[1] = (u8)(val >> 16);
-	buf[2] = (u8)(val >> 8);
-	buf[3] = (u8)val;
-
-	len = min(scsi_bufflen(srb), (unsigned int)4);
-	rtsx_stor_set_xfer_buf(buf, len, srb);
-	scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
-	return TRANSPORT_GOOD;
-}
-
-static int write_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	u8 addr, buf[4];
-	u32 val;
-	unsigned int len;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	addr = srb->cmnd[4];
-
-	len = min(scsi_bufflen(srb), (unsigned int)4);
-	rtsx_stor_get_xfer_buf(buf, len, srb);
-	scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
-	val = ((u32)buf[0] << 24) | ((u32)buf[1] << 16) | ((u32)buf[2] << 8) | buf[3];
-
-	rtsx_writel(chip, addr, val);
-
-	return TRANSPORT_GOOD;
-}
-
-static int set_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned lun = SCSI_LUN(srb);
-
-	if (srb->cmnd[3] == 1) {
-		/* Variable Clock */
-		struct xd_info *xd_card = &(chip->xd_card);
-		struct sd_info *sd_card = &(chip->sd_card);
-		struct ms_info *ms_card = &(chip->ms_card);
-
-		switch (srb->cmnd[4]) {
-		case XD_CARD:
-			xd_card->xd_clock = srb->cmnd[5];
-			break;
-
-		case SD_CARD:
-			sd_card->sd_clock = srb->cmnd[5];
-			break;
-
-		case MS_CARD:
-			ms_card->ms_clock = srb->cmnd[5];
-			break;
-
-		default:
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	} else if (srb->cmnd[3] == 2) {
-		if (srb->cmnd[4]) {
-			chip->blink_led = 1;
-		} else {
-			int retval;
-
-			chip->blink_led = 0;
-
-			rtsx_disable_aspm(chip);
-
-			if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-				rtsx_exit_ss(chip);
-				wait_timeout(100);
-			}
-			rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-			retval = rtsx_force_power_on(chip, SSC_PDCTL);
-			if (retval != STATUS_SUCCESS) {
-				set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-				TRACE_RET(chip, TRANSPORT_FAILED);
-			}
-
-			turn_off_led(chip, LED_GPIO);
-		}
-	} else {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	return TRANSPORT_GOOD;
-}
-
-static int get_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned int lun = SCSI_LUN(srb);
-
-	if (srb->cmnd[3] == 1) {
-		struct xd_info *xd_card = &(chip->xd_card);
-		struct sd_info *sd_card = &(chip->sd_card);
-		struct ms_info *ms_card = &(chip->ms_card);
-		u8 tmp;
-
-		switch (srb->cmnd[4]) {
-		case XD_CARD:
-			tmp = (u8)(xd_card->xd_clock);
-			break;
-
-		case SD_CARD:
-			tmp = (u8)(sd_card->sd_clock);
-			break;
-
-		case MS_CARD:
-			tmp = (u8)(ms_card->ms_clock);
-			break;
-
-		default:
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-
-		rtsx_stor_set_xfer_buf(&tmp, 1, srb);
-	} else if (srb->cmnd[3] == 2) {
-		u8 tmp = chip->blink_led;
-		rtsx_stor_set_xfer_buf(&tmp, 1, srb);
-	} else {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	return TRANSPORT_GOOD;
-}
-
-static int dma_access_ring_buffer(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int retval;
-	unsigned int lun = SCSI_LUN(srb);
-	u16 len;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	len = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
-	len = min(len, (u16)scsi_bufflen(srb));
-
-	if (srb->sc_data_direction == DMA_FROM_DEVICE)
-		RTSX_DEBUGP("Read from device\n");
-	else
-		RTSX_DEBUGP("Write to device\n");
-
-	retval = rtsx_transfer_data(chip, 0, scsi_sglist(srb), len,
-			scsi_sg_count(srb), srb->sc_data_direction, 1000);
-	if (retval < 0) {
-		if (srb->sc_data_direction == DMA_FROM_DEVICE)
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-		else
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-	scsi_set_resid(srb, 0);
-
-	return TRANSPORT_GOOD;
-}
-
-static int get_dev_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	struct ms_info *ms_card = &(chip->ms_card);
-	int buf_len;
-	unsigned int lun = SCSI_LUN(srb);
-	u8 card = get_lun_card(chip, lun);
-	u8 status[32];
-#ifdef SUPPORT_OCP
-	u8 oc_now_mask = 0, oc_ever_mask = 0;
-#endif
-
-	memset(status, 0, 32);
-
-	status[0] = (u8)(chip->product_id);
-	status[1] = chip->ic_version;
-
-	if (chip->auto_delink_en)
-		status[2] = 0x10;
-	else
-		status[2] = 0x00;
-
-	status[3] = 20;
-	status[4] = 10;
-	status[5] = 05;
-	status[6] = 21;
-
-	if (chip->card_wp)
-		status[7] = 0x20;
-	else
-		status[7] = 0x00;
-
-#ifdef SUPPORT_OCP
-	status[8] = 0;
-	if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && (chip->lun2card[lun] == MS_CARD)) {
-		oc_now_mask = MS_OC_NOW;
-		oc_ever_mask = MS_OC_EVER;
-	} else {
-		oc_now_mask = SD_OC_NOW;
-		oc_ever_mask = SD_OC_EVER;
-	}
-
-	if (chip->ocp_stat & oc_now_mask)
-		status[8] |= 0x02;
-
-	if (chip->ocp_stat & oc_ever_mask)
-		status[8] |= 0x01;
-#endif
-
-	if (card == SD_CARD) {
-		if (CHK_SD(sd_card)) {
-			if (CHK_SD_HCXC(sd_card)) {
-				if (sd_card->capacity > 0x4000000)
-					status[0x0E] = 0x02;
-				else
-					status[0x0E] = 0x01;
-			} else {
-				status[0x0E] = 0x00;
-			}
-
-			if (CHK_SD_SDR104(sd_card))
-				status[0x0F] = 0x03;
-			else if (CHK_SD_DDR50(sd_card))
-				status[0x0F] = 0x04;
-			else if (CHK_SD_SDR50(sd_card))
-				status[0x0F] = 0x02;
-			else if (CHK_SD_HS(sd_card))
-				status[0x0F] = 0x01;
-			else
-				status[0x0F] = 0x00;
-		} else {
-			if (CHK_MMC_SECTOR_MODE(sd_card))
-				status[0x0E] = 0x01;
-			else
-				status[0x0E] = 0x00;
-
-			if (CHK_MMC_DDR52(sd_card))
-				status[0x0F] = 0x03;
-			else if (CHK_MMC_52M(sd_card))
-				status[0x0F] = 0x02;
-			else if (CHK_MMC_26M(sd_card))
-				status[0x0F] = 0x01;
-			else
-				status[0x0F] = 0x00;
-		}
-	} else if (card == MS_CARD) {
-		if (CHK_MSPRO(ms_card)) {
-			if (CHK_MSXC(ms_card))
-				status[0x0E] = 0x01;
-			else
-				status[0x0E] = 0x00;
-
-			if (CHK_HG8BIT(ms_card))
-				status[0x0F] = 0x01;
-			else
-				status[0x0F] = 0x00;
-		}
-	}
-
-#ifdef SUPPORT_SD_LOCK
-	if (card == SD_CARD) {
-		status[0x17] = 0x80;
-		if (sd_card->sd_erase_status)
-			status[0x17] |= 0x01;
-		if (sd_card->sd_lock_status & SD_LOCKED) {
-			status[0x17] |= 0x02;
-			status[0x07] |= 0x40;
-		}
-		if (sd_card->sd_lock_status & SD_PWD_EXIST)
-			status[0x17] |= 0x04;
-	} else {
-		status[0x17] = 0x00;
-	}
-
-	RTSX_DEBUGP("status[0x17] = 0x%x\n", status[0x17]);
-#endif
-
-	status[0x18] = 0x8A;
-	status[0x1A] = 0x28;
-#ifdef SUPPORT_SD_LOCK
-	status[0x1F] = 0x01;
-#endif
-
-	buf_len = min(scsi_bufflen(srb), (unsigned int)sizeof(status));
-	rtsx_stor_set_xfer_buf(status, buf_len, srb);
-	scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
-
-	return TRANSPORT_GOOD;
-}
-
-static int set_chip_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int phy_debug_mode;
-	int retval;
-	u16 reg;
-
-	if (!CHECK_PID(chip, 0x5208)) {
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	phy_debug_mode = (int)(srb->cmnd[3]);
-
-	if (phy_debug_mode) {
-		chip->phy_debug_mode = 1;
-		retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, TRANSPORT_FAILED);
-
-		rtsx_disable_bus_int(chip);
-
-		retval = rtsx_read_phy_register(chip, 0x1C, &reg);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, TRANSPORT_FAILED);
-
-		reg |= 0x0001;
-		retval = rtsx_write_phy_register(chip, 0x1C, reg);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, TRANSPORT_FAILED);
-	} else {
-		chip->phy_debug_mode = 0;
-		retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0x77);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, TRANSPORT_FAILED);
-
-		rtsx_enable_bus_int(chip);
-
-		retval = rtsx_read_phy_register(chip, 0x1C, &reg);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, TRANSPORT_FAILED);
-
-		reg &= 0xFFFE;
-		retval = rtsx_write_phy_register(chip, 0x1C, reg);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	return TRANSPORT_GOOD;
-}
-
-static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int retval =  STATUS_SUCCESS;
-	unsigned int lun = SCSI_LUN(srb);
-	u8 cmd_type, mask, value, idx;
-	u16 addr;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	switch (srb->cmnd[3]) {
-	case INIT_BATCHCMD:
-		rtsx_init_cmd(chip);
-		break;
-
-	case ADD_BATCHCMD:
-		cmd_type = srb->cmnd[4];
-		if (cmd_type > 2) {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-		addr = (srb->cmnd[5] << 8) | srb->cmnd[6];
-		mask = srb->cmnd[7];
-		value = srb->cmnd[8];
-		rtsx_add_cmd(chip, cmd_type, addr, mask, value);
-		break;
-
-	case SEND_BATCHCMD:
-		retval = rtsx_send_cmd(chip, 0, 1000);
-		break;
-
-	case GET_BATCHRSP:
-		idx = srb->cmnd[4];
-		value = *(rtsx_get_cmd_data(chip) + idx);
-		if (scsi_bufflen(srb) < 1) {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-		rtsx_stor_set_xfer_buf(&value, 1, srb);
-		scsi_set_resid(srb, 0);
-		break;
-
-	default:
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	return TRANSPORT_GOOD;
-}
-
-static int suit_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int result;
-
-	switch (srb->cmnd[3]) {
-	case INIT_BATCHCMD:
-	case ADD_BATCHCMD:
-	case SEND_BATCHCMD:
-	case GET_BATCHRSP:
-		result = rw_mem_cmd_buf(srb, chip);
-		break;
-	default:
-		result = TRANSPORT_ERROR;
-	}
-
-	return result;
-}
-
-static int read_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned short addr, len, i;
-	int retval;
-	u8 *buf;
-	u16 val;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-	len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
-
-	if (len % 2)
-		len -= len % 2;
-
-	if (len) {
-		buf = (u8 *)vmalloc(len);
-		if (!buf)
-			TRACE_RET(chip, TRANSPORT_ERROR);
-
-		retval = rtsx_force_power_on(chip, SSC_PDCTL);
-		if (retval != STATUS_SUCCESS) {
-			vfree(buf);
-			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-
-		for (i = 0; i < len / 2; i++) {
-			retval = rtsx_read_phy_register(chip, addr + i, &val);
-			if (retval != STATUS_SUCCESS) {
-				vfree(buf);
-				set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-				TRACE_RET(chip, TRANSPORT_FAILED);
-			}
-
-			buf[2*i] = (u8)(val >> 8);
-			buf[2*i+1] = (u8)val;
-		}
-
-		len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
-		rtsx_stor_set_xfer_buf(buf, len, srb);
-		scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
-		vfree(buf);
-	}
-
-	return TRANSPORT_GOOD;
-}
-
-static int write_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned short addr, len, i;
-	int retval;
-	u8 *buf;
-	u16 val;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-	len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
-
-	if (len % 2)
-		len -= len % 2;
-
-	if (len) {
-		len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
-
-		buf = (u8 *)vmalloc(len);
-		if (buf == NULL)
-			TRACE_RET(chip, TRANSPORT_ERROR);
-
-		rtsx_stor_get_xfer_buf(buf, len, srb);
-		scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
-		retval = rtsx_force_power_on(chip, SSC_PDCTL);
-		if (retval != STATUS_SUCCESS) {
-			vfree(buf);
-			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-
-		for (i = 0; i < len / 2; i++) {
-			val = ((u16)buf[2*i] << 8) | buf[2*i+1];
-			retval = rtsx_write_phy_register(chip, addr + i, val);
-			if (retval != STATUS_SUCCESS) {
-				vfree(buf);
-				set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-				TRACE_RET(chip, TRANSPORT_FAILED);
-			}
-		}
-
-		vfree(buf);
-	}
-
-	return TRANSPORT_GOOD;
-}
-
-static int erase_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned short addr;
-	int retval;
-	u8 mode;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	retval = rtsx_force_power_on(chip, SSC_PDCTL);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	mode = srb->cmnd[3];
-	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-
-	if (mode == 0) {
-		retval = spi_erase_eeprom_chip(chip);
-		if (retval != STATUS_SUCCESS) {
-			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	} else if (mode == 1) {
-		retval = spi_erase_eeprom_byte(chip, addr);
-		if (retval != STATUS_SUCCESS) {
-			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	} else {
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	return TRANSPORT_GOOD;
-}
-
-static int read_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned short addr, len, i;
-	int retval;
-	u8 *buf;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-	len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
-
-	buf = (u8 *)vmalloc(len);
-	if (!buf)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-
-	retval = rtsx_force_power_on(chip, SSC_PDCTL);
-	if (retval != STATUS_SUCCESS) {
-		vfree(buf);
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	for (i = 0; i < len; i++) {
-		retval = spi_read_eeprom(chip, addr + i, buf + i);
-		if (retval != STATUS_SUCCESS) {
-			vfree(buf);
-			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	}
-
-	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
-	rtsx_stor_set_xfer_buf(buf, len, srb);
-	scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
-	vfree(buf);
-
-	return TRANSPORT_GOOD;
-}
-
-static int write_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned short addr, len, i;
-	int retval;
-	u8 *buf;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-	len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
-
-	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
-	buf = (u8 *)vmalloc(len);
-	if (buf == NULL)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-
-	rtsx_stor_get_xfer_buf(buf, len, srb);
-	scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
-	retval = rtsx_force_power_on(chip, SSC_PDCTL);
-	if (retval != STATUS_SUCCESS) {
-		vfree(buf);
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	for (i = 0; i < len; i++) {
-		retval = spi_write_eeprom(chip, addr + i, buf[i]);
-		if (retval != STATUS_SUCCESS) {
-			vfree(buf);
-			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	}
-
-	vfree(buf);
-
-	return TRANSPORT_GOOD;
-}
-
-static int read_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int retval;
-	u8 addr, len, i;
-	u8 *buf;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	addr = srb->cmnd[4];
-	len = srb->cmnd[5];
-
-	buf = (u8 *)vmalloc(len);
-	if (!buf)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-
-	retval = rtsx_force_power_on(chip, SSC_PDCTL);
-	if (retval != STATUS_SUCCESS) {
-		vfree(buf);
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	for (i = 0; i < len; i++) {
-		retval = rtsx_read_efuse(chip, addr + i, buf + i);
-		if (retval != STATUS_SUCCESS) {
-			vfree(buf);
-			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	}
-
-	len = (u8)min(scsi_bufflen(srb), (unsigned int)len);
-	rtsx_stor_set_xfer_buf(buf, len, srb);
-	scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
-	vfree(buf);
-
-	return TRANSPORT_GOOD;
-}
-
-static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int retval, result = TRANSPORT_GOOD;
-	u16 val;
-	u8 addr, len, i;
-	u8 *buf;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	addr = srb->cmnd[4];
-	len = srb->cmnd[5];
-
-	len = (u8)min(scsi_bufflen(srb), (unsigned int)len);
-	buf = (u8 *)vmalloc(len);
-	if (buf == NULL)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-
-	rtsx_stor_get_xfer_buf(buf, len, srb);
-	scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
-	retval = rtsx_force_power_on(chip, SSC_PDCTL);
-	if (retval != STATUS_SUCCESS) {
-		vfree(buf);
-		TRACE_RET(chip, TRANSPORT_ERROR);
-	}
-
-	if (chip->asic_code) {
-		retval = rtsx_read_phy_register(chip, 0x08, &val);
-		if (retval != STATUS_SUCCESS) {
-			vfree(buf);
-			TRACE_RET(chip, TRANSPORT_ERROR);
-		}
-
-		retval = rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_OFF);
-		if (retval != STATUS_SUCCESS) {
-			vfree(buf);
-			TRACE_RET(chip, TRANSPORT_ERROR);
-		}
-
-		wait_timeout(600);
-
-		retval = rtsx_write_phy_register(chip, 0x08, 0x4C00 | chip->phy_voltage);
-		if (retval != STATUS_SUCCESS) {
-			vfree(buf);
-			TRACE_RET(chip, TRANSPORT_ERROR);
-		}
-
-		retval = rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON);
-		if (retval != STATUS_SUCCESS) {
-			vfree(buf);
-			TRACE_RET(chip, TRANSPORT_ERROR);
-		}
-
-		wait_timeout(600);
-	}
-
-	retval = card_power_on(chip, SPI_CARD);
-	if (retval != STATUS_SUCCESS) {
-		vfree(buf);
-		TRACE_RET(chip, TRANSPORT_ERROR);
-	}
-
-	wait_timeout(50);
-
-	for (i = 0; i < len; i++) {
-		retval = rtsx_write_efuse(chip, addr + i, buf[i]);
-		if (retval != STATUS_SUCCESS) {
-			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-			result = TRANSPORT_FAILED;
-			TRACE_GOTO(chip, Exit);
-		}
-	}
-
-Exit:
-	vfree(buf);
-
-	retval = card_power_off(chip, SPI_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-
-	if (chip->asic_code) {
-		retval = rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_OFF);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, TRANSPORT_ERROR);
-
-		wait_timeout(600);
-
-		retval = rtsx_write_phy_register(chip, 0x08, val);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, TRANSPORT_ERROR);
-
-		retval = rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, TRANSPORT_ERROR);
-	}
-
-	return result;
-}
-
-static int read_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int retval;
-	u8 func, func_max;
-	u16 addr, len;
-	u8 *buf;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	func = srb->cmnd[3];
-	addr = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
-	len = ((u16)(srb->cmnd[6]) << 8) | srb->cmnd[7];
-
-	RTSX_DEBUGP("%s: func = %d, addr = 0x%x, len = %d\n", __func__, func, addr, len);
-
-	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip))
-		func_max = 1;
-	else
-		func_max = 0;
-
-	if (func > func_max) {
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	buf = (u8 *)vmalloc(len);
-	if (!buf)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-
-	retval = rtsx_read_cfg_seq(chip, func, addr, buf, len);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-		vfree(buf);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	len = (u16)min(scsi_bufflen(srb), (unsigned int)len);
-	rtsx_stor_set_xfer_buf(buf, len, srb);
-	scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
-	vfree(buf);
-
-	return TRANSPORT_GOOD;
-}
-
-static int write_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int retval;
-	u8 func, func_max;
-	u16 addr, len;
-	u8 *buf;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	func = srb->cmnd[3];
-	addr = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
-	len = ((u16)(srb->cmnd[6]) << 8) | srb->cmnd[7];
-
-	RTSX_DEBUGP("%s: func = %d, addr = 0x%x\n", __func__, func, addr);
-
-	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip))
-		func_max = 1;
-	else
-		func_max = 0;
-
-	if (func > func_max) {
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
-	buf = (u8 *)vmalloc(len);
-	if (!buf)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-
-	rtsx_stor_get_xfer_buf(buf, len, srb);
-	scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
-	retval = rtsx_write_cfg_seq(chip, func, addr, buf, len);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-		vfree(buf);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	vfree(buf);
-
-	return TRANSPORT_GOOD;
-}
-
-static int app_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int result;
-
-	switch (srb->cmnd[2]) {
-	case PP_READ10:
-	case PP_WRITE10:
-		result = read_write(srb, chip);
-		break;
-
-	case READ_HOST_REG:
-		result = read_host_reg(srb, chip);
-		break;
-
-	case WRITE_HOST_REG:
-		result = write_host_reg(srb, chip);
-		break;
-
-	case GET_VAR:
-		result = get_variable(srb, chip);
-		break;
-
-	case SET_VAR:
-		result = set_variable(srb, chip);
-		break;
-
-	case DMA_READ:
-	case DMA_WRITE:
-		result = dma_access_ring_buffer(srb, chip);
-		break;
-
-	case READ_PHY:
-		result = read_phy_register(srb, chip);
-		break;
-
-	case WRITE_PHY:
-		result = write_phy_register(srb, chip);
-		break;
-
-	case ERASE_EEPROM2:
-		result = erase_eeprom2(srb, chip);
-		break;
-
-	case READ_EEPROM2:
-		result = read_eeprom2(srb, chip);
-		break;
-
-	case WRITE_EEPROM2:
-		result = write_eeprom2(srb, chip);
-		break;
-
-	case READ_EFUSE:
-		result = read_efuse(srb, chip);
-		break;
-
-	case WRITE_EFUSE:
-		result = write_efuse(srb, chip);
-		break;
-
-	case READ_CFG:
-		result = read_cfg_byte(srb, chip);
-		break;
-
-	case WRITE_CFG:
-		result = write_cfg_byte(srb, chip);
-		break;
-
-	case SET_CHIP_MODE:
-		result = set_chip_mode(srb, chip);
-		break;
-
-	case SUIT_CMD:
-		result = suit_cmd(srb, chip);
-		break;
-
-	case GET_DEV_STATUS:
-		result = get_dev_status(srb, chip);
-		break;
-
-	default:
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	return result;
-}
-
-
-static int read_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	u8 rtsx_status[16];
-	int buf_len;
-	unsigned int lun = SCSI_LUN(srb);
-
-	rtsx_status[0] = (u8)(chip->vendor_id >> 8);
-	rtsx_status[1] = (u8)(chip->vendor_id);
-
-	rtsx_status[2] = (u8)(chip->product_id >> 8);
-	rtsx_status[3] = (u8)(chip->product_id);
-
-	rtsx_status[4] = (u8)lun;
-
-	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
-		if (chip->lun2card[lun] == SD_CARD)
-			rtsx_status[5] = 2;
-		else
-			rtsx_status[5] = 3;
-	} else {
-		if (chip->card_exist) {
-			if (chip->card_exist & XD_CARD)
-				rtsx_status[5] = 4;
-			else if (chip->card_exist & SD_CARD)
-				rtsx_status[5] = 2;
-			else if (chip->card_exist & MS_CARD)
-				rtsx_status[5] = 3;
-			else
-				rtsx_status[5] = 7;
-		} else {
-			rtsx_status[5] = 7;
-		}
-	}
-
-	if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
-		rtsx_status[6] = 2;
-	else
-		rtsx_status[6] = 1;
-
-	rtsx_status[7] = (u8)(chip->product_id);
-	rtsx_status[8] = chip->ic_version;
-
-	if (check_card_exist(chip, lun))
-		rtsx_status[9] = 1;
-	else
-		rtsx_status[9] = 0;
-
-	if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
-		rtsx_status[10] = 0;
-	else
-		rtsx_status[10] = 1;
-
-	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
-		if (chip->lun2card[lun] == SD_CARD)
-			rtsx_status[11] = SD_CARD;
-		else
-			rtsx_status[11] = MS_CARD;
-	} else {
-		rtsx_status[11] = XD_CARD | SD_CARD | MS_CARD;
-	}
-
-	if (check_card_ready(chip, lun))
-		rtsx_status[12] = 1;
-	else
-		rtsx_status[12] = 0;
-
-	if (get_lun_card(chip, lun) == XD_CARD) {
-		rtsx_status[13] = 0x40;
-	} else if (get_lun_card(chip, lun) == SD_CARD) {
-		struct sd_info *sd_card = &(chip->sd_card);
-
-		rtsx_status[13] = 0x20;
-		if (CHK_SD(sd_card)) {
-			if (CHK_SD_HCXC(sd_card))
-				rtsx_status[13] |= 0x04;
-			if (CHK_SD_HS(sd_card))
-				rtsx_status[13] |= 0x02;
-		} else {
-			rtsx_status[13] |= 0x08;
-			if (CHK_MMC_52M(sd_card))
-				rtsx_status[13] |= 0x02;
-			if (CHK_MMC_SECTOR_MODE(sd_card))
-				rtsx_status[13] |= 0x04;
-		}
-	} else if (get_lun_card(chip, lun) == MS_CARD) {
-		struct ms_info *ms_card = &(chip->ms_card);
-
-		if (CHK_MSPRO(ms_card)) {
-			rtsx_status[13] = 0x38;
-			if (CHK_HG8BIT(ms_card))
-				rtsx_status[13] |= 0x04;
-#ifdef SUPPORT_MSXC
-			if (CHK_MSXC(ms_card))
-				rtsx_status[13] |= 0x01;
-#endif
-		} else {
-			rtsx_status[13] = 0x30;
-		}
-	} else {
-		if (CHECK_LUN_MODE(chip, DEFAULT_SINGLE)) {
-#ifdef SUPPORT_SDIO
-			if (chip->sd_io && chip->sd_int)
-				rtsx_status[13] = 0x60;
-			else
-				rtsx_status[13] = 0x70;
-#else
-			rtsx_status[13] = 0x70;
-#endif
-		} else {
-			if (chip->lun2card[lun] == SD_CARD)
-				rtsx_status[13] = 0x20;
-			else
-				rtsx_status[13] = 0x30;
-		}
-	}
-
-	rtsx_status[14] = 0x78;
-	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip))
-		rtsx_status[15] = 0x83;
-	else
-		rtsx_status[15] = 0x82;
-
-	buf_len = min(scsi_bufflen(srb), (unsigned int)sizeof(rtsx_status));
-	rtsx_stor_set_xfer_buf(rtsx_status, buf_len, srb);
-	scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
-
-	return TRANSPORT_GOOD;
-}
-
-static int get_card_bus_width(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned int lun = SCSI_LUN(srb);
-	u8 card, bus_width;
-
-	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	card = get_lun_card(chip, lun);
-	if ((card == SD_CARD) || (card == MS_CARD)) {
-		bus_width = chip->card_bus_width[lun];
-	} else {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	scsi_set_resid(srb, 0);
-	rtsx_stor_set_xfer_buf(&bus_width, scsi_bufflen(srb), srb);
-
-	return TRANSPORT_GOOD;
-}
-
-static int spi_vendor_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int result;
-	unsigned int lun = SCSI_LUN(srb);
-	u8 gpio_dir;
-
-	if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	rtsx_force_power_on(chip, SSC_PDCTL);
-
-	rtsx_read_register(chip, CARD_GPIO_DIR, &gpio_dir);
-	rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir & 0x06);
-
-	switch (srb->cmnd[2]) {
-	case SCSI_SPI_GETSTATUS:
-		result = spi_get_status(srb, chip);
-		break;
-
-	case SCSI_SPI_SETPARAMETER:
-		result = spi_set_parameter(srb, chip);
-		break;
-
-	case SCSI_SPI_READFALSHID:
-		result = spi_read_flash_id(srb, chip);
-		break;
-
-	case SCSI_SPI_READFLASH:
-		result = spi_read_flash(srb, chip);
-		break;
-
-	case SCSI_SPI_WRITEFLASH:
-		result = spi_write_flash(srb, chip);
-		break;
-
-	case SCSI_SPI_WRITEFLASHSTATUS:
-		result = spi_write_flash_status(srb, chip);
-		break;
-
-	case SCSI_SPI_ERASEFLASH:
-		result = spi_erase_flash(srb, chip);
-		break;
-
-	default:
-		rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir);
-
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir);
-
-	if (result != STATUS_SUCCESS)
-		TRACE_RET(chip, TRANSPORT_FAILED);
-
-	return TRANSPORT_GOOD;
-}
-
-static int vendor_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int result;
-
-	switch (srb->cmnd[1]) {
-	case READ_STATUS:
-		result = read_status(srb, chip);
-		break;
-
-	case READ_MEM:
-		result = read_mem(srb, chip);
-		break;
-
-	case WRITE_MEM:
-		result = write_mem(srb, chip);
-		break;
-
-	case READ_EEPROM:
-		result = read_eeprom(srb, chip);
-		break;
-
-	case WRITE_EEPROM:
-		result = write_eeprom(srb, chip);
-		break;
-
-	case TOGGLE_GPIO:
-		result = toggle_gpio_cmd(srb, chip);
-		break;
-
-	case GET_SD_CSD:
-		result = get_sd_csd(srb, chip);
-		break;
-
-	case GET_BUS_WIDTH:
-		result = get_card_bus_width(srb, chip);
-		break;
-
-#ifdef _MSG_TRACE
-	case TRACE_MSG:
-		result = trace_msg_cmd(srb, chip);
-		break;
-#endif
-
-	case SCSI_APP_CMD:
-		result = app_cmd(srb, chip);
-		break;
-
-	case SPI_VENDOR_COMMAND:
-		result = spi_vendor_cmd(srb, chip);
-		break;
-
-	default:
-		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	return result;
-}
-
-#if !defined(LED_AUTO_BLINK) && !defined(REGULAR_BLINK)
-void led_shine(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned int lun = SCSI_LUN(srb);
-	u16 sec_cnt;
-
-	if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10))
-		sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
-	else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6))
-		sec_cnt = srb->cmnd[4];
-	else
-		return;
-
-	if (chip->rw_cap[lun] >= GPIO_TOGGLE_THRESHOLD) {
-		toggle_gpio(chip, LED_GPIO);
-		chip->rw_cap[lun] = 0;
-	} else {
-		chip->rw_cap[lun] += sec_cnt;
-	}
-}
-#endif
-
-static int ms_format_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	unsigned int lun = SCSI_LUN(srb);
-	int retval, quick_format;
-
-	if (get_lun_card(chip, lun) != MS_CARD) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if ((srb->cmnd[3] != 0x4D) || (srb->cmnd[4] != 0x47) ||
-		(srb->cmnd[5] != 0x66) || (srb->cmnd[6] != 0x6D) ||
-		(srb->cmnd[7] != 0x74)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-
-		if (!check_card_ready(chip, lun) ||
-				(get_card_size(chip, lun) == 0)) {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	if (srb->cmnd[8] & 0x01)
-		quick_format = 0;
-	else
-		quick_format = 1;
-
-	if (!(chip->card_ready & MS_CARD)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (chip->card_wp & MS_CARD) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (!CHK_MSPRO(ms_card)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	retval = mspro_format(srb, chip, MS_SHORT_DATA_LEN, quick_format);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	scsi_set_resid(srb, 0);
-	return TRANSPORT_GOOD;
-}
-
-#ifdef SUPPORT_PCGL_1P18
-static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	unsigned int lun = SCSI_LUN(srb);
-	u8 dev_info_id, data_len;
-	u8 *buf;
-	unsigned int buf_len;
-	int i;
-
-	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-	if ((get_lun_card(chip, lun) != MS_CARD)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if ((srb->cmnd[2] != 0xB0) || (srb->cmnd[4] != 0x4D) ||
-		(srb->cmnd[5] != 0x53) || (srb->cmnd[6] != 0x49) ||
-		(srb->cmnd[7] != 0x44)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	dev_info_id = srb->cmnd[3];
-	if ((CHK_MSXC(ms_card) && (dev_info_id == 0x10)) ||
-			(!CHK_MSXC(ms_card) && (dev_info_id == 0x13)) ||
-			!CHK_MSPRO(ms_card)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (dev_info_id == 0x15)
-		buf_len = data_len = 0x3A;
-	else
-		buf_len = data_len = 0x6A;
-
-	buf = kmalloc(buf_len, GFP_KERNEL);
-	if (!buf)
-		TRACE_RET(chip, TRANSPORT_ERROR);
-
-	i = 0;
-	/*  GET Memory Stick Media Information Response Header */
-	buf[i++] = 0x00;		/* Data length MSB */
-	buf[i++] = data_len; 		/* Data length LSB */
-	/* Device Information Type Code */
-	if (CHK_MSXC(ms_card))
-		buf[i++] = 0x03;
-	else
-		buf[i++] = 0x02;
-
-	/* SGM bit */
-	buf[i++] = 0x01;
-	/* Reserved */
-	buf[i++] = 0x00;
-	buf[i++] = 0x00;
-	buf[i++] = 0x00;
-	/* Number of Device Information */
-	buf[i++] = 0x01;
-
-	/*  Device Information Body */
-
-	/* Device Information ID Number */
-	buf[i++] = dev_info_id;
-	/* Device Information Length */
-	if (dev_info_id == 0x15)
-		data_len = 0x31;
-	else
-		data_len = 0x61;
-
-	buf[i++] = 0x00;		/* Data length MSB */
-	buf[i++] = data_len; 		/* Data length LSB */
-	/* Valid Bit */
-	buf[i++] = 0x80;
-	if ((dev_info_id == 0x10) || (dev_info_id == 0x13)) {
-		/* System Information */
-		memcpy(buf+i, ms_card->raw_sys_info, 96);
-	} else {
-		/* Model Name */
-		memcpy(buf+i, ms_card->raw_model_name, 48);
-	}
-
-	rtsx_stor_set_xfer_buf(buf, buf_len, srb);
-
-	if (dev_info_id == 0x15)
-		scsi_set_resid(srb, scsi_bufflen(srb)-0x3C);
-	else
-		scsi_set_resid(srb, scsi_bufflen(srb)-0x6C);
-
-	kfree(buf);
-	return STATUS_SUCCESS;
-}
-#endif
-
-static int ms_sp_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int retval = TRANSPORT_ERROR;
-
-	if (srb->cmnd[2] == MS_FORMAT)
-		retval = ms_format_cmnd(srb, chip);
-#ifdef SUPPORT_PCGL_1P18
-	else if (srb->cmnd[2] == GET_MS_INFORMATION)
-		retval = get_ms_information(srb, chip);
-#endif
-
-	return retval;
-}
-
-#ifdef SUPPORT_CPRM
-static int sd_extention_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	unsigned int lun = SCSI_LUN(srb);
-	int result;
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	sd_cleanup_work(chip);
-
-	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-	if ((get_lun_card(chip, lun) != SD_CARD)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	switch (srb->cmnd[0]) {
-	case SD_PASS_THRU_MODE:
-		result = sd_pass_thru_mode(srb, chip);
-		break;
-
-	case SD_EXECUTE_NO_DATA:
-		result = sd_execute_no_data(srb, chip);
-		break;
-
-	case SD_EXECUTE_READ:
-		result = sd_execute_read_data(srb, chip);
-		break;
-
-	case SD_EXECUTE_WRITE:
-		result = sd_execute_write_data(srb, chip);
-		break;
-
-	case SD_GET_RSP:
-		result = sd_get_cmd_rsp(srb, chip);
-		break;
-
-	case SD_HW_RST:
-		result = sd_hw_rst(srb, chip);
-		break;
-
-	default:
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	return result;
-}
-#endif
-
-#ifdef SUPPORT_MAGIC_GATE
-static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	unsigned int lun = SCSI_LUN(srb);
-	int retval;
-	u8 key_format;
-
-	RTSX_DEBUGP("--%s--\n", __func__);
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	ms_cleanup_work(chip);
-
-	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-	if ((get_lun_card(chip, lun) != MS_CARD)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (srb->cmnd[7] != KC_MG_R_PRO) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (!CHK_MSPRO(ms_card)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	key_format = srb->cmnd[10] & 0x3F;
-	RTSX_DEBUGP("key_format = 0x%x\n", key_format);
-
-	switch (key_format) {
-	case KF_GET_LOC_EKB:
-		if ((scsi_bufflen(srb) == 0x41C) &&
-			(srb->cmnd[8] == 0x04) &&
-			(srb->cmnd[9] == 0x1C)) {
-			retval = mg_get_local_EKB(srb, chip);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, TRANSPORT_FAILED);
-
-		} else {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-		break;
-
-	case KF_RSP_CHG:
-		if ((scsi_bufflen(srb) == 0x24) &&
-			(srb->cmnd[8] == 0x00) &&
-			(srb->cmnd[9] == 0x24)) {
-			retval = mg_get_rsp_chg(srb, chip);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, TRANSPORT_FAILED);
-
-		} else {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-		break;
-
-	case KF_GET_ICV:
-		ms_card->mg_entry_num = srb->cmnd[5];
-		if ((scsi_bufflen(srb) == 0x404) &&
-			(srb->cmnd[8] == 0x04) &&
-			(srb->cmnd[9] == 0x04) &&
-			(srb->cmnd[2] == 0x00) &&
-			(srb->cmnd[3] == 0x00) &&
-			(srb->cmnd[4] == 0x00) &&
-			(srb->cmnd[5] < 32)) {
-			retval = mg_get_ICV(srb, chip);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, TRANSPORT_FAILED);
-
-		} else {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-		break;
-
-	default:
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	scsi_set_resid(srb, 0);
-	return TRANSPORT_GOOD;
-}
-
-static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct ms_info *ms_card = &(chip->ms_card);
-	unsigned int lun = SCSI_LUN(srb);
-	int retval;
-	u8 key_format;
-
-	RTSX_DEBUGP("--%s--\n", __func__);
-
-	rtsx_disable_aspm(chip);
-
-	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
-		rtsx_exit_ss(chip);
-		wait_timeout(100);
-	}
-	rtsx_set_stat(chip, RTSX_STAT_RUN);
-
-	ms_cleanup_work(chip);
-
-	if (!check_card_ready(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-	if (check_card_wp(chip, lun)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-	if ((get_lun_card(chip, lun) != MS_CARD)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (srb->cmnd[7] != KC_MG_R_PRO) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (!CHK_MSPRO(ms_card)) {
-		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	key_format = srb->cmnd[10] & 0x3F;
-	RTSX_DEBUGP("key_format = 0x%x\n", key_format);
-
-	switch (key_format) {
-	case KF_SET_LEAF_ID:
-		if ((scsi_bufflen(srb) == 0x0C) &&
-			(srb->cmnd[8] == 0x00) &&
-			(srb->cmnd[9] == 0x0C)) {
-			retval = mg_set_leaf_id(srb, chip);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, TRANSPORT_FAILED);
-
-		} else {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-		break;
-
-	case KF_CHG_HOST:
-		if ((scsi_bufflen(srb) == 0x0C) &&
-			(srb->cmnd[8] == 0x00) &&
-			(srb->cmnd[9] == 0x0C)) {
-			retval = mg_chg(srb, chip);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, TRANSPORT_FAILED);
-
-		} else {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-		break;
-
-	case KF_RSP_HOST:
-		if ((scsi_bufflen(srb) == 0x0C) &&
-			(srb->cmnd[8] == 0x00) &&
-			(srb->cmnd[9] == 0x0C)) {
-			retval = mg_rsp(srb, chip);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, TRANSPORT_FAILED);
-
-		} else {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-		break;
-
-	case KF_SET_ICV:
-		ms_card->mg_entry_num = srb->cmnd[5];
-		if ((scsi_bufflen(srb) == 0x404) &&
-			(srb->cmnd[8] == 0x04) &&
-			(srb->cmnd[9] == 0x04) &&
-			(srb->cmnd[2] == 0x00) &&
-			(srb->cmnd[3] == 0x00) &&
-			(srb->cmnd[4] == 0x00) &&
-			(srb->cmnd[5] < 32)) {
-			retval = mg_set_ICV(srb, chip);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, TRANSPORT_FAILED);
-
-		} else {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-		break;
-
-	default:
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	scsi_set_resid(srb, 0);
-	return TRANSPORT_GOOD;
-}
-#endif
-
-int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-#ifdef SUPPORT_SD_LOCK
-	struct sd_info *sd_card = &(chip->sd_card);
-#endif
-	struct ms_info *ms_card = &(chip->ms_card);
-	unsigned int lun = SCSI_LUN(srb);
-	int result;
-
-#ifdef SUPPORT_SD_LOCK
-	if (sd_card->sd_erase_status) {
-		/* Block all SCSI command except for
-		 * REQUEST_SENSE and rs_ppstatus
-		 */
-		if (!((srb->cmnd[0] == VENDOR_CMND) &&
-				(srb->cmnd[1] == SCSI_APP_CMD) &&
-				(srb->cmnd[2] == GET_DEV_STATUS)) &&
-				(srb->cmnd[0] != REQUEST_SENSE)) {
-			/* Logical Unit Not Ready Format in Progress */
-			set_sense_data(chip, lun, CUR_ERR,
-				       0x02, 0, 0x04, 0x04, 0, 0);
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	}
-#endif
-
-	if ((get_lun_card(chip, lun) == MS_CARD) &&
-			(ms_card->format_status == FORMAT_IN_PROGRESS)) {
-		if ((srb->cmnd[0] != REQUEST_SENSE) && (srb->cmnd[0] != INQUIRY)) {
-			/* Logical Unit Not Ready Format in Progress */
-			set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
-					0, (u16)(ms_card->progress));
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	}
-
-	switch (srb->cmnd[0]) {
-	case READ_10:
-	case WRITE_10:
-	case READ_6:
-	case WRITE_6:
-		result = read_write(srb, chip);
-#if !defined(LED_AUTO_BLINK) && !defined(REGULAR_BLINK)
-		led_shine(srb, chip);
-#endif
-		break;
-
-	case TEST_UNIT_READY:
-		result = test_unit_ready(srb, chip);
-		break;
-
-	case INQUIRY:
-		result = inquiry(srb, chip);
-		break;
-
-	case READ_CAPACITY:
-		result = read_capacity(srb, chip);
-		break;
-
-	case START_STOP:
-		result = start_stop_unit(srb, chip);
-		break;
-
-	case ALLOW_MEDIUM_REMOVAL:
-		result = allow_medium_removal(srb, chip);
-		break;
-
-	case REQUEST_SENSE:
-		result = request_sense(srb, chip);
-		break;
-
-	case MODE_SENSE:
-	case MODE_SENSE_10:
-		result = mode_sense(srb, chip);
-		break;
-
-	case 0x23:
-		result = read_format_capacity(srb, chip);
-		break;
-
-	case VENDOR_CMND:
-		result = vendor_cmnd(srb, chip);
-		break;
-
-	case MS_SP_CMND:
-		result = ms_sp_cmnd(srb, chip);
-		break;
-
-#ifdef SUPPORT_CPRM
-	case SD_PASS_THRU_MODE:
-	case SD_EXECUTE_NO_DATA:
-	case SD_EXECUTE_READ:
-	case SD_EXECUTE_WRITE:
-	case SD_GET_RSP:
-	case SD_HW_RST:
-		result = sd_extention_cmnd(srb, chip);
-		break;
-#endif
-
-#ifdef SUPPORT_MAGIC_GATE
-	case CMD_MSPRO_MG_RKEY:
-		result = mg_report_key(srb, chip);
-		break;
-
-	case CMD_MSPRO_MG_SKEY:
-		result = mg_send_key(srb, chip);
-		break;
-#endif
-
-	case FORMAT_UNIT:
-	case MODE_SELECT:
-	case VERIFY:
-		result = TRANSPORT_GOOD;
-		break;
-
-	default:
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		result = TRANSPORT_FAILED;
-	}
-
-	return result;
-}
diff --git a/drivers/staging/rts_pstor/rtsx_scsi.h b/drivers/staging/rts_pstor/rtsx_scsi.h
deleted file mode 100644
index 64b8499..0000000
--- a/drivers/staging/rts_pstor/rtsx_scsi.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- * Header file
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#ifndef __REALTEK_RTSX_SCSI_H
-#define __REALTEK_RTSX_SCSI_H
-
-#include "rtsx.h"
-#include "rtsx_chip.h"
-
-#define MS_SP_CMND		0xFA
-#define MS_FORMAT		0xA0
-#define GET_MS_INFORMATION	0xB0
-
-#define VENDOR_CMND		0xF0
-
-#define READ_STATUS		0x09
-
-#define READ_EEPROM		0x04
-#define WRITE_EEPROM		0x05
-#define READ_MEM		0x0D
-#define WRITE_MEM		0x0E
-#define GET_BUS_WIDTH		0x13
-#define GET_SD_CSD		0x14
-#define TOGGLE_GPIO		0x15
-#define TRACE_MSG		0x18
-
-#define SCSI_APP_CMD		0x10
-
-#define PP_READ10		0x1A
-#define PP_WRITE10		0x0A
-#define READ_HOST_REG		0x1D
-#define WRITE_HOST_REG		0x0D
-#define SET_VAR			0x05
-#define GET_VAR			0x15
-#define DMA_READ		0x16
-#define DMA_WRITE		0x06
-#define GET_DEV_STATUS		0x10
-#define SET_CHIP_MODE		0x27
-#define SUIT_CMD		0xE0
-#define WRITE_PHY		0x07
-#define READ_PHY		0x17
-#define WRITE_EEPROM2		0x03
-#define READ_EEPROM2		0x13
-#define ERASE_EEPROM2		0x23
-#define WRITE_EFUSE		0x04
-#define READ_EFUSE		0x14
-#define WRITE_CFG		0x0E
-#define READ_CFG		0x1E
-
-#define SPI_VENDOR_COMMAND		0x1C
-
-#define	SCSI_SPI_GETSTATUS		0x00
-#define	SCSI_SPI_SETPARAMETER		0x01
-#define	SCSI_SPI_READFALSHID		0x02
-#define	SCSI_SPI_READFLASH		0x03
-#define	SCSI_SPI_WRITEFLASH		0x04
-#define	SCSI_SPI_WRITEFLASHSTATUS	0x05
-#define	SCSI_SPI_ERASEFLASH		0x06
-
-#define INIT_BATCHCMD		0x41
-#define ADD_BATCHCMD		0x42
-#define SEND_BATCHCMD		0x43
-#define GET_BATCHRSP		0x44
-
-#define CHIP_NORMALMODE		0x00
-#define CHIP_DEBUGMODE		0x01
-
-/* SD Pass Through Command Extension */
-#define SD_PASS_THRU_MODE	0xD0
-#define SD_EXECUTE_NO_DATA	0xD1
-#define SD_EXECUTE_READ		0xD2
-#define SD_EXECUTE_WRITE	0xD3
-#define SD_GET_RSP		0xD4
-#define SD_HW_RST		0xD6
-
-#ifdef SUPPORT_MAGIC_GATE
-#define CMD_MSPRO_MG_RKEY	0xA4   /* Report Key Command */
-#define CMD_MSPRO_MG_SKEY	0xA3   /* Send Key Command */
-
-/* CBWCB field: key class */
-#define KC_MG_R_PRO		0xBE   /* MG-R PRO*/
-
-/* CBWCB field: key format */
-#define KF_SET_LEAF_ID		0x31   /* Set Leaf ID */
-#define KF_GET_LOC_EKB		0x32   /* Get Local EKB */
-#define KF_CHG_HOST		0x33   /* Challenge (host) */
-#define KF_RSP_CHG		0x34   /* Response and Challenge (device)  */
-#define KF_RSP_HOST		0x35   /* Response (host) */
-#define KF_GET_ICV		0x36   /* Get ICV */
-#define KF_SET_ICV		0x37   /* SSet ICV */
-#endif
-
-/* Sense type */
-#define	SENSE_TYPE_NO_SENSE				0
-#define	SENSE_TYPE_MEDIA_CHANGE				1
-#define	SENSE_TYPE_MEDIA_NOT_PRESENT			2
-#define	SENSE_TYPE_MEDIA_LBA_OVER_RANGE			3
-#define	SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT		4
-#define	SENSE_TYPE_MEDIA_WRITE_PROTECT			5
-#define	SENSE_TYPE_MEDIA_INVALID_CMD_FIELD		6
-#define	SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR		7
-#define	SENSE_TYPE_MEDIA_WRITE_ERR			8
-#define SENSE_TYPE_FORMAT_IN_PROGRESS			9
-#define SENSE_TYPE_FORMAT_CMD_FAILED			10
-#ifdef SUPPORT_MAGIC_GATE
-#define SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB		0x0b
-#define SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN		0x0c
-#define SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM		0x0d
-#define SENSE_TYPE_MG_WRITE_ERR				0x0e
-#endif
-#ifdef SUPPORT_SD_LOCK
-#define SENSE_TYPE_MEDIA_READ_FORBIDDEN			0x10  /* FOR Locked SD card*/
-#endif
-
-void scsi_show_command(struct scsi_cmnd *srb);
-void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type);
-void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code, u8 sense_key,
-		u32 info, u8 asc, u8 ascq, u8 sns_key_info0, u16 sns_key_info1);
-int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-
-#endif   /* __REALTEK_RTSX_SCSI_H */
-
diff --git a/drivers/staging/rts_pstor/rtsx_sys.h b/drivers/staging/rts_pstor/rtsx_sys.h
deleted file mode 100644
index 8e55a3a..0000000
--- a/drivers/staging/rts_pstor/rtsx_sys.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- * Header file
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#ifndef __RTSX_SYS_H
-#define __RTSX_SYS_H
-
-#include "rtsx.h"
-#include "rtsx_chip.h"
-#include "rtsx_card.h"
-
-typedef dma_addr_t ULONG_PTR;
-
-static inline void rtsx_exclusive_enter_ss(struct rtsx_chip *chip)
-{
-	struct rtsx_dev *dev = chip->rtsx;
-
-	spin_lock(&(dev->reg_lock));
-	rtsx_enter_ss(chip);
-	spin_unlock(&(dev->reg_lock));
-}
-
-static inline void rtsx_reset_detected_cards(struct rtsx_chip *chip, int flag)
-{
-	rtsx_reset_cards(chip);
-}
-
-#define RTSX_MSG_IN_INT(x)
-
-#endif  /* __RTSX_SYS_H */
-
diff --git a/drivers/staging/rts_pstor/rtsx_transport.c b/drivers/staging/rts_pstor/rtsx_transport.c
deleted file mode 100644
index 1f9a424..0000000
--- a/drivers/staging/rts_pstor/rtsx_transport.c
+++ /dev/null
@@ -1,769 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-
-#include "rtsx.h"
-#include "rtsx_scsi.h"
-#include "rtsx_transport.h"
-#include "rtsx_chip.h"
-#include "rtsx_card.h"
-#include "debug.h"
-
-/***********************************************************************
- * Scatter-gather transfer buffer access routines
- ***********************************************************************/
-
-/* Copy a buffer of length buflen to/from the srb's transfer buffer.
- * (Note: for scatter-gather transfers (srb->use_sg > 0), srb->request_buffer
- * points to a list of s-g entries and we ignore srb->request_bufflen.
- * For non-scatter-gather transfers, srb->request_buffer points to the
- * transfer buffer itself and srb->request_bufflen is the buffer's length.)
- * Update the *index and *offset variables so that the next copy will
- * pick up from where this one left off. */
-
-unsigned int rtsx_stor_access_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
-	unsigned int *offset, enum xfer_buf_dir dir)
-{
-	unsigned int cnt;
-
-	/* If not using scatter-gather, just transfer the data directly.
-	 * Make certain it will fit in the available buffer space. */
-	if (scsi_sg_count(srb) == 0) {
-		if (*offset >= scsi_bufflen(srb))
-			return 0;
-		cnt = min(buflen, scsi_bufflen(srb) - *offset);
-		if (dir == TO_XFER_BUF)
-			memcpy((unsigned char *) scsi_sglist(srb) + *offset,
-					buffer, cnt);
-		else
-			memcpy(buffer, (unsigned char *) scsi_sglist(srb) +
-					*offset, cnt);
-		*offset += cnt;
-
-	/* Using scatter-gather.  We have to go through the list one entry
-	 * at a time.  Each s-g entry contains some number of pages, and
-	 * each page has to be kmap()'ed separately.  If the page is already
-	 * in kernel-addressable memory then kmap() will return its address.
-	 * If the page is not directly accessible -- such as a user buffer
-	 * located in high memory -- then kmap() will map it to a temporary
-	 * position in the kernel's virtual address space. */
-	} else {
-		struct scatterlist *sg =
-				(struct scatterlist *) scsi_sglist(srb)
-				+ *index;
-
-		/* This loop handles a single s-g list entry, which may
-		 * include multiple pages.  Find the initial page structure
-		 * and the starting offset within the page, and update
-		 * the *offset and *index values for the next loop. */
-		cnt = 0;
-		while (cnt < buflen && *index < scsi_sg_count(srb)) {
-			struct page *page = sg_page(sg) +
-					((sg->offset + *offset) >> PAGE_SHIFT);
-			unsigned int poff =
-					(sg->offset + *offset) & (PAGE_SIZE-1);
-			unsigned int sglen = sg->length - *offset;
-
-			if (sglen > buflen - cnt) {
-
-				/* Transfer ends within this s-g entry */
-				sglen = buflen - cnt;
-				*offset += sglen;
-			} else {
-
-				/* Transfer continues to next s-g entry */
-				*offset = 0;
-				++*index;
-				++sg;
-			}
-
-			/* Transfer the data for all the pages in this
-			 * s-g entry.  For each page: call kmap(), do the
-			 * transfer, and call kunmap() immediately after. */
-			while (sglen > 0) {
-				unsigned int plen = min(sglen, (unsigned int)
-						PAGE_SIZE - poff);
-				unsigned char *ptr = kmap(page);
-
-				if (dir == TO_XFER_BUF)
-					memcpy(ptr + poff, buffer + cnt, plen);
-				else
-					memcpy(buffer + cnt, ptr + poff, plen);
-				kunmap(page);
-
-				/* Start at the beginning of the next page */
-				poff = 0;
-				++page;
-				cnt += plen;
-				sglen -= plen;
-			}
-		}
-	}
-
-	/* Return the amount actually transferred */
-	return cnt;
-}
-
-/* Store the contents of buffer into srb's transfer buffer and set the
-* SCSI residue. */
-void rtsx_stor_set_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, struct scsi_cmnd *srb)
-{
-	unsigned int index = 0, offset = 0;
-
-	rtsx_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset,
-				  TO_XFER_BUF);
-	if (buflen < scsi_bufflen(srb))
-		scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
-}
-
-void rtsx_stor_get_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, struct scsi_cmnd *srb)
-{
-	unsigned int index = 0, offset = 0;
-
-	rtsx_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset,
-				  FROM_XFER_BUF);
-	if (buflen < scsi_bufflen(srb))
-		scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
-}
-
-
-/***********************************************************************
- * Transport routines
- ***********************************************************************/
-
-/* Invoke the transport and basic error-handling/recovery methods
- *
- * This is used to send the message to the device and receive the response.
- */
-void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int result;
-
-	result = rtsx_scsi_handler(srb, chip);
-
-	/* if the command gets aborted by the higher layers, we need to
-	 * short-circuit all other processing
-	 */
-	if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) {
-		RTSX_DEBUGP("-- command was aborted\n");
-		srb->result = DID_ABORT << 16;
-		goto Handle_Errors;
-	}
-
-	/* if there is a transport error, reset and don't auto-sense */
-	if (result == TRANSPORT_ERROR) {
-		RTSX_DEBUGP("-- transport indicates error, resetting\n");
-		srb->result = DID_ERROR << 16;
-		goto Handle_Errors;
-	}
-
-	srb->result = SAM_STAT_GOOD;
-
-	/*
-	 * If we have a failure, we're going to do a REQUEST_SENSE
-	 * automatically.  Note that we differentiate between a command
-	 * "failure" and an "error" in the transport mechanism.
-	 */
-	if (result == TRANSPORT_FAILED) {
-		/* set the result so the higher layers expect this data */
-		srb->result = SAM_STAT_CHECK_CONDITION;
-		memcpy(srb->sense_buffer,
-			(unsigned char *)&(chip->sense_buffer[SCSI_LUN(srb)]),
-			sizeof(struct sense_data_t));
-	}
-
-	return;
-
-	/* Error and abort processing: try to resynchronize with the device
-	 * by issuing a port reset.  If that fails, try a class-specific
-	 * device reset. */
-Handle_Errors:
-	return;
-}
-
-void rtsx_add_cmd(struct rtsx_chip *chip,
-		u8 cmd_type, u16 reg_addr, u8 mask, u8 data)
-{
-	u32 *cb = (u32 *)(chip->host_cmds_ptr);
-	u32 val = 0;
-
-	val |= (u32)(cmd_type & 0x03) << 30;
-	val |= (u32)(reg_addr & 0x3FFF) << 16;
-	val |= (u32)mask << 8;
-	val |= (u32)data;
-
-	spin_lock_irq(&chip->rtsx->reg_lock);
-	if (chip->ci < (HOST_CMDS_BUF_LEN / 4))
-		cb[(chip->ci)++] = cpu_to_le32(val);
-
-	spin_unlock_irq(&chip->rtsx->reg_lock);
-}
-
-void rtsx_send_cmd_no_wait(struct rtsx_chip *chip)
-{
-	u32 val = 1 << 31;
-
-	rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr);
-
-	val |= (u32)(chip->ci * 4) & 0x00FFFFFF;
-	/* Hardware Auto Response */
-	val |= 0x40000000;
-	rtsx_writel(chip, RTSX_HCBCTLR, val);
-}
-
-int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout)
-{
-	struct rtsx_dev *rtsx = chip->rtsx;
-	struct completion trans_done;
-	u32 val = 1 << 31;
-	long timeleft;
-	int err = 0;
-
-	if (card == SD_CARD)
-		rtsx->check_card_cd = SD_EXIST;
-	else if (card == MS_CARD)
-		rtsx->check_card_cd = MS_EXIST;
-	else if (card == XD_CARD)
-		rtsx->check_card_cd = XD_EXIST;
-	else
-		rtsx->check_card_cd = 0;
-
-	spin_lock_irq(&rtsx->reg_lock);
-
-	/* set up data structures for the wakeup system */
-	rtsx->done = &trans_done;
-	rtsx->trans_result = TRANS_NOT_READY;
-	init_completion(&trans_done);
-	rtsx->trans_state = STATE_TRANS_CMD;
-
-	rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr);
-
-	val |= (u32)(chip->ci * 4) & 0x00FFFFFF;
-	/* Hardware Auto Response */
-	val |= 0x40000000;
-	rtsx_writel(chip, RTSX_HCBCTLR, val);
-
-	spin_unlock_irq(&rtsx->reg_lock);
-
-	/* Wait for TRANS_OK_INT */
-	timeleft = wait_for_completion_interruptible_timeout(
-		&trans_done, timeout * HZ / 1000);
-	if (timeleft <= 0) {
-		RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
-		err = -ETIMEDOUT;
-		TRACE_GOTO(chip, finish_send_cmd);
-	}
-
-	spin_lock_irq(&rtsx->reg_lock);
-	if (rtsx->trans_result == TRANS_RESULT_FAIL)
-		err = -EIO;
-	else if (rtsx->trans_result == TRANS_RESULT_OK)
-		err = 0;
-
-	spin_unlock_irq(&rtsx->reg_lock);
-
-finish_send_cmd:
-	rtsx->done = NULL;
-	rtsx->trans_state = STATE_TRANS_NONE;
-
-	if (err < 0)
-		rtsx_stop_cmd(chip, card);
-
-	return err;
-}
-
-static inline void rtsx_add_sg_tbl(
-	struct rtsx_chip *chip, u32 addr, u32 len, u8 option)
-{
-	u64 *sgb = (u64 *)(chip->host_sg_tbl_ptr);
-	u64 val = 0;
-	u32 temp_len = 0;
-	u8  temp_opt = 0;
-
-	do {
-		if (len > 0x80000) {
-			temp_len = 0x80000;
-			temp_opt = option & (~SG_END);
-		} else {
-			temp_len = len;
-			temp_opt = option;
-		}
-		val = ((u64)addr << 32) | ((u64)temp_len << 12) | temp_opt;
-
-		if (chip->sgi < (HOST_SG_TBL_BUF_LEN / 8))
-			sgb[(chip->sgi)++] = cpu_to_le64(val);
-
-		len -= temp_len;
-		addr += temp_len;
-	} while (len);
-}
-
-static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card,
-		struct scatterlist *sg, int num_sg, unsigned int *index,
-		unsigned int *offset, int size,
-		enum dma_data_direction dma_dir, int timeout)
-{
-	struct rtsx_dev *rtsx = chip->rtsx;
-	struct completion trans_done;
-	u8 dir;
-	int sg_cnt, i, resid;
-	int err = 0;
-	long timeleft;
-	struct scatterlist *sg_ptr;
-	u32 val = TRIG_DMA;
-
-	if ((sg == NULL) || (num_sg <= 0) || !offset || !index)
-		return -EIO;
-
-	if (dma_dir == DMA_TO_DEVICE)
-		dir = HOST_TO_DEVICE;
-	else if (dma_dir == DMA_FROM_DEVICE)
-		dir = DEVICE_TO_HOST;
-	else
-		return -ENXIO;
-
-	if (card == SD_CARD)
-		rtsx->check_card_cd = SD_EXIST;
-	else if (card == MS_CARD)
-		rtsx->check_card_cd = MS_EXIST;
-	else if (card == XD_CARD)
-		rtsx->check_card_cd = XD_EXIST;
-	else
-		rtsx->check_card_cd = 0;
-
-	spin_lock_irq(&rtsx->reg_lock);
-
-	/* set up data structures for the wakeup system */
-	rtsx->done = &trans_done;
-
-	rtsx->trans_state = STATE_TRANS_SG;
-	rtsx->trans_result = TRANS_NOT_READY;
-
-	spin_unlock_irq(&rtsx->reg_lock);
-
-	sg_cnt = dma_map_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
-
-	resid = size;
-	sg_ptr = sg;
-	chip->sgi = 0;
-	/* Usually the next entry will be @sg@ + 1, but if this sg element
-	 * is part of a chained scatterlist, it could jump to the start of
-	 * a new scatterlist array. So here we use sg_next to move to
-	 * the proper sg
-	 */
-	for (i = 0; i < *index; i++)
-		sg_ptr = sg_next(sg_ptr);
-	for (i = *index; i < sg_cnt; i++) {
-		dma_addr_t addr;
-		unsigned int len;
-		u8 option;
-
-		addr = sg_dma_address(sg_ptr);
-		len = sg_dma_len(sg_ptr);
-
-		RTSX_DEBUGP("DMA addr: 0x%x, Len: 0x%x\n",
-			     (unsigned int)addr, len);
-		RTSX_DEBUGP("*index = %d, *offset = %d\n", *index, *offset);
-
-		addr += *offset;
-
-		if ((len - *offset) > resid) {
-			*offset += resid;
-			len = resid;
-			resid = 0;
-		} else {
-			resid -= (len - *offset);
-			len -= *offset;
-			*offset = 0;
-			*index = *index + 1;
-		}
-		if ((i == (sg_cnt - 1)) || !resid)
-			option = SG_VALID | SG_END | SG_TRANS_DATA;
-		else
-			option = SG_VALID | SG_TRANS_DATA;
-
-		rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option);
-
-		if (!resid)
-			break;
-
-		sg_ptr = sg_next(sg_ptr);
-	}
-
-	RTSX_DEBUGP("SG table count = %d\n", chip->sgi);
-
-	val |= (u32)(dir & 0x01) << 29;
-	val |= ADMA_MODE;
-
-	spin_lock_irq(&rtsx->reg_lock);
-
-	init_completion(&trans_done);
-
-	rtsx_writel(chip, RTSX_HDBAR, chip->host_sg_tbl_addr);
-	rtsx_writel(chip, RTSX_HDBCTLR, val);
-
-	spin_unlock_irq(&rtsx->reg_lock);
-
-	timeleft = wait_for_completion_interruptible_timeout(
-		&trans_done, timeout * HZ / 1000);
-	if (timeleft <= 0) {
-		RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
-		RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
-		err = -ETIMEDOUT;
-		goto out;
-	}
-
-	spin_lock_irq(&rtsx->reg_lock);
-	if (rtsx->trans_result == TRANS_RESULT_FAIL) {
-		err = -EIO;
-		spin_unlock_irq(&rtsx->reg_lock);
-		goto out;
-	}
-	spin_unlock_irq(&rtsx->reg_lock);
-
-	/* Wait for TRANS_OK_INT */
-	spin_lock_irq(&rtsx->reg_lock);
-	if (rtsx->trans_result == TRANS_NOT_READY) {
-		init_completion(&trans_done);
-		spin_unlock_irq(&rtsx->reg_lock);
-		timeleft = wait_for_completion_interruptible_timeout(
-			&trans_done, timeout * HZ / 1000);
-		if (timeleft <= 0) {
-			RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
-			RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
-			err = -ETIMEDOUT;
-			goto out;
-		}
-	} else {
-		spin_unlock_irq(&rtsx->reg_lock);
-	}
-
-	spin_lock_irq(&rtsx->reg_lock);
-	if (rtsx->trans_result == TRANS_RESULT_FAIL)
-		err = -EIO;
-	else if (rtsx->trans_result == TRANS_RESULT_OK)
-		err = 0;
-
-	spin_unlock_irq(&rtsx->reg_lock);
-
-out:
-	rtsx->done = NULL;
-	rtsx->trans_state = STATE_TRANS_NONE;
-	dma_unmap_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
-
-	if (err < 0)
-		rtsx_stop_cmd(chip, card);
-
-	return err;
-}
-
-static int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card,
-		struct scatterlist *sg, int num_sg,
-		enum dma_data_direction dma_dir, int timeout)
-{
-	struct rtsx_dev *rtsx = chip->rtsx;
-	struct completion trans_done;
-	u8 dir;
-	int buf_cnt, i;
-	int err = 0;
-	long timeleft;
-	struct scatterlist *sg_ptr;
-
-	if ((sg == NULL) || (num_sg <= 0))
-		return -EIO;
-
-	if (dma_dir == DMA_TO_DEVICE)
-		dir = HOST_TO_DEVICE;
-	else if (dma_dir == DMA_FROM_DEVICE)
-		dir = DEVICE_TO_HOST;
-	else
-		return -ENXIO;
-
-	if (card == SD_CARD)
-		rtsx->check_card_cd = SD_EXIST;
-	else if (card == MS_CARD)
-		rtsx->check_card_cd = MS_EXIST;
-	else if (card == XD_CARD)
-		rtsx->check_card_cd = XD_EXIST;
-	else
-		rtsx->check_card_cd = 0;
-
-	spin_lock_irq(&rtsx->reg_lock);
-
-	/* set up data structures for the wakeup system */
-	rtsx->done = &trans_done;
-
-	rtsx->trans_state = STATE_TRANS_SG;
-	rtsx->trans_result = TRANS_NOT_READY;
-
-	spin_unlock_irq(&rtsx->reg_lock);
-
-	buf_cnt = dma_map_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
-
-	sg_ptr = sg;
-
-	for (i = 0; i <= buf_cnt / (HOST_SG_TBL_BUF_LEN / 8); i++) {
-		u32 val = TRIG_DMA;
-		int sg_cnt, j;
-
-		if (i == buf_cnt / (HOST_SG_TBL_BUF_LEN / 8))
-			sg_cnt = buf_cnt % (HOST_SG_TBL_BUF_LEN / 8);
-		else
-			sg_cnt = (HOST_SG_TBL_BUF_LEN / 8);
-
-		chip->sgi = 0;
-		for (j = 0; j < sg_cnt; j++) {
-			dma_addr_t addr = sg_dma_address(sg_ptr);
-			unsigned int len = sg_dma_len(sg_ptr);
-			u8 option;
-
-			RTSX_DEBUGP("DMA addr: 0x%x, Len: 0x%x\n",
-				     (unsigned int)addr, len);
-
-			if (j == (sg_cnt - 1))
-				option = SG_VALID | SG_END | SG_TRANS_DATA;
-			else
-				option = SG_VALID | SG_TRANS_DATA;
-
-			rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option);
-
-			sg_ptr = sg_next(sg_ptr);
-		}
-
-		RTSX_DEBUGP("SG table count = %d\n", chip->sgi);
-
-		val |= (u32)(dir & 0x01) << 29;
-		val |= ADMA_MODE;
-
-		spin_lock_irq(&rtsx->reg_lock);
-
-		init_completion(&trans_done);
-
-		rtsx_writel(chip, RTSX_HDBAR, chip->host_sg_tbl_addr);
-		rtsx_writel(chip, RTSX_HDBCTLR, val);
-
-		spin_unlock_irq(&rtsx->reg_lock);
-
-		timeleft = wait_for_completion_interruptible_timeout(
-			&trans_done, timeout * HZ / 1000);
-		if (timeleft <= 0) {
-			RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
-			RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
-			err = -ETIMEDOUT;
-			goto out;
-		}
-
-		spin_lock_irq(&rtsx->reg_lock);
-		if (rtsx->trans_result == TRANS_RESULT_FAIL) {
-			err = -EIO;
-			spin_unlock_irq(&rtsx->reg_lock);
-			goto out;
-		}
-		spin_unlock_irq(&rtsx->reg_lock);
-
-		sg_ptr += sg_cnt;
-	}
-
-	/* Wait for TRANS_OK_INT */
-	spin_lock_irq(&rtsx->reg_lock);
-	if (rtsx->trans_result == TRANS_NOT_READY) {
-		init_completion(&trans_done);
-		spin_unlock_irq(&rtsx->reg_lock);
-		timeleft = wait_for_completion_interruptible_timeout(
-			&trans_done, timeout * HZ / 1000);
-		if (timeleft <= 0) {
-			RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
-			RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
-			err = -ETIMEDOUT;
-			goto out;
-		}
-	} else {
-		spin_unlock_irq(&rtsx->reg_lock);
-	}
-
-	spin_lock_irq(&rtsx->reg_lock);
-	if (rtsx->trans_result == TRANS_RESULT_FAIL)
-		err = -EIO;
-	else if (rtsx->trans_result == TRANS_RESULT_OK)
-		err = 0;
-
-	spin_unlock_irq(&rtsx->reg_lock);
-
-out:
-	rtsx->done = NULL;
-	rtsx->trans_state = STATE_TRANS_NONE;
-	dma_unmap_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
-
-	if (err < 0)
-		rtsx_stop_cmd(chip, card);
-
-	return err;
-}
-
-static int rtsx_transfer_buf(struct rtsx_chip *chip, u8 card, void *buf, size_t len,
-		enum dma_data_direction dma_dir, int timeout)
-{
-	struct rtsx_dev *rtsx = chip->rtsx;
-	struct completion trans_done;
-	dma_addr_t addr;
-	u8 dir;
-	int err = 0;
-	u32 val = (1 << 31);
-	long timeleft;
-
-	if ((buf == NULL) || (len <= 0))
-		return -EIO;
-
-	if (dma_dir == DMA_TO_DEVICE)
-		dir = HOST_TO_DEVICE;
-	else if (dma_dir == DMA_FROM_DEVICE)
-		dir = DEVICE_TO_HOST;
-	else
-		return -ENXIO;
-
-	addr = dma_map_single(&(rtsx->pci->dev), buf, len, dma_dir);
-	if (!addr)
-		return -ENOMEM;
-
-	if (card == SD_CARD)
-		rtsx->check_card_cd = SD_EXIST;
-	else if (card == MS_CARD)
-		rtsx->check_card_cd = MS_EXIST;
-	else if (card == XD_CARD)
-		rtsx->check_card_cd = XD_EXIST;
-	else
-		rtsx->check_card_cd = 0;
-
-	val |= (u32)(dir & 0x01) << 29;
-	val |= (u32)(len & 0x00FFFFFF);
-
-	spin_lock_irq(&rtsx->reg_lock);
-
-	/* set up data structures for the wakeup system */
-	rtsx->done = &trans_done;
-
-	init_completion(&trans_done);
-
-	rtsx->trans_state = STATE_TRANS_BUF;
-	rtsx->trans_result = TRANS_NOT_READY;
-
-	rtsx_writel(chip, RTSX_HDBAR, addr);
-	rtsx_writel(chip, RTSX_HDBCTLR, val);
-
-	spin_unlock_irq(&rtsx->reg_lock);
-
-	/* Wait for TRANS_OK_INT */
-	timeleft = wait_for_completion_interruptible_timeout(
-		&trans_done, timeout * HZ / 1000);
-	if (timeleft <= 0) {
-		RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
-		RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
-		err = -ETIMEDOUT;
-		goto out;
-	}
-
-	spin_lock_irq(&rtsx->reg_lock);
-	if (rtsx->trans_result == TRANS_RESULT_FAIL)
-		err = -EIO;
-	else if (rtsx->trans_result == TRANS_RESULT_OK)
-		err = 0;
-
-	spin_unlock_irq(&rtsx->reg_lock);
-
-out:
-	rtsx->done = NULL;
-	rtsx->trans_state = STATE_TRANS_NONE;
-	dma_unmap_single(&(rtsx->pci->dev), addr, len, dma_dir);
-
-	if (err < 0)
-		rtsx_stop_cmd(chip, card);
-
-	return err;
-}
-
-int rtsx_transfer_data_partial(struct rtsx_chip *chip, u8 card,
-		void *buf, size_t len, int use_sg, unsigned int *index,
-		unsigned int *offset, enum dma_data_direction dma_dir,
-		int timeout)
-{
-	int err = 0;
-
-	/* don't transfer data during abort processing */
-	if (rtsx_chk_stat(chip, RTSX_STAT_ABORT))
-		return -EIO;
-
-	if (use_sg) {
-		err = rtsx_transfer_sglist_adma_partial(chip, card,
-				(struct scatterlist *)buf, use_sg,
-				index, offset, (int)len, dma_dir, timeout);
-	} else {
-		err = rtsx_transfer_buf(chip, card,
-					buf, len, dma_dir, timeout);
-	}
-
-	if (err < 0) {
-		if (RTSX_TST_DELINK(chip)) {
-			RTSX_CLR_DELINK(chip);
-			chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
-			rtsx_reinit_cards(chip, 1);
-		}
-	}
-
-	return err;
-}
-
-int rtsx_transfer_data(struct rtsx_chip *chip, u8 card, void *buf, size_t len,
-		int use_sg, enum dma_data_direction dma_dir, int timeout)
-{
-	int err = 0;
-
-	RTSX_DEBUGP("use_sg = %d\n", use_sg);
-
-	/* don't transfer data during abort processing */
-	if (rtsx_chk_stat(chip, RTSX_STAT_ABORT))
-		return -EIO;
-
-	if (use_sg) {
-		err = rtsx_transfer_sglist_adma(chip, card,
-				(struct scatterlist *)buf,
-				use_sg, dma_dir, timeout);
-	} else {
-		err = rtsx_transfer_buf(chip, card, buf, len, dma_dir, timeout);
-	}
-
-	if (err < 0) {
-		if (RTSX_TST_DELINK(chip)) {
-			RTSX_CLR_DELINK(chip);
-			chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
-			rtsx_reinit_cards(chip, 1);
-		}
-	}
-
-	return err;
-}
-
diff --git a/drivers/staging/rts_pstor/rtsx_transport.h b/drivers/staging/rts_pstor/rtsx_transport.h
deleted file mode 100644
index 41f1ea0..0000000
--- a/drivers/staging/rts_pstor/rtsx_transport.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- * Header file
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#ifndef __REALTEK_RTSX_TRANSPORT_H
-#define __REALTEK_RTSX_TRANSPORT_H
-
-#include "rtsx.h"
-#include "rtsx_chip.h"
-
-#define WAIT_TIME	2000
-
-unsigned int rtsx_stor_access_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
-	unsigned int *offset, enum xfer_buf_dir dir);
-void rtsx_stor_set_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, struct scsi_cmnd *srb);
-void rtsx_stor_get_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, struct scsi_cmnd *srb);
-void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-
-
-#define rtsx_init_cmd(chip)			((chip)->ci = 0)
-
-void rtsx_add_cmd(struct rtsx_chip *chip,
-		u8 cmd_type, u16 reg_addr, u8 mask, u8 data);
-void rtsx_send_cmd_no_wait(struct rtsx_chip *chip);
-int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout);
-
-extern inline u8 *rtsx_get_cmd_data(struct rtsx_chip *chip)
-{
-#ifdef CMD_USING_SG
-	return (u8 *)(chip->host_sg_tbl_ptr);
-#else
-	return (u8 *)(chip->host_cmds_ptr);
-#endif
-}
-
-int rtsx_transfer_data(struct rtsx_chip *chip, u8 card, void *buf, size_t len,
-		int use_sg, enum dma_data_direction dma_dir, int timeout);
-
-int rtsx_transfer_data_partial(struct rtsx_chip *chip, u8 card, void *buf, size_t len,
-		int use_sg, unsigned int *index, unsigned int *offset,
-		enum dma_data_direction dma_dir, int timeout);
-
-#endif   /* __REALTEK_RTSX_TRANSPORT_H */
-
diff --git a/drivers/staging/rts_pstor/sd.c b/drivers/staging/rts_pstor/sd.c
deleted file mode 100644
index c6a581c..0000000
--- a/drivers/staging/rts_pstor/sd.c
+++ /dev/null
@@ -1,4570 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-
-#include "rtsx.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
-#include "sd.h"
-
-#define SD_MAX_RETRY_COUNT	3
-
-static u16 REG_SD_CFG1;
-static u16 REG_SD_CFG2;
-static u16 REG_SD_CFG3;
-static u16 REG_SD_STAT1;
-static u16 REG_SD_STAT2;
-static u16 REG_SD_BUS_STAT;
-static u16 REG_SD_PAD_CTL;
-static u16 REG_SD_SAMPLE_POINT_CTL;
-static u16 REG_SD_PUSH_POINT_CTL;
-static u16 REG_SD_CMD0;
-static u16 REG_SD_CMD1;
-static u16 REG_SD_CMD2;
-static u16 REG_SD_CMD3;
-static u16 REG_SD_CMD4;
-static u16 REG_SD_CMD5;
-static u16 REG_SD_BYTE_CNT_L;
-static u16 REG_SD_BYTE_CNT_H;
-static u16 REG_SD_BLOCK_CNT_L;
-static u16 REG_SD_BLOCK_CNT_H;
-static u16 REG_SD_TRANSFER;
-static u16 REG_SD_VPCLK0_CTL;
-static u16 REG_SD_VPCLK1_CTL;
-static u16 REG_SD_DCMPS0_CTL;
-static u16 REG_SD_DCMPS1_CTL;
-
-static inline void sd_set_err_code(struct rtsx_chip *chip, u8 err_code)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-
-	sd_card->err_code |= err_code;
-}
-
-static inline void sd_clr_err_code(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-
-	sd_card->err_code = 0;
-}
-
-static inline int sd_check_err_code(struct rtsx_chip *chip, u8 err_code)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-
-	return sd_card->err_code & err_code;
-}
-
-static void sd_init_reg_addr(struct rtsx_chip *chip)
-{
-	if (CHECK_PID(chip, 0x5209)) {
-		REG_SD_CFG1 = SD_CFG1;
-		REG_SD_CFG2 = SD_CFG2;
-		REG_SD_CFG3 = SD_CFG3;
-		REG_SD_STAT1 = SD_STAT1;
-		REG_SD_STAT2 = SD_STAT2;
-		REG_SD_BUS_STAT = SD_BUS_STAT;
-		REG_SD_PAD_CTL = SD_PAD_CTL;
-		REG_SD_SAMPLE_POINT_CTL = SD_SAMPLE_POINT_CTL;
-		REG_SD_PUSH_POINT_CTL = SD_PUSH_POINT_CTL;
-		REG_SD_CMD0 = SD_CMD0;
-		REG_SD_CMD1 = SD_CMD1;
-		REG_SD_CMD2 = SD_CMD2;
-		REG_SD_CMD3 = SD_CMD3;
-		REG_SD_CMD4 = SD_CMD4;
-		REG_SD_CMD5 = SD_CMD5;
-		REG_SD_BYTE_CNT_L = SD_BYTE_CNT_L;
-		REG_SD_BYTE_CNT_H = SD_BYTE_CNT_H;
-		REG_SD_BLOCK_CNT_L = SD_BLOCK_CNT_L;
-		REG_SD_BLOCK_CNT_H = SD_BLOCK_CNT_H;
-		REG_SD_TRANSFER = SD_TRANSFER;
-		REG_SD_VPCLK0_CTL = SD_VPCLK0_CTL;
-		REG_SD_VPCLK1_CTL = SD_VPCLK1_CTL;
-		REG_SD_DCMPS0_CTL = SD_DCMPS0_CTL;
-		REG_SD_DCMPS1_CTL = SD_DCMPS1_CTL;
-	} else {
-		REG_SD_CFG1 = 0xFD31;
-		REG_SD_CFG2 = 0xFD33;
-		REG_SD_CFG3 = 0xFD3E;
-		REG_SD_STAT1 = 0xFD30;
-		REG_SD_STAT2 = 0;
-		REG_SD_BUS_STAT = 0;
-		REG_SD_PAD_CTL = 0;
-		REG_SD_SAMPLE_POINT_CTL = 0;
-		REG_SD_PUSH_POINT_CTL = 0;
-		REG_SD_CMD0 = 0xFD34;
-		REG_SD_CMD1 = 0xFD35;
-		REG_SD_CMD2 = 0xFD36;
-		REG_SD_CMD3 = 0xFD37;
-		REG_SD_CMD4 = 0xFD38;
-		REG_SD_CMD5 = 0xFD5A;
-		REG_SD_BYTE_CNT_L = 0xFD39;
-		REG_SD_BYTE_CNT_H = 0xFD3A;
-		REG_SD_BLOCK_CNT_L = 0xFD3B;
-		REG_SD_BLOCK_CNT_H = 0xFD3C;
-		REG_SD_TRANSFER = 0xFD32;
-		REG_SD_VPCLK0_CTL = 0;
-		REG_SD_VPCLK1_CTL = 0;
-		REG_SD_DCMPS0_CTL = 0;
-		REG_SD_DCMPS1_CTL = 0;
-	}
-}
-
-static int sd_check_data0_status(struct rtsx_chip *chip)
-{
-	u8 stat;
-
-	if (CHECK_PID(chip, 0x5209))
-		RTSX_READ_REG(chip, REG_SD_BUS_STAT, &stat);
-	else
-		RTSX_READ_REG(chip, REG_SD_STAT1, &stat);
-
-	if (!(stat & SD_DAT0_STATUS)) {
-		sd_set_err_code(chip, SD_BUSY);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
-		u32 arg, u8 rsp_type, u8 *rsp, int rsp_len)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	int timeout = 100;
-	u16 reg_addr;
-	u8 *ptr;
-	int stat_idx = 0;
-	int rty_cnt = 0;
-
-	sd_clr_err_code(chip);
-
-	RTSX_DEBUGP("SD/MMC CMD %d, arg = 0x%08x\n", cmd_idx, arg);
-
-	if (rsp_type == SD_RSP_TYPE_R1b)
-		timeout = 3000;
-
-RTY_SEND_CMD:
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
-			0x01, PINGPONG_BUFFER);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
-			0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
-		     SD_TRANSFER_END | SD_STAT_IDLE, SD_TRANSFER_END | SD_STAT_IDLE);
-
-	if (rsp_type == SD_RSP_TYPE_R2) {
-		for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++)
-			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
-		stat_idx = 16;
-	} else if (rsp_type != SD_RSP_TYPE_R0) {
-		for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++)
-			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
-		stat_idx = 5;
-	}
-
-	rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0);
-
-	retval = rtsx_send_cmd(chip, SD_CARD, timeout);
-	if (retval < 0) {
-		u8 val;
-
-		rtsx_read_register(chip, REG_SD_STAT1, &val);
-		RTSX_DEBUGP("SD_STAT1: 0x%x\n", val);
-
-		if (CHECK_PID(chip, 0x5209)) {
-			rtsx_read_register(chip, REG_SD_STAT2, &val);
-			RTSX_DEBUGP("SD_STAT2: 0x%x\n", val);
-
-			if (val & SD_RSP_80CLK_TIMEOUT) {
-				rtsx_clear_sd_error(chip);
-				sd_set_err_code(chip, SD_RSP_TIMEOUT);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			rtsx_read_register(chip, REG_SD_BUS_STAT, &val);
-			RTSX_DEBUGP("SD_BUS_STAT: 0x%x\n", val);
-		} else {
-			rtsx_read_register(chip, REG_SD_CFG3, &val);
-			RTSX_DEBUGP("SD_CFG3: 0x%x\n", val);
-		}
-
-		if (retval == -ETIMEDOUT) {
-			if (rsp_type & SD_WAIT_BUSY_END) {
-				retval = sd_check_data0_status(chip);
-				if (retval != STATUS_SUCCESS) {
-					rtsx_clear_sd_error(chip);
-					TRACE_RET(chip, retval);
-				}
-			} else {
-				sd_set_err_code(chip, SD_TO_ERR);
-			}
-			retval = STATUS_TIMEDOUT;
-		} else {
-			retval = STATUS_FAIL;
-		}
-		rtsx_clear_sd_error(chip);
-
-		TRACE_RET(chip, retval);
-	}
-
-	if (rsp_type == SD_RSP_TYPE_R0)
-		return STATUS_SUCCESS;
-
-	ptr = rtsx_get_cmd_data(chip) + 1;
-
-	if ((ptr[0] & 0xC0) != 0) {
-		sd_set_err_code(chip, SD_STS_ERR);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (!(rsp_type & SD_NO_CHECK_CRC7)) {
-		if (ptr[stat_idx] & SD_CRC7_ERR) {
-			if (cmd_idx == WRITE_MULTIPLE_BLOCK) {
-				sd_set_err_code(chip, SD_CRC_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			if (rty_cnt < SD_MAX_RETRY_COUNT) {
-				wait_timeout(20);
-				rty_cnt++;
-				goto RTY_SEND_CMD;
-			} else {
-				sd_set_err_code(chip, SD_CRC_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-	}
-
-	if ((rsp_type == SD_RSP_TYPE_R1) || (rsp_type == SD_RSP_TYPE_R1b)) {
-		if ((cmd_idx != SEND_RELATIVE_ADDR) && (cmd_idx != SEND_IF_COND)) {
-			if (cmd_idx != STOP_TRANSMISSION) {
-				if (ptr[1] & 0x80)
-					TRACE_RET(chip, STATUS_FAIL);
-			}
-#ifdef SUPPORT_SD_LOCK
-			if (ptr[1] & 0x7D)
-#else
-			if (ptr[1] & 0x7F)
-#endif
-			{
-				RTSX_DEBUGP("ptr[1]: 0x%02x\n", ptr[1]);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			if (ptr[2] & 0xFF) {
-				RTSX_DEBUGP("ptr[2]: 0x%02x\n", ptr[2]);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			if (ptr[3] & 0x80) {
-				RTSX_DEBUGP("ptr[3]: 0x%02x\n", ptr[3]);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			if (ptr[3] & 0x01)
-				sd_card->sd_data_buf_ready = 1;
-			else
-				sd_card->sd_data_buf_ready = 0;
-		}
-	}
-
-	if (rsp && rsp_len)
-		memcpy(rsp, ptr, rsp_len);
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_read_data(struct rtsx_chip *chip,
-			u8 trans_mode, u8 *cmd, int cmd_len, u16 byte_cnt,
-			u16 blk_cnt, u8 bus_width, u8 *buf, int buf_len,
-			int timeout)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	int i;
-
-	sd_clr_err_code(chip);
-
-	if (!buf)
-		buf_len = 0;
-
-	if (buf_len > 512)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	rtsx_init_cmd(chip);
-
-	if (cmd_len) {
-		RTSX_DEBUGP("SD/MMC CMD %d\n", cmd[0] - 0x40);
-		for (i = 0; i < (cmd_len < 6 ? cmd_len : 6); i++)
-			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0 + i, 0xFF, cmd[i]);
-	}
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, (u8)(byte_cnt >> 8));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, (u8)blk_cnt);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, (u8)(blk_cnt >> 8));
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
-			SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
-			SD_CHECK_CRC7 | SD_RSP_LEN_6);
-	if (trans_mode != SD_TM_AUTO_TUNING)
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, trans_mode | SD_TRANSFER_START);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
-
-	retval = rtsx_send_cmd(chip, SD_CARD, timeout);
-	if (retval < 0) {
-		if (retval == -ETIMEDOUT) {
-			sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
-					    SD_RSP_TYPE_R1, NULL, 0);
-		}
-
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (buf && buf_len) {
-		retval = rtsx_read_ppbuf(chip, buf, buf_len);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_write_data(struct rtsx_chip *chip, u8 trans_mode,
-		u8 *cmd, int cmd_len, u16 byte_cnt, u16 blk_cnt, u8 bus_width,
-		u8 *buf, int buf_len, int timeout)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	int i;
-
-	sd_clr_err_code(chip);
-
-	if (!buf)
-		buf_len = 0;
-
-	if (buf_len > 512) {
-		/* This function can't write data more than one page */
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (buf && buf_len) {
-		retval = rtsx_write_ppbuf(chip, buf, buf_len);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	rtsx_init_cmd(chip);
-
-	if (cmd_len) {
-		RTSX_DEBUGP("SD/MMC CMD %d\n", cmd[0] - 0x40);
-		for (i = 0; i < (cmd_len < 6 ? cmd_len : 6); i++) {
-			rtsx_add_cmd(chip, WRITE_REG_CMD,
-				     REG_SD_CMD0 + i, 0xFF, cmd[i]);
-		}
-	}
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, (u8)(byte_cnt >> 8));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, (u8)blk_cnt);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, (u8)(blk_cnt >> 8));
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
-		SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
-		SD_CHECK_CRC7 | SD_RSP_LEN_6);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, trans_mode | SD_TRANSFER_START);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
-
-	retval = rtsx_send_cmd(chip, SD_CARD, timeout);
-	if (retval < 0) {
-		if (retval == -ETIMEDOUT) {
-			sd_send_cmd_get_rsp(chip, SEND_STATUS,
-				sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-		}
-
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_check_csd(struct rtsx_chip *chip, char check_wp)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	int i;
-	u8 csd_ver, trans_speed;
-	u8 rsp[16];
-
-	for (i = 0; i < 6; i++) {
-		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
-			sd_set_err_code(chip, SD_NO_CARD);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		retval = sd_send_cmd_get_rsp(chip, SEND_CSD, sd_card->sd_addr, SD_RSP_TYPE_R2, rsp, 16);
-		if (retval == STATUS_SUCCESS)
-			break;
-	}
-
-	if (i == 6)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	memcpy(sd_card->raw_csd, rsp + 1, 15);
-
-	if (CHECK_PID(chip, 0x5209))
-		RTSX_READ_REG(chip, REG_SD_CMD5, sd_card->raw_csd + 15);
-
-	RTSX_DEBUGP("CSD Response:\n");
-	RTSX_DUMP(sd_card->raw_csd, 16);
-
-	csd_ver = (rsp[1] & 0xc0) >> 6;
-	RTSX_DEBUGP("csd_ver = %d\n", csd_ver);
-
-	trans_speed = rsp[4];
-	if ((trans_speed & 0x07) == 0x02) {
-		if ((trans_speed & 0xf8) >= 0x30) {
-			if (chip->asic_code)
-				sd_card->sd_clock = 47;
-			else
-				sd_card->sd_clock = CLK_50;
-
-		} else if ((trans_speed & 0xf8) == 0x28) {
-			if (chip->asic_code)
-				sd_card->sd_clock = 39;
-			else
-				sd_card->sd_clock = CLK_40;
-
-		} else if ((trans_speed & 0xf8) == 0x20) {
-			if (chip->asic_code)
-				sd_card->sd_clock = 29;
-			else
-				sd_card->sd_clock = CLK_30;
-
-		} else if ((trans_speed & 0xf8) >= 0x10) {
-			if (chip->asic_code)
-				sd_card->sd_clock = 23;
-			else
-				sd_card->sd_clock = CLK_20;
-
-		} else if ((trans_speed & 0x08) >= 0x08) {
-			if (chip->asic_code)
-				sd_card->sd_clock = 19;
-			else
-				sd_card->sd_clock = CLK_20;
-		} else {
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	} else {
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (CHK_MMC_SECTOR_MODE(sd_card)) {
-		sd_card->capacity = 0;
-	} else {
-		if ((!CHK_SD_HCXC(sd_card)) || (csd_ver == 0)) {
-			u8 blk_size, c_size_mult;
-			u16 c_size;
-			blk_size = rsp[6] & 0x0F;
-			c_size =  ((u16)(rsp[7] & 0x03) << 10)
-					+ ((u16)rsp[8] << 2)
-					+ ((u16)(rsp[9] & 0xC0) >> 6);
-			c_size_mult = (u8)((rsp[10] & 0x03) << 1);
-			c_size_mult += (rsp[11] & 0x80) >> 7;
-			sd_card->capacity = (((u32)(c_size + 1)) * (1 << (c_size_mult + 2))) << (blk_size - 9);
-		} else {
-			u32 total_sector = 0;
-			total_sector = (((u32)rsp[8] & 0x3f) << 16) |
-				((u32)rsp[9] << 8) | (u32)rsp[10];
-			sd_card->capacity = (total_sector + 1) << 10;
-		}
-	}
-
-	if (check_wp) {
-		if (rsp[15] & 0x30)
-			chip->card_wp |= SD_CARD;
-
-		RTSX_DEBUGP("CSD WP Status: 0x%x\n", rsp[15]);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_set_sample_push_timing(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-
-	if (CHECK_PID(chip, 0x5209)) {
-		if (CHK_SD_SDR104(sd_card) || CHK_SD_SDR50(sd_card)) {
-			RTSX_WRITE_REG(chip, SD_CFG1, 0x0C | SD_ASYNC_FIFO_NOT_RST,
-					SD_30_MODE | SD_ASYNC_FIFO_NOT_RST);
-			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ);
-			RTSX_WRITE_REG(chip, CARD_CLK_SOURCE, 0xFF,
-					CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1);
-			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0);
-		} else if (CHK_SD_DDR50(sd_card) || CHK_MMC_DDR52(sd_card)) {
-			RTSX_WRITE_REG(chip, SD_CFG1, 0x0C | SD_ASYNC_FIFO_NOT_RST,
-					SD_DDR_MODE | SD_ASYNC_FIFO_NOT_RST);
-			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ);
-			RTSX_WRITE_REG(chip, CARD_CLK_SOURCE, 0xFF,
-					CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1);
-			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0);
-			RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, DDR_VAR_TX_CMD_DAT,
-					DDR_VAR_TX_CMD_DAT);
-			RTSX_WRITE_REG(chip, SD_SAMPLE_POINT_CTL, DDR_VAR_RX_DAT | DDR_VAR_RX_CMD,
-					DDR_VAR_RX_DAT | DDR_VAR_RX_CMD);
-		} else {
-			u8 val = 0;
-
-			RTSX_WRITE_REG(chip, SD_CFG1, 0x0C, SD_20_MODE);
-			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ);
-			RTSX_WRITE_REG(chip, CARD_CLK_SOURCE, 0xFF,
-					CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1);
-			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0);
-
-			if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_AUTO)
-				val = SD20_TX_NEG_EDGE;
-			else if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY)
-				val = SD20_TX_14_AHEAD;
-			else
-				val = SD20_TX_NEG_EDGE;
-
-			RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, SD20_TX_SEL_MASK, val);
-
-			if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_AUTO) {
-				if (chip->asic_code) {
-					if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card))
-						val = SD20_RX_14_DELAY;
-					else
-						val = SD20_RX_POS_EDGE;
-				} else {
-					val = SD20_RX_14_DELAY;
-				}
-			} else if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_DELAY) {
-				val = SD20_RX_14_DELAY;
-			} else {
-				val = SD20_RX_POS_EDGE;
-			}
-			RTSX_WRITE_REG(chip, SD_SAMPLE_POINT_CTL, SD20_RX_SEL_MASK, val);
-		}
-	} else {
-		u8 val = 0;
-
-		if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY)
-			val |= 0x10;
-
-		if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_AUTO) {
-			if (chip->asic_code) {
-				if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card)) {
-					if (val & 0x10)
-						val |= 0x04;
-					else
-						val |= 0x08;
-				}
-			} else {
-				if (val & 0x10)
-					val |= 0x04;
-				else
-					val |= 0x08;
-			}
-		} else if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_DELAY) {
-			if (val & 0x10)
-				val |= 0x04;
-			else
-				val |= 0x08;
-		}
-
-		RTSX_WRITE_REG(chip, REG_SD_CFG1, 0x1C, val);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static void sd_choose_proper_clock(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-
-	if (CHK_SD_SDR104(sd_card)) {
-		if (chip->asic_code)
-			sd_card->sd_clock = chip->asic_sd_sdr104_clk;
-		else
-			sd_card->sd_clock = chip->fpga_sd_sdr104_clk;
-
-	} else if (CHK_SD_DDR50(sd_card)) {
-		if (chip->asic_code)
-			sd_card->sd_clock = chip->asic_sd_ddr50_clk;
-		else
-			sd_card->sd_clock = chip->fpga_sd_ddr50_clk;
-
-	} else if (CHK_SD_SDR50(sd_card)) {
-		if (chip->asic_code)
-			sd_card->sd_clock = chip->asic_sd_sdr50_clk;
-		else
-			sd_card->sd_clock = chip->fpga_sd_sdr50_clk;
-
-	} else if (CHK_SD_HS(sd_card)) {
-		if (chip->asic_code)
-			sd_card->sd_clock = chip->asic_sd_hs_clk;
-		else
-			sd_card->sd_clock = chip->fpga_sd_hs_clk;
-
-	} else if (CHK_MMC_52M(sd_card) || CHK_MMC_DDR52(sd_card)) {
-		if (chip->asic_code)
-			sd_card->sd_clock = chip->asic_mmc_52m_clk;
-		else
-			sd_card->sd_clock = chip->fpga_mmc_52m_clk;
-
-	} else if (CHK_MMC_26M(sd_card)) {
-		if (chip->asic_code)
-			sd_card->sd_clock = 48;
-		else
-			sd_card->sd_clock = CLK_50;
-	}
-}
-
-static int sd_set_clock_divider(struct rtsx_chip *chip, u8 clk_div)
-{
-	u8 mask = 0, val = 0;
-
-	if (CHECK_PID(chip, 0x5209)) {
-		mask = SD_CLK_DIVIDE_MASK;
-		val = clk_div;
-	} else {
-		mask = 0x60;
-		if (clk_div == SD_CLK_DIVIDE_0)
-			val = 0x00;
-		else if (clk_div == SD_CLK_DIVIDE_128)
-			val = 0x40;
-		else if (clk_div == SD_CLK_DIVIDE_256)
-			val = 0x20;
-	}
-
-	RTSX_WRITE_REG(chip, REG_SD_CFG1, mask, val);
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_set_init_para(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-
-	retval = sd_set_sample_push_timing(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	sd_choose_proper_clock(chip);
-
-	retval = switch_clock(chip, sd_card->sd_clock);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-int sd_select_card(struct rtsx_chip *chip, int select)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	u8 cmd_idx, cmd_type;
-	u32 addr;
-
-	if (select) {
-		cmd_idx = SELECT_CARD;
-		cmd_type = SD_RSP_TYPE_R1;
-		addr = sd_card->sd_addr;
-	} else {
-		cmd_idx = DESELECT_CARD;
-		cmd_type = SD_RSP_TYPE_R0;
-		addr = 0;
-	}
-
-	retval = sd_send_cmd_get_rsp(chip, cmd_idx, addr, cmd_type, NULL, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-#ifdef SUPPORT_SD_LOCK
-static int sd_update_lock_status(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	u8 rsp[5];
-
-	retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, rsp, 5);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (rsp[1] & 0x02)
-		sd_card->sd_lock_status |= SD_LOCKED;
-	else
-		sd_card->sd_lock_status &= ~SD_LOCKED;
-
-	RTSX_DEBUGP("sd_card->sd_lock_status = 0x%x\n", sd_card->sd_lock_status);
-
-	if (rsp[1] & 0x01)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-#endif
-
-static int sd_wait_state_data_ready(struct rtsx_chip *chip, u8 state, u8 data_ready, int polling_cnt)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval, i;
-	u8 rsp[5];
-
-	for (i = 0; i < polling_cnt; i++) {
-		retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
-					     sd_card->sd_addr, SD_RSP_TYPE_R1, rsp, 5);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		if (((rsp[3] & 0x1E) == state) && ((rsp[3] & 0x01) == data_ready))
-			return STATUS_SUCCESS;
-	}
-
-	TRACE_RET(chip, STATUS_FAIL);
-}
-
-static int sd_change_bank_voltage(struct rtsx_chip *chip, u8 voltage)
-{
-	int retval;
-
-	if (voltage == SD_IO_3V3) {
-		if (chip->asic_code) {
-			retval = rtsx_write_phy_register(chip, 0x08, 0x4FC0 | chip->phy_voltage);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-		} else {
-			RTSX_WRITE_REG(chip, SD_PAD_CTL, SD_IO_USING_1V8, 0);
-		}
-	} else if (voltage == SD_IO_1V8) {
-		if (chip->asic_code) {
-			retval = rtsx_write_phy_register(chip, 0x08, 0x4C40 | chip->phy_voltage);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-		} else {
-			RTSX_WRITE_REG(chip, SD_PAD_CTL, SD_IO_USING_1V8, SD_IO_USING_1V8);
-		}
-	} else {
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_voltage_switch(struct rtsx_chip *chip)
-{
-	int retval;
-	u8 stat;
-
-	RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, SD_CLK_TOGGLE_EN);
-
-	retval = sd_send_cmd_get_rsp(chip, VOLTAGE_SWITCH, 0, SD_RSP_TYPE_R1, NULL, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	udelay(chip->sd_voltage_switch_delay);
-
-	RTSX_READ_REG(chip, SD_BUS_STAT, &stat);
-	if (stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
-				SD_DAT1_STATUS | SD_DAT0_STATUS)) {
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	RTSX_WRITE_REG(chip, SD_BUS_STAT, 0xFF, SD_CLK_FORCE_STOP);
-	retval = sd_change_bank_voltage(chip, SD_IO_1V8);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	wait_timeout(50);
-
-	RTSX_WRITE_REG(chip, SD_BUS_STAT, 0xFF, SD_CLK_TOGGLE_EN);
-	wait_timeout(10);
-
-	RTSX_READ_REG(chip, SD_BUS_STAT, &stat);
-	if ((stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
-				SD_DAT1_STATUS | SD_DAT0_STATUS)) !=
-			(SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
-				SD_DAT1_STATUS | SD_DAT0_STATUS)) {
-		RTSX_DEBUGP("SD_BUS_STAT: 0x%x\n", stat);
-		rtsx_write_register(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
-		rtsx_write_register(chip, CARD_CLK_EN, 0xFF, 0);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_reset_dcm(struct rtsx_chip *chip, u8 tune_dir)
-{
-	if (tune_dir == TUNE_RX) {
-		RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RESET | DCM_RX);
-		RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RX);
-	} else {
-		RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RESET | DCM_TX);
-		RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_TX);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	u16 SD_VP_CTL, SD_DCMPS_CTL;
-	u8 val;
-	int retval;
-	int ddr_rx = 0;
-
-	RTSX_DEBUGP("sd_change_phase (sample_point = %d, tune_dir = %d)\n",
-				sample_point, tune_dir);
-
-	if (tune_dir == TUNE_RX) {
-		SD_VP_CTL = SD_VPRX_CTL;
-		SD_DCMPS_CTL = SD_DCMPS_RX_CTL;
-		if (CHK_SD_DDR50(sd_card))
-			ddr_rx = 1;
-	} else {
-		SD_VP_CTL = SD_VPTX_CTL;
-		SD_DCMPS_CTL = SD_DCMPS_TX_CTL;
-	}
-
-	if (chip->asic_code) {
-		RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, CHANGE_CLK);
-		RTSX_WRITE_REG(chip, SD_VP_CTL, 0x1F, sample_point);
-		RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
-		RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET);
-		RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, 0);
-	} else {
-#ifdef CONFIG_RTS_PSTOR_DEBUG
-		rtsx_read_register(chip, SD_VP_CTL, &val);
-		RTSX_DEBUGP("SD_VP_CTL: 0x%x\n", val);
-		rtsx_read_register(chip, SD_DCMPS_CTL, &val);
-		RTSX_DEBUGP("SD_DCMPS_CTL: 0x%x\n", val);
-#endif
-
-		if (ddr_rx) {
-			RTSX_WRITE_REG(chip, SD_VP_CTL, PHASE_CHANGE, PHASE_CHANGE);
-			udelay(50);
-			RTSX_WRITE_REG(chip, SD_VP_CTL, 0xFF,
-					PHASE_CHANGE | PHASE_NOT_RESET | sample_point);
-		} else {
-			RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, CHANGE_CLK);
-			udelay(50);
-			RTSX_WRITE_REG(chip, SD_VP_CTL, 0xFF,
-					PHASE_NOT_RESET | sample_point);
-		}
-		udelay(100);
-
-		rtsx_init_cmd(chip);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE, DCMPS_CHANGE);
-		rtsx_add_cmd(chip, CHECK_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE_DONE, DCMPS_CHANGE_DONE);
-		retval = rtsx_send_cmd(chip, SD_CARD, 100);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, Fail);
-
-		val = *rtsx_get_cmd_data(chip);
-		if (val & DCMPS_ERROR)
-			TRACE_GOTO(chip, Fail);
-
-		if ((val & DCMPS_CURRENT_PHASE) != sample_point)
-			TRACE_GOTO(chip, Fail);
-
-		RTSX_WRITE_REG(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0);
-		if (ddr_rx)
-			RTSX_WRITE_REG(chip, SD_VP_CTL, PHASE_CHANGE, 0);
-		else
-			RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, 0);
-
-		udelay(50);
-	}
-
-	RTSX_WRITE_REG(chip, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0);
-
-	return STATUS_SUCCESS;
-
-Fail:
-#ifdef CONFIG_RTS_PSTOR_DEBUG
-	rtsx_read_register(chip, SD_VP_CTL, &val);
-	RTSX_DEBUGP("SD_VP_CTL: 0x%x\n", val);
-	rtsx_read_register(chip, SD_DCMPS_CTL, &val);
-	RTSX_DEBUGP("SD_DCMPS_CTL: 0x%x\n", val);
-#endif
-
-	rtsx_write_register(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0);
-	rtsx_write_register(chip, SD_VP_CTL, PHASE_CHANGE, 0);
-	wait_timeout(10);
-	sd_reset_dcm(chip, tune_dir);
-	return STATUS_FAIL;
-}
-
-static int sd_check_spec(struct rtsx_chip *chip, u8 bus_width)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	u8 cmd[5], buf[8];
-
-	retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	cmd[0] = 0x40 | SEND_SCR;
-	cmd[1] = 0;
-	cmd[2] = 0;
-	cmd[3] = 0;
-	cmd[4] = 0;
-
-	retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 8, 1, bus_width, buf, 8, 250);
-	if (retval != STATUS_SUCCESS) {
-		rtsx_clear_sd_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	memcpy(sd_card->raw_scr, buf, 8);
-
-	if ((buf[0] & 0x0F) == 0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group, u8 func_to_switch,
-		u8 *buf, int buf_len)
-{
-	u8 support_mask = 0, query_switch = 0, switch_busy = 0;
-	int support_offset = 0, query_switch_offset = 0, check_busy_offset = 0;
-
-	if (func_group == SD_FUNC_GROUP_1) {
-		support_offset = FUNCTION_GROUP1_SUPPORT_OFFSET;
-		query_switch_offset = FUNCTION_GROUP1_QUERY_SWITCH_OFFSET;
-		check_busy_offset = FUNCTION_GROUP1_CHECK_BUSY_OFFSET;
-
-		switch (func_to_switch) {
-		case HS_SUPPORT:
-			support_mask = HS_SUPPORT_MASK;
-			query_switch = HS_QUERY_SWITCH_OK;
-			switch_busy = HS_SWITCH_BUSY;
-			break;
-
-		case SDR50_SUPPORT:
-			support_mask = SDR50_SUPPORT_MASK;
-			query_switch = SDR50_QUERY_SWITCH_OK;
-			switch_busy = SDR50_SWITCH_BUSY;
-			break;
-
-		case SDR104_SUPPORT:
-			support_mask = SDR104_SUPPORT_MASK;
-			query_switch = SDR104_QUERY_SWITCH_OK;
-			switch_busy = SDR104_SWITCH_BUSY;
-			break;
-
-		case DDR50_SUPPORT:
-			support_mask = DDR50_SUPPORT_MASK;
-			query_switch = DDR50_QUERY_SWITCH_OK;
-			switch_busy = DDR50_SWITCH_BUSY;
-			break;
-
-		default:
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	} else if (func_group == SD_FUNC_GROUP_3) {
-		support_offset = FUNCTION_GROUP3_SUPPORT_OFFSET;
-		query_switch_offset = FUNCTION_GROUP3_QUERY_SWITCH_OFFSET;
-		check_busy_offset = FUNCTION_GROUP3_CHECK_BUSY_OFFSET;
-
-		switch (func_to_switch) {
-		case DRIVING_TYPE_A:
-			support_mask = DRIVING_TYPE_A_MASK;
-			query_switch = TYPE_A_QUERY_SWITCH_OK;
-			switch_busy = TYPE_A_SWITCH_BUSY;
-			break;
-
-		case DRIVING_TYPE_C:
-			support_mask = DRIVING_TYPE_C_MASK;
-			query_switch = TYPE_C_QUERY_SWITCH_OK;
-			switch_busy = TYPE_C_SWITCH_BUSY;
-			break;
-
-		case DRIVING_TYPE_D:
-			support_mask = DRIVING_TYPE_D_MASK;
-			query_switch = TYPE_D_QUERY_SWITCH_OK;
-			switch_busy = TYPE_D_SWITCH_BUSY;
-			break;
-
-		default:
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	} else if (func_group == SD_FUNC_GROUP_4) {
-		support_offset = FUNCTION_GROUP4_SUPPORT_OFFSET;
-		query_switch_offset = FUNCTION_GROUP4_QUERY_SWITCH_OFFSET;
-		check_busy_offset = FUNCTION_GROUP4_CHECK_BUSY_OFFSET;
-
-		switch (func_to_switch) {
-		case CURRENT_LIMIT_400:
-			support_mask = CURRENT_LIMIT_400_MASK;
-			query_switch = CURRENT_LIMIT_400_QUERY_SWITCH_OK;
-			switch_busy = CURRENT_LIMIT_400_SWITCH_BUSY;
-			break;
-
-		case CURRENT_LIMIT_600:
-			support_mask = CURRENT_LIMIT_600_MASK;
-			query_switch = CURRENT_LIMIT_600_QUERY_SWITCH_OK;
-			switch_busy = CURRENT_LIMIT_600_SWITCH_BUSY;
-			break;
-
-		case CURRENT_LIMIT_800:
-			support_mask = CURRENT_LIMIT_800_MASK;
-			query_switch = CURRENT_LIMIT_800_QUERY_SWITCH_OK;
-			switch_busy = CURRENT_LIMIT_800_SWITCH_BUSY;
-			break;
-
-		default:
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	} else {
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (func_group == SD_FUNC_GROUP_1) {
-		if (!(buf[support_offset] & support_mask) ||
-				((buf[query_switch_offset] & 0x0F) != query_switch)) {
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	/* Check 'Busy Status' */
-	if ((buf[DATA_STRUCTURE_VER_OFFSET] == 0x01) &&
-		    ((buf[check_busy_offset] & switch_busy) == switch_busy)) {
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode,
-		u8 func_group, u8 func_to_switch, u8 bus_width)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	u8 cmd[5], buf[64];
-
-	RTSX_DEBUGP("sd_check_switch_mode (mode = %d, func_group = %d, func_to_switch = %d)\n",
-			mode, func_group, func_to_switch);
-
-	cmd[0] = 0x40 | SWITCH;
-	cmd[1] = mode;
-
-	if (func_group == SD_FUNC_GROUP_1) {
-		cmd[2] = 0xFF;
-		cmd[3] = 0xFF;
-		cmd[4] = 0xF0 + func_to_switch;
-	} else if (func_group == SD_FUNC_GROUP_3) {
-		cmd[2] = 0xFF;
-		cmd[3] = 0xF0 + func_to_switch;
-		cmd[4] = 0xFF;
-	} else if (func_group == SD_FUNC_GROUP_4) {
-		cmd[2] = 0xFF;
-		cmd[3] = 0x0F + (func_to_switch << 4);
-		cmd[4] = 0xFF;
-	} else {
-		cmd[1] = SD_CHECK_MODE;
-		cmd[2] = 0xFF;
-		cmd[3] = 0xFF;
-		cmd[4] = 0xFF;
-	}
-
-	retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, bus_width, buf, 64, 250);
-	if (retval != STATUS_SUCCESS) {
-		rtsx_clear_sd_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	RTSX_DUMP(buf, 64);
-
-	if (func_group == NO_ARGUMENT) {
-		sd_card->func_group1_mask = buf[0x0D];
-		sd_card->func_group2_mask = buf[0x0B];
-		sd_card->func_group3_mask = buf[0x09];
-		sd_card->func_group4_mask = buf[0x07];
-
-		RTSX_DEBUGP("func_group1_mask = 0x%02x\n", buf[0x0D]);
-		RTSX_DEBUGP("func_group2_mask = 0x%02x\n", buf[0x0B]);
-		RTSX_DEBUGP("func_group3_mask = 0x%02x\n", buf[0x09]);
-		RTSX_DEBUGP("func_group4_mask = 0x%02x\n", buf[0x07]);
-	} else {
-		/* Maximum current consumption, check whether current is acceptable;
-		 * bit[511:496] = 0x0000 means some error happened.
-		 */
-		u16 cc = ((u16)buf[0] << 8) | buf[1];
-		RTSX_DEBUGP("Maximum current consumption: %dmA\n", cc);
-		if ((cc == 0) || (cc > 800))
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = sd_query_switch_result(chip, func_group, func_to_switch, buf, 64);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		if ((cc > 400) || (func_to_switch > CURRENT_LIMIT_400)) {
-			RTSX_WRITE_REG(chip, OCPPARA2, SD_OCP_THD_MASK, chip->sd_800mA_ocp_thd);
-			RTSX_WRITE_REG(chip, CARD_PWR_CTL, PMOS_STRG_MASK, PMOS_STRG_800mA);
-		}
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static u8 downgrade_switch_mode(u8 func_group, u8 func_to_switch)
-{
-	if (func_group == SD_FUNC_GROUP_1) {
-		if (func_to_switch > HS_SUPPORT)
-			func_to_switch--;
-
-	} else if (func_group == SD_FUNC_GROUP_4) {
-		if (func_to_switch > CURRENT_LIMIT_200)
-			func_to_switch--;
-	}
-
-	return func_to_switch;
-}
-
-static int sd_check_switch(struct rtsx_chip *chip,
-		u8 func_group, u8 func_to_switch, u8 bus_width)
-{
-	int retval;
-	int i;
-	int switch_good = 0;
-
-	for (i = 0; i < 3; i++) {
-		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
-			sd_set_err_code(chip, SD_NO_CARD);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		retval = sd_check_switch_mode(chip, SD_CHECK_MODE, func_group,
-				func_to_switch, bus_width);
-		if (retval == STATUS_SUCCESS) {
-			u8 stat;
-
-			retval = sd_check_switch_mode(chip, SD_SWITCH_MODE,
-					func_group, func_to_switch, bus_width);
-			if (retval == STATUS_SUCCESS) {
-				switch_good = 1;
-				break;
-			}
-
-			RTSX_READ_REG(chip, SD_STAT1, &stat);
-			if (stat & SD_CRC16_ERR) {
-				RTSX_DEBUGP("SD CRC16 error when switching mode\n");
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-
-		func_to_switch = downgrade_switch_mode(func_group, func_to_switch);
-
-		wait_timeout(20);
-	}
-
-	if (!switch_good)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	int i;
-	u8 func_to_switch = 0;
-
-	/* Get supported functions */
-	retval = sd_check_switch_mode(chip, SD_CHECK_MODE,
-			NO_ARGUMENT, NO_ARGUMENT, bus_width);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	sd_card->func_group1_mask &= ~(sd_card->sd_switch_fail);
-
-	/* Function Group 1: Access Mode */
-	for (i = 0; i < 4; i++) {
-		switch ((u8)(chip->sd_speed_prior >> (i*8))) {
-		case SDR104_SUPPORT:
-			if ((sd_card->func_group1_mask & SDR104_SUPPORT_MASK)
-					&& chip->sdr104_en) {
-				func_to_switch = SDR104_SUPPORT;
-			}
-			break;
-
-		case DDR50_SUPPORT:
-			if ((sd_card->func_group1_mask & DDR50_SUPPORT_MASK)
-					&& chip->ddr50_en) {
-				func_to_switch = DDR50_SUPPORT;
-			}
-			break;
-
-		case SDR50_SUPPORT:
-			if ((sd_card->func_group1_mask & SDR50_SUPPORT_MASK)
-					&& chip->sdr50_en) {
-				func_to_switch = SDR50_SUPPORT;
-			}
-			break;
-
-		case HS_SUPPORT:
-			if (sd_card->func_group1_mask & HS_SUPPORT_MASK)
-				func_to_switch = HS_SUPPORT;
-
-			break;
-
-		default:
-			continue;
-		}
-
-
-		if (func_to_switch)
-			break;
-
-	}
-	RTSX_DEBUGP("SD_FUNC_GROUP_1: func_to_switch = 0x%02x", func_to_switch);
-
-#ifdef SUPPORT_SD_LOCK
-	if ((sd_card->sd_lock_status & SD_SDR_RST)
-			&& (DDR50_SUPPORT == func_to_switch)
-			&& (sd_card->func_group1_mask & SDR50_SUPPORT_MASK)) {
-		func_to_switch = SDR50_SUPPORT;
-		RTSX_DEBUGP("Using SDR50 instead of DDR50 for SD Lock\n");
-	}
-#endif
-
-	if (func_to_switch) {
-		retval = sd_check_switch(chip, SD_FUNC_GROUP_1, func_to_switch, bus_width);
-		if (retval != STATUS_SUCCESS) {
-			if (func_to_switch == SDR104_SUPPORT) {
-				sd_card->sd_switch_fail = SDR104_SUPPORT_MASK;
-			} else if (func_to_switch == DDR50_SUPPORT) {
-				sd_card->sd_switch_fail =
-					SDR104_SUPPORT_MASK | DDR50_SUPPORT_MASK;
-			} else if (func_to_switch == SDR50_SUPPORT) {
-				sd_card->sd_switch_fail =
-					SDR104_SUPPORT_MASK | DDR50_SUPPORT_MASK |
-					SDR50_SUPPORT_MASK;
-			}
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		if (func_to_switch == SDR104_SUPPORT)
-			SET_SD_SDR104(sd_card);
-		else if (func_to_switch == DDR50_SUPPORT)
-			SET_SD_DDR50(sd_card);
-		else if (func_to_switch == SDR50_SUPPORT)
-			SET_SD_SDR50(sd_card);
-		else
-			SET_SD_HS(sd_card);
-	}
-
-	if (CHK_SD_DDR50(sd_card)) {
-		RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0x06, 0x04);
-		retval = sd_set_sample_push_timing(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (!func_to_switch || (func_to_switch == HS_SUPPORT)) {
-		/* Do not try to switch current limit if the card doesn't
-		 * support UHS mode or we don't want it to support UHS mode
-		 */
-		return STATUS_SUCCESS;
-	}
-
-	/* Function Group 4: Current Limit */
-	func_to_switch = 0xFF;
-
-	for (i = 0; i < 4; i++) {
-		switch ((u8)(chip->sd_current_prior >> (i*8))) {
-		case CURRENT_LIMIT_800:
-			if (sd_card->func_group4_mask & CURRENT_LIMIT_800_MASK)
-				func_to_switch = CURRENT_LIMIT_800;
-
-			break;
-
-		case CURRENT_LIMIT_600:
-			if (sd_card->func_group4_mask & CURRENT_LIMIT_600_MASK)
-				func_to_switch = CURRENT_LIMIT_600;
-
-			break;
-
-		case CURRENT_LIMIT_400:
-			if (sd_card->func_group4_mask & CURRENT_LIMIT_400_MASK)
-				func_to_switch = CURRENT_LIMIT_400;
-
-			break;
-
-		case CURRENT_LIMIT_200:
-			if (sd_card->func_group4_mask & CURRENT_LIMIT_200_MASK)
-				func_to_switch = CURRENT_LIMIT_200;
-
-			break;
-
-		default:
-			continue;
-		}
-
-		if (func_to_switch != 0xFF)
-			break;
-	}
-
-	RTSX_DEBUGP("SD_FUNC_GROUP_4: func_to_switch = 0x%02x", func_to_switch);
-
-	if (func_to_switch <= CURRENT_LIMIT_800) {
-		retval = sd_check_switch(chip, SD_FUNC_GROUP_4, func_to_switch, bus_width);
-		if (retval != STATUS_SUCCESS) {
-			if (sd_check_err_code(chip, SD_NO_CARD))
-				TRACE_RET(chip, STATUS_FAIL);
-		}
-		RTSX_DEBUGP("Switch current limit finished! (%d)\n", retval);
-	}
-
-	if (CHK_SD_DDR50(sd_card))
-		RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0x06, 0);
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_wait_data_idle(struct rtsx_chip *chip)
-{
-	int retval = STATUS_TIMEDOUT;
-	int i;
-	u8 val = 0;
-
-	for (i = 0; i < 100; i++) {
-		RTSX_READ_REG(chip, SD_DATA_STATE, &val);
-		if (val & SD_DATA_IDLE) {
-			retval = STATUS_SUCCESS;
-			break;
-		}
-		udelay(100);
-	}
-	RTSX_DEBUGP("SD_DATA_STATE: 0x%02x\n", val);
-
-	return retval;
-}
-
-static int sd_sdr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
-{
-	int retval;
-	u8 cmd[5];
-
-	retval = sd_change_phase(chip, sample_point, TUNE_RX);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	cmd[0] = 0x40 | SEND_TUNING_PATTERN;
-	cmd[1] = 0;
-	cmd[2] = 0;
-	cmd[3] = 0;
-	cmd[4] = 0;
-
-	retval = sd_read_data(chip, SD_TM_AUTO_TUNING,
-			cmd, 5, 0x40, 1, SD_BUS_WIDTH_4, NULL, 0, 100);
-	if (retval != STATUS_SUCCESS) {
-		(void)sd_wait_data_idle(chip);
-
-		rtsx_clear_sd_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	u8 cmd[5];
-
-	retval = sd_change_phase(chip, sample_point, TUNE_RX);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_DEBUGP("sd ddr tuning rx\n");
-
-	retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	cmd[0] = 0x40 | SD_STATUS;
-	cmd[1] = 0;
-	cmd[2] = 0;
-	cmd[3] = 0;
-	cmd[4] = 0;
-
-	retval = sd_read_data(chip, SD_TM_NORMAL_READ,
-			cmd, 5, 64, 1, SD_BUS_WIDTH_4, NULL, 0, 100);
-	if (retval != STATUS_SUCCESS) {
-		(void)sd_wait_data_idle(chip);
-
-		rtsx_clear_sd_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int mmc_ddr_tunning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	u8 cmd[5], bus_width;
-
-	if (CHK_MMC_8BIT(sd_card))
-		bus_width = SD_BUS_WIDTH_8;
-	else if (CHK_MMC_4BIT(sd_card))
-		bus_width = SD_BUS_WIDTH_4;
-	else
-		bus_width = SD_BUS_WIDTH_1;
-
-	retval = sd_change_phase(chip, sample_point, TUNE_RX);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_DEBUGP("mmc ddr tuning rx\n");
-
-	cmd[0] = 0x40 | SEND_EXT_CSD;
-	cmd[1] = 0;
-	cmd[2] = 0;
-	cmd[3] = 0;
-	cmd[4] = 0;
-
-	retval = sd_read_data(chip, SD_TM_NORMAL_READ,
-			cmd, 5, 0x200, 1, bus_width, NULL, 0, 100);
-	if (retval != STATUS_SUCCESS) {
-		(void)sd_wait_data_idle(chip);
-
-		rtsx_clear_sd_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_sdr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-
-	retval = sd_change_phase(chip, sample_point, TUNE_TX);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, SD_RSP_80CLK_TIMEOUT_EN);
-
-	retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
-		SD_RSP_TYPE_R1, NULL, 0);
-	if (retval != STATUS_SUCCESS) {
-		if (sd_check_err_code(chip, SD_RSP_TIMEOUT)) {
-			rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	u8 cmd[5], bus_width;
-
-	retval = sd_change_phase(chip, sample_point, TUNE_TX);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (CHK_SD(sd_card)) {
-		bus_width = SD_BUS_WIDTH_4;
-	} else {
-		if (CHK_MMC_8BIT(sd_card))
-			bus_width = SD_BUS_WIDTH_8;
-		else if (CHK_MMC_4BIT(sd_card))
-			bus_width = SD_BUS_WIDTH_4;
-		else
-			bus_width = SD_BUS_WIDTH_1;
-	}
-
-	retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, SD_RSP_80CLK_TIMEOUT_EN);
-
-	cmd[0] = 0x40 | PROGRAM_CSD;
-	cmd[1] = 0;
-	cmd[2] = 0;
-	cmd[3] = 0;
-	cmd[4] = 0;
-
-	retval = sd_write_data(chip, SD_TM_AUTO_WRITE_2,
-			cmd, 5, 16, 1, bus_width, sd_card->raw_csd, 16, 100);
-	if (retval != STATUS_SUCCESS) {
-		rtsx_clear_sd_error(chip);
-		rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
-
-	sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-
-	return STATUS_SUCCESS;
-}
-
-static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map, u8 tune_dir)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	struct timing_phase_path path[MAX_PHASE + 1];
-	int i, j, cont_path_cnt;
-	int new_block, max_len, final_path_idx;
-	u8 final_phase = 0xFF;
-
-	if (phase_map == 0xFFFFFFFF) {
-		if (tune_dir == TUNE_RX)
-			final_phase = (u8)chip->sd_default_rx_phase;
-		else
-			final_phase = (u8)chip->sd_default_tx_phase;
-
-		goto Search_Finish;
-	}
-
-	cont_path_cnt = 0;
-	new_block = 1;
-	j = 0;
-	for (i = 0; i < MAX_PHASE + 1; i++) {
-		if (phase_map & (1 << i)) {
-			if (new_block) {
-				new_block = 0;
-				j = cont_path_cnt++;
-				path[j].start = i;
-				path[j].end = i;
-			} else {
-				path[j].end = i;
-			}
-		} else {
-			new_block = 1;
-			if (cont_path_cnt) {
-				int idx = cont_path_cnt - 1;
-				path[idx].len = path[idx].end - path[idx].start + 1;
-				path[idx].mid = path[idx].start + path[idx].len / 2;
-			}
-		}
-	}
-
-	if (cont_path_cnt == 0) {
-		RTSX_DEBUGP("No continuous phase path\n");
-		goto Search_Finish;
-	} else {
-		int idx = cont_path_cnt - 1;
-		path[idx].len = path[idx].end - path[idx].start + 1;
-		path[idx].mid = path[idx].start + path[idx].len / 2;
-	}
-
-	if ((path[0].start == 0) && (path[cont_path_cnt - 1].end == MAX_PHASE)) {
-		path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1;
-		path[0].len += path[cont_path_cnt - 1].len;
-		path[0].mid = path[0].start + path[0].len / 2;
-		if (path[0].mid < 0)
-			path[0].mid += MAX_PHASE + 1;
-
-		cont_path_cnt--;
-	}
-
-	max_len = 0;
-	final_phase = 0;
-	final_path_idx = 0;
-	for (i = 0; i < cont_path_cnt; i++) {
-		if (path[i].len > max_len) {
-			max_len = path[i].len;
-			final_phase = (u8)path[i].mid;
-			final_path_idx = i;
-		}
-
-		RTSX_DEBUGP("path[%d].start = %d\n", i, path[i].start);
-		RTSX_DEBUGP("path[%d].end = %d\n", i, path[i].end);
-		RTSX_DEBUGP("path[%d].len = %d\n", i, path[i].len);
-		RTSX_DEBUGP("path[%d].mid = %d\n", i, path[i].mid);
-		RTSX_DEBUGP("\n");
-	}
-
-	if (tune_dir == TUNE_TX) {
-		if (CHK_SD_SDR104(sd_card)) {
-			if (max_len > 15) {
-				int temp_mid = (max_len - 16) / 2;
-				int temp_final_phase =
-					path[final_path_idx].end - (max_len - (6 + temp_mid));
-
-				if (temp_final_phase < 0)
-					final_phase = (u8)(temp_final_phase + MAX_PHASE + 1);
-				else
-					final_phase = (u8)temp_final_phase;
-			}
-		} else if (CHK_SD_SDR50(sd_card)) {
-			if (max_len > 12) {
-				int temp_mid = (max_len - 13) / 2;
-				int temp_final_phase =
-					path[final_path_idx].end - (max_len - (3 + temp_mid));
-
-				if (temp_final_phase < 0)
-					final_phase = (u8)(temp_final_phase + MAX_PHASE + 1);
-				else
-					final_phase = (u8)temp_final_phase;
-			}
-		}
-	}
-
-Search_Finish:
-	RTSX_DEBUGP("Final chosen phase: %d\n", final_phase);
-	return final_phase;
-}
-
-static int sd_tuning_rx(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	int i, j;
-	u32 raw_phase_map[3], phase_map;
-	u8 final_phase;
-	int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point);
-
-	if (CHK_SD(sd_card)) {
-		if (CHK_SD_DDR50(sd_card))
-			tuning_cmd = sd_ddr_tuning_rx_cmd;
-		else
-			tuning_cmd = sd_sdr_tuning_rx_cmd;
-
-	} else {
-		if (CHK_MMC_DDR52(sd_card))
-			tuning_cmd = mmc_ddr_tunning_rx_cmd;
-		else
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	for (i = 0; i < 3; i++) {
-		raw_phase_map[i] = 0;
-		for (j = MAX_PHASE; j >= 0; j--) {
-			if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
-				sd_set_err_code(chip, SD_NO_CARD);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			retval = tuning_cmd(chip, (u8)j);
-			if (retval == STATUS_SUCCESS)
-				raw_phase_map[i] |= 1 << j;
-		}
-	}
-
-	phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2];
-	for (i = 0; i < 3; i++)
-		RTSX_DEBUGP("RX raw_phase_map[%d] = 0x%08x\n", i, raw_phase_map[i]);
-
-	RTSX_DEBUGP("RX phase_map = 0x%08x\n", phase_map);
-
-	final_phase = sd_search_final_phase(chip, phase_map, TUNE_RX);
-	if (final_phase == 0xFF)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = sd_change_phase(chip, final_phase, TUNE_RX);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	int i;
-	u32 phase_map;
-	u8 final_phase;
-
-	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, SD_RSP_80CLK_TIMEOUT_EN);
-
-	phase_map = 0;
-	for (i = MAX_PHASE; i >= 0; i--) {
-		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
-			sd_set_err_code(chip, SD_NO_CARD);
-			rtsx_write_register(chip, SD_CFG3,
-						SD_RSP_80CLK_TIMEOUT_EN, 0);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		retval = sd_change_phase(chip, (u8)i, TUNE_TX);
-		if (retval != STATUS_SUCCESS)
-			continue;
-
-		retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
-				SD_RSP_TYPE_R1, NULL, 0);
-		if ((retval == STATUS_SUCCESS) || !sd_check_err_code(chip, SD_RSP_TIMEOUT))
-			phase_map |= 1 << i;
-	}
-
-	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
-
-	RTSX_DEBUGP("DDR TX pre tune phase_map = 0x%08x\n", phase_map);
-
-	final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX);
-	if (final_phase == 0xFF)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = sd_change_phase(chip, final_phase, TUNE_TX);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_DEBUGP("DDR TX pre tune phase: %d\n", (int)final_phase);
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_tuning_tx(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	int i, j;
-	u32 raw_phase_map[3], phase_map;
-	u8 final_phase;
-	int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point);
-
-	if (CHK_SD(sd_card)) {
-		if (CHK_SD_DDR50(sd_card))
-			tuning_cmd = sd_ddr_tuning_tx_cmd;
-		else
-			tuning_cmd = sd_sdr_tuning_tx_cmd;
-
-	} else {
-		if (CHK_MMC_DDR52(sd_card))
-			tuning_cmd = sd_ddr_tuning_tx_cmd;
-		else
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	for (i = 0; i < 3; i++) {
-		raw_phase_map[i] = 0;
-		for (j = MAX_PHASE; j >= 0; j--) {
-			if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
-				sd_set_err_code(chip, SD_NO_CARD);
-				rtsx_write_register(chip, SD_CFG3,
-						    SD_RSP_80CLK_TIMEOUT_EN, 0);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			retval = tuning_cmd(chip, (u8)j);
-			if (retval == STATUS_SUCCESS)
-				raw_phase_map[i] |= 1 << j;
-		}
-	}
-
-	phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2];
-	for (i = 0; i < 3; i++)
-		RTSX_DEBUGP("TX raw_phase_map[%d] = 0x%08x\n", i, raw_phase_map[i]);
-
-	RTSX_DEBUGP("TX phase_map = 0x%08x\n", phase_map);
-
-	final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX);
-	if (final_phase == 0xFF)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = sd_change_phase(chip, final_phase, TUNE_TX);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_sdr_tuning(struct rtsx_chip *chip)
-{
-	int retval;
-
-	retval = sd_tuning_tx(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = sd_tuning_rx(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_ddr_tuning(struct rtsx_chip *chip)
-{
-	int retval;
-
-	if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) {
-		retval = sd_ddr_pre_tuning_tx(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	} else {
-		retval = sd_change_phase(chip, (u8)chip->sd_ddr_tx_phase, TUNE_TX);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	retval = sd_tuning_rx(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) {
-		retval = sd_tuning_tx(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int mmc_ddr_tuning(struct rtsx_chip *chip)
-{
-	int retval;
-
-	if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) {
-		retval = sd_ddr_pre_tuning_tx(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	} else {
-		retval = sd_change_phase(chip, (u8)chip->mmc_ddr_tx_phase, TUNE_TX);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	retval = sd_tuning_rx(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) {
-		retval = sd_tuning_tx(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int sd_switch_clock(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	int re_tuning = 0;
-
-	retval = select_card(chip, SD_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (CHECK_PID(chip, 0x5209) &&
-			(CHK_SD30_SPEED(sd_card) || CHK_MMC_DDR52(sd_card))) {
-		if (sd_card->need_retune && (sd_card->sd_clock != chip->cur_clk)) {
-			re_tuning = 1;
-			sd_card->need_retune = 0;
-		}
-	}
-
-	retval = switch_clock(chip, sd_card->sd_clock);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (re_tuning) {
-		if (CHK_SD(sd_card)) {
-			if (CHK_SD_DDR50(sd_card))
-				retval = sd_ddr_tuning(chip);
-			else
-				retval = sd_sdr_tuning(chip);
-		} else {
-			if (CHK_MMC_DDR52(sd_card))
-				retval = mmc_ddr_tuning(chip);
-		}
-
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_prepare_reset(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-
-	if (chip->asic_code)
-		sd_card->sd_clock = 29;
-	else
-		sd_card->sd_clock = CLK_30;
-
-	sd_card->sd_type = 0;
-	sd_card->seq_mode = 0;
-	sd_card->sd_data_buf_ready = 0;
-	sd_card->capacity = 0;
-
-#ifdef SUPPORT_SD_LOCK
-	sd_card->sd_lock_status = 0;
-	sd_card->sd_erase_status = 0;
-#endif
-
-	chip->capacity[chip->card2lun[SD_CARD]] = 0;
-	chip->sd_io = 0;
-
-	retval = sd_set_init_para(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, retval);
-
-	if (CHECK_PID(chip, 0x5209)) {
-		RTSX_WRITE_REG(chip, REG_SD_CFG1, 0xFF,
-			SD_CLK_DIVIDE_128 | SD_20_MODE | SD_BUS_WIDTH_1);
-		RTSX_WRITE_REG(chip, SD_SAMPLE_POINT_CTL, 0xFF, SD20_RX_POS_EDGE);
-		RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0xFF, 0);
-	} else {
-		RTSX_WRITE_REG(chip, REG_SD_CFG1, 0xFF, 0x40);
-	}
-
-	RTSX_WRITE_REG(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, SD_STOP | SD_CLR_ERR);
-
-	retval = select_card(chip, SD_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_pull_ctl_disable(struct rtsx_chip *chip)
-{
-	if (CHECK_PID(chip, 0x5209)) {
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0xD5);
-	} else if (CHECK_PID(chip, 0x5208)) {
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF,
-			XD_D3_PD | SD_D7_PD | SD_CLK_PD | SD_D5_PD);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF,
-			SD_D6_PD | SD_D0_PD | SD_D1_PD | XD_D5_PD);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF,
-			SD_D4_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF,
-			XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF,
-			MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD);
-	} else if (CHECK_PID(chip, 0x5288)) {
-		if (CHECK_BARO_PKG(chip, QFN)) {
-			RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55);
-			RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55);
-			RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0x4B);
-			RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x69);
-		}
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int sd_pull_ctl_enable(struct rtsx_chip *chip)
-{
-	int retval;
-
-	rtsx_init_cmd(chip);
-
-	if (CHECK_PID(chip, 0x5209)) {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xAA);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0xAA);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xE9);
-	} else if (CHECK_PID(chip, 0x5208)) {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
-			XD_D3_PD | SD_DAT7_PU | SD_CLK_NP | SD_D5_PU);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
-			SD_D6_PU | SD_D0_PU | SD_D1_PU | XD_D5_PD);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
-			SD_D4_PU | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
-			XD_RDY_PD | SD_D3_PU | SD_D2_PU | XD_ALE_PD);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
-			MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD);
-	} else if (CHECK_PID(chip, 0x5288)) {
-		if (CHECK_BARO_PKG(chip, QFN)) {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xA8);
-			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x5A);
-			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);
-			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0xAA);
-		}
-	}
-
-	retval = rtsx_send_cmd(chip, SD_CARD, 100);
-	if (retval < 0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_init_power(struct rtsx_chip *chip)
-{
-	int retval;
-
-	if (CHECK_PID(chip, 0x5209))
-		RTSX_WRITE_REG(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_OFF);
-
-	retval = sd_power_off_card3v3(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (!chip->ft2_fast_mode)
-		wait_timeout(250);
-
-	retval = enable_card_clock(chip, SD_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (chip->asic_code) {
-		retval = sd_pull_ctl_enable(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	} else {
-		RTSX_WRITE_REG(chip, FPGA_PULL_CTL, FPGA_SD_PULL_CTL_BIT | 0x20, 0);
-	}
-
-	if (chip->ft2_fast_mode) {
-		if (CHECK_PID(chip, 0x5209))
-			RTSX_WRITE_REG(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON);
-
-	} else {
-		retval = card_power_on(chip, SD_CARD);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		wait_timeout(260);
-
-#ifdef SUPPORT_OCP
-		if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
-			RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", chip->ocp_stat);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-#endif
-	}
-
-	RTSX_WRITE_REG(chip, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN);
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_dummy_clock(struct rtsx_chip *chip)
-{
-	if (CHECK_PID(chip, 0x5209)) {
-		RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN, SD_CLK_TOGGLE_EN);
-		wait_timeout(5);
-		RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN, 0x00);
-	} else {
-		RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x01, 0x01);
-		wait_timeout(5);
-		RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x01, 0);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_read_lba0(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	u8 cmd[5], bus_width;
-
-	cmd[0] = 0x40 | READ_SINGLE_BLOCK;
-	cmd[1] = 0;
-	cmd[2] = 0;
-	cmd[3] = 0;
-	cmd[4] = 0;
-
-	if (CHK_SD(sd_card)) {
-		bus_width = SD_BUS_WIDTH_4;
-	} else {
-		if (CHK_MMC_8BIT(sd_card))
-			bus_width = SD_BUS_WIDTH_8;
-		else if (CHK_MMC_4BIT(sd_card))
-			bus_width = SD_BUS_WIDTH_4;
-		else
-			bus_width = SD_BUS_WIDTH_1;
-	}
-
-	retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd,
-		5, 512, 1, bus_width, NULL, 0, 100);
-	if (retval != STATUS_SUCCESS) {
-		rtsx_clear_sd_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int sd_check_wp_state(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	u32 val;
-	u16 sd_card_type;
-	u8 cmd[5], buf[64];
-
-	retval = sd_send_cmd_get_rsp(chip, APP_CMD,
-			sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	cmd[0] = 0x40 | SD_STATUS;
-	cmd[1] = 0;
-	cmd[2] = 0;
-	cmd[3] = 0;
-	cmd[4] = 0;
-
-	retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, SD_BUS_WIDTH_4, buf, 64, 250);
-	if (retval != STATUS_SUCCESS) {
-		rtsx_clear_sd_error(chip);
-
-		sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	RTSX_DEBUGP("ACMD13:\n");
-	RTSX_DUMP(buf, 64);
-
-	sd_card_type = ((u16)buf[2] << 8) | buf[3];
-	RTSX_DEBUGP("sd_card_type = 0x%04x\n", sd_card_type);
-	if ((sd_card_type == 0x0001) || (sd_card_type == 0x0002)) {
-		/* ROM card or OTP */
-		chip->card_wp |= SD_CARD;
-	}
-
-	/* Check SD Machanical Write-Protect Switch */
-	val = rtsx_readl(chip, RTSX_BIPR);
-	if (val & SD_WRITE_PROTECT)
-		chip->card_wp |= SD_CARD;
-
-	return STATUS_SUCCESS;
-}
-
-static int reset_sd(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval, i = 0, j = 0, k = 0, hi_cap_flow = 0;
-	int sd_dont_switch = 0;
-	int support_1v8 = 0;
-	int try_sdio = 1;
-	u8 rsp[16];
-	u8 switch_bus_width;
-	u32 voltage = 0;
-	int sd20_mode = 0;
-
-	SET_SD(sd_card);
-
-Switch_Fail:
-
-	i = 0;
-	j = 0;
-	k = 0;
-	hi_cap_flow = 0;
-
-#ifdef SUPPORT_SD_LOCK
-	if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON)
-		goto SD_UNLOCK_ENTRY;
-#endif
-
-	retval = sd_prepare_reset(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = sd_dummy_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) && try_sdio) {
-		int rty_cnt = 0;
-
-		for (; rty_cnt < chip->sdio_retry_cnt; rty_cnt++) {
-			if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
-				sd_set_err_code(chip, SD_NO_CARD);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			retval = sd_send_cmd_get_rsp(chip, IO_SEND_OP_COND, 0, SD_RSP_TYPE_R4, rsp, 5);
-			if (retval == STATUS_SUCCESS) {
-				int func_num = (rsp[1] >> 4) & 0x07;
-				if (func_num) {
-					RTSX_DEBUGP("SD_IO card (Function number: %d)!\n", func_num);
-					chip->sd_io = 1;
-					TRACE_RET(chip, STATUS_FAIL);
-				}
-
-				break;
-			}
-
-			sd_init_power(chip);
-
-			sd_dummy_clock(chip);
-		}
-
-		RTSX_DEBUGP("Normal card!\n");
-	}
-
-	/* Start Initialization Process of SD Card */
-RTY_SD_RST:
-	retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0);
-	if (retval != STATUS_SUCCESS)
-	       TRACE_RET(chip, STATUS_FAIL);
-
-	wait_timeout(20);
-
-	retval = sd_send_cmd_get_rsp(chip, SEND_IF_COND, 0x000001AA, SD_RSP_TYPE_R7, rsp, 5);
-	if (retval == STATUS_SUCCESS) {
-		if ((rsp[4] == 0xAA) && ((rsp[3] & 0x0f) == 0x01)) {
-			hi_cap_flow = 1;
-			if (CHECK_PID(chip, 0x5209)) {
-				if (sd20_mode) {
-					voltage = SUPPORT_VOLTAGE |
-						SUPPORT_HIGH_AND_EXTENDED_CAPACITY;
-				} else {
-					voltage = SUPPORT_VOLTAGE |
-						SUPPORT_HIGH_AND_EXTENDED_CAPACITY |
-						SUPPORT_MAX_POWER_PERMANCE | SUPPORT_1V8;
-				}
-			} else {
-				voltage = SUPPORT_VOLTAGE | 0x40000000;
-			}
-		}
-	}
-
-	if (!hi_cap_flow) {
-		voltage = SUPPORT_VOLTAGE;
-
-		retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0);
-		if (retval != STATUS_SUCCESS)
-		       TRACE_RET(chip, STATUS_FAIL);
-
-		wait_timeout(20);
-	}
-
-	do {
-		retval = sd_send_cmd_get_rsp(chip, APP_CMD, 0, SD_RSP_TYPE_R1, NULL, 0);
-		if (retval != STATUS_SUCCESS) {
-			if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
-				sd_set_err_code(chip, SD_NO_CARD);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			j++;
-			if (j < 3)
-				goto RTY_SD_RST;
-			else
-				TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		retval = sd_send_cmd_get_rsp(chip, SD_APP_OP_COND, voltage, SD_RSP_TYPE_R3, rsp, 5);
-		if (retval != STATUS_SUCCESS) {
-			k++;
-			if (k < 3)
-				goto RTY_SD_RST;
-			else
-				TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		i++;
-		wait_timeout(20);
-	} while (!(rsp[1] & 0x80) && (i < 255));
-
-	if (i == 255)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (hi_cap_flow) {
-		if (rsp[1] & 0x40)
-			SET_SD_HCXC(sd_card);
-		else
-			CLR_SD_HCXC(sd_card);
-
-		if (CHECK_PID(chip, 0x5209) && CHK_SD_HCXC(sd_card) && !sd20_mode)
-			support_1v8 = (rsp[1] & 0x01) ? 1 : 0;
-		else
-			support_1v8 = 0;
-	} else {
-		CLR_SD_HCXC(sd_card);
-		support_1v8 = 0;
-	}
-	RTSX_DEBUGP("support_1v8 = %d\n", support_1v8);
-
-	if (support_1v8) {
-		retval = sd_voltage_switch(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, NULL, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	for (i = 0; i < 3; i++) {
-		retval = sd_send_cmd_get_rsp(chip, SEND_RELATIVE_ADDR, 0, SD_RSP_TYPE_R6, rsp, 5);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		sd_card->sd_addr = (u32)rsp[1] << 24;
-		sd_card->sd_addr += (u32)rsp[2] << 16;
-
-		if (sd_card->sd_addr)
-			break;
-	}
-
-	retval = sd_check_csd(chip, 1);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = sd_select_card(chip, 1);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-#ifdef SUPPORT_SD_LOCK
-SD_UNLOCK_ENTRY:
-	retval = sd_update_lock_status(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (sd_card->sd_lock_status & SD_LOCKED) {
-		sd_card->sd_lock_status |= (SD_LOCK_1BIT_MODE | SD_PWD_EXIST);
-		return STATUS_SUCCESS;
-	} else if (!(sd_card->sd_lock_status & SD_UNLOCK_POW_ON)) {
-		sd_card->sd_lock_status &= ~SD_PWD_EXIST;
-	}
-#endif
-
-	retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = sd_send_cmd_get_rsp(chip, SET_CLR_CARD_DETECT, 0, SD_RSP_TYPE_R1, NULL, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (support_1v8) {
-		retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, NULL, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		switch_bus_width = SD_BUS_WIDTH_4;
-	} else {
-		switch_bus_width = SD_BUS_WIDTH_1;
-	}
-
-	retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, NULL, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (!(sd_card->raw_csd[4] & 0x40))
-		sd_dont_switch = 1;
-
-	if (!sd_dont_switch) {
-		if (sd20_mode) {
-			/* Set sd_switch_fail here, because we needn't
-			 * switch to UHS mode
-			 */
-			sd_card->sd_switch_fail = SDR104_SUPPORT_MASK |
-				DDR50_SUPPORT_MASK | SDR50_SUPPORT_MASK;
-		}
-
-		/* Check the card whether follow SD1.1 spec or higher */
-		retval = sd_check_spec(chip, switch_bus_width);
-		if (retval == STATUS_SUCCESS) {
-			retval = sd_switch_function(chip, switch_bus_width);
-			if (retval != STATUS_SUCCESS) {
-				if (CHECK_PID(chip, 0x5209))
-					sd_change_bank_voltage(chip, SD_IO_3V3);
-
-				sd_init_power(chip);
-				sd_dont_switch = 1;
-				try_sdio = 0;
-
-				goto Switch_Fail;
-			}
-		} else {
-			if (support_1v8) {
-				if (CHECK_PID(chip, 0x5209))
-					sd_change_bank_voltage(chip, SD_IO_3V3);
-
-				sd_init_power(chip);
-				sd_dont_switch = 1;
-				try_sdio = 0;
-
-				goto Switch_Fail;
-			}
-		}
-	}
-
-	if (!support_1v8) {
-		retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, NULL, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-#ifdef SUPPORT_SD_LOCK
-	sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
-#endif
-
-	if (!sd20_mode && CHK_SD30_SPEED(sd_card)) {
-		int read_lba0 = 1;
-
-		RTSX_WRITE_REG(chip, SD30_DRIVE_SEL, 0x07, chip->sd30_drive_sel_1v8);
-
-		retval = sd_set_init_para(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		if (CHK_SD_DDR50(sd_card))
-			retval = sd_ddr_tuning(chip);
-		else
-			retval = sd_sdr_tuning(chip);
-
-		if (retval != STATUS_SUCCESS) {
-			if (sd20_mode) {
-				TRACE_RET(chip, STATUS_FAIL);
-			} else {
-				retval = sd_init_power(chip);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-
-				try_sdio = 0;
-				sd20_mode = 1;
-				goto Switch_Fail;
-			}
-		}
-
-		sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-
-		if (CHK_SD_DDR50(sd_card)) {
-			retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
-			if (retval != STATUS_SUCCESS)
-				read_lba0 = 0;
-		}
-
-		if (read_lba0) {
-			retval = sd_read_lba0(chip);
-			if (retval != STATUS_SUCCESS) {
-				if (sd20_mode) {
-					TRACE_RET(chip, STATUS_FAIL);
-				} else {
-					retval = sd_init_power(chip);
-					if (retval != STATUS_SUCCESS)
-						TRACE_RET(chip, STATUS_FAIL);
-
-					try_sdio = 0;
-					sd20_mode = 1;
-					goto Switch_Fail;
-				}
-			}
-		}
-	}
-
-	retval = sd_check_wp_state(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
-
-#ifdef SUPPORT_SD_LOCK
-	if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) {
-		RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_H, 0xFF, 0x02);
-		RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_L, 0xFF, 0x00);
-	}
-#endif
-
-	return STATUS_SUCCESS;
-}
-
-
-static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	u8 buf[8] = {0}, bus_width, *ptr;
-	u16 byte_cnt;
-	int len;
-
-	retval = sd_send_cmd_get_rsp(chip, BUSTEST_W, 0, SD_RSP_TYPE_R1, NULL, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, SWITCH_FAIL);
-
-	if (width == MMC_8BIT_BUS) {
-		buf[0] = 0x55;
-		buf[1] = 0xAA;
-		len = 8;
-		byte_cnt = 8;
-		bus_width = SD_BUS_WIDTH_8;
-	} else {
-		buf[0] = 0x5A;
-		len = 4;
-		byte_cnt = 4;
-		bus_width = SD_BUS_WIDTH_4;
-	}
-
-	if (!CHECK_PID(chip, 0x5209)) {
-		retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0x02);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, SWITCH_ERR);
-	}
-
-	retval = sd_write_data(chip, SD_TM_AUTO_WRITE_3,
-			NULL, 0, byte_cnt, 1, bus_width, buf, len, 100);
-	if (retval != STATUS_SUCCESS) {
-		if (CHECK_PID(chip, 0x5209)) {
-			u8 val1 = 0, val2 = 0;
-			rtsx_read_register(chip, REG_SD_STAT1, &val1);
-			rtsx_read_register(chip, REG_SD_STAT2, &val2);
-			rtsx_clear_sd_error(chip);
-			if ((val1 & 0xE0) || val2)
-				TRACE_RET(chip, SWITCH_ERR);
-		} else {
-			rtsx_clear_sd_error(chip);
-			rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
-			TRACE_RET(chip, SWITCH_ERR);
-		}
-	}
-
-	if (!CHECK_PID(chip, 0x5209)) {
-		retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, SWITCH_ERR);
-	}
-
-	RTSX_DEBUGP("SD/MMC CMD %d\n", BUSTEST_R);
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | BUSTEST_R);
-
-	if (width == MMC_8BIT_BUS)
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x08);
-	else
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x04);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
-			SD_CALCULATE_CRC7 | SD_NO_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
-			SD_CHECK_CRC7 | SD_RSP_LEN_6);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, SD_TM_NORMAL_READ | SD_TRANSFER_START);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
-
-	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2, 0, 0);
-	if (width == MMC_8BIT_BUS)
-		rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 1, 0, 0);
-
-	retval = rtsx_send_cmd(chip, SD_CARD, 100);
-	if (retval < 0) {
-		rtsx_clear_sd_error(chip);
-		TRACE_RET(chip, SWITCH_ERR);
-	}
-
-	ptr = rtsx_get_cmd_data(chip) + 1;
-
-	if (width == MMC_8BIT_BUS) {
-		RTSX_DEBUGP("BUSTEST_R [8bits]: 0x%02x 0x%02x\n", ptr[0], ptr[1]);
-		if ((ptr[0] == 0xAA) && (ptr[1] == 0x55)) {
-			u8 rsp[5];
-			u32 arg;
-
-			if (CHK_MMC_DDR52(sd_card))
-				arg = 0x03B70600;
-			else
-				arg = 0x03B70200;
-
-			retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, SD_RSP_TYPE_R1b, rsp, 5);
-			if ((retval == STATUS_SUCCESS) && !(rsp[4] & MMC_SWITCH_ERR))
-				return SWITCH_SUCCESS;
-		}
-	} else {
-		RTSX_DEBUGP("BUSTEST_R [4bits]: 0x%02x\n", ptr[0]);
-		if (ptr[0] == 0xA5) {
-			u8 rsp[5];
-			u32 arg;
-
-			if (CHK_MMC_DDR52(sd_card))
-				arg = 0x03B70500;
-			else
-				arg = 0x03B70100;
-
-			retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, SD_RSP_TYPE_R1b, rsp, 5);
-			if ((retval == STATUS_SUCCESS) && !(rsp[4] & MMC_SWITCH_ERR))
-				return SWITCH_SUCCESS;
-		}
-	}
-
-	TRACE_RET(chip, SWITCH_FAIL);
-}
-
-
-static int mmc_switch_timing_bus(struct rtsx_chip *chip, int switch_ddr)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-	u8 *ptr, card_type, card_type_mask = 0;
-
-	CLR_MMC_HS(sd_card);
-
-	RTSX_DEBUGP("SD/MMC CMD %d\n", SEND_EXT_CSD);
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | SEND_EXT_CSD);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, 0);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, 0);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, 0);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, 0);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 2);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
-			SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
-			SD_CHECK_CRC7 | SD_RSP_LEN_6);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, SD_TM_NORMAL_READ | SD_TRANSFER_START);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
-
-	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 196, 0xFF, 0);
-	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 212, 0xFF, 0);
-	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 213, 0xFF, 0);
-	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 214, 0xFF, 0);
-	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 215, 0xFF, 0);
-
-	retval = rtsx_send_cmd(chip, SD_CARD, 1000);
-	if (retval < 0) {
-		if (retval == -ETIMEDOUT) {
-			rtsx_clear_sd_error(chip);
-			sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
-					SD_RSP_TYPE_R1, NULL, 0);
-		}
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	ptr = rtsx_get_cmd_data(chip);
-	if (ptr[0] & SD_TRANSFER_ERR) {
-		sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (CHK_MMC_SECTOR_MODE(sd_card)) {
-		sd_card->capacity = ((u32)ptr[5] << 24) | ((u32)ptr[4] << 16) |
-			((u32)ptr[3] << 8) | ((u32)ptr[2]);
-	}
-
-	if (CHECK_PID(chip, 0x5209)) {
-#ifdef SUPPORT_SD_LOCK
-		if (!(sd_card->sd_lock_status & SD_SDR_RST) &&
-				(chip->sd_ctl & SUPPORT_MMC_DDR_MODE)) {
-			card_type_mask = 0x07;
-		} else {
-			card_type_mask = 0x03;
-		}
-#else
-		if (chip->sd_ctl & SUPPORT_MMC_DDR_MODE)
-			card_type_mask = 0x07;
-		else
-			card_type_mask = 0x03;
-#endif
-	} else {
-		card_type_mask = 0x03;
-	}
-	card_type = ptr[1] & card_type_mask;
-	if (card_type) {
-		u8 rsp[5];
-
-		if (card_type & 0x04) {
-			if (switch_ddr)
-				SET_MMC_DDR52(sd_card);
-			else
-				SET_MMC_52M(sd_card);
-		} else if (card_type & 0x02) {
-			SET_MMC_52M(sd_card);
-		} else {
-			SET_MMC_26M(sd_card);
-		}
-
-		retval = sd_send_cmd_get_rsp(chip, SWITCH,
-				0x03B90100, SD_RSP_TYPE_R1b, rsp, 5);
-		if ((retval != STATUS_SUCCESS) || (rsp[4] & MMC_SWITCH_ERR))
-			CLR_MMC_HS(sd_card);
-	}
-
-	sd_choose_proper_clock(chip);
-	retval = switch_clock(chip, sd_card->sd_clock);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	/* Test Bus Procedure */
-	retval = mmc_test_switch_bus(chip, MMC_8BIT_BUS);
-	if (retval == SWITCH_SUCCESS) {
-		SET_MMC_8BIT(sd_card);
-		chip->card_bus_width[chip->card2lun[SD_CARD]] = 8;
-#ifdef SUPPORT_SD_LOCK
-		sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
-#endif
-	} else if (retval == SWITCH_FAIL) {
-		retval = mmc_test_switch_bus(chip, MMC_4BIT_BUS);
-		if (retval == SWITCH_SUCCESS) {
-			SET_MMC_4BIT(sd_card);
-			chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
-#ifdef SUPPORT_SD_LOCK
-			sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
-#endif
-		} else if (retval == SWITCH_FAIL) {
-			CLR_MMC_8BIT(sd_card);
-			CLR_MMC_4BIT(sd_card);
-		} else {
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	} else {
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-
-static int reset_mmc(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval, i = 0, j = 0, k = 0;
-	int switch_ddr = 1;
-	u8 rsp[16];
-	u8 spec_ver = 0;
-	u32 temp;
-
-#ifdef SUPPORT_SD_LOCK
-	if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON)
-		goto MMC_UNLOCK_ENTRY;
-#endif
-
-Switch_Fail:
-	retval = sd_prepare_reset(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, retval);
-
-	SET_MMC(sd_card);
-
-RTY_MMC_RST:
-	retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0);
-	if (retval != STATUS_SUCCESS)
-	       TRACE_RET(chip, STATUS_FAIL);
-
-	do {
-		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
-			sd_set_err_code(chip, SD_NO_CARD);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		retval = sd_send_cmd_get_rsp(chip, SEND_OP_COND,
-				(SUPPORT_VOLTAGE|0x40000000), SD_RSP_TYPE_R3, rsp, 5);
-		if (retval != STATUS_SUCCESS) {
-			if (sd_check_err_code(chip, SD_BUSY) || sd_check_err_code(chip, SD_TO_ERR)) {
-				k++;
-				if (k < 20) {
-					sd_clr_err_code(chip);
-					goto RTY_MMC_RST;
-				} else {
-					TRACE_RET(chip, STATUS_FAIL);
-				}
-			} else {
-				j++;
-				if (j < 100) {
-					sd_clr_err_code(chip);
-					goto RTY_MMC_RST;
-				} else {
-					TRACE_RET(chip, STATUS_FAIL);
-				}
-			}
-		}
-
-		wait_timeout(20);
-		i++;
-	} while (!(rsp[1] & 0x80) && (i < 255));
-
-	if (i == 255)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if ((rsp[1] & 0x60) == 0x40)
-		SET_MMC_SECTOR_MODE(sd_card);
-	else
-		CLR_MMC_SECTOR_MODE(sd_card);
-
-	retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, NULL, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	sd_card->sd_addr = 0x00100000;
-	retval = sd_send_cmd_get_rsp(chip, SET_RELATIVE_ADDR, sd_card->sd_addr, SD_RSP_TYPE_R6, rsp, 5);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = sd_check_csd(chip, 1);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	spec_ver = (sd_card->raw_csd[0] & 0x3C) >> 2;
-
-	retval = sd_select_card(chip, 1);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, NULL, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-#ifdef SUPPORT_SD_LOCK
-MMC_UNLOCK_ENTRY:
-	retval = sd_update_lock_status(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-#endif
-
-	retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	chip->card_bus_width[chip->card2lun[SD_CARD]] = 1;
-
-	if (!sd_card->mmc_dont_switch_bus) {
-		if (spec_ver == 4) {
-			/* MMC 4.x Cards */
-			retval = mmc_switch_timing_bus(chip, switch_ddr);
-			if (retval != STATUS_SUCCESS) {
-				retval = sd_init_power(chip);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-				sd_card->mmc_dont_switch_bus = 1;
-				TRACE_GOTO(chip, Switch_Fail);
-			}
-		}
-
-		if (CHK_MMC_SECTOR_MODE(sd_card) && (sd_card->capacity == 0))
-			TRACE_RET(chip, STATUS_FAIL);
-
-		if (switch_ddr && CHK_MMC_DDR52(sd_card)) {
-			retval = sd_set_init_para(chip);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-
-			retval = mmc_ddr_tuning(chip);
-			if (retval != STATUS_SUCCESS) {
-				retval = sd_init_power(chip);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-
-				switch_ddr = 0;
-				TRACE_GOTO(chip, Switch_Fail);
-			}
-
-			retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
-			if (retval == STATUS_SUCCESS) {
-				retval = sd_read_lba0(chip);
-				if (retval != STATUS_SUCCESS) {
-					retval = sd_init_power(chip);
-					if (retval != STATUS_SUCCESS)
-						TRACE_RET(chip, STATUS_FAIL);
-
-					switch_ddr = 0;
-					TRACE_GOTO(chip, Switch_Fail);
-				}
-			}
-		}
-	}
-
-#ifdef SUPPORT_SD_LOCK
-	if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) {
-		RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_H, 0xFF, 0x02);
-		RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_L, 0xFF, 0x00);
-	}
-#endif
-
-	temp = rtsx_readl(chip, RTSX_BIPR);
-	if (temp & SD_WRITE_PROTECT)
-		chip->card_wp |= SD_CARD;
-
-	return STATUS_SUCCESS;
-}
-
-int reset_sd_card(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-
-	sd_init_reg_addr(chip);
-
-	memset(sd_card, 0, sizeof(struct sd_info));
-	chip->capacity[chip->card2lun[SD_CARD]] = 0;
-
-	retval = enable_card_clock(chip, SD_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (chip->ignore_sd && CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
-		if (chip->asic_code) {
-			retval = sd_pull_ctl_enable(chip);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-		} else {
-			retval = rtsx_write_register(chip, FPGA_PULL_CTL,
-						     FPGA_SD_PULL_CTL_BIT | 0x20, 0);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-		}
-		retval = card_share_mode(chip, SD_CARD);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		chip->sd_io = 1;
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	retval = sd_init_power(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (chip->sd_ctl & RESET_MMC_FIRST) {
-		retval = reset_mmc(chip);
-		if (retval != STATUS_SUCCESS) {
-			if (sd_check_err_code(chip, SD_NO_CARD))
-				TRACE_RET(chip, STATUS_FAIL);
-
-			retval = reset_sd(chip);
-			if (retval != STATUS_SUCCESS) {
-				if (CHECK_PID(chip, 0x5209))
-					sd_change_bank_voltage(chip, SD_IO_3V3);
-
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-	} else {
-		retval = reset_sd(chip);
-		if (retval != STATUS_SUCCESS) {
-			if (sd_check_err_code(chip, SD_NO_CARD))
-				TRACE_RET(chip, STATUS_FAIL);
-
-			if (CHECK_PID(chip, 0x5209)) {
-				retval = sd_change_bank_voltage(chip, SD_IO_3V3);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			if (chip->sd_io) {
-				TRACE_RET(chip, STATUS_FAIL);
-			} else {
-				retval = reset_mmc(chip);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-	}
-
-	retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_L, 0xFF, 0);
-	RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_H, 0xFF, 2);
-
-	chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity;
-
-	retval = sd_set_init_para(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_DEBUGP("sd_card->sd_type = 0x%x\n", sd_card->sd_type);
-
-	return STATUS_SUCCESS;
-}
-
-static int reset_mmc_only(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-
-	sd_card->sd_type = 0;
-	sd_card->seq_mode = 0;
-	sd_card->sd_data_buf_ready = 0;
-	sd_card->capacity = 0;
-	sd_card->sd_switch_fail = 0;
-
-#ifdef SUPPORT_SD_LOCK
-	sd_card->sd_lock_status = 0;
-	sd_card->sd_erase_status = 0;
-#endif
-
-	chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity = 0;
-
-	retval = enable_card_clock(chip, SD_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = sd_init_power(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = reset_mmc(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_L, 0xFF, 0);
-	RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_H, 0xFF, 2);
-
-	chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity;
-
-	retval = sd_set_init_para(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_DEBUGP("In reset_mmc_only, sd_card->sd_type = 0x%x\n", sd_card->sd_type);
-
-	return STATUS_SUCCESS;
-}
-
-#define WAIT_DATA_READY_RTY_CNT		255
-
-static int wait_data_buf_ready(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int i, retval;
-
-	for (i = 0; i < WAIT_DATA_READY_RTY_CNT; i++) {
-		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
-			sd_set_err_code(chip, SD_NO_CARD);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		sd_card->sd_data_buf_ready = 0;
-
-		retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
-				sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		if (sd_card->sd_data_buf_ready) {
-			return sd_send_cmd_get_rsp(chip, SEND_STATUS,
-				sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-		}
-	}
-
-	sd_set_err_code(chip, SD_TO_ERR);
-
-	TRACE_RET(chip, STATUS_FAIL);
-}
-
-void sd_stop_seq_mode(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-
-	if (sd_card->seq_mode) {
-		retval = sd_switch_clock(chip);
-		if (retval != STATUS_SUCCESS)
-			return;
-
-		retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0,
-				SD_RSP_TYPE_R1b, NULL, 0);
-		if (retval != STATUS_SUCCESS)
-			sd_set_err_code(chip, SD_STS_ERR);
-
-		retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
-		if (retval != STATUS_SUCCESS)
-			sd_set_err_code(chip, SD_STS_ERR);
-
-		sd_card->seq_mode = 0;
-
-		rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
-	}
-}
-
-static inline int sd_auto_tune_clock(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-
-	if (chip->asic_code) {
-		if (sd_card->sd_clock > 30)
-			sd_card->sd_clock -= 20;
-	} else {
-		switch (sd_card->sd_clock) {
-		case CLK_200:
-			sd_card->sd_clock = CLK_150;
-			break;
-
-		case CLK_150:
-			sd_card->sd_clock = CLK_120;
-			break;
-
-		case CLK_120:
-			sd_card->sd_clock = CLK_100;
-			break;
-
-		case CLK_100:
-			sd_card->sd_clock = CLK_80;
-			break;
-
-		case CLK_80:
-			sd_card->sd_clock = CLK_60;
-			break;
-
-		case CLK_60:
-			sd_card->sd_clock = CLK_50;
-			break;
-
-		default:
-			break;
-		}
-	}
-
-	retval = sd_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	u32 data_addr;
-	u8 cfg2;
-	int retval;
-
-	if (srb->sc_data_direction == DMA_FROM_DEVICE) {
-		RTSX_DEBUGP("sd_rw: Read %d %s from 0x%x\n", sector_cnt,
-			     (sector_cnt > 1) ? "sectors" : "sector", start_sector);
-	} else {
-		RTSX_DEBUGP("sd_rw: Write %d %s to 0x%x\n", sector_cnt,
-			     (sector_cnt > 1) ? "sectors" : "sector", start_sector);
-	}
-
-	sd_card->cleanup_counter = 0;
-
-	if (!(chip->card_ready & SD_CARD)) {
-		sd_card->seq_mode = 0;
-
-		retval = reset_sd_card(chip);
-		if (retval == STATUS_SUCCESS) {
-			chip->card_ready |= SD_CARD;
-			chip->card_fail &= ~SD_CARD;
-		} else {
-			chip->card_ready &= ~SD_CARD;
-			chip->card_fail |= SD_CARD;
-			chip->capacity[chip->card2lun[SD_CARD]] = 0;
-			chip->rw_need_retry = 1;
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	if (!CHK_SD_HCXC(sd_card) && !CHK_MMC_SECTOR_MODE(sd_card))
-		data_addr = start_sector << 9;
-	else
-		data_addr = start_sector;
-
-	sd_clr_err_code(chip);
-
-	retval = sd_switch_clock(chip);
-	if (retval != STATUS_SUCCESS) {
-		sd_set_err_code(chip, SD_IO_ERR);
-		TRACE_GOTO(chip, RW_FAIL);
-	}
-
-	if (sd_card->seq_mode && ((sd_card->pre_dir != srb->sc_data_direction)
-			|| ((sd_card->pre_sec_addr + sd_card->pre_sec_cnt) != start_sector))) {
-		if ((sd_card->pre_sec_cnt < 0x80)
-				&& (sd_card->pre_dir == DMA_FROM_DEVICE)
-				&& !CHK_SD30_SPEED(sd_card)
-				&& !CHK_SD_HS(sd_card)
-				&& !CHK_MMC_HS(sd_card)) {
-			sd_send_cmd_get_rsp(chip, SEND_STATUS,
-					sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-		}
-
-		retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION,
-				0, SD_RSP_TYPE_R1b, NULL, 0);
-		if (retval != STATUS_SUCCESS) {
-			chip->rw_need_retry = 1;
-			sd_set_err_code(chip, SD_STS_ERR);
-			TRACE_GOTO(chip, RW_FAIL);
-		}
-
-		sd_card->seq_mode = 0;
-
-		retval = rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
-		if (retval != STATUS_SUCCESS) {
-			sd_set_err_code(chip, SD_IO_ERR);
-			TRACE_GOTO(chip, RW_FAIL);
-		}
-
-		if ((sd_card->pre_sec_cnt < 0x80)
-				&& !CHK_SD30_SPEED(sd_card)
-				&& !CHK_SD_HS(sd_card)
-				&& !CHK_MMC_HS(sd_card)) {
-			sd_send_cmd_get_rsp(chip, SEND_STATUS,
-					sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
-		}
-	}
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, (u8)sector_cnt);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, (u8)(sector_cnt >> 8));
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-
-	if (CHK_MMC_8BIT(sd_card))
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_8);
-	else if (CHK_MMC_4BIT(sd_card) || CHK_SD(sd_card))
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
-	else
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_1);
-
-	if (sd_card->seq_mode) {
-		cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
-				SD_NO_CHECK_CRC7 | SD_RSP_LEN_0;
-		if (CHECK_PID(chip, 0x5209)) {
-			if (!CHK_SD30_SPEED(sd_card))
-				cfg2 |= SD_NO_CHECK_WAIT_CRC_TO;
-		}
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2);
-
-		trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512, DMA_512);
-
-		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
-				     SD_TM_AUTO_READ_3 | SD_TRANSFER_START);
-		} else {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
-				     SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
-		}
-
-		rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
-
-		rtsx_send_cmd_no_wait(chip);
-	} else {
-		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
-			RTSX_DEBUGP("SD/MMC CMD %d\n", READ_MULTIPLE_BLOCK);
-			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF,
-				     0x40 | READ_MULTIPLE_BLOCK);
-			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(data_addr >> 24));
-			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(data_addr >> 16));
-			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(data_addr >> 8));
-			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)data_addr);
-
-			cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
-					SD_CHECK_CRC7 | SD_RSP_LEN_6;
-			if (CHECK_PID(chip, 0x5209)) {
-				if (!CHK_SD30_SPEED(sd_card))
-					cfg2 |= SD_NO_CHECK_WAIT_CRC_TO;
-			}
-			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2);
-
-			trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512, DMA_512);
-
-			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
-				     SD_TM_AUTO_READ_2 | SD_TRANSFER_START);
-			rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
-				     SD_TRANSFER_END, SD_TRANSFER_END);
-
-			rtsx_send_cmd_no_wait(chip);
-		} else {
-			retval = rtsx_send_cmd(chip, SD_CARD, 50);
-			if (retval < 0) {
-				rtsx_clear_sd_error(chip);
-
-				chip->rw_need_retry = 1;
-				sd_set_err_code(chip, SD_TO_ERR);
-				TRACE_GOTO(chip, RW_FAIL);
-			}
-
-			retval = wait_data_buf_ready(chip);
-			if (retval != STATUS_SUCCESS) {
-				chip->rw_need_retry = 1;
-				sd_set_err_code(chip, SD_TO_ERR);
-				TRACE_GOTO(chip, RW_FAIL);
-			}
-
-			retval = sd_send_cmd_get_rsp(chip, WRITE_MULTIPLE_BLOCK,
-					data_addr, SD_RSP_TYPE_R1, NULL, 0);
-			if (retval != STATUS_SUCCESS) {
-				chip->rw_need_retry = 1;
-				TRACE_GOTO(chip, RW_FAIL);
-			}
-
-			rtsx_init_cmd(chip);
-
-			cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
-					SD_NO_CHECK_CRC7 | SD_RSP_LEN_0;
-			if (CHECK_PID(chip, 0x5209)) {
-				if (!CHK_SD30_SPEED(sd_card))
-					cfg2 |= SD_NO_CHECK_WAIT_CRC_TO;
-			}
-			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2);
-
-			trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512, DMA_512);
-
-			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
-				     SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
-			rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
-				     SD_TRANSFER_END, SD_TRANSFER_END);
-
-			rtsx_send_cmd_no_wait(chip);
-		}
-
-		sd_card->seq_mode = 1;
-	}
-
-	retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), scsi_bufflen(srb),
-			scsi_sg_count(srb), srb->sc_data_direction, chip->sd_timeout);
-	if (retval < 0) {
-		u8 stat = 0;
-		int err;
-
-		sd_card->seq_mode = 0;
-
-		if (retval == -ETIMEDOUT)
-			err = STATUS_TIMEDOUT;
-		else
-			err = STATUS_FAIL;
-
-		rtsx_read_register(chip, REG_SD_STAT1, &stat);
-		rtsx_clear_sd_error(chip);
-		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
-			chip->rw_need_retry = 0;
-			RTSX_DEBUGP("No card exist, exit sd_rw\n");
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		chip->rw_need_retry = 1;
-
-		retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, SD_RSP_TYPE_R1b, NULL, 0);
-		if (retval != STATUS_SUCCESS) {
-			sd_set_err_code(chip, SD_STS_ERR);
-			TRACE_GOTO(chip, RW_FAIL);
-		}
-
-		if (stat & (SD_CRC7_ERR | SD_CRC16_ERR | SD_CRC_WRITE_ERR)) {
-			RTSX_DEBUGP("SD CRC error, tune clock!\n");
-			sd_set_err_code(chip, SD_CRC_ERR);
-			TRACE_GOTO(chip, RW_FAIL);
-		}
-
-		if (err == STATUS_TIMEDOUT) {
-			sd_set_err_code(chip, SD_TO_ERR);
-			TRACE_GOTO(chip, RW_FAIL);
-		}
-
-		TRACE_RET(chip, err);
-	}
-
-	sd_card->pre_sec_addr = start_sector;
-	sd_card->pre_sec_cnt = sector_cnt;
-	sd_card->pre_dir = srb->sc_data_direction;
-
-	return STATUS_SUCCESS;
-
-RW_FAIL:
-	sd_card->seq_mode = 0;
-
-	if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
-		chip->rw_need_retry = 0;
-		RTSX_DEBUGP("No card exist, exit sd_rw\n");
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (sd_check_err_code(chip, SD_CRC_ERR)) {
-		if (CHK_MMC_4BIT(sd_card) || CHK_MMC_8BIT(sd_card)) {
-			sd_card->mmc_dont_switch_bus = 1;
-			reset_mmc_only(chip);
-			sd_card->mmc_dont_switch_bus = 0;
-		} else {
-			sd_card->need_retune = 1;
-			sd_auto_tune_clock(chip);
-		}
-	} else if (sd_check_err_code(chip, SD_TO_ERR | SD_STS_ERR)) {
-		retval = reset_sd_card(chip);
-		if (retval != STATUS_SUCCESS) {
-			chip->card_ready &= ~SD_CARD;
-			chip->card_fail |= SD_CARD;
-			chip->capacity[chip->card2lun[SD_CARD]] = 0;
-		}
-	}
-
-	TRACE_RET(chip, STATUS_FAIL);
-}
-
-#ifdef SUPPORT_CPRM
-int soft_reset_sd_card(struct rtsx_chip *chip)
-{
-	return reset_sd(chip);
-}
-
-int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
-		u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, int special_check)
-{
-	int retval;
-	int timeout = 100;
-	u16 reg_addr;
-	u8 *ptr;
-	int stat_idx = 0;
-	int rty_cnt = 0;
-
-	RTSX_DEBUGP("EXT SD/MMC CMD %d\n", cmd_idx);
-
-	if (rsp_type == SD_RSP_TYPE_R1b)
-		timeout = 3000;
-
-RTY_SEND_CMD:
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
-			0x01, PINGPONG_BUFFER);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
-			0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
-
-	if (rsp_type == SD_RSP_TYPE_R2) {
-		for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++)
-			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
-		stat_idx = 17;
-	} else if (rsp_type != SD_RSP_TYPE_R0) {
-		for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++)
-			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
-		stat_idx = 6;
-	}
-	rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0, 0);
-
-	rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0);
-
-	retval = rtsx_send_cmd(chip, SD_CARD, timeout);
-	if (retval < 0) {
-		if (retval == -ETIMEDOUT) {
-			rtsx_clear_sd_error(chip);
-
-			if (rsp_type & SD_WAIT_BUSY_END) {
-				retval = sd_check_data0_status(chip);
-				if (retval != STATUS_SUCCESS)
-					TRACE_RET(chip, retval);
-			} else {
-				sd_set_err_code(chip, SD_TO_ERR);
-			}
-		}
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (rsp_type == SD_RSP_TYPE_R0)
-		return STATUS_SUCCESS;
-
-	ptr = rtsx_get_cmd_data(chip) + 1;
-
-	if ((ptr[0] & 0xC0) != 0) {
-		sd_set_err_code(chip, SD_STS_ERR);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (!(rsp_type & SD_NO_CHECK_CRC7)) {
-		if (ptr[stat_idx] & SD_CRC7_ERR) {
-			if (cmd_idx == WRITE_MULTIPLE_BLOCK) {
-				sd_set_err_code(chip, SD_CRC_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			if (rty_cnt < SD_MAX_RETRY_COUNT) {
-				wait_timeout(20);
-				rty_cnt++;
-				goto RTY_SEND_CMD;
-			} else {
-				sd_set_err_code(chip, SD_CRC_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-	}
-
-	if ((cmd_idx == SELECT_CARD) || (cmd_idx == APP_CMD) ||
-			(cmd_idx == SEND_STATUS) || (cmd_idx == STOP_TRANSMISSION)) {
-		if ((cmd_idx != STOP_TRANSMISSION) && (special_check == 0)) {
-			if (ptr[1] & 0x80)
-				TRACE_RET(chip, STATUS_FAIL);
-		}
-#ifdef SUPPORT_SD_LOCK
-		if (ptr[1] & 0x7D)
-#else
-		if (ptr[1] & 0x7F)
-#endif
-		{
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-		if (ptr[2] & 0xF8)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		if (cmd_idx == SELECT_CARD) {
-			if (rsp_type == SD_RSP_TYPE_R2) {
-				if ((ptr[3] & 0x1E) != 0x04)
-					TRACE_RET(chip, STATUS_FAIL);
-
-			} else if (rsp_type == SD_RSP_TYPE_R0) {
-				if ((ptr[3] & 0x1E) != 0x03)
-					TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-	}
-
-	if (rsp && rsp_len)
-		memcpy(rsp, ptr, rsp_len);
-
-	return STATUS_SUCCESS;
-}
-
-int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type)
-{
-	int retval, rsp_len;
-	u16 reg_addr;
-
-	if (rsp_type == SD_RSP_TYPE_R0)
-		return STATUS_SUCCESS;
-
-	rtsx_init_cmd(chip);
-
-	if (rsp_type == SD_RSP_TYPE_R2) {
-		for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++)
-			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0);
-
-		rsp_len = 17;
-	} else if (rsp_type != SD_RSP_TYPE_R0) {
-		for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++)
-			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0);
-
-		rsp_len = 6;
-	}
-	rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0xFF, 0);
-
-	retval = rtsx_send_cmd(chip, SD_CARD, 100);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (rsp) {
-		int min_len = (rsp_len < len) ? rsp_len : len;
-
-		memcpy(rsp, rtsx_get_cmd_data(chip), min_len);
-
-		RTSX_DEBUGP("min_len = %d\n", min_len);
-		RTSX_DEBUGP("Response in cmd buf: 0x%x 0x%x 0x%x 0x%x\n",
-			rsp[0], rsp[1], rsp[2], rsp[3]);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	unsigned int lun = SCSI_LUN(srb);
-	int len;
-	u8 buf[18] = {
-		0x00,
-		0x00,
-		0x00,
-		0x0E,
-		0x00,
-		0x00,
-		0x00,
-		0x00,
-		0x53,
-		0x44,
-		0x20,
-		0x43,
-		0x61,
-		0x72,
-		0x64,
-		0x00,
-		0x00,
-		0x00,
-	};
-
-	sd_card->pre_cmd_err = 0;
-
-	if (!(CHK_BIT(chip->lun_mc, lun))) {
-		SET_BIT(chip->lun_mc, lun);
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) || (0x20 != srb->cmnd[4]) ||
-			(0x43 != srb->cmnd[5]) || (0x61 != srb->cmnd[6]) ||
-			(0x72 != srb->cmnd[7]) || (0x64 != srb->cmnd[8])) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	switch (srb->cmnd[1] & 0x0F) {
-	case 0:
-		sd_card->sd_pass_thru_en = 0;
-		break;
-
-	case 1:
-		sd_card->sd_pass_thru_en = 1;
-		break;
-
-	default:
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	buf[5] = (1 == CHK_SD(sd_card)) ?  0x01 : 0x02;
-	if (chip->card_wp & SD_CARD)
-		buf[5] |= 0x80;
-
-	buf[6] = (u8)(sd_card->sd_addr >> 16);
-	buf[7] = (u8)(sd_card->sd_addr >> 24);
-
-	buf[15] = chip->max_lun;
-
-	len = min(18, (int)scsi_bufflen(srb));
-	rtsx_stor_set_xfer_buf(buf, len, srb);
-
-	return TRANSPORT_GOOD;
-}
-
-static inline int get_rsp_type(struct scsi_cmnd *srb, u8 *rsp_type, int *rsp_len)
-{
-	if (!rsp_type || !rsp_len)
-		return STATUS_FAIL;
-
-	switch (srb->cmnd[10]) {
-	case 0x03:
-		*rsp_type = SD_RSP_TYPE_R0;
-		*rsp_len = 0;
-		break;
-
-	case 0x04:
-		*rsp_type = SD_RSP_TYPE_R1;
-		*rsp_len = 6;
-		break;
-
-	case 0x05:
-		*rsp_type = SD_RSP_TYPE_R1b;
-		*rsp_len = 6;
-		break;
-
-	case 0x06:
-		*rsp_type = SD_RSP_TYPE_R2;
-		*rsp_len = 17;
-		break;
-
-	case 0x07:
-		*rsp_type = SD_RSP_TYPE_R3;
-		*rsp_len = 6;
-		break;
-
-	default:
-		return STATUS_FAIL;
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	unsigned int lun = SCSI_LUN(srb);
-	int retval, rsp_len;
-	u8 cmd_idx, rsp_type;
-	u8 standby = 0, acmd = 0;
-	u32 arg;
-
-	if (!sd_card->sd_pass_thru_en) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	retval = sd_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, TRANSPORT_FAILED);
-
-	if (sd_card->pre_cmd_err) {
-		sd_card->pre_cmd_err = 0;
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	cmd_idx = srb->cmnd[2] & 0x3F;
-	if (srb->cmnd[1] & 0x02)
-		standby = 1;
-
-	if (srb->cmnd[1] & 0x01)
-		acmd = 1;
-
-	arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) |
-		((u32)srb->cmnd[5] << 8) | srb->cmnd[6];
-
-	retval = get_rsp_type(srb, &rsp_type, &rsp_len);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-	sd_card->last_rsp_type = rsp_type;
-
-	retval = sd_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, TRANSPORT_FAILED);
-
-#ifdef SUPPORT_SD_LOCK
-	if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
-		if (CHK_MMC_8BIT(sd_card)) {
-			retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_8);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, TRANSPORT_FAILED);
-
-		} else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
-			retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	}
-#else
-	retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, TRANSPORT_FAILED);
-#endif
-
-	if (standby) {
-		retval = sd_select_card(chip, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
-	}
-
-	if (acmd) {
-		retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
-				SD_RSP_TYPE_R1, NULL, 0, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
-	}
-
-	retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type,
-			sd_card->rsp, rsp_len, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
-
-	if (standby) {
-		retval = sd_select_card(chip, 1);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
-	}
-
-#ifdef SUPPORT_SD_LOCK
-	retval = sd_update_lock_status(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
-#endif
-
-	scsi_set_resid(srb, 0);
-	return TRANSPORT_GOOD;
-
-SD_Execute_Cmd_Failed:
-	sd_card->pre_cmd_err = 1;
-	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
-	release_sd_card(chip);
-	do_reset_sd_card(chip);
-	if (!(chip->card_ready & SD_CARD))
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-
-	TRACE_RET(chip, TRANSPORT_FAILED);
-}
-
-int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	unsigned int lun = SCSI_LUN(srb);
-	int retval, rsp_len, i;
-	int cmd13_checkbit = 0, read_err = 0;
-	u8 cmd_idx, rsp_type, bus_width;
-	u8 send_cmd12 = 0, standby = 0, acmd = 0;
-	u32 data_len;
-
-	if (!sd_card->sd_pass_thru_en) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (sd_card->pre_cmd_err) {
-		sd_card->pre_cmd_err = 0;
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	retval = sd_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, TRANSPORT_FAILED);
-
-	cmd_idx = srb->cmnd[2] & 0x3F;
-	if (srb->cmnd[1] & 0x04)
-		send_cmd12 = 1;
-
-	if (srb->cmnd[1] & 0x02)
-		standby = 1;
-
-	if (srb->cmnd[1] & 0x01)
-		acmd = 1;
-
-	data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8] << 8) | srb->cmnd[9];
-
-	retval = get_rsp_type(srb, &rsp_type, &rsp_len);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-	sd_card->last_rsp_type = rsp_type;
-
-	retval = sd_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, TRANSPORT_FAILED);
-
-#ifdef SUPPORT_SD_LOCK
-	if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
-		if (CHK_MMC_8BIT(sd_card))
-			bus_width = SD_BUS_WIDTH_8;
-		else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card))
-			bus_width = SD_BUS_WIDTH_4;
-		else
-			bus_width = SD_BUS_WIDTH_1;
-	} else {
-		bus_width = SD_BUS_WIDTH_4;
-	}
-	RTSX_DEBUGP("bus_width = %d\n", bus_width);
-#else
-	bus_width = SD_BUS_WIDTH_4;
-#endif
-
-	if (data_len < 512) {
-		retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
-				SD_RSP_TYPE_R1, NULL, 0, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
-	}
-
-	if (standby) {
-		retval = sd_select_card(chip, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
-	}
-
-	if (acmd) {
-		retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
-				SD_RSP_TYPE_R1, NULL, 0, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
-	}
-
-	if (data_len <= 512) {
-		int min_len;
-		u8 *buf;
-		u16 byte_cnt, blk_cnt;
-		u8 cmd[5];
-
-		byte_cnt = ((u16)(srb->cmnd[8] & 0x03) << 8) | srb->cmnd[9];
-		blk_cnt = 1;
-
-		cmd[0] = 0x40 | cmd_idx;
-		cmd[1] = srb->cmnd[3];
-		cmd[2] = srb->cmnd[4];
-		cmd[3] = srb->cmnd[5];
-		cmd[4] = srb->cmnd[6];
-
-		buf = kmalloc(data_len, GFP_KERNEL);
-		if (buf == NULL)
-			TRACE_RET(chip, TRANSPORT_ERROR);
-
-		retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, byte_cnt,
-				       blk_cnt, bus_width, buf, data_len, 2000);
-		if (retval != STATUS_SUCCESS) {
-			read_err = 1;
-			kfree(buf);
-			rtsx_clear_sd_error(chip);
-			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
-		}
-
-		min_len = min(data_len, scsi_bufflen(srb));
-		rtsx_stor_set_xfer_buf(buf, min_len, srb);
-
-		kfree(buf);
-	} else if (!(data_len & 0x1FF)) {
-		rtsx_init_cmd(chip);
-
-		trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H,
-				0xFF, (srb->cmnd[7] & 0xFE) >> 1);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L,
-				0xFF, (u8)((data_len & 0x0001FE00) >> 9));
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, srb->cmnd[3]);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, srb->cmnd[4]);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, srb->cmnd[5]);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, srb->cmnd[6]);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
-			     0xFF, SD_TM_AUTO_READ_2 | SD_TRANSFER_START);
-		rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
-
-		rtsx_send_cmd_no_wait(chip);
-
-		retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), scsi_bufflen(srb),
-			scsi_sg_count(srb), DMA_FROM_DEVICE, 10000);
-		if (retval < 0) {
-			read_err = 1;
-			rtsx_clear_sd_error(chip);
-			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
-		}
-
-	} else {
-		TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
-	}
-
-	retval = ext_sd_get_rsp(chip, rsp_len, sd_card->rsp, rsp_type);
-	if (retval != STATUS_SUCCESS)
-		TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
-
-	if (standby) {
-		retval = sd_select_card(chip, 1);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
-	}
-
-	if (send_cmd12) {
-		retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION,
-				0, SD_RSP_TYPE_R1b, NULL, 0, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
-	}
-
-	if (data_len < 512) {
-		retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200,
-				SD_RSP_TYPE_R1, NULL, 0, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
-
-		retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
-
-		retval = rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
-	}
-
-	if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04))
-		cmd13_checkbit = 1;
-
-	for (i = 0; i < 3; i++) {
-		retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
-			SD_RSP_TYPE_R1, NULL, 0, cmd13_checkbit);
-		if (retval == STATUS_SUCCESS)
-			break;
-	}
-	if (retval != STATUS_SUCCESS)
-		TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
-
-	scsi_set_resid(srb, 0);
-	return TRANSPORT_GOOD;
-
-SD_Execute_Read_Cmd_Failed:
-	sd_card->pre_cmd_err = 1;
-	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
-	if (read_err)
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-
-	release_sd_card(chip);
-	do_reset_sd_card(chip);
-	if (!(chip->card_ready & SD_CARD))
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-
-	TRACE_RET(chip, TRANSPORT_FAILED);
-}
-
-int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	unsigned int lun = SCSI_LUN(srb);
-	int retval, rsp_len, i;
-	int cmd13_checkbit = 0, write_err = 0;
-	u8 cmd_idx, rsp_type;
-	u8 send_cmd12 = 0, standby = 0, acmd = 0;
-	u32 data_len, arg;
-#ifdef SUPPORT_SD_LOCK
-	int lock_cmd_fail = 0;
-	u8 sd_lock_state = 0;
-	u8 lock_cmd_type = 0;
-#endif
-
-	if (!sd_card->sd_pass_thru_en) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (sd_card->pre_cmd_err) {
-		sd_card->pre_cmd_err = 0;
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	retval = sd_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, TRANSPORT_FAILED);
-
-	cmd_idx = srb->cmnd[2] & 0x3F;
-	if (srb->cmnd[1] & 0x04)
-		send_cmd12 = 1;
-
-	if (srb->cmnd[1] & 0x02)
-		standby = 1;
-
-	if (srb->cmnd[1] & 0x01)
-		acmd = 1;
-
-	data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8] << 8) | srb->cmnd[9];
-	arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) |
-		((u32)srb->cmnd[5] << 8) | srb->cmnd[6];
-
-#ifdef SUPPORT_SD_LOCK
-	if (cmd_idx == LOCK_UNLOCK) {
-		sd_lock_state = sd_card->sd_lock_status;
-		sd_lock_state &= SD_LOCKED;
-	}
-#endif
-
-	retval = get_rsp_type(srb, &rsp_type, &rsp_len);
-	if (retval != STATUS_SUCCESS) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-	sd_card->last_rsp_type = rsp_type;
-
-	retval = sd_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, TRANSPORT_FAILED);
-
-#ifdef SUPPORT_SD_LOCK
-	if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
-		if (CHK_MMC_8BIT(sd_card)) {
-			retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_8);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, TRANSPORT_FAILED);
-
-		} else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
-			retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-	}
-#else
-	retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, TRANSPORT_FAILED);
-#endif
-
-	if (data_len < 512) {
-		retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
-				SD_RSP_TYPE_R1, NULL, 0, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-	}
-
-	if (standby) {
-		retval = sd_select_card(chip, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-	}
-
-	if (acmd) {
-		retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
-				SD_RSP_TYPE_R1, NULL, 0, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-	}
-
-	retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type,
-			sd_card->rsp, rsp_len, 0);
-	if (retval != STATUS_SUCCESS)
-		TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-
-	if (data_len <= 512) {
-		u16 i;
-		u8 *buf;
-
-		buf = kmalloc(data_len, GFP_KERNEL);
-		if (buf == NULL)
-			TRACE_RET(chip, TRANSPORT_ERROR);
-
-		rtsx_stor_get_xfer_buf(buf, data_len, srb);
-
-#ifdef SUPPORT_SD_LOCK
-		if (cmd_idx == LOCK_UNLOCK)
-			lock_cmd_type = buf[0] & 0x0F;
-#endif
-
-		if (data_len > 256) {
-			rtsx_init_cmd(chip);
-			for (i = 0; i < 256; i++) {
-				rtsx_add_cmd(chip, WRITE_REG_CMD,
-						PPBUF_BASE2 + i, 0xFF, buf[i]);
-			}
-			retval = rtsx_send_cmd(chip, 0, 250);
-			if (retval != STATUS_SUCCESS) {
-				kfree(buf);
-				TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-			}
-
-			rtsx_init_cmd(chip);
-			for (i = 256; i < data_len; i++) {
-				rtsx_add_cmd(chip, WRITE_REG_CMD,
-						PPBUF_BASE2 + i, 0xFF, buf[i]);
-			}
-			retval = rtsx_send_cmd(chip, 0, 250);
-			if (retval != STATUS_SUCCESS) {
-				kfree(buf);
-				TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-			}
-		} else {
-			rtsx_init_cmd(chip);
-			for (i = 0; i < data_len; i++) {
-				rtsx_add_cmd(chip, WRITE_REG_CMD,
-						PPBUF_BASE2 + i, 0xFF, buf[i]);
-			}
-			retval = rtsx_send_cmd(chip, 0, 250);
-			if (retval != STATUS_SUCCESS) {
-				kfree(buf);
-				TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-			}
-		}
-
-		kfree(buf);
-
-		rtsx_init_cmd(chip);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, srb->cmnd[8] & 0x03);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, srb->cmnd[9]);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0x00);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 0x01);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
-			     SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
-		rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
-
-		retval = rtsx_send_cmd(chip, SD_CARD, 250);
-	} else if (!(data_len & 0x1FF)) {
-		rtsx_init_cmd(chip);
-
-		trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H,
-				0xFF, (srb->cmnd[7] & 0xFE) >> 1);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L,
-				0xFF, (u8)((data_len & 0x0001FE00) >> 9));
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
-		rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
-
-		rtsx_send_cmd_no_wait(chip);
-
-		retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), scsi_bufflen(srb),
-			scsi_sg_count(srb), DMA_TO_DEVICE, 10000);
-
-	} else {
-		TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-	}
-
-	if (retval < 0) {
-		write_err = 1;
-		rtsx_clear_sd_error(chip);
-		TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-	}
-
-#ifdef SUPPORT_SD_LOCK
-	if (cmd_idx == LOCK_UNLOCK) {
-		if (lock_cmd_type == SD_ERASE) {
-			sd_card->sd_erase_status = SD_UNDER_ERASING;
-			scsi_set_resid(srb, 0);
-			return TRANSPORT_GOOD;
-		}
-
-		rtsx_init_cmd(chip);
-		if (CHECK_PID(chip, 0x5209))
-			rtsx_add_cmd(chip, CHECK_REG_CMD, SD_BUS_STAT, SD_DAT0_STATUS, SD_DAT0_STATUS);
-		else
-			rtsx_add_cmd(chip, CHECK_REG_CMD, 0xFD30, 0x02, 0x02);
-
-		rtsx_send_cmd(chip, SD_CARD, 250);
-
-		retval = sd_update_lock_status(chip);
-		if (retval != STATUS_SUCCESS) {
-			RTSX_DEBUGP("Lock command fail!\n");
-			lock_cmd_fail = 1;
-		}
-	}
-#endif /* SUPPORT_SD_LOCK */
-
-	if (standby) {
-		retval = sd_select_card(chip, 1);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-	}
-
-	if (send_cmd12) {
-		retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION,
-				0, SD_RSP_TYPE_R1b, NULL, 0, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-	}
-
-	if (data_len < 512) {
-		retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200,
-				SD_RSP_TYPE_R1, NULL, 0, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-
-		retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-
-		rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00);
-		if (retval != STATUS_SUCCESS)
-			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-	}
-
-	if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04))
-		cmd13_checkbit = 1;
-
-	for (i = 0; i < 3; i++) {
-		retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
-			SD_RSP_TYPE_R1, NULL, 0, cmd13_checkbit);
-		if (retval == STATUS_SUCCESS)
-			break;
-	}
-	if (retval != STATUS_SUCCESS)
-		TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-
-#ifdef SUPPORT_SD_LOCK
-	if (cmd_idx == LOCK_UNLOCK) {
-		if (!lock_cmd_fail) {
-			RTSX_DEBUGP("lock_cmd_type = 0x%x\n", lock_cmd_type);
-			if (lock_cmd_type & SD_CLR_PWD)
-				sd_card->sd_lock_status &= ~SD_PWD_EXIST;
-
-			if (lock_cmd_type & SD_SET_PWD)
-				sd_card->sd_lock_status |= SD_PWD_EXIST;
-		}
-
-		RTSX_DEBUGP("sd_lock_state = 0x%x, sd_card->sd_lock_status = 0x%x\n",
-			     sd_lock_state, sd_card->sd_lock_status);
-		if (sd_lock_state ^ (sd_card->sd_lock_status & SD_LOCKED)) {
-			sd_card->sd_lock_notify = 1;
-			if (sd_lock_state) {
-				if (sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) {
-					sd_card->sd_lock_status |= (SD_UNLOCK_POW_ON | SD_SDR_RST);
-					if (CHK_SD(sd_card)) {
-						retval = reset_sd(chip);
-						if (retval != STATUS_SUCCESS) {
-							sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST);
-							TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
-						}
-					}
-
-					sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST);
-				}
-			}
-		}
-	}
-
-	if (lock_cmd_fail) {
-		scsi_set_resid(srb, 0);
-		set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-#endif  /* SUPPORT_SD_LOCK */
-
-	scsi_set_resid(srb, 0);
-	return TRANSPORT_GOOD;
-
-SD_Execute_Write_Cmd_Failed:
-	sd_card->pre_cmd_err = 1;
-	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
-	if (write_err)
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-
-	release_sd_card(chip);
-	do_reset_sd_card(chip);
-	if (!(chip->card_ready & SD_CARD))
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-
-	TRACE_RET(chip, TRANSPORT_FAILED);
-}
-
-int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	unsigned int lun = SCSI_LUN(srb);
-	int count;
-	u16 data_len;
-
-	if (!sd_card->sd_pass_thru_en) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (sd_card->pre_cmd_err) {
-		sd_card->pre_cmd_err = 0;
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	data_len = ((u16)srb->cmnd[7] << 8) | srb->cmnd[8];
-
-	if (sd_card->last_rsp_type == SD_RSP_TYPE_R0) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	} else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2) {
-		count = (data_len < 17) ? data_len : 17;
-	} else {
-		count = (data_len < 6) ? data_len : 6;
-	}
-	rtsx_stor_set_xfer_buf(sd_card->rsp, count, srb);
-
-	RTSX_DEBUGP("Response length: %d\n", data_len);
-	RTSX_DEBUGP("Response: 0x%x 0x%x 0x%x 0x%x\n",
-		sd_card->rsp[0], sd_card->rsp[1], sd_card->rsp[2], sd_card->rsp[3]);
-
-	scsi_set_resid(srb, 0);
-	return TRANSPORT_GOOD;
-}
-
-int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	unsigned int lun = SCSI_LUN(srb);
-	int retval;
-
-	if (!sd_card->sd_pass_thru_en) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if (sd_card->pre_cmd_err) {
-		sd_card->pre_cmd_err = 0;
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) || (0x20 != srb->cmnd[4]) ||
-			(0x43 != srb->cmnd[5]) || (0x61 != srb->cmnd[6]) ||
-			(0x72 != srb->cmnd[7]) || (0x64 != srb->cmnd[8])) {
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	switch (srb->cmnd[1] & 0x0F) {
-	case 0:
-#ifdef SUPPORT_SD_LOCK
-		if (0x64 == srb->cmnd[9])
-			sd_card->sd_lock_status |= SD_SDR_RST;
-#endif
-		retval = reset_sd_card(chip);
-		if (retval != STATUS_SUCCESS) {
-#ifdef SUPPORT_SD_LOCK
-			sd_card->sd_lock_status &= ~SD_SDR_RST;
-#endif
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-			sd_card->pre_cmd_err = 1;
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-#ifdef SUPPORT_SD_LOCK
-		sd_card->sd_lock_status &= ~SD_SDR_RST;
-#endif
-		break;
-
-	case 1:
-		retval = soft_reset_sd_card(chip);
-		if (retval != STATUS_SUCCESS) {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-			sd_card->pre_cmd_err = 1;
-			TRACE_RET(chip, TRANSPORT_FAILED);
-		}
-		break;
-
-	default:
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
-		TRACE_RET(chip, TRANSPORT_FAILED);
-	}
-
-	scsi_set_resid(srb, 0);
-	return TRANSPORT_GOOD;
-}
-#endif
-
-void sd_cleanup_work(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-
-	if (sd_card->seq_mode) {
-		RTSX_DEBUGP("SD: stop transmission\n");
-		sd_stop_seq_mode(chip);
-		sd_card->cleanup_counter = 0;
-	}
-}
-
-int sd_power_off_card3v3(struct rtsx_chip *chip)
-{
-	int retval;
-
-	retval = disable_card_clock(chip, SD_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_WRITE_REG(chip, CARD_OE, SD_OUTPUT_EN, 0);
-
-	if (!chip->ft2_fast_mode) {
-		retval = card_power_off(chip, SD_CARD);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		wait_timeout(50);
-	}
-
-	if (chip->asic_code) {
-		retval = sd_pull_ctl_disable(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	} else {
-		RTSX_WRITE_REG(chip, FPGA_PULL_CTL,
-			FPGA_SD_PULL_CTL_BIT | 0x20, FPGA_SD_PULL_CTL_BIT);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int release_sd_card(struct rtsx_chip *chip)
-{
-	struct sd_info *sd_card = &(chip->sd_card);
-	int retval;
-
-	RTSX_DEBUGP("release_sd_card\n");
-
-	chip->card_ready &= ~SD_CARD;
-	chip->card_fail &= ~SD_CARD;
-	chip->card_wp &= ~SD_CARD;
-
-	chip->sd_io = 0;
-	chip->sd_int = 0;
-
-#ifdef SUPPORT_SD_LOCK
-	sd_card->sd_lock_status = 0;
-	sd_card->sd_erase_status = 0;
-#endif
-
-	memset(sd_card->raw_csd, 0, 16);
-	memset(sd_card->raw_scr, 0, 8);
-
-	retval = sd_power_off_card3v3(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (CHECK_PID(chip, 0x5209)) {
-		retval = sd_change_bank_voltage(chip, SD_IO_3V3);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		if (CHK_SD30_SPEED(sd_card))
-			RTSX_WRITE_REG(chip, SD30_DRIVE_SEL, 0x07, chip->sd30_drive_sel_3v3);
-
-		RTSX_WRITE_REG(chip, OCPPARA2, SD_OCP_THD_MASK, chip->sd_400mA_ocp_thd);
-	}
-
-	return STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rts_pstor/sd.h b/drivers/staging/rts_pstor/sd.h
deleted file mode 100644
index 1df1aa7..0000000
--- a/drivers/staging/rts_pstor/sd.h
+++ /dev/null
@@ -1,300 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- * Header file
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#ifndef __REALTEK_RTSX_SD_H
-#define __REALTEK_RTSX_SD_H
-
-#include "rtsx_chip.h"
-
-#define SUPPORT_VOLTAGE	0x003C0000
-
-/* Error Code */
-#define	SD_NO_ERROR		0x0
-#define	SD_CRC_ERR		0x80
-#define	SD_TO_ERR		0x40
-#define	SD_NO_CARD		0x20
-#define SD_BUSY			0x10
-#define	SD_STS_ERR		0x08
-#define SD_RSP_TIMEOUT		0x04
-#define SD_IO_ERR		0x02
-
-/* Return code for MMC switch bus */
-#define SWITCH_SUCCESS		0
-#define SWITCH_ERR		1
-#define SWITCH_FAIL		2
-
-/* MMC/SD Command Index */
-/* Basic command (class 0) */
-#define GO_IDLE_STATE		0
-#define	SEND_OP_COND		1
-#define	ALL_SEND_CID		2
-#define	SET_RELATIVE_ADDR	3
-#define	SEND_RELATIVE_ADDR	3
-#define	SET_DSR			4
-#define IO_SEND_OP_COND		5
-#define	SWITCH			6
-#define	SELECT_CARD		7
-#define	DESELECT_CARD		7
-/* CMD8 is "SEND_EXT_CSD" for MMC4.x Spec
- * while is "SEND_IF_COND" for SD 2.0
- */
-#define	SEND_EXT_CSD		8
-#define	SEND_IF_COND		8
-
-#define	SEND_CSD		9
-#define	SEND_CID		10
-#define	VOLTAGE_SWITCH	    	11
-#define	READ_DAT_UTIL_STOP	11
-#define	STOP_TRANSMISSION	12
-#define	SEND_STATUS		13
-#define	GO_INACTIVE_STATE	15
-
-#define	SET_BLOCKLEN		16
-#define	READ_SINGLE_BLOCK	17
-#define	READ_MULTIPLE_BLOCK	18
-#define	SEND_TUNING_PATTERN	19
-
-#define	BUSTEST_R		14
-#define	BUSTEST_W		19
-
-#define	WRITE_BLOCK		24
-#define	WRITE_MULTIPLE_BLOCK	25
-#define	PROGRAM_CSD		27
-
-#define	ERASE_WR_BLK_START	32
-#define	ERASE_WR_BLK_END	33
-#define	ERASE_CMD		38
-
-#define LOCK_UNLOCK 		42
-#define	IO_RW_DIRECT		52
-
-#define	APP_CMD			55
-#define	GEN_CMD			56
-
-#define	SET_BUS_WIDTH		6
-#define	SD_STATUS		13
-#define	SEND_NUM_WR_BLOCKS	22
-#define	SET_WR_BLK_ERASE_COUNT	23
-#define	SD_APP_OP_COND		41
-#define	SET_CLR_CARD_DETECT	42
-#define	SEND_SCR		51
-
-#define	SD_READ_COMPLETE	0x00
-#define	SD_READ_TO		0x01
-#define	SD_READ_ADVENCE		0x02
-
-#define	SD_CHECK_MODE		0x00
-#define	SD_SWITCH_MODE		0x80
-#define	SD_FUNC_GROUP_1	    	0x01
-#define	SD_FUNC_GROUP_2	    	0x02
-#define	SD_FUNC_GROUP_3	    	0x03
-#define	SD_FUNC_GROUP_4	    	0x04
-#define	SD_CHECK_SPEC_V1_1	0xFF
-
-#define	NO_ARGUMENT	                        0x00
-#define	CHECK_PATTERN	                    	0x000000AA
-#define	VOLTAGE_SUPPLY_RANGE	            	0x00000100
-#define	SUPPORT_HIGH_AND_EXTENDED_CAPACITY	0x40000000
-#define	SUPPORT_MAX_POWER_PERMANCE	        0x10000000
-#define	SUPPORT_1V8	                        0x01000000
-
-#define	SWTICH_NO_ERR	  	0x00
-#define	CARD_NOT_EXIST	  	0x01
-#define	SPEC_NOT_SUPPORT  	0x02
-#define	CHECK_MODE_ERR	  	0x03
-#define	CHECK_NOT_READY	  	0x04
-#define	SWITCH_CRC_ERR	  	0x05
-#define	SWITCH_MODE_ERR	  	0x06
-#define	SWITCH_PASS		0x07
-
-#ifdef SUPPORT_SD_LOCK
-#define SD_ERASE		0x08
-#define SD_LOCK			0x04
-#define SD_UNLOCK		0x00
-#define SD_CLR_PWD		0x02
-#define SD_SET_PWD		0x01
-
-#define SD_PWD_LEN		0x10
-
-#define SD_LOCKED		0x80
-#define SD_LOCK_1BIT_MODE	0x40
-#define SD_PWD_EXIST		0x20
-#define SD_UNLOCK_POW_ON	0x01
-#define SD_SDR_RST		0x02
-
-#define SD_NOT_ERASE		0x00
-#define SD_UNDER_ERASING	0x01
-#define SD_COMPLETE_ERASE	0x02
-
-#define SD_RW_FORBIDDEN		0x0F
-
-#endif
-
-#define	HS_SUPPORT			0x01
-#define	SDR50_SUPPORT			0x02
-#define	SDR104_SUPPORT	        	0x03
-#define	DDR50_SUPPORT		    	0x04
-
-#define	HS_SUPPORT_MASK	        	0x02
-#define	SDR50_SUPPORT_MASK	    	0x04
-#define	SDR104_SUPPORT_MASK	    	0x08
-#define	DDR50_SUPPORT_MASK	    	0x10
-
-#define	HS_QUERY_SWITCH_OK	    	0x01
-#define	SDR50_QUERY_SWITCH_OK		0x02
-#define	SDR104_QUERY_SWITCH_OK  	0x03
-#define	DDR50_QUERY_SWITCH_OK   	0x04
-
-#define	HS_SWITCH_BUSY	        	0x02
-#define	SDR50_SWITCH_BUSY	    	0x04
-#define	SDR104_SWITCH_BUSY      	0x08
-#define	DDR50_SWITCH_BUSY       	0x10
-
-#define	FUNCTION_GROUP1_SUPPORT_OFFSET       0x0D
-#define FUNCTION_GROUP1_QUERY_SWITCH_OFFSET  0x10
-#define FUNCTION_GROUP1_CHECK_BUSY_OFFSET    0x1D
-
-#define	DRIVING_TYPE_A	        0x01
-#define	DRIVING_TYPE_B		    0x00
-#define	DRIVING_TYPE_C		    0x02
-#define	DRIVING_TYPE_D	        0x03
-
-#define	DRIVING_TYPE_A_MASK	    0x02
-#define	DRIVING_TYPE_B_MASK	    0x01
-#define	DRIVING_TYPE_C_MASK	    0x04
-#define	DRIVING_TYPE_D_MASK	    0x08
-
-#define	TYPE_A_QUERY_SWITCH_OK	0x01
-#define	TYPE_B_QUERY_SWITCH_OK	0x00
-#define	TYPE_C_QUERY_SWITCH_OK  0x02
-#define	TYPE_D_QUERY_SWITCH_OK  0x03
-
-#define	TYPE_A_SWITCH_BUSY	    0x02
-#define	TYPE_B_SWITCH_BUSY	    0x01
-#define	TYPE_C_SWITCH_BUSY      0x04
-#define	TYPE_D_SWITCH_BUSY      0x08
-
-#define	FUNCTION_GROUP3_SUPPORT_OFFSET       0x09
-#define FUNCTION_GROUP3_QUERY_SWITCH_OFFSET  0x0F
-#define FUNCTION_GROUP3_CHECK_BUSY_OFFSET    0x19
-
-#define	CURRENT_LIMIT_200	    0x00
-#define	CURRENT_LIMIT_400	    0x01
-#define	CURRENT_LIMIT_600	    0x02
-#define	CURRENT_LIMIT_800	    0x03
-
-#define	CURRENT_LIMIT_200_MASK	0x01
-#define	CURRENT_LIMIT_400_MASK	0x02
-#define	CURRENT_LIMIT_600_MASK	0x04
-#define	CURRENT_LIMIT_800_MASK	0x08
-
-#define	CURRENT_LIMIT_200_QUERY_SWITCH_OK    0x00
-#define	CURRENT_LIMIT_400_QUERY_SWITCH_OK    0x01
-#define	CURRENT_LIMIT_600_QUERY_SWITCH_OK    0x02
-#define	CURRENT_LIMIT_800_QUERY_SWITCH_OK    0x03
-
-#define	CURRENT_LIMIT_200_SWITCH_BUSY        0x01
-#define	CURRENT_LIMIT_400_SWITCH_BUSY	     0x02
-#define	CURRENT_LIMIT_600_SWITCH_BUSY        0x04
-#define	CURRENT_LIMIT_800_SWITCH_BUSY        0x08
-
-#define	FUNCTION_GROUP4_SUPPORT_OFFSET       0x07
-#define FUNCTION_GROUP4_QUERY_SWITCH_OFFSET  0x0F
-#define FUNCTION_GROUP4_CHECK_BUSY_OFFSET    0x17
-
-#define	DATA_STRUCTURE_VER_OFFSET	0x11
-
-#define MAX_PHASE			31
-
-#define MMC_8BIT_BUS			0x0010
-#define MMC_4BIT_BUS			0x0020
-
-#define MMC_SWITCH_ERR			0x80
-
-#define SD_IO_3V3		0
-#define SD_IO_1V8		1
-
-#define TUNE_TX    0x00
-#define TUNE_RX	   0x01
-
-#define CHANGE_TX  0x00
-#define CHANGE_RX  0x01
-
-#define DCM_HIGH_FREQUENCY_MODE  0x00
-#define DCM_LOW_FREQUENCY_MODE   0x01
-
-#define DCM_HIGH_FREQUENCY_MODE_SET  0x0C
-#define DCM_Low_FREQUENCY_MODE_SET   0x00
-
-#define MULTIPLY_BY_1    0x00
-#define MULTIPLY_BY_2    0x01
-#define MULTIPLY_BY_3    0x02
-#define MULTIPLY_BY_4    0x03
-#define MULTIPLY_BY_5    0x04
-#define MULTIPLY_BY_6    0x05
-#define MULTIPLY_BY_7    0x06
-#define MULTIPLY_BY_8    0x07
-#define MULTIPLY_BY_9    0x08
-#define MULTIPLY_BY_10   0x09
-
-#define DIVIDE_BY_2      0x01
-#define DIVIDE_BY_3      0x02
-#define DIVIDE_BY_4      0x03
-#define DIVIDE_BY_5      0x04
-#define DIVIDE_BY_6      0x05
-#define DIVIDE_BY_7      0x06
-#define DIVIDE_BY_8      0x07
-#define DIVIDE_BY_9      0x08
-#define DIVIDE_BY_10     0x09
-
-struct timing_phase_path {
-	int start;
-	int end;
-	int mid;
-	int len;
-};
-
-int sd_select_card(struct rtsx_chip *chip, int select);
-int sd_pull_ctl_enable(struct rtsx_chip *chip);
-int reset_sd_card(struct rtsx_chip *chip);
-int sd_switch_clock(struct rtsx_chip *chip);
-void sd_stop_seq_mode(struct rtsx_chip *chip);
-int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt);
-void sd_cleanup_work(struct rtsx_chip *chip);
-int sd_power_off_card3v3(struct rtsx_chip *chip);
-int release_sd_card(struct rtsx_chip *chip);
-#ifdef SUPPORT_CPRM
-int soft_reset_sd_card(struct rtsx_chip *chip);
-int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
-		u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, int special_check);
-int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type);
-
-int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-#endif
-
-#endif  /* __REALTEK_RTSX_SD_H */
diff --git a/drivers/staging/rts_pstor/spi.c b/drivers/staging/rts_pstor/spi.c
deleted file mode 100644
index 6b36cc5..0000000
--- a/drivers/staging/rts_pstor/spi.c
+++ /dev/null
@@ -1,812 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-
-#include "rtsx.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
-#include "spi.h"
-
-static inline void spi_set_err_code(struct rtsx_chip *chip, u8 err_code)
-{
-	struct spi_info *spi = &(chip->spi);
-
-	spi->err_code = err_code;
-}
-
-static int spi_init(struct rtsx_chip *chip)
-{
-	RTSX_WRITE_REG(chip, SPI_CONTROL, 0xFF,
-		CS_POLARITY_LOW | DTO_MSB_FIRST | SPI_MASTER | SPI_MODE0 | SPI_AUTO);
-	RTSX_WRITE_REG(chip, SPI_TCTL, EDO_TIMING_MASK, SAMPLE_DELAY_HALF);
-
-	return STATUS_SUCCESS;
-}
-
-static int spi_set_init_para(struct rtsx_chip *chip)
-{
-	struct spi_info *spi = &(chip->spi);
-	int retval;
-
-	RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER1, 0xFF, (u8)(spi->clk_div >> 8));
-	RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER0, 0xFF, (u8)(spi->clk_div));
-
-	retval = switch_clock(chip, spi->spi_clock);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = select_card(chip, SPI_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_WRITE_REG(chip, CARD_CLK_EN, SPI_CLK_EN, SPI_CLK_EN);
-	RTSX_WRITE_REG(chip, CARD_OE, SPI_OUTPUT_EN, SPI_OUTPUT_EN);
-
-	wait_timeout(10);
-
-	retval = spi_init(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int sf_polling_status(struct rtsx_chip *chip, int msec)
-{
-	int retval;
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, SPI_RDSR);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_POLLING_MODE0);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
-
-	retval = rtsx_send_cmd(chip, 0, msec);
-	if (retval < 0) {
-		rtsx_clear_spi_error(chip);
-		spi_set_err_code(chip, SPI_BUSY_ERR);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int sf_enable_write(struct rtsx_chip *chip, u8 ins)
-{
-	struct spi_info *spi = &(chip->spi);
-	int retval;
-
-	if (!spi->write_en)
-		return STATUS_SUCCESS;
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_C_MODE0);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
-
-	retval = rtsx_send_cmd(chip, 0, 100);
-	if (retval < 0) {
-		rtsx_clear_spi_error(chip);
-		spi_set_err_code(chip, SPI_HW_ERR);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int sf_disable_write(struct rtsx_chip *chip, u8 ins)
-{
-	struct spi_info *spi = &(chip->spi);
-	int retval;
-
-	if (!spi->write_en)
-		return STATUS_SUCCESS;
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_C_MODE0);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
-
-	retval = rtsx_send_cmd(chip, 0, 100);
-	if (retval < 0) {
-		rtsx_clear_spi_error(chip);
-		spi_set_err_code(chip, SPI_HW_ERR);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static void sf_program(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr, u16 len)
-{
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, (u8)len);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, (u8)(len >> 8));
-	if (addr_mode) {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 16));
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CADO_MODE0);
-	} else {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CDO_MODE0);
-	}
-	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
-}
-
-static int sf_erase(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr)
-{
-	int retval;
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
-	if (addr_mode) {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 16));
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
-	} else {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_C_MODE0);
-	}
-	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
-
-	retval = rtsx_send_cmd(chip, 0, 100);
-	if (retval < 0) {
-		rtsx_clear_spi_error(chip);
-		spi_set_err_code(chip, SPI_HW_ERR);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int spi_init_eeprom(struct rtsx_chip *chip)
-{
-	int retval;
-	int clk;
-
-	if (chip->asic_code)
-		clk = 30;
-	else
-		clk = CLK_30;
-
-	RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER1, 0xFF, 0x00);
-	RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER0, 0xFF, 0x27);
-
-	retval = switch_clock(chip, clk);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = select_card(chip, SPI_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_WRITE_REG(chip, CARD_CLK_EN, SPI_CLK_EN, SPI_CLK_EN);
-	RTSX_WRITE_REG(chip, CARD_OE, SPI_OUTPUT_EN, SPI_OUTPUT_EN);
-
-	wait_timeout(10);
-
-	RTSX_WRITE_REG(chip, SPI_CONTROL, 0xFF, CS_POLARITY_HIGH | SPI_EEPROM_AUTO);
-	RTSX_WRITE_REG(chip, SPI_TCTL, EDO_TIMING_MASK, SAMPLE_DELAY_HALF);
-
-	return STATUS_SUCCESS;
-}
-
-static int spi_eeprom_program_enable(struct rtsx_chip *chip)
-{
-	int retval;
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x86);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x13);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
-
-	retval = rtsx_send_cmd(chip, 0, 100);
-	if (retval < 0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-int spi_erase_eeprom_chip(struct rtsx_chip *chip)
-{
-	int retval;
-
-	retval = spi_init_eeprom(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = spi_eeprom_program_enable(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x12);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x84);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
-
-	retval = rtsx_send_cmd(chip, 0, 100);
-	if (retval < 0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01);
-
-	return STATUS_SUCCESS;
-}
-
-int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr)
-{
-	int retval;
-
-	retval = spi_init_eeprom(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = spi_eeprom_program_enable(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x07);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
-
-	retval = rtsx_send_cmd(chip, 0, 100);
-	if (retval < 0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01);
-
-	return STATUS_SUCCESS;
-}
-
-
-int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val)
-{
-	int retval;
-	u8 data;
-
-	retval = spi_init_eeprom(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x06);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CADI_MODE0);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
-
-	retval = rtsx_send_cmd(chip, 0, 100);
-	if (retval < 0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	wait_timeout(5);
-	RTSX_READ_REG(chip, SPI_DATA, &data);
-
-	if (val)
-		*val = data;
-
-	RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01);
-
-	return STATUS_SUCCESS;
-}
-
-int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val)
-{
-	int retval;
-
-	retval = spi_init_eeprom(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = spi_eeprom_program_enable(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x05);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, val);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)addr);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 8));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x4E);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
-
-	retval = rtsx_send_cmd(chip, 0, 100);
-	if (retval < 0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01);
-
-	return STATUS_SUCCESS;
-}
-
-
-int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct spi_info *spi = &(chip->spi);
-
-	RTSX_DEBUGP("spi_get_status: err_code = 0x%x\n", spi->err_code);
-	rtsx_stor_set_xfer_buf(&(spi->err_code), min((int)scsi_bufflen(srb), 1), srb);
-	scsi_set_resid(srb, scsi_bufflen(srb) - 1);
-
-	return STATUS_SUCCESS;
-}
-
-int spi_set_parameter(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	struct spi_info *spi = &(chip->spi);
-
-	spi_set_err_code(chip, SPI_NO_ERR);
-
-	if (chip->asic_code)
-		spi->spi_clock = ((u16)(srb->cmnd[8]) << 8) | srb->cmnd[9];
-	else
-		spi->spi_clock = srb->cmnd[3];
-
-	spi->clk_div = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
-	spi->write_en = srb->cmnd[6];
-
-	RTSX_DEBUGP("spi_set_parameter: spi_clock = %d, clk_div = %d, write_en = %d\n",
-		     spi->spi_clock, spi->clk_div, spi->write_en);
-
-	return STATUS_SUCCESS;
-}
-
-int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int retval;
-	u16 len;
-	u8 *buf;
-
-	spi_set_err_code(chip, SPI_NO_ERR);
-
-	len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
-	if (len > 512) {
-		spi_set_err_code(chip, SPI_INVALID_COMMAND);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	retval = spi_set_init_para(chip);
-	if (retval != STATUS_SUCCESS) {
-		spi_set_err_code(chip, SPI_HW_ERR);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, srb->cmnd[3]);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, srb->cmnd[4]);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, srb->cmnd[5]);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, srb->cmnd[6]);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, srb->cmnd[7]);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, srb->cmnd[8]);
-
-	if (len == 0) {
-		if (srb->cmnd[9]) {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,
-				      0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
-		} else {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,
-				      0xFF, SPI_TRANSFER0_START | SPI_C_MODE0);
-		}
-	} else {
-		if (srb->cmnd[9]) {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,
-				      0xFF, SPI_TRANSFER0_START | SPI_CADI_MODE0);
-		} else {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,
-				      0xFF, SPI_TRANSFER0_START | SPI_CDI_MODE0);
-		}
-	}
-
-	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
-
-	retval = rtsx_send_cmd(chip, 0, 100);
-	if (retval < 0) {
-		rtsx_clear_spi_error(chip);
-		spi_set_err_code(chip, SPI_HW_ERR);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (len) {
-		buf = kmalloc(len, GFP_KERNEL);
-		if (!buf)
-			TRACE_RET(chip, STATUS_ERROR);
-
-		retval = rtsx_read_ppbuf(chip, buf, len);
-		if (retval != STATUS_SUCCESS) {
-			spi_set_err_code(chip, SPI_READ_ERR);
-			kfree(buf);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
-		scsi_set_resid(srb, 0);
-
-		kfree(buf);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int retval;
-	unsigned int index = 0, offset = 0;
-	u8 ins, slow_read;
-	u32 addr;
-	u16 len;
-	u8 *buf;
-
-	spi_set_err_code(chip, SPI_NO_ERR);
-
-	ins = srb->cmnd[3];
-	addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5]) << 8) | srb->cmnd[6];
-	len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
-	slow_read = srb->cmnd[9];
-
-	retval = spi_set_init_para(chip);
-	if (retval != STATUS_SUCCESS) {
-		spi_set_err_code(chip, SPI_HW_ERR);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	buf = kmalloc(SF_PAGE_LEN, GFP_KERNEL);
-	if (buf == NULL)
-		TRACE_RET(chip, STATUS_ERROR);
-
-	while (len) {
-		u16 pagelen = SF_PAGE_LEN - (u8)addr;
-
-		if (pagelen > len)
-			pagelen = len;
-
-		rtsx_init_cmd(chip);
-
-		trans_dma_enable(DMA_FROM_DEVICE, chip, 256, DMA_256);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
-
-		if (slow_read) {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
-			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
-			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 16));
-			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
-		} else {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)addr);
-			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 8));
-			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR3, 0xFF, (u8)(addr >> 16));
-			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_32);
-		}
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, (u8)(pagelen >> 8));
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, (u8)pagelen);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CADI_MODE0);
-		rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
-
-		rtsx_send_cmd_no_wait(chip);
-
-		retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0, DMA_FROM_DEVICE, 10000);
-		if (retval < 0) {
-			kfree(buf);
-			rtsx_clear_spi_error(chip);
-			spi_set_err_code(chip, SPI_HW_ERR);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index, &offset, TO_XFER_BUF);
-
-		addr += pagelen;
-		len -= pagelen;
-	}
-
-	scsi_set_resid(srb, 0);
-	kfree(buf);
-
-	return STATUS_SUCCESS;
-}
-
-int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int retval;
-	u8 ins, program_mode;
-	u32 addr;
-	u16 len;
-	u8 *buf;
-	unsigned int index = 0, offset = 0;
-
-	spi_set_err_code(chip, SPI_NO_ERR);
-
-	ins = srb->cmnd[3];
-	addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5]) << 8) | srb->cmnd[6];
-	len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
-	program_mode = srb->cmnd[9];
-
-	retval = spi_set_init_para(chip);
-	if (retval != STATUS_SUCCESS) {
-		spi_set_err_code(chip, SPI_HW_ERR);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (program_mode == BYTE_PROGRAM) {
-		buf = kmalloc(4, GFP_KERNEL);
-		if (!buf)
-			TRACE_RET(chip, STATUS_ERROR);
-
-		while (len) {
-			retval = sf_enable_write(chip, SPI_WREN);
-			if (retval != STATUS_SUCCESS) {
-				kfree(buf);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset, FROM_XFER_BUF);
-
-			rtsx_init_cmd(chip);
-
-			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
-			rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, buf[0]);
-			sf_program(chip, ins, 1, addr, 1);
-
-			retval = rtsx_send_cmd(chip, 0, 100);
-			if (retval < 0) {
-				kfree(buf);
-				rtsx_clear_spi_error(chip);
-				spi_set_err_code(chip, SPI_HW_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			retval = sf_polling_status(chip, 100);
-			if (retval != STATUS_SUCCESS) {
-				kfree(buf);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			addr++;
-			len--;
-		}
-
-		kfree(buf);
-
-	} else if (program_mode == AAI_PROGRAM) {
-		int first_byte = 1;
-
-		retval = sf_enable_write(chip, SPI_WREN);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		buf = kmalloc(4, GFP_KERNEL);
-		if (!buf)
-			TRACE_RET(chip, STATUS_ERROR);
-
-		while (len) {
-			rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset, FROM_XFER_BUF);
-
-			rtsx_init_cmd(chip);
-
-			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
-			rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, buf[0]);
-			if (first_byte) {
-				sf_program(chip, ins, 1, addr, 1);
-				first_byte = 0;
-			} else {
-				sf_program(chip, ins, 0, 0, 1);
-			}
-
-			retval = rtsx_send_cmd(chip, 0, 100);
-			if (retval < 0) {
-				kfree(buf);
-				rtsx_clear_spi_error(chip);
-				spi_set_err_code(chip, SPI_HW_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			retval = sf_polling_status(chip, 100);
-			if (retval != STATUS_SUCCESS) {
-				kfree(buf);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			len--;
-		}
-
-		kfree(buf);
-
-		retval = sf_disable_write(chip, SPI_WRDI);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = sf_polling_status(chip, 100);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	} else if (program_mode == PAGE_PROGRAM) {
-		buf = kmalloc(SF_PAGE_LEN, GFP_KERNEL);
-		if (!buf)
-			TRACE_RET(chip, STATUS_NOMEM);
-
-		while (len) {
-			u16 pagelen = SF_PAGE_LEN - (u8)addr;
-
-			if (pagelen > len)
-				pagelen = len;
-
-			retval = sf_enable_write(chip, SPI_WREN);
-			if (retval != STATUS_SUCCESS) {
-				kfree(buf);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			rtsx_init_cmd(chip);
-
-			trans_dma_enable(DMA_TO_DEVICE, chip, 256, DMA_256);
-			sf_program(chip, ins, 1, addr, pagelen);
-
-			rtsx_send_cmd_no_wait(chip);
-
-			rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index, &offset, FROM_XFER_BUF);
-
-			retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0, DMA_TO_DEVICE, 100);
-			if (retval < 0) {
-				kfree(buf);
-				rtsx_clear_spi_error(chip);
-				spi_set_err_code(chip, SPI_HW_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			retval = sf_polling_status(chip, 100);
-			if (retval != STATUS_SUCCESS) {
-				kfree(buf);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			addr += pagelen;
-			len -= pagelen;
-		}
-
-		kfree(buf);
-	} else {
-		spi_set_err_code(chip, SPI_INVALID_COMMAND);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int retval;
-	u8 ins, erase_mode;
-	u32 addr;
-
-	spi_set_err_code(chip, SPI_NO_ERR);
-
-	ins = srb->cmnd[3];
-	addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5]) << 8) | srb->cmnd[6];
-	erase_mode = srb->cmnd[9];
-
-	retval = spi_set_init_para(chip);
-	if (retval != STATUS_SUCCESS) {
-		spi_set_err_code(chip, SPI_HW_ERR);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	if (erase_mode == PAGE_ERASE) {
-		retval = sf_enable_write(chip, SPI_WREN);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = sf_erase(chip, ins, 1, addr);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	} else if (erase_mode == CHIP_ERASE) {
-		retval = sf_enable_write(chip, SPI_WREN);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = sf_erase(chip, ins, 0, 0);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	} else {
-		spi_set_err_code(chip, SPI_INVALID_COMMAND);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-	int retval;
-	u8 ins, status, ewsr;
-
-	ins = srb->cmnd[3];
-	status = srb->cmnd[4];
-	ewsr = srb->cmnd[5];
-
-	retval = spi_set_init_para(chip);
-	if (retval != STATUS_SUCCESS) {
-		spi_set_err_code(chip, SPI_HW_ERR);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	retval = sf_enable_write(chip, ewsr);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, 0);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, status);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CDO_MODE0);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
-
-	retval = rtsx_send_cmd(chip, 0, 100);
-	if (retval != STATUS_SUCCESS) {
-		rtsx_clear_spi_error(chip);
-		spi_set_err_code(chip, SPI_HW_ERR);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
diff --git a/drivers/staging/rts_pstor/spi.h b/drivers/staging/rts_pstor/spi.h
deleted file mode 100644
index b59291f..0000000
--- a/drivers/staging/rts_pstor/spi.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- * Header file
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#ifndef __REALTEK_RTSX_SPI_H
-#define __REALTEK_RTSX_SPI_H
-
-/* SPI operation error */
-#define SPI_NO_ERR		0x00
-#define SPI_HW_ERR		0x01
-#define SPI_INVALID_COMMAND	0x02
-#define SPI_READ_ERR		0x03
-#define SPI_WRITE_ERR		0x04
-#define SPI_ERASE_ERR		0x05
-#define SPI_BUSY_ERR		0x06
-
-/* Serial flash instruction */
-#define SPI_READ 		0x03
-#define SPI_FAST_READ		0x0B
-#define SPI_WREN		0x06
-#define SPI_WRDI		0x04
-#define SPI_RDSR		0x05
-
-#define SF_PAGE_LEN		256
-
-#define BYTE_PROGRAM		0
-#define AAI_PROGRAM		1
-#define PAGE_PROGRAM		2
-
-#define PAGE_ERASE		0
-#define CHIP_ERASE		1
-
-int spi_erase_eeprom_chip(struct rtsx_chip *chip);
-int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr);
-int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val);
-int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val);
-int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_set_parameter(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-
-
-#endif  /* __REALTEK_RTSX_SPI_H */
diff --git a/drivers/staging/rts_pstor/trace.h b/drivers/staging/rts_pstor/trace.h
deleted file mode 100644
index cf60a1b..0000000
--- a/drivers/staging/rts_pstor/trace.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- * Header file
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#ifndef __REALTEK_RTSX_TRACE_H
-#define __REALTEK_RTSX_TRACE_H
-
-#define _MSG_TRACE
-
-#ifdef _MSG_TRACE
-static inline char *filename(char *path)
-{
-	char *ptr;
-
-	if (path == NULL)
-		return NULL;
-
-	ptr = path;
-
-	while (*ptr != '\0') {
-		if ((*ptr == '\\') || (*ptr == '/'))
-			path = ptr + 1;
-		
-		ptr++;
-	}
-
-	return path;
-}
-
-#define TRACE_RET(chip, ret)   										\
-do {													\
-	char *_file = filename(__FILE__);								\
-	RTSX_DEBUGP("[%s][%s]:[%d]\n", _file, __func__, __LINE__);					\
-	(chip)->trace_msg[(chip)->msg_idx].line = (u16)(__LINE__);					\
-	strncpy((chip)->trace_msg[(chip)->msg_idx].func, __func__, MSG_FUNC_LEN-1);			\
-	strncpy((chip)->trace_msg[(chip)->msg_idx].file, _file, MSG_FILE_LEN-1); 			\
-	get_current_time((chip)->trace_msg[(chip)->msg_idx].timeval_buf, TIME_VAL_LEN);			\
-	(chip)->trace_msg[(chip)->msg_idx].valid = 1;							\
-	(chip)->msg_idx++; 										\
-	if ((chip)->msg_idx >= TRACE_ITEM_CNT) { 							\
-		(chip)->msg_idx = 0;									\
-	}												\
-	return ret; 											\
-} while (0)
-
-#define TRACE_GOTO(chip, label)   									\
-do {													\
-	char *_file = filename(__FILE__);								\
-	RTSX_DEBUGP("[%s][%s]:[%d]\n", _file, __func__, __LINE__);					\
-	(chip)->trace_msg[(chip)->msg_idx].line = (u16)(__LINE__);					\
-	strncpy((chip)->trace_msg[(chip)->msg_idx].func, __func__, MSG_FUNC_LEN-1);			\
-	strncpy((chip)->trace_msg[(chip)->msg_idx].file, _file, MSG_FILE_LEN-1); 			\
-	get_current_time((chip)->trace_msg[(chip)->msg_idx].timeval_buf, TIME_VAL_LEN);			\
-	(chip)->trace_msg[(chip)->msg_idx].valid = 1;							\
-	(chip)->msg_idx++; 										\
-	if ((chip)->msg_idx >= TRACE_ITEM_CNT) { 							\
-		(chip)->msg_idx = 0;									\
-	}												\
-	goto label; 											\
-} while (0)
-#else
-#define TRACE_RET(chip, ret)	return ret
-#define TRACE_GOTO(chip, label)	goto label
-#endif
-
-#ifdef CONFIG_RTS_PSTOR_DEBUG
-#define RTSX_DUMP(buf, buf_len)					\
-	print_hex_dump(KERN_DEBUG, RTSX_STOR, DUMP_PREFIX_NONE,	\
-				16, 1, (buf), (buf_len), false)
-#else
-#define RTSX_DUMP(buf, buf_len)
-#endif
-
-#endif  /* __REALTEK_RTSX_TRACE_H */
diff --git a/drivers/staging/rts_pstor/xd.c b/drivers/staging/rts_pstor/xd.c
deleted file mode 100644
index 9bba5b1..0000000
--- a/drivers/staging/rts_pstor/xd.c
+++ /dev/null
@@ -1,2052 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/vmalloc.h>
-
-#include "rtsx.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
-#include "xd.h"
-
-static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no);
-static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk, u16 logoff, u8 start_page, u8 end_page);
-
-static inline void xd_set_err_code(struct rtsx_chip *chip, u8 err_code)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-
-	xd_card->err_code = err_code;
-}
-
-static inline int xd_check_err_code(struct rtsx_chip *chip, u8 err_code)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-
-	return (xd_card->err_code == err_code);
-}
-
-static int xd_set_init_para(struct rtsx_chip *chip)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	int retval;
-
-	if (chip->asic_code)
-		xd_card->xd_clock = 47;
-	else
-		xd_card->xd_clock = CLK_50;
-
-	retval = switch_clock(chip, xd_card->xd_clock);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int xd_switch_clock(struct rtsx_chip *chip)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	int retval;
-
-	retval = select_card(chip, XD_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = switch_clock(chip, xd_card->xd_clock);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int xd_read_id(struct rtsx_chip *chip, u8 id_cmd, u8 *id_buf, u8 buf_len)
-{
-	int retval, i;
-	u8 *ptr;
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, id_cmd);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_READ_ID);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
-
-	for (i = 0; i < 4; i++)
-		rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_ADDRESS1 + i), 0, 0);
-
-	retval = rtsx_send_cmd(chip, XD_CARD, 20);
-	if (retval < 0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ptr = rtsx_get_cmd_data(chip) + 1;
-	if (id_buf && buf_len) {
-		if (buf_len > 4)
-			buf_len = 4;
-		memcpy(id_buf, ptr, buf_len);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static void xd_assign_phy_addr(struct rtsx_chip *chip, u32 addr, u8 mode)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-
-	switch (mode) {
-	case XD_RW_ADDR:
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, 0);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, 0xFF, (u8)addr);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2, 0xFF, (u8)(addr >> 8));
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS3, 0xFF, (u8)(addr >> 16));
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF,
-				xd_card->addr_cycle | XD_CALC_ECC | XD_BA_NO_TRANSFORM);
-		break;
-
-	case XD_ERASE_ADDR:
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, (u8)addr);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, 0xFF, (u8)(addr >> 8));
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2, 0xFF, (u8)(addr >> 16));
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF,
-				(xd_card->addr_cycle - 1) | XD_CALC_ECC | XD_BA_NO_TRANSFORM);
-		break;
-
-	default:
-		break;
-	}
-}
-
-static int xd_read_redundant(struct rtsx_chip *chip, u32 page_addr, u8 *buf, int buf_len)
-{
-	int retval, i;
-
-	rtsx_init_cmd(chip);
-
-	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_READ_REDUNDANT);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
-
-	for (i = 0; i < 6; i++)
-		rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_PAGE_STATUS + i), 0, 0);
-	for (i = 0; i < 4; i++)
-		rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_RESERVED0 + i), 0, 0);
-	rtsx_add_cmd(chip, READ_REG_CMD, XD_PARITY, 0, 0);
-
-	retval = rtsx_send_cmd(chip, XD_CARD, 500);
-	if (retval < 0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (buf && buf_len) {
-		u8 *ptr = rtsx_get_cmd_data(chip) + 1;
-
-		if (buf_len > 11)
-			buf_len = 11;
-		memcpy(buf, ptr, buf_len);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int xd_read_data_from_ppb(struct rtsx_chip *chip, int offset, u8 *buf, int buf_len)
-{
-	int retval, i;
-
-	if (!buf || (buf_len < 0))
-		TRACE_RET(chip, STATUS_FAIL);
-
-	rtsx_init_cmd(chip);
-
-	for (i = 0; i < buf_len; i++)
-		rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + offset + i, 0, 0);
-
-	retval = rtsx_send_cmd(chip, 0, 250);
-	if (retval < 0) {
-		rtsx_clear_xd_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	memcpy(buf, rtsx_get_cmd_data(chip), buf_len);
-
-	return STATUS_SUCCESS;
-}
-
-static int xd_read_cis(struct rtsx_chip *chip, u32 page_addr, u8 *buf, int buf_len)
-{
-	int retval;
-	u8 reg;
-
-	if (!buf || (buf_len < 10))
-		TRACE_RET(chip, STATUS_FAIL);
-
-	rtsx_init_cmd(chip);
-
-	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_READ_PAGES);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
-
-	retval = rtsx_send_cmd(chip, XD_CARD, 250);
-	if (retval == -ETIMEDOUT) {
-		rtsx_clear_xd_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	RTSX_READ_REG(chip, XD_PAGE_STATUS, &reg);
-	if (reg != XD_GPG) {
-		rtsx_clear_xd_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	RTSX_READ_REG(chip, XD_CTL, &reg);
-	if (!(reg & XD_ECC1_ERROR) || !(reg & XD_ECC1_UNCORRECTABLE)) {
-		retval = xd_read_data_from_ppb(chip, 0, buf, buf_len);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-		if (reg & XD_ECC1_ERROR) {
-			u8 ecc_bit, ecc_byte;
-
-			RTSX_READ_REG(chip, XD_ECC_BIT1, &ecc_bit);
-			RTSX_READ_REG(chip, XD_ECC_BYTE1, &ecc_byte);
-
-			RTSX_DEBUGP("ECC_BIT1 = 0x%x, ECC_BYTE1 = 0x%x\n", ecc_bit, ecc_byte);
-			if (ecc_byte < buf_len) {
-				RTSX_DEBUGP("Before correct: 0x%x\n", buf[ecc_byte]);
-				buf[ecc_byte] ^= (1 << ecc_bit);
-				RTSX_DEBUGP("After correct: 0x%x\n", buf[ecc_byte]);
-			}
-		}
-	} else if (!(reg & XD_ECC2_ERROR) || !(reg & XD_ECC2_UNCORRECTABLE)) {
-		rtsx_clear_xd_error(chip);
-
-		retval = xd_read_data_from_ppb(chip, 256, buf, buf_len);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-		if (reg & XD_ECC2_ERROR) {
-			u8 ecc_bit, ecc_byte;
-
-			RTSX_READ_REG(chip, XD_ECC_BIT2, &ecc_bit);
-			RTSX_READ_REG(chip, XD_ECC_BYTE2, &ecc_byte);
-
-			RTSX_DEBUGP("ECC_BIT2 = 0x%x, ECC_BYTE2 = 0x%x\n", ecc_bit, ecc_byte);
-			if (ecc_byte < buf_len) {
-				RTSX_DEBUGP("Before correct: 0x%x\n", buf[ecc_byte]);
-				buf[ecc_byte] ^= (1 << ecc_bit);
-				RTSX_DEBUGP("After correct: 0x%x\n", buf[ecc_byte]);
-			}
-		}
-	} else {
-		rtsx_clear_xd_error(chip);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static void xd_fill_pull_ctl_disable(struct rtsx_chip *chip)
-{
-	if (CHECK_PID(chip, 0x5209)) {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xD5);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x15);
-	} else if (CHECK_PID(chip, 0x5208)) {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
-			XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
-			XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
-			XD_WP_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
-			XD_RDY_PD | XD_WE_PD | XD_RE_PD | XD_ALE_PD);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
-			MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD);
-	} else if (CHECK_PID(chip, 0x5288)) {
-		if (CHECK_BARO_PKG(chip, QFN)) {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55);
-			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
-			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x4B);
-			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x69);
-		}
-	}
-}
-
-static void xd_fill_pull_ctl_stage1_barossa(struct rtsx_chip *chip)
-{
-	if (CHECK_BARO_PKG(chip, QFN)) {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x4B);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
-	}
-}
-
-static void xd_fill_pull_ctl_enable(struct rtsx_chip *chip)
-{
-	if (CHECK_PID(chip, 0x5209)) {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xAA);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xD5);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x15);
-	} else if (CHECK_PID(chip, 0x5208)) {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
-			XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
-			XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
-			XD_WP_PD | XD_CE_PU | XD_CLE_PD | XD_CD_PU);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
-			XD_RDY_PU | XD_WE_PU | XD_RE_PU | XD_ALE_PD);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
-			MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD);
-	} else if (CHECK_PID(chip, 0x5288)) {
-		if (CHECK_BARO_PKG(chip, QFN)) {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55);
-			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
-			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x53);
-			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0xA9);
-		}
-	}
-}
-
-static int xd_pull_ctl_disable(struct rtsx_chip *chip)
-{
-	if (CHECK_PID(chip, 0x5209)) {
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0xD5);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x55);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF, 0x55);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF, 0x15);
-	} else if (CHECK_PID(chip, 0x5208)) {
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF,
-			XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF,
-			XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF,
-			XD_WP_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF,
-			XD_RDY_PD | XD_WE_PD | XD_RE_PD | XD_ALE_PD);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF,
-			MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
-		RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD);
-	} else if (CHECK_PID(chip, 0x5288)) {
-		if (CHECK_BARO_PKG(chip, QFN)) {
-			RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55);
-			RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55);
-			RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0x4B);
-			RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x69);
-		}
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static void xd_clear_dma_buffer(struct rtsx_chip *chip)
-{
-	if (CHECK_PID(chip, 0x5209)) {
-		int retval;
-		u8 *buf;
-
-		RTSX_DEBUGP("xD ECC error, dummy write!\n");
-
-		buf = kmalloc(512, GFP_KERNEL);
-		if (!buf)
-			return;
-
-		rtsx_init_cmd(chip);
-
-		trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, SD_CLK_EN);
-		if (chip->asic_code) {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0xAA);
-		} else {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL,
-					FPGA_SD_PULL_CTL_BIT, 0);
-		}
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, 0x03, SD_BUS_WIDTH_4);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
-			SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
-		rtsx_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
-
-		rtsx_send_cmd_no_wait(chip);
-
-		retval = rtsx_transfer_data(chip, SD_CARD, buf, 512, 0, DMA_TO_DEVICE, 100);
-		if (retval < 0) {
-			u8 val;
-
-			rtsx_read_register(chip, SD_STAT1, &val);
-			RTSX_DEBUGP("SD_STAT1: 0x%x\n", val);
-
-			rtsx_read_register(chip, SD_STAT2, &val);
-			RTSX_DEBUGP("SD_STAT2: 0x%x\n", val);
-
-			rtsx_read_register(chip, SD_BUS_STAT, &val);
-			RTSX_DEBUGP("SD_BUS_STAT: 0x%x\n", val);
-
-			rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, SD_STOP | SD_CLR_ERR);
-		}
-
-		kfree(buf);
-
-		if (chip->asic_code) {
-			rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF, 0x55);
-		} else {
-			rtsx_write_register(chip, FPGA_PULL_CTL,
-						FPGA_SD_PULL_CTL_BIT, FPGA_SD_PULL_CTL_BIT);
-		}
-		rtsx_write_register(chip, CARD_SELECT, 0x07, XD_MOD_SEL);
-		rtsx_write_register(chip, CARD_CLK_EN, SD_CLK_EN, 0);
-	}
-}
-
-static int reset_xd(struct rtsx_chip *chip)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	int retval, i, j;
-	u8 *ptr, id_buf[4], redunt[11];
-
-	retval = select_card(chip, XD_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, 0xFF, XD_PGSTS_NOT_FF);
-	if (chip->asic_code) {
-		if (!CHECK_PID(chip, 0x5288))
-			xd_fill_pull_ctl_disable(chip);
-		else
-			xd_fill_pull_ctl_stage1_barossa(chip);
-	} else {
-		rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF,
-			(FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN3) | 0x20);
-	}
-
-	if (!chip->ft2_fast_mode)
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_INIT, XD_NO_AUTO_PWR_OFF, 0);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, 0);
-
-	retval = rtsx_send_cmd(chip, XD_CARD, 100);
-	if (retval < 0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (!chip->ft2_fast_mode) {
-		retval = card_power_off(chip, XD_CARD);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		wait_timeout(250);
-
-		if (CHECK_PID(chip, 0x5209))
-			RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0xAA);
-
-		rtsx_init_cmd(chip);
-
-		if (chip->asic_code) {
-			xd_fill_pull_ctl_enable(chip);
-		} else {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF,
-				(FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN2) | 0x20);
-		}
-
-		retval = rtsx_send_cmd(chip, XD_CARD, 100);
-		if (retval < 0)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		retval = card_power_on(chip, XD_CARD);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-#ifdef SUPPORT_OCP
-		wait_timeout(50);
-		if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
-			RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", chip->ocp_stat);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-#endif
-	}
-
-	rtsx_init_cmd(chip);
-
-	if (chip->ft2_fast_mode) {
-		if (chip->asic_code) {
-			xd_fill_pull_ctl_enable(chip);
-		} else {
-			rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF,
-				(FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN2) | 0x20);
-		}
-	}
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, XD_OUTPUT_EN);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CTL, XD_CE_DISEN, XD_CE_DISEN);
-
-	retval = rtsx_send_cmd(chip, XD_CARD, 100);
-	if (retval < 0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if (!chip->ft2_fast_mode)
-		wait_timeout(200);
-
-	retval = xd_set_init_para(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	/* Read ID to check if the timing setting is right */
-	for (i = 0; i < 4; i++) {
-		rtsx_init_cmd(chip);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DTCTL, 0xFF,
-				XD_TIME_SETUP_STEP * 3 + XD_TIME_RW_STEP * (2 + i) + XD_TIME_RWN_STEP * i);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CATCTL, 0xFF,
-				XD_TIME_SETUP_STEP * 3 + XD_TIME_RW_STEP * (4 + i) + XD_TIME_RWN_STEP * (3 + i));
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_RESET);
-		rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
-
-		rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0);
-		rtsx_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0);
-
-		retval = rtsx_send_cmd(chip, XD_CARD, 100);
-		if (retval < 0)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		ptr = rtsx_get_cmd_data(chip) + 1;
-
-		RTSX_DEBUGP("XD_DAT: 0x%x, XD_CTL: 0x%x\n", ptr[0], ptr[1]);
-
-		if (((ptr[0] & READY_FLAG) != READY_STATE) || !(ptr[1] & XD_RDY))
-			continue;
-
-		retval = xd_read_id(chip, READ_ID, id_buf, 4);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		RTSX_DEBUGP("READ_ID: 0x%x 0x%x 0x%x 0x%x\n",
-					id_buf[0], id_buf[1], id_buf[2], id_buf[3]);
-
-		xd_card->device_code = id_buf[1];
-
-		/* Check if the xD card is supported */
-		switch (xd_card->device_code) {
-		case XD_4M_X8_512_1:
-		case XD_4M_X8_512_2:
-			xd_card->block_shift = 4;
-			xd_card->page_off = 0x0F;
-			xd_card->addr_cycle = 3;
-			xd_card->zone_cnt = 1;
-			xd_card->capacity = 8000;
-			XD_SET_4MB(xd_card);
-			break;
-		case XD_8M_X8_512:
-			xd_card->block_shift = 4;
-			xd_card->page_off = 0x0F;
-			xd_card->addr_cycle = 3;
-			xd_card->zone_cnt = 1;
-			xd_card->capacity = 16000;
-			break;
-		case XD_16M_X8_512:
-			XD_PAGE_512(xd_card);
-			xd_card->addr_cycle = 3;
-			xd_card->zone_cnt = 1;
-			xd_card->capacity = 32000;
-			break;
-		case XD_32M_X8_512:
-			XD_PAGE_512(xd_card);
-			xd_card->addr_cycle = 3;
-			xd_card->zone_cnt = 2;
-			xd_card->capacity = 64000;
-			break;
-		case XD_64M_X8_512:
-			XD_PAGE_512(xd_card);
-			xd_card->addr_cycle = 4;
-			xd_card->zone_cnt = 4;
-			xd_card->capacity = 128000;
-			break;
-		case XD_128M_X8_512:
-			XD_PAGE_512(xd_card);
-			xd_card->addr_cycle = 4;
-			xd_card->zone_cnt = 8;
-			xd_card->capacity = 256000;
-			break;
-		case XD_256M_X8_512:
-			XD_PAGE_512(xd_card);
-			xd_card->addr_cycle = 4;
-			xd_card->zone_cnt = 16;
-			xd_card->capacity = 512000;
-			break;
-		case XD_512M_X8:
-			XD_PAGE_512(xd_card);
-			xd_card->addr_cycle = 4;
-			xd_card->zone_cnt = 32;
-			xd_card->capacity = 1024000;
-			break;
-		case xD_1G_X8_512:
-			XD_PAGE_512(xd_card);
-			xd_card->addr_cycle = 4;
-			xd_card->zone_cnt = 64;
-			xd_card->capacity = 2048000;
-			break;
-		case xD_2G_X8_512:
-			XD_PAGE_512(xd_card);
-			xd_card->addr_cycle = 4;
-			xd_card->zone_cnt = 128;
-			xd_card->capacity = 4096000;
-			break;
-		default:
-			continue;
-		}
-
-		/* Confirm timing setting */
-		for (j = 0; j < 10; j++) {
-			retval = xd_read_id(chip, READ_ID, id_buf, 4);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-
-			if (id_buf[1] != xd_card->device_code)
-				break;
-		}
-
-		if (j == 10)
-			break;
-	}
-
-	if (i == 4) {
-		xd_card->block_shift = 0;
-		xd_card->page_off = 0;
-		xd_card->addr_cycle = 0;
-		xd_card->capacity = 0;
-
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	retval = xd_read_id(chip, READ_xD_ID, id_buf, 4);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-	RTSX_DEBUGP("READ_xD_ID: 0x%x 0x%x 0x%x 0x%x\n",
-			id_buf[0], id_buf[1], id_buf[2], id_buf[3]);
-	if (id_buf[2] != XD_ID_CODE)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	/* Search CIS block */
-	for (i = 0; i < 24; i++) {
-		u32 page_addr;
-
-		if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		page_addr = (u32)i << xd_card->block_shift;
-
-		for (j = 0; j < 3; j++) {
-			retval = xd_read_redundant(chip, page_addr, redunt, 11);
-			if (retval == STATUS_SUCCESS)
-				break;
-		}
-		if (j == 3)
-			continue;
-
-		if (redunt[BLOCK_STATUS] != XD_GBLK)
-			continue;
-
-		j = 0;
-		if (redunt[PAGE_STATUS] != XD_GPG) {
-			for (j = 1; j <= 8; j++) {
-				retval = xd_read_redundant(chip, page_addr + j, redunt, 11);
-				if (retval == STATUS_SUCCESS) {
-					if (redunt[PAGE_STATUS] == XD_GPG)
-						break;
-				}
-			}
-
-			if (j == 9)
-				break;
-		}
-
-		/* Check CIS data */
-		if ((redunt[BLOCK_STATUS] == XD_GBLK) && (redunt[PARITY] & XD_BA1_ALL0)) {
-			u8 buf[10];
-
-			page_addr += j;
-
-			retval = xd_read_cis(chip, page_addr, buf, 10);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-
-			if ((buf[0] == 0x01) && (buf[1] == 0x03) && (buf[2] == 0xD9)
-					&& (buf[3] == 0x01) && (buf[4] == 0xFF)
-					&& (buf[5] == 0x18) && (buf[6] == 0x02)
-					&& (buf[7] == 0xDF) && (buf[8] == 0x01)
-					&& (buf[9] == 0x20)) {
-				xd_card->cis_block = (u16)i;
-			}
-		}
-
-		break;
-	}
-
-	RTSX_DEBUGP("CIS block: 0x%x\n", xd_card->cis_block);
-	if (xd_card->cis_block == 0xFFFF)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	chip->capacity[chip->card2lun[XD_CARD]] = xd_card->capacity;
-
-	return STATUS_SUCCESS;
-}
-
-static int xd_check_data_blank(u8 *redunt)
-{
-	int i;
-
-	for (i = 0; i < 6; i++) {
-		if (redunt[PAGE_STATUS + i] != 0xFF)
-			return 0;
-	}
-
-	if ((redunt[PARITY] & (XD_ECC1_ALL1 | XD_ECC2_ALL1)) != (XD_ECC1_ALL1 | XD_ECC2_ALL1))
-		return 0;
-
-
-	for (i = 0; i < 4; i++) {
-		if (redunt[RESERVED0 + i] != 0xFF)
-			return 0;
-	}
-
-	return 1;
-}
-
-static u16 xd_load_log_block_addr(u8 *redunt)
-{
-	u16 addr = 0xFFFF;
-
-	if (redunt[PARITY] & XD_BA1_BA2_EQL)
-		addr = ((u16)redunt[BLOCK_ADDR1_H] << 8) | redunt[BLOCK_ADDR1_L];
-	else if (redunt[PARITY] & XD_BA1_VALID)
-		addr = ((u16)redunt[BLOCK_ADDR1_H] << 8) | redunt[BLOCK_ADDR1_L];
-	else if (redunt[PARITY] & XD_BA2_VALID)
-		addr = ((u16)redunt[BLOCK_ADDR2_H] << 8) | redunt[BLOCK_ADDR2_L];
-
-	return addr;
-}
-
-static int xd_init_l2p_tbl(struct rtsx_chip *chip)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	int size, i;
-
-	RTSX_DEBUGP("xd_init_l2p_tbl: zone_cnt = %d\n", xd_card->zone_cnt);
-
-	if (xd_card->zone_cnt < 1)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	size = xd_card->zone_cnt * sizeof(struct zone_entry);
-	RTSX_DEBUGP("Buffer size for l2p table is %d\n", size);
-
-	xd_card->zone = (struct zone_entry *)vmalloc(size);
-	if (!xd_card->zone)
-		TRACE_RET(chip, STATUS_ERROR);
-
-	for (i = 0; i < xd_card->zone_cnt; i++) {
-		xd_card->zone[i].build_flag = 0;
-		xd_card->zone[i].l2p_table = NULL;
-		xd_card->zone[i].free_table = NULL;
-		xd_card->zone[i].get_index = 0;
-		xd_card->zone[i].set_index = 0;
-		xd_card->zone[i].unused_blk_cnt = 0;
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static inline void free_zone(struct zone_entry *zone)
-{
-	RTSX_DEBUGP("free_zone\n");
-
-	if (!zone)
-		return;
-
-	zone->build_flag = 0;
-	zone->set_index = 0;
-	zone->get_index = 0;
-	zone->unused_blk_cnt = 0;
-	if (zone->l2p_table) {
-		vfree(zone->l2p_table);
-		zone->l2p_table = NULL;
-	}
-	if (zone->free_table) {
-		vfree(zone->free_table);
-		zone->free_table = NULL;
-	}
-}
-
-static void xd_set_unused_block(struct rtsx_chip *chip, u32 phy_blk)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	struct zone_entry *zone;
-	int zone_no;
-
-	zone_no = (int)phy_blk >> 10;
-	if (zone_no >= xd_card->zone_cnt) {
-		RTSX_DEBUGP("Set unused block to invalid zone (zone_no = %d, zone_cnt = %d)\n",
-			zone_no, xd_card->zone_cnt);
-		return;
-	}
-	zone = &(xd_card->zone[zone_no]);
-
-	if (zone->free_table == NULL) {
-		if (xd_build_l2p_tbl(chip, zone_no) != STATUS_SUCCESS)
-			return;
-	}
-
-	if ((zone->set_index >= XD_FREE_TABLE_CNT)
-			|| (zone->set_index < 0)) {
-		free_zone(zone);
-		RTSX_DEBUGP("Set unused block fail, invalid set_index\n");
-		return;
-	}
-
-	RTSX_DEBUGP("Set unused block to index %d\n", zone->set_index);
-
-	zone->free_table[zone->set_index++] = (u16) (phy_blk & 0x3ff);
-	if (zone->set_index >= XD_FREE_TABLE_CNT)
-		zone->set_index = 0;
-	zone->unused_blk_cnt++;
-}
-
-static u32 xd_get_unused_block(struct rtsx_chip *chip, int zone_no)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	struct zone_entry *zone;
-	u32 phy_blk;
-
-	if (zone_no >= xd_card->zone_cnt) {
-		RTSX_DEBUGP("Get unused block from invalid zone (zone_no = %d, zone_cnt = %d)\n",
-			zone_no, xd_card->zone_cnt);
-		return BLK_NOT_FOUND;
-	}
-	zone = &(xd_card->zone[zone_no]);
-
-	if ((zone->unused_blk_cnt == 0) || (zone->set_index == zone->get_index)) {
-		free_zone(zone);
-		RTSX_DEBUGP("Get unused block fail, no unused block available\n");
-		return BLK_NOT_FOUND;
-	}
-	if ((zone->get_index >= XD_FREE_TABLE_CNT) || (zone->get_index < 0)) {
-		free_zone(zone);
-		RTSX_DEBUGP("Get unused block fail, invalid get_index\n");
-		return BLK_NOT_FOUND;
-	}
-
-	RTSX_DEBUGP("Get unused block from index %d\n", zone->get_index);
-
-	phy_blk = zone->free_table[zone->get_index];
-	zone->free_table[zone->get_index++] = 0xFFFF;
-	if (zone->get_index >= XD_FREE_TABLE_CNT)
-		zone->get_index = 0;
-	zone->unused_blk_cnt--;
-
-	phy_blk += ((u32)(zone_no) << 10);
-	return phy_blk;
-}
-
-static void xd_set_l2p_tbl(struct rtsx_chip *chip, int zone_no, u16 log_off, u16 phy_off)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	struct zone_entry *zone;
-
-	zone = &(xd_card->zone[zone_no]);
-	zone->l2p_table[log_off] = phy_off;
-}
-
-static u32 xd_get_l2p_tbl(struct rtsx_chip *chip, int zone_no, u16 log_off)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	struct zone_entry *zone;
-	int retval;
-
-	zone = &(xd_card->zone[zone_no]);
-	if (zone->l2p_table[log_off] == 0xFFFF) {
-		u32 phy_blk = 0;
-		int i;
-
-#ifdef XD_DELAY_WRITE
-		retval = xd_delay_write(chip);
-		if (retval != STATUS_SUCCESS) {
-			RTSX_DEBUGP("In xd_get_l2p_tbl, delay write fail!\n");
-			return BLK_NOT_FOUND;
-		}
-#endif
-
-		if (zone->unused_blk_cnt <= 0) {
-			RTSX_DEBUGP("No unused block!\n");
-			return BLK_NOT_FOUND;
-		}
-
-		for (i = 0; i < zone->unused_blk_cnt; i++) {
-			phy_blk = xd_get_unused_block(chip, zone_no);
-			if (phy_blk == BLK_NOT_FOUND) {
-				RTSX_DEBUGP("No unused block available!\n");
-				return BLK_NOT_FOUND;
-			}
-
-			retval = xd_init_page(chip, phy_blk, log_off, 0, xd_card->page_off + 1);
-			if (retval == STATUS_SUCCESS)
-				break;
-		}
-		if (i >= zone->unused_blk_cnt) {
-			RTSX_DEBUGP("No good unused block available!\n");
-			return BLK_NOT_FOUND;
-		}
-
-		xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(phy_blk & 0x3FF));
-		return phy_blk;
-	}
-
-	return (u32)zone->l2p_table[log_off] + ((u32)(zone_no) << 10);
-}
-
-int reset_xd_card(struct rtsx_chip *chip)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	int retval;
-
-	memset(xd_card, 0, sizeof(struct xd_info));
-
-	xd_card->block_shift = 0;
-	xd_card->page_off = 0;
-	xd_card->addr_cycle = 0;
-	xd_card->capacity = 0;
-	xd_card->zone_cnt = 0;
-	xd_card->cis_block = 0xFFFF;
-	xd_card->delay_write.delay_write_flag = 0;
-
-	retval = enable_card_clock(chip, XD_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = reset_xd(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	retval = xd_init_l2p_tbl(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int xd_mark_bad_block(struct rtsx_chip *chip, u32 phy_blk)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	int retval;
-	u32 page_addr;
-	u8 reg = 0;
-
-	RTSX_DEBUGP("mark block 0x%x as bad block\n", phy_blk);
-
-	if (phy_blk == BLK_NOT_FOUND)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, XD_LATER_BBLK);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, 0xFF);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, 0xFF);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_H, 0xFF, 0xFF);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_L, 0xFF, 0xFF);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED0, 0xFF, 0xFF);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED1, 0xFF, 0xFF);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED2, 0xFF, 0xFF);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED3, 0xFF, 0xFF);
-
-	page_addr = phy_blk << xd_card->block_shift;
-
-	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, xd_card->page_off + 1);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_WRITE_REDUNDANT);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
-
-	retval = rtsx_send_cmd(chip, XD_CARD, 500);
-	if (retval < 0) {
-		rtsx_clear_xd_error(chip);
-		rtsx_read_register(chip, XD_DAT, &reg);
-		if (reg & PROGRAM_ERROR)
-			xd_set_err_code(chip, XD_PRG_ERROR);
-		else
-			xd_set_err_code(chip, XD_TO_ERROR);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk, u16 logoff, u8 start_page, u8 end_page)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	int retval;
-	u32 page_addr;
-	u8 reg = 0;
-
-	RTSX_DEBUGP("Init block 0x%x\n", phy_blk);
-
-	if (start_page > end_page)
-		TRACE_RET(chip, STATUS_FAIL);
-	if (phy_blk == BLK_NOT_FOUND)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, 0xFF);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, 0xFF);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, (u8)(logoff >> 8));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, (u8)logoff);
-
-	page_addr = (phy_blk << xd_card->block_shift) + start_page;
-
-	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_BA_TRANSFORM, XD_BA_TRANSFORM);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, (end_page - start_page));
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_WRITE_REDUNDANT);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
-
-	retval = rtsx_send_cmd(chip, XD_CARD, 500);
-	if (retval < 0) {
-		rtsx_clear_xd_error(chip);
-		rtsx_read_register(chip, XD_DAT, &reg);
-		if (reg & PROGRAM_ERROR) {
-			xd_mark_bad_block(chip, phy_blk);
-			xd_set_err_code(chip, XD_PRG_ERROR);
-		} else {
-			xd_set_err_code(chip, XD_TO_ERROR);
-		}
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk, u8 start_page, u8 end_page)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	u32 old_page, new_page;
-	u8 i, reg = 0;
-	int retval;
-
-	RTSX_DEBUGP("Copy page from block 0x%x to block 0x%x\n", old_blk, new_blk);
-
-	if (start_page > end_page)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	if ((old_blk == BLK_NOT_FOUND) || (new_blk == BLK_NOT_FOUND))
-		TRACE_RET(chip, STATUS_FAIL);
-
-	old_page = (old_blk << xd_card->block_shift) + start_page;
-	new_page = (new_blk << xd_card->block_shift) + start_page;
-
-	XD_CLR_BAD_NEWBLK(xd_card);
-
-	RTSX_WRITE_REG(chip, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
-
-	for (i = start_page; i < end_page; i++) {
-		if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
-			rtsx_clear_xd_error(chip);
-			xd_set_err_code(chip, XD_NO_CARD);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		rtsx_init_cmd(chip);
-
-		xd_assign_phy_addr(chip, old_page, XD_RW_ADDR);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS, 0);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_READ_PAGES);
-		rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
-
-		retval = rtsx_send_cmd(chip, XD_CARD, 500);
-		if (retval < 0) {
-			rtsx_clear_xd_error(chip);
-			reg = 0;
-			rtsx_read_register(chip, XD_CTL, &reg);
-			if (reg & (XD_ECC1_ERROR | XD_ECC2_ERROR)) {
-				wait_timeout(100);
-
-				if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
-					xd_set_err_code(chip, XD_NO_CARD);
-					TRACE_RET(chip, STATUS_FAIL);
-				}
-
-				if (((reg & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) ==
-						(XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE))
-					|| ((reg & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE)) ==
-						(XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) {
-					rtsx_write_register(chip, XD_PAGE_STATUS, 0xFF, XD_BPG);
-					rtsx_write_register(chip, XD_BLOCK_STATUS, 0xFF, XD_GBLK);
-					XD_SET_BAD_OLDBLK(xd_card);
-					RTSX_DEBUGP("old block 0x%x ecc error\n", old_blk);
-				}
-			} else {
-				xd_set_err_code(chip, XD_TO_ERROR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-
-		if (XD_CHK_BAD_OLDBLK(xd_card))
-			rtsx_clear_xd_error(chip);
-
-		rtsx_init_cmd(chip);
-
-		xd_assign_phy_addr(chip, new_page, XD_RW_ADDR);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1);
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
-			     XD_TRANSFER_START | XD_WRITE_PAGES);
-		rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
-
-		retval = rtsx_send_cmd(chip, XD_CARD, 300);
-		if (retval < 0) {
-			rtsx_clear_xd_error(chip);
-			reg = 0;
-			rtsx_read_register(chip, XD_DAT, &reg);
-			if (reg & PROGRAM_ERROR) {
-				xd_mark_bad_block(chip, new_blk);
-				xd_set_err_code(chip, XD_PRG_ERROR);
-				XD_SET_BAD_NEWBLK(xd_card);
-			} else {
-				xd_set_err_code(chip, XD_TO_ERROR);
-			}
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		old_page++;
-		new_page++;
-	}
-
-	return STATUS_SUCCESS;
-}
-
-static int xd_reset_cmd(struct rtsx_chip *chip)
-{
-	int retval;
-	u8 *ptr;
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_RESET);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
-	rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0);
-	rtsx_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0);
-
-	retval = rtsx_send_cmd(chip, XD_CARD, 100);
-	if (retval < 0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	ptr = rtsx_get_cmd_data(chip) + 1;
-	if (((ptr[0] & READY_FLAG) == READY_STATE) && (ptr[1] & XD_RDY))
-		return STATUS_SUCCESS;
-
-	TRACE_RET(chip, STATUS_FAIL);
-}
-
-static int xd_erase_block(struct rtsx_chip *chip, u32 phy_blk)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	u32 page_addr;
-	u8 reg = 0, *ptr;
-	int i, retval;
-
-	if (phy_blk == BLK_NOT_FOUND)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	page_addr = phy_blk << xd_card->block_shift;
-
-	for (i = 0; i < 3; i++) {
-		rtsx_init_cmd(chip);
-
-		xd_assign_phy_addr(chip, page_addr, XD_ERASE_ADDR);
-
-		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_ERASE);
-		rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
-		rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0);
-
-		retval = rtsx_send_cmd(chip, XD_CARD, 250);
-		if (retval < 0) {
-			rtsx_clear_xd_error(chip);
-			rtsx_read_register(chip, XD_DAT, &reg);
-			if (reg & PROGRAM_ERROR) {
-				xd_mark_bad_block(chip, phy_blk);
-				xd_set_err_code(chip, XD_PRG_ERROR);
-				TRACE_RET(chip, STATUS_FAIL);
-			} else {
-				xd_set_err_code(chip, XD_ERASE_FAIL);
-			}
-			retval = xd_reset_cmd(chip);
-			if (retval != STATUS_SUCCESS)
-				TRACE_RET(chip, STATUS_FAIL);
-			continue;
-		}
-
-		ptr = rtsx_get_cmd_data(chip) + 1;
-		if (*ptr & PROGRAM_ERROR) {
-			xd_mark_bad_block(chip, phy_blk);
-			xd_set_err_code(chip, XD_PRG_ERROR);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		return STATUS_SUCCESS;
-	}
-
-	xd_mark_bad_block(chip, phy_blk);
-	xd_set_err_code(chip, XD_ERASE_FAIL);
-	TRACE_RET(chip, STATUS_FAIL);
-}
-
-
-static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	struct zone_entry *zone;
-	int retval;
-	u32 start, end, i;
-	u16 max_logoff, cur_fst_page_logoff, cur_lst_page_logoff, ent_lst_page_logoff;
-	u8 redunt[11];
-
-	RTSX_DEBUGP("xd_build_l2p_tbl: %d\n", zone_no);
-
-	if (xd_card->zone == NULL) {
-		retval = xd_init_l2p_tbl(chip);
-		if (retval != STATUS_SUCCESS)
-			return retval;
-	}
-
-	if (xd_card->zone[zone_no].build_flag) {
-		RTSX_DEBUGP("l2p table of zone %d has been built\n", zone_no);
-		return STATUS_SUCCESS;
-	}
-
-	zone = &(xd_card->zone[zone_no]);
-
-	if (zone->l2p_table == NULL) {
-		zone->l2p_table = (u16 *)vmalloc(2000);
-		if (zone->l2p_table == NULL)
-			TRACE_GOTO(chip, Build_Fail);
-	}
-	memset((u8 *)(zone->l2p_table), 0xff, 2000);
-
-	if (zone->free_table == NULL) {
-		zone->free_table = (u16 *)vmalloc(XD_FREE_TABLE_CNT * 2);
-		if (zone->free_table == NULL)
-			TRACE_GOTO(chip, Build_Fail);
-	}
-	memset((u8 *)(zone->free_table), 0xff, XD_FREE_TABLE_CNT * 2);
-
-	if (zone_no == 0) {
-		if (xd_card->cis_block == 0xFFFF)
-			start = 0;
-		else
-			start = xd_card->cis_block + 1;
-		if (XD_CHK_4MB(xd_card)) {
-			end = 0x200;
-			max_logoff = 499;
-		} else {
-			end = 0x400;
-			max_logoff = 999;
-		}
-	} else {
-		start = (u32)(zone_no) << 10;
-		end = (u32)(zone_no + 1) << 10;
-		max_logoff = 999;
-	}
-
-	RTSX_DEBUGP("start block 0x%x, end block 0x%x\n", start, end);
-
-	zone->set_index = zone->get_index = 0;
-	zone->unused_blk_cnt = 0;
-
-	for (i = start; i < end; i++) {
-		u32 page_addr = i << xd_card->block_shift;
-		u32 phy_block;
-
-		retval = xd_read_redundant(chip, page_addr, redunt, 11);
-		if (retval != STATUS_SUCCESS)
-			continue;
-
-		if (redunt[BLOCK_STATUS] != 0xFF) {
-			RTSX_DEBUGP("bad block\n");
-			continue;
-		}
-
-		if (xd_check_data_blank(redunt)) {
-			RTSX_DEBUGP("blank block\n");
-			xd_set_unused_block(chip, i);
-			continue;
-		}
-
-		cur_fst_page_logoff = xd_load_log_block_addr(redunt);
-		if ((cur_fst_page_logoff == 0xFFFF) || (cur_fst_page_logoff > max_logoff)) {
-			retval = xd_erase_block(chip, i);
-			if (retval == STATUS_SUCCESS)
-				xd_set_unused_block(chip, i);
-			continue;
-		}
-
-		if ((zone_no == 0) && (cur_fst_page_logoff == 0) && (redunt[PAGE_STATUS] != XD_GPG))
-			XD_SET_MBR_FAIL(xd_card);
-
-		if (zone->l2p_table[cur_fst_page_logoff] == 0xFFFF) {
-			zone->l2p_table[cur_fst_page_logoff] = (u16)(i & 0x3FF);
-			continue;
-		}
-
-		phy_block = zone->l2p_table[cur_fst_page_logoff] + ((u32)((zone_no) << 10));
-
-		page_addr = ((i + 1) << xd_card->block_shift) - 1;
-
-		retval = xd_read_redundant(chip, page_addr, redunt, 11);
-		if (retval != STATUS_SUCCESS)
-			continue;
-
-		cur_lst_page_logoff = xd_load_log_block_addr(redunt);
-		if (cur_lst_page_logoff == cur_fst_page_logoff) {
-			int m;
-
-			page_addr = ((phy_block + 1) << xd_card->block_shift) - 1;
-
-			for (m = 0; m < 3; m++) {
-				retval = xd_read_redundant(chip, page_addr, redunt, 11);
-				if (retval == STATUS_SUCCESS)
-					break;
-			}
-
-			if (m == 3) {
-				zone->l2p_table[cur_fst_page_logoff] = (u16)(i & 0x3FF);
-				retval = xd_erase_block(chip, phy_block);
-				if (retval == STATUS_SUCCESS)
-					xd_set_unused_block(chip, phy_block);
-				continue;
-			}
-
-			ent_lst_page_logoff = xd_load_log_block_addr(redunt);
-			if (ent_lst_page_logoff != cur_fst_page_logoff) {
-				zone->l2p_table[cur_fst_page_logoff] = (u16)(i & 0x3FF);
-				retval = xd_erase_block(chip, phy_block);
-				if (retval == STATUS_SUCCESS)
-					xd_set_unused_block(chip, phy_block);
-				continue;
-			} else {
-				retval = xd_erase_block(chip, i);
-				if (retval == STATUS_SUCCESS)
-					xd_set_unused_block(chip, i);
-			}
-		} else {
-			retval = xd_erase_block(chip, i);
-			if (retval == STATUS_SUCCESS)
-				xd_set_unused_block(chip, i);
-		}
-	}
-
-	if (XD_CHK_4MB(xd_card))
-		end = 500;
-	else
-		end = 1000;
-
-	i = 0;
-	for (start = 0; start < end; start++) {
-		if (zone->l2p_table[start] == 0xFFFF)
-			i++;
-	}
-
-	RTSX_DEBUGP("Block count %d, invalid L2P entry %d\n", end, i);
-	RTSX_DEBUGP("Total unused block: %d\n", zone->unused_blk_cnt);
-
-	if ((zone->unused_blk_cnt - i) < 1)
-		chip->card_wp |= XD_CARD;
-
-	zone->build_flag = 1;
-
-	return STATUS_SUCCESS;
-
-Build_Fail:
-	if (zone->l2p_table) {
-		vfree(zone->l2p_table);
-		zone->l2p_table = NULL;
-	}
-	if (zone->free_table) {
-		vfree(zone->free_table);
-		zone->free_table = NULL;
-	}
-
-	return STATUS_FAIL;
-}
-
-static int xd_send_cmd(struct rtsx_chip *chip, u8 cmd)
-{
-	int retval;
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, cmd);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_SET_CMD);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
-
-	retval = rtsx_send_cmd(chip, XD_CARD, 200);
-	if (retval < 0)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
-
-static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk, u32 log_blk,
-		u8 start_page, u8 end_page, u8 *buf, unsigned int *index, unsigned int *offset)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	u32 page_addr, new_blk;
-	u16 log_off;
-	u8 reg_val, page_cnt;
-	int zone_no, retval, i;
-
-	if (start_page > end_page)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	page_cnt = end_page - start_page;
-	zone_no = (int)(log_blk / 1000);
-	log_off = (u16)(log_blk % 1000);
-
-	if ((phy_blk & 0x3FF) == 0x3FF) {
-		for (i = 0; i < 256; i++) {
-			page_addr = ((u32)i) << xd_card->block_shift;
-
-			retval = xd_read_redundant(chip, page_addr, NULL, 0);
-			if (retval == STATUS_SUCCESS)
-				break;
-
-			if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
-				xd_set_err_code(chip, XD_NO_CARD);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-	}
-
-	page_addr = (phy_blk << xd_card->block_shift) + start_page;
-
-	rtsx_init_cmd(chip);
-
-	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_PPB_TO_SIE, XD_PPB_TO_SIE);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS,
-			XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS);
-
-	trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512, DMA_512);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_READ_PAGES);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
-		     XD_TRANSFER_END | XD_PPB_EMPTY, XD_TRANSFER_END | XD_PPB_EMPTY);
-
-	rtsx_send_cmd_no_wait(chip);
-
-	retval = rtsx_transfer_data_partial(chip, XD_CARD, buf, page_cnt * 512, scsi_sg_count(chip->srb),
-			index, offset, DMA_FROM_DEVICE, chip->xd_timeout);
-	if (retval < 0) {
-		rtsx_clear_xd_error(chip);
-		xd_clear_dma_buffer(chip);
-
-		if (retval == -ETIMEDOUT) {
-			xd_set_err_code(chip, XD_TO_ERROR);
-			TRACE_RET(chip, STATUS_FAIL);
-		} else {
-			TRACE_GOTO(chip, Fail);
-		}
-	}
-
-	return STATUS_SUCCESS;
-
-Fail:
-	RTSX_READ_REG(chip, XD_PAGE_STATUS, &reg_val);
-
-	if (reg_val !=  XD_GPG)
-		xd_set_err_code(chip, XD_PRG_ERROR);
-
-	RTSX_READ_REG(chip, XD_CTL, &reg_val);
-
-	if (((reg_val & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE))
-				== (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE))
-		|| ((reg_val & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))
-			== (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) {
-		wait_timeout(100);
-
-		if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
-			xd_set_err_code(chip, XD_NO_CARD);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		xd_set_err_code(chip, XD_ECC_ERROR);
-
-		new_blk = xd_get_unused_block(chip, zone_no);
-		if (new_blk == NO_NEW_BLK) {
-			XD_CLR_BAD_OLDBLK(xd_card);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		retval = xd_copy_page(chip, phy_blk, new_blk, 0, xd_card->page_off + 1);
-		if (retval != STATUS_SUCCESS) {
-			if (!XD_CHK_BAD_NEWBLK(xd_card)) {
-				retval = xd_erase_block(chip, new_blk);
-				if (retval == STATUS_SUCCESS)
-					xd_set_unused_block(chip, new_blk);
-			} else {
-				XD_CLR_BAD_NEWBLK(xd_card);
-			}
-			XD_CLR_BAD_OLDBLK(xd_card);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-		xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF));
-		xd_erase_block(chip, phy_blk);
-		xd_mark_bad_block(chip, phy_blk);
-		XD_CLR_BAD_OLDBLK(xd_card);
-	}
-
-	TRACE_RET(chip, STATUS_FAIL);
-}
-
-static int xd_finish_write(struct rtsx_chip *chip,
-		u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	int retval, zone_no;
-	u16 log_off;
-
-	RTSX_DEBUGP("xd_finish_write, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x\n",
-				old_blk, new_blk, log_blk);
-
-	if (page_off > xd_card->page_off)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	zone_no = (int)(log_blk / 1000);
-	log_off = (u16)(log_blk % 1000);
-
-	if (old_blk == BLK_NOT_FOUND) {
-		retval = xd_init_page(chip, new_blk, log_off,
-				page_off, xd_card->page_off + 1);
-		if (retval != STATUS_SUCCESS) {
-			retval = xd_erase_block(chip, new_blk);
-			if (retval == STATUS_SUCCESS)
-				xd_set_unused_block(chip, new_blk);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	} else {
-		retval = xd_copy_page(chip, old_blk, new_blk,
-				page_off, xd_card->page_off + 1);
-		if (retval != STATUS_SUCCESS) {
-			if (!XD_CHK_BAD_NEWBLK(xd_card)) {
-				retval = xd_erase_block(chip, new_blk);
-				if (retval == STATUS_SUCCESS)
-					xd_set_unused_block(chip, new_blk);
-			}
-			XD_CLR_BAD_NEWBLK(xd_card);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		retval = xd_erase_block(chip, old_blk);
-		if (retval == STATUS_SUCCESS) {
-			if (XD_CHK_BAD_OLDBLK(xd_card)) {
-				xd_mark_bad_block(chip, old_blk);
-				XD_CLR_BAD_OLDBLK(xd_card);
-			} else {
-				xd_set_unused_block(chip, old_blk);
-			}
-		} else {
-			xd_set_err_code(chip, XD_NO_ERROR);
-			XD_CLR_BAD_OLDBLK(xd_card);
-		}
-	}
-
-	xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF));
-
-	return STATUS_SUCCESS;
-}
-
-static int xd_prepare_write(struct rtsx_chip *chip,
-		u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off)
-{
-	int retval;
-
-	RTSX_DEBUGP("%s, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x, page_off = %d\n",
-				__func__, old_blk, new_blk, log_blk, (int)page_off);
-
-	if (page_off) {
-		retval = xd_copy_page(chip, old_blk, new_blk, 0, page_off);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-
-static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, u32 new_blk, u32 log_blk,
-		u8 start_page, u8 end_page, u8 *buf, unsigned int *index, unsigned int *offset)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	u32 page_addr;
-	int zone_no, retval;
-	u16 log_off;
-	u8 page_cnt, reg_val;
-
-	RTSX_DEBUGP("%s, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x\n",
-				__func__, old_blk, new_blk, log_blk);
-
-	if (start_page > end_page)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	page_cnt = end_page - start_page;
-	zone_no = (int)(log_blk / 1000);
-	log_off = (u16)(log_blk % 1000);
-
-	page_addr = (new_blk << xd_card->block_shift) + start_page;
-
-	retval = xd_send_cmd(chip, READ1_1);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	rtsx_init_cmd(chip);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, (u8)(log_off >> 8));
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, (u8)log_off);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, XD_GBLK);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG);
-
-	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_BA_TRANSFORM, XD_BA_TRANSFORM);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt);
-	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-
-	trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512, DMA_512);
-
-	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_WRITE_PAGES);
-	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
-
-	rtsx_send_cmd_no_wait(chip);
-
-	retval = rtsx_transfer_data_partial(chip, XD_CARD, buf, page_cnt * 512, scsi_sg_count(chip->srb),
-			index, offset, DMA_TO_DEVICE, chip->xd_timeout);
-	if (retval < 0) {
-		rtsx_clear_xd_error(chip);
-
-		if (retval == -ETIMEDOUT) {
-			xd_set_err_code(chip, XD_TO_ERROR);
-			TRACE_RET(chip, STATUS_FAIL);
-		} else {
-			TRACE_GOTO(chip, Fail);
-		}
-	}
-
-	if (end_page == (xd_card->page_off + 1)) {
-		xd_card->delay_write.delay_write_flag = 0;
-
-		if (old_blk != BLK_NOT_FOUND) {
-			retval = xd_erase_block(chip, old_blk);
-			if (retval == STATUS_SUCCESS) {
-				if (XD_CHK_BAD_OLDBLK(xd_card)) {
-					xd_mark_bad_block(chip, old_blk);
-					XD_CLR_BAD_OLDBLK(xd_card);
-				} else {
-					xd_set_unused_block(chip, old_blk);
-				}
-			} else {
-				xd_set_err_code(chip, XD_NO_ERROR);
-				XD_CLR_BAD_OLDBLK(xd_card);
-			}
-		}
-		xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF));
-	}
-
-	return STATUS_SUCCESS;
-
-Fail:
-	RTSX_READ_REG(chip, XD_DAT, &reg_val);
-	if (reg_val & PROGRAM_ERROR) {
-		xd_set_err_code(chip, XD_PRG_ERROR);
-		xd_mark_bad_block(chip, new_blk);
-	}
-
-	TRACE_RET(chip, STATUS_FAIL);
-}
-
-#ifdef XD_DELAY_WRITE
-int xd_delay_write(struct rtsx_chip *chip)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	struct xd_delay_write_tag *delay_write = &(xd_card->delay_write);
-	int retval;
-
-	if (delay_write->delay_write_flag) {
-		RTSX_DEBUGP("xd_delay_write\n");
-		retval = xd_switch_clock(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		delay_write->delay_write_flag = 0;
-		retval = xd_finish_write(chip,
-				delay_write->old_phyblock, delay_write->new_phyblock,
-				delay_write->logblock, delay_write->pageoff);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	return STATUS_SUCCESS;
-}
-#endif
-
-int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	unsigned int lun = SCSI_LUN(srb);
-#ifdef XD_DELAY_WRITE
-	struct xd_delay_write_tag *delay_write = &(xd_card->delay_write);
-#endif
-	int retval, zone_no;
-	unsigned int index = 0, offset = 0;
-	u32 log_blk, old_blk = 0, new_blk = 0;
-	u16 log_off, total_sec_cnt = sector_cnt;
-	u8 start_page, end_page = 0, page_cnt;
-	u8 *ptr;
-
-	xd_set_err_code(chip, XD_NO_ERROR);
-
-	xd_card->cleanup_counter = 0;
-
-	RTSX_DEBUGP("xd_rw: scsi_sg_count = %d\n", scsi_sg_count(srb));
-
-	ptr = (u8 *)scsi_sglist(srb);
-
-	retval = xd_switch_clock(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-
-	if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
-		chip->card_fail |= XD_CARD;
-		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-		TRACE_RET(chip, STATUS_FAIL);
-	}
-
-	log_blk = start_sector >> xd_card->block_shift;
-	start_page = (u8)start_sector & xd_card->page_off;
-	zone_no = (int)(log_blk / 1000);
-	log_off = (u16)(log_blk % 1000);
-
-	if (xd_card->zone[zone_no].build_flag == 0) {
-		retval = xd_build_l2p_tbl(chip, zone_no);
-		if (retval != STATUS_SUCCESS) {
-			chip->card_fail |= XD_CARD;
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	if (srb->sc_data_direction == DMA_TO_DEVICE) {
-#ifdef XD_DELAY_WRITE
-		if (delay_write->delay_write_flag &&
-				(delay_write->logblock == log_blk) &&
-				(start_page > delay_write->pageoff)) {
-			delay_write->delay_write_flag = 0;
-			if (delay_write->old_phyblock != BLK_NOT_FOUND) {
-				retval = xd_copy_page(chip,
-					delay_write->old_phyblock,
-					delay_write->new_phyblock,
-					delay_write->pageoff, start_page);
-				if (retval != STATUS_SUCCESS) {
-					set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-					TRACE_RET(chip, STATUS_FAIL);
-				}
-			}
-			old_blk = delay_write->old_phyblock;
-			new_blk = delay_write->new_phyblock;
-		} else if (delay_write->delay_write_flag &&
-				(delay_write->logblock == log_blk) &&
-				(start_page == delay_write->pageoff)) {
-			delay_write->delay_write_flag = 0;
-			old_blk = delay_write->old_phyblock;
-			new_blk = delay_write->new_phyblock;
-		} else {
-			retval = xd_delay_write(chip);
-			if (retval != STATUS_SUCCESS) {
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-#endif
-			old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
-			new_blk  = xd_get_unused_block(chip, zone_no);
-			if ((old_blk == BLK_NOT_FOUND) || (new_blk == BLK_NOT_FOUND)) {
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-
-			retval = xd_prepare_write(chip, old_blk, new_blk, log_blk, start_page);
-			if (retval != STATUS_SUCCESS) {
-				if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
-					set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-					TRACE_RET(chip, STATUS_FAIL);
-				}
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-#ifdef XD_DELAY_WRITE
-		}
-#endif
-	} else {
-#ifdef XD_DELAY_WRITE
-		retval = xd_delay_write(chip);
-		if (retval != STATUS_SUCCESS) {
-			if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-#endif
-
-		old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
-		if (old_blk == BLK_NOT_FOUND) {
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-	}
-
-	RTSX_DEBUGP("old_blk = 0x%x\n", old_blk);
-
-	while (total_sec_cnt) {
-		if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
-			chip->card_fail |= XD_CARD;
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		if ((start_page + total_sec_cnt) > (xd_card->page_off + 1))
-			end_page = xd_card->page_off + 1;
-		else
-			end_page = start_page + (u8)total_sec_cnt;
-
-		page_cnt = end_page - start_page;
-		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
-			retval = xd_read_multiple_pages(chip, old_blk, log_blk,
-					start_page, end_page, ptr, &index, &offset);
-			if (retval != STATUS_SUCCESS) {
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		} else {
-			retval = xd_write_multiple_pages(chip, old_blk, new_blk, log_blk,
-					start_page, end_page, ptr, &index, &offset);
-			if (retval != STATUS_SUCCESS) {
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-
-		total_sec_cnt -= page_cnt;
-		if (scsi_sg_count(srb) == 0)
-			ptr += page_cnt * 512;
-
-		if (total_sec_cnt == 0)
-			break;
-
-		log_blk++;
-		zone_no = (int)(log_blk / 1000);
-		log_off = (u16)(log_blk % 1000);
-
-		if (xd_card->zone[zone_no].build_flag == 0) {
-			retval = xd_build_l2p_tbl(chip, zone_no);
-			if (retval != STATUS_SUCCESS) {
-				chip->card_fail |= XD_CARD;
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-
-		old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
-		if (old_blk == BLK_NOT_FOUND) {
-			if (srb->sc_data_direction == DMA_FROM_DEVICE)
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-			else
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-			
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		if (srb->sc_data_direction == DMA_TO_DEVICE) {
-			new_blk = xd_get_unused_block(chip, zone_no);
-			if (new_blk == BLK_NOT_FOUND) {
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-		}
-
-		start_page = 0;
-	}
-
-	if ((srb->sc_data_direction == DMA_TO_DEVICE) &&
-			(end_page != (xd_card->page_off + 1))) {
-#ifdef XD_DELAY_WRITE
-		delay_write->delay_write_flag = 1;
-		delay_write->old_phyblock = old_blk;
-		delay_write->new_phyblock = new_blk;
-		delay_write->logblock = log_blk;
-		delay_write->pageoff = end_page;
-#else
-		if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
-			chip->card_fail |= XD_CARD;
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-
-		retval = xd_finish_write(chip, old_blk, new_blk, log_blk, end_page);
-		if (retval != STATUS_SUCCESS) {
-			if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
-				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-				TRACE_RET(chip, STATUS_FAIL);
-			}
-			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-			TRACE_RET(chip, STATUS_FAIL);
-		}
-#endif
-	}
-
-	scsi_set_resid(srb, 0);
-
-	return STATUS_SUCCESS;
-}
-
-void xd_free_l2p_tbl(struct rtsx_chip *chip)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	int i = 0;
-
-	if (xd_card->zone != NULL) {
-		for (i = 0; i < xd_card->zone_cnt; i++) {
-			if (xd_card->zone[i].l2p_table != NULL) {
-				vfree(xd_card->zone[i].l2p_table);
-				xd_card->zone[i].l2p_table = NULL;
-			}
-			if (xd_card->zone[i].free_table != NULL) {
-				vfree(xd_card->zone[i].free_table);
-				xd_card->zone[i].free_table = NULL;
-			}
-		}
-		vfree(xd_card->zone);
-		xd_card->zone = NULL;
-	}
-}
-
-void xd_cleanup_work(struct rtsx_chip *chip)
-{
-#ifdef XD_DELAY_WRITE
-	struct xd_info *xd_card = &(chip->xd_card);
-
-	if (xd_card->delay_write.delay_write_flag) {
-		RTSX_DEBUGP("xD: delay write\n");
-		xd_delay_write(chip);
-		xd_card->cleanup_counter = 0;
-	}
-#endif
-}
-
-int xd_power_off_card3v3(struct rtsx_chip *chip)
-{
-	int retval;
-
-	retval = disable_card_clock(chip, XD_CARD);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	RTSX_WRITE_REG(chip, CARD_OE, XD_OUTPUT_EN, 0);
-
-	if (!chip->ft2_fast_mode) {
-		retval = card_power_off(chip, XD_CARD);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-
-		wait_timeout(50);
-	}
-
-	if (chip->asic_code) {
-		retval = xd_pull_ctl_disable(chip);
-		if (retval != STATUS_SUCCESS)
-			TRACE_RET(chip, STATUS_FAIL);
-	} else {
-		RTSX_WRITE_REG(chip, FPGA_PULL_CTL, 0xFF, 0xDF);
-	}
-
-	return STATUS_SUCCESS;
-}
-
-int release_xd_card(struct rtsx_chip *chip)
-{
-	struct xd_info *xd_card = &(chip->xd_card);
-	int retval;
-
-	RTSX_DEBUGP("release_xd_card\n");
-
-	chip->card_ready &= ~XD_CARD;
-	chip->card_fail &= ~XD_CARD;
-	chip->card_wp &= ~XD_CARD;
-
-	xd_card->delay_write.delay_write_flag = 0;
-
-	xd_free_l2p_tbl(chip);
-
-	retval = xd_power_off_card3v3(chip);
-	if (retval != STATUS_SUCCESS)
-		TRACE_RET(chip, STATUS_FAIL);
-
-	return STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rts_pstor/xd.h b/drivers/staging/rts_pstor/xd.h
deleted file mode 100644
index cd9fbc1..0000000
--- a/drivers/staging/rts_pstor/xd.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- * Header file
- *
- * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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/>.
- *
- * Author:
- *   wwang (wei_wang@realsil.com.cn)
- *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
- */
-
-#ifndef __REALTEK_RTSX_XD_H
-#define __REALTEK_RTSX_XD_H
-
-#define	XD_DELAY_WRITE
-
-/* Error Codes */
-#define	XD_NO_ERROR			0x00
-#define	XD_NO_MEMORY			0x80
-#define	XD_PRG_ERROR			0x40
-#define	XD_NO_CARD			0x20
-#define	XD_READ_FAIL			0x10
-#define	XD_ERASE_FAIL			0x08
-#define	XD_WRITE_FAIL			0x04
-#define	XD_ECC_ERROR			0x02
-#define	XD_TO_ERROR			0x01
-
-/* XD Commands */
-#define	READ1_1				0x00
-#define	READ1_2				0x01
-#define	READ2				0x50
-#define READ_ID				0x90
-#define RESET				0xff
-#define PAGE_PRG_1			0x80
-#define PAGE_PRG_2			0x10
-#define	BLK_ERASE_1			0x60
-#define	BLK_ERASE_2			0xD0
-#define READ_STS			0x70
-#define READ_xD_ID			0x9A
-#define	COPY_BACK_512			0x8A
-#define	COPY_BACK_2K			0x85
-#define	READ1_1_2			0x30
-#define	READ1_1_3			0x35
-#define	CHG_DAT_OUT_1			0x05
-#define RDM_DAT_OUT_1			0x05
-#define	CHG_DAT_OUT_2			0xE0
-#define RDM_DAT_OUT_2			0xE0
-#define	CHG_DAT_OUT_2			0xE0
-#define	CHG_DAT_IN_1			0x85
-#define	CACHE_PRG			0x15
-
-/* Redundant Area Related */
-#define XD_EXTRA_SIZE			0x10
-#define XD_2K_EXTRA_SIZE		0x40
-
-#define	NOT_WRITE_PROTECTED		0x80
-#define	READY_STATE			0x40
-#define	PROGRAM_ERROR			0x01
-#define	PROGRAM_ERROR_N_1		0x02
-#define	INTERNAL_READY			0x20
-#define	READY_FLAG			0x5F
-
-#define	XD_8M_X8_512			0xE6
-#define	XD_16M_X8_512			0x73
-#define	XD_32M_X8_512			0x75
-#define	XD_64M_X8_512			0x76
-#define	XD_128M_X8_512			0x79
-#define	XD_256M_X8_512			0x71
-#define	XD_128M_X8_2048			0xF1
-#define	XD_256M_X8_2048			0xDA
-#define	XD_512M_X8			0xDC
-#define	XD_128M_X16_2048		0xC1
-#define	XD_4M_X8_512_1			0xE3
-#define	XD_4M_X8_512_2			0xE5
-#define	xD_1G_X8_512			0xD3
-#define	xD_2G_X8_512			0xD5
-
-#define	XD_ID_CODE			0xB5
-
-#define	VENDOR_BLOCK			0xEFFF
-#define	CIS_BLOCK			0xDFFF
-
-#define	BLK_NOT_FOUND			0xFFFFFFFF
-
-#define	NO_NEW_BLK			0xFFFFFFFF
-
-#define	PAGE_CORRECTABLE		0x0
-#define	PAGE_NOTCORRECTABLE		0x1
-
-#define	NO_OFFSET			0x0
-#define	WITH_OFFSET			0x1
-
-#define	Sect_Per_Page			4
-#define	XD_ADDR_MODE_2C			XD_ADDR_MODE_2A
-
-#define ZONE0_BAD_BLOCK 		23
-#define NOT_ZONE0_BAD_BLOCK 		24
-
-#define	XD_RW_ADDR			0x01
-#define	XD_ERASE_ADDR			0x02
-
-#define	XD_PAGE_512(xd_card)		\
-do {					\
-	(xd_card)->block_shift = 5; 	\
-	(xd_card)->page_off = 0x1F;	\
-} while (0)
-
-#define	XD_SET_BAD_NEWBLK(xd_card)	((xd_card)->multi_flag |= 0x01)
-#define	XD_CLR_BAD_NEWBLK(xd_card)	((xd_card)->multi_flag &= ~0x01)
-#define	XD_CHK_BAD_NEWBLK(xd_card)	((xd_card)->multi_flag & 0x01)
-
-#define	XD_SET_BAD_OLDBLK(xd_card)	((xd_card)->multi_flag |= 0x02)
-#define	XD_CLR_BAD_OLDBLK(xd_card)	((xd_card)->multi_flag &= ~0x02)
-#define	XD_CHK_BAD_OLDBLK(xd_card)	((xd_card)->multi_flag & 0x02)
-
-#define	XD_SET_MBR_FAIL(xd_card)	((xd_card)->multi_flag |= 0x04)
-#define	XD_CLR_MBR_FAIL(xd_card)	((xd_card)->multi_flag &= ~0x04)
-#define	XD_CHK_MBR_FAIL(xd_card)	((xd_card)->multi_flag & 0x04)
-
-#define	XD_SET_ECC_FLD_ERR(xd_card)	((xd_card)->multi_flag |= 0x08)
-#define	XD_CLR_ECC_FLD_ERR(xd_card)	((xd_card)->multi_flag &= ~0x08)
-#define	XD_CHK_ECC_FLD_ERR(xd_card)	((xd_card)->multi_flag & 0x08)
-
-#define	XD_SET_4MB(xd_card)		((xd_card)->multi_flag |= 0x10)
-#define	XD_CLR_4MB(xd_card)		((xd_card)->multi_flag &= ~0x10)
-#define	XD_CHK_4MB(xd_card)		((xd_card)->multi_flag & 0x10)
-
-#define	XD_SET_ECC_ERR(xd_card)		((xd_card)->multi_flag |= 0x40)
-#define	XD_CLR_ECC_ERR(xd_card)		((xd_card)->multi_flag &= ~0x40)
-#define	XD_CHK_ECC_ERR(xd_card)		((xd_card)->multi_flag & 0x40)
-
-#define PAGE_STATUS		0
-#define BLOCK_STATUS		1
-#define BLOCK_ADDR1_L		2
-#define BLOCK_ADDR1_H		3
-#define BLOCK_ADDR2_L		4
-#define BLOCK_ADDR2_H		5
-#define RESERVED0		6
-#define RESERVED1		7
-#define RESERVED2		8
-#define RESERVED3		9
-#define PARITY			10
-
-#define	CIS0_0			0
-#define	CIS0_1			1
-#define	CIS0_2			2
-#define	CIS0_3			3
-#define	CIS0_4			4
-#define	CIS0_5			5
-#define	CIS0_6			6
-#define	CIS0_7			7
-#define	CIS0_8			8
-#define	CIS0_9			9
-#define	CIS1_0			256
-#define	CIS1_1			(256 + 1)
-#define	CIS1_2			(256 + 2)
-#define	CIS1_3			(256 + 3)
-#define	CIS1_4			(256 + 4)
-#define	CIS1_5			(256 + 5)
-#define	CIS1_6			(256 + 6)
-#define	CIS1_7			(256 + 7)
-#define	CIS1_8			(256 + 8)
-#define	CIS1_9			(256 + 9)
-
-int reset_xd_card(struct rtsx_chip *chip);
-#ifdef XD_DELAY_WRITE
-int xd_delay_write(struct rtsx_chip *chip);
-#endif
-int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt);
-void xd_free_l2p_tbl(struct rtsx_chip *chip);
-void xd_cleanup_work(struct rtsx_chip *chip);
-int xd_power_off_card3v3(struct rtsx_chip *chip);
-int release_xd_card(struct rtsx_chip *chip);
-
-#endif  /* __REALTEK_RTSX_XD_H */
-
diff --git a/drivers/staging/sb105x/Kconfig b/drivers/staging/sb105x/Kconfig
new file mode 100644
index 0000000..c957e32
--- /dev/null
+++ b/drivers/staging/sb105x/Kconfig
@@ -0,0 +1,10 @@
+config SB105X
+	tristate "SystemBase PCI Multiport UART"
+	select SERIAL_CORE
+	depends on PCI
+	depends on BROKEN
+	help
+	  A driver for the SystemBase Multi-2/PCI serial card
+
+	  To compile this driver a module, choose M here: the module
+	  will be called "sb105x".
diff --git a/drivers/staging/sb105x/Makefile b/drivers/staging/sb105x/Makefile
new file mode 100644
index 0000000..b1bf377
--- /dev/null
+++ b/drivers/staging/sb105x/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_SB105X) +=	sb105x.o
+
+sb105x-y :=  sb_pci_mp.o
diff --git a/drivers/staging/sb105x/sb_mp_register.h b/drivers/staging/sb105x/sb_mp_register.h
new file mode 100644
index 0000000..5480ae1
--- /dev/null
+++ b/drivers/staging/sb105x/sb_mp_register.h
@@ -0,0 +1,295 @@
+
+/*
+ * SB105X_UART.h
+ *
+ * Copyright (C) 2008 systembase
+ *
+ * UART registers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 UART_SB105X_H
+#define UART_SB105X_H
+
+/* 
+ * option register 
+ */
+
+/* Device Infomation Register */
+#define MP_OPTR_DIR0		0x04 	/* port0 ~ port8 */
+#define MP_OPTR_DIR1		0x05 	/* port8 ~ port15 */
+#define MP_OPTR_DIR2		0x06 	/* port16 ~ port23 */
+#define MP_OPTR_DIR3		0x07 	/* port24 ~ port31 */
+
+#define DIR_UART_16C550 	0
+#define DIR_UART_16C1050	1
+#define DIR_UART_16C1050A	2
+
+#define	DIR_CLK_1843200		0x0		/* input clock 1843200 Hz */
+#define	DIR_CLK_3686400		0x1		/* input clock 3686400 Hz */
+#define	DIR_CLK_7372800		0x2		/* input clock 7372800 Hz */
+#define	DIR_CLK_14745600	0x3		/* input clock 14745600 Hz */
+#define	DIR_CLK_29491200	0x4		/* input clock 29491200 Hz */
+#define	DIR_CLK_58985400	0x5		/* input clock 58985400 Hz */
+
+/* Interface Information Register */
+#define MP_OPTR_IIR0		0x08 	/* port0 ~ port8 */
+#define MP_OPTR_IIR1		0x09 	/* port8 ~ port15 */
+#define MP_OPTR_IIR2		0x0A 	/* port16 ~ port23 */
+#define MP_OPTR_IIR3		0x0B 	/* port24 ~ port31 */
+
+#define IIR_RS232		0x00		/* RS232 type */
+#define IIR_RS422		0x10		/* RS422 type */
+#define IIR_RS485		0x20		/* RS485 type */
+#define IIR_UNKNOWN		0x30		/* unknown type */
+
+/* Interrrupt Mask Register */
+#define MP_OPTR_IMR0		0x0C 	/* port0 ~ port8 */
+#define MP_OPTR_IMR1		0x0D 	/* port8 ~ port15 */
+#define MP_OPTR_IMR2		0x0E 	/* port16 ~ port23 */
+#define MP_OPTR_IMR3		0x0F 	/* port24 ~ port31 */
+
+/* Interrupt Poll Register */
+#define MP_OPTR_IPR0		0x10 	/* port0 ~ port8 */
+#define MP_OPTR_IPR1		0x11 	/* port8 ~ port15 */
+#define MP_OPTR_IPR2		0x12 	/* port16 ~ port23 */
+#define MP_OPTR_IPR3		0x13 	/* port24 ~ port31 */
+
+/* General Purpose Output Control Register */
+#define MP_OPTR_GPOCR		0x20
+
+/* General Purpose Output Data Register */
+#define MP_OPTR_GPODR		0x21
+
+/* Parallel Additional Function Register */
+#define MP_OPTR_PAFR		0x23
+
+/*
+ * systembase 16c105x UART register
+ */
+
+#define PAGE_0 0
+#define PAGE_1 1
+#define PAGE_2 2
+#define PAGE_3 3
+#define PAGE_4 4
+
+/*
+ *  ******************************************************************
+ *  * DLAB=0                  ===============       Page 0 Registers *
+ *  ******************************************************************
+ */
+
+#define SB105X_RX		0	/* In:  Receive buffer */
+#define SB105X_TX		0	/* Out: Transmit buffer */
+
+#define SB105X_IER		1	/* Out: Interrupt Enable Register */
+
+#define SB105X_IER_CTSI	  	0x80	/* CTS# Interrupt Enable (Requires EFR[4] = 1) */
+#define SB105X_IER_RTSI	  	0x40	/* RTS# Interrupt Enable (Requires EFR[4] = 1) */
+#define SB105X_IER_XOI	  	0x20	/* Xoff Interrupt Enable (Requires EFR[4] = 1) */
+#define SB105X_IER_SME	  	0x10	/* Sleep Mode Enable (Requires EFR[4] = 1) */
+#define SB105X_IER_MSI	  	0x08	/* Enable Modem status interrupt */
+#define SB105X_IER_RLSI	  	0x04	/* Enable receiver line status interrupt */
+#define SB105X_IER_THRI	  	0x02	/* Enable Transmitter holding register int. */
+#define SB105X_IER_RDI	  	0x01	/* Enable receiver data interrupt */
+
+#define SB105X_ISR		2	/* In:  Interrupt ID Register */
+
+#define SB105X_ISR_NOINT	0x01	/* No interrupts pending */
+#define SB105X_ISR_RLSI	  	0x06	/* Receiver line status interrupt (Priority = 1)*/
+#define SB105X_ISR_RDAI	  	0x0c	/* Receive Data Available interrupt */
+#define SB105X_ISR_CTII	  	0x04	/* Character Timeout Indication interrupt */
+#define SB105X_ISR_THRI	  	0x02	/* Transmitter holding register empty */
+#define SB105X_ISR_MSI	  	0x00	/* Modem status interrupt */
+#define SB105X_ISR_RXCI	  	0x10	/* Receive Xoff or Special Character interrupt */
+#define SB105X_ISR_RCSI	  	0x20	/* RTS#, CTS# status interrupt during Auto RTS/CTS flow control */
+
+#define SB105X_FCR		2	/* Out: FIFO Control Register */
+
+#define SB105X_FCR_FEN    	0x01	/* FIFO Enable */
+#define SB105X_FCR_RXFR	  	0x02	/* RX FIFO Reset */
+#define SB105X_FCR_TXFR	  	0x04	/* TX FIFO Reset */
+#define SB105X_FCR_DMS	  	0x08	/* DMA Mode Select */
+
+#define SB105X_FCR_RTR08  	0x00	/* Receice Trigger Level set at 8 */
+#define SB105X_FCR_RTR16  	0x40  /* Receice Trigger Level set at 16 */
+#define SB105X_FCR_RTR56  	0x80  /* Receice Trigger Level set at 56 */
+#define SB105X_FCR_RTR60  	0xc0  /* Receice Trigger Level set at 60 */
+#define SB105X_FCR_TTR08  	0x00  /* Transmit Trigger Level set at 8 */
+#define SB105X_FCR_TTR16	0x10  /* Transmit Trigger Level set at 16 */
+#define SB105X_FCR_TTR32	0x20  /* Transmit Trigger Level set at 32 */
+#define SB105X_FCR_TTR56	0x30  /* Transmit Trigger Level set at 56 */
+
+#define SB105X_LCR		3	/* Out: Line Control Register */
+/*
+ *  * Note: if the word length is 5 bits (SB105X_LCR_WLEN5), then setting 
+ *  * SB105X_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
+ */
+#define SB105X_LCR_DLAB   	0x80  /* Divisor Latch Enable */
+#define SB105X_LCR_SBC    	0x40  /* Break Enable*/
+#define SB105X_LCR_SPAR   	0x20  /* Set Stick parity */
+#define SB105X_LCR_EPAR   	0x10  /* Even parity select */
+#define SB105X_LCR_PAREN  	0x08  /* Parity Enable */
+#define SB105X_LCR_STOP   	0x04  /* Stop bits: 0->1 bit, 1->2 bits, 1 and SB105X_LCR_WLEN5 -> 1.5 bit */
+#define SB105X_LCR_WLEN5  	0x00  /* Wordlength: 5 bits */
+#define SB105X_LCR_WLEN6  	0x01  /* Wordlength: 6 bits */
+#define SB105X_LCR_WLEN7  	0x02  /* Wordlength: 7 bits */
+#define SB105X_LCR_WLEN8  	0x03  /* Wordlength: 8 bits */
+
+#define SB105X_LCR_BF		0xBF
+
+#define SB105X_MCR		4	/* Out: Modem Control Register */
+#define SB105X_MCR_CPS    	0x80  /* Clock Prescaler Select */
+#define SB105X_MCR_P2S    	0x40  /* Page 2 Select /Xoff Re-Transmit Access Enable */
+#define SB105X_MCR_XOA    	0x20  /* Xon Any Enable */
+#define SB105X_MCR_ILB		0x10  /* Internal Loopback Enable */
+#define SB105X_MCR_OUT2		0x08  /* Out2/Interrupt Output Enable*/
+#define SB105X_MCR_OUT1		0x04  /* Out1/Interrupt Output Enable */
+#define SB105X_MCR_RTS    	0x02  /* RTS# Output */
+#define SB105X_MCR_DTR    	0x01  /* DTR# Output */
+
+#define SB105X_LSR		5	/* In:  Line Status Register */
+#define SB105X_LSR_RFEI   	0x80  /* Receive FIFO data error Indicator */
+#define SB105X_LSR_TEMI   	0x40  /* THR and TSR Empty Indicator */
+#define SB105X_LSR_THRE		0x20  /* THR Empty Indicator */
+#define SB105X_LSR_BII		0x10  /* Break interrupt indicator */
+#define SB105X_LSR_FEI		0x08  /* Frame error indicator */
+#define SB105X_LSR_PEI		0x04  /* Parity error indicator */
+#define SB105X_LSR_OEI		0x02  /* Overrun error indicator */
+#define SB105X_LSR_RDRI		0x01  /* Receive data ready Indicator*/
+
+#define SB105X_MSR		6	/* In:  Modem Status Register */
+#define SB105X_MSR_DCD		0x80  /* Data Carrier Detect */
+#define SB105X_MSR_RI		0x40  /* Ring Indicator */
+#define SB105X_MSR_DSR		0x20  /* Data Set Ready */
+#define SB105X_MSR_CTS		0x10  /* Clear to Send */
+#define SB105X_MSR_DDCD		0x08  /* Delta DCD */
+#define SB105X_MSR_DRI		0x04  /* Delta ring indicator */
+#define SB105X_MSR_DDSR		0x02  /* Delta DSR */
+#define SB105X_MSR_DCTS		0x01  /* Delta CTS */
+
+#define SB105XA_MDR		6	/* Out: Multi Drop mode Register */
+#define SB105XA_MDR_NPS		0x08  /* 9th Bit Polarity Select */
+#define SB105XA_MDR_AME		0x02  /* Auto Multi-drop Enable */
+#define SB105XA_MDR_MDE		0x01  /* Multi Drop Enable */
+
+#define SB105X_SPR		7	/* I/O: Scratch Register */
+
+/*
+ * DLAB=1
+ */
+#define SB105X_DLL		0	/* Out: Divisor Latch Low */
+#define SB105X_DLM		1	/* Out: Divisor Latch High */
+
+/*
+ *  ******************************************************************
+ *  * DLAB(LCR[7]) = 0 , MCR[6] = 1  =============  Page 2 Registers *
+ *  ******************************************************************
+ */
+#define SB105X_GICR		1	/* Global Interrupt Control Register */
+#define SB105X_GICR_GIM   	0x01  /* Global Interrupt Mask */
+
+#define SB105X_GISR		2	/* Global Interrupt Status Register */
+#define SB105X_GISR_MGICR0  	0x80  /* Mirror the content of GICR[0] */
+#define SB105X_GISR_CS3IS   	0x08  /* SB105X of CS3# Interrupt Status */
+#define SB105X_GISR_CS2IS   	0x04  /* SB105X of CS2# Interrupt Status */
+#define SB105X_GISR_CS1IS   	0x02  /* SB105X of CS1# Interrupt Status */
+#define SB105X_GISR_CS0IS   	0x01  /* SB105X of CS0# Interrupt Status */
+
+#define SB105X_TFCR		5	/* Transmit FIFO Count Register */
+
+#define SB105X_RFCR		6	/* Receive FIFO Count Register */
+
+#define	SB105X_FSR		7	/* Flow Control Status Register */
+#define SB105X_FSR_THFS     	0x20  /* Transmit Hardware Flow Control Status */
+#define SB105X_FSR_TSFS     	0x10  /* Transmit Software Flow Control Status */
+#define SB105X_FSR_RHFS     	0x02  /* Receive Hardware Flow Control Status */
+#define SB105X_FSR_RSFS     	0x01  /* Receive Software Flow Control Status */
+
+/*
+ *  ******************************************************************
+ *  * LCR = 0xBF, PSR[0] = 0       =============    Page 3 Registers *
+ *  ******************************************************************
+ */
+
+#define SB105X_PSR		0	/* Page Select Register */
+#define SB105X_PSR_P3KEY    	0xA4 /* Page 3 Select Key */
+#define SB105X_PSR_P4KEY    	0xA5 /* Page 5 Select Key */
+
+#define SB105X_ATR		1	/* Auto Toggle Control Register */
+#define SB105X_ATR_RPS      	0x80  /* RXEN Polarity Select */
+#define SB105X_ATR_RCMS     	0x40  /* RXEN Control Mode Select */
+#define SB105X_ATR_TPS      	0x20  /* TXEN Polarity Select */
+#define SB105X_ATR_TCMS     	0x10  /* TXEN Control Mode Select */
+#define SB105X_ATR_ATDIS    	0x00  /* Auto Toggle is disabled */
+#define SB105X_ATR_ART      	0x01  /* RTS#/TXEN pin operates as TXEN */
+#define SB105X_ATR_ADT      	0x02  /* DTR#/TXEN pin operates as TXEN */
+#define SB105X_ATR_A80      	0x03  /* only in 80 pin use */
+
+#define SB105X_EFR		2	/* (Auto) Enhanced Feature Register */
+#define SB105X_EFR_ACTS     	0x80  /* Auto-CTS Flow Control Enable */
+#define SB105X_EFR_ARTS     	0x40  /* Auto-RTS Flow Control Enable */
+#define SB105X_EFR_SCD      	0x20  /* Special Character Detect */
+#define SB105X_EFR_EFBEN    	0x10  /* Enhanced Function Bits Enable */
+
+#define SB105X_XON1		4	/* Xon1 Character Register */
+#define SB105X_XON2		5	/* Xon2 Character Register */
+#define SB105X_XOFF1		6	/* Xoff1 Character Register */
+#define SB105X_XOFF2		7	/* Xoff2 Character Register */
+
+/*
+ *  ******************************************************************
+ *  * LCR = 0xBF, PSR[0] = 1       ============     Page 4 Registers *
+ *  ******************************************************************
+ */
+
+#define SB105X_AFR		1	/* Additional Feature Register */
+#define SB105X_AFR_GIPS     	0x20  /* Global Interrupt Polarity Select */
+#define SB105X_AFR_GIEN     	0x10  /* Global Interrupt Enable */
+#define SB105X_AFR_AFEN     	0x01  /* 256-byte FIFO Enable */
+
+#define SB105X_XRCR		2	/* Xoff Re-transmit Count Register */
+#define SB105X_XRCR_NRC1    	0x00  /* Transmits Xoff Character whenever the number of received data is 1 during XOFF status */
+#define SB105X_XRCR_NRC4    	0x01  /* Transmits Xoff Character whenever the number of received data is 4 during XOFF status */
+#define SB105X_XRCR_NRC8    	0x02  /* Transmits Xoff Character whenever the number of received data is 8 during XOFF status */
+#define SB105X_XRCR_NRC16   	0x03  /* Transmits Xoff Character whenever the number of received data is 16 during XOFF status */
+
+#define SB105X_TTR		4	/* Transmit FIFO Trigger Level Register */
+#define SB105X_RTR		5	/* Receive FIFO Trigger Level Register */
+#define SB105X_FUR		6	/* Flow Control Upper Threshold Register */
+#define SB105X_FLR		7	/* Flow Control Lower Threshold Register */
+
+
+/* page 0 */
+
+#define SB105X_GET_CHAR(port)	inb((port)->iobase + SB105X_RX)
+#define SB105X_GET_IER(port)	inb((port)->iobase + SB105X_IER)
+#define SB105X_GET_ISR(port)	inb((port)->iobase + SB105X_ISR)
+#define SB105X_GET_LCR(port)	inb((port)->iobase + SB105X_LCR)
+#define SB105X_GET_MCR(port)	inb((port)->iobase + SB105X_MCR)
+#define SB105X_GET_LSR(port)	inb((port)->iobase + SB105X_LSR)
+#define SB105X_GET_MSR(port)	inb((port)->iobase + SB105X_MSR)
+#define SB105X_GET_SPR(port)	inb((port)->iobase + SB105X_SPR)
+
+#define SB105X_PUT_CHAR(port,v)	outb((v),(port)->iobase + SB105X_TX )
+#define SB105X_PUT_IER(port,v)	outb((v),(port)->iobase + SB105X_IER )
+#define SB105X_PUT_FCR(port,v)	outb((v),(port)->iobase + SB105X_FCR )
+#define SB105X_PUT_LCR(port,v)	outb((v),(port)->iobase + SB105X_LCR )
+#define SB105X_PUT_MCR(port,v)	outb((v),(port)->iobase + SB105X_MCR )
+#define SB105X_PUT_SPR(port,v)	outb((v),(port)->iobase + SB105X_SPR )
+
+
+/* page 1 */
+#define SB105X_GET_REG(port,reg)	inb((port)->iobase + (reg))
+#define SB105X_PUT_REG(port,reg,v)	outb((v),(port)->iobase + (reg))
+
+/* page 2 */
+
+#define SB105X_PUT_PSR(port,v)	outb((v),(port)->iobase + SB105X_PSR )
+
+#endif 
diff --git a/drivers/staging/sb105x/sb_pci_mp.c b/drivers/staging/sb105x/sb_pci_mp.c
new file mode 100644
index 0000000..fbebf88
--- /dev/null
+++ b/drivers/staging/sb105x/sb_pci_mp.c
@@ -0,0 +1,3195 @@
+#include "sb_pci_mp.h"
+#include <linux/module.h>
+#include <linux/parport.h>
+
+extern struct parport *parport_pc_probe_port(unsigned long base_lo,
+		unsigned long base_hi,
+		int irq, int dma,
+		struct device *dev,
+		int irqflags);
+
+static struct mp_device_t mp_devs[MAX_MP_DEV];
+static int mp_nrpcibrds = sizeof(mp_pciboards)/sizeof(mppcibrd_t);
+static int NR_BOARD=0;
+static int NR_PORTS=0;
+static struct mp_port multi_ports[MAX_MP_PORT];
+static struct irq_info irq_lists[NR_IRQS];
+
+static _INLINE_ unsigned int serial_in(struct mp_port *mtpt, int offset);
+static _INLINE_ void serial_out(struct mp_port *mtpt, int offset, int value);
+static _INLINE_ unsigned int read_option_register(struct mp_port *mtpt, int offset);
+static int sb1054_get_register(struct sb_uart_port * port, int page, int reg);
+static int sb1054_set_register(struct sb_uart_port * port, int page, int reg, int value);
+static void SendATCommand(struct mp_port * mtpt);
+static int set_deep_fifo(struct sb_uart_port * port, int status);
+static int get_deep_fifo(struct sb_uart_port * port);
+static int get_device_type(int arg);
+static int set_auto_rts(struct sb_uart_port *port, int status);
+static void mp_stop(struct tty_struct *tty);
+static void __mp_start(struct tty_struct *tty);
+static void mp_start(struct tty_struct *tty);
+static void mp_tasklet_action(unsigned long data);
+static inline void mp_update_mctrl(struct sb_uart_port *port, unsigned int set, unsigned int clear);
+static int mp_startup(struct sb_uart_state *state, int init_hw);
+static void mp_shutdown(struct sb_uart_state *state);
+static void mp_change_speed(struct sb_uart_state *state, struct MP_TERMIOS *old_termios);
+
+static inline int __mp_put_char(struct sb_uart_port *port, struct circ_buf *circ, unsigned char c);
+static int mp_put_char(struct tty_struct *tty, unsigned char ch);
+
+static void mp_put_chars(struct tty_struct *tty);
+static int mp_write(struct tty_struct *tty, const unsigned char * buf, int count);
+static int mp_write_room(struct tty_struct *tty);
+static int mp_chars_in_buffer(struct tty_struct *tty);
+static void mp_flush_buffer(struct tty_struct *tty);
+static void mp_send_xchar(struct tty_struct *tty, char ch);
+static void mp_throttle(struct tty_struct *tty);
+static void mp_unthrottle(struct tty_struct *tty);
+static int mp_get_info(struct sb_uart_state *state, struct serial_struct *retinfo);
+static int mp_set_info(struct sb_uart_state *state, struct serial_struct *newinfo);
+static int mp_get_lsr_info(struct sb_uart_state *state, unsigned int *value);
+
+static int mp_tiocmget(struct tty_struct *tty);
+static int mp_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear);
+static int mp_break_ctl(struct tty_struct *tty, int break_state);
+static int mp_do_autoconfig(struct sb_uart_state *state);
+static int mp_wait_modem_status(struct sb_uart_state *state, unsigned long arg);
+static int mp_get_count(struct sb_uart_state *state, struct serial_icounter_struct *icnt);
+static int mp_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
+static void mp_set_termios(struct tty_struct *tty, struct MP_TERMIOS *old_termios);
+static void mp_close(struct tty_struct *tty, struct file *filp);
+static void mp_wait_until_sent(struct tty_struct *tty, int timeout);
+static void mp_hangup(struct tty_struct *tty);
+static void mp_update_termios(struct sb_uart_state *state);
+static int mp_block_til_ready(struct file *filp, struct sb_uart_state *state);
+static struct sb_uart_state *uart_get(struct uart_driver *drv, int line);
+static int mp_open(struct tty_struct *tty, struct file *filp);
+static const char *mp_type(struct sb_uart_port *port);
+static void mp_change_pm(struct sb_uart_state *state, int pm_state);
+static inline void mp_report_port(struct uart_driver *drv, struct sb_uart_port *port);
+static void mp_configure_port(struct uart_driver *drv, struct sb_uart_state *state, struct sb_uart_port *port);
+static void mp_unconfigure_port(struct uart_driver *drv, struct sb_uart_state *state);
+static int mp_register_driver(struct uart_driver *drv);
+static void mp_unregister_driver(struct uart_driver *drv);
+static int mp_add_one_port(struct uart_driver *drv, struct sb_uart_port *port);
+static int mp_remove_one_port(struct uart_driver *drv, struct sb_uart_port *port);
+static void autoconfig(struct mp_port *mtpt, unsigned int probeflags);
+static void autoconfig_irq(struct mp_port *mtpt);
+static void multi_stop_tx(struct sb_uart_port *port);
+static void multi_start_tx(struct sb_uart_port *port);
+static void multi_stop_rx(struct sb_uart_port *port);
+static void multi_enable_ms(struct sb_uart_port *port);
+static _INLINE_ void receive_chars(struct mp_port *mtpt, int *status );
+static _INLINE_ void transmit_chars(struct mp_port *mtpt);
+static _INLINE_ void check_modem_status(struct mp_port *mtpt);
+static inline void multi_handle_port(struct mp_port *mtpt);
+static irqreturn_t multi_interrupt(int irq, void *dev_id);
+static void serial_do_unlink(struct irq_info *i, struct mp_port *mtpt);
+static int serial_link_irq_chain(struct mp_port *mtpt);
+static void serial_unlink_irq_chain(struct mp_port *mtpt);
+static void multi_timeout(unsigned long data);
+static unsigned int multi_tx_empty(struct sb_uart_port *port);
+static unsigned int multi_get_mctrl(struct sb_uart_port *port);
+static void multi_set_mctrl(struct sb_uart_port *port, unsigned int mctrl);
+static void multi_break_ctl(struct sb_uart_port *port, int break_state);
+static int multi_startup(struct sb_uart_port *port);
+static void multi_shutdown(struct sb_uart_port *port);
+static unsigned int multi_get_divisor(struct sb_uart_port *port, unsigned int baud);
+static void multi_set_termios(struct sb_uart_port *port, struct MP_TERMIOS *termios, struct MP_TERMIOS *old);
+static void multi_pm(struct sb_uart_port *port, unsigned int state, unsigned int oldstate);
+static void multi_release_std_resource(struct mp_port *mtpt);
+static void multi_release_port(struct sb_uart_port *port);
+static int multi_request_port(struct sb_uart_port *port);
+static void multi_config_port(struct sb_uart_port *port, int flags);
+static int multi_verify_port(struct sb_uart_port *port, struct serial_struct *ser);
+static const char * multi_type(struct sb_uart_port *port);
+static void __init multi_init_ports(void);
+static void __init multi_register_ports(struct uart_driver *drv);
+static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd);
+
+static int deep[256];
+static int deep_count;
+static int fcr_arr[256];
+static int fcr_count;
+static int ttr[256];
+static int ttr_count;
+static int rtr[256];
+static int rtr_count;
+
+module_param_array(deep,int,&deep_count,0);
+module_param_array(fcr_arr,int,&fcr_count,0);
+module_param_array(ttr,int,&ttr_count,0);
+module_param_array(rtr,int,&rtr_count,0);
+
+static _INLINE_ unsigned int serial_in(struct mp_port *mtpt, int offset)
+{
+	return inb(mtpt->port.iobase + offset);
+}
+
+static _INLINE_ void serial_out(struct mp_port *mtpt, int offset, int value)
+{
+	outb(value, mtpt->port.iobase + offset);
+}
+
+static _INLINE_ unsigned int read_option_register(struct mp_port *mtpt, int offset)
+{
+	return inb(mtpt->option_base_addr + offset);
+}
+
+static int sb1053a_get_interface(struct mp_port *mtpt, int port_num)
+{
+	unsigned long option_base_addr = mtpt->option_base_addr;
+	unsigned int  interface = 0;
+
+	switch (port_num)
+	{
+		case 0:
+		case 1:
+			/* set GPO[1:0] = 00 */
+			outb(0x00, option_base_addr + MP_OPTR_GPODR);
+			break;
+		case 2:
+		case 3:
+			/* set GPO[1:0] = 01 */
+			outb(0x01, option_base_addr + MP_OPTR_GPODR);
+			break;
+		case 4:
+		case 5:
+			/* set GPO[1:0] = 10 */
+			outb(0x02, option_base_addr + MP_OPTR_GPODR);
+			break;
+		default:
+			break;
+	}
+
+	port_num &= 0x1;
+
+	/* get interface */
+	interface = inb(option_base_addr + MP_OPTR_IIR0 + port_num);
+
+	/* set GPO[1:0] = 11 */
+	outb(0x03, option_base_addr + MP_OPTR_GPODR);
+
+	return (interface);
+}
+		
+static int sb1054_get_register(struct sb_uart_port * port, int page, int reg)
+{
+	int ret = 0;
+	unsigned int lcr = 0;
+	unsigned int mcr = 0;
+	unsigned int tmp = 0;
+
+	if( page <= 0)
+	{
+		printk(" page 0 can not use this fuction\n");
+		return -1;
+	}
+
+	switch(page)
+	{
+		case 1:
+			lcr = SB105X_GET_LCR(port);
+			tmp = lcr | SB105X_LCR_DLAB;
+			SB105X_PUT_LCR(port, tmp);
+
+			tmp = SB105X_GET_LCR(port);
+
+			ret = SB105X_GET_REG(port,reg);
+			SB105X_PUT_LCR(port,lcr);
+			break;
+		case 2:
+			mcr = SB105X_GET_MCR(port);
+			tmp = mcr | SB105X_MCR_P2S;
+			SB105X_PUT_MCR(port,tmp);
+
+			ret = SB105X_GET_REG(port,reg);
+
+			SB105X_PUT_MCR(port,mcr);
+			break;
+		case 3:
+			lcr = SB105X_GET_LCR(port);
+			tmp = lcr | SB105X_LCR_BF;
+			SB105X_PUT_LCR(port,tmp);
+			SB105X_PUT_REG(port,SB105X_PSR,SB105X_PSR_P3KEY);
+
+			ret = SB105X_GET_REG(port,reg);
+
+			SB105X_PUT_LCR(port,lcr);
+			break;
+		case 4:
+			lcr = SB105X_GET_LCR(port);
+			tmp = lcr | SB105X_LCR_BF;
+			SB105X_PUT_LCR(port,tmp);
+			SB105X_PUT_REG(port,SB105X_PSR,SB105X_PSR_P4KEY);
+
+			ret = SB105X_GET_REG(port,reg);
+
+			SB105X_PUT_LCR(port,lcr);
+			break;
+		default:
+			printk(" error invalid page number \n");
+			return -1;
+	}
+
+	return ret;
+}
+
+static int sb1054_set_register(struct sb_uart_port * port, int page, int reg, int value)
+{  
+	int lcr = 0;
+	int mcr = 0;
+	int ret = 0;
+
+	if( page <= 0)
+	{
+		printk(" page 0 can not use this fuction\n");
+		return -1;
+	}
+	switch(page)
+	{
+		case 1:
+			lcr = SB105X_GET_LCR(port);
+			SB105X_PUT_LCR(port, lcr | SB105X_LCR_DLAB);
+
+			SB105X_PUT_REG(port,reg,value);
+
+			SB105X_PUT_LCR(port, lcr);
+			ret = 1;
+			break;
+		case 2:
+			mcr = SB105X_GET_MCR(port);
+			SB105X_PUT_MCR(port, mcr | SB105X_MCR_P2S);
+
+			SB105X_PUT_REG(port,reg,value);
+
+			SB105X_PUT_MCR(port, mcr);
+			ret = 1;
+			break;
+		case 3:
+			lcr = SB105X_GET_LCR(port);
+			SB105X_PUT_LCR(port, lcr | SB105X_LCR_BF);
+			SB105X_PUT_PSR(port, SB105X_PSR_P3KEY);
+
+			SB105X_PUT_REG(port,reg,value);
+
+			SB105X_PUT_LCR(port, lcr);
+			ret = 1;
+			break;
+		case 4:
+			lcr = SB105X_GET_LCR(port);
+			SB105X_PUT_LCR(port, lcr | SB105X_LCR_BF);
+			SB105X_PUT_PSR(port, SB105X_PSR_P4KEY);
+
+			SB105X_PUT_REG(port,reg,value);
+
+			SB105X_PUT_LCR(port, lcr);
+			ret = 1;
+			break;
+		default:
+			printk(" error invalid page number \n");
+			return -1;
+	}
+
+	return ret;
+}
+
+static int set_multidrop_mode(struct sb_uart_port *port, unsigned int mode)
+{
+	int mdr = SB105XA_MDR_NPS;
+
+	if (mode & MDMODE_ENABLE)
+	{
+		mdr |= SB105XA_MDR_MDE;
+	}
+
+	if (1) //(mode & MDMODE_AUTO)
+	{
+		int efr = 0;
+		mdr |= SB105XA_MDR_AME;
+		efr = sb1054_get_register(port, PAGE_3, SB105X_EFR);
+		efr |= SB105X_EFR_SCD;
+		sb1054_set_register(port, PAGE_3, SB105X_EFR, efr);
+	}
+
+	sb1054_set_register(port, PAGE_1, SB105XA_MDR, mdr);
+	port->mdmode &= ~0x6;
+	port->mdmode |= mode;
+	printk("[%d] multidrop init: %x\n", port->line, port->mdmode);
+
+	return 0;
+}
+
+static int get_multidrop_addr(struct sb_uart_port *port)
+{
+	return sb1054_get_register(port, PAGE_3, SB105X_XOFF2);
+}
+
+static int set_multidrop_addr(struct sb_uart_port *port, unsigned int addr)
+{
+	sb1054_set_register(port, PAGE_3, SB105X_XOFF2, addr);
+
+	return 0;
+}
+
+static void SendATCommand(struct mp_port * mtpt)
+{
+	//		      a    t	cr   lf
+	unsigned char ch[] = {0x61,0x74,0x0d,0x0a,0x0};
+	unsigned char lineControl;
+	unsigned char i=0;
+	unsigned char Divisor = 0xc;
+
+	lineControl = serial_inp(mtpt,UART_LCR);
+	serial_outp(mtpt,UART_LCR,(lineControl | UART_LCR_DLAB));
+	serial_outp(mtpt,UART_DLL,(Divisor & 0xff));
+	serial_outp(mtpt,UART_DLM,(Divisor & 0xff00)>>8); //baudrate is 4800
+
+
+	serial_outp(mtpt,UART_LCR,lineControl);	
+	serial_outp(mtpt,UART_LCR,0x03); // N-8-1
+	serial_outp(mtpt,UART_FCR,7); 
+	serial_outp(mtpt,UART_MCR,0x3);
+	while(ch[i]){
+		while((serial_inp(mtpt,UART_LSR) & 0x60) !=0x60){
+			;
+		}
+		serial_outp(mtpt,0,ch[i++]);
+	}
+
+
+}// end of SendATCommand()
+
+static int set_deep_fifo(struct sb_uart_port * port, int status)
+{
+	int afr_status = 0;
+	afr_status = sb1054_get_register(port, PAGE_4, SB105X_AFR);
+
+	if(status == ENABLE)
+	{
+		afr_status |= SB105X_AFR_AFEN;
+	}
+	else
+	{
+		afr_status &= ~SB105X_AFR_AFEN;
+	}
+		
+	sb1054_set_register(port,PAGE_4,SB105X_AFR,afr_status);
+	sb1054_set_register(port,PAGE_4,SB105X_TTR,ttr[port->line]); 
+	sb1054_set_register(port,PAGE_4,SB105X_RTR,rtr[port->line]); 
+	afr_status = sb1054_get_register(port, PAGE_4, SB105X_AFR);
+		
+	return afr_status;
+}
+
+static int get_device_type(int arg)
+{
+	int ret;
+        ret = inb(mp_devs[arg].option_reg_addr+MP_OPTR_DIR0);
+        ret = (ret & 0xf0) >> 4;
+        switch (ret)
+        {
+               case DIR_UART_16C550:
+                    return PORT_16C55X;
+               case DIR_UART_16C1050:
+                    return PORT_16C105X;
+               case DIR_UART_16C1050A:
+               /*
+               if (mtpt->port.line < 2)
+               {
+                    return PORT_16C105XA;
+               }
+               else
+               {
+                   if (mtpt->device->device_id & 0x50)
+                   {
+                       return PORT_16C55X;
+                   }
+                   else
+                   {
+                       return PORT_16C105X;
+                   }
+               }*/
+               return PORT_16C105XA;
+               default:
+                    return PORT_UNKNOWN;
+        }
+
+}
+static int get_deep_fifo(struct sb_uart_port * port)
+{
+	int afr_status = 0;
+	afr_status = sb1054_get_register(port, PAGE_4, SB105X_AFR);
+	return afr_status;
+}
+
+static int set_auto_rts(struct sb_uart_port *port, int status)
+{
+	int atr_status = 0;
+
+#if 0
+	int efr_status = 0;
+
+	efr_status = sb1054_get_register(port, PAGE_3, SB105X_EFR);
+	if(status == ENABLE)
+		efr_status |= SB105X_EFR_ARTS;
+	else
+		efr_status &= ~SB105X_EFR_ARTS;
+	sb1054_set_register(port,PAGE_3,SB105X_EFR,efr_status);
+	efr_status = sb1054_get_register(port, PAGE_3, SB105X_EFR);
+#endif
+		
+//ATR
+	atr_status = sb1054_get_register(port, PAGE_3, SB105X_ATR);
+	switch(status)
+	{
+		case RS422PTP:
+			atr_status = (SB105X_ATR_TPS) | (SB105X_ATR_A80);
+			break;
+		case RS422MD:
+			atr_status = (SB105X_ATR_TPS) | (SB105X_ATR_TCMS) | (SB105X_ATR_A80);
+			break;
+		case RS485NE:
+			atr_status = (SB105X_ATR_RCMS) | (SB105X_ATR_TPS) | (SB105X_ATR_TCMS) | (SB105X_ATR_A80);
+			break;
+		case RS485ECHO:
+			atr_status = (SB105X_ATR_TPS) | (SB105X_ATR_TCMS) | (SB105X_ATR_A80);
+			break;
+	}
+
+	sb1054_set_register(port,PAGE_3,SB105X_ATR,atr_status);
+	atr_status = sb1054_get_register(port, PAGE_3, SB105X_ATR);
+
+	return atr_status;
+}
+
+static void mp_stop(struct tty_struct *tty)
+{
+	struct sb_uart_state *state = tty->driver_data;
+	struct sb_uart_port *port = state->port;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	port->ops->stop_tx(port);
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void __mp_start(struct tty_struct *tty)
+{
+	struct sb_uart_state *state = tty->driver_data;
+	struct sb_uart_port *port = state->port;
+
+	if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf &&
+			!tty->stopped && !tty->hw_stopped)
+		port->ops->start_tx(port);
+}
+
+static void mp_start(struct tty_struct *tty)
+{
+	__mp_start(tty);
+}
+
+static void mp_tasklet_action(unsigned long data)
+{
+	struct sb_uart_state *state = (struct sb_uart_state *)data;
+	struct tty_struct *tty;
+
+	printk("tasklet is called!\n");
+	tty = state->info->tty;
+	tty_wakeup(tty);
+}
+
+static inline void mp_update_mctrl(struct sb_uart_port *port, unsigned int set, unsigned int clear)
+{
+	unsigned int old;
+
+	old = port->mctrl;
+	port->mctrl = (old & ~clear) | set;
+	if (old != port->mctrl)
+		port->ops->set_mctrl(port, port->mctrl);
+}
+
+#define uart_set_mctrl(port,set)	mp_update_mctrl(port,set,0)
+#define uart_clear_mctrl(port,clear)	mp_update_mctrl(port,0,clear)
+
+static int mp_startup(struct sb_uart_state *state, int init_hw)
+{
+	struct sb_uart_info *info = state->info;
+	struct sb_uart_port *port = state->port;
+	unsigned long page;
+	int retval = 0;
+
+	if (info->flags & UIF_INITIALIZED)
+		return 0;
+
+	if (info->tty)
+		set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+	if (port->type == PORT_UNKNOWN)
+		return 0;
+
+	if (!info->xmit.buf) {
+		page = get_zeroed_page(GFP_KERNEL);
+		if (!page)
+			return -ENOMEM;
+
+		info->xmit.buf = (unsigned char *) page;
+			
+		uart_circ_clear(&info->xmit);
+	}
+
+	retval = port->ops->startup(port);
+	if (retval == 0) {
+		if (init_hw) {
+			mp_change_speed(state, NULL);
+
+			if (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 (retval && capable(CAP_SYS_ADMIN))
+		retval = 0;
+
+	return retval;
+}
+
+static void mp_shutdown(struct sb_uart_state *state)
+{
+	struct sb_uart_info *info = state->info;
+	struct sb_uart_port *port = state->port;
+
+	if (info->tty)
+		set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+	if (info->flags & UIF_INITIALIZED) {
+		info->flags &= ~UIF_INITIALIZED;
+
+		if (!info->tty || (info->tty->termios.c_cflag & HUPCL))
+			uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+
+		wake_up_interruptible(&info->delta_msr_wait);
+
+		port->ops->shutdown(port);
+
+		synchronize_irq(port->irq);
+	}
+	tasklet_kill(&info->tlet);
+
+	if (info->xmit.buf) {
+		free_page((unsigned long)info->xmit.buf);
+		info->xmit.buf = NULL;
+	}
+}
+
+static void mp_change_speed(struct sb_uart_state *state, struct MP_TERMIOS *old_termios)
+{
+	struct tty_struct *tty = state->info->tty;
+	struct sb_uart_port *port = state->port;
+
+	if (!tty || port->type == PORT_UNKNOWN)
+		return;
+
+	if (tty->termios.c_cflag & CRTSCTS)
+		state->info->flags |= UIF_CTS_FLOW;
+	else
+		state->info->flags &= ~UIF_CTS_FLOW;
+
+	if (tty->termios.c_cflag & CLOCAL)
+		state->info->flags &= ~UIF_CHECK_CD;
+	else
+		state->info->flags |= UIF_CHECK_CD;
+
+	port->ops->set_termios(port, &tty->termios, old_termios);
+}
+
+static inline int __mp_put_char(struct sb_uart_port *port, struct circ_buf *circ, unsigned char c)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	if (!circ->buf)
+		return 0;
+
+	spin_lock_irqsave(&port->lock, flags);
+	if (uart_circ_chars_free(circ) != 0) {
+		circ->buf[circ->head] = c;
+		circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
+		ret = 1;
+	}
+	spin_unlock_irqrestore(&port->lock, flags);
+	return ret;
+}
+
+static int mp_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct sb_uart_state *state = tty->driver_data;
+
+	return __mp_put_char(state->port, &state->info->xmit, ch);
+}
+
+static void mp_put_chars(struct tty_struct *tty)
+{
+	mp_start(tty);
+}
+
+static int mp_write(struct tty_struct *tty, const unsigned char * buf, int count)
+{
+	struct sb_uart_state *state = tty->driver_data;
+	struct sb_uart_port *port;
+	struct circ_buf *circ;
+	int c, ret = 0;
+
+	if (!state || !state->info) {
+		return -EL3HLT;
+	}
+
+	port = state->port;
+	circ = &state->info->xmit;
+
+	if (!circ->buf)
+		return 0;
+		
+	while (1) {
+		c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
+		if (count < c)
+			c = count;
+		if (c <= 0)
+			break;
+	memcpy(circ->buf + circ->head, buf, c);
+
+		circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
+		buf += c;
+		count -= c;
+		ret += c;
+	}
+	mp_start(tty);
+	return ret;
+}
+
+static int mp_write_room(struct tty_struct *tty)
+{
+	struct sb_uart_state *state = tty->driver_data;
+
+	return uart_circ_chars_free(&state->info->xmit);
+}
+
+static int mp_chars_in_buffer(struct tty_struct *tty)
+{
+	struct sb_uart_state *state = tty->driver_data;
+
+	return uart_circ_chars_pending(&state->info->xmit);
+}
+
+static void mp_flush_buffer(struct tty_struct *tty)
+{
+	struct sb_uart_state *state = tty->driver_data;
+	struct sb_uart_port *port = state->port;
+	unsigned long flags;
+
+	if (!state || !state->info) {
+		return;
+	}
+
+	spin_lock_irqsave(&port->lock, flags);
+	uart_circ_clear(&state->info->xmit);
+	spin_unlock_irqrestore(&port->lock, flags);
+	wake_up_interruptible(&tty->write_wait);
+	tty_wakeup(tty);
+}
+
+static void mp_send_xchar(struct tty_struct *tty, char ch)
+{
+	struct sb_uart_state *state = tty->driver_data;
+	struct sb_uart_port *port = state->port;
+	unsigned long flags;
+
+	if (port->ops->send_xchar)
+		port->ops->send_xchar(port, ch);
+	else {
+		port->x_char = ch;
+		if (ch) {
+			spin_lock_irqsave(&port->lock, flags);
+			port->ops->start_tx(port);
+			spin_unlock_irqrestore(&port->lock, flags);
+		}
+	}
+}
+
+static void mp_throttle(struct tty_struct *tty)
+{
+	struct sb_uart_state *state = tty->driver_data;
+
+	if (I_IXOFF(tty))
+		mp_send_xchar(tty, STOP_CHAR(tty));
+
+	if (tty->termios.c_cflag & CRTSCTS)
+		uart_clear_mctrl(state->port, TIOCM_RTS);
+}
+
+static void mp_unthrottle(struct tty_struct *tty)
+{
+	struct sb_uart_state *state = tty->driver_data;
+	struct sb_uart_port *port = state->port;
+
+	if (I_IXOFF(tty)) {
+		if (port->x_char)
+			port->x_char = 0;
+		else
+			mp_send_xchar(tty, START_CHAR(tty));
+	}
+
+	if (tty->termios.c_cflag & CRTSCTS)
+		uart_set_mctrl(port, TIOCM_RTS);
+}
+
+static int mp_get_info(struct sb_uart_state *state, struct serial_struct *retinfo)
+{
+	struct sb_uart_port *port = state->port;
+	struct serial_struct tmp;
+
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.type	    = port->type;
+	tmp.line	    = port->line;
+	tmp.port	    = port->iobase;
+	if (HIGH_BITS_OFFSET)
+		tmp.port_high = (long) port->iobase >> HIGH_BITS_OFFSET;
+	tmp.irq		    = port->irq;
+	tmp.flags	    = port->flags;
+	tmp.xmit_fifo_size  = port->fifosize;
+	tmp.baud_base	    = port->uartclk / 16;
+	tmp.close_delay	    = state->close_delay;
+	tmp.closing_wait    = state->closing_wait == USF_CLOSING_WAIT_NONE ?
+		ASYNC_CLOSING_WAIT_NONE :
+		state->closing_wait;
+	tmp.custom_divisor  = port->custom_divisor;
+	tmp.hub6	    = port->hub6;
+	tmp.io_type         = port->iotype;
+	tmp.iomem_reg_shift = port->regshift;
+	tmp.iomem_base      = (void *)port->mapbase;
+
+	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return -EFAULT;
+	return 0;
+}
+
+static int mp_set_info(struct sb_uart_state *state, struct serial_struct *newinfo)
+{
+	struct serial_struct new_serial;
+	struct sb_uart_port *port = state->port;
+	unsigned long new_port;
+	unsigned int change_irq, change_port, closing_wait;
+	unsigned int old_custom_divisor;
+	unsigned int old_flags, new_flags;
+	int retval = 0;
+
+	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
+		return -EFAULT;
+
+	new_port = new_serial.port;
+	if (HIGH_BITS_OFFSET)
+		new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
+
+	new_serial.irq = irq_canonicalize(new_serial.irq);
+
+	closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
+		USF_CLOSING_WAIT_NONE : new_serial.closing_wait;
+	MP_STATE_LOCK(state);
+
+	change_irq  = new_serial.irq != port->irq;
+	change_port = new_port != port->iobase ||
+		(unsigned long)new_serial.iomem_base != port->mapbase ||
+		new_serial.hub6 != port->hub6 ||
+		new_serial.io_type != port->iotype ||
+		new_serial.iomem_reg_shift != port->regshift ||
+		new_serial.type != port->type;
+	old_flags = port->flags;
+	new_flags = new_serial.flags;
+	old_custom_divisor = port->custom_divisor;
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		retval = -EPERM;
+		if (change_irq || change_port ||
+				(new_serial.baud_base != port->uartclk / 16) ||
+				(new_serial.close_delay != state->close_delay) ||
+				(closing_wait != state->closing_wait) ||
+				(new_serial.xmit_fifo_size != port->fifosize) ||
+				(((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0))
+			goto exit;
+		port->flags = ((port->flags & ~UPF_USR_MASK) |
+				(new_flags & UPF_USR_MASK));
+		port->custom_divisor = new_serial.custom_divisor;
+		goto check_and_exit;
+	}
+
+	if (port->ops->verify_port)
+		retval = port->ops->verify_port(port, &new_serial);
+
+	if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
+			(new_serial.baud_base < 9600))
+		retval = -EINVAL;
+
+	if (retval)
+		goto exit;
+
+	if (change_port || change_irq) {
+		retval = -EBUSY;
+
+		if (uart_users(state) > 1)
+			goto exit;
+
+		mp_shutdown(state);
+	}
+
+	if (change_port) {
+		unsigned long old_iobase, old_mapbase;
+		unsigned int old_type, old_iotype, old_hub6, old_shift;
+
+		old_iobase = port->iobase;
+		old_mapbase = port->mapbase;
+		old_type = port->type;
+		old_hub6 = port->hub6;
+		old_iotype = port->iotype;
+		old_shift = port->regshift;
+
+		if (old_type != PORT_UNKNOWN)
+			port->ops->release_port(port);
+
+		port->iobase = new_port;
+		port->type = new_serial.type;
+		port->hub6 = new_serial.hub6;
+		port->iotype = new_serial.io_type;
+		port->regshift = new_serial.iomem_reg_shift;
+		port->mapbase = (unsigned long)new_serial.iomem_base;
+
+		if (port->type != PORT_UNKNOWN) {
+			retval = port->ops->request_port(port);
+		} else {
+			retval = 0;
+		}
+
+		if (retval && old_type != PORT_UNKNOWN) {
+			port->iobase = old_iobase;
+			port->type = old_type;
+			port->hub6 = old_hub6;
+			port->iotype = old_iotype;
+			port->regshift = old_shift;
+			port->mapbase = old_mapbase;
+			retval = port->ops->request_port(port);
+			if (retval)
+				port->type = PORT_UNKNOWN;
+
+			retval = -EBUSY;
+		}
+	}
+
+	port->irq              = new_serial.irq;
+	port->uartclk          = new_serial.baud_base * 16;
+	port->flags            = (port->flags & ~UPF_CHANGE_MASK) |
+		(new_flags & UPF_CHANGE_MASK);
+	port->custom_divisor   = new_serial.custom_divisor;
+	state->close_delay     = new_serial.close_delay;
+	state->closing_wait    = closing_wait;
+	port->fifosize         = new_serial.xmit_fifo_size;
+	if (state->info->tty)
+		state->info->tty->low_latency =
+			(port->flags & UPF_LOW_LATENCY) ? 1 : 0;
+
+check_and_exit:
+	retval = 0;
+	if (port->type == PORT_UNKNOWN)
+		goto exit;
+	if (state->info->flags & UIF_INITIALIZED) {
+		if (((old_flags ^ port->flags) & UPF_SPD_MASK) ||
+				old_custom_divisor != port->custom_divisor) {
+			if (port->flags & UPF_SPD_MASK) {
+				printk(KERN_NOTICE
+						"%s sets custom speed on ttyMP%d. This "
+						"is deprecated.\n", current->comm,
+						port->line);
+			}
+			mp_change_speed(state, NULL);
+		}
+	} else
+		retval = mp_startup(state, 1);
+exit:
+	MP_STATE_UNLOCK(state);
+	return retval;
+}
+
+
+static int mp_get_lsr_info(struct sb_uart_state *state, unsigned int *value)
+{
+	struct sb_uart_port *port = state->port;
+	unsigned int result;
+
+	result = port->ops->tx_empty(port);
+
+	if (port->x_char ||
+			((uart_circ_chars_pending(&state->info->xmit) > 0) &&
+				!state->info->tty->stopped && !state->info->tty->hw_stopped))
+		result &= ~TIOCSER_TEMT;
+
+	return put_user(result, value);
+}
+
+static int mp_tiocmget(struct tty_struct *tty)
+{
+	struct sb_uart_state *state = tty->driver_data;
+	struct sb_uart_port *port = state->port;
+	int result = -EIO;
+
+	MP_STATE_LOCK(state);
+	if (!(tty->flags & (1 << TTY_IO_ERROR))) {
+		result = port->mctrl;
+		spin_lock_irq(&port->lock);
+		result |= port->ops->get_mctrl(port);
+		spin_unlock_irq(&port->lock);
+	}
+	MP_STATE_UNLOCK(state);
+	return result;
+}
+
+static int mp_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
+{
+	struct sb_uart_state *state = tty->driver_data;
+	struct sb_uart_port *port = state->port;
+	int ret = -EIO;
+
+
+	MP_STATE_LOCK(state);
+	if (!(tty->flags & (1 << TTY_IO_ERROR))) {
+		mp_update_mctrl(port, set, clear);
+		ret = 0;
+	}
+	MP_STATE_UNLOCK(state);
+
+	return ret;
+}
+
+static int mp_break_ctl(struct tty_struct *tty, int break_state)
+{
+	struct sb_uart_state *state = tty->driver_data;
+	struct sb_uart_port *port = state->port;
+
+	MP_STATE_LOCK(state);
+
+	if (port->type != PORT_UNKNOWN)
+		port->ops->break_ctl(port, break_state);
+
+	MP_STATE_UNLOCK(state);
+	return 0;
+}
+
+static int mp_do_autoconfig(struct sb_uart_state *state)
+{
+	struct sb_uart_port *port = state->port;
+	int flags, ret;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (mutex_lock_interruptible(&state->mutex))
+		return -ERESTARTSYS;
+	ret = -EBUSY;
+	if (uart_users(state) == 1) {
+		mp_shutdown(state);
+
+		if (port->type != PORT_UNKNOWN)
+			port->ops->release_port(port);
+
+		flags = UART_CONFIG_TYPE;
+		if (port->flags & UPF_AUTO_IRQ)
+			flags |= UART_CONFIG_IRQ;
+
+		port->ops->config_port(port, flags);
+
+		ret = mp_startup(state, 1);
+	}
+	MP_STATE_UNLOCK(state);
+	return ret;
+}
+
+static int mp_wait_modem_status(struct sb_uart_state *state, unsigned long arg)
+{
+	struct sb_uart_port *port = state->port;
+	DECLARE_WAITQUEUE(wait, current);
+	struct sb_uart_icount cprev, cnow;
+	int ret;
+
+	spin_lock_irq(&port->lock);
+	memcpy(&cprev, &port->icount, sizeof(struct sb_uart_icount));
+
+	port->ops->enable_ms(port);
+	spin_unlock_irq(&port->lock);
+
+	add_wait_queue(&state->info->delta_msr_wait, &wait);
+	for (;;) {
+		spin_lock_irq(&port->lock);
+		memcpy(&cnow, &port->icount, sizeof(struct sb_uart_icount));
+		spin_unlock_irq(&port->lock);
+
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+				((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+				((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
+				((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
+			ret = 0;
+			break;
+		}
+
+		schedule();
+
+		if (signal_pending(current)) {
+			ret = -ERESTARTSYS;
+			break;
+		}
+
+		cprev = cnow;
+	}
+
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&state->info->delta_msr_wait, &wait);
+
+	return ret;
+}
+
+static int mp_get_count(struct sb_uart_state *state, struct serial_icounter_struct *icnt)
+{
+	struct serial_icounter_struct icount;
+	struct sb_uart_icount cnow;
+	struct sb_uart_port *port = state->port;
+
+	spin_lock_irq(&port->lock);
+	memcpy(&cnow, &port->icount, sizeof(struct sb_uart_icount));
+	spin_unlock_irq(&port->lock);
+
+	icount.cts         = cnow.cts;
+	icount.dsr         = cnow.dsr;
+	icount.rng         = cnow.rng;
+	icount.dcd         = cnow.dcd;
+	icount.rx          = cnow.rx;
+	icount.tx          = cnow.tx;
+	icount.frame       = cnow.frame;
+	icount.overrun     = cnow.overrun;
+	icount.parity      = cnow.parity;
+	icount.brk         = cnow.brk;
+	icount.buf_overrun = cnow.buf_overrun;
+
+	return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
+}
+
+static int mp_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
+{
+	struct sb_uart_state *state = tty->driver_data;
+	struct mp_port *info = (struct mp_port *)state->port;
+	int ret = -ENOIOCTLCMD;
+
+
+	switch (cmd) {
+		case TIOCSMULTIDROP:
+			/* set multi-drop mode enable or disable, and default operation mode is H/W mode */
+			if (info->port.type == PORT_16C105XA)
+			{
+				//arg &= ~0x6;
+				//state->port->mdmode = 0;
+				return set_multidrop_mode((struct sb_uart_port *)info, (unsigned int)arg);
+			}
+			ret = -ENOTSUPP;
+			break;
+		case GETDEEPFIFO:
+			ret = get_deep_fifo(state->port);
+			return ret;
+		case SETDEEPFIFO:
+			ret = set_deep_fifo(state->port,arg);
+			deep[state->port->line] = arg;
+			return ret;
+		case SETTTR:
+			if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
+				ret = sb1054_set_register(state->port,PAGE_4,SB105X_TTR,arg);
+				ttr[state->port->line] = arg;
+			}
+			return ret;
+		case SETRTR:
+			if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
+				ret = sb1054_set_register(state->port,PAGE_4,SB105X_RTR,arg);
+				rtr[state->port->line] = arg;
+			}
+			return ret;
+		case GETTTR:
+			if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
+				ret = sb1054_get_register(state->port,PAGE_4,SB105X_TTR);
+			}
+			return ret;
+		case GETRTR:
+			if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
+				ret = sb1054_get_register(state->port,PAGE_4,SB105X_RTR);
+			}
+			return ret;
+
+		case SETFCR:
+			if (info->port.type == PORT_16C105X || info->port.type == PORT_16C105XA){
+				ret = sb1054_set_register(state->port,PAGE_1,SB105X_FCR,arg);
+			}
+			else{
+				serial_out(info,2,arg);
+			}
+
+			return ret;
+		case TIOCSMDADDR:
+			/* set multi-drop address */
+			if (info->port.type == PORT_16C105XA)
+			{
+				state->port->mdmode |= MDMODE_ADDR;
+				return set_multidrop_addr((struct sb_uart_port *)info, (unsigned int)arg);
+			}
+			ret = -ENOTSUPP;
+			break;
+
+		case TIOCGMDADDR:
+			/* set multi-drop address */
+			if ((info->port.type == PORT_16C105XA) && (state->port->mdmode & MDMODE_ADDR))
+			{
+				return get_multidrop_addr((struct sb_uart_port *)info);
+			}
+			ret = -ENOTSUPP;
+			break;
+
+		case TIOCSENDADDR:
+			/* send address in multi-drop mode */
+			if ((info->port.type == PORT_16C105XA) 
+					&& (state->port->mdmode & (MDMODE_ENABLE)))
+			{
+				if (mp_chars_in_buffer(tty) > 0)
+				{
+					tty_wait_until_sent(tty, 0);
+				}
+				//while ((serial_in(info, UART_LSR) & 0x60) != 0x60);
+				//while (sb1054_get_register(state->port, PAGE_2, SB105X_TFCR) != 0);
+				while ((serial_in(info, UART_LSR) & 0x60) != 0x60);
+				serial_out(info, UART_SCR, (int)arg);
+			}
+			break;
+
+		case TIOCGSERIAL:
+			ret = mp_get_info(state, (struct serial_struct *)arg);
+			break;
+
+		case TIOCSSERIAL:
+			ret = mp_set_info(state, (struct serial_struct *)arg);
+			break;
+
+		case TIOCSERCONFIG:
+			ret = mp_do_autoconfig(state);
+			break;
+
+		case TIOCSERGWILD: /* obsolete */
+		case TIOCSERSWILD: /* obsolete */
+			ret = 0;
+			break;
+			/* for Multiport */
+		case TIOCGNUMOFPORT: /* Get number of ports */
+			return NR_PORTS;
+		case TIOCGGETDEVID:
+			return mp_devs[arg].device_id;
+		case TIOCGGETREV:
+			return mp_devs[arg].revision;
+		case TIOCGGETNRPORTS:
+			return mp_devs[arg].nr_ports;
+		case TIOCGGETBDNO:
+			return NR_BOARD;
+		case TIOCGGETINTERFACE:
+			if (mp_devs[arg].revision == 0xc0)
+			{
+				/* for SB16C1053APCI */
+				return (sb1053a_get_interface(info, info->port.line));
+			}
+			else
+			{
+				return (inb(mp_devs[arg].option_reg_addr+MP_OPTR_IIR0+(state->port->line/8)));
+			}
+		case TIOCGGETPORTTYPE:
+			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 ,  
+					info->interface_config_addr);
+			return 0;
+		case TIOCSPTPNOECHO: /* set to multi-drop mode(RS422) or echo mode(RS485) */
+			outb( ( inb(info->interface_config_addr) & ~0x03 )  ,             
+					info->interface_config_addr);
+			return 0;
+	}
+
+	if (ret != -ENOIOCTLCMD)
+		goto out;
+
+	if (tty->flags & (1 << TTY_IO_ERROR)) {
+		ret = -EIO;
+		goto out;
+	}
+
+	switch (cmd) {
+		case TIOCMIWAIT:
+			ret = mp_wait_modem_status(state, arg);
+			break;
+
+		case TIOCGICOUNT:
+			ret = mp_get_count(state, (struct serial_icounter_struct *)arg);
+			break;
+	}
+
+	if (ret != -ENOIOCTLCMD)
+		goto out;
+
+	MP_STATE_LOCK(state);
+	switch (cmd) {
+		case TIOCSERGETLSR: /* Get line status register */
+			ret = mp_get_lsr_info(state, (unsigned int *)arg);
+			break;
+
+		default: {
+					struct sb_uart_port *port = state->port;
+					if (port->ops->ioctl)
+						ret = port->ops->ioctl(port, cmd, arg);
+					break;
+				}
+	}
+
+	MP_STATE_UNLOCK(state);
+out:
+	return ret;
+}
+
+static void mp_set_termios(struct tty_struct *tty, struct MP_TERMIOS *old_termios)
+{
+	struct sb_uart_state *state = tty->driver_data;
+	unsigned long flags;
+	unsigned int cflag = tty->termios.c_cflag;
+
+#define RELEVANT_IFLAG(iflag)	((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+	if ((cflag ^ old_termios->c_cflag) == 0 &&
+			RELEVANT_IFLAG(tty->termios.c_iflag ^ old_termios->c_iflag) == 0)
+		return;
+
+	mp_change_speed(state, old_termios);
+
+	if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
+		uart_clear_mctrl(state->port, TIOCM_RTS | TIOCM_DTR);
+
+	if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
+		unsigned int mask = TIOCM_DTR;
+		if (!(cflag & CRTSCTS) ||
+				!test_bit(TTY_THROTTLED, &tty->flags))
+			mask |= TIOCM_RTS;
+		uart_set_mctrl(state->port, mask);
+	}
+
+	if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
+		spin_lock_irqsave(&state->port->lock, flags);
+		tty->hw_stopped = 0;
+		__mp_start(tty);
+		spin_unlock_irqrestore(&state->port->lock, flags);
+	}
+
+	if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
+		spin_lock_irqsave(&state->port->lock, flags);
+		if (!(state->port->ops->get_mctrl(state->port) & TIOCM_CTS)) {
+			tty->hw_stopped = 1;
+			state->port->ops->stop_tx(state->port);
+		}
+		spin_unlock_irqrestore(&state->port->lock, flags);
+	}
+}
+
+static void mp_close(struct tty_struct *tty, struct file *filp)
+{
+	struct sb_uart_state *state = tty->driver_data;
+	struct sb_uart_port *port;
+
+	printk("mp_close!\n");
+	if (!state || !state->port)
+		return;
+
+	port = state->port;
+
+	printk("close1 %d\n", __LINE__);
+	MP_STATE_LOCK(state);
+
+	printk("close2 %d\n", __LINE__);
+	if (tty_hung_up_p(filp))
+		goto done;
+
+	printk("close3 %d\n", __LINE__);
+	if ((tty->count == 1) && (state->count != 1)) {
+		printk("mp_close: bad serial port count; tty->count is 1, "
+				"state->count is %d\n", state->count);
+		state->count = 1;
+	}
+	printk("close4 %d\n", __LINE__);
+	if (--state->count < 0) {
+		printk("rs_close: bad serial port count for ttyMP%d: %d\n",
+				port->line, state->count);
+		state->count = 0;
+	}
+	if (state->count)
+		goto done;
+
+	tty->closing = 1;
+
+	printk("close5 %d\n", __LINE__);
+	if (state->closing_wait != USF_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, state->closing_wait);
+
+	printk("close6 %d\n", __LINE__);
+	if (state->info->flags & UIF_INITIALIZED) {
+		unsigned long flags;
+		spin_lock_irqsave(&port->lock, flags);
+		port->ops->stop_rx(port);
+		spin_unlock_irqrestore(&port->lock, flags);
+		mp_wait_until_sent(tty, port->timeout);
+	}
+	printk("close7 %d\n", __LINE__);
+
+	mp_shutdown(state);
+	printk("close8 %d\n", __LINE__);
+	mp_flush_buffer(tty);
+	tty_ldisc_flush(tty);
+	tty->closing = 0;
+	state->info->tty = NULL;
+	if (state->info->blocked_open) 
+	{
+		if (state->close_delay)
+		{
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(state->close_delay);
+		}
+	}
+	else
+	{
+		mp_change_pm(state, 3);
+	}
+	printk("close8 %d\n", __LINE__);
+
+	state->info->flags &= ~UIF_NORMAL_ACTIVE;
+	wake_up_interruptible(&state->info->open_wait);
+
+done:
+	printk("close done\n");
+	MP_STATE_UNLOCK(state);
+	module_put(THIS_MODULE);
+}
+
+static void mp_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	struct sb_uart_state *state = tty->driver_data;
+	struct sb_uart_port *port = state->port;
+	unsigned long char_time, expire;
+
+	if (port->type == PORT_UNKNOWN || port->fifosize == 0)
+		return;
+
+	char_time = (port->timeout - HZ/50) / port->fifosize;
+	char_time = char_time / 5;
+	if (char_time == 0)
+		char_time = 1;
+	if (timeout && timeout < char_time)
+		char_time = timeout;
+
+	if (timeout == 0 || timeout > 2 * port->timeout)
+		timeout = 2 * port->timeout;
+
+	expire = jiffies + timeout;
+
+	while (!port->ops->tx_empty(port)) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(char_time);
+		if (signal_pending(current))
+			break;
+		if (time_after(jiffies, expire))
+			break;
+	}
+	set_current_state(TASK_RUNNING); /* might not be needed */
+}
+
+static void mp_hangup(struct tty_struct *tty)
+{
+	struct sb_uart_state *state = tty->driver_data;
+
+	MP_STATE_LOCK(state);
+	if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) {
+		mp_flush_buffer(tty);
+		mp_shutdown(state);
+		state->count = 0;
+		state->info->flags &= ~UIF_NORMAL_ACTIVE;
+		state->info->tty = NULL;
+		wake_up_interruptible(&state->info->open_wait);
+		wake_up_interruptible(&state->info->delta_msr_wait);
+	}
+	MP_STATE_UNLOCK(state);
+}
+
+static void mp_update_termios(struct sb_uart_state *state)
+{
+	struct tty_struct *tty = state->info->tty;
+	struct sb_uart_port *port = state->port;
+
+	if (!(tty->flags & (1 << TTY_IO_ERROR))) {
+		mp_change_speed(state, NULL);
+
+		if (tty->termios.c_cflag & CBAUD)
+			uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+	}
+}
+
+static int mp_block_til_ready(struct file *filp, struct sb_uart_state *state)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	struct sb_uart_info *info = state->info;
+	struct sb_uart_port *port = state->port;
+	unsigned int mctrl;
+
+	info->blocked_open++;
+	state->count--;
+
+	add_wait_queue(&info->open_wait, &wait);
+	while (1) {
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		if (tty_hung_up_p(filp) || info->tty == NULL)
+			break;
+
+		if (!(info->flags & UIF_INITIALIZED))
+			break;
+
+		if ((filp->f_flags & O_NONBLOCK) ||
+				(info->tty->termios.c_cflag & CLOCAL) ||
+				(info->tty->flags & (1 << TTY_IO_ERROR))) {
+			break;
+		}
+
+		if (info->tty->termios.c_cflag & CBAUD)
+			uart_set_mctrl(port, TIOCM_DTR);
+
+		spin_lock_irq(&port->lock);
+		port->ops->enable_ms(port);
+		mctrl = port->ops->get_mctrl(port);
+		spin_unlock_irq(&port->lock);
+		if (mctrl & TIOCM_CAR)
+			break;
+
+		MP_STATE_UNLOCK(state);
+		schedule();
+		MP_STATE_LOCK(state);
+
+		if (signal_pending(current))
+			break;
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&info->open_wait, &wait);
+
+	state->count++;
+	info->blocked_open--;
+
+	if (signal_pending(current))
+		return -ERESTARTSYS;
+
+	if (!info->tty || tty_hung_up_p(filp))
+		return -EAGAIN;
+
+	return 0;
+}
+
+static struct sb_uart_state *uart_get(struct uart_driver *drv, int line)
+{
+	struct sb_uart_state *state;
+
+	MP_MUTEX_LOCK(mp_mutex);
+	state = drv->state + line;
+	if (mutex_lock_interruptible(&state->mutex)) {
+		state = ERR_PTR(-ERESTARTSYS);
+		goto out;
+	}
+	state->count++;
+	if (!state->port) {
+		state->count--;
+		MP_STATE_UNLOCK(state);
+		state = ERR_PTR(-ENXIO);
+		goto out;
+	}
+
+	if (!state->info) {
+		state->info = kmalloc(sizeof(struct sb_uart_info), GFP_KERNEL);
+		if (state->info) {
+			memset(state->info, 0, sizeof(struct sb_uart_info));
+			init_waitqueue_head(&state->info->open_wait);
+			init_waitqueue_head(&state->info->delta_msr_wait);
+
+			state->port->info = state->info;
+
+			tasklet_init(&state->info->tlet, mp_tasklet_action,
+					(unsigned long)state);
+		} else {
+			state->count--;
+			MP_STATE_UNLOCK(state);
+			state = ERR_PTR(-ENOMEM);
+		}
+	}
+
+out:
+	MP_MUTEX_UNLOCK(mp_mutex);
+	return state;
+}
+
+static int mp_open(struct tty_struct *tty, struct file *filp)
+{
+	struct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state;
+	struct sb_uart_state *state;
+	int retval;
+	int  line = tty->index;
+	struct mp_port *mtpt;
+
+	retval = -ENODEV;
+	if (line >= tty->driver->num)
+		goto fail;
+
+	state = uart_get(drv, line);
+
+	mtpt  = (struct mp_port *)state->port;
+
+	if (IS_ERR(state)) {
+		retval = PTR_ERR(state);
+		goto fail;
+	}
+
+	tty->driver_data = state;
+	tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0;
+	tty->alt_speed = 0;
+	state->info->tty = tty;
+
+	if (tty_hung_up_p(filp)) {
+		retval = -EAGAIN;
+		state->count--;
+		MP_STATE_UNLOCK(state);
+		goto fail;
+	}
+
+	if (state->count == 1)
+		mp_change_pm(state, 0);
+
+	retval = mp_startup(state, 0);
+
+	if (retval == 0)
+		retval = mp_block_til_ready(filp, state);
+	MP_STATE_UNLOCK(state);
+
+	if (retval == 0 && !(state->info->flags & UIF_NORMAL_ACTIVE)) {
+		state->info->flags |= UIF_NORMAL_ACTIVE;
+
+		mp_update_termios(state);
+	}
+
+	uart_clear_mctrl(state->port, TIOCM_RTS);
+	try_module_get(THIS_MODULE);
+fail:
+	return retval;
+}
+
+
+static const char *mp_type(struct sb_uart_port *port)
+{
+	const char *str = NULL;
+
+	if (port->ops->type)
+		str = port->ops->type(port);
+
+	if (!str)
+		str = "unknown";
+
+	return str;
+}
+
+static void mp_change_pm(struct sb_uart_state *state, int pm_state)
+{
+	struct sb_uart_port *port = state->port;
+	if (port->ops->pm)
+		port->ops->pm(port, pm_state, state->pm_state);
+	state->pm_state = pm_state;
+}
+
+static inline void mp_report_port(struct uart_driver *drv, struct sb_uart_port *port)
+{
+	char address[64];
+
+	switch (port->iotype) {
+		case UPIO_PORT:
+			snprintf(address, sizeof(address),"I/O 0x%x", port->iobase);
+			break;
+		case UPIO_HUB6:
+			snprintf(address, sizeof(address),"I/O 0x%x offset 0x%x", port->iobase, port->hub6);
+			break;
+		case UPIO_MEM:
+			snprintf(address, sizeof(address),"MMIO 0x%lx", port->mapbase);
+			break;
+		default:
+			snprintf(address, sizeof(address),"*unknown*" );
+			strlcpy(address, "*unknown*", sizeof(address));
+			break;
+	}
+
+	printk( "%s%d at %s (irq = %d) is a %s\n",
+			drv->dev_name, port->line, address, port->irq, mp_type(port));
+
+}
+
+static void mp_configure_port(struct uart_driver *drv, struct sb_uart_state *state, struct sb_uart_port *port)
+{
+	unsigned int flags;
+
+
+	if (!port->iobase && !port->mapbase && !port->membase)
+	{
+		DPRINTK("%s error \n",__FUNCTION__);
+		return;
+	}
+	flags = UART_CONFIG_TYPE;
+	if (port->flags & UPF_AUTO_IRQ)
+		flags |= UART_CONFIG_IRQ;
+	if (port->flags & UPF_BOOT_AUTOCONF) {
+		port->type = PORT_UNKNOWN;
+		port->ops->config_port(port, flags);
+	}
+
+	if (port->type != PORT_UNKNOWN) {
+		unsigned long flags;
+
+		mp_report_port(drv, port);
+
+		spin_lock_irqsave(&port->lock, flags);
+		port->ops->set_mctrl(port, 0);
+		spin_unlock_irqrestore(&port->lock, flags);
+
+		mp_change_pm(state, 3);
+	}
+}
+
+static void mp_unconfigure_port(struct uart_driver *drv, struct sb_uart_state *state)
+{
+	struct sb_uart_port *port = state->port;
+	struct sb_uart_info *info = state->info;
+
+	if (info && info->tty)
+		tty_hangup(info->tty);
+
+	MP_STATE_LOCK(state);
+
+	state->info = NULL;
+
+	if (port->type != PORT_UNKNOWN)
+		port->ops->release_port(port);
+
+	port->type = PORT_UNKNOWN;
+
+	if (info) {
+		tasklet_kill(&info->tlet);
+		kfree(info);
+	}
+
+	MP_STATE_UNLOCK(state);
+}
+static struct tty_operations mp_ops = {
+	.open		= mp_open,
+	.close		= mp_close,
+	.write		= mp_write,
+	.put_char	= mp_put_char,
+	.flush_chars	= mp_put_chars,
+	.write_room	= mp_write_room,
+	.chars_in_buffer= mp_chars_in_buffer,
+	.flush_buffer	= mp_flush_buffer,
+	.ioctl		= mp_ioctl,
+	.throttle	= mp_throttle,
+	.unthrottle	= mp_unthrottle,
+	.send_xchar	= mp_send_xchar,
+	.set_termios	= mp_set_termios,
+	.stop		= mp_stop,
+	.start		= mp_start,
+	.hangup		= mp_hangup,
+	.break_ctl	= mp_break_ctl,
+	.wait_until_sent= mp_wait_until_sent,
+#ifdef CONFIG_PROC_FS
+	.proc_fops	= NULL,
+#endif
+	.tiocmget	= mp_tiocmget,
+	.tiocmset	= mp_tiocmset,
+};
+
+static int mp_register_driver(struct uart_driver *drv)
+{
+	struct tty_driver *normal = NULL;
+	int i, retval;
+
+	drv->state = kmalloc(sizeof(struct sb_uart_state) * drv->nr, GFP_KERNEL);
+	retval = -ENOMEM;
+	if (!drv->state)
+	{
+		printk("SB PCI Error: Kernel memory allocation error!\n");
+		goto out;
+	}
+	memset(drv->state, 0, sizeof(struct sb_uart_state) * drv->nr);
+
+	normal = alloc_tty_driver(drv->nr);
+	if (!normal)
+	{
+		printk("SB PCI Error: tty allocation error!\n");
+		goto out;
+	}
+
+	drv->tty_driver = normal;
+
+	normal->owner           = drv->owner;
+	normal->magic		= TTY_DRIVER_MAGIC;
+	normal->driver_name     = drv->driver_name;
+	normal->name		= drv->dev_name;
+	normal->major		= drv->major;
+	normal->minor_start	= drv->minor;
+
+	normal->num		= MAX_MP_PORT ; 
+
+	normal->type		= TTY_DRIVER_TYPE_SERIAL;
+	normal->subtype		= SERIAL_TYPE_NORMAL;
+	normal->init_termios	= tty_std_termios;
+	normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	normal->flags		= TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	normal->driver_state    = drv;
+
+	tty_set_operations(normal, &mp_ops);
+
+for (i = 0; i < drv->nr; i++) {
+	struct sb_uart_state *state = drv->state + i;
+
+	state->close_delay     = 500;   
+	state->closing_wait    = 30000; 
+
+	mutex_init(&state->mutex);
+	}
+
+	retval = tty_register_driver(normal);
+out:
+	if (retval < 0) {
+		printk("Register tty driver Fail!\n");
+		put_tty_driver(normal);
+		kfree(drv->state);
+	}
+
+	return retval;
+}
+
+void mp_unregister_driver(struct uart_driver *drv)
+{
+    struct tty_driver *normal = NULL;
+
+    normal = drv->tty_driver;
+
+    if (!normal)
+    {
+        return;
+    }
+
+    tty_unregister_driver(normal);
+    put_tty_driver(normal);
+    drv->tty_driver = NULL;
+
+
+    if (drv->state)
+    {
+        kfree(drv->state);
+    }
+
+}
+
+static int mp_add_one_port(struct uart_driver *drv, struct sb_uart_port *port)
+{
+	struct sb_uart_state *state;
+	int ret = 0;
+
+
+	if (port->line >= drv->nr)
+		return -EINVAL;
+
+	state = drv->state + port->line;
+
+	MP_MUTEX_LOCK(mp_mutex);
+	if (state->port) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	state->port = port;
+
+	spin_lock_init(&port->lock);
+	port->cons = drv->cons;
+	port->info = state->info;
+
+	mp_configure_port(drv, state, port);
+
+	tty_register_device(drv->tty_driver, port->line, port->dev);
+
+out:
+	MP_MUTEX_UNLOCK(mp_mutex);
+
+
+	return ret;
+}
+
+static int mp_remove_one_port(struct uart_driver *drv, struct sb_uart_port *port)
+{
+	struct sb_uart_state *state = drv->state + port->line;
+
+	if (state->port != port)
+		printk(KERN_ALERT "Removing wrong port: %p != %p\n",
+				state->port, port);
+
+	MP_MUTEX_LOCK(mp_mutex);
+
+	tty_unregister_device(drv->tty_driver, port->line);
+
+	mp_unconfigure_port(drv, state);
+	state->port = NULL;
+	MP_MUTEX_UNLOCK(mp_mutex);
+
+	return 0;
+}
+
+static void autoconfig(struct mp_port *mtpt, unsigned int probeflags)
+{
+	unsigned char status1, scratch, scratch2, scratch3;
+	unsigned char save_lcr, save_mcr;
+	unsigned long flags;
+
+	unsigned char u_type;
+	unsigned char b_ret = 0;
+
+	if (!mtpt->port.iobase && !mtpt->port.mapbase && !mtpt->port.membase)
+		return;
+
+	DEBUG_AUTOCONF("ttyMP%d: autoconf (0x%04x, 0x%p): ",
+			mtpt->port.line, mtpt->port.iobase, mtpt->port.membase);
+
+	spin_lock_irqsave(&mtpt->port.lock, flags);
+
+	if (!(mtpt->port.flags & UPF_BUGGY_UART)) {
+		scratch = serial_inp(mtpt, UART_IER);
+		serial_outp(mtpt, UART_IER, 0);
+#ifdef __i386__
+		outb(0xff, 0x080);
+#endif
+		scratch2 = serial_inp(mtpt, UART_IER) & 0x0f;
+		serial_outp(mtpt, UART_IER, 0x0F);
+#ifdef __i386__
+		outb(0, 0x080);
+#endif
+		scratch3 = serial_inp(mtpt, UART_IER) & 0x0F;
+		serial_outp(mtpt, UART_IER, scratch);
+		if (scratch2 != 0 || scratch3 != 0x0F) {
+			DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
+					scratch2, scratch3);
+			goto out;
+		}
+	}
+
+	save_mcr = serial_in(mtpt, UART_MCR);
+	save_lcr = serial_in(mtpt, UART_LCR);
+
+	if (!(mtpt->port.flags & UPF_SKIP_TEST)) {
+		serial_outp(mtpt, UART_MCR, UART_MCR_LOOP | 0x0A);
+		status1 = serial_inp(mtpt, UART_MSR) & 0xF0;
+		serial_outp(mtpt, UART_MCR, save_mcr);
+		if (status1 != 0x90) {
+			DEBUG_AUTOCONF("LOOP test failed (%02x) ",
+					status1);
+			goto out;
+		}
+	}
+
+	serial_outp(mtpt, UART_LCR, 0xBF);
+	serial_outp(mtpt, UART_EFR, 0);
+	serial_outp(mtpt, UART_LCR, 0);
+
+	serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO);
+	scratch = serial_in(mtpt, UART_IIR) >> 6;
+
+	DEBUG_AUTOCONF("iir=%d ", scratch);
+	if(mtpt->device->nr_ports >= 8)
+		b_ret = read_option_register(mtpt,(MP_OPTR_DIR0 + ((mtpt->port.line)/8)));
+	else	
+		b_ret = read_option_register(mtpt,MP_OPTR_DIR0);
+	u_type = (b_ret & 0xf0) >> 4;
+	if(mtpt->port.type == PORT_UNKNOWN )
+	{
+		switch (u_type)
+		{
+			case DIR_UART_16C550:
+				mtpt->port.type = PORT_16C55X;
+				break;
+			case DIR_UART_16C1050:
+				mtpt->port.type = PORT_16C105X;
+				break;
+			case DIR_UART_16C1050A:
+				if (mtpt->port.line < 2)
+				{
+					mtpt->port.type = PORT_16C105XA;
+				}
+				else
+				{
+					if (mtpt->device->device_id & 0x50)
+					{
+						mtpt->port.type = PORT_16C55X;
+					}
+					else
+					{
+						mtpt->port.type = PORT_16C105X;
+					}
+				}
+				break;
+			default:	
+				mtpt->port.type = PORT_UNKNOWN;
+				break;
+		}
+	}
+
+	if(mtpt->port.type == PORT_UNKNOWN )
+	{
+printk("unknow2\n");
+		switch (scratch) {
+			case 0:
+			case 1:
+				mtpt->port.type = PORT_UNKNOWN;
+				break;
+			case 2:
+			case 3:
+				mtpt->port.type = PORT_16C55X;
+				break;
+		}
+	}
+
+	serial_outp(mtpt, UART_LCR, save_lcr);
+
+	mtpt->port.fifosize = uart_config[mtpt->port.type].dfl_xmit_fifo_size;
+	mtpt->capabilities = uart_config[mtpt->port.type].flags;
+
+	if (mtpt->port.type == PORT_UNKNOWN)
+		goto out;
+	serial_outp(mtpt, UART_MCR, save_mcr);
+	serial_outp(mtpt, UART_FCR, (UART_FCR_ENABLE_FIFO |
+				UART_FCR_CLEAR_RCVR |
+				UART_FCR_CLEAR_XMIT));
+	serial_outp(mtpt, UART_FCR, 0);
+	(void)serial_in(mtpt, UART_RX);
+	serial_outp(mtpt, UART_IER, 0);
+
+out:
+	spin_unlock_irqrestore(&mtpt->port.lock, flags);
+	DEBUG_AUTOCONF("type=%s\n", uart_config[mtpt->port.type].name);
+}
+
+static void autoconfig_irq(struct mp_port *mtpt)
+{
+	unsigned char save_mcr, save_ier;
+	unsigned long irqs;
+	int irq;
+
+	/* forget possible initially masked and pending IRQ */
+	probe_irq_off(probe_irq_on());
+	save_mcr = serial_inp(mtpt, UART_MCR);
+	save_ier = serial_inp(mtpt, UART_IER);
+	serial_outp(mtpt, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
+
+	irqs = probe_irq_on();
+	serial_outp(mtpt, UART_MCR, 0);
+	serial_outp(mtpt, UART_MCR,
+		UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
+
+	serial_outp(mtpt, UART_IER, 0x0f);    /* enable all intrs */
+	(void)serial_inp(mtpt, UART_LSR);
+	(void)serial_inp(mtpt, UART_RX);
+	(void)serial_inp(mtpt, UART_IIR);
+	(void)serial_inp(mtpt, UART_MSR);
+	serial_outp(mtpt, UART_TX, 0xFF);
+	irq = probe_irq_off(irqs);
+
+	serial_outp(mtpt, UART_MCR, save_mcr);
+	serial_outp(mtpt, UART_IER, save_ier);
+
+	mtpt->port.irq = (irq > 0) ? irq : 0;
+}
+
+static void multi_stop_tx(struct sb_uart_port *port)
+{
+	struct mp_port *mtpt = (struct mp_port *)port;
+
+	if (mtpt->ier & UART_IER_THRI) {
+		mtpt->ier &= ~UART_IER_THRI;
+		serial_out(mtpt, UART_IER, mtpt->ier);
+	}
+
+	tasklet_schedule(&port->info->tlet);
+}
+
+static void multi_start_tx(struct sb_uart_port *port)
+{
+	struct mp_port *mtpt = (struct mp_port *)port;
+
+	if (!(mtpt->ier & UART_IER_THRI)) {
+		mtpt->ier |= UART_IER_THRI;
+		serial_out(mtpt, UART_IER, mtpt->ier);
+	}
+}
+
+static void multi_stop_rx(struct sb_uart_port *port)
+{
+	struct mp_port *mtpt = (struct mp_port *)port;
+
+	mtpt->ier &= ~UART_IER_RLSI;
+	mtpt->port.read_status_mask &= ~UART_LSR_DR;
+	serial_out(mtpt, UART_IER, mtpt->ier);
+}
+
+static void multi_enable_ms(struct sb_uart_port *port)
+{
+	struct mp_port *mtpt = (struct mp_port *)port;
+
+	mtpt->ier |= UART_IER_MSI;
+	serial_out(mtpt, UART_IER, mtpt->ier);
+}
+
+
+static _INLINE_ void receive_chars(struct mp_port *mtpt, int *status )
+{
+	struct tty_struct *tty = mtpt->port.info->tty;
+	unsigned char lsr = *status;
+	int max_count = 256;
+	unsigned char ch;
+	char flag;
+
+	//lsr &= mtpt->port.read_status_mask;
+
+	do {
+		if ((lsr & UART_LSR_PE) && (mtpt->port.mdmode & MDMODE_ENABLE))
+		{
+			ch = serial_inp(mtpt, UART_RX);
+		}
+		else if (lsr & UART_LSR_SPECIAL) 
+		{
+			flag = 0;
+			ch = serial_inp(mtpt, UART_RX);
+
+			if (lsr & UART_LSR_BI) 
+			{
+
+				mtpt->port.icount.brk++;
+				flag = TTY_BREAK;
+
+				if (sb_uart_handle_break(&mtpt->port))
+					goto ignore_char;
+			} 
+			if (lsr & UART_LSR_PE)
+			{
+				mtpt->port.icount.parity++;
+				flag = TTY_PARITY;
+			}
+			if (lsr & UART_LSR_FE)
+			{
+				mtpt->port.icount.frame++;
+				flag = TTY_FRAME;
+			}
+			if (lsr & UART_LSR_OE)
+			{
+				mtpt->port.icount.overrun++;
+				flag = TTY_OVERRUN;
+			}
+			tty_insert_flip_char(tty, ch, flag);
+		}
+		else
+		{
+			ch = serial_inp(mtpt, UART_RX);
+			tty_insert_flip_char(tty, ch, 0);
+		}
+ignore_char:
+		lsr = serial_inp(mtpt, UART_LSR);
+	} while ((lsr & UART_LSR_DR) && (max_count-- > 0));
+
+	tty_flip_buffer_push(tty);
+}
+
+
+
+
+static _INLINE_ void transmit_chars(struct mp_port *mtpt)
+{
+	struct circ_buf *xmit = &mtpt->port.info->xmit;
+	int count;
+
+	if (mtpt->port.x_char) {
+		serial_outp(mtpt, UART_TX, mtpt->port.x_char);
+		mtpt->port.icount.tx++;
+		mtpt->port.x_char = 0;
+		return;
+	}
+	if (uart_circ_empty(xmit) || uart_tx_stopped(&mtpt->port)) {
+		multi_stop_tx(&mtpt->port);
+		return;
+	}
+
+	count = uart_circ_chars_pending(xmit);
+
+	if(count > mtpt->port.fifosize)
+	{
+		count = mtpt->port.fifosize;
+	}
+
+	printk("[%d] mdmode: %x\n", mtpt->port.line, mtpt->port.mdmode);
+	do {
+#if 0
+		/* check multi-drop mode */
+		if ((mtpt->port.mdmode & (MDMODE_ENABLE | MDMODE_ADDR)) == (MDMODE_ENABLE | MDMODE_ADDR))
+		{
+			printk("send address\n");
+			/* send multi-drop address */
+			serial_out(mtpt, UART_SCR, xmit->buf[xmit->tail]);
+		}
+		else
+#endif
+		{
+			serial_out(mtpt, UART_TX, xmit->buf[xmit->tail]);
+		}
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		mtpt->port.icount.tx++;
+	} while (--count > 0);
+}
+
+
+
+static _INLINE_ void check_modem_status(struct mp_port *mtpt)
+{
+	int status;
+
+	status = serial_in(mtpt, UART_MSR);
+
+	if ((status & UART_MSR_ANY_DELTA) == 0)
+		return;
+
+	if (status & UART_MSR_TERI)
+		mtpt->port.icount.rng++;
+	if (status & UART_MSR_DDSR)
+		mtpt->port.icount.dsr++;
+	if (status & UART_MSR_DDCD)
+		sb_uart_handle_dcd_change(&mtpt->port, status & UART_MSR_DCD);
+	if (status & UART_MSR_DCTS)
+		sb_uart_handle_cts_change(&mtpt->port, status & UART_MSR_CTS);
+
+	wake_up_interruptible(&mtpt->port.info->delta_msr_wait);
+}
+
+static inline void multi_handle_port(struct mp_port *mtpt)
+{
+	unsigned int status = serial_inp(mtpt, UART_LSR);
+
+	//printk("lsr: %x\n", status);
+
+	if ((status & UART_LSR_DR) || (status & UART_LSR_SPECIAL))
+		receive_chars(mtpt, &status);
+	check_modem_status(mtpt);
+	if (status & UART_LSR_THRE)
+	{
+		if ((mtpt->port.type == PORT_16C105X)
+			|| (mtpt->port.type == PORT_16C105XA))
+			transmit_chars(mtpt);
+		else
+		{
+			if (mtpt->interface >= RS485NE)
+				uart_set_mctrl(&mtpt->port, TIOCM_RTS);
+			
+			transmit_chars(mtpt);
+
+
+			if (mtpt->interface >= RS485NE)
+			{
+				while((status=serial_in(mtpt,UART_LSR) &0x60)!=0x60);
+				uart_clear_mctrl(&mtpt->port, TIOCM_RTS);
+			}
+		}
+	}
+}
+
+
+
+static irqreturn_t multi_interrupt(int irq, void *dev_id)
+{
+	struct irq_info *iinfo = dev_id;
+	struct list_head *lhead, *end = NULL;
+	int pass_counter = 0;
+
+
+	spin_lock(&iinfo->lock);
+
+	lhead = iinfo->head;
+	do {
+		struct mp_port *mtpt;
+		unsigned int iir;
+
+		mtpt = list_entry(lhead, struct mp_port, list);
+		
+		iir = serial_in(mtpt, UART_IIR);
+		printk("intrrupt! port %d, iir 0x%x\n", mtpt->port.line, iir); //wlee
+		if (!(iir & UART_IIR_NO_INT)) 
+		{
+			printk("interrupt handle\n");
+			spin_lock(&mtpt->port.lock);
+			multi_handle_port(mtpt);
+			spin_unlock(&mtpt->port.lock);
+
+			end = NULL;
+		} else if (end == NULL)
+			end = lhead;
+
+		lhead = lhead->next;
+		if (lhead == iinfo->head && pass_counter++ > PASS_LIMIT) 
+		{
+			printk(KERN_ERR "multi: too much work for "
+					"irq%d\n", irq);
+			printk( "multi: too much work for "
+					"irq%d\n", irq);
+			break;
+		}
+	} while (lhead != end);
+
+	spin_unlock(&iinfo->lock);
+
+
+        return IRQ_HANDLED;
+}
+
+static void serial_do_unlink(struct irq_info *i, struct mp_port *mtpt)
+{
+	spin_lock_irq(&i->lock);
+
+	if (!list_empty(i->head)) {
+		if (i->head == &mtpt->list)
+			i->head = i->head->next;
+		list_del(&mtpt->list);
+	} else {
+		i->head = NULL;
+	}
+
+	spin_unlock_irq(&i->lock);
+}
+
+static int serial_link_irq_chain(struct mp_port *mtpt)
+{
+	struct irq_info *i = irq_lists + mtpt->port.irq;
+	int ret, irq_flags = mtpt->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
+	spin_lock_irq(&i->lock);
+
+	if (i->head) {
+		list_add(&mtpt->list, i->head);
+		spin_unlock_irq(&i->lock);
+
+		ret = 0;
+	} else {
+		INIT_LIST_HEAD(&mtpt->list);
+		i->head = &mtpt->list;
+		spin_unlock_irq(&i->lock);
+
+		ret = request_irq(mtpt->port.irq, multi_interrupt,
+				irq_flags, "serial", i);
+		if (ret < 0)
+			serial_do_unlink(i, mtpt);
+	}
+
+	return ret;
+}
+
+
+
+
+static void serial_unlink_irq_chain(struct mp_port *mtpt)
+{
+	struct irq_info *i = irq_lists + mtpt->port.irq;
+
+	if (list_empty(i->head))
+	{
+		free_irq(mtpt->port.irq, i);
+	}
+	serial_do_unlink(i, mtpt);
+}
+
+static void multi_timeout(unsigned long data)
+{
+	struct mp_port *mtpt = (struct mp_port *)data;
+
+
+	spin_lock(&mtpt->port.lock);
+	multi_handle_port(mtpt);
+	spin_unlock(&mtpt->port.lock);
+
+	mod_timer(&mtpt->timer, jiffies+1 );
+}
+
+static unsigned int multi_tx_empty(struct sb_uart_port *port)
+{
+	struct mp_port *mtpt = (struct mp_port *)port;
+	unsigned long flags;
+	unsigned int ret;
+
+	spin_lock_irqsave(&mtpt->port.lock, flags);
+	ret = serial_in(mtpt, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+	spin_unlock_irqrestore(&mtpt->port.lock, flags);
+
+	return ret;
+}
+
+
+static unsigned int multi_get_mctrl(struct sb_uart_port *port)
+{
+	struct mp_port *mtpt = (struct mp_port *)port;
+	unsigned char status;
+	unsigned int ret;
+
+	status = serial_in(mtpt, UART_MSR);
+
+	ret = 0;
+	if (status & UART_MSR_DCD)
+		ret |= TIOCM_CAR;
+	if (status & UART_MSR_RI)
+		ret |= TIOCM_RNG;
+	if (status & UART_MSR_DSR)
+		ret |= TIOCM_DSR;
+	if (status & UART_MSR_CTS)
+		ret |= TIOCM_CTS;
+	return ret;
+}
+
+static void multi_set_mctrl(struct sb_uart_port *port, unsigned int mctrl)
+{
+	struct mp_port *mtpt = (struct mp_port *)port;
+	unsigned char mcr = 0;
+
+	mctrl &= 0xff;
+
+	if (mctrl & TIOCM_RTS)
+		mcr |= UART_MCR_RTS;
+	if (mctrl & TIOCM_DTR)
+		mcr |= UART_MCR_DTR;
+	if (mctrl & TIOCM_OUT1)
+		mcr |= UART_MCR_OUT1;
+	if (mctrl & TIOCM_OUT2)
+		mcr |= UART_MCR_OUT2;
+	if (mctrl & TIOCM_LOOP)
+		mcr |= UART_MCR_LOOP;
+
+
+	serial_out(mtpt, UART_MCR, mcr);
+}
+
+
+static void multi_break_ctl(struct sb_uart_port *port, int break_state)
+{
+	struct mp_port *mtpt = (struct mp_port *)port;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mtpt->port.lock, flags);
+	if (break_state == -1)
+		mtpt->lcr |= UART_LCR_SBC;
+	else
+		mtpt->lcr &= ~UART_LCR_SBC;
+	serial_out(mtpt, UART_LCR, mtpt->lcr);
+	spin_unlock_irqrestore(&mtpt->port.lock, flags);
+}
+
+
+
+static int multi_startup(struct sb_uart_port *port)
+{
+	struct mp_port *mtpt = (struct mp_port *)port;
+	unsigned long flags;
+	int retval;
+
+	mtpt->capabilities = uart_config[mtpt->port.type].flags;
+	mtpt->mcr = 0;
+
+	if (mtpt->capabilities & UART_CLEAR_FIFO) {
+		serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO);
+		serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO |
+				UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+		serial_outp(mtpt, UART_FCR, 0);
+	}
+
+	(void) serial_inp(mtpt, UART_LSR);
+	(void) serial_inp(mtpt, UART_RX);
+	(void) serial_inp(mtpt, UART_IIR);
+	(void) serial_inp(mtpt, UART_MSR);
+	//test-wlee 9-bit disable
+	serial_outp(mtpt, UART_MSR, 0);
+
+
+	if (!(mtpt->port.flags & UPF_BUGGY_UART) &&
+			(serial_inp(mtpt, UART_LSR) == 0xff)) {
+		printk("ttyS%d: LSR safety check engaged!\n", mtpt->port.line);
+		//return -ENODEV;
+	}
+
+	if ((!is_real_interrupt(mtpt->port.irq)) || (mtpt->poll_type==TYPE_POLL)) {
+		unsigned int timeout = mtpt->port.timeout;
+
+		timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
+
+		mtpt->timer.data = (unsigned long)mtpt;
+		mod_timer(&mtpt->timer, jiffies + timeout);
+	} 
+	else 
+	{
+		retval = serial_link_irq_chain(mtpt);
+		if (retval)
+			return retval;
+	}
+
+	serial_outp(mtpt, UART_LCR, UART_LCR_WLEN8);
+
+	spin_lock_irqsave(&mtpt->port.lock, flags);
+	if ((is_real_interrupt(mtpt->port.irq))||(mtpt->poll_type==TYPE_INTERRUPT))
+		mtpt->port.mctrl |= TIOCM_OUT2;
+
+	multi_set_mctrl(&mtpt->port, mtpt->port.mctrl);
+	spin_unlock_irqrestore(&mtpt->port.lock, flags);
+
+	
+	mtpt->ier = UART_IER_RLSI | UART_IER_RDI;
+	serial_outp(mtpt, UART_IER, mtpt->ier);
+
+	(void) serial_inp(mtpt, UART_LSR);
+	(void) serial_inp(mtpt, UART_RX);
+	(void) serial_inp(mtpt, UART_IIR);
+	(void) serial_inp(mtpt, UART_MSR);
+
+	return 0;
+}
+
+
+
+static void multi_shutdown(struct sb_uart_port *port)
+{
+	struct mp_port *mtpt = (struct mp_port *)port;
+	unsigned long flags;
+
+
+	mtpt->ier = 0;
+	serial_outp(mtpt, UART_IER, 0);
+
+	spin_lock_irqsave(&mtpt->port.lock, flags);
+	mtpt->port.mctrl &= ~TIOCM_OUT2;
+
+	multi_set_mctrl(&mtpt->port, mtpt->port.mctrl);
+	spin_unlock_irqrestore(&mtpt->port.lock, flags);
+
+	serial_out(mtpt, UART_LCR, serial_inp(mtpt, UART_LCR) & ~UART_LCR_SBC);
+	serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO |
+			UART_FCR_CLEAR_RCVR |
+			UART_FCR_CLEAR_XMIT);
+	serial_outp(mtpt, UART_FCR, 0);
+
+
+	(void) serial_in(mtpt, UART_RX);
+
+	if ((!is_real_interrupt(mtpt->port.irq))||(mtpt->poll_type==TYPE_POLL))
+	{
+		del_timer_sync(&mtpt->timer);
+	}
+	else
+	{
+		serial_unlink_irq_chain(mtpt);
+	}
+}
+
+
+
+static unsigned int multi_get_divisor(struct sb_uart_port *port, unsigned int baud)
+{
+	unsigned int quot;
+
+	if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+			baud == (port->uartclk/4))
+		quot = 0x8001;
+	else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+			baud == (port->uartclk/8))
+		quot = 0x8002;
+	else
+		quot = sb_uart_get_divisor(port, baud);
+
+	return quot;
+}
+
+
+
+
+static void multi_set_termios(struct sb_uart_port *port, struct MP_TERMIOS *termios, struct MP_TERMIOS *old)
+{
+	struct mp_port *mtpt = (struct mp_port *)port;
+	unsigned char cval, fcr = 0;
+	unsigned long flags;
+	unsigned int baud, quot;
+
+	switch (termios->c_cflag & CSIZE) {
+		case CS5:
+			cval = 0x00;
+			break;
+		case CS6:
+			cval = 0x01;
+			break;
+		case CS7:
+			cval = 0x02;
+			break;
+		default:
+		case CS8:
+			cval = 0x03;
+			break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		cval |= 0x04;
+	if (termios->c_cflag & PARENB)
+		cval |= UART_LCR_PARITY;
+	if (!(termios->c_cflag & PARODD))
+		cval |= UART_LCR_EPAR;
+
+#ifdef CMSPAR
+	if (termios->c_cflag & CMSPAR)
+		cval |= UART_LCR_SPAR;
+#endif
+
+	baud = sb_uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+	quot = multi_get_divisor(port, baud);
+
+	if (mtpt->capabilities & UART_USE_FIFO) {
+		//if (baud < 2400)
+		//	fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
+		//else
+		//	fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
+
+		//	fcr = UART_FCR_ENABLE_FIFO | 0x90;
+			fcr = fcr_arr[mtpt->port.line];
+	}
+
+	spin_lock_irqsave(&mtpt->port.lock, flags);
+
+	sb_uart_update_timeout(port, termios->c_cflag, baud);
+
+	mtpt->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+	if (termios->c_iflag & INPCK)
+		mtpt->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		mtpt->port.read_status_mask |= UART_LSR_BI;
+
+	mtpt->port.ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		mtpt->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+	if (termios->c_iflag & IGNBRK) {
+		mtpt->port.ignore_status_mask |= UART_LSR_BI;
+		if (termios->c_iflag & IGNPAR)
+			mtpt->port.ignore_status_mask |= UART_LSR_OE;
+	}
+
+	if ((termios->c_cflag & CREAD) == 0)
+		mtpt->port.ignore_status_mask |= UART_LSR_DR;
+
+	mtpt->ier &= ~UART_IER_MSI;
+	if (UART_ENABLE_MS(&mtpt->port, termios->c_cflag))
+		mtpt->ier |= UART_IER_MSI;
+
+	serial_out(mtpt, UART_IER, mtpt->ier);
+
+	if (mtpt->capabilities & UART_STARTECH) {
+		serial_outp(mtpt, UART_LCR, 0xBF);
+		serial_outp(mtpt, UART_EFR,
+				termios->c_cflag & CRTSCTS ? UART_EFR_CTS :0);
+	}
+
+	serial_outp(mtpt, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
+
+	serial_outp(mtpt, UART_DLL, quot & 0xff);     /* LS of divisor */
+	serial_outp(mtpt, UART_DLM, quot >> 8);       /* MS of divisor */
+
+	serial_outp(mtpt, UART_LCR, cval);        /* reset DLAB */
+	mtpt->lcr = cval;                 /* Save LCR */
+
+	if (fcr & UART_FCR_ENABLE_FIFO) {
+		/* emulated UARTs (Lucent Venus 167x) need two steps */
+		serial_outp(mtpt, UART_FCR, UART_FCR_ENABLE_FIFO);
+	}
+
+	serial_outp(mtpt, UART_FCR, fcr);     /* set fcr */
+
+
+	if ((mtpt->port.type == PORT_16C105X)
+		|| (mtpt->port.type == PORT_16C105XA))
+	{
+		if(deep[mtpt->port.line]!=0)
+			set_deep_fifo(port, ENABLE);
+
+		if (mtpt->interface != RS232)
+			set_auto_rts(port,mtpt->interface);
+
+	}
+	else
+	{
+		if (mtpt->interface >= RS485NE)
+		{
+			uart_clear_mctrl(&mtpt->port, TIOCM_RTS);
+		}
+	}
+
+	if(mtpt->device->device_id == PCI_DEVICE_ID_MP4M)
+	{
+		SendATCommand(mtpt);
+		printk("SendATCommand\n");
+	}	
+	multi_set_mctrl(&mtpt->port, mtpt->port.mctrl);
+	spin_unlock_irqrestore(&mtpt->port.lock, flags);
+}
+
+static void multi_pm(struct sb_uart_port *port, unsigned int state, unsigned int oldstate)
+{
+	struct mp_port *mtpt = (struct mp_port *)port;
+	if (state) {
+		if (mtpt->capabilities & UART_STARTECH) {
+			serial_outp(mtpt, UART_LCR, 0xBF);
+			serial_outp(mtpt, UART_EFR, UART_EFR_ECB);
+			serial_outp(mtpt, UART_LCR, 0);
+			serial_outp(mtpt, UART_IER, UART_IERX_SLEEP);
+			serial_outp(mtpt, UART_LCR, 0xBF);
+			serial_outp(mtpt, UART_EFR, 0);
+			serial_outp(mtpt, UART_LCR, 0);
+		}
+
+		if (mtpt->pm)
+			mtpt->pm(port, state, oldstate);
+	} 
+	else 
+	{
+		if (mtpt->capabilities & UART_STARTECH) {
+			serial_outp(mtpt, UART_LCR, 0xBF);
+			serial_outp(mtpt, UART_EFR, UART_EFR_ECB);
+			serial_outp(mtpt, UART_LCR, 0);
+			serial_outp(mtpt, UART_IER, 0);
+			serial_outp(mtpt, UART_LCR, 0xBF);
+			serial_outp(mtpt, UART_EFR, 0);
+			serial_outp(mtpt, UART_LCR, 0);
+		}
+
+		if (mtpt->pm)
+			mtpt->pm(port, state, oldstate);
+	}
+}
+
+static void multi_release_std_resource(struct mp_port *mtpt)
+{
+	unsigned int size = 8 << mtpt->port.regshift;
+
+	switch (mtpt->port.iotype) {
+		case UPIO_MEM:
+			if (!mtpt->port.mapbase)
+				break;
+
+			if (mtpt->port.flags & UPF_IOREMAP) {
+				iounmap(mtpt->port.membase);
+				mtpt->port.membase = NULL;
+			}
+
+			release_mem_region(mtpt->port.mapbase, size);
+			break;
+
+		case UPIO_HUB6:
+		case UPIO_PORT:
+			release_region(mtpt->port.iobase,size);
+			break;
+	}
+}
+
+static void multi_release_port(struct sb_uart_port *port)
+{
+}
+
+static int multi_request_port(struct sb_uart_port *port)
+{
+	return 0;
+}
+
+static void multi_config_port(struct sb_uart_port *port, int flags)
+{
+	struct mp_port *mtpt = (struct mp_port *)port;
+	int probeflags = PROBE_ANY;
+
+	if (flags & UART_CONFIG_TYPE)
+		autoconfig(mtpt, probeflags);
+	if (mtpt->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
+		autoconfig_irq(mtpt);
+
+	if (mtpt->port.type == PORT_UNKNOWN)
+		multi_release_std_resource(mtpt);
+}
+
+static int multi_verify_port(struct sb_uart_port *port, struct serial_struct *ser)
+{
+	if (ser->irq >= NR_IRQS || ser->irq < 0 ||
+			ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
+			ser->type == PORT_STARTECH)
+		return -EINVAL;
+	return 0;
+}
+
+static const char * multi_type(struct sb_uart_port *port)
+{
+	int type = port->type;
+
+	if (type >= ARRAY_SIZE(uart_config))
+		type = 0;
+	return uart_config[type].name;
+}
+
+static struct sb_uart_ops multi_pops = {
+	.tx_empty   = multi_tx_empty,
+	.set_mctrl  = multi_set_mctrl,
+	.get_mctrl  = multi_get_mctrl,
+	.stop_tx    = multi_stop_tx,
+	.start_tx   = multi_start_tx,
+	.stop_rx    = multi_stop_rx,
+	.enable_ms  = multi_enable_ms,
+	.break_ctl  = multi_break_ctl,
+	.startup    = multi_startup,
+	.shutdown   = multi_shutdown,
+	.set_termios    = multi_set_termios,
+	.pm     	= multi_pm,
+	.type       	= multi_type,
+	.release_port   = multi_release_port,
+	.request_port   = multi_request_port,
+	.config_port    = multi_config_port,
+	.verify_port    = multi_verify_port,
+};
+
+static struct uart_driver multi_reg = {
+	.owner          = THIS_MODULE,
+	.driver_name    = "goldel_tulip",
+	.dev_name       = "ttyMP",
+	.major          = SB_TTY_MP_MAJOR,
+	.minor          = 0,
+	.nr             = MAX_MP_PORT, 
+	.cons           = NULL,
+};
+
+static void __init multi_init_ports(void)
+{
+	struct mp_port *mtpt;
+	static int first = 1;
+	int i,j,k;
+	unsigned char osc;
+	unsigned char b_ret = 0;
+	static struct mp_device_t * sbdev; 
+
+	if (!first)
+		return;
+	first = 0;
+
+	mtpt = multi_ports; 
+
+	for (k=0;k<NR_BOARD;k++)
+	{
+		sbdev = &mp_devs[k];
+
+		for (i = 0; i < sbdev->nr_ports; i++, mtpt++) 
+		{
+			mtpt->device 		= sbdev;
+			mtpt->port.iobase   = sbdev->uart_access_addr + 8*i;
+			mtpt->port.irq      = sbdev->irq;
+			if ( ((sbdev->device_id == PCI_DEVICE_ID_MP4)&&(sbdev->revision==0x91)))
+				mtpt->interface_config_addr = sbdev->option_reg_addr + 0x08 + i;
+			else if (sbdev->revision == 0xc0)
+				mtpt->interface_config_addr = sbdev->option_reg_addr + 0x08 + (i & 0x1);
+			else
+				mtpt->interface_config_addr = sbdev->option_reg_addr + 0x08 + i/8;
+
+			mtpt->option_base_addr = sbdev->option_reg_addr;
+
+			mtpt->poll_type = sbdev->poll_type;
+
+			mtpt->port.uartclk  = BASE_BAUD * 16;
+
+			/* get input clock infomation */
+			osc = inb(sbdev->option_reg_addr + MP_OPTR_DIR0 + i/8) & 0x0F;
+			if (osc==0x0f)
+				osc = 0;
+			for(j=0;j<osc;j++)
+				mtpt->port.uartclk *= 2;
+			mtpt->port.flags    |= STD_COM_FLAGS | UPF_SHARE_IRQ ;
+			mtpt->port.iotype   = UPIO_PORT;
+			mtpt->port.ops      = &multi_pops;
+
+			if (sbdev->revision == 0xc0)
+			{
+				/* for SB16C1053APCI */
+				b_ret = sb1053a_get_interface(mtpt, i);
+			}
+			else
+			{
+				b_ret = read_option_register(mtpt,(MP_OPTR_IIR0 + i/8));
+				printk("IIR_RET = %x\n",b_ret);
+			}
+
+			if(IIR_RS232 == (b_ret & IIR_RS232))
+			{
+				mtpt->interface = RS232;
+			}
+			if(IIR_RS422 == (b_ret & IIR_RS422))
+			{
+				mtpt->interface = RS422PTP;
+			}
+			if(IIR_RS485 == (b_ret & IIR_RS485))
+			{
+				mtpt->interface = RS485NE;
+			}
+		}
+	}
+}
+
+static void __init multi_register_ports(struct uart_driver *drv)
+{
+	int i;
+
+	multi_init_ports();
+
+	for (i = 0; i < NR_PORTS; i++) {
+		struct mp_port *mtpt = &multi_ports[i];
+
+		mtpt->port.line = i;
+		mtpt->port.ops = &multi_pops;
+		init_timer(&mtpt->timer);
+		mtpt->timer.function = multi_timeout;
+		mp_add_one_port(drv, &mtpt->port);
+	}
+}
+
+/**
+ * pci_remap_base - remap BAR value of pci device
+ *
+ * PARAMETERS
+ *  pcidev  - pci_dev structure address
+ *  offset  - BAR offset PCI_BASE_ADDRESS_0 ~ PCI_BASE_ADDRESS_4
+ *  address - address to be changed BAR value
+ *  size	- size of address space 
+ *
+ * RETURNS
+ *  If this function performs successful, it returns 0. Otherwise, It returns -1.
+ */
+static int pci_remap_base(struct pci_dev *pcidev, unsigned int offset, 
+		unsigned int address, unsigned int size) 
+{
+#if 0
+	struct resource *root;
+	unsigned index = (offset - 0x10) >> 2;
+#endif
+
+	pci_write_config_dword(pcidev, offset, address);
+#if 0
+	root = pcidev->resource[index].parent;
+	release_resource(&pcidev->resource[index]);
+	address &= ~0x1;
+	pcidev->resource[index].start = address;
+	pcidev->resource[index].end	  = address + size - 1;
+
+	if (request_resource(root, &pcidev->resource[index]) != NULL)
+	{
+		printk(KERN_ERR "pci remap conflict!! 0x%x\n", address);
+		return (-1);
+	}
+#endif
+
+	return (0);
+}
+
+static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd)
+{
+	static struct mp_device_t * sbdev = mp_devs;
+	unsigned long addr = 0;
+	int j;
+	struct resource * ret = NULL;
+
+	sbdev->device_id = brd.device_id;
+	pci_read_config_byte(pcidev, PCI_CLASS_REVISION, &(sbdev->revision));
+	sbdev->name = brd.name;
+	sbdev->uart_access_addr = pcidev->resource[0].start & PCI_BASE_ADDRESS_IO_MASK;
+
+	/* check revision. The SB16C1053APCI's option i/o address is BAR4 */
+	if (sbdev->revision == 0xc0)
+	{
+		/* SB16C1053APCI */
+		sbdev->option_reg_addr = pcidev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK;
+	}
+	else
+	{
+		sbdev->option_reg_addr = pcidev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
+	}
+#if 1	
+	if (sbdev->revision == 0xc0)
+	{
+		outb(0x00, sbdev->option_reg_addr + MP_OPTR_GPOCR);
+		inb(sbdev->option_reg_addr + MP_OPTR_GPOCR);
+		outb(0x83, sbdev->option_reg_addr + MP_OPTR_GPOCR);
+	}
+#endif
+
+	sbdev->irq = pcidev->irq;
+
+	if ((brd.device_id & 0x0800) || !(brd.device_id &0xff00))
+	{
+		sbdev->poll_type = TYPE_INTERRUPT;
+	}
+	else
+	{
+		sbdev->poll_type = TYPE_POLL;
+	}
+
+	/* codes which is specific to each board*/
+	switch(brd.device_id){
+		case PCI_DEVICE_ID_MP1 :
+		case PCIE_DEVICE_ID_MP1 :
+		case PCIE_DEVICE_ID_MP1E :
+		case PCIE_DEVICE_ID_GT_MP1 :
+			sbdev->nr_ports = 1;
+			break;
+		case PCI_DEVICE_ID_MP2 :
+		case PCIE_DEVICE_ID_MP2 :
+		case PCIE_DEVICE_ID_GT_MP2 :
+		case PCIE_DEVICE_ID_MP2B :
+		case PCIE_DEVICE_ID_MP2E :
+			sbdev->nr_ports = 2;
+
+			/* serial base address remap */
+			if (sbdev->revision == 0xc0)
+			{
+				int prev_port_addr = 0;
+
+				pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &prev_port_addr);
+				pci_remap_base(pcidev, PCI_BASE_ADDRESS_1, prev_port_addr + 8, 8);
+			}
+			break;
+		case PCI_DEVICE_ID_MP4 :
+		case PCI_DEVICE_ID_MP4A :
+		case PCIE_DEVICE_ID_MP4 :
+		case PCI_DEVICE_ID_GT_MP4 :
+		case PCI_DEVICE_ID_GT_MP4A :
+		case PCIE_DEVICE_ID_GT_MP4 :
+		case PCI_DEVICE_ID_MP4M :
+		case PCIE_DEVICE_ID_MP4B :
+			sbdev->nr_ports = 4;
+
+			if(sbdev->revision == 0x91){
+				sbdev->reserved_addr[0] = pcidev->resource[0].start & PCI_BASE_ADDRESS_IO_MASK;
+				outb(0x03 , sbdev->reserved_addr[0] + 0x01);
+				outb(0x03 , sbdev->reserved_addr[0] + 0x02);
+				outb(0x01 , sbdev->reserved_addr[0] + 0x20);
+				outb(0x00 , sbdev->reserved_addr[0] + 0x21);
+				request_region(sbdev->reserved_addr[0], 32, sbdev->name);
+				sbdev->uart_access_addr = pcidev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
+				sbdev->option_reg_addr = pcidev->resource[2].start & PCI_BASE_ADDRESS_IO_MASK;
+			}
+
+			/* SB16C1053APCI */
+			if (sbdev->revision == 0xc0)
+			{
+				int prev_port_addr = 0;
+
+				pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &prev_port_addr);
+				pci_remap_base(pcidev, PCI_BASE_ADDRESS_1, prev_port_addr + 8, 8);
+				pci_remap_base(pcidev, PCI_BASE_ADDRESS_2, prev_port_addr + 16, 8);
+				pci_remap_base(pcidev, PCI_BASE_ADDRESS_3, prev_port_addr + 24, 8);
+			}
+			break;
+		case PCI_DEVICE_ID_MP6 :
+		case PCI_DEVICE_ID_MP6A :
+		case PCI_DEVICE_ID_GT_MP6 :
+		case PCI_DEVICE_ID_GT_MP6A :
+			sbdev->nr_ports = 6;
+
+			/* SB16C1053APCI */
+			if (sbdev->revision == 0xc0)
+			{
+				int prev_port_addr = 0;
+
+				pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &prev_port_addr);
+				pci_remap_base(pcidev, PCI_BASE_ADDRESS_1, prev_port_addr + 8, 8);
+				pci_remap_base(pcidev, PCI_BASE_ADDRESS_2, prev_port_addr + 16, 16);
+				pci_remap_base(pcidev, PCI_BASE_ADDRESS_3, prev_port_addr + 32, 16);
+			}
+			break;
+		case PCI_DEVICE_ID_MP8 :
+		case PCIE_DEVICE_ID_MP8 :
+		case PCI_DEVICE_ID_GT_MP8 :
+		case PCIE_DEVICE_ID_GT_MP8 :
+		case PCIE_DEVICE_ID_MP8B :
+			sbdev->nr_ports = 8;
+			break;
+		case PCI_DEVICE_ID_MP32 :
+		case PCIE_DEVICE_ID_MP32 :
+		case PCI_DEVICE_ID_GT_MP32 :
+		case PCIE_DEVICE_ID_GT_MP32 :
+			{
+				int portnum_hex=0;
+				portnum_hex = inb(sbdev->option_reg_addr);
+				sbdev->nr_ports = ((portnum_hex/16)*10) + (portnum_hex % 16);
+			}
+			break;
+		case PCI_DEVICE_ID_MP2S1P :
+			sbdev->nr_ports = 2;
+
+			/* SB16C1053APCI */
+			if (sbdev->revision == 0xc0)
+			{
+				int prev_port_addr = 0;
+
+				pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &prev_port_addr);
+				pci_remap_base(pcidev, PCI_BASE_ADDRESS_1, prev_port_addr + 8, 8);
+			}
+
+			/* add PC compatible parallel port */
+			parport_pc_probe_port(pcidev->resource[2].start, pcidev->resource[3].start, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &pcidev->dev, 0);
+			break;
+		case PCI_DEVICE_ID_MP1P :
+			/* add PC compatible parallel port */
+			parport_pc_probe_port(pcidev->resource[2].start, pcidev->resource[3].start, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &pcidev->dev, 0);
+			break;
+	}
+
+	ret = request_region(sbdev->uart_access_addr, (8*sbdev->nr_ports), sbdev->name);
+
+	if (sbdev->revision == 0xc0)
+	{
+		ret = request_region(sbdev->option_reg_addr, 0x40, sbdev->name);
+	}
+	else
+	{
+		ret = request_region(sbdev->option_reg_addr, 0x20, sbdev->name);
+	}
+
+
+	NR_BOARD++;
+	NR_PORTS += sbdev->nr_ports;
+
+	/* Enable PCI interrupt */
+	addr = sbdev->option_reg_addr + MP_OPTR_IMR0;
+	for(j=0; j < (sbdev->nr_ports/8)+1; j++)
+	{
+		if (sbdev->poll_type == TYPE_INTERRUPT)
+		{
+			outb(0xff,addr +j);
+		}
+	}
+	sbdev++;
+
+	return 0;
+}
+
+static int __init multi_init(void)
+{
+	int ret, i;
+	struct pci_dev  *dev = NULL;
+
+	if(fcr_count==0)
+	{
+		for(i=0;i<256;i++)
+		{
+			fcr_arr[i] = 0x01;
+			
+		}
+	}
+	if(deep_count==0)
+	{
+		for(i=0;i<256;i++)
+		{
+			deep[i] = 1;
+			
+		}
+	}
+	if(rtr_count==0)
+        {
+                for(i=0;i<256;i++)
+                {
+                        rtr[i] = 0x10;
+                }
+        }
+	if(ttr_count==0)
+        {
+                for(i=0;i<256;i++)
+                {
+                        ttr[i] = 0x38;
+                }
+        }
+
+
+printk("MULTI INIT\n");
+	for( i=0; i< mp_nrpcibrds; i++)
+	{
+
+		while( (dev = pci_get_device(mp_pciboards[i].vendor_id, mp_pciboards[i].device_id, dev) ) )
+
+		{
+printk("FOUND~~~\n");
+//	Cent OS bug fix
+//			if (mp_pciboards[i].device_id & 0x0800)
+			{
+				int status;
+	        		pci_disable_device(dev);
+	        		status = pci_enable_device(dev);
+            
+	   		     	if (status != 0)
+        			{ 
+               				printk("Multiport Board Enable Fail !\n\n");
+               				status = -ENXIO;
+                			return status;
+           			}
+			}
+
+			init_mp_dev(dev, mp_pciboards[i]);	
+		}
+	}
+
+	for (i = 0; i < NR_IRQS; i++)
+		spin_lock_init(&irq_lists[i].lock);
+
+	ret = mp_register_driver(&multi_reg);
+
+	if (ret >= 0)
+		multi_register_ports(&multi_reg);
+
+	return ret;
+}
+
+static void __exit multi_exit(void)
+{
+	int i;
+
+	for (i = 0; i < NR_PORTS; i++)
+		mp_remove_one_port(&multi_reg, &multi_ports[i].port);
+
+	mp_unregister_driver(&multi_reg);
+}
+
+module_init(multi_init);
+module_exit(multi_exit);
+
+MODULE_DESCRIPTION("SystemBase Multiport PCI/PCIe CORE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/sb105x/sb_pci_mp.h b/drivers/staging/sb105x/sb_pci_mp.h
new file mode 100644
index 0000000..f33efde
--- /dev/null
+++ b/drivers/staging/sb105x/sb_pci_mp.h
@@ -0,0 +1,293 @@
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/tty_driver.h>
+#include <linux/pci.h>
+#include <linux/circ_buf.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/segment.h>
+#include <asm/serial.h>
+#include <linux/interrupt.h>
+
+
+#include <linux/parport.h>
+#include <linux/ctype.h>
+#include <linux/poll.h>
+
+
+#define MP_TERMIOS  ktermios
+
+#include "sb_mp_register.h"
+#include "sb_ser_core.h"
+
+#define DRIVER_VERSION  "1.1"
+#define DRIVER_DATE     "2012/01/05"
+#define DRIVER_AUTHOR  "SYSTEMBASE<tech@sysbas.com>"
+#define DRIVER_DESC  "SystemBase PCI/PCIe Multiport Core"
+
+#define SB_TTY_MP_MAJOR			54
+#define PCI_VENDOR_ID_MULTIPORT		0x14A1
+
+#define PCI_DEVICE_ID_MP1		0x4d01
+#define PCI_DEVICE_ID_MP2		0x4d02
+#define PCI_DEVICE_ID_MP4		0x4d04
+#define PCI_DEVICE_ID_MP4A		0x4d54
+#define PCI_DEVICE_ID_MP6		0x4d06
+#define PCI_DEVICE_ID_MP6A		0x4d56
+#define PCI_DEVICE_ID_MP8		0x4d08
+#define PCI_DEVICE_ID_MP32		0x4d32
+/* Parallel port */
+#define PCI_DEVICE_ID_MP1P		0x4301
+#define PCI_DEVICE_ID_MP2S1P		0x4303
+
+#define PCIE_DEVICE_ID_MP1		0x4501
+#define PCIE_DEVICE_ID_MP2		0x4502
+#define PCIE_DEVICE_ID_MP4		0x4504
+#define PCIE_DEVICE_ID_MP8		0x4508
+#define PCIE_DEVICE_ID_MP32		0x4532
+
+#define PCIE_DEVICE_ID_MP1E		0x4e01
+#define PCIE_DEVICE_ID_MP2E		0x4e02
+#define PCIE_DEVICE_ID_MP2B		0x4b02
+#define PCIE_DEVICE_ID_MP4B		0x4b04
+#define PCIE_DEVICE_ID_MP8B		0x4b08
+
+#define PCI_DEVICE_ID_GT_MP4		0x0004
+#define PCI_DEVICE_ID_GT_MP4A		0x0054
+#define PCI_DEVICE_ID_GT_MP6		0x0006
+#define PCI_DEVICE_ID_GT_MP6A		0x0056
+#define PCI_DEVICE_ID_GT_MP8		0x0008
+#define PCI_DEVICE_ID_GT_MP32		0x0032
+
+#define PCIE_DEVICE_ID_GT_MP1		0x1501
+#define PCIE_DEVICE_ID_GT_MP2		0x1502
+#define PCIE_DEVICE_ID_GT_MP4		0x1504
+#define PCIE_DEVICE_ID_GT_MP8		0x1508
+#define PCIE_DEVICE_ID_GT_MP32		0x1532
+
+#define PCI_DEVICE_ID_MP4M		0x4604  //modem
+
+#define MAX_MP_DEV  8
+#define BD_MAX_PORT 32 	/* Max serial port in one board */
+#define MAX_MP_PORT 256 /* Max serial port in one PC */
+
+#define PORT_16C105XA	3
+#define PORT_16C105X	2
+#define PORT_16C55X		1
+
+#define ENABLE		1
+#define DISABLE		0
+
+/* ioctls */
+#define TIOCGNUMOFPORT		0x545F
+#define TIOCSMULTIECHO		0x5440
+#define TIOCSPTPNOECHO		0x5441
+
+#define TIOCGOPTIONREG		0x5461
+#define TIOCGDISABLEIRQ		0x5462
+#define TIOCGENABLEIRQ		0x5463
+#define TIOCGSOFTRESET		0x5464
+#define TIOCGSOFTRESETR		0x5465
+#define TIOCGREGINFO		0x5466
+#define TIOCGGETLSR		0x5467
+#define TIOCGGETDEVID		0x5468
+#define TIOCGGETBDNO		0x5469
+#define TIOCGGETINTERFACE	0x546A
+#define TIOCGGETREV		0x546B
+#define TIOCGGETNRPORTS		0x546C
+#define TIOCGGETPORTTYPE	0x546D
+#define GETDEEPFIFO		0x54AA
+#define SETDEEPFIFO		0x54AB
+#define SETFCR			0x54BA
+#define SETTTR			0x54B1
+#define SETRTR			0x54B2
+#define GETTTR			0x54B3
+#define GETRTR			0x54B4
+
+/* multi-drop mode related ioctl commands */
+#define TIOCSMULTIDROP		0x5470
+#define TIOCSMDADDR   		0x5471
+#define TIOCGMDADDR   		0x5472
+#define TIOCSENDADDR		0x5473
+
+
+/* serial interface */
+#define RS232		1 
+#define RS422PTP	2
+#define RS422MD		3
+#define RS485NE		4
+#define RS485ECHO	5
+
+#define serial_inp(up, offset)      serial_in(up, offset)
+#define serial_outp(up, offset, value)  serial_out(up, offset, value)
+	
+#define PASS_LIMIT  256
+#define is_real_interrupt(irq)  ((irq) != 0)
+
+#define PROBE_ANY   (~0)
+
+static DEFINE_MUTEX(mp_mutex);
+#define MP_MUTEX_LOCK(x) mutex_lock(&(x)) 
+#define MP_MUTEX_UNLOCK(x) mutex_unlock(&(x)) 
+#define MP_STATE_LOCK(x) mutex_lock(&((x)->mutex)) 
+#define MP_STATE_UNLOCK(x) mutex_unlock(&((x)->mutex)) 
+        
+
+#define UART_LSR_SPECIAL    0x1E
+        
+#define HIGH_BITS_OFFSET        ((sizeof(long)-sizeof(int))*8)
+#define uart_users(state)       ((state)->count + ((state)->info ? (state)->info->blocked_open : 0))
+
+
+//#define MP_DEBUG 1
+#undef MP_DEBUG
+
+#ifdef MP_DEBUG
+#define DPRINTK(x...)   printk(x)
+#else
+#define DPRINTK(x...)   do { } while (0)
+#endif
+
+#ifdef MP_DEBUG
+#define DEBUG_AUTOCONF(fmt...)  printk(fmt)
+#else
+#define DEBUG_AUTOCONF(fmt...)  do { } while (0)
+#endif
+
+#ifdef MP_DEBUG
+#define DEBUG_INTR(fmt...)  printk(fmt)
+#else
+#define DEBUG_INTR(fmt...)  do { } while (0)
+#endif
+
+#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
+#define SERIAL_INLINE
+#endif
+#ifdef SERIAL_INLINE
+#define _INLINE_ inline
+#else
+#define _INLINE_
+#endif
+
+#define TYPE_POLL	1
+#define TYPE_INTERRUPT	2
+
+
+struct mp_device_t {
+        unsigned short  device_id;
+        unsigned char   revision;
+        char            *name;
+        unsigned long   uart_access_addr;
+        unsigned long   option_reg_addr;
+        unsigned long   reserved_addr[4];
+        int             irq;
+        int             nr_ports;
+        int             poll_type;
+};
+
+typedef struct mppcibrd {
+        char            *name;
+        unsigned short  vendor_id;
+        unsigned short  device_id;
+} mppcibrd_t;
+
+static mppcibrd_t mp_pciboards[] = {
+
+        { "Multi-1 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP1} ,
+        { "Multi-2 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP2} ,
+        { "Multi-4 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP4} ,
+        { "Multi-4 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP4A} ,
+        { "Multi-6 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP6} ,
+        { "Multi-6 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP6A} ,
+        { "Multi-8 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP8} ,
+        { "Multi-32 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP32} ,
+
+        { "Multi-1P PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP1P} ,
+        { "Multi-2S1P PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP2S1P} ,
+
+        { "Multi-4(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP4} ,
+        { "Multi-4(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP4A} ,
+        { "Multi-6(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP6} ,
+        { "Multi-6(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP6A} ,
+        { "Multi-8(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP8} ,
+        { "Multi-32(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP32} ,
+
+        { "Multi-1 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP1} ,
+        { "Multi-2 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP2} ,
+        { "Multi-4 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP4} ,
+        { "Multi-8 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP8} ,
+        { "Multi-32 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP32} ,
+
+        { "Multi-1 PCIe E", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP1E} ,
+        { "Multi-2 PCIe E", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP2E} ,
+        { "Multi-2 PCIe B", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP2B} ,
+        { "Multi-4 PCIe B", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP4B} ,
+        { "Multi-8 PCIe B", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP8B} ,
+
+        { "Multi-1(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP1} ,
+        { "Multi-2(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP2} ,
+        { "Multi-4(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP4} ,
+        { "Multi-8(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP8} ,
+        { "Multi-32(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP32} ,
+
+        { "Multi-4M PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP4M} ,
+};
+
+struct mp_port {
+        struct sb_uart_port port;
+
+        struct timer_list   timer;      /* "no irq" timer */
+        struct list_head    list;       /* ports on this IRQ */
+        unsigned int        capabilities;   /* port capabilities */
+        unsigned short      rev;
+        unsigned char       acr;
+        unsigned char       ier;
+        unsigned char       lcr;
+        unsigned char       mcr;
+        unsigned char       mcr_mask;   /* mask of user bits */
+        unsigned char       mcr_force;  /* mask of forced bits */
+        unsigned char       lsr_break_flag;
+
+        void            (*pm)(struct sb_uart_port *port,
+                        unsigned int state, unsigned int old);
+        struct mp_device_t *device;
+        unsigned long   interface_config_addr;
+        unsigned long   option_base_addr;
+        unsigned char   interface;
+        unsigned char   poll_type;
+};
+
+struct irq_info {
+        spinlock_t      lock;
+        struct list_head    *head;
+};
+
+struct sb105x_uart_config {
+	char    *name;
+	int     dfl_xmit_fifo_size;
+	int     flags;
+};
+
+static const struct sb105x_uart_config uart_config[] = {
+        { "unknown",    1,  0 },
+        { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO },
+        { "SB16C1050",    128,    UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
+        { "SB16C1050A",    128,    UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
+};
+
+
+
diff --git a/drivers/staging/sb105x/sb_ser_core.h b/drivers/staging/sb105x/sb_ser_core.h
new file mode 100644
index 0000000..c8fb991
--- /dev/null
+++ b/drivers/staging/sb105x/sb_ser_core.h
@@ -0,0 +1,368 @@
+#include <linux/wait.h>
+
+#define UART_CONFIG_TYPE	(1 << 0)
+#define UART_CONFIG_IRQ		(1 << 1)
+#define UPIO_PORT		(0)
+#define UPIO_HUB6		(1)
+#define UPIO_MEM		(2)
+#define UPIO_MEM32		(3)
+#define UPIO_AU			(4)			/* Au1x00 type IO */
+#define UPIO_TSI		(5)			/* Tsi108/109 type IO */
+#define UPF_FOURPORT		(1 << 1)
+#define UPF_SAK			(1 << 2)
+#define UPF_SPD_MASK		(0x1030)
+#define UPF_SPD_HI		(0x0010)
+#define UPF_SPD_VHI		(0x0020)
+#define UPF_SPD_CUST		(0x0030)
+#define UPF_SPD_SHI		(0x1000)
+#define UPF_SPD_WARP		(0x1010)
+#define UPF_SKIP_TEST		(1 << 6)
+#define UPF_AUTO_IRQ		(1 << 7)
+#define UPF_HARDPPS_CD		(1 << 11)
+#define UPF_LOW_LATENCY		(1 << 13)
+#define UPF_BUGGY_UART		(1 << 14)
+#define UPF_MAGIC_MULTIPLIER	(1 << 16)
+#define UPF_CONS_FLOW		(1 << 23)
+#define UPF_SHARE_IRQ		(1 << 24)
+#define UPF_BOOT_AUTOCONF	(1 << 28)
+#define UPF_DEAD		(1 << 30)
+#define UPF_IOREMAP		(1 << 31)
+#define UPF_CHANGE_MASK		(0x17fff)
+#define UPF_USR_MASK		(UPF_SPD_MASK|UPF_LOW_LATENCY)
+#define USF_CLOSING_WAIT_INF	(0)
+#define USF_CLOSING_WAIT_NONE	(~0U)
+
+#define UART_XMIT_SIZE	PAGE_SIZE
+
+#define UIF_CHECK_CD		(1 << 25)
+#define UIF_CTS_FLOW		(1 << 26)
+#define UIF_NORMAL_ACTIVE	(1 << 29)
+#define UIF_INITIALIZED		(1 << 31)
+#define UIF_SUSPENDED		(1 << 30)
+
+#define WAKEUP_CHARS		256
+
+#define uart_circ_empty(circ)		((circ)->head == (circ)->tail)
+#define uart_circ_clear(circ)		((circ)->head = (circ)->tail = 0)
+
+#define uart_circ_chars_pending(circ)	\
+	(CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))
+
+#define uart_circ_chars_free(circ)	\
+	(CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))
+
+#define uart_tx_stopped(port)		\
+	((port)->info->tty->stopped || (port)->info->tty->hw_stopped)
+
+#define UART_ENABLE_MS(port,cflag)	((port)->flags & UPF_HARDPPS_CD || \
+					 (cflag) & CRTSCTS || \
+					 !((cflag) & CLOCAL))
+
+
+struct sb_uart_port;
+struct sb_uart_info;
+struct serial_struct;
+struct device;
+
+struct sb_uart_ops {
+	unsigned int	(*tx_empty)(struct sb_uart_port *);
+	void		(*set_mctrl)(struct sb_uart_port *, unsigned int mctrl);
+	unsigned int	(*get_mctrl)(struct sb_uart_port *);
+	void		(*stop_tx)(struct sb_uart_port *);
+	void		(*start_tx)(struct sb_uart_port *);
+	void		(*send_xchar)(struct sb_uart_port *, char ch);
+	void		(*stop_rx)(struct sb_uart_port *);
+	void		(*enable_ms)(struct sb_uart_port *);
+	void		(*break_ctl)(struct sb_uart_port *, int ctl);
+	int		(*startup)(struct sb_uart_port *);
+	void		(*shutdown)(struct sb_uart_port *);
+	void		(*set_termios)(struct sb_uart_port *, struct MP_TERMIOS *new,
+				       struct MP_TERMIOS *old);
+	void		(*pm)(struct sb_uart_port *, unsigned int state,
+			      unsigned int oldstate);
+	int		(*set_wake)(struct sb_uart_port *, unsigned int state);
+
+	const char *(*type)(struct sb_uart_port *);
+
+	void		(*release_port)(struct sb_uart_port *);
+
+	int		(*request_port)(struct sb_uart_port *);
+	void		(*config_port)(struct sb_uart_port *, int);
+	int		(*verify_port)(struct sb_uart_port *, struct serial_struct *);
+	int		(*ioctl)(struct sb_uart_port *, unsigned int, unsigned long);
+};
+
+
+struct sb_uart_icount {
+	__u32	cts;
+	__u32	dsr;
+	__u32	rng;
+	__u32	dcd;
+	__u32	rx;
+	__u32	tx;
+	__u32	frame;
+	__u32	overrun;
+	__u32	parity;
+	__u32	brk;
+	__u32	buf_overrun;
+};
+typedef unsigned int  upf_t;
+
+struct sb_uart_port {
+	spinlock_t		lock;			/* port lock */
+	unsigned int		iobase;			/* in/out[bwl] */
+	unsigned char __iomem	*membase;		/* read/write[bwl] */
+	unsigned int		irq;			/* irq number */
+	unsigned int		uartclk;		/* base uart clock */
+	unsigned int		fifosize;		/* tx fifo size */
+	unsigned char		x_char;			/* xon/xoff char */
+	unsigned char		regshift;		/* reg offset shift */
+	unsigned char		iotype;			/* io access style */
+	unsigned char		unused1;
+
+
+	unsigned int		read_status_mask;	/* driver specific */
+	unsigned int		ignore_status_mask;	/* driver specific */
+	struct sb_uart_info	*info;			/* pointer to parent info */
+	struct sb_uart_icount	icount;			/* statistics */
+
+	struct console		*cons;			/* struct console, if any */
+#ifdef CONFIG_SERIAL_CORE_CONSOLE
+	unsigned long		sysrq;			/* sysrq timeout */
+#endif
+
+	upf_t			flags;
+
+	unsigned int		mctrl;			/* current modem ctrl settings */
+	unsigned int		timeout;		/* character-based timeout */
+	unsigned int		type;			/* port type */
+	const struct sb_uart_ops	*ops;
+	unsigned int		custom_divisor;
+	unsigned int		line;			/* port index */
+	unsigned long		mapbase;		/* for ioremap */
+	struct device		*dev;			/* parent device */
+	unsigned char		hub6;			/* this should be in the 8250 driver */
+	unsigned char		unused[3];
+};
+
+#define mdmode			unused[2]
+#define MDMODE_ADDR		0x1
+#define MDMODE_ENABLE	0x2
+#define MDMODE_AUTO		0x4
+#define MDMODE_ADDRSEND	0x8
+
+struct sb_uart_state {
+	unsigned int		close_delay;		/* msec */
+	unsigned int		closing_wait;		/* msec */
+
+
+	int			count;
+	int			pm_state;
+	struct sb_uart_info	*info;
+	struct sb_uart_port	*port;
+
+	struct mutex		mutex;
+};
+
+typedef unsigned int  uif_t;
+
+struct sb_uart_info {
+	struct tty_struct	*tty;
+	struct circ_buf		xmit;
+	uif_t			flags;
+
+	int			blocked_open;
+
+	struct tasklet_struct	tlet;
+
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	delta_msr_wait;
+};
+
+
+struct module;
+struct tty_driver;
+
+struct uart_driver {
+	struct module		*owner;
+	const char		*driver_name;
+	const char		*dev_name;
+	int			 major;
+	int			 minor;
+	int			 nr;
+	struct console		*cons;
+
+	struct sb_uart_state	*state;
+        struct tty_driver               *tty_driver;
+};
+
+void sb_uart_write_wakeup(struct sb_uart_port *port)
+{
+    struct sb_uart_info *info = port->info;
+    tasklet_schedule(&info->tlet);
+}
+
+void sb_uart_update_timeout(struct sb_uart_port *port, unsigned int cflag,
+			 unsigned int baud)
+{
+    unsigned int bits;
+
+    switch (cflag & CSIZE)
+    {
+        case CS5:
+            bits = 7;
+            break;
+
+        case CS6:
+            bits = 8;
+            break;
+
+        case CS7:
+            bits = 9;
+            break;
+
+        default:
+            bits = 10;
+            break;
+    }
+
+    if (cflag & CSTOPB)
+    {
+        bits++;
+    }
+
+    if (cflag & PARENB)
+    {
+        bits++;
+    }
+
+    bits = bits * port->fifosize;
+
+    port->timeout = (HZ * bits) / baud + HZ/50;
+}
+unsigned int sb_uart_get_baud_rate(struct sb_uart_port *port, struct MP_TERMIOS *termios,
+				struct MP_TERMIOS *old, unsigned int min,
+				unsigned int max)
+{
+        unsigned int try, baud, altbaud = 38400;
+        upf_t flags = port->flags & UPF_SPD_MASK;
+
+        if (flags == UPF_SPD_HI)
+                altbaud = 57600;
+        if (flags == UPF_SPD_VHI)
+                altbaud = 115200;
+        if (flags == UPF_SPD_SHI)
+                altbaud = 230400;
+        if (flags == UPF_SPD_WARP)
+                altbaud = 460800;
+
+        for (try = 0; try < 2; try++) {
+
+                switch (termios->c_cflag & (CBAUD | CBAUDEX))
+                {
+                	case B921600    : baud = 921600;    break;
+                	case B460800    : baud = 460800;    break;
+                	case B230400    : baud = 230400;    break;
+                	case B115200    : baud = 115200;    break;
+                	case B57600     : baud = 57600;     break;
+                	case B38400     : baud = 38400;     break;
+                	case B19200     : baud = 19200;     break;
+                	case B9600      : baud = 9600;      break;
+                	case B4800      : baud = 4800;      break;
+                	case B2400      : baud = 2400;      break;
+                	case B1800      : baud = 1800;      break;
+                	case B1200      : baud = 1200;      break;
+                	case B600       : baud = 600;       break;
+                	case B300       : baud = 300;       break;
+                        case B200       : baud = 200;       break;
+                	case B150       : baud = 150;       break;
+                	case B134       : baud = 134;       break;
+                	case B110       : baud = 110;       break;
+                	case B75        : baud = 75;        break;
+                	case B50        : baud = 50;        break;
+                	default         : baud = 9600;      break;
+                }
+
+                if (baud == 38400)
+                        baud = altbaud;
+
+                if (baud == 0)
+                        baud = 9600;
+
+                if (baud >= min && baud <= max)
+                        return baud;
+
+                termios->c_cflag &= ~CBAUD;
+                if (old) {
+                        termios->c_cflag |= old->c_cflag & CBAUD;
+                        old = NULL;
+                        continue;
+                }
+
+                termios->c_cflag |= B9600;
+        }
+
+        return 0;
+}
+unsigned int sb_uart_get_divisor(struct sb_uart_port *port, unsigned int baud)
+{
+        unsigned int quot;
+
+        if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
+                quot = port->custom_divisor;
+        else
+                quot = (port->uartclk + (8 * baud)) / (16 * baud);
+
+        return quot;
+}
+
+
+
+static inline int sb_uart_handle_break(struct sb_uart_port *port)
+{
+	struct sb_uart_info *info = port->info;
+
+	if (port->flags & UPF_SAK)
+		do_SAK(info->tty);
+	return 0;
+}
+
+static inline void sb_uart_handle_dcd_change(struct sb_uart_port *port, unsigned int status)
+{
+	struct sb_uart_info *info = port->info;
+
+	port->icount.dcd++;
+
+	if (info->flags & UIF_CHECK_CD) {
+		if (status)
+			wake_up_interruptible(&info->open_wait);
+		else if (info->tty)
+			tty_hangup(info->tty);
+	}
+}
+
+static inline void sb_uart_handle_cts_change(struct sb_uart_port *port, unsigned int status)
+{
+	struct sb_uart_info *info = port->info;
+	struct tty_struct *tty = info->tty;
+
+	port->icount.cts++;
+
+	if (info->flags & UIF_CTS_FLOW) {
+		if (tty->hw_stopped) {
+			if (status) {
+				tty->hw_stopped = 0;
+				port->ops->start_tx(port);
+				sb_uart_write_wakeup(port);
+			}
+		} else {
+			if (!status) {
+				tty->hw_stopped = 1;
+				port->ops->stop_tx(port);
+			}
+		}
+	}
+}
+
+
+
diff --git a/drivers/staging/sbe-2t3e3/cpld.c b/drivers/staging/sbe-2t3e3/cpld.c
index cc2b54d..27365f9 100644
--- a/drivers/staging/sbe-2t3e3/cpld.c
+++ b/drivers/staging/sbe-2t3e3/cpld.c
@@ -338,7 +338,7 @@ void cpld_set_fractional_mode(struct channel *sc, u32 mode,
 			   SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_2);
 		break;
 	default:
-		printk(KERN_ERR "wrong mode in set_fractional_mode\n");
+		netdev_err(sc->dev, "wrong mode in set_fractional_mode\n");
 		return;
 	}
 
diff --git a/drivers/staging/sbe-2t3e3/main.c b/drivers/staging/sbe-2t3e3/main.c
index f3dbef6..c8e0398 100644
--- a/drivers/staging/sbe-2t3e3/main.c
+++ b/drivers/staging/sbe-2t3e3/main.c
@@ -135,9 +135,10 @@ void t3e3_read_card_serial_number(struct channel *sc)
 	for (i = 0; i < 3; i++)
 		sc->ether.card_serial_number[i] = t3e3_eeprom_read_word(sc, 10 + i);
 
-	printk(KERN_INFO "SBE wanPMC-2T3E3 serial number: %04X%04X%04X\n",
-	       sc->ether.card_serial_number[0], sc->ether.card_serial_number[1],
-	       sc->ether.card_serial_number[2]);
+	netdev_info(sc->dev, "SBE wanPMC-2T3E3 serial number: %04X%04X%04X\n",
+		    sc->ether.card_serial_number[0],
+		    sc->ether.card_serial_number[1],
+		    sc->ether.card_serial_number[2]);
 }
 
 /*
diff --git a/drivers/staging/sbe-2t3e3/module.c b/drivers/staging/sbe-2t3e3/module.c
index 8adb178..ae7af39 100644
--- a/drivers/staging/sbe-2t3e3/module.c
+++ b/drivers/staging/sbe-2t3e3/module.c
@@ -10,6 +10,8 @@
  * This code is based on a driver written by SBE Inc.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -50,7 +52,7 @@ static void t3e3_remove_channel(struct channel *channel)
 	pci_set_drvdata(pdev, NULL);
 }
 
-static int __devinit t3e3_init_channel(struct channel *channel, struct pci_dev *pdev, struct card *card)
+static int t3e3_init_channel(struct channel *channel, struct pci_dev *pdev, struct card *card)
 {
 	struct net_device *dev;
 	unsigned int val;
@@ -66,7 +68,7 @@ static int __devinit t3e3_init_channel(struct channel *channel, struct pci_dev *
 
 	dev = alloc_hdlcdev(channel);
 	if (!dev) {
-		printk(KERN_ERR "SBE 2T3E3" ": Out of memory\n");
+		pr_err("Out of memory\n");
 		err = -ENOMEM;
 		goto free_regions;
 	}
@@ -96,7 +98,8 @@ static int __devinit t3e3_init_channel(struct channel *channel, struct pci_dev *
 
 	err = request_irq(dev->irq, &t3e3_intr, IRQF_SHARED, dev->name, dev);
 	if (err) {
-		printk(KERN_WARNING "%s: could not get irq: %d\n", dev->name, dev->irq);
+		netdev_warn(channel->dev, "%s: could not get irq: %d\n",
+			    dev->name, dev->irq);
 		goto unregister_dev;
 	}
 
@@ -114,7 +117,7 @@ disable:
 	return err;
 }
 
-static void __devexit t3e3_remove_card(struct pci_dev *pdev)
+static void t3e3_remove_card(struct pci_dev *pdev)
 {
 	struct channel *channel0 = pci_get_drvdata(pdev);
 	struct card *card = channel0->card;
@@ -128,7 +131,7 @@ static void __devexit t3e3_remove_card(struct pci_dev *pdev)
 	kfree(card);
 }
 
-static int __devinit t3e3_init_card(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int t3e3_init_card(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	/* pdev points to channel #0 */
 	struct pci_dev *pdev1 = NULL;
@@ -144,7 +147,7 @@ static int __devinit t3e3_init_card(struct pci_dev *pdev, const struct pci_devic
 				break; /* found the second channel */
 
 		if (!pdev1) {
-			printk(KERN_ERR "SBE 2T3E3" ": Can't find the second channel\n");
+			dev_err(&pdev->dev, "Can't find the second channel\n");
 			return -EFAULT;
 		}
 		channels = 2;
@@ -153,7 +156,7 @@ static int __devinit t3e3_init_card(struct pci_dev *pdev, const struct pci_devic
 
 	card = kzalloc(sizeof(struct card) + channels * sizeof(struct channel), GFP_KERNEL);
 	if (!card) {
-		printk(KERN_ERR "SBE 2T3E3" ": Out of memory\n");
+		dev_err(&pdev->dev, "Out of memory\n");
 		return -ENOBUFS;
 	}
 
@@ -185,7 +188,7 @@ free_card:
 	return err;
 }
 
-static struct pci_device_id t3e3_pci_tbl[] __devinitdata = {
+static struct pci_device_id t3e3_pci_tbl[] = {
 	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
 	  PCI_VENDOR_ID_SBE, PCI_SUBDEVICE_ID_SBE_T3E3, 0, 0, 0 },
 	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
diff --git a/drivers/staging/sbe-2t3e3/netdev.c b/drivers/staging/sbe-2t3e3/netdev.c
index 180c963..1f5088b 100644
--- a/drivers/staging/sbe-2t3e3/netdev.c
+++ b/drivers/staging/sbe-2t3e3/netdev.c
@@ -57,7 +57,7 @@ static int t3e3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	return 0;
 }
 
-static struct net_device_stats* t3e3_get_stats(struct net_device *dev)
+static struct net_device_stats *t3e3_get_stats(struct net_device *dev)
 {
 	struct net_device_stats *nstats = &dev->stats;
 	struct channel *sc = dev_to_priv(dev);
@@ -134,7 +134,8 @@ int setup_device(struct net_device *dev, struct channel *sc)
 	dev->tx_queue_len = 100;
 	hdlc->xmit = t3e3_if_start_xmit;
 	hdlc->attach = t3e3_attach;
-	if ((retval = register_hdlc_device(dev))) {
+	retval = register_hdlc_device(dev);
+	if (retval) {
 		dev_err(&sc->pdev->dev, "error registering HDLC device\n");
 		return retval;
 	}
diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c
index a414e52..15c6e3d 100644
--- a/drivers/staging/sep/sep_main.c
+++ b/drivers/staging/sep/sep_main.c
@@ -3431,7 +3431,7 @@ static ssize_t sep_create_dcb_dmatables_context(struct sep_device *sep,
 	if (copy_from_user(dcb_args,
 			user_dcb_args,
 			num_dcbs * sizeof(struct build_dcb_struct))) {
-		error = -EINVAL;
+		error = -EFAULT;
 		goto end_function;
 	}
 
@@ -3619,7 +3619,7 @@ static ssize_t sep_create_msgarea_context(struct sep_device *sep,
 
 	/* Copy input data to write() to allocated message buffer */
 	if (copy_from_user(*msg_region, msg_user, msg_len)) {
-		error = -EINVAL;
+		error = -EFAULT;
 		goto end_function;
 	}
 
@@ -4112,7 +4112,7 @@ static int sep_register_driver_with_fs(struct sep_device *sep)
  *Attempt to set up and configure a SEP device that has been
  *discovered by the PCI layer. Allocates all required resources.
  */
-static int __devinit sep_probe(struct pci_dev *pdev,
+static int sep_probe(struct pci_dev *pdev,
 	const struct pci_device_id *ent)
 {
 	int error = 0;
diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
index 099bc69..1b3e995 100644
--- a/drivers/staging/serqt_usb2/serqt_usb2.c
+++ b/drivers/staging/serqt_usb2/serqt_usb2.c
@@ -272,7 +272,8 @@ static void qt_write_bulk_callback(struct urb *urb)
 	status = urb->status;
 
 	if (status) {
-		dev_dbg(&urb->dev->dev, "nonzero write bulk status received:%d\n", status);
+		dev_dbg(&urb->dev->dev,
+			"nonzero write bulk status received:%d\n", status);
 		return;
 	}
 
@@ -290,22 +291,80 @@ static void qt_interrupt_callback(struct urb *urb)
 	/* FIXME */
 }
 
+static void qt_status_change_check(struct tty_struct *tty,
+				   struct urb *urb,
+				   struct quatech_port *qt_port,
+				   struct usb_serial_port *port)
+{
+	int flag, i;
+	unsigned char *data = urb->transfer_buffer;
+	unsigned int RxCount = urb->actual_length;
+
+	for (i = 0; i < RxCount; ++i) {
+		/* Look ahead code here */
+		if ((i <= (RxCount - 3)) && (data[i] == 0x1b)
+		    && (data[i + 1] == 0x1b)) {
+			flag = 0;
+			switch (data[i + 2]) {
+			case 0x00:
+				if (i > (RxCount - 4)) {
+					dev_dbg(&port->dev,
+						"Illegal escape seuences in received data\n");
+					break;
+				}
+
+				ProcessLineStatus(qt_port, data[i + 3]);
+
+				i += 3;
+				flag = 1;
+				break;
+
+			case 0x01:
+				if (i > (RxCount - 4)) {
+					dev_dbg(&port->dev,
+						"Illegal escape seuences in received data\n");
+					break;
+				}
+
+				ProcessModemStatus(qt_port, data[i + 3]);
+
+				i += 3;
+				flag = 1;
+				break;
+
+			case 0xff:
+				dev_dbg(&port->dev, "No status sequence.\n");
+
+				ProcessRxChar(tty, port, data[i]);
+				ProcessRxChar(tty, port, data[i + 1]);
+
+				i += 2;
+				break;
+			}
+			if (flag == 1)
+				continue;
+		}
+
+		if (tty && urb->actual_length)
+			tty_insert_flip_char(tty, data[i], TTY_NORMAL);
+
+	}
+	tty_flip_buffer_push(tty);
+}
+
 static void qt_read_bulk_callback(struct urb *urb)
 {
 
 	struct usb_serial_port *port = urb->context;
 	struct usb_serial *serial = get_usb_serial(port, __func__);
 	struct quatech_port *qt_port = qt_get_port_private(port);
-	unsigned char *data;
 	struct tty_struct *tty;
-	unsigned int index;
-	unsigned int RxCount;
-	int i, result;
-	int flag, flag_data;
+	int result;
 
 	if (urb->status) {
 		qt_port->ReadBulkStopped = 1;
-		dev_dbg(&urb->dev->dev, "%s - nonzero write bulk status received: %d\n",
+		dev_dbg(&urb->dev->dev,
+			"%s - nonzero write bulk status received: %d\n",
 			__func__, urb->status);
 		return;
 	}
@@ -314,14 +373,8 @@ static void qt_read_bulk_callback(struct urb *urb)
 	if (!tty)
 		return;
 
-	data = urb->transfer_buffer;
-
-	RxCount = urb->actual_length;
-
-	/* index = MINOR(port->tty->device) - serial->minor; */
-	index = tty->index - serial->minor;
-
-	dev_dbg(&port->dev, "%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding);
+	dev_dbg(&port->dev,
+		"%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding);
 
 	if (port_paranoia_check(port, __func__) != 0) {
 		qt_port->ReadBulkStopped = 1;
@@ -333,7 +386,8 @@ static void qt_read_bulk_callback(struct urb *urb)
 
 	if (qt_port->closePending == 1) {
 		/* Were closing , stop reading */
-		dev_dbg(&port->dev, "%s - (qt_port->closepending == 1\n", __func__);
+		dev_dbg(&port->dev,
+			"%s - (qt_port->closepending == 1\n", __func__);
 		qt_port->ReadBulkStopped = 1;
 		goto exit;
 	}
@@ -351,62 +405,14 @@ static void qt_read_bulk_callback(struct urb *urb)
 	if (urb->status) {
 		qt_port->ReadBulkStopped = 1;
 
-		dev_dbg(&port->dev, "%s - nonzero read bulk status received: %d\n",
+		dev_dbg(&port->dev,
+			"%s - nonzero read bulk status received: %d\n",
 			__func__, urb->status);
 		goto exit;
 	}
 
-	if (RxCount) {
-		flag_data = 0;
-		for (i = 0; i < RxCount; ++i) {
-			/* Look ahead code here */
-			if ((i <= (RxCount - 3)) && (data[i] == 0x1b)
-			    && (data[i + 1] == 0x1b)) {
-				flag = 0;
-				switch (data[i + 2]) {
-				case 0x00:
-					/* line status change 4th byte must follow */
-					if (i > (RxCount - 4)) {
-						dev_dbg(&port->dev, "Illegal escape seuences in received data\n");
-						break;
-					}
-					ProcessLineStatus(qt_port, data[i + 3]);
-					i += 3;
-					flag = 1;
-					break;
-
-				case 0x01:
-					/* Modem status status change 4th byte must follow */
-					dev_dbg(&port->dev, "Modem status status.\n");
-					if (i > (RxCount - 4)) {
-						dev_dbg(&port->dev, "Illegal escape sequences in received data\n");
-						break;
-					}
-					ProcessModemStatus(qt_port,
-							   data[i + 3]);
-					i += 3;
-					flag = 1;
-					break;
-				case 0xff:
-					dev_dbg(&port->dev, "No status sequence.\n");
-
-					if (tty) {
-						ProcessRxChar(tty, port, data[i]);
-						ProcessRxChar(tty, port, data[i + 1]);
-					}
-					i += 2;
-					break;
-				}
-				if (flag == 1)
-					continue;
-			}
-
-			if (tty && urb->actual_length)
-				tty_insert_flip_char(tty, data[i], TTY_NORMAL);
-
-		}
-		tty_flip_buffer_push(tty);
-	}
+	if (urb->actual_length)
+		qt_status_change_check(tty, urb, qt_port, port);
 
 	/* Continue trying to always read  */
 	usb_fill_bulk_urb(port->read_urb, serial->dev,
@@ -417,10 +423,11 @@ static void qt_read_bulk_callback(struct urb *urb)
 			  qt_read_bulk_callback, port);
 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 	if (result)
-		dev_dbg(&port->dev, "%s - failed resubmitting read urb, error %d",
+		dev_dbg(&port->dev,
+			"%s - failed resubmitting read urb, error %d",
 			__func__, result);
 	else {
-		if (RxCount) {
+		if (urb->actual_length) {
 			tty_flip_buffer_push(tty);
 			tty_schedule_flip(tty);
 		}
@@ -824,6 +831,31 @@ static void qt_release(struct usb_serial *serial)
 
 }
 
+static void qt_submit_urb_from_open(struct usb_serial *serial,
+				    struct usb_serial_port *port)
+{
+	int result;
+	struct usb_serial_port *port0 = serial->port[0];
+
+	/* set up interrupt urb */
+	usb_fill_int_urb(port0->interrupt_in_urb,
+			 serial->dev,
+			 usb_rcvintpipe(serial->dev,
+					port0->interrupt_in_endpointAddress),
+			 port0->interrupt_in_buffer,
+			 port0->interrupt_in_urb->transfer_buffer_length,
+			 qt_interrupt_callback, serial,
+			 port0->interrupt_in_urb->interval);
+
+	result = usb_submit_urb(port0->interrupt_in_urb,
+				GFP_KERNEL);
+	if (result) {
+		dev_err(&port->dev,
+			"%s - Error %d submitting interrupt urb\n",
+			__func__, result);
+	}
+}
+
 static int qt_open(struct tty_struct *tty,
 		   struct usb_serial_port *port)
 {
@@ -884,38 +916,20 @@ static int qt_open(struct tty_struct *tty,
 
 	/*  Check to see if we've set up our endpoint info yet */
 	if (port0->open_ports == 1) {
-		if (serial->port[0]->interrupt_in_buffer == NULL) {
-			/* set up interrupt urb */
-			usb_fill_int_urb(serial->port[0]->interrupt_in_urb,
-					 serial->dev,
-					 usb_rcvintpipe(serial->dev,
-							serial->port[0]->interrupt_in_endpointAddress),
-					 serial->port[0]->interrupt_in_buffer,
-					 serial->port[0]->
-					 interrupt_in_urb->transfer_buffer_length,
-					 qt_interrupt_callback, serial,
-					 serial->port[0]->
-					 interrupt_in_urb->interval);
-
-			result =
-			    usb_submit_urb(serial->port[0]->interrupt_in_urb,
-					   GFP_KERNEL);
-			if (result) {
-				dev_err(&port->dev,
-					"%s - Error %d submitting "
-					"interrupt urb\n", __func__, result);
-			}
-
-		}
-
+		if (serial->port[0]->interrupt_in_buffer == NULL)
+			qt_submit_urb_from_open(serial, port);
 	}
 
 	dev_dbg(&port->dev, "port number is %d\n", port->number);
 	dev_dbg(&port->dev, "serial number is %d\n", port->serial->minor);
-	dev_dbg(&port->dev, "Bulkin endpoint is %d\n", port->bulk_in_endpointAddress);
-	dev_dbg(&port->dev, "BulkOut endpoint is %d\n", port->bulk_out_endpointAddress);
-	dev_dbg(&port->dev, "Interrupt endpoint is %d\n", port->interrupt_in_endpointAddress);
-	dev_dbg(&port->dev, "port's number in the device is %d\n", quatech_port->port_num);
+	dev_dbg(&port->dev,
+		"Bulkin endpoint is %d\n", port->bulk_in_endpointAddress);
+	dev_dbg(&port->dev,
+		"BulkOut endpoint is %d\n", port->bulk_out_endpointAddress);
+	dev_dbg(&port->dev, "Interrupt endpoint is %d\n",
+		port->interrupt_in_endpointAddress);
+	dev_dbg(&port->dev, "port's number in the device is %d\n",
+		quatech_port->port_num);
 	quatech_port->read_urb = port->read_urb;
 
 	/* set up our bulk in urb */
@@ -928,7 +942,8 @@ static int qt_open(struct tty_struct *tty,
 			  quatech_port->read_urb->transfer_buffer_length,
 			  qt_read_bulk_callback, quatech_port);
 
-	dev_dbg(&port->dev, "qt_open: bulkin endpoint is %d\n", port->bulk_in_endpointAddress);
+	dev_dbg(&port->dev, "qt_open: bulkin endpoint is %d\n",
+		port->bulk_in_endpointAddress);
 	quatech_port->read_urb_busy = true;
 	result = usb_submit_urb(quatech_port->read_urb, GFP_KERNEL);
 	if (result) {
@@ -1021,15 +1036,18 @@ static void qt_close(struct usb_serial_port *port)
 	/* Close uart channel */
 	status = qt_close_channel(serial, index);
 	if (status < 0)
-		dev_dbg(&port->dev, "%s - port %d qt_close_channel failed.\n", __func__, port->number);
+		dev_dbg(&port->dev,
+			"%s - port %d qt_close_channel failed.\n",
+			__func__, port->number);
 
 	port0->open_ports--;
 
-	dev_dbg(&port->dev, "qt_num_open_ports in close%d:in port%d\n", port0->open_ports, port->number);
+	dev_dbg(&port->dev, "qt_num_open_ports in close%d:in port%d\n",
+		port0->open_ports, port->number);
 
 	if (port0->open_ports == 0) {
 		if (serial->port[0]->interrupt_in_urb) {
-			dev_dbg(&port->dev, "%s", "Shutdown interrupt_in_urb\n");
+			dev_dbg(&port->dev, "Shutdown interrupt_in_urb\n");
 			usb_kill_urb(serial->port[0]->interrupt_in_urb);
 		}
 
@@ -1053,7 +1071,8 @@ static int qt_write(struct tty_struct *tty, struct usb_serial_port *port,
 		return -ENODEV;
 
 	if (count == 0) {
-		dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__);
+		dev_dbg(&port->dev,
+			"%s - write request of 0 bytes\n", __func__);
 		return 0;
 	}
 
@@ -1080,7 +1099,8 @@ static int qt_write(struct tty_struct *tty, struct usb_serial_port *port,
 		/* send the data out the bulk port */
 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 		if (result)
-			dev_dbg(&port->dev, "%s - failed submitting write urb, error %d\n",
+			dev_dbg(&port->dev,
+				"%s - failed submitting write urb, error %d\n",
 				__func__, result);
 		else
 			result = count;
@@ -1163,7 +1183,8 @@ static int qt_ioctl(struct tty_struct *tty,
 		return 0;
 	}
 
-	dev_dbg(&port->dev, "%s -No ioctl for that one.  port = %d\n", __func__, port->number);
+	dev_dbg(&port->dev, "%s -No ioctl for that one.  port = %d\n",
+		__func__, port->number);
 	return -ENOIOCTLCMD;
 }
 
@@ -1238,7 +1259,8 @@ static void qt_set_termios(struct tty_struct *tty,
 
 	/* Now determine flow control */
 	if (cflag & CRTSCTS) {
-		dev_dbg(&port->dev, "%s - Enabling HW flow control port %d\n", __func__, port->number);
+		dev_dbg(&port->dev, "%s - Enabling HW flow control port %d\n",
+			__func__, port->number);
 
 		/* Enable RTS/CTS flow control */
 		status = BoxSetHW_FlowCtrl(port->serial, index, 1);
@@ -1249,7 +1271,9 @@ static void qt_set_termios(struct tty_struct *tty,
 		}
 	} else {
 		/* Disable RTS/CTS flow control */
-		dev_dbg(&port->dev, "%s - disabling HW flow control port %d\n", __func__, port->number);
+		dev_dbg(&port->dev,
+			"%s - disabling HW flow control port %d\n",
+			__func__, port->number);
 
 		status = BoxSetHW_FlowCtrl(port->serial, index, 0);
 		if (status < 0) {
@@ -1268,17 +1292,21 @@ static void qt_set_termios(struct tty_struct *tty,
 		    BoxSetSW_FlowCtrl(port->serial, index, stop_char,
 				      start_char);
 		if (status < 0)
-			dev_dbg(&port->dev, "BoxSetSW_FlowCtrl (enabled) failed\n");
+			dev_dbg(&port->dev,
+				"BoxSetSW_FlowCtrl (enabled) failed\n");
 
 	} else {
 		/* disable SW flow control */
 		status = BoxDisable_SW_FlowCtrl(port->serial, index);
 		if (status < 0)
-			dev_dbg(&port->dev, "BoxSetSW_FlowCtrl (diabling) failed\n");
+			dev_dbg(&port->dev,
+				"BoxSetSW_FlowCtrl (diabling) failed\n");
 
 	}
 	termios->c_cflag &= ~CMSPAR;
-	/* FIXME: Error cases should be returning the actual bits changed only */
+	/* FIXME:
+	   Error cases should be returning the actual bits changed only
+	*/
 }
 
 static void qt_break(struct tty_struct *tty, int break_state)
@@ -1436,12 +1464,32 @@ static void qt_throttle(struct tty_struct *tty)
 	mutex_unlock(&qt_port->lock);
 }
 
+static void qt_submit_urb_from_unthrottle(struct usb_serial_port *port,
+					  struct usb_serial *serial)
+{
+	int result;
+
+	/* Start reading from the device */
+	usb_fill_bulk_urb(port->read_urb, serial->dev,
+			  usb_rcvbulkpipe(serial->dev,
+					  port->bulk_in_endpointAddress),
+			  port->read_urb->transfer_buffer,
+			  port->read_urb->transfer_buffer_length,
+			  qt_read_bulk_callback, port);
+
+	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+
+	if (result)
+		dev_err(&port->dev,
+			"%s - failed restarting read urb, error %d\n",
+			__func__, result);
+}
+
 static void qt_unthrottle(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = get_usb_serial(port, __func__);
 	struct quatech_port *qt_port;
-	unsigned int result;
 
 	if (!serial)
 		return;
@@ -1457,21 +1505,8 @@ static void qt_unthrottle(struct tty_struct *tty)
 		dev_dbg(&port->dev, "%s - qt_port->RxHolding = 0\n", __func__);
 
 		/* if we have a bulk endpoint, start it up */
-		if ((serial->num_bulk_in) && (qt_port->ReadBulkStopped == 1)) {
-			/* Start reading from the device */
-			usb_fill_bulk_urb(port->read_urb, serial->dev,
-					  usb_rcvbulkpipe(serial->dev,
-							  port->bulk_in_endpointAddress),
-					  port->read_urb->transfer_buffer,
-					  port->read_urb->
-					  transfer_buffer_length,
-					  qt_read_bulk_callback, port);
-			result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-			if (result)
-				dev_err(&port->dev,
-					"%s - failed restarting read urb, error %d\n",
-					__func__, result);
-		}
+		if ((serial->num_bulk_in) && (qt_port->ReadBulkStopped == 1))
+			qt_submit_urb_from_unthrottle(port, serial);
 	}
 	mutex_unlock(&qt_port->lock);
 }
diff --git a/drivers/staging/silicom/bp_mod.c b/drivers/staging/silicom/bp_mod.c
index 3cfd051..58c5f5c 100644
--- a/drivers/staging/silicom/bp_mod.c
+++ b/drivers/staging/silicom/bp_mod.c
@@ -9,7 +9,6 @@
 /*                                                                            */
 /*                                                                            */
 /******************************************************************************/
-#include <linux/version.h>
 
 #include <linux/kernel.h>	/* We're doing kernel work */
 #include <linux/module.h>	/* Specifically, a module */
@@ -4319,16 +4318,6 @@ void remove_bypass_wd_auto(bpctl_dev_t *pbpctl_dev)
 		del_timer_sync(&pbpctl_dev->bp_timer);
 #ifdef BP_SELF_TEST
 		pbpctl_dev_sl = get_status_port_fn(pbpctl_dev);
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31))
-		if (pbpctl_dev_sl && (pbpctl_dev_sl->ndev)
-		    && (pbpctl_dev_sl->ndev->hard_start_xmit)
-		    && (pbpctl_dev_sl->hard_start_xmit_save)) {
-			rtnl_lock();
-			pbpctl_dev_sl->ndev->hard_start_xmit =
-			    pbpctl_dev_sl->hard_start_xmit_save;
-			rtnl_unlock();
-		}
-#else
 		if (pbpctl_dev_sl && (pbpctl_dev_sl->ndev)) {
 			if ((pbpctl_dev_sl->ndev->netdev_ops)
 			    && (pbpctl_dev_sl->old_ops)) {
@@ -4342,8 +4331,6 @@ void remove_bypass_wd_auto(bpctl_dev_t *pbpctl_dev)
 			}
 
 		}
-
-#endif
 #endif
 	}
 
@@ -4433,23 +4420,7 @@ int set_bp_self_test(bpctl_dev_t *pbpctl_dev, unsigned int param)
 	if (pbpctl_dev->bp_caps & WD_CTL_CAP) {
 		pbpctl_dev->bp_self_test_flag = param == 0 ? 0 : 1;
 		pbpctl_dev_sl = get_status_port_fn(pbpctl_dev);
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31))
-		if ((pbpctl_dev_sl->ndev) &&
-		    (pbpctl_dev_sl->ndev->hard_start_xmit)) {
-			rtnl_lock();
-			if (pbpctl_dev->bp_self_test_flag == 1) {
 
-				pbpctl_dev_sl->hard_start_xmit_save =
-				    pbpctl_dev_sl->ndev->hard_start_xmit;
-				pbpctl_dev_sl->ndev->hard_start_xmit =
-				    bp_hard_start_xmit;
-			} else if (pbpctl_dev_sl->hard_start_xmit_save) {
-				pbpctl_dev_sl->ndev->hard_start_xmit =
-				    pbpctl_dev_sl->hard_start_xmit_save;
-			}
-			rtnl_unlock();
-		}
-#else
 		if ((pbpctl_dev_sl->ndev) && (pbpctl_dev_sl->ndev->netdev_ops)) {
 			rtnl_lock();
 			if (pbpctl_dev->bp_self_test_flag == 1) {
@@ -4470,7 +4441,6 @@ int set_bp_self_test(bpctl_dev_t *pbpctl_dev, unsigned int param)
 			}
 			rtnl_unlock();
 		}
-#endif
 
 		set_bypass_wd_auto(pbpctl_dev, param);
 		return 0;
@@ -5428,15 +5398,8 @@ static void if_scan_init(void)
 	/* rcu_read_lock(); */
 	/* rtnl_lock();     */
 	/* rcu_read_lock(); */
-#if 1
-#if (LINUX_VERSION_CODE >= 0x020618)
-	for_each_netdev(&init_net, dev)
-#elif (LINUX_VERSION_CODE >= 0x20616)
-	for_each_netdev(dev)
-#else
-	for (dev = dev_base; dev; dev = dev->next)
-#endif
-	{
+
+	for_each_netdev(&init_net, dev) {
 
 		struct ethtool_drvinfo drvinfo;
 		char cbuf[32];
@@ -5454,8 +5417,6 @@ static void if_scan_init(void)
 			dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
 		} else
 			continue;
-		if (!drvinfo.bus_info)
-			continue;
 		if (!strcmp(drvinfo.bus_info, "N/A"))
 			continue;
 		memcpy(&cbuf, drvinfo.bus_info, 32);
@@ -5491,22 +5452,14 @@ static void if_scan_init(void)
 		}
 
 	}
-#endif
 	/* rtnl_unlock();     */
 	/* rcu_read_unlock(); */
 
 }
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
-static int device_ioctl(struct inode *inode,	/* see include/linux/fs.h */
-			struct file *file,	/* ditto */
-			unsigned int ioctl_num,	/* number and param for ioctl */
-			unsigned long ioctl_param)
-#else
-static long device_ioctl(struct file *file,	/* ditto */
+static long device_ioctl(struct file *file,	/* see include/linux/fs.h */
 			 unsigned int ioctl_num,	/* number and param for ioctl */
 			 unsigned long ioctl_param)
-#endif
 {
 	struct bpctl_cmd bpctl_cmd;
 	int dev_idx = 0;
@@ -5517,9 +5470,7 @@ static long device_ioctl(struct file *file,	/* ditto */
 
 	static bpctl_dev_t *pbpctl_dev;
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
 	/* lock_kernel(); */
-#endif
 	lock_bpctl();
 	/* local_irq_save(flags); */
 	/* if(!spin_trylock_irqsave(&bpvm_lock)){
@@ -5900,9 +5851,7 @@ static long device_ioctl(struct file *file,	/* ditto */
 		ret = -EFAULT;
 	ret = SUCCESS;
  bp_exit:
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
 	/* unlock_kernel(); */
-#endif
 	/* spin_unlock_irqrestore(&bpvm_lock, flags); */
 	unlock_bpctl();
 	/* unlock_kernel(); */
@@ -5911,12 +5860,7 @@ static long device_ioctl(struct file *file,	/* ditto */
 
 struct file_operations Fops = {
 	.owner = THIS_MODULE,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
-	.ioctl = device_ioctl,
-#else
 	.unlocked_ioctl = device_ioctl,
-#endif
-
 	.open = device_open,
 	.release = device_release,	/* a.k.a. close */
 };
@@ -6952,15 +6896,8 @@ static int __init bypass_init_module(void)
 				memset(bpctl_dev_arr[idx_dev].bp_tx_data + 7,
 				       0xaa, 5);
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9))
-				bpctl_dev_arr[idx_dev].bp_tx_data[12] =
-				    (ETH_P_BPTEST >> 8) & 0xff;
-				bpctl_dev_arr[idx_dev].bp_tx_data[13] =
-				    ETH_P_BPTEST & 0xff;
-#else
 				*(__be16 *) (bpctl_dev_arr[idx_dev].bp_tx_data +
 					     12) = htons(ETH_P_BPTEST);
-#endif
 
 			} else
 				printk("bp_ctl: Memory allocation error!\n");
@@ -7009,83 +6946,6 @@ static int __init bypass_init_module(void)
 		}
 	}
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
-	inter_module_register("is_bypass_sd", THIS_MODULE, &is_bypass_sd);
-	inter_module_register("get_bypass_slave_sd", THIS_MODULE,
-			      &get_bypass_slave_sd);
-	inter_module_register("get_bypass_caps_sd", THIS_MODULE,
-			      &get_bypass_caps_sd);
-	inter_module_register("get_wd_set_caps_sd", THIS_MODULE,
-			      &get_wd_set_caps_sd);
-	inter_module_register("set_bypass_sd", THIS_MODULE, &set_bypass_sd);
-	inter_module_register("get_bypass_sd", THIS_MODULE, &get_bypass_sd);
-	inter_module_register("get_bypass_change_sd", THIS_MODULE,
-			      &get_bypass_change_sd);
-	inter_module_register("set_dis_bypass_sd", THIS_MODULE,
-			      &set_dis_bypass_sd);
-	inter_module_register("get_dis_bypass_sd", THIS_MODULE,
-			      &get_dis_bypass_sd);
-	inter_module_register("set_bypass_pwoff_sd", THIS_MODULE,
-			      &set_bypass_pwoff_sd);
-	inter_module_register("get_bypass_pwoff_sd", THIS_MODULE,
-			      &get_bypass_pwoff_sd);
-	inter_module_register("set_bypass_pwup_sd", THIS_MODULE,
-			      &set_bypass_pwup_sd);
-	inter_module_register("get_bypass_pwup_sd", THIS_MODULE,
-			      &get_bypass_pwup_sd);
-	inter_module_register("get_bypass_wd_sd", THIS_MODULE,
-			      &get_bypass_wd_sd);
-	inter_module_register("set_bypass_wd_sd", THIS_MODULE,
-			      &set_bypass_wd_sd);
-	inter_module_register("get_wd_expire_time_sd", THIS_MODULE,
-			      &get_wd_expire_time_sd);
-	inter_module_register("reset_bypass_wd_timer_sd", THIS_MODULE,
-			      &reset_bypass_wd_timer_sd);
-	inter_module_register("set_std_nic_sd", THIS_MODULE, &set_std_nic_sd);
-	inter_module_register("get_std_nic_sd", THIS_MODULE, &get_std_nic_sd);
-	inter_module_register("set_tx_sd", THIS_MODULE, &set_tx_sd);
-	inter_module_register("get_tx_sd", THIS_MODULE, &get_tx_sd);
-	inter_module_register("set_tpl_sd", THIS_MODULE, &set_tpl_sd);
-	inter_module_register("get_tpl_sd", THIS_MODULE, &get_tpl_sd);
-
-	inter_module_register("set_bp_hw_reset_sd", THIS_MODULE,
-			      &set_bp_hw_reset_sd);
-	inter_module_register("get_bp_hw_reset_sd", THIS_MODULE,
-			      &get_bp_hw_reset_sd);
-
-	inter_module_register("set_tap_sd", THIS_MODULE, &set_tap_sd);
-	inter_module_register("get_tap_sd", THIS_MODULE, &get_tap_sd);
-	inter_module_register("get_tap_change_sd", THIS_MODULE,
-			      &get_tap_change_sd);
-	inter_module_register("set_dis_tap_sd", THIS_MODULE, &set_dis_tap_sd);
-	inter_module_register("get_dis_tap_sd", THIS_MODULE, &get_dis_tap_sd);
-	inter_module_register("set_tap_pwup_sd", THIS_MODULE, &set_tap_pwup_sd);
-	inter_module_register("get_tap_pwup_sd", THIS_MODULE, &get_tap_pwup_sd);
-	inter_module_register("set_bp_disc_sd", THIS_MODULE, &set_bp_disc_sd);
-	inter_module_register("get_bp_disc_sd", THIS_MODULE, &get_bp_disc_sd);
-	inter_module_register("get_bp_disc_change_sd", THIS_MODULE,
-			      &get_bp_disc_change_sd);
-	inter_module_register("set_bp_dis_disc_sd", THIS_MODULE,
-			      &set_bp_dis_disc_sd);
-	inter_module_register("get_bp_dis_disc_sd", THIS_MODULE,
-			      &get_bp_dis_disc_sd);
-	inter_module_register("set_bp_disc_pwup_sd", THIS_MODULE,
-			      &set_bp_disc_pwup_sd);
-	inter_module_register("get_bp_disc_pwup_sd", THIS_MODULE,
-			      &get_bp_disc_pwup_sd);
-	inter_module_register("set_wd_exp_mode_sd", THIS_MODULE,
-			      &set_wd_exp_mode_sd);
-	inter_module_register("get_wd_exp_mode_sd", THIS_MODULE,
-			      &get_wd_exp_mode_sd);
-	inter_module_register("set_wd_autoreset_sd", THIS_MODULE,
-			      &set_wd_autoreset_sd);
-	inter_module_register("get_wd_autoreset_sd", THIS_MODULE,
-			      &get_wd_autoreset_sd);
-	inter_module_register("get_bypass_info_sd", THIS_MODULE,
-			      &get_bypass_info_sd);
-	inter_module_register("bp_if_scan_sd", THIS_MODULE, &bp_if_scan_sd);
-
-#endif
 	register_netdevice_notifier(&bp_notifier_block);
 #ifdef BP_PROC_SUPPORT
 	{
@@ -7115,58 +6975,8 @@ static int __init bypass_init_module(void)
 static void __exit bypass_cleanup_module(void)
 {
 	int i;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23))
-	int ret;
-#endif
 	unregister_netdevice_notifier(&bp_notifier_block);
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
-	inter_module_unregister("is_bypass_sd");
-	inter_module_unregister("get_bypass_slave_sd");
-	inter_module_unregister("get_bypass_caps_sd");
-	inter_module_unregister("get_wd_set_caps_sd");
-	inter_module_unregister("set_bypass_sd");
-	inter_module_unregister("get_bypass_sd");
-	inter_module_unregister("get_bypass_change_sd");
-	inter_module_unregister("set_dis_bypass_sd");
-	inter_module_unregister("get_dis_bypass_sd");
-	inter_module_unregister("set_bypass_pwoff_sd");
-	inter_module_unregister("get_bypass_pwoff_sd");
-	inter_module_unregister("set_bypass_pwup_sd");
-	inter_module_unregister("get_bypass_pwup_sd");
-	inter_module_unregister("set_bypass_wd_sd");
-	inter_module_unregister("get_bypass_wd_sd");
-	inter_module_unregister("get_wd_expire_time_sd");
-	inter_module_unregister("reset_bypass_wd_timer_sd");
-	inter_module_unregister("set_std_nic_sd");
-	inter_module_unregister("get_std_nic_sd");
-	inter_module_unregister("set_tx_sd");
-	inter_module_unregister("get_tx_sd");
-	inter_module_unregister("set_tpl_sd");
-	inter_module_unregister("get_tpl_sd");
-	inter_module_unregister("set_tap_sd");
-	inter_module_unregister("get_tap_sd");
-	inter_module_unregister("get_tap_change_sd");
-	inter_module_unregister("set_dis_tap_sd");
-	inter_module_unregister("get_dis_tap_sd");
-	inter_module_unregister("set_tap_pwup_sd");
-	inter_module_unregister("get_tap_pwup_sd");
-	inter_module_unregister("set_bp_disc_sd");
-	inter_module_unregister("get_bp_disc_sd");
-	inter_module_unregister("get_bp_disc_change_sd");
-	inter_module_unregister("set_bp_dis_disc_sd");
-	inter_module_unregister("get_bp_dis_disc_sd");
-	inter_module_unregister("set_bp_disc_pwup_sd");
-	inter_module_unregister("get_bp_disc_pwup_sd");
-	inter_module_unregister("set_wd_exp_mode_sd");
-	inter_module_unregister("get_wd_exp_mode_sd");
-	inter_module_unregister("set_wd_autoreset_sd");
-	inter_module_unregister("get_wd_autoreset_sd");
-	inter_module_unregister("get_bypass_info_sd");
-	inter_module_unregister("bp_if_scan_sd");
-
-#endif
-
 	for (i = 0; i < device_num; i++) {
 		/* unsigned long flags; */
 #ifdef BP_PROC_SUPPORT
@@ -7198,17 +7008,7 @@ static void __exit bypass_cleanup_module(void)
 /*
 * Unregister the device                             
 */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23))
-	ret = unregister_chrdev(major_num, DEVICE_NAME);
-/*
-* If there's an error, report it
-*/
-	if (ret < 0)
-		printk("Error in module_unregister_chrdev: %d\n", ret);
-#else
 	unregister_chrdev(major_num, DEVICE_NAME);
-
-#endif
 }
 
 module_init(bypass_init_module);
@@ -7597,11 +7397,7 @@ static struct proc_dir_entry *proc_getdir(char *name,
 	}
 	if (pde == (struct proc_dir_entry *)0) {
 		/* create the directory */
-#if (LINUX_VERSION_CODE > 0x20300)
 		pde = proc_mkdir(name, proc_dir);
-#else
-		pde = create_proc_entry(name, S_IFDIR, proc_dir);
-#endif
 		if (pde == (struct proc_dir_entry *)0) {
 
 			return pde;
@@ -7703,13 +7499,8 @@ get_bypass_slave_pfs(char *page, char **start, off_t off, int count,
 		return len;
 	}
 	net_slave_dev = pbp_device_block_slave->ndev;
-	if (net_slave_dev) {
-		if (net_slave_dev)
-			len = sprintf(page, "%s\n", net_slave_dev->name);
-		else
-			len = sprintf(page, "fail\n");
-
-	}
+	if (net_slave_dev)
+		len = sprintf(page, "%s\n", net_slave_dev->name);
 
 	*eof = 1;
 	return len;
diff --git a/drivers/staging/silicom/bp_proc.c b/drivers/staging/silicom/bp_proc.c
index 6ad4b27..a01ca97 100644
--- a/drivers/staging/silicom/bp_proc.c
+++ b/drivers/staging/silicom/bp_proc.c
@@ -10,21 +10,20 @@
 /*                                                                            */
 /******************************************************************************/
 
-#include <linux/version.h>
-#if defined(CONFIG_SMP) && ! defined(__SMP__)
+#if defined(CONFIG_SMP) && !defined(__SMP__)
 #define __SMP__
 #endif
 
 #include <linux/proc_fs.h>
 #include <linux/netdevice.h>
 #include <asm/uaccess.h>
-//#include <linux/smp_lock.h>
+/* #include <linux/smp_lock.h> */
 #include "bp_mod.h"
 
 #define BP_PROC_DIR "bypass"
-//#define BYPASS_SUPPORT "bypass"
+/* #define BYPASS_SUPPORT "bypass" */
 
-#ifdef  BYPASS_SUPPORT
+#ifdef BYPASS_SUPPORT
 
 #define GPIO6_SET_ENTRY_SD           "gpio6_set"
 #define GPIO6_CLEAR_ENTRY_SD         "gpio6_clear"
@@ -70,7 +69,7 @@
 #define DISC_CHANGE_ENTRY_SD      "disc_change"
 #define DIS_DISC_ENTRY_SD         "dis_disc"
 #define DISC_PWUP_ENTRY_SD        "disc_pwup"
-#endif				//bypass_support
+
 static struct proc_dir_entry *bp_procfs_dir;
 
 static struct proc_dir_entry *proc_getdir(char *name,
@@ -86,20 +85,17 @@ static struct proc_dir_entry *proc_getdir(char *name,
 	if (pde == (struct proc_dir_entry *)0) {
 		/* create the directory */
 		pde = create_proc_entry(name, S_IFDIR, proc_dir);
-		if (pde == (struct proc_dir_entry *)0) {
-			return (pde);
-		}
+		if (pde == (struct proc_dir_entry *)0)
+			return pde;
 	}
-	return (pde);
+	return pde;
 }
 
-#ifdef BYPASS_SUPPORT
-
 int
 bypass_proc_create_entry_sd(struct pfs_unit *pfs_unit_curr,
 			    char *proc_name,
-			    write_proc_t * write_proc,
-			    read_proc_t * read_proc,
+			    write_proc_t *write_proc,
+			    read_proc_t *read_proc,
 			    struct proc_dir_entry *parent_pfs, void *data)
 {
 	strcpy(pfs_unit_curr->proc_name, proc_name);
@@ -107,10 +103,8 @@ bypass_proc_create_entry_sd(struct pfs_unit *pfs_unit_curr,
 						      S_IFREG | S_IRUSR |
 						      S_IWUSR | S_IRGRP |
 						      S_IROTH, parent_pfs);
-	if (pfs_unit_curr->proc_entry == 0) {
-
+	if (pfs_unit_curr->proc_entry == 0)
 		return -1;
-	}
 
 	pfs_unit_curr->proc_entry->read_proc = read_proc;
 	pfs_unit_curr->proc_entry->write_proc = write_proc;
@@ -207,9 +201,8 @@ set_bypass_pfs(struct file *file, const char *buffer,
 	if (count > (sizeof(kbuf) - 1))
 		return -1;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -239,9 +232,8 @@ set_tap_pfs(struct file *file, const char *buffer,
 	if (count > (sizeof(kbuf) - 1))
 		return -1;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -271,9 +263,8 @@ set_disc_pfs(struct file *file, const char *buffer,
 	if (count > (sizeof(kbuf) - 1))
 		return -1;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -421,9 +412,8 @@ set_bypass_wd_pfs(struct file *file, const char *buffer,
 	unsigned int timeout = 0;
 	char *timeout_ptr = kbuf;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	timeout_ptr = kbuf;
 	timeout = atoi(&timeout_ptr);
@@ -570,9 +560,8 @@ set_dis_bypass_pfs(struct file *file, const char *buffer,
 
 	int bypass_param = 0, length = 0;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -599,9 +588,8 @@ set_dis_tap_pfs(struct file *file, const char *buffer,
 
 	int tap_param = 0, length = 0;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -628,9 +616,8 @@ set_dis_disc_pfs(struct file *file, const char *buffer,
 
 	int tap_param = 0, length = 0;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -717,9 +704,8 @@ set_bypass_pwup_pfs(struct file *file, const char *buffer,
 
 	int bypass_param = 0, length = 0;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -746,9 +732,8 @@ set_bypass_pwoff_pfs(struct file *file, const char *buffer,
 
 	int bypass_param = 0, length = 0;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -775,9 +760,8 @@ set_tap_pwup_pfs(struct file *file, const char *buffer,
 
 	int tap_param = 0, length = 0;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -804,9 +788,8 @@ set_disc_pwup_pfs(struct file *file, const char *buffer,
 
 	int tap_param = 0, length = 0;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -913,9 +896,8 @@ set_std_nic_pfs(struct file *file, const char *buffer,
 
 	int bypass_param = 0, length = 0;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -988,9 +970,8 @@ set_wd_exp_mode_pfs(struct file *file, const char *buffer,
 	if (count > (sizeof(kbuf) - 1))
 		return -1;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -1036,9 +1017,8 @@ set_wd_autoreset_pfs(struct file *file, const char *buffer,
 	u32 timeout = 0;
 	char *timeout_ptr = kbuf;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	timeout_ptr = kbuf;
 	timeout = atoi(&timeout_ptr);
@@ -1061,9 +1041,8 @@ set_tpl_pfs(struct file *file, const char *buffer,
 	if (count > (sizeof(kbuf) - 1))
 		return -1;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -1094,9 +1073,8 @@ set_wait_at_pwup_pfs(struct file *file, const char *buffer,
 	if (count > (sizeof(kbuf) - 1))
 		return -1;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -1126,9 +1104,8 @@ set_hw_reset_pfs(struct file *file, const char *buffer,
 	if (count > (sizeof(kbuf) - 1))
 		return -1;
 
-	if (copy_from_user(&kbuf, buffer, count)) {
+	if (copy_from_user(&kbuf, buffer, count))
 		return -1;
-	}
 
 	kbuf[count] = '\0';
 	length = strlen(kbuf);
@@ -1147,10 +1124,10 @@ set_hw_reset_pfs(struct file *file, const char *buffer,
 
 #endif				/*PMC_FIX_FLAG */
 
-int bypass_proc_create_dev_sd(bpctl_dev_t * pbp_device_block)
+int bypass_proc_create_dev_sd(bpctl_dev_t *pbp_device_block)
 {
 	struct bypass_pfs_sd *current_pfs = &(pbp_device_block->bypass_pfs_set);
-	static struct proc_dir_entry *procfs_dir = NULL;
+	static struct proc_dir_entry *procfs_dir;
 	int ret = 0;
 
 	sprintf(current_pfs->dir_name, "bypass_%s", dev->name);
@@ -1327,7 +1304,7 @@ int bypass_proc_create_dev_sd(bpctl_dev_t * pbp_device_block)
 	return ret;
 }
 
-int bypass_proc_remove_dev_sd(bpctl_dev_t * pbp_device_block)
+int bypass_proc_remove_dev_sd(bpctl_dev_t *pbp_device_block)
 {
 
 	struct bypass_pfs_sd *current_pfs = &pbp_device_block->bypass_pfs_set;
diff --git a/drivers/staging/silicom/bypasslib/bplibk.h b/drivers/staging/silicom/bypasslib/bplibk.h
index a1c85ee..d8c1d27 100644
--- a/drivers/staging/silicom/bypasslib/bplibk.h
+++ b/drivers/staging/silicom/bypasslib/bplibk.h
@@ -28,16 +28,7 @@
         ((pid==INTEL_PEG4BPII_PID)||   \
           (pid==INTEL_PEG4BPFII_PID)))
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
-#define pci_get_class pci_find_class
-
-#define pci_get_device pci_find_device
-
-#endif
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10))
 #define EXPORT_SYMBOL_NOVERS EXPORT_SYMBOL
-#endif
 
 #ifdef BP_VENDOR_SUPPORT
 char *bp_desc_array[] =
diff --git a/drivers/staging/silicom/bypasslib/bypass.c b/drivers/staging/silicom/bypasslib/bypass.c
index 527829d..95a1f18 100644
--- a/drivers/staging/silicom/bypasslib/bypass.c
+++ b/drivers/staging/silicom/bypasslib/bypass.c
@@ -11,7 +11,6 @@
 /*                                                                            */
 /******************************************************************************/
 
-#include <linux/version.h>
 #if defined(CONFIG_SMP) && ! defined(__SMP__)
 #define __SMP__
 #endif
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
index cd920da..78578ee 100644
--- a/drivers/staging/slicoss/slicoss.c
+++ b/drivers/staging/slicoss/slicoss.c
@@ -142,39 +142,12 @@ static DEFINE_PCI_DEVICE_TABLE(slic_pci_tbl) = {
 
 MODULE_DEVICE_TABLE(pci, slic_pci_tbl);
 
-#ifdef ASSERT
-#undef ASSERT
-#endif
-
-static void slic_assert_fail(void)
-{
-	u32 cpuid;
-	u32 curr_pid;
-	cpuid = smp_processor_id();
-	curr_pid = current->pid;
-
-	printk(KERN_ERR "%s CPU # %d ---- PID # %d\n",
-	       __func__, cpuid, curr_pid);
-}
-
-#ifndef ASSERT
-#define ASSERT(a) do {							\
-	if (!(a)) {							\
-		printk(KERN_ERR "slicoss ASSERT() Failure: function %s"	\
-			"line %d\n", __func__, __LINE__);		\
-		slic_assert_fail();					\
-	}								\
-} while (0)
-#endif
-
-
 #define SLIC_GET_SLIC_HANDLE(_adapter, _pslic_handle)                   \
 {                                                                       \
     spin_lock_irqsave(&_adapter->handle_lock.lock,                      \
 			_adapter->handle_lock.flags);                   \
     _pslic_handle  =  _adapter->pfree_slic_handles;                     \
     if (_pslic_handle) {                                                \
-	ASSERT(_pslic_handle->type == SLIC_HANDLE_FREE);                \
 	_adapter->pfree_slic_handles = _pslic_handle->next;             \
     }                                                                   \
     spin_unlock_irqrestore(&_adapter->handle_lock.lock,                 \
@@ -325,11 +298,8 @@ static void slic_timer_ping(ulong dev)
 	struct adapter *adapter;
 	struct sliccard *card;
 
-	ASSERT(dev);
 	adapter = netdev_priv((struct net_device *)dev);
-	ASSERT(adapter);
 	card = adapter->card;
-	ASSERT(card);
 
 	adapter->pingtimer.expires = jiffies + (PING_TIMER_INTERVAL * HZ);
 	add_timer(&adapter->pingtimer);
@@ -361,9 +331,6 @@ static void slic_link_config(struct adapter *adapter,
 	if (adapter->state != ADAPT_UP)
 		return;
 
-	ASSERT((adapter->devid == SLIC_1GB_DEVICE_ID)
-	       || (adapter->devid == SLIC_2GB_DEVICE_ID));
-
 	if (linkspeed > LINK_1000MB)
 		linkspeed = LINK_AUTOSPEED;
 	if (linkduplex > LINK_AUTOD)
@@ -593,8 +560,7 @@ static int slic_card_download(struct adapter *adapter)
 		file = "slicoss/gbdownload.sys";
 		break;
 	default:
-		ASSERT(0);
-		break;
+		return -ENOENT;
 	}
 	ret = request_firmware(&fw, file, &adapter->pcidev->dev);
 	if (ret) {
@@ -604,7 +570,6 @@ static int slic_card_download(struct adapter *adapter)
 	}
 	numsects = *(u32 *)(fw->data + index);
 	index += 4;
-	ASSERT(numsects <= 3);
 	for (i = 0; i < numsects; i++) {
 		sectsize[i] = *(u32 *)(fw->data + index);
 		index += 4;
@@ -1060,8 +1025,6 @@ static void slic_upr_start(struct adapter *adapter)
 	case SLIC_UPR_PING:
 		slic_reg32_write(&slic_regs->slic_ping, 1, FLUSH);
 		break;
-	default:
-		ASSERT(0);
 	}
 }
 
@@ -1116,9 +1079,6 @@ static void slic_link_upr_complete(struct adapter *adapter, u32 isr)
 	if (adapter->state != ADAPT_UP)
 		return;
 
-	ASSERT((adapter->devid == SLIC_1GB_DEVICE_ID)
-	       || (adapter->devid == SLIC_2GB_DEVICE_ID));
-
 	linkup = linkstatus & GIG_LINKUP ? LINK_UP : LINK_DOWN;
 	if (linkstatus & GIG_SPEED_1000)
 		linkspeed = LINK_1000MB;
@@ -1170,7 +1130,6 @@ static void slic_upr_request_complete(struct adapter *adapter, u32 isr)
 	spin_lock_irqsave(&adapter->upr_lock.lock, adapter->upr_lock.flags);
 	upr = adapter->upr_list;
 	if (!upr) {
-		ASSERT(0);
 		spin_unlock_irqrestore(&adapter->upr_lock.lock,
 					adapter->upr_lock.flags);
 		return;
@@ -1178,7 +1137,6 @@ static void slic_upr_request_complete(struct adapter *adapter, u32 isr)
 	adapter->upr_list = upr->next;
 	upr->next = NULL;
 	adapter->upr_busy = 0;
-	ASSERT(adapter->port == upr->adapter);
 	switch (upr->upr_request) {
 	case SLIC_UPR_STATS:
 		{
@@ -1260,23 +1218,9 @@ static void slic_upr_request_complete(struct adapter *adapter, u32 isr)
 		break;
 	case SLIC_UPR_RCONFIG:
 		break;
-	case SLIC_UPR_RPHY:
-		ASSERT(0);
-		break;
-	case SLIC_UPR_ENLB:
-		ASSERT(0);
-		break;
-	case SLIC_UPR_ENCT:
-		ASSERT(0);
-		break;
-	case SLIC_UPR_PDWN:
-		ASSERT(0);
-		break;
 	case SLIC_UPR_PING:
 		card->pingstatus |= (isr & ISR_PINGDSMASK);
 		break;
-	default:
-		ASSERT(0);
 	}
 	kfree(upr);
 	slic_upr_start(adapter);
@@ -1292,7 +1236,6 @@ static void slic_config_get(struct adapter *adapter, u32 config,
 	status = slic_upr_request(adapter,
 				  SLIC_UPR_RCONFIG,
 				  (u32) config, (u32) config_h, 0, 0);
-	ASSERT(status == 0);
 }
 
 /*
@@ -1422,7 +1365,6 @@ static int slic_rspqueue_init(struct adapter *adapter)
 	__iomem struct slic_regs *slic_regs = adapter->slic_regs;
 	u32 paddrh = 0;
 
-	ASSERT(adapter->state == ADAPT_DOWN);
 	memset(rspq, 0, sizeof(struct slic_rspqueue));
 
 	rspq->num_pages = SLIC_RSPQ_PAGES_GB;
@@ -1439,14 +1381,6 @@ static int slic_rspqueue_init(struct adapter *adapter)
 		}
 		/* FIXME:
 		 * do we really need this assertions (4K PAGE_SIZE aligned addr)? */
-#if 0
-#ifndef CONFIG_X86_64
-		ASSERT(((u32) rspq->vaddr[i] & 0xFFFFF000) ==
-		       (u32) rspq->vaddr[i]);
-		ASSERT(((u32) rspq->paddr[i] & 0xFFFFF000) ==
-		       (u32) rspq->paddr[i]);
-#endif
-#endif
 		memset(rspq->vaddr[i], 0, PAGE_SIZE);
 
 		if (paddrh == 0) {
@@ -1475,18 +1409,9 @@ static struct slic_rspbuf *slic_rspqueue_getnext(struct adapter *adapter)
 		return NULL;
 
 	buf = rspq->rspbuf;
-#if BITS_PER_LONG == 32
-	ASSERT((buf->status & 0xFFFFFFE0) == 0);
-#endif
-	ASSERT(buf->hosthandle);
 	if (++rspq->offset < SLIC_RSPQ_BUFSINPAGE) {
 		rspq->rspbuf++;
-#if BITS_PER_LONG == 32
-		ASSERT(((u32) rspq->rspbuf & 0xFFFFFFE0) ==
-		       (u32) rspq->rspbuf);
-#endif
 	} else {
-		ASSERT(rspq->offset == SLIC_RSPQ_BUFSINPAGE);
 		slic_reg64_write(adapter, &adapter->slic_regs->slic_rbar64,
 			(rspq->paddr[rspq->pageindex] | SLIC_RSPQ_BUFSINPAGE),
 			&adapter->slic_regs->slic_addr_upper, 0, DONT_FLUSH);
@@ -1494,22 +1419,9 @@ static struct slic_rspbuf *slic_rspqueue_getnext(struct adapter *adapter)
 		rspq->offset = 0;
 		rspq->rspbuf = (struct slic_rspbuf *)
 						rspq->vaddr[rspq->pageindex];
-#if BITS_PER_LONG == 32
-		ASSERT(((u32) rspq->rspbuf & 0xFFFFF000) ==
-		       (u32) rspq->rspbuf);
-#endif
 	}
-#if BITS_PER_LONG == 32
-	ASSERT(((u32) buf & 0xFFFFFFE0) == (u32) buf);
-#endif
-	return buf;
-}
-
-static void slic_cmdqmem_init(struct adapter *adapter)
-{
-	struct slic_cmdqmem *cmdqmem = &adapter->cmdqmem;
 
-	memset(cmdqmem, 0, sizeof(struct slic_cmdqmem));
+	return buf;
 }
 
 static void slic_cmdqmem_free(struct adapter *adapter)
@@ -1540,9 +1452,7 @@ static u32 *slic_cmdqmem_addpage(struct adapter *adapter)
 					&cmdqmem->dma_pages[cmdqmem->pagecnt]);
 	if (!pageaddr)
 		return NULL;
-#if BITS_PER_LONG == 32
-	ASSERT(((u32) pageaddr & 0xFFFFF000) == (u32) pageaddr);
-#endif
+
 	cmdqmem->pages[cmdqmem->pagecnt] = pageaddr;
 	cmdqmem->pagecnt++;
 	return pageaddr;
@@ -1598,11 +1508,6 @@ static void slic_cmdq_addcmdpage(struct adapter *adapter, u32 *page)
 	       (adapter->slic_handle_ix < 256)) {
 		/* Allocate and initialize a SLIC_HANDLE for this command */
 		SLIC_GET_SLIC_HANDLE(adapter, pslic_handle);
-		if (pslic_handle == NULL)
-			ASSERT(0);
-		ASSERT(pslic_handle ==
-		       &adapter->slic_handles[pslic_handle->token.
-					      handle_index]);
 		pslic_handle->type = SLIC_HANDLE_CMD;
 		pslic_handle->address = (void *) cmd;
 		pslic_handle->offset = (ushort) adapter->slic_handle_ix++;
@@ -1641,20 +1546,16 @@ static int slic_cmdq_init(struct adapter *adapter)
 	int i;
 	u32 *pageaddr;
 
-	ASSERT(adapter->state == ADAPT_DOWN);
 	memset(&adapter->cmdq_all, 0, sizeof(struct slic_cmdqueue));
 	memset(&adapter->cmdq_free, 0, sizeof(struct slic_cmdqueue));
 	memset(&adapter->cmdq_done, 0, sizeof(struct slic_cmdqueue));
 	spin_lock_init(&adapter->cmdq_all.lock.lock);
 	spin_lock_init(&adapter->cmdq_free.lock.lock);
 	spin_lock_init(&adapter->cmdq_done.lock.lock);
-	slic_cmdqmem_init(adapter);
+	memset(&adapter->cmdqmem, 0, sizeof(struct slic_cmdqmem));
 	adapter->slic_handle_ix = 1;
 	for (i = 0; i < SLIC_CMDQ_INITPAGES; i++) {
 		pageaddr = slic_cmdqmem_addpage(adapter);
-#if BITS_PER_LONG == 32
-		ASSERT(((u32) pageaddr & 0xFFFFF000) == (u32) pageaddr);
-#endif
 		if (!pageaddr) {
 			slic_cmdq_free(adapter);
 			return -ENOMEM;
@@ -1682,7 +1583,6 @@ static void slic_cmdq_reset(struct adapter *adapter)
 	while (hcmd) {
 		if (hcmd->busy) {
 			skb = hcmd->skb;
-			ASSERT(skb);
 			hcmd->busy = 0;
 			hcmd->skb = NULL;
 			dev_kfree_skb_irq(skb);
@@ -1718,7 +1618,6 @@ static void slic_cmdq_getdone(struct adapter *adapter)
 	struct slic_cmdqueue *done_cmdq = &adapter->cmdq_done;
 	struct slic_cmdqueue *free_cmdq = &adapter->cmdq_free;
 
-	ASSERT(free_cmdq->head == NULL);
 	spin_lock_irqsave(&done_cmdq->lock.lock, done_cmdq->lock.flags);
 
 	free_cmdq->head = done_cmdq->head;
@@ -1884,7 +1783,6 @@ static int slic_rcvqueue_init(struct adapter *adapter)
 	int i, count;
 	struct slic_rcvqueue *rcvq = &adapter->rcvqueue;
 
-	ASSERT(adapter->state == ADAPT_DOWN);
 	rcvq->tail = NULL;
 	rcvq->head = NULL;
 	rcvq->size = SLIC_RCVQ_ENTRIES;
@@ -1913,7 +1811,6 @@ static struct sk_buff *slic_rcvqueue_getnext(struct adapter *adapter)
 	if (rcvq->count) {
 		skb = rcvq->head;
 		rcvbuf = (struct slic_rcvbuf *)skb->head;
-		ASSERT(rcvbuf);
 
 		if (rcvbuf->status & IRHDDR_SVALID) {
 			rcvq->head = rcvq->head->next;
@@ -1946,8 +1843,6 @@ static u32 slic_rcvqueue_reinsert(struct adapter *adapter, struct sk_buff *skb)
 	struct slic_rcvbuf *rcvbuf = (struct slic_rcvbuf *)skb->head;
 	struct device *dev;
 
-	ASSERT(skb->len == SLIC_RCVBUF_HEADSIZE);
-
 	paddr = (void *)pci_map_single(adapter->pcidev, skb->head,
 				  SLIC_RCVQ_RCVBUFSIZE, PCI_DMA_FROMDEVICE);
 	rcvbuf->status = 0;
@@ -2019,7 +1914,6 @@ static int slic_debug_card_show(struct seq_file *seq, void *v)
 		    card->adapters_activated);
 	seq_printf(seq, "     Allocated           : %d\n",
 		    card->adapters_allocated);
-	ASSERT(card->card_size <= SLIC_NBR_MACS);
 	for (i = 0; i < card->card_size; i++) {
 		seq_printf(seq,
 			   "     MAC%d : %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
@@ -2460,7 +2354,6 @@ static void slic_link_event_handler(struct adapter *adapter)
 		(u32) &pshmem->linkstatus,	/* no 4GB wrap guaranteed */
 				  0, 0, 0);
 #endif
-	ASSERT(status == 0);
 }
 
 static void slic_init_cleanup(struct adapter *adapter)
@@ -2524,8 +2417,6 @@ static void slic_mcast_set_list(struct net_device *dev)
 	char *addresses;
 	struct netdev_hw_addr *ha;
 
-	ASSERT(adapter);
-
 	netdev_for_each_mc_addr(ha, dev) {
 		addresses = (char *) &ha->addr;
 		status = slic_mcast_add_list(adapter, addresses);
@@ -2612,8 +2503,6 @@ static void slic_xmit_fail(struct adapter *adapter,
 				"xmit_start skb[%p] type[%x] No host commands "
 				"available\n", skb, skb->pkt_type);
 			break;
-		default:
-			ASSERT(0);
 		}
 	}
 	dev_kfree_skb(skb);
@@ -2725,7 +2614,6 @@ static void slic_rcv_handler(struct adapter *adapter)
 	while ((skb = slic_rcvqueue_getnext(adapter))) {
 		u32 rx_bytes;
 
-		ASSERT(skb->head);
 		rcvbuf = (struct slic_rcvbuf *)skb->head;
 		adapter->card->events++;
 		if (rcvbuf->status & IRHDDR_ERR) {
@@ -2781,16 +2669,11 @@ static void slic_xmit_complete(struct adapter *adapter)
 		 Get the complete host command buffer
 		*/
 		slic_handle_word.handle_token = rspbuf->hosthandle;
-		ASSERT(slic_handle_word.handle_index);
-		ASSERT(slic_handle_word.handle_index <= SLIC_CMDQ_MAXCMDS);
 		hcmd =
 		    (struct slic_hostcmd *)
 			adapter->slic_handles[slic_handle_word.handle_index].
 									address;
 /*      hcmd = (struct slic_hostcmd *) rspbuf->hosthandle; */
-		ASSERT(hcmd);
-		ASSERT(hcmd->pslic_handle ==
-		       &adapter->slic_handles[slic_handle_word.handle_index]);
 		if (hcmd->type == SLIC_CMD_DUMB) {
 			if (hcmd->skb)
 				dev_kfree_skb_irq(hcmd->skb);
@@ -2884,9 +2767,6 @@ static irqreturn_t slic_interrupt(int irq, void *dev_id)
 				slic_upr_request_complete(adapter, isr);
 			}
 			break;
-
-		default:
-			break;
 		}
 
 		adapter->isrcopy = 0;
@@ -2911,7 +2791,6 @@ static netdev_tx_t slic_xmit_start(struct sk_buff *skb, struct net_device *dev)
 	void *offloadcmd = NULL;
 
 	card = adapter->card;
-	ASSERT(card);
 	if ((adapter->linkstate != LINK_UP) ||
 	    (adapter->state != ADAPT_UP) || (card->state != CARD_UP)) {
 		status = XMIT_FAIL_LINK_STATE;
@@ -2929,9 +2808,6 @@ static netdev_tx_t slic_xmit_start(struct sk_buff *skb, struct net_device *dev)
 			status = XMIT_FAIL_HOSTCMD_FAIL;
 			goto xmit_fail;
 		}
-		ASSERT(hcmd->pslic_handle);
-		ASSERT(hcmd->cmd64.hosthandle ==
-		       hcmd->pslic_handle->token.handle_token);
 		hcmd->skb = skb;
 		hcmd->busy = 1;
 		hcmd->type = SLIC_CMD_DUMB;
@@ -3024,8 +2900,6 @@ static int slic_if_init(struct adapter *adapter)
 	struct slic_shmem *pshmem;
 	int rc;
 
-	ASSERT(card);
-
 	/* adapter should be down at this point */
 	if (adapter->state != ADAPT_DOWN) {
 		dev_err(&dev->dev, "%s: adapter->state != ADAPT_DOWN\n",
@@ -3033,7 +2907,6 @@ static int slic_if_init(struct adapter *adapter)
 		rc = -EIO;
 		goto err;
 	}
-	ASSERT(adapter->linkstate == LINK_DOWN);
 
 	adapter->devflags_prev = dev->flags;
 	adapter->macopts = MAC_DIRECTED;
@@ -3133,9 +3006,6 @@ static int slic_entry_open(struct net_device *dev)
 	struct sliccard *card = adapter->card;
 	int status;
 
-	ASSERT(adapter);
-	ASSERT(card);
-
 	netif_stop_queue(adapter->netdev);
 
 	spin_lock_irqsave(&slic_global.driver_lock.lock,
@@ -3176,7 +3046,7 @@ static void slic_card_cleanup(struct sliccard *card)
 	kfree(card);
 }
 
-static void __devexit slic_entry_remove(struct pci_dev *pcidev)
+static void slic_entry_remove(struct pci_dev *pcidev)
 {
 	struct net_device *dev = pci_get_drvdata(pcidev);
 	u32 mmio_start = 0;
@@ -3202,9 +3072,7 @@ static void __devexit slic_entry_remove(struct pci_dev *pcidev)
 		mlist = mlist->next;
 		kfree(mcaddr);
 	}
-	ASSERT(adapter->card);
 	card = adapter->card;
-	ASSERT(card->adapters_allocated);
 	card->adapters_allocated--;
 	adapter->allocated = 0;
 	if (!card->adapters_allocated) {
@@ -3214,10 +3082,8 @@ static void __devexit slic_entry_remove(struct pci_dev *pcidev)
 		} else {
 			while (curr_card->next != card)
 				curr_card = curr_card->next;
-			ASSERT(curr_card);
 			curr_card->next = card->next;
 		}
-		ASSERT(slic_global.num_slic_cards);
 		slic_global.num_slic_cards--;
 		slic_card_cleanup(card);
 	}
@@ -3234,14 +3100,12 @@ static int slic_entry_halt(struct net_device *dev)
 
 	spin_lock_irqsave(&slic_global.driver_lock.lock,
 				slic_global.driver_lock.flags);
-	ASSERT(card);
 	netif_stop_queue(adapter->netdev);
 	adapter->state = ADAPT_DOWN;
 	adapter->linkstate = LINK_DOWN;
 	adapter->upr_list = NULL;
 	adapter->upr_busy = 0;
 	adapter->devflags_prev = 0;
-	ASSERT(card->adapter[adapter->cardindex] == adapter);
 	slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH);
 	adapter->all_reg_writes++;
 	adapter->icr_reg_writes++;
@@ -3273,7 +3137,6 @@ static struct net_device_stats *slic_get_stats(struct net_device *dev)
 {
 	struct adapter *adapter = netdev_priv(dev);
 
-	ASSERT(adapter);
 	dev->stats.collisions = adapter->slic_stats.iface.xmit_collisions;
 	dev->stats.rx_errors = adapter->slic_stats.iface.rcv_errors;
 	dev->stats.tx_errors = adapter->slic_stats.iface.xmt_errors;
@@ -3296,7 +3159,6 @@ static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	u32 data[7];
 	u32 intagg;
 
-	ASSERT(rq);
 	switch (cmd) {
 	case SIOCSLICSETINTAGG:
 		if (copy_from_user(data, rq->ifr_data, 28))
@@ -3342,7 +3204,6 @@ static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 		}
 #endif
 	case SIOCETHTOOL:
-		ASSERT(adapter);
 		if (copy_from_user(&ecmd, rq->ifr_data, sizeof(ecmd)))
 			return -EFAULT;
 
@@ -3682,7 +3543,6 @@ static void slic_init_adapter(struct net_device *netdev,
 	/*
 	  Initialize slic_handle array
 	*/
-	ASSERT(SLIC_CMDQ_MAXCMDS <= 0xFFFF);
 	/*
 	 Start with 1.  0 is an invalid host handle.
 	*/
@@ -3699,8 +3559,6 @@ static void slic_init_adapter(struct net_device *netdev,
 					sizeof(struct slic_shmem),
 					&adapter->
 					phys_shmem);
-	ASSERT(adapter->pshmem);
-
 	if (adapter->pshmem)
 		memset(adapter->pshmem, 0, sizeof(struct slic_shmem));
 }
@@ -3775,11 +3633,9 @@ static u32 slic_card_locate(struct adapter *adapter)
 		}
 	}
 
-	ASSERT(card);
 	if (!card)
 		return -ENXIO;
 	/* Put the adapter in the card's adapter list */
-	ASSERT(card->adapter[adapter->port] == NULL);
 	if (!card->adapter[adapter->port]) {
 		card->adapter[adapter->port] = adapter;
 		adapter->card = card;
@@ -3794,7 +3650,6 @@ static u32 slic_card_locate(struct adapter *adapter)
 			else
 				break;
 		}
-		ASSERT(i != SLIC_MAX_PORTS);
 		if (physcard->adapter[i]->slotnumber == adapter->slotnumber)
 			break;
 		physcard = physcard->next;
@@ -3802,7 +3657,11 @@ static u32 slic_card_locate(struct adapter *adapter)
 	if (!physcard) {
 		/* no structure allocated for this physical card yet */
 		physcard = kzalloc(sizeof(struct physcard), GFP_ATOMIC);
-		ASSERT(physcard);
+		if (!physcard) {
+			if (card_hostid == SLIC_HOSTID_DEFAULT)
+				kfree(card);
+			return -ENOMEM;
+		}
 
 		physcard->next = slic_global.phys_card;
 		slic_global.phys_card = physcard;
@@ -3813,14 +3672,13 @@ static u32 slic_card_locate(struct adapter *adapter)
 	/* Note - this is ZERO relative */
 	adapter->physport = physcard->adapters_allocd - 1;
 
-	ASSERT(physcard->adapter[adapter->physport] == NULL);
 	physcard->adapter[adapter->physport] = adapter;
 	adapter->physcard = physcard;
 
 	return 0;
 }
 
-static int __devinit slic_entry_probe(struct pci_dev *pcidev,
+static int slic_entry_probe(struct pci_dev *pcidev,
 			       const struct pci_device_id *pci_tbl_entry)
 {
 	static int cards_found;
@@ -3962,7 +3820,7 @@ static struct pci_driver slic_driver = {
 	.name = DRV_NAME,
 	.id_table = slic_pci_tbl,
 	.probe = slic_entry_probe,
-	.remove = __devexit_p(slic_entry_remove),
+	.remove = slic_entry_remove,
 };
 
 static int __init slic_module_init(void)
diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c
index f27182d..0764bbb 100644
--- a/drivers/staging/sm7xxfb/sm7xxfb.c
+++ b/drivers/staging/sm7xxfb/sm7xxfb.c
@@ -768,7 +768,7 @@ static inline void sm7xx_init_hw(void)
 	outb_p(0x11, 0x3c5);
 }
 
-static int __devinit smtcfb_pci_probe(struct pci_dev *pdev,
+static int smtcfb_pci_probe(struct pci_dev *pdev,
 				   const struct pci_device_id *ent)
 {
 	struct smtcfb_info *sfb;
@@ -928,7 +928,7 @@ static DEFINE_PCI_DEVICE_TABLE(smtcfb_pci_table) = {
 	{0,}
 };
 
-static void __devexit smtcfb_pci_remove(struct pci_dev *pdev)
+static void smtcfb_pci_remove(struct pci_dev *pdev)
 {
 	struct smtcfb_info *sfb;
 
@@ -1027,7 +1027,7 @@ static struct pci_driver smtcfb_driver = {
 	.name = "smtcfb",
 	.id_table = smtcfb_pci_table,
 	.probe = smtcfb_pci_probe,
-	.remove = __devexit_p(smtcfb_pci_remove),
+	.remove = smtcfb_pci_remove,
 	.driver.pm  = SM7XX_PM_OPS,
 };
 
diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
index 277491a..299f518 100644
--- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
+++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
@@ -31,6 +31,7 @@
 #include <linux/interrupt.h>
 #include <linux/regulator/consumer.h>
 #include <linux/module.h>
+#include <linux/input/mt.h>
 #include "synaptics_i2c_rmi4.h"
 
 /* TODO: for multiple device support will need a per-device mutex */
@@ -67,7 +68,6 @@
 #define PDT_START_SCAN_LOCATION (0x00E9)
 #define PDT_END_SCAN_LOCATION	(0x000A)
 #define PDT_ENTRY_SIZE		(0x0006)
-#define RMI4_NUMBER_OF_MAX_FINGERS		(8)
 #define SYNAPTICS_RMI4_TOUCHPAD_FUNC_NUM	(0x11)
 #define SYNAPTICS_RMI4_DEVICE_CONTROL_FUNC_NUM	(0x01)
 
@@ -164,6 +164,7 @@ struct synaptics_rmi4_device_info {
  * @regulator: pointer to the regulator structure
  * @wait: wait queue structure variable
  * @touch_stopped: flag to stop the thread function
+ * @fingers_supported: maximum supported fingers
  *
  * This structure gives the device data information.
  */
@@ -184,6 +185,7 @@ struct synaptics_rmi4_data {
 	struct regulator	*regulator;
 	wait_queue_head_t	wait;
 	bool			touch_stopped;
+	unsigned char		fingers_supported;
 };
 
 /**
@@ -303,22 +305,21 @@ static int synpatics_rmi4_touchpad_report(struct synaptics_rmi4_data *pdata,
 	/* number of touch points - fingers down in this case */
 	int	touch_count = 0;
 	int	finger;
-	int	fingers_supported;
 	int	finger_registers;
 	int	reg;
 	int	finger_shift;
 	int	finger_status;
 	int	retval;
+	int	x, y;
+	int	wx, wy;
 	unsigned short	data_base_addr;
 	unsigned short	data_offset;
 	unsigned char	data_reg_blk_size;
 	unsigned char	values[2];
 	unsigned char	data[DATA_LEN];
-	int	x[RMI4_NUMBER_OF_MAX_FINGERS];
-	int	y[RMI4_NUMBER_OF_MAX_FINGERS];
-	int	wx[RMI4_NUMBER_OF_MAX_FINGERS];
-	int	wy[RMI4_NUMBER_OF_MAX_FINGERS];
+	unsigned char	fingers_supported = pdata->fingers_supported;
 	struct	i2c_client *client = pdata->i2c_client;
+	struct	input_dev *input_dev = pdata->input_dev;
 
 	/* get 2D sensor finger data */
 	/*
@@ -333,7 +334,6 @@ static int synpatics_rmi4_touchpad_report(struct synaptics_rmi4_data *pdata,
 	 *	10 = finger present but data may not be accurate,
 	 *	11 = reserved for product use.
 	 */
-	fingers_supported	= rfi->num_of_data_points;
 	finger_registers	= (fingers_supported + 3)/4;
 	data_base_addr		= rfi->fn_desc.data_base_addr;
 	retval = synaptics_rmi4_i2c_block_read(pdata, data_base_addr, values,
@@ -358,7 +358,11 @@ static int synpatics_rmi4_touchpad_report(struct synaptics_rmi4_data *pdata,
 		 * if finger status indicates a finger is present then
 		 * read the finger data and report it
 		 */
-		if (finger_status == 1 || finger_status == 2) {
+		input_mt_slot(input_dev, finger);
+		input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
+							finger_status != 0);
+
+		if (finger_status) {
 			/* Read the finger data */
 			data_offset = data_base_addr +
 					((finger * data_reg_blk_size) +
@@ -367,50 +371,33 @@ static int synpatics_rmi4_touchpad_report(struct synaptics_rmi4_data *pdata,
 						data_offset, data,
 						data_reg_blk_size);
 			if (retval != data_reg_blk_size) {
-				printk(KERN_ERR "%s:read data failed\n",
+				dev_err(&client->dev, "%s:read data failed\n",
 								__func__);
 				return 0;
-			} else {
-				x[touch_count]	=
-					(data[0] << 4) | (data[2] & MASK_4BIT);
-				y[touch_count]	=
-					(data[1] << 4) |
-					((data[2] >> 4) & MASK_4BIT);
-				wy[touch_count]	=
-						(data[3] >> 4) & MASK_4BIT;
-				wx[touch_count]	=
-						(data[3] & MASK_4BIT);
-
-				if (pdata->board->x_flip)
-					x[touch_count] =
-						pdata->sensor_max_x -
-								x[touch_count];
-				if (pdata->board->y_flip)
-					y[touch_count] =
-						pdata->sensor_max_y -
-								y[touch_count];
 			}
+			x = (data[0] << 4) | (data[2] & MASK_4BIT);
+			y = (data[1] << 4) | ((data[2] >> 4) & MASK_4BIT);
+			wy = (data[3] >> 4) & MASK_4BIT;
+			wx = (data[3] & MASK_4BIT);
+
+			if (pdata->board->x_flip)
+				x = pdata->sensor_max_x - x;
+			if (pdata->board->y_flip)
+				y = pdata->sensor_max_y - y;
+
+			input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
+								max(wx, wy));
+			input_report_abs(input_dev, ABS_MT_POSITION_X, x);
+			input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
+
 			/* number of active touch points */
 			touch_count++;
 		}
 	}
 
-	/* report to input subsystem */
-	if (touch_count) {
-		for (finger = 0; finger < touch_count; finger++) {
-			input_report_abs(pdata->input_dev, ABS_MT_TOUCH_MAJOR,
-						max(wx[finger] , wy[finger]));
-			input_report_abs(pdata->input_dev, ABS_MT_POSITION_X,
-								x[finger]);
-			input_report_abs(pdata->input_dev, ABS_MT_POSITION_Y,
-								y[finger]);
-			input_mt_sync(pdata->input_dev);
-		}
-	} else
-		input_mt_sync(pdata->input_dev);
-
 	/* sync after groups of events */
-	input_sync(pdata->input_dev);
+	input_mt_sync_frame(input_dev);
+	input_sync(input_dev);
 	/* return the number of touch points */
 	return touch_count;
 }
@@ -575,6 +562,7 @@ static int synpatics_rmi4_touchpad_detect(struct synaptics_rmi4_data *pdata,
 		if ((queries[1] & MASK_3BIT) == 5)
 			rfi->num_of_data_points = 10;
 	}
+	pdata->fingers_supported = rfi->num_of_data_points;
 	/* Need to get interrupt info for handling interrupts */
 	rfi->index_to_intr_reg = (interruptcount + 7)/8;
 	if (rfi->index_to_intr_reg != 0)
@@ -891,7 +879,7 @@ static int synaptics_rmi4_i2c_query_device(struct synaptics_rmi4_data *pdata)
  * the rmi4 Physical Device Table and enumerate any rmi4 functions that
  * have data sources associated with them.
  */
-static int __devinit synaptics_rmi4_probe
+static int synaptics_rmi4_probe
 	(struct i2c_client *client, const struct i2c_device_id *dev_id)
 {
 	int retval;
@@ -988,6 +976,8 @@ static int __devinit synaptics_rmi4_probe
 					rmi4_data->sensor_max_y, 0, 0);
 	input_set_abs_params(rmi4_data->input_dev, ABS_MT_TOUCH_MAJOR, 0,
 						MAX_TOUCH_MAJOR, 0, 0);
+	input_mt_init_slots(rmi4_data->input_dev,
+				rmi4_data->fingers_supported, 0);
 
 	/* Clear interrupts */
 	synaptics_rmi4_i2c_block_read(rmi4_data,
@@ -1032,7 +1022,7 @@ err_input:
  * This function uses to remove the i2c-client
  * touchscreen driver and returns integer.
  */
-static int __devexit synaptics_rmi4_remove(struct i2c_client *client)
+static int synaptics_rmi4_remove(struct i2c_client *client)
 {
 	struct synaptics_rmi4_data *rmi4_data = i2c_get_clientdata(client);
 	const struct synaptics_rmi4_platform_data *pdata = rmi4_data->board;
@@ -1140,33 +1130,11 @@ static struct i2c_driver synaptics_rmi4_driver = {
 #endif
 	},
 	.probe		=	synaptics_rmi4_probe,
-	.remove		=	__devexit_p(synaptics_rmi4_remove),
+	.remove		=	synaptics_rmi4_remove,
 	.id_table	=	synaptics_rmi4_id_table,
 };
-/**
- * synaptics_rmi4_init() - Initialize the touchscreen driver
- *
- * This function uses to initializes the synaptics
- * touchscreen driver and returns integer.
- */
-static int __init synaptics_rmi4_init(void)
-{
-	return i2c_add_driver(&synaptics_rmi4_driver);
-}
-/**
- * synaptics_rmi4_exit() - De-initialize the touchscreen driver
- *
- * This function uses to de-initialize the synaptics
- * touchscreen driver and returns none.
- */
-static void __exit synaptics_rmi4_exit(void)
-{
-	i2c_del_driver(&synaptics_rmi4_driver);
-}
-
 
-module_init(synaptics_rmi4_init);
-module_exit(synaptics_rmi4_exit);
+module_i2c_driver(synaptics_rmi4_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("naveen.gaddipati@stericsson.com, js.ha@stericsson.com");
diff --git a/drivers/staging/telephony/Kconfig b/drivers/staging/telephony/Kconfig
deleted file mode 100644
index b5f78b6..0000000
--- a/drivers/staging/telephony/Kconfig
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# Telephony device configuration
-#
-
-menuconfig PHONE
-	tristate "Telephony support"
-	depends on HAS_IOMEM
-	---help---
-	  Say Y here if you have a telephony card, which for example allows
-	  you to use a regular phone for voice-over-IP applications.
-
-	  Note: this has nothing to do with modems.  You do not need to say Y
-	  here in order to be able to use a modem under Linux.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called phonedev.
-
-if PHONE
-
-config PHONE_IXJ
-	tristate "QuickNet Internet LineJack/PhoneJack support"
-	depends on ISA || PCI
-	---help---
-	  Say M if you have a telephony card manufactured by Quicknet
-	  Technologies, Inc.  These include the Internet PhoneJACK and
-	  Internet LineJACK Telephony Cards. You will get a module called
-	  ixj.
-
-	  For the ISA versions of these products, you can configure the
-	  cards using the isapnp tools (pnpdump/isapnp) or you can use the
-	  isapnp support.  Please read <file:Documentation/telephony/ixj.txt>.
-
-	  For more information on these cards, see Quicknet's web site at:
-	  <http://www.quicknet.net/>.
-
-	  If you do not have any Quicknet telephony cards, you can safely
-	  say N here.
-
-config PHONE_IXJ_PCMCIA
-	tristate "QuickNet Internet LineJack/PhoneJack PCMCIA support"
-	depends on PHONE_IXJ && PCMCIA
-	help
-	  Say Y here to configure in PCMCIA service support for the Quicknet
-	  cards manufactured by Quicknet Technologies, Inc.  This changes the
-	  card initialization code to work with the card manager daemon.
-
-endif # PHONE
diff --git a/drivers/staging/telephony/Makefile b/drivers/staging/telephony/Makefile
deleted file mode 100644
index 1206615..0000000
--- a/drivers/staging/telephony/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for drivers/telephony
-#
-
-obj-$(CONFIG_PHONE) += phonedev.o
-obj-$(CONFIG_PHONE_IXJ) += ixj.o
-obj-$(CONFIG_PHONE_IXJ_PCMCIA) += ixj_pcmcia.o
diff --git a/drivers/staging/telephony/TODO b/drivers/staging/telephony/TODO
deleted file mode 100644
index d47dec3..0000000
--- a/drivers/staging/telephony/TODO
+++ /dev/null
@@ -1,10 +0,0 @@
-TODO
-. Determine if the boards are still in use
-  and move this module back to drivers/telephony if necessary
-. Coding style cleanups
-
-Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
-cc Joe Perches <joe@perches.com> if the module should be reactivated.
-
-If no module activity occurs before version 3.6 is released, this
-module should be removed.
diff --git a/drivers/staging/telephony/ixj-ver.h b/drivers/staging/telephony/ixj-ver.h
deleted file mode 100644
index 2031ac6..0000000
--- a/drivers/staging/telephony/ixj-ver.h
+++ /dev/null
@@ -1,4 +0,0 @@
-/* configuration management identifiers */
-#define IXJ_VER_MAJOR 1
-#define IXJ_VER_MINOR 0
-#define IXJ_BLD_VER   1
diff --git a/drivers/staging/telephony/ixj.c b/drivers/staging/telephony/ixj.c
deleted file mode 100644
index 1cfa0b0..0000000
--- a/drivers/staging/telephony/ixj.c
+++ /dev/null
@@ -1,10571 +0,0 @@
-/****************************************************************************
- *    ixj.c
- *
- * Device Driver for Quicknet Technologies, Inc.'s Telephony cards
- * including the Internet PhoneJACK, Internet PhoneJACK Lite,
- * Internet PhoneJACK PCI, Internet LineJACK, Internet PhoneCARD and
- * SmartCABLE
- *
- *    (c) Copyright 1999-2001  Quicknet Technologies, 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.
- *
- * Author:          Ed Okerson, <eokerson@quicknet.net>
- *
- * Contributors:    Greg Herlein, <gherlein@quicknet.net>
- *                  David W. Erhart, <derhart@quicknet.net>
- *                  John Sellers, <jsellers@quicknet.net>
- *                  Mike Preston, <mpreston@quicknet.net>
- *
- * Fixes:           David Huggins-Daines, <dhd@cepstral.com>
- *                  Fabio Ferrari, <fabio.ferrari@digitro.com.br>
- *                  Artis Kugevics, <artis@mt.lv>
- *                  Daniele Bellucci, <bellucda@tiscali.it>
- *
- * More information about the hardware related to this driver can be found
- * at our website:    http://www.quicknet.net
- *
- * IN NO EVENT SHALL QUICKNET TECHNOLOGIES, INC. BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF QUICKNET
- * TECHNOLOGIES, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * QUICKNET TECHNOLOGIES, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND QUICKNET TECHNOLOGIES, INC. HAS NO OBLIGATION
- * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- ***************************************************************************/
-
-/*
- * Revision 4.8  2003/07/09 19:39:00  Daniele Bellucci
- * Audit some copy_*_user and minor cleanup.
- *
- * Revision 4.7  2001/08/13 06:19:33  craigs
- * Added additional changes from Alan Cox and John Anderson for
- * 2.2 to 2.4 cleanup and bounds checking
- *
- * Revision 4.6  2001/08/13 01:05:05  craigs
- * Really fixed PHONE_QUERY_CODEC problem this time
- *
- * Revision 4.5  2001/08/13 00:11:03  craigs
- * Fixed problem in handling of PHONE_QUERY_CODEC, thanks to Shane Anderson
- *
- * Revision 4.4  2001/08/07 07:58:12  craigs
- * Changed back to three digit version numbers
- * Added tagbuild target to allow automatic and easy tagging of versions
- *
- * Revision 4.3  2001/08/07 07:24:47  craigs
- * Added ixj-ver.h to allow easy configuration management of driver
- * Added display of version number in /prox/ixj
- *
- * Revision 4.2  2001/08/06 07:07:19  craigs
- * Reverted IXJCTL_DSP_TYPE and IXJCTL_DSP_VERSION files to original
- * behaviour of returning int rather than short *
- *
- * Revision 4.1  2001/08/05 00:17:37  craigs
- * More changes for correct PCMCIA installation
- * Start of changes for backward Linux compatibility
- *
- * Revision 4.0  2001/08/04 12:33:12  craigs
- * New version using GNU autoconf
- *
- * Revision 3.105  2001/07/20 23:14:32  eokerson
- * More work on CallerID generation when using ring cadences.
- *
- * Revision 3.104  2001/07/06 01:33:55  eokerson
- * Some bugfixes from Robert Vojta <vojta@ipex.cz> and a few mods to the Makefile.
- *
- * Revision 3.103  2001/07/05 19:20:16  eokerson
- * Updated HOWTO
- * Changed mic gain to 30dB on Internet LineJACK mic/speaker port.
- *
- * Revision 3.102  2001/07/03 23:51:21  eokerson
- * Un-mute mic on Internet LineJACK when in speakerphone mode.
- *
- * Revision 3.101  2001/07/02 19:26:56  eokerson
- * Removed initialiazation of ixjdebug and ixj_convert_loaded so they will go in the .bss instead of the .data
- *
- * Revision 3.100  2001/07/02 19:18:27  eokerson
- * Changed driver to make dynamic allocation possible.  We now pass IXJ * between functions instead of array indexes.
- * Fixed the way the POTS and PSTN ports interact during a PSTN call to allow local answering.
- * Fixed speaker mode on Internet LineJACK.
- *
- * Revision 3.99  2001/05/09 14:11:16  eokerson
- * Fixed kmalloc error in ixj_build_filter_cadence.  Thanks David Chan <cat@waulogy.stanford.edu>.
- *
- * Revision 3.98  2001/05/08 19:55:33  eokerson
- * Fixed POTS hookstate detection while it is connected to PSTN port.
- *
- * Revision 3.97  2001/05/08 00:01:04  eokerson
- * Fixed kernel oops when sending caller ID data.
- *
- * Revision 3.96  2001/05/04 23:09:30  eokerson
- * Now uses one kernel timer for each card, instead of one for the entire driver.
- *
- * Revision 3.95  2001/04/25 22:06:47  eokerson
- * Fixed squawking at beginning of some G.723.1 calls.
- *
- * Revision 3.94  2001/04/03 23:42:00  eokerson
- * Added linear volume ioctls
- * Added raw filter load ioctl
- *
- * Revision 3.93  2001/02/27 01:00:06  eokerson
- * Fixed blocking in CallerID.
- * Reduced size of ixj structure for smaller driver footprint.
- *
- * Revision 3.92  2001/02/20 22:02:59  eokerson
- * Fixed isapnp and pcmcia module compatibility for 2.4.x kernels.
- * Improved PSTN ring detection.
- * Fixed wink generation on POTS ports.
- *
- * Revision 3.91  2001/02/13 00:55:44  eokerson
- * Turn AEC back on after changing frame sizes.
- *
- * Revision 3.90  2001/02/12 16:42:00  eokerson
- * Added ALAW codec, thanks to Fabio Ferrari for the table based converters to make ALAW from ULAW.
- *
- * Revision 3.89  2001/02/12 15:41:16  eokerson
- * Fix from Artis Kugevics - Tone gains were not being set correctly.
- *
- * Revision 3.88  2001/02/05 23:25:42  eokerson
- * Fixed lockup bugs with deregister.
- *
- * Revision 3.87  2001/01/29 21:00:39  eokerson
- * Fix from Fabio Ferrari <fabio.ferrari@digitro.com.br> to properly handle EAGAIN and EINTR during non-blocking write.
- * Updated copyright date.
- *
- * Revision 3.86  2001/01/23 23:53:46  eokerson
- * Fixes to G.729 compatibility.
- *
- * Revision 3.85  2001/01/23 21:30:36  eokerson
- * Added verbage about cards supported.
- * Removed commands that put the card in low power mode at some times that it should not be in low power mode.
- *
- * Revision 3.84  2001/01/22 23:32:10  eokerson
- * Some bugfixes from David Huggins-Daines, <dhd@cepstral.com> and other cleanups.
- *
- * Revision 3.83  2001/01/19 14:51:41  eokerson
- * Fixed ixj_WriteDSPCommand to decrement usage counter when command fails.
- *
- * Revision 3.82  2001/01/19 00:34:49  eokerson
- * Added verbosity to write overlap errors.
- *
- * Revision 3.81  2001/01/18 23:56:54  eokerson
- * Fixed PSTN line test functions.
- *
- * Revision 3.80  2001/01/18 22:29:27  eokerson
- * Updated AEC/AGC values for different cards.
- *
- * Revision 3.79  2001/01/17 02:58:54  eokerson
- * Fixed AEC reset after Caller ID.
- * Fixed Codec lockup after Caller ID on Call Waiting when not using 30ms frames.
- *
- * Revision 3.78  2001/01/16 19:43:09  eokerson
- * Added support for Linux 2.4.x kernels.
- *
- * Revision 3.77  2001/01/09 04:00:52  eokerson
- * Linetest will now test the line, even if it has previously succeeded.
- *
- * Revision 3.76  2001/01/08 19:27:00  eokerson
- * Fixed problem with standard cable on Internet PhoneCARD.
- *
- * Revision 3.75  2000/12/22 16:52:14  eokerson
- * Modified to allow hookstate detection on the POTS port when the PSTN port is selected.
- *
- * Revision 3.74  2000/12/08 22:41:50  eokerson
- * Added capability for G729B.
- *
- * Revision 3.73  2000/12/07 23:35:16  eokerson
- * Added capability to have different ring pattern before CallerID data.
- * Added hookstate checks in CallerID routines to stop FSK.
- *
- * Revision 3.72  2000/12/06 19:31:31  eokerson
- * Modified signal behavior to only send one signal per event.
- *
- * Revision 3.71  2000/12/06 03:23:08  eokerson
- * Fixed CallerID on Call Waiting.
- *
- * Revision 3.70  2000/12/04 21:29:37  eokerson
- * Added checking to Smart Cable gain functions.
- *
- * Revision 3.69  2000/12/04 21:05:20  eokerson
- * Changed ixjdebug levels.
- * Added ioctls to change gains in Internet Phone CARD Smart Cable.
- *
- * Revision 3.68  2000/12/04 00:17:21  craigs
- * Changed mixer voice gain to +6dB rather than 0dB
- *
- * Revision 3.67  2000/11/30 21:25:51  eokerson
- * Fixed write signal errors.
- *
- * Revision 3.66  2000/11/29 22:42:44  eokerson
- * Fixed PSTN ring detect problems.
- *
- * Revision 3.65  2000/11/29 07:31:55  craigs
- * Added new 425Hz filter co-efficients
- * Added card-specific DTMF prescaler initialisation
- *
- * Revision 3.64  2000/11/28 14:03:32  craigs
- * Changed certain mixer initialisations to be 0dB rather than 12dB
- * Added additional information to /proc/ixj
- *
- * Revision 3.63  2000/11/28 11:38:41  craigs
- * Added display of AEC modes in AUTO and AGC mode
- *
- * Revision 3.62  2000/11/28 04:05:44  eokerson
- * Improved PSTN ring detection routine.
- *
- * Revision 3.61  2000/11/27 21:53:12  eokerson
- * Fixed flash detection.
- *
- * Revision 3.60  2000/11/27 15:57:29  eokerson
- * More work on G.729 load routines.
- *
- * Revision 3.59  2000/11/25 21:55:12  eokerson
- * Fixed errors in G.729 load routine.
- *
- * Revision 3.58  2000/11/25 04:08:29  eokerson
- * Added board locks around G.729 and TS85 load routines.
- *
- * Revision 3.57  2000/11/24 05:35:17  craigs
- * Added ability to retrieve mixer values on LineJACK
- * Added complete initialisation of all mixer values at startup
- * Fixed spelling mistake
- *
- * Revision 3.56  2000/11/23 02:52:11  robertj
- * Added cvs change log keyword.
- * Fixed bug in capabilities list when using G.729 module.
- *
- */
-
-#include "ixj-ver.h"
-
-#define PERFMON_STATS
-#define IXJDEBUG 0
-#define MAXRINGS 5
-
-#include <linux/module.h>
-
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>	/* printk() */
-#include <linux/fs.h>		/* everything... */
-#include <linux/errno.h>	/* error codes */
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/poll.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <linux/isapnp.h>
-
-#include "ixj.h"
-
-#define TYPE(inode) (iminor(inode) >> 4)
-#define NUM(inode) (iminor(inode) & 0xf)
-
-static DEFINE_MUTEX(ixj_mutex);
-static int ixjdebug;
-static int hertz = HZ;
-static int samplerate = 100;
-
-module_param(ixjdebug, int, 0);
-
-static DEFINE_PCI_DEVICE_TABLE(ixj_pci_tbl) = {
-	{ PCI_VENDOR_ID_QUICKNET, PCI_DEVICE_ID_QUICKNET_XJ,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, ixj_pci_tbl);
-
-/************************************************************************
-*
-* ixjdebug meanings are now bit mapped instead of level based
-* Values can be or'ed together to turn on multiple messages
-*
-* bit  0 (0x0001) = any failure
-* bit  1 (0x0002) = general messages
-* bit  2 (0x0004) = POTS ringing related
-* bit  3 (0x0008) = PSTN events
-* bit  4 (0x0010) = PSTN Cadence state details
-* bit  5 (0x0020) = Tone detection triggers
-* bit  6 (0x0040) = Tone detection cadence details
-* bit  7 (0x0080) = ioctl tracking
-* bit  8 (0x0100) = signal tracking
-* bit  9 (0x0200) = CallerID generation details
-*
-************************************************************************/
-
-#ifdef IXJ_DYN_ALLOC
-
-static IXJ *ixj[IXJMAX];
-#define	get_ixj(b)	ixj[(b)]
-
-/*
- *	Allocate a free IXJ device
- */
-
-static IXJ *ixj_alloc()
-{
-	for(cnt=0; cnt<IXJMAX; cnt++)
-	{
-		if(ixj[cnt] == NULL || !ixj[cnt]->DSPbase)
-		{
-			j = kmalloc(sizeof(IXJ), GFP_KERNEL);
-			if (j == NULL)
-				return NULL;
-			ixj[cnt] = j;
-			return j;
-		}
-	}
-	return NULL;
-}
-
-static void ixj_fsk_free(IXJ *j)
-{
-	kfree(j->fskdata);
-	j->fskdata = NULL;
-}
-
-static void ixj_fsk_alloc(IXJ *j)
-{
-	if(!j->fskdata) {
-		j->fskdata = kmalloc(8000, GFP_KERNEL);
-		if (!j->fskdata) {
-			if(ixjdebug & 0x0200) {
-				printk("IXJ phone%d - allocate failed\n", j->board);
-			}
-			return;
-		} else {
-			j->fsksize = 8000;
-			if(ixjdebug & 0x0200) {
-				printk("IXJ phone%d - allocate succeeded\n", j->board);
-			}
-		}
-	}
-}
-
-#else
-
-static IXJ ixj[IXJMAX];
-#define	get_ixj(b)	(&ixj[(b)])
-
-/*
- *	Allocate a free IXJ device
- */
-
-static IXJ *ixj_alloc(void)
-{
-	int cnt;
-	for(cnt=0; cnt<IXJMAX; cnt++) {
-		if(!ixj[cnt].DSPbase)
-			return &ixj[cnt];
-	}
-	return NULL;
-}
-
-static inline void ixj_fsk_free(IXJ *j) {;}
-
-static inline void ixj_fsk_alloc(IXJ *j)
-{
-	j->fsksize = 8000;
-}
-
-#endif
-
-#ifdef PERFMON_STATS
-#define ixj_perfmon(x)	((x)++)
-#else
-#define ixj_perfmon(x)	do { } while(0)
-#endif
-
-static int ixj_convert_loaded;
-
-static int ixj_WriteDSPCommand(unsigned short, IXJ *j);
-
-/************************************************************************
-*
-* These are function definitions to allow external modules to register
-* enhanced functionality call backs.
-*
-************************************************************************/
-
-static int Stub(IXJ * J, unsigned long arg)
-{
-	return 0;
-}
-
-static IXJ_REGFUNC ixj_PreRead = &Stub;
-static IXJ_REGFUNC ixj_PostRead = &Stub;
-static IXJ_REGFUNC ixj_PreWrite = &Stub;
-static IXJ_REGFUNC ixj_PostWrite = &Stub;
-
-static void ixj_read_frame(IXJ *j);
-static void ixj_write_frame(IXJ *j);
-static void ixj_init_timer(IXJ *j);
-static void ixj_add_timer(IXJ *	j);
-static void ixj_timeout(unsigned long ptr);
-static int read_filters(IXJ *j);
-static int LineMonitor(IXJ *j);
-static int ixj_fasync(int fd, struct file *, int mode);
-static int ixj_set_port(IXJ *j, int arg);
-static int ixj_set_pots(IXJ *j, int arg);
-static int ixj_hookstate(IXJ *j);
-static int ixj_record_start(IXJ *j);
-static void ixj_record_stop(IXJ *j);
-static void set_rec_volume(IXJ *j, int volume);
-static int get_rec_volume(IXJ *j);
-static int set_rec_codec(IXJ *j, int rate);
-static void ixj_vad(IXJ *j, int arg);
-static int ixj_play_start(IXJ *j);
-static void ixj_play_stop(IXJ *j);
-static int ixj_set_tone_on(unsigned short arg, IXJ *j);
-static int ixj_set_tone_off(unsigned short, IXJ *j);
-static int ixj_play_tone(IXJ *j, char tone);
-static void ixj_aec_start(IXJ *j, int level);
-static int idle(IXJ *j);
-static void ixj_ring_on(IXJ *j);
-static void ixj_ring_off(IXJ *j);
-static void aec_stop(IXJ *j);
-static void ixj_ringback(IXJ *j);
-static void ixj_busytone(IXJ *j);
-static void ixj_dialtone(IXJ *j);
-static void ixj_cpt_stop(IXJ *j);
-static char daa_int_read(IXJ *j);
-static char daa_CR_read(IXJ *j, int cr);
-static int daa_set_mode(IXJ *j, int mode);
-static int ixj_linetest(IXJ *j);
-static int ixj_daa_write(IXJ *j);
-static int ixj_daa_cid_read(IXJ *j);
-static void DAA_Coeff_US(IXJ *j);
-static void DAA_Coeff_UK(IXJ *j);
-static void DAA_Coeff_France(IXJ *j);
-static void DAA_Coeff_Germany(IXJ *j);
-static void DAA_Coeff_Australia(IXJ *j);
-static void DAA_Coeff_Japan(IXJ *j);
-static int ixj_init_filter(IXJ *j, IXJ_FILTER * jf);
-static int ixj_init_filter_raw(IXJ *j, IXJ_FILTER_RAW * jfr);
-static int ixj_init_tone(IXJ *j, IXJ_TONE * ti);
-static int ixj_build_cadence(IXJ *j, IXJ_CADENCE __user * cp);
-static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE __user * cp);
-/* Serial Control Interface funtions */
-static int SCI_Control(IXJ *j, int control);
-static int SCI_Prepare(IXJ *j);
-static int SCI_WaitHighSCI(IXJ *j);
-static int SCI_WaitLowSCI(IXJ *j);
-static DWORD PCIEE_GetSerialNumber(WORD wAddress);
-static int ixj_PCcontrol_wait(IXJ *j);
-static void ixj_pre_cid(IXJ *j);
-static void ixj_write_cid(IXJ *j);
-static void ixj_write_cid_bit(IXJ *j, int bit);
-static int set_base_frame(IXJ *j, int size);
-static int set_play_codec(IXJ *j, int rate);
-static void set_rec_depth(IXJ *j, int depth);
-static int ixj_mixer(long val, IXJ *j);
-
-/************************************************************************
-CT8020/CT8021 Host Programmers Model
-Host address	Function					Access
-DSPbase +
-0-1		Aux Software Status Register (reserved)		Read Only
-2-3		Software Status Register			Read Only
-4-5		Aux Software Control Register (reserved)	Read Write
-6-7		Software Control Register			Read Write
-8-9		Hardware Status Register			Read Only
-A-B		Hardware Control Register			Read Write
-C-D Host Transmit (Write) Data Buffer Access Port (buffer input)Write Only
-E-F Host Receive (Read) Data Buffer Access Port (buffer input)	Read Only
-************************************************************************/
-
-static inline void ixj_read_HSR(IXJ *j)
-{
-	j->hsr.bytes.low = inb_p(j->DSPbase + 8);
-	j->hsr.bytes.high = inb_p(j->DSPbase + 9);
-}
-
-static inline int IsControlReady(IXJ *j)
-{
-	ixj_read_HSR(j);
-	return j->hsr.bits.controlrdy ? 1 : 0;
-}
-
-static inline int IsPCControlReady(IXJ *j)
-{
-	j->pccr1.byte = inb_p(j->XILINXbase + 3);
-	return j->pccr1.bits.crr ? 1 : 0;
-}
-
-static inline int IsStatusReady(IXJ *j)
-{
-	ixj_read_HSR(j);
-	return j->hsr.bits.statusrdy ? 1 : 0;
-}
-
-static inline int IsRxReady(IXJ *j)
-{
-	ixj_read_HSR(j);
-	ixj_perfmon(j->rxreadycheck);
-	return j->hsr.bits.rxrdy ? 1 : 0;
-}
-
-static inline int IsTxReady(IXJ *j)
-{
-	ixj_read_HSR(j);
-	ixj_perfmon(j->txreadycheck);
-	return j->hsr.bits.txrdy ? 1 : 0;
-}
-
-static inline void set_play_volume(IXJ *j, int volume)
-{
-	if (ixjdebug & 0x0002)
-		printk(KERN_INFO "IXJ: /dev/phone%d Setting Play Volume to 0x%4.4x\n", j->board, volume);
-	ixj_WriteDSPCommand(0xCF02, j);
-	ixj_WriteDSPCommand(volume, j);
-}
-
-static int set_play_volume_linear(IXJ *j, int volume)
-{
-	int newvolume, dspplaymax;
-
-	if (ixjdebug & 0x0002)
-		printk(KERN_INFO "IXJ: /dev/phone %d Setting Linear Play Volume to 0x%4.4x\n", j->board, volume);
-	if(volume > 100 || volume < 0) {
-		return -1;
-	}
-
-	/* This should normalize the perceived volumes between the different cards caused by differences in the hardware */
-	switch (j->cardtype) {
-	case QTI_PHONEJACK:
-		dspplaymax = 0x380;
-		break;
-	case QTI_LINEJACK:
-		if(j->port == PORT_PSTN) {
-			dspplaymax = 0x48;
-		} else {
-			dspplaymax = 0x100;
-		}
-		break;
-	case QTI_PHONEJACK_LITE:
-		dspplaymax = 0x380;
-		break;
-	case QTI_PHONEJACK_PCI:
-		dspplaymax = 0x6C;
-		break;
-	case QTI_PHONECARD:
-		dspplaymax = 0x50;
-		break;
-	default:
-		return -1;
-	}
-	newvolume = (dspplaymax * volume) / 100;
-	set_play_volume(j, newvolume);
-	return 0;
-}
-
-static inline void set_play_depth(IXJ *j, int depth)
-{
-	if (depth > 60)
-		depth = 60;
-	if (depth < 0)
-		depth = 0;
-	ixj_WriteDSPCommand(0x5280 + depth, j);
-}
-
-static inline int get_play_volume(IXJ *j)
-{
-	ixj_WriteDSPCommand(0xCF00, j);
-	return j->ssr.high << 8 | j->ssr.low;
-}
-
-static int get_play_volume_linear(IXJ *j)
-{
-	int volume, newvolume, dspplaymax;
-
-	/* This should normalize the perceived volumes between the different cards caused by differences in the hardware */
-	switch (j->cardtype) {
-	case QTI_PHONEJACK:
-		dspplaymax = 0x380;
-		break;
-	case QTI_LINEJACK:
-		if(j->port == PORT_PSTN) {
-			dspplaymax = 0x48;
-		} else {
-			dspplaymax = 0x100;
-		}
-		break;
-	case QTI_PHONEJACK_LITE:
-		dspplaymax = 0x380;
-		break;
-	case QTI_PHONEJACK_PCI:
-		dspplaymax = 0x6C;
-		break;
-	case QTI_PHONECARD:
-		dspplaymax = 100;
-		break;
-	default:
-		return -1;
-	}
-	volume = get_play_volume(j);
-	newvolume = (volume * 100) / dspplaymax;
-	if(newvolume > 100)
-		newvolume = 100;
-	return newvolume;
-}
-
-static inline BYTE SLIC_GetState(IXJ *j)
-{
-	if (j->cardtype == QTI_PHONECARD) {
-		j->pccr1.byte = 0;
-		j->psccr.bits.dev = 3;
-		j->psccr.bits.rw = 1;
-		outw_p(j->psccr.byte << 8, j->XILINXbase + 0x00);
-		ixj_PCcontrol_wait(j);
-		j->pslic.byte = inw_p(j->XILINXbase + 0x00) & 0xFF;
-		ixj_PCcontrol_wait(j);
-		if (j->pslic.bits.powerdown)
-			return PLD_SLIC_STATE_OC;
-		else if (!j->pslic.bits.ring0 && !j->pslic.bits.ring1)
-			return PLD_SLIC_STATE_ACTIVE;
-		else
-			return PLD_SLIC_STATE_RINGING;
-	} else {
-		j->pld_slicr.byte = inb_p(j->XILINXbase + 0x01);
-	}
-	return j->pld_slicr.bits.state;
-}
-
-static bool SLIC_SetState(BYTE byState, IXJ *j)
-{
-	bool fRetVal = false;
-
-	if (j->cardtype == QTI_PHONECARD) {
-		if (j->flags.pcmciasct) {
-			switch (byState) {
-			case PLD_SLIC_STATE_TIPOPEN:
-			case PLD_SLIC_STATE_OC:
-				j->pslic.bits.powerdown = 1;
-				j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0;
-				fRetVal = true;
-				break;
-			case PLD_SLIC_STATE_RINGING:
-				if (j->readers || j->writers) {
-					j->pslic.bits.powerdown = 0;
-					j->pslic.bits.ring0 = 1;
-					j->pslic.bits.ring1 = 0;
-					fRetVal = true;
-				}
-				break;
-			case PLD_SLIC_STATE_OHT:	/* On-hook transmit */
-
-			case PLD_SLIC_STATE_STANDBY:
-			case PLD_SLIC_STATE_ACTIVE:
-				if (j->readers || j->writers) {
-					j->pslic.bits.powerdown = 0;
-				} else {
-					j->pslic.bits.powerdown = 1;
-				}
-				j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0;
-				fRetVal = true;
-				break;
-			case PLD_SLIC_STATE_APR:	/* Active polarity reversal */
-
-			case PLD_SLIC_STATE_OHTPR:	/* OHT polarity reversal */
-
-			default:
-				fRetVal = false;
-				break;
-			}
-			j->psccr.bits.dev = 3;
-			j->psccr.bits.rw = 0;
-			outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00);
-			ixj_PCcontrol_wait(j);
-		}
-	} else {
-		/* Set the C1, C2, C3 & B2EN signals. */
-		switch (byState) {
-		case PLD_SLIC_STATE_OC:
-			j->pld_slicw.bits.c1 = 0;
-			j->pld_slicw.bits.c2 = 0;
-			j->pld_slicw.bits.c3 = 0;
-			j->pld_slicw.bits.b2en = 0;
-			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = true;
-			break;
-		case PLD_SLIC_STATE_RINGING:
-			j->pld_slicw.bits.c1 = 1;
-			j->pld_slicw.bits.c2 = 0;
-			j->pld_slicw.bits.c3 = 0;
-			j->pld_slicw.bits.b2en = 1;
-			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = true;
-			break;
-		case PLD_SLIC_STATE_ACTIVE:
-			j->pld_slicw.bits.c1 = 0;
-			j->pld_slicw.bits.c2 = 1;
-			j->pld_slicw.bits.c3 = 0;
-			j->pld_slicw.bits.b2en = 0;
-			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = true;
-			break;
-		case PLD_SLIC_STATE_OHT:	/* On-hook transmit */
-
-			j->pld_slicw.bits.c1 = 1;
-			j->pld_slicw.bits.c2 = 1;
-			j->pld_slicw.bits.c3 = 0;
-			j->pld_slicw.bits.b2en = 0;
-			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = true;
-			break;
-		case PLD_SLIC_STATE_TIPOPEN:
-			j->pld_slicw.bits.c1 = 0;
-			j->pld_slicw.bits.c2 = 0;
-			j->pld_slicw.bits.c3 = 1;
-			j->pld_slicw.bits.b2en = 0;
-			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = true;
-			break;
-		case PLD_SLIC_STATE_STANDBY:
-			j->pld_slicw.bits.c1 = 1;
-			j->pld_slicw.bits.c2 = 0;
-			j->pld_slicw.bits.c3 = 1;
-			j->pld_slicw.bits.b2en = 1;
-			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = true;
-			break;
-		case PLD_SLIC_STATE_APR:	/* Active polarity reversal */
-
-			j->pld_slicw.bits.c1 = 0;
-			j->pld_slicw.bits.c2 = 1;
-			j->pld_slicw.bits.c3 = 1;
-			j->pld_slicw.bits.b2en = 0;
-			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = true;
-			break;
-		case PLD_SLIC_STATE_OHTPR:	/* OHT polarity reversal */
-
-			j->pld_slicw.bits.c1 = 1;
-			j->pld_slicw.bits.c2 = 1;
-			j->pld_slicw.bits.c3 = 1;
-			j->pld_slicw.bits.b2en = 0;
-			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = true;
-			break;
-		default:
-			fRetVal = false;
-			break;
-		}
-	}
-
-	return fRetVal;
-}
-
-static int ixj_wink(IXJ *j)
-{
-	BYTE slicnow;
-
-	slicnow = SLIC_GetState(j);
-
-	j->pots_winkstart = jiffies;
-	SLIC_SetState(PLD_SLIC_STATE_OC, j);
-
-	msleep(jiffies_to_msecs(j->winktime));
-
-	SLIC_SetState(slicnow, j);
-	return 0;
-}
-
-static void ixj_init_timer(IXJ *j)
-{
-	init_timer(&j->timer);
-	j->timer.function = ixj_timeout;
-	j->timer.data = (unsigned long)j;
-}
-
-static void ixj_add_timer(IXJ *j)
-{
-	j->timer.expires = jiffies + (hertz / samplerate);
-	add_timer(&j->timer);
-}
-
-static void ixj_tone_timeout(IXJ *j)
-{
-	IXJ_TONE ti;
-
-	j->tone_state++;
-	if (j->tone_state == 3) {
-		j->tone_state = 0;
-		if (j->cadence_t) {
-			j->tone_cadence_state++;
-			if (j->tone_cadence_state >= j->cadence_t->elements_used) {
-				switch (j->cadence_t->termination) {
-				case PLAY_ONCE:
-					ixj_cpt_stop(j);
-					break;
-				case REPEAT_LAST_ELEMENT:
-					j->tone_cadence_state--;
-					ixj_play_tone(j, j->cadence_t->ce[j->tone_cadence_state].index);
-					break;
-				case REPEAT_ALL:
-					j->tone_cadence_state = 0;
-					if (j->cadence_t->ce[j->tone_cadence_state].freq0) {
-						ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index;
-						ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0;
-						ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0;
-						ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1;
-						ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1;
-						ixj_init_tone(j, &ti);
-					}
-					ixj_set_tone_on(j->cadence_t->ce[0].tone_on_time, j);
-					ixj_set_tone_off(j->cadence_t->ce[0].tone_off_time, j);
-					ixj_play_tone(j, j->cadence_t->ce[0].index);
-					break;
-				}
-			} else {
-				if (j->cadence_t->ce[j->tone_cadence_state].gain0) {
-					ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index;
-					ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0;
-					ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0;
-					ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1;
-					ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1;
-					ixj_init_tone(j, &ti);
-				}
-				ixj_set_tone_on(j->cadence_t->ce[j->tone_cadence_state].tone_on_time, j);
-				ixj_set_tone_off(j->cadence_t->ce[j->tone_cadence_state].tone_off_time, j);
-				ixj_play_tone(j, j->cadence_t->ce[j->tone_cadence_state].index);
-			}
-		}
-	}
-}
-
-static inline void ixj_kill_fasync(IXJ *j, IXJ_SIGEVENT event, int dir)
-{
-	if(j->ixj_signals[event]) {
-		if(ixjdebug & 0x0100)
-			printk("Sending signal for event %d\n", event);
-			/* Send apps notice of change */
-		/* see config.h for macro definition */
-		kill_fasync(&(j->async_queue), j->ixj_signals[event], dir);
-	}
-}
-
-static void ixj_pstn_state(IXJ *j)
-{
-	int var;
-	union XOPXR0 XR0, daaint;
-
-	var = 10;
-
-	XR0.reg = j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.reg;
-	daaint.reg = 0;
-	XR0.bitreg.RMR = j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.bitreg.RMR;
-
-	j->pld_scrr.byte = inb_p(j->XILINXbase);
-	if (j->pld_scrr.bits.daaflag) {
-		daa_int_read(j);
-		if(j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.RING) {
-			if(time_after(jiffies, j->pstn_sleeptil) && !(j->flags.pots_pstn && j->hookstate)) {
-				daaint.bitreg.RING = 1;
-				if(ixjdebug & 0x0008) {
-					printk(KERN_INFO "IXJ DAA Ring Interrupt /dev/phone%d at %ld\n", j->board, jiffies);
-				}
-			} else {
-				daa_set_mode(j, SOP_PU_RESET);
-			}
-		}
-		if(j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.Caller_ID) {
-			daaint.bitreg.Caller_ID = 1;
-			j->pstn_cid_intr = 1;
-			j->pstn_cid_received = jiffies;
-			if(ixjdebug & 0x0008) {
-				printk(KERN_INFO "IXJ DAA Caller_ID Interrupt /dev/phone%d at %ld\n", j->board, jiffies);
-			}
-		}
-		if(j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.Cadence) {
-			daaint.bitreg.Cadence = 1;
-			if(ixjdebug & 0x0008) {
-				printk(KERN_INFO "IXJ DAA Cadence Interrupt /dev/phone%d at %ld\n", j->board, jiffies);
-			}
-		}
-		if(j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK != XR0.bitreg.VDD_OK) {
-			daaint.bitreg.VDD_OK = 1;
-			daaint.bitreg.SI_0 = j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK;
-		}
-	}
-	daa_CR_read(j, 1);
-	if(j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.bitreg.RMR != XR0.bitreg.RMR && time_after(jiffies, j->pstn_sleeptil) && !(j->flags.pots_pstn && j->hookstate)) {
-		daaint.bitreg.RMR = 1;
-		daaint.bitreg.SI_1 = j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.bitreg.RMR;
-		if(ixjdebug & 0x0008) {
-                        printk(KERN_INFO "IXJ DAA RMR /dev/phone%d was %s for %ld\n", j->board, XR0.bitreg.RMR?"on":"off", jiffies - j->pstn_last_rmr);
-		}
-		j->pstn_prev_rmr = j->pstn_last_rmr;
-		j->pstn_last_rmr = jiffies;
-	}
-	switch(j->daa_mode) {
-		case SOP_PU_SLEEP:
-			if (daaint.bitreg.RING) {
-				if (!j->flags.pstn_ringing) {
-					if (j->daa_mode != SOP_PU_RINGING) {
-						j->pstn_ring_int = jiffies;
-						daa_set_mode(j, SOP_PU_RINGING);
-					}
-				}
-			}
-			break;
-		case SOP_PU_RINGING:
-			if (daaint.bitreg.RMR) {
-				if (ixjdebug & 0x0008) {
-					printk(KERN_INFO "IXJ Ring Cadence a state = %d /dev/phone%d at %ld\n", j->cadence_f[4].state, j->board, jiffies);
-				}
-				if (daaint.bitreg.SI_1) {                /* Rising edge of RMR */
-					j->flags.pstn_rmr = 1;
-					j->pstn_ring_start = jiffies;
-					j->pstn_ring_stop = 0;
-					j->ex.bits.pstn_ring = 0;
-					if (j->cadence_f[4].state == 0) {
-						j->cadence_f[4].state = 1;
-						j->cadence_f[4].on1min = jiffies + (long)((j->cadence_f[4].on1 * hertz * (100 - var)) / 10000);
-						j->cadence_f[4].on1dot = jiffies + (long)((j->cadence_f[4].on1 * hertz * (100)) / 10000);
-						j->cadence_f[4].on1max = jiffies + (long)((j->cadence_f[4].on1 * hertz * (100 + var)) / 10000);
-					} else if (j->cadence_f[4].state == 2) {
-						if((time_after(jiffies, j->cadence_f[4].off1min) &&
-						    time_before(jiffies, j->cadence_f[4].off1max))) {
-							if (j->cadence_f[4].on2) {
-								j->cadence_f[4].state = 3;
-								j->cadence_f[4].on2min = jiffies + (long)((j->cadence_f[4].on2 * (hertz * (100 - var)) / 10000));
-								j->cadence_f[4].on2dot = jiffies + (long)((j->cadence_f[4].on2 * (hertz * (100)) / 10000));
-								j->cadence_f[4].on2max = jiffies + (long)((j->cadence_f[4].on2 * (hertz * (100 + var)) / 10000));
-							} else {
-								j->cadence_f[4].state = 7;
-							}
-						} else {
-							if (ixjdebug & 0x0008) {
-								printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n",
-										j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr,
-										j->cadence_f[4].off1);
-							}
-							j->cadence_f[4].state = 0;
-						}
-					} else if (j->cadence_f[4].state == 4) {
-						if((time_after(jiffies, j->cadence_f[4].off2min) &&
-						    time_before(jiffies, j->cadence_f[4].off2max))) {
-							if (j->cadence_f[4].on3) {
-								j->cadence_f[4].state = 5;
-								j->cadence_f[4].on3min = jiffies + (long)((j->cadence_f[4].on3 * (hertz * (100 - var)) / 10000));
-								j->cadence_f[4].on3dot = jiffies + (long)((j->cadence_f[4].on3 * (hertz * (100)) / 10000));
-								j->cadence_f[4].on3max = jiffies + (long)((j->cadence_f[4].on3 * (hertz * (100 + var)) / 10000));
-							} else {
-								j->cadence_f[4].state = 7;
-							}
-						} else {
-							if (ixjdebug & 0x0008) {
-								printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n",
-										j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr,
-										j->cadence_f[4].off2);
-							}
-							j->cadence_f[4].state = 0;
-						}
-					} else if (j->cadence_f[4].state == 6) {
-						if((time_after(jiffies, j->cadence_f[4].off3min) &&
-						    time_before(jiffies, j->cadence_f[4].off3max))) {
-							j->cadence_f[4].state = 7;
-						} else {
-							if (ixjdebug & 0x0008) {
-								printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n",
-										j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr,
-										j->cadence_f[4].off3);
-							}
-							j->cadence_f[4].state = 0;
-						}
-					} else {
-						j->cadence_f[4].state = 0;
-					}
-				} else {                                /* Falling edge of RMR */
-					j->pstn_ring_start = 0;
-					j->pstn_ring_stop = jiffies;
-					if (j->cadence_f[4].state == 1) {
-						if(!j->cadence_f[4].on1) {
-							j->cadence_f[4].state = 7;
-						} else if((time_after(jiffies, j->cadence_f[4].on1min) &&
-					          time_before(jiffies, j->cadence_f[4].on1max))) {
-							if (j->cadence_f[4].off1) {
-								j->cadence_f[4].state = 2;
-								j->cadence_f[4].off1min = jiffies + (long)((j->cadence_f[4].off1 * (hertz * (100 - var)) / 10000));
-								j->cadence_f[4].off1dot = jiffies + (long)((j->cadence_f[4].off1 * (hertz * (100)) / 10000));
-								j->cadence_f[4].off1max = jiffies + (long)((j->cadence_f[4].off1 * (hertz * (100 + var)) / 10000));
-							} else {
-								j->cadence_f[4].state = 7;
-							}
-						} else {
-							if (ixjdebug & 0x0008) {
-								printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n",
-										j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr,
-										j->cadence_f[4].on1);
-							}
-							j->cadence_f[4].state = 0;
-						}
-					} else if (j->cadence_f[4].state == 3) {
-						if((time_after(jiffies, j->cadence_f[4].on2min) &&
-						    time_before(jiffies, j->cadence_f[4].on2max))) {
-							if (j->cadence_f[4].off2) {
-								j->cadence_f[4].state = 4;
-								j->cadence_f[4].off2min = jiffies + (long)((j->cadence_f[4].off2 * (hertz * (100 - var)) / 10000));
-								j->cadence_f[4].off2dot = jiffies + (long)((j->cadence_f[4].off2 * (hertz * (100)) / 10000));
-								j->cadence_f[4].off2max = jiffies + (long)((j->cadence_f[4].off2 * (hertz * (100 + var)) / 10000));
-							} else {
-								j->cadence_f[4].state = 7;
-							}
-						} else {
-							if (ixjdebug & 0x0008) {
-								printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n",
-										j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr,
-										j->cadence_f[4].on2);
-							}
-							j->cadence_f[4].state = 0;
-						}
-					} else if (j->cadence_f[4].state == 5) {
-						if((time_after(jiffies, j->cadence_f[4].on3min) &&
-						    time_before(jiffies, j->cadence_f[4].on3max))) {
-							if (j->cadence_f[4].off3) {
-								j->cadence_f[4].state = 6;
-								j->cadence_f[4].off3min = jiffies + (long)((j->cadence_f[4].off3 * (hertz * (100 - var)) / 10000));
-								j->cadence_f[4].off3dot = jiffies + (long)((j->cadence_f[4].off3 * (hertz * (100)) / 10000));
-								j->cadence_f[4].off3max = jiffies + (long)((j->cadence_f[4].off3 * (hertz * (100 + var)) / 10000));
-							} else {
-								j->cadence_f[4].state = 7;
-							}
-						} else {
-							j->cadence_f[4].state = 0;
-						}
-					} else {
-						if (ixjdebug & 0x0008) {
-							printk(KERN_INFO "IXJ Ring Cadence fail state = %d /dev/phone%d at %ld should be %d\n",
-									j->cadence_f[4].state, j->board, jiffies - j->pstn_prev_rmr,
-									j->cadence_f[4].on3);
-						}
-						j->cadence_f[4].state = 0;
-					}
-				}
-				if (ixjdebug & 0x0010) {
-					printk(KERN_INFO "IXJ Ring Cadence b state = %d /dev/phone%d at %ld\n", j->cadence_f[4].state, j->board, jiffies);
-				}
-				if (ixjdebug & 0x0010) {
-					switch(j->cadence_f[4].state) {
-						case 1:
-							printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board,
-						j->cadence_f[4].on1, j->cadence_f[4].on1min, j->cadence_f[4].on1dot, j->cadence_f[4].on1max);
-							break;
-						case 2:
-							printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board,
-						j->cadence_f[4].off1, j->cadence_f[4].off1min, j->cadence_f[4].off1dot, j->cadence_f[4].off1max);
-							break;
-						case 3:
-							printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board,
-						j->cadence_f[4].on2, j->cadence_f[4].on2min, j->cadence_f[4].on2dot, j->cadence_f[4].on2max);
-							break;
-						case 4:
-							printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board,
-						j->cadence_f[4].off2, j->cadence_f[4].off2min, j->cadence_f[4].off2dot, j->cadence_f[4].off2max);
-							break;
-						case 5:
-							printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board,
-						j->cadence_f[4].on3, j->cadence_f[4].on3min, j->cadence_f[4].on3dot, j->cadence_f[4].on3max);
-							break;
-						case 6:
-							printk(KERN_INFO "IXJ /dev/phone%d Next Ring Cadence state at %u min %ld - %ld - max %ld\n", j->board,
-						j->cadence_f[4].off3, j->cadence_f[4].off3min, j->cadence_f[4].off3dot, j->cadence_f[4].off3max);
-							break;
-					}
-				}
-			}
-			if (j->cadence_f[4].state == 7) {
-				j->cadence_f[4].state = 0;
-				j->pstn_ring_stop = jiffies;
-				j->ex.bits.pstn_ring = 1;
-				ixj_kill_fasync(j, SIG_PSTN_RING, POLL_IN);
-				if(ixjdebug & 0x0008) {
-					printk(KERN_INFO "IXJ Ring int set /dev/phone%d at %ld\n", j->board, jiffies);
-				}
-			}
-			if((j->pstn_ring_int != 0 && time_after(jiffies, j->pstn_ring_int + (hertz * 5)) && !j->flags.pstn_rmr) ||
-			   (j->pstn_ring_stop != 0 && time_after(jiffies, j->pstn_ring_stop + (hertz * 5)))) {
-				if(ixjdebug & 0x0008) {
-					printk("IXJ DAA no ring in 5 seconds /dev/phone%d at %ld\n", j->board, jiffies);
-					printk("IXJ DAA pstn ring int /dev/phone%d at %ld\n", j->board, j->pstn_ring_int);
-					printk("IXJ DAA pstn ring stop /dev/phone%d at %ld\n", j->board, j->pstn_ring_stop);
-				}
-				j->pstn_ring_stop = j->pstn_ring_int = 0;
-				daa_set_mode(j, SOP_PU_SLEEP);
-			}
-			outb_p(j->pld_scrw.byte, j->XILINXbase);
-			if (j->pstn_cid_intr && time_after(jiffies, j->pstn_cid_received + hertz)) {
-				ixj_daa_cid_read(j);
-				j->ex.bits.caller_id = 1;
-				ixj_kill_fasync(j, SIG_CALLER_ID, POLL_IN);
-				j->pstn_cid_intr = 0;
-			}
-			if (daaint.bitreg.Cadence) {
-				if(ixjdebug & 0x0008) {
-					printk("IXJ DAA Cadence interrupt going to sleep /dev/phone%d\n", j->board);
-				}
-				daa_set_mode(j, SOP_PU_SLEEP);
-				j->ex.bits.pstn_ring = 0;
-			}
-			break;
-		case SOP_PU_CONVERSATION:
-			if (daaint.bitreg.VDD_OK) {
-				if(!daaint.bitreg.SI_0) {
-					if (!j->pstn_winkstart) {
-						if(ixjdebug & 0x0008) {
-							printk("IXJ DAA possible wink /dev/phone%d %ld\n", j->board, jiffies);
-						}
-						j->pstn_winkstart = jiffies;
-					}
-				} else {
-					if (j->pstn_winkstart) {
-						if(ixjdebug & 0x0008) {
-							printk("IXJ DAA possible wink end /dev/phone%d %ld\n", j->board, jiffies);
-						}
-						j->pstn_winkstart = 0;
-					}
-				}
-			}
-			if (j->pstn_winkstart && time_after(jiffies, j->pstn_winkstart + ((hertz * j->winktime) / 1000))) {
-				if(ixjdebug & 0x0008) {
-					printk("IXJ DAA wink detected going to sleep /dev/phone%d %ld\n", j->board, jiffies);
-				}
-				daa_set_mode(j, SOP_PU_SLEEP);
-				j->pstn_winkstart = 0;
-				j->ex.bits.pstn_wink = 1;
-				ixj_kill_fasync(j, SIG_PSTN_WINK, POLL_IN);
-			}
-			break;
-	}
-}
-
-static void ixj_timeout(unsigned long ptr)
-{
-	int board;
-	unsigned long jifon;
-	IXJ *j = (IXJ *)ptr;
-	board = j->board;
-
-	if (j->DSPbase && atomic_read(&j->DSPWrite) == 0 && test_and_set_bit(board, (void *)&j->busyflags) == 0) {
-		ixj_perfmon(j->timerchecks);
-		j->hookstate = ixj_hookstate(j);
-		if (j->tone_state) {
-			if (!(j->hookstate)) {
-				ixj_cpt_stop(j);
-				if (j->m_hook) {
-					j->m_hook = 0;
-					j->ex.bits.hookstate = 1;
-					ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN);
-				}
-				clear_bit(board, &j->busyflags);
-				ixj_add_timer(j);
-				return;
-			}
-			if (j->tone_state == 1)
-				jifon = ((hertz * j->tone_on_time) * 25 / 100000);
-			else
-				jifon = ((hertz * j->tone_on_time) * 25 / 100000) + ((hertz * j->tone_off_time) * 25 / 100000);
-			if (time_before(jiffies, j->tone_start_jif + jifon)) {
-				if (j->tone_state == 1) {
-					ixj_play_tone(j, j->tone_index);
-					if (j->dsp.low == 0x20) {
-						clear_bit(board, &j->busyflags);
-						ixj_add_timer(j);
-						return;
-					}
-				} else {
-					ixj_play_tone(j, 0);
-					if (j->dsp.low == 0x20) {
-						clear_bit(board, &j->busyflags);
-						ixj_add_timer(j);
-						return;
-					}
-				}
-			} else {
-				ixj_tone_timeout(j);
-				if (j->flags.dialtone) {
-					ixj_dialtone(j);
-				}
-				if (j->flags.busytone) {
-					ixj_busytone(j);
-					if (j->dsp.low == 0x20) {
-						clear_bit(board, &j->busyflags);
-						ixj_add_timer(j);
-						return;
-					}
-				}
-				if (j->flags.ringback) {
-					ixj_ringback(j);
-					if (j->dsp.low == 0x20) {
-						clear_bit(board, &j->busyflags);
-						ixj_add_timer(j);
-						return;
-					}
-				}
-				if (!j->tone_state) {
-					ixj_cpt_stop(j);
-				}
-			}
-		}
-		if (!(j->tone_state && j->dsp.low == 0x20)) {
-			if (IsRxReady(j)) {
-				ixj_read_frame(j);
-			}
-			if (IsTxReady(j)) {
-				ixj_write_frame(j);
-			}
-		}
-		if (j->flags.cringing) {
-			if (j->hookstate & 1) {
-				j->flags.cringing = 0;
-				ixj_ring_off(j);
-			} else if(j->cadence_f[5].enable && ((!j->cadence_f[5].en_filter) || (j->cadence_f[5].en_filter && j->flags.firstring))) {
-				switch(j->cadence_f[5].state) {
-					case 0:
-						j->cadence_f[5].on1dot = jiffies + (long)((j->cadence_f[5].on1 * (hertz * 100) / 10000));
-						if (time_before(jiffies, j->cadence_f[5].on1dot)) {
-							if(ixjdebug & 0x0004) {
-								printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies);
-							}
-							ixj_ring_on(j);
-						}
-						j->cadence_f[5].state = 1;
-						break;
-					case 1:
-						if (time_after(jiffies, j->cadence_f[5].on1dot)) {
-							j->cadence_f[5].off1dot = jiffies + (long)((j->cadence_f[5].off1 * (hertz * 100) / 10000));
-							if(ixjdebug & 0x0004) {
-								printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies);
-							}
-							ixj_ring_off(j);
-							j->cadence_f[5].state = 2;
-						}
-						break;
-					case 2:
-						if (time_after(jiffies, j->cadence_f[5].off1dot)) {
-							if(ixjdebug & 0x0004) {
-								printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies);
-							}
-							ixj_ring_on(j);
-							if (j->cadence_f[5].on2) {
-								j->cadence_f[5].on2dot = jiffies + (long)((j->cadence_f[5].on2 * (hertz * 100) / 10000));
-								j->cadence_f[5].state = 3;
-							} else {
-								j->cadence_f[5].state = 7;
-							}
-						}
-						break;
-					case 3:
-						if (time_after(jiffies, j->cadence_f[5].on2dot)) {
-							if(ixjdebug & 0x0004) {
-								printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies);
-							}
-							ixj_ring_off(j);
-							if (j->cadence_f[5].off2) {
-								j->cadence_f[5].off2dot = jiffies + (long)((j->cadence_f[5].off2 * (hertz * 100) / 10000));
-								j->cadence_f[5].state = 4;
-							} else {
-								j->cadence_f[5].state = 7;
-							}
-						}
-						break;
-					case 4:
-						if (time_after(jiffies, j->cadence_f[5].off2dot)) {
-							if(ixjdebug & 0x0004) {
-								printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies);
-							}
-							ixj_ring_on(j);
-							if (j->cadence_f[5].on3) {
-								j->cadence_f[5].on3dot = jiffies + (long)((j->cadence_f[5].on3 * (hertz * 100) / 10000));
-								j->cadence_f[5].state = 5;
-							} else {
-								j->cadence_f[5].state = 7;
-							}
-						}
-						break;
-					case 5:
-						if (time_after(jiffies, j->cadence_f[5].on3dot)) {
-							if(ixjdebug & 0x0004) {
-								printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies);
-							}
-							ixj_ring_off(j);
-							if (j->cadence_f[5].off3) {
-								j->cadence_f[5].off3dot = jiffies + (long)((j->cadence_f[5].off3 * (hertz * 100) / 10000));
-								j->cadence_f[5].state = 6;
-							} else {
-								j->cadence_f[5].state = 7;
-							}
-						}
-						break;
-					case 6:
-						if (time_after(jiffies, j->cadence_f[5].off3dot)) {
-							if(ixjdebug & 0x0004) {
-								printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies);
-							}
-							j->cadence_f[5].state = 7;
-						}
-						break;
-					case 7:
-						if(ixjdebug & 0x0004) {
-							printk("Ringing cadence state = %d - %ld\n", j->cadence_f[5].state, jiffies);
-						}
-						j->flags.cidring = 1;
-						j->cadence_f[5].state = 0;
-						break;
-				}
-				if (j->flags.cidring && !j->flags.cidsent) {
-					j->flags.cidsent = 1;
-					if(j->fskdcnt) {
-						SLIC_SetState(PLD_SLIC_STATE_OHT, j);
-						ixj_pre_cid(j);
-					}
-					j->flags.cidring = 0;
-				}
-				clear_bit(board, &j->busyflags);
-				ixj_add_timer(j);
-				return;
-			} else {
-				if (time_after(jiffies, j->ring_cadence_jif + (hertz / 2))) {
-					if (j->flags.cidring && !j->flags.cidsent) {
-						j->flags.cidsent = 1;
-						if(j->fskdcnt) {
-							SLIC_SetState(PLD_SLIC_STATE_OHT, j);
-							ixj_pre_cid(j);
-						}
-						j->flags.cidring = 0;
-					}
-					j->ring_cadence_t--;
-					if (j->ring_cadence_t == -1)
-						j->ring_cadence_t = 15;
-					j->ring_cadence_jif = jiffies;
-
-					if (j->ring_cadence & 1 << j->ring_cadence_t) {
-						if(j->flags.cidsent && j->cadence_f[5].en_filter)
-							j->flags.firstring = 1;
-						else
-							ixj_ring_on(j);
-					} else {
-						ixj_ring_off(j);
-						if(!j->flags.cidsent)
-							j->flags.cidring = 1;
-					}
-				}
-				clear_bit(board, &j->busyflags);
-				ixj_add_timer(j);
-				return;
-			}
-		}
-		if (!j->flags.ringing) {
-			if (j->hookstate) { /* & 1) { */
-				if (j->dsp.low != 0x20 &&
-				    SLIC_GetState(j) != PLD_SLIC_STATE_ACTIVE) {
-					SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j);
-				}
-				LineMonitor(j);
-				read_filters(j);
-				ixj_WriteDSPCommand(0x511B, j);
-				j->proc_load = j->ssr.high << 8 | j->ssr.low;
-				if (!j->m_hook && (j->hookstate & 1)) {
-					j->m_hook = j->ex.bits.hookstate = 1;
-					ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN);
-				}
-			} else {
-				if (j->ex.bits.dtmf_ready) {
-					j->dtmf_wp = j->dtmf_rp = j->ex.bits.dtmf_ready = 0;
-				}
-				if (j->m_hook) {
-					j->m_hook = 0;
-					j->ex.bits.hookstate = 1;
-					ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN);
-				}
-			}
-		}
-		if (j->cardtype == QTI_LINEJACK && !j->flags.pstncheck && j->flags.pstn_present) {
-			ixj_pstn_state(j);
-		}
-		if (j->ex.bytes) {
-			wake_up_interruptible(&j->poll_q);	/* Wake any blocked selects */
-		}
-		clear_bit(board, &j->busyflags);
-	}
-	ixj_add_timer(j);
-}
-
-static int ixj_status_wait(IXJ *j)
-{
-	unsigned long jif;
-
-	jif = jiffies + ((60 * hertz) / 100);
-	while (!IsStatusReady(j)) {
-		ixj_perfmon(j->statuswait);
-		if (time_after(jiffies, jif)) {
-			ixj_perfmon(j->statuswaitfail);
-			return -1;
-		}
-	}
-	return 0;
-}
-
-static int ixj_PCcontrol_wait(IXJ *j)
-{
-	unsigned long jif;
-
-	jif = jiffies + ((60 * hertz) / 100);
-	while (!IsPCControlReady(j)) {
-		ixj_perfmon(j->pcontrolwait);
-		if (time_after(jiffies, jif)) {
-			ixj_perfmon(j->pcontrolwaitfail);
-			return -1;
-		}
-	}
-	return 0;
-}
-
-static int ixj_WriteDSPCommand(unsigned short cmd, IXJ *j)
-{
-	BYTES bytes;
-	unsigned long jif;
-
-	atomic_inc(&j->DSPWrite);
-	if(atomic_read(&j->DSPWrite) > 1) {
-		printk("IXJ %d DSP write overlap attempting command 0x%4.4x\n", j->board, cmd);
-		return -1;
-	}
-	bytes.high = (cmd & 0xFF00) >> 8;
-	bytes.low = cmd & 0x00FF;
-	jif = jiffies + ((60 * hertz) / 100);
-	while (!IsControlReady(j)) {
-		ixj_perfmon(j->iscontrolready);
-		if (time_after(jiffies, jif)) {
-			ixj_perfmon(j->iscontrolreadyfail);
-			atomic_dec(&j->DSPWrite);
-			if(atomic_read(&j->DSPWrite) > 0) {
-				printk("IXJ %d DSP overlaped command 0x%4.4x during control ready failure.\n", j->board, cmd);
-				while(atomic_read(&j->DSPWrite) > 0) {
-					atomic_dec(&j->DSPWrite);
-				}
-			}
-			return -1;
-		}
-	}
-	outb(bytes.low, j->DSPbase + 6);
-	outb(bytes.high, j->DSPbase + 7);
-
-	if (ixj_status_wait(j)) {
-		j->ssr.low = 0xFF;
-		j->ssr.high = 0xFF;
-		atomic_dec(&j->DSPWrite);
-		if(atomic_read(&j->DSPWrite) > 0) {
-			printk("IXJ %d DSP overlaped command 0x%4.4x during status wait failure.\n", j->board, cmd);
-			while(atomic_read(&j->DSPWrite) > 0) {
-				atomic_dec(&j->DSPWrite);
-			}
-		}
-		return -1;
-	}
-/* Read Software Status Register */
-	j->ssr.low = inb_p(j->DSPbase + 2);
-	j->ssr.high = inb_p(j->DSPbase + 3);
-	atomic_dec(&j->DSPWrite);
-	if(atomic_read(&j->DSPWrite) > 0) {
-		printk("IXJ %d DSP overlaped command 0x%4.4x\n", j->board, cmd);
-		while(atomic_read(&j->DSPWrite) > 0) {
-			atomic_dec(&j->DSPWrite);
-		}
-	}
-	return 0;
-}
-
-/***************************************************************************
-*
-*  General Purpose IO Register read routine
-*
-***************************************************************************/
-static inline int ixj_gpio_read(IXJ *j)
-{
-	if (ixj_WriteDSPCommand(0x5143, j))
-		return -1;
-
-	j->gpio.bytes.low = j->ssr.low;
-	j->gpio.bytes.high = j->ssr.high;
-
-	return 0;
-}
-
-static inline void LED_SetState(int state, IXJ *j)
-{
-	if (j->cardtype == QTI_LINEJACK) {
-		j->pld_scrw.bits.led1 = state & 0x1 ? 1 : 0;
-		j->pld_scrw.bits.led2 = state & 0x2 ? 1 : 0;
-		j->pld_scrw.bits.led3 = state & 0x4 ? 1 : 0;
-		j->pld_scrw.bits.led4 = state & 0x8 ? 1 : 0;
-
-		outb(j->pld_scrw.byte, j->XILINXbase);
-	}
-}
-
-/*********************************************************************
-*  GPIO Pins are configured as follows on the Quicknet Internet
-*  PhoneJACK Telephony Cards
-*
-* POTS Select        GPIO_6=0 GPIO_7=0
-* Mic/Speaker Select GPIO_6=0 GPIO_7=1
-* Handset Select     GPIO_6=1 GPIO_7=0
-*
-* SLIC Active        GPIO_1=0 GPIO_2=1 GPIO_5=0
-* SLIC Ringing       GPIO_1=1 GPIO_2=1 GPIO_5=0
-* SLIC Open Circuit  GPIO_1=0 GPIO_2=0 GPIO_5=0
-*
-* Hook Switch changes reported on GPIO_3
-*********************************************************************/
-static int ixj_set_port(IXJ *j, int arg)
-{
-	if (j->cardtype == QTI_PHONEJACK_LITE) {
-		if (arg != PORT_POTS)
-			return 10;
-		else
-			return 0;
-	}
-	switch (arg) {
-	case PORT_POTS:
-		j->port = PORT_POTS;
-		switch (j->cardtype) {
-		case QTI_PHONECARD:
-			if (j->flags.pcmciasct == 1)
-				SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j);
-			else
-				return 11;
-			break;
-		case QTI_PHONEJACK_PCI:
-			j->pld_slicw.pcib.mic = 0;
-			j->pld_slicw.pcib.spk = 0;
-			outb(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			break;
-		case QTI_LINEJACK:
-			ixj_set_pots(j, 0);			/* Disconnect POTS/PSTN relay */
-			if (ixj_WriteDSPCommand(0xC528, j))		/* Write CODEC config to
-									   Software Control Register */
-				return 2;
-			j->pld_scrw.bits.daafsyncen = 0;	/* Turn off DAA Frame Sync */
-
-			outb(j->pld_scrw.byte, j->XILINXbase);
-			j->pld_clock.byte = 0;
-			outb(j->pld_clock.byte, j->XILINXbase + 0x04);
-			j->pld_slicw.bits.rly1 = 1;
-			j->pld_slicw.bits.spken = 0;
-			outb(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			ixj_mixer(0x1200, j);	/* Turn Off MIC switch on mixer left */
-			ixj_mixer(0x1401, j);	/* Turn On Mono1 switch on mixer left */
-			ixj_mixer(0x1300, j);       /* Turn Off MIC switch on mixer right */
-			ixj_mixer(0x1501, j);       /* Turn On Mono1 switch on mixer right */
-			ixj_mixer(0x0E80, j);	/*Mic mute */
-			ixj_mixer(0x0F00, j);	/* Set mono out (SLIC) to 0dB */
-			ixj_mixer(0x0080, j);	/* Mute Master Left volume */
-			ixj_mixer(0x0180, j);	/* Mute Master Right volume */
-			SLIC_SetState(PLD_SLIC_STATE_STANDBY, j);
-/*			SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); */
-			break;
-		case QTI_PHONEJACK:
-			j->gpio.bytes.high = 0x0B;
-			j->gpio.bits.gpio6 = 0;
-			j->gpio.bits.gpio7 = 0;
-			ixj_WriteDSPCommand(j->gpio.word, j);
-			break;
-		}
-		break;
-	case PORT_PSTN:
-		if (j->cardtype == QTI_LINEJACK) {
-			ixj_WriteDSPCommand(0xC534, j);	/* Write CODEC config to Software Control Register */
-
-			j->pld_slicw.bits.rly3 = 0;
-			j->pld_slicw.bits.rly1 = 1;
-			j->pld_slicw.bits.spken = 0;
-			outb(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			j->port = PORT_PSTN;
-		} else {
-			return 4;
-		}
-		break;
-	case PORT_SPEAKER:
-		j->port = PORT_SPEAKER;
-		switch (j->cardtype) {
-		case QTI_PHONECARD:
-			if (j->flags.pcmciasct) {
-				SLIC_SetState(PLD_SLIC_STATE_OC, j);
-			}
-			break;
-		case QTI_PHONEJACK_PCI:
-			j->pld_slicw.pcib.mic = 1;
-			j->pld_slicw.pcib.spk = 1;
-			outb(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			break;
-		case QTI_LINEJACK:
-			ixj_set_pots(j, 0);			/* Disconnect POTS/PSTN relay */
-			if (ixj_WriteDSPCommand(0xC528, j))		/* Write CODEC config to
-									   Software Control Register */
-				return 2;
-			j->pld_scrw.bits.daafsyncen = 0;	/* Turn off DAA Frame Sync */
-
-			outb(j->pld_scrw.byte, j->XILINXbase);
-			j->pld_clock.byte = 0;
-			outb(j->pld_clock.byte, j->XILINXbase + 0x04);
-			j->pld_slicw.bits.rly1 = 1;
-			j->pld_slicw.bits.spken = 1;
-			outb(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			ixj_mixer(0x1201, j);	/* Turn On MIC switch on mixer left */
-			ixj_mixer(0x1400, j);	/* Turn Off Mono1 switch on mixer left */
-			ixj_mixer(0x1301, j);       /* Turn On MIC switch on mixer right */
-			ixj_mixer(0x1500, j);       /* Turn Off Mono1 switch on mixer right */
-			ixj_mixer(0x0E06, j);	/*Mic un-mute 0dB */
-			ixj_mixer(0x0F80, j);	/* Mute mono out (SLIC) */
-			ixj_mixer(0x0000, j);	/* Set Master Left volume to 0dB */
-			ixj_mixer(0x0100, j);	/* Set Master Right volume to 0dB */
-			break;
-		case QTI_PHONEJACK:
-			j->gpio.bytes.high = 0x0B;
-			j->gpio.bits.gpio6 = 0;
-			j->gpio.bits.gpio7 = 1;
-			ixj_WriteDSPCommand(j->gpio.word, j);
-			break;
-		}
-		break;
-	case PORT_HANDSET:
-		if (j->cardtype != QTI_PHONEJACK) {
-			return 5;
-		} else {
-			j->gpio.bytes.high = 0x0B;
-			j->gpio.bits.gpio6 = 1;
-			j->gpio.bits.gpio7 = 0;
-			ixj_WriteDSPCommand(j->gpio.word, j);
-			j->port = PORT_HANDSET;
-		}
-		break;
-	default:
-		return 6;
-		break;
-	}
-	return 0;
-}
-
-static int ixj_set_pots(IXJ *j, int arg)
-{
-	if (j->cardtype == QTI_LINEJACK) {
-		if (arg) {
-			if (j->port == PORT_PSTN) {
-				j->pld_slicw.bits.rly1 = 0;
-				outb(j->pld_slicw.byte, j->XILINXbase + 0x01);
-				j->flags.pots_pstn = 1;
-				return 1;
-			} else {
-				j->flags.pots_pstn = 0;
-				return 0;
-			}
-		} else {
-			j->pld_slicw.bits.rly1 = 1;
-			outb(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			j->flags.pots_pstn = 0;
-			return 1;
-		}
-	} else {
-		return 0;
-	}
-}
-
-static void ixj_ring_on(IXJ *j)
-{
-	if (j->dsp.low == 0x20)	/* Internet PhoneJACK */
-	 {
-		if (ixjdebug & 0x0004)
-			printk(KERN_INFO "IXJ Ring On /dev/phone%d\n", 	j->board);
-
-		j->gpio.bytes.high = 0x0B;
-		j->gpio.bytes.low = 0x00;
-		j->gpio.bits.gpio1 = 1;
-		j->gpio.bits.gpio2 = 1;
-		j->gpio.bits.gpio5 = 0;
-		ixj_WriteDSPCommand(j->gpio.word, j);	/* send the ring signal */
-	} else			/* Internet LineJACK, Internet PhoneJACK Lite or Internet PhoneJACK PCI */
-	{
-		if (ixjdebug & 0x0004)
-			printk(KERN_INFO "IXJ Ring On /dev/phone%d\n", j->board);
-
-		SLIC_SetState(PLD_SLIC_STATE_RINGING, j);
-	}
-}
-
-static int ixj_siadc(IXJ *j, int val)
-{
-	if(j->cardtype == QTI_PHONECARD){
-		if(j->flags.pcmciascp){
-			if(val == -1)
-				return j->siadc.bits.rxg;
-
-			if(val < 0 || val > 0x1F)
-				return -1;
-
-			j->siadc.bits.hom = 0;				/* Handset Out Mute */
-			j->siadc.bits.lom = 0;				/* Line Out Mute */
-			j->siadc.bits.rxg = val;			/*(0xC000 - 0x41C8) / 0x4EF;    RX PGA Gain */
-			j->psccr.bits.addr = 6;				/* R/W Smart Cable Register Address */
-			j->psccr.bits.rw = 0;				/* Read / Write flag */
-			j->psccr.bits.dev = 0;
-			outb(j->siadc.byte, j->XILINXbase + 0x00);
-			outb(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(j);
-			return j->siadc.bits.rxg;
-		}
-	}
-	return -1;
-}
-
-static int ixj_sidac(IXJ *j, int val)
-{
-	if(j->cardtype == QTI_PHONECARD){
-		if(j->flags.pcmciascp){
-			if(val == -1)
-				return j->sidac.bits.txg;
-
-			if(val < 0 || val > 0x1F)
-				return -1;
-
-			j->sidac.bits.srm = 1;				/* Speaker Right Mute */
-			j->sidac.bits.slm = 1;				/* Speaker Left Mute */
-			j->sidac.bits.txg = val;			/* (0xC000 - 0x45E4) / 0x5D3;	 TX PGA Gain */
-			j->psccr.bits.addr = 7;				/* R/W Smart Cable Register Address */
-			j->psccr.bits.rw = 0;				/* Read / Write flag */
-			j->psccr.bits.dev = 0;
-			outb(j->sidac.byte, j->XILINXbase + 0x00);
-			outb(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(j);
-			return j->sidac.bits.txg;
-		}
-	}
-	return -1;
-}
-
-static int ixj_pcmcia_cable_check(IXJ *j)
-{
-	j->pccr1.byte = inb_p(j->XILINXbase + 0x03);
-	if (!j->flags.pcmciastate) {
-		j->pccr2.byte = inb_p(j->XILINXbase + 0x02);
-		if (j->pccr1.bits.drf || j->pccr2.bits.rstc) {
-			j->flags.pcmciastate = 4;
-			return 0;
-		}
-		if (j->pccr1.bits.ed) {
-			j->pccr1.bits.ed = 0;
-			j->psccr.bits.dev = 3;
-			j->psccr.bits.rw = 1;
-			outw_p(j->psccr.byte << 8, j->XILINXbase + 0x00);
-			ixj_PCcontrol_wait(j);
-			j->pslic.byte = inw_p(j->XILINXbase + 0x00) & 0xFF;
-			j->pslic.bits.led2 = j->pslic.bits.det ? 1 : 0;
-			j->psccr.bits.dev = 3;
-			j->psccr.bits.rw = 0;
-			outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00);
-			ixj_PCcontrol_wait(j);
-			return j->pslic.bits.led2 ? 1 : 0;
-		} else if (j->flags.pcmciasct) {
-			return j->r_hook;
-		} else {
-			return 1;
-		}
-	} else if (j->flags.pcmciastate == 4) {
-		if (!j->pccr1.bits.drf) {
-			j->flags.pcmciastate = 3;
-		}
-		return 0;
-	} else if (j->flags.pcmciastate == 3) {
-		j->pccr2.bits.pwr = 0;
-		j->pccr2.bits.rstc = 1;
-		outb(j->pccr2.byte, j->XILINXbase + 0x02);
-		j->checkwait = jiffies + (hertz * 2);
-		j->flags.incheck = 1;
-		j->flags.pcmciastate = 2;
-		return 0;
-	} else if (j->flags.pcmciastate == 2) {
-		if (j->flags.incheck) {
-			if (time_before(jiffies, j->checkwait)) {
-				return 0;
-			} else {
-				j->flags.incheck = 0;
-			}
-		}
-		j->pccr2.bits.pwr = 0;
-		j->pccr2.bits.rstc = 0;
-		outb_p(j->pccr2.byte, j->XILINXbase + 0x02);
-		j->flags.pcmciastate = 1;
-		return 0;
-	} else if (j->flags.pcmciastate == 1) {
-		j->flags.pcmciastate = 0;
-		if (!j->pccr1.bits.drf) {
-			j->psccr.bits.dev = 3;
-			j->psccr.bits.rw = 1;
-			outb_p(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(j);
-			j->flags.pcmciascp = 1;		/* Set Cable Present Flag */
-
-			j->flags.pcmciasct = (inw_p(j->XILINXbase + 0x00) >> 8) & 0x03;		/* Get Cable Type */
-
-			if (j->flags.pcmciasct == 3) {
-				j->flags.pcmciastate = 4;
-				return 0;
-			} else if (j->flags.pcmciasct == 0) {
-				j->pccr2.bits.pwr = 1;
-				j->pccr2.bits.rstc = 0;
-				outb_p(j->pccr2.byte, j->XILINXbase + 0x02);
-				j->port = PORT_SPEAKER;
-			} else {
-				j->port = PORT_POTS;
-			}
-			j->sic1.bits.cpd = 0;				/* Chip Power Down */
-			j->sic1.bits.mpd = 0;				/* MIC Bias Power Down */
-			j->sic1.bits.hpd = 0;				/* Handset Bias Power Down */
-			j->sic1.bits.lpd = 0;				/* Line Bias Power Down */
-			j->sic1.bits.spd = 1;				/* Speaker Drive Power Down */
-			j->psccr.bits.addr = 1;				/* R/W Smart Cable Register Address */
-			j->psccr.bits.rw = 0;				/* Read / Write flag */
-			j->psccr.bits.dev = 0;
-			outb(j->sic1.byte, j->XILINXbase + 0x00);
-			outb(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(j);
-
-			j->sic2.bits.al = 0;				/* Analog Loopback DAC analog -> ADC analog */
-			j->sic2.bits.dl2 = 0;				/* Digital Loopback DAC -> ADC one bit */
-			j->sic2.bits.dl1 = 0;				/* Digital Loopback ADC -> DAC one bit */
-			j->sic2.bits.pll = 0;				/* 1 = div 10, 0 = div 5 */
-			j->sic2.bits.hpd = 0;				/* HPF disable */
-			j->psccr.bits.addr = 2;				/* R/W Smart Cable Register Address */
-			j->psccr.bits.rw = 0;				/* Read / Write flag */
-			j->psccr.bits.dev = 0;
-			outb(j->sic2.byte, j->XILINXbase + 0x00);
-			outb(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(j);
-
-			j->psccr.bits.addr = 3;				/* R/W Smart Cable Register Address */
-			j->psccr.bits.rw = 0;				/* Read / Write flag */
-			j->psccr.bits.dev = 0;
-			outb(0x00, j->XILINXbase + 0x00);		/* PLL Divide N1 */
-			outb(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(j);
-
-			j->psccr.bits.addr = 4;				/* R/W Smart Cable Register Address */
-			j->psccr.bits.rw = 0;				/* Read / Write flag */
-			j->psccr.bits.dev = 0;
-			outb(0x09, j->XILINXbase + 0x00);		/* PLL Multiply M1 */
-			outb(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(j);
-
-			j->sirxg.bits.lig = 1;				/* Line In Gain */
-			j->sirxg.bits.lim = 1;				/* Line In Mute */
-			j->sirxg.bits.mcg = 0;				/* MIC In Gain was 3 */
-			j->sirxg.bits.mcm = 0;				/* MIC In Mute */
-			j->sirxg.bits.him = 0;				/* Handset In Mute */
-			j->sirxg.bits.iir = 1;				/* IIR */
-			j->psccr.bits.addr = 5;				/* R/W Smart Cable Register Address */
-			j->psccr.bits.rw = 0;				/* Read / Write flag */
-			j->psccr.bits.dev = 0;
-			outb(j->sirxg.byte, j->XILINXbase + 0x00);
-			outb(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(j);
-
-			ixj_siadc(j, 0x17);
-			ixj_sidac(j, 0x1D);
-
-			j->siaatt.bits.sot = 0;
-			j->psccr.bits.addr = 9;				/* R/W Smart Cable Register Address */
-			j->psccr.bits.rw = 0;				/* Read / Write flag */
-			j->psccr.bits.dev = 0;
-			outb(j->siaatt.byte, j->XILINXbase + 0x00);
-			outb(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(j);
-
-			if (j->flags.pcmciasct == 1 && !j->readers && !j->writers) {
-				j->psccr.byte = j->pslic.byte = 0;
-				j->pslic.bits.powerdown = 1;
-				j->psccr.bits.dev = 3;
-				j->psccr.bits.rw = 0;
-				outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00);
-				ixj_PCcontrol_wait(j);
-			}
-		}
-		return 0;
-	} else {
-		j->flags.pcmciascp = 0;
-		return 0;
-	}
-	return 0;
-}
-
-static int ixj_hookstate(IXJ *j)
-{
-	int fOffHook = 0;
-
-	switch (j->cardtype) {
-	case QTI_PHONEJACK:
-		ixj_gpio_read(j);
-		fOffHook = j->gpio.bits.gpio3read ? 1 : 0;
-		break;
-	case QTI_LINEJACK:
-	case QTI_PHONEJACK_LITE:
-	case QTI_PHONEJACK_PCI:
-		SLIC_GetState(j);
-		if(j->cardtype == QTI_LINEJACK && j->flags.pots_pstn == 1 && (j->readers || j->writers)) {
-			fOffHook = j->pld_slicr.bits.potspstn ? 1 : 0;
-			if(fOffHook != j->p_hook) {
-				if(!j->checkwait) {
-					j->checkwait = jiffies;
-				}
-				if(time_before(jiffies, j->checkwait + 2)) {
-					fOffHook ^= 1;
-				} else {
-					j->checkwait = 0;
-				}
-				j->p_hook = fOffHook;
-	 			printk("IXJ : /dev/phone%d pots-pstn hookstate check %d at %ld\n", j->board, fOffHook, jiffies);
-			}
-		} else {
-			if (j->pld_slicr.bits.state == PLD_SLIC_STATE_ACTIVE ||
-			    j->pld_slicr.bits.state == PLD_SLIC_STATE_STANDBY) {
-				if (j->flags.ringing || j->flags.cringing) {
-					if (!in_interrupt()) {
-						msleep(20);
-					}
-					SLIC_GetState(j);
-					if (j->pld_slicr.bits.state == PLD_SLIC_STATE_RINGING) {
-						ixj_ring_on(j);
-					}
-				}
-				if (j->cardtype == QTI_PHONEJACK_PCI) {
-					j->pld_scrr.byte = inb_p(j->XILINXbase);
-					fOffHook = j->pld_scrr.pcib.det ? 1 : 0;
-				} else
-					fOffHook = j->pld_slicr.bits.det ? 1 : 0;
-			}
-		}
-		break;
-	case QTI_PHONECARD:
-		fOffHook = ixj_pcmcia_cable_check(j);
-		break;
-	}
-	if (j->r_hook != fOffHook) {
-		j->r_hook = fOffHook;
-		if (j->port == PORT_SPEAKER || j->port == PORT_HANDSET) { // || (j->port == PORT_PSTN && j->flags.pots_pstn == 0)) {
-			j->ex.bits.hookstate = 1;
-			ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN);
-		} else if (!fOffHook) {
-			j->flash_end = jiffies + ((60 * hertz) / 100);
-		}
-	}
-	if (fOffHook) {
-		if(time_before(jiffies, j->flash_end)) {
-			j->ex.bits.flash = 1;
-			j->flash_end = 0;
-			ixj_kill_fasync(j, SIG_FLASH, POLL_IN);
-		}
-	} else {
-		if(time_before(jiffies, j->flash_end)) {
-			fOffHook = 1;
-		}
-	}
-
-	if (j->port == PORT_PSTN && j->daa_mode == SOP_PU_CONVERSATION)
-		fOffHook |= 2;
-
-	if (j->port == PORT_SPEAKER) {
-		if(j->cardtype == QTI_PHONECARD) {
-			if(j->flags.pcmciascp && j->flags.pcmciasct) {
-				fOffHook |= 2;
-			}
-		} else {
-			fOffHook |= 2;
-		}
-	}
-
-	if (j->port == PORT_HANDSET)
-		fOffHook |= 2;
-
-	return fOffHook;
-}
-
-static void ixj_ring_off(IXJ *j)
-{
-	if (j->dsp.low == 0x20)	/* Internet PhoneJACK */
-	 {
-		if (ixjdebug & 0x0004)
-			printk(KERN_INFO "IXJ Ring Off\n");
-		j->gpio.bytes.high = 0x0B;
-		j->gpio.bytes.low = 0x00;
-		j->gpio.bits.gpio1 = 0;
-		j->gpio.bits.gpio2 = 1;
-		j->gpio.bits.gpio5 = 0;
-		ixj_WriteDSPCommand(j->gpio.word, j);
-	} else			/* Internet LineJACK */
-	{
-		if (ixjdebug & 0x0004)
-			printk(KERN_INFO "IXJ Ring Off\n");
-
-		if(!j->flags.cidplay)
-			SLIC_SetState(PLD_SLIC_STATE_STANDBY, j);
-
-		SLIC_GetState(j);
-	}
-}
-
-static void ixj_ring_start(IXJ *j)
-{
-	j->flags.cringing = 1;
-	if (ixjdebug & 0x0004)
-		printk(KERN_INFO "IXJ Cadence Ringing Start /dev/phone%d\n", j->board);
-	if (ixj_hookstate(j) & 1) {
-		if (j->port == PORT_POTS)
-			ixj_ring_off(j);
-		j->flags.cringing = 0;
-		if (ixjdebug & 0x0004)
-			printk(KERN_INFO "IXJ Cadence Ringing Stopped /dev/phone%d off hook\n", j->board);
-	} else if(j->cadence_f[5].enable && (!j->cadence_f[5].en_filter)) {
-		j->ring_cadence_jif = jiffies;
-		j->flags.cidsent = j->flags.cidring = 0;
-		j->cadence_f[5].state = 0;
-		if(j->cadence_f[5].on1)
-			ixj_ring_on(j);
-	} else {
-		j->ring_cadence_jif = jiffies;
-		j->ring_cadence_t = 15;
-		if (j->ring_cadence & 1 << j->ring_cadence_t) {
-			ixj_ring_on(j);
-		} else {
-			ixj_ring_off(j);
-		}
-		j->flags.cidsent = j->flags.cidring = j->flags.firstring = 0;
-	}
-}
-
-static int ixj_ring(IXJ *j)
-{
-	char cntr;
-	unsigned long jif;
-
-	j->flags.ringing = 1;
-	if (ixj_hookstate(j) & 1) {
-		ixj_ring_off(j);
-		j->flags.ringing = 0;
-		return 1;
-	}
-	for (cntr = 0; cntr < j->maxrings; cntr++) {
-		jif = jiffies + (1 * hertz);
-		ixj_ring_on(j);
-		while (time_before(jiffies, jif)) {
-			if (ixj_hookstate(j) & 1) {
-				ixj_ring_off(j);
-				j->flags.ringing = 0;
-				return 1;
-			}
-			schedule_timeout_interruptible(1);
-			if (signal_pending(current))
-				break;
-		}
-		jif = jiffies + (3 * hertz);
-		ixj_ring_off(j);
-		while (time_before(jiffies, jif)) {
-			if (ixj_hookstate(j) & 1) {
-				msleep(10);
-				if (ixj_hookstate(j) & 1) {
-					j->flags.ringing = 0;
-					return 1;
-				}
-			}
-			schedule_timeout_interruptible(1);
-			if (signal_pending(current))
-				break;
-		}
-	}
-	ixj_ring_off(j);
-	j->flags.ringing = 0;
-	return 0;
-}
-
-static int ixj_open(struct phone_device *p, struct file *file_p)
-{
-	IXJ *j = get_ixj(p->board);
-	file_p->private_data = j;
-
-	if (!j->DSPbase)
-		return -ENODEV;
-
-        if (file_p->f_mode & FMODE_READ) {
-		if(!j->readers) {
-	                j->readers++;
-        	} else {
-                	return -EBUSY;
-		}
-        }
-
-	if (file_p->f_mode & FMODE_WRITE) {
-		if(!j->writers) {
-			j->writers++;
-		} else {
-			if (file_p->f_mode & FMODE_READ){
-				j->readers--;
-			}
-			return -EBUSY;
-		}
-	}
-
-	if (j->cardtype == QTI_PHONECARD) {
-		j->pslic.bits.powerdown = 0;
-		j->psccr.bits.dev = 3;
-		j->psccr.bits.rw = 0;
-		outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00);
-		ixj_PCcontrol_wait(j);
-	}
-
-	j->flags.cidplay = 0;
-	j->flags.cidcw_ack = 0;
-
-	if (ixjdebug & 0x0002)
-		printk(KERN_INFO "Opening board %d\n", p->board);
-
-	j->framesread = j->frameswritten = 0;
-	return 0;
-}
-
-static int ixj_release(struct inode *inode, struct file *file_p)
-{
-	IXJ_TONE ti;
-	int cnt;
-	IXJ *j = file_p->private_data;
-	int board = j->p.board;
-
-	/*
-	 *    Set up locks to ensure that only one process is talking to the DSP at a time.
-	 *    This is necessary to keep the DSP from locking up.
-	 */
-	while(test_and_set_bit(board, (void *)&j->busyflags) != 0)
-		schedule_timeout_interruptible(1);
-	if (ixjdebug & 0x0002)
-		printk(KERN_INFO "Closing board %d\n", NUM(inode));
-
-	if (j->cardtype == QTI_PHONECARD)
-		ixj_set_port(j, PORT_SPEAKER);
-	else
-		ixj_set_port(j, PORT_POTS);
-
-	aec_stop(j);
-	ixj_play_stop(j);
-	ixj_record_stop(j);
-	set_play_volume(j, 0x100);
-	set_rec_volume(j, 0x100);
-	ixj_ring_off(j);
-
-	/* Restore the tone table to default settings. */
-	ti.tone_index = 10;
-	ti.gain0 = 1;
-	ti.freq0 = hz941;
-	ti.gain1 = 0;
-	ti.freq1 = hz1209;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 11;
-	ti.gain0 = 1;
-	ti.freq0 = hz941;
-	ti.gain1 = 0;
-	ti.freq1 = hz1336;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 12;
-	ti.gain0 = 1;
-	ti.freq0 = hz941;
-	ti.gain1 = 0;
-	ti.freq1 = hz1477;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 13;
-	ti.gain0 = 1;
-	ti.freq0 = hz800;
-	ti.gain1 = 0;
-	ti.freq1 = 0;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 14;
-	ti.gain0 = 1;
-	ti.freq0 = hz1000;
-	ti.gain1 = 0;
-	ti.freq1 = 0;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 15;
-	ti.gain0 = 1;
-	ti.freq0 = hz1250;
-	ti.gain1 = 0;
-	ti.freq1 = 0;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 16;
-	ti.gain0 = 1;
-	ti.freq0 = hz950;
-	ti.gain1 = 0;
-	ti.freq1 = 0;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 17;
-	ti.gain0 = 1;
-	ti.freq0 = hz1100;
-	ti.gain1 = 0;
-	ti.freq1 = 0;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 18;
-	ti.gain0 = 1;
-	ti.freq0 = hz1400;
-	ti.gain1 = 0;
-	ti.freq1 = 0;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 19;
-	ti.gain0 = 1;
-	ti.freq0 = hz1500;
-	ti.gain1 = 0;
-	ti.freq1 = 0;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 20;
-	ti.gain0 = 1;
-	ti.freq0 = hz1600;
-	ti.gain1 = 0;
-	ti.freq1 = 0;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 21;
-	ti.gain0 = 1;
-	ti.freq0 = hz1800;
-	ti.gain1 = 0;
-	ti.freq1 = 0;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 22;
-	ti.gain0 = 1;
-	ti.freq0 = hz2100;
-	ti.gain1 = 0;
-	ti.freq1 = 0;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 23;
-	ti.gain0 = 1;
-	ti.freq0 = hz1300;
-	ti.gain1 = 0;
-	ti.freq1 = 0;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 24;
-	ti.gain0 = 1;
-	ti.freq0 = hz2450;
-	ti.gain1 = 0;
-	ti.freq1 = 0;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 25;
-	ti.gain0 = 1;
-	ti.freq0 = hz350;
-	ti.gain1 = 0;
-	ti.freq1 = hz440;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 26;
-	ti.gain0 = 1;
-	ti.freq0 = hz440;
-	ti.gain1 = 0;
-	ti.freq1 = hz480;
-	ixj_init_tone(j, &ti);
-	ti.tone_index = 27;
-	ti.gain0 = 1;
-	ti.freq0 = hz480;
-	ti.gain1 = 0;
-	ti.freq1 = hz620;
-	ixj_init_tone(j, &ti);
-
-	set_rec_depth(j, 2);	/* Set Record Channel Limit to 2 frames */
-
-	set_play_depth(j, 2);	/* Set Playback Channel Limit to 2 frames */
-
-	j->ex.bits.dtmf_ready = 0;
-	j->dtmf_state = 0;
-	j->dtmf_wp = j->dtmf_rp = 0;
-	j->rec_mode = j->play_mode = -1;
-	j->flags.ringing = 0;
-	j->maxrings = MAXRINGS;
-	j->ring_cadence = USA_RING_CADENCE;
-	if(j->cadence_f[5].enable) {
-		j->cadence_f[5].enable = j->cadence_f[5].en_filter = j->cadence_f[5].state = 0;
-	}
-	j->drybuffer = 0;
-	j->winktime = 320;
-	j->flags.dtmf_oob = 0;
-	for (cnt = 0; cnt < 4; cnt++)
-		j->cadence_f[cnt].enable = 0;
-
-	idle(j);
-
-	if(j->cardtype == QTI_PHONECARD) {
-		SLIC_SetState(PLD_SLIC_STATE_OC, j);
-	}
-
-	if (file_p->f_mode & FMODE_READ)
-		j->readers--;
-	if (file_p->f_mode & FMODE_WRITE)
-		j->writers--;
-
-	if (j->read_buffer && !j->readers) {
-		kfree(j->read_buffer);
-		j->read_buffer = NULL;
-		j->read_buffer_size = 0;
-	}
-	if (j->write_buffer && !j->writers) {
-		kfree(j->write_buffer);
-		j->write_buffer = NULL;
-		j->write_buffer_size = 0;
-	}
-	j->rec_codec = j->play_codec = 0;
-	j->rec_frame_size = j->play_frame_size = 0;
-	j->flags.cidsent = j->flags.cidring = 0;
-
-	if(j->cardtype == QTI_LINEJACK && !j->readers && !j->writers) {
-		ixj_set_port(j, PORT_PSTN);
-		daa_set_mode(j, SOP_PU_SLEEP);
-		ixj_set_pots(j, 1);
-	}
-	ixj_WriteDSPCommand(0x0FE3, j);	/* Put the DSP in 1/5 power mode. */
-
-	/* Set up the default signals for events */
-	for (cnt = 0; cnt < 35; cnt++)
-		j->ixj_signals[cnt] = SIGIO;
-
-	/* Set the excetion signal enable flags */
-	j->ex_sig.bits.dtmf_ready = j->ex_sig.bits.hookstate = j->ex_sig.bits.flash = j->ex_sig.bits.pstn_ring =
-	j->ex_sig.bits.caller_id = j->ex_sig.bits.pstn_wink = j->ex_sig.bits.f0 = j->ex_sig.bits.f1 = j->ex_sig.bits.f2 =
-	j->ex_sig.bits.f3 = j->ex_sig.bits.fc0 = j->ex_sig.bits.fc1 = j->ex_sig.bits.fc2 = j->ex_sig.bits.fc3 = 1;
-
-	file_p->private_data = NULL;
-	clear_bit(board, &j->busyflags);
-	return 0;
-}
-
-static int read_filters(IXJ *j)
-{
-	unsigned short fc, cnt, trg;
-	int var;
-
-	trg = 0;
-	if (ixj_WriteDSPCommand(0x5144, j)) {
-		if(ixjdebug & 0x0001) {
-			printk(KERN_INFO "Read Frame Counter failed!\n");
-		}
-		return -1;
-	}
-	fc = j->ssr.high << 8 | j->ssr.low;
-	if (fc == j->frame_count)
-		return 1;
-
-	j->frame_count = fc;
-
-	if (j->dtmf_proc)
-		return 1;
-
-	var = 10;
-
-	for (cnt = 0; cnt < 4; cnt++) {
-		if (ixj_WriteDSPCommand(0x5154 + cnt, j)) {
-			if(ixjdebug & 0x0001) {
-				printk(KERN_INFO "Select Filter %d failed!\n", cnt);
-			}
-			return -1;
-		}
-		if (ixj_WriteDSPCommand(0x515C, j)) {
-			if(ixjdebug & 0x0001) {
-				printk(KERN_INFO "Read Filter History %d failed!\n", cnt);
-			}
-			return -1;
-		}
-		j->filter_hist[cnt] = j->ssr.high << 8 | j->ssr.low;
-
-		if (j->cadence_f[cnt].enable) {
-			if (j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12)) {
-				if (j->cadence_f[cnt].state == 0) {
-					j->cadence_f[cnt].state = 1;
-					j->cadence_f[cnt].on1min = jiffies + (long)((j->cadence_f[cnt].on1 * (hertz * (100 - var)) / 10000));
-					j->cadence_f[cnt].on1dot = jiffies + (long)((j->cadence_f[cnt].on1 * (hertz * (100)) / 10000));
-					j->cadence_f[cnt].on1max = jiffies + (long)((j->cadence_f[cnt].on1 * (hertz * (100 + var)) / 10000));
-				} else if (j->cadence_f[cnt].state == 2 &&
-					   (time_after(jiffies, j->cadence_f[cnt].off1min) &&
-					    time_before(jiffies, j->cadence_f[cnt].off1max))) {
-					if (j->cadence_f[cnt].on2) {
-						j->cadence_f[cnt].state = 3;
-						j->cadence_f[cnt].on2min = jiffies + (long)((j->cadence_f[cnt].on2 * (hertz * (100 - var)) / 10000));
-						j->cadence_f[cnt].on2dot = jiffies + (long)((j->cadence_f[cnt].on2 * (hertz * (100)) / 10000));
-						j->cadence_f[cnt].on2max = jiffies + (long)((j->cadence_f[cnt].on2 * (hertz * (100 + var)) / 10000));
-					} else {
-						j->cadence_f[cnt].state = 7;
-					}
-				} else if (j->cadence_f[cnt].state == 4 &&
-					   (time_after(jiffies, j->cadence_f[cnt].off2min) &&
-					    time_before(jiffies, j->cadence_f[cnt].off2max))) {
-					if (j->cadence_f[cnt].on3) {
-						j->cadence_f[cnt].state = 5;
-						j->cadence_f[cnt].on3min = jiffies + (long)((j->cadence_f[cnt].on3 * (hertz * (100 - var)) / 10000));
-						j->cadence_f[cnt].on3dot = jiffies + (long)((j->cadence_f[cnt].on3 * (hertz * (100)) / 10000));
-						j->cadence_f[cnt].on3max = jiffies + (long)((j->cadence_f[cnt].on3 * (hertz * (100 + var)) / 10000));
-					} else {
-						j->cadence_f[cnt].state = 7;
-					}
-				} else {
-					j->cadence_f[cnt].state = 0;
-				}
-			} else if (j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3)) {
-				if (j->cadence_f[cnt].state == 1) {
-					if(!j->cadence_f[cnt].on1) {
-						j->cadence_f[cnt].state = 7;
-					} else if((time_after(jiffies, j->cadence_f[cnt].on1min) &&
-					  time_before(jiffies, j->cadence_f[cnt].on1max))) {
-						if(j->cadence_f[cnt].off1) {
-							j->cadence_f[cnt].state = 2;
-							j->cadence_f[cnt].off1min = jiffies + (long)((j->cadence_f[cnt].off1 * (hertz * (100 - var)) / 10000));
-							j->cadence_f[cnt].off1dot = jiffies + (long)((j->cadence_f[cnt].off1 * (hertz * (100)) / 10000));
-							j->cadence_f[cnt].off1max = jiffies + (long)((j->cadence_f[cnt].off1 * (hertz * (100 + var)) / 10000));
-						} else {
-							j->cadence_f[cnt].state = 7;
-						}
-					} else {
-						j->cadence_f[cnt].state = 0;
-					}
-				} else if (j->cadence_f[cnt].state == 3) {
-					if((time_after(jiffies, j->cadence_f[cnt].on2min) &&
-					    time_before(jiffies, j->cadence_f[cnt].on2max))) {
-						if(j->cadence_f[cnt].off2) {
-							j->cadence_f[cnt].state = 4;
-							j->cadence_f[cnt].off2min = jiffies + (long)((j->cadence_f[cnt].off2 * (hertz * (100 - var)) / 10000));
-							j->cadence_f[cnt].off2dot = jiffies + (long)((j->cadence_f[cnt].off2 * (hertz * (100)) / 10000));
-							j->cadence_f[cnt].off2max = jiffies + (long)((j->cadence_f[cnt].off2 * (hertz * (100 + var)) / 10000));
-						} else {
-							j->cadence_f[cnt].state = 7;
-						}
-					} else {
-						j->cadence_f[cnt].state = 0;
-					}
-				} else if (j->cadence_f[cnt].state == 5) {
-					if ((time_after(jiffies, j->cadence_f[cnt].on3min) &&
-					    time_before(jiffies, j->cadence_f[cnt].on3max))) {
-						if(j->cadence_f[cnt].off3) {
-							j->cadence_f[cnt].state = 6;
-							j->cadence_f[cnt].off3min = jiffies + (long)((j->cadence_f[cnt].off3 * (hertz * (100 - var)) / 10000));
-							j->cadence_f[cnt].off3dot = jiffies + (long)((j->cadence_f[cnt].off3 * (hertz * (100)) / 10000));
-							j->cadence_f[cnt].off3max = jiffies + (long)((j->cadence_f[cnt].off3 * (hertz * (100 + var)) / 10000));
-						} else {
-							j->cadence_f[cnt].state = 7;
-						}
-					} else {
-						j->cadence_f[cnt].state = 0;
-					}
-				} else {
-					j->cadence_f[cnt].state = 0;
-				}
-			} else {
-				switch(j->cadence_f[cnt].state) {
-					case 1:
-						if(time_after(jiffies, j->cadence_f[cnt].on1dot) &&
-						   !j->cadence_f[cnt].off1 &&
-						   !j->cadence_f[cnt].on2 && !j->cadence_f[cnt].off2 &&
-						   !j->cadence_f[cnt].on3 && !j->cadence_f[cnt].off3) {
-							j->cadence_f[cnt].state = 7;
-						}
-						break;
-					case 3:
-						if(time_after(jiffies, j->cadence_f[cnt].on2dot) &&
-						   !j->cadence_f[cnt].off2 &&
-						   !j->cadence_f[cnt].on3 && !j->cadence_f[cnt].off3) {
-							j->cadence_f[cnt].state = 7;
-						}
-						break;
-					case 5:
-						if(time_after(jiffies, j->cadence_f[cnt].on3dot) &&
-						   !j->cadence_f[cnt].off3) {
-							j->cadence_f[cnt].state = 7;
-						}
-						break;
-				}
-			}
-
-			if (ixjdebug & 0x0040) {
-				printk(KERN_INFO "IXJ Tone Cadence state = %d /dev/phone%d at %ld\n", j->cadence_f[cnt].state, j->board, jiffies);
-				switch(j->cadence_f[cnt].state) {
-					case 0:
-						printk(KERN_INFO "IXJ /dev/phone%d No Tone detected\n", j->board);
-						break;
-					case 1:
-						printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %u %ld - %ld - %ld\n", j->board,
-					j->cadence_f[cnt].on1, j->cadence_f[cnt].on1min, j->cadence_f[cnt].on1dot, j->cadence_f[cnt].on1max);
-						break;
-					case 2:
-						printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].off1min,
-															j->cadence_f[cnt].off1max);
-						break;
-					case 3:
-						printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].on2min,
-															j->cadence_f[cnt].on2max);
-						break;
-					case 4:
-						printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].off2min,
-															j->cadence_f[cnt].off2max);
-						break;
-					case 5:
-						printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].on3min,
-															j->cadence_f[cnt].on3max);
-						break;
-					case 6:
-						printk(KERN_INFO "IXJ /dev/phone%d Next Tone Cadence state at %ld - %ld\n", j->board, j->cadence_f[cnt].off3min,
-															j->cadence_f[cnt].off3max);
-						break;
-				}
-			}
-		}
-		if (j->cadence_f[cnt].state == 7) {
-			j->cadence_f[cnt].state = 0;
-			if (j->cadence_f[cnt].enable == 1)
-				j->cadence_f[cnt].enable = 0;
-			switch (cnt) {
-			case 0:
-				if(ixjdebug & 0x0020) {
-					printk(KERN_INFO "Filter Cadence 0 triggered %ld\n", jiffies);
-				}
-				j->ex.bits.fc0 = 1;
-				ixj_kill_fasync(j, SIG_FC0, POLL_IN);
-				break;
-			case 1:
-				if(ixjdebug & 0x0020) {
-					printk(KERN_INFO "Filter Cadence 1 triggered %ld\n", jiffies);
-				}
-				j->ex.bits.fc1 = 1;
-				ixj_kill_fasync(j, SIG_FC1, POLL_IN);
-				break;
-			case 2:
-				if(ixjdebug & 0x0020) {
-					printk(KERN_INFO "Filter Cadence 2 triggered %ld\n", jiffies);
-				}
-				j->ex.bits.fc2 = 1;
-				ixj_kill_fasync(j, SIG_FC2, POLL_IN);
-				break;
-			case 3:
-				if(ixjdebug & 0x0020) {
-					printk(KERN_INFO "Filter Cadence 3 triggered %ld\n", jiffies);
-				}
-				j->ex.bits.fc3 = 1;
-				ixj_kill_fasync(j, SIG_FC3, POLL_IN);
-				break;
-			}
-		}
-		if (j->filter_en[cnt] && ((j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12)) ||
-					  (j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3)))) {
-			if((j->filter_hist[cnt] & 3 && !(j->filter_hist[cnt] & 12))) {
-				trg = 1;
-			} else if((j->filter_hist[cnt] & 12 && !(j->filter_hist[cnt] & 3))) {
-				trg = 0;
-			}
-			switch (cnt) {
-			case 0:
-				if(ixjdebug & 0x0020) {
-					printk(KERN_INFO "Filter 0 triggered %d at %ld\n", trg, jiffies);
-				}
-				j->ex.bits.f0 = 1;
-				ixj_kill_fasync(j, SIG_F0, POLL_IN);
-				break;
-			case 1:
-				if(ixjdebug & 0x0020) {
-					printk(KERN_INFO "Filter 1 triggered %d at %ld\n", trg, jiffies);
-				}
-				j->ex.bits.f1 = 1;
-				ixj_kill_fasync(j, SIG_F1, POLL_IN);
-				break;
-			case 2:
-				if(ixjdebug & 0x0020) {
-					printk(KERN_INFO "Filter 2 triggered %d at %ld\n", trg, jiffies);
-				}
-				j->ex.bits.f2 = 1;
-				ixj_kill_fasync(j, SIG_F2, POLL_IN);
-				break;
-			case 3:
-				if(ixjdebug & 0x0020) {
-					printk(KERN_INFO "Filter 3 triggered %d at %ld\n", trg, jiffies);
-				}
-				j->ex.bits.f3 = 1;
-				ixj_kill_fasync(j, SIG_F3, POLL_IN);
-				break;
-			}
-		}
-	}
-	return 0;
-}
-
-static int LineMonitor(IXJ *j)
-{
-	if (j->dtmf_proc) {
-		return -1;
-	}
-	j->dtmf_proc = 1;
-
-	if (ixj_WriteDSPCommand(0x7000, j))		/* Line Monitor */
-		return -1;
-
-	j->dtmf.bytes.high = j->ssr.high;
-	j->dtmf.bytes.low = j->ssr.low;
-	if (!j->dtmf_state && j->dtmf.bits.dtmf_valid) {
-		j->dtmf_state = 1;
-		j->dtmf_current = j->dtmf.bits.digit;
-	}
-	if (j->dtmf_state && !j->dtmf.bits.dtmf_valid)	/* && j->dtmf_wp != j->dtmf_rp) */
-	 {
-		if(!j->cidcw_wait) {
-			j->dtmfbuffer[j->dtmf_wp] = j->dtmf_current;
-			j->dtmf_wp++;
-			if (j->dtmf_wp == 79)
-				j->dtmf_wp = 0;
-			j->ex.bits.dtmf_ready = 1;
-			if(j->ex_sig.bits.dtmf_ready) {
-				ixj_kill_fasync(j, SIG_DTMF_READY, POLL_IN);
-			}
-		}
-		else if(j->dtmf_current == 0x00 || j->dtmf_current == 0x0D) {
-			if(ixjdebug & 0x0020) {
-				printk("IXJ phone%d saw CIDCW Ack DTMF %d from display at %ld\n", j->board, j->dtmf_current, jiffies);
-			}
-			j->flags.cidcw_ack = 1;
-		}
-		j->dtmf_state = 0;
-	}
-	j->dtmf_proc = 0;
-
-	return 0;
-}
-
-/************************************************************************
-*
-* Functions to allow alaw <-> ulaw conversions.
-*
-************************************************************************/
-
-static void ulaw2alaw(unsigned char *buff, unsigned long len)
-{
-	static unsigned char table_ulaw2alaw[] =
-	{
-		0x2A, 0x2B, 0x28, 0x29, 0x2E, 0x2F, 0x2C, 0x2D,
-		0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25,
-		0x3A, 0x3B, 0x38, 0x39, 0x3E, 0x3F, 0x3C, 0x3D,
-		0x32, 0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35,
-		0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D, 0x02,
-		0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x1A,
-		0x1B, 0x18, 0x19, 0x1E, 0x1F, 0x1C, 0x1D, 0x12,
-		0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x6B,
-		0x68, 0x69, 0x6E, 0x6F, 0x6C, 0x6D, 0x62, 0x63,
-		0x60, 0x61, 0x66, 0x67, 0x64, 0x65, 0x7B, 0x79,
-		0x7E, 0x7F, 0x7C, 0x7D, 0x72, 0x73, 0x70, 0x71,
-		0x76, 0x77, 0x74, 0x75, 0x4B, 0x49, 0x4F, 0x4D,
-		0x42, 0x43, 0x40, 0x41, 0x46, 0x47, 0x44, 0x45,
-		0x5A, 0x5B, 0x58, 0x59, 0x5E, 0x5F, 0x5C, 0x5D,
-		0x52, 0x52, 0x53, 0x53, 0x50, 0x50, 0x51, 0x51,
-		0x56, 0x56, 0x57, 0x57, 0x54, 0x54, 0x55, 0xD5,
-		0xAA, 0xAB, 0xA8, 0xA9, 0xAE, 0xAF, 0xAC, 0xAD,
-		0xA2, 0xA3, 0xA0, 0xA1, 0xA6, 0xA7, 0xA4, 0xA5,
-		0xBA, 0xBB, 0xB8, 0xB9, 0xBE, 0xBF, 0xBC, 0xBD,
-		0xB2, 0xB3, 0xB0, 0xB1, 0xB6, 0xB7, 0xB4, 0xB5,
-		0x8B, 0x88, 0x89, 0x8E, 0x8F, 0x8C, 0x8D, 0x82,
-		0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85, 0x9A,
-		0x9B, 0x98, 0x99, 0x9E, 0x9F, 0x9C, 0x9D, 0x92,
-		0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95, 0xEB,
-		0xE8, 0xE9, 0xEE, 0xEF, 0xEC, 0xED, 0xE2, 0xE3,
-		0xE0, 0xE1, 0xE6, 0xE7, 0xE4, 0xE5, 0xFB, 0xF9,
-		0xFE, 0xFF, 0xFC, 0xFD, 0xF2, 0xF3, 0xF0, 0xF1,
-		0xF6, 0xF7, 0xF4, 0xF5, 0xCB, 0xC9, 0xCF, 0xCD,
-		0xC2, 0xC3, 0xC0, 0xC1, 0xC6, 0xC7, 0xC4, 0xC5,
-		0xDA, 0xDB, 0xD8, 0xD9, 0xDE, 0xDF, 0xDC, 0xDD,
-		0xD2, 0xD2, 0xD3, 0xD3, 0xD0, 0xD0, 0xD1, 0xD1,
-		0xD6, 0xD6, 0xD7, 0xD7, 0xD4, 0xD4, 0xD5, 0xD5
-	};
-
-	while (len--)
-	{
-		*buff = table_ulaw2alaw[*(unsigned char *)buff];
-		buff++;
-	}
-}
-
-static void alaw2ulaw(unsigned char *buff, unsigned long len)
-{
-	static unsigned char table_alaw2ulaw[] =
-	{
-		0x29, 0x2A, 0x27, 0x28, 0x2D, 0x2E, 0x2B, 0x2C,
-		0x21, 0x22, 0x1F, 0x20, 0x25, 0x26, 0x23, 0x24,
-		0x39, 0x3A, 0x37, 0x38, 0x3D, 0x3E, 0x3B, 0x3C,
-		0x31, 0x32, 0x2F, 0x30, 0x35, 0x36, 0x33, 0x34,
-		0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D,
-		0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05,
-		0x1A, 0x1B, 0x18, 0x19, 0x1E, 0x1F, 0x1C, 0x1D,
-		0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15,
-		0x62, 0x63, 0x60, 0x61, 0x66, 0x67, 0x64, 0x65,
-		0x5D, 0x5D, 0x5C, 0x5C, 0x5F, 0x5F, 0x5E, 0x5E,
-		0x74, 0x76, 0x70, 0x72, 0x7C, 0x7E, 0x78, 0x7A,
-		0x6A, 0x6B, 0x68, 0x69, 0x6E, 0x6F, 0x6C, 0x6D,
-		0x48, 0x49, 0x46, 0x47, 0x4C, 0x4D, 0x4A, 0x4B,
-		0x40, 0x41, 0x3F, 0x3F, 0x44, 0x45, 0x42, 0x43,
-		0x56, 0x57, 0x54, 0x55, 0x5A, 0x5B, 0x58, 0x59,
-		0x4F, 0x4F, 0x4E, 0x4E, 0x52, 0x53, 0x50, 0x51,
-		0xA9, 0xAA, 0xA7, 0xA8, 0xAD, 0xAE, 0xAB, 0xAC,
-		0xA1, 0xA2, 0x9F, 0xA0, 0xA5, 0xA6, 0xA3, 0xA4,
-		0xB9, 0xBA, 0xB7, 0xB8, 0xBD, 0xBE, 0xBB, 0xBC,
-		0xB1, 0xB2, 0xAF, 0xB0, 0xB5, 0xB6, 0xB3, 0xB4,
-		0x8A, 0x8B, 0x88, 0x89, 0x8E, 0x8F, 0x8C, 0x8D,
-		0x82, 0x83, 0x80, 0x81, 0x86, 0x87, 0x84, 0x85,
-		0x9A, 0x9B, 0x98, 0x99, 0x9E, 0x9F, 0x9C, 0x9D,
-		0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95,
-		0xE2, 0xE3, 0xE0, 0xE1, 0xE6, 0xE7, 0xE4, 0xE5,
-		0xDD, 0xDD, 0xDC, 0xDC, 0xDF, 0xDF, 0xDE, 0xDE,
-		0xF4, 0xF6, 0xF0, 0xF2, 0xFC, 0xFE, 0xF8, 0xFA,
-		0xEA, 0xEB, 0xE8, 0xE9, 0xEE, 0xEF, 0xEC, 0xED,
-		0xC8, 0xC9, 0xC6, 0xC7, 0xCC, 0xCD, 0xCA, 0xCB,
-		0xC0, 0xC1, 0xBF, 0xBF, 0xC4, 0xC5, 0xC2, 0xC3,
-		0xD6, 0xD7, 0xD4, 0xD5, 0xDA, 0xDB, 0xD8, 0xD9,
-		0xCF, 0xCF, 0xCE, 0xCE, 0xD2, 0xD3, 0xD0, 0xD1
-	};
-
-        while (len--)
-        {
-                *buff = table_alaw2ulaw[*(unsigned char *)buff];
-                buff++;
-	}
-}
-
-static ssize_t ixj_read(struct file * file_p, char __user *buf, size_t length, loff_t * ppos)
-{
-	unsigned long i = *ppos;
-	IXJ * j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
-
-	DECLARE_WAITQUEUE(wait, current);
-
-	if (j->flags.inread)
-		return -EALREADY;
-
-	j->flags.inread = 1;
-
-	add_wait_queue(&j->read_q, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	mb();
-
-	while (!j->read_buffer_ready || (j->dtmf_state && j->flags.dtmf_oob)) {
-		++j->read_wait;
-		if (file_p->f_flags & O_NONBLOCK) {
-			set_current_state(TASK_RUNNING);
-			remove_wait_queue(&j->read_q, &wait);
-			j->flags.inread = 0;
-			return -EAGAIN;
-		}
-		if (!ixj_hookstate(j)) {
-			set_current_state(TASK_RUNNING);
-			remove_wait_queue(&j->read_q, &wait);
-			j->flags.inread = 0;
-			return 0;
-		}
-		interruptible_sleep_on(&j->read_q);
-		if (signal_pending(current)) {
-			set_current_state(TASK_RUNNING);
-			remove_wait_queue(&j->read_q, &wait);
-			j->flags.inread = 0;
-			return -EINTR;
-		}
-	}
-
-	remove_wait_queue(&j->read_q, &wait);
-	set_current_state(TASK_RUNNING);
-	/* Don't ever copy more than the user asks */
-	if(j->rec_codec == ALAW)
-		ulaw2alaw(j->read_buffer, min(length, j->read_buffer_size));
-	i = copy_to_user(buf, j->read_buffer, min(length, j->read_buffer_size));
-	j->read_buffer_ready = 0;
-	if (i) {
-		j->flags.inread = 0;
-		return -EFAULT;
-	} else {
-		j->flags.inread = 0;
-		return min(length, j->read_buffer_size);
-	}
-}
-
-static ssize_t ixj_enhanced_read(struct file * file_p, char __user *buf, size_t length,
-			  loff_t * ppos)
-{
-	int pre_retval;
-	ssize_t read_retval = 0;
-	IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
-
-	pre_retval = ixj_PreRead(j, 0L);
-	switch (pre_retval) {
-	case NORMAL:
-		read_retval = ixj_read(file_p, buf, length, ppos);
-		ixj_PostRead(j, 0L);
-		break;
-	case NOPOST:
-		read_retval = ixj_read(file_p, buf, length, ppos);
-		break;
-	case POSTONLY:
-		ixj_PostRead(j, 0L);
-		break;
-	default:
-		read_retval = pre_retval;
-	}
-	return read_retval;
-}
-
-static ssize_t ixj_write(struct file *file_p, const char __user *buf, size_t count, loff_t * ppos)
-{
-	unsigned long i = *ppos;
-	IXJ *j = file_p->private_data;
-
-	DECLARE_WAITQUEUE(wait, current);
-
-	if (j->flags.inwrite)
-		return -EALREADY;
-
-	j->flags.inwrite = 1;
-
-	add_wait_queue(&j->write_q, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	mb();
-
-
-	while (!j->write_buffers_empty) {
-		++j->write_wait;
-		if (file_p->f_flags & O_NONBLOCK) {
-			set_current_state(TASK_RUNNING);
-			remove_wait_queue(&j->write_q, &wait);
-			j->flags.inwrite = 0;
-			return -EAGAIN;
-		}
-		if (!ixj_hookstate(j)) {
-			set_current_state(TASK_RUNNING);
-			remove_wait_queue(&j->write_q, &wait);
-			j->flags.inwrite = 0;
-			return 0;
-		}
-		interruptible_sleep_on(&j->write_q);
-		if (signal_pending(current)) {
-			set_current_state(TASK_RUNNING);
-			remove_wait_queue(&j->write_q, &wait);
-			j->flags.inwrite = 0;
-			return -EINTR;
-		}
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&j->write_q, &wait);
-	if (j->write_buffer_wp + count >= j->write_buffer_end)
-		j->write_buffer_wp = j->write_buffer;
-	i = copy_from_user(j->write_buffer_wp, buf, min(count, j->write_buffer_size));
-	if (i) {
-		j->flags.inwrite = 0;
-		return -EFAULT;
-	}
-       if(j->play_codec == ALAW)
-               alaw2ulaw(j->write_buffer_wp, min(count, j->write_buffer_size));
-	j->flags.inwrite = 0;
-	return min(count, j->write_buffer_size);
-}
-
-static ssize_t ixj_enhanced_write(struct file * file_p, const char __user *buf, size_t count, loff_t * ppos)
-{
-	int pre_retval;
-	ssize_t write_retval = 0;
-
-	IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
-
-	pre_retval = ixj_PreWrite(j, 0L);
-	switch (pre_retval) {
-	case NORMAL:
-		write_retval = ixj_write(file_p, buf, count, ppos);
-		if (write_retval > 0) {
-			ixj_PostWrite(j, 0L);
-			j->write_buffer_wp += write_retval;
-			j->write_buffers_empty--;
-		}
-		break;
-	case NOPOST:
-		write_retval = ixj_write(file_p, buf, count, ppos);
-		if (write_retval > 0) {
-			j->write_buffer_wp += write_retval;
-			j->write_buffers_empty--;
-		}
-		break;
-	case POSTONLY:
-		ixj_PostWrite(j, 0L);
-		break;
-	default:
-		write_retval = pre_retval;
-	}
-	return write_retval;
-}
-
-static void ixj_read_frame(IXJ *j)
-{
-	int cnt, dly;
-
-	if (j->read_buffer) {
-		for (cnt = 0; cnt < j->rec_frame_size * 2; cnt += 2) {
-			if (!(cnt % 16) && !IsRxReady(j)) {
-				dly = 0;
-				while (!IsRxReady(j)) {
-					if (dly++ > 5) {
-						dly = 0;
-						break;
-					}
-					udelay(10);
-				}
-			}
-			/* Throw away word 0 of the 8021 compressed format to get standard G.729. */
-			if (j->rec_codec == G729 && (cnt == 0 || cnt == 10 || cnt == 20)) {
-				inb_p(j->DSPbase + 0x0E);
-				inb_p(j->DSPbase + 0x0F);
-			}
-			*(j->read_buffer + cnt) = inb_p(j->DSPbase + 0x0E);
-			*(j->read_buffer + cnt + 1) = inb_p(j->DSPbase + 0x0F);
-		}
-		++j->framesread;
-		if (j->intercom != -1) {
-			if (IsTxReady(get_ixj(j->intercom))) {
-				for (cnt = 0; cnt < j->rec_frame_size * 2; cnt += 2) {
-					if (!(cnt % 16) && !IsTxReady(j)) {
-						dly = 0;
-						while (!IsTxReady(j)) {
-							if (dly++ > 5) {
-								dly = 0;
-								break;
-							}
-							udelay(10);
-						}
-					}
-					outb_p(*(j->read_buffer + cnt), get_ixj(j->intercom)->DSPbase + 0x0C);
-					outb_p(*(j->read_buffer + cnt + 1), get_ixj(j->intercom)->DSPbase + 0x0D);
-				}
-				get_ixj(j->intercom)->frameswritten++;
-			}
-		} else {
-			j->read_buffer_ready = 1;
-			wake_up_interruptible(&j->read_q);	/* Wake any blocked readers */
-
-			wake_up_interruptible(&j->poll_q);	/* Wake any blocked selects */
-
-			if(j->ixj_signals[SIG_READ_READY])
-				ixj_kill_fasync(j, SIG_READ_READY, POLL_OUT);
-		}
-	}
-}
-
-static short fsk[][6][20] =
-{
-	{
-		{
-			0, 17846, 29934, 32364, 24351, 8481, -10126, -25465, -32587, -29196,
-			-16384, 1715, 19260, 30591, 32051, 23170, 6813, -11743, -26509, -32722
-		},
-		{
-			-28377, -14876, 3425, 20621, 31163, 31650, 21925, 5126, -13328, -27481,
-			-32767, -27481, -13328, 5126, 21925, 31650, 31163, 20621, 3425, -14876
-		},
-		{
-			-28377, -32722, -26509, -11743, 6813, 23170, 32051, 30591, 19260, 1715,
-			-16384, -29196, -32587, -25465, -10126, 8481, 24351, 32364, 29934, 17846
-		},
-		{
-			0, -17846, -29934, -32364, -24351, -8481, 10126, 25465, 32587, 29196,
-			16384, -1715, -19260, -30591, -32051, -23170, -6813, 11743, 26509, 32722
-		},
-		{
-			28377, 14876, -3425, -20621, -31163, -31650, -21925, -5126, 13328, 27481,
-			32767, 27481, 13328, -5126, -21925, -31650, -31163, -20621, -3425, 14876
-		},
-		{
-			28377, 32722, 26509, 11743, -6813, -23170, -32051, -30591, -19260, -1715,
-			16384, 29196, 32587, 25465, 10126, -8481, -24351, -32364, -29934, -17846
-		}
-	},
-	{
-		{
-			0, 10126, 19260, 26509, 31163, 32767, 31163, 26509, 19260, 10126,
-			0, -10126, -19260, -26509, -31163, -32767, -31163, -26509, -19260, -10126
-		},
-		{
-			-28377, -21925, -13328, -3425, 6813, 16384, 24351, 29934, 32587, 32051,
-			28377, 21925, 13328, 3425, -6813, -16384, -24351, -29934, -32587, -32051
-		},
-		{
-			-28377, -32051, -32587, -29934, -24351, -16384, -6813, 3425, 13328, 21925,
-			28377, 32051, 32587, 29934, 24351, 16384, 6813, -3425, -13328, -21925
-		},
-		{
-			0, -10126, -19260, -26509, -31163, -32767, -31163, -26509, -19260, -10126,
-			0, 10126, 19260, 26509, 31163, 32767, 31163, 26509, 19260, 10126
-		},
-		{
-			28377, 21925, 13328, 3425, -6813, -16383, -24351, -29934, -32587, -32051,
-			-28377, -21925, -13328, -3425, 6813, 16383, 24351, 29934, 32587, 32051
-		},
-		{
-			28377, 32051, 32587, 29934, 24351, 16384, 6813, -3425, -13328, -21925,
-			-28377, -32051, -32587, -29934, -24351, -16384, -6813, 3425, 13328, 21925
-		}
-	}
-};
-
-
-static void ixj_write_cid_bit(IXJ *j, int bit)
-{
-	while (j->fskcnt < 20) {
-		if(j->fskdcnt < (j->fsksize - 1))
-			j->fskdata[j->fskdcnt++] = fsk[bit][j->fskz][j->fskcnt];
-
-		j->fskcnt += 3;
-	}
-	j->fskcnt %= 20;
-
-	if (!bit)
-		j->fskz++;
-	if (j->fskz >= 6)
-		j->fskz = 0;
-
-}
-
-static void ixj_write_cid_byte(IXJ *j, char byte)
-{
-	IXJ_CBYTE cb;
-
-		cb.cbyte = byte;
-		ixj_write_cid_bit(j, 0);
-		ixj_write_cid_bit(j, cb.cbits.b0 ? 1 : 0);
-		ixj_write_cid_bit(j, cb.cbits.b1 ? 1 : 0);
-		ixj_write_cid_bit(j, cb.cbits.b2 ? 1 : 0);
-		ixj_write_cid_bit(j, cb.cbits.b3 ? 1 : 0);
-		ixj_write_cid_bit(j, cb.cbits.b4 ? 1 : 0);
-		ixj_write_cid_bit(j, cb.cbits.b5 ? 1 : 0);
-		ixj_write_cid_bit(j, cb.cbits.b6 ? 1 : 0);
-		ixj_write_cid_bit(j, cb.cbits.b7 ? 1 : 0);
-		ixj_write_cid_bit(j, 1);
-}
-
-static void ixj_write_cid_seize(IXJ *j)
-{
-	int cnt;
-
-	for (cnt = 0; cnt < 150; cnt++) {
-		ixj_write_cid_bit(j, 0);
-		ixj_write_cid_bit(j, 1);
-	}
-	for (cnt = 0; cnt < 180; cnt++) {
-		ixj_write_cid_bit(j, 1);
-	}
-}
-
-static void ixj_write_cidcw_seize(IXJ *j)
-{
-	int cnt;
-
-	for (cnt = 0; cnt < 80; cnt++) {
-		ixj_write_cid_bit(j, 1);
-	}
-}
-
-static int ixj_write_cid_string(IXJ *j, char *s, int checksum)
-{
-	int cnt;
-
-	for (cnt = 0; cnt < strlen(s); cnt++) {
-		ixj_write_cid_byte(j, s[cnt]);
-		checksum = (checksum + s[cnt]);
-	}
-	return checksum;
-}
-
-static void ixj_pad_fsk(IXJ *j, int pad)
-{
-	int cnt;
-
-	for (cnt = 0; cnt < pad; cnt++) {
-		if(j->fskdcnt < (j->fsksize - 1))
-			j->fskdata[j->fskdcnt++] = 0x0000;
-	}
-	for (cnt = 0; cnt < 720; cnt++) {
-		if(j->fskdcnt < (j->fsksize - 1))
-			j->fskdata[j->fskdcnt++] = 0x0000;
-	}
-}
-
-static void ixj_pre_cid(IXJ *j)
-{
-	j->cid_play_codec = j->play_codec;
-	j->cid_play_frame_size = j->play_frame_size;
-	j->cid_play_volume = get_play_volume(j);
-	j->cid_play_flag = j->flags.playing;
-
-	j->cid_rec_codec = j->rec_codec;
-	j->cid_rec_volume = get_rec_volume(j);
-	j->cid_rec_flag = j->flags.recording;
-
-	j->cid_play_aec_level = j->aec_level;
-
-	switch(j->baseframe.low) {
-		case 0xA0:
-			j->cid_base_frame_size = 20;
-			break;
-		case 0x50:
-			j->cid_base_frame_size = 10;
-			break;
-		case 0xF0:
-			j->cid_base_frame_size = 30;
-			break;
-	}
-
-	ixj_play_stop(j);
-	ixj_cpt_stop(j);
-
-	j->flags.cidplay = 1;
-
-	set_base_frame(j, 30);
-	set_play_codec(j, LINEAR16);
-	set_play_volume(j, 0x1B);
-	ixj_play_start(j);
-}
-
-static void ixj_post_cid(IXJ *j)
-{
-	ixj_play_stop(j);
-
-	if(j->cidsize > 5000) {
-		SLIC_SetState(PLD_SLIC_STATE_STANDBY, j);
-	}
-	j->flags.cidplay = 0;
-	if(ixjdebug & 0x0200) {
-		printk("IXJ phone%d Finished Playing CallerID data %ld\n", j->board, jiffies);
-	}
-
-	ixj_fsk_free(j);
-
-	j->fskdcnt = 0;
-	set_base_frame(j, j->cid_base_frame_size);
-	set_play_codec(j, j->cid_play_codec);
-	ixj_aec_start(j, j->cid_play_aec_level);
-	set_play_volume(j, j->cid_play_volume);
-
-	set_rec_codec(j, j->cid_rec_codec);
-	set_rec_volume(j, j->cid_rec_volume);
-
-	if(j->cid_rec_flag)
-		ixj_record_start(j);
-
-	if(j->cid_play_flag)
-		ixj_play_start(j);
-
-	if(j->cid_play_flag) {
-		wake_up_interruptible(&j->write_q);	/* Wake any blocked writers */
-	}
-}
-
-static void ixj_write_cid(IXJ *j)
-{
-	char sdmf1[50];
-	char sdmf2[50];
-	char sdmf3[80];
-	char mdmflen, len1, len2, len3;
-	int pad;
-
-	int checksum = 0;
-
-	if (j->dsp.low == 0x20 || j->flags.cidplay)
-		return;
-
-	j->fskz = j->fskphase = j->fskcnt = j->fskdcnt = 0;
-	j->cidsize = j->cidcnt = 0;
-
-	ixj_fsk_alloc(j);
-
-	strcpy(sdmf1, j->cid_send.month);
-	strcat(sdmf1, j->cid_send.day);
-	strcat(sdmf1, j->cid_send.hour);
-	strcat(sdmf1, j->cid_send.min);
-	strcpy(sdmf2, j->cid_send.number);
-	strcpy(sdmf3, j->cid_send.name);
-
-	len1 = strlen(sdmf1);
-	len2 = strlen(sdmf2);
-	len3 = strlen(sdmf3);
-	mdmflen = len1 + len2 + len3 + 6;
-
-	while(1){
-		ixj_write_cid_seize(j);
-
-		ixj_write_cid_byte(j, 0x80);
-		checksum = 0x80;
-		ixj_write_cid_byte(j, mdmflen);
-		checksum = checksum + mdmflen;
-
-		ixj_write_cid_byte(j, 0x01);
-		checksum = checksum + 0x01;
-		ixj_write_cid_byte(j, len1);
-		checksum = checksum + len1;
-		checksum = ixj_write_cid_string(j, sdmf1, checksum);
-		if(ixj_hookstate(j) & 1)
-			break;
-
-		ixj_write_cid_byte(j, 0x02);
-		checksum = checksum + 0x02;
-		ixj_write_cid_byte(j, len2);
-		checksum = checksum + len2;
-		checksum = ixj_write_cid_string(j, sdmf2, checksum);
-		if(ixj_hookstate(j) & 1)
-			break;
-
-		ixj_write_cid_byte(j, 0x07);
-		checksum = checksum + 0x07;
-		ixj_write_cid_byte(j, len3);
-		checksum = checksum + len3;
-		checksum = ixj_write_cid_string(j, sdmf3, checksum);
-		if(ixj_hookstate(j) & 1)
-			break;
-
-		checksum %= 256;
-		checksum ^= 0xFF;
-		checksum += 1;
-
-		ixj_write_cid_byte(j, (char) checksum);
-
-		pad = j->fskdcnt % 240;
-		if (pad) {
-			pad = 240 - pad;
-		}
-		ixj_pad_fsk(j, pad);
-		break;
-	}
-
-	ixj_write_frame(j);
-}
-
-static void ixj_write_cidcw(IXJ *j)
-{
-	IXJ_TONE ti;
-
-	char sdmf1[50];
-	char sdmf2[50];
-	char sdmf3[80];
-	char mdmflen, len1, len2, len3;
-	int pad;
-
-	int checksum = 0;
-
-	if (j->dsp.low == 0x20 || j->flags.cidplay)
-		return;
-
-	j->fskz = j->fskphase = j->fskcnt = j->fskdcnt = 0;
-	j->cidsize = j->cidcnt = 0;
-
-	ixj_fsk_alloc(j);
-
-	j->flags.cidcw_ack = 0;
-
-	ti.tone_index = 23;
-	ti.gain0 = 1;
-	ti.freq0 = hz440;
-	ti.gain1 = 0;
-	ti.freq1 = 0;
-	ixj_init_tone(j, &ti);
-
-	ixj_set_tone_on(1500, j);
-	ixj_set_tone_off(32, j);
-	if(ixjdebug & 0x0200) {
-		printk("IXJ cidcw phone%d first tone start at %ld\n", j->board, jiffies);
-	}
-	ixj_play_tone(j, 23);
-
-	clear_bit(j->board, &j->busyflags);
-	while(j->tone_state)
-		schedule_timeout_interruptible(1);
-	while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0)
-		schedule_timeout_interruptible(1);
-	if(ixjdebug & 0x0200) {
-		printk("IXJ cidcw phone%d first tone end at %ld\n", j->board, jiffies);
-	}
-
-	ti.tone_index = 24;
-	ti.gain0 = 1;
-	ti.freq0 = hz2130;
-	ti.gain1 = 0;
-	ti.freq1 = hz2750;
-	ixj_init_tone(j, &ti);
-
-	ixj_set_tone_off(10, j);
-	ixj_set_tone_on(600, j);
-	if(ixjdebug & 0x0200) {
-		printk("IXJ cidcw phone%d second tone start at %ld\n", j->board, jiffies);
-	}
-	ixj_play_tone(j, 24);
-
-	clear_bit(j->board, &j->busyflags);
-	while(j->tone_state)
-		schedule_timeout_interruptible(1);
-	while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0)
-		schedule_timeout_interruptible(1);
-	if(ixjdebug & 0x0200) {
-		printk("IXJ cidcw phone%d sent second tone at %ld\n", j->board, jiffies);
-	}
-
-	j->cidcw_wait = jiffies + ((50 * hertz) / 100);
-
-	clear_bit(j->board, &j->busyflags);
-	while(!j->flags.cidcw_ack && time_before(jiffies, j->cidcw_wait))
-		schedule_timeout_interruptible(1);
-	while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0)
-		schedule_timeout_interruptible(1);
-	j->cidcw_wait = 0;
-	if(!j->flags.cidcw_ack) {
-		if(ixjdebug & 0x0200) {
-			printk("IXJ cidcw phone%d did not receive ACK from display %ld\n", j->board, jiffies);
-		}
-		ixj_post_cid(j);
-		if(j->cid_play_flag) {
-			wake_up_interruptible(&j->write_q);	/* Wake any blocked readers */
-		}
-		return;
-	} else {
-		ixj_pre_cid(j);
-	}
-	j->flags.cidcw_ack = 0;
-	strcpy(sdmf1, j->cid_send.month);
-	strcat(sdmf1, j->cid_send.day);
-	strcat(sdmf1, j->cid_send.hour);
-	strcat(sdmf1, j->cid_send.min);
-	strcpy(sdmf2, j->cid_send.number);
-	strcpy(sdmf3, j->cid_send.name);
-
-	len1 = strlen(sdmf1);
-	len2 = strlen(sdmf2);
-	len3 = strlen(sdmf3);
-	mdmflen = len1 + len2 + len3 + 6;
-
-	ixj_write_cidcw_seize(j);
-
-	ixj_write_cid_byte(j, 0x80);
-	checksum = 0x80;
-	ixj_write_cid_byte(j, mdmflen);
-	checksum = checksum + mdmflen;
-
-	ixj_write_cid_byte(j, 0x01);
-	checksum = checksum + 0x01;
-	ixj_write_cid_byte(j, len1);
-	checksum = checksum + len1;
-	checksum = ixj_write_cid_string(j, sdmf1, checksum);
-
-	ixj_write_cid_byte(j, 0x02);
-	checksum = checksum + 0x02;
-	ixj_write_cid_byte(j, len2);
-	checksum = checksum + len2;
-	checksum = ixj_write_cid_string(j, sdmf2, checksum);
-
-	ixj_write_cid_byte(j, 0x07);
-	checksum = checksum + 0x07;
-	ixj_write_cid_byte(j, len3);
-	checksum = checksum + len3;
-	checksum = ixj_write_cid_string(j, sdmf3, checksum);
-
-	checksum %= 256;
-	checksum ^= 0xFF;
-	checksum += 1;
-
-	ixj_write_cid_byte(j, (char) checksum);
-
-	pad = j->fskdcnt % 240;
-	if (pad) {
-		pad = 240 - pad;
-	}
-	ixj_pad_fsk(j, pad);
-	if(ixjdebug & 0x0200) {
-		printk("IXJ cidcw phone%d sent FSK data at %ld\n", j->board, jiffies);
-	}
-}
-
-static void ixj_write_vmwi(IXJ *j, int msg)
-{
-	char mdmflen;
-	int pad;
-
-	int checksum = 0;
-
-	if (j->dsp.low == 0x20 || j->flags.cidplay)
-		return;
-
-	j->fskz = j->fskphase = j->fskcnt = j->fskdcnt = 0;
-	j->cidsize = j->cidcnt = 0;
-
-	ixj_fsk_alloc(j);
-
-	mdmflen = 3;
-
-	if (j->port == PORT_POTS)
-		SLIC_SetState(PLD_SLIC_STATE_OHT, j);
-
-	ixj_write_cid_seize(j);
-
-	ixj_write_cid_byte(j, 0x82);
-	checksum = 0x82;
-	ixj_write_cid_byte(j, mdmflen);
-	checksum = checksum + mdmflen;
-
-	ixj_write_cid_byte(j, 0x0B);
-	checksum = checksum + 0x0B;
-	ixj_write_cid_byte(j, 1);
-	checksum = checksum + 1;
-
-	if(msg) {
-		ixj_write_cid_byte(j, 0xFF);
-		checksum = checksum + 0xFF;
-	}
-	else {
-		ixj_write_cid_byte(j, 0x00);
-		checksum = checksum + 0x00;
-	}
-
-	checksum %= 256;
-	checksum ^= 0xFF;
-	checksum += 1;
-
-	ixj_write_cid_byte(j, (char) checksum);
-
-	pad = j->fskdcnt % 240;
-	if (pad) {
-		pad = 240 - pad;
-	}
-	ixj_pad_fsk(j, pad);
-}
-
-static void ixj_write_frame(IXJ *j)
-{
-	int cnt, frame_count, dly;
-	IXJ_WORD dat;
-
-	frame_count = 0;
-	if(j->flags.cidplay) {
-		for(cnt = 0; cnt < 480; cnt++) {
-			if (!(cnt % 16) && !IsTxReady(j)) {
-				dly = 0;
-				while (!IsTxReady(j)) {
-					if (dly++ > 5) {
-						dly = 0;
-						break;
-					}
-					udelay(10);
-				}
-			}
-			dat.word = j->fskdata[j->cidcnt++];
-			outb_p(dat.bytes.low, j->DSPbase + 0x0C);
-			outb_p(dat.bytes.high, j->DSPbase + 0x0D);
-			cnt++;
-		}
-		if(j->cidcnt >= j->fskdcnt) {
-			ixj_post_cid(j);
-		}
-		/* This may seem rude, but if we just played one frame of FSK data for CallerID
-		   and there is real audio data in the buffer, we need to throw it away because
-		   we just used it's time slot */
-		if (j->write_buffer_rp > j->write_buffer_wp) {
-			j->write_buffer_rp += j->cid_play_frame_size * 2;
-			if (j->write_buffer_rp >= j->write_buffer_end) {
-				j->write_buffer_rp = j->write_buffer;
-			}
-			j->write_buffers_empty++;
-			wake_up_interruptible(&j->write_q);	/* Wake any blocked writers */
-
-			wake_up_interruptible(&j->poll_q);	/* Wake any blocked selects */
-		}
-	} else if (j->write_buffer && j->write_buffers_empty < 1) {
-		if (j->write_buffer_wp > j->write_buffer_rp) {
-			frame_count =
-			    (j->write_buffer_wp - j->write_buffer_rp) / (j->play_frame_size * 2);
-		}
-		if (j->write_buffer_rp > j->write_buffer_wp) {
-			frame_count =
-			    (j->write_buffer_wp - j->write_buffer) / (j->play_frame_size * 2) +
-			    (j->write_buffer_end - j->write_buffer_rp) / (j->play_frame_size * 2);
-		}
-		if (frame_count >= 1) {
-			if (j->ver.low == 0x12 && j->play_mode && j->flags.play_first_frame) {
-				BYTES blankword;
-
-				switch (j->play_mode) {
-				case PLAYBACK_MODE_ULAW:
-				case PLAYBACK_MODE_ALAW:
-					blankword.low = blankword.high = 0xFF;
-					break;
-				case PLAYBACK_MODE_8LINEAR:
-				case PLAYBACK_MODE_16LINEAR:
-				default:
-					blankword.low = blankword.high = 0x00;
-					break;
-				case PLAYBACK_MODE_8LINEAR_WSS:
-					blankword.low = blankword.high = 0x80;
-					break;
-				}
-				for (cnt = 0; cnt < 16; cnt++) {
-					if (!(cnt % 16) && !IsTxReady(j)) {
-						dly = 0;
-						while (!IsTxReady(j)) {
-							if (dly++ > 5) {
-								dly = 0;
-								break;
-							}
-							udelay(10);
-						}
-					}
-					outb_p((blankword.low), j->DSPbase + 0x0C);
-					outb_p((blankword.high), j->DSPbase + 0x0D);
-				}
-				j->flags.play_first_frame = 0;
-			} else	if (j->play_codec == G723_63 && j->flags.play_first_frame) {
-				for (cnt = 0; cnt < 24; cnt++) {
-					BYTES blankword;
-
-					if(cnt == 12) {
-						blankword.low = 0x02;
-						blankword.high = 0x00;
-					}
-					else {
-						blankword.low = blankword.high = 0x00;
-					}
-					if (!(cnt % 16) && !IsTxReady(j)) {
-						dly = 0;
-						while (!IsTxReady(j)) {
-							if (dly++ > 5) {
-								dly = 0;
-								break;
-							}
-							udelay(10);
-						}
-					}
-					outb_p((blankword.low), j->DSPbase + 0x0C);
-					outb_p((blankword.high), j->DSPbase + 0x0D);
-				}
-				j->flags.play_first_frame = 0;
-			}
-			for (cnt = 0; cnt < j->play_frame_size * 2; cnt += 2) {
-				if (!(cnt % 16) && !IsTxReady(j)) {
-					dly = 0;
-					while (!IsTxReady(j)) {
-						if (dly++ > 5) {
-							dly = 0;
-							break;
-						}
-						udelay(10);
-					}
-				}
-			/* Add word 0 to G.729 frames for the 8021.  Right now we don't do VAD/CNG  */
-				if (j->play_codec == G729 && (cnt == 0 || cnt == 10 || cnt == 20)) {
-					if (j->write_buffer_rp[cnt] == 0 &&
-					    j->write_buffer_rp[cnt + 1] == 0 &&
-					    j->write_buffer_rp[cnt + 2] == 0 &&
-					    j->write_buffer_rp[cnt + 3] == 0 &&
-					    j->write_buffer_rp[cnt + 4] == 0 &&
-					    j->write_buffer_rp[cnt + 5] == 0 &&
-					    j->write_buffer_rp[cnt + 6] == 0 &&
-					    j->write_buffer_rp[cnt + 7] == 0 &&
-					    j->write_buffer_rp[cnt + 8] == 0 &&
-					    j->write_buffer_rp[cnt + 9] == 0) {
-					/* someone is trying to write silence lets make this a type 0 frame. */
-						outb_p(0x00, j->DSPbase + 0x0C);
-						outb_p(0x00, j->DSPbase + 0x0D);
-					} else {
-					/* so all other frames are type 1. */
-						outb_p(0x01, j->DSPbase + 0x0C);
-						outb_p(0x00, j->DSPbase + 0x0D);
-					}
-				}
-				outb_p(*(j->write_buffer_rp + cnt), j->DSPbase + 0x0C);
-				outb_p(*(j->write_buffer_rp + cnt + 1), j->DSPbase + 0x0D);
-				*(j->write_buffer_rp + cnt) = 0;
-				*(j->write_buffer_rp + cnt + 1) = 0;
-			}
-			j->write_buffer_rp += j->play_frame_size * 2;
-			if (j->write_buffer_rp >= j->write_buffer_end) {
-				j->write_buffer_rp = j->write_buffer;
-			}
-			j->write_buffers_empty++;
-			wake_up_interruptible(&j->write_q);	/* Wake any blocked writers */
-
-			wake_up_interruptible(&j->poll_q);	/* Wake any blocked selects */
-
-			++j->frameswritten;
-		}
-	} else {
-		j->drybuffer++;
-	}
-	if(j->ixj_signals[SIG_WRITE_READY]) {
-		ixj_kill_fasync(j, SIG_WRITE_READY, POLL_OUT);
-	}
-}
-
-static int idle(IXJ *j)
-{
-	if (ixj_WriteDSPCommand(0x0000, j))		/* DSP Idle */
-
-		return 0;
-
-	if (j->ssr.high || j->ssr.low) {
-		return 0;
-	} else {
-		j->play_mode = -1;
-		j->flags.playing = 0;
-		j->rec_mode = -1;
-		j->flags.recording = 0;
-		return 1;
-        }
-}
-
-static int set_base_frame(IXJ *j, int size)
-{
-	unsigned short cmd;
-	int cnt;
-
-	idle(j);
-	j->cid_play_aec_level = j->aec_level;
-	aec_stop(j);
-	for (cnt = 0; cnt < 10; cnt++) {
-		if (idle(j))
-			break;
-	}
-	if (j->ssr.high || j->ssr.low)
-		return -1;
-	if (j->dsp.low != 0x20) {
-		switch (size) {
-		case 30:
-			cmd = 0x07F0;
-			/* Set Base Frame Size to 240 pg9-10 8021 */
-			break;
-		case 20:
-			cmd = 0x07A0;
-			/* Set Base Frame Size to 160 pg9-10 8021 */
-			break;
-		case 10:
-			cmd = 0x0750;
-			/* Set Base Frame Size to 80 pg9-10 8021 */
-			break;
-		default:
-			return -1;
-		}
-	} else {
-		if (size == 30)
-			return size;
-		else
-			return -1;
-	}
-	if (ixj_WriteDSPCommand(cmd, j)) {
-		j->baseframe.high = j->baseframe.low = 0xFF;
-		return -1;
-	} else {
-		j->baseframe.high = j->ssr.high;
-		j->baseframe.low = j->ssr.low;
-		/* If the status returned is 0x0000 (pg9-9 8021) the call failed */
-		if(j->baseframe.high == 0x00 && j->baseframe.low == 0x00) {
-			return -1;
-		}
-	}
-	ixj_aec_start(j, j->cid_play_aec_level);
-	return size;
-}
-
-static int set_rec_codec(IXJ *j, int rate)
-{
-	int retval = 0;
-
-	j->rec_codec = rate;
-
-	switch (rate) {
-	case G723_63:
-		if (j->ver.low != 0x12 || ixj_convert_loaded) {
-			j->rec_frame_size = 12;
-			j->rec_mode = 0;
-		} else {
-			retval = 1;
-		}
-		break;
-	case G723_53:
-		if (j->ver.low != 0x12 || ixj_convert_loaded) {
-			j->rec_frame_size = 10;
-			j->rec_mode = 0;
-		} else {
-			retval = 1;
-		}
-		break;
-	case TS85:
-		if (j->dsp.low == 0x20 || j->flags.ts85_loaded) {
-			j->rec_frame_size = 16;
-			j->rec_mode = 0;
-		} else {
-			retval = 1;
-		}
-		break;
-	case TS48:
-		if (j->ver.low != 0x12 || ixj_convert_loaded) {
-			j->rec_frame_size = 9;
-			j->rec_mode = 0;
-		} else {
-			retval = 1;
-		}
-		break;
-	case TS41:
-		if (j->ver.low != 0x12 || ixj_convert_loaded) {
-			j->rec_frame_size = 8;
-			j->rec_mode = 0;
-		} else {
-			retval = 1;
-		}
-		break;
-	case G728:
-		if (j->dsp.low != 0x20) {
-			j->rec_frame_size = 48;
-			j->rec_mode = 0;
-		} else {
-			retval = 1;
-		}
-		break;
-	case G729:
-		if (j->dsp.low != 0x20) {
-			if (!j->flags.g729_loaded) {
-				retval = 1;
-				break;
-			}
-			switch (j->baseframe.low) {
-			case 0xA0:
-				j->rec_frame_size = 10;
-				break;
-			case 0x50:
-				j->rec_frame_size = 5;
-				break;
-			default:
-				j->rec_frame_size = 15;
-				break;
-			}
-			j->rec_mode = 0;
-		} else {
-			retval = 1;
-		}
-		break;
-	case G729B:
-		if (j->dsp.low != 0x20) {
-			if (!j->flags.g729_loaded) {
-				retval = 1;
-				break;
-			}
-			switch (j->baseframe.low) {
-			case 0xA0:
-				j->rec_frame_size = 12;
-				break;
-			case 0x50:
-				j->rec_frame_size = 6;
-				break;
-			default:
-				j->rec_frame_size = 18;
-				break;
-			}
-			j->rec_mode = 0;
-		} else {
-			retval = 1;
-		}
-		break;
-	case ULAW:
-		switch (j->baseframe.low) {
-		case 0xA0:
-			j->rec_frame_size = 80;
-			break;
-		case 0x50:
-			j->rec_frame_size = 40;
-			break;
-		default:
-			j->rec_frame_size = 120;
-			break;
-		}
-		j->rec_mode = 4;
-		break;
-	case ALAW:
-		switch (j->baseframe.low) {
-		case 0xA0:
-			j->rec_frame_size = 80;
-			break;
-		case 0x50:
-			j->rec_frame_size = 40;
-			break;
-		default:
-			j->rec_frame_size = 120;
-			break;
-		}
-		j->rec_mode = 4;
-		break;
-	case LINEAR16:
-		switch (j->baseframe.low) {
-		case 0xA0:
-			j->rec_frame_size = 160;
-			break;
-		case 0x50:
-			j->rec_frame_size = 80;
-			break;
-		default:
-			j->rec_frame_size = 240;
-			break;
-		}
-		j->rec_mode = 5;
-		break;
-	case LINEAR8:
-		switch (j->baseframe.low) {
-		case 0xA0:
-			j->rec_frame_size = 80;
-			break;
-		case 0x50:
-			j->rec_frame_size = 40;
-			break;
-		default:
-			j->rec_frame_size = 120;
-			break;
-		}
-		j->rec_mode = 6;
-		break;
-	case WSS:
-		switch (j->baseframe.low) {
-		case 0xA0:
-			j->rec_frame_size = 80;
-			break;
-		case 0x50:
-			j->rec_frame_size = 40;
-			break;
-		default:
-			j->rec_frame_size = 120;
-			break;
-		}
-		j->rec_mode = 7;
-		break;
-	default:
-		kfree(j->read_buffer);
-		j->rec_frame_size = 0;
-		j->rec_mode = -1;
-		j->read_buffer = NULL;
-		j->read_buffer_size = 0;
-		retval = 1;
-		break;
-	}
-	return retval;
-}
-
-static int ixj_record_start(IXJ *j)
-{
-	unsigned short cmd = 0x0000;
-
-	if (j->read_buffer) {
-		ixj_record_stop(j);
-	}
-	j->flags.recording = 1;
-	ixj_WriteDSPCommand(0x0FE0, j);	/* Put the DSP in full power mode. */
-
-	if(ixjdebug & 0x0002)
-		printk("IXJ %d Starting Record Codec %d at %ld\n", j->board, j->rec_codec, jiffies);
-
-	if (!j->rec_mode) {
-		switch (j->rec_codec) {
-		case G723_63:
-			cmd = 0x5131;
-			break;
-		case G723_53:
-			cmd = 0x5132;
-			break;
-		case TS85:
-			cmd = 0x5130;	/* TrueSpeech 8.5 */
-
-			break;
-		case TS48:
-			cmd = 0x5133;	/* TrueSpeech 4.8 */
-
-			break;
-		case TS41:
-			cmd = 0x5134;	/* TrueSpeech 4.1 */
-
-			break;
-		case G728:
-			cmd = 0x5135;
-			break;
-		case G729:
-		case G729B:
-			cmd = 0x5136;
-			break;
-		default:
-			return 1;
-		}
-		if (ixj_WriteDSPCommand(cmd, j))
-			return -1;
-	}
-	if (!j->read_buffer) {
-		if (!j->read_buffer)
-			j->read_buffer = kmalloc(j->rec_frame_size * 2, GFP_ATOMIC);
-		if (!j->read_buffer) {
-			printk("Read buffer allocation for ixj board %d failed!\n", j->board);
-			return -ENOMEM;
-		}
-	}
-	j->read_buffer_size = j->rec_frame_size * 2;
-
-	if (ixj_WriteDSPCommand(0x5102, j))		/* Set Poll sync mode */
-
-		return -1;
-
-	switch (j->rec_mode) {
-	case 0:
-		cmd = 0x1C03;	/* Record C1 */
-
-		break;
-	case 4:
-		if (j->ver.low == 0x12) {
-			cmd = 0x1E03;	/* Record C1 */
-
-		} else {
-			cmd = 0x1E01;	/* Record C1 */
-
-		}
-		break;
-	case 5:
-		if (j->ver.low == 0x12) {
-			cmd = 0x1E83;	/* Record C1 */
-
-		} else {
-			cmd = 0x1E81;	/* Record C1 */
-
-		}
-		break;
-	case 6:
-		if (j->ver.low == 0x12) {
-			cmd = 0x1F03;	/* Record C1 */
-
-		} else {
-			cmd = 0x1F01;	/* Record C1 */
-
-		}
-		break;
-	case 7:
-		if (j->ver.low == 0x12) {
-			cmd = 0x1F83;	/* Record C1 */
-		} else {
-			cmd = 0x1F81;	/* Record C1 */
-		}
-		break;
-	}
-	if (ixj_WriteDSPCommand(cmd, j))
-		return -1;
-
-	if (j->flags.playing) {
-		ixj_aec_start(j, j->aec_level);
-	}
-	return 0;
-}
-
-static void ixj_record_stop(IXJ *j)
-{
-	if (ixjdebug & 0x0002)
-		printk("IXJ %d Stopping Record Codec %d at %ld\n", j->board, j->rec_codec, jiffies);
-
-	kfree(j->read_buffer);
-	j->read_buffer = NULL;
-	j->read_buffer_size = 0;
-	if (j->rec_mode > -1) {
-		ixj_WriteDSPCommand(0x5120, j);
-		j->rec_mode = -1;
-	}
-	j->flags.recording = 0;
-}
-static void ixj_vad(IXJ *j, int arg)
-{
-	if (arg)
-		ixj_WriteDSPCommand(0x513F, j);
-	else
-		ixj_WriteDSPCommand(0x513E, j);
-}
-
-static void set_rec_depth(IXJ *j, int depth)
-{
-	if (depth > 60)
-		depth = 60;
-	if (depth < 0)
-		depth = 0;
-	ixj_WriteDSPCommand(0x5180 + depth, j);
-}
-
-static void set_dtmf_prescale(IXJ *j, int volume)
-{
-	ixj_WriteDSPCommand(0xCF07, j);
-	ixj_WriteDSPCommand(volume, j);
-}
-
-static int get_dtmf_prescale(IXJ *j)
-{
-	ixj_WriteDSPCommand(0xCF05, j);
-	return j->ssr.high << 8 | j->ssr.low;
-}
-
-static void set_rec_volume(IXJ *j, int volume)
-{
-	if(j->aec_level == AEC_AGC) {
-		if (ixjdebug & 0x0002)
-			printk(KERN_INFO "IXJ: /dev/phone%d Setting AGC Threshold to 0x%4.4x\n", j->board, volume);
-		ixj_WriteDSPCommand(0xCF96, j);
-		ixj_WriteDSPCommand(volume, j);
-	} else {
-		if (ixjdebug & 0x0002)
-			printk(KERN_INFO "IXJ: /dev/phone %d Setting Record Volume to 0x%4.4x\n", j->board, volume);
-		ixj_WriteDSPCommand(0xCF03, j);
-		ixj_WriteDSPCommand(volume, j);
-	}
-}
-
-static int set_rec_volume_linear(IXJ *j, int volume)
-{
-	int newvolume, dsprecmax;
-
-	if (ixjdebug & 0x0002)
-		printk(KERN_INFO "IXJ: /dev/phone %d Setting Linear Record Volume to 0x%4.4x\n", j->board, volume);
-	if(volume > 100 || volume < 0) {
-	  return -1;
-	}
-
-	/* This should normalize the perceived volumes between the different cards caused by differences in the hardware */
-	switch (j->cardtype) {
-	case QTI_PHONEJACK:
-		dsprecmax = 0x440;
-		break;
-	case QTI_LINEJACK:
-		dsprecmax = 0x180;
-		ixj_mixer(0x0203, j);	/*Voice Left Volume unmute 6db */
-		ixj_mixer(0x0303, j);	/*Voice Right Volume unmute 6db */
-		ixj_mixer(0x0C00, j);	/*Mono1 unmute 12db */
-		break;
-	case QTI_PHONEJACK_LITE:
-		dsprecmax = 0x4C0;
-		break;
-	case QTI_PHONEJACK_PCI:
-		dsprecmax = 0x100;
-		break;
-	case QTI_PHONECARD:
-		dsprecmax = 0x400;
-		break;
-	default:
-		return -1;
-	}
-	newvolume = (dsprecmax * volume) / 100;
-	set_rec_volume(j, newvolume);
-	return 0;
-}
-
-static int get_rec_volume(IXJ *j)
-{
-	if(j->aec_level == AEC_AGC) {
-		if (ixjdebug & 0x0002)
-			printk(KERN_INFO "Getting AGC Threshold\n");
-		ixj_WriteDSPCommand(0xCF86, j);
-		if (ixjdebug & 0x0002)
-			printk(KERN_INFO "AGC Threshold is 0x%2.2x%2.2x\n", j->ssr.high, j->ssr.low);
-		return j->ssr.high << 8 | j->ssr.low;
-	} else {
-		if (ixjdebug & 0x0002)
-			printk(KERN_INFO "Getting Record Volume\n");
-		ixj_WriteDSPCommand(0xCF01, j);
-		return j->ssr.high << 8 | j->ssr.low;
-	}
-}
-
-static int get_rec_volume_linear(IXJ *j)
-{
-	int volume, newvolume, dsprecmax;
-
-	switch (j->cardtype) {
-	case QTI_PHONEJACK:
-		dsprecmax = 0x440;
-		break;
-	case QTI_LINEJACK:
-		dsprecmax = 0x180;
-		break;
-	case QTI_PHONEJACK_LITE:
-		dsprecmax = 0x4C0;
-		break;
-	case QTI_PHONEJACK_PCI:
-		dsprecmax = 0x100;
-		break;
-	case QTI_PHONECARD:
-		dsprecmax = 0x400;
-		break;
-	default:
-		return -1;
-	}
-	volume = get_rec_volume(j);
-	newvolume = (volume * 100) / dsprecmax;
-	if(newvolume > 100)
-		newvolume = 100;
-	return newvolume;
-}
-
-static int get_rec_level(IXJ *j)
-{
-	int retval;
-
-	ixj_WriteDSPCommand(0xCF88, j);
-
-	retval = j->ssr.high << 8 | j->ssr.low;
-	retval = (retval * 256) / 240;
-	return retval;
-}
-
-static void ixj_aec_start(IXJ *j, int level)
-{
-	j->aec_level = level;
-	if (ixjdebug & 0x0002)
-		printk(KERN_INFO "AGC set = 0x%2.2x\n", j->aec_level);
-	if (!level) {
-		aec_stop(j);
-	} else {
-		if (j->rec_codec == G729 || j->play_codec == G729 || j->rec_codec == G729B || j->play_codec == G729B) {
-			ixj_WriteDSPCommand(0xE022, j);	/* Move AEC filter buffer */
-
-			ixj_WriteDSPCommand(0x0300, j);
-		}
-		ixj_WriteDSPCommand(0xB001, j);	/* AEC On */
-
-		ixj_WriteDSPCommand(0xE013, j);	/* Advanced AEC C1 */
-
-		switch (level) {
-		case AEC_LOW:
-			ixj_WriteDSPCommand(0x0000, j);	/* Advanced AEC C2 = off */
-
-			ixj_WriteDSPCommand(0xE011, j);
-			ixj_WriteDSPCommand(0xFFFF, j);
-
-			ixj_WriteDSPCommand(0xCF97, j);	/* Set AGC Enable */
-			ixj_WriteDSPCommand(0x0000, j);	/* to off */
-
-			break;
-
-		case AEC_MED:
-			ixj_WriteDSPCommand(0x0600, j);	/* Advanced AEC C2 = on medium */
-
-			ixj_WriteDSPCommand(0xE011, j);
-			ixj_WriteDSPCommand(0x0080, j);
-
-			ixj_WriteDSPCommand(0xCF97, j);	/* Set AGC Enable */
-			ixj_WriteDSPCommand(0x0000, j);	/* to off */
-
-			break;
-
-		case AEC_HIGH:
-			ixj_WriteDSPCommand(0x0C00, j);	/* Advanced AEC C2 = on high */
-
-			ixj_WriteDSPCommand(0xE011, j);
-			ixj_WriteDSPCommand(0x0080, j);
-
-			ixj_WriteDSPCommand(0xCF97, j);	/* Set AGC Enable */
-			ixj_WriteDSPCommand(0x0000, j);	/* to off */
-
-			break;
-
-		case AEC_AGC:
-                        /* First we have to put the AEC into advance auto mode so that AGC will not conflict with it */
-			ixj_WriteDSPCommand(0x0002, j);	/* Attenuation scaling factor of 2 */
-
-			ixj_WriteDSPCommand(0xE011, j);
-			ixj_WriteDSPCommand(0x0100, j);	/* Higher Threshold Floor */
-
-			ixj_WriteDSPCommand(0xE012, j);	/* Set Train and Lock */
-
-			if(j->cardtype == QTI_LINEJACK || j->cardtype == QTI_PHONECARD)
-				ixj_WriteDSPCommand(0x0224, j);
-			else
-				ixj_WriteDSPCommand(0x1224, j);
-
-			ixj_WriteDSPCommand(0xE014, j);
-			ixj_WriteDSPCommand(0x0003, j);	/* Lock threshold at 3dB */
-
-			ixj_WriteDSPCommand(0xE338, j);	/* Set Echo Suppresser Attenuation to 0dB */
-
-			/* Now we can set the AGC initial parameters and turn it on */
-			ixj_WriteDSPCommand(0xCF90, j);	/* Set AGC Minimum gain */
-			ixj_WriteDSPCommand(0x0020, j);	/* to 0.125 (-18dB) */
-
-			ixj_WriteDSPCommand(0xCF91, j);	/* Set AGC Maximum gain */
-			ixj_WriteDSPCommand(0x1000, j);	/* to 16 (24dB) */
-
-			ixj_WriteDSPCommand(0xCF92, j);	/* Set AGC start gain */
-			ixj_WriteDSPCommand(0x0800, j);	/* to 8 (+18dB) */
-
-			ixj_WriteDSPCommand(0xCF93, j);	/* Set AGC hold time */
-			ixj_WriteDSPCommand(0x1F40, j);	/* to 2 seconds (units are 250us) */
-
-			ixj_WriteDSPCommand(0xCF94, j);	/* Set AGC Attack Time Constant */
-			ixj_WriteDSPCommand(0x0005, j);	/* to 8ms */
-
-			ixj_WriteDSPCommand(0xCF95, j);	/* Set AGC Decay Time Constant */
-			ixj_WriteDSPCommand(0x000D, j);	/* to 4096ms */
-
-			ixj_WriteDSPCommand(0xCF96, j);	/* Set AGC Attack Threshold */
-			ixj_WriteDSPCommand(0x1200, j);	/* to 25% */
-
-			ixj_WriteDSPCommand(0xCF97, j);	/* Set AGC Enable */
-			ixj_WriteDSPCommand(0x0001, j);	/* to on */
-
-			break;
-
-		case AEC_AUTO:
-			ixj_WriteDSPCommand(0x0002, j);	/* Attenuation scaling factor of 2 */
-
-			ixj_WriteDSPCommand(0xE011, j);
-			ixj_WriteDSPCommand(0x0100, j);	/* Higher Threshold Floor */
-
-			ixj_WriteDSPCommand(0xE012, j);	/* Set Train and Lock */
-
-			if(j->cardtype == QTI_LINEJACK || j->cardtype == QTI_PHONECARD)
-				ixj_WriteDSPCommand(0x0224, j);
-			else
-				ixj_WriteDSPCommand(0x1224, j);
-
-			ixj_WriteDSPCommand(0xE014, j);
-			ixj_WriteDSPCommand(0x0003, j);	/* Lock threshold at 3dB */
-
-			ixj_WriteDSPCommand(0xE338, j);	/* Set Echo Suppresser Attenuation to 0dB */
-
-			break;
-		}
-	}
-}
-
-static void aec_stop(IXJ *j)
-{
-	j->aec_level = AEC_OFF;
-	if (j->rec_codec == G729 || j->play_codec == G729 || j->rec_codec == G729B || j->play_codec == G729B) {
-		ixj_WriteDSPCommand(0xE022, j);	/* Move AEC filter buffer back */
-
-		ixj_WriteDSPCommand(0x0700, j);
-	}
-	if (j->play_mode != -1 && j->rec_mode != -1)
-	{
-		ixj_WriteDSPCommand(0xB002, j);	/* AEC Stop */
-	}
-}
-
-static int set_play_codec(IXJ *j, int rate)
-{
-	int retval = 0;
-
-	j->play_codec = rate;
-
-	switch (rate) {
-	case G723_63:
-		if (j->ver.low != 0x12 || ixj_convert_loaded) {
-			j->play_frame_size = 12;
-			j->play_mode = 0;
-		} else {
-			retval = 1;
-		}
-		break;
-	case G723_53:
-		if (j->ver.low != 0x12 || ixj_convert_loaded) {
-			j->play_frame_size = 10;
-			j->play_mode = 0;
-		} else {
-			retval = 1;
-		}
-		break;
-	case TS85:
-		if (j->dsp.low == 0x20 || j->flags.ts85_loaded) {
-			j->play_frame_size = 16;
-			j->play_mode = 0;
-		} else {
-			retval = 1;
-		}
-		break;
-	case TS48:
-		if (j->ver.low != 0x12 || ixj_convert_loaded) {
-			j->play_frame_size = 9;
-			j->play_mode = 0;
-		} else {
-			retval = 1;
-		}
-		break;
-	case TS41:
-		if (j->ver.low != 0x12 || ixj_convert_loaded) {
-			j->play_frame_size = 8;
-			j->play_mode = 0;
-		} else {
-			retval = 1;
-		}
-		break;
-	case G728:
-		if (j->dsp.low != 0x20) {
-			j->play_frame_size = 48;
-			j->play_mode = 0;
-		} else {
-			retval = 1;
-		}
-		break;
-	case G729:
-		if (j->dsp.low != 0x20) {
-			if (!j->flags.g729_loaded) {
-				retval = 1;
-				break;
-			}
-			switch (j->baseframe.low) {
-			case 0xA0:
-				j->play_frame_size = 10;
-				break;
-			case 0x50:
-				j->play_frame_size = 5;
-				break;
-			default:
-				j->play_frame_size = 15;
-				break;
-			}
-			j->play_mode = 0;
-		} else {
-			retval = 1;
-		}
-		break;
-	case G729B:
-		if (j->dsp.low != 0x20) {
-			if (!j->flags.g729_loaded) {
-				retval = 1;
-				break;
-			}
-			switch (j->baseframe.low) {
-			case 0xA0:
-				j->play_frame_size = 12;
-				break;
-			case 0x50:
-				j->play_frame_size = 6;
-				break;
-			default:
-				j->play_frame_size = 18;
-				break;
-			}
-			j->play_mode = 0;
-		} else {
-			retval = 1;
-		}
-		break;
-	case ULAW:
-		switch (j->baseframe.low) {
-		case 0xA0:
-			j->play_frame_size = 80;
-			break;
-		case 0x50:
-			j->play_frame_size = 40;
-			break;
-		default:
-			j->play_frame_size = 120;
-			break;
-		}
-		j->play_mode = 2;
-		break;
-	case ALAW:
-		switch (j->baseframe.low) {
-		case 0xA0:
-			j->play_frame_size = 80;
-			break;
-		case 0x50:
-			j->play_frame_size = 40;
-			break;
-		default:
-			j->play_frame_size = 120;
-			break;
-		}
-		j->play_mode = 2;
-		break;
-	case LINEAR16:
-		switch (j->baseframe.low) {
-		case 0xA0:
-			j->play_frame_size = 160;
-			break;
-		case 0x50:
-			j->play_frame_size = 80;
-			break;
-		default:
-			j->play_frame_size = 240;
-			break;
-		}
-		j->play_mode = 6;
-		break;
-	case LINEAR8:
-		switch (j->baseframe.low) {
-		case 0xA0:
-			j->play_frame_size = 80;
-			break;
-		case 0x50:
-			j->play_frame_size = 40;
-			break;
-		default:
-			j->play_frame_size = 120;
-			break;
-		}
-		j->play_mode = 4;
-		break;
-	case WSS:
-		switch (j->baseframe.low) {
-		case 0xA0:
-			j->play_frame_size = 80;
-			break;
-		case 0x50:
-			j->play_frame_size = 40;
-			break;
-		default:
-			j->play_frame_size = 120;
-			break;
-		}
-		j->play_mode = 5;
-		break;
-	default:
-		kfree(j->write_buffer);
-		j->play_frame_size = 0;
-		j->play_mode = -1;
-		j->write_buffer = NULL;
-		j->write_buffer_size = 0;
-		retval = 1;
-		break;
-	}
-	return retval;
-}
-
-static int ixj_play_start(IXJ *j)
-{
-	unsigned short cmd = 0x0000;
-
-	if (j->write_buffer) {
-		ixj_play_stop(j);
-	}
-
-	if(ixjdebug & 0x0002)
-		printk("IXJ %d Starting Play Codec %d at %ld\n", j->board, j->play_codec, jiffies);
-
-	j->flags.playing = 1;
-	ixj_WriteDSPCommand(0x0FE0, j);	/* Put the DSP in full power mode. */
-
-	j->flags.play_first_frame = 1;
-	j->drybuffer = 0;
-
-	if (!j->play_mode) {
-		switch (j->play_codec) {
-		case G723_63:
-			cmd = 0x5231;
-			break;
-		case G723_53:
-			cmd = 0x5232;
-			break;
-		case TS85:
-			cmd = 0x5230;	/* TrueSpeech 8.5 */
-
-			break;
-		case TS48:
-			cmd = 0x5233;	/* TrueSpeech 4.8 */
-
-			break;
-		case TS41:
-			cmd = 0x5234;	/* TrueSpeech 4.1 */
-
-			break;
-		case G728:
-			cmd = 0x5235;
-			break;
-		case G729:
-		case G729B:
-			cmd = 0x5236;
-			break;
-		default:
-			return 1;
-		}
-		if (ixj_WriteDSPCommand(cmd, j))
-			return -1;
-	}
-	j->write_buffer = kmalloc(j->play_frame_size * 2, GFP_ATOMIC);
-	if (!j->write_buffer) {
-		printk("Write buffer allocation for ixj board %d failed!\n", j->board);
-		return -ENOMEM;
-	}
-/*	j->write_buffers_empty = 2; */
-	j->write_buffers_empty = 1;
-	j->write_buffer_size = j->play_frame_size * 2;
-	j->write_buffer_end = j->write_buffer + j->play_frame_size * 2;
-	j->write_buffer_rp = j->write_buffer_wp = j->write_buffer;
-
-	if (ixj_WriteDSPCommand(0x5202, j))		/* Set Poll sync mode */
-
-		return -1;
-
-	switch (j->play_mode) {
-	case 0:
-		cmd = 0x2C03;
-		break;
-	case 2:
-		if (j->ver.low == 0x12) {
-			cmd = 0x2C23;
-		} else {
-			cmd = 0x2C21;
-		}
-		break;
-	case 4:
-		if (j->ver.low == 0x12) {
-			cmd = 0x2C43;
-		} else {
-			cmd = 0x2C41;
-		}
-		break;
-	case 5:
-		if (j->ver.low == 0x12) {
-			cmd = 0x2C53;
-		} else {
-			cmd = 0x2C51;
-		}
-		break;
-	case 6:
-		if (j->ver.low == 0x12) {
-			cmd = 0x2C63;
-		} else {
-			cmd = 0x2C61;
-		}
-		break;
-	}
-	if (ixj_WriteDSPCommand(cmd, j))
-		return -1;
-
-	if (ixj_WriteDSPCommand(0x2000, j))		/* Playback C2 */
-		return -1;
-
-	if (ixj_WriteDSPCommand(0x2000 + j->play_frame_size, j))	/* Playback C3 */
-		return -1;
-
-	if (j->flags.recording) {
-		ixj_aec_start(j, j->aec_level);
-	}
-
-	return 0;
-}
-
-static void ixj_play_stop(IXJ *j)
-{
-	if (ixjdebug & 0x0002)
-		printk("IXJ %d Stopping Play Codec %d at %ld\n", j->board, j->play_codec, jiffies);
-
-	kfree(j->write_buffer);
-	j->write_buffer = NULL;
-	j->write_buffer_size = 0;
-	if (j->play_mode > -1) {
-		ixj_WriteDSPCommand(0x5221, j);	/* Stop playback and flush buffers.  8022 reference page 9-40 */
-
-		j->play_mode = -1;
-	}
-	j->flags.playing = 0;
-}
-
-static inline int get_play_level(IXJ *j)
-{
-	int retval;
-
-	ixj_WriteDSPCommand(0xCF8F, j); /* 8022 Reference page 9-38 */
-	return j->ssr.high << 8 | j->ssr.low;
-	retval = j->ssr.high << 8 | j->ssr.low;
-	retval = (retval * 256) / 240;
-	return retval;
-}
-
-static unsigned int ixj_poll(struct file *file_p, poll_table * wait)
-{
-	unsigned int mask = 0;
-
-	IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
-
-	poll_wait(file_p, &(j->poll_q), wait);
-	if (j->read_buffer_ready > 0)
-		mask |= POLLIN | POLLRDNORM;	/* readable */
-	if (j->write_buffers_empty > 0)
-		mask |= POLLOUT | POLLWRNORM;	/* writable */
-	if (j->ex.bytes)
-		mask |= POLLPRI;
-	return mask;
-}
-
-static int ixj_play_tone(IXJ *j, char tone)
-{
-	if (!j->tone_state) {
-		if(ixjdebug & 0x0002) {
-			printk("IXJ %d starting tone %d at %ld\n", j->board, tone, jiffies);
-		}
-		if (j->dsp.low == 0x20) {
-			idle(j);
-		}
-		j->tone_start_jif = jiffies;
-
-		j->tone_state = 1;
-	}
-
-	j->tone_index = tone;
-	if (ixj_WriteDSPCommand(0x6000 + j->tone_index, j))
-		return -1;
-
-	return 0;
-}
-
-static int ixj_set_tone_on(unsigned short arg, IXJ *j)
-{
-	j->tone_on_time = arg;
-
-	if (ixj_WriteDSPCommand(0x6E04, j))		/* Set Tone On Period */
-
-		return -1;
-
-	if (ixj_WriteDSPCommand(arg, j))
-		return -1;
-
-	return 0;
-}
-
-static int SCI_WaitHighSCI(IXJ *j)
-{
-	int cnt;
-
-	j->pld_scrr.byte = inb_p(j->XILINXbase);
-	if (!j->pld_scrr.bits.sci) {
-		for (cnt = 0; cnt < 10; cnt++) {
-			udelay(32);
-			j->pld_scrr.byte = inb_p(j->XILINXbase);
-
-			if ((j->pld_scrr.bits.sci))
-				return 1;
-		}
-		if (ixjdebug & 0x0001)
-			printk(KERN_INFO "SCI Wait High failed %x\n", j->pld_scrr.byte);
-		return 0;
-	} else
-		return 1;
-}
-
-static int SCI_WaitLowSCI(IXJ *j)
-{
-	int cnt;
-
-	j->pld_scrr.byte = inb_p(j->XILINXbase);
-	if (j->pld_scrr.bits.sci) {
-		for (cnt = 0; cnt < 10; cnt++) {
-			udelay(32);
-			j->pld_scrr.byte = inb_p(j->XILINXbase);
-
-			if (!(j->pld_scrr.bits.sci))
-				return 1;
-		}
-		if (ixjdebug & 0x0001)
-			printk(KERN_INFO "SCI Wait Low failed %x\n", j->pld_scrr.byte);
-		return 0;
-	} else
-		return 1;
-}
-
-static int SCI_Control(IXJ *j, int control)
-{
-	switch (control) {
-	case SCI_End:
-		j->pld_scrw.bits.c0 = 0;	/* Set PLD Serial control interface */
-
-		j->pld_scrw.bits.c1 = 0;	/* to no selection */
-
-		break;
-	case SCI_Enable_DAA:
-		j->pld_scrw.bits.c0 = 1;	/* Set PLD Serial control interface */
-
-		j->pld_scrw.bits.c1 = 0;	/* to write to DAA */
-
-		break;
-	case SCI_Enable_Mixer:
-		j->pld_scrw.bits.c0 = 0;	/* Set PLD Serial control interface */
-
-		j->pld_scrw.bits.c1 = 1;	/* to write to mixer */
-
-		break;
-	case SCI_Enable_EEPROM:
-		j->pld_scrw.bits.c0 = 1;	/* Set PLD Serial control interface */
-
-		j->pld_scrw.bits.c1 = 1;	/* to write to EEPROM */
-
-		break;
-	default:
-		return 0;
-		break;
-	}
-	outb_p(j->pld_scrw.byte, j->XILINXbase);
-
-	switch (control) {
-	case SCI_End:
-		return 1;
-		break;
-	case SCI_Enable_DAA:
-	case SCI_Enable_Mixer:
-	case SCI_Enable_EEPROM:
-		if (!SCI_WaitHighSCI(j))
-			return 0;
-		break;
-	default:
-		return 0;
-		break;
-	}
-	return 1;
-}
-
-static int SCI_Prepare(IXJ *j)
-{
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-
-	if (!SCI_WaitLowSCI(j))
-		return 0;
-
-	return 1;
-}
-
-static int ixj_get_mixer(long val, IXJ *j)
-{
-	int reg = (val & 0x1F00) >> 8;
-        return j->mix.vol[reg];
-}
-
-static int ixj_mixer(long val, IXJ *j)
-{
-	BYTES bytes;
-
-	bytes.high = (val & 0x1F00) >> 8;
-	bytes.low = val & 0x00FF;
-
-        /* save mixer value so we can get back later on */
-        j->mix.vol[bytes.high] = bytes.low;
-
-	outb_p(bytes.high & 0x1F, j->XILINXbase + 0x03);	/* Load Mixer Address */
-
-	outb_p(bytes.low, j->XILINXbase + 0x02);	/* Load Mixer Data */
-
-	SCI_Control(j, SCI_Enable_Mixer);
-
-	SCI_Control(j, SCI_End);
-
-	return 0;
-}
-
-static int daa_load(BYTES * p_bytes, IXJ *j)
-{
-	outb_p(p_bytes->high, j->XILINXbase + 0x03);
-	outb_p(p_bytes->low, j->XILINXbase + 0x02);
-	if (!SCI_Control(j, SCI_Enable_DAA))
-		return 0;
-	else
-		return 1;
-}
-
-static int ixj_daa_cr4(IXJ *j, char reg)
-{
-	BYTES bytes;
-
-	switch (j->daa_mode) {
-	case SOP_PU_SLEEP:
-		bytes.high = 0x14;
-		break;
-	case SOP_PU_RINGING:
-		bytes.high = 0x54;
-		break;
-	case SOP_PU_CONVERSATION:
-		bytes.high = 0x94;
-		break;
-	case SOP_PU_PULSEDIALING:
-		bytes.high = 0xD4;
-		break;
-	}
-
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = reg;
-
-	switch (j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGX) {
-	case 0:
-		j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 0;
-		break;
-	case 1:
-		j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 2;
-		break;
-	case 2:
-		j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 1;
-		break;
-	case 3:
-		j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.bitreg.AGR_Z = 3;
-		break;
-	}
-
-	bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg;
-
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Prepare(j))
-		return 0;
-
-	return 1;
-}
-
-static char daa_int_read(IXJ *j)
-{
-	BYTES bytes;
-
-	if (!SCI_Prepare(j))
-		return 0;
-
-	bytes.high = 0x38;
-	bytes.low = 0x00;
-	outb_p(bytes.high, j->XILINXbase + 0x03);
-	outb_p(bytes.low, j->XILINXbase + 0x02);
-
-	if (!SCI_Control(j, SCI_Enable_DAA))
-		return 0;
-
-	bytes.high = inb_p(j->XILINXbase + 0x03);
-	bytes.low = inb_p(j->XILINXbase + 0x02);
-	if (bytes.low != ALISDAA_ID_BYTE) {
-		if (ixjdebug & 0x0001)
-			printk("Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low);
-		return 0;
-	}
-	if (!SCI_Control(j, SCI_Enable_DAA))
-		return 0;
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-
-	bytes.high = inb_p(j->XILINXbase + 0x03);
-	bytes.low = inb_p(j->XILINXbase + 0x02);
-
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.reg = bytes.high;
-
-	return 1;
-}
-
-static char daa_CR_read(IXJ *j, int cr)
-{
-	IXJ_WORD wdata;
-	BYTES bytes;
-
-	if (!SCI_Prepare(j))
-		return 0;
-
-	switch (j->daa_mode) {
-	case SOP_PU_SLEEP:
-		bytes.high = 0x30 + cr;
-		break;
-	case SOP_PU_RINGING:
-		bytes.high = 0x70 + cr;
-		break;
-	case SOP_PU_CONVERSATION:
-		bytes.high = 0xB0 + cr;
-		break;
-	case SOP_PU_PULSEDIALING:
-	default:
-		bytes.high = 0xF0 + cr;
-		break;
-	}
-
-	bytes.low = 0x00;
-
-	outb_p(bytes.high, j->XILINXbase + 0x03);
-	outb_p(bytes.low, j->XILINXbase + 0x02);
-
-	if (!SCI_Control(j, SCI_Enable_DAA))
-		return 0;
-
-	bytes.high = inb_p(j->XILINXbase + 0x03);
-	bytes.low = inb_p(j->XILINXbase + 0x02);
-	if (bytes.low != ALISDAA_ID_BYTE) {
-		if (ixjdebug & 0x0001)
-			printk("Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low);
-		return 0;
-	}
-	if (!SCI_Control(j, SCI_Enable_DAA))
-		return 0;
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-
-	wdata.word = inw_p(j->XILINXbase + 0x02);
-
-	switch(cr){
-		case 5:
-			j->m_DAAShadowRegs.SOP_REGS.SOP.cr5.reg = wdata.bytes.high;
-			break;
-		case 4:
-			j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = wdata.bytes.high;
-			break;
-		case 3:
-			j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = wdata.bytes.high;
-			break;
-		case 2:
-			j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = wdata.bytes.high;
-			break;
-		case 1:
-			j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = wdata.bytes.high;
-			break;
-		case 0:
-			j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = wdata.bytes.high;
-			break;
-		default:
-			return 0;
-	}
-	return 1;
-}
-
-static int ixj_daa_cid_reset(IXJ *j)
-{
-	int i;
-	BYTES bytes;
-
-	if (ixjdebug & 0x0002)
-		printk("DAA Clearing CID ram\n");
-
-	if (!SCI_Prepare(j))
-		return 0;
-
-	bytes.high = 0x58;
-	bytes.low = 0x00;
-	outb_p(bytes.high, j->XILINXbase + 0x03);
-	outb_p(bytes.low, j->XILINXbase + 0x02);
-
-	if (!SCI_Control(j, SCI_Enable_DAA))
-		return 0;
-
-	if (!SCI_WaitHighSCI(j))
-		return 0;
-
-	for (i = 0; i < ALISDAA_CALLERID_SIZE - 1; i += 2) {
-		bytes.high = bytes.low = 0x00;
-		outb_p(bytes.high, j->XILINXbase + 0x03);
-
-		if (i < ALISDAA_CALLERID_SIZE - 1)
-			outb_p(bytes.low, j->XILINXbase + 0x02);
-
-		if (!SCI_Control(j, SCI_Enable_DAA))
-			return 0;
-
-		if (!SCI_WaitHighSCI(j))
-			return 0;
-
-	}
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-
-	if (ixjdebug & 0x0002)
-		printk("DAA CID ram cleared\n");
-
-	return 1;
-}
-
-static int ixj_daa_cid_read(IXJ *j)
-{
-	int i;
-	BYTES bytes;
-	char CID[ALISDAA_CALLERID_SIZE];
-	bool mContinue;
-	char *pIn, *pOut;
-
-	if (!SCI_Prepare(j))
-		return 0;
-
-	bytes.high = 0x78;
-	bytes.low = 0x00;
-	outb_p(bytes.high, j->XILINXbase + 0x03);
-	outb_p(bytes.low, j->XILINXbase + 0x02);
-
-	if (!SCI_Control(j, SCI_Enable_DAA))
-		return 0;
-
-	if (!SCI_WaitHighSCI(j))
-		return 0;
-
-	bytes.high = inb_p(j->XILINXbase + 0x03);
-	bytes.low = inb_p(j->XILINXbase + 0x02);
-	if (bytes.low != ALISDAA_ID_BYTE) {
-		if (ixjdebug & 0x0001)
-			printk("DAA Get Version Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low);
-		return 0;
-	}
-	for (i = 0; i < ALISDAA_CALLERID_SIZE; i += 2) {
-		bytes.high = bytes.low = 0x00;
-		outb_p(bytes.high, j->XILINXbase + 0x03);
-		outb_p(bytes.low, j->XILINXbase + 0x02);
-
-		if (!SCI_Control(j, SCI_Enable_DAA))
-			return 0;
-
-		if (!SCI_WaitHighSCI(j))
-			return 0;
-
-		CID[i + 0] = inb_p(j->XILINXbase + 0x03);
-		CID[i + 1] = inb_p(j->XILINXbase + 0x02);
-	}
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-
-	pIn = CID;
-	pOut = j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID;
-	mContinue = true;
-	while (mContinue) {
-		if ((pIn[1] & 0x03) == 0x01) {
-			pOut[0] = pIn[0];
-		}
-		if ((pIn[2] & 0x0c) == 0x04) {
-			pOut[1] = ((pIn[2] & 0x03) << 6) | ((pIn[1] & 0xfc) >> 2);
-		}
-		if ((pIn[3] & 0x30) == 0x10) {
-			pOut[2] = ((pIn[3] & 0x0f) << 4) | ((pIn[2] & 0xf0) >> 4);
-		}
-		if ((pIn[4] & 0xc0) == 0x40) {
-			pOut[3] = ((pIn[4] & 0x3f) << 2) | ((pIn[3] & 0xc0) >> 6);
-		} else {
-			mContinue = false;
-		}
-		pIn += 5, pOut += 4;
-	}
-	memset(&j->cid, 0, sizeof(PHONE_CID));
-	pOut = j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID;
-	pOut += 4;
-	strncpy(j->cid.month, pOut, 2);
-	pOut += 2;
-	strncpy(j->cid.day, pOut, 2);
-	pOut += 2;
-	strncpy(j->cid.hour, pOut, 2);
-	pOut += 2;
-	strncpy(j->cid.min, pOut, 2);
-	pOut += 3;
-	j->cid.numlen = *pOut;
-	pOut += 1;
-	strncpy(j->cid.number, pOut, j->cid.numlen);
-	pOut += j->cid.numlen + 1;
-	j->cid.namelen = *pOut;
-	pOut += 1;
-	strncpy(j->cid.name, pOut, j->cid.namelen);
-
-	ixj_daa_cid_reset(j);
-	return 1;
-}
-
-static char daa_get_version(IXJ *j)
-{
-	BYTES bytes;
-
-	if (!SCI_Prepare(j))
-		return 0;
-
-	bytes.high = 0x35;
-	bytes.low = 0x00;
-	outb_p(bytes.high, j->XILINXbase + 0x03);
-	outb_p(bytes.low, j->XILINXbase + 0x02);
-
-	if (!SCI_Control(j, SCI_Enable_DAA))
-		return 0;
-
-	bytes.high = inb_p(j->XILINXbase + 0x03);
-	bytes.low = inb_p(j->XILINXbase + 0x02);
-	if (bytes.low != ALISDAA_ID_BYTE) {
-		if (ixjdebug & 0x0001)
-			printk("DAA Get Version Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low);
-		return 0;
-	}
-	if (!SCI_Control(j, SCI_Enable_DAA))
-		return 0;
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-
-	bytes.high = inb_p(j->XILINXbase + 0x03);
-	bytes.low = inb_p(j->XILINXbase + 0x02);
-	if (ixjdebug & 0x0002)
-		printk("DAA CR5 Byte high = 0x%x low = 0x%x\n", bytes.high, bytes.low);
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr5.reg = bytes.high;
-	return bytes.high;
-}
-
-static int daa_set_mode(IXJ *j, int mode)
-{
-	/* NOTE:
-	      The DAA *MUST* be in the conversation mode if the
-	      PSTN line is to be seized (PSTN line off-hook).
-	      Taking the PSTN line off-hook while the DAA is in
-	      a mode other than conversation mode will cause a
-	      hardware failure of the ALIS-A part.
-
-	   NOTE:
-	      The DAA can only go to SLEEP, RINGING or PULSEDIALING modes
-	      if the PSTN line is on-hook.  Failure to have the PSTN line
-	      in the on-hook state WILL CAUSE A HARDWARE FAILURE OF THE
-	      ALIS-A part.
-	*/
-
-	BYTES bytes;
-
-	j->flags.pstn_rmr = 0;
-
-	if (!SCI_Prepare(j))
-		return 0;
-
-	switch (mode) {
-	case SOP_PU_RESET:
-		j->pld_scrw.bits.daafsyncen = 0;	/* Turn off DAA Frame Sync */
-
-		outb_p(j->pld_scrw.byte, j->XILINXbase);
-		j->pld_slicw.bits.rly2 = 0;
-		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		bytes.high = 0x10;
-		bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
-		daa_load(&bytes, j);
-		if (!SCI_Prepare(j))
-			return 0;
-
-		j->daa_mode = SOP_PU_SLEEP;
-		break;
-	case SOP_PU_SLEEP:
-		if(j->daa_mode == SOP_PU_SLEEP)
-		{
-			break;
-		}
-		if (ixjdebug & 0x0008)
-			printk(KERN_INFO "phone DAA: SOP_PU_SLEEP at %ld\n", jiffies);
-/*		if(j->daa_mode == SOP_PU_CONVERSATION) */
-		{
-			j->pld_scrw.bits.daafsyncen = 0;	/* Turn off DAA Frame Sync */
-
-			outb_p(j->pld_scrw.byte, j->XILINXbase);
-			j->pld_slicw.bits.rly2 = 0;
-			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			bytes.high = 0x10;
-			bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
-			daa_load(&bytes, j);
-			if (!SCI_Prepare(j))
-				return 0;
-		}
-		j->pld_scrw.bits.daafsyncen = 0;	/* Turn off DAA Frame Sync */
-
-		outb_p(j->pld_scrw.byte, j->XILINXbase);
-		j->pld_slicw.bits.rly2 = 0;
-		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		bytes.high = 0x10;
-		bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
-		daa_load(&bytes, j);
-		if (!SCI_Prepare(j))
-			return 0;
-
-		j->daa_mode = SOP_PU_SLEEP;
-		j->flags.pstn_ringing = 0;
-		j->ex.bits.pstn_ring = 0;
-		j->pstn_sleeptil = jiffies + (hertz / 4);
-		wake_up_interruptible(&j->read_q);      /* Wake any blocked readers */
-		wake_up_interruptible(&j->write_q);     /* Wake any blocked writers */
-		wake_up_interruptible(&j->poll_q);      /* Wake any blocked selects */
- 		break;
-	case SOP_PU_RINGING:
-		if (ixjdebug & 0x0008)
-			printk(KERN_INFO "phone DAA: SOP_PU_RINGING at %ld\n", jiffies);
-		j->pld_scrw.bits.daafsyncen = 0;	/* Turn off DAA Frame Sync */
-
-		outb_p(j->pld_scrw.byte, j->XILINXbase);
-		j->pld_slicw.bits.rly2 = 0;
-		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		bytes.high = 0x50;
-		bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
-		daa_load(&bytes, j);
-		if (!SCI_Prepare(j))
-			return 0;
-		j->daa_mode = SOP_PU_RINGING;
-		break;
-	case SOP_PU_CONVERSATION:
-		if (ixjdebug & 0x0008)
-			printk(KERN_INFO "phone DAA: SOP_PU_CONVERSATION at %ld\n", jiffies);
-		bytes.high = 0x90;
-		bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
-		daa_load(&bytes, j);
-		if (!SCI_Prepare(j))
-			return 0;
-		j->pld_slicw.bits.rly2 = 1;
-		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		j->pld_scrw.bits.daafsyncen = 1;	/* Turn on DAA Frame Sync */
-
-		outb_p(j->pld_scrw.byte, j->XILINXbase);
-		j->daa_mode = SOP_PU_CONVERSATION;
-		j->flags.pstn_ringing = 0;
-		j->ex.bits.pstn_ring = 0;
-		j->pstn_sleeptil = jiffies;
-		j->pstn_ring_start = j->pstn_ring_stop = j->pstn_ring_int = 0;
-		break;
-	case SOP_PU_PULSEDIALING:
-		if (ixjdebug & 0x0008)
-			printk(KERN_INFO "phone DAA: SOP_PU_PULSEDIALING at %ld\n", jiffies);
-		j->pld_scrw.bits.daafsyncen = 0;	/* Turn off DAA Frame Sync */
-
-		outb_p(j->pld_scrw.byte, j->XILINXbase);
-		j->pld_slicw.bits.rly2 = 0;
-		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		bytes.high = 0xD0;
-		bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
-		daa_load(&bytes, j);
-		if (!SCI_Prepare(j))
-			return 0;
-		j->daa_mode = SOP_PU_PULSEDIALING;
-		break;
-	default:
-		break;
-	}
-	return 1;
-}
-
-static int ixj_daa_write(IXJ *j)
-{
-	BYTES bytes;
-
-	j->flags.pstncheck = 1;
-
-	daa_set_mode(j, SOP_PU_SLEEP);
-
-	if (!SCI_Prepare(j))
-		return 0;
-
-	outb_p(j->pld_scrw.byte, j->XILINXbase);
-
-	bytes.high = 0x14;
-	bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg;
-	bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg;
-	bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Prepare(j))
-		return 0;
-
-	bytes.high = 0x1F;
-	bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.XOP_xr6_W.reg;
-	bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg;
-	bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg;
-	bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.XOP_xr0_W.reg;
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Prepare(j))
-		return 0;
-
-	bytes.high = 0x00;
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0];
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-	if (!SCI_WaitLowSCI(j))
-		return 0;
-
-	bytes.high = 0x01;
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0];
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-	if (!SCI_WaitLowSCI(j))
-		return 0;
-
-	bytes.high = 0x02;
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0];
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-	if (!SCI_WaitLowSCI(j))
-		return 0;
-
-	bytes.high = 0x03;
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0];
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-	if (!SCI_WaitLowSCI(j))
-		return 0;
-
-	bytes.high = 0x04;
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0];
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-	if (!SCI_WaitLowSCI(j))
-		return 0;
-
-	bytes.high = 0x05;
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0];
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-	if (!SCI_WaitLowSCI(j))
-		return 0;
-
-	bytes.high = 0x06;
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0];
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-	if (!SCI_WaitLowSCI(j))
-		return 0;
-
-	bytes.high = 0x07;
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0];
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-	if (!SCI_WaitLowSCI(j))
-		return 0;
-
-	bytes.high = 0x08;
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0];
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-	if (!SCI_WaitLowSCI(j))
-		return 0;
-
-	bytes.high = 0x09;
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0];
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-	if (!SCI_WaitLowSCI(j))
-		return 0;
-
-	bytes.high = 0x0A;
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0];
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-	if (!SCI_WaitLowSCI(j))
-		return 0;
-
-	bytes.high = 0x0B;
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0];
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-	if (!SCI_WaitLowSCI(j))
-		return 0;
-
-	bytes.high = 0x0C;
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0];
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-	if (!SCI_WaitLowSCI(j))
-		return 0;
-
-	bytes.high = 0x0D;
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0];
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-	if (!SCI_WaitLowSCI(j))
-		return 0;
-
-	bytes.high = 0x0E;
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0];
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-	if (!SCI_WaitLowSCI(j))
-		return 0;
-
-	bytes.high = 0x0F;
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2];
-	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1];
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0];
-	bytes.low = 0x00;
-	if (!daa_load(&bytes, j))
-		return 0;
-
-	udelay(32);
-	j->pld_scrr.byte = inb_p(j->XILINXbase);
-	if (!SCI_Control(j, SCI_End))
-		return 0;
-
-	outb_p(j->pld_scrw.byte, j->XILINXbase);
-
-	if (ixjdebug & 0x0002)
-		printk("DAA Coefficients Loaded\n");
-
-	j->flags.pstncheck = 0;
-	return 1;
-}
-
-static int ixj_set_tone_off(unsigned short arg, IXJ *j)
-{
-	j->tone_off_time = arg;
-	if (ixj_WriteDSPCommand(0x6E05, j))		/* Set Tone Off Period */
-
-		return -1;
-	if (ixj_WriteDSPCommand(arg, j))
-		return -1;
-	return 0;
-}
-
-static int ixj_get_tone_on(IXJ *j)
-{
-	if (ixj_WriteDSPCommand(0x6E06, j))		/* Get Tone On Period */
-
-		return -1;
-	return 0;
-}
-
-static int ixj_get_tone_off(IXJ *j)
-{
-	if (ixj_WriteDSPCommand(0x6E07, j))		/* Get Tone Off Period */
-
-		return -1;
-	return 0;
-}
-
-static void ixj_busytone(IXJ *j)
-{
-	j->flags.ringback = 0;
-	j->flags.dialtone = 0;
-	j->flags.busytone = 1;
-	ixj_set_tone_on(0x07D0, j);
-	ixj_set_tone_off(0x07D0, j);
-	ixj_play_tone(j, 27);
-}
-
-static void ixj_dialtone(IXJ *j)
-{
-	j->flags.ringback = 0;
-	j->flags.dialtone = 1;
-	j->flags.busytone = 0;
-	if (j->dsp.low == 0x20) {
-		return;
-	} else {
-		ixj_set_tone_on(0xFFFF, j);
-		ixj_set_tone_off(0x0000, j);
-		ixj_play_tone(j, 25);
-	}
-}
-
-static void ixj_cpt_stop(IXJ *j)
-{
-	if(j->tone_state || j->tone_cadence_state)
-	{
-		j->flags.dialtone = 0;
-		j->flags.busytone = 0;
-		j->flags.ringback = 0;
-		ixj_set_tone_on(0x0001, j);
-		ixj_set_tone_off(0x0000, j);
-		ixj_play_tone(j, 0);
-		j->tone_state = j->tone_cadence_state = 0;
-		if (j->cadence_t) {
-			kfree(j->cadence_t->ce);
-			kfree(j->cadence_t);
-			j->cadence_t = NULL;
-		}
-	}
-	if (j->play_mode == -1 && j->rec_mode == -1)
-		idle(j);
-	if (j->play_mode != -1 && j->dsp.low == 0x20)
-		ixj_play_start(j);
-	if (j->rec_mode != -1 && j->dsp.low == 0x20)
-		ixj_record_start(j);
-}
-
-static void ixj_ringback(IXJ *j)
-{
-	j->flags.busytone = 0;
-	j->flags.dialtone = 0;
-	j->flags.ringback = 1;
-	ixj_set_tone_on(0x0FA0, j);
-	ixj_set_tone_off(0x2EE0, j);
-	ixj_play_tone(j, 26);
-}
-
-static void ixj_testram(IXJ *j)
-{
-	ixj_WriteDSPCommand(0x3001, j);	/* Test External SRAM */
-}
-
-static int ixj_build_cadence(IXJ *j, IXJ_CADENCE __user * cp)
-{
-	ixj_cadence *lcp;
-	IXJ_CADENCE_ELEMENT __user *cep;
-	IXJ_CADENCE_ELEMENT *lcep;
-	IXJ_TONE ti;
-	int err;
-
-	lcp = kmalloc(sizeof(ixj_cadence), GFP_KERNEL);
-	if (lcp == NULL)
-		return -ENOMEM;
-
-	err = -EFAULT;
-	if (copy_from_user(&lcp->elements_used,
-			   &cp->elements_used, sizeof(int)))
-		goto out;
-	if (copy_from_user(&lcp->termination,
-			   &cp->termination, sizeof(IXJ_CADENCE_TERM)))
-		goto out;
-	if (get_user(cep, &cp->ce))
-		goto out;
-
-	err = -EINVAL;
-	if ((unsigned)lcp->elements_used >= ~0U/sizeof(IXJ_CADENCE_ELEMENT))
-		goto out;
-
-	err = -ENOMEM;
-	lcep = kmalloc(sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used, GFP_KERNEL);
-	if (!lcep)
-		goto out;
-
-	err = -EFAULT;
-	if (copy_from_user(lcep, cep, sizeof(IXJ_CADENCE_ELEMENT) * lcp->elements_used))
-		goto out1;
-
-	if (j->cadence_t) {
-		kfree(j->cadence_t->ce);
-		kfree(j->cadence_t);
-	}
-	lcp->ce = (void *) lcep;
-	j->cadence_t = lcp;
-	j->tone_cadence_state = 0;
-	ixj_set_tone_on(lcp->ce[0].tone_on_time, j);
-	ixj_set_tone_off(lcp->ce[0].tone_off_time, j);
-	if (j->cadence_t->ce[j->tone_cadence_state].freq0) {
-		ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index;
-		ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0;
-		ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0;
-		ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1;
-		ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1;
-		ixj_init_tone(j, &ti);
-	}
-	ixj_play_tone(j, lcp->ce[0].index);
-	return 1;
-out1:
-	kfree(lcep);
-out:
-	kfree(lcp);
-	return err;
-}
-
-static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE __user * cp)
-{
-	IXJ_FILTER_CADENCE *lcp;
-	lcp = memdup_user(cp, sizeof(IXJ_FILTER_CADENCE));
-	if (IS_ERR(lcp)) {
-		if(ixjdebug & 0x0001) {
-			printk(KERN_INFO "Could not allocate memory for cadence or could not copy cadence to kernel\n");
-		}
-		return PTR_ERR(lcp);
-        }
-	if (lcp->filter > 5) {
-		if(ixjdebug & 0x0001) {
-			printk(KERN_INFO "Cadence out of range\n");
-		}
-		kfree(lcp);
-		return -1;
-	}
-	j->cadence_f[lcp->filter].state = 0;
-	j->cadence_f[lcp->filter].enable = lcp->enable;
-	j->filter_en[lcp->filter] = j->cadence_f[lcp->filter].en_filter = lcp->en_filter;
-	j->cadence_f[lcp->filter].on1 = lcp->on1;
-	j->cadence_f[lcp->filter].on1min = 0;
-	j->cadence_f[lcp->filter].on1max = 0;
-	j->cadence_f[lcp->filter].off1 = lcp->off1;
-	j->cadence_f[lcp->filter].off1min = 0;
-	j->cadence_f[lcp->filter].off1max = 0;
-	j->cadence_f[lcp->filter].on2 = lcp->on2;
-	j->cadence_f[lcp->filter].on2min = 0;
-	j->cadence_f[lcp->filter].on2max = 0;
-	j->cadence_f[lcp->filter].off2 = lcp->off2;
-	j->cadence_f[lcp->filter].off2min = 0;
-	j->cadence_f[lcp->filter].off2max = 0;
-	j->cadence_f[lcp->filter].on3 = lcp->on3;
-	j->cadence_f[lcp->filter].on3min = 0;
-	j->cadence_f[lcp->filter].on3max = 0;
-	j->cadence_f[lcp->filter].off3 = lcp->off3;
-	j->cadence_f[lcp->filter].off3min = 0;
-	j->cadence_f[lcp->filter].off3max = 0;
-	if(ixjdebug & 0x0002) {
-		printk(KERN_INFO "Cadence %d loaded\n", lcp->filter);
-	}
-	kfree(lcp);
-	return 0;
-}
-
-static void add_caps(IXJ *j)
-{
-	j->caps = 0;
-	j->caplist[j->caps].cap = PHONE_VENDOR_QUICKNET;
-	strcpy(j->caplist[j->caps].desc, "Quicknet Technologies, Inc. (www.quicknet.net)");
-	j->caplist[j->caps].captype = vendor;
-	j->caplist[j->caps].handle = j->caps;
-	j->caps++;
-	j->caplist[j->caps].captype = device;
-	switch (j->cardtype) {
-	case QTI_PHONEJACK:
-		strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneJACK");
-		break;
-	case QTI_LINEJACK:
-		strcpy(j->caplist[j->caps].desc, "Quicknet Internet LineJACK");
-		break;
-	case QTI_PHONEJACK_LITE:
-		strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneJACK Lite");
-		break;
-	case QTI_PHONEJACK_PCI:
-		strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneJACK PCI");
-		break;
-	case QTI_PHONECARD:
-		strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneCARD");
-		break;
-	}
-	j->caplist[j->caps].cap = j->cardtype;
-	j->caplist[j->caps].handle = j->caps;
-	j->caps++;
-	strcpy(j->caplist[j->caps].desc, "POTS");
-	j->caplist[j->caps].captype = port;
-	j->caplist[j->caps].cap = pots;
-	j->caplist[j->caps].handle = j->caps;
-	j->caps++;
-
- 	/* add devices that can do speaker/mic */
-	switch (j->cardtype) {
-	case QTI_PHONEJACK:
-	case QTI_LINEJACK:
-	case QTI_PHONEJACK_PCI:
-	case QTI_PHONECARD:
-		strcpy(j->caplist[j->caps].desc, "SPEAKER");
-		j->caplist[j->caps].captype = port;
-		j->caplist[j->caps].cap = speaker;
-		j->caplist[j->caps].handle = j->caps;
-		j->caps++;
-        default:
-     		break;
-	}
-
- 	/* add devices that can do handset */
-	switch (j->cardtype) {
-	case QTI_PHONEJACK:
-		strcpy(j->caplist[j->caps].desc, "HANDSET");
-		j->caplist[j->caps].captype = port;
-		j->caplist[j->caps].cap = handset;
-		j->caplist[j->caps].handle = j->caps;
-		j->caps++;
-		break;
-        default:
-     		break;
-	}
-
- 	/* add devices that can do PSTN */
-	switch (j->cardtype) {
-	case QTI_LINEJACK:
-		strcpy(j->caplist[j->caps].desc, "PSTN");
-		j->caplist[j->caps].captype = port;
-		j->caplist[j->caps].cap = pstn;
-		j->caplist[j->caps].handle = j->caps;
-		j->caps++;
-		break;
-        default:
-     		break;
-	}
-
-	/* add codecs - all cards can do uLaw, linear 8/16, and Windows sound system */
-	strcpy(j->caplist[j->caps].desc, "ULAW");
-	j->caplist[j->caps].captype = codec;
-	j->caplist[j->caps].cap = ULAW;
-	j->caplist[j->caps].handle = j->caps;
-	j->caps++;
-
-	strcpy(j->caplist[j->caps].desc, "LINEAR 16 bit");
-	j->caplist[j->caps].captype = codec;
-	j->caplist[j->caps].cap = LINEAR16;
-	j->caplist[j->caps].handle = j->caps;
-	j->caps++;
-
-	strcpy(j->caplist[j->caps].desc, "LINEAR 8 bit");
-	j->caplist[j->caps].captype = codec;
-	j->caplist[j->caps].cap = LINEAR8;
-	j->caplist[j->caps].handle = j->caps;
-	j->caps++;
-
-	strcpy(j->caplist[j->caps].desc, "Windows Sound System");
-	j->caplist[j->caps].captype = codec;
-	j->caplist[j->caps].cap = WSS;
-	j->caplist[j->caps].handle = j->caps;
-	j->caps++;
-
-	/* software ALAW codec, made from ULAW */
-	strcpy(j->caplist[j->caps].desc, "ALAW");
-	j->caplist[j->caps].captype = codec;
-	j->caplist[j->caps].cap = ALAW;
-	j->caplist[j->caps].handle = j->caps;
-	j->caps++;
-
-	/* version 12 of the 8020 does the following codecs in a broken way */
-	if (j->dsp.low != 0x20 || j->ver.low != 0x12) {
-		strcpy(j->caplist[j->caps].desc, "G.723.1 6.3kbps");
-		j->caplist[j->caps].captype = codec;
-		j->caplist[j->caps].cap = G723_63;
-		j->caplist[j->caps].handle = j->caps;
-		j->caps++;
-
-		strcpy(j->caplist[j->caps].desc, "G.723.1 5.3kbps");
-		j->caplist[j->caps].captype = codec;
-		j->caplist[j->caps].cap = G723_53;
-		j->caplist[j->caps].handle = j->caps;
-		j->caps++;
-
-		strcpy(j->caplist[j->caps].desc, "TrueSpeech 4.8kbps");
-		j->caplist[j->caps].captype = codec;
-		j->caplist[j->caps].cap = TS48;
-		j->caplist[j->caps].handle = j->caps;
-		j->caps++;
-
-		strcpy(j->caplist[j->caps].desc, "TrueSpeech 4.1kbps");
-		j->caplist[j->caps].captype = codec;
-		j->caplist[j->caps].cap = TS41;
-		j->caplist[j->caps].handle = j->caps;
-		j->caps++;
-	}
-
-	/* 8020 chips can do TS8.5 native, and 8021/8022 can load it */
-	if (j->dsp.low == 0x20 || j->flags.ts85_loaded) {
-		strcpy(j->caplist[j->caps].desc, "TrueSpeech 8.5kbps");
-		j->caplist[j->caps].captype = codec;
-		j->caplist[j->caps].cap = TS85;
-		j->caplist[j->caps].handle = j->caps;
-		j->caps++;
-	}
-
-	/* 8021 chips can do G728 */
-	if (j->dsp.low == 0x21) {
-		strcpy(j->caplist[j->caps].desc, "G.728 16kbps");
-		j->caplist[j->caps].captype = codec;
-		j->caplist[j->caps].cap = G728;
-		j->caplist[j->caps].handle = j->caps;
-		j->caps++;
-	}
-
-	/* 8021/8022 chips can do G729 if loaded */
-	if (j->dsp.low != 0x20 && j->flags.g729_loaded) {
-		strcpy(j->caplist[j->caps].desc, "G.729A 8kbps");
-		j->caplist[j->caps].captype = codec;
-		j->caplist[j->caps].cap = G729;
-		j->caplist[j->caps].handle = j->caps;
-		j->caps++;
-	}
-	if (j->dsp.low != 0x20 && j->flags.g729_loaded) {
-		strcpy(j->caplist[j->caps].desc, "G.729B 8kbps");
-		j->caplist[j->caps].captype = codec;
-		j->caplist[j->caps].cap = G729B;
-		j->caplist[j->caps].handle = j->caps;
-		j->caps++;
-	}
-}
-
-static int capabilities_check(IXJ *j, struct phone_capability *pcreq)
-{
-	int cnt;
-	int retval = 0;
-	for (cnt = 0; cnt < j->caps; cnt++) {
-		if (pcreq->captype == j->caplist[cnt].captype
-		    && pcreq->cap == j->caplist[cnt].cap) {
-			retval = 1;
-			break;
-		}
-	}
-	return retval;
-}
-
-static long do_ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long arg)
-{
-	IXJ_TONE ti;
-	IXJ_FILTER jf;
-	IXJ_FILTER_RAW jfr;
-	void __user *argp = (void __user *)arg;
-	struct inode *inode = file_p->f_path.dentry->d_inode;
-	unsigned int minor = iminor(inode);
-	unsigned int raise, mant;
-	int board = NUM(inode);
-
-	IXJ *j = get_ixj(NUM(inode));
-
-	int retval = 0;
-
-	/*
-	 *    Set up locks to ensure that only one process is talking to the DSP at a time.
-	 *    This is necessary to keep the DSP from locking up.
-	 */
-	while(test_and_set_bit(board, (void *)&j->busyflags) != 0)
-		schedule_timeout_interruptible(1);
-	if (ixjdebug & 0x0040)
-		printk("phone%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg);
-	if (minor >= IXJMAX) {
-		clear_bit(board, &j->busyflags);
-		return -ENODEV;
-	}
-	/*
-	 *    Check ioctls only root can use.
-	 */
-	if (!capable(CAP_SYS_ADMIN)) {
-		switch (cmd) {
-		case IXJCTL_TESTRAM:
-		case IXJCTL_HZ:
-			retval = -EPERM;
-		}
-	}
-	switch (cmd) {
-	case IXJCTL_TESTRAM:
-		ixj_testram(j);
-		retval = (j->ssr.high << 8) + j->ssr.low;
-		break;
-	case IXJCTL_CARDTYPE:
-		retval = j->cardtype;
-		break;
-	case IXJCTL_SERIAL:
-		retval = j->serial;
-		break;
-	case IXJCTL_VERSION:
-		{
-			char arg_str[100];
-			snprintf(arg_str, sizeof(arg_str),
-				"\nDriver version %i.%i.%i", IXJ_VER_MAJOR,
-				IXJ_VER_MINOR, IXJ_BLD_VER);
-			if (copy_to_user(argp, arg_str, strlen(arg_str)))
-				retval = -EFAULT;
-		}
-		break;
-	case PHONE_RING_CADENCE:
-		j->ring_cadence = arg;
-		break;
-	case IXJCTL_CIDCW:
-		if(arg) {
-			if (copy_from_user(&j->cid_send, argp, sizeof(PHONE_CID))) {
-				retval = -EFAULT;
-				break;
-			}
-		} else {
-			memset(&j->cid_send, 0, sizeof(PHONE_CID));
-		}
-		ixj_write_cidcw(j);
-		break;
-        /* Binary compatbility */
-        case OLD_PHONE_RING_START:
-                arg = 0;
-                /* Fall through */
- 	case PHONE_RING_START:
-		if(arg) {
-			if (copy_from_user(&j->cid_send, argp, sizeof(PHONE_CID))) {
-				retval = -EFAULT;
-				break;
-			}
-			ixj_write_cid(j);
-		} else {
-			memset(&j->cid_send, 0, sizeof(PHONE_CID));
-		}
-		ixj_ring_start(j);
-		break;
-	case PHONE_RING_STOP:
-		j->flags.cringing = 0;
-		if(j->cadence_f[5].enable) {
-			j->cadence_f[5].state = 0;
-		}
-		ixj_ring_off(j);
-		break;
-	case PHONE_RING:
-		retval = ixj_ring(j);
-		break;
-	case PHONE_EXCEPTION:
-		retval = j->ex.bytes;
-		if(j->ex.bits.flash) {
-			j->flash_end = 0;
-			j->ex.bits.flash = 0;
-		}
-		j->ex.bits.pstn_ring = 0;
-		j->ex.bits.caller_id = 0;
-		j->ex.bits.pstn_wink = 0;
-		j->ex.bits.f0 = 0;
-		j->ex.bits.f1 = 0;
-		j->ex.bits.f2 = 0;
-		j->ex.bits.f3 = 0;
-		j->ex.bits.fc0 = 0;
-		j->ex.bits.fc1 = 0;
-		j->ex.bits.fc2 = 0;
-		j->ex.bits.fc3 = 0;
-		j->ex.bits.reserved = 0;
-		break;
-	case PHONE_HOOKSTATE:
-		j->ex.bits.hookstate = 0;
-		retval = j->hookstate;  //j->r_hook;
-		break;
-	case IXJCTL_SET_LED:
-		LED_SetState(arg, j);
-		break;
-	case PHONE_FRAME:
-		retval = set_base_frame(j, arg);
-		break;
-	case PHONE_REC_CODEC:
-		retval = set_rec_codec(j, arg);
-		break;
-	case PHONE_VAD:
-		ixj_vad(j, arg);
-		break;
-	case PHONE_REC_START:
-		ixj_record_start(j);
-		break;
-	case PHONE_REC_STOP:
-		ixj_record_stop(j);
-		break;
-	case PHONE_REC_DEPTH:
-		set_rec_depth(j, arg);
-		break;
-	case PHONE_REC_VOLUME:
-		if(arg == -1) {
-			retval = get_rec_volume(j);
-		}
-		else {
-			set_rec_volume(j, arg);
-			retval = arg;
-		}
-		break;
-	case PHONE_REC_VOLUME_LINEAR:
-		if(arg == -1) {
-			retval = get_rec_volume_linear(j);
-		}
-		else {
-			set_rec_volume_linear(j, arg);
-			retval = arg;
-		}
-		break;
-	case IXJCTL_DTMF_PRESCALE:
-		if(arg == -1) {
-			retval = get_dtmf_prescale(j);
-		}
-		else {
-			set_dtmf_prescale(j, arg);
-			retval = arg;
-		}
-		break;
-	case PHONE_REC_LEVEL:
-		retval = get_rec_level(j);
-		break;
-	case IXJCTL_SC_RXG:
-		retval = ixj_siadc(j, arg);
-		break;
-	case IXJCTL_SC_TXG:
-		retval = ixj_sidac(j, arg);
-		break;
-	case IXJCTL_AEC_START:
-		ixj_aec_start(j, arg);
-		break;
-	case IXJCTL_AEC_STOP:
-		aec_stop(j);
-		break;
-	case IXJCTL_AEC_GET_LEVEL:
-		retval = j->aec_level;
-		break;
-	case PHONE_PLAY_CODEC:
-		retval = set_play_codec(j, arg);
-		break;
-	case PHONE_PLAY_START:
-		retval = ixj_play_start(j);
-		break;
-	case PHONE_PLAY_STOP:
-		ixj_play_stop(j);
-		break;
-	case PHONE_PLAY_DEPTH:
-		set_play_depth(j, arg);
-		break;
-	case PHONE_PLAY_VOLUME:
-		if(arg == -1) {
-			retval = get_play_volume(j);
-		}
-		else {
-			set_play_volume(j, arg);
-			retval = arg;
-		}
-		break;
-	case PHONE_PLAY_VOLUME_LINEAR:
-		if(arg == -1) {
-			retval = get_play_volume_linear(j);
-		}
-		else {
-			set_play_volume_linear(j, arg);
-			retval = arg;
-		}
-		break;
-	case PHONE_PLAY_LEVEL:
-		retval = get_play_level(j);
-		break;
-	case IXJCTL_DSP_TYPE:
-		retval = (j->dsp.high << 8) + j->dsp.low;
-		break;
-	case IXJCTL_DSP_VERSION:
-		retval = (j->ver.high << 8) + j->ver.low;
-		break;
-	case IXJCTL_HZ:
-		hertz = arg;
-		break;
-	case IXJCTL_RATE:
-		if (arg > hertz)
-			retval = -1;
-		else
-			samplerate = arg;
-		break;
-	case IXJCTL_DRYBUFFER_READ:
-		put_user(j->drybuffer, (unsigned long __user *) argp);
-		break;
-	case IXJCTL_DRYBUFFER_CLEAR:
-		j->drybuffer = 0;
-		break;
-	case IXJCTL_FRAMES_READ:
-		put_user(j->framesread, (unsigned long __user *) argp);
-		break;
-	case IXJCTL_FRAMES_WRITTEN:
-		put_user(j->frameswritten, (unsigned long __user *) argp);
-		break;
-	case IXJCTL_READ_WAIT:
-		put_user(j->read_wait, (unsigned long __user *) argp);
-		break;
-	case IXJCTL_WRITE_WAIT:
-		put_user(j->write_wait, (unsigned long __user *) argp);
-		break;
-	case PHONE_MAXRINGS:
-		j->maxrings = arg;
-		break;
-	case PHONE_SET_TONE_ON_TIME:
-		ixj_set_tone_on(arg, j);
-		break;
-	case PHONE_SET_TONE_OFF_TIME:
-		ixj_set_tone_off(arg, j);
-		break;
-	case PHONE_GET_TONE_ON_TIME:
-		if (ixj_get_tone_on(j)) {
-			retval = -1;
-		} else {
-			retval = (j->ssr.high << 8) + j->ssr.low;
-		}
-		break;
-	case PHONE_GET_TONE_OFF_TIME:
-		if (ixj_get_tone_off(j)) {
-			retval = -1;
-		} else {
-			retval = (j->ssr.high << 8) + j->ssr.low;
-		}
-		break;
-	case PHONE_PLAY_TONE:
-		if (!j->tone_state)
-			retval = ixj_play_tone(j, arg);
-		else
-			retval = -1;
-		break;
-	case PHONE_GET_TONE_STATE:
-		retval = j->tone_state;
-		break;
-	case PHONE_DTMF_READY:
-		retval = j->ex.bits.dtmf_ready;
-		break;
-	case PHONE_GET_DTMF:
-		if (ixj_hookstate(j)) {
-			if (j->dtmf_rp != j->dtmf_wp) {
-				retval = j->dtmfbuffer[j->dtmf_rp];
-				j->dtmf_rp++;
-				if (j->dtmf_rp == 79)
-					j->dtmf_rp = 0;
-				if (j->dtmf_rp == j->dtmf_wp) {
-					j->ex.bits.dtmf_ready = j->dtmf_rp = j->dtmf_wp = 0;
-				}
-			}
-		}
-		break;
-	case PHONE_GET_DTMF_ASCII:
-		if (ixj_hookstate(j)) {
-			if (j->dtmf_rp != j->dtmf_wp) {
-				switch (j->dtmfbuffer[j->dtmf_rp]) {
-				case 10:
-					retval = 42;	/* '*'; */
-
-					break;
-				case 11:
-					retval = 48;	/*'0'; */
-
-					break;
-				case 12:
-					retval = 35;	/*'#'; */
-
-					break;
-				case 28:
-					retval = 65;	/*'A'; */
-
-					break;
-				case 29:
-					retval = 66;	/*'B'; */
-
-					break;
-				case 30:
-					retval = 67;	/*'C'; */
-
-					break;
-				case 31:
-					retval = 68;	/*'D'; */
-
-					break;
-				default:
-					retval = 48 + j->dtmfbuffer[j->dtmf_rp];
-					break;
-				}
-				j->dtmf_rp++;
-				if (j->dtmf_rp == 79)
-					j->dtmf_rp = 0;
-				if(j->dtmf_rp == j->dtmf_wp)
-				{
-					j->ex.bits.dtmf_ready = j->dtmf_rp = j->dtmf_wp = 0;
-				}
-			}
-		}
-		break;
-	case PHONE_DTMF_OOB:
-		j->flags.dtmf_oob = arg;
-		break;
-	case PHONE_DIALTONE:
-		ixj_dialtone(j);
-		break;
-	case PHONE_BUSY:
-		ixj_busytone(j);
-		break;
-	case PHONE_RINGBACK:
-		ixj_ringback(j);
-		break;
-	case PHONE_WINK:
-		if(j->cardtype == QTI_PHONEJACK)
-			retval = -1;
-		else
-			retval = ixj_wink(j);
-		break;
-	case PHONE_CPT_STOP:
-		ixj_cpt_stop(j);
-		break;
-        case PHONE_QUERY_CODEC:
-        {
-                struct phone_codec_data pd;
-                int val;
-                int proto_size[] = {
-                        -1,
-                        12, 10, 16, 9, 8, 48, 5,
-                        40, 40, 80, 40, 40, 6
-                };
-                if(copy_from_user(&pd, argp, sizeof(pd))) {
-                        retval = -EFAULT;
-			break;
-		}
-                if(pd.type<1 || pd.type>13) {
-                        retval = -EPROTONOSUPPORT;
-			break;
-		}
-                if(pd.type<G729)
-                        val=proto_size[pd.type];
-                else switch(j->baseframe.low)
-                {
-                        case 0xA0:val=2*proto_size[pd.type];break;
-                        case 0x50:val=proto_size[pd.type];break;
-                        default:val=proto_size[pd.type]*3;break;
-                }
-                pd.buf_min=pd.buf_max=pd.buf_opt=val;
-                if(copy_to_user(argp, &pd, sizeof(pd)))
-                        retval = -EFAULT;
-        	break;
-        }
-	case IXJCTL_DSP_IDLE:
-		idle(j);
-		break;
-	case IXJCTL_MIXER:
-                if ((arg & 0xff) == 0xff)
-			retval = ixj_get_mixer(arg, j);
-                else
-			ixj_mixer(arg, j);
-		break;
-	case IXJCTL_DAA_COEFF_SET:
-		switch (arg) {
-		case DAA_US:
-			DAA_Coeff_US(j);
-			retval = ixj_daa_write(j);
-			break;
-		case DAA_UK:
-			DAA_Coeff_UK(j);
-			retval = ixj_daa_write(j);
-			break;
-		case DAA_FRANCE:
-			DAA_Coeff_France(j);
-			retval = ixj_daa_write(j);
-			break;
-		case DAA_GERMANY:
-			DAA_Coeff_Germany(j);
-			retval = ixj_daa_write(j);
-			break;
-		case DAA_AUSTRALIA:
-			DAA_Coeff_Australia(j);
-			retval = ixj_daa_write(j);
-			break;
-		case DAA_JAPAN:
-			DAA_Coeff_Japan(j);
-			retval = ixj_daa_write(j);
-			break;
-		default:
-			retval = 1;
-			break;
-		}
-		break;
-	case IXJCTL_DAA_AGAIN:
-		ixj_daa_cr4(j, arg | 0x02);
-		break;
-	case IXJCTL_PSTN_LINETEST:
-		retval = ixj_linetest(j);
-		break;
-	case IXJCTL_VMWI:
-		ixj_write_vmwi(j, arg);
-		break;
-	case IXJCTL_CID:
-		if (copy_to_user(argp, &j->cid, sizeof(PHONE_CID)))
-			retval = -EFAULT;
-		j->ex.bits.caller_id = 0;
-		break;
-	case IXJCTL_WINK_DURATION:
-		j->winktime = arg;
-		break;
-	case IXJCTL_PORT:
-		if (arg)
-			retval = ixj_set_port(j, arg);
-		else
-			retval = j->port;
-		break;
-	case IXJCTL_POTS_PSTN:
-		retval = ixj_set_pots(j, arg);
-		break;
-	case PHONE_CAPABILITIES:
-		add_caps(j);
-		retval = j->caps;
-		break;
-	case PHONE_CAPABILITIES_LIST:
-		add_caps(j);
-		if (copy_to_user(argp, j->caplist, sizeof(struct phone_capability) * j->caps))
-			retval = -EFAULT;
-		break;
-	case PHONE_CAPABILITIES_CHECK:
-		{
-			struct phone_capability cap;
-			if (copy_from_user(&cap, argp, sizeof(cap)))
-				retval = -EFAULT;
-			else {
-				add_caps(j);
-				retval = capabilities_check(j, &cap);
-			}
-		}
-		break;
-	case PHONE_PSTN_SET_STATE:
-		daa_set_mode(j, arg);
-		break;
-	case PHONE_PSTN_GET_STATE:
-		retval = j->daa_mode;
-		j->ex.bits.pstn_ring = 0;
-		break;
-	case IXJCTL_SET_FILTER:
-		if (copy_from_user(&jf, argp, sizeof(jf)))
-			retval = -EFAULT;
-		else
-			retval = ixj_init_filter(j, &jf);
-		break;
-	case IXJCTL_SET_FILTER_RAW:
-		if (copy_from_user(&jfr, argp, sizeof(jfr)))
-			retval = -EFAULT;
-		else
-			retval = ixj_init_filter_raw(j, &jfr);
-		break;
-	case IXJCTL_GET_FILTER_HIST:
-		if(arg<0||arg>3)
-			retval = -EINVAL;
-		else
-			retval = j->filter_hist[arg];
-		break;
-	case IXJCTL_INIT_TONE:
-		if (copy_from_user(&ti, argp, sizeof(ti)))
-			retval = -EFAULT;
-		else
-			retval = ixj_init_tone(j, &ti);
-		break;
-	case IXJCTL_TONE_CADENCE:
-		retval = ixj_build_cadence(j, argp);
-		break;
-	case IXJCTL_FILTER_CADENCE:
-		retval = ixj_build_filter_cadence(j, argp);
-		break;
-	case IXJCTL_SIGCTL:
-		if (copy_from_user(&j->sigdef, argp, sizeof(IXJ_SIGDEF))) {
-			retval = -EFAULT;
-			break;
-		}
-		j->ixj_signals[j->sigdef.event] = j->sigdef.signal;
-		if(j->sigdef.event < 33) {
-			raise = 1;
-			for(mant = 0; mant < j->sigdef.event; mant++){
-				raise *= 2;
-			}
-			if(j->sigdef.signal)
-				j->ex_sig.bytes |= raise;
-			else
-				j->ex_sig.bytes &= (raise^0xffff);
-		}
-		break;
-	case IXJCTL_INTERCOM_STOP:
-		if(arg < 0 || arg >= IXJMAX)
-			return -EINVAL;
-		j->intercom = -1;
-		ixj_record_stop(j);
-		ixj_play_stop(j);
-		idle(j);
-		get_ixj(arg)->intercom = -1;
-		ixj_record_stop(get_ixj(arg));
-		ixj_play_stop(get_ixj(arg));
-		idle(get_ixj(arg));
-		break;
-	case IXJCTL_INTERCOM_START:
-		if(arg < 0 || arg >= IXJMAX)
-			return -EINVAL;
-		j->intercom = arg;
-		ixj_record_start(j);
-		ixj_play_start(j);
-		get_ixj(arg)->intercom = board;
-		ixj_play_start(get_ixj(arg));
-		ixj_record_start(get_ixj(arg));
-		break;
-	}
-	if (ixjdebug & 0x0040)
-		printk("phone%d ioctl end, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg);
-	clear_bit(board, &j->busyflags);
-	return retval;
-}
-
-static long ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long arg)
-{
-	long ret;
-	mutex_lock(&ixj_mutex);
-	ret = do_ixj_ioctl(file_p, cmd, arg);
-	mutex_unlock(&ixj_mutex);
-	return ret;
-}
-
-static int ixj_fasync(int fd, struct file *file_p, int mode)
-{
-	IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
-
-	return fasync_helper(fd, file_p, mode, &j->async_queue);
-}
-
-static const struct file_operations ixj_fops =
-{
-        .owner          = THIS_MODULE,
-        .read           = ixj_enhanced_read,
-        .write          = ixj_enhanced_write,
-        .poll           = ixj_poll,
-        .unlocked_ioctl = ixj_ioctl,
-        .release        = ixj_release,
-        .fasync         = ixj_fasync,
-        .llseek	 = default_llseek,
-};
-
-static int ixj_linetest(IXJ *j)
-{
-	j->flags.pstncheck = 1;	/* Testing */
-	j->flags.pstn_present = 0; /* Assume the line is not there */
-
-	daa_int_read(j);	/*Clear DAA Interrupt flags */
-	/* */
-	/* Hold all relays in the normally de-energized position. */
-	/* */
-
-	j->pld_slicw.bits.rly1 = 0;
-	j->pld_slicw.bits.rly2 = 0;
-	j->pld_slicw.bits.rly3 = 0;
-	outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-	j->pld_scrw.bits.daafsyncen = 0;	/* Turn off DAA Frame Sync */
-
-	outb_p(j->pld_scrw.byte, j->XILINXbase);
-	j->pld_slicr.byte = inb_p(j->XILINXbase + 0x01);
-	if (j->pld_slicr.bits.potspstn) {
-		j->flags.pots_pstn = 1;
-		j->flags.pots_correct = 0;
-		LED_SetState(0x4, j);
-	} else {
-		j->flags.pots_pstn = 0;
-		j->pld_slicw.bits.rly1 = 0;
-		j->pld_slicw.bits.rly2 = 0;
-		j->pld_slicw.bits.rly3 = 1;
-		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		j->pld_scrw.bits.daafsyncen = 0;	/* Turn off DAA Frame Sync */
-
-		outb_p(j->pld_scrw.byte, j->XILINXbase);
-		daa_set_mode(j, SOP_PU_CONVERSATION);
-		msleep(1000);
-		daa_int_read(j);
-		daa_set_mode(j, SOP_PU_RESET);
-		if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
-			j->flags.pots_correct = 0;	/* Should not be line voltage on POTS port. */
-			LED_SetState(0x4, j);
-			j->pld_slicw.bits.rly3 = 0;
-			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		} else {
-			j->flags.pots_correct = 1;
-			LED_SetState(0x8, j);
-			j->pld_slicw.bits.rly1 = 1;
-			j->pld_slicw.bits.rly2 = 0;
-			j->pld_slicw.bits.rly3 = 0;
-			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-		}
-	}
-	j->pld_slicw.bits.rly3 = 0;
-	outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-	daa_set_mode(j, SOP_PU_CONVERSATION);
-	msleep(1000);
-	daa_int_read(j);
-	daa_set_mode(j, SOP_PU_RESET);
-	if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
-		j->pstn_sleeptil = jiffies + (hertz / 4);
-		j->flags.pstn_present = 1;
-	} else {
-		j->flags.pstn_present = 0;
-	}
-	if (j->flags.pstn_present) {
-		if (j->flags.pots_correct) {
-			LED_SetState(0xA, j);
-		} else {
-			LED_SetState(0x6, j);
-		}
-	} else {
-		if (j->flags.pots_correct) {
-			LED_SetState(0x9, j);
-		} else {
-			LED_SetState(0x5, j);
-		}
-	}
-	j->flags.pstncheck = 0;	/* Testing */
-	return j->flags.pstn_present;
-}
-
-static int ixj_selfprobe(IXJ *j)
-{
-	unsigned short cmd;
-	int cnt;
-	BYTES bytes;
-
-        init_waitqueue_head(&j->poll_q);
-        init_waitqueue_head(&j->read_q);
-        init_waitqueue_head(&j->write_q);
-
-	while(atomic_read(&j->DSPWrite) > 0)
-		atomic_dec(&j->DSPWrite);
-	if (ixjdebug & 0x0002)
-		printk(KERN_INFO "Write IDLE to Software Control Register\n");
-	ixj_WriteDSPCommand(0x0FE0, j);	/* Put the DSP in full power mode. */
-
-	if (ixj_WriteDSPCommand(0x0000, j))		/* Write IDLE to Software Control Register */
-		return -1;
-/* The read values of the SSR should be 0x00 for the IDLE command */
-	if (j->ssr.low || j->ssr.high)
-		return -1;
-	if (ixjdebug & 0x0002)
-		printk(KERN_INFO "Get Device ID Code\n");
-	if (ixj_WriteDSPCommand(0x3400, j))		/* Get Device ID Code */
-		return -1;
-	j->dsp.low = j->ssr.low;
-	j->dsp.high = j->ssr.high;
-	if (ixjdebug & 0x0002)
-		printk(KERN_INFO "Get Device Version Code\n");
-	if (ixj_WriteDSPCommand(0x3800, j))		/* Get Device Version Code */
-		return -1;
-	j->ver.low = j->ssr.low;
-	j->ver.high = j->ssr.high;
-	if (!j->cardtype) {
-		if (j->dsp.low == 0x21) {
-			bytes.high = bytes.low = inb_p(j->XILINXbase + 0x02);
-			outb_p(bytes.low ^ 0xFF, j->XILINXbase + 0x02);
-/* Test for Internet LineJACK or Internet PhoneJACK Lite */
-			bytes.low = inb_p(j->XILINXbase + 0x02);
-			if (bytes.low == bytes.high)	/*  Register is read only on */
-				/*  Internet PhoneJack Lite */
-			 {
-				j->cardtype = QTI_PHONEJACK_LITE;
-				if (!request_region(j->XILINXbase, 4, "ixj control")) {
-					printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
-					return -1;
-				}
-				j->pld_slicw.pcib.e1 = 1;
-				outb_p(j->pld_slicw.byte, j->XILINXbase);
-			} else {
-				j->cardtype = QTI_LINEJACK;
-
-				if (!request_region(j->XILINXbase, 8, "ixj control")) {
-					printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
-					return -1;
-				}
-			}
-		} else if (j->dsp.low == 0x22) {
-			j->cardtype = QTI_PHONEJACK_PCI;
-			request_region(j->XILINXbase, 4, "ixj control");
-			j->pld_slicw.pcib.e1 = 1;
-			outb_p(j->pld_slicw.byte, j->XILINXbase);
-		} else
-			j->cardtype = QTI_PHONEJACK;
-	} else {
-		switch (j->cardtype) {
-		case QTI_PHONEJACK:
-			if (!j->dsp.low != 0x20) {
-				j->dsp.high = 0x80;
-				j->dsp.low = 0x20;
-				ixj_WriteDSPCommand(0x3800, j);
-				j->ver.low = j->ssr.low;
-				j->ver.high = j->ssr.high;
-			}
-			break;
-		case QTI_LINEJACK:
-			if (!request_region(j->XILINXbase, 8, "ixj control")) {
-				printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
-				return -1;
-			}
-			break;
-		case QTI_PHONEJACK_LITE:
-		case QTI_PHONEJACK_PCI:
-			if (!request_region(j->XILINXbase, 4, "ixj control")) {
-				printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
-				return -1;
-			}
-			j->pld_slicw.pcib.e1 = 1;
-			outb_p(j->pld_slicw.byte, j->XILINXbase);
-			break;
-		case QTI_PHONECARD:
-			break;
-		}
-	}
-	if (j->dsp.low == 0x20 || j->cardtype == QTI_PHONEJACK_LITE || j->cardtype == QTI_PHONEJACK_PCI) {
-		if (ixjdebug & 0x0002)
-			printk(KERN_INFO "Write CODEC config to Software Control Register\n");
-		if (ixj_WriteDSPCommand(0xC462, j))		/* Write CODEC config to Software Control Register */
-			return -1;
-		if (ixjdebug & 0x0002)
-			printk(KERN_INFO "Write CODEC timing to Software Control Register\n");
-		if (j->cardtype == QTI_PHONEJACK) {
-			cmd = 0x9FF2;
-		} else {
-			cmd = 0x9FF5;
-		}
-		if (ixj_WriteDSPCommand(cmd, j))	/* Write CODEC timing to Software Control Register */
-			return -1;
-	} else {
-		if (set_base_frame(j, 30) != 30)
-			return -1;
-		if (ixjdebug & 0x0002)
-			printk(KERN_INFO "Write CODEC config to Software Control Register\n");
-		if (j->cardtype == QTI_PHONECARD) {
-			if (ixj_WriteDSPCommand(0xC528, j))		/* Write CODEC config to Software Control Register */
-				return -1;
-		}
-		if (j->cardtype == QTI_LINEJACK) {
-			if (ixj_WriteDSPCommand(0xC528, j))		/* Write CODEC config to Software Control Register */
-				return -1;
-			if (ixjdebug & 0x0002)
-				printk(KERN_INFO "Turn on the PLD Clock at 8Khz\n");
-			j->pld_clock.byte = 0;
-			outb_p(j->pld_clock.byte, j->XILINXbase + 0x04);
-		}
-	}
-
-	if (j->dsp.low == 0x20) {
-		if (ixjdebug & 0x0002)
-			printk(KERN_INFO "Configure GPIO pins\n");
-		j->gpio.bytes.high = 0x09;
-/*  bytes.low = 0xEF;  0xF7 */
-		j->gpio.bits.gpio1 = 1;
-		j->gpio.bits.gpio2 = 1;
-		j->gpio.bits.gpio3 = 0;
-		j->gpio.bits.gpio4 = 1;
-		j->gpio.bits.gpio5 = 1;
-		j->gpio.bits.gpio6 = 1;
-		j->gpio.bits.gpio7 = 1;
-		ixj_WriteDSPCommand(j->gpio.word, j);	/* Set GPIO pin directions */
-		if (ixjdebug & 0x0002)
-			printk(KERN_INFO "Enable SLIC\n");
-		j->gpio.bytes.high = 0x0B;
-		j->gpio.bytes.low = 0x00;
-		j->gpio.bits.gpio1 = 0;
-		j->gpio.bits.gpio2 = 1;
-		j->gpio.bits.gpio5 = 0;
-		ixj_WriteDSPCommand(j->gpio.word, j);	/* send the ring stop signal */
-		j->port = PORT_POTS;
-	} else {
-		if (j->cardtype == QTI_LINEJACK) {
-			LED_SetState(0x1, j);
-			msleep(100);
-			LED_SetState(0x2, j);
-			msleep(100);
-			LED_SetState(0x4, j);
-			msleep(100);
-			LED_SetState(0x8, j);
-			msleep(100);
-			LED_SetState(0x0, j);
-			daa_get_version(j);
-			if (ixjdebug & 0x0002)
-				printk("Loading DAA Coefficients\n");
-			DAA_Coeff_US(j);
-			if (!ixj_daa_write(j)) {
-				printk("DAA write failed on board %d\n", j->board);
-				return -1;
-			}
-			if(!ixj_daa_cid_reset(j)) {
-				printk("DAA CID reset failed on board %d\n", j->board);
-				return -1;
-			}
-			j->flags.pots_correct = 0;
-			j->flags.pstn_present = 0;
-			ixj_linetest(j);
-			if (j->flags.pots_correct) {
-				j->pld_scrw.bits.daafsyncen = 0;	/* Turn off DAA Frame Sync */
-
-				outb_p(j->pld_scrw.byte, j->XILINXbase);
-				j->pld_slicw.bits.rly1 = 1;
-				j->pld_slicw.bits.spken = 1;
-				outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-				SLIC_SetState(PLD_SLIC_STATE_STANDBY, j);
-/*				SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); */
-				j->port = PORT_POTS;
-			}
-			ixj_set_port(j, PORT_PSTN);
-			ixj_set_pots(j, 1);
-			if (ixjdebug & 0x0002)
-				printk(KERN_INFO "Enable Mixer\n");
-			ixj_mixer(0x0000, j);	/*Master Volume Left unmute 0db */
-			ixj_mixer(0x0100, j);	/*Master Volume Right unmute 0db */
-
-			ixj_mixer(0x0203, j);	/*Voice Left Volume unmute 6db */
-			ixj_mixer(0x0303, j);	/*Voice Right Volume unmute 6db */
-
-			ixj_mixer(0x0480, j);	/*FM Left mute */
-			ixj_mixer(0x0580, j);	/*FM Right mute */
-
-			ixj_mixer(0x0680, j);	/*CD Left mute */
-			ixj_mixer(0x0780, j);	/*CD Right mute */
-
-			ixj_mixer(0x0880, j);	/*Line Left mute */
-			ixj_mixer(0x0980, j);	/*Line Right mute */
-
-			ixj_mixer(0x0A80, j);	/*Aux left mute  */
-			ixj_mixer(0x0B80, j);	/*Aux right mute */
-
-			ixj_mixer(0x0C00, j);	/*Mono1 unmute 12db */
-			ixj_mixer(0x0D80, j);	/*Mono2 mute */
-
-			ixj_mixer(0x0E80, j);	/*Mic mute */
-
-			ixj_mixer(0x0F00, j);	/*Mono Out Volume unmute 0db */
-
-			ixj_mixer(0x1000, j);	/*Voice Left and Right out only */
-			ixj_mixer(0x110C, j);
-
-
-			ixj_mixer(0x1200, j);	/*Mono1 switch on mixer left */
-			ixj_mixer(0x1401, j);
-
-			ixj_mixer(0x1300, j);       /*Mono1 switch on mixer right */
-			ixj_mixer(0x1501, j);
-
-			ixj_mixer(0x1700, j);	/*Clock select */
-
-			ixj_mixer(0x1800, j);	/*ADC input from mixer */
-
-			ixj_mixer(0x1901, j);	/*Mic gain 30db */
-
-			if (ixjdebug & 0x0002)
-				printk(KERN_INFO "Setting Default US Ring Cadence Detection\n");
-			j->cadence_f[4].state = 0;
-			j->cadence_f[4].on1 = 0;	/*Cadence Filter 4 is used for PSTN ring cadence */
-			j->cadence_f[4].off1 = 0;
-			j->cadence_f[4].on2 = 0;
-			j->cadence_f[4].off2 = 0;
-			j->cadence_f[4].on3 = 0;
-			j->cadence_f[4].off3 = 0;	/* These should represent standard US ring pulse. */
-			j->pstn_last_rmr = jiffies;
-
-		} else {
-			if (j->cardtype == QTI_PHONECARD) {
-				ixj_WriteDSPCommand(0xCF07, j);
-				ixj_WriteDSPCommand(0x00B0, j);
-				ixj_set_port(j, PORT_SPEAKER);
-			} else {
-				ixj_set_port(j, PORT_POTS);
-				SLIC_SetState(PLD_SLIC_STATE_STANDBY, j);
-/*				SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j); */
-			}
-		}
-	}
-
-	j->intercom = -1;
-	j->framesread = j->frameswritten = 0;
-	j->read_wait = j->write_wait = 0;
-	j->rxreadycheck = j->txreadycheck = 0;
-
-	/* initialise the DTMF prescale to a sensible value */
-	if (j->cardtype == QTI_LINEJACK) {
-		set_dtmf_prescale(j, 0x10);
-	} else {
-		set_dtmf_prescale(j, 0x40);
-	}
-	set_play_volume(j, 0x100);
-	set_rec_volume(j, 0x100);
-
-	if (ixj_WriteDSPCommand(0x0000, j))		/* Write IDLE to Software Control Register */
-		return -1;
-/* The read values of the SSR should be 0x00 for the IDLE command */
-	if (j->ssr.low || j->ssr.high)
-		return -1;
-
-	if (ixjdebug & 0x0002)
-		printk(KERN_INFO "Enable Line Monitor\n");
-
-	if (ixjdebug & 0x0002)
-		printk(KERN_INFO "Set Line Monitor to Asynchronous Mode\n");
-
-	if (ixj_WriteDSPCommand(0x7E01, j))		/* Asynchronous Line Monitor */
-		return -1;
-
-	if (ixjdebug & 0x002)
-		printk(KERN_INFO "Enable DTMF Detectors\n");
-
-	if (ixj_WriteDSPCommand(0x5151, j))		/* Enable DTMF detection */
-		return -1;
-
-	if (ixj_WriteDSPCommand(0x6E01, j))		/* Set Asynchronous Tone Generation */
-		return -1;
-
-	set_rec_depth(j, 2);	/* Set Record Channel Limit to 2 frames */
-
-	set_play_depth(j, 2);	/* Set Playback Channel Limit to 2 frames */
-
-	j->ex.bits.dtmf_ready = 0;
-	j->dtmf_state = 0;
-	j->dtmf_wp = j->dtmf_rp = 0;
-	j->rec_mode = j->play_mode = -1;
-	j->flags.ringing = 0;
-	j->maxrings = MAXRINGS;
-	j->ring_cadence = USA_RING_CADENCE;
-	j->drybuffer = 0;
-	j->winktime = 320;
-	j->flags.dtmf_oob = 0;
-	for (cnt = 0; cnt < 4; cnt++)
-		j->cadence_f[cnt].enable = 0;
-	/* must be a device on the specified address */
-	ixj_WriteDSPCommand(0x0FE3, j);	/* Put the DSP in 1/5 power mode. */
-
-	/* Set up the default signals for events */
-	for (cnt = 0; cnt < 35; cnt++)
-		j->ixj_signals[cnt] = SIGIO;
-
-	/* Set the exception signal enable flags */
-	j->ex_sig.bits.dtmf_ready = j->ex_sig.bits.hookstate = j->ex_sig.bits.flash = j->ex_sig.bits.pstn_ring =
-	j->ex_sig.bits.caller_id = j->ex_sig.bits.pstn_wink = j->ex_sig.bits.f0 = j->ex_sig.bits.f1 = j->ex_sig.bits.f2 =
-	j->ex_sig.bits.f3 = j->ex_sig.bits.fc0 = j->ex_sig.bits.fc1 = j->ex_sig.bits.fc2 = j->ex_sig.bits.fc3 = 1;
-#ifdef IXJ_DYN_ALLOC
-	j->fskdata = NULL;
-#endif
-	j->fskdcnt = 0;
-	j->cidcw_wait = 0;
-
-	/* Register with the Telephony for Linux subsystem */
-	j->p.f_op = &ixj_fops;
-	j->p.open = ixj_open;
-	j->p.board = j->board;
-	phone_register_device(&j->p, PHONE_UNIT_ANY);
-
-	ixj_init_timer(j);
-	ixj_add_timer(j);
-	return 0;
-}
-
-/*
- *	Exported service for pcmcia card handling
- */
-
-IXJ *ixj_pcmcia_probe(unsigned long dsp, unsigned long xilinx)
-{
-	IXJ *j = ixj_alloc();
-
-	j->board = 0;
-
-	j->DSPbase = dsp;
-	j->XILINXbase = xilinx;
-	j->cardtype = QTI_PHONECARD;
-	ixj_selfprobe(j);
-	return j;
-}
-
-EXPORT_SYMBOL(ixj_pcmcia_probe);		/* For PCMCIA */
-
-static int ixj_get_status_proc(char *buf)
-{
-	int len;
-	int cnt;
-	IXJ *j;
-	len = 0;
-	len += sprintf(buf + len, "\nDriver version %i.%i.%i", IXJ_VER_MAJOR, IXJ_VER_MINOR, IXJ_BLD_VER);
-	len += sprintf(buf + len, "\nsizeof IXJ struct %Zd bytes", sizeof(IXJ));
-	len += sprintf(buf + len, "\nsizeof DAA struct %Zd bytes", sizeof(DAA_REGS));
-	len += sprintf(buf + len, "\nUsing old telephony API");
-	len += sprintf(buf + len, "\nDebug Level %d\n", ixjdebug);
-
-	for (cnt = 0; cnt < IXJMAX; cnt++) {
-		j = get_ixj(cnt);
-		if(j==NULL)
-			continue;
-		if (j->DSPbase) {
-			len += sprintf(buf + len, "\nCard Num %d", cnt);
-			len += sprintf(buf + len, "\nDSP Base Address 0x%4.4x", j->DSPbase);
-			if (j->cardtype != QTI_PHONEJACK)
-				len += sprintf(buf + len, "\nXILINX Base Address 0x%4.4x", j->XILINXbase);
-			len += sprintf(buf + len, "\nDSP Type %2.2x%2.2x", j->dsp.high, j->dsp.low);
-			len += sprintf(buf + len, "\nDSP Version %2.2x.%2.2x", j->ver.high, j->ver.low);
-			len += sprintf(buf + len, "\nSerial Number %8.8x", j->serial);
-			switch (j->cardtype) {
-			case (QTI_PHONEJACK):
-				len += sprintf(buf + len, "\nCard Type = Internet PhoneJACK");
-				break;
-			case (QTI_LINEJACK):
-				len += sprintf(buf + len, "\nCard Type = Internet LineJACK");
-				if (j->flags.g729_loaded)
-					len += sprintf(buf + len, " w/G.729 A/B");
-				len += sprintf(buf + len, " Country = %d", j->daa_country);
-				break;
-			case (QTI_PHONEJACK_LITE):
-				len += sprintf(buf + len, "\nCard Type = Internet PhoneJACK Lite");
-				if (j->flags.g729_loaded)
-					len += sprintf(buf + len, " w/G.729 A/B");
-				break;
-			case (QTI_PHONEJACK_PCI):
-				len += sprintf(buf + len, "\nCard Type = Internet PhoneJACK PCI");
-				if (j->flags.g729_loaded)
-					len += sprintf(buf + len, " w/G.729 A/B");
-				break;
-			case (QTI_PHONECARD):
-				len += sprintf(buf + len, "\nCard Type = Internet PhoneCARD");
-				if (j->flags.g729_loaded)
-					len += sprintf(buf + len, " w/G.729 A/B");
-				len += sprintf(buf + len, "\nSmart Cable %spresent", j->pccr1.bits.drf ? "not " : "");
-				if (!j->pccr1.bits.drf)
-					len += sprintf(buf + len, "\nSmart Cable type %d", j->flags.pcmciasct);
-				len += sprintf(buf + len, "\nSmart Cable state %d", j->flags.pcmciastate);
-				break;
-			default:
-				len += sprintf(buf + len, "\nCard Type = %d", j->cardtype);
-				break;
-			}
-			len += sprintf(buf + len, "\nReaders %d", j->readers);
-			len += sprintf(buf + len, "\nWriters %d", j->writers);
-			add_caps(j);
-			len += sprintf(buf + len, "\nCapabilities %d", j->caps);
-			if (j->dsp.low != 0x20)
-				len += sprintf(buf + len, "\nDSP Processor load %d", j->proc_load);
-			if (j->flags.cidsent)
-				len += sprintf(buf + len, "\nCaller ID data sent");
-			else
-				len += sprintf(buf + len, "\nCaller ID data not sent");
-
-			len += sprintf(buf + len, "\nPlay CODEC ");
-			switch (j->play_codec) {
-			case G723_63:
-				len += sprintf(buf + len, "G.723.1 6.3");
-				break;
-			case G723_53:
-				len += sprintf(buf + len, "G.723.1 5.3");
-				break;
-			case TS85:
-				len += sprintf(buf + len, "TrueSpeech 8.5");
-				break;
-			case TS48:
-				len += sprintf(buf + len, "TrueSpeech 4.8");
-				break;
-			case TS41:
-				len += sprintf(buf + len, "TrueSpeech 4.1");
-				break;
-			case G728:
-				len += sprintf(buf + len, "G.728");
-				break;
-			case G729:
-				len += sprintf(buf + len, "G.729");
-				break;
-			case G729B:
-				len += sprintf(buf + len, "G.729B");
-				break;
-			case ULAW:
-				len += sprintf(buf + len, "uLaw");
-				break;
-			case ALAW:
-				len += sprintf(buf + len, "aLaw");
-				break;
-			case LINEAR16:
-				len += sprintf(buf + len, "16 bit Linear");
-				break;
-			case LINEAR8:
-				len += sprintf(buf + len, "8 bit Linear");
-				break;
-			case WSS:
-				len += sprintf(buf + len, "Windows Sound System");
-				break;
-			default:
-				len += sprintf(buf + len, "NO CODEC CHOSEN");
-				break;
-			}
-			len += sprintf(buf + len, "\nRecord CODEC ");
-			switch (j->rec_codec) {
-			case G723_63:
-				len += sprintf(buf + len, "G.723.1 6.3");
-				break;
-			case G723_53:
-				len += sprintf(buf + len, "G.723.1 5.3");
-				break;
-			case TS85:
-				len += sprintf(buf + len, "TrueSpeech 8.5");
-				break;
-			case TS48:
-				len += sprintf(buf + len, "TrueSpeech 4.8");
-				break;
-			case TS41:
-				len += sprintf(buf + len, "TrueSpeech 4.1");
-				break;
-			case G728:
-				len += sprintf(buf + len, "G.728");
-				break;
-			case G729:
-				len += sprintf(buf + len, "G.729");
-				break;
-			case G729B:
-				len += sprintf(buf + len, "G.729B");
-				break;
-			case ULAW:
-				len += sprintf(buf + len, "uLaw");
-				break;
-			case ALAW:
-				len += sprintf(buf + len, "aLaw");
-				break;
-			case LINEAR16:
-				len += sprintf(buf + len, "16 bit Linear");
-				break;
-			case LINEAR8:
-				len += sprintf(buf + len, "8 bit Linear");
-				break;
-			case WSS:
-				len += sprintf(buf + len, "Windows Sound System");
-				break;
-			default:
-				len += sprintf(buf + len, "NO CODEC CHOSEN");
-				break;
-			}
-			len += sprintf(buf + len, "\nAEC ");
-			switch (j->aec_level) {
-			case AEC_OFF:
-				len += sprintf(buf + len, "Off");
-				break;
-			case AEC_LOW:
-				len += sprintf(buf + len, "Low");
-				break;
-			case AEC_MED:
-				len += sprintf(buf + len, "Med");
-				break;
-			case AEC_HIGH:
-				len += sprintf(buf + len, "High");
-				break;
-			case AEC_AUTO:
-				len += sprintf(buf + len, "Auto");
-				break;
-			case AEC_AGC:
-				len += sprintf(buf + len, "AEC/AGC");
-				break;
-			default:
-				len += sprintf(buf + len, "unknown(%i)", j->aec_level);
-				break;
-			}
-
-			len += sprintf(buf + len, "\nRec volume 0x%x", get_rec_volume(j));
-			len += sprintf(buf + len, "\nPlay volume 0x%x", get_play_volume(j));
-			len += sprintf(buf + len, "\nDTMF prescale 0x%x", get_dtmf_prescale(j));
-
-			len += sprintf(buf + len, "\nHook state %d", j->hookstate); /* j->r_hook);	*/
-
-			if (j->cardtype == QTI_LINEJACK) {
-				len += sprintf(buf + len, "\nPOTS Correct %d", j->flags.pots_correct);
-				len += sprintf(buf + len, "\nPSTN Present %d", j->flags.pstn_present);
-				len += sprintf(buf + len, "\nPSTN Check %d", j->flags.pstncheck);
-				len += sprintf(buf + len, "\nPOTS to PSTN %d", j->flags.pots_pstn);
-				switch (j->daa_mode) {
-				case SOP_PU_SLEEP:
-					len += sprintf(buf + len, "\nDAA PSTN On Hook");
-					break;
-				case SOP_PU_RINGING:
-					len += sprintf(buf + len, "\nDAA PSTN Ringing");
-					len += sprintf(buf + len, "\nRinging state = %d", j->cadence_f[4].state);
-					break;
-				case SOP_PU_CONVERSATION:
-					len += sprintf(buf + len, "\nDAA PSTN Off Hook");
-					break;
-				case SOP_PU_PULSEDIALING:
-					len += sprintf(buf + len, "\nDAA PSTN Pulse Dialing");
-					break;
-				}
-				len += sprintf(buf + len, "\nDAA RMR = %d", j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.bitreg.RMR);
-				len += sprintf(buf + len, "\nDAA VDD OK = %d", j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK);
-				len += sprintf(buf + len, "\nDAA CR0 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg);
-				len += sprintf(buf + len, "\nDAA CR1 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg);
-				len += sprintf(buf + len, "\nDAA CR2 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg);
-				len += sprintf(buf + len, "\nDAA CR3 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg);
-				len += sprintf(buf + len, "\nDAA CR4 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg);
-				len += sprintf(buf + len, "\nDAA CR5 = 0x%02x", j->m_DAAShadowRegs.SOP_REGS.SOP.cr5.reg);
-				len += sprintf(buf + len, "\nDAA XR0 = 0x%02x", j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.reg);
-				len += sprintf(buf + len, "\nDAA ringstop %ld - jiffies %ld", j->pstn_ring_stop, jiffies);
-			}
-			switch (j->port) {
-			case PORT_POTS:
-				len += sprintf(buf + len, "\nPort POTS");
-				break;
-			case PORT_PSTN:
-				len += sprintf(buf + len, "\nPort PSTN");
-				break;
-			case PORT_SPEAKER:
-				len += sprintf(buf + len, "\nPort SPEAKER/MIC");
-				break;
-			case PORT_HANDSET:
-				len += sprintf(buf + len, "\nPort HANDSET");
-				break;
-			}
-			if (j->dsp.low == 0x21 || j->dsp.low == 0x22) {
-				len += sprintf(buf + len, "\nSLIC state ");
-				switch (SLIC_GetState(j)) {
-				case PLD_SLIC_STATE_OC:
-					len += sprintf(buf + len, "OC");
-					break;
-				case PLD_SLIC_STATE_RINGING:
-					len += sprintf(buf + len, "RINGING");
-					break;
-				case PLD_SLIC_STATE_ACTIVE:
-					len += sprintf(buf + len, "ACTIVE");
-					break;
-				case PLD_SLIC_STATE_OHT:	/* On-hook transmit */
-					len += sprintf(buf + len, "OHT");
-					break;
-				case PLD_SLIC_STATE_TIPOPEN:
-					len += sprintf(buf + len, "TIPOPEN");
-					break;
-				case PLD_SLIC_STATE_STANDBY:
-					len += sprintf(buf + len, "STANDBY");
-					break;
-				case PLD_SLIC_STATE_APR:	/* Active polarity reversal */
-					len += sprintf(buf + len, "APR");
-					break;
-				case PLD_SLIC_STATE_OHTPR:	/* OHT polarity reversal */
-					len += sprintf(buf + len, "OHTPR");
-					break;
-				default:
-					len += sprintf(buf + len, "%d", SLIC_GetState(j));
-					break;
-				}
-			}
-			len += sprintf(buf + len, "\nBase Frame %2.2x.%2.2x", j->baseframe.high, j->baseframe.low);
-			len += sprintf(buf + len, "\nCID Base Frame %2d", j->cid_base_frame_size);
-#ifdef PERFMON_STATS
-			len += sprintf(buf + len, "\nTimer Checks %ld", j->timerchecks);
-			len += sprintf(buf + len, "\nRX Ready Checks %ld", j->rxreadycheck);
-			len += sprintf(buf + len, "\nTX Ready Checks %ld", j->txreadycheck);
-			len += sprintf(buf + len, "\nFrames Read %ld", j->framesread);
-			len += sprintf(buf + len, "\nFrames Written %ld", j->frameswritten);
-			len += sprintf(buf + len, "\nDry Buffer %ld", j->drybuffer);
-			len += sprintf(buf + len, "\nRead Waits %ld", j->read_wait);
-			len += sprintf(buf + len, "\nWrite Waits %ld", j->write_wait);
-                        len += sprintf(buf + len, "\nStatus Waits %ld", j->statuswait);
-                        len += sprintf(buf + len, "\nStatus Wait Fails %ld", j->statuswaitfail);
-                        len += sprintf(buf + len, "\nPControl Waits %ld", j->pcontrolwait);
-                        len += sprintf(buf + len, "\nPControl Wait Fails %ld", j->pcontrolwaitfail);
-                        len += sprintf(buf + len, "\nIs Control Ready Checks %ld", j->iscontrolready);
-                        len += sprintf(buf + len, "\nIs Control Ready Check failures %ld", j->iscontrolreadyfail);
-
-#endif
-			len += sprintf(buf + len, "\n");
-		}
-	}
-	return len;
-}
-
-static int ixj_read_proc(char *page, char **start, off_t off,
-                              int count, int *eof, void *data)
-{
-        int len = ixj_get_status_proc(page);
-        if (len <= off+count) *eof = 1;
-        *start = page + off;
-        len -= off;
-        if (len>count) len = count;
-        if (len<0) len = 0;
-        return len;
-}
-
-
-static void cleanup(void)
-{
-	int cnt;
-	IXJ *j;
-
-	for (cnt = 0; cnt < IXJMAX; cnt++) {
-		j = get_ixj(cnt);
-		if(j != NULL && j->DSPbase) {
-			if (ixjdebug & 0x0002)
-				printk(KERN_INFO "IXJ: Deleting timer for /dev/phone%d\n", cnt);
-			del_timer(&j->timer);
-			if (j->cardtype == QTI_LINEJACK) {
-				j->pld_scrw.bits.daafsyncen = 0;	/* Turn off DAA Frame Sync */
-
-				outb_p(j->pld_scrw.byte, j->XILINXbase);
-				j->pld_slicw.bits.rly1 = 0;
-				j->pld_slicw.bits.rly2 = 0;
-				j->pld_slicw.bits.rly3 = 0;
-				outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-				LED_SetState(0x0, j);
-				if (ixjdebug & 0x0002)
-					printk(KERN_INFO "IXJ: Releasing XILINX address for /dev/phone%d\n", cnt);
-				release_region(j->XILINXbase, 8);
-			} else if (j->cardtype == QTI_PHONEJACK_LITE || j->cardtype == QTI_PHONEJACK_PCI) {
-				if (ixjdebug & 0x0002)
-					printk(KERN_INFO "IXJ: Releasing XILINX address for /dev/phone%d\n", cnt);
-				release_region(j->XILINXbase, 4);
-			}
-			kfree(j->read_buffer);
-			kfree(j->write_buffer);
-			if (j->dev)
-				pnp_device_detach(j->dev);
-			if (ixjdebug & 0x0002)
-				printk(KERN_INFO "IXJ: Unregistering /dev/phone%d from LTAPI\n", cnt);
-			phone_unregister_device(&j->p);
-			if (ixjdebug & 0x0002)
-				printk(KERN_INFO "IXJ: Releasing DSP address for /dev/phone%d\n", cnt);
-			release_region(j->DSPbase, 16);
-#ifdef IXJ_DYN_ALLOC
-			if (ixjdebug & 0x0002)
-				printk(KERN_INFO "IXJ: Freeing memory for /dev/phone%d\n", cnt);
-			kfree(j);
-			ixj[cnt] = NULL;
-#endif
-		}
-	}
-	if (ixjdebug & 0x0002)
-		printk(KERN_INFO "IXJ: Removing /proc/ixj\n");
-	remove_proc_entry ("ixj", NULL);
-}
-
-/* Typedefs */
-typedef struct {
-	BYTE length;
-	DWORD bits;
-} DATABLOCK;
-
-static void PCIEE_WriteBit(WORD wEEPROMAddress, BYTE lastLCC, BYTE byData)
-{
-	lastLCC = lastLCC & 0xfb;
-	lastLCC = lastLCC | (byData ? 4 : 0);
-	outb(lastLCC, wEEPROMAddress);	/*set data out bit as appropriate */
-
-	mdelay(1);
-	lastLCC = lastLCC | 0x01;
-	outb(lastLCC, wEEPROMAddress);	/*SK rising edge */
-
-	byData = byData << 1;
-	lastLCC = lastLCC & 0xfe;
-	mdelay(1);
-	outb(lastLCC, wEEPROMAddress);	/*after delay, SK falling edge */
-
-}
-
-static BYTE PCIEE_ReadBit(WORD wEEPROMAddress, BYTE lastLCC)
-{
-	mdelay(1);
-	lastLCC = lastLCC | 0x01;
-	outb(lastLCC, wEEPROMAddress);	/*SK rising edge */
-
-	lastLCC = lastLCC & 0xfe;
-	mdelay(1);
-	outb(lastLCC, wEEPROMAddress);	/*after delay, SK falling edge */
-
-	return ((inb(wEEPROMAddress) >> 3) & 1);
-}
-
-static bool PCIEE_ReadWord(WORD wAddress, WORD wLoc, WORD * pwResult)
-{
-	BYTE lastLCC;
-	WORD wEEPROMAddress = wAddress + 3;
-	DWORD i;
-	BYTE byResult;
-	*pwResult = 0;
-	lastLCC = inb(wEEPROMAddress);
-	lastLCC = lastLCC | 0x02;
-	lastLCC = lastLCC & 0xfe;
-	outb(lastLCC, wEEPROMAddress);	/* CS hi, SK lo */
-
-	mdelay(1);		/* delay */
-
-	PCIEE_WriteBit(wEEPROMAddress, lastLCC, 1);
-	PCIEE_WriteBit(wEEPROMAddress, lastLCC, 1);
-	PCIEE_WriteBit(wEEPROMAddress, lastLCC, 0);
-	for (i = 0; i < 8; i++) {
-		PCIEE_WriteBit(wEEPROMAddress, lastLCC, wLoc & 0x80 ? 1 : 0);
-		wLoc <<= 1;
-	}
-
-	for (i = 0; i < 16; i++) {
-		byResult = PCIEE_ReadBit(wEEPROMAddress, lastLCC);
-		*pwResult = (*pwResult << 1) | byResult;
-	}
-
-	mdelay(1);		/* another delay */
-
-	lastLCC = lastLCC & 0xfd;
-	outb(lastLCC, wEEPROMAddress);	/* negate CS */
-
-	return 0;
-}
-
-static DWORD PCIEE_GetSerialNumber(WORD wAddress)
-{
-	WORD wLo, wHi;
-	if (PCIEE_ReadWord(wAddress, 62, &wLo))
-		return 0;
-	if (PCIEE_ReadWord(wAddress, 63, &wHi))
-		return 0;
-	return (((DWORD) wHi << 16) | wLo);
-}
-
-static int dspio[IXJMAX + 1] =
-{
-	0,
-};
-static int xio[IXJMAX + 1] =
-{
-	0,
-};
-
-module_param_array(dspio, int, NULL, 0);
-module_param_array(xio, int, NULL, 0);
-MODULE_DESCRIPTION("Quicknet VoIP Telephony card module - www.quicknet.net");
-MODULE_AUTHOR("Ed Okerson <eokerson@quicknet.net>");
-MODULE_LICENSE("GPL");
-
-static void __exit ixj_exit(void)
-{
-        cleanup();
-}
-
-static IXJ *new_ixj(unsigned long port)
-{
-	IXJ *res;
-	if (!request_region(port, 16, "ixj DSP")) {
-		printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", port);
-		return NULL;
-	}
-	res = ixj_alloc();
-	if (!res) {
-		release_region(port, 16);
-		printk(KERN_INFO "ixj: out of memory\n");
-		return NULL;
-	}
-	res->DSPbase = port;
-	return res;
-}
-
-static int __init ixj_probe_isapnp(int *cnt)
-{
-	int probe = 0;
-	int func = 0x110;
-        struct pnp_dev *dev = NULL, *old_dev = NULL;
-
-	while (1) {
-		do {
-			IXJ *j;
-			int result;
-
-			old_dev = dev;
-			dev = pnp_find_dev(NULL, ISAPNP_VENDOR('Q', 'T', 'I'),
-					 ISAPNP_FUNCTION(func), old_dev);
-			if (!dev || !dev->card)
-				break;
-			result = pnp_device_attach(dev);
-			if (result < 0) {
-				printk("pnp attach failed %d \n", result);
-				break;
-			}
-			if (pnp_activate_dev(dev) < 0) {
-				printk("pnp activate failed (out of resources?)\n");
-				pnp_device_detach(dev);
-				return -ENOMEM;
-			}
-
-			if (!pnp_port_valid(dev, 0)) {
-				pnp_device_detach(dev);
-				return -ENODEV;
-			}
-
-			j = new_ixj(pnp_port_start(dev, 0));
-			if (!j)
-				break;
-
-			if (func != 0x110)
-				j->XILINXbase = pnp_port_start(dev, 1);	/* get real port */
-
-			switch (func) {
-			case (0x110):
-				j->cardtype = QTI_PHONEJACK;
-				break;
-			case (0x310):
-				j->cardtype = QTI_LINEJACK;
-				break;
-			case (0x410):
-				j->cardtype = QTI_PHONEJACK_LITE;
-				break;
-			}
-			j->board = *cnt;
-			probe = ixj_selfprobe(j);
-			if(!probe) {
-				j->serial = dev->card->serial;
-				j->dev = dev;
-				switch (func) {
-				case 0x110:
-					printk(KERN_INFO "ixj: found Internet PhoneJACK at 0x%x\n", j->DSPbase);
-					break;
-				case 0x310:
-					printk(KERN_INFO "ixj: found Internet LineJACK at 0x%x\n", j->DSPbase);
-					break;
-				case 0x410:
-					printk(KERN_INFO "ixj: found Internet PhoneJACK Lite at 0x%x\n", j->DSPbase);
-					break;
-				}
-			}
-			++*cnt;
-		} while (dev);
-		if (func == 0x410)
-			break;
-		if (func == 0x310)
-			func = 0x410;
-		if (func == 0x110)
-			func = 0x310;
-		dev = NULL;
-	}
-	return probe;
-}
-
-static int __init ixj_probe_isa(int *cnt)
-{
-	int i, probe;
-
-	/* Use passed parameters for older kernels without PnP */
-	for (i = 0; i < IXJMAX; i++) {
-		if (dspio[i]) {
-			IXJ *j = new_ixj(dspio[i]);
-
-			if (!j)
-				break;
-
-			j->XILINXbase = xio[i];
-			j->cardtype = 0;
-
-			j->board = *cnt;
-			probe = ixj_selfprobe(j);
-			j->dev = NULL;
-			++*cnt;
-		}
-	}
-	return 0;
-}
-
-static int __init ixj_probe_pci(int *cnt)
-{
-	struct pci_dev *pci = NULL;
-	int i, probe = 0;
-	IXJ *j = NULL;
-
-	for (i = 0; i < IXJMAX - *cnt; i++) {
-		pci = pci_get_device(PCI_VENDOR_ID_QUICKNET,
-				      PCI_DEVICE_ID_QUICKNET_XJ, pci);
-		if (!pci)
-			break;
-
-		if (pci_enable_device(pci))
-			break;
-		j = new_ixj(pci_resource_start(pci, 0));
-		if (!j)
-			break;
-
-		j->serial = (PCIEE_GetSerialNumber)pci_resource_start(pci, 2);
-		j->XILINXbase = j->DSPbase + 0x10;
-		j->cardtype = QTI_PHONEJACK_PCI;
-		j->board = *cnt;
-		probe = ixj_selfprobe(j);
-		if (!probe)
-			printk(KERN_INFO "ixj: found Internet PhoneJACK PCI at 0x%x\n", j->DSPbase);
-		++*cnt;
-	}
-	pci_dev_put(pci);
-	return probe;
-}
-
-static int __init ixj_init(void)
-{
-	int cnt = 0;
-	int probe = 0;
-
-	cnt = 0;
-
-	/* These might be no-ops, see above. */
-	if ((probe = ixj_probe_isapnp(&cnt)) < 0) {
-		return probe;
-	}
-	if ((probe = ixj_probe_isa(&cnt)) < 0) {
-		return probe;
-	}
-	if ((probe = ixj_probe_pci(&cnt)) < 0) {
-		return probe;
-	}
-	printk(KERN_INFO "ixj driver initialized.\n");
-	create_proc_read_entry ("ixj", 0, NULL, ixj_read_proc, NULL);
-	return probe;
-}
-
-module_init(ixj_init);
-module_exit(ixj_exit);
-
-static void DAA_Coeff_US(IXJ *j)
-{
-	int i;
-
-	j->daa_country = DAA_US;
-	/*----------------------------------------------- */
-	/* CAO */
-	for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) {
-		j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0;
-	}
-
-/* Bytes for IM-filter part 1 (04): 0E,32,E2,2F,C2,5A,C0,00 */
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x03;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0x4B;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0x5D;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0xCD;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0x24;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0xC5;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00;
-/* Bytes for IM-filter part 2 (05): 72,85,00,0E,2B,3A,D0,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x71;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x1A;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x0A;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0xB5;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08;
-/* Bytes for FRX-filter       (08): 03,8F,48,F2,8F,48,70,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x05;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0xA3;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0x72;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0x34;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x3F;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x3B;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x30;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08;
-/* Bytes for FRR-filter       (07): 04,8F,38,7F,9B,EA,B0,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x05;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x87;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xF9;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x3E;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xDA;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xB0;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08;
-/* Bytes for AX-filter        (0A): 16,55,DD,CA */
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x41;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xB5;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA;
-/* Bytes for AR-filter        (09): 52,D3,11,42 */
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x25;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xC7;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6;
-/* Bytes for TH-filter part 1 (00): 00,42,48,81,B3,80,00,98 */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x81;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xA5;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98;
-/* Bytes for TH-filter part 2 (01): 02,F2,33,A0,68,AB,8A,AD */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xA2;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x2B;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0xB0;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0xE8;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0xAB;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x81;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xCC;
-/* Bytes for TH-filter part 3 (02): 00,88,DA,54,A4,BA,2D,BB */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0xD2;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0x24;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0xBA;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xA9;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x3B;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xA6;
-/* ;  (10K, 0.68uF) */
-	/*  */
-	/* Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 */
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0x3A;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x22;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23;
-	/* Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 */
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x22;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5;
-
-	/* Levelmetering Ringing        (0D):B2,45,0F,8E       */
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x35;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E;
-
-	/* Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1C; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0xB3; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0xAB; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0xAB; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x54; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x2D; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0x62; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x2D; */
-	/* Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x2D; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0x62; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBB; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x2A; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7D; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD4; */
-/* */
-	/* Levelmetering Ringing        (0D):B2,45,0F,8E       */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x05; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F; */
-/*	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E; */
-
-	/* Caller ID 1st Tone           (0E):CA,0E,CA,09,99,99,99,99 */
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99;
-/* Caller ID 2nd Tone           (0F):FD,B5,BA,07,DA,00,00,00 */
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00;
-/*  */
-	/* ;CR Registers */
-	/* Config. Reg. 0 (filters)       (cr0):FE ; CLK gen. by crystal */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF;
-/* Config. Reg. 1 (dialing)       (cr1):05 */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05;
-/* Config. Reg. 2 (caller ID)     (cr2):04 */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04;
-/* Config. Reg. 3 (testloops)     (cr3):03 ; SEL Bit==0, HP-disabled */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00;
-/* Config. Reg. 4 (analog gain)   (cr4):02 */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02;
-	/* Config. Reg. 5 (Version)       (cr5):02 */
-	/* Config. Reg. 6 (Reserved)      (cr6):00 */
-	/* Config. Reg. 7 (Reserved)      (cr7):00 */
-	/*  */
-	/* ;xr Registers */
-	/* Ext. Reg. 0 (Interrupt Reg.)   (xr0):02 */
-
-	j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02;	/* SO_1 set to '1' because it is inverted. */
-	/* Ext. Reg. 1 (Interrupt enable) (xr1):3C Cadence, RING, Caller ID, VDD_OK */
-
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x3C;
-/* Ext. Reg. 2 (Cadence Time Out) (xr2):7D */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D;
-/* Ext. Reg. 3 (DC Char)          (xr3):32 ; B-Filter Off == 1 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x3B;		/*0x32; */
-	/* Ext. Reg. 4 (Cadence)          (xr4):00 */
-
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00;
-/* Ext. Reg. 5 (Ring timer)       (xr5):22 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22;
-/* Ext. Reg. 6 (Power State)      (xr6):00 */
-	j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00;
-/* Ext. Reg. 7 (Vdd)              (xr7):40 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40;		/* 0x40 ??? Should it be 0x00? */
-	/*  */
-	/* DTMF Tone 1                     (0B): 11,B3,5A,2C ;   697 Hz   */
-	/*                                       12,33,5A,C3 ;  770 Hz   */
-	/*                                       13,3C,5B,32 ;  852 Hz   */
-	/*                                       1D,1B,5C,CC ;  941 Hz   */
-
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C;
-/* DTMF Tone 2                     (0C): 32,32,52,B3 ;  1209 Hz   */
-	/*                                       EC,1D,52,22 ;  1336 Hz   */
-	/*                                       AA,AC,51,D2 ;  1477 Hz   */
-	/*                                       9B,3B,51,25 ;  1633 Hz   */
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3;
-}
-
-static void DAA_Coeff_UK(IXJ *j)
-{
-	int i;
-
-	j->daa_country = DAA_UK;
-	/*----------------------------------------------- */
-	/* CAO */
-	for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) {
-		j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0;
-	}
-
-/*  Bytes for IM-filter part 1 (04): 00,C2,BB,A8,CB,81,A0,00 */
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xC2;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xBB;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0xA8;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0xCB;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x81;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00;
-/* Bytes for IM-filter part 2 (05): 40,00,00,0A,A4,33,E0,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x40;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x0A;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0xA4;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08;
-/* Bytes for FRX-filter       (08): 07,9B,ED,24,B2,A2,A0,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x9B;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0xED;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0x24;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0xB2;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0xA2;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xA0;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08;
-/* Bytes for FRR-filter       (07): 0F,92,F2,B2,87,D2,30,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x0F;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x92;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xF2;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0xB2;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x87;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xD2;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x30;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08;
-/* Bytes for AX-filter        (0A): 1B,A5,DD,CA */
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x1B;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xA5;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA;
-/* Bytes for AR-filter        (09): E2,27,10,D6 */
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0xE2;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x27;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6;
-/* Bytes for TH-filter part 1 (00): 80,2D,38,8B,D0,00,00,98 */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x2D;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x38;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x8B;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xD0;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98;
-/* Bytes for TH-filter part 2 (01): 02,5A,53,F0,0B,5F,84,D4 */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0x5A;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x53;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0xF0;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0x0B;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x5F;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x84;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xD4;
-/* Bytes for TH-filter part 3 (02): 00,88,6A,A4,8F,52,F5,32 */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0x6A;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0xA4;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0x8F;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x52;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0xF5;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x32;
-/* ; idle */
-	/* Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 */
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0x3A;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x22;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23;
-/* Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 */
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x22;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5;
-/* Levelmetering Ringing           (0D):AA,35,0F,8E     ; 25Hz 30V less possible? */
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x35;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E;
-/* Caller ID 1st Tone              (0E):CA,0E,CA,09,99,99,99,99 */
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99;
-/* Caller ID 2nd Tone              (0F):FD,B5,BA,07,DA,00,00,00 */
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00;
-/* ;CR Registers */
-	/* Config. Reg. 0 (filters)        (cr0):FF */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF;
-/* Config. Reg. 1 (dialing)        (cr1):05 */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05;
-/* Config. Reg. 2 (caller ID)      (cr2):04 */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04;
-/* Config. Reg. 3 (testloops)      (cr3):00        ;  */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00;
-/* Config. Reg. 4 (analog gain)    (cr4):02 */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02;
-	/* Config. Reg. 5 (Version)        (cr5):02 */
-	/* Config. Reg. 6 (Reserved)       (cr6):00 */
-	/* Config. Reg. 7 (Reserved)       (cr7):00 */
-	/* ;xr Registers */
-	/* Ext. Reg. 0 (Interrupt Reg.)    (xr0):02 */
-
-	j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02;	/* SO_1 set to '1' because it is inverted. */
-	/* Ext. Reg. 1 (Interrupt enable)  (xr1):1C */
-
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C;		/* RING, Caller ID, VDD_OK */
-	/* Ext. Reg. 2 (Cadence Time Out)  (xr2):7D */
-
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D;
-/* Ext. Reg. 3 (DC Char)           (xr3):36        ;  */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x36;
-/* Ext. Reg. 4 (Cadence)           (xr4):00 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00;
-/* Ext. Reg. 5 (Ring timer)        (xr5):22 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22;
-/* Ext. Reg. 6 (Power State)       (xr6):00 */
-	j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00;
-/* Ext. Reg. 7 (Vdd)               (xr7):46 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x46;		/* 0x46 ??? Should it be 0x00? */
-	/* DTMF Tone 1                     (0B): 11,B3,5A,2C    ;   697 Hz   */
-	/*                                       12,33,5A,C3    ;  770 Hz   */
-	/*                                       13,3C,5B,32    ;  852 Hz   */
-	/*                                       1D,1B,5C,CC    ;  941 Hz   */
-
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C;
-/* DTMF Tone 2                     (0C): 32,32,52,B3    ;  1209 Hz   */
-	/*                                       EC,1D,52,22    ;  1336 Hz   */
-	/*                                       AA,AC,51,D2    ;  1477 Hz   */
-	/*                                       9B,3B,51,25    ;  1633 Hz   */
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3;
-}
-
-
-static void DAA_Coeff_France(IXJ *j)
-{
-	int i;
-
-	j->daa_country = DAA_FRANCE;
-	/*----------------------------------------------- */
-	/* CAO */
-	for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) {
-		j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0;
-	}
-
-/* Bytes for IM-filter part 1 (04): 02,A2,43,2C,22,AF,A0,00 */
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x02;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xA2;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0x43;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x2C;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0x22;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0xAF;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00;
-/* Bytes for IM-filter part 2 (05): 67,CE,00,0C,22,33,E0,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x67;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0xCE;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x2C;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0x22;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08;
-/* Bytes for FRX-filter       (08): 07,9A,28,F6,23,4A,B0,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x9A;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0x28;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0xF6;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x23;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x4A;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xB0;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08;
-/* Bytes for FRR-filter       (07): 03,8F,F9,2F,9E,FA,20,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x03;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x8F;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xF9;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x2F;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x9E;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xFA;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x20;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08;
-/* Bytes for AX-filter        (0A): 16,B5,DD,CA */
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x16;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xB5;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA;
-/* Bytes for AR-filter        (09): 52,C7,10,D6 */
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0xE2;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xC7;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6;
-/* Bytes for TH-filter part 1 (00): 00,42,48,81,A6,80,00,98 */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x81;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xA6;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98;
-/* Bytes for TH-filter part 2 (01): 02,AC,2A,30,78,AC,8A,2C */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xAC;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x2A;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0x30;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0x78;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0xAC;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x8A;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x2C;
-/* Bytes for TH-filter part 3 (02): 00,88,DA,A5,22,BA,2C,45 */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0xDA;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0xA5;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0x22;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xBA;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x2C;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x45;
-/* ; idle */
-	/* Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 */
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0x3A;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x22;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23;
-/* Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 */
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x22;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5;
-/* Levelmetering Ringing           (0D):32,45,B5,84     ; 50Hz 20V */
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0xB5;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x84;
-/* Caller ID 1st Tone              (0E):CA,0E,CA,09,99,99,99,99 */
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99;
-/* Caller ID 2nd Tone              (0F):FD,B5,BA,07,DA,00,00,00 */
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00;
-/* ;CR Registers */
-	/* Config. Reg. 0 (filters)        (cr0):FF */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF;
-/* Config. Reg. 1 (dialing)        (cr1):05 */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05;
-/* Config. Reg. 2 (caller ID)      (cr2):04 */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04;
-/* Config. Reg. 3 (testloops)      (cr3):00        ;  */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00;
-/* Config. Reg. 4 (analog gain)    (cr4):02 */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02;
-	/* Config. Reg. 5 (Version)        (cr5):02 */
-	/* Config. Reg. 6 (Reserved)       (cr6):00 */
-	/* Config. Reg. 7 (Reserved)       (cr7):00 */
-	/* ;xr Registers */
-	/* Ext. Reg. 0 (Interrupt Reg.)    (xr0):02 */
-
-	j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02;	/* SO_1 set to '1' because it is inverted. */
-	/* Ext. Reg. 1 (Interrupt enable)  (xr1):1C */
-
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C;		/* RING, Caller ID, VDD_OK */
-	/* Ext. Reg. 2 (Cadence Time Out)  (xr2):7D */
-
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D;
-/* Ext. Reg. 3 (DC Char)           (xr3):36        ;  */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x36;
-/* Ext. Reg. 4 (Cadence)           (xr4):00 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00;
-/* Ext. Reg. 5 (Ring timer)        (xr5):22 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22;
-/* Ext. Reg. 6 (Power State)       (xr6):00 */
-	j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00;
-/* Ext. Reg. 7 (Vdd)               (xr7):46 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x46;		/* 0x46 ??? Should it be 0x00? */
-	/* DTMF Tone 1                     (0B): 11,B3,5A,2C    ;   697 Hz   */
-	/*                                       12,33,5A,C3    ;  770 Hz   */
-	/*                                       13,3C,5B,32    ;  852 Hz   */
-	/*                                       1D,1B,5C,CC    ;  941 Hz   */
-
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C;
-/* DTMF Tone 2                     (0C): 32,32,52,B3    ;  1209 Hz   */
-	/*                                       EC,1D,52,22    ;  1336 Hz   */
-	/*                                       AA,AC,51,D2    ;  1477 Hz   */
-	/*                                       9B,3B,51,25    ;  1633 Hz   */
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3;
-}
-
-
-static void DAA_Coeff_Germany(IXJ *j)
-{
-	int i;
-
-	j->daa_country = DAA_GERMANY;
-	/*----------------------------------------------- */
-	/* CAO */
-	for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) {
-		j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0;
-	}
-
-/* Bytes for IM-filter part 1 (04): 00,CE,BB,B8,D2,81,B0,00 */
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xCE;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xBB;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0xB8;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0xD2;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x81;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xB0;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00;
-/* Bytes for IM-filter part 2 (05): 45,8F,00,0C,D2,3A,D0,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x45;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x8F;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x0C;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0xD2;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x3A;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xD0;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08;
-/* Bytes for FRX-filter       (08): 07,AA,E2,34,24,89,20,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0xAA;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0xE2;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0x34;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x24;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x89;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x20;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08;
-/* Bytes for FRR-filter       (07): 02,87,FA,37,9A,CA,B0,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x02;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x87;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xFA;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x37;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x9A;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xCA;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xB0;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08;
-/* Bytes for AX-filter        (0A): 72,D5,DD,CA */
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x72;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xD5;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA;
-/* Bytes for AR-filter        (09): 72,42,13,4B */
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x72;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x42;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x13;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0x4B;
-/* Bytes for TH-filter part 1 (00): 80,52,48,81,AD,80,00,98 */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x52;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x81;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xAD;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98;
-/* Bytes for TH-filter part 2 (01): 02,42,5A,20,E8,1A,81,27 */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0x42;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x5A;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0x20;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0xE8;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x1A;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x81;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x27;
-/* Bytes for TH-filter part 3 (02): 00,88,63,26,BD,4B,A3,C2 */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0x63;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0x26;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0xBD;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x4B;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0xA3;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xC2;
-/* ;  (10K, 0.68uF) */
-	/* Bytes for Ringing part 1 (03):1B,3B,9B,BA,D4,1C,B3,23 */
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3B;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x9B;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0xBA;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0xD4;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x1C;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xB3;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23;
-/* Bytes for Ringing part 2 (06):13,42,A6,BA,D4,73,CA,D5 */
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x13;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0x42;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0xD4;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x73;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0xCA;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5;
-/* Levelmetering Ringing        (0D):B2,45,0F,8E       */
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xB2;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E;
-/* Caller ID 1st Tone           (0E):CA,0E,CA,09,99,99,99,99 */
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99;
-/* Caller ID 2nd Tone           (0F):FD,B5,BA,07,DA,00,00,00 */
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00;
-/* ;CR Registers */
-	/* Config. Reg. 0 (filters)        (cr0):FF ; all Filters enabled, CLK from ext. source */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF;
-/* Config. Reg. 1 (dialing)        (cr1):05 ; Manual Ring, Ring metering enabled */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05;
-/* Config. Reg. 2 (caller ID)      (cr2):04 ; Analog Gain 0dB, FSC internal */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04;
-/* Config. Reg. 3 (testloops)      (cr3):00 ; SEL Bit==0, HP-enabled */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00;
-/* Config. Reg. 4 (analog gain)    (cr4):02 */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02;
-	/* Config. Reg. 5 (Version)        (cr5):02 */
-	/* Config. Reg. 6 (Reserved)       (cr6):00 */
-	/* Config. Reg. 7 (Reserved)       (cr7):00 */
-	/* ;xr Registers */
-	/* Ext. Reg. 0 (Interrupt Reg.)    (xr0):02 */
-
-	j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02;	/* SO_1 set to '1' because it is inverted. */
-	/* Ext. Reg. 1 (Interrupt enable)  (xr1):1C ; Ring, CID, VDDOK Interrupts enabled */
-
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C;		/* RING, Caller ID, VDD_OK */
-	/* Ext. Reg. 2 (Cadence Time Out)  (xr2):7D */
-
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D;
-/* Ext. Reg. 3 (DC Char)           (xr3):32 ; B-Filter Off==1, U0=3.5V, R=200Ohm */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x32;
-/* Ext. Reg. 4 (Cadence)           (xr4):00 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00;
-/* Ext. Reg. 5 (Ring timer)        (xr5):22 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22;
-/* Ext. Reg. 6 (Power State)       (xr6):00 */
-	j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00;
-/* Ext. Reg. 7 (Vdd)               (xr7):40 ; VDD=4.25 V */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40;		/* 0x40 ??? Should it be 0x00? */
-	/* DTMF Tone 1                     (0B): 11,B3,5A,2C    ;   697 Hz   */
-	/*                                       12,33,5A,C3    ;  770 Hz   */
-	/*                                       13,3C,5B,32    ;  852 Hz   */
-	/*                                       1D,1B,5C,CC    ;  941 Hz   */
-
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C;
-/* DTMF Tone 2                     (0C): 32,32,52,B3    ;  1209 Hz   */
-	/*                                       EC,1D,52,22    ;  1336 Hz   */
-	/*                                       AA,AC,51,D2    ;  1477 Hz   */
-	/*                                       9B,3B,51,25    ;  1633 Hz   */
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3;
-}
-
-
-static void DAA_Coeff_Australia(IXJ *j)
-{
-	int i;
-
-	j->daa_country = DAA_AUSTRALIA;
-	/*----------------------------------------------- */
-	/* CAO */
-	for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) {
-		j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0;
-	}
-
-/* Bytes for IM-filter part 1 (04): 00,A3,AA,28,B3,82,D0,00 */
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xA3;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xAA;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x28;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0xB3;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0x82;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xD0;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00;
-/* Bytes for IM-filter part 2 (05): 70,96,00,09,32,6B,C0,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x70;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0x96;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x09;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x6B;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xC0;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08;
-/* Bytes for FRX-filter       (08): 07,96,E2,34,32,9B,30,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x07;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x96;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0xE2;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0x34;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x9B;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0x30;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08;
-/* Bytes for FRR-filter       (07): 0F,9A,E9,2F,22,CC,A0,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x0F;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x9A;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0xE9;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x2F;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x22;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xCC;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0xA0;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08;
-/* Bytes for AX-filter        (0A): CB,45,DD,CA */
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0xCB;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0x45;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA;
-/* Bytes for AR-filter        (09): 1B,67,10,D6 */
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x1B;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0x67;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6;
-/* Bytes for TH-filter part 1 (00): 80,52,48,81,AF,80,00,98 */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x80;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x52;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x81;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xAF;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98;
-/* Bytes for TH-filter part 2 (01): 02,DB,52,B0,38,01,82,AC */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xDB;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x52;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0xB0;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0x38;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x01;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x82;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0xAC;
-/* Bytes for TH-filter part 3 (02): 00,88,4A,3E,2C,3B,24,46 */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0x4A;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0x3E;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0x2C;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0x3B;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x24;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0x46;
-/* ;  idle */
-	/* Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 */
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0x3A;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x22;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23;
-/* Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 */
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x22;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5;
-/* Levelmetering Ringing           (0D):32,45,B5,84   ; 50Hz 20V */
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x45;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0xB5;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x84;
-/* Caller ID 1st Tone              (0E):CA,0E,CA,09,99,99,99,99 */
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99;
-/* Caller ID 2nd Tone              (0F):FD,B5,BA,07,DA,00,00,00 */
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00;
-/* ;CR Registers */
-	/* Config. Reg. 0 (filters)        (cr0):FF */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF;
-/* Config. Reg. 1 (dialing)        (cr1):05 */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05;
-/* Config. Reg. 2 (caller ID)      (cr2):04 */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04;
-/* Config. Reg. 3 (testloops)      (cr3):00        ;  */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00;
-/* Config. Reg. 4 (analog gain)    (cr4):02 */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02;
-	/* Config. Reg. 5 (Version)        (cr5):02 */
-	/* Config. Reg. 6 (Reserved)       (cr6):00 */
-	/* Config. Reg. 7 (Reserved)       (cr7):00 */
-	/* ;xr Registers */
-	/* Ext. Reg. 0 (Interrupt Reg.)    (xr0):02 */
-
-	j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02;	/* SO_1 set to '1' because it is inverted. */
-	/* Ext. Reg. 1 (Interrupt enable)  (xr1):1C */
-
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C;		/* RING, Caller ID, VDD_OK */
-	/* Ext. Reg. 2 (Cadence Time Out)  (xr2):7D */
-
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D;
-/* Ext. Reg. 3 (DC Char)           (xr3):2B      ;  */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x2B;
-/* Ext. Reg. 4 (Cadence)           (xr4):00 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00;
-/* Ext. Reg. 5 (Ring timer)        (xr5):22 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22;
-/* Ext. Reg. 6 (Power State)       (xr6):00 */
-	j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00;
-/* Ext. Reg. 7 (Vdd)               (xr7):40 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40;		/* 0x40 ??? Should it be 0x00? */
-
-	/* DTMF Tone 1                     (0B): 11,B3,5A,2C    ;  697 Hz   */
-	/*                                       12,33,5A,C3    ;  770 Hz   */
-	/*                                       13,3C,5B,32    ;  852 Hz   */
-	/*                                       1D,1B,5C,CC    ;  941 Hz   */
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C;
-
-	/* DTMF Tone 2                     (0C): 32,32,52,B3    ;  1209 Hz   */
-	/*                                       EC,1D,52,22    ;  1336 Hz   */
-	/*                                       AA,AC,51,D2    ;  1477 Hz   */
-	/*                                       9B,3B,51,25    ;  1633 Hz   */
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3;
-}
-
-static void DAA_Coeff_Japan(IXJ *j)
-{
-	int i;
-
-	j->daa_country = DAA_JAPAN;
-	/*----------------------------------------------- */
-	/* CAO */
-	for (i = 0; i < ALISDAA_CALLERID_SIZE; i++) {
-		j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID[i] = 0;
-	}
-
-/* Bytes for IM-filter part 1 (04): 06,BD,E2,2D,BA,F9,A0,00 */
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7] = 0x06;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6] = 0xBD;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5] = 0xE2;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4] = 0x2D;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3] = 0xBA;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2] = 0xF9;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1] = 0xA0;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0] = 0x00;
-/* Bytes for IM-filter part 2 (05): 6F,F7,00,0E,34,33,E0,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7] = 0x6F;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6] = 0xF7;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4] = 0x0E;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3] = 0x34;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2] = 0x33;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1] = 0xE0;
-	j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0] = 0x08;
-/* Bytes for FRX-filter       (08): 02,8F,68,77,9C,58,F0,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7] = 0x02;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6] = 0x8F;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5] = 0x68;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4] = 0x77;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3] = 0x9C;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2] = 0x58;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1] = 0xF0;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0] = 0x08;
-/* Bytes for FRR-filter       (07): 03,8F,38,73,87,EA,20,08 */
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7] = 0x03;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6] = 0x8F;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5] = 0x38;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4] = 0x73;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3] = 0x87;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2] = 0xEA;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1] = 0x20;
-	j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0] = 0x08;
-/* Bytes for AX-filter        (0A): 51,C5,DD,CA */
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3] = 0x51;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2] = 0xC5;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1] = 0xDD;
-	j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0] = 0xCA;
-/* Bytes for AR-filter        (09): 25,A7,10,D6 */
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3] = 0x25;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2] = 0xA7;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1] = 0x10;
-	j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0] = 0xD6;
-/* Bytes for TH-filter part 1 (00): 00,42,48,81,AE,80,00,98 */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6] = 0x42;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5] = 0x48;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4] = 0x81;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3] = 0xAE;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2] = 0x80;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0] = 0x98;
-/* Bytes for TH-filter part 2 (01): 02,AB,2A,20,99,5B,89,28 */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7] = 0x02;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6] = 0xAB;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5] = 0x2A;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4] = 0x20;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2] = 0x5B;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1] = 0x89;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0] = 0x28;
-/* Bytes for TH-filter part 3 (02): 00,88,DA,25,34,C5,4C,BA */
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6] = 0x88;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5] = 0xDA;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4] = 0x25;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3] = 0x34;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2] = 0xC5;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1] = 0x4C;
-	j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0] = 0xBA;
-/* ;  idle */
-	/* Bytes for Ringing part 1 (03):1B,3C,93,3A,22,12,A3,23 */
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7] = 0x1B;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6] = 0x3C;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5] = 0x93;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4] = 0x3A;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3] = 0x22;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2] = 0x12;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1] = 0xA3;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0] = 0x23;
-/* Bytes for Ringing part 2 (06):12,A2,A6,BA,22,7A,0A,D5 */
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7] = 0x12;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6] = 0xA2;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5] = 0xA6;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4] = 0xBA;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3] = 0x22;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2] = 0x7A;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1] = 0x0A;
-	j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0] = 0xD5;
-/* Levelmetering Ringing           (0D):AA,35,0F,8E    ; 25Hz 30V ????????? */
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3] = 0xAA;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2] = 0x35;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1] = 0x0F;
-	j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0] = 0x8E;
-/* Caller ID 1st Tone              (0E):CA,0E,CA,09,99,99,99,99 */
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7] = 0xCA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6] = 0x0E;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5] = 0xCA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4] = 0x09;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1] = 0x99;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0] = 0x99;
-/* Caller ID 2nd Tone              (0F):FD,B5,BA,07,DA,00,00,00 */
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7] = 0xFD;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6] = 0xB5;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5] = 0xBA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4] = 0x07;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3] = 0xDA;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1] = 0x00;
-	j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0] = 0x00;
-/* ;CR Registers */
-	/* Config. Reg. 0 (filters)        (cr0):FF */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg = 0xFF;
-/* Config. Reg. 1 (dialing)        (cr1):05 */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg = 0x05;
-/* Config. Reg. 2 (caller ID)      (cr2):04 */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg = 0x04;
-/* Config. Reg. 3 (testloops)      (cr3):00        ;  */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg = 0x00;
-/* Config. Reg. 4 (analog gain)    (cr4):02 */
-	j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg = 0x02;
-	/* Config. Reg. 5 (Version)        (cr5):02 */
-	/* Config. Reg. 6 (Reserved)       (cr6):00 */
-	/* Config. Reg. 7 (Reserved)       (cr7):00 */
-	/* ;xr Registers */
-	/* Ext. Reg. 0 (Interrupt Reg.)    (xr0):02 */
-
-	j->m_DAAShadowRegs.XOP_xr0_W.reg = 0x02;	/* SO_1 set to '1' because it is inverted. */
-	/* Ext. Reg. 1 (Interrupt enable)  (xr1):1C */
-
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg = 0x1C;		/* RING, Caller ID, VDD_OK */
-	/* Ext. Reg. 2 (Cadence Time Out)  (xr2):7D */
-
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg = 0x7D;
-/* Ext. Reg. 3 (DC Char)           (xr3):22        ;  */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg = 0x22;
-/* Ext. Reg. 4 (Cadence)           (xr4):00 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg = 0x00;
-/* Ext. Reg. 5 (Ring timer)        (xr5):22 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg = 0x22;
-/* Ext. Reg. 6 (Power State)       (xr6):00 */
-	j->m_DAAShadowRegs.XOP_xr6_W.reg = 0x00;
-/* Ext. Reg. 7 (Vdd)               (xr7):40 */
-	j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg = 0x40;		/* 0x40 ??? Should it be 0x00? */
-	/* DTMF Tone 1                     (0B): 11,B3,5A,2C    ;   697 Hz   */
-	/*                                       12,33,5A,C3    ;  770 Hz   */
-	/*                                       13,3C,5B,32    ;  852 Hz   */
-	/*                                       1D,1B,5C,CC    ;  941 Hz   */
-
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3] = 0x11;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2] = 0xB3;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1] = 0x5A;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0] = 0x2C;
-/* DTMF Tone 2                     (0C): 32,32,52,B3    ;  1209 Hz   */
-	/*                                       EC,1D,52,22    ;  1336 Hz   */
-	/*                                       AA,AC,51,D2    ;  1477 Hz   */
-	/*                                       9B,3B,51,25    ;  1633 Hz   */
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2] = 0x32;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1] = 0x52;
-	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3;
-}
-
-static s16 tone_table[][19] =
-{
-	{			/* f20_50[] 11 */
-		32538,		/* A1 = 1.985962 */
-		 -32325,	/* A2 = -0.986511 */
-		 -343,		/* B2 = -0.010493 */
-		 0,		/* B1 = 0 */
-		 343,		/* B0 = 0.010493 */
-		 32619,		/* A1 = 1.990906 */
-		 -32520,	/* A2 = -0.992462 */
-		 19179,		/* B2 = 0.585327 */
-		 -19178,	/* B1 = -1.170593 */
-		 19179,		/* B0 = 0.585327 */
-		 32723,		/* A1 = 1.997314 */
-		 -32686,	/* A2 = -0.997528 */
-		 9973,		/* B2 = 0.304352 */
-		 -9955,		/* B1 = -0.607605 */
-		 9973,		/* B0 = 0.304352 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f133_200[] 12 */
-		32072,		/* A1 = 1.95752 */
-		 -31896,	/* A2 = -0.973419 */
-		 -435,		/* B2 = -0.013294 */
-		 0,		/* B1 = 0 */
-		 435,		/* B0 = 0.013294 */
-		 32188,		/* A1 = 1.9646 */
-		 -32400,	/* A2 = -0.98877 */
-		 15139,		/* B2 = 0.462036 */
-		 -14882,	/* B1 = -0.908356 */
-		 15139,		/* B0 = 0.462036 */
-		 32473,		/* A1 = 1.981995 */
-		 -32524,	/* A2 = -0.992584 */
-		 23200,		/* B2 = 0.708008 */
-		 -23113,	/* B1 = -1.410706 */
-		 23200,		/* B0 = 0.708008 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f300 13 */
-		31769,		/* A1 = -1.939026 */
-		 -32584,	/* A2 = 0.994385 */
-		 -475,		/* B2 = -0.014522 */
-		 0,		/* B1 = 0.000000 */
-		 475,		/* B0 = 0.014522 */
-		 31789,		/* A1 = -1.940247 */
-		 -32679,	/* A2 = 0.997284 */
-		 17280,		/* B2 = 0.527344 */
-		 -16865,	/* B1 = -1.029358 */
-		 17280,		/* B0 = 0.527344 */
-		 31841,		/* A1 = -1.943481 */
-		 -32681,	/* A2 = 0.997345 */
-		 543,		/* B2 = 0.016579 */
-		 -525,		/* B1 = -0.032097 */
-		 543,		/* B0 = 0.016579 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f300_420[] 14 */
-		30750,		/* A1 = 1.876892 */
-		 -31212,	/* A2 = -0.952515 */
-		 -804,		/* B2 = -0.024541 */
-		 0,		/* B1 = 0 */
-		 804,		/* B0 = 0.024541 */
-		 30686,		/* A1 = 1.872925 */
-		 -32145,	/* A2 = -0.980988 */
-		 14747,		/* B2 = 0.450043 */
-		 -13703,	/* B1 = -0.836395 */
-		 14747,		/* B0 = 0.450043 */
-		 31651,		/* A1 = 1.931824 */
-		 -32321,	/* A2 = -0.986389 */
-		 24425,		/* B2 = 0.745422 */
-		 -23914,	/* B1 = -1.459595 */
-		 24427,		/* B0 = 0.745483 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f330 15 */
-		31613,		/* A1 = -1.929565 */
-		 -32646,	/* A2 = 0.996277 */
-		 -185,		/* B2 = -0.005657 */
-		 0,		/* B1 = 0.000000 */
-		 185,		/* B0 = 0.005657 */
-		 31620,		/* A1 = -1.929932 */
-		 -32713,	/* A2 = 0.998352 */
-		 19253,		/* B2 = 0.587585 */
-		 -18566,	/* B1 = -1.133179 */
-		 19253,		/* B0 = 0.587585 */
-		 31674,		/* A1 = -1.933228 */
-		 -32715,	/* A2 = 0.998413 */
-		 2575,		/* B2 = 0.078590 */
-		 -2495,		/* B1 = -0.152283 */
-		 2575,		/* B0 = 0.078590 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f300_425[] 16 */
-		30741,		/* A1 = 1.876282 */
-		 -31475,	/* A2 = -0.960541 */
-		 -703,		/* B2 = -0.021484 */
-		 0,		/* B1 = 0 */
-		 703,		/* B0 = 0.021484 */
-		 30688,		/* A1 = 1.873047 */
-		 -32248,	/* A2 = -0.984161 */
-		 14542,		/* B2 = 0.443787 */
-		 -13523,	/* B1 = -0.825439 */
-		 14542,		/* B0 = 0.443817 */
-		 31494,		/* A1 = 1.922302 */
-		 -32366,	/* A2 = -0.987762 */
-		 21577,		/* B2 = 0.658508 */
-		 -21013,	/* B1 = -1.282532 */
-		 21577,		/* B0 = 0.658508 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f330_440[] 17 */
-		30627,		/* A1 = 1.869324 */
-		 -31338,	/* A2 = -0.95636 */
-		 -843,		/* B2 = -0.025749 */
-		 0,		/* B1 = 0 */
-		 843,		/* B0 = 0.025749 */
-		 30550,		/* A1 = 1.864685 */
-		 -32221,	/* A2 = -0.983337 */
-		 13594,		/* B2 = 0.414886 */
-		 -12589,	/* B1 = -0.768402 */
-		 13594,		/* B0 = 0.414886 */
-		 31488,		/* A1 = 1.921936 */
-		 -32358,	/* A2 = -0.987518 */
-		 24684,		/* B2 = 0.753296 */
-		 -24029,	/* B1 = -1.466614 */
-		 24684,		/* B0 = 0.753296 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f340 18 */
-		31546,		/* A1 = -1.925476 */
-		 -32646,	/* A2 = 0.996277 */
-		 -445,		/* B2 = -0.013588 */
-		 0,		/* B1 = 0.000000 */
-		 445,		/* B0 = 0.013588 */
-		 31551,		/* A1 = -1.925781 */
-		 -32713,	/* A2 = 0.998352 */
-		 23884,		/* B2 = 0.728882 */
-		 -22979,	/* B1 = -1.402527 */
-		 23884,		/* B0 = 0.728882 */
-		 31606,		/* A1 = -1.929138 */
-		 -32715,	/* A2 = 0.998413 */
-		 863,		/* B2 = 0.026367 */
-		 -835,		/* B1 = -0.050985 */
-		 863,		/* B0 = 0.026367 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f350_400[] 19 */
-		31006,		/* A1 = 1.892517 */
-		 -32029,	/* A2 = -0.977448 */
-		 -461,		/* B2 = -0.014096 */
-		 0,		/* B1 = 0 */
-		 461,		/* B0 = 0.014096 */
-		 30999,		/* A1 = 1.892029 */
-		 -32487,	/* A2 = -0.991455 */
-		 11325,		/* B2 = 0.345612 */
-		 -10682,	/* B1 = -0.651978 */
-		 11325,		/* B0 = 0.345612 */
-		 31441,		/* A1 = 1.919067 */
-		 -32526,	/* A2 = -0.992615 */
-		 24324,		/* B2 = 0.74231 */
-		 -23535,	/* B1 = -1.436523 */
-		 24324,		/* B0 = 0.74231 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f350_440[] */
-		30634,		/* A1 = 1.869751 */
-		 -31533,	/* A2 = -0.962341 */
-		 -680,		/* B2 = -0.020782 */
-		 0,		/* B1 = 0 */
-		 680,		/* B0 = 0.020782 */
-		 30571,		/* A1 = 1.865906 */
-		 -32277,	/* A2 = -0.985016 */
-		 12894,		/* B2 = 0.393524 */
-		 -11945,	/* B1 = -0.729065 */
-		 12894,		/* B0 = 0.393524 */
-		 31367,		/* A1 = 1.91449 */
-		 -32379,	/* A2 = -0.988129 */
-		 23820,		/* B2 = 0.726929 */
-		 -23104,	/* B1 = -1.410217 */
-		 23820,		/* B0 = 0.726929 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f350_450[] */
-		30552,		/* A1 = 1.864807 */
-		 -31434,	/* A2 = -0.95929 */
-		 -690,		/* B2 = -0.021066 */
-		 0,		/* B1 = 0 */
-		 690,		/* B0 = 0.021066 */
-		 30472,		/* A1 = 1.859924 */
-		 -32248,	/* A2 = -0.984161 */
-		 13385,		/* B2 = 0.408478 */
-		 -12357,	/* B1 = -0.754242 */
-		 13385,		/* B0 = 0.408478 */
-		 31358,		/* A1 = 1.914001 */
-		 -32366,	/* A2 = -0.987732 */
-		 26488,		/* B2 = 0.80835 */
-		 -25692,	/* B1 = -1.568176 */
-		 26490,		/* B0 = 0.808411 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f360 */
-		31397,		/* A1 = -1.916321 */
-		 -32623,	/* A2 = 0.995605 */
-		 -117,		/* B2 = -0.003598 */
-		 0,		/* B1 = 0.000000 */
-		 117,		/* B0 = 0.003598 */
-		 31403,		/* A1 = -1.916687 */
-		 -32700,	/* A2 = 0.997925 */
-		 3388,		/* B2 = 0.103401 */
-		 -3240,		/* B1 = -0.197784 */
-		 3388,		/* B0 = 0.103401 */
-		 31463,		/* A1 = -1.920410 */
-		 -32702,	/* A2 = 0.997986 */
-		 13346,		/* B2 = 0.407288 */
-		 -12863,	/* B1 = -0.785126 */
-		 13346,		/* B0 = 0.407288 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f380_420[] */
-		30831,		/* A1 = 1.881775 */
-		 -32064,	/* A2 = -0.978546 */
-		 -367,		/* B2 = -0.01122 */
-		 0,		/* B1 = 0 */
-		 367,		/* B0 = 0.01122 */
-		 30813,		/* A1 = 1.880737 */
-		 -32456,	/* A2 = -0.990509 */
-		 11068,		/* B2 = 0.337769 */
-		 -10338,	/* B1 = -0.631042 */
-		 11068,		/* B0 = 0.337769 */
-		 31214,		/* A1 = 1.905212 */
-		 -32491,	/* A2 = -0.991577 */
-		 16374,		/* B2 = 0.499695 */
-		 -15781,	/* B1 = -0.963196 */
-		 16374,		/* B0 = 0.499695 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f392 */
-		31152,		/* A1 = -1.901428 */
-		 -32613,	/* A2 = 0.995300 */
-		 -314,		/* B2 = -0.009605 */
-		 0,		/* B1 = 0.000000 */
-		 314,		/* B0 = 0.009605 */
-		 31156,		/* A1 = -1.901672 */
-		 -32694,	/* A2 = 0.997742 */
-		 28847,		/* B2 = 0.880371 */
-		 -2734,		/* B1 = -0.166901 */
-		 28847,		/* B0 = 0.880371 */
-		 31225,		/* A1 = -1.905823 */
-		 -32696,	/* A2 = 0.997803 */
-		 462,		/* B2 = 0.014108 */
-		 -442,		/* B1 = -0.027019 */
-		 462,		/* B0 = 0.014108 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f400_425[] */
-		30836,		/* A1 = 1.882141 */
-		 -32296,	/* A2 = -0.985596 */
-		 -324,		/* B2 = -0.009903 */
-		 0,		/* B1 = 0 */
-		 324,		/* B0 = 0.009903 */
-		 30825,		/* A1 = 1.881409 */
-		 -32570,	/* A2 = -0.993958 */
-		 16847,		/* B2 = 0.51416 */
-		 -15792,	/* B1 = -0.963898 */
-		 16847,		/* B0 = 0.51416 */
-		 31106,		/* A1 = 1.89856 */
-		 -32584,	/* A2 = -0.994415 */
-		 9579,		/* B2 = 0.292328 */
-		 -9164,		/* B1 = -0.559357 */
-		 9579,		/* B0 = 0.292328 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f400_440[] */
-		30702,		/* A1 = 1.873962 */
-		 -32134,	/* A2 = -0.980682 */
-		 -517,		/* B2 = -0.015793 */
-		 0,		/* B1 = 0 */
-		 517,		/* B0 = 0.015793 */
-		 30676,		/* A1 = 1.872375 */
-		 -32520,	/* A2 = -0.992462 */
-		 8144,		/* B2 = 0.24855 */
-		 -7596,		/* B1 = -0.463684 */
-		 8144,		/* B0 = 0.24855 */
-		 31084,		/* A1 = 1.897217 */
-		 -32547,	/* A2 = -0.993256 */
-		 22713,		/* B2 = 0.693176 */
-		 -21734,	/* B1 = -1.326599 */
-		 22713,		/* B0 = 0.693176 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f400_450[] */
-		30613,		/* A1 = 1.86853 */
-		 -32031,	/* A2 = -0.977509 */
-		 -618,		/* B2 = -0.018866 */
-		 0,		/* B1 = 0 */
-		 618,		/* B0 = 0.018866 */
-		 30577,		/* A1 = 1.866272 */
-		 -32491,	/* A2 = -0.991577 */
-		 9612,		/* B2 = 0.293335 */
-		 -8935,		/* B1 = -0.54541 */
-		 9612,		/* B0 = 0.293335 */
-		 31071,		/* A1 = 1.896484 */
-		 -32524,	/* A2 = -0.992584 */
-		 21596,		/* B2 = 0.659058 */
-		 -20667,	/* B1 = -1.261414 */
-		 21596,		/* B0 = 0.659058 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f420 */
-		30914,		/* A1 = -1.886841 */
-		 -32584,	/* A2 = 0.994385 */
-		 -426,		/* B2 = -0.013020 */
-		 0,		/* B1 = 0.000000 */
-		 426,		/* B0 = 0.013020 */
-		 30914,		/* A1 = -1.886841 */
-		 -32679,	/* A2 = 0.997314 */
-		 17520,		/* B2 = 0.534668 */
-		 -16471,	/* B1 = -1.005310 */
-		 17520,		/* B0 = 0.534668 */
-		 31004,		/* A1 = -1.892334 */
-		 -32683,	/* A2 = 0.997406 */
-		 819,		/* B2 = 0.025023 */
-		 -780,		/* B1 = -0.047619 */
-		 819,		/* B0 = 0.025023 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-#if 0
-	{			/* f425 */
-		30881,		/* A1 = -1.884827 */
-		 -32603,	/* A2 = 0.994965 */
-		 -496,		/* B2 = -0.015144 */
-		 0,		/* B1 = 0.000000 */
-		 496,		/* B0 = 0.015144 */
-		 30880,		/* A1 = -1.884766 */
-		 -32692,	/* A2 = 0.997711 */
-		 24767,		/* B2 = 0.755859 */
-		 -23290,	/* B1 = -1.421509 */
-		 24767,		/* B0 = 0.755859 */
-		 30967,		/* A1 = -1.890076 */
-		 -32694,	/* A2 = 0.997772 */
-		 728,		/* B2 = 0.022232 */
-		 -691,		/* B1 = -0.042194 */
-		 728,		/* B0 = 0.022232 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-#else
-	{
-		30850,
-		-32534,
-		-504,
-		0,
-		504,
-		30831,
-		-32669,
-		24303,
-		-22080,
-		24303,
-		30994,
-		-32673,
-		1905,
-		-1811,
-		1905,
-		5,
-		129,
-		17,
-		0xff5
-	},
-#endif
-	{			/* f425_450[] */
-		30646,		/* A1 = 1.870544 */
-		 -32327,	/* A2 = -0.986572 */
-		 -287,		/* B2 = -0.008769 */
-		 0,		/* B1 = 0 */
-		 287,		/* B0 = 0.008769 */
-		 30627,		/* A1 = 1.869324 */
-		 -32607,	/* A2 = -0.995087 */
-		 13269,		/* B2 = 0.404968 */
-		 -12376,	/* B1 = -0.755432 */
-		 13269,		/* B0 = 0.404968 */
-		 30924,		/* A1 = 1.887512 */
-		 -32619,	/* A2 = -0.995453 */
-		 19950,		/* B2 = 0.608826 */
-		 -18940,	/* B1 = -1.156006 */
-		 19950,		/* B0 = 0.608826 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f425_475[] */
-		30396,		/* A1 = 1.855225 */
-		 -32014,	/* A2 = -0.97699 */
-		 -395,		/* B2 = -0.012055 */
-		 0,		/* B1 = 0 */
-		 395,		/* B0 = 0.012055 */
-		 30343,		/* A1 = 1.85199 */
-		 -32482,	/* A2 = -0.991302 */
-		 17823,		/* B2 = 0.543945 */
-		 -16431,	/* B1 = -1.002869 */
-		 17823,		/* B0 = 0.543945 */
-		 30872,		/* A1 = 1.884338 */
-		 -32516,	/* A2 = -0.99231 */
-		 18124,		/* B2 = 0.553101 */
-		 -17246,	/* B1 = -1.052673 */
-		 18124,		/* B0 = 0.553101 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f435 */
-		30796,		/* A1 = -1.879639 */
-		 -32603,	/* A2 = 0.994965 */
-		 -254,		/* B2 = -0.007762 */
-		 0,		/* B1 = 0.000000 */
-		 254,		/* B0 = 0.007762 */
-		 30793,		/* A1 = -1.879456 */
-		 -32692,	/* A2 = 0.997711 */
-		 18934,		/* B2 = 0.577820 */
-		 -17751,	/* B1 = -1.083496 */
-		 18934,		/* B0 = 0.577820 */
-		 30882,		/* A1 = -1.884888 */
-		 -32694,	/* A2 = 0.997772 */
-		 1858,		/* B2 = 0.056713 */
-		 -1758,		/* B1 = -0.107357 */
-		 1858,		/* B0 = 0.056713 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f440_450[] */
-		30641,		/* A1 = 1.870239 */
-		 -32458,	/* A2 = -0.99057 */
-		 -155,		/* B2 = -0.004735 */
-		 0,		/* B1 = 0 */
-		 155,		/* B0 = 0.004735 */
-		 30631,		/* A1 = 1.869568 */
-		 -32630,	/* A2 = -0.995789 */
-		 11453,		/* B2 = 0.349548 */
-		 -10666,	/* B1 = -0.651001 */
-		 11453,		/* B0 = 0.349548 */
-		 30810,		/* A1 = 1.880554 */
-		 -32634,	/* A2 = -0.995941 */
-		 12237,		/* B2 = 0.373474 */
-		 -11588,	/* B1 = -0.707336 */
-		 12237,		/* B0 = 0.373474 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f440_480[] */
-		30367,		/* A1 = 1.853455 */
-		 -32147,	/* A2 = -0.981079 */
-		 -495,		/* B2 = -0.015113 */
-		 0,		/* B1 = 0 */
-		 495,		/* B0 = 0.015113 */
-		 30322,		/* A1 = 1.850769 */
-		 -32543,	/* A2 = -0.993134 */
-		 10031,		/* B2 = 0.306152 */
-		 -9252,		/* B1 = -0.564728 */
-		 10031,		/* B0 = 0.306152 */
-		 30770,		/* A1 = 1.878052 */
-		 -32563,	/* A2 = -0.993774 */
-		 22674,		/* B2 = 0.691956 */
-		 -21465,	/* B1 = -1.31012 */
-		 22674,		/* B0 = 0.691956 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f445 */
-		30709,		/* A1 = -1.874329 */
-		 -32603,	/* A2 = 0.994965 */
-		 -83,		/* B2 = -0.002545 */
-		 0,		/* B1 = 0.000000 */
-		 83,		/* B0 = 0.002545 */
-		 30704,		/* A1 = -1.874084 */
-		 -32692,	/* A2 = 0.997711 */
-		 10641,		/* B2 = 0.324738 */
-		 -9947,		/* B1 = -0.607147 */
-		 10641,		/* B0 = 0.324738 */
-		 30796,		/* A1 = -1.879639 */
-		 -32694,	/* A2 = 0.997772 */
-		 10079,		/* B2 = 0.307587 */
-		 9513,		/* B1 = 0.580688 */
-		 10079,		/* B0 = 0.307587 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f450 */
-		30664,		/* A1 = -1.871643 */
-		 -32603,	/* A2 = 0.994965 */
-		 -164,		/* B2 = -0.005029 */
-		 0,		/* B1 = 0.000000 */
-		 164,		/* B0 = 0.005029 */
-		 30661,		/* A1 = -1.871399 */
-		 -32692,	/* A2 = 0.997711 */
-		 15294,		/* B2 = 0.466736 */
-		 -14275,	/* B1 = -0.871307 */
-		 15294,		/* B0 = 0.466736 */
-		 30751,		/* A1 = -1.876953 */
-		 -32694,	/* A2 = 0.997772 */
-		 3548,		/* B2 = 0.108284 */
-		 -3344,		/* B1 = -0.204155 */
-		 3548,		/* B0 = 0.108284 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f452 */
-		30653,		/* A1 = -1.870911 */
-		 -32615,	/* A2 = 0.995361 */
-		 -209,		/* B2 = -0.006382 */
-		 0,		/* B1 = 0.000000 */
-		 209,		/* B0 = 0.006382 */
-		 30647,		/* A1 = -1.870605 */
-		 -32702,	/* A2 = 0.997986 */
-		 18971,		/* B2 = 0.578979 */
-		 -17716,	/* B1 = -1.081299 */
-		 18971,		/* B0 = 0.578979 */
-		 30738,		/* A1 = -1.876099 */
-		 -32702,	/* A2 = 0.998016 */
-		 2967,		/* B2 = 0.090561 */
-		 -2793,		/* B1 = -0.170502 */
-		 2967,		/* B0 = 0.090561 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f475 */
-		30437,		/* A1 = -1.857727 */
-		 -32603,	/* A2 = 0.994965 */
-		 -264,		/* B2 = -0.008062 */
-		 0,		/* B1 = 0.000000 */
-		 264,		/* B0 = 0.008062 */
-		 30430,		/* A1 = -1.857300 */
-		 -32692,	/* A2 = 0.997711 */
-		 21681,		/* B2 = 0.661682 */
-		 -20082,	/* B1 = -1.225708 */
-		 21681,		/* B0 = 0.661682 */
-		 30526,		/* A1 = -1.863220 */
-		 -32694,	/* A2 = 0.997742 */
-		 1559,		/* B2 = 0.047600 */
-		 -1459,		/* B1 = -0.089096 */
-		 1559,		/* B0 = 0.047600 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f480_620[] */
-		28975,		/* A1 = 1.768494 */
-		 -30955,	/* A2 = -0.944672 */
-		 -1026,		/* B2 = -0.03133 */
-		 0,		/* B1 = 0 */
-		 1026,		/* B0 = 0.03133 */
-		 28613,		/* A1 = 1.746399 */
-		 -32089,	/* A2 = -0.979309 */
-		 14214,		/* B2 = 0.433807 */
-		 -12202,	/* B1 = -0.744812 */
-		 14214,		/* B0 = 0.433807 */
-		 30243,		/* A1 = 1.845947 */
-		 -32238,	/* A2 = -0.983856 */
-		 24825,		/* B2 = 0.757629 */
-		 -23402,	/* B1 = -1.428345 */
-		 24825,		/* B0 = 0.757629 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f494 */
-		30257,		/* A1 = -1.846741 */
-		 -32605,	/* A2 = 0.995056 */
-		 -249,		/* B2 = -0.007625 */
-		 0,		/* B1 = 0.000000 */
-		 249,		/* B0 = 0.007625 */
-		 30247,		/* A1 = -1.846191 */
-		 -32694,	/* A2 = 0.997772 */
-		 18088,		/* B2 = 0.552002 */
-		 -16652,	/* B1 = -1.016418 */
-		 18088,		/* B0 = 0.552002 */
-		 30348,		/* A1 = -1.852295 */
-		 -32696,	/* A2 = 0.997803 */
-		 2099,		/* B2 = 0.064064 */
-		 -1953,		/* B1 = -0.119202 */
-		 2099,		/* B0 = 0.064064 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f500 */
-		30202,		/* A1 = -1.843431 */
-		 -32624,	/* A2 = 0.995622 */
-		 -413,		/* B2 = -0.012622 */
-		 0,		/* B1 = 0.000000 */
-		 413,		/* B0 = 0.012622 */
-		 30191,		/* A1 = -1.842721 */
-		 -32714,	/* A2 = 0.998364 */
-		 25954,		/* B2 = 0.792057 */
-		 -23890,	/* B1 = -1.458131 */
-		 25954,		/* B0 = 0.792057 */
-		 30296,		/* A1 = -1.849172 */
-		 -32715,	/* A2 = 0.998397 */
-		 2007,		/* B2 = 0.061264 */
-		 -1860,		/* B1 = -0.113568 */
-		 2007,		/* B0 = 0.061264 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f520 */
-		30001,		/* A1 = -1.831116 */
-		 -32613,	/* A2 = 0.995270 */
-		 -155,		/* B2 = -0.004750 */
-		 0,		/* B1 = 0.000000 */
-		 155,		/* B0 = 0.004750 */
-		 29985,		/* A1 = -1.830200 */
-		 -32710,	/* A2 = 0.998260 */
-		 6584,		/* B2 = 0.200928 */
-		 -6018,		/* B1 = -0.367355 */
-		 6584,		/* B0 = 0.200928 */
-		 30105,		/* A1 = -1.837524 */
-		 -32712,	/* A2 = 0.998291 */
-		 23812,		/* B2 = 0.726685 */
-		 -21936,	/* B1 = -1.338928 */
-		 23812,		/* B0 = 0.726685 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f523 */
-		29964,		/* A1 = -1.828918 */
-		 -32601,	/* A2 = 0.994904 */
-		 -101,		/* B2 = -0.003110 */
-		 0,		/* B1 = 0.000000 */
-		 101,		/* B0 = 0.003110 */
-		 29949,		/* A1 = -1.827942 */
-		 -32700,	/* A2 = 0.997925 */
-		 11041,		/* B2 = 0.336975 */
-		 -10075,	/* B1 = -0.614960 */
-		 11041,		/* B0 = 0.336975 */
-		 30070,		/* A1 = -1.835388 */
-		 -32702,	/* A2 = 0.997986 */
-		 16762,		/* B2 = 0.511536 */
-		 -15437,	/* B1 = -0.942230 */
-		 16762,		/* B0 = 0.511536 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f525 */
-		29936,		/* A1 = -1.827209 */
-		 -32584,	/* A2 = 0.994415 */
-		 -91,		/* B2 = -0.002806 */
-		 0,		/* B1 = 0.000000 */
-		 91,		/* B0 = 0.002806 */
-		 29921,		/* A1 = -1.826233 */
-		 -32688,	/* A2 = 0.997559 */
-		 11449,		/* B2 = 0.349396 */
-		 -10426,	/* B1 = -0.636383 */
-		 11449,		/* B0 = 0.349396 */
-		 30045,		/* A1 = -1.833862 */
-		 -32688,	/* A2 = 0.997589 */
-		 13055,		/* B2 = 0.398407 */
-		 -12028,	/* B1 = -0.734161 */
-		 13055,		/* B0 = 0.398407 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f540_660[] */
-		28499,		/* A1 = 1.739441 */
-		 -31129,	/* A2 = -0.949982 */
-		 -849,		/* B2 = -0.025922 */
-		 0,		/* B1 = 0 */
-		 849,		/* B0 = 0.025922 */
-		 28128,		/* A1 = 1.716797 */
-		 -32130,	/* A2 = -0.98056 */
-		 14556,		/* B2 = 0.444214 */
-		 -12251,	/* B1 = -0.747772 */
-		 14556,		/* B0 = 0.444244 */
-		 29667,		/* A1 = 1.81073 */
-		 -32244,	/* A2 = -0.984039 */
-		 23038,		/* B2 = 0.703064 */
-		 -21358,	/* B1 = -1.303589 */
-		 23040,		/* B0 = 0.703125 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f587 */
-		29271,		/* A1 = -1.786560 */
-		 -32599,	/* A2 = 0.994873 */
-		 -490,		/* B2 = -0.014957 */
-		 0,		/* B1 = 0.000000 */
-		 490,		/* B0 = 0.014957 */
-		 29246,		/* A1 = -1.785095 */
-		 -32700,	/* A2 = 0.997925 */
-		 28961,		/* B2 = 0.883850 */
-		 -25796,	/* B1 = -1.574463 */
-		 28961,		/* B0 = 0.883850 */
-		 29383,		/* A1 = -1.793396 */
-		 -32700,	/* A2 = 0.997955 */
-		 1299,		/* B2 = 0.039650 */
-		 -1169,		/* B1 = -0.071396 */
-		 1299,		/* B0 = 0.039650 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f590 */
-		29230,		/* A1 = -1.784058 */
-		 -32584,	/* A2 = 0.994415 */
-		 -418,		/* B2 = -0.012757 */
-		 0,		/* B1 = 0.000000 */
-		 418,		/* B0 = 0.012757 */
-		 29206,		/* A1 = -1.782593 */
-		 -32688,	/* A2 = 0.997559 */
-		 36556,		/* B2 = 1.115601 */
-		 -32478,	/* B1 = -1.982300 */
-		 36556,		/* B0 = 1.115601 */
-		 29345,		/* A1 = -1.791077 */
-		 -32688,	/* A2 = 0.997589 */
-		 897,		/* B2 = 0.027397 */
-		 -808,		/* B1 = -0.049334 */
-		 897,		/* B0 = 0.027397 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f600 */
-		29116,		/* A1 = -1.777100 */
-		 -32603,	/* A2 = 0.994965 */
-		 -165,		/* B2 = -0.005039 */
-		 0,		/* B1 = 0.000000 */
-		 165,		/* B0 = 0.005039 */
-		 29089,		/* A1 = -1.775452 */
-		 -32708,	/* A2 = 0.998199 */
-		 6963,		/* B2 = 0.212494 */
-		 -6172,		/* B1 = -0.376770 */
-		 6963,		/* B0 = 0.212494 */
-		 29237,		/* A1 = -1.784485 */
-		 -32710,	/* A2 = 0.998230 */
-		 24197,		/* B2 = 0.738464 */
-		 -21657,	/* B1 = -1.321899 */
-		 24197,		/* B0 = 0.738464 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f660 */
-		28376,		/* A1 = -1.731934 */
-		 -32567,	/* A2 = 0.993896 */
-		 -363,		/* B2 = -0.011102 */
-		 0,		/* B1 = 0.000000 */
-		 363,		/* B0 = 0.011102 */
-		 28337,		/* A1 = -1.729614 */
-		 -32683,	/* A2 = 0.997434 */
-		 21766,		/* B2 = 0.664246 */
-		 -18761,	/* B1 = -1.145081 */
-		 21766,		/* B0 = 0.664246 */
-		 28513,		/* A1 = -1.740356 */
-		 -32686,	/* A2 = 0.997498 */
-		 2509,		/* B2 = 0.076584 */
-		 -2196,		/* B1 = -0.134041 */
-		 2509,		/* B0 = 0.076584 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f700 */
-		27844,		/* A1 = -1.699463 */
-		 -32563,	/* A2 = 0.993744 */
-		 -366,		/* B2 = -0.011187 */
-		 0,		/* B1 = 0.000000 */
-		 366,		/* B0 = 0.011187 */
-		 27797,		/* A1 = -1.696655 */
-		 -32686,	/* A2 = 0.997498 */
-		 22748,		/* B2 = 0.694214 */
-		 -19235,	/* B1 = -1.174072 */
-		 22748,		/* B0 = 0.694214 */
-		 27995,		/* A1 = -1.708740 */
-		 -32688,	/* A2 = 0.997559 */
-		 2964,		/* B2 = 0.090477 */
-		 -2546,		/* B1 = -0.155449 */
-		 2964,		/* B0 = 0.090477 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f740 */
-		27297,		/* A1 = -1.666077 */
-		 -32551,	/* A2 = 0.993408 */
-		 -345,		/* B2 = -0.010540 */
-		 0,		/* B1 = 0.000000 */
-		 345,		/* B0 = 0.010540 */
-		 27240,		/* A1 = -1.662598 */
-		 -32683,	/* A2 = 0.997406 */
-		 22560,		/* B2 = 0.688477 */
-		 -18688,	/* B1 = -1.140625 */
-		 22560,		/* B0 = 0.688477 */
-		 27461,		/* A1 = -1.676147 */
-		 -32684,	/* A2 = 0.997467 */
-		 3541,		/* B2 = 0.108086 */
-		 -2985,		/* B1 = -0.182220 */
-		 3541,		/* B0 = 0.108086 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f750 */
-		27155,		/* A1 = -1.657410 */
-		 -32551,	/* A2 = 0.993408 */
-		 -462,		/* B2 = -0.014117 */
-		 0,		/* B1 = 0.000000 */
-		 462,		/* B0 = 0.014117 */
-		 27097,		/* A1 = -1.653870 */
-		 -32683,	/* A2 = 0.997406 */
-		 32495,		/* B2 = 0.991699 */
-		 -26776,	/* B1 = -1.634338 */
-		 32495,		/* B0 = 0.991699 */
-		 27321,		/* A1 = -1.667542 */
-		 -32684,	/* A2 = 0.997467 */
-		 1835,		/* B2 = 0.056007 */
-		 -1539,		/* B1 = -0.093948 */
-		 1835,		/* B0 = 0.056007 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f750_1450[] */
-		19298,		/* A1 = 1.177917 */
-		 -24471,	/* A2 = -0.746796 */
-		 -4152,		/* B2 = -0.126709 */
-		 0,		/* B1 = 0 */
-		 4152,		/* B0 = 0.126709 */
-		 12902,		/* A1 = 0.787476 */
-		 -29091,	/* A2 = -0.887817 */
-		 12491,		/* B2 = 0.38121 */
-		 -1794,		/* B1 = -0.109528 */
-		 12494,		/* B0 = 0.381317 */
-		 26291,		/* A1 = 1.604736 */
-		 -30470,	/* A2 = -0.929901 */
-		 28859,		/* B2 = 0.880737 */
-		 -26084,	/* B1 = -1.592102 */
-		 28861,		/* B0 = 0.880798 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f770 */
-		26867,		/* A1 = -1.639832 */
-		 -32551,	/* A2 = 0.993408 */
-		 -123,		/* B2 = -0.003755 */
-		 0,		/* B1 = 0.000000 */
-		 123,		/* B0 = 0.003755 */
-		 26805,		/* A1 = -1.636108 */
-		 -32683,	/* A2 = 0.997406 */
-		 17297,		/* B2 = 0.527863 */
-		 -14096,	/* B1 = -0.860382 */
-		 17297,		/* B0 = 0.527863 */
-		 27034,		/* A1 = -1.650085 */
-		 -32684,	/* A2 = 0.997467 */
-		 12958,		/* B2 = 0.395477 */
-		 -10756,	/* B1 = -0.656525 */
-		 12958,		/* B0 = 0.395477 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f800 */
-		26413,		/* A1 = -1.612122 */
-		 -32547,	/* A2 = 0.993286 */
-		 -223,		/* B2 = -0.006825 */
-		 0,		/* B1 = 0.000000 */
-		 223,		/* B0 = 0.006825 */
-		 26342,		/* A1 = -1.607849 */
-		 -32686,	/* A2 = 0.997498 */
-		 6391,		/* B2 = 0.195053 */
-		 -5120,		/* B1 = -0.312531 */
-		 6391,		/* B0 = 0.195053 */
-		 26593,		/* A1 = -1.623108 */
-		 -32688,	/* A2 = 0.997559 */
-		 23681,		/* B2 = 0.722717 */
-		 -19328,	/* B1 = -1.179688 */
-		 23681,		/* B0 = 0.722717 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f816 */
-		26168,		/* A1 = -1.597209 */
-		 -32528,	/* A2 = 0.992706 */
-		 -235,		/* B2 = -0.007182 */
-		 0,		/* B1 = 0.000000 */
-		 235,		/* B0 = 0.007182 */
-		 26092,		/* A1 = -1.592590 */
-		 -32675,	/* A2 = 0.997192 */
-		 20823,		/* B2 = 0.635498 */
-		 -16510,	/* B1 = -1.007751 */
-		 20823,		/* B0 = 0.635498 */
-		 26363,		/* A1 = -1.609070 */
-		 -32677,	/* A2 = 0.997253 */
-		 6739,		/* B2 = 0.205688 */
-		 -5459,		/* B1 = -0.333206 */
-		 6739,		/* B0 = 0.205688 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f850 */
-		25641,		/* A1 = -1.565063 */
-		 -32536,	/* A2 = 0.992950 */
-		 -121,		/* B2 = -0.003707 */
-		 0,		/* B1 = 0.000000 */
-		 121,		/* B0 = 0.003707 */
-		 25560,		/* A1 = -1.560059 */
-		 -32684,	/* A2 = 0.997437 */
-		 18341,		/* B2 = 0.559753 */
-		 -14252,	/* B1 = -0.869904 */
-		 18341,		/* B0 = 0.559753 */
-		 25837,		/* A1 = -1.577026 */
-		 -32684,	/* A2 = 0.997467 */
-		 16679,		/* B2 = 0.509003 */
-		 -13232,	/* B1 = -0.807648 */
-		 16679,		/* B0 = 0.509003 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f857_1645[] */
-		16415,		/* A1 = 1.001953 */
-		 -23669,	/* A2 = -0.722321 */
-		 -4549,		/* B2 = -0.138847 */
-		 0,		/* B1 = 0 */
-		 4549,		/* B0 = 0.138847 */
-		 8456,		/* A1 = 0.516174 */
-		 -28996,	/* A2 = -0.884918 */
-		 13753,		/* B2 = 0.419724 */
-		 -12,		/* B1 = -0.000763 */
-		 13757,		/* B0 = 0.419846 */
-		 24632,		/* A1 = 1.503418 */
-		 -30271,	/* A2 = -0.923828 */
-		 29070,		/* B2 = 0.887146 */
-		 -25265,	/* B1 = -1.542114 */
-		 29073,		/* B0 = 0.887268 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f900 */
-		24806,		/* A1 = -1.514099 */
-		 -32501,	/* A2 = 0.991852 */
-		 -326,		/* B2 = -0.009969 */
-		 0,		/* B1 = 0.000000 */
-		 326,		/* B0 = 0.009969 */
-		 24709,		/* A1 = -1.508118 */
-		 -32659,	/* A2 = 0.996674 */
-		 20277,		/* B2 = 0.618835 */
-		 -15182,	/* B1 = -0.926636 */
-		 20277,		/* B0 = 0.618835 */
-		 25022,		/* A1 = -1.527222 */
-		 -32661,	/* A2 = 0.996735 */
-		 4320,		/* B2 = 0.131836 */
-		 -3331,		/* B1 = -0.203339 */
-		 4320,		/* B0 = 0.131836 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f900_1300[] */
-		19776,		/* A1 = 1.207092 */
-		 -27437,	/* A2 = -0.837341 */
-		 -2666,		/* B2 = -0.081371 */
-		 0,		/* B1 = 0 */
-		 2666,		/* B0 = 0.081371 */
-		 16302,		/* A1 = 0.995026 */
-		 -30354,	/* A2 = -0.926361 */
-		 10389,		/* B2 = 0.317062 */
-		 -3327,		/* B1 = -0.203064 */
-		 10389,		/* B0 = 0.317062 */
-		 24299,		/* A1 = 1.483154 */
-		 -30930,	/* A2 = -0.943909 */
-		 25016,		/* B2 = 0.763428 */
-		 -21171,	/* B1 = -1.292236 */
-		 25016,		/* B0 = 0.763428 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f935_1215[] */
-		20554,		/* A1 = 1.254517 */
-		 -28764,	/* A2 = -0.877838 */
-		 -2048,		/* B2 = -0.062515 */
-		 0,		/* B1 = 0 */
-		 2048,		/* B0 = 0.062515 */
-		 18209,		/* A1 = 1.11145 */
-		 -30951,	/* A2 = -0.94458 */
-		 9390,		/* B2 = 0.286575 */
-		 -3955,		/* B1 = -0.241455 */
-		 9390,		/* B0 = 0.286575 */
-		 23902,		/* A1 = 1.458923 */
-		 -31286,	/* A2 = -0.954803 */
-		 23252,		/* B2 = 0.709595 */
-		 -19132,	/* B1 = -1.167725 */
-		 23252,		/* B0 = 0.709595 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f941_1477[] */
-		17543,		/* A1 = 1.07074 */
-		 -26220,	/* A2 = -0.800201 */
-		 -3298,		/* B2 = -0.100647 */
-		 0,		/* B1 = 0 */
-		 3298,		/* B0 = 0.100647 */
-		 12423,		/* A1 = 0.75827 */
-		 -30036,	/* A2 = -0.916626 */
-		 12651,		/* B2 = 0.386078 */
-		 -2444,		/* B1 = -0.14917 */
-		 12653,		/* B0 = 0.386154 */
-		 23518,		/* A1 = 1.435425 */
-		 -30745,	/* A2 = -0.938293 */
-		 27282,		/* B2 = 0.832581 */
-		 -22529,	/* B1 = -1.375122 */
-		 27286,		/* B0 = 0.832703 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f942 */
-		24104,		/* A1 = -1.471252 */
-		 -32507,	/* A2 = 0.992065 */
-		 -351,		/* B2 = -0.010722 */
-		 0,		/* B1 = 0.000000 */
-		 351,		/* B0 = 0.010722 */
-		 23996,		/* A1 = -1.464600 */
-		 -32671,	/* A2 = 0.997040 */
-		 22848,		/* B2 = 0.697266 */
-		 -16639,	/* B1 = -1.015564 */
-		 22848,		/* B0 = 0.697266 */
-		 24332,		/* A1 = -1.485168 */
-		 -32673,	/* A2 = 0.997101 */
-		 4906,		/* B2 = 0.149727 */
-		 -3672,		/* B1 = -0.224174 */
-		 4906,		/* B0 = 0.149727 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f950 */
-		23967,		/* A1 = -1.462830 */
-		 -32507,	/* A2 = 0.992065 */
-		 -518,		/* B2 = -0.015821 */
-		 0,		/* B1 = 0.000000 */
-		 518,		/* B0 = 0.015821 */
-		 23856,		/* A1 = -1.456055 */
-		 -32671,	/* A2 = 0.997040 */
-		 26287,		/* B2 = 0.802246 */
-		 -19031,	/* B1 = -1.161560 */
-		 26287,		/* B0 = 0.802246 */
-		 24195,		/* A1 = -1.476746 */
-		 -32673,	/* A2 = 0.997101 */
-		 2890,		/* B2 = 0.088196 */
-		 -2151,		/* B1 = -0.131317 */
-		 2890,		/* B0 = 0.088196 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f950_1400[] */
-		18294,		/* A1 = 1.116638 */
-		 -26962,	/* A2 = -0.822845 */
-		 -2914,		/* B2 = -0.088936 */
-		 0,		/* B1 = 0 */
-		 2914,		/* B0 = 0.088936 */
-		 14119,		/* A1 = 0.861786 */
-		 -30227,	/* A2 = -0.922455 */
-		 11466,		/* B2 = 0.349945 */
-		 -2833,		/* B1 = -0.172943 */
-		 11466,		/* B0 = 0.349945 */
-		 23431,		/* A1 = 1.430115 */
-		 -30828,	/* A2 = -0.940796 */
-		 25331,		/* B2 = 0.773071 */
-		 -20911,	/* B1 = -1.276367 */
-		 25331,		/* B0 = 0.773071 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f975 */
-		23521,		/* A1 = -1.435608 */
-		 -32489,	/* A2 = 0.991516 */
-		 -193,		/* B2 = -0.005915 */
-		 0,		/* B1 = 0.000000 */
-		 193,		/* B0 = 0.005915 */
-		 23404,		/* A1 = -1.428467 */
-		 -32655,	/* A2 = 0.996582 */
-		 17740,		/* B2 = 0.541412 */
-		 -12567,	/* B1 = -0.767029 */
-		 17740,		/* B0 = 0.541412 */
-		 23753,		/* A1 = -1.449829 */
-		 -32657,	/* A2 = 0.996613 */
-		 9090,		/* B2 = 0.277405 */
-		 -6662,		/* B1 = -0.406647 */
-		 9090,		/* B0 = 0.277405 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1000 */
-		23071,		/* A1 = -1.408203 */
-		 -32489,	/* A2 = 0.991516 */
-		 -293,		/* B2 = -0.008965 */
-		 0,		/* B1 = 0.000000 */
-		 293,		/* B0 = 0.008965 */
-		 22951,		/* A1 = -1.400818 */
-		 -32655,	/* A2 = 0.996582 */
-		 5689,		/* B2 = 0.173645 */
-		 -3951,		/* B1 = -0.241150 */
-		 5689,		/* B0 = 0.173645 */
-		 23307,		/* A1 = -1.422607 */
-		 -32657,	/* A2 = 0.996613 */
-		 18692,		/* B2 = 0.570435 */
-		 -13447,	/* B1 = -0.820770 */
-		 18692,		/* B0 = 0.570435 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1020 */
-		22701,		/* A1 = -1.385620 */
-		 -32474,	/* A2 = 0.991058 */
-		 -292,		/* B2 = -0.008933 */
-		 0,		/*163840      , B1 = 10.000000 */
-		 292,		/* B0 = 0.008933 */
-		 22564,		/* A1 = -1.377258 */
-		 -32655,	/* A2 = 0.996552 */
-		 20756,		/* B2 = 0.633423 */
-		 -14176,	/* B1 = -0.865295 */
-		 20756,		/* B0 = 0.633423 */
-		 22960,		/* A1 = -1.401428 */
-		 -32657,	/* A2 = 0.996613 */
-		 6520,		/* B2 = 0.198990 */
-		 -4619,		/* B1 = -0.281937 */
-		 6520,		/* B0 = 0.198990 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1050 */
-		22142,		/* A1 = -1.351501 */
-		 -32474,	/* A2 = 0.991058 */
-		 -147,		/* B2 = -0.004493 */
-		 0,		/* B1 = 0.000000 */
-		 147,		/* B0 = 0.004493 */
-		 22000,		/* A1 = -1.342834 */
-		 -32655,	/* A2 = 0.996552 */
-		 15379,		/* B2 = 0.469360 */
-		 -10237,	/* B1 = -0.624847 */
-		 15379,		/* B0 = 0.469360 */
-		 22406,		/* A1 = -1.367554 */
-		 -32657,	/* A2 = 0.996613 */
-		 17491,		/* B2 = 0.533783 */
-		 -12096,	/* B1 = -0.738312 */
-		 17491,		/* B0 = 0.533783 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1100_1750[] */
-		12973,		/* A1 = 0.79184 */
-		 -24916,	/* A2 = -0.760376 */
-		 6655,		/* B2 = 0.203102 */
-		 367,		/* B1 = 0.0224 */
-		 6657,		/* B0 = 0.203171 */
-		 5915,		/* A1 = 0.361053 */
-		 -29560,	/* A2 = -0.90213 */
-		 -7777,		/* B2 = -0.23735 */
-		 0,		/* B1 = 0 */
-		 7777,		/* B0 = 0.23735 */
-		 20510,		/* A1 = 1.251892 */
-		 -30260,	/* A2 = -0.923462 */
-		 26662,		/* B2 = 0.81366 */
-		 -20573,	/* B1 = -1.255737 */
-		 26668,		/* B0 = 0.813843 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1140 */
-		20392,		/* A1 = -1.244629 */
-		 -32460,	/* A2 = 0.990601 */
-		 -270,		/* B2 = -0.008240 */
-		 0,		/* B1 = 0.000000 */
-		 270,		/* B0 = 0.008240 */
-		 20218,		/* A1 = -1.234009 */
-		 -32655,	/* A2 = 0.996582 */
-		 21337,		/* B2 = 0.651154 */
-		 -13044,	/* B1 = -0.796143 */
-		 21337,		/* B0 = 0.651154 */
-		 20684,		/* A1 = -1.262512 */
-		 -32657,	/* A2 = 0.996643 */
-		 8572,		/* B2 = 0.261612 */
-		 -5476,		/* B1 = -0.334244 */
-		 8572,		/* B0 = 0.261612 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1200 */
-		19159,		/* A1 = -1.169373 */
-		 -32456,	/* A2 = 0.990509 */
-		 -335,		/* B2 = -0.010252 */
-		 0,		/* B1 = 0.000000 */
-		 335,		/* B0 = 0.010252 */
-		 18966,		/* A1 = -1.157593 */
-		 -32661,	/* A2 = 0.996735 */
-		 6802,		/* B2 = 0.207588 */
-		 -3900,		/* B1 = -0.238098 */
-		 6802,		/* B0 = 0.207588 */
-		 19467,		/* A1 = -1.188232 */
-		 -32661,	/* A2 = 0.996765 */
-		 25035,		/* B2 = 0.764008 */
-		 -15049,	/* B1 = -0.918579 */
-		 25035,		/* B0 = 0.764008 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1209 */
-		18976,		/* A1 = -1.158264 */
-		 -32439,	/* A2 = 0.989990 */
-		 -183,		/* B2 = -0.005588 */
-		 0,		/* B1 = 0.000000 */
-		 183,		/* B0 = 0.005588 */
-		 18774,		/* A1 = -1.145874 */
-		 -32650,	/* A2 = 0.996429 */
-		 15468,		/* B2 = 0.472076 */
-		 -8768,		/* B1 = -0.535217 */
-		 15468,		/* B0 = 0.472076 */
-		 19300,		/* A1 = -1.177979 */
-		 -32652,	/* A2 = 0.996490 */
-		 19840,		/* B2 = 0.605499 */
-		 -11842,	/* B1 = -0.722809 */
-		 19840,		/* B0 = 0.605499 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1330 */
-		16357,		/* A1 = -0.998413 */
-		 -32368,	/* A2 = 0.987793 */
-		 -217,		/* B2 = -0.006652 */
-		 0,		/* B1 = 0.000000 */
-		 217,		/* B0 = 0.006652 */
-		 16107,		/* A1 = -0.983126 */
-		 -32601,	/* A2 = 0.994904 */
-		 11602,		/* B2 = 0.354065 */
-		 -5555,		/* B1 = -0.339111 */
-		 11602,		/* B0 = 0.354065 */
-		 16722,		/* A1 = -1.020630 */
-		 -32603,	/* A2 = 0.994965 */
-		 15574,		/* B2 = 0.475311 */
-		 -8176,		/* B1 = -0.499069 */
-		 15574,		/* B0 = 0.475311 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1336 */
-		16234,		/* A1 = -0.990875 */
-		 32404,		/* A2 = -0.988922 */
-		 -193,		/* B2 = -0.005908 */
-		 0,		/* B1 = 0.000000 */
-		 193,		/* B0 = 0.005908 */
-		 15986,		/* A1 = -0.975769 */
-		 -32632,	/* A2 = 0.995880 */
-		 18051,		/* B2 = 0.550903 */
-		 -8658,		/* B1 = -0.528473 */
-		 18051,		/* B0 = 0.550903 */
-		 16591,		/* A1 = -1.012695 */
-		 -32634,	/* A2 = 0.995941 */
-		 15736,		/* B2 = 0.480240 */
-		 -8125,		/* B1 = -0.495926 */
-		 15736,		/* B0 = 0.480240 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1366 */
-		15564,		/* A1 = -0.949982 */
-		 -32404,	/* A2 = 0.988922 */
-		 -269,		/* B2 = -0.008216 */
-		 0,		/* B1 = 0.000000 */
-		 269,		/* B0 = 0.008216 */
-		 15310,		/* A1 = -0.934479 */
-		 -32632,	/* A2 = 0.995880 */
-		 10815,		/* B2 = 0.330063 */
-		 -4962,		/* B1 = -0.302887 */
-		 10815,		/* B0 = 0.330063 */
-		 15924,		/* A1 = -0.971924 */
-		 -32634,	/* A2 = 0.995941 */
-		 18880,		/* B2 = 0.576172 */
-		 -9364,		/* B1 = -0.571594 */
-		 18880,		/* B0 = 0.576172 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1380 */
-		15247,		/* A1 = -0.930603 */
-		 -32397,	/* A2 = 0.988708 */
-		 -244,		/* B2 = -0.007451 */
-		 0,		/* B1 = 0.000000 */
-		 244,		/* B0 = 0.007451 */
-		 14989,		/* A1 = -0.914886 */
-		 -32627,	/* A2 = 0.995697 */
-		 18961,		/* B2 = 0.578644 */
-		 -8498,		/* B1 = -0.518707 */
-		 18961,		/* B0 = 0.578644 */
-		 15608,		/* A1 = -0.952667 */
-		 -32628,	/* A2 = 0.995758 */
-		 11145,		/* B2 = 0.340134 */
-		 -5430,		/* B1 = -0.331467 */
-		 11145,		/* B0 = 0.340134 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1400 */
-		14780,		/* A1 = -0.902130 */
-		 -32393,	/* A2 = 0.988586 */
-		 -396,		/* B2 = -0.012086 */
-		 0,		/* B1 = 0.000000 */
-		 396,		/* B0 = 0.012086 */
-		 14510,		/* A1 = -0.885651 */
-		 -32630,	/* A2 = 0.995819 */
-		 6326,		/* B2 = 0.193069 */
-		 -2747,		/* B1 = -0.167671 */
-		 6326,		/* B0 = 0.193069 */
-		 15154,		/* A1 = -0.924957 */
-		 -32632,	/* A2 = 0.995850 */
-		 23235,		/* B2 = 0.709076 */
-		 -10983,	/* B1 = -0.670380 */
-		 23235,		/* B0 = 0.709076 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1477 */
-		13005,		/* A1 = -0.793793 */
-		 -32368,	/* A2 = 0.987823 */
-		 -500,		/* B2 = -0.015265 */
-		 0,		/* B1 = 0.000000 */
-		 500,		/* B0 = 0.015265 */
-		 12708,		/* A1 = -0.775665 */
-		 -32615,	/* A2 = 0.995331 */
-		 11420,		/* B2 = 0.348526 */
-		 -4306,		/* B1 = -0.262833 */
-		 11420,		/* B0 = 0.348526 */
-		 13397,		/* A1 = -0.817688 */
-		 -32615,	/* A2 = 0.995361 */
-		 9454,		/* B2 = 0.288528 */
-		 -3981,		/* B1 = -0.243027 */
-		 9454,		/* B0 = 0.288528 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1600 */
-		10046,		/* A1 = -0.613190 */
-		 -32331,	/* A2 = 0.986694 */
-		 -455,		/* B2 = -0.013915 */
-		 0,		/* B1 = 0.000000 */
-		 455,		/* B0 = 0.013915 */
-		 9694,		/* A1 = -0.591705 */
-		 -32601,	/* A2 = 0.994934 */
-		 6023,		/* B2 = 0.183815 */
-		 -1708,		/* B1 = -0.104279 */
-		 6023,		/* B0 = 0.183815 */
-		 10478,		/* A1 = -0.639587 */
-		 -32603,	/* A2 = 0.994965 */
-		 22031,		/* B2 = 0.672333 */
-		 -7342,		/* B1 = -0.448151 */
-		 22031,		/* B0 = 0.672333 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1633_1638[] */
-		9181,		/* A1 = 0.560394 */
-		 -32256,	/* A2 = -0.984375 */
-		 -556,		/* B2 = -0.016975 */
-		 0,		/* B1 = 0 */
-		 556,		/* B0 = 0.016975 */
-		 8757,		/* A1 = 0.534515 */
-		 -32574,	/* A2 = -0.99408 */
-		 8443,		/* B2 = 0.25769 */
-		 -2135,		/* B1 = -0.130341 */
-		 8443,		/* B0 = 0.25769 */
-		 9691,		/* A1 = 0.591522 */
-		 -32574,	/* A2 = -0.99411 */
-		 15446,		/* B2 = 0.471375 */
-		 -4809,		/* B1 = -0.293579 */
-		 15446,		/* B0 = 0.471375 */
-		 7,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1800 */
-		5076,		/* A1 = -0.309875 */
-		 -32304,	/* A2 = 0.985840 */
-		 -508,		/* B2 = -0.015503 */
-		 0,		/* B1 = 0.000000 */
-		 508,		/* B0 = 0.015503 */
-		 4646,		/* A1 = -0.283600 */
-		 -32605,	/* A2 = 0.995026 */
-		 6742,		/* B2 = 0.205780 */
-		 -878,		/* B1 = -0.053635 */
-		 6742,		/* B0 = 0.205780 */
-		 5552,		/* A1 = -0.338928 */
-		 -32605,	/* A2 = 0.995056 */
-		 23667,		/* B2 = 0.722260 */
-		 -4297,		/* B1 = -0.262329 */
-		 23667,		/* B0 = 0.722260 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-	{			/* f1860 */
-		3569,		/* A1 = -0.217865 */
-		 -32292,	/* A2 = 0.985504 */
-		 -239,		/* B2 = -0.007322 */
-		 0,		/* B1 = 0.000000 */
-		 239,		/* B0 = 0.007322 */
-		 3117,		/* A1 = -0.190277 */
-		 -32603,	/* A2 = 0.994965 */
-		 18658,		/* B2 = 0.569427 */
-		 -1557,		/* B1 = -0.095032 */
-		 18658,		/* B0 = 0.569427 */
-		 4054,		/* A1 = -0.247437 */
-		 -32603,	/* A2 = 0.994965 */
-		 18886,		/* B2 = 0.576385 */
-		 -2566,		/* B1 = -0.156647 */
-		 18886,		/* B0 = 0.576385 */
-		 5,		/* Internal filter scaling */
-		 159,		/* Minimum in-band energy threshold */
-		 21,		/* 21/32 in-band to broad-band ratio */
-		 0x0FF5		/* shift-mask 0x0FF (look at 16 half-frames) bit count = 5 */
-	},
-};
-static int ixj_init_filter(IXJ *j, IXJ_FILTER * jf)
-{
-	unsigned short cmd;
-	int cnt, max;
-
-	if (jf->filter > 3) {
-		return -1;
-	}
-	if (ixj_WriteDSPCommand(0x5154 + jf->filter, j))	/* Select Filter */
-
-		return -1;
-	if (!jf->enable) {
-		if (ixj_WriteDSPCommand(0x5152, j))		/* Disable Filter */
-
-			return -1;
-		else
-			return 0;
-	} else {
-		if (ixj_WriteDSPCommand(0x5153, j))		/* Enable Filter */
-
-			return -1;
-		/* Select the filter (f0 - f3) to use. */
-		if (ixj_WriteDSPCommand(0x5154 + jf->filter, j))
-			return -1;
-	}
-	if (jf->freq < 12 && jf->freq > 3) {
-		/* Select the frequency for the selected filter. */
-		if (ixj_WriteDSPCommand(0x5170 + jf->freq, j))
-			return -1;
-	} else if (jf->freq > 11) {
-		/* We need to load a programmable filter set for undefined */
-		/* frequencies.  So we will point the filter to a programmable set. */
-		/* Since there are only 4 filters and 4 programmable sets, we will */
-		/* just point the filter to the same number set and program it for the */
-		/* frequency we want. */
-		if (ixj_WriteDSPCommand(0x5170 + jf->filter, j))
-			return -1;
-		if (j->ver.low != 0x12) {
-			cmd = 0x515B;
-			max = 19;
-		} else {
-			cmd = 0x515E;
-			max = 15;
-		}
-		if (ixj_WriteDSPCommand(cmd, j))
-			return -1;
-		for (cnt = 0; cnt < max; cnt++) {
-			if (ixj_WriteDSPCommand(tone_table[jf->freq - 12][cnt], j))
-				return -1;
-		}
-	}
-	j->filter_en[jf->filter] = jf->enable;
-	return 0;
-}
-
-static int ixj_init_filter_raw(IXJ *j, IXJ_FILTER_RAW * jfr)
-{
-	unsigned short cmd;
-	int cnt, max;
-	if (jfr->filter > 3) {
-		return -1;
-	}
-	if (ixj_WriteDSPCommand(0x5154 + jfr->filter, j))	/* Select Filter */
-		return -1;
-
-	if (!jfr->enable) {
-		if (ixj_WriteDSPCommand(0x5152, j))		/* Disable Filter */
-			return -1;
-		else
-			return 0;
-	} else {
-		if (ixj_WriteDSPCommand(0x5153, j))		/* Enable Filter */
-			return -1;
-		/* Select the filter (f0 - f3) to use. */
-		if (ixj_WriteDSPCommand(0x5154 + jfr->filter, j))
-			return -1;
-	}
-	/* We need to load a programmable filter set for undefined */
-	/* frequencies.  So we will point the filter to a programmable set. */
-	/* Since there are only 4 filters and 4 programmable sets, we will */
-	/* just point the filter to the same number set and program it for the */
-	/* frequency we want. */
-	if (ixj_WriteDSPCommand(0x5170 + jfr->filter, j))
-		return -1;
-	if (j->ver.low != 0x12) {
-		cmd = 0x515B;
-		max = 19;
-	} else {
-		cmd = 0x515E;
-		max = 15;
-	}
-	if (ixj_WriteDSPCommand(cmd, j))
-		return -1;
-	for (cnt = 0; cnt < max; cnt++) {
-		if (ixj_WriteDSPCommand(jfr->coeff[cnt], j))
-			return -1;
-	}
-	j->filter_en[jfr->filter] = jfr->enable;
-	return 0;
-}
-
-static int ixj_init_tone(IXJ *j, IXJ_TONE * ti)
-{
-	int freq0, freq1;
-	unsigned short data;
-	if (ti->freq0) {
-		freq0 = ti->freq0;
-	} else {
-		freq0 = 0x7FFF;
-	}
-
-	if (ti->freq1) {
-		freq1 = ti->freq1;
-	} else {
-		freq1 = 0x7FFF;
-	}
-
-	if(ti->tone_index > 12 && ti->tone_index < 28)
-	{
-		if (ixj_WriteDSPCommand(0x6800 + ti->tone_index, j))
-			return -1;
-		if (ixj_WriteDSPCommand(0x6000 + (ti->gain1 << 4) + ti->gain0, j))
-			return -1;
-		data = freq0;
-		if (ixj_WriteDSPCommand(data, j))
-			return -1;
-		data = freq1;
-		if (ixj_WriteDSPCommand(data, j))
-			return -1;
-	}
-	return freq0;
-}
-
diff --git a/drivers/staging/telephony/ixj.h b/drivers/staging/telephony/ixj.h
deleted file mode 100644
index 2c84113..0000000
--- a/drivers/staging/telephony/ixj.h
+++ /dev/null
@@ -1,1322 +0,0 @@
-/******************************************************************************
- *    ixj.h
- *
- *
- * Device Driver for Quicknet Technologies, Inc.'s Telephony cards
- * including the Internet PhoneJACK, Internet PhoneJACK Lite,
- * Internet PhoneJACK PCI, Internet LineJACK, Internet PhoneCARD and
- * SmartCABLE
- *
- *    (c) Copyright 1999-2001  Quicknet Technologies, 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.
- *
- * Author:          Ed Okerson, <eokerson@quicknet.net>
- *    
- * Contributors:    Greg Herlein, <gherlein@quicknet.net>
- *                  David W. Erhart, <derhart@quicknet.net>
- *                  John Sellers, <jsellers@quicknet.net>
- *                  Mike Preston, <mpreston@quicknet.net>
- *
- * More information about the hardware related to this driver can be found
- * at our website:    http://www.quicknet.net
- *
- * Fixes:
- *
- * IN NO EVENT SHALL QUICKNET TECHNOLOGIES, INC. BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF QUICKNET
- * TECHNOLOGIES, INC.HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * QUICKNET TECHNOLOGIES, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND QUICKNET TECHNOLOGIES, INC. HAS NO OBLIGATION 
- * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- *****************************************************************************/
-#define IXJ_VERSION 3031
-
-#include <linux/types.h>
-
-#include <linux/ixjuser.h>
-#include <linux/phonedev.h>
-
-typedef __u16 WORD;
-typedef __u32 DWORD;
-typedef __u8 BYTE;
-
-#ifndef IXJMAX
-#define IXJMAX 16
-#endif
-
-/******************************************************************************
-*
-*  This structure when unioned with the structures below makes simple byte
-*  access to the registers easier.
-*
-******************************************************************************/
-typedef struct {
-	unsigned char low;
-	unsigned char high;
-} BYTES;
-
-typedef union {
-        BYTES bytes;
-        short word;
-} IXJ_WORD;
-
-typedef struct{
-	unsigned int b0:1;
-	unsigned int b1:1;
-	unsigned int b2:1;
-	unsigned int b3:1;
-	unsigned int b4:1;
-	unsigned int b5:1;
-	unsigned int b6:1;
-	unsigned int b7:1;
-} IXJ_CBITS;
-
-typedef union{
-	IXJ_CBITS cbits;
-	  char  cbyte;
-} IXJ_CBYTE;
-
-/******************************************************************************
-*
-*  This structure represents the Hardware Control Register of the CT8020/8021
-*  The CT8020 is used in the Internet PhoneJACK, and the 8021 in the
-*  Internet LineJACK
-*
-******************************************************************************/
-typedef struct {
-	unsigned int rxrdy:1;
-	unsigned int txrdy:1;
-	unsigned int status:1;
-	unsigned int auxstatus:1;
-	unsigned int rxdma:1;
-	unsigned int txdma:1;
-	unsigned int rxburst:1;
-	unsigned int txburst:1;
-	unsigned int dmadir:1;
-	unsigned int cont:1;
-	unsigned int irqn:1;
-	unsigned int t:5;
-} HCRBIT;
-
-typedef union {
-	HCRBIT bits;
-	BYTES bytes;
-} HCR;
-
-/******************************************************************************
-*
-*  This structure represents the Hardware Status Register of the CT8020/8021
-*  The CT8020 is used in the Internet PhoneJACK, and the 8021 in the
-*  Internet LineJACK
-*
-******************************************************************************/
-typedef struct {
-	unsigned int controlrdy:1;
-	unsigned int auxctlrdy:1;
-	unsigned int statusrdy:1;
-	unsigned int auxstatusrdy:1;
-	unsigned int rxrdy:1;
-	unsigned int txrdy:1;
-	unsigned int restart:1;
-	unsigned int irqn:1;
-	unsigned int rxdma:1;
-	unsigned int txdma:1;
-	unsigned int cohostshutdown:1;
-	unsigned int t:5;
-} HSRBIT;
-
-typedef union {
-	HSRBIT bits;
-	BYTES bytes;
-} HSR;
-
-/******************************************************************************
-*
-*  This structure represents the General Purpose IO Register of the CT8020/8021
-*  The CT8020 is used in the Internet PhoneJACK, and the 8021 in the
-*  Internet LineJACK
-*
-******************************************************************************/
-typedef struct {
-	unsigned int x:1;
-	unsigned int gpio1:1;
-	unsigned int gpio2:1;
-	unsigned int gpio3:1;
-	unsigned int gpio4:1;
-	unsigned int gpio5:1;
-	unsigned int gpio6:1;
-	unsigned int gpio7:1;
-	unsigned int xread:1;
-	unsigned int gpio1read:1;
-	unsigned int gpio2read:1;
-	unsigned int gpio3read:1;
-	unsigned int gpio4read:1;
-	unsigned int gpio5read:1;
-	unsigned int gpio6read:1;
-	unsigned int gpio7read:1;
-} GPIOBIT;
-
-typedef union {
-	GPIOBIT bits;
-	BYTES bytes;
-	unsigned short word;
-} GPIO;
-
-/******************************************************************************
-*
-*  This structure represents the Line Monitor status response
-*
-******************************************************************************/
-typedef struct {
-	unsigned int digit:4;
-	unsigned int cpf_valid:1;
-	unsigned int dtmf_valid:1;
-	unsigned int peak:1;
-	unsigned int z:1;
-	unsigned int f0:1;
-	unsigned int f1:1;
-	unsigned int f2:1;
-	unsigned int f3:1;
-	unsigned int frame:4;
-} LMON;
-
-typedef union {
-	LMON bits;
-	BYTES bytes;
-} DTMF;
-
-typedef struct {
-	unsigned int z:7;
-	unsigned int dtmf_en:1;
-	unsigned int y:4;
-	unsigned int F3:1;
-	unsigned int F2:1;
-	unsigned int F1:1;
-	unsigned int F0:1;
-} CP;
-
-typedef union {
-	CP bits;
-	BYTES bytes;
-} CPTF;
-
-/******************************************************************************
-*
-*  This structure represents the Status Control Register on the Internet
-*  LineJACK
-*
-******************************************************************************/
-typedef struct {
-	unsigned int c0:1;
-	unsigned int c1:1;
-	unsigned int stereo:1;
-	unsigned int daafsyncen:1;
-	unsigned int led1:1;
-	unsigned int led2:1;
-	unsigned int led3:1;
-	unsigned int led4:1;
-} PSCRWI;			/* Internet LineJACK and Internet PhoneJACK Lite */
-
-typedef struct {
-	unsigned int eidp:1;
-	unsigned int eisd:1;
-	unsigned int x:6;
-} PSCRWP;			/* Internet PhoneJACK PCI */
-
-typedef union {
-	PSCRWI bits;
-	PSCRWP pcib;
-	char byte;
-} PLD_SCRW;
-
-typedef struct {
-	unsigned int c0:1;
-	unsigned int c1:1;
-	unsigned int x:1;
-	unsigned int d0ee:1;
-	unsigned int mixerbusy:1;
-	unsigned int sci:1;
-	unsigned int dspflag:1;
-	unsigned int daaflag:1;
-} PSCRRI;
-
-typedef struct {
-	unsigned int eidp:1;
-	unsigned int eisd:1;
-	unsigned int x:4;
-	unsigned int dspflag:1;
-	unsigned int det:1;
-} PSCRRP;
-
-typedef union {
-	PSCRRI bits;
-	PSCRRP pcib;
-	char byte;
-} PLD_SCRR;
-
-/******************************************************************************
-*
-*  These structures represents the SLIC Control Register on the
-*  Internet LineJACK
-*
-******************************************************************************/
-typedef struct {
-	unsigned int c1:1;
-	unsigned int c2:1;
-	unsigned int c3:1;
-	unsigned int b2en:1;
-	unsigned int spken:1;
-	unsigned int rly1:1;
-	unsigned int rly2:1;
-	unsigned int rly3:1;
-} PSLICWRITE;
-
-typedef struct {
-	unsigned int state:3;
-	unsigned int b2en:1;
-	unsigned int spken:1;
-	unsigned int c3:1;
-	unsigned int potspstn:1;
-	unsigned int det:1;
-} PSLICREAD;
-
-typedef struct {
-	unsigned int c1:1;
-	unsigned int c2:1;
-	unsigned int c3:1;
-	unsigned int b2en:1;
-	unsigned int e1:1;
-	unsigned int mic:1;
-	unsigned int spk:1;
-	unsigned int x:1;
-} PSLICPCI;
-
-typedef union {
-	PSLICPCI pcib;
-	PSLICWRITE bits;
-	PSLICREAD slic;
-	char byte;
-} PLD_SLICW;
-
-typedef union {
-	PSLICPCI pcib;
-	PSLICREAD bits;
-	char byte;
-} PLD_SLICR;
-
-/******************************************************************************
-*
-*  These structures represents the Clock Control Register on the
-*  Internet LineJACK
-*
-******************************************************************************/
-typedef struct {
-	unsigned int clk0:1;
-	unsigned int clk1:1;
-	unsigned int clk2:1;
-	unsigned int x0:1;
-	unsigned int slic_e1:1;
-	unsigned int x1:1;
-	unsigned int x2:1;
-	unsigned int x3:1;
-} PCLOCK;
-
-typedef union {
-	PCLOCK bits;
-	char byte;
-} PLD_CLOCK;
-
-/******************************************************************************
-*
-*  These structures deal with the mixer on the Internet LineJACK
-*
-******************************************************************************/
-
-typedef struct {
-	unsigned short vol[10];
-	unsigned int recsrc;
-	unsigned int modcnt;
-	unsigned short micpreamp;
-} MIX;
-
-/******************************************************************************
-*
-*  These structures deal with the control logic on the Internet PhoneCARD
-*
-******************************************************************************/
-typedef struct {
-	unsigned int x0:4;	/* unused bits */
-
-	unsigned int ed:1;	/* Event Detect */
-
-	unsigned int drf:1;	/* SmartCABLE Removal Flag 1=no cable */
-
-	unsigned int dspf:1;	/* DSP Flag 1=DSP Ready */
-
-	unsigned int crr:1;	/* Control Register Ready */
-
-} COMMAND_REG1;
-
-typedef union {
-	COMMAND_REG1 bits;
-	unsigned char byte;
-} PCMCIA_CR1;
-
-typedef struct {
-	unsigned int x0:4;	/* unused bits */
-
-	unsigned int rstc:1;	/* SmartCABLE Reset */
-
-	unsigned int pwr:1;	/* SmartCABLE Power */
-
-	unsigned int x1:2;	/* unused bits */
-
-} COMMAND_REG2;
-
-typedef union {
-	COMMAND_REG2 bits;
-	unsigned char byte;
-} PCMCIA_CR2;
-
-typedef struct {
-	unsigned int addr:5;	/* R/W SmartCABLE Register Address */
-
-	unsigned int rw:1;	/* Read / Write flag */
-
-	unsigned int dev:2;	/* 2 bit SmartCABLE Device Address */
-
-} CONTROL_REG;
-
-typedef union {
-	CONTROL_REG bits;
-	unsigned char byte;
-} PCMCIA_SCCR;
-
-typedef struct {
-	unsigned int hsw:1;
-	unsigned int det:1;
-	unsigned int led2:1;
-	unsigned int led1:1;
-	unsigned int ring1:1;
-	unsigned int ring0:1;
-	unsigned int x:1;
-	unsigned int powerdown:1;
-} PCMCIA_SLIC_REG;
-
-typedef union {
-	PCMCIA_SLIC_REG bits;
-	unsigned char byte;
-} PCMCIA_SLIC;
-
-typedef struct {
-	unsigned int cpd:1;	/* Chip Power Down */
-
-	unsigned int mpd:1;	/* MIC Bias Power Down */
-
-	unsigned int hpd:1;	/* Handset Drive Power Down */
-
-	unsigned int lpd:1;	/* Line Drive Power Down */
-
-	unsigned int spd:1;	/* Speaker Drive Power Down */
-
-	unsigned int x:2;	/* unused bits */
-
-	unsigned int sr:1;	/* Software Reset */
-
-} Si3CONTROL1;
-
-typedef union {
-	Si3CONTROL1 bits;
-	unsigned char byte;
-} Si3C1;
-
-typedef struct {
-	unsigned int al:1;	/* Analog Loopback DAC analog -> ADC analog */
-
-	unsigned int dl2:1;	/* Digital Loopback DAC -> ADC one bit */
-
-	unsigned int dl1:1;	/* Digital Loopback ADC -> DAC one bit */
-
-	unsigned int pll:1;	/* 1 = div 10, 0 = div 5 */
-
-	unsigned int hpd:1;	/* HPF disable */
-
-	unsigned int x:3;	/* unused bits */
-
-} Si3CONTROL2;
-
-typedef union {
-	Si3CONTROL2 bits;
-	unsigned char byte;
-} Si3C2;
-
-typedef struct {
-	unsigned int iir:1;	/* 1 enables IIR, 0 enables FIR */
-
-	unsigned int him:1;	/* Handset Input Mute */
-
-	unsigned int mcm:1;	/* MIC In Mute */
-
-	unsigned int mcg:2;	/* MIC In Gain */
-
-	unsigned int lim:1;	/* Line In Mute */
-
-	unsigned int lig:2;	/* Line In Gain */
-
-} Si3RXGAIN;
-
-typedef union {
-	Si3RXGAIN bits;
-	unsigned char byte;
-} Si3RXG;
-
-typedef struct {
-	unsigned int hom:1;	/* Handset Out Mute */
-
-	unsigned int lom:1;	/* Line Out Mute */
-
-	unsigned int rxg:5;	/* RX PGA Gain */
-
-	unsigned int x:1;	/* unused bit */
-
-} Si3ADCVOLUME;
-
-typedef union {
-	Si3ADCVOLUME bits;
-	unsigned char byte;
-} Si3ADC;
-
-typedef struct {
-	unsigned int srm:1;	/* Speaker Right Mute */
-
-	unsigned int slm:1;	/* Speaker Left Mute */
-
-	unsigned int txg:5;	/* TX PGA Gain */
-
-	unsigned int x:1;	/* unused bit */
-
-} Si3DACVOLUME;
-
-typedef union {
-	Si3DACVOLUME bits;
-	unsigned char byte;
-} Si3DAC;
-
-typedef struct {
-	unsigned int x:5;	/* unused bit */
-
-	unsigned int losc:1;	/* Line Out Short Circuit */
-
-	unsigned int srsc:1;	/* Speaker Right Short Circuit */
-
-	unsigned int slsc:1;	/* Speaker Left Short Circuit */
-
-} Si3STATUSREPORT;
-
-typedef union {
-	Si3STATUSREPORT bits;
-	unsigned char byte;
-} Si3STAT;
-
-typedef struct {
-	unsigned int sot:2;	/* Speaker Out Attenuation */
-
-	unsigned int lot:2;	/* Line Out Attenuation */
-
-	unsigned int x:4;	/* unused bits */
-
-} Si3ANALOGATTN;
-
-typedef union {
-	Si3ANALOGATTN bits;
-	unsigned char byte;
-} Si3AATT;
-
-/******************************************************************************
-*
-*  These structures deal with the DAA on the Internet LineJACK
-*
-******************************************************************************/
-
-typedef struct _DAA_REGS {
-	/*----------------------------------------------- */
-	/* SOP Registers */
-	/* */
-	BYTE bySOP;
-
-	union _SOP_REGS {
-		struct _SOP {
-			union	/* SOP - CR0 Register */
-			 {
-				BYTE reg;
-				struct _CR0_BITREGS {
-					BYTE CLK_EXT:1;		/* cr0[0:0] */
-
-					BYTE RIP:1;	/* cr0[1:1] */
-
-					BYTE AR:1;	/* cr0[2:2] */
-
-					BYTE AX:1;	/* cr0[3:3] */
-
-					BYTE FRR:1;	/* cr0[4:4] */
-
-					BYTE FRX:1;	/* cr0[5:5] */
-
-					BYTE IM:1;	/* cr0[6:6] */
-
-					BYTE TH:1;	/* cr0[7:7] */
-
-				} bitreg;
-			} cr0;
-
-			union	/* SOP - CR1 Register */
-			 {
-				BYTE reg;
-				struct _CR1_REGS {
-					BYTE RM:1;	/* cr1[0:0] */
-
-					BYTE RMR:1;	/* cr1[1:1] */
-
-					BYTE No_auto:1;		/* cr1[2:2] */
-
-					BYTE Pulse:1;	/* cr1[3:3] */
-
-					BYTE P_Tone1:1;		/* cr1[4:4] */
-
-					BYTE P_Tone2:1;		/* cr1[5:5] */
-
-					BYTE E_Tone1:1;		/* cr1[6:6] */
-
-					BYTE E_Tone2:1;		/* cr1[7:7] */
-
-				} bitreg;
-			} cr1;
-
-			union	/* SOP - CR2 Register */
-			 {
-				BYTE reg;
-				struct _CR2_REGS {
-					BYTE Call_II:1;		/* CR2[0:0] */
-
-					BYTE Call_I:1;	/* CR2[1:1] */
-
-					BYTE Call_en:1;		/* CR2[2:2] */
-
-					BYTE Call_pon:1;	/* CR2[3:3] */
-
-					BYTE IDR:1;	/* CR2[4:4] */
-
-					BYTE COT_R:3;	/* CR2[5:7] */
-
-				} bitreg;
-			} cr2;
-
-			union	/* SOP - CR3 Register */
-			 {
-				BYTE reg;
-				struct _CR3_REGS {
-					BYTE DHP_X:1;	/* CR3[0:0] */
-
-					BYTE DHP_R:1;	/* CR3[1:1] */
-
-					BYTE Cal_pctl:1;	/* CR3[2:2] */
-
-					BYTE SEL:1;	/* CR3[3:3] */
-
-					BYTE TestLoops:4;	/* CR3[4:7] */
-
-				} bitreg;
-			} cr3;
-
-			union	/* SOP - CR4 Register */
-			 {
-				BYTE reg;
-				struct _CR4_REGS {
-					BYTE Fsc_en:1;	/* CR4[0:0] */
-
-					BYTE Int_en:1;	/* CR4[1:1] */
-
-					BYTE AGX:2;	/* CR4[2:3] */
-
-					BYTE AGR_R:2;	/* CR4[4:5] */
-
-					BYTE AGR_Z:2;	/* CR4[6:7] */
-
-				} bitreg;
-			} cr4;
-
-			union	/* SOP - CR5 Register */
-			 {
-				BYTE reg;
-				struct _CR5_REGS {
-					BYTE V_0:1;	/* CR5[0:0] */
-
-					BYTE V_1:1;	/* CR5[1:1] */
-
-					BYTE V_2:1;	/* CR5[2:2] */
-
-					BYTE V_3:1;	/* CR5[3:3] */
-
-					BYTE V_4:1;	/* CR5[4:4] */
-
-					BYTE V_5:1;	/* CR5[5:5] */
-
-					BYTE V_6:1;	/* CR5[6:6] */
-
-					BYTE V_7:1;	/* CR5[7:7] */
-
-				} bitreg;
-			} cr5;
-
-			union	/* SOP - CR6 Register */
-			 {
-				BYTE reg;
-				struct _CR6_REGS {
-					BYTE reserved:8;	/* CR6[0:7] */
-
-				} bitreg;
-			} cr6;
-
-			union	/* SOP - CR7 Register */
-			 {
-				BYTE reg;
-				struct _CR7_REGS {
-					BYTE reserved:8;	/* CR7[0:7] */
-
-				} bitreg;
-			} cr7;
-		} SOP;
-
-		BYTE ByteRegs[sizeof(struct _SOP)];
-
-	} SOP_REGS;
-
-	/* DAA_REGS.SOP_REGS.SOP.CR5.reg */
-	/* DAA_REGS.SOP_REGS.SOP.CR5.bitreg */
-	/* DAA_REGS.SOP_REGS.SOP.CR5.bitreg.V_2 */
-	/* DAA_REGS.SOP_REGS.ByteRegs[5] */
-
-	/*----------------------------------------------- */
-	/* XOP Registers */
-	/* */
-	BYTE byXOP;
-
-	union _XOP_REGS {
-		struct _XOP {
-			union	XOPXR0/* XOP - XR0 Register - Read values */
-			 {
-				BYTE reg;
-				struct _XR0_BITREGS {
-					BYTE SI_0:1;	/* XR0[0:0] - Read */
-
-					BYTE SI_1:1;	/* XR0[1:1] - Read */
-
-					BYTE VDD_OK:1;	/* XR0[2:2] - Read */
-
-					BYTE Caller_ID:1;	/* XR0[3:3] - Read */
-
-					BYTE RING:1;	/* XR0[4:4] - Read */
-
-					BYTE Cadence:1;		/* XR0[5:5] - Read */
-
-					BYTE Wake_up:1;		/* XR0[6:6] - Read */
-
-					BYTE RMR:1;	/* XR0[7:7] - Read */
-
-				} bitreg;
-			} xr0;
-
-			union	/* XOP - XR1 Register */
-			 {
-				BYTE reg;
-				struct _XR1_BITREGS {
-					BYTE M_SI_0:1;	/* XR1[0:0] */
-
-					BYTE M_SI_1:1;	/* XR1[1:1] */
-
-					BYTE M_VDD_OK:1;	/* XR1[2:2] */
-
-					BYTE M_Caller_ID:1;	/* XR1[3:3] */
-
-					BYTE M_RING:1;	/* XR1[4:4] */
-
-					BYTE M_Cadence:1;	/* XR1[5:5] */
-
-					BYTE M_Wake_up:1;	/* XR1[6:6] */
-
-					BYTE unused:1;	/* XR1[7:7] */
-
-				} bitreg;
-			} xr1;
-
-			union	/* XOP - XR2 Register */
-			 {
-				BYTE reg;
-				struct _XR2_BITREGS {
-					BYTE CTO0:1;	/* XR2[0:0] */
-
-					BYTE CTO1:1;	/* XR2[1:1] */
-
-					BYTE CTO2:1;	/* XR2[2:2] */
-
-					BYTE CTO3:1;	/* XR2[3:3] */
-
-					BYTE CTO4:1;	/* XR2[4:4] */
-
-					BYTE CTO5:1;	/* XR2[5:5] */
-
-					BYTE CTO6:1;	/* XR2[6:6] */
-
-					BYTE CTO7:1;	/* XR2[7:7] */
-
-				} bitreg;
-			} xr2;
-
-			union	/* XOP - XR3 Register */
-			 {
-				BYTE reg;
-				struct _XR3_BITREGS {
-					BYTE DCR0:1;	/* XR3[0:0] */
-
-					BYTE DCR1:1;	/* XR3[1:1] */
-
-					BYTE DCI:1;	/* XR3[2:2] */
-
-					BYTE DCU0:1;	/* XR3[3:3] */
-
-					BYTE DCU1:1;	/* XR3[4:4] */
-
-					BYTE B_off:1;	/* XR3[5:5] */
-
-					BYTE AGB0:1;	/* XR3[6:6] */
-
-					BYTE AGB1:1;	/* XR3[7:7] */
-
-				} bitreg;
-			} xr3;
-
-			union	/* XOP - XR4 Register */
-			 {
-				BYTE reg;
-				struct _XR4_BITREGS {
-					BYTE C_0:1;	/* XR4[0:0] */
-
-					BYTE C_1:1;	/* XR4[1:1] */
-
-					BYTE C_2:1;	/* XR4[2:2] */
-
-					BYTE C_3:1;	/* XR4[3:3] */
-
-					BYTE C_4:1;	/* XR4[4:4] */
-
-					BYTE C_5:1;	/* XR4[5:5] */
-
-					BYTE C_6:1;	/* XR4[6:6] */
-
-					BYTE C_7:1;	/* XR4[7:7] */
-
-				} bitreg;
-			} xr4;
-
-			union	/* XOP - XR5 Register */
-			 {
-				BYTE reg;
-				struct _XR5_BITREGS {
-					BYTE T_0:1;	/* XR5[0:0] */
-
-					BYTE T_1:1;	/* XR5[1:1] */
-
-					BYTE T_2:1;	/* XR5[2:2] */
-
-					BYTE T_3:1;	/* XR5[3:3] */
-
-					BYTE T_4:1;	/* XR5[4:4] */
-
-					BYTE T_5:1;	/* XR5[5:5] */
-
-					BYTE T_6:1;	/* XR5[6:6] */
-
-					BYTE T_7:1;	/* XR5[7:7] */
-
-				} bitreg;
-			} xr5;
-
-			union	/* XOP - XR6 Register - Read Values */
-			 {
-				BYTE reg;
-				struct _XR6_BITREGS {
-					BYTE CPS0:1;	/* XR6[0:0] */
-
-					BYTE CPS1:1;	/* XR6[1:1] */
-
-					BYTE unused1:2;		/* XR6[2:3] */
-
-					BYTE CLK_OFF:1;		/* XR6[4:4] */
-
-					BYTE unused2:3;		/* XR6[5:7] */
-
-				} bitreg;
-			} xr6;
-
-			union	/* XOP - XR7 Register */
-			 {
-				BYTE reg;
-				struct _XR7_BITREGS {
-					BYTE unused1:1;		/* XR7[0:0] */
-
-					BYTE Vdd0:1;	/* XR7[1:1] */
-
-					BYTE Vdd1:1;	/* XR7[2:2] */
-
-					BYTE unused2:5;		/* XR7[3:7] */
-
-				} bitreg;
-			} xr7;
-		} XOP;
-
-		BYTE ByteRegs[sizeof(struct _XOP)];
-
-	} XOP_REGS;
-
-	/* DAA_REGS.XOP_REGS.XOP.XR7.reg */
-	/* DAA_REGS.XOP_REGS.XOP.XR7.bitreg */
-	/* DAA_REGS.XOP_REGS.XOP.XR7.bitreg.Vdd0 */
-	/* DAA_REGS.XOP_REGS.ByteRegs[7] */
-
-	/*----------------------------------------------- */
-	/* COP Registers */
-	/* */
-	BYTE byCOP;
-
-	union _COP_REGS {
-		struct _COP {
-			BYTE THFilterCoeff_1[8];	/* COP - TH Filter Coefficients,      CODE=0, Part 1 */
-
-			BYTE THFilterCoeff_2[8];	/* COP - TH Filter Coefficients,      CODE=1, Part 2 */
-
-			BYTE THFilterCoeff_3[8];	/* COP - TH Filter Coefficients,      CODE=2, Part 3 */
-
-			BYTE RingerImpendance_1[8];	/* COP - Ringer Impendance Coefficients,  CODE=3, Part 1 */
-
-			BYTE IMFilterCoeff_1[8];	/* COP - IM Filter Coefficients,      CODE=4, Part 1 */
-
-			BYTE IMFilterCoeff_2[8];	/* COP - IM Filter Coefficients,      CODE=5, Part 2 */
-
-			BYTE RingerImpendance_2[8];	/* COP - Ringer Impendance Coefficients,  CODE=6, Part 2 */
-
-			BYTE FRRFilterCoeff[8];		/* COP - FRR Filter Coefficients,      CODE=7 */
-
-			BYTE FRXFilterCoeff[8];		/* COP - FRX Filter Coefficients,      CODE=8 */
-
-			BYTE ARFilterCoeff[4];	/* COP - AR Filter Coefficients,      CODE=9 */
-
-			BYTE AXFilterCoeff[4];	/* COP - AX Filter Coefficients,      CODE=10  */
-
-			BYTE Tone1Coeff[4];	/* COP - Tone1 Coefficients,        CODE=11 */
-
-			BYTE Tone2Coeff[4];	/* COP - Tone2 Coefficients,        CODE=12 */
-
-			BYTE LevelmeteringRinging[4];	/* COP - Levelmetering Ringing,        CODE=13 */
-
-			BYTE CallerID1stTone[8];	/* COP - Caller ID 1st Tone,        CODE=14 */
-
-			BYTE CallerID2ndTone[8];	/* COP - Caller ID 2nd Tone,        CODE=15 */
-
-		} COP;
-
-		BYTE ByteRegs[sizeof(struct _COP)];
-
-	} COP_REGS;
-
-	/* DAA_REGS.COP_REGS.COP.XR7.Tone1Coeff[3] */
-	/* DAA_REGS.COP_REGS.COP.XR7.bitreg */
-	/* DAA_REGS.COP_REGS.COP.XR7.bitreg.Vdd0 */
-	/* DAA_REGS.COP_REGS.ByteRegs[57] */
-
-	/*----------------------------------------------- */
-	/* CAO Registers */
-	/* */
-	BYTE byCAO;
-
-	union _CAO_REGS {
-		struct _CAO {
-			BYTE CallerID[512];	/* CAO - Caller ID Bytes */
-
-		} CAO;
-
-		BYTE ByteRegs[sizeof(struct _CAO)];
-	} CAO_REGS;
-
-	union			/* XOP - XR0 Register - Write values */
-	 {
-		BYTE reg;
-		struct _XR0_BITREGSW {
-			BYTE SO_0:1;	/* XR1[0:0] - Write */
-
-			BYTE SO_1:1;	/* XR1[1:1] - Write */
-
-			BYTE SO_2:1;	/* XR1[2:2] - Write */
-
-			BYTE unused:5;	/* XR1[3:7] - Write */
-
-		} bitreg;
-	} XOP_xr0_W;
-
-	union			/* XOP - XR6 Register - Write values */
-	 {
-		BYTE reg;
-		struct _XR6_BITREGSW {
-			BYTE unused1:4;		/* XR6[0:3] */
-
-			BYTE CLK_OFF:1;		/* XR6[4:4] */
-
-			BYTE unused2:3;		/* XR6[5:7] */
-
-		} bitreg;
-	} XOP_xr6_W;
-
-} DAA_REGS;
-
-#define ALISDAA_ID_BYTE      0x81
-#define ALISDAA_CALLERID_SIZE  512
-
-/*------------------------------ */
-/* */
-/*  Misc definitions */
-/* */
-
-/* Power Up Operation */
-#define SOP_PU_SLEEP    0
-#define SOP_PU_RINGING    1
-#define SOP_PU_CONVERSATION  2
-#define SOP_PU_PULSEDIALING  3
-#define SOP_PU_RESET    4
-
-#define ALISDAA_CALLERID_SIZE 512
-
-#define PLAYBACK_MODE_COMPRESSED	0	/*        Selects: Compressed modes, TrueSpeech 8.5-4.1, G.723.1, G.722, G.728, G.729 */
-#define PLAYBACK_MODE_TRUESPEECH_V40	0	/*        Selects: TrueSpeech 8.5, 6.3, 5.3, 4.8 or 4.1 Kbps */
-#define PLAYBACK_MODE_TRUESPEECH	8	/*        Selects: TrueSpeech 8.5, 6.3, 5.3, 4.8 or 4.1 Kbps Version 5.1 */
-#define PLAYBACK_MODE_ULAW		2	/*        Selects: 64 Kbit/sec MuA-law PCM */
-#define PLAYBACK_MODE_ALAW		10	/*        Selects: 64 Kbit/sec A-law PCM */
-#define PLAYBACK_MODE_16LINEAR		6	/*        Selects: 128 Kbit/sec 16-bit linear */
-#define PLAYBACK_MODE_8LINEAR		4	/*        Selects: 64 Kbit/sec 8-bit signed linear */
-#define PLAYBACK_MODE_8LINEAR_WSS	5	/*        Selects: 64 Kbit/sec WSS 8-bit unsigned linear */
-
-#define RECORD_MODE_COMPRESSED		0	/*        Selects: Compressed modes, TrueSpeech 8.5-4.1, G.723.1, G.722, G.728, G.729 */
-#define RECORD_MODE_TRUESPEECH		0	/*        Selects: TrueSpeech 8.5, 6.3, 5.3, 4.8 or 4.1 Kbps */
-#define RECORD_MODE_ULAW		4	/*        Selects: 64 Kbit/sec Mu-law PCM */
-#define RECORD_MODE_ALAW		12	/*        Selects: 64 Kbit/sec A-law PCM */
-#define RECORD_MODE_16LINEAR		5	/*        Selects: 128 Kbit/sec 16-bit linear */
-#define RECORD_MODE_8LINEAR		6	/*        Selects: 64 Kbit/sec 8-bit signed linear */
-#define RECORD_MODE_8LINEAR_WSS		7	/*        Selects: 64 Kbit/sec WSS 8-bit unsigned linear */
-
-enum SLIC_STATES {
-	PLD_SLIC_STATE_OC = 0,
-	PLD_SLIC_STATE_RINGING,
-	PLD_SLIC_STATE_ACTIVE,
-	PLD_SLIC_STATE_OHT,
-	PLD_SLIC_STATE_TIPOPEN,
-	PLD_SLIC_STATE_STANDBY,
-	PLD_SLIC_STATE_APR,
-	PLD_SLIC_STATE_OHTPR
-};
-
-enum SCI_CONTROL {
-	SCI_End = 0,
-	SCI_Enable_DAA,
-	SCI_Enable_Mixer,
-	SCI_Enable_EEPROM
-};
-
-enum Mode {
-	T63, T53, T48, T40
-};
-enum Dir {
-	V3_TO_V4, V4_TO_V3, V4_TO_V5, V5_TO_V4
-};
-
-typedef struct Proc_Info_Tag {
-	enum Mode convert_mode;
-	enum Dir convert_dir;
-	int Prev_Frame_Type;
-	int Current_Frame_Type;
-} Proc_Info_Type;
-
-enum PREVAL {
-	NORMAL = 0,
-	NOPOST,
-	POSTONLY,
-	PREERROR
-};
-
-enum IXJ_EXTENSIONS {
-	G729LOADER = 0,
-	TS85LOADER,
-	PRE_READ,
-	POST_READ,
-	PRE_WRITE,
-	POST_WRITE,
-	PRE_IOCTL,
-	POST_IOCTL
-};
-
-typedef struct {
-	char enable;
-	char en_filter;
-	unsigned int filter;
-	unsigned int state;	/* State 0 when cadence has not started. */
-
-	unsigned int on1;	/* State 1 */
-
-	unsigned long on1min;	/* State 1 - 10% + jiffies */
- 	unsigned long on1dot;	/* State 1 + jiffies */
-
-	unsigned long on1max;	/* State 1 + 10% + jiffies */
-
-	unsigned int off1;	/* State 2 */
-
-	unsigned long off1min;
- 	unsigned long off1dot;	/* State 2 + jiffies */
-	unsigned long off1max;
-	unsigned int on2;	/* State 3 */
-
-	unsigned long on2min;
-	unsigned long on2dot;
-	unsigned long on2max;
-	unsigned int off2;	/* State 4 */
-
-	unsigned long off2min;
- 	unsigned long off2dot;	/* State 4 + jiffies */
-	unsigned long off2max;
-	unsigned int on3;	/* State 5 */
-
-	unsigned long on3min;
-	unsigned long on3dot;
-	unsigned long on3max;
-	unsigned int off3;	/* State 6 */
-
-	unsigned long off3min;
- 	unsigned long off3dot;	/* State 6 + jiffies */
-	unsigned long off3max;
-} IXJ_CADENCE_F;
-
-typedef struct {
-	unsigned int busytone:1;
-	unsigned int dialtone:1;
-	unsigned int ringback:1;
-	unsigned int ringing:1;
-	unsigned int playing:1;
-	unsigned int recording:1;
-	unsigned int cringing:1;
-	unsigned int play_first_frame:1;
-	unsigned int pstn_present:1;
-	unsigned int pstn_ringing:1;
-	unsigned int pots_correct:1;
-	unsigned int pots_pstn:1;
-	unsigned int g729_loaded:1;
-	unsigned int ts85_loaded:1;
-	unsigned int dtmf_oob:1;	/* DTMF Out-Of-Band */
-
-	unsigned int pcmciascp:1;	/* SmartCABLE Present */
-
-	unsigned int pcmciasct:2;	/* SmartCABLE Type */
-
-	unsigned int pcmciastate:3;	/* SmartCABLE Init State */
-
-	unsigned int inwrite:1;	/* Currently writing */
-
-	unsigned int inread:1;	/* Currently reading */
-
-	unsigned int incheck:1;	/* Currently checking the SmartCABLE */
-
-	unsigned int cidplay:1; /* Currently playing Caller ID */
-
-	unsigned int cidring:1; /* This is the ring for Caller ID */
-
-	unsigned int cidsent:1; /* Caller ID has been sent */
-
-	unsigned int cidcw_ack:1; /* Caller ID CW ACK (from CPE) */
-	unsigned int firstring:1; /* First ring cadence is complete */
-	unsigned int pstncheck:1;	/* Currently checking the PSTN Line */
-	unsigned int pstn_rmr:1;
-	unsigned int x:3;	/* unused bits */
-
-} IXJ_FLAGS;
-
-/******************************************************************************
-*
-*  This structure holds the state of all of the Quicknet cards
-*
-******************************************************************************/
-
-typedef struct {
-	int elements_used;
-	IXJ_CADENCE_TERM termination;
-	IXJ_CADENCE_ELEMENT *ce;
-} ixj_cadence;
-
-typedef struct {
-	struct phone_device p;
-	struct timer_list timer;
-	unsigned int board;
-	unsigned int DSPbase;
-	unsigned int XILINXbase;
-	unsigned int serial;
-	atomic_t DSPWrite;
-	struct phone_capability caplist[30];
-	unsigned int caps;
-	struct pnp_dev *dev;
-	unsigned int cardtype;
-	unsigned int rec_codec;
-	unsigned int cid_rec_codec;
-	unsigned int cid_rec_volume;
-	unsigned char cid_rec_flag;
-	signed char rec_mode;
-	unsigned int play_codec;
-	unsigned int cid_play_codec;
-	unsigned int cid_play_volume;
-	unsigned char cid_play_flag;
-	signed char play_mode;
-	IXJ_FLAGS flags;
-	unsigned long busyflags;
-	unsigned int rec_frame_size;
-	unsigned int play_frame_size;
-	unsigned int cid_play_frame_size;
-	unsigned int cid_base_frame_size;
-	unsigned long cidcw_wait;
-	int aec_level;
-	int cid_play_aec_level;
-	int readers, writers;
-        wait_queue_head_t poll_q;
-        wait_queue_head_t read_q;
-	char *read_buffer, *read_buffer_end;
-	char *read_convert_buffer;
-	size_t read_buffer_size;
-	unsigned int read_buffer_ready;
-        wait_queue_head_t write_q;
-	char *write_buffer, *write_buffer_end;
-	char *write_convert_buffer;
-	size_t write_buffer_size;
-	unsigned int write_buffers_empty;
-	unsigned long drybuffer;
-	char *write_buffer_rp, *write_buffer_wp;
-	char dtmfbuffer[80];
-	char dtmf_current;
-	int dtmf_wp, dtmf_rp, dtmf_state, dtmf_proc;
-	int tone_off_time, tone_on_time;
-	struct fasync_struct *async_queue;
-	unsigned long tone_start_jif;
-	char tone_index;
-	char tone_state;
-	char maxrings;
-	ixj_cadence *cadence_t;
-	ixj_cadence *cadence_r;
-	int tone_cadence_state;
-	IXJ_CADENCE_F cadence_f[6];
-	DTMF dtmf;
-	CPTF cptf;
-	BYTES dsp;
-	BYTES ver;
-	BYTES scr;
-	BYTES ssr;
-	BYTES baseframe;
-	HSR hsr;
-	GPIO gpio;
-	PLD_SCRR pld_scrr;
-	PLD_SCRW pld_scrw;
-	PLD_SLICW pld_slicw;
-	PLD_SLICR pld_slicr;
-	PLD_CLOCK pld_clock;
-	PCMCIA_CR1 pccr1;
-	PCMCIA_CR2 pccr2;
-	PCMCIA_SCCR psccr;
-	PCMCIA_SLIC pslic;
-	char pscdd;
-	Si3C1 sic1;
-	Si3C2 sic2;
-	Si3RXG sirxg;
-	Si3ADC siadc;
-	Si3DAC sidac;
-	Si3STAT sistat;
-	Si3AATT siaatt;
-	MIX mix;
-	unsigned short ring_cadence;
-	int ring_cadence_t;
-	unsigned long ring_cadence_jif;
-	unsigned long checkwait;
-	int intercom;
-	int m_hook;
-	int r_hook;
-	int p_hook;
-	char pstn_envelope;
-	char pstn_cid_intr;
-	unsigned char fskz;
-	unsigned char fskphase;
-	unsigned char fskcnt;
-        unsigned int cidsize;
-	unsigned int cidcnt;
-	unsigned long pstn_cid_received;
-	PHONE_CID cid;
-	PHONE_CID cid_send;
-	unsigned long pstn_ring_int;
-	unsigned long pstn_ring_start;
-	unsigned long pstn_ring_stop;
-	unsigned long pstn_winkstart;
-	unsigned long pstn_last_rmr;
-	unsigned long pstn_prev_rmr;
-	unsigned long pots_winkstart;
-	unsigned int winktime;
-	unsigned long flash_end;
-	char port;
-	char hookstate;
-	union telephony_exception ex;
-	union telephony_exception ex_sig;
-	int ixj_signals[35];
-	IXJ_SIGDEF sigdef;
-	char daa_mode;
-	char daa_country;
-	unsigned long pstn_sleeptil;
-	DAA_REGS m_DAAShadowRegs;
-	Proc_Info_Type Info_read;
-	Proc_Info_Type Info_write;
-	unsigned short frame_count;
-	unsigned int filter_hist[4];
-	unsigned char filter_en[6];
-	unsigned short proc_load;
-	unsigned long framesread;
-	unsigned long frameswritten;
-	unsigned long read_wait;
-	unsigned long write_wait;
-	unsigned long timerchecks;
-	unsigned long txreadycheck;
-	unsigned long rxreadycheck;
-	unsigned long statuswait;
-	unsigned long statuswaitfail;
-	unsigned long pcontrolwait;
-	unsigned long pcontrolwaitfail;
-	unsigned long iscontrolready;
-	unsigned long iscontrolreadyfail;
-	unsigned long pstnstatecheck;
-#ifdef IXJ_DYN_ALLOC
-	short *fskdata;
-#else
-	short fskdata[8000];
-#endif
-	int fsksize;
-	int fskdcnt;
-} IXJ;
-
-typedef int (*IXJ_REGFUNC) (IXJ * j, unsigned long arg);
-
-extern IXJ *ixj_pcmcia_probe(unsigned long, unsigned long);
-
diff --git a/drivers/staging/telephony/ixj_pcmcia.c b/drivers/staging/telephony/ixj_pcmcia.c
deleted file mode 100644
index 05032e2..0000000
--- a/drivers/staging/telephony/ixj_pcmcia.c
+++ /dev/null
@@ -1,187 +0,0 @@
-#include "ixj-ver.h"
-
-#include <linux/module.h>
-
-#include <linux/init.h>
-#include <linux/kernel.h>	/* printk() */
-#include <linux/fs.h>		/* everything... */
-#include <linux/errno.h>	/* error codes */
-#include <linux/slab.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-
-#include "ixj.h"
-
-/*
- *	PCMCIA service support for Quicknet cards
- */
- 
-
-typedef struct ixj_info_t {
-	int ndev;
-	struct ixj *port;
-} ixj_info_t;
-
-static void ixj_detach(struct pcmcia_device *p_dev);
-static int ixj_config(struct pcmcia_device * link);
-static void ixj_cs_release(struct pcmcia_device * link);
-
-static int ixj_probe(struct pcmcia_device *p_dev)
-{
-	dev_dbg(&p_dev->dev, "ixj_attach()\n");
-	/* Create new ixj device */
-	p_dev->priv = kzalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
-	if (!p_dev->priv) {
-		return -ENOMEM;
-	}
-
-	return ixj_config(p_dev);
-}
-
-static void ixj_detach(struct pcmcia_device *link)
-{
-	dev_dbg(&link->dev, "ixj_detach\n");
-
-	ixj_cs_release(link);
-
-        kfree(link->priv);
-}
-
-static void ixj_get_serial(struct pcmcia_device * link, IXJ * j)
-{
-	char *str;
-	int i, place;
-	dev_dbg(&link->dev, "ixj_get_serial\n");
-
-	str = link->prod_id[0];
-	if (!str)
-		goto failed;
-	printk("%s", str);
-	str = link->prod_id[1];
-	if (!str)
-		goto failed;
-	printk(" %s", str);
-	str = link->prod_id[2];
-	if (!str)
-		goto failed;
-	place = 1;
-	for (i = strlen(str) - 1; i >= 0; i--) {
-		switch (str[i]) {
-		case '0':
-		case '1':
-		case '2':
-		case '3':
-		case '4':
-		case '5':
-		case '6':
-		case '7':
-		case '8':
-		case '9':
-			j->serial += (str[i] - 48) * place;
-			break;
-		case 'A':
-		case 'B':
-		case 'C':
-		case 'D':
-		case 'E':
-		case 'F':
-			j->serial += (str[i] - 55) * place;
-			break;
-		case 'a':
-		case 'b':
-		case 'c':
-		case 'd':
-		case 'e':
-		case 'f':
-			j->serial += (str[i] - 87) * place;
-			break;
-		}
-		place = place * 0x10;
-	}
-	str = link->prod_id[3];
-	if (!str)
-		goto failed;
-	printk(" version %s\n", str);
-failed:
-	return;
-}
-
-static int ixj_config_check(struct pcmcia_device *p_dev, void *priv_data)
-{
-	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-	p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
-	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-	p_dev->io_lines = 3;
-
-	return pcmcia_request_io(p_dev);
-}
-
-static int ixj_config(struct pcmcia_device * link)
-{
-	IXJ *j;
-	ixj_info_t *info;
-
-	info = link->priv;
-	dev_dbg(&link->dev, "ixj_config\n");
-
-	link->config_flags = CONF_AUTO_SET_IO;
-
-	if (pcmcia_loop_config(link, ixj_config_check, NULL))
-		goto failed;
-
-	if (pcmcia_enable_device(link))
-		goto failed;
-
-	/*
- 	 *	Register the card with the core.
-	 */
-	j = ixj_pcmcia_probe(link->resource[0]->start,
-			     link->resource[0]->start + 0x10);
-
-	info->ndev = 1;
-	ixj_get_serial(link, j);
-	return 0;
-
-failed:
-	ixj_cs_release(link);
-	return -ENODEV;
-}
-
-static void ixj_cs_release(struct pcmcia_device *link)
-{
-	ixj_info_t *info = link->priv;
-	dev_dbg(&link->dev, "ixj_cs_release\n");
-	info->ndev = 0;
-	pcmcia_disable_device(link);
-}
-
-static const struct pcmcia_device_id ixj_ids[] = {
-	PCMCIA_DEVICE_MANF_CARD(0x0257, 0x0600),
-	PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, ixj_ids);
-
-static struct pcmcia_driver ixj_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "ixj_cs",
-	.probe		= ixj_probe,
-	.remove		= ixj_detach,
-	.id_table	= ixj_ids,
-};
-
-static int __init ixj_pcmcia_init(void)
-{
-	return pcmcia_register_driver(&ixj_driver);
-}
-
-static void ixj_pcmcia_exit(void)
-{
-	pcmcia_unregister_driver(&ixj_driver);
-}
-
-module_init(ixj_pcmcia_init);
-module_exit(ixj_pcmcia_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/telephony/phonedev.c b/drivers/staging/telephony/phonedev.c
deleted file mode 100644
index 1dd0b67..0000000
--- a/drivers/staging/telephony/phonedev.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- *            Telephony registration for Linux
- *
- *              (c) Copyright 1999 Red Hat Software 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.
- *
- * Author:      Alan Cox, <alan@lxorguk.ukuu.org.uk>
- *
- * Fixes:       Mar 01 2000 Thomas Sparr, <thomas.l.sparr@telia.com>
- *              phone_register_device now works with unit!=PHONE_UNIT_ANY
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/phonedev.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-
-#include <linux/kmod.h>
-#include <linux/sem.h>
-#include <linux/mutex.h>
-
-#define PHONE_NUM_DEVICES	256
-
-/*
- *    Active devices 
- */
-
-static struct phone_device *phone_device[PHONE_NUM_DEVICES];
-static DEFINE_MUTEX(phone_lock);
-
-/*
- *    Open a phone device.
- */
-
-static int phone_open(struct inode *inode, struct file *file)
-{
-	unsigned int minor = iminor(inode);
-	int err = 0;
-	struct phone_device *p;
-	const struct file_operations *old_fops, *new_fops = NULL;
-
-	if (minor >= PHONE_NUM_DEVICES)
-		return -ENODEV;
-
-	mutex_lock(&phone_lock);
-	p = phone_device[minor];
-	if (p)
-		new_fops = fops_get(p->f_op);
-	if (!new_fops) {
-		mutex_unlock(&phone_lock);
-		request_module("char-major-%d-%d", PHONE_MAJOR, minor);
-		mutex_lock(&phone_lock);
-		p = phone_device[minor];
-		if (p == NULL || (new_fops = fops_get(p->f_op)) == NULL)
-		{
-			err=-ENODEV;
-			goto end;
-		}
-	}
-	old_fops = file->f_op;
-	file->f_op = new_fops;
-	if (p->open)
-		err = p->open(p, file);	/* Tell the device it is open */
-	if (err) {
-		fops_put(file->f_op);
-		file->f_op = fops_get(old_fops);
-	}
-	fops_put(old_fops);
-end:
-	mutex_unlock(&phone_lock);
-	return err;
-}
-
-/*
- *    Telephony For Linux device drivers request registration here.
- */
-
-int phone_register_device(struct phone_device *p, int unit)
-{
-	int base;
-	int end;
-	int i;
-
-	base = 0;
-	end = PHONE_NUM_DEVICES - 1;
-
-	if (unit != PHONE_UNIT_ANY) {
-		base = unit;
-		end = unit + 1;  /* enter the loop at least one time */
-	}
-	
-	mutex_lock(&phone_lock);
-	for (i = base; i < end; i++) {
-		if (phone_device[i] == NULL) {
-			phone_device[i] = p;
-			p->minor = i;
-			mutex_unlock(&phone_lock);
-			return 0;
-		}
-	}
-	mutex_unlock(&phone_lock);
-	return -ENFILE;
-}
-
-/*
- *    Unregister an unused Telephony for linux device
- */
-
-void phone_unregister_device(struct phone_device *pfd)
-{
-	mutex_lock(&phone_lock);
-	if (likely(phone_device[pfd->minor] == pfd))
-		phone_device[pfd->minor] = NULL;
-	mutex_unlock(&phone_lock);
-}
-
-
-static const struct file_operations phone_fops =
-{
-	.owner		= THIS_MODULE,
-	.open		= phone_open,
-	.llseek		= noop_llseek,
-};
-
-/*
- *	Board init functions
- */
- 
-
-/*
- *    Initialise Telephony for linux
- */
-
-static int __init telephony_init(void)
-{
-	printk(KERN_INFO "Linux telephony interface: v1.00\n");
-	if (register_chrdev(PHONE_MAJOR, "telephony", &phone_fops)) {
-		printk("phonedev: unable to get major %d\n", PHONE_MAJOR);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static void __exit telephony_exit(void)
-{
-	unregister_chrdev(PHONE_MAJOR, "telephony");
-}
-
-module_init(telephony_init);
-module_exit(telephony_exit);
-
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(phone_register_device);
-EXPORT_SYMBOL(phone_unregister_device);
diff --git a/drivers/staging/tidspbridge/dynload/dload_internal.h b/drivers/staging/tidspbridge/dynload/dload_internal.h
index 7b77573..b9d079b 100644
--- a/drivers/staging/tidspbridge/dynload/dload_internal.h
+++ b/drivers/staging/tidspbridge/dynload/dload_internal.h
@@ -313,14 +313,14 @@ extern uint32_t dload_reverse_checksum16(void *data, unsigned siz);
 /*
  * exported by reloc.c
  */
-extern void dload_relocate(struct dload_state *dlthis, tgt_au_t * data,
-			   struct reloc_record_t *rp, bool * tramps_generated,
+extern void dload_relocate(struct dload_state *dlthis, tgt_au_t *data,
+			   struct reloc_record_t *rp, bool *tramps_generated,
 			   bool second_pass);
 
-extern rvalue dload_unpack(struct dload_state *dlthis, tgt_au_t * data,
+extern rvalue dload_unpack(struct dload_state *dlthis, tgt_au_t *data,
 			   int fieldsz, int offset, unsigned sgn);
 
-extern int dload_repack(struct dload_state *dlthis, rvalue val, tgt_au_t * data,
+extern int dload_repack(struct dload_state *dlthis, rvalue val, tgt_au_t *data,
 			int fieldsz, int offset, unsigned sgn);
 
 /*
diff --git a/drivers/staging/tidspbridge/dynload/reloc.c b/drivers/staging/tidspbridge/dynload/reloc.c
index 7b28c07..463abdb 100644
--- a/drivers/staging/tidspbridge/dynload/reloc.c
+++ b/drivers/staging/tidspbridge/dynload/reloc.c
@@ -45,7 +45,7 @@ static const char bsssymbol[] = { ".bss" };
  * Effect:
  *	Extracts the specified field and returns it.
  ************************************************************************* */
-rvalue dload_unpack(struct dload_state *dlthis, tgt_au_t * data, int fieldsz,
+rvalue dload_unpack(struct dload_state *dlthis, tgt_au_t *data, int fieldsz,
 		    int offset, unsigned sgn)
 {
 	register rvalue objval;
@@ -98,7 +98,7 @@ rvalue dload_unpack(struct dload_state *dlthis, tgt_au_t * data, int fieldsz,
  ************************************************************************* */
 static const unsigned char ovf_limit[] = { 1, 2, 2 };
 
-int dload_repack(struct dload_state *dlthis, rvalue val, tgt_au_t * data,
+int dload_repack(struct dload_state *dlthis, rvalue val, tgt_au_t *data,
 		 int fieldsz, int offset, unsigned sgn)
 {
 	register urvalue objval, mask;
@@ -161,7 +161,7 @@ static const u8 c60_scale[SCALE_MASK + 1] = {
  * Effect:
  *	Performs the specified relocation operation
  ************************************************************************* */
-void dload_relocate(struct dload_state *dlthis, tgt_au_t * data,
+void dload_relocate(struct dload_state *dlthis, tgt_au_t *data,
 		    struct reloc_record_t *rp, bool *tramps_generated,
 		    bool second_pass)
 {
diff --git a/drivers/staging/tidspbridge/include/dspbridge/host_os.h b/drivers/staging/tidspbridge/include/dspbridge/host_os.h
index 5e2f4d8..7f3a1db 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/host_os.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/host_os.h
@@ -40,7 +40,6 @@
 #include <linux/vmalloc.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
-#include <plat/clock.h>
 #include <linux/clk.h>
 #include <plat/mailbox.h>
 #include <linux/pagemap.h>
diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c
index 701a11a..e6f31d8 100644
--- a/drivers/staging/tidspbridge/rmgr/drv_interface.c
+++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c
@@ -471,7 +471,7 @@ err1:
 	return err;
 }
 
-static int __devinit omap34_xx_bridge_probe(struct platform_device *pdev)
+static int omap34_xx_bridge_probe(struct platform_device *pdev)
 {
 	int err;
 	dev_t dev = 0;
@@ -527,7 +527,7 @@ err1:
 	return err;
 }
 
-static int __devexit omap34_xx_bridge_remove(struct platform_device *pdev)
+static int omap34_xx_bridge_remove(struct platform_device *pdev)
 {
 	dev_t devno;
 	int status = 0;
@@ -606,7 +606,7 @@ static struct platform_driver bridge_driver = {
 		   .name = "omap-dsp",
 		   },
 	.probe = omap34_xx_bridge_probe,
-	.remove = __devexit_p(omap34_xx_bridge_remove),
+	.remove = omap34_xx_bridge_remove,
 #ifdef CONFIG_PM
 	.suspend = bridge_suspend,
 	.resume = bridge_resume,
diff --git a/drivers/staging/tidspbridge/rmgr/node.c b/drivers/staging/tidspbridge/rmgr/node.c
index 294e9b4..737f4a9 100644
--- a/drivers/staging/tidspbridge/rmgr/node.c
+++ b/drivers/staging/tidspbridge/rmgr/node.c
@@ -736,7 +736,7 @@ DBAPI node_alloc_msg_buf(struct node_object *hnode, u32 usize,
 		case 4:
 			break;
 		default:
-			/* alignment value not suportted */
+			/* alignment value not supportted */
 			status = -EPERM;
 			break;
 		}
diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
index c8d79a7..ee36415 100644
--- a/drivers/staging/usbip/stub_dev.c
+++ b/drivers/staging/usbip/stub_dev.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/file.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
 
@@ -203,7 +204,7 @@ static void stub_shutdown_connection(struct usbip_device *ud)
 	 * not touch NULL socket.
 	 */
 	if (ud->tcp_socket) {
-		sock_release(ud->tcp_socket);
+		fput(ud->tcp_socket->file);
 		ud->tcp_socket = NULL;
 	}
 
@@ -432,6 +433,8 @@ static int stub_probe(struct usb_interface *interface,
 		dev_err(&interface->dev, "stub_add_files for %s\n", udev_busid);
 		usb_set_intfdata(interface, NULL);
 		usb_put_intf(interface);
+		usb_put_dev(udev);
+		kthread_stop_put(sdev->ud.eh);
 
 		busid_priv->interf_count = 0;
 		busid_priv->sdev = NULL;
@@ -477,19 +480,17 @@ static void stub_disconnect(struct usb_interface *interface)
 	/* get stub_device */
 	if (!sdev) {
 		dev_err(&interface->dev, "could not get device");
-		/* BUG(); */
 		return;
 	}
 
 	usb_set_intfdata(interface, NULL);
 
 	/*
-	 * NOTE:
-	 * rx/tx threads are invoked for each usb_device.
+	 * NOTE: rx/tx threads are invoked for each usb_device.
 	 */
 	stub_remove_files(&interface->dev);
 
-	/*If usb reset called from event handler*/
+	/* If usb reset is called from event handler */
 	if (busid_priv->sdev->ud.eh == current) {
 		busid_priv->interf_count--;
 		return;
@@ -504,13 +505,13 @@ static void stub_disconnect(struct usb_interface *interface)
 
 	busid_priv->interf_count = 0;
 
-	/* 1. shutdown the current connection */
+	/* shutdown the current connection */
 	shutdown_busid(busid_priv);
 
 	usb_put_dev(sdev->udev);
 	usb_put_intf(interface);
 
-	/* 3. free sdev */
+	/* free sdev */
 	busid_priv->sdev = NULL;
 	stub_device_free(sdev);
 
diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c
index 694cfd7..0572a15 100644
--- a/drivers/staging/usbip/stub_rx.c
+++ b/drivers/staging/usbip/stub_rx.c
@@ -164,7 +164,6 @@ static int tweak_set_configuration_cmd(struct urb *urb)
 		 config, dev_name(&urb->dev->dev));
 
 	return 0;
-	/* return usb_driver_set_configuration(urb->dev, config); */
 }
 
 static int tweak_reset_device_cmd(struct urb *urb)
@@ -480,7 +479,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
 		return;
 	}
 
-	/* set priv->urb->transfer_buffer */
+	/* allocate urb transfer buffer, if needed */
 	if (pdu->u.cmd_submit.transfer_buffer_length > 0) {
 		priv->urb->transfer_buffer =
 			kzalloc(pdu->u.cmd_submit.transfer_buffer_length,
@@ -492,7 +491,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
 		}
 	}
 
-	/* set priv->urb->setup_packet */
+	/* copy urb setup packet */
 	priv->urb->setup_packet = kmemdup(&pdu->u.cmd_submit.setup, 8,
 					  GFP_KERNEL);
 	if (!priv->urb->setup_packet) {
diff --git a/drivers/staging/usbip/stub_tx.c b/drivers/staging/usbip/stub_tx.c
index 023fda3..513961f 100644
--- a/drivers/staging/usbip/stub_tx.c
+++ b/drivers/staging/usbip/stub_tx.c
@@ -166,7 +166,7 @@ static int stub_send_ret_submit(struct stub_device *sdev)
 		int ret;
 		struct urb *urb = priv->urb;
 		struct usbip_header pdu_header;
-		void *iso_buffer = NULL;
+		struct usbip_iso_packet_descriptor *iso_buffer = NULL;
 		struct kvec *iov = NULL;
 		int iovnum = 0;
 
@@ -192,7 +192,6 @@ static int stub_send_ret_submit(struct stub_device *sdev)
 		setup_ret_submit_pdu(&pdu_header, urb);
 		usbip_dbg_stub_tx("setup txdata seqnum: %d urb: %p\n",
 				  pdu_header.base.seqnum, urb);
-		/*usbip_dump_header(pdu_header);*/
 		usbip_header_correct_endian(&pdu_header, 1);
 
 		iov[iovnum].iov_base = &pdu_header;
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
index 57f11f9..75189fe 100644
--- a/drivers/staging/usbip/usbip_common.c
+++ b/drivers/staging/usbip/usbip_common.c
@@ -413,8 +413,10 @@ struct socket *sockfd_to_socket(unsigned int sockfd)
 
 	inode = file->f_dentry->d_inode;
 
-	if (!inode || !S_ISSOCK(inode->i_mode))
+	if (!inode || !S_ISSOCK(inode->i_mode)) {
+		fput(file);
 		return NULL;
+	}
 
 	socket = SOCKET_I(inode);
 
@@ -439,7 +441,6 @@ static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb,
 	 * will be discussed when usbip is ported to other operating systems.
 	 */
 	if (pack) {
-		/* vhci_tx.c */
 		spdu->transfer_flags =
 			tweak_transfer_flags(urb->transfer_flags);
 		spdu->transfer_buffer_length	= urb->transfer_buffer_length;
@@ -447,9 +448,7 @@ static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb,
 		spdu->number_of_packets		= urb->number_of_packets;
 		spdu->interval			= urb->interval;
 	} else  {
-		/* stub_rx.c */
 		urb->transfer_flags         = spdu->transfer_flags;
-
 		urb->transfer_buffer_length = spdu->transfer_buffer_length;
 		urb->start_frame            = spdu->start_frame;
 		urb->number_of_packets      = spdu->number_of_packets;
@@ -463,16 +462,12 @@ static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb,
 	struct usbip_header_ret_submit *rpdu = &pdu->u.ret_submit;
 
 	if (pack) {
-		/* stub_tx.c */
-
 		rpdu->status		= urb->status;
 		rpdu->actual_length	= urb->actual_length;
 		rpdu->start_frame	= urb->start_frame;
 		rpdu->number_of_packets = urb->number_of_packets;
 		rpdu->error_count	= urb->error_count;
 	} else {
-		/* vhci_rx.c */
-
 		urb->status		= rpdu->status;
 		urb->actual_length	= rpdu->actual_length;
 		urb->start_frame	= rpdu->start_frame;
@@ -639,28 +634,26 @@ static void usbip_pack_iso(struct usbip_iso_packet_descriptor *iso,
 }
 
 /* must free buffer */
-void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen)
+struct usbip_iso_packet_descriptor*
+usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen)
 {
-	void *buff;
 	struct usbip_iso_packet_descriptor *iso;
 	int np = urb->number_of_packets;
 	ssize_t size = np * sizeof(*iso);
 	int i;
 
-	buff = kzalloc(size, GFP_KERNEL);
-	if (!buff)
+	iso = kzalloc(size, GFP_KERNEL);
+	if (!iso)
 		return NULL;
 
 	for (i = 0; i < np; i++) {
-		iso = buff + (i * sizeof(*iso));
-
-		usbip_pack_iso(iso, &urb->iso_frame_desc[i], 1);
-		usbip_iso_packet_correct_endian(iso, 1);
+		usbip_pack_iso(&iso[i], &urb->iso_frame_desc[i], 1);
+		usbip_iso_packet_correct_endian(&iso[i], 1);
 	}
 
 	*bufflen = size;
 
-	return buff;
+	return iso;
 }
 EXPORT_SYMBOL_GPL(usbip_alloc_iso_desc_pdu);
 
@@ -680,8 +673,6 @@ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb)
 
 	/* my Bluetooth dongle gets ISO URBs which are np = 0 */
 	if (np == 0) {
-		/* pr_info("iso np == 0\n"); */
-		/* usbip_dump_urb(urb); */
 		return 0;
 	}
 
@@ -703,11 +694,10 @@ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb)
 		return -EPIPE;
 	}
 
+	iso = (struct usbip_iso_packet_descriptor *) buff;
 	for (i = 0; i < np; i++) {
-		iso = buff + (i * sizeof(*iso));
-
-		usbip_iso_packet_correct_endian(iso, 0);
-		usbip_pack_iso(iso, &urb->iso_frame_desc[i], 0);
+		usbip_iso_packet_correct_endian(&iso[i], 0);
+		usbip_pack_iso(&iso[i], &urb->iso_frame_desc[i], 0);
 		total_length += urb->iso_frame_desc[i].actual_length;
 	}
 
@@ -754,7 +744,7 @@ void usbip_pad_iso(struct usbip_device *ud, struct urb *urb)
 	/*
 	 * if actual_length is transfer_buffer_length then no padding is
 	 * present.
-	*/
+	 */
 	if (urb->actual_length == urb->transfer_buffer_length)
 		return;
 
@@ -778,14 +768,12 @@ int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb)
 	int size;
 
 	if (ud->side == USBIP_STUB) {
-		/* stub_rx.c */
 		/* the direction of urb must be OUT. */
 		if (usb_pipein(urb->pipe))
 			return 0;
 
 		size = urb->transfer_buffer_length;
 	} else {
-		/* vhci_rx.c */
 		/* the direction of urb must be IN. */
 		if (usb_pipeout(urb->pipe))
 			return 0;
diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h
index 5d89c0f..7e6c543 100644
--- a/drivers/staging/usbip/usbip_common.h
+++ b/drivers/staging/usbip/usbip_common.h
@@ -320,7 +320,9 @@ void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd,
 		    int pack);
 void usbip_header_correct_endian(struct usbip_header *pdu, int send);
 
-void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen);
+struct usbip_iso_packet_descriptor*
+usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen);
+
 /* some members of urb must be substituted before. */
 int usbip_recv_iso(struct usbip_device *ud, struct urb *urb);
 void usbip_pad_iso(struct usbip_device *ud, struct urb *urb);
diff --git a/drivers/staging/usbip/userspace/src/usbip_detach.c b/drivers/staging/usbip/userspace/src/usbip_detach.c
index 89bf3c1..dac5f06 100644
--- a/drivers/staging/usbip/userspace/src/usbip_detach.c
+++ b/drivers/staging/usbip/userspace/src/usbip_detach.c
@@ -19,6 +19,7 @@
 #include <sysfs/libsysfs.h>
 
 #include <ctype.h>
+#include <limits.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -46,6 +47,7 @@ static int detach_port(char *port)
 {
 	int ret;
 	uint8_t portnum;
+	char path[PATH_MAX+1];
 
 	for (unsigned int i=0; i < strlen(port); i++)
 		if (!isdigit(port[i])) {
@@ -57,6 +59,13 @@ static int detach_port(char *port)
 
 	portnum = atoi(port);
 
+	/* remove the port state file */
+
+	snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", portnum);
+
+	remove(path);
+	rmdir(VHCI_STATE_PATH);
+
 	ret = usbip_vhci_driver_open();
 	if (ret < 0) {
 		err("open vhci_driver");
diff --git a/drivers/staging/usbip/vhci.h b/drivers/staging/usbip/vhci.h
index c66b8b3..5dddc4d 100644
--- a/drivers/staging/usbip/vhci.h
+++ b/drivers/staging/usbip/vhci.h
@@ -99,7 +99,6 @@ extern const struct attribute_group dev_attr_group;
 
 /* vhci_hcd.c */
 void rh_port_connect(int rhport, enum usb_device_speed speed);
-void rh_port_disconnect(int rhport);
 
 /* vhci_rx.c */
 struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum);
diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c
index 620d1be..c3aa219 100644
--- a/drivers/staging/usbip/vhci_hcd.c
+++ b/drivers/staging/usbip/vhci_hcd.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/file.h>
 #include <linux/kernel.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
@@ -140,32 +141,23 @@ void rh_port_connect(int rhport, enum usb_device_speed speed)
 		break;
 	}
 
-	/* spin_lock(&the_controller->vdev[rhport].ud.lock);
-	 * the_controller->vdev[rhport].ud.status = VDEV_CONNECT;
-	 * spin_unlock(&the_controller->vdev[rhport].ud.lock); */
-
 	spin_unlock_irqrestore(&the_controller->lock, flags);
 
 	usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
 }
 
-void rh_port_disconnect(int rhport)
+static void rh_port_disconnect(int rhport)
 {
 	unsigned long flags;
 
 	usbip_dbg_vhci_rh("rh_port_disconnect %d\n", rhport);
 
 	spin_lock_irqsave(&the_controller->lock, flags);
-	/* stop_activity(dum, driver); */
+
 	the_controller->port_status[rhport] &= ~USB_PORT_STAT_CONNECTION;
 	the_controller->port_status[rhport] |=
 					(1 << USB_PORT_FEAT_C_CONNECTION);
 
-	/* not yet complete the disconnection
-	 * spin_lock(&vdev->ud.lock);
-	 * vdev->ud.status = VHC_ST_DISCONNECT;
-	 * spin_unlock(&vdev->ud.lock); */
-
 	spin_unlock_irqrestore(&the_controller->lock, flags);
 	usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
 }
@@ -228,7 +220,6 @@ done:
 	return changed ? retval : 0;
 }
 
-/* See hub_configure in hub.c */
 static inline void hub_descriptor(struct usb_hub_descriptor *desc)
 {
 	memset(desc, 0, sizeof(*desc));
@@ -292,8 +283,6 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			usbip_dbg_vhci_rh(" ClearPortFeature: "
 					  "USB_PORT_FEAT_POWER\n");
 			dum->port_status[rhport] = 0;
-			/* dum->address = 0; */
-			/* dum->hdev = 0; */
 			dum->resuming = 0;
 			break;
 		case USB_PORT_FEAT_C_RESET:
@@ -333,11 +322,11 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			retval = -EPIPE;
 		}
 
-		/* we do no care of resume. */
+		/* we do not care about resume. */
 
 		/* whoever resets or resumes must GetPortStatus to
 		 * complete it!!
-		 *                                   */
+		 */
 		if (dum->resuming && time_after(jiffies, dum->re_timeout)) {
 			dum->port_status[rhport] |=
 				(1 << USB_PORT_FEAT_C_SUSPEND);
@@ -345,11 +334,6 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 				~(1 << USB_PORT_FEAT_SUSPEND);
 			dum->resuming = 0;
 			dum->re_timeout = 0;
-			/* if (dum->driver && dum->driver->resume) {
-			 *	spin_unlock (&dum->lock);
-			 *	dum->driver->resume (&dum->gadget);
-			 *	spin_lock (&dum->lock);
-			 * } */
 		}
 
 		if ((dum->port_status[rhport] & (1 << USB_PORT_FEAT_RESET)) !=
@@ -411,9 +395,6 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 
 	default:
 		pr_err("default: no such request\n");
-		/* dev_dbg (hardware,
-		 *		"hub control req%04x v%04x i%04x l%d\n",
-		 *		typeReq, wValue, wIndex, wLength); */
 
 		/* "protocol stall" on error */
 		retval = -EPIPE;
@@ -456,7 +437,6 @@ static void vhci_tx_urb(struct urb *urb)
 
 	if (!vdev) {
 		pr_err("could not get virtual device");
-		/* BUG(); */
 		return;
 	}
 
@@ -813,7 +793,7 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
 		kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
 	}
 
-	/* kill threads related to this sdev, if v.c. exists */
+	/* kill threads related to this sdev */
 	if (vdev->ud.tcp_rx) {
 		kthread_stop_put(vdev->ud.tcp_rx);
 		vdev->ud.tcp_rx = NULL;
@@ -825,8 +805,8 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
 	pr_info("stop threads\n");
 
 	/* active connection is closed */
-	if (vdev->ud.tcp_socket != NULL) {
-		sock_release(vdev->ud.tcp_socket);
+	if (vdev->ud.tcp_socket) {
+		fput(vdev->ud.tcp_socket->file);
 		vdev->ud.tcp_socket = NULL;
 	}
 	pr_info("release socket\n");
@@ -872,7 +852,10 @@ static void vhci_device_reset(struct usbip_device *ud)
 		usb_put_dev(vdev->udev);
 	vdev->udev = NULL;
 
-	ud->tcp_socket = NULL;
+	if (ud->tcp_socket) {
+		fput(ud->tcp_socket->file);
+		ud->tcp_socket = NULL;
+	}
 	ud->status = VDEV_ST_NULL;
 
 	spin_unlock(&ud->lock);
@@ -928,7 +911,6 @@ static int vhci_start(struct usb_hcd *hcd)
 	spin_lock_init(&vhci->lock);
 
 	hcd->power_budget = 0; /* no limit */
-	hcd->state  = HC_STATE_RUNNING;
 	hcd->uses_new_polling = 1;
 
 	/* vhci_hcd is now ready to be controlled through sysfs */
@@ -976,8 +958,6 @@ static int vhci_bus_suspend(struct usb_hcd *hcd)
 	dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
 
 	spin_lock_irq(&vhci->lock);
-	/* vhci->rh_state = DUMMY_RH_SUSPENDED;
-	 * set_link_state(vhci); */
 	hcd->state = HC_STATE_SUSPENDED;
 	spin_unlock_irq(&vhci->lock);
 
@@ -995,10 +975,6 @@ static int vhci_bus_resume(struct usb_hcd *hcd)
 	if (!HCD_HW_ACCESSIBLE(hcd)) {
 		rc = -ESHUTDOWN;
 	} else {
-		/* vhci->rh_state = DUMMY_RH_RUNNING;
-		 * set_link_state(vhci);
-		 * if (!list_empty(&vhci->urbp_list))
-		 *	mod_timer(&vhci->timer, jiffies); */
 		hcd->state = HC_STATE_RUNNING;
 	}
 	spin_unlock_irq(&vhci->lock);
@@ -1151,7 +1127,7 @@ static int vhci_hcd_resume(struct platform_device *pdev)
 
 static struct platform_driver vhci_driver = {
 	.probe	= vhci_hcd_probe,
-	.remove	= __devexit_p(vhci_hcd_remove),
+	.remove	= vhci_hcd_remove,
 	.suspend = vhci_hcd_suspend,
 	.resume	= vhci_hcd_resume,
 	.driver	= {
@@ -1175,7 +1151,6 @@ static struct platform_device the_pdev = {
 	.name = (char *) driver_name,
 	.id = -1,
 	.dev = {
-		/* .driver = &vhci_driver, */
 		.release = the_pdev_release,
 	},
 };
diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c
index f0eaf04..ba5f1c0 100644
--- a/drivers/staging/usbip/vhci_rx.c
+++ b/drivers/staging/usbip/vhci_rx.c
@@ -167,7 +167,7 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,
 	} else {
 		usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
 
-		/* If unlink is succeed, status is -ECONNRESET */
+		/* If unlink is successful, status is -ECONNRESET */
 		urb->status = pdu->u.ret_unlink.status;
 		pr_info("urb->status %d\n", urb->status);
 
diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c
index 7ce9c2f..c66e9c0 100644
--- a/drivers/staging/usbip/vhci_sysfs.c
+++ b/drivers/staging/usbip/vhci_sysfs.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/kthread.h>
+#include <linux/file.h>
 #include <linux/net.h>
 
 #include "usbip_common.h"
@@ -189,7 +190,8 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
 	if (valid_args(rhport, speed) < 0)
 		return -EINVAL;
 
-	/* check sockfd */
+	/* Extract socket from fd. */
+	/* The correct way to clean this up is to fput(socket->file). */
 	socket = sockfd_to_socket(sockfd);
 	if (!socket)
 		return -EINVAL;
@@ -206,6 +208,8 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
 		spin_unlock(&vdev->ud.lock);
 		spin_unlock(&the_controller->lock);
 
+		fput(socket->file);
+
 		dev_err(dev, "port %d already used\n", rhport);
 		return -EINVAL;
 	}
diff --git a/drivers/staging/usbip/vhci_tx.c b/drivers/staging/usbip/vhci_tx.c
index 9b437e7..b1f0dcd 100644
--- a/drivers/staging/usbip/vhci_tx.c
+++ b/drivers/staging/usbip/vhci_tx.c
@@ -76,7 +76,7 @@ static int vhci_send_cmd_submit(struct vhci_device *vdev)
 		int ret;
 		struct urb *urb = priv->urb;
 		struct usbip_header pdu_header;
-		void *iso_buffer = NULL;
+		struct usbip_iso_packet_descriptor *iso_buffer = NULL;
 
 		txsize = 0;
 		memset(&pdu_header, 0, sizeof(pdu_header));
diff --git a/drivers/staging/vme/devices/vme_pio2.h b/drivers/staging/vme/devices/vme_pio2.h
index 72d9ce0..d5d94c4 100644
--- a/drivers/staging/vme/devices/vme_pio2.h
+++ b/drivers/staging/vme/devices/vme_pio2.h
@@ -243,7 +243,7 @@ struct pio2_card {
 int pio2_cntr_reset(struct pio2_card *);
 
 int pio2_gpio_reset(struct pio2_card *);
-int __devinit pio2_gpio_init(struct pio2_card *);
+int pio2_gpio_init(struct pio2_card *);
 void pio2_gpio_exit(struct pio2_card *);
 
 #endif /* _VME_PIO2_H_ */
diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c
index dad8281..0331178 100644
--- a/drivers/staging/vme/devices/vme_pio2_core.c
+++ b/drivers/staging/vme/devices/vme_pio2_core.c
@@ -42,8 +42,8 @@ static int variant_num;
 static bool loopback;
 
 static int pio2_match(struct vme_dev *);
-static int __devinit pio2_probe(struct vme_dev *);
-static int __devexit pio2_remove(struct vme_dev *);
+static int pio2_probe(struct vme_dev *);
+static int pio2_remove(struct vme_dev *);
 
 static int pio2_get_led(struct pio2_card *card)
 {
@@ -156,7 +156,7 @@ static struct vme_driver pio2_driver = {
 	.name = driver_name,
 	.match = pio2_match,
 	.probe = pio2_probe,
-	.remove = __devexit_p(pio2_remove),
+	.remove = pio2_remove,
 };
 
 
@@ -222,7 +222,7 @@ static int pio2_match(struct vme_dev *vdev)
 	return 1;
 }
 
-static int __devinit pio2_probe(struct vme_dev *vdev)
+static int pio2_probe(struct vme_dev *vdev)
 {
 	struct pio2_card *card;
 	int retval;
@@ -455,7 +455,7 @@ err_struct:
 	return retval;
 }
 
-static int __devexit pio2_remove(struct vme_dev *vdev)
+static int pio2_remove(struct vme_dev *vdev)
 {
 	int vec;
 	int i;
diff --git a/drivers/staging/vme/devices/vme_pio2_gpio.c b/drivers/staging/vme/devices/vme_pio2_gpio.c
index ad76a47..69d8805 100644
--- a/drivers/staging/vme/devices/vme_pio2_gpio.c
+++ b/drivers/staging/vme/devices/vme_pio2_gpio.c
@@ -186,7 +186,7 @@ int pio2_gpio_reset(struct pio2_card *card)
 	return 0;
 }
 
-int __devinit pio2_gpio_init(struct pio2_card *card)
+int pio2_gpio_init(struct pio2_card *card)
 {
 	int retval = 0;
 	char *label;
diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c
index c3f94f3..4ef852c 100644
--- a/drivers/staging/vme/devices/vme_user.c
+++ b/drivers/staging/vme/devices/vme_user.c
@@ -15,6 +15,8 @@
  * option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/cdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
@@ -135,8 +137,8 @@ static loff_t vme_user_llseek(struct file *, loff_t, int);
 static long vme_user_unlocked_ioctl(struct file *, unsigned int, unsigned long);
 
 static int vme_user_match(struct vme_dev *);
-static int __devinit vme_user_probe(struct vme_dev *);
-static int __devexit vme_user_remove(struct vme_dev *);
+static int vme_user_probe(struct vme_dev *);
+static int vme_user_remove(struct vme_dev *);
 
 static const struct file_operations vme_user_fops = {
 	.open = vme_user_open,
@@ -170,7 +172,7 @@ static int vme_user_open(struct inode *inode, struct file *file)
 	mutex_lock(&image[minor].mutex);
 	/* Allow device to be opened if a resource is needed and allocated. */
 	if (minor < CONTROL_MINOR && image[minor].resource == NULL) {
-		printk(KERN_ERR "No resources allocated for device\n");
+		pr_err("No resources allocated for device\n");
 		err = -EINVAL;
 		goto err_res;
 	}
@@ -225,13 +227,13 @@ static ssize_t resource_to_user(int minor, char __user *buf, size_t count,
 			(unsigned long)copied);
 		if (retval != 0) {
 			copied = (copied - retval);
-			printk(KERN_INFO "User copy failed\n");
+			pr_info("User copy failed\n");
 			return -EINVAL;
 		}
 
 	} else {
 		/* XXX Need to write this */
-		printk(KERN_INFO "Currently don't support large transfers\n");
+		pr_info("Currently don't support large transfers\n");
 		/* Map in pages from userspace */
 
 		/* Call vme_master_read to do the transfer */
@@ -265,7 +267,7 @@ static ssize_t resource_from_user(unsigned int minor, const char __user *buf,
 			image[minor].kern_buf, copied, *ppos);
 	} else {
 		/* XXX Need to write this */
-		printk(KERN_INFO "Currently don't support large transfers\n");
+		pr_info("Currently don't support large transfers\n");
 		/* Map in pages from userspace */
 
 		/* Call vme_master_write to do the transfer */
@@ -286,7 +288,7 @@ static ssize_t buffer_to_user(unsigned int minor, char __user *buf,
 	retval = __copy_to_user(buf, image_ptr, (unsigned long)count);
 	if (retval != 0) {
 		retval = (count - retval);
-		printk(KERN_WARNING "Partial copy to userspace\n");
+		pr_warn("Partial copy to userspace\n");
 	} else
 		retval = count;
 
@@ -305,7 +307,7 @@ static ssize_t buffer_from_user(unsigned int minor, const char __user *buf,
 	retval = __copy_from_user(image_ptr, buf, (unsigned long)count);
 	if (retval != 0) {
 		retval = (count - retval);
-		printk(KERN_WARNING "Partial copy to userspace\n");
+		pr_warn("Partial copy to userspace\n");
 	} else
 		retval = count;
 
@@ -476,7 +478,7 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
 			copied = copy_from_user(&irq_req, argp,
 						sizeof(struct vme_irq_id));
 			if (copied != 0) {
-				printk(KERN_WARNING "Partial copy from userspace\n");
+				pr_warn("Partial copy from userspace\n");
 				return -EFAULT;
 			}
 
@@ -503,8 +505,7 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
 			copied = copy_to_user(argp, &master,
 				sizeof(struct vme_master));
 			if (copied != 0) {
-				printk(KERN_WARNING "Partial copy to "
-					"userspace\n");
+				pr_warn("Partial copy to userspace\n");
 				return -EFAULT;
 			}
 
@@ -515,8 +516,7 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
 
 			copied = copy_from_user(&master, argp, sizeof(master));
 			if (copied != 0) {
-				printk(KERN_WARNING "Partial copy from "
-					"userspace\n");
+				pr_warn("Partial copy from userspace\n");
 				return -EFAULT;
 			}
 
@@ -546,8 +546,7 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
 			copied = copy_to_user(argp, &slave,
 				sizeof(struct vme_slave));
 			if (copied != 0) {
-				printk(KERN_WARNING "Partial copy to "
-					"userspace\n");
+				pr_warn("Partial copy to userspace\n");
 				return -EFAULT;
 			}
 
@@ -558,8 +557,7 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
 
 			copied = copy_from_user(&slave, argp, sizeof(slave));
 			if (copied != 0) {
-				printk(KERN_WARNING "Partial copy from "
-					"userspace\n");
+				pr_warn("Partial copy from userspace\n");
 				return -EFAULT;
 			}
 
@@ -599,8 +597,8 @@ static void buf_unalloc(int num)
 {
 	if (image[num].kern_buf) {
 #ifdef VME_DEBUG
-		printk(KERN_DEBUG "UniverseII:Releasing buffer at %p\n",
-			image[num].pci_buf);
+		pr_debug("UniverseII:Releasing buffer at %p\n",
+			 image[num].pci_buf);
 #endif
 
 		vme_free_consistent(image[num].resource, image[num].size_buf,
@@ -612,7 +610,7 @@ static void buf_unalloc(int num)
 
 #ifdef VME_DEBUG
 	} else {
-		printk(KERN_DEBUG "UniverseII: Buffer not allocated\n");
+		pr_debug("UniverseII: Buffer not allocated\n");
 #endif
 	}
 }
@@ -621,7 +619,7 @@ static struct vme_driver vme_user_driver = {
 	.name = driver_name,
 	.match = vme_user_match,
 	.probe = vme_user_probe,
-	.remove = __devexit_p(vme_user_remove),
+	.remove = vme_user_remove,
 };
 
 
@@ -629,11 +627,10 @@ static int __init vme_user_init(void)
 {
 	int retval = 0;
 
-	printk(KERN_INFO "VME User Space Access Driver\n");
+	pr_info("VME User Space Access Driver\n");
 
 	if (bus_num == 0) {
-		printk(KERN_ERR "%s: No cards, skipping registration\n",
-			driver_name);
+		pr_err("No cards, skipping registration\n");
 		retval = -ENODEV;
 		goto err_nocard;
 	}
@@ -642,8 +639,8 @@ static int __init vme_user_init(void)
 	 * in future revisions if that ever becomes necessary.
 	 */
 	if (bus_num > VME_USER_BUS_MAX) {
-		printk(KERN_ERR "%s: Driver only able to handle %d buses\n",
-			driver_name, VME_USER_BUS_MAX);
+		pr_err("Driver only able to handle %d buses\n",
+		       VME_USER_BUS_MAX);
 		bus_num = VME_USER_BUS_MAX;
 	}
 
@@ -676,15 +673,14 @@ static int vme_user_match(struct vme_dev *vdev)
  * as practical. We will therefore reserve the buffers and request the images
  * here so that we don't have to do it later.
  */
-static int __devinit vme_user_probe(struct vme_dev *vdev)
+static int vme_user_probe(struct vme_dev *vdev)
 {
 	int i, err;
 	char name[12];
 
 	/* Save pointer to the bridge device */
 	if (vme_user_bridge != NULL) {
-		printk(KERN_ERR "%s: Driver can only be loaded for 1 device\n",
-			driver_name);
+		dev_err(&vdev->dev, "Driver can only be loaded for 1 device\n");
 		err = -EINVAL;
 		goto err_dev;
 	}
@@ -707,8 +703,8 @@ static int __devinit vme_user_probe(struct vme_dev *vdev)
 	err = register_chrdev_region(MKDEV(VME_MAJOR, 0), VME_DEVS,
 		driver_name);
 	if (err) {
-		printk(KERN_WARNING "%s: Error getting Major Number %d for "
-		"driver.\n", driver_name, VME_MAJOR);
+		dev_warn(&vdev->dev, "Error getting Major Number %d for driver.\n",
+			 VME_MAJOR);
 		goto err_region;
 	}
 
@@ -718,7 +714,7 @@ static int __devinit vme_user_probe(struct vme_dev *vdev)
 	vme_user_cdev->owner = THIS_MODULE;
 	err = cdev_add(vme_user_cdev, MKDEV(VME_MAJOR, 0), VME_DEVS);
 	if (err) {
-		printk(KERN_WARNING "%s: cdev_all failed\n", driver_name);
+		dev_warn(&vdev->dev, "cdev_all failed\n");
 		goto err_char;
 	}
 
@@ -732,16 +728,16 @@ static int __devinit vme_user_probe(struct vme_dev *vdev)
 		image[i].resource = vme_slave_request(vme_user_bridge,
 			VME_A24, VME_SCT);
 		if (image[i].resource == NULL) {
-			printk(KERN_WARNING "Unable to allocate slave "
-				"resource\n");
+			dev_warn(&vdev->dev,
+				 "Unable to allocate slave resource\n");
 			goto err_slave;
 		}
 		image[i].size_buf = PCI_BUF_SIZE;
 		image[i].kern_buf = vme_alloc_consistent(image[i].resource,
 			image[i].size_buf, &image[i].pci_buf);
 		if (image[i].kern_buf == NULL) {
-			printk(KERN_WARNING "Unable to allocate memory for "
-				"buffer\n");
+			dev_warn(&vdev->dev,
+				 "Unable to allocate memory for buffer\n");
 			image[i].pci_buf = 0;
 			vme_slave_free(image[i].resource);
 			err = -ENOMEM;
@@ -758,15 +754,15 @@ static int __devinit vme_user_probe(struct vme_dev *vdev)
 		image[i].resource = vme_master_request(vme_user_bridge,
 			VME_A32, VME_SCT, VME_D32);
 		if (image[i].resource == NULL) {
-			printk(KERN_WARNING "Unable to allocate master "
-				"resource\n");
+			dev_warn(&vdev->dev,
+				 "Unable to allocate master resource\n");
 			goto err_master;
 		}
 		image[i].size_buf = PCI_BUF_SIZE;
 		image[i].kern_buf = kmalloc(image[i].size_buf, GFP_KERNEL);
 		if (image[i].kern_buf == NULL) {
-			printk(KERN_WARNING "Unable to allocate memory for "
-				"master window buffers\n");
+			dev_warn(&vdev->dev,
+				 "Unable to allocate memory for master window buffers\n");
 			err = -ENOMEM;
 			goto err_master_buf;
 		}
@@ -775,7 +771,7 @@ static int __devinit vme_user_probe(struct vme_dev *vdev)
 	/* Create sysfs entries - on udev systems this creates the dev files */
 	vme_user_sysfs_class = class_create(THIS_MODULE, driver_name);
 	if (IS_ERR(vme_user_sysfs_class)) {
-		printk(KERN_ERR "Error creating vme_user class.\n");
+		dev_err(&vdev->dev, "Error creating vme_user class.\n");
 		err = PTR_ERR(vme_user_sysfs_class);
 		goto err_class;
 	}
@@ -803,8 +799,7 @@ static int __devinit vme_user_probe(struct vme_dev *vdev)
 		image[i].device = device_create(vme_user_sysfs_class, NULL,
 					MKDEV(VME_MAJOR, i), NULL, name, num);
 		if (IS_ERR(image[i].device)) {
-			printk(KERN_INFO "%s: Error creating sysfs device\n",
-				driver_name);
+			dev_info(&vdev->dev, "Error creating sysfs device\n");
 			err = PTR_ERR(image[i].device);
 			goto err_sysfs;
 		}
@@ -851,7 +846,7 @@ err_dev:
 	return err;
 }
 
-static int __devexit vme_user_remove(struct vme_dev *dev)
+static int vme_user_remove(struct vme_dev *dev)
 {
 	int i;
 
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index 9e3b3f2b..453c83d 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -356,7 +356,7 @@ static char* get_chip_name(int chip_id)
 	return chip_info_table[i].name;
 }
 
-static void __devexit vt6655_remove(struct pci_dev *pcid)
+static void vt6655_remove(struct pci_dev *pcid)
 {
 	PSDevice pDevice = pci_get_drvdata(pcid);
 
@@ -902,7 +902,7 @@ static const struct net_device_ops device_netdev_ops = {
 	.ndo_set_rx_mode	= device_set_multi,
 };
 
-static int __devinit
+static int
 vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent)
 {
     static bool bFirst = true;
@@ -1099,7 +1099,7 @@ static void device_print_info(PSDevice pDevice)
 
 }
 
-static void __devinit vt6655_init_info(struct pci_dev* pcid, PSDevice* ppDevice,
+static void vt6655_init_info(struct pci_dev* pcid, PSDevice* ppDevice,
     PCHIP_INFO pChip_info) {
 
     PSDevice p;
diff --git a/drivers/staging/vt6655/hostap.c b/drivers/staging/vt6655/hostap.c
index 67b1b88..5f13890 100644
--- a/drivers/staging/vt6655/hostap.c
+++ b/drivers/staging/vt6655/hostap.c
@@ -596,9 +596,9 @@ static int hostap_set_encryption(PSDevice pDevice,
 
 	if (param->u.crypt.seq) {
 	    memcpy(&abySeq, param->u.crypt.seq, 8);
-		for (ii = 0 ; ii < 8 ; ii++) {
-	         KeyRSC |= (abySeq[ii] << (ii * 8));
-		}
+		for (ii = 0 ; ii < 8 ; ii++)
+			KeyRSC |= (unsigned long)abySeq[ii] << (ii * 8);
+
 		dwKeyIndex |= 1 << 29;
 		pMgmt->sNodeDBTable[iNodeIndex].KeyRSC = KeyRSC;
 	}
diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c
index 4972e57..875ee44 100644
--- a/drivers/staging/vt6655/rxtx.c
+++ b/drivers/staging/vt6655/rxtx.c
@@ -242,7 +242,7 @@ s_vFillTxKey (
         }
         // Append IV after Mac Header
         *pdwIV &= WEP_IV_MASK;//00000000 11111111 11111111 11111111
-        *pdwIV |= (byKeyIndex << 30);
+        *pdwIV |= (unsigned long)byKeyIndex << 30;
         *pdwIV = cpu_to_le32(*pdwIV);
         pDevice->dwIVCounter++;
         if (pDevice->dwIVCounter > WEP_IV_MASK) {
diff --git a/drivers/staging/vt6655/wcmd.c b/drivers/staging/vt6655/wcmd.c
index 94bd1fc..6d0b87a 100644
--- a/drivers/staging/vt6655/wcmd.c
+++ b/drivers/staging/vt6655/wcmd.c
@@ -412,6 +412,7 @@ vCommandTimer (
 		if (!is_channel_valid(pMgmt->uScanChannel)) {
                     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Invalid channel pMgmt->uScanChannel = %d \n",pMgmt->uScanChannel);
                     s_bCommandComplete(pDevice);
+                    spin_unlock_irq(&pDevice->lock);
                     return;
                 }
 //printk("chester-pMgmt->uScanChannel=%d,pDevice->byMaxChannel=%d\n",pMgmt->uScanChannel,pDevice->byMaxChannel);
diff --git a/drivers/staging/vt6656/80211mgr.c b/drivers/staging/vt6656/80211mgr.c
index 39f9842..e6ced95 100644
--- a/drivers/staging/vt6656/80211mgr.c
+++ b/drivers/staging/vt6656/80211mgr.c
@@ -52,11 +52,11 @@
  *
  */
 
+#include "device.h"
 #include "tmacro.h"
 #include "tether.h"
 #include "80211mgr.h"
 #include "80211hdr.h"
-#include "device.h"
 #include "wpa.h"
 
 /*---------------------  Static Definitions -------------------------*/
diff --git a/drivers/staging/vt6656/Makefile b/drivers/staging/vt6656/Makefile
index 41ed06b..c998547 100644
--- a/drivers/staging/vt6656/Makefile
+++ b/drivers/staging/vt6656/Makefile
@@ -20,7 +20,6 @@ vt6656_stage-y +=	main_usb.o \
 			rc4.o \
 			tether.o \
 			tcrc.o \
-			ioctl.o \
 			hostap.o \
 			wpa.o \
 			key.o \
diff --git a/drivers/staging/vt6656/bssdb.c b/drivers/staging/vt6656/bssdb.c
index 2ac066d..6a13941 100644
--- a/drivers/staging/vt6656/bssdb.c
+++ b/drivers/staging/vt6656/bssdb.c
@@ -882,7 +882,6 @@ void BSSvSecondCallBack(void *hDeviceContext)
     unsigned int            uSleepySTACnt = 0;
     unsigned int            uNonShortSlotSTACnt = 0;
     unsigned int            uLongPreambleSTACnt = 0;
-    viawget_wpa_header *wpahdr;
 
     spin_lock_irq(&pDevice->lock);
 
@@ -913,7 +912,6 @@ if(pDevice->byReAssocCount > 0) {
    if((pDevice->byReAssocCount > 10) && (pDevice->bLinkPass != TRUE)) {  //10 sec timeout
                      printk("Re-association timeout!!!\n");
 		   pDevice->byReAssocCount = 0;
-                     #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
                     // if(pDevice->bWPASuppWextEnabled == TRUE)
                         {
                   	union iwreq_data  wrqu;
@@ -922,20 +920,11 @@ if(pDevice->byReAssocCount > 0) {
                   	PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated)\n");
                   	wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
                        }
-                    #endif
      }
    else if(pDevice->bLinkPass == TRUE)
    	pDevice->byReAssocCount = 0;
 }
 
-if((pMgmt->eCurrState!=WMAC_STATE_ASSOC) &&
-     (pMgmt->eLastState==WMAC_STATE_ASSOC))
-{
-  union iwreq_data      wrqu;
-  memset(&wrqu, 0, sizeof(wrqu));
-  wrqu.data.flags = RT_DISCONNECTED_EVENT_FLAG;
-  wireless_send_event(pDevice->dev, IWEVCUSTOM, &wrqu, NULL);
-}
  pMgmt->eLastState = pMgmt->eCurrState ;
 
    s_uCalculateLinkQual((void *)pDevice);
@@ -1102,21 +1091,6 @@ if((pMgmt->eCurrState!=WMAC_STATE_ASSOC) &&
 
                 DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "Lost AP beacon [%d] sec, disconnected !\n", pMgmt->sNodeDBTable[0].uInActiveCount);
 		/* let wpa supplicant know AP may disconnect */
-        if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) {
-             wpahdr = (viawget_wpa_header *)pDevice->skb->data;
-             wpahdr->type = VIAWGET_DISASSOC_MSG;
-             wpahdr->resp_ie_len = 0;
-             wpahdr->req_ie_len = 0;
-             skb_put(pDevice->skb, sizeof(viawget_wpa_header));
-             pDevice->skb->dev = pDevice->wpadev;
-	     skb_reset_mac_header(pDevice->skb);
-             pDevice->skb->pkt_type = PACKET_HOST;
-             pDevice->skb->protocol = htons(ETH_P_802_2);
-             memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
-             netif_rx(pDevice->skb);
-             pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-         }
-   #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
       {
 	union iwreq_data  wrqu;
 	memset(&wrqu, 0, sizeof (wrqu));
@@ -1124,7 +1098,6 @@ if((pMgmt->eCurrState!=WMAC_STATE_ASSOC) &&
 	PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated)\n");
 	wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
      }
-  #endif
             }
         }
         else if (pItemSSID->len != 0) {
@@ -1144,20 +1117,6 @@ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "bIsRoaming %d, !\n", pDevice->bIsRoaming );
                 pDevice->uAutoReConnectTime = 0;
                 pDevice->uIsroamingTime = 0;
                 pDevice->bRoaming = FALSE;
-
-             wpahdr = (viawget_wpa_header *)pDevice->skb->data;
-             wpahdr->type = VIAWGET_CCKM_ROAM_MSG;
-             wpahdr->resp_ie_len = 0;
-             wpahdr->req_ie_len = 0;
-             skb_put(pDevice->skb, sizeof(viawget_wpa_header));
-             pDevice->skb->dev = pDevice->wpadev;
-	     skb_reset_mac_header(pDevice->skb);
-             pDevice->skb->pkt_type = PACKET_HOST;
-             pDevice->skb->protocol = htons(ETH_P_802_2);
-             memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
-             netif_rx(pDevice->skb);
-            pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-
           }
       else if ((pDevice->bRoaming == FALSE)&&(pDevice->bIsRoaming == TRUE)) {
                             pDevice->uIsroamingTime++;
@@ -1169,11 +1128,9 @@ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "bIsRoaming %d, !\n", pDevice->bIsRoaming );
 else {
             if (pDevice->uAutoReConnectTime < 10) {
                 pDevice->uAutoReConnectTime++;
-               #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
                 //network manager support need not do Roaming scan???
                 if(pDevice->bWPASuppWextEnabled ==TRUE)
 		 pDevice->uAutoReConnectTime = 0;
-	     #endif
             }
             else {
 	    //mike use old encryption status for wpa reauthen
diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h
index b68b2ec..5007e98 100644
--- a/drivers/staging/vt6656/desc.h
+++ b/drivers/staging/vt6656/desc.h
@@ -298,7 +298,7 @@ typedef const SCTS_FB *PCSCTS_FB;
 // Tx FIFO header
 //
 typedef struct tagSTxBufHead {
-    DWORD   adwTxKey[4];
+	u32 adwTxKey[4];
     WORD    wFIFOCtl;
     WORD    wTimeStamp;
     WORD    wFragCtl;
@@ -376,24 +376,24 @@ typedef const STxDataHead_a_FB *PCSTxDataHead_a_FB;
 // MICHDR data header
 //
 typedef struct tagSMICHDRHead {
-    DWORD   adwHDR0[4];
-    DWORD   adwHDR1[4];
-    DWORD   adwHDR2[4];
+	u32 adwHDR0[4];
+	u32 adwHDR1[4];
+	u32 adwHDR2[4];
 } __attribute__ ((__packed__))
 SMICHDRHead, *PSMICHDRHead;
 
 typedef const SMICHDRHead *PCSMICHDRHead;
 
 typedef struct tagSBEACONCtl {
-    DWORD   BufReady : 1;
-    DWORD   TSF : 15;
-    DWORD   BufLen : 11;
-    DWORD   Reserved : 5;
+	u32 BufReady:1;
+	u32 TSF:15;
+	u32 BufLen:11;
+	u32 Reserved:5;
 } __attribute__ ((__packed__))
 SBEACONCtl;
 
 typedef struct tagSSecretKey {
-    DWORD   dwLowDword;
+	u32 dwLowDword;
     BYTE    byHighByte;
 } __attribute__ ((__packed__))
 SSecretKey;
@@ -402,11 +402,11 @@ typedef struct tagSKeyEntry {
     BYTE  abyAddrHi[2];
     WORD  wKCTL;
     BYTE  abyAddrLo[4];
-    DWORD dwKey0[4];
-    DWORD dwKey1[4];
-    DWORD dwKey2[4];
-    DWORD dwKey3[4];
-    DWORD dwKey4[4];
+	u32 dwKey0[4];
+	u32 dwKey1[4];
+	u32 dwKey2[4];
+	u32 dwKey3[4];
+	u32 dwKey4[4];
 } __attribute__ ((__packed__))
 SKeyEntry;
 
diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h
index 6370d10..25bf03a 100644
--- a/drivers/staging/vt6656/device.h
+++ b/drivers/staging/vt6656/device.h
@@ -30,47 +30,28 @@
 #define __DEVICE_H__
 
 #include <linux/module.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
 #include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
 #include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/string.h>
-#include <linux/wait.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+#include <linux/suspend.h>
 #include <linux/if_arp.h>
-#include <linux/sched.h>
-#include <linux/if.h>
-#include <linux/rtnetlink.h>//James
-#include <linux/proc_fs.h>
-#include <linux/inetdevice.h>
-#include <linux/reboot.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <net/cfg80211.h>
+#include <linux/timer.h>
 #include <linux/usb.h>
-#include <linux/signal.h>
-#include <linux/firmware.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
+
+
 #ifdef SIOCETHTOOL
 #define DEVICE_ETHTOOL_IOCTL_SUPPORT
 #include <linux/ethtool.h>
 #else
 #undef DEVICE_ETHTOOL_IOCTL_SUPPORT
 #endif
-/* Include Wireless Extension definition and check version - Jean II */
-#include <linux/wireless.h>
-#include <net/iw_handler.h>	// New driver API
-
-#ifndef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-#define WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-#endif
 
 //please copy below macro to driver_event.c for API
 #define RT_INSMOD_EVENT_FLAG                             0x0101
@@ -418,7 +399,6 @@ typedef struct __device_info {
     struct net_device*          dev;
     struct net_device_stats     stats;
 
-    const struct firmware	*firmware;
 
     OPTIONS                     sOpts;
 
@@ -734,7 +714,6 @@ typedef struct __device_info {
     BYTE                    byKeyIndex;
 
     BOOL                    bAES;
-    BYTE                    byCntMeasure;
 
     unsigned int                    uKeyLength;
     BYTE                    abyKey[WLAN_WEP232_KEYLEN];
@@ -814,16 +793,13 @@ typedef struct __device_info {
     //WPA supplicant daemon
 	struct net_device       *wpadev;
 	BOOL                    bWPADEVUp;
-    struct sk_buff          *skb;
     //--
 
-#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
         BOOL                 bwextstep0;
         BOOL                 bwextstep1;
         BOOL                 bwextstep2;
         BOOL                 bwextstep3;
         BOOL                 bWPASuppWextEnabled;
-#endif
 
 #ifdef HOSTAP
     // user space daemon: hostapd, is used for HOSTAP
diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c
index 28edf9e..e94f6a1 100644
--- a/drivers/staging/vt6656/dpc.c
+++ b/drivers/staging/vt6656/dpc.c
@@ -332,7 +332,7 @@ RXbBulkInProcessData (
     PBYTE           pbyFrame;
     BOOL            bDeFragRx = FALSE;
     unsigned int            cbHeaderOffset;
-    unsigned int            FrameSize;
+	u32 FrameSize;
     WORD            wEtherType = 0;
     signed int             iSANodeIndex = -1;
     signed int             iDANodeIndex = -1;
@@ -351,7 +351,7 @@ RXbBulkInProcessData (
     /* signed long ldBm = 0; */
     BOOL            bIsWEP = FALSE;
     BOOL            bExtIV = FALSE;
-    DWORD           dwWbkStatus;
+	u32 dwWbkStatus;
     PRCB            pRCBIndicate = pRCB;
     PBYTE           pbyDAddress;
     PWORD           pwPLCP_Length;
@@ -366,15 +366,15 @@ RXbBulkInProcessData (
 
     skb = pRCB->skb;
 
-    //[31:16]RcvByteCount ( not include 4-byte Status )
-    dwWbkStatus =  *( (PDWORD)(skb->data) );
-    FrameSize = (unsigned int)(dwWbkStatus >> 16);
-    FrameSize += 4;
+	/* [31:16]RcvByteCount ( not include 4-byte Status ) */
+	dwWbkStatus = *((u32 *)(skb->data));
+	FrameSize = dwWbkStatus >> 16;
+	FrameSize += 4;
 
-    if (BytesToIndicate != FrameSize) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---------- WRONG Length 1 \n");
-        return FALSE;
-    }
+	if (BytesToIndicate != FrameSize) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"------- WRONG Length 1\n");
+		return FALSE;
+	}
 
     if ((BytesToIndicate > 2372) || (BytesToIndicate <= 40)) {
         // Frame Size error drop this packet.
@@ -617,7 +617,7 @@ RXbBulkInProcessData (
                 //Discard beacon packet which channel is 0
                 if ( (WLAN_GET_FC_FSTYPE((pRxPacket->p80211Header->sA3.wFrameCtl)) == WLAN_FSTYPE_BEACON) ||
                      (WLAN_GET_FC_FSTYPE((pRxPacket->p80211Header->sA3.wFrameCtl)) == WLAN_FSTYPE_PROBERESP) ) {
-                    return TRUE;
+			return FALSE;
                 }
             }
             pRxPacket->byRxChannel = (*pbyRxSts) >> 2;
@@ -818,7 +818,6 @@ RXbBulkInProcessData (
             DWORD           dwMICKey0 = 0, dwMICKey1 = 0;
             DWORD           dwLocalMIC_L = 0;
             DWORD           dwLocalMIC_R = 0;
-            viawget_wpa_header *wpahdr;
 
 
             if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
@@ -864,7 +863,6 @@ RXbBulkInProcessData (
                             pDevice->dev->name);
                     }
                 }
-       #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 				//send event to wpa_supplicant
 				//if(pDevice->bWPASuppWextEnabled == TRUE)
 				{
@@ -889,31 +887,6 @@ RXbBulkInProcessData (
 					wireless_send_event(pDevice->dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);
 
 				}
-         #endif
-
-
-                if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) {
-                     wpahdr = (viawget_wpa_header *)pDevice->skb->data;
-                     if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
-                         (pMgmt->eCurrState == WMAC_STATE_ASSOC) &&
-                         (*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) == 0) {
-                         //s802_11_Status.Flags = NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR;
-                         wpahdr->type = VIAWGET_PTK_MIC_MSG;
-                     } else {
-                         //s802_11_Status.Flags = NDIS_802_11_AUTH_REQUEST_GROUP_ERROR;
-                         wpahdr->type = VIAWGET_GTK_MIC_MSG;
-                     }
-                     wpahdr->resp_ie_len = 0;
-                     wpahdr->req_ie_len = 0;
-                     skb_put(pDevice->skb, sizeof(viawget_wpa_header));
-                     pDevice->skb->dev = pDevice->wpadev;
-		     skb_reset_mac_header(pDevice->skb);
-                     pDevice->skb->pkt_type = PACKET_HOST;
-                     pDevice->skb->protocol = htons(ETH_P_802_2);
-                     memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
-                     netif_rx(pDevice->skb);
-                     pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-                 }
 
                 return FALSE;
 
@@ -1217,7 +1190,7 @@ static BOOL s_bHandleRxEncryption (
     if (byDecMode == KEY_CTL_WEP) {
         // handle WEP
         if ((pDevice->byLocalID <= REV_ID_VT3253_A1) ||
-            (((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == TRUE)) {
+		(((PSKeyTable)(&pKey->pvKeyTable))->bSoftWEP == TRUE)) {
             // Software WEP
             // 1. 3253A
             // 2. WEP 256
@@ -1238,7 +1211,7 @@ static BOOL s_bHandleRxEncryption (
 
         PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc
         *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4));
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16);
         if (byDecMode == KEY_CTL_TKIP) {
             *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV));
         } else {
@@ -1324,9 +1297,9 @@ static BOOL s_bHostWepRxEncryption (
 
     if (byDecMode == KEY_CTL_WEP) {
         // handle WEP
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"byDecMode == KEY_CTL_WEP \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"byDecMode == KEY_CTL_WEP\n");
         if ((pDevice->byLocalID <= REV_ID_VT3253_A1) ||
-            (((PSKeyTable)(pKey->pvKeyTable))->bSoftWEP == TRUE) ||
+		(((PSKeyTable)(&pKey->pvKeyTable))->bSoftWEP == TRUE) ||
             (bOnFly == FALSE)) {
             // Software WEP
             // 1. 3253A
@@ -1349,7 +1322,7 @@ static BOOL s_bHostWepRxEncryption (
 
         PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc
         *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4));
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16);
 
         if (byDecMode == KEY_CTL_TKIP) {
             *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV));
@@ -1534,6 +1507,11 @@ RXvFreeRCB(
     ASSERT(!pRCB->Ref);     // should be 0
     ASSERT(pRCB->pDevice);  // shouldn't be NULL
 
+	if (bReAllocSkb == FALSE) {
+		kfree_skb(pRCB->skb);
+		bReAllocSkb = TRUE;
+	}
+
     if (bReAllocSkb == TRUE) {
         pRCB->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
         // todo error handling
diff --git a/drivers/staging/vt6656/firmware.c b/drivers/staging/vt6656/firmware.c
index 8c8126a..8831ea0 100644
--- a/drivers/staging/vt6656/firmware.c
+++ b/drivers/staging/vt6656/firmware.c
@@ -61,28 +61,24 @@ FIRMWAREbDownload(
      PSDevice pDevice
     )
 {
+	struct device *dev = &pDevice->usb->dev;
 	const struct firmware *fw;
 	int NdisStatus;
 	void *pBuffer = NULL;
 	BOOL result = FALSE;
 	u16 wLength;
-	int ii;
+	int ii, rc;
+
 
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Download firmware\n");
 	spin_unlock_irq(&pDevice->lock);
 
-	if (!pDevice->firmware) {
-		struct device *dev = &pDevice->usb->dev;
-		int rc;
-
-		rc = request_firmware(&pDevice->firmware, FIRMWARE_NAME, dev);
-		if (rc) {
-			dev_err(dev, "firmware file %s request failed (%d)\n",
-				FIRMWARE_NAME, rc);
+	rc = request_firmware(&fw, FIRMWARE_NAME, dev);
+	if (rc) {
+		dev_err(dev, "firmware file %s request failed (%d)\n",
+			FIRMWARE_NAME, rc);
 			goto out;
-		}
 	}
-	fw = pDevice->firmware;
 
 	pBuffer = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
 	if (!pBuffer)
@@ -103,10 +99,12 @@ FIRMWAREbDownload(
 		DBG_PRT(MSG_LEVEL_DEBUG,
 			KERN_INFO"Download firmware...%d %zu\n", ii, fw->size);
 		if (NdisStatus != STATUS_SUCCESS)
-			goto out;
+			goto free_fw;
         }
 
 	result = TRUE;
+free_fw:
+	release_firmware(fw);
 
 out:
 	kfree(pBuffer);
diff --git a/drivers/staging/vt6656/hostap.c b/drivers/staging/vt6656/hostap.c
index 0a73d40..26a7d0e 100644
--- a/drivers/staging/vt6656/hostap.c
+++ b/drivers/staging/vt6656/hostap.c
@@ -542,9 +542,9 @@ static int hostap_set_encryption(PSDevice pDevice,
 
 	if (param->u.crypt.seq) {
 	    memcpy(&abySeq, param->u.crypt.seq, 8);
-		for (ii = 0 ; ii < 8 ; ii++) {
-	         KeyRSC |= (abySeq[ii] << (ii * 8));
-		}
+		for (ii = 0 ; ii < 8 ; ii++)
+			KeyRSC |= (unsigned long)abySeq[ii] << (ii * 8);
+
 		dwKeyIndex |= 1 << 29;
 		pMgmt->sNodeDBTable[iNodeIndex].KeyRSC = KeyRSC;
 	}
diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h
index 3734e2c..5d8faf9 100644
--- a/drivers/staging/vt6656/int.h
+++ b/drivers/staging/vt6656/int.h
@@ -48,8 +48,8 @@ typedef struct tagSINTData {
 	BYTE byTSR3;
 	BYTE byPkt3;
 	WORD wTime3;
-	DWORD dwLoTSF;
-	DWORD dwHiTSF;
+	u32 dwLoTSF;
+	u32 dwHiTSF;
 	BYTE byISR0;
 	BYTE byISR1;
 	BYTE byRTSSuccess;
diff --git a/drivers/staging/vt6656/ioctl.c b/drivers/staging/vt6656/ioctl.c
deleted file mode 100644
index b6af5f6..0000000
--- a/drivers/staging/vt6656/ioctl.c
+++ /dev/null
@@ -1,648 +0,0 @@
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * File: ioctl.c
- *
- * Purpose:  private ioctl functions
- *
- * Author: Lyndon Chen
- *
- * Date: Auguest 20, 2003
- *
- * Functions:
- *
- * Revision History:
- *
- */
-
-#include "ioctl.h"
-#include "iocmd.h"
-#include "mac.h"
-#include "card.h"
-#include "hostap.h"
-#include "wpactl.h"
-#include "control.h"
-#include "rndis.h"
-#include "rf.h"
-
-SWPAResult wpa_Result;
-static int msglevel = MSG_LEVEL_INFO;
-
-int private_ioctl(PSDevice pDevice, struct ifreq *rq)
-{
-
-	PSCmdRequest	pReq = (PSCmdRequest)rq;
-	PSMgmtObject	pMgmt = &(pDevice->sMgmtObj);
-	int		result = 0;
-	PWLAN_IE_SSID	pItemSSID;
-	SCmdBSSJoin	sJoinCmd;
-	SCmdZoneTypeSet	sZoneTypeCmd;
-	SCmdScan	sScanCmd;
-	SCmdStartAP	sStartAPCmd;
-	SCmdSetWEP	sWEPCmd;
-	SCmdValue	sValue;
-	SBSSIDList	sList;
-	SNodeList	sNodeList;
-	PSBSSIDList	pList;
-	PSNodeList	pNodeList;
-	unsigned int	cbListCount;
-	PKnownBSS	pBSS;
-	PKnownNodeDB	pNode;
-	unsigned int	ii, jj;
-	SCmdLinkStatus	sLinkStatus;
-	BYTE		abySuppRates[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16};
-	BYTE		abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-	DWORD		dwKeyIndex = 0;
-	BYTE		abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
-	signed long	ldBm;
-
-	pReq->wResult = 0;
-
-	switch (pReq->wCmdCode) {
-	case WLAN_CMD_BSS_SCAN:
-		if (copy_from_user(&sScanCmd, pReq->data, sizeof(SCmdScan))) {
-			result = -EFAULT;
-			break;
-		}
-
-		pItemSSID = (PWLAN_IE_SSID)sScanCmd.ssid;
-		if (pItemSSID->len > WLAN_SSID_MAXLEN + 1)
-			return -EINVAL;
-		if (pItemSSID->len != 0) {
-			memset(abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-			memcpy(abyScanSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN);
-		}
-		spin_lock_irq(&pDevice->lock);
-
-		if (memcmp(pMgmt->abyCurrBSSID, &abyNullAddr[0], 6) == 0)
-			BSSvClearBSSList(pDevice, FALSE);
-		else
-			BSSvClearBSSList(pDevice, pDevice->bLinkPass);
-
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_BSS_SCAN..begin\n");
-
-		if (pItemSSID->len != 0)
-			bScheduleCommand(pDevice, WLAN_CMD_BSSID_SCAN,
-					 abyScanSSID);
-		else
-			bScheduleCommand(pDevice, WLAN_CMD_BSSID_SCAN, NULL);
-
-		spin_unlock_irq(&pDevice->lock);
-		break;
-
-	case WLAN_CMD_ZONETYPE_SET:
-		result = -EOPNOTSUPP;
-		break;
-
-		if (copy_from_user(&sZoneTypeCmd, pReq->data, sizeof(SCmdZoneTypeSet))) {
-			result = -EFAULT;
-			break;
-		}
-
-		if (sZoneTypeCmd.bWrite == TRUE) {
-			/* write zonetype */
-			if (sZoneTypeCmd.ZoneType == ZoneType_USA) {
-				/* set to USA */
-				printk("set_ZoneType:USA\n");
-			} else if (sZoneTypeCmd.ZoneType == ZoneType_Japan) {
-				/* set to Japan */
-				printk("set_ZoneType:Japan\n");
-			} else if (sZoneTypeCmd.ZoneType == ZoneType_Europe) {
-				/* set to Europe */
-				printk("set_ZoneType:Europe\n");
-			}
-		} else {
-			/* read zonetype */
-			BYTE zonetype = 0;
-
-			if (zonetype == 0x00) {        /* USA */
-				sZoneTypeCmd.ZoneType = ZoneType_USA;
-			} else if (zonetype == 0x01) { /* Japan */
-				sZoneTypeCmd.ZoneType = ZoneType_Japan;
-			} else if (zonetype == 0x02) { /* Europe */
-				sZoneTypeCmd.ZoneType = ZoneType_Europe;
-			} else {                       /* Unknown ZoneType */
-				printk("Error:ZoneType[%x] Unknown ???\n", zonetype);
-				result = -EFAULT;
-				break;
-			}
-
-			if (copy_to_user(pReq->data, &sZoneTypeCmd,
-						sizeof(SCmdZoneTypeSet))) {
-				result = -EFAULT;
-				break;
-			}
-		}
-		break;
-
-	case WLAN_CMD_BSS_JOIN:
-		if (copy_from_user(&sJoinCmd, pReq->data, sizeof(SCmdBSSJoin))) {
-			result = -EFAULT;
-			break;
-		}
-
-		pItemSSID = (PWLAN_IE_SSID)sJoinCmd.ssid;
-		if (pItemSSID->len > WLAN_SSID_MAXLEN + 1)
-			return -EINVAL;
-		memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-		memcpy(pMgmt->abyDesireSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN);
-		if (sJoinCmd.wBSSType == ADHOC) {
-			pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to adhoc mode\n");
-		} else {
-			pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to STA mode\n");
-		}
-		if (sJoinCmd.bPSEnable == TRUE) {
-			pDevice->ePSMode = WMAC_POWER_FAST;
-			pMgmt->wListenInterval = 2;
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Power Saving On\n");
-		} else {
-			pDevice->ePSMode = WMAC_POWER_CAM;
-			pMgmt->wListenInterval = 1;
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Power Saving Off\n");
-		}
-
-		if (sJoinCmd.bShareKeyAuth == TRUE) {
-			pMgmt->bShareKeyAlgorithm = TRUE;
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Share Key\n");
-		} else {
-			pMgmt->bShareKeyAlgorithm = FALSE;
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Open System\n");
-		}
-
-		pDevice->uChannel = sJoinCmd.uChannel;
-		netif_stop_queue(pDevice->dev);
-		spin_lock_irq(&pDevice->lock);
-		pMgmt->eCurrState = WMAC_STATE_IDLE;
-		bScheduleCommand(pDevice, WLAN_CMD_BSSID_SCAN,
-				 pMgmt->abyDesireSSID);
-		bScheduleCommand(pDevice, WLAN_CMD_SSID, NULL);
-		spin_unlock_irq(&pDevice->lock);
-		break;
-
-	case WLAN_CMD_SET_WEP:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_WEP Key.\n");
-		memset(&sWEPCmd, 0, sizeof(SCmdSetWEP));
-		if (copy_from_user(&sWEPCmd, pReq->data, sizeof(SCmdSetWEP))) {
-			result = -EFAULT;
-			break;
-		}
-		if (sWEPCmd.bEnableWep != TRUE) {
-			int uu;
-
-			pDevice->bEncryptionEnable = FALSE;
-			pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
-			spin_lock_irq(&pDevice->lock);
-			for (uu = 0; uu < MAX_KEY_TABLE; uu++)
-				MACvDisableKeyEntry(pDevice, uu);
-			spin_unlock_irq(&pDevice->lock);
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WEP function disable.\n");
-			break;
-		}
-
-		for (ii = 0; ii < WLAN_WEP_NKEYS; ii++) {
-			if (sWEPCmd.bWepKeyAvailable[ii]) {
-				if (ii == sWEPCmd.byKeyIndex)
-					dwKeyIndex = ii | (1 << 31);
-				else
-					dwKeyIndex = ii;
-				spin_lock_irq(&pDevice->lock);
-				KeybSetDefaultKey(pDevice, &(pDevice->sKey),
-						  dwKeyIndex,
-						  sWEPCmd.auWepKeyLength[ii],
-						  NULL,
-						  (PBYTE)&sWEPCmd.abyWepKey[ii][0],
-						  KEY_CTL_WEP);
-				spin_unlock_irq(&pDevice->lock);
-			}
-		}
-		pDevice->byKeyIndex = sWEPCmd.byKeyIndex;
-		pDevice->bTransmitKey = TRUE;
-		pDevice->bEncryptionEnable = TRUE;
-		pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
-		break;
-
-	case WLAN_CMD_GET_LINK:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_GET_LINK status.\n");
-
-		memset(sLinkStatus.abySSID, 0, WLAN_SSID_MAXLEN + 1);
-
-		if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)
-			sLinkStatus.wBSSType = ADHOC;
-		else
-			sLinkStatus.wBSSType = INFRA;
-
-		if (pMgmt->eCurrState == WMAC_STATE_JOINTED)
-			sLinkStatus.byState = ADHOC_JOINTED;
-		else
-			sLinkStatus.byState = ADHOC_STARTED;
-
-		sLinkStatus.uChannel = pMgmt->uCurrChannel;
-		if (pDevice->bLinkPass == TRUE) {
-			sLinkStatus.bLink = TRUE;
-			pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
-			memcpy(sLinkStatus.abySSID, pItemSSID->abySSID, pItemSSID->len);
-			memcpy(sLinkStatus.abyBSSID, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
-			sLinkStatus.uLinkRate = pMgmt->sNodeDBTable[0].wTxDataRate;
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Link Success!\n");
-		} else {
-			sLinkStatus.bLink = FALSE;
-			sLinkStatus.uLinkRate = 0;
-		}
-		if (copy_to_user(pReq->data, &sLinkStatus,
-					sizeof(SCmdLinkStatus))) {
-			result = -EFAULT;
-			break;
-		}
-		break;
-
-	case WLAN_CMD_GET_LISTLEN:
-		cbListCount = 0;
-		pBSS = &(pMgmt->sBSSList[0]);
-		for (ii = 0; ii < MAX_BSS_NUM; ii++) {
-			pBSS = &(pMgmt->sBSSList[ii]);
-			if (!pBSS->bActive)
-				continue;
-			cbListCount++;
-		}
-		sList.uItem = cbListCount;
-		if (copy_to_user(pReq->data, &sList, sizeof(SBSSIDList))) {
-			result = -EFAULT;
-			break;
-		}
-		pReq->wResult = 0;
-		break;
-
-	case WLAN_CMD_GET_LIST:
-		if (copy_from_user(&sList, pReq->data, sizeof(SBSSIDList))) {
-			result = -EFAULT;
-			break;
-		}
-		if (sList.uItem > (ULONG_MAX - sizeof(SBSSIDList)) / sizeof(SBSSIDItem)) {
-			result = -EINVAL;
-			break;
-		}
-		pList = kmalloc(sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)), GFP_ATOMIC);
-		if (pList == NULL) {
-			result = -ENOMEM;
-			break;
-		}
-		pList->uItem = sList.uItem;
-		pBSS = &(pMgmt->sBSSList[0]);
-		for (ii = 0, jj = 0; jj < MAX_BSS_NUM ; jj++) {
-			pBSS = &(pMgmt->sBSSList[jj]);
-			if (pBSS->bActive) {
-				pList->sBSSIDList[ii].uChannel = pBSS->uChannel;
-				pList->sBSSIDList[ii].wBeaconInterval = pBSS->wBeaconInterval;
-				pList->sBSSIDList[ii].wCapInfo = pBSS->wCapInfo;
-				RFvRSSITodBm(pDevice, (BYTE)(pBSS->uRSSI), &ldBm);
-				pList->sBSSIDList[ii].uRSSI = (unsigned int)ldBm;
-				/* pList->sBSSIDList[ii].uRSSI = pBSS->uRSSI; */
-				memcpy(pList->sBSSIDList[ii].abyBSSID, pBSS->abyBSSID, WLAN_BSSID_LEN);
-				pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
-				memset(pList->sBSSIDList[ii].abySSID, 0, WLAN_SSID_MAXLEN + 1);
-				memcpy(pList->sBSSIDList[ii].abySSID, pItemSSID->abySSID, pItemSSID->len);
-				if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo)) {
-					pList->sBSSIDList[ii].byNetType = INFRA;
-				} else {
-					pList->sBSSIDList[ii].byNetType = ADHOC;
-				}
-				if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo)) {
-					pList->sBSSIDList[ii].bWEPOn = TRUE;
-				} else {
-					pList->sBSSIDList[ii].bWEPOn = FALSE;
-				}
-				ii++;
-				if (ii >= pList->uItem)
-					break;
-			}
-		}
-
-		if (copy_to_user(pReq->data, pList, sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)))) {
-			result = -EFAULT;
-			break;
-		}
-		kfree(pList);
-		pReq->wResult = 0;
-		break;
-
-	case WLAN_CMD_GET_MIB:
-		if (copy_to_user(pReq->data, &(pDevice->s802_11Counter), sizeof(SDot11MIBCount))) {
-			result = -EFAULT;
-			break;
-		}
-		break;
-
-	case WLAN_CMD_GET_STAT:
-		if (copy_to_user(pReq->data, &(pDevice->scStatistic), sizeof(SStatCounter))) {
-			result = -EFAULT;
-			break;
-		}
-		break;
-
-	case WLAN_CMD_STOP_MAC:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_STOP_MAC\n");
-		/* Todo xxxxxx */
-		netif_stop_queue(pDevice->dev);
-		spin_lock_irq(&pDevice->lock);
-		if (pDevice->bRadioOff == FALSE) {
-			CARDbRadioPowerOff(pDevice);
-		}
-		pDevice->bLinkPass = FALSE;
-		ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW);
-		memset(pMgmt->abyCurrBSSID, 0, 6);
-		pMgmt->eCurrState = WMAC_STATE_IDLE;
-		/* del_timer(&pDevice->sTimerCommand); */
-		/* del_timer(&pMgmt->sTimerSecondCallback); */
-		pDevice->bCmdRunning = FALSE;
-		spin_unlock_irq(&pDevice->lock);
-		break;
-
-	case WLAN_CMD_START_MAC:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_START_MAC\n");
-		/* Todo xxxxxxx */
-		if (pDevice->bRadioOff == TRUE)
-			CARDbRadioPowerOn(pDevice);
-		break;
-
-	case WLAN_CMD_SET_HOSTAPD:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOSTAPD\n");
-
-		if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
-			result = -EFAULT;
-			break;
-		}
-		if (sValue.dwValue == 1) {
-			if (vt6656_hostap_set_hostapd(pDevice, 1, 1) == 0) {
-				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable HOSTAP\n");
-			} else {
-				result = -EFAULT;
-				break;
-			}
-		} else {
-			vt6656_hostap_set_hostapd(pDevice, 0, 1);
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable HOSTAP\n");
-		}
-		break;
-
-	case WLAN_CMD_SET_HOSTAPD_STA:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOSTAPD_STA\n");
-		break;
-
-	case WLAN_CMD_SET_802_1X:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_802_1X\n");
-		if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
-			result = -EFAULT;
-			break;
-		}
-
-		if (sValue.dwValue == 1) {
-			pDevice->bEnable8021x = TRUE;
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable 802.1x\n");
-		} else {
-			pDevice->bEnable8021x = FALSE;
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable 802.1x\n");
-		}
-		break;
-
-	case WLAN_CMD_SET_HOST_WEP:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_HOST_WEP\n");
-		if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
-			result = -EFAULT;
-			break;
-		}
-
-		if (sValue.dwValue == 1) {
-			pDevice->bEnableHostWEP = TRUE;
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Enable HostWEP\n");
-		} else {
-			pDevice->bEnableHostWEP = FALSE;
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disable HostWEP\n");
-		}
-		break;
-
-	case WLAN_CMD_SET_WPA:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_SET_WPA\n");
-
-		if (copy_from_user(&sValue, pReq->data, sizeof(SCmdValue))) {
-			result = -EFAULT;
-			break;
-		}
-		if (sValue.dwValue == 1) {
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "up wpadev\n");
-			memcpy(pDevice->wpadev->dev_addr, pDevice->dev->dev_addr,
-			       ETH_ALEN);
-			pDevice->bWPADEVUp = TRUE;
-		} else {
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "close wpadev\n");
-			pDevice->bWPADEVUp = FALSE;
-		}
-		break;
-
-	case WLAN_CMD_AP_START:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WLAN_CMD_AP_START\n");
-		if (pDevice->bRadioOff == TRUE) {
-			CARDbRadioPowerOn(pDevice);
-			add_timer(&pMgmt->sTimerSecondCallback);
-		}
-		if (copy_from_user(&sStartAPCmd, pReq->data, sizeof(SCmdStartAP))) {
-			result = -EFAULT;
-			break;
-		}
-
-		if (sStartAPCmd.wBSSType == AP) {
-			pMgmt->eConfigMode = WMAC_CONFIG_AP;
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct set to AP mode\n");
-		} else {
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ioct BSS type not set to AP mode\n");
-			result = -EFAULT;
-			break;
-		}
-
-		if (sStartAPCmd.wBBPType == PHY80211g) {
-			pMgmt->byAPBBType = PHY_TYPE_11G;
-		} else if (sStartAPCmd.wBBPType == PHY80211a) {
-			pMgmt->byAPBBType = PHY_TYPE_11A;
-		} else {
-			pMgmt->byAPBBType = PHY_TYPE_11B;
-		}
-
-		pItemSSID = (PWLAN_IE_SSID)sStartAPCmd.ssid;
-		if (pItemSSID->len > WLAN_SSID_MAXLEN + 1)
-			return -EINVAL;
-		memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-		memcpy(pMgmt->abyDesireSSID, pItemSSID, pItemSSID->len + WLAN_IEHDR_LEN);
-
-		if ((sStartAPCmd.uChannel > 0) && (sStartAPCmd.uChannel <= 14))
-			pDevice->uChannel = sStartAPCmd.uChannel;
-
-		if ((sStartAPCmd.uBeaconInt >= 20) && (sStartAPCmd.uBeaconInt <= 1000))
-			pMgmt->wIBSSBeaconPeriod = sStartAPCmd.uBeaconInt;
-		else
-			pMgmt->wIBSSBeaconPeriod = 100;
-
-		if (sStartAPCmd.bShareKeyAuth == TRUE) {
-			pMgmt->bShareKeyAlgorithm = TRUE;
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Share Key\n");
-		} else {
-			pMgmt->bShareKeyAlgorithm = FALSE;
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Open System\n");
-		}
-		memcpy(pMgmt->abyIBSSSuppRates, abySuppRates, 6);
-
-		if (sStartAPCmd.byBasicRate & BIT3) {
-			pMgmt->abyIBSSSuppRates[2] |= BIT7;
-			pMgmt->abyIBSSSuppRates[3] |= BIT7;
-			pMgmt->abyIBSSSuppRates[4] |= BIT7;
-			pMgmt->abyIBSSSuppRates[5] |= BIT7;
-		} else if (sStartAPCmd.byBasicRate & BIT2) {
-			pMgmt->abyIBSSSuppRates[2] |= BIT7;
-			pMgmt->abyIBSSSuppRates[3] |= BIT7;
-			pMgmt->abyIBSSSuppRates[4] |= BIT7;
-		} else if (sStartAPCmd.byBasicRate & BIT1) {
-			pMgmt->abyIBSSSuppRates[2] |= BIT7;
-			pMgmt->abyIBSSSuppRates[3] |= BIT7;
-		} else if (sStartAPCmd.byBasicRate & BIT1) {
-			pMgmt->abyIBSSSuppRates[2] |= BIT7;
-		} else {
-			/* default 1,2M */
-			pMgmt->abyIBSSSuppRates[2] |= BIT7;
-			pMgmt->abyIBSSSuppRates[3] |= BIT7;
-		}
-
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Support Rate= %*ph\n",
-			4, pMgmt->abyIBSSSuppRates + 2);
-
-		netif_stop_queue(pDevice->dev);
-		spin_lock_irq(&pDevice->lock);
-		bScheduleCommand(pDevice, WLAN_CMD_RUN_AP, NULL);
-		spin_unlock_irq(&pDevice->lock);
-		break;
-
-	case WLAN_CMD_GET_NODE_CNT:
-		cbListCount = 0;
-		pNode = &(pMgmt->sNodeDBTable[0]);
-		for (ii = 0; ii < (MAX_NODE_NUM + 1); ii++) {
-			pNode = &(pMgmt->sNodeDBTable[ii]);
-			if (!pNode->bActive)
-				continue;
-			cbListCount++;
-		}
-
-		sNodeList.uItem = cbListCount;
-		if (copy_to_user(pReq->data, &sNodeList, sizeof(SNodeList))) {
-			result = -EFAULT;
-			break;
-		}
-		pReq->wResult = 0;
-		break;
-
-	case WLAN_CMD_GET_NODE_LIST:
-		if (copy_from_user(&sNodeList, pReq->data, sizeof(SNodeList))) {
-			result = -EFAULT;
-			break;
-		}
-		if (sNodeList.uItem > (ULONG_MAX - sizeof(SNodeList)) / sizeof(SNodeItem)) {
-			result = -ENOMEM;
-			break;
-		}
-		pNodeList = kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), GFP_ATOMIC);
-		if (pNodeList == NULL) {
-			result = -ENOMEM;
-			break;
-		}
-		pNodeList->uItem = sNodeList.uItem;
-		pNode = &(pMgmt->sNodeDBTable[0]);
-		for (ii = 0, jj = 0; ii < (MAX_NODE_NUM + 1); ii++) {
-			pNode = &(pMgmt->sNodeDBTable[ii]);
-			if (pNode->bActive) {
-				pNodeList->sNodeList[jj].wAID = pNode->wAID;
-				memcpy(pNodeList->sNodeList[jj].abyMACAddr, pNode->abyMACAddr, WLAN_ADDR_LEN);
-				pNodeList->sNodeList[jj].wTxDataRate = pNode->wTxDataRate;
-				pNodeList->sNodeList[jj].wInActiveCount = (WORD)pNode->uInActiveCount;
-				pNodeList->sNodeList[jj].wEnQueueCnt = (WORD)pNode->wEnQueueCnt;
-				pNodeList->sNodeList[jj].wFlags = (WORD)pNode->dwFlags;
-				pNodeList->sNodeList[jj].bPWBitOn = pNode->bPSEnable;
-				pNodeList->sNodeList[jj].byKeyIndex = pNode->byKeyIndex;
-				pNodeList->sNodeList[jj].wWepKeyLength = pNode->uWepKeyLength;
-				memcpy(&(pNodeList->sNodeList[jj].abyWepKey[0]), &(pNode->abyWepKey[0]), WEP_KEYMAXLEN);
-				DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key= %2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
-					pNodeList->sNodeList[jj].abyWepKey[0],
-					pNodeList->sNodeList[jj].abyWepKey[1],
-					pNodeList->sNodeList[jj].abyWepKey[2],
-					pNodeList->sNodeList[jj].abyWepKey[3],
-					pNodeList->sNodeList[jj].abyWepKey[4]);
-				pNodeList->sNodeList[jj].bIsInFallback = pNode->bIsInFallback;
-				pNodeList->sNodeList[jj].uTxFailures = pNode->uTxFailures;
-				pNodeList->sNodeList[jj].uTxAttempts = pNode->uTxAttempts;
-				pNodeList->sNodeList[jj].wFailureRatio = (WORD)pNode->uFailureRatio;
-				jj++;
-				if (jj >= pNodeList->uItem)
-					break;
-			}
-		}
-		if (copy_to_user(pReq->data, pNodeList, sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)))) {
-			kfree(pNodeList);
-			result = -EFAULT;
-			break;
-		}
-		kfree(pNodeList);
-		pReq->wResult = 0;
-		break;
-
-	case 0xFF:
-		memset(wpa_Result.ifname, 0, sizeof(wpa_Result.ifname));
-		wpa_Result.proto = 0;
-		wpa_Result.key_mgmt = 0;
-		wpa_Result.eap_type = 0;
-		wpa_Result.authenticated = FALSE;
-		pDevice->fWPA_Authened = FALSE;
-		if (copy_from_user(&wpa_Result, pReq->data, sizeof(wpa_Result))) {
-			result = -EFAULT;
-			break;
-		}
-		/* for some AP's maybe a good authentication */
-		if (wpa_Result.key_mgmt == 0x20)
-			pMgmt->Cisco_cckm = 1;
-		else
-			pMgmt->Cisco_cckm = 0;
-
-		if (wpa_Result.authenticated == TRUE) {
-			{
-				union iwreq_data wrqu;
-
-				pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
-				memset(&wrqu, 0, sizeof(wrqu));
-				wrqu.data.flags = RT_WPACONNECTED_EVENT_FLAG;
-				wrqu.data.length = pItemSSID->len;
-				wireless_send_event(pDevice->dev, IWEVCUSTOM, &wrqu, pItemSSID->abySSID);
-			}
-
-			pDevice->fWPA_Authened = TRUE; /* is successful peer to wpa_Result.authenticated? */
-		}
-
-		pReq->wResult = 0;
-		break;
-
-	default:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Private command not supported..\n");
-	}
-
-	return result;
-}
diff --git a/drivers/staging/vt6656/ioctl.h b/drivers/staging/vt6656/ioctl.h
deleted file mode 100644
index caa4ac9..0000000
--- a/drivers/staging/vt6656/ioctl.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * File: hostap.h
- *
- * Purpose:
- *
- * Author: Lyndon Chen
- *
- * Date: May 21, 2003
- *
- */
-
-#ifndef __IOCTL_H__
-#define __IOCTL_H__
-
-#include "device.h"
-
-/*---------------------  Export Definitions -------------------------*/
-
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
-int private_ioctl(PSDevice pDevice, struct ifreq *rq);
-
-/*
-void vConfigWEPKey (
-     PSDevice pDevice,
-     DWORD    dwKeyIndex,
-     PBYTE    pbyKey,
-     unsigned long    uKeyLength
-    );
-*/
-
-#endif /* __IOCTL_H__ */
diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c
index 8f19874..52fce69 100644
--- a/drivers/staging/vt6656/iwctl.c
+++ b/drivers/staging/vt6656/iwctl.c
@@ -31,26 +31,17 @@
  */
 
 #include "device.h"
-#include "ioctl.h"
-#include "iocmd.h"
+#include "iwctl.h"
 #include "mac.h"
 #include "card.h"
 #include "hostap.h"
 #include "power.h"
 #include "rf.h"
-
-#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 #include "iowpa.h"
 #include "wpactl.h"
-#endif
-
-#include <net/iw_handler.h>
+#include "control.h"
+#include "rndis.h"
 
-#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-#define SUPPORTED_WIRELESS_EXT 18
-#else
-#define SUPPORTED_WIRELESS_EXT 17
-#endif
 
 static const long frequency_list[] = {
 	2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484,
@@ -88,9 +79,9 @@ struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev)
  * Wireless Handler: get protocol name
  */
 int iwctl_giwname(struct net_device *dev, struct iw_request_info *info,
-		char *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
-	strcpy(wrq, "802.11-a/b/g");
+	strcpy(wrqu->name, "802.11-a/b/g");
 	return 0;
 }
 
@@ -98,9 +89,10 @@ int iwctl_giwname(struct net_device *dev, struct iw_request_info *info,
  * Wireless Handler: set scan
  */
 int iwctl_siwscan(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	struct iw_point *wrq = &wrqu->data;
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
 	struct iw_scan_req *req = (struct iw_scan_req *)extra;
 	BYTE abyScanSSID[WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1];
@@ -109,7 +101,10 @@ int iwctl_siwscan(struct net_device *dev, struct iw_request_info *info,
 	if (!(pDevice->flags & DEVICE_FLAGS_OPENED))
 		return -EINVAL;
 
-	PRINT_K(" SIOCSIWSCAN \n");
+	PRINT_K(" SIOCSIWSCAN\n");
+
+	if (pMgmt == NULL)
+		return -EFAULT;
 
 	if (pMgmt->eScanState ==  WMAC_IS_SCANNING) {
 		// In scanning..
@@ -137,9 +132,9 @@ int iwctl_siwscan(struct net_device *dev, struct iw_request_info *info,
 			pItemSSID = (PWLAN_IE_SSID)abyScanSSID;
 			pItemSSID->byElementID = WLAN_EID_SSID;
 			memcpy(pItemSSID->abySSID, req->essid, (int)req->essid_len);
-			if (pItemSSID->abySSID[req->essid_len - 1] == '\0') {
+			if (pItemSSID->abySSID[req->essid_len] == '\0') {
 				if (req->essid_len > 0)
-					pItemSSID->len = req->essid_len - 1;
+					pItemSSID->len = req->essid_len;
 			} else {
 				pItemSSID->len = req->essid_len;
 			}
@@ -168,8 +163,9 @@ int iwctl_siwscan(struct net_device *dev, struct iw_request_info *info,
  * Wireless Handler : get scan results
  */
 int iwctl_giwscan(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
+	struct iw_point *wrq = &wrqu->data;
 	int ii;
 	int jj;
 	int kk;
@@ -184,10 +180,12 @@ int iwctl_giwscan(struct net_device *dev, struct iw_request_info *info,
 	char *current_val = NULL;
 	struct iw_event iwe;
 	long ldBm;
-	char buf[MAX_WPA_IE_LEN * 2 + 30];
 
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSCAN\n");
 
+	if (pMgmt == NULL)
+		return -EFAULT;
+
 	if (pMgmt->eScanState ==  WMAC_IS_SCANNING) {
 		// In scanning..
 		return -EAGAIN;
@@ -286,12 +284,6 @@ int iwctl_giwscan(struct net_device *dev, struct iw_request_info *info,
 			if ((current_val - current_ev) > IW_EV_LCP_LEN)
 				current_ev = current_val;
 
-			memset(&iwe, 0, sizeof(iwe));
-			iwe.cmd = IWEVCUSTOM;
-			sprintf(buf, "bcn_int=%d", pBSS->wBeaconInterval);
-			iwe.u.data.length = strlen(buf);
-			current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, buf);
-
 			if ((pBSS->wWPALen > 0) && (pBSS->wWPALen <= MAX_WPA_IE_LEN)) {
 				memset(&iwe, 0, sizeof(iwe));
 				iwe.cmd = IWEVGENIE;
@@ -315,12 +307,13 @@ int iwctl_giwscan(struct net_device *dev, struct iw_request_info *info,
  * Wireless Handler: set frequence or channel
  */
 int iwctl_siwfreq(struct net_device *dev, struct iw_request_info *info,
-		struct iw_freq *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	struct iw_freq *wrq = &wrqu->freq;
 	int rc = 0;
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWFREQ \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWFREQ\n");
 
 	// If setting by frequency, convert to a channel
 	if ((wrq->e == 1) && (wrq->m >= (int)2.412e8) &&
@@ -353,12 +346,17 @@ int iwctl_siwfreq(struct net_device *dev, struct iw_request_info *info,
  * Wireless Handler: get frequence or channel
  */
 int iwctl_giwfreq(struct net_device *dev, struct iw_request_info *info,
-		struct iw_freq *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	struct iw_freq *wrq = &wrqu->freq;
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWFREQ \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWFREQ\n");
+
+	if (pMgmt == NULL)
+		return -EFAULT;
+
 
 #ifdef WEXT_USECHANNELS
 	wrq->m = (int)pMgmt->uCurrChannel;
@@ -379,16 +377,21 @@ int iwctl_giwfreq(struct net_device *dev, struct iw_request_info *info,
  * Wireless Handler: set operation mode
  */
 int iwctl_siwmode(struct net_device *dev, struct iw_request_info *info,
-		__u32 *wmode, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	__u32 *wmode = &wrqu->mode;
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
 	int rc = 0;
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWMODE \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWMODE\n");
+
+	if (pMgmt == NULL)
+		return -EFAULT;
 
 	if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP && pDevice->bEnableHostapd) {
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Can't set operation mode, hostapd is running \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+			"Can't set operation mode, hostapd is running\n");
 		return rc;
 	}
 
@@ -432,19 +435,72 @@ int iwctl_siwmode(struct net_device *dev, struct iw_request_info *info,
 		rc = -EINVAL;
 	}
 
+	if (pDevice->bCommit) {
+		if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
+			netif_stop_queue(pDevice->dev);
+			spin_lock_irq(&pDevice->lock);
+			bScheduleCommand((void *) pDevice,
+				WLAN_CMD_RUN_AP, NULL);
+			spin_unlock_irq(&pDevice->lock);
+		} else {
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+				"Commit the settings\n");
+
+			spin_lock_irq(&pDevice->lock);
+
+			if (pDevice->bLinkPass &&
+				memcmp(pMgmt->abyCurrSSID,
+					pMgmt->abyDesireSSID,
+					WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN)) {
+				bScheduleCommand((void *) pDevice,
+					WLAN_CMD_DISASSOCIATE, NULL);
+			} else {
+				pDevice->bLinkPass = FALSE;
+				pMgmt->eCurrState = WMAC_STATE_IDLE;
+				memset(pMgmt->abyCurrBSSID, 0, 6);
+			}
+
+			ControlvMaskByte(pDevice,
+				MESSAGE_REQUEST_MACREG,	MAC_REG_PAPEDELAY,
+					LEDSTS_STS, LEDSTS_SLOW);
+
+			netif_stop_queue(pDevice->dev);
+
+			pMgmt->eScanType = WMAC_SCAN_ACTIVE;
+
+			if (!pDevice->bWPASuppWextEnabled)
+				bScheduleCommand((void *) pDevice,
+					 WLAN_CMD_BSSID_SCAN,
+					 pMgmt->abyDesireSSID);
+
+			bScheduleCommand((void *) pDevice,
+				 WLAN_CMD_SSID,
+				 NULL);
+
+			spin_unlock_irq(&pDevice->lock);
+		}
+		pDevice->bCommit = FALSE;
+	}
+
+
 	return rc;
 }
 
 /*
  * Wireless Handler: get operation mode
  */
-void iwctl_giwmode(struct net_device *dev, struct iw_request_info *info,
-		__u32 *wmode, char *extra)
+int iwctl_giwmode(struct net_device *dev, struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	__u32 *wmode = &wrqu->mode;
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWMODE \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWMODE\n");
+
+	if (pMgmt == NULL)
+		return -EFAULT;
+
 	// If not managed, assume it's ad-hoc
 	switch (pMgmt->eConfigMode) {
 	case WMAC_CONFIG_ESS_STA:
@@ -462,14 +518,17 @@ void iwctl_giwmode(struct net_device *dev, struct iw_request_info *info,
 	default:
 		*wmode = IW_MODE_ADHOC;
 	}
+
+	return 0;
 }
 
 /*
  * Wireless Handler: get capability range
  */
-void iwctl_giwrange(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra)
+int iwctl_giwrange(struct net_device *dev, struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
 {
+	struct iw_point *wrq = &wrqu->data;
 	struct iw_range *range = (struct iw_range *)extra;
 	int i;
 	int k;
@@ -546,7 +605,7 @@ void iwctl_giwrange(struct net_device *dev, struct iw_request_info *info,
 		range->txpower[0] = 100;
 		range->num_txpower = 1;
 		range->txpower_capa = IW_TXPOW_MWATT;
-		range->we_version_source = SUPPORTED_WIRELESS_EXT;
+		range->we_version_source = WIRELESS_EXT;
 		range->we_version_compiled = WIRELESS_EXT;
 		range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
 		range->retry_flags = IW_RETRY_LIMIT;
@@ -562,20 +621,26 @@ void iwctl_giwrange(struct net_device *dev, struct iw_request_info *info,
 		range->avg_qual.level = 176; // -80 dBm
 		range->avg_qual.noise = 0;
 	}
+
+	return 0;
 }
 
 /*
  * Wireless Handler : set ap mac address
  */
 int iwctl_siwap(struct net_device *dev, struct iw_request_info *info,
-		struct sockaddr *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	struct sockaddr *wrq = &wrqu->ap_addr;
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
 	int rc = 0;
 	BYTE ZeroBSSID[WLAN_BSSID_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
-	PRINT_K(" SIOCSIWAP \n");
+	PRINT_K(" SIOCSIWAP\n");
+
+	if (pMgmt == NULL)
+		return -EFAULT;
 
 	if (wrq->sa_family != ARPHRD_ETHER) {
 		rc = -EINVAL;
@@ -616,12 +681,16 @@ int iwctl_siwap(struct net_device *dev, struct iw_request_info *info,
  * Wireless Handler: get ap mac address
  */
 int iwctl_giwap(struct net_device *dev, struct iw_request_info *info,
-		struct sockaddr *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	struct sockaddr *wrq = &wrqu->ap_addr;
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAP \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAP\n");
+
+	if (pMgmt == NULL)
+		return -EFAULT;
 
 	memcpy(wrq->sa_data, pMgmt->abyCurrBSSID, 6);
 
@@ -639,59 +708,77 @@ int iwctl_giwap(struct net_device *dev, struct iw_request_info *info,
  * Wireless Handler: get ap list
  */
 int iwctl_giwaplist(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
+	struct iw_point *wrq = &wrqu->data;
+	struct sockaddr *sock;
+	struct iw_quality *qual;
+	PSDevice pDevice = netdev_priv(dev);
+	PSMgmtObject pMgmt = &pDevice->sMgmtObj;
+	PKnownBSS pBSS = &pMgmt->sBSSList[0];
 	int ii;
 	int jj;
-	int rc = 0;
-	struct sockaddr sock[IW_MAX_AP];
-	struct iw_quality qual[IW_MAX_AP];
-	PSDevice pDevice = netdev_priv(dev);
-	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAPLIST \n");
-	// Only super-user can see AP list
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAPLIST\n");
+	/* Only super-user can see AP list */
 
-	if (!capable(CAP_NET_ADMIN)) {
-		rc = -EPERM;
-		return rc;
-	}
+	if (pBSS == NULL)
+		return -ENODEV;
 
-	if (wrq->pointer) {
-		PKnownBSS pBSS = &(pMgmt->sBSSList[0]);
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
 
-		for (ii = 0, jj= 0; ii < MAX_BSS_NUM; ii++) {
-			pBSS = &(pMgmt->sBSSList[ii]);
-			if (!pBSS->bActive)
-				continue;
-			if (jj >= IW_MAX_AP)
-				break;
-			memcpy(sock[jj].sa_data, pBSS->abyBSSID, 6);
-			sock[jj].sa_family = ARPHRD_ETHER;
-			qual[jj].level = pBSS->uRSSI;
-			qual[jj].qual = qual[jj].noise = 0;
-			qual[jj].updated = 2;
-			jj++;
-		}
+	if (!wrq->pointer)
+		return -EINVAL;
 
-		wrq->flags = 1; // Should be defined
-		wrq->length = jj;
-		memcpy(extra, sock, sizeof(struct sockaddr) * jj);
-		memcpy(extra + sizeof(struct sockaddr) * jj, qual, sizeof(struct iw_quality) * jj);
+	sock = kzalloc(sizeof(struct sockaddr) * IW_MAX_AP, GFP_KERNEL);
+	if (sock == NULL)
+		return -ENOMEM;
+	qual = kzalloc(sizeof(struct iw_quality) * IW_MAX_AP, GFP_KERNEL);
+	if (qual == NULL) {
+		kfree(sock);
+		return -ENOMEM;
 	}
-	return rc;
+
+	for (ii = 0, jj = 0; ii < MAX_BSS_NUM; ii++) {
+		if (!pBSS[ii].bActive)
+			continue;
+		if (jj >= IW_MAX_AP)
+			break;
+		memcpy(sock[jj].sa_data, pBSS[ii].abyBSSID, 6);
+		sock[jj].sa_family = ARPHRD_ETHER;
+		qual[jj].level = pBSS[ii].uRSSI;
+		qual[jj].qual = qual[jj].noise = 0;
+		qual[jj].updated = 2;
+		jj++;
+	}
+
+	wrq->flags = 1; /* Should be defined */
+	wrq->length = jj;
+	memcpy(extra, sock, sizeof(struct sockaddr) * jj);
+	memcpy(extra + sizeof(struct sockaddr) * jj, qual,
+		sizeof(struct iw_quality) * jj);
+
+	kfree(sock);
+	kfree(qual);
+
+	return 0;
 }
 
 /*
  * Wireless Handler: set essid
  */
 int iwctl_siwessid(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	struct iw_point	*wrq = &wrqu->essid;
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
 	PWLAN_IE_SSID pItemSSID;
 
+	if (pMgmt == NULL)
+		return -EFAULT;
+
 	if (!(pDevice->flags & DEVICE_FLAGS_OPENED))
 		return -EINVAL;
 
@@ -704,10 +791,8 @@ int iwctl_siwessid(struct net_device *dev, struct iw_request_info *info,
 		memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
 		memset(pMgmt->abyDesireBSSID, 0xFF,6);
 		PRINT_K("set essid to 'any' \n");
-#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 		// Unknown desired AP, so here need not associate??
 		return 0;
-#endif
 	} else {
 		// Set the SSID
 		memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
@@ -715,9 +800,9 @@ int iwctl_siwessid(struct net_device *dev, struct iw_request_info *info,
 		pItemSSID->byElementID = WLAN_EID_SSID;
 
 		memcpy(pItemSSID->abySSID, extra, wrq->length);
-		if (pItemSSID->abySSID[wrq->length - 1] == '\0') {
+		if (pItemSSID->abySSID[wrq->length] == '\0') {
 			if (wrq->length>0)
-				pItemSSID->len = wrq->length - 1;
+				pItemSSID->len = wrq->length;
 		} else {
 			pItemSSID->len = wrq->length;
 		}
@@ -729,7 +814,6 @@ int iwctl_siwessid(struct net_device *dev, struct iw_request_info *info,
 			return 0;
 		}
 
-#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 		// Wext wil order another command of siwap to link
 		// with desired AP, so here need not associate??
 		if (pDevice->bWPASuppWextEnabled == TRUE)  {
@@ -778,7 +862,6 @@ int iwctl_siwessid(struct net_device *dev, struct iw_request_info *info,
 			}
 			return 0;
 		}
-#endif
 
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set essid = %s \n", pItemSSID->abySSID);
 	}
@@ -792,14 +875,18 @@ int iwctl_siwessid(struct net_device *dev, struct iw_request_info *info,
 /*
  * Wireless Handler: get essid
  */
-void iwctl_giwessid(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra)
+int iwctl_giwessid(struct net_device *dev, struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	struct iw_point	*wrq = &wrqu->essid;
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
 	PWLAN_IE_SSID pItemSSID;
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWESSID \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWESSID\n");
+
+	if (pMgmt == NULL)
+		return -EFAULT;
 
 	// Note: if wrq->u.data.flags != 0, we should get the relevant
 	// SSID from the SSID list...
@@ -811,15 +898,18 @@ void iwctl_giwessid(struct net_device *dev, struct iw_request_info *info,
 
         wrq->length = pItemSSID->len;
 	wrq->flags = 1; // active
+
+	return 0;
 }
 
 /*
  * Wireless Handler: set data rate
  */
 int iwctl_siwrate(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	struct iw_param *wrq = &wrqu->bitrate;
 	int rc = 0;
 	u8 brate = 0;
 	int i;
@@ -893,13 +983,18 @@ int iwctl_siwrate(struct net_device *dev, struct iw_request_info *info,
 /*
  * Wireless Handler: get data rate
  */
-void iwctl_giwrate(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra)
+int iwctl_giwrate(struct net_device *dev, struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	struct iw_param *wrq = &wrqu->bitrate;
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRATE \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRATE\n");
+
+	if (pMgmt == NULL)
+		return -EFAULT;
+
 	{
 		BYTE abySupportedRates[13] = {
 			0x02, 0x04, 0x0B, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30,
@@ -932,14 +1027,18 @@ void iwctl_giwrate(struct net_device *dev, struct iw_request_info *info,
 		if (pDevice->bFixRate == TRUE)
 			wrq->fixed = TRUE;
 	}
+
+	return 0;
 }
 
 /*
  * Wireless Handler: set rts threshold
  */
-int iwctl_siwrts(struct net_device *dev, struct iw_param *wrq)
+int iwctl_siwrts(struct net_device *dev, struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	struct iw_param *wrq = &wrqu->rts;
 
 	if ((wrq->value < 0 || wrq->value > 2312) && !wrq->disabled)
 		return -EINVAL;
@@ -956,11 +1055,12 @@ int iwctl_siwrts(struct net_device *dev, struct iw_param *wrq)
  * Wireless Handler: get rts
  */
 int iwctl_giwrts(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	struct iw_param *wrq = &wrqu->rts;
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRTS \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRTS\n");
 	wrq->value = pDevice->wRTSThreshold;
 	wrq->disabled = (wrq->value >= 2312);
 	wrq->fixed = 1;
@@ -971,13 +1071,14 @@ int iwctl_giwrts(struct net_device *dev, struct iw_request_info *info,
  * Wireless Handler: set fragment threshold
  */
 int iwctl_siwfrag(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	struct iw_param *wrq = &wrqu->frag;
 	int rc = 0;
 	int fthr = wrq->value;
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWFRAG \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWFRAG\n");
 
 	if (wrq->disabled)
 		fthr = 2312;
@@ -994,11 +1095,12 @@ int iwctl_siwfrag(struct net_device *dev, struct iw_request_info *info,
  * Wireless Handler: get fragment threshold
  */
 int iwctl_giwfrag(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	struct iw_param *wrq = &wrqu->frag;
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWFRAG \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWFRAG\n");
 	wrq->value = pDevice->wFragmentationThreshold;
 	wrq->disabled = (wrq->value >= 2312);
 	wrq->fixed = 1;
@@ -1009,12 +1111,13 @@ int iwctl_giwfrag(struct net_device *dev, struct iw_request_info *info,
  * Wireless Handler: set retry threshold
  */
 int iwctl_siwretry(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	struct iw_param *wrq = &wrqu->retry;
 	int rc = 0;
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRETRY \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRETRY\n");
 
 	if (wrq->disabled) {
 		rc = -EINVAL;
@@ -1041,10 +1144,11 @@ int iwctl_siwretry(struct net_device *dev, struct iw_request_info *info,
  * Wireless Handler: get retry threshold
  */
 int iwctl_giwretry(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRETRY \n");
+	struct iw_param *wrq = &wrqu->retry;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWRETRY\n");
 	wrq->disabled = 0; // Can't be disabled
 
 	// Note: by default, display the min retry number
@@ -1067,17 +1171,21 @@ int iwctl_giwretry(struct net_device *dev, struct iw_request_info *info,
  * Wireless Handler: set encode mode
  */
 int iwctl_siwencode(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
-	DWORD dwKeyIndex = (DWORD)(wrq->flags & IW_ENCODE_INDEX);
+	struct iw_point *wrq = &wrqu->encoding;
+	u32 dwKeyIndex = (u32)(wrq->flags & IW_ENCODE_INDEX);
 	int ii;
 	int uu;
 	int rc = 0;
 	int index = (wrq->flags & IW_ENCODE_INDEX);
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWENCODE \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWENCODE\n");
+
+	if (pMgmt == NULL)
+		return -EFAULT;
 
 	// Check the size of the key
 	if (wrq->length > WLAN_WEP232_KEYLEN) {
@@ -1155,17 +1263,17 @@ int iwctl_siwencode(struct net_device *dev, struct iw_request_info *info,
 		pMgmt->bShareKeyAlgorithm = FALSE;
 	}
 
-#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 	memset(pMgmt->abyDesireBSSID, 0xFF, 6);
-#endif
+
 	return rc;
 }
 
 int iwctl_giwencode(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
+	struct iw_point *wrq = &wrqu->encoding;
 	char abyKey[WLAN_WEP232_KEYLEN];
 
 	unsigned index = (unsigned)(wrq->flags & IW_ENCODE_INDEX);
@@ -1173,6 +1281,9 @@ int iwctl_giwencode(struct net_device *dev, struct iw_request_info *info,
 
 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWENCODE\n");
 
+	if (pMgmt == NULL)
+		return -EFAULT;
+
 	if (index > WLAN_WEP_NKEYS)
 		return	-EINVAL;
 	if (index < 1) { // get default key
@@ -1220,13 +1331,17 @@ int iwctl_giwencode(struct net_device *dev, struct iw_request_info *info,
  * Wireless Handler: set power mode
  */
 int iwctl_siwpower(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
+	struct iw_param *wrq = &wrqu->power;
 	int rc = 0;
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER\n");
+
+	if (pMgmt == NULL)
+		return -EFAULT;
 
 	if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) {
 		rc = -EINVAL;
@@ -1268,24 +1383,31 @@ int iwctl_siwpower(struct net_device *dev, struct iw_request_info *info,
  * Wireless Handler: get power mode
  */
 int iwctl_giwpower(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
+	struct iw_param *wrq = &wrqu->power;
 	int mode = pDevice->ePSMode;
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWPOWER \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWPOWER\n");
+
+	if (pMgmt == NULL)
+		return -EFAULT;
 
 	if ((wrq->disabled = (mode == WMAC_POWER_CAM)))
 		return 0;
 
 	if ((wrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
-		wrq->value = (int)((pMgmt->wListenInterval * pMgmt->wCurrBeaconPeriod) << 10);
+		wrq->value = (int)((pMgmt->wListenInterval *
+			pMgmt->wCurrBeaconPeriod) / 100);
 		wrq->flags = IW_POWER_TIMEOUT;
 	} else {
-		wrq->value = (int)((pMgmt->wListenInterval * pMgmt->wCurrBeaconPeriod) << 10);
+		wrq->value = (int)((pMgmt->wListenInterval *
+			pMgmt->wCurrBeaconPeriod) / 100);
 		wrq->flags = IW_POWER_PERIOD;
 	}
+
 	wrq->flags |= IW_POWER_ALL_R;
 	return 0;
 }
@@ -1294,12 +1416,13 @@ int iwctl_giwpower(struct net_device *dev, struct iw_request_info *info,
  * Wireless Handler: get Sensitivity
  */
 int iwctl_giwsens(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
+	struct iw_param *wrq = &wrqu->sens;
 	long ldBm;
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSENS \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSENS\n");
 	if (pDevice->bLinkPass == TRUE) {
 		RFvRSSITodBm(pDevice, (BYTE)(pDevice->uCurrRSSI), &ldBm);
 		wrq->value = ldBm;
@@ -1311,18 +1434,20 @@ int iwctl_giwsens(struct net_device *dev, struct iw_request_info *info,
 	return 0;
 }
 
-#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-
 int iwctl_siwauth(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
+	struct iw_param *wrq = &wrqu->param;
 	int ret = 0;
 	static int wpa_version = 0; // must be static to save the last value, einsn liu
 	static int pairwise = 0;
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWAUTH \n");
+	if (pMgmt == NULL)
+		return -EFAULT;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWAUTH\n");
 	switch (wrq->flags & IW_AUTH_INDEX) {
 	case IW_AUTH_WPA_VERSION:
 		wpa_version = wrq->value;
@@ -1406,6 +1531,7 @@ int iwctl_siwauth(struct net_device *dev, struct iw_request_info *info,
 		}
 		break;
 	default:
+		PRINT_K("iwctl_siwauth: not supported %x\n", wrq->flags);
 		ret = -EOPNOTSUPP;
 		break;
 	}
@@ -1413,18 +1539,22 @@ int iwctl_siwauth(struct net_device *dev, struct iw_request_info *info,
 }
 
 int iwctl_giwauth(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	return -EOPNOTSUPP;
 }
 
 int iwctl_siwgenie(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
+	struct iw_point *wrq = &wrqu->data;
 	int ret = 0;
 
+	if (pMgmt == NULL)
+		return -EFAULT;
+
 	if (wrq->length){
 		if ((wrq->length < 2) || (extra[1] + 2 != wrq->length)) {
 			ret = -EINVAL;
@@ -1450,13 +1580,17 @@ out: // not completely ...not necessary in wpa_supplicant 0.5.8
 }
 
 int iwctl_giwgenie(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
+	struct iw_point *wrq = &wrqu->data;
 	int ret = 0;
 	int space = wrq->length;
 
+	if (pMgmt == NULL)
+		return -EFAULT;
+
 	wrq->length = 0;
 	if (pMgmt->wWPAIELen > 0) {
 		wrq->length = pMgmt->wWPAIELen;
@@ -1472,10 +1606,11 @@ int iwctl_giwgenie(struct net_device *dev, struct iw_request_info *info,
 }
 
 int iwctl_siwencodeext(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
+	struct iw_point *wrq = &wrqu->encoding;
 	struct iw_encode_ext *ext = (struct iw_encode_ext*)extra;
 	struct viawget_wpa_param *param=NULL;
 // original member
@@ -1488,17 +1623,18 @@ int iwctl_siwencodeext(struct net_device *dev, struct iw_request_info *info,
 	size_t seq_len = 0;
 	size_t key_len = 0;
 	u8 *buf;
-	size_t blen;
 	u8 key_array[64];
 	int ret = 0;
 
-	PRINT_K("SIOCSIWENCODEEXT...... \n");
+	PRINT_K("SIOCSIWENCODEEXT......\n");
 
-	blen = sizeof(*param);
-	buf = kmalloc((int)blen, (int)GFP_KERNEL);
+	if (pMgmt == NULL)
+		return -EFAULT;
+
+	buf = kzalloc(sizeof(struct viawget_wpa_param), GFP_KERNEL);
 	if (buf == NULL)
 		return -ENOMEM;
-	memset(buf, 0, blen);
+
 	param = (struct viawget_wpa_param *)buf;
 
 // recover alg_name
@@ -1588,28 +1724,33 @@ int iwctl_siwencodeext(struct net_device *dev, struct iw_request_info *info,
 	}
 /*******/
 	spin_lock_irq(&pDevice->lock);
-	ret = wpa_set_keys(pDevice, param, TRUE);
+	ret = wpa_set_keys(pDevice, param);
 	spin_unlock_irq(&pDevice->lock);
 
 error:
-	kfree(param);
+	kfree(buf);
 	return ret;
 }
 
 int iwctl_giwencodeext(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	return -EOPNOTSUPP;
 }
 
 int iwctl_siwmlme(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra)
+		union iwreq_data *wrqu, char *extra)
 {
 	PSDevice pDevice = netdev_priv(dev);
 	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
 	struct iw_mlme *mlme = (struct iw_mlme *)extra;
 	int ret = 0;
 
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWMLME\n");
+
+	if (pMgmt == NULL)
+		return -EFAULT;
+
 	if (memcmp(pMgmt->abyCurrBSSID, mlme->addr.sa_data, ETH_ALEN)) {
 		ret = -EINVAL;
 		return ret;
@@ -1629,81 +1770,62 @@ int iwctl_siwmlme(struct net_device *dev, struct iw_request_info *info,
 	return ret;
 }
 
-#endif
+static int iwctl_config_commit(struct net_device *dev,
+	struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+{
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "SIOCSIWCOMMIT\n");
+
+	return 0;
+}
 
 static const iw_handler iwctl_handler[] = {
-	(iw_handler)NULL, // SIOCSIWCOMMIT
-	(iw_handler)NULL, // SIOCGIWNAME
-	(iw_handler)NULL, // SIOCSIWNWID
-	(iw_handler)NULL, // SIOCGIWNWID
-	(iw_handler)NULL, // SIOCSIWFREQ
-	(iw_handler)NULL, // SIOCGIWFREQ
-	(iw_handler)NULL, // SIOCSIWMODE
-	(iw_handler)NULL, // SIOCGIWMODE
-	(iw_handler)NULL, // SIOCSIWSENS
-	(iw_handler)NULL, // SIOCGIWSENS
-	(iw_handler)NULL, // SIOCSIWRANGE
-	(iw_handler)iwctl_giwrange, // SIOCGIWRANGE
-	(iw_handler)NULL, // SIOCSIWPRIV
-	(iw_handler)NULL, // SIOCGIWPRIV
-	(iw_handler)NULL, // SIOCSIWSTATS
-	(iw_handler)NULL, // SIOCGIWSTATS
-	(iw_handler)NULL, // SIOCSIWSPY
-	(iw_handler)NULL, // SIOCGIWSPY
-	(iw_handler)NULL, // -- hole --
-	(iw_handler)NULL, // -- hole --
-	(iw_handler)NULL, // SIOCSIWAP
-	(iw_handler)NULL, // SIOCGIWAP
-	(iw_handler)NULL, // -- hole -- 0x16
-	(iw_handler)NULL, // SIOCGIWAPLIST
-	(iw_handler)iwctl_siwscan, // SIOCSIWSCAN
-	(iw_handler)iwctl_giwscan, // SIOCGIWSCAN
-	(iw_handler)NULL, // SIOCSIWESSID
-	(iw_handler)NULL, // SIOCGIWESSID
-	(iw_handler)NULL, // SIOCSIWNICKN
-	(iw_handler)NULL, // SIOCGIWNICKN
-	(iw_handler)NULL, // -- hole --
-	(iw_handler)NULL, // -- hole --
-	(iw_handler)NULL, // SIOCSIWRATE 0x20
-	(iw_handler)NULL, // SIOCGIWRATE
-	(iw_handler)NULL, // SIOCSIWRTS
-	(iw_handler)NULL, // SIOCGIWRTS
-	(iw_handler)NULL, // SIOCSIWFRAG
-	(iw_handler)NULL, // SIOCGIWFRAG
-	(iw_handler)NULL, // SIOCSIWTXPOW
-	(iw_handler)NULL, // SIOCGIWTXPOW
-	(iw_handler)NULL, // SIOCSIWRETRY
-	(iw_handler)NULL, // SIOCGIWRETRY
-	(iw_handler)NULL, // SIOCSIWENCODE
-	(iw_handler)NULL, // SIOCGIWENCODE
-	(iw_handler)NULL, // SIOCSIWPOWER
-	(iw_handler)NULL, // SIOCGIWPOWER
-	(iw_handler)NULL, // -- hole --
-	(iw_handler)NULL, // -- hole --
-	(iw_handler)NULL, // SIOCSIWGENIE
-	(iw_handler)NULL, // SIOCGIWGENIE
-	(iw_handler)NULL, // SIOCSIWAUTH
-	(iw_handler)NULL, // SIOCGIWAUTH
-	(iw_handler)NULL, // SIOCSIWENCODEEXT
-	(iw_handler)NULL, // SIOCGIWENCODEEXT
-	(iw_handler)NULL, // SIOCSIWPMKSA
-	(iw_handler)NULL, // -- hole --
+	IW_HANDLER(SIOCSIWCOMMIT, iwctl_config_commit),
+	IW_HANDLER(SIOCGIWNAME, iwctl_giwname),
+	IW_HANDLER(SIOCSIWFREQ, iwctl_siwfreq),
+	IW_HANDLER(SIOCGIWFREQ, iwctl_giwfreq),
+	IW_HANDLER(SIOCSIWMODE, iwctl_siwmode),
+	IW_HANDLER(SIOCGIWMODE, iwctl_giwmode),
+	IW_HANDLER(SIOCGIWSENS, iwctl_giwsens),
+	IW_HANDLER(SIOCGIWRANGE, iwctl_giwrange),
+	IW_HANDLER(SIOCSIWAP, iwctl_siwap),
+	IW_HANDLER(SIOCGIWAP, iwctl_giwap),
+	IW_HANDLER(SIOCSIWMLME, iwctl_siwmlme),
+	IW_HANDLER(SIOCGIWAPLIST, iwctl_giwaplist),
+	IW_HANDLER(SIOCSIWSCAN, iwctl_siwscan),
+	IW_HANDLER(SIOCGIWSCAN, iwctl_giwscan),
+	IW_HANDLER(SIOCSIWESSID, iwctl_siwessid),
+	IW_HANDLER(SIOCGIWESSID, iwctl_giwessid),
+	IW_HANDLER(SIOCSIWRATE, iwctl_siwrate),
+	IW_HANDLER(SIOCGIWRATE, iwctl_giwrate),
+	IW_HANDLER(SIOCSIWRTS, iwctl_siwrts),
+	IW_HANDLER(SIOCGIWRTS, iwctl_giwrts),
+	IW_HANDLER(SIOCSIWFRAG, iwctl_siwfrag),
+	IW_HANDLER(SIOCGIWFRAG, iwctl_giwfrag),
+	IW_HANDLER(SIOCSIWRETRY, iwctl_siwretry),
+	IW_HANDLER(SIOCGIWRETRY, iwctl_giwretry),
+	IW_HANDLER(SIOCSIWENCODE, iwctl_siwencode),
+	IW_HANDLER(SIOCGIWENCODE, iwctl_giwencode),
+	IW_HANDLER(SIOCSIWPOWER, iwctl_siwpower),
+	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),
+	IW_HANDLER(SIOCGIWENCODEEXT, iwctl_giwencodeext)
 };
 
 static const iw_handler iwctl_private_handler[] = {
 	NULL, // SIOCIWFIRSTPRIV
 };
 
-struct iw_priv_args iwctl_private_args[] = {
-	{ IOCTL_CMD_SET, IW_PRIV_TYPE_CHAR | 1024, 0, "set" },
-};
-
 const struct iw_handler_def iwctl_handler_def = {
 	.get_wireless_stats	= &iwctl_get_wireless_stats,
-	.num_standard		= sizeof(iwctl_handler) / sizeof(iw_handler),
+	.num_standard		= ARRAY_SIZE(iwctl_handler),
 	.num_private		= 0,
 	.num_private_args	= 0,
-	.standard		= (iw_handler *)iwctl_handler,
+	.standard		= iwctl_handler,
 	.private		= NULL,
 	.private_args		= NULL,
 };
diff --git a/drivers/staging/vt6656/iwctl.h b/drivers/staging/vt6656/iwctl.h
index d056f83..b594a10 100644
--- a/drivers/staging/vt6656/iwctl.h
+++ b/drivers/staging/vt6656/iwctl.h
@@ -42,106 +42,105 @@
 struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev);
 
 int iwctl_siwap(struct net_device *dev, struct iw_request_info *info,
-		struct sockaddr *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
-void iwctl_giwrange(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra);
+int iwctl_giwrange(struct net_device *dev, struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra);
 
-void iwctl_giwmode(struct net_device *dev, struct iw_request_info *info,
-		__u32 *wmode, char *extra);
+int iwctl_giwmode(struct net_device *dev, struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_siwmode(struct net_device *dev, struct iw_request_info *info,
-		__u32 *wmode, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_giwfreq(struct net_device *dev, struct iw_request_info *info,
-		struct iw_freq *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_siwfreq(struct net_device *dev, struct iw_request_info *info,
-		struct iw_freq *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_giwname(struct net_device *dev, struct iw_request_info *info,
-		char *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_giwsens(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_giwap(struct net_device *dev, struct iw_request_info *info,
-		struct sockaddr *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_giwaplist(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_siwessid(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
-void iwctl_giwessid(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra);
+int iwctl_giwessid(struct net_device *dev, struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_siwrate(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
-void iwctl_giwrate(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra);
+int iwctl_giwrate(struct net_device *dev, struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra);
 
-int iwctl_siwrts(struct net_device *dev, struct iw_param *wrq);
+int iwctl_siwrts(struct net_device *dev, struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_giwrts(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_siwfrag(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_giwfrag(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_siwretry(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_giwretry(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_siwencode(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_giwencode(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_siwpower(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_giwpower(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_giwscan(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_siwscan(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
-#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 int iwctl_siwauth(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_giwauth(struct net_device *dev, struct iw_request_info *info,
-		struct iw_param *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_siwgenie(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_giwgenie(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_siwencodeext(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_giwencodeext(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra);
+		union iwreq_data *wrqu, char *extra);
 
 int iwctl_siwmlme(struct net_device *dev, struct iw_request_info *info,
-		struct iw_point *wrq, char *extra);
-#endif // #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
+		union iwreq_data *wrqu, char *extra);
 
 extern const struct iw_handler_def iwctl_handler_def;
-extern const struct iw_priv_args iwctl_private_args;
+extern const struct iw_priv_args iwctl_priv_args;
 
 #endif /* __IWCTL_H__ */
diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c
index a61fcb9..8c78b86 100644
--- a/drivers/staging/vt6656/key.c
+++ b/drivers/staging/vt6656/key.c
@@ -36,9 +36,9 @@
  *
  */
 
+#include "mac.h"
 #include "tmacro.h"
 #include "key.h"
-#include "mac.h"
 #include "rndis.h"
 #include "control.h"
 
@@ -223,7 +223,7 @@ BOOL KeybSetKey(
     PSKeyManagement pTable,
     PBYTE           pbyBSSID,
     DWORD           dwKeyIndex,
-    unsigned long           uKeyLength,
+	u32 uKeyLength,
     PQWORD          pKeyRSC,
     PBYTE           pbyKey,
     BYTE            byKeyDecMode
@@ -235,7 +235,8 @@ BOOL KeybSetKey(
     PSKeyItem   pKey;
     unsigned int        uKeyIdx;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetKey: %lX\n", dwKeyIndex);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+		"Enter KeybSetKey: %X\n", dwKeyIndex);
 
     j = (MAX_KEY_TABLE-1);
     for (i=0;i<(MAX_KEY_TABLE-1);i++) {
@@ -261,7 +262,9 @@ BOOL KeybSetKey(
                 if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
                     // Group transmit key
                     pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex;
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+				"Group transmit key(R)[%X]: %d\n",
+					pTable->KeyTable[i].dwGTKeyIndex, i);
                 }
                 pTable->KeyTable[i].wKeyCtl &= 0xFF0F;          // clear group key control filed
                 pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4);
@@ -302,9 +305,12 @@ BOOL KeybSetKey(
             }
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n");
 
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n ",
+			pKey->dwTSC47_16);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ",
+			pKey->wTSC15_0);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n ",
+			pKey->dwKeyIndex);
 
             return (TRUE);
         }
@@ -326,7 +332,9 @@ BOOL KeybSetKey(
             if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
                 // Group transmit key
                 pTable->KeyTable[j].dwGTKeyIndex = dwKeyIndex;
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(N)[%lX]: %d\n", pTable->KeyTable[j].dwGTKeyIndex, j);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+			"Group transmit key(N)[%X]: %d\n",
+				pTable->KeyTable[j].dwGTKeyIndex, j);
             }
             pTable->KeyTable[j].wKeyCtl &= 0xFF0F;          // clear group key control filed
             pTable->KeyTable[j].wKeyCtl |= (byKeyDecMode << 4);
@@ -367,9 +375,11 @@ BOOL KeybSetKey(
         }
         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n");
 
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n ",
+		pKey->dwTSC47_16);
         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n ",
+		pKey->dwKeyIndex);
 
         return (TRUE);
     }
@@ -597,7 +607,8 @@ BOOL KeybGetTransmitKey(PSKeyManagement pTable, PBYTE pbyBSSID, DWORD dwKeyType,
                             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x ", pTable->KeyTable[i].abyBSSID[ii]);
                         }
                         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n");
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwGTKeyIndex: %lX\n", pTable->KeyTable[i].dwGTKeyIndex);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwGTKeyIndex: %X\n",
+				pTable->KeyTable[i].dwGTKeyIndex);
 
                     return (TRUE);
                 }
@@ -664,7 +675,7 @@ BOOL KeybSetDefaultKey(
     void *pDeviceHandler,
     PSKeyManagement pTable,
     DWORD           dwKeyIndex,
-    unsigned long           uKeyLength,
+	u32 uKeyLength,
     PQWORD          pKeyRSC,
     PBYTE           pbyKey,
     BYTE            byKeyDecMode
@@ -696,7 +707,10 @@ BOOL KeybSetDefaultKey(
     if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
         // Group transmit key
         pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = dwKeyIndex;
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, MAX_KEY_TABLE-1);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+		"Group transmit key(R)[%X]: %d\n",
+		pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex,
+		MAX_KEY_TABLE-1);
 
     }
     pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl &= 0x7F00;          // clear all key control filed
@@ -747,9 +761,11 @@ BOOL KeybSetDefaultKey(
     }
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n");
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n", pKey->dwTSC47_16);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n",
+		pKey->dwTSC47_16);
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n", pKey->wTSC15_0);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n", pKey->dwKeyIndex);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n",
+		pKey->dwKeyIndex);
 
     return (TRUE);
 }
@@ -775,7 +791,7 @@ BOOL KeybSetAllGroupKey(
     void *pDeviceHandler,
     PSKeyManagement pTable,
     DWORD           dwKeyIndex,
-    unsigned long           uKeyLength,
+	u32 uKeyLength,
     PQWORD          pKeyRSC,
     PBYTE           pbyKey,
     BYTE            byKeyDecMode
@@ -787,7 +803,8 @@ BOOL KeybSetAllGroupKey(
     PSKeyItem   pKey;
     unsigned int        uKeyIdx;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %lX\n", dwKeyIndex);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %X\n",
+		dwKeyIndex);
 
 
     if ((dwKeyIndex & PAIRWISE_KEY) != 0) {                  // Pairwise key
@@ -804,7 +821,9 @@ BOOL KeybSetAllGroupKey(
             if ((dwKeyIndex & TRANSMIT_KEY) != 0)  {
                 // Group transmit key
                 pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex;
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
+			"Group transmit key(R)[%X]: %d\n",
+			pTable->KeyTable[i].dwGTKeyIndex, i);
 
             }
             pTable->KeyTable[i].wKeyCtl &= 0xFF0F;          // clear group key control filed
diff --git a/drivers/staging/vt6656/key.h b/drivers/staging/vt6656/key.h
index f749c7a..bd35d39 100644
--- a/drivers/staging/vt6656/key.h
+++ b/drivers/staging/vt6656/key.h
@@ -58,7 +58,7 @@
 typedef struct tagSKeyItem
 {
     BOOL        bKeyValid;
-    unsigned long       uKeyLength;
+	u32 uKeyLength;
     BYTE        abyKey[MAX_KEY_LEN];
     QWORD       KeyRSC;
     DWORD       dwTSC47_16;
@@ -107,7 +107,7 @@ BOOL KeybSetKey(
     PSKeyManagement pTable,
     PBYTE           pbyBSSID,
     DWORD           dwKeyIndex,
-    unsigned long           uKeyLength,
+	u32 uKeyLength,
     PQWORD          pKeyRSC,
     PBYTE           pbyKey,
     BYTE            byKeyDecMode
@@ -146,7 +146,7 @@ BOOL KeybSetDefaultKey(
     void *pDeviceHandler,
     PSKeyManagement pTable,
     DWORD           dwKeyIndex,
-    unsigned long           uKeyLength,
+	u32 uKeyLength,
     PQWORD          pKeyRSC,
     PBYTE           pbyKey,
     BYTE            byKeyDecMode
@@ -156,7 +156,7 @@ BOOL KeybSetAllGroupKey(
     void *pDeviceHandler,
     PSKeyManagement pTable,
     DWORD           dwKeyIndex,
-    unsigned long           uKeyLength,
+	u32 uKeyLength,
     PQWORD          pKeyRSC,
     PBYTE           pbyKey,
     BYTE            byKeyDecMode
diff --git a/drivers/staging/vt6656/mac.c b/drivers/staging/vt6656/mac.c
index af4a29d..8fddc7b 100644
--- a/drivers/staging/vt6656/mac.c
+++ b/drivers/staging/vt6656/mac.c
@@ -260,7 +260,8 @@ BYTE            pbyData[24];
     dwData1 <<= 16;
     dwData1 |= MAKEWORD(*(pbyAddr+4), *(pbyAddr+5));
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %lX, KeyCtl:%X\n", wOffset, dwData1, wKeyCtl);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %X,"\
+		" KeyCtl:%X\n", wOffset, dwData1, wKeyCtl);
 
     //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
     //VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
@@ -277,7 +278,8 @@ BYTE            pbyData[24];
     dwData2 <<= 8;
     dwData2 |= *(pbyAddr+0);
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2. wOffset: %d, Data: %lX\n", wOffset, dwData2);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2. wOffset: %d, Data: %X\n",
+		wOffset, dwData2);
 
     //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
     //VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData);
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index ad422de..f33086d 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -61,7 +61,6 @@
 #include "bssdb.h"
 #include "hostap.h"
 #include "wpactl.h"
-#include "ioctl.h"
 #include "iwctl.h"
 #include "dpc.h"
 #include "datarate.h"
@@ -244,7 +243,6 @@ static int Config_FileGetParameter(unsigned char *string,
 				   unsigned char *dest,
 				   unsigned char *source);
 
-static BOOL device_release_WPADEV(PSDevice pDevice);
 
 static void usb_device_reset(PSDevice pDevice);
 
@@ -634,40 +632,6 @@ static BOOL device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType)
     return TRUE;
 }
 
-static BOOL device_release_WPADEV(PSDevice pDevice)
-{
-  viawget_wpa_header *wpahdr;
-  int ii=0;
- // wait_queue_head_t	Set_wait;
-  //send device close to wpa_supplicant layer
-    if (pDevice->bWPADEVUp==TRUE) {
-                 wpahdr = (viawget_wpa_header *)pDevice->skb->data;
-                 wpahdr->type = VIAWGET_DEVICECLOSE_MSG;
-                 wpahdr->resp_ie_len = 0;
-                 wpahdr->req_ie_len = 0;
-                 skb_put(pDevice->skb, sizeof(viawget_wpa_header));
-                 pDevice->skb->dev = pDevice->wpadev;
-		 skb_reset_mac_header(pDevice->skb);
-                 pDevice->skb->pkt_type = PACKET_HOST;
-                 pDevice->skb->protocol = htons(ETH_P_802_2);
-                 memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
-                 netif_rx(pDevice->skb);
-                 pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-
- //wait release WPADEV
-              //    init_waitqueue_head(&Set_wait);
-              //    wait_event_timeout(Set_wait, ((pDevice->wpadev==NULL)&&(pDevice->skb == NULL)),5*HZ);    //1s wait
-              while(pDevice->bWPADEVUp==TRUE) {
-	        set_current_state(TASK_UNINTERRUPTIBLE);
-                 schedule_timeout (HZ/20);          //wait 50ms
-                 ii++;
-	        if(ii>20)
-		  break;
-              }
-           }
-    return TRUE;
-}
-
 #ifdef CONFIG_PM	/* Minimal support for suspend and resume */
 
 static int vt6656_suspend(struct usb_interface *intf, pm_message_t message)
@@ -711,7 +675,7 @@ static const struct net_device_ops device_netdev_ops = {
     .ndo_set_rx_mode	    = device_set_multi,
 };
 
-static int __devinit
+static int
 vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	u8 fake_mac[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
@@ -758,17 +722,6 @@ vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id)
 
 	usb_device_reset(pDevice);
 
-	{
-		union iwreq_data wrqu;
-		memset(&wrqu, 0, sizeof(wrqu));
-		wrqu.data.flags = RT_INSMOD_EVENT_FLAG;
-		wrqu.data.length = IFNAMSIZ;
-		wireless_send_event(pDevice->dev,
-				    IWEVCUSTOM,
-				    &wrqu,
-				    pDevice->dev->name);
-	}
-
 	return 0;
 
 err_netdev:
@@ -991,12 +944,6 @@ BOOL device_alloc_frag_buf(PSDevice pDevice, PSDeFragControlBlock pDeF) {
 static int  device_open(struct net_device *dev) {
     PSDevice    pDevice=(PSDevice) netdev_priv(dev);
 
-     extern SWPAResult wpa_Result;
-     memset(wpa_Result.ifname,0,sizeof(wpa_Result.ifname));
-     wpa_Result.proto = 0;
-     wpa_Result.key_mgmt = 0;
-     wpa_Result.eap_type = 0;
-     wpa_Result.authenticated = FALSE;
      pDevice->fWPA_Authened = FALSE;
 
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " device_open...\n");
@@ -1056,13 +1003,11 @@ static int  device_open(struct net_device *dev) {
     pDevice->bEventAvailable = FALSE;
 
    pDevice->bWPADEVUp = FALSE;
-#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
      pDevice->bwextstep0 = FALSE;
      pDevice->bwextstep1 = FALSE;
      pDevice->bwextstep2 = FALSE;
      pDevice->bwextstep3 = FALSE;
      pDevice->bWPASuppWextEnabled = FALSE;
-#endif
     pDevice->byReAssocCount = 0;
 
     RXvWorkItem(pDevice);
@@ -1096,15 +1041,8 @@ static int  device_open(struct net_device *dev) {
     netif_stop_queue(pDevice->dev);
     pDevice->flags |= DEVICE_FLAGS_OPENED;
 
-{
-  union iwreq_data      wrqu;
-  memset(&wrqu, 0, sizeof(wrqu));
-  wrqu.data.flags = RT_UPDEV_EVENT_FLAG;
-  wireless_send_event(pDevice->dev, IWEVCUSTOM, &wrqu, NULL);
-}
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_open success.. \n");
-    return 0;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_open success..\n");
+	return 0;
 
 free_all:
     device_free_frag_bufs(pDevice);
@@ -1133,19 +1071,11 @@ static int  device_close(struct net_device *dev) {
     if (pDevice == NULL)
         return -ENODEV;
 
-{
-  union iwreq_data      wrqu;
-  memset(&wrqu, 0, sizeof(wrqu));
-  wrqu.data.flags = RT_DOWNDEV_EVENT_FLAG;
-  wireless_send_event(pDevice->dev, IWEVCUSTOM, &wrqu, NULL);
-}
-
     if (pDevice->bLinkPass) {
 	bScheduleCommand((void *) pDevice, WLAN_CMD_DISASSOCIATE, NULL);
         mdelay(30);
     }
 
-device_release_WPADEV(pDevice);
 
         memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
         pMgmt->bShareKeyAlgorithm = FALSE;
@@ -1204,22 +1134,13 @@ device_release_WPADEV(pDevice);
     return 0;
 }
 
-static void __devexit vt6656_disconnect(struct usb_interface *intf)
+static void vt6656_disconnect(struct usb_interface *intf)
 {
 	PSDevice device = usb_get_intfdata(intf);
 
 	if (!device)
 		return;
 
-	{
-		union iwreq_data req;
-		memset(&req, 0, sizeof(req));
-		req.data.flags = RT_RMMOD_EVENT_FLAG;
-		wireless_send_event(device->dev, IWEVCUSTOM, &req, NULL);
-	}
-
-	device_release_WPADEV(device);
-	release_firmware(device->firmware);
 
 	usb_set_intfdata(intf, NULL);
 	usb_put_dev(interface_to_usbdev(intf));
@@ -1228,9 +1149,9 @@ static void __devexit vt6656_disconnect(struct usb_interface *intf)
 
 	if (device->dev) {
 		unregister_netdev(device->dev);
-		wpa_set_wpadev(device, 0);
 		free_netdev(device->dev);
 	}
+
 }
 
 static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev)
@@ -1549,470 +1470,35 @@ static void device_set_multi(struct net_device *dev) {
 
 }
 
-
-static struct net_device_stats *device_get_stats(struct net_device *dev) {
+static struct net_device_stats *device_get_stats(struct net_device *dev)
+{
     PSDevice pDevice=(PSDevice) netdev_priv(dev);
 
     return &pDevice->stats;
 }
 
-
-static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
-	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
-    PSCmdRequest        pReq;
-    //BOOL                bCommit = FALSE;
+static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	PSDevice pDevice = (PSDevice)netdev_priv(dev);
 	struct iwreq *wrq = (struct iwreq *) rq;
-	int                 rc =0;
-
-    if (pMgmt == NULL) {
-        rc = -EFAULT;
-        return rc;
-    }
-
-    switch(cmd) {
-
-	case SIOCGIWNAME:
-		rc = iwctl_giwname(dev, NULL, (char *)&(wrq->u.name), NULL);
-		break;
-
-	case SIOCSIWNWID:
-	case SIOCGIWNWID:     //0x8b03  support
-		rc = -EOPNOTSUPP;
-		break;
-
-		// Set frequency/channel
-	case SIOCSIWFREQ:
-	    rc = iwctl_siwfreq(dev, NULL, &(wrq->u.freq), NULL);
-		break;
-
-		// Get frequency/channel
-	case SIOCGIWFREQ:
-		rc = iwctl_giwfreq(dev, NULL, &(wrq->u.freq), NULL);
-		break;
-
-		// Set desired network name (ESSID)
-	case SIOCSIWESSID:
-
-		{
-			char essid[IW_ESSID_MAX_SIZE+1];
-			if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) {
-				rc = -E2BIG;
-				break;
-			}
-			if (copy_from_user(essid, wrq->u.essid.pointer,
-					   wrq->u.essid.length)) {
-				rc = -EFAULT;
-				break;
-			}
-			rc = iwctl_siwessid(dev, NULL,
-					    &(wrq->u.essid), essid);
-		}
-		break;
-
-
-		// Get current network name (ESSID)
-	case SIOCGIWESSID:
-
-		{
-			char essid[IW_ESSID_MAX_SIZE+1];
-			if (wrq->u.essid.pointer) {
-				iwctl_giwessid(dev, NULL,
-					    &(wrq->u.essid), essid);
-				if (copy_to_user(wrq->u.essid.pointer,
-						         essid,
-						         wrq->u.essid.length) )
-					rc = -EFAULT;
-			}
-		}
-		break;
-
-	case SIOCSIWAP:
-
-		rc = iwctl_siwap(dev, NULL, &(wrq->u.ap_addr), NULL);
-		break;
-
-
-		// Get current Access Point (BSSID)
-	case SIOCGIWAP:
-		rc = iwctl_giwap(dev, NULL, &(wrq->u.ap_addr), NULL);
-		break;
-
-
-		// Set desired station name
-	case SIOCSIWNICKN:
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWNICKN \n");
-        rc = -EOPNOTSUPP;
-		break;
-
-		// Get current station name
-	case SIOCGIWNICKN:
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWNICKN \n");
-        rc = -EOPNOTSUPP;
-		break;
-
-		// Set the desired bit-rate
-	case SIOCSIWRATE:
-		rc = iwctl_siwrate(dev, NULL, &(wrq->u.bitrate), NULL);
-		break;
-
-	// Get the current bit-rate
-	case SIOCGIWRATE:
-		iwctl_giwrate(dev, NULL, &(wrq->u.bitrate), NULL);
-		break;
-
-	// Set the desired RTS threshold
-	case SIOCSIWRTS:
-
-		rc = iwctl_siwrts(dev, &(wrq->u.rts));
-		break;
-
-	// Get the current RTS threshold
-	case SIOCGIWRTS:
-
-		rc = iwctl_giwrts(dev, NULL, &(wrq->u.rts), NULL);
-		break;
-
-		// Set the desired fragmentation threshold
-	case SIOCSIWFRAG:
-
-		rc = iwctl_siwfrag(dev, NULL, &(wrq->u.frag), NULL);
-	    break;
-
-	// Get the current fragmentation threshold
-	case SIOCGIWFRAG:
-
-		rc = iwctl_giwfrag(dev, NULL, &(wrq->u.frag), NULL);
-		break;
-
-		// Set mode of operation
-	case SIOCSIWMODE:
-    	rc = iwctl_siwmode(dev, NULL, &(wrq->u.mode), NULL);
-		break;
-
-		// Get mode of operation
-	case SIOCGIWMODE:
-		iwctl_giwmode(dev, NULL, &(wrq->u.mode), NULL);
-		break;
-
-		// Set WEP keys and mode
-	case SIOCSIWENCODE:
-		{
-            char abyKey[WLAN_WEP232_KEYLEN];
-
-			if (wrq->u.encoding.pointer) {
-
-
-				if (wrq->u.encoding.length > WLAN_WEP232_KEYLEN) {
-					rc = -E2BIG;
-					break;
-				}
-				memset(abyKey, 0, WLAN_WEP232_KEYLEN);
-				if (copy_from_user(abyKey,
-				                  wrq->u.encoding.pointer,
-				                  wrq->u.encoding.length)) {
-					rc = -EFAULT;
-					break;
-				}
-			} else if (wrq->u.encoding.length != 0) {
-				rc = -EINVAL;
-				break;
-			}
-			rc = iwctl_siwencode(dev, NULL, &(wrq->u.encoding), abyKey);
-		}
-		break;
-
-		// Get the WEP keys and mode
-	case SIOCGIWENCODE:
-
-		if (!capable(CAP_NET_ADMIN)) {
-			rc = -EPERM;
-			break;
-		}
-		{
-		    char abyKey[WLAN_WEP232_KEYLEN];
-
-		    rc = iwctl_giwencode(dev, NULL, &(wrq->u.encoding), abyKey);
-		    if (rc != 0) break;
-			if (wrq->u.encoding.pointer) {
-				if (copy_to_user(wrq->u.encoding.pointer,
-						        abyKey,
-						        wrq->u.encoding.length))
-					rc = -EFAULT;
-			}
-		}
-		break;
-
-		// Get the current Tx-Power
-	case SIOCGIWTXPOW:
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWTXPOW \n");
-        rc = -EOPNOTSUPP;
-		break;
-
-	case SIOCSIWTXPOW:
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWTXPOW \n");
-        rc = -EOPNOTSUPP;
-		break;
-
-	case SIOCSIWRETRY:
-
-		rc = iwctl_siwretry(dev, NULL, &(wrq->u.retry), NULL);
-		break;
-
-	case SIOCGIWRETRY:
-
-		rc = iwctl_giwretry(dev, NULL, &(wrq->u.retry), NULL);
-		break;
-
-		// Get range of parameters
-	case SIOCGIWRANGE:
-
-		{
-			struct iw_range range;
-
-			iwctl_giwrange(dev, NULL, &(wrq->u.data), (char *) &range);
-			if (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range)))
-				rc = -EFAULT;
-		}
-
-		break;
-
-	case SIOCGIWPOWER:
-
-		rc = iwctl_giwpower(dev, NULL, &(wrq->u.power), NULL);
-		break;
-
-
-	case SIOCSIWPOWER:
-
-		rc = iwctl_siwpower(dev, NULL, &(wrq->u.power), NULL);
-		break;
-
-
-	case SIOCGIWSENS:
-
-	    rc = iwctl_giwsens(dev, NULL, &(wrq->u.sens), NULL);
-		break;
-
-	case SIOCSIWSENS:
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSENS \n");
-		rc = -EOPNOTSUPP;
-		break;
-
-	case SIOCGIWAPLIST:
-	    {
-            char buffer[IW_MAX_AP * (sizeof(struct sockaddr) + sizeof(struct iw_quality))];
-
-		    if (wrq->u.data.pointer) {
-		        rc = iwctl_giwaplist(dev, NULL, &(wrq->u.data), buffer);
-		        if (rc == 0) {
-                    if (copy_to_user(wrq->u.data.pointer,
-					                buffer,
-					               (wrq->u.data.length * (sizeof(struct sockaddr) +  sizeof(struct iw_quality)))
-				        ))
-				    rc = -EFAULT;
-		        }
-            }
-        }
-		break;
-
-
-#ifdef WIRELESS_SPY
-		// Set the spy list
-	case SIOCSIWSPY:
-
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSPY \n");
-		rc = -EOPNOTSUPP;
-		break;
-
-		// Get the spy list
-	case SIOCGIWSPY:
-
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSPY \n");
-		rc = -EOPNOTSUPP;
-		break;
-
-#endif // WIRELESS_SPY
-
-	case SIOCGIWPRIV:
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWPRIV \n");
-		rc = -EOPNOTSUPP;
-/*
-		if(wrq->u.data.pointer) {
-			wrq->u.data.length = sizeof(iwctl_private_args) / sizeof( iwctl_private_args[0]);
-
-			if(copy_to_user(wrq->u.data.pointer,
-					(u_char *) iwctl_private_args,
-					sizeof(iwctl_private_args)))
-				rc = -EFAULT;
-		}
-*/
-		break;
-
-#ifdef  WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-	case SIOCSIWAUTH:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWAUTH\n");
-		rc = iwctl_siwauth(dev, NULL, &(wrq->u.param), NULL);
-		break;
-
-	case SIOCGIWAUTH:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAUTH \n");
-		rc = iwctl_giwauth(dev, NULL, &(wrq->u.param), NULL);
-		break;
-
-	case SIOCSIWGENIE:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWGENIE \n");
-		rc = iwctl_siwgenie(dev, NULL, &(wrq->u.data), wrq->u.data.pointer);
-		break;
-
-	case SIOCGIWGENIE:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWGENIE \n");
-		rc = iwctl_giwgenie(dev, NULL, &(wrq->u.data), wrq->u.data.pointer);
-		break;
-
-	case SIOCSIWENCODEEXT:
-		{
-			char extra[sizeof(struct iw_encode_ext)+MAX_KEY_LEN+1];
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWENCODEEXT \n");
-			if(wrq->u.encoding.pointer){
-				memset(extra, 0, sizeof(struct iw_encode_ext)+MAX_KEY_LEN+1);
-				if(wrq->u.encoding.length > (sizeof(struct iw_encode_ext)+ MAX_KEY_LEN)){
-					rc = -E2BIG;
-					break;
-				}
-				if(copy_from_user(extra, wrq->u.encoding.pointer,wrq->u.encoding.length)){
-					rc = -EFAULT;
-					break;
-				}
-			}else if(wrq->u.encoding.length != 0){
-				rc = -EINVAL;
-				break;
-			}
-			rc = iwctl_siwencodeext(dev, NULL, &(wrq->u.encoding), extra);
-		}
-		break;
-
-	case SIOCGIWENCODEEXT:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWENCODEEXT \n");
-		rc = iwctl_giwencodeext(dev, NULL, &(wrq->u.encoding), NULL);
-		break;
-
-	case SIOCSIWMLME:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWMLME \n");
-		rc = iwctl_siwmlme(dev, NULL, &(wrq->u.data), wrq->u.data.pointer);
-		break;
-
-#endif // #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-
-    case IOCTL_CMD_TEST:
-
-		if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) {
-		    rc = -EFAULT;
-		    break;
-		} else {
-		    rc = 0;
-		}
-        pReq = (PSCmdRequest)rq;
-
-   //20080130-01,<Remark> by Mike Liu
-      // if(pDevice->bLinkPass==TRUE)
-          pReq->wResult = MAGIC_CODE;         //Linking status:0x3142
-   //20080130-02,<Remark> by Mike Liu
-      //  else
-      //	 pReq->wResult = MAGIC_CODE+1;    //disconnect status:0x3143
-        break;
-
-    case IOCTL_CMD_SET:
-		if (!(pDevice->flags & DEVICE_FLAGS_OPENED) &&
-		       (((PSCmdRequest)rq)->wCmdCode !=WLAN_CMD_SET_WPA))
-		{
-		    rc = -EFAULT;
-		    break;
-		} else {
-		    rc = 0;
-		}
+	int rc = 0;
 
-	    if (test_and_set_bit( 0, (void*)&(pMgmt->uCmdBusy))) {
-		    return -EBUSY;
-	    }
-        rc = private_ioctl(pDevice, rq);
-        clear_bit( 0, (void*)&(pMgmt->uCmdBusy));
-        break;
+	switch (cmd) {
 
-    case IOCTL_CMD_HOSTAPD:
+	case IOCTL_CMD_HOSTAPD:
 
-		if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) {
-		    rc = -EFAULT;
-		    break;
-		} else {
-		    rc = 0;
-		}
+		if (!(pDevice->flags & DEVICE_FLAGS_OPENED))
+			rc = -EFAULT;
 
 		rc = vt6656_hostap_ioctl(pDevice, &wrq->u.data);
-        break;
-
-    case IOCTL_CMD_WPA:
-
-		if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) {
-		    rc = -EFAULT;
-		    break;
-		} else {
-		    rc = 0;
-		}
-
-		rc = wpa_ioctl(pDevice, &wrq->u.data);
-        break;
+		break;
 
 	case SIOCETHTOOL:
-        return ethtool_ioctl(dev, (void *) rq->ifr_data);
-	// All other calls are currently unsupported
-
-	default:
-		rc = -EOPNOTSUPP;
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Ioctl command not supported..%x\n", cmd);
-
-
-    }
-
-    if (pDevice->bCommit) {
-       if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
-           netif_stop_queue(pDevice->dev);
-           spin_lock_irq(&pDevice->lock);
-	bScheduleCommand((void *) pDevice, WLAN_CMD_RUN_AP, NULL);
-           spin_unlock_irq(&pDevice->lock);
-       }
-       else {
-           DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Commit the settings\n");
-           spin_lock_irq(&pDevice->lock);
-//2007-1121-01<Modify>by EinsnLiu
-	    if (pDevice->bLinkPass &&
-		  memcmp(pMgmt->abyCurrSSID,pMgmt->abyDesireSSID,WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN)) {
-		bScheduleCommand((void *) pDevice, WLAN_CMD_DISASSOCIATE, NULL);
-	     } else {
-           pDevice->bLinkPass = FALSE;
-	   pMgmt->eCurrState = WMAC_STATE_IDLE;
-	   memset(pMgmt->abyCurrBSSID, 0, 6);
-		 }
-           ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_SLOW);
-//End Modify
-           netif_stop_queue(pDevice->dev);
-#ifdef  WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-           pMgmt->eScanType = WMAC_SCAN_ACTIVE;
-	   if (!pDevice->bWPASuppWextEnabled)
-#endif
-		bScheduleCommand((void *) pDevice,
-				 WLAN_CMD_BSSID_SCAN,
-				 pMgmt->abyDesireSSID);
-		bScheduleCommand((void *) pDevice,
-				 WLAN_CMD_SSID,
-				 NULL);
-           spin_unlock_irq(&pDevice->lock);
-      }
-      pDevice->bCommit = FALSE;
-    }
+		return ethtool_ioctl(dev, (void *) rq->ifr_data);
 
+	}
 
-    return rc;
+	return rc;
 }
 
 
diff --git a/drivers/staging/vt6656/mib.c b/drivers/staging/vt6656/mib.c
index 8a6ee72..d4c7b0c 100644
--- a/drivers/staging/vt6656/mib.c
+++ b/drivers/staging/vt6656/mib.c
@@ -37,7 +37,6 @@
  *
  */
 
-#include "upc.h"
 #include "mac.h"
 #include "tether.h"
 #include "mib.h"
diff --git a/drivers/staging/vt6656/mib.h b/drivers/staging/vt6656/mib.h
index 82d69a9..85c28e9 100644
--- a/drivers/staging/vt6656/mib.h
+++ b/drivers/staging/vt6656/mib.h
@@ -68,7 +68,6 @@ typedef struct tagSDot11Counters {
     unsigned long long   TKIPLocalMICFailures;
     unsigned long long   TKIPRemoteMICFailures;
     unsigned long long   TKIPICVErrors;
-    unsigned long long   TKIPCounterMeasuresInvoked;
     unsigned long long   TKIPReplays;
     unsigned long long   CCMPFormatErrors;
     unsigned long long   CCMPReplays;
diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c
index 593cdc7..74c0598 100644
--- a/drivers/staging/vt6656/rf.c
+++ b/drivers/staging/vt6656/rf.c
@@ -769,6 +769,9 @@ BYTE    byPwr = pDevice->byCCKPwr;
         return TRUE;
     }
 
+	if (uCH == 0)
+		return -EINVAL;
+
     switch (uRATE) {
     case RATE_1M:
     case RATE_2M:
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 3390838..83c04e1 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -355,7 +355,7 @@ s_vFillTxKey (
         }
         // Append IV after Mac Header
         *pdwIV &= WEP_IV_MASK;//00000000 11111111 11111111 11111111
-        *pdwIV |= (pDevice->byKeyIndex << 30);
+	*pdwIV |= (u32)pDevice->byKeyIndex << 30;
         *pdwIV = cpu_to_le32(*pdwIV);
         pDevice->dwIVCounter++;
         if (pDevice->dwIVCounter > WEP_IV_MASK) {
@@ -375,7 +375,8 @@ s_vFillTxKey (
         *(pbyIVHead+3) = (BYTE)(((pDevice->byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV
         // Append IV&ExtIV after Mac Header
         *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %lx\n", *pdwExtIV);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %x\n",
+		*pdwExtIV);
 
     } else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) {
         pTransmitKey->wTSC15_0++;
@@ -1452,12 +1453,10 @@ s_bPacketToWirelessUsb(
 
 
     pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL;
-    if ((bNeedEncryption) && (pTransmitKey != NULL))  {
-        if (((PSKeyTable) (pTransmitKey->pvKeyTable))->bSoftWEP == TRUE) {
-            // WEP 256
-            bSoftWEP = TRUE;
-        }
-    }
+	if (bNeedEncryption && pTransmitKey->pvKeyTable) {
+		if (((PSKeyTable)&pTransmitKey->pvKeyTable)->bSoftWEP == TRUE)
+			bSoftWEP = TRUE; /* WEP 256 */
+	}
 
     pTxBufHead = (PTX_BUFFER) usbPacketBuf;
     memset(pTxBufHead, 0, sizeof(TX_BUFFER));
@@ -1751,7 +1750,8 @@ s_bPacketToWirelessUsb(
         MIC_vAppend((PBYTE)&(psEthHeader->abyDstAddr[0]), 12);
         dwMIC_Priority = 0;
         MIC_vAppend((PBYTE)&dwMIC_Priority, 4);
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %X, %X\n",
+		dwMICKey0, dwMICKey1);
 
         ///////////////////////////////////////////////////////////////////
 
@@ -2633,7 +2633,8 @@ vDMA0_tx_80211(PSDevice  pDevice, struct sk_buff *skb) {
             MIC_vAppend((PBYTE)&(sEthHeader.abyDstAddr[0]), 12);
             dwMIC_Priority = 0;
             MIC_vAppend((PBYTE)&dwMIC_Priority, 4);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY:"\
+			" %X, %X\n", dwMICKey0, dwMICKey1);
 
             uLength = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen;
 
@@ -2653,7 +2654,8 @@ vDMA0_tx_80211(PSDevice  pDevice, struct sk_buff *skb) {
 
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uLength: %d, %d\n", uLength, cbFrameBodySize);
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderSize, uPadding, cbIVlen);
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lx, %lx\n", *pdwMIC_L, *pdwMIC_R);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%x, %x\n",
+			*pdwMIC_L, *pdwMIC_R);
 
         }
 
@@ -3027,21 +3029,18 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb)
                         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"error: KEY is GTK!!~~\n");
                     }
                     else {
-                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%X]\n",
+				pTransmitKey->dwKeyIndex);
                         bNeedEncryption = TRUE;
                     }
                 }
             }
 
-            if (pDevice->byCntMeasure == 2) {
-                bNeedDeAuth = TRUE;
-                pDevice->s802_11Counter.TKIPCounterMeasuresInvoked++;
-            }
-
             if (pDevice->bEnableHostWEP) {
                 if ((uNodeIndex != 0) &&
                     (pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex & PAIRWISE_KEY)) {
-                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%X]\n",
+				pTransmitKey->dwKeyIndex);
                     bNeedEncryption = TRUE;
                  }
              }
@@ -3050,6 +3049,7 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb)
 
             if (pTransmitKey == NULL) {
                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"return no tx key\n");
+		pContext->bBoolInUse = FALSE;
                 dev_kfree_skb_irq(skb);
                 pStats->tx_dropped++;
                 return STATUS_FAILURE;
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
index f99acf1..dd2198a 100644
--- a/drivers/staging/vt6656/rxtx.h
+++ b/drivers/staging/vt6656/rxtx.h
@@ -61,9 +61,9 @@ typedef struct tagSCTSDataF {
 // MICHDR data header
 //
 typedef struct tagSMICHDR {
-    DWORD   adwHDR0[4];
-    DWORD   adwHDR1[4];
-    DWORD   adwHDR2[4];
+	u32 adwHDR0[4];
+	u32 adwHDR1[4];
+	u32 adwHDR2[4];
 } SMICHDR, *PSMICHDR;
 
 
@@ -630,7 +630,7 @@ typedef struct tagSTX_BUFFER
     BYTE                            byPKTNO;
     WORD                            wTxByteCount;
 
-    DWORD                           adwTxKey[4];
+	u32 adwTxKey[4];
     WORD                            wFIFOCtl;
     WORD                            wTimeStamp;
     WORD                            wFragCtl;
diff --git a/drivers/staging/vt6656/tkip.c b/drivers/staging/vt6656/tkip.c
index 003123e..282c08d 100644
--- a/drivers/staging/vt6656/tkip.c
+++ b/drivers/staging/vt6656/tkip.c
@@ -189,27 +189,25 @@ void TKIPvMixKey(
     PBYTE   pbyRC4Key
     )
 {
-    unsigned int p1k[5];
-//    unsigned int ttak0, ttak1, ttak2, ttak3, ttak4;
-    unsigned int tsc0, tsc1, tsc2;
-    unsigned int ppk0, ppk1, ppk2, ppk3, ppk4, ppk5;
-    unsigned long int pnl,pnh;
-
-    int i, j;
-
-    pnl = wTSC15_0;
-    pnh = dwTSC47_16;
-
-    tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */
-    tsc1 = (unsigned int)(pnh % 65536);
-    tsc2 = (unsigned int)(pnl % 65536); /* lsb */
-
-    /* Phase 1, step 1 */
-    p1k[0] = tsc1;
-    p1k[1] = tsc0;
-    p1k[2] = (unsigned int)(pbyTA[0] + (pbyTA[1]*256));
-    p1k[3] = (unsigned int)(pbyTA[2] + (pbyTA[3]*256));
-    p1k[4] = (unsigned int)(pbyTA[4] + (pbyTA[5]*256));
+	u32 p1k[5];
+	u32 tsc0, tsc1, tsc2;
+	u32 ppk0, ppk1, ppk2, ppk3, ppk4, ppk5;
+	u32 pnl, pnh;
+	int i, j;
+
+	pnl = (u32)wTSC15_0;
+	pnh = (u32)(dwTSC47_16 & 0xffffffff);
+
+	tsc0 = (u32)((pnh >> 16) % 65536); /* msb */
+	tsc1 = (u32)(pnh % 65536);
+	tsc2 = (u32)(pnl % 65536); /* lsb */
+
+	/* Phase 1, step 1 */
+	p1k[0] = tsc1;
+	p1k[1] = tsc0;
+	p1k[2] = (u32)(pbyTA[0] + (pbyTA[1]*256));
+	p1k[3] = (u32)(pbyTA[2] + (pbyTA[3]*256));
+	p1k[4] = (u32)(pbyTA[4] + (pbyTA[5]*256));
 
     /* Phase 1, step 2 */
     for (i=0; i<8; i++) {
diff --git a/drivers/staging/vt6656/ttype.h b/drivers/staging/vt6656/ttype.h
index 8e9450e..dfbf747 100644
--- a/drivers/staging/vt6656/ttype.h
+++ b/drivers/staging/vt6656/ttype.h
@@ -29,6 +29,8 @@
 #ifndef __TTYPE_H__
 #define __TTYPE_H__
 
+#include <linux/types.h>
+
 /******* Common definitions and typedefs ***********************************/
 
 typedef int             BOOL;
@@ -42,17 +44,17 @@ typedef int             BOOL;
 
 /****** Simple typedefs  ***************************************************/
 
-typedef unsigned char   BYTE;           //  8-bit
-typedef unsigned short  WORD;           // 16-bit
-typedef unsigned long   DWORD;          // 32-bit
+typedef u8 BYTE;
+typedef u16 WORD;
+typedef u32 DWORD;
 
 // QWORD is for those situation that we want
 // an 8-byte-aligned 8 byte long structure
 // which is NOT really a floating point number.
 typedef union tagUQuadWord {
     struct {
-        DWORD   dwLowDword;
-        DWORD   dwHighDword;
+	u32 dwLowDword;
+	u32 dwHighDword;
     } u;
     double      DoNotUseThisField;
 } UQuadWord;
@@ -60,8 +62,8 @@ typedef UQuadWord       QWORD;          // 64-bit
 
 /****** Common pointer types ***********************************************/
 
-typedef unsigned long   ULONG_PTR;      // 32-bit
-typedef unsigned long   DWORD_PTR;      // 32-bit
+typedef u32 ULONG_PTR;
+typedef u32 DWORD_PTR;
 
 // boolean pointer
 
diff --git a/drivers/staging/vt6656/upc.h b/drivers/staging/vt6656/upc.h
deleted file mode 100644
index b33aba4..0000000
--- a/drivers/staging/vt6656/upc.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * File: upc.h
- *
- * Purpose: Macros to access device
- *
- * Author: Tevin Chen
- *
- * Date: Mar 17, 1997
- *
- */
-
-#ifndef __UPC_H__
-#define __UPC_H__
-
-#include "device.h"
-#include "ttype.h"
-
-/*---------------------  Export Definitions -------------------------*/
-
-
-//
-//  For IO mapped
-//
-
-#ifdef IO_MAP
-
-#define VNSvInPortB(dwIOAddress, pbyData) {                     \
-	*(pbyData) = inb(dwIOAddress);                              \
-}
-
-
-#define VNSvInPortW(dwIOAddress, pwData) {                      \
-	    *(pwData) = inw(dwIOAddress);                           \
-}
-
-#define VNSvInPortD(dwIOAddress, pdwData) {                     \
-	    *(pdwData) = inl(dwIOAddress);                          \
-}
-
-
-#define VNSvOutPortB(dwIOAddress, byData) {                     \
-        outb(byData, dwIOAddress);                              \
-}
-
-
-#define VNSvOutPortW(dwIOAddress, wData) {                      \
-        outw(wData, dwIOAddress);                               \
-}
-
-#define VNSvOutPortD(dwIOAddress, dwData) {                     \
-        outl(dwData, dwIOAddress);                              \
-}
-
-#else
-
-//
-//  For memory mapped IO
-//
-
-
-#define VNSvInPortB(dwIOAddress, pbyData) {                     \
-	volatile BYTE* pbyAddr = ((PBYTE)(dwIOAddress));            \
-	*(pbyData) = readb(pbyAddr);                           \
-}
-
-
-#define VNSvInPortW(dwIOAddress, pwData) {                      \
-	volatile WORD* pwAddr = ((PWORD)(dwIOAddress));             \
-	*(pwData) = readw(pwAddr);                             \
-}
-
-#define VNSvInPortD(dwIOAddress, pdwData) {                     \
-	volatile DWORD* pdwAddr = ((PDWORD)(dwIOAddress));          \
-	*(pdwData) = readl(pdwAddr);                           \
-}
-
-
-#define VNSvOutPortB(dwIOAddress, byData) {                     \
-    volatile BYTE* pbyAddr = ((PBYTE)(dwIOAddress));            \
-    writeb((BYTE)byData, pbyAddr);							\
-}
-
-
-#define VNSvOutPortW(dwIOAddress, wData) {                      \
-    volatile WORD* pwAddr = ((PWORD)(dwIOAddress));             \
-    writew((WORD)wData, pwAddr);							\
-}
-
-#define VNSvOutPortD(dwIOAddress, dwData) {                     \
-    volatile DWORD* pdwAddr = ((PDWORD)(dwIOAddress));          \
-    writel((DWORD)dwData, pdwAddr);					    \
-}
-
-#endif
-
-
-//
-// ALWAYS IO-Mapped IO when in 16-bit/32-bit environment
-//
-#define PCBvInPortB(dwIOAddress, pbyData) {     \
-	    *(pbyData) = inb(dwIOAddress);          \
-}
-
-#define PCBvInPortW(dwIOAddress, pwData) {      \
-	    *(pwData) = inw(dwIOAddress);           \
-}
-
-#define PCBvInPortD(dwIOAddress, pdwData) {     \
-	    *(pdwData) = inl(dwIOAddress);          \
-}
-
-#define PCBvOutPortB(dwIOAddress, byData) {     \
-        outb(byData, dwIOAddress);              \
-}
-
-#define PCBvOutPortW(dwIOAddress, wData) {      \
-        outw(wData, dwIOAddress);               \
-}
-
-#define PCBvOutPortD(dwIOAddress, dwData) {     \
-        outl(dwData, dwIOAddress);              \
-}
-
-
-#define PCAvDelayByIO(uDelayUnit) {             \
-    BYTE    byData;                             \
-    unsigned long   ii;                                 \
-                                                \
-    if (uDelayUnit <= 50) {                     \
-        udelay(uDelayUnit);                     \
-    }                                           \
-    else {                                      \
-        for (ii = 0; ii < (uDelayUnit); ii++)   \
-		     byData = inb(0x61);				\
-    }                                           \
-}
-
-
-/*---------------------  Export Classes  ----------------------------*/
-
-/*---------------------  Export Variables  --------------------------*/
-
-/*---------------------  Export Functions  --------------------------*/
-
-#endif /* __UPC_H__ */
diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c
index 609e8fa..fc68518 100644
--- a/drivers/staging/vt6656/usbpipe.c
+++ b/drivers/staging/vt6656/usbpipe.c
@@ -575,7 +575,8 @@ s_nsBulkInUsbIoCompleteRead(
 //            MP_SET_FLAG(pDevice, fMP_DISCONNECTED);
 //        }
     } else {
-        bIndicateReceive = TRUE;
+	if (bytesRead)
+		bIndicateReceive = TRUE;
         pDevice->ulBulkInContCRCError = 0;
         pDevice->ulBulkInBytesRead += bytesRead;
 
@@ -660,6 +661,7 @@ PIPEnsSendBulkOut(
     	if (status != 0)
     	{
     		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Tx URB failed %d\n", status);
+		pContext->bBoolInUse = FALSE;
     		return STATUS_FAILURE;
     	}
         return STATUS_PENDING;
diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c
index 586fbe1..22f6b41 100644
--- a/drivers/staging/vt6656/wcmd.c
+++ b/drivers/staging/vt6656/wcmd.c
@@ -316,17 +316,19 @@ s_MgrMakeProbeRequest(
     return pTxPacket;
 }
 
-void vCommandTimerWait(void *hDeviceContext, unsigned int MSecond)
+void vCommandTimerWait(void *hDeviceContext, unsigned long MSecond)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
+	PSDevice pDevice = (PSDevice)hDeviceContext;
 
-    init_timer(&pDevice->sTimerCommand);
-    pDevice->sTimerCommand.data = (unsigned long)pDevice;
-    pDevice->sTimerCommand.function = (TimerFunction)vRunCommand;
-    // RUN_AT :1 msec ~= (HZ/1024)
-    pDevice->sTimerCommand.expires = (unsigned int)RUN_AT((MSecond * HZ) >> 10);
-    add_timer(&pDevice->sTimerCommand);
-    return;
+	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;
 }
 
 void vRunCommand(void *hDeviceContext)
@@ -340,6 +342,7 @@ void vRunCommand(void *hDeviceContext)
     BYTE            byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
     struct sk_buff  *skb;
     BYTE            byData;
+	union iwreq_data wrqu;
 
 
     if (pDevice->dwDiagRefCount != 0)
@@ -501,16 +504,11 @@ void vRunCommand(void *hDeviceContext)
             pMgmt->eScanState = WMAC_NO_SCANNING;
             pDevice->bStopDataPkt = FALSE;
 
-#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
-	if(pMgmt->eScanType == WMAC_SCAN_PASSIVE)
-		{
-			//send scan event to wpa_Supplicant
-				union iwreq_data wrqu;
-				PRINT_K("wireless_send_event--->SIOCGIWSCAN(scan done)\n");
-				memset(&wrqu, 0, sizeof(wrqu));
-				wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL);
-			}
-#endif
+		/*send scan event to wpa_Supplicant*/
+		PRINT_K("wireless_send_event--->SIOCGIWSCAN(scan done)\n");
+		memset(&wrqu, 0, sizeof(wrqu));
+		wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL);
+
             s_bCommandComplete(pDevice);
             break;
 
@@ -523,13 +521,11 @@ void vRunCommand(void *hDeviceContext)
                 return;
             } else {
 
-          #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 		      pDevice->bwextstep0 = FALSE;
                         pDevice->bwextstep1 = FALSE;
                         pDevice->bwextstep2 = FALSE;
                         pDevice->bwextstep3 = FALSE;
 		   pDevice->bWPASuppWextEnabled = FALSE;
-	 #endif
                    pDevice->fWPA_Authened = FALSE;
 
                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send Disassociation Packet..\n");
@@ -672,7 +668,6 @@ void vRunCommand(void *hDeviceContext)
                 }
                 else {
                     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Disconnect SSID none\n");
-                     #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
                     // if(pDevice->bWPASuppWextEnabled == TRUE)
                         {
                   	union iwreq_data  wrqu;
@@ -681,7 +676,6 @@ void vRunCommand(void *hDeviceContext)
                   	PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated:vMgrJoinBSSBegin Fail !!)\n");
                   	wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
                        }
-                    #endif
                 }
             }
             s_bCommandComplete(pDevice);
@@ -924,7 +918,6 @@ void vRunCommand(void *hDeviceContext)
                 // unlock command busy
                         pMgmt->eCurrState = WMAC_STATE_IDLE;
                         pMgmt->sNodeDBTable[0].bActive = FALSE;
-                     #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
                     // if(pDevice->bWPASuppWextEnabled == TRUE)
                         {
                   	union iwreq_data  wrqu;
@@ -933,15 +926,12 @@ void vRunCommand(void *hDeviceContext)
                   	PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated)\n");
                   	wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
                        }
-                    #endif
 	  	}
-	       #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 	               pDevice->bwextstep0 = FALSE;
                         pDevice->bwextstep1 = FALSE;
                         pDevice->bwextstep2 = FALSE;
                         pDevice->bwextstep3 = FALSE;
 		      pDevice->bWPASuppWextEnabled = FALSE;
-		#endif
 	                  //clear current SSID
                   pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
                   pItemSSID->len = 0;
diff --git a/drivers/staging/vt6656/wmgr.c b/drivers/staging/vt6656/wmgr.c
index 7db6a8d..95ddc83 100644
--- a/drivers/staging/vt6656/wmgr.c
+++ b/drivers/staging/vt6656/wmgr.c
@@ -925,7 +925,6 @@ s_vMgrRxAssocResponse(
     WLAN_FR_ASSOCRESP   sFrame;
     PWLAN_IE_SSID   pItemSSID;
     PBYTE   pbyIEs;
-    viawget_wpa_header *wpahdr;
 
 
 
@@ -973,32 +972,7 @@ s_vMgrRxAssocResponse(
             DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "Link with AP(SSID): %s\n", pItemSSID->abySSID);
             pDevice->bLinkPass = TRUE;
             ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER);
-            if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) {
-	       if(skb_tailroom(pDevice->skb) <(sizeof(viawget_wpa_header)+pMgmt->sAssocInfo.AssocInfo.ResponseIELength+
-		   	                                                 pMgmt->sAssocInfo.AssocInfo.RequestIELength)) {    //data room not enough
-                     dev_kfree_skb(pDevice->skb);
-		   pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-	       	}
-                wpahdr = (viawget_wpa_header *)pDevice->skb->data;
-                wpahdr->type = VIAWGET_ASSOC_MSG;
-                wpahdr->resp_ie_len = pMgmt->sAssocInfo.AssocInfo.ResponseIELength;
-                wpahdr->req_ie_len = pMgmt->sAssocInfo.AssocInfo.RequestIELength;
-                memcpy(pDevice->skb->data + sizeof(viawget_wpa_header), pMgmt->sAssocInfo.abyIEs, wpahdr->req_ie_len);
-                memcpy(pDevice->skb->data + sizeof(viawget_wpa_header) + wpahdr->req_ie_len,
-                       pbyIEs,
-                       wpahdr->resp_ie_len
-                       );
-                skb_put(pDevice->skb, sizeof(viawget_wpa_header) + wpahdr->resp_ie_len + wpahdr->req_ie_len);
-                pDevice->skb->dev = pDevice->wpadev;
-		skb_reset_mac_header(pDevice->skb);
-                pDevice->skb->pkt_type = PACKET_HOST;
-                pDevice->skb->protocol = htons(ETH_P_802_2);
-                memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
-                netif_rx(pDevice->skb);
-                pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-            }
 
-#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 	//if(pDevice->bWPASuppWextEnabled == TRUE)
 	   {
 		BYTE buf[512];
@@ -1037,7 +1011,6 @@ s_vMgrRxAssocResponse(
 	wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
 
 	}
-#endif //#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 
         }
         else {
@@ -1053,14 +1026,12 @@ s_vMgrRxAssocResponse(
 
     }
 
-#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 //need clear flags related to Networkmanager
               pDevice->bwextstep0 = FALSE;
               pDevice->bwextstep1 = FALSE;
               pDevice->bwextstep2 = FALSE;
               pDevice->bwextstep3 = FALSE;
               pDevice->bWPASuppWextEnabled = FALSE;
-#endif
 
 if(pMgmt->eCurrState == WMAC_STATE_ASSOC)
       timer_expire(pDevice->sTimerCommand, 0);
@@ -1587,7 +1558,6 @@ s_vMgrRxDisassociation(
     WLAN_FR_DISASSOC    sFrame;
     unsigned int        uNodeIndex = 0;
     CMD_STATUS          CmdStatus;
-    viawget_wpa_header *wpahdr;
 
     if ( pMgmt->eCurrMode == WMAC_MODE_ESS_AP ){
         // if is acting an AP..
@@ -1608,20 +1578,6 @@ s_vMgrRxDisassociation(
         DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP disassociated me, reason=%d.\n", cpu_to_le16(*(sFrame.pwReason)));
 
           pDevice->fWPA_Authened = FALSE;
-	if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) {
-             wpahdr = (viawget_wpa_header *)pDevice->skb->data;
-             wpahdr->type = VIAWGET_DISASSOC_MSG;
-             wpahdr->resp_ie_len = 0;
-             wpahdr->req_ie_len = 0;
-             skb_put(pDevice->skb, sizeof(viawget_wpa_header));
-             pDevice->skb->dev = pDevice->wpadev;
-	     skb_reset_mac_header(pDevice->skb);
-             pDevice->skb->pkt_type = PACKET_HOST;
-             pDevice->skb->protocol = htons(ETH_P_802_2);
-             memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
-             netif_rx(pDevice->skb);
-             pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-         }
 
         //TODO: do something let upper layer know or
         //try to send associate packet again because of inactivity timeout
@@ -1638,7 +1594,6 @@ s_vMgrRxDisassociation(
               }
         }
 
-   #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
   // if(pDevice->bWPASuppWextEnabled == TRUE)
       {
 	union iwreq_data  wrqu;
@@ -1647,7 +1602,6 @@ s_vMgrRxDisassociation(
 	PRINT_K("wireless_send_event--->SIOCGIWAP(disassociated)\n");
 	wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
      }
-  #endif
     }
     /* else, ignore it */
 
@@ -1676,7 +1630,6 @@ s_vMgrRxDeauthentication(
 {
     WLAN_FR_DEAUTHEN    sFrame;
     unsigned int        uNodeIndex = 0;
-    viawget_wpa_header *wpahdr;
 
 
     if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP ){
@@ -1712,22 +1665,6 @@ s_vMgrRxDeauthentication(
                 }
             }
 
-            if ((pDevice->bWPADEVUp) && (pDevice->skb != NULL)) {
-                 wpahdr = (viawget_wpa_header *)pDevice->skb->data;
-                 wpahdr->type = VIAWGET_DISASSOC_MSG;
-                 wpahdr->resp_ie_len = 0;
-                 wpahdr->req_ie_len = 0;
-                 skb_put(pDevice->skb, sizeof(viawget_wpa_header));
-                 pDevice->skb->dev = pDevice->wpadev;
-		 skb_reset_mac_header(pDevice->skb);
-                 pDevice->skb->pkt_type = PACKET_HOST;
-                 pDevice->skb->protocol = htons(ETH_P_802_2);
-                 memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb));
-                 netif_rx(pDevice->skb);
-                 pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-           }
-
-   #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
   // if(pDevice->bWPASuppWextEnabled == TRUE)
       {
 	union iwreq_data  wrqu;
@@ -1736,7 +1673,6 @@ s_vMgrRxDeauthentication(
 	PRINT_K("wireless_send_event--->SIOCGIWAP(disauthen)\n");
 	wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
      }
-  #endif
 
         }
         /* else, ignore it.  TODO: IBSS authentication service
@@ -2645,10 +2581,8 @@ void vMgrJoinBSSBegin(void *hDeviceContext, PCMD_STATUS pStatus)
 */
         }
 
-#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 	//if(pDevice->bWPASuppWextEnabled == TRUE)
             Encyption_Rebuild(pDevice, pCurr);
-#endif
 
         // Infrastructure BSS
         s_vMgrSynchBSS(pDevice,
diff --git a/drivers/staging/vt6656/wmgr.h b/drivers/staging/vt6656/wmgr.h
index 13dfb3b..52b1b56 100644
--- a/drivers/staging/vt6656/wmgr.h
+++ b/drivers/staging/vt6656/wmgr.h
@@ -89,44 +89,44 @@ typedef void (*TimerFunction)(unsigned long);
 
 //+++ NDIS related
 
-typedef unsigned char NDIS_802_11_MAC_ADDRESS[ETH_ALEN];
+typedef u8 NDIS_802_11_MAC_ADDRESS[ETH_ALEN];
 typedef struct _NDIS_802_11_AI_REQFI
 {
-    unsigned short Capabilities;
-    unsigned short ListenInterval;
+	u16 Capabilities;
+	u16 ListenInterval;
     NDIS_802_11_MAC_ADDRESS  CurrentAPAddress;
 } NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI;
 
 typedef struct _NDIS_802_11_AI_RESFI
 {
-    unsigned short Capabilities;
-    unsigned short StatusCode;
-    unsigned short AssociationId;
+	u16 Capabilities;
+	u16 StatusCode;
+	u16 AssociationId;
 } NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI;
 
 typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION
 {
-    unsigned long                   Length;
-    unsigned short                  AvailableRequestFixedIEs;
-    NDIS_802_11_AI_REQFI    RequestFixedIEs;
-    unsigned long                   RequestIELength;
-    unsigned long                   OffsetRequestIEs;
-    unsigned short                  AvailableResponseFixedIEs;
-    NDIS_802_11_AI_RESFI    ResponseFixedIEs;
-    unsigned long                   ResponseIELength;
-    unsigned long                   OffsetResponseIEs;
+	u32 Length;
+	u16 AvailableRequestFixedIEs;
+	NDIS_802_11_AI_REQFI RequestFixedIEs;
+	u32 RequestIELength;
+	u32 OffsetRequestIEs;
+	u16 AvailableResponseFixedIEs;
+	NDIS_802_11_AI_RESFI ResponseFixedIEs;
+	u32 ResponseIELength;
+	u32 OffsetResponseIEs;
 } NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION;
 
 
 
 typedef struct tagSAssocInfo {
-    NDIS_802_11_ASSOCIATION_INFORMATION     AssocInfo;
-    BYTE                                    abyIEs[WLAN_BEACON_FR_MAXLEN+WLAN_BEACON_FR_MAXLEN];
-    // store ReqIEs set by OID_802_11_ASSOCIATION_INFORMATION
-    unsigned long                                   RequestIELength;
-    BYTE                                    abyReqIEs[WLAN_BEACON_FR_MAXLEN];
+	NDIS_802_11_ASSOCIATION_INFORMATION AssocInfo;
+	u8 abyIEs[WLAN_BEACON_FR_MAXLEN+WLAN_BEACON_FR_MAXLEN];
+	/* store ReqIEs set by OID_802_11_ASSOCIATION_INFORMATION */
+	u32 RequestIELength;
+	u8 abyReqIEs[WLAN_BEACON_FR_MAXLEN];
 } SAssocInfo, *PSAssocInfo;
-//---
+
 
 
 
diff --git a/drivers/staging/vt6656/wpa2.c b/drivers/staging/vt6656/wpa2.c
index c092697..616e24d 100644
--- a/drivers/staging/vt6656/wpa2.c
+++ b/drivers/staging/vt6656/wpa2.c
@@ -31,8 +31,8 @@
  *
  */
 
-#include "wpa2.h"
 #include "device.h"
+#include "wpa2.h"
 
 /*---------------------  Static Definitions -------------------------*/
 static int          msglevel                =MSG_LEVEL_INFO;
diff --git a/drivers/staging/vt6656/wpa2.h b/drivers/staging/vt6656/wpa2.h
index 46c2959..c359252 100644
--- a/drivers/staging/vt6656/wpa2.h
+++ b/drivers/staging/vt6656/wpa2.h
@@ -45,8 +45,8 @@ typedef struct tagsPMKIDInfo {
 } PMKIDInfo, *PPMKIDInfo;
 
 typedef struct tagSPMKIDCache {
-    unsigned long       BSSIDInfoCount;
-    PMKIDInfo   BSSIDInfo[MAX_PMKID_CACHE];
+	u32 BSSIDInfoCount;
+	PMKIDInfo BSSIDInfo[MAX_PMKID_CACHE];
 } SPMKIDCache, *PSPMKIDCache;
 
 
diff --git a/drivers/staging/vt6656/wpactl.c b/drivers/staging/vt6656/wpactl.c
index 3e65aa1..cc1d48b 100644
--- a/drivers/staging/vt6656/wpactl.c
+++ b/drivers/staging/vt6656/wpactl.c
@@ -44,13 +44,6 @@
 
 /*---------------------  Static Definitions -------------------------*/
 
-#define VIAWGET_WPA_MAX_BUF_SIZE 1024
-
-static const int frequency_list[] = {
-	2412, 2417, 2422, 2427, 2432, 2437, 2442,
-	2447, 2452, 2457, 2462, 2467, 2472, 2484
-};
-
 /*---------------------  Static Classes  ----------------------------*/
 
 /*---------------------  Static Variables  --------------------------*/
@@ -59,118 +52,7 @@ static int msglevel = MSG_LEVEL_INFO;
 /*---------------------  Static Functions  --------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
-static void wpadev_setup(struct net_device *dev)
-{
-	dev->type               = ARPHRD_IEEE80211;
-	dev->hard_header_len    = ETH_HLEN;
-	dev->mtu                = 2048;
-	dev->addr_len           = ETH_ALEN;
-	dev->tx_queue_len       = 1000;
 
-	memset(dev->broadcast, 0xFF, ETH_ALEN);
-
-	dev->flags              = IFF_BROADCAST | IFF_MULTICAST;
-}
-
-/*
- * Description:
- *      register netdev for wpa supplicant daemon
- *
- * Parameters:
- *  In:
- *      pDevice             -
- *      enable              -
- *  Out:
- *
- * Return Value:
- *
- */
-static int wpa_init_wpadev(PSDevice pDevice)
-{
-	PSDevice wpadev_priv;
-	struct net_device *dev = pDevice->dev;
-	int ret = 0;
-
-	pDevice->wpadev = alloc_netdev(sizeof(PSDevice), "vntwpa", wpadev_setup);
-	if (pDevice->wpadev == NULL)
-		return -ENOMEM;
-
-	wpadev_priv = netdev_priv(pDevice->wpadev);
-	*wpadev_priv = *pDevice;
-	memcpy(pDevice->wpadev->dev_addr, dev->dev_addr, ETH_ALEN);
-	pDevice->wpadev->base_addr = dev->base_addr;
-	pDevice->wpadev->irq = dev->irq;
-	pDevice->wpadev->mem_start = dev->mem_start;
-	pDevice->wpadev->mem_end = dev->mem_end;
-	ret = register_netdev(pDevice->wpadev);
-	if (ret) {
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdev(WPA) failed!\n",
-			dev->name);
-		free_netdev(pDevice->wpadev);
-		return -1;
-	}
-
-	if (pDevice->skb == NULL) {
-		pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
-		if (pDevice->skb == NULL)
-			return -ENOMEM;
-	}
-
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdev %s for WPA management\n",
-		dev->name, pDevice->wpadev->name);
-
-	return 0;
-}
-
-/*
- * Description:
- *      unregister net_device (wpadev)
- *
- * Parameters:
- *  In:
- *      pDevice             -
- *  Out:
- *
- * Return Value:
- *
- */
-static int wpa_release_wpadev(PSDevice pDevice)
-{
-	if (pDevice->skb) {
-		dev_kfree_skb(pDevice->skb);
-		pDevice->skb = NULL;
-	}
-
-	if (pDevice->wpadev) {
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n",
-			pDevice->dev->name, pDevice->wpadev->name);
-		unregister_netdev(pDevice->wpadev);
-		free_netdev(pDevice->wpadev);
-		pDevice->wpadev = NULL;
-	}
-
-	return 0;
-}
-
-/*
- * Description:
- *      Set enable/disable dev for wpa supplicant daemon
- *
- * Parameters:
- *  In:
- *      pDevice             -
- *      val                 -
- *  Out:
- *
- * Return Value:
- *
- */
-int wpa_set_wpadev(PSDevice pDevice, int val)
-{
-	if (val)
-		return wpa_init_wpadev(pDevice);
-	return wpa_release_wpadev(pDevice);
-}
 
 /*
  * Description:
@@ -185,7 +67,7 @@ int wpa_set_wpadev(PSDevice pDevice, int val)
  * Return Value:
  *
  */
- int wpa_set_keys(PSDevice pDevice, void *ctx, BOOL  fcpfkernel)
+int wpa_set_keys(PSDevice pDevice, void *ctx)
 {
 	struct viawget_wpa_param *param = ctx;
 	PSMgmtObject pMgmt = &pDevice->sMgmtObj;
@@ -217,18 +99,7 @@ int wpa_set_wpadev(PSDevice pDevice, int val)
 	if (param->u.wpa_key.key && param->u.wpa_key.key_len > sizeof(abyKey))
 		return -EINVAL;
 
-	spin_unlock_irq(&pDevice->lock);
-	if (param->u.wpa_key.key && fcpfkernel) {
-		memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len);
-	} else {
-		if (param->u.wpa_key.key &&
-			copy_from_user(&abyKey[0], param->u.wpa_key.key,
-				param->u.wpa_key.key_len)) {
-			spin_lock_irq(&pDevice->lock);
-			return -EINVAL;
-		}
-	}
-	spin_lock_irq(&pDevice->lock);
+	memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len);
 
 	dwKeyIndex = (DWORD)(param->u.wpa_key.key_index);
 
@@ -260,18 +131,7 @@ int wpa_set_wpadev(PSDevice pDevice, int val)
 	if (param->u.wpa_key.seq && param->u.wpa_key.seq_len > sizeof(abySeq))
 		return -EINVAL;
 
-	spin_unlock_irq(&pDevice->lock);
-        if (param->u.wpa_key.seq && fcpfkernel) {
-		memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len);
-	} else {
-		if (param->u.wpa_key.seq &&
-			copy_from_user(&abySeq[0], param->u.wpa_key.seq,
-				param->u.wpa_key.seq_len)) {
-			spin_lock_irq(&pDevice->lock);
-			return -EINVAL;
-		}
-	}
-	spin_lock_irq(&pDevice->lock);
+	memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len);
 
 	if (param->u.wpa_key.seq_len > 0) {
 		for (ii = 0 ; ii < param->u.wpa_key.seq_len ; ii++) {
@@ -399,521 +259,3 @@ int wpa_set_wpadev(PSDevice pDevice, int val)
 }
 
 
-/*
- * Description:
- *      enable wpa auth & mode
- *
- * Parameters:
- *  In:
- *      pDevice   -
- *      param     -
- *  Out:
- *
- * Return Value:
- *
- */
-static int wpa_set_wpa(PSDevice pDevice, struct viawget_wpa_param *param)
-{
-	PSMgmtObject pMgmt = &pDevice->sMgmtObj;
-	int ret = 0;
-
-	pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
-	pMgmt->bShareKeyAlgorithm = FALSE;
-
-	return ret;
-}
-
- /*
- * Description:
- *      set disassociate
- *
- * Parameters:
- *  In:
- *      pDevice   -
- *      param     -
- *  Out:
- *
- * Return Value:
- *
- */
-static int wpa_set_disassociate(PSDevice pDevice, struct viawget_wpa_param *param)
-{
-	PSMgmtObject pMgmt = &pDevice->sMgmtObj;
-	int ret = 0;
-
-	spin_lock_irq(&pDevice->lock);
-	if (pDevice->bLinkPass) {
-		if (!memcmp(param->addr, pMgmt->abyCurrBSSID, 6))
-			bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL);
-	}
-	spin_unlock_irq(&pDevice->lock);
-
-	return ret;
-}
-
-/*
- * Description:
- *      enable scan process
- *
- * Parameters:
- *  In:
- *      pDevice   -
- *      param     -
- *  Out:
- *
- * Return Value:
- *
- */
-static int wpa_set_scan(PSDevice pDevice, struct viawget_wpa_param *param)
-{
-	int ret = 0;
-
-/**set ap_scan=1&&scan_ssid=1 under hidden ssid mode**/
-        PSMgmtObject pMgmt = &pDevice->sMgmtObj;
-        PWLAN_IE_SSID pItemSSID;
-	printk("wpa_set_scan-->desired [ssid=%s,ssid_len=%d]\n",
-		param->u.scan_req.ssid,param->u.scan_req.ssid_len);
-// Set the SSID
-	memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-	pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
-	pItemSSID->byElementID = WLAN_EID_SSID;
-	memcpy(pItemSSID->abySSID, param->u.scan_req.ssid, param->u.scan_req.ssid_len);
-	pItemSSID->len = param->u.scan_req.ssid_len;
-
-	spin_lock_irq(&pDevice->lock);
-	BSSvClearBSSList((void *) pDevice, pDevice->bLinkPass);
-	bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN,
-			pMgmt->abyDesireSSID);
-	spin_unlock_irq(&pDevice->lock);
-
-	return ret;
-}
-
-/*
- * Description:
- *      get bssid
- *
- * Parameters:
- *  In:
- *      pDevice   -
- *      param     -
- *  Out:
- *
- * Return Value:
- *
- */
-static int wpa_get_bssid(PSDevice pDevice, struct viawget_wpa_param *param)
-{
-    PSMgmtObject pMgmt = &pDevice->sMgmtObj;
-    int ret = 0;
-    memcpy(param->u.wpa_associate.bssid, pMgmt->abyCurrBSSID, 6);
-
-    return ret;
-}
-
-/*
- * Description:
- *      get bssid
- *
- * Parameters:
- *  In:
- *      pDevice   -
- *      param     -
- *  Out:
- *
- * Return Value:
- *
- */
-static int wpa_get_ssid(PSDevice pDevice, struct viawget_wpa_param *param)
-{
-	PSMgmtObject pMgmt = &pDevice->sMgmtObj;
-	PWLAN_IE_SSID pItemSSID;
-	int ret = 0;
-
-	pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
-
-	memcpy(param->u.wpa_associate.ssid, pItemSSID->abySSID, pItemSSID->len);
-	param->u.wpa_associate.ssid_len = pItemSSID->len;
-
-	return ret;
-}
-
-/*
- * Description:
- *      get scan results
- *
- * Parameters:
- *  In:
- *      pDevice   -
- *      param     -
- *  Out:
- *
- * Return Value:
- *
- */
-static int wpa_get_scan(PSDevice pDevice, struct viawget_wpa_param *param)
-{
-	struct viawget_scan_result *scan_buf;
-	PSMgmtObject pMgmt = &pDevice->sMgmtObj;
-	PWLAN_IE_SSID pItemSSID;
-	PKnownBSS pBSS;
-	PBYTE pBuf;
-	int ret = 0;
-	u16 count = 0;
-	u16 ii;
-	u16 jj;
-	long ldBm; //James //add
-
-//******mike:bubble sort by stronger RSSI*****//
-	PBYTE ptempBSS;
-
-	ptempBSS = kmalloc(sizeof(KnownBSS), GFP_ATOMIC);
-
-	if (ptempBSS == NULL) {
-		printk("bubble sort kmalloc memory fail@@@\n");
-		ret = -ENOMEM;
-		return ret;
-	}
-
-	for (ii = 0; ii < MAX_BSS_NUM; ii++) {
-		for (jj = 0; jj < MAX_BSS_NUM - ii - 1; jj++) {
-			if ((pMgmt->sBSSList[jj].bActive != TRUE)
-				|| ((pMgmt->sBSSList[jj].uRSSI > pMgmt->sBSSList[jj + 1].uRSSI)
-					&& (pMgmt->sBSSList[jj + 1].bActive != FALSE))) {
-				memcpy(ptempBSS,&pMgmt->sBSSList[jj], sizeof(KnownBSS));
-				memcpy(&pMgmt->sBSSList[jj], &pMgmt->sBSSList[jj + 1],
-					sizeof(KnownBSS));
-				memcpy(&pMgmt->sBSSList[jj + 1], ptempBSS, sizeof(KnownBSS));
-			}
-		}
-	}
-	kfree(ptempBSS);
-
-	count = 0;
-	pBSS = &(pMgmt->sBSSList[0]);
-	for (ii = 0; ii < MAX_BSS_NUM; ii++) {
-		pBSS = &(pMgmt->sBSSList[ii]);
-		if (!pBSS->bActive)
-			continue;
-		count++;
-	}
-
-	pBuf = kcalloc(count, sizeof(struct viawget_scan_result), GFP_ATOMIC);
-
-	if (pBuf == NULL) {
-		ret = -ENOMEM;
-		return ret;
-	}
-	scan_buf = (struct viawget_scan_result *)pBuf;
-	pBSS = &(pMgmt->sBSSList[0]);
-	for (ii = 0, jj = 0; ii < MAX_BSS_NUM; ii++) {
-		pBSS = &(pMgmt->sBSSList[ii]);
-		if (pBSS->bActive) {
-			if (jj >= count)
-				break;
-			memcpy(scan_buf->bssid, pBSS->abyBSSID, WLAN_BSSID_LEN);
-			pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
-			memcpy(scan_buf->ssid, pItemSSID->abySSID, pItemSSID->len);
-			scan_buf->ssid_len = pItemSSID->len;
-			scan_buf->freq = frequency_list[pBSS->uChannel-1];
-			scan_buf->caps = pBSS->wCapInfo; // DavidWang for sharemode
-
-			RFvRSSITodBm(pDevice, (BYTE)(pBSS->uRSSI), &ldBm);
-			if (-ldBm < 50)
-				scan_buf->qual = 100;
-			else if (-ldBm > 90)
-				scan_buf->qual = 0;
-			else
-				scan_buf->qual=(40-(-ldBm-50))*100/40;
-
-			//James
-			//scan_buf->caps = pBSS->wCapInfo;
-			//scan_buf->qual =
-			scan_buf->noise = 0;
-			scan_buf->level = ldBm;
-
-			//scan_buf->maxrate =
-			if (pBSS->wWPALen != 0) {
-				scan_buf->wpa_ie_len = pBSS->wWPALen;
-				memcpy(scan_buf->wpa_ie, pBSS->byWPAIE, pBSS->wWPALen);
-			}
-			if (pBSS->wRSNLen != 0) {
-				scan_buf->rsn_ie_len = pBSS->wRSNLen;
-				memcpy(scan_buf->rsn_ie, pBSS->byRSNIE, pBSS->wRSNLen);
-			}
-			scan_buf = (struct viawget_scan_result *)((PBYTE)scan_buf + sizeof(struct viawget_scan_result));
-			jj ++;
-		}
-	}
-
-	if (jj < count)
-		count = jj;
-
-	if (copy_to_user(param->u.scan_results.buf, pBuf, sizeof(struct viawget_scan_result) * count))
-		ret = -EFAULT;
-
-	param->u.scan_results.scan_count = count;
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " param->u.scan_results.scan_count = %d\n", count);
-
-	kfree(pBuf);
-	return ret;
-}
-
-/*
- * Description:
- *      set associate with AP
- *
- * Parameters:
- *  In:
- *      pDevice   -
- *      param     -
- *  Out:
- *
- * Return Value:
- *
- */
-static int wpa_set_associate(PSDevice pDevice, struct viawget_wpa_param *param)
-{
-	PSMgmtObject pMgmt = &pDevice->sMgmtObj;
-	PWLAN_IE_SSID pItemSSID;
-	BYTE abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-	BYTE abyWPAIE[64];
-	int ret = 0;
-	BOOL bwepEnabled=FALSE;
-
-	// set key type & algorithm
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise_suite = %d\n", param->u.wpa_associate.pairwise_suite);
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "group_suite = %d\n", param->u.wpa_associate.group_suite);
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key_mgmt_suite = %d\n", param->u.wpa_associate.key_mgmt_suite);
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "auth_alg = %d\n", param->u.wpa_associate.auth_alg);
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "mode = %d\n", param->u.wpa_associate.mode);
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len);
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Roaming dBm = %d\n", param->u.wpa_associate.roam_dbm); // Davidwang
-
-	if (param->u.wpa_associate.wpa_ie) {
-		if (param->u.wpa_associate.wpa_ie_len > sizeof(abyWPAIE))
-			return -EINVAL;
-
-		if (copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie,
-					param->u.wpa_associate.wpa_ie_len))
-			return -EFAULT;
-	}
-
-	if (param->u.wpa_associate.mode == 1)
-		pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
-	else
-		pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
-
-	// set bssid
-	if (memcmp(param->u.wpa_associate.bssid, &abyNullAddr[0], 6) != 0)
-		memcpy(pMgmt->abyDesireBSSID, param->u.wpa_associate.bssid, 6);
-	// set ssid
-	memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-	pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
-	pItemSSID->byElementID = WLAN_EID_SSID;
-	pItemSSID->len = param->u.wpa_associate.ssid_len;
-	memcpy(pItemSSID->abySSID, param->u.wpa_associate.ssid, pItemSSID->len);
-
-	if (param->u.wpa_associate.wpa_ie_len == 0) {
-		if (param->u.wpa_associate.auth_alg & AUTH_ALG_SHARED_KEY)
-			pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY;
-		else
-			pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
-	} else if (abyWPAIE[0] == RSN_INFO_ELEM) {
-		if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK)
-			pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK;
-		else
-			pMgmt->eAuthenMode = WMAC_AUTH_WPA2;
-	} else {
-		if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_WPA_NONE)
-			pMgmt->eAuthenMode = WMAC_AUTH_WPANONE;
-		else if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK)
-			pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK;
-		else
-			pMgmt->eAuthenMode = WMAC_AUTH_WPA;
-	}
-
-	switch (param->u.wpa_associate.pairwise_suite) {
-	case CIPHER_CCMP:
-		pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
-		break;
-	case CIPHER_TKIP:
-		pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
-		break;
-	case CIPHER_WEP40:
-	case CIPHER_WEP104:
-		pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
-		bwepEnabled = TRUE;
-		break;
-	case CIPHER_NONE:
-		if (param->u.wpa_associate.group_suite == CIPHER_CCMP)
-			pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
-		else
-			pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
-		break;
-	default:
-		pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
-	}
-
-	pMgmt->Roam_dbm = param->u.wpa_associate.roam_dbm;
-	if (pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) { // @wep-sharekey
-		pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
-		pMgmt->bShareKeyAlgorithm = TRUE;
-	} else if (pMgmt->eAuthenMode == WMAC_AUTH_OPEN) {
-		if(bwepEnabled==TRUE) { //@open-wep
-			pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
-	   	} else {
-			// @only open
-			pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
-	   	}
-	}
-	// mike save old encryption status
-	pDevice->eOldEncryptionStatus = pDevice->eEncryptionStatus;
-
-	if (pDevice->eEncryptionStatus !=  Ndis802_11EncryptionDisabled)
-		pDevice->bEncryptionEnable = TRUE;
-	else
-		pDevice->bEncryptionEnable = FALSE;
-
-	if ((pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) ||
-		((pMgmt->eAuthenMode == WMAC_AUTH_OPEN) && (bwepEnabled==TRUE)))  {
-		// mike re-comment:open-wep && sharekey-wep needn't do initial key!!
-	} else {
-		KeyvInitTable(pDevice,&pDevice->sKey);
-	}
-
-	spin_lock_irq(&pDevice->lock);
-	pDevice->bLinkPass = FALSE;
-	ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW);
-	memset(pMgmt->abyCurrBSSID, 0, 6);
-	pMgmt->eCurrState = WMAC_STATE_IDLE;
-	netif_stop_queue(pDevice->dev);
-
-/******* search if ap_scan=2, which is associating request in hidden ssid mode ****/
-	{
-		PKnownBSS pCurr = NULL;
-		pCurr = BSSpSearchBSSList(pDevice,
-					pMgmt->abyDesireBSSID,
-					pMgmt->abyDesireSSID,
-					pDevice->eConfigPHYMode
-			);
-
-		if (pCurr == NULL){
-			printk("wpa_set_associate---->hidden mode site survey before associate.......\n");
-			bScheduleCommand((void *)pDevice,
-					WLAN_CMD_BSSID_SCAN,
-					pMgmt->abyDesireSSID);
-		}
-	}
-/****************************************************************/
-
-	bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL);
-	spin_unlock_irq(&pDevice->lock);
-
-	return ret;
-}
-
-/*
- * Description:
- *      wpa_ioctl main function supported for wpa supplicant
- *
- * Parameters:
- *  In:
- *      pDevice   -
- *      iw_point  -
- *  Out:
- *
- * Return Value:
- *
- */
-int wpa_ioctl(PSDevice pDevice, struct iw_point *p)
-{
-	struct viawget_wpa_param *param;
-	int ret = 0;
-	int wpa_ioctl = 0;
-
-	if (p->length < sizeof(struct viawget_wpa_param) ||
-		p->length > VIAWGET_WPA_MAX_BUF_SIZE || !p->pointer)
-		return -EINVAL;
-
-	param = kmalloc((int)p->length, GFP_KERNEL);
-	if (param == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(param, p->pointer, p->length)) {
-		ret = -EFAULT;
-		goto out;
-	}
-
-	switch (param->cmd) {
-	case VIAWGET_SET_WPA:
-		ret = wpa_set_wpa(pDevice, param);
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_WPA \n");
-		break;
-
-	case VIAWGET_SET_KEY:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_KEY \n");
-		spin_lock_irq(&pDevice->lock);
-		ret = wpa_set_keys(pDevice, param, FALSE);
-		spin_unlock_irq(&pDevice->lock);
-		break;
-
-	case VIAWGET_SET_SCAN:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_SCAN \n");
-		ret = wpa_set_scan(pDevice, param);
-		break;
-
-	case VIAWGET_GET_SCAN:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SCAN\n");
-		ret = wpa_get_scan(pDevice, param);
-		wpa_ioctl = 1;
-		break;
-
-	case VIAWGET_GET_SSID:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SSID \n");
-		ret = wpa_get_ssid(pDevice, param);
-		wpa_ioctl = 1;
-		break;
-
-	case VIAWGET_GET_BSSID:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_BSSID \n");
-		ret = wpa_get_bssid(pDevice, param);
-		wpa_ioctl = 1;
-		break;
-
-	case VIAWGET_SET_ASSOCIATE:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_ASSOCIATE \n");
-		ret = wpa_set_associate(pDevice, param);
-		break;
-
-	case VIAWGET_SET_DISASSOCIATE:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DISASSOCIATE \n");
-		ret = wpa_set_disassociate(pDevice, param);
-		break;
-
-	case VIAWGET_SET_DROP_UNENCRYPT:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DROP_UNENCRYPT \n");
-		break;
-
-	case VIAWGET_SET_DEAUTHENTICATE:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DEAUTHENTICATE \n");
-		break;
-
-	default:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ioctl: unknown cmd=%d\n",
-			param->cmd);
-		kfree(param);
-		return -EOPNOTSUPP;
-	}
-
-	if ((ret == 0) && wpa_ioctl) {
-		if (copy_to_user(p->pointer, param, p->length)) {
-			ret = -EFAULT;
-			goto out;
-		}
-	}
-
-out:
-	kfree(param);
-	return ret;
-}
diff --git a/drivers/staging/vt6656/wpactl.h b/drivers/staging/vt6656/wpactl.h
index 00c8451..b4ec6b0 100644
--- a/drivers/staging/vt6656/wpactl.h
+++ b/drivers/staging/vt6656/wpactl.h
@@ -30,9 +30,7 @@
 #define __WPACTL_H__
 
 #include "device.h"
-#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
 #include "iowpa.h"
-#endif
 
 /*---------------------  Export Definitions -------------------------*/
 
@@ -40,17 +38,11 @@
 //WPA related
 
 typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg;
-typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP,
-	       CIPHER_WEP104 } wpa_cipher;
-typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
-	       KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE, KEY_MGMT_CCKM } wpa_key_mgmt;//20080717-02,<Modify> by James Li
 
 #define AUTH_ALG_OPEN_SYSTEM	0x01
 #define AUTH_ALG_SHARED_KEY	0x02
 #define AUTH_ALG_LEAP		0x04
 
-#define GENERIC_INFO_ELEM 0xdd
-#define RSN_INFO_ELEM 0x30
 
 typedef unsigned long long NDIS_802_11_KEY_RSC;
 
@@ -60,8 +52,6 @@ typedef unsigned long long NDIS_802_11_KEY_RSC;
 
 /*---------------------  Export Functions  --------------------------*/
 
-int wpa_set_wpadev(PSDevice pDevice, int val);
-int wpa_ioctl(PSDevice pDevice, struct iw_point *p);
-int wpa_set_keys(PSDevice pDevice, void *ctx, BOOL  fcpfkernel);
+int wpa_set_keys(PSDevice pDevice, void *ctx);
 
 #endif /* __WPACL_H__ */
diff --git a/drivers/staging/winbond/mds.c b/drivers/staging/winbond/mds.c
index 1b8b8ac..faa93f0 100644
--- a/drivers/staging/winbond/mds.c
+++ b/drivers/staging/winbond/mds.c
@@ -315,7 +315,7 @@ static void Mds_HeaderCopy(struct wbsoft_priv *adapter, struct wb35_descriptor *
 
 	pT00->T00_tx_packet_id = pDes->Descriptor_ID; /* Set packet ID */
 	pT00->T00_header_length = 24; /* Set header length */
-	pT01->T01_retry_abort_ebable = 1; /* 921013 931130.5.h */
+	pT01->T01_retry_abort_enable = 1; /* 921013 931130.5.h */
 
 	/* Key ID setup */
 	pT01->T01_wep_id = 0;
@@ -476,11 +476,8 @@ Mds_Tx(struct wbsoft_priv *adapter)
 			/* 931130.5.b */
 			FragmentCount = PacketSize/FragmentThreshold + 1;
 			stmp = PacketSize + FragmentCount*32 + 8; /* 931130.5.c 8:MIC */
-			if ((XmitBufSize + stmp) >= MAX_USB_TX_BUFFER) {
-				printk("[Mds_Tx] Excess max tx buffer.\n");
+			if ((XmitBufSize + stmp) >= MAX_USB_TX_BUFFER)
 				break; /* buffer is not enough */
-			}
-
 
 			/*
 			 * Start transmitting
diff --git a/drivers/staging/winbond/wb35rx_f.h b/drivers/staging/winbond/wb35rx_f.h
index 1fdf65e..559bdca 100644
--- a/drivers/staging/winbond/wb35rx_f.h
+++ b/drivers/staging/winbond/wb35rx_f.h
@@ -4,12 +4,12 @@
 #include <net/mac80211.h>
 #include "wbhal.h"
 
-//====================================
-// Interface function declare
-//====================================
-unsigned char		Wb35Rx_initial(  struct hw_data * pHwData );
-void		Wb35Rx_destroy(  struct hw_data * pHwData );
-void		Wb35Rx_stop(  struct hw_data * pHwData );
+/*
+ * Interface function declaration
+ */
+unsigned char	Wb35Rx_initial(struct hw_data *pHwData);
+void		Wb35Rx_destroy(struct hw_data *pHwData);
+void		Wb35Rx_stop(struct hw_data *pHwData);
 void		Wb35Rx_start(struct ieee80211_hw *hw);
 
 #endif
diff --git a/drivers/staging/winbond/wb35rx_s.h b/drivers/staging/winbond/wb35rx_s.h
index 4b03274..545bc95 100644
--- a/drivers/staging/winbond/wb35rx_s.h
+++ b/drivers/staging/winbond/wb35rx_s.h
@@ -1,44 +1,44 @@
-//============================================================================
-// wb35rx.h --
-//============================================================================
+#ifndef __WINBOND_35RX_S_H
+#define __WINBOND_35RX_S_H
 
-// Definition for this module used
-#define MAX_USB_RX_BUFFER	4096	// This parameter must be 4096 931130.4.f
+/* Definition for this module used */
+#define MAX_USB_RX_BUFFER		4096	/* This parameter must be 4096 931130.4.f */
+#define MAX_USB_RX_BUFFER_NUMBER	ETHERNET_RX_DESCRIPTORS	/* Maximum 254, 255 is RESERVED ID */
+#define RX_INTERFACE			0	/* Interface 1 */
+#define RX_PIPE				2	/* Pipe 3 */
+#define MAX_PACKET_SIZE			1600	/* 1568	= 8 + 1532 + 4 + 24(IV EIV MIC ICV CRC) for check DMA data 931130.4.g */
+#define RX_END_TAG			0x0badbeef
 
-#define MAX_USB_RX_BUFFER_NUMBER	ETHERNET_RX_DESCRIPTORS		// Maximum 254, 255 is RESERVED ID
-#define RX_INTERFACE				0	// Interface 1
-#define RX_PIPE						2	// Pipe 3
-#define MAX_PACKET_SIZE				1600 //1568	// 8 + 1532 + 4 + 24(IV EIV MIC ICV CRC) for check DMA data 931130.4.g
-#define RX_END_TAG					0x0badbeef
 
-
-//====================================
-// Internal variable for module
-//====================================
+/*
+ * Internal variable for module
+ */
 struct wb35_rx {
-	u32			ByteReceived;// For calculating throughput of BulkIn
-	atomic_t		RxFireCounter;// Does Wb35Rx module fire?
+	u32		ByteReceived; /* For calculating throughput of BulkIn */
+	atomic_t	RxFireCounter;/* Does Wb35Rx module fire? */
 
-	u8	RxBuffer[ MAX_USB_RX_BUFFER_NUMBER ][ ((MAX_USB_RX_BUFFER+3) & ~0x03 ) ];
-	u16	RxBufferSize[ ((MAX_USB_RX_BUFFER_NUMBER+1) & ~0x01) ];
-	u8	RxOwner[ ((MAX_USB_RX_BUFFER_NUMBER+3) & ~0x03 ) ];//Ownership of buffer  0: SW 1:HW
+	u8		RxBuffer[MAX_USB_RX_BUFFER_NUMBER][((MAX_USB_RX_BUFFER+3) & ~0x03)];
+	u16		RxBufferSize[((MAX_USB_RX_BUFFER_NUMBER+1) & ~0x01)];
+	u8		RxOwner[((MAX_USB_RX_BUFFER_NUMBER+3) & ~0x03)]; /* Ownership of buffer  0:SW 1:HW */
 
-	u32	RxProcessIndex;//The next index to process
-	u32	RxBufferId;
-	u32	EP3vm_state;
+	u32		RxProcessIndex; /* The next index to process */
+	u32		RxBufferId;
+	u32		EP3vm_state;
 
-	u32	rx_halt; // For VM stopping
+	u32		rx_halt; /* For VM stopping */
 
-	u16	MoreDataSize;
-	u16	PacketSize;
+	u16		MoreDataSize;
+	u16		PacketSize;
 
-	u32	CurrentRxBufferId; // For complete routine usage
-	u32	Rx3UrbCancel;
+	u32		CurrentRxBufferId; /* For complete routine usage */
+	u32		Rx3UrbCancel;
 
-	u32	LastR1; // For RSSI reporting
-	struct urb *				RxUrb;
-	u32		Ep3ErrorCount2; // 20060625.1 Usbd for Rx DMA error count
+	u32		LastR1; /* For RSSI reporting */
+	struct urb	*RxUrb;
+	u32		Ep3ErrorCount2; /* 20060625.1 Usbd for Rx DMA error count */
 
 	int		EP3VM_status;
-	u8 *	pDRx;
+	u8		*pDRx;
 };
+
+#endif /* __WINBOND_35RX_S_H */
diff --git a/drivers/staging/winbond/wbhal.h b/drivers/staging/winbond/wbhal.h
index 39e84a0..289ee54 100644
--- a/drivers/staging/winbond/wbhal.h
+++ b/drivers/staging/winbond/wbhal.h
@@ -226,11 +226,11 @@ struct T01_descriptor {
 			u32	T01_add_challenge_text:1;
 			u32	T01_inhibit_crc:1;
 			u32	T01_loop_back_wep_mode:1;
-			u32	T01_retry_abort_ebable:1;
+			u32	T01_retry_abort_enable:1;
 		};
 #else
 		struct {
-			u32	T01_retry_abort_ebable:1;
+			u32	T01_retry_abort_enable:1;
 			u32	T01_loop_back_wep_mode:1;
 			u32	T01_inhibit_crc:1;
 			u32	T01_add_challenge_text:1;
diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c
index 48aa136..3fa1ae4 100644
--- a/drivers/staging/winbond/wbusb.c
+++ b/drivers/staging/winbond/wbusb.c
@@ -79,18 +79,15 @@ static int wbsoft_add_interface(struct ieee80211_hw *dev,
 static void wbsoft_remove_interface(struct ieee80211_hw *dev,
 				    struct ieee80211_vif *vif)
 {
-	printk("wbsoft_remove interface called\n");
 }
 
 static void wbsoft_stop(struct ieee80211_hw *hw)
 {
-	printk(KERN_INFO "%s called\n", __func__);
 }
 
 static int wbsoft_get_stats(struct ieee80211_hw *hw,
 			    struct ieee80211_low_level_stats *stats)
 {
-	printk(KERN_INFO "%s called\n", __func__);
 	return 0;
 }
 
@@ -179,12 +176,9 @@ static void hal_set_current_channel_ex(struct hw_data *pHwData, struct chan_info
 	if (pHwData->SurpriseRemove)
 		return;
 
-	printk("Going to channel: %d/%d\n", channel.band, channel.ChanNo);
-
 	RFSynthesizer_SwitchingChannel(pHwData, channel); /* Switch channel */
 	pHwData->Channel = channel.ChanNo;
 	pHwData->band = channel.band;
-	pr_debug("Set channel is %d, band =%d\n", pHwData->Channel, pHwData->band);
 	reg->M28_MacControl &= ~0xff;	/* Clean channel information field */
 	reg->M28_MacControl |= channel.ChanNo;
 	Wb35Reg_WriteWithCallbackValue(pHwData, 0x0828, reg->M28_MacControl,
@@ -264,8 +258,6 @@ static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
 	struct wbsoft_priv *priv = dev->priv;
 	struct chan_info ch;
 
-	printk("wbsoft_config called\n");
-
 	/* Should use channel_num, or something, as that is already pre-translated */
 	ch.band = 1;
 	ch.ChanNo = 1;
@@ -282,7 +274,6 @@ static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
 
 static u64 wbsoft_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif)
 {
-	printk("wbsoft_get_tsf called\n");
 	return 0;
 }
 
@@ -716,7 +707,6 @@ static int wb35_hw_init(struct ieee80211_hw *hw)
 	}
 
 	priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData);
-	pr_debug("Driver init, antenna no = %d\n", priv->sLocalPara.bAntennaNo);
 	hal_get_hw_radio_off(pHwData);
 
 	/* Waiting for HAL setting OK */
@@ -782,9 +772,6 @@ static int wb35_probe(struct usb_interface *intf,
 	interface = intf->cur_altsetting;
 	endpoint = &interface->endpoint[0].desc;
 
-	if (endpoint[2].wMaxPacketSize == 512)
-		printk("[w35und] Working on USB 2.0\n");
-
 	err = wb35_hw_init(dev);
 	if (err)
 		goto error_free_hw;
@@ -836,7 +823,6 @@ static void wb35_hw_halt(struct wbsoft_priv *adapter)
 {
 	/* Turn off Rx and Tx hardware ability */
 	hal_stop(&adapter->sHwData);
-	pr_debug("[w35und] Hal_stop O.K.\n");
 	/* Waiting Irp completed */
 	msleep(100);
 
diff --git a/drivers/staging/wlags49_h2/ap_h2.c b/drivers/staging/wlags49_h2/ap_h2.c
index eb8244c..e524153 100644
--- a/drivers/staging/wlags49_h2/ap_h2.c
+++ b/drivers/staging/wlags49_h2/ap_h2.c
@@ -25,10 +25,10 @@
  */
 
 
-#include "hcfcfg.h"				/* to get hcf_16 etc defined as well as */
+#include "hcfcfg.h"			/* to get hcf_16 etc defined as well as */
 					/* possible settings which inluence mdd.h or dhf.h */
-#include "mdd.h"   				/* to get COMP_ID_STA etc defined */
-#include "dhf.h"   				/* used to be "fhfmem.h", to get memblock,plugrecord, */
+#include "mdd.h"			/* to get COMP_ID_STA etc defined */
+#include "dhf.h"			/* used to be "fhfmem.h", to get memblock,plugrecord, */
 
 static const hcf_8 fw_image_1_data[] = {
 	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -3301,7 +3301,7 @@ static const CFG_RANGE20_STRCT fw_image_infocompat[] = {
 		COMP_ROLE_SUPL,
 		COMP_ID_APF,
 		{
-			{ 2, 2, 4 }  				/* variant, bottom, top */
+			{ 2, 2, 4 }				/* variant, bottom, top */
 		}
 	},
 	{	3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)),
@@ -3309,9 +3309,9 @@ static const CFG_RANGE20_STRCT fw_image_infocompat[] = {
 		COMP_ROLE_ACT,
 		COMP_ID_MFI,
 		{
-			{ 4, 6, 7 }, 				/* variant, bottom, top */
-			{ 5, 6, 7 }, 				/* variant, bottom, top */
-			{ 6, 6, 7 }  				/* variant, bottom, top */
+			{ 4, 6, 7 },				/* variant, bottom, top */
+			{ 5, 6, 7 },				/* variant, bottom, top */
+			{ 6, 6, 7 }				/* variant, bottom, top */
 		}
 	},
 	{	3 + ((20 * sizeof(CFG_RANGE_SPEC_STRCT)) / sizeof(hcf_16)),
@@ -3319,7 +3319,7 @@ static const CFG_RANGE20_STRCT fw_image_infocompat[] = {
 		COMP_ROLE_ACT,
 		COMP_ID_CFI,
 		{
-			{ 2, 1, 2 }  				/* variant, bottom, top */
+			{ 2, 1, 2 }				/* variant, bottom, top */
 		}
 	},
 	{ 0000, 0000, 0000, 0000, { { 0000, 0000, 0000 } } }			/* endsentinel */
diff --git a/drivers/staging/wlags49_h2/man/wlags49.4 b/drivers/staging/wlags49_h2/man/wlags49.4
index a345885..37df998 100644
--- a/drivers/staging/wlags49_h2/man/wlags49.4
+++ b/drivers/staging/wlags49_h2/man/wlags49.4
@@ -108,7 +108,7 @@ with the I/O base address and MAC address used by the card.
  \- Card power management
  \- Support for Hermes-II & Hermes-II.5 based PCMCIA, Mini PCI, and CardBus cards
  \- Wired Equivalent Privacy (WEP)
- \- WPA-PSK support (EXPERIMENTAL)
+ \- WPA-PSK support
  \- Driver utility interface (UIL)
  \- Wireless Extensions
  \- Software AP mode
diff --git a/drivers/staging/wlags49_h2/wl_if.h b/drivers/staging/wlags49_h2/wl_if.h
index 6d66dab..425d373 100644
--- a/drivers/staging/wlags49_h2/wl_if.h
+++ b/drivers/staging/wlags49_h2/wl_if.h
@@ -71,45 +71,39 @@
 #define MAX_LTV_BUF_SIZE            (512 - (sizeof(hcf_16) * 2))
 
 #define HCF_TALLIES_SIZE            (sizeof(CFG_HERMES_TALLIES_STRCT) + \
-                                     (sizeof(hcf_16) * 2))
+				    (sizeof(hcf_16) * 2))
 
 #define HCF_MAX_MULTICAST           16
 #define HCF_MAX_NAME_LEN            32
-#define MAX_LINE_SIZE   			256
+#define MAX_LINE_SIZE               256
 #define HCF_NUM_IO_PORTS            0x80
 #define TX_TIMEOUT                  ((800 * HZ) / 1000)
 
 
-//#define HCF_MIN_COMM_QUALITY        0
-//#define HCF_MAX_COMM_QUALITY        92
-//#define HCF_MIN_SIGNAL_LEVEL        47
-//#define HCF_MAX_SIGNAL_LEVEL        138
-//#define HCF_MIN_NOISE_LEVEL         47
-//#define HCF_MAX_NOISE_LEVEL         138
-//#define HCF_0DBM_OFFSET             149
-
-// PE1DNN
-// Better data from the real world. Not scientific but empirical data gathered
-// from a Thomson Speedtouch 110 which is identified as:
-// PCMCIA Info: "Agere Systems" "Wireless PC Card Model 0110"
-//              Manufacture ID: 0156,0003
-// Lowest measurment for noise floor seen is value 54
-// Highest signal strength in close proximity to the AP seen is value 118
-// Very good must be around 100 (otherwise its never "full scale"
-// All other constants are derrived from these. This makes the signal gauge
-// work for me...
+/* PE1DNN
+ * Better data from the real world. Not scientific but empirical data gathered
+ * from a Thomson Speedtouch 110 which is identified as:
+ * PCMCIA Info: "Agere Systems" "Wireless PC Card Model 0110"
+ *              Manufacture ID: 0156,0003
+ * Lowest measurment for noise floor seen is value 54
+ * Highest signal strength in close proximity to the AP seen is value 118
+ * Very good must be around 100 (otherwise its never "full scale"
+ * All other constants are derrived from these. This makes the signal gauge
+ * work for me...
+ */
 #define HCF_MIN_SIGNAL_LEVEL        54
 #define HCF_MAX_SIGNAL_LEVEL        100
 #define HCF_MIN_NOISE_LEVEL         HCF_MIN_SIGNAL_LEVEL
 #define HCF_MAX_NOISE_LEVEL         HCF_MAX_SIGNAL_LEVEL
 #define HCF_0DBM_OFFSET             (HCF_MAX_SIGNAL_LEVEL + 1)
 #define HCF_MIN_COMM_QUALITY        0
-#define HCF_MAX_COMM_QUALITY        (HCF_MAX_SIGNAL_LEVEL - HCF_MIN_NOISE_LEVEL + 1)
+#define HCF_MAX_COMM_QUALITY        (HCF_MAX_SIGNAL_LEVEL - \
+					HCF_MIN_NOISE_LEVEL + 1)
 
 
 /* For encryption (WEP) */
-#define MIN_KEY_SIZE                5       // 40 bits RC4 - WEP
-#define MAX_KEY_SIZE                13      // 104 bits
+#define MIN_KEY_SIZE                5       /* 40 bits RC4 - WEP */
+#define MAX_KEY_SIZE                13      /* 104 bits */
 #define MAX_KEYS                    4
 
 #define RADIO_CHANNELS              14
@@ -121,12 +115,12 @@
 #define MAX_RTS_BYTES               2347
 
 #define MAX_RATES                   8
-#define MEGABIT                     1024*1024
+#define MEGABIT                     (1024 * 1024)
 
 #define HCF_FAILURE                 0xFF
 #define UIL_FAILURE		            0xFF
-#define CFG_UIL_CONNECT             0xA123          // Define differently?
-#define CFG_UIL_CONNECT_ACK_CODE    0x5653435A      // VSCZ
+#define CFG_UIL_CONNECT             0xA123          /* Define differently? */
+#define CFG_UIL_CONNECT_ACK_CODE    0x5653435A      /* VSCZ */
 #define WVLAN2_UIL_CONNECTED        (0x01L << 0)
 #define WVLAN2_UIL_BUSY             (0x01L << 1)
 
@@ -154,15 +148,15 @@ UIL_FUN_GET_INFO
 UIL_FUN_PUT_INFO
 */
 
-#define SIOCSIWNETNAME              SIOCDEVPRIVATE+1
-#define SIOCGIWNETNAME              SIOCDEVPRIVATE+2
-#define SIOCSIWSTANAME              SIOCDEVPRIVATE+3
-#define SIOCGIWSTANAME              SIOCDEVPRIVATE+4
-#define SIOCSIWPORTTYPE             SIOCDEVPRIVATE+5
-#define SIOCGIWPORTTYPE             SIOCDEVPRIVATE+6
+#define SIOCSIWNETNAME              (SIOCDEVPRIVATE + 1)
+#define SIOCGIWNETNAME              (SIOCDEVPRIVATE + 2)
+#define SIOCSIWSTANAME              (SIOCDEVPRIVATE + 3)
+#define SIOCGIWSTANAME              (SIOCDEVPRIVATE + 4)
+#define SIOCSIWPORTTYPE             (SIOCDEVPRIVATE + 5)
+#define SIOCGIWPORTTYPE             (SIOCDEVPRIVATE + 6)
 
 /* IOCTL code for the RTS interface */
-#define WL_IOCTL_RTS                SIOCDEVPRIVATE+7
+#define WL_IOCTL_RTS                (SIOCDEVPRIVATE + 7)
 
 /* IOCTL subcodes for WL_IOCTL_RTS */
 #define WL_IOCTL_RTS_READ           1
@@ -174,61 +168,54 @@ UIL_FUN_PUT_INFO
 /*******************************************************************************
  * STRUCTURE DEFINITIONS
  ******************************************************************************/
-typedef struct
-{
-    __u16   length;
-    __u8    name[HCF_MAX_NAME_LEN];
+typedef struct {
+	__u16   length;
+	__u8    name[HCF_MAX_NAME_LEN];
 }
 wvName_t;
 
 
-typedef struct
-{
-    hcf_16      len;
-    hcf_16      typ;
-    union
-    {
-        hcf_8       u8[MAX_LTV_BUF_SIZE / sizeof(hcf_8)];
-        hcf_16      u16[MAX_LTV_BUF_SIZE / sizeof(hcf_16)];
-        hcf_32      u32[MAX_LTV_BUF_SIZE / sizeof(hcf_32)];
-    } u;
+typedef struct {
+	hcf_16      len;
+	hcf_16      typ;
+	union {
+		hcf_8       u8[MAX_LTV_BUF_SIZE / sizeof(hcf_8)];
+		hcf_16      u16[MAX_LTV_BUF_SIZE / sizeof(hcf_16)];
+		hcf_32      u32[MAX_LTV_BUF_SIZE / sizeof(hcf_32)];
+	} u;
 }
 ltv_t;
 
 
-struct uilreq
-{
-    union
-    {
-        char    ifrn_name[IFNAMSIZ];
-    } ifr_ifrn;
+struct uilreq {
+	union {
+		char    ifrn_name[IFNAMSIZ];
+	} ifr_ifrn;
 
-    IFBP        hcfCtx;
-    __u8        command;
-    __u8        result;
+	IFBP        hcfCtx;
+	__u8        command;
+	__u8        result;
 
-    /* The data field in this structure is typically an LTV of some type. The
-       len field is the size of the buffer in bytes, as opposed to words (like
-       the L-field in the LTV */
-    __u16       len;
-    void       *data;
+	/* The data field in this structure is typically an LTV of some type.
+	   The len field is the size of the buffer in bytes, as opposed to words
+	   (like the L-field in the LTV */
+	__u16       len;
+	void       *data;
 };
 
 
-struct rtsreq
-{
-    union
-    {
-        char    ifrn_name[IFNAMSIZ];
-    }
-    ifr_ifrn;
+struct rtsreq {
+	union {
+		char    ifrn_name[IFNAMSIZ];
+	}
+	ifr_ifrn;
 
-    __u16   typ;
-    __u16   reg;
-    __u16   len;
-    __u16   *data;
+	__u16   typ;
+	__u16   reg;
+	__u16   len;
+	__u16   *data;
 };
 
 
-#endif  // __WAVELAN2_IF_H__
+#endif  /* __WAVELAN2_IF_H__ */
 
diff --git a/drivers/staging/wlags49_h2/wl_pci.c b/drivers/staging/wlags49_h2/wl_pci.c
index a09c3ac..6226e5e 100644
--- a/drivers/staging/wlags49_h2/wl_pci.c
+++ b/drivers/staging/wlags49_h2/wl_pci.c
@@ -111,7 +111,7 @@ extern dbg_info_t *DbgInfo;
 #endif  // DBG
 
 /* define the PCI device Table Cardname and id tables */
-static struct pci_device_id wl_pci_tbl[] __devinitdata = {
+static struct pci_device_id wl_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_0), },
 	{ PCI_DEVICE(PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_1), },
 	{ PCI_DEVICE(PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_2), },
@@ -124,9 +124,9 @@ MODULE_DEVICE_TABLE(pci, wl_pci_tbl);
 /*******************************************************************************
  * function prototypes
  ******************************************************************************/
-int __devinit wl_pci_probe( struct pci_dev *pdev,
+int wl_pci_probe( struct pci_dev *pdev,
                                 const struct pci_device_id *ent );
-void __devexit wl_pci_remove(struct pci_dev *pdev);
+void wl_pci_remove(struct pci_dev *pdev);
 int wl_pci_setup( struct pci_dev *pdev );
 void wl_pci_enable_cardbus_interrupts( struct pci_dev *pdev );
 
@@ -160,14 +160,13 @@ void wl_pci_dma_hcf_reclaim_rx( struct wl_private *lp );
 /*******************************************************************************
  * PCI module function registration
  ******************************************************************************/
-static struct pci_driver wl_driver =
-{
-	name:		MODULE_NAME,
-    id_table:	wl_pci_tbl,
-	probe:		wl_pci_probe,
-	remove:		__devexit_p(wl_pci_remove),
-    suspend:    NULL,
-    resume:     NULL,
+static struct pci_driver wl_driver = {
+	.name	  = MODULE_NAME,
+	.id_table = wl_pci_tbl,
+	.probe	  = wl_pci_probe,
+	.remove	  = wl_pci_remove,
+	.suspend  = NULL,
+	.resume	  = NULL
 };
 
 /*******************************************************************************
@@ -399,7 +398,7 @@ int wl_adapter_is_open( struct net_device *dev )
  *      errno value otherwise
  *
  ******************************************************************************/
-int __devinit wl_pci_probe( struct pci_dev *pdev,
+int wl_pci_probe( struct pci_dev *pdev,
                                 const struct pci_device_id *ent )
 {
     int result;
@@ -436,7 +435,7 @@ int __devinit wl_pci_probe( struct pci_dev *pdev,
  *      N/A
  *
  ******************************************************************************/
-void __devexit wl_pci_remove(struct pci_dev *pdev)
+void wl_pci_remove(struct pci_dev *pdev)
 {
     struct net_device       *dev = NULL;
     /*------------------------------------------------------------------------*/
diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c
index f180c3d..c1a8cb6 100644
--- a/drivers/staging/wlan-ng/hfa384x_usb.c
+++ b/drivers/staging/wlan-ng/hfa384x_usb.c
@@ -171,11 +171,11 @@ static void hfa384x_ctlxout_callback(struct urb *urb);
 static void hfa384x_usbin_callback(struct urb *urb);
 
 static void
-hfa384x_usbin_txcompl(wlandevice_t *wlandev, hfa384x_usbin_t * usbin);
+hfa384x_usbin_txcompl(wlandevice_t *wlandev, hfa384x_usbin_t *usbin);
 
 static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb);
 
-static void hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t * usbin);
+static void hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin);
 
 static void
 hfa384x_usbout_tx(wlandevice_t *wlandev, hfa384x_usbout_t *usbout);
@@ -285,7 +285,7 @@ static inline const char *ctlxstr(CTLX_STATE s)
 	return ctlx_str[s];
 };
 
-static inline hfa384x_usbctlx_t *get_active_ctlx(hfa384x_t * hw)
+static inline hfa384x_usbctlx_t *get_active_ctlx(hfa384x_t *hw)
 {
 	return list_entry(hw->ctlxq.active.next, hfa384x_usbctlx_t, list);
 }
diff --git a/drivers/staging/xgifb/TODO b/drivers/staging/xgifb/TODO
index 13d9bc2..392b29d 100644
--- a/drivers/staging/xgifb/TODO
+++ b/drivers/staging/xgifb/TODO
@@ -1,4 +1,4 @@
-This drivers still need a lot of work. I can list all cleanups to do but it's
+This drivers still needs a lot of work. I can list all cleanups to do but it's
 going to be long. So, I'm writing "cleanups" and not the list.
 
 Arnaud
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
index f775c54..e0f745d 100644
--- a/drivers/staging/xgifb/XGI_main_26.c
+++ b/drivers/staging/xgifb/XGI_main_26.c
@@ -73,9 +73,9 @@ static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
 	RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
 			ModeIdIndex, XGI_Pr);
 
-	ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+	ClockIndex = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
 
-	Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000;
+	Clock = XGI_VCLKData[ClockIndex].CLOCK * 1000;
 
 	return Clock;
 }
@@ -101,35 +101,35 @@ static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
 		return 0;
 	RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
 			ModeIdIndex, XGI_Pr);
-	index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+	index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
 
-	sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
+	sr_data = XGI_CRT1Table[index].CR[5];
 
-	cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
+	cr_data = XGI_CRT1Table[index].CR[0];
 
 	/* Horizontal total */
 	HT = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8);
 	A = HT + 5;
 
-	HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) - 1;
+	HDE = (XGI330_RefIndex[RefreshRateTableIndex].XRes >> 3) - 1;
 	E = HDE + 1;
 
-	cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
+	cr_data = XGI_CRT1Table[index].CR[3];
 
 	/* Horizontal retrace (=sync) start */
 	HRS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0xC0) << 2);
 	F = HRS - E - 3;
 
-	cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
+	cr_data = XGI_CRT1Table[index].CR[1];
 
 	/* Horizontal blank start */
 	HBS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x30) << 4);
 
-	sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
+	sr_data = XGI_CRT1Table[index].CR[6];
 
-	cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
+	cr_data = XGI_CRT1Table[index].CR[2];
 
-	cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
+	cr_data2 = XGI_CRT1Table[index].CR[4];
 
 	/* Horizontal blank end */
 	HBE = (cr_data & 0x1f) | ((unsigned short) (cr_data2 & 0x80) >> 2)
@@ -150,11 +150,11 @@ static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
 	*right_margin = F * 8;
 	*hsync_len = C * 8;
 
-	sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
+	sr_data = XGI_CRT1Table[index].CR[14];
 
-	cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
+	cr_data = XGI_CRT1Table[index].CR[8];
 
-	cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
+	cr_data2 = XGI_CRT1Table[index].CR[9];
 
 	/* Vertical total */
 	VT = (cr_data & 0xFF) | ((unsigned short) (cr_data2 & 0x01) << 8)
@@ -162,10 +162,10 @@ static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
 			| ((unsigned short) (sr_data & 0x01) << 10);
 	A = VT + 2;
 
-	VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes - 1;
+	VDE = XGI330_RefIndex[RefreshRateTableIndex].YRes - 1;
 	E = VDE + 1;
 
-	cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
+	cr_data = XGI_CRT1Table[index].CR[10];
 
 	/* Vertical retrace (=sync) start */
 	VRS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x04) << 6)
@@ -173,23 +173,23 @@ static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
 			| ((unsigned short) (sr_data & 0x08) << 7);
 	F = VRS + 1 - E;
 
-	cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
+	cr_data = XGI_CRT1Table[index].CR[12];
 
-	cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
+	cr_data3 = (XGI_CRT1Table[index].CR[14] & 0x80) << 5;
 
 	/* Vertical blank start */
 	VBS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x08) << 5)
 			| ((unsigned short) (cr_data3 & 0x20) << 4)
 			| ((unsigned short) (sr_data & 0x04) << 8);
 
-	cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
+	cr_data = XGI_CRT1Table[index].CR[13];
 
 	/* Vertical blank end */
 	VBE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x10) << 4);
 	temp = VBE - ((E - 1) & 511);
 	B = (temp > 0) ? temp : (temp + 512);
 
-	cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
+	cr_data = XGI_CRT1Table[index].CR[11];
 
 	/* Vertical retrace (=sync) end */
 	VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
@@ -202,25 +202,25 @@ static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
 	*lower_margin = F;
 	*vsync_len = C;
 
-	if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
+	if (XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
 		*sync &= ~FB_SYNC_VERT_HIGH_ACT;
 	else
 		*sync |= FB_SYNC_VERT_HIGH_ACT;
 
-	if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
+	if (XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
 		*sync &= ~FB_SYNC_HOR_HIGH_ACT;
 	else
 		*sync |= FB_SYNC_HOR_HIGH_ACT;
 
 	*vmode = FB_VMODE_NONINTERLACED;
-	if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
+	if (XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
 		*vmode = FB_VMODE_INTERLACED;
 	else {
 		j = 0;
-		while (XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
-			if (XGI_Pr->EModeIDTable[j].Ext_ModeID ==
-			    XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
-				if (XGI_Pr->EModeIDTable[j].Ext_ModeFlag &
+		while (XGI330_EModeIDTable[j].Ext_ModeID != 0xff) {
+			if (XGI330_EModeIDTable[j].Ext_ModeID ==
+			    XGI330_RefIndex[RefreshRateTableIndex].ModeID) {
+				if (XGI330_EModeIDTable[j].Ext_ModeFlag &
 				    DoubleScanMode) {
 					*vmode = FB_VMODE_DOUBLE;
 				}
@@ -1695,7 +1695,7 @@ static int __init XGIfb_setup(char *options)
 	return 0;
 }
 
-static int __devinit xgifb_probe(struct pci_dev *pdev,
+static int xgifb_probe(struct pci_dev *pdev,
 		const struct pci_device_id *ent)
 {
 	u8 reg, reg1;
@@ -2103,7 +2103,7 @@ error:
 /*                PCI DEVICE HANDLING                */
 /*****************************************************/
 
-static void __devexit xgifb_remove(struct pci_dev *pdev)
+static void xgifb_remove(struct pci_dev *pdev)
 {
 	struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
 	struct fb_info *fb_info = xgifb_info->fb_info;
@@ -2127,7 +2127,7 @@ static struct pci_driver xgifb_driver = {
 	.name = "xgifb",
 	.id_table = xgifb_pci_table,
 	.probe = xgifb_probe,
-	.remove = __devexit_p(xgifb_remove)
+	.remove = xgifb_remove
 };
 
 
diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h
index 77137e4..148f637 100644
--- a/drivers/staging/xgifb/vb_def.h
+++ b/drivers/staging/xgifb/vb_def.h
@@ -254,9 +254,16 @@
 #define XGI330_SR1F 0
 #define XGI330_SR23 0xf6
 #define XGI330_SR24 0x0d
-#define XGI330_SR25 0
 #define XGI330_SR31 0xc0
 #define XGI330_SR32 0x11
 #define XGI330_SR33 0
 
+extern const struct XGI_ExtStruct XGI330_EModeIDTable[];
+extern const struct XGI_Ext2Struct XGI330_RefIndex[];
+extern const struct XGI_CRT1TableStruct XGI_CRT1Table[];
+extern const struct XGI_ECLKDataStruct XGI340_ECLKData[];
+extern const struct SiS_VCLKData XGI_VCLKData[];
+extern const unsigned char XGI340_CR6B[][4];
+extern const unsigned char XGI340_AGPReg[];
+
 #endif
diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
index 7739dbd..2b791c1 100644
--- a/drivers/staging/xgifb/vb_init.c
+++ b/drivers/staging/xgifb/vb_init.c
@@ -94,8 +94,8 @@ static void XGINew_DDR1x_MRS_340(unsigned long P3c4,
 		      0x18,
 		      pVBInfo->SR15[2][pVBInfo->ram_type]); /* SR18 */
 	xgifb_reg_set(P3c4, 0x19, 0x01);
-	xgifb_reg_set(P3c4, 0x16, pVBInfo->SR16[0]);
-	xgifb_reg_set(P3c4, 0x16, pVBInfo->SR16[1]);
+	xgifb_reg_set(P3c4, 0x16, 0x03);
+	xgifb_reg_set(P3c4, 0x16, 0x83);
 	mdelay(1);
 	xgifb_reg_set(P3c4, 0x1B, 0x03);
 	udelay(500);
@@ -103,8 +103,8 @@ static void XGINew_DDR1x_MRS_340(unsigned long P3c4,
 		      0x18,
 		      pVBInfo->SR15[2][pVBInfo->ram_type]); /* SR18 */
 	xgifb_reg_set(P3c4, 0x19, 0x00);
-	xgifb_reg_set(P3c4, 0x16, pVBInfo->SR16[2]);
-	xgifb_reg_set(P3c4, 0x16, pVBInfo->SR16[3]);
+	xgifb_reg_set(P3c4, 0x16, 0x03);
+	xgifb_reg_set(P3c4, 0x16, 0x83);
 	xgifb_reg_set(P3c4, 0x1B, 0x00);
 }
 
@@ -124,13 +124,13 @@ static void XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension,
 
 	xgifb_reg_set(pVBInfo->P3c4,
 		      0x2E,
-		      pVBInfo->ECLKData[pVBInfo->ram_type].SR2E);
+		      XGI340_ECLKData[pVBInfo->ram_type].SR2E);
 	xgifb_reg_set(pVBInfo->P3c4,
 		      0x2F,
-		      pVBInfo->ECLKData[pVBInfo->ram_type].SR2F);
+		      XGI340_ECLKData[pVBInfo->ram_type].SR2F);
 	xgifb_reg_set(pVBInfo->P3c4,
 		      0x30,
-		      pVBInfo->ECLKData[pVBInfo->ram_type].SR30);
+		      XGI340_ECLKData[pVBInfo->ram_type].SR30);
 
 	/* When XG42 ECLK = MCLK = 207MHz, Set SR32 D[1:0] = 10b */
 	/* Modify SR32 value, when MCLK=207MHZ, ELCK=250MHz,
@@ -138,10 +138,10 @@ static void XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension,
 	if (HwDeviceExtension->jChipType == XG42) {
 		if ((pVBInfo->MCLKData[pVBInfo->ram_type].SR28 == 0x1C) &&
 		    (pVBInfo->MCLKData[pVBInfo->ram_type].SR29 == 0x01) &&
-		    (((pVBInfo->ECLKData[pVBInfo->ram_type].SR2E == 0x1C) &&
-		      (pVBInfo->ECLKData[pVBInfo->ram_type].SR2F == 0x01)) ||
-		     ((pVBInfo->ECLKData[pVBInfo->ram_type].SR2E == 0x22) &&
-		      (pVBInfo->ECLKData[pVBInfo->ram_type].SR2F == 0x01))))
+		    (((XGI340_ECLKData[pVBInfo->ram_type].SR2E == 0x1C) &&
+		      (XGI340_ECLKData[pVBInfo->ram_type].SR2F == 0x01)) ||
+		     ((XGI340_ECLKData[pVBInfo->ram_type].SR2E == 0x22) &&
+		      (XGI340_ECLKData[pVBInfo->ram_type].SR2F == 0x01))))
 			xgifb_reg_set(pVBInfo->P3c4,
 				      0x32,
 				      ((unsigned char) xgifb_reg_get(
@@ -429,7 +429,7 @@ static void XGINew_SetDRAMDefaultRegister340(
 	temp2 = 0;
 	for (i = 0; i < 4; i++) {
 		/* CR6B DQS fine tune delay */
-		temp = pVBInfo->CR6B[pVBInfo->ram_type][i];
+		temp = XGI340_CR6B[pVBInfo->ram_type][i];
 		for (j = 0; j < 4; j++) {
 			temp1 = ((temp >> (2 * j)) & 0x03) << 2;
 			temp2 |= temp1;
@@ -444,7 +444,7 @@ static void XGINew_SetDRAMDefaultRegister340(
 	temp2 = 0;
 	for (i = 0; i < 4; i++) {
 		/* CR6E DQM fine tune delay */
-		temp = pVBInfo->CR6E[pVBInfo->ram_type][i];
+		temp = 0;
 		for (j = 0; j < 4; j++) {
 			temp1 = ((temp >> (2 * j)) & 0x03) << 2;
 			temp2 |= temp1;
@@ -463,7 +463,7 @@ static void XGINew_SetDRAMDefaultRegister340(
 		temp2 = 0;
 		for (i = 0; i < 8; i++) {
 			/* CR6F DQ fine tune delay */
-			temp = pVBInfo->CR6F[pVBInfo->ram_type][8 * k + i];
+			temp = 0;
 			for (j = 0; j < 4; j++) {
 				temp1 = (temp >> (2 * j)) & 0x03;
 				temp2 |= temp1;
@@ -486,7 +486,7 @@ static void XGINew_SetDRAMDefaultRegister340(
 
 	temp2 = 0x80;
 	/* CR89 terminator type select */
-	temp = pVBInfo->CR89[pVBInfo->ram_type][0];
+	temp = 0;
 	for (j = 0; j < 4; j++) {
 		temp1 = (temp >> (2 * j)) & 0x03;
 		temp2 |= temp1;
@@ -496,7 +496,7 @@ static void XGINew_SetDRAMDefaultRegister340(
 		temp2 += 0x10;
 	}
 
-	temp = pVBInfo->CR89[pVBInfo->ram_type][1];
+	temp = 0;
 	temp1 = temp & 0x03;
 	temp2 |= temp1;
 	xgifb_reg_set(P3d4, 0x89, temp2);
@@ -1378,17 +1378,17 @@ unsigned char XGIInitNew(struct pci_dev *pdev)
 		for (i = 0x47; i <= 0x4C; i++)
 			xgifb_reg_set(pVBInfo->P3d4,
 				      i,
-				      pVBInfo->AGPReg[i - 0x47]);
+				      XGI340_AGPReg[i - 0x47]);
 
 		for (i = 0x70; i <= 0x71; i++)
 			xgifb_reg_set(pVBInfo->P3d4,
 				      i,
-				      pVBInfo->AGPReg[6 + i - 0x70]);
+				      XGI340_AGPReg[6 + i - 0x70]);
 
 		for (i = 0x74; i <= 0x77; i++)
 			xgifb_reg_set(pVBInfo->P3d4,
 				      i,
-				      pVBInfo->AGPReg[8 + i - 0x74]);
+				      XGI340_AGPReg[8 + i - 0x74]);
 
 		pci_read_config_dword(pdev, 0x50, &Temp);
 		Temp >>= 20;
@@ -1401,7 +1401,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev)
 	/* Set PCI */
 	xgifb_reg_set(pVBInfo->P3c4, 0x23, XGI330_SR23);
 	xgifb_reg_set(pVBInfo->P3c4, 0x24, XGI330_SR24);
-	xgifb_reg_set(pVBInfo->P3c4, 0x25, XGI330_SR25);
+	xgifb_reg_set(pVBInfo->P3c4, 0x25, 0);
 
 	if (HwDeviceExtension->jChipType < XG20) {
 		/* Set VB */
@@ -1482,11 +1482,8 @@ unsigned char XGIInitNew(struct pci_dev *pdev)
 
 	XGINew_SetDRAMSize_340(xgifb_info, HwDeviceExtension, pVBInfo);
 
-	xgifb_reg_set(pVBInfo->P3c4,
-		      0x22,
-		      (unsigned char) ((pVBInfo->SR22) & 0xFE));
-
-	xgifb_reg_set(pVBInfo->P3c4, 0x21, pVBInfo->SR21);
+	xgifb_reg_set(pVBInfo->P3c4, 0x22, 0xfa);
+	xgifb_reg_set(pVBInfo->P3c4, 0x21, 0xa3);
 
 	XGINew_ChkSenseStatus(HwDeviceExtension, pVBInfo);
 	XGINew_SetModeScratch(HwDeviceExtension, pVBInfo);
diff --git a/drivers/staging/xgifb/vb_init.h b/drivers/staging/xgifb/vb_init.h
index a27b4fe..d548983 100644
--- a/drivers/staging/xgifb/vb_init.h
+++ b/drivers/staging/xgifb/vb_init.h
@@ -1,6 +1,5 @@
 #ifndef _VBINIT_
 #define _VBINIT_
 extern unsigned char XGIInitNew(struct pci_dev *pdev);
-extern struct XGI21_LVDSCapStruct  XGI21_LCDCapList[13];
 #endif
 
diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
index e95a165..d723a25 100644
--- a/drivers/staging/xgifb/vb_setmode.c
+++ b/drivers/staging/xgifb/vb_setmode.c
@@ -23,18 +23,7 @@ static const unsigned short XGINew_VGA_DAC[] = {
 
 void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
 {
-	pVBInfo->StandTable = &XGI330_StandTable;
-	pVBInfo->EModeIDTable = XGI330_EModeIDTable;
-	pVBInfo->RefIndex = XGI330_RefIndex;
-	pVBInfo->XGINEWUB_CRT1Table = XGI_CRT1Table;
-
 	pVBInfo->MCLKData = XGI340New_MCLKData;
-	pVBInfo->ECLKData = XGI340_ECLKData;
-	pVBInfo->VCLKData = XGI_VCLKData;
-	pVBInfo->VBVCLKData = XGI_VBVCLKData;
-	pVBInfo->ScreenOffset = XGI330_ScreenOffset;
-	pVBInfo->StResInfo = XGI330_StResInfo;
-	pVBInfo->ModeResInfo = XGI330_ModeResInfo;
 
 	pVBInfo->LCDResInfo = 0;
 	pVBInfo->LCDTypeInfo = 0;
@@ -44,19 +33,6 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
 
 	pVBInfo->SR15 = XGI340_SR13;
 	pVBInfo->CR40 = XGI340_cr41;
-	pVBInfo->CR6B = XGI340_CR6B;
-	pVBInfo->CR6E = XGI340_CR6E;
-	pVBInfo->CR6F = XGI340_CR6F;
-	pVBInfo->CR89 = XGI340_CR89;
-	pVBInfo->AGPReg = XGI340_AGPReg;
-	pVBInfo->SR16 = XGI340_SR16;
-
-	pVBInfo->SR21 = 0xa3;
-	pVBInfo->SR22 = 0xfb;
-
-	pVBInfo->TimingH = XGI_TimingH;
-	pVBInfo->TimingV = XGI_TimingV;
-	pVBInfo->UpdateCRT1 = XGI_UpdateCRT1Table;
 
 	/* 310 customization related */
 	if ((pVBInfo->VBType & VB_SIS301LV) || (pVBInfo->VBType & VB_SIS302LV))
@@ -90,10 +66,10 @@ static void XGI_SetSeqRegs(unsigned short ModeNo,
 	unsigned char tempah, SRdata;
 	unsigned short i, modeflag;
 
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
 	xgifb_reg_set(pVBInfo->P3c4, 0x00, 0x03); /* Set SR0 */
-	tempah = pVBInfo->StandTable->SR[0];
+	tempah = XGI330_StandTable.SR[0];
 
 	i = XGI_SetCRT2ToLCDA;
 	if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
@@ -108,7 +84,7 @@ static void XGI_SetSeqRegs(unsigned short ModeNo,
 
 	for (i = 02; i <= 04; i++) {
 		/* Get SR2,3,4 from file */
-		SRdata = pVBInfo->StandTable->SR[i - 1];
+		SRdata = XGI330_StandTable.SR[i - 1];
 		xgifb_reg_set(pVBInfo->P3c4, i, SRdata); /* Set SR2 3 4 */
 	}
 }
@@ -125,7 +101,7 @@ static void XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension,
 
 	for (i = 0; i <= 0x18; i++) {
 		/* Get CRTC from file */
-		CRTCdata = pVBInfo->StandTable->CRTC[i];
+		CRTCdata = XGI330_StandTable.CRTC[i];
 		xgifb_reg_set(pVBInfo->P3d4, i, CRTCdata); /* Set CRTC(3d4) */
 	}
 }
@@ -137,10 +113,10 @@ static void XGI_SetATTRegs(unsigned short ModeNo,
 	unsigned char ARdata;
 	unsigned short i, modeflag;
 
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
 	for (i = 0; i <= 0x13; i++) {
-		ARdata = pVBInfo->StandTable->ATTR[i];
+		ARdata = XGI330_StandTable.ATTR[i];
 
 		if ((modeflag & Charx8Dot) && i == 0x13) { /* ifndef Dot9 */
 			if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
@@ -171,7 +147,7 @@ static void XGI_SetGRCRegs(struct vb_device_info *pVBInfo)
 
 	for (i = 0; i <= 0x08; i++) {
 		/* Get GR from file */
-		GRdata = pVBInfo->StandTable->GRC[i];
+		GRdata = XGI330_StandTable.GRC[i];
 		xgifb_reg_set(pVBInfo->P3ce, i, GRdata); /* Set GR(3ce) */
 	}
 
@@ -194,12 +170,12 @@ static unsigned char XGI_SetDefaultVCLK(struct vb_device_info *pVBInfo)
 {
 
 	xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, 0x20);
-	xgifb_reg_set(pVBInfo->P3c4, 0x2B, pVBInfo->VCLKData[0].SR2B);
-	xgifb_reg_set(pVBInfo->P3c4, 0x2C, pVBInfo->VCLKData[0].SR2C);
+	xgifb_reg_set(pVBInfo->P3c4, 0x2B, XGI_VCLKData[0].SR2B);
+	xgifb_reg_set(pVBInfo->P3c4, 0x2C, XGI_VCLKData[0].SR2C);
 
 	xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, 0x10);
-	xgifb_reg_set(pVBInfo->P3c4, 0x2B, pVBInfo->VCLKData[1].SR2B);
-	xgifb_reg_set(pVBInfo->P3c4, 0x2C, pVBInfo->VCLKData[1].SR2C);
+	xgifb_reg_set(pVBInfo->P3c4, 0x2B, XGI_VCLKData[1].SR2B);
+	xgifb_reg_set(pVBInfo->P3c4, 0x2C, XGI_VCLKData[1].SR2C);
 
 	xgifb_reg_and(pVBInfo->P3c4, 0x31, ~0x30);
 	return 0;
@@ -212,9 +188,9 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo,
 {
 	unsigned short tempax, tempbx, resinfo, modeflag, infoflag;
 
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
-	tempbx = pVBInfo->RefIndex[RefreshRateTableIndex + (*i)].ModeID;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	tempbx = XGI330_RefIndex[RefreshRateTableIndex + (*i)].ModeID;
 	tempax = 0;
 
 	if (pVBInfo->IF_DEF_LVDS == 0) {
@@ -279,9 +255,9 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo,
 		}
 	}
 
-	for (; pVBInfo->RefIndex[RefreshRateTableIndex + (*i)].ModeID ==
+	for (; XGI330_RefIndex[RefreshRateTableIndex + (*i)].ModeID ==
 	       tempbx; (*i)--) {
-		infoflag = pVBInfo->RefIndex[RefreshRateTableIndex + (*i)].
+		infoflag = XGI330_RefIndex[RefreshRateTableIndex + (*i)].
 				Ext_InfoFlag;
 		if (infoflag & tempax)
 			return 1;
@@ -291,9 +267,9 @@ static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo,
 	}
 
 	for ((*i) = 0;; (*i)++) {
-		infoflag = pVBInfo->RefIndex[RefreshRateTableIndex + (*i)].
+		infoflag = XGI330_RefIndex[RefreshRateTableIndex + (*i)].
 				Ext_InfoFlag;
-		if (pVBInfo->RefIndex[RefreshRateTableIndex + (*i)].ModeID
+		if (XGI330_RefIndex[RefreshRateTableIndex + (*i)].ModeID
 				!= tempbx) {
 			return 0;
 		}
@@ -310,7 +286,7 @@ static void XGI_SetSync(unsigned short RefreshRateTableIndex,
 	unsigned short sync, temp;
 
 	/* di+0x00 */
-	sync = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag >> 8;
+	sync = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag >> 8;
 	sync &= 0xC0;
 	temp = 0x2F;
 	temp |= sync;
@@ -328,22 +304,22 @@ static void XGI_SetCRT1Timing_H(struct vb_device_info *pVBInfo,
 	data &= 0x7F;
 	xgifb_reg_set(pVBInfo->P3d4, 0x11, data);
 
-	data = pVBInfo->TimingH[0].data[0];
+	data = pVBInfo->TimingH.data[0];
 	xgifb_reg_set(pVBInfo->P3d4, 0, data);
 
 	for (i = 0x01; i <= 0x04; i++) {
-		data = pVBInfo->TimingH[0].data[i];
+		data = pVBInfo->TimingH.data[i];
 		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 1), data);
 	}
 
 	for (i = 0x05; i <= 0x06; i++) {
-		data = pVBInfo->TimingH[0].data[i];
+		data = pVBInfo->TimingH.data[i];
 		xgifb_reg_set(pVBInfo->P3c4, (unsigned short) (i + 6), data);
 	}
 
 	j = (unsigned char) xgifb_reg_get(pVBInfo->P3c4, 0x0e);
 	j &= 0x1F;
-	data = pVBInfo->TimingH[0].data[7];
+	data = pVBInfo->TimingH.data[7];
 	data &= 0xE0;
 	data |= j;
 	xgifb_reg_set(pVBInfo->P3c4, 0x0e, data);
@@ -385,32 +361,32 @@ static void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex,
 	unsigned short i, j;
 
 	for (i = 0x00; i <= 0x01; i++) {
-		data = pVBInfo->TimingV[0].data[i];
+		data = pVBInfo->TimingV.data[i];
 		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 6), data);
 	}
 
 	for (i = 0x02; i <= 0x03; i++) {
-		data = pVBInfo->TimingV[0].data[i];
+		data = pVBInfo->TimingV.data[i];
 		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 0x0e), data);
 	}
 
 	for (i = 0x04; i <= 0x05; i++) {
-		data = pVBInfo->TimingV[0].data[i];
+		data = pVBInfo->TimingV.data[i];
 		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 0x11), data);
 	}
 
 	j = (unsigned char) xgifb_reg_get(pVBInfo->P3c4, 0x0a);
 	j &= 0xC0;
-	data = pVBInfo->TimingV[0].data[6];
+	data = pVBInfo->TimingV.data[6];
 	data &= 0x3F;
 	data |= j;
 	xgifb_reg_set(pVBInfo->P3c4, 0x0a, data);
 
-	data = pVBInfo->TimingV[0].data[6];
+	data = pVBInfo->TimingV.data[6];
 	data &= 0x80;
 	data = data >> 2;
 
-	i = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	i = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 	i &= DoubleScanMode;
 	if (i)
 		data |= 0x80;
@@ -430,7 +406,7 @@ static void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
 	unsigned short i;
 
 	/* Get index */
-	index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+	index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
 	index = index & IndexMask;
 
 	data = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x11);
@@ -438,12 +414,12 @@ static void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
 	xgifb_reg_set(pVBInfo->P3d4, 0x11, data); /* Unlock CRTC */
 
 	for (i = 0; i < 8; i++)
-		pVBInfo->TimingH[0].data[i]
-				= pVBInfo->XGINEWUB_CRT1Table[index].CR[i];
+		pVBInfo->TimingH.data[i]
+				= XGI_CRT1Table[index].CR[i];
 
 	for (i = 0; i < 7; i++)
-		pVBInfo->TimingV[0].data[i]
-				= pVBInfo->XGINEWUB_CRT1Table[index].CR[i + 8];
+		pVBInfo->TimingV.data[i]
+				= XGI_CRT1Table[index].CR[i + 8];
 
 	XGI_SetCRT1Timing_H(pVBInfo, HwDeviceExtension);
 
@@ -466,23 +442,23 @@ static void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
 	unsigned char index, Tempax, Tempbx, Tempcx, Tempdx;
 	unsigned short Temp1, Temp2, Temp3;
 
-	index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+	index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
 	/* Tempax: CR4 HRS */
-	Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[3];
+	Tempax = XGI_CRT1Table[index].CR[3];
 	Tempcx = Tempax; /* Tempcx: HRS */
 	/* SR2E[7:0]->HRS */
 	xgifb_reg_set(pVBInfo->P3c4, 0x2E, Tempax);
 
-	Tempdx = pVBInfo->XGINEWUB_CRT1Table[index].CR[5]; /* SRB */
+	Tempdx = XGI_CRT1Table[index].CR[5]; /* SRB */
 	Tempdx &= 0xC0; /* Tempdx[7:6]: SRB[7:6] */
 	Temp1 = Tempdx; /* Temp1[7:6]: HRS[9:8] */
 	Temp1 <<= 2; /* Temp1[9:8]: HRS[9:8] */
 	Temp1 |= Tempax; /* Temp1[9:0]: HRS[9:0] */
 
-	Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[4]; /* CR5 HRE */
+	Tempax = XGI_CRT1Table[index].CR[4]; /* CR5 HRE */
 	Tempax &= 0x1F; /* Tempax[4:0]: HRE[4:0] */
 
-	Tempbx = pVBInfo->XGINEWUB_CRT1Table[index].CR[6]; /* SRC */
+	Tempbx = XGI_CRT1Table[index].CR[6]; /* SRC */
 	Tempbx &= 0x04; /* Tempbx[2]: HRE[5] */
 	Tempbx <<= 3; /* Tempbx[5]: HRE[5] */
 	Tempax |= Tempbx; /* Tempax[5:0]: HRE[5:0] */
@@ -504,12 +480,12 @@ static void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
 	xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00);
 
 	/* CR10 VRS */
-	Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[10];
+	Tempax = XGI_CRT1Table[index].CR[10];
 	Tempbx = Tempax; /* Tempbx: VRS */
 	Tempax &= 0x01; /* Tempax[0]: VRS[0] */
 	xgifb_reg_or(pVBInfo->P3c4, 0x33, Tempax); /* SR33[0]->VRS[0] */
 	/* CR7[2][7] VRE */
-	Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[9];
+	Tempax = XGI_CRT1Table[index].CR[9];
 	Tempcx = Tempbx >> 1; /* Tempcx[6:0]: VRS[7:1] */
 	Tempdx = Tempax & 0x04; /* Tempdx[2]: CR7[2] */
 	Tempdx <<= 5; /* Tempdx[7]: VRS[8] */
@@ -523,17 +499,17 @@ static void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
 	Temp2 = Tempax << 2; /* Temp2[9]: VRS[9] */
 	Temp1 |= Temp2; /* Temp1[9:0]: VRS[9:0] */
 	/* Tempax: SRA */
-	Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[14];
+	Tempax = XGI_CRT1Table[index].CR[14];
 	Tempax &= 0x08; /* Tempax[3]: VRS[3] */
 	Temp2 = Tempax;
 	Temp2 <<= 7; /* Temp2[10]: VRS[10] */
 	Temp1 |= Temp2; /* Temp1[10:0]: VRS[10:0] */
 
 	/* Tempax: CR11 VRE */
-	Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[11];
+	Tempax = XGI_CRT1Table[index].CR[11];
 	Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
 	/* Tempbx: SRA */
-	Tempbx = pVBInfo->XGINEWUB_CRT1Table[index].CR[14];
+	Tempbx = XGI_CRT1Table[index].CR[14];
 	Tempbx &= 0x20; /* Tempbx[5]: VRE[5] */
 	Tempbx >>= 1; /* Tempbx[4]: VRE[4] */
 	Tempax |= Tempbx; /* Tempax[4:0]: VRE[4:0] */
@@ -563,23 +539,23 @@ static void XGI_SetXG27CRTC(unsigned short ModeNo,
 {
 	unsigned short index, Tempax, Tempbx, Tempcx;
 
-	index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+	index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
 	/* Tempax: CR4 HRS */
-	Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[3];
+	Tempax = XGI_CRT1Table[index].CR[3];
 	Tempbx = Tempax; /* Tempbx: HRS[7:0] */
 	/* SR2E[7:0]->HRS */
 	xgifb_reg_set(pVBInfo->P3c4, 0x2E, Tempax);
 
 	/* SR0B */
-	Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[5];
+	Tempax = XGI_CRT1Table[index].CR[5];
 	Tempax &= 0xC0; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
 	Tempbx |= (Tempax << 2); /* Tempbx: HRS[9:0] */
 
-	Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[4]; /* CR5 HRE */
+	Tempax = XGI_CRT1Table[index].CR[4]; /* CR5 HRE */
 	Tempax &= 0x1F; /* Tempax[4:0]: HRE[4:0] */
 	Tempcx = Tempax; /* Tempcx: HRE[4:0] */
 
-	Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[6]; /* SRC */
+	Tempax = XGI_CRT1Table[index].CR[6]; /* SRC */
 	Tempax &= 0x04; /* Tempax[2]: HRE[5] */
 	Tempax <<= 3; /* Tempax[5]: HRE[5] */
 	Tempcx |= Tempax; /* Tempcx[5:0]: HRE[5:0] */
@@ -588,12 +564,12 @@ static void XGI_SetXG27CRTC(unsigned short ModeNo,
 	Tempbx |= Tempcx; /* Tempbx: HRS[9:6]HRE[5:0] */
 
 	/* Tempax: CR4 HRS */
-	Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[3];
+	Tempax = XGI_CRT1Table[index].CR[3];
 	Tempax &= 0x3F; /* Tempax: HRS[5:0] */
 	if (Tempcx <= Tempax) /* HRE[5:0] < HRS[5:0] */
 		Tempbx += 0x40; /* Tempbx= Tempbx + 0x40 : HRE[9:0]*/
 
-	Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[5]; /* SR0B */
+	Tempax = XGI_CRT1Table[index].CR[5]; /* SR0B */
 	Tempax &= 0xC0; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
 	Tempax >>= 6; /* Tempax[1:0]: HRS[9:8]*/
 	Tempax |= ((Tempbx << 2) & 0xFF); /* Tempax[7:2]: HRE[5:0] */
@@ -602,13 +578,13 @@ static void XGI_SetXG27CRTC(unsigned short ModeNo,
 	xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00);
 
 	/* CR10 VRS */
-	Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[10];
+	Tempax = XGI_CRT1Table[index].CR[10];
 	/* SR34[7:0]->VRS[7:0] */
 	xgifb_reg_set(pVBInfo->P3c4, 0x34, Tempax);
 
 	Tempcx = Tempax; /* Tempcx <= VRS[7:0] */
 	/* CR7[7][2] VRS[9][8] */
-	Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[9];
+	Tempax = XGI_CRT1Table[index].CR[9];
 	Tempbx = Tempax; /* Tempbx <= CR07[7:0] */
 	Tempax = Tempax & 0x04; /* Tempax[2]: CR7[2]: VRS[8] */
 	Tempax >>= 2; /* Tempax[0]: VRS[8] */
@@ -617,15 +593,15 @@ static void XGI_SetXG27CRTC(unsigned short ModeNo,
 	Tempcx |= (Tempax << 8); /* Tempcx <= VRS[8:0] */
 	Tempcx |= ((Tempbx & 0x80) << 2); /* Tempcx <= VRS[9:0] */
 	/* Tempax: SR0A */
-	Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[14];
+	Tempax = XGI_CRT1Table[index].CR[14];
 	Tempax &= 0x08; /* SR0A[3] VRS[10] */
 	Tempcx |= (Tempax << 7); /* Tempcx <= VRS[10:0] */
 
 	/* Tempax: CR11 VRE */
-	Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[11];
+	Tempax = XGI_CRT1Table[index].CR[11];
 	Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
 	/* Tempbx: SR0A */
-	Tempbx = pVBInfo->XGINEWUB_CRT1Table[index].CR[14];
+	Tempbx = XGI_CRT1Table[index].CR[14];
 	Tempbx &= 0x20; /* Tempbx[5]: SR0A[5]: VRE[4] */
 	Tempbx >>= 1; /* Tempbx[4]: VRE[4] */
 	Tempax |= Tempbx; /* Tempax[4:0]: VRE[4:0] */
@@ -698,7 +674,7 @@ static void xgifb_set_lcd(int chip_id,
 	xgifb_reg_and(pVBInfo->P3c4, 0x30, ~0x20); /* Hsync polarity */
 	xgifb_reg_and(pVBInfo->P3c4, 0x35, ~0x80); /* Vsync polarity */
 
-	Data = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+	Data = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
 	if (Data & 0x4000)
 		/* Hsync polarity */
 		xgifb_reg_or(pVBInfo->P3c4, 0x30, 0x20);
@@ -721,10 +697,10 @@ static void XGI_UpdateXG21CRTC(unsigned short ModeNo,
 
 	xgifb_reg_and(pVBInfo->P3d4, 0x11, 0x7F); /* Unlock CR0~7 */
 	if (ModeNo == 0x2E &&
-	    (pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC ==
+	    (XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC ==
 						      RES640x480x60))
 		index = 12;
-	else if (ModeNo == 0x2E && (pVBInfo->RefIndex[RefreshRateTableIndex].
+	else if (ModeNo == 0x2E && (XGI330_RefIndex[RefreshRateTableIndex].
 				Ext_CRT1CRTC == RES640x480x72))
 		index = 13;
 	else if (ModeNo == 0x2F)
@@ -736,13 +712,13 @@ static void XGI_UpdateXG21CRTC(unsigned short ModeNo,
 
 	if (index != -1) {
 		xgifb_reg_set(pVBInfo->P3d4, 0x02,
-				pVBInfo->UpdateCRT1[index].CR02);
+				XGI_UpdateCRT1Table[index].CR02);
 		xgifb_reg_set(pVBInfo->P3d4, 0x03,
-				pVBInfo->UpdateCRT1[index].CR03);
+				XGI_UpdateCRT1Table[index].CR03);
 		xgifb_reg_set(pVBInfo->P3d4, 0x15,
-				pVBInfo->UpdateCRT1[index].CR15);
+				XGI_UpdateCRT1Table[index].CR15);
 		xgifb_reg_set(pVBInfo->P3d4, 0x16,
-				pVBInfo->UpdateCRT1[index].CR16);
+				XGI_UpdateCRT1Table[index].CR16);
 	}
 }
 
@@ -755,11 +731,11 @@ static void XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension,
 
 	unsigned char data;
 
-	resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
 
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	tempax = pVBInfo->ModeResInfo[resindex].HTotal;
-	tempbx = pVBInfo->ModeResInfo[resindex].VTotal;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	tempax = XGI330_ModeResInfo[resindex].HTotal;
+	tempbx = XGI330_ModeResInfo[resindex].VTotal;
 
 	if (modeflag & HalfDCLK)
 		tempax = tempax >> 1;
@@ -767,7 +743,7 @@ static void XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension,
 	if (modeflag & HalfDCLK)
 		tempax = tempax << 1;
 
-	temp = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+	temp = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
 
 	if (temp & InterlaceMode)
 		tempbx = tempbx >> 1;
@@ -819,11 +795,11 @@ static void XGI_SetCRT1Offset(unsigned short ModeNo,
 	unsigned short temp, ah, al, temp2, i, DisplayUnit;
 
 	/* GetOffset */
-	temp = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeInfo;
+	temp = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeInfo;
 	temp = temp >> 8;
-	temp = pVBInfo->ScreenOffset[temp];
+	temp = XGI330_ScreenOffset[temp];
 
-	temp2 = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+	temp2 = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
 	temp2 &= InterlaceMode;
 
 	if (temp2)
@@ -874,7 +850,7 @@ static void XGI_SetCRT1Offset(unsigned short ModeNo,
 	xgifb_reg_set(pVBInfo->P3d4, 0x13, temp);
 
 	/* SetDisplayUnit */
-	temp2 = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+	temp2 = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
 	temp2 &= InterlaceMode;
 	if (temp2)
 		DisplayUnit >>= 1;
@@ -904,9 +880,9 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
 	unsigned short modeflag, resinfo;
 
 	/* si+Ext_ResInfo */
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
-	CRT2Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	CRT2Index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 
 	if (pVBInfo->IF_DEF_LVDS == 0) {
 		CRT2Index = CRT2Index >> 6; /*  for LCD */
@@ -947,7 +923,7 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
 				VCLKIndex = TVCLKBASE_315_25 + TVVCLK;
 		} else { /* for CRT2 */
 			/* di+Ext_CRTVCLK */
-			VCLKIndex = pVBInfo->RefIndex[RefreshRateTableIndex].
+			VCLKIndex = XGI330_RefIndex[RefreshRateTableIndex].
 								Ext_CRTVCLK;
 			VCLKIndex &= IndexMask;
 		}
@@ -971,13 +947,11 @@ static void XGI_SetCRT1VCLK(unsigned short ModeNo,
 	unsigned short vclkindex;
 
 	if (pVBInfo->IF_DEF_LVDS == 1) {
-		index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+		index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
 		data = xgifb_reg_get(pVBInfo->P3c4, 0x31) & 0xCF;
 		xgifb_reg_set(pVBInfo->P3c4, 0x31, data);
-		xgifb_reg_set(pVBInfo->P3c4, 0x2B,
-				pVBInfo->VCLKData[index].SR2B);
-		xgifb_reg_set(pVBInfo->P3c4, 0x2C,
-				pVBInfo->VCLKData[index].SR2C);
+		xgifb_reg_set(pVBInfo->P3c4, 0x2B, XGI_VCLKData[index].SR2B);
+		xgifb_reg_set(pVBInfo->P3c4, 0x2C, XGI_VCLKData[index].SR2C);
 		xgifb_reg_set(pVBInfo->P3c4, 0x2D, 0x01);
 	} else if ((pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
 			| VB_SIS302LV | VB_XGI301C)) && (pVBInfo->VBInfo
@@ -987,24 +961,22 @@ static void XGI_SetCRT1VCLK(unsigned short ModeNo,
 				pVBInfo);
 		data = xgifb_reg_get(pVBInfo->P3c4, 0x31) & 0xCF;
 		xgifb_reg_set(pVBInfo->P3c4, 0x31, data);
-		data = pVBInfo->VBVCLKData[vclkindex].Part4_A;
+		data = XGI_VBVCLKData[vclkindex].Part4_A;
 		xgifb_reg_set(pVBInfo->P3c4, 0x2B, data);
-		data = pVBInfo->VBVCLKData[vclkindex].Part4_B;
+		data = XGI_VBVCLKData[vclkindex].Part4_B;
 		xgifb_reg_set(pVBInfo->P3c4, 0x2C, data);
 		xgifb_reg_set(pVBInfo->P3c4, 0x2D, 0x01);
 	} else {
-		index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+		index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
 		data = xgifb_reg_get(pVBInfo->P3c4, 0x31) & 0xCF;
 		xgifb_reg_set(pVBInfo->P3c4, 0x31, data);
-		xgifb_reg_set(pVBInfo->P3c4, 0x2B,
-				pVBInfo->VCLKData[index].SR2B);
-		xgifb_reg_set(pVBInfo->P3c4, 0x2C,
-				pVBInfo->VCLKData[index].SR2C);
+		xgifb_reg_set(pVBInfo->P3c4, 0x2B, XGI_VCLKData[index].SR2B);
+		xgifb_reg_set(pVBInfo->P3c4, 0x2C, XGI_VCLKData[index].SR2C);
 		xgifb_reg_set(pVBInfo->P3c4, 0x2D, 0x01);
 	}
 
 	if (HwDeviceExtension->jChipType >= XG20) {
-		if (pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag &
+		if (XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag &
 		    HalfDCLK) {
 			data = xgifb_reg_get(pVBInfo->P3c4, 0x2B);
 			xgifb_reg_set(pVBInfo->P3c4, 0x2B, data);
@@ -1064,9 +1036,9 @@ static void XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension,
 
 	unsigned char index;
 
-	index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+	index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
 	index &= IndexMask;
-	VCLK = pVBInfo->VCLKData[index].CLOCK;
+	VCLK = XGI_VCLKData[index].CLOCK;
 
 	data = xgifb_reg_get(pVBInfo->P3c4, 0x32);
 	data &= 0xf3;
@@ -1102,8 +1074,8 @@ static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
 	unsigned short data, data2, data3, infoflag = 0, modeflag, resindex,
 			xres;
 
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	infoflag = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	infoflag = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
 
 	if (xgifb_reg_get(pVBInfo->P3d4, 0x31) & 0x01)
 		xgifb_reg_and_or(pVBInfo->P3c4, 0x1F, 0x3F, 0x00);
@@ -1120,8 +1092,8 @@ static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
 		data2 |= 0x20;
 
 	xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0x3F, data2);
-	resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
-	xres = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
+	resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	xres = XGI330_ModeResInfo[resindex].HTotal; /* xres->ax */
 
 	data = 0x0000;
 	if (infoflag & InterlaceMode) {
@@ -1282,13 +1254,13 @@ static void XGI_GetLVDSResInfo(unsigned short ModeNo,
 	unsigned short resindex, xres, yres, modeflag;
 
 	/* si+Ext_ResInfo */
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
 
 	/* si+Ext_ResInfo */
-	resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
 
-	xres = pVBInfo->ModeResInfo[resindex].HTotal;
-	yres = pVBInfo->ModeResInfo[resindex].VTotal;
+	xres = XGI330_ModeResInfo[resindex].HTotal;
+	yres = XGI330_ModeResInfo[resindex].VTotal;
 
 	if (modeflag & HalfDCLK)
 		xres = xres << 1;
@@ -1305,64 +1277,21 @@ static void XGI_GetLVDSResInfo(unsigned short ModeNo,
 	pVBInfo->VDE = yres;
 }
 
-static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo,
+static void const *XGI_GetLcdPtr(struct XGI330_LCDDataTablStruct const *table,
+		unsigned short ModeNo,
 		unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short i, tempdx, tempbx, tempal, modeflag, table;
-
-	struct XGI330_LCDDataTablStruct *tempdi = NULL;
-
-	tempbx = BX;
-
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-
-	tempal = tempal & 0x0f;
-
-	if (tempbx <= 1) { /* ExpLink */
-		tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-
-		if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
-			tempal = pVBInfo->RefIndex[RefreshRateTableIndex].
-							Ext_CRT2CRTC2;
-		}
+	unsigned short i, tempdx, tempbx, modeflag;
 
-		if (tempbx & 0x01)
-			tempal = (tempal >> 4);
-
-		tempal = (tempal & 0x0f);
-	}
-
-	switch (tempbx) {
-	case 0:
-	case 1:
-		tempdi = xgifb_epllcd_crt1;
-		break;
-	case 2:
-		tempdi = XGI_EPLLCDDataPtr;
-		break;
-	case 3:
-		tempdi = XGI_EPLLCDDesDataPtr;
-		break;
-	case 4:
-		tempdi = XGI_LCDDataTable;
-		break;
-	case 5:
-		tempdi = XGI_LCDDesDataTable;
-		break;
-	default:
-		break;
-	}
+	tempbx = 0;
 
-	if (tempdi == NULL) /* OEMUtil */
-		return NULL;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
-	table = tempbx;
 	i = 0;
 
-	while (tempdi[i].PANELID != 0xff) {
+	while (table[i].PANELID != 0xff) {
 		tempdx = pVBInfo->LCDResInfo;
 		if (tempbx & 0x0080) { /* OEMUtil */
 			tempbx &= (~0x0080);
@@ -1372,341 +1301,21 @@ static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo,
 		if (pVBInfo->LCDInfo & EnableScalingLCD)
 			tempdx &= (~PanelResInfo);
 
-		if (tempdi[i].PANELID == tempdx) {
-			tempbx = tempdi[i].MASK;
+		if (table[i].PANELID == tempdx) {
+			tempbx = table[i].MASK;
 			tempdx = pVBInfo->LCDInfo;
 
 			if (modeflag & HalfDCLK)
 				tempdx |= SetLCDLowResolution;
 
 			tempbx &= tempdx;
-			if (tempbx == tempdi[i].CAP)
+			if (tempbx == table[i].CAP)
 				break;
 		}
 		i++;
 	}
 
-	if (table == 0) {
-		switch (tempdi[i].DATAPTR) {
-		case 0:
-			return &XGI_LVDSCRT11024x768_1_H[tempal];
-			break;
-		case 1:
-			return &XGI_LVDSCRT11024x768_2_H[tempal];
-			break;
-		case 2:
-			return &XGI_LVDSCRT11280x1024_1_H[tempal];
-			break;
-		case 3:
-			return &XGI_LVDSCRT11280x1024_2_H[tempal];
-			break;
-		case 4:
-			return &XGI_LVDSCRT11400x1050_1_H[tempal];
-			break;
-		case 5:
-			return &XGI_LVDSCRT11400x1050_2_H[tempal];
-			break;
-		case 6:
-			return &XGI_LVDSCRT11600x1200_1_H[tempal];
-			break;
-		case 7:
-			return &XGI_LVDSCRT11024x768_1_Hx75[tempal];
-			break;
-		case 8:
-			return &XGI_LVDSCRT11024x768_2_Hx75[tempal];
-			break;
-		case 9:
-			return &XGI_LVDSCRT11280x1024_1_Hx75[tempal];
-			break;
-		case 10:
-			return &XGI_LVDSCRT11280x1024_2_Hx75[tempal];
-			break;
-		default:
-			break;
-		}
-	} else if (table == 1) {
-		switch (tempdi[i].DATAPTR) {
-		case 0:
-			return &XGI_LVDSCRT11024x768_1_V[tempal];
-			break;
-		case 1:
-			return &XGI_LVDSCRT11024x768_2_V[tempal];
-			break;
-		case 2:
-			return &XGI_LVDSCRT11280x1024_1_V[tempal];
-			break;
-		case 3:
-			return &XGI_LVDSCRT11280x1024_2_V[tempal];
-			break;
-		case 4:
-			return &XGI_LVDSCRT11400x1050_1_V[tempal];
-			break;
-		case 5:
-			return &XGI_LVDSCRT11400x1050_2_V[tempal];
-			break;
-		case 6:
-			return &XGI_LVDSCRT11600x1200_1_V[tempal];
-			break;
-		case 7:
-			return &XGI_LVDSCRT11024x768_1_Vx75[tempal];
-			break;
-		case 8:
-			return &XGI_LVDSCRT11024x768_2_Vx75[tempal];
-			break;
-		case 9:
-			return &XGI_LVDSCRT11280x1024_1_Vx75[tempal];
-			break;
-		case 10:
-			return &XGI_LVDSCRT11280x1024_2_Vx75[tempal];
-			break;
-		default:
-			break;
-		}
-	} else if (table == 2) {
-		switch (tempdi[i].DATAPTR) {
-		case 0:
-			return &XGI_LVDS1024x768Data_1[tempal];
-			break;
-		case 1:
-			return &XGI_LVDS1024x768Data_2[tempal];
-			break;
-		case 2:
-			return &XGI_LVDS1280x1024Data_1[tempal];
-			break;
-		case 3:
-			return &XGI_LVDS1280x1024Data_2[tempal];
-			break;
-		case 4:
-			return &XGI_LVDS1400x1050Data_1[tempal];
-			break;
-		case 5:
-			return &XGI_LVDS1400x1050Data_2[tempal];
-			break;
-		case 6:
-			return &XGI_LVDS1600x1200Data_1[tempal];
-			break;
-		case 7:
-			return &XGI_LVDSNoScalingData[tempal];
-			break;
-		case 8:
-			return &XGI_LVDS1024x768Data_1x75[tempal];
-			break;
-		case 9:
-			return &XGI_LVDS1024x768Data_2x75[tempal];
-			break;
-		case 10:
-			return &XGI_LVDS1280x1024Data_1x75[tempal];
-			break;
-		case 11:
-			return &XGI_LVDS1280x1024Data_2x75[tempal];
-			break;
-		case 12:
-			return &XGI_LVDSNoScalingDatax75[tempal];
-			break;
-		default:
-			break;
-		}
-	} else if (table == 3) {
-		switch (tempdi[i].DATAPTR) {
-		case 0:
-			return &XGI_LVDS1024x768Des_1[tempal];
-			break;
-		case 1:
-			return &XGI_LVDS1024x768Des_3[tempal];
-			break;
-		case 2:
-			return &XGI_LVDS1024x768Des_2[tempal];
-			break;
-		case 3:
-			return &XGI_LVDS1280x1024Des_1[tempal];
-			break;
-		case 4:
-			return &XGI_LVDS1280x1024Des_2[tempal];
-			break;
-		case 5:
-			return &XGI_LVDS1400x1050Des_1[tempal];
-			break;
-		case 6:
-			return &XGI_LVDS1400x1050Des_2[tempal];
-			break;
-		case 7:
-			return &XGI_LVDS1600x1200Des_1[tempal];
-			break;
-		case 8:
-			return &XGI_LVDSNoScalingDesData[tempal];
-			break;
-		case 9:
-			return &XGI_LVDS1024x768Des_1x75[tempal];
-			break;
-		case 10:
-			return &XGI_LVDS1024x768Des_3x75[tempal];
-			break;
-		case 11:
-			return &XGI_LVDS1024x768Des_2x75[tempal];
-			break;
-		case 12:
-			return &XGI_LVDS1280x1024Des_1x75[tempal];
-			break;
-		case 13:
-			return &XGI_LVDS1280x1024Des_2x75[tempal];
-			break;
-		case 14:
-			return &XGI_LVDSNoScalingDesDatax75[tempal];
-			break;
-		default:
-			break;
-		}
-	} else if (table == 4) {
-		switch (tempdi[i].DATAPTR) {
-		case 0:
-			return &XGI_ExtLCD1024x768Data[tempal];
-			break;
-		case 1:
-			return &XGI_StLCD1024x768Data[tempal];
-			break;
-		case 2:
-			return &XGI_CetLCD1024x768Data[tempal];
-			break;
-		case 3:
-			return &XGI_ExtLCD1280x1024Data[tempal];
-			break;
-		case 4:
-			return &XGI_StLCD1280x1024Data[tempal];
-			break;
-		case 5:
-			return &XGI_CetLCD1280x1024Data[tempal];
-			break;
-		case 6:
-		case 7:
-			return &xgifb_lcd_1400x1050[tempal];
-			break;
-		case 8:
-			return &XGI_CetLCD1400x1050Data[tempal];
-			break;
-		case 9:
-			return &XGI_ExtLCD1600x1200Data[tempal];
-			break;
-		case 10:
-			return &XGI_StLCD1600x1200Data[tempal];
-			break;
-		case 11:
-			return &XGI_NoScalingData[tempal];
-			break;
-		case 12:
-			return &XGI_ExtLCD1024x768x75Data[tempal];
-			break;
-		case 13:
-			return &XGI_ExtLCD1024x768x75Data[tempal];
-			break;
-		case 14:
-			return &XGI_CetLCD1024x768x75Data[tempal];
-			break;
-		case 15:
-		case 16:
-			return &xgifb_lcd_1280x1024x75[tempal];
-			break;
-		case 17:
-			return &XGI_CetLCD1280x1024x75Data[tempal];
-			break;
-		case 18:
-			return &XGI_NoScalingDatax75[tempal];
-			break;
-		default:
-			break;
-		}
-	} else if (table == 5) {
-		switch (tempdi[i].DATAPTR) {
-		case 0:
-			return &XGI_ExtLCDDes1024x768Data[tempal];
-			break;
-		case 1:
-			return &XGI_StLCDDes1024x768Data[tempal];
-			break;
-		case 2:
-			return &XGI_CetLCDDes1024x768Data[tempal];
-			break;
-		case 3:
-			if ((pVBInfo->VBType & VB_SIS301LV) ||
-				(pVBInfo->VBType & VB_SIS302LV))
-				return &XGI_ExtLCDDLDes1280x1024Data[tempal];
-			else
-				return &XGI_ExtLCDDes1280x1024Data[tempal];
-			break;
-		case 4:
-			if ((pVBInfo->VBType & VB_SIS301LV) ||
-			    (pVBInfo->VBType & VB_SIS302LV))
-				return &XGI_StLCDDLDes1280x1024Data[tempal];
-			else
-				return &XGI_StLCDDes1280x1024Data[tempal];
-			break;
-		case 5:
-			if ((pVBInfo->VBType & VB_SIS301LV) ||
-			    (pVBInfo->VBType & VB_SIS302LV))
-				return &XGI_CetLCDDLDes1280x1024Data[tempal];
-			else
-				return &XGI_CetLCDDes1280x1024Data[tempal];
-			break;
-		case 6:
-		case 7:
-			if ((pVBInfo->VBType & VB_SIS301LV) ||
-			    (pVBInfo->VBType & VB_SIS302LV))
-				return &xgifb_lcddldes_1400x1050[tempal];
-			else
-				return &xgifb_lcddes_1400x1050[tempal];
-			break;
-		case 8:
-			return &XGI_CetLCDDes1400x1050Data[tempal];
-			break;
-		case 9:
-			return &XGI_CetLCDDes1400x1050Data2[tempal];
-			break;
-		case 10:
-			if ((pVBInfo->VBType & VB_SIS301LV) ||
-			    (pVBInfo->VBType & VB_SIS302LV))
-				return &XGI_ExtLCDDLDes1600x1200Data[tempal];
-			else
-				return &XGI_ExtLCDDes1600x1200Data[tempal];
-			break;
-		case 11:
-			if ((pVBInfo->VBType & VB_SIS301LV) ||
-			    (pVBInfo->VBType & VB_SIS302LV))
-				return &XGI_StLCDDLDes1600x1200Data[tempal];
-			else
-				return &XGI_StLCDDes1600x1200Data[tempal];
-			break;
-		case 12:
-			return &XGI_NoScalingDesData[tempal];
-			break;
-		case 13:
-		case 14:
-			return &xgifb_lcddes_1024x768x75[tempal];
-			break;
-		case 15:
-			return &XGI_CetLCDDes1024x768x75Data[tempal];
-			break;
-		case 16:
-		case 17:
-			if ((pVBInfo->VBType & VB_SIS301LV) ||
-			    (pVBInfo->VBType & VB_SIS302LV))
-				return &xgifb_lcddldes_1280x1024x75[tempal];
-			else
-				return &xgifb_lcddes_1280x1024x75[tempal];
-			break;
-		case 18:
-			if ((pVBInfo->VBType & VB_SIS301LV) ||
-			    (pVBInfo->VBType & VB_SIS302LV))
-				return &XGI_CetLCDDLDes1280x1024x75Data[tempal];
-			else
-				return &XGI_CetLCDDes1280x1024x75Data[tempal];
-			break;
-		case 19:
-			return &XGI_NoScalingDesDatax75[tempal];
-			break;
-		default:
-			break;
-		}
-	}
-	return NULL;
+	return table[i].DATAPTR;
 }
 
 static struct SiS_TVData const *XGI_GetTVPtr(unsigned short ModeNo,
@@ -1716,8 +1325,8 @@ static struct SiS_TVData const *XGI_GetTVPtr(unsigned short ModeNo,
 {
 	unsigned short i, tempdx, tempal, modeflag;
 
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	tempal = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 	tempal = tempal & 0x3f;
 	tempdx = pVBInfo->TVInfo;
 
@@ -1743,40 +1352,35 @@ static void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short tempbx;
-	struct SiS_LVDSData *LCDPtr = NULL;
+	struct SiS_LVDSData const *LCDPtr;
 
-	tempbx = 2;
+	if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)))
+		return;
 
-	if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
-		LCDPtr = XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex,
-				       RefreshRateTableIndex, pVBInfo);
-		pVBInfo->VGAHT = LCDPtr->VGAHT;
-		pVBInfo->VGAVT = LCDPtr->VGAVT;
-		pVBInfo->HT = LCDPtr->LCDHT;
-		pVBInfo->VT = LCDPtr->LCDVT;
-	}
+	LCDPtr = XGI_GetLcdPtr(XGI_EPLLCDDataPtr, ModeNo, ModeIdIndex,
+			       RefreshRateTableIndex, pVBInfo);
+	pVBInfo->VGAHT	= LCDPtr->VGAHT;
+	pVBInfo->VGAVT	= LCDPtr->VGAVT;
+	pVBInfo->HT	= LCDPtr->LCDHT;
+	pVBInfo->VT	= LCDPtr->LCDVT;
 
-	if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
-		if (!(pVBInfo->LCDInfo & (SetLCDtoNonExpanding
-				| EnableScalingLCD))) {
-			if ((pVBInfo->LCDResInfo == Panel_1024x768) ||
-			    (pVBInfo->LCDResInfo == Panel_1024x768x75)) {
-				pVBInfo->HDE = 1024;
-				pVBInfo->VDE = 768;
-			} else if ((pVBInfo->LCDResInfo == Panel_1280x1024) ||
-				   (pVBInfo->LCDResInfo ==
-					Panel_1280x1024x75)) {
-				pVBInfo->HDE = 1280;
-				pVBInfo->VDE = 1024;
-			} else if (pVBInfo->LCDResInfo == Panel_1400x1050) {
-				pVBInfo->HDE = 1400;
-				pVBInfo->VDE = 1050;
-			} else {
-				pVBInfo->HDE = 1600;
-				pVBInfo->VDE = 1200;
-			}
-		}
+	if (pVBInfo->LCDInfo & (SetLCDtoNonExpanding | EnableScalingLCD))
+		return;
+
+	if ((pVBInfo->LCDResInfo == Panel_1024x768) ||
+	    (pVBInfo->LCDResInfo == Panel_1024x768x75)) {
+		pVBInfo->HDE = 1024;
+		pVBInfo->VDE = 768;
+	} else if ((pVBInfo->LCDResInfo == Panel_1280x1024) ||
+		   (pVBInfo->LCDResInfo == Panel_1280x1024x75)) {
+		pVBInfo->HDE = 1280;
+		pVBInfo->VDE = 1024;
+	} else if (pVBInfo->LCDResInfo == Panel_1400x1050) {
+		pVBInfo->HDE = 1400;
+		pVBInfo->VDE = 1050;
+	} else {
+		pVBInfo->HDE = 1600;
+		pVBInfo->VDE = 1200;
 	}
 }
 
@@ -1786,32 +1390,29 @@ static void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned char index;
-	unsigned short tempbx, i;
-	struct XGI_LVDSCRT1HDataStruct *LCDPtr = NULL;
-	struct XGI_LVDSCRT1VDataStruct *LCDPtr1 = NULL;
+	unsigned short i;
+	struct XGI_LVDSCRT1HDataStruct const *LCDPtr = NULL;
+	struct XGI_LVDSCRT1VDataStruct const *LCDPtr1 = NULL;
 
-	index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+	index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 	index = index & IndexMask;
 
-	tempbx = 0;
-
 	if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
-		LCDPtr = XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex,
+		LCDPtr = XGI_GetLcdPtr(xgifb_epllcd_crt1_h, ModeNo, ModeIdIndex,
 				       RefreshRateTableIndex, pVBInfo);
 
 		for (i = 0; i < 8; i++)
-			pVBInfo->TimingH[0].data[i] = LCDPtr[0].Reg[i];
+			pVBInfo->TimingH.data[i] = LCDPtr[0].Reg[i];
 	}
 
 	XGI_SetCRT1Timing_H(pVBInfo, HwDeviceExtension);
 
-	tempbx = 1;
-
 	if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
-		LCDPtr1 = XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex,
-					RefreshRateTableIndex, pVBInfo);
+		LCDPtr1 = XGI_GetLcdPtr(xgifb_epllcd_crt1_v, ModeNo,
+					ModeIdIndex, RefreshRateTableIndex,
+					pVBInfo);
 		for (i = 0; i < 7; i++)
-			pVBInfo->TimingV[0].data[i] = LCDPtr1[0].Reg[i];
+			pVBInfo->TimingV.data[i] = LCDPtr1[0].Reg[i];
 	}
 
 	XGI_SetCRT1Timing_V(ModeIdIndex, ModeNo, pVBInfo);
@@ -1895,17 +1496,18 @@ static void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
 {
 	unsigned short tempbx, tempax, tempcx, tempdx, push1, push2, modeflag;
 	unsigned long temp, temp1, temp2, temp3, push3;
-	struct XGI_LCDDesStruct *LCDPtr = NULL;
-	struct XGI330_LCDDataDesStruct2 *LCDPtr1 = NULL;
+	struct XGI_LCDDesStruct const *LCDPtr = NULL;
+	struct XGI330_LCDDataDesStruct2 const *LCDPtr1 = NULL;
 
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	tempbx = 3;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 	if (pVBInfo->LCDInfo & EnableScalingLCD)
-		LCDPtr1 = XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex,
-					RefreshRateTableIndex, pVBInfo);
+		LCDPtr1 = XGI_GetLcdPtr(XGI_EPLLCDDesDataPtr, ModeNo,
+					ModeIdIndex, RefreshRateTableIndex,
+					pVBInfo);
 	else
-		LCDPtr = XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex,
-				       RefreshRateTableIndex, pVBInfo);
+		LCDPtr = XGI_GetLcdPtr(XGI_EPLLCDDesDataPtr, ModeNo,
+				       ModeIdIndex, RefreshRateTableIndex,
+				       pVBInfo);
 
 	XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
 	push1 = tempbx;
@@ -2179,7 +1781,7 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
 	unsigned char tempal;
 
 	/* si+Ext_ResInfo */
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
 	if ((pVBInfo->SetFlag & ProgrammingCRT2) &&
 	    (!(pVBInfo->LCDInfo & EnableScalingLCD))) { /* {LCDA/LCDB} */
@@ -2241,7 +1843,7 @@ static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
 	if ((pVBInfo->LCDInfo & EnableScalingLCD) && (modeflag & Charx8Dot))
 		tempal = tempal ^ tempal; /* ; set to VCLK25MHz always */
 
-	tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+	tempal = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
 	return tempal;
 }
 
@@ -2425,7 +2027,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
 {
 	unsigned short tempax, push, tempbx, temp, modeflag;
 
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 	pVBInfo->SetFlag = 0;
 	pVBInfo->ModeType = modeflag & ModeTypeMask;
 	tempbx = 0;
@@ -2501,7 +2103,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
 		} else {
 			temp = 0x017C;
 		}
-	} else { /* 3nd party chip */
+	} else { /* 3rd party chip */
 		temp = SetCRT2ToLCD;
 	}
 
@@ -2611,8 +2213,8 @@ static void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
 	resinfo = 0;
 
 	if (pVBInfo->VBInfo & SetCRT2ToTV) {
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-		resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+		modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+		resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
 
 		if (pVBInfo->VBInfo & SetCRT2ToTV) {
 			temp = xgifb_reg_get(pVBInfo->P3d4, 0x35);
@@ -2697,9 +2299,9 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeNo,
 	pVBInfo->LCDTypeInfo = 0;
 	pVBInfo->LCDInfo = 0;
 
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 	/* si+Ext_ResInfo // */
-	resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
 	temp = xgifb_reg_get(pVBInfo->P3d4, 0x36); /* Get LCD Res.Info */
 	tempbx = temp & 0x0F;
 
@@ -2778,9 +2380,9 @@ unsigned char XGI_SearchModeID(unsigned short ModeNo,
 		unsigned short *ModeIdIndex, struct vb_device_info *pVBInfo)
 {
 	for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
-		if (pVBInfo->EModeIDTable[*ModeIdIndex].Ext_ModeID == ModeNo)
+		if (XGI330_EModeIDTable[*ModeIdIndex].Ext_ModeID == ModeNo)
 			break;
-		if (pVBInfo->EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
+		if (XGI330_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
 			return 0;
 	}
 
@@ -3020,11 +2622,11 @@ static void XGI_GetCRT2ResInfo(unsigned short ModeNo,
 {
 	unsigned short xres, yres, modeflag, resindex;
 
-	resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
-	xres = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
-	yres = pVBInfo->ModeResInfo[resindex].VTotal; /* yres->bx */
+	resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	xres = XGI330_ModeResInfo[resindex].HTotal; /* xres->ax */
+	yres = XGI330_ModeResInfo[resindex].VTotal; /* yres->bx */
 	/* si+St_ModeFlag */
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
 	if (modeflag & HalfDCLK)
 		xres *= 2;
@@ -3099,19 +2701,19 @@ static void XGI_GetRAMDAC2DATA(unsigned short ModeNo,
 
 	pVBInfo->RVBHCMAX = 1;
 	pVBInfo->RVBHCFACT = 1;
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	CRT1Index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
 	CRT1Index &= IndexMask;
-	temp1 = (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[0];
-	temp2 = (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[5];
+	temp1 = (unsigned short) XGI_CRT1Table[CRT1Index].CR[0];
+	temp2 = (unsigned short) XGI_CRT1Table[CRT1Index].CR[5];
 	tempax = (temp1 & 0xFF) | ((temp2 & 0x03) << 8);
-	tempbx = (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[8];
+	tempbx = (unsigned short) XGI_CRT1Table[CRT1Index].CR[8];
 	tempcx = (unsigned short)
-			pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[14] << 8;
+			XGI_CRT1Table[CRT1Index].CR[14] << 8;
 	tempcx &= 0x0100;
 	tempcx = tempcx << 2;
 	tempbx |= tempcx;
-	temp1 = (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[9];
+	temp1 = (unsigned short) XGI_CRT1Table[CRT1Index].CR[9];
 
 	if (temp1 & 0x01)
 		tempbx |= 0x0100;
@@ -3136,13 +2738,13 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short tempax = 0, tempbx, modeflag, resinfo;
+	unsigned short tempax = 0, tempbx = 0, modeflag, resinfo;
 
-	struct SiS_LCDData *LCDPtr = NULL;
+	struct SiS_LCDData const *LCDPtr = NULL;
 
 	/* si+Ext_ResInfo */
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
 	pVBInfo->NewFlickerMode = 0;
 	pVBInfo->RVBHRS = 50;
 
@@ -3152,10 +2754,8 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex,
 		return;
 	}
 
-	tempbx = 4;
-
 	if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
-		LCDPtr = XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex,
+		LCDPtr = XGI_GetLcdPtr(XGI_LCDDataTable, ModeNo, ModeIdIndex,
 				       RefreshRateTableIndex, pVBInfo);
 
 		pVBInfo->RVBHCMAX = LCDPtr->RVBHCMAX;
@@ -3345,7 +2945,7 @@ static unsigned short XGI_GetColorDepth(unsigned short ModeNo,
 	short index;
 	unsigned short modeflag;
 
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 	index = (modeflag & ModeTypeMask) - ModeEGA;
 
 	if (index < 0)
@@ -3363,12 +2963,12 @@ static unsigned short XGI_GetOffset(unsigned short ModeNo,
 	unsigned short temp, colordepth, modeinfo, index, infoflag,
 			ColorDepth[] = { 0x01, 0x02, 0x04 };
 
-	modeinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeInfo;
-	infoflag = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+	modeinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeInfo;
+	infoflag = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
 
 	index = (modeinfo >> 8) & 0xFF;
 
-	temp = pVBInfo->ScreenOffset[index];
+	temp = XGI330_ScreenOffset[index];
 
 	if (infoflag & InterlaceMode)
 		temp = temp << 1;
@@ -3424,9 +3024,9 @@ static void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
 {
 	unsigned short tempcx = 0, CRT1Index = 0, resinfo = 0;
 
-	CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+	CRT1Index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
 	CRT1Index &= IndexMask;
-	resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
 
 	XGI_SetCRT2Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex,
 			HwDeviceExtension, pVBInfo);
@@ -3447,10 +3047,10 @@ static void XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
 	unsigned short temp = 0, tempax = 0, tempbx = 0, tempcx = 0,
 			pushbx = 0, CRT1Index = 0, modeflag, resinfo = 0;
 
-	CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+	CRT1Index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
 	CRT1Index &= IndexMask;
-	resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
 	/* bainy change table name */
 	if (modeflag & HalfDCLK) {
@@ -3469,14 +3069,13 @@ static void XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
 		tempcx += tempbx;
 
 		if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
-			tempbx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[4];
-			tempbx |= ((pVBInfo->
-					XGINEWUB_CRT1Table[CRT1Index].CR[14] &
+			tempbx = XGI_CRT1Table[CRT1Index].CR[4];
+			tempbx |= ((XGI_CRT1Table[CRT1Index].CR[14] &
 						0xC0) << 2);
 			tempbx = (tempbx - 3) << 3; /* (VGAHRS-3)*8 */
-			tempcx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[5];
+			tempcx = XGI_CRT1Table[CRT1Index].CR[5];
 			tempcx &= 0x1F;
-			temp = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[15];
+			temp = XGI_CRT1Table[CRT1Index].CR[15];
 			temp = (temp & 0x04) << (5 - 2); /* VGAHRE D[5] */
 			tempcx = ((tempcx | temp) - 3) << 3; /* (VGAHRE-3)*8 */
 		}
@@ -3505,14 +3104,13 @@ static void XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
 		tempcx += tempbx;
 
 		if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
-			tempbx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[3];
-			tempbx |= ((pVBInfo->
-					XGINEWUB_CRT1Table[CRT1Index].CR[5] &
+			tempbx = XGI_CRT1Table[CRT1Index].CR[3];
+			tempbx |= ((XGI_CRT1Table[CRT1Index].CR[5] &
 						0xC0) << 2);
 			tempbx = (tempbx - 3) << 3; /* (VGAHRS-3)*8 */
-			tempcx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[4];
+			tempcx = XGI_CRT1Table[CRT1Index].CR[4];
 			tempcx &= 0x1F;
-			temp = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[6];
+			temp = XGI_CRT1Table[CRT1Index].CR[6];
 			temp = (temp & 0x04) << (5 - 2); /* VGAHRE D[5] */
 			tempcx = ((tempcx | temp) - 3) << 3; /* (VGAHRE-3)*8 */
 			tempbx += 16;
@@ -3554,8 +3152,8 @@ static void XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
 	tempcx = ((pVBInfo->VGAVT - pVBInfo->VGAVDE) >> 4) + tempbx + 1;
 
 	if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
-		tempbx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[10];
-		temp = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[9];
+		tempbx = XGI_CRT1Table[CRT1Index].CR[10];
+		temp = XGI_CRT1Table[CRT1Index].CR[9];
 
 		if (temp & 0x04)
 			tempbx |= 0x0100;
@@ -3563,12 +3161,12 @@ static void XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
 		if (temp & 0x080)
 			tempbx |= 0x0200;
 
-		temp = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[14];
+		temp = XGI_CRT1Table[CRT1Index].CR[14];
 
 		if (temp & 0x08)
 			tempbx |= 0x0400;
 
-		temp = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[11];
+		temp = XGI_CRT1Table[CRT1Index].CR[11];
 		tempcx = (tempcx & 0xFF00) | (temp & 0x00FF);
 	}
 
@@ -3609,9 +3207,9 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
 			modeflag, CRT1Index;
 
 	/* si+Ext_ResInfo */
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
-	CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	CRT1Index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
 	CRT1Index &= IndexMask;
 
 	if (!(pVBInfo->VBInfo & SetInSlaveMode))
@@ -3909,9 +3507,9 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
 	unsigned long longtemp, tempeax, tempebx, temp2, tempecx;
 
 	/* si+Ext_ResInfo */
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
-	crt2crtc = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	crt2crtc = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 
 	tempax = 0;
 
@@ -4345,12 +3943,12 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
 	unsigned short push1, push2, pushbx, tempax, tempbx, tempcx, temp,
 			tempah, tempbh, tempch, resinfo, modeflag, CRT1Index;
 
-	struct XGI_LCDDesStruct *LCDBDesPtr = NULL;
+	struct XGI_LCDDesStruct const *LCDBDesPtr = NULL;
 
 	/* si+Ext_ResInfo */
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
-	CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	CRT1Index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
 	CRT1Index &= IndexMask;
 
 	if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
@@ -4390,10 +3988,15 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
 	xgifb_reg_and_or(pVBInfo->Part2Port, 0x17, 0xFB, 0x00);
 	xgifb_reg_and_or(pVBInfo->Part2Port, 0x18, 0xDF, 0x00);
 
-	/* Customized LCDB Des no add */
-	tempbx = 5;
-	LCDBDesPtr = XGI_GetLcdPtr(tempbx, ModeNo, ModeIdIndex,
-				   RefreshRateTableIndex, pVBInfo);
+	/* Customized LCDB Does not add */
+	if ((pVBInfo->VBType & VB_SIS301LV) || (pVBInfo->VBType & VB_SIS302LV))
+		LCDBDesPtr = XGI_GetLcdPtr(xgifb_lcddldes, ModeNo, ModeIdIndex,
+					   RefreshRateTableIndex, pVBInfo);
+	else
+		LCDBDesPtr = XGI_GetLcdPtr(XGI_LCDDesDataTable, ModeNo,
+					   ModeIdIndex, RefreshRateTableIndex,
+					   pVBInfo);
+
 	tempah = pVBInfo->LCDResInfo;
 	tempah &= PanelResInfo;
 
@@ -4545,12 +4148,11 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
 /* Output : di -> Tap4 Reg. Setting Pointer */
 /* Description : */
 /* --------------------------------------------------------------------- */
-static struct XGI301C_Tap4TimingStruct *XGI_GetTap4Ptr(unsigned short tempcx,
-		struct vb_device_info *pVBInfo)
+static struct XGI301C_Tap4TimingStruct const
+*XGI_GetTap4Ptr(unsigned short tempcx, struct vb_device_info *pVBInfo)
 {
 	unsigned short tempax, tempbx, i;
-
-	struct XGI301C_Tap4TimingStruct *Tap4TimingPtr;
+	struct XGI301C_Tap4TimingStruct const *Tap4TimingPtr;
 
 	if (tempcx == 0) {
 		tempax = pVBInfo->VGAHDE;
@@ -4591,8 +4193,7 @@ static struct XGI301C_Tap4TimingStruct *XGI_GetTap4Ptr(unsigned short tempcx,
 static void XGI_SetTap4Regs(struct vb_device_info *pVBInfo)
 {
 	unsigned short i, j;
-
-	struct XGI301C_Tap4TimingStruct *Tap4TimingPtr;
+	struct XGI301C_Tap4TimingStruct const *Tap4TimingPtr;
 
 	if (!(pVBInfo->VBType & VB_XGI301C))
 		return;
@@ -4628,7 +4229,7 @@ static void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex,
 	unsigned short modeflag;
 
 	/* si+Ext_ResInfo */
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
 	xgifb_reg_set(pVBInfo->Part3Port, 0x00, 0x00);
 	if (pVBInfo->TVInfo & TVSetPAL) {
@@ -4687,7 +4288,7 @@ static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex,
 	unsigned long tempebx, tempeax, templong;
 
 	/* si+Ext_ResInfo */
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 	temp = pVBInfo->RVBHCFACT;
 	xgifb_reg_set(pVBInfo->Part4Port, 0x13, temp);
 
@@ -4890,11 +4491,11 @@ static unsigned char XGI_XG21CheckLVDSMode(struct xgifb_video_info *xgifb_info,
 {
 	unsigned short xres, yres, colordepth, modeflag, resindex;
 
-	resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
-	xres = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
-	yres = pVBInfo->ModeResInfo[resindex].VTotal; /* yres->bx */
+	resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	xres = XGI330_ModeResInfo[resindex].HTotal; /* xres->ax */
+	yres = XGI330_ModeResInfo[resindex].VTotal; /* yres->bx */
 	/* si+St_ModeFlag */
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
 	if (!(modeflag & Charx8Dot)) {
 		xres /= 9;
@@ -4952,11 +4553,11 @@ static void xgifb_set_lvds(struct xgifb_video_info *xgifb_info,
 	else
 		XGI_SetXG21FPBits(pVBInfo);
 
-	resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
-	xres = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
-	yres = pVBInfo->ModeResInfo[resindex].VTotal; /* yres->bx */
+	resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	xres = XGI330_ModeResInfo[resindex].HTotal; /* xres->ax */
+	yres = XGI330_ModeResInfo[resindex].VTotal; /* yres->bx */
 	/* si+St_ModeFlag */
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
 	if (!(modeflag & Charx8Dot))
 		xres = xres * 8 / 9;
@@ -5619,8 +5220,8 @@ static void XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned short tempbx, index;
-
-	unsigned char tempcl, tempch, tempal, *filterPtr;
+	unsigned char const *filterPtr;
+	unsigned char tempcl, tempch, tempal;
 
 	XGI_GetTVPtrIndex2(&tempbx, &tempcl, &tempch, pVBInfo); /* bx, cl, ch */
 
@@ -5653,7 +5254,7 @@ static void XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex,
 		return;
 	}
 
-	tempal = pVBInfo->EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
+	tempal = XGI330_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
 	if (tempcl == 0)
 		index = tempal * 4;
 	else
@@ -5915,7 +5516,7 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
 
 	unsigned short RefreshRateTableIndex, i, modeflag, index, temp;
 
-	modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
 	index = xgifb_reg_get(pVBInfo->P3d4, 0x33);
 	index = index >> pVBInfo->SelectCRT2Rate;
@@ -5948,31 +5549,30 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
 		}
 	}
 
-	RefreshRateTableIndex = pVBInfo->EModeIDTable[ModeIdIndex].REFindex;
-	ModeNo = pVBInfo->RefIndex[RefreshRateTableIndex].ModeID;
+	RefreshRateTableIndex = XGI330_EModeIDTable[ModeIdIndex].REFindex;
+	ModeNo = XGI330_RefIndex[RefreshRateTableIndex].ModeID;
 	if (pXGIHWDE->jChipType >= XG20) { /* for XG20, XG21, XG27 */
-		if ((pVBInfo->RefIndex[RefreshRateTableIndex].XRes == 800) &&
-		    (pVBInfo->RefIndex[RefreshRateTableIndex].YRes == 600)) {
+		if ((XGI330_RefIndex[RefreshRateTableIndex].XRes == 800) &&
+		    (XGI330_RefIndex[RefreshRateTableIndex].YRes == 600)) {
 			index++;
 		}
 		/* do the similar adjustment like XGISearchCRT1Rate() */
-		if ((pVBInfo->RefIndex[RefreshRateTableIndex].XRes == 1024) &&
-		    (pVBInfo->RefIndex[RefreshRateTableIndex].YRes == 768)) {
+		if ((XGI330_RefIndex[RefreshRateTableIndex].XRes == 1024) &&
+		    (XGI330_RefIndex[RefreshRateTableIndex].YRes == 768)) {
 			index++;
 		}
-		if ((pVBInfo->RefIndex[RefreshRateTableIndex].XRes == 1280) &&
-		    (pVBInfo->RefIndex[RefreshRateTableIndex].YRes == 1024)) {
+		if ((XGI330_RefIndex[RefreshRateTableIndex].XRes == 1280) &&
+		    (XGI330_RefIndex[RefreshRateTableIndex].YRes == 1024)) {
 			index++;
 		}
 	}
 
 	i = 0;
 	do {
-		if (pVBInfo->RefIndex[RefreshRateTableIndex + i].
+		if (XGI330_RefIndex[RefreshRateTableIndex + i].
 			ModeID != ModeNo)
 			break;
-		temp = pVBInfo->RefIndex[RefreshRateTableIndex + i].
-			Ext_InfoFlag;
+		temp = XGI330_RefIndex[RefreshRateTableIndex + i].Ext_InfoFlag;
 		temp &= ModeTypeMask;
 		if (temp < pVBInfo->ModeType)
 			break;
@@ -5982,7 +5582,7 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
 	} while (index != 0xFFFF);
 	if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC)) {
 		if (pVBInfo->VBInfo & SetInSlaveMode) {
-			temp = pVBInfo->RefIndex[RefreshRateTableIndex + i - 1].
+			temp = XGI330_RefIndex[RefreshRateTableIndex + i - 1].
 				Ext_InfoFlag;
 			if (temp & InterlaceMode)
 				i++;
@@ -6272,7 +5872,7 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info,
 	unsigned short RefreshRateTableIndex, temp;
 
 	XGI_SetSeqRegs(ModeNo, ModeIdIndex, pVBInfo);
-	outb(pVBInfo->StandTable->MISC, pVBInfo->P3c2);
+	outb(XGI330_StandTable.MISC, pVBInfo->P3c2);
 	XGI_SetCRTCRegs(HwDeviceExtension, pVBInfo);
 	XGI_SetATTRegs(ModeNo, ModeIdIndex, pVBInfo);
 	XGI_SetGRCRegs(pVBInfo);
@@ -6458,7 +6058,7 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
 						   pVBInfo))
 				return 0;
 
-		pVBInfo->ModeType = pVBInfo->EModeIDTable[ModeIdIndex].
+		pVBInfo->ModeType = XGI330_EModeIDTable[ModeIdIndex].
 						Ext_ModeFlag & ModeTypeMask;
 
 		pVBInfo->SetFlag = 0;
diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h
index 70158c2..acf6e7f 100644
--- a/drivers/staging/xgifb/vb_struct.h
+++ b/drivers/staging/xgifb/vb_struct.h
@@ -56,7 +56,7 @@ struct XGI330_LCDDataTablStruct {
 	unsigned char  PANELID;
 	unsigned short MASK;
 	unsigned short CAP;
-	unsigned short DATAPTR;
+	void const *DATAPTR;
 };
 
 struct XGI330_TVDataTablStruct {
@@ -158,40 +158,18 @@ struct vb_device_info {
 	void __iomem *FBAddr;
 	unsigned long BaseAddr;
 
-	unsigned char (*CR6B)[4];
-	unsigned char (*CR6E)[4];
-	unsigned char (*CR6F)[32];
-	unsigned char (*CR89)[2];
+	unsigned char const (*SR15)[8];
+	unsigned char const (*CR40)[8];
 
-	unsigned char (*SR15)[8];
-	unsigned char (*CR40)[8];
+	struct SiS_MCLKData const *MCLKData;
 
-	unsigned char  *AGPReg;
-	unsigned char  *SR16;
-	unsigned char  SR21;
-	unsigned char  SR22;
-	unsigned char  SR25;
-	struct SiS_MCLKData  *MCLKData;
-	struct XGI_ECLKDataStruct  *ECLKData;
-
-	unsigned char   *ScreenOffset;
 	unsigned char   *pXGINew_DRAMTypeDefinition;
 	unsigned char   XGINew_CR97;
 
-	struct XGI330_LCDCapStruct  *LCDCapList;
-
-	struct XGI_TimingHStruct  *TimingH;
-	struct XGI_TimingVStruct  *TimingV;
+	struct XGI330_LCDCapStruct const *LCDCapList;
 
-	struct SiS_StandTable_S  *StandTable;
-	struct XGI_ExtStruct         *EModeIDTable;
-	struct XGI_Ext2Struct        *RefIndex;
-	struct XGI_CRT1TableStruct    *XGINEWUB_CRT1Table;
-	struct SiS_VCLKData    *VCLKData;
-	struct SiS_VBVCLKData  *VBVCLKData;
-	struct SiS_StResInfo_S   *StResInfo;
-	struct SiS_ModeResInfo_S *ModeResInfo;
-	struct XGI_XG21CRT1Struct	  *UpdateCRT1;
+	struct XGI_TimingHStruct TimingH;
+	struct XGI_TimingVStruct TimingV;
 
 	int ram_type;
 	int ram_channel;
diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
index 180aae0..39f528b 100644
--- a/drivers/staging/xgifb/vb_table.h
+++ b/drivers/staging/xgifb/vb_table.h
@@ -1,6 +1,6 @@
 #ifndef _VB_TABLE_
 #define _VB_TABLE_
-static struct SiS_MCLKData XGI340New_MCLKData[] = {
+static const struct SiS_MCLKData XGI340New_MCLKData[] = {
 	{0x16, 0x01, 0x01, 166},
 	{0x19, 0x02, 0x01, 124},
 	{0x7C, 0x08, 0x01, 200},
@@ -11,7 +11,7 @@ static struct SiS_MCLKData XGI340New_MCLKData[] = {
 	{0x5c, 0x23, 0x01, 166}
 };
 
-static struct SiS_MCLKData XGI27New_MCLKData[] = {
+static const struct SiS_MCLKData XGI27New_MCLKData[] = {
 	{0x5c, 0x23, 0x01, 166},
 	{0x19, 0x02, 0x01, 124},
 	{0x7C, 0x08, 0x80, 200},
@@ -22,7 +22,7 @@ static struct SiS_MCLKData XGI27New_MCLKData[] = {
 	{0x5c, 0x23, 0x01, 166}
 };
 
-static struct XGI_ECLKDataStruct XGI340_ECLKData[] = {
+const struct XGI_ECLKDataStruct XGI340_ECLKData[] = {
 	{0x5c, 0x23, 0x01, 166},
 	{0x55, 0x84, 0x01, 123},
 	{0x7C, 0x08, 0x01, 200},
@@ -33,21 +33,21 @@ static struct XGI_ECLKDataStruct XGI340_ECLKData[] = {
 	{0x5c, 0x23, 0x01, 166}
 };
 
-static unsigned char XG27_SR13[4][8] = {
+static const unsigned char XG27_SR13[4][8] = {
 	{0x35, 0x45, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR13 */
 	{0x41, 0x51, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR14 */
 	{0x32, 0x32, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR18 */
 	{0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}  /* SR1B */
 };
 
-static unsigned char XGI340_SR13[4][8] = {
+static const unsigned char XGI340_SR13[4][8] = {
 	{0x35, 0x45, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR13 */
 	{0x41, 0x51, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR14 */
 	{0x31, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR18 */
 	{0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}  /* SR1B */
 };
 
-static unsigned char XGI340_cr41[24][8] = {
+static const unsigned char XGI340_cr41[24][8] = {
 	{0x20, 0x50, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0 CR41 */
 	{0xc4, 0x40, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 1 CR8A */
 	{0xc4, 0x40, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 2 CR8B */
@@ -74,7 +74,7 @@ static unsigned char XGI340_cr41[24][8] = {
 	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}  /* 23 CRC5 */
 };
 
-static unsigned char XGI27_cr41[24][8] = {
+static const unsigned char XGI27_cr41[24][8] = {
 	{0x20, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0 CR41 */
 	{0xC4, 0x40, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 1 CR8A */
 	{0xC4, 0x40, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 2 CR8B */
@@ -103,7 +103,7 @@ static unsigned char XGI27_cr41[24][8] = {
 	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}  /* 23 CRC5 */
 };
 
-static unsigned char XGI340_CR6B[8][4] = {
+const unsigned char XGI340_CR6B[8][4] = {
 	{0xaa, 0xaa, 0xaa, 0xaa},
 	{0xaa, 0xaa, 0xaa, 0xaa},
 	{0xaa, 0xaa, 0xaa, 0xaa},
@@ -114,21 +114,13 @@ static unsigned char XGI340_CR6B[8][4] = {
 	{0x00, 0x00, 0x00, 0x00}
 };
 
-static unsigned char XGI340_CR6E[8][4];
-
-static unsigned char XGI340_CR6F[8][32];
-
-static unsigned char XGI340_CR89[8][2];
-
 /* CR47,CR48,CR49,CR4A,CR4B,CR4C,CR70,CR71,CR74,CR75,CR76,CR77 */
-static unsigned char XGI340_AGPReg[12] = {
+const unsigned char XGI340_AGPReg[12] = {
 	0x28, 0x23, 0x00, 0x20, 0x00, 0x20,
 	0x00, 0x05, 0xd0, 0x10, 0x10, 0x00
 };
 
-static unsigned char XGI340_SR16[4] = {0x03, 0x83, 0x03, 0x83};
-
-static struct XGI_ExtStruct XGI330_EModeIDTable[] = {
+const struct XGI_ExtStruct XGI330_EModeIDTable[] = {
 	{0x2e, 0x0a1b, 0x0306, 0x06, 0x05, 0x06},
 	{0x2f, 0x0a1b, 0x0305, 0x05, 0x05, 0x05},
 	{0x30, 0x2a1b, 0x0407, 0x07, 0x07, 0x0e},
@@ -200,7 +192,7 @@ static struct XGI_ExtStruct XGI330_EModeIDTable[] = {
 	{0xff, 0x0000, 0x0000, 0x00, 0x00, 0x00}
 };
 
-static struct SiS_StandTable_S XGI330_StandTable = {
+static const struct SiS_StandTable_S XGI330_StandTable = {
 /* ExtVGATable */
 	0x00, 0x00, 0x00, 0x0000,
 	{0x01, 0x0f, 0x00, 0x0e},
@@ -216,11 +208,7 @@ static struct SiS_StandTable_S XGI330_StandTable = {
 	 0xff}
 };
 
-static struct XGI_TimingHStruct XGI_TimingH[1];
-
-static struct XGI_TimingVStruct XGI_TimingV[1];
-
-static struct XGI_XG21CRT1Struct XGI_UpdateCRT1Table[] = {
+static const struct XGI_XG21CRT1Struct XGI_UpdateCRT1Table[] = {
 	{0x01, 0x27, 0x91, 0x8f, 0xc0},	/* 00 */
 	{0x03, 0x4f, 0x83, 0x8f, 0xc0},	/* 01 */
 	{0x05, 0x27, 0x91, 0x8f, 0xc0},	/* 02 */
@@ -240,7 +228,7 @@ static struct XGI_XG21CRT1Struct XGI_UpdateCRT1Table[] = {
 	{0x59, 0x27, 0x91, 0x8f, 0xc0}	/* 16 */
 };
 
-static struct XGI_CRT1TableStruct XGI_CRT1Table[] = {
+const struct XGI_CRT1TableStruct XGI_CRT1Table[] = {
 	{ {0x2d, 0x28, 0x90, 0x2c, 0x90, 0x00, 0x04, 0x00,
 	  0xbf, 0x1f, 0x9c, 0x8e, 0x96, 0xb9, 0x30} }, /* 0x0 */
 	{ {0x2d, 0x28, 0x90, 0x2c, 0x90, 0x00, 0x04, 0x00,
@@ -404,7 +392,7 @@ static struct XGI_CRT1TableStruct XGI_CRT1Table[] = {
 };
 
 /*add for new UNIVGABIOS*/
-static struct SiS_LCDData  XGI_StLCD1024x768Data[] = {
+static const struct SiS_LCDData XGI_StLCD1024x768Data[] = {
 	{62,  25, 800,  546, 1344, 806},
 	{32,  15, 930,  546, 1344, 806},
 	{62,  25, 800,  546, 1344, 806}, /*chiawenfordot9->dot8*/
@@ -414,7 +402,7 @@ static struct SiS_LCDData  XGI_StLCD1024x768Data[] = {
 	{1,   1,  1344, 806, 1344, 806}
 };
 
-static struct SiS_LCDData  XGI_ExtLCD1024x768Data[] = {
+static const struct SiS_LCDData XGI_ExtLCD1024x768Data[] = {
 	{42, 25, 1536, 419, 1344, 806},
 	{48, 25, 1536, 369, 1344, 806},
 	{42, 25, 1536, 419, 1344, 806},
@@ -430,7 +418,7 @@ static struct SiS_LCDData  XGI_ExtLCD1024x768Data[] = {
 	{1,  1,  1344, 806, 1344, 806}
 };
 
-static struct SiS_LCDData  XGI_CetLCD1024x768Data[] = {
+static const struct SiS_LCDData XGI_CetLCD1024x768Data[] = {
 	{1, 1, 1344, 806, 1344, 806}, /* ; 00 (320x200,320x400,
 					       640x200,640x400) */
 	{1, 1, 1344, 806, 1344, 806}, /* 01 (320x350,640x350) */
@@ -441,7 +429,7 @@ static struct SiS_LCDData  XGI_CetLCD1024x768Data[] = {
 	{1, 1, 1344, 806, 1344, 806}  /* 06 (1024x768x60Hz) */
 };
 
-static struct SiS_LCDData  XGI_StLCD1280x1024Data[] = {
+static const struct SiS_LCDData XGI_StLCD1280x1024Data[] = {
 	{22,  5,  800,  510,  1650, 1088},
 	{22,  5,  800,  510,  1650, 1088},
 	{176, 45, 900,  510,  1650, 1088},
@@ -452,7 +440,7 @@ static struct SiS_LCDData  XGI_StLCD1280x1024Data[] = {
 	{1,   1,  1688, 1066, 1688, 1066}
 };
 
-static struct SiS_LCDData  XGI_ExtLCD1280x1024Data[] = {
+static const struct SiS_LCDData XGI_ExtLCD1280x1024Data[] = {
 	{211, 60,  1024, 501,  1688, 1066},
 	{211, 60,  1024, 508,  1688, 1066},
 	{211, 60,  1024, 501,  1688, 1066},
@@ -463,7 +451,7 @@ static struct SiS_LCDData  XGI_ExtLCD1280x1024Data[] = {
 	{1,   1,   1688, 1066, 1688, 1066}
 };
 
-static struct SiS_LCDData  XGI_CetLCD1280x1024Data[] = {
+static const struct SiS_LCDData XGI_CetLCD1280x1024Data[] = {
 	{1, 1, 1688, 1066, 1688, 1066}, /* 00 (320x200,320x400,
 					       640x200,640x400) */
 	{1, 1, 1688, 1066, 1688, 1066}, /* 01 (320x350,640x350) */
@@ -476,7 +464,7 @@ static struct SiS_LCDData  XGI_CetLCD1280x1024Data[] = {
 	{1, 1, 1688, 1066, 1688, 1066}  /* 08 (1400x1050x60Hz) */
 };
 
-static struct SiS_LCDData xgifb_lcd_1400x1050[] = {
+static const struct SiS_LCDData xgifb_lcd_1400x1050[] = {
 	{211, 100, 2100, 408,  1688, 1066}, /* 00 (320x200,320x400,
 						   640x200,640x400) */
 	{211, 64,  1536, 358,  1688, 1066}, /* 01 (320x350,640x350) */
@@ -490,7 +478,7 @@ static struct SiS_LCDData xgifb_lcd_1400x1050[] = {
 	{1,   1,   1688, 1066, 1688, 1066}  /* 08 (1400x1050x60Hz) */
 };
 
-static struct SiS_LCDData  XGI_ExtLCD1600x1200Data[] = {
+static const struct SiS_LCDData XGI_ExtLCD1600x1200Data[] = {
 	{4,  1,  1620, 420,  2160, 1250}, /* 00 (320x200,320x400,
 						 640x200,640x400)*/
 	{27, 7,  1920, 375,  2160, 1250}, /* 01 (320x350,640x350) */
@@ -504,7 +492,7 @@ static struct SiS_LCDData  XGI_ExtLCD1600x1200Data[] = {
 	{1,  1,  2160, 1250, 2160, 1250}  /* 09 (1600x1200x60Hz) ;302lv */
 };
 
-static struct SiS_LCDData  XGI_StLCD1600x1200Data[] = {
+static const struct SiS_LCDData XGI_StLCD1600x1200Data[] = {
 	{27,  4,  800,  500,  2160, 1250}, /* 00 (320x200,320x400,
 						  640x200,640x400) */
 	{27,  4,  800,  500,  2160, 1250}, /* 01 (320x350,640x350) */
@@ -520,7 +508,7 @@ static struct SiS_LCDData  XGI_StLCD1600x1200Data[] = {
 
 #define XGI_CetLCD1400x1050Data XGI_CetLCD1280x1024Data
 
-static struct SiS_LCDData  XGI_NoScalingData[] = {
+static const struct SiS_LCDData XGI_NoScalingData[] = {
 	{1, 1, 800,  449,  800,  449},
 	{1, 1, 800,  449,  800,  449},
 	{1, 1, 900,  449,  900,  449},
@@ -531,7 +519,7 @@ static struct SiS_LCDData  XGI_NoScalingData[] = {
 	{1, 1, 1688, 1066, 1688, 1066}
 };
 
-static struct SiS_LCDData  XGI_ExtLCD1024x768x75Data[] = {
+static const struct SiS_LCDData XGI_ExtLCD1024x768x75Data[] = {
 	{42, 25, 1536, 419, 1344, 806}, /* ; 00 (320x200,320x400,
 						 640x200,640x400) */
 	{48, 25, 1536, 369, 1344, 806}, /* ; 01 (320x350,640x350) */
@@ -542,7 +530,7 @@ static struct SiS_LCDData  XGI_ExtLCD1024x768x75Data[] = {
 	{1,  1,  1312, 800, 1312, 800}  /* ; 06 (1024x768x75Hz) */
 };
 
-static struct SiS_LCDData  XGI_CetLCD1024x768x75Data[] = {
+static const struct SiS_LCDData XGI_CetLCD1024x768x75Data[] = {
 	{1, 1, 1312, 800, 1312, 800}, /* ; 00 (320x200,320x400,
 					       640x200,640x400) */
 	{1, 1, 1312, 800, 1312, 800}, /* ; 01 (320x350,640x350) */
@@ -553,7 +541,7 @@ static struct SiS_LCDData  XGI_CetLCD1024x768x75Data[] = {
 	{1, 1, 1312, 800, 1312, 800}  /* ; 06 (1024x768x75Hz) */
 };
 
-static struct SiS_LCDData xgifb_lcd_1280x1024x75[] = {
+static const struct SiS_LCDData xgifb_lcd_1280x1024x75[] = {
 	{211, 60,  1024, 501,  1688, 1066}, /* ; 00 (320x200,320x400,
 						     640x200,640x400) */
 	{211, 60,  1024, 508,  1688, 1066}, /* ; 01 (320x350,640x350) */
@@ -567,7 +555,7 @@ static struct SiS_LCDData xgifb_lcd_1280x1024x75[] = {
 
 #define XGI_CetLCD1280x1024x75Data XGI_CetLCD1280x1024Data
 
-static struct SiS_LCDData  XGI_NoScalingDatax75[] = {
+static const struct SiS_LCDData XGI_NoScalingDatax75[] = {
 	{1, 1, 800,  449,  800,  449},  /* ; 00 (320x200, 320x400,
 						 640x200, 640x400) */
 	{1, 1, 800,  449,  800,  449},  /* ; 01 (320x350, 640x350) */
@@ -582,7 +570,7 @@ static struct SiS_LCDData  XGI_NoScalingDatax75[] = {
 	{1, 1, 1688, 806,  1688, 806}   /* ; 0A (1280x768x75Hz) */
 };
 
-static struct XGI_LCDDesStruct XGI_ExtLCDDes1024x768Data[] = {
+static const struct XGI_LCDDesStruct XGI_ExtLCDDes1024x768Data[] = {
 	{9, 1057, 0,   771}, /* ; 00 (320x200,320x400,640x200,640x400) */
 	{9, 1057, 0,   771}, /* ; 01 (320x350,640x350) */
 	{9, 1057, 0,   771}, /* ; 02 (360x400,720x400) */
@@ -592,7 +580,7 @@ static struct XGI_LCDDesStruct XGI_ExtLCDDes1024x768Data[] = {
 	{9, 1057, 805, 770}  /* ; 06 (1024x768x60Hz) */
 };
 
-static struct XGI_LCDDesStruct XGI_StLCDDes1024x768Data[] = {
+static const struct XGI_LCDDesStruct XGI_StLCDDes1024x768Data[] = {
 	{9, 1057, 737, 703}, /* ; 00 (320x200,320x400,640x200,640x400) */
 	{9, 1057, 686, 651}, /* ; 01 (320x350,640x350) */
 	{9, 1057, 737, 703}, /* ; 02 (360x400,720x400) */
@@ -602,7 +590,7 @@ static struct XGI_LCDDesStruct XGI_StLCDDes1024x768Data[] = {
 	{9, 1057, 805, 770}  /* ; 06 (1024x768x60Hz) */
 };
 
-static struct XGI_LCDDesStruct XGI_CetLCDDes1024x768Data[] = {
+static const struct XGI_LCDDesStruct XGI_CetLCDDes1024x768Data[] = {
 	{1152, 856,  622, 587}, /* ; 00 (320x200,320x400,640x200,640x400) */
 	{1152, 856,  597, 562}, /* ; 01 (320x350,640x350) */
 	{1152, 856,  622, 587}, /* ; 02 (360x400,720x400) */
@@ -612,7 +600,7 @@ static struct XGI_LCDDesStruct XGI_CetLCDDes1024x768Data[] = {
 	{0,    1048, 805, 770}  /* ; 06 (1024x768x60Hz) */
 };
 
-static struct XGI_LCDDesStruct XGI_ExtLCDDLDes1280x1024Data[] = {
+static const struct XGI_LCDDesStruct XGI_ExtLCDDLDes1280x1024Data[] = {
 	{18, 1346, 981,  940},  /* 00 (320x200,320x400,640x200,640x400) */
 	{18, 1346, 926,  865},  /* 01 (320x350,640x350) */
 	{18, 1346, 981,  940},  /* 02 (360x400,720x400) */
@@ -623,7 +611,7 @@ static struct XGI_LCDDesStruct XGI_ExtLCDDLDes1280x1024Data[] = {
 	{18, 1346, 1065, 1024}  /* 07 (1280x1024x60Hz) */
 };
 
-static struct XGI_LCDDesStruct XGI_StLCDDLDes1280x1024Data[] = {
+static const struct XGI_LCDDesStruct XGI_StLCDDLDes1280x1024Data[] = {
 	{18, 1346, 970,  907},  /* 00 (320x200,320x400,640x200,640x400) */
 	{18, 1346, 917,  854},  /* 01 (320x350,640x350) */
 	{18, 1346, 970,  907},  /* 02 (360x400,720x400) */
@@ -634,7 +622,7 @@ static struct XGI_LCDDesStruct XGI_StLCDDLDes1280x1024Data[] = {
 	{18, 1346, 1065, 1024}  /* 07 (1280x1024x60Hz) */
 };
 
-static struct XGI_LCDDesStruct XGI_CetLCDDLDes1280x1024Data[] = {
+static const struct XGI_LCDDesStruct XGI_CetLCDDLDes1280x1024Data[] = {
 	{1368, 1008, 752,  711}, /* 00 (320x200,320x400,640x200,640x400) */
 	{1368, 1008, 729,  688}, /* 01 (320x350,640x350) */
 	{1368, 1008, 752,  711}, /* 02 (360x400,720x400) */
@@ -645,7 +633,7 @@ static struct XGI_LCDDesStruct XGI_CetLCDDLDes1280x1024Data[] = {
 	{18,   1346, 1065, 1024} /* 07 (1280x1024x60Hz) */
 };
 
-static struct XGI_LCDDesStruct XGI_ExtLCDDes1280x1024Data[] = {
+static const struct XGI_LCDDesStruct XGI_ExtLCDDes1280x1024Data[] = {
 	{9, 1337, 981,  940},  /* ; 00 (320x200,320x400,640x200,640x400) */
 	{9, 1337, 926,  884},  /* ; 01 (320x350,640x350) alan, 2003/09/30 */
 	{9, 1337, 981,  940},  /* ; 02 (360x400,720x400) */
@@ -656,7 +644,7 @@ static struct XGI_LCDDesStruct XGI_ExtLCDDes1280x1024Data[] = {
 	{9, 1337, 1065, 1024}  /* ; 07 (1280x1024x60Hz) */
 };
 
-static struct XGI_LCDDesStruct XGI_StLCDDes1280x1024Data[] = {
+static const struct XGI_LCDDesStruct XGI_StLCDDes1280x1024Data[] = {
 	{9, 1337, 970,  907},  /* ; 00 (320x200,320x400,640x200,640x400) */
 	{9, 1337, 917,  854},  /* ; 01 (320x350,640x350) */
 	{9, 1337, 970,  907},  /* ; 02 (360x400,720x400) */
@@ -667,7 +655,7 @@ static struct XGI_LCDDesStruct XGI_StLCDDes1280x1024Data[] = {
 	{9, 1337, 1065, 1024}  /* ; 07 (1280x1024x60Hz) */
 };
 
-static struct XGI_LCDDesStruct XGI_CetLCDDes1280x1024Data[] = {
+static const struct XGI_LCDDesStruct XGI_CetLCDDes1280x1024Data[] = {
 	{1368, 1008, 752,  711}, /* 00 (320x200,320x400,640x200,640x400) */
 	{1368, 1008, 729,  688}, /* 01 (320x350,640x350) */
 	{1368, 1008, 752,  711}, /* 02 (360x400,720x400) */
@@ -678,7 +666,7 @@ static struct XGI_LCDDesStruct XGI_CetLCDDes1280x1024Data[] = {
 	{9,    1337, 1065, 1024} /* 07 (1280x1024x60Hz) */
 };
 
-static struct XGI_LCDDesStruct xgifb_lcddldes_1400x1050[] = {
+static const struct XGI_LCDDesStruct xgifb_lcddldes_1400x1050[] = {
 	{18,   1464, 0,    1051}, /* 00 (320x200,320x400,640x200,640x400) */
 	{18,   1464, 0,    1051}, /* 01 (320x350,640x350) */
 	{18,   1464, 0,    1051}, /* 02 (360x400,720x400) */
@@ -690,7 +678,7 @@ static struct XGI_LCDDesStruct xgifb_lcddldes_1400x1050[] = {
 	{18,   1464, 0,    1051}  /* 08 (1400x1050x60Hz) */
 };
 
-static struct XGI_LCDDesStruct xgifb_lcddes_1400x1050[] = {
+static const struct XGI_LCDDesStruct xgifb_lcddes_1400x1050[] = {
 	{9,    1455, 0,    1051}, /* 00 (320x200,320x400,640x200,640x400) */
 	{9,    1455, 0,    1051}, /* 01 (320x350,640x350) */
 	{9,    1455, 0,    1051}, /* 02 (360x400,720x400) */
@@ -702,7 +690,7 @@ static struct XGI_LCDDesStruct xgifb_lcddes_1400x1050[] = {
 	{9,    1455, 0,    1051}  /* 08 (1400x1050x60Hz) */
 };
 
-static struct XGI_LCDDesStruct XGI_CetLCDDes1400x1050Data[] = {
+static const struct XGI_LCDDesStruct XGI_CetLCDDes1400x1050Data[] = {
 	{1308, 1068, 781,  766},  /* 00 (320x200,320x400,640x200,640x400) */
 	{1308, 1068, 781,  766},  /* 01 (320x350,640x350) */
 	{1308, 1068, 781,  766},  /* 02 (360x400,720x400) */
@@ -714,7 +702,7 @@ static struct XGI_LCDDesStruct XGI_CetLCDDes1400x1050Data[] = {
 	{18,   1464, 0,    1051}  /* 08 (1400x1050x60Hz) */
 };
 
-static struct XGI_LCDDesStruct XGI_CetLCDDes1400x1050Data2[] = {
+static const struct XGI_LCDDesStruct XGI_CetLCDDes1400x1050Data2[] = {
 	{0, 1448, 0, 1051}, /* 00 (320x200,320x400,640x200,640x400) */
 	{0, 1448, 0, 1051}, /* 01 (320x350,640x350) */
 	{0, 1448, 0, 1051}, /* 02 (360x400,720x400) */
@@ -722,7 +710,7 @@ static struct XGI_LCDDesStruct XGI_CetLCDDes1400x1050Data2[] = {
 	{0, 1448, 0, 1051}  /* 04 (640x480x60Hz) */
 };
 
-static struct XGI_LCDDesStruct XGI_ExtLCDDLDes1600x1200Data[] = {
+static const struct XGI_LCDDesStruct XGI_ExtLCDDLDes1600x1200Data[] = {
 	{18, 1682, 0, 1201}, /* 00 (320x200,320x400,640x200,640x400) */
 	{18, 1682, 0, 1201}, /* 01 (320x350,640x350) */
 	{18, 1682, 0, 1201}, /* 02 (360x400,720x400) */
@@ -735,7 +723,7 @@ static struct XGI_LCDDesStruct XGI_ExtLCDDLDes1600x1200Data[] = {
 	{18, 1682, 0, 1201}  /* 09 (1600x1200x60Hz) */
 };
 
-static struct XGI_LCDDesStruct XGI_StLCDDLDes1600x1200Data[] = {
+static const struct XGI_LCDDesStruct XGI_StLCDDLDes1600x1200Data[] = {
 	{18, 1682, 1150, 1101}, /* 00 (320x200,320x400,640x200,640x400) */
 	{18, 1682, 1083, 1034}, /* 01 (320x350,640x350) */
 	{18, 1682, 1150, 1101}, /* 02 (360x400,720x400) */
@@ -748,7 +736,7 @@ static struct XGI_LCDDesStruct XGI_StLCDDLDes1600x1200Data[] = {
 	{18, 1682, 0,    1201} /* 09 (1600x1200x60Hz) */
 };
 
-static struct XGI_LCDDesStruct XGI_ExtLCDDes1600x1200Data[] = {
+static const struct XGI_LCDDesStruct XGI_ExtLCDDes1600x1200Data[] = {
 	{9, 1673, 0, 1201}, /* 00 (320x200,320x400,640x200,640x400) */
 	{9, 1673, 0, 1201}, /* 01 (320x350,640x350) */
 	{9, 1673, 0, 1201}, /* 02 (360x400,720x400) */
@@ -761,7 +749,7 @@ static struct XGI_LCDDesStruct XGI_ExtLCDDes1600x1200Data[] = {
 	{9, 1673, 0, 1201}  /* 09 (1600x1200x60Hz) */
 };
 
-static struct XGI_LCDDesStruct XGI_StLCDDes1600x1200Data[] = {
+static const struct XGI_LCDDesStruct XGI_StLCDDes1600x1200Data[] = {
 	{9, 1673, 1150, 1101}, /* 00 (320x200,320x400,640x200,640x400) */
 	{9, 1673, 1083, 1034}, /* 01 (320x350,640x350) */
 	{9, 1673, 1150, 1101}, /* 02 (360x400,720x400) */
@@ -774,7 +762,7 @@ static struct XGI_LCDDesStruct XGI_StLCDDes1600x1200Data[] = {
 	{9, 1673, 0,    1201}  /* 09 (1600x1200x60Hz) */
 };
 
-static struct XGI330_LCDDataDesStruct2  XGI_NoScalingDesData[] = {
+static const struct XGI330_LCDDataDesStruct2  XGI_NoScalingDesData[] = {
 	{9, 657,  448, 405,  96,   2}, /* 00 (320x200,320x400,
 					      640x200,640x400) */
 	{9, 657,  448, 355,  96,   2}, /* 01 (320x350,640x350) */
@@ -790,7 +778,7 @@ static struct XGI330_LCDDataDesStruct2  XGI_NoScalingDesData[] = {
 };
 
 /* ;;1024x768x75Hz */
-static struct XGI_LCDDesStruct xgifb_lcddes_1024x768x75[] = {
+static const struct XGI_LCDDesStruct xgifb_lcddes_1024x768x75[] = {
 	{9, 1049, 0, 769}, /* ; 00 (320x200,320x400,640x200,640x400) */
 	{9, 1049, 0, 769}, /* ; 01 (320x350,640x350) */
 	{9, 1049, 0, 769}, /* ; 02 (360x400,720x400) */
@@ -801,7 +789,7 @@ static struct XGI_LCDDesStruct xgifb_lcddes_1024x768x75[] = {
 };
 
 /* ;;1024x768x75Hz */
-static struct XGI_LCDDesStruct XGI_CetLCDDes1024x768x75Data[] = {
+static const struct XGI_LCDDesStruct XGI_CetLCDDes1024x768x75Data[] = {
 	{1152, 856,  622, 587}, /* ; 00 (320x200,320x400,640x200,640x400) */
 	{1152, 856,  597, 562}, /* ; 01 (320x350,640x350) */
 	{1192, 896,  622, 587}, /* ; 02 (360x400,720x400) */
@@ -812,7 +800,7 @@ static struct XGI_LCDDesStruct XGI_CetLCDDes1024x768x75Data[] = {
 };
 
 /* ;;1280x1024x75Hz */
-static struct XGI_LCDDesStruct xgifb_lcddldes_1280x1024x75[] = {
+static const struct XGI_LCDDesStruct xgifb_lcddldes_1280x1024x75[] = {
 	{18, 1314, 0, 1025}, /* ; 00 (320x200,320x400,640x200,640x400) */
 	{18, 1314, 0, 1025}, /* ; 01 (320x350,640x350) */
 	{18, 1314, 0, 1025}, /* ; 02 (360x400,720x400) */
@@ -824,7 +812,7 @@ static struct XGI_LCDDesStruct xgifb_lcddldes_1280x1024x75[] = {
 };
 
 /* 1280x1024x75Hz */
-static struct XGI_LCDDesStruct XGI_CetLCDDLDes1280x1024x75Data[] = {
+static const struct XGI_LCDDesStruct XGI_CetLCDDLDes1280x1024x75Data[] = {
 	{1368, 1008, 752, 711}, /* ; 00 (320x200,320x400,640x200,640x400) */
 	{1368, 1008, 729, 688}, /* ; 01 (320x350,640x350) */
 	{1408, 1048, 752, 711}, /* ; 02 (360x400,720x400) */
@@ -836,7 +824,7 @@ static struct XGI_LCDDesStruct XGI_CetLCDDLDes1280x1024x75Data[] = {
 };
 
 /* ;;1280x1024x75Hz */
-static struct XGI_LCDDesStruct xgifb_lcddes_1280x1024x75[] = {
+static const struct XGI_LCDDesStruct xgifb_lcddes_1280x1024x75[] = {
 	{9, 1305, 0, 1025}, /* ; 00 (320x200,320x400,640x200,640x400) */
 	{9, 1305, 0, 1025}, /* ; 01 (320x350,640x350) */
 	{9, 1305, 0, 1025}, /* ; 02 (360x400,720x400) */
@@ -848,7 +836,7 @@ static struct XGI_LCDDesStruct xgifb_lcddes_1280x1024x75[] = {
 };
 
 /* 1280x1024x75Hz */
-static struct XGI_LCDDesStruct XGI_CetLCDDes1280x1024x75Data[] = {
+static const struct XGI_LCDDesStruct XGI_CetLCDDes1280x1024x75Data[] = {
 	{1368, 1008, 752, 711}, /* ; 00 (320x200,320x400,640x200,640x400) */
 	{1368, 1008, 729, 688}, /* ; 01 (320x350,640x350) */
 	{1408, 1048, 752, 711}, /* ; 02 (360x400,720x400) */
@@ -860,7 +848,7 @@ static struct XGI_LCDDesStruct XGI_CetLCDDes1280x1024x75Data[] = {
 };
 
 /* Scaling LCD 75Hz */
-static struct XGI330_LCDDataDesStruct2 XGI_NoScalingDesDatax75[] =  {
+static const struct XGI330_LCDDataDesStruct2 XGI_NoScalingDesDatax75[] =  {
 	{9, 657,  448, 405,  96,  2}, /* ; 00 (320x200,320x400,
 					       640x200,640x400) */
 	{9, 657,  448, 355,  96,  2}, /* ; 01 (320x350,640x350) */
@@ -1174,7 +1162,7 @@ static const unsigned char XGI330_Ren750pGroup3[] = {
 	0x18, 0x1D, 0x23, 0x28, 0x4C, 0xAA, 0x01
 };
 
-static struct SiS_LVDSData  XGI_LVDS1024x768Data_1[] = {
+static const struct SiS_LVDSData XGI_LVDS1024x768Data_1[] = {
 	{ 960, 438, 1344, 806},	/* 00 (320x200,320x400,640x200,640x400) */
 	{ 960, 388, 1344, 806},	/* 01 (320x350,640x350) */
 	{1040, 438, 1344, 806},	/* 02 (360x400,720x400) */
@@ -1185,7 +1173,7 @@ static struct SiS_LVDSData  XGI_LVDS1024x768Data_1[] = {
 };
 
 
-static struct SiS_LVDSData  XGI_LVDS1024x768Data_2[] = {
+static const struct SiS_LVDSData XGI_LVDS1024x768Data_2[] = {
 	{1344, 806, 1344, 806},
 	{1344, 806, 1344, 806},
 	{1344, 806, 1344, 806},
@@ -1197,7 +1185,7 @@ static struct SiS_LVDSData  XGI_LVDS1024x768Data_2[] = {
 	{800,  525, 1280, 813}
 };
 
-static struct SiS_LVDSData  XGI_LVDS1280x1024Data_1[] = {
+static const struct SiS_LVDSData XGI_LVDS1280x1024Data_1[] = {
 	{1048, 442,  1688, 1066},
 	{1048, 392,  1688, 1066},
 	{1048, 442,  1688, 1066},
@@ -1210,7 +1198,7 @@ static struct SiS_LVDSData  XGI_LVDS1280x1024Data_1[] = {
 
 #define XGI_LVDS1280x1024Data_2 XGI_LVDS1024x768Data_2
 
-static struct SiS_LVDSData  XGI_LVDS1400x1050Data_1[] = {
+static const struct SiS_LVDSData XGI_LVDS1400x1050Data_1[] = {
 	{928,   416, 1688, 1066},
 	{928,   366, 1688, 1066},
 	{928,   416, 1688, 1066},
@@ -1222,7 +1210,7 @@ static struct SiS_LVDSData  XGI_LVDS1400x1050Data_1[] = {
 	{1688, 1066, 1688, 1066}
 };
 
-static struct SiS_LVDSData  XGI_LVDS1400x1050Data_2[] = {
+static const struct SiS_LVDSData XGI_LVDS1400x1050Data_2[] = {
 	{1688, 1066, 1688, 1066},
 	{1688, 1066, 1688, 1066},
 	{1688, 1066, 1688, 1066},
@@ -1235,7 +1223,7 @@ static struct SiS_LVDSData  XGI_LVDS1400x1050Data_2[] = {
 };
 
 /* ;;[ycchen] 12/05/02 LCDHTxLCDVT=2048x1320 */
-static struct SiS_LVDSData XGI_LVDS1600x1200Data_1[] = {
+static const struct SiS_LVDSData XGI_LVDS1600x1200Data_1[] = {
 	{1088, 520,  2048, 1320}, /* 00 (320x200,320x400,640x200,640x400) */
 	{1088, 470,  2048, 1320}, /* 01 (320x350,640x350) */
 	{1088, 520,  2048, 1320}, /* 02 (360x400,720x400) */
@@ -1248,7 +1236,7 @@ static struct SiS_LVDSData XGI_LVDS1600x1200Data_1[] = {
 	{2048, 1320, 2048, 1320}  /* 09 (1600x1200) */
 };
 
-static struct SiS_LVDSData XGI_LVDSNoScalingData[] = {
+static const struct SiS_LVDSData XGI_LVDSNoScalingData[] = {
 	{ 800,  449,  800,  449}, /* 00 (320x200,320x400,640x200,640x400) */
 	{ 800,  449,  800,  449}, /* 01 (320x350,640x350) */
 	{ 800,  449,  800,  449}, /* 02 (360x400,720x400) */
@@ -1262,7 +1250,7 @@ static struct SiS_LVDSData XGI_LVDSNoScalingData[] = {
 	{1688,  806, 1688,  806}  /* 0A (1280x768x60Hz) */
 };
 
-static struct SiS_LVDSData XGI_LVDS1024x768Data_1x75[] = {
+static const struct SiS_LVDSData XGI_LVDS1024x768Data_1x75[] = {
 	{ 960, 438, 1312, 800}, /* 00 (320x200,320x400,640x200,640x400) */
 	{ 960, 388, 1312, 800}, /* 01 (320x350,640x350) */
 	{1040, 438, 1312, 800}, /* 02 (360x400,720x400) */
@@ -1273,7 +1261,7 @@ static struct SiS_LVDSData XGI_LVDS1024x768Data_1x75[] = {
 };
 
 
-static struct SiS_LVDSData XGI_LVDS1024x768Data_2x75[] = {
+static const struct SiS_LVDSData XGI_LVDS1024x768Data_2x75[] = {
 	{1312, 800, 1312, 800}, /* ; 00 (320x200,320x400,640x200,640x400) */
 	{1312, 800, 1312, 800}, /* ; 01 (320x350,640x350) */
 	{1312, 800, 1312, 800}, /* ; 02 (360x400,720x400) */
@@ -1283,7 +1271,7 @@ static struct SiS_LVDSData XGI_LVDS1024x768Data_2x75[] = {
 	{1312, 800, 1312, 800}, /* ; 06 (512x384,1024x768) */
 };
 
-static struct SiS_LVDSData XGI_LVDS1280x1024Data_1x75[] = {
+static const struct SiS_LVDSData XGI_LVDS1280x1024Data_1x75[] = {
 	{1048,  442, 1688, 1066  }, /* ; 00 (320x200,320x400,640x200,640x400) */
 	{1048,  392, 1688, 1066  }, /* ; 01 (320x350,640x350) */
 	{1128,  442, 1688, 1066  }, /* ; 02 (360x400,720x400) */
@@ -1294,7 +1282,7 @@ static struct SiS_LVDSData XGI_LVDS1280x1024Data_1x75[] = {
 	{1688, 1066, 1688, 1066 },  /* ; 06; 07 (640x512,1280x1024) */
 };
 
-static struct SiS_LVDSData XGI_LVDS1280x1024Data_2x75[] = {
+static const struct SiS_LVDSData XGI_LVDS1280x1024Data_2x75[] = {
 	{1688, 1066, 1688, 1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */
 	{1688, 1066, 1688, 1066 }, /* ; 01 (320x350,640x350) */
 	{1688, 1066, 1688, 1066 }, /* ; 02 (360x400,720x400) */
@@ -1305,7 +1293,7 @@ static struct SiS_LVDSData XGI_LVDS1280x1024Data_2x75[] = {
 	{1688, 1066, 1688, 1066 }, /* ; 06; 07 (640x512,1280x1024) */
 };
 
-static struct SiS_LVDSData XGI_LVDSNoScalingDatax75[] = {
+static const struct SiS_LVDSData XGI_LVDSNoScalingDatax75[] = {
 	{ 800,  449,  800, 449},  /* ; 00 (320x200,320x400,640x200,640x400) */
 	{ 800,  449,  800, 449},  /* ; 01 (320x350,640x350) */
 	{ 900,  449,  900, 449},  /* ; 02 (360x400,720x400) */
@@ -1320,7 +1308,7 @@ static struct SiS_LVDSData XGI_LVDSNoScalingDatax75[] = {
 	{1688,  806, 1688, 806},  /* ; 0A (1280x768x75Hz) */
 };
 
-static struct SiS_LVDSData XGI_LVDS1024x768Des_1[] = {
+static const struct SiS_LVDSData XGI_LVDS1024x768Des_1[] = {
 	{0, 1048,   0, 771}, /* 00 (320x200,320x400,640x200,640x400) */
 	{0, 1048,   0, 771}, /* 01 (320x350,640x350) */
 	{0, 1048,   0, 771}, /* 02 (360x400,720x400) */
@@ -1330,7 +1318,7 @@ static struct SiS_LVDSData XGI_LVDS1024x768Des_1[] = {
 	{0, 1048, 805, 770}  /* 06 (1024x768x60Hz) */
 } ;
 
-static struct SiS_LVDSData XGI_LVDS1024x768Des_2[] = {
+static const struct SiS_LVDSData XGI_LVDS1024x768Des_2[] = {
 	{1142,  856, 622, 587}, /* 00 (320x200,320x400,640x200,640x400) */
 	{1142,  856, 597, 562}, /* 01 (320x350,640x350) */
 	{1142,  856, 622, 587}, /* 02 (360x400,720x400) */
@@ -1340,7 +1328,7 @@ static struct SiS_LVDSData XGI_LVDS1024x768Des_2[] = {
 	{   0, 1048, 805, 771}  /* 06 (1024x768x60Hz) */
 };
 
-static struct SiS_LVDSData XGI_LVDS1024x768Des_3[] = {
+static const struct SiS_LVDSData XGI_LVDS1024x768Des_3[] = {
 	{320, 24, 622, 587}, /* 00 (320x200,320x400,640x200,640x400) */
 	{320, 24, 597, 562}, /* 01 (320x350,640x350) */
 	{320, 24, 622, 587}, /* 02 (360x400,720x400) */
@@ -1348,7 +1336,7 @@ static struct SiS_LVDSData XGI_LVDS1024x768Des_3[] = {
 	{320, 24, 722, 687}  /* 04 (640x480x60Hz) */
 };
 
-static struct SiS_LVDSData XGI_LVDS1280x1024Des_1[] = {
+static const struct SiS_LVDSData XGI_LVDS1280x1024Des_1[] = {
 	{0, 1328,    0, 1025}, /* 00 (320x200,320x400,640x200,640x400) */
 	{0, 1328,    0, 1025}, /* 01 (320x350,640x350) */
 	{0, 1328,    0, 1025}, /* 02 (360x400,720x400) */
@@ -1360,7 +1348,7 @@ static struct SiS_LVDSData XGI_LVDS1280x1024Des_1[] = {
 };
 
  /* The Display setting for DE Mode Panel */
-static struct SiS_LVDSData XGI_LVDS1280x1024Des_2[] = {
+static const struct SiS_LVDSData XGI_LVDS1280x1024Des_2[] = {
 	{1368, 1008, 752, 711}, /* 00 (320x200,320x400,640x200,640x400) */
 	{1368, 1008, 729, 688}, /* 01 (320x350,640x350) */
 	{1408, 1048, 752, 711}, /* 02 (360x400,720x400) */
@@ -1371,7 +1359,7 @@ static struct SiS_LVDSData XGI_LVDS1280x1024Des_2[] = {
 	{0000, 1328,   0, 1025} /* 07 (1280x1024x60Hz) */
 };
 
-static struct SiS_LVDSData XGI_LVDS1400x1050Des_1[] = {
+static const struct SiS_LVDSData XGI_LVDS1400x1050Des_1[] = {
 	{0, 1448, 0, 1051}, /* 00 (320x200,320x400,640x200,640x400) */
 	{0, 1448, 0, 1051}, /* 01 (320x350,640x350) */
 	{0, 1448, 0, 1051}, /* 02 (360x400,720x400) */
@@ -1383,7 +1371,7 @@ static struct SiS_LVDSData XGI_LVDS1400x1050Des_1[] = {
 	{0, 1448, 0, 1051}  /* 08 (1400x1050x60Hz) */
 };
 
-static struct SiS_LVDSData XGI_LVDS1400x1050Des_2[] = {
+static const struct SiS_LVDSData XGI_LVDS1400x1050Des_2[] = {
 	{1308, 1068,  781,  766}, /* 00 (320x200,320x400,640x200,640x400) */
 	{1308, 1068,  781,  766}, /* 01 (320x350,640x350) */
 	{1308, 1068,  781,  766}, /* 02 (360x400,720x400) */
@@ -1395,7 +1383,7 @@ static struct SiS_LVDSData XGI_LVDS1400x1050Des_2[] = {
 	{   0, 1448,    0, 1051}  /* 08 (1400x1050x60Hz) */
 };
 
-static struct SiS_LVDSData XGI_LVDS1600x1200Des_1[] = {
+static const struct SiS_LVDSData XGI_LVDS1600x1200Des_1[] = {
 	{0, 1664, 0, 1201}, /* 00 (320x200,320x400,640x200,640x400) */
 	{0, 1664, 0, 1201}, /* 01 (320x350,640x350) */
 	{0, 1664, 0, 1201}, /* 02 (360x400,720x400) */
@@ -1408,7 +1396,7 @@ static struct SiS_LVDSData XGI_LVDS1600x1200Des_1[] = {
 	{0, 1664, 0, 1201}  /* 09 (1600x1200x60Hz) */
 };
 
-static struct XGI330_LCDDataDesStruct2  XGI_LVDSNoScalingDesData[] = {
+static const struct XGI330_LCDDataDesStruct2  XGI_LVDSNoScalingDesData[] = {
 	{0,  648,  448,  405,  96, 2}, /* 00 (320x200,320x400,
 					      640x200,640x400) */
 	{0,  648,  448,  355,  96, 2}, /* 01 (320x350,640x350) */
@@ -1424,7 +1412,7 @@ static struct XGI330_LCDDataDesStruct2  XGI_LVDSNoScalingDesData[] = {
 };
 
 /* ; 1024x768 Full-screen */
-static struct SiS_LVDSData XGI_LVDS1024x768Des_1x75[] = {
+static const struct SiS_LVDSData XGI_LVDS1024x768Des_1x75[] = {
 	{0, 1040, 0, 769}, /* ; 00 (320x200,320x400,640x200,640x400) */
 	{0, 1040, 0, 769}, /* ; 01 (320x350,640x350) */
 	{0, 1040, 0, 769}, /* ; 02 (360x400,720x400) */
@@ -1435,7 +1423,7 @@ static struct SiS_LVDSData XGI_LVDS1024x768Des_1x75[] = {
 };
 
 /* ; 1024x768 center-screen (Enh. Mode) */
-static struct SiS_LVDSData XGI_LVDS1024x768Des_2x75[] = {
+static const struct SiS_LVDSData XGI_LVDS1024x768Des_2x75[] = {
 	{1142,  856, 622, 587}, /* 00 (320x200,320x400,640x200,640x400) */
 	{1142,  856, 597, 562}, /* 01 (320x350,640x350) */
 	{1142,  856, 622, 587}, /* 02 (360x400,720x400) */
@@ -1446,7 +1434,7 @@ static struct SiS_LVDSData XGI_LVDS1024x768Des_2x75[] = {
 };
 
 /* ; 1024x768 center-screen (St.Mode) */
-static struct SiS_LVDSData XGI_LVDS1024x768Des_3x75[] =  {
+static const struct SiS_LVDSData XGI_LVDS1024x768Des_3x75[] =  {
 	{320, 24, 622, 587}, /* ; 00 (320x200,320x400,640x200,640x400) */
 	{320, 24, 597, 562}, /* ; 01 (320x350,640x350) */
 	{320, 24, 622, 587}, /* ; 02 (360x400,720x400) */
@@ -1454,7 +1442,7 @@ static struct SiS_LVDSData XGI_LVDS1024x768Des_3x75[] =  {
 	{320, 24, 722, 687}  /* ; 04 (640x480x60Hz) */
 };
 
-static struct SiS_LVDSData XGI_LVDS1280x1024Des_1x75[] = {
+static const struct SiS_LVDSData XGI_LVDS1280x1024Des_1x75[] = {
 	{0, 1296, 0, 1025}, /* ; 00 (320x200,320x400,640x200,640x400) */
 	{0, 1296, 0, 1025}, /* ; 01 (320x350,640x350) */
 	{0, 1296, 0, 1025}, /* ; 02 (360x400,720x400) */
@@ -1467,7 +1455,7 @@ static struct SiS_LVDSData XGI_LVDS1280x1024Des_1x75[] = {
 
 /* The Display setting for DE Mode Panel */
 /* Set DE as default */
-static struct SiS_LVDSData XGI_LVDS1280x1024Des_2x75[] = {
+static const struct SiS_LVDSData XGI_LVDS1280x1024Des_2x75[] = {
 	{1368,  976, 752,  711}, /* ; 00 (320x200,320x400,640x200,640x400) */
 	{1368,  976, 729,  688}, /* ; 01 (320x350,640x350) */
 	{1408,  976, 752,  711}, /* ; 02 (360x400,720x400) */
@@ -1479,7 +1467,7 @@ static struct SiS_LVDSData XGI_LVDS1280x1024Des_2x75[] = {
 };
 
 /* Scaling LCD 75Hz */
-static struct XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[] = {
+static const struct XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[] = {
 	{0,  648, 448,  405,  96, 2}, /* ; 00 (320x200,320x400,
 					       640x200,640x400) */
 	{0,  648, 448,  355,  96, 2}, /* ; 01 (320x350,640x350) */
@@ -1495,7 +1483,7 @@ static struct XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[] = {
 };
 
 /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static struct XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11024x768_1_H[] = {
+static const struct XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11024x768_1_H[] = {
 	{ {0x4B, 0x27, 0x8F, 0x32, 0x1B, 0x00, 0x45, 0x00} }, /* 00 (320x) */
 	{ {0x4B, 0x27, 0x8F, 0x2B, 0x03, 0x00, 0x44, 0x00} }, /* 01 (360x) */
 	{ {0x55, 0x31, 0x99, 0x46, 0x1D, 0x00, 0x55, 0x00} }, /* 02 (400x) */
@@ -1507,7 +1495,7 @@ static struct XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11024x768_1_H[] = {
 };
 
 /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static struct XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11280x1024_1_H[] = {
+static const struct XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11280x1024_1_H[] = {
 	{ {0x56, 0x27, 0x9A, 0x30, 0x1E, 0x00, 0x05, 0x00 } }, /* 00 (320x) */
 	{ {0x56, 0x27, 0x9A, 0x30, 0x1E, 0x00, 0x05, 0x00 } }, /* 01 (360x) */
 	{ {0x60, 0x31, 0x84, 0x3A, 0x88, 0x00, 0x01, 0x00 } }, /* 02 (400x) */
@@ -1520,7 +1508,7 @@ static struct XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11280x1024_1_H[] = {
 };
 
 /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static struct XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11024x768_2_H[] = {
+static const struct XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11024x768_2_H[] = {
 	{ {0x63, 0x27, 0x87, 0x3B, 0x8C, 0x00, 0x01, 0x00} }, /* 00 (320x) */
 	{ {0x63, 0x27, 0x87, 0x3B, 0x8C, 0x00, 0x01, 0x00} }, /* 01 (360x) */
 	{ {0x63, 0x31, 0x87, 0x3D, 0x8E, 0x00, 0x01, 0x00} }, /* 02 (400x) */
@@ -1532,7 +1520,7 @@ static struct XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11024x768_2_H[] = {
 };
 
 /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static struct XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11280x1024_2_H[] = {
+static const struct XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11280x1024_2_H[] = {
 	{ {0x7E, 0x3B, 0x9A, 0x44, 0x12, 0x00, 0x01, 0x00} }, /* 00 (320x) */
 	{ {0x7E, 0x3B, 0x9A, 0x44, 0x12, 0x00, 0x01, 0x00} }, /* 01 (360x) */
 	{ {0x7E, 0x40, 0x84, 0x49, 0x91, 0x00, 0x01, 0x00} }, /* 02 (400x) */
@@ -1545,7 +1533,7 @@ static struct XGI_LVDSCRT1HDataStruct  XGI_LVDSCRT11280x1024_2_H[] = {
 };
 
 /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_1_H[] = {
+static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_1_H[] = {
 	{ {0x47, 0x27, 0x8B, 0x2C, 0x1A, 0x00, 0x05, 0x00} }, /* 00 (320x) */
 	{ {0x47, 0x27, 0x8B, 0x30, 0x1E, 0x00, 0x05, 0x00} }, /* 01 (360x) */
 	{ {0x51, 0x31, 0x95, 0x36, 0x04, 0x00, 0x01, 0x00} }, /* 02 (400x) */
@@ -1559,7 +1547,7 @@ static struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_1_H[] = {
 };
 
 /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_2_H[] = {
+static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_2_H[] = {
 	{ {0x76, 0x3F, 0x83, 0x45, 0x8C, 0x00, 0x41, 0x00} }, /* 00 (320x) */
 	{ {0x76, 0x3F, 0x83, 0x45, 0x8C, 0x00, 0x41, 0x00} }, /* 01 (360x) */
 	{ {0x76, 0x31, 0x9A, 0x48, 0x9F, 0x00, 0x41, 0x00} }, /* 02 (400x) */
@@ -1574,7 +1562,7 @@ static struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_2_H[] = {
 
 /* ;302lv channelA [ycchen] 12/05/02 LCDHT=2048 */
 /* ; CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11600x1200_1_H[] = {
+static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11600x1200_1_H[] = {
 	{ {0x5B, 0x27, 0x9F, 0x32, 0x0A, 0x00, 0x01, 0x00} }, /* 00 (320x) */
 	{ {0x5B, 0x27, 0x9F, 0x32, 0x0A, 0x00, 0x01, 0x00} }, /* 01 (360x) */
 	{ {0x65, 0x31, 0x89, 0x3C, 0x94, 0x00, 0x01, 0x00} }, /* 02 (400x) */
@@ -1589,7 +1577,7 @@ static struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11600x1200_1_H[] = {
 };
 
 /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
-static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_V[] = {
+static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_V[] = {
 	{ {0x97, 0x1F, 0x60, 0x87, 0x5D, 0x83, 0x10} }, /* 00 (x350) */
 	{ {0xB4, 0x1F, 0x92, 0x89, 0x8F, 0xB5, 0x30} }, /* 01 (x400) */
 	{ {0x04, 0x3E, 0xE2, 0x89, 0xDF, 0x05, 0x00} }, /* 02 (x480) */
@@ -1598,7 +1586,7 @@ static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_V[] = {
 };
 
 /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
-static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_V[] = {
+static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_V[] = {
 	{ {0x24, 0xBB, 0x31, 0x87, 0x5D, 0x25, 0x30} }, /* 00 (x350) */
 	{ {0x24, 0xBB, 0x4A, 0x80, 0x8F, 0x25, 0x30} }, /* 01 (x400) */
 	{ {0x24, 0xBB, 0x72, 0x88, 0xDF, 0x25, 0x30} }, /* 02 (x480) */
@@ -1607,7 +1595,7 @@ static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_V[] = {
 };
 
 /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
-static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_V[] = {
+static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_V[] = {
 	{ {0x86, 0x1F, 0x5E, 0x82, 0x5D, 0x87, 0x00} }, /* 00 (x350) */
 	{ {0xB8, 0x1F, 0x90, 0x84, 0x8F, 0xB9, 0x30} }, /* 01 (x400) */
 	{ {0x08, 0x3E, 0xE0, 0x84, 0xDF, 0x09, 0x00} }, /* 02 (x480) */
@@ -1617,7 +1605,7 @@ static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_V[] = {
 };
 
 /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
-static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_V[] = {
+static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_V[] = {
 	{ {0x28, 0xD2, 0xAF, 0x83, 0xAE, 0xD8, 0xA1} }, /* 00 (x350) */
 	{ {0x28, 0xD2, 0xC8, 0x8C, 0xC7, 0xF2, 0x81} }, /* 01 (x400) */
 	{ {0x28, 0xD2, 0xF0, 0x84, 0xEF, 0x1A, 0xB1} }, /* 02 (x480) */
@@ -1627,7 +1615,7 @@ static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_V[] = {
 };
 
 /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
-static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_1_V[] = {
+static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_1_V[] = {
 	{ {0x6C, 0x1F, 0x60, 0x84, 0x5D, 0x6D, 0x10} }, /* 00 (x350) */
 	{ {0x9E, 0x1F, 0x93, 0x86, 0x8F, 0x9F, 0x30} }, /* 01 (x400) */
 	{ {0xEE, 0x1F, 0xE2, 0x86, 0xDF, 0xEF, 0x10} }, /* 02 (x480) */
@@ -1638,7 +1626,7 @@ static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_1_V[] = {
 };
 
 /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
-static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_2_V[] = {
+static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_2_V[] = {
 	{ {0x28, 0x92, 0xB6, 0x83, 0xB5, 0xCF, 0x81} }, /* 00 (x350) */
 	{ {0x28, 0x92, 0xD5, 0x82, 0xD4, 0xEE, 0x81} }, /* 01 (x400) */
 	{ {0x28, 0x92, 0xFD, 0x8A, 0xFC, 0x16, 0xB1} }, /* 02 (x480) */
@@ -1649,7 +1637,7 @@ static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_2_V[] = {
 };
 
 /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
-static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11600x1200_1_V[] = {
+static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11600x1200_1_V[] = {
 	{ {0xd4, 0x1F, 0x81, 0x84, 0x5D, 0xd5, 0x10} }, /* 00 (x350) */
 	{ {0x06, 0x3e, 0xb3, 0x86, 0x8F, 0x07, 0x20} }, /* 01 (x400) */
 	{ {0x56, 0xba, 0x03, 0x86, 0xDF, 0x57, 0x00} }, /* 02 (x480) */
@@ -1661,7 +1649,7 @@ static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11600x1200_1_V[] = {
 };
 
 /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_1_Hx75[] = {
+static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_1_Hx75[] = {
 	{ {0x4B, 0x27, 0x8F, 0x32, 0x1B, 0x00, 0x45, 0x00} },/* ; 00 (320x) */
 	{ {0x4B, 0x27, 0x8F, 0x2B, 0x03, 0x00, 0x44, 0x00} },/* ; 01 (360x) */
 	{ {0x55, 0x31, 0x99, 0x46, 0x1D, 0x00, 0x55, 0x00} },/* ; 02 (400x) */
@@ -1673,7 +1661,7 @@ static struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_1_Hx75[] = {
 };
 
 /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
-static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_Vx75[] = {
+static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_Vx75[] = {
 	{ {0x97, 0x1F, 0x60, 0x87, 0x5D, 0x83, 0x10} },/* ; 00 (x350) */
 	{ {0xB4, 0x1F, 0x92, 0x89, 0x8F, 0xB5, 0x30} },/* ; 01 (x400) */
 	{ {0xFE, 0x1F, 0xE0, 0x84, 0xDF, 0xFF, 0x10} },/* ; 02 (x480) */
@@ -1682,7 +1670,7 @@ static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_Vx75[] = {
 };
 
 /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_2_Hx75[] = {
+static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_2_Hx75[] = {
 	{ {0x63, 0x27, 0x87, 0x3B, 0x8C, 0x00, 0x01, 0x00} },/* ; 00 (320x) */
 	{ {0x63, 0x27, 0x87, 0x3B, 0x8C, 0x00, 0x01, 0x00} },/* ; 01 (360x) */
 	{ {0x63, 0x31, 0x87, 0x3D, 0x8E, 0x00, 0x01, 0x00} },/* ; 02 (400x) */
@@ -1694,7 +1682,7 @@ static struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_2_Hx75[] = {
 };
 
 /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
-static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_Vx75[] = {
+static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_Vx75[] = {
 	{ {0x24, 0xBB, 0x31, 0x87, 0x5D, 0x25, 0x30} },/* ; 00 (x350) */
 	{ {0x24, 0xBB, 0x4A, 0x80, 0x8F, 0x25, 0x30} },/* ; 01 (x400) */
 	{ {0x24, 0xBB, 0x72, 0x88, 0xDF, 0x25, 0x30} },/* ; 02 (x480) */
@@ -1703,7 +1691,7 @@ static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_Vx75[] = {
 };
 
 /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_1_Hx75[] = {
+static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_1_Hx75[] = {
 	{ {0x56, 0x27, 0x9A, 0x30, 0x1E, 0x00, 0x05, 0x00} },/* ; 00 (320x) */
 	{ {0x56, 0x27, 0x9A, 0x30, 0x1E, 0x00, 0x05, 0x00} },/* ; 01 (360x) */
 	{ {0x60, 0x31, 0x84, 0x3A, 0x88, 0x00, 0x01, 0x00} },/* ; 02 (400x) */
@@ -1716,7 +1704,7 @@ static struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_1_Hx75[] = {
 };
 
 /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
-static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_Vx75[] = {
+static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_Vx75[] = {
 	{ {0x86, 0xD1, 0xBC, 0x80, 0xBB, 0xE5, 0x00} },/* ; 00 (x350) */
 	{ {0xB8, 0x1F, 0x90, 0x84, 0x8F, 0xB9, 0x30} },/* ; 01 (x400) */
 	{ {0x08, 0x3E, 0xE0, 0x84, 0xDF, 0x09, 0x00} },/* ; 02 (x480) */
@@ -1725,7 +1713,7 @@ static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_Vx75[] = {
 	{ {0x28, 0x5A, 0x13, 0x87, 0xFF, 0x29, 0xA9} } /* ; 05 (x1024) */
 };
 /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
-static struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_2_Hx75[] = {
+static const struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_2_Hx75[] = {
 	{ {0x7E, 0x3B, 0x9A, 0x44, 0x12, 0x00, 0x01, 0x00} },/* ; 00 (320x) */
 	{ {0x7E, 0x3B, 0x9A, 0x44, 0x12, 0x00, 0x01, 0x00} },/* ; 01 (360x) */
 	{ {0x7E, 0x40, 0x84, 0x49, 0x91, 0x00, 0x01, 0x00} },/* ; 02 (400x) */
@@ -1738,7 +1726,7 @@ static struct XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_2_Hx75[] = {
 };
 
 /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
-static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_Vx75[] = {
+static const struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_Vx75[] = {
 	{ {0x28, 0xD2, 0xAF, 0x83, 0xAE, 0xD8, 0xA1} },/* ; 00 (x350) */
 	{ {0x28, 0xD2, 0xC8, 0x8C, 0xC7, 0xF2, 0x81} },/* ; 01 (x400) */
 	{ {0x28, 0xD2, 0xF0, 0x84, 0xEF, 0x1A, 0xB1} },/* ; 02 (x480) */
@@ -1748,115 +1736,141 @@ static struct XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_Vx75[] = {
 };
 
 /*add for new UNIVGABIOS*/
-static struct XGI330_LCDDataTablStruct XGI_LCDDataTable[] = {
-	{Panel_1024x768, 0x0019, 0x0001, 0}, /* XGI_ExtLCD1024x768Data */
-	{Panel_1024x768, 0x0019, 0x0000, 1}, /* XGI_StLCD1024x768Data */
-	{Panel_1024x768, 0x0018, 0x0010, 2}, /* XGI_CetLCD1024x768Data */
-	{Panel_1280x1024, 0x0019, 0x0001, 3}, /* XGI_ExtLCD1280x1024Data */
-	{Panel_1280x1024, 0x0019, 0x0000, 4}, /* XGI_StLCD1280x1024Data */
-	{Panel_1280x1024, 0x0018, 0x0010, 5}, /* XGI_CetLCD1280x1024Data */
-	{Panel_1400x1050, 0x0019, 0x0001, 6}, /* XGI_ExtLCD1400x1050Data */
-	{Panel_1400x1050, 0x0019, 0x0000, 7}, /* XGI_StLCD1400x1050Data */
-	{Panel_1400x1050, 0x0018, 0x0010, 8}, /* XGI_CetLCD1400x1050Data */
-	{Panel_1600x1200, 0x0019, 0x0001, 9}, /* XGI_ExtLCD1600x1200Data */
-	{Panel_1600x1200, 0x0019, 0x0000, 10}, /* XGI_StLCD1600x1200Data */
-	{PanelRef60Hz, 0x0008, 0x0008, 11}, /* XGI_NoScalingData */
-	{Panel_1024x768x75, 0x0019, 0x0001, 12}, /* XGI_ExtLCD1024x768x75Data */
-	{Panel_1024x768x75, 0x0019, 0x0000, 13}, /* XGI_StLCD1024x768x75Data */
-	{Panel_1024x768x75, 0x0018, 0x0010, 14}, /* XGI_CetLCD1024x768x75Data */
-	/* XGI_ExtLCD1280x1024x75Data */
-	{Panel_1280x1024x75, 0x0019, 0x0001, 15},
-	/* XGI_StLCD1280x1024x75Data */
-	{Panel_1280x1024x75, 0x0019, 0x0000, 16},
-	/* XGI_CetLCD1280x1024x75Data */
-	{Panel_1280x1024x75, 0x0018, 0x0010, 17},
-	{PanelRef75Hz, 0x0008, 0x0008, 18}, /* XGI_NoScalingDatax75 */
-	{0xFF, 0x0000, 0x0000, 0} /* End of table */
-};
-
-static struct XGI330_LCDDataTablStruct XGI_LCDDesDataTable[] = {
-	{Panel_1024x768, 0x0019, 0x0001, 0}, /* XGI_ExtLCDDes1024x768Data */
-	{Panel_1024x768, 0x0019, 0x0000, 1}, /* XGI_StLCDDes1024x768Data */
-	{Panel_1024x768, 0x0018, 0x0010, 2}, /* XGI_CetLCDDes1024x768Data */
-	{Panel_1280x1024, 0x0019, 0x0001, 3}, /* XGI_ExtLCDDes1280x1024Data */
-	{Panel_1280x1024, 0x0019, 0x0000, 4}, /* XGI_StLCDDes1280x1024Data */
-	{Panel_1280x1024, 0x0018, 0x0010, 5}, /* XGI_CetLCDDes1280x1024Data */
-	{Panel_1400x1050, 0x0019, 0x0001, 6}, /* XGI_ExtLCDDes1400x1050Data */
-	{Panel_1400x1050, 0x0019, 0x0000, 7}, /* XGI_StLCDDes1400x1050Data */
-	{Panel_1400x1050, 0x0418, 0x0010, 8}, /* XGI_CetLCDDes1400x1050Data */
-	{Panel_1400x1050, 0x0418, 0x0410, 9}, /* XGI_CetLCDDes1400x1050Data2 */
-	{Panel_1600x1200, 0x0019, 0x0001, 10}, /* XGI_ExtLCDDes1600x1200Data */
-	{Panel_1600x1200, 0x0019, 0x0000, 11}, /* XGI_StLCDDes1600x1200Data */
-	{PanelRef60Hz, 0x0008, 0x0008, 12}, /* XGI_NoScalingDesData */
-	/* XGI_ExtLCDDes1024x768x75Data */
-	{Panel_1024x768x75, 0x0019, 0x0001, 13},
-	/* XGI_StLCDDes1024x768x75Data */
-	{Panel_1024x768x75, 0x0019, 0x0000, 14},
-	/* XGI_CetLCDDes1024x768x75Data */
-	{Panel_1024x768x75, 0x0018, 0x0010, 15},
-	/* XGI_ExtLCDDes1280x1024x75Data */
-	{Panel_1280x1024x75, 0x0019, 0x0001, 16},
-	/* XGI_StLCDDes1280x1024x75Data */
-	{Panel_1280x1024x75, 0x0019, 0x0000, 17},
-	/* XGI_CetLCDDes1280x1024x75Data */
-	{Panel_1280x1024x75, 0x0018, 0x0010, 18},
-	{PanelRef75Hz, 0x0008, 0x0008, 19}, /* XGI_NoScalingDesDatax75 */
-	{0xFF, 0x0000, 0x0000, 0}
-};
-
-static struct XGI330_LCDDataTablStruct xgifb_epllcd_crt1[] = {
-	{Panel_1024x768, 0x0018, 0x0000, 0}, /* XGI_LVDSCRT11024x768_1 */
-	{Panel_1024x768, 0x0018, 0x0010, 1}, /* XGI_LVDSCRT11024x768_2 */
-	{Panel_1280x1024, 0x0018, 0x0000, 2}, /* XGI_LVDSCRT11280x1024_1 */
-	{Panel_1280x1024, 0x0018, 0x0010, 3}, /* XGI_LVDSCRT11280x1024_2 */
-	{Panel_1400x1050, 0x0018, 0x0000, 4}, /* XGI_LVDSCRT11400x1050_1 */
-	{Panel_1400x1050, 0x0018, 0x0010, 5}, /* XGI_LVDSCRT11400x1050_2 */
-	{Panel_1600x1200, 0x0018, 0x0000, 6}, /* XGI_LVDSCRT11600x1200_1 */
-	{Panel_1024x768x75, 0x0018, 0x0000, 7}, /* XGI_LVDSCRT11024x768_1x75 */
-	{Panel_1024x768x75, 0x0018, 0x0010, 8}, /* XGI_LVDSCRT11024x768_2x75 */
-	{Panel_1280x1024x75, 0x0018, 0x0000, 9}, /*XGI_LVDSCRT11280x1024_1x75*/
-	{Panel_1280x1024x75, 0x0018, 0x0010, 10},/*XGI_LVDSCRT11280x1024_2x75*/
-	{0xFF, 0x0000, 0x0000, 0}
-};
-
-static struct XGI330_LCDDataTablStruct XGI_EPLLCDDataPtr[] = {
-	{Panel_1024x768, 0x0018, 0x0000, 0}, /* XGI_LVDS1024x768Data_1 */
-	{Panel_1024x768, 0x0018, 0x0010, 1}, /* XGI_LVDS1024x768Data_2 */
-	{Panel_1280x1024, 0x0018, 0x0000, 2}, /* XGI_LVDS1280x1024Data_1 */
-	{Panel_1280x1024, 0x0018, 0x0010, 3}, /* XGI_LVDS1280x1024Data_2 */
-	{Panel_1400x1050, 0x0018, 0x0000, 4}, /* XGI_LVDS1400x1050Data_1 */
-	{Panel_1400x1050, 0x0018, 0x0010, 5}, /* XGI_LVDS1400x1050Data_2 */
-	{Panel_1600x1200, 0x0018, 0x0000, 6}, /* XGI_LVDS1600x1200Data_1 */
-	{PanelRef60Hz, 0x0008, 0x0008, 7}, /* XGI_LVDSNoScalingData */
-	{Panel_1024x768x75, 0x0018, 0x0000, 8}, /* XGI_LVDS1024x768Data_1x75 */
-	{Panel_1024x768x75, 0x0018, 0x0010, 9}, /* XGI_LVDS1024x768Data_2x75 */
-	/* XGI_LVDS1280x1024Data_1x75 */
-	{Panel_1280x1024x75, 0x0018, 0x0000, 10},
-	/* XGI_LVDS1280x1024Data_2x75 */
-	{Panel_1280x1024x75, 0x0018, 0x0010, 11},
-	{PanelRef75Hz, 0x0008, 0x0008, 12}, /* XGI_LVDSNoScalingDatax75 */
-	{0xFF, 0x0000, 0x0000, 0}
-};
-
-static struct XGI330_LCDDataTablStruct XGI_EPLLCDDesDataPtr[] = {
-	{Panel_1024x768, 0x0018, 0x0000, 0}, /* XGI_LVDS1024x768Des_1 */
-	{Panel_1024x768, 0x0618, 0x0410, 1}, /* XGI_LVDS1024x768Des_3 */
-	{Panel_1024x768, 0x0018, 0x0010, 2}, /* XGI_LVDS1024x768Des_2 */
-	{Panel_1280x1024, 0x0018, 0x0000, 3}, /* XGI_LVDS1280x1024Des_1 */
-	{Panel_1280x1024, 0x0018, 0x0010, 4}, /* XGI_LVDS1280x1024Des_2 */
-	{Panel_1400x1050, 0x0018, 0x0000, 5}, /* XGI_LVDS1400x1050Des_1 */
-	{Panel_1400x1050, 0x0018, 0x0010, 6}, /* XGI_LVDS1400x1050Des_2 */
-	{Panel_1600x1200, 0x0018, 0x0000, 7}, /* XGI_LVDS1600x1200Des_1 */
-	{PanelRef60Hz, 0x0008, 0x0008, 8},  /* XGI_LVDSNoScalingDesData */
-	{Panel_1024x768x75, 0x0018, 0x0000, 9}, /* XGI_LVDS1024x768Des_1x75 */
-	{Panel_1024x768x75, 0x0618, 0x0410, 10}, /* XGI_LVDS1024x768Des_3x75 */
-	{Panel_1024x768x75, 0x0018, 0x0010, 11}, /* XGI_LVDS1024x768Des_2x75 */
-	/* XGI_LVDS1280x1024Des_1x75 */
-	{Panel_1280x1024x75, 0x0018, 0x0000, 12},
-	/* XGI_LVDS1280x1024Des_2x75 */
-	{Panel_1280x1024x75, 0x0018, 0x0010, 13},
-	{PanelRef75Hz, 0x0008, 0x0008, 14}, /* XGI_LVDSNoScalingDesDatax75 */
-	{0xFF, 0x0000, 0x0000, 0}
+static const struct XGI330_LCDDataTablStruct XGI_LCDDataTable[] = {
+	{Panel_1024x768, 0x0019, 0x0001, XGI_ExtLCD1024x768Data },
+	{Panel_1024x768, 0x0019, 0x0000, XGI_StLCD1024x768Data },
+	{Panel_1024x768, 0x0018, 0x0010, XGI_CetLCD1024x768Data },
+	{Panel_1280x1024, 0x0019, 0x0001, XGI_ExtLCD1280x1024Data },
+	{Panel_1280x1024, 0x0019, 0x0000, XGI_StLCD1280x1024Data },
+	{Panel_1280x1024, 0x0018, 0x0010, XGI_CetLCD1280x1024Data },
+	{Panel_1400x1050, 0x0019, 0x0001, xgifb_lcd_1400x1050 },
+	{Panel_1400x1050, 0x0019, 0x0000, xgifb_lcd_1400x1050 },
+	{Panel_1400x1050, 0x0018, 0x0010, XGI_CetLCD1400x1050Data },
+	{Panel_1600x1200, 0x0019, 0x0001, XGI_ExtLCD1600x1200Data },
+	{Panel_1600x1200, 0x0019, 0x0000, XGI_StLCD1600x1200Data },
+	{PanelRef60Hz, 0x0008, 0x0008, XGI_NoScalingData },
+	{Panel_1024x768x75, 0x0019, 0x0001, XGI_ExtLCD1024x768x75Data },
+	{Panel_1024x768x75, 0x0019, 0x0000, XGI_ExtLCD1024x768x75Data },
+	{Panel_1024x768x75, 0x0018, 0x0010, XGI_CetLCD1024x768x75Data },
+	{Panel_1280x1024x75, 0x0019, 0x0001, xgifb_lcd_1280x1024x75 },
+	{Panel_1280x1024x75, 0x0019, 0x0000, xgifb_lcd_1280x1024x75 },
+	{Panel_1280x1024x75, 0x0018, 0x0010, XGI_CetLCD1280x1024x75Data },
+	{PanelRef75Hz, 0x0008, 0x0008, XGI_NoScalingDatax75 },
+	{0xFF, 0x0000, 0x0000, NULL } /* End of table */
+};
+
+static const struct XGI330_LCDDataTablStruct XGI_LCDDesDataTable[] = {
+	{Panel_1024x768, 0x0019, 0x0001, XGI_ExtLCDDes1024x768Data },
+	{Panel_1024x768, 0x0019, 0x0000, XGI_StLCDDes1024x768Data },
+	{Panel_1024x768, 0x0018, 0x0010, XGI_CetLCDDes1024x768Data },
+	{Panel_1280x1024, 0x0019, 0x0001, XGI_ExtLCDDes1280x1024Data },
+	{Panel_1280x1024, 0x0019, 0x0000, XGI_StLCDDes1280x1024Data },
+	{Panel_1280x1024, 0x0018, 0x0010, XGI_CetLCDDes1280x1024Data },
+	{Panel_1400x1050, 0x0019, 0x0001, xgifb_lcddes_1400x1050 },
+	{Panel_1400x1050, 0x0019, 0x0000, xgifb_lcddes_1400x1050 },
+	{Panel_1400x1050, 0x0418, 0x0010, XGI_CetLCDDes1400x1050Data },
+	{Panel_1400x1050, 0x0418, 0x0410, XGI_CetLCDDes1400x1050Data2 },
+	{Panel_1600x1200, 0x0019, 0x0001, XGI_ExtLCDDes1600x1200Data },
+	{Panel_1600x1200, 0x0019, 0x0000, XGI_StLCDDes1600x1200Data },
+	{PanelRef60Hz, 0x0008, 0x0008, XGI_NoScalingDesData },
+	{Panel_1024x768x75, 0x0019, 0x0001, xgifb_lcddes_1024x768x75 },
+	{Panel_1024x768x75, 0x0019, 0x0000, xgifb_lcddes_1024x768x75 },
+	{Panel_1024x768x75, 0x0018, 0x0010, XGI_CetLCDDes1024x768x75Data },
+	{Panel_1280x1024x75, 0x0019, 0x0001, xgifb_lcddes_1280x1024x75 },
+	{Panel_1280x1024x75, 0x0019, 0x0000, xgifb_lcddes_1280x1024x75 },
+	{Panel_1280x1024x75, 0x0018, 0x0010, XGI_CetLCDDes1280x1024x75Data },
+	{PanelRef75Hz, 0x0008, 0x0008, XGI_NoScalingDesDatax75 },
+	{0xFF, 0x0000, 0x0000, NULL }
+};
+
+static const struct XGI330_LCDDataTablStruct xgifb_lcddldes[] = {
+	{Panel_1024x768, 0x0019, 0x0001, XGI_ExtLCDDes1024x768Data },
+	{Panel_1024x768, 0x0019, 0x0000, XGI_StLCDDes1024x768Data },
+	{Panel_1024x768, 0x0018, 0x0010, XGI_CetLCDDes1024x768Data },
+	{Panel_1280x1024, 0x0019, 0x0001, XGI_ExtLCDDLDes1280x1024Data },
+	{Panel_1280x1024, 0x0019, 0x0000, XGI_StLCDDLDes1280x1024Data },
+	{Panel_1280x1024, 0x0018, 0x0010, XGI_CetLCDDLDes1280x1024Data },
+	{Panel_1400x1050, 0x0019, 0x0001, xgifb_lcddldes_1400x1050 },
+	{Panel_1400x1050, 0x0019, 0x0000, xgifb_lcddldes_1400x1050 },
+	{Panel_1400x1050, 0x0418, 0x0010, XGI_CetLCDDes1400x1050Data },
+	{Panel_1400x1050, 0x0418, 0x0410, XGI_CetLCDDes1400x1050Data2 },
+	{Panel_1600x1200, 0x0019, 0x0001, XGI_ExtLCDDLDes1600x1200Data },
+	{Panel_1600x1200, 0x0019, 0x0000, XGI_StLCDDLDes1600x1200Data },
+	{PanelRef60Hz, 0x0008, 0x0008, XGI_NoScalingDesData },
+	{Panel_1024x768x75, 0x0019, 0x0001, xgifb_lcddes_1024x768x75 },
+	{Panel_1024x768x75, 0x0019, 0x0000, xgifb_lcddes_1024x768x75 },
+	{Panel_1024x768x75, 0x0018, 0x0010, XGI_CetLCDDes1024x768x75Data },
+	{Panel_1280x1024x75, 0x0019, 0x0001, xgifb_lcddldes_1280x1024x75 },
+	{Panel_1280x1024x75, 0x0019, 0x0000, xgifb_lcddldes_1280x1024x75 },
+	{Panel_1280x1024x75, 0x0018, 0x0010, XGI_CetLCDDLDes1280x1024x75Data },
+	{PanelRef75Hz, 0x0008, 0x0008, XGI_NoScalingDesDatax75 },
+	{0xFF, 0x0000, 0x0000, NULL }
+};
+
+static const struct XGI330_LCDDataTablStruct xgifb_epllcd_crt1_h[] = {
+	{Panel_1024x768, 0x0018, 0x0000, XGI_LVDSCRT11024x768_1_H },
+	{Panel_1024x768, 0x0018, 0x0010, XGI_LVDSCRT11024x768_2_H },
+	{Panel_1280x1024, 0x0018, 0x0000, XGI_LVDSCRT11280x1024_1_H },
+	{Panel_1280x1024, 0x0018, 0x0010, XGI_LVDSCRT11280x1024_2_H },
+	{Panel_1400x1050, 0x0018, 0x0000, XGI_LVDSCRT11400x1050_1_H },
+	{Panel_1400x1050, 0x0018, 0x0010, XGI_LVDSCRT11400x1050_2_H },
+	{Panel_1600x1200, 0x0018, 0x0000, XGI_LVDSCRT11600x1200_1_H },
+	{Panel_1024x768x75, 0x0018, 0x0000, XGI_LVDSCRT11024x768_1_Hx75 },
+	{Panel_1024x768x75, 0x0018, 0x0010, XGI_LVDSCRT11024x768_2_Hx75 },
+	{Panel_1280x1024x75, 0x0018, 0x0000, XGI_LVDSCRT11280x1024_1_Hx75 },
+	{Panel_1280x1024x75, 0x0018, 0x0010, XGI_LVDSCRT11280x1024_2_Hx75 },
+	{0xFF, 0x0000, 0x0000, NULL }
+};
+
+static const struct XGI330_LCDDataTablStruct xgifb_epllcd_crt1_v[] = {
+	{Panel_1024x768, 0x0018, 0x0000, XGI_LVDSCRT11024x768_1_V },
+	{Panel_1024x768, 0x0018, 0x0010, XGI_LVDSCRT11024x768_2_V },
+	{Panel_1280x1024, 0x0018, 0x0000, XGI_LVDSCRT11280x1024_1_V },
+	{Panel_1280x1024, 0x0018, 0x0010, XGI_LVDSCRT11280x1024_2_V },
+	{Panel_1400x1050, 0x0018, 0x0000, XGI_LVDSCRT11400x1050_1_V },
+	{Panel_1400x1050, 0x0018, 0x0010, XGI_LVDSCRT11400x1050_2_V },
+	{Panel_1600x1200, 0x0018, 0x0000, XGI_LVDSCRT11600x1200_1_V },
+	{Panel_1024x768x75, 0x0018, 0x0000, XGI_LVDSCRT11024x768_1_Vx75 },
+	{Panel_1024x768x75, 0x0018, 0x0010, XGI_LVDSCRT11024x768_2_Vx75 },
+	{Panel_1280x1024x75, 0x0018, 0x0000, XGI_LVDSCRT11280x1024_1_Vx75 },
+	{Panel_1280x1024x75, 0x0018, 0x0010, XGI_LVDSCRT11280x1024_2_Vx75 },
+	{0xFF, 0x0000, 0x0000, NULL }
+};
+
+static const struct XGI330_LCDDataTablStruct XGI_EPLLCDDataPtr[] = {
+	{Panel_1024x768, 0x0018, 0x0000, XGI_LVDS1024x768Data_1 },
+	{Panel_1024x768, 0x0018, 0x0010, XGI_LVDS1024x768Data_2 },
+	{Panel_1280x1024, 0x0018, 0x0000, XGI_LVDS1280x1024Data_1 },
+	{Panel_1280x1024, 0x0018, 0x0010, XGI_LVDS1280x1024Data_2 },
+	{Panel_1400x1050, 0x0018, 0x0000, XGI_LVDS1400x1050Data_1 },
+	{Panel_1400x1050, 0x0018, 0x0010, XGI_LVDS1400x1050Data_2 },
+	{Panel_1600x1200, 0x0018, 0x0000, XGI_LVDS1600x1200Data_1 },
+	{PanelRef60Hz, 0x0008, 0x0008, XGI_LVDSNoScalingData },
+	{Panel_1024x768x75, 0x0018, 0x0000, XGI_LVDS1024x768Data_1x75 },
+	{Panel_1024x768x75, 0x0018, 0x0010, XGI_LVDS1024x768Data_2x75 },
+	{Panel_1280x1024x75, 0x0018, 0x0000, XGI_LVDS1280x1024Data_1x75 },
+	{Panel_1280x1024x75, 0x0018, 0x0010, XGI_LVDS1280x1024Data_2x75 },
+	{PanelRef75Hz, 0x0008, 0x0008, XGI_LVDSNoScalingDatax75 },
+	{0xFF, 0x0000, 0x0000, NULL }
+};
+
+static const struct XGI330_LCDDataTablStruct XGI_EPLLCDDesDataPtr[] = {
+	{Panel_1024x768, 0x0018, 0x0000, XGI_LVDS1024x768Des_1 },
+	{Panel_1024x768, 0x0618, 0x0410, XGI_LVDS1024x768Des_3 },
+	{Panel_1024x768, 0x0018, 0x0010, XGI_LVDS1024x768Des_2 },
+	{Panel_1280x1024, 0x0018, 0x0000, XGI_LVDS1280x1024Des_1 },
+	{Panel_1280x1024, 0x0018, 0x0010, XGI_LVDS1280x1024Des_2 },
+	{Panel_1400x1050, 0x0018, 0x0000, XGI_LVDS1400x1050Des_1 },
+	{Panel_1400x1050, 0x0018, 0x0010, XGI_LVDS1400x1050Des_2 },
+	{Panel_1600x1200, 0x0018, 0x0000, XGI_LVDS1600x1200Des_1 },
+	{PanelRef60Hz, 0x0008, 0x0008, XGI_LVDSNoScalingDesData },
+	{Panel_1024x768x75, 0x0018, 0x0000, XGI_LVDS1024x768Des_1x75 },
+	{Panel_1024x768x75, 0x0618, 0x0410, XGI_LVDS1024x768Des_3x75 },
+	{Panel_1024x768x75, 0x0018, 0x0010, XGI_LVDS1024x768Des_2x75 },
+	{Panel_1280x1024x75, 0x0018, 0x0000, XGI_LVDS1280x1024Des_1x75 },
+	{Panel_1280x1024x75, 0x0018, 0x0010, XGI_LVDS1280x1024Des_2x75 },
+	{PanelRef75Hz, 0x0008, 0x0008, XGI_LVDSNoScalingDesDatax75 },
+	{0xFF, 0x0000, 0x0000, NULL }
 };
 
 static const struct XGI330_TVDataTablStruct XGI_TVDataTable[] = {
@@ -1877,7 +1891,7 @@ static const struct XGI330_TVDataTablStruct XGI_TVDataTable[] = {
 };
 
 /* Dual link only */
-static struct XGI330_LCDCapStruct  XGI_LCDDLCapList[] = {
+static const struct XGI330_LCDCapStruct XGI_LCDDLCapList[] = {
 /* LCDCap1024x768 */
 	{Panel_1024x768, DefaultLCDCap, 0, 0x88, 0x06, VCLK65_315,
 	0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
@@ -1912,7 +1926,7 @@ static struct XGI330_LCDCapStruct  XGI_LCDDLCapList[] = {
 	0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
 };
 
-static struct XGI330_LCDCapStruct  XGI_LCDCapList[] = {
+static const struct XGI330_LCDCapStruct XGI_LCDCapList[] = {
 /* LCDCap1024x768 */
 	{Panel_1024x768, DefaultLCDCap, 0, 0x88, 0x06, VCLK65_315,
 	0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
@@ -1947,7 +1961,7 @@ static struct XGI330_LCDCapStruct  XGI_LCDCapList[] = {
 	0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
 };
 
-static struct XGI_Ext2Struct XGI330_RefIndex[] = {
+const struct XGI_Ext2Struct XGI330_RefIndex[] = {
 	{Mode32Bpp + SupportAllCRT2 + SyncPN, RES320x200, VCLK25_175,
 	0x00, 0x10, 0x59, 320, 200},/* 00 */
 	{Mode32Bpp + SupportAllCRT2 + SyncPN, RES320x200, VCLK25_175,
@@ -2101,21 +2115,13 @@ static struct XGI_Ext2Struct XGI330_RefIndex[] = {
 	0x30, 0x47, 0x37, 1024, 768},/* 48 1024x768x160Hz */
 };
 
-static unsigned char XGI330_ScreenOffset[] = {
+static const unsigned char XGI330_ScreenOffset[] = {
 	0x14, 0x19, 0x20, 0x28, 0x32, 0x40,
 	0x50, 0x64, 0x78, 0x80, 0x2d, 0x35,
 	0x57, 0x48
 };
 
-static struct SiS_StResInfo_S XGI330_StResInfo[] = {
-	{640, 400},
-	{640, 350},
-	{720, 400},
-	{720, 350},
-	{640, 480}
-};
-
-static struct SiS_ModeResInfo_S XGI330_ModeResInfo[] = {
+static const struct SiS_ModeResInfo_S XGI330_ModeResInfo[] = {
 	{ 320,  200, 8,  8},
 	{ 320,  240, 8,  8},
 	{ 320,  400, 8,  8},
@@ -2141,7 +2147,7 @@ static struct SiS_ModeResInfo_S XGI330_ModeResInfo[] = {
 	{1152,  864, 8, 16}
 };
 
-static struct SiS_VCLKData XGI_VCLKData[] = {
+const struct SiS_VCLKData XGI_VCLKData[] = {
 	/* SR2B,SR2C,SR2D */
 	{0x1B, 0xE1,  25}, /* 00 (25.175MHz) */
 	{0x4E, 0xE4,  28}, /* 01 (28.322MHz) */
@@ -2234,7 +2240,7 @@ static struct SiS_VCLKData XGI_VCLKData[] = {
 	{0xFF, 0x00,   0}  /* End mark */
 };
 
-static struct SiS_VBVCLKData XGI_VBVCLKData[] = {
+static const struct SiS_VBVCLKData XGI_VBVCLKData[] = {
 	{0x1B, 0xE1,  25}, /* 00 (25.175MHz) */
 	{0x4E, 0xE4,  28}, /* 01 (28.322MHz) */
 	{0x57, 0xE4,  31}, /* 02 (31.500MHz) */
@@ -2329,7 +2335,7 @@ static struct SiS_VBVCLKData XGI_VBVCLKData[] = {
 #define XGI301TVDelay 0x22
 #define XGI301LCDDelay 0x12
 
-static unsigned char TVAntiFlickList[] = {/* NTSCAntiFlicker */
+static const unsigned char TVAntiFlickList[] = {/* NTSCAntiFlicker */
 	0x04, /* ; 0 Adaptive */
 	0x00, /* ; 1 new anti-flicker ? */
 
@@ -2341,7 +2347,7 @@ static unsigned char TVAntiFlickList[] = {/* NTSCAntiFlicker */
 };
 
 
-static unsigned char TVEdgeList[] = {
+static const unsigned char TVEdgeList[] = {
 	0x00, /* ; 0 NTSC No Edge enhance */
 	0x04, /* ; 1 NTSC Adaptive Edge enhance */
 	0x00, /* ; 0 PAL No Edge enhance */
@@ -2350,7 +2356,7 @@ static unsigned char TVEdgeList[] = {
 	0x00  /* ; 1 HiTV */
 };
 
-static unsigned long TVPhaseList[] = {
+static const unsigned long TVPhaseList[] = {
 	0x08BAED21, /* ; 0 NTSC phase */
 	0x00E3052A, /* ; 1 PAL phase */
 	0x9B2EE421, /* ; 2 PAL-M phase */
@@ -2367,7 +2373,7 @@ static unsigned long TVPhaseList[] = {
 	0xE00A831E  /* ; D PAL-M 1024x768 */
 };
 
-static unsigned char NTSCYFilter1[] = {
+static const unsigned char NTSCYFilter1[] = {
 	0x00, 0xF4, 0x10, 0x38, /* 0 : 320x text mode */
 	0x00, 0xF4, 0x10, 0x38, /* 1 : 360x text mode */
 	0xEB, 0x04, 0x25, 0x18, /* 2 : 640x text mode */
@@ -2377,7 +2383,7 @@ static unsigned char NTSCYFilter1[] = {
 	0xEB, 0x15, 0x25, 0xF6  /* 6 : 800x gra. mode */
 };
 
-static unsigned char PALYFilter1[] = {
+static const unsigned char PALYFilter1[] = {
 	0x00, 0xF4, 0x10, 0x38, /* 0 : 320x text mode */
 	0x00, 0xF4, 0x10, 0x38, /* 1 : 360x text mode */
 	0xF1, 0xF7, 0x1F, 0x32, /* 2 : 640x text mode */
@@ -2387,7 +2393,7 @@ static unsigned char PALYFilter1[] = {
 	0xFC, 0xFB, 0x14, 0x2A  /* 6 : 800x gra. mode */
 };
 
-static unsigned char xgifb_palmn_yfilter1[] = {
+static const unsigned char xgifb_palmn_yfilter1[] = {
 	0x00, 0xF4, 0x10, 0x38, /* 0 : 320x text mode */
 	0x00, 0xF4, 0x10, 0x38, /* 1 : 360x text mode */
 	0xEB, 0x04, 0x10, 0x18, /* 2 : 640x text mode */
@@ -2398,7 +2404,7 @@ static unsigned char xgifb_palmn_yfilter1[] = {
 	0xFF, 0xFF, 0xFF, 0xFF  /* End of Table */
 };
 
-static unsigned char xgifb_yfilter2[] = {
+static const unsigned char xgifb_yfilter2[] = {
 	0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 0 : 320x text mode */
 	0x01, 0x02, 0xFE, 0xF7, 0x03, 0x27, 0x3C, /* 1 : 360x text mode */
 	0xFF, 0x03, 0x02, 0xF6, 0xFC, 0x27, 0x46, /* 2 : 640x text mode */
@@ -2409,13 +2415,13 @@ static unsigned char xgifb_yfilter2[] = {
 	0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0x22, 0x28  /* 7 : 1024xgra. mode */
 };
 
-static unsigned char XGI_NTSC1024AdjTime[] = {
+static const unsigned char XGI_NTSC1024AdjTime[] = {
 	0xa7, 0x07, 0xf2, 0x6e, 0x17, 0x8b, 0x73, 0x53,
 	0x13, 0x40, 0x34, 0xF4, 0x63, 0xBB, 0xCC, 0x7A,
 	0x58, 0xe4, 0x73, 0xd0, 0x13
 };
 
-static struct XGI301C_Tap4TimingStruct xgifb_tap4_timing[] = {
+static const struct XGI301C_Tap4TimingStruct xgifb_tap4_timing[] = {
 	{0, {
 	0x00, 0x20, 0x00, 0x00, 0x7F, 0x20, 0x02, 0x7F, /* ; C0-C7 */
 	0x7D, 0x20, 0x04, 0x7F, 0x7D, 0x1F, 0x06, 0x7E, /* ; C8-CF */
@@ -2429,7 +2435,7 @@ static struct XGI301C_Tap4TimingStruct xgifb_tap4_timing[] = {
 	}
 };
 
-static struct XGI301C_Tap4TimingStruct PALTap4Timing[] = {
+static const struct XGI301C_Tap4TimingStruct PALTap4Timing[] = {
 	{600,	{
 		0x05, 0x19, 0x05, 0x7D, 0x03, 0x19, 0x06, 0x7E, /* ; C0-C7 */
 		0x02, 0x19, 0x08, 0x7D, 0x01, 0x18, 0x0A, 0x7D, /* ; C8-CF */
@@ -2465,7 +2471,7 @@ static struct XGI301C_Tap4TimingStruct PALTap4Timing[] = {
 	}
 };
 
-static struct XGI301C_Tap4TimingStruct xgifb_ntsc_525_tap4_timing[] = {
+static const struct XGI301C_Tap4TimingStruct xgifb_ntsc_525_tap4_timing[] = {
 	{480,	{
 		0x04, 0x1A, 0x04, 0x7E, 0x03, 0x1A, 0x06, 0x7D, /* ; C0-C7 */
 		0x01, 0x1A, 0x08, 0x7D, 0x00, 0x19, 0x0A, 0x7D, /* ; C8-CF */
@@ -2501,7 +2507,7 @@ static struct XGI301C_Tap4TimingStruct xgifb_ntsc_525_tap4_timing[] = {
 	}
 };
 
-static struct XGI301C_Tap4TimingStruct YPbPr750pTap4Timing[] = {
+static const struct XGI301C_Tap4TimingStruct YPbPr750pTap4Timing[] = {
 	{0xFFFF, {
 		 0x05, 0x19, 0x05, 0x7D, 0x03, 0x19, 0x06, 0x7E, /* ; C0-C7 */
 		 0x02, 0x19, 0x08, 0x7D, 0x01, 0x18, 0x0A, 0x7D, /* ; C8-CF */
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
index 6edefde..fb4a7c9 100644
--- a/drivers/staging/zram/zram_drv.c
+++ b/drivers/staging/zram/zram_drv.c
@@ -183,62 +183,25 @@ static inline int is_partial_io(struct bio_vec *bvec)
 	return bvec->bv_len != PAGE_SIZE;
 }
 
-static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
-			  u32 index, int offset, struct bio *bio)
+static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
 {
-	int ret;
-	size_t clen;
-	struct page *page;
-	unsigned char *user_mem, *cmem, *uncmem = NULL;
-
-	page = bvec->bv_page;
-
-	if (zram_test_flag(zram, index, ZRAM_ZERO)) {
-		handle_zero_page(bvec);
-		return 0;
-	}
+	int ret = LZO_E_OK;
+	size_t clen = PAGE_SIZE;
+	unsigned char *cmem;
+	unsigned long handle = zram->table[index].handle;
 
-	/* Requested page is not present in compressed area */
-	if (unlikely(!zram->table[index].handle)) {
-		pr_debug("Read before write: sector=%lu, size=%u",
-			 (ulong)(bio->bi_sector), bio->bi_size);
-		handle_zero_page(bvec);
+	if (!handle || zram_test_flag(zram, index, ZRAM_ZERO)) {
+		memset(mem, 0, PAGE_SIZE);
 		return 0;
 	}
 
-	if (is_partial_io(bvec)) {
-		/* Use  a temporary buffer to decompress the page */
-		uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL);
-		if (!uncmem) {
-			pr_info("Error allocating temp memory!\n");
-			return -ENOMEM;
-		}
-	}
-
-	user_mem = kmap_atomic(page);
-	if (!is_partial_io(bvec))
-		uncmem = user_mem;
-	clen = PAGE_SIZE;
-
-	cmem = zs_map_object(zram->mem_pool, zram->table[index].handle,
-				ZS_MM_RO);
-
-	if (zram->table[index].size == PAGE_SIZE) {
-		memcpy(uncmem, cmem, PAGE_SIZE);
-		ret = LZO_E_OK;
-	} else {
+	cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_RO);
+	if (zram->table[index].size == PAGE_SIZE)
+		memcpy(mem, cmem, PAGE_SIZE);
+	else
 		ret = lzo1x_decompress_safe(cmem, zram->table[index].size,
-				    uncmem, &clen);
-	}
-
-	if (is_partial_io(bvec)) {
-		memcpy(user_mem + bvec->bv_offset, uncmem + offset,
-		       bvec->bv_len);
-		kfree(uncmem);
-	}
-
-	zs_unmap_object(zram->mem_pool, zram->table[index].handle);
-	kunmap_atomic(user_mem);
+						mem, &clen);
+	zs_unmap_object(zram->mem_pool, handle);
 
 	/* Should NEVER happen. Return bio error if it does. */
 	if (unlikely(ret != LZO_E_OK)) {
@@ -247,36 +210,56 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
 		return ret;
 	}
 
-	flush_dcache_page(page);
-
 	return 0;
 }
 
-static int zram_read_before_write(struct zram *zram, char *mem, u32 index)
+static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
+			  u32 index, int offset, struct bio *bio)
 {
 	int ret;
-	size_t clen = PAGE_SIZE;
-	unsigned char *cmem;
-	unsigned long handle = zram->table[index].handle;
+	struct page *page;
+	unsigned char *user_mem, *uncmem = NULL;
 
-	if (zram_test_flag(zram, index, ZRAM_ZERO) || !handle) {
-		memset(mem, 0, PAGE_SIZE);
+	page = bvec->bv_page;
+
+	if (unlikely(!zram->table[index].handle) ||
+			zram_test_flag(zram, index, ZRAM_ZERO)) {
+		handle_zero_page(bvec);
 		return 0;
 	}
 
-	cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_RO);
-	ret = lzo1x_decompress_safe(cmem, zram->table[index].size,
-				    mem, &clen);
-	zs_unmap_object(zram->mem_pool, handle);
+	user_mem = kmap_atomic(page);
+	if (is_partial_io(bvec))
+		/* Use  a temporary buffer to decompress the page */
+		uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	else
+		uncmem = user_mem;
 
+	if (!uncmem) {
+		pr_info("Unable to allocate temp memory\n");
+		ret = -ENOMEM;
+		goto out_cleanup;
+	}
+
+	ret = zram_decompress_page(zram, uncmem, index);
 	/* Should NEVER happen. Return bio error if it does. */
 	if (unlikely(ret != LZO_E_OK)) {
 		pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
 		zram_stat64_inc(zram, &zram->stats.failed_reads);
-		return ret;
+		goto out_cleanup;
 	}
 
-	return 0;
+	if (is_partial_io(bvec))
+		memcpy(user_mem + bvec->bv_offset, uncmem + offset,
+				bvec->bv_len);
+
+	flush_dcache_page(page);
+	ret = 0;
+out_cleanup:
+	kunmap_atomic(user_mem);
+	if (is_partial_io(bvec))
+		kfree(uncmem);
+	return ret;
 }
 
 static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
@@ -302,7 +285,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 			ret = -ENOMEM;
 			goto out;
 		}
-		ret = zram_read_before_write(zram, uncmem, index);
+		ret = zram_decompress_page(zram, uncmem, index);
 		if (ret) {
 			kfree(uncmem);
 			goto out;
diff --git a/drivers/staging/zram/zram_drv.h b/drivers/staging/zram/zram_drv.h
index 572c0b1..df2eec4 100644
--- a/drivers/staging/zram/zram_drv.h
+++ b/drivers/staging/zram/zram_drv.h
@@ -39,8 +39,8 @@ static const size_t max_zpage_size = PAGE_SIZE / 4 * 3;
 
 /*
  * NOTE: max_zpage_size must be less than or equal to:
- *   ZS_MAX_ALLOC_SIZE - sizeof(struct zobj_header)
- * otherwise, xv_malloc() would always return failure.
+ *   ZS_MAX_ALLOC_SIZE. Otherwise, zs_malloc() would
+ * always return failure.
  */
 
 /*-- End of configurable params */
diff --git a/drivers/staging/zram/zram_sysfs.c b/drivers/staging/zram/zram_sysfs.c
index edb0ed4..de1eacf 100644
--- a/drivers/staging/zram/zram_sysfs.c
+++ b/drivers/staging/zram/zram_sysfs.c
@@ -15,6 +15,7 @@
 #include <linux/device.h>
 #include <linux/genhd.h>
 #include <linux/mm.h>
+#include <linux/kernel.h>
 
 #include "zram_drv.h"
 
@@ -54,13 +55,12 @@ static ssize_t disksize_show(struct device *dev,
 static ssize_t disksize_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t len)
 {
-	int ret;
 	u64 disksize;
 	struct zram *zram = dev_to_zram(dev);
 
-	ret = kstrtoull(buf, 10, &disksize);
-	if (ret)
-		return ret;
+	disksize = memparse(buf, NULL);
+	if (!disksize)
+		return -EINVAL;
 
 	down_write(&zram->init_lock);
 	if (zram->init_done) {
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 035c2c7..339f97f 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -735,7 +735,7 @@ static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
 	list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
 		spin_lock(&cmd->istate_lock);
 		if ((cmd->i_state == ISTATE_SENT_STATUS) &&
-		    (cmd->stat_sn < exp_statsn)) {
+		    iscsi_sna_lt(cmd->stat_sn, exp_statsn)) {
 			cmd->i_state = ISTATE_REMOVE;
 			spin_unlock(&cmd->istate_lock);
 			iscsit_add_cmd_to_immediate_queue(cmd, conn,
@@ -767,9 +767,8 @@ static int iscsit_handle_scsi_cmd(
 	struct iscsi_conn *conn,
 	unsigned char *buf)
 {
-	int	data_direction, cmdsn_ret = 0, immed_ret, ret, transport_ret;
-	int	dump_immediate_data = 0, send_check_condition = 0, payload_length;
-	struct iscsi_cmd	*cmd = NULL;
+	int data_direction, payload_length, cmdsn_ret = 0, immed_ret;
+	struct iscsi_cmd *cmd = NULL;
 	struct iscsi_scsi_req *hdr;
 	int iscsi_task_attr;
 	int sam_task_attr;
@@ -956,38 +955,26 @@ done:
 		" ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt,
 		hdr->cmdsn, hdr->data_length, payload_length, conn->cid);
 
-	/*
-	 * The CDB is going to an se_device_t.
-	 */
-	ret = transport_lookup_cmd_lun(&cmd->se_cmd,
-				       scsilun_to_int(&hdr->lun));
-	if (ret < 0) {
-		if (cmd->se_cmd.scsi_sense_reason == TCM_NON_EXISTENT_LUN) {
-			pr_debug("Responding to non-acl'ed,"
-				" non-existent or non-exported iSCSI LUN:"
-				" 0x%016Lx\n", get_unaligned_le64(&hdr->lun));
+	cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd,
+						     scsilun_to_int(&hdr->lun));
+	if (cmd->sense_reason)
+		goto attach_cmd;
+
+	cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb);
+	if (cmd->sense_reason) {
+		if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) {
+			return iscsit_add_reject_from_cmd(
+					ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+					1, 1, buf, cmd);
 		}
-		send_check_condition = 1;
+
 		goto attach_cmd;
 	}
 
-	transport_ret = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb);
-	if (transport_ret == -ENOMEM) {
+	if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) {
 		return iscsit_add_reject_from_cmd(
-				ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-				1, 1, buf, cmd);
-	} else if (transport_ret < 0) {
-		/*
-		 * Unsupported SAM Opcode.  CHECK_CONDITION will be sent
-		 * in iscsit_execute_cmd() during the CmdSN OOO Execution
-		 * Mechinism.
-		 */
-		send_check_condition = 1;
-	} else {
-		if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0)
-			return iscsit_add_reject_from_cmd(
-				ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-				1, 1, buf, cmd);
+			ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+			1, 1, buf, cmd);
 	}
 
 attach_cmd:
@@ -1000,11 +987,12 @@ attach_cmd:
 	 */
 	core_alua_check_nonop_delay(&cmd->se_cmd);
 
-	ret = iscsit_allocate_iovecs(cmd);
-	if (ret < 0)
+	if (iscsit_allocate_iovecs(cmd) < 0) {
 		return iscsit_add_reject_from_cmd(
 				ISCSI_REASON_BOOKMARK_NO_RESOURCES,
 				1, 0, buf, cmd);
+	}
+
 	/*
 	 * Check the CmdSN against ExpCmdSN/MaxCmdSN here if
 	 * the Immediate Bit is not set, and no Immediate
@@ -1031,10 +1019,7 @@ attach_cmd:
 	 * If no Immediate Data is attached, it's OK to return now.
 	 */
 	if (!cmd->immediate_data) {
-		if (send_check_condition)
-			return 0;
-
-		if (cmd->unsolicited_data) {
+		if (!cmd->sense_reason && cmd->unsolicited_data) {
 			iscsit_set_dataout_sequence_values(cmd);
 
 			spin_lock_bh(&cmd->dataout_timeout_lock);
@@ -1050,19 +1035,17 @@ attach_cmd:
 	 * thread.  They are processed in CmdSN order by
 	 * iscsit_check_received_cmdsn() below.
 	 */
-	if (send_check_condition) {
+	if (cmd->sense_reason) {
 		immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
-		dump_immediate_data = 1;
 		goto after_immediate_data;
 	}
 	/*
 	 * Call directly into transport_generic_new_cmd() to perform
 	 * the backend memory allocation.
 	 */
-	ret = transport_generic_new_cmd(&cmd->se_cmd);
-	if (ret < 0) {
+	cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd);
+	if (cmd->sense_reason) {
 		immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
-		dump_immediate_data = 1;
 		goto after_immediate_data;
 	}
 
@@ -1079,7 +1062,7 @@ after_immediate_data:
 		 * Special case for Unsupported SAM WRITE Opcodes
 		 * and ImmediateData=Yes.
 		 */
-		if (dump_immediate_data) {
+		if (cmd->sense_reason) {
 			if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
 				return -1;
 		} else if (cmd->unsolicited_data) {
@@ -1272,8 +1255,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
 		spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
 
 		spin_lock_irqsave(&se_cmd->t_state_lock, flags);
-		if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE) ||
-		     (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION))
+		if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE))
 			dump_unsolicited_data = 1;
 		spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
 
@@ -1742,7 +1724,6 @@ static int iscsit_handle_task_mgt_cmd(
 		ret = transport_lookup_tmr_lun(&cmd->se_cmd,
 					       scsilun_to_int(&hdr->lun));
 		if (ret < 0) {
-			cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
 			se_tmr->response = ISCSI_TMF_RSP_NO_LUN;
 			goto attach;
 		}
@@ -1751,10 +1732,8 @@ static int iscsit_handle_task_mgt_cmd(
 	switch (function) {
 	case ISCSI_TM_FUNC_ABORT_TASK:
 		se_tmr->response = iscsit_tmr_abort_task(cmd, buf);
-		if (se_tmr->response != ISCSI_TMF_RSP_COMPLETE) {
-			cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+		if (se_tmr->response)
 			goto attach;
-		}
 		break;
 	case ISCSI_TM_FUNC_ABORT_TASK_SET:
 	case ISCSI_TM_FUNC_CLEAR_ACA:
@@ -1763,14 +1742,12 @@ static int iscsit_handle_task_mgt_cmd(
 		break;
 	case ISCSI_TM_FUNC_TARGET_WARM_RESET:
 		if (iscsit_tmr_task_warm_reset(conn, tmr_req, buf) < 0) {
-			cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
 			se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED;
 			goto attach;
 		}
 		break;
 	case ISCSI_TM_FUNC_TARGET_COLD_RESET:
 		if (iscsit_tmr_task_cold_reset(conn, tmr_req, buf) < 0) {
-			cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
 			se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED;
 			goto attach;
 		}
@@ -1781,7 +1758,7 @@ static int iscsit_handle_task_mgt_cmd(
 		 * Perform sanity checks on the ExpDataSN only if the
 		 * TASK_REASSIGN was successful.
 		 */
-		if (se_tmr->response != ISCSI_TMF_RSP_COMPLETE)
+		if (se_tmr->response)
 			break;
 
 		if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0)
@@ -1792,7 +1769,6 @@ static int iscsit_handle_task_mgt_cmd(
 	default:
 		pr_err("Unknown TMR function: 0x%02x, protocol"
 			" error.\n", function);
-		cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
 		se_tmr->response = ISCSI_TMF_RSP_NOT_SUPPORTED;
 		goto attach;
 	}
@@ -2360,7 +2336,7 @@ static void iscsit_build_conn_drop_async_message(struct iscsi_conn *conn)
 	if (!conn_p)
 		return;
 
-	cmd = iscsit_allocate_cmd(conn_p, GFP_KERNEL);
+	cmd = iscsit_allocate_cmd(conn_p, GFP_ATOMIC);
 	if (!cmd) {
 		iscsit_dec_conn_usage_count(conn_p);
 		return;
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index ff6fd4f..e752ab8 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -235,7 +235,7 @@ static struct se_tpg_np *lio_target_call_addnptotpg(
 	 * iSER/SCTP (TODO, software emulation with osc-iwarp)
 	 * iSER/IB (TODO, hardware available)
 	 *
-	 * can be enabled with atributes under
+	 * can be enabled with attributes under
 	 * sys/kernel/config/iscsi/$IQN/$TPG/np/$IP:$PORT/
 	 *
 	 */
@@ -803,7 +803,7 @@ static struct se_node_acl *lio_target_make_nodeacl(
 	acl = container_of(se_nacl, struct iscsi_node_acl, se_node_acl);
 	stats_cg = &se_nacl->acl_fabric_stat_group;
 
-	stats_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
+	stats_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2,
 				GFP_KERNEL);
 	if (!stats_cg->default_groups) {
 		pr_err("Unable to allocate memory for"
@@ -1268,7 +1268,7 @@ static struct se_wwn *lio_target_call_coreaddtiqn(
 	 */
 	stats_cg = &tiqn->tiqn_wwn.fabric_stat_group;
 
-	stats_cg->default_groups = kzalloc(sizeof(struct config_group) * 6,
+	stats_cg->default_groups = kmalloc(sizeof(struct config_group *) * 6,
 				GFP_KERNEL);
 	if (!stats_cg->default_groups) {
 		pr_err("Unable to allocate memory for"
diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h
index 21048db..7a333d2 100644
--- a/drivers/target/iscsi/iscsi_target_core.h
+++ b/drivers/target/iscsi/iscsi_target_core.h
@@ -474,7 +474,7 @@ struct iscsi_cmd {
 	struct scatterlist	*first_data_sg;
 	u32			first_data_sg_off;
 	u32			kmapped_nents;
-
+	sense_reason_t		sense_reason;
 }  ____cacheline_aligned;
 
 struct iscsi_tmr_req {
diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c
index 8aacf61..8e6298c 100644
--- a/drivers/target/iscsi/iscsi_target_erl0.c
+++ b/drivers/target/iscsi/iscsi_target_erl0.c
@@ -410,11 +410,11 @@ static int iscsit_dataout_pre_datapduinorder_yes(
 	/*
 	 * For DataSequenceInOrder=Yes: If the offset is greater than the global
 	 * DataPDUInOrder=Yes offset counter in struct iscsi_cmd a protcol error has
-	 * occured and fail the connection.
+	 * occurred and fail the connection.
 	 *
 	 * For DataSequenceInOrder=No: If the offset is greater than the per
 	 * sequence DataPDUInOrder=Yes offset counter in struct iscsi_seq a protocol
-	 * error has occured and fail the connection.
+	 * error has occurred and fail the connection.
 	 */
 	if (conn->sess->sess_ops->DataSequenceInOrder) {
 		if (be32_to_cpu(hdr->offset) != cmd->write_data_done) {
@@ -801,7 +801,7 @@ void iscsit_start_time2retain_handler(struct iscsi_session *sess)
 {
 	int tpg_active;
 	/*
-	 * Only start Time2Retain timer when the assoicated TPG is still in
+	 * Only start Time2Retain timer when the associated TPG is still in
 	 * an ACTIVE (eg: not disabled or shutdown) state.
 	 */
 	spin_lock(&ISCSI_TPG_S(sess)->tpg_state_lock);
diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c
index 21f29d9..0b52a23 100644
--- a/drivers/target/iscsi/iscsi_target_erl1.c
+++ b/drivers/target/iscsi/iscsi_target_erl1.c
@@ -929,11 +929,10 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
 	case ISCSI_OP_SCSI_CMD:
 		/*
 		 * Go ahead and send the CHECK_CONDITION status for
-		 * any SCSI CDB exceptions that may have occurred, also
-		 * handle the SCF_SCSI_RESERVATION_CONFLICT case here as well.
+		 * any SCSI CDB exceptions that may have occurred.
 		 */
-		if (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION) {
-			if (se_cmd->scsi_sense_reason == TCM_RESERVATION_CONFLICT) {
+		if (cmd->sense_reason) {
+			if (cmd->sense_reason == TCM_RESERVATION_CONFLICT) {
 				cmd->i_state = ISTATE_SEND_STATUS;
 				spin_unlock_bh(&cmd->istate_lock);
 				iscsit_add_cmd_to_response_queue(cmd, cmd->conn,
@@ -956,7 +955,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
 			 * exception
 			 */
 			return transport_send_check_condition_and_sense(se_cmd,
-					se_cmd->scsi_sense_reason, 0);
+					cmd->sense_reason, 0);
 		}
 		/*
 		 * Special case for delayed CmdSN with Immediate
@@ -1013,7 +1012,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
 		iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
 		break;
 	case ISCSI_OP_SCSI_TMFUNC:
-		if (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION) {
+		if (cmd->se_cmd.se_tmr_req->response) {
 			spin_unlock_bh(&cmd->istate_lock);
 			iscsit_add_cmd_to_response_queue(cmd, cmd->conn,
 					cmd->i_state);
diff --git a/drivers/target/iscsi/iscsi_target_erl2.c b/drivers/target/iscsi/iscsi_target_erl2.c
index 17d8c20..9ac4c151 100644
--- a/drivers/target/iscsi/iscsi_target_erl2.c
+++ b/drivers/target/iscsi/iscsi_target_erl2.c
@@ -372,7 +372,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
 		 * made generic here.
 		 */
 		if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd &&
-		     (cmd->cmd_sn >= conn->sess->exp_cmd_sn)) {
+		     iscsi_sna_gte(cmd->stat_sn, conn->sess->exp_cmd_sn)) {
 			list_del(&cmd->i_conn_node);
 			spin_unlock_bh(&conn->cmd_lock);
 			iscsit_free_cmd(cmd);
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index f8dbec0..fdb632f 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -127,13 +127,13 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
 
 	initiatorname_param = iscsi_find_param_from_key(
 			INITIATORNAME, conn->param_list);
-	if (!initiatorname_param)
-		return -1;
-
 	sessiontype_param = iscsi_find_param_from_key(
 			SESSIONTYPE, conn->param_list);
-	if (!sessiontype_param)
+	if (!initiatorname_param || !sessiontype_param) {
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+			ISCSI_LOGIN_STATUS_MISSING_FIELDS);
 		return -1;
+	}
 
 	sessiontype = (strncmp(sessiontype_param->value, NORMAL, 6)) ? 1 : 0;
 
@@ -254,9 +254,9 @@ static int iscsi_login_zero_tsih_s1(
 		kfree(sess);
 		return -ENOMEM;
 	}
-	spin_lock(&sess_idr_lock);
+	spin_lock_bh(&sess_idr_lock);
 	ret = idr_get_new(&sess_idr, NULL, &sess->session_index);
-	spin_unlock(&sess_idr_lock);
+	spin_unlock_bh(&sess_idr_lock);
 
 	if (ret < 0) {
 		pr_err("idr_get_new() for sess_idr failed\n");
@@ -1118,10 +1118,8 @@ new_sess_out:
 		idr_remove(&sess_idr, conn->sess->session_index);
 		spin_unlock_bh(&sess_idr_lock);
 	}
-	if (conn->sess->sess_ops)
-		kfree(conn->sess->sess_ops);
-	if (conn->sess)
-		kfree(conn->sess);
+	kfree(conn->sess->sess_ops);
+	kfree(conn->sess);
 old_sess_out:
 	iscsi_stop_login_thread_timer(np);
 	/*
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
index e9053a0..9d902ae 100644
--- a/drivers/target/iscsi/iscsi_target_nego.c
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -620,8 +620,11 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log
 			login->req_buf,
 			payload_length,
 			conn);
-	if (ret < 0)
+	if (ret < 0) {
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+				ISCSI_LOGIN_STATUS_INIT_ERR);
 		return -1;
+	}
 
 	if (login->first_request)
 		if (iscsi_target_check_first_request(conn, login) < 0)
@@ -636,8 +639,11 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log
 			login->rsp_buf,
 			&login->rsp_length,
 			conn->param_list);
-	if (ret < 0)
+	if (ret < 0) {
+		iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
+				ISCSI_LOGIN_STATUS_INIT_ERR);
 		return -1;
+	}
 
 	if (!login->auth_complete &&
 	     ISCSI_TPG_ATTRIB(ISCSI_TPG_C(conn))->authentication) {
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c
index 90b7400..1bf7432 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.c
+++ b/drivers/target/iscsi/iscsi_target_parameters.c
@@ -1432,6 +1432,7 @@ static struct iscsi_param *iscsi_check_key(
 			break;
 		case PHASE_OPERATIONAL:
 			pr_debug("Operational phase.\n");
+			break;
 		default:
 			pr_debug("Unknown phase.\n");
 		}
diff --git a/drivers/target/iscsi/iscsi_target_tmr.c b/drivers/target/iscsi/iscsi_target_tmr.c
index 4a99820..9d4417a 100644
--- a/drivers/target/iscsi/iscsi_target_tmr.c
+++ b/drivers/target/iscsi/iscsi_target_tmr.c
@@ -50,8 +50,8 @@ u8 iscsit_tmr_abort_task(
 	if (!ref_cmd) {
 		pr_err("Unable to locate RefTaskTag: 0x%08x on CID:"
 			" %hu.\n", hdr->rtt, conn->cid);
-		return (be32_to_cpu(hdr->refcmdsn) >= conn->sess->exp_cmd_sn &&
-			be32_to_cpu(hdr->refcmdsn) <= conn->sess->max_cmd_sn) ?
+		return (iscsi_sna_gte(be32_to_cpu(hdr->refcmdsn), conn->sess->exp_cmd_sn) &&
+			iscsi_sna_lte(be32_to_cpu(hdr->refcmdsn), conn->sess->max_cmd_sn)) ?
 			ISCSI_TMF_RSP_COMPLETE : ISCSI_TMF_RSP_NO_TASK;
 	}
 	if (ref_cmd->cmd_sn != be32_to_cpu(hdr->refcmdsn)) {
diff --git a/drivers/target/iscsi/iscsi_target_tq.c b/drivers/target/iscsi/iscsi_target_tq.c
index 9d881a0..8128952 100644
--- a/drivers/target/iscsi/iscsi_target_tq.c
+++ b/drivers/target/iscsi/iscsi_target_tq.c
@@ -66,8 +66,7 @@ static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void)
 		return NULL;
 	}
 
-	list_for_each_entry(ts, &inactive_ts_list, ts_list)
-		break;
+	ts = list_first_entry(&inactive_ts_list, struct iscsi_thread_set, ts_list);
 
 	list_del(&ts->ts_list);
 	iscsit_global->inactive_ts--;
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index 1a91195..7ce3505 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -500,8 +500,8 @@ struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *c
 		spin_unlock_bh(&conn->immed_queue_lock);
 		return NULL;
 	}
-	list_for_each_entry(qr, &conn->immed_queue_list, qr_list)
-		break;
+	qr = list_first_entry(&conn->immed_queue_list,
+			      struct iscsi_queue_req, qr_list);
 
 	list_del(&qr->qr_list);
 	if (qr->cmd)
@@ -575,8 +575,8 @@ struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *co
 		return NULL;
 	}
 
-	list_for_each_entry(qr, &conn->response_queue_list, qr_list)
-		break;
+	qr = list_first_entry(&conn->response_queue_list,
+			      struct iscsi_queue_req, qr_list);
 
 	list_del(&qr->qr_list);
 	if (qr->cmd)
@@ -684,7 +684,7 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd)
 void iscsit_free_cmd(struct iscsi_cmd *cmd)
 {
 	/*
-	 * Determine if a struct se_cmd is assoicated with
+	 * Determine if a struct se_cmd is associated with
 	 * this struct iscsi_cmd.
 	 */
 	switch (cmd->iscsi_opcode) {
diff --git a/drivers/target/loopback/tcm_loop.h b/drivers/target/loopback/tcm_loop.h
index 7b54893..dd7a84e 100644
--- a/drivers/target/loopback/tcm_loop.h
+++ b/drivers/target/loopback/tcm_loop.h
@@ -53,7 +53,6 @@ struct tcm_loop_hba {
 	struct se_hba_s *se_hba;
 	struct se_lun *tl_hba_lun;
 	struct se_port *tl_hba_lun_sep;
-	struct se_device_s *se_dev_hba_ptr;
 	struct tcm_loop_nexus *tl_nexus;
 	struct device dev;
 	struct Scsi_Host *sh;
diff --git a/drivers/target/sbp/Kconfig b/drivers/target/sbp/Kconfig
index 132da54..1614bc7 100644
--- a/drivers/target/sbp/Kconfig
+++ b/drivers/target/sbp/Kconfig
@@ -1,6 +1,6 @@
 config SBP_TARGET
 	tristate "FireWire SBP-2 fabric module"
-	depends on FIREWIRE && EXPERIMENTAL
+	depends on FIREWIRE
 	help
 	  Say Y or M here to enable SCSI target functionality over FireWire.
 	  This enables you to expose SCSI devices to other nodes on the FireWire
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index 9a5f9a7..85140f7 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -3,8 +3,7 @@
  *
  * This file contains SPC-3 compliant asymmetric logical unit assigntment (ALUA)
  *
- * Copyright (c) 2009-2010 Rising Tide Systems
- * Copyright (c) 2009-2010 Linux-iSCSI.org
+ * (c) Copyright 2009-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@kernel.org>
  *
@@ -41,7 +40,7 @@
 #include "target_core_alua.h"
 #include "target_core_ua.h"
 
-static int core_alua_check_transition(int state, int *primary);
+static sense_reason_t core_alua_check_transition(int state, int *primary);
 static int core_alua_set_tg_pt_secondary_state(
 		struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem,
 		struct se_port *port, int explict, int offline);
@@ -59,15 +58,17 @@ struct t10_alua_lu_gp *default_lu_gp;
  *
  * See spc4r17 section 6.27
  */
-int target_emulate_report_target_port_groups(struct se_cmd *cmd)
+sense_reason_t
+target_emulate_report_target_port_groups(struct se_cmd *cmd)
 {
-	struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
+	struct se_device *dev = cmd->se_dev;
 	struct se_port *port;
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
 	unsigned char *buf;
 	u32 rd_len = 0, off;
 	int ext_hdr = (cmd->t_task_cdb[1] & 0x20);
+
 	/*
 	 * Skip over RESERVED area to first Target port group descriptor
 	 * depending on the PARAMETER DATA FORMAT type..
@@ -81,13 +82,14 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd)
 		pr_warn("REPORT TARGET PORT GROUPS allocation length %u too"
 			" small for %s header\n", cmd->data_length,
 			(ext_hdr) ? "extended" : "normal");
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		return -EINVAL;
+		return TCM_INVALID_CDB_FIELD;
 	}
 	buf = transport_kmap_data_sg(cmd);
+	if (!buf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-	spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
-	list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list,
+	spin_lock(&dev->t10_alua.tg_pt_gps_lock);
+	list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list,
 			tg_pt_gp_list) {
 		/*
 		 * Check if the Target port group and Target port descriptor list
@@ -160,7 +162,7 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd)
 		}
 		spin_unlock(&tg_pt_gp->tg_pt_gp_lock);
 	}
-	spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
+	spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 	/*
 	 * Set the RETURN DATA LENGTH set in the header of the DataIN Payload
 	 */
@@ -200,32 +202,33 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd)
  *
  * See spc4r17 section 6.35
  */
-int target_emulate_set_target_port_groups(struct se_cmd *cmd)
+sense_reason_t
+target_emulate_set_target_port_groups(struct se_cmd *cmd)
 {
 	struct se_device *dev = cmd->se_dev;
-	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
 	struct se_port *port, *l_port = cmd->se_lun->lun_sep;
 	struct se_node_acl *nacl = cmd->se_sess->se_node_acl;
 	struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *l_tg_pt_gp;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem;
 	unsigned char *buf;
 	unsigned char *ptr;
+	sense_reason_t rc;
 	u32 len = 4; /* Skip over RESERVED area in header */
-	int alua_access_state, primary = 0, rc;
+	int alua_access_state, primary = 0;
 	u16 tg_pt_id, rtpi;
 
-	if (!l_port) {
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		return -EINVAL;
-	}
+	if (!l_port)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
 	if (cmd->data_length < 4) {
 		pr_warn("SET TARGET PORT GROUPS parameter list length %u too"
 			" small\n", cmd->data_length);
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		return -EINVAL;
+		return TCM_INVALID_PARAMETER_LIST;
 	}
 
 	buf = transport_kmap_data_sg(cmd);
+	if (!buf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
 	/*
 	 * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed
@@ -234,8 +237,7 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd)
 	l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem;
 	if (!l_tg_pt_gp_mem) {
 		pr_err("Unable to access l_port->sep_alua_tg_pt_gp_mem\n");
-		cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-		rc = -EINVAL;
+		rc = TCM_UNSUPPORTED_SCSI_OPCODE;
 		goto out;
 	}
 	spin_lock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
@@ -243,24 +245,22 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd)
 	if (!l_tg_pt_gp) {
 		spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
 		pr_err("Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n");
-		cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-		rc = -EINVAL;
+		rc = TCM_UNSUPPORTED_SCSI_OPCODE;
 		goto out;
 	}
-	rc = (l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA);
 	spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
 
-	if (!rc) {
+	if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA)) {
 		pr_debug("Unable to process SET_TARGET_PORT_GROUPS"
 				" while TPGS_EXPLICT_ALUA is disabled\n");
-		cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-		rc = -EINVAL;
+		rc = TCM_UNSUPPORTED_SCSI_OPCODE;
 		goto out;
 	}
 
 	ptr = &buf[4]; /* Skip over RESERVED area in header */
 
 	while (len < cmd->data_length) {
+		bool found = false;
 		alua_access_state = (ptr[0] & 0x0f);
 		/*
 		 * Check the received ALUA access state, and determine if
@@ -268,7 +268,7 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd)
 		 * access state.
 		 */
 		rc = core_alua_check_transition(alua_access_state, &primary);
-		if (rc != 0) {
+		if (rc) {
 			/*
 			 * If the SET TARGET PORT GROUPS attempts to establish
 			 * an invalid combination of target port asymmetric
@@ -279,11 +279,9 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd)
 			 * REQUEST, and the additional sense code set to INVALID
 			 * FIELD IN PARAMETER LIST.
 			 */
-			cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-			rc = -EINVAL;
 			goto out;
 		}
-		rc = -1;
+
 		/*
 		 * If the ASYMMETRIC ACCESS STATE field (see table 267)
 		 * specifies a primary target port asymmetric access state,
@@ -303,9 +301,9 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd)
 			 * Locate the matching target port group ID from
 			 * the global tg_pt_gp list
 			 */
-			spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
+			spin_lock(&dev->t10_alua.tg_pt_gps_lock);
 			list_for_each_entry(tg_pt_gp,
-					&su_dev->t10_alua.tg_pt_gps_list,
+					&dev->t10_alua.tg_pt_gps_list,
 					tg_pt_gp_list) {
 				if (!tg_pt_gp->tg_pt_gp_valid_id)
 					continue;
@@ -315,27 +313,20 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd)
 
 				atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
 				smp_mb__after_atomic_inc();
-				spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
 
-				rc = core_alua_do_port_transition(tg_pt_gp,
+				spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
+
+				if (!core_alua_do_port_transition(tg_pt_gp,
 						dev, l_port, nacl,
-						alua_access_state, 1);
+						alua_access_state, 1))
+					found = true;
 
-				spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
+				spin_lock(&dev->t10_alua.tg_pt_gps_lock);
 				atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
 				smp_mb__after_atomic_dec();
 				break;
 			}
-			spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
-			/*
-			 * If not matching target port group ID can be located
-			 * throw an exception with ASCQ: INVALID_PARAMETER_LIST
-			 */
-			if (rc != 0) {
-				cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-				rc = -EINVAL;
-				goto out;
-			}
+			spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 		} else {
 			/*
 			 * Extact the RELATIVE TARGET PORT IDENTIFIER to identify
@@ -354,25 +345,22 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd)
 					continue;
 
 				tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
+
 				spin_unlock(&dev->se_port_lock);
 
-				rc = core_alua_set_tg_pt_secondary_state(
-						tg_pt_gp_mem, port, 1, 1);
+				if (!core_alua_set_tg_pt_secondary_state(
+						tg_pt_gp_mem, port, 1, 1))
+					found = true;
 
 				spin_lock(&dev->se_port_lock);
 				break;
 			}
 			spin_unlock(&dev->se_port_lock);
-			/*
-			 * If not matching relative target port identifier can
-			 * be located, throw an exception with ASCQ:
-			 * INVALID_PARAMETER_LIST
-			 */
-			if (rc != 0) {
-				cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-				rc = -EINVAL;
-				goto out;
-			}
+		}
+
+		if (!found) {
+			rc = TCM_INVALID_PARAMETER_LIST;
+			goto out;
 		}
 
 		ptr += 4;
@@ -523,40 +511,27 @@ static inline int core_alua_state_transition(
 }
 
 /*
- * Used for alua_type SPC_ALUA_PASSTHROUGH and SPC2_ALUA_DISABLED
- * in transport_cmd_sequencer().  This function is assigned to
- * struct t10_alua *->state_check() in core_setup_alua()
- */
-static int core_alua_state_check_nop(
-	struct se_cmd *cmd,
-	unsigned char *cdb,
-	u8 *alua_ascq)
-{
-	return 0;
-}
-
-/*
- * Used for alua_type SPC3_ALUA_EMULATED in transport_cmd_sequencer().
- * This function is assigned to struct t10_alua *->state_check() in
- * core_setup_alua()
- *
- * Also, this function can return three different return codes to
- * signal transport_generic_cmd_sequencer()
- *
  * return 1: Is used to signal LUN not accecsable, and check condition/not ready
  * return 0: Used to signal success
  * reutrn -1: Used to signal failure, and invalid cdb field
  */
-static int core_alua_state_check(
-	struct se_cmd *cmd,
-	unsigned char *cdb,
-	u8 *alua_ascq)
+sense_reason_t
+target_alua_state_check(struct se_cmd *cmd)
 {
+	struct se_device *dev = cmd->se_dev;
+	unsigned char *cdb = cmd->t_task_cdb;
 	struct se_lun *lun = cmd->se_lun;
 	struct se_port *port = lun->lun_sep;
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
 	int out_alua_state, nonop_delay_msecs;
+	u8 alua_ascq;
+	int ret;
+
+	if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)
+		return 0;
+	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
+		return 0;
 
 	if (!port)
 		return 0;
@@ -565,11 +540,11 @@ static int core_alua_state_check(
 	 * access state: OFFLINE
 	 */
 	if (atomic_read(&port->sep_tg_pt_secondary_offline)) {
-		*alua_ascq = ASCQ_04H_ALUA_OFFLINE;
 		pr_debug("ALUA: Got secondary offline status for local"
 				" target port\n");
-		*alua_ascq = ASCQ_04H_ALUA_OFFLINE;
-		return 1;
+		alua_ascq = ASCQ_04H_ALUA_OFFLINE;
+		ret = 1;
+		goto out;
 	}
 	 /*
 	 * Second, obtain the struct t10_alua_tg_pt_gp_member pointer to the
@@ -594,14 +569,18 @@ static int core_alua_state_check(
 
 	switch (out_alua_state) {
 	case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
-		return core_alua_state_nonoptimized(cmd, cdb,
-					nonop_delay_msecs, alua_ascq);
+		ret = core_alua_state_nonoptimized(cmd, cdb,
+					nonop_delay_msecs, &alua_ascq);
+		break;
 	case ALUA_ACCESS_STATE_STANDBY:
-		return core_alua_state_standby(cmd, cdb, alua_ascq);
+		ret = core_alua_state_standby(cmd, cdb, &alua_ascq);
+		break;
 	case ALUA_ACCESS_STATE_UNAVAILABLE:
-		return core_alua_state_unavailable(cmd, cdb, alua_ascq);
+		ret = core_alua_state_unavailable(cmd, cdb, &alua_ascq);
+		break;
 	case ALUA_ACCESS_STATE_TRANSITION:
-		return core_alua_state_transition(cmd, cdb, alua_ascq);
+		ret = core_alua_state_transition(cmd, cdb, &alua_ascq);
+		break;
 	/*
 	 * OFFLINE is a secondary ALUA target port group access state, that is
 	 * handled above with struct se_port->sep_tg_pt_secondary_offline=1
@@ -610,7 +589,24 @@ static int core_alua_state_check(
 	default:
 		pr_err("Unknown ALUA access state: 0x%02x\n",
 				out_alua_state);
-		return -EINVAL;
+		return TCM_INVALID_CDB_FIELD;
+	}
+
+out:
+	if (ret > 0) {
+		/*
+		 * Set SCSI additional sense code (ASC) to 'LUN Not Accessible';
+		 * The ALUA additional sense code qualifier (ASCQ) is determined
+		 * by the ALUA primary or secondary access state..
+		 */
+		pr_debug("[%s]: ALUA TG Port not available, "
+			"SenseKey: NOT_READY, ASC/ASCQ: "
+			"0x04/0x%02x\n",
+			cmd->se_tfo->get_fabric_name(), alua_ascq);
+
+		cmd->scsi_asc = 0x04;
+		cmd->scsi_ascq = alua_ascq;
+		return TCM_CHECK_CONDITION_NOT_READY;
 	}
 
 	return 0;
@@ -619,7 +615,8 @@ static int core_alua_state_check(
 /*
  * Check implict and explict ALUA state change request.
  */
-static int core_alua_check_transition(int state, int *primary)
+static sense_reason_t
+core_alua_check_transition(int state, int *primary)
 {
 	switch (state) {
 	case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED:
@@ -641,7 +638,7 @@ static int core_alua_check_transition(int state, int *primary)
 		break;
 	default:
 		pr_err("Unknown ALUA access state: 0x%02x\n", state);
-		return -EINVAL;
+		return TCM_INVALID_PARAMETER_LIST;
 	}
 
 	return 0;
@@ -758,8 +755,7 @@ static int core_alua_update_tpg_primary_metadata(
 	int primary_state,
 	unsigned char *md_buf)
 {
-	struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev;
-	struct t10_wwn *wwn = &su_dev->t10_wwn;
+	struct t10_wwn *wwn = &tg_pt_gp->tg_pt_gp_dev->t10_wwn;
 	char path[ALUA_METADATA_PATH_LEN];
 	int len;
 
@@ -899,7 +895,6 @@ int core_alua_do_port_transition(
 {
 	struct se_device *dev;
 	struct se_port *port;
-	struct se_subsystem_dev *su_dev;
 	struct se_node_acl *nacl;
 	struct t10_alua_lu_gp *lu_gp;
 	struct t10_alua_lu_gp_member *lu_gp_mem, *local_lu_gp_mem;
@@ -949,14 +944,13 @@ int core_alua_do_port_transition(
 				lu_gp_mem_list) {
 
 		dev = lu_gp_mem->lu_gp_mem_dev;
-		su_dev = dev->se_sub_dev;
 		atomic_inc(&lu_gp_mem->lu_gp_mem_ref_cnt);
 		smp_mb__after_atomic_inc();
 		spin_unlock(&lu_gp->lu_gp_lock);
 
-		spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
+		spin_lock(&dev->t10_alua.tg_pt_gps_lock);
 		list_for_each_entry(tg_pt_gp,
-				&su_dev->t10_alua.tg_pt_gps_list,
+				&dev->t10_alua.tg_pt_gps_list,
 				tg_pt_gp_list) {
 
 			if (!tg_pt_gp->tg_pt_gp_valid_id)
@@ -981,7 +975,7 @@ int core_alua_do_port_transition(
 			}
 			atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
 			smp_mb__after_atomic_inc();
-			spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
+			spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 			/*
 			 * core_alua_do_transition_tg_pt() will always return
 			 * success.
@@ -989,11 +983,11 @@ int core_alua_do_port_transition(
 			core_alua_do_transition_tg_pt(tg_pt_gp, port,
 					nacl, md_buf, new_state, explict);
 
-			spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
+			spin_lock(&dev->t10_alua.tg_pt_gps_lock);
 			atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
 			smp_mb__after_atomic_dec();
 		}
-		spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
+		spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 
 		spin_lock(&lu_gp->lu_gp_lock);
 		atomic_dec(&lu_gp_mem->lu_gp_mem_ref_cnt);
@@ -1268,14 +1262,9 @@ void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp)
 
 void core_alua_free_lu_gp_mem(struct se_device *dev)
 {
-	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
-	struct t10_alua *alua = &su_dev->t10_alua;
 	struct t10_alua_lu_gp *lu_gp;
 	struct t10_alua_lu_gp_member *lu_gp_mem;
 
-	if (alua->alua_type != SPC3_ALUA_EMULATED)
-		return;
-
 	lu_gp_mem = dev->dev_alua_lu_gp_mem;
 	if (!lu_gp_mem)
 		return;
@@ -1358,10 +1347,8 @@ void __core_alua_drop_lu_gp_mem(
 	spin_unlock(&lu_gp->lu_gp_lock);
 }
 
-struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(
-	struct se_subsystem_dev *su_dev,
-	const char *name,
-	int def_group)
+struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev,
+		const char *name, int def_group)
 {
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
 
@@ -1375,7 +1362,7 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(
 	mutex_init(&tg_pt_gp->tg_pt_gp_md_mutex);
 	spin_lock_init(&tg_pt_gp->tg_pt_gp_lock);
 	atomic_set(&tg_pt_gp->tg_pt_gp_ref_cnt, 0);
-	tg_pt_gp->tg_pt_gp_su_dev = su_dev;
+	tg_pt_gp->tg_pt_gp_dev = dev;
 	tg_pt_gp->tg_pt_gp_md_buf_len = ALUA_MD_BUF_LEN;
 	atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
 		ALUA_ACCESS_STATE_ACTIVE_OPTMIZED);
@@ -1392,14 +1379,14 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(
 	tg_pt_gp->tg_pt_gp_implict_trans_secs = ALUA_DEFAULT_IMPLICT_TRANS_SECS;
 
 	if (def_group) {
-		spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
+		spin_lock(&dev->t10_alua.tg_pt_gps_lock);
 		tg_pt_gp->tg_pt_gp_id =
-				su_dev->t10_alua.alua_tg_pt_gps_counter++;
+				dev->t10_alua.alua_tg_pt_gps_counter++;
 		tg_pt_gp->tg_pt_gp_valid_id = 1;
-		su_dev->t10_alua.alua_tg_pt_gps_count++;
+		dev->t10_alua.alua_tg_pt_gps_count++;
 		list_add_tail(&tg_pt_gp->tg_pt_gp_list,
-			      &su_dev->t10_alua.tg_pt_gps_list);
-		spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
+			      &dev->t10_alua.tg_pt_gps_list);
+		spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 	}
 
 	return tg_pt_gp;
@@ -1409,9 +1396,10 @@ int core_alua_set_tg_pt_gp_id(
 	struct t10_alua_tg_pt_gp *tg_pt_gp,
 	u16 tg_pt_gp_id)
 {
-	struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev;
+	struct se_device *dev = tg_pt_gp->tg_pt_gp_dev;
 	struct t10_alua_tg_pt_gp *tg_pt_gp_tmp;
 	u16 tg_pt_gp_id_tmp;
+
 	/*
 	 * The tg_pt_gp->tg_pt_gp_id may only be set once..
 	 */
@@ -1421,19 +1409,19 @@ int core_alua_set_tg_pt_gp_id(
 		return -EINVAL;
 	}
 
-	spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
-	if (su_dev->t10_alua.alua_tg_pt_gps_count == 0x0000ffff) {
+	spin_lock(&dev->t10_alua.tg_pt_gps_lock);
+	if (dev->t10_alua.alua_tg_pt_gps_count == 0x0000ffff) {
 		pr_err("Maximum ALUA alua_tg_pt_gps_count:"
 			" 0x0000ffff reached\n");
-		spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
+		spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 		kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp);
 		return -ENOSPC;
 	}
 again:
 	tg_pt_gp_id_tmp = (tg_pt_gp_id != 0) ? tg_pt_gp_id :
-			su_dev->t10_alua.alua_tg_pt_gps_counter++;
+			dev->t10_alua.alua_tg_pt_gps_counter++;
 
-	list_for_each_entry(tg_pt_gp_tmp, &su_dev->t10_alua.tg_pt_gps_list,
+	list_for_each_entry(tg_pt_gp_tmp, &dev->t10_alua.tg_pt_gps_list,
 			tg_pt_gp_list) {
 		if (tg_pt_gp_tmp->tg_pt_gp_id == tg_pt_gp_id_tmp) {
 			if (!tg_pt_gp_id)
@@ -1441,7 +1429,7 @@ again:
 
 			pr_err("ALUA Target Port Group ID: %hu already"
 				" exists, ignoring request\n", tg_pt_gp_id);
-			spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
+			spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 			return -EINVAL;
 		}
 	}
@@ -1449,9 +1437,9 @@ again:
 	tg_pt_gp->tg_pt_gp_id = tg_pt_gp_id_tmp;
 	tg_pt_gp->tg_pt_gp_valid_id = 1;
 	list_add_tail(&tg_pt_gp->tg_pt_gp_list,
-			&su_dev->t10_alua.tg_pt_gps_list);
-	su_dev->t10_alua.alua_tg_pt_gps_count++;
-	spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
+			&dev->t10_alua.tg_pt_gps_list);
+	dev->t10_alua.alua_tg_pt_gps_count++;
+	spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 
 	return 0;
 }
@@ -1480,8 +1468,9 @@ struct t10_alua_tg_pt_gp_member *core_alua_allocate_tg_pt_gp_mem(
 void core_alua_free_tg_pt_gp(
 	struct t10_alua_tg_pt_gp *tg_pt_gp)
 {
-	struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev;
+	struct se_device *dev = tg_pt_gp->tg_pt_gp_dev;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *tg_pt_gp_mem_tmp;
+
 	/*
 	 * Once we have reached this point, config_item_put() has already
 	 * been called from target_core_alua_drop_tg_pt_gp().
@@ -1490,10 +1479,11 @@ void core_alua_free_tg_pt_gp(
 	 * no assications *OR* explict ALUA via SET_TARGET_PORT_GROUPS
 	 * can be made while we are releasing struct t10_alua_tg_pt_gp.
 	 */
-	spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
+	spin_lock(&dev->t10_alua.tg_pt_gps_lock);
 	list_del(&tg_pt_gp->tg_pt_gp_list);
-	su_dev->t10_alua.alua_tg_pt_gps_counter--;
-	spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
+	dev->t10_alua.alua_tg_pt_gps_counter--;
+	spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
+
 	/*
 	 * Allow a struct t10_alua_tg_pt_gp_member * referenced by
 	 * core_alua_get_tg_pt_gp_by_name() in
@@ -1502,6 +1492,7 @@ void core_alua_free_tg_pt_gp(
 	 */
 	while (atomic_read(&tg_pt_gp->tg_pt_gp_ref_cnt))
 		cpu_relax();
+
 	/*
 	 * Release reference to struct t10_alua_tg_pt_gp from all associated
 	 * struct se_port.
@@ -1525,9 +1516,9 @@ void core_alua_free_tg_pt_gp(
 		 * default_tg_pt_gp.
 		 */
 		spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
-		if (tg_pt_gp != su_dev->t10_alua.default_tg_pt_gp) {
+		if (tg_pt_gp != dev->t10_alua.default_tg_pt_gp) {
 			__core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem,
-					su_dev->t10_alua.default_tg_pt_gp);
+					dev->t10_alua.default_tg_pt_gp);
 		} else
 			tg_pt_gp_mem->tg_pt_gp = NULL;
 		spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
@@ -1541,14 +1532,9 @@ void core_alua_free_tg_pt_gp(
 
 void core_alua_free_tg_pt_gp_mem(struct se_port *port)
 {
-	struct se_subsystem_dev *su_dev = port->sep_lun->lun_se_dev->se_sub_dev;
-	struct t10_alua *alua = &su_dev->t10_alua;
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
 
-	if (alua->alua_type != SPC3_ALUA_EMULATED)
-		return;
-
 	tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
 	if (!tg_pt_gp_mem)
 		return;
@@ -1574,25 +1560,24 @@ void core_alua_free_tg_pt_gp_mem(struct se_port *port)
 }
 
 static struct t10_alua_tg_pt_gp *core_alua_get_tg_pt_gp_by_name(
-	struct se_subsystem_dev *su_dev,
-	const char *name)
+		struct se_device *dev, const char *name)
 {
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
 	struct config_item *ci;
 
-	spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
-	list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list,
+	spin_lock(&dev->t10_alua.tg_pt_gps_lock);
+	list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list,
 			tg_pt_gp_list) {
 		if (!tg_pt_gp->tg_pt_gp_valid_id)
 			continue;
 		ci = &tg_pt_gp->tg_pt_gp_group.cg_item;
 		if (!strcmp(config_item_name(ci), name)) {
 			atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
-			spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
+			spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 			return tg_pt_gp;
 		}
 	}
-	spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
+	spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 
 	return NULL;
 }
@@ -1600,11 +1585,11 @@ static struct t10_alua_tg_pt_gp *core_alua_get_tg_pt_gp_by_name(
 static void core_alua_put_tg_pt_gp_from_name(
 	struct t10_alua_tg_pt_gp *tg_pt_gp)
 {
-	struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev;
+	struct se_device *dev = tg_pt_gp->tg_pt_gp_dev;
 
-	spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
+	spin_lock(&dev->t10_alua.tg_pt_gps_lock);
 	atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
-	spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock);
+	spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 }
 
 /*
@@ -1640,16 +1625,11 @@ static void __core_alua_drop_tg_pt_gp_mem(
 
 ssize_t core_alua_show_tg_pt_gp_info(struct se_port *port, char *page)
 {
-	struct se_subsystem_dev *su_dev = port->sep_lun->lun_se_dev->se_sub_dev;
 	struct config_item *tg_pt_ci;
-	struct t10_alua *alua = &su_dev->t10_alua;
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
 	ssize_t len = 0;
 
-	if (alua->alua_type != SPC3_ALUA_EMULATED)
-		return len;
-
 	tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
 	if (!tg_pt_gp_mem)
 		return len;
@@ -1683,7 +1663,7 @@ ssize_t core_alua_store_tg_pt_gp_info(
 {
 	struct se_portal_group *tpg;
 	struct se_lun *lun;
-	struct se_subsystem_dev *su_dev = port->sep_lun->lun_se_dev->se_sub_dev;
+	struct se_device *dev = port->sep_lun->lun_se_dev;
 	struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *tg_pt_gp_new = NULL;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
 	unsigned char buf[TG_PT_GROUP_NAME_BUF];
@@ -1692,13 +1672,9 @@ ssize_t core_alua_store_tg_pt_gp_info(
 	tpg = port->sep_tpg;
 	lun = port->sep_lun;
 
-	if (su_dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) {
-		pr_warn("SPC3_ALUA_EMULATED not enabled for"
-			" %s/tpgt_%hu/%s\n", tpg->se_tpg_tfo->tpg_get_wwn(tpg),
-			tpg->se_tpg_tfo->tpg_get_tag(tpg),
-			config_item_name(&lun->lun_group.cg_item));
-		return -EINVAL;
-	}
+	tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
+	if (!tg_pt_gp_mem)
+		return 0;
 
 	if (count > TG_PT_GROUP_NAME_BUF) {
 		pr_err("ALUA Target Port Group alias too large!\n");
@@ -1716,18 +1692,11 @@ ssize_t core_alua_store_tg_pt_gp_info(
 		 * struct t10_alua_tg_pt_gp.  This reference is released with
 		 * core_alua_put_tg_pt_gp_from_name() below.
 		 */
-		tg_pt_gp_new = core_alua_get_tg_pt_gp_by_name(su_dev,
+		tg_pt_gp_new = core_alua_get_tg_pt_gp_by_name(dev,
 					strstrip(buf));
 		if (!tg_pt_gp_new)
 			return -ENODEV;
 	}
-	tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
-	if (!tg_pt_gp_mem) {
-		if (tg_pt_gp_new)
-			core_alua_put_tg_pt_gp_from_name(tg_pt_gp_new);
-		pr_err("NULL struct se_port->sep_alua_tg_pt_gp_mem pointer\n");
-		return -EINVAL;
-	}
 
 	spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 	tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
@@ -1750,7 +1719,7 @@ ssize_t core_alua_store_tg_pt_gp_info(
 
 			__core_alua_drop_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp);
 			__core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem,
-					su_dev->t10_alua.default_tg_pt_gp);
+					dev->t10_alua.default_tg_pt_gp);
 			spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 
 			return count;
@@ -2054,32 +2023,12 @@ ssize_t core_alua_store_secondary_write_metadata(
 	return count;
 }
 
-int core_setup_alua(struct se_device *dev, int force_pt)
+int core_setup_alua(struct se_device *dev)
 {
-	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
-	struct t10_alua *alua = &su_dev->t10_alua;
-	struct t10_alua_lu_gp_member *lu_gp_mem;
-	/*
-	 * If this device is from Target_Core_Mod/pSCSI, use the ALUA logic
-	 * of the Underlying SCSI hardware.  In Linux/SCSI terms, this can
-	 * cause a problem because libata and some SATA RAID HBAs appear
-	 * under Linux/SCSI, but emulate SCSI logic themselves.
-	 */
-	if (((dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) &&
-	    !(dev->se_sub_dev->se_dev_attrib.emulate_alua)) || force_pt) {
-		alua->alua_type = SPC_ALUA_PASSTHROUGH;
-		alua->alua_state_check = &core_alua_state_check_nop;
-		pr_debug("%s: Using SPC_ALUA_PASSTHROUGH, no ALUA"
-			" emulation\n", dev->transport->name);
-		return 0;
-	}
-	/*
-	 * If SPC-3 or above is reported by real or emulated struct se_device,
-	 * use emulated ALUA.
-	 */
-	if (dev->transport->get_device_rev(dev) >= SCSI_3) {
-		pr_debug("%s: Enabling ALUA Emulation for SPC-3"
-			" device\n", dev->transport->name);
+	if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV &&
+	    !(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) {
+		struct t10_alua_lu_gp_member *lu_gp_mem;
+
 		/*
 		 * Associate this struct se_device with the default ALUA
 		 * LUN Group.
@@ -2088,8 +2037,6 @@ int core_setup_alua(struct se_device *dev, int force_pt)
 		if (IS_ERR(lu_gp_mem))
 			return PTR_ERR(lu_gp_mem);
 
-		alua->alua_type = SPC3_ALUA_EMULATED;
-		alua->alua_state_check = &core_alua_state_check;
 		spin_lock(&lu_gp_mem->lu_gp_mem_lock);
 		__core_alua_attach_lu_gp_mem(lu_gp_mem,
 				default_lu_gp);
@@ -2098,11 +2045,6 @@ int core_setup_alua(struct se_device *dev, int force_pt)
 		pr_debug("%s: Adding to default ALUA LU Group:"
 			" core/alua/lu_gps/default_lu_gp\n",
 			dev->transport->name);
-	} else {
-		alua->alua_type = SPC2_ALUA_DISABLED;
-		alua->alua_state_check = &core_alua_state_check_nop;
-		pr_debug("%s: Disabling ALUA Emulation for SPC-2"
-			" device\n", dev->transport->name);
 	}
 
 	return 0;
diff --git a/drivers/target/target_core_alua.h b/drivers/target/target_core_alua.h
index f920c17..e539c3e 100644
--- a/drivers/target/target_core_alua.h
+++ b/drivers/target/target_core_alua.h
@@ -72,8 +72,8 @@ extern struct kmem_cache *t10_alua_lu_gp_mem_cache;
 extern struct kmem_cache *t10_alua_tg_pt_gp_cache;
 extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache;
 
-extern int target_emulate_report_target_port_groups(struct se_cmd *);
-extern int target_emulate_set_target_port_groups(struct se_cmd *);
+extern sense_reason_t target_emulate_report_target_port_groups(struct se_cmd *);
+extern sense_reason_t target_emulate_set_target_port_groups(struct se_cmd *);
 extern int core_alua_check_nonop_delay(struct se_cmd *);
 extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *,
 				struct se_device *, struct se_port *,
@@ -91,7 +91,7 @@ extern void __core_alua_drop_lu_gp_mem(struct t10_alua_lu_gp_member *,
 					struct t10_alua_lu_gp *);
 extern void core_alua_drop_lu_gp_dev(struct se_device *);
 extern struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(
-			struct se_subsystem_dev *, const char *, int);
+			struct se_device *, const char *, int);
 extern int core_alua_set_tg_pt_gp_id(struct t10_alua_tg_pt_gp *, u16);
 extern struct t10_alua_tg_pt_gp_member *core_alua_allocate_tg_pt_gp_mem(
 					struct se_port *);
@@ -131,6 +131,7 @@ extern ssize_t core_alua_show_secondary_write_metadata(struct se_lun *,
 					char *);
 extern ssize_t core_alua_store_secondary_write_metadata(struct se_lun *,
 					const char *, size_t);
-extern int core_setup_alua(struct se_device *, int);
+extern int core_setup_alua(struct se_device *);
+extern sense_reason_t target_alua_state_check(struct se_cmd *cmd);
 
 #endif /* TARGET_CORE_ALUA_H */
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index c123327..4efb61b 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -3,8 +3,7 @@
  *
  * This file contains ConfigFS logic for the Generic Target Engine project.
  *
- * Copyright (c) 2008-2011 Rising Tide Systems
- * Copyright (c) 2008-2011 Linux-iSCSI.org
+ * (c) Copyright 2008-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@kernel.org>
  *
@@ -565,21 +564,8 @@ static ssize_t target_core_dev_show_attr_##_name(			\
 	struct se_dev_attrib *da,					\
 	char *page)							\
 {									\
-	struct se_device *dev;						\
-	struct se_subsystem_dev *se_dev = da->da_sub_dev;			\
-	ssize_t rb;							\
-									\
-	spin_lock(&se_dev->se_dev_lock);				\
-	dev = se_dev->se_dev_ptr;					\
-	if (!dev) {							\
-		spin_unlock(&se_dev->se_dev_lock); 			\
-		return -ENODEV;						\
-	}								\
-	rb = snprintf(page, PAGE_SIZE, "%u\n",				\
-		(u32)dev->se_sub_dev->se_dev_attrib._name);		\
-	spin_unlock(&se_dev->se_dev_lock);				\
-									\
-	return rb;							\
+	return snprintf(page, PAGE_SIZE, "%u\n",			\
+		(u32)da->da_dev->dev_attrib._name);			\
 }
 
 #define DEF_DEV_ATTRIB_STORE(_name)					\
@@ -588,26 +574,16 @@ static ssize_t target_core_dev_store_attr_##_name(			\
 	const char *page,						\
 	size_t count)							\
 {									\
-	struct se_device *dev;						\
-	struct se_subsystem_dev *se_dev = da->da_sub_dev;			\
 	unsigned long val;						\
 	int ret;							\
 									\
-	spin_lock(&se_dev->se_dev_lock);				\
-	dev = se_dev->se_dev_ptr;					\
-	if (!dev) {							\
-		spin_unlock(&se_dev->se_dev_lock);			\
-		return -ENODEV;						\
-	}								\
 	ret = strict_strtoul(page, 0, &val);				\
 	if (ret < 0) {							\
-		spin_unlock(&se_dev->se_dev_lock);                      \
 		pr_err("strict_strtoul() failed with"		\
 			" ret: %d\n", ret);				\
 		return -EINVAL;						\
 	}								\
-	ret = se_dev_set_##_name(dev, (u32)val);			\
-	spin_unlock(&se_dev->se_dev_lock);				\
+	ret = se_dev_set_##_name(da->da_dev, (u32)val);			\
 									\
 	return (!ret) ? count : -EINVAL;				\
 }
@@ -699,6 +675,9 @@ SE_DEV_ATTR(unmap_granularity, S_IRUGO | S_IWUSR);
 DEF_DEV_ATTRIB(unmap_granularity_alignment);
 SE_DEV_ATTR(unmap_granularity_alignment, S_IRUGO | S_IWUSR);
 
+DEF_DEV_ATTRIB(max_write_same_len);
+SE_DEV_ATTR(max_write_same_len, S_IRUGO | S_IWUSR);
+
 CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group);
 
 static struct configfs_attribute *target_core_dev_attrib_attrs[] = {
@@ -724,6 +703,7 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = {
 	&target_core_dev_attrib_max_unmap_block_desc_count.attr,
 	&target_core_dev_attrib_unmap_granularity.attr,
 	&target_core_dev_attrib_unmap_granularity_alignment.attr,
+	&target_core_dev_attrib_max_write_same_len.attr,
 	NULL,
 };
 
@@ -764,13 +744,6 @@ static ssize_t target_core_dev_wwn_show_attr_vpd_unit_serial(
 	struct t10_wwn *t10_wwn,
 	char *page)
 {
-	struct se_subsystem_dev *se_dev = t10_wwn->t10_sub_dev;
-	struct se_device *dev;
-
-	dev = se_dev->se_dev_ptr;
-	if (!dev)
-		return -ENODEV;
-
 	return sprintf(page, "T10 VPD Unit Serial Number: %s\n",
 		&t10_wwn->unit_serial[0]);
 }
@@ -780,8 +753,7 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial(
 	const char *page,
 	size_t count)
 {
-	struct se_subsystem_dev *su_dev = t10_wwn->t10_sub_dev;
-	struct se_device *dev;
+	struct se_device *dev = t10_wwn->t10_dev;
 	unsigned char buf[INQUIRY_VPD_SERIAL_LEN];
 
 	/*
@@ -794,7 +766,7 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial(
 	 * it is doing 'the right thing' wrt a world wide unique
 	 * VPD Unit Serial Number that OS dependent multipath can depend on.
 	 */
-	if (su_dev->su_dev_flags & SDF_FIRMWARE_VPD_UNIT_SERIAL) {
+	if (dev->dev_flags & DF_FIRMWARE_VPD_UNIT_SERIAL) {
 		pr_err("Underlying SCSI device firmware provided VPD"
 			" Unit Serial, ignoring request\n");
 		return -EOPNOTSUPP;
@@ -811,15 +783,13 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial(
 	 * (underneath the initiator side OS dependent multipath code)
 	 * could cause negative effects.
 	 */
-	dev = su_dev->se_dev_ptr;
-	if (dev) {
-		if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
-			pr_err("Unable to set VPD Unit Serial while"
-				" active %d $FABRIC_MOD exports exist\n",
-				atomic_read(&dev->dev_export_obj.obj_access_count));
-			return -EINVAL;
-		}
+	if (dev->export_count) {
+		pr_err("Unable to set VPD Unit Serial while"
+			" active %d $FABRIC_MOD exports exist\n",
+			dev->export_count);
+		return -EINVAL;
 	}
+
 	/*
 	 * This currently assumes ASCII encoding for emulated VPD Unit Serial.
 	 *
@@ -828,12 +798,12 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial(
 	 */
 	memset(buf, 0, INQUIRY_VPD_SERIAL_LEN);
 	snprintf(buf, INQUIRY_VPD_SERIAL_LEN, "%s", page);
-	snprintf(su_dev->t10_wwn.unit_serial, INQUIRY_VPD_SERIAL_LEN,
+	snprintf(dev->t10_wwn.unit_serial, INQUIRY_VPD_SERIAL_LEN,
 			"%s", strstrip(buf));
-	su_dev->su_dev_flags |= SDF_EMULATED_VPD_UNIT_SERIAL;
+	dev->dev_flags |= DF_EMULATED_VPD_UNIT_SERIAL;
 
 	pr_debug("Target_Core_ConfigFS: Set emulated VPD Unit Serial:"
-			" %s\n", su_dev->t10_wwn.unit_serial);
+			" %s\n", dev->t10_wwn.unit_serial);
 
 	return count;
 }
@@ -847,16 +817,10 @@ static ssize_t target_core_dev_wwn_show_attr_vpd_protocol_identifier(
 	struct t10_wwn *t10_wwn,
 	char *page)
 {
-	struct se_subsystem_dev *se_dev = t10_wwn->t10_sub_dev;
-	struct se_device *dev;
 	struct t10_vpd *vpd;
 	unsigned char buf[VPD_TMP_BUF_SIZE];
 	ssize_t len = 0;
 
-	dev = se_dev->se_dev_ptr;
-	if (!dev)
-		return -ENODEV;
-
 	memset(buf, 0, VPD_TMP_BUF_SIZE);
 
 	spin_lock(&t10_wwn->t10_vpd_lock);
@@ -894,16 +858,10 @@ static ssize_t target_core_dev_wwn_show_attr_##_name(			\
 	struct t10_wwn *t10_wwn,					\
 	char *page)							\
 {									\
-	struct se_subsystem_dev *se_dev = t10_wwn->t10_sub_dev;		\
-	struct se_device *dev;						\
 	struct t10_vpd *vpd;							\
 	unsigned char buf[VPD_TMP_BUF_SIZE];				\
 	ssize_t len = 0;						\
 									\
-	dev = se_dev->se_dev_ptr;					\
-	if (!dev)							\
-		return -ENODEV;						\
-									\
 	spin_lock(&t10_wwn->t10_vpd_lock);				\
 	list_for_each_entry(vpd, &t10_wwn->t10_vpd_list, vpd_list) {	\
 		if (vpd->association != _assoc)				\
@@ -1003,7 +961,7 @@ static struct config_item_type target_core_dev_wwn_cit = {
 
 /*  Start functions for struct config_item_type target_core_dev_pr_cit */
 
-CONFIGFS_EATTR_STRUCT(target_core_dev_pr, se_subsystem_dev);
+CONFIGFS_EATTR_STRUCT(target_core_dev_pr, se_device);
 #define SE_DEV_PR_ATTR(_name, _mode)					\
 static struct target_core_dev_pr_attribute target_core_dev_pr_##_name = \
 	__CONFIGFS_EATTR(_name, _mode,					\
@@ -1015,13 +973,8 @@ static struct target_core_dev_pr_attribute target_core_dev_pr_##_name =	\
 	__CONFIGFS_EATTR_RO(_name,					\
 	target_core_dev_pr_show_attr_##_name);
 
-/*
- * res_holder
- */
-static ssize_t target_core_dev_pr_show_spc3_res(
-	struct se_device *dev,
-	char *page,
-	ssize_t *len)
+static ssize_t target_core_dev_pr_show_spc3_res(struct se_device *dev,
+		char *page)
 {
 	struct se_node_acl *se_nacl;
 	struct t10_pr_registration *pr_reg;
@@ -1030,134 +983,82 @@ static ssize_t target_core_dev_pr_show_spc3_res(
 
 	memset(i_buf, 0, PR_REG_ISID_ID_LEN);
 
-	spin_lock(&dev->dev_reservation_lock);
 	pr_reg = dev->dev_pr_res_holder;
-	if (!pr_reg) {
-		*len += sprintf(page + *len, "No SPC-3 Reservation holder\n");
-		spin_unlock(&dev->dev_reservation_lock);
-		return *len;
-	}
+	if (!pr_reg)
+		return sprintf(page, "No SPC-3 Reservation holder\n");
+
 	se_nacl = pr_reg->pr_reg_nacl;
 	prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0],
 				PR_REG_ISID_ID_LEN);
 
-	*len += sprintf(page + *len, "SPC-3 Reservation: %s Initiator: %s%s\n",
+	return sprintf(page, "SPC-3 Reservation: %s Initiator: %s%s\n",
 		se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(),
 		se_nacl->initiatorname, (prf_isid) ? &i_buf[0] : "");
-	spin_unlock(&dev->dev_reservation_lock);
-
-	return *len;
 }
 
-static ssize_t target_core_dev_pr_show_spc2_res(
-	struct se_device *dev,
-	char *page,
-	ssize_t *len)
+static ssize_t target_core_dev_pr_show_spc2_res(struct se_device *dev,
+		char *page)
 {
 	struct se_node_acl *se_nacl;
+	ssize_t len;
 
-	spin_lock(&dev->dev_reservation_lock);
 	se_nacl = dev->dev_reserved_node_acl;
-	if (!se_nacl) {
-		*len += sprintf(page + *len, "No SPC-2 Reservation holder\n");
-		spin_unlock(&dev->dev_reservation_lock);
-		return *len;
+	if (se_nacl) {
+		len = sprintf(page,
+			      "SPC-2 Reservation: %s Initiator: %s\n",
+			      se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(),
+			      se_nacl->initiatorname);
+	} else {
+		len = sprintf(page, "No SPC-2 Reservation holder\n");
 	}
-	*len += sprintf(page + *len, "SPC-2 Reservation: %s Initiator: %s\n",
-		se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(),
-		se_nacl->initiatorname);
-	spin_unlock(&dev->dev_reservation_lock);
-
-	return *len;
+	return len;
 }
 
-static ssize_t target_core_dev_pr_show_attr_res_holder(
-	struct se_subsystem_dev *su_dev,
-	char *page)
+static ssize_t target_core_dev_pr_show_attr_res_holder(struct se_device *dev,
+		char *page)
 {
-	ssize_t len = 0;
+	int ret;
 
-	if (!su_dev->se_dev_ptr)
-		return -ENODEV;
-
-	switch (su_dev->t10_pr.res_type) {
-	case SPC3_PERSISTENT_RESERVATIONS:
-		target_core_dev_pr_show_spc3_res(su_dev->se_dev_ptr,
-				page, &len);
-		break;
-	case SPC2_RESERVATIONS:
-		target_core_dev_pr_show_spc2_res(su_dev->se_dev_ptr,
-				page, &len);
-		break;
-	case SPC_PASSTHROUGH:
-		len += sprintf(page+len, "Passthrough\n");
-		break;
-	default:
-		len += sprintf(page+len, "Unknown\n");
-		break;
-	}
+	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
+		return sprintf(page, "Passthrough\n");
 
-	return len;
+	spin_lock(&dev->dev_reservation_lock);
+	if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
+		ret = target_core_dev_pr_show_spc2_res(dev, page);
+	else
+		ret = target_core_dev_pr_show_spc3_res(dev, page);
+	spin_unlock(&dev->dev_reservation_lock);
+	return ret;
 }
 
 SE_DEV_PR_ATTR_RO(res_holder);
 
-/*
- * res_pr_all_tgt_pts
- */
 static ssize_t target_core_dev_pr_show_attr_res_pr_all_tgt_pts(
-	struct se_subsystem_dev *su_dev,
-	char *page)
+		struct se_device *dev, char *page)
 {
-	struct se_device *dev;
-	struct t10_pr_registration *pr_reg;
 	ssize_t len = 0;
 
-	dev = su_dev->se_dev_ptr;
-	if (!dev)
-		return -ENODEV;
-
-	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
-		return len;
-
 	spin_lock(&dev->dev_reservation_lock);
-	pr_reg = dev->dev_pr_res_holder;
-	if (!pr_reg) {
+	if (!dev->dev_pr_res_holder) {
 		len = sprintf(page, "No SPC-3 Reservation holder\n");
-		spin_unlock(&dev->dev_reservation_lock);
-		return len;
-	}
-	/*
-	 * See All Target Ports (ALL_TG_PT) bit in spcr17, section 6.14.3
-	 * Basic PERSISTENT RESERVER OUT parameter list, page 290
-	 */
-	if (pr_reg->pr_reg_all_tg_pt)
+	} else if (dev->dev_pr_res_holder->pr_reg_all_tg_pt) {
 		len = sprintf(page, "SPC-3 Reservation: All Target"
 			" Ports registration\n");
-	else
+	} else {
 		len = sprintf(page, "SPC-3 Reservation: Single"
 			" Target Port registration\n");
-	spin_unlock(&dev->dev_reservation_lock);
+	}
 
+	spin_unlock(&dev->dev_reservation_lock);
 	return len;
 }
 
 SE_DEV_PR_ATTR_RO(res_pr_all_tgt_pts);
 
-/*
- * res_pr_generation
- */
 static ssize_t target_core_dev_pr_show_attr_res_pr_generation(
-	struct se_subsystem_dev *su_dev,
-	char *page)
+		struct se_device *dev, char *page)
 {
-	if (!su_dev->se_dev_ptr)
-		return -ENODEV;
-
-	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
-		return 0;
-
-	return sprintf(page, "0x%08x\n", su_dev->t10_pr.pr_generation);
+	return sprintf(page, "0x%08x\n", dev->t10_pr.pr_generation);
 }
 
 SE_DEV_PR_ATTR_RO(res_pr_generation);
@@ -1166,10 +1067,8 @@ SE_DEV_PR_ATTR_RO(res_pr_generation);
  * res_pr_holder_tg_port
  */
 static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port(
-	struct se_subsystem_dev *su_dev,
-	char *page)
+		struct se_device *dev, char *page)
 {
-	struct se_device *dev;
 	struct se_node_acl *se_nacl;
 	struct se_lun *lun;
 	struct se_portal_group *se_tpg;
@@ -1177,20 +1076,13 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port(
 	struct target_core_fabric_ops *tfo;
 	ssize_t len = 0;
 
-	dev = su_dev->se_dev_ptr;
-	if (!dev)
-		return -ENODEV;
-
-	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
-		return len;
-
 	spin_lock(&dev->dev_reservation_lock);
 	pr_reg = dev->dev_pr_res_holder;
 	if (!pr_reg) {
 		len = sprintf(page, "No SPC-3 Reservation holder\n");
-		spin_unlock(&dev->dev_reservation_lock);
-		return len;
+		goto out_unlock;
 	}
+
 	se_nacl = pr_reg->pr_reg_nacl;
 	se_tpg = se_nacl->se_tpg;
 	lun = pr_reg->pr_reg_tg_pt_lun;
@@ -1204,19 +1096,16 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port(
 		" %s Logical Unit: %u\n", lun->lun_sep->sep_rtpi,
 		tfo->get_fabric_name(), tfo->tpg_get_tag(se_tpg),
 		tfo->get_fabric_name(), lun->unpacked_lun);
-	spin_unlock(&dev->dev_reservation_lock);
 
+out_unlock:
+	spin_unlock(&dev->dev_reservation_lock);
 	return len;
 }
 
 SE_DEV_PR_ATTR_RO(res_pr_holder_tg_port);
 
-/*
- * res_pr_registered_i_pts
- */
 static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts(
-	struct se_subsystem_dev *su_dev,
-	char *page)
+		struct se_device *dev, char *page)
 {
 	struct target_core_fabric_ops *tfo;
 	struct t10_pr_registration *pr_reg;
@@ -1225,16 +1114,10 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts(
 	ssize_t len = 0;
 	int reg_count = 0, prf_isid;
 
-	if (!su_dev->se_dev_ptr)
-		return -ENODEV;
-
-	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
-		return len;
-
 	len += sprintf(page+len, "SPC-3 PR Registrations:\n");
 
-	spin_lock(&su_dev->t10_pr.registration_lock);
-	list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list,
+	spin_lock(&dev->t10_pr.registration_lock);
+	list_for_each_entry(pr_reg, &dev->t10_pr.registration_list,
 			pr_reg_list) {
 
 		memset(buf, 0, 384);
@@ -1254,7 +1137,7 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts(
 		len += sprintf(page+len, "%s", buf);
 		reg_count++;
 	}
-	spin_unlock(&su_dev->t10_pr.registration_lock);
+	spin_unlock(&dev->t10_pr.registration_lock);
 
 	if (!reg_count)
 		len += sprintf(page+len, "None\n");
@@ -1264,88 +1147,48 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts(
 
 SE_DEV_PR_ATTR_RO(res_pr_registered_i_pts);
 
-/*
- * res_pr_type
- */
 static ssize_t target_core_dev_pr_show_attr_res_pr_type(
-	struct se_subsystem_dev *su_dev,
-	char *page)
+		struct se_device *dev, char *page)
 {
-	struct se_device *dev;
 	struct t10_pr_registration *pr_reg;
 	ssize_t len = 0;
 
-	dev = su_dev->se_dev_ptr;
-	if (!dev)
-		return -ENODEV;
-
-	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
-		return len;
-
 	spin_lock(&dev->dev_reservation_lock);
 	pr_reg = dev->dev_pr_res_holder;
-	if (!pr_reg) {
+	if (pr_reg) {
+		len = sprintf(page, "SPC-3 Reservation Type: %s\n",
+			core_scsi3_pr_dump_type(pr_reg->pr_res_type));
+	} else {
 		len = sprintf(page, "No SPC-3 Reservation holder\n");
-		spin_unlock(&dev->dev_reservation_lock);
-		return len;
 	}
-	len = sprintf(page, "SPC-3 Reservation Type: %s\n",
-		core_scsi3_pr_dump_type(pr_reg->pr_res_type));
-	spin_unlock(&dev->dev_reservation_lock);
 
+	spin_unlock(&dev->dev_reservation_lock);
 	return len;
 }
 
 SE_DEV_PR_ATTR_RO(res_pr_type);
 
-/*
- * res_type
- */
 static ssize_t target_core_dev_pr_show_attr_res_type(
-	struct se_subsystem_dev *su_dev,
-	char *page)
+		struct se_device *dev, char *page)
 {
-	ssize_t len = 0;
-
-	if (!su_dev->se_dev_ptr)
-		return -ENODEV;
-
-	switch (su_dev->t10_pr.res_type) {
-	case SPC3_PERSISTENT_RESERVATIONS:
-		len = sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n");
-		break;
-	case SPC2_RESERVATIONS:
-		len = sprintf(page, "SPC2_RESERVATIONS\n");
-		break;
-	case SPC_PASSTHROUGH:
-		len = sprintf(page, "SPC_PASSTHROUGH\n");
-		break;
-	default:
-		len = sprintf(page, "UNKNOWN\n");
-		break;
-	}
-
-	return len;
+	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
+		return sprintf(page, "SPC_PASSTHROUGH\n");
+	else if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
+		return sprintf(page, "SPC2_RESERVATIONS\n");
+	else
+		return sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n");
 }
 
 SE_DEV_PR_ATTR_RO(res_type);
 
-/*
- * res_aptpl_active
- */
-
 static ssize_t target_core_dev_pr_show_attr_res_aptpl_active(
-	struct se_subsystem_dev *su_dev,
-	char *page)
+		struct se_device *dev, char *page)
 {
-	if (!su_dev->se_dev_ptr)
-		return -ENODEV;
-
-	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
+	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
 		return 0;
 
 	return sprintf(page, "APTPL Bit Status: %s\n",
-		(su_dev->t10_pr.pr_aptpl_active) ? "Activated" : "Disabled");
+		(dev->t10_pr.pr_aptpl_active) ? "Activated" : "Disabled");
 }
 
 SE_DEV_PR_ATTR_RO(res_aptpl_active);
@@ -1354,13 +1197,9 @@ SE_DEV_PR_ATTR_RO(res_aptpl_active);
  * res_aptpl_metadata
  */
 static ssize_t target_core_dev_pr_show_attr_res_aptpl_metadata(
-	struct se_subsystem_dev *su_dev,
-	char *page)
+		struct se_device *dev, char *page)
 {
-	if (!su_dev->se_dev_ptr)
-		return -ENODEV;
-
-	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
+	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
 		return 0;
 
 	return sprintf(page, "Ready to process PR APTPL metadata..\n");
@@ -1392,11 +1231,10 @@ static match_table_t tokens = {
 };
 
 static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
-	struct se_subsystem_dev *su_dev,
+	struct se_device *dev,
 	const char *page,
 	size_t count)
 {
-	struct se_device *dev;
 	unsigned char *i_fabric = NULL, *i_port = NULL, *isid = NULL;
 	unsigned char *t_fabric = NULL, *t_port = NULL;
 	char *orig, *ptr, *arg_p, *opts;
@@ -1408,14 +1246,12 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
 	u16 port_rpti = 0, tpgt = 0;
 	u8 type = 0, scope;
 
-	dev = su_dev->se_dev_ptr;
-	if (!dev)
-		return -ENODEV;
-
-	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
+	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
+		return 0;
+	if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
 		return 0;
 
-	if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
+	if (dev->export_count) {
 		pr_debug("Unable to process APTPL metadata while"
 			" active fabric exports exist\n");
 		return -EINVAL;
@@ -1558,7 +1394,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
 		goto out;
 	}
 
-	ret = core_scsi3_alloc_aptpl_registration(&su_dev->t10_pr, sa_res_key,
+	ret = core_scsi3_alloc_aptpl_registration(&dev->t10_pr, sa_res_key,
 			i_port, isid, mapped_lun, t_port, tpgt, target_lun,
 			res_holder, all_tg_pt, type);
 out:
@@ -1573,7 +1409,7 @@ out:
 
 SE_DEV_PR_ATTR(res_aptpl_metadata, S_IRUGO | S_IWUSR);
 
-CONFIGFS_EATTR_OPS(target_core_dev_pr, se_subsystem_dev, se_dev_pr_group);
+CONFIGFS_EATTR_OPS(target_core_dev_pr, se_device, dev_pr_group);
 
 static struct configfs_attribute *target_core_dev_pr_attrs[] = {
 	&target_core_dev_pr_res_holder.attr,
@@ -1605,18 +1441,14 @@ static struct config_item_type target_core_dev_pr_cit = {
 
 static ssize_t target_core_show_dev_info(void *p, char *page)
 {
-	struct se_subsystem_dev *se_dev = p;
-	struct se_hba *hba = se_dev->se_dev_hba;
-	struct se_subsystem_api *t = hba->transport;
+	struct se_device *dev = p;
+	struct se_subsystem_api *t = dev->transport;
 	int bl = 0;
 	ssize_t read_bytes = 0;
 
-	if (!se_dev->se_dev_ptr)
-		return -ENODEV;
-
-	transport_dump_dev_state(se_dev->se_dev_ptr, page, &bl);
+	transport_dump_dev_state(dev, page, &bl);
 	read_bytes += bl;
-	read_bytes += t->show_configfs_dev_params(hba, se_dev, page+read_bytes);
+	read_bytes += t->show_configfs_dev_params(dev, page+read_bytes);
 	return read_bytes;
 }
 
@@ -1633,17 +1465,10 @@ static ssize_t target_core_store_dev_control(
 	const char *page,
 	size_t count)
 {
-	struct se_subsystem_dev *se_dev = p;
-	struct se_hba *hba = se_dev->se_dev_hba;
-	struct se_subsystem_api *t = hba->transport;
+	struct se_device *dev = p;
+	struct se_subsystem_api *t = dev->transport;
 
-	if (!se_dev->se_dev_su_ptr) {
-		pr_err("Unable to locate struct se_subsystem_dev>se"
-				"_dev_su_ptr\n");
-		return -EINVAL;
-	}
-
-	return t->set_configfs_dev_params(hba, se_dev, page, count);
+	return t->set_configfs_dev_params(dev, page, count);
 }
 
 static struct target_core_configfs_attribute target_core_attr_dev_control = {
@@ -1656,12 +1481,12 @@ static struct target_core_configfs_attribute target_core_attr_dev_control = {
 
 static ssize_t target_core_show_dev_alias(void *p, char *page)
 {
-	struct se_subsystem_dev *se_dev = p;
+	struct se_device *dev = p;
 
-	if (!(se_dev->su_dev_flags & SDF_USING_ALIAS))
+	if (!(dev->dev_flags & DF_USING_ALIAS))
 		return 0;
 
-	return snprintf(page, PAGE_SIZE, "%s\n", se_dev->se_dev_alias);
+	return snprintf(page, PAGE_SIZE, "%s\n", dev->dev_alias);
 }
 
 static ssize_t target_core_store_dev_alias(
@@ -1669,8 +1494,8 @@ static ssize_t target_core_store_dev_alias(
 	const char *page,
 	size_t count)
 {
-	struct se_subsystem_dev *se_dev = p;
-	struct se_hba *hba = se_dev->se_dev_hba;
+	struct se_device *dev = p;
+	struct se_hba *hba = dev->se_hba;
 	ssize_t read_bytes;
 
 	if (count > (SE_DEV_ALIAS_LEN-1)) {
@@ -1680,19 +1505,18 @@ static ssize_t target_core_store_dev_alias(
 		return -EINVAL;
 	}
 
-	read_bytes = snprintf(&se_dev->se_dev_alias[0], SE_DEV_ALIAS_LEN,
-			"%s", page);
+	read_bytes = snprintf(&dev->dev_alias[0], SE_DEV_ALIAS_LEN, "%s", page);
 	if (!read_bytes)
 		return -EINVAL;
-	if (se_dev->se_dev_alias[read_bytes - 1] == '\n')
-		se_dev->se_dev_alias[read_bytes - 1] = '\0';
+	if (dev->dev_alias[read_bytes - 1] == '\n')
+		dev->dev_alias[read_bytes - 1] = '\0';
 
-	se_dev->su_dev_flags |= SDF_USING_ALIAS;
+	dev->dev_flags |= DF_USING_ALIAS;
 
 	pr_debug("Target_Core_ConfigFS: %s/%s set alias: %s\n",
 		config_item_name(&hba->hba_group.cg_item),
-		config_item_name(&se_dev->se_dev_group.cg_item),
-		se_dev->se_dev_alias);
+		config_item_name(&dev->dev_group.cg_item),
+		dev->dev_alias);
 
 	return read_bytes;
 }
@@ -1707,12 +1531,12 @@ static struct target_core_configfs_attribute target_core_attr_dev_alias = {
 
 static ssize_t target_core_show_dev_udev_path(void *p, char *page)
 {
-	struct se_subsystem_dev *se_dev = p;
+	struct se_device *dev = p;
 
-	if (!(se_dev->su_dev_flags & SDF_USING_UDEV_PATH))
+	if (!(dev->dev_flags & DF_USING_UDEV_PATH))
 		return 0;
 
-	return snprintf(page, PAGE_SIZE, "%s\n", se_dev->se_dev_udev_path);
+	return snprintf(page, PAGE_SIZE, "%s\n", dev->udev_path);
 }
 
 static ssize_t target_core_store_dev_udev_path(
@@ -1720,8 +1544,8 @@ static ssize_t target_core_store_dev_udev_path(
 	const char *page,
 	size_t count)
 {
-	struct se_subsystem_dev *se_dev = p;
-	struct se_hba *hba = se_dev->se_dev_hba;
+	struct se_device *dev = p;
+	struct se_hba *hba = dev->se_hba;
 	ssize_t read_bytes;
 
 	if (count > (SE_UDEV_PATH_LEN-1)) {
@@ -1731,19 +1555,19 @@ static ssize_t target_core_store_dev_udev_path(
 		return -EINVAL;
 	}
 
-	read_bytes = snprintf(&se_dev->se_dev_udev_path[0], SE_UDEV_PATH_LEN,
+	read_bytes = snprintf(&dev->udev_path[0], SE_UDEV_PATH_LEN,
 			"%s", page);
 	if (!read_bytes)
 		return -EINVAL;
-	if (se_dev->se_dev_udev_path[read_bytes - 1] == '\n')
-		se_dev->se_dev_udev_path[read_bytes - 1] = '\0';
+	if (dev->udev_path[read_bytes - 1] == '\n')
+		dev->udev_path[read_bytes - 1] = '\0';
 
-	se_dev->su_dev_flags |= SDF_USING_UDEV_PATH;
+	dev->dev_flags |= DF_USING_UDEV_PATH;
 
 	pr_debug("Target_Core_ConfigFS: %s/%s set udev_path: %s\n",
 		config_item_name(&hba->hba_group.cg_item),
-		config_item_name(&se_dev->se_dev_group.cg_item),
-		se_dev->se_dev_udev_path);
+		config_item_name(&dev->dev_group.cg_item),
+		dev->udev_path);
 
 	return read_bytes;
 }
@@ -1761,11 +1585,9 @@ static ssize_t target_core_store_dev_enable(
 	const char *page,
 	size_t count)
 {
-	struct se_subsystem_dev *se_dev = p;
-	struct se_device *dev;
-	struct se_hba *hba = se_dev->se_dev_hba;
-	struct se_subsystem_api *t = hba->transport;
+	struct se_device *dev = p;
 	char *ptr;
+	int ret;
 
 	ptr = strstr(page, "1");
 	if (!ptr) {
@@ -1773,25 +1595,10 @@ static ssize_t target_core_store_dev_enable(
 				" is \"1\"\n");
 		return -EINVAL;
 	}
-	if (se_dev->se_dev_ptr) {
-		pr_err("se_dev->se_dev_ptr already set for storage"
-				" object\n");
-		return -EEXIST;
-	}
-
-	if (t->check_configfs_dev_params(hba, se_dev) < 0)
-		return -EINVAL;
-
-	dev = t->create_virtdevice(hba, se_dev, se_dev->se_dev_su_ptr);
-	if (IS_ERR(dev))
-		return PTR_ERR(dev);
-	else if (!dev)
-		return -EINVAL;
-
-	se_dev->se_dev_ptr = dev;
-	pr_debug("Target_Core_ConfigFS: Registered se_dev->se_dev_ptr:"
-		" %p\n", se_dev->se_dev_ptr);
 
+	ret = target_configure_device(dev);
+	if (ret)
+		return ret;
 	return count;
 }
 
@@ -1805,26 +1612,15 @@ static struct target_core_configfs_attribute target_core_attr_dev_enable = {
 
 static ssize_t target_core_show_alua_lu_gp(void *p, char *page)
 {
-	struct se_device *dev;
-	struct se_subsystem_dev *su_dev = p;
+	struct se_device *dev = p;
 	struct config_item *lu_ci;
 	struct t10_alua_lu_gp *lu_gp;
 	struct t10_alua_lu_gp_member *lu_gp_mem;
 	ssize_t len = 0;
 
-	dev = su_dev->se_dev_ptr;
-	if (!dev)
-		return -ENODEV;
-
-	if (su_dev->t10_alua.alua_type != SPC3_ALUA_EMULATED)
-		return len;
-
 	lu_gp_mem = dev->dev_alua_lu_gp_mem;
-	if (!lu_gp_mem) {
-		pr_err("NULL struct se_device->dev_alua_lu_gp_mem"
-				" pointer\n");
-		return -EINVAL;
-	}
+	if (!lu_gp_mem)
+		return 0;
 
 	spin_lock(&lu_gp_mem->lu_gp_mem_lock);
 	lu_gp = lu_gp_mem->lu_gp;
@@ -1843,24 +1639,17 @@ static ssize_t target_core_store_alua_lu_gp(
 	const char *page,
 	size_t count)
 {
-	struct se_device *dev;
-	struct se_subsystem_dev *su_dev = p;
-	struct se_hba *hba = su_dev->se_dev_hba;
+	struct se_device *dev = p;
+	struct se_hba *hba = dev->se_hba;
 	struct t10_alua_lu_gp *lu_gp = NULL, *lu_gp_new = NULL;
 	struct t10_alua_lu_gp_member *lu_gp_mem;
 	unsigned char buf[LU_GROUP_NAME_BUF];
 	int move = 0;
 
-	dev = su_dev->se_dev_ptr;
-	if (!dev)
-		return -ENODEV;
+	lu_gp_mem = dev->dev_alua_lu_gp_mem;
+	if (!lu_gp_mem)
+		return 0;
 
-	if (su_dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) {
-		pr_warn("SPC3_ALUA_EMULATED not enabled for %s/%s\n",
-			config_item_name(&hba->hba_group.cg_item),
-			config_item_name(&su_dev->se_dev_group.cg_item));
-		return -EINVAL;
-	}
 	if (count > LU_GROUP_NAME_BUF) {
 		pr_err("ALUA LU Group Alias too large!\n");
 		return -EINVAL;
@@ -1881,14 +1670,6 @@ static ssize_t target_core_store_alua_lu_gp(
 		if (!lu_gp_new)
 			return -ENODEV;
 	}
-	lu_gp_mem = dev->dev_alua_lu_gp_mem;
-	if (!lu_gp_mem) {
-		if (lu_gp_new)
-			core_alua_put_lu_gp_from_name(lu_gp_new);
-		pr_err("NULL struct se_device->dev_alua_lu_gp_mem"
-				" pointer\n");
-		return -EINVAL;
-	}
 
 	spin_lock(&lu_gp_mem->lu_gp_mem_lock);
 	lu_gp = lu_gp_mem->lu_gp;
@@ -1902,7 +1683,7 @@ static ssize_t target_core_store_alua_lu_gp(
 				" from ALUA LU Group: core/alua/lu_gps/%s, ID:"
 				" %hu\n",
 				config_item_name(&hba->hba_group.cg_item),
-				config_item_name(&su_dev->se_dev_group.cg_item),
+				config_item_name(&dev->dev_group.cg_item),
 				config_item_name(&lu_gp->lu_gp_group.cg_item),
 				lu_gp->lu_gp_id);
 
@@ -1927,7 +1708,7 @@ static ssize_t target_core_store_alua_lu_gp(
 		" core/alua/lu_gps/%s, ID: %hu\n",
 		(move) ? "Moving" : "Adding",
 		config_item_name(&hba->hba_group.cg_item),
-		config_item_name(&su_dev->se_dev_group.cg_item),
+		config_item_name(&dev->dev_group.cg_item),
 		config_item_name(&lu_gp_new->lu_gp_group.cg_item),
 		lu_gp_new->lu_gp_id);
 
@@ -1955,69 +1736,44 @@ static struct configfs_attribute *lio_core_dev_attrs[] = {
 
 static void target_core_dev_release(struct config_item *item)
 {
-	struct se_subsystem_dev *se_dev = container_of(to_config_group(item),
-				struct se_subsystem_dev, se_dev_group);
-	struct se_hba *hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item);
-	struct se_subsystem_api *t = hba->transport;
-	struct config_group *dev_cg = &se_dev->se_dev_group;
+	struct config_group *dev_cg = to_config_group(item);
+	struct se_device *dev =
+		container_of(dev_cg, struct se_device, dev_group);
 
 	kfree(dev_cg->default_groups);
-	/*
-	 * This pointer will set when the storage is enabled with:
-	 *`echo 1 > $CONFIGFS/core/$HBA/$DEV/dev_enable`
-	 */
-	if (se_dev->se_dev_ptr) {
-		pr_debug("Target_Core_ConfigFS: Calling se_free_"
-			"virtual_device() for se_dev_ptr: %p\n",
-			se_dev->se_dev_ptr);
-
-		se_free_virtual_device(se_dev->se_dev_ptr, hba);
-	} else {
-		/*
-		 * Release struct se_subsystem_dev->se_dev_su_ptr..
-		 */
-		pr_debug("Target_Core_ConfigFS: Calling t->free_"
-			"device() for se_dev_su_ptr: %p\n",
-			se_dev->se_dev_su_ptr);
-
-		t->free_device(se_dev->se_dev_su_ptr);
-	}
-
-	pr_debug("Target_Core_ConfigFS: Deallocating se_subsystem"
-			"_dev_t: %p\n", se_dev);
-	kfree(se_dev);
+	target_free_device(dev);
 }
 
 static ssize_t target_core_dev_show(struct config_item *item,
 				     struct configfs_attribute *attr,
 				     char *page)
 {
-	struct se_subsystem_dev *se_dev = container_of(
-			to_config_group(item), struct se_subsystem_dev,
-			se_dev_group);
+	struct config_group *dev_cg = to_config_group(item);
+	struct se_device *dev =
+		container_of(dev_cg, struct se_device, dev_group);
 	struct target_core_configfs_attribute *tc_attr = container_of(
 			attr, struct target_core_configfs_attribute, attr);
 
 	if (!tc_attr->show)
 		return -EINVAL;
 
-	return tc_attr->show(se_dev, page);
+	return tc_attr->show(dev, page);
 }
 
 static ssize_t target_core_dev_store(struct config_item *item,
 				      struct configfs_attribute *attr,
 				      const char *page, size_t count)
 {
-	struct se_subsystem_dev *se_dev = container_of(
-			to_config_group(item), struct se_subsystem_dev,
-			se_dev_group);
+	struct config_group *dev_cg = to_config_group(item);
+	struct se_device *dev =
+		container_of(dev_cg, struct se_device, dev_group);
 	struct target_core_configfs_attribute *tc_attr = container_of(
 			attr, struct target_core_configfs_attribute, attr);
 
 	if (!tc_attr->store)
 		return -EINVAL;
 
-	return tc_attr->store(se_dev, page, count);
+	return tc_attr->store(dev, page, count);
 }
 
 static struct configfs_item_operations target_core_dev_item_ops = {
@@ -2107,7 +1863,6 @@ static ssize_t target_core_alua_lu_gp_show_attr_members(
 {
 	struct se_device *dev;
 	struct se_hba *hba;
-	struct se_subsystem_dev *su_dev;
 	struct t10_alua_lu_gp_member *lu_gp_mem;
 	ssize_t len = 0, cur_len;
 	unsigned char buf[LU_GROUP_NAME_BUF];
@@ -2117,12 +1872,11 @@ static ssize_t target_core_alua_lu_gp_show_attr_members(
 	spin_lock(&lu_gp->lu_gp_lock);
 	list_for_each_entry(lu_gp_mem, &lu_gp->lu_gp_mem_list, lu_gp_mem_list) {
 		dev = lu_gp_mem->lu_gp_mem_dev;
-		su_dev = dev->se_sub_dev;
-		hba = su_dev->se_dev_hba;
+		hba = dev->se_hba;
 
 		cur_len = snprintf(buf, LU_GROUP_NAME_BUF, "%s/%s\n",
 			config_item_name(&hba->hba_group.cg_item),
-			config_item_name(&su_dev->se_dev_group.cg_item));
+			config_item_name(&dev->dev_group.cg_item));
 		cur_len++; /* Extra byte for NULL terminator */
 
 		if ((cur_len + len) > PAGE_SIZE) {
@@ -2260,7 +2014,7 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state(
 	const char *page,
 	size_t count)
 {
-	struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev;
+	struct se_device *dev = tg_pt_gp->tg_pt_gp_dev;
 	unsigned long tmp;
 	int new_state, ret;
 
@@ -2284,7 +2038,7 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state(
 		return -EINVAL;
 	}
 
-	ret = core_alua_do_port_transition(tg_pt_gp, su_dev->se_dev_ptr,
+	ret = core_alua_do_port_transition(tg_pt_gp, dev,
 					NULL, NULL, new_state, 0);
 	return (!ret) ? count : -EINVAL;
 }
@@ -2620,11 +2374,10 @@ static struct config_group *target_core_alua_create_tg_pt_gp(
 	struct t10_alua *alua = container_of(group, struct t10_alua,
 					alua_tg_pt_gps_group);
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
-	struct se_subsystem_dev *su_dev = alua->t10_sub_dev;
 	struct config_group *alua_tg_pt_gp_cg = NULL;
 	struct config_item *alua_tg_pt_gp_ci = NULL;
 
-	tg_pt_gp = core_alua_allocate_tg_pt_gp(su_dev, name, 0);
+	tg_pt_gp = core_alua_allocate_tg_pt_gp(alua->t10_dev, name, 0);
 	if (!tg_pt_gp)
 		return NULL;
 
@@ -2721,10 +2474,10 @@ static struct config_group *target_core_make_subdev(
 	const char *name)
 {
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
-	struct se_subsystem_dev *se_dev;
 	struct se_subsystem_api *t;
 	struct config_item *hba_ci = &group->cg_item;
 	struct se_hba *hba = item_to_hba(hba_ci);
+	struct se_device *dev;
 	struct config_group *dev_cg = NULL, *tg_pt_gp_cg = NULL;
 	struct config_group *dev_stat_grp = NULL;
 	int errno = -ENOMEM, ret;
@@ -2737,120 +2490,80 @@ static struct config_group *target_core_make_subdev(
 	 */
 	t = hba->transport;
 
-	se_dev = kzalloc(sizeof(struct se_subsystem_dev), GFP_KERNEL);
-	if (!se_dev) {
-		pr_err("Unable to allocate memory for"
-				" struct se_subsystem_dev\n");
-		goto unlock;
-	}
-	INIT_LIST_HEAD(&se_dev->t10_wwn.t10_vpd_list);
-	spin_lock_init(&se_dev->t10_wwn.t10_vpd_lock);
-	INIT_LIST_HEAD(&se_dev->t10_pr.registration_list);
-	INIT_LIST_HEAD(&se_dev->t10_pr.aptpl_reg_list);
-	spin_lock_init(&se_dev->t10_pr.registration_lock);
-	spin_lock_init(&se_dev->t10_pr.aptpl_reg_lock);
-	INIT_LIST_HEAD(&se_dev->t10_alua.tg_pt_gps_list);
-	spin_lock_init(&se_dev->t10_alua.tg_pt_gps_lock);
-	spin_lock_init(&se_dev->se_dev_lock);
-	se_dev->t10_pr.pr_aptpl_buf_len = PR_APTPL_BUF_LEN;
-	se_dev->t10_wwn.t10_sub_dev = se_dev;
-	se_dev->t10_alua.t10_sub_dev = se_dev;
-	se_dev->se_dev_attrib.da_sub_dev = se_dev;
-
-	se_dev->se_dev_hba = hba;
-	dev_cg = &se_dev->se_dev_group;
-
-	dev_cg->default_groups = kzalloc(sizeof(struct config_group) * 7,
+	dev = target_alloc_device(hba, name);
+	if (!dev)
+		goto out_unlock;
+
+	dev_cg = &dev->dev_group;
+
+	dev_cg->default_groups = kmalloc(sizeof(struct config_group *) * 6,
 			GFP_KERNEL);
 	if (!dev_cg->default_groups)
-		goto out;
-	/*
-	 * Set se_dev_su_ptr from struct se_subsystem_api returned void ptr
-	 * for ->allocate_virtdevice()
-	 *
-	 * se_dev->se_dev_ptr will be set after ->create_virtdev()
-	 * has been called successfully in the next level up in the
-	 * configfs tree for device object's struct config_group.
-	 */
-	se_dev->se_dev_su_ptr = t->allocate_virtdevice(hba, name);
-	if (!se_dev->se_dev_su_ptr) {
-		pr_err("Unable to locate subsystem dependent pointer"
-			" from allocate_virtdevice()\n");
-		goto out;
-	}
+		goto out_free_device;
 
-	config_group_init_type_name(&se_dev->se_dev_group, name,
-			&target_core_dev_cit);
-	config_group_init_type_name(&se_dev->se_dev_attrib.da_group, "attrib",
+	config_group_init_type_name(dev_cg, name, &target_core_dev_cit);
+	config_group_init_type_name(&dev->dev_attrib.da_group, "attrib",
 			&target_core_dev_attrib_cit);
-	config_group_init_type_name(&se_dev->se_dev_pr_group, "pr",
+	config_group_init_type_name(&dev->dev_pr_group, "pr",
 			&target_core_dev_pr_cit);
-	config_group_init_type_name(&se_dev->t10_wwn.t10_wwn_group, "wwn",
+	config_group_init_type_name(&dev->t10_wwn.t10_wwn_group, "wwn",
 			&target_core_dev_wwn_cit);
-	config_group_init_type_name(&se_dev->t10_alua.alua_tg_pt_gps_group,
+	config_group_init_type_name(&dev->t10_alua.alua_tg_pt_gps_group,
 			"alua", &target_core_alua_tg_pt_gps_cit);
-	config_group_init_type_name(&se_dev->dev_stat_grps.stat_group,
+	config_group_init_type_name(&dev->dev_stat_grps.stat_group,
 			"statistics", &target_core_stat_cit);
 
-	dev_cg->default_groups[0] = &se_dev->se_dev_attrib.da_group;
-	dev_cg->default_groups[1] = &se_dev->se_dev_pr_group;
-	dev_cg->default_groups[2] = &se_dev->t10_wwn.t10_wwn_group;
-	dev_cg->default_groups[3] = &se_dev->t10_alua.alua_tg_pt_gps_group;
-	dev_cg->default_groups[4] = &se_dev->dev_stat_grps.stat_group;
+	dev_cg->default_groups[0] = &dev->dev_attrib.da_group;
+	dev_cg->default_groups[1] = &dev->dev_pr_group;
+	dev_cg->default_groups[2] = &dev->t10_wwn.t10_wwn_group;
+	dev_cg->default_groups[3] = &dev->t10_alua.alua_tg_pt_gps_group;
+	dev_cg->default_groups[4] = &dev->dev_stat_grps.stat_group;
 	dev_cg->default_groups[5] = NULL;
 	/*
 	 * Add core/$HBA/$DEV/alua/default_tg_pt_gp
 	 */
-	tg_pt_gp = core_alua_allocate_tg_pt_gp(se_dev, "default_tg_pt_gp", 1);
+	tg_pt_gp = core_alua_allocate_tg_pt_gp(dev, "default_tg_pt_gp", 1);
 	if (!tg_pt_gp)
-		goto out;
+		goto out_free_dev_cg_default_groups;
+	dev->t10_alua.default_tg_pt_gp = tg_pt_gp;
 
-	tg_pt_gp_cg = &se_dev->t10_alua.alua_tg_pt_gps_group;
-	tg_pt_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
+	tg_pt_gp_cg = &dev->t10_alua.alua_tg_pt_gps_group;
+	tg_pt_gp_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2,
 				GFP_KERNEL);
 	if (!tg_pt_gp_cg->default_groups) {
 		pr_err("Unable to allocate tg_pt_gp_cg->"
 				"default_groups\n");
-		goto out;
+		goto out_free_tg_pt_gp;
 	}
 
 	config_group_init_type_name(&tg_pt_gp->tg_pt_gp_group,
 			"default_tg_pt_gp", &target_core_alua_tg_pt_gp_cit);
 	tg_pt_gp_cg->default_groups[0] = &tg_pt_gp->tg_pt_gp_group;
 	tg_pt_gp_cg->default_groups[1] = NULL;
-	se_dev->t10_alua.default_tg_pt_gp = tg_pt_gp;
 	/*
 	 * Add core/$HBA/$DEV/statistics/ default groups
 	 */
-	dev_stat_grp = &se_dev->dev_stat_grps.stat_group;
-	dev_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 4,
+	dev_stat_grp = &dev->dev_stat_grps.stat_group;
+	dev_stat_grp->default_groups = kmalloc(sizeof(struct config_group *) * 4,
 				GFP_KERNEL);
 	if (!dev_stat_grp->default_groups) {
 		pr_err("Unable to allocate dev_stat_grp->default_groups\n");
-		goto out;
+		goto out_free_tg_pt_gp_cg_default_groups;
 	}
-	target_stat_setup_dev_default_groups(se_dev);
-
-	pr_debug("Target_Core_ConfigFS: Allocated struct se_subsystem_dev:"
-		" %p se_dev_su_ptr: %p\n", se_dev, se_dev->se_dev_su_ptr);
+	target_stat_setup_dev_default_groups(dev);
 
 	mutex_unlock(&hba->hba_access_mutex);
-	return &se_dev->se_dev_group;
-out:
-	if (se_dev->t10_alua.default_tg_pt_gp) {
-		core_alua_free_tg_pt_gp(se_dev->t10_alua.default_tg_pt_gp);
-		se_dev->t10_alua.default_tg_pt_gp = NULL;
-	}
-	if (dev_stat_grp)
-		kfree(dev_stat_grp->default_groups);
-	if (tg_pt_gp_cg)
-		kfree(tg_pt_gp_cg->default_groups);
-	if (dev_cg)
-		kfree(dev_cg->default_groups);
-	if (se_dev->se_dev_su_ptr)
-		t->free_device(se_dev->se_dev_su_ptr);
-	kfree(se_dev);
-unlock:
+	return dev_cg;
+
+out_free_tg_pt_gp_cg_default_groups:
+	kfree(tg_pt_gp_cg->default_groups);
+out_free_tg_pt_gp:
+	core_alua_free_tg_pt_gp(tg_pt_gp);
+out_free_dev_cg_default_groups:
+	kfree(dev_cg->default_groups);
+out_free_device:
+	target_free_device(dev);
+out_unlock:
 	mutex_unlock(&hba->hba_access_mutex);
 	return ERR_PTR(errno);
 }
@@ -2859,18 +2572,19 @@ static void target_core_drop_subdev(
 	struct config_group *group,
 	struct config_item *item)
 {
-	struct se_subsystem_dev *se_dev = container_of(to_config_group(item),
-				struct se_subsystem_dev, se_dev_group);
+	struct config_group *dev_cg = to_config_group(item);
+	struct se_device *dev =
+		container_of(dev_cg, struct se_device, dev_group);
 	struct se_hba *hba;
 	struct config_item *df_item;
-	struct config_group *dev_cg, *tg_pt_gp_cg, *dev_stat_grp;
+	struct config_group *tg_pt_gp_cg, *dev_stat_grp;
 	int i;
 
-	hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item);
+	hba = item_to_hba(&dev->se_hba->hba_group.cg_item);
 
 	mutex_lock(&hba->hba_access_mutex);
 
-	dev_stat_grp = &se_dev->dev_stat_grps.stat_group;
+	dev_stat_grp = &dev->dev_stat_grps.stat_group;
 	for (i = 0; dev_stat_grp->default_groups[i]; i++) {
 		df_item = &dev_stat_grp->default_groups[i]->cg_item;
 		dev_stat_grp->default_groups[i] = NULL;
@@ -2878,7 +2592,7 @@ static void target_core_drop_subdev(
 	}
 	kfree(dev_stat_grp->default_groups);
 
-	tg_pt_gp_cg = &se_dev->t10_alua.alua_tg_pt_gps_group;
+	tg_pt_gp_cg = &dev->t10_alua.alua_tg_pt_gps_group;
 	for (i = 0; tg_pt_gp_cg->default_groups[i]; i++) {
 		df_item = &tg_pt_gp_cg->default_groups[i]->cg_item;
 		tg_pt_gp_cg->default_groups[i] = NULL;
@@ -2889,17 +2603,15 @@ static void target_core_drop_subdev(
 	 * core_alua_free_tg_pt_gp() is called from ->default_tg_pt_gp
 	 * directly from target_core_alua_tg_pt_gp_release().
 	 */
-	se_dev->t10_alua.default_tg_pt_gp = NULL;
+	dev->t10_alua.default_tg_pt_gp = NULL;
 
-	dev_cg = &se_dev->se_dev_group;
 	for (i = 0; dev_cg->default_groups[i]; i++) {
 		df_item = &dev_cg->default_groups[i]->cg_item;
 		dev_cg->default_groups[i] = NULL;
 		config_item_put(df_item);
 	}
 	/*
-	 * The releasing of se_dev and associated se_dev->se_dev_ptr is done
-	 * from target_core_dev_item_ops->release() ->target_core_dev_release().
+	 * se_dev is released from target_core_dev_item_ops->release()
 	 */
 	config_item_put(item);
 	mutex_unlock(&hba->hba_access_mutex);
@@ -2962,13 +2674,10 @@ static ssize_t target_core_hba_store_attr_hba_mode(struct se_hba *hba,
 		return -EINVAL;
 	}
 
-	spin_lock(&hba->device_lock);
-	if (!list_empty(&hba->hba_dev_list)) {
+	if (hba->dev_count) {
 		pr_err("Unable to set hba_mode with active devices\n");
-		spin_unlock(&hba->device_lock);
 		return -EINVAL;
 	}
-	spin_unlock(&hba->device_lock);
 
 	ret = transport->pmode_enable_hba(hba, mode_flag);
 	if (ret < 0)
@@ -3120,7 +2829,7 @@ static int __init target_core_init_configfs(void)
 	 * and ALUA Logical Unit Group and Target Port Group infrastructure.
 	 */
 	target_cg = &subsys->su_group;
-	target_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
+	target_cg->default_groups = kmalloc(sizeof(struct config_group) * 2,
 				GFP_KERNEL);
 	if (!target_cg->default_groups) {
 		pr_err("Unable to allocate target_cg->default_groups\n");
@@ -3136,7 +2845,7 @@ static int __init target_core_init_configfs(void)
 	 * Create ALUA infrastructure under /sys/kernel/config/target/core/alua/
 	 */
 	hba_cg = &target_core_hbagroup;
-	hba_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
+	hba_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2,
 				GFP_KERNEL);
 	if (!hba_cg->default_groups) {
 		pr_err("Unable to allocate hba_cg->default_groups\n");
@@ -3152,7 +2861,7 @@ static int __init target_core_init_configfs(void)
 	 * groups under /sys/kernel/config/target/core/alua/
 	 */
 	alua_cg = &alua_group;
-	alua_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
+	alua_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2,
 			GFP_KERNEL);
 	if (!alua_cg->default_groups) {
 		pr_err("Unable to allocate alua_cg->default_groups\n");
@@ -3174,7 +2883,7 @@ static int __init target_core_init_configfs(void)
 	}
 
 	lu_gp_cg = &alua_lu_gps_group;
-	lu_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
+	lu_gp_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2,
 			GFP_KERNEL);
 	if (!lu_gp_cg->default_groups) {
 		pr_err("Unable to allocate lu_gp_cg->default_groups\n");
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index 9abef9f..3f60439 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -4,10 +4,7 @@
  * This file contains the TCM Virtual Device and Disk Transport
  * agnostic related functions.
  *
- * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc.
- * Copyright (c) 2005-2006 SBE, Inc.  All Rights Reserved.
- * Copyright (c) 2007-2010 Rising Tide Systems
- * Copyright (c) 2008-2010 Linux-iSCSI.org
+ * (c) Copyright 2003-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@kernel.org>
  *
@@ -50,26 +47,20 @@
 #include "target_core_pr.h"
 #include "target_core_ua.h"
 
-static void se_dev_start(struct se_device *dev);
-static void se_dev_stop(struct se_device *dev);
-
 static struct se_hba *lun0_hba;
-static struct se_subsystem_dev *lun0_su_dev;
 /* not static, needed by tpg.c */
 struct se_device *g_lun0_dev;
 
-int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
+sense_reason_t
+transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
 {
 	struct se_lun *se_lun = NULL;
 	struct se_session *se_sess = se_cmd->se_sess;
 	struct se_device *dev;
 	unsigned long flags;
 
-	if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) {
-		se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN;
-		se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		return -ENODEV;
-	}
+	if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG)
+		return TCM_NON_EXISTENT_LUN;
 
 	spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags);
 	se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun];
@@ -81,14 +72,12 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
 
 		if ((se_cmd->data_direction == DMA_TO_DEVICE) &&
 		    (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) {
-			se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED;
-			se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
 			pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN"
 				" Access for 0x%08x\n",
 				se_cmd->se_tfo->get_fabric_name(),
 				unpacked_lun);
 			spin_unlock_irqrestore(&se_sess->se_node_acl->device_list_lock, flags);
-			return -EACCES;
+			return TCM_WRITE_PROTECTED;
 		}
 
 		if (se_cmd->data_direction == DMA_TO_DEVICE)
@@ -113,38 +102,24 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
 		 * MappedLUN=0 exists for this Initiator Port.
 		 */
 		if (unpacked_lun != 0) {
-			se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN;
-			se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
 			pr_err("TARGET_CORE[%s]: Detected NON_EXISTENT_LUN"
 				" Access for 0x%08x\n",
 				se_cmd->se_tfo->get_fabric_name(),
 				unpacked_lun);
-			return -ENODEV;
+			return TCM_NON_EXISTENT_LUN;
 		}
 		/*
 		 * Force WRITE PROTECT for virtual LUN 0
 		 */
 		if ((se_cmd->data_direction != DMA_FROM_DEVICE) &&
-		    (se_cmd->data_direction != DMA_NONE)) {
-			se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED;
-			se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-			return -EACCES;
-		}
+		    (se_cmd->data_direction != DMA_NONE))
+			return TCM_WRITE_PROTECTED;
 
 		se_lun = &se_sess->se_tpg->tpg_virt_lun0;
 		se_cmd->se_lun = &se_sess->se_tpg->tpg_virt_lun0;
 		se_cmd->orig_fe_lun = 0;
 		se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD;
 	}
-	/*
-	 * Determine if the struct se_lun is online.
-	 * FIXME: Check for LUN_RESET + UNIT Attention
-	 */
-	if (se_dev_check_online(se_lun->lun_se_dev) != 0) {
-		se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN;
-		se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		return -ENODEV;
-	}
 
 	/* Directly associate cmd with se_dev */
 	se_cmd->se_dev = se_lun->lun_se_dev;
@@ -175,11 +150,8 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
 	struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
 	unsigned long flags;
 
-	if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) {
-		se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN;
-		se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+	if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG)
 		return -ENODEV;
-	}
 
 	spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags);
 	se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun];
@@ -199,15 +171,6 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
 			" Access for 0x%08x\n",
 			se_cmd->se_tfo->get_fabric_name(),
 			unpacked_lun);
-		se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		return -ENODEV;
-	}
-	/*
-	 * Determine if the struct se_lun is online.
-	 * FIXME: Check for LUN_RESET + UNIT Attention
-	 */
-	if (se_dev_check_online(se_lun->lun_se_dev) != 0) {
-		se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
 		return -ENODEV;
 	}
 
@@ -565,7 +528,6 @@ static void core_export_port(
 	struct se_port *port,
 	struct se_lun *lun)
 {
-	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem = NULL;
 
 	spin_lock(&dev->se_port_lock);
@@ -578,7 +540,8 @@ static void core_export_port(
 	list_add_tail(&port->sep_list, &dev->dev_sep_list);
 	spin_unlock(&dev->se_port_lock);
 
-	if (su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
+	if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV &&
+	    !(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) {
 		tg_pt_gp_mem = core_alua_allocate_tg_pt_gp_mem(port);
 		if (IS_ERR(tg_pt_gp_mem) || !tg_pt_gp_mem) {
 			pr_err("Unable to allocate t10_alua_tg_pt"
@@ -587,7 +550,7 @@ static void core_export_port(
 		}
 		spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 		__core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem,
-			su_dev->t10_alua.default_tg_pt_gp);
+			dev->t10_alua.default_tg_pt_gp);
 		spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 		pr_debug("%s/%s: Adding to default ALUA Target Port"
 			" Group: alua/default_tg_pt_gp\n",
@@ -625,6 +588,7 @@ int core_dev_export(
 	struct se_portal_group *tpg,
 	struct se_lun *lun)
 {
+	struct se_hba *hba = dev->se_hba;
 	struct se_port *port;
 
 	port = core_alloc_port(dev);
@@ -632,9 +596,11 @@ int core_dev_export(
 		return PTR_ERR(port);
 
 	lun->lun_se_dev = dev;
-	se_dev_start(dev);
 
-	atomic_inc(&dev->dev_export_obj.obj_access_count);
+	spin_lock(&hba->device_lock);
+	dev->export_count++;
+	spin_unlock(&hba->device_lock);
+
 	core_export_port(dev, tpg, port, lun);
 	return 0;
 }
@@ -644,6 +610,7 @@ void core_dev_unexport(
 	struct se_portal_group *tpg,
 	struct se_lun *lun)
 {
+	struct se_hba *hba = dev->se_hba;
 	struct se_port *port = lun->lun_sep;
 
 	spin_lock(&lun->lun_sep_lock);
@@ -654,198 +621,27 @@ void core_dev_unexport(
 	spin_unlock(&lun->lun_sep_lock);
 
 	spin_lock(&dev->se_port_lock);
-	atomic_dec(&dev->dev_export_obj.obj_access_count);
 	core_release_port(dev, port);
 	spin_unlock(&dev->se_port_lock);
 
-	se_dev_stop(dev);
-	lun->lun_se_dev = NULL;
-}
-
-int target_report_luns(struct se_cmd *se_cmd)
-{
-	struct se_dev_entry *deve;
-	struct se_session *se_sess = se_cmd->se_sess;
-	unsigned char *buf;
-	u32 lun_count = 0, offset = 8, i;
-
-	if (se_cmd->data_length < 16) {
-		pr_warn("REPORT LUNS allocation length %u too small\n",
-			se_cmd->data_length);
-		se_cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		return -EINVAL;
-	}
-
-	buf = transport_kmap_data_sg(se_cmd);
-	if (!buf)
-		return -ENOMEM;
-
-	/*
-	 * If no struct se_session pointer is present, this struct se_cmd is
-	 * coming via a target_core_mod PASSTHROUGH op, and not through
-	 * a $FABRIC_MOD.  In that case, report LUN=0 only.
-	 */
-	if (!se_sess) {
-		int_to_scsilun(0, (struct scsi_lun *)&buf[offset]);
-		lun_count = 1;
-		goto done;
-	}
-
-	spin_lock_irq(&se_sess->se_node_acl->device_list_lock);
-	for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
-		deve = se_sess->se_node_acl->device_list[i];
-		if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS))
-			continue;
-		/*
-		 * We determine the correct LUN LIST LENGTH even once we
-		 * have reached the initial allocation length.
-		 * See SPC2-R20 7.19.
-		 */
-		lun_count++;
-		if ((offset + 8) > se_cmd->data_length)
-			continue;
-
-		int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]);
-		offset += 8;
-	}
-	spin_unlock_irq(&se_sess->se_node_acl->device_list_lock);
-
-	/*
-	 * See SPC3 r07, page 159.
-	 */
-done:
-	lun_count *= 8;
-	buf[0] = ((lun_count >> 24) & 0xff);
-	buf[1] = ((lun_count >> 16) & 0xff);
-	buf[2] = ((lun_count >> 8) & 0xff);
-	buf[3] = (lun_count & 0xff);
-	transport_kunmap_data_sg(se_cmd);
-
-	target_complete_cmd(se_cmd, GOOD);
-	return 0;
-}
-
-/*	se_release_device_for_hba():
- *
- *
- */
-void se_release_device_for_hba(struct se_device *dev)
-{
-	struct se_hba *hba = dev->se_hba;
-
-	if ((dev->dev_status & TRANSPORT_DEVICE_ACTIVATED) ||
-	    (dev->dev_status & TRANSPORT_DEVICE_DEACTIVATED) ||
-	    (dev->dev_status & TRANSPORT_DEVICE_SHUTDOWN) ||
-	    (dev->dev_status & TRANSPORT_DEVICE_OFFLINE_ACTIVATED) ||
-	    (dev->dev_status & TRANSPORT_DEVICE_OFFLINE_DEACTIVATED))
-		se_dev_stop(dev);
-
-	if (dev->dev_ptr) {
-		destroy_workqueue(dev->tmr_wq);
-		if (dev->transport->free_device)
-			dev->transport->free_device(dev->dev_ptr);
-	}
-
 	spin_lock(&hba->device_lock);
-	list_del(&dev->dev_list);
-	hba->dev_count--;
+	dev->export_count--;
 	spin_unlock(&hba->device_lock);
 
-	core_scsi3_free_all_registrations(dev);
-	se_release_vpd_for_dev(dev);
-
-	kfree(dev);
+	lun->lun_se_dev = NULL;
 }
 
-void se_release_vpd_for_dev(struct se_device *dev)
+static void se_release_vpd_for_dev(struct se_device *dev)
 {
 	struct t10_vpd *vpd, *vpd_tmp;
 
-	spin_lock(&dev->se_sub_dev->t10_wwn.t10_vpd_lock);
+	spin_lock(&dev->t10_wwn.t10_vpd_lock);
 	list_for_each_entry_safe(vpd, vpd_tmp,
-			&dev->se_sub_dev->t10_wwn.t10_vpd_list, vpd_list) {
+			&dev->t10_wwn.t10_vpd_list, vpd_list) {
 		list_del(&vpd->vpd_list);
 		kfree(vpd);
 	}
-	spin_unlock(&dev->se_sub_dev->t10_wwn.t10_vpd_lock);
-}
-
-/*	se_free_virtual_device():
- *
- *	Used for IBLOCK, RAMDISK, and FILEIO Transport Drivers.
- */
-int se_free_virtual_device(struct se_device *dev, struct se_hba *hba)
-{
-	if (!list_empty(&dev->dev_sep_list))
-		dump_stack();
-
-	core_alua_free_lu_gp_mem(dev);
-	se_release_device_for_hba(dev);
-
-	return 0;
-}
-
-static void se_dev_start(struct se_device *dev)
-{
-	struct se_hba *hba = dev->se_hba;
-
-	spin_lock(&hba->device_lock);
-	atomic_inc(&dev->dev_obj.obj_access_count);
-	if (atomic_read(&dev->dev_obj.obj_access_count) == 1) {
-		if (dev->dev_status & TRANSPORT_DEVICE_DEACTIVATED) {
-			dev->dev_status &= ~TRANSPORT_DEVICE_DEACTIVATED;
-			dev->dev_status |= TRANSPORT_DEVICE_ACTIVATED;
-		} else if (dev->dev_status &
-			   TRANSPORT_DEVICE_OFFLINE_DEACTIVATED) {
-			dev->dev_status &=
-				~TRANSPORT_DEVICE_OFFLINE_DEACTIVATED;
-			dev->dev_status |= TRANSPORT_DEVICE_OFFLINE_ACTIVATED;
-		}
-	}
-	spin_unlock(&hba->device_lock);
-}
-
-static void se_dev_stop(struct se_device *dev)
-{
-	struct se_hba *hba = dev->se_hba;
-
-	spin_lock(&hba->device_lock);
-	atomic_dec(&dev->dev_obj.obj_access_count);
-	if (atomic_read(&dev->dev_obj.obj_access_count) == 0) {
-		if (dev->dev_status & TRANSPORT_DEVICE_ACTIVATED) {
-			dev->dev_status &= ~TRANSPORT_DEVICE_ACTIVATED;
-			dev->dev_status |= TRANSPORT_DEVICE_DEACTIVATED;
-		} else if (dev->dev_status &
-			   TRANSPORT_DEVICE_OFFLINE_ACTIVATED) {
-			dev->dev_status &= ~TRANSPORT_DEVICE_OFFLINE_ACTIVATED;
-			dev->dev_status |= TRANSPORT_DEVICE_OFFLINE_DEACTIVATED;
-		}
-	}
-	spin_unlock(&hba->device_lock);
-}
-
-int se_dev_check_online(struct se_device *dev)
-{
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&dev->dev_status_lock, flags);
-	ret = ((dev->dev_status & TRANSPORT_DEVICE_ACTIVATED) ||
-	       (dev->dev_status & TRANSPORT_DEVICE_DEACTIVATED)) ? 0 : 1;
-	spin_unlock_irqrestore(&dev->dev_status_lock, flags);
-
-	return ret;
-}
-
-int se_dev_check_shutdown(struct se_device *dev)
-{
-	int ret;
-
-	spin_lock_irq(&dev->dev_status_lock);
-	ret = (dev->dev_status & TRANSPORT_DEVICE_SHUTDOWN);
-	spin_unlock_irq(&dev->dev_status_lock);
-
-	return ret;
+	spin_unlock(&dev->t10_wwn.t10_vpd_lock);
 }
 
 static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
@@ -866,72 +662,13 @@ static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
 	return aligned_max_sectors;
 }
 
-void se_dev_set_default_attribs(
-	struct se_device *dev,
-	struct se_dev_limits *dev_limits)
-{
-	struct queue_limits *limits = &dev_limits->limits;
-
-	dev->se_sub_dev->se_dev_attrib.emulate_dpo = DA_EMULATE_DPO;
-	dev->se_sub_dev->se_dev_attrib.emulate_fua_write = DA_EMULATE_FUA_WRITE;
-	dev->se_sub_dev->se_dev_attrib.emulate_fua_read = DA_EMULATE_FUA_READ;
-	dev->se_sub_dev->se_dev_attrib.emulate_write_cache = DA_EMULATE_WRITE_CACHE;
-	dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl = DA_EMULATE_UA_INTLLCK_CTRL;
-	dev->se_sub_dev->se_dev_attrib.emulate_tas = DA_EMULATE_TAS;
-	dev->se_sub_dev->se_dev_attrib.emulate_tpu = DA_EMULATE_TPU;
-	dev->se_sub_dev->se_dev_attrib.emulate_tpws = DA_EMULATE_TPWS;
-	dev->se_sub_dev->se_dev_attrib.emulate_reservations = DA_EMULATE_RESERVATIONS;
-	dev->se_sub_dev->se_dev_attrib.emulate_alua = DA_EMULATE_ALUA;
-	dev->se_sub_dev->se_dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS;
-	dev->se_sub_dev->se_dev_attrib.is_nonrot = DA_IS_NONROT;
-	dev->se_sub_dev->se_dev_attrib.emulate_rest_reord = DA_EMULATE_REST_REORD;
-	/*
-	 * The TPU=1 and TPWS=1 settings will be set in TCM/IBLOCK
-	 * iblock_create_virtdevice() from struct queue_limits values
-	 * if blk_queue_discard()==1
-	 */
-	dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count = DA_MAX_UNMAP_LBA_COUNT;
-	dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count =
-		DA_MAX_UNMAP_BLOCK_DESC_COUNT;
-	dev->se_sub_dev->se_dev_attrib.unmap_granularity = DA_UNMAP_GRANULARITY_DEFAULT;
-	dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment =
-				DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT;
-	/*
-	 * block_size is based on subsystem plugin dependent requirements.
-	 */
-	dev->se_sub_dev->se_dev_attrib.hw_block_size = limits->logical_block_size;
-	dev->se_sub_dev->se_dev_attrib.block_size = limits->logical_block_size;
-	/*
-	 * Align max_hw_sectors down to PAGE_SIZE I/O transfers
-	 */
-	limits->max_hw_sectors = se_dev_align_max_sectors(limits->max_hw_sectors,
-						limits->logical_block_size);
-	dev->se_sub_dev->se_dev_attrib.hw_max_sectors = limits->max_hw_sectors;
-
-	/*
-	 * Set fabric_max_sectors, which is reported in block limits
-	 * VPD page (B0h).
-	 */
-	dev->se_sub_dev->se_dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS;
-	/*
-	 * Set optimal_sectors from fabric_max_sectors, which can be
-	 * lowered via configfs.
-	 */
-	dev->se_sub_dev->se_dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS;
-	/*
-	 * queue_depth is based on subsystem plugin dependent requirements.
-	 */
-	dev->se_sub_dev->se_dev_attrib.hw_queue_depth = dev_limits->hw_queue_depth;
-	dev->se_sub_dev->se_dev_attrib.queue_depth = dev_limits->queue_depth;
-}
-
 int se_dev_set_max_unmap_lba_count(
 	struct se_device *dev,
 	u32 max_unmap_lba_count)
 {
-	dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count = max_unmap_lba_count;
+	dev->dev_attrib.max_unmap_lba_count = max_unmap_lba_count;
 	pr_debug("dev[%p]: Set max_unmap_lba_count: %u\n",
-			dev, dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count);
+			dev, dev->dev_attrib.max_unmap_lba_count);
 	return 0;
 }
 
@@ -939,10 +676,10 @@ int se_dev_set_max_unmap_block_desc_count(
 	struct se_device *dev,
 	u32 max_unmap_block_desc_count)
 {
-	dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count =
+	dev->dev_attrib.max_unmap_block_desc_count =
 		max_unmap_block_desc_count;
 	pr_debug("dev[%p]: Set max_unmap_block_desc_count: %u\n",
-			dev, dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count);
+			dev, dev->dev_attrib.max_unmap_block_desc_count);
 	return 0;
 }
 
@@ -950,9 +687,9 @@ int se_dev_set_unmap_granularity(
 	struct se_device *dev,
 	u32 unmap_granularity)
 {
-	dev->se_sub_dev->se_dev_attrib.unmap_granularity = unmap_granularity;
+	dev->dev_attrib.unmap_granularity = unmap_granularity;
 	pr_debug("dev[%p]: Set unmap_granularity: %u\n",
-			dev, dev->se_sub_dev->se_dev_attrib.unmap_granularity);
+			dev, dev->dev_attrib.unmap_granularity);
 	return 0;
 }
 
@@ -960,9 +697,19 @@ int se_dev_set_unmap_granularity_alignment(
 	struct se_device *dev,
 	u32 unmap_granularity_alignment)
 {
-	dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment = unmap_granularity_alignment;
+	dev->dev_attrib.unmap_granularity_alignment = unmap_granularity_alignment;
 	pr_debug("dev[%p]: Set unmap_granularity_alignment: %u\n",
-			dev, dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment);
+			dev, dev->dev_attrib.unmap_granularity_alignment);
+	return 0;
+}
+
+int se_dev_set_max_write_same_len(
+	struct se_device *dev,
+	u32 max_write_same_len)
+{
+	dev->dev_attrib.max_write_same_len = max_write_same_len;
+	pr_debug("dev[%p]: Set max_write_same_len: %u\n",
+			dev, dev->dev_attrib.max_write_same_len);
 	return 0;
 }
 
@@ -993,9 +740,9 @@ int se_dev_set_emulate_fua_write(struct se_device *dev, int flag)
 		pr_err("emulate_fua_write not supported for pSCSI\n");
 		return -EINVAL;
 	}
-	dev->se_sub_dev->se_dev_attrib.emulate_fua_write = flag;
+	dev->dev_attrib.emulate_fua_write = flag;
 	pr_debug("dev[%p]: SE Device Forced Unit Access WRITEs: %d\n",
-			dev, dev->se_sub_dev->se_dev_attrib.emulate_fua_write);
+			dev, dev->dev_attrib.emulate_fua_write);
 	return 0;
 }
 
@@ -1025,9 +772,9 @@ int se_dev_set_emulate_write_cache(struct se_device *dev, int flag)
 		pr_err("emulate_write_cache not supported for pSCSI\n");
 		return -EINVAL;
 	}
-	dev->se_sub_dev->se_dev_attrib.emulate_write_cache = flag;
+	dev->dev_attrib.emulate_write_cache = flag;
 	pr_debug("dev[%p]: SE Device WRITE_CACHE_EMULATION flag: %d\n",
-			dev, dev->se_sub_dev->se_dev_attrib.emulate_write_cache);
+			dev, dev->dev_attrib.emulate_write_cache);
 	return 0;
 }
 
@@ -1038,16 +785,15 @@ int se_dev_set_emulate_ua_intlck_ctrl(struct se_device *dev, int flag)
 		return -EINVAL;
 	}
 
-	if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
+	if (dev->export_count) {
 		pr_err("dev[%p]: Unable to change SE Device"
-			" UA_INTRLCK_CTRL while dev_export_obj: %d count"
-			" exists\n", dev,
-			atomic_read(&dev->dev_export_obj.obj_access_count));
+			" UA_INTRLCK_CTRL while export_count is %d\n",
+			dev, dev->export_count);
 		return -EINVAL;
 	}
-	dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl = flag;
+	dev->dev_attrib.emulate_ua_intlck_ctrl = flag;
 	pr_debug("dev[%p]: SE Device UA_INTRLCK_CTRL flag: %d\n",
-		dev, dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl);
+		dev, dev->dev_attrib.emulate_ua_intlck_ctrl);
 
 	return 0;
 }
@@ -1059,15 +805,15 @@ int se_dev_set_emulate_tas(struct se_device *dev, int flag)
 		return -EINVAL;
 	}
 
-	if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
+	if (dev->export_count) {
 		pr_err("dev[%p]: Unable to change SE Device TAS while"
-			" dev_export_obj: %d count exists\n", dev,
-			atomic_read(&dev->dev_export_obj.obj_access_count));
+			" export_count is %d\n",
+			dev, dev->export_count);
 		return -EINVAL;
 	}
-	dev->se_sub_dev->se_dev_attrib.emulate_tas = flag;
+	dev->dev_attrib.emulate_tas = flag;
 	pr_debug("dev[%p]: SE Device TASK_ABORTED status bit: %s\n",
-		dev, (dev->se_sub_dev->se_dev_attrib.emulate_tas) ? "Enabled" : "Disabled");
+		dev, (dev->dev_attrib.emulate_tas) ? "Enabled" : "Disabled");
 
 	return 0;
 }
@@ -1082,12 +828,12 @@ int se_dev_set_emulate_tpu(struct se_device *dev, int flag)
 	 * We expect this value to be non-zero when generic Block Layer
 	 * Discard supported is detected iblock_create_virtdevice().
 	 */
-	if (flag && !dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) {
+	if (flag && !dev->dev_attrib.max_unmap_block_desc_count) {
 		pr_err("Generic Block Discard not supported\n");
 		return -ENOSYS;
 	}
 
-	dev->se_sub_dev->se_dev_attrib.emulate_tpu = flag;
+	dev->dev_attrib.emulate_tpu = flag;
 	pr_debug("dev[%p]: SE Device Thin Provisioning UNMAP bit: %d\n",
 				dev, flag);
 	return 0;
@@ -1103,12 +849,12 @@ int se_dev_set_emulate_tpws(struct se_device *dev, int flag)
 	 * We expect this value to be non-zero when generic Block Layer
 	 * Discard supported is detected iblock_create_virtdevice().
 	 */
-	if (flag && !dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) {
+	if (flag && !dev->dev_attrib.max_unmap_block_desc_count) {
 		pr_err("Generic Block Discard not supported\n");
 		return -ENOSYS;
 	}
 
-	dev->se_sub_dev->se_dev_attrib.emulate_tpws = flag;
+	dev->dev_attrib.emulate_tpws = flag;
 	pr_debug("dev[%p]: SE Device Thin Provisioning WRITE_SAME: %d\n",
 				dev, flag);
 	return 0;
@@ -1120,9 +866,9 @@ int se_dev_set_enforce_pr_isids(struct se_device *dev, int flag)
 		pr_err("Illegal value %d\n", flag);
 		return -EINVAL;
 	}
-	dev->se_sub_dev->se_dev_attrib.enforce_pr_isids = flag;
+	dev->dev_attrib.enforce_pr_isids = flag;
 	pr_debug("dev[%p]: SE Device enforce_pr_isids bit: %s\n", dev,
-		(dev->se_sub_dev->se_dev_attrib.enforce_pr_isids) ? "Enabled" : "Disabled");
+		(dev->dev_attrib.enforce_pr_isids) ? "Enabled" : "Disabled");
 	return 0;
 }
 
@@ -1132,7 +878,7 @@ int se_dev_set_is_nonrot(struct se_device *dev, int flag)
 		printk(KERN_ERR "Illegal value %d\n", flag);
 		return -EINVAL;
 	}
-	dev->se_sub_dev->se_dev_attrib.is_nonrot = flag;
+	dev->dev_attrib.is_nonrot = flag;
 	pr_debug("dev[%p]: SE Device is_nonrot bit: %d\n",
 	       dev, flag);
 	return 0;
@@ -1145,7 +891,7 @@ int se_dev_set_emulate_rest_reord(struct se_device *dev, int flag)
 			" reordering not implemented\n", dev);
 		return -ENOSYS;
 	}
-	dev->se_sub_dev->se_dev_attrib.emulate_rest_reord = flag;
+	dev->dev_attrib.emulate_rest_reord = flag;
 	pr_debug("dev[%p]: SE Device emulate_rest_reord: %d\n", dev, flag);
 	return 0;
 }
@@ -1155,10 +901,10 @@ int se_dev_set_emulate_rest_reord(struct se_device *dev, int flag)
  */
 int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth)
 {
-	if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
+	if (dev->export_count) {
 		pr_err("dev[%p]: Unable to change SE Device TCQ while"
-			" dev_export_obj: %d count exists\n", dev,
-			atomic_read(&dev->dev_export_obj.obj_access_count));
+			" export_count is %d\n",
+			dev, dev->export_count);
 		return -EINVAL;
 	}
 	if (!queue_depth) {
@@ -1168,26 +914,26 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth)
 	}
 
 	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
-		if (queue_depth > dev->se_sub_dev->se_dev_attrib.hw_queue_depth) {
+		if (queue_depth > dev->dev_attrib.hw_queue_depth) {
 			pr_err("dev[%p]: Passed queue_depth: %u"
 				" exceeds TCM/SE_Device TCQ: %u\n",
 				dev, queue_depth,
-				dev->se_sub_dev->se_dev_attrib.hw_queue_depth);
+				dev->dev_attrib.hw_queue_depth);
 			return -EINVAL;
 		}
 	} else {
-		if (queue_depth > dev->se_sub_dev->se_dev_attrib.queue_depth) {
-			if (queue_depth > dev->se_sub_dev->se_dev_attrib.hw_queue_depth) {
+		if (queue_depth > dev->dev_attrib.queue_depth) {
+			if (queue_depth > dev->dev_attrib.hw_queue_depth) {
 				pr_err("dev[%p]: Passed queue_depth:"
 					" %u exceeds TCM/SE_Device MAX"
 					" TCQ: %u\n", dev, queue_depth,
-					dev->se_sub_dev->se_dev_attrib.hw_queue_depth);
+					dev->dev_attrib.hw_queue_depth);
 				return -EINVAL;
 			}
 		}
 	}
 
-	dev->se_sub_dev->se_dev_attrib.queue_depth = dev->queue_depth = queue_depth;
+	dev->dev_attrib.queue_depth = dev->queue_depth = queue_depth;
 	pr_debug("dev[%p]: SE Device TCQ Depth changed to: %u\n",
 			dev, queue_depth);
 	return 0;
@@ -1195,10 +941,10 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth)
 
 int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors)
 {
-	if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
+	if (dev->export_count) {
 		pr_err("dev[%p]: Unable to change SE Device"
-			" fabric_max_sectors while dev_export_obj: %d count exists\n",
-			dev, atomic_read(&dev->dev_export_obj.obj_access_count));
+			" fabric_max_sectors while export_count is %d\n",
+			dev, dev->export_count);
 		return -EINVAL;
 	}
 	if (!fabric_max_sectors) {
@@ -1213,11 +959,11 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors)
 		return -EINVAL;
 	}
 	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
-		if (fabric_max_sectors > dev->se_sub_dev->se_dev_attrib.hw_max_sectors) {
+		if (fabric_max_sectors > dev->dev_attrib.hw_max_sectors) {
 			pr_err("dev[%p]: Passed fabric_max_sectors: %u"
 				" greater than TCM/SE_Device max_sectors:"
 				" %u\n", dev, fabric_max_sectors,
-				dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
+				dev->dev_attrib.hw_max_sectors);
 			 return -EINVAL;
 		}
 	} else {
@@ -1233,9 +979,9 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors)
 	 * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks()
 	 */
 	fabric_max_sectors = se_dev_align_max_sectors(fabric_max_sectors,
-						      dev->se_sub_dev->se_dev_attrib.block_size);
+						      dev->dev_attrib.block_size);
 
-	dev->se_sub_dev->se_dev_attrib.fabric_max_sectors = fabric_max_sectors;
+	dev->dev_attrib.fabric_max_sectors = fabric_max_sectors;
 	pr_debug("dev[%p]: SE Device max_sectors changed to %u\n",
 			dev, fabric_max_sectors);
 	return 0;
@@ -1243,10 +989,10 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors)
 
 int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors)
 {
-	if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
+	if (dev->export_count) {
 		pr_err("dev[%p]: Unable to change SE Device"
-			" optimal_sectors while dev_export_obj: %d count exists\n",
-			dev, atomic_read(&dev->dev_export_obj.obj_access_count));
+			" optimal_sectors while export_count is %d\n",
+			dev, dev->export_count);
 		return -EINVAL;
 	}
 	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
@@ -1254,14 +1000,14 @@ int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors)
 				" changed for TCM/pSCSI\n", dev);
 		return -EINVAL;
 	}
-	if (optimal_sectors > dev->se_sub_dev->se_dev_attrib.fabric_max_sectors) {
+	if (optimal_sectors > dev->dev_attrib.fabric_max_sectors) {
 		pr_err("dev[%p]: Passed optimal_sectors %u cannot be"
 			" greater than fabric_max_sectors: %u\n", dev,
-			optimal_sectors, dev->se_sub_dev->se_dev_attrib.fabric_max_sectors);
+			optimal_sectors, dev->dev_attrib.fabric_max_sectors);
 		return -EINVAL;
 	}
 
-	dev->se_sub_dev->se_dev_attrib.optimal_sectors = optimal_sectors;
+	dev->dev_attrib.optimal_sectors = optimal_sectors;
 	pr_debug("dev[%p]: SE Device optimal_sectors changed to %u\n",
 			dev, optimal_sectors);
 	return 0;
@@ -1269,10 +1015,10 @@ int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors)
 
 int se_dev_set_block_size(struct se_device *dev, u32 block_size)
 {
-	if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
+	if (dev->export_count) {
 		pr_err("dev[%p]: Unable to change SE Device block_size"
-			" while dev_export_obj: %d count exists\n", dev,
-			atomic_read(&dev->dev_export_obj.obj_access_count));
+			" while export_count is %d\n",
+			dev, dev->export_count);
 		return -EINVAL;
 	}
 
@@ -1293,7 +1039,7 @@ int se_dev_set_block_size(struct se_device *dev, u32 block_size)
 		return -EINVAL;
 	}
 
-	dev->se_sub_dev->se_dev_attrib.block_size = block_size;
+	dev->dev_attrib.block_size = block_size;
 	pr_debug("dev[%p]: SE Device block_size changed to %u\n",
 			dev, block_size);
 	return 0;
@@ -1307,12 +1053,6 @@ struct se_lun *core_dev_add_lun(
 	struct se_lun *lun_p;
 	int rc;
 
-	if (atomic_read(&dev->dev_access_obj.obj_access_count) != 0) {
-		pr_err("Unable to export struct se_device while dev_access_obj: %d\n",
-			atomic_read(&dev->dev_access_obj.obj_access_count));
-		return ERR_PTR(-EACCES);
-	}
-
 	lun_p = core_tpg_pre_addlun(tpg, lun);
 	if (IS_ERR(lun_p))
 		return lun_p;
@@ -1568,12 +1308,210 @@ void core_dev_free_initiator_node_lun_acl(
 	kfree(lacl);
 }
 
+static void scsi_dump_inquiry(struct se_device *dev)
+{
+	struct t10_wwn *wwn = &dev->t10_wwn;
+	char buf[17];
+	int i, device_type;
+	/*
+	 * Print Linux/SCSI style INQUIRY formatting to the kernel ring buffer
+	 */
+	for (i = 0; i < 8; i++)
+		if (wwn->vendor[i] >= 0x20)
+			buf[i] = wwn->vendor[i];
+		else
+			buf[i] = ' ';
+	buf[i] = '\0';
+	pr_debug("  Vendor: %s\n", buf);
+
+	for (i = 0; i < 16; i++)
+		if (wwn->model[i] >= 0x20)
+			buf[i] = wwn->model[i];
+		else
+			buf[i] = ' ';
+	buf[i] = '\0';
+	pr_debug("  Model: %s\n", buf);
+
+	for (i = 0; i < 4; i++)
+		if (wwn->revision[i] >= 0x20)
+			buf[i] = wwn->revision[i];
+		else
+			buf[i] = ' ';
+	buf[i] = '\0';
+	pr_debug("  Revision: %s\n", buf);
+
+	device_type = dev->transport->get_device_type(dev);
+	pr_debug("  Type:   %s ", scsi_device_type(device_type));
+}
+
+struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
+{
+	struct se_device *dev;
+
+	dev = hba->transport->alloc_device(hba, name);
+	if (!dev)
+		return NULL;
+
+	dev->se_hba = hba;
+	dev->transport = hba->transport;
+
+	INIT_LIST_HEAD(&dev->dev_list);
+	INIT_LIST_HEAD(&dev->dev_sep_list);
+	INIT_LIST_HEAD(&dev->dev_tmr_list);
+	INIT_LIST_HEAD(&dev->delayed_cmd_list);
+	INIT_LIST_HEAD(&dev->state_list);
+	INIT_LIST_HEAD(&dev->qf_cmd_list);
+	spin_lock_init(&dev->stats_lock);
+	spin_lock_init(&dev->execute_task_lock);
+	spin_lock_init(&dev->delayed_cmd_lock);
+	spin_lock_init(&dev->dev_reservation_lock);
+	spin_lock_init(&dev->se_port_lock);
+	spin_lock_init(&dev->se_tmr_lock);
+	spin_lock_init(&dev->qf_cmd_lock);
+	atomic_set(&dev->dev_ordered_id, 0);
+	INIT_LIST_HEAD(&dev->t10_wwn.t10_vpd_list);
+	spin_lock_init(&dev->t10_wwn.t10_vpd_lock);
+	INIT_LIST_HEAD(&dev->t10_pr.registration_list);
+	INIT_LIST_HEAD(&dev->t10_pr.aptpl_reg_list);
+	spin_lock_init(&dev->t10_pr.registration_lock);
+	spin_lock_init(&dev->t10_pr.aptpl_reg_lock);
+	INIT_LIST_HEAD(&dev->t10_alua.tg_pt_gps_list);
+	spin_lock_init(&dev->t10_alua.tg_pt_gps_lock);
+
+	dev->t10_pr.pr_aptpl_buf_len = PR_APTPL_BUF_LEN;
+	dev->t10_wwn.t10_dev = dev;
+	dev->t10_alua.t10_dev = dev;
+
+	dev->dev_attrib.da_dev = dev;
+	dev->dev_attrib.emulate_dpo = DA_EMULATE_DPO;
+	dev->dev_attrib.emulate_fua_write = DA_EMULATE_FUA_WRITE;
+	dev->dev_attrib.emulate_fua_read = DA_EMULATE_FUA_READ;
+	dev->dev_attrib.emulate_write_cache = DA_EMULATE_WRITE_CACHE;
+	dev->dev_attrib.emulate_ua_intlck_ctrl = DA_EMULATE_UA_INTLLCK_CTRL;
+	dev->dev_attrib.emulate_tas = DA_EMULATE_TAS;
+	dev->dev_attrib.emulate_tpu = DA_EMULATE_TPU;
+	dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS;
+	dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS;
+	dev->dev_attrib.is_nonrot = DA_IS_NONROT;
+	dev->dev_attrib.emulate_rest_reord = DA_EMULATE_REST_REORD;
+	dev->dev_attrib.max_unmap_lba_count = DA_MAX_UNMAP_LBA_COUNT;
+	dev->dev_attrib.max_unmap_block_desc_count =
+		DA_MAX_UNMAP_BLOCK_DESC_COUNT;
+	dev->dev_attrib.unmap_granularity = DA_UNMAP_GRANULARITY_DEFAULT;
+	dev->dev_attrib.unmap_granularity_alignment =
+				DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT;
+	dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN;
+	dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS;
+	dev->dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS;
+
+	return dev;
+}
+
+int target_configure_device(struct se_device *dev)
+{
+	struct se_hba *hba = dev->se_hba;
+	int ret;
+
+	if (dev->dev_flags & DF_CONFIGURED) {
+		pr_err("se_dev->se_dev_ptr already set for storage"
+				" object\n");
+		return -EEXIST;
+	}
+
+	ret = dev->transport->configure_device(dev);
+	if (ret)
+		goto out;
+	dev->dev_flags |= DF_CONFIGURED;
+
+	/*
+	 * XXX: there is not much point to have two different values here..
+	 */
+	dev->dev_attrib.block_size = dev->dev_attrib.hw_block_size;
+	dev->dev_attrib.queue_depth = dev->dev_attrib.hw_queue_depth;
+
+	/*
+	 * Align max_hw_sectors down to PAGE_SIZE I/O transfers
+	 */
+	dev->dev_attrib.hw_max_sectors =
+		se_dev_align_max_sectors(dev->dev_attrib.hw_max_sectors,
+					 dev->dev_attrib.hw_block_size);
+
+	dev->dev_index = scsi_get_new_index(SCSI_DEVICE_INDEX);
+	dev->creation_time = get_jiffies_64();
+
+	ret = core_setup_alua(dev);
+	if (ret)
+		goto out;
+
+	/*
+	 * Startup the struct se_device processing thread
+	 */
+	dev->tmr_wq = alloc_workqueue("tmr-%s", WQ_MEM_RECLAIM | WQ_UNBOUND, 1,
+				      dev->transport->name);
+	if (!dev->tmr_wq) {
+		pr_err("Unable to create tmr workqueue for %s\n",
+			dev->transport->name);
+		ret = -ENOMEM;
+		goto out_free_alua;
+	}
+
+	/*
+	 * Setup work_queue for QUEUE_FULL
+	 */
+	INIT_WORK(&dev->qf_work_queue, target_qf_do_work);
+
+	/*
+	 * Preload the initial INQUIRY const values if we are doing
+	 * anything virtual (IBLOCK, FILEIO, RAMDISK), but not for TCM/pSCSI
+	 * passthrough because this is being provided by the backend LLD.
+	 */
+	if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) {
+		strncpy(&dev->t10_wwn.vendor[0], "LIO-ORG", 8);
+		strncpy(&dev->t10_wwn.model[0],
+			dev->transport->inquiry_prod, 16);
+		strncpy(&dev->t10_wwn.revision[0],
+			dev->transport->inquiry_rev, 4);
+	}
+
+	scsi_dump_inquiry(dev);
+
+	spin_lock(&hba->device_lock);
+	hba->dev_count++;
+	spin_unlock(&hba->device_lock);
+	return 0;
+
+out_free_alua:
+	core_alua_free_lu_gp_mem(dev);
+out:
+	se_release_vpd_for_dev(dev);
+	return ret;
+}
+
+void target_free_device(struct se_device *dev)
+{
+	struct se_hba *hba = dev->se_hba;
+
+	WARN_ON(!list_empty(&dev->dev_sep_list));
+
+	if (dev->dev_flags & DF_CONFIGURED) {
+		destroy_workqueue(dev->tmr_wq);
+
+		spin_lock(&hba->device_lock);
+		hba->dev_count--;
+		spin_unlock(&hba->device_lock);
+	}
+
+	core_alua_free_lu_gp_mem(dev);
+	core_scsi3_free_all_registrations(dev);
+	se_release_vpd_for_dev(dev);
+
+	dev->transport->free_device(dev);
+}
+
 int core_dev_setup_virtual_lun0(void)
 {
 	struct se_hba *hba;
 	struct se_device *dev;
-	struct se_subsystem_dev *se_dev = NULL;
-	struct se_subsystem_api *t;
 	char buf[16];
 	int ret;
 
@@ -1581,60 +1519,28 @@ int core_dev_setup_virtual_lun0(void)
 	if (IS_ERR(hba))
 		return PTR_ERR(hba);
 
-	lun0_hba = hba;
-	t = hba->transport;
-
-	se_dev = kzalloc(sizeof(struct se_subsystem_dev), GFP_KERNEL);
-	if (!se_dev) {
-		pr_err("Unable to allocate memory for"
-				" struct se_subsystem_dev\n");
+	dev = target_alloc_device(hba, "virt_lun0");
+	if (!dev) {
 		ret = -ENOMEM;
-		goto out;
+		goto out_free_hba;
 	}
-	INIT_LIST_HEAD(&se_dev->t10_wwn.t10_vpd_list);
-	spin_lock_init(&se_dev->t10_wwn.t10_vpd_lock);
-	INIT_LIST_HEAD(&se_dev->t10_pr.registration_list);
-	INIT_LIST_HEAD(&se_dev->t10_pr.aptpl_reg_list);
-	spin_lock_init(&se_dev->t10_pr.registration_lock);
-	spin_lock_init(&se_dev->t10_pr.aptpl_reg_lock);
-	INIT_LIST_HEAD(&se_dev->t10_alua.tg_pt_gps_list);
-	spin_lock_init(&se_dev->t10_alua.tg_pt_gps_lock);
-	spin_lock_init(&se_dev->se_dev_lock);
-	se_dev->t10_pr.pr_aptpl_buf_len = PR_APTPL_BUF_LEN;
-	se_dev->t10_wwn.t10_sub_dev = se_dev;
-	se_dev->t10_alua.t10_sub_dev = se_dev;
-	se_dev->se_dev_attrib.da_sub_dev = se_dev;
-	se_dev->se_dev_hba = hba;
-
-	se_dev->se_dev_su_ptr = t->allocate_virtdevice(hba, "virt_lun0");
-	if (!se_dev->se_dev_su_ptr) {
-		pr_err("Unable to locate subsystem dependent pointer"
-			" from allocate_virtdevice()\n");
-		ret = -ENOMEM;
-		goto out;
-	}
-	lun0_su_dev = se_dev;
 
 	memset(buf, 0, 16);
 	sprintf(buf, "rd_pages=8");
-	t->set_configfs_dev_params(hba, se_dev, buf, sizeof(buf));
+	hba->transport->set_configfs_dev_params(dev, buf, sizeof(buf));
 
-	dev = t->create_virtdevice(hba, se_dev, se_dev->se_dev_su_ptr);
-	if (IS_ERR(dev)) {
-		ret = PTR_ERR(dev);
-		goto out;
-	}
-	se_dev->se_dev_ptr = dev;
-	g_lun0_dev = dev;
+	ret = target_configure_device(dev);
+	if (ret)
+		goto out_free_se_dev;
 
+	lun0_hba = hba;
+	g_lun0_dev = dev;
 	return 0;
-out:
-	lun0_su_dev = NULL;
-	kfree(se_dev);
-	if (lun0_hba) {
-		core_delete_hba(lun0_hba);
-		lun0_hba = NULL;
-	}
+
+out_free_se_dev:
+	target_free_device(dev);
+out_free_hba:
+	core_delete_hba(hba);
 	return ret;
 }
 
@@ -1642,14 +1548,11 @@ out:
 void core_dev_release_virtual_lun0(void)
 {
 	struct se_hba *hba = lun0_hba;
-	struct se_subsystem_dev *su_dev = lun0_su_dev;
 
 	if (!hba)
 		return;
 
 	if (g_lun0_dev)
-		se_free_virtual_device(g_lun0_dev, hba);
-
-	kfree(su_dev);
+		target_free_device(g_lun0_dev);
 	core_delete_hba(hba);
 }
diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c
index bca737b..9c67917 100644
--- a/drivers/target/target_core_fabric_configfs.c
+++ b/drivers/target/target_core_fabric_configfs.c
@@ -4,10 +4,9 @@
  * This file contains generic fabric module configfs infrastructure for
  * TCM v4.x code
  *
- * Copyright (c) 2010,2011 Rising Tide Systems
- * Copyright (c) 2010,2011 Linux-iSCSI.org
+ * (c) Copyright 2010-2012 RisingTide Systems LLC.
  *
- * Copyright (c) Nicholas A. Bellinger <nab@linux-iscsi.org>
+ * Nicholas A. Bellinger <nab@linux-iscsi.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
@@ -358,7 +357,7 @@ static struct config_group *target_fabric_make_mappedlun(
 	}
 
 	lacl_cg = &lacl->se_lun_group;
-	lacl_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
+	lacl_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2,
 				GFP_KERNEL);
 	if (!lacl_cg->default_groups) {
 		pr_err("Unable to allocate lacl_cg->default_groups\n");
@@ -374,7 +373,7 @@ static struct config_group *target_fabric_make_mappedlun(
 	lacl_cg->default_groups[1] = NULL;
 
 	ml_stat_grp = &lacl->ml_stat_grps.stat_group;
-	ml_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 3,
+	ml_stat_grp->default_groups = kmalloc(sizeof(struct config_group *) * 3,
 				GFP_KERNEL);
 	if (!ml_stat_grp->default_groups) {
 		pr_err("Unable to allocate ml_stat_grp->default_groups\n");
@@ -734,14 +733,12 @@ static int target_fabric_port_link(
 	struct config_item *se_dev_ci)
 {
 	struct config_item *tpg_ci;
-	struct se_device *dev;
 	struct se_lun *lun = container_of(to_config_group(lun_ci),
 				struct se_lun, lun_group);
 	struct se_lun *lun_p;
 	struct se_portal_group *se_tpg;
-	struct se_subsystem_dev *se_dev = container_of(
-				to_config_group(se_dev_ci), struct se_subsystem_dev,
-				se_dev_group);
+	struct se_device *dev =
+		container_of(to_config_group(se_dev_ci), struct se_device, dev_group);
 	struct target_fabric_configfs *tf;
 	int ret;
 
@@ -755,14 +752,6 @@ static int target_fabric_port_link(
 		return -EEXIST;
 	}
 
-	dev = se_dev->se_dev_ptr;
-	if (!dev) {
-		pr_err("Unable to locate struct se_device pointer from"
-			" %s\n", config_item_name(se_dev_ci));
-		ret = -ENODEV;
-		goto out;
-	}
-
 	lun_p = core_dev_add_lun(se_tpg, dev, lun->unpacked_lun);
 	if (IS_ERR(lun_p)) {
 		pr_err("core_dev_add_lun() failed\n");
@@ -869,7 +858,7 @@ static struct config_group *target_fabric_make_lun(
 		return ERR_PTR(-EINVAL);
 
 	lun_cg = &lun->lun_group;
-	lun_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
+	lun_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2,
 				GFP_KERNEL);
 	if (!lun_cg->default_groups) {
 		pr_err("Unable to allocate lun_cg->default_groups\n");
diff --git a/drivers/target/target_core_fabric_lib.c b/drivers/target/target_core_fabric_lib.c
index e460d62..687b0b0 100644
--- a/drivers/target/target_core_fabric_lib.c
+++ b/drivers/target/target_core_fabric_lib.c
@@ -4,8 +4,7 @@
  * This file contains generic high level protocol identifier and PR
  * handlers for TCM fabric modules
  *
- * Copyright (c) 2010 Rising Tide Systems, Inc.
- * Copyright (c) 2010 Linux-iSCSI.org
+ * (c) Copyright 2010-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@linux-iscsi.org>
  *
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index 0360383..8f6dae0 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -3,10 +3,7 @@
  *
  * This file contains the Storage Engine <-> FILEIO transport specific functions
  *
- * Copyright (c) 2005 PyX Technologies, Inc.
- * Copyright (c) 2005-2006 SBE, Inc.  All Rights Reserved.
- * Copyright (c) 2007-2010 Rising Tide Systems
- * Copyright (c) 2008-2010 Linux-iSCSI.org
+ * (c) Copyright 2005-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@kernel.org>
  *
@@ -41,7 +38,10 @@
 
 #include "target_core_file.h"
 
-static struct se_subsystem_api fileio_template;
+static inline struct fd_dev *FD_DEV(struct se_device *dev)
+{
+	return container_of(dev, struct fd_dev, dev);
+}
 
 /*	fd_attach_hba(): (Part of se_subsystem_api_t template)
  *
@@ -82,7 +82,7 @@ static void fd_detach_hba(struct se_hba *hba)
 	hba->hba_ptr = NULL;
 }
 
-static void *fd_allocate_virtdevice(struct se_hba *hba, const char *name)
+static struct se_device *fd_alloc_device(struct se_hba *hba, const char *name)
 {
 	struct fd_dev *fd_dev;
 	struct fd_host *fd_host = hba->hba_ptr;
@@ -97,34 +97,28 @@ static void *fd_allocate_virtdevice(struct se_hba *hba, const char *name)
 
 	pr_debug("FILEIO: Allocated fd_dev for %p\n", name);
 
-	return fd_dev;
+	return &fd_dev->dev;
 }
 
-/*	fd_create_virtdevice(): (Part of se_subsystem_api_t template)
- *
- *
- */
-static struct se_device *fd_create_virtdevice(
-	struct se_hba *hba,
-	struct se_subsystem_dev *se_dev,
-	void *p)
+static int fd_configure_device(struct se_device *dev)
 {
-	struct se_device *dev;
-	struct se_dev_limits dev_limits;
-	struct queue_limits *limits;
-	struct fd_dev *fd_dev = p;
-	struct fd_host *fd_host = hba->hba_ptr;
+	struct fd_dev *fd_dev = FD_DEV(dev);
+	struct fd_host *fd_host = dev->se_hba->hba_ptr;
 	struct file *file;
 	struct inode *inode = NULL;
-	int dev_flags = 0, flags, ret = -EINVAL;
+	int flags, ret = -EINVAL;
 
-	memset(&dev_limits, 0, sizeof(struct se_dev_limits));
+	if (!(fd_dev->fbd_flags & FBDF_HAS_PATH)) {
+		pr_err("Missing fd_dev_name=\n");
+		return -EINVAL;
+	}
 
 	/*
 	 * Use O_DSYNC by default instead of O_SYNC to forgo syncing
 	 * of pure timestamp updates.
 	 */
 	flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC;
+
 	/*
 	 * Optionally allow fd_buffered_io=1 to be enabled for people
 	 * who want use the fs buffer cache as an WriteCache mechanism.
@@ -154,22 +148,17 @@ static struct se_device *fd_create_virtdevice(
 	 */
 	inode = file->f_mapping->host;
 	if (S_ISBLK(inode->i_mode)) {
-		struct request_queue *q;
+		struct request_queue *q = bdev_get_queue(inode->i_bdev);
 		unsigned long long dev_size;
-		/*
-		 * Setup the local scope queue_limits from struct request_queue->limits
-		 * to pass into transport_add_device_to_core_hba() as struct se_dev_limits.
-		 */
-		q = bdev_get_queue(inode->i_bdev);
-		limits = &dev_limits.limits;
-		limits->logical_block_size = bdev_logical_block_size(inode->i_bdev);
-		limits->max_hw_sectors = queue_max_hw_sectors(q);
-		limits->max_sectors = queue_max_sectors(q);
+
+		dev->dev_attrib.hw_block_size =
+			bdev_logical_block_size(inode->i_bdev);
+		dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q);
+
 		/*
 		 * Determine the number of bytes from i_size_read() minus
 		 * one (1) logical sector from underlying struct block_device
 		 */
-		fd_dev->fd_block_size = bdev_logical_block_size(inode->i_bdev);
 		dev_size = (i_size_read(file->f_mapping->host) -
 				       fd_dev->fd_block_size);
 
@@ -185,26 +174,18 @@ static struct se_device *fd_create_virtdevice(
 			goto fail;
 		}
 
-		limits = &dev_limits.limits;
-		limits->logical_block_size = FD_BLOCKSIZE;
-		limits->max_hw_sectors = FD_MAX_SECTORS;
-		limits->max_sectors = FD_MAX_SECTORS;
-		fd_dev->fd_block_size = FD_BLOCKSIZE;
+		dev->dev_attrib.hw_block_size = FD_BLOCKSIZE;
+		dev->dev_attrib.hw_max_sectors = FD_MAX_SECTORS;
 	}
 
-	dev_limits.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH;
-	dev_limits.queue_depth = FD_DEVICE_QUEUE_DEPTH;
+	fd_dev->fd_block_size = dev->dev_attrib.hw_block_size;
 
-	dev = transport_add_device_to_core_hba(hba, &fileio_template,
-				se_dev, dev_flags, fd_dev,
-				&dev_limits, "FILEIO", FD_VERSION);
-	if (!dev)
-		goto fail;
+	dev->dev_attrib.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH;
 
 	if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) {
 		pr_debug("FILEIO: Forcing setting of emulate_write_cache=1"
 			" with FDBD_HAS_BUFFERED_IO_WCE\n");
-		dev->se_sub_dev->se_dev_attrib.emulate_write_cache = 1;
+		dev->dev_attrib.emulate_write_cache = 1;
 	}
 
 	fd_dev->fd_dev_id = fd_host->fd_host_dev_id_count++;
@@ -214,22 +195,18 @@ static struct se_device *fd_create_virtdevice(
 		" %llu total bytes\n", fd_host->fd_host_id, fd_dev->fd_dev_id,
 			fd_dev->fd_dev_name, fd_dev->fd_dev_size);
 
-	return dev;
+	return 0;
 fail:
 	if (fd_dev->fd_file) {
 		filp_close(fd_dev->fd_file, NULL);
 		fd_dev->fd_file = NULL;
 	}
-	return ERR_PTR(ret);
+	return ret;
 }
 
-/*	fd_free_device(): (Part of se_subsystem_api_t template)
- *
- *
- */
-static void fd_free_device(void *p)
+static void fd_free_device(struct se_device *dev)
 {
-	struct fd_dev *fd_dev = p;
+	struct fd_dev *fd_dev = FD_DEV(dev);
 
 	if (fd_dev->fd_file) {
 		filp_close(fd_dev->fd_file, NULL);
@@ -243,13 +220,12 @@ static int fd_do_readv(struct se_cmd *cmd, struct scatterlist *sgl,
 		u32 sgl_nents)
 {
 	struct se_device *se_dev = cmd->se_dev;
-	struct fd_dev *dev = se_dev->dev_ptr;
+	struct fd_dev *dev = FD_DEV(se_dev);
 	struct file *fd = dev->fd_file;
 	struct scatterlist *sg;
 	struct iovec *iov;
 	mm_segment_t old_fs;
-	loff_t pos = (cmd->t_task_lba *
-		      se_dev->se_sub_dev->se_dev_attrib.block_size);
+	loff_t pos = (cmd->t_task_lba * se_dev->dev_attrib.block_size);
 	int ret = 0, i;
 
 	iov = kzalloc(sizeof(struct iovec) * sgl_nents, GFP_KERNEL);
@@ -296,13 +272,12 @@ static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl,
 		u32 sgl_nents)
 {
 	struct se_device *se_dev = cmd->se_dev;
-	struct fd_dev *dev = se_dev->dev_ptr;
+	struct fd_dev *dev = FD_DEV(se_dev);
 	struct file *fd = dev->fd_file;
 	struct scatterlist *sg;
 	struct iovec *iov;
 	mm_segment_t old_fs;
-	loff_t pos = (cmd->t_task_lba *
-		      se_dev->se_sub_dev->se_dev_attrib.block_size);
+	loff_t pos = (cmd->t_task_lba * se_dev->dev_attrib.block_size);
 	int ret, i = 0;
 
 	iov = kzalloc(sizeof(struct iovec) * sgl_nents, GFP_KERNEL);
@@ -331,10 +306,11 @@ static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl,
 	return 1;
 }
 
-static int fd_execute_sync_cache(struct se_cmd *cmd)
+static sense_reason_t
+fd_execute_sync_cache(struct se_cmd *cmd)
 {
 	struct se_device *dev = cmd->se_dev;
-	struct fd_dev *fd_dev = dev->dev_ptr;
+	struct fd_dev *fd_dev = FD_DEV(dev);
 	int immed = (cmd->t_task_cdb[1] & 0x2);
 	loff_t start, end;
 	int ret;
@@ -353,7 +329,7 @@ static int fd_execute_sync_cache(struct se_cmd *cmd)
 		start = 0;
 		end = LLONG_MAX;
 	} else {
-		start = cmd->t_task_lba * dev->se_sub_dev->se_dev_attrib.block_size;
+		start = cmd->t_task_lba * dev->dev_attrib.block_size;
 		if (cmd->data_length)
 			end = start + cmd->data_length;
 		else
@@ -367,17 +343,16 @@ static int fd_execute_sync_cache(struct se_cmd *cmd)
 	if (immed)
 		return 0;
 
-	if (ret) {
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+	if (ret)
 		target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION);
-	} else {
+	else
 		target_complete_cmd(cmd, SAM_STAT_GOOD);
-	}
 
 	return 0;
 }
 
-static int fd_execute_rw(struct se_cmd *cmd)
+static sense_reason_t
+fd_execute_rw(struct se_cmd *cmd)
 {
 	struct scatterlist *sgl = cmd->t_data_sg;
 	u32 sgl_nents = cmd->t_data_nents;
@@ -399,21 +374,20 @@ static int fd_execute_rw(struct se_cmd *cmd)
 		 * Allow this to happen independent of WCE=0 setting.
 		 */
 		if (ret > 0 &&
-		    dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 &&
+		    dev->dev_attrib.emulate_fua_write > 0 &&
 		    (cmd->se_cmd_flags & SCF_FUA)) {
-			struct fd_dev *fd_dev = dev->dev_ptr;
+			struct fd_dev *fd_dev = FD_DEV(dev);
 			loff_t start = cmd->t_task_lba *
-				dev->se_sub_dev->se_dev_attrib.block_size;
+				dev->dev_attrib.block_size;
 			loff_t end = start + cmd->data_length;
 
 			vfs_fsync_range(fd_dev->fd_file, start, end, 1);
 		}
 	}
 
-	if (ret < 0) {
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		return ret;
-	}
+	if (ret < 0)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
 	if (ret)
 		target_complete_cmd(cmd, SAM_STAT_GOOD);
 	return 0;
@@ -430,12 +404,10 @@ static match_table_t tokens = {
 	{Opt_err, NULL}
 };
 
-static ssize_t fd_set_configfs_dev_params(
-	struct se_hba *hba,
-	struct se_subsystem_dev *se_dev,
-	const char *page, ssize_t count)
+static ssize_t fd_set_configfs_dev_params(struct se_device *dev,
+		const char *page, ssize_t count)
 {
-	struct fd_dev *fd_dev = se_dev->se_dev_su_ptr;
+	struct fd_dev *fd_dev = FD_DEV(dev);
 	char *orig, *ptr, *arg_p, *opts;
 	substring_t args[MAX_OPT_ARGS];
 	int ret = 0, arg, token;
@@ -502,24 +474,9 @@ out:
 	return (!ret) ? count : ret;
 }
 
-static ssize_t fd_check_configfs_dev_params(struct se_hba *hba, struct se_subsystem_dev *se_dev)
-{
-	struct fd_dev *fd_dev = se_dev->se_dev_su_ptr;
-
-	if (!(fd_dev->fbd_flags & FBDF_HAS_PATH)) {
-		pr_err("Missing fd_dev_name=\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static ssize_t fd_show_configfs_dev_params(
-	struct se_hba *hba,
-	struct se_subsystem_dev *se_dev,
-	char *b)
+static ssize_t fd_show_configfs_dev_params(struct se_device *dev, char *b)
 {
-	struct fd_dev *fd_dev = se_dev->se_dev_su_ptr;
+	struct fd_dev *fd_dev = FD_DEV(dev);
 	ssize_t bl = 0;
 
 	bl = sprintf(b + bl, "TCM FILEIO ID: %u", fd_dev->fd_dev_id);
@@ -530,27 +487,9 @@ static ssize_t fd_show_configfs_dev_params(
 	return bl;
 }
 
-/*	fd_get_device_rev(): (Part of se_subsystem_api_t template)
- *
- *
- */
-static u32 fd_get_device_rev(struct se_device *dev)
-{
-	return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */
-}
-
-/*	fd_get_device_type(): (Part of se_subsystem_api_t template)
- *
- *
- */
-static u32 fd_get_device_type(struct se_device *dev)
-{
-	return TYPE_DISK;
-}
-
 static sector_t fd_get_blocks(struct se_device *dev)
 {
-	struct fd_dev *fd_dev = dev->dev_ptr;
+	struct fd_dev *fd_dev = FD_DEV(dev);
 	struct file *f = fd_dev->fd_file;
 	struct inode *i = f->f_mapping->host;
 	unsigned long long dev_size;
@@ -564,34 +503,35 @@ static sector_t fd_get_blocks(struct se_device *dev)
 	else
 		dev_size = fd_dev->fd_dev_size;
 
-	return div_u64(dev_size, dev->se_sub_dev->se_dev_attrib.block_size);
+	return div_u64(dev_size, dev->dev_attrib.block_size);
 }
 
-static struct spc_ops fd_spc_ops = {
+static struct sbc_ops fd_sbc_ops = {
 	.execute_rw		= fd_execute_rw,
 	.execute_sync_cache	= fd_execute_sync_cache,
 };
 
-static int fd_parse_cdb(struct se_cmd *cmd)
+static sense_reason_t
+fd_parse_cdb(struct se_cmd *cmd)
 {
-	return sbc_parse_cdb(cmd, &fd_spc_ops);
+	return sbc_parse_cdb(cmd, &fd_sbc_ops);
 }
 
 static struct se_subsystem_api fileio_template = {
 	.name			= "fileio",
+	.inquiry_prod		= "FILEIO",
+	.inquiry_rev		= FD_VERSION,
 	.owner			= THIS_MODULE,
 	.transport_type		= TRANSPORT_PLUGIN_VHBA_PDEV,
 	.attach_hba		= fd_attach_hba,
 	.detach_hba		= fd_detach_hba,
-	.allocate_virtdevice	= fd_allocate_virtdevice,
-	.create_virtdevice	= fd_create_virtdevice,
+	.alloc_device		= fd_alloc_device,
+	.configure_device	= fd_configure_device,
 	.free_device		= fd_free_device,
 	.parse_cdb		= fd_parse_cdb,
-	.check_configfs_dev_params = fd_check_configfs_dev_params,
 	.set_configfs_dev_params = fd_set_configfs_dev_params,
 	.show_configfs_dev_params = fd_show_configfs_dev_params,
-	.get_device_rev		= fd_get_device_rev,
-	.get_device_type	= fd_get_device_type,
+	.get_device_type	= sbc_get_device_type,
 	.get_blocks		= fd_get_blocks,
 };
 
diff --git a/drivers/target/target_core_file.h b/drivers/target/target_core_file.h
index 876ae53..bc02b01 100644
--- a/drivers/target/target_core_file.h
+++ b/drivers/target/target_core_file.h
@@ -17,6 +17,8 @@
 #define FDBD_HAS_BUFFERED_IO_WCE 0x04
 
 struct fd_dev {
+	struct se_device dev;
+
 	u32		fbd_flags;
 	unsigned char	fd_dev_name[FD_MAX_DEV_NAME];
 	/* Unique Ramdisk Device ID in Ramdisk HBA */
diff --git a/drivers/target/target_core_hba.c b/drivers/target/target_core_hba.c
index 3dd1bd4..d2616cd 100644
--- a/drivers/target/target_core_hba.c
+++ b/drivers/target/target_core_hba.c
@@ -3,10 +3,7 @@
  *
  * This file contains the TCM HBA Transport related functions.
  *
- * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc.
- * Copyright (c) 2005, 2006, 2007 SBE, Inc.
- * Copyright (c) 2007-2010 Rising Tide Systems
- * Copyright (c) 2008-2010 Linux-iSCSI.org
+ * (c) Copyright 2003-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@kernel.org>
  *
@@ -113,7 +110,6 @@ core_alloc_hba(const char *plugin_name, u32 plugin_dep_id, u32 hba_flags)
 		return ERR_PTR(-ENOMEM);
 	}
 
-	INIT_LIST_HEAD(&hba->hba_dev_list);
 	spin_lock_init(&hba->device_lock);
 	mutex_init(&hba->hba_access_mutex);
 
@@ -152,8 +148,7 @@ out_free_hba:
 int
 core_delete_hba(struct se_hba *hba)
 {
-	if (!list_empty(&hba->hba_dev_list))
-		dump_stack();
+	WARN_ON(hba->dev_count);
 
 	hba->transport->detach_hba(hba);
 
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 57d7674..b526d23 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -4,10 +4,7 @@
  * This file contains the Storage Engine  <-> Linux BlockIO transport
  * specific functions.
  *
- * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc.
- * Copyright (c) 2005, 2006, 2007 SBE, Inc.
- * Copyright (c) 2007-2010 Rising Tide Systems
- * Copyright (c) 2008-2010 Linux-iSCSI.org
+ * (c) Copyright 2003-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@kernel.org>
  *
@@ -50,9 +47,13 @@
 #define IBLOCK_MAX_BIO_PER_TASK	 32	/* max # of bios to submit at a time */
 #define IBLOCK_BIO_POOL_SIZE	128
 
-static struct se_subsystem_api iblock_template;
+static inline struct iblock_dev *IBLOCK_DEV(struct se_device *dev)
+{
+	return container_of(dev, struct iblock_dev, dev);
+}
+
 
-static void iblock_bio_done(struct bio *, int);
+static struct se_subsystem_api iblock_template;
 
 /*	iblock_attach_hba(): (Part of se_subsystem_api_t template)
  *
@@ -70,7 +71,7 @@ static void iblock_detach_hba(struct se_hba *hba)
 {
 }
 
-static void *iblock_allocate_virtdevice(struct se_hba *hba, const char *name)
+static struct se_device *iblock_alloc_device(struct se_hba *hba, const char *name)
 {
 	struct iblock_dev *ib_dev = NULL;
 
@@ -82,40 +83,28 @@ static void *iblock_allocate_virtdevice(struct se_hba *hba, const char *name)
 
 	pr_debug( "IBLOCK: Allocated ib_dev for %s\n", name);
 
-	return ib_dev;
+	return &ib_dev->dev;
 }
 
-static struct se_device *iblock_create_virtdevice(
-	struct se_hba *hba,
-	struct se_subsystem_dev *se_dev,
-	void *p)
+static int iblock_configure_device(struct se_device *dev)
 {
-	struct iblock_dev *ib_dev = p;
-	struct se_device *dev;
-	struct se_dev_limits dev_limits;
-	struct block_device *bd = NULL;
+	struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
 	struct request_queue *q;
-	struct queue_limits *limits;
-	u32 dev_flags = 0;
+	struct block_device *bd = NULL;
 	fmode_t mode;
-	int ret = -EINVAL;
+	int ret = -ENOMEM;
 
-	if (!ib_dev) {
-		pr_err("Unable to locate struct iblock_dev parameter\n");
-		return ERR_PTR(ret);
+	if (!(ib_dev->ibd_flags & IBDF_HAS_UDEV_PATH)) {
+		pr_err("Missing udev_path= parameters for IBLOCK\n");
+		return -EINVAL;
 	}
-	memset(&dev_limits, 0, sizeof(struct se_dev_limits));
 
 	ib_dev->ibd_bio_set = bioset_create(IBLOCK_BIO_POOL_SIZE, 0);
 	if (!ib_dev->ibd_bio_set) {
-		pr_err("IBLOCK: Unable to create bioset()\n");
-		return ERR_PTR(-ENOMEM);
+		pr_err("IBLOCK: Unable to create bioset\n");
+		goto out;
 	}
-	pr_debug("IBLOCK: Created bio_set()\n");
-	/*
-	 * iblock_check_configfs_dev_params() ensures that ib_dev->ibd_udev_path
-	 * must already have been set in order for echo 1 > $HBA/$DEV/enable to run.
-	 */
+
 	pr_debug( "IBLOCK: Claiming struct block_device: %s\n",
 			ib_dev->ibd_udev_path);
 
@@ -126,27 +115,15 @@ static struct se_device *iblock_create_virtdevice(
 	bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev);
 	if (IS_ERR(bd)) {
 		ret = PTR_ERR(bd);
-		goto failed;
+		goto out_free_bioset;
 	}
-	/*
-	 * Setup the local scope queue_limits from struct request_queue->limits
-	 * to pass into transport_add_device_to_core_hba() as struct se_dev_limits.
-	 */
-	q = bdev_get_queue(bd);
-	limits = &dev_limits.limits;
-	limits->logical_block_size = bdev_logical_block_size(bd);
-	limits->max_hw_sectors = UINT_MAX;
-	limits->max_sectors = UINT_MAX;
-	dev_limits.hw_queue_depth = q->nr_requests;
-	dev_limits.queue_depth = q->nr_requests;
-
 	ib_dev->ibd_bd = bd;
 
-	dev = transport_add_device_to_core_hba(hba,
-			&iblock_template, se_dev, dev_flags, ib_dev,
-			&dev_limits, "IBLOCK", IBLOCK_VERSION);
-	if (!dev)
-		goto failed;
+	q = bdev_get_queue(bd);
+
+	dev->dev_attrib.hw_block_size = bdev_logical_block_size(bd);
+	dev->dev_attrib.hw_max_sectors = UINT_MAX;
+	dev->dev_attrib.hw_queue_depth = q->nr_requests;
 
 	/*
 	 * Check if the underlying struct block_device request_queue supports
@@ -154,38 +131,41 @@ static struct se_device *iblock_create_virtdevice(
 	 * in ATA and we need to set TPE=1
 	 */
 	if (blk_queue_discard(q)) {
-		dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count =
+		dev->dev_attrib.max_unmap_lba_count =
 				q->limits.max_discard_sectors;
+
 		/*
 		 * Currently hardcoded to 1 in Linux/SCSI code..
 		 */
-		dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count = 1;
-		dev->se_sub_dev->se_dev_attrib.unmap_granularity =
+		dev->dev_attrib.max_unmap_block_desc_count = 1;
+		dev->dev_attrib.unmap_granularity =
 				q->limits.discard_granularity >> 9;
-		dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment =
+		dev->dev_attrib.unmap_granularity_alignment =
 				q->limits.discard_alignment;
 
 		pr_debug("IBLOCK: BLOCK Discard support available,"
 				" disabled by default\n");
 	}
+	/*
+	 * Enable write same emulation for IBLOCK and use 0xFFFF as
+	 * the smaller WRITE_SAME(10) only has a two-byte block count.
+	 */
+	dev->dev_attrib.max_write_same_len = 0xFFFF;
 
 	if (blk_queue_nonrot(q))
-		dev->se_sub_dev->se_dev_attrib.is_nonrot = 1;
-
-	return dev;
+		dev->dev_attrib.is_nonrot = 1;
+	return 0;
 
-failed:
-	if (ib_dev->ibd_bio_set) {
-		bioset_free(ib_dev->ibd_bio_set);
-		ib_dev->ibd_bio_set = NULL;
-	}
-	ib_dev->ibd_bd = NULL;
-	return ERR_PTR(ret);
+out_free_bioset:
+	bioset_free(ib_dev->ibd_bio_set);
+	ib_dev->ibd_bio_set = NULL;
+out:
+	return ret;
 }
 
-static void iblock_free_device(void *p)
+static void iblock_free_device(struct se_device *dev)
 {
-	struct iblock_dev *ib_dev = p;
+	struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
 
 	if (ib_dev->ibd_bd != NULL)
 		blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL);
@@ -203,12 +183,12 @@ static unsigned long long iblock_emulate_read_cap_with_block_size(
 					bdev_logical_block_size(bd)) - 1);
 	u32 block_size = bdev_logical_block_size(bd);
 
-	if (block_size == dev->se_sub_dev->se_dev_attrib.block_size)
+	if (block_size == dev->dev_attrib.block_size)
 		return blocks_long;
 
 	switch (block_size) {
 	case 4096:
-		switch (dev->se_sub_dev->se_dev_attrib.block_size) {
+		switch (dev->dev_attrib.block_size) {
 		case 2048:
 			blocks_long <<= 1;
 			break;
@@ -222,7 +202,7 @@ static unsigned long long iblock_emulate_read_cap_with_block_size(
 		}
 		break;
 	case 2048:
-		switch (dev->se_sub_dev->se_dev_attrib.block_size) {
+		switch (dev->dev_attrib.block_size) {
 		case 4096:
 			blocks_long >>= 1;
 			break;
@@ -237,7 +217,7 @@ static unsigned long long iblock_emulate_read_cap_with_block_size(
 		}
 		break;
 	case 1024:
-		switch (dev->se_sub_dev->se_dev_attrib.block_size) {
+		switch (dev->dev_attrib.block_size) {
 		case 4096:
 			blocks_long >>= 2;
 			break;
@@ -252,7 +232,7 @@ static unsigned long long iblock_emulate_read_cap_with_block_size(
 		}
 		break;
 	case 512:
-		switch (dev->se_sub_dev->se_dev_attrib.block_size) {
+		switch (dev->dev_attrib.block_size) {
 		case 4096:
 			blocks_long >>= 3;
 			break;
@@ -273,6 +253,87 @@ static unsigned long long iblock_emulate_read_cap_with_block_size(
 	return blocks_long;
 }
 
+static void iblock_complete_cmd(struct se_cmd *cmd)
+{
+	struct iblock_req *ibr = cmd->priv;
+	u8 status;
+
+	if (!atomic_dec_and_test(&ibr->pending))
+		return;
+
+	if (atomic_read(&ibr->ib_bio_err_cnt))
+		status = SAM_STAT_CHECK_CONDITION;
+	else
+		status = SAM_STAT_GOOD;
+
+	target_complete_cmd(cmd, status);
+	kfree(ibr);
+}
+
+static void iblock_bio_done(struct bio *bio, int err)
+{
+	struct se_cmd *cmd = bio->bi_private;
+	struct iblock_req *ibr = cmd->priv;
+
+	/*
+	 * Set -EIO if !BIO_UPTODATE and the passed is still err=0
+	 */
+	if (!test_bit(BIO_UPTODATE, &bio->bi_flags) && !err)
+		err = -EIO;
+
+	if (err != 0) {
+		pr_err("test_bit(BIO_UPTODATE) failed for bio: %p,"
+			" err: %d\n", bio, err);
+		/*
+		 * Bump the ib_bio_err_cnt and release bio.
+		 */
+		atomic_inc(&ibr->ib_bio_err_cnt);
+		smp_mb__after_atomic_inc();
+	}
+
+	bio_put(bio);
+
+	iblock_complete_cmd(cmd);
+}
+
+static struct bio *
+iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num)
+{
+	struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev);
+	struct bio *bio;
+
+	/*
+	 * Only allocate as many vector entries as the bio code allows us to,
+	 * we'll loop later on until we have handled the whole request.
+	 */
+	if (sg_num > BIO_MAX_PAGES)
+		sg_num = BIO_MAX_PAGES;
+
+	bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set);
+	if (!bio) {
+		pr_err("Unable to allocate memory for bio\n");
+		return NULL;
+	}
+
+	bio->bi_bdev = ib_dev->ibd_bd;
+	bio->bi_private = cmd;
+	bio->bi_end_io = &iblock_bio_done;
+	bio->bi_sector = lba;
+
+	return bio;
+}
+
+static void iblock_submit_bios(struct bio_list *list, int rw)
+{
+	struct blk_plug plug;
+	struct bio *bio;
+
+	blk_start_plug(&plug);
+	while ((bio = bio_list_pop(list)))
+		submit_bio(rw, bio);
+	blk_finish_plug(&plug);
+}
+
 static void iblock_end_io_flush(struct bio *bio, int err)
 {
 	struct se_cmd *cmd = bio->bi_private;
@@ -281,13 +342,10 @@ static void iblock_end_io_flush(struct bio *bio, int err)
 		pr_err("IBLOCK: cache flush failed: %d\n", err);
 
 	if (cmd) {
-		if (err) {
-			cmd->scsi_sense_reason =
-				TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+		if (err)
 			target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION);
-		} else {
+		else
 			target_complete_cmd(cmd, SAM_STAT_GOOD);
-		}
 	}
 
 	bio_put(bio);
@@ -297,9 +355,10 @@ static void iblock_end_io_flush(struct bio *bio, int err)
  * Implement SYCHRONIZE CACHE.  Note that we can't handle lba ranges and must
  * always flush the whole cache.
  */
-static int iblock_execute_sync_cache(struct se_cmd *cmd)
+static sense_reason_t
+iblock_execute_sync_cache(struct se_cmd *cmd)
 {
-	struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr;
+	struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev);
 	int immed = (cmd->t_task_cdb[1] & 0x2);
 	struct bio *bio;
 
@@ -319,25 +378,27 @@ static int iblock_execute_sync_cache(struct se_cmd *cmd)
 	return 0;
 }
 
-static int iblock_execute_unmap(struct se_cmd *cmd)
+static sense_reason_t
+iblock_execute_unmap(struct se_cmd *cmd)
 {
 	struct se_device *dev = cmd->se_dev;
-	struct iblock_dev *ibd = dev->dev_ptr;
+	struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
 	unsigned char *buf, *ptr = NULL;
 	sector_t lba;
 	int size;
 	u32 range;
-	int ret = 0;
-	int dl, bd_dl;
+	sense_reason_t ret = 0;
+	int dl, bd_dl, err;
 
 	if (cmd->data_length < 8) {
 		pr_warn("UNMAP parameter list length %u too small\n",
 			cmd->data_length);
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		return -EINVAL;
+		return TCM_INVALID_PARAMETER_LIST;
 	}
 
 	buf = transport_kmap_data_sg(cmd);
+	if (!buf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
 	dl = get_unaligned_be16(&buf[0]);
 	bd_dl = get_unaligned_be16(&buf[2]);
@@ -349,9 +410,8 @@ static int iblock_execute_unmap(struct se_cmd *cmd)
 	else
 		size = bd_dl;
 
-	if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) {
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		ret = -EINVAL;
+	if (size / 16 > dev->dev_attrib.max_unmap_block_desc_count) {
+		ret = TCM_INVALID_PARAMETER_LIST;
 		goto err;
 	}
 
@@ -366,23 +426,22 @@ static int iblock_execute_unmap(struct se_cmd *cmd)
 		pr_debug("UNMAP: Using lba: %llu and range: %u\n",
 				 (unsigned long long)lba, range);
 
-		if (range > dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count) {
-			cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-			ret = -EINVAL;
+		if (range > dev->dev_attrib.max_unmap_lba_count) {
+			ret = TCM_INVALID_PARAMETER_LIST;
 			goto err;
 		}
 
 		if (lba + range > dev->transport->get_blocks(dev) + 1) {
-			cmd->scsi_sense_reason = TCM_ADDRESS_OUT_OF_RANGE;
-			ret = -EINVAL;
+			ret = TCM_ADDRESS_OUT_OF_RANGE;
 			goto err;
 		}
 
-		ret = blkdev_issue_discard(ibd->ibd_bd, lba, range,
+		err = blkdev_issue_discard(ib_dev->ibd_bd, lba, range,
 					   GFP_KERNEL, 0);
-		if (ret < 0) {
+		if (err < 0) {
 			pr_err("blkdev_issue_discard() failed: %d\n",
-					ret);
+					err);
+			ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 			goto err;
 		}
 
@@ -397,23 +456,86 @@ err:
 	return ret;
 }
 
-static int iblock_execute_write_same(struct se_cmd *cmd)
+static sense_reason_t
+iblock_execute_write_same_unmap(struct se_cmd *cmd)
 {
-	struct iblock_dev *ibd = cmd->se_dev->dev_ptr;
-	int ret;
-
-	ret = blkdev_issue_discard(ibd->ibd_bd, cmd->t_task_lba,
-				   spc_get_write_same_sectors(cmd), GFP_KERNEL,
-				   0);
-	if (ret < 0) {
-		pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n");
-		return ret;
+	struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev);
+	int rc;
+
+	rc = blkdev_issue_discard(ib_dev->ibd_bd, cmd->t_task_lba,
+			spc_get_write_same_sectors(cmd), GFP_KERNEL, 0);
+	if (rc < 0) {
+		pr_warn("blkdev_issue_discard() failed: %d\n", rc);
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	}
 
 	target_complete_cmd(cmd, GOOD);
 	return 0;
 }
 
+static sense_reason_t
+iblock_execute_write_same(struct se_cmd *cmd)
+{
+	struct iblock_req *ibr;
+	struct scatterlist *sg;
+	struct bio *bio;
+	struct bio_list list;
+	sector_t block_lba = cmd->t_task_lba;
+	sector_t sectors = spc_get_write_same_sectors(cmd);
+
+	sg = &cmd->t_data_sg[0];
+
+	if (cmd->t_data_nents > 1 ||
+	    sg->length != cmd->se_dev->dev_attrib.block_size) {
+		pr_err("WRITE_SAME: Illegal SGL t_data_nents: %u length: %u"
+			" block_size: %u\n", cmd->t_data_nents, sg->length,
+			cmd->se_dev->dev_attrib.block_size);
+		return TCM_INVALID_CDB_FIELD;
+	}
+
+	ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
+	if (!ibr)
+		goto fail;
+	cmd->priv = ibr;
+
+	bio = iblock_get_bio(cmd, block_lba, 1);
+	if (!bio)
+		goto fail_free_ibr;
+
+	bio_list_init(&list);
+	bio_list_add(&list, bio);
+
+	atomic_set(&ibr->pending, 1);
+
+	while (sectors) {
+		while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset)
+				!= sg->length) {
+
+			bio = iblock_get_bio(cmd, block_lba, 1);
+			if (!bio)
+				goto fail_put_bios;
+
+			atomic_inc(&ibr->pending);
+			bio_list_add(&list, bio);
+		}
+
+		/* Always in 512 byte units for Linux/Block */
+		block_lba += sg->length >> IBLOCK_LBA_SHIFT;
+		sectors -= 1;
+	}
+
+	iblock_submit_bios(&list, WRITE);
+	return 0;
+
+fail_put_bios:
+	while ((bio = bio_list_pop(&list)))
+		bio_put(bio);
+fail_free_ibr:
+	kfree(ibr);
+fail:
+	return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+}
+
 enum {
 	Opt_udev_path, Opt_readonly, Opt_force, Opt_err
 };
@@ -425,11 +547,10 @@ static match_table_t tokens = {
 	{Opt_err, NULL}
 };
 
-static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba,
-					       struct se_subsystem_dev *se_dev,
-					       const char *page, ssize_t count)
+static ssize_t iblock_set_configfs_dev_params(struct se_device *dev,
+		const char *page, ssize_t count)
 {
-	struct iblock_dev *ib_dev = se_dev->se_dev_su_ptr;
+	struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
 	char *orig, *ptr, *arg_p, *opts;
 	substring_t args[MAX_OPT_ARGS];
 	int ret = 0, token;
@@ -491,43 +612,26 @@ out:
 	return (!ret) ? count : ret;
 }
 
-static ssize_t iblock_check_configfs_dev_params(
-	struct se_hba *hba,
-	struct se_subsystem_dev *se_dev)
+static ssize_t iblock_show_configfs_dev_params(struct se_device *dev, char *b)
 {
-	struct iblock_dev *ibd = se_dev->se_dev_su_ptr;
-
-	if (!(ibd->ibd_flags & IBDF_HAS_UDEV_PATH)) {
-		pr_err("Missing udev_path= parameters for IBLOCK\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static ssize_t iblock_show_configfs_dev_params(
-	struct se_hba *hba,
-	struct se_subsystem_dev *se_dev,
-	char *b)
-{
-	struct iblock_dev *ibd = se_dev->se_dev_su_ptr;
-	struct block_device *bd = ibd->ibd_bd;
+	struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
+	struct block_device *bd = ib_dev->ibd_bd;
 	char buf[BDEVNAME_SIZE];
 	ssize_t bl = 0;
 
 	if (bd)
 		bl += sprintf(b + bl, "iBlock device: %s",
 				bdevname(bd, buf));
-	if (ibd->ibd_flags & IBDF_HAS_UDEV_PATH)
+	if (ib_dev->ibd_flags & IBDF_HAS_UDEV_PATH)
 		bl += sprintf(b + bl, "  UDEV PATH: %s",
-				ibd->ibd_udev_path);
-	bl += sprintf(b + bl, "  readonly: %d\n", ibd->ibd_readonly);
+				ib_dev->ibd_udev_path);
+	bl += sprintf(b + bl, "  readonly: %d\n", ib_dev->ibd_readonly);
 
 	bl += sprintf(b + bl, "        ");
 	if (bd) {
 		bl += sprintf(b + bl, "Major: %d Minor: %d  %s\n",
 			MAJOR(bd->bd_dev), MINOR(bd->bd_dev), (!bd->bd_contains) ?
-			"" : (bd->bd_holder == ibd) ?
+			"" : (bd->bd_holder == ib_dev) ?
 			"CLAIMED: IBLOCK" : "CLAIMED: OS");
 	} else {
 		bl += sprintf(b + bl, "Major: 0 Minor: 0\n");
@@ -536,61 +640,8 @@ static ssize_t iblock_show_configfs_dev_params(
 	return bl;
 }
 
-static void iblock_complete_cmd(struct se_cmd *cmd)
-{
-	struct iblock_req *ibr = cmd->priv;
-	u8 status;
-
-	if (!atomic_dec_and_test(&ibr->pending))
-		return;
-
-	if (atomic_read(&ibr->ib_bio_err_cnt))
-		status = SAM_STAT_CHECK_CONDITION;
-	else
-		status = SAM_STAT_GOOD;
-
-	target_complete_cmd(cmd, status);
-	kfree(ibr);
-}
-
-static struct bio *
-iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num)
-{
-	struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr;
-	struct bio *bio;
-
-	/*
-	 * Only allocate as many vector entries as the bio code allows us to,
-	 * we'll loop later on until we have handled the whole request.
-	 */
-	if (sg_num > BIO_MAX_PAGES)
-		sg_num = BIO_MAX_PAGES;
-
-	bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set);
-	if (!bio) {
-		pr_err("Unable to allocate memory for bio\n");
-		return NULL;
-	}
-
-	bio->bi_bdev = ib_dev->ibd_bd;
-	bio->bi_private = cmd;
-	bio->bi_end_io = &iblock_bio_done;
-	bio->bi_sector = lba;
-	return bio;
-}
-
-static void iblock_submit_bios(struct bio_list *list, int rw)
-{
-	struct blk_plug plug;
-	struct bio *bio;
-
-	blk_start_plug(&plug);
-	while ((bio = bio_list_pop(list)))
-		submit_bio(rw, bio);
-	blk_finish_plug(&plug);
-}
-
-static int iblock_execute_rw(struct se_cmd *cmd)
+static sense_reason_t
+iblock_execute_rw(struct se_cmd *cmd)
 {
 	struct scatterlist *sgl = cmd->t_data_sg;
 	u32 sgl_nents = cmd->t_data_nents;
@@ -611,8 +662,8 @@ static int iblock_execute_rw(struct se_cmd *cmd)
 		 * Force data to disk if we pretend to not have a volatile
 		 * write cache, or the initiator set the Force Unit Access bit.
 		 */
-		if (dev->se_sub_dev->se_dev_attrib.emulate_write_cache == 0 ||
-		    (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 &&
+		if (dev->dev_attrib.emulate_write_cache == 0 ||
+		    (dev->dev_attrib.emulate_fua_write > 0 &&
 		     (cmd->se_cmd_flags & SCF_FUA)))
 			rw = WRITE_FUA;
 		else
@@ -625,19 +676,18 @@ static int iblock_execute_rw(struct se_cmd *cmd)
 	 * Convert the blocksize advertised to the initiator to the 512 byte
 	 * units unconditionally used by the Linux block layer.
 	 */
-	if (dev->se_sub_dev->se_dev_attrib.block_size == 4096)
+	if (dev->dev_attrib.block_size == 4096)
 		block_lba = (cmd->t_task_lba << 3);
-	else if (dev->se_sub_dev->se_dev_attrib.block_size == 2048)
+	else if (dev->dev_attrib.block_size == 2048)
 		block_lba = (cmd->t_task_lba << 2);
-	else if (dev->se_sub_dev->se_dev_attrib.block_size == 1024)
+	else if (dev->dev_attrib.block_size == 1024)
 		block_lba = (cmd->t_task_lba << 1);
-	else if (dev->se_sub_dev->se_dev_attrib.block_size == 512)
+	else if (dev->dev_attrib.block_size == 512)
 		block_lba = cmd->t_task_lba;
 	else {
 		pr_err("Unsupported SCSI -> BLOCK LBA conversion:"
-				" %u\n", dev->se_sub_dev->se_dev_attrib.block_size);
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		return -ENOSYS;
+				" %u\n", dev->dev_attrib.block_size);
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	}
 
 	ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
@@ -697,83 +747,48 @@ fail_put_bios:
 		bio_put(bio);
 fail_free_ibr:
 	kfree(ibr);
-	cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 fail:
-	return -ENOMEM;
-}
-
-static u32 iblock_get_device_rev(struct se_device *dev)
-{
-	return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */
-}
-
-static u32 iblock_get_device_type(struct se_device *dev)
-{
-	return TYPE_DISK;
+	return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 }
 
 static sector_t iblock_get_blocks(struct se_device *dev)
 {
-	struct iblock_dev *ibd = dev->dev_ptr;
-	struct block_device *bd = ibd->ibd_bd;
+	struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
+	struct block_device *bd = ib_dev->ibd_bd;
 	struct request_queue *q = bdev_get_queue(bd);
 
 	return iblock_emulate_read_cap_with_block_size(dev, bd, q);
 }
 
-static void iblock_bio_done(struct bio *bio, int err)
-{
-	struct se_cmd *cmd = bio->bi_private;
-	struct iblock_req *ibr = cmd->priv;
-
-	/*
-	 * Set -EIO if !BIO_UPTODATE and the passed is still err=0
-	 */
-	if (!test_bit(BIO_UPTODATE, &bio->bi_flags) && !err)
-		err = -EIO;
-
-	if (err != 0) {
-		pr_err("test_bit(BIO_UPTODATE) failed for bio: %p,"
-			" err: %d\n", bio, err);
-		/*
-		 * Bump the ib_bio_err_cnt and release bio.
-		 */
-		atomic_inc(&ibr->ib_bio_err_cnt);
-		smp_mb__after_atomic_inc();
-	}
-
-	bio_put(bio);
-
-	iblock_complete_cmd(cmd);
-}
-
-static struct spc_ops iblock_spc_ops = {
+static struct sbc_ops iblock_sbc_ops = {
 	.execute_rw		= iblock_execute_rw,
 	.execute_sync_cache	= iblock_execute_sync_cache,
 	.execute_write_same	= iblock_execute_write_same,
+	.execute_write_same_unmap = iblock_execute_write_same_unmap,
 	.execute_unmap		= iblock_execute_unmap,
 };
 
-static int iblock_parse_cdb(struct se_cmd *cmd)
+static sense_reason_t
+iblock_parse_cdb(struct se_cmd *cmd)
 {
-	return sbc_parse_cdb(cmd, &iblock_spc_ops);
+	return sbc_parse_cdb(cmd, &iblock_sbc_ops);
 }
 
 static struct se_subsystem_api iblock_template = {
 	.name			= "iblock",
+	.inquiry_prod		= "IBLOCK",
+	.inquiry_rev		= IBLOCK_VERSION,
 	.owner			= THIS_MODULE,
 	.transport_type		= TRANSPORT_PLUGIN_VHBA_PDEV,
 	.attach_hba		= iblock_attach_hba,
 	.detach_hba		= iblock_detach_hba,
-	.allocate_virtdevice	= iblock_allocate_virtdevice,
-	.create_virtdevice	= iblock_create_virtdevice,
+	.alloc_device		= iblock_alloc_device,
+	.configure_device	= iblock_configure_device,
 	.free_device		= iblock_free_device,
 	.parse_cdb		= iblock_parse_cdb,
-	.check_configfs_dev_params = iblock_check_configfs_dev_params,
 	.set_configfs_dev_params = iblock_set_configfs_dev_params,
 	.show_configfs_dev_params = iblock_show_configfs_dev_params,
-	.get_device_rev		= iblock_get_device_rev,
-	.get_device_type	= iblock_get_device_type,
+	.get_device_type	= sbc_get_device_type,
 	.get_blocks		= iblock_get_blocks,
 };
 
diff --git a/drivers/target/target_core_iblock.h b/drivers/target/target_core_iblock.h
index 533627a..01c2afd 100644
--- a/drivers/target/target_core_iblock.h
+++ b/drivers/target/target_core_iblock.h
@@ -14,6 +14,7 @@ struct iblock_req {
 #define IBDF_HAS_UDEV_PATH		0x01
 
 struct iblock_dev {
+	struct se_device dev;
 	unsigned char ibd_udev_path[SE_UDEV_PATH_LEN];
 	u32	ibd_flags;
 	struct bio_set	*ibd_bio_set;
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
index 0fd4282..93e9c1f 100644
--- a/drivers/target/target_core_internal.h
+++ b/drivers/target/target_core_internal.h
@@ -19,18 +19,12 @@ int	core_dev_export(struct se_device *, struct se_portal_group *,
 		struct se_lun *);
 void	core_dev_unexport(struct se_device *, struct se_portal_group *,
 		struct se_lun *);
-int	target_report_luns(struct se_cmd *);
-void	se_release_device_for_hba(struct se_device *);
-void	se_release_vpd_for_dev(struct se_device *);
-int	se_free_virtual_device(struct se_device *, struct se_hba *);
-int	se_dev_check_online(struct se_device *);
-int	se_dev_check_shutdown(struct se_device *);
-void	se_dev_set_default_attribs(struct se_device *, struct se_dev_limits *);
 int	se_dev_set_task_timeout(struct se_device *, u32);
 int	se_dev_set_max_unmap_lba_count(struct se_device *, u32);
 int	se_dev_set_max_unmap_block_desc_count(struct se_device *, u32);
 int	se_dev_set_unmap_granularity(struct se_device *, u32);
 int	se_dev_set_unmap_granularity_alignment(struct se_device *, u32);
+int	se_dev_set_max_write_same_len(struct se_device *, u32);
 int	se_dev_set_emulate_dpo(struct se_device *, int);
 int	se_dev_set_emulate_fua_write(struct se_device *, int);
 int	se_dev_set_emulate_fua_read(struct se_device *, int);
@@ -60,6 +54,9 @@ void	core_dev_free_initiator_node_lun_acl(struct se_portal_group *,
 		struct se_lun_acl *lacl);
 int	core_dev_setup_virtual_lun0(void);
 void	core_dev_release_virtual_lun0(void);
+struct se_device *target_alloc_device(struct se_hba *hba, const char *name);
+int	target_configure_device(struct se_device *dev);
+void	target_free_device(struct se_device *);
 
 /* target_core_hba.c */
 struct se_hba *core_alloc_hba(const char *, u32, u32);
@@ -105,10 +102,11 @@ int	transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int);
 bool	target_stop_cmd(struct se_cmd *cmd, unsigned long *flags);
 int	transport_clear_lun_from_sessions(struct se_lun *);
 void	transport_send_task_abort(struct se_cmd *);
-int	target_cmd_size_check(struct se_cmd *cmd, unsigned int size);
+sense_reason_t	target_cmd_size_check(struct se_cmd *cmd, unsigned int size);
+void	target_qf_do_work(struct work_struct *work);
 
 /* target_core_stat.c */
-void	target_stat_setup_dev_default_groups(struct se_subsystem_dev *);
+void	target_stat_setup_dev_default_groups(struct se_device *);
 void	target_stat_setup_port_default_groups(struct se_lun *);
 void	target_stat_setup_mappedlun_default_groups(struct se_lun_acl *);
 
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index 8c323a9..e35dbf8 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -4,8 +4,7 @@
  * This file contains SPC-3 compliant persistent reservations and
  * legacy SPC-2 reservations with compatible reservation handling (CRH=1)
  *
- * Copyright (c) 2009, 2010 Rising Tide Systems
- * Copyright (c) 2009, 2010 Linux-iSCSI.org
+ * (c) Copyright 2009-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@kernel.org>
  *
@@ -68,49 +67,33 @@ int core_pr_dump_initiator_port(
 static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *,
 			struct t10_pr_registration *, int);
 
-static int core_scsi2_reservation_seq_non_holder(
-	struct se_cmd *cmd,
-	unsigned char *cdb,
-	u32 pr_reg_type)
+static sense_reason_t
+target_scsi2_reservation_check(struct se_cmd *cmd)
 {
-	switch (cdb[0]) {
+	struct se_device *dev = cmd->se_dev;
+	struct se_session *sess = cmd->se_sess;
+
+	switch (cmd->t_task_cdb[0]) {
 	case INQUIRY:
 	case RELEASE:
 	case RELEASE_10:
 		return 0;
 	default:
-		return 1;
+		break;
 	}
 
-	return 1;
-}
-
-static int core_scsi2_reservation_check(struct se_cmd *cmd, u32 *pr_reg_type)
-{
-	struct se_device *dev = cmd->se_dev;
-	struct se_session *sess = cmd->se_sess;
-	int ret;
-
-	if (!sess)
+	if (!dev->dev_reserved_node_acl || !sess)
 		return 0;
 
-	spin_lock(&dev->dev_reservation_lock);
-	if (!dev->dev_reserved_node_acl || !sess) {
-		spin_unlock(&dev->dev_reservation_lock);
-		return 0;
-	}
-	if (dev->dev_reserved_node_acl != sess->se_node_acl) {
-		spin_unlock(&dev->dev_reservation_lock);
-		return -EINVAL;
-	}
-	if (!(dev->dev_flags & DF_SPC2_RESERVATIONS_WITH_ISID)) {
-		spin_unlock(&dev->dev_reservation_lock);
-		return 0;
+	if (dev->dev_reserved_node_acl != sess->se_node_acl)
+		return TCM_RESERVATION_CONFLICT;
+
+	if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) {
+		if (dev->dev_res_bin_isid != sess->sess_bin_isid)
+			return TCM_RESERVATION_CONFLICT;
 	}
-	ret = (dev->dev_res_bin_isid == sess->sess_bin_isid) ? 0 : -EINVAL;
-	spin_unlock(&dev->dev_reservation_lock);
 
-	return ret;
+	return 0;
 }
 
 static struct t10_pr_registration *core_scsi3_locate_pr_reg(struct se_device *,
@@ -120,15 +103,11 @@ static void core_scsi3_put_pr_reg(struct t10_pr_registration *);
 static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd)
 {
 	struct se_session *se_sess = cmd->se_sess;
-	struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
+	struct se_device *dev = cmd->se_dev;
 	struct t10_pr_registration *pr_reg;
-	struct t10_reservation *pr_tmpl = &su_dev->t10_pr;
-	int crh = (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS);
+	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 	int conflict = 0;
 
-	if (!crh)
-		return -EINVAL;
-
 	pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl,
 			se_sess);
 	if (pr_reg) {
@@ -186,32 +165,28 @@ static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd)
 		pr_err("Received legacy SPC-2 RESERVE/RELEASE"
 			" while active SPC-3 registrations exist,"
 			" returning RESERVATION_CONFLICT\n");
-		cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
 		return -EBUSY;
 	}
 
 	return 0;
 }
 
-int target_scsi2_reservation_release(struct se_cmd *cmd)
+sense_reason_t
+target_scsi2_reservation_release(struct se_cmd *cmd)
 {
 	struct se_device *dev = cmd->se_dev;
 	struct se_session *sess = cmd->se_sess;
 	struct se_portal_group *tpg;
-	int ret = 0, rc;
+	int rc;
 
 	if (!sess || !sess->se_tpg)
 		goto out;
 	rc = target_check_scsi2_reservation_conflict(cmd);
 	if (rc == 1)
 		goto out;
-	else if (rc < 0) {
-		cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-		ret = -EINVAL;
-		goto out;
-	}
+	if (rc < 0)
+		return TCM_RESERVATION_CONFLICT;
 
-	ret = 0;
 	spin_lock(&dev->dev_reservation_lock);
 	if (!dev->dev_reserved_node_acl || !sess)
 		goto out_unlock;
@@ -223,10 +198,10 @@ int target_scsi2_reservation_release(struct se_cmd *cmd)
 		goto out_unlock;
 
 	dev->dev_reserved_node_acl = NULL;
-	dev->dev_flags &= ~DF_SPC2_RESERVATIONS;
-	if (dev->dev_flags & DF_SPC2_RESERVATIONS_WITH_ISID) {
+	dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS;
+	if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) {
 		dev->dev_res_bin_isid = 0;
-		dev->dev_flags &= ~DF_SPC2_RESERVATIONS_WITH_ISID;
+		dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS_WITH_ISID;
 	}
 	tpg = sess->se_tpg;
 	pr_debug("SCSI-2 Released reservation for %s LUN: %u ->"
@@ -237,25 +212,24 @@ int target_scsi2_reservation_release(struct se_cmd *cmd)
 out_unlock:
 	spin_unlock(&dev->dev_reservation_lock);
 out:
-	if (!ret)
-		target_complete_cmd(cmd, GOOD);
-	return ret;
+	target_complete_cmd(cmd, GOOD);
+	return 0;
 }
 
-int target_scsi2_reservation_reserve(struct se_cmd *cmd)
+sense_reason_t
+target_scsi2_reservation_reserve(struct se_cmd *cmd)
 {
 	struct se_device *dev = cmd->se_dev;
 	struct se_session *sess = cmd->se_sess;
 	struct se_portal_group *tpg;
-	int ret = 0, rc;
+	sense_reason_t ret = 0;
+	int rc;
 
 	if ((cmd->t_task_cdb[1] & 0x01) &&
 	    (cmd->t_task_cdb[1] & 0x02)) {
 		pr_err("LongIO and Obselete Bits set, returning"
 				" ILLEGAL_REQUEST\n");
-		cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-		ret = -EINVAL;
-		goto out;
+		return TCM_UNSUPPORTED_SCSI_OPCODE;
 	}
 	/*
 	 * This is currently the case for target_core_mod passthrough struct se_cmd
@@ -266,13 +240,10 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd)
 	rc = target_check_scsi2_reservation_conflict(cmd);
 	if (rc == 1)
 		goto out;
-	else if (rc < 0) {
-		cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-		ret = -EINVAL;
-		goto out;
-	}
 
-	ret = 0;
+	if (rc < 0)
+		return TCM_RESERVATION_CONFLICT;
+
 	tpg = sess->se_tpg;
 	spin_lock(&dev->dev_reservation_lock);
 	if (dev->dev_reserved_node_acl &&
@@ -286,16 +257,15 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd)
 			" from %s \n", cmd->se_lun->unpacked_lun,
 			cmd->se_deve->mapped_lun,
 			sess->se_node_acl->initiatorname);
-		cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-		ret = -EINVAL;
+		ret = TCM_RESERVATION_CONFLICT;
 		goto out_unlock;
 	}
 
 	dev->dev_reserved_node_acl = sess->se_node_acl;
-	dev->dev_flags |= DF_SPC2_RESERVATIONS;
+	dev->dev_reservation_flags |= DRF_SPC2_RESERVATIONS;
 	if (sess->sess_bin_isid != 0) {
 		dev->dev_res_bin_isid = sess->sess_bin_isid;
-		dev->dev_flags |= DF_SPC2_RESERVATIONS_WITH_ISID;
+		dev->dev_reservation_flags |= DRF_SPC2_RESERVATIONS_WITH_ISID;
 	}
 	pr_debug("SCSI-2 Reserved %s LUN: %u -> MAPPED LUN: %u"
 		" for %s\n", tpg->se_tpg_tfo->get_fabric_name(),
@@ -319,9 +289,9 @@ out:
  */
 static int core_scsi3_pr_seq_non_holder(
 	struct se_cmd *cmd,
-	unsigned char *cdb,
 	u32 pr_reg_type)
 {
+	unsigned char *cdb = cmd->t_task_cdb;
 	struct se_dev_entry *se_deve;
 	struct se_session *se_sess = cmd->se_sess;
 	int other_cdb = 0, ignore_reg;
@@ -330,17 +300,11 @@ static int core_scsi3_pr_seq_non_holder(
 	int we = 0; /* Write Exclusive */
 	int legacy = 0; /* Act like a legacy device and return
 			 * RESERVATION CONFLICT on some CDBs */
-	/*
-	 * A legacy SPC-2 reservation is being held.
-	 */
-	if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS)
-		return core_scsi2_reservation_seq_non_holder(cmd,
-					cdb, pr_reg_type);
 
 	se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun];
 	/*
 	 * Determine if the registration should be ignored due to
-	 * non-matching ISIDs in core_scsi3_pr_reservation_check().
+	 * non-matching ISIDs in target_scsi3_pr_reservation_check().
 	 */
 	ignore_reg = (pr_reg_type & 0x80000000);
 	if (ignore_reg)
@@ -563,10 +527,41 @@ static int core_scsi3_pr_seq_non_holder(
 	return 1; /* Conflict by default */
 }
 
+static sense_reason_t
+target_scsi3_pr_reservation_check(struct se_cmd *cmd)
+{
+	struct se_device *dev = cmd->se_dev;
+	struct se_session *sess = cmd->se_sess;
+	u32 pr_reg_type;
+
+	if (!dev->dev_pr_res_holder)
+		return 0;
+
+	pr_reg_type = dev->dev_pr_res_holder->pr_res_type;
+	cmd->pr_res_key = dev->dev_pr_res_holder->pr_res_key;
+	if (dev->dev_pr_res_holder->pr_reg_nacl != sess->se_node_acl)
+		goto check_nonholder;
+
+	if (dev->dev_pr_res_holder->isid_present_at_reg) {
+		if (dev->dev_pr_res_holder->pr_reg_bin_isid !=
+		    sess->sess_bin_isid) {
+			pr_reg_type |= 0x80000000;
+			goto check_nonholder;
+		}
+	}
+
+	return 0;
+
+check_nonholder:
+	if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type))
+		return TCM_RESERVATION_CONFLICT;
+	return 0;
+}
+
 static u32 core_scsi3_pr_generation(struct se_device *dev)
 {
-	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
 	u32 prg;
+
 	/*
 	 * PRGeneration field shall contain the value of a 32-bit wrapping
 	 * counter mainted by the device server.
@@ -577,56 +572,12 @@ static u32 core_scsi3_pr_generation(struct se_device *dev)
 	 * See spc4r17 section 6.3.12 READ_KEYS service action
 	 */
 	spin_lock(&dev->dev_reservation_lock);
-	prg = su_dev->t10_pr.pr_generation++;
+	prg = dev->t10_pr.pr_generation++;
 	spin_unlock(&dev->dev_reservation_lock);
 
 	return prg;
 }
 
-static int core_scsi3_pr_reservation_check(
-	struct se_cmd *cmd,
-	u32 *pr_reg_type)
-{
-	struct se_device *dev = cmd->se_dev;
-	struct se_session *sess = cmd->se_sess;
-	int ret;
-
-	if (!sess)
-		return 0;
-	/*
-	 * A legacy SPC-2 reservation is being held.
-	 */
-	if (dev->dev_flags & DF_SPC2_RESERVATIONS)
-		return core_scsi2_reservation_check(cmd, pr_reg_type);
-
-	spin_lock(&dev->dev_reservation_lock);
-	if (!dev->dev_pr_res_holder) {
-		spin_unlock(&dev->dev_reservation_lock);
-		return 0;
-	}
-	*pr_reg_type = dev->dev_pr_res_holder->pr_res_type;
-	cmd->pr_res_key = dev->dev_pr_res_holder->pr_res_key;
-	if (dev->dev_pr_res_holder->pr_reg_nacl != sess->se_node_acl) {
-		spin_unlock(&dev->dev_reservation_lock);
-		return -EINVAL;
-	}
-	if (!dev->dev_pr_res_holder->isid_present_at_reg) {
-		spin_unlock(&dev->dev_reservation_lock);
-		return 0;
-	}
-	ret = (dev->dev_pr_res_holder->pr_reg_bin_isid ==
-	       sess->sess_bin_isid) ? 0 : -EINVAL;
-	/*
-	 * Use bit in *pr_reg_type to notify ISID mismatch in
-	 * core_scsi3_pr_seq_non_holder().
-	 */
-	if (ret != 0)
-		*pr_reg_type |= 0x80000000;
-	spin_unlock(&dev->dev_reservation_lock);
-
-	return ret;
-}
-
 static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
 	struct se_device *dev,
 	struct se_node_acl *nacl,
@@ -636,7 +587,6 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
 	int all_tg_pt,
 	int aptpl)
 {
-	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
 	struct t10_pr_registration *pr_reg;
 
 	pr_reg = kmem_cache_zalloc(t10_pr_reg_cache, GFP_ATOMIC);
@@ -645,7 +595,7 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
 		return NULL;
 	}
 
-	pr_reg->pr_aptpl_buf = kzalloc(su_dev->t10_pr.pr_aptpl_buf_len,
+	pr_reg->pr_aptpl_buf = kzalloc(dev->t10_pr.pr_aptpl_buf_len,
 					GFP_ATOMIC);
 	if (!pr_reg->pr_aptpl_buf) {
 		pr_err("Unable to allocate pr_reg->pr_aptpl_buf\n");
@@ -929,7 +879,7 @@ static int __core_scsi3_check_aptpl_registration(
 	struct se_dev_entry *deve)
 {
 	struct t10_pr_registration *pr_reg, *pr_reg_tmp;
-	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 	unsigned char i_port[PR_APTPL_MAX_IPORT_LEN];
 	unsigned char t_port[PR_APTPL_MAX_TPORT_LEN];
 	u16 tpgt;
@@ -996,11 +946,10 @@ int core_scsi3_check_aptpl_registration(
 	struct se_lun *lun,
 	struct se_lun_acl *lun_acl)
 {
-	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
 	struct se_node_acl *nacl = lun_acl->se_lun_nacl;
 	struct se_dev_entry *deve = nacl->device_list[lun_acl->mapped_lun];
 
-	if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
+	if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
 		return 0;
 
 	return __core_scsi3_check_aptpl_registration(dev, tpg, lun,
@@ -1051,10 +1000,9 @@ static void __core_scsi3_add_registration(
 	int register_type,
 	int register_move)
 {
-	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
 	struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
 	struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe;
-	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 
 	/*
 	 * Increment PRgeneration counter for struct se_device upon a successful
@@ -1066,7 +1014,7 @@ static void __core_scsi3_add_registration(
 	 * for the REGISTER.
 	 */
 	pr_reg->pr_res_generation = (register_move) ?
-			su_dev->t10_pr.pr_generation++ :
+			dev->t10_pr.pr_generation++ :
 			core_scsi3_pr_generation(dev);
 
 	spin_lock(&pr_tmpl->registration_lock);
@@ -1135,7 +1083,7 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg(
 	struct se_node_acl *nacl,
 	unsigned char *isid)
 {
-	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 	struct t10_pr_registration *pr_reg, *pr_reg_tmp;
 	struct se_portal_group *tpg;
 
@@ -1160,7 +1108,7 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg(
 			 * for fabric modules (iSCSI) requiring them.
 			 */
 			if (tpg->se_tpg_tfo->sess_get_initiator_sid != NULL) {
-				if (dev->se_sub_dev->se_dev_attrib.enforce_pr_isids)
+				if (dev->dev_attrib.enforce_pr_isids)
 					continue;
 			}
 			atomic_inc(&pr_reg->pr_res_holders);
@@ -1274,7 +1222,7 @@ static void __core_scsi3_free_registration(
 {
 	struct target_core_fabric_ops *tfo =
 			pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo;
-	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 	char i_buf[PR_REG_ISID_ID_LEN];
 	int prf_isid;
 
@@ -1335,7 +1283,7 @@ void core_scsi3_free_pr_reg_from_nacl(
 	struct se_device *dev,
 	struct se_node_acl *nacl)
 {
-	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 	struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder;
 	/*
 	 * If the passed se_node_acl matches the reservation holder,
@@ -1365,7 +1313,7 @@ void core_scsi3_free_pr_reg_from_nacl(
 void core_scsi3_free_all_registrations(
 	struct se_device *dev)
 {
-	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 	struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder;
 
 	spin_lock(&dev->dev_reservation_lock);
@@ -1479,7 +1427,8 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve)
 	smp_mb__after_atomic_dec();
 }
 
-static int core_scsi3_decode_spec_i_port(
+static sense_reason_t
+core_scsi3_decode_spec_i_port(
 	struct se_cmd *cmd,
 	struct se_portal_group *tpg,
 	unsigned char *l_isid,
@@ -1501,8 +1450,9 @@ static int core_scsi3_decode_spec_i_port(
 	unsigned char *buf;
 	unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident;
 	char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN];
+	sense_reason_t ret;
 	u32 tpdl, tid_len = 0;
-	int ret, dest_local_nexus, prf_isid;
+	int dest_local_nexus, prf_isid;
 	u32 dest_rtpi = 0;
 
 	memset(dest_iport, 0, 64);
@@ -1517,8 +1467,7 @@ static int core_scsi3_decode_spec_i_port(
 	tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL);
 	if (!tidh_new) {
 		pr_err("Unable to allocate tidh_new\n");
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		return -EINVAL;
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	}
 	INIT_LIST_HEAD(&tidh_new->dest_list);
 	tidh_new->dest_tpg = tpg;
@@ -1530,8 +1479,7 @@ static int core_scsi3_decode_spec_i_port(
 				sa_res_key, all_tg_pt, aptpl);
 	if (!local_pr_reg) {
 		kfree(tidh_new);
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		return -ENOMEM;
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	}
 	tidh_new->dest_pr_reg = local_pr_reg;
 	/*
@@ -1545,12 +1493,16 @@ static int core_scsi3_decode_spec_i_port(
 	if (cmd->data_length < 28) {
 		pr_warn("SPC-PR: Received PR OUT parameter list"
 			" length too small: %u\n", cmd->data_length);
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		ret = -EINVAL;
+		ret = TCM_INVALID_PARAMETER_LIST;
 		goto out;
 	}
 
 	buf = transport_kmap_data_sg(cmd);
+	if (!buf) {
+		ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+		goto out;
+	}
+
 	/*
 	 * For a PERSISTENT RESERVE OUT specify initiator ports payload,
 	 * first extract TransportID Parameter Data Length, and make sure
@@ -1565,9 +1517,8 @@ static int core_scsi3_decode_spec_i_port(
 		pr_err("SPC-3 PR: Illegal tpdl: %u + 28 byte header"
 			" does not equal CDB data_length: %u\n", tpdl,
 			cmd->data_length);
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		ret = -EINVAL;
-		goto out;
+		ret = TCM_INVALID_PARAMETER_LIST;
+		goto out_unmap;
 	}
 	/*
 	 * Start processing the received transport IDs using the
@@ -1610,16 +1561,13 @@ static int core_scsi3_decode_spec_i_port(
 			smp_mb__after_atomic_inc();
 			spin_unlock(&dev->se_port_lock);
 
-			ret = core_scsi3_tpg_depend_item(tmp_tpg);
-			if (ret != 0) {
+			if (core_scsi3_tpg_depend_item(tmp_tpg)) {
 				pr_err(" core_scsi3_tpg_depend_item()"
 					" for tmp_tpg\n");
 				atomic_dec(&tmp_tpg->tpg_pr_ref_count);
 				smp_mb__after_atomic_dec();
-				cmd->scsi_sense_reason =
-					TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-				ret = -EINVAL;
-				goto out;
+				ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+				goto out_unmap;
 			}
 			/*
 			 * Locate the destination initiator ACL to be registered
@@ -1641,17 +1589,14 @@ static int core_scsi3_decode_spec_i_port(
 				continue;
 			}
 
-			ret = core_scsi3_nodeacl_depend_item(dest_node_acl);
-			if (ret != 0) {
+			if (core_scsi3_nodeacl_depend_item(dest_node_acl)) {
 				pr_err("configfs_depend_item() failed"
 					" for dest_node_acl->acl_group\n");
 				atomic_dec(&dest_node_acl->acl_pr_ref_count);
 				smp_mb__after_atomic_dec();
 				core_scsi3_tpg_undepend_item(tmp_tpg);
-				cmd->scsi_sense_reason =
-					TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-				ret = -EINVAL;
-				goto out;
+				ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+				goto out_unmap;
 			}
 
 			dest_tpg = tmp_tpg;
@@ -1668,9 +1613,8 @@ static int core_scsi3_decode_spec_i_port(
 		if (!dest_tpg) {
 			pr_err("SPC-3 PR SPEC_I_PT: Unable to locate"
 					" dest_tpg\n");
-			cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-			ret = -EINVAL;
-			goto out;
+			ret = TCM_INVALID_PARAMETER_LIST;
+			goto out_unmap;
 		}
 
 		pr_debug("SPC-3 PR SPEC_I_PT: Got %s data_length: %u tpdl: %u"
@@ -1683,9 +1627,8 @@ static int core_scsi3_decode_spec_i_port(
 				" %u for Transport ID: %s\n", tid_len, ptr);
 			core_scsi3_nodeacl_undepend_item(dest_node_acl);
 			core_scsi3_tpg_undepend_item(dest_tpg);
-			cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-			ret = -EINVAL;
-			goto out;
+			ret = TCM_INVALID_PARAMETER_LIST;
+			goto out_unmap;
 		}
 		/*
 		 * Locate the desintation struct se_dev_entry pointer for matching
@@ -1702,23 +1645,19 @@ static int core_scsi3_decode_spec_i_port(
 
 			core_scsi3_nodeacl_undepend_item(dest_node_acl);
 			core_scsi3_tpg_undepend_item(dest_tpg);
-			cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-			ret = -EINVAL;
-			goto out;
+			ret = TCM_INVALID_PARAMETER_LIST;
+			goto out_unmap;
 		}
 
-		ret = core_scsi3_lunacl_depend_item(dest_se_deve);
-		if (ret < 0) {
+		if (core_scsi3_lunacl_depend_item(dest_se_deve)) {
 			pr_err("core_scsi3_lunacl_depend_item()"
 					" failed\n");
 			atomic_dec(&dest_se_deve->pr_ref_count);
 			smp_mb__after_atomic_dec();
 			core_scsi3_nodeacl_undepend_item(dest_node_acl);
 			core_scsi3_tpg_undepend_item(dest_tpg);
-			cmd->scsi_sense_reason =
-				TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-			ret = -EINVAL;
-			goto out;
+			ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+			goto out_unmap;
 		}
 
 		pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s"
@@ -1754,10 +1693,8 @@ static int core_scsi3_decode_spec_i_port(
 			core_scsi3_lunacl_undepend_item(dest_se_deve);
 			core_scsi3_nodeacl_undepend_item(dest_node_acl);
 			core_scsi3_tpg_undepend_item(dest_tpg);
-			cmd->scsi_sense_reason =
-				TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-			ret = -ENOMEM;
-			goto out;
+			ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+			goto out_unmap;
 		}
 		INIT_LIST_HEAD(&tidh_new->dest_list);
 		tidh_new->dest_tpg = dest_tpg;
@@ -1788,9 +1725,8 @@ static int core_scsi3_decode_spec_i_port(
 			core_scsi3_nodeacl_undepend_item(dest_node_acl);
 			core_scsi3_tpg_undepend_item(dest_tpg);
 			kfree(tidh_new);
-			cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-			ret = -EINVAL;
-			goto out;
+			ret = TCM_INVALID_PARAMETER_LIST;
+			goto out_unmap;
 		}
 		tidh_new->dest_pr_reg = dest_pr_reg;
 		list_add_tail(&tidh_new->dest_list, &tid_dest_list);
@@ -1848,8 +1784,9 @@ static int core_scsi3_decode_spec_i_port(
 	}
 
 	return 0;
-out:
+out_unmap:
 	transport_kunmap_data_sg(cmd);
+out:
 	/*
 	 * For the failure case, release everything from tid_dest_list
 	 * including *dest_pr_reg and the configfs dependances..
@@ -1899,7 +1836,6 @@ static int __core_scsi3_update_aptpl_buf(
 {
 	struct se_lun *lun;
 	struct se_portal_group *tpg;
-	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
 	struct t10_pr_registration *pr_reg;
 	unsigned char tmp[512], isid_buf[32];
 	ssize_t len = 0;
@@ -1917,8 +1853,8 @@ static int __core_scsi3_update_aptpl_buf(
 	/*
 	 * Walk the registration list..
 	 */
-	spin_lock(&su_dev->t10_pr.registration_lock);
-	list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list,
+	spin_lock(&dev->t10_pr.registration_lock);
+	list_for_each_entry(pr_reg, &dev->t10_pr.registration_list,
 			pr_reg_list) {
 
 		tmp[0] = '\0';
@@ -1963,7 +1899,7 @@ static int __core_scsi3_update_aptpl_buf(
 		if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
 			pr_err("Unable to update renaming"
 				" APTPL metadata\n");
-			spin_unlock(&su_dev->t10_pr.registration_lock);
+			spin_unlock(&dev->t10_pr.registration_lock);
 			return -EMSGSIZE;
 		}
 		len += sprintf(buf+len, "%s", tmp);
@@ -1981,13 +1917,13 @@ static int __core_scsi3_update_aptpl_buf(
 		if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
 			pr_err("Unable to update renaming"
 				" APTPL metadata\n");
-			spin_unlock(&su_dev->t10_pr.registration_lock);
+			spin_unlock(&dev->t10_pr.registration_lock);
 			return -EMSGSIZE;
 		}
 		len += sprintf(buf+len, "%s", tmp);
 		reg_count++;
 	}
-	spin_unlock(&su_dev->t10_pr.registration_lock);
+	spin_unlock(&dev->t10_pr.registration_lock);
 
 	if (!reg_count)
 		len += sprintf(buf+len, "No Registrations or Reservations");
@@ -2019,7 +1955,7 @@ static int __core_scsi3_write_aptpl_to_file(
 	unsigned char *buf,
 	u32 pr_aptpl_buf_len)
 {
-	struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn;
+	struct t10_wwn *wwn = &dev->t10_wwn;
 	struct file *file;
 	struct iovec iov[1];
 	mm_segment_t old_fs;
@@ -2065,14 +2001,15 @@ static int __core_scsi3_write_aptpl_to_file(
 	return 0;
 }
 
-static int core_scsi3_update_and_write_aptpl(
-	struct se_device *dev,
-	unsigned char *in_buf,
-	u32 in_pr_aptpl_buf_len)
+static int
+core_scsi3_update_and_write_aptpl(struct se_device *dev, unsigned char *in_buf,
+		u32 in_pr_aptpl_buf_len)
 {
 	unsigned char null_buf[64], *buf;
 	u32 pr_aptpl_buf_len;
-	int ret, clear_aptpl_metadata = 0;
+	int clear_aptpl_metadata = 0;
+	int ret;
+
 	/*
 	 * Can be called with a NULL pointer from PROUT service action CLEAR
 	 */
@@ -2094,25 +2031,17 @@ static int core_scsi3_update_and_write_aptpl(
 				clear_aptpl_metadata);
 	if (ret != 0)
 		return ret;
+
 	/*
 	 * __core_scsi3_write_aptpl_to_file() will call strlen()
 	 * on the passed buf to determine pr_aptpl_buf_len.
 	 */
-	ret = __core_scsi3_write_aptpl_to_file(dev, buf, 0);
-	if (ret != 0)
-		return ret;
-
-	return ret;
+	return __core_scsi3_write_aptpl_to_file(dev, buf, 0);
 }
 
-static int core_scsi3_emulate_pro_register(
-	struct se_cmd *cmd,
-	u64 res_key,
-	u64 sa_res_key,
-	int aptpl,
-	int all_tg_pt,
-	int spec_i_pt,
-	int ignore_key)
+static sense_reason_t
+core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
+		int aptpl, int all_tg_pt, int spec_i_pt, int ignore_key)
 {
 	struct se_session *se_sess = cmd->se_sess;
 	struct se_device *dev = cmd->se_dev;
@@ -2120,16 +2049,16 @@ static int core_scsi3_emulate_pro_register(
 	struct se_lun *se_lun = cmd->se_lun;
 	struct se_portal_group *se_tpg;
 	struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp, *pr_reg_e;
-	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 	/* Used for APTPL metadata w/ UNREGISTER */
 	unsigned char *pr_aptpl_buf = NULL;
 	unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL;
-	int pr_holder = 0, ret = 0, type;
+	sense_reason_t ret;
+	int pr_holder = 0, type;
 
 	if (!se_sess || !se_lun) {
 		pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		return -EINVAL;
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	}
 	se_tpg = se_sess->se_tpg;
 	se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun];
@@ -2148,8 +2077,7 @@ static int core_scsi3_emulate_pro_register(
 		if (res_key) {
 			pr_warn("SPC-3 PR: Reservation Key non-zero"
 				" for SA REGISTER, returning CONFLICT\n");
-			cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-			return -EINVAL;
+			return TCM_RESERVATION_CONFLICT;
 		}
 		/*
 		 * Do nothing but return GOOD status.
@@ -2163,15 +2091,13 @@ static int core_scsi3_emulate_pro_register(
 			 * Port Endpoint that the PRO was received from on the
 			 * Logical Unit of the SCSI device server.
 			 */
-			ret = core_scsi3_alloc_registration(cmd->se_dev,
+			if (core_scsi3_alloc_registration(cmd->se_dev,
 					se_sess->se_node_acl, se_deve, isid_ptr,
 					sa_res_key, all_tg_pt, aptpl,
-					ignore_key, 0);
-			if (ret != 0) {
+					ignore_key, 0)) {
 				pr_err("Unable to allocate"
 					" struct t10_pr_registration\n");
-				cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-				return -EINVAL;
+				return TCM_INVALID_PARAMETER_LIST;
 			}
 		} else {
 			/*
@@ -2205,201 +2131,192 @@ static int core_scsi3_emulate_pro_register(
 		pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev,
 				se_sess->se_node_acl, se_sess);
 
-		ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
+		if (core_scsi3_update_and_write_aptpl(cmd->se_dev,
 				&pr_reg->pr_aptpl_buf[0],
-				pr_tmpl->pr_aptpl_buf_len);
-		if (!ret) {
+				pr_tmpl->pr_aptpl_buf_len)) {
 			pr_tmpl->pr_aptpl_active = 1;
 			pr_debug("SPC-3 PR: Set APTPL Bit Activated for REGISTER\n");
 		}
 
-		core_scsi3_put_pr_reg(pr_reg);
-		return ret;
-	} else {
-		/*
-		 * Locate the existing *pr_reg via struct se_node_acl pointers
-		 */
-		pr_reg = pr_reg_e;
-		type = pr_reg->pr_res_type;
-
-		if (!ignore_key) {
-			if (res_key != pr_reg->pr_res_key) {
-				pr_err("SPC-3 PR REGISTER: Received"
-					" res_key: 0x%016Lx does not match"
-					" existing SA REGISTER res_key:"
-					" 0x%016Lx\n", res_key,
-					pr_reg->pr_res_key);
-				core_scsi3_put_pr_reg(pr_reg);
-				cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-				return -EINVAL;
-			}
+		goto out_put_pr_reg;
+	}
+
+	/*
+	 * Locate the existing *pr_reg via struct se_node_acl pointers
+	 */
+	pr_reg = pr_reg_e;
+	type = pr_reg->pr_res_type;
+
+	if (!ignore_key) {
+		if (res_key != pr_reg->pr_res_key) {
+			pr_err("SPC-3 PR REGISTER: Received"
+				" res_key: 0x%016Lx does not match"
+				" existing SA REGISTER res_key:"
+				" 0x%016Lx\n", res_key,
+				pr_reg->pr_res_key);
+			ret = TCM_RESERVATION_CONFLICT;
+			goto out_put_pr_reg;
 		}
-		if (spec_i_pt) {
-			pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT"
-				" set while sa_res_key=0\n");
-			core_scsi3_put_pr_reg(pr_reg);
-			cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-			return -EINVAL;
+	}
+
+	if (spec_i_pt) {
+		pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT"
+			" set while sa_res_key=0\n");
+		ret = TCM_INVALID_PARAMETER_LIST;
+		goto out_put_pr_reg;
+	}
+
+	/*
+	 * An existing ALL_TG_PT=1 registration being released
+	 * must also set ALL_TG_PT=1 in the incoming PROUT.
+	 */
+	if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) {
+		pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1"
+			" registration exists, but ALL_TG_PT=1 bit not"
+			" present in received PROUT\n");
+		ret = TCM_INVALID_CDB_FIELD;
+		goto out_put_pr_reg;
+	}
+
+	/*
+	 * Allocate APTPL metadata buffer used for UNREGISTER ops
+	 */
+	if (aptpl) {
+		pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len,
+					GFP_KERNEL);
+		if (!pr_aptpl_buf) {
+			pr_err("Unable to allocate"
+				" pr_aptpl_buf\n");
+			ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+			goto out_put_pr_reg;
 		}
-		/*
-		 * An existing ALL_TG_PT=1 registration being released
-		 * must also set ALL_TG_PT=1 in the incoming PROUT.
-		 */
-		if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) {
-			pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1"
-				" registration exists, but ALL_TG_PT=1 bit not"
-				" present in received PROUT\n");
-			core_scsi3_put_pr_reg(pr_reg);
-			cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-			return -EINVAL;
+	}
+
+	/*
+	 * sa_res_key=0 Unregister Reservation Key for registered I_T
+	 * Nexus sa_res_key=1 Change Reservation Key for registered I_T
+	 * Nexus.
+	 */
+	if (!sa_res_key) {
+		pr_holder = core_scsi3_check_implict_release(
+				cmd->se_dev, pr_reg);
+		if (pr_holder < 0) {
+			kfree(pr_aptpl_buf);
+			ret = TCM_RESERVATION_CONFLICT;
+			goto out_put_pr_reg;
 		}
+
+		spin_lock(&pr_tmpl->registration_lock);
 		/*
-		 * Allocate APTPL metadata buffer used for UNREGISTER ops
+		 * Release all ALL_TG_PT=1 for the matching SCSI Initiator Port
+		 * and matching pr_res_key.
 		 */
-		if (aptpl) {
-			pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len,
-						GFP_KERNEL);
-			if (!pr_aptpl_buf) {
-				pr_err("Unable to allocate"
-					" pr_aptpl_buf\n");
-				core_scsi3_put_pr_reg(pr_reg);
-				cmd->scsi_sense_reason =
-					TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-				return -EINVAL;
+		if (pr_reg->pr_reg_all_tg_pt) {
+			list_for_each_entry_safe(pr_reg_p, pr_reg_tmp,
+					&pr_tmpl->registration_list,
+					pr_reg_list) {
+
+				if (!pr_reg_p->pr_reg_all_tg_pt)
+					continue;
+				if (pr_reg_p->pr_res_key != res_key)
+					continue;
+				if (pr_reg == pr_reg_p)
+					continue;
+				if (strcmp(pr_reg->pr_reg_nacl->initiatorname,
+					   pr_reg_p->pr_reg_nacl->initiatorname))
+					continue;
+
+				__core_scsi3_free_registration(dev,
+						pr_reg_p, NULL, 0);
 			}
 		}
+
 		/*
-		 * sa_res_key=0 Unregister Reservation Key for registered I_T
-		 * Nexus sa_res_key=1 Change Reservation Key for registered I_T
-		 * Nexus.
+		 * Release the calling I_T Nexus registration now..
 		 */
-		if (!sa_res_key) {
-			pr_holder = core_scsi3_check_implict_release(
-					cmd->se_dev, pr_reg);
-			if (pr_holder < 0) {
-				kfree(pr_aptpl_buf);
-				core_scsi3_put_pr_reg(pr_reg);
-				cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-				return -EINVAL;
-			}
-
-			spin_lock(&pr_tmpl->registration_lock);
-			/*
-			 * Release all ALL_TG_PT=1 for the matching SCSI Initiator Port
-			 * and matching pr_res_key.
-			 */
-			if (pr_reg->pr_reg_all_tg_pt) {
-				list_for_each_entry_safe(pr_reg_p, pr_reg_tmp,
-						&pr_tmpl->registration_list,
-						pr_reg_list) {
-
-					if (!pr_reg_p->pr_reg_all_tg_pt)
-						continue;
+		__core_scsi3_free_registration(cmd->se_dev, pr_reg, NULL, 1);
 
-					if (pr_reg_p->pr_res_key != res_key)
-						continue;
-
-					if (pr_reg == pr_reg_p)
-						continue;
-
-					if (strcmp(pr_reg->pr_reg_nacl->initiatorname,
-						   pr_reg_p->pr_reg_nacl->initiatorname))
-						continue;
-
-					__core_scsi3_free_registration(dev,
-							pr_reg_p, NULL, 0);
-				}
-			}
-			/*
-			 * Release the calling I_T Nexus registration now..
-			 */
-			__core_scsi3_free_registration(cmd->se_dev, pr_reg,
-							NULL, 1);
-			/*
-			 * From spc4r17, section 5.7.11.3 Unregistering
-			 *
-			 * If the persistent reservation is a registrants only
-			 * type, the device server shall establish a unit
-			 * attention condition for the initiator port associated
-			 * with every registered I_T nexus except for the I_T
-			 * nexus on which the PERSISTENT RESERVE OUT command was
-			 * received, with the additional sense code set to
-			 * RESERVATIONS RELEASED.
-			 */
-			if (pr_holder &&
-			   ((type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY) ||
-			    (type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY))) {
-				list_for_each_entry(pr_reg_p,
-						&pr_tmpl->registration_list,
-						pr_reg_list) {
-
-					core_scsi3_ua_allocate(
-						pr_reg_p->pr_reg_nacl,
-						pr_reg_p->pr_res_mapped_lun,
-						0x2A,
-						ASCQ_2AH_RESERVATIONS_RELEASED);
-				}
+		/*
+		 * From spc4r17, section 5.7.11.3 Unregistering
+		 *
+		 * If the persistent reservation is a registrants only
+		 * type, the device server shall establish a unit
+		 * attention condition for the initiator port associated
+		 * with every registered I_T nexus except for the I_T
+		 * nexus on which the PERSISTENT RESERVE OUT command was
+		 * received, with the additional sense code set to
+		 * RESERVATIONS RELEASED.
+		 */
+		if (pr_holder &&
+		   (type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY ||
+		    type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) {
+			list_for_each_entry(pr_reg_p,
+					&pr_tmpl->registration_list,
+					pr_reg_list) {
+
+				core_scsi3_ua_allocate(
+					pr_reg_p->pr_reg_nacl,
+					pr_reg_p->pr_res_mapped_lun,
+					0x2A,
+					ASCQ_2AH_RESERVATIONS_RELEASED);
 			}
-			spin_unlock(&pr_tmpl->registration_lock);
+		}
+		spin_unlock(&pr_tmpl->registration_lock);
 
-			if (!aptpl) {
-				pr_tmpl->pr_aptpl_active = 0;
-				core_scsi3_update_and_write_aptpl(dev, NULL, 0);
-				pr_debug("SPC-3 PR: Set APTPL Bit Deactivated"
-						" for UNREGISTER\n");
-				return 0;
-			}
+		if (!aptpl) {
+			pr_tmpl->pr_aptpl_active = 0;
+			core_scsi3_update_and_write_aptpl(dev, NULL, 0);
+			pr_debug("SPC-3 PR: Set APTPL Bit Deactivated"
+					" for UNREGISTER\n");
+			return 0;
+		}
 
-			ret = core_scsi3_update_and_write_aptpl(dev,
-					&pr_aptpl_buf[0],
-					pr_tmpl->pr_aptpl_buf_len);
-			if (!ret) {
-				pr_tmpl->pr_aptpl_active = 1;
-				pr_debug("SPC-3 PR: Set APTPL Bit Activated"
-						" for UNREGISTER\n");
-			}
+		if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0],
+				pr_tmpl->pr_aptpl_buf_len)) {
+			pr_tmpl->pr_aptpl_active = 1;
+			pr_debug("SPC-3 PR: Set APTPL Bit Activated"
+					" for UNREGISTER\n");
+		}
 
-			kfree(pr_aptpl_buf);
-			return ret;
-		} else {
-			/*
-			 * Increment PRgeneration counter for struct se_device"
-			 * upon a successful REGISTER, see spc4r17 section 6.3.2
-			 * READ_KEYS service action.
-			 */
-			pr_reg->pr_res_generation = core_scsi3_pr_generation(
-							cmd->se_dev);
-			pr_reg->pr_res_key = sa_res_key;
-			pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation"
-				" Key for %s to: 0x%016Lx PRgeneration:"
-				" 0x%08x\n", cmd->se_tfo->get_fabric_name(),
-				(ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "",
-				pr_reg->pr_reg_nacl->initiatorname,
-				pr_reg->pr_res_key, pr_reg->pr_res_generation);
-
-			if (!aptpl) {
-				pr_tmpl->pr_aptpl_active = 0;
-				core_scsi3_update_and_write_aptpl(dev, NULL, 0);
-				core_scsi3_put_pr_reg(pr_reg);
-				pr_debug("SPC-3 PR: Set APTPL Bit Deactivated"
-						" for REGISTER\n");
-				return 0;
-			}
+		goto out_free_aptpl_buf;
+	}
 
-			ret = core_scsi3_update_and_write_aptpl(dev,
-					&pr_aptpl_buf[0],
-					pr_tmpl->pr_aptpl_buf_len);
-			if (!ret) {
-				pr_tmpl->pr_aptpl_active = 1;
-				pr_debug("SPC-3 PR: Set APTPL Bit Activated"
-						" for REGISTER\n");
-			}
+	/*
+	 * Increment PRgeneration counter for struct se_device"
+	 * upon a successful REGISTER, see spc4r17 section 6.3.2
+	 * READ_KEYS service action.
+	 */
+	pr_reg->pr_res_generation = core_scsi3_pr_generation(cmd->se_dev);
+	pr_reg->pr_res_key = sa_res_key;
+	pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation"
+		" Key for %s to: 0x%016Lx PRgeneration:"
+		" 0x%08x\n", cmd->se_tfo->get_fabric_name(),
+		(ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "",
+		pr_reg->pr_reg_nacl->initiatorname,
+		pr_reg->pr_res_key, pr_reg->pr_res_generation);
 
-			kfree(pr_aptpl_buf);
-			core_scsi3_put_pr_reg(pr_reg);
-		}
+	if (!aptpl) {
+		pr_tmpl->pr_aptpl_active = 0;
+		core_scsi3_update_and_write_aptpl(dev, NULL, 0);
+		pr_debug("SPC-3 PR: Set APTPL Bit Deactivated"
+				" for REGISTER\n");
+		ret = 0;
+		goto out_put_pr_reg;
 	}
-	return 0;
+
+	if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0],
+						pr_tmpl->pr_aptpl_buf_len)) {
+		pr_tmpl->pr_aptpl_active = 1;
+		pr_debug("SPC-3 PR: Set APTPL Bit Activated"
+			" for REGISTER\n");
+	}
+
+out_free_aptpl_buf:
+	kfree(pr_aptpl_buf);
+	ret = 0;
+out_put_pr_reg:
+	core_scsi3_put_pr_reg(pr_reg);
+	return ret;
 }
 
 unsigned char *core_scsi3_pr_dump_type(int type)
@@ -2424,26 +2341,23 @@ unsigned char *core_scsi3_pr_dump_type(int type)
 	return "Unknown SPC-3 PR Type";
 }
 
-static int core_scsi3_pro_reserve(
-	struct se_cmd *cmd,
-	struct se_device *dev,
-	int type,
-	int scope,
-	u64 res_key)
+static sense_reason_t
+core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key)
 {
+	struct se_device *dev = cmd->se_dev;
 	struct se_session *se_sess = cmd->se_sess;
 	struct se_lun *se_lun = cmd->se_lun;
 	struct t10_pr_registration *pr_reg, *pr_res_holder;
-	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 	char i_buf[PR_REG_ISID_ID_LEN];
-	int ret, prf_isid;
+	sense_reason_t ret;
+	int prf_isid;
 
 	memset(i_buf, 0, PR_REG_ISID_ID_LEN);
 
 	if (!se_sess || !se_lun) {
 		pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		return -EINVAL;
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	}
 	/*
 	 * Locate the existing *pr_reg via struct se_node_acl pointers
@@ -2453,8 +2367,7 @@ static int core_scsi3_pro_reserve(
 	if (!pr_reg) {
 		pr_err("SPC-3 PR: Unable to locate"
 			" PR_REGISTERED *pr_reg for RESERVE\n");
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		return -EINVAL;
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	}
 	/*
 	 * From spc4r17 Section 5.7.9: Reserving:
@@ -2469,9 +2382,8 @@ static int core_scsi3_pro_reserve(
 		pr_err("SPC-3 PR RESERVE: Received res_key: 0x%016Lx"
 			" does not match existing SA REGISTER res_key:"
 			" 0x%016Lx\n", res_key, pr_reg->pr_res_key);
-		core_scsi3_put_pr_reg(pr_reg);
-		cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-		return -EINVAL;
+		ret = TCM_RESERVATION_CONFLICT;
+		goto out_put_pr_reg;
 	}
 	/*
 	 * From spc4r17 Section 5.7.9: Reserving:
@@ -2485,9 +2397,8 @@ static int core_scsi3_pro_reserve(
 	 */
 	if (scope != PR_SCOPE_LU_SCOPE) {
 		pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope);
-		core_scsi3_put_pr_reg(pr_reg);
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		return -EINVAL;
+		ret = TCM_INVALID_PARAMETER_LIST;
+		goto out_put_pr_reg;
 	}
 	/*
 	 * See if we have an existing PR reservation holder pointer at
@@ -2518,9 +2429,8 @@ static int core_scsi3_pro_reserve(
 				pr_res_holder->pr_reg_nacl->initiatorname);
 
 			spin_unlock(&dev->dev_reservation_lock);
-			core_scsi3_put_pr_reg(pr_reg);
-			cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-			return -EINVAL;
+			ret = TCM_RESERVATION_CONFLICT;
+			goto out_put_pr_reg;
 		}
 		/*
 		 * From spc4r17 Section 5.7.9: Reserving:
@@ -2542,9 +2452,8 @@ static int core_scsi3_pro_reserve(
 				pr_res_holder->pr_reg_nacl->initiatorname);
 
 			spin_unlock(&dev->dev_reservation_lock);
-			core_scsi3_put_pr_reg(pr_reg);
-			cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-			return -EINVAL;
+			ret = TCM_RESERVATION_CONFLICT;
+			goto out_put_pr_reg;
 		}
 		/*
 		 * From spc4r17 Section 5.7.9: Reserving:
@@ -2557,8 +2466,8 @@ static int core_scsi3_pro_reserve(
 		 * shall completethe command with GOOD status.
 		 */
 		spin_unlock(&dev->dev_reservation_lock);
-		core_scsi3_put_pr_reg(pr_reg);
-		return 0;
+		ret = 0;
+		goto out_put_pr_reg;
 	}
 	/*
 	 * Otherwise, our *pr_reg becomes the PR reservation holder for said
@@ -2582,27 +2491,24 @@ static int core_scsi3_pro_reserve(
 	spin_unlock(&dev->dev_reservation_lock);
 
 	if (pr_tmpl->pr_aptpl_active) {
-		ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
+		if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
 				&pr_reg->pr_aptpl_buf[0],
-				pr_tmpl->pr_aptpl_buf_len);
-		if (!ret)
+				pr_tmpl->pr_aptpl_buf_len)) {
 			pr_debug("SPC-3 PR: Updated APTPL metadata"
 					" for RESERVE\n");
+		}
 	}
 
+	ret = 0;
+out_put_pr_reg:
 	core_scsi3_put_pr_reg(pr_reg);
-	return 0;
+	return ret;
 }
 
-static int core_scsi3_emulate_pro_reserve(
-	struct se_cmd *cmd,
-	int type,
-	int scope,
-	u64 res_key)
+static sense_reason_t
+core_scsi3_emulate_pro_reserve(struct se_cmd *cmd, int type, int scope,
+		u64 res_key)
 {
-	struct se_device *dev = cmd->se_dev;
-	int ret = 0;
-
 	switch (type) {
 	case PR_TYPE_WRITE_EXCLUSIVE:
 	case PR_TYPE_EXCLUSIVE_ACCESS:
@@ -2610,16 +2516,12 @@ static int core_scsi3_emulate_pro_reserve(
 	case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY:
 	case PR_TYPE_WRITE_EXCLUSIVE_ALLREG:
 	case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG:
-		ret = core_scsi3_pro_reserve(cmd, dev, type, scope, res_key);
-		break;
+		return core_scsi3_pro_reserve(cmd, type, scope, res_key);
 	default:
 		pr_err("SPC-3 PR: Unknown Service Action RESERVE Type:"
 			" 0x%02x\n", type);
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		return -EINVAL;
+		return TCM_INVALID_CDB_FIELD;
 	}
-
-	return ret;
 }
 
 /*
@@ -2657,23 +2559,21 @@ static void __core_scsi3_complete_pro_release(
 	pr_reg->pr_res_holder = pr_reg->pr_res_type = pr_reg->pr_res_scope = 0;
 }
 
-static int core_scsi3_emulate_pro_release(
-	struct se_cmd *cmd,
-	int type,
-	int scope,
-	u64 res_key)
+static sense_reason_t
+core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope,
+		u64 res_key)
 {
 	struct se_device *dev = cmd->se_dev;
 	struct se_session *se_sess = cmd->se_sess;
 	struct se_lun *se_lun = cmd->se_lun;
 	struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_res_holder;
-	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
-	int ret, all_reg = 0;
+	struct t10_reservation *pr_tmpl = &dev->t10_pr;
+	int all_reg = 0;
+	sense_reason_t ret = 0;
 
 	if (!se_sess || !se_lun) {
 		pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		return -EINVAL;
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	}
 	/*
 	 * Locate the existing *pr_reg via struct se_node_acl pointers
@@ -2682,8 +2582,7 @@ static int core_scsi3_emulate_pro_release(
 	if (!pr_reg) {
 		pr_err("SPC-3 PR: Unable to locate"
 			" PR_REGISTERED *pr_reg for RELEASE\n");
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		return -EINVAL;
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	}
 	/*
 	 * From spc4r17 Section 5.7.11.2 Releasing:
@@ -2704,8 +2603,7 @@ static int core_scsi3_emulate_pro_release(
 		 * No persistent reservation, return GOOD status.
 		 */
 		spin_unlock(&dev->dev_reservation_lock);
-		core_scsi3_put_pr_reg(pr_reg);
-		return 0;
+		goto out_put_pr_reg;
 	}
 	if ((pr_res_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) ||
 	    (pr_res_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG))
@@ -2718,9 +2616,9 @@ static int core_scsi3_emulate_pro_release(
 		 * persistent reservation holder. return GOOD status.
 		 */
 		spin_unlock(&dev->dev_reservation_lock);
-		core_scsi3_put_pr_reg(pr_reg);
-		return 0;
+		goto out_put_pr_reg;
 	}
+
 	/*
 	 * From spc4r17 Section 5.7.11.2 Releasing:
 	 *
@@ -2740,9 +2638,8 @@ static int core_scsi3_emulate_pro_release(
 			" does not match existing SA REGISTER res_key:"
 			" 0x%016Lx\n", res_key, pr_reg->pr_res_key);
 		spin_unlock(&dev->dev_reservation_lock);
-		core_scsi3_put_pr_reg(pr_reg);
-		cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-		return -EINVAL;
+		ret = TCM_RESERVATION_CONFLICT;
+		goto out_put_pr_reg;
 	}
 	/*
 	 * From spc4r17 Section 5.7.11.2 Releasing and above:
@@ -2763,9 +2660,8 @@ static int core_scsi3_emulate_pro_release(
 			pr_res_holder->pr_reg_nacl->initiatorname);
 
 		spin_unlock(&dev->dev_reservation_lock);
-		core_scsi3_put_pr_reg(pr_reg);
-		cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-		return -EINVAL;
+		ret = TCM_RESERVATION_CONFLICT;
+		goto out_put_pr_reg;
 	}
 	/*
 	 * In response to a persistent reservation release request from the
@@ -2818,25 +2714,23 @@ static int core_scsi3_emulate_pro_release(
 
 write_aptpl:
 	if (pr_tmpl->pr_aptpl_active) {
-		ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
-				&pr_reg->pr_aptpl_buf[0],
-				pr_tmpl->pr_aptpl_buf_len);
-		if (!ret)
+		if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
+			&pr_reg->pr_aptpl_buf[0], pr_tmpl->pr_aptpl_buf_len)) {
 			pr_debug("SPC-3 PR: Updated APTPL metadata for RELEASE\n");
+		}
 	}
-
+out_put_pr_reg:
 	core_scsi3_put_pr_reg(pr_reg);
-	return 0;
+	return ret;
 }
 
-static int core_scsi3_emulate_pro_clear(
-	struct se_cmd *cmd,
-	u64 res_key)
+static sense_reason_t
+core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key)
 {
 	struct se_device *dev = cmd->se_dev;
 	struct se_node_acl *pr_reg_nacl;
 	struct se_session *se_sess = cmd->se_sess;
-	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 	struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder;
 	u32 pr_res_mapped_lun = 0;
 	int calling_it_nexus = 0;
@@ -2848,8 +2742,7 @@ static int core_scsi3_emulate_pro_clear(
 	if (!pr_reg_n) {
 		pr_err("SPC-3 PR: Unable to locate"
 			" PR_REGISTERED *pr_reg for CLEAR\n");
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		return -EINVAL;
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	}
 	/*
 	 * From spc4r17 section 5.7.11.6, Clearing:
@@ -2868,8 +2761,7 @@ static int core_scsi3_emulate_pro_clear(
 			" existing SA REGISTER res_key:"
 			" 0x%016Lx\n", res_key, pr_reg_n->pr_res_key);
 		core_scsi3_put_pr_reg(pr_reg_n);
-		cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-		return -EINVAL;
+		return TCM_RESERVATION_CONFLICT;
 	}
 	/*
 	 * a) Release the persistent reservation, if any;
@@ -2993,28 +2885,22 @@ static void core_scsi3_release_preempt_and_abort(
 	}
 }
 
-static int core_scsi3_pro_preempt(
-	struct se_cmd *cmd,
-	int type,
-	int scope,
-	u64 res_key,
-	u64 sa_res_key,
-	int abort)
+static sense_reason_t
+core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
+		u64 sa_res_key, int abort)
 {
 	struct se_device *dev = cmd->se_dev;
 	struct se_node_acl *pr_reg_nacl;
 	struct se_session *se_sess = cmd->se_sess;
 	LIST_HEAD(preempt_and_abort_list);
 	struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder;
-	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 	u32 pr_res_mapped_lun = 0;
 	int all_reg = 0, calling_it_nexus = 0, released_regs = 0;
-	int prh_type = 0, prh_scope = 0, ret;
+	int prh_type = 0, prh_scope = 0;
 
-	if (!se_sess) {
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		return -EINVAL;
-	}
+	if (!se_sess)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
 	pr_reg_n = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl,
 				se_sess);
@@ -3022,19 +2908,16 @@ static int core_scsi3_pro_preempt(
 		pr_err("SPC-3 PR: Unable to locate"
 			" PR_REGISTERED *pr_reg for PREEMPT%s\n",
 			(abort) ? "_AND_ABORT" : "");
-		cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-		return -EINVAL;
+		return TCM_RESERVATION_CONFLICT;
 	}
 	if (pr_reg_n->pr_res_key != res_key) {
 		core_scsi3_put_pr_reg(pr_reg_n);
-		cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-		return -EINVAL;
+		return TCM_RESERVATION_CONFLICT;
 	}
 	if (scope != PR_SCOPE_LU_SCOPE) {
 		pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope);
 		core_scsi3_put_pr_reg(pr_reg_n);
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		return -EINVAL;
+		return TCM_INVALID_PARAMETER_LIST;
 	}
 
 	spin_lock(&dev->dev_reservation_lock);
@@ -3047,8 +2930,7 @@ static int core_scsi3_pro_preempt(
 	if (!all_reg && !sa_res_key) {
 		spin_unlock(&dev->dev_reservation_lock);
 		core_scsi3_put_pr_reg(pr_reg_n);
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		return -EINVAL;
+		return TCM_INVALID_PARAMETER_LIST;
 	}
 	/*
 	 * From spc4r17, section 5.7.11.4.4 Removing Registrations:
@@ -3142,8 +3024,7 @@ static int core_scsi3_pro_preempt(
 		if (!released_regs) {
 			spin_unlock(&dev->dev_reservation_lock);
 			core_scsi3_put_pr_reg(pr_reg_n);
-			cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-			return -EINVAL;
+			return TCM_RESERVATION_CONFLICT;
 		}
 		/*
 		 * For an existing all registrants type reservation
@@ -3162,13 +3043,13 @@ static int core_scsi3_pro_preempt(
 		spin_unlock(&dev->dev_reservation_lock);
 
 		if (pr_tmpl->pr_aptpl_active) {
-			ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
+			if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
 					&pr_reg_n->pr_aptpl_buf[0],
-					pr_tmpl->pr_aptpl_buf_len);
-			if (!ret)
+					pr_tmpl->pr_aptpl_buf_len)) {
 				pr_debug("SPC-3 PR: Updated APTPL"
 					" metadata for  PREEMPT%s\n", (abort) ?
 					"_AND_ABORT" : "");
+			}
 		}
 
 		core_scsi3_put_pr_reg(pr_reg_n);
@@ -3298,12 +3179,12 @@ static int core_scsi3_pro_preempt(
 	}
 
 	if (pr_tmpl->pr_aptpl_active) {
-		ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
+		if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
 				&pr_reg_n->pr_aptpl_buf[0],
-				pr_tmpl->pr_aptpl_buf_len);
-		if (!ret)
+				pr_tmpl->pr_aptpl_buf_len)) {
 			pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT"
-				"%s\n", (abort) ? "_AND_ABORT" : "");
+				"%s\n", abort ? "_AND_ABORT" : "");
+		}
 	}
 
 	core_scsi3_put_pr_reg(pr_reg_n);
@@ -3311,16 +3192,10 @@ static int core_scsi3_pro_preempt(
 	return 0;
 }
 
-static int core_scsi3_emulate_pro_preempt(
-	struct se_cmd *cmd,
-	int type,
-	int scope,
-	u64 res_key,
-	u64 sa_res_key,
-	int abort)
+static sense_reason_t
+core_scsi3_emulate_pro_preempt(struct se_cmd *cmd, int type, int scope,
+		u64 res_key, u64 sa_res_key, int abort)
 {
-	int ret = 0;
-
 	switch (type) {
 	case PR_TYPE_WRITE_EXCLUSIVE:
 	case PR_TYPE_EXCLUSIVE_ACCESS:
@@ -3328,26 +3203,19 @@ static int core_scsi3_emulate_pro_preempt(
 	case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY:
 	case PR_TYPE_WRITE_EXCLUSIVE_ALLREG:
 	case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG:
-		ret = core_scsi3_pro_preempt(cmd, type, scope,
-				res_key, sa_res_key, abort);
-		break;
+		return core_scsi3_pro_preempt(cmd, type, scope, res_key,
+					      sa_res_key, abort);
 	default:
 		pr_err("SPC-3 PR: Unknown Service Action PREEMPT%s"
 			" Type: 0x%02x\n", (abort) ? "_AND_ABORT" : "", type);
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		return -EINVAL;
+		return TCM_INVALID_CDB_FIELD;
 	}
-
-	return ret;
 }
 
 
-static int core_scsi3_emulate_pro_register_and_move(
-	struct se_cmd *cmd,
-	u64 res_key,
-	u64 sa_res_key,
-	int aptpl,
-	int unreg)
+static sense_reason_t
+core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
+		u64 sa_res_key, int aptpl, int unreg)
 {
 	struct se_session *se_sess = cmd->se_sess;
 	struct se_device *dev = cmd->se_dev;
@@ -3358,20 +3226,21 @@ static int core_scsi3_emulate_pro_register_and_move(
 	struct se_portal_group *se_tpg, *dest_se_tpg = NULL;
 	struct target_core_fabric_ops *dest_tf_ops = NULL, *tf_ops;
 	struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg;
-	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 	unsigned char *buf;
 	unsigned char *initiator_str;
 	char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN];
 	u32 tid_len, tmp_tid_len;
-	int new_reg = 0, type, scope, ret, matching_iname, prf_isid;
+	int new_reg = 0, type, scope, matching_iname, prf_isid;
+	sense_reason_t ret;
 	unsigned short rtpi;
 	unsigned char proto_ident;
 
 	if (!se_sess || !se_lun) {
 		pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		return -EINVAL;
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	}
+
 	memset(dest_iport, 0, 64);
 	memset(i_buf, 0, PR_REG_ISID_ID_LEN);
 	se_tpg = se_sess->se_tpg;
@@ -3387,8 +3256,7 @@ static int core_scsi3_emulate_pro_register_and_move(
 	if (!pr_reg) {
 		pr_err("SPC-3 PR: Unable to locate PR_REGISTERED"
 			" *pr_reg for REGISTER_AND_MOVE\n");
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		return -EINVAL;
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	}
 	/*
 	 * The provided reservation key much match the existing reservation key
@@ -3398,9 +3266,8 @@ static int core_scsi3_emulate_pro_register_and_move(
 		pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received"
 			" res_key: 0x%016Lx does not match existing SA REGISTER"
 			" res_key: 0x%016Lx\n", res_key, pr_reg->pr_res_key);
-		core_scsi3_put_pr_reg(pr_reg);
-		cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-		return -EINVAL;
+		ret = TCM_RESERVATION_CONFLICT;
+		goto out_put_pr_reg;
 	}
 	/*
 	 * The service active reservation key needs to be non zero
@@ -3408,9 +3275,8 @@ static int core_scsi3_emulate_pro_register_and_move(
 	if (!sa_res_key) {
 		pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received zero"
 			" sa_res_key\n");
-		core_scsi3_put_pr_reg(pr_reg);
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		return -EINVAL;
+		ret = TCM_INVALID_PARAMETER_LIST;
+		goto out_put_pr_reg;
 	}
 
 	/*
@@ -3419,6 +3285,11 @@ static int core_scsi3_emulate_pro_register_and_move(
 	 * information.
 	 */
 	buf = transport_kmap_data_sg(cmd);
+	if (!buf) {
+		ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+		goto out_put_pr_reg;
+	}
+
 	rtpi = (buf[18] & 0xff) << 8;
 	rtpi |= buf[19] & 0xff;
 	tid_len = (buf[20] & 0xff) << 24;
@@ -3432,9 +3303,8 @@ static int core_scsi3_emulate_pro_register_and_move(
 		pr_err("SPC-3 PR: Illegal tid_len: %u + 24 byte header"
 			" does not equal CDB data_length: %u\n", tid_len,
 			cmd->data_length);
-		core_scsi3_put_pr_reg(pr_reg);
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		return -EINVAL;
+		ret = TCM_INVALID_PARAMETER_LIST;
+		goto out_put_pr_reg;
 	}
 
 	spin_lock(&dev->se_port_lock);
@@ -3452,15 +3322,13 @@ static int core_scsi3_emulate_pro_register_and_move(
 		smp_mb__after_atomic_inc();
 		spin_unlock(&dev->se_port_lock);
 
-		ret = core_scsi3_tpg_depend_item(dest_se_tpg);
-		if (ret != 0) {
+		if (core_scsi3_tpg_depend_item(dest_se_tpg)) {
 			pr_err("core_scsi3_tpg_depend_item() failed"
 				" for dest_se_tpg\n");
 			atomic_dec(&dest_se_tpg->tpg_pr_ref_count);
 			smp_mb__after_atomic_dec();
-			core_scsi3_put_pr_reg(pr_reg);
-			cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-			return -EINVAL;
+			ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+			goto out_put_pr_reg;
 		}
 
 		spin_lock(&dev->se_port_lock);
@@ -3472,12 +3340,15 @@ static int core_scsi3_emulate_pro_register_and_move(
 		pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
 			" fabric ops from Relative Target Port Identifier:"
 			" %hu\n", rtpi);
-		core_scsi3_put_pr_reg(pr_reg);
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		return -EINVAL;
+		ret = TCM_INVALID_PARAMETER_LIST;
+		goto out_put_pr_reg;
 	}
 
 	buf = transport_kmap_data_sg(cmd);
+	if (!buf) {
+		ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+		goto out_put_pr_reg;
+	}
 	proto_ident = (buf[24] & 0x0f);
 
 	pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:"
@@ -3489,16 +3360,14 @@ static int core_scsi3_emulate_pro_register_and_move(
 			" from fabric: %s\n", proto_ident,
 			dest_tf_ops->get_fabric_proto_ident(dest_se_tpg),
 			dest_tf_ops->get_fabric_name());
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		ret = -EINVAL;
+		ret = TCM_INVALID_PARAMETER_LIST;
 		goto out;
 	}
 	if (dest_tf_ops->tpg_parse_pr_out_transport_id == NULL) {
 		pr_err("SPC-3 PR REGISTER_AND_MOVE: Fabric does not"
 			" containg a valid tpg_parse_pr_out_transport_id"
 			" function pointer\n");
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		ret = -EINVAL;
+		ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 		goto out;
 	}
 	initiator_str = dest_tf_ops->tpg_parse_pr_out_transport_id(dest_se_tpg,
@@ -3506,8 +3375,7 @@ static int core_scsi3_emulate_pro_register_and_move(
 	if (!initiator_str) {
 		pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
 			" initiator_str from Transport ID\n");
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		ret = -EINVAL;
+		ret = TCM_INVALID_PARAMETER_LIST;
 		goto out;
 	}
 
@@ -3536,8 +3404,7 @@ static int core_scsi3_emulate_pro_register_and_move(
 		pr_err("SPC-3 PR REGISTER_AND_MOVE: TransportID: %s"
 			" matches: %s on received I_T Nexus\n", initiator_str,
 			pr_reg_nacl->initiatorname);
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		ret = -EINVAL;
+		ret = TCM_INVALID_PARAMETER_LIST;
 		goto out;
 	}
 	if (!strcmp(iport_ptr, pr_reg->pr_reg_isid)) {
@@ -3545,8 +3412,7 @@ static int core_scsi3_emulate_pro_register_and_move(
 			" matches: %s %s on received I_T Nexus\n",
 			initiator_str, iport_ptr, pr_reg_nacl->initiatorname,
 			pr_reg->pr_reg_isid);
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		ret = -EINVAL;
+		ret = TCM_INVALID_PARAMETER_LIST;
 		goto out;
 	}
 after_iport_check:
@@ -3566,19 +3432,17 @@ after_iport_check:
 		pr_err("Unable to locate %s dest_node_acl for"
 			" TransportID%s\n", dest_tf_ops->get_fabric_name(),
 			initiator_str);
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		ret = -EINVAL;
+		ret = TCM_INVALID_PARAMETER_LIST;
 		goto out;
 	}
-	ret = core_scsi3_nodeacl_depend_item(dest_node_acl);
-	if (ret != 0) {
+
+	if (core_scsi3_nodeacl_depend_item(dest_node_acl)) {
 		pr_err("core_scsi3_nodeacl_depend_item() for"
 			" dest_node_acl\n");
 		atomic_dec(&dest_node_acl->acl_pr_ref_count);
 		smp_mb__after_atomic_dec();
 		dest_node_acl = NULL;
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		ret = -EINVAL;
+		ret = TCM_INVALID_PARAMETER_LIST;
 		goto out;
 	}
 
@@ -3594,19 +3458,16 @@ after_iport_check:
 	if (!dest_se_deve) {
 		pr_err("Unable to locate %s dest_se_deve from RTPI:"
 			" %hu\n",  dest_tf_ops->get_fabric_name(), rtpi);
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		ret = -EINVAL;
+		ret = TCM_INVALID_PARAMETER_LIST;
 		goto out;
 	}
 
-	ret = core_scsi3_lunacl_depend_item(dest_se_deve);
-	if (ret < 0) {
+	if (core_scsi3_lunacl_depend_item(dest_se_deve)) {
 		pr_err("core_scsi3_lunacl_depend_item() failed\n");
 		atomic_dec(&dest_se_deve->pr_ref_count);
 		smp_mb__after_atomic_dec();
 		dest_se_deve = NULL;
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		ret = -EINVAL;
+		ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 		goto out;
 	}
 
@@ -3625,8 +3486,7 @@ after_iport_check:
 		pr_warn("SPC-3 PR REGISTER_AND_MOVE: No reservation"
 			" currently held\n");
 		spin_unlock(&dev->dev_reservation_lock);
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		ret = -EINVAL;
+		ret = TCM_INVALID_CDB_FIELD;
 		goto out;
 	}
 	/*
@@ -3639,8 +3499,7 @@ after_iport_check:
 		pr_warn("SPC-3 PR REGISTER_AND_MOVE: Calling I_T"
 			" Nexus is not reservation holder\n");
 		spin_unlock(&dev->dev_reservation_lock);
-		cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-		ret = -EINVAL;
+		ret = TCM_RESERVATION_CONFLICT;
 		goto out;
 	}
 	/*
@@ -3658,8 +3517,7 @@ after_iport_check:
 			" reservation for type: %s\n",
 			core_scsi3_pr_dump_type(pr_res_holder->pr_res_type));
 		spin_unlock(&dev->dev_reservation_lock);
-		cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-		ret = -EINVAL;
+		ret = TCM_RESERVATION_CONFLICT;
 		goto out;
 	}
 	pr_res_nacl = pr_res_holder->pr_reg_nacl;
@@ -3691,13 +3549,11 @@ after_iport_check:
 	dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl,
 					iport_ptr);
 	if (!dest_pr_reg) {
-		ret = core_scsi3_alloc_registration(cmd->se_dev,
+		if (core_scsi3_alloc_registration(cmd->se_dev,
 				dest_node_acl, dest_se_deve, iport_ptr,
-				sa_res_key, 0, aptpl, 2, 1);
-		if (ret != 0) {
+				sa_res_key, 0, aptpl, 2, 1)) {
 			spin_unlock(&dev->dev_reservation_lock);
-			cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-			ret = -EINVAL;
+			ret = TCM_INVALID_PARAMETER_LIST;
 			goto out;
 		}
 		dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl,
@@ -3768,12 +3624,12 @@ after_iport_check:
 				" REGISTER_AND_MOVE\n");
 	} else {
 		pr_tmpl->pr_aptpl_active = 1;
-		ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
+		if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
 				&dest_pr_reg->pr_aptpl_buf[0],
-				pr_tmpl->pr_aptpl_buf_len);
-		if (!ret)
+				pr_tmpl->pr_aptpl_buf_len)) {
 			pr_debug("SPC-3 PR: Set APTPL Bit Activated for"
 					" REGISTER_AND_MOVE\n");
+		}
 	}
 
 	transport_kunmap_data_sg(cmd);
@@ -3788,6 +3644,8 @@ out:
 	if (dest_node_acl)
 		core_scsi3_nodeacl_undepend_item(dest_node_acl);
 	core_scsi3_tpg_undepend_item(dest_se_tpg);
+
+out_put_pr_reg:
 	core_scsi3_put_pr_reg(pr_reg);
 	return ret;
 }
@@ -3805,14 +3663,15 @@ static unsigned long long core_scsi3_extract_reservation_key(unsigned char *cdb)
 /*
  * See spc4r17 section 6.14 Table 170
  */
-int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
+sense_reason_t
+target_scsi3_emulate_pr_out(struct se_cmd *cmd)
 {
 	unsigned char *cdb = &cmd->t_task_cdb[0];
 	unsigned char *buf;
 	u64 res_key, sa_res_key;
 	int sa, scope, type, aptpl;
 	int spec_i_pt = 0, all_tg_pt = 0, unreg = 0;
-	int ret;
+	sense_reason_t ret;
 
 	/*
 	 * Following spc2r20 5.5.1 Reservations overview:
@@ -3823,32 +3682,26 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
 	 * initiator or service action and shall terminate with a RESERVATION
 	 * CONFLICT status.
 	 */
-	if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS) {
+	if (cmd->se_dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) {
 		pr_err("Received PERSISTENT_RESERVE CDB while legacy"
 			" SPC-2 reservation is held, returning"
 			" RESERVATION_CONFLICT\n");
-		cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-		ret = -EINVAL;
-		goto out;
+		return TCM_RESERVATION_CONFLICT;
 	}
 
 	/*
 	 * FIXME: A NULL struct se_session pointer means an this is not coming from
 	 * a $FABRIC_MOD's nexus, but from internal passthrough ops.
 	 */
-	if (!cmd->se_sess) {
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		ret = -EINVAL;
-		goto out;
-	}
+	if (!cmd->se_sess)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
 	if (cmd->data_length < 24) {
 		pr_warn("SPC-PR: Received PR OUT parameter list"
 			" length too small: %u\n", cmd->data_length);
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		ret = -EINVAL;
-		goto out;
+		return TCM_INVALID_PARAMETER_LIST;
 	}
+
 	/*
 	 * From the PERSISTENT_RESERVE_OUT command descriptor block (CDB)
 	 */
@@ -3857,6 +3710,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
 	type = (cdb[2] & 0x0f);
 
 	buf = transport_kmap_data_sg(cmd);
+	if (!buf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
 	/*
 	 * From PERSISTENT_RESERVE_OUT parameter list (payload)
 	 */
@@ -3880,11 +3736,8 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
 	/*
 	 * SPEC_I_PT=1 is only valid for Service action: REGISTER
 	 */
-	if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER)) {
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		ret = -EINVAL;
-		goto out;
-	}
+	if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER))
+		return TCM_INVALID_PARAMETER_LIST;
 
 	/*
 	 * From spc4r17 section 6.14:
@@ -3899,10 +3752,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
 	    (cmd->data_length != 24)) {
 		pr_warn("SPC-PR: Received PR OUT illegal parameter"
 			" list length: %u\n", cmd->data_length);
-		cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
-		ret = -EINVAL;
-		goto out;
+		return TCM_INVALID_PARAMETER_LIST;
 	}
+
 	/*
 	 * (core_scsi3_emulate_pro_* function parameters
 	 * are defined by spc4r17 Table 174:
@@ -3941,12 +3793,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
 	default:
 		pr_err("Unknown PERSISTENT_RESERVE_OUT service"
 			" action: 0x%02x\n", cdb[1] & 0x1f);
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		ret = -EINVAL;
-		break;
+		return TCM_INVALID_CDB_FIELD;
 	}
 
-out:
 	if (!ret)
 		target_complete_cmd(cmd, GOOD);
 	return ret;
@@ -3957,10 +3806,10 @@ out:
  *
  * See spc4r17 section 5.7.6.2 and section 6.13.2, Table 160
  */
-static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
+static sense_reason_t
+core_scsi3_pri_read_keys(struct se_cmd *cmd)
 {
-	struct se_device *se_dev = cmd->se_dev;
-	struct se_subsystem_dev *su_dev = se_dev->se_sub_dev;
+	struct se_device *dev = cmd->se_dev;
 	struct t10_pr_registration *pr_reg;
 	unsigned char *buf;
 	u32 add_len = 0, off = 8;
@@ -3968,18 +3817,20 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
 	if (cmd->data_length < 8) {
 		pr_err("PRIN SA READ_KEYS SCSI Data Length: %u"
 			" too small\n", cmd->data_length);
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		return -EINVAL;
+		return TCM_INVALID_CDB_FIELD;
 	}
 
 	buf = transport_kmap_data_sg(cmd);
-	buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
-	buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
-	buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
-	buf[3] = (su_dev->t10_pr.pr_generation & 0xff);
+	if (!buf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-	spin_lock(&su_dev->t10_pr.registration_lock);
-	list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list,
+	buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff);
+	buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff);
+	buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff);
+	buf[3] = (dev->t10_pr.pr_generation & 0xff);
+
+	spin_lock(&dev->t10_pr.registration_lock);
+	list_for_each_entry(pr_reg, &dev->t10_pr.registration_list,
 			pr_reg_list) {
 		/*
 		 * Check for overflow of 8byte PRI READ_KEYS payload and
@@ -3999,7 +3850,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
 
 		add_len += 8;
 	}
-	spin_unlock(&su_dev->t10_pr.registration_lock);
+	spin_unlock(&dev->t10_pr.registration_lock);
 
 	buf[4] = ((add_len >> 24) & 0xff);
 	buf[5] = ((add_len >> 16) & 0xff);
@@ -4016,10 +3867,10 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
  *
  * See spc4r17 section 5.7.6.3 and section 6.13.3.2 Table 161 and 162
  */
-static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
+static sense_reason_t
+core_scsi3_pri_read_reservation(struct se_cmd *cmd)
 {
-	struct se_device *se_dev = cmd->se_dev;
-	struct se_subsystem_dev *su_dev = se_dev->se_sub_dev;
+	struct se_device *dev = cmd->se_dev;
 	struct t10_pr_registration *pr_reg;
 	unsigned char *buf;
 	u64 pr_res_key;
@@ -4028,18 +3879,20 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
 	if (cmd->data_length < 8) {
 		pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u"
 			" too small\n", cmd->data_length);
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		return -EINVAL;
+		return TCM_INVALID_CDB_FIELD;
 	}
 
 	buf = transport_kmap_data_sg(cmd);
-	buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
-	buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
-	buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
-	buf[3] = (su_dev->t10_pr.pr_generation & 0xff);
+	if (!buf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-	spin_lock(&se_dev->dev_reservation_lock);
-	pr_reg = se_dev->dev_pr_res_holder;
+	buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff);
+	buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff);
+	buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff);
+	buf[3] = (dev->t10_pr.pr_generation & 0xff);
+
+	spin_lock(&dev->dev_reservation_lock);
+	pr_reg = dev->dev_pr_res_holder;
 	if (pr_reg) {
 		/*
 		 * Set the hardcoded Additional Length
@@ -4090,7 +3943,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
 	}
 
 err:
-	spin_unlock(&se_dev->dev_reservation_lock);
+	spin_unlock(&dev->dev_reservation_lock);
 	transport_kunmap_data_sg(cmd);
 
 	return 0;
@@ -4101,21 +3954,23 @@ err:
  *
  * See spc4r17 section 6.13.4 Table 165
  */
-static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
+static sense_reason_t
+core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
 {
 	struct se_device *dev = cmd->se_dev;
-	struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 	unsigned char *buf;
 	u16 add_len = 8; /* Hardcoded to 8. */
 
 	if (cmd->data_length < 6) {
 		pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:"
 			" %u too small\n", cmd->data_length);
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		return -EINVAL;
+		return TCM_INVALID_CDB_FIELD;
 	}
 
 	buf = transport_kmap_data_sg(cmd);
+	if (!buf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
 	buf[0] = ((add_len << 8) & 0xff);
 	buf[1] = (add_len & 0xff);
@@ -4157,14 +4012,14 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
  *
  * See spc4r17 section 6.13.5 Table 168 and 169
  */
-static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
+static sense_reason_t
+core_scsi3_pri_read_full_status(struct se_cmd *cmd)
 {
-	struct se_device *se_dev = cmd->se_dev;
+	struct se_device *dev = cmd->se_dev;
 	struct se_node_acl *se_nacl;
-	struct se_subsystem_dev *su_dev = se_dev->se_sub_dev;
 	struct se_portal_group *se_tpg;
 	struct t10_pr_registration *pr_reg, *pr_reg_tmp;
-	struct t10_reservation *pr_tmpl = &se_dev->se_sub_dev->t10_pr;
+	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 	unsigned char *buf;
 	u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len;
 	u32 off = 8; /* off into first Full Status descriptor */
@@ -4173,16 +4028,17 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
 	if (cmd->data_length < 8) {
 		pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u"
 			" too small\n", cmd->data_length);
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		return -EINVAL;
+		return TCM_INVALID_CDB_FIELD;
 	}
 
 	buf = transport_kmap_data_sg(cmd);
+	if (!buf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-	buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
-	buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
-	buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
-	buf[3] = (su_dev->t10_pr.pr_generation & 0xff);
+	buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff);
+	buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff);
+	buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff);
+	buf[3] = (dev->t10_pr.pr_generation & 0xff);
 
 	spin_lock(&pr_tmpl->registration_lock);
 	list_for_each_entry_safe(pr_reg, pr_reg_tmp,
@@ -4303,9 +4159,10 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
 	return 0;
 }
 
-int target_scsi3_emulate_pr_in(struct se_cmd *cmd)
+sense_reason_t
+target_scsi3_emulate_pr_in(struct se_cmd *cmd)
 {
-	int ret;
+	sense_reason_t ret;
 
 	/*
 	 * Following spc2r20 5.5.1 Reservations overview:
@@ -4316,12 +4173,11 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd)
 	 * initiator or service action and shall terminate with a RESERVATION
 	 * CONFLICT status.
 	 */
-	if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS) {
+	if (cmd->se_dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) {
 		pr_err("Received PERSISTENT_RESERVE CDB while legacy"
 			" SPC-2 reservation is held, returning"
 			" RESERVATION_CONFLICT\n");
-		cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-		return -EINVAL;
+		return TCM_RESERVATION_CONFLICT;
 	}
 
 	switch (cmd->t_task_cdb[1] & 0x1f) {
@@ -4340,9 +4196,7 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd)
 	default:
 		pr_err("Unknown PERSISTENT_RESERVE_IN service"
 			" action: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f);
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		ret = -EINVAL;
-		break;
+		return TCM_INVALID_CDB_FIELD;
 	}
 
 	if (!ret)
@@ -4350,56 +4204,25 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd)
 	return ret;
 }
 
-static int core_pt_reservation_check(struct se_cmd *cmd, u32 *pr_res_type)
-{
-	return 0;
-}
-
-static int core_pt_seq_non_holder(
-	struct se_cmd *cmd,
-	unsigned char *cdb,
-	u32 pr_reg_type)
+sense_reason_t
+target_check_reservation(struct se_cmd *cmd)
 {
-	return 0;
-}
+	struct se_device *dev = cmd->se_dev;
+	sense_reason_t ret;
 
-int core_setup_reservations(struct se_device *dev, int force_pt)
-{
-	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
-	struct t10_reservation *rest = &su_dev->t10_pr;
-	/*
-	 * If this device is from Target_Core_Mod/pSCSI, use the reservations
-	 * of the Underlying SCSI hardware.  In Linux/SCSI terms, this can
-	 * cause a problem because libata and some SATA RAID HBAs appear
-	 * under Linux/SCSI, but to emulate reservations themselves.
-	 */
-	if (((dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) &&
-	    !(dev->se_sub_dev->se_dev_attrib.emulate_reservations)) || force_pt) {
-		rest->res_type = SPC_PASSTHROUGH;
-		rest->pr_ops.t10_reservation_check = &core_pt_reservation_check;
-		rest->pr_ops.t10_seq_non_holder = &core_pt_seq_non_holder;
-		pr_debug("%s: Using SPC_PASSTHROUGH, no reservation"
-			" emulation\n", dev->transport->name);
+	if (!cmd->se_sess)
+		return 0;
+	if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)
+		return 0;
+	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
 		return 0;
-	}
-	/*
-	 * If SPC-3 or above is reported by real or emulated struct se_device,
-	 * use emulated Persistent Reservations.
-	 */
-	if (dev->transport->get_device_rev(dev) >= SCSI_3) {
-		rest->res_type = SPC3_PERSISTENT_RESERVATIONS;
-		rest->pr_ops.t10_reservation_check = &core_scsi3_pr_reservation_check;
-		rest->pr_ops.t10_seq_non_holder = &core_scsi3_pr_seq_non_holder;
-		pr_debug("%s: Using SPC3_PERSISTENT_RESERVATIONS"
-			" emulation\n", dev->transport->name);
-	} else {
-		rest->res_type = SPC2_RESERVATIONS;
-		rest->pr_ops.t10_reservation_check = &core_scsi2_reservation_check;
-		rest->pr_ops.t10_seq_non_holder =
-				&core_scsi2_reservation_seq_non_holder;
-		pr_debug("%s: Using SPC2_RESERVATIONS emulation\n",
-			dev->transport->name);
-	}
 
-	return 0;
+	spin_lock(&dev->dev_reservation_lock);
+	if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
+		ret = target_scsi2_reservation_check(cmd);
+	else
+		ret = target_scsi3_pr_reservation_check(cmd);
+	spin_unlock(&dev->dev_reservation_lock);
+
+	return ret;
 }
diff --git a/drivers/target/target_core_pr.h b/drivers/target/target_core_pr.h
index af6c460..b4a0042 100644
--- a/drivers/target/target_core_pr.h
+++ b/drivers/target/target_core_pr.h
@@ -47,8 +47,8 @@ extern struct kmem_cache *t10_pr_reg_cache;
 
 extern int core_pr_dump_initiator_port(struct t10_pr_registration *,
 			char *, u32);
-extern int target_scsi2_reservation_release(struct se_cmd *);
-extern int target_scsi2_reservation_reserve(struct se_cmd *);
+extern sense_reason_t target_scsi2_reservation_release(struct se_cmd *);
+extern sense_reason_t target_scsi2_reservation_reserve(struct se_cmd *);
 extern int core_scsi3_alloc_aptpl_registration(
 			struct t10_reservation *, u64,
 			unsigned char *, unsigned char *, u32,
@@ -61,8 +61,8 @@ extern void core_scsi3_free_pr_reg_from_nacl(struct se_device *,
 extern void core_scsi3_free_all_registrations(struct se_device *);
 extern unsigned char *core_scsi3_pr_dump_type(int);
 
-extern int target_scsi3_emulate_pr_in(struct se_cmd *);
-extern int target_scsi3_emulate_pr_out(struct se_cmd *);
-extern int core_setup_reservations(struct se_device *, int);
+extern sense_reason_t target_scsi3_emulate_pr_in(struct se_cmd *);
+extern sense_reason_t target_scsi3_emulate_pr_out(struct se_cmd *);
+extern sense_reason_t target_check_reservation(struct se_cmd *);
 
 #endif /* TARGET_CORE_PR_H */
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index 617c086..2bcfd79 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -3,10 +3,7 @@
  *
  * This file contains the generic target mode <-> Linux SCSI subsystem plugin.
  *
- * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc.
- * Copyright (c) 2005, 2006, 2007 SBE, Inc.
- * Copyright (c) 2007-2010 Rising Tide Systems
- * Copyright (c) 2008-2010 Linux-iSCSI.org
+ * (c) Copyright 2003-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@kernel.org>
  *
@@ -53,9 +50,14 @@
 
 #define ISPRINT(a)  ((a >= ' ') && (a <= '~'))
 
+static inline struct pscsi_dev_virt *PSCSI_DEV(struct se_device *dev)
+{
+	return container_of(dev, struct pscsi_dev_virt, dev);
+}
+
 static struct se_subsystem_api pscsi_template;
 
-static int pscsi_execute_cmd(struct se_cmd *cmd);
+static sense_reason_t pscsi_execute_cmd(struct se_cmd *cmd);
 static void pscsi_req_done(struct request *, int);
 
 /*	pscsi_attach_hba():
@@ -219,7 +221,7 @@ pscsi_get_inquiry_vpd_serial(struct scsi_device *sdev, struct t10_wwn *wwn)
 
 	snprintf(&wwn->unit_serial[0], INQUIRY_VPD_SERIAL_LEN, "%s", &buf[4]);
 
-	wwn->t10_sub_dev->su_dev_flags |= SDF_FIRMWARE_VPD_UNIT_SERIAL;
+	wwn->t10_dev->dev_flags |= DF_FIRMWARE_VPD_UNIT_SERIAL;
 
 	kfree(buf);
 	return 0;
@@ -299,23 +301,13 @@ out:
 	kfree(buf);
 }
 
-/*	pscsi_add_device_to_list():
- *
- *
- */
-static struct se_device *pscsi_add_device_to_list(
-	struct se_hba *hba,
-	struct se_subsystem_dev *se_dev,
-	struct pscsi_dev_virt *pdv,
-	struct scsi_device *sd,
-	int dev_flags)
+static int pscsi_add_device_to_list(struct se_device *dev,
+		struct scsi_device *sd)
 {
-	struct se_device *dev;
-	struct se_dev_limits dev_limits;
-	struct request_queue *q;
-	struct queue_limits *limits;
+	struct pscsi_dev_virt *pdv = PSCSI_DEV(dev);
+	struct request_queue *q = sd->request_queue;
 
-	memset(&dev_limits, 0, sizeof(struct se_dev_limits));
+	pdv->pdv_sd = sd;
 
 	if (!sd->queue_depth) {
 		sd->queue_depth = PSCSI_DEFAULT_QUEUEDEPTH;
@@ -324,54 +316,27 @@ static struct se_device *pscsi_add_device_to_list(
 			" queue_depth to %d\n", sd->channel, sd->id,
 				sd->lun, sd->queue_depth);
 	}
-	/*
-	 * Setup the local scope queue_limits from struct request_queue->limits
-	 * to pass into transport_add_device_to_core_hba() as struct se_dev_limits.
-	 */
-	q = sd->request_queue;
-	limits = &dev_limits.limits;
-	limits->logical_block_size = sd->sector_size;
-	limits->max_hw_sectors = min_t(int, sd->host->max_sectors, queue_max_hw_sectors(q));
-	limits->max_sectors = min_t(int, sd->host->max_sectors, queue_max_sectors(q));
-	dev_limits.hw_queue_depth = sd->queue_depth;
-	dev_limits.queue_depth = sd->queue_depth;
-	/*
-	 * Setup our standard INQUIRY info into se_dev->t10_wwn
-	 */
-	pscsi_set_inquiry_info(sd, &se_dev->t10_wwn);
+
+	dev->dev_attrib.hw_block_size = sd->sector_size;
+	dev->dev_attrib.hw_max_sectors =
+		min_t(int, sd->host->max_sectors, queue_max_hw_sectors(q));
+	dev->dev_attrib.hw_queue_depth = sd->queue_depth;
 
 	/*
-	 * Set the pointer pdv->pdv_sd to from passed struct scsi_device,
-	 * which has already been referenced with Linux SCSI code with
-	 * scsi_device_get() in this file's pscsi_create_virtdevice().
-	 *
-	 * The passthrough operations called by the transport_add_device_*
-	 * function below will require this pointer to be set for passthroug
-	 *  ops.
-	 *
-	 * For the shutdown case in pscsi_free_device(), this struct
-	 * scsi_device  reference is released with Linux SCSI code
-	 * scsi_device_put() and the pdv->pdv_sd cleared.
+	 * Setup our standard INQUIRY info into se_dev->t10_wwn
 	 */
-	pdv->pdv_sd = sd;
-	dev = transport_add_device_to_core_hba(hba, &pscsi_template,
-				se_dev, dev_flags, pdv,
-				&dev_limits, NULL, NULL);
-	if (!dev) {
-		pdv->pdv_sd = NULL;
-		return NULL;
-	}
+	pscsi_set_inquiry_info(sd, &dev->t10_wwn);
 
 	/*
 	 * Locate VPD WWN Information used for various purposes within
 	 * the Storage Engine.
 	 */
-	if (!pscsi_get_inquiry_vpd_serial(sd, &se_dev->t10_wwn)) {
+	if (!pscsi_get_inquiry_vpd_serial(sd, &dev->t10_wwn)) {
 		/*
 		 * If VPD Unit Serial returned GOOD status, try
 		 * VPD Device Identification page (0x83).
 		 */
-		pscsi_get_inquiry_vpd_device_ident(sd, &se_dev->t10_wwn);
+		pscsi_get_inquiry_vpd_device_ident(sd, &dev->t10_wwn);
 	}
 
 	/*
@@ -379,10 +344,11 @@ static struct se_device *pscsi_add_device_to_list(
 	 */
 	if (sd->type == TYPE_TAPE)
 		pscsi_tape_read_blocksize(dev, sd);
-	return dev;
+	return 0;
 }
 
-static void *pscsi_allocate_virtdevice(struct se_hba *hba, const char *name)
+static struct se_device *pscsi_alloc_device(struct se_hba *hba,
+		const char *name)
 {
 	struct pscsi_dev_virt *pdv;
 
@@ -391,139 +357,125 @@ static void *pscsi_allocate_virtdevice(struct se_hba *hba, const char *name)
 		pr_err("Unable to allocate memory for struct pscsi_dev_virt\n");
 		return NULL;
 	}
-	pdv->pdv_se_hba = hba;
 
 	pr_debug("PSCSI: Allocated pdv: %p for %s\n", pdv, name);
-	return pdv;
+	return &pdv->dev;
 }
 
 /*
  * Called with struct Scsi_Host->host_lock called.
  */
-static struct se_device *pscsi_create_type_disk(
-	struct scsi_device *sd,
-	struct pscsi_dev_virt *pdv,
-	struct se_subsystem_dev *se_dev,
-	struct se_hba *hba)
+static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd)
 	__releases(sh->host_lock)
 {
-	struct se_device *dev;
-	struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr;
+	struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr;
+	struct pscsi_dev_virt *pdv = PSCSI_DEV(dev);
 	struct Scsi_Host *sh = sd->host;
 	struct block_device *bd;
-	u32 dev_flags = 0;
+	int ret;
 
 	if (scsi_device_get(sd)) {
 		pr_err("scsi_device_get() failed for %d:%d:%d:%d\n",
 			sh->host_no, sd->channel, sd->id, sd->lun);
 		spin_unlock_irq(sh->host_lock);
-		return NULL;
+		return -EIO;
 	}
 	spin_unlock_irq(sh->host_lock);
 	/*
 	 * Claim exclusive struct block_device access to struct scsi_device
 	 * for TYPE_DISK using supplied udev_path
 	 */
-	bd = blkdev_get_by_path(se_dev->se_dev_udev_path,
+	bd = blkdev_get_by_path(dev->udev_path,
 				FMODE_WRITE|FMODE_READ|FMODE_EXCL, pdv);
 	if (IS_ERR(bd)) {
 		pr_err("pSCSI: blkdev_get_by_path() failed\n");
 		scsi_device_put(sd);
-		return NULL;
+		return PTR_ERR(bd);
 	}
 	pdv->pdv_bd = bd;
 
-	dev = pscsi_add_device_to_list(hba, se_dev, pdv, sd, dev_flags);
-	if (!dev) {
+	ret = pscsi_add_device_to_list(dev, sd);
+	if (ret) {
 		blkdev_put(pdv->pdv_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL);
 		scsi_device_put(sd);
-		return NULL;
+		return ret;
 	}
+
 	pr_debug("CORE_PSCSI[%d] - Added TYPE_DISK for %d:%d:%d:%d\n",
 		phv->phv_host_id, sh->host_no, sd->channel, sd->id, sd->lun);
-
-	return dev;
+	return 0;
 }
 
 /*
  * Called with struct Scsi_Host->host_lock called.
  */
-static struct se_device *pscsi_create_type_rom(
-	struct scsi_device *sd,
-	struct pscsi_dev_virt *pdv,
-	struct se_subsystem_dev *se_dev,
-	struct se_hba *hba)
+static int pscsi_create_type_rom(struct se_device *dev, struct scsi_device *sd)
 	__releases(sh->host_lock)
 {
-	struct se_device *dev;
-	struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr;
+	struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr;
 	struct Scsi_Host *sh = sd->host;
-	u32 dev_flags = 0;
+	int ret;
 
 	if (scsi_device_get(sd)) {
 		pr_err("scsi_device_get() failed for %d:%d:%d:%d\n",
 			sh->host_no, sd->channel, sd->id, sd->lun);
 		spin_unlock_irq(sh->host_lock);
-		return NULL;
+		return -EIO;
 	}
 	spin_unlock_irq(sh->host_lock);
 
-	dev = pscsi_add_device_to_list(hba, se_dev, pdv, sd, dev_flags);
-	if (!dev) {
+	ret = pscsi_add_device_to_list(dev, sd);
+	if (ret) {
 		scsi_device_put(sd);
-		return NULL;
+		return ret;
 	}
 	pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%d\n",
 		phv->phv_host_id, scsi_device_type(sd->type), sh->host_no,
 		sd->channel, sd->id, sd->lun);
 
-	return dev;
+	return 0;
 }
 
 /*
- *Called with struct Scsi_Host->host_lock called.
+ * Called with struct Scsi_Host->host_lock called.
  */
-static struct se_device *pscsi_create_type_other(
-	struct scsi_device *sd,
-	struct pscsi_dev_virt *pdv,
-	struct se_subsystem_dev *se_dev,
-	struct se_hba *hba)
+static int pscsi_create_type_other(struct se_device *dev,
+		struct scsi_device *sd)
 	__releases(sh->host_lock)
 {
-	struct se_device *dev;
-	struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr;
+	struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr;
 	struct Scsi_Host *sh = sd->host;
-	u32 dev_flags = 0;
+	int ret;
 
 	spin_unlock_irq(sh->host_lock);
-	dev = pscsi_add_device_to_list(hba, se_dev, pdv, sd, dev_flags);
-	if (!dev)
-		return NULL;
+	ret = pscsi_add_device_to_list(dev, sd);
+	if (ret)
+		return ret;
 
 	pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%d\n",
 		phv->phv_host_id, scsi_device_type(sd->type), sh->host_no,
 		sd->channel, sd->id, sd->lun);
-
-	return dev;
+	return 0;
 }
 
-static struct se_device *pscsi_create_virtdevice(
-	struct se_hba *hba,
-	struct se_subsystem_dev *se_dev,
-	void *p)
+static int pscsi_configure_device(struct se_device *dev)
 {
-	struct pscsi_dev_virt *pdv = p;
-	struct se_device *dev;
+	struct se_hba *hba = dev->se_hba;
+	struct pscsi_dev_virt *pdv = PSCSI_DEV(dev);
 	struct scsi_device *sd;
-	struct pscsi_hba_virt *phv = hba->hba_ptr;
+	struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr;
 	struct Scsi_Host *sh = phv->phv_lld_host;
 	int legacy_mode_enable = 0;
+	int ret;
 
-	if (!pdv) {
-		pr_err("Unable to locate struct pscsi_dev_virt"
-				" parameter\n");
-		return ERR_PTR(-EINVAL);
+	if (!(pdv->pdv_flags & PDF_HAS_CHANNEL_ID) ||
+	    !(pdv->pdv_flags & PDF_HAS_TARGET_ID) ||
+	    !(pdv->pdv_flags & PDF_HAS_LUN_ID)) {
+		pr_err("Missing scsi_channel_id=, scsi_target_id= and"
+			" scsi_lun_id= parameters\n");
+		return -EINVAL;
 	}
+
 	/*
 	 * If not running in PHV_LLD_SCSI_HOST_NO mode, locate the
 	 * struct Scsi_Host we will need to bring the TCM/pSCSI object online
@@ -532,16 +484,16 @@ static struct se_device *pscsi_create_virtdevice(
 		if (phv->phv_mode == PHV_LLD_SCSI_HOST_NO) {
 			pr_err("pSCSI: Unable to locate struct"
 				" Scsi_Host for PHV_LLD_SCSI_HOST_NO\n");
-			return ERR_PTR(-ENODEV);
+			return -ENODEV;
 		}
 		/*
 		 * For the newer PHV_VIRTUAL_HOST_ID struct scsi_device
 		 * reference, we enforce that udev_path has been set
 		 */
-		if (!(se_dev->su_dev_flags & SDF_USING_UDEV_PATH)) {
+		if (!(dev->dev_flags & DF_USING_UDEV_PATH)) {
 			pr_err("pSCSI: udev_path attribute has not"
 				" been set before ENABLE=1\n");
-			return ERR_PTR(-EINVAL);
+			return -EINVAL;
 		}
 		/*
 		 * If no scsi_host_id= was passed for PHV_VIRTUAL_HOST_ID,
@@ -549,17 +501,14 @@ static struct se_device *pscsi_create_virtdevice(
 		 * and enable for PHV_LLD_SCSI_HOST_NO mode.
 		 */
 		if (!(pdv->pdv_flags & PDF_HAS_VIRT_HOST_ID)) {
-			spin_lock(&hba->device_lock);
-			if (!list_empty(&hba->hba_dev_list)) {
+			if (hba->dev_count) {
 				pr_err("pSCSI: Unable to set hba_mode"
 					" with active devices\n");
-				spin_unlock(&hba->device_lock);
-				return ERR_PTR(-EEXIST);
+				return -EEXIST;
 			}
-			spin_unlock(&hba->device_lock);
 
 			if (pscsi_pmode_enable_hba(hba, 1) != 1)
-				return ERR_PTR(-ENODEV);
+				return -ENODEV;
 
 			legacy_mode_enable = 1;
 			hba->hba_flags |= HBA_FLAGS_PSCSI_MODE;
@@ -569,14 +518,14 @@ static struct se_device *pscsi_create_virtdevice(
 			if (IS_ERR(sh)) {
 				pr_err("pSCSI: Unable to locate"
 					" pdv_host_id: %d\n", pdv->pdv_host_id);
-				return ERR_CAST(sh);
+				return PTR_ERR(sh);
 			}
 		}
 	} else {
 		if (phv->phv_mode == PHV_VIRTUAL_HOST_ID) {
 			pr_err("pSCSI: PHV_VIRTUAL_HOST_ID set while"
 				" struct Scsi_Host exists\n");
-			return ERR_PTR(-EEXIST);
+			return -EEXIST;
 		}
 	}
 
@@ -593,17 +542,17 @@ static struct se_device *pscsi_create_virtdevice(
 		 */
 		switch (sd->type) {
 		case TYPE_DISK:
-			dev = pscsi_create_type_disk(sd, pdv, se_dev, hba);
+			ret = pscsi_create_type_disk(dev, sd);
 			break;
 		case TYPE_ROM:
-			dev = pscsi_create_type_rom(sd, pdv, se_dev, hba);
+			ret = pscsi_create_type_rom(dev, sd);
 			break;
 		default:
-			dev = pscsi_create_type_other(sd, pdv, se_dev, hba);
+			ret = pscsi_create_type_other(dev, sd);
 			break;
 		}
 
-		if (!dev) {
+		if (ret) {
 			if (phv->phv_mode == PHV_VIRTUAL_HOST_ID)
 				scsi_host_put(sh);
 			else if (legacy_mode_enable) {
@@ -611,9 +560,9 @@ static struct se_device *pscsi_create_virtdevice(
 				hba->hba_flags &= ~HBA_FLAGS_PSCSI_MODE;
 			}
 			pdv->pdv_sd = NULL;
-			return ERR_PTR(-ENODEV);
+			return ret;
 		}
-		return dev;
+		return 0;
 	}
 	spin_unlock_irq(sh->host_lock);
 
@@ -627,17 +576,13 @@ static struct se_device *pscsi_create_virtdevice(
 		hba->hba_flags &= ~HBA_FLAGS_PSCSI_MODE;
 	}
 
-	return ERR_PTR(-ENODEV);
+	return -ENODEV;
 }
 
-/*	pscsi_free_device(): (Part of se_subsystem_api_t template)
- *
- *
- */
-static void pscsi_free_device(void *p)
+static void pscsi_free_device(struct se_device *dev)
 {
-	struct pscsi_dev_virt *pdv = p;
-	struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr;
+	struct pscsi_dev_virt *pdv = PSCSI_DEV(dev);
+	struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr;
 	struct scsi_device *sd = pdv->pdv_sd;
 
 	if (sd) {
@@ -670,7 +615,7 @@ static void pscsi_free_device(void *p)
 static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg,
 				     unsigned char *sense_buffer)
 {
-	struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr;
+	struct pscsi_dev_virt *pdv = PSCSI_DEV(cmd->se_dev);
 	struct scsi_device *sd = pdv->pdv_sd;
 	int result;
 	struct pscsi_plugin_task *pt = cmd->priv;
@@ -694,7 +639,11 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg,
 	if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) &&
 	     (status_byte(result) << 1) == SAM_STAT_GOOD) {
 		if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) {
-			unsigned char *buf = transport_kmap_data_sg(cmd);
+			unsigned char *buf;
+
+			buf = transport_kmap_data_sg(cmd);
+			if (!buf)
+				; /* XXX: TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE */
 
 			if (cdb[0] == MODE_SENSE_10) {
 				if (!(buf[3] & 0x80))
@@ -770,13 +719,11 @@ static match_table_t tokens = {
 	{Opt_err, NULL}
 };
 
-static ssize_t pscsi_set_configfs_dev_params(struct se_hba *hba,
-	struct se_subsystem_dev *se_dev,
-	const char *page,
-	ssize_t count)
+static ssize_t pscsi_set_configfs_dev_params(struct se_device *dev,
+		const char *page, ssize_t count)
 {
-	struct pscsi_dev_virt *pdv = se_dev->se_dev_su_ptr;
-	struct pscsi_hba_virt *phv = hba->hba_ptr;
+	struct pscsi_dev_virt *pdv = PSCSI_DEV(dev);
+	struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr;
 	char *orig, *ptr, *opts;
 	substring_t args[MAX_OPT_ARGS];
 	int ret = 0, arg, token;
@@ -841,29 +788,10 @@ out:
 	return (!ret) ? count : ret;
 }
 
-static ssize_t pscsi_check_configfs_dev_params(
-	struct se_hba *hba,
-	struct se_subsystem_dev *se_dev)
+static ssize_t pscsi_show_configfs_dev_params(struct se_device *dev, char *b)
 {
-	struct pscsi_dev_virt *pdv = se_dev->se_dev_su_ptr;
-
-	if (!(pdv->pdv_flags & PDF_HAS_CHANNEL_ID) ||
-	    !(pdv->pdv_flags & PDF_HAS_TARGET_ID) ||
-	    !(pdv->pdv_flags & PDF_HAS_LUN_ID)) {
-		pr_err("Missing scsi_channel_id=, scsi_target_id= and"
-			" scsi_lun_id= parameters\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static ssize_t pscsi_show_configfs_dev_params(struct se_hba *hba,
-					      struct se_subsystem_dev *se_dev,
-					      char *b)
-{
-	struct pscsi_hba_virt *phv = hba->hba_ptr;
-        struct pscsi_dev_virt *pdv = se_dev->se_dev_su_ptr;
+	struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr;
+	struct pscsi_dev_virt *pdv = PSCSI_DEV(dev);
 	struct scsi_device *sd = pdv->pdv_sd;
 	unsigned char host_id[16];
 	ssize_t bl;
@@ -929,11 +857,11 @@ static inline struct bio *pscsi_get_bio(int sg_num)
 	return bio;
 }
 
-static int pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl,
-		u32 sgl_nents, enum dma_data_direction data_direction,
-		struct bio **hbio)
+static sense_reason_t
+pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
+		enum dma_data_direction data_direction, struct bio **hbio)
 {
-	struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr;
+	struct pscsi_dev_virt *pdv = PSCSI_DEV(cmd->se_dev);
 	struct bio *bio = NULL, *tbio = NULL;
 	struct page *page;
 	struct scatterlist *sg;
@@ -1019,7 +947,7 @@ static int pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl,
 		}
 	}
 
-	return sgl_nents;
+	return 0;
 fail:
 	while (*hbio) {
 		bio = *hbio;
@@ -1027,8 +955,7 @@ fail:
 		bio->bi_next = NULL;
 		bio_endio(bio, 0);	/* XXX: should be error */
 	}
-	cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-	return -ENOMEM;
+	return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 }
 
 /*
@@ -1055,17 +982,13 @@ static inline void pscsi_clear_cdb_lun(unsigned char *cdb)
 	}
 }
 
-static int pscsi_parse_cdb(struct se_cmd *cmd)
+static sense_reason_t
+pscsi_parse_cdb(struct se_cmd *cmd)
 {
 	unsigned char *cdb = cmd->t_task_cdb;
-	unsigned int dummy_size;
-	int ret;
 
-	if (cmd->se_cmd_flags & SCF_BIDI) {
-		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-		return -EINVAL;
-	}
+	if (cmd->se_cmd_flags & SCF_BIDI)
+		return TCM_UNSUPPORTED_SCSI_OPCODE;
 
 	pscsi_clear_cdb_lun(cdb);
 
@@ -1076,10 +999,8 @@ static int pscsi_parse_cdb(struct se_cmd *cmd)
 	 */
 	switch (cdb[0]) {
 	case REPORT_LUNS:
-		ret = spc_parse_cdb(cmd, &dummy_size);
-		if (ret)
-			return ret;
-		break;
+		cmd->execute_cmd = spc_emulate_report_luns;
+		return 0;
 	case READ_6:
 	case READ_10:
 	case READ_12:
@@ -1093,22 +1014,21 @@ static int pscsi_parse_cdb(struct se_cmd *cmd)
 		/* FALLTHROUGH*/
 	default:
 		cmd->execute_cmd = pscsi_execute_cmd;
-		break;
+		return 0;
 	}
-
-	return 0;
 }
 
-static int pscsi_execute_cmd(struct se_cmd *cmd)
+static sense_reason_t
+pscsi_execute_cmd(struct se_cmd *cmd)
 {
 	struct scatterlist *sgl = cmd->t_data_sg;
 	u32 sgl_nents = cmd->t_data_nents;
 	enum dma_data_direction data_direction = cmd->data_direction;
-	struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr;
+	struct pscsi_dev_virt *pdv = PSCSI_DEV(cmd->se_dev);
 	struct pscsi_plugin_task *pt;
 	struct request *req;
 	struct bio *hbio;
-	int ret;
+	sense_reason_t ret;
 
 	/*
 	 * Dynamically alloc cdb space, since it may be larger than
@@ -1116,8 +1036,7 @@ static int pscsi_execute_cmd(struct se_cmd *cmd)
 	 */
 	pt = kzalloc(sizeof(*pt) + scsi_command_size(cmd->t_task_cdb), GFP_KERNEL);
 	if (!pt) {
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-		return -ENOMEM;
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	}
 	cmd->priv = pt;
 
@@ -1131,24 +1050,21 @@ static int pscsi_execute_cmd(struct se_cmd *cmd)
 		if (!req || IS_ERR(req)) {
 			pr_err("PSCSI: blk_get_request() failed: %ld\n",
 					req ? IS_ERR(req) : -ENOMEM);
-			cmd->scsi_sense_reason =
-				TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+			ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 			goto fail;
 		}
 	} else {
 		BUG_ON(!cmd->data_length);
 
 		ret = pscsi_map_sg(cmd, sgl, sgl_nents, data_direction, &hbio);
-		if (ret < 0) {
-			cmd->scsi_sense_reason =
-				TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+		if (ret)
 			goto fail;
-		}
 
 		req = blk_make_request(pdv->pdv_sd->request_queue, hbio,
 				       GFP_KERNEL);
 		if (IS_ERR(req)) {
 			pr_err("pSCSI: blk_make_request() failed\n");
+			ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 			goto fail_free_bio;
 		}
 	}
@@ -1179,22 +1095,10 @@ fail_free_bio:
 		bio->bi_next = NULL;
 		bio_endio(bio, 0);	/* XXX: should be error */
 	}
-	cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+	ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 fail:
 	kfree(pt);
-	return -ENOMEM;
-}
-
-/*	pscsi_get_device_rev():
- *
- *
- */
-static u32 pscsi_get_device_rev(struct se_device *dev)
-{
-	struct pscsi_dev_virt *pdv = dev->dev_ptr;
-	struct scsi_device *sd = pdv->pdv_sd;
-
-	return (sd->scsi_level - 1) ? sd->scsi_level - 1 : 1;
+	return ret;
 }
 
 /*	pscsi_get_device_type():
@@ -1203,7 +1107,7 @@ static u32 pscsi_get_device_rev(struct se_device *dev)
  */
 static u32 pscsi_get_device_type(struct se_device *dev)
 {
-	struct pscsi_dev_virt *pdv = dev->dev_ptr;
+	struct pscsi_dev_virt *pdv = PSCSI_DEV(dev);
 	struct scsi_device *sd = pdv->pdv_sd;
 
 	return sd->type;
@@ -1211,7 +1115,7 @@ static u32 pscsi_get_device_type(struct se_device *dev)
 
 static sector_t pscsi_get_blocks(struct se_device *dev)
 {
-	struct pscsi_dev_virt *pdv = dev->dev_ptr;
+	struct pscsi_dev_virt *pdv = PSCSI_DEV(dev);
 
 	if (pdv->pdv_bd && pdv->pdv_bd->bd_part)
 		return pdv->pdv_bd->bd_part->nr_sects;
@@ -1243,7 +1147,6 @@ static void pscsi_req_done(struct request *req, int uptodate)
 		pr_debug("PSCSI Host Byte exception at cmd: %p CDB:"
 			" 0x%02x Result: 0x%08x\n", cmd, pt->pscsi_cdb[0],
 			pt->pscsi_result);
-		cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
 		target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION);
 		break;
 	}
@@ -1259,15 +1162,13 @@ static struct se_subsystem_api pscsi_template = {
 	.attach_hba		= pscsi_attach_hba,
 	.detach_hba		= pscsi_detach_hba,
 	.pmode_enable_hba	= pscsi_pmode_enable_hba,
-	.allocate_virtdevice	= pscsi_allocate_virtdevice,
-	.create_virtdevice	= pscsi_create_virtdevice,
+	.alloc_device		= pscsi_alloc_device,
+	.configure_device	= pscsi_configure_device,
 	.free_device		= pscsi_free_device,
 	.transport_complete	= pscsi_transport_complete,
 	.parse_cdb		= pscsi_parse_cdb,
-	.check_configfs_dev_params = pscsi_check_configfs_dev_params,
 	.set_configfs_dev_params = pscsi_set_configfs_dev_params,
 	.show_configfs_dev_params = pscsi_show_configfs_dev_params,
-	.get_device_rev		= pscsi_get_device_rev,
 	.get_device_type	= pscsi_get_device_type,
 	.get_blocks		= pscsi_get_blocks,
 };
diff --git a/drivers/target/target_core_pscsi.h b/drivers/target/target_core_pscsi.h
index bc1e5e11..1bd757d 100644
--- a/drivers/target/target_core_pscsi.h
+++ b/drivers/target/target_core_pscsi.h
@@ -37,6 +37,7 @@ struct pscsi_plugin_task {
 #define PDF_HAS_VIRT_HOST_ID	0x20
 
 struct pscsi_dev_virt {
+	struct se_device dev;
 	int	pdv_flags;
 	int	pdv_host_id;
 	int	pdv_channel_id;
@@ -44,7 +45,6 @@ struct pscsi_dev_virt {
 	int	pdv_lun_id;
 	struct block_device *pdv_bd;
 	struct scsi_device *pdv_sd;
-	struct se_hba *pdv_se_hba;
 } ____cacheline_aligned;
 
 typedef enum phv_modes {
diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c
index d00bbe3..0457de3 100644
--- a/drivers/target/target_core_rd.c
+++ b/drivers/target/target_core_rd.c
@@ -4,10 +4,7 @@
  * This file contains the Storage Engine <-> Ramdisk transport
  * specific functions.
  *
- * Copyright (c) 2003, 2004, 2005 PyX Technologies, Inc.
- * Copyright (c) 2005, 2006, 2007 SBE, Inc.
- * Copyright (c) 2007-2010 Rising Tide Systems
- * Copyright (c) 2008-2010 Linux-iSCSI.org
+ * (c) Copyright 2003-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@kernel.org>
  *
@@ -41,7 +38,10 @@
 
 #include "target_core_rd.h"
 
-static struct se_subsystem_api rd_mcp_template;
+static inline struct rd_dev *RD_DEV(struct se_device *dev)
+{
+	return container_of(dev, struct rd_dev, dev);
+}
 
 /*	rd_attach_hba(): (Part of se_subsystem_api_t template)
  *
@@ -196,7 +196,7 @@ static int rd_build_device_space(struct rd_dev *rd_dev)
 	return 0;
 }
 
-static void *rd_allocate_virtdevice(struct se_hba *hba, const char *name)
+static struct se_device *rd_alloc_device(struct se_hba *hba, const char *name)
 {
 	struct rd_dev *rd_dev;
 	struct rd_host *rd_host = hba->hba_ptr;
@@ -209,39 +209,27 @@ static void *rd_allocate_virtdevice(struct se_hba *hba, const char *name)
 
 	rd_dev->rd_host = rd_host;
 
-	return rd_dev;
+	return &rd_dev->dev;
 }
 
-static struct se_device *rd_create_virtdevice(struct se_hba *hba,
-		struct se_subsystem_dev *se_dev, void *p)
+static int rd_configure_device(struct se_device *dev)
 {
-	struct se_device *dev;
-	struct se_dev_limits dev_limits;
-	struct rd_dev *rd_dev = p;
-	struct rd_host *rd_host = hba->hba_ptr;
-	int dev_flags = 0, ret;
-	char prod[16], rev[4];
+	struct rd_dev *rd_dev = RD_DEV(dev);
+	struct rd_host *rd_host = dev->se_hba->hba_ptr;
+	int ret;
 
-	memset(&dev_limits, 0, sizeof(struct se_dev_limits));
+	if (!(rd_dev->rd_flags & RDF_HAS_PAGE_COUNT)) {
+		pr_debug("Missing rd_pages= parameter\n");
+		return -EINVAL;
+	}
 
 	ret = rd_build_device_space(rd_dev);
 	if (ret < 0)
 		goto fail;
 
-	snprintf(prod, 16, "RAMDISK-MCP");
-	snprintf(rev, 4, "%s", RD_MCP_VERSION);
-
-	dev_limits.limits.logical_block_size = RD_BLOCKSIZE;
-	dev_limits.limits.max_hw_sectors = UINT_MAX;
-	dev_limits.limits.max_sectors = UINT_MAX;
-	dev_limits.hw_queue_depth = RD_MAX_DEVICE_QUEUE_DEPTH;
-	dev_limits.queue_depth = RD_DEVICE_QUEUE_DEPTH;
-
-	dev = transport_add_device_to_core_hba(hba,
-			&rd_mcp_template, se_dev, dev_flags, rd_dev,
-			&dev_limits, prod, rev);
-	if (!dev)
-		goto fail;
+	dev->dev_attrib.hw_block_size = RD_BLOCKSIZE;
+	dev->dev_attrib.hw_max_sectors = UINT_MAX;
+	dev->dev_attrib.hw_queue_depth = RD_MAX_DEVICE_QUEUE_DEPTH;
 
 	rd_dev->rd_dev_id = rd_host->rd_host_dev_id_count++;
 
@@ -251,16 +239,16 @@ static struct se_device *rd_create_virtdevice(struct se_hba *hba,
 		rd_dev->sg_table_count,
 		(unsigned long)(rd_dev->rd_page_count * PAGE_SIZE));
 
-	return dev;
+	return 0;
 
 fail:
 	rd_release_device_space(rd_dev);
-	return ERR_PTR(ret);
+	return ret;
 }
 
-static void rd_free_device(void *p)
+static void rd_free_device(struct se_device *dev)
 {
-	struct rd_dev *rd_dev = p;
+	struct rd_dev *rd_dev = RD_DEV(dev);
 
 	rd_release_device_space(rd_dev);
 	kfree(rd_dev);
@@ -284,13 +272,14 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page)
 	return NULL;
 }
 
-static int rd_execute_rw(struct se_cmd *cmd)
+static sense_reason_t
+rd_execute_rw(struct se_cmd *cmd)
 {
 	struct scatterlist *sgl = cmd->t_data_sg;
 	u32 sgl_nents = cmd->t_data_nents;
 	enum dma_data_direction data_direction = cmd->data_direction;
 	struct se_device *se_dev = cmd->se_dev;
-	struct rd_dev *dev = se_dev->dev_ptr;
+	struct rd_dev *dev = RD_DEV(se_dev);
 	struct rd_dev_sg_table *table;
 	struct scatterlist *rd_sg;
 	struct sg_mapping_iter m;
@@ -300,14 +289,14 @@ static int rd_execute_rw(struct se_cmd *cmd)
 	u32 src_len;
 	u64 tmp;
 
-	tmp = cmd->t_task_lba * se_dev->se_sub_dev->se_dev_attrib.block_size;
+	tmp = cmd->t_task_lba * se_dev->dev_attrib.block_size;
 	rd_offset = do_div(tmp, PAGE_SIZE);
 	rd_page = tmp;
 	rd_size = cmd->data_length;
 
 	table = rd_get_sg_table(dev, rd_page);
 	if (!table)
-		return -EINVAL;
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
 	rd_sg = &table->sg_table[rd_page - table->page_start_offset];
 
@@ -357,7 +346,7 @@ static int rd_execute_rw(struct se_cmd *cmd)
 		table = rd_get_sg_table(dev, rd_page);
 		if (!table) {
 			sg_miter_stop(&m);
-			return -EINVAL;
+			return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 		}
 
 		/* since we increment, the first sg entry is correct */
@@ -378,13 +367,10 @@ static match_table_t tokens = {
 	{Opt_err, NULL}
 };
 
-static ssize_t rd_set_configfs_dev_params(
-	struct se_hba *hba,
-	struct se_subsystem_dev *se_dev,
-	const char *page,
-	ssize_t count)
+static ssize_t rd_set_configfs_dev_params(struct se_device *dev,
+		const char *page, ssize_t count)
 {
-	struct rd_dev *rd_dev = se_dev->se_dev_su_ptr;
+	struct rd_dev *rd_dev = RD_DEV(dev);
 	char *orig, *ptr, *opts;
 	substring_t args[MAX_OPT_ARGS];
 	int ret = 0, arg, token;
@@ -417,24 +403,10 @@ static ssize_t rd_set_configfs_dev_params(
 	return (!ret) ? count : ret;
 }
 
-static ssize_t rd_check_configfs_dev_params(struct se_hba *hba, struct se_subsystem_dev *se_dev)
+static ssize_t rd_show_configfs_dev_params(struct se_device *dev, char *b)
 {
-	struct rd_dev *rd_dev = se_dev->se_dev_su_ptr;
+	struct rd_dev *rd_dev = RD_DEV(dev);
 
-	if (!(rd_dev->rd_flags & RDF_HAS_PAGE_COUNT)) {
-		pr_debug("Missing rd_pages= parameter\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static ssize_t rd_show_configfs_dev_params(
-	struct se_hba *hba,
-	struct se_subsystem_dev *se_dev,
-	char *b)
-{
-	struct rd_dev *rd_dev = se_dev->se_dev_su_ptr;
 	ssize_t bl = sprintf(b, "TCM RamDisk ID: %u  RamDisk Makeup: rd_mcp\n",
 			rd_dev->rd_dev_id);
 	bl += sprintf(b + bl, "        PAGES/PAGE_SIZE: %u*%lu"
@@ -443,48 +415,40 @@ static ssize_t rd_show_configfs_dev_params(
 	return bl;
 }
 
-static u32 rd_get_device_rev(struct se_device *dev)
-{
-	return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */
-}
-
-static u32 rd_get_device_type(struct se_device *dev)
-{
-	return TYPE_DISK;
-}
-
 static sector_t rd_get_blocks(struct se_device *dev)
 {
-	struct rd_dev *rd_dev = dev->dev_ptr;
+	struct rd_dev *rd_dev = RD_DEV(dev);
+
 	unsigned long long blocks_long = ((rd_dev->rd_page_count * PAGE_SIZE) /
-			dev->se_sub_dev->se_dev_attrib.block_size) - 1;
+			dev->dev_attrib.block_size) - 1;
 
 	return blocks_long;
 }
 
-static struct spc_ops rd_spc_ops = {
+static struct sbc_ops rd_sbc_ops = {
 	.execute_rw		= rd_execute_rw,
 };
 
-static int rd_parse_cdb(struct se_cmd *cmd)
+static sense_reason_t
+rd_parse_cdb(struct se_cmd *cmd)
 {
-	return sbc_parse_cdb(cmd, &rd_spc_ops);
+	return sbc_parse_cdb(cmd, &rd_sbc_ops);
 }
 
 static struct se_subsystem_api rd_mcp_template = {
 	.name			= "rd_mcp",
+	.inquiry_prod		= "RAMDISK-MCP",
+	.inquiry_rev		= RD_MCP_VERSION,
 	.transport_type		= TRANSPORT_PLUGIN_VHBA_VDEV,
 	.attach_hba		= rd_attach_hba,
 	.detach_hba		= rd_detach_hba,
-	.allocate_virtdevice	= rd_allocate_virtdevice,
-	.create_virtdevice	= rd_create_virtdevice,
+	.alloc_device		= rd_alloc_device,
+	.configure_device	= rd_configure_device,
 	.free_device		= rd_free_device,
 	.parse_cdb		= rd_parse_cdb,
-	.check_configfs_dev_params = rd_check_configfs_dev_params,
 	.set_configfs_dev_params = rd_set_configfs_dev_params,
 	.show_configfs_dev_params = rd_show_configfs_dev_params,
-	.get_device_rev		= rd_get_device_rev,
-	.get_device_type	= rd_get_device_type,
+	.get_device_type	= sbc_get_device_type,
 	.get_blocks		= rd_get_blocks,
 };
 
diff --git a/drivers/target/target_core_rd.h b/drivers/target/target_core_rd.h
index 2145812..933b38b 100644
--- a/drivers/target/target_core_rd.h
+++ b/drivers/target/target_core_rd.h
@@ -24,6 +24,7 @@ struct rd_dev_sg_table {
 #define RDF_HAS_PAGE_COUNT	0x01
 
 struct rd_dev {
+	struct se_device dev;
 	u32		rd_flags;
 	/* Unique Ramdisk Device ID in Ramdisk HBA */
 	u32		rd_dev_id;
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index a6e27d9..26a6d18 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -1,10 +1,7 @@
 /*
  * SCSI Block Commands (SBC) parsing and emulation.
  *
- * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc.
- * Copyright (c) 2005, 2006, 2007 SBE, Inc.
- * Copyright (c) 2007-2010 Rising Tide Systems
- * Copyright (c) 2008-2010 Linux-iSCSI.org
+ * (c) Copyright 2002-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@kernel.org>
  *
@@ -37,7 +34,8 @@
 #include "target_core_ua.h"
 
 
-static int sbc_emulate_readcapacity(struct se_cmd *cmd)
+static sense_reason_t
+sbc_emulate_readcapacity(struct se_cmd *cmd)
 {
 	struct se_device *dev = cmd->se_dev;
 	unsigned long long blocks_long = dev->transport->get_blocks(dev);
@@ -54,22 +52,24 @@ static int sbc_emulate_readcapacity(struct se_cmd *cmd)
 	buf[1] = (blocks >> 16) & 0xff;
 	buf[2] = (blocks >> 8) & 0xff;
 	buf[3] = blocks & 0xff;
-	buf[4] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff;
-	buf[5] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff;
-	buf[6] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff;
-	buf[7] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff;
+	buf[4] = (dev->dev_attrib.block_size >> 24) & 0xff;
+	buf[5] = (dev->dev_attrib.block_size >> 16) & 0xff;
+	buf[6] = (dev->dev_attrib.block_size >> 8) & 0xff;
+	buf[7] = dev->dev_attrib.block_size & 0xff;
 
 	rbuf = transport_kmap_data_sg(cmd);
-	if (rbuf) {
-		memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
-		transport_kunmap_data_sg(cmd);
-	}
+	if (!rbuf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+	memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+	transport_kunmap_data_sg(cmd);
 
 	target_complete_cmd(cmd, GOOD);
 	return 0;
 }
 
-static int sbc_emulate_readcapacity_16(struct se_cmd *cmd)
+static sense_reason_t
+sbc_emulate_readcapacity_16(struct se_cmd *cmd)
 {
 	struct se_device *dev = cmd->se_dev;
 	unsigned char *rbuf;
@@ -85,28 +85,29 @@ static int sbc_emulate_readcapacity_16(struct se_cmd *cmd)
 	buf[5] = (blocks >> 16) & 0xff;
 	buf[6] = (blocks >> 8) & 0xff;
 	buf[7] = blocks & 0xff;
-	buf[8] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff;
-	buf[9] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff;
-	buf[10] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff;
-	buf[11] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff;
+	buf[8] = (dev->dev_attrib.block_size >> 24) & 0xff;
+	buf[9] = (dev->dev_attrib.block_size >> 16) & 0xff;
+	buf[10] = (dev->dev_attrib.block_size >> 8) & 0xff;
+	buf[11] = dev->dev_attrib.block_size & 0xff;
 	/*
 	 * Set Thin Provisioning Enable bit following sbc3r22 in section
 	 * READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled.
 	 */
-	if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
+	if (dev->dev_attrib.emulate_tpu || dev->dev_attrib.emulate_tpws)
 		buf[14] = 0x80;
 
 	rbuf = transport_kmap_data_sg(cmd);
-	if (rbuf) {
-		memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
-		transport_kunmap_data_sg(cmd);
-	}
+	if (!rbuf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+	memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+	transport_kunmap_data_sg(cmd);
 
 	target_complete_cmd(cmd, GOOD);
 	return 0;
 }
 
-int spc_get_write_same_sectors(struct se_cmd *cmd)
+sector_t spc_get_write_same_sectors(struct se_cmd *cmd)
 {
 	u32 num_blocks;
 
@@ -129,13 +130,8 @@ int spc_get_write_same_sectors(struct se_cmd *cmd)
 }
 EXPORT_SYMBOL(spc_get_write_same_sectors);
 
-static int sbc_emulate_verify(struct se_cmd *cmd)
-{
-	target_complete_cmd(cmd, GOOD);
-	return 0;
-}
-
-static int sbc_emulate_noop(struct se_cmd *cmd)
+static sense_reason_t
+sbc_emulate_noop(struct se_cmd *cmd)
 {
 	target_complete_cmd(cmd, GOOD);
 	return 0;
@@ -143,7 +139,7 @@ static int sbc_emulate_noop(struct se_cmd *cmd)
 
 static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors)
 {
-	return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors;
+	return cmd->se_dev->dev_attrib.block_size * sectors;
 }
 
 static int sbc_check_valid_sectors(struct se_cmd *cmd)
@@ -152,7 +148,7 @@ static int sbc_check_valid_sectors(struct se_cmd *cmd)
 	unsigned long long end_lba;
 	u32 sectors;
 
-	sectors = cmd->data_length / dev->se_sub_dev->se_dev_attrib.block_size;
+	sectors = cmd->data_length / dev->dev_attrib.block_size;
 	end_lba = dev->transport->get_blocks(dev) + 1;
 
 	if (cmd->t_task_lba + sectors > end_lba) {
@@ -236,26 +232,37 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb)
 	return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32;
 }
 
-static int sbc_write_same_supported(struct se_device *dev,
-		unsigned char *flags)
+static sense_reason_t
+sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops)
 {
+	unsigned int sectors = spc_get_write_same_sectors(cmd);
+
 	if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
 		pr_err("WRITE_SAME PBDATA and LBDATA"
 			" bits not supported for Block Discard"
 			" Emulation\n");
-		return -ENOSYS;
+		return TCM_UNSUPPORTED_SCSI_OPCODE;
+	}
+	if (sectors > cmd->se_dev->dev_attrib.max_write_same_len) {
+		pr_warn("WRITE_SAME sectors: %u exceeds max_write_same_len: %u\n",
+			sectors, cmd->se_dev->dev_attrib.max_write_same_len);
+		return TCM_INVALID_CDB_FIELD;
 	}
-
 	/*
-	 * Currently for the emulated case we only accept
-	 * tpws with the UNMAP=1 bit set.
+	 * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting
+	 * translated into block discard requests within backend code.
 	 */
-	if (!(flags[0] & 0x08)) {
-		pr_err("WRITE_SAME w/o UNMAP bit not"
-			" supported for Block Discard Emulation\n");
-		return -ENOSYS;
+	if (flags[0] & 0x08) {
+		if (!ops->execute_write_same_unmap)
+			return TCM_UNSUPPORTED_SCSI_OPCODE;
+
+		cmd->execute_cmd = ops->execute_write_same_unmap;
+		return 0;
 	}
+	if (!ops->execute_write_same)
+		return TCM_UNSUPPORTED_SCSI_OPCODE;
 
+	cmd->execute_cmd = ops->execute_write_same;
 	return 0;
 }
 
@@ -313,14 +320,14 @@ out:
 	kfree(buf);
 }
 
-int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
+sense_reason_t
+sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
 {
-	struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
 	struct se_device *dev = cmd->se_dev;
 	unsigned char *cdb = cmd->t_task_cdb;
 	unsigned int size;
 	u32 sectors = 0;
-	int ret;
+	sense_reason_t ret;
 
 	switch (cdb[0]) {
 	case READ_6:
@@ -379,9 +386,9 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
 		cmd->execute_cmd = ops->execute_rw;
 		break;
 	case XDWRITEREAD_10:
-		if ((cmd->data_direction != DMA_TO_DEVICE) ||
+		if (cmd->data_direction != DMA_TO_DEVICE ||
 		    !(cmd->se_cmd_flags & SCF_BIDI))
-			goto out_invalid_cdb_field;
+			return TCM_INVALID_CDB_FIELD;
 		sectors = transport_get_sectors_10(cdb);
 
 		cmd->t_task_lba = transport_lba_32(cdb);
@@ -419,27 +426,24 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
 				cmd->se_cmd_flags |= SCF_FUA;
 			break;
 		case WRITE_SAME_32:
-			if (!ops->execute_write_same)
-				goto out_unsupported_cdb;
-
 			sectors = transport_get_sectors_32(cdb);
 			if (!sectors) {
 				pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not"
 				       " supported\n");
-				goto out_invalid_cdb_field;
+				return TCM_INVALID_CDB_FIELD;
 			}
 
 			size = sbc_get_size(cmd, 1);
 			cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
 
-			if (sbc_write_same_supported(dev, &cdb[10]) < 0)
-				goto out_unsupported_cdb;
-			cmd->execute_cmd = ops->execute_write_same;
+			ret = sbc_setup_write_same(cmd, &cdb[10], ops);
+			if (ret)
+				return ret;
 			break;
 		default:
 			pr_err("VARIABLE_LENGTH_CMD service action"
 				" 0x%04x not supported\n", service_action);
-			goto out_unsupported_cdb;
+			return TCM_UNSUPPORTED_SCSI_OPCODE;
 		}
 		break;
 	}
@@ -455,7 +459,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
 		default:
 			pr_err("Unsupported SA: 0x%02x\n",
 				cmd->t_task_cdb[1] & 0x1f);
-			goto out_invalid_cdb_field;
+			return TCM_INVALID_CDB_FIELD;
 		}
 		size = (cdb[10] << 24) | (cdb[11] << 16) |
 		       (cdb[12] << 8) | cdb[13];
@@ -463,7 +467,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
 	case SYNCHRONIZE_CACHE:
 	case SYNCHRONIZE_CACHE_16:
 		if (!ops->execute_sync_cache)
-			goto out_unsupported_cdb;
+			return TCM_UNSUPPORTED_SCSI_OPCODE;
 
 		/*
 		 * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE
@@ -484,42 +488,36 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
 		 */
 		if (cmd->t_task_lba || sectors) {
 			if (sbc_check_valid_sectors(cmd) < 0)
-				goto out_invalid_cdb_field;
+				return TCM_INVALID_CDB_FIELD;
 		}
 		cmd->execute_cmd = ops->execute_sync_cache;
 		break;
 	case UNMAP:
 		if (!ops->execute_unmap)
-			goto out_unsupported_cdb;
+			return TCM_UNSUPPORTED_SCSI_OPCODE;
 
 		size = get_unaligned_be16(&cdb[7]);
 		cmd->execute_cmd = ops->execute_unmap;
 		break;
 	case WRITE_SAME_16:
-		if (!ops->execute_write_same)
-			goto out_unsupported_cdb;
-
 		sectors = transport_get_sectors_16(cdb);
 		if (!sectors) {
 			pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
-			goto out_invalid_cdb_field;
+			return TCM_INVALID_CDB_FIELD;
 		}
 
 		size = sbc_get_size(cmd, 1);
 		cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
 
-		if (sbc_write_same_supported(dev, &cdb[1]) < 0)
-			goto out_unsupported_cdb;
-		cmd->execute_cmd = ops->execute_write_same;
+		ret = sbc_setup_write_same(cmd, &cdb[1], ops);
+		if (ret)
+			return ret;
 		break;
 	case WRITE_SAME:
-		if (!ops->execute_write_same)
-			goto out_unsupported_cdb;
-
 		sectors = transport_get_sectors_10(cdb);
 		if (!sectors) {
 			pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
-			goto out_invalid_cdb_field;
+			return TCM_INVALID_CDB_FIELD;
 		}
 
 		size = sbc_get_size(cmd, 1);
@@ -529,13 +527,13 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
 		 * Follow sbcr26 with WRITE_SAME (10) and check for the existence
 		 * of byte 1 bit 3 UNMAP instead of original reserved field
 		 */
-		if (sbc_write_same_supported(dev, &cdb[1]) < 0)
-			goto out_unsupported_cdb;
-		cmd->execute_cmd = ops->execute_write_same;
+		ret = sbc_setup_write_same(cmd, &cdb[1], ops);
+		if (ret)
+			return ret;
 		break;
 	case VERIFY:
 		size = 0;
-		cmd->execute_cmd = sbc_emulate_verify;
+		cmd->execute_cmd = sbc_emulate_noop;
 		break;
 	case REZERO_UNIT:
 	case SEEK_6:
@@ -557,24 +555,24 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
 
 	/* reject any command that we don't have a handler for */
 	if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->execute_cmd)
-		goto out_unsupported_cdb;
+		return TCM_UNSUPPORTED_SCSI_OPCODE;
 
 	if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
 		unsigned long long end_lba;
 
-		if (sectors > su_dev->se_dev_attrib.fabric_max_sectors) {
+		if (sectors > dev->dev_attrib.fabric_max_sectors) {
 			printk_ratelimited(KERN_ERR "SCSI OP %02xh with too"
 				" big sectors %u exceeds fabric_max_sectors:"
 				" %u\n", cdb[0], sectors,
-				su_dev->se_dev_attrib.fabric_max_sectors);
-			goto out_invalid_cdb_field;
+				dev->dev_attrib.fabric_max_sectors);
+			return TCM_INVALID_CDB_FIELD;
 		}
-		if (sectors > su_dev->se_dev_attrib.hw_max_sectors) {
+		if (sectors > dev->dev_attrib.hw_max_sectors) {
 			printk_ratelimited(KERN_ERR "SCSI OP %02xh with too"
 				" big sectors %u exceeds backend hw_max_sectors:"
 				" %u\n", cdb[0], sectors,
-				su_dev->se_dev_attrib.hw_max_sectors);
-			goto out_invalid_cdb_field;
+				dev->dev_attrib.hw_max_sectors);
+			return TCM_INVALID_CDB_FIELD;
 		}
 
 		end_lba = dev->transport->get_blocks(dev) + 1;
@@ -582,25 +580,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
 			pr_err("cmd exceeds last lba %llu "
 				"(lba %llu, sectors %u)\n",
 				end_lba, cmd->t_task_lba, sectors);
-			goto out_invalid_cdb_field;
+			return TCM_INVALID_CDB_FIELD;
 		}
 
 		size = sbc_get_size(cmd, sectors);
 	}
 
-	ret = target_cmd_size_check(cmd, size);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-
-out_unsupported_cdb:
-	cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-	cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-	return -EINVAL;
-out_invalid_cdb_field:
-	cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-	cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-	return -EINVAL;
+	return target_cmd_size_check(cmd, size);
 }
 EXPORT_SYMBOL(sbc_parse_cdb);
+
+u32 sbc_get_device_type(struct se_device *dev)
+{
+	return TYPE_DISK;
+}
+EXPORT_SYMBOL(sbc_get_device_type);
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index 6fd434d..84f9e96 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -1,10 +1,7 @@
 /*
  * SCSI Primary Commands (SPC) parsing and emulation.
  *
- * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc.
- * Copyright (c) 2005, 2006, 2007 SBE, Inc.
- * Copyright (c) 2007-2010 Rising Tide Systems
- * Copyright (c) 2008-2010 Linux-iSCSI.org
+ * (c) Copyright 2002-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@kernel.org>
  *
@@ -69,7 +66,8 @@ static void spc_fill_alua_data(struct se_port *port, unsigned char *buf)
 	spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 }
 
-static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf)
+static sense_reason_t
+spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf)
 {
 	struct se_lun *lun = cmd->se_lun;
 	struct se_device *dev = cmd->se_dev;
@@ -78,7 +76,7 @@ static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf)
 	if (dev->transport->get_device_type(dev) == TYPE_TAPE)
 		buf[1] = 0x80;
 
-	buf[2] = dev->transport->get_device_rev(dev);
+	buf[2] = 0x05; /* SPC-3 */
 
 	/*
 	 * NORMACA and HISUP = 0, RESPONSE DATA FORMAT = 2
@@ -95,34 +93,32 @@ static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf)
 	/*
 	 * Enable SCCS and TPGS fields for Emulated ALUA
 	 */
-	if (dev->se_sub_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED)
-		spc_fill_alua_data(lun->lun_sep, buf);
+	spc_fill_alua_data(lun->lun_sep, buf);
 
 	buf[7] = 0x2; /* CmdQue=1 */
 
 	snprintf(&buf[8], 8, "LIO-ORG");
-	snprintf(&buf[16], 16, "%s", dev->se_sub_dev->t10_wwn.model);
-	snprintf(&buf[32], 4, "%s", dev->se_sub_dev->t10_wwn.revision);
+	snprintf(&buf[16], 16, "%s", dev->t10_wwn.model);
+	snprintf(&buf[32], 4, "%s", dev->t10_wwn.revision);
 	buf[4] = 31; /* Set additional length to 31 */
 
 	return 0;
 }
 
 /* unit serial number */
-static int spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
+static sense_reason_t
+spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
 {
 	struct se_device *dev = cmd->se_dev;
 	u16 len = 0;
 
-	if (dev->se_sub_dev->su_dev_flags &
-			SDF_EMULATED_VPD_UNIT_SERIAL) {
+	if (dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL) {
 		u32 unit_serial_len;
 
-		unit_serial_len = strlen(dev->se_sub_dev->t10_wwn.unit_serial);
+		unit_serial_len = strlen(dev->t10_wwn.unit_serial);
 		unit_serial_len++; /* For NULL Terminator */
 
-		len += sprintf(&buf[4], "%s",
-			dev->se_sub_dev->t10_wwn.unit_serial);
+		len += sprintf(&buf[4], "%s", dev->t10_wwn.unit_serial);
 		len++; /* Extra Byte for NULL Terminator */
 		buf[3] = len;
 	}
@@ -132,7 +128,7 @@ static int spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
 static void spc_parse_naa_6h_vendor_specific(struct se_device *dev,
 		unsigned char *buf)
 {
-	unsigned char *p = &dev->se_sub_dev->t10_wwn.unit_serial[0];
+	unsigned char *p = &dev->t10_wwn.unit_serial[0];
 	int cnt;
 	bool next = true;
 
@@ -164,7 +160,8 @@ static void spc_parse_naa_6h_vendor_specific(struct se_device *dev,
  * Device identification VPD, for a complete list of
  * DESIGNATOR TYPEs see spc4r17 Table 459.
  */
-static int spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
+static sense_reason_t
+spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
 {
 	struct se_device *dev = cmd->se_dev;
 	struct se_lun *lun = cmd->se_lun;
@@ -173,7 +170,7 @@ static int spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
 	struct t10_alua_lu_gp_member *lu_gp_mem;
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
-	unsigned char *prod = &dev->se_sub_dev->t10_wwn.model[0];
+	unsigned char *prod = &dev->t10_wwn.model[0];
 	u32 prod_len;
 	u32 unit_serial_len, off = 0;
 	u16 len = 0, id_len;
@@ -188,7 +185,7 @@ static int spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
 	 * /sys/kernel/config/target/core/$HBA/$DEV/wwn/vpd_unit_serial
 	 * value in order to return the NAA id.
 	 */
-	if (!(dev->se_sub_dev->su_dev_flags & SDF_EMULATED_VPD_UNIT_SERIAL))
+	if (!(dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL))
 		goto check_t10_vend_desc;
 
 	/* CODE SET == Binary */
@@ -236,14 +233,12 @@ check_t10_vend_desc:
 	prod_len += strlen(prod);
 	prod_len++; /* For : */
 
-	if (dev->se_sub_dev->su_dev_flags &
-			SDF_EMULATED_VPD_UNIT_SERIAL) {
-		unit_serial_len =
-			strlen(&dev->se_sub_dev->t10_wwn.unit_serial[0]);
+	if (dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL) {
+		unit_serial_len = strlen(&dev->t10_wwn.unit_serial[0]);
 		unit_serial_len++; /* For NULL Terminator */
 
 		id_len += sprintf(&buf[off+12], "%s:%s", prod,
-				&dev->se_sub_dev->t10_wwn.unit_serial[0]);
+				&dev->t10_wwn.unit_serial[0]);
 	}
 	buf[off] = 0x2; /* ASCII */
 	buf[off+1] = 0x1; /* T10 Vendor ID */
@@ -298,10 +293,6 @@ check_t10_vend_desc:
 		 * Get the PROTOCOL IDENTIFIER as defined by spc4r17
 		 * section 7.5.1 Table 362
 		 */
-		if (dev->se_sub_dev->t10_alua.alua_type !=
-				SPC3_ALUA_EMULATED)
-			goto check_scsi_name;
-
 		tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
 		if (!tg_pt_gp_mem)
 			goto check_lu_gp;
@@ -415,20 +406,22 @@ check_scsi_name:
 }
 
 /* Extended INQUIRY Data VPD Page */
-static int spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
+static sense_reason_t
+spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
 {
 	buf[3] = 0x3c;
 	/* Set HEADSUP, ORDSUP, SIMPSUP */
 	buf[5] = 0x07;
 
 	/* If WriteCache emulation is enabled, set V_SUP */
-	if (cmd->se_dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0)
+	if (cmd->se_dev->dev_attrib.emulate_write_cache > 0)
 		buf[6] = 0x01;
 	return 0;
 }
 
 /* Block Limits VPD page */
-static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
+static sense_reason_t
+spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 {
 	struct se_device *dev = cmd->se_dev;
 	u32 max_sectors;
@@ -439,7 +432,7 @@ static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 	 * emulate_tpu=1 or emulate_tpws=1 we will be expect a
 	 * different page length for Thin Provisioning.
 	 */
-	if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
+	if (dev->dev_attrib.emulate_tpu || dev->dev_attrib.emulate_tpws)
 		have_tp = 1;
 
 	buf[0] = dev->transport->get_device_type(dev);
@@ -456,62 +449,70 @@ static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 	/*
 	 * Set MAXIMUM TRANSFER LENGTH
 	 */
-	max_sectors = min(dev->se_sub_dev->se_dev_attrib.fabric_max_sectors,
-			  dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
+	max_sectors = min(dev->dev_attrib.fabric_max_sectors,
+			  dev->dev_attrib.hw_max_sectors);
 	put_unaligned_be32(max_sectors, &buf[8]);
 
 	/*
 	 * Set OPTIMAL TRANSFER LENGTH
 	 */
-	put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.optimal_sectors, &buf[12]);
+	put_unaligned_be32(dev->dev_attrib.optimal_sectors, &buf[12]);
 
 	/*
 	 * Exit now if we don't support TP.
 	 */
 	if (!have_tp)
-		return 0;
+		goto max_write_same;
 
 	/*
 	 * Set MAXIMUM UNMAP LBA COUNT
 	 */
-	put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count, &buf[20]);
+	put_unaligned_be32(dev->dev_attrib.max_unmap_lba_count, &buf[20]);
 
 	/*
 	 * Set MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT
 	 */
-	put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count,
+	put_unaligned_be32(dev->dev_attrib.max_unmap_block_desc_count,
 			   &buf[24]);
 
 	/*
 	 * Set OPTIMAL UNMAP GRANULARITY
 	 */
-	put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.unmap_granularity, &buf[28]);
+	put_unaligned_be32(dev->dev_attrib.unmap_granularity, &buf[28]);
 
 	/*
 	 * UNMAP GRANULARITY ALIGNMENT
 	 */
-	put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment,
+	put_unaligned_be32(dev->dev_attrib.unmap_granularity_alignment,
 			   &buf[32]);
-	if (dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment != 0)
+	if (dev->dev_attrib.unmap_granularity_alignment != 0)
 		buf[32] |= 0x80; /* Set the UGAVALID bit */
 
+	/*
+	 * MAXIMUM WRITE SAME LENGTH
+	 */
+max_write_same:
+	put_unaligned_be64(dev->dev_attrib.max_write_same_len, &buf[36]);
+
 	return 0;
 }
 
 /* Block Device Characteristics VPD page */
-static int spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf)
+static sense_reason_t
+spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf)
 {
 	struct se_device *dev = cmd->se_dev;
 
 	buf[0] = dev->transport->get_device_type(dev);
 	buf[3] = 0x3c;
-	buf[5] = dev->se_sub_dev->se_dev_attrib.is_nonrot ? 1 : 0;
+	buf[5] = dev->dev_attrib.is_nonrot ? 1 : 0;
 
 	return 0;
 }
 
 /* Thin Provisioning VPD */
-static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
+static sense_reason_t
+spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
 {
 	struct se_device *dev = cmd->se_dev;
 
@@ -546,7 +547,7 @@ static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
 	 * the UNMAP command (see 5.25). A TPU bit set to zero indicates
 	 * that the device server does not support the UNMAP command.
 	 */
-	if (dev->se_sub_dev->se_dev_attrib.emulate_tpu != 0)
+	if (dev->dev_attrib.emulate_tpu != 0)
 		buf[5] = 0x80;
 
 	/*
@@ -555,17 +556,18 @@ static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
 	 * A TPWS bit set to zero indicates that the device server does not
 	 * support the use of the WRITE SAME (16) command to unmap LBAs.
 	 */
-	if (dev->se_sub_dev->se_dev_attrib.emulate_tpws != 0)
+	if (dev->dev_attrib.emulate_tpws != 0)
 		buf[5] |= 0x40;
 
 	return 0;
 }
 
-static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf);
+static sense_reason_t
+spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf);
 
 static struct {
 	uint8_t		page;
-	int		(*emulate)(struct se_cmd *, unsigned char *);
+	sense_reason_t	(*emulate)(struct se_cmd *, unsigned char *);
 } evpd_handlers[] = {
 	{ .page = 0x00, .emulate = spc_emulate_evpd_00 },
 	{ .page = 0x80, .emulate = spc_emulate_evpd_80 },
@@ -577,7 +579,8 @@ static struct {
 };
 
 /* supported vital product data pages */
-static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
+static sense_reason_t
+spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
 {
 	int p;
 
@@ -586,8 +589,7 @@ static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
 	 * Registered Extended LUN WWN has been set via ConfigFS
 	 * during device creation/restart.
 	 */
-	if (cmd->se_dev->se_sub_dev->su_dev_flags &
-			SDF_EMULATED_VPD_UNIT_SERIAL) {
+	if (cmd->se_dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL) {
 		buf[3] = ARRAY_SIZE(evpd_handlers);
 		for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p)
 			buf[p + 4] = evpd_handlers[p].page;
@@ -596,14 +598,16 @@ static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
 	return 0;
 }
 
-static int spc_emulate_inquiry(struct se_cmd *cmd)
+static sense_reason_t
+spc_emulate_inquiry(struct se_cmd *cmd)
 {
 	struct se_device *dev = cmd->se_dev;
 	struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg;
 	unsigned char *rbuf;
 	unsigned char *cdb = cmd->t_task_cdb;
 	unsigned char buf[SE_INQUIRY_BUF];
-	int p, ret;
+	sense_reason_t ret;
+	int p;
 
 	memset(buf, 0, SE_INQUIRY_BUF);
 
@@ -616,8 +620,7 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)
 		if (cdb[2]) {
 			pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n",
 			       cdb[2]);
-			cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-			ret = -EINVAL;
+			ret = TCM_INVALID_CDB_FIELD;
 			goto out;
 		}
 
@@ -634,33 +637,43 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)
 	}
 
 	pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]);
-	cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-	ret = -EINVAL;
+	ret = TCM_INVALID_CDB_FIELD;
 
 out:
 	rbuf = transport_kmap_data_sg(cmd);
-	if (rbuf) {
-		memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
-		transport_kunmap_data_sg(cmd);
-	}
+	if (!rbuf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+	memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+	transport_kunmap_data_sg(cmd);
 
 	if (!ret)
 		target_complete_cmd(cmd, GOOD);
 	return ret;
 }
 
-static int spc_modesense_rwrecovery(unsigned char *p)
+static int spc_modesense_rwrecovery(struct se_device *dev, u8 pc, u8 *p)
 {
 	p[0] = 0x01;
 	p[1] = 0x0a;
 
+	/* No changeable values for now */
+	if (pc == 1)
+		goto out;
+
+out:
 	return 12;
 }
 
-static int spc_modesense_control(struct se_device *dev, unsigned char *p)
+static int spc_modesense_control(struct se_device *dev, u8 pc, u8 *p)
 {
 	p[0] = 0x0a;
 	p[1] = 0x0a;
+
+	/* No changeable values for now */
+	if (pc == 1)
+		goto out;
+
 	p[2] = 2;
 	/*
 	 * From spc4r23, 7.4.7 Control mode page
@@ -690,7 +703,7 @@ static int spc_modesense_control(struct se_device *dev, unsigned char *p)
 	 * command sequence order shall be explicitly handled by the application client
 	 * through the selection of appropriate ommands and task attributes.
 	 */
-	p[3] = (dev->se_sub_dev->se_dev_attrib.emulate_rest_reord == 1) ? 0x00 : 0x10;
+	p[3] = (dev->dev_attrib.emulate_rest_reord == 1) ? 0x00 : 0x10;
 	/*
 	 * From spc4r17, section 7.4.6 Control mode Page
 	 *
@@ -720,8 +733,8 @@ static int spc_modesense_control(struct se_device *dev, unsigned char *p)
 	 * for a BUSY, TASK SET FULL, or RESERVATION CONFLICT status regardless
 	 * to the number of commands completed with one of those status codes.
 	 */
-	p[4] = (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 2) ? 0x30 :
-	       (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 1) ? 0x20 : 0x00;
+	p[4] = (dev->dev_attrib.emulate_ua_intlck_ctrl == 2) ? 0x30 :
+	       (dev->dev_attrib.emulate_ua_intlck_ctrl == 1) ? 0x20 : 0x00;
 	/*
 	 * From spc4r17, section 7.4.6 Control mode Page
 	 *
@@ -734,25 +747,56 @@ static int spc_modesense_control(struct se_device *dev, unsigned char *p)
 	 * which the command was received shall be completed with TASK ABORTED
 	 * status (see SAM-4).
 	 */
-	p[5] = (dev->se_sub_dev->se_dev_attrib.emulate_tas) ? 0x40 : 0x00;
+	p[5] = (dev->dev_attrib.emulate_tas) ? 0x40 : 0x00;
 	p[8] = 0xff;
 	p[9] = 0xff;
 	p[11] = 30;
 
+out:
 	return 12;
 }
 
-static int spc_modesense_caching(struct se_device *dev, unsigned char *p)
+static int spc_modesense_caching(struct se_device *dev, u8 pc, u8 *p)
 {
 	p[0] = 0x08;
 	p[1] = 0x12;
-	if (dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0)
+
+	/* No changeable values for now */
+	if (pc == 1)
+		goto out;
+
+	if (dev->dev_attrib.emulate_write_cache > 0)
 		p[2] = 0x04; /* Write Cache Enable */
 	p[12] = 0x20; /* Disabled Read Ahead */
 
+out:
 	return 20;
 }
 
+static int spc_modesense_informational_exceptions(struct se_device *dev, u8 pc, unsigned char *p)
+{
+	p[0] = 0x1c;
+	p[1] = 0x0a;
+
+	/* No changeable values for now */
+	if (pc == 1)
+		goto out;
+
+out:
+	return 12;
+}
+
+static struct {
+	uint8_t		page;
+	uint8_t		subpage;
+	int		(*emulate)(struct se_device *, u8, unsigned char *);
+} modesense_handlers[] = {
+	{ .page = 0x01, .subpage = 0x00, .emulate = spc_modesense_rwrecovery },
+	{ .page = 0x08, .subpage = 0x00, .emulate = spc_modesense_caching },
+	{ .page = 0x0a, .subpage = 0x00, .emulate = spc_modesense_control },
+	{ .page = 0x1c, .subpage = 0x00, .emulate = spc_modesense_informational_exceptions },
+};
+
 static void spc_modesense_write_protect(unsigned char *buf, int type)
 {
 	/*
@@ -779,82 +823,224 @@ static void spc_modesense_dpofua(unsigned char *buf, int type)
 	}
 }
 
-static int spc_emulate_modesense(struct se_cmd *cmd)
+static int spc_modesense_blockdesc(unsigned char *buf, u64 blocks, u32 block_size)
+{
+	*buf++ = 8;
+	put_unaligned_be32(min(blocks, 0xffffffffull), buf);
+	buf += 4;
+	put_unaligned_be32(block_size, buf);
+	return 9;
+}
+
+static int spc_modesense_long_blockdesc(unsigned char *buf, u64 blocks, u32 block_size)
+{
+	if (blocks <= 0xffffffff)
+		return spc_modesense_blockdesc(buf + 3, blocks, block_size) + 3;
+
+	*buf++ = 1;		/* LONGLBA */
+	buf += 2;
+	*buf++ = 16;
+	put_unaligned_be64(blocks, buf);
+	buf += 12;
+	put_unaligned_be32(block_size, buf);
+
+	return 17;
+}
+
+static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)
 {
 	struct se_device *dev = cmd->se_dev;
 	char *cdb = cmd->t_task_cdb;
-	unsigned char *rbuf;
+	unsigned char *buf, *map_buf;
 	int type = dev->transport->get_device_type(dev);
 	int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10);
-	u32 offset = ten ? 8 : 4;
+	bool dbd = !!(cdb[1] & 0x08);
+	bool llba = ten ? !!(cdb[1] & 0x10) : false;
+	u8 pc = cdb[2] >> 6;
+	u8 page = cdb[2] & 0x3f;
+	u8 subpage = cdb[3];
 	int length = 0;
-	unsigned char buf[SE_MODE_PAGE_BUF];
-
-	memset(buf, 0, SE_MODE_PAGE_BUF);
+	int ret;
+	int i;
 
-	switch (cdb[2] & 0x3f) {
-	case 0x01:
-		length = spc_modesense_rwrecovery(&buf[offset]);
-		break;
-	case 0x08:
-		length = spc_modesense_caching(dev, &buf[offset]);
-		break;
-	case 0x0a:
-		length = spc_modesense_control(dev, &buf[offset]);
-		break;
-	case 0x3f:
-		length = spc_modesense_rwrecovery(&buf[offset]);
-		length += spc_modesense_caching(dev, &buf[offset+length]);
-		length += spc_modesense_control(dev, &buf[offset+length]);
-		break;
-	default:
-		pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n",
-		       cdb[2] & 0x3f, cdb[3]);
-		cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE;
-		return -EINVAL;
+	map_buf = transport_kmap_data_sg(cmd);
+	if (!map_buf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+	/*
+	 * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we
+	 * know we actually allocated a full page.  Otherwise, if the
+	 * data buffer is too small, allocate a temporary buffer so we
+	 * don't have to worry about overruns in all our INQUIRY
+	 * emulation handling.
+	 */
+	if (cmd->data_length < SE_MODE_PAGE_BUF &&
+	    (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) {
+		buf = kzalloc(SE_MODE_PAGE_BUF, GFP_KERNEL);
+		if (!buf) {
+			transport_kunmap_data_sg(cmd);
+			return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+		}
+	} else {
+		buf = map_buf;
 	}
-	offset += length;
-
-	if (ten) {
-		offset -= 2;
-		buf[0] = (offset >> 8) & 0xff;
-		buf[1] = offset & 0xff;
-		offset += 2;
-
-		if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
-		    (cmd->se_deve &&
-		    (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
-			spc_modesense_write_protect(&buf[3], type);
-
-		if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
-		    (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
-			spc_modesense_dpofua(&buf[3], type);
+	/*
+	 * Skip over MODE DATA LENGTH + MEDIUM TYPE fields to byte 3 for
+	 * MODE_SENSE_10 and byte 2 for MODE_SENSE (6).
+	 */
+	length = ten ? 3 : 2;
+
+	/* DEVICE-SPECIFIC PARAMETER */
+	if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
+	    (cmd->se_deve &&
+	     (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
+		spc_modesense_write_protect(&buf[length], type);
+
+	if ((dev->dev_attrib.emulate_write_cache > 0) &&
+	    (dev->dev_attrib.emulate_fua_write > 0))
+		spc_modesense_dpofua(&buf[length], type);
+
+	++length;
+
+	/* BLOCK DESCRIPTOR */
+
+	/*
+	 * For now we only include a block descriptor for disk (SBC)
+	 * devices; other command sets use a slightly different format.
+	 */
+	if (!dbd && type == TYPE_DISK) {
+		u64 blocks = dev->transport->get_blocks(dev);
+		u32 block_size = dev->dev_attrib.block_size;
+
+		if (ten) {
+			if (llba) {
+				length += spc_modesense_long_blockdesc(&buf[length],
+								       blocks, block_size);
+			} else {
+				length += 3;
+				length += spc_modesense_blockdesc(&buf[length],
+								  blocks, block_size);
+			}
+		} else {
+			length += spc_modesense_blockdesc(&buf[length], blocks,
+							  block_size);
+		}
 	} else {
-		offset -= 1;
-		buf[0] = offset & 0xff;
-		offset += 1;
-
-		if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
-		    (cmd->se_deve &&
-		    (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
-			spc_modesense_write_protect(&buf[2], type);
-
-		if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
-		    (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
-			spc_modesense_dpofua(&buf[2], type);
+		if (ten)
+			length += 4;
+		else
+			length += 1;
 	}
 
-	rbuf = transport_kmap_data_sg(cmd);
-	if (rbuf) {
-		memcpy(rbuf, buf, min(offset, cmd->data_length));
-		transport_kunmap_data_sg(cmd);
+	if (page == 0x3f) {
+		if (subpage != 0x00 && subpage != 0xff) {
+			pr_warn("MODE_SENSE: Invalid subpage code: 0x%02x\n", subpage);
+			kfree(buf);
+			transport_kunmap_data_sg(cmd);
+			return TCM_INVALID_CDB_FIELD;
+		}
+
+		for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i) {
+			/*
+			 * Tricky way to say all subpage 00h for
+			 * subpage==0, all subpages for subpage==0xff
+			 * (and we just checked above that those are
+			 * the only two possibilities).
+			 */
+			if ((modesense_handlers[i].subpage & ~subpage) == 0) {
+				ret = modesense_handlers[i].emulate(dev, pc, &buf[length]);
+				if (!ten && length + ret >= 255)
+					break;
+				length += ret;
+			}
+		}
+
+		goto set_length;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i)
+		if (modesense_handlers[i].page == page &&
+		    modesense_handlers[i].subpage == subpage) {
+			length += modesense_handlers[i].emulate(dev, pc, &buf[length]);
+			goto set_length;
+		}
+
+	/*
+	 * We don't intend to implement:
+	 *  - obsolete page 03h "format parameters" (checked by Solaris)
+	 */
+	if (page != 0x03)
+		pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n",
+		       page, subpage);
+
+	transport_kunmap_data_sg(cmd);
+	return TCM_UNKNOWN_MODE_PAGE;
+
+set_length:
+	if (ten)
+		put_unaligned_be16(length - 2, buf);
+	else
+		buf[0] = length - 1;
+
+	if (buf != map_buf) {
+		memcpy(map_buf, buf, cmd->data_length);
+		kfree(buf);
 	}
 
+	transport_kunmap_data_sg(cmd);
 	target_complete_cmd(cmd, GOOD);
 	return 0;
 }
 
-static int spc_emulate_request_sense(struct se_cmd *cmd)
+static sense_reason_t spc_emulate_modeselect(struct se_cmd *cmd)
+{
+	struct se_device *dev = cmd->se_dev;
+	char *cdb = cmd->t_task_cdb;
+	bool ten = cdb[0] == MODE_SELECT_10;
+	int off = ten ? 8 : 4;
+	bool pf = !!(cdb[1] & 0x10);
+	u8 page, subpage;
+	unsigned char *buf;
+	unsigned char tbuf[SE_MODE_PAGE_BUF];
+	int length;
+	int ret = 0;
+	int i;
+
+	buf = transport_kmap_data_sg(cmd);
+	if (!buf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+	if (!pf) {
+		ret = TCM_INVALID_CDB_FIELD;
+		goto out;
+	}
+
+	page = buf[off] & 0x3f;
+	subpage = buf[off] & 0x40 ? buf[off + 1] : 0;
+
+	for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i)
+		if (modesense_handlers[i].page == page &&
+		    modesense_handlers[i].subpage == subpage) {
+			memset(tbuf, 0, SE_MODE_PAGE_BUF);
+			length = modesense_handlers[i].emulate(dev, 0, tbuf);
+			goto check_contents;
+		}
+
+	ret = TCM_UNKNOWN_MODE_PAGE;
+	goto out;
+
+check_contents:
+	if (memcmp(buf + off, tbuf, length))
+		ret = TCM_INVALID_PARAMETER_LIST;
+
+out:
+	transport_kunmap_data_sg(cmd);
+
+	if (!ret)
+		target_complete_cmd(cmd, GOOD);
+	return ret;
+}
+
+static sense_reason_t spc_emulate_request_sense(struct se_cmd *cmd)
 {
 	unsigned char *cdb = cmd->t_task_cdb;
 	unsigned char *rbuf;
@@ -866,19 +1052,14 @@ static int spc_emulate_request_sense(struct se_cmd *cmd)
 	if (cdb[1] & 0x01) {
 		pr_err("REQUEST_SENSE description emulation not"
 			" supported\n");
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		return -ENOSYS;
+		return TCM_INVALID_CDB_FIELD;
 	}
 
 	rbuf = transport_kmap_data_sg(cmd);
-	if (cmd->scsi_sense_reason != 0) {
-		/*
-		 * Out of memory.  We will fail with CHECK CONDITION, so
-		 * we must not clear the unit attention condition.
-		 */
-		target_complete_cmd(cmd, CHECK_CONDITION);
-		return 0;
-	} else if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
+	if (!rbuf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+	if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
 		/*
 		 * CURRENT ERROR, UNIT ATTENTION
 		 */
@@ -905,33 +1086,97 @@ static int spc_emulate_request_sense(struct se_cmd *cmd)
 		buf[7] = 0x0A;
 	}
 
-	if (rbuf) {
-		memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
-		transport_kunmap_data_sg(cmd);
+	memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+	transport_kunmap_data_sg(cmd);
+
+	target_complete_cmd(cmd, GOOD);
+	return 0;
+}
+
+sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
+{
+	struct se_dev_entry *deve;
+	struct se_session *sess = cmd->se_sess;
+	unsigned char *buf;
+	u32 lun_count = 0, offset = 8, i;
+
+	if (cmd->data_length < 16) {
+		pr_warn("REPORT LUNS allocation length %u too small\n",
+			cmd->data_length);
+		return TCM_INVALID_CDB_FIELD;
+	}
+
+	buf = transport_kmap_data_sg(cmd);
+	if (!buf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+	/*
+	 * If no struct se_session pointer is present, this struct se_cmd is
+	 * coming via a target_core_mod PASSTHROUGH op, and not through
+	 * a $FABRIC_MOD.  In that case, report LUN=0 only.
+	 */
+	if (!sess) {
+		int_to_scsilun(0, (struct scsi_lun *)&buf[offset]);
+		lun_count = 1;
+		goto done;
+	}
+
+	spin_lock_irq(&sess->se_node_acl->device_list_lock);
+	for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
+		deve = sess->se_node_acl->device_list[i];
+		if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS))
+			continue;
+		/*
+		 * We determine the correct LUN LIST LENGTH even once we
+		 * have reached the initial allocation length.
+		 * See SPC2-R20 7.19.
+		 */
+		lun_count++;
+		if ((offset + 8) > cmd->data_length)
+			continue;
+
+		int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]);
+		offset += 8;
 	}
+	spin_unlock_irq(&sess->se_node_acl->device_list_lock);
+
+	/*
+	 * See SPC3 r07, page 159.
+	 */
+done:
+	lun_count *= 8;
+	buf[0] = ((lun_count >> 24) & 0xff);
+	buf[1] = ((lun_count >> 16) & 0xff);
+	buf[2] = ((lun_count >> 8) & 0xff);
+	buf[3] = (lun_count & 0xff);
+	transport_kunmap_data_sg(cmd);
 
 	target_complete_cmd(cmd, GOOD);
 	return 0;
 }
+EXPORT_SYMBOL(spc_emulate_report_luns);
 
-static int spc_emulate_testunitready(struct se_cmd *cmd)
+static sense_reason_t
+spc_emulate_testunitready(struct se_cmd *cmd)
 {
 	target_complete_cmd(cmd, GOOD);
 	return 0;
 }
 
-int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
+sense_reason_t
+spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
 {
 	struct se_device *dev = cmd->se_dev;
-	struct se_subsystem_dev *su_dev = dev->se_sub_dev;
 	unsigned char *cdb = cmd->t_task_cdb;
 
 	switch (cdb[0]) {
 	case MODE_SELECT:
 		*size = cdb[4];
+		cmd->execute_cmd = spc_emulate_modeselect;
 		break;
 	case MODE_SELECT_10:
 		*size = (cdb[7] << 8) + cdb[8];
+		cmd->execute_cmd = spc_emulate_modeselect;
 		break;
 	case MODE_SENSE:
 		*size = cdb[4];
@@ -946,14 +1191,12 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
 		*size = (cdb[7] << 8) + cdb[8];
 		break;
 	case PERSISTENT_RESERVE_IN:
-		if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
-			cmd->execute_cmd = target_scsi3_emulate_pr_in;
 		*size = (cdb[7] << 8) + cdb[8];
+		cmd->execute_cmd = target_scsi3_emulate_pr_in;
 		break;
 	case PERSISTENT_RESERVE_OUT:
-		if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
-			cmd->execute_cmd = target_scsi3_emulate_pr_out;
 		*size = (cdb[7] << 8) + cdb[8];
+		cmd->execute_cmd = target_scsi3_emulate_pr_out;
 		break;
 	case RELEASE:
 	case RELEASE_10:
@@ -962,8 +1205,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
 		else
 			*size = cmd->data_length;
 
-		if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
-			cmd->execute_cmd = target_scsi2_reservation_release;
+		cmd->execute_cmd = target_scsi2_reservation_release;
 		break;
 	case RESERVE:
 	case RESERVE_10:
@@ -976,15 +1218,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
 		else
 			*size = cmd->data_length;
 
-		/*
-		 * Setup the legacy emulated handler for SPC-2 and
-		 * >= SPC-3 compatible reservation handling (CRH=1)
-		 * Otherwise, we assume the underlying SCSI logic is
-		 * is running in SPC_PASSTHROUGH, and wants reservations
-		 * emulation disabled.
-		 */
-		if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
-			cmd->execute_cmd = target_scsi2_reservation_reserve;
+		cmd->execute_cmd = target_scsi2_reservation_reserve;
 		break;
 	case REQUEST_SENSE:
 		*size = cdb[4];
@@ -997,8 +1231,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
 		 * Do implict HEAD_OF_QUEUE processing for INQUIRY.
 		 * See spc4r17 section 5.3
 		 */
-		if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
-			cmd->sam_task_attr = MSG_HEAD_TAG;
+		cmd->sam_task_attr = MSG_HEAD_TAG;
 		cmd->execute_cmd = spc_emulate_inquiry;
 		break;
 	case SECURITY_PROTOCOL_IN:
@@ -1020,14 +1253,13 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
 		*size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
 		break;
 	case REPORT_LUNS:
-		cmd->execute_cmd = target_report_luns;
+		cmd->execute_cmd = spc_emulate_report_luns;
 		*size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
 		/*
 		 * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS
 		 * See spc4r17 section 5.3
 		 */
-		if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
-			cmd->sam_task_attr = MSG_HEAD_TAG;
+		cmd->sam_task_attr = MSG_HEAD_TAG;
 		break;
 	case TEST_UNIT_READY:
 		cmd->execute_cmd = spc_emulate_testunitready;
@@ -1039,8 +1271,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
 			 * MAINTENANCE_IN from SCC-2
 			 * Check for emulated MI_REPORT_TARGET_PGS
 			 */
-			if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS &&
-			    su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
+			if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS) {
 				cmd->execute_cmd =
 					target_emulate_report_target_port_groups;
 			}
@@ -1058,8 +1289,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
 			 * MAINTENANCE_OUT from SCC-2
 			 * Check for emulated MO_SET_TARGET_PGS.
 			 */
-			if (cdb[1] == MO_SET_TARGET_PGS &&
-			    su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
+			if (cdb[1] == MO_SET_TARGET_PGS) {
 				cmd->execute_cmd =
 					target_emulate_set_target_port_groups;
 			}
@@ -1075,9 +1305,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
 		pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode"
 			" 0x%02x, sending CHECK_CONDITION.\n",
 			cmd->se_tfo->get_fabric_name(), cdb[0]);
-		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-		return -EINVAL;
+		return TCM_UNSUPPORTED_SCSI_OPCODE;
 	}
 
 	return 0;
diff --git a/drivers/target/target_core_stat.c b/drivers/target/target_core_stat.c
index cb6b003..d154ce7 100644
--- a/drivers/target/target_core_stat.c
+++ b/drivers/target/target_core_stat.c
@@ -1,13 +1,10 @@
 /*******************************************************************************
  * Filename:  target_core_stat.c
  *
- * Copyright (c) 2011 Rising Tide Systems
- * Copyright (c) 2011 Linux-iSCSI.org
- *
  * Modern ConfigFS group context specific statistics based on original
  * target_core_mib.c code
  *
- * Copyright (c) 2006-2007 SBE, Inc.  All Rights Reserved.
+ * (c) Copyright 2006-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@linux-iscsi.org>
  *
@@ -80,13 +77,9 @@ static struct target_stat_scsi_dev_attribute				\
 static ssize_t target_stat_scsi_dev_show_attr_inst(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_hba *hba = se_subdev->se_dev_hba;
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
+	struct se_hba *hba = dev->se_hba;
 
 	return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
 }
@@ -95,12 +88,8 @@ DEV_STAT_SCSI_DEV_ATTR_RO(inst);
 static ssize_t target_stat_scsi_dev_show_attr_indx(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 
 	return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
 }
@@ -109,13 +98,6 @@ DEV_STAT_SCSI_DEV_ATTR_RO(indx);
 static ssize_t target_stat_scsi_dev_show_attr_role(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
-
 	return snprintf(page, PAGE_SIZE, "Target\n");
 }
 DEV_STAT_SCSI_DEV_ATTR_RO(role);
@@ -123,12 +105,8 @@ DEV_STAT_SCSI_DEV_ATTR_RO(role);
 static ssize_t target_stat_scsi_dev_show_attr_ports(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 
 	return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_port_count);
 }
@@ -176,13 +154,9 @@ static struct target_stat_scsi_tgt_dev_attribute			\
 static ssize_t target_stat_scsi_tgt_dev_show_attr_inst(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_hba *hba = se_subdev->se_dev_hba;
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
+	struct se_hba *hba = dev->se_hba;
 
 	return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
 }
@@ -191,12 +165,8 @@ DEV_STAT_SCSI_TGT_DEV_ATTR_RO(inst);
 static ssize_t target_stat_scsi_tgt_dev_show_attr_indx(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 
 	return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
 }
@@ -205,13 +175,6 @@ DEV_STAT_SCSI_TGT_DEV_ATTR_RO(indx);
 static ssize_t target_stat_scsi_tgt_dev_show_attr_num_lus(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
-
 	return snprintf(page, PAGE_SIZE, "%u\n", LU_COUNT);
 }
 DEV_STAT_SCSI_TGT_DEV_ATTR_RO(num_lus);
@@ -219,60 +182,27 @@ DEV_STAT_SCSI_TGT_DEV_ATTR_RO(num_lus);
 static ssize_t target_stat_scsi_tgt_dev_show_attr_status(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-	char status[16];
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 
-	if (!dev)
-		return -ENODEV;
-
-	switch (dev->dev_status) {
-	case TRANSPORT_DEVICE_ACTIVATED:
-		strcpy(status, "activated");
-		break;
-	case TRANSPORT_DEVICE_DEACTIVATED:
-		strcpy(status, "deactivated");
-		break;
-	case TRANSPORT_DEVICE_SHUTDOWN:
-		strcpy(status, "shutdown");
-		break;
-	case TRANSPORT_DEVICE_OFFLINE_ACTIVATED:
-	case TRANSPORT_DEVICE_OFFLINE_DEACTIVATED:
-		strcpy(status, "offline");
-		break;
-	default:
-		sprintf(status, "unknown(%d)", dev->dev_status);
-		break;
-	}
-
-	return snprintf(page, PAGE_SIZE, "%s\n", status);
+	if (dev->export_count)
+		return snprintf(page, PAGE_SIZE, "activated");
+	else
+		return snprintf(page, PAGE_SIZE, "deactivated");
 }
 DEV_STAT_SCSI_TGT_DEV_ATTR_RO(status);
 
 static ssize_t target_stat_scsi_tgt_dev_show_attr_non_access_lus(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 	int non_accessible_lus;
 
-	if (!dev)
-		return -ENODEV;
-
-	switch (dev->dev_status) {
-	case TRANSPORT_DEVICE_ACTIVATED:
+	if (dev->export_count)
 		non_accessible_lus = 0;
-		break;
-	case TRANSPORT_DEVICE_DEACTIVATED:
-	case TRANSPORT_DEVICE_SHUTDOWN:
-	case TRANSPORT_DEVICE_OFFLINE_ACTIVATED:
-	case TRANSPORT_DEVICE_OFFLINE_DEACTIVATED:
-	default:
+	else
 		non_accessible_lus = 1;
-		break;
-	}
 
 	return snprintf(page, PAGE_SIZE, "%u\n", non_accessible_lus);
 }
@@ -281,12 +211,8 @@ DEV_STAT_SCSI_TGT_DEV_ATTR_RO(non_access_lus);
 static ssize_t target_stat_scsi_tgt_dev_show_attr_resets(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 
 	return snprintf(page, PAGE_SIZE, "%u\n", dev->num_resets);
 }
@@ -335,13 +261,9 @@ static struct target_stat_scsi_lu_attribute target_stat_scsi_lu_##_name = \
 static ssize_t target_stat_scsi_lu_show_attr_inst(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_hba *hba = se_subdev->se_dev_hba;
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
+	struct se_hba *hba = dev->se_hba;
 
 	return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
 }
@@ -350,12 +272,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(inst);
 static ssize_t target_stat_scsi_lu_show_attr_dev(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 
 	return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
 }
@@ -364,13 +282,6 @@ DEV_STAT_SCSI_LU_ATTR_RO(dev);
 static ssize_t target_stat_scsi_lu_show_attr_indx(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
-
 	return snprintf(page, PAGE_SIZE, "%u\n", SCSI_LU_INDEX);
 }
 DEV_STAT_SCSI_LU_ATTR_RO(indx);
@@ -378,12 +289,6 @@ DEV_STAT_SCSI_LU_ATTR_RO(indx);
 static ssize_t target_stat_scsi_lu_show_attr_lun(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
 	/* FIXME: scsiLuDefaultLun */
 	return snprintf(page, PAGE_SIZE, "%llu\n", (unsigned long long)0);
 }
@@ -392,35 +297,28 @@ DEV_STAT_SCSI_LU_ATTR_RO(lun);
 static ssize_t target_stat_scsi_lu_show_attr_lu_name(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 
-	if (!dev)
-		return -ENODEV;
 	/* scsiLuWwnName */
 	return snprintf(page, PAGE_SIZE, "%s\n",
-			(strlen(dev->se_sub_dev->t10_wwn.unit_serial)) ?
-			dev->se_sub_dev->t10_wwn.unit_serial : "None");
+			(strlen(dev->t10_wwn.unit_serial)) ?
+			dev->t10_wwn.unit_serial : "None");
 }
 DEV_STAT_SCSI_LU_ATTR_RO(lu_name);
 
 static ssize_t target_stat_scsi_lu_show_attr_vend(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 	int i;
-	char str[sizeof(dev->se_sub_dev->t10_wwn.vendor)+1];
-
-	if (!dev)
-		return -ENODEV;
+	char str[sizeof(dev->t10_wwn.vendor)+1];
 
 	/* scsiLuVendorId */
-	for (i = 0; i < sizeof(dev->se_sub_dev->t10_wwn.vendor); i++)
-		str[i] = ISPRINT(dev->se_sub_dev->t10_wwn.vendor[i]) ?
-			dev->se_sub_dev->t10_wwn.vendor[i] : ' ';
+	for (i = 0; i < sizeof(dev->t10_wwn.vendor); i++)
+		str[i] = ISPRINT(dev->t10_wwn.vendor[i]) ?
+			dev->t10_wwn.vendor[i] : ' ';
 	str[i] = '\0';
 	return snprintf(page, PAGE_SIZE, "%s\n", str);
 }
@@ -429,19 +327,15 @@ DEV_STAT_SCSI_LU_ATTR_RO(vend);
 static ssize_t target_stat_scsi_lu_show_attr_prod(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 	int i;
-	char str[sizeof(dev->se_sub_dev->t10_wwn.model)+1];
-
-	if (!dev)
-		return -ENODEV;
+	char str[sizeof(dev->t10_wwn.model)+1];
 
 	/* scsiLuProductId */
-	for (i = 0; i < sizeof(dev->se_sub_dev->t10_wwn.vendor); i++)
-		str[i] = ISPRINT(dev->se_sub_dev->t10_wwn.model[i]) ?
-			dev->se_sub_dev->t10_wwn.model[i] : ' ';
+	for (i = 0; i < sizeof(dev->t10_wwn.vendor); i++)
+		str[i] = ISPRINT(dev->t10_wwn.model[i]) ?
+			dev->t10_wwn.model[i] : ' ';
 	str[i] = '\0';
 	return snprintf(page, PAGE_SIZE, "%s\n", str);
 }
@@ -450,19 +344,15 @@ DEV_STAT_SCSI_LU_ATTR_RO(prod);
 static ssize_t target_stat_scsi_lu_show_attr_rev(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 	int i;
-	char str[sizeof(dev->se_sub_dev->t10_wwn.revision)+1];
-
-	if (!dev)
-		return -ENODEV;
+	char str[sizeof(dev->t10_wwn.revision)+1];
 
 	/* scsiLuRevisionId */
-	for (i = 0; i < sizeof(dev->se_sub_dev->t10_wwn.revision); i++)
-		str[i] = ISPRINT(dev->se_sub_dev->t10_wwn.revision[i]) ?
-			dev->se_sub_dev->t10_wwn.revision[i] : ' ';
+	for (i = 0; i < sizeof(dev->t10_wwn.revision); i++)
+		str[i] = ISPRINT(dev->t10_wwn.revision[i]) ?
+			dev->t10_wwn.revision[i] : ' ';
 	str[i] = '\0';
 	return snprintf(page, PAGE_SIZE, "%s\n", str);
 }
@@ -471,12 +361,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(rev);
 static ssize_t target_stat_scsi_lu_show_attr_dev_type(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 
 	/* scsiLuPeripheralType */
 	return snprintf(page, PAGE_SIZE, "%u\n",
@@ -487,30 +373,18 @@ DEV_STAT_SCSI_LU_ATTR_RO(dev_type);
 static ssize_t target_stat_scsi_lu_show_attr_status(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 
 	/* scsiLuStatus */
 	return snprintf(page, PAGE_SIZE, "%s\n",
-		(dev->dev_status == TRANSPORT_DEVICE_ACTIVATED) ?
-		"available" : "notavailable");
+		(dev->export_count) ? "available" : "notavailable");
 }
 DEV_STAT_SCSI_LU_ATTR_RO(status);
 
 static ssize_t target_stat_scsi_lu_show_attr_state_bit(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
-
 	/* scsiLuState */
 	return snprintf(page, PAGE_SIZE, "exposed\n");
 }
@@ -519,12 +393,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(state_bit);
 static ssize_t target_stat_scsi_lu_show_attr_num_cmds(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 
 	/* scsiLuNumCommands */
 	return snprintf(page, PAGE_SIZE, "%llu\n",
@@ -535,12 +405,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(num_cmds);
 static ssize_t target_stat_scsi_lu_show_attr_read_mbytes(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 
 	/* scsiLuReadMegaBytes */
 	return snprintf(page, PAGE_SIZE, "%u\n", (u32)(dev->read_bytes >> 20));
@@ -550,12 +416,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(read_mbytes);
 static ssize_t target_stat_scsi_lu_show_attr_write_mbytes(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 
 	/* scsiLuWrittenMegaBytes */
 	return snprintf(page, PAGE_SIZE, "%u\n", (u32)(dev->write_bytes >> 20));
@@ -565,12 +427,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(write_mbytes);
 static ssize_t target_stat_scsi_lu_show_attr_resets(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 
 	/* scsiLuInResets */
 	return snprintf(page, PAGE_SIZE, "%u\n", dev->num_resets);
@@ -580,13 +438,6 @@ DEV_STAT_SCSI_LU_ATTR_RO(resets);
 static ssize_t target_stat_scsi_lu_show_attr_full_stat(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
-
 	/* FIXME: scsiLuOutTaskSetFullStatus */
 	return snprintf(page, PAGE_SIZE, "%u\n", 0);
 }
@@ -595,13 +446,6 @@ DEV_STAT_SCSI_LU_ATTR_RO(full_stat);
 static ssize_t target_stat_scsi_lu_show_attr_hs_num_cmds(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
-
 	/* FIXME: scsiLuHSInCommands */
 	return snprintf(page, PAGE_SIZE, "%u\n", 0);
 }
@@ -610,12 +454,8 @@ DEV_STAT_SCSI_LU_ATTR_RO(hs_num_cmds);
 static ssize_t target_stat_scsi_lu_show_attr_creation_time(
 	struct se_dev_stat_grps *sgrps, char *page)
 {
-	struct se_subsystem_dev *se_subdev = container_of(sgrps,
-			struct se_subsystem_dev, dev_stat_grps);
-	struct se_device *dev = se_subdev->se_dev_ptr;
-
-	if (!dev)
-		return -ENODEV;
+	struct se_device *dev =
+		container_of(sgrps, struct se_device, dev_stat_grps);
 
 	/* scsiLuCreationTime */
 	return snprintf(page, PAGE_SIZE, "%u\n", (u32)(((u32)dev->creation_time -
@@ -662,20 +502,20 @@ static struct config_item_type target_stat_scsi_lu_cit = {
  * Called from target_core_configfs.c:target_core_make_subdev() to setup
  * the target statistics groups + configfs CITs located in target_core_stat.c
  */
-void target_stat_setup_dev_default_groups(struct se_subsystem_dev *se_subdev)
+void target_stat_setup_dev_default_groups(struct se_device *dev)
 {
-	struct config_group *dev_stat_grp = &se_subdev->dev_stat_grps.stat_group;
+	struct config_group *dev_stat_grp = &dev->dev_stat_grps.stat_group;
 
-	config_group_init_type_name(&se_subdev->dev_stat_grps.scsi_dev_group,
+	config_group_init_type_name(&dev->dev_stat_grps.scsi_dev_group,
 			"scsi_dev", &target_stat_scsi_dev_cit);
-	config_group_init_type_name(&se_subdev->dev_stat_grps.scsi_tgt_dev_group,
+	config_group_init_type_name(&dev->dev_stat_grps.scsi_tgt_dev_group,
 			"scsi_tgt_dev", &target_stat_scsi_tgt_dev_cit);
-	config_group_init_type_name(&se_subdev->dev_stat_grps.scsi_lu_group,
+	config_group_init_type_name(&dev->dev_stat_grps.scsi_lu_group,
 			"scsi_lu", &target_stat_scsi_lu_cit);
 
-	dev_stat_grp->default_groups[0] = &se_subdev->dev_stat_grps.scsi_dev_group;
-	dev_stat_grp->default_groups[1] = &se_subdev->dev_stat_grps.scsi_tgt_dev_group;
-	dev_stat_grp->default_groups[2] = &se_subdev->dev_stat_grps.scsi_lu_group;
+	dev_stat_grp->default_groups[0] = &dev->dev_stat_grps.scsi_dev_group;
+	dev_stat_grp->default_groups[1] = &dev->dev_stat_grps.scsi_tgt_dev_group;
+	dev_stat_grp->default_groups[2] = &dev->dev_stat_grps.scsi_lu_group;
 	dev_stat_grp->default_groups[3] = NULL;
 }
 
@@ -1161,7 +1001,7 @@ static ssize_t target_stat_scsi_transport_show_attr_dev_name(
 		return -ENODEV;
 	}
 	tpg = sep->sep_tpg;
-	wwn = &dev->se_sub_dev->t10_wwn;
+	wwn = &dev->t10_wwn;
 	/* scsiTransportDevName */
 	ret = snprintf(page, PAGE_SIZE, "%s+%s\n",
 			tpg->se_tpg_tfo->tpg_get_wwn(tpg),
diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c
index be75c43..c6e0293 100644
--- a/drivers/target/target_core_tmr.c
+++ b/drivers/target/target_core_tmr.c
@@ -3,8 +3,7 @@
  *
  * This file contains SPC-3 task management infrastructure
  *
- * Copyright (c) 2009,2010 Rising Tide Systems
- * Copyright (c) 2009,2010 Linux-iSCSI.org
+ * (c) Copyright 2009-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@kernel.org>
  *
@@ -371,7 +370,7 @@ int core_tmr_lun_reset(
 	 * which the command was received shall be completed with TASK ABORTED
 	 * status (see SAM-4).
 	 */
-	tas = dev->se_sub_dev->se_dev_attrib.emulate_tas;
+	tas = dev->dev_attrib.emulate_tas;
 	/*
 	 * Determine if this se_tmr is coming from a $FABRIC_MOD
 	 * or struct se_device passthrough..
@@ -399,10 +398,10 @@ int core_tmr_lun_reset(
 	 * LOGICAL UNIT RESET
 	 */
 	if (!preempt_and_abort_list &&
-	     (dev->dev_flags & DF_SPC2_RESERVATIONS)) {
+	     (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)) {
 		spin_lock(&dev->dev_reservation_lock);
 		dev->dev_reserved_node_acl = NULL;
-		dev->dev_flags &= ~DF_SPC2_RESERVATIONS;
+		dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS;
 		spin_unlock(&dev->dev_reservation_lock);
 		pr_debug("LUN_RESET: SCSI-2 Released reservation\n");
 	}
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
index a531fe2..d84cc0a 100644
--- a/drivers/target/target_core_tpg.c
+++ b/drivers/target/target_core_tpg.c
@@ -3,10 +3,7 @@
  *
  * This file contains generic Target Portal Group related functions.
  *
- * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc.
- * Copyright (c) 2005, 2006, 2007 SBE, Inc.
- * Copyright (c) 2007-2010 Rising Tide Systems
- * Copyright (c) 2008-2010 Linux-iSCSI.org
+ * (c) Copyright 2002-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@kernel.org>
  *
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 9097155..1ebde4c5 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -3,10 +3,7 @@
  *
  * This file contains the Generic Target Engine Core.
  *
- * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc.
- * Copyright (c) 2005, 2006, 2007 SBE, Inc.
- * Copyright (c) 2007-2010 Rising Tide Systems
- * Copyright (c) 2008-2010 Linux-iSCSI.org
+ * (c) Copyright 2002-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@kernel.org>
  *
@@ -70,7 +67,6 @@ static void transport_handle_queue_full(struct se_cmd *cmd,
 static int transport_generic_get_mem(struct se_cmd *cmd);
 static int target_get_sess_cmd(struct se_session *, struct se_cmd *, bool);
 static void transport_put_cmd(struct se_cmd *cmd);
-static int transport_set_sense_codes(struct se_cmd *cmd, u8 asc, u8 ascq);
 static void target_complete_ok_work(struct work_struct *work);
 
 int init_se_kmem_caches(void)
@@ -297,7 +293,7 @@ void transport_register_session(
 }
 EXPORT_SYMBOL(transport_register_session);
 
-void target_release_session(struct kref *kref)
+static void target_release_session(struct kref *kref)
 {
 	struct se_session *se_sess = container_of(kref,
 			struct se_session, sess_kref);
@@ -558,7 +554,8 @@ static void target_complete_failure_work(struct work_struct *work)
 {
 	struct se_cmd *cmd = container_of(work, struct se_cmd, work);
 
-	transport_generic_request_failure(cmd);
+	transport_generic_request_failure(cmd,
+			TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE);
 }
 
 /*
@@ -626,7 +623,6 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
 		complete(&cmd->t_transport_stop_comp);
 		return;
 	} else if (cmd->transport_state & CMD_T_FAILED) {
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 		INIT_WORK(&cmd->work, target_complete_failure_work);
 	} else {
 		INIT_WORK(&cmd->work, target_complete_ok_work);
@@ -659,7 +655,7 @@ static void target_add_to_state_list(struct se_cmd *cmd)
 static void transport_write_pending_qf(struct se_cmd *cmd);
 static void transport_complete_qf(struct se_cmd *cmd);
 
-static void target_qf_do_work(struct work_struct *work)
+void target_qf_do_work(struct work_struct *work)
 {
 	struct se_device *dev = container_of(work, struct se_device,
 					qf_work_queue);
@@ -712,29 +708,15 @@ void transport_dump_dev_state(
 	int *bl)
 {
 	*bl += sprintf(b + *bl, "Status: ");
-	switch (dev->dev_status) {
-	case TRANSPORT_DEVICE_ACTIVATED:
+	if (dev->export_count)
 		*bl += sprintf(b + *bl, "ACTIVATED");
-		break;
-	case TRANSPORT_DEVICE_DEACTIVATED:
+	else
 		*bl += sprintf(b + *bl, "DEACTIVATED");
-		break;
-	case TRANSPORT_DEVICE_SHUTDOWN:
-		*bl += sprintf(b + *bl, "SHUTDOWN");
-		break;
-	case TRANSPORT_DEVICE_OFFLINE_ACTIVATED:
-	case TRANSPORT_DEVICE_OFFLINE_DEACTIVATED:
-		*bl += sprintf(b + *bl, "OFFLINE");
-		break;
-	default:
-		*bl += sprintf(b + *bl, "UNKNOWN=%d", dev->dev_status);
-		break;
-	}
 
 	*bl += sprintf(b + *bl, "  Max Queue Depth: %d", dev->queue_depth);
 	*bl += sprintf(b + *bl, "  SectorSize: %u  HwMaxSectors: %u\n",
-		dev->se_sub_dev->se_dev_attrib.block_size,
-		dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
+		dev->dev_attrib.block_size,
+		dev->dev_attrib.hw_max_sectors);
 	*bl += sprintf(b + *bl, "        ");
 }
 
@@ -991,186 +973,8 @@ transport_set_vpd_ident(struct t10_vpd *vpd, unsigned char *page_83)
 }
 EXPORT_SYMBOL(transport_set_vpd_ident);
 
-static void core_setup_task_attr_emulation(struct se_device *dev)
-{
-	/*
-	 * If this device is from Target_Core_Mod/pSCSI, disable the
-	 * SAM Task Attribute emulation.
-	 *
-	 * This is currently not available in upsream Linux/SCSI Target
-	 * mode code, and is assumed to be disabled while using TCM/pSCSI.
-	 */
-	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
-		dev->dev_task_attr_type = SAM_TASK_ATTR_PASSTHROUGH;
-		return;
-	}
-
-	dev->dev_task_attr_type = SAM_TASK_ATTR_EMULATED;
-	pr_debug("%s: Using SAM_TASK_ATTR_EMULATED for SPC: 0x%02x"
-		" device\n", dev->transport->name,
-		dev->transport->get_device_rev(dev));
-}
-
-static void scsi_dump_inquiry(struct se_device *dev)
-{
-	struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn;
-	char buf[17];
-	int i, device_type;
-	/*
-	 * Print Linux/SCSI style INQUIRY formatting to the kernel ring buffer
-	 */
-	for (i = 0; i < 8; i++)
-		if (wwn->vendor[i] >= 0x20)
-			buf[i] = wwn->vendor[i];
-		else
-			buf[i] = ' ';
-	buf[i] = '\0';
-	pr_debug("  Vendor: %s\n", buf);
-
-	for (i = 0; i < 16; i++)
-		if (wwn->model[i] >= 0x20)
-			buf[i] = wwn->model[i];
-		else
-			buf[i] = ' ';
-	buf[i] = '\0';
-	pr_debug("  Model: %s\n", buf);
-
-	for (i = 0; i < 4; i++)
-		if (wwn->revision[i] >= 0x20)
-			buf[i] = wwn->revision[i];
-		else
-			buf[i] = ' ';
-	buf[i] = '\0';
-	pr_debug("  Revision: %s\n", buf);
-
-	device_type = dev->transport->get_device_type(dev);
-	pr_debug("  Type:   %s ", scsi_device_type(device_type));
-	pr_debug("                 ANSI SCSI revision: %02x\n",
-				dev->transport->get_device_rev(dev));
-}
-
-struct se_device *transport_add_device_to_core_hba(
-	struct se_hba *hba,
-	struct se_subsystem_api *transport,
-	struct se_subsystem_dev *se_dev,
-	u32 device_flags,
-	void *transport_dev,
-	struct se_dev_limits *dev_limits,
-	const char *inquiry_prod,
-	const char *inquiry_rev)
-{
-	int force_pt;
-	struct se_device  *dev;
-
-	dev = kzalloc(sizeof(struct se_device), GFP_KERNEL);
-	if (!dev) {
-		pr_err("Unable to allocate memory for se_dev_t\n");
-		return NULL;
-	}
-
-	dev->dev_flags		= device_flags;
-	dev->dev_status		|= TRANSPORT_DEVICE_DEACTIVATED;
-	dev->dev_ptr		= transport_dev;
-	dev->se_hba		= hba;
-	dev->se_sub_dev		= se_dev;
-	dev->transport		= transport;
-	INIT_LIST_HEAD(&dev->dev_list);
-	INIT_LIST_HEAD(&dev->dev_sep_list);
-	INIT_LIST_HEAD(&dev->dev_tmr_list);
-	INIT_LIST_HEAD(&dev->delayed_cmd_list);
-	INIT_LIST_HEAD(&dev->state_list);
-	INIT_LIST_HEAD(&dev->qf_cmd_list);
-	spin_lock_init(&dev->execute_task_lock);
-	spin_lock_init(&dev->delayed_cmd_lock);
-	spin_lock_init(&dev->dev_reservation_lock);
-	spin_lock_init(&dev->dev_status_lock);
-	spin_lock_init(&dev->se_port_lock);
-	spin_lock_init(&dev->se_tmr_lock);
-	spin_lock_init(&dev->qf_cmd_lock);
-	atomic_set(&dev->dev_ordered_id, 0);
-
-	se_dev_set_default_attribs(dev, dev_limits);
-
-	dev->dev_index = scsi_get_new_index(SCSI_DEVICE_INDEX);
-	dev->creation_time = get_jiffies_64();
-	spin_lock_init(&dev->stats_lock);
-
-	spin_lock(&hba->device_lock);
-	list_add_tail(&dev->dev_list, &hba->hba_dev_list);
-	hba->dev_count++;
-	spin_unlock(&hba->device_lock);
-	/*
-	 * Setup the SAM Task Attribute emulation for struct se_device
-	 */
-	core_setup_task_attr_emulation(dev);
-	/*
-	 * Force PR and ALUA passthrough emulation with internal object use.
-	 */
-	force_pt = (hba->hba_flags & HBA_FLAGS_INTERNAL_USE);
-	/*
-	 * Setup the Reservations infrastructure for struct se_device
-	 */
-	core_setup_reservations(dev, force_pt);
-	/*
-	 * Setup the Asymmetric Logical Unit Assignment for struct se_device
-	 */
-	if (core_setup_alua(dev, force_pt) < 0)
-		goto err_dev_list;
-
-	/*
-	 * Startup the struct se_device processing thread
-	 */
-	dev->tmr_wq = alloc_workqueue("tmr-%s", WQ_MEM_RECLAIM | WQ_UNBOUND, 1,
-				      dev->transport->name);
-	if (!dev->tmr_wq) {
-		pr_err("Unable to create tmr workqueue for %s\n",
-			dev->transport->name);
-		goto err_dev_list;
-	}
-	/*
-	 * Setup work_queue for QUEUE_FULL
-	 */
-	INIT_WORK(&dev->qf_work_queue, target_qf_do_work);
-	/*
-	 * Preload the initial INQUIRY const values if we are doing
-	 * anything virtual (IBLOCK, FILEIO, RAMDISK), but not for TCM/pSCSI
-	 * passthrough because this is being provided by the backend LLD.
-	 * This is required so that transport_get_inquiry() copies these
-	 * originals once back into DEV_T10_WWN(dev) for the virtual device
-	 * setup.
-	 */
-	if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) {
-		if (!inquiry_prod || !inquiry_rev) {
-			pr_err("All non TCM/pSCSI plugins require"
-				" INQUIRY consts\n");
-			goto err_wq;
-		}
-
-		strncpy(&dev->se_sub_dev->t10_wwn.vendor[0], "LIO-ORG", 8);
-		strncpy(&dev->se_sub_dev->t10_wwn.model[0], inquiry_prod, 16);
-		strncpy(&dev->se_sub_dev->t10_wwn.revision[0], inquiry_rev, 4);
-	}
-	scsi_dump_inquiry(dev);
-
-	return dev;
-
-err_wq:
-	destroy_workqueue(dev->tmr_wq);
-err_dev_list:
-	spin_lock(&hba->device_lock);
-	list_del(&dev->dev_list);
-	hba->dev_count--;
-	spin_unlock(&hba->device_lock);
-
-	se_release_vpd_for_dev(dev);
-
-	kfree(dev);
-
-	return NULL;
-}
-EXPORT_SYMBOL(transport_add_device_to_core_hba);
-
-int target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
+sense_reason_t
+target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
 {
 	struct se_device *dev = cmd->se_dev;
 
@@ -1185,18 +989,18 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
 		if (cmd->data_direction == DMA_TO_DEVICE) {
 			pr_err("Rejecting underflow/overflow"
 					" WRITE data\n");
-			goto out_invalid_cdb_field;
+			return TCM_INVALID_CDB_FIELD;
 		}
 		/*
 		 * Reject READ_* or WRITE_* with overflow/underflow for
 		 * type SCF_SCSI_DATA_CDB.
 		 */
-		if (dev->se_sub_dev->se_dev_attrib.block_size != 512)  {
+		if (dev->dev_attrib.block_size != 512)  {
 			pr_err("Failing OVERFLOW/UNDERFLOW for LBA op"
 				" CDB on non 512-byte sector setup subsystem"
 				" plugin: %s\n", dev->transport->name);
 			/* Returns CHECK_CONDITION + INVALID_CDB_FIELD */
-			goto out_invalid_cdb_field;
+			return TCM_INVALID_CDB_FIELD;
 		}
 		/*
 		 * For the overflow case keep the existing fabric provided
@@ -1216,10 +1020,6 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
 
 	return 0;
 
-out_invalid_cdb_field:
-	cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-	cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-	return -EINVAL;
 }
 
 /*
@@ -1259,45 +1059,41 @@ void transport_init_se_cmd(
 }
 EXPORT_SYMBOL(transport_init_se_cmd);
 
-static int transport_check_alloc_task_attr(struct se_cmd *cmd)
+static sense_reason_t
+transport_check_alloc_task_attr(struct se_cmd *cmd)
 {
+	struct se_device *dev = cmd->se_dev;
+
 	/*
 	 * Check if SAM Task Attribute emulation is enabled for this
 	 * struct se_device storage object
 	 */
-	if (cmd->se_dev->dev_task_attr_type != SAM_TASK_ATTR_EMULATED)
+	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
 		return 0;
 
 	if (cmd->sam_task_attr == MSG_ACA_TAG) {
 		pr_debug("SAM Task Attribute ACA"
 			" emulation is not supported\n");
-		return -EINVAL;
+		return TCM_INVALID_CDB_FIELD;
 	}
 	/*
 	 * Used to determine when ORDERED commands should go from
 	 * Dormant to Active status.
 	 */
-	cmd->se_ordered_id = atomic_inc_return(&cmd->se_dev->dev_ordered_id);
+	cmd->se_ordered_id = atomic_inc_return(&dev->dev_ordered_id);
 	smp_mb__after_atomic_inc();
 	pr_debug("Allocated se_ordered_id: %u for Task Attr: 0x%02x on %s\n",
 			cmd->se_ordered_id, cmd->sam_task_attr,
-			cmd->se_dev->transport->name);
+			dev->transport->name);
 	return 0;
 }
 
-/*	target_setup_cmd_from_cdb():
- *
- *	Called from fabric RX Thread.
- */
-int target_setup_cmd_from_cdb(
-	struct se_cmd *cmd,
-	unsigned char *cdb)
+sense_reason_t
+target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb)
 {
-	struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
-	u32 pr_reg_type = 0;
-	u8 alua_ascq = 0;
+	struct se_device *dev = cmd->se_dev;
 	unsigned long flags;
-	int ret;
+	sense_reason_t ret;
 
 	/*
 	 * Ensure that the received CDB is less than the max (252 + 8) bytes
@@ -1307,9 +1103,7 @@ int target_setup_cmd_from_cdb(
 		pr_err("Received SCSI CDB with command_size: %d that"
 			" exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n",
 			scsi_command_size(cdb), SCSI_MAX_VARLEN_CDB_SIZE);
-		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		return -EINVAL;
+		return TCM_INVALID_CDB_FIELD;
 	}
 	/*
 	 * If the received CDB is larger than TCM_MAX_COMMAND_SIZE,
@@ -1324,10 +1118,7 @@ int target_setup_cmd_from_cdb(
 				" %u > sizeof(cmd->__t_task_cdb): %lu ops\n",
 				scsi_command_size(cdb),
 				(unsigned long)sizeof(cmd->__t_task_cdb));
-			cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-			cmd->scsi_sense_reason =
-					TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-			return -ENOMEM;
+			return TCM_OUT_OF_RESOURCES;
 		}
 	} else
 		cmd->t_task_cdb = &cmd->__t_task_cdb[0];
@@ -1339,70 +1130,30 @@ int target_setup_cmd_from_cdb(
 	/*
 	 * Check for an existing UNIT ATTENTION condition
 	 */
-	if (core_scsi3_ua_check(cmd, cdb) < 0) {
-		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		cmd->scsi_sense_reason = TCM_CHECK_CONDITION_UNIT_ATTENTION;
-		return -EINVAL;
-	}
+	ret = target_scsi3_ua_check(cmd);
+	if (ret)
+		return ret;
 
-	ret = su_dev->t10_alua.alua_state_check(cmd, cdb, &alua_ascq);
-	if (ret != 0) {
-		/*
-		 * Set SCSI additional sense code (ASC) to 'LUN Not Accessible';
-		 * The ALUA additional sense code qualifier (ASCQ) is determined
-		 * by the ALUA primary or secondary access state..
-		 */
-		if (ret > 0) {
-			pr_debug("[%s]: ALUA TG Port not available, "
-				"SenseKey: NOT_READY, ASC/ASCQ: "
-				"0x04/0x%02x\n",
-				cmd->se_tfo->get_fabric_name(), alua_ascq);
-
-			transport_set_sense_codes(cmd, 0x04, alua_ascq);
-			cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-			cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY;
-			return -EINVAL;
-		}
-		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		return -EINVAL;
-	}
+	ret = target_alua_state_check(cmd);
+	if (ret)
+		return ret;
 
-	/*
-	 * Check status for SPC-3 Persistent Reservations
-	 */
-	if (su_dev->t10_pr.pr_ops.t10_reservation_check(cmd, &pr_reg_type)) {
-		if (su_dev->t10_pr.pr_ops.t10_seq_non_holder(
-					cmd, cdb, pr_reg_type) != 0) {
-			cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-			cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT;
-			cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
-			cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-			return -EBUSY;
-		}
-		/*
-		 * This means the CDB is allowed for the SCSI Initiator port
-		 * when said port is *NOT* holding the legacy SPC-2 or
-		 * SPC-3 Persistent Reservation.
-		 */
-	}
+	ret = target_check_reservation(cmd);
+	if (ret)
+		return ret;
 
-	ret = cmd->se_dev->transport->parse_cdb(cmd);
-	if (ret < 0)
+	ret = dev->transport->parse_cdb(cmd);
+	if (ret)
+		return ret;
+
+	ret = transport_check_alloc_task_attr(cmd);
+	if (ret)
 		return ret;
 
 	spin_lock_irqsave(&cmd->t_state_lock, flags);
 	cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE;
 	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-	/*
-	 * Check for SAM Task Attribute Emulation
-	 */
-	if (transport_check_alloc_task_attr(cmd) < 0) {
-		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		return -EINVAL;
-	}
 	spin_lock(&cmd->se_lun->lun_sep_lock);
 	if (cmd->se_lun->lun_sep)
 		cmd->se_lun->lun_sep->sep_stats.cmd_pdus++;
@@ -1418,7 +1169,7 @@ EXPORT_SYMBOL(target_setup_cmd_from_cdb);
 int transport_handle_cdb_direct(
 	struct se_cmd *cmd)
 {
-	int ret;
+	sense_reason_t ret;
 
 	if (!cmd->se_lun) {
 		dump_stack();
@@ -1448,13 +1199,41 @@ int transport_handle_cdb_direct(
 	 * and call transport_generic_request_failure() if necessary..
 	 */
 	ret = transport_generic_new_cmd(cmd);
-	if (ret < 0)
-		transport_generic_request_failure(cmd);
-
+	if (ret)
+		transport_generic_request_failure(cmd, ret);
 	return 0;
 }
 EXPORT_SYMBOL(transport_handle_cdb_direct);
 
+static sense_reason_t
+transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
+		u32 sgl_count, struct scatterlist *sgl_bidi, u32 sgl_bidi_count)
+{
+	if (!sgl || !sgl_count)
+		return 0;
+
+	/*
+	 * Reject SCSI data overflow with map_mem_to_cmd() as incoming
+	 * scatterlists already have been set to follow what the fabric
+	 * passes for the original expected data transfer length.
+	 */
+	if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
+		pr_warn("Rejecting SCSI DATA overflow for fabric using"
+			" SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n");
+		return TCM_INVALID_CDB_FIELD;
+	}
+
+	cmd->t_data_sg = sgl;
+	cmd->t_data_nents = sgl_count;
+
+	if (sgl_bidi && sgl_bidi_count) {
+		cmd->t_bidi_data_sg = sgl_bidi;
+		cmd->t_bidi_data_nents = sgl_bidi_count;
+	}
+	cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
+	return 0;
+}
+
 /*
  * target_submit_cmd_map_sgls - lookup unpacked lun and submit uninitialized
  * 			 se_cmd + use pre-allocated SGL memory.
@@ -1487,7 +1266,8 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
 		struct scatterlist *sgl_bidi, u32 sgl_bidi_count)
 {
 	struct se_portal_group *se_tpg;
-	int rc;
+	sense_reason_t rc;
+	int ret;
 
 	se_tpg = se_sess->se_tpg;
 	BUG_ON(!se_tpg);
@@ -1508,9 +1288,9 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
 	 * for fabrics using TARGET_SCF_ACK_KREF that expect a second
 	 * kref_put() to happen during fabric packet acknowledgement.
 	 */
-	rc = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
-	if (rc)
-		return rc;
+	ret = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
+	if (ret)
+		return ret;
 	/*
 	 * Signal bidirectional data payloads to target-core
 	 */
@@ -1519,16 +1299,16 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
 	/*
 	 * Locate se_lun pointer and attach it to struct se_cmd
 	 */
-	if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) {
-		transport_send_check_condition_and_sense(se_cmd,
-				se_cmd->scsi_sense_reason, 0);
+	rc = transport_lookup_cmd_lun(se_cmd, unpacked_lun);
+	if (rc) {
+		transport_send_check_condition_and_sense(se_cmd, rc, 0);
 		target_put_sess_cmd(se_sess, se_cmd);
 		return 0;
 	}
 
 	rc = target_setup_cmd_from_cdb(se_cmd, cdb);
 	if (rc != 0) {
-		transport_generic_request_failure(se_cmd);
+		transport_generic_request_failure(se_cmd, rc);
 		return 0;
 	}
 	/*
@@ -1563,7 +1343,7 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
 		rc = transport_generic_map_mem_to_cmd(se_cmd, sgl, sgl_count,
 				sgl_bidi, sgl_bidi_count);
 		if (rc != 0) {
-			transport_generic_request_failure(se_cmd);
+			transport_generic_request_failure(se_cmd, rc);
 			return 0;
 		}
 	}
@@ -1709,16 +1489,17 @@ bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags)
 /*
  * Handle SAM-esque emulation for generic transport request failures.
  */
-void transport_generic_request_failure(struct se_cmd *cmd)
+void transport_generic_request_failure(struct se_cmd *cmd,
+		sense_reason_t sense_reason)
 {
 	int ret = 0;
 
 	pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08x"
 		" CDB: 0x%02x\n", cmd, cmd->se_tfo->get_task_tag(cmd),
 		cmd->t_task_cdb[0]);
-	pr_debug("-----[ i_state: %d t_state: %d scsi_sense_reason: %d\n",
+	pr_debug("-----[ i_state: %d t_state: %d sense_reason: %d\n",
 		cmd->se_tfo->get_cmd_state(cmd),
-		cmd->t_state, cmd->scsi_sense_reason);
+		cmd->t_state, sense_reason);
 	pr_debug("-----[ CMD_T_ACTIVE: %d CMD_T_STOP: %d CMD_T_SENT: %d\n",
 		(cmd->transport_state & CMD_T_ACTIVE) != 0,
 		(cmd->transport_state & CMD_T_STOP) != 0,
@@ -1727,10 +1508,9 @@ void transport_generic_request_failure(struct se_cmd *cmd)
 	/*
 	 * For SAM Task Attribute emulation for failed struct se_cmd
 	 */
-	if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
-		transport_complete_task_attr(cmd);
+	transport_complete_task_attr(cmd);
 
-	switch (cmd->scsi_sense_reason) {
+	switch (sense_reason) {
 	case TCM_NON_EXISTENT_LUN:
 	case TCM_UNSUPPORTED_SCSI_OPCODE:
 	case TCM_INVALID_CDB_FIELD:
@@ -1743,6 +1523,9 @@ void transport_generic_request_failure(struct se_cmd *cmd)
 	case TCM_CHECK_CONDITION_UNIT_ATTENTION:
 	case TCM_CHECK_CONDITION_NOT_READY:
 		break;
+	case TCM_OUT_OF_RESOURCES:
+		sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+		break;
 	case TCM_RESERVATION_CONFLICT:
 		/*
 		 * No SENSE Data payload for this case, set SCSI Status
@@ -1759,7 +1542,7 @@ void transport_generic_request_failure(struct se_cmd *cmd)
 		 * See spc4r17, section 7.4.6 Control Mode Page, Table 349
 		 */
 		if (cmd->se_sess &&
-		    cmd->se_dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 2)
+		    cmd->se_dev->dev_attrib.emulate_ua_intlck_ctrl == 2)
 			core_scsi3_ua_allocate(cmd->se_sess->se_node_acl,
 				cmd->orig_fe_lun, 0x2C,
 				ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS);
@@ -1770,13 +1553,12 @@ void transport_generic_request_failure(struct se_cmd *cmd)
 		goto check_stop;
 	default:
 		pr_err("Unknown transport error for CDB 0x%02x: %d\n",
-			cmd->t_task_cdb[0], cmd->scsi_sense_reason);
-		cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
+			cmd->t_task_cdb[0], sense_reason);
+		sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
 		break;
 	}
 
-	ret = transport_send_check_condition_and_sense(cmd,
-			cmd->scsi_sense_reason, 0);
+	ret = transport_send_check_condition_and_sense(cmd, sense_reason, 0);
 	if (ret == -EAGAIN || ret == -ENOMEM)
 		goto queue_full;
 
@@ -1794,67 +1576,30 @@ EXPORT_SYMBOL(transport_generic_request_failure);
 
 static void __target_execute_cmd(struct se_cmd *cmd)
 {
-	int error = 0;
+	sense_reason_t ret;
 
 	spin_lock_irq(&cmd->t_state_lock);
 	cmd->transport_state |= (CMD_T_BUSY|CMD_T_SENT);
 	spin_unlock_irq(&cmd->t_state_lock);
 
-	if (cmd->execute_cmd)
-		error = cmd->execute_cmd(cmd);
+	if (cmd->execute_cmd) {
+		ret = cmd->execute_cmd(cmd);
+		if (ret) {
+			spin_lock_irq(&cmd->t_state_lock);
+			cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
+			spin_unlock_irq(&cmd->t_state_lock);
 
-	if (error) {
-		spin_lock_irq(&cmd->t_state_lock);
-		cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
-		spin_unlock_irq(&cmd->t_state_lock);
-
-		transport_generic_request_failure(cmd);
+			transport_generic_request_failure(cmd, ret);
+		}
 	}
 }
 
-void target_execute_cmd(struct se_cmd *cmd)
+static bool target_handle_task_attr(struct se_cmd *cmd)
 {
 	struct se_device *dev = cmd->se_dev;
 
-	/*
-	 * If the received CDB has aleady been aborted stop processing it here.
-	 */
-	if (transport_check_aborted_status(cmd, 1))
-		return;
-
-	/*
-	 * Determine if IOCTL context caller in requesting the stopping of this
-	 * command for LUN shutdown purposes.
-	 */
-	spin_lock_irq(&cmd->t_state_lock);
-	if (cmd->transport_state & CMD_T_LUN_STOP) {
-		pr_debug("%s:%d CMD_T_LUN_STOP for ITT: 0x%08x\n",
-			__func__, __LINE__, cmd->se_tfo->get_task_tag(cmd));
-
-		cmd->transport_state &= ~CMD_T_ACTIVE;
-		spin_unlock_irq(&cmd->t_state_lock);
-		complete(&cmd->transport_lun_stop_comp);
-		return;
-	}
-	/*
-	 * Determine if frontend context caller is requesting the stopping of
-	 * this command for frontend exceptions.
-	 */
-	if (cmd->transport_state & CMD_T_STOP) {
-		pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08x\n",
-			__func__, __LINE__,
-			cmd->se_tfo->get_task_tag(cmd));
-
-		spin_unlock_irq(&cmd->t_state_lock);
-		complete(&cmd->t_transport_stop_comp);
-		return;
-	}
-
-	cmd->t_state = TRANSPORT_PROCESSING;
-	spin_unlock_irq(&cmd->t_state_lock);
-
-	if (dev->dev_task_attr_type != SAM_TASK_ATTR_EMULATED)
-		goto execute;
+	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
+		return false;
 
 	/*
 	 * Check for the existence of HEAD_OF_QUEUE, and if true return 1
@@ -1865,7 +1610,7 @@ void target_execute_cmd(struct se_cmd *cmd)
 		pr_debug("Added HEAD_OF_QUEUE for CDB: 0x%02x, "
 			 "se_ordered_id: %u\n",
 			 cmd->t_task_cdb[0], cmd->se_ordered_id);
-		goto execute;
+		return false;
 	case MSG_ORDERED_TAG:
 		atomic_inc(&dev->dev_ordered_sync);
 		smp_mb__after_atomic_inc();
@@ -1879,7 +1624,7 @@ void target_execute_cmd(struct se_cmd *cmd)
 		 * exist that need to be completed first.
 		 */
 		if (!atomic_read(&dev->simple_cmds))
-			goto execute;
+			return false;
 		break;
 	default:
 		/*
@@ -1890,23 +1635,61 @@ void target_execute_cmd(struct se_cmd *cmd)
 		break;
 	}
 
-	if (atomic_read(&dev->dev_ordered_sync) != 0) {
-		spin_lock(&dev->delayed_cmd_lock);
-		list_add_tail(&cmd->se_delayed_node, &dev->delayed_cmd_list);
-		spin_unlock(&dev->delayed_cmd_lock);
+	if (atomic_read(&dev->dev_ordered_sync) == 0)
+		return false;
 
-		pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to"
-			" delayed CMD list, se_ordered_id: %u\n",
-			cmd->t_task_cdb[0], cmd->sam_task_attr,
-			cmd->se_ordered_id);
+	spin_lock(&dev->delayed_cmd_lock);
+	list_add_tail(&cmd->se_delayed_node, &dev->delayed_cmd_list);
+	spin_unlock(&dev->delayed_cmd_lock);
+
+	pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to"
+		" delayed CMD list, se_ordered_id: %u\n",
+		cmd->t_task_cdb[0], cmd->sam_task_attr,
+		cmd->se_ordered_id);
+	return true;
+}
+
+void target_execute_cmd(struct se_cmd *cmd)
+{
+	/*
+	 * If the received CDB has aleady been aborted stop processing it here.
+	 */
+	if (transport_check_aborted_status(cmd, 1))
 		return;
-	}
 
-execute:
 	/*
-	 * Otherwise, no ORDERED task attributes exist..
+	 * Determine if IOCTL context caller in requesting the stopping of this
+	 * command for LUN shutdown purposes.
 	 */
-	__target_execute_cmd(cmd);
+	spin_lock_irq(&cmd->t_state_lock);
+	if (cmd->transport_state & CMD_T_LUN_STOP) {
+		pr_debug("%s:%d CMD_T_LUN_STOP for ITT: 0x%08x\n",
+			__func__, __LINE__, cmd->se_tfo->get_task_tag(cmd));
+
+		cmd->transport_state &= ~CMD_T_ACTIVE;
+		spin_unlock_irq(&cmd->t_state_lock);
+		complete(&cmd->transport_lun_stop_comp);
+		return;
+	}
+	/*
+	 * Determine if frontend context caller is requesting the stopping of
+	 * this command for frontend exceptions.
+	 */
+	if (cmd->transport_state & CMD_T_STOP) {
+		pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08x\n",
+			__func__, __LINE__,
+			cmd->se_tfo->get_task_tag(cmd));
+
+		spin_unlock_irq(&cmd->t_state_lock);
+		complete(&cmd->t_transport_stop_comp);
+		return;
+	}
+
+	cmd->t_state = TRANSPORT_PROCESSING;
+	spin_unlock_irq(&cmd->t_state_lock);
+
+	if (!target_handle_task_attr(cmd))
+		__target_execute_cmd(cmd);
 }
 EXPORT_SYMBOL(target_execute_cmd);
 
@@ -1945,6 +1728,9 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
 {
 	struct se_device *dev = cmd->se_dev;
 
+	if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
+		return;
+
 	if (cmd->sam_task_attr == MSG_SIMPLE_TAG) {
 		atomic_dec(&dev->simple_cmds);
 		smp_mb__after_atomic_dec();
@@ -1973,8 +1759,7 @@ static void transport_complete_qf(struct se_cmd *cmd)
 {
 	int ret = 0;
 
-	if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
-		transport_complete_task_attr(cmd);
+	transport_complete_task_attr(cmd);
 
 	if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) {
 		ret = cmd->se_tfo->queue_status(cmd);
@@ -2032,8 +1817,8 @@ static void target_complete_ok_work(struct work_struct *work)
 	 * delayed execution list after a HEAD_OF_QUEUE or ORDERED Task
 	 * Attribute.
 	 */
-	if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
-		transport_complete_task_attr(cmd);
+	transport_complete_task_attr(cmd);
+
 	/*
 	 * Check to schedule QUEUE_FULL work, or execute an existing
 	 * cmd->transport_qf_callback()
@@ -2181,9 +1966,10 @@ static void transport_put_cmd(struct se_cmd *cmd)
 	unsigned long flags;
 
 	spin_lock_irqsave(&cmd->t_state_lock, flags);
-	if (atomic_read(&cmd->t_fe_count)) {
-		if (!atomic_dec_and_test(&cmd->t_fe_count))
-			goto out_busy;
+	if (atomic_read(&cmd->t_fe_count) &&
+	    !atomic_dec_and_test(&cmd->t_fe_count)) {
+		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+		return;
 	}
 
 	if (cmd->transport_state & CMD_T_DEV_ACTIVE) {
@@ -2195,57 +1981,8 @@ static void transport_put_cmd(struct se_cmd *cmd)
 	transport_free_pages(cmd);
 	transport_release_cmd(cmd);
 	return;
-out_busy:
-	spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 }
 
-/*
- * transport_generic_map_mem_to_cmd - Use fabric-alloced pages instead of
- * allocating in the core.
- * @cmd:  Associated se_cmd descriptor
- * @mem:  SGL style memory for TCM WRITE / READ
- * @sg_mem_num: Number of SGL elements
- * @mem_bidi_in: SGL style memory for TCM BIDI READ
- * @sg_mem_bidi_num: Number of BIDI READ SGL elements
- *
- * Return: nonzero return cmd was rejected for -ENOMEM or inproper usage
- * of parameters.
- */
-int transport_generic_map_mem_to_cmd(
-	struct se_cmd *cmd,
-	struct scatterlist *sgl,
-	u32 sgl_count,
-	struct scatterlist *sgl_bidi,
-	u32 sgl_bidi_count)
-{
-	if (!sgl || !sgl_count)
-		return 0;
-
-	/*
-	 * Reject SCSI data overflow with map_mem_to_cmd() as incoming
-	 * scatterlists already have been set to follow what the fabric
-	 * passes for the original expected data transfer length.
-	 */
-	if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
-		pr_warn("Rejecting SCSI DATA overflow for fabric using"
-			" SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n");
-		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		return -EINVAL;
-	}
-
-	cmd->t_data_sg = sgl;
-	cmd->t_data_nents = sgl_count;
-
-	if (sgl_bidi && sgl_bidi_count) {
-		cmd->t_bidi_data_sg = sgl_bidi;
-		cmd->t_bidi_data_nents = sgl_bidi_count;
-	}
-	cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
-	return 0;
-}
-EXPORT_SYMBOL(transport_generic_map_mem_to_cmd);
-
 void *transport_kmap_data_sg(struct se_cmd *cmd)
 {
 	struct scatterlist *sg = cmd->t_data_sg;
@@ -2266,10 +2003,8 @@ void *transport_kmap_data_sg(struct se_cmd *cmd)
 
 	/* >1 page. use vmap */
 	pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL);
-	if (!pages) {
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+	if (!pages)
 		return NULL;
-	}
 
 	/* convert sg[] to pages[] */
 	for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) {
@@ -2278,10 +2013,8 @@ void *transport_kmap_data_sg(struct se_cmd *cmd)
 
 	cmd->t_data_vmap = vmap(pages, cmd->t_data_nents,  VM_MAP, PAGE_KERNEL);
 	kfree(pages);
-	if (!cmd->t_data_vmap) {
-		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+	if (!cmd->t_data_vmap)
 		return NULL;
-	}
 
 	return cmd->t_data_vmap + cmd->t_data_sg[0].offset;
 }
@@ -2347,7 +2080,8 @@ out:
  * might not have the payload yet, so notify the fabric via a call to
  * ->write_pending instead. Otherwise place it on the execution queue.
  */
-int transport_generic_new_cmd(struct se_cmd *cmd)
+sense_reason_t
+transport_generic_new_cmd(struct se_cmd *cmd)
 {
 	int ret = 0;
 
@@ -2360,7 +2094,7 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
 	    cmd->data_length) {
 		ret = transport_generic_get_mem(cmd);
 		if (ret < 0)
-			goto out_fail;
+			return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	}
 
 	atomic_inc(&cmd->t_fe_count);
@@ -2386,14 +2120,11 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
 	if (ret == -EAGAIN || ret == -ENOMEM)
 		goto queue_full;
 
-	if (ret < 0)
-		return ret;
-	return 1;
+	/* fabric drivers should only return -EAGAIN or -ENOMEM as error */
+	WARN_ON(ret);
+
+	return (!ret) ? 0 : TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-out_fail:
-	cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-	cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-	return -EINVAL;
 queue_full:
 	pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd);
 	cmd->t_state = TRANSPORT_COMPLETE_QF_WP;
@@ -2837,21 +2568,9 @@ static int transport_get_sense_codes(
 	return 0;
 }
 
-static int transport_set_sense_codes(
-	struct se_cmd *cmd,
-	u8 asc,
-	u8 ascq)
-{
-	cmd->scsi_asc = asc;
-	cmd->scsi_ascq = ascq;
-
-	return 0;
-}
-
-int transport_send_check_condition_and_sense(
-	struct se_cmd *cmd,
-	u8 reason,
-	int from_transport)
+int
+transport_send_check_condition_and_sense(struct se_cmd *cmd,
+		sense_reason_t reason, int from_transport)
 {
 	unsigned char *buffer = cmd->sense_buffer;
 	unsigned long flags;
@@ -3042,23 +2761,19 @@ EXPORT_SYMBOL(transport_send_check_condition_and_sense);
 
 int transport_check_aborted_status(struct se_cmd *cmd, int send_status)
 {
-	int ret = 0;
+	if (!(cmd->transport_state & CMD_T_ABORTED))
+		return 0;
 
-	if (cmd->transport_state & CMD_T_ABORTED) {
-		if (!send_status ||
-		     (cmd->se_cmd_flags & SCF_SENT_DELAYED_TAS))
-			return 1;
+	if (!send_status || (cmd->se_cmd_flags & SCF_SENT_DELAYED_TAS))
+		return 1;
 
-		pr_debug("Sending delayed SAM_STAT_TASK_ABORTED"
-			" status for CDB: 0x%02x ITT: 0x%08x\n",
-			cmd->t_task_cdb[0],
-			cmd->se_tfo->get_task_tag(cmd));
+	pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB: 0x%02x ITT: 0x%08x\n",
+		 cmd->t_task_cdb[0], cmd->se_tfo->get_task_tag(cmd));
 
-		cmd->se_cmd_flags |= SCF_SENT_DELAYED_TAS;
-		cmd->se_tfo->queue_status(cmd);
-		ret = 1;
-	}
-	return ret;
+	cmd->se_cmd_flags |= SCF_SENT_DELAYED_TAS;
+	cmd->se_tfo->queue_status(cmd);
+
+	return 1;
 }
 EXPORT_SYMBOL(transport_check_aborted_status);
 
diff --git a/drivers/target/target_core_ua.c b/drivers/target/target_core_ua.c
index 6666a0c..bf0e390 100644
--- a/drivers/target/target_core_ua.c
+++ b/drivers/target/target_core_ua.c
@@ -3,8 +3,7 @@
  *
  * This file contains logic for SPC-3 Unit Attention emulation
  *
- * Copyright (c) 2009,2010 Rising Tide Systems
- * Copyright (c) 2009,2010 Linux-iSCSI.org
+ * (c) Copyright 2009-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@kernel.org>
  *
@@ -38,9 +37,8 @@
 #include "target_core_pr.h"
 #include "target_core_ua.h"
 
-int core_scsi3_ua_check(
-	struct se_cmd *cmd,
-	unsigned char *cdb)
+sense_reason_t
+target_scsi3_ua_check(struct se_cmd *cmd)
 {
 	struct se_dev_entry *deve;
 	struct se_session *sess = cmd->se_sess;
@@ -71,16 +69,14 @@ int core_scsi3_ua_check(
 	 *    was received, then the device server shall process the command
 	 *    and either:
 	 */
-	switch (cdb[0]) {
+	switch (cmd->t_task_cdb[0]) {
 	case INQUIRY:
 	case REPORT_LUNS:
 	case REQUEST_SENSE:
 		return 0;
 	default:
-		return -EINVAL;
+		return TCM_CHECK_CONDITION_UNIT_ATTENTION;
 	}
-
-	return -EINVAL;
 }
 
 int core_scsi3_ua_allocate(
@@ -237,7 +233,7 @@ void core_scsi3_ua_for_check_condition(
 		 * highest priority UNIT_ATTENTION and ASC/ASCQ without
 		 * clearing it.
 		 */
-		if (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl != 0) {
+		if (dev->dev_attrib.emulate_ua_intlck_ctrl != 0) {
 			*asc = ua->ua_asc;
 			*ascq = ua->ua_ascq;
 			break;
@@ -265,8 +261,8 @@ void core_scsi3_ua_for_check_condition(
 		" INTLCK_CTRL: %d, mapped LUN: %u, got CDB: 0x%02x"
 		" reported ASC: 0x%02x, ASCQ: 0x%02x\n",
 		nacl->se_tpg->se_tpg_tfo->get_fabric_name(),
-		(dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl != 0) ? "Reporting" :
-		"Releasing", dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl,
+		(dev->dev_attrib.emulate_ua_intlck_ctrl != 0) ? "Reporting" :
+		"Releasing", dev->dev_attrib.emulate_ua_intlck_ctrl,
 		cmd->orig_fe_lun, cmd->t_task_cdb[0], *asc, *ascq);
 }
 
diff --git a/drivers/target/target_core_ua.h b/drivers/target/target_core_ua.h
index 6e6b034..0204952 100644
--- a/drivers/target/target_core_ua.h
+++ b/drivers/target/target_core_ua.h
@@ -26,7 +26,7 @@
 
 extern struct kmem_cache *se_ua_cache;
 
-extern int core_scsi3_ua_check(struct se_cmd *, unsigned char *);
+extern sense_reason_t target_scsi3_ua_check(struct se_cmd *);
 extern int core_scsi3_ua_allocate(struct se_node_acl *, u32, u8, u8);
 extern void core_scsi3_ua_release_all(struct se_dev_entry *);
 extern void core_scsi3_ua_for_check_condition(struct se_cmd *, u8 *, u8 *);
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index e1cb6bd..8636fae 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -13,15 +13,62 @@ menuconfig THERMAL
 	  All platforms with ACPI thermal support can use this driver.
 	  If you want this support, you should say Y or M here.
 
+if THERMAL
+
 config THERMAL_HWMON
 	bool
-	depends on THERMAL
 	depends on HWMON=y || HWMON=THERMAL
 	default y
 
+choice
+	prompt "Default Thermal governor"
+	default THERMAL_DEFAULT_GOV_STEP_WISE
+	help
+	  This option sets which thermal governor shall be loaded at
+	  startup. If in doubt, select 'step_wise'.
+
+config THERMAL_DEFAULT_GOV_STEP_WISE
+	bool "step_wise"
+	select STEP_WISE
+	help
+	  Use the step_wise governor as default. This throttles the
+	  devices one step at a time.
+
+config THERMAL_DEFAULT_GOV_FAIR_SHARE
+	bool "fair_share"
+	select FAIR_SHARE
+	help
+	  Use the fair_share governor as default. This throttles the
+	  devices based on their 'contribution' to a zone. The
+	  contribution should be provided through platform data.
+
+config THERMAL_DEFAULT_GOV_USER_SPACE
+	bool "user_space"
+	select USER_SPACE
+	help
+	  Select this if you want to let the user space manage the
+	  lpatform thermals.
+
+endchoice
+
+config FAIR_SHARE
+	bool "Fair-share thermal governor"
+	help
+	  Enable this to manage platform thermals using fair-share governor.
+
+config STEP_WISE
+	bool "Step_wise thermal governor"
+	help
+	  Enable this to manage platform thermals using a simple linear
+
+config USER_SPACE
+	bool "User_space thermal governor"
+	help
+	  Enable this to let the user space manage the platform thermals.
+
 config CPU_THERMAL
-	bool "generic cpu cooling support"
-	depends on THERMAL && CPU_FREQ
+	tristate "generic cpu cooling support"
+	depends on CPU_FREQ
 	select CPU_FREQ_TABLE
 	help
 	  This implements the generic cpu cooling mechanism through frequency
@@ -33,7 +80,6 @@ config CPU_THERMAL
 
 config SPEAR_THERMAL
 	bool "SPEAr thermal sensor driver"
-	depends on THERMAL
 	depends on PLAT_SPEAR
 	depends on OF
 	help
@@ -42,7 +88,6 @@ config SPEAR_THERMAL
 
 config RCAR_THERMAL
 	tristate "Renesas R-Car thermal driver"
-	depends on THERMAL
 	depends on ARCH_SHMOBILE
 	help
 	  Enable this to plug the R-Car thermal sensor driver into the Linux
@@ -50,8 +95,31 @@ config RCAR_THERMAL
 
 config EXYNOS_THERMAL
 	tristate "Temperature sensor on Samsung EXYNOS"
-	depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5) && THERMAL
-	select CPU_FREQ_TABLE
+	depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5)
+	depends on CPU_THERMAL
 	help
 	  If you say yes here you get support for TMU (Thermal Managment
 	  Unit) on SAMSUNG EXYNOS series of SoC.
+
+config DB8500_THERMAL
+	bool "DB8500 thermal management"
+	depends on ARCH_U8500
+	default y
+	help
+	  Adds DB8500 thermal management implementation according to the thermal
+	  management framework. A thermal zone with several trip points will be
+	  created. Cooling devices can be bound to the trip points to cool this
+	  thermal zone if trip points reached.
+
+config DB8500_CPUFREQ_COOLING
+	tristate "DB8500 cpufreq cooling"
+	depends on ARCH_U8500
+	depends on CPU_THERMAL
+	default y
+	help
+	  Adds DB8500 cpufreq cooling devices, and these cooling devices can be
+	  bound to thermal zone trip points. When a trip point reached, the
+	  bound cpufreq cooling device turns active to set CPU frequency low to
+	  cool down the CPU.
+
+endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 885550d..d8da683 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -3,7 +3,18 @@
 #
 
 obj-$(CONFIG_THERMAL)		+= thermal_sys.o
-obj-$(CONFIG_CPU_THERMAL)		+= cpu_cooling.o
-obj-$(CONFIG_SPEAR_THERMAL)		+= spear_thermal.o
+
+# governors
+obj-$(CONFIG_FAIR_SHARE)	+= fair_share.o
+obj-$(CONFIG_STEP_WISE)		+= step_wise.o
+obj-$(CONFIG_USER_SPACE)	+= user_space.o
+
+# cpufreq cooling
+obj-$(CONFIG_CPU_THERMAL)	+= cpu_cooling.o
+
+# platform thermal drivers
+obj-$(CONFIG_SPEAR_THERMAL)	+= spear_thermal.o
 obj-$(CONFIG_RCAR_THERMAL)	+= rcar_thermal.o
-obj-$(CONFIG_EXYNOS_THERMAL)		+= exynos_thermal.o
+obj-$(CONFIG_EXYNOS_THERMAL)	+= exynos_thermal.o
+obj-$(CONFIG_DB8500_THERMAL)	+= db8500_thermal.o
+obj-$(CONFIG_DB8500_CPUFREQ_COOLING)	+= db8500_cpufreq_cooling.o
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index cc1c930..836828e 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -58,12 +58,13 @@ struct cpufreq_cooling_device {
 };
 static LIST_HEAD(cooling_cpufreq_list);
 static DEFINE_IDR(cpufreq_idr);
+static DEFINE_MUTEX(cooling_cpufreq_lock);
 
-static struct mutex cooling_cpufreq_lock;
+static unsigned int cpufreq_dev_count;
 
 /* notify_table passes value to the CPUFREQ_ADJUST callback function. */
 #define NOTIFY_INVALID NULL
-struct cpufreq_cooling_device *notify_device;
+static struct cpufreq_cooling_device *notify_device;
 
 /**
  * get_idr - function to get a unique id.
@@ -240,42 +241,32 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
 static int cpufreq_get_max_state(struct thermal_cooling_device *cdev,
 				 unsigned long *state)
 {
-	int ret = -EINVAL, i = 0;
-	struct cpufreq_cooling_device *cpufreq_device;
-	struct cpumask *maskPtr;
+	struct cpufreq_cooling_device *cpufreq_device = cdev->devdata;
+	struct cpumask *maskPtr = &cpufreq_device->allowed_cpus;
 	unsigned int cpu;
 	struct cpufreq_frequency_table *table;
+	unsigned long count = 0;
+	int i = 0;
 
-	mutex_lock(&cooling_cpufreq_lock);
-	list_for_each_entry(cpufreq_device, &cooling_cpufreq_list, node) {
-		if (cpufreq_device && cpufreq_device->cool_dev == cdev)
-			break;
-	}
-	if (cpufreq_device == NULL)
-		goto return_get_max_state;
-
-	maskPtr = &cpufreq_device->allowed_cpus;
 	cpu = cpumask_any(maskPtr);
 	table = cpufreq_frequency_get_table(cpu);
 	if (!table) {
 		*state = 0;
-		ret = 0;
-		goto return_get_max_state;
+		return 0;
 	}
 
-	while (table[i].frequency != CPUFREQ_TABLE_END) {
+	for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
 		if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
 			continue;
-		i++;
+		count++;
 	}
-	if (i > 0) {
-		*state = --i;
-		ret = 0;
+
+	if (count > 0) {
+		*state = --count;
+		return 0;
 	}
 
-return_get_max_state:
-	mutex_unlock(&cooling_cpufreq_lock);
-	return ret;
+	return -EINVAL;
 }
 
 /**
@@ -286,20 +277,10 @@ return_get_max_state:
 static int cpufreq_get_cur_state(struct thermal_cooling_device *cdev,
 				 unsigned long *state)
 {
-	int ret = -EINVAL;
-	struct cpufreq_cooling_device *cpufreq_device;
+	struct cpufreq_cooling_device *cpufreq_device = cdev->devdata;
 
-	mutex_lock(&cooling_cpufreq_lock);
-	list_for_each_entry(cpufreq_device, &cooling_cpufreq_list, node) {
-		if (cpufreq_device && cpufreq_device->cool_dev == cdev) {
-			*state = cpufreq_device->cpufreq_state;
-			ret = 0;
-			break;
-		}
-	}
-	mutex_unlock(&cooling_cpufreq_lock);
-
-	return ret;
+	*state = cpufreq_device->cpufreq_state;
+	return 0;
 }
 
 /**
@@ -310,22 +291,9 @@ static int cpufreq_get_cur_state(struct thermal_cooling_device *cdev,
 static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
 				 unsigned long state)
 {
-	int ret = -EINVAL;
-	struct cpufreq_cooling_device *cpufreq_device;
+	struct cpufreq_cooling_device *cpufreq_device = cdev->devdata;
 
-	mutex_lock(&cooling_cpufreq_lock);
-	list_for_each_entry(cpufreq_device, &cooling_cpufreq_list, node) {
-		if (cpufreq_device && cpufreq_device->cool_dev == cdev) {
-			ret = 0;
-			break;
-		}
-	}
-	if (!ret)
-		ret = cpufreq_apply_cooling(cpufreq_device, state);
-
-	mutex_unlock(&cooling_cpufreq_lock);
-
-	return ret;
+	return cpufreq_apply_cooling(cpufreq_device, state);
 }
 
 /* Bind cpufreq callbacks to thermal cooling device ops */
@@ -345,18 +313,15 @@ static struct notifier_block thermal_cpufreq_notifier_block = {
  * @clip_cpus: cpumask of cpus where the frequency constraints will happen.
  */
 struct thermal_cooling_device *cpufreq_cooling_register(
-	struct cpumask *clip_cpus)
+	const struct cpumask *clip_cpus)
 {
 	struct thermal_cooling_device *cool_dev;
 	struct cpufreq_cooling_device *cpufreq_dev = NULL;
-	unsigned int cpufreq_dev_count = 0, min = 0, max = 0;
+	unsigned int min = 0, max = 0;
 	char dev_name[THERMAL_NAME_LENGTH];
 	int ret = 0, i;
 	struct cpufreq_policy policy;
 
-	list_for_each_entry(cpufreq_dev, &cooling_cpufreq_list, node)
-		cpufreq_dev_count++;
-
 	/*Verify that all the clip cpus have same freq_min, freq_max limit*/
 	for_each_cpu(i, clip_cpus) {
 		/*continue if cpufreq policy not found and not return error*/
@@ -369,7 +334,7 @@ struct thermal_cooling_device *cpufreq_cooling_register(
 			if (min != policy.cpuinfo.min_freq ||
 				max != policy.cpuinfo.max_freq)
 				return ERR_PTR(-EINVAL);
-}
+		}
 	}
 	cpufreq_dev = kzalloc(sizeof(struct cpufreq_cooling_device),
 			GFP_KERNEL);
@@ -378,9 +343,6 @@ struct thermal_cooling_device *cpufreq_cooling_register(
 
 	cpumask_copy(&cpufreq_dev->allowed_cpus, clip_cpus);
 
-	if (cpufreq_dev_count == 0)
-		mutex_init(&cooling_cpufreq_lock);
-
 	ret = get_idr(&cpufreq_idr, &cpufreq_dev->id);
 	if (ret) {
 		kfree(cpufreq_dev);
@@ -399,12 +361,12 @@ struct thermal_cooling_device *cpufreq_cooling_register(
 	cpufreq_dev->cool_dev = cool_dev;
 	cpufreq_dev->cpufreq_state = 0;
 	mutex_lock(&cooling_cpufreq_lock);
-	list_add_tail(&cpufreq_dev->node, &cooling_cpufreq_list);
 
 	/* Register the notifier for first cpufreq cooling device */
 	if (cpufreq_dev_count == 0)
 		cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
 						CPUFREQ_POLICY_NOTIFIER);
+	cpufreq_dev_count++;
 
 	mutex_unlock(&cooling_cpufreq_lock);
 	return cool_dev;
@@ -417,33 +379,20 @@ EXPORT_SYMBOL(cpufreq_cooling_register);
  */
 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 {
-	struct cpufreq_cooling_device *cpufreq_dev = NULL;
-	unsigned int cpufreq_dev_count = 0;
+	struct cpufreq_cooling_device *cpufreq_dev = cdev->devdata;
 
 	mutex_lock(&cooling_cpufreq_lock);
-	list_for_each_entry(cpufreq_dev, &cooling_cpufreq_list, node) {
-		if (cpufreq_dev && cpufreq_dev->cool_dev == cdev)
-			break;
-		cpufreq_dev_count++;
-	}
-
-	if (!cpufreq_dev || cpufreq_dev->cool_dev != cdev) {
-		mutex_unlock(&cooling_cpufreq_lock);
-		return;
-	}
-
-	list_del(&cpufreq_dev->node);
+	cpufreq_dev_count--;
 
 	/* Unregister the notifier for the last cpufreq cooling device */
-	if (cpufreq_dev_count == 1) {
+	if (cpufreq_dev_count == 0) {
 		cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block,
 					CPUFREQ_POLICY_NOTIFIER);
 	}
 	mutex_unlock(&cooling_cpufreq_lock);
+
 	thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
 	release_idr(&cpufreq_idr, cpufreq_dev->id);
-	if (cpufreq_dev_count == 1)
-		mutex_destroy(&cooling_cpufreq_lock);
 	kfree(cpufreq_dev);
 }
 EXPORT_SYMBOL(cpufreq_cooling_unregister);
diff --git a/drivers/thermal/db8500_cpufreq_cooling.c b/drivers/thermal/db8500_cpufreq_cooling.c
new file mode 100644
index 0000000..4cf8e72
--- /dev/null
+++ b/drivers/thermal/db8500_cpufreq_cooling.c
@@ -0,0 +1,108 @@
+/*
+ * db8500_cpufreq_cooling.c - DB8500 cpufreq works as cooling device.
+ *
+ * Copyright (C) 2012 ST-Ericsson
+ * Copyright (C) 2012 Linaro Ltd.
+ *
+ * Author: Hongbo Zhang <hongbo.zhang@linaro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/cpu_cooling.h>
+#include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+static int db8500_cpufreq_cooling_probe(struct platform_device *pdev)
+{
+	struct thermal_cooling_device *cdev;
+	struct cpumask mask_val;
+
+	/* make sure cpufreq driver has been initialized */
+	if (!cpufreq_frequency_get_table(0))
+		return -EPROBE_DEFER;
+
+	cpumask_set_cpu(0, &mask_val);
+	cdev = cpufreq_cooling_register(&mask_val);
+
+	if (IS_ERR_OR_NULL(cdev)) {
+		dev_err(&pdev->dev, "Failed to register cooling device\n");
+		return PTR_ERR(cdev);
+	}
+
+	platform_set_drvdata(pdev, cdev);
+
+	dev_info(&pdev->dev, "Cooling device registered: %s\n",	cdev->type);
+
+	return 0;
+}
+
+static int db8500_cpufreq_cooling_remove(struct platform_device *pdev)
+{
+	struct thermal_cooling_device *cdev = platform_get_drvdata(pdev);
+
+	cpufreq_cooling_unregister(cdev);
+
+	return 0;
+}
+
+static int db8500_cpufreq_cooling_suspend(struct platform_device *pdev,
+		pm_message_t state)
+{
+	return -ENOSYS;
+}
+
+static int db8500_cpufreq_cooling_resume(struct platform_device *pdev)
+{
+	return -ENOSYS;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id db8500_cpufreq_cooling_match[] = {
+	{ .compatible = "stericsson,db8500-cpufreq-cooling" },
+	{},
+};
+#else
+#define db8500_cpufreq_cooling_match NULL
+#endif
+
+static struct platform_driver db8500_cpufreq_cooling_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "db8500-cpufreq-cooling",
+		.of_match_table = db8500_cpufreq_cooling_match,
+	},
+	.probe = db8500_cpufreq_cooling_probe,
+	.suspend = db8500_cpufreq_cooling_suspend,
+	.resume = db8500_cpufreq_cooling_resume,
+	.remove = db8500_cpufreq_cooling_remove,
+};
+
+static int __init db8500_cpufreq_cooling_init(void)
+{
+	return platform_driver_register(&db8500_cpufreq_cooling_driver);
+}
+
+static void __exit db8500_cpufreq_cooling_exit(void)
+{
+	platform_driver_unregister(&db8500_cpufreq_cooling_driver);
+}
+
+/* Should be later than db8500_cpufreq_register */
+late_initcall(db8500_cpufreq_cooling_init);
+module_exit(db8500_cpufreq_cooling_exit);
+
+MODULE_AUTHOR("Hongbo Zhang <hongbo.zhang@stericsson.com>");
+MODULE_DESCRIPTION("DB8500 cpufreq cooling driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c
new file mode 100644
index 0000000..ec71ade
--- /dev/null
+++ b/drivers/thermal/db8500_thermal.c
@@ -0,0 +1,531 @@
+/*
+ * db8500_thermal.c - DB8500 Thermal Management Implementation
+ *
+ * Copyright (C) 2012 ST-Ericsson
+ * Copyright (C) 2012 Linaro Ltd.
+ *
+ * Author: Hongbo Zhang <hongbo.zhang@linaro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/cpu_cooling.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_data/db8500_thermal.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/thermal.h>
+
+#define PRCMU_DEFAULT_MEASURE_TIME	0xFFF
+#define PRCMU_DEFAULT_LOW_TEMP		0
+
+struct db8500_thermal_zone {
+	struct thermal_zone_device *therm_dev;
+	struct mutex th_lock;
+	struct work_struct therm_work;
+	struct db8500_thsens_platform_data *trip_tab;
+	enum thermal_device_mode mode;
+	enum thermal_trend trend;
+	unsigned long cur_temp_pseudo;
+	unsigned int cur_index;
+};
+
+/* Local function to check if thermal zone matches cooling devices */
+static int db8500_thermal_match_cdev(struct thermal_cooling_device *cdev,
+		struct db8500_trip_point *trip_point)
+{
+	int i;
+
+	if (!strlen(cdev->type))
+		return -EINVAL;
+
+	for (i = 0; i < COOLING_DEV_MAX; i++) {
+		if (!strcmp(trip_point->cdev_name[i], cdev->type))
+			return 0;
+	}
+
+	return -ENODEV;
+}
+
+/* Callback to bind cooling device to thermal zone */
+static int db8500_cdev_bind(struct thermal_zone_device *thermal,
+		struct thermal_cooling_device *cdev)
+{
+	struct db8500_thermal_zone *pzone = thermal->devdata;
+	struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
+	unsigned long max_state, upper, lower;
+	int i, ret = -EINVAL;
+
+	cdev->ops->get_max_state(cdev, &max_state);
+
+	for (i = 0; i < ptrips->num_trips; i++) {
+		if (db8500_thermal_match_cdev(cdev, &ptrips->trip_points[i]))
+			continue;
+
+		upper = lower = i > max_state ? max_state : i;
+
+		ret = thermal_zone_bind_cooling_device(thermal, i, cdev,
+			upper, lower);
+
+		dev_info(&cdev->device, "%s bind to %d: %d-%s\n", cdev->type,
+			i, ret, ret ? "fail" : "succeed");
+	}
+
+	return ret;
+}
+
+/* Callback to unbind cooling device from thermal zone */
+static int db8500_cdev_unbind(struct thermal_zone_device *thermal,
+		struct thermal_cooling_device *cdev)
+{
+	struct db8500_thermal_zone *pzone = thermal->devdata;
+	struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
+	int i, ret = -EINVAL;
+
+	for (i = 0; i < ptrips->num_trips; i++) {
+		if (db8500_thermal_match_cdev(cdev, &ptrips->trip_points[i]))
+			continue;
+
+		ret = thermal_zone_unbind_cooling_device(thermal, i, cdev);
+
+		dev_info(&cdev->device, "%s unbind from %d: %s\n", cdev->type,
+			i, ret ? "fail" : "succeed");
+	}
+
+	return ret;
+}
+
+/* Callback to get current temperature */
+static int db8500_sys_get_temp(struct thermal_zone_device *thermal,
+		unsigned long *temp)
+{
+	struct db8500_thermal_zone *pzone = thermal->devdata;
+
+	/*
+	 * TODO: There is no PRCMU interface to get temperature data currently,
+	 * so a pseudo temperature is returned , it works for thermal framework
+	 * and this will be fixed when the PRCMU interface is available.
+	 */
+	*temp = pzone->cur_temp_pseudo;
+
+	return 0;
+}
+
+/* Callback to get temperature changing trend */
+static int db8500_sys_get_trend(struct thermal_zone_device *thermal,
+		int trip, enum thermal_trend *trend)
+{
+	struct db8500_thermal_zone *pzone = thermal->devdata;
+
+	*trend = pzone->trend;
+
+	return 0;
+}
+
+/* Callback to get thermal zone mode */
+static int db8500_sys_get_mode(struct thermal_zone_device *thermal,
+		enum thermal_device_mode *mode)
+{
+	struct db8500_thermal_zone *pzone = thermal->devdata;
+
+	mutex_lock(&pzone->th_lock);
+	*mode = pzone->mode;
+	mutex_unlock(&pzone->th_lock);
+
+	return 0;
+}
+
+/* Callback to set thermal zone mode */
+static int db8500_sys_set_mode(struct thermal_zone_device *thermal,
+		enum thermal_device_mode mode)
+{
+	struct db8500_thermal_zone *pzone = thermal->devdata;
+
+	mutex_lock(&pzone->th_lock);
+
+	pzone->mode = mode;
+	if (mode == THERMAL_DEVICE_ENABLED)
+		schedule_work(&pzone->therm_work);
+
+	mutex_unlock(&pzone->th_lock);
+
+	return 0;
+}
+
+/* Callback to get trip point type */
+static int db8500_sys_get_trip_type(struct thermal_zone_device *thermal,
+		int trip, enum thermal_trip_type *type)
+{
+	struct db8500_thermal_zone *pzone = thermal->devdata;
+	struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
+
+	if (trip >= ptrips->num_trips)
+		return -EINVAL;
+
+	*type = ptrips->trip_points[trip].type;
+
+	return 0;
+}
+
+/* Callback to get trip point temperature */
+static int db8500_sys_get_trip_temp(struct thermal_zone_device *thermal,
+		int trip, unsigned long *temp)
+{
+	struct db8500_thermal_zone *pzone = thermal->devdata;
+	struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
+
+	if (trip >= ptrips->num_trips)
+		return -EINVAL;
+
+	*temp = ptrips->trip_points[trip].temp;
+
+	return 0;
+}
+
+/* Callback to get critical trip point temperature */
+static int db8500_sys_get_crit_temp(struct thermal_zone_device *thermal,
+		unsigned long *temp)
+{
+	struct db8500_thermal_zone *pzone = thermal->devdata;
+	struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
+	int i;
+
+	for (i = ptrips->num_trips - 1; i > 0; i--) {
+		if (ptrips->trip_points[i].type == THERMAL_TRIP_CRITICAL) {
+			*temp = ptrips->trip_points[i].temp;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static struct thermal_zone_device_ops thdev_ops = {
+	.bind = db8500_cdev_bind,
+	.unbind = db8500_cdev_unbind,
+	.get_temp = db8500_sys_get_temp,
+	.get_trend = db8500_sys_get_trend,
+	.get_mode = db8500_sys_get_mode,
+	.set_mode = db8500_sys_set_mode,
+	.get_trip_type = db8500_sys_get_trip_type,
+	.get_trip_temp = db8500_sys_get_trip_temp,
+	.get_crit_temp = db8500_sys_get_crit_temp,
+};
+
+static void db8500_thermal_update_config(struct db8500_thermal_zone *pzone,
+		unsigned int idx, enum thermal_trend trend,
+		unsigned long next_low, unsigned long next_high)
+{
+	prcmu_stop_temp_sense();
+
+	pzone->cur_index = idx;
+	pzone->cur_temp_pseudo = (next_low + next_high)/2;
+	pzone->trend = trend;
+
+	prcmu_config_hotmon((u8)(next_low/1000), (u8)(next_high/1000));
+	prcmu_start_temp_sense(PRCMU_DEFAULT_MEASURE_TIME);
+}
+
+static irqreturn_t prcmu_low_irq_handler(int irq, void *irq_data)
+{
+	struct db8500_thermal_zone *pzone = irq_data;
+	struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
+	unsigned int idx = pzone->cur_index;
+	unsigned long next_low, next_high;
+
+	if (unlikely(idx == 0))
+		/* Meaningless for thermal management, ignoring it */
+		return IRQ_HANDLED;
+
+	if (idx == 1) {
+		next_high = ptrips->trip_points[0].temp;
+		next_low = PRCMU_DEFAULT_LOW_TEMP;
+	} else {
+		next_high = ptrips->trip_points[idx-1].temp;
+		next_low = ptrips->trip_points[idx-2].temp;
+	}
+	idx -= 1;
+
+	db8500_thermal_update_config(pzone, idx, THERMAL_TREND_DROPPING,
+		next_low, next_high);
+
+	dev_dbg(&pzone->therm_dev->device,
+		"PRCMU set max %ld, min %ld\n", next_high, next_low);
+
+	schedule_work(&pzone->therm_work);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t prcmu_high_irq_handler(int irq, void *irq_data)
+{
+	struct db8500_thermal_zone *pzone = irq_data;
+	struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
+	unsigned int idx = pzone->cur_index;
+	unsigned long next_low, next_high;
+
+	if (idx < ptrips->num_trips - 1) {
+		next_high = ptrips->trip_points[idx+1].temp;
+		next_low = ptrips->trip_points[idx].temp;
+		idx += 1;
+
+		db8500_thermal_update_config(pzone, idx, THERMAL_TREND_RAISING,
+			next_low, next_high);
+
+		dev_dbg(&pzone->therm_dev->device,
+		"PRCMU set max %ld, min %ld\n", next_high, next_low);
+	} else if (idx == ptrips->num_trips - 1)
+		pzone->cur_temp_pseudo = ptrips->trip_points[idx].temp + 1;
+
+	schedule_work(&pzone->therm_work);
+
+	return IRQ_HANDLED;
+}
+
+static void db8500_thermal_work(struct work_struct *work)
+{
+	enum thermal_device_mode cur_mode;
+	struct db8500_thermal_zone *pzone;
+
+	pzone = container_of(work, struct db8500_thermal_zone, therm_work);
+
+	mutex_lock(&pzone->th_lock);
+	cur_mode = pzone->mode;
+	mutex_unlock(&pzone->th_lock);
+
+	if (cur_mode == THERMAL_DEVICE_DISABLED)
+		return;
+
+	thermal_zone_device_update(pzone->therm_dev);
+	dev_dbg(&pzone->therm_dev->device, "thermal work finished.\n");
+}
+
+#ifdef CONFIG_OF
+static struct db8500_thsens_platform_data*
+		db8500_thermal_parse_dt(struct platform_device *pdev)
+{
+	struct db8500_thsens_platform_data *ptrips;
+	struct device_node *np = pdev->dev.of_node;
+	char prop_name[32];
+	const char *tmp_str;
+	u32 tmp_data;
+	int i, j;
+
+	ptrips = devm_kzalloc(&pdev->dev, sizeof(*ptrips), GFP_KERNEL);
+	if (!ptrips)
+		return NULL;
+
+	if (of_property_read_u32(np, "num-trips", &tmp_data))
+		goto err_parse_dt;
+
+	if (tmp_data > THERMAL_MAX_TRIPS)
+		goto err_parse_dt;
+
+	ptrips->num_trips = tmp_data;
+
+	for (i = 0; i < ptrips->num_trips; i++) {
+		sprintf(prop_name, "trip%d-temp", i);
+		if (of_property_read_u32(np, prop_name, &tmp_data))
+			goto err_parse_dt;
+
+		ptrips->trip_points[i].temp = tmp_data;
+
+		sprintf(prop_name, "trip%d-type", i);
+		if (of_property_read_string(np, prop_name, &tmp_str))
+			goto err_parse_dt;
+
+		if (!strcmp(tmp_str, "active"))
+			ptrips->trip_points[i].type = THERMAL_TRIP_ACTIVE;
+		else if (!strcmp(tmp_str, "passive"))
+			ptrips->trip_points[i].type = THERMAL_TRIP_PASSIVE;
+		else if (!strcmp(tmp_str, "hot"))
+			ptrips->trip_points[i].type = THERMAL_TRIP_HOT;
+		else if (!strcmp(tmp_str, "critical"))
+			ptrips->trip_points[i].type = THERMAL_TRIP_CRITICAL;
+		else
+			goto err_parse_dt;
+
+		sprintf(prop_name, "trip%d-cdev-num", i);
+		if (of_property_read_u32(np, prop_name, &tmp_data))
+			goto err_parse_dt;
+
+		if (tmp_data > COOLING_DEV_MAX)
+			goto err_parse_dt;
+
+		for (j = 0; j < tmp_data; j++) {
+			sprintf(prop_name, "trip%d-cdev-name%d", i, j);
+			if (of_property_read_string(np, prop_name, &tmp_str))
+				goto err_parse_dt;
+
+			if (strlen(tmp_str) >= THERMAL_NAME_LENGTH)
+				goto err_parse_dt;
+
+			strcpy(ptrips->trip_points[i].cdev_name[j], tmp_str);
+		}
+	}
+	return ptrips;
+
+err_parse_dt:
+	dev_err(&pdev->dev, "Parsing device tree data error.\n");
+	return NULL;
+}
+#else
+static inline struct db8500_thsens_platform_data*
+		db8500_thermal_parse_dt(struct platform_device *pdev)
+{
+	return NULL;
+}
+#endif
+
+static int db8500_thermal_probe(struct platform_device *pdev)
+{
+	struct db8500_thermal_zone *pzone = NULL;
+	struct db8500_thsens_platform_data *ptrips = NULL;
+	struct device_node *np = pdev->dev.of_node;
+	int low_irq, high_irq, ret = 0;
+	unsigned long dft_low, dft_high;
+
+	if (np)
+		ptrips = db8500_thermal_parse_dt(pdev);
+	else
+		ptrips = dev_get_platdata(&pdev->dev);
+
+	if (!ptrips)
+		return -EINVAL;
+
+	pzone = devm_kzalloc(&pdev->dev, sizeof(*pzone), GFP_KERNEL);
+	if (!pzone)
+		return -ENOMEM;
+
+	mutex_init(&pzone->th_lock);
+	mutex_lock(&pzone->th_lock);
+
+	pzone->mode = THERMAL_DEVICE_DISABLED;
+	pzone->trip_tab = ptrips;
+
+	INIT_WORK(&pzone->therm_work, db8500_thermal_work);
+
+	low_irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_LOW");
+	if (low_irq < 0) {
+		dev_err(&pdev->dev, "Get IRQ_HOTMON_LOW failed.\n");
+		return low_irq;
+	}
+
+	ret = devm_request_threaded_irq(&pdev->dev, low_irq, NULL,
+		prcmu_low_irq_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT,
+		"dbx500_temp_low", pzone);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to allocate temp low irq.\n");
+		return ret;
+	}
+
+	high_irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_HIGH");
+	if (high_irq < 0) {
+		dev_err(&pdev->dev, "Get IRQ_HOTMON_HIGH failed.\n");
+		return high_irq;
+	}
+
+	ret = devm_request_threaded_irq(&pdev->dev, high_irq, NULL,
+		prcmu_high_irq_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT,
+		"dbx500_temp_high", pzone);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to allocate temp high irq.\n");
+		return ret;
+	}
+
+	pzone->therm_dev = thermal_zone_device_register("db8500_thermal_zone",
+		ptrips->num_trips, 0, pzone, &thdev_ops, NULL, 0, 0);
+
+	if (IS_ERR_OR_NULL(pzone->therm_dev)) {
+		dev_err(&pdev->dev, "Register thermal zone device failed.\n");
+		return PTR_ERR(pzone->therm_dev);
+	}
+	dev_info(&pdev->dev, "Thermal zone device registered.\n");
+
+	dft_low = PRCMU_DEFAULT_LOW_TEMP;
+	dft_high = ptrips->trip_points[0].temp;
+
+	db8500_thermal_update_config(pzone, 0, THERMAL_TREND_STABLE,
+		dft_low, dft_high);
+
+	platform_set_drvdata(pdev, pzone);
+	pzone->mode = THERMAL_DEVICE_ENABLED;
+	mutex_unlock(&pzone->th_lock);
+
+	return 0;
+}
+
+static int db8500_thermal_remove(struct platform_device *pdev)
+{
+	struct db8500_thermal_zone *pzone = platform_get_drvdata(pdev);
+
+	thermal_zone_device_unregister(pzone->therm_dev);
+	cancel_work_sync(&pzone->therm_work);
+	mutex_destroy(&pzone->th_lock);
+
+	return 0;
+}
+
+static int db8500_thermal_suspend(struct platform_device *pdev,
+		pm_message_t state)
+{
+	struct db8500_thermal_zone *pzone = platform_get_drvdata(pdev);
+
+	flush_work(&pzone->therm_work);
+	prcmu_stop_temp_sense();
+
+	return 0;
+}
+
+static int db8500_thermal_resume(struct platform_device *pdev)
+{
+	struct db8500_thermal_zone *pzone = platform_get_drvdata(pdev);
+	struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
+	unsigned long dft_low, dft_high;
+
+	dft_low = PRCMU_DEFAULT_LOW_TEMP;
+	dft_high = ptrips->trip_points[0].temp;
+
+	db8500_thermal_update_config(pzone, 0, THERMAL_TREND_STABLE,
+		dft_low, dft_high);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id db8500_thermal_match[] = {
+	{ .compatible = "stericsson,db8500-thermal" },
+	{},
+};
+#else
+#define db8500_thermal_match NULL
+#endif
+
+static struct platform_driver db8500_thermal_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "db8500-thermal",
+		.of_match_table = db8500_thermal_match,
+	},
+	.probe = db8500_thermal_probe,
+	.suspend = db8500_thermal_suspend,
+	.resume = db8500_thermal_resume,
+	.remove = db8500_thermal_remove,
+};
+
+module_platform_driver(db8500_thermal_driver);
+
+MODULE_AUTHOR("Hongbo Zhang <hongbo.zhang@stericsson.com>");
+MODULE_DESCRIPTION("DB8500 thermal driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c
index 6dd29e4..7772d16 100644
--- a/drivers/thermal/exynos_thermal.c
+++ b/drivers/thermal/exynos_thermal.c
@@ -451,7 +451,7 @@ static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
 	th_zone->cool_dev_size++;
 
 	th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
-			EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, 0,
+			EXYNOS_ZONE_COUNT, 0, NULL, &exynos_dev_ops, NULL, 0,
 			IDLE_INTERVAL);
 
 	if (IS_ERR(th_zone->therm_dev)) {
diff --git a/drivers/thermal/fair_share.c b/drivers/thermal/fair_share.c
new file mode 100644
index 0000000..792479f
--- /dev/null
+++ b/drivers/thermal/fair_share.c
@@ -0,0 +1,133 @@
+/*
+ *  fair_share.c - A simple weight based Thermal governor
+ *
+ *  Copyright (C) 2012 Intel Corp
+ *  Copyright (C) 2012 Durgadoss R <durgadoss.r@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.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/thermal.h>
+
+#include "thermal_core.h"
+
+/**
+ * get_trip_level: - obtains the current trip level for a zone
+ * @tz:		thermal zone device
+ */
+static int get_trip_level(struct thermal_zone_device *tz)
+{
+	int count = 0;
+	unsigned long trip_temp;
+
+	if (tz->trips == 0 || !tz->ops->get_trip_temp)
+		return 0;
+
+	for (count = 0; count < tz->trips; count++) {
+		tz->ops->get_trip_temp(tz, count, &trip_temp);
+		if (tz->temperature < trip_temp)
+			break;
+	}
+	return count;
+}
+
+static long get_target_state(struct thermal_zone_device *tz,
+		struct thermal_cooling_device *cdev, int weight, int level)
+{
+	unsigned long max_state;
+
+	cdev->ops->get_max_state(cdev, &max_state);
+
+	return (long)(weight * level * max_state) / (100 * tz->trips);
+}
+
+/**
+ * fair_share_throttle - throttles devices asscciated with the given zone
+ * @tz - thermal_zone_device
+ *
+ * Throttling Logic: This uses three parameters to calculate the new
+ * throttle state of the cooling devices associated with the given zone.
+ *
+ * Parameters used for Throttling:
+ * P1. max_state: Maximum throttle state exposed by the cooling device.
+ * P2. weight[i]/100:
+ *	How 'effective' the 'i'th device is, in cooling the given zone.
+ * P3. cur_trip_level/max_no_of_trips:
+ *	This describes the extent to which the devices should be throttled.
+ *	We do not want to throttle too much when we trip a lower temperature,
+ *	whereas the throttling is at full swing if we trip critical levels.
+ *	(Heavily assumes the trip points are in ascending order)
+ * new_state of cooling device = P3 * P2 * P1
+ */
+static int fair_share_throttle(struct thermal_zone_device *tz, int trip)
+{
+	const struct thermal_zone_params *tzp;
+	struct thermal_cooling_device *cdev;
+	struct thermal_instance *instance;
+	int i;
+	int cur_trip_level = get_trip_level(tz);
+
+	if (!tz->tzp || !tz->tzp->tbp)
+		return -EINVAL;
+
+	tzp = tz->tzp;
+
+	for (i = 0; i < tzp->num_tbps; i++) {
+		if (!tzp->tbp[i].cdev)
+			continue;
+
+		cdev = tzp->tbp[i].cdev;
+		instance = get_thermal_instance(tz, cdev, trip);
+		if (!instance)
+			continue;
+
+		instance->target = get_target_state(tz, cdev,
+					tzp->tbp[i].weight, cur_trip_level);
+
+		instance->cdev->updated = false;
+		thermal_cdev_update(cdev);
+	}
+	return 0;
+}
+
+static struct thermal_governor thermal_gov_fair_share = {
+	.name		= "fair_share",
+	.throttle	= fair_share_throttle,
+	.owner		= THIS_MODULE,
+};
+
+static int __init thermal_gov_fair_share_init(void)
+{
+	return thermal_register_governor(&thermal_gov_fair_share);
+}
+
+static void __exit thermal_gov_fair_share_exit(void)
+{
+	thermal_unregister_governor(&thermal_gov_fair_share);
+}
+
+/* This should load after thermal framework */
+fs_initcall(thermal_gov_fair_share_init);
+module_exit(thermal_gov_fair_share_exit);
+
+MODULE_AUTHOR("Durgadoss R");
+MODULE_DESCRIPTION("A simple weight based thermal throttling governor");
+MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
index f7a1b57..90db951 100644
--- a/drivers/thermal/rcar_thermal.c
+++ b/drivers/thermal/rcar_thermal.c
@@ -43,6 +43,9 @@ struct rcar_thermal_priv {
 	u32 comp;
 };
 
+#define MCELSIUS(temp)			((temp) * 1000)
+#define rcar_zone_to_priv(zone)		(zone->devdata)
+
 /*
  *		basic functions
  */
@@ -96,7 +99,7 @@ static void rcar_thermal_bset(struct rcar_thermal_priv *priv, u32 reg,
 static int rcar_thermal_get_temp(struct thermal_zone_device *zone,
 			   unsigned long *temp)
 {
-	struct rcar_thermal_priv *priv = zone->devdata;
+	struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
 	int val, min, max, tmp;
 
 	tmp = -200; /* default */
@@ -169,7 +172,7 @@ static int rcar_thermal_get_temp(struct thermal_zone_device *zone,
 		}
 	}
 
-	*temp = tmp;
+	*temp = MCELSIUS(tmp);
 	return 0;
 }
 
@@ -185,7 +188,6 @@ static int rcar_thermal_probe(struct platform_device *pdev)
 	struct thermal_zone_device *zone;
 	struct rcar_thermal_priv *priv;
 	struct resource *res;
-	int ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
@@ -206,16 +208,14 @@ static int rcar_thermal_probe(struct platform_device *pdev)
 					  res->start, resource_size(res));
 	if (!priv->base) {
 		dev_err(&pdev->dev, "Unable to ioremap thermal register\n");
-		ret = -ENOMEM;
-		goto error_free_priv;
+		return -ENOMEM;
 	}
 
 	zone = thermal_zone_device_register("rcar_thermal", 0, 0, priv,
-					    &rcar_thermal_zone_ops, 0, 0);
+				    &rcar_thermal_zone_ops, NULL, 0, 0);
 	if (IS_ERR(zone)) {
 		dev_err(&pdev->dev, "thermal zone device is NULL\n");
-		ret = PTR_ERR(zone);
-		goto error_iounmap;
+		return PTR_ERR(zone);
 	}
 
 	platform_set_drvdata(pdev, zone);
@@ -223,26 +223,15 @@ static int rcar_thermal_probe(struct platform_device *pdev)
 	dev_info(&pdev->dev, "proved\n");
 
 	return 0;
-
-error_iounmap:
-	devm_iounmap(&pdev->dev, priv->base);
-error_free_priv:
-	devm_kfree(&pdev->dev, priv);
-
-	return ret;
 }
 
 static int rcar_thermal_remove(struct platform_device *pdev)
 {
 	struct thermal_zone_device *zone = platform_get_drvdata(pdev);
-	struct rcar_thermal_priv *priv = zone->devdata;
 
 	thermal_zone_device_unregister(zone);
 	platform_set_drvdata(pdev, NULL);
 
-	devm_iounmap(&pdev->dev, priv->base);
-	devm_kfree(&pdev->dev, priv);
-
 	return 0;
 }
 
diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
index 9bc9692..6b2d8b2 100644
--- a/drivers/thermal/spear_thermal.c
+++ b/drivers/thermal/spear_thermal.c
@@ -147,7 +147,7 @@ static int spear_thermal_probe(struct platform_device *pdev)
 	writel_relaxed(stdev->flags, stdev->thermal_base);
 
 	spear_thermal = thermal_zone_device_register("spear_thermal", 0, 0,
-				stdev, &ops, 0, 0);
+				stdev, &ops, NULL, 0, 0);
 	if (IS_ERR(spear_thermal)) {
 		dev_err(&pdev->dev, "thermal zone device is NULL\n");
 		ret = PTR_ERR(spear_thermal);
diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c
new file mode 100644
index 0000000..1242cff
--- /dev/null
+++ b/drivers/thermal/step_wise.c
@@ -0,0 +1,194 @@
+/*
+ *  step_wise.c - A step-by-step Thermal throttling governor
+ *
+ *  Copyright (C) 2012 Intel Corp
+ *  Copyright (C) 2012 Durgadoss R <durgadoss.r@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.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/thermal.h>
+
+#include "thermal_core.h"
+
+/*
+ * If the temperature is higher than a trip point,
+ *    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
+ *       state for this trip point
+ *    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
+ *       state for this trip point
+ */
+static unsigned long get_target_state(struct thermal_instance *instance,
+					enum thermal_trend trend)
+{
+	struct thermal_cooling_device *cdev = instance->cdev;
+	unsigned long cur_state;
+
+	cdev->ops->get_cur_state(cdev, &cur_state);
+
+	if (trend == THERMAL_TREND_RAISING) {
+		cur_state = cur_state < instance->upper ?
+			    (cur_state + 1) : instance->upper;
+	} else if (trend == THERMAL_TREND_DROPPING) {
+		cur_state = cur_state > instance->lower ?
+			    (cur_state - 1) : instance->lower;
+	}
+
+	return cur_state;
+}
+
+static void update_passive_instance(struct thermal_zone_device *tz,
+				enum thermal_trip_type type, int value)
+{
+	/*
+	 * If value is +1, activate a passive instance.
+	 * If value is -1, deactivate a passive instance.
+	 */
+	if (type == THERMAL_TRIP_PASSIVE || type == THERMAL_TRIPS_NONE)
+		tz->passive += value;
+}
+
+static void update_instance_for_throttle(struct thermal_zone_device *tz,
+				int trip, enum thermal_trip_type trip_type,
+				enum thermal_trend trend)
+{
+	struct thermal_instance *instance;
+
+	list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+		if (instance->trip != trip)
+			continue;
+
+		instance->target = get_target_state(instance, trend);
+
+		/* Activate a passive thermal instance */
+		if (instance->target == THERMAL_NO_TARGET)
+			update_passive_instance(tz, trip_type, 1);
+
+		instance->cdev->updated = false; /* cdev needs update */
+	}
+}
+
+static void update_instance_for_dethrottle(struct thermal_zone_device *tz,
+				int trip, enum thermal_trip_type trip_type)
+{
+	struct thermal_instance *instance;
+	struct thermal_cooling_device *cdev;
+	unsigned long cur_state;
+
+	list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+		if (instance->trip != trip ||
+			instance->target == THERMAL_NO_TARGET)
+			continue;
+
+		cdev = instance->cdev;
+		cdev->ops->get_cur_state(cdev, &cur_state);
+
+		instance->target = cur_state > instance->lower ?
+			    (cur_state - 1) : THERMAL_NO_TARGET;
+
+		/* Deactivate a passive thermal instance */
+		if (instance->target == THERMAL_NO_TARGET)
+			update_passive_instance(tz, trip_type, -1);
+
+		cdev->updated = false; /* cdev needs update */
+	}
+}
+
+static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
+{
+	long trip_temp;
+	enum thermal_trip_type trip_type;
+	enum thermal_trend trend;
+
+	if (trip == THERMAL_TRIPS_NONE) {
+		trip_temp = tz->forced_passive;
+		trip_type = THERMAL_TRIPS_NONE;
+	} else {
+		tz->ops->get_trip_temp(tz, trip, &trip_temp);
+		tz->ops->get_trip_type(tz, trip, &trip_type);
+	}
+
+	trend = get_tz_trend(tz, trip);
+
+	mutex_lock(&tz->lock);
+
+	if (tz->temperature >= trip_temp)
+		update_instance_for_throttle(tz, trip, trip_type, trend);
+	else
+		update_instance_for_dethrottle(tz, trip, trip_type);
+
+	mutex_unlock(&tz->lock);
+}
+
+/**
+ * step_wise_throttle - throttles devices asscciated with the given zone
+ * @tz - thermal_zone_device
+ * @trip - the trip point
+ * @trip_type - type of the trip point
+ *
+ * Throttling Logic: This uses the trend of the thermal zone to throttle.
+ * If the thermal zone is 'heating up' this throttles all the cooling
+ * devices associated with the zone and its particular trip point, by one
+ * step. If the zone is 'cooling down' it brings back the performance of
+ * the devices by one step.
+ */
+static int step_wise_throttle(struct thermal_zone_device *tz, int trip)
+{
+	struct thermal_instance *instance;
+
+	thermal_zone_trip_update(tz, trip);
+
+	if (tz->forced_passive)
+		thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE);
+
+	mutex_lock(&tz->lock);
+
+	list_for_each_entry(instance, &tz->thermal_instances, tz_node)
+		thermal_cdev_update(instance->cdev);
+
+	mutex_unlock(&tz->lock);
+
+	return 0;
+}
+
+static struct thermal_governor thermal_gov_step_wise = {
+	.name		= DEFAULT_THERMAL_GOVERNOR,
+	.throttle	= step_wise_throttle,
+	.owner		= THIS_MODULE,
+};
+
+static int __init thermal_gov_step_wise_init(void)
+{
+	return thermal_register_governor(&thermal_gov_step_wise);
+}
+
+static void __exit thermal_gov_step_wise_exit(void)
+{
+	thermal_unregister_governor(&thermal_gov_step_wise);
+}
+
+/* This should load after thermal framework */
+fs_initcall(thermal_gov_step_wise_init);
+module_exit(thermal_gov_step_wise_exit);
+
+MODULE_AUTHOR("Durgadoss R");
+MODULE_DESCRIPTION("A step-by-step thermal throttling governor");
+MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
new file mode 100644
index 0000000..0d3205a
--- /dev/null
+++ b/drivers/thermal/thermal_core.h
@@ -0,0 +1,53 @@
+/*
+ *  thermal_core.h
+ *
+ *  Copyright (C) 2012  Intel Corp
+ *  Author: Durgadoss R <durgadoss.r@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.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You 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 __THERMAL_CORE_H__
+#define __THERMAL_CORE_H__
+
+#include <linux/device.h>
+#include <linux/thermal.h>
+
+/* Initial state of a cooling device during binding */
+#define THERMAL_NO_TARGET -1UL
+
+/*
+ * This structure is used to describe the behavior of
+ * a certain cooling device on a certain trip point
+ * in a certain thermal zone
+ */
+struct thermal_instance {
+	int id;
+	char name[THERMAL_NAME_LENGTH];
+	struct thermal_zone_device *tz;
+	struct thermal_cooling_device *cdev;
+	int trip;
+	unsigned long upper;	/* Highest cooling state for this trip point */
+	unsigned long lower;	/* Lowest cooling state for this trip point */
+	unsigned long target;	/* expected cooling state */
+	char attr_name[THERMAL_NAME_LENGTH];
+	struct device_attribute attr;
+	struct list_head tz_node; /* node in tz->thermal_instances */
+	struct list_head cdev_node; /* node in cdev->thermal_instances */
+};
+
+#endif /* __THERMAL_CORE_H__ */
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 9ee42ca..8f0f37b 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -37,38 +37,98 @@
 #include <net/netlink.h>
 #include <net/genetlink.h>
 
+#include "thermal_core.h"
+
 MODULE_AUTHOR("Zhang Rui");
 MODULE_DESCRIPTION("Generic thermal management sysfs support");
 MODULE_LICENSE("GPL");
 
-#define THERMAL_NO_TARGET -1UL
-/*
- * This structure is used to describe the behavior of
- * a certain cooling device on a certain trip point
- * in a certain thermal zone
- */
-struct thermal_instance {
-	int id;
-	char name[THERMAL_NAME_LENGTH];
-	struct thermal_zone_device *tz;
-	struct thermal_cooling_device *cdev;
-	int trip;
-	unsigned long upper;	/* Highest cooling state for this trip point */
-	unsigned long lower;	/* Lowest cooling state for this trip point */
-	unsigned long target;	/* expected cooling state */
-	char attr_name[THERMAL_NAME_LENGTH];
-	struct device_attribute attr;
-	struct list_head tz_node; /* node in tz->thermal_instances */
-	struct list_head cdev_node; /* node in cdev->thermal_instances */
-};
-
 static DEFINE_IDR(thermal_tz_idr);
 static DEFINE_IDR(thermal_cdev_idr);
 static DEFINE_MUTEX(thermal_idr_lock);
 
 static LIST_HEAD(thermal_tz_list);
 static LIST_HEAD(thermal_cdev_list);
+static LIST_HEAD(thermal_governor_list);
+
 static DEFINE_MUTEX(thermal_list_lock);
+static DEFINE_MUTEX(thermal_governor_lock);
+
+static struct thermal_governor *__find_governor(const char *name)
+{
+	struct thermal_governor *pos;
+
+	list_for_each_entry(pos, &thermal_governor_list, governor_list)
+		if (!strnicmp(name, pos->name, THERMAL_NAME_LENGTH))
+			return pos;
+
+	return NULL;
+}
+
+int thermal_register_governor(struct thermal_governor *governor)
+{
+	int err;
+	const char *name;
+	struct thermal_zone_device *pos;
+
+	if (!governor)
+		return -EINVAL;
+
+	mutex_lock(&thermal_governor_lock);
+
+	err = -EBUSY;
+	if (__find_governor(governor->name) == NULL) {
+		err = 0;
+		list_add(&governor->governor_list, &thermal_governor_list);
+	}
+
+	mutex_lock(&thermal_list_lock);
+
+	list_for_each_entry(pos, &thermal_tz_list, node) {
+		if (pos->governor)
+			continue;
+		if (pos->tzp)
+			name = pos->tzp->governor_name;
+		else
+			name = DEFAULT_THERMAL_GOVERNOR;
+		if (!strnicmp(name, governor->name, THERMAL_NAME_LENGTH))
+			pos->governor = governor;
+	}
+
+	mutex_unlock(&thermal_list_lock);
+	mutex_unlock(&thermal_governor_lock);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(thermal_register_governor);
+
+void thermal_unregister_governor(struct thermal_governor *governor)
+{
+	struct thermal_zone_device *pos;
+
+	if (!governor)
+		return;
+
+	mutex_lock(&thermal_governor_lock);
+
+	if (__find_governor(governor->name) == NULL)
+		goto exit;
+
+	mutex_lock(&thermal_list_lock);
+
+	list_for_each_entry(pos, &thermal_tz_list, node) {
+		if (!strnicmp(pos->governor->name, governor->name,
+						THERMAL_NAME_LENGTH))
+			pos->governor = NULL;
+	}
+
+	mutex_unlock(&thermal_list_lock);
+	list_del(&governor->governor_list);
+exit:
+	mutex_unlock(&thermal_governor_lock);
+	return;
+}
+EXPORT_SYMBOL_GPL(thermal_unregister_governor);
 
 static int get_idr(struct idr *idr, struct mutex *lock, int *id)
 {
@@ -101,6 +161,261 @@ static void release_idr(struct idr *idr, struct mutex *lock, int id)
 		mutex_unlock(lock);
 }
 
+int get_tz_trend(struct thermal_zone_device *tz, int trip)
+{
+	enum thermal_trend trend;
+
+	if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) {
+		if (tz->temperature > tz->last_temperature)
+			trend = THERMAL_TREND_RAISING;
+		else if (tz->temperature < tz->last_temperature)
+			trend = THERMAL_TREND_DROPPING;
+		else
+			trend = THERMAL_TREND_STABLE;
+	}
+
+	return trend;
+}
+EXPORT_SYMBOL(get_tz_trend);
+
+struct thermal_instance *get_thermal_instance(struct thermal_zone_device *tz,
+			struct thermal_cooling_device *cdev, int trip)
+{
+	struct thermal_instance *pos = NULL;
+	struct thermal_instance *target_instance = NULL;
+
+	mutex_lock(&tz->lock);
+	mutex_lock(&cdev->lock);
+
+	list_for_each_entry(pos, &tz->thermal_instances, tz_node) {
+		if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
+			target_instance = pos;
+			break;
+		}
+	}
+
+	mutex_unlock(&cdev->lock);
+	mutex_unlock(&tz->lock);
+
+	return target_instance;
+}
+EXPORT_SYMBOL(get_thermal_instance);
+
+static void print_bind_err_msg(struct thermal_zone_device *tz,
+			struct thermal_cooling_device *cdev, int ret)
+{
+	dev_err(&tz->device, "binding zone %s with cdev %s failed:%d\n",
+				tz->type, cdev->type, ret);
+}
+
+static void __bind(struct thermal_zone_device *tz, int mask,
+			struct thermal_cooling_device *cdev)
+{
+	int i, ret;
+
+	for (i = 0; i < tz->trips; i++) {
+		if (mask & (1 << i)) {
+			ret = thermal_zone_bind_cooling_device(tz, i, cdev,
+					THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
+			if (ret)
+				print_bind_err_msg(tz, cdev, ret);
+		}
+	}
+}
+
+static void __unbind(struct thermal_zone_device *tz, int mask,
+			struct thermal_cooling_device *cdev)
+{
+	int i;
+
+	for (i = 0; i < tz->trips; i++)
+		if (mask & (1 << i))
+			thermal_zone_unbind_cooling_device(tz, i, cdev);
+}
+
+static void bind_cdev(struct thermal_cooling_device *cdev)
+{
+	int i, ret;
+	const struct thermal_zone_params *tzp;
+	struct thermal_zone_device *pos = NULL;
+
+	mutex_lock(&thermal_list_lock);
+
+	list_for_each_entry(pos, &thermal_tz_list, node) {
+		if (!pos->tzp && !pos->ops->bind)
+			continue;
+
+		if (!pos->tzp && pos->ops->bind) {
+			ret = pos->ops->bind(pos, cdev);
+			if (ret)
+				print_bind_err_msg(pos, cdev, ret);
+		}
+
+		tzp = pos->tzp;
+		if (!tzp || !tzp->tbp)
+			continue;
+
+		for (i = 0; i < tzp->num_tbps; i++) {
+			if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
+				continue;
+			if (tzp->tbp[i].match(pos, cdev))
+				continue;
+			tzp->tbp[i].cdev = cdev;
+			__bind(pos, tzp->tbp[i].trip_mask, cdev);
+		}
+	}
+
+	mutex_unlock(&thermal_list_lock);
+}
+
+static void bind_tz(struct thermal_zone_device *tz)
+{
+	int i, ret;
+	struct thermal_cooling_device *pos = NULL;
+	const struct thermal_zone_params *tzp = tz->tzp;
+
+	if (!tzp && !tz->ops->bind)
+		return;
+
+	mutex_lock(&thermal_list_lock);
+
+	/* If there is no platform data, try to use ops->bind */
+	if (!tzp && tz->ops->bind) {
+		list_for_each_entry(pos, &thermal_cdev_list, node) {
+			ret = tz->ops->bind(tz, pos);
+			if (ret)
+				print_bind_err_msg(tz, pos, ret);
+		}
+		goto exit;
+	}
+
+	if (!tzp || !tzp->tbp)
+		goto exit;
+
+	list_for_each_entry(pos, &thermal_cdev_list, node) {
+		for (i = 0; i < tzp->num_tbps; i++) {
+			if (tzp->tbp[i].cdev || !tzp->tbp[i].match)
+				continue;
+			if (tzp->tbp[i].match(tz, pos))
+				continue;
+			tzp->tbp[i].cdev = pos;
+			__bind(tz, tzp->tbp[i].trip_mask, pos);
+		}
+	}
+exit:
+	mutex_unlock(&thermal_list_lock);
+}
+
+static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
+					    int delay)
+{
+	if (delay > 1000)
+		mod_delayed_work(system_freezable_wq, &tz->poll_queue,
+				 round_jiffies(msecs_to_jiffies(delay)));
+	else if (delay)
+		mod_delayed_work(system_freezable_wq, &tz->poll_queue,
+				 msecs_to_jiffies(delay));
+	else
+		cancel_delayed_work(&tz->poll_queue);
+}
+
+static void monitor_thermal_zone(struct thermal_zone_device *tz)
+{
+	mutex_lock(&tz->lock);
+
+	if (tz->passive)
+		thermal_zone_device_set_polling(tz, tz->passive_delay);
+	else if (tz->polling_delay)
+		thermal_zone_device_set_polling(tz, tz->polling_delay);
+	else
+		thermal_zone_device_set_polling(tz, 0);
+
+	mutex_unlock(&tz->lock);
+}
+
+static void handle_non_critical_trips(struct thermal_zone_device *tz,
+			int trip, enum thermal_trip_type trip_type)
+{
+	tz->governor->throttle(tz, trip);
+}
+
+static void handle_critical_trips(struct thermal_zone_device *tz,
+				int trip, enum thermal_trip_type trip_type)
+{
+	long trip_temp;
+
+	tz->ops->get_trip_temp(tz, trip, &trip_temp);
+
+	/* If we have not crossed the trip_temp, we do not care. */
+	if (tz->temperature < trip_temp)
+		return;
+
+	if (tz->ops->notify)
+		tz->ops->notify(tz, trip, trip_type);
+
+	if (trip_type == THERMAL_TRIP_CRITICAL) {
+		pr_emerg("Critical temperature reached(%d C),shutting down\n",
+			 tz->temperature / 1000);
+		orderly_poweroff(true);
+	}
+}
+
+static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
+{
+	enum thermal_trip_type type;
+
+	tz->ops->get_trip_type(tz, trip, &type);
+
+	if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
+		handle_critical_trips(tz, trip, type);
+	else
+		handle_non_critical_trips(tz, trip, type);
+	/*
+	 * Alright, we handled this trip successfully.
+	 * So, start monitoring again.
+	 */
+	monitor_thermal_zone(tz);
+}
+
+static void update_temperature(struct thermal_zone_device *tz)
+{
+	long temp;
+	int ret;
+
+	mutex_lock(&tz->lock);
+
+	ret = tz->ops->get_temp(tz, &temp);
+	if (ret) {
+		pr_warn("failed to read out thermal zone %d\n", tz->id);
+		goto exit;
+	}
+
+	tz->last_temperature = tz->temperature;
+	tz->temperature = temp;
+
+exit:
+	mutex_unlock(&tz->lock);
+}
+
+void thermal_zone_device_update(struct thermal_zone_device *tz)
+{
+	int count;
+
+	update_temperature(tz);
+
+	for (count = 0; count < tz->trips; count++)
+		handle_thermal_trip(tz, count);
+}
+EXPORT_SYMBOL(thermal_zone_device_update);
+
+static void thermal_zone_device_check(struct work_struct *work)
+{
+	struct thermal_zone_device *tz = container_of(work, struct
+						      thermal_zone_device,
+						      poll_queue.work);
+	thermal_zone_device_update(tz);
+}
+
 /* sys I/F for thermal zone */
 
 #define to_thermal_zone(_dev) \
@@ -354,10 +669,41 @@ passive_show(struct device *dev, struct device_attribute *attr,
 	return sprintf(buf, "%d\n", tz->forced_passive);
 }
 
+static ssize_t
+policy_store(struct device *dev, struct device_attribute *attr,
+		    const char *buf, size_t count)
+{
+	int ret = -EINVAL;
+	struct thermal_zone_device *tz = to_thermal_zone(dev);
+	struct thermal_governor *gov;
+
+	mutex_lock(&thermal_governor_lock);
+
+	gov = __find_governor(buf);
+	if (!gov)
+		goto exit;
+
+	tz->governor = gov;
+	ret = count;
+
+exit:
+	mutex_unlock(&thermal_governor_lock);
+	return ret;
+}
+
+static ssize_t
+policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct thermal_zone_device *tz = to_thermal_zone(dev);
+
+	return sprintf(buf, "%s\n", tz->governor->name);
+}
+
 static DEVICE_ATTR(type, 0444, type_show, NULL);
 static DEVICE_ATTR(temp, 0444, temp_show, NULL);
 static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
 static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
+static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
 
 /* sys I/F for cooling device */
 #define to_cooling_device(_dev)	\
@@ -700,27 +1046,6 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
 }
 #endif
 
-static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
-					    int delay)
-{
-	if (delay > 1000)
-		mod_delayed_work(system_freezable_wq, &tz->poll_queue,
-				 round_jiffies(msecs_to_jiffies(delay)));
-	else if (delay)
-		mod_delayed_work(system_freezable_wq, &tz->poll_queue,
-				 msecs_to_jiffies(delay));
-	else
-		cancel_delayed_work(&tz->poll_queue);
-}
-
-static void thermal_zone_device_check(struct work_struct *work)
-{
-	struct thermal_zone_device *tz = container_of(work, struct
-						      thermal_zone_device,
-						      poll_queue.work);
-	thermal_zone_device_update(tz);
-}
-
 /**
  * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone
  * @tz:		thermal zone device
@@ -895,7 +1220,6 @@ thermal_cooling_device_register(char *type, void *devdata,
 				const struct thermal_cooling_device_ops *ops)
 {
 	struct thermal_cooling_device *cdev;
-	struct thermal_zone_device *pos;
 	int result;
 
 	if (type && strlen(type) >= THERMAL_NAME_LENGTH)
@@ -945,20 +1269,15 @@ thermal_cooling_device_register(char *type, void *devdata,
 	if (result)
 		goto unregister;
 
+	/* Add 'this' new cdev to the global cdev list */
 	mutex_lock(&thermal_list_lock);
 	list_add(&cdev->node, &thermal_cdev_list);
-	list_for_each_entry(pos, &thermal_tz_list, node) {
-		if (!pos->ops->bind)
-			continue;
-		result = pos->ops->bind(pos, cdev);
-		if (result)
-			break;
-
-	}
 	mutex_unlock(&thermal_list_lock);
 
-	if (!result)
-		return cdev;
+	/* Update binding information for 'this' new cdev */
+	bind_cdev(cdev);
+
+	return cdev;
 
 unregister:
 	release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
@@ -974,10 +1293,10 @@ EXPORT_SYMBOL(thermal_cooling_device_register);
  * thermal_cooling_device_unregister() must be called when the device is no
  * longer needed.
  */
-void thermal_cooling_device_unregister(struct
-				       thermal_cooling_device
-				       *cdev)
+void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
 {
+	int i;
+	const struct thermal_zone_params *tzp;
 	struct thermal_zone_device *tz;
 	struct thermal_cooling_device *pos = NULL;
 
@@ -994,12 +1313,28 @@ void thermal_cooling_device_unregister(struct
 		return;
 	}
 	list_del(&cdev->node);
+
+	/* Unbind all thermal zones associated with 'this' cdev */
 	list_for_each_entry(tz, &thermal_tz_list, node) {
-		if (!tz->ops->unbind)
+		if (tz->ops->unbind) {
+			tz->ops->unbind(tz, cdev);
 			continue;
-		tz->ops->unbind(tz, cdev);
+		}
+
+		if (!tz->tzp || !tz->tzp->tbp)
+			continue;
+
+		tzp = tz->tzp;
+		for (i = 0; i < tzp->num_tbps; i++) {
+			if (tzp->tbp[i].cdev == cdev) {
+				__unbind(tz, tzp->tbp[i].trip_mask, cdev);
+				tzp->tbp[i].cdev = NULL;
+			}
+		}
 	}
+
 	mutex_unlock(&thermal_list_lock);
+
 	if (cdev->type[0])
 		device_remove_file(&cdev->device, &dev_attr_cdev_type);
 	device_remove_file(&cdev->device, &dev_attr_max_state);
@@ -1011,7 +1346,7 @@ void thermal_cooling_device_unregister(struct
 }
 EXPORT_SYMBOL(thermal_cooling_device_unregister);
 
-static void thermal_cdev_do_update(struct thermal_cooling_device *cdev)
+void thermal_cdev_update(struct thermal_cooling_device *cdev)
 {
 	struct thermal_instance *instance;
 	unsigned long target = 0;
@@ -1032,183 +1367,25 @@ static void thermal_cdev_do_update(struct thermal_cooling_device *cdev)
 	cdev->ops->set_cur_state(cdev, target);
 	cdev->updated = true;
 }
+EXPORT_SYMBOL(thermal_cdev_update);
 
-static void thermal_zone_do_update(struct thermal_zone_device *tz)
-{
-	struct thermal_instance *instance;
-
-	list_for_each_entry(instance, &tz->thermal_instances, tz_node)
-		thermal_cdev_do_update(instance->cdev);
-}
-
-/*
- * Cooling algorithm for both active and passive cooling
- *
- * 1. if the temperature is higher than a trip point,
- *    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
- *       state for this trip point
- *    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
- *       state for this trip point
- *
- * 2. if the temperature is lower than a trip point, use lower
- *    cooling state for this trip point
- *
- * Note that this behaves the same as the previous passive cooling
- * algorithm.
- */
-
-static void thermal_zone_trip_update(struct thermal_zone_device *tz,
-				     int trip, long temp)
-{
-	struct thermal_instance *instance;
-	struct thermal_cooling_device *cdev = NULL;
-	unsigned long cur_state, max_state;
-	long trip_temp;
-	enum thermal_trip_type trip_type;
-	enum thermal_trend trend;
-
-	if (trip == THERMAL_TRIPS_NONE) {
-		trip_temp = tz->forced_passive;
-		trip_type = THERMAL_TRIPS_NONE;
-	} else {
-		tz->ops->get_trip_temp(tz, trip, &trip_temp);
-		tz->ops->get_trip_type(tz, trip, &trip_type);
-	}
-
-	if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) {
-		/*
-		 * compare the current temperature and previous temperature
-		 * to get the thermal trend, if no special requirement
-		 */
-		if (tz->temperature > tz->last_temperature)
-			trend = THERMAL_TREND_RAISING;
-		else if (tz->temperature < tz->last_temperature)
-			trend = THERMAL_TREND_DROPPING;
-		else
-			trend = THERMAL_TREND_STABLE;
-	}
-
-	if (temp >= trip_temp) {
-		list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
-			if (instance->trip != trip)
-				continue;
-
-			cdev = instance->cdev;
-
-			cdev->ops->get_cur_state(cdev, &cur_state);
-			cdev->ops->get_max_state(cdev, &max_state);
-
-			if (trend == THERMAL_TREND_RAISING) {
-				cur_state = cur_state < instance->upper ?
-					    (cur_state + 1) : instance->upper;
-			} else if (trend == THERMAL_TREND_DROPPING) {
-				cur_state = cur_state > instance->lower ?
-				    (cur_state - 1) : instance->lower;
-			}
-
-			/* activate a passive thermal instance */
-			if ((trip_type == THERMAL_TRIP_PASSIVE ||
-			     trip_type == THERMAL_TRIPS_NONE) &&
-			     instance->target == THERMAL_NO_TARGET)
-				tz->passive++;
-
-			instance->target = cur_state;
-			cdev->updated = false; /* cooling device needs update */
-		}
-	} else {	/* below trip */
-		list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
-			if (instance->trip != trip)
-				continue;
-
-			/* Do not use the inactive thermal instance */
-			if (instance->target == THERMAL_NO_TARGET)
-				continue;
-			cdev = instance->cdev;
-			cdev->ops->get_cur_state(cdev, &cur_state);
-
-			cur_state = cur_state > instance->lower ?
-				    (cur_state - 1) : THERMAL_NO_TARGET;
-
-			/* deactivate a passive thermal instance */
-			if ((trip_type == THERMAL_TRIP_PASSIVE ||
-			     trip_type == THERMAL_TRIPS_NONE) &&
-			     cur_state == THERMAL_NO_TARGET)
-				tz->passive--;
-			instance->target = cur_state;
-			cdev->updated = false; /* cooling device needs update */
-		}
-	}
-
-	return;
-}
 /**
- * thermal_zone_device_update - force an update of a thermal zone's state
- * @ttz:	the thermal zone to update
+ * notify_thermal_framework - Sensor drivers use this API to notify framework
+ * @tz:		thermal zone device
+ * @trip:	indicates which trip point has been crossed
+ *
+ * This function handles the trip events from sensor drivers. It starts
+ * throttling the cooling devices according to the policy configured.
+ * For CRITICAL and HOT trip points, this notifies the respective drivers,
+ * and does actual throttling for other trip points i.e ACTIVE and PASSIVE.
+ * The throttling policy is based on the configured platform data; if no
+ * platform data is provided, this uses the step_wise throttling policy.
  */
-
-void thermal_zone_device_update(struct thermal_zone_device *tz)
+void notify_thermal_framework(struct thermal_zone_device *tz, int trip)
 {
-	int count, ret = 0;
-	long temp, trip_temp;
-	enum thermal_trip_type trip_type;
-
-	mutex_lock(&tz->lock);
-
-	if (tz->ops->get_temp(tz, &temp)) {
-		/* get_temp failed - retry it later */
-		pr_warn("failed to read out thermal zone %d\n", tz->id);
-		goto leave;
-	}
-
-	tz->last_temperature = tz->temperature;
-	tz->temperature = temp;
-
-	for (count = 0; count < tz->trips; count++) {
-		tz->ops->get_trip_type(tz, count, &trip_type);
-		tz->ops->get_trip_temp(tz, count, &trip_temp);
-
-		switch (trip_type) {
-		case THERMAL_TRIP_CRITICAL:
-			if (temp >= trip_temp) {
-				if (tz->ops->notify)
-					ret = tz->ops->notify(tz, count,
-							      trip_type);
-				if (!ret) {
-					pr_emerg("Critical temperature reached (%ld C), shutting down\n",
-						 temp/1000);
-					orderly_poweroff(true);
-				}
-			}
-			break;
-		case THERMAL_TRIP_HOT:
-			if (temp >= trip_temp)
-				if (tz->ops->notify)
-					tz->ops->notify(tz, count, trip_type);
-			break;
-		case THERMAL_TRIP_ACTIVE:
-			thermal_zone_trip_update(tz, count, temp);
-			break;
-		case THERMAL_TRIP_PASSIVE:
-			if (temp >= trip_temp || tz->passive)
-				thermal_zone_trip_update(tz, count, temp);
-			break;
-		}
-	}
-
-	if (tz->forced_passive)
-		thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE, temp);
-	thermal_zone_do_update(tz);
-
-leave:
-	if (tz->passive)
-		thermal_zone_device_set_polling(tz, tz->passive_delay);
-	else if (tz->polling_delay)
-		thermal_zone_device_set_polling(tz, tz->polling_delay);
-	else
-		thermal_zone_device_set_polling(tz, 0);
-	mutex_unlock(&tz->lock);
+	handle_thermal_trip(tz, trip);
 }
-EXPORT_SYMBOL(thermal_zone_device_update);
+EXPORT_SYMBOL(notify_thermal_framework);
 
 /**
  * create_trip_attrs - create attributes for trip points
@@ -1320,6 +1497,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
  * @mask:	a bit string indicating the writeablility of trip points
  * @devdata:	private device data
  * @ops:	standard thermal zone device callbacks
+ * @tzp:	thermal zone platform parameters
  * @passive_delay: number of milliseconds to wait between polls when
  *		   performing passive cooling
  * @polling_delay: number of milliseconds to wait between polls when checking
@@ -1332,10 +1510,10 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
 struct thermal_zone_device *thermal_zone_device_register(const char *type,
 	int trips, int mask, void *devdata,
 	const struct thermal_zone_device_ops *ops,
+	const struct thermal_zone_params *tzp,
 	int passive_delay, int polling_delay)
 {
 	struct thermal_zone_device *tz;
-	struct thermal_cooling_device *pos;
 	enum thermal_trip_type trip_type;
 	int result;
 	int count;
@@ -1365,6 +1543,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
 
 	strcpy(tz->type, type ? : "");
 	tz->ops = ops;
+	tz->tzp = tzp;
 	tz->device.class = &thermal_class;
 	tz->devdata = devdata;
 	tz->trips = trips;
@@ -1406,27 +1585,38 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
 			passive = 1;
 	}
 
-	if (!passive)
-		result = device_create_file(&tz->device,
-					    &dev_attr_passive);
+	if (!passive) {
+		result = device_create_file(&tz->device, &dev_attr_passive);
+		if (result)
+			goto unregister;
+	}
 
+	/* Create policy attribute */
+	result = device_create_file(&tz->device, &dev_attr_policy);
 	if (result)
 		goto unregister;
 
+	/* Update 'this' zone's governor information */
+	mutex_lock(&thermal_governor_lock);
+
+	if (tz->tzp)
+		tz->governor = __find_governor(tz->tzp->governor_name);
+	else
+		tz->governor = __find_governor(DEFAULT_THERMAL_GOVERNOR);
+
+	mutex_unlock(&thermal_governor_lock);
+
 	result = thermal_add_hwmon_sysfs(tz);
 	if (result)
 		goto unregister;
 
 	mutex_lock(&thermal_list_lock);
 	list_add_tail(&tz->node, &thermal_tz_list);
-	if (ops->bind)
-		list_for_each_entry(pos, &thermal_cdev_list, node) {
-		result = ops->bind(tz, pos);
-		if (result)
-			break;
-		}
 	mutex_unlock(&thermal_list_lock);
 
+	/* Bind cooling devices for this zone */
+	bind_tz(tz);
+
 	INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
 
 	thermal_zone_device_update(tz);
@@ -1447,12 +1637,16 @@ EXPORT_SYMBOL(thermal_zone_device_register);
  */
 void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 {
+	int i;
+	const struct thermal_zone_params *tzp;
 	struct thermal_cooling_device *cdev;
 	struct thermal_zone_device *pos = NULL;
 
 	if (!tz)
 		return;
 
+	tzp = tz->tzp;
+
 	mutex_lock(&thermal_list_lock);
 	list_for_each_entry(pos, &thermal_tz_list, node)
 	    if (pos == tz)
@@ -1463,9 +1657,25 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 		return;
 	}
 	list_del(&tz->node);
-	if (tz->ops->unbind)
-		list_for_each_entry(cdev, &thermal_cdev_list, node)
-		    tz->ops->unbind(tz, cdev);
+
+	/* Unbind all cdevs associated with 'this' thermal zone */
+	list_for_each_entry(cdev, &thermal_cdev_list, node) {
+		if (tz->ops->unbind) {
+			tz->ops->unbind(tz, cdev);
+			continue;
+		}
+
+		if (!tzp || !tzp->tbp)
+			break;
+
+		for (i = 0; i < tzp->num_tbps; i++) {
+			if (tzp->tbp[i].cdev == cdev) {
+				__unbind(tz, tzp->tbp[i].trip_mask, cdev);
+				tzp->tbp[i].cdev = NULL;
+			}
+		}
+	}
+
 	mutex_unlock(&thermal_list_lock);
 
 	thermal_zone_device_set_polling(tz, 0);
@@ -1475,7 +1685,9 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 	device_remove_file(&tz->device, &dev_attr_temp);
 	if (tz->ops->get_mode)
 		device_remove_file(&tz->device, &dev_attr_mode);
+	device_remove_file(&tz->device, &dev_attr_policy);
 	remove_trip_attrs(tz);
+	tz->governor = NULL;
 
 	thermal_remove_hwmon_sysfs(tz);
 	release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
diff --git a/drivers/thermal/user_space.c b/drivers/thermal/user_space.c
new file mode 100644
index 0000000..6bbb380
--- /dev/null
+++ b/drivers/thermal/user_space.c
@@ -0,0 +1,68 @@
+/*
+ *  user_space.c - A simple user space Thermal events notifier
+ *
+ *  Copyright (C) 2012 Intel Corp
+ *  Copyright (C) 2012 Durgadoss R <durgadoss.r@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.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/thermal.h>
+
+#include "thermal_core.h"
+
+/**
+ * notify_user_space - Notifies user space about thermal events
+ * @tz - thermal_zone_device
+ *
+ * This function notifies the user space through UEvents.
+ */
+static int notify_user_space(struct thermal_zone_device *tz, int trip)
+{
+	mutex_lock(&tz->lock);
+	kobject_uevent(&tz->device.kobj, KOBJ_CHANGE);
+	mutex_unlock(&tz->lock);
+	return 0;
+}
+
+static struct thermal_governor thermal_gov_user_space = {
+	.name		= "user_space",
+	.throttle	= notify_user_space,
+	.owner		= THIS_MODULE,
+};
+
+static int __init thermal_gov_user_space_init(void)
+{
+	return thermal_register_governor(&thermal_gov_user_space);
+}
+
+static void __exit thermal_gov_user_space_exit(void)
+{
+	thermal_unregister_governor(&thermal_gov_user_space);
+}
+
+/* This should load after thermal framework */
+fs_initcall(thermal_gov_user_space_init);
+module_exit(thermal_gov_user_space_exit);
+
+MODULE_AUTHOR("Durgadoss R");
+MODULE_DESCRIPTION("A user space Thermal notifier");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
index d8e05ee..0ecf22b 100644
--- a/drivers/tty/Kconfig
+++ b/drivers/tty/Kconfig
@@ -357,6 +357,7 @@ config TRACE_SINK
 config PPC_EPAPR_HV_BYTECHAN
 	tristate "ePAPR hypervisor byte channel driver"
 	depends on PPC
+	select EPAPR_PARAVIRT
 	help
 	  This driver creates /dev entries for each ePAPR hypervisor byte
 	  channel, thereby allowing applications to communicate with byte
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 42d0a25..9d7d00c 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -1771,6 +1771,7 @@ fail_free_irq:
 fail_unregister:
 	tty_unregister_driver(serial_driver);
 fail_put_tty_driver:
+	tty_port_destroy(&state->tport);
 	put_tty_driver(serial_driver);
 	return error;
 }
@@ -1785,6 +1786,7 @@ static int __exit amiga_serial_remove(struct platform_device *pdev)
 		printk("SERIAL: failed to unregister serial driver (%d)\n",
 		       error);
 	put_tty_driver(serial_driver);
+	tty_port_destroy(&state->tport);
 
 	free_irq(IRQ_AMIGA_TBE, state);
 	free_irq(IRQ_AMIGA_RBF, state);
diff --git a/drivers/tty/bfin_jtag_comm.c b/drivers/tty/bfin_jtag_comm.c
index 02b7d3a..1cfcdbf 100644
--- a/drivers/tty/bfin_jtag_comm.c
+++ b/drivers/tty/bfin_jtag_comm.c
@@ -240,8 +240,6 @@ static int __init bfin_jc_init(void)
 {
 	int ret;
 
-	tty_port_init(&port);
-
 	bfin_jc_kthread = kthread_create(bfin_jc_emudat_manager, NULL, DRV_NAME);
 	if (IS_ERR(bfin_jc_kthread))
 		return PTR_ERR(bfin_jc_kthread);
@@ -257,6 +255,8 @@ static int __init bfin_jc_init(void)
 	if (!bfin_jc_driver)
 		goto err_driver;
 
+	tty_port_init(&port);
+
 	bfin_jc_driver->driver_name  = DRV_NAME;
 	bfin_jc_driver->name         = DEV_NAME;
 	bfin_jc_driver->type         = TTY_DRIVER_TYPE_SERIAL;
@@ -274,6 +274,7 @@ static int __init bfin_jc_init(void)
 	return 0;
 
  err:
+	tty_port_destroy(&port);
 	put_tty_driver(bfin_jc_driver);
  err_driver:
 	kfree(bfin_jc_write_buf.buf);
@@ -289,6 +290,7 @@ static void __exit bfin_jc_exit(void)
 	kfree(bfin_jc_write_buf.buf);
 	tty_unregister_driver(bfin_jc_driver);
 	put_tty_driver(bfin_jc_driver);
+	tty_port_destroy(&port);
 }
 module_exit(bfin_jc_exit);
 
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
index 0a6a0bc..b09c8d1f 100644
--- a/drivers/tty/cyclades.c
+++ b/drivers/tty/cyclades.c
@@ -3099,7 +3099,7 @@ static const struct tty_port_operations cyz_port_ops = {
  * ---------------------------------------------------------------------
  */
 
-static int __devinit cy_init_card(struct cyclades_card *cinfo)
+static int cy_init_card(struct cyclades_card *cinfo)
 {
 	struct cyclades_port *info;
 	unsigned int channel, port;
@@ -3196,7 +3196,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
 
 /* initialize chips on Cyclom-Y card -- return number of valid
    chips (which is number of ports/4) */
-static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr,
+static unsigned short cyy_init_card(void __iomem *true_base_addr,
 		int index)
 {
 	unsigned int chip_number;
@@ -3405,7 +3405,7 @@ static int __init cy_detect_isa(void)
 }				/* cy_detect_isa */
 
 #ifdef CONFIG_PCI
-static inline int __devinit cyc_isfwstr(const char *str, unsigned int size)
+static inline int cyc_isfwstr(const char *str, unsigned int size)
 {
 	unsigned int a;
 
@@ -3420,7 +3420,7 @@ static inline int __devinit cyc_isfwstr(const char *str, unsigned int size)
 	return 0;
 }
 
-static inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data,
+static inline void cyz_fpga_copy(void __iomem *fpga, const u8 *data,
 		unsigned int size)
 {
 	for (; size > 0; size--) {
@@ -3429,7 +3429,7 @@ static inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data,
 	}
 }
 
-static void __devinit plx_init(struct pci_dev *pdev, int irq,
+static void plx_init(struct pci_dev *pdev, int irq,
 		struct RUNTIME_9060 __iomem *addr)
 {
 	/* Reset PLX */
@@ -3449,7 +3449,7 @@ static void __devinit plx_init(struct pci_dev *pdev, int irq,
 	pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
 }
 
-static int __devinit __cyz_load_fw(const struct firmware *fw,
+static int __cyz_load_fw(const struct firmware *fw,
 		const char *name, const u32 mailbox, void __iomem *base,
 		void __iomem *fpga)
 {
@@ -3526,7 +3526,7 @@ static int __devinit __cyz_load_fw(const struct firmware *fw,
 	return 0;
 }
 
-static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
+static int cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
 		struct RUNTIME_9060 __iomem *ctl_addr, int irq)
 {
 	const struct firmware *fw;
@@ -3692,7 +3692,7 @@ err:
 	return retval;
 }
 
-static int __devinit cy_pci_probe(struct pci_dev *pdev,
+static int cy_pci_probe(struct pci_dev *pdev,
 		const struct pci_device_id *ent)
 {
 	struct cyclades_card *card;
@@ -3931,10 +3931,10 @@ err:
 	return retval;
 }
 
-static void __devexit cy_pci_remove(struct pci_dev *pdev)
+static void cy_pci_remove(struct pci_dev *pdev)
 {
 	struct cyclades_card *cinfo = pci_get_drvdata(pdev);
-	unsigned int i;
+	unsigned int i, channel;
 
 	/* non-Z with old PLX */
 	if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
@@ -3960,9 +3960,11 @@ static void __devexit cy_pci_remove(struct pci_dev *pdev)
 	pci_release_regions(pdev);
 
 	cinfo->base_addr = NULL;
-	for (i = cinfo->first_line; i < cinfo->first_line +
-			cinfo->nports; i++)
+	for (channel = 0, i = cinfo->first_line; i < cinfo->first_line +
+			cinfo->nports; i++, channel++) {
 		tty_unregister_device(cy_serial_driver, i);
+		tty_port_destroy(&cinfo->ports[channel].port);
+	}
 	cinfo->nports = 0;
 	kfree(cinfo->ports);
 }
@@ -3971,7 +3973,7 @@ static struct pci_driver cy_pci_driver = {
 	.name = "cyclades",
 	.id_table = cy_pci_dev_id,
 	.probe = cy_pci_probe,
-	.remove = __devexit_p(cy_pci_remove)
+	.remove = cy_pci_remove
 };
 #endif
 
diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c
index 4ab936b..c117d77 100644
--- a/drivers/tty/ehv_bytechan.c
+++ b/drivers/tty/ehv_bytechan.c
@@ -699,7 +699,7 @@ static const struct tty_port_operations ehv_bc_tty_port_ops = {
 	.shutdown = ehv_bc_tty_port_shutdown,
 };
 
-static int __devinit ehv_bc_tty_probe(struct platform_device *pdev)
+static int ehv_bc_tty_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct ehv_bc_data *bc;
@@ -757,6 +757,7 @@ static int __devinit ehv_bc_tty_probe(struct platform_device *pdev)
 	return 0;
 
 error:
+	tty_port_destroy(&bc->port);
 	irq_dispose_mapping(bc->tx_irq);
 	irq_dispose_mapping(bc->rx_irq);
 
@@ -770,6 +771,7 @@ static int ehv_bc_tty_remove(struct platform_device *pdev)
 
 	tty_unregister_device(ehv_bc_driver, bc - bcs);
 
+	tty_port_destroy(&bc->port);
 	irq_dispose_mapping(bc->tx_irq);
 	irq_dispose_mapping(bc->rx_irq);
 
diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c
index 0d2ea0c..cd69b48 100644
--- a/drivers/tty/hvc/hvc_opal.c
+++ b/drivers/tty/hvc/hvc_opal.c
@@ -41,7 +41,7 @@
 
 static const char hvc_opal_name[] = "hvc_opal";
 
-static struct of_device_id hvc_opal_match[] __devinitdata = {
+static struct of_device_id hvc_opal_match[] = {
 	{ .name = "serial", .compatible = "ibm,opal-console-raw" },
 	{ .name = "serial", .compatible = "ibm,opal-console-hvsi" },
 	{ },
@@ -161,7 +161,7 @@ static const struct hv_ops hvc_opal_hvsi_ops = {
 	.tiocmset = hvc_opal_hvsi_tiocmset,
 };
 
-static int __devinit hvc_opal_probe(struct platform_device *dev)
+static int hvc_opal_probe(struct platform_device *dev)
 {
 	const struct hv_ops *ops;
 	struct hvc_struct *hp;
@@ -178,7 +178,7 @@ static int __devinit hvc_opal_probe(struct platform_device *dev)
 		proto = HV_PROTOCOL_HVSI;
 		ops = &hvc_opal_hvsi_ops;
 	} else {
-		pr_err("hvc_opal: Unkown protocol for %s\n",
+		pr_err("hvc_opal: Unknown protocol for %s\n",
 		       dev->dev.of_node->full_name);
 		return -ENXIO;
 	}
@@ -222,7 +222,7 @@ static int __devinit hvc_opal_probe(struct platform_device *dev)
 	return 0;
 }
 
-static int __devexit hvc_opal_remove(struct platform_device *dev)
+static int hvc_opal_remove(struct platform_device *dev)
 {
 	struct hvc_struct *hp = dev_get_drvdata(&dev->dev);
 	int rc, termno;
@@ -239,7 +239,7 @@ static int __devexit hvc_opal_remove(struct platform_device *dev)
 
 static struct platform_driver hvc_opal_driver = {
 	.probe		= hvc_opal_probe,
-	.remove		= __devexit_p(hvc_opal_remove),
+	.remove		= hvc_opal_remove,
 	.driver		= {
 		.name	= hvc_opal_name,
 		.owner	= THIS_MODULE,
diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c
index 070c0ee6..0c62980 100644
--- a/drivers/tty/hvc/hvc_vio.c
+++ b/drivers/tty/hvc/hvc_vio.c
@@ -53,7 +53,7 @@
 
 static const char hvc_driver_name[] = "hvc_console";
 
-static struct vio_device_id hvc_driver_table[] __devinitdata = {
+static struct vio_device_id hvc_driver_table[] = {
 	{"serial", "hvterm1"},
 #ifndef HVC_OLD_HVSI
 	{"serial", "hvterm-protocol"},
@@ -293,7 +293,7 @@ static int udbg_hvc_getc(void)
 	}
 }
 
-static int __devinit hvc_vio_probe(struct vio_dev *vdev,
+static int hvc_vio_probe(struct vio_dev *vdev,
 				   const struct vio_device_id *id)
 {
 	const struct hv_ops *ops;
@@ -313,7 +313,7 @@ static int __devinit hvc_vio_probe(struct vio_dev *vdev,
 		proto = HV_PROTOCOL_HVSI;
 		ops = &hvterm_hvsi_ops;
 	} else {
-		pr_err("hvc_vio: Unkown protocol for %s\n", vdev->dev.of_node->full_name);
+		pr_err("hvc_vio: Unknown protocol for %s\n", vdev->dev.of_node->full_name);
 		return -ENXIO;
 	}
 
@@ -362,7 +362,7 @@ static int __devinit hvc_vio_probe(struct vio_dev *vdev,
 	return 0;
 }
 
-static int __devexit hvc_vio_remove(struct vio_dev *vdev)
+static int hvc_vio_remove(struct vio_dev *vdev)
 {
 	struct hvc_struct *hp = dev_get_drvdata(&vdev->dev);
 	int rc, termno;
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
index f4abfe2..19843ec 100644
--- a/drivers/tty/hvc/hvc_xen.c
+++ b/drivers/tty/hvc/hvc_xen.c
@@ -422,7 +422,7 @@ static int xencons_connect_backend(struct xenbus_device *dev,
 	return ret;
 }
 
-static int __devinit xencons_probe(struct xenbus_device *dev,
+static int xencons_probe(struct xenbus_device *dev,
 				  const struct xenbus_device_id *id)
 {
 	int ret, devid;
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index cab5c7a..8776357 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -330,12 +330,12 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp);
 static void hvcs_close(struct tty_struct *tty, struct file *filp);
 static void hvcs_hangup(struct tty_struct * tty);
 
-static int __devinit hvcs_probe(struct vio_dev *dev,
+static int hvcs_probe(struct vio_dev *dev,
 		const struct vio_device_id *id);
-static int __devexit hvcs_remove(struct vio_dev *dev);
+static int hvcs_remove(struct vio_dev *dev);
 static int __init hvcs_module_init(void);
 static void __exit hvcs_module_exit(void);
-static int __devinit hvcs_initialize(void);
+static int hvcs_initialize(void);
 
 #define HVCS_SCHED_READ	0x00000001
 #define HVCS_QUICK_READ	0x00000002
@@ -676,7 +676,7 @@ static int khvcsd(void *unused)
 	return 0;
 }
 
-static struct vio_device_id hvcs_driver_table[] __devinitdata= {
+static struct vio_device_id hvcs_driver_table[] = {
 	{"serial-server", "hvterm2"},
 	{ "", "" }
 };
@@ -756,7 +756,7 @@ static int hvcs_get_index(void)
 	return -1;
 }
 
-static int __devinit hvcs_probe(
+static int hvcs_probe(
 	struct vio_dev *dev,
 	const struct vio_device_id *id)
 {
@@ -835,7 +835,7 @@ static int __devinit hvcs_probe(
 	return 0;
 }
 
-static int __devexit hvcs_remove(struct vio_dev *dev)
+static int hvcs_remove(struct vio_dev *dev)
 {
 	struct hvcs_struct *hvcsd = dev_get_drvdata(&dev->dev);
 	unsigned long flags;
@@ -874,7 +874,7 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
 static struct vio_driver hvcs_vio_driver = {
 	.id_table	= hvcs_driver_table,
 	.probe		= hvcs_probe,
-	.remove		= __devexit_p(hvcs_remove),
+	.remove		= hvcs_remove,
 	.name		= hvcs_driver_name,
 };
 
@@ -1478,7 +1478,7 @@ static void hvcs_free_index_list(void)
 	hvcs_index_count = 0;
 }
 
-static int __devinit hvcs_initialize(void)
+static int hvcs_initialize(void)
 {
 	int rc, num_ttys_to_alloc;
 
@@ -1496,8 +1496,10 @@ static int __devinit hvcs_initialize(void)
 		num_ttys_to_alloc = hvcs_parm_num_devs;
 
 	hvcs_tty_driver = alloc_tty_driver(num_ttys_to_alloc);
-	if (!hvcs_tty_driver)
+	if (!hvcs_tty_driver) {
+		mutex_unlock(&hvcs_init_mutex);
 		return -ENOMEM;
+	}
 
 	if (hvcs_alloc_index_list(num_ttys_to_alloc)) {
 		rc = -ENOMEM;
diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c
index 5b95b4f..68357a6 100644
--- a/drivers/tty/hvc/hvsi.c
+++ b/drivers/tty/hvc/hvsi.c
@@ -1218,6 +1218,7 @@ static int __init hvsi_console_init(void)
 		if (hp->virq == 0) {
 			printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n",
 				__func__, irq[0]);
+			tty_port_destroy(&hp->port);
 			continue;
 		}
 
diff --git a/drivers/tty/ipwireless/network.c b/drivers/tty/ipwireless/network.c
index 57102e6..c0dfb64 100644
--- a/drivers/tty/ipwireless/network.c
+++ b/drivers/tty/ipwireless/network.c
@@ -352,6 +352,8 @@ static struct sk_buff *ipw_packet_received_skb(unsigned char *data,
 	}
 
 	skb = dev_alloc_skb(length + 4);
+	if (skb == NULL)
+		return NULL;
 	skb_reserve(skb, 2);
 	memcpy(skb_put(skb, length), data, length);
 
@@ -397,7 +399,8 @@ void ipwireless_network_packet_received(struct ipw_network *network,
 
 				/* Send the data to the ppp_generic module. */
 				skb = ipw_packet_received_skb(data, length);
-				ppp_input(network->ppp_channel, skb);
+				if (skb)
+					ppp_input(network->ppp_channel, skb);
 			} else
 				spin_unlock_irqrestore(&network->lock,
 						flags);
diff --git a/drivers/tty/ipwireless/setup_protocol.h b/drivers/tty/ipwireless/setup_protocol.h
index 9d6bcc7..002c34e 100644
--- a/drivers/tty/ipwireless/setup_protocol.h
+++ b/drivers/tty/ipwireless/setup_protocol.h
@@ -59,7 +59,7 @@ struct tl_setup_config_done_msg {
 	unsigned char sig_no;		/* TL_SETUP_SIGNO_CONFIG_DONE_MSG */
 } __attribute__ ((__packed__));
 
-/* Asyncronous messages */
+/* Asynchronous messages */
 struct tl_setup_open_msg {
 	unsigned char sig_no;		/* TL_SETUP_SIGNO_OPEN_MSG */
 	unsigned char port_no;
diff --git a/drivers/tty/ipwireless/tty.c b/drivers/tty/ipwireless/tty.c
index 160f0ad..2cde13d 100644
--- a/drivers/tty/ipwireless/tty.c
+++ b/drivers/tty/ipwireless/tty.c
@@ -566,6 +566,7 @@ void ipwireless_tty_free(struct ipw_tty *tty)
 			ipwireless_disassociate_network_ttys(network,
 							     ttyj->channel_idx);
 			tty_unregister_device(ipw_tty_driver, j);
+			tty_port_destroy(&ttyj->port);
 			ttys[j] = NULL;
 			mutex_unlock(&ttyj->ipw_tty_mutex);
 			kfree(ttyj);
diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c
index d7492e1..3205b2e 100644
--- a/drivers/tty/isicom.c
+++ b/drivers/tty/isicom.c
@@ -148,7 +148,7 @@
 #endif
 
 static int isicom_probe(struct pci_dev *, const struct pci_device_id *);
-static void __devexit isicom_remove(struct pci_dev *);
+static void isicom_remove(struct pci_dev *);
 
 static struct pci_device_id isicom_pci_tbl[] = {
 	{ PCI_DEVICE(VENDOR_ID, 0x2028) },
@@ -168,7 +168,7 @@ static struct pci_driver isicom_driver = {
 	.name		= "isicom",
 	.id_table	= isicom_pci_tbl,
 	.probe		= isicom_probe,
-	.remove		= __devexit_p(isicom_remove)
+	.remove		= isicom_remove
 };
 
 static int prev_card = 3;	/*	start servicing isi_card[0]	*/
@@ -603,7 +603,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
 			if (tty_port_cts_enabled(&port->port)) {
 				if (tty->hw_stopped) {
 					if (header & ISI_CTS) {
-						port->port.tty->hw_stopped = 0;
+						tty->hw_stopped = 0;
 						/* start tx ing */
 						port->status |= (ISI_TXOK
 							| ISI_CTS);
@@ -1307,7 +1307,7 @@ static const struct tty_port_operations isicom_port_ops = {
 	.shutdown		= isicom_shutdown,
 };
 
-static int __devinit reset_card(struct pci_dev *pdev,
+static int reset_card(struct pci_dev *pdev,
 	const unsigned int card, unsigned int *signature)
 {
 	struct isi_board *board = pci_get_drvdata(pdev);
@@ -1368,7 +1368,7 @@ end:
 	return retval;
 }
 
-static int __devinit load_firmware(struct pci_dev *pdev,
+static int load_firmware(struct pci_dev *pdev,
 	const unsigned int index, const unsigned int signature)
 {
 	struct isi_board *board = pci_get_drvdata(pdev);
@@ -1548,7 +1548,7 @@ end:
  */
 static unsigned int card_count;
 
-static int __devinit isicom_probe(struct pci_dev *pdev,
+static int isicom_probe(struct pci_dev *pdev,
 	const struct pci_device_id *ent)
 {
 	unsigned int uninitialized_var(signature), index;
@@ -1610,10 +1610,15 @@ static int __devinit isicom_probe(struct pci_dev *pdev,
 	if (retval < 0)
 		goto errunri;
 
-	for (index = 0; index < board->port_count; index++)
-		tty_port_register_device(&board->ports[index].port,
-				isicom_normal, board->index * 16 + index,
-				&pdev->dev);
+	for (index = 0; index < board->port_count; index++) {
+		struct tty_port *tport = &board->ports[index].port;
+		tty_port_init(tport);
+		tport->ops = &isicom_port_ops;
+		tport->close_delay = 50 * HZ/100;
+		tport->closing_wait = 3000 * HZ/100;
+		tty_port_register_device(tport, isicom_normal,
+				board->index * 16 + index, &pdev->dev);
+	}
 
 	return 0;
 
@@ -1630,13 +1635,15 @@ err:
 	return retval;
 }
 
-static void __devexit isicom_remove(struct pci_dev *pdev)
+static void isicom_remove(struct pci_dev *pdev)
 {
 	struct isi_board *board = pci_get_drvdata(pdev);
 	unsigned int i;
 
-	for (i = 0; i < board->port_count; i++)
+	for (i = 0; i < board->port_count; i++) {
 		tty_unregister_device(isicom_normal, board->index * 16 + i);
+		tty_port_destroy(&board->ports[i].port);
+	}
 
 	free_irq(board->irq, board);
 	pci_release_region(pdev, 3);
@@ -1655,13 +1662,9 @@ static int __init isicom_init(void)
 		isi_card[idx].ports = port;
 		spin_lock_init(&isi_card[idx].card_lock);
 		for (channel = 0; channel < 16; channel++, port++) {
-			tty_port_init(&port->port);
-			port->port.ops = &isicom_port_ops;
 			port->magic = ISICOM_MAGIC;
 			port->card = &isi_card[idx];
 			port->channel = channel;
-			port->port.close_delay = 50 * HZ/100;
-			port->port.closing_wait = 3000 * HZ/100;
 			port->status = 0;
 			/*  . . .  */
 		}
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
index 56e616b..f9d2850 100644
--- a/drivers/tty/moxa.c
+++ b/drivers/tty/moxa.c
@@ -895,6 +895,8 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
 
 	return 0;
 err_free:
+	for (i = 0; i < MAX_PORTS_PER_BOARD; i++)
+		tty_port_destroy(&brd->ports[i].port);
 	kfree(brd->ports);
 err:
 	return ret;
@@ -919,6 +921,8 @@ static void moxa_board_deinit(struct moxa_board_conf *brd)
 				tty_kref_put(tty);
 			}
 		}
+	for (a = 0; a < MAX_PORTS_PER_BOARD; a++)
+		tty_port_destroy(&brd->ports[a].port);
 	while (1) {
 		opened = 0;
 		for (a = 0; a < brd->numPorts; a++)
@@ -941,7 +945,7 @@ static void moxa_board_deinit(struct moxa_board_conf *brd)
 }
 
 #ifdef CONFIG_PCI
-static int __devinit moxa_pci_probe(struct pci_dev *pdev,
+static int moxa_pci_probe(struct pci_dev *pdev,
 		const struct pci_device_id *ent)
 {
 	struct moxa_board_conf *board;
@@ -1016,7 +1020,7 @@ err:
 	return retval;
 }
 
-static void __devexit moxa_pci_remove(struct pci_dev *pdev)
+static void moxa_pci_remove(struct pci_dev *pdev)
 {
 	struct moxa_board_conf *brd = pci_get_drvdata(pdev);
 
@@ -1029,7 +1033,7 @@ static struct pci_driver moxa_pci_driver = {
 	.name = "moxa",
 	.id_table = moxa_pcibrds,
 	.probe = moxa_pci_probe,
-	.remove = __devexit_p(moxa_pci_remove)
+	.remove = moxa_pci_remove
 };
 #endif /* CONFIG_PCI */
 
@@ -1370,7 +1374,7 @@ static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
         	p->DCDState = dcd;
         	spin_unlock_irqrestore(&p->port.lock, flags);
 		tty = tty_port_tty_get(&p->port);
-		if (tty && C_CLOCAL(tty) && !dcd)
+		if (tty && !C_CLOCAL(tty) && !dcd)
 			tty_hangup(tty);
 		tty_kref_put(tty);
 	}
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
index cfda47d..4011386 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -487,7 +487,7 @@ static void mxser_disable_must_rx_software_flow_control(unsigned long baseio)
 }
 
 #ifdef CONFIG_PCI
-static int __devinit CheckIsMoxaMust(unsigned long io)
+static int CheckIsMoxaMust(unsigned long io)
 {
 	u8 oldmcr, hwid;
 	int i;
@@ -2369,7 +2369,7 @@ static void mxser_release_ISA_res(struct mxser_board *brd)
 	mxser_release_vector(brd);
 }
 
-static int __devinit mxser_initbrd(struct mxser_board *brd,
+static int mxser_initbrd(struct mxser_board *brd,
 		struct pci_dev *pdev)
 {
 	struct mxser_port *info;
@@ -2411,14 +2411,27 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
 
 	retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser",
 			brd);
-	if (retval)
+	if (retval) {
+		for (i = 0; i < brd->info->nports; i++)
+			tty_port_destroy(&brd->ports[i].port);
 		printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
 			"conflict with another device.\n",
 			brd->info->name, brd->irq);
+	}
 
 	return retval;
 }
 
+static void mxser_board_remove(struct mxser_board *brd)
+{
+	unsigned int i;
+
+	for (i = 0; i < brd->info->nports; i++) {
+		tty_unregister_device(mxvar_sdriver, brd->idx + i);
+		tty_port_destroy(&brd->ports[i].port);
+	}
+}
+
 static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
 {
 	int id, i, bits, ret;
@@ -2534,7 +2547,7 @@ err_irqconflict:
 	return -EIO;
 }
 
-static int __devinit mxser_probe(struct pci_dev *pdev,
+static int mxser_probe(struct pci_dev *pdev,
 		const struct pci_device_id *ent)
 {
 #ifdef CONFIG_PCI
@@ -2645,14 +2658,12 @@ err:
 #endif
 }
 
-static void __devexit mxser_remove(struct pci_dev *pdev)
+static void mxser_remove(struct pci_dev *pdev)
 {
 #ifdef CONFIG_PCI
 	struct mxser_board *brd = pci_get_drvdata(pdev);
-	unsigned int i;
 
-	for (i = 0; i < brd->info->nports; i++)
-		tty_unregister_device(mxvar_sdriver, brd->idx + i);
+	mxser_board_remove(brd);
 
 	free_irq(pdev->irq, brd);
 	pci_release_region(pdev, 2);
@@ -2666,7 +2677,7 @@ static struct pci_driver mxser_driver = {
 	.name = "mxser",
 	.id_table = mxser_pcibrds,
 	.probe = mxser_probe,
-	.remove = __devexit_p(mxser_remove)
+	.remove = mxser_remove
 };
 
 static int __init mxser_module_init(void)
@@ -2748,15 +2759,13 @@ err_put:
 
 static void __exit mxser_module_exit(void)
 {
-	unsigned int i, j;
+	unsigned int i;
 
 	pci_unregister_driver(&mxser_driver);
 
 	for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */
 		if (mxser_boards[i].info != NULL)
-			for (j = 0; j < mxser_boards[i].info->nports; j++)
-				tty_unregister_device(mxvar_sdriver,
-						mxser_boards[i].idx + j);
+			mxser_board_remove(&mxser_boards[i]);
 	tty_unregister_driver(mxvar_sdriver);
 	put_tty_driver(mxvar_sdriver);
 
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 1e8e8ce..dcc0430 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -134,7 +134,6 @@ struct gsm_dlci {
 #define DLCI_OPENING		1	/* Sending SABM not seen UA */
 #define DLCI_OPEN		2	/* SABM/UA complete */
 #define DLCI_CLOSING		3	/* Sending DISC not seen UA/DM */
-	struct kref ref;		/* freed from port or mux close */
 	struct mutex mutex;
 
 	/* Link layer */
@@ -1635,7 +1634,6 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr)
 	if (dlci == NULL)
 		return NULL;
 	spin_lock_init(&dlci->lock);
-	kref_init(&dlci->ref);
 	mutex_init(&dlci->mutex);
 	dlci->fifo = &dlci->_fifo;
 	if (kfifo_alloc(&dlci->_fifo, 4096, GFP_KERNEL) < 0) {
@@ -1669,9 +1667,9 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr)
  *
  *	Can sleep.
  */
-static void gsm_dlci_free(struct kref *ref)
+static void gsm_dlci_free(struct tty_port *port)
 {
-	struct gsm_dlci *dlci = container_of(ref, struct gsm_dlci, ref);
+	struct gsm_dlci *dlci = container_of(port, struct gsm_dlci, port);
 
 	del_timer_sync(&dlci->t1);
 	dlci->gsm->dlci[dlci->addr] = NULL;
@@ -1683,12 +1681,12 @@ static void gsm_dlci_free(struct kref *ref)
 
 static inline void dlci_get(struct gsm_dlci *dlci)
 {
-	kref_get(&dlci->ref);
+	tty_port_get(&dlci->port);
 }
 
 static inline void dlci_put(struct gsm_dlci *dlci)
 {
-	kref_put(&dlci->ref, gsm_dlci_free);
+	tty_port_put(&dlci->port);
 }
 
 /**
@@ -2874,6 +2872,7 @@ static void gsm_dtr_rts(struct tty_port *port, int onoff)
 static const struct tty_port_operations gsm_port_ops = {
 	.carrier_raised = gsm_carrier_raised,
 	.dtr_rts = gsm_dtr_rts,
+	.destruct = gsm_dlci_free,
 };
 
 static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 8c0b7b4..19083ef 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -73,10 +73,42 @@
 #define ECHO_OP_SET_CANON_COL 0x81
 #define ECHO_OP_ERASE_TAB 0x82
 
+struct n_tty_data {
+	unsigned int column;
+	unsigned long overrun_time;
+	int num_overrun;
+
+	unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
+	unsigned char echo_overrun:1;
+
+	DECLARE_BITMAP(process_char_map, 256);
+	DECLARE_BITMAP(read_flags, N_TTY_BUF_SIZE);
+
+	char *read_buf;
+	int read_head;
+	int read_tail;
+	int read_cnt;
+
+	unsigned char *echo_buf;
+	unsigned int echo_pos;
+	unsigned int echo_cnt;
+
+	int canon_data;
+	unsigned long canon_head;
+	unsigned int canon_column;
+
+	struct mutex atomic_read_lock;
+	struct mutex output_lock;
+	struct mutex echo_lock;
+	spinlock_t read_lock;
+};
+
 static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
 			       unsigned char __user *ptr)
 {
-	tty_audit_add_data(tty, &x, 1);
+	struct n_tty_data *ldata = tty->disc_data;
+
+	tty_audit_add_data(tty, &x, 1, ldata->icanon);
 	return put_user(x, ptr);
 }
 
@@ -92,17 +124,18 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
 
 static void n_tty_set_room(struct tty_struct *tty)
 {
+	struct n_tty_data *ldata = tty->disc_data;
 	int left;
 	int old_left;
 
-	/* tty->read_cnt is not read locked ? */
+	/* ldata->read_cnt is not read locked ? */
 	if (I_PARMRK(tty)) {
 		/* Multiply read_cnt by 3, since each byte might take up to
 		 * three times as many spaces when PARMRK is set (depending on
 		 * its flags, e.g. parity error). */
-		left = N_TTY_BUF_SIZE - tty->read_cnt * 3 - 1;
+		left = N_TTY_BUF_SIZE - ldata->read_cnt * 3 - 1;
 	} else
-		left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+		left = N_TTY_BUF_SIZE - ldata->read_cnt - 1;
 
 	/*
 	 * If we are doing input canonicalization, and there are no
@@ -111,44 +144,47 @@ static void n_tty_set_room(struct tty_struct *tty)
 	 * characters will be beeped.
 	 */
 	if (left <= 0)
-		left = tty->icanon && !tty->canon_data;
+		left = ldata->icanon && !ldata->canon_data;
 	old_left = tty->receive_room;
 	tty->receive_room = left;
 
 	/* Did this open up the receive buffer? We may need to flip */
-	if (left && !old_left)
-		schedule_work(&tty->buf.work);
+	if (left && !old_left) {
+		WARN_RATELIMIT(tty->port->itty == NULL,
+				"scheduling with invalid itty\n");
+		schedule_work(&tty->port->buf.work);
+	}
 }
 
-static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
+static void put_tty_queue_nolock(unsigned char c, struct n_tty_data *ldata)
 {
-	if (tty->read_cnt < N_TTY_BUF_SIZE) {
-		tty->read_buf[tty->read_head] = c;
-		tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);
-		tty->read_cnt++;
+	if (ldata->read_cnt < N_TTY_BUF_SIZE) {
+		ldata->read_buf[ldata->read_head] = c;
+		ldata->read_head = (ldata->read_head + 1) & (N_TTY_BUF_SIZE-1);
+		ldata->read_cnt++;
 	}
 }
 
 /**
  *	put_tty_queue		-	add character to tty
  *	@c: character
- *	@tty: tty device
+ *	@ldata: n_tty data
  *
  *	Add a character to the tty read_buf queue. This is done under the
  *	read_lock to serialize character addition and also to protect us
  *	against parallel reads or flushes
  */
 
-static void put_tty_queue(unsigned char c, struct tty_struct *tty)
+static void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
 {
 	unsigned long flags;
 	/*
 	 *	The problem of stomping on the buffers ends here.
 	 *	Why didn't anyone see this one coming? --AJK
 	*/
-	spin_lock_irqsave(&tty->read_lock, flags);
-	put_tty_queue_nolock(c, tty);
-	spin_unlock_irqrestore(&tty->read_lock, flags);
+	spin_lock_irqsave(&ldata->read_lock, flags);
+	put_tty_queue_nolock(c, ldata);
+	spin_unlock_irqrestore(&ldata->read_lock, flags);
 }
 
 /**
@@ -179,18 +215,19 @@ static void check_unthrottle(struct tty_struct *tty)
 
 static void reset_buffer_flags(struct tty_struct *tty)
 {
+	struct n_tty_data *ldata = tty->disc_data;
 	unsigned long flags;
 
-	spin_lock_irqsave(&tty->read_lock, flags);
-	tty->read_head = tty->read_tail = tty->read_cnt = 0;
-	spin_unlock_irqrestore(&tty->read_lock, flags);
+	spin_lock_irqsave(&ldata->read_lock, flags);
+	ldata->read_head = ldata->read_tail = ldata->read_cnt = 0;
+	spin_unlock_irqrestore(&ldata->read_lock, flags);
 
-	mutex_lock(&tty->echo_lock);
-	tty->echo_pos = tty->echo_cnt = tty->echo_overrun = 0;
-	mutex_unlock(&tty->echo_lock);
+	mutex_lock(&ldata->echo_lock);
+	ldata->echo_pos = ldata->echo_cnt = ldata->echo_overrun = 0;
+	mutex_unlock(&ldata->echo_lock);
 
-	tty->canon_head = tty->canon_data = tty->erasing = 0;
-	memset(&tty->read_flags, 0, sizeof tty->read_flags);
+	ldata->canon_head = ldata->canon_data = ldata->erasing = 0;
+	bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
 	n_tty_set_room(tty);
 }
 
@@ -235,18 +272,19 @@ static void n_tty_flush_buffer(struct tty_struct *tty)
 
 static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
 {
+	struct n_tty_data *ldata = tty->disc_data;
 	unsigned long flags;
 	ssize_t n = 0;
 
-	spin_lock_irqsave(&tty->read_lock, flags);
-	if (!tty->icanon) {
-		n = tty->read_cnt;
-	} else if (tty->canon_data) {
-		n = (tty->canon_head > tty->read_tail) ?
-			tty->canon_head - tty->read_tail :
-			tty->canon_head + (N_TTY_BUF_SIZE - tty->read_tail);
+	spin_lock_irqsave(&ldata->read_lock, flags);
+	if (!ldata->icanon) {
+		n = ldata->read_cnt;
+	} else if (ldata->canon_data) {
+		n = (ldata->canon_head > ldata->read_tail) ?
+			ldata->canon_head - ldata->read_tail :
+			ldata->canon_head + (N_TTY_BUF_SIZE - ldata->read_tail);
 	}
-	spin_unlock_irqrestore(&tty->read_lock, flags);
+	spin_unlock_irqrestore(&ldata->read_lock, flags);
 	return n;
 }
 
@@ -301,6 +339,7 @@ static inline int is_continuation(unsigned char c, struct tty_struct *tty)
 
 static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
 {
+	struct n_tty_data *ldata = tty->disc_data;
 	int	spaces;
 
 	if (!space)
@@ -309,48 +348,48 @@ static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
 	switch (c) {
 	case '\n':
 		if (O_ONLRET(tty))
-			tty->column = 0;
+			ldata->column = 0;
 		if (O_ONLCR(tty)) {
 			if (space < 2)
 				return -1;
-			tty->canon_column = tty->column = 0;
+			ldata->canon_column = ldata->column = 0;
 			tty->ops->write(tty, "\r\n", 2);
 			return 2;
 		}
-		tty->canon_column = tty->column;
+		ldata->canon_column = ldata->column;
 		break;
 	case '\r':
-		if (O_ONOCR(tty) && tty->column == 0)
+		if (O_ONOCR(tty) && ldata->column == 0)
 			return 0;
 		if (O_OCRNL(tty)) {
 			c = '\n';
 			if (O_ONLRET(tty))
-				tty->canon_column = tty->column = 0;
+				ldata->canon_column = ldata->column = 0;
 			break;
 		}
-		tty->canon_column = tty->column = 0;
+		ldata->canon_column = ldata->column = 0;
 		break;
 	case '\t':
-		spaces = 8 - (tty->column & 7);
+		spaces = 8 - (ldata->column & 7);
 		if (O_TABDLY(tty) == XTABS) {
 			if (space < spaces)
 				return -1;
-			tty->column += spaces;
+			ldata->column += spaces;
 			tty->ops->write(tty, "        ", spaces);
 			return spaces;
 		}
-		tty->column += spaces;
+		ldata->column += spaces;
 		break;
 	case '\b':
-		if (tty->column > 0)
-			tty->column--;
+		if (ldata->column > 0)
+			ldata->column--;
 		break;
 	default:
 		if (!iscntrl(c)) {
 			if (O_OLCUC(tty))
 				c = toupper(c);
 			if (!is_continuation(c, tty))
-				tty->column++;
+				ldata->column++;
 		}
 		break;
 	}
@@ -375,14 +414,15 @@ static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
 
 static int process_output(unsigned char c, struct tty_struct *tty)
 {
+	struct n_tty_data *ldata = tty->disc_data;
 	int	space, retval;
 
-	mutex_lock(&tty->output_lock);
+	mutex_lock(&ldata->output_lock);
 
 	space = tty_write_room(tty);
 	retval = do_output_char(c, tty, space);
 
-	mutex_unlock(&tty->output_lock);
+	mutex_unlock(&ldata->output_lock);
 	if (retval < 0)
 		return -1;
 	else
@@ -411,15 +451,16 @@ static int process_output(unsigned char c, struct tty_struct *tty)
 static ssize_t process_output_block(struct tty_struct *tty,
 				    const unsigned char *buf, unsigned int nr)
 {
+	struct n_tty_data *ldata = tty->disc_data;
 	int	space;
 	int	i;
 	const unsigned char *cp;
 
-	mutex_lock(&tty->output_lock);
+	mutex_lock(&ldata->output_lock);
 
 	space = tty_write_room(tty);
 	if (!space) {
-		mutex_unlock(&tty->output_lock);
+		mutex_unlock(&ldata->output_lock);
 		return 0;
 	}
 	if (nr > space)
@@ -431,30 +472,30 @@ static ssize_t process_output_block(struct tty_struct *tty,
 		switch (c) {
 		case '\n':
 			if (O_ONLRET(tty))
-				tty->column = 0;
+				ldata->column = 0;
 			if (O_ONLCR(tty))
 				goto break_out;
-			tty->canon_column = tty->column;
+			ldata->canon_column = ldata->column;
 			break;
 		case '\r':
-			if (O_ONOCR(tty) && tty->column == 0)
+			if (O_ONOCR(tty) && ldata->column == 0)
 				goto break_out;
 			if (O_OCRNL(tty))
 				goto break_out;
-			tty->canon_column = tty->column = 0;
+			ldata->canon_column = ldata->column = 0;
 			break;
 		case '\t':
 			goto break_out;
 		case '\b':
-			if (tty->column > 0)
-				tty->column--;
+			if (ldata->column > 0)
+				ldata->column--;
 			break;
 		default:
 			if (!iscntrl(c)) {
 				if (O_OLCUC(tty))
 					goto break_out;
 				if (!is_continuation(c, tty))
-					tty->column++;
+					ldata->column++;
 			}
 			break;
 		}
@@ -462,7 +503,7 @@ static ssize_t process_output_block(struct tty_struct *tty,
 break_out:
 	i = tty->ops->write(tty, buf, i);
 
-	mutex_unlock(&tty->output_lock);
+	mutex_unlock(&ldata->output_lock);
 	return i;
 }
 
@@ -494,21 +535,22 @@ break_out:
 
 static void process_echoes(struct tty_struct *tty)
 {
+	struct n_tty_data *ldata = tty->disc_data;
 	int	space, nr;
 	unsigned char c;
 	unsigned char *cp, *buf_end;
 
-	if (!tty->echo_cnt)
+	if (!ldata->echo_cnt)
 		return;
 
-	mutex_lock(&tty->output_lock);
-	mutex_lock(&tty->echo_lock);
+	mutex_lock(&ldata->output_lock);
+	mutex_lock(&ldata->echo_lock);
 
 	space = tty_write_room(tty);
 
-	buf_end = tty->echo_buf + N_TTY_BUF_SIZE;
-	cp = tty->echo_buf + tty->echo_pos;
-	nr = tty->echo_cnt;
+	buf_end = ldata->echo_buf + N_TTY_BUF_SIZE;
+	cp = ldata->echo_buf + ldata->echo_pos;
+	nr = ldata->echo_cnt;
 	while (nr > 0) {
 		c = *cp;
 		if (c == ECHO_OP_START) {
@@ -545,7 +587,7 @@ static void process_echoes(struct tty_struct *tty)
 				 * Otherwise, tab spacing is normal.
 				 */
 				if (!(num_chars & 0x80))
-					num_chars += tty->canon_column;
+					num_chars += ldata->canon_column;
 				num_bs = 8 - (num_chars & 7);
 
 				if (num_bs > space) {
@@ -555,22 +597,22 @@ static void process_echoes(struct tty_struct *tty)
 				space -= num_bs;
 				while (num_bs--) {
 					tty_put_char(tty, '\b');
-					if (tty->column > 0)
-						tty->column--;
+					if (ldata->column > 0)
+						ldata->column--;
 				}
 				cp += 3;
 				nr -= 3;
 				break;
 
 			case ECHO_OP_SET_CANON_COL:
-				tty->canon_column = tty->column;
+				ldata->canon_column = ldata->column;
 				cp += 2;
 				nr -= 2;
 				break;
 
 			case ECHO_OP_MOVE_BACK_COL:
-				if (tty->column > 0)
-					tty->column--;
+				if (ldata->column > 0)
+					ldata->column--;
 				cp += 2;
 				nr -= 2;
 				break;
@@ -582,7 +624,7 @@ static void process_echoes(struct tty_struct *tty)
 					break;
 				}
 				tty_put_char(tty, ECHO_OP_START);
-				tty->column++;
+				ldata->column++;
 				space--;
 				cp += 2;
 				nr -= 2;
@@ -604,7 +646,7 @@ static void process_echoes(struct tty_struct *tty)
 				}
 				tty_put_char(tty, '^');
 				tty_put_char(tty, op ^ 0100);
-				tty->column += 2;
+				ldata->column += 2;
 				space -= 2;
 				cp += 2;
 				nr -= 2;
@@ -635,20 +677,20 @@ static void process_echoes(struct tty_struct *tty)
 	}
 
 	if (nr == 0) {
-		tty->echo_pos = 0;
-		tty->echo_cnt = 0;
-		tty->echo_overrun = 0;
+		ldata->echo_pos = 0;
+		ldata->echo_cnt = 0;
+		ldata->echo_overrun = 0;
 	} else {
-		int num_processed = tty->echo_cnt - nr;
-		tty->echo_pos += num_processed;
-		tty->echo_pos &= N_TTY_BUF_SIZE - 1;
-		tty->echo_cnt = nr;
+		int num_processed = ldata->echo_cnt - nr;
+		ldata->echo_pos += num_processed;
+		ldata->echo_pos &= N_TTY_BUF_SIZE - 1;
+		ldata->echo_cnt = nr;
 		if (num_processed > 0)
-			tty->echo_overrun = 0;
+			ldata->echo_overrun = 0;
 	}
 
-	mutex_unlock(&tty->echo_lock);
-	mutex_unlock(&tty->output_lock);
+	mutex_unlock(&ldata->echo_lock);
+	mutex_unlock(&ldata->output_lock);
 
 	if (tty->ops->flush_chars)
 		tty->ops->flush_chars(tty);
@@ -657,72 +699,70 @@ static void process_echoes(struct tty_struct *tty)
 /**
  *	add_echo_byte	-	add a byte to the echo buffer
  *	@c: unicode byte to echo
- *	@tty: terminal device
+ *	@ldata: n_tty data
  *
  *	Add a character or operation byte to the echo buffer.
  *
  *	Should be called under the echo lock to protect the echo buffer.
  */
 
-static void add_echo_byte(unsigned char c, struct tty_struct *tty)
+static void add_echo_byte(unsigned char c, struct n_tty_data *ldata)
 {
 	int	new_byte_pos;
 
-	if (tty->echo_cnt == N_TTY_BUF_SIZE) {
+	if (ldata->echo_cnt == N_TTY_BUF_SIZE) {
 		/* Circular buffer is already at capacity */
-		new_byte_pos = tty->echo_pos;
+		new_byte_pos = ldata->echo_pos;
 
 		/*
 		 * Since the buffer start position needs to be advanced,
 		 * be sure to step by a whole operation byte group.
 		 */
-		if (tty->echo_buf[tty->echo_pos] == ECHO_OP_START) {
-			if (tty->echo_buf[(tty->echo_pos + 1) &
+		if (ldata->echo_buf[ldata->echo_pos] == ECHO_OP_START) {
+			if (ldata->echo_buf[(ldata->echo_pos + 1) &
 					  (N_TTY_BUF_SIZE - 1)] ==
 						ECHO_OP_ERASE_TAB) {
-				tty->echo_pos += 3;
-				tty->echo_cnt -= 2;
+				ldata->echo_pos += 3;
+				ldata->echo_cnt -= 2;
 			} else {
-				tty->echo_pos += 2;
-				tty->echo_cnt -= 1;
+				ldata->echo_pos += 2;
+				ldata->echo_cnt -= 1;
 			}
 		} else {
-			tty->echo_pos++;
+			ldata->echo_pos++;
 		}
-		tty->echo_pos &= N_TTY_BUF_SIZE - 1;
+		ldata->echo_pos &= N_TTY_BUF_SIZE - 1;
 
-		tty->echo_overrun = 1;
+		ldata->echo_overrun = 1;
 	} else {
-		new_byte_pos = tty->echo_pos + tty->echo_cnt;
+		new_byte_pos = ldata->echo_pos + ldata->echo_cnt;
 		new_byte_pos &= N_TTY_BUF_SIZE - 1;
-		tty->echo_cnt++;
+		ldata->echo_cnt++;
 	}
 
-	tty->echo_buf[new_byte_pos] = c;
+	ldata->echo_buf[new_byte_pos] = c;
 }
 
 /**
  *	echo_move_back_col	-	add operation to move back a column
- *	@tty: terminal device
+ *	@ldata: n_tty data
  *
  *	Add an operation to the echo buffer to move back one column.
  *
  *	Locking: echo_lock to protect the echo buffer
  */
 
-static void echo_move_back_col(struct tty_struct *tty)
+static void echo_move_back_col(struct n_tty_data *ldata)
 {
-	mutex_lock(&tty->echo_lock);
-
-	add_echo_byte(ECHO_OP_START, tty);
-	add_echo_byte(ECHO_OP_MOVE_BACK_COL, tty);
-
-	mutex_unlock(&tty->echo_lock);
+	mutex_lock(&ldata->echo_lock);
+	add_echo_byte(ECHO_OP_START, ldata);
+	add_echo_byte(ECHO_OP_MOVE_BACK_COL, ldata);
+	mutex_unlock(&ldata->echo_lock);
 }
 
 /**
  *	echo_set_canon_col	-	add operation to set the canon column
- *	@tty: terminal device
+ *	@ldata: n_tty data
  *
  *	Add an operation to the echo buffer to set the canon column
  *	to the current column.
@@ -730,21 +770,19 @@ static void echo_move_back_col(struct tty_struct *tty)
  *	Locking: echo_lock to protect the echo buffer
  */
 
-static void echo_set_canon_col(struct tty_struct *tty)
+static void echo_set_canon_col(struct n_tty_data *ldata)
 {
-	mutex_lock(&tty->echo_lock);
-
-	add_echo_byte(ECHO_OP_START, tty);
-	add_echo_byte(ECHO_OP_SET_CANON_COL, tty);
-
-	mutex_unlock(&tty->echo_lock);
+	mutex_lock(&ldata->echo_lock);
+	add_echo_byte(ECHO_OP_START, ldata);
+	add_echo_byte(ECHO_OP_SET_CANON_COL, ldata);
+	mutex_unlock(&ldata->echo_lock);
 }
 
 /**
  *	echo_erase_tab	-	add operation to erase a tab
  *	@num_chars: number of character columns already used
  *	@after_tab: true if num_chars starts after a previous tab
- *	@tty: terminal device
+ *	@ldata: n_tty data
  *
  *	Add an operation to the echo buffer to erase a tab.
  *
@@ -758,12 +796,12 @@ static void echo_set_canon_col(struct tty_struct *tty)
  */
 
 static void echo_erase_tab(unsigned int num_chars, int after_tab,
-			   struct tty_struct *tty)
+			   struct n_tty_data *ldata)
 {
-	mutex_lock(&tty->echo_lock);
+	mutex_lock(&ldata->echo_lock);
 
-	add_echo_byte(ECHO_OP_START, tty);
-	add_echo_byte(ECHO_OP_ERASE_TAB, tty);
+	add_echo_byte(ECHO_OP_START, ldata);
+	add_echo_byte(ECHO_OP_ERASE_TAB, ldata);
 
 	/* We only need to know this modulo 8 (tab spacing) */
 	num_chars &= 7;
@@ -772,9 +810,9 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab,
 	if (after_tab)
 		num_chars |= 0x80;
 
-	add_echo_byte(num_chars, tty);
+	add_echo_byte(num_chars, ldata);
 
-	mutex_unlock(&tty->echo_lock);
+	mutex_unlock(&ldata->echo_lock);
 }
 
 /**
@@ -790,18 +828,16 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab,
  *	Locking: echo_lock to protect the echo buffer
  */
 
-static void echo_char_raw(unsigned char c, struct tty_struct *tty)
+static void echo_char_raw(unsigned char c, struct n_tty_data *ldata)
 {
-	mutex_lock(&tty->echo_lock);
-
+	mutex_lock(&ldata->echo_lock);
 	if (c == ECHO_OP_START) {
-		add_echo_byte(ECHO_OP_START, tty);
-		add_echo_byte(ECHO_OP_START, tty);
+		add_echo_byte(ECHO_OP_START, ldata);
+		add_echo_byte(ECHO_OP_START, ldata);
 	} else {
-		add_echo_byte(c, tty);
+		add_echo_byte(c, ldata);
 	}
-
-	mutex_unlock(&tty->echo_lock);
+	mutex_unlock(&ldata->echo_lock);
 }
 
 /**
@@ -820,30 +856,32 @@ static void echo_char_raw(unsigned char c, struct tty_struct *tty)
 
 static void echo_char(unsigned char c, struct tty_struct *tty)
 {
-	mutex_lock(&tty->echo_lock);
+	struct n_tty_data *ldata = tty->disc_data;
+
+	mutex_lock(&ldata->echo_lock);
 
 	if (c == ECHO_OP_START) {
-		add_echo_byte(ECHO_OP_START, tty);
-		add_echo_byte(ECHO_OP_START, tty);
+		add_echo_byte(ECHO_OP_START, ldata);
+		add_echo_byte(ECHO_OP_START, ldata);
 	} else {
 		if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t')
-			add_echo_byte(ECHO_OP_START, tty);
-		add_echo_byte(c, tty);
+			add_echo_byte(ECHO_OP_START, ldata);
+		add_echo_byte(c, ldata);
 	}
 
-	mutex_unlock(&tty->echo_lock);
+	mutex_unlock(&ldata->echo_lock);
 }
 
 /**
  *	finish_erasing		-	complete erase
- *	@tty: tty doing the erase
+ *	@ldata: n_tty data
  */
 
-static inline void finish_erasing(struct tty_struct *tty)
+static inline void finish_erasing(struct n_tty_data *ldata)
 {
-	if (tty->erasing) {
-		echo_char_raw('/', tty);
-		tty->erasing = 0;
+	if (ldata->erasing) {
+		echo_char_raw('/', ldata);
+		ldata->erasing = 0;
 	}
 }
 
@@ -861,12 +899,13 @@ static inline void finish_erasing(struct tty_struct *tty)
 
 static void eraser(unsigned char c, struct tty_struct *tty)
 {
+	struct n_tty_data *ldata = tty->disc_data;
 	enum { ERASE, WERASE, KILL } kill_type;
 	int head, seen_alnums, cnt;
 	unsigned long flags;
 
 	/* FIXME: locking needed ? */
-	if (tty->read_head == tty->canon_head) {
+	if (ldata->read_head == ldata->canon_head) {
 		/* process_output('\a', tty); */ /* what do you think? */
 		return;
 	}
@@ -876,24 +915,24 @@ static void eraser(unsigned char c, struct tty_struct *tty)
 		kill_type = WERASE;
 	else {
 		if (!L_ECHO(tty)) {
-			spin_lock_irqsave(&tty->read_lock, flags);
-			tty->read_cnt -= ((tty->read_head - tty->canon_head) &
+			spin_lock_irqsave(&ldata->read_lock, flags);
+			ldata->read_cnt -= ((ldata->read_head - ldata->canon_head) &
 					  (N_TTY_BUF_SIZE - 1));
-			tty->read_head = tty->canon_head;
-			spin_unlock_irqrestore(&tty->read_lock, flags);
+			ldata->read_head = ldata->canon_head;
+			spin_unlock_irqrestore(&ldata->read_lock, flags);
 			return;
 		}
 		if (!L_ECHOK(tty) || !L_ECHOKE(tty) || !L_ECHOE(tty)) {
-			spin_lock_irqsave(&tty->read_lock, flags);
-			tty->read_cnt -= ((tty->read_head - tty->canon_head) &
+			spin_lock_irqsave(&ldata->read_lock, flags);
+			ldata->read_cnt -= ((ldata->read_head - ldata->canon_head) &
 					  (N_TTY_BUF_SIZE - 1));
-			tty->read_head = tty->canon_head;
-			spin_unlock_irqrestore(&tty->read_lock, flags);
-			finish_erasing(tty);
+			ldata->read_head = ldata->canon_head;
+			spin_unlock_irqrestore(&ldata->read_lock, flags);
+			finish_erasing(ldata);
 			echo_char(KILL_CHAR(tty), tty);
 			/* Add a newline if ECHOK is on and ECHOKE is off. */
 			if (L_ECHOK(tty))
-				echo_char_raw('\n', tty);
+				echo_char_raw('\n', ldata);
 			return;
 		}
 		kill_type = KILL;
@@ -901,14 +940,14 @@ static void eraser(unsigned char c, struct tty_struct *tty)
 
 	seen_alnums = 0;
 	/* FIXME: Locking ?? */
-	while (tty->read_head != tty->canon_head) {
-		head = tty->read_head;
+	while (ldata->read_head != ldata->canon_head) {
+		head = ldata->read_head;
 
 		/* erase a single possibly multibyte character */
 		do {
 			head = (head - 1) & (N_TTY_BUF_SIZE-1);
-			c = tty->read_buf[head];
-		} while (is_continuation(c, tty) && head != tty->canon_head);
+			c = ldata->read_buf[head];
+		} while (is_continuation(c, tty) && head != ldata->canon_head);
 
 		/* do not partially erase */
 		if (is_continuation(c, tty))
@@ -921,30 +960,31 @@ static void eraser(unsigned char c, struct tty_struct *tty)
 			else if (seen_alnums)
 				break;
 		}
-		cnt = (tty->read_head - head) & (N_TTY_BUF_SIZE-1);
-		spin_lock_irqsave(&tty->read_lock, flags);
-		tty->read_head = head;
-		tty->read_cnt -= cnt;
-		spin_unlock_irqrestore(&tty->read_lock, flags);
+		cnt = (ldata->read_head - head) & (N_TTY_BUF_SIZE-1);
+		spin_lock_irqsave(&ldata->read_lock, flags);
+		ldata->read_head = head;
+		ldata->read_cnt -= cnt;
+		spin_unlock_irqrestore(&ldata->read_lock, flags);
 		if (L_ECHO(tty)) {
 			if (L_ECHOPRT(tty)) {
-				if (!tty->erasing) {
-					echo_char_raw('\\', tty);
-					tty->erasing = 1;
+				if (!ldata->erasing) {
+					echo_char_raw('\\', ldata);
+					ldata->erasing = 1;
 				}
 				/* if cnt > 1, output a multi-byte character */
 				echo_char(c, tty);
 				while (--cnt > 0) {
 					head = (head+1) & (N_TTY_BUF_SIZE-1);
-					echo_char_raw(tty->read_buf[head], tty);
-					echo_move_back_col(tty);
+					echo_char_raw(ldata->read_buf[head],
+							ldata);
+					echo_move_back_col(ldata);
 				}
 			} else if (kill_type == ERASE && !L_ECHOE(tty)) {
 				echo_char(ERASE_CHAR(tty), tty);
 			} else if (c == '\t') {
 				unsigned int num_chars = 0;
 				int after_tab = 0;
-				unsigned long tail = tty->read_head;
+				unsigned long tail = ldata->read_head;
 
 				/*
 				 * Count the columns used for characters
@@ -953,9 +993,9 @@ static void eraser(unsigned char c, struct tty_struct *tty)
 				 * This info is used to go back the correct
 				 * number of columns.
 				 */
-				while (tail != tty->canon_head) {
+				while (tail != ldata->canon_head) {
 					tail = (tail-1) & (N_TTY_BUF_SIZE-1);
-					c = tty->read_buf[tail];
+					c = ldata->read_buf[tail];
 					if (c == '\t') {
 						after_tab = 1;
 						break;
@@ -966,25 +1006,25 @@ static void eraser(unsigned char c, struct tty_struct *tty)
 						num_chars++;
 					}
 				}
-				echo_erase_tab(num_chars, after_tab, tty);
+				echo_erase_tab(num_chars, after_tab, ldata);
 			} else {
 				if (iscntrl(c) && L_ECHOCTL(tty)) {
-					echo_char_raw('\b', tty);
-					echo_char_raw(' ', tty);
-					echo_char_raw('\b', tty);
+					echo_char_raw('\b', ldata);
+					echo_char_raw(' ', ldata);
+					echo_char_raw('\b', ldata);
 				}
 				if (!iscntrl(c) || L_ECHOCTL(tty)) {
-					echo_char_raw('\b', tty);
-					echo_char_raw(' ', tty);
-					echo_char_raw('\b', tty);
+					echo_char_raw('\b', ldata);
+					echo_char_raw(' ', ldata);
+					echo_char_raw('\b', ldata);
 				}
 			}
 		}
 		if (kill_type == ERASE)
 			break;
 	}
-	if (tty->read_head == tty->canon_head && L_ECHO(tty))
-		finish_erasing(tty);
+	if (ldata->read_head == ldata->canon_head && L_ECHO(tty))
+		finish_erasing(ldata);
 }
 
 /**
@@ -1023,6 +1063,8 @@ static inline void isig(int sig, struct tty_struct *tty, int flush)
 
 static inline void n_tty_receive_break(struct tty_struct *tty)
 {
+	struct n_tty_data *ldata = tty->disc_data;
+
 	if (I_IGNBRK(tty))
 		return;
 	if (I_BRKINT(tty)) {
@@ -1030,10 +1072,10 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
 		return;
 	}
 	if (I_PARMRK(tty)) {
-		put_tty_queue('\377', tty);
-		put_tty_queue('\0', tty);
+		put_tty_queue('\377', ldata);
+		put_tty_queue('\0', ldata);
 	}
-	put_tty_queue('\0', tty);
+	put_tty_queue('\0', ldata);
 	wake_up_interruptible(&tty->read_wait);
 }
 
@@ -1052,16 +1094,17 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
 
 static inline void n_tty_receive_overrun(struct tty_struct *tty)
 {
+	struct n_tty_data *ldata = tty->disc_data;
 	char buf[64];
 
-	tty->num_overrun++;
-	if (time_before(tty->overrun_time, jiffies - HZ) ||
-			time_after(tty->overrun_time, jiffies)) {
+	ldata->num_overrun++;
+	if (time_after(jiffies, ldata->overrun_time + HZ) ||
+			time_after(ldata->overrun_time, jiffies)) {
 		printk(KERN_WARNING "%s: %d input overrun(s)\n",
 			tty_name(tty, buf),
-			tty->num_overrun);
-		tty->overrun_time = jiffies;
-		tty->num_overrun = 0;
+			ldata->num_overrun);
+		ldata->overrun_time = jiffies;
+		ldata->num_overrun = 0;
 	}
 }
 
@@ -1076,16 +1119,18 @@ static inline void n_tty_receive_overrun(struct tty_struct *tty)
 static inline void n_tty_receive_parity_error(struct tty_struct *tty,
 					      unsigned char c)
 {
+	struct n_tty_data *ldata = tty->disc_data;
+
 	if (I_IGNPAR(tty))
 		return;
 	if (I_PARMRK(tty)) {
-		put_tty_queue('\377', tty);
-		put_tty_queue('\0', tty);
-		put_tty_queue(c, tty);
+		put_tty_queue('\377', ldata);
+		put_tty_queue('\0', ldata);
+		put_tty_queue(c, ldata);
 	} else	if (I_INPCK(tty))
-		put_tty_queue('\0', tty);
+		put_tty_queue('\0', ldata);
 	else
-		put_tty_queue(c, tty);
+		put_tty_queue(c, ldata);
 	wake_up_interruptible(&tty->read_wait);
 }
 
@@ -1101,11 +1146,12 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty,
 
 static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
 {
+	struct n_tty_data *ldata = tty->disc_data;
 	unsigned long flags;
 	int parmrk;
 
-	if (tty->raw) {
-		put_tty_queue(c, tty);
+	if (ldata->raw) {
+		put_tty_queue(c, ldata);
 		return;
 	}
 
@@ -1115,7 +1161,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
 		c = tolower(c);
 
 	if (L_EXTPROC(tty)) {
-		put_tty_queue(c, tty);
+		put_tty_queue(c, ldata);
 		return;
 	}
 
@@ -1143,26 +1189,26 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
 	 * handle specially, do shortcut processing to speed things
 	 * up.
 	 */
-	if (!test_bit(c, tty->process_char_map) || tty->lnext) {
-		tty->lnext = 0;
+	if (!test_bit(c, ldata->process_char_map) || ldata->lnext) {
+		ldata->lnext = 0;
 		parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
-		if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
+		if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
 			/* beep if no space */
 			if (L_ECHO(tty))
 				process_output('\a', tty);
 			return;
 		}
 		if (L_ECHO(tty)) {
-			finish_erasing(tty);
+			finish_erasing(ldata);
 			/* Record the column of first canon char. */
-			if (tty->canon_head == tty->read_head)
-				echo_set_canon_col(tty);
+			if (ldata->canon_head == ldata->read_head)
+				echo_set_canon_col(ldata);
 			echo_char(c, tty);
 			process_echoes(tty);
 		}
 		if (parmrk)
-			put_tty_queue(c, tty);
-		put_tty_queue(c, tty);
+			put_tty_queue(c, ldata);
+		put_tty_queue(c, ldata);
 		return;
 	}
 
@@ -1218,7 +1264,7 @@ send_signal:
 	} else if (c == '\n' && I_INLCR(tty))
 		c = '\r';
 
-	if (tty->icanon) {
+	if (ldata->icanon) {
 		if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
 		    (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
 			eraser(c, tty);
@@ -1226,12 +1272,12 @@ send_signal:
 			return;
 		}
 		if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {
-			tty->lnext = 1;
+			ldata->lnext = 1;
 			if (L_ECHO(tty)) {
-				finish_erasing(tty);
+				finish_erasing(ldata);
 				if (L_ECHOCTL(tty)) {
-					echo_char_raw('^', tty);
-					echo_char_raw('\b', tty);
+					echo_char_raw('^', ldata);
+					echo_char_raw('\b', ldata);
 					process_echoes(tty);
 				}
 			}
@@ -1239,34 +1285,34 @@ send_signal:
 		}
 		if (c == REPRINT_CHAR(tty) && L_ECHO(tty) &&
 		    L_IEXTEN(tty)) {
-			unsigned long tail = tty->canon_head;
+			unsigned long tail = ldata->canon_head;
 
-			finish_erasing(tty);
+			finish_erasing(ldata);
 			echo_char(c, tty);
-			echo_char_raw('\n', tty);
-			while (tail != tty->read_head) {
-				echo_char(tty->read_buf[tail], tty);
+			echo_char_raw('\n', ldata);
+			while (tail != ldata->read_head) {
+				echo_char(ldata->read_buf[tail], tty);
 				tail = (tail+1) & (N_TTY_BUF_SIZE-1);
 			}
 			process_echoes(tty);
 			return;
 		}
 		if (c == '\n') {
-			if (tty->read_cnt >= N_TTY_BUF_SIZE) {
+			if (ldata->read_cnt >= N_TTY_BUF_SIZE) {
 				if (L_ECHO(tty))
 					process_output('\a', tty);
 				return;
 			}
 			if (L_ECHO(tty) || L_ECHONL(tty)) {
-				echo_char_raw('\n', tty);
+				echo_char_raw('\n', ldata);
 				process_echoes(tty);
 			}
 			goto handle_newline;
 		}
 		if (c == EOF_CHAR(tty)) {
-			if (tty->read_cnt >= N_TTY_BUF_SIZE)
+			if (ldata->read_cnt >= N_TTY_BUF_SIZE)
 				return;
-			if (tty->canon_head != tty->read_head)
+			if (ldata->canon_head != ldata->read_head)
 				set_bit(TTY_PUSH, &tty->flags);
 			c = __DISABLED_CHAR;
 			goto handle_newline;
@@ -1275,7 +1321,7 @@ send_signal:
 		    (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) {
 			parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty))
 				 ? 1 : 0;
-			if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk)) {
+			if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk)) {
 				if (L_ECHO(tty))
 					process_output('\a', tty);
 				return;
@@ -1285,8 +1331,8 @@ send_signal:
 			 */
 			if (L_ECHO(tty)) {
 				/* Record the column of first canon char. */
-				if (tty->canon_head == tty->read_head)
-					echo_set_canon_col(tty);
+				if (ldata->canon_head == ldata->read_head)
+					echo_set_canon_col(ldata);
 				echo_char(c, tty);
 				process_echoes(tty);
 			}
@@ -1295,15 +1341,15 @@ send_signal:
 			 * EOL_CHAR and EOL2_CHAR?
 			 */
 			if (parmrk)
-				put_tty_queue(c, tty);
+				put_tty_queue(c, ldata);
 
 handle_newline:
-			spin_lock_irqsave(&tty->read_lock, flags);
-			set_bit(tty->read_head, tty->read_flags);
-			put_tty_queue_nolock(c, tty);
-			tty->canon_head = tty->read_head;
-			tty->canon_data++;
-			spin_unlock_irqrestore(&tty->read_lock, flags);
+			spin_lock_irqsave(&ldata->read_lock, flags);
+			set_bit(ldata->read_head, ldata->read_flags);
+			put_tty_queue_nolock(c, ldata);
+			ldata->canon_head = ldata->read_head;
+			ldata->canon_data++;
+			spin_unlock_irqrestore(&ldata->read_lock, flags);
 			kill_fasync(&tty->fasync, SIGIO, POLL_IN);
 			if (waitqueue_active(&tty->read_wait))
 				wake_up_interruptible(&tty->read_wait);
@@ -1312,29 +1358,29 @@ handle_newline:
 	}
 
 	parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
-	if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
+	if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
 		/* beep if no space */
 		if (L_ECHO(tty))
 			process_output('\a', tty);
 		return;
 	}
 	if (L_ECHO(tty)) {
-		finish_erasing(tty);
+		finish_erasing(ldata);
 		if (c == '\n')
-			echo_char_raw('\n', tty);
+			echo_char_raw('\n', ldata);
 		else {
 			/* Record the column of first canon char. */
-			if (tty->canon_head == tty->read_head)
-				echo_set_canon_col(tty);
+			if (ldata->canon_head == ldata->read_head)
+				echo_set_canon_col(ldata);
 			echo_char(c, tty);
 		}
 		process_echoes(tty);
 	}
 
 	if (parmrk)
-		put_tty_queue(c, tty);
+		put_tty_queue(c, ldata);
 
-	put_tty_queue(c, tty);
+	put_tty_queue(c, ldata);
 }
 
 
@@ -1369,33 +1415,31 @@ static void n_tty_write_wakeup(struct tty_struct *tty)
 static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 			      char *fp, int count)
 {
+	struct n_tty_data *ldata = tty->disc_data;
 	const unsigned char *p;
 	char *f, flags = TTY_NORMAL;
 	int	i;
 	char	buf[64];
 	unsigned long cpuflags;
 
-	if (!tty->read_buf)
-		return;
-
-	if (tty->real_raw) {
-		spin_lock_irqsave(&tty->read_lock, cpuflags);
-		i = min(N_TTY_BUF_SIZE - tty->read_cnt,
-			N_TTY_BUF_SIZE - tty->read_head);
+	if (ldata->real_raw) {
+		spin_lock_irqsave(&ldata->read_lock, cpuflags);
+		i = min(N_TTY_BUF_SIZE - ldata->read_cnt,
+			N_TTY_BUF_SIZE - ldata->read_head);
 		i = min(count, i);
-		memcpy(tty->read_buf + tty->read_head, cp, i);
-		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
-		tty->read_cnt += i;
+		memcpy(ldata->read_buf + ldata->read_head, cp, i);
+		ldata->read_head = (ldata->read_head + i) & (N_TTY_BUF_SIZE-1);
+		ldata->read_cnt += i;
 		cp += i;
 		count -= i;
 
-		i = min(N_TTY_BUF_SIZE - tty->read_cnt,
-			N_TTY_BUF_SIZE - tty->read_head);
+		i = min(N_TTY_BUF_SIZE - ldata->read_cnt,
+			N_TTY_BUF_SIZE - ldata->read_head);
 		i = min(count, i);
-		memcpy(tty->read_buf + tty->read_head, cp, i);
-		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
-		tty->read_cnt += i;
-		spin_unlock_irqrestore(&tty->read_lock, cpuflags);
+		memcpy(ldata->read_buf + ldata->read_head, cp, i);
+		ldata->read_head = (ldata->read_head + i) & (N_TTY_BUF_SIZE-1);
+		ldata->read_cnt += i;
+		spin_unlock_irqrestore(&ldata->read_lock, cpuflags);
 	} else {
 		for (i = count, p = cp, f = fp; i; i--, p++) {
 			if (f)
@@ -1426,7 +1470,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 
 	n_tty_set_room(tty);
 
-	if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) ||
+	if ((!ldata->icanon && (ldata->read_cnt >= tty->minimum_to_wake)) ||
 		L_EXTPROC(tty)) {
 		kill_fasync(&tty->fasync, SIGIO, POLL_IN);
 		if (waitqueue_active(&tty->read_wait))
@@ -1470,25 +1514,25 @@ int is_ignored(int sig)
 
 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;
-	BUG_ON(!tty);
 
 	if (old)
 		canon_change = (old->c_lflag ^ tty->termios.c_lflag) & ICANON;
 	if (canon_change) {
-		memset(&tty->read_flags, 0, sizeof tty->read_flags);
-		tty->canon_head = tty->read_tail;
-		tty->canon_data = 0;
-		tty->erasing = 0;
+		bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
+		ldata->canon_head = ldata->read_tail;
+		ldata->canon_data = 0;
+		ldata->erasing = 0;
 	}
 
-	if (canon_change && !L_ICANON(tty) && tty->read_cnt)
+	if (canon_change && !L_ICANON(tty) && ldata->read_cnt)
 		wake_up_interruptible(&tty->read_wait);
 
-	tty->icanon = (L_ICANON(tty) != 0);
+	ldata->icanon = (L_ICANON(tty) != 0);
 	if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
-		tty->raw = 1;
-		tty->real_raw = 1;
+		ldata->raw = 1;
+		ldata->real_raw = 1;
 		n_tty_set_room(tty);
 		return;
 	}
@@ -1496,51 +1540,51 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
 	    I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
 	    I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
 	    I_PARMRK(tty)) {
-		memset(tty->process_char_map, 0, 256/8);
+		bitmap_zero(ldata->process_char_map, 256);
 
 		if (I_IGNCR(tty) || I_ICRNL(tty))
-			set_bit('\r', tty->process_char_map);
+			set_bit('\r', ldata->process_char_map);
 		if (I_INLCR(tty))
-			set_bit('\n', tty->process_char_map);
+			set_bit('\n', ldata->process_char_map);
 
 		if (L_ICANON(tty)) {
-			set_bit(ERASE_CHAR(tty), tty->process_char_map);
-			set_bit(KILL_CHAR(tty), tty->process_char_map);
-			set_bit(EOF_CHAR(tty), tty->process_char_map);
-			set_bit('\n', tty->process_char_map);
-			set_bit(EOL_CHAR(tty), tty->process_char_map);
+			set_bit(ERASE_CHAR(tty), ldata->process_char_map);
+			set_bit(KILL_CHAR(tty), ldata->process_char_map);
+			set_bit(EOF_CHAR(tty), ldata->process_char_map);
+			set_bit('\n', ldata->process_char_map);
+			set_bit(EOL_CHAR(tty), ldata->process_char_map);
 			if (L_IEXTEN(tty)) {
 				set_bit(WERASE_CHAR(tty),
-					tty->process_char_map);
+					ldata->process_char_map);
 				set_bit(LNEXT_CHAR(tty),
-					tty->process_char_map);
+					ldata->process_char_map);
 				set_bit(EOL2_CHAR(tty),
-					tty->process_char_map);
+					ldata->process_char_map);
 				if (L_ECHO(tty))
 					set_bit(REPRINT_CHAR(tty),
-						tty->process_char_map);
+						ldata->process_char_map);
 			}
 		}
 		if (I_IXON(tty)) {
-			set_bit(START_CHAR(tty), tty->process_char_map);
-			set_bit(STOP_CHAR(tty), tty->process_char_map);
+			set_bit(START_CHAR(tty), ldata->process_char_map);
+			set_bit(STOP_CHAR(tty), ldata->process_char_map);
 		}
 		if (L_ISIG(tty)) {
-			set_bit(INTR_CHAR(tty), tty->process_char_map);
-			set_bit(QUIT_CHAR(tty), tty->process_char_map);
-			set_bit(SUSP_CHAR(tty), tty->process_char_map);
+			set_bit(INTR_CHAR(tty), ldata->process_char_map);
+			set_bit(QUIT_CHAR(tty), ldata->process_char_map);
+			set_bit(SUSP_CHAR(tty), ldata->process_char_map);
 		}
-		clear_bit(__DISABLED_CHAR, tty->process_char_map);
-		tty->raw = 0;
-		tty->real_raw = 0;
+		clear_bit(__DISABLED_CHAR, ldata->process_char_map);
+		ldata->raw = 0;
+		ldata->real_raw = 0;
 	} else {
-		tty->raw = 1;
+		ldata->raw = 1;
 		if ((I_IGNBRK(tty) || (!I_BRKINT(tty) && !I_PARMRK(tty))) &&
 		    (I_IGNPAR(tty) || !I_INPCK(tty)) &&
 		    (tty->driver->flags & TTY_DRIVER_REAL_RAW))
-			tty->real_raw = 1;
+			ldata->real_raw = 1;
 		else
-			tty->real_raw = 0;
+			ldata->real_raw = 0;
 	}
 	n_tty_set_room(tty);
 	/* The termios change make the tty ready for I/O */
@@ -1560,15 +1604,13 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
 
 static void n_tty_close(struct tty_struct *tty)
 {
+	struct n_tty_data *ldata = tty->disc_data;
+
 	n_tty_flush_buffer(tty);
-	if (tty->read_buf) {
-		kfree(tty->read_buf);
-		tty->read_buf = NULL;
-	}
-	if (tty->echo_buf) {
-		kfree(tty->echo_buf);
-		tty->echo_buf = NULL;
-	}
+	kfree(ldata->read_buf);
+	kfree(ldata->echo_buf);
+	kfree(ldata);
+	tty->disc_data = NULL;
 }
 
 /**
@@ -1583,37 +1625,50 @@ static void n_tty_close(struct tty_struct *tty)
 
 static int n_tty_open(struct tty_struct *tty)
 {
-	if (!tty)
-		return -EINVAL;
+	struct n_tty_data *ldata;
+
+	ldata = kzalloc(sizeof(*ldata), GFP_KERNEL);
+	if (!ldata)
+		goto err;
+
+	ldata->overrun_time = jiffies;
+	mutex_init(&ldata->atomic_read_lock);
+	mutex_init(&ldata->output_lock);
+	mutex_init(&ldata->echo_lock);
+	spin_lock_init(&ldata->read_lock);
 
 	/* These are ugly. Currently a malloc failure here can panic */
-	if (!tty->read_buf) {
-		tty->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
-		if (!tty->read_buf)
-			return -ENOMEM;
-	}
-	if (!tty->echo_buf) {
-		tty->echo_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+	ldata->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+	ldata->echo_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+	if (!ldata->read_buf || !ldata->echo_buf)
+		goto err_free_bufs;
 
-		if (!tty->echo_buf)
-			return -ENOMEM;
-	}
+	tty->disc_data = ldata;
 	reset_buffer_flags(tty);
 	tty_unthrottle(tty);
-	tty->column = 0;
+	ldata->column = 0;
 	n_tty_set_termios(tty, NULL);
 	tty->minimum_to_wake = 1;
 	tty->closing = 0;
+
 	return 0;
+err_free_bufs:
+	kfree(ldata->read_buf);
+	kfree(ldata->echo_buf);
+	kfree(ldata);
+err:
+	return -ENOMEM;
 }
 
 static inline int input_available_p(struct tty_struct *tty, int amt)
 {
+	struct n_tty_data *ldata = tty->disc_data;
+
 	tty_flush_to_ldisc(tty);
-	if (tty->icanon && !L_EXTPROC(tty)) {
-		if (tty->canon_data)
+	if (ldata->icanon && !L_EXTPROC(tty)) {
+		if (ldata->canon_data)
 			return 1;
-	} else if (tty->read_cnt >= (amt ? amt : 1))
+	} else if (ldata->read_cnt >= (amt ? amt : 1))
 		return 1;
 
 	return 0;
@@ -1632,7 +1687,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt)
  *	buffer, and once to drain the space from the (physical) beginning of
  *	the buffer to head pointer.
  *
- *	Called under the tty->atomic_read_lock sem
+ *	Called under the ldata->atomic_read_lock sem
  *
  */
 
@@ -1641,29 +1696,31 @@ static int copy_from_read_buf(struct tty_struct *tty,
 				      size_t *nr)
 
 {
+	struct n_tty_data *ldata = tty->disc_data;
 	int retval;
 	size_t n;
 	unsigned long flags;
 	bool is_eof;
 
 	retval = 0;
-	spin_lock_irqsave(&tty->read_lock, flags);
-	n = min(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail);
+	spin_lock_irqsave(&ldata->read_lock, flags);
+	n = min(ldata->read_cnt, N_TTY_BUF_SIZE - ldata->read_tail);
 	n = min(*nr, n);
-	spin_unlock_irqrestore(&tty->read_lock, flags);
+	spin_unlock_irqrestore(&ldata->read_lock, flags);
 	if (n) {
-		retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
+		retval = copy_to_user(*b, &ldata->read_buf[ldata->read_tail], n);
 		n -= retval;
 		is_eof = n == 1 &&
-			tty->read_buf[tty->read_tail] == EOF_CHAR(tty);
-		tty_audit_add_data(tty, &tty->read_buf[tty->read_tail], n);
-		spin_lock_irqsave(&tty->read_lock, flags);
-		tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
-		tty->read_cnt -= n;
+			ldata->read_buf[ldata->read_tail] == EOF_CHAR(tty);
+		tty_audit_add_data(tty, &ldata->read_buf[ldata->read_tail], n,
+				ldata->icanon);
+		spin_lock_irqsave(&ldata->read_lock, flags);
+		ldata->read_tail = (ldata->read_tail + n) & (N_TTY_BUF_SIZE-1);
+		ldata->read_cnt -= n;
 		/* Turn single EOF into zero-length read */
-		if (L_EXTPROC(tty) && tty->icanon && is_eof && !tty->read_cnt)
+		if (L_EXTPROC(tty) && ldata->icanon && is_eof && !ldata->read_cnt)
 			n = 0;
-		spin_unlock_irqrestore(&tty->read_lock, flags);
+		spin_unlock_irqrestore(&ldata->read_lock, flags);
 		*b += n;
 		*nr -= n;
 	}
@@ -1730,6 +1787,7 @@ static int job_control(struct tty_struct *tty, struct file *file)
 static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
 			 unsigned char __user *buf, size_t nr)
 {
+	struct n_tty_data *ldata = tty->disc_data;
 	unsigned char __user *b = buf;
 	DECLARE_WAITQUEUE(wait, current);
 	int c;
@@ -1741,17 +1799,13 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
 	int packet;
 
 do_it_again:
-
-	if (WARN_ON(!tty->read_buf))
-		return -EAGAIN;
-
 	c = job_control(tty, file);
 	if (c < 0)
 		return c;
 
 	minimum = time = 0;
 	timeout = MAX_SCHEDULE_TIMEOUT;
-	if (!tty->icanon) {
+	if (!ldata->icanon) {
 		time = (HZ / 10) * TIME_CHAR(tty);
 		minimum = MIN_CHAR(tty);
 		if (minimum) {
@@ -1774,10 +1828,10 @@ do_it_again:
 	 *	Internal serialization of reads.
 	 */
 	if (file->f_flags & O_NONBLOCK) {
-		if (!mutex_trylock(&tty->atomic_read_lock))
+		if (!mutex_trylock(&ldata->atomic_read_lock))
 			return -EAGAIN;
 	} else {
-		if (mutex_lock_interruptible(&tty->atomic_read_lock))
+		if (mutex_lock_interruptible(&ldata->atomic_read_lock))
 			return -ERESTARTSYS;
 	}
 	packet = tty->packet;
@@ -1830,7 +1884,6 @@ do_it_again:
 			/* FIXME: does n_tty_set_room need locking ? */
 			n_tty_set_room(tty);
 			timeout = schedule_timeout(timeout);
-			BUG_ON(!tty->read_buf);
 			continue;
 		}
 		__set_current_state(TASK_RUNNING);
@@ -1845,45 +1898,45 @@ do_it_again:
 			nr--;
 		}
 
-		if (tty->icanon && !L_EXTPROC(tty)) {
+		if (ldata->icanon && !L_EXTPROC(tty)) {
 			/* N.B. avoid overrun if nr == 0 */
-			spin_lock_irqsave(&tty->read_lock, flags);
-			while (nr && tty->read_cnt) {
+			spin_lock_irqsave(&ldata->read_lock, flags);
+			while (nr && ldata->read_cnt) {
 				int eol;
 
-				eol = test_and_clear_bit(tty->read_tail,
-						tty->read_flags);
-				c = tty->read_buf[tty->read_tail];
-				tty->read_tail = ((tty->read_tail+1) &
+				eol = test_and_clear_bit(ldata->read_tail,
+						ldata->read_flags);
+				c = ldata->read_buf[ldata->read_tail];
+				ldata->read_tail = ((ldata->read_tail+1) &
 						  (N_TTY_BUF_SIZE-1));
-				tty->read_cnt--;
+				ldata->read_cnt--;
 				if (eol) {
 					/* this test should be redundant:
 					 * we shouldn't be reading data if
 					 * canon_data is 0
 					 */
-					if (--tty->canon_data < 0)
-						tty->canon_data = 0;
+					if (--ldata->canon_data < 0)
+						ldata->canon_data = 0;
 				}
-				spin_unlock_irqrestore(&tty->read_lock, flags);
+				spin_unlock_irqrestore(&ldata->read_lock, flags);
 
 				if (!eol || (c != __DISABLED_CHAR)) {
 					if (tty_put_user(tty, c, b++)) {
 						retval = -EFAULT;
 						b--;
-						spin_lock_irqsave(&tty->read_lock, flags);
+						spin_lock_irqsave(&ldata->read_lock, flags);
 						break;
 					}
 					nr--;
 				}
 				if (eol) {
 					tty_audit_push(tty);
-					spin_lock_irqsave(&tty->read_lock, flags);
+					spin_lock_irqsave(&ldata->read_lock, flags);
 					break;
 				}
-				spin_lock_irqsave(&tty->read_lock, flags);
+				spin_lock_irqsave(&ldata->read_lock, flags);
 			}
-			spin_unlock_irqrestore(&tty->read_lock, flags);
+			spin_unlock_irqrestore(&ldata->read_lock, flags);
 			if (retval)
 				break;
 		} else {
@@ -1915,7 +1968,7 @@ do_it_again:
 		if (time)
 			timeout = time;
 	}
-	mutex_unlock(&tty->atomic_read_lock);
+	mutex_unlock(&ldata->atomic_read_lock);
 	remove_wait_queue(&tty->read_wait, &wait);
 
 	if (!waitqueue_active(&tty->read_wait))
@@ -2076,19 +2129,19 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,
 	return mask;
 }
 
-static unsigned long inq_canon(struct tty_struct *tty)
+static unsigned long inq_canon(struct n_tty_data *ldata)
 {
 	int nr, head, tail;
 
-	if (!tty->canon_data)
+	if (!ldata->canon_data)
 		return 0;
-	head = tty->canon_head;
-	tail = tty->read_tail;
+	head = ldata->canon_head;
+	tail = ldata->read_tail;
 	nr = (head - tail) & (N_TTY_BUF_SIZE-1);
 	/* Skip EOF-chars.. */
 	while (head != tail) {
-		if (test_bit(tail, tty->read_flags) &&
-		    tty->read_buf[tail] == __DISABLED_CHAR)
+		if (test_bit(tail, ldata->read_flags) &&
+		    ldata->read_buf[tail] == __DISABLED_CHAR)
 			nr--;
 		tail = (tail+1) & (N_TTY_BUF_SIZE-1);
 	}
@@ -2098,6 +2151,7 @@ static unsigned long inq_canon(struct tty_struct *tty)
 static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
 		       unsigned int cmd, unsigned long arg)
 {
+	struct n_tty_data *ldata = tty->disc_data;
 	int retval;
 
 	switch (cmd) {
@@ -2105,9 +2159,9 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
 		return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
 	case TIOCINQ:
 		/* FIXME: Locking */
-		retval = tty->read_cnt;
+		retval = ldata->read_cnt;
 		if (L_ICANON(tty))
-			retval = inq_canon(tty);
+			retval = inq_canon(ldata);
 		return put_user(retval, (unsigned int __user *) arg);
 	default:
 		return n_tty_ioctl_helper(tty, file, cmd, arg);
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
index b917c94..a0c69ab 100644
--- a/drivers/tty/nozomi.c
+++ b/drivers/tty/nozomi.c
@@ -400,7 +400,7 @@ struct buffer {
 } __attribute__ ((packed));
 
 /*    Global variables */
-static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = {
+static const struct pci_device_id nozomi_pci_tbl[] = {
 	{PCI_DEVICE(0x1931, 0x000c)},	/* Nozomi HSDPA */
 	{},
 };
@@ -1360,7 +1360,7 @@ static void remove_sysfs_files(struct nozomi *dc)
 }
 
 /* Allocate memory for one device */
-static int __devinit nozomi_card_init(struct pci_dev *pdev,
+static int nozomi_card_init(struct pci_dev *pdev,
 				      const struct pci_device_id *ent)
 {
 	resource_size_t start;
@@ -1479,6 +1479,7 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
 		if (IS_ERR(tty_dev)) {
 			ret = PTR_ERR(tty_dev);
 			dev_err(&pdev->dev, "Could not allocate tty?\n");
+			tty_port_destroy(&port->port);
 			goto err_free_tty;
 		}
 	}
@@ -1486,8 +1487,10 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
 	return 0;
 
 err_free_tty:
-	for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
-		tty_unregister_device(ntty_driver, i);
+	for (i = 0; i < MAX_PORT; ++i) {
+		tty_unregister_device(ntty_driver, dc->index_start + i);
+		tty_port_destroy(&dc->port[i].port);
+	}
 err_free_kfifo:
 	for (i = 0; i < MAX_PORT; i++)
 		kfifo_free(&dc->port[i].fifo_ul);
@@ -1504,7 +1507,7 @@ err:
 	return ret;
 }
 
-static void __devexit tty_exit(struct nozomi *dc)
+static void tty_exit(struct nozomi *dc)
 {
 	unsigned int i;
 
@@ -1520,12 +1523,14 @@ static void __devexit tty_exit(struct nozomi *dc)
 	   complete off a hangup method ? */
 	while (dc->open_ttys)
 		msleep(1);
-	for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
-		tty_unregister_device(ntty_driver, i);
+	for (i = 0; i < MAX_PORT; ++i) {
+		tty_unregister_device(ntty_driver, dc->index_start + i);
+		tty_port_destroy(&dc->port[i].port);
+	}
 }
 
 /* Deallocate memory for one device */
-static void __devexit nozomi_card_exit(struct pci_dev *pdev)
+static void nozomi_card_exit(struct pci_dev *pdev)
 {
 	int i;
 	struct ctrl_ul ctrl;
@@ -1903,7 +1908,7 @@ static struct pci_driver nozomi_driver = {
 	.name = NOZOMI_NAME,
 	.id_table = nozomi_pci_tbl,
 	.probe = nozomi_card_init,
-	.remove = __devexit_p(nozomi_card_exit),
+	.remove = nozomi_card_exit,
 };
 
 static __init int nozomi_init(void)
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index a82b399..be6a373 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -4,9 +4,6 @@
  *  Added support for a Unix98-style ptmx device.
  *    -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
  *
- *  When reading this code see also fs/devpts. In particular note that the
- *  driver_data field is used by the devpts side as a binding to the devpts
- *  inode.
  */
 
 #include <linux/module.h>
@@ -59,7 +56,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
 #ifdef CONFIG_UNIX98_PTYS
 		if (tty->driver == ptm_driver) {
 		        mutex_lock(&devpts_mutex);
-			devpts_pty_kill(tty->link);
+			devpts_pty_kill(tty->link->driver_data);
 		        mutex_unlock(&devpts_mutex);
 		}
 #endif
@@ -96,7 +93,7 @@ static void pty_unthrottle(struct tty_struct *tty)
 
 static int pty_space(struct tty_struct *to)
 {
-	int n = 8192 - to->buf.memory_used;
+	int n = 8192 - to->port->buf.memory_used;
 	if (n < 0)
 		return 0;
 	return n;
@@ -174,6 +171,41 @@ static int pty_set_lock(struct tty_struct *tty, int __user *arg)
 	return 0;
 }
 
+static int pty_get_lock(struct tty_struct *tty, int __user *arg)
+{
+	int locked = test_bit(TTY_PTY_LOCK, &tty->flags);
+	return put_user(locked, arg);
+}
+
+/* Set the packet mode on a pty */
+static int pty_set_pktmode(struct tty_struct *tty, int __user *arg)
+{
+	unsigned long flags;
+	int pktmode;
+
+	if (get_user(pktmode, arg))
+		return -EFAULT;
+
+	spin_lock_irqsave(&tty->ctrl_lock, flags);
+	if (pktmode) {
+		if (!tty->packet) {
+			tty->packet = 1;
+			tty->link->ctrl_status = 0;
+		}
+	} else
+		tty->packet = 0;
+	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+
+	return 0;
+}
+
+/* Get the packet mode of a pty */
+static int pty_get_pktmode(struct tty_struct *tty, int __user *arg)
+{
+	int pktmode = tty->packet;
+	return put_user(pktmode, arg);
+}
+
 /* Send a signal to the slave */
 static int pty_signal(struct tty_struct *tty, int sig)
 {
@@ -245,7 +277,7 @@ static void pty_set_termios(struct tty_struct *tty,
  *	peform a terminal resize correctly
  */
 
-int pty_resize(struct tty_struct *tty,  struct winsize *ws)
+static int pty_resize(struct tty_struct *tty,  struct winsize *ws)
 {
 	struct pid *pgrp, *rpgrp;
 	unsigned long flags;
@@ -348,6 +380,7 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
 	tty_port_init(ports[1]);
 	o_tty->port = ports[0];
 	tty->port = ports[1];
+	o_tty->port->itty = o_tty;
 
 	tty_driver_kref_get(driver);
 	tty->count++;
@@ -366,9 +399,16 @@ err:
 	return retval;
 }
 
+/* this is called once with whichever end is closed last */
+static void pty_unix98_shutdown(struct tty_struct *tty)
+{
+	devpts_kill_index(tty->driver_data, tty->index);
+}
+
 static void pty_cleanup(struct tty_struct *tty)
 {
-	kfree(tty->port);
+	tty->port->itty = NULL;
+	tty_port_put(tty->port);
 }
 
 /* Traditional BSD devices */
@@ -393,6 +433,12 @@ static int pty_bsd_ioctl(struct tty_struct *tty,
 	switch (cmd) {
 	case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
 		return pty_set_lock(tty, (int __user *) arg);
+	case TIOCGPTLCK: /* Get PT Lock status */
+		return pty_get_lock(tty, (int __user *)arg);
+	case TIOCPKT: /* Set PT packet mode */
+		return pty_set_pktmode(tty, (int __user *)arg);
+	case TIOCGPKT: /* Get PT packet mode */
+		return pty_get_pktmode(tty, (int __user *)arg);
 	case TIOCSIG:    /* Send signal to other side of pty */
 		return pty_signal(tty, (int) arg);
 	}
@@ -507,6 +553,12 @@ static int pty_unix98_ioctl(struct tty_struct *tty,
 	switch (cmd) {
 	case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
 		return pty_set_lock(tty, (int __user *)arg);
+	case TIOCGPTLCK: /* Get PT Lock status */
+		return pty_get_lock(tty, (int __user *)arg);
+	case TIOCPKT: /* Set PT packet mode */
+		return pty_set_pktmode(tty, (int __user *)arg);
+	case TIOCGPKT: /* Get PT packet mode */
+		return pty_get_pktmode(tty, (int __user *)arg);
 	case TIOCGPTN: /* Get PT Number */
 		return put_user(tty->index, (unsigned int __user *)arg);
 	case TIOCSIG:    /* Send signal to other side of pty */
@@ -547,7 +599,7 @@ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
 	struct tty_struct *tty;
 
 	mutex_lock(&devpts_mutex);
-	tty = devpts_get_tty(pts_inode, idx);
+	tty = devpts_get_priv(pts_inode);
 	mutex_unlock(&devpts_mutex);
 	/* Master must be open before slave */
 	if (!tty)
@@ -581,6 +633,7 @@ static const struct tty_operations ptm_unix98_ops = {
 	.set_termios = pty_set_termios,
 	.ioctl = pty_unix98_ioctl,
 	.resize = pty_resize,
+	.shutdown = pty_unix98_shutdown,
 	.cleanup = pty_cleanup
 };
 
@@ -596,6 +649,7 @@ static const struct tty_operations pty_unix98_ops = {
 	.chars_in_buffer = pty_chars_in_buffer,
 	.unthrottle = pty_unthrottle,
 	.set_termios = pty_set_termios,
+	.shutdown = pty_unix98_shutdown,
 	.cleanup = pty_cleanup,
 };
 
@@ -614,6 +668,7 @@ static const struct tty_operations pty_unix98_ops = {
 static int ptmx_open(struct inode *inode, struct file *filp)
 {
 	struct tty_struct *tty;
+	struct inode *slave_inode;
 	int retval;
 	int index;
 
@@ -650,15 +705,21 @@ static int ptmx_open(struct inode *inode, struct file *filp)
 
 	tty_add_file(tty, filp);
 
-	retval = devpts_pty_new(inode, tty->link);
-	if (retval)
+	slave_inode = devpts_pty_new(inode,
+			MKDEV(UNIX98_PTY_SLAVE_MAJOR, index), index,
+			tty->link);
+	if (IS_ERR(slave_inode)) {
+		retval = PTR_ERR(slave_inode);
 		goto err_release;
+	}
 
 	retval = ptm_driver->ops->open(tty, filp);
 	if (retval)
 		goto err_release;
 
 	tty_unlock(tty);
+	tty->driver_data = inode;
+	tty->link->driver_data = slave_inode;
 	return 0;
 err_release:
 	tty_unlock(tty);
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c
index 9700d34..e42009a 100644
--- a/drivers/tty/rocket.c
+++ b/drivers/tty/rocket.c
@@ -673,6 +673,7 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
 	if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) {
 		printk(KERN_ERR "RocketPort sInitChan(%d, %d, %d) failed!\n",
 				board, aiop, chan);
+		tty_port_destroy(&info->port);
 		kfree(info);
 		return;
 	}
@@ -1757,7 +1758,7 @@ static void rp_flush_buffer(struct tty_struct *tty)
 
 #ifdef CONFIG_PCI
 
-static struct pci_device_id __devinitdata __used rocket_pci_ids[] = {
+static struct pci_device_id __used rocket_pci_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_ANY_ID) },
 	{ }
 };
@@ -2357,6 +2358,7 @@ static void rp_cleanup_module(void)
 	for (i = 0; i < MAX_RP_PORTS; i++)
 		if (rp_table[i]) {
 			tty_unregister_device(rocket_driver, i);
+			tty_port_destroy(&rp_table[i]->port);
 			kfree(rp_table[i]);
 		}
 
diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c
index 66c38a3..f99a845 100644
--- a/drivers/tty/serial/68328serial.c
+++ b/drivers/tty/serial/68328serial.c
@@ -1225,6 +1225,8 @@ rs68328_init(void)
 
 	if (tty_register_driver(serial_driver)) {
 		put_tty_driver(serial_driver);
+		for (i = 0; i < NR_PORTS; i++)
+			tty_port_destroy(&m68k_soft[i].tport);
 		printk(KERN_ERR "Couldn't register serial driver\n");
 		return -ENOMEM;
 	}
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 3ba4234..d085e3a 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -280,7 +280,17 @@ static const struct serial8250_config uart_config[] = {
 		.fifo_size	= 64,
 		.tx_loadsz	= 64,
 		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-		.flags		= UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR,
+		.flags		= UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
+				  UART_CAP_SLEEP,
+	},
+	[PORT_XR17V35X] = {
+		.name		= "XR17V35X",
+		.fifo_size	= 256,
+		.tx_loadsz	= 256,
+		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11 |
+				  UART_FCR_T_TRIG_11,
+		.flags		= UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
+				  UART_CAP_SLEEP,
 	},
 	[PORT_LPC3220] = {
 		.name		= "LPC3220",
@@ -455,6 +465,7 @@ static void io_serial_out(struct uart_port *p, int offset, int value)
 }
 
 static int serial8250_default_handle_irq(struct uart_port *port);
+static int exar_handle_irq(struct uart_port *port);
 
 static void set_io_from_upio(struct uart_port *p)
 {
@@ -574,6 +585,19 @@ EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
  */
 static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
 {
+	/*
+	 * Exar UARTs have a SLEEP register that enables or disables
+	 * each UART to enter sleep mode separately.  On the XR17V35x the
+	 * register is accessible to each UART at the UART_EXAR_SLEEP
+	 * offset but the UART channel may only write to the corresponding
+	 * bit.
+	 */
+	if ((p->port.type == PORT_XR17V35X) ||
+	   (p->port.type == PORT_XR17D15X)) {
+		serial_out(p, UART_EXAR_SLEEP, 0xff);
+		return;
+	}
+
 	if (p->capabilities & UART_CAP_SLEEP) {
 		if (p->capabilities & UART_CAP_EFR) {
 			serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
@@ -882,6 +906,27 @@ static void autoconfig_16550a(struct uart_8250_port *up)
 	up->capabilities |= UART_CAP_FIFO;
 
 	/*
+	 * XR17V35x UARTs have an extra divisor register, DLD
+	 * that gets enabled with when DLAB is set which will
+	 * cause the device to incorrectly match and assign
+	 * port type to PORT_16650.  The EFR for this UART is
+	 * found at offset 0x09. Instead check the Deice ID (DVID)
+	 * register for a 2, 4 or 8 port UART.
+	 */
+	if (up->port.flags & UPF_EXAR_EFR) {
+		status1 = serial_in(up, UART_EXAR_DVID);
+		if (status1 == 0x82 || status1 == 0x84 || status1 == 0x88) {
+			DEBUG_AUTOCONF("Exar XR17V35x ");
+			up->port.type = PORT_XR17V35X;
+			up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
+						UART_CAP_SLEEP;
+
+			return;
+		}
+
+	}
+
+	/*
 	 * Check for presence of the EFR when DLAB is set.
 	 * Only ST16C650V1 UARTs pass this test.
 	 */
@@ -1013,8 +1058,12 @@ static void autoconfig_16550a(struct uart_8250_port *up)
 	 * Exar uarts have EFR in a weird location
 	 */
 	if (up->port.flags & UPF_EXAR_EFR) {
+		DEBUG_AUTOCONF("Exar XR17D15x ");
 		up->port.type = PORT_XR17D15X;
-		up->capabilities |= UART_CAP_AFE | UART_CAP_EFR;
+		up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
+				    UART_CAP_SLEEP;
+
+		return;
 	}
 
 	/*
@@ -1516,6 +1565,31 @@ static int serial8250_default_handle_irq(struct uart_port *port)
 }
 
 /*
+ * These Exar UARTs have an extra interrupt indicator that could
+ * fire for a few unimplemented interrupts.  One of which is a
+ * wakeup event when coming out of sleep.  Put this here just
+ * to be on the safe side that these interrupts don't go unhandled.
+ */
+static int exar_handle_irq(struct uart_port *port)
+{
+	unsigned char int0, int1, int2, int3;
+	unsigned int iir = serial_port_in(port, UART_IIR);
+	int ret;
+
+	ret = serial8250_handle_irq(port, iir);
+
+	if ((port->type == PORT_XR17V35X) ||
+	   (port->type == PORT_XR17D15X)) {
+		int0 = serial_port_in(port, 0x80);
+		int1 = serial_port_in(port, 0x81);
+		int2 = serial_port_in(port, 0x82);
+		int3 = serial_port_in(port, 0x83);
+	}
+
+	return ret;
+}
+
+/*
  * This is the serial driver's interrupt routine.
  *
  * Arjan thinks the old way was overly complex, so it got simplified.
@@ -2349,16 +2423,14 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 			serial_port_out(port, UART_EFR, efr);
 	}
 
-#ifdef CONFIG_ARCH_OMAP1
 	/* Workaround to enable 115200 baud on OMAP1510 internal ports */
-	if (cpu_is_omap1510() && is_omap_port(up)) {
+	if (is_omap1510_8250(up)) {
 		if (baud == 115200) {
 			quot = 1;
 			serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
 		} else
 			serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
 	}
-#endif
 
 	/*
 	 * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
@@ -2439,10 +2511,9 @@ static unsigned int serial8250_port_size(struct uart_8250_port *pt)
 {
 	if (pt->port.iotype == UPIO_AU)
 		return 0x1000;
-#ifdef CONFIG_ARCH_OMAP1
-	if (is_omap_port(pt))
+	if (is_omap1_8250(pt))
 		return 0x16 << pt->port.regshift;
-#endif
+
 	return 8 << pt->port.regshift;
 }
 
@@ -2617,6 +2688,11 @@ static void serial8250_config_port(struct uart_port *port, int flags)
 		serial8250_release_rsa_resource(up);
 	if (port->type == PORT_UNKNOWN)
 		serial8250_release_std_resource(up);
+
+	/* Fixme: probably not the best place for this */
+	if ((port->type == PORT_XR17V35X) ||
+	   (port->type == PORT_XR17D15X))
+		port->handle_irq = exar_handle_irq;
 }
 
 static int
@@ -2992,7 +3068,7 @@ void serial8250_resume_port(int line)
  * list is terminated with a zero flags entry, which means we expect
  * all entries to have at least UPF_BOOT_AUTOCONF set.
  */
-static int __devinit serial8250_probe(struct platform_device *dev)
+static int serial8250_probe(struct platform_device *dev)
 {
 	struct plat_serial8250_port *p = dev->dev.platform_data;
 	struct uart_8250_port uart;
@@ -3038,7 +3114,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
 /*
  * Remove serial ports registered against a platform device.
  */
-static int __devexit serial8250_remove(struct platform_device *dev)
+static int serial8250_remove(struct platform_device *dev)
 {
 	int i;
 
@@ -3081,7 +3157,7 @@ static int serial8250_resume(struct platform_device *dev)
 
 static struct platform_driver serial8250_isa_driver = {
 	.probe		= serial8250_probe,
-	.remove		= __devexit_p(serial8250_remove),
+	.remove		= serial8250_remove,
 	.suspend	= serial8250_suspend,
 	.resume		= serial8250_resume,
 	.driver		= {
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 5a76f9c..3b4ea84 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -106,3 +106,39 @@ static inline int serial8250_pnp_init(void) { return 0; }
 static inline void serial8250_pnp_exit(void) { }
 #endif
 
+#ifdef CONFIG_ARCH_OMAP1
+static inline int is_omap1_8250(struct uart_8250_port *pt)
+{
+	int res;
+
+	switch (pt->port.mapbase) {
+	case OMAP1_UART1_BASE:
+	case OMAP1_UART2_BASE:
+	case OMAP1_UART3_BASE:
+		res = 1;
+		break;
+	default:
+		res = 0;
+		break;
+	}
+
+	return res;
+}
+
+static inline int is_omap1510_8250(struct uart_8250_port *pt)
+{
+	if (!cpu_is_omap1510())
+		return 0;
+
+	return is_omap1_8250(pt);
+}
+#else
+static inline int is_omap1_8250(struct uart_8250_port *pt)
+{
+	return 0;
+}
+static inline int is_omap1510_8250(struct uart_8250_port *pt)
+{
+	return 0;
+}
+#endif
diff --git a/drivers/tty/serial/8250/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c
index 8574983..549aa07 100644
--- a/drivers/tty/serial/8250/8250_acorn.c
+++ b/drivers/tty/serial/8250/8250_acorn.c
@@ -38,7 +38,7 @@ struct serial_card_info {
 	void __iomem *vaddr;
 };
 
-static int __devinit
+static int
 serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
 	struct serial_card_info *info;
@@ -80,7 +80,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
 	return 0;
 }
 
-static void __devexit serial_card_remove(struct expansion_card *ec)
+static void serial_card_remove(struct expansion_card *ec)
 {
 	struct serial_card_info *info = ecard_get_drvdata(ec);
 	int i;
@@ -116,7 +116,7 @@ static const struct ecard_id serial_cids[] = {
 
 static struct ecard_driver serial_card_driver = {
 	.probe		= serial_card_probe,
-	.remove 	= __devexit_p(serial_card_remove),
+	.remove		= serial_card_remove,
 	.id_table	= serial_cids,
 	.drv = {
 		.name	= "8250_acorn",
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index c3b2ec0..1d0dba2 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -87,7 +87,7 @@ static int dw8250_handle_irq(struct uart_port *p)
 	return 0;
 }
 
-static int __devinit dw8250_probe(struct platform_device *pdev)
+static int dw8250_probe(struct platform_device *pdev)
 {
 	struct uart_8250_port uart = {};
 	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -152,7 +152,7 @@ static int __devinit dw8250_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit dw8250_remove(struct platform_device *pdev)
+static int dw8250_remove(struct platform_device *pdev)
 {
 	struct dw8250_data *data = platform_get_drvdata(pdev);
 
@@ -161,6 +161,29 @@ static int __devexit dw8250_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int dw8250_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct dw8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_suspend_port(data->line);
+
+	return 0;
+}
+
+static int dw8250_resume(struct platform_device *pdev)
+{
+	struct dw8250_data *data = platform_get_drvdata(pdev);
+
+	serial8250_resume_port(data->line);
+
+	return 0;
+}
+#else
+#define dw8250_suspend NULL
+#define dw8250_resume NULL
+#endif /* CONFIG_PM */
+
 static const struct of_device_id dw8250_match[] = {
 	{ .compatible = "snps,dw-apb-uart" },
 	{ /* Sentinel */ }
@@ -174,7 +197,9 @@ static struct platform_driver dw8250_platform_driver = {
 		.of_match_table	= dw8250_match,
 	},
 	.probe			= dw8250_probe,
-	.remove			= __devexit_p(dw8250_remove),
+	.remove			= dw8250_remove,
+	.suspend		= dw8250_suspend,
+	.resume			= dw8250_resume,
 };
 
 module_platform_driver(dw8250_platform_driver);
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index eaafb98..f53a7db 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -48,7 +48,7 @@ struct early_serial8250_device {
 
 static struct early_serial8250_device early_device;
 
-static unsigned int __init serial_in(struct uart_port *port, int offset)
+unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offset)
 {
 	switch (port->iotype) {
 	case UPIO_MEM:
@@ -62,7 +62,7 @@ static unsigned int __init serial_in(struct uart_port *port, int offset)
 	}
 }
 
-static void __init serial_out(struct uart_port *port, int offset, int value)
+void __weak __init serial8250_early_out(struct uart_port *port, int offset, int value)
 {
 	switch (port->iotype) {
 	case UPIO_MEM:
@@ -84,7 +84,7 @@ static void __init wait_for_xmitr(struct uart_port *port)
 	unsigned int status;
 
 	for (;;) {
-		status = serial_in(port, UART_LSR);
+		status = serial8250_early_in(port, UART_LSR);
 		if ((status & BOTH_EMPTY) == BOTH_EMPTY)
 			return;
 		cpu_relax();
@@ -94,7 +94,7 @@ static void __init wait_for_xmitr(struct uart_port *port)
 static void __init serial_putc(struct uart_port *port, int c)
 {
 	wait_for_xmitr(port);
-	serial_out(port, UART_TX, c);
+	serial8250_early_out(port, UART_TX, c);
 }
 
 static void __init early_serial8250_write(struct console *console,
@@ -104,14 +104,14 @@ static void __init early_serial8250_write(struct console *console,
 	unsigned int ier;
 
 	/* Save the IER and disable interrupts */
-	ier = serial_in(port, UART_IER);
-	serial_out(port, UART_IER, 0);
+	ier = serial8250_early_in(port, UART_IER);
+	serial8250_early_out(port, UART_IER, 0);
 
 	uart_console_write(port, s, count, serial_putc);
 
 	/* Wait for transmitter to become empty and restore the IER */
 	wait_for_xmitr(port);
-	serial_out(port, UART_IER, ier);
+	serial8250_early_out(port, UART_IER, ier);
 }
 
 static unsigned int __init probe_baud(struct uart_port *port)
@@ -119,11 +119,11 @@ static unsigned int __init probe_baud(struct uart_port *port)
 	unsigned char lcr, dll, dlm;
 	unsigned int quot;
 
-	lcr = serial_in(port, UART_LCR);
-	serial_out(port, UART_LCR, lcr | UART_LCR_DLAB);
-	dll = serial_in(port, UART_DLL);
-	dlm = serial_in(port, UART_DLM);
-	serial_out(port, UART_LCR, lcr);
+	lcr = serial8250_early_in(port, UART_LCR);
+	serial8250_early_out(port, UART_LCR, lcr | UART_LCR_DLAB);
+	dll = serial8250_early_in(port, UART_DLL);
+	dlm = serial8250_early_in(port, UART_DLM);
+	serial8250_early_out(port, UART_LCR, lcr);
 
 	quot = (dlm << 8) | dll;
 	return (port->uartclk / 16) / quot;
@@ -135,17 +135,17 @@ static void __init init_port(struct early_serial8250_device *device)
 	unsigned int divisor;
 	unsigned char c;
 
-	serial_out(port, UART_LCR, 0x3);	/* 8n1 */
-	serial_out(port, UART_IER, 0);		/* no interrupt */
-	serial_out(port, UART_FCR, 0);		/* no fifo */
-	serial_out(port, UART_MCR, 0x3);	/* DTR + RTS */
-
-	divisor = port->uartclk / (16 * device->baud);
-	c = serial_in(port, UART_LCR);
-	serial_out(port, UART_LCR, c | UART_LCR_DLAB);
-	serial_out(port, UART_DLL, divisor & 0xff);
-	serial_out(port, UART_DLM, (divisor >> 8) & 0xff);
-	serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
+	serial8250_early_out(port, UART_LCR, 0x3);	/* 8n1 */
+	serial8250_early_out(port, UART_IER, 0);	/* no interrupt */
+	serial8250_early_out(port, UART_FCR, 0);	/* no fifo */
+	serial8250_early_out(port, UART_MCR, 0x3);	/* DTR + RTS */
+
+	divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * device->baud);
+	c = serial8250_early_in(port, UART_LCR);
+	serial8250_early_out(port, UART_LCR, c | UART_LCR_DLAB);
+	serial8250_early_out(port, UART_DLL, divisor & 0xff);
+	serial8250_early_out(port, UART_DLM, (divisor >> 8) & 0xff);
+	serial8250_early_out(port, UART_LCR, c & ~UART_LCR_DLAB);
 }
 
 static int __init parse_options(struct early_serial8250_device *device,
diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
index 3a0363e..916cc19 100644
--- a/drivers/tty/serial/8250/8250_em.c
+++ b/drivers/tty/serial/8250/8250_em.c
@@ -89,7 +89,7 @@ static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value)
 	serial_out(up, UART_DLM_EM, value >> 8 & 0xff);
 }
 
-static int __devinit serial8250_em_probe(struct platform_device *pdev)
+static int serial8250_em_probe(struct platform_device *pdev)
 {
 	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -152,7 +152,7 @@ static int __devinit serial8250_em_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit serial8250_em_remove(struct platform_device *pdev)
+static int serial8250_em_remove(struct platform_device *pdev)
 {
 	struct serial8250_em_priv *priv = platform_get_drvdata(pdev);
 
@@ -163,7 +163,7 @@ static int __devexit serial8250_em_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id serial8250_em_dt_ids[] __devinitconst = {
+static const struct of_device_id serial8250_em_dt_ids[] = {
 	{ .compatible = "renesas,em-uart", },
 	{},
 };
@@ -176,7 +176,7 @@ static struct platform_driver serial8250_em_platform_driver = {
 		.owner		= THIS_MODULE,
 	},
 	.probe			= serial8250_em_probe,
-	.remove			= __devexit_p(serial8250_em_remove),
+	.remove			= serial8250_em_remove,
 };
 
 module_platform_driver(serial8250_em_platform_driver);
diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c
index f3d0edf..5bdaf27 100644
--- a/drivers/tty/serial/8250/8250_hp300.c
+++ b/drivers/tty/serial/8250/8250_hp300.c
@@ -36,9 +36,9 @@ static struct hp300_port *hp300_ports;
 
 #ifdef CONFIG_HPDCA
 
-static int __devinit hpdca_init_one(struct dio_dev *d,
+static int hpdca_init_one(struct dio_dev *d,
 					const struct dio_device_id *ent);
-static void __devexit hpdca_remove_one(struct dio_dev *d);
+static void hpdca_remove_one(struct dio_dev *d);
 
 static struct dio_device_id hpdca_dio_tbl[] = {
 	{ DIO_ID_DCA0 },
@@ -52,7 +52,7 @@ static struct dio_driver hpdca_driver = {
 	.name      = "hpdca",
 	.id_table  = hpdca_dio_tbl,
 	.probe     = hpdca_init_one,
-	.remove    = __devexit_p(hpdca_remove_one),
+	.remove    = hpdca_remove_one,
 };
 
 #endif
@@ -159,7 +159,7 @@ int __init hp300_setup_serial_console(void)
 #endif /* CONFIG_SERIAL_8250_CONSOLE */
 
 #ifdef CONFIG_HPDCA
-static int __devinit hpdca_init_one(struct dio_dev *d,
+static int hpdca_init_one(struct dio_dev *d,
 				const struct dio_device_id *ent)
 {
 	struct uart_8250_port uart;
@@ -288,7 +288,7 @@ static int __init hp300_8250_init(void)
 }
 
 #ifdef CONFIG_HPDCA
-static void __devexit hpdca_remove_one(struct dio_dev *d)
+static void hpdca_remove_one(struct dio_dev *d)
 {
 	int line;
 
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 17b7d26..26b9dc0 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -288,7 +288,7 @@ static int pci_plx9050_init(struct pci_dev *dev)
 	return 0;
 }
 
-static void __devexit pci_plx9050_exit(struct pci_dev *dev)
+static void pci_plx9050_exit(struct pci_dev *dev)
 {
 	u8 __iomem *p;
 
@@ -313,7 +313,7 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev)
 #define NI8420_INT_ENABLE_REG	0x38
 #define NI8420_INT_ENABLE_BIT	0x2000
 
-static void __devexit pci_ni8420_exit(struct pci_dev *dev)
+static void pci_ni8420_exit(struct pci_dev *dev)
 {
 	void __iomem *p;
 	unsigned long base, len;
@@ -345,7 +345,7 @@ static void __devexit pci_ni8420_exit(struct pci_dev *dev)
 
 #define MITE_LCIMR2_CLR_CPU_IE	(1 << 30)
 
-static void __devexit pci_ni8430_exit(struct pci_dev *dev)
+static void pci_ni8430_exit(struct pci_dev *dev)
 {
 	void __iomem *p;
 	unsigned long base, len;
@@ -422,7 +422,7 @@ static int sbs_init(struct pci_dev *dev)
  * Disables the global interrupt of PMC-OctalPro
  */
 
-static void __devexit sbs_exit(struct pci_dev *dev)
+static void sbs_exit(struct pci_dev *dev)
 {
 	u8 __iomem *p;
 
@@ -991,7 +991,7 @@ static int pci_ite887x_init(struct pci_dev *dev)
 	return ret;
 }
 
-static void __devexit pci_ite887x_exit(struct pci_dev *dev)
+static void pci_ite887x_exit(struct pci_dev *dev)
 {
 	u32 ioport;
 	/* the ioport is bit 0-15 in POSIO0R */
@@ -1068,7 +1068,7 @@ ce4100_serial_setup(struct serial_private *priv,
 {
 	int ret;
 
-	ret = setup_port(priv, port, 0, 0, board->reg_shift);
+	ret = setup_port(priv, port, idx, 0, board->reg_shift);
 	port->port.iotype = UPIO_MEM32;
 	port->port.type = PORT_XSCALE;
 	port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
@@ -1165,6 +1165,94 @@ pci_xr17c154_setup(struct serial_private *priv,
 }
 
 static int
+pci_xr17v35x_setup(struct serial_private *priv,
+		  const struct pciserial_board *board,
+		  struct uart_8250_port *port, int idx)
+{
+	u8 __iomem *p;
+
+	p = pci_ioremap_bar(priv->dev, 0);
+	if (p == NULL)
+		return -ENOMEM;
+
+	port->port.flags |= UPF_EXAR_EFR;
+
+	/*
+	 * Setup Multipurpose Input/Output pins.
+	 */
+	if (idx == 0) {
+		writeb(0x00, p + 0x8f); /*MPIOINT[7:0]*/
+		writeb(0x00, p + 0x90); /*MPIOLVL[7:0]*/
+		writeb(0x00, p + 0x91); /*MPIO3T[7:0]*/
+		writeb(0x00, p + 0x92); /*MPIOINV[7:0]*/
+		writeb(0x00, p + 0x93); /*MPIOSEL[7:0]*/
+		writeb(0x00, p + 0x94); /*MPIOOD[7:0]*/
+		writeb(0x00, p + 0x95); /*MPIOINT[15:8]*/
+		writeb(0x00, p + 0x96); /*MPIOLVL[15:8]*/
+		writeb(0x00, p + 0x97); /*MPIO3T[15:8]*/
+		writeb(0x00, p + 0x98); /*MPIOINV[15:8]*/
+		writeb(0x00, p + 0x99); /*MPIOSEL[15:8]*/
+		writeb(0x00, p + 0x9a); /*MPIOOD[15:8]*/
+	}
+	writeb(0x00, p + UART_EXAR_8XMODE);
+	writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR);
+	writeb(128, p + UART_EXAR_TXTRG);
+	writeb(128, p + UART_EXAR_RXTRG);
+	iounmap(p);
+
+	return pci_default_setup(priv, board, port, idx);
+}
+
+#define PCI_DEVICE_ID_COMMTECH_4222PCI335 0x0004
+#define PCI_DEVICE_ID_COMMTECH_4224PCI335 0x0002
+#define PCI_DEVICE_ID_COMMTECH_2324PCI335 0x000a
+#define PCI_DEVICE_ID_COMMTECH_2328PCI335 0x000b
+
+static int
+pci_fastcom335_setup(struct serial_private *priv,
+		  const struct pciserial_board *board,
+		  struct uart_8250_port *port, int idx)
+{
+	u8 __iomem *p;
+
+	p = pci_ioremap_bar(priv->dev, 0);
+	if (p == NULL)
+		return -ENOMEM;
+
+	port->port.flags |= UPF_EXAR_EFR;
+
+	/*
+	 * Setup Multipurpose Input/Output pins.
+	 */
+	if (idx == 0) {
+		switch (priv->dev->device) {
+		case PCI_DEVICE_ID_COMMTECH_4222PCI335:
+		case PCI_DEVICE_ID_COMMTECH_4224PCI335:
+			writeb(0x78, p + 0x90); /* MPIOLVL[7:0] */
+			writeb(0x00, p + 0x92); /* MPIOINV[7:0] */
+			writeb(0x00, p + 0x93); /* MPIOSEL[7:0] */
+			break;
+		case PCI_DEVICE_ID_COMMTECH_2324PCI335:
+		case PCI_DEVICE_ID_COMMTECH_2328PCI335:
+			writeb(0x00, p + 0x90); /* MPIOLVL[7:0] */
+			writeb(0xc0, p + 0x92); /* MPIOINV[7:0] */
+			writeb(0xc0, p + 0x93); /* MPIOSEL[7:0] */
+			break;
+		}
+		writeb(0x00, p + 0x8f); /* MPIOINT[7:0] */
+		writeb(0x00, p + 0x91); /* MPIO3T[7:0] */
+		writeb(0x00, p + 0x94); /* MPIOOD[7:0] */
+	}
+	writeb(0x00, p + UART_EXAR_8XMODE);
+	writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR);
+	writeb(32, p + UART_EXAR_TXTRG);
+	writeb(32, p + UART_EXAR_RXTRG);
+	iounmap(p);
+
+	return pci_default_setup(priv, board, port, idx);
+}
+
+static int
 pci_wch_ch353_setup(struct serial_private *priv,
                     const struct pciserial_board *board,
                     struct uart_8250_port *port, int idx)
@@ -1213,6 +1301,10 @@ pci_wch_ch353_setup(struct serial_private *priv,
 #define PCI_VENDOR_ID_AGESTAR		0x5372
 #define PCI_DEVICE_ID_AGESTAR_9375	0x6872
 #define PCI_VENDOR_ID_ASIX		0x9710
+#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0019
+#define PCI_DEVICE_ID_COMMTECH_4224PCIE	0x0020
+#define PCI_DEVICE_ID_COMMTECH_4228PCIE	0x0021
+
 
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584	0x1584
@@ -1314,7 +1406,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_ite887x_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_ite887x_exit),
+		.exit		= pci_ite887x_exit,
 	},
 	/*
 	 * National Instruments
@@ -1326,7 +1418,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_ni8420_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_ni8420_exit),
+		.exit		= pci_ni8420_exit,
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_NI,
@@ -1335,7 +1427,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_ni8420_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_ni8420_exit),
+		.exit		= pci_ni8420_exit,
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_NI,
@@ -1344,7 +1436,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_ni8420_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_ni8420_exit),
+		.exit		= pci_ni8420_exit,
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_NI,
@@ -1353,7 +1445,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_ni8420_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_ni8420_exit),
+		.exit		= pci_ni8420_exit,
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_NI,
@@ -1362,7 +1454,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_ni8420_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_ni8420_exit),
+		.exit		= pci_ni8420_exit,
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_NI,
@@ -1371,7 +1463,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_ni8420_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_ni8420_exit),
+		.exit		= pci_ni8420_exit,
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_NI,
@@ -1380,7 +1472,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_ni8420_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_ni8420_exit),
+		.exit		= pci_ni8420_exit,
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_NI,
@@ -1389,7 +1481,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_ni8420_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_ni8420_exit),
+		.exit		= pci_ni8420_exit,
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_NI,
@@ -1398,7 +1490,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_ni8420_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_ni8420_exit),
+		.exit		= pci_ni8420_exit,
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_NI,
@@ -1407,7 +1499,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_ni8420_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_ni8420_exit),
+		.exit		= pci_ni8420_exit,
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_NI,
@@ -1416,7 +1508,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_ni8420_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_ni8420_exit),
+		.exit		= pci_ni8420_exit,
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_NI,
@@ -1425,7 +1517,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_ni8420_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_ni8420_exit),
+		.exit		= pci_ni8420_exit,
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_NI,
@@ -1434,7 +1526,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_ni8430_init,
 		.setup		= pci_ni8430_setup,
-		.exit		= __devexit_p(pci_ni8430_exit),
+		.exit		= pci_ni8430_exit,
 	},
 	/*
 	 * Panacom
@@ -1446,7 +1538,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_plx9050_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_plx9050_exit),
+		.exit		= pci_plx9050_exit,
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_PANACOM,
@@ -1455,7 +1547,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.init		= pci_plx9050_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_plx9050_exit),
+		.exit		= pci_plx9050_exit,
 	},
 	/*
 	 * PLX
@@ -1474,7 +1566,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_SUBDEVICE_ID_EXSYS_4055,
 		.init		= pci_plx9050_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_plx9050_exit),
+		.exit		= pci_plx9050_exit,
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_PLX,
@@ -1483,7 +1575,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_SUBDEVICE_ID_KEYSPAN_SX2,
 		.init		= pci_plx9050_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_plx9050_exit),
+		.exit		= pci_plx9050_exit,
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_PLX,
@@ -1492,7 +1584,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
 		.init		= pci_plx9050_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_plx9050_exit),
+		.exit		= pci_plx9050_exit,
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_PLX,
@@ -1501,7 +1593,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_DEVICE_ID_PLX_ROMULUS,
 		.init		= pci_plx9050_init,
 		.setup		= pci_default_setup,
-		.exit		= __devexit_p(pci_plx9050_exit),
+		.exit		= pci_plx9050_exit,
 	},
 	/*
 	 * SBS Technologies, Inc., PMC-OCTALPRO 232
@@ -1513,7 +1605,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_SUBDEVICE_ID_OCTPRO232,
 		.init		= sbs_init,
 		.setup		= sbs_setup,
-		.exit		= __devexit_p(sbs_exit),
+		.exit		= sbs_exit,
 	},
 	/*
 	 * SBS Technologies, Inc., PMC-OCTALPRO 422
@@ -1525,7 +1617,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_SUBDEVICE_ID_OCTPRO422,
 		.init		= sbs_init,
 		.setup		= sbs_setup,
-		.exit		= __devexit_p(sbs_exit),
+		.exit		= sbs_exit,
 	},
 	/*
 	 * SBS Technologies, Inc., P-Octal 232
@@ -1537,7 +1629,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_SUBDEVICE_ID_POCTAL232,
 		.init		= sbs_init,
 		.setup		= sbs_setup,
-		.exit		= __devexit_p(sbs_exit),
+		.exit		= sbs_exit,
 	},
 	/*
 	 * SBS Technologies, Inc., P-Octal 422
@@ -1549,7 +1641,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_SUBDEVICE_ID_POCTAL422,
 		.init		= sbs_init,
 		.setup		= sbs_setup,
-		.exit		= __devexit_p(sbs_exit),
+		.exit		= sbs_exit,
 	},
 	/*
 	 * SIIG cards - these may be called via parport_serial
@@ -1622,6 +1714,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.setup		= pci_xr17c154_setup,
 	},
+	{
+		.vendor = PCI_VENDOR_ID_EXAR,
+		.device = PCI_DEVICE_ID_EXAR_XR17V352,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_xr17v35x_setup,
+	},
+	{
+		.vendor = PCI_VENDOR_ID_EXAR,
+		.device = PCI_DEVICE_ID_EXAR_XR17V354,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_xr17v35x_setup,
+	},
+	{
+		.vendor = PCI_VENDOR_ID_EXAR,
+		.device = PCI_DEVICE_ID_EXAR_XR17V358,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_xr17v35x_setup,
+	},
 	/*
 	 * Xircom cards
 	 */
@@ -1788,6 +1901,59 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.setup		= pci_asix_setup,
 	},
 	/*
+	 * Commtech, Inc. Fastcom adapters
+	 *
+	 */
+	{
+		.vendor = PCI_VENDOR_ID_COMMTECH,
+		.device = PCI_DEVICE_ID_COMMTECH_4222PCI335,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_fastcom335_setup,
+	},
+	{
+		.vendor = PCI_VENDOR_ID_COMMTECH,
+		.device = PCI_DEVICE_ID_COMMTECH_4224PCI335,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_fastcom335_setup,
+	},
+	{
+		.vendor = PCI_VENDOR_ID_COMMTECH,
+		.device = PCI_DEVICE_ID_COMMTECH_2324PCI335,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_fastcom335_setup,
+	},
+	{
+		.vendor = PCI_VENDOR_ID_COMMTECH,
+		.device = PCI_DEVICE_ID_COMMTECH_2328PCI335,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_fastcom335_setup,
+	},
+	{
+		.vendor = PCI_VENDOR_ID_COMMTECH,
+		.device = PCI_DEVICE_ID_COMMTECH_4222PCIE,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_xr17v35x_setup,
+	},
+	{
+		.vendor = PCI_VENDOR_ID_COMMTECH,
+		.device = PCI_DEVICE_ID_COMMTECH_4224PCIE,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_xr17v35x_setup,
+	},
+	{
+		.vendor = PCI_VENDOR_ID_COMMTECH,
+		.device = PCI_DEVICE_ID_COMMTECH_4228PCIE,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_xr17v35x_setup,
+	},
+	/*
 	 * Default "match everything" terminator entry
 	 */
 	{
@@ -1863,6 +2029,10 @@ enum pci_board_num_t {
 
 	pbn_b0_4_1152000,
 
+	pbn_b0_2_1152000_200,
+	pbn_b0_4_1152000_200,
+	pbn_b0_8_1152000_200,
+
 	pbn_b0_2_1843200,
 	pbn_b0_4_1843200,
 
@@ -1962,6 +2132,9 @@ enum pci_board_num_t {
 	pbn_exar_XR17C152,
 	pbn_exar_XR17C154,
 	pbn_exar_XR17C158,
+	pbn_exar_XR17V352,
+	pbn_exar_XR17V354,
+	pbn_exar_XR17V358,
 	pbn_exar_ibm_saturn,
 	pbn_pasemi_1682M,
 	pbn_ni8430_2,
@@ -1987,7 +2160,7 @@ enum pci_board_num_t {
  * see first lines of serial_in() and serial_out() in 8250.c
 */
 
-static struct pciserial_board pci_boards[] __devinitdata = {
+static struct pciserial_board pci_boards[] = {
 	[pbn_default] = {
 		.flags		= FL_BASE0,
 		.num_ports	= 1,
@@ -2057,6 +2230,27 @@ static struct pciserial_board pci_boards[] __devinitdata = {
 		.uart_offset	= 8,
 	},
 
+	[pbn_b0_2_1152000_200] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 2,
+		.base_baud	= 1152000,
+		.uart_offset	= 0x200,
+	},
+
+	[pbn_b0_4_1152000_200] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 4,
+		.base_baud	= 1152000,
+		.uart_offset	= 0x200,
+	},
+
+	[pbn_b0_8_1152000_200] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 2,
+		.base_baud	= 1152000,
+		.uart_offset	= 0x200,
+	},
+
 	[pbn_b0_2_1843200] = {
 		.flags		= FL_BASE0,
 		.num_ports	= 2,
@@ -2580,6 +2774,30 @@ static struct pciserial_board pci_boards[] __devinitdata = {
 		.base_baud	= 921600,
 		.uart_offset	= 0x200,
 	},
+	[pbn_exar_XR17V352] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 2,
+		.base_baud	= 7812500,
+		.uart_offset	= 0x400,
+		.reg_shift	= 0,
+		.first_offset	= 0,
+	},
+	[pbn_exar_XR17V354] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 4,
+		.base_baud	= 7812500,
+		.uart_offset	= 0x400,
+		.reg_shift	= 0,
+		.first_offset	= 0,
+	},
+	[pbn_exar_XR17V358] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 8,
+		.base_baud	= 7812500,
+		.uart_offset	= 0x400,
+		.reg_shift	= 0,
+		.first_offset	= 0,
+	},
 	[pbn_exar_ibm_saturn] = {
 		.flags		= FL_BASE0,
 		.num_ports	= 1,
@@ -2658,8 +2876,8 @@ static struct pciserial_board pci_boards[] __devinitdata = {
 		.first_offset	= 0x1000,
 	},
 	[pbn_ce4100_1_115200] = {
-		.flags		= FL_BASE0,
-		.num_ports	= 1,
+		.flags		= FL_BASE_BARS,
+		.num_ports	= 2,
 		.base_baud	= 921600,
 		.reg_shift      = 2,
 	},
@@ -2691,7 +2909,7 @@ static const struct pci_device_id blacklist[] = {
  * guess what the configuration might be, based on the pitiful PCI
  * serial specs.  Returns 0 on success, 1 on failure.
  */
-static int __devinit
+static int
 serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
 {
 	const struct pci_device_id *bldev;
@@ -2917,7 +3135,7 @@ EXPORT_SYMBOL_GPL(pciserial_resume_ports);
  * Probe one serial board.  Unfortunately, there is no rhyme nor reason
  * to the arrangement of serial ports on a PCI card.
  */
-static int __devinit
+static int
 pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
 {
 	struct pci_serial_quirk *quirk;
@@ -2988,7 +3206,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
 	return rc;
 }
 
-static void __devexit pciserial_remove_one(struct pci_dev *dev)
+static void pciserial_remove_one(struct pci_dev *dev)
 {
 	struct serial_private *priv = pci_get_drvdata(dev);
 
@@ -3826,6 +4044,21 @@ static struct pci_device_id serial_pci_tbl[] = {
 		PCI_ANY_ID, PCI_ANY_ID,
 		0,
 		0, pbn_exar_XR17C158 },
+	/*
+	 * Exar Corp. XR17V35[248] Dual/Quad/Octal PCIe UARTs
+	 */
+	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V352,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_exar_XR17V352 },
+	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V354,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_exar_XR17V354 },
+	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V358,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_exar_XR17V358 },
 
 	/*
 	 * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
@@ -4257,6 +4490,38 @@ static struct pci_device_id serial_pci_tbl[] = {
 		0, 0, pbn_b0_bt_2_115200 },
 
 	/*
+	 * Commtech, Inc. Fastcom adapters
+	 */
+	{	PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4222PCI335,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_b0_2_1152000_200 },
+	{	PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4224PCI335,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_b0_4_1152000_200 },
+	{	PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_2324PCI335,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_b0_4_1152000_200 },
+	{	PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_2328PCI335,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_b0_8_1152000_200 },
+	{	PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4222PCIE,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_exar_XR17V352 },
+	{	PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4224PCIE,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_exar_XR17V354 },
+	{	PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4228PCIE,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_exar_XR17V358 },
+
+	/*
 	 * These entries match devices with class COMMUNICATION_SERIAL,
 	 * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
 	 */
@@ -4323,7 +4588,7 @@ static const struct pci_error_handlers serial8250_err_handler = {
 static struct pci_driver serial_pci_driver = {
 	.name		= "serial",
 	.probe		= pciserial_init_one,
-	.remove		= __devexit_p(pciserial_remove_one),
+	.remove		= pciserial_remove_one,
 #ifdef CONFIG_PM
 	.suspend	= pciserial_suspend_one,
 	.resume		= pciserial_resume_one,
@@ -4332,18 +4597,7 @@ static struct pci_driver serial_pci_driver = {
 	.err_handler	= &serial8250_err_handler,
 };
 
-static int __init serial8250_pci_init(void)
-{
-	return pci_register_driver(&serial_pci_driver);
-}
-
-static void __exit serial8250_pci_exit(void)
-{
-	pci_unregister_driver(&serial_pci_driver);
-}
-
-module_init(serial8250_pci_init);
-module_exit(serial8250_pci_exit);
+module_pci_driver(serial_pci_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
index f8ee250..35d9ab9 100644
--- a/drivers/tty/serial/8250/8250_pnp.c
+++ b/drivers/tty/serial/8250/8250_pnp.c
@@ -370,14 +370,14 @@ static const struct pnp_device_id pnp_dev_table[] = {
 
 MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
 
-static char *modem_names[] __devinitdata = {
+static char *modem_names[] = {
 	"MODEM", "Modem", "modem", "FAX", "Fax", "fax",
 	"56K", "56k", "K56", "33.6", "28.8", "14.4",
 	"33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
 	"33600", "28800", "14400", "V.90", "V.34", "V.32", NULL
 };
 
-static int __devinit check_name(char *name)
+static int check_name(char *name)
 {
 	char **tmp;
 
@@ -388,7 +388,7 @@ static int __devinit check_name(char *name)
 	return 0;
 }
 
-static int __devinit check_resources(struct pnp_dev *dev)
+static int check_resources(struct pnp_dev *dev)
 {
 	resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8};
 	int i;
@@ -412,7 +412,7 @@ static int __devinit check_resources(struct pnp_dev *dev)
  * PnP modems, alternatively we must hardcode all modems in pnp_devices[]
  * table.
  */
-static int __devinit serial_pnp_guess_board(struct pnp_dev *dev)
+static int serial_pnp_guess_board(struct pnp_dev *dev)
 {
 	if (!(check_name(pnp_dev_name(dev)) ||
 		(dev->card && check_name(dev->card->name))))
@@ -424,7 +424,7 @@ static int __devinit serial_pnp_guess_board(struct pnp_dev *dev)
 	return -ENODEV;
 }
 
-static int __devinit
+static int
 serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
 {
 	struct uart_8250_port uart;
@@ -476,7 +476,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
 	return 0;
 }
 
-static void __devexit serial_pnp_remove(struct pnp_dev *dev)
+static void serial_pnp_remove(struct pnp_dev *dev)
 {
 	long line = (long)pnp_get_drvdata(dev);
 	if (line)
@@ -511,7 +511,7 @@ static int serial_pnp_resume(struct pnp_dev *dev)
 static struct pnp_driver serial_pnp_driver = {
 	.name		= "serial",
 	.probe		= serial_pnp_probe,
-	.remove		= __devexit_p(serial_pnp_remove),
+	.remove		= serial_pnp_remove,
 	.suspend	= serial_pnp_suspend,
 	.resume		= serial_pnp_resume,
 	.id_table	= pnp_dev_table,
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index f3d283f..c31133a 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -271,7 +271,7 @@ config SERIAL_8250_DW
 	  present in the Synopsys DesignWare APB UART.
 
 config SERIAL_8250_EM
-	tristate "Support for Emma Mobile intergrated serial port"
+	tristate "Support for Emma Mobile integrated serial port"
 	depends on SERIAL_8250 && ARM && HAVE_CLK
 	help
 	  Selecting this option will add support for the integrated serial
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 2a53be5..59c23d0 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -93,7 +93,7 @@ config SERIAL_SB1250_DUART_CONSOLE
 
 config SERIAL_ATMEL
 	bool "AT91 / AT32 on-chip serial port support"
-	depends on (ARM && ARCH_AT91) || AVR32
+	depends on ARCH_AT91 || AVR32
 	select SERIAL_CORE
 	help
 	  This enables the driver for the on-chip UARTs of the Atmel
@@ -198,7 +198,7 @@ config SERIAL_CLPS711X_CONSOLE
 
 config SERIAL_SAMSUNG
 	tristate "Samsung SoC serial support"
-	depends on ARM && PLAT_SAMSUNG
+	depends on PLAT_SAMSUNG
 	select SERIAL_CORE
 	help
 	  Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
@@ -208,14 +208,14 @@ config SERIAL_SAMSUNG
 
 config SERIAL_SAMSUNG_UARTS_4
 	bool
-	depends on ARM && PLAT_SAMSUNG
+	depends on PLAT_SAMSUNG
 	default y if !(CPU_S3C2410 || SERIAL_S3C2412 || CPU_S3C2440 || CPU_S3C2442)
 	help
 	  Internal node for the common case of 4 Samsung compatible UARTs
 
 config SERIAL_SAMSUNG_UARTS
 	int
-	depends on ARM && PLAT_SAMSUNG
+	depends on PLAT_SAMSUNG
 	default 6 if ARCH_S5P6450
 	default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416
 	default 3
@@ -249,7 +249,7 @@ config SERIAL_SAMSUNG_CONSOLE
 
 config SERIAL_SIRFSOC
         tristate "SiRF SoC Platform Serial port support"
-        depends on ARM && ARCH_PRIMA2
+        depends on ARCH_PRIMA2
         select SERIAL_CORE
         help
           Support for the on-chip UART on the CSR SiRFprimaII series,
@@ -347,7 +347,7 @@ config SERIAL_ZS_CONSOLE
 
 config SERIAL_21285
 	tristate "DC21285 serial port support"
-	depends on ARM && FOOTBRIDGE
+	depends on FOOTBRIDGE
 	select SERIAL_CORE
 	help
 	  If you have a machine based on a 21285 (Footbridge) StrongARM(R)/
@@ -371,7 +371,7 @@ config SERIAL_21285_CONSOLE
 
 config SERIAL_MPSC
 	bool "Marvell MPSC serial port support"
-	depends on PPC32 && MV64X60
+	depends on MV64X60
 	select SERIAL_CORE
 	help
 	  Say Y here if you want to use the Marvell MPSC serial controller.
@@ -408,7 +408,7 @@ config SERIAL_PXA_CONSOLE
 
 config SERIAL_SA1100
 	bool "SA1100 serial port support"
-	depends on ARM && ARCH_SA1100
+	depends on ARCH_SA1100
 	select SERIAL_CORE
 	help
 	  If you have a machine based on a SA1100/SA1110 StrongARM(R) CPU you
@@ -716,7 +716,7 @@ config SERIAL_SH_SCI_DMA
 
 config SERIAL_PNX8XXX
 	bool "Enable PNX8XXX SoCs' UART Support"
-	depends on MIPS && (SOC_PNX8550 || SOC_PNX833X)
+	depends on SOC_PNX8550 || SOC_PNX833X
 	select SERIAL_CORE
 	help
 	  If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330
@@ -1013,7 +1013,7 @@ config SERIAL_SGI_IOC3
 
 config SERIAL_MSM
 	bool "MSM on-chip serial port support"
-	depends on ARM && ARCH_MSM
+	depends on ARCH_MSM
 	select SERIAL_CORE
 
 config SERIAL_MSM_CONSOLE
@@ -1035,7 +1035,7 @@ config SERIAL_MSM_HS
 
 config SERIAL_VT8500
 	bool "VIA VT8500 on-chip serial port support"
-	depends on ARM && ARCH_VT8500
+	depends on ARCH_VT8500
 	select SERIAL_CORE
 
 config SERIAL_VT8500_CONSOLE
@@ -1045,7 +1045,7 @@ config SERIAL_VT8500_CONSOLE
 
 config SERIAL_NETX
 	tristate "NetX serial port support"
-	depends on ARM && ARCH_NETX
+	depends on ARCH_NETX
 	select SERIAL_CORE
 	help
 	  If you have a machine based on a Hilscher NetX SoC you
@@ -1376,6 +1376,7 @@ config SERIAL_MXS_AUART_CONSOLE
 
 config SERIAL_XILINX_PS_UART
 	tristate "Xilinx PS UART support"
+	depends on OF
 	select SERIAL_CORE
 	help
 	  This driver supports the Xilinx PS UART port.
@@ -1423,4 +1424,27 @@ config SERIAL_EFM32_UART_CONSOLE
 	depends on SERIAL_EFM32_UART=y
 	select SERIAL_CORE_CONSOLE
 
+config SERIAL_ARC
+	tristate "ARC UART driver support"
+	select SERIAL_CORE
+	help
+	  Driver for on-chip UART for ARC(Synopsys) for the legacy
+	  FPGA Boards (ML50x/ARCAngel4)
+
+config SERIAL_ARC_CONSOLE
+	bool "Console on ARC UART"
+	depends on SERIAL_ARC=y
+	select SERIAL_CORE_CONSOLE
+	help
+	  Enable system Console on ARC UART
+
+config SERIAL_ARC_NR_PORTS
+	int "Number of ARC UART ports"
+	depends on SERIAL_ARC
+	range 1 3
+	default "1"
+	help
+	  Set this to the number of serial ports you want the driver
+	  to support.
+
 endmenu
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 4f694da..df1b998 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -82,3 +82,4 @@ obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
 obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o
 obj-$(CONFIG_SERIAL_AR933X)   += ar933x_uart.o
 obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o
+obj-$(CONFIG_SERIAL_ARC)	+= arc_uart.o
diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c
index 530181e..872f14a 100644
--- a/drivers/tty/serial/altera_jtaguart.c
+++ b/drivers/tty/serial/altera_jtaguart.c
@@ -406,7 +406,7 @@ static struct uart_driver altera_jtaguart_driver = {
 	.cons		= ALTERA_JTAGUART_CONSOLE,
 };
 
-static int __devinit altera_jtaguart_probe(struct platform_device *pdev)
+static int altera_jtaguart_probe(struct platform_device *pdev)
 {
 	struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data;
 	struct uart_port *port;
@@ -453,7 +453,7 @@ static int __devinit altera_jtaguart_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit altera_jtaguart_remove(struct platform_device *pdev)
+static int altera_jtaguart_remove(struct platform_device *pdev)
 {
 	struct uart_port *port;
 	int i = pdev->id;
@@ -477,7 +477,7 @@ MODULE_DEVICE_TABLE(of, altera_jtaguart_match);
 
 static struct platform_driver altera_jtaguart_platform_driver = {
 	.probe	= altera_jtaguart_probe,
-	.remove	= __devexit_p(altera_jtaguart_remove),
+	.remove	= altera_jtaguart_remove,
 	.driver	= {
 		.name		= DRV_NAME,
 		.owner		= THIS_MODULE,
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 15d80b9..684a080 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -532,7 +532,7 @@ static int altera_uart_get_of_uartclk(struct platform_device *pdev,
 }
 #endif /* CONFIG_OF */
 
-static int __devinit altera_uart_probe(struct platform_device *pdev)
+static int altera_uart_probe(struct platform_device *pdev)
 {
 	struct altera_uart_platform_uart *platp = pdev->dev.platform_data;
 	struct uart_port *port;
@@ -598,7 +598,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit altera_uart_remove(struct platform_device *pdev)
+static int altera_uart_remove(struct platform_device *pdev)
 {
 	struct uart_port *port = platform_get_drvdata(pdev);
 
@@ -621,7 +621,7 @@ MODULE_DEVICE_TABLE(of, altera_uart_match);
 
 static struct platform_driver altera_uart_platform_driver = {
 	.probe	= altera_uart_probe,
-	.remove	= __devexit_p(altera_uart_remove),
+	.remove	= altera_uart_remove,
 	.driver	= {
 		.name		= DRV_NAME,
 		.owner		= THIS_MODULE,
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index d7e1ede..7fca402 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -56,8 +56,7 @@
 #include <linux/of_device.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/sizes.h>
-
-#include <asm/io.h>
+#include <linux/io.h>
 
 #define UART_NR			14
 
@@ -1973,7 +1972,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 		goto out;
 	}
 
-	uap = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
+	uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
+			   GFP_KERNEL);
 	if (uap == NULL) {
 		ret = -ENOMEM;
 		goto out;
@@ -1981,16 +1981,17 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 
 	i = pl011_probe_dt_alias(i, &dev->dev);
 
-	base = ioremap(dev->res.start, resource_size(&dev->res));
+	base = devm_ioremap(&dev->dev, dev->res.start,
+			    resource_size(&dev->res));
 	if (!base) {
 		ret = -ENOMEM;
-		goto free;
+		goto out;
 	}
 
 	uap->pinctrl = devm_pinctrl_get(&dev->dev);
 	if (IS_ERR(uap->pinctrl)) {
 		ret = PTR_ERR(uap->pinctrl);
-		goto unmap;
+		goto out;
 	}
 	uap->pins_default = pinctrl_lookup_state(uap->pinctrl,
 						 PINCTRL_STATE_DEFAULT);
@@ -2002,10 +2003,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 	if (IS_ERR(uap->pins_sleep))
 		dev_dbg(&dev->dev, "could not get sleep pinstate\n");
 
-	uap->clk = clk_get(&dev->dev, NULL);
+	uap->clk = devm_clk_get(&dev->dev, NULL);
 	if (IS_ERR(uap->clk)) {
 		ret = PTR_ERR(uap->clk);
-		goto unmap;
+		goto out;
 	}
 
 	uap->vendor = vendor;
@@ -2038,11 +2039,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 		amba_set_drvdata(dev, NULL);
 		amba_ports[i] = NULL;
 		pl011_dma_remove(uap);
-		clk_put(uap->clk);
- unmap:
-		iounmap(base);
- free:
-		kfree(uap);
 	}
  out:
 	return ret;
@@ -2062,9 +2058,6 @@ static int pl011_remove(struct amba_device *dev)
 			amba_ports[i] = NULL;
 
 	pl011_dma_remove(uap);
-	iounmap(uap->port.membase);
-	clk_put(uap->clk);
-	kfree(uap);
 	return 0;
 }
 
diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c
index 7162f70..59ae2b5 100644
--- a/drivers/tty/serial/apbuart.c
+++ b/drivers/tty/serial/apbuart.c
@@ -554,7 +554,7 @@ static struct uart_driver grlib_apbuart_driver = {
 /* OF Platform Driver                                                       */
 /* ======================================================================== */
 
-static int __devinit apbuart_probe(struct platform_device *op)
+static int apbuart_probe(struct platform_device *op)
 {
 	int i;
 	struct uart_port *port = NULL;
diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c
index e4f60e2..505c490 100644
--- a/drivers/tty/serial/ar933x_uart.c
+++ b/drivers/tty/serial/ar933x_uart.c
@@ -25,11 +25,19 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 
+#include <asm/div64.h>
+
 #include <asm/mach-ath79/ar933x_uart.h>
 #include <asm/mach-ath79/ar933x_uart_platform.h>
 
 #define DRIVER_NAME "ar933x-uart"
 
+#define AR933X_UART_MAX_SCALE	0xff
+#define AR933X_UART_MAX_STEP	0xffff
+
+#define AR933X_UART_MIN_BAUD	300
+#define AR933X_UART_MAX_BAUD	3000000
+
 #define AR933X_DUMMY_STATUS_RD	0x01
 
 static struct uart_driver ar933x_uart_driver;
@@ -37,6 +45,8 @@ static struct uart_driver ar933x_uart_driver;
 struct ar933x_uart_port {
 	struct uart_port	port;
 	unsigned int		ier;	/* shadow Interrupt Enable Register */
+	unsigned int		min_baud;
+	unsigned int		max_baud;
 };
 
 static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up,
@@ -162,6 +172,57 @@ static void ar933x_uart_enable_ms(struct uart_port *port)
 {
 }
 
+/*
+ * baudrate = (clk / (scale + 1)) * (step * (1 / 2^17))
+ */
+static unsigned long ar933x_uart_get_baud(unsigned int clk,
+					  unsigned int scale,
+					  unsigned int step)
+{
+	u64 t;
+	u32 div;
+
+	div = (2 << 16) * (scale + 1);
+	t = clk;
+	t *= step;
+	t += (div / 2);
+	do_div(t, div);
+
+	return t;
+}
+
+static void ar933x_uart_get_scale_step(unsigned int clk,
+				       unsigned int baud,
+				       unsigned int *scale,
+				       unsigned int *step)
+{
+	unsigned int tscale;
+	long min_diff;
+
+	*scale = 0;
+	*step = 0;
+
+	min_diff = baud;
+	for (tscale = 0; tscale < AR933X_UART_MAX_SCALE; tscale++) {
+		u64 tstep;
+		int diff;
+
+		tstep = baud * (tscale + 1);
+		tstep *= (2 << 16);
+		do_div(tstep, clk);
+
+		if (tstep > AR933X_UART_MAX_STEP)
+			break;
+
+		diff = abs(ar933x_uart_get_baud(clk, tscale, tstep) - baud);
+		if (diff < min_diff) {
+			min_diff = diff;
+			*scale = tscale;
+			*step = tstep;
+		}
+	}
+}
+
 static void ar933x_uart_set_termios(struct uart_port *port,
 				    struct ktermios *new,
 				    struct ktermios *old)
@@ -169,7 +230,7 @@ static void ar933x_uart_set_termios(struct uart_port *port,
 	struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
 	unsigned int cs;
 	unsigned long flags;
-	unsigned int baud, scale;
+	unsigned int baud, scale, step;
 
 	/* Only CS8 is supported */
 	new->c_cflag &= ~CSIZE;
@@ -191,8 +252,8 @@ static void ar933x_uart_set_termios(struct uart_port *port,
 	/* Mark/space parity is not supported */
 	new->c_cflag &= ~CMSPAR;
 
-	baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
-	scale = (port->uartclk / (16 * baud)) - 1;
+	baud = uart_get_baud_rate(port, new, old, up->min_baud, up->max_baud);
+	ar933x_uart_get_scale_step(port->uartclk, baud, &scale, &step);
 
 	/*
 	 * Ok, we're now changing the port state. Do it with
@@ -200,6 +261,10 @@ static void ar933x_uart_set_termios(struct uart_port *port,
 	 */
 	spin_lock_irqsave(&up->port.lock, flags);
 
+	/* disable the UART */
+	ar933x_uart_rmw_clear(up, AR933X_UART_CS_REG,
+		      AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S);
+
 	/* Update the per-port timeout. */
 	uart_update_timeout(port, new->c_cflag, baud);
 
@@ -210,7 +275,7 @@ static void ar933x_uart_set_termios(struct uart_port *port,
 		up->port.ignore_status_mask |= AR933X_DUMMY_STATUS_RD;
 
 	ar933x_uart_write(up, AR933X_UART_CLOCK_REG,
-			  scale << AR933X_UART_CLOCK_SCALE_S | 8192);
+			  scale << AR933X_UART_CLOCK_SCALE_S | step);
 
 	/* setup configuration register */
 	ar933x_uart_rmw(up, AR933X_UART_CS_REG, AR933X_UART_CS_PARITY_M, cs);
@@ -219,6 +284,11 @@ static void ar933x_uart_set_termios(struct uart_port *port,
 	ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
 			    AR933X_UART_CS_HOST_INT_EN);
 
+	/* reenable the UART */
+	ar933x_uart_rmw(up, AR933X_UART_CS_REG,
+			AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S,
+			AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S);
+
 	spin_unlock_irqrestore(&up->port.lock, flags);
 
 	if (tty_termios_baud_rate(new))
@@ -401,6 +471,8 @@ static void ar933x_uart_config_port(struct uart_port *port, int flags)
 static int ar933x_uart_verify_port(struct uart_port *port,
 				   struct serial_struct *ser)
 {
+	struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
+
 	if (ser->type != PORT_UNKNOWN &&
 	    ser->type != PORT_AR933X)
 		return -EINVAL;
@@ -408,7 +480,8 @@ static int ar933x_uart_verify_port(struct uart_port *port,
 	if (ser->irq < 0 || ser->irq >= NR_IRQS)
 		return -EINVAL;
 
-	if (ser->baud_base < 28800)
+	if (ser->baud_base < up->min_baud ||
+	    ser->baud_base > up->max_baud)
 		return -EINVAL;
 
 	return 0;
@@ -554,13 +627,14 @@ static struct uart_driver ar933x_uart_driver = {
 	.cons		= AR933X_SERIAL_CONSOLE,
 };
 
-static int __devinit ar933x_uart_probe(struct platform_device *pdev)
+static int ar933x_uart_probe(struct platform_device *pdev)
 {
 	struct ar933x_uart_platform_data *pdata;
 	struct ar933x_uart_port *up;
 	struct uart_port *port;
 	struct resource *mem_res;
 	struct resource *irq_res;
+	unsigned int baud;
 	int id;
 	int ret;
 
@@ -611,6 +685,12 @@ static int __devinit ar933x_uart_probe(struct platform_device *pdev)
 	port->fifosize = AR933X_UART_FIFO_SIZE;
 	port->ops = &ar933x_uart_ops;
 
+	baud = ar933x_uart_get_baud(port->uartclk, AR933X_UART_MAX_SCALE, 1);
+	up->min_baud = max_t(unsigned int, baud, AR933X_UART_MIN_BAUD);
+
+	baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP);
+	up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD);
+
 	ar933x_uart_add_console_port(up);
 
 	ret = uart_add_one_port(&ar933x_uart_driver, &up->port);
@@ -627,7 +707,7 @@ err_free_up:
 	return ret;
 }
 
-static int __devexit ar933x_uart_remove(struct platform_device *pdev)
+static int ar933x_uart_remove(struct platform_device *pdev)
 {
 	struct ar933x_uart_port *up;
 
@@ -645,7 +725,7 @@ static int __devexit ar933x_uart_remove(struct platform_device *pdev)
 
 static struct platform_driver ar933x_uart_platform_driver = {
 	.probe		= ar933x_uart_probe,
-	.remove		= __devexit_p(ar933x_uart_remove),
+	.remove		= ar933x_uart_remove,
 	.driver		= {
 		.name		= DRIVER_NAME,
 		.owner		= THIS_MODULE,
diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
new file mode 100644
index 0000000..3e0b3fa
--- /dev/null
+++ b/drivers/tty/serial/arc_uart.c
@@ -0,0 +1,746 @@
+/*
+ * ARC On-Chip(fpga) UART Driver
+ *
+ * Copyright (C) 2010-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.
+ *
+ * vineetg: July 10th 2012
+ *  -Decoupled the driver from arch/arc
+ *    +Using platform_get_resource() for irq/membase (thx to bfin_uart.c)
+ *    +Using early_platform_xxx() for early console (thx to mach-shmobile/xxx)
+ *
+ * Vineetg: Aug 21st 2010
+ *  -Is uart_tx_stopped() not done in tty write path as it has already been
+ *   taken care of, in serial core
+ *
+ * Vineetg: Aug 18th 2010
+ *  -New Serial Core based ARC UART driver
+ *  -Derived largely from blackfin driver albiet with some major tweaks
+ *
+ * TODO:
+ *  -check if sysreq works
+ */
+
+#if defined(CONFIG_SERIAL_ARC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/platform_device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+
+/*************************************
+ * ARC UART Hardware Specs
+ ************************************/
+#define ARC_UART_TX_FIFO_SIZE  1
+
+/*
+ * UART Register set (this is not a Standards Compliant IP)
+ * Also each reg is Word aligned, but only 8 bits wide
+ */
+#define R_ID0	0
+#define R_ID1	4
+#define R_ID2	8
+#define R_ID3	12
+#define R_DATA	16
+#define R_STS	20
+#define R_BAUDL	24
+#define R_BAUDH	28
+
+/* Bits for UART Status Reg (R/W) */
+#define RXIENB  0x04	/* Receive Interrupt Enable */
+#define TXIENB  0x40	/* Transmit Interrupt Enable */
+
+#define RXEMPTY 0x20	/* Receive FIFO Empty: No char receivede */
+#define TXEMPTY 0x80	/* Transmit FIFO Empty, thus char can be written into */
+
+#define RXFULL  0x08	/* Receive FIFO full */
+#define RXFULL1 0x10	/* Receive FIFO has space for 1 char (tot space=4) */
+
+#define RXFERR  0x01	/* Frame Error: Stop Bit not detected */
+#define RXOERR  0x02	/* OverFlow Err: Char recv but RXFULL still set */
+
+/* Uart bit fiddling helpers: lowest level */
+#define RBASE(uart, reg)      (uart->port.membase + reg)
+#define UART_REG_SET(u, r, v) writeb((v), RBASE(u, r))
+#define UART_REG_GET(u, r)    readb(RBASE(u, r))
+
+#define UART_REG_OR(u, r, v)  UART_REG_SET(u, r, UART_REG_GET(u, r) | (v))
+#define UART_REG_CLR(u, r, v) UART_REG_SET(u, r, UART_REG_GET(u, r) & ~(v))
+
+/* Uart bit fiddling helpers: API level */
+#define UART_SET_DATA(uart, val)   UART_REG_SET(uart, R_DATA, val)
+#define UART_GET_DATA(uart)        UART_REG_GET(uart, R_DATA)
+
+#define UART_SET_BAUDH(uart, val)  UART_REG_SET(uart, R_BAUDH, val)
+#define UART_SET_BAUDL(uart, val)  UART_REG_SET(uart, R_BAUDL, val)
+
+#define UART_CLR_STATUS(uart, val) UART_REG_CLR(uart, R_STS, val)
+#define UART_GET_STATUS(uart)      UART_REG_GET(uart, R_STS)
+
+#define UART_ALL_IRQ_DISABLE(uart) UART_REG_CLR(uart, R_STS, RXIENB|TXIENB)
+#define UART_RX_IRQ_DISABLE(uart)  UART_REG_CLR(uart, R_STS, RXIENB)
+#define UART_TX_IRQ_DISABLE(uart)  UART_REG_CLR(uart, R_STS, TXIENB)
+
+#define UART_ALL_IRQ_ENABLE(uart)  UART_REG_OR(uart, R_STS, RXIENB|TXIENB)
+#define UART_RX_IRQ_ENABLE(uart)   UART_REG_OR(uart, R_STS, RXIENB)
+#define UART_TX_IRQ_ENABLE(uart)   UART_REG_OR(uart, R_STS, TXIENB)
+
+#define ARC_SERIAL_DEV_NAME	"ttyARC"
+
+struct arc_uart_port {
+	struct uart_port port;
+	unsigned long baud;
+	int is_emulated;	/* H/w vs. Instruction Set Simulator */
+};
+
+#define to_arc_port(uport)  container_of(uport, struct arc_uart_port, port)
+
+static struct arc_uart_port arc_uart_ports[CONFIG_SERIAL_ARC_NR_PORTS];
+
+#ifdef CONFIG_SERIAL_ARC_CONSOLE
+static struct console arc_console;
+#endif
+
+#define DRIVER_NAME	"arc-uart"
+
+static struct uart_driver arc_uart_driver = {
+	.owner		= THIS_MODULE,
+	.driver_name	= DRIVER_NAME,
+	.dev_name	= ARC_SERIAL_DEV_NAME,
+	.major		= 0,
+	.minor		= 0,
+	.nr		= CONFIG_SERIAL_ARC_NR_PORTS,
+#ifdef CONFIG_SERIAL_ARC_CONSOLE
+	.cons		= &arc_console,
+#endif
+};
+
+static void arc_serial_stop_rx(struct uart_port *port)
+{
+	struct arc_uart_port *uart = to_arc_port(port);
+
+	UART_RX_IRQ_DISABLE(uart);
+}
+
+static void arc_serial_stop_tx(struct uart_port *port)
+{
+	struct arc_uart_port *uart = to_arc_port(port);
+
+	while (!(UART_GET_STATUS(uart) & TXEMPTY))
+		cpu_relax();
+
+	UART_TX_IRQ_DISABLE(uart);
+}
+
+/*
+ * Return TIOCSER_TEMT when transmitter is not busy.
+ */
+static unsigned int arc_serial_tx_empty(struct uart_port *port)
+{
+	struct arc_uart_port *uart = to_arc_port(port);
+	unsigned int stat;
+
+	stat = UART_GET_STATUS(uart);
+	if (stat & TXEMPTY)
+		return TIOCSER_TEMT;
+
+	return 0;
+}
+
+/*
+ * Driver internal routine, used by both tty(serial core) as well as tx-isr
+ *  -Called under spinlock in either cases
+ *  -also tty->stopped / tty->hw_stopped has already been checked
+ *     = by uart_start( ) before calling us
+ *     = tx_ist checks that too before calling
+ */
+static void arc_serial_tx_chars(struct arc_uart_port *uart)
+{
+	struct circ_buf *xmit = &uart->port.state->xmit;
+	int sent = 0;
+	unsigned char ch;
+
+	if (unlikely(uart->port.x_char)) {
+		UART_SET_DATA(uart, uart->port.x_char);
+		uart->port.icount.tx++;
+		uart->port.x_char = 0;
+		sent = 1;
+	} else if (xmit->tail != xmit->head) {	/* TODO: uart_circ_empty */
+		ch = xmit->buf[xmit->tail];
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		uart->port.icount.tx++;
+		while (!(UART_GET_STATUS(uart) & TXEMPTY))
+			cpu_relax();
+		UART_SET_DATA(uart, ch);
+		sent = 1;
+	}
+
+	/*
+	 * If num chars in xmit buffer are too few, ask tty layer for more.
+	 * By Hard ISR to schedule processing in software interrupt part
+	 */
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&uart->port);
+
+	if (sent)
+		UART_TX_IRQ_ENABLE(uart);
+}
+
+/*
+ * port is locked and interrupts are disabled
+ * uart_start( ) calls us under the port spinlock irqsave
+ */
+static void arc_serial_start_tx(struct uart_port *port)
+{
+	struct arc_uart_port *uart = to_arc_port(port);
+
+	arc_serial_tx_chars(uart);
+}
+
+static void arc_serial_rx_chars(struct arc_uart_port *uart)
+{
+	struct tty_struct *tty = tty_port_tty_get(&uart->port.state->port);
+	unsigned int status, ch, flg = 0;
+
+	if (!tty)
+		return;
+
+	/*
+	 * UART has 4 deep RX-FIFO. Driver's recongnition of this fact
+	 * is very subtle. Here's how ...
+	 * Upon getting a RX-Intr, such that RX-EMPTY=0, meaning data available,
+	 * driver reads the DATA Reg and keeps doing that in a loop, until
+	 * RX-EMPTY=1. Multiple chars being avail, with a single Interrupt,
+	 * before RX-EMPTY=0, implies some sort of buffering going on in the
+	 * controller, which is indeed the Rx-FIFO.
+	 */
+	while (!((status = UART_GET_STATUS(uart)) & RXEMPTY)) {
+
+		ch = UART_GET_DATA(uart);
+		uart->port.icount.rx++;
+
+		if (unlikely(status & (RXOERR | RXFERR))) {
+			if (status & RXOERR) {
+				uart->port.icount.overrun++;
+				flg = TTY_OVERRUN;
+				UART_CLR_STATUS(uart, RXOERR);
+			}
+
+			if (status & RXFERR) {
+				uart->port.icount.frame++;
+				flg = TTY_FRAME;
+				UART_CLR_STATUS(uart, RXFERR);
+			}
+		} else
+			flg = TTY_NORMAL;
+
+		if (unlikely(uart_handle_sysrq_char(&uart->port, ch)))
+			goto done;
+
+		uart_insert_char(&uart->port, status, RXOERR, ch, flg);
+
+done:
+		tty_flip_buffer_push(tty);
+	}
+
+	tty_kref_put(tty);
+}
+
+/*
+ * A note on the Interrupt handling state machine of this driver
+ *
+ * kernel printk writes funnel thru the console driver framework and in order
+ * to keep things simple as well as efficient, it writes to UART in polled
+ * mode, in one shot, and exits.
+ *
+ * OTOH, Userland output (via tty layer), uses interrupt based writes as there
+ * can be undeterministic delay between char writes.
+ *
+ * Thus Rx-interrupts are always enabled, while tx-interrupts are by default
+ * disabled.
+ *
+ * When tty has some data to send out, serial core calls driver's start_tx
+ * which
+ *   -checks-if-tty-buffer-has-char-to-send
+ *   -writes-data-to-uart
+ *   -enable-tx-intr
+ *
+ * Once data bits are pushed out, controller raises the Tx-room-avail-Interrupt.
+ * The first thing Tx ISR does is disable further Tx interrupts (as this could
+ * be the last char to send, before settling down into the quiet polled mode).
+ * It then calls the exact routine used by tty layer write to send out any
+ * more char in tty buffer. In case of sending, it re-enables Tx-intr. In case
+ * of no data, it remains disabled.
+ * This is how the transmit state machine is dynamically switched on/off
+ */
+
+static irqreturn_t arc_serial_isr(int irq, void *dev_id)
+{
+	struct arc_uart_port *uart = dev_id;
+	unsigned int status;
+
+	status = UART_GET_STATUS(uart);
+
+	/*
+	 * Single IRQ for both Rx (data available) Tx (room available) Interrupt
+	 * notifications from the UART Controller.
+	 * To demultiplex between the two, we check the relevant bits
+	 */
+	if ((status & RXIENB) && !(status & RXEMPTY)) {
+
+		/* already in ISR, no need of xx_irqsave */
+		spin_lock(&uart->port.lock);
+		arc_serial_rx_chars(uart);
+		spin_unlock(&uart->port.lock);
+	}
+
+	if ((status & TXIENB) && (status & TXEMPTY)) {
+
+		/* Unconditionally disable further Tx-Interrupts.
+		 * will be enabled by tx_chars() if needed.
+		 */
+		UART_TX_IRQ_DISABLE(uart);
+
+		spin_lock(&uart->port.lock);
+
+		if (!uart_tx_stopped(&uart->port))
+			arc_serial_tx_chars(uart);
+
+		spin_unlock(&uart->port.lock);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static unsigned int arc_serial_get_mctrl(struct uart_port *port)
+{
+	/*
+	 * Pretend we have a Modem status reg and following bits are
+	 *  always set, to satify the serial core state machine
+	 *  (DSR) Data Set Ready
+	 *  (CTS) Clear To Send
+	 *  (CAR) Carrier Detect
+	 */
+	return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+}
+
+static void arc_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	/* MCR not present */
+}
+
+/* Enable Modem Status Interrupts */
+
+static void arc_serial_enable_ms(struct uart_port *port)
+{
+	/* MSR not present */
+}
+
+static void arc_serial_break_ctl(struct uart_port *port, int break_state)
+{
+	/* ARC UART doesn't support sending Break signal */
+}
+
+static int arc_serial_startup(struct uart_port *port)
+{
+	struct arc_uart_port *uart = to_arc_port(port);
+
+	/* Before we hook up the ISR, Disable all UART Interrupts */
+	UART_ALL_IRQ_DISABLE(uart);
+
+	if (request_irq(uart->port.irq, arc_serial_isr, 0, "arc uart rx-tx",
+			uart)) {
+		dev_warn(uart->port.dev, "Unable to attach ARC UART intr\n");
+		return -EBUSY;
+	}
+
+	UART_RX_IRQ_ENABLE(uart); /* Only Rx IRQ enabled to begin with */
+
+	return 0;
+}
+
+/* This is not really needed */
+static void arc_serial_shutdown(struct uart_port *port)
+{
+	struct arc_uart_port *uart = to_arc_port(port);
+	free_irq(uart->port.irq, uart);
+}
+
+static void
+arc_serial_set_termios(struct uart_port *port, struct ktermios *new,
+		       struct ktermios *old)
+{
+	struct arc_uart_port *uart = to_arc_port(port);
+	unsigned int baud, uartl, uarth, hw_val;
+	unsigned long flags;
+
+	/*
+	 * Use the generic handler so that any specially encoded baud rates
+	 * such as SPD_xx flags or "%B0" can be handled
+	 * Max Baud I suppose will not be more than current 115K * 4
+	 * Formula for ARC UART is: hw-val = ((CLK/(BAUD*4)) -1)
+	 * spread over two 8-bit registers
+	 */
+	baud = uart_get_baud_rate(port, new, old, 0, 460800);
+
+	hw_val = port->uartclk / (uart->baud * 4) - 1;
+	uartl = hw_val & 0xFF;
+	uarth = (hw_val >> 8) & 0xFF;
+
+	/*
+	 * UART ISS(Instruction Set simulator) emulation has a subtle bug:
+	 * A existing value of Baudh = 0 is used as a indication to startup
+	 * it's internal state machine.
+	 * Thus if baudh is set to 0, 2 times, it chokes.
+	 * This happens with BAUD=115200 and the formaula above
+	 * Until that is fixed, when running on ISS, we will set baudh to !0
+	 */
+	if (uart->is_emulated)
+		uarth = 1;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	UART_ALL_IRQ_DISABLE(uart);
+
+	UART_SET_BAUDL(uart, uartl);
+	UART_SET_BAUDH(uart, uarth);
+
+	UART_RX_IRQ_ENABLE(uart);
+
+	/*
+	 * UART doesn't support Parity/Hardware Flow Control;
+	 * Only supports 8N1 character size
+	 */
+	new->c_cflag &= ~(CMSPAR|CRTSCTS|CSIZE);
+	new->c_cflag |= CS8;
+
+	if (old)
+		tty_termios_copy_hw(new, old);
+
+	/* Don't rewrite B0 */
+	if (tty_termios_baud_rate(new))
+		tty_termios_encode_baud_rate(new, baud, baud);
+
+	uart_update_timeout(port, new->c_cflag, baud);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *arc_serial_type(struct uart_port *port)
+{
+	struct arc_uart_port *uart = to_arc_port(port);
+
+	return uart->port.type == PORT_ARC ? DRIVER_NAME : NULL;
+}
+
+static void arc_serial_release_port(struct uart_port *port)
+{
+}
+
+static int arc_serial_request_port(struct uart_port *port)
+{
+	return 0;
+}
+
+/*
+ * Verify the new serial_struct (for TIOCSSERIAL).
+ */
+static int
+arc_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	if (port->type != PORT_UNKNOWN && ser->type != PORT_ARC)
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * Configure/autoconfigure the port.
+ */
+static void arc_serial_config_port(struct uart_port *port, int flags)
+{
+	struct arc_uart_port *uart = to_arc_port(port);
+
+	if (flags & UART_CONFIG_TYPE)
+		uart->port.type = PORT_ARC;
+}
+
+#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_ARC_CONSOLE)
+
+static void arc_serial_poll_putchar(struct uart_port *port, unsigned char chr)
+{
+	struct arc_uart_port *uart = to_arc_port(port);
+
+	while (!(UART_GET_STATUS(uart) & TXEMPTY))
+		cpu_relax();
+
+	UART_SET_DATA(uart, chr);
+}
+#endif
+
+#ifdef CONFIG_CONSOLE_POLL
+static int arc_serial_poll_getchar(struct uart_port *port)
+{
+	struct arc_uart_port *uart = to_arc_port(port);
+	unsigned char chr;
+
+	while (!(UART_GET_STATUS(uart) & RXEMPTY))
+		cpu_relax();
+
+	chr = UART_GET_DATA(uart);
+	return chr;
+}
+#endif
+
+static struct uart_ops arc_serial_pops = {
+	.tx_empty	= arc_serial_tx_empty,
+	.set_mctrl	= arc_serial_set_mctrl,
+	.get_mctrl	= arc_serial_get_mctrl,
+	.stop_tx	= arc_serial_stop_tx,
+	.start_tx	= arc_serial_start_tx,
+	.stop_rx	= arc_serial_stop_rx,
+	.enable_ms	= arc_serial_enable_ms,
+	.break_ctl	= arc_serial_break_ctl,
+	.startup	= arc_serial_startup,
+	.shutdown	= arc_serial_shutdown,
+	.set_termios	= arc_serial_set_termios,
+	.type		= arc_serial_type,
+	.release_port	= arc_serial_release_port,
+	.request_port	= arc_serial_request_port,
+	.config_port	= arc_serial_config_port,
+	.verify_port	= arc_serial_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_put_char = arc_serial_poll_putchar,
+	.poll_get_char = arc_serial_poll_getchar,
+#endif
+};
+
+static int
+arc_uart_init_one(struct platform_device *pdev, struct arc_uart_port *uart)
+{
+	struct resource *res, *res2;
+	unsigned long *plat_data;
+
+	if (pdev->id < 0 || pdev->id >= CONFIG_SERIAL_ARC_NR_PORTS) {
+		dev_err(&pdev->dev, "Wrong uart platform device id.\n");
+		return -ENOENT;
+	}
+
+	plat_data = ((unsigned long *)(pdev->dev.platform_data));
+	uart->baud = plat_data[0];
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res2)
+		return -ENODEV;
+
+	uart->port.mapbase = res->start;
+	uart->port.membase = ioremap_nocache(res->start, resource_size(res));
+	if (!uart->port.membase)
+		/* No point of dev_err since UART itself is hosed here */
+		return -ENXIO;
+
+	uart->port.irq = res2->start;
+	uart->port.dev = &pdev->dev;
+	uart->port.iotype = UPIO_MEM;
+	uart->port.flags = UPF_BOOT_AUTOCONF;
+	uart->port.line = pdev->id;
+	uart->port.ops = &arc_serial_pops;
+
+	uart->port.uartclk = plat_data[1];
+	uart->port.fifosize = ARC_UART_TX_FIFO_SIZE;
+
+	/*
+	 * uart_insert_char( ) uses it in decideding whether to ignore a
+	 * char or not. Explicitly setting it here, removes the subtelty
+	 */
+	uart->port.ignore_status_mask = 0;
+
+	/* Real Hardware vs. emulated to work around a bug */
+	uart->is_emulated = !!plat_data[2];
+
+	return 0;
+}
+
+#ifdef CONFIG_SERIAL_ARC_CONSOLE
+
+static int arc_serial_console_setup(struct console *co, char *options)
+{
+	struct uart_port *port;
+	int baud = 115200;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	if (co->index < 0 || co->index >= CONFIG_SERIAL_ARC_NR_PORTS)
+		return -ENODEV;
+
+	/*
+	 * The uart port backing the console (e.g. ttyARC1) might not have been
+	 * init yet. If so, defer the console setup to after the port.
+	 */
+	port = &arc_uart_ports[co->index].port;
+	if (!port->membase)
+		return -ENODEV;
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	/*
+	 * Serial core will call port->ops->set_termios( )
+	 * which will set the baud reg
+	 */
+	return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static void arc_serial_console_putchar(struct uart_port *port, int ch)
+{
+	arc_serial_poll_putchar(port, (unsigned char)ch);
+}
+
+/*
+ * Interrupts are disabled on entering
+ */
+static void arc_serial_console_write(struct console *co, const char *s,
+				     unsigned int count)
+{
+	struct uart_port *port = &arc_uart_ports[co->index].port;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	uart_console_write(port, s, count, arc_serial_console_putchar);
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static struct console arc_console = {
+	.name	= ARC_SERIAL_DEV_NAME,
+	.write	= arc_serial_console_write,
+	.device	= uart_console_device,
+	.setup	= arc_serial_console_setup,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
+	.data	= &arc_uart_driver
+};
+
+static __init void early_serial_write(struct console *con, const char *s,
+					unsigned int n)
+{
+	struct uart_port *port = &arc_uart_ports[con->index].port;
+	unsigned int i;
+
+	for (i = 0; i < n; i++, s++) {
+		if (*s == '\n')
+			arc_serial_poll_putchar(port, '\r');
+		arc_serial_poll_putchar(port, *s);
+	}
+}
+
+static struct __initdata console arc_early_serial_console = {
+	.name = "early_ARCuart",
+	.write = early_serial_write,
+	.flags = CON_PRINTBUFFER | CON_BOOT,
+	.index = -1
+};
+
+static int arc_serial_probe_earlyprintk(struct platform_device *pdev)
+{
+	arc_early_serial_console.index = pdev->id;
+
+	arc_uart_init_one(pdev, &arc_uart_ports[pdev->id]);
+
+	arc_serial_console_setup(&arc_early_serial_console, NULL);
+
+	register_console(&arc_early_serial_console);
+	return 0;
+}
+#else
+static int arc_serial_probe_earlyprintk(struct platform_device *pdev)
+{
+	return -ENODEV;
+}
+#endif	/* CONFIG_SERIAL_ARC_CONSOLE */
+
+static int arc_serial_probe(struct platform_device *pdev)
+{
+	struct arc_uart_port *uart;
+	int rc;
+
+	if (is_early_platform_device(pdev))
+		return arc_serial_probe_earlyprintk(pdev);
+
+	uart = &arc_uart_ports[pdev->id];
+	rc = arc_uart_init_one(pdev, uart);
+	if (rc)
+		return rc;
+
+	return uart_add_one_port(&arc_uart_driver, &uart->port);
+}
+
+static int arc_serial_remove(struct platform_device *pdev)
+{
+	/* This will never be called */
+	return 0;
+}
+
+static struct platform_driver arc_platform_driver = {
+	.probe = arc_serial_probe,
+	.remove = arc_serial_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+	 },
+};
+
+#ifdef CONFIG_SERIAL_ARC_CONSOLE
+/*
+ * Register an early platform driver of "earlyprintk" class.
+ * ARCH platform code installs the driver and probes the early devices
+ * The installation could rely on user specifying earlyprintk=xyx in cmd line
+ * or it could be done independently, for all "earlyprintk" class drivers.
+ * [see arch/arc/plat-arcfpga/platform.c]
+ */
+early_platform_init("earlyprintk", &arc_platform_driver);
+
+#endif  /* CONFIG_SERIAL_ARC_CONSOLE */
+
+static int __init arc_serial_init(void)
+{
+	int ret;
+
+	ret = uart_register_driver(&arc_uart_driver);
+	if (ret)
+		return ret;
+
+	ret = platform_driver_register(&arc_platform_driver);
+	if (ret)
+		uart_unregister_driver(&arc_uart_driver);
+
+	return ret;
+}
+
+static void __exit arc_serial_exit(void)
+{
+	platform_driver_unregister(&arc_platform_driver);
+	uart_unregister_driver(&arc_uart_driver);
+}
+
+module_init(arc_serial_init);
+module_exit(arc_serial_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("plat-arcfpga/uart");
+MODULE_AUTHOR("Vineet Gupta");
+MODULE_DESCRIPTION("ARC(Synopsys) On-Chip(fpga) serial driver");
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 3d7e1ee..922e85a 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -39,13 +39,12 @@
 #include <linux/atmel_pdc.h>
 #include <linux/atmel_serial.h>
 #include <linux/uaccess.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_data/atmel.h>
 
 #include <asm/io.h>
 #include <asm/ioctls.h>
 
-#include <asm/mach/serial_at91.h>
-#include <mach/board.h>
-
 #ifdef CONFIG_ARM
 #include <mach/cpu.h>
 #include <asm/gpio.h>
@@ -1423,7 +1422,7 @@ static struct uart_ops atmel_pops = {
 #endif
 };
 
-static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port,
+static void atmel_of_init_port(struct atmel_uart_port *atmel_port,
 					 struct device_node *np)
 {
 	u32 rs485_delay[2];
@@ -1458,7 +1457,7 @@ static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port,
 /*
  * Configure the port from the platform device resource info.
  */
-static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
+static void atmel_init_port(struct atmel_uart_port *atmel_port,
 				      struct platform_device *pdev)
 {
 	struct uart_port *port = &atmel_port->uart;
@@ -1513,23 +1512,6 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
 	}
 }
 
-/*
- * Register board-specific modem-control line handlers.
- */
-void __init atmel_register_uart_fns(struct atmel_port_fns *fns)
-{
-	if (fns->enable_ms)
-		atmel_pops.enable_ms = fns->enable_ms;
-	if (fns->get_mctrl)
-		atmel_pops.get_mctrl = fns->get_mctrl;
-	if (fns->set_mctrl)
-		atmel_pops.set_mctrl = fns->set_mctrl;
-	atmel_open_hook		= fns->open;
-	atmel_close_hook	= fns->close;
-	atmel_pops.pm		= fns->pm;
-	atmel_pops.set_wake	= fns->set_wake;
-}
-
 struct platform_device *atmel_default_console_device;	/* the serial console device */
 
 #ifdef CONFIG_SERIAL_ATMEL_CONSOLE
@@ -1766,13 +1748,14 @@ static int atmel_serial_resume(struct platform_device *pdev)
 #define atmel_serial_resume NULL
 #endif
 
-static int __devinit atmel_serial_probe(struct platform_device *pdev)
+static int atmel_serial_probe(struct platform_device *pdev)
 {
 	struct atmel_uart_port *port;
 	struct device_node *np = pdev->dev.of_node;
 	struct atmel_uart_data *pdata = pdev->dev.platform_data;
 	void *data;
 	int ret = -ENODEV;
+	struct pinctrl *pinctrl;
 
 	BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
 
@@ -1805,6 +1788,12 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
 
 	atmel_init_port(port, pdev);
 
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl)) {
+		ret = PTR_ERR(pinctrl);
+		goto err;
+	}
+
 	if (!atmel_use_dma_rx(&port->uart)) {
 		ret = -ENOMEM;
 		data = kmalloc(sizeof(struct atmel_uart_char)
@@ -1851,7 +1840,7 @@ err:
 	return ret;
 }
 
-static int __devexit atmel_serial_remove(struct platform_device *pdev)
+static int atmel_serial_remove(struct platform_device *pdev)
 {
 	struct uart_port *port = platform_get_drvdata(pdev);
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
@@ -1876,7 +1865,7 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev)
 
 static struct platform_driver atmel_serial_driver = {
 	.probe		= atmel_serial_probe,
-	.remove		= __devexit_p(atmel_serial_remove),
+	.remove		= atmel_serial_remove,
 	.suspend	= atmel_serial_suspend,
 	.resume		= atmel_serial_resume,
 	.driver		= {
diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c
index c0b68b9..c76a226 100644
--- a/drivers/tty/serial/bcm63xx_uart.c
+++ b/drivers/tty/serial/bcm63xx_uart.c
@@ -801,7 +801,7 @@ static struct uart_driver bcm_uart_driver = {
 /*
  * platform driver probe/remove callback
  */
-static int __devinit bcm_uart_probe(struct platform_device *pdev)
+static int bcm_uart_probe(struct platform_device *pdev)
 {
 	struct resource *res_mem, *res_irq;
 	struct uart_port *port;
@@ -848,7 +848,7 @@ static int __devinit bcm_uart_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit bcm_uart_remove(struct platform_device *pdev)
+static int bcm_uart_remove(struct platform_device *pdev)
 {
 	struct uart_port *port;
 
@@ -865,7 +865,7 @@ static int __devexit bcm_uart_remove(struct platform_device *pdev)
  */
 static struct platform_driver bcm_uart_platform_driver = {
 	.probe	= bcm_uart_probe,
-	.remove	= __devexit_p(bcm_uart_remove),
+	.remove	= bcm_uart_remove,
 	.driver	= {
 		.owner = THIS_MODULE,
 		.name  = "bcm63xx_uart",
diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c
index 7fbc3a0..f5d1173 100644
--- a/drivers/tty/serial/bfin_sport_uart.c
+++ b/drivers/tty/serial/bfin_sport_uart.c
@@ -740,7 +740,7 @@ static struct dev_pm_ops bfin_sport_uart_dev_pm_ops = {
 };
 #endif
 
-static int __devinit sport_uart_probe(struct platform_device *pdev)
+static int sport_uart_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	struct sport_uart_port *sport;
@@ -850,7 +850,7 @@ out_error_free_mem:
 	return ret;
 }
 
-static int __devexit sport_uart_remove(struct platform_device *pdev)
+static int sport_uart_remove(struct platform_device *pdev)
 {
 	struct sport_uart_port *sport = platform_get_drvdata(pdev);
 
@@ -871,7 +871,7 @@ static int __devexit sport_uart_remove(struct platform_device *pdev)
 
 static struct platform_driver sport_uart_driver = {
 	.probe		= sport_uart_probe,
-	.remove		= __devexit_p(sport_uart_remove),
+	.remove		= sport_uart_remove,
 	.driver		= {
 		.name	= DRV_NAME,
 #ifdef CONFIG_PM
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
index 9242d56..2e2b2c1 100644
--- a/drivers/tty/serial/bfin_uart.c
+++ b/drivers/tty/serial/bfin_uart.c
@@ -477,9 +477,9 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
 void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
 {
 	int x_pos, pos;
+	unsigned long flags;
 
-	dma_disable_irq_nosync(uart->rx_dma_channel);
-	spin_lock_bh(&uart->rx_lock);
+	spin_lock_irqsave(&uart->rx_lock, flags);
 
 	/* 2D DMA RX buffer ring is used. Because curr_y_count and
 	 * curr_x_count can't be read as an atomic operation,
@@ -510,8 +510,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
 		uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
 	}
 
-	spin_unlock_bh(&uart->rx_lock);
-	dma_enable_irq(uart->rx_dma_channel);
+	spin_unlock_irqrestore(&uart->rx_lock, flags);
 
 	mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
 }
@@ -800,6 +799,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
 	unsigned long flags;
 	unsigned int baud, quot;
 	unsigned int ier, lcr = 0;
+	unsigned long timeout;
 
 	switch (termios->c_cflag & CSIZE) {
 	case CS8:
@@ -815,7 +815,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
 		lcr = WLS(5);
 		break;
 	default:
-		printk(KERN_ERR "%s: word lengh not supported\n",
+		printk(KERN_ERR "%s: word length not supported\n",
 			__func__);
 	}
 
@@ -869,6 +869,14 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15);
 
+	/* Wait till the transfer buffer is empty */
+	timeout = jiffies + msecs_to_jiffies(10);
+	while (UART_GET_GCTL(uart) & UCEN && !(UART_GET_LSR(uart) & TEMT))
+		if (time_after(jiffies, timeout)) {
+			dev_warn(port->dev, "timeout waiting for TX buffer empty\n");
+			break;
+		}
+
 	/* Disable UART */
 	ier = UART_GET_IER(uart);
 	UART_PUT_GCTL(uart, UART_GET_GCTL(uart) & ~UCEN);
@@ -1390,7 +1398,7 @@ out_error_free_mem:
 	return ret;
 }
 
-static int __devexit bfin_serial_remove(struct platform_device *pdev)
+static int bfin_serial_remove(struct platform_device *pdev)
 {
 	struct bfin_serial_port *uart = platform_get_drvdata(pdev);
 
@@ -1410,7 +1418,7 @@ static int __devexit bfin_serial_remove(struct platform_device *pdev)
 
 static struct platform_driver bfin_serial_driver = {
 	.probe		= bfin_serial_probe,
-	.remove		= __devexit_p(bfin_serial_remove),
+	.remove		= bfin_serial_remove,
 	.suspend	= bfin_serial_suspend,
 	.resume		= bfin_serial_resume,
 	.driver		= {
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index d0f719f..3fd2526 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -10,15 +10,6 @@
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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
  */
 
 #if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
@@ -26,172 +17,169 @@
 #endif
 
 #include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/spinlock.h>
 #include <linux/device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
+#include <linux/console.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
 #include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
 
 #include <mach/hardware.h>
-#include <asm/irq.h>
-
-#define UART_NR		2
-
-#define SERIAL_CLPS711X_MAJOR	204
-#define SERIAL_CLPS711X_MINOR	40
-#define SERIAL_CLPS711X_NR	UART_NR
-
-/*
- * We use the relevant SYSCON register as a base address for these ports.
- */
-#define UBRLCR(port)		((port)->iobase + UBRLCR1 - SYSCON1)
-#define UARTDR(port)		((port)->iobase + UARTDR1 - SYSCON1)
-#define SYSFLG(port)		((port)->iobase + SYSFLG1 - SYSCON1)
-#define SYSCON(port)		((port)->iobase + SYSCON1 - SYSCON1)
-
-#define TX_IRQ(port)		((port)->irq)
-#define RX_IRQ(port)		((port)->irq + 1)
 
-#define UART_ANY_ERR		(UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR)
-
-#define tx_enabled(port)	((port)->unused[0])
+#define UART_CLPS711X_NAME	"uart-clps711x"
+#define UART_CLPS711X_NR	2
+#define UART_CLPS711X_MAJOR	204
+#define UART_CLPS711X_MINOR	40
+
+#define UBRLCR(port)		((port)->line ? UBRLCR2 : UBRLCR1)
+#define UARTDR(port)		((port)->line ? UARTDR2 : UARTDR1)
+#define SYSFLG(port)		((port)->line ? SYSFLG2 : SYSFLG1)
+#define SYSCON(port)		((port)->line ? SYSCON2 : SYSCON1)
+#define TX_IRQ(port)		((port)->line ? IRQ_UTXINT2 : IRQ_UTXINT1)
+#define RX_IRQ(port)		((port)->line ? IRQ_URXINT2 : IRQ_URXINT1)
+
+struct clps711x_port {
+	struct uart_driver	uart;
+	struct clk		*uart_clk;
+	struct uart_port	port[UART_CLPS711X_NR];
+	int			tx_enabled[UART_CLPS711X_NR];
+#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
+	struct console		console;
+#endif
+};
 
-static void clps711xuart_stop_tx(struct uart_port *port)
+static void uart_clps711x_stop_tx(struct uart_port *port)
 {
-	if (tx_enabled(port)) {
+	struct clps711x_port *s = dev_get_drvdata(port->dev);
+
+	if (s->tx_enabled[port->line]) {
 		disable_irq(TX_IRQ(port));
-		tx_enabled(port) = 0;
+		s->tx_enabled[port->line] = 0;
 	}
 }
 
-static void clps711xuart_start_tx(struct uart_port *port)
+static void uart_clps711x_start_tx(struct uart_port *port)
 {
-	if (!tx_enabled(port)) {
+	struct clps711x_port *s = dev_get_drvdata(port->dev);
+
+	if (!s->tx_enabled[port->line]) {
 		enable_irq(TX_IRQ(port));
-		tx_enabled(port) = 1;
+		s->tx_enabled[port->line] = 1;
 	}
 }
 
-static void clps711xuart_stop_rx(struct uart_port *port)
+static void uart_clps711x_stop_rx(struct uart_port *port)
 {
 	disable_irq(RX_IRQ(port));
 }
 
-static void clps711xuart_enable_ms(struct uart_port *port)
+static void uart_clps711x_enable_ms(struct uart_port *port)
 {
+	/* Do nothing */
 }
 
-static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id)
+static irqreturn_t uart_clps711x_int_rx(int irq, void *dev_id)
 {
 	struct uart_port *port = dev_id;
-	struct tty_struct *tty = port->state->port.tty;
+	struct tty_struct *tty = tty_port_tty_get(&port->state->port);
 	unsigned int status, ch, flg;
 
-	status = clps_readl(SYSFLG(port));
-	while (!(status & SYSFLG_URXFE)) {
-		ch = clps_readl(UARTDR(port));
+	if (!tty)
+		return IRQ_HANDLED;
 
-		port->icount.rx++;
+	for (;;) {
+		status = clps_readl(SYSFLG(port));
+		if (status & SYSFLG_URXFE)
+			break;
+
+		ch = clps_readw(UARTDR(port));
+		status = ch & (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR);
+		ch &= 0xff;
 
+		port->icount.rx++;
 		flg = TTY_NORMAL;
 
-		/*
-		 * Note that the error handling code is
-		 * out of the main execution path
-		 */
-		if (unlikely(ch & UART_ANY_ERR)) {
-			if (ch & UARTDR_PARERR)
+		if (unlikely(status)) {
+			if (status & UARTDR_PARERR)
 				port->icount.parity++;
-			else if (ch & UARTDR_FRMERR)
+			else if (status & UARTDR_FRMERR)
 				port->icount.frame++;
-			if (ch & UARTDR_OVERR)
+			else if (status & UARTDR_OVERR)
 				port->icount.overrun++;
 
-			ch &= port->read_status_mask;
+			status &= port->read_status_mask;
 
-			if (ch & UARTDR_PARERR)
+			if (status & UARTDR_PARERR)
 				flg = TTY_PARITY;
-			else if (ch & UARTDR_FRMERR)
+			else if (status & UARTDR_FRMERR)
 				flg = TTY_FRAME;
-
-#ifdef SUPPORT_SYSRQ
-			port->sysrq = 0;
-#endif
+			else if (status & UARTDR_OVERR)
+				flg = TTY_OVERRUN;
 		}
 
 		if (uart_handle_sysrq_char(port, ch))
-			goto ignore_char;
+			continue;
 
-		/*
-		 * CHECK: does overrun affect the current character?
-		 * ASSUMPTION: it does not.
-		 */
-		uart_insert_char(port, ch, UARTDR_OVERR, ch, flg);
+		if (status & port->ignore_status_mask)
+			continue;
 
-	ignore_char:
-		status = clps_readl(SYSFLG(port));
+		uart_insert_char(port, status, UARTDR_OVERR, ch, flg);
 	}
+
 	tty_flip_buffer_push(tty);
+
+	tty_kref_put(tty);
+
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id)
+static irqreturn_t uart_clps711x_int_tx(int irq, void *dev_id)
 {
 	struct uart_port *port = dev_id;
+	struct clps711x_port *s = dev_get_drvdata(port->dev);
 	struct circ_buf *xmit = &port->state->xmit;
-	int count;
 
 	if (port->x_char) {
-		clps_writel(port->x_char, UARTDR(port));
+		clps_writew(port->x_char, UARTDR(port));
 		port->icount.tx++;
 		port->x_char = 0;
 		return IRQ_HANDLED;
 	}
 
-	if (uart_circ_empty(xmit) || uart_tx_stopped(port))
-		goto disable_tx_irq;
+	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+		disable_irq_nosync(TX_IRQ(port));
+		s->tx_enabled[port->line] = 0;
+		return IRQ_HANDLED;
+	}
 
-	count = port->fifosize >> 1;
-	do {
-		clps_writel(xmit->buf[xmit->tail], UARTDR(port));
+	while (!uart_circ_empty(xmit)) {
+		clps_writew(xmit->buf[xmit->tail], UARTDR(port));
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		port->icount.tx++;
-		if (uart_circ_empty(xmit))
+		if (clps_readl(SYSFLG(port) & SYSFLG_UTXFF))
 			break;
-	} while (--count > 0);
+	}
 
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(port);
 
-	if (uart_circ_empty(xmit)) {
-	disable_tx_irq:
-		disable_irq_nosync(TX_IRQ(port));
-		tx_enabled(port) = 0;
-	}
-
 	return IRQ_HANDLED;
 }
 
-static unsigned int clps711xuart_tx_empty(struct uart_port *port)
+static unsigned int uart_clps711x_tx_empty(struct uart_port *port)
 {
-	unsigned int status = clps_readl(SYSFLG(port));
-	return status & SYSFLG_UBUSY ? 0 : TIOCSER_TEMT;
+	return (clps_readl(SYSFLG(port) & SYSFLG_UBUSY)) ? 0 : TIOCSER_TEMT;
 }
 
-static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
+static unsigned int uart_clps711x_get_mctrl(struct uart_port *port)
 {
-	unsigned int port_addr;
-	unsigned int result = 0;
-	unsigned int status;
+	unsigned int status, result = 0;
 
-	port_addr = SYSFLG(port);
-	if (port_addr == SYSFLG1) {
+	if (port->line == 0) {
 		status = clps_readl(SYSFLG1);
 		if (status & SYSFLG1_DCD)
 			result |= TIOCM_CAR;
@@ -199,104 +187,86 @@ static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
 			result |= TIOCM_DSR;
 		if (status & SYSFLG1_CTS)
 			result |= TIOCM_CTS;
-	}
+	} else
+		result = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
 
 	return result;
 }
 
-static void
-clps711xuart_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
+static void uart_clps711x_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
+	/* Do nothing */
 }
 
-static void clps711xuart_break_ctl(struct uart_port *port, int break_state)
+static void uart_clps711x_break_ctl(struct uart_port *port, int break_state)
 {
 	unsigned long flags;
 	unsigned int ubrlcr;
 
 	spin_lock_irqsave(&port->lock, flags);
+
 	ubrlcr = clps_readl(UBRLCR(port));
-	if (break_state == -1)
+	if (break_state)
 		ubrlcr |= UBRLCR_BREAK;
 	else
 		ubrlcr &= ~UBRLCR_BREAK;
 	clps_writel(ubrlcr, UBRLCR(port));
+
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 
-static int clps711xuart_startup(struct uart_port *port)
+static int uart_clps711x_startup(struct uart_port *port)
 {
-	unsigned int syscon;
-	int retval;
-
-	tx_enabled(port) = 1;
-
-	/*
-	 * Allocate the IRQs
-	 */
-	retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0,
-			     "clps711xuart_tx", port);
-	if (retval)
-		return retval;
-
-	retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0,
-			     "clps711xuart_rx", port);
-	if (retval) {
-		free_irq(TX_IRQ(port), port);
-		return retval;
+	struct clps711x_port *s = dev_get_drvdata(port->dev);
+	int ret;
+
+	s->tx_enabled[port->line] = 1;
+	/* Allocate the IRQs */
+	ret = devm_request_irq(port->dev, TX_IRQ(port), uart_clps711x_int_tx,
+			       0, UART_CLPS711X_NAME " TX", port);
+	if (ret)
+		return ret;
+
+	ret = devm_request_irq(port->dev, RX_IRQ(port), uart_clps711x_int_rx,
+			       0, UART_CLPS711X_NAME " RX", port);
+	if (ret) {
+		devm_free_irq(port->dev, TX_IRQ(port), port);
+		return ret;
 	}
 
-	/*
-	 * enable the port
-	 */
-	syscon = clps_readl(SYSCON(port));
-	syscon |= SYSCON_UARTEN;
-	clps_writel(syscon, SYSCON(port));
+	/* Disable break */
+	clps_writel(clps_readl(UBRLCR(port)) & ~UBRLCR_BREAK, UBRLCR(port));
+
+	/* Enable the port */
+	clps_writel(clps_readl(SYSCON(port)) | SYSCON_UARTEN, SYSCON(port));
 
 	return 0;
 }
 
-static void clps711xuart_shutdown(struct uart_port *port)
+static void uart_clps711x_shutdown(struct uart_port *port)
 {
-	unsigned int ubrlcr, syscon;
+	/* Free the interrupts */
+	devm_free_irq(port->dev, TX_IRQ(port), port);
+	devm_free_irq(port->dev, RX_IRQ(port), port);
 
-	/*
-	 * Free the interrupt
-	 */
-	free_irq(TX_IRQ(port), port);	/* TX interrupt */
-	free_irq(RX_IRQ(port), port);	/* RX interrupt */
-
-	/*
-	 * disable the port
-	 */
-	syscon = clps_readl(SYSCON(port));
-	syscon &= ~SYSCON_UARTEN;
-	clps_writel(syscon, SYSCON(port));
-
-	/*
-	 * disable break condition and fifos
-	 */
-	ubrlcr = clps_readl(UBRLCR(port));
-	ubrlcr &= ~(UBRLCR_FIFOEN | UBRLCR_BREAK);
-	clps_writel(ubrlcr, UBRLCR(port));
+	/* Disable the port */
+	clps_writel(clps_readl(SYSCON(port)) & ~SYSCON_UARTEN, SYSCON(port));
 }
 
-static void
-clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios,
-			 struct ktermios *old)
+static void uart_clps711x_set_termios(struct uart_port *port,
+				      struct ktermios *termios,
+				      struct ktermios *old)
 {
 	unsigned int ubrlcr, baud, quot;
 	unsigned long flags;
 
-	/*
-	 * We don't implement CREAD.
-	 */
-	termios->c_cflag |= CREAD;
+	/* Mask termios capabilities we don't support */
+	termios->c_cflag &= ~CMSPAR;
+	termios->c_iflag &= ~(BRKINT | IGNBRK);
 
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
+	/* Ask the core to calculate the divisor for us */
+	baud = uart_get_baud_rate(port, termios, old, port->uartclk / 4096,
+						      port->uartclk / 16);
 	quot = uart_get_divisor(port, baud);
 
 	switch (termios->c_cflag & CSIZE) {
@@ -309,160 +279,117 @@ clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios,
 	case CS7:
 		ubrlcr = UBRLCR_WRDLEN7;
 		break;
-	default: // CS8
+	case CS8:
+	default:
 		ubrlcr = UBRLCR_WRDLEN8;
 		break;
 	}
+
 	if (termios->c_cflag & CSTOPB)
 		ubrlcr |= UBRLCR_XSTOP;
+
 	if (termios->c_cflag & PARENB) {
 		ubrlcr |= UBRLCR_PRTEN;
 		if (!(termios->c_cflag & PARODD))
 			ubrlcr |= UBRLCR_EVENPRT;
 	}
-	if (port->fifosize > 1)
-		ubrlcr |= UBRLCR_FIFOEN;
 
-	spin_lock_irqsave(&port->lock, flags);
+	/* Enable FIFO */
+	ubrlcr |= UBRLCR_FIFOEN;
 
-	/*
-	 * Update the per-port timeout.
-	 */
-	uart_update_timeout(port, termios->c_cflag, baud);
+	spin_lock_irqsave(&port->lock, flags);
 
+	/* Set read status mask */
 	port->read_status_mask = UARTDR_OVERR;
 	if (termios->c_iflag & INPCK)
 		port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;
 
-	/*
-	 * Characters to ignore
-	 */
+	/* Set status ignore mask */
 	port->ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		port->ignore_status_mask |= UARTDR_FRMERR | UARTDR_PARERR;
-	if (termios->c_iflag & IGNBRK) {
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns to (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			port->ignore_status_mask |= UARTDR_OVERR;
-	}
+	if (!(termios->c_cflag & CREAD))
+		port->ignore_status_mask |= UARTDR_OVERR | UARTDR_PARERR |
+					    UARTDR_FRMERR;
 
-	quot -= 1;
+	uart_update_timeout(port, termios->c_cflag, baud);
 
-	clps_writel(ubrlcr | quot, UBRLCR(port));
+	clps_writel(ubrlcr | (quot - 1), UBRLCR(port));
 
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 
-static const char *clps711xuart_type(struct uart_port *port)
+static const char *uart_clps711x_type(struct uart_port *port)
 {
-	return port->type == PORT_CLPS711X ? "CLPS711x" : NULL;
+	return (port->type == PORT_CLPS711X) ? "CLPS711X" : NULL;
 }
 
-/*
- * Configure/autoconfigure the port.
- */
-static void clps711xuart_config_port(struct uart_port *port, int flags)
+static void uart_clps711x_config_port(struct uart_port *port, int flags)
 {
 	if (flags & UART_CONFIG_TYPE)
 		port->type = PORT_CLPS711X;
 }
 
-static void clps711xuart_release_port(struct uart_port *port)
+static void uart_clps711x_release_port(struct uart_port *port)
 {
+	/* Do nothing */
 }
 
-static int clps711xuart_request_port(struct uart_port *port)
+static int uart_clps711x_request_port(struct uart_port *port)
 {
+	/* Do nothing */
 	return 0;
 }
 
-static struct uart_ops clps711x_pops = {
-	.tx_empty	= clps711xuart_tx_empty,
-	.set_mctrl	= clps711xuart_set_mctrl_null,
-	.get_mctrl	= clps711xuart_get_mctrl,
-	.stop_tx	= clps711xuart_stop_tx,
-	.start_tx	= clps711xuart_start_tx,
-	.stop_rx	= clps711xuart_stop_rx,
-	.enable_ms	= clps711xuart_enable_ms,
-	.break_ctl	= clps711xuart_break_ctl,
-	.startup	= clps711xuart_startup,
-	.shutdown	= clps711xuart_shutdown,
-	.set_termios	= clps711xuart_set_termios,
-	.type		= clps711xuart_type,
-	.config_port	= clps711xuart_config_port,
-	.release_port	= clps711xuart_release_port,
-	.request_port	= clps711xuart_request_port,
-};
-
-static struct uart_port clps711x_ports[UART_NR] = {
-	{
-		.iobase		= SYSCON1,
-		.irq		= IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
-		.uartclk	= 3686400,
-		.fifosize	= 16,
-		.ops		= &clps711x_pops,
-		.line		= 0,
-		.flags		= UPF_BOOT_AUTOCONF,
-	},
-	{
-		.iobase		= SYSCON2,
-		.irq		= IRQ_UTXINT2, /* IRQ_URXINT2 */
-		.uartclk	= 3686400,
-		.fifosize	= 16,
-		.ops		= &clps711x_pops,
-		.line		= 1,
-		.flags		= UPF_BOOT_AUTOCONF,
-	}
+static const struct uart_ops uart_clps711x_ops = {
+	.tx_empty	= uart_clps711x_tx_empty,
+	.set_mctrl	= uart_clps711x_set_mctrl,
+	.get_mctrl	= uart_clps711x_get_mctrl,
+	.stop_tx	= uart_clps711x_stop_tx,
+	.start_tx	= uart_clps711x_start_tx,
+	.stop_rx	= uart_clps711x_stop_rx,
+	.enable_ms	= uart_clps711x_enable_ms,
+	.break_ctl	= uart_clps711x_break_ctl,
+	.startup	= uart_clps711x_startup,
+	.shutdown	= uart_clps711x_shutdown,
+	.set_termios	= uart_clps711x_set_termios,
+	.type		= uart_clps711x_type,
+	.config_port	= uart_clps711x_config_port,
+	.release_port	= uart_clps711x_release_port,
+	.request_port	= uart_clps711x_request_port,
 };
 
 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
-static void clps711xuart_console_putchar(struct uart_port *port, int ch)
+static void uart_clps711x_console_putchar(struct uart_port *port, int ch)
 {
 	while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF)
 		barrier();
-	clps_writel(ch, UARTDR(port));
+
+	clps_writew(ch, UARTDR(port));
 }
 
-/*
- *	Print a string to the serial port trying not to disturb
- *	any possible real use of the port...
- *
- *	The console_lock must be held when we get here.
- *
- *	Note that this is called with interrupts already disabled
- */
-static void
-clps711xuart_console_write(struct console *co, const char *s,
-			   unsigned int count)
+static void uart_clps711x_console_write(struct console *co, const char *c,
+					unsigned n)
 {
-	struct uart_port *port = clps711x_ports + co->index;
-	unsigned int status, syscon;
+	struct clps711x_port *s = (struct clps711x_port *)co->data;
+	struct uart_port *port = &s->port[co->index];
+	u32 syscon;
 
-	/*
-	 *	Ensure that the port is enabled.
-	 */
+	/* Ensure that the port is enabled */
 	syscon = clps_readl(SYSCON(port));
 	clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
 
-	uart_console_write(port, s, count, clps711xuart_console_putchar);
+	uart_console_write(port, c, n, uart_clps711x_console_putchar);
 
-	/*
-	 *	Finally, wait for transmitter to become empty
-	 *	and restore the uart state.
-	 */
-	do {
-		status = clps_readl(SYSFLG(port));
-	} while (status & SYSFLG_UBUSY);
+	/* Wait for transmitter to become empty */
+	while (clps_readl(SYSFLG(port)) & SYSFLG_UBUSY)
+		barrier();
 
+	/* Restore the uart state */
 	clps_writel(syscon, SYSCON(port));
 }
 
-static void __init
-clps711xuart_console_get_options(struct uart_port *port, int *baud,
-				 int *parity, int *bits)
+static void uart_clps711x_console_get_options(struct uart_port *port,
+					      int *baud, int *parity,
+					      int *bits)
 {
 	if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) {
 		unsigned int ubrlcr, quot;
@@ -487,92 +414,124 @@ clps711xuart_console_get_options(struct uart_port *port, int *baud,
 	}
 }
 
-static int __init clps711xuart_console_setup(struct console *co, char *options)
+static int uart_clps711x_console_setup(struct console *co, char *options)
 {
-	struct uart_port *port;
-	int baud = 38400;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	/*
-	 * Check whether an invalid uart number has been specified, and
-	 * if so, search for the first available port that does have
-	 * console support.
-	 */
-	port = uart_get_console(clps711x_ports, UART_NR, co);
+	int baud = 38400, bits = 8, parity = 'n', flow = 'n';
+	struct clps711x_port *s = (struct clps711x_port *)co->data;
+	struct uart_port *port = &s->port[(co->index > 0) ? co->index : 0];
 
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 	else
-		clps711xuart_console_get_options(port, &baud, &parity, &bits);
+		uart_clps711x_console_get_options(port, &baud, &parity, &bits);
 
 	return uart_set_options(port, co, baud, parity, bits, flow);
 }
+#endif
 
-static struct uart_driver clps711x_reg;
-static struct console clps711x_console = {
-	.name		= "ttyCL",
-	.write		= clps711xuart_console_write,
-	.device		= uart_console_device,
-	.setup		= clps711xuart_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &clps711x_reg,
-};
-
-static int __init clps711xuart_console_init(void)
+static int uart_clps711x_probe(struct platform_device *pdev)
 {
-	register_console(&clps711x_console);
-	return 0;
-}
-console_initcall(clps711xuart_console_init);
+	struct clps711x_port *s;
+	int ret, i;
+
+	s = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_port), GFP_KERNEL);
+	if (!s) {
+		dev_err(&pdev->dev, "Error allocating port structure\n");
+		return -ENOMEM;
+	}
+	platform_set_drvdata(pdev, s);
 
-#define CLPS711X_CONSOLE	&clps711x_console
-#else
-#define CLPS711X_CONSOLE	NULL
+	s->uart_clk = devm_clk_get(&pdev->dev, "uart");
+	if (IS_ERR(s->uart_clk)) {
+		dev_err(&pdev->dev, "Can't get UART clocks\n");
+		ret = PTR_ERR(s->uart_clk);
+		goto err_out;
+	}
+
+	s->uart.owner		= THIS_MODULE;
+	s->uart.dev_name	= "ttyCL";
+	s->uart.major		= UART_CLPS711X_MAJOR;
+	s->uart.minor		= UART_CLPS711X_MINOR;
+	s->uart.nr		= UART_CLPS711X_NR;
+#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
+	s->uart.cons		= &s->console;
+	s->uart.cons->device	= uart_console_device;
+	s->uart.cons->write	= uart_clps711x_console_write;
+	s->uart.cons->setup	= uart_clps711x_console_setup;
+	s->uart.cons->flags	= CON_PRINTBUFFER;
+	s->uart.cons->index	= -1;
+	s->uart.cons->data	= s;
+	strcpy(s->uart.cons->name, "ttyCL");
 #endif
+	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);
+		goto err_out;
+	}
 
-static struct uart_driver clps711x_reg = {
-	.driver_name		= "ttyCL",
-	.dev_name		= "ttyCL",
-	.major			= SERIAL_CLPS711X_MAJOR,
-	.minor			= SERIAL_CLPS711X_MINOR,
-	.nr			= UART_NR,
+	for (i = 0; i < UART_CLPS711X_NR; i++) {
+		s->port[i].line		= i;
+		s->port[i].dev		= &pdev->dev;
+		s->port[i].irq		= TX_IRQ(&s->port[i]);
+		s->port[i].iobase	= SYSCON(&s->port[i]);
+		s->port[i].type		= PORT_CLPS711X;
+		s->port[i].fifosize	= 16;
+		s->port[i].flags	= UPF_SKIP_TEST | UPF_FIXED_TYPE;
+		s->port[i].uartclk	= clk_get_rate(s->uart_clk);
+		s->port[i].ops		= &uart_clps711x_ops;
+		WARN_ON(uart_add_one_port(&s->uart, &s->port[i]));
+	}
 
-	.cons			= CLPS711X_CONSOLE,
-};
+	return 0;
 
-static int __init clps711xuart_init(void)
-{
-	int ret, i;
+err_out:
+	platform_set_drvdata(pdev, NULL);
 
-	printk(KERN_INFO "Serial: CLPS711x driver\n");
+	return ret;
+}
 
-	ret = uart_register_driver(&clps711x_reg);
-	if (ret)
-		return ret;
+static int uart_clps711x_remove(struct platform_device *pdev)
+{
+	struct clps711x_port *s = platform_get_drvdata(pdev);
+	int i;
 
-	for (i = 0; i < UART_NR; i++)
-		uart_add_one_port(&clps711x_reg, &clps711x_ports[i]);
+	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);
+	platform_set_drvdata(pdev, NULL);
 
 	return 0;
 }
 
-static void __exit clps711xuart_exit(void)
-{
-	int i;
+static struct platform_driver clps711x_uart_driver = {
+	.driver = {
+		.name	= UART_CLPS711X_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe	= uart_clps711x_probe,
+	.remove	= uart_clps711x_remove,
+};
+module_platform_driver(clps711x_uart_driver);
 
-	for (i = 0; i < UART_NR; i++)
-		uart_remove_one_port(&clps711x_reg, &clps711x_ports[i]);
+static struct platform_device clps711x_uart_device = {
+	.name	= UART_CLPS711X_NAME,
+};
 
-	uart_unregister_driver(&clps711x_reg);
+static int __init uart_clps711x_init(void)
+{
+	return platform_device_register(&clps711x_uart_device);
 }
+module_init(uart_clps711x_init);
 
-module_init(clps711xuart_init);
-module_exit(clps711xuart_exit);
+static void __exit uart_clps711x_exit(void)
+{
+	platform_device_unregister(&clps711x_uart_device);
+}
+module_exit(uart_clps711x_exit);
 
 MODULE_AUTHOR("Deep Blue Solutions Ltd");
-MODULE_DESCRIPTION("CLPS-711x generic serial driver");
+MODULE_DESCRIPTION("CLPS711X serial driver");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR);
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
index d0dd919..ad0caf1 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
@@ -1373,7 +1373,7 @@ static struct uart_driver cpm_reg = {
 
 static int probe_index;
 
-static int __devinit cpm_uart_probe(struct platform_device *ofdev)
+static int cpm_uart_probe(struct platform_device *ofdev)
 {
 	int index = probe_index++;
 	struct uart_cpm_port *pinfo = &cpm_uart_ports[index];
@@ -1396,7 +1396,7 @@ static int __devinit cpm_uart_probe(struct platform_device *ofdev)
 	return uart_add_one_port(&cpm_reg, &pinfo->port);
 }
 
-static int __devexit cpm_uart_remove(struct platform_device *ofdev)
+static int cpm_uart_remove(struct platform_device *ofdev)
 {
 	struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev);
 	return uart_remove_one_port(&cpm_reg, &pinfo->port);
diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c
index 615e464..a8cbb26 100644
--- a/drivers/tty/serial/efm32-uart.c
+++ b/drivers/tty/serial/efm32-uart.c
@@ -690,7 +690,7 @@ static int efm32_uart_probe_dt(struct platform_device *pdev,
 
 }
 
-static int __devinit efm32_uart_probe(struct platform_device *pdev)
+static int efm32_uart_probe(struct platform_device *pdev)
 {
 	struct efm32_uart_port *efm_port;
 	struct resource *res;
@@ -764,7 +764,7 @@ err_get_base:
 	return ret;
 }
 
-static int __devexit efm32_uart_remove(struct platform_device *pdev)
+static int efm32_uart_remove(struct platform_device *pdev)
 {
 	struct efm32_uart_port *efm_port = platform_get_drvdata(pdev);
 
@@ -791,7 +791,7 @@ MODULE_DEVICE_TABLE(of, efm32_uart_dt_ids);
 
 static struct platform_driver efm32_uart_driver = {
 	.probe = efm32_uart_probe,
-	.remove = __devexit_p(efm32_uart_remove),
+	.remove = efm32_uart_remove,
 
 	.driver = {
 		.name = DRIVER_NAME,
diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c
index defc4e3..72b6334 100644
--- a/drivers/tty/serial/icom.c
+++ b/drivers/tty/serial/icom.c
@@ -175,7 +175,7 @@ static void free_port_memory(struct icom_port *icom_port)
 	}
 }
 
-static int __devinit get_port_memory(struct icom_port *icom_port)
+static int get_port_memory(struct icom_port *icom_port)
 {
 	int index;
 	unsigned long stgAddr;
@@ -505,7 +505,7 @@ static void load_code(struct icom_port *icom_port)
 		/* Stop processor */
 		stop_processor(icom_port);
 
-		dev_err(&icom_port->adapter->pci_dev->dev,"Port not opertional\n");
+		dev_err(&icom_port->adapter->pci_dev->dev,"Port not operational\n");
 	}
 
 	if (new_page != NULL)
@@ -1314,7 +1314,7 @@ static struct uart_driver icom_uart_driver = {
 	.cons = ICOM_CONSOLE,
 };
 
-static int __devinit icom_init_ports(struct icom_adapter *icom_adapter)
+static int icom_init_ports(struct icom_adapter *icom_adapter)
 {
 	u32 subsystem_id = icom_adapter->subsystem_id;
 	int i;
@@ -1381,7 +1381,7 @@ static void icom_port_active(struct icom_port *icom_port, struct icom_adapter *i
 			    0x8024 + 2 - 2 * (icom_port->port - 2);
 	}
 }
-static int __devinit icom_load_ports(struct icom_adapter *icom_adapter)
+static int icom_load_ports(struct icom_adapter *icom_adapter)
 {
 	struct icom_port *icom_port;
 	int port_num;
@@ -1407,7 +1407,7 @@ static int __devinit icom_load_ports(struct icom_adapter *icom_adapter)
 	return 0;
 }
 
-static int __devinit icom_alloc_adapter(struct icom_adapter
+static int icom_alloc_adapter(struct icom_adapter
 					**icom_adapter_ref)
 {
 	int adapter_count = 0;
@@ -1487,7 +1487,7 @@ static void icom_kref_release(struct kref *kref)
 	icom_remove_adapter(icom_adapter);
 }
 
-static int __devinit icom_probe(struct pci_dev *dev,
+static int icom_probe(struct pci_dev *dev,
 				const struct pci_device_id *ent)
 {
 	int index;
@@ -1596,7 +1596,7 @@ probe_exit0:
 	return retval;
 }
 
-static void __devexit icom_remove(struct pci_dev *dev)
+static void icom_remove(struct pci_dev *dev)
 {
 	struct icom_adapter *icom_adapter;
 	struct list_head *tmp;
@@ -1617,7 +1617,7 @@ static struct pci_driver icom_pci_driver = {
 	.name = ICOM_DRIVER_NAME,
 	.id_table = icom_pci_table,
 	.probe = icom_probe,
-	.remove = __devexit_p(icom_remove),
+	.remove = icom_remove,
 };
 
 static int __init icom_init(void)
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 5b9bc19..675d94a 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -60,20 +60,27 @@
 #include <linux/pm_runtime.h>
 #include <linux/spi/ifx_modem.h>
 #include <linux/delay.h>
+#include <linux/reboot.h>
 
 #include "ifx6x60.h"
 
 #define IFX_SPI_MORE_MASK		0x10
-#define IFX_SPI_MORE_BIT		12	/* bit position in u16 */
-#define IFX_SPI_CTS_BIT			13	/* bit position in u16 */
+#define IFX_SPI_MORE_BIT		4	/* bit position in u8 */
+#define IFX_SPI_CTS_BIT			6	/* bit position in u8 */
 #define IFX_SPI_MODE			SPI_MODE_1
 #define IFX_SPI_TTY_ID			0
 #define IFX_SPI_TIMEOUT_SEC		2
 #define IFX_SPI_HEADER_0		(-1)
 #define IFX_SPI_HEADER_F		(-2)
 
+#define PO_POST_DELAY		200
+#define IFX_MDM_RST_PMU	4
+
 /* forward reference */
 static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev);
+static int ifx_modem_reboot_callback(struct notifier_block *nfb,
+				unsigned long event, void *data);
+static int ifx_modem_power_off(struct ifx_spi_device *ifx_dev);
 
 /* local variables */
 static int spi_bpw = 16;		/* 8, 16 or 32 bit word length */
@@ -81,6 +88,29 @@ static struct tty_driver *tty_drv;
 static struct ifx_spi_device *saved_ifx_dev;
 static struct lock_class_key ifx_spi_key;
 
+static struct notifier_block ifx_modem_reboot_notifier_block = {
+	.notifier_call = ifx_modem_reboot_callback,
+};
+
+static int ifx_modem_power_off(struct ifx_spi_device *ifx_dev)
+{
+	gpio_set_value(IFX_MDM_RST_PMU, 1);
+	msleep(PO_POST_DELAY);
+
+	return 0;
+}
+
+static int ifx_modem_reboot_callback(struct notifier_block *nfb,
+				 unsigned long event, void *data)
+{
+	if (saved_ifx_dev)
+		ifx_modem_power_off(saved_ifx_dev);
+	else
+		pr_warn("no ifx modem active;\n");
+
+	return NOTIFY_OK;
+}
+
 /* GPIO/GPE settings */
 
 /**
@@ -152,26 +182,67 @@ ifx_spi_power_state_clear(struct ifx_spi_device *ifx_dev, unsigned char val)
 }
 
 /**
- *	swap_buf
+ *	swap_buf_8
  *	@buf: our buffer
  *	@len : number of bytes (not words) in the buffer
  *	@end: end of buffer
  *
  *	Swap the contents of a buffer into big endian format
  */
-static inline void swap_buf(u16 *buf, int len, void *end)
+static inline void swap_buf_8(unsigned char *buf, int len, void *end)
+{
+	/* don't swap buffer if SPI word width is 8 bits */
+	return;
+}
+
+/**
+ *	swap_buf_16
+ *	@buf: our buffer
+ *	@len : number of bytes (not words) in the buffer
+ *	@end: end of buffer
+ *
+ *	Swap the contents of a buffer into big endian format
+ */
+static inline void swap_buf_16(unsigned char *buf, int len, void *end)
 {
 	int n;
 
+	u16 *buf_16 = (u16 *)buf;
 	len = ((len + 1) >> 1);
-	if ((void *)&buf[len] > end) {
-		pr_err("swap_buf: swap exceeds boundary (%p > %p)!",
-		       &buf[len], end);
+	if ((void *)&buf_16[len] > end) {
+		pr_err("swap_buf_16: swap exceeds boundary (%p > %p)!",
+		       &buf_16[len], end);
+		return;
+	}
+	for (n = 0; n < len; n++) {
+		*buf_16 = cpu_to_be16(*buf_16);
+		buf_16++;
+	}
+}
+
+/**
+ *	swap_buf_32
+ *	@buf: our buffer
+ *	@len : number of bytes (not words) in the buffer
+ *	@end: end of buffer
+ *
+ *	Swap the contents of a buffer into big endian format
+ */
+static inline void swap_buf_32(unsigned char *buf, int len, void *end)
+{
+	int n;
+
+	u32 *buf_32 = (u32 *)buf;
+	len = (len + 3) >> 2;
+
+	if ((void *)&buf_32[len] > end) {
+		pr_err("swap_buf_32: swap exceeds boundary (%p > %p)!\n",
+		       &buf_32[len], end);
 		return;
 	}
 	for (n = 0; n < len; n++) {
-		*buf = cpu_to_be16(*buf);
-		buf++;
+		*buf_32 = cpu_to_be32(*buf_32);
+		buf_32++;
 	}
 }
 
@@ -190,9 +261,7 @@ static void mrdy_assert(struct ifx_spi_device *ifx_dev)
 	if (!val) {
 		if (!test_and_set_bit(IFX_SPI_STATE_TIMER_PENDING,
 				      &ifx_dev->flags)) {
-			ifx_dev->spi_timer.expires =
-				jiffies + IFX_SPI_TIMEOUT_SEC*HZ;
-			add_timer(&ifx_dev->spi_timer);
+			mod_timer(&ifx_dev->spi_timer,jiffies + IFX_SPI_TIMEOUT_SEC*HZ);
 
 		}
 	}
@@ -449,7 +518,7 @@ static int ifx_spi_prepare_tx_buffer(struct ifx_spi_device *ifx_dev)
 					tx_count-IFX_SPI_HEADER_OVERHEAD,
 					ifx_dev->spi_more);
 	/* swap actual data in the buffer */
-	swap_buf((u16 *)(ifx_dev->tx_buffer), tx_count,
+	ifx_dev->swap_buf((ifx_dev->tx_buffer), tx_count,
 		&ifx_dev->tx_buffer[IFX_SPI_TRANSFER_SIZE]);
 	return tx_count;
 }
@@ -469,9 +538,17 @@ static int ifx_spi_write(struct tty_struct *tty, const unsigned char *buf,
 {
 	struct ifx_spi_device *ifx_dev = tty->driver_data;
 	unsigned char *tmp_buf = (unsigned char *)buf;
-	int tx_count = kfifo_in_locked(&ifx_dev->tx_fifo, tmp_buf, count,
-				   &ifx_dev->fifo_lock);
-	mrdy_assert(ifx_dev);
+	unsigned long flags;
+	bool is_fifo_empty;
+	int tx_count;
+
+	spin_lock_irqsave(&ifx_dev->fifo_lock, flags);
+	is_fifo_empty = kfifo_is_empty(&ifx_dev->tx_fifo);
+	tx_count = kfifo_in(&ifx_dev->tx_fifo, tmp_buf, count);
+	spin_unlock_irqrestore(&ifx_dev->fifo_lock, flags);
+	if (is_fifo_empty)
+		mrdy_assert(ifx_dev);
+
 	return tx_count;
 }
 
@@ -530,12 +607,19 @@ static int ifx_port_activate(struct tty_port *port, struct tty_struct *tty)
 	/* clear any old data; can't do this in 'close' */
 	kfifo_reset(&ifx_dev->tx_fifo);
 
+	/* clear any flag which may be set in port shutdown procedure */
+	clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags);
+	clear_bit(IFX_SPI_STATE_IO_READY, &ifx_dev->flags);
+
 	/* put port data into this tty */
 	tty->driver_data = ifx_dev;
 
 	/* allows flip string push from int context */
 	tty->low_latency = 1;
 
+	/* set flag to allows data transfer */
+	set_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags);
+
 	return 0;
 }
 
@@ -551,6 +635,7 @@ static void ifx_port_shutdown(struct tty_port *port)
 	struct ifx_spi_device *ifx_dev =
 		container_of(port, struct ifx_spi_device, tty_port);
 
+	clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags);
 	mrdy_set_low(ifx_dev);
 	clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
 	tasklet_kill(&ifx_dev->io_work_tasklet);
@@ -617,7 +702,7 @@ static void ifx_spi_complete(void *ctx)
 
 	if (!ifx_dev->spi_msg.status) {
 		/* check header validity, get comm flags */
-		swap_buf((u16 *)ifx_dev->rx_buffer, IFX_SPI_HEADER_OVERHEAD,
+		ifx_dev->swap_buf(ifx_dev->rx_buffer, IFX_SPI_HEADER_OVERHEAD,
 			&ifx_dev->rx_buffer[IFX_SPI_HEADER_OVERHEAD]);
 		decode_result = ifx_spi_decode_spi_header(ifx_dev->rx_buffer,
 				&length, &more, &cts);
@@ -636,7 +721,8 @@ static void ifx_spi_complete(void *ctx)
 
 		actual_length = min((unsigned int)length,
 					ifx_dev->spi_msg.actual_length);
-		swap_buf((u16 *)(ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD),
+		ifx_dev->swap_buf(
+			(ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD),
 			 actual_length,
 			 &ifx_dev->rx_buffer[IFX_SPI_TRANSFER_SIZE]);
 		ifx_spi_insert_flip_string(
@@ -705,7 +791,8 @@ static void ifx_spi_io(unsigned long data)
 	int retval;
 	struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *) data;
 
-	if (!test_and_set_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags)) {
+	if (!test_and_set_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags) &&
+		test_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags)) {
 		if (ifx_dev->gpio.unack_srdy_int_nb > 0)
 			ifx_dev->gpio.unack_srdy_int_nb--;
 
@@ -773,6 +860,7 @@ static void ifx_spi_free_port(struct ifx_spi_device *ifx_dev)
 {
 	if (ifx_dev->tty_dev)
 		tty_unregister_device(tty_drv, ifx_dev->minor);
+	tty_port_destroy(&ifx_dev->tty_port);
 	kfifo_free(&ifx_dev->tx_fifo);
 }
 
@@ -806,10 +894,12 @@ static int ifx_spi_create_port(struct ifx_spi_device *ifx_dev)
 		dev_dbg(&ifx_dev->spi_dev->dev,
 			"%s: registering tty device failed", __func__);
 		ret = PTR_ERR(ifx_dev->tty_dev);
-		goto error_ret;
+		goto error_port;
 	}
 	return 0;
 
+error_port:
+	tty_port_destroy(pport);
 error_ret:
 	ifx_spi_free_port(ifx_dev);
 	return ret;
@@ -826,7 +916,7 @@ error_ret:
 static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev)
 {
 	if (test_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags)) {
-		del_timer_sync(&ifx_dev->spi_timer);
+		del_timer(&ifx_dev->spi_timer);
 		clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
 	}
 
@@ -1001,6 +1091,14 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
 		return -ENODEV;
 	}
 
+	/* init swap_buf function according to word width configuration */
+	if (spi->bits_per_word == 32)
+		ifx_dev->swap_buf = swap_buf_32;
+	else if (spi->bits_per_word == 16)
+		ifx_dev->swap_buf = swap_buf_16;
+	else
+		ifx_dev->swap_buf = swap_buf_8;
+
 	/* ensure SPI protocol flags are initialized to enable transfer */
 	ifx_dev->spi_more = 0;
 	ifx_dev->spi_slave_cts = 0;
@@ -1219,6 +1317,9 @@ static int ifx_spi_spi_remove(struct spi_device *spi)
 
 static void ifx_spi_spi_shutdown(struct spi_device *spi)
 {
+	struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi);
+
+	ifx_modem_power_off(ifx_dev);
 }
 
 /*
@@ -1338,7 +1439,7 @@ static struct spi_driver ifx_spi_driver = {
 		.owner = THIS_MODULE},
 	.probe = ifx_spi_spi_probe,
 	.shutdown = ifx_spi_spi_shutdown,
-	.remove = __devexit_p(ifx_spi_spi_remove),
+	.remove = ifx_spi_spi_remove,
 	.suspend = ifx_spi_spi_suspend,
 	.resume = ifx_spi_spi_resume,
 	.id_table = ifx_id_table
@@ -1354,7 +1455,9 @@ static void __exit ifx_spi_exit(void)
 {
 	/* unregister */
 	tty_unregister_driver(tty_drv);
+	put_tty_driver(tty_drv);
 	spi_unregister_driver((void *)&ifx_spi_driver);
+	unregister_reboot_notifier(&ifx_modem_reboot_notifier_block);
 }
 
 /**
@@ -1389,16 +1492,31 @@ static int __init ifx_spi_init(void)
 	if (result) {
 		pr_err("%s: tty_register_driver failed(%d)",
 			DRVNAME, result);
-		put_tty_driver(tty_drv);
-		return result;
+		goto err_free_tty;
 	}
 
 	result = spi_register_driver((void *)&ifx_spi_driver);
 	if (result) {
 		pr_err("%s: spi_register_driver failed(%d)",
 			DRVNAME, result);
-		tty_unregister_driver(tty_drv);
+		goto err_unreg_tty;
 	}
+
+	result = register_reboot_notifier(&ifx_modem_reboot_notifier_block);
+	if (result) {
+		pr_err("%s: register ifx modem reboot notifier failed(%d)",
+			DRVNAME, result);
+		goto err_unreg_spi;
+	}
+
+	return 0;
+err_unreg_spi:
+	spi_unregister_driver((void *)&ifx_spi_driver);
+err_unreg_tty:
+	tty_unregister_driver(tty_drv);
+err_free_tty:
+	put_tty_driver(tty_drv);
+
 	return result;
 }
 
diff --git a/drivers/tty/serial/ifx6x60.h b/drivers/tty/serial/ifx6x60.h
index e8464ba..4fbddc2 100644
--- a/drivers/tty/serial/ifx6x60.h
+++ b/drivers/tty/serial/ifx6x60.h
@@ -41,6 +41,7 @@
 #define IFX_SPI_STATE_IO_IN_PROGRESS	1
 #define IFX_SPI_STATE_IO_READY		2
 #define IFX_SPI_STATE_TIMER_PENDING	3
+#define IFX_SPI_STATE_IO_AVAILABLE	4
 
 /* flow control bitfields */
 #define IFX_SPI_DCD			0
@@ -124,6 +125,7 @@ struct ifx_spi_device {
 #define MR_INPROGRESS	1
 #define MR_COMPLETE	2
 	wait_queue_head_t mdm_reset_wait;
+	void (*swap_buf)(unsigned char *buf, int len, void *end);
 };
 
 #endif /* _IFX6X60_H */
diff --git a/drivers/tty/serial/ioc3_serial.c b/drivers/tty/serial/ioc3_serial.c
index 5ac5289..d8f1d1d 100644
--- a/drivers/tty/serial/ioc3_serial.c
+++ b/drivers/tty/serial/ioc3_serial.c
@@ -2010,7 +2010,7 @@ static int ioc3uart_remove(struct ioc3_submodule *is,
  * @idd: ioc3 driver data for this card
  */
 
-static int __devinit
+static int
 ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
 {
 	struct pci_dev *pdev = idd->pdev;
diff --git a/drivers/tty/serial/jsm/jsm.h b/drivers/tty/serial/jsm/jsm.h
index 529bec6..844d5e4 100644
--- a/drivers/tty/serial/jsm/jsm.h
+++ b/drivers/tty/serial/jsm/jsm.h
@@ -57,9 +57,11 @@ enum {
 	DBG_CARR	= 0x10000,
 };
 
-#define jsm_printk(nlevel, klevel, pdev, fmt, args...)	\
-	if ((DBG_##nlevel & jsm_debug))			\
-	dev_printk(KERN_##klevel, pdev->dev, fmt, ## args)
+#define jsm_dbg(nlevel, pdev, fmt, ...)				\
+do {								\
+	if (DBG_##nlevel & jsm_debug)				\
+		dev_dbg(pdev->dev, fmt, ##__VA_ARGS__);		\
+} while (0)
 
 #define	MAXLINES	256
 #define MAXPORTS	8
diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c
index 5ab3c3b..a47d882 100644
--- a/drivers/tty/serial/jsm/jsm_driver.c
+++ b/drivers/tty/serial/jsm/jsm_driver.c
@@ -64,7 +64,7 @@ int jsm_debug;
 module_param(jsm_debug, int, 0);
 MODULE_PARM_DESC(jsm_debug, "Driver debugging level");
 
-static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	int rc = 0;
 	struct jsm_board *brd;
@@ -107,8 +107,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device
 
 	brd->irq = pdev->irq;
 
-	jsm_printk(INIT, INFO, &brd->pci_dev,
-		"jsm_found_board - NEO adapter\n");
+	jsm_dbg(INIT, &brd->pci_dev, "jsm_found_board - NEO adapter\n");
 
 	/* get the PCI Base Address Registers */
 	brd->membase	= pci_resource_start(pdev, 0);
@@ -179,7 +178,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device
 	return rc;
 }
 
-static void __devexit jsm_remove_one(struct pci_dev *pdev)
+static void jsm_remove_one(struct pci_dev *pdev)
 {
 	struct jsm_board *brd = pci_get_drvdata(pdev);
 	int i = 0;
@@ -218,7 +217,7 @@ static struct pci_driver jsm_driver = {
 	.name		= "jsm",
 	.id_table	= jsm_pci_tbl,
 	.probe		= jsm_probe_one,
-	.remove		= __devexit_p(jsm_remove_one),
+	.remove		= jsm_remove_one,
 	.err_handler    = &jsm_err_handler,
 };
 
diff --git a/drivers/tty/serial/jsm/jsm_neo.c b/drivers/tty/serial/jsm/jsm_neo.c
index 81dfafa..dfaf488 100644
--- a/drivers/tty/serial/jsm/jsm_neo.c
+++ b/drivers/tty/serial/jsm/jsm_neo.c
@@ -52,7 +52,7 @@ static void neo_set_cts_flow_control(struct jsm_channel *ch)
 	ier = readb(&ch->ch_neo_uart->ier);
 	efr = readb(&ch->ch_neo_uart->efr);
 
-	jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting CTSFLOW\n");
+	jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Setting CTSFLOW\n");
 
 	/* Turn on auto CTS flow control */
 	ier |= (UART_17158_IER_CTSDSR);
@@ -83,7 +83,7 @@ static void neo_set_rts_flow_control(struct jsm_channel *ch)
 	ier = readb(&ch->ch_neo_uart->ier);
 	efr = readb(&ch->ch_neo_uart->efr);
 
-	jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting RTSFLOW\n");
+	jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Setting RTSFLOW\n");
 
 	/* Turn on auto RTS flow control */
 	ier |= (UART_17158_IER_RTSDTR);
@@ -123,7 +123,7 @@ static void neo_set_ixon_flow_control(struct jsm_channel *ch)
 	ier = readb(&ch->ch_neo_uart->ier);
 	efr = readb(&ch->ch_neo_uart->efr);
 
-	jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting IXON FLOW\n");
+	jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Setting IXON FLOW\n");
 
 	/* Turn off auto CTS flow control */
 	ier &= ~(UART_17158_IER_CTSDSR);
@@ -160,7 +160,7 @@ static void neo_set_ixoff_flow_control(struct jsm_channel *ch)
 	ier = readb(&ch->ch_neo_uart->ier);
 	efr = readb(&ch->ch_neo_uart->efr);
 
-	jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting IXOFF FLOW\n");
+	jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Setting IXOFF FLOW\n");
 
 	/* Turn off auto RTS flow control */
 	ier &= ~(UART_17158_IER_RTSDTR);
@@ -198,7 +198,7 @@ static void neo_set_no_input_flow_control(struct jsm_channel *ch)
 	ier = readb(&ch->ch_neo_uart->ier);
 	efr = readb(&ch->ch_neo_uart->efr);
 
-	jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Unsetting Input FLOW\n");
+	jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Unsetting Input FLOW\n");
 
 	/* Turn off auto RTS flow control */
 	ier &= ~(UART_17158_IER_RTSDTR);
@@ -237,7 +237,7 @@ static void neo_set_no_output_flow_control(struct jsm_channel *ch)
 	ier = readb(&ch->ch_neo_uart->ier);
 	efr = readb(&ch->ch_neo_uart->efr);
 
-	jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Unsetting Output FLOW\n");
+	jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Unsetting Output FLOW\n");
 
 	/* Turn off auto CTS flow control */
 	ier &= ~(UART_17158_IER_CTSDSR);
@@ -276,7 +276,7 @@ static inline void neo_set_new_start_stop_chars(struct jsm_channel *ch)
 	if (ch->ch_c_cflag & CRTSCTS)
 		return;
 
-	jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "start\n");
+	jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "start\n");
 
 	/* Tell UART what start/stop chars it should be looking for */
 	writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
@@ -455,7 +455,7 @@ static void neo_copy_data_from_uart_to_queue(struct jsm_channel *ch)
 		 * I hope thats okay with everyone? Yes? Good.
 		 */
 		while (qleft < 1) {
-			jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+			jsm_dbg(READ, &ch->ch_bd->pci_dev,
 				"Queue full, dropping DATA:%x LSR:%x\n",
 				ch->ch_rqueue[tail], ch->ch_equeue[tail]);
 
@@ -467,8 +467,8 @@ static void neo_copy_data_from_uart_to_queue(struct jsm_channel *ch)
 		memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, 1);
 		ch->ch_equeue[head] = (u8) linestatus;
 
-		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
-				"DATA/LSR pair: %x %x\n", ch->ch_rqueue[head], ch->ch_equeue[head]);
+		jsm_dbg(READ, &ch->ch_bd->pci_dev, "DATA/LSR pair: %x %x\n",
+			ch->ch_rqueue[head], ch->ch_equeue[head]);
 
 		/* Ditch any remaining linestatus value. */
 		linestatus = 0;
@@ -521,8 +521,8 @@ static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch)
 			ch->ch_cached_lsr &= ~(UART_LSR_THRE);
 
 			writeb(circ->buf[circ->tail], &ch->ch_neo_uart->txrx);
-			jsm_printk(WRITE, INFO, &ch->ch_bd->pci_dev,
-					"Tx data: %x\n", circ->buf[circ->tail]);
+			jsm_dbg(WRITE, &ch->ch_bd->pci_dev,
+				"Tx data: %x\n", circ->buf[circ->tail]);
 			circ->tail = (circ->tail + 1) & (UART_XMIT_SIZE - 1);
 			ch->ch_txcount++;
 		}
@@ -575,8 +575,9 @@ static void neo_parse_modem(struct jsm_channel *ch, u8 signals)
 {
 	u8 msignals = signals;
 
-	jsm_printk(MSIGS, INFO, &ch->ch_bd->pci_dev,
-			"neo_parse_modem: port: %d msignals: %x\n", ch->ch_portnum, msignals);
+	jsm_dbg(MSIGS, &ch->ch_bd->pci_dev,
+		"neo_parse_modem: port: %d msignals: %x\n",
+		ch->ch_portnum, msignals);
 
 	/* Scrub off lower bits. They signify delta's, which I don't care about */
 	/* Keep DDCD and DDSR though */
@@ -606,8 +607,8 @@ static void neo_parse_modem(struct jsm_channel *ch, u8 signals)
 	else
 		ch->ch_mistat &= ~UART_MSR_CTS;
 
-	jsm_printk(MSIGS, INFO, &ch->ch_bd->pci_dev,
-			"Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n",
+	jsm_dbg(MSIGS, &ch->ch_bd->pci_dev,
+		"Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n",
 		ch->ch_portnum,
 		!!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_DTR),
 		!!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_RTS),
@@ -649,8 +650,8 @@ static void neo_flush_uart_write(struct jsm_channel *ch)
 		/* Check to see if the UART feels it completely flushed the FIFO. */
 		tmp = readb(&ch->ch_neo_uart->isr_fcr);
 		if (tmp & 4) {
-			jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
-					"Still flushing TX UART... i: %d\n", i);
+			jsm_dbg(IOCTL, &ch->ch_bd->pci_dev,
+				"Still flushing TX UART... i: %d\n", i);
 			udelay(10);
 		}
 		else
@@ -681,8 +682,8 @@ static void neo_flush_uart_read(struct jsm_channel *ch)
 		/* Check to see if the UART feels it completely flushed the FIFO. */
 		tmp = readb(&ch->ch_neo_uart->isr_fcr);
 		if (tmp & 2) {
-			jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
-					"Still flushing RX UART... i: %d\n", i);
+			jsm_dbg(IOCTL, &ch->ch_bd->pci_dev,
+				"Still flushing RX UART... i: %d\n", i);
 			udelay(10);
 		}
 		else
@@ -705,8 +706,9 @@ static void neo_clear_break(struct jsm_channel *ch, int force)
 		writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr);
 
 		ch->ch_flags &= ~(CH_BREAK_SENDING);
-		jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
-				"clear break Finishing UART_LCR_SBC! finished: %lx\n", jiffies);
+		jsm_dbg(IOCTL, &ch->ch_bd->pci_dev,
+			"clear break Finishing UART_LCR_SBC! finished: %lx\n",
+			jiffies);
 
 		/* flush write operation */
 		neo_pci_posting_flush(ch->ch_bd);
@@ -748,8 +750,8 @@ static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
 		 */
 		isr &= ~(UART_17158_IIR_FIFO_ENABLED);
 
-		jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
-				"%s:%d isr: %x\n", __FILE__, __LINE__, isr);
+		jsm_dbg(INTR, &ch->ch_bd->pci_dev, "%s:%d isr: %x\n",
+			__FILE__, __LINE__, isr);
 
 		if (isr & (UART_17158_IIR_RDI_TIMEOUT | UART_IIR_RDI)) {
 			/* Read data from uart -> queue */
@@ -772,8 +774,9 @@ static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
 		if (isr & UART_17158_IIR_XONXOFF) {
 			cause = readb(&ch->ch_neo_uart->xoffchar1);
 
-			jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
-					"Port %d. Got ISR_XONXOFF: cause:%x\n", port, cause);
+			jsm_dbg(INTR, &ch->ch_bd->pci_dev,
+				"Port %d. Got ISR_XONXOFF: cause:%x\n",
+				port, cause);
 
 			/*
 			 * Since the UART detected either an XON or
@@ -786,17 +789,19 @@ static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
 				if (brd->channels[port]->ch_flags & CH_STOP) {
 					ch->ch_flags &= ~(CH_STOP);
 				}
-				jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
-						"Port %d. XON detected in incoming data\n", port);
+				jsm_dbg(INTR, &ch->ch_bd->pci_dev,
+					"Port %d. XON detected in incoming data\n",
+					port);
 			}
 			else if (cause == UART_17158_XOFF_DETECT) {
 				if (!(brd->channels[port]->ch_flags & CH_STOP)) {
 					ch->ch_flags |= CH_STOP;
-					jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
-							"Setting CH_STOP\n");
+					jsm_dbg(INTR, &ch->ch_bd->pci_dev,
+						"Setting CH_STOP\n");
 				}
-				jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
-						"Port: %d. XOFF detected in incoming data\n", port);
+				jsm_dbg(INTR, &ch->ch_bd->pci_dev,
+					"Port: %d. XOFF detected in incoming data\n",
+					port);
 			}
 			spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
 		}
@@ -825,8 +830,8 @@ static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
 		}
 
 		/* Parse any modem signal changes */
-		jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
-				"MOD_STAT: sending to parse_modem_sigs\n");
+		jsm_dbg(INTR, &ch->ch_bd->pci_dev,
+			"MOD_STAT: sending to parse_modem_sigs\n");
 		neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
 	}
 }
@@ -849,8 +854,8 @@ static inline void neo_parse_lsr(struct jsm_board *brd, u32 port)
 
 	linestatus = readb(&ch->ch_neo_uart->lsr);
 
-	jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
-			"%s:%d port: %d linestatus: %x\n", __FILE__, __LINE__, port, linestatus);
+	jsm_dbg(INTR, &ch->ch_bd->pci_dev, "%s:%d port: %d linestatus: %x\n",
+		__FILE__, __LINE__, port, linestatus);
 
 	ch->ch_cached_lsr |= linestatus;
 
@@ -869,7 +874,7 @@ static inline void neo_parse_lsr(struct jsm_board *brd, u32 port)
 	 *to do the special RX+LSR read for this FIFO load.
 	 */
 	if (linestatus & UART_17158_RX_FIFO_DATA_ERROR)
-		jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
+		jsm_dbg(INTR, &ch->ch_bd->pci_dev,
 			"%s:%d Port: %d Got an RX error, need to parse LSR\n",
 			__FILE__, __LINE__, port);
 
@@ -880,20 +885,21 @@ static inline void neo_parse_lsr(struct jsm_board *brd, u32 port)
 
 	if (linestatus & UART_LSR_PE) {
 		ch->ch_err_parity++;
-		jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
-			"%s:%d Port: %d. PAR ERR!\n", __FILE__, __LINE__, port);
+		jsm_dbg(INTR, &ch->ch_bd->pci_dev, "%s:%d Port: %d. PAR ERR!\n",
+			__FILE__, __LINE__, port);
 	}
 
 	if (linestatus & UART_LSR_FE) {
 		ch->ch_err_frame++;
-		jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
-			"%s:%d Port: %d. FRM ERR!\n", __FILE__, __LINE__, port);
+		jsm_dbg(INTR, &ch->ch_bd->pci_dev, "%s:%d Port: %d. FRM ERR!\n",
+			__FILE__, __LINE__, port);
 	}
 
 	if (linestatus & UART_LSR_BI) {
 		ch->ch_err_break++;
-		jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
-			"%s:%d Port: %d. BRK INTR!\n", __FILE__, __LINE__, port);
+		jsm_dbg(INTR, &ch->ch_bd->pci_dev,
+			"%s:%d Port: %d. BRK INTR!\n",
+			__FILE__, __LINE__, port);
 	}
 
 	if (linestatus & UART_LSR_OE) {
@@ -904,8 +910,9 @@ static inline void neo_parse_lsr(struct jsm_board *brd, u32 port)
 		 * Probably we should eventually have an orun stat in our driver...
 		 */
 		ch->ch_err_overrun++;
-		jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
-			"%s:%d Port: %d. Rx Overrun!\n", __FILE__, __LINE__, port);
+		jsm_dbg(INTR, &ch->ch_bd->pci_dev,
+			"%s:%d Port: %d. Rx Overrun!\n",
+			__FILE__, __LINE__, port);
 	}
 
 	if (linestatus & UART_LSR_THRE) {
@@ -1128,11 +1135,11 @@ static irqreturn_t neo_intr(int irq, void *voidbrd)
 	 */
 	uart_poll = readl(brd->re_map_membase + UART_17158_POLL_ADDR_OFFSET);
 
-	jsm_printk(INTR, INFO, &brd->pci_dev,
-		"%s:%d uart_poll: %x\n", __FILE__, __LINE__, uart_poll);
+	jsm_dbg(INTR, &brd->pci_dev, "%s:%d uart_poll: %x\n",
+		__FILE__, __LINE__, uart_poll);
 
 	if (!uart_poll) {
-		jsm_printk(INTR, INFO, &brd->pci_dev,
+		jsm_dbg(INTR, &brd->pci_dev,
 			"Kernel interrupted to me, but no pending interrupts...\n");
 		spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);
 		return IRQ_NONE;
@@ -1158,15 +1165,15 @@ static irqreturn_t neo_intr(int irq, void *voidbrd)
 			continue;
 		}
 
-		jsm_printk(INTR, INFO, &brd->pci_dev,
-		"%s:%d port: %x type: %x\n", __FILE__, __LINE__, port, type);
+		jsm_dbg(INTR, &brd->pci_dev, "%s:%d port: %x type: %x\n",
+			__FILE__, __LINE__, port, type);
 
 		/* Remove this port + type from uart_poll */
 		uart_poll &= ~(jsm_offset_table[port]);
 
 		if (!type) {
 			/* If no type, just ignore it, and move onto next port */
-			jsm_printk(INTR, ERR, &brd->pci_dev,
+			jsm_dbg(INTR, &brd->pci_dev,
 				"Interrupt with no type! port: %d\n", port);
 			continue;
 		}
@@ -1231,15 +1238,16 @@ static irqreturn_t neo_intr(int irq, void *voidbrd)
 			 * these once and awhile.
 			 * Its harmless, just ignore it and move on.
 			 */
-			jsm_printk(INTR, ERR, &brd->pci_dev,
-				"%s:%d Unknown Interrupt type: %x\n", __FILE__, __LINE__, type);
+			jsm_dbg(INTR, &brd->pci_dev,
+				"%s:%d Unknown Interrupt type: %x\n",
+				__FILE__, __LINE__, type);
 			continue;
 		}
 	}
 
 	spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);
 
-	jsm_printk(INTR, INFO, &brd->pci_dev, "finish.\n");
+	jsm_dbg(INTR, &brd->pci_dev, "finish\n");
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c
index 7139796..4c00c55 100644
--- a/drivers/tty/serial/jsm/jsm_tty.c
+++ b/drivers/tty/serial/jsm/jsm_tty.c
@@ -43,7 +43,7 @@ static inline int jsm_get_mstat(struct jsm_channel *ch)
 	unsigned char mstat;
 	unsigned result;
 
-	jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "start\n");
+	jsm_dbg(IOCTL, &ch->ch_bd->pci_dev, "start\n");
 
 	mstat = (ch->ch_mostat | ch->ch_mistat);
 
@@ -62,7 +62,7 @@ static inline int jsm_get_mstat(struct jsm_channel *ch)
 	if (mstat & UART_MSR_DCD)
 		result |= TIOCM_CD;
 
-	jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
+	jsm_dbg(IOCTL, &ch->ch_bd->pci_dev, "finish\n");
 	return result;
 }
 
@@ -79,14 +79,14 @@ static unsigned int jsm_tty_get_mctrl(struct uart_port *port)
 	int result;
 	struct jsm_channel *channel = (struct jsm_channel *)port;
 
-	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
+	jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "start\n");
 
 	result = jsm_get_mstat(channel);
 
 	if (result < 0)
 		return -ENXIO;
 
-	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
+	jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "finish\n");
 
 	return result;
 }
@@ -100,7 +100,7 @@ static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 	struct jsm_channel *channel = (struct jsm_channel *)port;
 
-	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
+	jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "start\n");
 
 	if (mctrl & TIOCM_RTS)
 		channel->ch_mostat |= UART_MCR_RTS;
@@ -114,7 +114,7 @@ static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl)
 
 	channel->ch_bd->bd_ops->assert_modem_signals(channel);
 
-	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
+	jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "finish\n");
 	udelay(10);
 }
 
@@ -135,23 +135,23 @@ static void jsm_tty_start_tx(struct uart_port *port)
 {
 	struct jsm_channel *channel = (struct jsm_channel *)port;
 
-	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
+	jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "start\n");
 
 	channel->ch_flags &= ~(CH_STOP);
 	jsm_tty_write(port);
 
-	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
+	jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "finish\n");
 }
 
 static void jsm_tty_stop_tx(struct uart_port *port)
 {
 	struct jsm_channel *channel = (struct jsm_channel *)port;
 
-	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
+	jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "start\n");
 
 	channel->ch_flags |= (CH_STOP);
 
-	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
+	jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "finish\n");
 }
 
 static void jsm_tty_send_xchar(struct uart_port *port, char ch)
@@ -216,16 +216,16 @@ static int jsm_tty_open(struct uart_port *port)
 	if (!channel->ch_rqueue) {
 		channel->ch_rqueue = kzalloc(RQUEUESIZE, GFP_KERNEL);
 		if (!channel->ch_rqueue) {
-			jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
-				"unable to allocate read queue buf");
+			jsm_dbg(INIT, &channel->ch_bd->pci_dev,
+				"unable to allocate read queue buf\n");
 			return -ENOMEM;
 		}
 	}
 	if (!channel->ch_equeue) {
 		channel->ch_equeue = kzalloc(EQUEUESIZE, GFP_KERNEL);
 		if (!channel->ch_equeue) {
-			jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
-				"unable to allocate error queue buf");
+			jsm_dbg(INIT, &channel->ch_bd->pci_dev,
+				"unable to allocate error queue buf\n");
 			return -ENOMEM;
 		}
 	}
@@ -234,7 +234,7 @@ static int jsm_tty_open(struct uart_port *port)
 	/*
 	 * Initialize if neither terminal is open.
 	 */
-	jsm_printk(OPEN, INFO, &channel->ch_bd->pci_dev,
+	jsm_dbg(OPEN, &channel->ch_bd->pci_dev,
 		"jsm_open: initializing channel in open...\n");
 
 	/*
@@ -270,7 +270,7 @@ static int jsm_tty_open(struct uart_port *port)
 
 	channel->ch_open_count++;
 
-	jsm_printk(OPEN, INFO, &channel->ch_bd->pci_dev, "finish\n");
+	jsm_dbg(OPEN, &channel->ch_bd->pci_dev, "finish\n");
 	return 0;
 }
 
@@ -280,7 +280,7 @@ static void jsm_tty_close(struct uart_port *port)
 	struct ktermios *ts;
 	struct jsm_channel *channel = (struct jsm_channel *)port;
 
-	jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n");
+	jsm_dbg(CLOSE, &channel->ch_bd->pci_dev, "start\n");
 
 	bd = channel->ch_bd;
 	ts = &port->state->port.tty->termios;
@@ -293,7 +293,7 @@ static void jsm_tty_close(struct uart_port *port)
 	 * If we have HUPCL set, lower DTR and RTS
 	 */
 	if (channel->ch_c_cflag & HUPCL) {
-		jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev,
+		jsm_dbg(CLOSE, &channel->ch_bd->pci_dev,
 			"Close. HUPCL set, dropping DTR/RTS\n");
 
 		/* Drop RTS/DTR */
@@ -304,7 +304,7 @@ static void jsm_tty_close(struct uart_port *port)
 	/* Turn off UART interrupts for this port */
 	channel->ch_bd->bd_ops->uart_off(channel);
 
-	jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "finish\n");
+	jsm_dbg(CLOSE, &channel->ch_bd->pci_dev, "finish\n");
 }
 
 static void jsm_tty_set_termios(struct uart_port *port,
@@ -371,7 +371,7 @@ static struct uart_ops jsm_ops = {
  * Init the tty subsystem.  Called once per board after board has been
  * downloaded and init'ed.
  */
-int __devinit jsm_tty_init(struct jsm_board *brd)
+int jsm_tty_init(struct jsm_board *brd)
 {
 	int i;
 	void __iomem *vaddr;
@@ -380,7 +380,7 @@ int __devinit jsm_tty_init(struct jsm_board *brd)
 	if (!brd)
 		return -ENXIO;
 
-	jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
+	jsm_dbg(INIT, &brd->pci_dev, "start\n");
 
 	/*
 	 * Initialize board structure elements.
@@ -401,9 +401,9 @@ int __devinit jsm_tty_init(struct jsm_board *brd)
 			 */
 			brd->channels[i] = kzalloc(sizeof(struct jsm_channel), GFP_KERNEL);
 			if (!brd->channels[i]) {
-				jsm_printk(CORE, ERR, &brd->pci_dev,
+				jsm_dbg(CORE, &brd->pci_dev,
 					"%s:%d Unable to allocate memory for channel struct\n",
-							 __FILE__, __LINE__);
+					__FILE__, __LINE__);
 			}
 		}
 	}
@@ -431,7 +431,7 @@ int __devinit jsm_tty_init(struct jsm_board *brd)
 		init_waitqueue_head(&ch->ch_flags_wait);
 	}
 
-	jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
+	jsm_dbg(INIT, &brd->pci_dev, "finish\n");
 	return 0;
 }
 
@@ -444,7 +444,7 @@ int jsm_uart_port_init(struct jsm_board *brd)
 	if (!brd)
 		return -ENXIO;
 
-	jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
+	jsm_dbg(INIT, &brd->pci_dev, "start\n");
 
 	/*
 	 * Initialize board structure elements.
@@ -481,7 +481,7 @@ int jsm_uart_port_init(struct jsm_board *brd)
 			printk(KERN_INFO "jsm: Port %d added\n", i);
 	}
 
-	jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
+	jsm_dbg(INIT, &brd->pci_dev, "finish\n");
 	return 0;
 }
 
@@ -493,7 +493,7 @@ int jsm_remove_uart_port(struct jsm_board *brd)
 	if (!brd)
 		return -ENXIO;
 
-	jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
+	jsm_dbg(INIT, &brd->pci_dev, "start\n");
 
 	/*
 	 * Initialize board structure elements.
@@ -513,7 +513,7 @@ int jsm_remove_uart_port(struct jsm_board *brd)
 		uart_remove_one_port(&jsm_uart_driver, &brd->channels[i]->uart_port);
 	}
 
-	jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
+	jsm_dbg(INIT, &brd->pci_dev, "finish\n");
 	return 0;
 }
 
@@ -531,7 +531,7 @@ void jsm_input(struct jsm_channel *ch)
 	int s = 0;
 	int i = 0;
 
-	jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start\n");
+	jsm_dbg(READ, &ch->ch_bd->pci_dev, "start\n");
 
 	if (!ch)
 		return;
@@ -560,7 +560,7 @@ void jsm_input(struct jsm_channel *ch)
 		return;
 	}
 
-	jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start\n");
+	jsm_dbg(READ, &ch->ch_bd->pci_dev, "start\n");
 
 	/*
 	 *If the device is not open, or CREAD is off, flush
@@ -569,8 +569,9 @@ void jsm_input(struct jsm_channel *ch)
 	if (!tp ||
 		!(tp->termios.c_cflag & CREAD) ) {
 
-		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
-			"input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum);
+		jsm_dbg(READ, &ch->ch_bd->pci_dev,
+			"input. dropping %d bytes on port %d...\n",
+			data_len, ch->ch_portnum);
 		ch->ch_r_head = tail;
 
 		/* Force queue flow control to be released, if needed */
@@ -585,17 +586,17 @@ void jsm_input(struct jsm_channel *ch)
 	 */
 	if (ch->ch_flags & CH_STOPI) {
 		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+		jsm_dbg(READ, &ch->ch_bd->pci_dev,
 			"Port %d throttled, not reading any data. head: %x tail: %x\n",
 			ch->ch_portnum, head, tail);
 		return;
 	}
 
-	jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start 2\n");
+	jsm_dbg(READ, &ch->ch_bd->pci_dev, "start 2\n");
 
 	if (data_len <= 0) {
 		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n");
+		jsm_dbg(READ, &ch->ch_bd->pci_dev, "jsm_input 1\n");
 		return;
 	}
 
@@ -653,7 +654,7 @@ void jsm_input(struct jsm_channel *ch)
 	/* Tell the tty layer its okay to "eat" the data now */
 	tty_flip_buffer_push(tp);
 
-	jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
+	jsm_dbg(IOCTL, &ch->ch_bd->pci_dev, "finish\n");
 }
 
 static void jsm_carrier(struct jsm_channel *ch)
@@ -663,7 +664,7 @@ static void jsm_carrier(struct jsm_channel *ch)
 	int virt_carrier = 0;
 	int phys_carrier = 0;
 
-	jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev, "start\n");
+	jsm_dbg(CARR, &ch->ch_bd->pci_dev, "start\n");
 	if (!ch)
 		return;
 
@@ -673,16 +674,16 @@ static void jsm_carrier(struct jsm_channel *ch)
 		return;
 
 	if (ch->ch_mistat & UART_MSR_DCD) {
-		jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
-			"mistat: %x D_CD: %x\n", ch->ch_mistat, ch->ch_mistat & UART_MSR_DCD);
+		jsm_dbg(CARR, &ch->ch_bd->pci_dev, "mistat: %x D_CD: %x\n",
+			ch->ch_mistat, ch->ch_mistat & UART_MSR_DCD);
 		phys_carrier = 1;
 	}
 
 	if (ch->ch_c_cflag & CLOCAL)
 		virt_carrier = 1;
 
-	jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
-		"DCD: physical: %d virt: %d\n", phys_carrier, virt_carrier);
+	jsm_dbg(CARR, &ch->ch_bd->pci_dev, "DCD: physical: %d virt: %d\n",
+		phys_carrier, virt_carrier);
 
 	/*
 	 * Test for a VIRTUAL carrier transition to HIGH.
@@ -694,8 +695,7 @@ static void jsm_carrier(struct jsm_channel *ch)
 		 * for carrier in the open routine.
 		 */
 
-		jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
-			"carrier: virt DCD rose\n");
+		jsm_dbg(CARR, &ch->ch_bd->pci_dev, "carrier: virt DCD rose\n");
 
 		if (waitqueue_active(&(ch->ch_flags_wait)))
 			wake_up_interruptible(&ch->ch_flags_wait);
@@ -711,7 +711,7 @@ static void jsm_carrier(struct jsm_channel *ch)
 		 * for carrier in the open routine.
 		 */
 
-		jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
+		jsm_dbg(CARR, &ch->ch_bd->pci_dev,
 			"carrier: physical DCD rose\n");
 
 		if (waitqueue_active(&(ch->ch_flags_wait)))
@@ -790,8 +790,8 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
 			if(!(ch->ch_flags & CH_RECEIVER_OFF)) {
 				bd_ops->disable_receiver(ch);
 				ch->ch_flags |= (CH_RECEIVER_OFF);
-				jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
-					"Internal queue hit hilevel mark (%d)! Turning off interrupts.\n",
+				jsm_dbg(READ, &ch->ch_bd->pci_dev,
+					"Internal queue hit hilevel mark (%d)! Turning off interrupts\n",
 					qleft);
 			}
 		}
@@ -800,8 +800,9 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
 			if (ch->ch_stops_sent <= MAX_STOPS_SENT) {
 				bd_ops->send_stop_character(ch);
 				ch->ch_stops_sent++;
-				jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
-					"Sending stop char! Times sent: %x\n", ch->ch_stops_sent);
+				jsm_dbg(READ, &ch->ch_bd->pci_dev,
+					"Sending stop char! Times sent: %x\n",
+					ch->ch_stops_sent);
 			}
 		}
 	}
@@ -827,8 +828,8 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
 			if (ch->ch_flags & CH_RECEIVER_OFF) {
 				bd_ops->enable_receiver(ch);
 				ch->ch_flags &= ~(CH_RECEIVER_OFF);
-				jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
-					"Internal queue hit lowlevel mark (%d)! Turning on interrupts.\n",
+				jsm_dbg(READ, &ch->ch_bd->pci_dev,
+					"Internal queue hit lowlevel mark (%d)! Turning on interrupts\n",
 					qleft);
 			}
 		}
@@ -836,7 +837,8 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
 		else if (ch->ch_c_iflag & IXOFF && ch->ch_stops_sent) {
 			ch->ch_stops_sent = 0;
 			bd_ops->send_start_character(ch);
-			jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "Sending start char!\n");
+			jsm_dbg(READ, &ch->ch_bd->pci_dev,
+				"Sending start char!\n");
 		}
 	}
 }
diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c
index d185247..6ac2b79 100644
--- a/drivers/tty/serial/kgdb_nmi.c
+++ b/drivers/tty/serial/kgdb_nmi.c
@@ -266,6 +266,7 @@ static int kgdb_nmi_tty_install(struct tty_driver *drv, struct tty_struct *tty)
 	}
 	return 0;
 err:
+	tty_port_destroy(&priv->port);
 	kfree(priv);
 	return ret;
 }
@@ -275,6 +276,7 @@ static void kgdb_nmi_tty_cleanup(struct tty_struct *tty)
 	struct kgdb_nmi_tty_priv *priv = tty->driver_data;
 
 	tty->driver_data = NULL;
+	tty_port_destroy(&priv->port);
 	kfree(priv);
 }
 
diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
index ba3af3b..0e86bff 100644
--- a/drivers/tty/serial/lpc32xx_hs.c
+++ b/drivers/tty/serial/lpc32xx_hs.c
@@ -686,7 +686,7 @@ static struct uart_ops serial_lpc32xx_pops = {
 /*
  * Register a set of serial devices attached to a platform device
  */
-static int __devinit serial_hs_lpc32xx_probe(struct platform_device *pdev)
+static int serial_hs_lpc32xx_probe(struct platform_device *pdev)
 {
 	struct lpc32xx_hsuart_port *p = &lpc32xx_hs_ports[uarts_registered];
 	int ret = 0;
@@ -740,7 +740,7 @@ static int __devinit serial_hs_lpc32xx_probe(struct platform_device *pdev)
 /*
  * Remove serial ports registered against a platform device.
  */
-static int __devexit serial_hs_lpc32xx_remove(struct platform_device *pdev)
+static int serial_hs_lpc32xx_remove(struct platform_device *pdev)
 {
 	struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);
 
@@ -783,7 +783,7 @@ MODULE_DEVICE_TABLE(of, serial_hs_lpc32xx_dt_ids);
 
 static struct platform_driver serial_hs_lpc32xx_driver = {
 	.probe		= serial_hs_lpc32xx_probe,
-	.remove		= __devexit_p(serial_hs_lpc32xx_remove),
+	.remove		= serial_hs_lpc32xx_remove,
 	.suspend	= serial_hs_lpc32xx_suspend,
 	.resume		= serial_hs_lpc32xx_resume,
 	.driver		= {
diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c
index 0f24486..7ce3197 100644
--- a/drivers/tty/serial/max3100.c
+++ b/drivers/tty/serial/max3100.c
@@ -742,7 +742,7 @@ static struct uart_driver max3100_uart_driver = {
 };
 static int uart_driver_registered;
 
-static int __devinit max3100_probe(struct spi_device *spi)
+static int max3100_probe(struct spi_device *spi)
 {
 	int i, retval;
 	struct plat_max3100 *pdata;
@@ -818,7 +818,7 @@ static int __devinit max3100_probe(struct spi_device *spi)
 	return 0;
 }
 
-static int __devexit max3100_remove(struct spi_device *spi)
+static int max3100_remove(struct spi_device *spi)
 {
 	struct max3100_port *s = dev_get_drvdata(&spi->dev);
 	int i;
@@ -907,7 +907,7 @@ static struct spi_driver max3100_driver = {
 	},
 
 	.probe		= max3100_probe,
-	.remove		= __devexit_p(max3100_remove),
+	.remove		= max3100_remove,
 	.suspend	= max3100_suspend,
 	.resume		= max3100_resume,
 };
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 1ab1d2c..a801f68 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -378,7 +378,7 @@ static void max310x_wait_pll(struct max310x_port *s)
 	}
 }
 
-static int __devinit max310x_update_best_err(unsigned long f, long *besterr)
+static int max310x_update_best_err(unsigned long f, long *besterr)
 {
 	/* Use baudrate 115200 for calculate error */
 	long err = f % (115200 * 16);
@@ -391,7 +391,7 @@ static int __devinit max310x_update_best_err(unsigned long f, long *besterr)
 	return 1;
 }
 
-static int __devinit max310x_set_ref_clk(struct max310x_port *s)
+static int max310x_set_ref_clk(struct max310x_port *s)
 {
 	unsigned int div, clksrc, pllcfg = 0;
 	long besterr = -1;
@@ -995,7 +995,7 @@ static struct max310x_pdata generic_plat_data = {
 	.frequency	= 26000000,
 };
 
-static int __devinit max310x_probe(struct spi_device *spi)
+static int max310x_probe(struct spi_device *spi)
 {
 	struct max310x_port *s;
 	struct device *dev = &spi->dev;
@@ -1178,6 +1178,7 @@ static int __devinit max310x_probe(struct spi_device *spi)
 		s->gpio.set		= max310x_gpio_set;
 		s->gpio.base		= pdata->gpio_base;
 		s->gpio.ngpio		= s->nr_gpio;
+		s->gpio.can_sleep	= 1;
 		if (gpiochip_add(&s->gpio)) {
 			/* Indicate that we should not call gpiochip_remove */
 			s->gpio.base = 0;
@@ -1202,7 +1203,7 @@ err_out:
 	return ret;
 }
 
-static int __devexit max310x_remove(struct spi_device *spi)
+static int max310x_remove(struct spi_device *spi)
 {
 	struct device *dev = &spi->dev;
 	struct max310x_port *s = dev_get_drvdata(dev);
@@ -1249,7 +1250,7 @@ static struct spi_driver max310x_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= max310x_probe,
-	.remove		= __devexit_p(max310x_remove),
+	.remove		= max310x_remove,
 	.suspend	= max310x_suspend,
 	.resume		= max310x_resume,
 	.id_table	= max310x_id_table,
diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c
index 9afca09..fcd56ab 100644
--- a/drivers/tty/serial/mcf.c
+++ b/drivers/tty/serial/mcf.c
@@ -571,7 +571,7 @@ static struct uart_driver mcf_driver = {
 
 /****************************************************************************/
 
-static int __devinit mcf_probe(struct platform_device *pdev)
+static int mcf_probe(struct platform_device *pdev)
 {
 	struct mcf_platform_uart *platp = pdev->dev.platform_data;
 	struct uart_port *port;
@@ -599,7 +599,7 @@ static int __devinit mcf_probe(struct platform_device *pdev)
 
 /****************************************************************************/
 
-static int __devexit mcf_remove(struct platform_device *pdev)
+static int mcf_remove(struct platform_device *pdev)
 {
 	struct uart_port *port;
 	int i;
@@ -617,7 +617,7 @@ static int __devexit mcf_remove(struct platform_device *pdev)
 
 static struct platform_driver mcf_platform_driver = {
 	.probe		= mcf_probe,
-	.remove		= __devexit_p(mcf_remove),
+	.remove		= mcf_remove,
 	.driver		= {
 		.name	= "mcfuart",
 		.owner	= THIS_MODULE,
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c
index c4b50af..2c01344 100644
--- a/drivers/tty/serial/mfd.c
+++ b/drivers/tty/serial/mfd.c
@@ -36,6 +36,7 @@
 #include <linux/serial_mfd.h>
 #include <linux/dma-mapping.h>
 #include <linux/pci.h>
+#include <linux/nmi.h>
 #include <linux/io.h>
 #include <linux/debugfs.h>
 #include <linux/pm_runtime.h>
@@ -1113,6 +1114,8 @@ serial_hsu_console_write(struct console *co, const char *s, unsigned int count)
 	unsigned int ier;
 	int locked = 1;
 
+	touch_nmi_watchdog();
+
 	local_irq_save(flags);
 	if (up->port.sysrq)
 		locked = 0;
@@ -1456,7 +1459,7 @@ static void serial_hsu_remove(struct pci_dev *pdev)
 }
 
 /* First 3 are UART ports, and the 4th is the DMA */
-static const struct pci_device_id pci_ids[] __devinitconst = {
+static const struct pci_device_id pci_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081B) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081C) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081D) },
@@ -1468,7 +1471,7 @@ static struct pci_driver hsu_pci_driver = {
 	.name =		"HSU serial",
 	.id_table =	pci_ids,
 	.probe =	serial_hsu_probe,
-	.remove =	__devexit_p(serial_hsu_remove),
+	.remove =	serial_hsu_remove,
 	.suspend =	serial_hsu_suspend,
 	.resume	=	serial_hsu_resume,
 	.driver = {
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 8cf5770..7c23c4f 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -1308,7 +1308,7 @@ static struct of_device_id mpc52xx_uart_of_match[] = {
 	{},
 };
 
-static int __devinit mpc52xx_uart_of_probe(struct platform_device *op)
+static int mpc52xx_uart_of_probe(struct platform_device *op)
 {
 	int idx = -1;
 	unsigned int uartclk;
diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c
index df2a224..58734d7 100644
--- a/drivers/tty/serial/mrst_max3110.c
+++ b/drivers/tty/serial/mrst_max3110.c
@@ -773,7 +773,7 @@ static int serial_m3110_resume(struct spi_device *spi)
 #define serial_m3110_resume	NULL
 #endif
 
-static int __devinit serial_m3110_probe(struct spi_device *spi)
+static int serial_m3110_probe(struct spi_device *spi)
 {
 	struct uart_max3110 *max;
 	void *buffer;
@@ -855,7 +855,7 @@ err_get_page:
 	return ret;
 }
 
-static int __devexit serial_m3110_remove(struct spi_device *dev)
+static int serial_m3110_remove(struct spi_device *dev)
 {
 	struct uart_max3110 *max = spi_get_drvdata(dev);
 
@@ -879,7 +879,7 @@ static struct spi_driver uart_max3110_driver = {
 			.owner	= THIS_MODULE,
 	},
 	.probe		= serial_m3110_probe,
-	.remove		= __devexit_p(serial_m3110_remove),
+	.remove		= serial_m3110_remove,
 	.suspend	= serial_m3110_suspend,
 	.resume		= serial_m3110_resume,
 };
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 033e0bc..95fd39b 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -917,7 +917,7 @@ static int __init msm_serial_probe(struct platform_device *pdev)
 	return uart_add_one_port(&msm_uart_driver, port);
 }
 
-static int __devexit msm_serial_remove(struct platform_device *pdev)
+static int msm_serial_remove(struct platform_device *pdev)
 {
 	struct msm_port *msm_port = platform_get_drvdata(pdev);
 
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index fca13dc..1fa9228 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -401,7 +401,7 @@ static int msm_hs_request_port(struct uart_port *port)
 	return 0;
 }
 
-static int __devexit msm_hs_remove(struct platform_device *pdev)
+static int msm_hs_remove(struct platform_device *pdev)
 {
 
 	struct msm_hs_port *msm_uport;
@@ -1521,7 +1521,7 @@ err_msm_hs_init_clk:
 }
 
 /* Initialize tx and rx data structures */
-static int __devinit uartdm_init_port(struct uart_port *uport)
+static int uartdm_init_port(struct uart_port *uport)
 {
 	int ret = 0;
 	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
@@ -1614,7 +1614,7 @@ err_tx_command_ptr_ptr:
 	return ret;
 }
 
-static int __devinit msm_hs_probe(struct platform_device *pdev)
+static int msm_hs_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct uart_port *uport;
@@ -1838,7 +1838,7 @@ static const struct dev_pm_ops msm_hs_dev_pm_ops = {
 
 static struct platform_driver msm_serial_hs_platform_driver = {
 	.probe = msm_hs_probe,
-	.remove = __devexit_p(msm_hs_remove),
+	.remove = msm_hs_remove,
 	.driver = {
 		.name = "msm_serial_hs",
 		.owner = THIS_MODULE,
diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c
index 7ea8a26..e2775b6 100644
--- a/drivers/tty/serial/mux.c
+++ b/drivers/tty/serial/mux.c
@@ -520,7 +520,7 @@ static int __init mux_probe(struct parisc_device *dev)
 	return 0;
 }
 
-static int __devexit mux_remove(struct parisc_device *dev)
+static int mux_remove(struct parisc_device *dev)
 {
 	int i, j;
 	int port_count = (long)dev_get_drvdata(&dev->dev);
@@ -571,14 +571,14 @@ static struct parisc_driver builtin_serial_mux_driver = {
 	.name =		"builtin_serial_mux",
 	.id_table =	builtin_mux_tbl,
 	.probe =	mux_probe,
-	.remove =       __devexit_p(mux_remove),
+	.remove =       mux_remove,
 };
 
 static struct parisc_driver serial_mux_driver = {
 	.name =		"serial_mux",
 	.id_table =	mux_tbl,
 	.probe =	mux_probe,
-	.remove =       __devexit_p(mux_remove),
+	.remove =       mux_remove,
 };
 
 /**
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 6db3baa..6db23b0 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -34,6 +34,8 @@
 #include <linux/io.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/of_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/fsl/mxs-dma.h>
 
 #include <asm/cacheflush.h>
 
@@ -71,6 +73,15 @@
 
 #define AUART_CTRL0_SFTRST			(1 << 31)
 #define AUART_CTRL0_CLKGATE			(1 << 30)
+#define AUART_CTRL0_RXTO_ENABLE			(1 << 27)
+#define AUART_CTRL0_RXTIMEOUT(v)		(((v) & 0x7ff) << 16)
+#define AUART_CTRL0_XFER_COUNT(v)		((v) & 0xffff)
+
+#define AUART_CTRL1_XFER_COUNT(v)		((v) & 0xffff)
+
+#define AUART_CTRL2_DMAONERR			(1 << 26)
+#define AUART_CTRL2_TXDMAE			(1 << 25)
+#define AUART_CTRL2_RXDMAE			(1 << 24)
 
 #define AUART_CTRL2_CTSEN			(1 << 15)
 #define AUART_CTRL2_RTSEN			(1 << 14)
@@ -111,29 +122,170 @@
 #define AUART_STAT_BERR				(1 << 18)
 #define AUART_STAT_PERR				(1 << 17)
 #define AUART_STAT_FERR				(1 << 16)
+#define AUART_STAT_RXCOUNT_MASK			0xffff
 
 static struct uart_driver auart_driver;
 
+enum mxs_auart_type {
+	IMX23_AUART,
+	IMX28_AUART,
+};
+
 struct mxs_auart_port {
 	struct uart_port port;
 
-	unsigned int flags;
+#define MXS_AUART_DMA_CONFIG	0x1
+#define MXS_AUART_DMA_ENABLED	0x2
+#define MXS_AUART_DMA_TX_SYNC	2  /* bit 2 */
+#define MXS_AUART_DMA_RX_READY	3  /* bit 3 */
+	unsigned long flags;
 	unsigned int ctrl;
+	enum mxs_auart_type devtype;
 
 	unsigned int irq;
 
 	struct clk *clk;
 	struct device *dev;
+
+	/* for DMA */
+	struct mxs_dma_data dma_data;
+	int dma_channel_rx, dma_channel_tx;
+	int dma_irq_rx, dma_irq_tx;
+	int dma_channel;
+
+	struct scatterlist tx_sgl;
+	struct dma_chan	*tx_dma_chan;
+	void *tx_dma_buf;
+
+	struct scatterlist rx_sgl;
+	struct dma_chan	*rx_dma_chan;
+	void *rx_dma_buf;
+};
+
+static struct platform_device_id mxs_auart_devtype[] = {
+	{ .name = "mxs-auart-imx23", .driver_data = IMX23_AUART },
+	{ .name = "mxs-auart-imx28", .driver_data = IMX28_AUART },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, mxs_auart_devtype);
+
+static struct of_device_id mxs_auart_dt_ids[] = {
+	{
+		.compatible = "fsl,imx28-auart",
+		.data = &mxs_auart_devtype[IMX28_AUART]
+	}, {
+		.compatible = "fsl,imx23-auart",
+		.data = &mxs_auart_devtype[IMX23_AUART]
+	}, { /* sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, mxs_auart_dt_ids);
+
+static inline int is_imx28_auart(struct mxs_auart_port *s)
+{
+	return s->devtype == IMX28_AUART;
+}
+
+static inline bool auart_dma_enabled(struct mxs_auart_port *s)
+{
+	return s->flags & MXS_AUART_DMA_ENABLED;
+}
 
 static void mxs_auart_stop_tx(struct uart_port *u);
 
 #define to_auart_port(u) container_of(u, struct mxs_auart_port, port)
 
-static inline void mxs_auart_tx_chars(struct mxs_auart_port *s)
+static void mxs_auart_tx_chars(struct mxs_auart_port *s);
+
+static void dma_tx_callback(void *param)
 {
+	struct mxs_auart_port *s = param;
 	struct circ_buf *xmit = &s->port.state->xmit;
 
+	dma_unmap_sg(s->dev, &s->tx_sgl, 1, DMA_TO_DEVICE);
+
+	/* clear the bit used to serialize the DMA tx. */
+	clear_bit(MXS_AUART_DMA_TX_SYNC, &s->flags);
+	smp_mb__after_clear_bit();
+
+	/* wake up the possible processes. */
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&s->port);
+
+	mxs_auart_tx_chars(s);
+}
+
+static int mxs_auart_dma_tx(struct mxs_auart_port *s, int size)
+{
+	struct dma_async_tx_descriptor *desc;
+	struct scatterlist *sgl = &s->tx_sgl;
+	struct dma_chan *channel = s->tx_dma_chan;
+	u32 pio;
+
+	/* [1] : send PIO. Note, the first pio word is CTRL1. */
+	pio = AUART_CTRL1_XFER_COUNT(size);
+	desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)&pio,
+					1, DMA_TRANS_NONE, 0);
+	if (!desc) {
+		dev_err(s->dev, "step 1 error\n");
+		return -EINVAL;
+	}
+
+	/* [2] : set DMA buffer. */
+	sg_init_one(sgl, s->tx_dma_buf, size);
+	dma_map_sg(s->dev, sgl, 1, DMA_TO_DEVICE);
+	desc = dmaengine_prep_slave_sg(channel, sgl,
+			1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc) {
+		dev_err(s->dev, "step 2 error\n");
+		return -EINVAL;
+	}
+
+	/* [3] : submit the DMA */
+	desc->callback = dma_tx_callback;
+	desc->callback_param = s;
+	dmaengine_submit(desc);
+	dma_async_issue_pending(channel);
+	return 0;
+}
+
+static void mxs_auart_tx_chars(struct mxs_auart_port *s)
+{
+	struct circ_buf *xmit = &s->port.state->xmit;
+
+	if (auart_dma_enabled(s)) {
+		int i = 0;
+		int size;
+		void *buffer = s->tx_dma_buf;
+
+		if (test_and_set_bit(MXS_AUART_DMA_TX_SYNC, &s->flags))
+			return;
+
+		while (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) {
+			size = min_t(u32, UART_XMIT_SIZE - i,
+				     CIRC_CNT_TO_END(xmit->head,
+						     xmit->tail,
+						     UART_XMIT_SIZE));
+			memcpy(buffer + i, xmit->buf + xmit->tail, size);
+			xmit->tail = (xmit->tail + size) & (UART_XMIT_SIZE - 1);
+
+			i += size;
+			if (i >= UART_XMIT_SIZE)
+				break;
+		}
+
+		if (uart_tx_stopped(&s->port))
+			mxs_auart_stop_tx(&s->port);
+
+		if (i) {
+			mxs_auart_dma_tx(s, i);
+		} else {
+			clear_bit(MXS_AUART_DMA_TX_SYNC, &s->flags);
+			smp_mb__after_clear_bit();
+		}
+		return;
+	}
+
+
 	while (!(readl(s->port.membase + AUART_STAT) &
 		 AUART_STAT_TXFF)) {
 		if (s->port.x_char) {
@@ -287,10 +439,159 @@ static u32 mxs_auart_get_mctrl(struct uart_port *u)
 	return mctrl;
 }
 
+static bool mxs_auart_dma_filter(struct dma_chan *chan, void *param)
+{
+	struct mxs_auart_port *s = param;
+
+	if (!mxs_dma_is_apbx(chan))
+		return false;
+
+	if (s->dma_channel == chan->chan_id) {
+		chan->private = &s->dma_data;
+		return true;
+	}
+	return false;
+}
+
+static int mxs_auart_dma_prep_rx(struct mxs_auart_port *s);
+static void dma_rx_callback(void *arg)
+{
+	struct mxs_auart_port *s = (struct mxs_auart_port *) arg;
+	struct tty_struct *tty = s->port.state->port.tty;
+	int count;
+	u32 stat;
+
+	dma_unmap_sg(s->dev, &s->rx_sgl, 1, DMA_FROM_DEVICE);
+
+	stat = readl(s->port.membase + AUART_STAT);
+	stat &= ~(AUART_STAT_OERR | AUART_STAT_BERR |
+			AUART_STAT_PERR | AUART_STAT_FERR);
+
+	count = stat & AUART_STAT_RXCOUNT_MASK;
+	tty_insert_flip_string(tty, s->rx_dma_buf, count);
+
+	writel(stat, s->port.membase + AUART_STAT);
+	tty_flip_buffer_push(tty);
+
+	/* start the next DMA for RX. */
+	mxs_auart_dma_prep_rx(s);
+}
+
+static int mxs_auart_dma_prep_rx(struct mxs_auart_port *s)
+{
+	struct dma_async_tx_descriptor *desc;
+	struct scatterlist *sgl = &s->rx_sgl;
+	struct dma_chan *channel = s->rx_dma_chan;
+	u32 pio[1];
+
+	/* [1] : send PIO */
+	pio[0] = AUART_CTRL0_RXTO_ENABLE
+		| AUART_CTRL0_RXTIMEOUT(0x80)
+		| AUART_CTRL0_XFER_COUNT(UART_XMIT_SIZE);
+	desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)pio,
+					1, DMA_TRANS_NONE, 0);
+	if (!desc) {
+		dev_err(s->dev, "step 1 error\n");
+		return -EINVAL;
+	}
+
+	/* [2] : send DMA request */
+	sg_init_one(sgl, s->rx_dma_buf, UART_XMIT_SIZE);
+	dma_map_sg(s->dev, sgl, 1, DMA_FROM_DEVICE);
+	desc = dmaengine_prep_slave_sg(channel, sgl, 1, DMA_DEV_TO_MEM,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc) {
+		dev_err(s->dev, "step 2 error\n");
+		return -1;
+	}
+
+	/* [3] : submit the DMA, but do not issue it. */
+	desc->callback = dma_rx_callback;
+	desc->callback_param = s;
+	dmaengine_submit(desc);
+	dma_async_issue_pending(channel);
+	return 0;
+}
+
+static void mxs_auart_dma_exit_channel(struct mxs_auart_port *s)
+{
+	if (s->tx_dma_chan) {
+		dma_release_channel(s->tx_dma_chan);
+		s->tx_dma_chan = NULL;
+	}
+	if (s->rx_dma_chan) {
+		dma_release_channel(s->rx_dma_chan);
+		s->rx_dma_chan = NULL;
+	}
+
+	kfree(s->tx_dma_buf);
+	kfree(s->rx_dma_buf);
+	s->tx_dma_buf = NULL;
+	s->rx_dma_buf = NULL;
+}
+
+static void mxs_auart_dma_exit(struct mxs_auart_port *s)
+{
+
+	writel(AUART_CTRL2_TXDMAE | AUART_CTRL2_RXDMAE | AUART_CTRL2_DMAONERR,
+		s->port.membase + AUART_CTRL2_CLR);
+
+	mxs_auart_dma_exit_channel(s);
+	s->flags &= ~MXS_AUART_DMA_ENABLED;
+	clear_bit(MXS_AUART_DMA_TX_SYNC, &s->flags);
+	clear_bit(MXS_AUART_DMA_RX_READY, &s->flags);
+}
+
+static int mxs_auart_dma_init(struct mxs_auart_port *s)
+{
+	dma_cap_mask_t mask;
+
+	if (auart_dma_enabled(s))
+		return 0;
+
+	/* We do not get the right DMA channels. */
+	if (s->dma_channel_rx == -1 || s->dma_channel_rx == -1)
+		return -EINVAL;
+
+	/* init for RX */
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	s->dma_channel = s->dma_channel_rx;
+	s->dma_data.chan_irq = s->dma_irq_rx;
+	s->rx_dma_chan = dma_request_channel(mask, mxs_auart_dma_filter, s);
+	if (!s->rx_dma_chan)
+		goto err_out;
+	s->rx_dma_buf = kzalloc(UART_XMIT_SIZE, GFP_KERNEL | GFP_DMA);
+	if (!s->rx_dma_buf)
+		goto err_out;
+
+	/* init for TX */
+	s->dma_channel = s->dma_channel_tx;
+	s->dma_data.chan_irq = s->dma_irq_tx;
+	s->tx_dma_chan = dma_request_channel(mask, mxs_auart_dma_filter, s);
+	if (!s->tx_dma_chan)
+		goto err_out;
+	s->tx_dma_buf = kzalloc(UART_XMIT_SIZE, GFP_KERNEL | GFP_DMA);
+	if (!s->tx_dma_buf)
+		goto err_out;
+
+	/* set the flags */
+	s->flags |= MXS_AUART_DMA_ENABLED;
+	dev_dbg(s->dev, "enabled the DMA support.");
+
+	return 0;
+
+err_out:
+	mxs_auart_dma_exit_channel(s);
+	return -EINVAL;
+
+}
+
 static void mxs_auart_settermios(struct uart_port *u,
 				 struct ktermios *termios,
 				 struct ktermios *old)
 {
+	struct mxs_auart_port *s = to_auart_port(u);
 	u32 bm, ctrl, ctrl2, div;
 	unsigned int cflag, baud;
 
@@ -362,10 +663,23 @@ static void mxs_auart_settermios(struct uart_port *u,
 		ctrl |= AUART_LINECTRL_STP2;
 
 	/* figure out the hardware flow control settings */
-	if (cflag & CRTSCTS)
+	if (cflag & CRTSCTS) {
+		/*
+		 * The DMA has a bug(see errata:2836) in mx23.
+		 * So we can not implement the DMA for auart in mx23,
+		 * we can only implement the DMA support for auart
+		 * in mx28.
+		 */
+		if (is_imx28_auart(s) && (s->flags & MXS_AUART_DMA_CONFIG)) {
+			if (!mxs_auart_dma_init(s))
+				/* enable DMA tranfer */
+				ctrl2 |= AUART_CTRL2_TXDMAE | AUART_CTRL2_RXDMAE
+				       | AUART_CTRL2_DMAONERR;
+		}
 		ctrl2 |= AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN;
-	else
+	} else {
 		ctrl2 &= ~(AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN);
+	}
 
 	/* set baud rate */
 	baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk);
@@ -377,6 +691,19 @@ static void mxs_auart_settermios(struct uart_port *u,
 	writel(ctrl2, u->membase + AUART_CTRL2);
 
 	uart_update_timeout(u, termios->c_cflag, baud);
+
+	/* prepare for the DMA RX. */
+	if (auart_dma_enabled(s) &&
+		!test_and_set_bit(MXS_AUART_DMA_RX_READY, &s->flags)) {
+		if (!mxs_auart_dma_prep_rx(s)) {
+			/* Disable the normal RX interrupt. */
+			writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN,
+					u->membase + AUART_INTR_CLR);
+		} else {
+			mxs_auart_dma_exit(s);
+			dev_err(s->dev, "We can not start up the DMA.\n");
+		}
+	}
 }
 
 static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
@@ -395,7 +722,8 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
 	}
 
 	if (istat & (AUART_INTR_RTIS | AUART_INTR_RXIS)) {
-		mxs_auart_rx_chars(s);
+		if (!auart_dma_enabled(s))
+			mxs_auart_rx_chars(s);
 		istat &= ~(AUART_INTR_RTIS | AUART_INTR_RXIS);
 	}
 
@@ -455,6 +783,9 @@ static void mxs_auart_shutdown(struct uart_port *u)
 {
 	struct mxs_auart_port *s = to_auart_port(u);
 
+	if (auart_dma_enabled(s))
+		mxs_auart_dma_exit(s);
+
 	writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
 
 	writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
@@ -688,6 +1019,7 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
 		struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
+	u32 dma_channel[2];
 	int ret;
 
 	if (!np)
@@ -701,11 +1033,27 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
 	}
 	s->port.line = ret;
 
+	s->dma_irq_rx = platform_get_irq(pdev, 1);
+	s->dma_irq_tx = platform_get_irq(pdev, 2);
+
+	ret = of_property_read_u32_array(np, "fsl,auart-dma-channel",
+					dma_channel, 2);
+	if (ret == 0) {
+		s->dma_channel_rx = dma_channel[0];
+		s->dma_channel_tx = dma_channel[1];
+
+		s->flags |= MXS_AUART_DMA_CONFIG;
+	} else {
+		s->dma_channel_rx = -1;
+		s->dma_channel_tx = -1;
+	}
 	return 0;
 }
 
-static int __devinit mxs_auart_probe(struct platform_device *pdev)
+static int mxs_auart_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *of_id =
+			of_match_device(mxs_auart_dt_ids, &pdev->dev);
 	struct mxs_auart_port *s;
 	u32 version;
 	int ret = 0;
@@ -730,6 +1078,11 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
 		goto out_free;
 	}
 
+	if (of_id) {
+		pdev->id_entry = of_id->data;
+		s->devtype = pdev->id_entry->driver_data;
+	}
+
 	s->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(s->clk)) {
 		ret = PTR_ERR(s->clk);
@@ -751,7 +1104,6 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
 	s->port.type = PORT_IMX;
 	s->port.dev = s->dev = get_device(&pdev->dev);
 
-	s->flags = 0;
 	s->ctrl = 0;
 
 	s->irq = platform_get_irq(pdev, 0);
@@ -789,7 +1141,7 @@ out:
 	return ret;
 }
 
-static int __devexit mxs_auart_remove(struct platform_device *pdev)
+static int mxs_auart_remove(struct platform_device *pdev)
 {
 	struct mxs_auart_port *s = platform_get_drvdata(pdev);
 
@@ -805,15 +1157,9 @@ static int __devexit mxs_auart_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static struct of_device_id mxs_auart_dt_ids[] = {
-	{ .compatible = "fsl,imx23-auart", },
-	{ /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, mxs_auart_dt_ids);
-
 static struct platform_driver mxs_auart_driver = {
 	.probe = mxs_auart_probe,
-	.remove = __devexit_p(mxs_auart_remove),
+	.remove = mxs_auart_remove,
 	.driver = {
 		.name = "mxs-auart",
 		.owner = THIS_MODULE,
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index df443b9..e7cae1c 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -21,8 +21,10 @@
 #include <linux/of_serial.h>
 #include <linux/of_platform.h>
 #include <linux/nwpserial.h>
+#include <linux/clk.h>
 
 struct of_serial_info {
+	struct clk *clk;
 	int type;
 	int line;
 };
@@ -50,8 +52,9 @@ EXPORT_SYMBOL_GPL(tegra_serial_handle_break);
 /*
  * Fill a struct uart_port for a given device node
  */
-static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
-					int type, struct uart_port *port)
+static int of_platform_serial_setup(struct platform_device *ofdev,
+			int type, struct uart_port *port,
+			struct of_serial_info *info)
 {
 	struct resource resource;
 	struct device_node *np = ofdev->dev.of_node;
@@ -60,8 +63,17 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
 
 	memset(port, 0, sizeof *port);
 	if (of_property_read_u32(np, "clock-frequency", &clk)) {
-		dev_warn(&ofdev->dev, "no clock-frequency property set\n");
-		return -ENODEV;
+
+		/* Get clk rate through clk driver if present */
+		info->clk = clk_get(&ofdev->dev, NULL);
+		if (IS_ERR(info->clk)) {
+			dev_warn(&ofdev->dev,
+				"clk or clock-frequency not defined\n");
+			return PTR_ERR(info->clk);
+		}
+
+		clk_prepare_enable(info->clk);
+		clk = clk_get_rate(info->clk);
 	}
 	/* If current-speed was set, then try not to change it. */
 	if (of_property_read_u32(np, "current-speed", &spd) == 0)
@@ -70,7 +82,7 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
 	ret = of_address_to_resource(np, 0, &resource);
 	if (ret) {
 		dev_warn(&ofdev->dev, "invalid address\n");
-		return ret;
+		goto out;
 	}
 
 	spin_lock_init(&port->lock);
@@ -97,7 +109,8 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
 		default:
 			dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n",
 				 prop);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto out;
 		}
 	}
 
@@ -115,13 +128,17 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
 		port->handle_break = tegra_serial_handle_break;
 
 	return 0;
+out:
+	if (info->clk)
+		clk_disable_unprepare(info->clk);
+	return ret;
 }
 
 /*
  * Try to register a serial port
  */
 static struct of_device_id of_platform_serial_table[];
-static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
+static int of_platform_serial_probe(struct platform_device *ofdev)
 {
 	const struct of_device_id *match;
 	struct of_serial_info *info;
@@ -141,7 +158,7 @@ static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
 		return -ENOMEM;
 
 	port_type = (unsigned long)match->data;
-	ret = of_platform_serial_setup(ofdev, port_type, &port);
+	ret = of_platform_serial_setup(ofdev, port_type, &port, info);
 	if (ret)
 		goto out;
 
@@ -204,6 +221,9 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
 		/* need to add code for these */
 		break;
 	}
+
+	if (info->clk)
+		clk_disable_unprepare(info->clk);
 	kfree(info);
 	return 0;
 }
@@ -211,7 +231,7 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
 /*
  * A few common types, add more as needed.
  */
-static struct of_device_id __devinitdata of_platform_serial_table[] = {
+static struct of_device_id of_platform_serial_table[] = {
 	{ .compatible = "ns8250",   .data = (void *)PORT_8250, },
 	{ .compatible = "ns16450",  .data = (void *)PORT_16450, },
 	{ .compatible = "ns16550a", .data = (void *)PORT_16550A, },
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 6d3d26a..23f797e 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -44,6 +44,8 @@
 
 #include <plat/omap-serial.h>
 
+#define OMAP_MAX_HSUART_PORTS	6
+
 #define UART_BUILD_REVISION(x, y)	(((x) << 8) | (y))
 
 #define OMAP_UART_REV_42 0x0402
@@ -51,10 +53,14 @@
 #define OMAP_UART_REV_52 0x0502
 #define OMAP_UART_REV_63 0x0603
 
+#define UART_ERRATA_i202_MDR1_ACCESS	BIT(0)
+#define UART_ERRATA_i291_DMA_FORCEIDLE	BIT(1)
+
 #define DEFAULT_CLK_SPEED 48000000 /* 48Mhz*/
 
 /* SCR register bitmasks */
 #define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK		(1 << 7)
+#define OMAP_UART_SCR_TX_EMPTY			(1 << 3)
 
 /* FCR register bitmasks */
 #define OMAP_UART_FCR_RX_FIFO_TRIG_MASK			(0x3 << 6)
@@ -71,6 +77,52 @@
 #define OMAP_UART_MVR_MAJ_SHIFT		8
 #define OMAP_UART_MVR_MIN_MASK		0x3f
 
+#define OMAP_UART_DMA_CH_FREE	-1
+
+#define MSR_SAVE_FLAGS		UART_MSR_ANY_DELTA
+#define OMAP_MODE13X_SPEED	230400
+
+/* WER = 0x7F
+ * Enable module level wakeup in WER reg
+ */
+#define OMAP_UART_WER_MOD_WKUP	0X7F
+
+/* Enable XON/XOFF flow control on output */
+#define OMAP_UART_SW_TX		0x08
+
+/* Enable XON/XOFF flow control on input */
+#define OMAP_UART_SW_RX		0x02
+
+#define OMAP_UART_SW_CLR	0xF0
+
+#define OMAP_UART_TCR_TRIG	0x0F
+
+struct uart_omap_dma {
+	u8			uart_dma_tx;
+	u8			uart_dma_rx;
+	int			rx_dma_channel;
+	int			tx_dma_channel;
+	dma_addr_t		rx_buf_dma_phys;
+	dma_addr_t		tx_buf_dma_phys;
+	unsigned int		uart_base;
+	/*
+	 * Buffer for rx dma.It is not required for tx because the buffer
+	 * comes from port structure.
+	 */
+	unsigned char		*rx_buf;
+	unsigned int		prev_rx_dma_pos;
+	int			tx_buf_size;
+	int			tx_dma_used;
+	int			rx_dma_used;
+	spinlock_t		tx_lock;
+	spinlock_t		rx_lock;
+	/* timer to poll activity on rx dma */
+	struct timer_list	rx_timer;
+	unsigned int		rx_buf_size;
+	unsigned int		rx_poll_rate;
+	unsigned int		rx_timeout;
+};
+
 struct uart_omap_port {
 	struct uart_port	port;
 	struct uart_omap_dma	uart_dma;
@@ -96,10 +148,9 @@ struct uart_omap_port {
 	unsigned char		msr_saved_flags;
 	char			name[20];
 	unsigned long		port_activity;
-	u32			context_loss_cnt;
+	int			context_loss_cnt;
 	u32			errata;
 	u8			wakeups_enabled;
-	unsigned int		irq_pending:1;
 
 	int			DTR_gpio;
 	int			DTR_inverted;
@@ -303,6 +354,34 @@ static void serial_omap_start_tx(struct uart_port *port)
 	pm_runtime_put_autosuspend(up->dev);
 }
 
+static void serial_omap_throttle(struct uart_port *port)
+{
+	struct uart_omap_port *up = to_uart_omap_port(port);
+	unsigned long flags;
+
+	pm_runtime_get_sync(up->dev);
+	spin_lock_irqsave(&up->port.lock, flags);
+	up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
+	serial_out(up, UART_IER, up->ier);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+	pm_runtime_mark_last_busy(up->dev);
+	pm_runtime_put_autosuspend(up->dev);
+}
+
+static void serial_omap_unthrottle(struct uart_port *port)
+{
+	struct uart_omap_port *up = to_uart_omap_port(port);
+	unsigned long flags;
+
+	pm_runtime_get_sync(up->dev);
+	spin_lock_irqsave(&up->port.lock, flags);
+	up->ier |= UART_IER_RLSI | UART_IER_RDI;
+	serial_out(up, UART_IER, up->ier);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+	pm_runtime_mark_last_busy(up->dev);
+	pm_runtime_put_autosuspend(up->dev);
+}
+
 static unsigned int check_modem_status(struct uart_omap_port *up)
 {
 	unsigned int status;
@@ -504,7 +583,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port)
 static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 	struct uart_omap_port *up = to_uart_omap_port(port);
-	unsigned char mcr = 0;
+	unsigned char mcr = 0, old_mcr;
 
 	dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line);
 	if (mctrl & TIOCM_RTS)
@@ -519,8 +598,10 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
 		mcr |= UART_MCR_LOOP;
 
 	pm_runtime_get_sync(up->dev);
-	up->mcr = serial_in(up, UART_MCR);
-	up->mcr |= mcr;
+	old_mcr = serial_in(up, UART_MCR);
+	old_mcr &= ~(UART_MCR_LOOP | UART_MCR_OUT2 | UART_MCR_OUT1 |
+		     UART_MCR_DTR | UART_MCR_RTS);
+	up->mcr = old_mcr | mcr;
 	serial_out(up, UART_MCR, up->mcr);
 	pm_runtime_mark_last_busy(up->dev);
 	pm_runtime_put_autosuspend(up->dev);
@@ -654,65 +735,6 @@ static void serial_omap_shutdown(struct uart_port *port)
 	free_irq(up->port.irq, up);
 }
 
-static inline void
-serial_omap_configure_xonxoff
-		(struct uart_omap_port *up, struct ktermios *termios)
-{
-	up->lcr = serial_in(up, UART_LCR);
-	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-	up->efr = serial_in(up, UART_EFR);
-	serial_out(up, UART_EFR, up->efr & ~UART_EFR_ECB);
-
-	serial_out(up, UART_XON1, termios->c_cc[VSTART]);
-	serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]);
-
-	/* clear SW control mode bits */
-	up->efr &= OMAP_UART_SW_CLR;
-
-	/*
-	 * IXON Flag:
-	 * Enable XON/XOFF flow control on output.
-	 * Transmit XON1, XOFF1
-	 */
-	if (termios->c_iflag & IXON)
-		up->efr |= OMAP_UART_SW_TX;
-
-	/*
-	 * IXOFF Flag:
-	 * Enable XON/XOFF flow control on input.
-	 * Receiver compares XON1, XOFF1.
-	 */
-	if (termios->c_iflag & IXOFF)
-		up->efr |= OMAP_UART_SW_RX;
-
-	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
-	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-
-	up->mcr = serial_in(up, UART_MCR);
-
-	/*
-	 * IXANY Flag:
-	 * Enable any character to restart output.
-	 * Operation resumes after receiving any
-	 * character after recognition of the XOFF character
-	 */
-	if (termios->c_iflag & IXANY)
-		up->mcr |= UART_MCR_XONANY;
-
-	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
-	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-	serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
-	/* Enable special char function UARTi.EFR_REG[5] and
-	 * load the new software flow control mode IXON or IXOFF
-	 * and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
-	 */
-	serial_out(up, UART_EFR, up->efr | UART_EFR_SCD);
-	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-
-	serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
-	serial_out(up, UART_LCR, up->lcr);
-}
-
 static void serial_omap_uart_qos_work(struct work_struct *work)
 {
 	struct uart_omap_port *up = container_of(work, struct uart_omap_port,
@@ -730,7 +752,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 {
 	struct uart_omap_port *up = to_uart_omap_port(port);
 	unsigned char cval = 0;
-	unsigned char efr = 0;
 	unsigned long flags = 0;
 	unsigned int baud, quot;
 
@@ -840,11 +861,12 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 
-	up->efr = serial_in(up, UART_EFR);
+	up->efr = serial_in(up, UART_EFR) & ~UART_EFR_ECB;
+	up->efr &= ~UART_EFR_SCD;
 	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
 
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-	up->mcr = serial_in(up, UART_MCR);
+	up->mcr = serial_in(up, UART_MCR) & ~UART_MCR_TCRTLR;
 	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
 	/* FIFO ENABLE, DMA MODE */
 
@@ -863,9 +885,12 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	serial_out(up, UART_OMAP_SCR, up->scr);
 
-	serial_out(up, UART_EFR, up->efr);
+	/* Reset UART_MCR_TCRTLR: this must be done with the EFR_ECB bit set */
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
 	serial_out(up, UART_MCR, up->mcr);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+	serial_out(up, UART_EFR, up->efr);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
 
 	/* Protocol, Baud Rate, and Interrupt Settings */
 
@@ -875,8 +900,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 		serial_out(up, UART_OMAP_MDR1, up->mdr1);
 
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-
-	up->efr = serial_in(up, UART_EFR);
 	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
 
 	serial_out(up, UART_LCR, 0);
@@ -903,29 +926,68 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 	else
 		serial_out(up, UART_OMAP_MDR1, up->mdr1);
 
-	/* Hardware Flow Control Configuration */
+	/* Configure flow control */
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+	/* XON1/XOFF1 accessible mode B, TCRTLR=0, ECB=0 */
+	serial_out(up, UART_XON1, termios->c_cc[VSTART]);
+	serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]);
+
+	/* Enable access to TCR/TLR */
+	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
 
-	if (termios->c_cflag & CRTSCTS) {
-		efr |= (UART_EFR_CTS | UART_EFR_RTS);
-		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+	serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
 
-		up->mcr = serial_in(up, UART_MCR);
-		serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
+	if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) {
+		/* Enable AUTORTS and AUTOCTS */
+		up->efr |= UART_EFR_CTS | UART_EFR_RTS;
 
-		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-		up->efr = serial_in(up, UART_EFR);
-		serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+		/* Ensure MCR RTS is asserted */
+		up->mcr |= UART_MCR_RTS;
+	} else {
+		/* Disable AUTORTS and AUTOCTS */
+		up->efr &= ~(UART_EFR_CTS | UART_EFR_RTS);
+	}
+
+	if (up->port.flags & UPF_SOFT_FLOW) {
+		/* clear SW control mode bits */
+		up->efr &= OMAP_UART_SW_CLR;
+
+		/*
+		 * IXON Flag:
+		 * Enable XON/XOFF flow control on input.
+		 * Receiver compares XON1, XOFF1.
+		 */
+		if (termios->c_iflag & IXON)
+			up->efr |= OMAP_UART_SW_RX;
 
-		serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
-		serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */
-		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-		serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS);
-		serial_out(up, UART_LCR, cval);
+		/*
+		 * IXOFF Flag:
+		 * Enable XON/XOFF flow control on output.
+		 * Transmit XON1, XOFF1
+		 */
+		if (termios->c_iflag & IXOFF)
+			up->efr |= OMAP_UART_SW_TX;
+
+		/*
+		 * IXANY Flag:
+		 * Enable any character to restart output.
+		 * Operation resumes after receiving any
+		 * character after recognition of the XOFF character
+		 */
+		if (termios->c_iflag & IXANY)
+			up->mcr |= UART_MCR_XONANY;
+		else
+			up->mcr &= ~UART_MCR_XONANY;
 	}
+	serial_out(up, UART_MCR, up->mcr);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+	serial_out(up, UART_EFR, up->efr);
+	serial_out(up, UART_LCR, up->lcr);
 
 	serial_omap_set_mctrl(&up->port, up->port.mctrl);
-	/* Software Flow Control Configuration */
-	serial_omap_configure_xonxoff(up, termios);
 
 	spin_unlock_irqrestore(&up->port.lock, flags);
 	pm_runtime_mark_last_busy(up->dev);
@@ -991,6 +1053,7 @@ static void serial_omap_config_port(struct uart_port *port, int flags)
 	dev_dbg(up->port.dev, "serial_omap_config_port+%d\n",
 							up->port.line);
 	up->port.type = PORT_OMAP;
+	up->port.flags |= UPF_SOFT_FLOW | UPF_HARD_FLOW;
 }
 
 static int
@@ -1081,7 +1144,7 @@ out:
 
 #ifdef CONFIG_SERIAL_OMAP_CONSOLE
 
-static struct uart_omap_port *serial_omap_console_ports[4];
+static struct uart_omap_port *serial_omap_console_ports[OMAP_MAX_HSUART_PORTS];
 
 static struct uart_driver serial_omap_reg;
 
@@ -1194,6 +1257,8 @@ static struct uart_ops serial_omap_pops = {
 	.get_mctrl	= serial_omap_get_mctrl,
 	.stop_tx	= serial_omap_stop_tx,
 	.start_tx	= serial_omap_start_tx,
+	.throttle	= serial_omap_throttle,
+	.unthrottle	= serial_omap_unthrottle,
 	.stop_rx	= serial_omap_stop_rx,
 	.enable_ms	= serial_omap_enable_ms,
 	.break_ctl	= serial_omap_break_ctl,
@@ -1242,7 +1307,7 @@ static int serial_omap_resume(struct device *dev)
 }
 #endif
 
-static void __devinit omap_serial_fill_features_erratas(struct uart_omap_port *up)
+static void omap_serial_fill_features_erratas(struct uart_omap_port *up)
 {
 	u32 mvr, scheme;
 	u16 revision, major, minor;
@@ -1295,7 +1360,7 @@ static void __devinit omap_serial_fill_features_erratas(struct uart_omap_port *u
 	}
 }
 
-static __devinit struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
+static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
 {
 	struct omap_uart_port_info *omap_up_info;
 
@@ -1308,7 +1373,7 @@ static __devinit struct omap_uart_port_info *of_get_uart_port_info(struct device
 	return omap_up_info;
 }
 
-static int __devinit serial_omap_probe(struct platform_device *pdev)
+static int serial_omap_probe(struct platform_device *pdev)
 {
 	struct uart_omap_port	*up;
 	struct resource		*mem, *irq;
@@ -1445,7 +1510,7 @@ err_port_line:
 	return ret;
 }
 
-static int __devexit serial_omap_remove(struct platform_device *dev)
+static int serial_omap_remove(struct platform_device *dev)
 {
 	struct uart_omap_port *up = platform_get_drvdata(dev);
 
@@ -1556,11 +1621,15 @@ static int serial_omap_runtime_resume(struct device *dev)
 {
 	struct uart_omap_port *up = dev_get_drvdata(dev);
 
-	u32 loss_cnt = serial_omap_get_context_loss_count(up);
+	int loss_cnt = serial_omap_get_context_loss_count(up);
 
-	if (up->context_loss_cnt != loss_cnt)
+	if (loss_cnt < 0) {
+		dev_err(dev, "serial_omap_get_context_loss_count failed : %d\n",
+			loss_cnt);
 		serial_omap_restore_context(up);
-
+	} else if (up->context_loss_cnt != loss_cnt) {
+		serial_omap_restore_context(up);
+	}
 	up->latency = up->calc_latency;
 	schedule_work(&up->qos_work);
 
@@ -1586,7 +1655,7 @@ MODULE_DEVICE_TABLE(of, omap_serial_of_match);
 
 static struct platform_driver serial_omap_driver = {
 	.probe          = serial_omap_probe,
-	.remove         = __devexit_p(serial_omap_remove),
+	.remove         = serial_omap_remove,
 	.driver		= {
 		.name	= DRIVER_NAME,
 		.pm	= &serial_omap_dev_pm_ops,
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 4cd6c23..8318925 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -1839,7 +1839,7 @@ static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = {
 	{0,},
 };
 
-static int __devinit pch_uart_pci_probe(struct pci_dev *pdev,
+static int pch_uart_pci_probe(struct pci_dev *pdev,
 					const struct pci_device_id *id)
 {
 	int ret;
@@ -1869,7 +1869,7 @@ static struct pci_driver pch_uart_pci_driver = {
 	.name = "pch_uart",
 	.id_table = pch_uart_pci_id,
 	.probe = pch_uart_pci_probe,
-	.remove = __devexit_p(pch_uart_pci_remove),
+	.remove = pch_uart_pci_remove,
 	.suspend = pch_uart_pci_suspend,
 	.resume = pch_uart_pci_resume,
 };
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 9033fc6..2764828 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -705,6 +705,57 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
 	clk_disable_unprepare(up->clk);
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Console polling routines for writing and reading from the uart while
+ * in an interrupt or debug context.
+ */
+
+static int serial_pxa_get_poll_char(struct uart_port *port)
+{
+	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+	unsigned char lsr = serial_in(up, UART_LSR);
+
+	while (!(lsr & UART_LSR_DR))
+		lsr = serial_in(up, UART_LSR);
+
+	return serial_in(up, UART_RX);
+}
+
+
+static void serial_pxa_put_poll_char(struct uart_port *port,
+			 unsigned char c)
+{
+	unsigned int ier;
+	struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+
+	/*
+	 *	First save the IER then disable the interrupts
+	 */
+	ier = serial_in(up, UART_IER);
+	serial_out(up, UART_IER, UART_IER_UUE);
+
+	wait_for_xmitr(up);
+	/*
+	 *	Send the character out.
+	 *	If a LF, also do CR...
+	 */
+	serial_out(up, UART_TX, c);
+	if (c == 10) {
+		wait_for_xmitr(up);
+		serial_out(up, UART_TX, 13);
+	}
+
+	/*
+	 *	Finally, wait for transmitter to become empty
+	 *	and restore the IER
+	 */
+	wait_for_xmitr(up);
+	serial_out(up, UART_IER, ier);
+}
+
+#endif /* CONFIG_CONSOLE_POLL */
+
 static int __init
 serial_pxa_console_setup(struct console *co, char *options)
 {
@@ -759,6 +810,10 @@ struct uart_ops serial_pxa_pops = {
 	.request_port	= serial_pxa_request_port,
 	.config_port	= serial_pxa_config_port,
 	.verify_port	= serial_pxa_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_get_char = serial_pxa_get_poll_char,
+	.poll_put_char = serial_pxa_put_poll_char,
+#endif
 };
 
 static struct uart_driver serial_pxa_reg = {
diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
index 2ca5959..5d4b9b4 100644
--- a/drivers/tty/serial/sa1100.c
+++ b/drivers/tty/serial/sa1100.c
@@ -29,6 +29,7 @@
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
+#include <linux/platform_data/sa11x0-serial.h>
 #include <linux/platform_device.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
@@ -39,7 +40,6 @@
 #include <asm/irq.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
-#include <asm/mach/serial_sa1100.h>
 
 /* We've been assigned a range on the "Low-density serial ports" major */
 #define SERIAL_SA1100_MAJOR	204
@@ -637,7 +637,7 @@ static void __init sa1100_init_ports(void)
 	PPSR |= PPC_TXD1 | PPC_TXD3;
 }
 
-void __devinit sa1100_register_uart_fns(struct sa1100_port_fns *fns)
+void sa1100_register_uart_fns(struct sa1100_port_fns *fns)
 {
 	if (fns->get_mctrl)
 		sa1100_pops.get_mctrl = fns->get_mctrl;
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 7f04717..12e5249 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -223,8 +223,11 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id)
 	struct uart_port *port = &ourport->port;
 	struct tty_struct *tty = port->state->port.tty;
 	unsigned int ufcon, ch, flag, ufstat, uerstat;
+	unsigned long flags;
 	int max_count = 64;
 
+	spin_lock_irqsave(&port->lock, flags);
+
 	while (max_count-- > 0) {
 		ufcon = rd_regl(port, S3C2410_UFCON);
 		ufstat = rd_regl(port, S3C2410_UFSTAT);
@@ -299,6 +302,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id)
 	tty_flip_buffer_push(tty);
 
  out:
+	spin_unlock_irqrestore(&port->lock, flags);
 	return IRQ_HANDLED;
 }
 
@@ -307,8 +311,11 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
 	struct s3c24xx_uart_port *ourport = id;
 	struct uart_port *port = &ourport->port;
 	struct circ_buf *xmit = &port->state->xmit;
+	unsigned long flags;
 	int count = 256;
 
+	spin_lock_irqsave(&port->lock, flags);
+
 	if (port->x_char) {
 		wr_regb(port, S3C2410_UTXH, port->x_char);
 		port->icount.tx++;
@@ -336,13 +343,17 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
 		port->icount.tx++;
 	}
 
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
+		spin_unlock(&port->lock);
 		uart_write_wakeup(port);
+		spin_lock(&port->lock);
+	}
 
 	if (uart_circ_empty(xmit))
 		s3c24xx_serial_stop_tx(port);
 
  out:
+	spin_unlock_irqrestore(&port->lock, flags);
 	return IRQ_HANDLED;
 }
 
@@ -352,10 +363,8 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
 	struct s3c24xx_uart_port *ourport = id;
 	struct uart_port *port = &ourport->port;
 	unsigned int pend = rd_regl(port, S3C64XX_UINTP);
-	unsigned long flags;
 	irqreturn_t ret = IRQ_HANDLED;
 
-	spin_lock_irqsave(&port->lock, flags);
 	if (pend & S3C64XX_UINTM_RXD_MSK) {
 		ret = s3c24xx_serial_rx_chars(irq, id);
 		wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK);
@@ -364,7 +373,6 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
 		ret = s3c24xx_serial_tx_chars(irq, id);
 		wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK);
 	}
-	spin_unlock_irqrestore(&port->lock, flags);
 	return ret;
 }
 
@@ -530,16 +538,16 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
 	switch (level) {
 	case 3:
 		if (!IS_ERR(ourport->baudclk))
-			clk_disable(ourport->baudclk);
+			clk_disable_unprepare(ourport->baudclk);
 
-		clk_disable(ourport->clk);
+		clk_disable_unprepare(ourport->clk);
 		break;
 
 	case 0:
-		clk_enable(ourport->clk);
+		clk_prepare_enable(ourport->clk);
 
 		if (!IS_ERR(ourport->baudclk))
-			clk_enable(ourport->baudclk);
+			clk_prepare_enable(ourport->baudclk);
 
 		break;
 	default:
@@ -713,11 +721,11 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
 		s3c24xx_serial_setsource(port, clk_sel);
 
 		if (!IS_ERR(ourport->baudclk)) {
-			clk_disable(ourport->baudclk);
+			clk_disable_unprepare(ourport->baudclk);
 			ourport->baudclk = ERR_PTR(-EINVAL);
 		}
 
-		clk_enable(clk);
+		clk_prepare_enable(clk);
 
 		ourport->baudclk = clk;
 		ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
@@ -1256,7 +1264,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit s3c24xx_serial_remove(struct platform_device *dev)
+static int s3c24xx_serial_remove(struct platform_device *dev)
 {
 	struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
 
@@ -1287,9 +1295,9 @@ static int s3c24xx_serial_resume(struct device *dev)
 	struct s3c24xx_uart_port *ourport = to_ourport(port);
 
 	if (port) {
-		clk_enable(ourport->clk);
+		clk_prepare_enable(ourport->clk);
 		s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
-		clk_disable(ourport->clk);
+		clk_disable_unprepare(ourport->clk);
 
 		uart_resume_port(&s3c24xx_uart_drv, port);
 	}
@@ -1646,7 +1654,8 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
 #endif
 
 #if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212) || \
-	defined(CONFIG_SOC_EXYNOS4412) || defined(CONFIG_SOC_EXYNOS5250)
+	defined(CONFIG_SOC_EXYNOS4412) || defined(CONFIG_SOC_EXYNOS5250) || \
+	defined(CONFIG_SOC_EXYNOS5440)
 static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
 	.info = &(struct s3c24xx_uart_info) {
 		.name		= "Samsung Exynos4 UART",
@@ -1701,6 +1710,16 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_serial_driver_ids);
 
 #ifdef CONFIG_OF
 static const struct of_device_id s3c24xx_uart_dt_match[] = {
+	{ .compatible = "samsung,s3c2410-uart",
+		.data = (void *)S3C2410_SERIAL_DRV_DATA },
+	{ .compatible = "samsung,s3c2412-uart",
+		.data = (void *)S3C2412_SERIAL_DRV_DATA },
+	{ .compatible = "samsung,s3c2440-uart",
+		.data = (void *)S3C2440_SERIAL_DRV_DATA },
+	{ .compatible = "samsung,s3c6400-uart",
+		.data = (void *)S3C6400_SERIAL_DRV_DATA },
+	{ .compatible = "samsung,s5pv210-uart",
+		.data = (void *)S5PV210_SERIAL_DRV_DATA },
 	{ .compatible = "samsung,exynos4210-uart",
 		.data = (void *)EXYNOS4210_SERIAL_DRV_DATA },
 	{},
@@ -1712,7 +1731,7 @@ MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
 
 static struct platform_driver samsung_serial_driver = {
 	.probe		= s3c24xx_serial_probe,
-	.remove		= __devexit_p(s3c24xx_serial_remove),
+	.remove		= s3c24xx_serial_remove,
 	.id_table	= s3c24xx_serial_driver_ids,
 	.driver		= {
 		.name	= "samsung-uart",
diff --git a/drivers/tty/serial/sc26xx.c b/drivers/tty/serial/sc26xx.c
index 9d66424..aced1dd 100644
--- a/drivers/tty/serial/sc26xx.c
+++ b/drivers/tty/serial/sc26xx.c
@@ -621,7 +621,7 @@ static u8 sc26xx_flags2mask(unsigned int flags, unsigned int bitpos)
 	return bit ? (1 << (bit - 1)) : 0;
 }
 
-static void __devinit sc26xx_init_masks(struct uart_sc26xx_port *up,
+static void sc26xx_init_masks(struct uart_sc26xx_port *up,
 					int line, unsigned int data)
 {
 	up->dtr_mask[line] = sc26xx_flags2mask(data,  0);
@@ -632,7 +632,7 @@ static void __devinit sc26xx_init_masks(struct uart_sc26xx_port *up,
 	up->ri_mask[line]  = sc26xx_flags2mask(data, 20);
 }
 
-static int __devinit sc26xx_probe(struct platform_device *dev)
+static int sc26xx_probe(struct platform_device *dev)
 {
 	struct resource *res;
 	struct uart_sc26xx_port *up;
@@ -733,7 +733,7 @@ static int __exit sc26xx_driver_remove(struct platform_device *dev)
 
 static struct platform_driver sc26xx_driver = {
 	.probe	= sc26xx_probe,
-	.remove	= __devexit_p(sc26xx_driver_remove),
+	.remove	= sc26xx_driver_remove,
 	.driver	= {
 		.name	= "SC26xx",
 		.owner	= THIS_MODULE,
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c
index e821068..418b495 100644
--- a/drivers/tty/serial/sccnxp.c
+++ b/drivers/tty/serial/sccnxp.c
@@ -740,7 +740,7 @@ static int sccnxp_console_setup(struct console *co, char *options)
 }
 #endif
 
-static int __devinit sccnxp_probe(struct platform_device *pdev)
+static int sccnxp_probe(struct platform_device *pdev)
 {
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	int chiptype = pdev->id_entry->driver_data;
@@ -943,7 +943,7 @@ err_out:
 	return ret;
 }
 
-static int __devexit sccnxp_remove(struct platform_device *pdev)
+static int sccnxp_remove(struct platform_device *pdev)
 {
 	int i;
 	struct sccnxp_port *s = platform_get_drvdata(pdev);
@@ -981,7 +981,7 @@ static struct platform_driver sccnxp_uart_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= sccnxp_probe,
-	.remove		= __devexit_p(sccnxp_remove),
+	.remove		= sccnxp_remove,
 	.id_table	= sccnxp_id_table,
 };
 module_platform_driver(sccnxp_uart_driver);
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 0fcfd98..2c7230a 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -610,34 +610,57 @@ static void uart_send_xchar(struct tty_struct *tty, char ch)
 static void uart_throttle(struct tty_struct *tty)
 {
 	struct uart_state *state = tty->driver_data;
+	struct uart_port *port = state->uart_port;
+	uint32_t mask = 0;
 
 	if (I_IXOFF(tty))
+		mask |= UPF_SOFT_FLOW;
+	if (tty->termios.c_cflag & CRTSCTS)
+		mask |= UPF_HARD_FLOW;
+
+	if (port->flags & mask) {
+		port->ops->throttle(port);
+		mask &= ~port->flags;
+	}
+
+	if (mask & UPF_SOFT_FLOW)
 		uart_send_xchar(tty, STOP_CHAR(tty));
 
-	if (tty->termios.c_cflag & CRTSCTS)
-		uart_clear_mctrl(state->uart_port, TIOCM_RTS);
+	if (mask & UPF_HARD_FLOW)
+		uart_clear_mctrl(port, TIOCM_RTS);
 }
 
 static void uart_unthrottle(struct tty_struct *tty)
 {
 	struct uart_state *state = tty->driver_data;
 	struct uart_port *port = state->uart_port;
+	uint32_t mask = 0;
+
+	if (I_IXOFF(tty))
+		mask |= UPF_SOFT_FLOW;
+	if (tty->termios.c_cflag & CRTSCTS)
+		mask |= UPF_HARD_FLOW;
 
-	if (I_IXOFF(tty)) {
+	if (port->flags & mask) {
+		port->ops->unthrottle(port);
+		mask &= ~port->flags;
+	}
+
+	if (mask & UPF_SOFT_FLOW) {
 		if (port->x_char)
 			port->x_char = 0;
 		else
 			uart_send_xchar(tty, START_CHAR(tty));
 	}
 
-	if (tty->termios.c_cflag & CRTSCTS)
+	if (mask & UPF_HARD_FLOW)
 		uart_set_mctrl(port, TIOCM_RTS);
 }
 
-static void uart_get_info(struct tty_port *port,
-                        struct uart_state *state,
+static void do_uart_get_info(struct tty_port *port,
 			struct serial_struct *retinfo)
 {
+	struct uart_state *state = container_of(port, struct uart_state, port);
 	struct uart_port *uport = state->uart_port;
 
 	memset(retinfo, 0, sizeof(*retinfo));
@@ -662,17 +685,21 @@ static void uart_get_info(struct tty_port *port,
 	retinfo->iomem_base      = (void *)(unsigned long)uport->mapbase;
 }
 
-static int uart_get_info_user(struct uart_state *state,
-			 struct serial_struct __user *retinfo)
+static void uart_get_info(struct tty_port *port,
+			struct serial_struct *retinfo)
 {
-	struct tty_port *port = &state->port;
-	struct serial_struct tmp;
-
 	/* Ensure the state we copy is consistent and no hardware changes
 	   occur as we go */
 	mutex_lock(&port->mutex);
-	uart_get_info(port, state, &tmp);
+	do_uart_get_info(port, retinfo);
 	mutex_unlock(&port->mutex);
+}
+
+static int uart_get_info_user(struct tty_port *port,
+			 struct serial_struct __user *retinfo)
+{
+	struct serial_struct tmp;
+	uart_get_info(port, &tmp);
 
 	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
 		return -EFAULT;
@@ -1131,7 +1158,7 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd,
 	 */
 	switch (cmd) {
 	case TIOCGSERIAL:
-		ret = uart_get_info_user(state, uarg);
+		ret = uart_get_info_user(port, uarg);
 		break;
 
 	case TIOCSSERIAL:
@@ -1210,9 +1237,22 @@ static void uart_set_termios(struct tty_struct *tty,
 						struct ktermios *old_termios)
 {
 	struct uart_state *state = tty->driver_data;
+	struct uart_port *uport = state->uart_port;
 	unsigned long flags;
 	unsigned int cflag = tty->termios.c_cflag;
+	unsigned int iflag_mask = IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK;
+	bool sw_changed = false;
 
+	/*
+	 * Drivers doing software flow control also need to know
+	 * about changes to these input settings.
+	 */
+	if (uport->flags & UPF_SOFT_FLOW) {
+		iflag_mask |= IXANY|IXON|IXOFF;
+		sw_changed =
+		   tty->termios.c_cc[VSTART] != old_termios->c_cc[VSTART] ||
+		   tty->termios.c_cc[VSTOP] != old_termios->c_cc[VSTOP];
+	}
 
 	/*
 	 * These are the bits that are used to setup various
@@ -1220,11 +1260,11 @@ static void uart_set_termios(struct tty_struct *tty,
 	 * bits in c_cflag; c_[io]speed will always be set
 	 * appropriately by set_termios() in tty_ioctl.c
 	 */
-#define RELEVANT_IFLAG(iflag)	((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
 	if ((cflag ^ old_termios->c_cflag) == 0 &&
 	    tty->termios.c_ospeed == old_termios->c_ospeed &&
 	    tty->termios.c_ispeed == old_termios->c_ispeed &&
-	    RELEVANT_IFLAG(tty->termios.c_iflag ^ old_termios->c_iflag) == 0) {
+	    ((tty->termios.c_iflag ^ old_termios->c_iflag) & iflag_mask) == 0 &&
+	    !sw_changed) {
 		return;
 	}
 
@@ -1232,31 +1272,38 @@ static void uart_set_termios(struct tty_struct *tty,
 
 	/* Handle transition to B0 status */
 	if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
-		uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR);
+		uart_clear_mctrl(uport, TIOCM_RTS | TIOCM_DTR);
 	/* Handle transition away from B0 status */
 	else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
 		unsigned int mask = TIOCM_DTR;
 		if (!(cflag & CRTSCTS) ||
 		    !test_bit(TTY_THROTTLED, &tty->flags))
 			mask |= TIOCM_RTS;
-		uart_set_mctrl(state->uart_port, mask);
+		uart_set_mctrl(uport, mask);
 	}
 
+	/*
+	 * If the port is doing h/w assisted flow control, do nothing.
+	 * We assume that tty->hw_stopped has never been set.
+	 */
+	if (uport->flags & UPF_HARD_FLOW)
+		return;
+
 	/* Handle turning off CRTSCTS */
 	if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
-		spin_lock_irqsave(&state->uart_port->lock, flags);
+		spin_lock_irqsave(&uport->lock, flags);
 		tty->hw_stopped = 0;
 		__uart_start(tty);
-		spin_unlock_irqrestore(&state->uart_port->lock, flags);
+		spin_unlock_irqrestore(&uport->lock, flags);
 	}
 	/* Handle turning on CRTSCTS */
 	else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
-		spin_lock_irqsave(&state->uart_port->lock, flags);
-		if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) {
+		spin_lock_irqsave(&uport->lock, flags);
+		if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) {
 			tty->hw_stopped = 1;
-			state->uart_port->ops->stop_tx(state->uart_port);
+			uport->ops->stop_tx(uport);
 		}
-		spin_unlock_irqrestore(&state->uart_port->lock, flags);
+		spin_unlock_irqrestore(&uport->lock, flags);
 	}
 }
 
@@ -2293,6 +2340,8 @@ int uart_register_driver(struct uart_driver *drv)
 	if (retval >= 0)
 		return retval;
 
+	for (i = 0; i < drv->nr; i++)
+		tty_port_destroy(&drv->state[i].port);
 	put_tty_driver(normal);
 out_kfree:
 	kfree(drv->state);
@@ -2312,8 +2361,12 @@ out:
 void uart_unregister_driver(struct uart_driver *drv)
 {
 	struct tty_driver *p = drv->tty_driver;
+	unsigned int i;
+
 	tty_unregister_driver(p);
 	put_tty_driver(p);
+	for (i = 0; i < drv->nr; i++)
+		tty_port_destroy(&drv->state[i].port);
 	kfree(drv->state);
 	drv->state = NULL;
 	drv->tty_driver = NULL;
@@ -2329,21 +2382,166 @@ struct tty_driver *uart_console_device(struct console *co, int *index)
 static ssize_t uart_get_attr_uartclk(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
-	int ret;
+	struct serial_struct tmp;
 	struct tty_port *port = dev_get_drvdata(dev);
-	struct uart_state *state = container_of(port, struct uart_state, port);
 
-	mutex_lock(&state->port.mutex);
-	ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk);
-	mutex_unlock(&state->port.mutex);
+	uart_get_info(port, &tmp);
+	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.baud_base * 16);
+}
 
-	return ret;
+static ssize_t uart_get_attr_type(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct serial_struct tmp;
+	struct tty_port *port = dev_get_drvdata(dev);
+
+	uart_get_info(port, &tmp);
+	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.type);
+}
+static ssize_t uart_get_attr_line(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct serial_struct tmp;
+	struct tty_port *port = dev_get_drvdata(dev);
+
+	uart_get_info(port, &tmp);
+	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.line);
+}
+
+static ssize_t uart_get_attr_port(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct serial_struct tmp;
+	struct tty_port *port = dev_get_drvdata(dev);
+	unsigned long ioaddr;
+
+	uart_get_info(port, &tmp);
+	ioaddr = tmp.port;
+	if (HIGH_BITS_OFFSET)
+		ioaddr |= (unsigned long)tmp.port_high << HIGH_BITS_OFFSET;
+	return snprintf(buf, PAGE_SIZE, "0x%lX\n", ioaddr);
 }
 
+static ssize_t uart_get_attr_irq(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct serial_struct tmp;
+	struct tty_port *port = dev_get_drvdata(dev);
+
+	uart_get_info(port, &tmp);
+	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.irq);
+}
+
+static ssize_t uart_get_attr_flags(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct serial_struct tmp;
+	struct tty_port *port = dev_get_drvdata(dev);
+
+	uart_get_info(port, &tmp);
+	return snprintf(buf, PAGE_SIZE, "0x%X\n", tmp.flags);
+}
+
+static ssize_t uart_get_attr_xmit_fifo_size(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct serial_struct tmp;
+	struct tty_port *port = dev_get_drvdata(dev);
+
+	uart_get_info(port, &tmp);
+	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.xmit_fifo_size);
+}
+
+
+static ssize_t uart_get_attr_close_delay(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct serial_struct tmp;
+	struct tty_port *port = dev_get_drvdata(dev);
+
+	uart_get_info(port, &tmp);
+	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.close_delay);
+}
+
+
+static ssize_t uart_get_attr_closing_wait(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct serial_struct tmp;
+	struct tty_port *port = dev_get_drvdata(dev);
+
+	uart_get_info(port, &tmp);
+	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.closing_wait);
+}
+
+static ssize_t uart_get_attr_custom_divisor(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct serial_struct tmp;
+	struct tty_port *port = dev_get_drvdata(dev);
+
+	uart_get_info(port, &tmp);
+	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.custom_divisor);
+}
+
+static ssize_t uart_get_attr_io_type(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct serial_struct tmp;
+	struct tty_port *port = dev_get_drvdata(dev);
+
+	uart_get_info(port, &tmp);
+	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.io_type);
+}
+
+static ssize_t uart_get_attr_iomem_base(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct serial_struct tmp;
+	struct tty_port *port = dev_get_drvdata(dev);
+
+	uart_get_info(port, &tmp);
+	return snprintf(buf, PAGE_SIZE, "0x%lX\n", (unsigned long)tmp.iomem_base);
+}
+
+static ssize_t uart_get_attr_iomem_reg_shift(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct serial_struct tmp;
+	struct tty_port *port = dev_get_drvdata(dev);
+
+	uart_get_info(port, &tmp);
+	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.iomem_reg_shift);
+}
+
+static DEVICE_ATTR(type, S_IRUSR | S_IRGRP, uart_get_attr_type, NULL);
+static DEVICE_ATTR(line, S_IRUSR | S_IRGRP, uart_get_attr_line, NULL);
+static DEVICE_ATTR(port, S_IRUSR | S_IRGRP, uart_get_attr_port, NULL);
+static DEVICE_ATTR(irq, S_IRUSR | S_IRGRP, uart_get_attr_irq, NULL);
+static DEVICE_ATTR(flags, S_IRUSR | S_IRGRP, uart_get_attr_flags, NULL);
+static DEVICE_ATTR(xmit_fifo_size, S_IRUSR | S_IRGRP, uart_get_attr_xmit_fifo_size, NULL);
 static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk, NULL);
+static DEVICE_ATTR(close_delay, S_IRUSR | S_IRGRP, uart_get_attr_close_delay, NULL);
+static DEVICE_ATTR(closing_wait, S_IRUSR | S_IRGRP, uart_get_attr_closing_wait, NULL);
+static DEVICE_ATTR(custom_divisor, S_IRUSR | S_IRGRP, uart_get_attr_custom_divisor, NULL);
+static DEVICE_ATTR(io_type, S_IRUSR | S_IRGRP, uart_get_attr_io_type, NULL);
+static DEVICE_ATTR(iomem_base, S_IRUSR | S_IRGRP, uart_get_attr_iomem_base, NULL);
+static DEVICE_ATTR(iomem_reg_shift, S_IRUSR | S_IRGRP, uart_get_attr_iomem_reg_shift, NULL);
 
 static struct attribute *tty_dev_attrs[] = {
+	&dev_attr_type.attr,
+	&dev_attr_line.attr,
+	&dev_attr_port.attr,
+	&dev_attr_irq.attr,
+	&dev_attr_flags.attr,
+	&dev_attr_xmit_fifo_size.attr,
 	&dev_attr_uartclk.attr,
+	&dev_attr_close_delay.attr,
+	&dev_attr_closing_wait.attr,
+	&dev_attr_custom_divisor.attr,
+	&dev_attr_io_type.attr,
+	&dev_attr_iomem_base.attr,
+	&dev_attr_iomem_reg_shift.attr,
 	NULL,
 	};
 
@@ -2356,6 +2554,7 @@ static const struct attribute_group *tty_dev_attr_groups[] = {
 	NULL
 	};
 
+
 /**
  *	uart_add_one_port - attach a driver-defined port structure
  *	@drv: pointer to the uart low level driver structure for this port
diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
index 6ae2a58..b52b21a 100644
--- a/drivers/tty/serial/serial_txx9.c
+++ b/drivers/tty/serial/serial_txx9.c
@@ -1030,7 +1030,7 @@ static DEFINE_MUTEX(serial_txx9_mutex);
  *
  *	On success the port is ready to use and the line number is returned.
  */
-static int __devinit serial_txx9_register_port(struct uart_port *port)
+static int serial_txx9_register_port(struct uart_port *port)
 {
 	int i;
 	struct uart_txx9_port *uart;
@@ -1078,7 +1078,7 @@ static int __devinit serial_txx9_register_port(struct uart_port *port)
  *	Remove one serial port.  This may not be called from interrupt
  *	context.  We hand the port back to the our control.
  */
-static void __devexit serial_txx9_unregister_port(int line)
+static void serial_txx9_unregister_port(int line)
 {
 	struct uart_txx9_port *uart = &serial_txx9_ports[line];
 
@@ -1096,7 +1096,7 @@ static void __devexit serial_txx9_unregister_port(int line)
 /*
  * Register a set of serial devices attached to a platform device.
  */
-static int __devinit serial_txx9_probe(struct platform_device *dev)
+static int serial_txx9_probe(struct platform_device *dev)
 {
 	struct uart_port *p = dev->dev.platform_data;
 	struct uart_port port;
@@ -1126,7 +1126,7 @@ static int __devinit serial_txx9_probe(struct platform_device *dev)
 /*
  * Remove serial ports registered against a platform device.
  */
-static int __devexit serial_txx9_remove(struct platform_device *dev)
+static int serial_txx9_remove(struct platform_device *dev)
 {
 	int i;
 
@@ -1171,7 +1171,7 @@ static int serial_txx9_resume(struct platform_device *dev)
 
 static struct platform_driver serial_txx9_plat_driver = {
 	.probe		= serial_txx9_probe,
-	.remove		= __devexit_p(serial_txx9_remove),
+	.remove		= serial_txx9_remove,
 #ifdef CONFIG_PM
 	.suspend	= serial_txx9_suspend,
 	.resume		= serial_txx9_resume,
@@ -1187,7 +1187,7 @@ static struct platform_driver serial_txx9_plat_driver = {
  * Probe one serial board.  Unfortunately, there is no rhyme nor reason
  * to the arrangement of serial ports on a PCI card.
  */
-static int __devinit
+static int
 pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
 {
 	struct uart_port port;
@@ -1217,7 +1217,7 @@ pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
 	return 0;
 }
 
-static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev)
+static void pciserial_txx9_remove_one(struct pci_dev *dev)
 {
 	struct uart_txx9_port *up = pci_get_drvdata(dev);
 
@@ -1261,7 +1261,7 @@ static const struct pci_device_id serial_txx9_pci_tbl[] = {
 static struct pci_driver serial_txx9_pci_driver = {
 	.name		= "serial_txx9",
 	.probe		= pciserial_txx9_init_one,
-	.remove		= __devexit_p(pciserial_txx9_remove_one),
+	.remove		= pciserial_txx9_remove_one,
 #ifdef CONFIG_PM
 	.suspend	= pciserial_txx9_suspend_one,
 	.resume		= pciserial_txx9_resume_one,
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 6ee5900..6147756 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -99,12 +99,6 @@ struct sci_port {
 #endif
 
 	struct notifier_block		freq_transition;
-
-#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
-	unsigned short saved_smr;
-	unsigned short saved_fcr;
-	unsigned char saved_brr;
-#endif
 };
 
 /* Function prototypes */
@@ -202,9 +196,9 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
 		[SCxSR]		= { 0x14, 16 },
 		[SCxRDR]	= { 0x60,  8 },
 		[SCFCR]		= { 0x18, 16 },
-		[SCFDR]		= { 0x1c, 16 },
-		[SCTFDR]	= sci_reg_invalid,
-		[SCRFDR]	= sci_reg_invalid,
+		[SCFDR]		= sci_reg_invalid,
+		[SCTFDR]	= { 0x38, 16 },
+		[SCRFDR]	= { 0x3c, 16 },
 		[SCSPTR]	= sci_reg_invalid,
 		[SCLSR]		= sci_reg_invalid,
 	},
@@ -491,7 +485,7 @@ static int sci_txfill(struct uart_port *port)
 
 	reg = sci_getreg(port, SCTFDR);
 	if (reg->size)
-		return serial_port_in(port, SCTFDR) & 0xff;
+		return serial_port_in(port, SCTFDR) & ((port->fifosize << 1) - 1);
 
 	reg = sci_getreg(port, SCFDR);
 	if (reg->size)
@@ -511,7 +505,7 @@ static int sci_rxfill(struct uart_port *port)
 
 	reg = sci_getreg(port, SCRFDR);
 	if (reg->size)
-		return serial_port_in(port, SCRFDR) & 0xff;
+		return serial_port_in(port, SCRFDR) & ((port->fifosize << 1) - 1);
 
 	reg = sci_getreg(port, SCFDR);
 	if (reg->size)
@@ -1132,7 +1126,7 @@ static const char *sci_gpio_str(unsigned int index)
 	return sci_gpio_names[index];
 }
 
-static void __devinit sci_init_gpios(struct sci_port *port)
+static void sci_init_gpios(struct sci_port *port)
 {
 	struct uart_port *up = &port->port;
 	int i;
@@ -1749,22 +1743,21 @@ static inline void sci_free_dma(struct uart_port *port)
 static int sci_startup(struct uart_port *port)
 {
 	struct sci_port *s = to_sci_port(port);
+	unsigned long flags;
 	int ret;
 
 	dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
 
-	pm_runtime_put_noidle(port->dev);
-
-	sci_port_enable(s);
-
 	ret = sci_request_irq(s);
 	if (unlikely(ret < 0))
 		return ret;
 
 	sci_request_dma(port);
 
+	spin_lock_irqsave(&port->lock, flags);
 	sci_start_tx(port);
 	sci_start_rx(port);
+	spin_unlock_irqrestore(&port->lock, flags);
 
 	return 0;
 }
@@ -1772,18 +1765,17 @@ static int sci_startup(struct uart_port *port)
 static void sci_shutdown(struct uart_port *port)
 {
 	struct sci_port *s = to_sci_port(port);
+	unsigned long flags;
 
 	dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
 
+	spin_lock_irqsave(&port->lock, flags);
 	sci_stop_rx(port);
 	sci_stop_tx(port);
+	spin_unlock_irqrestore(&port->lock, flags);
 
 	sci_free_dma(port);
 	sci_free_irq(s);
-
-	sci_port_disable(s);
-
-	pm_runtime_get_noresume(port->dev);
 }
 
 static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
@@ -1829,7 +1821,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 {
 	struct sci_port *s = to_sci_port(port);
 	struct plat_sci_reg *reg;
-	unsigned int baud, smr_val, max_baud;
+	unsigned int baud, smr_val, max_baud, cks;
 	int t = -1;
 
 	/*
@@ -1863,21 +1855,18 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	uart_update_timeout(port, termios->c_cflag, baud);
 
-	serial_port_out(port, SCSMR, smr_val);
-
-	dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t,
-		s->cfg->scscr);
+	for (cks = 0; t >= 256 && cks <= 3; cks++)
+		t >>= 2;
 
-	if (t > 0) {
-		if (t >= 256) {
-			serial_port_out(port, SCSMR, (serial_port_in(port, SCSMR) & ~3) | 1);
-			t >>= 2;
-		} else
-			serial_port_out(port, SCSMR, serial_port_in(port, SCSMR) & ~3);
+	dev_dbg(port->dev, "%s: SMR %x, cks %x, t %x, SCSCR %x\n",
+		__func__, smr_val, cks, t, s->cfg->scscr);
 
+	if (t >= 0) {
+		serial_port_out(port, SCSMR, (smr_val & ~3) | cks);
 		serial_port_out(port, SCBRR, t);
 		udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */
-	}
+	} else
+		serial_port_out(port, SCSMR, smr_val);
 
 	sci_init_pins(port, termios->c_cflag);
 
@@ -1932,6 +1921,21 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 	sci_port_disable(s);
 }
 
+static void sci_pm(struct uart_port *port, unsigned int state,
+		   unsigned int oldstate)
+{
+	struct sci_port *sci_port = to_sci_port(port);
+
+	switch (state) {
+	case 3:
+		sci_port_disable(sci_port);
+		break;
+	default:
+		sci_port_enable(sci_port);
+		break;
+	}
+}
+
 static const char *sci_type(struct uart_port *port)
 {
 	switch (port->type) {
@@ -2053,6 +2057,7 @@ static struct uart_ops sci_uart_ops = {
 	.startup	= sci_startup,
 	.shutdown	= sci_shutdown,
 	.set_termios	= sci_set_termios,
+	.pm		= sci_pm,
 	.type		= sci_type,
 	.release_port	= sci_release_port,
 	.request_port	= sci_request_port,
@@ -2064,7 +2069,7 @@ static struct uart_ops sci_uart_ops = {
 #endif
 };
 
-static int __devinit sci_init_single(struct platform_device *dev,
+static int sci_init_single(struct platform_device *dev,
 				     struct sci_port *sci_port,
 				     unsigned int index,
 				     struct plat_sci_port *p)
@@ -2121,8 +2126,6 @@ static int __devinit sci_init_single(struct platform_device *dev,
 
 		sci_init_gpios(sci_port);
 
-		pm_runtime_irq_safe(&dev->dev);
-		pm_runtime_get_noresume(&dev->dev);
 		pm_runtime_enable(&dev->dev);
 	}
 
@@ -2206,9 +2209,21 @@ static void serial_console_write(struct console *co, const char *s,
 {
 	struct sci_port *sci_port = &sci_ports[co->index];
 	struct uart_port *port = &sci_port->port;
-	unsigned short bits;
+	unsigned short bits, ctrl;
+	unsigned long flags;
+	int locked = 1;
+
+	local_irq_save(flags);
+	if (port->sysrq)
+		locked = 0;
+	else if (oops_in_progress)
+		locked = spin_trylock(&port->lock);
+	else
+		spin_lock(&port->lock);
 
-	sci_port_enable(sci_port);
+	/* first save the SCSCR then disable the interrupts */
+	ctrl = serial_port_in(port, SCSCR);
+	serial_port_out(port, SCSCR, sci_port->cfg->scscr);
 
 	uart_console_write(port, s, count, serial_console_putchar);
 
@@ -2217,10 +2232,15 @@ static void serial_console_write(struct console *co, const char *s,
 	while ((serial_port_in(port, SCxSR) & bits) != bits)
 		cpu_relax();
 
-	sci_port_disable(sci_port);
+	/* restore the SCSCR */
+	serial_port_out(port, SCSCR, ctrl);
+
+	if (locked)
+		spin_unlock(&port->lock);
+	local_irq_restore(flags);
 }
 
-static int __devinit serial_console_setup(struct console *co, char *options)
+static int serial_console_setup(struct console *co, char *options)
 {
 	struct sci_port *sci_port;
 	struct uart_port *port;
@@ -2249,13 +2269,9 @@ static int __devinit serial_console_setup(struct console *co, char *options)
 	if (unlikely(ret != 0))
 		return ret;
 
-	sci_port_enable(sci_port);
-
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 
-	sci_port_disable(sci_port);
-
 	return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
@@ -2278,7 +2294,7 @@ static struct console early_serial_console = {
 
 static char early_serial_buf[32];
 
-static int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
+static int sci_probe_earlyprintk(struct platform_device *pdev)
 {
 	struct plat_sci_port *cfg = pdev->dev.platform_data;
 
@@ -2298,57 +2314,15 @@ static int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
 	return 0;
 }
 
-#define uart_console(port)	((port)->cons->index == (port)->line)
-
-static int sci_runtime_suspend(struct device *dev)
-{
-	struct sci_port *sci_port = dev_get_drvdata(dev);
-	struct uart_port *port = &sci_port->port;
-
-	if (uart_console(port)) {
-		struct plat_sci_reg *reg;
-
-		sci_port->saved_smr = serial_port_in(port, SCSMR);
-		sci_port->saved_brr = serial_port_in(port, SCBRR);
-
-		reg = sci_getreg(port, SCFCR);
-		if (reg->size)
-			sci_port->saved_fcr = serial_port_in(port, SCFCR);
-		else
-			sci_port->saved_fcr = 0;
-	}
-	return 0;
-}
-
-static int sci_runtime_resume(struct device *dev)
-{
-	struct sci_port *sci_port = dev_get_drvdata(dev);
-	struct uart_port *port = &sci_port->port;
-
-	if (uart_console(port)) {
-		sci_reset(port);
-		serial_port_out(port, SCSMR, sci_port->saved_smr);
-		serial_port_out(port, SCBRR, sci_port->saved_brr);
-
-		if (sci_port->saved_fcr)
-			serial_port_out(port, SCFCR, sci_port->saved_fcr);
-
-		serial_port_out(port, SCSCR, sci_port->cfg->scscr);
-	}
-	return 0;
-}
-
 #define SCI_CONSOLE	(&serial_console)
 
 #else
-static inline int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
+static inline int sci_probe_earlyprintk(struct platform_device *pdev)
 {
 	return -EINVAL;
 }
 
 #define SCI_CONSOLE	NULL
-#define sci_runtime_suspend	NULL
-#define sci_runtime_resume	NULL
 
 #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
 
@@ -2379,7 +2353,7 @@ static int sci_remove(struct platform_device *dev)
 	return 0;
 }
 
-static int __devinit sci_probe_single(struct platform_device *dev,
+static int sci_probe_single(struct platform_device *dev,
 				      unsigned int index,
 				      struct plat_sci_port *p,
 				      struct sci_port *sciport)
@@ -2409,7 +2383,7 @@ static int __devinit sci_probe_single(struct platform_device *dev,
 	return 0;
 }
 
-static int __devinit sci_probe(struct platform_device *dev)
+static int sci_probe(struct platform_device *dev)
 {
 	struct plat_sci_port *p = dev->dev.platform_data;
 	struct sci_port *sp = &sci_ports[dev->id];
@@ -2466,8 +2440,6 @@ static int sci_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops sci_dev_pm_ops = {
-	.runtime_suspend = sci_runtime_suspend,
-	.runtime_resume = sci_runtime_resume,
 	.suspend	= sci_suspend,
 	.resume		= sci_resume,
 };
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c
index a9e2bd1..5da5cb9 100644
--- a/drivers/tty/serial/sirfsoc_uart.c
+++ b/drivers/tty/serial/sirfsoc_uart.c
@@ -727,7 +727,7 @@ static int sirfsoc_uart_resume(struct platform_device *pdev)
 	return 0;
 }
 
-static struct of_device_id sirfsoc_uart_ids[] __devinitdata = {
+static struct of_device_id sirfsoc_uart_ids[] = {
 	{ .compatible = "sirf,prima2-uart", },
 	{}
 };
@@ -735,7 +735,7 @@ MODULE_DEVICE_TABLE(of, sirfsoc_serial_of_match);
 
 static struct platform_driver sirfsoc_uart_driver = {
 	.probe		= sirfsoc_uart_probe,
-	.remove		= __devexit_p(sirfsoc_uart_remove),
+	.remove		= sirfsoc_uart_remove,
 	.suspend	= sirfsoc_uart_suspend,
 	.resume		= sirfsoc_uart_resume,
 	.driver		= {
diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c
index 505961c..b9bf9c5 100644
--- a/drivers/tty/serial/sunhv.c
+++ b/drivers/tty/serial/sunhv.c
@@ -519,7 +519,7 @@ static struct console sunhv_console = {
 	.data	=	&sunhv_reg,
 };
 
-static int __devinit hv_probe(struct platform_device *op)
+static int hv_probe(struct platform_device *op)
 {
 	struct uart_port *port;
 	unsigned long minor;
@@ -598,7 +598,7 @@ out_free_port:
 	return err;
 }
 
-static int __devexit hv_remove(struct platform_device *dev)
+static int hv_remove(struct platform_device *dev)
 {
 	struct uart_port *port = dev_get_drvdata(&dev->dev);
 
@@ -636,7 +636,7 @@ static struct platform_driver hv_driver = {
 		.of_match_table = hv_match,
 	},
 	.probe		= hv_probe,
-	.remove		= __devexit_p(hv_remove),
+	.remove		= hv_remove,
 };
 
 static int __init sunhv_init(void)
diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c
index f0d93eb..bd8b3b6 100644
--- a/drivers/tty/serial/sunsab.c
+++ b/drivers/tty/serial/sunsab.c
@@ -954,7 +954,7 @@ static inline struct console *SUNSAB_CONSOLE(void)
 #define sunsab_console_init()	do { } while (0)
 #endif
 
-static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
+static int sunsab_init_one(struct uart_sunsab_port *up,
 				     struct platform_device *op,
 				     unsigned long offset,
 				     int line)
@@ -1007,7 +1007,7 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
 	return 0;
 }
 
-static int __devinit sab_probe(struct platform_device *op)
+static int sab_probe(struct platform_device *op)
 {
 	static int inst;
 	struct uart_sunsab_port *up;
@@ -1063,7 +1063,7 @@ out:
 	return err;
 }
 
-static int __devexit sab_remove(struct platform_device *op)
+static int sab_remove(struct platform_device *op)
 {
 	struct uart_sunsab_port *up = dev_get_drvdata(&op->dev);
 
@@ -1100,7 +1100,7 @@ static struct platform_driver sab_driver = {
 		.of_match_table = sab_match,
 	},
 	.probe		= sab_probe,
-	.remove		= __devexit_p(sab_remove),
+	.remove		= sab_remove,
 };
 
 static int __init sunsab_init(void)
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index b97913d..220da3f 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -1185,7 +1185,7 @@ static struct uart_driver sunsu_reg = {
 	.major			= TTY_MAJOR,
 };
 
-static int __devinit sunsu_kbd_ms_init(struct uart_sunsu_port *up)
+static int sunsu_kbd_ms_init(struct uart_sunsu_port *up)
 {
 	int quot, baud;
 #ifdef CONFIG_SERIO
@@ -1391,7 +1391,7 @@ static inline struct console *SUNSU_CONSOLE(void)
 #define sunsu_serial_console_init()	do { } while (0)
 #endif
 
-static enum su_type __devinit su_get_type(struct device_node *dp)
+static enum su_type su_get_type(struct device_node *dp)
 {
 	struct device_node *ap = of_find_node_by_path("/aliases");
 
@@ -1412,7 +1412,7 @@ static enum su_type __devinit su_get_type(struct device_node *dp)
 	return SU_PORT_PORT;
 }
 
-static int __devinit su_probe(struct platform_device *op)
+static int su_probe(struct platform_device *op)
 {
 	static int inst;
 	struct device_node *dp = op->dev.of_node;
@@ -1503,7 +1503,7 @@ out_unmap:
 	return err;
 }
 
-static int __devexit su_remove(struct platform_device *op)
+static int su_remove(struct platform_device *op)
 {
 	struct uart_sunsu_port *up = dev_get_drvdata(&op->dev);
 	bool kbdms = false;
@@ -1556,7 +1556,7 @@ static struct platform_driver su_driver = {
 		.of_match_table = su_match,
 	},
 	.probe		= su_probe,
-	.remove		= __devexit_p(su_remove),
+	.remove		= su_remove,
 };
 
 static int __init sunsu_init(void)
diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
index babd947..aef4fab 100644
--- a/drivers/tty/serial/sunzilog.c
+++ b/drivers/tty/serial/sunzilog.c
@@ -1282,7 +1282,7 @@ static inline struct console *SUNZILOG_CONSOLE(void)
 #define SUNZILOG_CONSOLE()	(NULL)
 #endif
 
-static void __devinit sunzilog_init_kbdms(struct uart_sunzilog_port *up)
+static void sunzilog_init_kbdms(struct uart_sunzilog_port *up)
 {
 	int baud, brg;
 
@@ -1302,7 +1302,7 @@ static void __devinit sunzilog_init_kbdms(struct uart_sunzilog_port *up)
 }
 
 #ifdef CONFIG_SERIO
-static void __devinit sunzilog_register_serio(struct uart_sunzilog_port *up)
+static void sunzilog_register_serio(struct uart_sunzilog_port *up)
 {
 	struct serio *serio = &up->serio;
 
@@ -1331,7 +1331,7 @@ static void __devinit sunzilog_register_serio(struct uart_sunzilog_port *up)
 }
 #endif
 
-static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
+static void sunzilog_init_hw(struct uart_sunzilog_port *up)
 {
 	struct zilog_channel __iomem *channel;
 	unsigned long flags;
@@ -1400,7 +1400,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
 
 static int zilog_irq;
 
-static int __devinit zs_probe(struct platform_device *op)
+static int zs_probe(struct platform_device *op)
 {
 	static int kbm_inst, uart_inst;
 	int inst;
@@ -1507,7 +1507,7 @@ static int __devinit zs_probe(struct platform_device *op)
 	return 0;
 }
 
-static void __devexit zs_remove_one(struct uart_sunzilog_port *up)
+static void zs_remove_one(struct uart_sunzilog_port *up)
 {
 	if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
 #ifdef CONFIG_SERIO
@@ -1517,7 +1517,7 @@ static void __devexit zs_remove_one(struct uart_sunzilog_port *up)
 		uart_remove_one_port(&sunzilog_reg, &up->port);
 }
 
-static int __devexit zs_remove(struct platform_device *op)
+static int zs_remove(struct platform_device *op)
 {
 	struct uart_sunzilog_port *up = dev_get_drvdata(&op->dev);
 	struct zilog_layout __iomem *regs;
@@ -1548,7 +1548,7 @@ static struct platform_driver zs_driver = {
 		.of_match_table = zs_match,
 	},
 	.probe		= zs_probe,
-	.remove		= __devexit_p(zs_remove),
+	.remove		= zs_remove,
 };
 
 static int __init sunzilog_init(void)
diff --git a/drivers/tty/serial/timbuart.c b/drivers/tty/serial/timbuart.c
index 70f9749..5be0d68 100644
--- a/drivers/tty/serial/timbuart.c
+++ b/drivers/tty/serial/timbuart.c
@@ -426,7 +426,7 @@ static struct uart_driver timbuart_driver = {
 	.nr = 1
 };
 
-static int __devinit timbuart_probe(struct platform_device *dev)
+static int timbuart_probe(struct platform_device *dev)
 {
 	int err, irq;
 	struct timbuart_port *uart;
@@ -492,7 +492,7 @@ err_mem:
 	return err;
 }
 
-static int __devexit timbuart_remove(struct platform_device *dev)
+static int timbuart_remove(struct platform_device *dev)
 {
 	struct timbuart_port *uart = platform_get_drvdata(dev);
 
@@ -510,7 +510,7 @@ static struct platform_driver timbuart_platform_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= timbuart_probe,
-	.remove		= __devexit_p(timbuart_remove),
+	.remove		= timbuart_remove,
 };
 
 module_platform_driver(timbuart_platform_driver);
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 6579ffd..89eee43 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -408,7 +408,7 @@ static void ulite_console_write(struct console *co, const char *s,
 		spin_unlock_irqrestore(&port->lock, flags);
 }
 
-static int __devinit ulite_console_setup(struct console *co, char *options)
+static int ulite_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
 	int baud = 9600;
@@ -486,7 +486,7 @@ static struct uart_driver ulite_uart_driver = {
  *
  * Returns: 0 on success, <0 otherwise
  */
-static int __devinit ulite_assign(struct device *dev, int id, u32 base, int irq)
+static int ulite_assign(struct device *dev, int id, u32 base, int irq)
 {
 	struct uart_port *port;
 	int rc;
@@ -542,7 +542,7 @@ static int __devinit ulite_assign(struct device *dev, int id, u32 base, int irq)
  *
  * @dev: pointer to device structure
  */
-static int __devexit ulite_release(struct device *dev)
+static int ulite_release(struct device *dev)
 {
 	struct uart_port *port = dev_get_drvdata(dev);
 	int rc = 0;
@@ -562,7 +562,7 @@ static int __devexit ulite_release(struct device *dev)
 
 #if defined(CONFIG_OF)
 /* Match table for of_platform binding */
-static struct of_device_id ulite_of_match[] __devinitdata = {
+static struct of_device_id ulite_of_match[] = {
 	{ .compatible = "xlnx,opb-uartlite-1.00.b", },
 	{ .compatible = "xlnx,xps-uartlite-1.00.a", },
 	{}
@@ -570,7 +570,7 @@ static struct of_device_id ulite_of_match[] __devinitdata = {
 MODULE_DEVICE_TABLE(of, ulite_of_match);
 #endif /* CONFIG_OF */
 
-static int __devinit ulite_probe(struct platform_device *pdev)
+static int ulite_probe(struct platform_device *pdev)
 {
 	struct resource *res, *res2;
 	int id = pdev->id;
@@ -593,7 +593,7 @@ static int __devinit ulite_probe(struct platform_device *pdev)
 	return ulite_assign(&pdev->dev, id, res->start, res2->start);
 }
 
-static int __devexit ulite_remove(struct platform_device *pdev)
+static int ulite_remove(struct platform_device *pdev)
 {
 	return ulite_release(&pdev->dev);
 }
@@ -603,7 +603,7 @@ MODULE_ALIAS("platform:uartlite");
 
 static struct platform_driver ulite_platform_driver = {
 	.probe = ulite_probe,
-	.remove = __devexit_p(ulite_remove),
+	.remove = ulite_remove,
 	.driver = {
 		.owner = THIS_MODULE,
 		.name  = "uartlite",
diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c
index cf0d948..62ee016 100644
--- a/drivers/tty/serial/vr41xx_siu.c
+++ b/drivers/tty/serial/vr41xx_siu.c
@@ -823,7 +823,7 @@ static struct console siu_console = {
 	.data	= &siu_uart_driver,
 };
 
-static int __devinit siu_console_init(void)
+static int siu_console_init(void)
 {
 	struct uart_port *port;
 	int i;
@@ -867,7 +867,7 @@ static struct uart_driver siu_uart_driver = {
 	.cons		= SERIAL_VR41XX_CONSOLE,
 };
 
-static int __devinit siu_probe(struct platform_device *dev)
+static int siu_probe(struct platform_device *dev)
 {
 	struct uart_port *port;
 	int num, i, retval;
@@ -901,7 +901,7 @@ static int __devinit siu_probe(struct platform_device *dev)
 	return 0;
 }
 
-static int __devexit siu_remove(struct platform_device *dev)
+static int siu_remove(struct platform_device *dev)
 {
 	struct uart_port *port;
 	int i;
@@ -952,7 +952,7 @@ static int siu_resume(struct platform_device *dev)
 
 static struct platform_driver siu_device_driver = {
 	.probe		= siu_probe,
-	.remove		= __devexit_p(siu_remove),
+	.remove		= siu_remove,
 	.suspend	= siu_suspend,
 	.resume		= siu_resume,
 	.driver		= {
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
index 205d4cf..8fd1814 100644
--- a/drivers/tty/serial/vt8500_serial.c
+++ b/drivers/tty/serial/vt8500_serial.c
@@ -554,7 +554,7 @@ static struct uart_driver vt8500_uart_driver = {
 	.cons		= VT8500_CONSOLE,
 };
 
-static int __devinit vt8500_serial_probe(struct platform_device *pdev)
+static int vt8500_serial_probe(struct platform_device *pdev)
 {
 	struct vt8500_port *vt8500_port;
 	struct resource *mmres, *irqres;
@@ -567,10 +567,6 @@ static int __devinit vt8500_serial_probe(struct platform_device *pdev)
 	if (!mmres || !irqres)
 		return -ENODEV;
 
-	vt8500_port = kzalloc(sizeof(struct vt8500_port), GFP_KERNEL);
-	if (!vt8500_port)
-		return -ENOMEM;
-
 	if (np)
 		port = of_alias_get_id(np, "serial");
 		if (port > VT8500_MAX_PORTS)
@@ -593,6 +589,10 @@ static int __devinit vt8500_serial_probe(struct platform_device *pdev)
 		return -EBUSY;
 	}
 
+	vt8500_port = kzalloc(sizeof(struct vt8500_port), GFP_KERNEL);
+	if (!vt8500_port)
+		return -ENOMEM;
+
 	vt8500_port->uart.type = PORT_VT8500;
 	vt8500_port->uart.iotype = UPIO_MEM;
 	vt8500_port->uart.mapbase = mmres->start;
@@ -634,7 +634,7 @@ err:
 	return ret;
 }
 
-static int __devexit vt8500_serial_remove(struct platform_device *pdev)
+static int vt8500_serial_remove(struct platform_device *pdev)
 {
 	struct vt8500_port *vt8500_port = platform_get_drvdata(pdev);
 
@@ -652,7 +652,7 @@ static const struct of_device_id wmt_dt_ids[] = {
 
 static struct platform_driver vt8500_platform_driver = {
 	.probe  = vt8500_serial_probe,
-	.remove = __devexit_p(vt8500_serial_remove),
+	.remove = vt8500_serial_remove,
 	.driver = {
 		.name = "vt8500_serial",
 		.owner = THIS_MODULE,
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index b627363..2be22a2 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -17,6 +17,7 @@
 #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>
 #include <linux/of.h>
@@ -939,27 +940,25 @@ static struct uart_driver xuartps_uart_driver = {
  *
  * Returns 0 on success, negative error otherwise
  **/
-static int __devinit xuartps_probe(struct platform_device *pdev)
+static int xuartps_probe(struct platform_device *pdev)
 {
 	int rc;
 	struct uart_port *port;
 	struct resource *res, *res2;
-	int clk = 0;
+	struct clk *clk;
 
-#ifdef CONFIG_OF
-	const unsigned int *prop;
-
-	prop = of_get_property(pdev->dev.of_node, "clock", NULL);
-	if (prop)
-		clk = be32_to_cpup(prop);
-#else
-	clk = *((unsigned int *)(pdev->dev.platform_data));
-#endif
+	clk = of_clk_get(pdev->dev.of_node, 0);
 	if (!clk) {
 		dev_err(&pdev->dev, "no clock specified\n");
 		return -ENODEV;
 	}
 
+	rc = clk_prepare_enable(clk);
+	if (rc) {
+		dev_err(&pdev->dev, "could not enable clock\n");
+		return -EBUSY;
+	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
 		return -ENODEV;
@@ -982,7 +981,8 @@ static int __devinit xuartps_probe(struct platform_device *pdev)
 		port->mapbase = res->start;
 		port->irq = res2->start;
 		port->dev = &pdev->dev;
-		port->uartclk = clk;
+		port->uartclk = clk_get_rate(clk);
+		port->private_data = clk;
 		dev_set_drvdata(&pdev->dev, port);
 		rc = uart_add_one_port(&xuartps_uart_driver, port);
 		if (rc) {
@@ -1001,17 +1001,17 @@ static int __devinit xuartps_probe(struct platform_device *pdev)
  *
  * Returns 0 on success, negative error otherwise
  **/
-static int __devexit xuartps_remove(struct platform_device *pdev)
+static int xuartps_remove(struct platform_device *pdev)
 {
 	struct uart_port *port = dev_get_drvdata(&pdev->dev);
-	int rc = 0;
+	struct clk *clk = port->private_data;
+	int rc;
 
 	/* Remove the xuartps port from the serial core */
-	if (port) {
-		rc = uart_remove_one_port(&xuartps_uart_driver, port);
-		dev_set_drvdata(&pdev->dev, NULL);
-		port->mapbase = 0;
-	}
+	rc = uart_remove_one_port(&xuartps_uart_driver, port);
+	dev_set_drvdata(&pdev->dev, NULL);
+	port->mapbase = 0;
+	clk_disable_unprepare(clk);
 	return rc;
 }
 
@@ -1044,16 +1044,11 @@ static int xuartps_resume(struct platform_device *pdev)
 }
 
 /* Match table for of_platform binding */
-
-#ifdef CONFIG_OF
-static struct of_device_id xuartps_of_match[] __devinitdata = {
+static struct of_device_id xuartps_of_match[] = {
 	{ .compatible = "xlnx,xuartps", },
 	{}
 };
 MODULE_DEVICE_TABLE(of, xuartps_of_match);
-#else
-#define xuartps_of_match NULL
-#endif
 
 static struct platform_driver xuartps_platform_driver = {
 	.probe   = xuartps_probe,		/* Probe method */
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
index 70e3a52..9e071f6 100644
--- a/drivers/tty/synclink.c
+++ b/drivers/tty/synclink.c
@@ -898,7 +898,7 @@ static struct pci_driver synclink_pci_driver = {
 	.name		= "synclink",
 	.id_table	= synclink_pci_tbl,
 	.probe		= synclink_init_one,
-	.remove		= __devexit_p(synclink_remove_one),
+	.remove		= synclink_remove_one,
 };
 
 static struct tty_driver *serial_driver;
@@ -4425,6 +4425,7 @@ static void synclink_cleanup(void)
 		mgsl_release_resources(info);
 		tmp = info;
 		info = info->next_device;
+		tty_port_destroy(&tmp->port);
 		kfree(tmp);
 	}
 	
@@ -8064,7 +8065,7 @@ static void hdlcdev_exit(struct mgsl_struct *info)
 #endif /* CONFIG_HDLC */
 
 
-static int __devinit synclink_init_one (struct pci_dev *dev,
+static int synclink_init_one (struct pci_dev *dev,
 					const struct pci_device_id *ent)
 {
 	struct mgsl_struct *info;
@@ -8116,7 +8117,7 @@ static int __devinit synclink_init_one (struct pci_dev *dev,
 	return 0;
 }
 
-static void __devexit synclink_remove_one (struct pci_dev *dev)
+static void synclink_remove_one (struct pci_dev *dev)
 {
 }
 
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
index b38e954..aba1e59 100644
--- a/drivers/tty/synclink_gt.c
+++ b/drivers/tty/synclink_gt.c
@@ -110,7 +110,7 @@ static struct pci_driver pci_driver = {
 	.name		= "synclink_gt",
 	.id_table	= pci_table,
 	.probe		= init_one,
-	.remove		= __devexit_p(remove_one),
+	.remove		= remove_one,
 };
 
 static bool pci_registered;
@@ -3645,8 +3645,10 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
 	for (i=0; i < port_count; ++i) {
 		port_array[i] = alloc_dev(adapter_num, i, pdev);
 		if (port_array[i] == NULL) {
-			for (--i; i >= 0; --i)
+			for (--i; i >= 0; --i) {
+				tty_port_destroy(&port_array[i]->port);
 				kfree(port_array[i]);
+			}
 			return;
 		}
 	}
@@ -3696,7 +3698,7 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
 	}
 }
 
-static int __devinit init_one(struct pci_dev *dev,
+static int init_one(struct pci_dev *dev,
 			      const struct pci_device_id *ent)
 {
 	if (pci_enable_device(dev)) {
@@ -3708,7 +3710,7 @@ static int __devinit init_one(struct pci_dev *dev,
 	return 0;
 }
 
-static void __devexit remove_one(struct pci_dev *dev)
+static void remove_one(struct pci_dev *dev)
 {
 }
 
@@ -3773,6 +3775,7 @@ static void slgt_cleanup(void)
 			release_resources(info);
 		tmp = info;
 		info = info->next_device;
+		tty_port_destroy(&tmp->port);
 		kfree(tmp);
 	}
 
diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c
index f17d9f3..fd43fb6 100644
--- a/drivers/tty/synclinkmp.c
+++ b/drivers/tty/synclinkmp.c
@@ -492,7 +492,7 @@ static struct pci_driver synclinkmp_pci_driver = {
 	.name		= "synclinkmp",
 	.id_table	= synclinkmp_pci_tbl,
 	.probe		= synclinkmp_init_one,
-	.remove		= __devexit_p(synclinkmp_remove_one),
+	.remove		= synclinkmp_remove_one,
 };
 
 
@@ -3843,8 +3843,10 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
 	for ( port = 0; port < SCA_MAX_PORTS; ++port ) {
 		port_array[port] = alloc_dev(adapter_num,port,pdev);
 		if( port_array[port] == NULL ) {
-			for ( --port; port >= 0; --port )
+			for (--port; port >= 0; --port) {
+				tty_port_destroy(&port_array[port]->port);
 				kfree(port_array[port]);
+			}
 			return;
 		}
 	}
@@ -3953,6 +3955,7 @@ static void synclinkmp_cleanup(void)
 		}
 		tmp = info;
 		info = info->next_device;
+		tty_port_destroy(&tmp->port);
 		kfree(tmp);
 	}
 
@@ -5592,7 +5595,7 @@ static void write_control_reg(SLMP_INFO * info)
 }
 
 
-static int __devinit synclinkmp_init_one (struct pci_dev *dev,
+static int synclinkmp_init_one (struct pci_dev *dev,
 					  const struct pci_device_id *ent)
 {
 	if (pci_enable_device(dev)) {
@@ -5603,6 +5606,6 @@ static int __devinit synclinkmp_init_one (struct pci_dev *dev,
 	return 0;
 }
 
-static void __devexit synclinkmp_remove_one (struct pci_dev *dev)
+static void synclinkmp_remove_one (struct pci_dev *dev)
 {
 }
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 16ee6ce..b3c4a25 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -346,7 +346,8 @@ static struct sysrq_key_op sysrq_term_op = {
 
 static void moom_callback(struct work_struct *ignored)
 {
-	out_of_memory(node_zonelist(0, GFP_KERNEL), GFP_KERNEL, 0, NULL, true);
+	out_of_memory(node_zonelist(first_online_node, GFP_KERNEL), GFP_KERNEL,
+		      0, NULL, true);
 }
 
 static DECLARE_WORK(moom_work, moom_callback);
diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
index b0b39b8..6953dc8 100644
--- a/drivers/tty/tty_audit.c
+++ b/drivers/tty/tty_audit.c
@@ -23,7 +23,7 @@ struct tty_audit_buf {
 };
 
 static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor,
-						 int icanon)
+						 unsigned icanon)
 {
 	struct tty_audit_buf *buf;
 
@@ -239,7 +239,8 @@ int tty_audit_push_task(struct task_struct *tsk, kuid_t loginuid, u32 sessionid)
  *	if TTY auditing is disabled or out of memory.  Otherwise, return a new
  *	reference to the buffer.
  */
-static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
+static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
+		unsigned icanon)
 {
 	struct tty_audit_buf *buf, *buf2;
 
@@ -257,7 +258,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
 
 	buf2 = tty_audit_buf_alloc(tty->driver->major,
 				   tty->driver->minor_start + tty->index,
-				   tty->icanon);
+				   icanon);
 	if (buf2 == NULL) {
 		audit_log_lost("out of memory in TTY auditing");
 		return NULL;
@@ -287,7 +288,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
  *	Audit @data of @size from @tty, if necessary.
  */
 void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
-			size_t size)
+			size_t size, unsigned icanon)
 {
 	struct tty_audit_buf *buf;
 	int major, minor;
@@ -299,7 +300,7 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
 	    && tty->driver->subtype == PTY_TYPE_MASTER)
 		return;
 
-	buf = tty_audit_buf_get(tty);
+	buf = tty_audit_buf_get(tty, icanon);
 	if (!buf)
 		return;
 
@@ -307,11 +308,11 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
 	major = tty->driver->major;
 	minor = tty->driver->minor_start + tty->index;
 	if (buf->major != major || buf->minor != minor
-	    || buf->icanon != tty->icanon) {
+	    || buf->icanon != icanon) {
 		tty_audit_buf_push_current(buf);
 		buf->major = major;
 		buf->minor = minor;
-		buf->icanon = tty->icanon;
+		buf->icanon = icanon;
 	}
 	do {
 		size_t run;
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 91e326f..45d9161 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -27,19 +27,21 @@
  *	Locking: none
  */
 
-void tty_buffer_free_all(struct tty_struct *tty)
+void tty_buffer_free_all(struct tty_port *port)
 {
+	struct tty_bufhead *buf = &port->buf;
 	struct tty_buffer *thead;
-	while ((thead = tty->buf.head) != NULL) {
-		tty->buf.head = thead->next;
+
+	while ((thead = buf->head) != NULL) {
+		buf->head = thead->next;
 		kfree(thead);
 	}
-	while ((thead = tty->buf.free) != NULL) {
-		tty->buf.free = thead->next;
+	while ((thead = buf->free) != NULL) {
+		buf->free = thead->next;
 		kfree(thead);
 	}
-	tty->buf.tail = NULL;
-	tty->buf.memory_used = 0;
+	buf->tail = NULL;
+	buf->memory_used = 0;
 }
 
 /**
@@ -54,11 +56,11 @@ void tty_buffer_free_all(struct tty_struct *tty)
  *	Locking: Caller must hold tty->buf.lock
  */
 
-static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
+static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size)
 {
 	struct tty_buffer *p;
 
-	if (tty->buf.memory_used + size > 65536)
+	if (port->buf.memory_used + size > 65536)
 		return NULL;
 	p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
 	if (p == NULL)
@@ -70,7 +72,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
 	p->read = 0;
 	p->char_buf_ptr = (char *)(p->data);
 	p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
-	tty->buf.memory_used += size;
+	port->buf.memory_used += size;
 	return p;
 }
 
@@ -85,17 +87,19 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
  *	Locking: Caller must hold tty->buf.lock
  */
 
-static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
+static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b)
 {
+	struct tty_bufhead *buf = &port->buf;
+
 	/* Dumb strategy for now - should keep some stats */
-	tty->buf.memory_used -= b->size;
-	WARN_ON(tty->buf.memory_used < 0);
+	buf->memory_used -= b->size;
+	WARN_ON(buf->memory_used < 0);
 
 	if (b->size >= 512)
 		kfree(b);
 	else {
-		b->next = tty->buf.free;
-		tty->buf.free = b;
+		b->next = buf->free;
+		buf->free = b;
 	}
 }
 
@@ -110,15 +114,16 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
  *	Locking: Caller must hold tty->buf.lock
  */
 
-static void __tty_buffer_flush(struct tty_struct *tty)
+static void __tty_buffer_flush(struct tty_port *port)
 {
+	struct tty_bufhead *buf = &port->buf;
 	struct tty_buffer *thead;
 
-	while ((thead = tty->buf.head) != NULL) {
-		tty->buf.head = thead->next;
-		tty_buffer_free(tty, thead);
+	while ((thead = buf->head) != NULL) {
+		buf->head = thead->next;
+		tty_buffer_free(port, thead);
 	}
-	tty->buf.tail = NULL;
+	buf->tail = NULL;
 }
 
 /**
@@ -134,21 +139,24 @@ static void __tty_buffer_flush(struct tty_struct *tty)
 
 void tty_buffer_flush(struct tty_struct *tty)
 {
+	struct tty_port *port = tty->port;
+	struct tty_bufhead *buf = &port->buf;
 	unsigned long flags;
-	spin_lock_irqsave(&tty->buf.lock, flags);
+
+	spin_lock_irqsave(&buf->lock, flags);
 
 	/* If the data is being pushed to the tty layer then we can't
 	   process it here. Instead set a flag and the flush_to_ldisc
 	   path will process the flush request before it exits */
-	if (test_bit(TTY_FLUSHING, &tty->flags)) {
-		set_bit(TTY_FLUSHPENDING, &tty->flags);
-		spin_unlock_irqrestore(&tty->buf.lock, flags);
+	if (test_bit(TTYP_FLUSHING, &port->iflags)) {
+		set_bit(TTYP_FLUSHPENDING, &port->iflags);
+		spin_unlock_irqrestore(&buf->lock, flags);
 		wait_event(tty->read_wait,
-				test_bit(TTY_FLUSHPENDING, &tty->flags) == 0);
+				test_bit(TTYP_FLUSHPENDING, &port->iflags) == 0);
 		return;
 	} else
-		__tty_buffer_flush(tty);
-	spin_unlock_irqrestore(&tty->buf.lock, flags);
+		__tty_buffer_flush(port);
+	spin_unlock_irqrestore(&buf->lock, flags);
 }
 
 /**
@@ -163,9 +171,9 @@ void tty_buffer_flush(struct tty_struct *tty)
  *	Locking: Caller must hold tty->buf.lock
  */
 
-static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
+static struct tty_buffer *tty_buffer_find(struct tty_port *port, size_t size)
 {
-	struct tty_buffer **tbh = &tty->buf.free;
+	struct tty_buffer **tbh = &port->buf.free;
 	while ((*tbh) != NULL) {
 		struct tty_buffer *t = *tbh;
 		if (t->size >= size) {
@@ -174,14 +182,14 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
 			t->used = 0;
 			t->commit = 0;
 			t->read = 0;
-			tty->buf.memory_used += t->size;
+			port->buf.memory_used += t->size;
 			return t;
 		}
 		tbh = &((*tbh)->next);
 	}
 	/* Round the buffer size out */
 	size = (size + 0xFF) & ~0xFF;
-	return tty_buffer_alloc(tty, size);
+	return tty_buffer_alloc(port, size);
 	/* Should possibly check if this fails for the largest buffer we
 	   have queued and recycle that ? */
 }
@@ -192,29 +200,31 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
  *
  *	Make at least size bytes of linear space available for the tty
  *	buffer. If we fail return the size we managed to find.
- *      Locking: Caller must hold tty->buf.lock
+ *      Locking: Caller must hold port->buf.lock
  */
-static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)
+static int __tty_buffer_request_room(struct tty_port *port, size_t size)
 {
+	struct tty_bufhead *buf = &port->buf;
 	struct tty_buffer *b, *n;
 	int left;
 	/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
 	   remove this conditional if its worth it. This would be invisible
 	   to the callers */
-	if ((b = tty->buf.tail) != NULL)
+	b = buf->tail;
+	if (b != NULL)
 		left = b->size - b->used;
 	else
 		left = 0;
 
 	if (left < size) {
 		/* This is the slow path - looking for new buffers to use */
-		if ((n = tty_buffer_find(tty, size)) != NULL) {
+		if ((n = tty_buffer_find(port, size)) != NULL) {
 			if (b != NULL) {
 				b->next = n;
 				b->commit = b->used;
 			} else
-				tty->buf.head = n;
-			tty->buf.tail = n;
+				buf->head = n;
+			buf->tail = n;
 		} else
 			size = left;
 	}
@@ -231,16 +241,17 @@ static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)
  *	Make at least size bytes of linear space available for the tty
  *	buffer. If we fail return the size we managed to find.
  *
- *	Locking: Takes tty->buf.lock
+ *	Locking: Takes port->buf.lock
  */
 int tty_buffer_request_room(struct tty_struct *tty, size_t size)
 {
+	struct tty_port *port = tty->port;
 	unsigned long flags;
 	int length;
 
-	spin_lock_irqsave(&tty->buf.lock, flags);
-	length = __tty_buffer_request_room(tty, size);
-	spin_unlock_irqrestore(&tty->buf.lock, flags);
+	spin_lock_irqsave(&port->buf.lock, flags);
+	length = __tty_buffer_request_room(port, size);
+	spin_unlock_irqrestore(&port->buf.lock, flags);
 	return length;
 }
 EXPORT_SYMBOL_GPL(tty_buffer_request_room);
@@ -255,12 +266,13 @@ EXPORT_SYMBOL_GPL(tty_buffer_request_room);
  *	Queue a series of bytes to the tty buffering. All the characters
  *	passed are marked with the supplied flag. Returns the number added.
  *
- *	Locking: Called functions may take tty->buf.lock
+ *	Locking: Called functions may take port->buf.lock
  */
 
 int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
 		const unsigned char *chars, char flag, size_t size)
 {
+	struct tty_bufhead *buf = &tty->port->buf;
 	int copied = 0;
 	do {
 		int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
@@ -268,18 +280,18 @@ int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
 		unsigned long flags;
 		struct tty_buffer *tb;
 
-		spin_lock_irqsave(&tty->buf.lock, flags);
-		space = __tty_buffer_request_room(tty, goal);
-		tb = tty->buf.tail;
+		spin_lock_irqsave(&buf->lock, flags);
+		space = __tty_buffer_request_room(tty->port, goal);
+		tb = buf->tail;
 		/* If there is no space then tb may be NULL */
 		if (unlikely(space == 0)) {
-			spin_unlock_irqrestore(&tty->buf.lock, flags);
+			spin_unlock_irqrestore(&buf->lock, flags);
 			break;
 		}
 		memcpy(tb->char_buf_ptr + tb->used, chars, space);
 		memset(tb->flag_buf_ptr + tb->used, flag, space);
 		tb->used += space;
-		spin_unlock_irqrestore(&tty->buf.lock, flags);
+		spin_unlock_irqrestore(&buf->lock, flags);
 		copied += space;
 		chars += space;
 		/* There is a small chance that we need to split the data over
@@ -300,12 +312,13 @@ EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag);
  *	the flags array indicates the status of the character. Returns the
  *	number added.
  *
- *	Locking: Called functions may take tty->buf.lock
+ *	Locking: Called functions may take port->buf.lock
  */
 
 int tty_insert_flip_string_flags(struct tty_struct *tty,
 		const unsigned char *chars, const char *flags, size_t size)
 {
+	struct tty_bufhead *buf = &tty->port->buf;
 	int copied = 0;
 	do {
 		int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
@@ -313,18 +326,18 @@ int tty_insert_flip_string_flags(struct tty_struct *tty,
 		unsigned long __flags;
 		struct tty_buffer *tb;
 
-		spin_lock_irqsave(&tty->buf.lock, __flags);
-		space = __tty_buffer_request_room(tty, goal);
-		tb = tty->buf.tail;
+		spin_lock_irqsave(&buf->lock, __flags);
+		space = __tty_buffer_request_room(tty->port, goal);
+		tb = buf->tail;
 		/* If there is no space then tb may be NULL */
 		if (unlikely(space == 0)) {
-			spin_unlock_irqrestore(&tty->buf.lock, __flags);
+			spin_unlock_irqrestore(&buf->lock, __flags);
 			break;
 		}
 		memcpy(tb->char_buf_ptr + tb->used, chars, space);
 		memcpy(tb->flag_buf_ptr + tb->used, flags, space);
 		tb->used += space;
-		spin_unlock_irqrestore(&tty->buf.lock, __flags);
+		spin_unlock_irqrestore(&buf->lock, __flags);
 		copied += space;
 		chars += space;
 		flags += space;
@@ -342,18 +355,23 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags);
  *	Takes any pending buffers and transfers their ownership to the
  *	ldisc side of the queue. It then schedules those characters for
  *	processing by the line discipline.
+ *	Note that this function can only be used when the low_latency flag
+ *	is unset. Otherwise the workqueue won't be flushed.
  *
- *	Locking: Takes tty->buf.lock
+ *	Locking: Takes port->buf.lock
  */
 
 void tty_schedule_flip(struct tty_struct *tty)
 {
+	struct tty_bufhead *buf = &tty->port->buf;
 	unsigned long flags;
-	spin_lock_irqsave(&tty->buf.lock, flags);
-	if (tty->buf.tail != NULL)
-		tty->buf.tail->commit = tty->buf.tail->used;
-	spin_unlock_irqrestore(&tty->buf.lock, flags);
-	schedule_work(&tty->buf.work);
+	WARN_ON(tty->low_latency);
+
+	spin_lock_irqsave(&buf->lock, flags);
+	if (buf->tail != NULL)
+		buf->tail->commit = buf->tail->used;
+	spin_unlock_irqrestore(&buf->lock, flags);
+	schedule_work(&buf->work);
 }
 EXPORT_SYMBOL(tty_schedule_flip);
 
@@ -369,26 +387,27 @@ EXPORT_SYMBOL(tty_schedule_flip);
  *	that need their own block copy routines into the buffer. There is no
  *	guarantee the buffer is a DMA target!
  *
- *	Locking: May call functions taking tty->buf.lock
+ *	Locking: May call functions taking port->buf.lock
  */
 
 int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars,
-								size_t size)
+		size_t size)
 {
+	struct tty_bufhead *buf = &tty->port->buf;
 	int space;
 	unsigned long flags;
 	struct tty_buffer *tb;
 
-	spin_lock_irqsave(&tty->buf.lock, flags);
-	space = __tty_buffer_request_room(tty, size);
+	spin_lock_irqsave(&buf->lock, flags);
+	space = __tty_buffer_request_room(tty->port, size);
 
-	tb = tty->buf.tail;
+	tb = buf->tail;
 	if (likely(space)) {
 		*chars = tb->char_buf_ptr + tb->used;
 		memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
 		tb->used += space;
 	}
-	spin_unlock_irqrestore(&tty->buf.lock, flags);
+	spin_unlock_irqrestore(&buf->lock, flags);
 	return space;
 }
 EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
@@ -406,26 +425,27 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
  *	that need their own block copy routines into the buffer. There is no
  *	guarantee the buffer is a DMA target!
  *
- *	Locking: May call functions taking tty->buf.lock
+ *	Locking: May call functions taking port->buf.lock
  */
 
 int tty_prepare_flip_string_flags(struct tty_struct *tty,
 			unsigned char **chars, char **flags, size_t size)
 {
+	struct tty_bufhead *buf = &tty->port->buf;
 	int space;
 	unsigned long __flags;
 	struct tty_buffer *tb;
 
-	spin_lock_irqsave(&tty->buf.lock, __flags);
-	space = __tty_buffer_request_room(tty, size);
+	spin_lock_irqsave(&buf->lock, __flags);
+	space = __tty_buffer_request_room(tty->port, size);
 
-	tb = tty->buf.tail;
+	tb = buf->tail;
 	if (likely(space)) {
 		*chars = tb->char_buf_ptr + tb->used;
 		*flags = tb->flag_buf_ptr + tb->used;
 		tb->used += space;
 	}
-	spin_unlock_irqrestore(&tty->buf.lock, __flags);
+	spin_unlock_irqrestore(&buf->lock, __flags);
 	return space;
 }
 EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
@@ -446,20 +466,25 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
 
 static void flush_to_ldisc(struct work_struct *work)
 {
-	struct tty_struct *tty =
-		container_of(work, struct tty_struct, buf.work);
+	struct tty_port *port = container_of(work, struct tty_port, buf.work);
+	struct tty_bufhead *buf = &port->buf;
+	struct tty_struct *tty;
 	unsigned long 	flags;
 	struct tty_ldisc *disc;
 
+	tty = port->itty;
+	if (WARN_RATELIMIT(tty == NULL, "tty is NULL\n"))
+		return;
+
 	disc = tty_ldisc_ref(tty);
 	if (disc == NULL)	/*  !TTY_LDISC */
 		return;
 
-	spin_lock_irqsave(&tty->buf.lock, flags);
+	spin_lock_irqsave(&buf->lock, flags);
 
-	if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) {
+	if (!test_and_set_bit(TTYP_FLUSHING, &port->iflags)) {
 		struct tty_buffer *head;
-		while ((head = tty->buf.head) != NULL) {
+		while ((head = buf->head) != NULL) {
 			int count;
 			char *char_buf;
 			unsigned char *flag_buf;
@@ -468,14 +493,14 @@ static void flush_to_ldisc(struct work_struct *work)
 			if (!count) {
 				if (head->next == NULL)
 					break;
-				tty->buf.head = head->next;
-				tty_buffer_free(tty, head);
+				buf->head = head->next;
+				tty_buffer_free(port, head);
 				continue;
 			}
 			/* Ldisc or user is trying to flush the buffers
 			   we are feeding to the ldisc, stop feeding the
 			   line discipline as we want to empty the queue */
-			if (test_bit(TTY_FLUSHPENDING, &tty->flags))
+			if (test_bit(TTYP_FLUSHPENDING, &port->iflags))
 				break;
 			if (!tty->receive_room)
 				break;
@@ -484,22 +509,22 @@ static void flush_to_ldisc(struct work_struct *work)
 			char_buf = head->char_buf_ptr + head->read;
 			flag_buf = head->flag_buf_ptr + head->read;
 			head->read += count;
-			spin_unlock_irqrestore(&tty->buf.lock, flags);
+			spin_unlock_irqrestore(&buf->lock, flags);
 			disc->ops->receive_buf(tty, char_buf,
 							flag_buf, count);
-			spin_lock_irqsave(&tty->buf.lock, flags);
+			spin_lock_irqsave(&buf->lock, flags);
 		}
-		clear_bit(TTY_FLUSHING, &tty->flags);
+		clear_bit(TTYP_FLUSHING, &port->iflags);
 	}
 
 	/* We may have a deferred request to flush the input buffer,
 	   if so pull the chain under the lock and empty the queue */
-	if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
-		__tty_buffer_flush(tty);
-		clear_bit(TTY_FLUSHPENDING, &tty->flags);
+	if (test_bit(TTYP_FLUSHPENDING, &port->iflags)) {
+		__tty_buffer_flush(port);
+		clear_bit(TTYP_FLUSHPENDING, &port->iflags);
 		wake_up(&tty->read_wait);
 	}
-	spin_unlock_irqrestore(&tty->buf.lock, flags);
+	spin_unlock_irqrestore(&buf->lock, flags);
 
 	tty_ldisc_deref(disc);
 }
@@ -514,7 +539,8 @@ static void flush_to_ldisc(struct work_struct *work)
  */
 void tty_flush_to_ldisc(struct tty_struct *tty)
 {
-	flush_work(&tty->buf.work);
+	if (!tty->low_latency)
+		flush_work(&tty->port->buf.work);
 }
 
 /**
@@ -532,16 +558,18 @@ void tty_flush_to_ldisc(struct tty_struct *tty)
 
 void tty_flip_buffer_push(struct tty_struct *tty)
 {
+	struct tty_bufhead *buf = &tty->port->buf;
 	unsigned long flags;
-	spin_lock_irqsave(&tty->buf.lock, flags);
-	if (tty->buf.tail != NULL)
-		tty->buf.tail->commit = tty->buf.tail->used;
-	spin_unlock_irqrestore(&tty->buf.lock, flags);
+
+	spin_lock_irqsave(&buf->lock, flags);
+	if (buf->tail != NULL)
+		buf->tail->commit = buf->tail->used;
+	spin_unlock_irqrestore(&buf->lock, flags);
 
 	if (tty->low_latency)
-		flush_to_ldisc(&tty->buf.work);
+		flush_to_ldisc(&buf->work);
 	else
-		schedule_work(&tty->buf.work);
+		schedule_work(&buf->work);
 }
 EXPORT_SYMBOL(tty_flip_buffer_push);
 
@@ -555,13 +583,15 @@ EXPORT_SYMBOL(tty_flip_buffer_push);
  *	Locking: none
  */
 
-void tty_buffer_init(struct tty_struct *tty)
+void tty_buffer_init(struct tty_port *port)
 {
-	spin_lock_init(&tty->buf.lock);
-	tty->buf.head = NULL;
-	tty->buf.tail = NULL;
-	tty->buf.free = NULL;
-	tty->buf.memory_used = 0;
-	INIT_WORK(&tty->buf.work, flush_to_ldisc);
+	struct tty_bufhead *buf = &port->buf;
+
+	spin_lock_init(&buf->lock);
+	buf->head = NULL;
+	buf->tail = NULL;
+	buf->free = NULL;
+	buf->memory_used = 0;
+	INIT_WORK(&buf->work, flush_to_ldisc);
 }
 
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 2ea176b..da9fde8 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -186,7 +186,6 @@ void free_tty_struct(struct tty_struct *tty)
 	if (tty->dev)
 		put_device(tty->dev);
 	kfree(tty->write_buf);
-	tty_buffer_free_all(tty);
 	tty->magic = 0xDEADDEAD;
 	kfree(tty);
 }
@@ -237,7 +236,7 @@ void tty_free_file(struct file *file)
 }
 
 /* Delete file from its tty */
-void tty_del_file(struct file *file)
+static void tty_del_file(struct file *file)
 {
 	struct tty_file_private *priv = file->private_data;
 
@@ -555,7 +554,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup);
  *		  tasklist_lock to walk task list for hangup event
  *		    ->siglock to protect ->signal/->sighand
  */
-void __tty_hangup(struct tty_struct *tty)
+static void __tty_hangup(struct tty_struct *tty)
 {
 	struct file *cons_filp = NULL;
 	struct file *filp, *f = NULL;
@@ -1417,6 +1416,8 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
 			"%s: %s driver does not set tty->port. This will crash the kernel later. Fix the driver!\n",
 			__func__, tty->driver->name);
 
+	tty->port->itty = tty;
+
 	/*
 	 * Structures all installed ... call the ldisc open routines.
 	 * If we fail here just call release_tty to clean up.  No need
@@ -1552,6 +1553,7 @@ static void release_tty(struct tty_struct *tty, int idx)
 		tty->ops->shutdown(tty);
 	tty_free_termios(tty);
 	tty_driver_remove_tty(tty->driver, tty);
+	tty->port->itty = NULL;
 
 	if (tty->link)
 		tty_kref_put(tty->link);
@@ -1625,7 +1627,6 @@ int tty_release(struct inode *inode, struct file *filp)
 	struct tty_struct *tty = file_tty(filp);
 	struct tty_struct *o_tty;
 	int	pty_master, tty_closing, o_tty_closing, do_sleep;
-	int	devpts;
 	int	idx;
 	char	buf[64];
 
@@ -1640,7 +1641,6 @@ int tty_release(struct inode *inode, struct file *filp)
 	idx = tty->index;
 	pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
 		      tty->driver->subtype == PTY_TYPE_MASTER);
-	devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
 	/* Review: parallel close */
 	o_tty = tty->link;
 
@@ -1799,9 +1799,6 @@ int tty_release(struct inode *inode, struct file *filp)
 	release_tty(tty, idx);
 	mutex_unlock(&tty_mutex);
 
-	/* Make this pty number available for reallocation */
-	if (devpts)
-		devpts_kill_index(inode, idx);
 	return 0;
 }
 
@@ -2690,6 +2687,11 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	case TIOCNXCL:
 		clear_bit(TTY_EXCLUSIVE, &tty->flags);
 		return 0;
+	case TIOCGEXCL:
+	{
+		int excl = test_bit(TTY_EXCLUSIVE, &tty->flags);
+		return put_user(excl, (int __user *)p);
+	}
 	case TIOCNOTTY:
 		if (current->signal->tty != tty)
 			return -ENOTTY;
@@ -2937,19 +2939,13 @@ void initialize_tty_struct(struct tty_struct *tty,
 	tty_ldisc_init(tty);
 	tty->session = NULL;
 	tty->pgrp = NULL;
-	tty->overrun_time = jiffies;
-	tty_buffer_init(tty);
 	mutex_init(&tty->legacy_mutex);
 	mutex_init(&tty->termios_mutex);
 	mutex_init(&tty->ldisc_mutex);
 	init_waitqueue_head(&tty->write_wait);
 	init_waitqueue_head(&tty->read_wait);
 	INIT_WORK(&tty->hangup_work, do_tty_hangup);
-	mutex_init(&tty->atomic_read_lock);
 	mutex_init(&tty->atomic_write_lock);
-	mutex_init(&tty->output_lock);
-	mutex_init(&tty->echo_lock);
-	spin_lock_init(&tty->read_lock);
 	spin_lock_init(&tty->ctrl_lock);
 	INIT_LIST_HEAD(&tty->tty_files);
 	INIT_WORK(&tty->SAK_work, do_SAK_work);
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index 12b1fa0..8481b29 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -1118,7 +1118,6 @@ EXPORT_SYMBOL_GPL(tty_perform_flush);
 int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
 		       unsigned int cmd, unsigned long arg)
 {
-	unsigned long flags;
 	int retval;
 
 	switch (cmd) {
@@ -1153,26 +1152,6 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
 		return 0;
 	case TCFLSH:
 		return tty_perform_flush(tty, arg);
-	case TIOCPKT:
-	{
-		int pktmode;
-
-		if (tty->driver->type != TTY_DRIVER_TYPE_PTY ||
-		    tty->driver->subtype != PTY_TYPE_MASTER)
-			return -ENOTTY;
-		if (get_user(pktmode, (int __user *) arg))
-			return -EFAULT;
-		spin_lock_irqsave(&tty->ctrl_lock, flags);
-		if (pktmode) {
-			if (!tty->packet) {
-				tty->packet = 1;
-				tty->link->ctrl_status = 0;
-			}
-		} else
-			tty->packet = 0;
-		spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-		return 0;
-	}
 	default:
 		/* Try the mode commands */
 		return tty_mode_ioctl(tty, file, cmd, arg);
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 0f2a2c5..c578229 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -26,7 +26,7 @@
  *	callers who will do ldisc lookups and cannot sleep.
  */
 
-static DEFINE_SPINLOCK(tty_ldisc_lock);
+static DEFINE_RAW_SPINLOCK(tty_ldisc_lock);
 static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
 /* Line disc dispatch table */
 static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
@@ -49,21 +49,21 @@ static void put_ldisc(struct tty_ldisc *ld)
 	 * If this is the last user, free the ldisc, and
 	 * release the ldisc ops.
 	 *
-	 * We really want an "atomic_dec_and_lock_irqsave()",
+	 * We really want an "atomic_dec_and_raw_lock_irqsave()",
 	 * but we don't have it, so this does it by hand.
 	 */
-	local_irq_save(flags);
-	if (atomic_dec_and_lock(&ld->users, &tty_ldisc_lock)) {
+	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
+	if (atomic_dec_and_test(&ld->users)) {
 		struct tty_ldisc_ops *ldo = ld->ops;
 
 		ldo->refcount--;
 		module_put(ldo->owner);
-		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+		raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 
 		kfree(ld);
 		return;
 	}
-	local_irq_restore(flags);
+	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 	wake_up(&ld->wq_idle);
 }
 
@@ -88,11 +88,11 @@ int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
 	if (disc < N_TTY || disc >= NR_LDISCS)
 		return -EINVAL;
 
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
 	tty_ldiscs[disc] = new_ldisc;
 	new_ldisc->num = disc;
 	new_ldisc->refcount = 0;
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 
 	return ret;
 }
@@ -118,12 +118,12 @@ int tty_unregister_ldisc(int disc)
 	if (disc < N_TTY || disc >= NR_LDISCS)
 		return -EINVAL;
 
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
 	if (tty_ldiscs[disc]->refcount)
 		ret = -EBUSY;
 	else
 		tty_ldiscs[disc] = NULL;
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 
 	return ret;
 }
@@ -134,7 +134,7 @@ static struct tty_ldisc_ops *get_ldops(int disc)
 	unsigned long flags;
 	struct tty_ldisc_ops *ldops, *ret;
 
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
 	ret = ERR_PTR(-EINVAL);
 	ldops = tty_ldiscs[disc];
 	if (ldops) {
@@ -144,7 +144,7 @@ static struct tty_ldisc_ops *get_ldops(int disc)
 			ret = ldops;
 		}
 	}
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 	return ret;
 }
 
@@ -152,10 +152,10 @@ static void put_ldops(struct tty_ldisc_ops *ldops)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
 	ldops->refcount--;
 	module_put(ldops->owner);
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 }
 
 /**
@@ -287,11 +287,11 @@ static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty)
 	unsigned long flags;
 	struct tty_ldisc *ld;
 
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
 	ld = NULL;
 	if (test_bit(TTY_LDISC, &tty->flags))
 		ld = get_ldisc(tty->ldisc);
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 	return ld;
 }
 
@@ -512,7 +512,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
 static int tty_ldisc_halt(struct tty_struct *tty)
 {
 	clear_bit(TTY_LDISC, &tty->flags);
-	return cancel_work_sync(&tty->buf.work);
+	return cancel_work_sync(&tty->port->buf.work);
 }
 
 /**
@@ -525,7 +525,7 @@ static void tty_ldisc_flush_works(struct tty_struct *tty)
 {
 	flush_work(&tty->hangup_work);
 	flush_work(&tty->SAK_work);
-	flush_work(&tty->buf.work);
+	flush_work(&tty->port->buf.work);
 }
 
 /**
@@ -704,9 +704,9 @@ enable:
 	/* Restart the work queue in case no characters kick it off. Safe if
 	   already running */
 	if (work)
-		schedule_work(&tty->buf.work);
+		schedule_work(&tty->port->buf.work);
 	if (o_work)
-		schedule_work(&o_tty->buf.work);
+		schedule_work(&o_tty->port->buf.work);
 	mutex_unlock(&tty->ldisc_mutex);
 	tty_unlock(tty);
 	return retval;
@@ -817,7 +817,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
 	 */
 	clear_bit(TTY_LDISC, &tty->flags);
 	tty_unlock(tty);
-	cancel_work_sync(&tty->buf.work);
+	cancel_work_sync(&tty->port->buf.work);
 	mutex_unlock(&tty->ldisc_mutex);
 retry:
 	tty_lock(tty);
@@ -897,6 +897,11 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
 
 static void tty_ldisc_kill(struct tty_struct *tty)
 {
+	/* There cannot be users from userspace now. But there still might be
+	 * drivers holding a reference via tty_ldisc_ref. Do not steal them the
+	 * ldisc until they are done. */
+	tty_ldisc_wait_idle(tty, MAX_SCHEDULE_TIMEOUT);
+
 	mutex_lock(&tty->ldisc_mutex);
 	/*
 	 * Now kill off the ldisc
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c
index 67feac9..2e41abe 100644
--- a/drivers/tty/tty_mutex.c
+++ b/drivers/tty/tty_mutex.c
@@ -19,7 +19,7 @@ static void __lockfunc tty_lock_nested(struct tty_struct *tty,
 				       unsigned int subclass)
 {
 	if (tty->magic != TTY_MAGIC) {
-		printk(KERN_ERR "L Bad %p\n", tty);
+		pr_err("L Bad %p\n", tty);
 		WARN_ON(1);
 		return;
 	}
@@ -36,7 +36,7 @@ EXPORT_SYMBOL(tty_lock);
 void __lockfunc tty_unlock(struct tty_struct *tty)
 {
 	if (tty->magic != TTY_MAGIC) {
-		printk(KERN_ERR "U Bad %p\n", tty);
+		pr_err("U Bad %p\n", tty);
 		WARN_ON(1);
 		return;
 	}
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index d7bdd8d..b7ff59d 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -21,6 +21,7 @@
 void tty_port_init(struct tty_port *port)
 {
 	memset(port, 0, sizeof(*port));
+	tty_buffer_init(port);
 	init_waitqueue_head(&port->open_wait);
 	init_waitqueue_head(&port->close_wait);
 	init_waitqueue_head(&port->delta_msr_wait);
@@ -121,12 +122,27 @@ void tty_port_free_xmit_buf(struct tty_port *port)
 }
 EXPORT_SYMBOL(tty_port_free_xmit_buf);
 
+/**
+ * tty_port_destroy -- destroy inited port
+ * @port: tty port to be doestroyed
+ *
+ * When a port was initialized using tty_port_init, one has to destroy the
+ * port by this function. Either indirectly by using tty_port refcounting
+ * (tty_port_put) or directly if refcounting is not used.
+ */
+void tty_port_destroy(struct tty_port *port)
+{
+	tty_buffer_free_all(port);
+}
+EXPORT_SYMBOL(tty_port_destroy);
+
 static void tty_port_destructor(struct kref *kref)
 {
 	struct tty_port *port = container_of(kref, struct tty_port, kref);
 	if (port->xmit_buf)
 		free_page((unsigned long)port->xmit_buf);
-	if (port->ops->destruct)
+	tty_port_destroy(port);
+	if (port->ops && port->ops->destruct)
 		port->ops->destruct(port);
 	else
 		kfree(port);
diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c
index 2aaa0c2..248381b 100644
--- a/drivers/tty/vt/consolemap.c
+++ b/drivers/tty/vt/consolemap.c
@@ -410,10 +410,8 @@ static void con_release_unimap(struct uni_pagedir *p)
 		kfree(p->inverse_translations[i]);
 		p->inverse_translations[i] = NULL;
 	}
-	if (p->inverse_trans_unicode) {
-		kfree(p->inverse_trans_unicode);
-		p->inverse_trans_unicode = NULL;
-	}
+	kfree(p->inverse_trans_unicode);
+	p->inverse_trans_unicode = NULL;
 }
 
 /* Caller must hold the console lock */
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 8e9b4be..60b7b69 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -341,15 +341,11 @@ int paste_selection(struct tty_struct *tty)
 	struct  tty_ldisc *ld;
 	DECLARE_WAITQUEUE(wait, current);
 
-
 	console_lock();
 	poke_blanked_console();
 	console_unlock();
 
-	/* FIXME: wtf is this supposed to achieve ? */
-	ld = tty_ldisc_ref(tty);
-	if (!ld)
-		ld = tty_ldisc_ref_wait(tty);
+	ld = tty_ldisc_ref_wait(tty);
 
 	/* FIXME: this is completely unsafe */
 	add_wait_queue(&vc->paste_wait, &wait);
@@ -361,8 +357,7 @@ int paste_selection(struct tty_struct *tty)
 		}
 		count = sel_buffer_lth - pasted;
 		count = min(count, tty->receive_room);
-		tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted,
-								NULL, count);
+		ld->ops->receive_buf(tty, sel_buffer + pasted, NULL, count);
 		pasted += count;
 	}
 	remove_wait_queue(&vc->paste_wait, &wait);
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index f87d7e8..8fd8968 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -539,25 +539,25 @@ static void insert_char(struct vc_data *vc, unsigned int nr)
 {
 	unsigned short *p = (unsigned short *) vc->vc_pos;
 
-	scr_memmovew(p + nr, p, vc->vc_cols - vc->vc_x);
+	scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x) * 2);
 	scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
 	vc->vc_need_wrap = 0;
 	if (DO_UPDATE(vc))
 		do_update_region(vc, (unsigned long) p,
-			(vc->vc_cols - vc->vc_x) / 2 + 1);
+			vc->vc_cols - vc->vc_x);
 }
 
 static void delete_char(struct vc_data *vc, unsigned int nr)
 {
 	unsigned short *p = (unsigned short *) vc->vc_pos;
 
-	scr_memcpyw(p, p + nr, vc->vc_cols - vc->vc_x - nr);
+	scr_memcpyw(p, p + nr, (vc->vc_cols - vc->vc_x - nr) * 2);
 	scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char,
 			nr * 2);
 	vc->vc_need_wrap = 0;
 	if (DO_UPDATE(vc))
 		do_update_region(vc, (unsigned long) p,
-			(vc->vc_cols - vc->vc_x) / 2);
+			vc->vc_cols - vc->vc_x);
 }
 
 static int softcursor_original;
@@ -779,6 +779,7 @@ int vc_allocate(unsigned int currcons)	/* return 0 on success */
 		con_set_default_unimap(vc);
 	    vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
 	    if (!vc->vc_screenbuf) {
+		tty_port_destroy(&vc->port);
 		kfree(vc);
 		vc_cons[currcons].d = NULL;
 		return -ENOMEM;
@@ -999,8 +1000,10 @@ void vc_deallocate(unsigned int currcons)
 		put_pid(vc->vt_pid);
 		module_put(vc->vc_sw->owner);
 		kfree(vc->vc_screenbuf);
-		if (currcons >= MIN_NR_CONSOLES)
+		if (currcons >= MIN_NR_CONSOLES) {
+			tty_port_destroy(&vc->port);
 			kfree(vc);
+		}
 		vc_cons[currcons].d = NULL;
 	}
 }
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index b841f56..98ff173 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -25,6 +25,7 @@
 #include <linux/console.h>
 #include <linux/consolemap.h>
 #include <linux/signal.h>
+#include <linux/suspend.h>
 #include <linux/timex.h>
 
 #include <asm/io.h>
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 6f3ea9b..f56d185 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -44,6 +44,22 @@ config UIO_PDRV_GENIRQ
 
 	  If you don't know what to do here, say N.
 
+config UIO_DMEM_GENIRQ
+	tristate "Userspace platform driver with generic irq and dynamic memory"
+	help
+	  Platform driver for Userspace I/O devices, including generic
+	  interrupt handling code. Shared interrupts are not supported.
+
+	  Memory regions can be specified with the same platform device
+	  resources as the UIO_PDRV drivers, but dynamic regions can also
+	  be specified.
+	  The number and size of these regions is static,
+	  but the memory allocation is not performed until
+	  the associated device file is opened. The
+	  memory is freed once the uio device is closed.
+
+	  If you don't know what to do here, say N.
+
 config UIO_AEC
 	tristate "AEC video timestamp device"
 	depends on PCI
@@ -97,6 +113,7 @@ config UIO_NETX
 config UIO_PRUSS
 	tristate "Texas Instruments PRUSS driver"
 	depends on ARCH_DAVINCI_DA850
+	select GENERIC_ALLOCATOR
 	help
 	  PRUSS driver for OMAPL138/DA850/AM18XX devices
 	  PRUSS driver requires user space components, examples and user space
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index d4dd9a5..b354c53 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_UIO)	+= uio.o
 obj-$(CONFIG_UIO_CIF)	+= uio_cif.o
 obj-$(CONFIG_UIO_PDRV)	+= uio_pdrv.o
 obj-$(CONFIG_UIO_PDRV_GENIRQ)	+= uio_pdrv_genirq.o
+obj-$(CONFIG_UIO_DMEM_GENIRQ)	+= uio_dmem_genirq.o
 obj-$(CONFIG_UIO_AEC)	+= uio_aec.o
 obj-$(CONFIG_UIO_SERCOS3)	+= uio_sercos3.o
 obj-$(CONFIG_UIO_PCI_GENERIC)	+= uio_pci_generic.o
diff --git a/drivers/uio/uio_aec.c b/drivers/uio/uio_aec.c
index 72b22d4..1548982 100644
--- a/drivers/uio/uio_aec.c
+++ b/drivers/uio/uio_aec.c
@@ -78,7 +78,7 @@ static void print_board_data(struct pci_dev *pdev, struct uio_info *i)
 		ioread8(i->priv + 0x07));
 }
 
-static int __devinit probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct uio_info *info;
 	int ret;
diff --git a/drivers/uio/uio_cif.c b/drivers/uio/uio_cif.c
index a84a451..7dd6fc6 100644
--- a/drivers/uio/uio_cif.c
+++ b/drivers/uio/uio_cif.c
@@ -40,7 +40,7 @@ static irqreturn_t hilscher_handler(int irq, struct uio_info *dev_info)
 	return IRQ_HANDLED;
 }
 
-static int __devinit hilscher_pci_probe(struct pci_dev *dev,
+static int hilscher_pci_probe(struct pci_dev *dev,
 					const struct pci_device_id *id)
 {
 	struct uio_info *info;
@@ -112,7 +112,7 @@ static void hilscher_pci_remove(struct pci_dev *dev)
 	kfree (info);
 }
 
-static struct pci_device_id hilscher_pci_ids[] __devinitdata = {
+static struct pci_device_id hilscher_pci_ids[] = {
 	{
 		.vendor =	PCI_VENDOR_ID_PLX,
 		.device =	PCI_DEVICE_ID_PLX_9030,
diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c
new file mode 100644
index 0000000..252434c
--- /dev/null
+++ b/drivers/uio/uio_dmem_genirq.c
@@ -0,0 +1,359 @@
+/*
+ * drivers/uio/uio_dmem_genirq.c
+ *
+ * Userspace I/O platform driver with generic IRQ handling code.
+ *
+ * Copyright (C) 2012 Damian Hobson-Garcia
+ *
+ * Based on uio_pdrv_genirq.c by 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/platform_device.h>
+#include <linux/uio_driver.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_data/uio_dmem_genirq.h>
+#include <linux/stringify.h>
+#include <linux/pm_runtime.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+
+#define DRIVER_NAME "uio_dmem_genirq"
+#define DMEM_MAP_ERROR (~0)
+
+struct uio_dmem_genirq_platdata {
+	struct uio_info *uioinfo;
+	spinlock_t lock;
+	unsigned long flags;
+	struct platform_device *pdev;
+	unsigned int dmem_region_start;
+	unsigned int num_dmem_regions;
+	void *dmem_region_vaddr[MAX_UIO_MAPS];
+	struct mutex alloc_lock;
+	unsigned int refcnt;
+};
+
+static int uio_dmem_genirq_open(struct uio_info *info, struct inode *inode)
+{
+	struct uio_dmem_genirq_platdata *priv = info->priv;
+	struct uio_mem *uiomem;
+	int ret = 0;
+	int dmem_region = priv->dmem_region_start;
+
+	uiomem = &priv->uioinfo->mem[priv->dmem_region_start];
+
+	mutex_lock(&priv->alloc_lock);
+	while (!priv->refcnt && uiomem < &priv->uioinfo->mem[MAX_UIO_MAPS]) {
+		void *addr;
+		if (!uiomem->size)
+			break;
+
+		addr = dma_alloc_coherent(&priv->pdev->dev, uiomem->size,
+				(dma_addr_t *)&uiomem->addr, GFP_KERNEL);
+		if (!addr) {
+			uiomem->addr = DMEM_MAP_ERROR;
+		}
+		priv->dmem_region_vaddr[dmem_region++] = addr;
+		++uiomem;
+	}
+	priv->refcnt++;
+
+	mutex_unlock(&priv->alloc_lock);
+	/* Wait until the Runtime PM code has woken up the device */
+	pm_runtime_get_sync(&priv->pdev->dev);
+	return ret;
+}
+
+static int uio_dmem_genirq_release(struct uio_info *info, struct inode *inode)
+{
+	struct uio_dmem_genirq_platdata *priv = info->priv;
+	struct uio_mem *uiomem;
+	int dmem_region = priv->dmem_region_start;
+
+	/* Tell the Runtime PM code that the device has become idle */
+	pm_runtime_put_sync(&priv->pdev->dev);
+
+	uiomem = &priv->uioinfo->mem[priv->dmem_region_start];
+
+	mutex_lock(&priv->alloc_lock);
+
+	priv->refcnt--;
+	while (!priv->refcnt && uiomem < &priv->uioinfo->mem[MAX_UIO_MAPS]) {
+		if (!uiomem->size)
+			break;
+		if (priv->dmem_region_vaddr[dmem_region]) {
+			dma_free_coherent(&priv->pdev->dev, uiomem->size,
+					priv->dmem_region_vaddr[dmem_region],
+					uiomem->addr);
+		}
+		uiomem->addr = DMEM_MAP_ERROR;
+		++dmem_region;
+		++uiomem;
+	}
+
+	mutex_unlock(&priv->alloc_lock);
+	return 0;
+}
+
+static irqreturn_t uio_dmem_genirq_handler(int irq, struct uio_info *dev_info)
+{
+	struct uio_dmem_genirq_platdata *priv = dev_info->priv;
+
+	/* Just disable the interrupt in the interrupt controller, and
+	 * remember the state so we can allow user space to enable it later.
+	 */
+
+	if (!test_and_set_bit(0, &priv->flags))
+		disable_irq_nosync(irq);
+
+	return IRQ_HANDLED;
+}
+
+static int uio_dmem_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on)
+{
+	struct uio_dmem_genirq_platdata *priv = dev_info->priv;
+	unsigned long flags;
+
+	/* Allow user space to enable and disable the interrupt
+	 * in the interrupt controller, but keep track of the
+	 * state to prevent per-irq depth damage.
+	 *
+	 * Serialize this operation to support multiple tasks.
+	 */
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (irq_on) {
+		if (test_and_clear_bit(0, &priv->flags))
+			enable_irq(dev_info->irq);
+	} else {
+		if (!test_and_set_bit(0, &priv->flags))
+			disable_irq(dev_info->irq);
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+
+static int uio_dmem_genirq_probe(struct platform_device *pdev)
+{
+	struct uio_dmem_genirq_pdata *pdata = pdev->dev.platform_data;
+	struct uio_info *uioinfo = &pdata->uioinfo;
+	struct uio_dmem_genirq_platdata *priv;
+	struct uio_mem *uiomem;
+	int ret = -EINVAL;
+	int i;
+
+	if (pdev->dev.of_node) {
+		int irq;
+
+		/* alloc uioinfo for one device */
+		uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL);
+		if (!uioinfo) {
+			ret = -ENOMEM;
+			dev_err(&pdev->dev, "unable to kmalloc\n");
+			goto bad2;
+		}
+		uioinfo->name = pdev->dev.of_node->name;
+		uioinfo->version = "devicetree";
+
+		/* Multiple IRQs are not supported */
+		irq = platform_get_irq(pdev, 0);
+		if (irq == -ENXIO)
+			uioinfo->irq = UIO_IRQ_NONE;
+		else
+			uioinfo->irq = irq;
+	}
+
+	if (!uioinfo || !uioinfo->name || !uioinfo->version) {
+		dev_err(&pdev->dev, "missing platform_data\n");
+		goto bad0;
+	}
+
+	if (uioinfo->handler || uioinfo->irqcontrol ||
+	    uioinfo->irq_flags & IRQF_SHARED) {
+		dev_err(&pdev->dev, "interrupt configuration error\n");
+		goto bad0;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		dev_err(&pdev->dev, "unable to kmalloc\n");
+		goto bad0;
+	}
+
+	dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+
+	priv->uioinfo = uioinfo;
+	spin_lock_init(&priv->lock);
+	priv->flags = 0; /* interrupt is enabled to begin with */
+	priv->pdev = pdev;
+	mutex_init(&priv->alloc_lock);
+
+	if (!uioinfo->irq) {
+		ret = platform_get_irq(pdev, 0);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "failed to get IRQ\n");
+			goto bad0;
+		}
+		uioinfo->irq = ret;
+	}
+	uiomem = &uioinfo->mem[0];
+
+	for (i = 0; i < pdev->num_resources; ++i) {
+		struct resource *r = &pdev->resource[i];
+
+		if (r->flags != IORESOURCE_MEM)
+			continue;
+
+		if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
+			dev_warn(&pdev->dev, "device has more than "
+					__stringify(MAX_UIO_MAPS)
+					" I/O memory resources.\n");
+			break;
+		}
+
+		uiomem->memtype = UIO_MEM_PHYS;
+		uiomem->addr = r->start;
+		uiomem->size = resource_size(r);
+		++uiomem;
+	}
+
+	priv->dmem_region_start = i;
+	priv->num_dmem_regions = pdata->num_dynamic_regions;
+
+	for (i = 0; i < pdata->num_dynamic_regions; ++i) {
+		if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
+			dev_warn(&pdev->dev, "device has more than "
+					__stringify(MAX_UIO_MAPS)
+					" dynamic and fixed memory regions.\n");
+			break;
+		}
+		uiomem->memtype = UIO_MEM_PHYS;
+		uiomem->addr = DMEM_MAP_ERROR;
+		uiomem->size = pdata->dynamic_region_sizes[i];
+		++uiomem;
+	}
+
+	while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) {
+		uiomem->size = 0;
+		++uiomem;
+	}
+
+	/* This driver requires no hardware specific kernel code to handle
+	 * interrupts. Instead, the interrupt handler simply disables the
+	 * interrupt in the interrupt controller. User space is responsible
+	 * for performing hardware specific acknowledge and re-enabling of
+	 * the interrupt in the interrupt controller.
+	 *
+	 * Interrupt sharing is not supported.
+	 */
+
+	uioinfo->handler = uio_dmem_genirq_handler;
+	uioinfo->irqcontrol = uio_dmem_genirq_irqcontrol;
+	uioinfo->open = uio_dmem_genirq_open;
+	uioinfo->release = uio_dmem_genirq_release;
+	uioinfo->priv = priv;
+
+	/* Enable Runtime PM for this device:
+	 * The device starts in suspended state to allow the hardware to be
+	 * turned off by default. The Runtime PM bus code should power on the
+	 * hardware and enable clocks at open().
+	 */
+	pm_runtime_enable(&pdev->dev);
+
+	ret = uio_register_device(&pdev->dev, priv->uioinfo);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to register uio device\n");
+		goto bad1;
+	}
+
+	platform_set_drvdata(pdev, priv);
+	return 0;
+ bad1:
+	kfree(priv);
+	pm_runtime_disable(&pdev->dev);
+ bad0:
+	/* kfree uioinfo for OF */
+	if (pdev->dev.of_node)
+		kfree(uioinfo);
+ bad2:
+	return ret;
+}
+
+static int uio_dmem_genirq_remove(struct platform_device *pdev)
+{
+	struct uio_dmem_genirq_platdata *priv = platform_get_drvdata(pdev);
+
+	uio_unregister_device(priv->uioinfo);
+	pm_runtime_disable(&pdev->dev);
+
+	priv->uioinfo->handler = NULL;
+	priv->uioinfo->irqcontrol = NULL;
+
+	/* kfree uioinfo for OF */
+	if (pdev->dev.of_node)
+		kfree(priv->uioinfo);
+
+	kfree(priv);
+	return 0;
+}
+
+static int uio_dmem_genirq_runtime_nop(struct device *dev)
+{
+	/* Runtime PM callback shared between ->runtime_suspend()
+	 * and ->runtime_resume(). Simply returns success.
+	 *
+	 * In this driver pm_runtime_get_sync() and pm_runtime_put_sync()
+	 * are used at open() and release() time. This allows the
+	 * Runtime PM code to turn off power to the device while the
+	 * device is unused, ie before open() and after release().
+	 *
+	 * This Runtime PM callback does not need to save or restore
+	 * any registers since user space is responsbile for hardware
+	 * register reinitialization after open().
+	 */
+	return 0;
+}
+
+static const struct dev_pm_ops uio_dmem_genirq_dev_pm_ops = {
+	.runtime_suspend = uio_dmem_genirq_runtime_nop,
+	.runtime_resume = uio_dmem_genirq_runtime_nop,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id uio_of_genirq_match[] = {
+	{ /* empty for now */ },
+};
+MODULE_DEVICE_TABLE(of, uio_of_genirq_match);
+#else
+# define uio_of_genirq_match NULL
+#endif
+
+static struct platform_driver uio_dmem_genirq = {
+	.probe = uio_dmem_genirq_probe,
+	.remove = uio_dmem_genirq_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.pm = &uio_dmem_genirq_dev_pm_ops,
+		.of_match_table = uio_of_genirq_match,
+	},
+};
+
+module_platform_driver(uio_dmem_genirq);
+
+MODULE_AUTHOR("Damian Hobson-Garcia");
+MODULE_DESCRIPTION("Userspace I/O platform driver with dynamic memory.");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/uio/uio_netx.c b/drivers/uio/uio_netx.c
index a879fd5..6a4ba5e 100644
--- a/drivers/uio/uio_netx.c
+++ b/drivers/uio/uio_netx.c
@@ -48,7 +48,7 @@ static irqreturn_t netx_handler(int irq, struct uio_info *dev_info)
 	return IRQ_HANDLED;
 }
 
-static int __devinit netx_pci_probe(struct pci_dev *dev,
+static int netx_pci_probe(struct pci_dev *dev,
 					const struct pci_device_id *id)
 {
 	struct uio_info *info;
diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c
index 0bd08ef..14aa10c 100644
--- a/drivers/uio/uio_pci_generic.c
+++ b/drivers/uio/uio_pci_generic.c
@@ -53,7 +53,7 @@ static irqreturn_t irqhandler(int irq, struct uio_info *info)
 	return IRQ_HANDLED;
 }
 
-static int __devinit probe(struct pci_dev *pdev,
+static int probe(struct pci_dev *pdev,
 			   const struct pci_device_id *id)
 {
 	struct uio_pci_generic_dev *gdev;
diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c
index 72d3646..39be9e0 100644
--- a/drivers/uio/uio_pdrv.c
+++ b/drivers/uio/uio_pdrv.c
@@ -60,6 +60,7 @@ static int uio_pdrv_probe(struct platform_device *pdev)
 		uiomem->memtype = UIO_MEM_PHYS;
 		uiomem->addr = r->start;
 		uiomem->size = resource_size(r);
+		uiomem->name = r->name;
 		++uiomem;
 	}
 
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c
index 42202cd..c122bca 100644
--- a/drivers/uio/uio_pdrv_genirq.c
+++ b/drivers/uio/uio_pdrv_genirq.c
@@ -102,7 +102,7 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
 	int ret = -EINVAL;
 	int i;
 
-	if (!uioinfo) {
+	if (pdev->dev.of_node) {
 		int irq;
 
 		/* alloc uioinfo for one device */
@@ -172,6 +172,7 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
 		uiomem->memtype = UIO_MEM_PHYS;
 		uiomem->addr = r->start;
 		uiomem->size = resource_size(r);
+		uiomem->name = r->name;
 		++uiomem;
 	}
 
diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
index 33a7a27..6e2ab00 100644
--- a/drivers/uio/uio_pruss.c
+++ b/drivers/uio/uio_pruss.c
@@ -25,7 +25,7 @@
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
-#include <mach/sram.h>
+#include <linux/genalloc.h>
 
 #define DRV_NAME "pruss_uio"
 #define DRV_VERSION "1.0"
@@ -65,10 +65,11 @@ struct uio_pruss_dev {
 	dma_addr_t sram_paddr;
 	dma_addr_t ddr_paddr;
 	void __iomem *prussio_vaddr;
-	void *sram_vaddr;
+	unsigned long sram_vaddr;
 	void *ddr_vaddr;
 	unsigned int hostirq_start;
 	unsigned int pintc_base;
+	struct gen_pool *sram_pool;
 };
 
 static irqreturn_t pruss_handler(int irq, struct uio_info *info)
@@ -106,13 +107,15 @@ static void pruss_cleanup(struct platform_device *dev,
 			gdev->ddr_paddr);
 	}
 	if (gdev->sram_vaddr)
-		sram_free(gdev->sram_vaddr, sram_pool_sz);
+		gen_pool_free(gdev->sram_pool,
+			      gdev->sram_vaddr,
+			      sram_pool_sz);
 	kfree(gdev->info);
 	clk_put(gdev->pruss_clk);
 	kfree(gdev);
 }
 
-static int __devinit pruss_probe(struct platform_device *dev)
+static int pruss_probe(struct platform_device *dev)
 {
 	struct uio_info *p;
 	struct uio_pruss_dev *gdev;
@@ -152,10 +155,17 @@ static int __devinit pruss_probe(struct platform_device *dev)
 		goto out_free;
 	}
 
-	gdev->sram_vaddr = sram_alloc(sram_pool_sz, &(gdev->sram_paddr));
-	if (!gdev->sram_vaddr) {
-		dev_err(&dev->dev, "Could not allocate SRAM pool\n");
-		goto out_free;
+	if (pdata->sram_pool) {
+		gdev->sram_pool = pdata->sram_pool;
+		gdev->sram_vaddr =
+			gen_pool_alloc(gdev->sram_pool, sram_pool_sz);
+		if (!gdev->sram_vaddr) {
+			dev_err(&dev->dev, "Could not allocate SRAM pool\n");
+			goto out_free;
+		}
+		gdev->sram_paddr =
+			gen_pool_virt_to_phys(gdev->sram_pool,
+					      gdev->sram_vaddr);
 	}
 
 	gdev->ddr_vaddr = dma_alloc_coherent(&dev->dev, extram_pool_sz,
@@ -209,7 +219,7 @@ out_free:
 	return ret;
 }
 
-static int __devexit pruss_remove(struct platform_device *dev)
+static int pruss_remove(struct platform_device *dev)
 {
 	struct uio_pruss_dev *gdev = platform_get_drvdata(dev);
 
@@ -220,7 +230,7 @@ static int __devexit pruss_remove(struct platform_device *dev)
 
 static struct platform_driver pruss_driver = {
 	.probe = pruss_probe,
-	.remove = __devexit_p(pruss_remove),
+	.remove = pruss_remove,
 	.driver = {
 		   .name = DRV_NAME,
 		   .owner = THIS_MODULE,
diff --git a/drivers/uio/uio_sercos3.c b/drivers/uio/uio_sercos3.c
index a187fa1..81a10a5 100644
--- a/drivers/uio/uio_sercos3.c
+++ b/drivers/uio/uio_sercos3.c
@@ -116,7 +116,7 @@ static int sercos3_setup_iomem(struct pci_dev *dev, struct uio_info *info,
 	return 0;
 }
 
-static int __devinit sercos3_pci_probe(struct pci_dev *dev,
+static int sercos3_pci_probe(struct pci_dev *dev,
 				       const struct pci_device_id *id)
 {
 	struct uio_info *info;
@@ -197,7 +197,7 @@ static void sercos3_pci_remove(struct pci_dev *dev)
 	kfree(info);
 }
 
-static struct pci_device_id sercos3_pci_ids[] __devinitdata = {
+static struct pci_device_id sercos3_pci_ids[] = {
 	{
 		.vendor =       PCI_VENDOR_ID_PLX,
 		.device =       PCI_DEVICE_ID_PLX_9030,
diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c
index 6f3b6e2..fe815ec 100644
--- a/drivers/usb/c67x00/c67x00-drv.c
+++ b/drivers/usb/c67x00/c67x00-drv.c
@@ -116,7 +116,7 @@ static irqreturn_t c67x00_irq(int irq, void *__dev)
 
 /* ------------------------------------------------------------------------- */
 
-static int __devinit c67x00_drv_probe(struct platform_device *pdev)
+static int c67x00_drv_probe(struct platform_device *pdev)
 {
 	struct c67x00_device *c67x00;
 	struct c67x00_platform_data *pdata;
@@ -191,7 +191,7 @@ static int __devinit c67x00_drv_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit c67x00_drv_remove(struct platform_device *pdev)
+static int c67x00_drv_remove(struct platform_device *pdev)
 {
 	struct c67x00_device *c67x00 = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -219,7 +219,7 @@ static int __devexit c67x00_drv_remove(struct platform_device *pdev)
 
 static struct platform_driver c67x00_driver = {
 	.probe	= c67x00_drv_probe,
-	.remove	= __devexit_p(c67x00_drv_remove),
+	.remove	= c67x00_drv_remove,
 	.driver	= {
 		.owner = THIS_MODULE,
 		.name = "c67x00",
diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig
index 1ea932a..608a2ae 100644
--- a/drivers/usb/chipidea/Kconfig
+++ b/drivers/usb/chipidea/Kconfig
@@ -20,6 +20,7 @@ config USB_CHIPIDEA_UDC
 config USB_CHIPIDEA_HOST
 	bool "ChipIdea host controller"
 	depends on USB=y || USB=USB_CHIPIDEA
+	depends on USB_EHCI_HCD
 	select USB_EHCI_ROOT_HUB_TT
 	help
 	  Say Y here to enable host controller functionality of the
diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c
index 0f5ca4b..8c29122 100644
--- a/drivers/usb/chipidea/ci13xxx_imx.c
+++ b/drivers/usb/chipidea/ci13xxx_imx.c
@@ -85,7 +85,7 @@ EXPORT_SYMBOL_GPL(usbmisc_get_init_data);
 
 /* End of common functions shared by usbmisc drivers*/
 
-static struct ci13xxx_platform_data ci13xxx_imx_platdata __devinitdata  = {
+static struct ci13xxx_platform_data ci13xxx_imx_platdata  = {
 	.name			= "ci13xxx_imx",
 	.flags			= CI13XXX_REQUIRE_TRANSCEIVER |
 				  CI13XXX_PULLUP_ON_VBUS |
@@ -93,7 +93,7 @@ static struct ci13xxx_platform_data ci13xxx_imx_platdata __devinitdata  = {
 	.capoffset		= DEF_CAPOFFSET,
 };
 
-static int __devinit ci13xxx_imx_probe(struct platform_device *pdev)
+static int ci13xxx_imx_probe(struct platform_device *pdev)
 {
 	struct ci13xxx_imx_data *data;
 	struct platform_device *plat_ci, *phy_pdev;
@@ -220,7 +220,7 @@ put_np:
 	return ret;
 }
 
-static int __devexit ci13xxx_imx_remove(struct platform_device *pdev)
+static int ci13xxx_imx_remove(struct platform_device *pdev)
 {
 	struct ci13xxx_imx_data *data = platform_get_drvdata(pdev);
 
@@ -252,7 +252,7 @@ MODULE_DEVICE_TABLE(of, ci13xxx_imx_dt_ids);
 
 static struct platform_driver ci13xxx_imx_driver = {
 	.probe = ci13xxx_imx_probe,
-	.remove = __devexit_p(ci13xxx_imx_remove),
+	.remove = ci13xxx_imx_remove,
 	.driver = {
 		.name = "imx_usb",
 		.owner = THIS_MODULE,
diff --git a/drivers/usb/chipidea/ci13xxx_msm.c b/drivers/usb/chipidea/ci13xxx_msm.c
index b01feb3..7d16681 100644
--- a/drivers/usb/chipidea/ci13xxx_msm.c
+++ b/drivers/usb/chipidea/ci13xxx_msm.c
@@ -55,7 +55,7 @@ static struct ci13xxx_platform_data ci13xxx_msm_platdata = {
 	.notify_event		= ci13xxx_msm_notify_event,
 };
 
-static int __devinit ci13xxx_msm_probe(struct platform_device *pdev)
+static int ci13xxx_msm_probe(struct platform_device *pdev)
 {
 	struct platform_device *plat_ci;
 
@@ -77,7 +77,7 @@ static int __devinit ci13xxx_msm_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit ci13xxx_msm_remove(struct platform_device *pdev)
+static int ci13xxx_msm_remove(struct platform_device *pdev)
 {
 	struct platform_device *plat_ci = platform_get_drvdata(pdev);
 
@@ -89,7 +89,7 @@ static int __devexit ci13xxx_msm_remove(struct platform_device *pdev)
 
 static struct platform_driver ci13xxx_msm_driver = {
 	.probe = ci13xxx_msm_probe,
-	.remove = __devexit_p(ci13xxx_msm_remove),
+	.remove = ci13xxx_msm_remove,
 	.driver = { .name = "msm_hsusb", },
 };
 
diff --git a/drivers/usb/chipidea/ci13xxx_pci.c b/drivers/usb/chipidea/ci13xxx_pci.c
index 918e149..9b227e3 100644
--- a/drivers/usb/chipidea/ci13xxx_pci.c
+++ b/drivers/usb/chipidea/ci13xxx_pci.c
@@ -48,7 +48,7 @@ struct ci13xxx_platform_data penwell_pci_platdata = {
  * Allocates basic PCI resources for this USB device controller, and then
  * invokes the udc_probe() method to start the UDC associated with it
  */
-static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
+static int ci13xxx_pci_probe(struct pci_dev *pdev,
 				       const struct pci_device_id *id)
 {
 	struct ci13xxx_platform_data *platdata = (void *)id->driver_data;
@@ -107,7 +107,7 @@ static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
  * first invoking the udc_remove() and then releases
  * all PCI resources allocated for this USB device controller
  */
-static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
+static void ci13xxx_pci_remove(struct pci_dev *pdev)
 {
 	struct platform_device *plat_ci = pci_get_drvdata(pdev);
 
@@ -147,7 +147,7 @@ static struct pci_driver ci13xxx_pci_driver = {
 	.name         =	UDC_DRIVER_NAME,
 	.id_table     =	ci13xxx_pci_id_table,
 	.probe        =	ci13xxx_pci_probe,
-	.remove       =	__devexit_p(ci13xxx_pci_remove),
+	.remove       =	ci13xxx_pci_remove,
 };
 
 module_pci_driver(ci13xxx_pci_driver);
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index f69d029..aebf695 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -385,12 +385,13 @@ EXPORT_SYMBOL_GPL(ci13xxx_add_device);
 
 void ci13xxx_remove_device(struct platform_device *pdev)
 {
+	int id = pdev->id;
 	platform_device_unregister(pdev);
-	ida_simple_remove(&ci_ida, pdev->id);
+	ida_simple_remove(&ci_ida, id);
 }
 EXPORT_SYMBOL_GPL(ci13xxx_remove_device);
 
-static int __devinit ci_hdrc_probe(struct platform_device *pdev)
+static int ci_hdrc_probe(struct platform_device *pdev)
 {
 	struct device	*dev = &pdev->dev;
 	struct ci13xxx	*ci;
@@ -508,7 +509,7 @@ rm_wq:
 	return ret;
 }
 
-static int __devexit ci_hdrc_remove(struct platform_device *pdev)
+static int ci_hdrc_remove(struct platform_device *pdev)
 {
 	struct ci13xxx *ci = platform_get_drvdata(pdev);
 
@@ -523,7 +524,7 @@ static int __devexit ci_hdrc_remove(struct platform_device *pdev)
 
 static struct platform_driver ci_hdrc_driver = {
 	.probe	= ci_hdrc_probe,
-	.remove	= __devexit_p(ci_hdrc_remove),
+	.remove	= ci_hdrc_remove,
 	.driver	= {
 		.name	= "ci_hdrc",
 	},
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c
index c6f50a2..3bc244d 100644
--- a/drivers/usb/chipidea/debug.c
+++ b/drivers/usb/chipidea/debug.c
@@ -160,9 +160,6 @@ static ssize_t show_device(struct device *dev, struct device_attribute *attr,
 		       gadget->speed);
 	n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed         = %d\n",
 		       gadget->max_speed);
-	/* TODO: Scheduled for removal in 3.8. */
-	n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed      = %d\n",
-		       gadget_is_dualspeed(gadget));
 	n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg            = %d\n",
 		       gadget->is_otg);
 	n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral   = %d\n",
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index ebff9f4..caecad9 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -20,77 +20,18 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/io.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
 #include <linux/usb/chipidea.h>
 
-#define CHIPIDEA_EHCI
-#include "../host/ehci-hcd.c"
+#include "../host/ehci.h"
 
 #include "ci.h"
 #include "bits.h"
 #include "host.h"
 
-static int ci_ehci_setup(struct usb_hcd *hcd)
-{
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	int ret;
-
-	hcd->has_tt = 1;
-
-	ret = ehci_setup(hcd);
-	if (ret)
-		return ret;
-
-	ehci_port_power(ehci, 0);
-
-	return ret;
-}
-
-static const struct hc_driver ci_ehci_hc_driver = {
-	.description	= "ehci_hcd",
-	.product_desc	= "ChipIdea HDRC EHCI",
-	.hcd_priv_size	= sizeof(struct ehci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq	= ehci_irq,
-	.flags	= HCD_MEMORY | HCD_USB2,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.reset		= ci_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,
-	.bus_suspend		= ehci_bus_suspend,
-	.bus_resume		= ehci_bus_resume,
-	.relinquish_port	= ehci_relinquish_port,
-	.port_handed_over	= ehci_port_handed_over,
-
-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
+static struct hc_driver __read_mostly ci_ehci_hc_driver;
 
 static irqreturn_t host_irq(struct ci13xxx *ci)
 {
@@ -157,5 +98,7 @@ int ci_hdrc_host_init(struct ci13xxx *ci)
 	rdrv->name	= "host";
 	ci->roles[CI_ROLE_HOST] = rdrv;
 
+	ehci_init_driver(&ci_ehci_hc_driver, NULL);
+
 	return 0;
 }
diff --git a/drivers/usb/chipidea/usbmisc_imx6q.c b/drivers/usb/chipidea/usbmisc_imx6q.c
index 416e3fc..845efe2 100644
--- a/drivers/usb/chipidea/usbmisc_imx6q.c
+++ b/drivers/usb/chipidea/usbmisc_imx6q.c
@@ -82,7 +82,7 @@ static const struct of_device_id usbmisc_imx6q_dt_ids[] = {
 	{ /* sentinel */ }
 };
 
-static int __devinit usbmisc_imx6q_probe(struct platform_device *pdev)
+static int usbmisc_imx6q_probe(struct platform_device *pdev)
 {
 	struct resource	*res;
 	struct imx6q_usbmisc *data;
@@ -127,7 +127,7 @@ static int __devinit usbmisc_imx6q_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit usbmisc_imx6q_remove(struct platform_device *pdev)
+static int usbmisc_imx6q_remove(struct platform_device *pdev)
 {
 	usbmisc_unset_ops(&imx6q_usbmisc_ops);
 	clk_disable_unprepare(usbmisc->clk);
@@ -136,7 +136,7 @@ static int __devexit usbmisc_imx6q_remove(struct platform_device *pdev)
 
 static struct platform_driver usbmisc_imx6q_driver = {
 	.probe = usbmisc_imx6q_probe,
-	.remove = __devexit_p(usbmisc_imx6q_remove),
+	.remove = usbmisc_imx6q_remove,
 	.driver = {
 		.name = "usbmisc_imx6q",
 		.owner = THIS_MODULE,
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 6e49ec6..8d809a8 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -787,6 +787,10 @@ static int get_serial_info(struct acm *acm, struct serial_struct __user *info)
 	tmp.flags = ASYNC_LOW_LATENCY;
 	tmp.xmit_fifo_size = acm->writesize;
 	tmp.baud_base = le32_to_cpu(acm->line.dwDTERate);
+	tmp.close_delay	= acm->port.close_delay / 10;
+	tmp.closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
+				ASYNC_CLOSING_WAIT_NONE :
+				acm->port.closing_wait / 10;
 
 	if (copy_to_user(info, &tmp, sizeof(tmp)))
 		return -EFAULT;
@@ -794,6 +798,37 @@ static int get_serial_info(struct acm *acm, struct serial_struct __user *info)
 		return 0;
 }
 
+static int set_serial_info(struct acm *acm,
+				struct serial_struct __user *newinfo)
+{
+	struct serial_struct new_serial;
+	unsigned int closing_wait, close_delay;
+	int retval = 0;
+
+	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
+		return -EFAULT;
+
+	close_delay = new_serial.close_delay * 10;
+	closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
+			ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10;
+
+	mutex_lock(&acm->port.mutex);
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		if ((close_delay != acm->port.close_delay) ||
+		    (closing_wait != acm->port.closing_wait))
+			retval = -EPERM;
+		else
+			retval = -EOPNOTSUPP;
+	} else {
+		acm->port.close_delay  = close_delay;
+		acm->port.closing_wait = closing_wait;
+	}
+
+	mutex_unlock(&acm->port.mutex);
+	return retval;
+}
+
 static int acm_tty_ioctl(struct tty_struct *tty,
 					unsigned int cmd, unsigned long arg)
 {
@@ -804,6 +839,9 @@ static int acm_tty_ioctl(struct tty_struct *tty,
 	case TIOCGSERIAL: /* gets serial port data */
 		rv = get_serial_info(acm, (struct serial_struct __user *) arg);
 		break;
+	case TIOCSSERIAL:
+		rv = set_serial_info(acm, (struct serial_struct __user *) arg);
+		break;
 	}
 
 	return rv;
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index f460de3..cbacea9 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -591,16 +591,14 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
 
 	/* Now look at all of this device's children. */
 	usb_hub_for_each_child(usbdev, chix, childdev) {
-		if (childdev) {
-			usb_lock_device(childdev);
-			ret = usb_device_dump(buffer, nbytes, skip_bytes,
-					      file_offset, childdev, bus,
-					      level + 1, chix - 1, ++cnt);
-			usb_unlock_device(childdev);
-			if (ret == -EFAULT)
-				return total_written;
-			total_written += ret;
-		}
+		usb_lock_device(childdev);
+		ret = usb_device_dump(buffer, nbytes, skip_bytes,
+				      file_offset, childdev, bus,
+				      level + 1, chix - 1, ++cnt);
+		usb_unlock_device(childdev);
+		if (ret == -EFAULT)
+			return total_written;
+		total_written += ret;
 	}
 	return total_written;
 }
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 6056db7..d938b2b 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -32,8 +32,6 @@
 #include "usb.h"
 
 
-#ifdef CONFIG_HOTPLUG
-
 /*
  * Adds a new dynamic USBdevice ID to this driver,
  * and cause the driver to probe for all devices again.
@@ -194,20 +192,6 @@ static void usb_free_dynids(struct usb_driver *usb_drv)
 	}
 	spin_unlock(&usb_drv->dynids.lock);
 }
-#else
-static inline int usb_create_newid_files(struct usb_driver *usb_drv)
-{
-	return 0;
-}
-
-static void usb_remove_newid_files(struct usb_driver *usb_drv)
-{
-}
-
-static inline void usb_free_dynids(struct usb_driver *usb_drv)
-{
-}
-#endif
 
 static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf,
 							struct usb_driver *drv)
@@ -238,7 +222,7 @@ static int usb_probe_device(struct device *dev)
 	/* TODO: Add real matching code */
 
 	/* The device should always appear to be in use
-	 * unless the driver suports autosuspend.
+	 * unless the driver supports autosuspend.
 	 */
 	if (!udriver->supports_autosuspend)
 		error = usb_autoresume_device(udev);
@@ -790,7 +774,6 @@ static int usb_device_match(struct device *dev, struct device_driver *drv)
 	return 0;
 }
 
-#ifdef	CONFIG_HOTPLUG
 static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
 	struct usb_device *usb_dev;
@@ -832,14 +815,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
 	return 0;
 }
 
-#else
-
-static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-	return -ENODEV;
-}
-#endif	/* CONFIG_HOTPLUG */
-
 /**
  * usb_register_device_driver - register a USB device (not interface) driver
  * @new_udriver: USB operations for the device driver
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index 69ecd3c..eff2010 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -47,6 +47,9 @@ int usb_choose_configuration(struct usb_device *udev)
 	int insufficient_power = 0;
 	struct usb_host_config *c, *best;
 
+	if (usb_device_is_owned(udev))
+		return 0;
+
 	best = NULL;
 	c = udev->config;
 	num_configs = udev->descriptor.bNumConfigurations;
@@ -160,9 +163,7 @@ static int generic_probe(struct usb_device *udev)
 	/* Choose and set the configuration.  This registers the interfaces
 	 * with the driver core and lets interface drivers bind to them.
 	 */
-	if (usb_device_is_owned(udev))
-		;		/* Don't configure if the device is owned */
-	else if (udev->authorized == 0)
+	if (udev->authorized == 0)
 		dev_err(&udev->dev, "Device is not authorized for usage\n");
 	else {
 		c = usb_choose_configuration(udev);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index f034716..4225d5e 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2039,8 +2039,9 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
 	status = hcd->driver->bus_resume(hcd);
 	clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
 	if (status == 0) {
-		/* TRSMRCY = 10 msec */
-		msleep(10);
+		struct usb_device *udev;
+		int port1;
+
 		spin_lock_irq(&hcd_root_hub_lock);
 		if (!HCD_DEAD(hcd)) {
 			usb_set_device_state(rhdev, rhdev->actconfig
@@ -2050,6 +2051,20 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
 			hcd->state = HC_STATE_RUNNING;
 		}
 		spin_unlock_irq(&hcd_root_hub_lock);
+
+		/*
+		 * Check whether any of the enabled ports on the root hub are
+		 * unsuspended.  If they are then a TRSMRCY delay is needed
+		 * (this is what the USB-2 spec calls a "global resume").
+		 * Otherwise we can skip the delay.
+		 */
+		usb_hub_for_each_child(rhdev, port1, udev) {
+			if (udev->state != USB_STATE_NOTATTACHED &&
+					!udev->port_is_suspended) {
+				usleep_range(10000, 11000);	/* TRSMRCY */
+				break;
+			}
+		}
 	} else {
 		hcd->state = old_state;
 		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 1af04bd..a815fd2 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -39,6 +39,9 @@
 #endif
 #endif
 
+#define USB_VENDOR_GENESYS_LOGIC		0x05e3
+#define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND	0x01
+
 struct usb_port {
 	struct usb_device *child;
 	struct device dev;
@@ -86,6 +89,8 @@ struct usb_hub {
 	unsigned		quiescing:1;
 	unsigned		disconnected:1;
 
+	unsigned		quirk_check_port_auto_suspend:1;
+
 	unsigned		has_indicators:1;
 	u8			indicator[USB_MAXCHILDREN];
 	struct delayed_work	leds;
@@ -736,7 +741,6 @@ static void hub_tt_work(struct work_struct *work)
 	struct usb_hub		*hub =
 		container_of(work, struct usb_hub, tt.clear_work);
 	unsigned long		flags;
-	int			limit = 100;
 
 	spin_lock_irqsave (&hub->tt.lock, flags);
 	while (!list_empty(&hub->tt.clear_list)) {
@@ -746,9 +750,6 @@ static void hub_tt_work(struct work_struct *work)
 		const struct hc_driver	*drv;
 		int			status;
 
-		if (!hub->quiescing && --limit < 0)
-			break;
-
 		next = hub->tt.clear_list.next;
 		clear = list_entry (next, struct usb_tt_clear, clear_list);
 		list_del (&clear->clear_list);
@@ -1612,6 +1613,41 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
 	desc = intf->cur_altsetting;
 	hdev = interface_to_usbdev(intf);
 
+	/*
+	 * Set default autosuspend delay as 0 to speedup bus suspend,
+	 * based on the below considerations:
+	 *
+	 * - Unlike other drivers, the hub driver does not rely on the
+	 *   autosuspend delay to provide enough time to handle a wakeup
+	 *   event, and the submitted status URB is just to check future
+	 *   change on hub downstream ports, so it is safe to do it.
+	 *
+	 * - The patch might cause one or more auto supend/resume for
+	 *   below very rare devices when they are plugged into hub
+	 *   first time:
+	 *
+	 *   	devices having trouble initializing, and disconnect
+	 *   	themselves from the bus and then reconnect a second
+	 *   	or so later
+	 *
+	 *   	devices just for downloading firmware, and disconnects
+	 *   	themselves after completing it
+	 *
+	 *   For these quite rare devices, their drivers may change the
+	 *   autosuspend delay of their parent hub in the probe() to one
+	 *   appropriate value to avoid the subtle problem if someone
+	 *   does care it.
+	 *
+	 * - The patch may cause one or more auto suspend/resume on
+	 *   hub during running 'lsusb', but it is probably too
+	 *   infrequent to worry about.
+	 *
+	 * - Change autosuspend delay of hub can avoid unnecessary auto
+	 *   suspend timer for hub, also may decrease power consumption
+	 *   of USB bus.
+	 */
+	pm_runtime_set_autosuspend_delay(&hdev->dev, 0);
+
 	/* Hubs have proper suspend/resume support. */
 	usb_enable_autosuspend(hdev);
 
@@ -1670,6 +1706,9 @@ descriptor_error:
 	if (hdev->speed == USB_SPEED_HIGH)
 		highspeed_hubs++;
 
+	if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND)
+		hub->quirk_check_port_auto_suspend = 1;
+
 	if (hub_configure(hub, endpoint) >= 0)
 		return 0;
 
@@ -2012,7 +2051,7 @@ static void show_string(struct usb_device *udev, char *id, char *string)
 {
 	if (!string)
 		return;
-	dev_printk(KERN_INFO, &udev->dev, "%s: %s\n", id, string);
+	dev_info(&udev->dev, "%s: %s\n", id, string);
 }
 
 static void announce_device(struct usb_device *udev)
@@ -2879,6 +2918,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 				(PMSG_IS_AUTO(msg) ? "auto-" : ""),
 				udev->do_remote_wakeup);
 		usb_set_device_state(udev, USB_STATE_SUSPENDED);
+		udev->port_is_suspended = 1;
 		msleep(10);
 	}
 	usb_mark_last_busy(hub->hdev);
@@ -3043,6 +3083,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
 
  SuspendCleared:
 	if (status == 0) {
+		udev->port_is_suspended = 0;
 		if (hub_is_superspeed(hub->hdev)) {
 			if (portchange & USB_PORT_STAT_C_LINK_STATE)
 				clear_port_feature(hub->hdev, port1,
@@ -3126,6 +3167,21 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
 
 #endif
 
+static int check_ports_changed(struct usb_hub *hub)
+{
+	int port1;
+
+	for (port1 = 1; port1 <= hub->hdev->maxchild; ++port1) {
+		u16 portstatus, portchange;
+		int status;
+
+		status = hub_port_status(hub, port1, &portstatus, &portchange);
+		if (!status && portchange)
+			return 1;
+	}
+	return 0;
+}
+
 static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 {
 	struct usb_hub		*hub = usb_get_intfdata (intf);
@@ -3144,6 +3200,16 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 				return -EBUSY;
 		}
 	}
+
+	if (hdev->do_remote_wakeup && hub->quirk_check_port_auto_suspend) {
+		/* check if there are changes pending on hub ports */
+		if (check_ports_changed(hub)) {
+			if (PMSG_IS_AUTO(msg))
+				return -EBUSY;
+			pm_wakeup_event(&hdev->dev, 2000);
+		}
+	}
+
 	if (hub_is_superspeed(hdev) && hdev->do_remote_wakeup) {
 		/* Enable hub to send remote wakeup for all ports. */
 		for (port1 = 1; port1 <= hdev->maxchild; port1++) {
@@ -3972,6 +4038,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
 	if (retval)
 		goto fail;
 
+	if (hcd->phy && !hdev->parent)
+		usb_phy_notify_connect(hcd->phy, udev->speed);
+
 	/*
 	 * Some superspeed devices have finished the link training process
 	 * and attached to a superspeed hub port, but the device descriptor
@@ -4166,8 +4235,12 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 	}
 
 	/* Disconnect any existing devices under this port */
-	if (udev)
+	if (udev) {
+		if (hcd->phy && !hdev->parent &&
+				!(portstatus & USB_PORT_STAT_CONNECTION))
+			usb_phy_notify_disconnect(hcd->phy, udev->speed);
 		usb_disconnect(&hub->ports[port1 - 1]->child);
+	}
 	clear_bit(port1, hub->change_bits);
 
 	/* We can forget about a "removed" device when there's a physical
@@ -4190,13 +4263,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 		}
 	}
 
-	if (hcd->phy && !hdev->parent) {
-		if (portstatus & USB_PORT_STAT_CONNECTION)
-			usb_phy_notify_connect(hcd->phy, port1);
-		else
-			usb_phy_notify_disconnect(hcd->phy, port1);
-	}
-
 	/* Return now if debouncing failed or nothing is connected or
 	 * the device was "removed".
 	 */
@@ -4648,6 +4714,11 @@ static int hub_thread(void *__unused)
 }
 
 static const struct usb_device_id hub_id_table[] = {
+    { .match_flags = USB_DEVICE_ID_MATCH_VENDOR
+	           | USB_DEVICE_ID_MATCH_INT_CLASS,
+      .idVendor = USB_VENDOR_GENESYS_LOGIC,
+      .bInterfaceClass = USB_CLASS_HUB,
+      .driver_info = HUB_QUIRK_CHECK_PORT_AUTOSUSPEND},
     { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS,
       .bDeviceClass = USB_CLASS_HUB},
     { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 1ed5afd..131f736 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1540,7 +1540,6 @@ static void usb_release_interface(struct device *dev)
 	kfree(intf);
 }
 
-#ifdef	CONFIG_HOTPLUG
 static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
 	struct usb_device *usb_dev;
@@ -1575,14 +1574,6 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
 	return 0;
 }
 
-#else
-
-static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-	return -ENODEV;
-}
-#endif	/* CONFIG_HOTPLUG */
-
 struct device_type usb_if_device_type = {
 	.name =		"usb_interface",
 	.release =	usb_release_interface,
@@ -1795,7 +1786,8 @@ free_interfaces:
 	if (dev->actconfig && usb_disable_lpm(dev)) {
 		dev_err(&dev->dev, "%s Failed to disable LPM\n.", __func__);
 		mutex_unlock(hcd->bandwidth_mutex);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto free_interfaces;
 	}
 	ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
 	if (ret < 0) {
@@ -1806,29 +1798,8 @@ free_interfaces:
 		goto free_interfaces;
 	}
 
-	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-			      USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
-			      NULL, 0, USB_CTRL_SET_TIMEOUT);
-	if (ret < 0) {
-		/* All the old state is gone, so what else can we do?
-		 * The device is probably useless now anyway.
-		 */
-		cp = NULL;
-	}
-
-	dev->actconfig = cp;
-	if (!cp) {
-		usb_set_device_state(dev, USB_STATE_ADDRESS);
-		usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
-		/* Leave LPM disabled while the device is unconfigured. */
-		mutex_unlock(hcd->bandwidth_mutex);
-		usb_autosuspend_device(dev);
-		goto free_interfaces;
-	}
-	mutex_unlock(hcd->bandwidth_mutex);
-	usb_set_device_state(dev, USB_STATE_CONFIGURED);
-
-	/* Initialize the new interface structures and the
+	/*
+	 * Initialize the new interface structures and the
 	 * hc/hcd/usbcore interface/endpoint state.
 	 */
 	for (i = 0; i < nintf; ++i) {
@@ -1872,6 +1843,35 @@ free_interfaces:
 	}
 	kfree(new_interfaces);
 
+	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+			      USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
+			      NULL, 0, USB_CTRL_SET_TIMEOUT);
+	if (ret < 0 && cp) {
+		/*
+		 * All the old state is gone, so what else can we do?
+		 * The device is probably useless now anyway.
+		 */
+		usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
+		for (i = 0; i < nintf; ++i) {
+			usb_disable_interface(dev, cp->interface[i], true);
+			put_device(&cp->interface[i]->dev);
+			cp->interface[i] = NULL;
+		}
+		cp = NULL;
+	}
+
+	dev->actconfig = cp;
+	mutex_unlock(hcd->bandwidth_mutex);
+
+	if (!cp) {
+		usb_set_device_state(dev, USB_STATE_ADDRESS);
+
+		/* Leave LPM disabled while the device is unconfigured. */
+		usb_autosuspend_device(dev);
+		return ret;
+	}
+	usb_set_device_state(dev, USB_STATE_CONFIGURED);
+
 	if (cp->string == NULL &&
 			!(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
 		cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 9d912bf..e0d9d94 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -214,9 +214,25 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
  * urb->interval is modified to reflect the actual transfer period used
  * (normally some power of two units).  And for isochronous urbs,
  * urb->start_frame is modified to reflect when the URB's transfers were
- * scheduled to start.  Not all isochronous transfer scheduling policies
- * will work, but most host controller drivers should easily handle ISO
- * queues going from now until 10-200 msec into the future.
+ * scheduled to start.
+ *
+ * Not all isochronous transfer scheduling policies will work, but most
+ * host controller drivers should easily handle ISO queues going from now
+ * until 10-200 msec into the future.  Drivers should try to keep at
+ * least one or two msec of data in the queue; many controllers require
+ * that new transfers start at least 1 msec in the future when they are
+ * added.  If the driver is unable to keep up and the queue empties out,
+ * the behavior for new submissions is governed by the URB_ISO_ASAP flag.
+ * If the flag is set, or if the queue is idle, then the URB is always
+ * assigned to the first available (and not yet expired) slot in the
+ * endpoint's schedule.  If the flag is not set and the queue is active
+ * then the URB is always assigned to the next slot in the schedule
+ * following the end of the endpoint's previous URB, even if that slot is
+ * in the past.  When a packet is assigned in this way to a slot that has
+ * already expired, the packet is not transmitted and the corresponding
+ * usb_iso_packet_descriptor's status field will return -EXDEV.  If this
+ * would happen to all the packets in the URB, submission fails with a
+ * -EXDEV error code.
  *
  * For control endpoints, the synchronous usb_control_msg() call is
  * often used (in non-interrupt context) instead of this call.
@@ -305,8 +321,13 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 	struct usb_host_endpoint	*ep;
 	int				is_out;
 
-	if (!urb || urb->hcpriv || !urb->complete)
+	if (!urb || !urb->complete)
 		return -EINVAL;
+	if (urb->hcpriv) {
+		WARN_ONCE(1, "URB %p submitted while active\n", urb);
+		return -EBUSY;
+	}
+
 	dev = urb->dev;
 	if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED))
 		return -ENODEV;
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index cd8fb44..f81b925 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -233,7 +233,6 @@ static void usb_release_dev(struct device *dev)
 	kfree(udev);
 }
 
-#ifdef	CONFIG_HOTPLUG
 static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
 	struct usb_device *usb_dev;
@@ -249,14 +248,6 @@ static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
 	return 0;
 }
 
-#else
-
-static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-	return -ENODEV;
-}
-#endif	/* CONFIG_HOTPLUG */
-
 #ifdef	CONFIG_PM
 
 /* USB device Power-Management thunks.
@@ -370,14 +361,14 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
 				 struct usb_bus *bus, unsigned port1)
 {
 	struct usb_device *dev;
-	struct usb_hcd *usb_hcd = container_of(bus, struct usb_hcd, self);
+	struct usb_hcd *usb_hcd = bus_to_hcd(bus);
 	unsigned root_hub = 0;
 
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev)
 		return NULL;
 
-	if (!usb_get_hcd(bus_to_hcd(bus))) {
+	if (!usb_get_hcd(usb_hcd)) {
 		kfree(dev);
 		return NULL;
 	}
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index d441fe4..4502648 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -27,19 +27,7 @@ endif
 ##
 
 obj-$(CONFIG_USB_DWC3)		+= dwc3-omap.o
-
-##
-# REVISIT Samsung Exynos platform needs the clk API which isn't
-# defined on all architectures. If we allow dwc3-exynos.c compile
-# always we will fail the linking phase on those architectures
-# which don't provide clk api implementation and that's unnaceptable.
-#
-# When Samsung's platform start supporting pm_runtime, this check
-# for HAVE_CLK should be removed.
-##
-ifneq ($(CONFIG_HAVE_CLK),)
-	obj-$(CONFIG_USB_DWC3)		+= dwc3-exynos.o
-endif
+obj-$(CONFIG_USB_DWC3)		+= dwc3-exynos.o
 
 ifneq ($(CONFIG_PCI),)
 	obj-$(CONFIG_USB_DWC3)		+= dwc3-pci.o
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index c14ebc9..3a4004a 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -66,45 +66,6 @@ MODULE_PARM_DESC(maximum_speed, "Maximum supported speed.");
 
 /* -------------------------------------------------------------------------- */
 
-#define DWC3_DEVS_POSSIBLE	32
-
-static DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE);
-
-int dwc3_get_device_id(void)
-{
-	int		id;
-
-again:
-	id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
-	if (id < DWC3_DEVS_POSSIBLE) {
-		int old;
-
-		old = test_and_set_bit(id, dwc3_devs);
-		if (old)
-			goto again;
-	} else {
-		pr_err("dwc3: no space for new device\n");
-		id = -ENOMEM;
-	}
-
-	return id;
-}
-EXPORT_SYMBOL_GPL(dwc3_get_device_id);
-
-void dwc3_put_device_id(int id)
-{
-	int			ret;
-
-	if (id < 0)
-		return;
-
-	ret = test_bit(id, dwc3_devs);
-	WARN(!ret, "dwc3: ID %d not in use\n", id);
-	smp_mb__before_clear_bit();
-	clear_bit(id, dwc3_devs);
-}
-EXPORT_SYMBOL_GPL(dwc3_put_device_id);
-
 void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
 {
 	u32 reg;
@@ -169,7 +130,6 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
 		struct dwc3_event_buffer *evt)
 {
 	dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma);
-	kfree(evt);
 }
 
 /**
@@ -180,12 +140,11 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
  * Returns a pointer to the allocated event buffer structure on success
  * otherwise ERR_PTR(errno).
  */
-static struct dwc3_event_buffer *__devinit
-dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
+static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
 {
 	struct dwc3_event_buffer	*evt;
 
-	evt = kzalloc(sizeof(*evt), GFP_KERNEL);
+	evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL);
 	if (!evt)
 		return ERR_PTR(-ENOMEM);
 
@@ -193,10 +152,8 @@ dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
 	evt->length	= length;
 	evt->buf	= dma_alloc_coherent(dwc->dev, length,
 			&evt->dma, GFP_KERNEL);
-	if (!evt->buf) {
-		kfree(evt);
+	if (!evt->buf)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	return evt;
 }
@@ -215,8 +172,6 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc)
 		if (evt)
 			dwc3_free_one_event_buffer(dwc, evt);
 	}
-
-	kfree(dwc->ev_buffs);
 }
 
 /**
@@ -227,7 +182,7 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc)
  * Returns 0 on success otherwise negative errno. In the error case, dwc
  * may contain some buffers allocated but not all which were requested.
  */
-static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
+static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
 {
 	int			num;
 	int			i;
@@ -235,7 +190,8 @@ static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
 	num = DWC3_NUM_INT(dwc->hwparams.hwparams1);
 	dwc->num_event_buffers = num;
 
-	dwc->ev_buffs = kzalloc(sizeof(*dwc->ev_buffs) * num, GFP_KERNEL);
+	dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num,
+			GFP_KERNEL);
 	if (!dwc->ev_buffs) {
 		dev_err(dwc->dev, "can't allocate event buffers array\n");
 		return -ENOMEM;
@@ -303,7 +259,7 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
 	}
 }
 
-static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc)
+static void dwc3_cache_hwparams(struct dwc3 *dwc)
 {
 	struct dwc3_hwparams	*parms = &dwc->hwparams;
 
@@ -324,7 +280,7 @@ static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc)
  *
  * Returns 0 on success otherwise negative errno.
  */
-static int __devinit dwc3_core_init(struct dwc3 *dwc)
+static int dwc3_core_init(struct dwc3 *dwc)
 {
 	unsigned long		timeout;
 	u32			reg;
@@ -358,8 +314,6 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc)
 
 	dwc3_core_soft_reset(dwc);
 
-	dwc3_cache_hwparams(dwc);
-
 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
 	reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
 	reg &= ~DWC3_GCTL_DISSCRAMBLE;
@@ -383,24 +337,14 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc)
 
 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 
-	ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
-	if (ret) {
-		dev_err(dwc->dev, "failed to allocate event buffers\n");
-		ret = -ENOMEM;
-		goto err1;
-	}
-
 	ret = dwc3_event_buffers_setup(dwc);
 	if (ret) {
 		dev_err(dwc->dev, "failed to setup event buffers\n");
-		goto err1;
+		goto err0;
 	}
 
 	return 0;
 
-err1:
-	dwc3_free_event_buffers(dwc);
-
 err0:
 	return ret;
 }
@@ -408,16 +352,14 @@ err0:
 static void dwc3_core_exit(struct dwc3 *dwc)
 {
 	dwc3_event_buffers_cleanup(dwc);
-	dwc3_free_event_buffers(dwc);
 
 	usb_phy_shutdown(dwc->usb2_phy);
 	usb_phy_shutdown(dwc->usb3_phy);
-
 }
 
 #define DWC3_ALIGN_MASK		(16 - 1)
 
-static int __devinit dwc3_probe(struct platform_device *pdev)
+static int dwc3_probe(struct platform_device *pdev)
 {
 	struct device_node	*node = pdev->dev.of_node;
 	struct resource		*res;
@@ -515,10 +457,19 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
 	pm_runtime_get_sync(dev);
 	pm_runtime_forbid(dev);
 
+	dwc3_cache_hwparams(dwc);
+
+	ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
+	if (ret) {
+		dev_err(dwc->dev, "failed to allocate event buffers\n");
+		ret = -ENOMEM;
+		goto err0;
+	}
+
 	ret = dwc3_core_init(dwc);
 	if (ret) {
 		dev_err(dev, "failed to initialize core\n");
-		return ret;
+		goto err0;
 	}
 
 	mode = DWC3_MODE(dwc->hwparams.hwparams0);
@@ -590,10 +541,13 @@ err2:
 err1:
 	dwc3_core_exit(dwc);
 
+err0:
+	dwc3_free_event_buffers(dwc);
+
 	return ret;
 }
 
-static int __devexit dwc3_remove(struct platform_device *pdev)
+static int dwc3_remove(struct platform_device *pdev)
 {
 	struct dwc3	*dwc = platform_get_drvdata(pdev);
 	struct resource	*res;
@@ -628,7 +582,7 @@ static int __devexit dwc3_remove(struct platform_device *pdev)
 
 static struct platform_driver dwc3_driver = {
 	.probe		= dwc3_probe,
-	.remove		= __devexit_p(dwc3_remove),
+	.remove		= dwc3_remove,
 	.driver		= {
 		.name	= "dwc3",
 	},
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 243affc..4999563 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -868,7 +868,4 @@ void dwc3_host_exit(struct dwc3 *dwc);
 int dwc3_gadget_init(struct dwc3 *dwc);
 void dwc3_gadget_exit(struct dwc3 *dwc);
 
-extern int dwc3_get_device_id(void);
-extern void dwc3_put_device_id(int id);
-
 #endif /* __DRIVERS_USB_DWC3_CORE_H */
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index d4a30f1..92604b4 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
@@ -652,7 +652,7 @@ static const struct file_operations dwc3_link_state_fops = {
 	.release		= single_release,
 };
 
-int __devinit dwc3_debugfs_init(struct dwc3 *dwc)
+int dwc3_debugfs_init(struct dwc3 *dwc)
 {
 	struct dentry		*root;
 	struct dentry		*file;
@@ -703,7 +703,7 @@ err0:
 	return ret;
 }
 
-void __devexit dwc3_debugfs_exit(struct dwc3 *dwc)
+void dwc3_debugfs_exit(struct dwc3 *dwc)
 {
 	debugfs_remove_recursive(dwc->root);
 	dwc->root = NULL;
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index ca65978..aae5328 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -21,6 +21,7 @@
 #include <linux/clk.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/nop-usb-xceiv.h>
+#include <linux/of.h>
 
 #include "core.h"
 
@@ -33,7 +34,7 @@ struct dwc3_exynos {
 	struct clk		*clk;
 };
 
-static int __devinit dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
+static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
 {
 	struct nop_usb_xceiv_platform_data pdata;
 	struct platform_device	*pdev;
@@ -87,14 +88,14 @@ err1:
 	return ret;
 }
 
-static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
+static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32);
+
+static int dwc3_exynos_probe(struct platform_device *pdev)
 {
-	struct dwc3_exynos_data	*pdata = pdev->dev.platform_data;
 	struct platform_device	*dwc3;
 	struct dwc3_exynos	*exynos;
 	struct clk		*clk;
 
-	int			devid;
 	int			ret = -ENOMEM;
 
 	exynos = kzalloc(sizeof(*exynos), GFP_KERNEL);
@@ -103,11 +104,15 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
 		goto err0;
 	}
 
-	platform_set_drvdata(pdev, exynos);
+	/*
+	 * 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 = &dwc3_exynos_dma_mask;
 
-	devid = dwc3_get_device_id();
-	if (devid < 0)
-		goto err1;
+	platform_set_drvdata(pdev, exynos);
 
 	ret = dwc3_exynos_register_phys(exynos);
 	if (ret) {
@@ -115,10 +120,10 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
 		goto err1;
 	}
 
-	dwc3 = platform_device_alloc("dwc3", devid);
+	dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
 	if (!dwc3) {
 		dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
-		goto err2;
+		goto err1;
 	}
 
 	clk = clk_get(&pdev->dev, "usbdrd30");
@@ -139,14 +144,6 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
 
 	clk_enable(exynos->clk);
 
-	/* PHY initialization */
-	if (!pdata) {
-		dev_dbg(&pdev->dev, "missing platform data\n");
-	} else {
-		if (pdata->phy_init)
-			pdata->phy_init(pdev, pdata->phy_type);
-	}
-
 	ret = platform_device_add_resources(dwc3, pdev->resource,
 			pdev->num_resources);
 	if (ret) {
@@ -163,35 +160,24 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
 	return 0;
 
 err4:
-	if (pdata && pdata->phy_exit)
-		pdata->phy_exit(pdev, pdata->phy_type);
-
 	clk_disable(clk);
 	clk_put(clk);
 err3:
 	platform_device_put(dwc3);
-err2:
-	dwc3_put_device_id(devid);
 err1:
 	kfree(exynos);
 err0:
 	return ret;
 }
 
-static int __devexit dwc3_exynos_remove(struct platform_device *pdev)
+static int dwc3_exynos_remove(struct platform_device *pdev)
 {
 	struct dwc3_exynos	*exynos = platform_get_drvdata(pdev);
-	struct dwc3_exynos_data *pdata = pdev->dev.platform_data;
 
 	platform_device_unregister(exynos->dwc3);
 	platform_device_unregister(exynos->usb2_phy);
 	platform_device_unregister(exynos->usb3_phy);
 
-	dwc3_put_device_id(exynos->dwc3->id);
-
-	if (pdata && pdata->phy_exit)
-		pdata->phy_exit(pdev, pdata->phy_type);
-
 	clk_disable(exynos->clk);
 	clk_put(exynos->clk);
 
@@ -200,11 +186,20 @@ static int __devexit dwc3_exynos_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id exynos_dwc3_match[] = {
+	{ .compatible = "samsung,exynos-dwc3" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
+#endif
+
 static struct platform_driver dwc3_exynos_driver = {
 	.probe		= dwc3_exynos_probe,
-	.remove		= __devexit_p(dwc3_exynos_remove),
+	.remove		= dwc3_exynos_remove,
 	.driver		= {
 		.name	= "exynos-dwc3",
+		.of_match_table = of_match_ptr(exynos_dwc3_match),
 	},
 };
 
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index ee57a10..f31867f 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -157,7 +157,7 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
 	writel(value, base + offset);
 }
 
-static int __devinit dwc3_omap_register_phys(struct dwc3_omap *omap)
+static int dwc3_omap_register_phys(struct dwc3_omap *omap)
 {
 	struct nop_usb_xceiv_platform_data pdata;
 	struct platform_device	*pdev;
@@ -262,7 +262,7 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
 	return IRQ_HANDLED;
 }
 
-static int __devinit dwc3_omap_probe(struct platform_device *pdev)
+static int dwc3_omap_probe(struct platform_device *pdev)
 {
 	struct dwc3_omap_data	*pdata = pdev->dev.platform_data;
 	struct device_node	*node = pdev->dev.of_node;
@@ -272,7 +272,6 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
 	struct resource		*res;
 	struct device		*dev = &pdev->dev;
 
-	int			devid;
 	int			size;
 	int			ret = -ENOMEM;
 	int			irq;
@@ -315,14 +314,10 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	devid = dwc3_get_device_id();
-	if (devid < 0)
-		return -ENODEV;
-
-	dwc3 = platform_device_alloc("dwc3", devid);
+	dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
 	if (!dwc3) {
 		dev_err(dev, "couldn't allocate dwc3 device\n");
-		goto err1;
+		return -ENOMEM;
 	}
 
 	context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL);
@@ -423,23 +418,16 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
 
 err2:
 	platform_device_put(dwc3);
-
-err1:
-	dwc3_put_device_id(devid);
-
 	return ret;
 }
 
-static int __devexit dwc3_omap_remove(struct platform_device *pdev)
+static int dwc3_omap_remove(struct platform_device *pdev)
 {
 	struct dwc3_omap	*omap = platform_get_drvdata(pdev);
 
 	platform_device_unregister(omap->dwc3);
 	platform_device_unregister(omap->usb2_phy);
 	platform_device_unregister(omap->usb3_phy);
-
-	dwc3_put_device_id(omap->dwc3->id);
-
 	return 0;
 }
 
@@ -453,7 +441,7 @@ MODULE_DEVICE_TABLE(of, of_dwc3_matach);
 
 static struct platform_driver dwc3_omap_driver = {
 	.probe		= dwc3_omap_probe,
-	.remove		= __devexit_p(dwc3_omap_remove),
+	.remove		= dwc3_omap_remove,
 	.driver		= {
 		.name	= "omap-dwc3",
 		.of_match_table	= of_dwc3_matach,
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index 94f550e..7d70f44 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -58,7 +58,7 @@ struct dwc3_pci {
 	struct platform_device	*usb3_phy;
 };
 
-static int __devinit dwc3_pci_register_phys(struct dwc3_pci *glue)
+static int dwc3_pci_register_phys(struct dwc3_pci *glue)
 {
 	struct nop_usb_xceiv_platform_data pdata;
 	struct platform_device	*pdev;
@@ -112,14 +112,13 @@ err1:
 	return ret;
 }
 
-static int __devinit dwc3_pci_probe(struct pci_dev *pci,
+static int dwc3_pci_probe(struct pci_dev *pci,
 		const struct pci_device_id *id)
 {
 	struct resource		res[2];
 	struct platform_device	*dwc3;
 	struct dwc3_pci		*glue;
 	int			ret = -ENOMEM;
-	int			devid;
 	struct device		*dev = &pci->dev;
 
 	glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
@@ -145,13 +144,7 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci,
 		return ret;
 	}
 
-	devid = dwc3_get_device_id();
-	if (devid < 0) {
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	dwc3 = platform_device_alloc("dwc3", devid);
+	dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
 	if (!dwc3) {
 		dev_err(dev, "couldn't allocate dwc3 device\n");
 		ret = -ENOMEM;
@@ -172,7 +165,7 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci,
 	ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res));
 	if (ret) {
 		dev_err(dev, "couldn't add resources to dwc3 device\n");
-		goto err2;
+		goto err1;
 	}
 
 	pci_set_drvdata(pci, glue);
@@ -195,23 +188,18 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci,
 err3:
 	pci_set_drvdata(pci, NULL);
 	platform_device_put(dwc3);
-
-err2:
-	dwc3_put_device_id(devid);
-
 err1:
 	pci_disable_device(pci);
 
 	return ret;
 }
 
-static void __devexit dwc3_pci_remove(struct pci_dev *pci)
+static void dwc3_pci_remove(struct pci_dev *pci)
 {
 	struct dwc3_pci	*glue = pci_get_drvdata(pci);
 
 	platform_device_unregister(glue->usb2_phy);
 	platform_device_unregister(glue->usb3_phy);
-	dwc3_put_device_id(glue->dwc3->id);
 	platform_device_unregister(glue->dwc3);
 	pci_set_drvdata(pci, NULL);
 	pci_disable_device(pci);
@@ -230,7 +218,7 @@ static struct pci_driver dwc3_pci_driver = {
 	.name		= "dwc3-pci",
 	.id_table	= dwc3_pci_id_table,
 	.probe		= dwc3_pci_probe,
-	.remove		= __devexit_p(dwc3_pci_remove),
+	.remove		= dwc3_pci_remove,
 };
 
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 7b7dedd..2e43b33 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1579,7 +1579,7 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
 
 /* -------------------------------------------------------------------------- */
 
-static int __devinit dwc3_gadget_init_endpoints(struct dwc3 *dwc)
+static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
 {
 	struct dwc3_ep			*dep;
 	u8				epnum;
@@ -2374,7 +2374,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
  *
  * Returns 0 on success otherwise negative errno.
  */
-int __devinit dwc3_gadget_init(struct dwc3 *dwc)
+int dwc3_gadget_init(struct dwc3 *dwc)
 {
 	u32					reg;
 	int					ret;
diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c
index 4bfa78a..5e29dde 100644
--- a/drivers/usb/early/ehci-dbgp.c
+++ b/drivers/usb/early/ehci-dbgp.c
@@ -974,7 +974,7 @@ struct console early_dbgp_console = {
 	.index =	-1,
 };
 
-#if IS_ENABLED(CONFIG_USB_EHCI_HCD)
+#if IS_ENABLED(CONFIG_USB)
 int dbgp_reset_prep(struct usb_hcd *hcd)
 {
 	int ret = xen_dbgp_reset_prep(hcd);
@@ -1008,7 +1008,7 @@ int dbgp_external_startup(struct usb_hcd *hcd)
 	return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
 }
 EXPORT_SYMBOL_GPL(dbgp_external_startup);
-#endif /* USB_EHCI_HCD */
+#endif /* USB */
 
 #ifdef CONFIG_KGDB
 
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index e0ff51b..14625fd 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -721,31 +721,6 @@ config USB_FUNCTIONFS_GENERIC
 	  Include a configuration with the Function Filesystem alone with
 	  no Ethernet interface.
 
-config USB_FILE_STORAGE
-	tristate "File-backed Storage Gadget (DEPRECATED)"
-	depends on BLOCK
-	help
-	  The File-backed 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.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_file_storage".
-
-	  NOTE: This driver is deprecated.  Its replacement is the
-	  Mass Storage Gadget.
-
-config USB_FILE_STORAGE_TEST
-	bool "File-backed Storage Gadget testing version"
-	depends on USB_FILE_STORAGE
-	default n
-	help
-	  Say "y" to generate the larger testing version of the
-	  File-backed Storage Gadget, useful for probing the
-	  behavior of USB Mass Storage hosts.  Not needed for
-	  normal operation.
-
 config USB_MASS_STORAGE
 	tristate "Mass Storage Gadget"
 	depends on BLOCK
@@ -756,8 +731,8 @@ config USB_MASS_STORAGE
 	  device (in much the same way as the "loop" device driver),
 	  specified as a module parameter or sysfs option.
 
-	  This driver is an updated replacement for the deprecated
-	  File-backed Storage Gadget (g_file_storage).
+	  This driver is a replacement for now removed File-backed
+	  Storage Gadget (g_file_storage).
 
 	  Say "y" to link the driver statically, or "m" to build
 	  a dynamically linked module called "g_mass_storage".
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 307be5f..8b4acfd 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -44,7 +44,6 @@ g_ether-y			:= ether.o
 g_serial-y			:= serial.o
 g_midi-y			:= gmidi.o
 gadgetfs-y			:= inode.o
-g_file_storage-y		:= file_storage.o
 g_mass_storage-y		:= mass_storage.o
 g_printer-y			:= printer.o
 g_cdc-y				:= cdc2.o
@@ -62,7 +61,6 @@ obj-$(CONFIG_USB_AUDIO)		+= g_audio.o
 obj-$(CONFIG_USB_ETH)		+= g_ether.o
 obj-$(CONFIG_USB_GADGETFS)	+= gadgetfs.o
 obj-$(CONFIG_USB_FUNCTIONFS)	+= g_ffs.o
-obj-$(CONFIG_USB_FILE_STORAGE)	+= g_file_storage.o
 obj-$(CONFIG_USB_MASS_STORAGE)	+= g_mass_storage.o
 obj-$(CONFIG_USB_G_SERIAL)	+= g_serial.o
 obj-$(CONFIG_USB_G_PRINTER)	+= g_printer.o
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index fc0ec5e..ba6f2a1 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -3133,7 +3133,7 @@ static int init_dma_pools(struct udc *dev)
 	}
 
 	/* DMA setup */
-	dev->data_requests = dma_pool_create("data_requests", NULL,
+	dev->data_requests = dma_pool_create("data_requests", &dev->pdev->dev,
 		sizeof(struct udc_data_dma), 0, 0);
 	if (!dev->data_requests) {
 		DBG(dev, "can't get request data pool\n");
@@ -3145,7 +3145,7 @@ static int init_dma_pools(struct udc *dev)
 	dev->ep[UDC_EP0IN_IX].dma = &dev->regs->ctl;
 
 	/* dma desc for setup data */
-	dev->stp_requests = dma_pool_create("setup requests", NULL,
+	dev->stp_requests = dma_pool_create("setup requests", &dev->pdev->dev,
 		sizeof(struct udc_stp_dma), 0, 0);
 	if (!dev->stp_requests) {
 		DBG(dev, "can't get stp request pool\n");
@@ -3266,6 +3266,12 @@ static int udc_pci_probe(
 	pci_set_master(pdev);
 	pci_try_set_mwi(pdev);
 
+	dev->phys_addr = resource;
+	dev->irq = pdev->irq;
+	dev->pdev = pdev;
+	dev->gadget.dev.parent = &pdev->dev;
+	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
+
 	/* init dma pools */
 	if (use_dma) {
 		retval = init_dma_pools(dev);
@@ -3273,12 +3279,6 @@ static int udc_pci_probe(
 			goto finished;
 	}
 
-	dev->phys_addr = resource;
-	dev->irq = pdev->irq;
-	dev->pdev = pdev;
-	dev->gadget.dev.parent = &pdev->dev;
-	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
 	/* general probing */
 	if (udc_probe(dev) == 0)
 		return 0;
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 89d90b5..f4a21f6 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -31,6 +31,7 @@
 #include <linux/usb/gadget.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
+#include <linux/platform_data/atmel.h>
 
 #include <asm/byteorder.h>
 #include <mach/hardware.h>
@@ -38,7 +39,6 @@
 #include <asm/irq.h>
 #include <asm/gpio.h>
 
-#include <mach/board.h>
 #include <mach/cpu.h>
 #include <mach/at91sam9261_matrix.h>
 #include <mach/at91_matrix.h>
@@ -51,7 +51,7 @@
  * full speed USB controllers, including the at91rm9200 (arm920T, with MMU),
  * at91sam926x (arm926ejs, with MMU), and several no-mmu versions.
  *
- * This driver expects the board has been wired with two GPIOs suppporting
+ * This driver expects the board has been wired with two GPIOs supporting
  * a VBUS sensing IRQ, and a D+ pullup.  (They may be omitted, but the
  * testing hasn't covered such cases.)
  *
@@ -1673,7 +1673,7 @@ static void at91udc_shutdown(struct platform_device *dev)
 	spin_unlock_irqrestore(&udc->lock, flags);
 }
 
-static void __devinit at91udc_of_init(struct at91_udc *udc,
+static void at91udc_of_init(struct at91_udc *udc,
 				     struct device_node *np)
 {
 	struct at91_udc_data *board = &udc->board;
@@ -1693,7 +1693,7 @@ static void __devinit at91udc_of_init(struct at91_udc *udc,
 	board->pullup_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
 }
 
-static int __devinit at91udc_probe(struct platform_device *pdev)
+static int at91udc_probe(struct platform_device *pdev)
 {
 	struct device	*dev = &pdev->dev;
 	struct at91_udc	*udc;
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index 9a9bced..a7aed84 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -21,9 +21,9 @@
 #include <linux/usb/gadget.h>
 #include <linux/usb/atmel_usba_udc.h>
 #include <linux/delay.h>
+#include <linux/platform_data/atmel.h>
 
 #include <asm/gpio.h>
-#include <mach/board.h>
 
 #include "atmel_usba_udc.h"
 
diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c
index 9ca7922..47a4993 100644
--- a/drivers/usb/gadget/bcm63xx_udc.c
+++ b/drivers/usb/gadget/bcm63xx_udc.c
@@ -2323,7 +2323,7 @@ static void bcm63xx_udc_gadget_release(struct device *dev)
  * Note that platform data is required, because pd.port_no varies from chip
  * to chip and is used to switch the correct USB port to device mode.
  */
-static int __devinit bcm63xx_udc_probe(struct platform_device *pdev)
+static int bcm63xx_udc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct bcm63xx_usbd_platform_data *pd = dev->platform_data;
@@ -2433,7 +2433,7 @@ out_uninit:
  * bcm63xx_udc_remove - Remove the device from the system.
  * @pdev: Platform device struct from the bcm63xx BSP code.
  */
-static int __devexit bcm63xx_udc_remove(struct platform_device *pdev)
+static int bcm63xx_udc_remove(struct platform_device *pdev)
 {
 	struct bcm63xx_udc *udc = platform_get_drvdata(pdev);
 
@@ -2450,7 +2450,7 @@ static int __devexit bcm63xx_udc_remove(struct platform_device *pdev)
 
 static struct platform_driver bcm63xx_udc_driver = {
 	.probe		= bcm63xx_udc_probe,
-	.remove		= __devexit_p(bcm63xx_udc_remove),
+	.remove		= bcm63xx_udc_remove,
 	.driver		= {
 		.name	= DRV_MODULE_NAME,
 		.owner	= THIS_MODULE,
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 957f973..2a6bfe7 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -107,7 +107,7 @@ int config_ep_by_speed(struct usb_gadget *g,
 		}
 		/* else: fall through */
 	default:
-		speed_desc = f->descriptors;
+		speed_desc = f->fs_descriptors;
 	}
 	/* find descriptors */
 	for_each_ep_desc(speed_desc, d_spd) {
@@ -200,7 +200,7 @@ int usb_add_function(struct usb_configuration *config,
 	 * as full speed ... it's the function drivers that will need
 	 * to avoid bulk and ISO transfers.
 	 */
-	if (!config->fullspeed && function->descriptors)
+	if (!config->fullspeed && function->fs_descriptors)
 		config->fullspeed = true;
 	if (!config->highspeed && function->hs_descriptors)
 		config->highspeed = true;
@@ -363,7 +363,7 @@ static int config_buf(struct usb_configuration *config,
 			descriptors = f->hs_descriptors;
 			break;
 		default:
-			descriptors = f->descriptors;
+			descriptors = f->fs_descriptors;
 		}
 
 		if (!descriptors)
@@ -620,7 +620,7 @@ static int set_config(struct usb_composite_dev *cdev,
 			descriptors = f->hs_descriptors;
 			break;
 		default:
-			descriptors = f->descriptors;
+			descriptors = f->fs_descriptors;
 		}
 
 		for (; *descriptors; ++descriptors) {
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index e3a9892..34e12fc 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -19,7 +19,7 @@
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
-
+#include <linux/usb/composite.h>
 
 /**
  * usb_descriptor_fillbuf - fill buffer with descriptors
@@ -158,3 +158,40 @@ usb_copy_descriptors(struct usb_descriptor_header **src)
 	return ret;
 }
 EXPORT_SYMBOL_GPL(usb_copy_descriptors);
+
+int usb_assign_descriptors(struct usb_function *f,
+		struct usb_descriptor_header **fs,
+		struct usb_descriptor_header **hs,
+		struct usb_descriptor_header **ss)
+{
+	struct usb_gadget *g = f->config->cdev->gadget;
+
+	if (fs) {
+		f->fs_descriptors = usb_copy_descriptors(fs);
+		if (!f->fs_descriptors)
+			goto err;
+	}
+	if (hs && gadget_is_dualspeed(g)) {
+		f->hs_descriptors = usb_copy_descriptors(hs);
+		if (!f->hs_descriptors)
+			goto err;
+	}
+	if (ss && gadget_is_superspeed(g)) {
+		f->ss_descriptors = usb_copy_descriptors(ss);
+		if (!f->ss_descriptors)
+			goto err;
+	}
+	return 0;
+err:
+	usb_free_all_descriptors(f);
+	return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(usb_assign_descriptors);
+
+void usb_free_all_descriptors(struct usb_function *f)
+{
+	usb_free_descriptors(f->fs_descriptors);
+	usb_free_descriptors(f->hs_descriptors);
+	usb_free_descriptors(f->ss_descriptors);
+}
+EXPORT_SYMBOL_GPL(usb_free_all_descriptors);
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 0f7541b..95d584d 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -63,16 +63,20 @@ MODULE_LICENSE("GPL");
 struct dummy_hcd_module_parameters {
 	bool is_super_speed;
 	bool is_high_speed;
+	unsigned int num;
 };
 
 static struct dummy_hcd_module_parameters mod_data = {
 	.is_super_speed = false,
 	.is_high_speed = true,
+	.num = 1,
 };
 module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO);
 MODULE_PARM_DESC(is_super_speed, "true to simulate SuperSpeed connection");
 module_param_named(is_high_speed, mod_data.is_high_speed, bool, S_IRUGO);
 MODULE_PARM_DESC(is_high_speed, "true to simulate HighSpeed connection");
+module_param_named(num, mod_data.num, uint, S_IRUGO);
+MODULE_PARM_DESC(num, "number of emulated controllers");
 /*-------------------------------------------------------------------------*/
 
 /* gadget side driver data structres */
@@ -238,8 +242,6 @@ static inline struct dummy *gadget_dev_to_dummy(struct device *dev)
 	return container_of(dev, struct dummy, gadget.dev);
 }
 
-static struct dummy			the_controller;
-
 /*-------------------------------------------------------------------------*/
 
 /* SLAVE/GADGET SIDE UTILITY ROUTINES */
@@ -973,9 +975,10 @@ static void init_dummy_udc_hw(struct dummy *dum)
 
 static int dummy_udc_probe(struct platform_device *pdev)
 {
-	struct dummy	*dum = &the_controller;
+	struct dummy	*dum;
 	int		rc;
 
+	dum = *((void **)dev_get_platdata(&pdev->dev));
 	dum->gadget.name = gadget_name;
 	dum->gadget.ops = &dummy_ops;
 	dum->gadget.max_speed = USB_SPEED_SUPER;
@@ -2398,10 +2401,13 @@ static int dummy_h_get_frame(struct usb_hcd *hcd)
 
 static int dummy_setup(struct usb_hcd *hcd)
 {
+	struct dummy *dum;
+
+	dum = *((void **)dev_get_platdata(hcd->self.controller));
 	hcd->self.sg_tablesize = ~0;
 	if (usb_hcd_is_primary_hcd(hcd)) {
-		the_controller.hs_hcd = hcd_to_dummy_hcd(hcd);
-		the_controller.hs_hcd->dum = &the_controller;
+		dum->hs_hcd = hcd_to_dummy_hcd(hcd);
+		dum->hs_hcd->dum = dum;
 		/*
 		 * Mark the first roothub as being USB 2.0.
 		 * The USB 3.0 roothub will be registered later by
@@ -2410,8 +2416,8 @@ static int dummy_setup(struct usb_hcd *hcd)
 		hcd->speed = HCD_USB2;
 		hcd->self.root_hub->speed = USB_SPEED_HIGH;
 	} else {
-		the_controller.ss_hcd = hcd_to_dummy_hcd(hcd);
-		the_controller.ss_hcd->dum = &the_controller;
+		dum->ss_hcd = hcd_to_dummy_hcd(hcd);
+		dum->ss_hcd->dum = dum;
 		hcd->speed = HCD_USB3;
 		hcd->self.root_hub->speed = USB_SPEED_SUPER;
 	}
@@ -2524,11 +2530,13 @@ static struct hc_driver dummy_hcd = {
 
 static int dummy_hcd_probe(struct platform_device *pdev)
 {
+	struct dummy		*dum;
 	struct usb_hcd		*hs_hcd;
 	struct usb_hcd		*ss_hcd;
 	int			retval;
 
 	dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
+	dum = *((void **)dev_get_platdata(&pdev->dev));
 
 	if (!mod_data.is_super_speed)
 		dummy_hcd.flags = HCD_USB2;
@@ -2561,7 +2569,7 @@ dealloc_usb2_hcd:
 	usb_remove_hcd(hs_hcd);
 put_usb2_hcd:
 	usb_put_hcd(hs_hcd);
-	the_controller.hs_hcd = the_controller.ss_hcd = NULL;
+	dum->hs_hcd = dum->ss_hcd = NULL;
 	return retval;
 }
 
@@ -2579,8 +2587,8 @@ static int dummy_hcd_remove(struct platform_device *pdev)
 	usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
 	usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
 
-	the_controller.hs_hcd = NULL;
-	the_controller.ss_hcd = NULL;
+	dum->hs_hcd = NULL;
+	dum->ss_hcd = NULL;
 
 	return 0;
 }
@@ -2627,13 +2635,15 @@ static struct platform_driver dummy_hcd_driver = {
 };
 
 /*-------------------------------------------------------------------------*/
-
-static struct platform_device *the_udc_pdev;
-static struct platform_device *the_hcd_pdev;
+#define MAX_NUM_UDC	2
+static struct platform_device *the_udc_pdev[MAX_NUM_UDC];
+static struct platform_device *the_hcd_pdev[MAX_NUM_UDC];
 
 static int __init init(void)
 {
 	int	retval = -ENOMEM;
+	int	i;
+	struct	dummy *dum[MAX_NUM_UDC];
 
 	if (usb_disabled())
 		return -ENODEV;
@@ -2641,65 +2651,129 @@ static int __init init(void)
 	if (!mod_data.is_high_speed && mod_data.is_super_speed)
 		return -EINVAL;
 
-	the_hcd_pdev = platform_device_alloc(driver_name, -1);
-	if (!the_hcd_pdev)
-		return retval;
-	the_udc_pdev = platform_device_alloc(gadget_name, -1);
-	if (!the_udc_pdev)
-		goto err_alloc_udc;
+	if (mod_data.num < 1 || mod_data.num > MAX_NUM_UDC) {
+		pr_err("Number of emulated UDC must be in range of 1…%d\n",
+				MAX_NUM_UDC);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < mod_data.num; i++) {
+		the_hcd_pdev[i] = platform_device_alloc(driver_name, i);
+		if (!the_hcd_pdev[i]) {
+			i--;
+			while (i >= 0)
+				platform_device_put(the_hcd_pdev[i--]);
+			return retval;
+		}
+	}
+	for (i = 0; i < mod_data.num; i++) {
+		the_udc_pdev[i] = platform_device_alloc(gadget_name, i);
+		if (!the_udc_pdev[i]) {
+			i--;
+			while (i >= 0)
+				platform_device_put(the_udc_pdev[i--]);
+			goto err_alloc_udc;
+		}
+	}
+	for (i = 0; i < mod_data.num; i++) {
+		dum[i] = kzalloc(sizeof(struct dummy), GFP_KERNEL);
+		if (!dum[i])
+			goto err_add_pdata;
+		retval = platform_device_add_data(the_hcd_pdev[i], &dum[i],
+				sizeof(void *));
+		if (retval)
+			goto err_add_pdata;
+		retval = platform_device_add_data(the_udc_pdev[i], &dum[i],
+				sizeof(void *));
+		if (retval)
+			goto err_add_pdata;
+	}
 
 	retval = platform_driver_register(&dummy_hcd_driver);
 	if (retval < 0)
-		goto err_register_hcd_driver;
+		goto err_add_pdata;
 	retval = platform_driver_register(&dummy_udc_driver);
 	if (retval < 0)
 		goto err_register_udc_driver;
 
-	retval = platform_device_add(the_hcd_pdev);
-	if (retval < 0)
-		goto err_add_hcd;
-	if (!the_controller.hs_hcd ||
-	    (!the_controller.ss_hcd && mod_data.is_super_speed)) {
-		/*
-		 * The hcd was added successfully but its probe function failed
-		 * for some reason.
-		 */
-		retval = -EINVAL;
-		goto err_add_udc;
+	for (i = 0; i < mod_data.num; i++) {
+		retval = platform_device_add(the_hcd_pdev[i]);
+		if (retval < 0) {
+			i--;
+			while (i >= 0)
+				platform_device_del(the_hcd_pdev[i--]);
+			goto err_add_hcd;
+		}
 	}
-	retval = platform_device_add(the_udc_pdev);
-	if (retval < 0)
-		goto err_add_udc;
-	if (!platform_get_drvdata(the_udc_pdev)) {
-		/*
-		 * The udc was added successfully but its probe function failed
-		 * for some reason.
-		 */
-		retval = -EINVAL;
-		goto err_probe_udc;
+	for (i = 0; i < mod_data.num; i++) {
+		if (!dum[i]->hs_hcd ||
+				(!dum[i]->ss_hcd && mod_data.is_super_speed)) {
+			/*
+			 * The hcd was added successfully but its probe
+			 * function failed for some reason.
+			 */
+			retval = -EINVAL;
+			goto err_add_udc;
+		}
+	}
+
+	for (i = 0; i < mod_data.num; i++) {
+		retval = platform_device_add(the_udc_pdev[i]);
+		if (retval < 0) {
+			i--;
+			while (i >= 0)
+				platform_device_del(the_udc_pdev[i]);
+			goto err_add_udc;
+		}
+	}
+
+	for (i = 0; i < mod_data.num; i++) {
+		if (!platform_get_drvdata(the_udc_pdev[i])) {
+			/*
+			 * The udc was added successfully but its probe
+			 * function failed for some reason.
+			 */
+			retval = -EINVAL;
+			goto err_probe_udc;
+		}
 	}
 	return retval;
 
 err_probe_udc:
-	platform_device_del(the_udc_pdev);
+	for (i = 0; i < mod_data.num; i++)
+		platform_device_del(the_udc_pdev[i]);
 err_add_udc:
-	platform_device_del(the_hcd_pdev);
+	for (i = 0; i < mod_data.num; i++)
+		platform_device_del(the_hcd_pdev[i]);
 err_add_hcd:
 	platform_driver_unregister(&dummy_udc_driver);
 err_register_udc_driver:
 	platform_driver_unregister(&dummy_hcd_driver);
-err_register_hcd_driver:
-	platform_device_put(the_udc_pdev);
+err_add_pdata:
+	for (i = 0; i < mod_data.num; i++)
+		kfree(dum[i]);
+	for (i = 0; i < mod_data.num; i++)
+		platform_device_put(the_udc_pdev[i]);
 err_alloc_udc:
-	platform_device_put(the_hcd_pdev);
+	for (i = 0; i < mod_data.num; i++)
+		platform_device_put(the_hcd_pdev[i]);
 	return retval;
 }
 module_init(init);
 
 static void __exit cleanup(void)
 {
-	platform_device_unregister(the_udc_pdev);
-	platform_device_unregister(the_hcd_pdev);
+	int i;
+
+	for (i = 0; i < mod_data.num; i++) {
+		struct dummy *dum;
+
+		dum = *((void **)dev_get_platdata(&the_udc_pdev[i]->dev));
+
+		platform_device_unregister(the_udc_pdev[i]);
+		platform_device_unregister(the_hcd_pdev[i]);
+		kfree(dum);
+	}
 	platform_driver_unregister(&dummy_udc_driver);
 	platform_driver_unregister(&dummy_hcd_driver);
 }
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index d672250a..5491744 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -87,7 +87,7 @@ static inline struct f_acm *port_to_acm(struct gserial *p)
 
 /* notification endpoint uses smallish and infrequent fixed-size messages */
 
-#define GS_LOG2_NOTIFY_INTERVAL		5	/* 1 << 5 == 32 msec */
+#define GS_NOTIFY_INTERVAL_MS		32
 #define GS_NOTIFY_MAXPACKET		10	/* notification + 2 bytes */
 
 /* interface and class descriptors: */
@@ -167,7 +167,7 @@ static struct usb_endpoint_descriptor acm_fs_notify_desc = {
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
 	.wMaxPacketSize =	cpu_to_le16(GS_NOTIFY_MAXPACKET),
-	.bInterval =		1 << GS_LOG2_NOTIFY_INTERVAL,
+	.bInterval =		GS_NOTIFY_INTERVAL_MS,
 };
 
 static struct usb_endpoint_descriptor acm_fs_in_desc = {
@@ -199,14 +199,13 @@ static struct usb_descriptor_header *acm_fs_function[] = {
 };
 
 /* high speed support: */
-
 static struct usb_endpoint_descriptor acm_hs_notify_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
 	.wMaxPacketSize =	cpu_to_le16(GS_NOTIFY_MAXPACKET),
-	.bInterval =		GS_LOG2_NOTIFY_INTERVAL+4,
+	.bInterval =		USB_MS_TO_HS_INTERVAL(GS_NOTIFY_INTERVAL_MS),
 };
 
 static struct usb_endpoint_descriptor acm_hs_in_desc = {
@@ -659,37 +658,22 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
 	acm->notify_req->complete = acm_cdc_notify_complete;
 	acm->notify_req->context = acm;
 
-	/* copy descriptors */
-	f->descriptors = usb_copy_descriptors(acm_fs_function);
-	if (!f->descriptors)
-		goto fail;
-
 	/* support all relevant hardware speeds... we expect that when
 	 * hardware is dual speed, all bulk-capable endpoints work at
 	 * both speeds
 	 */
-	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		acm_hs_in_desc.bEndpointAddress =
-				acm_fs_in_desc.bEndpointAddress;
-		acm_hs_out_desc.bEndpointAddress =
-				acm_fs_out_desc.bEndpointAddress;
-		acm_hs_notify_desc.bEndpointAddress =
-				acm_fs_notify_desc.bEndpointAddress;
-
-		/* copy descriptors */
-		f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
-	}
-	if (gadget_is_superspeed(c->cdev->gadget)) {
-		acm_ss_in_desc.bEndpointAddress =
-			acm_fs_in_desc.bEndpointAddress;
-		acm_ss_out_desc.bEndpointAddress =
-			acm_fs_out_desc.bEndpointAddress;
-
-		/* copy descriptors, and track endpoint copies */
-		f->ss_descriptors = usb_copy_descriptors(acm_ss_function);
-		if (!f->ss_descriptors)
-			goto fail;
-	}
+	acm_hs_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress;
+	acm_hs_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress;
+	acm_hs_notify_desc.bEndpointAddress =
+		acm_fs_notify_desc.bEndpointAddress;
+
+	acm_ss_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress;
+	acm_ss_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress;
+
+	status = usb_assign_descriptors(f, acm_fs_function, acm_hs_function,
+			acm_ss_function);
+	if (status)
+		goto fail;
 
 	DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
 			acm->port_num,
@@ -721,11 +705,8 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f)
 {
 	struct f_acm		*acm = func_to_acm(f);
 
-	if (gadget_is_dualspeed(c->cdev->gadget))
-		usb_free_descriptors(f->hs_descriptors);
-	if (gadget_is_superspeed(c->cdev->gadget))
-		usb_free_descriptors(f->ss_descriptors);
-	usb_free_descriptors(f->descriptors);
+	acm_string_defs[0].id = 0;
+	usb_free_all_descriptors(f);
 	gs_free_req(acm->notify, acm->notify_req);
 	kfree(acm);
 }
@@ -762,27 +743,15 @@ int acm_bind_config(struct usb_configuration *c, u8 port_num)
 	 */
 
 	/* maybe allocate device-global string IDs, and patch descriptors */
-	if (acm_string_defs[ACM_CTRL_IDX].id == 0) {
-		status = usb_string_id(c->cdev);
+	if (acm_string_defs[0].id == 0) {
+		status = usb_string_ids_tab(c->cdev, acm_string_defs);
 		if (status < 0)
 			return status;
-		acm_string_defs[ACM_CTRL_IDX].id = status;
-
-		acm_control_interface_desc.iInterface = status;
-
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		acm_string_defs[ACM_DATA_IDX].id = status;
-
-		acm_data_interface_desc.iInterface = status;
-
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		acm_string_defs[ACM_IAD_IDX].id = status;
-
-		acm_iad_descriptor.iFunction = status;
+		acm_control_interface_desc.iInterface =
+			acm_string_defs[ACM_CTRL_IDX].id;
+		acm_data_interface_desc.iInterface =
+			acm_string_defs[ACM_DATA_IDX].id;
+		acm_iad_descriptor.iFunction = acm_string_defs[ACM_IAD_IDX].id;
 	}
 
 	/* allocate and initialize one new instance */
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
index 95bc94f..83420a3 100644
--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/f_ecm.c
@@ -91,7 +91,7 @@ static inline unsigned ecm_bitrate(struct usb_gadget *g)
  * encapsulated commands (vendor-specific, using control-OUT).
  */
 
-#define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */
+#define ECM_STATUS_INTERVAL_MS		32
 #define ECM_STATUS_BYTECOUNT		16	/* 8 byte header + data */
 
 
@@ -192,7 +192,7 @@ static struct usb_endpoint_descriptor fs_ecm_notify_desc = {
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
 	.wMaxPacketSize =	cpu_to_le16(ECM_STATUS_BYTECOUNT),
-	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
+	.bInterval =		ECM_STATUS_INTERVAL_MS,
 };
 
 static struct usb_endpoint_descriptor fs_ecm_in_desc = {
@@ -239,7 +239,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc = {
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
 	.wMaxPacketSize =	cpu_to_le16(ECM_STATUS_BYTECOUNT),
-	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
+	.bInterval =		USB_MS_TO_HS_INTERVAL(ECM_STATUS_INTERVAL_MS),
 };
 
 static struct usb_endpoint_descriptor hs_ecm_in_desc = {
@@ -288,7 +288,7 @@ static struct usb_endpoint_descriptor ss_ecm_notify_desc = {
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
 	.wMaxPacketSize =	cpu_to_le16(ECM_STATUS_BYTECOUNT),
-	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
+	.bInterval =		USB_MS_TO_HS_INTERVAL(ECM_STATUS_INTERVAL_MS),
 };
 
 static struct usb_ss_ep_comp_descriptor ss_ecm_intr_comp_desc = {
@@ -330,6 +330,7 @@ static struct usb_ss_ep_comp_descriptor ss_ecm_bulk_comp_desc = {
 
 static struct usb_descriptor_header *ecm_ss_function[] = {
 	/* CDC ECM control descriptors */
+	(struct usb_descriptor_header *) &ecm_iad_descriptor,
 	(struct usb_descriptor_header *) &ecm_control_intf,
 	(struct usb_descriptor_header *) &ecm_header_desc,
 	(struct usb_descriptor_header *) &ecm_union_desc,
@@ -353,7 +354,7 @@ static struct usb_descriptor_header *ecm_ss_function[] = {
 
 static struct usb_string ecm_string_defs[] = {
 	[0].s = "CDC Ethernet Control Model (ECM)",
-	[1].s = NULL /* DYNAMIC */,
+	[1].s = "",
 	[2].s = "CDC Ethernet Data",
 	[3].s = "CDC ECM",
 	{  } /* end of list */
@@ -742,42 +743,24 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
 	ecm->notify_req->context = ecm;
 	ecm->notify_req->complete = ecm_notify_complete;
 
-	/* copy descriptors, and track endpoint copies */
-	f->descriptors = usb_copy_descriptors(ecm_fs_function);
-	if (!f->descriptors)
-		goto fail;
-
 	/* support all relevant hardware speeds... we expect that when
 	 * hardware is dual speed, all bulk-capable endpoints work at
 	 * both speeds
 	 */
-	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		hs_ecm_in_desc.bEndpointAddress =
-				fs_ecm_in_desc.bEndpointAddress;
-		hs_ecm_out_desc.bEndpointAddress =
-				fs_ecm_out_desc.bEndpointAddress;
-		hs_ecm_notify_desc.bEndpointAddress =
-				fs_ecm_notify_desc.bEndpointAddress;
-
-		/* copy descriptors, and track endpoint copies */
-		f->hs_descriptors = usb_copy_descriptors(ecm_hs_function);
-		if (!f->hs_descriptors)
-			goto fail;
-	}
-
-	if (gadget_is_superspeed(c->cdev->gadget)) {
-		ss_ecm_in_desc.bEndpointAddress =
-				fs_ecm_in_desc.bEndpointAddress;
-		ss_ecm_out_desc.bEndpointAddress =
-				fs_ecm_out_desc.bEndpointAddress;
-		ss_ecm_notify_desc.bEndpointAddress =
-				fs_ecm_notify_desc.bEndpointAddress;
-
-		/* copy descriptors, and track endpoint copies */
-		f->ss_descriptors = usb_copy_descriptors(ecm_ss_function);
-		if (!f->ss_descriptors)
-			goto fail;
-	}
+	hs_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress;
+	hs_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress;
+	hs_ecm_notify_desc.bEndpointAddress =
+		fs_ecm_notify_desc.bEndpointAddress;
+
+	ss_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress;
+	ss_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress;
+	ss_ecm_notify_desc.bEndpointAddress =
+		fs_ecm_notify_desc.bEndpointAddress;
+
+	status = usb_assign_descriptors(f, ecm_fs_function, ecm_hs_function,
+			ecm_ss_function);
+	if (status)
+		goto fail;
 
 	/* NOTE:  all that is done without knowing or caring about
 	 * the network link ... which is unavailable to this code
@@ -795,11 +778,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
 	return 0;
 
 fail:
-	if (f->descriptors)
-		usb_free_descriptors(f->descriptors);
-	if (f->hs_descriptors)
-		usb_free_descriptors(f->hs_descriptors);
-
 	if (ecm->notify_req) {
 		kfree(ecm->notify_req->buf);
 		usb_ep_free_request(ecm->notify, ecm->notify_req);
@@ -808,9 +786,9 @@ fail:
 	/* we might as well release our claims on endpoints */
 	if (ecm->notify)
 		ecm->notify->driver_data = NULL;
-	if (ecm->port.out_ep->desc)
+	if (ecm->port.out_ep)
 		ecm->port.out_ep->driver_data = NULL;
-	if (ecm->port.in_ep->desc)
+	if (ecm->port.in_ep)
 		ecm->port.in_ep->driver_data = NULL;
 
 	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -825,16 +803,11 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
 
 	DBG(c->cdev, "ecm unbind\n");
 
-	if (gadget_is_superspeed(c->cdev->gadget))
-		usb_free_descriptors(f->ss_descriptors);
-	if (gadget_is_dualspeed(c->cdev->gadget))
-		usb_free_descriptors(f->hs_descriptors);
-	usb_free_descriptors(f->descriptors);
+	ecm_string_defs[0].id = 0;
+	usb_free_all_descriptors(f);
 
 	kfree(ecm->notify_req->buf);
 	usb_ep_free_request(ecm->notify, ecm->notify_req);
-
-	ecm_string_defs[1].s = NULL;
 	kfree(ecm);
 }
 
@@ -859,36 +832,15 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 	if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
 		return -EINVAL;
 
-	/* maybe allocate device-global string IDs */
 	if (ecm_string_defs[0].id == 0) {
-
-		/* control interface label */
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		ecm_string_defs[0].id = status;
-		ecm_control_intf.iInterface = status;
-
-		/* data interface label */
-		status = usb_string_id(c->cdev);
-		if (status < 0)
+		status = usb_string_ids_tab(c->cdev, ecm_string_defs);
+		if (status)
 			return status;
-		ecm_string_defs[2].id = status;
-		ecm_data_intf.iInterface = status;
 
-		/* MAC address */
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		ecm_string_defs[1].id = status;
-		ecm_desc.iMACAddress = status;
-
-		/* IAD label */
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		ecm_string_defs[3].id = status;
-		ecm_iad_descriptor.iFunction = status;
+		ecm_control_intf.iInterface = ecm_string_defs[0].id;
+		ecm_data_intf.iInterface = ecm_string_defs[2].id;
+		ecm_desc.iMACAddress = ecm_string_defs[1].id;
+		ecm_iad_descriptor.iFunction = ecm_string_defs[3].id;
 	}
 
 	/* allocate and initialize one new instance */
@@ -913,9 +865,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 	ecm->port.func.disable = ecm_disable;
 
 	status = usb_add_function(c, &ecm->port.func);
-	if (status) {
-		ecm_string_defs[1].s = NULL;
+	if (status)
 		kfree(ecm);
-	}
 	return status;
 }
diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c
index 1a7b2dd..cf0ebee 100644
--- a/drivers/usb/gadget/f_eem.c
+++ b/drivers/usb/gadget/f_eem.c
@@ -274,38 +274,20 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
 
 	status = -ENOMEM;
 
-	/* copy descriptors, and track endpoint copies */
-	f->descriptors = usb_copy_descriptors(eem_fs_function);
-	if (!f->descriptors)
-		goto fail;
-
 	/* support all relevant hardware speeds... we expect that when
 	 * hardware is dual speed, all bulk-capable endpoints work at
 	 * both speeds
 	 */
-	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		eem_hs_in_desc.bEndpointAddress =
-				eem_fs_in_desc.bEndpointAddress;
-		eem_hs_out_desc.bEndpointAddress =
-				eem_fs_out_desc.bEndpointAddress;
-
-		/* copy descriptors, and track endpoint copies */
-		f->hs_descriptors = usb_copy_descriptors(eem_hs_function);
-		if (!f->hs_descriptors)
-			goto fail;
-	}
+	eem_hs_in_desc.bEndpointAddress = eem_fs_in_desc.bEndpointAddress;
+	eem_hs_out_desc.bEndpointAddress = eem_fs_out_desc.bEndpointAddress;
 
-	if (gadget_is_superspeed(c->cdev->gadget)) {
-		eem_ss_in_desc.bEndpointAddress =
-				eem_fs_in_desc.bEndpointAddress;
-		eem_ss_out_desc.bEndpointAddress =
-				eem_fs_out_desc.bEndpointAddress;
+	eem_ss_in_desc.bEndpointAddress = eem_fs_in_desc.bEndpointAddress;
+	eem_ss_out_desc.bEndpointAddress = eem_fs_out_desc.bEndpointAddress;
 
-		/* copy descriptors, and track endpoint copies */
-		f->ss_descriptors = usb_copy_descriptors(eem_ss_function);
-		if (!f->ss_descriptors)
-			goto fail;
-	}
+	status = usb_assign_descriptors(f, eem_fs_function, eem_hs_function,
+			eem_ss_function);
+	if (status)
+		goto fail;
 
 	DBG(cdev, "CDC Ethernet (EEM): %s speed IN/%s OUT/%s\n",
 			gadget_is_superspeed(c->cdev->gadget) ? "super" :
@@ -314,15 +296,10 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
 	return 0;
 
 fail:
-	if (f->descriptors)
-		usb_free_descriptors(f->descriptors);
-	if (f->hs_descriptors)
-		usb_free_descriptors(f->hs_descriptors);
-
-	/* we might as well release our claims on endpoints */
-	if (eem->port.out_ep->desc)
+	usb_free_all_descriptors(f);
+	if (eem->port.out_ep)
 		eem->port.out_ep->driver_data = NULL;
-	if (eem->port.in_ep->desc)
+	if (eem->port.in_ep)
 		eem->port.in_ep->driver_data = NULL;
 
 	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -337,11 +314,7 @@ eem_unbind(struct usb_configuration *c, struct usb_function *f)
 
 	DBG(c->cdev, "eem unbind\n");
 
-	if (gadget_is_superspeed(c->cdev->gadget))
-		usb_free_descriptors(f->ss_descriptors);
-	if (gadget_is_dualspeed(c->cdev->gadget))
-		usb_free_descriptors(f->hs_descriptors);
-	usb_free_descriptors(f->descriptors);
+	usb_free_all_descriptors(f);
 	kfree(eem);
 }
 
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 64c4ec1..4a6961c 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -2097,7 +2097,7 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
 	if (isHS)
 		func->function.hs_descriptors[(long)valuep] = desc;
 	else
-		func->function.descriptors[(long)valuep]    = desc;
+		func->function.fs_descriptors[(long)valuep]    = desc;
 
 	if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT)
 		return 0;
@@ -2249,7 +2249,7 @@ static int ffs_func_bind(struct usb_configuration *c,
 	 * numbers without worrying that it may be described later on.
 	 */
 	if (likely(full)) {
-		func->function.descriptors = data->fs_descs;
+		func->function.fs_descriptors = data->fs_descs;
 		ret = ffs_do_descs(ffs->fs_descs_count,
 				   data->raw_descs,
 				   sizeof data->raw_descs,
diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c
index 511e527..6e69a8e 100644
--- a/drivers/usb/gadget/f_hid.c
+++ b/drivers/usb/gadget/f_hid.c
@@ -573,7 +573,6 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
 		goto fail;
 	hidg_interface_desc.bInterfaceNumber = status;
 
-
 	/* allocate instance-specific endpoints */
 	status = -ENODEV;
 	ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_in_ep_desc);
@@ -609,20 +608,15 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
 	hidg_desc.desc[0].wDescriptorLength =
 		cpu_to_le16(hidg->report_desc_length);
 
-	/* copy descriptors */
-	f->descriptors = usb_copy_descriptors(hidg_fs_descriptors);
-	if (!f->descriptors)
-		goto fail;
+	hidg_hs_in_ep_desc.bEndpointAddress =
+		hidg_fs_in_ep_desc.bEndpointAddress;
+	hidg_hs_out_ep_desc.bEndpointAddress =
+		hidg_fs_out_ep_desc.bEndpointAddress;
 
-	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		hidg_hs_in_ep_desc.bEndpointAddress =
-			hidg_fs_in_ep_desc.bEndpointAddress;
-		hidg_hs_out_ep_desc.bEndpointAddress =
-			hidg_fs_out_ep_desc.bEndpointAddress;
-		f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors);
-		if (!f->hs_descriptors)
-			goto fail;
-	}
+	status = usb_assign_descriptors(f, hidg_fs_descriptors,
+			hidg_hs_descriptors, NULL);
+	if (status)
+		goto fail;
 
 	mutex_init(&hidg->lock);
 	spin_lock_init(&hidg->spinlock);
@@ -649,9 +643,7 @@ fail:
 			usb_ep_free_request(hidg->in_ep, hidg->req);
 	}
 
-	usb_free_descriptors(f->hs_descriptors);
-	usb_free_descriptors(f->descriptors);
-
+	usb_free_all_descriptors(f);
 	return status;
 }
 
@@ -668,9 +660,7 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
 	kfree(hidg->req->buf);
 	usb_ep_free_request(hidg->in_ep, hidg->req);
 
-	/* free descriptors copies */
-	usb_free_descriptors(f->hs_descriptors);
-	usb_free_descriptors(f->descriptors);
+	usb_free_all_descriptors(f);
 
 	kfree(hidg->report_desc);
 	kfree(hidg);
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
index 7275706..bb39cb2 100644
--- a/drivers/usb/gadget/f_loopback.c
+++ b/drivers/usb/gadget/f_loopback.c
@@ -177,6 +177,7 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f)
 	struct usb_composite_dev *cdev = c->cdev;
 	struct f_loopback	*loop = func_to_loop(f);
 	int			id;
+	int ret;
 
 	/* allocate interface ID(s) */
 	id = usb_interface_id(c, f);
@@ -201,22 +202,19 @@ autoconf_fail:
 	loop->out_ep->driver_data = cdev;	/* claim */
 
 	/* support high speed hardware */
-	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		hs_loop_source_desc.bEndpointAddress =
-				fs_loop_source_desc.bEndpointAddress;
-		hs_loop_sink_desc.bEndpointAddress =
-				fs_loop_sink_desc.bEndpointAddress;
-		f->hs_descriptors = hs_loopback_descs;
-	}
+	hs_loop_source_desc.bEndpointAddress =
+		fs_loop_source_desc.bEndpointAddress;
+	hs_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
 
 	/* support super speed hardware */
-	if (gadget_is_superspeed(c->cdev->gadget)) {
-		ss_loop_source_desc.bEndpointAddress =
-				fs_loop_source_desc.bEndpointAddress;
-		ss_loop_sink_desc.bEndpointAddress =
-				fs_loop_sink_desc.bEndpointAddress;
-		f->ss_descriptors = ss_loopback_descs;
-	}
+	ss_loop_source_desc.bEndpointAddress =
+		fs_loop_source_desc.bEndpointAddress;
+	ss_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
+
+	ret = usb_assign_descriptors(f, fs_loopback_descs, hs_loopback_descs,
+			ss_loopback_descs);
+	if (ret)
+		return ret;
 
 	DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
 	    (gadget_is_superspeed(c->cdev->gadget) ? "super" :
@@ -228,6 +226,7 @@ autoconf_fail:
 static void
 loopback_unbind(struct usb_configuration *c, struct usb_function *f)
 {
+	usb_free_all_descriptors(f);
 	kfree(func_to_loop(f));
 }
 
@@ -379,7 +378,6 @@ static int __init loopback_bind_config(struct usb_configuration *c)
 		return -ENOMEM;
 
 	loop->function.name = "loopback";
-	loop->function.descriptors = fs_loopback_descs;
 	loop->function.bind = loopback_bind;
 	loop->function.unbind = loopback_unbind;
 	loop->function.set_alt = loopback_set_alt;
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 3a7668b..5d027b3 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -228,10 +228,6 @@
 
 static const char fsg_string_interface[] = "Mass Storage";
 
-#define FSG_NO_DEVICE_STRINGS    1
-#define FSG_NO_OTG               1
-#define FSG_NO_INTR_EP           1
-
 #include "storage_common.c"
 
 
@@ -2904,9 +2900,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
 	}
 
 	fsg_common_put(common);
-	usb_free_descriptors(fsg->function.descriptors);
-	usb_free_descriptors(fsg->function.hs_descriptors);
-	usb_free_descriptors(fsg->function.ss_descriptors);
+	usb_free_all_descriptors(&fsg->function);
 	kfree(fsg);
 }
 
@@ -2916,6 +2910,8 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
 	struct usb_gadget	*gadget = c->cdev->gadget;
 	int			i;
 	struct usb_ep		*ep;
+	unsigned		max_burst;
+	int			ret;
 
 	fsg->gadget = gadget;
 
@@ -2939,45 +2935,27 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
 	ep->driver_data = fsg->common;	/* claim the endpoint */
 	fsg->bulk_out = ep;
 
-	/* Copy descriptors */
-	f->descriptors = usb_copy_descriptors(fsg_fs_function);
-	if (unlikely(!f->descriptors))
-		return -ENOMEM;
-
-	if (gadget_is_dualspeed(gadget)) {
-		/* Assume endpoint addresses are the same for both speeds */
-		fsg_hs_bulk_in_desc.bEndpointAddress =
-			fsg_fs_bulk_in_desc.bEndpointAddress;
-		fsg_hs_bulk_out_desc.bEndpointAddress =
-			fsg_fs_bulk_out_desc.bEndpointAddress;
-		f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
-		if (unlikely(!f->hs_descriptors)) {
-			usb_free_descriptors(f->descriptors);
-			return -ENOMEM;
-		}
-	}
-
-	if (gadget_is_superspeed(gadget)) {
-		unsigned	max_burst;
+	/* Assume endpoint addresses are the same for both speeds */
+	fsg_hs_bulk_in_desc.bEndpointAddress =
+		fsg_fs_bulk_in_desc.bEndpointAddress;
+	fsg_hs_bulk_out_desc.bEndpointAddress =
+		fsg_fs_bulk_out_desc.bEndpointAddress;
 
-		/* Calculate bMaxBurst, we know packet size is 1024 */
-		max_burst = min_t(unsigned, FSG_BUFLEN / 1024, 15);
+	/* Calculate bMaxBurst, we know packet size is 1024 */
+	max_burst = min_t(unsigned, FSG_BUFLEN / 1024, 15);
 
-		fsg_ss_bulk_in_desc.bEndpointAddress =
-			fsg_fs_bulk_in_desc.bEndpointAddress;
-		fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
+	fsg_ss_bulk_in_desc.bEndpointAddress =
+		fsg_fs_bulk_in_desc.bEndpointAddress;
+	fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
 
-		fsg_ss_bulk_out_desc.bEndpointAddress =
-			fsg_fs_bulk_out_desc.bEndpointAddress;
-		fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
+	fsg_ss_bulk_out_desc.bEndpointAddress =
+		fsg_fs_bulk_out_desc.bEndpointAddress;
+	fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
 
-		f->ss_descriptors = usb_copy_descriptors(fsg_ss_function);
-		if (unlikely(!f->ss_descriptors)) {
-			usb_free_descriptors(f->hs_descriptors);
-			usb_free_descriptors(f->descriptors);
-			return -ENOMEM;
-		}
-	}
+	ret = usb_assign_descriptors(f, fsg_fs_function, fsg_hs_function,
+			fsg_ss_function);
+	if (ret)
+		goto autoconf_fail;
 
 	return 0;
 
@@ -2986,7 +2964,6 @@ autoconf_fail:
 	return -ENOTSUPP;
 }
 
-
 /****************************** ADD FUNCTION ******************************/
 
 static struct usb_gadget_strings *fsg_strings_array[] = {
diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c
index 8ed1259..263e721 100644
--- a/drivers/usb/gadget/f_midi.c
+++ b/drivers/usb/gadget/f_midi.c
@@ -414,7 +414,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
 	kfree(midi->id);
 	midi->id = NULL;
 
-	usb_free_descriptors(f->descriptors);
+	usb_free_all_descriptors(f);
 	kfree(midi);
 }
 
@@ -881,19 +881,25 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
 	 * both speeds
 	 */
 	/* copy descriptors, and track endpoint copies */
+	f->fs_descriptors = usb_copy_descriptors(midi_function);
+	if (!f->fs_descriptors)
+		goto fail_f_midi;
+
 	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		c->highspeed = true;
 		bulk_in_desc.wMaxPacketSize = cpu_to_le16(512);
 		bulk_out_desc.wMaxPacketSize = cpu_to_le16(512);
 		f->hs_descriptors = usb_copy_descriptors(midi_function);
-	} else {
-		f->descriptors = usb_copy_descriptors(midi_function);
+		if (!f->hs_descriptors)
+			goto fail_f_midi;
 	}
 
 	kfree(midi_function);
 
 	return 0;
 
+fail_f_midi:
+	kfree(midi_function);
+	usb_free_descriptors(f->hs_descriptors);
 fail:
 	/* we might as well release our claims on endpoints */
 	if (midi->out_ep)
diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c
index b651b52..6c8362f 100644
--- a/drivers/usb/gadget/f_ncm.c
+++ b/drivers/usb/gadget/f_ncm.c
@@ -102,7 +102,7 @@ static inline unsigned ncm_bitrate(struct usb_gadget *g)
 				 USB_CDC_NCM_NTB32_SUPPORTED)
 
 static struct usb_cdc_ncm_ntb_parameters ntb_parameters = {
-	.wLength = sizeof ntb_parameters,
+	.wLength = cpu_to_le16(sizeof(ntb_parameters)),
 	.bmNtbFormatsSupported = cpu_to_le16(FORMATS_SUPPORTED),
 	.dwNtbInMaxSize = cpu_to_le32(NTB_DEFAULT_IN_SIZE),
 	.wNdpInDivisor = cpu_to_le16(4),
@@ -121,7 +121,7 @@ static struct usb_cdc_ncm_ntb_parameters ntb_parameters = {
  * waste less bandwidth.
  */
 
-#define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */
+#define NCM_STATUS_INTERVAL_MS		32
 #define NCM_STATUS_BYTECOUNT		16	/* 8 byte header + data */
 
 static struct usb_interface_assoc_descriptor ncm_iad_desc __initdata = {
@@ -230,7 +230,7 @@ static struct usb_endpoint_descriptor fs_ncm_notify_desc __initdata = {
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
 	.wMaxPacketSize =	cpu_to_le16(NCM_STATUS_BYTECOUNT),
-	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
+	.bInterval =		NCM_STATUS_INTERVAL_MS,
 };
 
 static struct usb_endpoint_descriptor fs_ncm_in_desc __initdata = {
@@ -275,7 +275,7 @@ static struct usb_endpoint_descriptor hs_ncm_notify_desc __initdata = {
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
 	.wMaxPacketSize =	cpu_to_le16(NCM_STATUS_BYTECOUNT),
-	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
+	.bInterval =		USB_MS_TO_HS_INTERVAL(NCM_STATUS_INTERVAL_MS),
 };
 static struct usb_endpoint_descriptor hs_ncm_in_desc __initdata = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
@@ -321,7 +321,7 @@ static struct usb_descriptor_header *ncm_hs_function[] __initdata = {
 
 static struct usb_string ncm_string_defs[] = {
 	[STRING_CTRL_IDX].s = "CDC Network Control Model (NCM)",
-	[STRING_MAC_IDX].s = NULL /* DYNAMIC */,
+	[STRING_MAC_IDX].s = "",
 	[STRING_DATA_IDX].s = "CDC Network Data",
 	[STRING_IAD_IDX].s = "CDC NCM",
 	{  } /* end of list */
@@ -869,15 +869,19 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port,
 	struct sk_buff	*skb2;
 	int		ncb_len = 0;
 	__le16		*tmp;
-	int		div = ntb_parameters.wNdpInDivisor;
-	int		rem = ntb_parameters.wNdpInPayloadRemainder;
+	int		div;
+	int		rem;
 	int		pad;
-	int		ndp_align = ntb_parameters.wNdpInAlignment;
+	int		ndp_align;
 	int		ndp_pad;
 	unsigned	max_size = ncm->port.fixed_in_len;
 	struct ndp_parser_opts *opts = ncm->parser_opts;
 	unsigned	crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
 
+	div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
+	rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder);
+	ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
+
 	ncb_len += opts->nth_size;
 	ndp_pad = ALIGN(ncb_len, ndp_align) - ncb_len;
 	ncb_len += ndp_pad;
@@ -1208,30 +1212,18 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)
 	ncm->notify_req->context = ncm;
 	ncm->notify_req->complete = ncm_notify_complete;
 
-	/* copy descriptors, and track endpoint copies */
-	f->descriptors = usb_copy_descriptors(ncm_fs_function);
-	if (!f->descriptors)
-		goto fail;
-
 	/*
 	 * support all relevant hardware speeds... we expect that when
 	 * hardware is dual speed, all bulk-capable endpoints work at
 	 * both speeds
 	 */
-	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		hs_ncm_in_desc.bEndpointAddress =
-				fs_ncm_in_desc.bEndpointAddress;
-		hs_ncm_out_desc.bEndpointAddress =
-				fs_ncm_out_desc.bEndpointAddress;
-		hs_ncm_notify_desc.bEndpointAddress =
-				fs_ncm_notify_desc.bEndpointAddress;
-
-		/* copy descriptors, and track endpoint copies */
-		f->hs_descriptors = usb_copy_descriptors(ncm_hs_function);
-		if (!f->hs_descriptors)
-			goto fail;
-	}
+	hs_ncm_in_desc.bEndpointAddress = fs_ncm_in_desc.bEndpointAddress;
+	hs_ncm_out_desc.bEndpointAddress = fs_ncm_out_desc.bEndpointAddress;
+	hs_ncm_notify_desc.bEndpointAddress =
+		fs_ncm_notify_desc.bEndpointAddress;
 
+	status = usb_assign_descriptors(f, ncm_fs_function, ncm_hs_function,
+			NULL);
 	/*
 	 * NOTE:  all that is done without knowing or caring about
 	 * the network link ... which is unavailable to this code
@@ -1248,9 +1240,7 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)
 	return 0;
 
 fail:
-	if (f->descriptors)
-		usb_free_descriptors(f->descriptors);
-
+	usb_free_all_descriptors(f);
 	if (ncm->notify_req) {
 		kfree(ncm->notify_req->buf);
 		usb_ep_free_request(ncm->notify, ncm->notify_req);
@@ -1259,9 +1249,9 @@ fail:
 	/* we might as well release our claims on endpoints */
 	if (ncm->notify)
 		ncm->notify->driver_data = NULL;
-	if (ncm->port.out_ep->desc)
+	if (ncm->port.out_ep)
 		ncm->port.out_ep->driver_data = NULL;
-	if (ncm->port.in_ep->desc)
+	if (ncm->port.in_ep)
 		ncm->port.in_ep->driver_data = NULL;
 
 	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -1276,14 +1266,12 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f)
 
 	DBG(c->cdev, "ncm unbind\n");
 
-	if (gadget_is_dualspeed(c->cdev->gadget))
-		usb_free_descriptors(f->hs_descriptors);
-	usb_free_descriptors(f->descriptors);
+	ncm_string_defs[0].id = 0;
+	usb_free_all_descriptors(f);
 
 	kfree(ncm->notify_req->buf);
 	usb_ep_free_request(ncm->notify, ncm->notify_req);
 
-	ncm_string_defs[1].s = NULL;
 	kfree(ncm);
 }
 
@@ -1307,37 +1295,19 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 	if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
 		return -EINVAL;
 
-	/* maybe allocate device-global string IDs */
 	if (ncm_string_defs[0].id == 0) {
-
-		/* control interface label */
-		status = usb_string_id(c->cdev);
+		status = usb_string_ids_tab(c->cdev, ncm_string_defs);
 		if (status < 0)
 			return status;
-		ncm_string_defs[STRING_CTRL_IDX].id = status;
-		ncm_control_intf.iInterface = status;
+		ncm_control_intf.iInterface =
+			ncm_string_defs[STRING_CTRL_IDX].id;
 
-		/* data interface label */
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		ncm_string_defs[STRING_DATA_IDX].id = status;
+		status = ncm_string_defs[STRING_DATA_IDX].id;
 		ncm_data_nop_intf.iInterface = status;
 		ncm_data_intf.iInterface = status;
 
-		/* MAC address */
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		ncm_string_defs[STRING_MAC_IDX].id = status;
-		ecm_desc.iMACAddress = status;
-
-		/* IAD */
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		ncm_string_defs[STRING_IAD_IDX].id = status;
-		ncm_iad_desc.iFunction = status;
+		ecm_desc.iMACAddress = ncm_string_defs[STRING_MAC_IDX].id;
+		ncm_iad_desc.iFunction = ncm_string_defs[STRING_IAD_IDX].id;
 	}
 
 	/* allocate and initialize one new instance */
@@ -1347,7 +1317,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 
 	/* export host's Ethernet address in CDC format */
 	snprintf(ncm->ethaddr, sizeof ncm->ethaddr, "%pm", ethaddr);
-	ncm_string_defs[1].s = ncm->ethaddr;
+	ncm_string_defs[STRING_MAC_IDX].s = ncm->ethaddr;
 
 	spin_lock_init(&ncm->lock);
 	ncm_reset_values(ncm);
@@ -1367,9 +1337,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 	ncm->port.unwrap = ncm_unwrap_ntb;
 
 	status = usb_add_function(c, &ncm->port.func);
-	if (status) {
-		ncm_string_defs[1].s = NULL;
+	if (status)
 		kfree(ncm);
-	}
 	return status;
 }
diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c
index 5f400f6..d8dd878 100644
--- a/drivers/usb/gadget/f_obex.c
+++ b/drivers/usb/gadget/f_obex.c
@@ -331,23 +331,19 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
 	obex->port.out = ep;
 	ep->driver_data = cdev;	/* claim */
 
-	/* copy descriptors, and track endpoint copies */
-	f->descriptors = usb_copy_descriptors(fs_function);
-
 	/* support all relevant hardware speeds... we expect that when
 	 * hardware is dual speed, all bulk-capable endpoints work at
 	 * both speeds
 	 */
-	if (gadget_is_dualspeed(c->cdev->gadget)) {
 
-		obex_hs_ep_in_desc.bEndpointAddress =
-				obex_fs_ep_in_desc.bEndpointAddress;
-		obex_hs_ep_out_desc.bEndpointAddress =
-				obex_fs_ep_out_desc.bEndpointAddress;
+	obex_hs_ep_in_desc.bEndpointAddress =
+		obex_fs_ep_in_desc.bEndpointAddress;
+	obex_hs_ep_out_desc.bEndpointAddress =
+		obex_fs_ep_out_desc.bEndpointAddress;
 
-		/* copy descriptors, and track endpoint copies */
-		f->hs_descriptors = usb_copy_descriptors(hs_function);
-	}
+	status = usb_assign_descriptors(f, fs_function, hs_function, NULL);
+	if (status)
+		goto fail;
 
 	/* Avoid letting this gadget enumerate until the userspace
 	 * OBEX server is active.
@@ -368,6 +364,7 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
 	return 0;
 
 fail:
+	usb_free_all_descriptors(f);
 	/* we might as well release our claims on endpoints */
 	if (obex->port.out)
 		obex->port.out->driver_data = NULL;
@@ -382,9 +379,8 @@ fail:
 static void
 obex_unbind(struct usb_configuration *c, struct usb_function *f)
 {
-	if (gadget_is_dualspeed(c->cdev->gadget))
-		usb_free_descriptors(f->hs_descriptors);
-	usb_free_descriptors(f->descriptors);
+	obex_string_defs[OBEX_CTRL_IDX].id = 0;
+	usb_free_all_descriptors(f);
 	kfree(func_to_obex(f));
 }
 
@@ -423,22 +419,16 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
 	if (!can_support_obex(c))
 		return -EINVAL;
 
-	/* maybe allocate device-global string IDs, and patch descriptors */
 	if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		obex_string_defs[OBEX_CTRL_IDX].id = status;
-
-		obex_control_intf.iInterface = status;
-
-		status = usb_string_id(c->cdev);
+		status = usb_string_ids_tab(c->cdev, obex_string_defs);
 		if (status < 0)
 			return status;
-		obex_string_defs[OBEX_DATA_IDX].id = status;
+		obex_control_intf.iInterface =
+			obex_string_defs[OBEX_CTRL_IDX].id;
 
-		obex_data_nop_intf.iInterface =
-			obex_data_intf.iInterface = status;
+		status = obex_string_defs[OBEX_DATA_IDX].id;
+		obex_data_nop_intf.iInterface = status;
+		obex_data_intf.iInterface = status;
 	}
 
 	/* allocate and initialize one new instance */
diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c
index 8ee9268..b21ab55 100644
--- a/drivers/usb/gadget/f_phonet.c
+++ b/drivers/usb/gadget/f_phonet.c
@@ -515,14 +515,14 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)
 	fp->in_ep = ep;
 	ep->driver_data = fp; /* Claim */
 
-	pn_hs_sink_desc.bEndpointAddress =
-		pn_fs_sink_desc.bEndpointAddress;
-	pn_hs_source_desc.bEndpointAddress =
-		pn_fs_source_desc.bEndpointAddress;
+	pn_hs_sink_desc.bEndpointAddress = pn_fs_sink_desc.bEndpointAddress;
+	pn_hs_source_desc.bEndpointAddress = pn_fs_source_desc.bEndpointAddress;
 
 	/* Do not try to bind Phonet twice... */
-	fp->function.descriptors = fs_pn_function;
-	fp->function.hs_descriptors = hs_pn_function;
+	status = usb_assign_descriptors(f, fs_pn_function, hs_pn_function,
+			NULL);
+	if (status)
+		goto err;
 
 	/* Incoming USB requests */
 	status = -ENOMEM;
@@ -531,7 +531,7 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)
 
 		req = usb_ep_alloc_request(fp->out_ep, GFP_KERNEL);
 		if (!req)
-			goto err;
+			goto err_req;
 
 		req->complete = pn_rx_complete;
 		fp->out_reqv[i] = req;
@@ -540,14 +540,18 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)
 	/* Outgoing USB requests */
 	fp->in_req = usb_ep_alloc_request(fp->in_ep, GFP_KERNEL);
 	if (!fp->in_req)
-		goto err;
+		goto err_req;
 
 	INFO(cdev, "USB CDC Phonet function\n");
 	INFO(cdev, "using %s, OUT %s, IN %s\n", cdev->gadget->name,
 		fp->out_ep->name, fp->in_ep->name);
 	return 0;
 
+err_req:
+	for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++)
+		usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
 err:
+	usb_free_all_descriptors(f);
 	if (fp->out_ep)
 		fp->out_ep->driver_data = NULL;
 	if (fp->in_ep)
@@ -569,6 +573,7 @@ pn_unbind(struct usb_configuration *c, struct usb_function *f)
 		if (fp->out_reqv[i])
 			usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
 
+	usb_free_all_descriptors(f);
 	kfree(fp);
 }
 
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index b1681e4..71beeb8 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -101,7 +101,7 @@ static unsigned int bitrate(struct usb_gadget *g)
 /*
  */
 
-#define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */
+#define RNDIS_STATUS_INTERVAL_MS	32
 #define STATUS_BYTECOUNT		8	/* 8 bytes data */
 
 
@@ -190,7 +190,7 @@ static struct usb_endpoint_descriptor fs_notify_desc = {
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
 	.wMaxPacketSize =	cpu_to_le16(STATUS_BYTECOUNT),
-	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
+	.bInterval =		RNDIS_STATUS_INTERVAL_MS,
 };
 
 static struct usb_endpoint_descriptor fs_in_desc = {
@@ -236,7 +236,7 @@ static struct usb_endpoint_descriptor hs_notify_desc = {
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
 	.wMaxPacketSize =	cpu_to_le16(STATUS_BYTECOUNT),
-	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
+	.bInterval =		USB_MS_TO_HS_INTERVAL(RNDIS_STATUS_INTERVAL_MS)
 };
 
 static struct usb_endpoint_descriptor hs_in_desc = {
@@ -284,7 +284,7 @@ static struct usb_endpoint_descriptor ss_notify_desc = {
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
 	.wMaxPacketSize =	cpu_to_le16(STATUS_BYTECOUNT),
-	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
+	.bInterval =		USB_MS_TO_HS_INTERVAL(RNDIS_STATUS_INTERVAL_MS)
 };
 
 static struct usb_ss_ep_comp_descriptor ss_intr_comp_desc = {
@@ -722,42 +722,22 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
 	rndis->notify_req->context = rndis;
 	rndis->notify_req->complete = rndis_response_complete;
 
-	/* copy descriptors, and track endpoint copies */
-	f->descriptors = usb_copy_descriptors(eth_fs_function);
-	if (!f->descriptors)
-		goto fail;
-
 	/* support all relevant hardware speeds... we expect that when
 	 * hardware is dual speed, all bulk-capable endpoints work at
 	 * both speeds
 	 */
-	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		hs_in_desc.bEndpointAddress =
-				fs_in_desc.bEndpointAddress;
-		hs_out_desc.bEndpointAddress =
-				fs_out_desc.bEndpointAddress;
-		hs_notify_desc.bEndpointAddress =
-				fs_notify_desc.bEndpointAddress;
-
-		/* copy descriptors, and track endpoint copies */
-		f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
-		if (!f->hs_descriptors)
-			goto fail;
-	}
+	hs_in_desc.bEndpointAddress = fs_in_desc.bEndpointAddress;
+	hs_out_desc.bEndpointAddress = fs_out_desc.bEndpointAddress;
+	hs_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress;
 
-	if (gadget_is_superspeed(c->cdev->gadget)) {
-		ss_in_desc.bEndpointAddress =
-				fs_in_desc.bEndpointAddress;
-		ss_out_desc.bEndpointAddress =
-				fs_out_desc.bEndpointAddress;
-		ss_notify_desc.bEndpointAddress =
-				fs_notify_desc.bEndpointAddress;
-
-		/* copy descriptors, and track endpoint copies */
-		f->ss_descriptors = usb_copy_descriptors(eth_ss_function);
-		if (!f->ss_descriptors)
-			goto fail;
-	}
+	ss_in_desc.bEndpointAddress = fs_in_desc.bEndpointAddress;
+	ss_out_desc.bEndpointAddress = fs_out_desc.bEndpointAddress;
+	ss_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress;
+
+	status = usb_assign_descriptors(f, eth_fs_function, eth_hs_function,
+			eth_ss_function);
+	if (status)
+		goto fail;
 
 	rndis->port.open = rndis_open;
 	rndis->port.close = rndis_close;
@@ -788,12 +768,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
 	return 0;
 
 fail:
-	if (gadget_is_superspeed(c->cdev->gadget) && f->ss_descriptors)
-		usb_free_descriptors(f->ss_descriptors);
-	if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors)
-		usb_free_descriptors(f->hs_descriptors);
-	if (f->descriptors)
-		usb_free_descriptors(f->descriptors);
+	usb_free_all_descriptors(f);
 
 	if (rndis->notify_req) {
 		kfree(rndis->notify_req->buf);
@@ -803,9 +778,9 @@ fail:
 	/* we might as well release our claims on endpoints */
 	if (rndis->notify)
 		rndis->notify->driver_data = NULL;
-	if (rndis->port.out_ep->desc)
+	if (rndis->port.out_ep)
 		rndis->port.out_ep->driver_data = NULL;
-	if (rndis->port.in_ep->desc)
+	if (rndis->port.in_ep)
 		rndis->port.in_ep->driver_data = NULL;
 
 	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -820,13 +795,9 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f)
 
 	rndis_deregister(rndis->config);
 	rndis_exit();
-	rndis_string_defs[0].id = 0;
 
-	if (gadget_is_superspeed(c->cdev->gadget))
-		usb_free_descriptors(f->ss_descriptors);
-	if (gadget_is_dualspeed(c->cdev->gadget))
-		usb_free_descriptors(f->hs_descriptors);
-	usb_free_descriptors(f->descriptors);
+	rndis_string_defs[0].id = 0;
+	usb_free_all_descriptors(f);
 
 	kfree(rndis->notify_req->buf);
 	usb_ep_free_request(rndis->notify, rndis->notify_req);
@@ -851,34 +822,19 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 	if (!can_support_rndis(c) || !ethaddr)
 		return -EINVAL;
 
-	/* maybe allocate device-global string IDs */
 	if (rndis_string_defs[0].id == 0) {
-
 		/* ... and setup RNDIS itself */
 		status = rndis_init();
 		if (status < 0)
 			return status;
 
-		/* control interface label */
-		status = usb_string_id(c->cdev);
-		if (status < 0)
+		status = usb_string_ids_tab(c->cdev, rndis_string_defs);
+		if (status)
 			return status;
-		rndis_string_defs[0].id = status;
-		rndis_control_intf.iInterface = status;
 
-		/* data interface label */
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		rndis_string_defs[1].id = status;
-		rndis_data_intf.iInterface = status;
-
-		/* IAD iFunction label */
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		rndis_string_defs[2].id = status;
-		rndis_iad_descriptor.iFunction = status;
+		rndis_control_intf.iInterface = rndis_string_defs[0].id;
+		rndis_data_intf.iInterface = rndis_string_defs[1].id;
+		rndis_iad_descriptor.iFunction = rndis_string_defs[2].id;
 	}
 
 	/* allocate and initialize one new instance */
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
index 07197d6..98fa779 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -213,34 +213,20 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)
 	gser->port.out = ep;
 	ep->driver_data = cdev;	/* claim */
 
-	/* copy descriptors, and track endpoint copies */
-	f->descriptors = usb_copy_descriptors(gser_fs_function);
-
 	/* support all relevant hardware speeds... we expect that when
 	 * hardware is dual speed, all bulk-capable endpoints work at
 	 * both speeds
 	 */
-	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		gser_hs_in_desc.bEndpointAddress =
-				gser_fs_in_desc.bEndpointAddress;
-		gser_hs_out_desc.bEndpointAddress =
-				gser_fs_out_desc.bEndpointAddress;
-
-		/* copy descriptors, and track endpoint copies */
-		f->hs_descriptors = usb_copy_descriptors(gser_hs_function);
-	}
-	if (gadget_is_superspeed(c->cdev->gadget)) {
-		gser_ss_in_desc.bEndpointAddress =
-			gser_fs_in_desc.bEndpointAddress;
-		gser_ss_out_desc.bEndpointAddress =
-			gser_fs_out_desc.bEndpointAddress;
-
-		/* copy descriptors, and track endpoint copies */
-		f->ss_descriptors = usb_copy_descriptors(gser_ss_function);
-		if (!f->ss_descriptors)
-			goto fail;
-	}
+	gser_hs_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress;
+	gser_hs_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress;
 
+	gser_ss_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress;
+	gser_ss_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress;
+
+	status = usb_assign_descriptors(f, gser_fs_function, gser_hs_function,
+			gser_ss_function);
+	if (status)
+		goto fail;
 	DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
 			gser->port_num,
 			gadget_is_superspeed(c->cdev->gadget) ? "super" :
@@ -263,11 +249,7 @@ fail:
 static void
 gser_unbind(struct usb_configuration *c, struct usb_function *f)
 {
-	if (gadget_is_dualspeed(c->cdev->gadget))
-		usb_free_descriptors(f->hs_descriptors);
-	if (gadget_is_superspeed(c->cdev->gadget))
-		usb_free_descriptors(f->ss_descriptors);
-	usb_free_descriptors(f->descriptors);
+	usb_free_all_descriptors(f);
 	kfree(func_to_gser(f));
 }
 
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
index 3c126fd..102d49b 100644
--- a/drivers/usb/gadget/f_sourcesink.c
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -319,6 +319,7 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
 	struct usb_composite_dev *cdev = c->cdev;
 	struct f_sourcesink	*ss = func_to_ss(f);
 	int	id;
+	int ret;
 
 	/* allocate interface ID(s) */
 	id = usb_interface_id(c, f);
@@ -387,64 +388,57 @@ no_iso:
 		isoc_maxpacket = 1024;
 
 	/* support high speed hardware */
-	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		hs_source_desc.bEndpointAddress =
-				fs_source_desc.bEndpointAddress;
-		hs_sink_desc.bEndpointAddress =
-				fs_sink_desc.bEndpointAddress;
+	hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
+	hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
 
-		/*
-		 * Fill in the HS isoc descriptors from the module parameters.
-		 * We assume that the user knows what they are doing and won't
-		 * give parameters that their UDC doesn't support.
-		 */
-		hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
-		hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11;
-		hs_iso_source_desc.bInterval = isoc_interval;
-		hs_iso_source_desc.bEndpointAddress =
-				fs_iso_source_desc.bEndpointAddress;
-
-		hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
-		hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11;
-		hs_iso_sink_desc.bInterval = isoc_interval;
-		hs_iso_sink_desc.bEndpointAddress =
-				fs_iso_sink_desc.bEndpointAddress;
-
-		f->hs_descriptors = hs_source_sink_descs;
-	}
+	/*
+	 * Fill in the HS isoc descriptors from the module parameters.
+	 * We assume that the user knows what they are doing and won't
+	 * give parameters that their UDC doesn't support.
+	 */
+	hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
+	hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11;
+	hs_iso_source_desc.bInterval = isoc_interval;
+	hs_iso_source_desc.bEndpointAddress =
+		fs_iso_source_desc.bEndpointAddress;
+
+	hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
+	hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11;
+	hs_iso_sink_desc.bInterval = isoc_interval;
+	hs_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
 
 	/* support super speed hardware */
-	if (gadget_is_superspeed(c->cdev->gadget)) {
-		ss_source_desc.bEndpointAddress =
-				fs_source_desc.bEndpointAddress;
-		ss_sink_desc.bEndpointAddress =
-				fs_sink_desc.bEndpointAddress;
+	ss_source_desc.bEndpointAddress =
+		fs_source_desc.bEndpointAddress;
+	ss_sink_desc.bEndpointAddress =
+		fs_sink_desc.bEndpointAddress;
 
-		/*
-		 * Fill in the SS isoc descriptors from the module parameters.
-		 * We assume that the user knows what they are doing and won't
-		 * give parameters that their UDC doesn't support.
-		 */
-		ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
-		ss_iso_source_desc.bInterval = isoc_interval;
-		ss_iso_source_comp_desc.bmAttributes = isoc_mult;
-		ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst;
-		ss_iso_source_comp_desc.wBytesPerInterval =
-			isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
-		ss_iso_source_desc.bEndpointAddress =
-				fs_iso_source_desc.bEndpointAddress;
-
-		ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
-		ss_iso_sink_desc.bInterval = isoc_interval;
-		ss_iso_sink_comp_desc.bmAttributes = isoc_mult;
-		ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst;
-		ss_iso_sink_comp_desc.wBytesPerInterval =
-			isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
-		ss_iso_sink_desc.bEndpointAddress =
-				fs_iso_sink_desc.bEndpointAddress;
-
-		f->ss_descriptors = ss_source_sink_descs;
-	}
+	/*
+	 * Fill in the SS isoc descriptors from the module parameters.
+	 * We assume that the user knows what they are doing and won't
+	 * give parameters that their UDC doesn't support.
+	 */
+	ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
+	ss_iso_source_desc.bInterval = isoc_interval;
+	ss_iso_source_comp_desc.bmAttributes = isoc_mult;
+	ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst;
+	ss_iso_source_comp_desc.wBytesPerInterval =
+		isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
+	ss_iso_source_desc.bEndpointAddress =
+		fs_iso_source_desc.bEndpointAddress;
+
+	ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
+	ss_iso_sink_desc.bInterval = isoc_interval;
+	ss_iso_sink_comp_desc.bmAttributes = isoc_mult;
+	ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst;
+	ss_iso_sink_comp_desc.wBytesPerInterval =
+		isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
+	ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
+
+	ret = usb_assign_descriptors(f, fs_source_sink_descs,
+			hs_source_sink_descs, ss_source_sink_descs);
+	if (ret)
+		return ret;
 
 	DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s\n",
 	    (gadget_is_superspeed(c->cdev->gadget) ? "super" :
@@ -458,6 +452,7 @@ no_iso:
 static void
 sourcesink_unbind(struct usb_configuration *c, struct usb_function *f)
 {
+	usb_free_all_descriptors(f);
 	kfree(func_to_ss(f));
 }
 
@@ -773,7 +768,6 @@ static int __init sourcesink_bind_config(struct usb_configuration *c)
 		return -ENOMEM;
 
 	ss->function.name = "source/sink";
-	ss->function.descriptors = fs_source_sink_descs;
 	ss->function.bind = sourcesink_bind;
 	ss->function.unbind = sourcesink_unbind;
 	ss->function.set_alt = sourcesink_set_alt;
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c
index 4060c0b..f172bd1 100644
--- a/drivers/usb/gadget/f_subset.c
+++ b/drivers/usb/gadget/f_subset.c
@@ -236,7 +236,7 @@ static struct usb_descriptor_header *ss_eth_function[] = {
 
 static struct usb_string geth_string_defs[] = {
 	[0].s = "CDC Ethernet Subset/SAFE",
-	[1].s = NULL /* DYNAMIC */,
+	[1].s = "",
 	{  } /* end of list */
 };
 
@@ -319,38 +319,22 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
 	geth->port.out_ep = ep;
 	ep->driver_data = cdev;	/* claim */
 
-	/* copy descriptors, and track endpoint copies */
-	f->descriptors = usb_copy_descriptors(fs_eth_function);
-	if (!f->descriptors)
-		goto fail;
-
 	/* support all relevant hardware speeds... we expect that when
 	 * hardware is dual speed, all bulk-capable endpoints work at
 	 * both speeds
 	 */
-	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		hs_subset_in_desc.bEndpointAddress =
-				fs_subset_in_desc.bEndpointAddress;
-		hs_subset_out_desc.bEndpointAddress =
-				fs_subset_out_desc.bEndpointAddress;
-
-		/* copy descriptors, and track endpoint copies */
-		f->hs_descriptors = usb_copy_descriptors(hs_eth_function);
-		if (!f->hs_descriptors)
-			goto fail;
-	}
+	hs_subset_in_desc.bEndpointAddress = fs_subset_in_desc.bEndpointAddress;
+	hs_subset_out_desc.bEndpointAddress =
+		fs_subset_out_desc.bEndpointAddress;
 
-	if (gadget_is_superspeed(c->cdev->gadget)) {
-		ss_subset_in_desc.bEndpointAddress =
-				fs_subset_in_desc.bEndpointAddress;
-		ss_subset_out_desc.bEndpointAddress =
-				fs_subset_out_desc.bEndpointAddress;
+	ss_subset_in_desc.bEndpointAddress = fs_subset_in_desc.bEndpointAddress;
+	ss_subset_out_desc.bEndpointAddress =
+		fs_subset_out_desc.bEndpointAddress;
 
-		/* copy descriptors, and track endpoint copies */
-		f->ss_descriptors = usb_copy_descriptors(ss_eth_function);
-		if (!f->ss_descriptors)
-			goto fail;
-	}
+	status = usb_assign_descriptors(f, fs_eth_function, hs_eth_function,
+			ss_eth_function);
+	if (status)
+		goto fail;
 
 	/* NOTE:  all that is done without knowing or caring about
 	 * the network link ... which is unavailable to this code
@@ -364,15 +348,11 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
 	return 0;
 
 fail:
-	if (f->descriptors)
-		usb_free_descriptors(f->descriptors);
-	if (f->hs_descriptors)
-		usb_free_descriptors(f->hs_descriptors);
-
+	usb_free_all_descriptors(f);
 	/* we might as well release our claims on endpoints */
-	if (geth->port.out_ep->desc)
+	if (geth->port.out_ep)
 		geth->port.out_ep->driver_data = NULL;
-	if (geth->port.in_ep->desc)
+	if (geth->port.in_ep)
 		geth->port.in_ep->driver_data = NULL;
 
 	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -383,12 +363,8 @@ fail:
 static void
 geth_unbind(struct usb_configuration *c, struct usb_function *f)
 {
-	if (gadget_is_superspeed(c->cdev->gadget))
-		usb_free_descriptors(f->ss_descriptors);
-	if (gadget_is_dualspeed(c->cdev->gadget))
-		usb_free_descriptors(f->hs_descriptors);
-	usb_free_descriptors(f->descriptors);
-	geth_string_defs[1].s = NULL;
+	geth_string_defs[0].id = 0;
+	usb_free_all_descriptors(f);
 	kfree(func_to_geth(f));
 }
 
@@ -414,20 +390,11 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 
 	/* maybe allocate device-global string IDs */
 	if (geth_string_defs[0].id == 0) {
-
-		/* interface label */
-		status = usb_string_id(c->cdev);
+		status = usb_string_ids_tab(c->cdev, geth_string_defs);
 		if (status < 0)
 			return status;
-		geth_string_defs[0].id = status;
-		subset_data_intf.iInterface = status;
-
-		/* MAC address */
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		geth_string_defs[1].id = status;
-		ether_desc.iMACAddress = status;
+		subset_data_intf.iInterface = geth_string_defs[0].id;
+		ether_desc.iMACAddress = geth_string_defs[1].id;
 	}
 
 	/* allocate and initialize one new instance */
@@ -449,9 +416,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 	geth->port.func.disable = geth_disable;
 
 	status = usb_add_function(c, &geth->port.func);
-	if (status) {
-		geth_string_defs[1].s = NULL;
+	if (status)
 		kfree(geth);
-	}
 	return status;
 }
diff --git a/drivers/usb/gadget/f_uac1.c b/drivers/usb/gadget/f_uac1.c
index 1a5dcd5..f570e66 100644
--- a/drivers/usb/gadget/f_uac1.c
+++ b/drivers/usb/gadget/f_uac1.c
@@ -630,7 +630,7 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
 	struct usb_composite_dev *cdev = c->cdev;
 	struct f_audio		*audio = func_to_audio(f);
 	int			status;
-	struct usb_ep		*ep;
+	struct usb_ep		*ep = NULL;
 
 	f_audio_build_desc(audio);
 
@@ -659,22 +659,14 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
 	status = -ENOMEM;
 
 	/* copy descriptors, and track endpoint copies */
-	f->descriptors = usb_copy_descriptors(f_audio_desc);
-
-	/*
-	 * support all relevant hardware speeds... we expect that when
-	 * hardware is dual speed, all bulk-capable endpoints work at
-	 * both speeds
-	 */
-	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		c->highspeed = true;
-		f->hs_descriptors = usb_copy_descriptors(f_audio_desc);
-	}
-
+	status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL);
+	if (status)
+		goto fail;
 	return 0;
 
 fail:
-
+	if (ep)
+		ep->driver_data = NULL;
 	return status;
 }
 
@@ -683,8 +675,7 @@ f_audio_unbind(struct usb_configuration *c, struct usb_function *f)
 {
 	struct f_audio		*audio = func_to_audio(f);
 
-	usb_free_descriptors(f->descriptors);
-	usb_free_descriptors(f->hs_descriptors);
+	usb_free_all_descriptors(f);
 	kfree(audio);
 }
 
diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/f_uac2.c
index d3c6cff..d7da258 100644
--- a/drivers/usb/gadget/f_uac2.c
+++ b/drivers/usb/gadget/f_uac2.c
@@ -50,13 +50,6 @@ static int c_ssize = 2;
 module_param(c_ssize, uint, S_IRUGO);
 MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
 
-#define DMA_ADDR_INVALID	(~(dma_addr_t)0)
-
-#define ALT_SET(x, a)	do {(x) &= ~0xff; (x) |= (a); } while (0)
-#define ALT_GET(x)	((x) & 0xff)
-#define INTF_SET(x, i)	do {(x) &= 0xff; (x) |= ((i) << 8); } while (0)
-#define INTF_GET(x)	((x >> 8) & 0xff)
-
 /* Keep everyone on toes */
 #define USB_XFERS	2
 
@@ -144,8 +137,9 @@ static struct snd_pcm_hardware uac2_pcm_hardware = {
 };
 
 struct audio_dev {
-	/* Currently active {Interface[15:8] | AltSettings[7:0]} */
-	__u16 ac_alt, as_out_alt, as_in_alt;
+	u8 ac_intf, ac_alt;
+	u8 as_out_intf, as_out_alt;
+	u8 as_in_intf, as_in_alt;
 
 	struct usb_ep *in_ep, *out_ep;
 	struct usb_function func;
@@ -408,7 +402,7 @@ static struct snd_pcm_ops uac2_pcm_ops = {
 	.prepare = uac2_pcm_null,
 };
 
-static int __devinit snd_uac2_probe(struct platform_device *pdev)
+static int snd_uac2_probe(struct platform_device *pdev)
 {
 	struct snd_uac2_chip *uac2 = pdev_to_uac2(pdev);
 	struct snd_card *card;
@@ -526,32 +520,22 @@ enum {
 	STR_AS_IN_ALT1,
 };
 
-static const char ifassoc[] = "Source/Sink";
-static const char ifctrl[] = "Topology Control";
 static char clksrc_in[8];
 static char clksrc_out[8];
-static const char usb_it[] = "USBH Out";
-static const char io_it[] = "USBD Out";
-static const char usb_ot[] = "USBH In";
-static const char io_ot[] = "USBD In";
-static const char out_alt0[] = "Playback Inactive";
-static const char out_alt1[] = "Playback Active";
-static const char in_alt0[] = "Capture Inactive";
-static const char in_alt1[] = "Capture Active";
 
 static struct usb_string strings_fn[] = {
-	[STR_ASSOC].s = ifassoc,
-	[STR_IF_CTRL].s = ifctrl,
+	[STR_ASSOC].s = "Source/Sink",
+	[STR_IF_CTRL].s = "Topology Control",
 	[STR_CLKSRC_IN].s = clksrc_in,
 	[STR_CLKSRC_OUT].s = clksrc_out,
-	[STR_USB_IT].s = usb_it,
-	[STR_IO_IT].s = io_it,
-	[STR_USB_OT].s = usb_ot,
-	[STR_IO_OT].s = io_ot,
-	[STR_AS_OUT_ALT0].s = out_alt0,
-	[STR_AS_OUT_ALT1].s = out_alt1,
-	[STR_AS_IN_ALT0].s = in_alt0,
-	[STR_AS_IN_ALT1].s = in_alt1,
+	[STR_USB_IT].s = "USBH Out",
+	[STR_IO_IT].s = "USBD Out",
+	[STR_USB_OT].s = "USBH In",
+	[STR_IO_OT].s = "USBD In",
+	[STR_AS_OUT_ALT0].s = "Playback Inactive",
+	[STR_AS_OUT_ALT1].s = "Playback Active",
+	[STR_AS_IN_ALT0].s = "Capture Inactive",
+	[STR_AS_IN_ALT1].s = "Capture Active",
 	{ },
 };
 
@@ -952,8 +936,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
 		return ret;
 	}
 	std_ac_if_desc.bInterfaceNumber = ret;
-	ALT_SET(agdev->ac_alt, 0);
-	INTF_SET(agdev->ac_alt, ret);
+	agdev->ac_intf = ret;
+	agdev->ac_alt = 0;
 
 	ret = usb_interface_id(cfg, fn);
 	if (ret < 0) {
@@ -963,8 +947,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
 	}
 	std_as_out_if0_desc.bInterfaceNumber = ret;
 	std_as_out_if1_desc.bInterfaceNumber = ret;
-	ALT_SET(agdev->as_out_alt, 0);
-	INTF_SET(agdev->as_out_alt, ret);
+	agdev->as_out_intf = ret;
+	agdev->as_out_alt = 0;
 
 	ret = usb_interface_id(cfg, fn);
 	if (ret < 0) {
@@ -974,19 +958,23 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
 	}
 	std_as_in_if0_desc.bInterfaceNumber = ret;
 	std_as_in_if1_desc.bInterfaceNumber = ret;
-	ALT_SET(agdev->as_in_alt, 0);
-	INTF_SET(agdev->as_in_alt, ret);
+	agdev->as_in_intf = ret;
+	agdev->as_in_alt = 0;
 
 	agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
-	if (!agdev->out_ep)
+	if (!agdev->out_ep) {
 		dev_err(&uac2->pdev.dev,
 			"%s:%d Error!\n", __func__, __LINE__);
+		goto err;
+	}
 	agdev->out_ep->driver_data = agdev;
 
 	agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc);
-	if (!agdev->in_ep)
+	if (!agdev->in_ep) {
 		dev_err(&uac2->pdev.dev,
 			"%s:%d Error!\n", __func__, __LINE__);
+		goto err;
+	}
 	agdev->in_ep->driver_data = agdev;
 
 	hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
@@ -994,9 +982,9 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
 	hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
 	hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize;
 
-	fn->descriptors = usb_copy_descriptors(fs_audio_desc);
-	if (gadget_is_dualspeed(gadget))
-		fn->hs_descriptors = usb_copy_descriptors(hs_audio_desc);
+	ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL);
+	if (ret)
+		goto err;
 
 	prm = &agdev->uac2.c_prm;
 	prm->max_psize = hs_epout_desc.wMaxPacketSize;
@@ -1005,6 +993,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
 		prm->max_psize = 0;
 		dev_err(&uac2->pdev.dev,
 			"%s:%d Error!\n", __func__, __LINE__);
+		goto err;
 	}
 
 	prm = &agdev->uac2.p_prm;
@@ -1014,17 +1003,28 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
 		prm->max_psize = 0;
 		dev_err(&uac2->pdev.dev,
 			"%s:%d Error!\n", __func__, __LINE__);
+		goto err;
 	}
 
-	return alsa_uac2_init(agdev);
+	ret = alsa_uac2_init(agdev);
+	if (ret)
+		goto err;
+	return 0;
+err:
+	kfree(agdev->uac2.p_prm.rbuf);
+	kfree(agdev->uac2.c_prm.rbuf);
+	usb_free_all_descriptors(fn);
+	if (agdev->in_ep)
+		agdev->in_ep->driver_data = NULL;
+	if (agdev->out_ep)
+		agdev->out_ep->driver_data = NULL;
+	return -EINVAL;
 }
 
 static void
 afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn)
 {
 	struct audio_dev *agdev = func_to_agdev(fn);
-	struct usb_composite_dev *cdev = cfg->cdev;
-	struct usb_gadget *gadget = cdev->gadget;
 	struct uac2_rtd_params *prm;
 
 	alsa_uac2_exit(agdev);
@@ -1034,10 +1034,7 @@ afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn)
 
 	prm = &agdev->uac2.c_prm;
 	kfree(prm->rbuf);
-
-	if (gadget_is_dualspeed(gadget))
-		usb_free_descriptors(fn->hs_descriptors);
-	usb_free_descriptors(fn->descriptors);
+	usb_free_all_descriptors(fn);
 
 	if (agdev->in_ep)
 		agdev->in_ep->driver_data = NULL;
@@ -1064,7 +1061,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
 		return -EINVAL;
 	}
 
-	if (intf == INTF_GET(agdev->ac_alt)) {
+	if (intf == agdev->ac_intf) {
 		/* Control I/f has only 1 AltSetting - 0 */
 		if (alt) {
 			dev_err(&uac2->pdev.dev,
@@ -1074,16 +1071,16 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
 		return 0;
 	}
 
-	if (intf == INTF_GET(agdev->as_out_alt)) {
+	if (intf == agdev->as_out_intf) {
 		ep = agdev->out_ep;
 		prm = &uac2->c_prm;
 		config_ep_by_speed(gadget, fn, ep);
-		ALT_SET(agdev->as_out_alt, alt);
-	} else if (intf == INTF_GET(agdev->as_in_alt)) {
+		agdev->as_out_alt = alt;
+	} else if (intf == agdev->as_in_intf) {
 		ep = agdev->in_ep;
 		prm = &uac2->p_prm;
 		config_ep_by_speed(gadget, fn, ep);
-		ALT_SET(agdev->as_in_alt, alt);
+		agdev->as_in_alt = alt;
 	} else {
 		dev_err(&uac2->pdev.dev,
 			"%s:%d Error!\n", __func__, __LINE__);
@@ -1117,7 +1114,6 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
 		prm->ureq[i].pp = prm;
 
 		req->zero = 0;
-		req->dma = DMA_ADDR_INVALID;
 		req->context = &prm->ureq[i];
 		req->length = prm->max_psize;
 		req->complete =	agdev_iso_complete;
@@ -1136,12 +1132,12 @@ afunc_get_alt(struct usb_function *fn, unsigned intf)
 	struct audio_dev *agdev = func_to_agdev(fn);
 	struct snd_uac2_chip *uac2 = &agdev->uac2;
 
-	if (intf == INTF_GET(agdev->ac_alt))
-		return ALT_GET(agdev->ac_alt);
-	else if (intf == INTF_GET(agdev->as_out_alt))
-		return ALT_GET(agdev->as_out_alt);
-	else if (intf == INTF_GET(agdev->as_in_alt))
-		return ALT_GET(agdev->as_in_alt);
+	if (intf == agdev->ac_intf)
+		return agdev->ac_alt;
+	else if (intf == agdev->as_out_intf)
+		return agdev->as_out_alt;
+	else if (intf == agdev->as_in_intf)
+		return agdev->as_in_alt;
 	else
 		dev_err(&uac2->pdev.dev,
 			"%s:%d Invalid Interface %d!\n",
@@ -1157,10 +1153,10 @@ afunc_disable(struct usb_function *fn)
 	struct snd_uac2_chip *uac2 = &agdev->uac2;
 
 	free_ep(&uac2->p_prm, agdev->in_ep);
-	ALT_SET(agdev->as_in_alt, 0);
+	agdev->as_in_alt = 0;
 
 	free_ep(&uac2->c_prm, agdev->out_ep);
-	ALT_SET(agdev->as_out_alt, 0);
+	agdev->as_out_alt = 0;
 }
 
 static int
@@ -1267,7 +1263,7 @@ setup_rq_inf(struct usb_function *fn, const struct usb_ctrlrequest *cr)
 	u16 w_index = le16_to_cpu(cr->wIndex);
 	u8 intf = w_index & 0xff;
 
-	if (intf != INTF_GET(agdev->ac_alt)) {
+	if (intf != agdev->ac_intf) {
 		dev_err(&uac2->pdev.dev,
 			"%s:%d Error!\n", __func__, __LINE__);
 		return -EOPNOTSUPP;
@@ -1316,7 +1312,7 @@ afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr)
 
 static int audio_bind_config(struct usb_configuration *cfg)
 {
-	int id, res;
+	int res;
 
 	agdev_g = kzalloc(sizeof *agdev_g, GFP_KERNEL);
 	if (agdev_g == NULL) {
@@ -1324,89 +1320,21 @@ static int audio_bind_config(struct usb_configuration *cfg)
 		return -ENOMEM;
 	}
 
-	id = usb_string_id(cfg->cdev);
-	if (id < 0)
-		return id;
-
-	strings_fn[STR_ASSOC].id = id;
-	iad_desc.iFunction = id,
-
-	id = usb_string_id(cfg->cdev);
-	if (id < 0)
-		return id;
-
-	strings_fn[STR_IF_CTRL].id = id;
-	std_ac_if_desc.iInterface = id,
-
-	id = usb_string_id(cfg->cdev);
-	if (id < 0)
-		return id;
-
-	strings_fn[STR_CLKSRC_IN].id = id;
-	in_clk_src_desc.iClockSource = id,
-
-	id = usb_string_id(cfg->cdev);
-	if (id < 0)
-		return id;
-
-	strings_fn[STR_CLKSRC_OUT].id = id;
-	out_clk_src_desc.iClockSource = id,
-
-	id = usb_string_id(cfg->cdev);
-	if (id < 0)
-		return id;
-
-	strings_fn[STR_USB_IT].id = id;
-	usb_out_it_desc.iTerminal = id,
-
-	id = usb_string_id(cfg->cdev);
-	if (id < 0)
-		return id;
-
-	strings_fn[STR_IO_IT].id = id;
-	io_in_it_desc.iTerminal = id;
-
-	id = usb_string_id(cfg->cdev);
-	if (id < 0)
-		return id;
-
-	strings_fn[STR_USB_OT].id = id;
-	usb_in_ot_desc.iTerminal = id;
-
-	id = usb_string_id(cfg->cdev);
-	if (id < 0)
-		return id;
-
-	strings_fn[STR_IO_OT].id = id;
-	io_out_ot_desc.iTerminal = id;
-
-	id = usb_string_id(cfg->cdev);
-	if (id < 0)
-		return id;
-
-	strings_fn[STR_AS_OUT_ALT0].id = id;
-	std_as_out_if0_desc.iInterface = id;
-
-	id = usb_string_id(cfg->cdev);
-	if (id < 0)
-		return id;
-
-	strings_fn[STR_AS_OUT_ALT1].id = id;
-	std_as_out_if1_desc.iInterface = id;
-
-	id = usb_string_id(cfg->cdev);
-	if (id < 0)
-		return id;
-
-	strings_fn[STR_AS_IN_ALT0].id = id;
-	std_as_in_if0_desc.iInterface = id;
-
-	id = usb_string_id(cfg->cdev);
-	if (id < 0)
-		return id;
-
-	strings_fn[STR_AS_IN_ALT1].id = id;
-	std_as_in_if1_desc.iInterface = id;
+	res = usb_string_ids_tab(cfg->cdev, strings_fn);
+	if (res)
+		return res;
+	iad_desc.iFunction = strings_fn[STR_ASSOC].id;
+	std_ac_if_desc.iInterface = strings_fn[STR_IF_CTRL].id;
+	in_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_IN].id;
+	out_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_OUT].id;
+	usb_out_it_desc.iTerminal = strings_fn[STR_USB_IT].id;
+	io_in_it_desc.iTerminal = strings_fn[STR_IO_IT].id;
+	usb_in_ot_desc.iTerminal = strings_fn[STR_USB_OT].id;
+	io_out_ot_desc.iTerminal = strings_fn[STR_IO_OT].id;
+	std_as_out_if0_desc.iInterface = strings_fn[STR_AS_OUT_ALT0].id;
+	std_as_out_if1_desc.iInterface = strings_fn[STR_AS_OUT_ALT1].id;
+	std_as_in_if0_desc.iInterface = strings_fn[STR_AS_IN_ALT0].id;
+	std_as_in_if1_desc.iInterface = strings_fn[STR_AS_IN_ALT1].id;
 
 	agdev_g->func.name = "uac2_func";
 	agdev_g->func.strings = fn_strings;
diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c
index 2a8bf06..5b62987 100644
--- a/drivers/usb/gadget/f_uvc.c
+++ b/drivers/usb/gadget/f_uvc.c
@@ -417,7 +417,6 @@ uvc_register_video(struct uvc_device *uvc)
 		return -ENOMEM;
 
 	video->parent = &cdev->gadget->dev;
-	video->minor = -1;
 	video->fops = &uvc_v4l2_fops;
 	video->release = video_device_release;
 	strncpy(video->name, cdev->gadget->name, sizeof(video->name));
@@ -577,27 +576,15 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)
 
 	INFO(cdev, "uvc_function_unbind\n");
 
-	if (uvc->vdev) {
-		if (uvc->vdev->minor == -1)
-			video_device_release(uvc->vdev);
-		else
-			video_unregister_device(uvc->vdev);
-		uvc->vdev = NULL;
-	}
+	video_unregister_device(uvc->vdev);
+	uvc->control_ep->driver_data = NULL;
+	uvc->video.ep->driver_data = NULL;
 
-	if (uvc->control_ep)
-		uvc->control_ep->driver_data = NULL;
-	if (uvc->video.ep)
-		uvc->video.ep->driver_data = NULL;
-
-	if (uvc->control_req) {
-		usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
-		kfree(uvc->control_buf);
-	}
+	uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = 0;
+	usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
+	kfree(uvc->control_buf);
 
-	kfree(f->descriptors);
-	kfree(f->hs_descriptors);
-	kfree(f->ss_descriptors);
+	usb_free_all_descriptors(f);
 
 	kfree(uvc);
 }
@@ -663,49 +650,40 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 	/* sanity check the streaming endpoint module parameters */
 	if (streaming_maxpacket > 1024)
 		streaming_maxpacket = 1024;
+	/*
+	 * Fill in the HS descriptors from the module parameters for the Video
+	 * Streaming endpoint.
+	 * NOTE: We assume that the user knows what they are doing and won't
+	 * give parameters that their UDC doesn't support.
+	 */
+	uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
+	uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
+	uvc_hs_streaming_ep.bInterval = streaming_interval;
+	uvc_hs_streaming_ep.bEndpointAddress =
+		uvc_fs_streaming_ep.bEndpointAddress;
 
-	/* Copy descriptors for FS. */
-	f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
-
-	/* support high speed hardware */
-	if (gadget_is_dualspeed(cdev->gadget)) {
-		/*
-		 * Fill in the HS descriptors from the module parameters for the
-		 * Video Streaming endpoint.
-		 * NOTE: We assume that the user knows what they are doing and
-		 * won't give parameters that their UDC doesn't support.
-		 */
-		uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
-		uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
-		uvc_hs_streaming_ep.bInterval = streaming_interval;
-		uvc_hs_streaming_ep.bEndpointAddress =
-				uvc_fs_streaming_ep.bEndpointAddress;
-
-		/* Copy descriptors. */
-		f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
-	}
+	/*
+	 * Fill in the SS descriptors from the module parameters for the Video
+	 * Streaming endpoint.
+	 * NOTE: We assume that the user knows what they are doing and won't
+	 * give parameters that their UDC doesn't support.
+	 */
+	uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
+	uvc_ss_streaming_ep.bInterval = streaming_interval;
+	uvc_ss_streaming_comp.bmAttributes = streaming_mult;
+	uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
+	uvc_ss_streaming_comp.wBytesPerInterval =
+		streaming_maxpacket * (streaming_mult + 1) *
+		(streaming_maxburst + 1);
+	uvc_ss_streaming_ep.bEndpointAddress =
+		uvc_fs_streaming_ep.bEndpointAddress;
 
-	/* support super speed hardware */
-	if (gadget_is_superspeed(c->cdev->gadget)) {
-		/*
-		 * Fill in the SS descriptors from the module parameters for the
-		 * Video Streaming endpoint.
-		 * NOTE: We assume that the user knows what they are doing and
-		 * won't give parameters that their UDC doesn't support.
-		 */
-		uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
-		uvc_ss_streaming_ep.bInterval = streaming_interval;
-		uvc_ss_streaming_comp.bmAttributes = streaming_mult;
-		uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
-		uvc_ss_streaming_comp.wBytesPerInterval =
-			streaming_maxpacket * (streaming_mult + 1) *
-			(streaming_maxburst + 1);
-		uvc_ss_streaming_ep.bEndpointAddress =
-				uvc_fs_streaming_ep.bEndpointAddress;
-
-		/* Copy descriptors. */
+	/* Copy descriptors */
+	f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
+	if (gadget_is_dualspeed(cdev->gadget))
+		f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
+	if (gadget_is_superspeed(c->cdev->gadget))
 		f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER);
-	}
 
 	/* Preallocate control endpoint request. */
 	uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
@@ -740,7 +718,20 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 	return 0;
 
 error:
-	uvc_function_unbind(c, f);
+	if (uvc->vdev)
+		video_device_release(uvc->vdev);
+
+	if (uvc->control_ep)
+		uvc->control_ep->driver_data = NULL;
+	if (uvc->video.ep)
+		uvc->video.ep->driver_data = NULL;
+
+	if (uvc->control_req) {
+		usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
+		kfree(uvc->control_buf);
+	}
+
+	usb_free_all_descriptors(f);
 	return ret;
 }
 
@@ -808,25 +799,16 @@ uvc_bind_config(struct usb_configuration *c,
 	uvc->desc.hs_streaming = hs_streaming;
 	uvc->desc.ss_streaming = ss_streaming;
 
-	/* maybe allocate device-global string IDs, and patch descriptors */
+	/* Allocate string descriptor numbers. */
 	if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) {
-		/* Allocate string descriptor numbers. */
-		ret = usb_string_id(c->cdev);
-		if (ret < 0)
-			goto error;
-		uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret;
-		uvc_iad.iFunction = ret;
-
-		ret = usb_string_id(c->cdev);
-		if (ret < 0)
-			goto error;
-		uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret;
-		uvc_control_intf.iInterface = ret;
-
-		ret = usb_string_id(c->cdev);
-		if (ret < 0)
+		ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);
+		if (ret)
 			goto error;
-		uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret;
+		uvc_iad.iFunction =
+			uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id;
+		uvc_control_intf.iInterface =
+			uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
+		ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id;
 		uvc_streaming_intf_alt0.iInterface = ret;
 		uvc_streaming_intf_alt1.iInterface = ret;
 	}
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
deleted file mode 100644
index 3f7d640..0000000
--- a/drivers/usb/gadget/file_storage.c
+++ /dev/null
@@ -1,3656 +0,0 @@
-/*
- * file_storage.c -- File-backed USB Storage Gadget, for USB development
- *
- * Copyright (C) 2003-2008 Alan Stern
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-/*
- * The File-backed Storage Gadget acts as a USB Mass Storage device,
- * appearing to the host as a disk drive or as a CD-ROM drive.  In addition
- * to providing an example of a genuinely useful gadget driver for a USB
- * device, it also illustrates a technique of double-buffering for increased
- * throughput.  Last but not least, it gives an easy way to probe the
- * behavior of the Mass Storage drivers in a USB host.
- *
- * Backing storage is provided by a regular file or a block device, specified
- * by the "file" module parameter.  Access can be limited to read-only by
- * setting the optional "ro" module parameter.  (For CD-ROM emulation,
- * access is always read-only.)  The gadget will indicate that it has
- * removable media if the optional "removable" module parameter is set.
- *
- * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
- * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
- * by the optional "transport" module parameter.  It also supports the
- * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
- * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
- * the optional "protocol" module parameter.  In addition, the default
- * Vendor ID, Product ID, release number and serial number can be overridden.
- *
- * There is support for multiple logical units (LUNs), each of which has
- * its own backing file.  The number of LUNs can be set using the optional
- * "luns" module parameter (anywhere from 1 to 8), and the corresponding
- * files are specified using comma-separated lists for "file" and "ro".
- * The default number of LUNs is taken from the number of "file" elements;
- * it is 1 if "file" is not given.  If "removable" is not set then a backing
- * file must be specified for each LUN.  If it is set, then an unspecified
- * or empty backing filename means the LUN's medium is not loaded.  Ideally
- * each LUN would be settable independently as a disk drive or a CD-ROM
- * drive, but currently all LUNs have to be the same type.  The CD-ROM
- * emulation includes a single data track and no audio tracks; hence there
- * need be only one backing file per LUN.
- *
- * Requirements are modest; only a bulk-in and a bulk-out endpoint are
- * needed (an interrupt-out endpoint is also needed for CBI).  The memory
- * requirement amounts to two 16K buffers, size configurable by a parameter.
- * Support is included for both full-speed and high-speed operation.
- *
- * Note that the driver is slightly non-portable in that it assumes a
- * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
- * interrupt-in endpoints.  With most device controllers this isn't an
- * issue, but there may be some with hardware restrictions that prevent
- * a buffer from being used by more than one endpoint.
- *
- * Module options:
- *
- *	file=filename[,filename...]
- *				Required if "removable" is not set, names of
- *					the files or block devices used for
- *					backing storage
- *	serial=HHHH...		Required serial number (string of hex chars)
- *	ro=b[,b...]		Default false, booleans for read-only access
- *	removable		Default false, boolean for removable media
- *	luns=N			Default N = number of filenames, number of
- *					LUNs to support
- *	nofua=b[,b...]		Default false, booleans for ignore FUA flag
- *					in SCSI WRITE(10,12) commands
- *	stall			Default determined according to the type of
- *					USB device controller (usually true),
- *					boolean to permit the driver to halt
- *					bulk endpoints
- *	cdrom			Default false, boolean for whether to emulate
- *					a CD-ROM drive
- *	transport=XXX		Default BBB, transport name (CB, CBI, or BBB)
- *	protocol=YYY		Default SCSI, protocol name (RBC, 8020 or
- *					ATAPI, QIC, UFI, 8070, or SCSI;
- *					also 1 - 6)
- *	vendor=0xVVVV		Default 0x0525 (NetChip), USB Vendor ID
- *	product=0xPPPP		Default 0xa4a5 (FSG), USB Product ID
- *	release=0xRRRR		Override the USB release number (bcdDevice)
- *	buflen=N		Default N=16384, buffer size used (will be
- *					rounded down to a multiple of
- *					PAGE_CACHE_SIZE)
- *
- * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro",
- * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
- * default values are used for everything else.
- *
- * The pathnames of the backing files and the ro settings are available in
- * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of
- * the gadget's sysfs directory.  If the "removable" option is set, writing to
- * these files will simulate ejecting/loading the medium (writing an empty
- * line means eject) and adjusting a write-enable tab.  Changes to the ro
- * setting are not allowed when the medium is loaded or if CD-ROM emulation
- * is being used.
- *
- * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
- * The driver's SCSI command interface was based on the "Information
- * technology - Small Computer System Interface - 2" document from
- * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at
- * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>.  The single exception
- * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the
- * "Universal Serial Bus Mass Storage Class UFI Command Specification"
- * document, Revision 1.0, December 14, 1998, available at
- * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
- */
-
-
-/*
- *				Driver Design
- *
- * The FSG driver is fairly straightforward.  There is a main kernel
- * thread that handles most of the work.  Interrupt routines field
- * callbacks from the controller driver: bulk- and interrupt-request
- * completion notifications, endpoint-0 events, and disconnect events.
- * Completion events are passed to the main thread by wakeup calls.  Many
- * ep0 requests are handled at interrupt time, but SetInterface,
- * SetConfiguration, and device reset requests are forwarded to the
- * thread in the form of "exceptions" using SIGUSR1 signals (since they
- * should interrupt any ongoing file I/O operations).
- *
- * The thread's main routine implements the standard command/data/status
- * parts of a SCSI interaction.  It and its subroutines are full of tests
- * for pending signals/exceptions -- all this polling is necessary since
- * the kernel has no setjmp/longjmp equivalents.  (Maybe this is an
- * indication that the driver really wants to be running in userspace.)
- * An important point is that so long as the thread is alive it keeps an
- * open reference to the backing file.  This will prevent unmounting
- * the backing file's underlying filesystem and could cause problems
- * during system shutdown, for example.  To prevent such problems, the
- * thread catches INT, TERM, and KILL signals and converts them into
- * an EXIT exception.
- *
- * In normal operation the main thread is started during the gadget's
- * fsg_bind() callback and stopped during fsg_unbind().  But it can also
- * exit when it receives a signal, and there's no point leaving the
- * gadget running when the thread is dead.  So just before the thread
- * exits, it deregisters the gadget driver.  This makes things a little
- * tricky: The driver is deregistered at two places, and the exiting
- * thread can indirectly call fsg_unbind() which in turn can tell the
- * thread to exit.  The first problem is resolved through the use of the
- * REGISTERED atomic bitflag; the driver will only be deregistered once.
- * The second problem is resolved by having fsg_unbind() check
- * fsg->state; it won't try to stop the thread if the state is already
- * FSG_STATE_TERMINATED.
- *
- * To provide maximum throughput, the driver uses a circular pipeline of
- * buffer heads (struct fsg_buffhd).  In principle the pipeline can be
- * arbitrarily long; in practice the benefits don't justify having more
- * than 2 stages (i.e., double buffering).  But it helps to think of the
- * pipeline as being a long one.  Each buffer head contains a bulk-in and
- * a bulk-out request pointer (since the buffer can be used for both
- * output and input -- directions always are given from the host's
- * point of view) as well as a pointer to the buffer and various state
- * variables.
- *
- * Use of the pipeline follows a simple protocol.  There is a variable
- * (fsg->next_buffhd_to_fill) that points to the next buffer head to use.
- * At any time that buffer head may still be in use from an earlier
- * request, so each buffer head has a state variable indicating whether
- * it is EMPTY, FULL, or BUSY.  Typical use involves waiting for the
- * buffer head to be EMPTY, filling the buffer either by file I/O or by
- * USB I/O (during which the buffer head is BUSY), and marking the buffer
- * head FULL when the I/O is complete.  Then the buffer will be emptied
- * (again possibly by USB I/O, during which it is marked BUSY) and
- * finally marked EMPTY again (possibly by a completion routine).
- *
- * A module parameter tells the driver to avoid stalling the bulk
- * endpoints wherever the transport specification allows.  This is
- * necessary for some UDCs like the SuperH, which cannot reliably clear a
- * halt on a bulk endpoint.  However, under certain circumstances the
- * Bulk-only specification requires a stall.  In such cases the driver
- * will halt the endpoint and set a flag indicating that it should clear
- * the halt in software during the next device reset.  Hopefully this
- * will permit everything to work correctly.  Furthermore, although the
- * specification allows the bulk-out endpoint to halt when the host sends
- * too much data, implementing this would cause an unavoidable race.
- * The driver will always use the "no-stall" approach for OUT transfers.
- *
- * One subtle point concerns sending status-stage responses for ep0
- * requests.  Some of these requests, such as device reset, can involve
- * interrupting an ongoing file I/O operation, which might take an
- * arbitrarily long time.  During that delay the host might give up on
- * the original ep0 request and issue a new one.  When that happens the
- * driver should not notify the host about completion of the original
- * request, as the host will no longer be waiting for it.  So the driver
- * assigns to each ep0 request a unique tag, and it keeps track of the
- * tag value of the request associated with a long-running exception
- * (device-reset, interface-change, or configuration-change).  When the
- * exception handler is finished, the status-stage response is submitted
- * only if the current ep0 request tag is equal to the exception request
- * tag.  Thus only the most recently received ep0 request will get a
- * status-stage response.
- *
- * Warning: This driver source file is too long.  It ought to be split up
- * into a header file plus about 3 separate .c files, to handle the details
- * of the Gadget, USB Mass Storage, and SCSI protocols.
- */
-
-
-/* #define VERBOSE_DEBUG */
-/* #define DUMP_MSGS */
-
-
-#include <linux/blkdev.h>
-#include <linux/completion.h>
-#include <linux/dcache.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/fcntl.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/kref.h>
-#include <linux/kthread.h>
-#include <linux/limits.h>
-#include <linux/module.h>
-#include <linux/rwsem.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/freezer.h>
-#include <linux/utsname.h>
-
-#include <linux/usb/composite.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-#include "gadget_chips.h"
-
-#define DRIVER_DESC		"File-backed Storage Gadget"
-#define DRIVER_NAME		"g_file_storage"
-#define DRIVER_VERSION		"1 September 2010"
-
-static       char fsg_string_manufacturer[64];
-static const char fsg_string_product[] = DRIVER_DESC;
-static const char fsg_string_config[] = "Self-powered";
-static const char fsg_string_interface[] = "Mass Storage";
-
-
-#include "storage_common.c"
-
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Alan Stern");
-MODULE_LICENSE("Dual BSD/GPL");
-
-/*
- * This driver assumes self-powered hardware and has no way for users to
- * trigger remote wakeup.  It uses autoconfiguration to select endpoints
- * and endpoint addresses.
- */
-
-
-/*-------------------------------------------------------------------------*/
-
-
-/* Encapsulate the module parameter settings */
-
-static struct {
-	char		*file[FSG_MAX_LUNS];
-	char		*serial;
-	bool		ro[FSG_MAX_LUNS];
-	bool		nofua[FSG_MAX_LUNS];
-	unsigned int	num_filenames;
-	unsigned int	num_ros;
-	unsigned int	num_nofuas;
-	unsigned int	nluns;
-
-	bool		removable;
-	bool		can_stall;
-	bool		cdrom;
-
-	char		*transport_parm;
-	char		*protocol_parm;
-	unsigned short	vendor;
-	unsigned short	product;
-	unsigned short	release;
-	unsigned int	buflen;
-
-	int		transport_type;
-	char		*transport_name;
-	int		protocol_type;
-	char		*protocol_name;
-
-} mod_data = {					// Default values
-	.transport_parm		= "BBB",
-	.protocol_parm		= "SCSI",
-	.removable		= 0,
-	.can_stall		= 1,
-	.cdrom			= 0,
-	.vendor			= FSG_VENDOR_ID,
-	.product		= FSG_PRODUCT_ID,
-	.release		= 0xffff,	// Use controller chip type
-	.buflen			= 16384,
-	};
-
-
-module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
-		S_IRUGO);
-MODULE_PARM_DESC(file, "names of backing files or devices");
-
-module_param_named(serial, mod_data.serial, charp, S_IRUGO);
-MODULE_PARM_DESC(serial, "USB serial number");
-
-module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
-MODULE_PARM_DESC(ro, "true to force read-only");
-
-module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas,
-		S_IRUGO);
-MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit");
-
-module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
-MODULE_PARM_DESC(luns, "number of LUNs");
-
-module_param_named(removable, mod_data.removable, bool, S_IRUGO);
-MODULE_PARM_DESC(removable, "true to simulate removable media");
-
-module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
-MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
-
-module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
-MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
-
-/* In the non-TEST version, only the module parameters listed above
- * are available. */
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-
-module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO);
-MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)");
-
-module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO);
-MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "
-		"8070, or SCSI)");
-
-module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
-MODULE_PARM_DESC(vendor, "USB Vendor ID");
-
-module_param_named(product, mod_data.product, ushort, S_IRUGO);
-MODULE_PARM_DESC(product, "USB Product ID");
-
-module_param_named(release, mod_data.release, ushort, S_IRUGO);
-MODULE_PARM_DESC(release, "USB release number");
-
-module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);
-MODULE_PARM_DESC(buflen, "I/O buffer size");
-
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-/*
- * These definitions will permit the compiler to avoid generating code for
- * parts of the driver that aren't used in the non-TEST version.  Even gcc
- * can recognize when a test of a constant expression yields a dead code
- * path.
- */
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-
-#define transport_is_bbb()	(mod_data.transport_type == USB_PR_BULK)
-#define transport_is_cbi()	(mod_data.transport_type == USB_PR_CBI)
-#define protocol_is_scsi()	(mod_data.protocol_type == USB_SC_SCSI)
-
-#else
-
-#define transport_is_bbb()	1
-#define transport_is_cbi()	0
-#define protocol_is_scsi()	1
-
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-/*-------------------------------------------------------------------------*/
-
-
-struct fsg_dev {
-	/* lock protects: state, all the req_busy's, and cbbuf_cmnd */
-	spinlock_t		lock;
-	struct usb_gadget	*gadget;
-
-	/* filesem protects: backing files in use */
-	struct rw_semaphore	filesem;
-
-	/* reference counting: wait until all LUNs are released */
-	struct kref		ref;
-
-	struct usb_ep		*ep0;		// Handy copy of gadget->ep0
-	struct usb_request	*ep0req;	// For control responses
-	unsigned int		ep0_req_tag;
-	const char		*ep0req_name;
-
-	struct usb_request	*intreq;	// For interrupt responses
-	int			intreq_busy;
-	struct fsg_buffhd	*intr_buffhd;
-
-	unsigned int		bulk_out_maxpacket;
-	enum fsg_state		state;		// For exception handling
-	unsigned int		exception_req_tag;
-
-	u8			config, new_config;
-
-	unsigned int		running : 1;
-	unsigned int		bulk_in_enabled : 1;
-	unsigned int		bulk_out_enabled : 1;
-	unsigned int		intr_in_enabled : 1;
-	unsigned int		phase_error : 1;
-	unsigned int		short_packet_received : 1;
-	unsigned int		bad_lun_okay : 1;
-
-	unsigned long		atomic_bitflags;
-#define REGISTERED		0
-#define IGNORE_BULK_OUT		1
-#define SUSPENDED		2
-
-	struct usb_ep		*bulk_in;
-	struct usb_ep		*bulk_out;
-	struct usb_ep		*intr_in;
-
-	struct fsg_buffhd	*next_buffhd_to_fill;
-	struct fsg_buffhd	*next_buffhd_to_drain;
-
-	int			thread_wakeup_needed;
-	struct completion	thread_notifier;
-	struct task_struct	*thread_task;
-
-	int			cmnd_size;
-	u8			cmnd[MAX_COMMAND_SIZE];
-	enum data_direction	data_dir;
-	u32			data_size;
-	u32			data_size_from_cmnd;
-	u32			tag;
-	unsigned int		lun;
-	u32			residue;
-	u32			usb_amount_left;
-
-	/* The CB protocol offers no way for a host to know when a command
-	 * has completed.  As a result the next command may arrive early,
-	 * and we will still have to handle it.  For that reason we need
-	 * a buffer to store new commands when using CB (or CBI, which
-	 * does not oblige a host to wait for command completion either). */
-	int			cbbuf_cmnd_size;
-	u8			cbbuf_cmnd[MAX_COMMAND_SIZE];
-
-	unsigned int		nluns;
-	struct fsg_lun		*luns;
-	struct fsg_lun		*curlun;
-	/* Must be the last entry */
-	struct fsg_buffhd	buffhds[];
-};
-
-typedef void (*fsg_routine_t)(struct fsg_dev *);
-
-static int exception_in_progress(struct fsg_dev *fsg)
-{
-	return (fsg->state > FSG_STATE_IDLE);
-}
-
-/* Make bulk-out requests be divisible by the maxpacket size */
-static void set_bulk_out_req_length(struct fsg_dev *fsg,
-		struct fsg_buffhd *bh, unsigned int length)
-{
-	unsigned int	rem;
-
-	bh->bulk_out_intended_length = length;
-	rem = length % fsg->bulk_out_maxpacket;
-	if (rem > 0)
-		length += fsg->bulk_out_maxpacket - rem;
-	bh->outreq->length = length;
-}
-
-static struct fsg_dev			*the_fsg;
-static struct usb_gadget_driver		fsg_driver;
-
-
-/*-------------------------------------------------------------------------*/
-
-static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
-{
-	const char	*name;
-
-	if (ep == fsg->bulk_in)
-		name = "bulk-in";
-	else if (ep == fsg->bulk_out)
-		name = "bulk-out";
-	else
-		name = ep->name;
-	DBG(fsg, "%s set halt\n", name);
-	return usb_ep_set_halt(ep);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * DESCRIPTORS ... most are static, but strings and (full) configuration
- * descriptors are built on demand.  Also the (static) config and interface
- * descriptors are adjusted during fsg_bind().
- */
-
-/* There is only one configuration. */
-#define	CONFIG_VALUE		1
-
-static struct usb_device_descriptor
-device_desc = {
-	.bLength =		sizeof device_desc,
-	.bDescriptorType =	USB_DT_DEVICE,
-
-	.bcdUSB =		cpu_to_le16(0x0200),
-	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
-
-	/* The next three values can be overridden by module parameters */
-	.idVendor =		cpu_to_le16(FSG_VENDOR_ID),
-	.idProduct =		cpu_to_le16(FSG_PRODUCT_ID),
-	.bcdDevice =		cpu_to_le16(0xffff),
-
-	.iManufacturer =	FSG_STRING_MANUFACTURER,
-	.iProduct =		FSG_STRING_PRODUCT,
-	.iSerialNumber =	FSG_STRING_SERIAL,
-	.bNumConfigurations =	1,
-};
-
-static struct usb_config_descriptor
-config_desc = {
-	.bLength =		sizeof config_desc,
-	.bDescriptorType =	USB_DT_CONFIG,
-
-	/* wTotalLength computed by usb_gadget_config_buf() */
-	.bNumInterfaces =	1,
-	.bConfigurationValue =	CONFIG_VALUE,
-	.iConfiguration =	FSG_STRING_CONFIG,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower =		CONFIG_USB_GADGET_VBUS_DRAW / 2,
-};
-
-
-static struct usb_qualifier_descriptor
-dev_qualifier = {
-	.bLength =		sizeof dev_qualifier,
-	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
-
-	.bcdUSB =		cpu_to_le16(0x0200),
-	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
-
-	.bNumConfigurations =	1,
-};
-
-static int populate_bos(struct fsg_dev *fsg, u8 *buf)
-{
-	memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE);
-	buf += USB_DT_BOS_SIZE;
-
-	memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE);
-	buf += USB_DT_USB_EXT_CAP_SIZE;
-
-	memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE);
-
-	return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE
-		+ USB_DT_USB_EXT_CAP_SIZE;
-}
-
-/*
- * Config descriptors must agree with the code that sets configurations
- * and with code managing interfaces and their altsettings.  They must
- * also handle different speeds and other-speed requests.
- */
-static int populate_config_buf(struct usb_gadget *gadget,
-		u8 *buf, u8 type, unsigned index)
-{
-	enum usb_device_speed			speed = gadget->speed;
-	int					len;
-	const struct usb_descriptor_header	**function;
-
-	if (index > 0)
-		return -EINVAL;
-
-	if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG)
-		speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;
-	function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH
-		? (const struct usb_descriptor_header **)fsg_hs_function
-		: (const struct usb_descriptor_header **)fsg_fs_function;
-
-	/* for now, don't advertise srp-only devices */
-	if (!gadget_is_otg(gadget))
-		function++;
-
-	len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
-	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
-	return len;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* These routines may be called in process context or in_irq */
-
-/* Caller must hold fsg->lock */
-static void wakeup_thread(struct fsg_dev *fsg)
-{
-	/* Tell the main thread that something has happened */
-	fsg->thread_wakeup_needed = 1;
-	if (fsg->thread_task)
-		wake_up_process(fsg->thread_task);
-}
-
-
-static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
-{
-	unsigned long		flags;
-
-	/* Do nothing if a higher-priority exception is already in progress.
-	 * If a lower-or-equal priority exception is in progress, preempt it
-	 * and notify the main thread by sending it a signal. */
-	spin_lock_irqsave(&fsg->lock, flags);
-	if (fsg->state <= new_state) {
-		fsg->exception_req_tag = fsg->ep0_req_tag;
-		fsg->state = new_state;
-		if (fsg->thread_task)
-			send_sig_info(SIGUSR1, SEND_SIG_FORCED,
-					fsg->thread_task);
-	}
-	spin_unlock_irqrestore(&fsg->lock, flags);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* The disconnect callback and ep0 routines.  These always run in_irq,
- * except that ep0_queue() is called in the main thread to acknowledge
- * completion of various requests: set config, set interface, and
- * Bulk-only device reset. */
-
-static void fsg_disconnect(struct usb_gadget *gadget)
-{
-	struct fsg_dev		*fsg = get_gadget_data(gadget);
-
-	DBG(fsg, "disconnect or port reset\n");
-	raise_exception(fsg, FSG_STATE_DISCONNECT);
-}
-
-
-static int ep0_queue(struct fsg_dev *fsg)
-{
-	int	rc;
-
-	rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC);
-	if (rc != 0 && rc != -ESHUTDOWN) {
-
-		/* We can't do much more than wait for a reset */
-		WARNING(fsg, "error in submission: %s --> %d\n",
-				fsg->ep0->name, rc);
-	}
-	return rc;
-}
-
-static void ep0_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct fsg_dev		*fsg = ep->driver_data;
-
-	if (req->actual > 0)
-		dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);
-	if (req->status || req->actual != req->length)
-		DBG(fsg, "%s --> %d, %u/%u\n", __func__,
-				req->status, req->actual, req->length);
-	if (req->status == -ECONNRESET)		// Request was cancelled
-		usb_ep_fifo_flush(ep);
-
-	if (req->status == 0 && req->context)
-		((fsg_routine_t) (req->context))(fsg);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Bulk and interrupt endpoint completion handlers.
- * These always run in_irq. */
-
-static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct fsg_dev		*fsg = ep->driver_data;
-	struct fsg_buffhd	*bh = req->context;
-
-	if (req->status || req->actual != req->length)
-		DBG(fsg, "%s --> %d, %u/%u\n", __func__,
-				req->status, req->actual, req->length);
-	if (req->status == -ECONNRESET)		// Request was cancelled
-		usb_ep_fifo_flush(ep);
-
-	/* Hold the lock while we update the request and buffer states */
-	smp_wmb();
-	spin_lock(&fsg->lock);
-	bh->inreq_busy = 0;
-	bh->state = BUF_STATE_EMPTY;
-	wakeup_thread(fsg);
-	spin_unlock(&fsg->lock);
-}
-
-static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct fsg_dev		*fsg = ep->driver_data;
-	struct fsg_buffhd	*bh = req->context;
-
-	dump_msg(fsg, "bulk-out", req->buf, req->actual);
-	if (req->status || req->actual != bh->bulk_out_intended_length)
-		DBG(fsg, "%s --> %d, %u/%u\n", __func__,
-				req->status, req->actual,
-				bh->bulk_out_intended_length);
-	if (req->status == -ECONNRESET)		// Request was cancelled
-		usb_ep_fifo_flush(ep);
-
-	/* Hold the lock while we update the request and buffer states */
-	smp_wmb();
-	spin_lock(&fsg->lock);
-	bh->outreq_busy = 0;
-	bh->state = BUF_STATE_FULL;
-	wakeup_thread(fsg);
-	spin_unlock(&fsg->lock);
-}
-
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct fsg_dev		*fsg = ep->driver_data;
-	struct fsg_buffhd	*bh = req->context;
-
-	if (req->status || req->actual != req->length)
-		DBG(fsg, "%s --> %d, %u/%u\n", __func__,
-				req->status, req->actual, req->length);
-	if (req->status == -ECONNRESET)		// Request was cancelled
-		usb_ep_fifo_flush(ep);
-
-	/* Hold the lock while we update the request and buffer states */
-	smp_wmb();
-	spin_lock(&fsg->lock);
-	fsg->intreq_busy = 0;
-	bh->state = BUF_STATE_EMPTY;
-	wakeup_thread(fsg);
-	spin_unlock(&fsg->lock);
-}
-
-#else
-static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
-{}
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Ep0 class-specific handlers.  These always run in_irq. */
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-	struct usb_request	*req = fsg->ep0req;
-	static u8		cbi_reset_cmnd[6] = {
-			SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
-
-	/* Error in command transfer? */
-	if (req->status || req->length != req->actual ||
-			req->actual < 6 || req->actual > MAX_COMMAND_SIZE) {
-
-		/* Not all controllers allow a protocol stall after
-		 * receiving control-out data, but we'll try anyway. */
-		fsg_set_halt(fsg, fsg->ep0);
-		return;			// Wait for reset
-	}
-
-	/* Is it the special reset command? */
-	if (req->actual >= sizeof cbi_reset_cmnd &&
-			memcmp(req->buf, cbi_reset_cmnd,
-				sizeof cbi_reset_cmnd) == 0) {
-
-		/* Raise an exception to stop the current operation
-		 * and reinitialize our state. */
-		DBG(fsg, "cbi reset request\n");
-		raise_exception(fsg, FSG_STATE_RESET);
-		return;
-	}
-
-	VDBG(fsg, "CB[I] accept device-specific command\n");
-	spin_lock(&fsg->lock);
-
-	/* Save the command for later */
-	if (fsg->cbbuf_cmnd_size)
-		WARNING(fsg, "CB[I] overwriting previous command\n");
-	fsg->cbbuf_cmnd_size = req->actual;
-	memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
-
-	wakeup_thread(fsg);
-	spin_unlock(&fsg->lock);
-}
-
-#else
-static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{}
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-static int class_setup_req(struct fsg_dev *fsg,
-		const struct usb_ctrlrequest *ctrl)
-{
-	struct usb_request	*req = fsg->ep0req;
-	int			value = -EOPNOTSUPP;
-	u16			w_index = le16_to_cpu(ctrl->wIndex);
-	u16                     w_value = le16_to_cpu(ctrl->wValue);
-	u16			w_length = le16_to_cpu(ctrl->wLength);
-
-	if (!fsg->config)
-		return value;
-
-	/* Handle Bulk-only class-specific requests */
-	if (transport_is_bbb()) {
-		switch (ctrl->bRequest) {
-
-		case US_BULK_RESET_REQUEST:
-			if (ctrl->bRequestType != (USB_DIR_OUT |
-					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
-				break;
-			if (w_index != 0 || w_value != 0 || w_length != 0) {
-				value = -EDOM;
-				break;
-			}
-
-			/* Raise an exception to stop the current operation
-			 * and reinitialize our state. */
-			DBG(fsg, "bulk reset request\n");
-			raise_exception(fsg, FSG_STATE_RESET);
-			value = DELAYED_STATUS;
-			break;
-
-		case US_BULK_GET_MAX_LUN:
-			if (ctrl->bRequestType != (USB_DIR_IN |
-					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
-				break;
-			if (w_index != 0 || w_value != 0 || w_length != 1) {
-				value = -EDOM;
-				break;
-			}
-			VDBG(fsg, "get max LUN\n");
-			*(u8 *) req->buf = fsg->nluns - 1;
-			value = 1;
-			break;
-		}
-	}
-
-	/* Handle CBI class-specific requests */
-	else {
-		switch (ctrl->bRequest) {
-
-		case USB_CBI_ADSC_REQUEST:
-			if (ctrl->bRequestType != (USB_DIR_OUT |
-					USB_TYPE_CLASS | USB_RECIP_INTERFACE))
-				break;
-			if (w_index != 0 || w_value != 0) {
-				value = -EDOM;
-				break;
-			}
-			if (w_length > MAX_COMMAND_SIZE) {
-				value = -EOVERFLOW;
-				break;
-			}
-			value = w_length;
-			fsg->ep0req->context = received_cbi_adsc;
-			break;
-		}
-	}
-
-	if (value == -EOPNOTSUPP)
-		VDBG(fsg,
-			"unknown class-specific control req "
-			"%02x.%02x v%04x i%04x l%u\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			le16_to_cpu(ctrl->wValue), w_index, w_length);
-	return value;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Ep0 standard request handlers.  These always run in_irq. */
-
-static int standard_setup_req(struct fsg_dev *fsg,
-		const struct usb_ctrlrequest *ctrl)
-{
-	struct usb_request	*req = fsg->ep0req;
-	int			value = -EOPNOTSUPP;
-	u16			w_index = le16_to_cpu(ctrl->wIndex);
-	u16			w_value = le16_to_cpu(ctrl->wValue);
-
-	/* Usually this just stores reply data in the pre-allocated ep0 buffer,
-	 * but config change events will also reconfigure hardware. */
-	switch (ctrl->bRequest) {
-
-	case USB_REQ_GET_DESCRIPTOR:
-		if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
-				USB_RECIP_DEVICE))
-			break;
-		switch (w_value >> 8) {
-
-		case USB_DT_DEVICE:
-			VDBG(fsg, "get device descriptor\n");
-			device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
-			value = sizeof device_desc;
-			memcpy(req->buf, &device_desc, value);
-			break;
-		case USB_DT_DEVICE_QUALIFIER:
-			VDBG(fsg, "get device qualifier\n");
-			if (!gadget_is_dualspeed(fsg->gadget) ||
-					fsg->gadget->speed == USB_SPEED_SUPER)
-				break;
-			/*
-			 * Assume ep0 uses the same maxpacket value for both
-			 * speeds
-			 */
-			dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
-			value = sizeof dev_qualifier;
-			memcpy(req->buf, &dev_qualifier, value);
-			break;
-
-		case USB_DT_OTHER_SPEED_CONFIG:
-			VDBG(fsg, "get other-speed config descriptor\n");
-			if (!gadget_is_dualspeed(fsg->gadget) ||
-					fsg->gadget->speed == USB_SPEED_SUPER)
-				break;
-			goto get_config;
-		case USB_DT_CONFIG:
-			VDBG(fsg, "get configuration descriptor\n");
-get_config:
-			value = populate_config_buf(fsg->gadget,
-					req->buf,
-					w_value >> 8,
-					w_value & 0xff);
-			break;
-
-		case USB_DT_STRING:
-			VDBG(fsg, "get string descriptor\n");
-
-			/* wIndex == language code */
-			value = usb_gadget_get_string(&fsg_stringtab,
-					w_value & 0xff, req->buf);
-			break;
-
-		case USB_DT_BOS:
-			VDBG(fsg, "get bos descriptor\n");
-
-			if (gadget_is_superspeed(fsg->gadget))
-				value = populate_bos(fsg, req->buf);
-			break;
-		}
-
-		break;
-
-	/* One config, two speeds */
-	case USB_REQ_SET_CONFIGURATION:
-		if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
-				USB_RECIP_DEVICE))
-			break;
-		VDBG(fsg, "set configuration\n");
-		if (w_value == CONFIG_VALUE || w_value == 0) {
-			fsg->new_config = w_value;
-
-			/* Raise an exception to wipe out previous transaction
-			 * state (queued bufs, etc) and set the new config. */
-			raise_exception(fsg, FSG_STATE_CONFIG_CHANGE);
-			value = DELAYED_STATUS;
-		}
-		break;
-	case USB_REQ_GET_CONFIGURATION:
-		if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
-				USB_RECIP_DEVICE))
-			break;
-		VDBG(fsg, "get configuration\n");
-		*(u8 *) req->buf = fsg->config;
-		value = 1;
-		break;
-
-	case USB_REQ_SET_INTERFACE:
-		if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD |
-				USB_RECIP_INTERFACE))
-			break;
-		if (fsg->config && w_index == 0) {
-
-			/* Raise an exception to wipe out previous transaction
-			 * state (queued bufs, etc) and install the new
-			 * interface altsetting. */
-			raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE);
-			value = DELAYED_STATUS;
-		}
-		break;
-	case USB_REQ_GET_INTERFACE:
-		if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
-				USB_RECIP_INTERFACE))
-			break;
-		if (!fsg->config)
-			break;
-		if (w_index != 0) {
-			value = -EDOM;
-			break;
-		}
-		VDBG(fsg, "get interface\n");
-		*(u8 *) req->buf = 0;
-		value = 1;
-		break;
-
-	default:
-		VDBG(fsg,
-			"unknown control req %02x.%02x v%04x i%04x l%u\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			w_value, w_index, le16_to_cpu(ctrl->wLength));
-	}
-
-	return value;
-}
-
-
-static int fsg_setup(struct usb_gadget *gadget,
-		const struct usb_ctrlrequest *ctrl)
-{
-	struct fsg_dev		*fsg = get_gadget_data(gadget);
-	int			rc;
-	int			w_length = le16_to_cpu(ctrl->wLength);
-
-	++fsg->ep0_req_tag;		// Record arrival of a new request
-	fsg->ep0req->context = NULL;
-	fsg->ep0req->length = 0;
-	dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl));
-
-	if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)
-		rc = class_setup_req(fsg, ctrl);
-	else
-		rc = standard_setup_req(fsg, ctrl);
-
-	/* Respond with data/status or defer until later? */
-	if (rc >= 0 && rc != DELAYED_STATUS) {
-		rc = min(rc, w_length);
-		fsg->ep0req->length = rc;
-		fsg->ep0req->zero = rc < w_length;
-		fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
-				"ep0-in" : "ep0-out");
-		rc = ep0_queue(fsg);
-	}
-
-	/* Device either stalls (rc < 0) or reports success */
-	return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* All the following routines run in process context */
-
-
-/* Use this for bulk or interrupt transfers, not ep0 */
-static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
-		struct usb_request *req, int *pbusy,
-		enum fsg_buffer_state *state)
-{
-	int	rc;
-
-	if (ep == fsg->bulk_in)
-		dump_msg(fsg, "bulk-in", req->buf, req->length);
-	else if (ep == fsg->intr_in)
-		dump_msg(fsg, "intr-in", req->buf, req->length);
-
-	spin_lock_irq(&fsg->lock);
-	*pbusy = 1;
-	*state = BUF_STATE_BUSY;
-	spin_unlock_irq(&fsg->lock);
-	rc = usb_ep_queue(ep, req, GFP_KERNEL);
-	if (rc != 0) {
-		*pbusy = 0;
-		*state = BUF_STATE_EMPTY;
-
-		/* We can't do much more than wait for a reset */
-
-		/* Note: currently the net2280 driver fails zero-length
-		 * submissions if DMA is enabled. */
-		if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP &&
-						req->length == 0))
-			WARNING(fsg, "error in submission: %s --> %d\n",
-					ep->name, rc);
-	}
-}
-
-
-static int sleep_thread(struct fsg_dev *fsg)
-{
-	int	rc = 0;
-
-	/* Wait until a signal arrives or we are woken up */
-	for (;;) {
-		try_to_freeze();
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (signal_pending(current)) {
-			rc = -EINTR;
-			break;
-		}
-		if (fsg->thread_wakeup_needed)
-			break;
-		schedule();
-	}
-	__set_current_state(TASK_RUNNING);
-	fsg->thread_wakeup_needed = 0;
-	return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_read(struct fsg_dev *fsg)
-{
-	struct fsg_lun		*curlun = fsg->curlun;
-	u32			lba;
-	struct fsg_buffhd	*bh;
-	int			rc;
-	u32			amount_left;
-	loff_t			file_offset, file_offset_tmp;
-	unsigned int		amount;
-	ssize_t			nread;
-
-	/* Get the starting Logical Block Address and check that it's
-	 * not too big */
-	if (fsg->cmnd[0] == READ_6)
-		lba = get_unaligned_be24(&fsg->cmnd[1]);
-	else {
-		lba = get_unaligned_be32(&fsg->cmnd[2]);
-
-		/* We allow DPO (Disable Page Out = don't save data in the
-		 * cache) and FUA (Force Unit Access = don't read from the
-		 * cache), but we don't implement them. */
-		if ((fsg->cmnd[1] & ~0x18) != 0) {
-			curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-			return -EINVAL;
-		}
-	}
-	if (lba >= curlun->num_sectors) {
-		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-	file_offset = ((loff_t) lba) << curlun->blkbits;
-
-	/* Carry out the file reads */
-	amount_left = fsg->data_size_from_cmnd;
-	if (unlikely(amount_left == 0))
-		return -EIO;		// No default reply
-
-	for (;;) {
-
-		/* Figure out how much we need to read:
-		 * Try to read the remaining amount.
-		 * But don't read more than the buffer size.
-		 * And don't try to read past the end of the file.
-		 */
-		amount = min((unsigned int) amount_left, mod_data.buflen);
-		amount = min((loff_t) amount,
-				curlun->file_length - file_offset);
-
-		/* Wait for the next buffer to become available */
-		bh = fsg->next_buffhd_to_fill;
-		while (bh->state != BUF_STATE_EMPTY) {
-			rc = sleep_thread(fsg);
-			if (rc)
-				return rc;
-		}
-
-		/* If we were asked to read past the end of file,
-		 * end with an empty buffer. */
-		if (amount == 0) {
-			curlun->sense_data =
-					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-			curlun->sense_data_info = file_offset >> curlun->blkbits;
-			curlun->info_valid = 1;
-			bh->inreq->length = 0;
-			bh->state = BUF_STATE_FULL;
-			break;
-		}
-
-		/* Perform the read */
-		file_offset_tmp = file_offset;
-		nread = vfs_read(curlun->filp,
-				(char __user *) bh->buf,
-				amount, &file_offset_tmp);
-		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
-				(unsigned long long) file_offset,
-				(int) nread);
-		if (signal_pending(current))
-			return -EINTR;
-
-		if (nread < 0) {
-			LDBG(curlun, "error in file read: %d\n",
-					(int) nread);
-			nread = 0;
-		} else if (nread < amount) {
-			LDBG(curlun, "partial file read: %d/%u\n",
-					(int) nread, amount);
-			nread = round_down(nread, curlun->blksize);
-		}
-		file_offset  += nread;
-		amount_left  -= nread;
-		fsg->residue -= nread;
-
-		/* Except at the end of the transfer, nread will be
-		 * equal to the buffer size, which is divisible by the
-		 * bulk-in maxpacket size.
-		 */
-		bh->inreq->length = nread;
-		bh->state = BUF_STATE_FULL;
-
-		/* If an error occurred, report it and its position */
-		if (nread < amount) {
-			curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
-			curlun->sense_data_info = file_offset >> curlun->blkbits;
-			curlun->info_valid = 1;
-			break;
-		}
-
-		if (amount_left == 0)
-			break;		// No more left to read
-
-		/* Send this buffer and go read some more */
-		bh->inreq->zero = 0;
-		start_transfer(fsg, fsg->bulk_in, bh->inreq,
-				&bh->inreq_busy, &bh->state);
-		fsg->next_buffhd_to_fill = bh->next;
-	}
-
-	return -EIO;		// No default reply
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_write(struct fsg_dev *fsg)
-{
-	struct fsg_lun		*curlun = fsg->curlun;
-	u32			lba;
-	struct fsg_buffhd	*bh;
-	int			get_some_more;
-	u32			amount_left_to_req, amount_left_to_write;
-	loff_t			usb_offset, file_offset, file_offset_tmp;
-	unsigned int		amount;
-	ssize_t			nwritten;
-	int			rc;
-
-	if (curlun->ro) {
-		curlun->sense_data = SS_WRITE_PROTECTED;
-		return -EINVAL;
-	}
-	spin_lock(&curlun->filp->f_lock);
-	curlun->filp->f_flags &= ~O_SYNC;	// Default is not to wait
-	spin_unlock(&curlun->filp->f_lock);
-
-	/* Get the starting Logical Block Address and check that it's
-	 * not too big */
-	if (fsg->cmnd[0] == WRITE_6)
-		lba = get_unaligned_be24(&fsg->cmnd[1]);
-	else {
-		lba = get_unaligned_be32(&fsg->cmnd[2]);
-
-		/* We allow DPO (Disable Page Out = don't save data in the
-		 * cache) and FUA (Force Unit Access = write directly to the
-		 * medium).  We don't implement DPO; we implement FUA by
-		 * performing synchronous output. */
-		if ((fsg->cmnd[1] & ~0x18) != 0) {
-			curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-			return -EINVAL;
-		}
-		/* FUA */
-		if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) {
-			spin_lock(&curlun->filp->f_lock);
-			curlun->filp->f_flags |= O_DSYNC;
-			spin_unlock(&curlun->filp->f_lock);
-		}
-	}
-	if (lba >= curlun->num_sectors) {
-		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-
-	/* Carry out the file writes */
-	get_some_more = 1;
-	file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits;
-	amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd;
-
-	while (amount_left_to_write > 0) {
-
-		/* Queue a request for more data from the host */
-		bh = fsg->next_buffhd_to_fill;
-		if (bh->state == BUF_STATE_EMPTY && get_some_more) {
-
-			/* Figure out how much we want to get:
-			 * Try to get the remaining amount,
-			 * but not more than the buffer size.
-			 */
-			amount = min(amount_left_to_req, mod_data.buflen);
-
-			/* Beyond the end of the backing file? */
-			if (usb_offset >= curlun->file_length) {
-				get_some_more = 0;
-				curlun->sense_data =
-					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-				curlun->sense_data_info = usb_offset >> curlun->blkbits;
-				curlun->info_valid = 1;
-				continue;
-			}
-
-			/* Get the next buffer */
-			usb_offset += amount;
-			fsg->usb_amount_left -= amount;
-			amount_left_to_req -= amount;
-			if (amount_left_to_req == 0)
-				get_some_more = 0;
-
-			/* Except at the end of the transfer, amount will be
-			 * equal to the buffer size, which is divisible by
-			 * the bulk-out maxpacket size.
-			 */
-			set_bulk_out_req_length(fsg, bh, amount);
-			start_transfer(fsg, fsg->bulk_out, bh->outreq,
-					&bh->outreq_busy, &bh->state);
-			fsg->next_buffhd_to_fill = bh->next;
-			continue;
-		}
-
-		/* Write the received data to the backing file */
-		bh = fsg->next_buffhd_to_drain;
-		if (bh->state == BUF_STATE_EMPTY && !get_some_more)
-			break;			// We stopped early
-		if (bh->state == BUF_STATE_FULL) {
-			smp_rmb();
-			fsg->next_buffhd_to_drain = bh->next;
-			bh->state = BUF_STATE_EMPTY;
-
-			/* Did something go wrong with the transfer? */
-			if (bh->outreq->status != 0) {
-				curlun->sense_data = SS_COMMUNICATION_FAILURE;
-				curlun->sense_data_info = file_offset >> curlun->blkbits;
-				curlun->info_valid = 1;
-				break;
-			}
-
-			amount = bh->outreq->actual;
-			if (curlun->file_length - file_offset < amount) {
-				LERROR(curlun,
-	"write %u @ %llu beyond end %llu\n",
-	amount, (unsigned long long) file_offset,
-	(unsigned long long) curlun->file_length);
-				amount = curlun->file_length - file_offset;
-			}
-
-			/* Don't accept excess data.  The spec doesn't say
-			 * what to do in this case.  We'll ignore the error.
-			 */
-			amount = min(amount, bh->bulk_out_intended_length);
-
-			/* Don't write a partial block */
-			amount = round_down(amount, curlun->blksize);
-			if (amount == 0)
-				goto empty_write;
-
-			/* Perform the write */
-			file_offset_tmp = file_offset;
-			nwritten = vfs_write(curlun->filp,
-					(char __user *) bh->buf,
-					amount, &file_offset_tmp);
-			VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
-					(unsigned long long) file_offset,
-					(int) nwritten);
-			if (signal_pending(current))
-				return -EINTR;		// Interrupted!
-
-			if (nwritten < 0) {
-				LDBG(curlun, "error in file write: %d\n",
-						(int) nwritten);
-				nwritten = 0;
-			} else if (nwritten < amount) {
-				LDBG(curlun, "partial file write: %d/%u\n",
-						(int) nwritten, amount);
-				nwritten = round_down(nwritten, curlun->blksize);
-			}
-			file_offset += nwritten;
-			amount_left_to_write -= nwritten;
-			fsg->residue -= nwritten;
-
-			/* If an error occurred, report it and its position */
-			if (nwritten < amount) {
-				curlun->sense_data = SS_WRITE_ERROR;
-				curlun->sense_data_info = file_offset >> curlun->blkbits;
-				curlun->info_valid = 1;
-				break;
-			}
-
- empty_write:
-			/* Did the host decide to stop early? */
-			if (bh->outreq->actual < bh->bulk_out_intended_length) {
-				fsg->short_packet_received = 1;
-				break;
-			}
-			continue;
-		}
-
-		/* Wait for something to happen */
-		rc = sleep_thread(fsg);
-		if (rc)
-			return rc;
-	}
-
-	return -EIO;		// No default reply
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_synchronize_cache(struct fsg_dev *fsg)
-{
-	struct fsg_lun	*curlun = fsg->curlun;
-	int		rc;
-
-	/* We ignore the requested LBA and write out all file's
-	 * dirty data buffers. */
-	rc = fsg_lun_fsync_sub(curlun);
-	if (rc)
-		curlun->sense_data = SS_WRITE_ERROR;
-	return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void invalidate_sub(struct fsg_lun *curlun)
-{
-	struct file	*filp = curlun->filp;
-	struct inode	*inode = filp->f_path.dentry->d_inode;
-	unsigned long	rc;
-
-	rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);
-	VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc);
-}
-
-static int do_verify(struct fsg_dev *fsg)
-{
-	struct fsg_lun		*curlun = fsg->curlun;
-	u32			lba;
-	u32			verification_length;
-	struct fsg_buffhd	*bh = fsg->next_buffhd_to_fill;
-	loff_t			file_offset, file_offset_tmp;
-	u32			amount_left;
-	unsigned int		amount;
-	ssize_t			nread;
-
-	/* Get the starting Logical Block Address and check that it's
-	 * not too big */
-	lba = get_unaligned_be32(&fsg->cmnd[2]);
-	if (lba >= curlun->num_sectors) {
-		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-
-	/* We allow DPO (Disable Page Out = don't save data in the
-	 * cache) but we don't implement it. */
-	if ((fsg->cmnd[1] & ~0x10) != 0) {
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	verification_length = get_unaligned_be16(&fsg->cmnd[7]);
-	if (unlikely(verification_length == 0))
-		return -EIO;		// No default reply
-
-	/* Prepare to carry out the file verify */
-	amount_left = verification_length << curlun->blkbits;
-	file_offset = ((loff_t) lba) << curlun->blkbits;
-
-	/* Write out all the dirty buffers before invalidating them */
-	fsg_lun_fsync_sub(curlun);
-	if (signal_pending(current))
-		return -EINTR;
-
-	invalidate_sub(curlun);
-	if (signal_pending(current))
-		return -EINTR;
-
-	/* Just try to read the requested blocks */
-	while (amount_left > 0) {
-
-		/* Figure out how much we need to read:
-		 * Try to read the remaining amount, but not more than
-		 * the buffer size.
-		 * And don't try to read past the end of the file.
-		 */
-		amount = min((unsigned int) amount_left, mod_data.buflen);
-		amount = min((loff_t) amount,
-				curlun->file_length - file_offset);
-		if (amount == 0) {
-			curlun->sense_data =
-					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-			curlun->sense_data_info = file_offset >> curlun->blkbits;
-			curlun->info_valid = 1;
-			break;
-		}
-
-		/* Perform the read */
-		file_offset_tmp = file_offset;
-		nread = vfs_read(curlun->filp,
-				(char __user *) bh->buf,
-				amount, &file_offset_tmp);
-		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
-				(unsigned long long) file_offset,
-				(int) nread);
-		if (signal_pending(current))
-			return -EINTR;
-
-		if (nread < 0) {
-			LDBG(curlun, "error in file verify: %d\n",
-					(int) nread);
-			nread = 0;
-		} else if (nread < amount) {
-			LDBG(curlun, "partial file verify: %d/%u\n",
-					(int) nread, amount);
-			nread = round_down(nread, curlun->blksize);
-		}
-		if (nread == 0) {
-			curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
-			curlun->sense_data_info = file_offset >> curlun->blkbits;
-			curlun->info_valid = 1;
-			break;
-		}
-		file_offset += nread;
-		amount_left -= nread;
-	}
-	return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-	u8	*buf = (u8 *) bh->buf;
-
-	static char vendor_id[] = "Linux   ";
-	static char product_disk_id[] = "File-Stor Gadget";
-	static char product_cdrom_id[] = "File-CD Gadget  ";
-
-	if (!fsg->curlun) {		// Unsupported LUNs are okay
-		fsg->bad_lun_okay = 1;
-		memset(buf, 0, 36);
-		buf[0] = 0x7f;		// Unsupported, no device-type
-		buf[4] = 31;		// Additional length
-		return 36;
-	}
-
-	memset(buf, 0, 8);
-	buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK);
-	if (mod_data.removable)
-		buf[1] = 0x80;
-	buf[2] = 2;		// ANSI SCSI level 2
-	buf[3] = 2;		// SCSI-2 INQUIRY data format
-	buf[4] = 31;		// Additional length
-				// No special options
-	sprintf(buf + 8, "%-8s%-16s%04x", vendor_id,
-			(mod_data.cdrom ? product_cdrom_id :
-				product_disk_id),
-			mod_data.release);
-	return 36;
-}
-
-
-static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-	struct fsg_lun	*curlun = fsg->curlun;
-	u8		*buf = (u8 *) bh->buf;
-	u32		sd, sdinfo;
-	int		valid;
-
-	/*
-	 * From the SCSI-2 spec., section 7.9 (Unit attention condition):
-	 *
-	 * If a REQUEST SENSE command is received from an initiator
-	 * with a pending unit attention condition (before the target
-	 * generates the contingent allegiance condition), then the
-	 * target shall either:
-	 *   a) report any pending sense data and preserve the unit
-	 *	attention condition on the logical unit, or,
-	 *   b) report the unit attention condition, may discard any
-	 *	pending sense data, and clear the unit attention
-	 *	condition on the logical unit for that initiator.
-	 *
-	 * FSG normally uses option a); enable this code to use option b).
-	 */
-#if 0
-	if (curlun && curlun->unit_attention_data != SS_NO_SENSE) {
-		curlun->sense_data = curlun->unit_attention_data;
-		curlun->unit_attention_data = SS_NO_SENSE;
-	}
-#endif
-
-	if (!curlun) {		// Unsupported LUNs are okay
-		fsg->bad_lun_okay = 1;
-		sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
-		sdinfo = 0;
-		valid = 0;
-	} else {
-		sd = curlun->sense_data;
-		sdinfo = curlun->sense_data_info;
-		valid = curlun->info_valid << 7;
-		curlun->sense_data = SS_NO_SENSE;
-		curlun->sense_data_info = 0;
-		curlun->info_valid = 0;
-	}
-
-	memset(buf, 0, 18);
-	buf[0] = valid | 0x70;			// Valid, current error
-	buf[2] = SK(sd);
-	put_unaligned_be32(sdinfo, &buf[3]);	/* Sense information */
-	buf[7] = 18 - 8;			// Additional sense length
-	buf[12] = ASC(sd);
-	buf[13] = ASCQ(sd);
-	return 18;
-}
-
-
-static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-	struct fsg_lun	*curlun = fsg->curlun;
-	u32		lba = get_unaligned_be32(&fsg->cmnd[2]);
-	int		pmi = fsg->cmnd[8];
-	u8		*buf = (u8 *) bh->buf;
-
-	/* Check the PMI and LBA fields */
-	if (pmi > 1 || (pmi == 0 && lba != 0)) {
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);
-						/* Max logical block */
-	put_unaligned_be32(curlun->blksize, &buf[4]);	/* Block length */
-	return 8;
-}
-
-
-static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-	struct fsg_lun	*curlun = fsg->curlun;
-	int		msf = fsg->cmnd[1] & 0x02;
-	u32		lba = get_unaligned_be32(&fsg->cmnd[2]);
-	u8		*buf = (u8 *) bh->buf;
-
-	if ((fsg->cmnd[1] & ~0x02) != 0) {		/* Mask away MSF */
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-	if (lba >= curlun->num_sectors) {
-		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-
-	memset(buf, 0, 8);
-	buf[0] = 0x01;		/* 2048 bytes of user data, rest is EC */
-	store_cdrom_address(&buf[4], msf, lba);
-	return 8;
-}
-
-
-static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-	struct fsg_lun	*curlun = fsg->curlun;
-	int		msf = fsg->cmnd[1] & 0x02;
-	int		start_track = fsg->cmnd[6];
-	u8		*buf = (u8 *) bh->buf;
-
-	if ((fsg->cmnd[1] & ~0x02) != 0 ||		/* Mask away MSF */
-			start_track > 1) {
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	memset(buf, 0, 20);
-	buf[1] = (20-2);		/* TOC data length */
-	buf[2] = 1;			/* First track number */
-	buf[3] = 1;			/* Last track number */
-	buf[5] = 0x16;			/* Data track, copying allowed */
-	buf[6] = 0x01;			/* Only track is number 1 */
-	store_cdrom_address(&buf[8], msf, 0);
-
-	buf[13] = 0x16;			/* Lead-out track is data */
-	buf[14] = 0xAA;			/* Lead-out track number */
-	store_cdrom_address(&buf[16], msf, curlun->num_sectors);
-	return 20;
-}
-
-
-static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-	struct fsg_lun	*curlun = fsg->curlun;
-	int		mscmnd = fsg->cmnd[0];
-	u8		*buf = (u8 *) bh->buf;
-	u8		*buf0 = buf;
-	int		pc, page_code;
-	int		changeable_values, all_pages;
-	int		valid_page = 0;
-	int		len, limit;
-
-	if ((fsg->cmnd[1] & ~0x08) != 0) {		// Mask away DBD
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-	pc = fsg->cmnd[2] >> 6;
-	page_code = fsg->cmnd[2] & 0x3f;
-	if (pc == 3) {
-		curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
-		return -EINVAL;
-	}
-	changeable_values = (pc == 1);
-	all_pages = (page_code == 0x3f);
-
-	/* Write the mode parameter header.  Fixed values are: default
-	 * medium type, no cache control (DPOFUA), and no block descriptors.
-	 * The only variable value is the WriteProtect bit.  We will fill in
-	 * the mode data length later. */
-	memset(buf, 0, 8);
-	if (mscmnd == MODE_SENSE) {
-		buf[2] = (curlun->ro ? 0x80 : 0x00);		// WP, DPOFUA
-		buf += 4;
-		limit = 255;
-	} else {			// MODE_SENSE_10
-		buf[3] = (curlun->ro ? 0x80 : 0x00);		// WP, DPOFUA
-		buf += 8;
-		limit = 65535;		// Should really be mod_data.buflen
-	}
-
-	/* No block descriptors */
-
-	/* The mode pages, in numerical order.  The only page we support
-	 * is the Caching page. */
-	if (page_code == 0x08 || all_pages) {
-		valid_page = 1;
-		buf[0] = 0x08;		// Page code
-		buf[1] = 10;		// Page length
-		memset(buf+2, 0, 10);	// None of the fields are changeable
-
-		if (!changeable_values) {
-			buf[2] = 0x04;	// Write cache enable,
-					// Read cache not disabled
-					// No cache retention priorities
-			put_unaligned_be16(0xffff, &buf[4]);
-					/* Don't disable prefetch */
-					/* Minimum prefetch = 0 */
-			put_unaligned_be16(0xffff, &buf[8]);
-					/* Maximum prefetch */
-			put_unaligned_be16(0xffff, &buf[10]);
-					/* Maximum prefetch ceiling */
-		}
-		buf += 12;
-	}
-
-	/* Check that a valid page was requested and the mode data length
-	 * isn't too long. */
-	len = buf - buf0;
-	if (!valid_page || len > limit) {
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	/*  Store the mode data length */
-	if (mscmnd == MODE_SENSE)
-		buf0[0] = len - 1;
-	else
-		put_unaligned_be16(len - 2, buf0);
-	return len;
-}
-
-
-static int do_start_stop(struct fsg_dev *fsg)
-{
-	struct fsg_lun	*curlun = fsg->curlun;
-	int		loej, start;
-
-	if (!mod_data.removable) {
-		curlun->sense_data = SS_INVALID_COMMAND;
-		return -EINVAL;
-	}
-
-	// int immed = fsg->cmnd[1] & 0x01;
-	loej = fsg->cmnd[4] & 0x02;
-	start = fsg->cmnd[4] & 0x01;
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-	if ((fsg->cmnd[1] & ~0x01) != 0 ||		// Mask away Immed
-			(fsg->cmnd[4] & ~0x03) != 0) {	// Mask LoEj, Start
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	if (!start) {
-
-		/* Are we allowed to unload the media? */
-		if (curlun->prevent_medium_removal) {
-			LDBG(curlun, "unload attempt prevented\n");
-			curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
-			return -EINVAL;
-		}
-		if (loej) {		// Simulate an unload/eject
-			up_read(&fsg->filesem);
-			down_write(&fsg->filesem);
-			fsg_lun_close(curlun);
-			up_write(&fsg->filesem);
-			down_read(&fsg->filesem);
-		}
-	} else {
-
-		/* Our emulation doesn't support mounting; the medium is
-		 * available for use as soon as it is loaded. */
-		if (!fsg_lun_is_open(curlun)) {
-			curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
-			return -EINVAL;
-		}
-	}
-#endif
-	return 0;
-}
-
-
-static int do_prevent_allow(struct fsg_dev *fsg)
-{
-	struct fsg_lun	*curlun = fsg->curlun;
-	int		prevent;
-
-	if (!mod_data.removable) {
-		curlun->sense_data = SS_INVALID_COMMAND;
-		return -EINVAL;
-	}
-
-	prevent = fsg->cmnd[4] & 0x01;
-	if ((fsg->cmnd[4] & ~0x01) != 0) {		// Mask away Prevent
-		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-		return -EINVAL;
-	}
-
-	if (curlun->prevent_medium_removal && !prevent)
-		fsg_lun_fsync_sub(curlun);
-	curlun->prevent_medium_removal = prevent;
-	return 0;
-}
-
-
-static int do_read_format_capacities(struct fsg_dev *fsg,
-			struct fsg_buffhd *bh)
-{
-	struct fsg_lun	*curlun = fsg->curlun;
-	u8		*buf = (u8 *) bh->buf;
-
-	buf[0] = buf[1] = buf[2] = 0;
-	buf[3] = 8;		// Only the Current/Maximum Capacity Descriptor
-	buf += 4;
-
-	put_unaligned_be32(curlun->num_sectors, &buf[0]);
-						/* Number of blocks */
-	put_unaligned_be32(curlun->blksize, &buf[4]);	/* Block length */
-	buf[4] = 0x02;				/* Current capacity */
-	return 12;
-}
-
-
-static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-	struct fsg_lun	*curlun = fsg->curlun;
-
-	/* We don't support MODE SELECT */
-	curlun->sense_data = SS_INVALID_COMMAND;
-	return -EINVAL;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
-{
-	int	rc;
-
-	rc = fsg_set_halt(fsg, fsg->bulk_in);
-	if (rc == -EAGAIN)
-		VDBG(fsg, "delayed bulk-in endpoint halt\n");
-	while (rc != 0) {
-		if (rc != -EAGAIN) {
-			WARNING(fsg, "usb_ep_set_halt -> %d\n", rc);
-			rc = 0;
-			break;
-		}
-
-		/* Wait for a short time and then try again */
-		if (msleep_interruptible(100) != 0)
-			return -EINTR;
-		rc = usb_ep_set_halt(fsg->bulk_in);
-	}
-	return rc;
-}
-
-static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
-{
-	int	rc;
-
-	DBG(fsg, "bulk-in set wedge\n");
-	rc = usb_ep_set_wedge(fsg->bulk_in);
-	if (rc == -EAGAIN)
-		VDBG(fsg, "delayed bulk-in endpoint wedge\n");
-	while (rc != 0) {
-		if (rc != -EAGAIN) {
-			WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc);
-			rc = 0;
-			break;
-		}
-
-		/* Wait for a short time and then try again */
-		if (msleep_interruptible(100) != 0)
-			return -EINTR;
-		rc = usb_ep_set_wedge(fsg->bulk_in);
-	}
-	return rc;
-}
-
-static int throw_away_data(struct fsg_dev *fsg)
-{
-	struct fsg_buffhd	*bh;
-	u32			amount;
-	int			rc;
-
-	while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY ||
-			fsg->usb_amount_left > 0) {
-
-		/* Throw away the data in a filled buffer */
-		if (bh->state == BUF_STATE_FULL) {
-			smp_rmb();
-			bh->state = BUF_STATE_EMPTY;
-			fsg->next_buffhd_to_drain = bh->next;
-
-			/* A short packet or an error ends everything */
-			if (bh->outreq->actual < bh->bulk_out_intended_length ||
-					bh->outreq->status != 0) {
-				raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
-				return -EINTR;
-			}
-			continue;
-		}
-
-		/* Try to submit another request if we need one */
-		bh = fsg->next_buffhd_to_fill;
-		if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) {
-			amount = min(fsg->usb_amount_left,
-					(u32) mod_data.buflen);
-
-			/* Except at the end of the transfer, amount will be
-			 * equal to the buffer size, which is divisible by
-			 * the bulk-out maxpacket size.
-			 */
-			set_bulk_out_req_length(fsg, bh, amount);
-			start_transfer(fsg, fsg->bulk_out, bh->outreq,
-					&bh->outreq_busy, &bh->state);
-			fsg->next_buffhd_to_fill = bh->next;
-			fsg->usb_amount_left -= amount;
-			continue;
-		}
-
-		/* Otherwise wait for something to happen */
-		rc = sleep_thread(fsg);
-		if (rc)
-			return rc;
-	}
-	return 0;
-}
-
-
-static int finish_reply(struct fsg_dev *fsg)
-{
-	struct fsg_buffhd	*bh = fsg->next_buffhd_to_fill;
-	int			rc = 0;
-
-	switch (fsg->data_dir) {
-	case DATA_DIR_NONE:
-		break;			// Nothing to send
-
-	/* If we don't know whether the host wants to read or write,
-	 * this must be CB or CBI with an unknown command.  We mustn't
-	 * try to send or receive any data.  So stall both bulk pipes
-	 * if we can and wait for a reset. */
-	case DATA_DIR_UNKNOWN:
-		if (mod_data.can_stall) {
-			fsg_set_halt(fsg, fsg->bulk_out);
-			rc = halt_bulk_in_endpoint(fsg);
-		}
-		break;
-
-	/* All but the last buffer of data must have already been sent */
-	case DATA_DIR_TO_HOST:
-		if (fsg->data_size == 0)
-			;		// Nothing to send
-
-		/* If there's no residue, simply send the last buffer */
-		else if (fsg->residue == 0) {
-			bh->inreq->zero = 0;
-			start_transfer(fsg, fsg->bulk_in, bh->inreq,
-					&bh->inreq_busy, &bh->state);
-			fsg->next_buffhd_to_fill = bh->next;
-		}
-
-		/* There is a residue.  For CB and CBI, simply mark the end
-		 * of the data with a short packet.  However, if we are
-		 * allowed to stall, there was no data at all (residue ==
-		 * data_size), and the command failed (invalid LUN or
-		 * sense data is set), then halt the bulk-in endpoint
-		 * instead. */
-		else if (!transport_is_bbb()) {
-			if (mod_data.can_stall &&
-					fsg->residue == fsg->data_size &&
-	(!fsg->curlun || fsg->curlun->sense_data != SS_NO_SENSE)) {
-				bh->state = BUF_STATE_EMPTY;
-				rc = halt_bulk_in_endpoint(fsg);
-			} else {
-				bh->inreq->zero = 1;
-				start_transfer(fsg, fsg->bulk_in, bh->inreq,
-						&bh->inreq_busy, &bh->state);
-				fsg->next_buffhd_to_fill = bh->next;
-			}
-		}
-
-		/*
-		 * For Bulk-only, mark the end of the data with a short
-		 * packet.  If we are allowed to stall, halt the bulk-in
-		 * endpoint.  (Note: This violates the Bulk-Only Transport
-		 * specification, which requires us to pad the data if we
-		 * don't halt the endpoint.  Presumably nobody will mind.)
-		 */
-		else {
-			bh->inreq->zero = 1;
-			start_transfer(fsg, fsg->bulk_in, bh->inreq,
-					&bh->inreq_busy, &bh->state);
-			fsg->next_buffhd_to_fill = bh->next;
-			if (mod_data.can_stall)
-				rc = halt_bulk_in_endpoint(fsg);
-		}
-		break;
-
-	/* We have processed all we want from the data the host has sent.
-	 * There may still be outstanding bulk-out requests. */
-	case DATA_DIR_FROM_HOST:
-		if (fsg->residue == 0)
-			;		// Nothing to receive
-
-		/* Did the host stop sending unexpectedly early? */
-		else if (fsg->short_packet_received) {
-			raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
-			rc = -EINTR;
-		}
-
-		/* We haven't processed all the incoming data.  Even though
-		 * we may be allowed to stall, doing so would cause a race.
-		 * The controller may already have ACK'ed all the remaining
-		 * bulk-out packets, in which case the host wouldn't see a
-		 * STALL.  Not realizing the endpoint was halted, it wouldn't
-		 * clear the halt -- leading to problems later on. */
-#if 0
-		else if (mod_data.can_stall) {
-			fsg_set_halt(fsg, fsg->bulk_out);
-			raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
-			rc = -EINTR;
-		}
-#endif
-
-		/* We can't stall.  Read in the excess data and throw it
-		 * all away. */
-		else
-			rc = throw_away_data(fsg);
-		break;
-	}
-	return rc;
-}
-
-
-static int send_status(struct fsg_dev *fsg)
-{
-	struct fsg_lun		*curlun = fsg->curlun;
-	struct fsg_buffhd	*bh;
-	int			rc;
-	u8			status = US_BULK_STAT_OK;
-	u32			sd, sdinfo = 0;
-
-	/* Wait for the next buffer to become available */
-	bh = fsg->next_buffhd_to_fill;
-	while (bh->state != BUF_STATE_EMPTY) {
-		rc = sleep_thread(fsg);
-		if (rc)
-			return rc;
-	}
-
-	if (curlun) {
-		sd = curlun->sense_data;
-		sdinfo = curlun->sense_data_info;
-	} else if (fsg->bad_lun_okay)
-		sd = SS_NO_SENSE;
-	else
-		sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
-
-	if (fsg->phase_error) {
-		DBG(fsg, "sending phase-error status\n");
-		status = US_BULK_STAT_PHASE;
-		sd = SS_INVALID_COMMAND;
-	} else if (sd != SS_NO_SENSE) {
-		DBG(fsg, "sending command-failure status\n");
-		status = US_BULK_STAT_FAIL;
-		VDBG(fsg, "  sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
-				"  info x%x\n",
-				SK(sd), ASC(sd), ASCQ(sd), sdinfo);
-	}
-
-	if (transport_is_bbb()) {
-		struct bulk_cs_wrap	*csw = bh->buf;
-
-		/* Store and send the Bulk-only CSW */
-		csw->Signature = cpu_to_le32(US_BULK_CS_SIGN);
-		csw->Tag = fsg->tag;
-		csw->Residue = cpu_to_le32(fsg->residue);
-		csw->Status = status;
-
-		bh->inreq->length = US_BULK_CS_WRAP_LEN;
-		bh->inreq->zero = 0;
-		start_transfer(fsg, fsg->bulk_in, bh->inreq,
-				&bh->inreq_busy, &bh->state);
-
-	} else if (mod_data.transport_type == USB_PR_CB) {
-
-		/* Control-Bulk transport has no status phase! */
-		return 0;
-
-	} else {			// USB_PR_CBI
-		struct interrupt_data	*buf = bh->buf;
-
-		/* Store and send the Interrupt data.  UFI sends the ASC
-		 * and ASCQ bytes.  Everything else sends a Type (which
-		 * is always 0) and the status Value. */
-		if (mod_data.protocol_type == USB_SC_UFI) {
-			buf->bType = ASC(sd);
-			buf->bValue = ASCQ(sd);
-		} else {
-			buf->bType = 0;
-			buf->bValue = status;
-		}
-		fsg->intreq->length = CBI_INTERRUPT_DATA_LEN;
-
-		fsg->intr_buffhd = bh;		// Point to the right buffhd
-		fsg->intreq->buf = bh->inreq->buf;
-		fsg->intreq->context = bh;
-		start_transfer(fsg, fsg->intr_in, fsg->intreq,
-				&fsg->intreq_busy, &bh->state);
-	}
-
-	fsg->next_buffhd_to_fill = bh->next;
-	return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Check whether the command is properly formed and whether its data size
- * and direction agree with the values we already have. */
-static int check_command(struct fsg_dev *fsg, int cmnd_size,
-		enum data_direction data_dir, unsigned int mask,
-		int needs_medium, const char *name)
-{
-	int			i;
-	int			lun = fsg->cmnd[1] >> 5;
-	static const char	dirletter[4] = {'u', 'o', 'i', 'n'};
-	char			hdlen[20];
-	struct fsg_lun		*curlun;
-
-	/* Adjust the expected cmnd_size for protocol encapsulation padding.
-	 * Transparent SCSI doesn't pad. */
-	if (protocol_is_scsi())
-		;
-
-	/* There's some disagreement as to whether RBC pads commands or not.
-	 * We'll play it safe and accept either form. */
-	else if (mod_data.protocol_type == USB_SC_RBC) {
-		if (fsg->cmnd_size == 12)
-			cmnd_size = 12;
-
-	/* All the other protocols pad to 12 bytes */
-	} else
-		cmnd_size = 12;
-
-	hdlen[0] = 0;
-	if (fsg->data_dir != DATA_DIR_UNKNOWN)
-		sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir],
-				fsg->data_size);
-	VDBG(fsg, "SCSI command: %s;  Dc=%d, D%c=%u;  Hc=%d%s\n",
-			name, cmnd_size, dirletter[(int) data_dir],
-			fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen);
-
-	/* We can't reply at all until we know the correct data direction
-	 * and size. */
-	if (fsg->data_size_from_cmnd == 0)
-		data_dir = DATA_DIR_NONE;
-	if (fsg->data_dir == DATA_DIR_UNKNOWN) {	// CB or CBI
-		fsg->data_dir = data_dir;
-		fsg->data_size = fsg->data_size_from_cmnd;
-
-	} else {					// Bulk-only
-		if (fsg->data_size < fsg->data_size_from_cmnd) {
-
-			/* Host data size < Device data size is a phase error.
-			 * Carry out the command, but only transfer as much
-			 * as we are allowed. */
-			fsg->data_size_from_cmnd = fsg->data_size;
-			fsg->phase_error = 1;
-		}
-	}
-	fsg->residue = fsg->usb_amount_left = fsg->data_size;
-
-	/* Conflicting data directions is a phase error */
-	if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) {
-		fsg->phase_error = 1;
-		return -EINVAL;
-	}
-
-	/* Verify the length of the command itself */
-	if (cmnd_size != fsg->cmnd_size) {
-
-		/* Special case workaround: There are plenty of buggy SCSI
-		 * implementations. Many have issues with cbw->Length
-		 * field passing a wrong command size. For those cases we
-		 * always try to work around the problem by using the length
-		 * sent by the host side provided it is at least as large
-		 * as the correct command length.
-		 * Examples of such cases would be MS-Windows, which issues
-		 * REQUEST SENSE with cbw->Length == 12 where it should
-		 * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and
-		 * REQUEST SENSE with cbw->Length == 10 where it should
-		 * be 6 as well.
-		 */
-		if (cmnd_size <= fsg->cmnd_size) {
-			DBG(fsg, "%s is buggy! Expected length %d "
-					"but we got %d\n", name,
-					cmnd_size, fsg->cmnd_size);
-			cmnd_size = fsg->cmnd_size;
-		} else {
-			fsg->phase_error = 1;
-			return -EINVAL;
-		}
-	}
-
-	/* Check that the LUN values are consistent */
-	if (transport_is_bbb()) {
-		if (fsg->lun != lun)
-			DBG(fsg, "using LUN %d from CBW, "
-					"not LUN %d from CDB\n",
-					fsg->lun, lun);
-	}
-
-	/* Check the LUN */
-	curlun = fsg->curlun;
-	if (curlun) {
-		if (fsg->cmnd[0] != REQUEST_SENSE) {
-			curlun->sense_data = SS_NO_SENSE;
-			curlun->sense_data_info = 0;
-			curlun->info_valid = 0;
-		}
-	} else {
-		fsg->bad_lun_okay = 0;
-
-		/* INQUIRY and REQUEST SENSE commands are explicitly allowed
-		 * to use unsupported LUNs; all others may not. */
-		if (fsg->cmnd[0] != INQUIRY &&
-				fsg->cmnd[0] != REQUEST_SENSE) {
-			DBG(fsg, "unsupported LUN %d\n", fsg->lun);
-			return -EINVAL;
-		}
-	}
-
-	/* If a unit attention condition exists, only INQUIRY and
-	 * REQUEST SENSE commands are allowed; anything else must fail. */
-	if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
-			fsg->cmnd[0] != INQUIRY &&
-			fsg->cmnd[0] != REQUEST_SENSE) {
-		curlun->sense_data = curlun->unit_attention_data;
-		curlun->unit_attention_data = SS_NO_SENSE;
-		return -EINVAL;
-	}
-
-	/* Check that only command bytes listed in the mask are non-zero */
-	fsg->cmnd[1] &= 0x1f;			// Mask away the LUN
-	for (i = 1; i < cmnd_size; ++i) {
-		if (fsg->cmnd[i] && !(mask & (1 << i))) {
-			if (curlun)
-				curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-			return -EINVAL;
-		}
-	}
-
-	/* If the medium isn't mounted and the command needs to access
-	 * it, return an error. */
-	if (curlun && !fsg_lun_is_open(curlun) && needs_medium) {
-		curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* wrapper of check_command for data size in blocks handling */
-static int check_command_size_in_blocks(struct fsg_dev *fsg, int cmnd_size,
-		enum data_direction data_dir, unsigned int mask,
-		int needs_medium, const char *name)
-{
-	if (fsg->curlun)
-		fsg->data_size_from_cmnd <<= fsg->curlun->blkbits;
-	return check_command(fsg, cmnd_size, data_dir,
-			mask, needs_medium, name);
-}
-
-static int do_scsi_command(struct fsg_dev *fsg)
-{
-	struct fsg_buffhd	*bh;
-	int			rc;
-	int			reply = -EINVAL;
-	int			i;
-	static char		unknown[16];
-
-	dump_cdb(fsg);
-
-	/* Wait for the next buffer to become available for data or status */
-	bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill;
-	while (bh->state != BUF_STATE_EMPTY) {
-		rc = sleep_thread(fsg);
-		if (rc)
-			return rc;
-	}
-	fsg->phase_error = 0;
-	fsg->short_packet_received = 0;
-
-	down_read(&fsg->filesem);	// We're using the backing file
-	switch (fsg->cmnd[0]) {
-
-	case INQUIRY:
-		fsg->data_size_from_cmnd = fsg->cmnd[4];
-		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
-				(1<<4), 0,
-				"INQUIRY")) == 0)
-			reply = do_inquiry(fsg, bh);
-		break;
-
-	case MODE_SELECT:
-		fsg->data_size_from_cmnd = fsg->cmnd[4];
-		if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
-				(1<<1) | (1<<4), 0,
-				"MODE SELECT(6)")) == 0)
-			reply = do_mode_select(fsg, bh);
-		break;
-
-	case MODE_SELECT_10:
-		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
-		if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
-				(1<<1) | (3<<7), 0,
-				"MODE SELECT(10)")) == 0)
-			reply = do_mode_select(fsg, bh);
-		break;
-
-	case MODE_SENSE:
-		fsg->data_size_from_cmnd = fsg->cmnd[4];
-		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
-				(1<<1) | (1<<2) | (1<<4), 0,
-				"MODE SENSE(6)")) == 0)
-			reply = do_mode_sense(fsg, bh);
-		break;
-
-	case MODE_SENSE_10:
-		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
-		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
-				(1<<1) | (1<<2) | (3<<7), 0,
-				"MODE SENSE(10)")) == 0)
-			reply = do_mode_sense(fsg, bh);
-		break;
-
-	case ALLOW_MEDIUM_REMOVAL:
-		fsg->data_size_from_cmnd = 0;
-		if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
-				(1<<4), 0,
-				"PREVENT-ALLOW MEDIUM REMOVAL")) == 0)
-			reply = do_prevent_allow(fsg);
-		break;
-
-	case READ_6:
-		i = fsg->cmnd[4];
-		fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
-		if ((reply = check_command_size_in_blocks(fsg, 6,
-				DATA_DIR_TO_HOST,
-				(7<<1) | (1<<4), 1,
-				"READ(6)")) == 0)
-			reply = do_read(fsg);
-		break;
-
-	case READ_10:
-		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
-		if ((reply = check_command_size_in_blocks(fsg, 10,
-				DATA_DIR_TO_HOST,
-				(1<<1) | (0xf<<2) | (3<<7), 1,
-				"READ(10)")) == 0)
-			reply = do_read(fsg);
-		break;
-
-	case READ_12:
-		fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
-		if ((reply = check_command_size_in_blocks(fsg, 12,
-				DATA_DIR_TO_HOST,
-				(1<<1) | (0xf<<2) | (0xf<<6), 1,
-				"READ(12)")) == 0)
-			reply = do_read(fsg);
-		break;
-
-	case READ_CAPACITY:
-		fsg->data_size_from_cmnd = 8;
-		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
-				(0xf<<2) | (1<<8), 1,
-				"READ CAPACITY")) == 0)
-			reply = do_read_capacity(fsg, bh);
-		break;
-
-	case READ_HEADER:
-		if (!mod_data.cdrom)
-			goto unknown_cmnd;
-		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
-		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
-				(3<<7) | (0x1f<<1), 1,
-				"READ HEADER")) == 0)
-			reply = do_read_header(fsg, bh);
-		break;
-
-	case READ_TOC:
-		if (!mod_data.cdrom)
-			goto unknown_cmnd;
-		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
-		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
-				(7<<6) | (1<<1), 1,
-				"READ TOC")) == 0)
-			reply = do_read_toc(fsg, bh);
-		break;
-
-	case READ_FORMAT_CAPACITIES:
-		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
-		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
-				(3<<7), 1,
-				"READ FORMAT CAPACITIES")) == 0)
-			reply = do_read_format_capacities(fsg, bh);
-		break;
-
-	case REQUEST_SENSE:
-		fsg->data_size_from_cmnd = fsg->cmnd[4];
-		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
-				(1<<4), 0,
-				"REQUEST SENSE")) == 0)
-			reply = do_request_sense(fsg, bh);
-		break;
-
-	case START_STOP:
-		fsg->data_size_from_cmnd = 0;
-		if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
-				(1<<1) | (1<<4), 0,
-				"START-STOP UNIT")) == 0)
-			reply = do_start_stop(fsg);
-		break;
-
-	case SYNCHRONIZE_CACHE:
-		fsg->data_size_from_cmnd = 0;
-		if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
-				(0xf<<2) | (3<<7), 1,
-				"SYNCHRONIZE CACHE")) == 0)
-			reply = do_synchronize_cache(fsg);
-		break;
-
-	case TEST_UNIT_READY:
-		fsg->data_size_from_cmnd = 0;
-		reply = check_command(fsg, 6, DATA_DIR_NONE,
-				0, 1,
-				"TEST UNIT READY");
-		break;
-
-	/* Although optional, this command is used by MS-Windows.  We
-	 * support a minimal version: BytChk must be 0. */
-	case VERIFY:
-		fsg->data_size_from_cmnd = 0;
-		if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
-				(1<<1) | (0xf<<2) | (3<<7), 1,
-				"VERIFY")) == 0)
-			reply = do_verify(fsg);
-		break;
-
-	case WRITE_6:
-		i = fsg->cmnd[4];
-		fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
-		if ((reply = check_command_size_in_blocks(fsg, 6,
-				DATA_DIR_FROM_HOST,
-				(7<<1) | (1<<4), 1,
-				"WRITE(6)")) == 0)
-			reply = do_write(fsg);
-		break;
-
-	case WRITE_10:
-		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
-		if ((reply = check_command_size_in_blocks(fsg, 10,
-				DATA_DIR_FROM_HOST,
-				(1<<1) | (0xf<<2) | (3<<7), 1,
-				"WRITE(10)")) == 0)
-			reply = do_write(fsg);
-		break;
-
-	case WRITE_12:
-		fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
-		if ((reply = check_command_size_in_blocks(fsg, 12,
-				DATA_DIR_FROM_HOST,
-				(1<<1) | (0xf<<2) | (0xf<<6), 1,
-				"WRITE(12)")) == 0)
-			reply = do_write(fsg);
-		break;
-
-	/* Some mandatory commands that we recognize but don't implement.
-	 * They don't mean much in this setting.  It's left as an exercise
-	 * for anyone interested to implement RESERVE and RELEASE in terms
-	 * of Posix locks. */
-	case FORMAT_UNIT:
-	case RELEASE:
-	case RESERVE:
-	case SEND_DIAGNOSTIC:
-		// Fall through
-
-	default:
- unknown_cmnd:
-		fsg->data_size_from_cmnd = 0;
-		sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
-		if ((reply = check_command(fsg, fsg->cmnd_size,
-				DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) {
-			fsg->curlun->sense_data = SS_INVALID_COMMAND;
-			reply = -EINVAL;
-		}
-		break;
-	}
-	up_read(&fsg->filesem);
-
-	if (reply == -EINTR || signal_pending(current))
-		return -EINTR;
-
-	/* Set up the single reply buffer for finish_reply() */
-	if (reply == -EINVAL)
-		reply = 0;		// Error reply length
-	if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) {
-		reply = min((u32) reply, fsg->data_size_from_cmnd);
-		bh->inreq->length = reply;
-		bh->state = BUF_STATE_FULL;
-		fsg->residue -= reply;
-	}				// Otherwise it's already set
-
-	return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-	struct usb_request		*req = bh->outreq;
-	struct bulk_cb_wrap	*cbw = req->buf;
-
-	/* Was this a real packet?  Should it be ignored? */
-	if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
-		return -EINVAL;
-
-	/* Is the CBW valid? */
-	if (req->actual != US_BULK_CB_WRAP_LEN ||
-			cbw->Signature != cpu_to_le32(
-				US_BULK_CB_SIGN)) {
-		DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
-				req->actual,
-				le32_to_cpu(cbw->Signature));
-
-		/* The Bulk-only spec says we MUST stall the IN endpoint
-		 * (6.6.1), so it's unavoidable.  It also says we must
-		 * retain this state until the next reset, but there's
-		 * no way to tell the controller driver it should ignore
-		 * Clear-Feature(HALT) requests.
-		 *
-		 * We aren't required to halt the OUT endpoint; instead
-		 * we can simply accept and discard any data received
-		 * until the next reset. */
-		wedge_bulk_in_endpoint(fsg);
-		set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
-		return -EINVAL;
-	}
-
-	/* Is the CBW meaningful? */
-	if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
-			cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
-		DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
-				"cmdlen %u\n",
-				cbw->Lun, cbw->Flags, cbw->Length);
-
-		/* We can do anything we want here, so let's stall the
-		 * bulk pipes if we are allowed to. */
-		if (mod_data.can_stall) {
-			fsg_set_halt(fsg, fsg->bulk_out);
-			halt_bulk_in_endpoint(fsg);
-		}
-		return -EINVAL;
-	}
-
-	/* Save the command for later */
-	fsg->cmnd_size = cbw->Length;
-	memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size);
-	if (cbw->Flags & US_BULK_FLAG_IN)
-		fsg->data_dir = DATA_DIR_TO_HOST;
-	else
-		fsg->data_dir = DATA_DIR_FROM_HOST;
-	fsg->data_size = le32_to_cpu(cbw->DataTransferLength);
-	if (fsg->data_size == 0)
-		fsg->data_dir = DATA_DIR_NONE;
-	fsg->lun = cbw->Lun;
-	fsg->tag = cbw->Tag;
-	return 0;
-}
-
-
-static int get_next_command(struct fsg_dev *fsg)
-{
-	struct fsg_buffhd	*bh;
-	int			rc = 0;
-
-	if (transport_is_bbb()) {
-
-		/* Wait for the next buffer to become available */
-		bh = fsg->next_buffhd_to_fill;
-		while (bh->state != BUF_STATE_EMPTY) {
-			rc = sleep_thread(fsg);
-			if (rc)
-				return rc;
-		}
-
-		/* Queue a request to read a Bulk-only CBW */
-		set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN);
-		start_transfer(fsg, fsg->bulk_out, bh->outreq,
-				&bh->outreq_busy, &bh->state);
-
-		/* We will drain the buffer in software, which means we
-		 * can reuse it for the next filling.  No need to advance
-		 * next_buffhd_to_fill. */
-
-		/* Wait for the CBW to arrive */
-		while (bh->state != BUF_STATE_FULL) {
-			rc = sleep_thread(fsg);
-			if (rc)
-				return rc;
-		}
-		smp_rmb();
-		rc = received_cbw(fsg, bh);
-		bh->state = BUF_STATE_EMPTY;
-
-	} else {		// USB_PR_CB or USB_PR_CBI
-
-		/* Wait for the next command to arrive */
-		while (fsg->cbbuf_cmnd_size == 0) {
-			rc = sleep_thread(fsg);
-			if (rc)
-				return rc;
-		}
-
-		/* Is the previous status interrupt request still busy?
-		 * The host is allowed to skip reading the status,
-		 * so we must cancel it. */
-		if (fsg->intreq_busy)
-			usb_ep_dequeue(fsg->intr_in, fsg->intreq);
-
-		/* Copy the command and mark the buffer empty */
-		fsg->data_dir = DATA_DIR_UNKNOWN;
-		spin_lock_irq(&fsg->lock);
-		fsg->cmnd_size = fsg->cbbuf_cmnd_size;
-		memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size);
-		fsg->cbbuf_cmnd_size = 0;
-		spin_unlock_irq(&fsg->lock);
-
-		/* Use LUN from the command */
-		fsg->lun = fsg->cmnd[1] >> 5;
-	}
-
-	/* Update current lun */
-	if (fsg->lun >= 0 && fsg->lun < fsg->nluns)
-		fsg->curlun = &fsg->luns[fsg->lun];
-	else
-		fsg->curlun = NULL;
-
-	return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep,
-		const struct usb_endpoint_descriptor *d)
-{
-	int	rc;
-
-	ep->driver_data = fsg;
-	ep->desc = d;
-	rc = usb_ep_enable(ep);
-	if (rc)
-		ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc);
-	return rc;
-}
-
-static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep,
-		struct usb_request **preq)
-{
-	*preq = usb_ep_alloc_request(ep, GFP_ATOMIC);
-	if (*preq)
-		return 0;
-	ERROR(fsg, "can't allocate request for %s\n", ep->name);
-	return -ENOMEM;
-}
-
-/*
- * Reset interface setting and re-init endpoint state (toggle etc).
- * Call with altsetting < 0 to disable the interface.  The only other
- * available altsetting is 0, which enables the interface.
- */
-static int do_set_interface(struct fsg_dev *fsg, int altsetting)
-{
-	int	rc = 0;
-	int	i;
-	const struct usb_endpoint_descriptor	*d;
-
-	if (fsg->running)
-		DBG(fsg, "reset interface\n");
-
-reset:
-	/* Deallocate the requests */
-	for (i = 0; i < fsg_num_buffers; ++i) {
-		struct fsg_buffhd *bh = &fsg->buffhds[i];
-
-		if (bh->inreq) {
-			usb_ep_free_request(fsg->bulk_in, bh->inreq);
-			bh->inreq = NULL;
-		}
-		if (bh->outreq) {
-			usb_ep_free_request(fsg->bulk_out, bh->outreq);
-			bh->outreq = NULL;
-		}
-	}
-	if (fsg->intreq) {
-		usb_ep_free_request(fsg->intr_in, fsg->intreq);
-		fsg->intreq = NULL;
-	}
-
-	/* Disable the endpoints */
-	if (fsg->bulk_in_enabled) {
-		usb_ep_disable(fsg->bulk_in);
-		fsg->bulk_in_enabled = 0;
-	}
-	if (fsg->bulk_out_enabled) {
-		usb_ep_disable(fsg->bulk_out);
-		fsg->bulk_out_enabled = 0;
-	}
-	if (fsg->intr_in_enabled) {
-		usb_ep_disable(fsg->intr_in);
-		fsg->intr_in_enabled = 0;
-	}
-
-	fsg->running = 0;
-	if (altsetting < 0 || rc != 0)
-		return rc;
-
-	DBG(fsg, "set interface %d\n", altsetting);
-
-	/* Enable the endpoints */
-	d = fsg_ep_desc(fsg->gadget,
-			&fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc,
-			&fsg_ss_bulk_in_desc);
-	if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0)
-		goto reset;
-	fsg->bulk_in_enabled = 1;
-
-	d = fsg_ep_desc(fsg->gadget,
-			&fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc,
-			&fsg_ss_bulk_out_desc);
-	if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0)
-		goto reset;
-	fsg->bulk_out_enabled = 1;
-	fsg->bulk_out_maxpacket = usb_endpoint_maxp(d);
-	clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
-
-	if (transport_is_cbi()) {
-		d = fsg_ep_desc(fsg->gadget,
-				&fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc,
-				&fsg_ss_intr_in_desc);
-		if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0)
-			goto reset;
-		fsg->intr_in_enabled = 1;
-	}
-
-	/* Allocate the requests */
-	for (i = 0; i < fsg_num_buffers; ++i) {
-		struct fsg_buffhd	*bh = &fsg->buffhds[i];
-
-		if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0)
-			goto reset;
-		if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)
-			goto reset;
-		bh->inreq->buf = bh->outreq->buf = bh->buf;
-		bh->inreq->context = bh->outreq->context = bh;
-		bh->inreq->complete = bulk_in_complete;
-		bh->outreq->complete = bulk_out_complete;
-	}
-	if (transport_is_cbi()) {
-		if ((rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq)) != 0)
-			goto reset;
-		fsg->intreq->complete = intr_in_complete;
-	}
-
-	fsg->running = 1;
-	for (i = 0; i < fsg->nluns; ++i)
-		fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
-	return rc;
-}
-
-
-/*
- * Change our operational configuration.  This code must agree with the code
- * that returns config descriptors, and with interface altsetting code.
- *
- * It's also responsible for power management interactions.  Some
- * configurations might not work with our current power sources.
- * For now we just assume the gadget is always self-powered.
- */
-static int do_set_config(struct fsg_dev *fsg, u8 new_config)
-{
-	int	rc = 0;
-
-	/* Disable the single interface */
-	if (fsg->config != 0) {
-		DBG(fsg, "reset config\n");
-		fsg->config = 0;
-		rc = do_set_interface(fsg, -1);
-	}
-
-	/* Enable the interface */
-	if (new_config != 0) {
-		fsg->config = new_config;
-		if ((rc = do_set_interface(fsg, 0)) != 0)
-			fsg->config = 0;	// Reset on errors
-		else
-			INFO(fsg, "%s config #%d\n",
-			     usb_speed_string(fsg->gadget->speed),
-			     fsg->config);
-	}
-	return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void handle_exception(struct fsg_dev *fsg)
-{
-	siginfo_t		info;
-	int			sig;
-	int			i;
-	int			num_active;
-	struct fsg_buffhd	*bh;
-	enum fsg_state		old_state;
-	u8			new_config;
-	struct fsg_lun		*curlun;
-	unsigned int		exception_req_tag;
-	int			rc;
-
-	/* Clear the existing signals.  Anything but SIGUSR1 is converted
-	 * into a high-priority EXIT exception. */
-	for (;;) {
-		sig = dequeue_signal_lock(current, &current->blocked, &info);
-		if (!sig)
-			break;
-		if (sig != SIGUSR1) {
-			if (fsg->state < FSG_STATE_EXIT)
-				DBG(fsg, "Main thread exiting on signal\n");
-			raise_exception(fsg, FSG_STATE_EXIT);
-		}
-	}
-
-	/* Cancel all the pending transfers */
-	if (fsg->intreq_busy)
-		usb_ep_dequeue(fsg->intr_in, fsg->intreq);
-	for (i = 0; i < fsg_num_buffers; ++i) {
-		bh = &fsg->buffhds[i];
-		if (bh->inreq_busy)
-			usb_ep_dequeue(fsg->bulk_in, bh->inreq);
-		if (bh->outreq_busy)
-			usb_ep_dequeue(fsg->bulk_out, bh->outreq);
-	}
-
-	/* Wait until everything is idle */
-	for (;;) {
-		num_active = fsg->intreq_busy;
-		for (i = 0; i < fsg_num_buffers; ++i) {
-			bh = &fsg->buffhds[i];
-			num_active += bh->inreq_busy + bh->outreq_busy;
-		}
-		if (num_active == 0)
-			break;
-		if (sleep_thread(fsg))
-			return;
-	}
-
-	/* Clear out the controller's fifos */
-	if (fsg->bulk_in_enabled)
-		usb_ep_fifo_flush(fsg->bulk_in);
-	if (fsg->bulk_out_enabled)
-		usb_ep_fifo_flush(fsg->bulk_out);
-	if (fsg->intr_in_enabled)
-		usb_ep_fifo_flush(fsg->intr_in);
-
-	/* Reset the I/O buffer states and pointers, the SCSI
-	 * state, and the exception.  Then invoke the handler. */
-	spin_lock_irq(&fsg->lock);
-
-	for (i = 0; i < fsg_num_buffers; ++i) {
-		bh = &fsg->buffhds[i];
-		bh->state = BUF_STATE_EMPTY;
-	}
-	fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain =
-			&fsg->buffhds[0];
-
-	exception_req_tag = fsg->exception_req_tag;
-	new_config = fsg->new_config;
-	old_state = fsg->state;
-
-	if (old_state == FSG_STATE_ABORT_BULK_OUT)
-		fsg->state = FSG_STATE_STATUS_PHASE;
-	else {
-		for (i = 0; i < fsg->nluns; ++i) {
-			curlun = &fsg->luns[i];
-			curlun->prevent_medium_removal = 0;
-			curlun->sense_data = curlun->unit_attention_data =
-					SS_NO_SENSE;
-			curlun->sense_data_info = 0;
-			curlun->info_valid = 0;
-		}
-		fsg->state = FSG_STATE_IDLE;
-	}
-	spin_unlock_irq(&fsg->lock);
-
-	/* Carry out any extra actions required for the exception */
-	switch (old_state) {
-	default:
-		break;
-
-	case FSG_STATE_ABORT_BULK_OUT:
-		send_status(fsg);
-		spin_lock_irq(&fsg->lock);
-		if (fsg->state == FSG_STATE_STATUS_PHASE)
-			fsg->state = FSG_STATE_IDLE;
-		spin_unlock_irq(&fsg->lock);
-		break;
-
-	case FSG_STATE_RESET:
-		/* In case we were forced against our will to halt a
-		 * bulk endpoint, clear the halt now.  (The SuperH UDC
-		 * requires this.) */
-		if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
-			usb_ep_clear_halt(fsg->bulk_in);
-
-		if (transport_is_bbb()) {
-			if (fsg->ep0_req_tag == exception_req_tag)
-				ep0_queue(fsg);	// Complete the status stage
-
-		} else if (transport_is_cbi())
-			send_status(fsg);	// Status by interrupt pipe
-
-		/* Technically this should go here, but it would only be
-		 * a waste of time.  Ditto for the INTERFACE_CHANGE and
-		 * CONFIG_CHANGE cases. */
-		// for (i = 0; i < fsg->nluns; ++i)
-		//	fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
-		break;
-
-	case FSG_STATE_INTERFACE_CHANGE:
-		rc = do_set_interface(fsg, 0);
-		if (fsg->ep0_req_tag != exception_req_tag)
-			break;
-		if (rc != 0)			// STALL on errors
-			fsg_set_halt(fsg, fsg->ep0);
-		else				// Complete the status stage
-			ep0_queue(fsg);
-		break;
-
-	case FSG_STATE_CONFIG_CHANGE:
-		rc = do_set_config(fsg, new_config);
-		if (fsg->ep0_req_tag != exception_req_tag)
-			break;
-		if (rc != 0)			// STALL on errors
-			fsg_set_halt(fsg, fsg->ep0);
-		else				// Complete the status stage
-			ep0_queue(fsg);
-		break;
-
-	case FSG_STATE_DISCONNECT:
-		for (i = 0; i < fsg->nluns; ++i)
-			fsg_lun_fsync_sub(fsg->luns + i);
-		do_set_config(fsg, 0);		// Unconfigured state
-		break;
-
-	case FSG_STATE_EXIT:
-	case FSG_STATE_TERMINATED:
-		do_set_config(fsg, 0);			// Free resources
-		spin_lock_irq(&fsg->lock);
-		fsg->state = FSG_STATE_TERMINATED;	// Stop the thread
-		spin_unlock_irq(&fsg->lock);
-		break;
-	}
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int fsg_main_thread(void *fsg_)
-{
-	struct fsg_dev		*fsg = fsg_;
-
-	/* Allow the thread to be killed by a signal, but set the signal mask
-	 * to block everything but INT, TERM, KILL, and USR1. */
-	allow_signal(SIGINT);
-	allow_signal(SIGTERM);
-	allow_signal(SIGKILL);
-	allow_signal(SIGUSR1);
-
-	/* Allow the thread to be frozen */
-	set_freezable();
-
-	/* Arrange for userspace references to be interpreted as kernel
-	 * pointers.  That way we can pass a kernel pointer to a routine
-	 * that expects a __user pointer and it will work okay. */
-	set_fs(get_ds());
-
-	/* The main loop */
-	while (fsg->state != FSG_STATE_TERMINATED) {
-		if (exception_in_progress(fsg) || signal_pending(current)) {
-			handle_exception(fsg);
-			continue;
-		}
-
-		if (!fsg->running) {
-			sleep_thread(fsg);
-			continue;
-		}
-
-		if (get_next_command(fsg))
-			continue;
-
-		spin_lock_irq(&fsg->lock);
-		if (!exception_in_progress(fsg))
-			fsg->state = FSG_STATE_DATA_PHASE;
-		spin_unlock_irq(&fsg->lock);
-
-		if (do_scsi_command(fsg) || finish_reply(fsg))
-			continue;
-
-		spin_lock_irq(&fsg->lock);
-		if (!exception_in_progress(fsg))
-			fsg->state = FSG_STATE_STATUS_PHASE;
-		spin_unlock_irq(&fsg->lock);
-
-		if (send_status(fsg))
-			continue;
-
-		spin_lock_irq(&fsg->lock);
-		if (!exception_in_progress(fsg))
-			fsg->state = FSG_STATE_IDLE;
-		spin_unlock_irq(&fsg->lock);
-		}
-
-	spin_lock_irq(&fsg->lock);
-	fsg->thread_task = NULL;
-	spin_unlock_irq(&fsg->lock);
-
-	/* If we are exiting because of a signal, unregister the
-	 * gadget driver. */
-	if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
-		usb_gadget_unregister_driver(&fsg_driver);
-
-	/* Let the unbind and cleanup routines know the thread has exited */
-	complete_and_exit(&fsg->thread_notifier, 0);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-
-/* The write permissions and store_xxx pointers are set in fsg_bind() */
-static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL);
-static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL);
-static DEVICE_ATTR(file, 0444, fsg_show_file, NULL);
-
-
-/*-------------------------------------------------------------------------*/
-
-static void fsg_release(struct kref *ref)
-{
-	struct fsg_dev	*fsg = container_of(ref, struct fsg_dev, ref);
-
-	kfree(fsg->luns);
-	kfree(fsg);
-}
-
-static void lun_release(struct device *dev)
-{
-	struct rw_semaphore	*filesem = dev_get_drvdata(dev);
-	struct fsg_dev		*fsg =
-		container_of(filesem, struct fsg_dev, filesem);
-
-	kref_put(&fsg->ref, fsg_release);
-}
-
-static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
-{
-	struct fsg_dev		*fsg = get_gadget_data(gadget);
-	int			i;
-	struct fsg_lun		*curlun;
-	struct usb_request	*req = fsg->ep0req;
-
-	DBG(fsg, "unbind\n");
-	clear_bit(REGISTERED, &fsg->atomic_bitflags);
-
-	/* If the thread isn't already dead, tell it to exit now */
-	if (fsg->state != FSG_STATE_TERMINATED) {
-		raise_exception(fsg, FSG_STATE_EXIT);
-		wait_for_completion(&fsg->thread_notifier);
-
-		/* The cleanup routine waits for this completion also */
-		complete(&fsg->thread_notifier);
-	}
-
-	/* Unregister the sysfs attribute files and the LUNs */
-	for (i = 0; i < fsg->nluns; ++i) {
-		curlun = &fsg->luns[i];
-		if (curlun->registered) {
-			device_remove_file(&curlun->dev, &dev_attr_nofua);
-			device_remove_file(&curlun->dev, &dev_attr_ro);
-			device_remove_file(&curlun->dev, &dev_attr_file);
-			fsg_lun_close(curlun);
-			device_unregister(&curlun->dev);
-			curlun->registered = 0;
-		}
-	}
-
-	/* Free the data buffers */
-	for (i = 0; i < fsg_num_buffers; ++i)
-		kfree(fsg->buffhds[i].buf);
-
-	/* Free the request and buffer for endpoint 0 */
-	if (req) {
-		kfree(req->buf);
-		usb_ep_free_request(fsg->ep0, req);
-	}
-
-	set_gadget_data(gadget, NULL);
-}
-
-
-static int __init check_parameters(struct fsg_dev *fsg)
-{
-	int	prot;
-
-	/* Store the default values */
-	mod_data.transport_type = USB_PR_BULK;
-	mod_data.transport_name = "Bulk-only";
-	mod_data.protocol_type = USB_SC_SCSI;
-	mod_data.protocol_name = "Transparent SCSI";
-
-	/* Some peripheral controllers are known not to be able to
-	 * halt bulk endpoints correctly.  If one of them is present,
-	 * disable stalls.
-	 */
-	if (gadget_is_at91(fsg->gadget))
-		mod_data.can_stall = 0;
-
-	if (mod_data.release == 0xffff)
-		mod_data.release = get_default_bcdDevice();
-
-	prot = simple_strtol(mod_data.protocol_parm, NULL, 0);
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-	if (strnicmp(mod_data.transport_parm, "BBB", 10) == 0) {
-		;		// Use default setting
-	} else if (strnicmp(mod_data.transport_parm, "CB", 10) == 0) {
-		mod_data.transport_type = USB_PR_CB;
-		mod_data.transport_name = "Control-Bulk";
-	} else if (strnicmp(mod_data.transport_parm, "CBI", 10) == 0) {
-		mod_data.transport_type = USB_PR_CBI;
-		mod_data.transport_name = "Control-Bulk-Interrupt";
-	} else {
-		ERROR(fsg, "invalid transport: %s\n", mod_data.transport_parm);
-		return -EINVAL;
-	}
-
-	if (strnicmp(mod_data.protocol_parm, "SCSI", 10) == 0 ||
-			prot == USB_SC_SCSI) {
-		;		// Use default setting
-	} else if (strnicmp(mod_data.protocol_parm, "RBC", 10) == 0 ||
-			prot == USB_SC_RBC) {
-		mod_data.protocol_type = USB_SC_RBC;
-		mod_data.protocol_name = "RBC";
-	} else if (strnicmp(mod_data.protocol_parm, "8020", 4) == 0 ||
-			strnicmp(mod_data.protocol_parm, "ATAPI", 10) == 0 ||
-			prot == USB_SC_8020) {
-		mod_data.protocol_type = USB_SC_8020;
-		mod_data.protocol_name = "8020i (ATAPI)";
-	} else if (strnicmp(mod_data.protocol_parm, "QIC", 3) == 0 ||
-			prot == USB_SC_QIC) {
-		mod_data.protocol_type = USB_SC_QIC;
-		mod_data.protocol_name = "QIC-157";
-	} else if (strnicmp(mod_data.protocol_parm, "UFI", 10) == 0 ||
-			prot == USB_SC_UFI) {
-		mod_data.protocol_type = USB_SC_UFI;
-		mod_data.protocol_name = "UFI";
-	} else if (strnicmp(mod_data.protocol_parm, "8070", 4) == 0 ||
-			prot == USB_SC_8070) {
-		mod_data.protocol_type = USB_SC_8070;
-		mod_data.protocol_name = "8070i";
-	} else {
-		ERROR(fsg, "invalid protocol: %s\n", mod_data.protocol_parm);
-		return -EINVAL;
-	}
-
-	mod_data.buflen &= PAGE_CACHE_MASK;
-	if (mod_data.buflen <= 0) {
-		ERROR(fsg, "invalid buflen\n");
-		return -ETOOSMALL;
-	}
-
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-	/* Serial string handling.
-	 * On a real device, the serial string would be loaded
-	 * from permanent storage. */
-	if (mod_data.serial) {
-		const char *ch;
-		unsigned len = 0;
-
-		/* Sanity check :
-		 * The CB[I] specification limits the serial string to
-		 * 12 uppercase hexadecimal characters.
-		 * BBB need at least 12 uppercase hexadecimal characters,
-		 * with a maximum of 126. */
-		for (ch = mod_data.serial; *ch; ++ch) {
-			++len;
-			if ((*ch < '0' || *ch > '9') &&
-			    (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */
-				WARNING(fsg,
-					"Invalid serial string character: %c\n",
-					*ch);
-				goto no_serial;
-			}
-		}
-		if (len > 126 ||
-		    (mod_data.transport_type == USB_PR_BULK && len < 12) ||
-		    (mod_data.transport_type != USB_PR_BULK && len > 12)) {
-			WARNING(fsg, "Invalid serial string length!\n");
-			goto no_serial;
-		}
-		fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial;
-	} else {
-		WARNING(fsg, "No serial-number string provided!\n");
- no_serial:
-		device_desc.iSerialNumber = 0;
-	}
-
-	return 0;
-}
-
-
-static int __init fsg_bind(struct usb_gadget *gadget,
-		struct usb_gadget_driver *driver)
-{
-	struct fsg_dev		*fsg = the_fsg;
-	int			rc;
-	int			i;
-	struct fsg_lun		*curlun;
-	struct usb_ep		*ep;
-	struct usb_request	*req;
-	char			*pathbuf, *p;
-
-	fsg->gadget = gadget;
-	set_gadget_data(gadget, fsg);
-	fsg->ep0 = gadget->ep0;
-	fsg->ep0->driver_data = fsg;
-
-	if ((rc = check_parameters(fsg)) != 0)
-		goto out;
-
-	if (mod_data.removable) {	// Enable the store_xxx attributes
-		dev_attr_file.attr.mode = 0644;
-		dev_attr_file.store = fsg_store_file;
-		if (!mod_data.cdrom) {
-			dev_attr_ro.attr.mode = 0644;
-			dev_attr_ro.store = fsg_store_ro;
-		}
-	}
-
-	/* Only for removable media? */
-	dev_attr_nofua.attr.mode = 0644;
-	dev_attr_nofua.store = fsg_store_nofua;
-
-	/* Find out how many LUNs there should be */
-	i = mod_data.nluns;
-	if (i == 0)
-		i = max(mod_data.num_filenames, 1u);
-	if (i > FSG_MAX_LUNS) {
-		ERROR(fsg, "invalid number of LUNs: %d\n", i);
-		rc = -EINVAL;
-		goto out;
-	}
-
-	/* Create the LUNs, open their backing files, and register the
-	 * LUN devices in sysfs. */
-	fsg->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL);
-	if (!fsg->luns) {
-		rc = -ENOMEM;
-		goto out;
-	}
-	fsg->nluns = i;
-
-	for (i = 0; i < fsg->nluns; ++i) {
-		curlun = &fsg->luns[i];
-		curlun->cdrom = !!mod_data.cdrom;
-		curlun->ro = mod_data.cdrom || mod_data.ro[i];
-		curlun->initially_ro = curlun->ro;
-		curlun->removable = mod_data.removable;
-		curlun->nofua = mod_data.nofua[i];
-		curlun->dev.release = lun_release;
-		curlun->dev.parent = &gadget->dev;
-		curlun->dev.driver = &fsg_driver.driver;
-		dev_set_drvdata(&curlun->dev, &fsg->filesem);
-		dev_set_name(&curlun->dev,"%s-lun%d",
-			     dev_name(&gadget->dev), i);
-
-		kref_get(&fsg->ref);
-		rc = device_register(&curlun->dev);
-		if (rc) {
-			INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
-			put_device(&curlun->dev);
-			goto out;
-		}
-		curlun->registered = 1;
-
-		rc = device_create_file(&curlun->dev, &dev_attr_ro);
-		if (rc)
-			goto out;
-		rc = device_create_file(&curlun->dev, &dev_attr_nofua);
-		if (rc)
-			goto out;
-		rc = device_create_file(&curlun->dev, &dev_attr_file);
-		if (rc)
-			goto out;
-
-		if (mod_data.file[i] && *mod_data.file[i]) {
-			rc = fsg_lun_open(curlun, mod_data.file[i]);
-			if (rc)
-				goto out;
-		} else if (!mod_data.removable) {
-			ERROR(fsg, "no file given for LUN%d\n", i);
-			rc = -EINVAL;
-			goto out;
-		}
-	}
-
-	/* Find all the endpoints we will use */
-	usb_ep_autoconfig_reset(gadget);
-	ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc);
-	if (!ep)
-		goto autoconf_fail;
-	ep->driver_data = fsg;		// claim the endpoint
-	fsg->bulk_in = ep;
-
-	ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc);
-	if (!ep)
-		goto autoconf_fail;
-	ep->driver_data = fsg;		// claim the endpoint
-	fsg->bulk_out = ep;
-
-	if (transport_is_cbi()) {
-		ep = usb_ep_autoconfig(gadget, &fsg_fs_intr_in_desc);
-		if (!ep)
-			goto autoconf_fail;
-		ep->driver_data = fsg;		// claim the endpoint
-		fsg->intr_in = ep;
-	}
-
-	/* Fix up the descriptors */
-	device_desc.idVendor = cpu_to_le16(mod_data.vendor);
-	device_desc.idProduct = cpu_to_le16(mod_data.product);
-	device_desc.bcdDevice = cpu_to_le16(mod_data.release);
-
-	i = (transport_is_cbi() ? 3 : 2);	// Number of endpoints
-	fsg_intf_desc.bNumEndpoints = i;
-	fsg_intf_desc.bInterfaceSubClass = mod_data.protocol_type;
-	fsg_intf_desc.bInterfaceProtocol = mod_data.transport_type;
-	fsg_fs_function[i + FSG_FS_FUNCTION_PRE_EP_ENTRIES] = NULL;
-
-	if (gadget_is_dualspeed(gadget)) {
-		fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL;
-
-		/* Assume endpoint addresses are the same for both speeds */
-		fsg_hs_bulk_in_desc.bEndpointAddress =
-			fsg_fs_bulk_in_desc.bEndpointAddress;
-		fsg_hs_bulk_out_desc.bEndpointAddress =
-			fsg_fs_bulk_out_desc.bEndpointAddress;
-		fsg_hs_intr_in_desc.bEndpointAddress =
-			fsg_fs_intr_in_desc.bEndpointAddress;
-	}
-
-	if (gadget_is_superspeed(gadget)) {
-		unsigned		max_burst;
-
-		fsg_ss_function[i + FSG_SS_FUNCTION_PRE_EP_ENTRIES] = NULL;
-
-		/* Calculate bMaxBurst, we know packet size is 1024 */
-		max_burst = min_t(unsigned, mod_data.buflen / 1024, 15);
-
-		/* Assume endpoint addresses are the same for both speeds */
-		fsg_ss_bulk_in_desc.bEndpointAddress =
-			fsg_fs_bulk_in_desc.bEndpointAddress;
-		fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
-
-		fsg_ss_bulk_out_desc.bEndpointAddress =
-			fsg_fs_bulk_out_desc.bEndpointAddress;
-		fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
-	}
-
-	if (gadget_is_otg(gadget))
-		fsg_otg_desc.bmAttributes |= USB_OTG_HNP;
-
-	rc = -ENOMEM;
-
-	/* Allocate the request and buffer for endpoint 0 */
-	fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
-	if (!req)
-		goto out;
-	req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL);
-	if (!req->buf)
-		goto out;
-	req->complete = ep0_complete;
-
-	/* Allocate the data buffers */
-	for (i = 0; i < fsg_num_buffers; ++i) {
-		struct fsg_buffhd	*bh = &fsg->buffhds[i];
-
-		/* Allocate for the bulk-in endpoint.  We assume that
-		 * the buffer will also work with the bulk-out (and
-		 * interrupt-in) endpoint. */
-		bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL);
-		if (!bh->buf)
-			goto out;
-		bh->next = bh + 1;
-	}
-	fsg->buffhds[fsg_num_buffers - 1].next = &fsg->buffhds[0];
-
-	/* This should reflect the actual gadget power source */
-	usb_gadget_set_selfpowered(gadget);
-
-	snprintf(fsg_string_manufacturer, sizeof fsg_string_manufacturer,
-			"%s %s with %s",
-			init_utsname()->sysname, init_utsname()->release,
-			gadget->name);
-
-	fsg->thread_task = kthread_create(fsg_main_thread, fsg,
-			"file-storage-gadget");
-	if (IS_ERR(fsg->thread_task)) {
-		rc = PTR_ERR(fsg->thread_task);
-		goto out;
-	}
-
-	INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
-	INFO(fsg, "NOTE: This driver is deprecated.  "
-			"Consider using g_mass_storage instead.\n");
-	INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
-
-	pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
-	for (i = 0; i < fsg->nluns; ++i) {
-		curlun = &fsg->luns[i];
-		if (fsg_lun_is_open(curlun)) {
-			p = NULL;
-			if (pathbuf) {
-				p = d_path(&curlun->filp->f_path,
-					   pathbuf, PATH_MAX);
-				if (IS_ERR(p))
-					p = NULL;
-			}
-			LINFO(curlun, "ro=%d, nofua=%d, file: %s\n",
-			      curlun->ro, curlun->nofua, (p ? p : "(error)"));
-		}
-	}
-	kfree(pathbuf);
-
-	DBG(fsg, "transport=%s (x%02x)\n",
-			mod_data.transport_name, mod_data.transport_type);
-	DBG(fsg, "protocol=%s (x%02x)\n",
-			mod_data.protocol_name, mod_data.protocol_type);
-	DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n",
-			mod_data.vendor, mod_data.product, mod_data.release);
-	DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n",
-			mod_data.removable, mod_data.can_stall,
-			mod_data.cdrom, mod_data.buflen);
-	DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task));
-
-	set_bit(REGISTERED, &fsg->atomic_bitflags);
-
-	/* Tell the thread to start working */
-	wake_up_process(fsg->thread_task);
-	return 0;
-
-autoconf_fail:
-	ERROR(fsg, "unable to autoconfigure all endpoints\n");
-	rc = -ENOTSUPP;
-
-out:
-	fsg->state = FSG_STATE_TERMINATED;	// The thread is dead
-	fsg_unbind(gadget);
-	complete(&fsg->thread_notifier);
-	return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void fsg_suspend(struct usb_gadget *gadget)
-{
-	struct fsg_dev		*fsg = get_gadget_data(gadget);
-
-	DBG(fsg, "suspend\n");
-	set_bit(SUSPENDED, &fsg->atomic_bitflags);
-}
-
-static void fsg_resume(struct usb_gadget *gadget)
-{
-	struct fsg_dev		*fsg = get_gadget_data(gadget);
-
-	DBG(fsg, "resume\n");
-	clear_bit(SUSPENDED, &fsg->atomic_bitflags);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static __refdata struct usb_gadget_driver		fsg_driver = {
-	.max_speed	= USB_SPEED_SUPER,
-	.function	= (char *) fsg_string_product,
-	.bind		= fsg_bind,
-	.unbind		= fsg_unbind,
-	.disconnect	= fsg_disconnect,
-	.setup		= fsg_setup,
-	.suspend	= fsg_suspend,
-	.resume		= fsg_resume,
-
-	.driver		= {
-		.name		= DRIVER_NAME,
-		.owner		= THIS_MODULE,
-		// .release = ...
-		// .suspend = ...
-		// .resume = ...
-	},
-};
-
-
-static int __init fsg_alloc(void)
-{
-	struct fsg_dev		*fsg;
-
-	fsg = kzalloc(sizeof *fsg +
-		      fsg_num_buffers * sizeof *(fsg->buffhds), GFP_KERNEL);
-
-	if (!fsg)
-		return -ENOMEM;
-	spin_lock_init(&fsg->lock);
-	init_rwsem(&fsg->filesem);
-	kref_init(&fsg->ref);
-	init_completion(&fsg->thread_notifier);
-
-	the_fsg = fsg;
-	return 0;
-}
-
-
-static int __init fsg_init(void)
-{
-	int		rc;
-	struct fsg_dev	*fsg;
-
-	rc = fsg_num_buffers_validate();
-	if (rc != 0)
-		return rc;
-
-	if ((rc = fsg_alloc()) != 0)
-		return rc;
-	fsg = the_fsg;
-	rc = usb_gadget_probe_driver(&fsg_driver);
-	if (rc != 0)
-		kref_put(&fsg->ref, fsg_release);
-	return rc;
-}
-module_init(fsg_init);
-
-
-static void __exit fsg_cleanup(void)
-{
-	struct fsg_dev	*fsg = the_fsg;
-
-	/* Unregister the driver iff the thread hasn't already done so */
-	if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
-		usb_gadget_unregister_driver(&fsg_driver);
-
-	/* Wait for the thread to finish up */
-	wait_for_completion(&fsg->thread_notifier);
-
-	kref_put(&fsg->ref, fsg_release);
-}
-module_exit(fsg_cleanup);
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index b09452d..ec50f18 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -2347,7 +2347,7 @@ static int fsl_qe_stop(struct usb_gadget *gadget,
 }
 
 /* udc structure's alloc and setup, include ep-param alloc */
-static struct qe_udc __devinit *qe_udc_config(struct platform_device *ofdev)
+static struct qe_udc *qe_udc_config(struct platform_device *ofdev)
 {
 	struct qe_udc *udc;
 	struct device_node *np = ofdev->dev.of_node;
@@ -2402,7 +2402,7 @@ cleanup:
 }
 
 /* USB Controller register init */
-static int __devinit qe_udc_reg_init(struct qe_udc *udc)
+static int qe_udc_reg_init(struct qe_udc *udc)
 {
 	struct usb_ctlr __iomem *qe_usbregs;
 	qe_usbregs = udc->usb_regs;
@@ -2420,7 +2420,7 @@ static int __devinit qe_udc_reg_init(struct qe_udc *udc)
 	return 0;
 }
 
-static int __devinit qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
+static int qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
 {
 	struct qe_ep *ep = &udc->eps[pipe_num];
 
@@ -2473,7 +2473,7 @@ static void qe_udc_release(struct device *dev)
 
 /* Driver probe functions */
 static const struct of_device_id qe_udc_match[];
-static int __devinit qe_udc_probe(struct platform_device *ofdev)
+static int qe_udc_probe(struct platform_device *ofdev)
 {
 	struct qe_udc *udc;
 	const struct of_device_id *match;
@@ -2651,7 +2651,7 @@ static int qe_udc_resume(struct platform_device *dev)
 }
 #endif
 
-static int __devexit qe_udc_remove(struct platform_device *ofdev)
+static int qe_udc_remove(struct platform_device *ofdev)
 {
 	struct qe_udc *udc = dev_get_drvdata(&ofdev->dev);
 	struct qe_ep *ep;
@@ -2710,7 +2710,7 @@ static int __devexit qe_udc_remove(struct platform_device *ofdev)
 }
 
 /*-------------------------------------------------------------------------*/
-static const struct of_device_id qe_udc_match[] __devinitconst = {
+static const struct of_device_id qe_udc_match[] = {
 	{
 		.compatible = "fsl,mpc8323-qe-usb",
 		.data = (void *)PORT_QE,
@@ -2735,7 +2735,7 @@ static struct platform_driver udc_driver = {
 		.of_match_table = qe_udc_match,
 	},
 	.probe          = qe_udc_probe,
-	.remove         = __devexit_p(qe_udc_remove),
+	.remove         = qe_udc_remove,
 #ifdef CONFIG_PM
 	.suspend        = qe_udc_suspend,
 	.resume         = qe_udc_resume,
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 6ae70cb..c19f7f1 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -2126,7 +2126,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
 
 	tmp_reg = fsl_readl(&dr_regs->usbintr);
 	t = scnprintf(next, size,
-			"USB Intrrupt Enable Reg:\n"
+			"USB Interrupt Enable Reg:\n"
 			"Sleep Enable: %d SOF Received Enable: %d "
 			"Reset Enable: %d\n"
 			"System Error Enable: %d "
diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c
index 74130f6..c36260ea 100644
--- a/drivers/usb/gadget/hid.c
+++ b/drivers/usb/gadget/hid.c
@@ -203,7 +203,7 @@ static int __init hidg_plat_driver_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit hidg_plat_driver_remove(struct platform_device *pdev)
+static int hidg_plat_driver_remove(struct platform_device *pdev)
 {
 	struct hidg_func_node *e, *n;
 
@@ -229,7 +229,7 @@ static __refdata struct usb_composite_driver hidg_driver = {
 };
 
 static struct platform_driver hidg_plat_driver = {
-	.remove		= __devexit_p(hidg_plat_driver_remove),
+	.remove		= hidg_plat_driver_remove,
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= "hidg",
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 76494ca..8ac840f 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -76,7 +76,6 @@ MODULE_LICENSE ("GPL");
 /*----------------------------------------------------------------------*/
 
 #define GADGETFS_MAGIC		0xaee71ee7
-#define DMA_ADDR_INVALID	(~(dma_addr_t)0)
 
 /* /dev/gadget/$CHIP represents ep0 and the whole device */
 enum ep0_state {
@@ -918,7 +917,6 @@ static void clean_req (struct usb_ep *ep, struct usb_request *req)
 	if (req->buf != dev->rbuf) {
 		kfree(req->buf);
 		req->buf = dev->rbuf;
-		req->dma = DMA_ADDR_INVALID;
 	}
 	req->complete = epio_complete;
 	dev->setup_out_ready = 0;
@@ -1408,7 +1406,6 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 		dev->setup_abort = 1;
 
 	req->buf = dev->rbuf;
-	req->dma = DMA_ADDR_INVALID;
 	req->context = NULL;
 	value = -EOPNOTSUPP;
 	switch (ctrl->bRequest) {
diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c
index 21a9861..dd1c9b1 100644
--- a/drivers/usb/gadget/lpc32xx_udc.c
+++ b/drivers/usb/gadget/lpc32xx_udc.c
@@ -2399,7 +2399,7 @@ static void udc_handle_ep0_setup(struct lpc32xx_udc *udc)
 
 		if (i < 0) {
 			/* setup processing failed, force stall */
-			dev_err(udc->dev,
+			dev_dbg(udc->dev,
 				"req %02x.%02x protocol STALL; stat %d\n",
 				reqtype, req, i);
 			udc->ep0state = WAIT_FOR_SETUP;
@@ -3352,7 +3352,7 @@ phy_fail:
 	return retval;
 }
 
-static int __devexit lpc32xx_udc_remove(struct platform_device *pdev)
+static int lpc32xx_udc_remove(struct platform_device *pdev)
 {
 	struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
 
@@ -3447,7 +3447,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_udc_of_match);
 #endif
 
 static struct platform_driver lpc32xx_udc_driver = {
-	.remove		= __devexit_p(lpc32xx_udc_remove),
+	.remove		= lpc32xx_udc_remove,
 	.shutdown	= lpc32xx_udc_shutdown,
 	.suspend	= lpc32xx_udc_suspend,
 	.resume		= lpc32xx_udc_resume,
diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c
index 8cfd5b0..b5cea27 100644
--- a/drivers/usb/gadget/mv_u3d_core.c
+++ b/drivers/usb/gadget/mv_u3d_core.c
@@ -1763,7 +1763,7 @@ static void mv_u3d_gadget_release(struct device *dev)
 	dev_dbg(dev, "%s\n", __func__);
 }
 
-static __devexit int mv_u3d_remove(struct platform_device *dev)
+static int mv_u3d_remove(struct platform_device *dev)
 {
 	struct mv_u3d *u3d = platform_get_drvdata(dev);
 
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index ea45224..379aac7 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -2128,7 +2128,7 @@ static void gadget_release(struct device *_dev)
 	complete(udc->done);
 }
 
-static int __devexit mv_udc_remove(struct platform_device *dev)
+static int mv_udc_remove(struct platform_device *dev)
 {
 	struct mv_udc *udc = the_controller;
 	int clk_i;
@@ -2188,7 +2188,7 @@ static int __devexit mv_udc_remove(struct platform_device *dev)
 	return 0;
 }
 
-static int __devinit mv_udc_probe(struct platform_device *dev)
+static int mv_udc_probe(struct platform_device *dev)
 {
 	struct mv_usb_platform_data *pdata = dev->dev.platform_data;
 	struct mv_udc *udc;
diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c
index c009263..d226058 100644
--- a/drivers/usb/gadget/net2272.c
+++ b/drivers/usb/gadget/net2272.c
@@ -2193,7 +2193,7 @@ net2272_gadget_release(struct device *_dev)
 
 /*---------------------------------------------------------------------------*/
 
-static void __devexit
+static void
 net2272_remove(struct net2272 *dev)
 {
 	usb_del_gadget_udc(&dev->gadget);
@@ -2215,8 +2215,7 @@ net2272_remove(struct net2272 *dev)
 	dev_info(dev->dev, "unbind\n");
 }
 
-static struct net2272 * __devinit
-net2272_probe_init(struct device *dev, unsigned int irq)
+static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq)
 {
 	struct net2272 *ret;
 
@@ -2246,7 +2245,7 @@ net2272_probe_init(struct device *dev, unsigned int irq)
 	return ret;
 }
 
-static int __devinit
+static int
 net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
 {
 	int ret;
@@ -2306,7 +2305,7 @@ err_add_udc:
  * don't respond over USB until a gadget driver binds to us
  */
 
-static int __devinit
+static int
 net2272_rdk1_probe(struct pci_dev *pdev, struct net2272 *dev)
 {
 	unsigned long resource, len, tmp;
@@ -2389,7 +2388,7 @@ net2272_rdk1_probe(struct pci_dev *pdev, struct net2272 *dev)
 	return ret;
 }
 
-static int __devinit
+static int
 net2272_rdk2_probe(struct pci_dev *pdev, struct net2272 *dev)
 {
 	unsigned long resource, len;
@@ -2447,7 +2446,7 @@ net2272_rdk2_probe(struct pci_dev *pdev, struct net2272 *dev)
 	return ret;
 }
 
-static int __devinit
+static int
 net2272_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct net2272 *dev;
@@ -2489,7 +2488,7 @@ net2272_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	return ret;
 }
 
-static void __devexit
+static void
 net2272_rdk1_remove(struct pci_dev *pdev, struct net2272 *dev)
 {
 	int i;
@@ -2511,7 +2510,7 @@ net2272_rdk1_remove(struct pci_dev *pdev, struct net2272 *dev)
 	}
 }
 
-static void __devexit
+static void
 net2272_rdk2_remove(struct pci_dev *pdev, struct net2272 *dev)
 {
 	int i;
@@ -2530,7 +2529,7 @@ net2272_rdk2_remove(struct pci_dev *pdev, struct net2272 *dev)
 			pci_resource_len(pdev, i));
 }
 
-static void __devexit
+static void
 net2272_pci_remove(struct pci_dev *pdev)
 {
 	struct net2272 *dev = pci_get_drvdata(pdev);
@@ -2549,7 +2548,7 @@ net2272_pci_remove(struct pci_dev *pdev)
 }
 
 /* Table of matching PCI IDs */
-static struct pci_device_id __devinitdata pci_ids[] = {
+static struct pci_device_id pci_ids[] = {
 	{	/* RDK 1 card */
 		.class       = ((PCI_CLASS_BRIDGE_OTHER << 8) | 0xfe),
 		.class_mask  = 0,
@@ -2575,7 +2574,7 @@ static struct pci_driver net2272_pci_driver = {
 	.id_table = pci_ids,
 
 	.probe    = net2272_pci_probe,
-	.remove   = __devexit_p(net2272_pci_remove),
+	.remove   = net2272_pci_remove,
 };
 
 static int net2272_pci_register(void)
@@ -2595,7 +2594,7 @@ static inline void net2272_pci_unregister(void) { }
 
 /*---------------------------------------------------------------------------*/
 
-static int __devinit
+static int
 net2272_plat_probe(struct platform_device *pdev)
 {
 	struct net2272 *dev;
@@ -2661,7 +2660,7 @@ net2272_plat_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit
+static int
 net2272_plat_remove(struct platform_device *pdev)
 {
 	struct net2272 *dev = platform_get_drvdata(pdev);
@@ -2678,7 +2677,7 @@ net2272_plat_remove(struct platform_device *pdev)
 
 static struct platform_driver net2272_plat_driver = {
 	.probe   = net2272_plat_probe,
-	.remove  = __devexit_p(net2272_plat_remove),
+	.remove  = net2272_plat_remove,
 	.driver  = {
 		.name  = driver_name,
 		.owner = THIS_MODULE,
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index ac335af..708c0b5 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -9,7 +9,7 @@
  * CODE STATUS HIGHLIGHTS
  *
  * This driver should work well with most "gadget" drivers, including
- * the File Storage, Serial, and Ethernet/RNDIS gadget drivers
+ * the Mass Storage, Serial, and Ethernet/RNDIS gadget drivers
  * as well as Gadget Zero and Gadgetfs.
  *
  * DMA is enabled by default.  Drivers using transfer queues might use
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 2a4749c..09699f6 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -44,7 +44,7 @@
 #include <asm/unaligned.h>
 #include <asm/mach-types.h>
 
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 
 #include <mach/usb.h>
 
@@ -61,6 +61,8 @@
 #define	DRIVER_DESC	"OMAP UDC driver"
 #define	DRIVER_VERSION	"4 October 2004"
 
+#define OMAP_DMA_USB_W2FC_TX0		29
+
 /*
  * The OMAP UDC needs _very_ early endpoint setup:  before enabling the
  * D+ pullup to allow enumeration.  That's too early for the gadget
@@ -2506,7 +2508,7 @@ static inline void remove_proc_file(void) {}
  * UDC_SYSCON_1.CFG_LOCK is set can now work.  We won't use that
  * capability yet though.
  */
-static unsigned __devinit
+static unsigned
 omap_ep_setup(char *name, u8 addr, u8 type,
 		unsigned buf, unsigned maxp, int dbuf)
 {
@@ -2624,7 +2626,7 @@ static void omap_udc_release(struct device *dev)
 	udc = NULL;
 }
 
-static int __devinit
+static int
 omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
 {
 	unsigned	tmp, buf;
@@ -2761,7 +2763,7 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
 	return 0;
 }
 
-static int __devinit omap_udc_probe(struct platform_device *pdev)
+static int omap_udc_probe(struct platform_device *pdev)
 {
 	int			status = -ENODEV;
 	int			hmc;
@@ -2974,7 +2976,7 @@ cleanup0:
 	return status;
 }
 
-static int __devexit omap_udc_remove(struct platform_device *pdev)
+static int omap_udc_remove(struct platform_device *pdev)
 {
 	DECLARE_COMPLETION_ONSTACK(done);
 
@@ -3060,7 +3062,7 @@ static int omap_udc_resume(struct platform_device *dev)
 
 static struct platform_driver udc_driver = {
 	.probe		= omap_udc_probe,
-	.remove		= __devexit_p(omap_udc_remove),
+	.remove		= omap_udc_remove,
 	.suspend	= omap_udc_suspend,
 	.resume		= omap_udc_resume,
 	.driver		= {
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index e156e3f..35bcc83 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -983,8 +983,10 @@ static int __init printer_func_bind(struct usb_configuration *c,
 {
 	struct printer_dev *dev = container_of(f, struct printer_dev, function);
 	struct usb_composite_dev *cdev = c->cdev;
-	struct usb_ep		*in_ep, *out_ep;
+	struct usb_ep *in_ep;
+	struct usb_ep *out_ep = NULL;
 	int id;
+	int ret;
 
 	id = usb_interface_id(c, f);
 	if (id < 0)
@@ -1010,6 +1012,11 @@ autoconf_fail:
 	hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
 	hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
 
+	ret = usb_assign_descriptors(f, fs_printer_function,
+			hs_printer_function, NULL);
+	if (ret)
+		return ret;
+
 	dev->in_ep = in_ep;
 	dev->out_ep = out_ep;
 	return 0;
@@ -1018,6 +1025,7 @@ autoconf_fail:
 static void printer_func_unbind(struct usb_configuration *c,
 		struct usb_function *f)
 {
+	usb_free_all_descriptors(f);
 }
 
 static int printer_func_set_alt(struct usb_function *f,
@@ -1110,8 +1118,6 @@ static int __init printer_bind_config(struct usb_configuration *c)
 	dev = &usb_printer_gadget;
 
 	dev->function.name = shortname;
-	dev->function.descriptors = fs_printer_function;
-	dev->function.hs_descriptors = hs_printer_function;
 	dev->function.bind = printer_func_bind;
 	dev->function.setup = printer_func_setup;
 	dev->function.unbind = printer_func_unbind;
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index 8efbf08..d4ca9f1 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -29,6 +29,7 @@
 #include <linux/list.h>
 #include <linux/interrupt.h>
 #include <linux/mm.h>
+#include <linux/platform_data/pxa2xx_udc.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/irq.h>
@@ -59,9 +60,6 @@
 #include <mach/lubbock.h>
 #endif
 
-#include <asm/mach/udc_pxa2xx.h>
-
-
 /*
  * This driver handles the USB Device Controller (UDC) in Intel's PXA 25x
  * series processors.  The UDC for the IXP 4xx series is very similar.
diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h
index a1d268c..79d81a4 100644
--- a/drivers/usb/gadget/pxa27x_udc.h
+++ b/drivers/usb/gadget/pxa27x_udc.h
@@ -418,7 +418,7 @@ struct udc_stats {
  * @irq: udc irq
  * @clk: udc clock
  * @usb_gadget: udc gadget structure
- * @driver: bound gadget (zero, g_ether, g_file_storage, ...)
+ * @driver: bound gadget (zero, g_ether, g_mass_storage, ...)
  * @dev: device
  * @mach: machine info, used to activate specific GPIO
  * @transceiver: external transceiver to handle vbus sense and D+ pullup
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 6f696ee..141971d 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -3072,7 +3072,7 @@ static struct usb_gadget_ops s3c_hsotg_gadget_ops = {
  * creation) to give to the gadget driver. Setup the endpoint name, any
  * direction information and other state that may be required.
  */
-static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg,
+static void s3c_hsotg_initep(struct s3c_hsotg *hsotg,
 				       struct s3c_hsotg_ep *hs_ep,
 				       int epnum)
 {
@@ -3414,7 +3414,7 @@ static const struct file_operations ep_fops = {
  * with the same name as the device itself, in case we end up
  * with multiple blocks in future systems.
  */
-static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
 {
 	struct dentry *root;
 	unsigned epidx;
@@ -3460,7 +3460,7 @@ static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
  *
  * Cleanup (remove) the debugfs files for use on module exit.
  */
-static void __devexit s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
 {
 	unsigned epidx;
 
@@ -3490,7 +3490,7 @@ static void s3c_hsotg_release(struct device *dev)
  * @pdev: The platform information for the driver
  */
 
-static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
+static int s3c_hsotg_probe(struct platform_device *pdev)
 {
 	struct s3c_hsotg_plat *plat = pdev->dev.platform_data;
 	struct device *dev = &pdev->dev;
@@ -3675,7 +3675,7 @@ err_clk:
  * s3c_hsotg_remove - remove function for hsotg driver
  * @pdev: The platform information for the driver
  */
-static int __devexit s3c_hsotg_remove(struct platform_device *pdev)
+static int s3c_hsotg_remove(struct platform_device *pdev)
 {
 	struct s3c_hsotg *hsotg = platform_get_drvdata(pdev);
 
@@ -3708,7 +3708,7 @@ static struct platform_driver s3c_hsotg_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= s3c_hsotg_probe,
-	.remove		= __devexit_p(s3c_hsotg_remove),
+	.remove		= s3c_hsotg_remove,
 	.suspend	= s3c_hsotg_suspend,
 	.resume		= s3c_hsotg_resume,
 };
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index d8e785d..52379b1 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -1261,7 +1261,7 @@ static struct usb_gadget_ops s3c_hsudc_gadget_ops = {
 	.vbus_draw	= s3c_hsudc_vbus_draw,
 };
 
-static int __devinit s3c_hsudc_probe(struct platform_device *pdev)
+static int s3c_hsudc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct resource *res;
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index 8d9bcd8..0e3ae43 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -11,30 +11,10 @@
  * (at your option) any later version.
  */
 
-
 /*
  * This file requires the following identifiers used in USB strings to
  * be defined (each of type pointer to char):
- *  - fsg_string_manufacturer -- name of the manufacturer
- *  - fsg_string_product      -- name of the product
- *  - fsg_string_config       -- name of the configuration
  *  - fsg_string_interface    -- name of the interface
- * The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS
- * macro is defined prior to including this file.
- */
-
-/*
- * When FSG_NO_INTR_EP is defined fsg_fs_intr_in_desc and
- * fsg_hs_intr_in_desc objects as well as
- * FSG_FS_FUNCTION_PRE_EP_ENTRIES and FSG_HS_FUNCTION_PRE_EP_ENTRIES
- * macros are not defined.
- *
- * When FSG_NO_DEVICE_STRINGS is defined FSG_STRING_MANUFACTURER,
- * FSG_STRING_PRODUCT, FSG_STRING_SERIAL and FSG_STRING_CONFIG are not
- * defined (as well as corresponding entries in string tables are
- * missing) and FSG_STRING_INTERFACE has value of zero.
- *
- * When FSG_NO_OTG is defined fsg_otg_desc won't be defined.
  */
 
 /*
@@ -78,34 +58,6 @@
 #define LWARN(lun, fmt, args...)  dev_warn(&(lun)->dev, fmt, ## args)
 #define LINFO(lun, fmt, args...)  dev_info(&(lun)->dev, fmt, ## args)
 
-/*
- * Keep those macros in sync with those in
- * include/linux/usb/composite.h or else GCC will complain.  If they
- * are identical (the same names of arguments, white spaces in the
- * same places) GCC will allow redefinition otherwise (even if some
- * white space is removed or added) warning will be issued.
- *
- * Those macros are needed here because File Storage Gadget does not
- * include the composite.h header.  For composite gadgets those macros
- * are redundant since composite.h is included any way.
- *
- * One could check whether those macros are already defined (which
- * would indicate composite.h had been included) or not (which would
- * indicate we were in FSG) but this is not done because a warning is
- * desired if definitions here differ from the ones in composite.h.
- *
- * We want the definitions to match and be the same in File Storage
- * Gadget as well as Mass Storage Function (and so composite gadgets
- * using MSF).  If someone changes them in composite.h it will produce
- * a warning in this file when building MSF.
- */
-#define DBG(d, fmt, args...)     dev_dbg(&(d)->gadget->dev , fmt , ## args)
-#define VDBG(d, fmt, args...)    dev_vdbg(&(d)->gadget->dev , fmt , ## args)
-#define ERROR(d, fmt, args...)   dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARNING(d, fmt, args...) dev_warn(&(d)->gadget->dev , fmt , ## args)
-#define INFO(d, fmt, args...)    dev_info(&(d)->gadget->dev , fmt , ## args)
-
-
 
 #ifdef DUMP_MSGS
 
@@ -203,9 +155,12 @@ struct fsg_lun {
 	struct device	dev;
 };
 
-#define fsg_lun_is_open(curlun)	((curlun)->filp != NULL)
+static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
+{
+	return curlun->filp != NULL;
+}
 
-static struct fsg_lun *fsg_lun_from_dev(struct device *dev)
+static inline struct fsg_lun *fsg_lun_from_dev(struct device *dev)
 {
 	return container_of(dev, struct fsg_lun, dev);
 }
@@ -308,26 +263,10 @@ static inline u32 get_unaligned_be24(u8 *buf)
 
 
 enum {
-#ifndef FSG_NO_DEVICE_STRINGS
-	FSG_STRING_MANUFACTURER	= 1,
-	FSG_STRING_PRODUCT,
-	FSG_STRING_SERIAL,
-	FSG_STRING_CONFIG,
-#endif
 	FSG_STRING_INTERFACE
 };
 
 
-#ifndef FSG_NO_OTG
-static struct usb_otg_descriptor
-fsg_otg_desc = {
-	.bLength =		sizeof fsg_otg_desc,
-	.bDescriptorType =	USB_DT_OTG,
-
-	.bmAttributes =		USB_OTG_SRP,
-};
-#endif
-
 /* There is only one interface. */
 
 static struct usb_interface_descriptor
@@ -367,37 +306,10 @@ fsg_fs_bulk_out_desc = {
 	/* wMaxPacketSize set by autoconfiguration */
 };
 
-#ifndef FSG_NO_INTR_EP
-
-static struct usb_endpoint_descriptor
-fsg_fs_intr_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	cpu_to_le16(2),
-	.bInterval =		32,	/* frames -> 32 ms */
-};
-
-#ifndef FSG_NO_OTG
-#  define FSG_FS_FUNCTION_PRE_EP_ENTRIES	2
-#else
-#  define FSG_FS_FUNCTION_PRE_EP_ENTRIES	1
-#endif
-
-#endif
-
 static struct usb_descriptor_header *fsg_fs_function[] = {
-#ifndef FSG_NO_OTG
-	(struct usb_descriptor_header *) &fsg_otg_desc,
-#endif
 	(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,
-#ifndef FSG_NO_INTR_EP
-	(struct usb_descriptor_header *) &fsg_fs_intr_in_desc,
-#endif
 	NULL,
 };
 
@@ -431,37 +343,11 @@ fsg_hs_bulk_out_desc = {
 	.bInterval =		1,	/* NAK every 1 uframe */
 };
 
-#ifndef FSG_NO_INTR_EP
-
-static struct usb_endpoint_descriptor
-fsg_hs_intr_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	/* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	cpu_to_le16(2),
-	.bInterval =		9,	/* 2**(9-1) = 256 uframes -> 32 ms */
-};
-
-#ifndef FSG_NO_OTG
-#  define FSG_HS_FUNCTION_PRE_EP_ENTRIES	2
-#else
-#  define FSG_HS_FUNCTION_PRE_EP_ENTRIES	1
-#endif
-
-#endif
 
 static struct usb_descriptor_header *fsg_hs_function[] = {
-#ifndef FSG_NO_OTG
-	(struct usb_descriptor_header *) &fsg_otg_desc,
-#endif
 	(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,
-#ifndef FSG_NO_INTR_EP
-	(struct usb_descriptor_header *) &fsg_hs_intr_in_desc,
-#endif
 	NULL,
 };
 
@@ -499,34 +385,6 @@ static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
 	/*.bMaxBurst =		DYNAMIC, */
 };
 
-#ifndef FSG_NO_INTR_EP
-
-static struct usb_endpoint_descriptor
-fsg_ss_intr_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	/* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	cpu_to_le16(2),
-	.bInterval =		9,	/* 2**(9-1) = 256 uframes -> 32 ms */
-};
-
-static struct usb_ss_ep_comp_descriptor fsg_ss_intr_in_comp_desc = {
-	.bLength =		sizeof(fsg_ss_bulk_in_comp_desc),
-	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
-
-	.wBytesPerInterval =	cpu_to_le16(2),
-};
-
-#ifndef FSG_NO_OTG
-#  define FSG_SS_FUNCTION_PRE_EP_ENTRIES	2
-#else
-#  define FSG_SS_FUNCTION_PRE_EP_ENTRIES	1
-#endif
-
-#endif
-
 static __maybe_unused struct usb_ext_cap_descriptor fsg_ext_cap_desc = {
 	.bLength =		USB_DT_USB_EXT_CAP_SIZE,
 	.bDescriptorType =	USB_DT_DEVICE_CAPABILITY,
@@ -563,18 +421,11 @@ static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = {
 };
 
 static struct usb_descriptor_header *fsg_ss_function[] = {
-#ifndef FSG_NO_OTG
-	(struct usb_descriptor_header *) &fsg_otg_desc,
-#endif
 	(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,
 	(struct usb_descriptor_header *) &fsg_ss_bulk_out_desc,
 	(struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc,
-#ifndef FSG_NO_INTR_EP
-	(struct usb_descriptor_header *) &fsg_ss_intr_in_desc,
-	(struct usb_descriptor_header *) &fsg_ss_intr_in_comp_desc,
-#endif
 	NULL,
 };
 
@@ -594,12 +445,6 @@ fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
 
 /* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
 static struct usb_string		fsg_strings[] = {
-#ifndef FSG_NO_DEVICE_STRINGS
-	{FSG_STRING_MANUFACTURER,	fsg_string_manufacturer},
-	{FSG_STRING_PRODUCT,		fsg_string_product},
-	{FSG_STRING_SERIAL,		""},
-	{FSG_STRING_CONFIG,		fsg_string_config},
-#endif
 	{FSG_STRING_INTERFACE,		fsg_string_interface},
 	{}
 };
diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c
index 97e68b3..4f7f76f 100644
--- a/drivers/usb/gadget/tcm_usb_gadget.c
+++ b/drivers/usb/gadget/tcm_usb_gadget.c
@@ -1384,7 +1384,7 @@ static struct se_node_acl *usbg_alloc_fabric_acl(struct se_portal_group *se_tpg)
 
 	nacl = kzalloc(sizeof(struct usbg_nacl), GFP_KERNEL);
 	if (!nacl) {
-		printk(KERN_ERR "Unable to alocate struct usbg_nacl\n");
+		printk(KERN_ERR "Unable to allocate struct usbg_nacl\n");
 		return NULL;
 	}
 
@@ -2139,6 +2139,7 @@ static struct usb_descriptor_header *uasp_fs_function_desc[] = {
 	(struct usb_descriptor_header *) &uasp_status_pipe_desc,
 	(struct usb_descriptor_header *) &uasp_fs_cmd_desc,
 	(struct usb_descriptor_header *) &uasp_cmd_pipe_desc,
+	NULL,
 };
 
 static struct usb_descriptor_header *uasp_hs_function_desc[] = {
@@ -2239,6 +2240,7 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
 	struct usb_gadget	*gadget = c->cdev->gadget;
 	struct usb_ep		*ep;
 	int			iface;
+	int			ret;
 
 	iface = usb_interface_id(c, f);
 	if (iface < 0)
@@ -2289,6 +2291,11 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
 		uasp_ss_status_desc.bEndpointAddress;
 	uasp_fs_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress;
 
+	ret = usb_assign_descriptors(f, uasp_fs_function_desc,
+			uasp_hs_function_desc, uasp_ss_function_desc);
+	if (ret)
+		goto ep_fail;
+
 	return 0;
 ep_fail:
 	pr_err("Can't claim all required eps\n");
@@ -2304,6 +2311,7 @@ static void usbg_unbind(struct usb_configuration *c, struct usb_function *f)
 {
 	struct f_uas *fu = to_f_uas(f);
 
+	usb_free_all_descriptors(f);
 	kfree(fu);
 }
 
@@ -2384,9 +2392,6 @@ static int usbg_cfg_bind(struct usb_configuration *c)
 	if (!fu)
 		return -ENOMEM;
 	fu->function.name = "Target Function";
-	fu->function.descriptors = uasp_fs_function_desc;
-	fu->function.hs_descriptors = uasp_hs_function_desc;
-	fu->function.ss_descriptors = uasp_ss_function_desc;
 	fu->function.bind = usbg_bind;
 	fu->function.unbind = usbg_unbind;
 	fu->function.set_alt = usbg_set_alt;
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index f173952..d0f9548 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -1145,8 +1145,10 @@ int gserial_setup(struct usb_gadget *g, unsigned count)
 
 	return status;
 fail:
-	while (count--)
+	while (count--) {
+		tty_port_destroy(&ports[count].port->port);
 		kfree(ports[count].port);
+	}
 	put_tty_driver(gs_tty_driver);
 	gs_tty_driver = NULL;
 	return status;
@@ -1200,6 +1202,7 @@ void gserial_cleanup(void)
 
 		WARN_ON(port->port_usb != NULL);
 
+		tty_port_destroy(&port->port);
 		kfree(port);
 	}
 	n_ports = 0;
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index f3cd969..4d90a80 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -439,16 +439,6 @@ static DEVICE_ATTR(name, S_IRUSR, usb_udc_##param##_show, NULL)
 static USB_UDC_SPEED_ATTR(current_speed, speed);
 static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
 
-/* TODO: Scheduled for removal in 3.8. */
-static ssize_t usb_udc_is_dualspeed_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct usb_udc		*udc = container_of(dev, struct usb_udc, dev);
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			gadget_is_dualspeed(udc->gadget));
-}
-static DEVICE_ATTR(is_dualspeed, S_IRUSR, usb_udc_is_dualspeed_show, NULL);
-
 #define USB_UDC_ATTR(name)					\
 ssize_t usb_udc_##name##_show(struct device *dev,		\
 		struct device_attribute *attr, char *buf)	\
@@ -472,7 +462,6 @@ static struct attribute *usb_udc_attrs[] = {
 	&dev_attr_current_speed.attr,
 	&dev_attr_maximum_speed.attr,
 
-	&dev_attr_is_dualspeed.attr,
 	&dev_attr_is_otg.attr,
 	&dev_attr_is_a_peripheral.attr,
 	&dev_attr_b_hnp_enable.attr,
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 3f1431d..d6bb128 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -95,6 +95,11 @@ config USB_EHCI_TT_NEWSCHED
 
 	  If unsure, say Y.
 
+config USB_EHCI_PCI
+	tristate
+	depends on USB_EHCI_HCD && PCI
+	default y
+
 config USB_EHCI_HCD_PMC_MSP
 	tristate "EHCI support for on-chip PMC MSP71xx USB controller"
 	depends on USB_EHCI_HCD && MSP_HAS_USB
@@ -215,9 +220,13 @@ config USB_W90X900_EHCI
 		Enables support for the W90X900 USB controller
 
 config USB_CNS3XXX_EHCI
-	bool "Cavium CNS3XXX EHCI Module"
+	bool "Cavium CNS3XXX EHCI Module (DEPRECATED)"
 	depends on USB_EHCI_HCD && ARCH_CNS3XXX
+	select USB_EHCI_HCD_PLATFORM
 	---help---
+	  This option is deprecated now and the driver was removed, use
+	  USB_EHCI_HCD_PLATFORM instead.
+
 	  Enable support for the CNS3XXX SOC's on-chip EHCI controller.
 	  It is needed for high-speed (480Mbit/sec) USB 2.0 device
 	  support.
@@ -333,16 +342,6 @@ config USB_OHCI_ATH79
 	  Enables support for the built-in OHCI controller present on the
 	  Atheros AR71XX/AR7240 SoCs.
 
-config USB_OHCI_HCD_PPC_SOC
-	bool "OHCI support for on-chip PPC USB controller"
-	depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx)
-	default y
-	select USB_OHCI_BIG_ENDIAN_DESC
-	select USB_OHCI_BIG_ENDIAN_MMIO
-	---help---
-	  Enables support for the USB controller on the MPC52xx or
-	  STB03xxx processor chip.  If unsure, say Y.
-
 config USB_OHCI_HCD_PPC_OF_BE
 	bool "OHCI support for OF platform bus (big endian)"
 	depends on USB_OHCI_HCD && PPC_OF
@@ -393,9 +392,13 @@ config USB_OHCI_HCD_SSB
 	  If unsure, say N.
 
 config USB_OHCI_SH
-	bool "OHCI support for SuperH USB controller"
+	bool "OHCI support for SuperH USB controller (DEPRECATED)"
 	depends on USB_OHCI_HCD && SUPERH
+	select USB_OHCI_HCD_PLATFORM
 	---help---
+	  This option is deprecated now and the driver was removed, use
+	  USB_OHCI_HCD_PLATFORM instead.
+
 	  Enables support for the on-chip OHCI controller on the SuperH.
 	  If you use the PCI OHCI controller, this option is not necessary.
 
@@ -406,9 +409,13 @@ config USB_OHCI_EXYNOS
 	 Enable support for the Samsung Exynos SOC's on-chip OHCI controller.
 
 config USB_CNS3XXX_OHCI
-	bool "Cavium CNS3XXX OHCI Module"
+	bool "Cavium CNS3XXX OHCI Module (DEPRECATED)"
 	depends on USB_OHCI_HCD && ARCH_CNS3XXX
+	select USB_OHCI_HCD_PLATFORM
 	---help---
+	  This option is deprecated now and the driver was removed, use
+	  USB_OHCI_HCD_PLATFORM instead.
+
 	  Enable support for the CNS3XXX SOC's on-chip OHCI controller.
 	  It is needed for low-speed USB 1.0 device support.
 
@@ -423,7 +430,7 @@ config USB_OHCI_HCD_PLATFORM
 	  If unsure, say N.
 
 config USB_EHCI_HCD_PLATFORM
-	bool "Generic EHCI driver for a platform device"
+	tristate "Generic EHCI driver for a platform device"
 	depends on USB_EHCI_HCD
 	default n
 	---help---
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 9e0a89c..1eb4c30 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -24,6 +24,9 @@ obj-$(CONFIG_USB_WHCI_HCD)	+= whci/
 obj-$(CONFIG_PCI)		+= pci-quirks.o
 
 obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
+obj-$(CONFIG_USB_EHCI_PCI)	+= ehci-pci.o
+obj-$(CONFIG_USB_EHCI_HCD_PLATFORM)	+= ehci-platform.o
+
 obj-$(CONFIG_USB_OXU210HP_HCD)	+= oxu210hp-hcd.o
 obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
 obj-$(CONFIG_USB_ISP1362_HCD)	+= isp1362-hcd.o
@@ -40,6 +43,5 @@ obj-$(CONFIG_USB_HWA_HCD)	+= hwa-hc.o
 obj-$(CONFIG_USB_IMX21_HCD)	+= imx21-hcd.o
 obj-$(CONFIG_USB_FSL_MPH_DR_OF)	+= fsl-mph-dr-of.o
 obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
-obj-$(CONFIG_MIPS_ALCHEMY)	+= alchemy-common.o
 obj-$(CONFIG_USB_HCD_BCMA)	+= bcma-hcd.o
 obj-$(CONFIG_USB_HCD_SSB)	+= ssb-hcd.o
diff --git a/drivers/usb/host/alchemy-common.c b/drivers/usb/host/alchemy-common.c
deleted file mode 100644
index 936af83..0000000
--- a/drivers/usb/host/alchemy-common.c
+++ /dev/null
@@ -1,614 +0,0 @@
-/*
- * USB block power/access management abstraction.
- *
- * Au1000+: The OHCI block control register is at the far end of the OHCI memory
- *	    area. Au1550 has OHCI on different base address. No need to handle
- *	    UDC here.
- * Au1200:  one register to control access and clocks to O/EHCI, UDC and OTG
- *	    as well as the PHY for EHCI and UDC.
- *
- */
-
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/syscore_ops.h>
-#include <asm/mach-au1x00/au1000.h>
-
-/* control register offsets */
-#define AU1000_OHCICFG	0x7fffc
-#define AU1550_OHCICFG	0x07ffc
-#define AU1200_USBCFG	0x04
-
-/* Au1000 USB block config bits */
-#define USBHEN_RD	(1 << 4)		/* OHCI reset-done indicator */
-#define USBHEN_CE	(1 << 3)		/* OHCI block clock enable */
-#define USBHEN_E	(1 << 2)		/* OHCI block enable */
-#define USBHEN_C	(1 << 1)		/* OHCI block coherency bit */
-#define USBHEN_BE	(1 << 0)		/* OHCI Big-Endian */
-
-/* Au1200 USB config bits */
-#define USBCFG_PFEN	(1 << 31)		/* prefetch enable (undoc) */
-#define USBCFG_RDCOMB	(1 << 30)		/* read combining (undoc) */
-#define USBCFG_UNKNOWN	(5 << 20)		/* unknown, leave this way */
-#define USBCFG_SSD	(1 << 23)		/* serial short detect en */
-#define USBCFG_PPE	(1 << 19)		/* HS PHY PLL */
-#define USBCFG_UCE	(1 << 18)		/* UDC clock enable */
-#define USBCFG_ECE	(1 << 17)		/* EHCI clock enable */
-#define USBCFG_OCE	(1 << 16)		/* OHCI clock enable */
-#define USBCFG_FLA(x)	(((x) & 0x3f) << 8)
-#define USBCFG_UCAM	(1 << 7)		/* coherent access (undoc) */
-#define USBCFG_GME	(1 << 6)		/* OTG mem access */
-#define USBCFG_DBE	(1 << 5)		/* UDC busmaster enable */
-#define USBCFG_DME	(1 << 4)		/* UDC mem enable */
-#define USBCFG_EBE	(1 << 3)		/* EHCI busmaster enable */
-#define USBCFG_EME	(1 << 2)		/* EHCI mem enable */
-#define USBCFG_OBE	(1 << 1)		/* OHCI busmaster enable */
-#define USBCFG_OME	(1 << 0)		/* OHCI mem enable */
-#define USBCFG_INIT_AU1200	(USBCFG_PFEN | USBCFG_RDCOMB | USBCFG_UNKNOWN |\
-				 USBCFG_SSD | USBCFG_FLA(0x20) | USBCFG_UCAM | \
-				 USBCFG_GME | USBCFG_DBE | USBCFG_DME |	       \
-				 USBCFG_EBE | USBCFG_EME | USBCFG_OBE |	       \
-				 USBCFG_OME)
-
-/* Au1300 USB config registers */
-#define USB_DWC_CTRL1		0x00
-#define USB_DWC_CTRL2		0x04
-#define USB_VBUS_TIMER		0x10
-#define USB_SBUS_CTRL		0x14
-#define USB_MSR_ERR		0x18
-#define USB_DWC_CTRL3		0x1C
-#define USB_DWC_CTRL4		0x20
-#define USB_OTG_STATUS		0x28
-#define USB_DWC_CTRL5		0x2C
-#define USB_DWC_CTRL6		0x30
-#define USB_DWC_CTRL7		0x34
-#define USB_PHY_STATUS		0xC0
-#define USB_INT_STATUS		0xC4
-#define USB_INT_ENABLE		0xC8
-
-#define USB_DWC_CTRL1_OTGD	0x04 /* set to DISable OTG */
-#define USB_DWC_CTRL1_HSTRS	0x02 /* set to ENable EHCI */
-#define USB_DWC_CTRL1_DCRS	0x01 /* set to ENable UDC */
-
-#define USB_DWC_CTRL2_PHY1RS	0x04 /* set to enable PHY1 */
-#define USB_DWC_CTRL2_PHY0RS	0x02 /* set to enable PHY0 */
-#define USB_DWC_CTRL2_PHYRS	0x01 /* set to enable PHY */
-
-#define USB_DWC_CTRL3_OHCI1_CKEN	(1 << 19)
-#define USB_DWC_CTRL3_OHCI0_CKEN	(1 << 18)
-#define USB_DWC_CTRL3_EHCI0_CKEN	(1 << 17)
-#define USB_DWC_CTRL3_OTG0_CKEN		(1 << 16)
-
-#define USB_SBUS_CTRL_SBCA		0x04 /* coherent access */
-
-#define USB_INTEN_FORCE			0x20
-#define USB_INTEN_PHY			0x10
-#define USB_INTEN_UDC			0x08
-#define USB_INTEN_EHCI			0x04
-#define USB_INTEN_OHCI1			0x02
-#define USB_INTEN_OHCI0			0x01
-
-static DEFINE_SPINLOCK(alchemy_usb_lock);
-
-static inline void __au1300_usb_phyctl(void __iomem *base, int enable)
-{
-	unsigned long r, s;
-
-	r = __raw_readl(base + USB_DWC_CTRL2);
-	s = __raw_readl(base + USB_DWC_CTRL3);
-
-	s &= USB_DWC_CTRL3_OHCI1_CKEN | USB_DWC_CTRL3_OHCI0_CKEN |
-		USB_DWC_CTRL3_EHCI0_CKEN | USB_DWC_CTRL3_OTG0_CKEN;
-
-	if (enable) {
-		/* simply enable all PHYs */
-		r |= USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
-		     USB_DWC_CTRL2_PHYRS;
-		__raw_writel(r, base + USB_DWC_CTRL2);
-		wmb();
-	} else if (!s) {
-		/* no USB block active, do disable all PHYs */
-		r &= ~(USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
-		       USB_DWC_CTRL2_PHYRS);
-		__raw_writel(r, base + USB_DWC_CTRL2);
-		wmb();
-	}
-}
-
-static inline void __au1300_ohci_control(void __iomem *base, int enable, int id)
-{
-	unsigned long r;
-
-	if (enable) {
-		__raw_writel(1, base + USB_DWC_CTRL7);  /* start OHCI clock */
-		wmb();
-
-		r = __raw_readl(base + USB_DWC_CTRL3);	/* enable OHCI block */
-		r |= (id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
-			       : USB_DWC_CTRL3_OHCI1_CKEN;
-		__raw_writel(r, base + USB_DWC_CTRL3);
-		wmb();
-
-		__au1300_usb_phyctl(base, enable);	/* power up the PHYs */
-
-		r = __raw_readl(base + USB_INT_ENABLE);
-		r |= (id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1;
-		__raw_writel(r, base + USB_INT_ENABLE);
-		wmb();
-
-		/* reset the OHCI start clock bit */
-		__raw_writel(0, base + USB_DWC_CTRL7);
-		wmb();
-	} else {
-		r = __raw_readl(base + USB_INT_ENABLE);
-		r &= ~((id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1);
-		__raw_writel(r, base + USB_INT_ENABLE);
-		wmb();
-
-		r = __raw_readl(base + USB_DWC_CTRL3);
-		r &= ~((id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
-				 : USB_DWC_CTRL3_OHCI1_CKEN);
-		__raw_writel(r, base + USB_DWC_CTRL3);
-		wmb();
-
-		__au1300_usb_phyctl(base, enable);
-	}
-}
-
-static inline void __au1300_ehci_control(void __iomem *base, int enable)
-{
-	unsigned long r;
-
-	if (enable) {
-		r = __raw_readl(base + USB_DWC_CTRL3);
-		r |= USB_DWC_CTRL3_EHCI0_CKEN;
-		__raw_writel(r, base + USB_DWC_CTRL3);
-		wmb();
-
-		r = __raw_readl(base + USB_DWC_CTRL1);
-		r |= USB_DWC_CTRL1_HSTRS;
-		__raw_writel(r, base + USB_DWC_CTRL1);
-		wmb();
-
-		__au1300_usb_phyctl(base, enable);
-
-		r = __raw_readl(base + USB_INT_ENABLE);
-		r |= USB_INTEN_EHCI;
-		__raw_writel(r, base + USB_INT_ENABLE);
-		wmb();
-	} else {
-		r = __raw_readl(base + USB_INT_ENABLE);
-		r &= ~USB_INTEN_EHCI;
-		__raw_writel(r, base + USB_INT_ENABLE);
-		wmb();
-
-		r = __raw_readl(base + USB_DWC_CTRL1);
-		r &= ~USB_DWC_CTRL1_HSTRS;
-		__raw_writel(r, base + USB_DWC_CTRL1);
-		wmb();
-
-		r = __raw_readl(base + USB_DWC_CTRL3);
-		r &= ~USB_DWC_CTRL3_EHCI0_CKEN;
-		__raw_writel(r, base + USB_DWC_CTRL3);
-		wmb();
-
-		__au1300_usb_phyctl(base, enable);
-	}
-}
-
-static inline void __au1300_udc_control(void __iomem *base, int enable)
-{
-	unsigned long r;
-
-	if (enable) {
-		r = __raw_readl(base + USB_DWC_CTRL1);
-		r |= USB_DWC_CTRL1_DCRS;
-		__raw_writel(r, base + USB_DWC_CTRL1);
-		wmb();
-
-		__au1300_usb_phyctl(base, enable);
-
-		r = __raw_readl(base + USB_INT_ENABLE);
-		r |= USB_INTEN_UDC;
-		__raw_writel(r, base + USB_INT_ENABLE);
-		wmb();
-	} else {
-		r = __raw_readl(base + USB_INT_ENABLE);
-		r &= ~USB_INTEN_UDC;
-		__raw_writel(r, base + USB_INT_ENABLE);
-		wmb();
-
-		r = __raw_readl(base + USB_DWC_CTRL1);
-		r &= ~USB_DWC_CTRL1_DCRS;
-		__raw_writel(r, base + USB_DWC_CTRL1);
-		wmb();
-
-		__au1300_usb_phyctl(base, enable);
-	}
-}
-
-static inline void __au1300_otg_control(void __iomem *base, int enable)
-{
-	unsigned long r;
-	if (enable) {
-		r = __raw_readl(base + USB_DWC_CTRL3);
-		r |= USB_DWC_CTRL3_OTG0_CKEN;
-		__raw_writel(r, base + USB_DWC_CTRL3);
-		wmb();
-
-		r = __raw_readl(base + USB_DWC_CTRL1);
-		r &= ~USB_DWC_CTRL1_OTGD;
-		__raw_writel(r, base + USB_DWC_CTRL1);
-		wmb();
-
-		__au1300_usb_phyctl(base, enable);
-	} else {
-		r = __raw_readl(base + USB_DWC_CTRL1);
-		r |= USB_DWC_CTRL1_OTGD;
-		__raw_writel(r, base + USB_DWC_CTRL1);
-		wmb();
-
-		r = __raw_readl(base + USB_DWC_CTRL3);
-		r &= ~USB_DWC_CTRL3_OTG0_CKEN;
-		__raw_writel(r, base + USB_DWC_CTRL3);
-		wmb();
-
-		__au1300_usb_phyctl(base, enable);
-	}
-}
-
-static inline int au1300_usb_control(int block, int enable)
-{
-	void __iomem *base =
-		(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
-	int ret = 0;
-
-	switch (block) {
-	case ALCHEMY_USB_OHCI0:
-		__au1300_ohci_control(base, enable, 0);
-		break;
-	case ALCHEMY_USB_OHCI1:
-		__au1300_ohci_control(base, enable, 1);
-		break;
-	case ALCHEMY_USB_EHCI0:
-		__au1300_ehci_control(base, enable);
-		break;
-	case ALCHEMY_USB_UDC0:
-		__au1300_udc_control(base, enable);
-		break;
-	case ALCHEMY_USB_OTG0:
-		__au1300_otg_control(base, enable);
-		break;
-	default:
-		ret = -ENODEV;
-	}
-	return ret;
-}
-
-static inline void au1300_usb_init(void)
-{
-	void __iomem *base =
-		(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
-
-	/* set some sane defaults.  Note: we don't fiddle with DWC_CTRL4
-	 * here at all: Port 2 routing (EHCI or UDC) must be set either
-	 * by boot firmware or platform init code; I can't autodetect
-	 * a sane setting.
-	 */
-	__raw_writel(0, base + USB_INT_ENABLE); /* disable all USB irqs */
-	wmb();
-	__raw_writel(0, base + USB_DWC_CTRL3); /* disable all clocks */
-	wmb();
-	__raw_writel(~0, base + USB_MSR_ERR); /* clear all errors */
-	wmb();
-	__raw_writel(~0, base + USB_INT_STATUS); /* clear int status */
-	wmb();
-	/* set coherent access bit */
-	__raw_writel(USB_SBUS_CTRL_SBCA, base + USB_SBUS_CTRL);
-	wmb();
-}
-
-static inline void __au1200_ohci_control(void __iomem *base, int enable)
-{
-	unsigned long r = __raw_readl(base + AU1200_USBCFG);
-	if (enable) {
-		__raw_writel(r | USBCFG_OCE, base + AU1200_USBCFG);
-		wmb();
-		udelay(2000);
-	} else {
-		__raw_writel(r & ~USBCFG_OCE, base + AU1200_USBCFG);
-		wmb();
-		udelay(1000);
-	}
-}
-
-static inline void __au1200_ehci_control(void __iomem *base, int enable)
-{
-	unsigned long r = __raw_readl(base + AU1200_USBCFG);
-	if (enable) {
-		__raw_writel(r | USBCFG_ECE | USBCFG_PPE, base + AU1200_USBCFG);
-		wmb();
-		udelay(1000);
-	} else {
-		if (!(r & USBCFG_UCE))		/* UDC also off? */
-			r &= ~USBCFG_PPE;	/* yes: disable HS PHY PLL */
-		__raw_writel(r & ~USBCFG_ECE, base + AU1200_USBCFG);
-		wmb();
-		udelay(1000);
-	}
-}
-
-static inline void __au1200_udc_control(void __iomem *base, int enable)
-{
-	unsigned long r = __raw_readl(base + AU1200_USBCFG);
-	if (enable) {
-		__raw_writel(r | USBCFG_UCE | USBCFG_PPE, base + AU1200_USBCFG);
-		wmb();
-	} else {
-		if (!(r & USBCFG_ECE))		/* EHCI also off? */
-			r &= ~USBCFG_PPE;	/* yes: disable HS PHY PLL */
-		__raw_writel(r & ~USBCFG_UCE, base + AU1200_USBCFG);
-		wmb();
-	}
-}
-
-static inline int au1200_coherency_bug(void)
-{
-#if defined(CONFIG_DMA_COHERENT)
-	/* Au1200 AB USB does not support coherent memory */
-	if (!(read_c0_prid() & 0xff)) {
-		printk(KERN_INFO "Au1200 USB: this is chip revision AB !!\n");
-		printk(KERN_INFO "Au1200 USB: update your board or re-configure"
-				 " the kernel\n");
-		return -ENODEV;
-	}
-#endif
-	return 0;
-}
-
-static inline int au1200_usb_control(int block, int enable)
-{
-	void __iomem *base =
-			(void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
-	int ret = 0;
-
-	switch (block) {
-	case ALCHEMY_USB_OHCI0:
-		ret = au1200_coherency_bug();
-		if (ret && enable)
-			goto out;
-		__au1200_ohci_control(base, enable);
-		break;
-	case ALCHEMY_USB_UDC0:
-		__au1200_udc_control(base, enable);
-		break;
-	case ALCHEMY_USB_EHCI0:
-		ret = au1200_coherency_bug();
-		if (ret && enable)
-			goto out;
-		__au1200_ehci_control(base, enable);
-		break;
-	default:
-		ret = -ENODEV;
-	}
-out:
-	return ret;
-}
-
-
-/* initialize USB block(s) to a known working state */
-static inline void au1200_usb_init(void)
-{
-	void __iomem *base =
-			(void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
-	__raw_writel(USBCFG_INIT_AU1200, base + AU1200_USBCFG);
-	wmb();
-	udelay(1000);
-}
-
-static inline void au1000_usb_init(unsigned long rb, int reg)
-{
-	void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg);
-	unsigned long r = __raw_readl(base);
-
-#if defined(__BIG_ENDIAN)
-	r |= USBHEN_BE;
-#endif
-	r |= USBHEN_C;
-
-	__raw_writel(r, base);
-	wmb();
-	udelay(1000);
-}
-
-
-static inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg)
-{
-	void __iomem *base = (void __iomem *)KSEG1ADDR(rb);
-	unsigned long r = __raw_readl(base + creg);
-
-	if (enable) {
-		__raw_writel(r | USBHEN_CE, base + creg);
-		wmb();
-		udelay(1000);
-		__raw_writel(r | USBHEN_CE | USBHEN_E, base + creg);
-		wmb();
-		udelay(1000);
-
-		/* wait for reset complete (read reg twice: au1500 erratum) */
-		while (__raw_readl(base + creg),
-			!(__raw_readl(base + creg) & USBHEN_RD))
-			udelay(1000);
-	} else {
-		__raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg);
-		wmb();
-	}
-}
-
-static inline int au1000_usb_control(int block, int enable, unsigned long rb,
-				     int creg)
-{
-	int ret = 0;
-
-	switch (block) {
-	case ALCHEMY_USB_OHCI0:
-		__au1xx0_ohci_control(enable, rb, creg);
-		break;
-	default:
-		ret = -ENODEV;
-	}
-	return ret;
-}
-
-/*
- * alchemy_usb_control - control Alchemy on-chip USB blocks
- * @block:	USB block to target
- * @enable:	set 1 to enable a block, 0 to disable
- */
-int alchemy_usb_control(int block, int enable)
-{
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&alchemy_usb_lock, flags);
-	switch (alchemy_get_cputype()) {
-	case ALCHEMY_CPU_AU1000:
-	case ALCHEMY_CPU_AU1500:
-	case ALCHEMY_CPU_AU1100:
-		ret = au1000_usb_control(block, enable,
-				AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
-		break;
-	case ALCHEMY_CPU_AU1550:
-		ret = au1000_usb_control(block, enable,
-				AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
-		break;
-	case ALCHEMY_CPU_AU1200:
-		ret = au1200_usb_control(block, enable);
-		break;
-	case ALCHEMY_CPU_AU1300:
-		ret = au1300_usb_control(block, enable);
-		break;
-	default:
-		ret = -ENODEV;
-	}
-	spin_unlock_irqrestore(&alchemy_usb_lock, flags);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(alchemy_usb_control);
-
-
-static unsigned long alchemy_usb_pmdata[2];
-
-static void au1000_usb_pm(unsigned long br, int creg, int susp)
-{
-	void __iomem *base = (void __iomem *)KSEG1ADDR(br);
-
-	if (susp) {
-		alchemy_usb_pmdata[0] = __raw_readl(base + creg);
-		/* There appears to be some undocumented reset register.... */
-		__raw_writel(0, base + 0x04);
-		wmb();
-		__raw_writel(0, base + creg);
-		wmb();
-	} else {
-		__raw_writel(alchemy_usb_pmdata[0], base + creg);
-		wmb();
-	}
-}
-
-static void au1200_usb_pm(int susp)
-{
-	void __iomem *base =
-			(void __iomem *)KSEG1ADDR(AU1200_USB_OTG_PHYS_ADDR);
-	if (susp) {
-		/* save OTG_CAP/MUX registers which indicate port routing */
-		/* FIXME: write an OTG driver to do that */
-		alchemy_usb_pmdata[0] = __raw_readl(base + 0x00);
-		alchemy_usb_pmdata[1] = __raw_readl(base + 0x04);
-	} else {
-		/* restore access to all MMIO areas */
-		au1200_usb_init();
-
-		/* restore OTG_CAP/MUX registers */
-		__raw_writel(alchemy_usb_pmdata[0], base + 0x00);
-		__raw_writel(alchemy_usb_pmdata[1], base + 0x04);
-		wmb();
-	}
-}
-
-static void au1300_usb_pm(int susp)
-{
-	void __iomem *base =
-			(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
-	/* remember Port2 routing */
-	if (susp) {
-		alchemy_usb_pmdata[0] = __raw_readl(base + USB_DWC_CTRL4);
-	} else {
-		au1300_usb_init();
-		__raw_writel(alchemy_usb_pmdata[0], base + USB_DWC_CTRL4);
-		wmb();
-	}
-}
-
-static void alchemy_usb_pm(int susp)
-{
-	switch (alchemy_get_cputype()) {
-	case ALCHEMY_CPU_AU1000:
-	case ALCHEMY_CPU_AU1500:
-	case ALCHEMY_CPU_AU1100:
-		au1000_usb_pm(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG, susp);
-		break;
-	case ALCHEMY_CPU_AU1550:
-		au1000_usb_pm(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG, susp);
-		break;
-	case ALCHEMY_CPU_AU1200:
-		au1200_usb_pm(susp);
-		break;
-	case ALCHEMY_CPU_AU1300:
-		au1300_usb_pm(susp);
-		break;
-	}
-}
-
-static int alchemy_usb_suspend(void)
-{
-	alchemy_usb_pm(1);
-	return 0;
-}
-
-static void alchemy_usb_resume(void)
-{
-	alchemy_usb_pm(0);
-}
-
-static struct syscore_ops alchemy_usb_pm_ops = {
-	.suspend	= alchemy_usb_suspend,
-	.resume		= alchemy_usb_resume,
-};
-
-static int __init alchemy_usb_init(void)
-{
-	switch (alchemy_get_cputype()) {
-	case ALCHEMY_CPU_AU1000:
-	case ALCHEMY_CPU_AU1500:
-	case ALCHEMY_CPU_AU1100:
-		au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
-		break;
-	case ALCHEMY_CPU_AU1550:
-		au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
-		break;
-	case ALCHEMY_CPU_AU1200:
-		au1200_usb_init();
-		break;
-	case ALCHEMY_CPU_AU1300:
-		au1300_usb_init();
-		break;
-	}
-
-	register_syscore_ops(&alchemy_usb_pm_ops);
-
-	return 0;
-}
-arch_initcall(alchemy_usb_init);
diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c
index 443da21..df13d42 100644
--- a/drivers/usb/host/bcma-hcd.c
+++ b/drivers/usb/host/bcma-hcd.c
@@ -54,7 +54,7 @@ static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask,
 	return -ETIMEDOUT;
 }
 
-static void __devinit bcma_hcd_4716wa(struct bcma_device *dev)
+static void bcma_hcd_4716wa(struct bcma_device *dev)
 {
 #ifdef CONFIG_BCMA_DRIVER_MIPS
 	/* Work around for 4716 failures. */
@@ -88,7 +88,7 @@ static void __devinit bcma_hcd_4716wa(struct bcma_device *dev)
 }
 
 /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
-static void __devinit bcma_hcd_init_chip(struct bcma_device *dev)
+static void bcma_hcd_init_chip(struct bcma_device *dev)
 {
 	u32 tmp;
 
@@ -165,8 +165,7 @@ static const struct usb_ehci_pdata ehci_pdata = {
 static const struct usb_ohci_pdata ohci_pdata = {
 };
 
-static struct platform_device * __devinit
-bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr)
+static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr)
 {
 	struct platform_device *hci_dev;
 	struct resource hci_res[2];
@@ -212,7 +211,7 @@ err_alloc:
 	return ERR_PTR(ret);
 }
 
-static int __devinit bcma_hcd_probe(struct bcma_device *dev)
+static int bcma_hcd_probe(struct bcma_device *dev)
 {
 	int err;
 	u16 chipid_top;
@@ -266,7 +265,7 @@ err_free_usb_dev:
 	return err;
 }
 
-static void __devexit bcma_hcd_remove(struct bcma_device *dev)
+static void bcma_hcd_remove(struct bcma_device *dev)
 {
 	struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
 	struct platform_device *ohci_dev = usb_dev->ohci_dev;
@@ -306,7 +305,7 @@ static int bcma_hcd_resume(struct bcma_device *dev)
 #define bcma_hcd_resume	NULL
 #endif /* CONFIG_PM */
 
-static const struct bcma_device_id bcma_hcd_table[] __devinitconst = {
+static const struct bcma_device_id bcma_hcd_table[] = {
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),
 	BCMA_CORETABLE_END
 };
@@ -316,7 +315,7 @@ static struct bcma_driver bcma_hcd_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= bcma_hcd_table,
 	.probe		= bcma_hcd_probe,
-	.remove		= __devexit_p(bcma_hcd_remove),
+	.remove		= bcma_hcd_remove,
 	.shutdown	= bcma_hcd_shutdown,
 	.suspend	= bcma_hcd_suspend,
 	.resume		= bcma_hcd_resume,
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 411bb74..27639487 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -53,18 +53,11 @@ static void atmel_stop_ehci(struct platform_device *pdev)
 static int ehci_atmel_setup(struct usb_hcd *hcd)
 {
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	int retval;
 
 	/* registers start at offset 0x0 */
 	ehci->caps = hcd->regs;
 
-	retval = ehci_setup(hcd);
-	if (retval)
-		return retval;
-
-	ehci_port_power(ehci, 0);
-
-	return retval;
+	return ehci_setup(hcd);
 }
 
 static const struct hc_driver ehci_atmel_hc_driver = {
@@ -104,7 +97,7 @@ static const struct hc_driver ehci_atmel_hc_driver = {
 
 static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32);
 
-static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev)
+static int ehci_atmel_drv_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
 	const struct hc_driver *driver = &ehci_atmel_hc_driver;
@@ -189,7 +182,7 @@ fail_create_hcd:
 	return retval;
 }
 
-static int __devexit ehci_atmel_drv_remove(struct platform_device *pdev)
+static int ehci_atmel_drv_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
@@ -214,7 +207,7 @@ MODULE_DEVICE_TABLE(of, atmel_ehci_dt_ids);
 
 static struct platform_driver ehci_atmel_driver = {
 	.probe		= ehci_atmel_drv_probe,
-	.remove		= __devexit_p(ehci_atmel_drv_remove),
+	.remove		= ehci_atmel_drv_remove,
 	.shutdown	= usb_hcd_platform_shutdown,
 	.driver		= {
 		.name	= "atmel-ehci",
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
deleted file mode 100644
index 65c945e..0000000
--- a/drivers/usb/host/ehci-au1xxx.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * EHCI HCD (Host Controller Driver) for USB.
- *
- * Bus Glue for AMD Alchemy Au1xxx
- *
- * Based on "ohci-au1xxx.c" by Matt Porter <mporter@kernel.crashing.org>
- *
- * Modified for AMD Alchemy Au1200 EHC
- *  by K.Boge <karsten.boge@amd.com>
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/platform_device.h>
-#include <asm/mach-au1x00/au1000.h>
-
-
-extern int usb_disabled(void);
-
-static int au1xxx_ehci_setup(struct usb_hcd *hcd)
-{
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	int ret;
-
-	ehci->caps = hcd->regs;
-	ret = ehci_setup(hcd);
-
-	ehci->need_io_watchdog = 0;
-	return ret;
-}
-
-static const struct hc_driver ehci_au1xxx_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "Au1xxx EHCI",
-	.hcd_priv_size		= sizeof(struct ehci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
-
-	/*
-	 * basic lifecycle operations
-	 *
-	 * FIXME -- ehci_init() doesn't do enough here.
-	 * See ehci-ppc-soc for a complete implementation.
-	 */
-	.reset			= au1xxx_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,
-	.bus_suspend		= ehci_bus_suspend,
-	.bus_resume		= ehci_bus_resume,
-	.relinquish_port	= ehci_relinquish_port,
-	.port_handed_over	= ehci_port_handed_over,
-
-	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
-};
-
-static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd;
-	struct resource *res;
-	int ret;
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	if (pdev->resource[1].flags != IORESOURCE_IRQ) {
-		pr_debug("resource[1] is not IORESOURCE_IRQ");
-		return -ENOMEM;
-	}
-	hcd = usb_create_hcd(&ehci_au1xxx_hc_driver, &pdev->dev, "Au1xxx");
-	if (!hcd)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_size(res);
-
-	hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
-	if (!hcd->regs) {
-		pr_debug("devm_request_and_ioremap failed");
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	if (alchemy_usb_control(ALCHEMY_USB_EHCI0, 1)) {
-		printk(KERN_INFO "%s: controller init failed!\n", pdev->name);
-		ret = -ENODEV;
-		goto err1;
-	}
-
-	ret = usb_add_hcd(hcd, pdev->resource[1].start,
-			  IRQF_SHARED);
-	if (ret == 0) {
-		platform_set_drvdata(pdev, hcd);
-		return ret;
-	}
-
-	alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
-err1:
-	usb_put_hcd(hcd);
-	return ret;
-}
-
-static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_remove_hcd(hcd);
-	alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
-	usb_put_hcd(hcd);
-	platform_set_drvdata(pdev, NULL);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
-{
-	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	bool do_wakeup = device_may_wakeup(dev);
-	int rc;
-
-	rc = ehci_suspend(hcd, do_wakeup);
-	alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
-
-	return rc;
-}
-
-static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
-{
-	struct usb_hcd *hcd = dev_get_drvdata(dev);
-
-	alchemy_usb_control(ALCHEMY_USB_EHCI0, 1);
-	ehci_resume(hcd, false);
-
-	return 0;
-}
-
-static const struct dev_pm_ops au1xxx_ehci_pmops = {
-	.suspend	= ehci_hcd_au1xxx_drv_suspend,
-	.resume		= ehci_hcd_au1xxx_drv_resume,
-};
-
-#define AU1XXX_EHCI_PMOPS &au1xxx_ehci_pmops
-
-#else
-#define AU1XXX_EHCI_PMOPS NULL
-#endif
-
-static struct platform_driver ehci_hcd_au1xxx_driver = {
-	.probe		= ehci_hcd_au1xxx_drv_probe,
-	.remove		= ehci_hcd_au1xxx_drv_remove,
-	.shutdown	= usb_hcd_platform_shutdown,
-	.driver = {
-		.name	= "au1xxx-ehci",
-		.owner	= THIS_MODULE,
-		.pm	= AU1XXX_EHCI_PMOPS,
-	}
-};
-
-MODULE_ALIAS("platform:au1xxx-ehci");
diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c
deleted file mode 100644
index d91708d..0000000
--- a/drivers/usb/host/ehci-cns3xxx.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 2008 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/atomic.h>
-#include <mach/cns3xxx.h>
-#include <mach/pm.h>
-
-static int cns3xxx_ehci_init(struct usb_hcd *hcd)
-{
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	int retval;
-
-	/*
-	 * EHCI and OHCI share the same clock and power,
-	 * resetting twice would cause the 1st controller been reset.
-	 * Therefore only do power up  at the first up device, and
-	 * power down at the last down device.
-	 *
-	 * Set USB AHB INCR length to 16
-	 */
-	if (atomic_inc_return(&usb_pwr_ref) == 1) {
-		cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
-		cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
-		cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
-		__raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
-			MISC_CHIP_CONFIG_REG);
-	}
-
-	ehci->caps = hcd->regs;
-
-	hcd->has_tt = 0;
-
-	retval = ehci_setup(hcd);
-	if (retval)
-		return retval;
-
-	ehci_port_power(ehci, 0);
-
-	return retval;
-}
-
-static const struct hc_driver cns3xxx_ehci_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "CNS3XXX EHCI Host Controller",
-	.hcd_priv_size		= sizeof(struct ehci_hcd),
-	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
-	.reset			= cns3xxx_ehci_init,
-	.start			= ehci_run,
-	.stop			= ehci_stop,
-	.shutdown		= ehci_shutdown,
-	.urb_enqueue		= ehci_urb_enqueue,
-	.urb_dequeue		= ehci_urb_dequeue,
-	.endpoint_disable	= ehci_endpoint_disable,
-	.endpoint_reset		= ehci_endpoint_reset,
-	.get_frame_number	= ehci_get_frame,
-	.hub_status_data	= ehci_hub_status_data,
-	.hub_control		= ehci_hub_control,
-#ifdef CONFIG_PM
-	.bus_suspend		= ehci_bus_suspend,
-	.bus_resume		= ehci_bus_resume,
-#endif
-	.relinquish_port	= ehci_relinquish_port,
-	.port_handed_over	= ehci_port_handed_over,
-
-	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
-};
-
-static int cns3xxx_ehci_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct usb_hcd *hcd;
-	const struct hc_driver *driver = &cns3xxx_ehci_hc_driver;
-	struct resource *res;
-	int irq;
-	int retval;
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		dev_err(dev, "Found HC with no IRQ.\n");
-		return -ENODEV;
-	}
-	irq = res->start;
-
-	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
-	if (!hcd)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "Found HC with no register addr.\n");
-		retval = -ENODEV;
-		goto err1;
-	}
-
-	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_size(res);
-
-	hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
-	if (hcd->regs == NULL) {
-		dev_dbg(dev, "error mapping memory\n");
-		retval = -EFAULT;
-		goto err1;
-	}
-
-	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
-	if (retval == 0)
-		return retval;
-
-err1:
-	usb_put_hcd(hcd);
-
-	return retval;
-}
-
-static int cns3xxx_ehci_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_remove_hcd(hcd);
-
-	/*
-	 * EHCI and OHCI share the same clock and power,
-	 * resetting twice would cause the 1st controller been reset.
-	 * Therefore only do power up  at the first up device, and
-	 * power down at the last down device.
-	 */
-	if (atomic_dec_return(&usb_pwr_ref) == 0)
-		cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
-
-	usb_put_hcd(hcd);
-
-	platform_set_drvdata(pdev, NULL);
-
-	return 0;
-}
-
-MODULE_ALIAS("platform:cns3xxx-ehci");
-
-static struct platform_driver cns3xxx_ehci_driver = {
-	.probe = cns3xxx_ehci_probe,
-	.remove = cns3xxx_ehci_remove,
-	.driver = {
-		.name = "cns3xxx-ehci",
-	},
-};
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 1599806..70b496d 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -18,21 +18,6 @@
 
 /* this file is part of ehci-hcd.c */
 
-#define ehci_dbg(ehci, fmt, args...) \
-	dev_dbg (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
-#define ehci_err(ehci, fmt, args...) \
-	dev_err (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
-#define ehci_info(ehci, fmt, args...) \
-	dev_info (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
-#define ehci_warn(ehci, fmt, args...) \
-	dev_warn (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
-
-#ifdef VERBOSE_DEBUG
-#	define ehci_vdbg ehci_dbg
-#else
-	static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {}
-#endif
-
 #ifdef	DEBUG
 
 /* check the values in the HCSPARAMS register
@@ -352,11 +337,6 @@ static int debug_async_open(struct inode *, struct file *);
 static int debug_periodic_open(struct inode *, struct file *);
 static int debug_registers_open(struct inode *, struct file *);
 static int debug_async_open(struct inode *, struct file *);
-static ssize_t debug_lpm_read(struct file *file, char __user *user_buf,
-				   size_t count, loff_t *ppos);
-static ssize_t debug_lpm_write(struct file *file, const char __user *buffer,
-			      size_t count, loff_t *ppos);
-static int debug_lpm_close(struct inode *inode, struct file *file);
 
 static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);
 static int debug_close(struct inode *, struct file *);
@@ -382,14 +362,6 @@ static const struct file_operations debug_registers_fops = {
 	.release	= debug_close,
 	.llseek		= default_llseek,
 };
-static const struct file_operations debug_lpm_fops = {
-	.owner		= THIS_MODULE,
-	.open		= simple_open,
-	.read		= debug_lpm_read,
-	.write		= debug_lpm_write,
-	.release	= debug_lpm_close,
-	.llseek		= noop_llseek,
-};
 
 static struct dentry *ehci_debug_root;
 
@@ -971,86 +943,6 @@ static int debug_registers_open(struct inode *inode, struct file *file)
 	return file->private_data ? 0 : -ENOMEM;
 }
 
-static int debug_lpm_close(struct inode *inode, struct file *file)
-{
-	return 0;
-}
-
-static ssize_t debug_lpm_read(struct file *file, char __user *user_buf,
-				   size_t count, loff_t *ppos)
-{
-	/* TODO: show lpm stats */
-	return 0;
-}
-
-static ssize_t debug_lpm_write(struct file *file, const char __user *user_buf,
-			      size_t count, loff_t *ppos)
-{
-	struct usb_hcd		*hcd;
-	struct ehci_hcd		*ehci;
-	char buf[50];
-	size_t len;
-	u32 temp;
-	unsigned long port;
-	u32 __iomem	*portsc ;
-	u32 params;
-
-	hcd = bus_to_hcd(file->private_data);
-	ehci = hcd_to_ehci(hcd);
-
-	len = min(count, sizeof(buf) - 1);
-	if (copy_from_user(buf, user_buf, len))
-		return -EFAULT;
-	buf[len] = '\0';
-	if (len > 0 && buf[len - 1] == '\n')
-		buf[len - 1] = '\0';
-
-	if (strncmp(buf, "enable", 5) == 0) {
-		if (strict_strtoul(buf + 7, 10, &port))
-			return -EINVAL;
-		params = ehci_readl(ehci, &ehci->caps->hcs_params);
-		if (port > HCS_N_PORTS(params)) {
-			ehci_dbg(ehci, "ERR: LPM on bad port %lu\n", port);
-			return -ENODEV;
-		}
-		portsc = &ehci->regs->port_status[port-1];
-		temp = ehci_readl(ehci, portsc);
-		if (!(temp & PORT_DEV_ADDR)) {
-			ehci_dbg(ehci, "LPM: no device attached\n");
-			return -ENODEV;
-		}
-		temp |= PORT_LPM;
-		ehci_writel(ehci, temp, portsc);
-		printk(KERN_INFO "force enable LPM for port %lu\n", port);
-	} else if (strncmp(buf, "hird=", 5) == 0) {
-		unsigned long hird;
-		if (strict_strtoul(buf + 5, 16, &hird))
-			return -EINVAL;
-		printk(KERN_INFO "setting hird %s %lu\n", buf + 6, hird);
-		ehci->command = (ehci->command & ~CMD_HIRD) | (hird << 24);
-		ehci_writel(ehci, ehci->command, &ehci->regs->command);
-	} else if (strncmp(buf, "disable", 7) == 0) {
-		if (strict_strtoul(buf + 8, 10, &port))
-			return -EINVAL;
-		params = ehci_readl(ehci, &ehci->caps->hcs_params);
-		if (port > HCS_N_PORTS(params)) {
-			ehci_dbg(ehci, "ERR: LPM off bad port %lu\n", port);
-			return -ENODEV;
-		}
-		portsc = &ehci->regs->port_status[port-1];
-		temp = ehci_readl(ehci, portsc);
-		if (!(temp & PORT_DEV_ADDR)) {
-			ehci_dbg(ehci, "ERR: no device attached\n");
-			return -ENODEV;
-		}
-		temp &= ~PORT_LPM;
-		ehci_writel(ehci, temp, portsc);
-		printk(KERN_INFO "disabled LPM for port %lu\n", port);
-	} else
-		return -EOPNOTSUPP;
-	return count;
-}
-
 static inline void create_debug_files (struct ehci_hcd *ehci)
 {
 	struct usb_bus *bus = &ehci_to_hcd(ehci)->self;
@@ -1071,10 +963,6 @@ static inline void create_debug_files (struct ehci_hcd *ehci)
 						    &debug_registers_fops))
 		goto file_error;
 
-	if (!debugfs_create_file("lpm", S_IRUGO|S_IWUSR, ehci->debug_dir, bus,
-						    &debug_lpm_fops))
-		goto file_error;
-
 	return;
 
 file_error:
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 0d2f35c..fd9b542 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -349,7 +349,6 @@ static int ehci_fsl_reinit(struct ehci_hcd *ehci)
 {
 	if (ehci_fsl_usb_setup(ehci))
 		return -EINVAL;
-	ehci_port_power(ehci, 0);
 
 	return 0;
 }
diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c
index 3180cb3..1fc8929 100644
--- a/drivers/usb/host/ehci-grlib.c
+++ b/drivers/usb/host/ehci-grlib.c
@@ -34,22 +34,6 @@
 
 #define GRUSBHC_HCIVERSION 0x0100 /* Known value of cap. reg. HCIVERSION */
 
-/* called during probe() after chip reset completes */
-static int ehci_grlib_setup(struct usb_hcd *hcd)
-{
-	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
-	int		retval;
-
-	retval = ehci_setup(hcd);
-	if (retval)
-		return retval;
-
-	ehci_port_power(ehci, 1);
-
-	return retval;
-}
-
-
 static const struct hc_driver ehci_grlib_hc_driver = {
 	.description		= hcd_name,
 	.product_desc		= "GRLIB GRUSBHC EHCI",
@@ -64,7 +48,7 @@ static const struct hc_driver ehci_grlib_hc_driver = {
 	/*
 	 * basic lifecycle operations
 	 */
-	.reset			= ehci_grlib_setup,
+	.reset			= ehci_setup,
 	.start			= ehci_run,
 	.stop			= ehci_stop,
 	.shutdown		= ehci_shutdown,
@@ -98,7 +82,7 @@ static const struct hc_driver ehci_grlib_hc_driver = {
 };
 
 
-static int __devinit ehci_hcd_grlib_probe(struct platform_device *op)
+static int ehci_hcd_grlib_probe(struct platform_device *op)
 {
 	struct device_node *dn = op->dev.of_node;
 	struct usb_hcd *hcd;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 6bf6c42..c97503b 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -39,7 +39,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
-#include <linux/uaccess.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -108,19 +107,39 @@ static bool ignore_oc = 0;
 module_param (ignore_oc, bool, S_IRUGO);
 MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
 
-/* for link power management(LPM) feature */
-static unsigned int hird;
-module_param(hird, int, S_IRUGO);
-MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
-
 #define	INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
 
 /*-------------------------------------------------------------------------*/
 
 #include "ehci.h"
-#include "ehci-dbg.c"
 #include "pci-quirks.h"
 
+/*
+ * The MosChip MCS9990 controller updates its microframe counter
+ * a little before the frame counter, and occasionally we will read
+ * the invalid intermediate value.  Avoid problems by checking the
+ * microframe number (the low-order 3 bits); if they are 0 then
+ * re-read the register to get the correct value.
+ */
+static unsigned ehci_moschip_read_frame_index(struct ehci_hcd *ehci)
+{
+	unsigned uf;
+
+	uf = ehci_readl(ehci, &ehci->regs->frame_index);
+	if (unlikely((uf & 7) == 0))
+		uf = ehci_readl(ehci, &ehci->regs->frame_index);
+	return uf;
+}
+
+static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
+{
+	if (ehci->frame_index_bug)
+		return ehci_moschip_read_frame_index(ehci);
+	return ehci_readl(ehci, &ehci->regs->frame_index);
+}
+
+#include "ehci-dbg.c"
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -293,7 +312,6 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
 
 #include "ehci-timer.c"
 #include "ehci-hub.c"
-#include "ehci-lpm.c"
 #include "ehci-mem.c"
 #include "ehci-q.c"
 #include "ehci-sched.c"
@@ -353,24 +371,6 @@ static void ehci_shutdown(struct usb_hcd *hcd)
 	hrtimer_cancel(&ehci->hrtimer);
 }
 
-static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
-{
-	unsigned port;
-
-	if (!HCS_PPC (ehci->hcs_params))
-		return;
-
-	ehci_dbg (ehci, "...power%s ports...\n", is_on ? "up" : "down");
-	for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; )
-		(void) ehci_hub_control(ehci_to_hcd(ehci),
-				is_on ? SetPortFeature : ClearPortFeature,
-				USB_PORT_FEAT_POWER,
-				port--, NULL, 0);
-	/* Flush those writes */
-	ehci_readl(ehci, &ehci->regs->command);
-	msleep(20);
-}
-
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -503,7 +503,7 @@ static int ehci_init(struct usb_hcd *hcd)
 
 	/* controllers may cache some of the periodic schedule ... */
 	if (HCC_ISOC_CACHE(hcc_params))		// full frame cache
-		ehci->i_thresh = 2 + 8;
+		ehci->i_thresh = 0;
 	else					// N microframes cached
 		ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
 
@@ -555,17 +555,6 @@ static int ehci_init(struct usb_hcd *hcd)
 		temp &= ~(3 << 2);
 		temp |= (EHCI_TUNE_FLS << 2);
 	}
-	if (HCC_LPM(hcc_params)) {
-		/* support link power management EHCI 1.1 addendum */
-		ehci_dbg(ehci, "support lpm\n");
-		ehci->has_lpm = 1;
-		if (hird > 0xf) {
-			ehci_dbg(ehci, "hird %d invalid, use default 0",
-			hird);
-			hird = 0;
-		}
-		temp |= hird << 24;
-	}
 	ehci->command = temp;
 
 	/* Accept arbitrarily long scatter-gather lists */
@@ -660,7 +649,7 @@ static int ehci_run (struct usb_hcd *hcd)
 	return 0;
 }
 
-static int ehci_setup(struct usb_hcd *hcd)
+int ehci_setup(struct usb_hcd *hcd)
 {
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	int retval;
@@ -691,6 +680,7 @@ static int ehci_setup(struct usb_hcd *hcd)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ehci_setup);
 
 /*-------------------------------------------------------------------------*/
 
@@ -1096,7 +1086,7 @@ static int ehci_get_frame (struct usb_hcd *hcd)
 
 /* These routines handle the generic parts of controller suspend/resume */
 
-static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 
@@ -1119,9 +1109,10 @@ static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ehci_suspend);
 
 /* Returns 0 if power was preserved, 1 if power was lost */
-static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
+int ehci_resume(struct usb_hcd *hcd, bool hibernated)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 
@@ -1177,33 +1168,83 @@ static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
 	ehci->rh_state = EHCI_RH_SUSPENDED;
 	spin_unlock_irq(&ehci->lock);
 
-	/* here we "know" root ports should always stay powered */
-	ehci_port_power(ehci, 1);
-
 	return 1;
 }
+EXPORT_SYMBOL_GPL(ehci_resume);
 
 #endif
 
 /*-------------------------------------------------------------------------*/
 
 /*
- * The EHCI in ChipIdea HDRC cannot be a separate module or device,
- * because its registers (and irq) are shared between host/gadget/otg
- * functions  and in order to facilitate role switching we cannot
- * give the ehci driver exclusive access to those.
+ * Generic structure: This gets copied for platform drivers so that
+ * individual entries can be overridden as needed.
  */
-#ifndef CHIPIDEA_EHCI
+
+static const struct hc_driver ehci_hc_driver = {
+	.description =		hcd_name,
+	.product_desc =		"EHCI Host Controller",
+	.hcd_priv_size =	sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq =			ehci_irq,
+	.flags =		HCD_MEMORY | HCD_USB2,
+
+	/*
+	 * 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,
+	.clear_tt_buffer_complete =	ehci_clear_tt_buffer_complete,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number =	ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data =	ehci_hub_status_data,
+	.hub_control =		ehci_hub_control,
+	.bus_suspend =		ehci_bus_suspend,
+	.bus_resume =		ehci_bus_resume,
+	.relinquish_port =	ehci_relinquish_port,
+	.port_handed_over =	ehci_port_handed_over,
+};
+
+void ehci_init_driver(struct hc_driver *drv,
+		const struct ehci_driver_overrides *over)
+{
+	/* Copy the generic table to drv and then apply the overrides */
+	*drv = ehci_hc_driver;
+
+	if (over) {
+		drv->hcd_priv_size += over->extra_priv_size;
+		if (over->reset)
+			drv->reset = over->reset;
+	}
+}
+EXPORT_SYMBOL_GPL(ehci_init_driver);
+
+/*-------------------------------------------------------------------------*/
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR (DRIVER_AUTHOR);
 MODULE_LICENSE ("GPL");
 
-#ifdef CONFIG_PCI
-#include "ehci-pci.c"
-#define	PCI_DRIVER		ehci_pci_driver
-#endif
-
 #ifdef CONFIG_USB_EHCI_FSL
 #include "ehci-fsl.c"
 #define	PLATFORM_DRIVER		ehci_fsl_driver
@@ -1219,11 +1260,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ehci_hcd_sh_driver
 #endif
 
-#ifdef CONFIG_MIPS_ALCHEMY
-#include "ehci-au1xxx.c"
-#define	PLATFORM_DRIVER		ehci_hcd_au1xxx_driver
-#endif
-
 #ifdef CONFIG_USB_EHCI_HCD_OMAP
 #include "ehci-omap.c"
 #define        PLATFORM_DRIVER         ehci_hcd_omap_driver
@@ -1249,11 +1285,6 @@ MODULE_LICENSE ("GPL");
 #define	PLATFORM_DRIVER		ehci_orion_driver
 #endif
 
-#ifdef CONFIG_ARCH_IXP4XX
-#include "ehci-ixp4xx.c"
-#define	PLATFORM_DRIVER		ixp4xx_ehci_driver
-#endif
-
 #ifdef CONFIG_USB_W90X900_EHCI
 #include "ehci-w90x900.c"
 #define	PLATFORM_DRIVER		ehci_hcd_w90x900_driver
@@ -1269,11 +1300,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ehci_octeon_driver
 #endif
 
-#ifdef CONFIG_USB_CNS3XXX_EHCI
-#include "ehci-cns3xxx.c"
-#define PLATFORM_DRIVER		cns3xxx_ehci_driver
-#endif
-
 #ifdef CONFIG_ARCH_VT8500
 #include "ehci-vt8500.c"
 #define	PLATFORM_DRIVER		vt8500_ehci_driver
@@ -1314,34 +1340,23 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ehci_grlib_driver
 #endif
 
-#ifdef CONFIG_CPU_XLR
-#include "ehci-xls.c"
-#define PLATFORM_DRIVER		ehci_xls_driver
-#endif
-
 #ifdef CONFIG_USB_EHCI_MV
 #include "ehci-mv.c"
 #define        PLATFORM_DRIVER         ehci_mv_driver
 #endif
 
-#ifdef CONFIG_MACH_LOONGSON1
-#include "ehci-ls1x.c"
-#define PLATFORM_DRIVER		ehci_ls1x_driver
-#endif
-
 #ifdef CONFIG_MIPS_SEAD3
 #include "ehci-sead3.c"
 #define	PLATFORM_DRIVER		ehci_hcd_sead3_driver
 #endif
 
-#ifdef CONFIG_USB_EHCI_HCD_PLATFORM
-#include "ehci-platform.c"
-#define PLATFORM_DRIVER		ehci_platform_driver
-#endif
-
-#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
-    !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
-    !defined(XILINX_OF_PLATFORM_DRIVER)
+#if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \
+	!IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
+	!defined(CONFIG_USB_CHIPIDEA_HOST) && \
+	!defined(PLATFORM_DRIVER) && \
+	!defined(PS3_SYSTEM_BUS_DRIVER) && \
+	!defined(OF_PLATFORM_DRIVER) && \
+	!defined(XILINX_OF_PLATFORM_DRIVER)
 #error "missing bus glue for ehci-hcd"
 #endif
 
@@ -1378,12 +1393,6 @@ static int __init ehci_hcd_init(void)
 		goto clean0;
 #endif
 
-#ifdef PCI_DRIVER
-	retval = pci_register_driver(&PCI_DRIVER);
-	if (retval < 0)
-		goto clean1;
-#endif
-
 #ifdef PS3_SYSTEM_BUS_DRIVER
 	retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
 	if (retval < 0)
@@ -1415,10 +1424,6 @@ clean3:
 	ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 clean2:
 #endif
-#ifdef PCI_DRIVER
-	pci_unregister_driver(&PCI_DRIVER);
-clean1:
-#endif
 #ifdef PLATFORM_DRIVER
 	platform_driver_unregister(&PLATFORM_DRIVER);
 clean0:
@@ -1444,9 +1449,6 @@ static void __exit ehci_hcd_cleanup(void)
 #ifdef PLATFORM_DRIVER
 	platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
-#ifdef PCI_DRIVER
-	pci_unregister_driver(&PCI_DRIVER);
-#endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
 	ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
@@ -1456,5 +1458,3 @@ static void __exit ehci_hcd_cleanup(void)
 	clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
 }
 module_exit(ehci_hcd_cleanup);
-
-#endif /* CHIPIDEA_EHCI */
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 914ce93..4ccb97c 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -56,6 +56,19 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
 	if (!ehci->owned_ports)
 		return;
 
+	/* Make sure the ports are powered */
+	port = HCS_N_PORTS(ehci->hcs_params);
+	while (port--) {
+		if (test_bit(port, &ehci->owned_ports)) {
+			reg = &ehci->regs->port_status[port];
+			status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
+			if (!(status & PORT_POWER)) {
+				status |= PORT_POWER;
+				ehci_writel(ehci, status, reg);
+			}
+		}
+	}
+
 	/* Give the connections some time to appear */
 	msleep(20);
 
@@ -384,11 +397,24 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 	ehci_writel(ehci, ehci->command, &ehci->regs->command);
 	ehci->rh_state = EHCI_RH_RUNNING;
 
-	/* Some controller/firmware combinations need a delay during which
-	 * they set up the port statuses.  See Bugzilla #8190. */
-	spin_unlock_irq(&ehci->lock);
-	msleep(8);
-	spin_lock_irq(&ehci->lock);
+	/*
+	 * According to Bugzilla #8190, the port status for some controllers
+	 * will be wrong without a delay. At their wrong status, the port
+	 * is enabled, but not suspended neither resumed.
+	 */
+	i = HCS_N_PORTS(ehci->hcs_params);
+	while (i--) {
+		temp = ehci_readl(ehci, &ehci->regs->port_status[i]);
+		if ((temp & PORT_PE) &&
+				!(temp & (PORT_SUSPEND | PORT_RESUME))) {
+			ehci_dbg(ehci, "Port status(0x%x) is wrong\n", temp);
+			spin_unlock_irq(&ehci->lock);
+			msleep(8);
+			spin_lock_irq(&ehci->lock);
+			break;
+		}
+	}
+
 	if (ehci->shutdown)
 		goto shutdown;
 
@@ -764,11 +790,6 @@ static int ehci_hub_control (
 						status_reg);
 			break;
 		case USB_PORT_FEAT_C_CONNECTION:
-			if (ehci->has_lpm) {
-				/* clear PORTSC bits on disconnect */
-				temp &= ~PORT_LPM;
-				temp &= ~PORT_DEV_ADDR;
-			}
 			ehci_writel(ehci, temp | PORT_CSC, status_reg);
 			break;
 		case USB_PORT_FEAT_C_OVER_CURRENT:
@@ -1088,8 +1109,7 @@ error_exit:
 	return retval;
 }
 
-static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd,
-		int portnum)
+static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 
@@ -1098,8 +1118,7 @@ static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd,
 	set_owner(ehci, --portnum, PORT_OWNER);
 }
 
-static int __maybe_unused ehci_port_handed_over(struct usb_hcd *hcd,
-		int portnum)
+static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 	u32 __iomem		*reg;
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
deleted file mode 100644
index f224c0a..0000000
--- a/drivers/usb/host/ehci-ixp4xx.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * IXP4XX EHCI Host Controller Driver
- *
- * Author: Vladimir Barinov <vbarinov@embeddedalley.com>
- *
- * Based on "ehci-fsl.c" by Randy Vinson <rvinson@mvista.com>
- *
- * 2007 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/platform_device.h>
-
-static int ixp4xx_ehci_init(struct usb_hcd *hcd)
-{
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	int retval = 0;
-
-	ehci->big_endian_desc = 1;
-	ehci->big_endian_mmio = 1;
-
-	ehci->caps = hcd->regs + 0x100;
-
-	hcd->has_tt = 1;
-
-	retval = ehci_setup(hcd);
-	if (retval)
-		return retval;
-
-	ehci_port_power(ehci, 0);
-
-	return retval;
-}
-
-static const struct hc_driver ixp4xx_ehci_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "IXP4XX EHCI Host Controller",
-	.hcd_priv_size		= sizeof(struct ehci_hcd),
-	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
-	.reset			= ixp4xx_ehci_init,
-	.start			= ehci_run,
-	.stop			= ehci_stop,
-	.shutdown		= ehci_shutdown,
-	.urb_enqueue		= ehci_urb_enqueue,
-	.urb_dequeue		= ehci_urb_dequeue,
-	.endpoint_disable	= ehci_endpoint_disable,
-	.endpoint_reset		= ehci_endpoint_reset,
-	.get_frame_number	= ehci_get_frame,
-	.hub_status_data	= ehci_hub_status_data,
-	.hub_control		= ehci_hub_control,
-#if defined(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 ixp4xx_ehci_probe(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd;
-	const struct hc_driver *driver = &ixp4xx_ehci_hc_driver;
-	struct resource *res;
-	int irq;
-	int retval;
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		dev_err(&pdev->dev,
-			"Found HC with no IRQ. Check %s setup!\n",
-			dev_name(&pdev->dev));
-		return -ENODEV;
-	}
-	irq = res->start;
-
-	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
-	if (!hcd) {
-		retval = -ENOMEM;
-		goto fail_create_hcd;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev,
-			"Found HC with no register addr. Check %s setup!\n",
-			dev_name(&pdev->dev));
-		retval = -ENODEV;
-		goto fail_request_resource;
-	}
-	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_size(res);
-
-	hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
-	if (hcd->regs == NULL) {
-		dev_dbg(&pdev->dev, "error mapping memory\n");
-		retval = -EFAULT;
-		goto fail_request_resource;
-	}
-
-	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
-	if (retval)
-		goto fail_request_resource;
-
-	return retval;
-
-fail_request_resource:
-	usb_put_hcd(hcd);
-fail_create_hcd:
-	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
-	return retval;
-}
-
-static int ixp4xx_ehci_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_remove_hcd(hcd);
-	usb_put_hcd(hcd);
-
-	return 0;
-}
-
-MODULE_ALIAS("platform:ixp4xx-ehci");
-
-static struct platform_driver ixp4xx_ehci_driver = {
-	.probe = ixp4xx_ehci_probe,
-	.remove = ixp4xx_ehci_remove,
-	.driver = {
-		.name = "ixp4xx-ehci",
-	},
-};
diff --git a/drivers/usb/host/ehci-lpm.c b/drivers/usb/host/ehci-lpm.c
deleted file mode 100644
index 2111627..0000000
--- a/drivers/usb/host/ehci-lpm.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* ehci-lpm.c EHCI HCD LPM support code
- * Copyright (c) 2008 - 2010,  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 version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/* this file is part of ehci-hcd.c */
-static int __maybe_unused ehci_lpm_set_da(struct ehci_hcd *ehci,
-	int dev_addr, int port_num)
-{
-	u32 __iomem portsc;
-
-	ehci_dbg(ehci, "set dev address %d for port %d\n", dev_addr, port_num);
-	if (port_num > HCS_N_PORTS(ehci->hcs_params)) {
-		ehci_dbg(ehci, "invalid port number %d\n", port_num);
-		return -ENODEV;
-	}
-	portsc = ehci_readl(ehci, &ehci->regs->port_status[port_num-1]);
-	portsc &= ~PORT_DEV_ADDR;
-	portsc |= dev_addr<<25;
-	ehci_writel(ehci, portsc, &ehci->regs->port_status[port_num-1]);
-	return 0;
-}
-
-/*
- * this function is used to check if the device support LPM
- * if yes, mark the PORTSC register with PORT_LPM bit
- */
-static int __maybe_unused ehci_lpm_check(struct ehci_hcd *ehci, int port)
-{
-	u32 __iomem	*portsc ;
-	u32 val32;
-	int retval;
-
-	portsc = &ehci->regs->port_status[port-1];
-	val32 = ehci_readl(ehci, portsc);
-	if (!(val32 & PORT_DEV_ADDR)) {
-		ehci_dbg(ehci, "LPM: no device attached\n");
-		return -ENODEV;
-	}
-	val32 |= PORT_LPM;
-	ehci_writel(ehci, val32, portsc);
-	msleep(5);
-	val32 |= PORT_SUSPEND;
-	ehci_dbg(ehci, "Sending LPM 0x%08x to port %d\n", val32, port);
-	ehci_writel(ehci, val32, portsc);
-	/* wait for ACK */
-	msleep(10);
-	retval = handshake(ehci, &ehci->regs->port_status[port-1], PORT_SSTS,
-			PORTSC_SUSPEND_STS_ACK, 125);
-	dbg_port(ehci, "LPM", port, val32);
-	if (retval != -ETIMEDOUT) {
-		ehci_dbg(ehci, "LPM: device ACK for LPM\n");
-		val32 |= PORT_LPM;
-		/*
-		 * now device should be in L1 sleep, let's wake up the device
-		 * so that we can complete enumeration.
-		 */
-		ehci_writel(ehci, val32, portsc);
-		msleep(10);
-		val32 |= PORT_RESUME;
-		ehci_writel(ehci, val32, portsc);
-	} else {
-		ehci_dbg(ehci, "LPM: device does not ACK, disable LPM %d\n",
-			retval);
-		val32 &= ~PORT_LPM;
-		retval = -ETIMEDOUT;
-		ehci_writel(ehci, val32, portsc);
-	}
-
-	return retval;
-}
diff --git a/drivers/usb/host/ehci-ls1x.c b/drivers/usb/host/ehci-ls1x.c
deleted file mode 100644
index aa0f328..0000000
--- a/drivers/usb/host/ehci-ls1x.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- *  Bus Glue for Loongson LS1X built-in EHCI controller.
- *
- *  Copyright (c) 2012 Zhang, Keguang <keguang.zhang@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/platform_device.h>
-
-static int ehci_ls1x_reset(struct usb_hcd *hcd)
-{
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	int ret;
-
-	ehci->caps = hcd->regs;
-
-	ret = ehci_setup(hcd);
-	if (ret)
-		return ret;
-
-	ehci_port_power(ehci, 0);
-
-	return 0;
-}
-
-static const struct hc_driver ehci_ls1x_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "LOONGSON1 EHCI",
-	.hcd_priv_size		= sizeof(struct ehci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.reset			= ehci_ls1x_reset,
-	.start			= ehci_run,
-	.stop			= ehci_stop,
-	.shutdown		= ehci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue		= ehci_urb_enqueue,
-	.urb_dequeue		= ehci_urb_dequeue,
-	.endpoint_disable	= ehci_endpoint_disable,
-	.endpoint_reset		= ehci_endpoint_reset,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number	= ehci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data	= ehci_hub_status_data,
-	.hub_control		= ehci_hub_control,
-	.relinquish_port	= ehci_relinquish_port,
-	.port_handed_over	= ehci_port_handed_over,
-
-	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
-};
-
-static int ehci_hcd_ls1x_probe(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd;
-	struct resource *res;
-	int irq;
-	int ret;
-
-	pr_debug("initializing loongson1 ehci USB Controller\n");
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		dev_err(&pdev->dev,
-			"Found HC with no IRQ. Check %s setup!\n",
-			dev_name(&pdev->dev));
-		return -ENODEV;
-	}
-	irq = res->start;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev,
-			"Found HC with no register addr. Check %s setup!\n",
-			dev_name(&pdev->dev));
-		return -ENODEV;
-	}
-
-	hcd = usb_create_hcd(&ehci_ls1x_hc_driver, &pdev->dev,
-				dev_name(&pdev->dev));
-	if (!hcd)
-		return -ENOMEM;
-	hcd->rsrc_start	= res->start;
-	hcd->rsrc_len	= resource_size(res);
-
-	hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
-	if (hcd->regs == NULL) {
-		dev_dbg(&pdev->dev, "error mapping memory\n");
-		ret = -EFAULT;
-		goto err_put_hcd;
-	}
-
-	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
-	if (ret)
-		goto err_put_hcd;
-
-	return ret;
-
-err_put_hcd:
-	usb_put_hcd(hcd);
-	return ret;
-}
-
-static int ehci_hcd_ls1x_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_remove_hcd(hcd);
-	usb_put_hcd(hcd);
-
-	return 0;
-}
-
-static struct platform_driver ehci_ls1x_driver = {
-	.probe = ehci_hcd_ls1x_probe,
-	.remove = ehci_hcd_ls1x_remove,
-	.shutdown = usb_hcd_platform_shutdown,
-	.driver = {
-		.name = "ls1x-ehci",
-		.owner	= THIS_MODULE,
-	},
-};
-
-MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ls1x-ehci");
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 4af4dc5..88a49c8 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -53,7 +53,6 @@ static int ehci_msm_reset(struct usb_hcd *hcd)
 	/* Disable streaming mode and select host mode */
 	writel(0x13, USB_USBMODE);
 
-	ehci_port_power(ehci, 1);
 	return 0;
 }
 
@@ -174,7 +173,7 @@ put_hcd:
 	return ret;
 }
 
-static int __devexit ehci_msm_remove(struct platform_device *pdev)
+static int ehci_msm_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
@@ -221,7 +220,7 @@ static const struct dev_pm_ops ehci_msm_dev_pm_ops = {
 
 static struct platform_driver ehci_msm_driver = {
 	.probe	= ehci_msm_probe,
-	.remove	= __devexit_p(ehci_msm_remove),
+	.remove	= ehci_msm_remove,
 	.driver = {
 		   .name = "msm_hsusb_host",
 		   .pm = &ehci_msm_dev_pm_ops,
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index 4a08fc0..ec7f5d2 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -24,7 +24,6 @@
 #include <linux/usb/ulpi.h>
 #include <linux/slab.h>
 
-#include <mach/hardware.h>
 #include <linux/platform_data/usb-ehci-mxc.h>
 
 #include <asm/mach-types.h>
@@ -39,17 +38,9 @@ struct ehci_mxc_priv {
 /* called during probe() after chip reset completes */
 static int ehci_mxc_setup(struct usb_hcd *hcd)
 {
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	int retval;
-
 	hcd->has_tt = 1;
 
-	retval = ehci_setup(hcd);
-	if (retval)
-		return retval;
-
-	ehci_port_power(ehci, 0);
-	return 0;
+	return ehci_setup(hcd);
 }
 
 static const struct hc_driver ehci_mxc_hc_driver = {
diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c
index ba26957a..a89750f 100644
--- a/drivers/usb/host/ehci-octeon.c
+++ b/drivers/usb/host/ehci-octeon.c
@@ -159,9 +159,6 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, hcd);
 
-	/* root ports should always stay powered */
-	ehci_port_power(ehci, 1);
-
 	return 0;
 err3:
 	ehci_octeon_stop();
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index d7fe287..ac17a7c 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -39,12 +39,13 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/usb/ulpi.h>
-#include <plat/usb.h>
 #include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
 #include <linux/gpio.h>
 #include <linux/clk.h>
 
+#include <linux/platform_data/usb-omap.h>
+
 /* EHCI Register Set */
 #define EHCI_INSNREG04					(0xA0)
 #define EHCI_INSNREG04_DISABLE_UNSUSPEND		(1 << 5)
@@ -146,9 +147,6 @@ static int omap_ehci_init(struct usb_hcd *hcd)
 			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
 	}
 
-	/* root ports should always stay powered */
-	ehci_port_power(ehci, 1);
-
 	return rc;
 }
 
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 9c2717d..a7d1f5b 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -14,6 +14,9 @@
 #include <linux/mbus.h>
 #include <linux/clk.h>
 #include <linux/platform_data/usb-ehci-orion.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
 
 #define rdl(off)	__raw_readl(hcd->regs + (off))
 #define wrl(off, val)	__raw_writel((val), hcd->regs + (off))
@@ -101,20 +104,6 @@ static void orion_usb_phy_v1_setup(struct usb_hcd *hcd)
 	wrl(USB_MODE, 0x13);
 }
 
-static int ehci_orion_setup(struct usb_hcd *hcd)
-{
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	int retval;
-
-	retval = ehci_setup(hcd);
-	if (retval)
-		return retval;
-
-	ehci_port_power(ehci, 0);
-
-	return retval;
-}
-
 static const struct hc_driver ehci_orion_hc_driver = {
 	.description = hcd_name,
 	.product_desc = "Marvell Orion EHCI",
@@ -129,7 +118,7 @@ static const struct hc_driver ehci_orion_hc_driver = {
 	/*
 	 * basic lifecycle operations
 	 */
-	.reset = ehci_orion_setup,
+	.reset = ehci_setup,
 	.start = ehci_run,
 	.stop = ehci_stop,
 	.shutdown = ehci_shutdown,
@@ -160,7 +149,7 @@ static const struct hc_driver ehci_orion_hc_driver = {
 	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
 };
 
-static void __devinit
+static void
 ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
 			     const struct mbus_dram_target_info *dram)
 {
@@ -181,7 +170,9 @@ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
 	}
 }
 
-static int __devinit ehci_orion_drv_probe(struct platform_device *pdev)
+static u64 ehci_orion_dma_mask = DMA_BIT_MASK(32);
+
+static int ehci_orion_drv_probe(struct platform_device *pdev)
 {
 	struct orion_ehci_data *pd = pdev->dev.platform_data;
 	const struct mbus_dram_target_info *dram;
@@ -191,13 +182,17 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev)
 	struct clk *clk;
 	void __iomem *regs;
 	int irq, err;
+	enum orion_ehci_phy_ver phy_version;
 
 	if (usb_disabled())
 		return -ENODEV;
 
 	pr_debug("Initializing Orion-SoC USB Host Controller\n");
 
-	irq = platform_get_irq(pdev, 0);
+	if (pdev->dev.of_node)
+		irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+	else
+		irq = platform_get_irq(pdev, 0);
 	if (irq <= 0) {
 		dev_err(&pdev->dev,
 			"Found HC with no IRQ. Check %s setup!\n",
@@ -215,6 +210,14 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev)
 		goto err1;
 	}
 
+	/*
+	 * 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 have dma capability bindings this can go away.
+	 */
+	if (!pdev->dev.dma_mask)
+		pdev->dev.dma_mask = &ehci_orion_dma_mask;
+
 	if (!request_mem_region(res->start, resource_size(res),
 				ehci_orion_hc_driver.description)) {
 		dev_dbg(&pdev->dev, "controller already in use\n");
@@ -262,7 +265,12 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev)
 	/*
 	 * setup Orion USB controller.
 	 */
-	switch (pd->phy_version) {
+	if (pdev->dev.of_node)
+		phy_version = EHCI_PHY_NA;
+	else
+		phy_version = pd->phy_version;
+
+	switch (phy_version) {
 	case EHCI_PHY_NA:	/* dont change USB phy settings */
 		break;
 	case EHCI_PHY_ORION:
@@ -317,9 +325,19 @@ static int __exit ehci_orion_drv_remove(struct platform_device *pdev)
 
 MODULE_ALIAS("platform:orion-ehci");
 
+static const struct of_device_id ehci_orion_dt_ids[] __devinitdata = {
+	{ .compatible = "marvell,orion-ehci", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids);
+
 static struct platform_driver ehci_orion_driver = {
 	.probe		= ehci_orion_drv_probe,
 	.remove		= __exit_p(ehci_orion_drv_remove),
 	.shutdown	= usb_hcd_platform_shutdown,
-	.driver.name	= "orion-ehci",
+	.driver = {
+		.name	= "orion-ehci",
+		.owner  = THIS_MODULE,
+		.of_match_table = of_match_ptr(ehci_orion_dt_ids),
+	},
 };
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 2cb7d37..dabb204 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -18,9 +18,18 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifndef CONFIG_PCI
-#error "This file is PCI bus glue.  CONFIG_PCI must be defined."
-#endif
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ehci.h"
+#include "pci-quirks.h"
+
+#define DRIVER_DESC "EHCI PCI platform driver"
+
+static const char hcd_name[] = "ehci-pci";
 
 /* defined here to avoid adding to pci_ids.h for single instance use */
 #define PCI_DEVICE_ID_INTEL_CE4100_USB	0x2e70
@@ -103,7 +112,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 		}
 		break;
 	case PCI_VENDOR_ID_INTEL:
-		ehci->fs_i_thresh = 1;
 		if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB)
 			hcd->has_tt = 1;
 		break;
@@ -203,11 +211,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 		break;
 	case PCI_VENDOR_ID_INTEL:
 		ehci->need_io_watchdog = 0;
-		if (pdev->device == 0x0806 || pdev->device == 0x0811
-				|| pdev->device == 0x0829) {
-			ehci_info(ehci, "disable lpm for langwell/penwell\n");
-			ehci->has_lpm = 0;
-		}
 		break;
 	case PCI_VENDOR_ID_NVIDIA:
 		switch (pdev->device) {
@@ -217,8 +220,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 		 * devices with PPCD enabled.
 		 */
 		case 0x0d9d:
-			ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89");
-			ehci->has_lpm = 0;
+			ehci_info(ehci, "disable ppcd for nvidia mcp89\n");
 			ehci->has_ppcd = 0;
 			ehci->command &= ~CMD_PPCEE;
 			break;
@@ -304,7 +306,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 		ehci_warn(ehci, "selective suspend/wakeup unavailable\n");
 #endif
 
-	ehci_port_power(ehci, 1);
 	retval = ehci_pci_reinit(ehci, pdev);
 done:
 	return retval;
@@ -323,18 +324,14 @@ done:
  * Also they depend on separate root hub suspend/resume.
  */
 
-static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
-{
-	return ehci_suspend(hcd, do_wakeup);
-}
-
 static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)
 {
 	return pdev->class == PCI_CLASS_SERIAL_USB_EHCI &&
 		pdev->vendor == PCI_VENDOR_ID_INTEL &&
 		(pdev->device == 0x1E26 ||
 		 pdev->device == 0x8C2D ||
-		 pdev->device == 0x8C26);
+		 pdev->device == 0x8C26 ||
+		 pdev->device == 0x9C26);
 }
 
 static void ehci_enable_xhci_companion(void)
@@ -378,76 +375,17 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
 		(void) ehci_pci_reinit(ehci, pdev);
 	return 0;
 }
-#endif
 
-static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
-{
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	int rc = 0;
-
-	if (!udev->parent) /* udev is root hub itself, impossible */
-		rc = -1;
-	/* we only support lpm device connected to root hub yet */
-	if (ehci->has_lpm && !udev->parent->parent) {
-		rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
-		if (!rc)
-			rc = ehci_lpm_check(ehci, udev->portnum);
-	}
-	return rc;
-}
+#else
 
-static const struct hc_driver ehci_pci_hc_driver = {
-	.description =		hcd_name,
-	.product_desc =		"EHCI Host Controller",
-	.hcd_priv_size =	sizeof(struct ehci_hcd),
+#define ehci_suspend		NULL
+#define ehci_pci_resume		NULL
+#endif	/* CONFIG_PM */
 
-	/*
-	 * generic hardware linkage
-	 */
-	.irq =			ehci_irq,
-	.flags =		HCD_MEMORY | HCD_USB2,
+static struct hc_driver __read_mostly ehci_pci_hc_driver;
 
-	/*
-	 * basic lifecycle operations
-	 */
+static const struct ehci_driver_overrides pci_overrides __initdata = {
 	.reset =		ehci_pci_setup,
-	.start =		ehci_run,
-#ifdef	CONFIG_PM
-	.pci_suspend =		ehci_pci_suspend,
-	.pci_resume =		ehci_pci_resume,
-#endif
-	.stop =			ehci_stop,
-	.shutdown =		ehci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue =		ehci_urb_enqueue,
-	.urb_dequeue =		ehci_urb_dequeue,
-	.endpoint_disable =	ehci_endpoint_disable,
-	.endpoint_reset =	ehci_endpoint_reset,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number =	ehci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data =	ehci_hub_status_data,
-	.hub_control =		ehci_hub_control,
-	.bus_suspend =		ehci_bus_suspend,
-	.bus_resume =		ehci_bus_resume,
-	.relinquish_port =	ehci_relinquish_port,
-	.port_handed_over =	ehci_port_handed_over,
-
-	/*
-	 * call back when device connected and addressed
-	 */
-	.update_device =	ehci_update_device,
-
-	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -480,3 +418,31 @@ static struct pci_driver ehci_pci_driver = {
 	},
 #endif
 };
+
+static int __init ehci_pci_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+	ehci_init_driver(&ehci_pci_hc_driver, &pci_overrides);
+
+	/* Entries for the PCI suspend/resume callbacks are special */
+	ehci_pci_hc_driver.pci_suspend = ehci_suspend;
+	ehci_pci_hc_driver.pci_resume = ehci_pci_resume;
+
+	return pci_register_driver(&ehci_pci_driver);
+}
+module_init(ehci_pci_init);
+
+static void __exit ehci_pci_cleanup(void)
+{
+	pci_unregister_driver(&ehci_pci_driver);
+}
+module_exit(ehci_pci_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("David Brownell");
+MODULE_AUTHOR("Alan Stern");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index 764e010..58fa0c9 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -18,9 +18,21 @@
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
+#include <linux/kernel.h>
+#include <linux/hrtimer.h>
+#include <linux/io.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
 #include <linux/usb/ehci_pdriver.h>
 
+#include "ehci.h"
+
+#define DRIVER_DESC "EHCI generic platform driver"
+
+static const char hcd_name[] = "ehci-platform";
+
 static int ehci_platform_reset(struct usb_hcd *hcd)
 {
 	struct platform_device *pdev = to_platform_device(hcd->self.controller);
@@ -38,47 +50,18 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
 	if (retval)
 		return retval;
 
-	if (pdata->port_power_on)
-		ehci_port_power(ehci, 1);
-	if (pdata->port_power_off)
-		ehci_port_power(ehci, 0);
-
+	if (pdata->no_io_watchdog)
+		ehci->need_io_watchdog = 0;
 	return 0;
 }
 
-static const struct hc_driver ehci_platform_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "Generic Platform EHCI Controller",
-	.hcd_priv_size		= sizeof(struct ehci_hcd),
-
-	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
-
-	.reset			= ehci_platform_reset,
-	.start			= ehci_run,
-	.stop			= ehci_stop,
-	.shutdown		= ehci_shutdown,
-
-	.urb_enqueue		= ehci_urb_enqueue,
-	.urb_dequeue		= ehci_urb_dequeue,
-	.endpoint_disable	= ehci_endpoint_disable,
-	.endpoint_reset		= ehci_endpoint_reset,
+static struct hc_driver __read_mostly ehci_platform_hc_driver;
 
-	.get_frame_number	= ehci_get_frame,
-
-	.hub_status_data	= ehci_hub_status_data,
-	.hub_control		= ehci_hub_control,
-#if defined(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 const struct ehci_driver_overrides platform_overrides __initdata = {
+	.reset =	ehci_platform_reset,
 };
 
-static int __devinit ehci_platform_probe(struct platform_device *dev)
+static int ehci_platform_probe(struct platform_device *dev)
 {
 	struct usb_hcd *hcd;
 	struct resource *res_mem;
@@ -96,12 +79,12 @@ static int __devinit ehci_platform_probe(struct platform_device *dev)
 
 	irq = platform_get_irq(dev, 0);
 	if (irq < 0) {
-		pr_err("no irq provided");
+		dev_err(&dev->dev, "no irq provided");
 		return irq;
 	}
 	res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
 	if (!res_mem) {
-		pr_err("no memory recourse provided");
+		dev_err(&dev->dev, "no memory resource provided");
 		return -ENXIO;
 	}
 
@@ -121,29 +104,19 @@ static int __devinit ehci_platform_probe(struct platform_device *dev)
 	hcd->rsrc_start = res_mem->start;
 	hcd->rsrc_len = resource_size(res_mem);
 
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		pr_err("controller already in use");
-		err = -EBUSY;
-		goto err_put_hcd;
-	}
-
-	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+	hcd->regs = devm_request_and_ioremap(&dev->dev, res_mem);
 	if (!hcd->regs) {
 		err = -ENOMEM;
-		goto err_release_region;
+		goto err_put_hcd;
 	}
 	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (err)
-		goto err_iounmap;
+		goto err_put_hcd;
 
 	platform_set_drvdata(dev, hcd);
 
 	return err;
 
-err_iounmap:
-	iounmap(hcd->regs);
-err_release_region:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 err_put_hcd:
 	usb_put_hcd(hcd);
 err_power:
@@ -153,14 +126,12 @@ err_power:
 	return err;
 }
 
-static int __devexit ehci_platform_remove(struct platform_device *dev)
+static int ehci_platform_remove(struct platform_device *dev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(dev);
 	struct usb_ehci_pdata *pdata = dev->dev.platform_data;
 
 	usb_remove_hcd(hcd);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 	platform_set_drvdata(dev, NULL);
 
@@ -225,7 +196,7 @@ static const struct dev_pm_ops ehci_platform_pm_ops = {
 static struct platform_driver ehci_platform_driver = {
 	.id_table	= ehci_platform_table,
 	.probe		= ehci_platform_probe,
-	.remove		= __devexit_p(ehci_platform_remove),
+	.remove		= ehci_platform_remove,
 	.shutdown	= usb_hcd_platform_shutdown,
 	.driver		= {
 		.owner	= THIS_MODULE,
@@ -233,3 +204,26 @@ static struct platform_driver ehci_platform_driver = {
 		.pm	= &ehci_platform_pm_ops,
 	}
 };
+
+static int __init ehci_platform_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+	ehci_init_driver(&ehci_platform_hc_driver, &platform_overrides);
+	return platform_driver_register(&ehci_platform_driver);
+}
+module_init(ehci_platform_init);
+
+static void __exit ehci_platform_cleanup(void)
+{
+	platform_driver_unregister(&ehci_platform_driver);
+}
+module_exit(ehci_platform_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Hauke Mehrtens");
+MODULE_AUTHOR("Alan Stern");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c
index 087aee2..363890e 100644
--- a/drivers/usb/host/ehci-pmcmsp.c
+++ b/drivers/usb/host/ehci-pmcmsp.c
@@ -90,7 +90,6 @@ static int ehci_msp_setup(struct usb_hcd *hcd)
 		return retval;
 
 	usb_hcd_tdi_set_mode(ehci);
-	ehci_port_power(ehci, 0);
 
 	return retval;
 }
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
index fa937d0..45aceef 100644
--- a/drivers/usb/host/ehci-ppc-of.c
+++ b/drivers/usb/host/ehci-ppc-of.c
@@ -71,7 +71,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
  * Fix: Enable Break Memory Transfer (BMT) in INSNREG3
  */
 #define PPC440EPX_EHCI0_INSREG_BMT	(0x1 << 0)
-static int __devinit
+static int
 ppc44x_enable_bmt(struct device_node *dn)
 {
 	__iomem u32 *insreg_virt;
@@ -87,7 +87,7 @@ ppc44x_enable_bmt(struct device_node *dn)
 }
 
 
-static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op)
+static int ehci_hcd_ppc_of_probe(struct platform_device *op)
 {
 	struct device_node *dn = op->dev.of_node;
 	struct usb_hcd *hcd;
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index 45a356e..df5925a 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -93,7 +93,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {
 	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
 };
 
-static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev)
+static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
 {
 	int result;
 	struct usb_hcd *hcd;
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 4b66374..3d98902 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -264,15 +264,9 @@ ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status)
 __releases(ehci->lock)
 __acquires(ehci->lock)
 {
-	if (likely (urb->hcpriv != NULL)) {
-		struct ehci_qh	*qh = (struct ehci_qh *) urb->hcpriv;
-
-		/* S-mask in a QH means it's an interrupt urb */
-		if ((qh->hw->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) {
-
-			/* ... update hc-wide periodic stats (for usbfs) */
-			ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
-		}
+	if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+		/* ... update hc-wide periodic stats */
+		ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
 	}
 
 	if (unlikely(urb->unlinked)) {
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
index 85b74be..319dcfa 100644
--- a/drivers/usb/host/ehci-s5p.c
+++ b/drivers/usb/host/ehci-s5p.c
@@ -85,7 +85,7 @@ static void s5p_setup_vbus_gpio(struct platform_device *pdev)
 
 static u64 ehci_s5p_dma_mask = DMA_BIT_MASK(32);
 
-static int __devinit s5p_ehci_probe(struct platform_device *pdev)
+static int s5p_ehci_probe(struct platform_device *pdev)
 {
 	struct s5p_ehci_platdata *pdata;
 	struct s5p_ehci_hcd *s5p_ehci;
@@ -136,7 +136,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
 		goto fail_clk;
 	}
 
-	err = clk_enable(s5p_ehci->clk);
+	err = clk_prepare_enable(s5p_ehci->clk);
 	if (err)
 		goto fail_clk;
 
@@ -183,13 +183,13 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
 	return 0;
 
 fail_io:
-	clk_disable(s5p_ehci->clk);
+	clk_disable_unprepare(s5p_ehci->clk);
 fail_clk:
 	usb_put_hcd(hcd);
 	return err;
 }
 
-static int __devexit s5p_ehci_remove(struct platform_device *pdev)
+static int s5p_ehci_remove(struct platform_device *pdev)
 {
 	struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
 	struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev);
@@ -200,7 +200,7 @@ static int __devexit s5p_ehci_remove(struct platform_device *pdev)
 	if (pdata && pdata->phy_exit)
 		pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 
-	clk_disable(s5p_ehci->clk);
+	clk_disable_unprepare(s5p_ehci->clk);
 
 	usb_put_hcd(hcd);
 
@@ -231,7 +231,7 @@ static int s5p_ehci_suspend(struct device *dev)
 	if (pdata && pdata->phy_exit)
 		pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 
-	clk_disable(s5p_ehci->clk);
+	clk_disable_unprepare(s5p_ehci->clk);
 
 	return rc;
 }
@@ -243,7 +243,7 @@ static int s5p_ehci_resume(struct device *dev)
 	struct platform_device *pdev = to_platform_device(dev);
 	struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
 
-	clk_enable(s5p_ehci->clk);
+	clk_prepare_enable(s5p_ehci->clk);
 
 	if (pdata && pdata->phy_init)
 		pdata->phy_init(pdev, S5P_USB_PHY_HOST);
@@ -274,7 +274,7 @@ MODULE_DEVICE_TABLE(of, exynos_ehci_match);
 
 static struct platform_driver s5p_ehci_driver = {
 	.probe		= s5p_ehci_probe,
-	.remove		= __devexit_p(s5p_ehci_remove),
+	.remove		= s5p_ehci_remove,
 	.shutdown	= s5p_ehci_shutdown,
 	.driver = {
 		.name	= "s5p-ehci",
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 7cf3da7..69ebee7 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -36,29 +36,6 @@
 
 static int ehci_get_frame (struct usb_hcd *hcd);
 
-#ifdef CONFIG_PCI
-
-static unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
-{
-	unsigned uf;
-
-	/*
-	 * The MosChip MCS9990 controller updates its microframe counter
-	 * a little before the frame counter, and occasionally we will read
-	 * the invalid intermediate value.  Avoid problems by checking the
-	 * microframe number (the low-order 3 bits); if they are 0 then
-	 * re-read the register to get the correct value.
-	 */
-	uf = ehci_readl(ehci, &ehci->regs->frame_index);
-	if (unlikely(ehci->frame_index_bug && ((uf & 7) == 0)))
-		uf = ehci_readl(ehci, &ehci->regs->frame_index);
-	return uf;
-}
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
 /*
  * periodic_next_shadow - return "next" pointer on shadow list
  * @periodic: host pointer to qh/itd/sitd
@@ -1361,7 +1338,7 @@ sitd_slot_ok (
  * given EHCI_TUNE_FLS and the slop).  Or, write a smarter scheduler!
  */
 
-#define SCHEDULE_SLOP	80	/* microframes */
+#define SCHEDULING_DELAY	40	/* microframes */
 
 static int
 iso_stream_schedule (
@@ -1370,7 +1347,7 @@ iso_stream_schedule (
 	struct ehci_iso_stream	*stream
 )
 {
-	u32			now, next, start, period, span;
+	u32			now, base, next, start, period, span;
 	int			status;
 	unsigned		mod = ehci->periodic_size << 3;
 	struct ehci_iso_sched	*sched = urb->hcpriv;
@@ -1382,62 +1359,72 @@ iso_stream_schedule (
 		span <<= 3;
 	}
 
-	if (span > mod - SCHEDULE_SLOP) {
-		ehci_dbg (ehci, "iso request %p too long\n", urb);
-		status = -EFBIG;
-		goto fail;
-	}
-
 	now = ehci_read_frame_index(ehci) & (mod - 1);
 
 	/* Typical case: reuse current schedule, stream is still active.
 	 * Hopefully there are no gaps from the host falling behind
-	 * (irq delays etc), but if there are we'll take the next
-	 * slot in the schedule, implicitly assuming URB_ISO_ASAP.
+	 * (irq delays etc).  If there are, the behavior depends on
+	 * whether URB_ISO_ASAP is set.
 	 */
 	if (likely (!list_empty (&stream->td_list))) {
-		u32	excess;
 
-		/* For high speed devices, allow scheduling within the
-		 * isochronous scheduling threshold.  For full speed devices
-		 * and Intel PCI-based controllers, don't (work around for
-		 * Intel ICH9 bug).
-		 */
-		if (!stream->highspeed && ehci->fs_i_thresh)
-			next = now + ehci->i_thresh;
+		/* Take the isochronous scheduling threshold into account */
+		if (ehci->i_thresh)
+			next = now + ehci->i_thresh;	/* uframe cache */
 		else
-			next = now;
+			next = (now + 2 + 7) & ~0x07;	/* full frame cache */
 
-		/* Fell behind (by up to twice the slop amount)?
-		 * We decide based on the time of the last currently-scheduled
-		 * slot, not the time of the next available slot.
+		/*
+		 * Use ehci->last_iso_frame as the base.  There can't be any
+		 * TDs scheduled for earlier than that.
 		 */
-		excess = (stream->next_uframe - period - next) & (mod - 1);
-		if (excess >= mod - 2 * SCHEDULE_SLOP)
-			start = next + excess - mod + period *
-					DIV_ROUND_UP(mod - excess, period);
-		else
-			start = next + excess + period;
-		if (start - now >= mod) {
-			ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n",
-					urb, start - now - period, period,
-					mod);
-			status = -EFBIG;
+		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)) {
+
+			/* 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.  If
+			 * the entire URB falls before the threshold, fail.
+			 */
+			else if (start + span - period < next) {
+				ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n",
+						urb, start + base,
+						span - period, next + base);
+				status = -EXDEV;
+				goto fail;
+			}
+		}
+
+		start += base;
 	}
 
 	/* 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 slop should handle reasonably slow cpus.  it
+	 * 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;
-		start = SCHEDULE_SLOP + (now & ~0x07);
 
-		/* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
+		base = now & ~0x07;
+		start = base + SCHEDULING_DELAY;
 
 		/* find a uframe slot with enough bandwidth.
 		 * Early uframes are more precious because full-speed
@@ -1464,19 +1451,16 @@ iso_stream_schedule (
 
 		/* no room in the schedule */
 		if (!done) {
-			ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n",
-				urb, now, now + mod);
+			ehci_dbg(ehci, "iso sched full %p", urb);
 			status = -ENOSPC;
 			goto fail;
 		}
 	}
 
 	/* Tried to schedule too far into the future? */
-	if (unlikely(start - now + span - period
-				>= mod - 2 * SCHEDULE_SLOP)) {
-		ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n",
-				urb, start - now, span - period,
-				mod - 2 * SCHEDULE_SLOP);
+	if (unlikely(start - base + span - period >= mod)) {
+		ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n",
+				urb, start - base, span - period, mod);
 		status = -EFBIG;
 		goto fail;
 	}
@@ -1490,7 +1474,7 @@ iso_stream_schedule (
 
 	/* Make sure scan_isoc() sees these */
 	if (ehci->isoc_count == 0)
-		ehci->next_frame = now >> 3;
+		ehci->last_iso_frame = now >> 3;
 	return 0;
 
  fail:
@@ -1646,7 +1630,7 @@ static void itd_link_urb(
 
 	/* don't need that schedule data any more */
 	iso_sched_free (stream, iso_sched);
-	urb->hcpriv = NULL;
+	urb->hcpriv = stream;
 
 	++ehci->isoc_count;
 	enable_periodic(ehci);
@@ -1708,7 +1692,7 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd)
 			urb->actual_length += desc->actual_length;
 		} else {
 			/* URB was too late */
-			desc->status = -EXDEV;
+			urb->error_count++;
 		}
 	}
 
@@ -2045,7 +2029,7 @@ static void sitd_link_urb(
 
 	/* don't need that schedule data any more */
 	iso_sched_free (stream, sched);
-	urb->hcpriv = NULL;
+	urb->hcpriv = stream;
 
 	++ehci->isoc_count;
 	enable_periodic(ehci);
@@ -2081,7 +2065,7 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
 	t = hc32_to_cpup(ehci, &sitd->hw_results);
 
 	/* report transfer status */
-	if (t & SITD_ERRS) {
+	if (unlikely(t & SITD_ERRS)) {
 		urb->error_count++;
 		if (t & SITD_STS_DBE)
 			desc->status = usb_pipein (urb->pipe)
@@ -2091,6 +2075,9 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
 			desc->status = -EOVERFLOW;
 		else /* XACT, MMF, etc */
 			desc->status = -EPROTO;
+	} else if (unlikely(t & SITD_STS_ACTIVE)) {
+		/* URB was too late */
+		urb->error_count++;
 	} else {
 		desc->status = 0;
 		desc->actual_length = desc->length - SITD_LENGTH(t);
@@ -2220,16 +2207,16 @@ static void scan_isoc(struct ehci_hcd *ehci)
 		now_frame = (uf >> 3) & fmask;
 		live = true;
 	} else  {
-		now_frame = (ehci->next_frame - 1) & fmask;
+		now_frame = (ehci->last_iso_frame - 1) & fmask;
 		live = false;
 	}
 	ehci->now_frame = now_frame;
 
-	frame = ehci->next_frame;
 	for (;;) {
 		union ehci_shadow	q, *q_p;
 		__hc32			type, *hw_p;
 
+		frame = ehci->last_iso_frame;
 restart:
 		/* scan each element in frame's queue for completions */
 		q_p = &ehci->pshadow [frame];
@@ -2334,7 +2321,6 @@ restart:
 		/* Stop when we have reached the current frame */
 		if (frame == now_frame)
 			break;
-		frame = (frame + 1) & fmask;
+		ehci->last_iso_frame = (frame + 1) & fmask;
 	}
-	ehci->next_frame = now_frame;
 }
diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c
index 6081e1e..0c90a24 100644
--- a/drivers/usb/host/ehci-sh.c
+++ b/drivers/usb/host/ehci-sh.c
@@ -21,17 +21,10 @@ struct ehci_sh_priv {
 static int ehci_sh_reset(struct usb_hcd *hcd)
 {
 	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
-	int ret;
 
 	ehci->caps = hcd->regs;
 
-	ret = ehci_setup(hcd);
-	if (unlikely(ret))
-		return ret;
-
-	ehci_port_power(ehci, 0);
-
-	return ret;
+	return ehci_setup(hcd);
 }
 
 static const struct hc_driver ehci_sh_hc_driver = {
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index c718a06..466c1bb 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -37,18 +37,11 @@ static void spear_stop_ehci(struct spear_ehci *ehci)
 static int ehci_spear_setup(struct usb_hcd *hcd)
 {
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	int retval = 0;
 
 	/* registers start at offset 0x0 */
 	ehci->caps = hcd->regs;
 
-	retval = ehci_setup(hcd);
-	if (retval)
-		return retval;
-
-	ehci_port_power(ehci, 0);
-
-	return retval;
+	return ehci_setup(hcd);
 }
 
 static const struct hc_driver ehci_spear_hc_driver = {
@@ -116,8 +109,6 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
 	struct clk *usbh_clk;
 	const struct hc_driver *driver = &ehci_spear_hc_driver;
 	int irq, retval;
-	char clk_name[20] = "usbh_clk";
-	static int instance = -1;
 
 	if (usb_disabled())
 		return -ENODEV;
@@ -125,7 +116,7 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		retval = irq;
-		goto fail_irq_get;
+		goto fail;
 	}
 
 	/*
@@ -136,47 +127,38 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
 	if (!pdev->dev.dma_mask)
 		pdev->dev.dma_mask = &spear_ehci_dma_mask;
 
-	/*
-	 * Increment the device instance, when probing via device-tree
-	 */
-	if (pdev->id < 0)
-		instance++;
-	else
-		instance = pdev->id;
-	sprintf(clk_name, "usbh.%01d_clk", instance);
-
-	usbh_clk = clk_get(NULL, clk_name);
+	usbh_clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(usbh_clk)) {
 		dev_err(&pdev->dev, "Error getting interface clock\n");
 		retval = PTR_ERR(usbh_clk);
-		goto fail_get_usbh_clk;
+		goto fail;
 	}
 
 	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
 	if (!hcd) {
 		retval = -ENOMEM;
-		goto fail_create_hcd;
+		goto fail;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		retval = -ENODEV;
-		goto fail_request_resource;
+		goto err_put_hcd;
 	}
 
 	hcd->rsrc_start = res->start;
 	hcd->rsrc_len = resource_size(res);
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
+	if (!devm_request_mem_region(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len,
 				driver->description)) {
 		retval = -EBUSY;
-		goto fail_request_resource;
+		goto err_put_hcd;
 	}
 
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	hcd->regs = devm_ioremap(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len);
 	if (hcd->regs == NULL) {
 		dev_dbg(&pdev->dev, "error mapping memory\n");
 		retval = -ENOMEM;
-		goto fail_ioremap;
+		goto err_put_hcd;
 	}
 
 	ehci = (struct spear_ehci *)hcd_to_ehci(hcd);
@@ -185,21 +167,15 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
 	spear_start_ehci(ehci);
 	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (retval)
-		goto fail_add_hcd;
+		goto err_stop_ehci;
 
 	return retval;
 
-fail_add_hcd:
+err_stop_ehci:
 	spear_stop_ehci(ehci);
-	iounmap(hcd->regs);
-fail_ioremap:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-fail_request_resource:
+err_put_hcd:
 	usb_put_hcd(hcd);
-fail_create_hcd:
-	clk_put(usbh_clk);
-fail_get_usbh_clk:
-fail_irq_get:
+fail:
 	dev_err(&pdev->dev, "init fail, %d\n", retval);
 
 	return retval ;
@@ -218,17 +194,12 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)
 
 	if (ehci_p->clk)
 		spear_stop_ehci(ehci_p);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 
-	if (ehci_p->clk)
-		clk_put(ehci_p->clk);
-
 	return 0;
 }
 
-static struct of_device_id spear_ehci_id_table[] __devinitdata = {
+static struct of_device_id spear_ehci_id_table[] = {
 	{ .compatible = "st,spear600-ehci", },
 	{ },
 };
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 6223d175..acf1755 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -28,7 +28,10 @@
 #include <linux/pm_runtime.h>
 
 #include <linux/usb/tegra_usb_phy.h>
-#include <mach/iomap.h>
+
+#define TEGRA_USB_BASE			0xC5000000
+#define TEGRA_USB2_BASE			0xC5004000
+#define TEGRA_USB3_BASE			0xC5008000
 
 #define TEGRA_USB_DMA_ALIGN 32
 
@@ -277,7 +280,6 @@ static void tegra_ehci_shutdown(struct usb_hcd *hcd)
 static int tegra_ehci_setup(struct usb_hcd *hcd)
 {
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	int retval;
 
 	/* EHCI registers start at offset 0x100 */
 	ehci->caps = hcd->regs + 0x100;
@@ -285,12 +287,7 @@ static int tegra_ehci_setup(struct usb_hcd *hcd)
 	/* switch to host mode */
 	hcd->has_tt = 1;
 
-	retval = ehci_setup(hcd);
-	if (retval)
-		return retval;
-
-	ehci_port_power(ehci, 1);
-	return retval;
+	return ehci_setup(hcd);
 }
 
 struct dma_aligned_buffer {
@@ -778,9 +775,6 @@ static int tegra_ehci_remove(struct platform_device *pdev)
 	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
 	struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
 
-	if (tegra == NULL || hcd == NULL)
-		return -EINVAL;
-
 	pm_runtime_get_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_put_noidle(&pdev->dev);
@@ -811,7 +805,7 @@ static void tegra_ehci_hcd_shutdown(struct platform_device *pdev)
 		hcd->driver->shutdown(hcd);
 }
 
-static struct of_device_id tegra_ehci_of_match[] __devinitdata = {
+static struct of_device_id tegra_ehci_of_match[] = {
 	{ .compatible = "nvidia,tegra20-ehci", },
 	{ },
 };
diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c
index d3c9a3e..11695d5 100644
--- a/drivers/usb/host/ehci-vt8500.c
+++ b/drivers/usb/host/ehci-vt8500.c
@@ -19,22 +19,6 @@
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
-static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
-{
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	int rc = 0;
-
-	if (!udev->parent) /* udev is root hub itself, impossible */
-		rc = -1;
-	/* we only support lpm device connected to root hub yet */
-	if (ehci->has_lpm && !udev->parent->parent) {
-		rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
-		if (!rc)
-			rc = ehci_lpm_check(ehci, udev->portnum);
-	}
-	return rc;
-}
-
 static const struct hc_driver vt8500_ehci_hc_driver = {
 	.description		= hcd_name,
 	.product_desc		= "VT8500 EHCI",
@@ -77,11 +61,6 @@ static const struct hc_driver vt8500_ehci_hc_driver = {
 	.relinquish_port	= ehci_relinquish_port,
 	.port_handed_over	= ehci_port_handed_over,
 
-	/*
-	 * call back when device connected and addressed
-	 */
-	.update_device =	ehci_update_device,
-
 	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
 };
 
diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c
index ec59808..59e0e24 100644
--- a/drivers/usb/host/ehci-w90x900.c
+++ b/drivers/usb/host/ehci-w90x900.c
@@ -13,12 +13,12 @@
 
 #include <linux/platform_device.h>
 
-/*ebable phy0 and phy1 for w90p910*/
+/* enable phy0 and phy1 for w90p910 */
 #define	ENPHY		(0x01<<8)
 #define PHY0_CTR	(0xA4)
 #define PHY1_CTR	(0xA8)
 
-static int __devinit usb_w90x900_probe(const struct hc_driver *driver,
+static int usb_w90x900_probe(const struct hc_driver *driver,
 		      struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
@@ -147,7 +147,7 @@ static const struct hc_driver ehci_w90x900_hc_driver = {
 	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
 };
 
-static int __devinit ehci_w90x900_probe(struct platform_device *pdev)
+static int ehci_w90x900_probe(struct platform_device *pdev)
 {
 	if (usb_disabled())
 		return -ENODEV;
@@ -155,7 +155,7 @@ static int __devinit ehci_w90x900_probe(struct platform_device *pdev)
 	return usb_w90x900_probe(&ehci_w90x900_hc_driver, pdev);
 }
 
-static int __devexit ehci_w90x900_remove(struct platform_device *pdev)
+static int ehci_w90x900_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
@@ -166,7 +166,7 @@ static int __devexit ehci_w90x900_remove(struct platform_device *pdev)
 
 static struct platform_driver ehci_hcd_w90x900_driver = {
 	.probe  = ehci_w90x900_probe,
-	.remove = __devexit_p(ehci_w90x900_remove),
+	.remove = ehci_w90x900_remove,
 	.driver = {
 		.name = "w90x900-ehci",
 		.owner = THIS_MODULE,
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
index 6a3f921..4f285e8 100644
--- a/drivers/usb/host/ehci-xilinx-of.c
+++ b/drivers/usb/host/ehci-xilinx-of.c
@@ -125,7 +125,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = {
  * as HS only or HS/FS only, it checks the configuration in the device tree
  * entry, and sets an appropriate value for hcd->has_tt.
  */
-static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op)
+static int ehci_hcd_xilinx_of_probe(struct platform_device *op)
 {
 	struct device_node *dn = op->dev.of_node;
 	struct usb_hcd *hcd;
diff --git a/drivers/usb/host/ehci-xls.c b/drivers/usb/host/ehci-xls.c
deleted file mode 100644
index 8dc6a22..0000000
--- a/drivers/usb/host/ehci-xls.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * EHCI HCD for Netlogic XLS processors.
- *
- * (C) Copyright 2011 Netlogic Microsystems Inc.
- *
- *  Based on various ehci-*.c drivers
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- */
-
-#include <linux/platform_device.h>
-
-static int ehci_xls_setup(struct usb_hcd *hcd)
-{
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-
-	ehci->caps = hcd->regs;
-
-	return ehci_setup(hcd);
-}
-
-int ehci_xls_probe_internal(const struct hc_driver *driver,
-	struct platform_device *pdev)
-{
-	struct usb_hcd  *hcd;
-	struct resource *res;
-	int retval, irq;
-
-	/* Get our IRQ from an earlier registered Platform Resource */
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "Found HC with no IRQ. Check %s setup!\n",
-				dev_name(&pdev->dev));
-		return -ENODEV;
-	}
-
-	/* Get our Memory Handle */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "Error: MMIO Handle %s setup!\n",
-				dev_name(&pdev->dev));
-		return -ENODEV;
-	}
-	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
-	if (!hcd) {
-		retval = -ENOMEM;
-		goto err1;
-	}
-
-	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_size(res);
-
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
-				driver->description)) {
-		dev_dbg(&pdev->dev, "controller already in use\n");
-		retval = -EBUSY;
-		goto err2;
-	}
-	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
-
-	if (hcd->regs == NULL) {
-		dev_dbg(&pdev->dev, "error mapping memory\n");
-		retval = -EFAULT;
-		goto err3;
-	}
-
-	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
-	if (retval != 0)
-		goto err4;
-	return retval;
-
-err4:
-	iounmap(hcd->regs);
-err3:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err2:
-	usb_put_hcd(hcd);
-err1:
-	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev),
-			retval);
-	return retval;
-}
-
-static struct hc_driver ehci_xls_hc_driver = {
-	.description	= hcd_name,
-	.product_desc	= "XLS EHCI Host Controller",
-	.hcd_priv_size	= sizeof(struct ehci_hcd),
-	.irq		= ehci_irq,
-	.flags		= HCD_USB2 | HCD_MEMORY,
-	.reset		= ehci_xls_setup,
-	.start		= ehci_run,
-	.stop		= ehci_stop,
-	.shutdown	= ehci_shutdown,
-
-	.urb_enqueue	= ehci_urb_enqueue,
-	.urb_dequeue	= ehci_urb_dequeue,
-	.endpoint_disable = ehci_endpoint_disable,
-	.endpoint_reset	= ehci_endpoint_reset,
-
-	.get_frame_number = ehci_get_frame,
-
-	.hub_status_data = ehci_hub_status_data,
-	.hub_control	= ehci_hub_control,
-	.bus_suspend	= ehci_bus_suspend,
-	.bus_resume	= ehci_bus_resume,
-	.relinquish_port = ehci_relinquish_port,
-	.port_handed_over = ehci_port_handed_over,
-
-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
-static int ehci_xls_probe(struct platform_device *pdev)
-{
-	if (usb_disabled())
-		return -ENODEV;
-
-	return ehci_xls_probe_internal(&ehci_xls_hc_driver, pdev);
-}
-
-static int ehci_xls_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_remove_hcd(hcd);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-	usb_put_hcd(hcd);
-	return 0;
-}
-
-MODULE_ALIAS("ehci-xls");
-
-static struct platform_driver ehci_xls_driver = {
-	.probe		= ehci_xls_probe,
-	.remove		= ehci_xls_remove,
-	.shutdown	= usb_hcd_platform_shutdown,
-	.driver		= {
-		.name = "ehci-xls",
-	},
-};
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index da07d98..9dadc71 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -143,7 +143,7 @@ struct ehci_hcd {			/* one per controller */
 	struct ehci_qh		*intr_unlink_last;
 	unsigned		intr_unlink_cycle;
 	unsigned		now_frame;	/* frame from HC hardware */
-	unsigned		next_frame;	/* scan periodic, start here */
+	unsigned		last_iso_frame;	/* last frame scanned for iso */
 	unsigned		intr_count;	/* intr activity count */
 	unsigned		isoc_count;	/* isoc activity count */
 	unsigned		periodic_count;	/* periodic activity count */
@@ -193,7 +193,6 @@ struct ehci_hcd {			/* one per controller */
 	unsigned		has_amcc_usb23:1;
 	unsigned		need_io_watchdog:1;
 	unsigned		amd_pll_fix:1;
-	unsigned		fs_i_thresh:1;	/* Intel iso scheduling */
 	unsigned		use_dummy_qh:1;	/* AMD Frame List table quirk*/
 	unsigned		has_synopsys_hc_bug:1; /* Synopsys HC */
 	unsigned		frame_index_bug:1; /* MosChip (AKA NetMos) */
@@ -207,7 +206,6 @@ struct ehci_hcd {			/* one per controller */
 	#define OHCI_HCCTRL_LEN         0x4
 	__hc32			*ohci_hcctrl_reg;
 	unsigned		has_hostpc:1;
-	unsigned		has_lpm:1;  /* support link power management */
 	unsigned		has_ppcd:1; /* support per-port change bits */
 	u8			sbrn;		/* packed release number */
 
@@ -762,26 +760,41 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef CONFIG_PCI
-
-/* For working around the MosChip frame-index-register bug */
-static unsigned ehci_read_frame_index(struct ehci_hcd *ehci);
-
+#define ehci_dbg(ehci, fmt, args...) \
+	dev_dbg(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
+#define ehci_err(ehci, fmt, args...) \
+	dev_err(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
+#define ehci_info(ehci, fmt, args...) \
+	dev_info(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
+#define ehci_warn(ehci, fmt, args...) \
+	dev_warn(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
+
+#ifdef VERBOSE_DEBUG
+#	define ehci_vdbg ehci_dbg
 #else
-
-static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
-{
-	return ehci_readl(ehci, &ehci->regs->frame_index);
-}
-
+	static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {}
 #endif
 
-/*-------------------------------------------------------------------------*/
-
 #ifndef DEBUG
 #define STUB_DEBUG_FILES
 #endif	/* DEBUG */
 
 /*-------------------------------------------------------------------------*/
 
+/* Declarations of things exported for use by ehci platform drivers */
+
+struct ehci_driver_overrides {
+	size_t		extra_priv_size;
+	int		(*reset)(struct usb_hcd *hcd);
+};
+
+extern void	ehci_init_driver(struct hc_driver *drv,
+				const struct ehci_driver_overrides *over);
+extern int	ehci_setup(struct usb_hcd *hcd);
+
+#ifdef CONFIG_PM
+extern int	ehci_suspend(struct usb_hcd *hcd, bool do_wakeup);
+extern int	ehci_resume(struct usb_hcd *hcd, bool hibernated);
+#endif	/* CONFIG_PM */
+
 #endif /* __LINUX_EHCI_HCD_H */
diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c
index 7da1a26..0b4654259 100644
--- a/drivers/usb/host/fhci-hcd.c
+++ b/drivers/usb/host/fhci-hcd.c
@@ -561,7 +561,7 @@ static const struct hc_driver fhci_driver = {
 	.hub_control = fhci_hub_control,
 };
 
-static int __devinit of_fhci_probe(struct platform_device *ofdev)
+static int of_fhci_probe(struct platform_device *ofdev)
 {
 	struct device *dev = &ofdev->dev;
 	struct device_node *node = dev->of_node;
@@ -780,7 +780,7 @@ err_regs:
 	return ret;
 }
 
-static int __devexit fhci_remove(struct device *dev)
+static int fhci_remove(struct device *dev)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	struct fhci_hcd *fhci = hcd_to_fhci(hcd);
@@ -803,7 +803,7 @@ static int __devexit fhci_remove(struct device *dev)
 	return 0;
 }
 
-static int __devexit of_fhci_remove(struct platform_device *ofdev)
+static int of_fhci_remove(struct platform_device *ofdev)
 {
 	return fhci_remove(&ofdev->dev);
 }
@@ -821,7 +821,7 @@ static struct platform_driver of_fhci_driver = {
 		.of_match_table = of_fhci_match,
 	},
 	.probe		= of_fhci_probe,
-	.remove		= __devexit_p(of_fhci_remove),
+	.remove		= of_fhci_remove,
 };
 
 module_platform_driver(of_fhci_driver);
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 1e77129..5105127 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -24,7 +24,7 @@ struct fsl_usb2_dev_data {
 	enum fsl_usb2_operating_modes op_mode;	/* operating mode */
 };
 
-struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = {
+struct fsl_usb2_dev_data dr_mode_data[] = {
 	{
 		.dr_mode = "host",
 		.drivers = { "fsl-ehci", NULL, NULL, },
@@ -42,7 +42,7 @@ struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = {
 	},
 };
 
-struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np)
+struct fsl_usb2_dev_data *get_dr_mode_data(struct device_node *np)
 {
 	const unsigned char *prop;
 	int i;
@@ -59,7 +59,7 @@ struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np)
 	return &dr_mode_data[0]; /* mode not specified, use host */
 }
 
-static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type)
+static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
 {
 	if (!phy_type)
 		return FSL_USB2_PHY_NONE;
@@ -75,7 +75,7 @@ static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type)
 	return FSL_USB2_PHY_NONE;
 }
 
-struct platform_device * __devinit fsl_usb2_device_register(
+struct platform_device *fsl_usb2_device_register(
 					struct platform_device *ofdev,
 					struct fsl_usb2_platform_data *pdata,
 					const char *name, int id)
@@ -154,7 +154,7 @@ static int usb_get_ver_info(struct device_node *np)
 	return ver;
 }
 
-static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
+static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct platform_device *usb_dev;
@@ -224,13 +224,13 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
 	return 0;
 }
 
-static int __devexit __unregister_subdev(struct device *dev, void *d)
+static int __unregister_subdev(struct device *dev, void *d)
 {
 	platform_device_unregister(to_platform_device(dev));
 	return 0;
 }
 
-static int __devexit fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)
+static int fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)
 {
 	device_for_each_child(&ofdev->dev, NULL, __unregister_subdev);
 	return 0;
@@ -336,7 +336,7 @@ static struct platform_driver fsl_usb2_mph_dr_driver = {
 		.of_match_table = fsl_usb2_mph_dr_of_match,
 	},
 	.probe	= fsl_usb2_mph_dr_of_probe,
-	.remove	= __devexit_p(fsl_usb2_mph_dr_of_remove),
+	.remove	= fsl_usb2_mph_dr_of_remove,
 };
 
 module_platform_driver(fsl_usb2_mph_dr_driver);
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
index f19e269..bd6a744 100644
--- a/drivers/usb/host/imx21-hcd.c
+++ b/drivers/usb/host/imx21-hcd.c
@@ -1680,7 +1680,7 @@ static int imx21_hc_reset(struct usb_hcd *hcd)
 	return 0;
 }
 
-static int __devinit imx21_hc_start(struct usb_hcd *hcd)
+static int imx21_hc_start(struct usb_hcd *hcd)
 {
 	struct imx21 *imx21 = hcd_to_imx21(hcd);
 	unsigned long flags;
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 9e65e30..b64e661 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1557,7 +1557,7 @@ static int isp116x_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devinit isp116x_probe(struct platform_device *pdev)
+static int isp116x_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
 	struct isp116x *isp116x;
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 2563263..974480c 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -2645,7 +2645,7 @@ static struct hc_driver isp1362_hc_driver = {
 
 /*-------------------------------------------------------------------------*/
 
-static int __devexit isp1362_remove(struct platform_device *pdev)
+static int isp1362_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 	struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd);
@@ -2680,7 +2680,7 @@ static int __devexit isp1362_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devinit isp1362_probe(struct platform_device *pdev)
+static int isp1362_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
 	struct isp1362_hcd *isp1362_hcd;
@@ -2856,7 +2856,7 @@ static int isp1362_resume(struct platform_device *pdev)
 
 static struct platform_driver isp1362_driver = {
 	.probe = isp1362_probe,
-	.remove = __devexit_p(isp1362_remove),
+	.remove = isp1362_remove,
 
 	.suspend = isp1362_suspend,
 	.resume = isp1362_resume,
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
index fff114f..bbb791b 100644
--- a/drivers/usb/host/isp1760-if.c
+++ b/drivers/usb/host/isp1760-if.c
@@ -43,7 +43,6 @@ static int of_isp1760_probe(struct platform_device *dev)
 	struct device_node *dp = dev->dev.of_node;
 	struct resource *res;
 	struct resource memory;
-	struct of_irq oirq;
 	int virq;
 	resource_size_t res_len;
 	int ret;
@@ -69,14 +68,12 @@ static int of_isp1760_probe(struct platform_device *dev)
 		goto free_data;
 	}
 
-	if (of_irq_map_one(dp, 0, &oirq)) {
+	virq = irq_of_parse_and_map(dp, 0);
+	if (!virq) {
 		ret = -ENODEV;
 		goto release_reg;
 	}
 
-	virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
-			oirq.size);
-
 	if (of_device_is_compatible(dp, "nxp,usb-isp1761"))
 		devflags |= ISP1760_FLAG_ISP1761;
 
@@ -175,7 +172,7 @@ static struct platform_driver isp1760_of_driver = {
 #endif
 
 #ifdef CONFIG_PCI
-static int __devinit isp1761_pci_probe(struct pci_dev *dev,
+static int isp1761_pci_probe(struct pci_dev *dev,
 		const struct pci_device_id *id)
 {
 	u8 latency, limit;
@@ -349,7 +346,7 @@ static struct pci_driver isp1761_pci_driver = {
 };
 #endif
 
-static int __devinit isp1760_plat_probe(struct platform_device *pdev)
+static int isp1760_plat_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 	struct usb_hcd *hcd;
@@ -416,7 +413,7 @@ out:
 	return ret;
 }
 
-static int __devexit isp1760_plat_remove(struct platform_device *pdev)
+static int isp1760_plat_remove(struct platform_device *pdev)
 {
 	struct resource *mem_res;
 	resource_size_t mem_size;
@@ -435,7 +432,7 @@ static int __devexit isp1760_plat_remove(struct platform_device *pdev)
 
 static struct platform_driver isp1760_plat_driver = {
 	.probe	= isp1760_plat_probe,
-	.remove	= __devexit_p(isp1760_plat_remove),
+	.remove	= isp1760_plat_remove,
 	.driver	= {
 		.name	= "isp1760",
 	},
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 0bf72f9..a0cb44f 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -16,11 +16,11 @@
 #include <linux/platform_device.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
+#include <linux/platform_data/atmel.h>
 
 #include <mach/hardware.h>
 #include <asm/gpio.h>
 
-#include <mach/board.h>
 #include <mach/cpu.h>
 
 #ifndef CONFIG_ARCH_AT91
@@ -94,7 +94,7 @@ static void at91_stop_hc(struct platform_device *pdev)
 
 /*-------------------------------------------------------------------------*/
 
-static void __devexit usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
+static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
 
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
@@ -108,7 +108,7 @@ static void __devexit usb_hcd_at91_remove (struct usb_hcd *, struct platform_dev
  * then invokes the start() method for the HCD associated with it
  * through the hotplug entry's driver_data.
  */
-static int __devinit usb_hcd_at91_probe(const struct hc_driver *driver,
+static int usb_hcd_at91_probe(const struct hc_driver *driver,
 			struct platform_device *pdev)
 {
 	int retval;
@@ -203,7 +203,7 @@ static int __devinit usb_hcd_at91_probe(const struct hc_driver *driver,
  * context, "rmmod" or something similar.
  *
  */
-static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd,
+static void usb_hcd_at91_remove(struct usb_hcd *hcd,
 				struct platform_device *pdev)
 {
 	usb_remove_hcd(hcd);
@@ -222,7 +222,7 @@ static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd,
 
 /*-------------------------------------------------------------------------*/
 
-static int __devinit
+static int
 ohci_at91_reset (struct usb_hcd *hcd)
 {
 	struct at91_usbh_data	*board = hcd->self.controller->platform_data;
@@ -236,7 +236,7 @@ ohci_at91_reset (struct usb_hcd *hcd)
 	return 0;
 }
 
-static int __devinit
+static int
 ohci_at91_start (struct usb_hcd *hcd)
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
@@ -506,7 +506,7 @@ MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids);
 
 static u64 at91_ohci_dma_mask = DMA_BIT_MASK(32);
 
-static int __devinit ohci_at91_of_init(struct platform_device *pdev)
+static int ohci_at91_of_init(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	int i, gpio;
@@ -548,7 +548,7 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev)
 	return 0;
 }
 #else
-static int __devinit ohci_at91_of_init(struct platform_device *pdev)
+static int ohci_at91_of_init(struct platform_device *pdev)
 {
 	return 0;
 }
@@ -556,7 +556,7 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev)
 
 /*-------------------------------------------------------------------------*/
 
-static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev)
+static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
 {
 	struct at91_usbh_data	*pdata;
 	int			i;
@@ -641,7 +641,7 @@ static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev)
 	return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);
 }
 
-static int __devexit ohci_hcd_at91_drv_remove(struct platform_device *pdev)
+static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
 {
 	struct at91_usbh_data	*pdata = pdev->dev.platform_data;
 	int			i;
@@ -705,7 +705,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
 	if (!clocked)
 		at91_start_clock();
 
-	ohci_finish_controller_resume(hcd);
+	ohci_resume(hcd, false);
 	return 0;
 }
 #else
@@ -717,7 +717,7 @@ MODULE_ALIAS("platform:at91_ohci");
 
 static struct platform_driver ohci_hcd_at91_driver = {
 	.probe		= ohci_hcd_at91_drv_probe,
-	.remove		= __devexit_p(ohci_hcd_at91_drv_remove),
+	.remove		= ohci_hcd_at91_drv_remove,
 	.shutdown	= usb_hcd_platform_shutdown,
 	.suspend	= ohci_hcd_at91_drv_suspend,
 	.resume		= ohci_hcd_at91_drv_resume,
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
deleted file mode 100644
index c611699..0000000
--- a/drivers/usb/host/ohci-au1xxx.c
+++ /dev/null
@@ -1,234 +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 AMD Alchemy Au1xxx
- *
- * 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 AMD Alchemy Au1xxx
- *  by Matt Porter <mporter@kernel.crashing.org>
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/platform_device.h>
-#include <linux/signal.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-
-extern int usb_disabled(void);
-
-static int __devinit ohci_au1xxx_start(struct usb_hcd *hcd)
-{
-	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
-	int ret;
-
-	ohci_dbg(ohci, "ohci_au1xxx_start, ohci:%p", ohci);
-
-	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_au1xxx_hc_driver = {
-	.description =		hcd_name,
-	.product_desc =		"Au1xxx OHCI",
-	.hcd_priv_size =	sizeof(struct ohci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq =			ohci_irq,
-	.flags =		HCD_USB11 | HCD_MEMORY,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.start =		ohci_au1xxx_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_au1xxx_drv_probe(struct platform_device *pdev)
-{
-	int ret, unit;
-	struct usb_hcd *hcd;
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	if (pdev->resource[1].flags != IORESOURCE_IRQ) {
-		pr_debug("resource[1] is not IORESOURCE_IRQ\n");
-		return -ENOMEM;
-	}
-
-	hcd = usb_create_hcd(&ohci_au1xxx_hc_driver, &pdev->dev, "au1xxx");
-	if (!hcd)
-		return -ENOMEM;
-
-	hcd->rsrc_start = pdev->resource[0].start;
-	hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
-
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		pr_debug("request_mem_region failed\n");
-		ret = -EBUSY;
-		goto err1;
-	}
-
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		pr_debug("ioremap failed\n");
-		ret = -ENOMEM;
-		goto err2;
-	}
-
-	unit = (hcd->rsrc_start == AU1300_USB_OHCI1_PHYS_ADDR) ?
-			ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
-	if (alchemy_usb_control(unit, 1)) {
-		printk(KERN_INFO "%s: controller init failed!\n", pdev->name);
-		ret = -ENODEV;
-		goto err3;
-	}
-
-	ohci_hcd_init(hcd_to_ohci(hcd));
-
-	ret = usb_add_hcd(hcd, pdev->resource[1].start,
-			  IRQF_SHARED);
-	if (ret == 0) {
-		platform_set_drvdata(pdev, hcd);
-		return ret;
-	}
-
-	alchemy_usb_control(unit, 0);
-err3:
-	iounmap(hcd->regs);
-err2:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err1:
-	usb_put_hcd(hcd);
-	return ret;
-}
-
-static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-	int unit;
-
-	unit = (hcd->rsrc_start == AU1300_USB_OHCI1_PHYS_ADDR) ?
-			ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
-	usb_remove_hcd(hcd);
-	alchemy_usb_control(unit, 0);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-	usb_put_hcd(hcd);
-	platform_set_drvdata(pdev, NULL);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int ohci_hcd_au1xxx_drv_suspend(struct device *dev)
-{
-	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
-	unsigned long flags;
-	int rc;
-
-	rc = 0;
-
-	/* Root hub was already suspended. Disable irq emission and
-	 * mark HW unaccessible, bail out if RH has been resumed. Use
-	 * the spinlock to properly synchronize with possible pending
-	 * RH suspend or resume activity.
-	 */
-	spin_lock_irqsave(&ohci->lock, flags);
-	if (ohci->rh_state != OHCI_RH_SUSPENDED) {
-		rc = -EINVAL;
-		goto bail;
-	}
-	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
-	(void)ohci_readl(ohci, &ohci->regs->intrdisable);
-
-	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-	alchemy_usb_control(ALCHEMY_USB_OHCI0, 0);
-bail:
-	spin_unlock_irqrestore(&ohci->lock, flags);
-
-	return rc;
-}
-
-static int ohci_hcd_au1xxx_drv_resume(struct device *dev)
-{
-	struct usb_hcd *hcd = dev_get_drvdata(dev);
-
-	alchemy_usb_control(ALCHEMY_USB_OHCI0, 1);
-
-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-	ohci_finish_controller_resume(hcd);
-
-	return 0;
-}
-
-static const struct dev_pm_ops au1xxx_ohci_pmops = {
-	.suspend	= ohci_hcd_au1xxx_drv_suspend,
-	.resume		= ohci_hcd_au1xxx_drv_resume,
-};
-
-#define AU1XXX_OHCI_PMOPS &au1xxx_ohci_pmops
-
-#else
-#define AU1XXX_OHCI_PMOPS NULL
-#endif
-
-static struct platform_driver ohci_hcd_au1xxx_driver = {
-	.probe		= ohci_hcd_au1xxx_drv_probe,
-	.remove		= ohci_hcd_au1xxx_drv_remove,
-	.shutdown	= usb_hcd_platform_shutdown,
-	.driver		= {
-		.name	= "au1xxx-ohci",
-		.owner	= THIS_MODULE,
-		.pm	= AU1XXX_OHCI_PMOPS,
-	},
-};
-
-MODULE_ALIAS("platform:au1xxx-ohci");
diff --git a/drivers/usb/host/ohci-cns3xxx.c b/drivers/usb/host/ohci-cns3xxx.c
deleted file mode 100644
index 2c9f233..0000000
--- a/drivers/usb/host/ohci-cns3xxx.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright 2008 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/atomic.h>
-#include <mach/cns3xxx.h>
-#include <mach/pm.h>
-
-static int __devinit
-cns3xxx_ohci_start(struct usb_hcd *hcd)
-{
-	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
-	int ret;
-
-	/*
-	 * EHCI and OHCI share the same clock and power,
-	 * resetting twice would cause the 1st controller been reset.
-	 * Therefore only do power up  at the first up device, and
-	 * power down at the last down device.
-	 *
-	 * Set USB AHB INCR length to 16
-	 */
-	if (atomic_inc_return(&usb_pwr_ref) == 1) {
-		cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
-		cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
-		cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
-		__raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
-			MISC_CHIP_CONFIG_REG);
-	}
-
-	ret = ohci_init(ohci);
-	if (ret < 0)
-		return ret;
-
-	ohci->num_ports = 1;
-
-	ret = ohci_run(ohci);
-	if (ret < 0) {
-		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 cns3xxx_ohci_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "CNS3XXX OHCI Host controller",
-	.hcd_priv_size		= sizeof(struct ohci_hcd),
-	.irq			= ohci_irq,
-	.flags			= HCD_USB11 | HCD_MEMORY,
-	.start			= cns3xxx_ohci_start,
-	.stop			= ohci_stop,
-	.shutdown		= ohci_shutdown,
-	.urb_enqueue		= ohci_urb_enqueue,
-	.urb_dequeue		= ohci_urb_dequeue,
-	.endpoint_disable	= ohci_endpoint_disable,
-	.get_frame_number	= ohci_get_frame,
-	.hub_status_data	= ohci_hub_status_data,
-	.hub_control		= ohci_hub_control,
-#ifdef CONFIG_PM
-	.bus_suspend		= ohci_bus_suspend,
-	.bus_resume		= ohci_bus_resume,
-#endif
-	.start_port_reset	= ohci_start_port_reset,
-};
-
-static int cns3xxx_ohci_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct usb_hcd *hcd;
-	const struct hc_driver *driver = &cns3xxx_ohci_hc_driver;
-	struct resource *res;
-	int irq;
-	int retval;
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		dev_err(dev, "Found HC with no IRQ.\n");
-		return -ENODEV;
-	}
-	irq = res->start;
-
-	hcd = usb_create_hcd(driver, dev, dev_name(dev));
-	if (!hcd)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "Found HC with no register addr.\n");
-		retval = -ENODEV;
-		goto err1;
-	}
-	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_size(res);
-
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
-			driver->description)) {
-		dev_dbg(dev, "controller already in use\n");
-		retval = -EBUSY;
-		goto err1;
-	}
-
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		dev_dbg(dev, "error mapping memory\n");
-		retval = -EFAULT;
-		goto err2;
-	}
-
-	ohci_hcd_init(hcd_to_ohci(hcd));
-
-	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
-	if (retval == 0)
-		return retval;
-
-	iounmap(hcd->regs);
-err2:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err1:
-	usb_put_hcd(hcd);
-	return retval;
-}
-
-static int cns3xxx_ohci_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_remove_hcd(hcd);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-
-	/*
-	 * EHCI and OHCI share the same clock and power,
-	 * resetting twice would cause the 1st controller been reset.
-	 * Therefore only do power up  at the first up device, and
-	 * power down at the last down device.
-	 */
-	if (atomic_dec_return(&usb_pwr_ref) == 0)
-		cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
-
-	usb_put_hcd(hcd);
-
-	platform_set_drvdata(pdev, NULL);
-
-	return 0;
-}
-
-MODULE_ALIAS("platform:cns3xxx-ohci");
-
-static struct platform_driver ohci_hcd_cns3xxx_driver = {
-	.probe = cns3xxx_ohci_probe,
-	.remove = cns3xxx_ohci_remove,
-	.driver = {
-		.name = "cns3xxx-ohci",
-	},
-};
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
index dbfbd1d..8704e9f 100644
--- a/drivers/usb/host/ohci-ep93xx.c
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -107,7 +107,7 @@ static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd,
 	usb_put_hcd(hcd);
 }
 
-static int __devinit ohci_ep93xx_start(struct usb_hcd *hcd)
+static int ohci_ep93xx_start(struct usb_hcd *hcd)
 {
 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
 	int ret;
@@ -194,7 +194,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
 
 	ep93xx_start_hc(&pdev->dev);
 
-	ohci_finish_controller_resume(hcd);
+	ohci_resume(hcd, false);
 	return 0;
 }
 #endif
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index 20a5008..aa3b884 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -23,6 +23,11 @@ struct exynos_ohci_hcd {
 	struct clk *clk;
 };
 
+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);
@@ -30,10 +35,6 @@ static int ohci_exynos_start(struct usb_hcd *hcd)
 
 	ohci_dbg(ohci, "ohci_exynos_start, ohci:%p", ohci);
 
-	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",
@@ -53,6 +54,7 @@ static const struct hc_driver exynos_ohci_hc_driver = {
 	.irq			= ohci_irq,
 	.flags			= HCD_MEMORY|HCD_USB11,
 
+	.reset			= ohci_exynos_reset,
 	.start			= ohci_exynos_start,
 	.stop			= ohci_stop,
 	.shutdown		= ohci_shutdown,
@@ -74,7 +76,7 @@ static const struct hc_driver exynos_ohci_hc_driver = {
 
 static u64 ohci_exynos_dma_mask = DMA_BIT_MASK(32);
 
-static int __devinit exynos_ohci_probe(struct platform_device *pdev)
+static int exynos_ohci_probe(struct platform_device *pdev)
 {
 	struct exynos4_ohci_platdata *pdata;
 	struct exynos_ohci_hcd *exynos_ohci;
@@ -115,7 +117,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
 	}
 
 	exynos_ohci->hcd = hcd;
-	exynos_ohci->clk = clk_get(&pdev->dev, "usbhost");
+	exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");
 
 	if (IS_ERR(exynos_ohci->clk)) {
 		dev_err(&pdev->dev, "Failed to get usbhost clock\n");
@@ -123,9 +125,9 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
 		goto fail_clk;
 	}
 
-	err = clk_enable(exynos_ohci->clk);
+	err = clk_prepare_enable(exynos_ohci->clk);
 	if (err)
-		goto fail_clken;
+		goto fail_clk;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
@@ -167,15 +169,13 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
 	return 0;
 
 fail_io:
-	clk_disable(exynos_ohci->clk);
-fail_clken:
-	clk_put(exynos_ohci->clk);
+	clk_disable_unprepare(exynos_ohci->clk);
 fail_clk:
 	usb_put_hcd(hcd);
 	return err;
 }
 
-static int __devexit exynos_ohci_remove(struct platform_device *pdev)
+static int exynos_ohci_remove(struct platform_device *pdev)
 {
 	struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
 	struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev);
@@ -186,8 +186,7 @@ static int __devexit exynos_ohci_remove(struct platform_device *pdev)
 	if (pdata && pdata->phy_exit)
 		pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 
-	clk_disable(exynos_ohci->clk);
-	clk_put(exynos_ohci->clk);
+	clk_disable_unprepare(exynos_ohci->clk);
 
 	usb_put_hcd(hcd);
 
@@ -232,7 +231,7 @@ static int exynos_ohci_suspend(struct device *dev)
 	if (pdata && pdata->phy_exit)
 		pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 
-	clk_disable(exynos_ohci->clk);
+	clk_disable_unprepare(exynos_ohci->clk);
 
 fail:
 	spin_unlock_irqrestore(&ohci->lock, flags);
@@ -247,15 +246,12 @@ static int exynos_ohci_resume(struct device *dev)
 	struct platform_device *pdev = to_platform_device(dev);
 	struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
 
-	clk_enable(exynos_ohci->clk);
+	clk_prepare_enable(exynos_ohci->clk);
 
 	if (pdata && pdata->phy_init)
 		pdata->phy_init(pdev, S5P_USB_PHY_HOST);
 
-	/* Mark hardware accessible again as we are out of D3 state by now */
-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-	ohci_finish_controller_resume(hcd);
+	ohci_resume(hcd, false);
 
 	return 0;
 }
@@ -279,7 +275,7 @@ MODULE_DEVICE_TABLE(of, exynos_ohci_match);
 
 static struct platform_driver exynos_ohci_driver = {
 	.probe		= exynos_ohci_probe,
-	.remove		= __devexit_p(exynos_ohci_remove),
+	.remove		= exynos_ohci_remove,
 	.shutdown	= exynos_ohci_shutdown,
 	.driver = {
 		.name	= "exynos-ohci",
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 4a1d64d..180a2b0 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -231,13 +231,41 @@ static int ohci_urb_enqueue (
 			frame &= ~(ed->interval - 1);
 			frame |= ed->branch;
 			urb->start_frame = frame;
+		}
+	} else if (ed->type == PIPE_ISOCHRONOUS) {
+		u16	next = ohci_frame_no(ohci) + 2;
+		u16	frame = ed->last_iso + ed->interval;
+
+		/* Behind the scheduling threshold? */
+		if (unlikely(tick_before(frame, next))) {
 
-			/* yes, only URB_ISO_ASAP is supported, and
-			 * urb->start_frame is never used as input.
+			/* USB_ISO_ASAP: Round up to the first available slot */
+			if (urb->transfer_flags & URB_ISO_ASAP)
+				frame += (next - frame + ed->interval - 1) &
+						-ed->interval;
+
+			/*
+			 * Not ASAP: Use the next slot in the stream.  If
+			 * the entire URB falls before the threshold, fail.
 			 */
+			else if (tick_before(frame + ed->interval *
+					(urb->number_of_packets - 1), next)) {
+				retval = -EXDEV;
+				usb_hcd_unlink_urb_from_ep(hcd, urb);
+				goto fail;
+			}
+
+			/*
+			 * Some OHCI hardware doesn't handle late TDs
+			 * correctly.  After retiring them it proceeds to
+			 * the next ED instead of the next TD.  Therefore
+			 * we have to omit the late TDs entirely.
+			 */
+			urb_priv->td_cnt = DIV_ROUND_UP(next - frame,
+					ed->interval);
 		}
-	} else if (ed->type == PIPE_ISOCHRONOUS)
-		urb->start_frame = ed->last_iso + ed->interval;
+		urb->start_frame = frame;
+	}
 
 	/* fill the TDs and link them to the ed; and
 	 * enable that part of the schedule, if needed
@@ -983,6 +1011,79 @@ static int ohci_restart (struct ohci_hcd *ohci)
 
 #endif
 
+#ifdef CONFIG_PM
+
+static int __maybe_unused ohci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+	unsigned long	flags;
+
+	/* Disable irq emission and mark HW unaccessible. Use
+	 * the spinlock to properly synchronize with possible pending
+	 * RH suspend or resume activity.
+	 */
+	spin_lock_irqsave (&ohci->lock, flags);
+	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+	(void)ohci_readl(ohci, &ohci->regs->intrdisable);
+
+	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+	spin_unlock_irqrestore (&ohci->lock, flags);
+
+	return 0;
+}
+
+
+static int __maybe_unused ohci_resume(struct usb_hcd *hcd, bool hibernated)
+{
+	struct ohci_hcd		*ohci = hcd_to_ohci(hcd);
+	int			port;
+	bool			need_reinit = false;
+
+	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+	/* Make sure resume from hibernation re-enumerates everything */
+	if (hibernated)
+		ohci_usb_reset(ohci);
+
+	/* See if the controller is already running or has been reset */
+	ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
+	if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
+		need_reinit = true;
+	} else {
+		switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+		case OHCI_USB_OPER:
+		case OHCI_USB_RESET:
+			need_reinit = true;
+		}
+	}
+
+	/* If needed, reinitialize and suspend the root hub */
+	if (need_reinit) {
+		spin_lock_irq(&ohci->lock);
+		ohci_rh_resume(ohci);
+		ohci_rh_suspend(ohci, 0);
+		spin_unlock_irq(&ohci->lock);
+	}
+
+	/* Normally just turn on port power and enable interrupts */
+	else {
+		ohci_dbg(ohci, "powerup ports\n");
+		for (port = 0; port < ohci->num_ports; port++)
+			ohci_writel(ohci, RH_PS_PPS,
+					&ohci->regs->roothub.portstatus[port]);
+
+		ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
+		ohci_readl(ohci, &ohci->regs->intrenable);
+		msleep(20);
+	}
+
+	usb_hcd_resume_root_hub(hcd);
+
+	return 0;
+}
+
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 MODULE_AUTHOR (DRIVER_AUTHOR);
@@ -1029,21 +1130,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ohci_hcd_ep93xx_driver
 #endif
 
-#ifdef CONFIG_MIPS_ALCHEMY
-#include "ohci-au1xxx.c"
-#define PLATFORM_DRIVER		ohci_hcd_au1xxx_driver
-#endif
-
-#ifdef CONFIG_PNX8550
-#include "ohci-pnx8550.c"
-#define PLATFORM_DRIVER		ohci_hcd_pnx8550_driver
-#endif
-
-#ifdef CONFIG_USB_OHCI_HCD_PPC_SOC
-#include "ohci-ppc-soc.c"
-#define PLATFORM_DRIVER		ohci_hcd_ppc_soc_driver
-#endif
-
 #ifdef CONFIG_ARCH_AT91
 #include "ohci-at91.c"
 #define PLATFORM_DRIVER		ohci_hcd_at91_driver
@@ -1059,11 +1145,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ohci_hcd_da8xx_driver
 #endif
 
-#ifdef CONFIG_USB_OHCI_SH
-#include "ohci-sh.c"
-#define PLATFORM_DRIVER		ohci_hcd_sh_driver
-#endif
-
 
 #ifdef CONFIG_USB_OHCI_HCD_PPC_OF
 #include "ohci-ppc-of.c"
@@ -1105,16 +1186,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ohci_hcd_tilegx_driver
 #endif
 
-#ifdef CONFIG_USB_CNS3XXX_OHCI
-#include "ohci-cns3xxx.c"
-#define PLATFORM_DRIVER		ohci_hcd_cns3xxx_driver
-#endif
-
-#ifdef CONFIG_CPU_XLR
-#include "ohci-xls.c"
-#define PLATFORM_DRIVER		ohci_xls_driver
-#endif
-
 #ifdef CONFIG_USB_OHCI_HCD_PLATFORM
 #include "ohci-platform.c"
 #define PLATFORM_DRIVER		ohci_platform_driver
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 2f3619e..db09dae 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -316,48 +316,6 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
 	return rc;
 }
 
-/* Carry out the final steps of resuming the controller device */
-static void __maybe_unused ohci_finish_controller_resume(struct usb_hcd *hcd)
-{
-	struct ohci_hcd		*ohci = hcd_to_ohci(hcd);
-	int			port;
-	bool			need_reinit = false;
-
-	/* See if the controller is already running or has been reset */
-	ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
-	if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
-		need_reinit = true;
-	} else {
-		switch (ohci->hc_control & OHCI_CTRL_HCFS) {
-		case OHCI_USB_OPER:
-		case OHCI_USB_RESET:
-			need_reinit = true;
-		}
-	}
-
-	/* If needed, reinitialize and suspend the root hub */
-	if (need_reinit) {
-		spin_lock_irq(&ohci->lock);
-		ohci_rh_resume(ohci);
-		ohci_rh_suspend(ohci, 0);
-		spin_unlock_irq(&ohci->lock);
-	}
-
-	/* Normally just turn on port power and enable interrupts */
-	else {
-		ohci_dbg(ohci, "powerup ports\n");
-		for (port = 0; port < ohci->num_ports; port++)
-			ohci_writel(ohci, RH_PS_PPS,
-					&ohci->regs->roothub.portstatus[port]);
-
-		ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
-		ohci_readl(ohci, &ohci->regs->intrenable);
-		msleep(20);
-	}
-
-	usb_hcd_resume_root_hub(hcd);
-}
-
 /* Carry out polling-, autostop-, and autoresume-related state changes */
 static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
 		int any_connected, int rhsc_status)
diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c
index 931d588..8062bb9 100644
--- a/drivers/usb/host/ohci-jz4740.c
+++ b/drivers/usb/host/ohci-jz4740.c
@@ -145,7 +145,7 @@ static const struct hc_driver ohci_jz4740_hc_driver = {
 };
 
 
-static __devinit int jz4740_ohci_probe(struct platform_device *pdev)
+static int jz4740_ohci_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct usb_hcd *hcd;
@@ -239,7 +239,7 @@ err_free:
 	return ret;
 }
 
-static __devexit int jz4740_ohci_remove(struct platform_device *pdev)
+static int jz4740_ohci_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 	struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd);
@@ -266,7 +266,7 @@ static __devexit int jz4740_ohci_remove(struct platform_device *pdev)
 
 static struct platform_driver ohci_hcd_jz4740_driver = {
 	.probe = jz4740_ohci_probe,
-	.remove = __devexit_p(jz4740_ohci_remove),
+	.remove = jz4740_ohci_remove,
 	.driver = {
 		.name = "jz4740-ohci",
 		.owner = THIS_MODULE,
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
index e068f03..2344040 100644
--- a/drivers/usb/host/ohci-nxp.c
+++ b/drivers/usb/host/ohci-nxp.c
@@ -147,7 +147,7 @@ static void nxp_stop_hc(void)
 	__raw_writel(tmp, USB_OTG_STAT_CONTROL);
 }
 
-static int __devinit ohci_nxp_start(struct usb_hcd *hcd)
+static int ohci_nxp_start(struct usb_hcd *hcd)
 {
 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
 	int ret;
@@ -205,7 +205,7 @@ static const struct hc_driver ohci_nxp_hc_driver = {
 	.start_port_reset = ohci_start_port_reset,
 };
 
-static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev)
+static int usb_hcd_nxp_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = 0;
 	struct ohci_hcd *ohci;
diff --git a/drivers/usb/host/ohci-octeon.c b/drivers/usb/host/ohci-octeon.c
index d469bf9..d44430d 100644
--- a/drivers/usb/host/ohci-octeon.c
+++ b/drivers/usb/host/ohci-octeon.c
@@ -42,7 +42,7 @@ static void ohci_octeon_hw_stop(void)
 	octeon2_usb_clocks_stop();
 }
 
-static int __devinit ohci_octeon_start(struct usb_hcd *hcd)
+static int ohci_octeon_start(struct usb_hcd *hcd)
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
 	int ret;
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 4531d03..b1d32fb 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -25,7 +25,6 @@
 #include <asm/mach-types.h>
 
 #include <mach/mux.h>
-#include <plat/fpga.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
@@ -93,14 +92,14 @@ static int omap_ohci_transceiver_power(int on)
 {
 	if (on) {
 		if (machine_is_omap_innovator() && cpu_is_omap1510())
-			fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
+			__raw_writeb(__raw_readb(INNOVATOR_FPGA_CAM_USB_CONTROL)
 				| ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
 			       INNOVATOR_FPGA_CAM_USB_CONTROL);
 		else if (machine_is_omap_osk())
 			tps65010_set_gpio_out_value(GPIO1, LOW);
 	} else {
 		if (machine_is_omap_innovator() && cpu_is_omap1510())
-			fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
+			__raw_writeb(__raw_readb(INNOVATOR_FPGA_CAM_USB_CONTROL)
 				& ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
 			       INNOVATOR_FPGA_CAM_USB_CONTROL);
 		else if (machine_is_omap_osk())
@@ -530,7 +529,7 @@ static int ohci_omap_resume(struct platform_device *dev)
 	ohci->next_statechange = jiffies;
 
 	omap_ohci_clock_power(1);
-	ohci_finish_controller_resume(hcd);
+	ohci_resume(hcd, false);
 	return 0;
 }
 
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
index 1b8133b..eb35d96 100644
--- a/drivers/usb/host/ohci-omap3.c
+++ b/drivers/usb/host/ohci-omap3.c
@@ -30,7 +30,6 @@
  */
 
 #include <linux/platform_device.h>
-#include <plat/usb.h>
 #include <linux/pm_runtime.h>
 
 /*-------------------------------------------------------------------------*/
@@ -125,7 +124,7 @@ static const struct hc_driver ohci_omap3_hc_driver = {
  * then invokes the start() method for the HCD associated with it
  * through the hotplug entry's driver_data.
  */
-static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev)
+static int ohci_hcd_omap3_probe(struct platform_device *pdev)
 {
 	struct device		*dev = &pdev->dev;
 	struct usb_hcd		*hcd = NULL;
@@ -209,7 +208,7 @@ err_io:
  * the HCD's stop() method.  It is always called from a thread
  * context, normally "rmmod", "apmd", or something similar.
  */
-static int __devexit ohci_hcd_omap3_remove(struct platform_device *pdev)
+static int ohci_hcd_omap3_remove(struct platform_device *pdev)
 {
 	struct device *dev	= &pdev->dev;
 	struct usb_hcd *hcd	= dev_get_drvdata(dev);
@@ -232,7 +231,7 @@ static void ohci_hcd_omap3_shutdown(struct platform_device *pdev)
 
 static struct platform_driver ohci_hcd_omap3_driver = {
 	.probe		= ohci_hcd_omap3_probe,
-	.remove		= __devexit_p(ohci_hcd_omap3_remove),
+	.remove		= ohci_hcd_omap3_remove,
 	.shutdown	= ohci_hcd_omap3_shutdown,
 	.driver		= {
 		.name	= "ohci-omap3",
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 1843bb6..951514e 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -270,7 +270,7 @@ static int ohci_pci_reset (struct usb_hcd *hcd)
 }
 
 
-static int __devinit ohci_pci_start (struct usb_hcd *hcd)
+static int ohci_pci_start (struct usb_hcd *hcd)
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 	int		ret;
@@ -296,49 +296,6 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd)
 	return ret;
 }
 
-#ifdef	CONFIG_PM
-
-static int ohci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
-{
-	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
-	unsigned long	flags;
-	int		rc = 0;
-
-	/* Root hub was already suspended. Disable irq emission and
-	 * mark HW unaccessible, bail out if RH has been resumed. Use
-	 * the spinlock to properly synchronize with possible pending
-	 * RH suspend or resume activity.
-	 */
-	spin_lock_irqsave (&ohci->lock, flags);
-	if (ohci->rh_state != OHCI_RH_SUSPENDED) {
-		rc = -EINVAL;
-		goto bail;
-	}
-	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
-	(void)ohci_readl(ohci, &ohci->regs->intrdisable);
-
-	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
- bail:
-	spin_unlock_irqrestore (&ohci->lock, flags);
-
-	return rc;
-}
-
-
-static int ohci_pci_resume(struct usb_hcd *hcd, bool hibernated)
-{
-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-	/* Make sure resume from hibernation re-enumerates everything */
-	if (hibernated)
-		ohci_usb_reset(hcd_to_ohci(hcd));
-
-	ohci_finish_controller_resume(hcd);
-	return 0;
-}
-
-#endif	/* CONFIG_PM */
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -362,8 +319,8 @@ static const struct hc_driver ohci_pci_hc_driver = {
 	.shutdown =		ohci_shutdown,
 
 #ifdef	CONFIG_PM
-	.pci_suspend =		ohci_pci_suspend,
-	.pci_resume =		ohci_pci_resume,
+	.pci_suspend =		ohci_suspend,
+	.pci_resume =		ohci_resume,
 #endif
 
 	/*
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index e24ec9f..084503b 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -31,6 +31,10 @@ static int ohci_platform_reset(struct usb_hcd *hcd)
 		ohci->flags |= OHCI_QUIRK_FRAME_NO;
 
 	ohci_hcd_init(ohci);
+
+	if (pdata->num_ports)
+		ohci->num_ports = pdata->num_ports;
+
 	err = ohci_init(ohci);
 
 	return err;
@@ -79,7 +83,7 @@ static const struct hc_driver ohci_platform_hc_driver = {
 	.start_port_reset	= ohci_start_port_reset,
 };
 
-static int __devinit ohci_platform_probe(struct platform_device *dev)
+static int ohci_platform_probe(struct platform_device *dev)
 {
 	struct usb_hcd *hcd;
 	struct resource *res_mem;
@@ -97,13 +101,13 @@ static int __devinit ohci_platform_probe(struct platform_device *dev)
 
 	irq = platform_get_irq(dev, 0);
 	if (irq < 0) {
-		pr_err("no irq provided");
+		dev_err(&dev->dev, "no irq provided");
 		return irq;
 	}
 
 	res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
 	if (!res_mem) {
-		pr_err("no memory recourse provided");
+		dev_err(&dev->dev, "no memory resource provided");
 		return -ENXIO;
 	}
 
@@ -123,29 +127,19 @@ static int __devinit ohci_platform_probe(struct platform_device *dev)
 	hcd->rsrc_start = res_mem->start;
 	hcd->rsrc_len = resource_size(res_mem);
 
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		pr_err("controller already in use");
-		err = -EBUSY;
-		goto err_put_hcd;
-	}
-
-	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+	hcd->regs = devm_request_and_ioremap(&dev->dev, res_mem);
 	if (!hcd->regs) {
 		err = -ENOMEM;
-		goto err_release_region;
+		goto err_put_hcd;
 	}
 	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (err)
-		goto err_iounmap;
+		goto err_put_hcd;
 
 	platform_set_drvdata(dev, hcd);
 
 	return err;
 
-err_iounmap:
-	iounmap(hcd->regs);
-err_release_region:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 err_put_hcd:
 	usb_put_hcd(hcd);
 err_power:
@@ -155,14 +149,12 @@ err_power:
 	return err;
 }
 
-static int __devexit ohci_platform_remove(struct platform_device *dev)
+static int ohci_platform_remove(struct platform_device *dev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(dev);
 	struct usb_ohci_pdata *pdata = dev->dev.platform_data;
 
 	usb_remove_hcd(hcd);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 	platform_set_drvdata(dev, NULL);
 
@@ -199,7 +191,7 @@ static int ohci_platform_resume(struct device *dev)
 			return err;
 	}
 
-	ohci_finish_controller_resume(hcd);
+	ohci_resume(hcd, false);
 	return 0;
 }
 
@@ -222,7 +214,7 @@ static const struct dev_pm_ops ohci_platform_pm_ops = {
 static struct platform_driver ohci_platform_driver = {
 	.id_table	= ohci_platform_table,
 	.probe		= ohci_platform_probe,
-	.remove		= __devexit_p(ohci_platform_remove),
+	.remove		= ohci_platform_remove,
 	.shutdown	= usb_hcd_platform_shutdown,
 	.driver		= {
 		.owner	= THIS_MODULE,
diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
deleted file mode 100644
index 148d27d..0000000
--- a/drivers/usb/host/ohci-pnx8550.c
+++ /dev/null
@@ -1,243 +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
- * (C) Copyright 2005 Embedded Alley Solutions, Inc.
- *
- * Bus Glue for PNX8550
- *
- * 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 PNX8550 from ohci-sa1111.c and sa-omap.c
- *  by Vitaly Wool <vitalywool@gmail.com>
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <asm/mach-pnx8550/usb.h>
-#include <asm/mach-pnx8550/int.h>
-#include <asm/mach-pnx8550/pci.h>
-
-#ifndef CONFIG_PNX8550
-#error "This file is PNX8550 bus glue.  CONFIG_PNX8550 must be defined."
-#endif
-
-extern int usb_disabled(void);
-
-/*-------------------------------------------------------------------------*/
-
-static void pnx8550_start_hc(struct platform_device *dev)
-{
-	/*
-	 * Set register CLK48CTL to enable and 48MHz
-	 */
-	outl(0x00000003, PCI_BASE | 0x0004770c);
-
-	/*
-	 * Set register CLK12CTL to enable and 48MHz
-	 */
-	outl(0x00000003, PCI_BASE | 0x00047710);
-
-	udelay(100);
-}
-
-static void pnx8550_stop_hc(struct platform_device *dev)
-{
-	udelay(10);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-
-/**
- * usb_hcd_pnx8550_probe - initialize pnx8550-based HCDs
- * Context: !in_interrupt()
- *
- * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- *
- */
-int usb_hcd_pnx8550_probe (const struct hc_driver *driver,
-			  struct platform_device *dev)
-{
-	int retval;
-	struct usb_hcd *hcd;
-
-	if (dev->resource[0].flags != IORESOURCE_MEM ||
-			dev->resource[1].flags != IORESOURCE_IRQ) {
-		dev_err (&dev->dev,"invalid resource type\n");
-		return -ENOMEM;
-	}
-
-	hcd = usb_create_hcd (driver, &dev->dev, "pnx8550");
-	if (!hcd)
-		return -ENOMEM;
-	hcd->rsrc_start = dev->resource[0].start;
-	hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
-
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		dev_err(&dev->dev, "request_mem_region [0x%08llx, 0x%08llx] "
-				"failed\n", hcd->rsrc_start, hcd->rsrc_len);
-		retval = -EBUSY;
-		goto err1;
-	}
-
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		dev_err(&dev->dev, "ioremap [[0x%08llx, 0x%08llx] failed\n",
-				hcd->rsrc_start, hcd->rsrc_len);
-		retval = -ENOMEM;
-		goto err2;
-	}
-
-	pnx8550_start_hc(dev);
-
-	ohci_hcd_init(hcd_to_ohci(hcd));
-
-	retval = usb_add_hcd(hcd, dev->resource[1].start, 0);
-	if (retval == 0)
-		return retval;
-
-	pnx8550_stop_hc(dev);
-	iounmap(hcd->regs);
- err2:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- err1:
-	usb_put_hcd(hcd);
-	return retval;
-}
-
-
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
-/**
- * usb_hcd_pnx8550_remove - shutdown processing for pnx8550-based HCDs
- * @dev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_hcd_pnx8550_probe(), first invoking
- * the HCD's stop() method.  It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- */
-void usb_hcd_pnx8550_remove (struct usb_hcd *hcd, struct platform_device *dev)
-{
-	usb_remove_hcd(hcd);
-	pnx8550_stop_hc(dev);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-	usb_put_hcd(hcd);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int __devinit
-ohci_pnx8550_start (struct usb_hcd *hcd)
-{
-	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
-	int		ret;
-
-	ohci_dbg (ohci, "ohci_pnx8550_start, ohci:%p", ohci);
-
-	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_pnx8550_hc_driver = {
-	.description =		hcd_name,
-	.product_desc =		"PNX8550 OHCI",
-	.hcd_priv_size =	sizeof(struct ohci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq =			ohci_irq,
-	.flags =		HCD_USB11 | HCD_MEMORY,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.start =		ohci_pnx8550_start,
-	.stop =			ohci_stop,
-
-	/*
-	 * 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_pnx8550_drv_probe(struct platform_device *pdev)
-{
-	int ret;
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	ret = usb_hcd_pnx8550_probe(&ohci_pnx8550_hc_driver, pdev);
-	return ret;
-}
-
-static int ohci_hcd_pnx8550_drv_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_hcd_pnx8550_remove(hcd, pdev);
-	return 0;
-}
-
-MODULE_ALIAS("platform:pnx8550-ohci");
-
-static struct platform_driver ohci_hcd_pnx8550_driver = {
-	.driver = {
-		.name	= "pnx8550-ohci",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= ohci_hcd_pnx8550_drv_probe,
-	.remove		= ohci_hcd_pnx8550_drv_remove,
-};
-
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
index e27d5ae..64c2ed9f 100644
--- a/drivers/usb/host/ohci-ppc-of.c
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -19,7 +19,7 @@
 #include <asm/prom.h>
 
 
-static int __devinit
+static int
 ohci_ppc_of_start(struct usb_hcd *hcd)
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
@@ -81,7 +81,7 @@ static const struct hc_driver ohci_ppc_of_hc_driver = {
 };
 
 
-static int __devinit ohci_hcd_ppc_of_probe(struct platform_device *op)
+static int ohci_hcd_ppc_of_probe(struct platform_device *op)
 {
 	struct device_node *dn = op->dev.of_node;
 	struct usb_hcd *hcd;
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
deleted file mode 100644
index 185c39e..0000000
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ /dev/null
@@ -1,216 +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
- * (C) Copyright 2003-2005 MontaVista Software Inc.
- *
- * Bus Glue for PPC On-Chip OHCI driver
- * Tested on Freescale MPC5200 and IBM STB04xxx
- *
- * Modified by Dale Farnsworth <dale@farnsworth.org> from ohci-sa1111.c
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/platform_device.h>
-#include <linux/signal.h>
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-/**
- * usb_hcd_ppc_soc_probe - initialize On-Chip HCDs
- * Context: !in_interrupt()
- *
- * Allocates basic resources for this USB host controller.
- *
- * Store this function in the HCD's struct pci_driver as probe().
- */
-static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
-			  struct platform_device *pdev)
-{
-	int retval;
-	struct usb_hcd *hcd;
-	struct ohci_hcd	*ohci;
-	struct resource *res;
-	int irq;
-
-	pr_debug("initializing PPC-SOC USB Controller\n");
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		pr_debug("%s: no irq\n", __FILE__);
-		return -ENODEV;
-	}
-	irq = res->start;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		pr_debug("%s: no reg addr\n", __FILE__);
-		return -ENODEV;
-	}
-
-	hcd = usb_create_hcd(driver, &pdev->dev, "PPC-SOC USB");
-	if (!hcd)
-		return -ENOMEM;
-	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_size(res);
-
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		pr_debug("%s: request_mem_region failed\n", __FILE__);
-		retval = -EBUSY;
-		goto err1;
-	}
-
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		pr_debug("%s: ioremap failed\n", __FILE__);
-		retval = -ENOMEM;
-		goto err2;
-	}
-
-	ohci = hcd_to_ohci(hcd);
-	ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
-
-#ifdef CONFIG_PPC_MPC52xx
-	/* MPC52xx doesn't need frame_no shift */
-	ohci->flags |= OHCI_QUIRK_FRAME_NO;
-#endif
-	ohci_hcd_init(ohci);
-
-	retval = usb_add_hcd(hcd, irq, 0);
-	if (retval == 0)
-		return retval;
-
-	pr_debug("Removing PPC-SOC USB Controller\n");
-
-	iounmap(hcd->regs);
- err2:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- err1:
-	usb_put_hcd(hcd);
-	return retval;
-}
-
-
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
-/**
- * usb_hcd_ppc_soc_remove - shutdown processing for On-Chip HCDs
- * @pdev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_hcd_ppc_soc_probe().
- * It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- */
-static void usb_hcd_ppc_soc_remove(struct usb_hcd *hcd,
-		struct platform_device *pdev)
-{
-	usb_remove_hcd(hcd);
-
-	pr_debug("stopping PPC-SOC USB Controller\n");
-
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-	usb_put_hcd(hcd);
-}
-
-static int __devinit
-ohci_ppc_soc_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 const struct hc_driver ohci_ppc_soc_hc_driver = {
-	.description =		hcd_name,
-	.hcd_priv_size =	sizeof(struct ohci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq =			ohci_irq,
-	.flags =		HCD_USB11 | HCD_MEMORY,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.start =		ohci_ppc_soc_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_ppc_soc_drv_probe(struct platform_device *pdev)
-{
-	int ret;
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	ret = usb_hcd_ppc_soc_probe(&ohci_ppc_soc_hc_driver, pdev);
-	return ret;
-}
-
-static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_hcd_ppc_soc_remove(hcd, pdev);
-	return 0;
-}
-
-static struct platform_driver ohci_hcd_ppc_soc_driver = {
-	.probe		= ohci_hcd_ppc_soc_drv_probe,
-	.remove		= ohci_hcd_ppc_soc_drv_remove,
-	.shutdown	= usb_hcd_platform_shutdown,
-#ifdef	CONFIG_PM
-	/*.suspend	= ohci_hcd_ppc_soc_drv_suspend,*/
-	/*.resume	= ohci_hcd_ppc_soc_drv_resume,*/
-#endif
-	.driver		= {
-		.name	= "ppc-soc-ohci",
-		.owner	= THIS_MODULE,
-	},
-};
-
-MODULE_ALIAS("platform:ppc-soc-ohci");
diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
index 2ee1d8d..7d35cd9 100644
--- a/drivers/usb/host/ohci-ps3.c
+++ b/drivers/usb/host/ohci-ps3.c
@@ -30,7 +30,7 @@ static int ps3_ohci_hc_reset(struct usb_hcd *hcd)
 	return ohci_init(ohci);
 }
 
-static int __devinit ps3_ohci_hc_start(struct usb_hcd *hcd)
+static int ps3_ohci_hc_start(struct usb_hcd *hcd)
 {
 	int result;
 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
@@ -76,7 +76,7 @@ static const struct hc_driver ps3_ohci_hc_driver = {
 #endif
 };
 
-static int __devinit ps3_ohci_probe(struct ps3_system_bus_device *dev)
+static int ps3_ohci_probe(struct ps3_system_bus_device *dev)
 {
 	int result;
 	struct usb_hcd *hcd;
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 2bf1144..efe71f3 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -284,7 +284,7 @@ MODULE_DEVICE_TABLE(of, pxa_ohci_dt_ids);
 
 static u64 pxa_ohci_dma_mask = DMA_BIT_MASK(32);
 
-static int __devinit ohci_pxa_of_init(struct platform_device *pdev)
+static int ohci_pxa_of_init(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct pxaohci_platform_data *pdata;
@@ -330,7 +330,7 @@ static int __devinit ohci_pxa_of_init(struct platform_device *pdev)
 	return 0;
 }
 #else
-static int __devinit ohci_pxa_of_init(struct platform_device *pdev)
+static int ohci_pxa_of_init(struct platform_device *pdev)
 {
 	return 0;
 }
@@ -471,7 +471,7 @@ void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev)
 
 /*-------------------------------------------------------------------------*/
 
-static int __devinit
+static int
 ohci_pxa27x_start (struct usb_hcd *hcd)
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
@@ -591,7 +591,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct device *dev)
 	/* Select Power Management Mode */
 	pxa27x_ohci_select_pmm(ohci, inf->port_mode);
 
-	ohci_finish_controller_resume(hcd);
+	ohci_resume(hcd, false);
 	return 0;
 }
 
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index c5a1ea9..7482cfb 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -596,7 +596,6 @@ static void td_submit_urb (
 		urb_priv->ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_C);
 	}
 
-	urb_priv->td_cnt = 0;
 	list_add (&urb_priv->pending, &ohci->pending);
 
 	if (data_len)
@@ -672,7 +671,8 @@ static void td_submit_urb (
 	 * we could often reduce the number of TDs here.
 	 */
 	case PIPE_ISOCHRONOUS:
-		for (cnt = 0; cnt < urb->number_of_packets; cnt++) {
+		for (cnt = urb_priv->td_cnt; cnt < urb->number_of_packets;
+				cnt++) {
 			int	frame = urb->start_frame;
 
 			// FIXME scheduling should handle frame counter
@@ -1128,6 +1128,25 @@ dl_done_list (struct ohci_hcd *ohci)
 
 	while (td) {
 		struct td	*td_next = td->next_dl_td;
+		struct ed	*ed = td->ed;
+
+		/*
+		 * Some OHCI controllers (NVIDIA for sure, maybe others)
+		 * occasionally forget to add TDs to the done queue.  Since
+		 * TDs for a given endpoint are always processed in order,
+		 * if we find a TD on the donelist then all of its
+		 * predecessors must be finished as well.
+		 */
+		for (;;) {
+			struct td	*td2;
+
+			td2 = list_first_entry(&ed->td_list, struct td,
+					td_list);
+			if (td2 == td)
+				break;
+			takeback_td(ohci, td2);
+		}
+
 		takeback_td(ohci, td);
 		td = td_next;
 	}
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 0d2309c..ad0f552 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -323,8 +323,6 @@ usb_hcd_s3c2410_remove(struct usb_hcd *hcd, struct platform_device *dev)
 {
 	usb_remove_hcd(hcd);
 	s3c2410_stop_hc(dev);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 }
 
@@ -353,35 +351,29 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,
 	hcd->rsrc_start = dev->resource[0].start;
 	hcd->rsrc_len	= resource_size(&dev->resource[0]);
 
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		dev_err(&dev->dev, "request_mem_region failed\n");
-		retval = -EBUSY;
+	hcd->regs = devm_request_and_ioremap(&dev->dev, &dev->resource[0]);
+	if (!hcd->regs) {
+		dev_err(&dev->dev, "devm_request_and_ioremap failed\n");
+		retval = -ENOMEM;
 		goto err_put;
 	}
 
-	clk = clk_get(&dev->dev, "usb-host");
+	clk = devm_clk_get(&dev->dev, "usb-host");
 	if (IS_ERR(clk)) {
 		dev_err(&dev->dev, "cannot get usb-host clock\n");
 		retval = PTR_ERR(clk);
-		goto err_mem;
+		goto err_put;
 	}
 
-	usb_clk = clk_get(&dev->dev, "usb-bus-host");
+	usb_clk = devm_clk_get(&dev->dev, "usb-bus-host");
 	if (IS_ERR(usb_clk)) {
 		dev_err(&dev->dev, "cannot get usb-bus-host clock\n");
 		retval = PTR_ERR(usb_clk);
-		goto err_clk;
+		goto err_put;
 	}
 
 	s3c2410_start_hc(dev, hcd);
 
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		dev_err(&dev->dev, "ioremap failed\n");
-		retval = -ENOMEM;
-		goto err_ioremap;
-	}
-
 	ohci_hcd_init(hcd_to_ohci(hcd));
 
 	retval = usb_add_hcd(hcd, dev->resource[1].start, 0);
@@ -392,14 +384,6 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,
 
  err_ioremap:
 	s3c2410_stop_hc(dev);
-	iounmap(hcd->regs);
-	clk_put(usb_clk);
-
- err_clk:
-	clk_put(clk);
-
- err_mem:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 
  err_put:
 	usb_put_hcd(hcd);
@@ -474,12 +458,12 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
 
 /* device driver */
 
-static int __devinit ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev)
+static int ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev)
 {
 	return usb_hcd_s3c2410_probe(&ohci_s3c2410_hc_driver, pdev);
 }
 
-static int __devexit ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev)
+static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
@@ -524,8 +508,7 @@ static int ohci_hcd_s3c2410_drv_resume(struct device *dev)
 
 	s3c2410_start_hc(pdev, hcd);
 
-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-	ohci_finish_controller_resume(hcd);
+	ohci_resume(hcd, false);
 
 	return 0;
 }
@@ -541,7 +524,7 @@ static const struct dev_pm_ops ohci_hcd_s3c2410_pm_ops = {
 
 static struct platform_driver ohci_hcd_s3c2410_driver = {
 	.probe		= ohci_hcd_s3c2410_drv_probe,
-	.remove		= __devexit_p(ohci_hcd_s3c2410_drv_remove),
+	.remove		= ohci_hcd_s3c2410_drv_remove,
 	.shutdown	= usb_hcd_platform_shutdown,
 	.driver		= {
 		.owner	= THIS_MODULE,
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index b6cc925..17b2a7d 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -63,7 +63,7 @@ static int ohci_sa1111_reset(struct usb_hcd *hcd)
 	return ohci_init(ohci);
 }
 
-static int __devinit ohci_sa1111_start(struct usb_hcd *hcd)
+static int ohci_sa1111_start(struct usb_hcd *hcd)
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
 	int ret;
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
deleted file mode 100644
index 76a20c2..0000000
--- a/drivers/usb/host/ohci-sh.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * Copyright (C) 2008 Renesas Solutions Corp.
- *
- * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#include <linux/platform_device.h>
-
-static int ohci_sh_start(struct usb_hcd *hcd)
-{
-	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
-
-	ohci_hcd_init(ohci);
-	ohci_init(ohci);
-	ohci_run(ohci);
-	return 0;
-}
-
-static const struct hc_driver ohci_sh_hc_driver = {
-	.description =		hcd_name,
-	.product_desc =		"SuperH OHCI",
-	.hcd_priv_size =	sizeof(struct ohci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq =			ohci_irq,
-	.flags =		HCD_USB11 | HCD_MEMORY,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.start =		ohci_sh_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_sh_probe(struct platform_device *pdev)
-{
-	struct resource *res = NULL;
-	struct usb_hcd *hcd = NULL;
-	int irq = -1;
-	int ret;
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "platform_get_resource error.\n");
-		return -ENODEV;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "platform_get_irq error.\n");
-		return -ENODEV;
-	}
-
-	/* initialize hcd */
-	hcd = usb_create_hcd(&ohci_sh_hc_driver, &pdev->dev, (char *)hcd_name);
-	if (!hcd) {
-		dev_err(&pdev->dev, "Failed to create hcd\n");
-		return -ENOMEM;
-	}
-
-	hcd->regs = (void __iomem *)res->start;
-	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_size(res);
-	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
-	if (ret != 0) {
-		dev_err(&pdev->dev, "Failed to add hcd\n");
-		usb_put_hcd(hcd);
-		return ret;
-	}
-
-	return ret;
-}
-
-static int ohci_hcd_sh_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_remove_hcd(hcd);
-	usb_put_hcd(hcd);
-
-	return 0;
-}
-
-static struct platform_driver ohci_hcd_sh_driver = {
-	.probe		= ohci_hcd_sh_probe,
-	.remove		= ohci_hcd_sh_remove,
-	.shutdown	= usb_hcd_platform_shutdown,
-	.driver		= {
-		.name	= "sh_ohci",
-		.owner	= THIS_MODULE,
-	},
-};
-
-MODULE_ALIAS("platform:sh_ohci");
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
index 5596ac2..3b5b908 100644
--- a/drivers/usb/host/ohci-sm501.c
+++ b/drivers/usb/host/ohci-sm501.c
@@ -238,7 +238,7 @@ static int ohci_sm501_resume(struct platform_device *pdev)
 	ohci->next_statechange = jiffies;
 
 	sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
-	ohci_finish_controller_resume(hcd);
+	ohci_resume(hcd, false);
 	return 0;
 }
 #else
diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
index fc7305e..9020bf0 100644
--- a/drivers/usb/host/ohci-spear.c
+++ b/drivers/usb/host/ohci-spear.c
@@ -33,7 +33,7 @@ static void spear_stop_ohci(struct spear_ohci *ohci)
 	clk_disable_unprepare(ohci->clk);
 }
 
-static int __devinit ohci_spear_start(struct usb_hcd *hcd)
+static int ohci_spear_start(struct usb_hcd *hcd)
 {
 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
 	int ret;
@@ -101,13 +101,11 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
 	struct spear_ohci *ohci_p;
 	struct resource *res;
 	int retval, irq;
-	char clk_name[20] = "usbh_clk";
-	static int instance = -1;
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		retval = irq;
-		goto fail_irq_get;
+		goto fail;
 	}
 
 	/*
@@ -118,47 +116,39 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
 	if (!pdev->dev.dma_mask)
 		pdev->dev.dma_mask = &spear_ohci_dma_mask;
 
-	/*
-	 * Increment the device instance, when probing via device-tree
-	 */
-	if (pdev->id < 0)
-		instance++;
-	else
-		instance = pdev->id;
-	sprintf(clk_name, "usbh.%01d_clk", instance);
-
-	usbh_clk = clk_get(NULL, clk_name);
+	usbh_clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(usbh_clk)) {
 		dev_err(&pdev->dev, "Error getting interface clock\n");
 		retval = PTR_ERR(usbh_clk);
-		goto fail_get_usbh_clk;
+		goto fail;
 	}
 
 	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
 	if (!hcd) {
 		retval = -ENOMEM;
-		goto fail_create_hcd;
+		goto fail;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		retval = -ENODEV;
-		goto fail_request_resource;
+		goto err_put_hcd;
 	}
 
 	hcd->rsrc_start = pdev->resource[0].start;
 	hcd->rsrc_len = resource_size(res);
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+	if (!devm_request_mem_region(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len,
+				hcd_name)) {
 		dev_dbg(&pdev->dev, "request_mem_region failed\n");
 		retval = -EBUSY;
-		goto fail_request_resource;
+		goto err_put_hcd;
 	}
 
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	hcd->regs = devm_ioremap(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len);
 	if (!hcd->regs) {
 		dev_dbg(&pdev->dev, "ioremap failed\n");
 		retval = -ENOMEM;
-		goto fail_ioremap;
+		goto err_put_hcd;
 	}
 
 	ohci_p = (struct spear_ohci *)hcd_to_ohci(hcd);
@@ -171,15 +161,9 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
 		return retval;
 
 	spear_stop_ohci(ohci_p);
-	iounmap(hcd->regs);
-fail_ioremap:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-fail_request_resource:
+err_put_hcd:
 	usb_put_hcd(hcd);
-fail_create_hcd:
-	clk_put(usbh_clk);
-fail_get_usbh_clk:
-fail_irq_get:
+fail:
 	dev_err(&pdev->dev, "init fail, %d\n", retval);
 
 	return retval;
@@ -194,12 +178,8 @@ static int spear_ohci_hcd_drv_remove(struct platform_device *pdev)
 	if (ohci_p->clk)
 		spear_stop_ohci(ohci_p);
 
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 
-	if (ohci_p->clk)
-		clk_put(ohci_p->clk);
 	platform_set_drvdata(pdev, NULL);
 	return 0;
 }
@@ -231,12 +211,12 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev)
 	ohci->next_statechange = jiffies;
 
 	spear_start_ohci(ohci_p);
-	ohci_finish_controller_resume(hcd);
+	ohci_resume(hcd, false);
 	return 0;
 }
 #endif
 
-static struct of_device_id spear_ohci_id_table[] __devinitdata = {
+static struct of_device_id spear_ohci_id_table[] = {
 	{ .compatible = "st,spear600-ohci", },
 	{ },
 };
diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
index 60c2b07..d370245 100644
--- a/drivers/usb/host/ohci-tmio.c
+++ b/drivers/usb/host/ohci-tmio.c
@@ -184,7 +184,7 @@ static const struct hc_driver ohci_tmio_hc_driver = {
 /*-------------------------------------------------------------------------*/
 static struct platform_driver ohci_hcd_tmio_driver;
 
-static int __devinit ohci_hcd_tmio_drv_probe(struct platform_device *dev)
+static int ohci_hcd_tmio_drv_probe(struct platform_device *dev)
 {
 	const struct mfd_cell *cell = mfd_get_cell(dev);
 	struct resource *regs = platform_get_resource(dev, IORESOURCE_MEM, 0);
@@ -271,7 +271,7 @@ err_usb_create_hcd:
 	return ret;
 }
 
-static int __devexit ohci_hcd_tmio_drv_remove(struct platform_device *dev)
+static int ohci_hcd_tmio_drv_remove(struct platform_device *dev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(dev);
 	struct tmio_hcd *tmio = hcd_to_tmio(hcd);
@@ -352,7 +352,7 @@ static int ohci_hcd_tmio_drv_resume(struct platform_device *dev)
 
 	spin_unlock_irqrestore(&tmio->lock, flags);
 
-	ohci_finish_controller_resume(hcd);
+	ohci_resume(hcd, false);
 
 	return 0;
 }
@@ -363,7 +363,7 @@ static int ohci_hcd_tmio_drv_resume(struct platform_device *dev)
 
 static struct platform_driver ohci_hcd_tmio_driver = {
 	.probe		= ohci_hcd_tmio_drv_probe,
-	.remove		= __devexit_p(ohci_hcd_tmio_drv_remove),
+	.remove		= ohci_hcd_tmio_drv_remove,
 	.shutdown	= usb_hcd_platform_shutdown,
 	.suspend	= ohci_hcd_tmio_drv_suspend,
 	.resume		= ohci_hcd_tmio_drv_resume,
diff --git a/drivers/usb/host/ohci-xls.c b/drivers/usb/host/ohci-xls.c
deleted file mode 100644
index 41e378f..0000000
--- a/drivers/usb/host/ohci-xls.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * OHCI HCD for Netlogic XLS processors.
- *
- * (C) Copyright 2011 Netlogic Microsystems Inc.
- *
- *  Based on ohci-au1xxx.c, and other Linux OHCI drivers.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/signal.h>
-
-static int ohci_xls_probe_internal(const struct hc_driver *driver,
-			struct platform_device *dev)
-{
-	struct resource *res;
-	struct usb_hcd *hcd;
-	int retval, irq;
-
-	/* Get our IRQ from an earlier registered Platform Resource */
-	irq = platform_get_irq(dev, 0);
-	if (irq < 0) {
-		dev_err(&dev->dev, "Found HC with no IRQ\n");
-		return -ENODEV;
-	}
-
-	/* Get our Memory Handle */
-	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&dev->dev, "MMIO Handle incorrect!\n");
-		return -ENODEV;
-	}
-
-	hcd = usb_create_hcd(driver, &dev->dev, "XLS");
-	if (!hcd) {
-		retval = -ENOMEM;
-		goto err1;
-	}
-	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_size(res);
-
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
-			driver->description)) {
-		dev_dbg(&dev->dev, "Controller already in use\n");
-		retval = -EBUSY;
-		goto err2;
-	}
-
-	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
-	if (hcd->regs == NULL) {
-		dev_dbg(&dev->dev, "error mapping memory\n");
-		retval = -EFAULT;
-		goto err3;
-	}
-
-	retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
-	if (retval != 0)
-		goto err4;
-	return retval;
-
-err4:
-	iounmap(hcd->regs);
-err3:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err2:
-	usb_put_hcd(hcd);
-err1:
-	dev_err(&dev->dev, "init fail, %d\n", retval);
-	return retval;
-}
-
-static int ohci_xls_reset(struct usb_hcd *hcd)
-{
-	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-
-	ohci_hcd_init(ohci);
-	return ohci_init(ohci);
-}
-
-static int __devinit ohci_xls_start(struct usb_hcd *hcd)
-{
-	struct ohci_hcd *ohci;
-	int ret;
-
-	ohci = hcd_to_ohci(hcd);
-	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 struct hc_driver ohci_xls_hc_driver = {
-	.description	= hcd_name,
-	.product_desc	= "XLS OHCI Host Controller",
-	.hcd_priv_size	= sizeof(struct ohci_hcd),
-	.irq		= ohci_irq,
-	.flags		= HCD_MEMORY | HCD_USB11,
-	.reset		= ohci_xls_reset,
-	.start		= ohci_xls_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_xls_probe(struct platform_device *dev)
-{
-	int ret;
-
-	pr_debug("In ohci_xls_probe");
-	if (usb_disabled())
-		return -ENODEV;
-	ret = ohci_xls_probe_internal(&ohci_xls_hc_driver, dev);
-	return ret;
-}
-
-static int ohci_xls_remove(struct platform_device *dev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(dev);
-
-	usb_remove_hcd(hcd);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-	usb_put_hcd(hcd);
-	return 0;
-}
-
-static struct platform_driver ohci_xls_driver = {
-	.probe		= ohci_xls_probe,
-	.remove		= ohci_xls_remove,
-	.shutdown	= usb_hcd_platform_shutdown,
-	.driver		= {
-		.name	= "ohci-xls-0",
-		.owner	= THIS_MODULE,
-	},
-};
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 39f9e4a..a3b6d71 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -443,7 +443,7 @@ static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask)
 #define pio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_IO)
 #define mmio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_MEMORY)
 
-static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
+static void quirk_usb_handoff_uhci(struct pci_dev *pdev)
 {
 	unsigned long base = 0;
 	int i;
@@ -461,12 +461,12 @@ static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
 		uhci_check_and_reset_hc(pdev, base);
 }
 
-static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx)
+static int mmio_resource_enabled(struct pci_dev *pdev, int idx)
 {
 	return pci_resource_start(pdev, idx) && mmio_enabled(pdev);
 }
 
-static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
+static void quirk_usb_handoff_ohci(struct pci_dev *pdev)
 {
 	void __iomem *base;
 	u32 control;
@@ -533,7 +533,7 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
 	iounmap(base);
 }
 
-static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {
+static const struct dmi_system_id ehci_dmi_nohandoff_table[] = {
 	{
 		/*  Pegatron Lucid (ExoPC) */
 		.matches = {
@@ -558,7 +558,7 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {
 	{ }
 };
 
-static void __devinit ehci_bios_handoff(struct pci_dev *pdev,
+static void ehci_bios_handoff(struct pci_dev *pdev,
 					void __iomem *op_reg_base,
 					u32 cap, u8 offset)
 {
@@ -626,7 +626,7 @@ static void __devinit ehci_bios_handoff(struct pci_dev *pdev,
 		writel(0, op_reg_base + EHCI_CONFIGFLAG);
 }
 
-static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
+static void quirk_usb_disable_ehci(struct pci_dev *pdev)
 {
 	void __iomem *base, *op_reg_base;
 	u32	hcc_params, cap, val;
@@ -723,6 +723,7 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done,
 }
 
 #define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI	0x8C31
+#define PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI	0x9C31
 
 bool usb_is_intel_ppt_switchable_xhci(struct pci_dev *pdev)
 {
@@ -736,7 +737,8 @@ bool usb_is_intel_lpt_switchable_xhci(struct pci_dev *pdev)
 {
 	return pdev->class == PCI_CLASS_SERIAL_USB_XHCI &&
 		pdev->vendor == PCI_VENDOR_ID_INTEL &&
-		pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI;
+		(pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI ||
+		 pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI);
 }
 
 bool usb_is_intel_switchable_xhci(struct pci_dev *pdev)
@@ -841,7 +843,7 @@ EXPORT_SYMBOL_GPL(usb_disable_xhci_ports);
  * and then waits 5 seconds for the BIOS to hand over control.
  * If we timeout, assume the BIOS is broken and take control anyway.
  */
-static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
+static void quirk_usb_handoff_xhci(struct pci_dev *pdev)
 {
 	void __iomem *base;
 	int ext_cap_offset;
@@ -941,7 +943,7 @@ hc_init:
 	iounmap(base);
 }
 
-static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
+static void quirk_usb_early_handoff(struct pci_dev *pdev)
 {
 	/* Skip Netlogic mips SoC's internal PCI USB controller.
 	 * This device does not need/support EHCI/OHCI handoff
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index fcc09e5..a6fd8f53 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -2036,10 +2036,8 @@ static void collect_usb_address_map(struct usb_device *udev, unsigned long *map)
 	    udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB)
 		map[udev->devnum/32] |= (1 << (udev->devnum % 32));
 
-	usb_hub_for_each_child(udev, chix, childdev) {
-		if (childdev)
-			collect_usb_address_map(childdev, map);
-	}
+	usb_hub_for_each_child(udev, chix, childdev)
+		collect_usb_address_map(childdev, map);
 }
 
 /* this function must be called with interrupt disabled */
@@ -2393,7 +2391,7 @@ static const struct dev_pm_ops r8a66597_dev_pm_ops = {
 #define R8A66597_DEV_PM_OPS	NULL
 #endif
 
-static int __devexit r8a66597_remove(struct platform_device *pdev)
+static int r8a66597_remove(struct platform_device *pdev)
 {
 	struct r8a66597		*r8a66597 = dev_get_drvdata(&pdev->dev);
 	struct usb_hcd		*hcd = r8a66597_to_hcd(r8a66597);
@@ -2407,7 +2405,7 @@ static int __devexit r8a66597_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devinit r8a66597_probe(struct platform_device *pdev)
+static int r8a66597_probe(struct platform_device *pdev)
 {
 	char clk_name[8];
 	struct resource *res = NULL, *ires;
@@ -2534,7 +2532,7 @@ clean_up:
 
 static struct platform_driver r8a66597_driver = {
 	.probe =	r8a66597_probe,
-	.remove =	__devexit_p(r8a66597_remove),
+	.remove =	r8a66597_remove,
 	.driver		= {
 		.name = (char *) hcd_name,
 		.owner	= THIS_MODULE,
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 619b05f..d62f040 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1595,7 +1595,7 @@ static struct hc_driver sl811h_hc_driver = {
 
 /*-------------------------------------------------------------------------*/
 
-static int __devexit
+static int
 sl811h_remove(struct platform_device *dev)
 {
 	struct usb_hcd		*hcd = platform_get_drvdata(dev);
@@ -1618,7 +1618,7 @@ sl811h_remove(struct platform_device *dev)
 	return 0;
 }
 
-static int __devinit
+static int
 sl811h_probe(struct platform_device *dev)
 {
 	struct usb_hcd		*hcd;
@@ -1808,7 +1808,7 @@ sl811h_resume(struct platform_device *dev)
 /* this driver is exported so sl811_cs can depend on it */
 struct platform_driver sl811h_driver = {
 	.probe =	sl811h_probe,
-	.remove =	__devexit_p(sl811h_remove),
+	.remove =	sl811h_remove,
 
 	.suspend =	sl811h_suspend,
 	.resume =	sl811h_resume,
diff --git a/drivers/usb/host/ssb-hcd.c b/drivers/usb/host/ssb-hcd.c
index c2a29fa..74af2c6 100644
--- a/drivers/usb/host/ssb-hcd.c
+++ b/drivers/usb/host/ssb-hcd.c
@@ -39,7 +39,7 @@ struct ssb_hcd_device {
 	u32 enable_flags;
 };
 
-static void __devinit ssb_hcd_5354wa(struct ssb_device *dev)
+static void ssb_hcd_5354wa(struct ssb_device *dev)
 {
 #ifdef CONFIG_SSB_DRIVER_MIPS
 	/* Work around for 5354 failures */
@@ -53,7 +53,7 @@ static void __devinit ssb_hcd_5354wa(struct ssb_device *dev)
 #endif
 }
 
-static void __devinit ssb_hcd_usb20wa(struct ssb_device *dev)
+static void ssb_hcd_usb20wa(struct ssb_device *dev)
 {
 	if (dev->id.coreid == SSB_DEV_USB20_HOST) {
 		/*
@@ -80,7 +80,7 @@ static void __devinit ssb_hcd_usb20wa(struct ssb_device *dev)
 }
 
 /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
-static u32 __devinit ssb_hcd_init_chip(struct ssb_device *dev)
+static u32 ssb_hcd_init_chip(struct ssb_device *dev)
 {
 	u32 flags = 0;
 
@@ -101,8 +101,7 @@ static const struct usb_ehci_pdata ehci_pdata = {
 static const struct usb_ohci_pdata ohci_pdata = {
 };
 
-static struct platform_device * __devinit
-ssb_hcd_create_pdev(struct ssb_device *dev, bool ohci, u32 addr, u32 len)
+static struct platform_device *ssb_hcd_create_pdev(struct ssb_device *dev, bool ohci, u32 addr, u32 len)
 {
 	struct platform_device *hci_dev;
 	struct resource hci_res[2];
@@ -148,7 +147,7 @@ err_alloc:
 	return ERR_PTR(ret);
 }
 
-static int __devinit ssb_hcd_probe(struct ssb_device *dev,
+static int ssb_hcd_probe(struct ssb_device *dev,
 				   const struct ssb_device_id *id)
 {
 	int err, tmp;
@@ -207,7 +206,7 @@ err_free_usb_dev:
 	return err;
 }
 
-static void __devexit ssb_hcd_remove(struct ssb_device *dev)
+static void ssb_hcd_remove(struct ssb_device *dev)
 {
 	struct ssb_hcd_device *usb_dev = ssb_get_drvdata(dev);
 	struct platform_device *ohci_dev = usb_dev->ohci_dev;
@@ -221,7 +220,7 @@ static void __devexit ssb_hcd_remove(struct ssb_device *dev)
 	ssb_device_disable(dev, 0);
 }
 
-static void __devexit ssb_hcd_shutdown(struct ssb_device *dev)
+static void ssb_hcd_shutdown(struct ssb_device *dev)
 {
 	ssb_device_disable(dev, 0);
 }
@@ -249,7 +248,7 @@ static int ssb_hcd_resume(struct ssb_device *dev)
 #define ssb_hcd_resume	NULL
 #endif /* CONFIG_PM */
 
-static const struct ssb_device_id ssb_hcd_table[] __devinitconst = {
+static const struct ssb_device_id ssb_hcd_table[] = {
 	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
 	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
 	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
@@ -261,7 +260,7 @@ static struct ssb_driver ssb_hcd_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= ssb_hcd_table,
 	.probe		= ssb_hcd_probe,
-	.remove		= __devexit_p(ssb_hcd_remove),
+	.remove		= ssb_hcd_remove,
 	.shutdown	= ssb_hcd_shutdown,
 	.suspend	= ssb_hcd_suspend,
 	.resume		= ssb_hcd_resume,
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index dbbd1ba..5efdffe 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -2990,7 +2990,7 @@ static struct hc_driver u132_hc_driver = {
 * synchronously - but instead should immediately stop activity to the
 * device and asynchronously call usb_remove_hcd()
 */
-static int __devexit u132_remove(struct platform_device *pdev)
+static int u132_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 	if (hcd) {
@@ -3084,7 +3084,7 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
 	mutex_unlock(&u132->sw_lock);
 }
 
-static int __devinit u132_probe(struct platform_device *pdev)
+static int u132_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
 	int retval;
@@ -3212,7 +3212,7 @@ static int u132_resume(struct platform_device *pdev)
 */
 static struct platform_driver u132_platform_driver = {
 	.probe = u132_probe,
-	.remove = __devexit_p(u132_remove),
+	.remove = u132_remove,
 	.suspend = u132_suspend,
 	.resume = u132_resume,
 	.driver = {
diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c
index f7a6213..511bfc4 100644
--- a/drivers/usb/host/uhci-grlib.c
+++ b/drivers/usb/host/uhci-grlib.c
@@ -85,7 +85,7 @@ static const struct hc_driver uhci_grlib_hc_driver = {
 };
 
 
-static int __devinit uhci_hcd_grlib_probe(struct platform_device *op)
+static int uhci_hcd_grlib_probe(struct platform_device *op)
 {
 	struct device_node *dn = op->dev.of_node;
 	struct usb_hcd *hcd;
diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
index 68ebf20..8c4dace 100644
--- a/drivers/usb/host/uhci-platform.c
+++ b/drivers/usb/host/uhci-platform.c
@@ -62,7 +62,7 @@ static const struct hc_driver uhci_platform_hc_driver = {
 
 static u64 platform_uhci_dma_mask = DMA_BIT_MASK(32);
 
-static int __devinit uhci_hcd_platform_probe(struct platform_device *pdev)
+static int uhci_hcd_platform_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
 	struct uhci_hcd	*uhci;
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index d2c6f5a..15921fd 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -1256,7 +1256,8 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
 		struct uhci_qh *qh)
 {
 	struct uhci_td *td = NULL;	/* Since urb->number_of_packets > 0 */
-	int i, frame;
+	int i;
+	unsigned frame, next;
 	unsigned long destination, status;
 	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
 
@@ -1265,37 +1266,29 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
 			urb->number_of_packets >= UHCI_NUMFRAMES)
 		return -EFBIG;
 
+	uhci_get_current_frame_number(uhci);
+
 	/* Check the period and figure out the starting frame number */
 	if (!qh->bandwidth_reserved) {
 		qh->period = urb->interval;
-		if (urb->transfer_flags & URB_ISO_ASAP) {
-			qh->phase = -1;		/* Find the best phase */
-			i = uhci_check_bandwidth(uhci, qh);
-			if (i)
-				return i;
-
-			/* Allow a little time to allocate the TDs */
-			uhci_get_current_frame_number(uhci);
-			frame = uhci->frame_number + 10;
-
-			/* Move forward to the first frame having the
-			 * correct phase */
-			urb->start_frame = frame + ((qh->phase - frame) &
-					(qh->period - 1));
-		} else {
-			i = urb->start_frame - uhci->last_iso_frame;
-			if (i <= 0 || i >= UHCI_NUMFRAMES)
-				return -EINVAL;
-			qh->phase = urb->start_frame & (qh->period - 1);
-			i = uhci_check_bandwidth(uhci, qh);
-			if (i)
-				return i;
-		}
+		qh->phase = -1;		/* Find the best phase */
+		i = uhci_check_bandwidth(uhci, qh);
+		if (i)
+			return i;
+
+		/* Allow a little time to allocate the TDs */
+		next = uhci->frame_number + 10;
+		frame = qh->phase;
+
+		/* Round up to the first available slot */
+		frame += (next - frame + qh->period - 1) & -qh->period;
 
 	} else if (qh->period != urb->interval) {
 		return -EINVAL;		/* Can't change the period */
 
 	} else {
+		next = uhci->frame_number + 2;
+
 		/* Find the next unused frame */
 		if (list_empty(&qh->queue)) {
 			frame = qh->iso_frame;
@@ -1308,25 +1301,31 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
 					lurb->number_of_packets *
 					lurb->interval;
 		}
-		if (urb->transfer_flags & URB_ISO_ASAP) {
-			/* Skip some frames if necessary to insure
-			 * the start frame is in the future.
+
+		/* Fell behind? */
+		if (uhci_frame_before_eq(frame, next)) {
+
+			/* USB_ISO_ASAP: Round up to the first available slot */
+			if (urb->transfer_flags & URB_ISO_ASAP)
+				frame += (next - frame + qh->period - 1) &
+						-qh->period;
+
+			/*
+			 * Not ASAP: Use the next slot in the stream.  If
+			 * the entire URB falls before the threshold, fail.
 			 */
-			uhci_get_current_frame_number(uhci);
-			if (uhci_frame_before_eq(frame, uhci->frame_number)) {
-				frame = uhci->frame_number + 1;
-				frame += ((qh->phase - frame) &
-					(qh->period - 1));
-			}
-		}	/* Otherwise pick up where the last URB leaves off */
-		urb->start_frame = frame;
+			else if (!uhci_frame_before_eq(next,
+					frame + (urb->number_of_packets - 1) *
+						qh->period))
+				return -EXDEV;
+		}
 	}
 
 	/* Make sure we won't have to go too far into the future */
 	if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES,
-			urb->start_frame + urb->number_of_packets *
-				urb->interval))
+			frame + urb->number_of_packets * urb->interval))
 		return -EFBIG;
+	urb->start_frame = frame;
 
 	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 487bc08..fb51c70 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -205,7 +205,12 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
 
 		next = xhci_segment_alloc(xhci, cycle_state, flags);
 		if (!next) {
-			xhci_free_segments_for_ring(xhci, *first);
+			prev = *first;
+			while (prev) {
+				next = prev->next;
+				xhci_segment_free(xhci, prev);
+				prev = next;
+			}
 			return -ENOMEM;
 		}
 		xhci_link_segments(xhci, prev, next, type);
@@ -258,7 +263,7 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
 	return ring;
 
 fail:
-	xhci_ring_free(xhci, ring);
+	kfree(ring);
 	return NULL;
 }
 
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 8345d7c..af259e0 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -29,6 +29,7 @@
 /* Device for a quirk */
 #define PCI_VENDOR_ID_FRESCO_LOGIC	0x1b73
 #define PCI_DEVICE_ID_FRESCO_LOGIC_PDK	0x1000
+#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400	0x1400
 
 #define PCI_VENDOR_ID_ETRON		0x1b6f
 #define PCI_DEVICE_ID_ASROCK_P67	0x7023
@@ -58,8 +59,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
 
 	/* Look for vendor-specific quirks */
 	if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
-			pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK) {
-		if (pdev->revision == 0x0) {
+			(pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK ||
+			 pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1400)) {
+		if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
+				pdev->revision == 0x0) {
 			xhci->quirks |= XHCI_RESET_EP_QUIRK;
 			xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
 					" endpoint cmd after reset endpoint\n");
@@ -218,15 +221,8 @@ static void xhci_pci_remove(struct pci_dev *dev)
 static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
-	int	retval = 0;
 
-	if (hcd->state != HC_STATE_SUSPENDED ||
-			xhci->shared_hcd->state != HC_STATE_SUSPENDED)
-		return -EINVAL;
-
-	retval = xhci_suspend(xhci);
-
-	return retval;
+	return xhci_suspend(xhci);
 }
 
 static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 4e1a894..cbb44b7 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -318,7 +318,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
 	 * seconds), then it should assume that the there are
 	 * larger problems with the xHC and assert HCRST.
 	 */
-	ret = handshake(xhci, &xhci->op_regs->cmd_ring,
+	ret = xhci_handshake(xhci, &xhci->op_regs->cmd_ring,
 			CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
 	if (ret < 0) {
 		xhci_err(xhci, "Stopped the command ring failed, "
@@ -3071,11 +3071,11 @@ static u32 xhci_td_remainder(unsigned int remainder)
 }
 
 /*
- * For xHCI 1.0 host controllers, TD size is the number of packets remaining in
- * the TD (*not* including this TRB).
+ * For xHCI 1.0 host controllers, TD size is the number of max packet sized
+ * packets remaining in the TD (*not* including this TRB).
  *
  * Total TD packet count = total_packet_count =
- *     roundup(TD size in bytes / wMaxPacketSize)
+ *     DIV_ROUND_UP(TD size in bytes / wMaxPacketSize)
  *
  * Packets transferred up to and including this TRB = packets_transferred =
  *     rounddown(total bytes transferred including this TRB / wMaxPacketSize)
@@ -3083,15 +3083,16 @@ static u32 xhci_td_remainder(unsigned int remainder)
  * TD size = total_packet_count - packets_transferred
  *
  * It must fit in bits 21:17, so it can't be bigger than 31.
+ * The last TRB in a TD must have the TD size set to zero.
  */
-
 static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
-		unsigned int total_packet_count, struct urb *urb)
+		unsigned int total_packet_count, struct urb *urb,
+		unsigned int num_trbs_left)
 {
 	int packets_transferred;
 
 	/* One TRB with a zero-length data packet. */
-	if (running_total == 0 && trb_buff_len == 0)
+	if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0))
 		return 0;
 
 	/* All the TRB queueing functions don't count the current TRB in
@@ -3100,7 +3101,9 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
 	packets_transferred = (running_total + trb_buff_len) /
 		usb_endpoint_maxp(&urb->ep->desc);
 
-	return xhci_td_remainder(total_packet_count - packets_transferred);
+	if ((total_packet_count - packets_transferred) > 31)
+		return 31 << 17;
+	return (total_packet_count - packets_transferred) << 17;
 }
 
 static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
@@ -3127,7 +3130,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 
 	num_trbs = count_sg_trbs_needed(xhci, urb);
 	num_sgs = urb->num_mapped_sgs;
-	total_packet_count = roundup(urb->transfer_buffer_length,
+	total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,
 			usb_endpoint_maxp(&urb->ep->desc));
 
 	trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
@@ -3210,7 +3213,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 					running_total);
 		} else {
 			remainder = xhci_v1_0_td_remainder(running_total,
-					trb_buff_len, total_packet_count, urb);
+					trb_buff_len, total_packet_count, urb,
+					num_trbs - 1);
 		}
 		length_field = TRB_LEN(trb_buff_len) |
 			remainder |
@@ -3318,7 +3322,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 	start_cycle = ep_ring->cycle_state;
 
 	running_total = 0;
-	total_packet_count = roundup(urb->transfer_buffer_length,
+	total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,
 			usb_endpoint_maxp(&urb->ep->desc));
 	/* How much data is in the first TRB? */
 	addr = (u64) urb->transfer_dma;
@@ -3364,7 +3368,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 					running_total);
 		} else {
 			remainder = xhci_v1_0_td_remainder(running_total,
-					trb_buff_len, total_packet_count, urb);
+					trb_buff_len, total_packet_count, urb,
+					num_trbs - 1);
 		}
 		length_field = TRB_LEN(trb_buff_len) |
 			remainder |
@@ -3627,7 +3632,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 		addr = start_addr + urb->iso_frame_desc[i].offset;
 		td_len = urb->iso_frame_desc[i].length;
 		td_remain_len = td_len;
-		total_packet_count = roundup(td_len,
+		total_packet_count = DIV_ROUND_UP(td_len,
 				usb_endpoint_maxp(&urb->ep->desc));
 		/* A zero-length transfer still involves at least one packet. */
 		if (total_packet_count == 0)
@@ -3706,7 +3711,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 			} else {
 				remainder = xhci_v1_0_td_remainder(
 						running_total, trb_buff_len,
-						total_packet_count, urb);
+						total_packet_count, urb,
+						(trbs_per_td - j - 1));
 			}
 			length_field = TRB_LEN(trb_buff_len) |
 				remainder |
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index c9e419f..5c72c43 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -40,7 +40,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB");
 
 /* TODO: copied from ehci-hcd.c - can this be refactored? */
 /*
- * handshake - spin reading hc until handshake completes or fails
+ * xhci_handshake - spin reading hc until handshake completes or fails
  * @ptr: address of hc register to be read
  * @mask: bits to look at in result of read
  * @done: value of those bits when handshake succeeds
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB");
  * handshake done).  There are two failure modes:  "usec" have passed (major
  * hardware flakeout), or the register reads as all-ones (hardware removed).
  */
-int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
+int xhci_handshake(struct xhci_hcd *xhci, void __iomem *ptr,
 		      u32 mask, u32 done, int usec)
 {
 	u32	result;
@@ -103,7 +103,7 @@ int xhci_halt(struct xhci_hcd *xhci)
 	xhci_dbg(xhci, "// Halt the HC\n");
 	xhci_quiesce(xhci);
 
-	ret = handshake(xhci, &xhci->op_regs->status,
+	ret = xhci_handshake(xhci, &xhci->op_regs->status,
 			STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
 	if (!ret) {
 		xhci->xhc_state |= XHCI_STATE_HALTED;
@@ -132,7 +132,7 @@ static int xhci_start(struct xhci_hcd *xhci)
 	 * Wait for the HCHalted Status bit to be 0 to indicate the host is
 	 * running.
 	 */
-	ret = handshake(xhci, &xhci->op_regs->status,
+	ret = xhci_handshake(xhci, &xhci->op_regs->status,
 			STS_HALT, 0, XHCI_MAX_HALT_USEC);
 	if (ret == -ETIMEDOUT)
 		xhci_err(xhci, "Host took too long to start, "
@@ -167,7 +167,7 @@ int xhci_reset(struct xhci_hcd *xhci)
 	command |= CMD_RESET;
 	xhci_writel(xhci, command, &xhci->op_regs->command);
 
-	ret = handshake(xhci, &xhci->op_regs->command,
+	ret = xhci_handshake(xhci, &xhci->op_regs->command,
 			CMD_RESET, 0, 10 * 1000 * 1000);
 	if (ret)
 		return ret;
@@ -177,7 +177,7 @@ int xhci_reset(struct xhci_hcd *xhci)
 	 * xHCI cannot write to any doorbells or operational registers other
 	 * than status until the "Controller Not Ready" flag is cleared.
 	 */
-	ret = handshake(xhci, &xhci->op_regs->status,
+	ret = xhci_handshake(xhci, &xhci->op_regs->status,
 			STS_CNR, 0, 10 * 1000 * 1000);
 
 	for (i = 0; i < 2; ++i) {
@@ -480,7 +480,7 @@ static bool compliance_mode_recovery_timer_quirk_check(void)
 	if (strstr(dmi_product_name, "Z420") ||
 			strstr(dmi_product_name, "Z620") ||
 			strstr(dmi_product_name, "Z820") ||
-			strstr(dmi_product_name, "Z1"))
+			strstr(dmi_product_name, "Z1 Workstation"))
 		return true;
 
 	return false;
@@ -880,6 +880,10 @@ int xhci_suspend(struct xhci_hcd *xhci)
 	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
 	u32			command;
 
+	if (hcd->state != HC_STATE_SUSPENDED ||
+			xhci->shared_hcd->state != HC_STATE_SUSPENDED)
+		return -EINVAL;
+
 	spin_lock_irq(&xhci->lock);
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
@@ -890,7 +894,7 @@ int xhci_suspend(struct xhci_hcd *xhci)
 	command = xhci_readl(xhci, &xhci->op_regs->command);
 	command &= ~CMD_RUN;
 	xhci_writel(xhci, command, &xhci->op_regs->command);
-	if (handshake(xhci, &xhci->op_regs->status,
+	if (xhci_handshake(xhci, &xhci->op_regs->status,
 		      STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) {
 		xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
 		spin_unlock_irq(&xhci->lock);
@@ -905,7 +909,8 @@ int xhci_suspend(struct xhci_hcd *xhci)
 	command = xhci_readl(xhci, &xhci->op_regs->command);
 	command |= CMD_CSS;
 	xhci_writel(xhci, command, &xhci->op_regs->command);
-	if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10 * 1000)) {
+	if (xhci_handshake(xhci, &xhci->op_regs->status,
+				STS_SAVE, 0, 10 * 1000)) {
 		xhci_warn(xhci, "WARN: xHC save state timeout\n");
 		spin_unlock_irq(&xhci->lock);
 		return -ETIMEDOUT;
@@ -967,7 +972,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 		command = xhci_readl(xhci, &xhci->op_regs->command);
 		command |= CMD_CRS;
 		xhci_writel(xhci, command, &xhci->op_regs->command);
-		if (handshake(xhci, &xhci->op_regs->status,
+		if (xhci_handshake(xhci, &xhci->op_regs->status,
 			      STS_RESTORE, 0, 10 * 1000)) {
 			xhci_warn(xhci, "WARN: xHC restore state timeout\n");
 			spin_unlock_irq(&xhci->lock);
@@ -1035,7 +1040,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 	command = xhci_readl(xhci, &xhci->op_regs->command);
 	command |= CMD_RUN;
 	xhci_writel(xhci, command, &xhci->op_regs->command);
-	handshake(xhci, &xhci->op_regs->status, STS_HALT,
+	xhci_handshake(xhci, &xhci->op_regs->status, STS_HALT,
 		  0, 250 * 1000);
 
 	/* step 5: walk topology and initialize portsc,
@@ -2254,7 +2259,7 @@ static bool xhci_is_async_ep(unsigned int ep_type)
 
 static bool xhci_is_sync_in_ep(unsigned int ep_type)
 {
-	return (ep_type == ISOC_IN_EP || ep_type != INT_IN_EP);
+	return (ep_type == ISOC_IN_EP || ep_type == INT_IN_EP);
 }
 
 static unsigned int xhci_get_ss_bw_consumed(struct xhci_bw_info *ep_bw)
@@ -3874,7 +3879,8 @@ static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd,
 	spin_lock_irqsave(&xhci->lock, flags);
 
 	/* Check L1 Status */
-	ret = handshake(xhci, pm_addr, PORT_L1S_MASK, PORT_L1S_SUCCESS, 125);
+	ret = xhci_handshake(xhci, pm_addr,
+			PORT_L1S_MASK, PORT_L1S_SUCCESS, 125);
 	if (ret != -ETIMEDOUT) {
 		/* enter L1 successfully */
 		temp = xhci_readl(xhci, addr);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 53df4e7..f791bd0 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1720,7 +1720,7 @@ static inline void xhci_unregister_plat(void)
 
 /* xHCI host controller glue */
 typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *);
-int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
+int xhci_handshake(struct xhci_hcd *xhci, void __iomem *ptr,
 		u32 mask, u32 done, int usec);
 void xhci_quiesce(struct xhci_hcd *xhci);
 int xhci_halt(struct xhci_hcd *xhci);
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index a8f0523..fecde69 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -246,6 +246,7 @@ config USB_YUREX
 
 config USB_EZUSB_FX2
 	tristate "Functions for loading firmware on EZUSB chips"
+	depends on USB
 	help
 	  Say Y here if you need EZUSB device support.
 	  (Cypress FX/FX2/FX2LP microcontrollers)
diff --git a/drivers/usb/misc/ezusb.c b/drivers/usb/misc/ezusb.c
index 6589268..e712afe 100644
--- a/drivers/usb/misc/ezusb.c
+++ b/drivers/usb/misc/ezusb.c
@@ -15,6 +15,7 @@
 #include <linux/usb.h>
 #include <linux/firmware.h>
 #include <linux/ihex.h>
+#include <linux/usb/ezusb.h>
 
 struct ezusb_fx_type {
 	/* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */
@@ -22,21 +23,16 @@ struct ezusb_fx_type {
 	unsigned short max_internal_adress;
 };
 
-struct ezusb_fx_type ezusb_fx1 = {
+static struct ezusb_fx_type ezusb_fx1 = {
 	.cpucs_reg = 0x7F92,
 	.max_internal_adress = 0x1B3F,
 };
 
-struct ezusb_fx_type ezusb_fx2 = {
-	.cpucs_reg = 0xE600,
-	.max_internal_adress = 0x3FFF,
-};
-
 /* Commands for writing to memory */
 #define WRITE_INT_RAM 0xA0
 #define WRITE_EXT_RAM 0xA3
 
-int ezusb_writememory(struct usb_device *dev, int address,
+static int ezusb_writememory(struct usb_device *dev, int address,
 				unsigned char *data, int length, __u8 request)
 {
 	int result;
@@ -58,10 +54,9 @@ int ezusb_writememory(struct usb_device *dev, int address,
 	kfree(transfer_buffer);
 	return result;
 }
-EXPORT_SYMBOL_GPL(ezusb_writememory);
 
-int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg,
-			 unsigned char reset_bit)
+static int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg,
+			   unsigned char reset_bit)
 {
 	int response = ezusb_writememory(dev, cpucs_reg, &reset_bit, 1, WRITE_INT_RAM);
 	if (response < 0)
@@ -76,12 +71,6 @@ int ezusb_fx1_set_reset(struct usb_device *dev, unsigned char reset_bit)
 }
 EXPORT_SYMBOL_GPL(ezusb_fx1_set_reset);
 
-int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit)
-{
-	return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit);
-}
-EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset);
-
 static int ezusb_ihex_firmware_download(struct usb_device *dev,
 					struct ezusb_fx_type fx,
 					const char *firmware_path)
@@ -151,11 +140,28 @@ int ezusb_fx1_ihex_firmware_download(struct usb_device *dev,
 }
 EXPORT_SYMBOL_GPL(ezusb_fx1_ihex_firmware_download);
 
+#if 0
+/*
+ * Once someone one needs these fx2 functions, uncomment them
+ * and add them to ezusb.h and all should be good.
+ */
+static struct ezusb_fx_type ezusb_fx2 = {
+	.cpucs_reg = 0xE600,
+	.max_internal_adress = 0x3FFF,
+};
+
+int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit)
+{
+	return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit);
+}
+EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset);
+
 int ezusb_fx2_ihex_firmware_download(struct usb_device *dev,
 				     const char *firmware_path)
 {
 	return ezusb_ihex_firmware_download(dev, ezusb_fx2, firmware_path);
 }
 EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download);
+#endif
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 055b84a..7667b12 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -423,6 +423,9 @@ alloc_sglist(int nents, int max, int vary)
 	unsigned		i;
 	unsigned		size = max;
 
+	if (max == 0)
+		return NULL;
+
 	sg = kmalloc_array(nents, sizeof *sg, GFP_KERNEL);
 	if (!sg)
 		return NULL;
@@ -2386,6 +2389,7 @@ static struct usbtest_info gz_info = {
 	.name		= "Linux gadget zero",
 	.autoconf	= 1,
 	.ctrl_out	= 1,
+	.iso		= 1,
 	.alt		= 0,
 };
 
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index c964d6a..c107d7c 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -34,8 +34,7 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/usb/nop-usb-xceiv.h>
-
-#include <plat/usb.h>
+#include <linux/platform_data/usb-omap.h>
 
 #include "musb_core.h"
 
@@ -455,7 +454,7 @@ static const struct musb_platform_ops am35x_ops = {
 
 static u64 am35x_dmamask = DMA_BIT_MASK(32);
 
-static int __devinit am35x_probe(struct platform_device *pdev)
+static int am35x_probe(struct platform_device *pdev)
 {
 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
 	struct platform_device		*musb;
@@ -465,7 +464,6 @@ static int __devinit am35x_probe(struct platform_device *pdev)
 	struct clk			*clk;
 
 	int				ret = -ENOMEM;
-	int				musbid;
 
 	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
@@ -473,18 +471,10 @@ static int __devinit am35x_probe(struct platform_device *pdev)
 		goto err0;
 	}
 
-	/* get the musb id */
-	musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
-	if (musbid < 0) {
-		dev_err(&pdev->dev, "failed to allocate musb id\n");
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	musb = platform_device_alloc("musb-hdrc", musbid);
+	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
 	if (!musb) {
 		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err2;
+		goto err1;
 	}
 
 	phy_clk = clk_get(&pdev->dev, "fck");
@@ -513,7 +503,6 @@ static int __devinit am35x_probe(struct platform_device *pdev)
 		goto err6;
 	}
 
-	musb->id			= musbid;
 	musb->dev.parent		= &pdev->dev;
 	musb->dev.dma_mask		= &am35x_dmamask;
 	musb->dev.coherent_dma_mask	= am35x_dmamask;
@@ -563,9 +552,6 @@ err4:
 err3:
 	platform_device_put(musb);
 
-err2:
-	musb_put_id(&pdev->dev, musbid);
-
 err1:
 	kfree(glue);
 
@@ -573,13 +559,11 @@ err0:
 	return ret;
 }
 
-static int __devexit am35x_remove(struct platform_device *pdev)
+static int am35x_remove(struct platform_device *pdev)
 {
 	struct am35x_glue	*glue = platform_get_drvdata(pdev);
 
-	musb_put_id(&pdev->dev, glue->musb->id);
-	platform_device_del(glue->musb);
-	platform_device_put(glue->musb);
+	platform_device_unregister(glue->musb);
 	clk_disable(glue->clk);
 	clk_disable(glue->phy_clk);
 	clk_put(glue->clk);
@@ -644,7 +628,7 @@ static struct dev_pm_ops am35x_pm_ops = {
 
 static struct platform_driver am35x_driver = {
 	.probe		= am35x_probe,
-	.remove		= __devexit_p(am35x_remove),
+	.remove		= am35x_remove,
 	.driver		= {
 		.name	= "musb-am35x",
 		.pm	= DEV_PM_OPS,
@@ -654,15 +638,4 @@ static struct platform_driver am35x_driver = {
 MODULE_DESCRIPTION("AM35x MUSB Glue Layer");
 MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
 MODULE_LICENSE("GPL v2");
-
-static int __init am35x_init(void)
-{
-	return platform_driver_register(&am35x_driver);
-}
-module_init(am35x_init);
-
-static void __exit am35x_exit(void)
-{
-	platform_driver_unregister(&am35x_driver);
-}
-module_exit(am35x_exit);
+module_platform_driver(am35x_driver);
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index e8cff9b..14dab9f 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -448,14 +448,13 @@ static const struct musb_platform_ops bfin_ops = {
 
 static u64 bfin_dmamask = DMA_BIT_MASK(32);
 
-static int __devinit bfin_probe(struct platform_device *pdev)
+static int bfin_probe(struct platform_device *pdev)
 {
 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
 	struct platform_device		*musb;
 	struct bfin_glue		*glue;
 
 	int				ret = -ENOMEM;
-	int				musbid;
 
 	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
@@ -463,21 +462,12 @@ static int __devinit bfin_probe(struct platform_device *pdev)
 		goto err0;
 	}
 
-	/* get the musb id */
-	musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
-	if (musbid < 0) {
-		dev_err(&pdev->dev, "failed to allocate musb id\n");
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	musb = platform_device_alloc("musb-hdrc", musbid);
+	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
 	if (!musb) {
 		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err2;
+		goto err1;
 	}
 
-	musb->id			= musbid;
 	musb->dev.parent		= &pdev->dev;
 	musb->dev.dma_mask		= &bfin_dmamask;
 	musb->dev.coherent_dma_mask	= bfin_dmamask;
@@ -513,9 +503,6 @@ static int __devinit bfin_probe(struct platform_device *pdev)
 err3:
 	platform_device_put(musb);
 
-err2:
-	musb_put_id(&pdev->dev, musbid);
-
 err1:
 	kfree(glue);
 
@@ -523,13 +510,11 @@ err0:
 	return ret;
 }
 
-static int __devexit bfin_remove(struct platform_device *pdev)
+static int bfin_remove(struct platform_device *pdev)
 {
 	struct bfin_glue		*glue = platform_get_drvdata(pdev);
 
-	musb_put_id(&pdev->dev, glue->musb->id);
-	platform_device_del(glue->musb);
-	platform_device_put(glue->musb);
+	platform_device_unregister(glue->musb);
 	kfree(glue);
 
 	return 0;
@@ -585,15 +570,4 @@ static struct platform_driver bfin_driver = {
 MODULE_DESCRIPTION("Blackfin MUSB Glue Layer");
 MODULE_AUTHOR("Bryan Wy <cooloney@kernel.org>");
 MODULE_LICENSE("GPL v2");
-
-static int __init bfin_init(void)
-{
-	return platform_driver_register(&bfin_driver);
-}
-module_init(bfin_init);
-
-static void __exit bfin_exit(void)
-{
-	platform_driver_unregister(&bfin_driver);
-}
-module_exit(bfin_exit);
+module_platform_driver(bfin_driver);
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
index e19da82..0968dd7 100644
--- a/drivers/usb/musb/cppi_dma.c
+++ b/drivers/usb/musb/cppi_dma.c
@@ -1314,10 +1314,10 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id)
 
 	return IRQ_HANDLED;
 }
+EXPORT_SYMBOL_GPL(cppi_interrupt);
 
 /* Instantiate a software object representing a DMA controller. */
-struct dma_controller *__devinit
-dma_controller_create(struct musb *musb, void __iomem *mregs)
+struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *mregs)
 {
 	struct cppi		*controller;
 	struct device		*dev = musb->controller;
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 8bc44b7..97996af 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -471,7 +471,7 @@ static const struct musb_platform_ops da8xx_ops = {
 
 static u64 da8xx_dmamask = DMA_BIT_MASK(32);
 
-static int __devinit da8xx_probe(struct platform_device *pdev)
+static int da8xx_probe(struct platform_device *pdev)
 {
 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
 	struct platform_device		*musb;
@@ -480,7 +480,6 @@ static int __devinit da8xx_probe(struct platform_device *pdev)
 	struct clk			*clk;
 
 	int				ret = -ENOMEM;
-	int				musbid;
 
 	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
@@ -488,18 +487,10 @@ static int __devinit da8xx_probe(struct platform_device *pdev)
 		goto err0;
 	}
 
-	/* get the musb id */
-	musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
-	if (musbid < 0) {
-		dev_err(&pdev->dev, "failed to allocate musb id\n");
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	musb = platform_device_alloc("musb-hdrc", musbid);
+	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
 	if (!musb) {
 		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err2;
+		goto err1;
 	}
 
 	clk = clk_get(&pdev->dev, "usb20");
@@ -515,7 +506,6 @@ static int __devinit da8xx_probe(struct platform_device *pdev)
 		goto err4;
 	}
 
-	musb->id			= musbid;
 	musb->dev.parent		= &pdev->dev;
 	musb->dev.dma_mask		= &da8xx_dmamask;
 	musb->dev.coherent_dma_mask	= da8xx_dmamask;
@@ -558,9 +548,6 @@ err4:
 err3:
 	platform_device_put(musb);
 
-err2:
-	musb_put_id(&pdev->dev, musbid);
-
 err1:
 	kfree(glue);
 
@@ -568,13 +555,11 @@ err0:
 	return ret;
 }
 
-static int __devexit da8xx_remove(struct platform_device *pdev)
+static int da8xx_remove(struct platform_device *pdev)
 {
 	struct da8xx_glue		*glue = platform_get_drvdata(pdev);
 
-	musb_put_id(&pdev->dev, glue->musb->id);
-	platform_device_del(glue->musb);
-	platform_device_put(glue->musb);
+	platform_device_unregister(glue->musb);
 	clk_disable(glue->clk);
 	clk_put(glue->clk);
 	kfree(glue);
@@ -584,7 +569,7 @@ static int __devexit da8xx_remove(struct platform_device *pdev)
 
 static struct platform_driver da8xx_driver = {
 	.probe		= da8xx_probe,
-	.remove		= __devexit_p(da8xx_remove),
+	.remove		= da8xx_remove,
 	.driver		= {
 		.name	= "musb-da8xx",
 	},
@@ -593,15 +578,4 @@ static struct platform_driver da8xx_driver = {
 MODULE_DESCRIPTION("DA8xx/OMAP-L1x MUSB Glue Layer");
 MODULE_AUTHOR("Sergei Shtylyov <sshtylyov@ru.mvista.com>");
 MODULE_LICENSE("GPL v2");
-
-static int __init da8xx_init(void)
-{
-	return platform_driver_register(&da8xx_driver);
-}
-module_init(da8xx_init);
-
-static void __exit da8xx_exit(void)
-{
-	platform_driver_unregister(&da8xx_driver);
-}
-module_exit(da8xx_exit);
+module_platform_driver(da8xx_driver);
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 606bfd0..b1c01ca 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -504,7 +504,7 @@ static const struct musb_platform_ops davinci_ops = {
 
 static u64 davinci_dmamask = DMA_BIT_MASK(32);
 
-static int __devinit davinci_probe(struct platform_device *pdev)
+static int davinci_probe(struct platform_device *pdev)
 {
 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
 	struct platform_device		*musb;
@@ -512,7 +512,6 @@ static int __devinit davinci_probe(struct platform_device *pdev)
 	struct clk			*clk;
 
 	int				ret = -ENOMEM;
-	int				musbid;
 
 	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
@@ -520,18 +519,10 @@ static int __devinit davinci_probe(struct platform_device *pdev)
 		goto err0;
 	}
 
-	/* get the musb id */
-	musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
-	if (musbid < 0) {
-		dev_err(&pdev->dev, "failed to allocate musb id\n");
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	musb = platform_device_alloc("musb-hdrc", musbid);
+	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
 	if (!musb) {
 		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err2;
+		goto err1;
 	}
 
 	clk = clk_get(&pdev->dev, "usb");
@@ -547,7 +538,6 @@ static int __devinit davinci_probe(struct platform_device *pdev)
 		goto err4;
 	}
 
-	musb->id			= musbid;
 	musb->dev.parent		= &pdev->dev;
 	musb->dev.dma_mask		= &davinci_dmamask;
 	musb->dev.coherent_dma_mask	= davinci_dmamask;
@@ -590,9 +580,6 @@ err4:
 err3:
 	platform_device_put(musb);
 
-err2:
-	musb_put_id(&pdev->dev, musbid);
-
 err1:
 	kfree(glue);
 
@@ -600,13 +587,11 @@ err0:
 	return ret;
 }
 
-static int __devexit davinci_remove(struct platform_device *pdev)
+static int davinci_remove(struct platform_device *pdev)
 {
 	struct davinci_glue		*glue = platform_get_drvdata(pdev);
 
-	musb_put_id(&pdev->dev, glue->musb->id);
-	platform_device_del(glue->musb);
-	platform_device_put(glue->musb);
+	platform_device_unregister(glue->musb);
 	clk_disable(glue->clk);
 	clk_put(glue->clk);
 	kfree(glue);
@@ -616,7 +601,7 @@ static int __devexit davinci_remove(struct platform_device *pdev)
 
 static struct platform_driver davinci_driver = {
 	.probe		= davinci_probe,
-	.remove		= __devexit_p(davinci_remove),
+	.remove		= davinci_remove,
 	.driver		= {
 		.name	= "musb-davinci",
 	},
@@ -625,15 +610,4 @@ static struct platform_driver davinci_driver = {
 MODULE_DESCRIPTION("DaVinci MUSB Glue Layer");
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
 MODULE_LICENSE("GPL v2");
-
-static int __init davinci_init(void)
-{
-	return platform_driver_register(&davinci_driver);
-}
-module_init(davinci_init);
-
-static void __exit davinci_exit(void)
-{
-	platform_driver_unregister(&davinci_driver);
-}
-module_exit(davinci_exit);
+module_platform_driver(davinci_driver);
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index bb56a0e..57cc9c6 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -116,7 +116,6 @@
 
 #define MUSB_DRIVER_NAME "musb-hdrc"
 const char musb_driver_name[] = MUSB_DRIVER_NAME;
-static DEFINE_IDA(musb_ida);
 
 MODULE_DESCRIPTION(DRIVER_INFO);
 MODULE_AUTHOR(DRIVER_AUTHOR);
@@ -133,35 +132,6 @@ static inline struct musb *dev_to_musb(struct device *dev)
 
 /*-------------------------------------------------------------------------*/
 
-int musb_get_id(struct device *dev, gfp_t gfp_mask)
-{
-	int ret;
-	int id;
-
-	ret = ida_pre_get(&musb_ida, gfp_mask);
-	if (!ret) {
-		dev_err(dev, "failed to reserve resource for id\n");
-		return -ENOMEM;
-	}
-
-	ret = ida_get_new(&musb_ida, &id);
-	if (ret < 0) {
-		dev_err(dev, "failed to allocate a new id\n");
-		return ret;
-	}
-
-	return id;
-}
-EXPORT_SYMBOL_GPL(musb_get_id);
-
-void musb_put_id(struct device *dev, int id)
-{
-
-	dev_dbg(dev, "removing id %d\n", id);
-	ida_remove(&musb_ida, id);
-}
-EXPORT_SYMBOL_GPL(musb_put_id);
-
 #ifndef CONFIG_BLACKFIN
 static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
 {
@@ -467,12 +437,12 @@ void musb_hnp_stop(struct musb *musb)
  */
 
 static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
-				u8 devctl, u8 power)
+				u8 devctl)
 {
 	struct usb_otg *otg = musb->xceiv->otg;
 	irqreturn_t handled = IRQ_NONE;
 
-	dev_dbg(musb->controller, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl,
+	dev_dbg(musb->controller, "<== DevCtl=%02x, int_usb=0x%x\n", devctl,
 		int_usb);
 
 	/* in host mode, the peripheral may issue remote wakeup.
@@ -485,6 +455,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 
 		if (devctl & MUSB_DEVCTL_HM) {
 			void __iomem *mbase = musb->mregs;
+			u8 power;
 
 			switch (musb->xceiv->state) {
 			case OTG_STATE_A_SUSPEND:
@@ -492,6 +463,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 				 * will stop RESUME signaling
 				 */
 
+				power = musb_readb(musb->mregs, MUSB_POWER);
 				if (power & MUSB_POWER_SUSPENDM) {
 					/* spurious */
 					musb->int_usb &= ~MUSB_INTR_SUSPEND;
@@ -655,8 +627,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 	}
 
 	if (int_usb & MUSB_INTR_SUSPEND) {
-		dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x power %02x\n",
-			otg_state_string(musb->xceiv->state), devctl, power);
+		dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x\n",
+			otg_state_string(musb->xceiv->state), devctl);
 		handled = IRQ_HANDLED;
 
 		switch (musb->xceiv->state) {
@@ -722,8 +694,10 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 		if (is_peripheral_active(musb)) {
 			/* REVISIT HNP; just force disconnect */
 		}
-		musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask);
-		musb_writew(musb->mregs, MUSB_INTRRXE, musb->epmask & 0xfffe);
+		musb->intrtxe = musb->epmask;
+		musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe);
+		musb->intrrxe = musb->epmask & 0xfffe;
+		musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe);
 		musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7);
 		musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED
 					|USB_PORT_STAT_HIGH_SPEED
@@ -944,8 +918,10 @@ void musb_start(struct musb *musb)
 	dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
 
 	/*  Set INT enable registers, enable interrupts */
-	musb_writew(regs, MUSB_INTRTXE, musb->epmask);
-	musb_writew(regs, MUSB_INTRRXE, musb->epmask & 0xfffe);
+	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);
@@ -983,7 +959,9 @@ static void musb_generic_disable(struct musb *musb)
 
 	/* disable interrupts */
 	musb_writeb(mbase, MUSB_INTRUSBE, 0);
+	musb->intrtxe = 0;
 	musb_writew(mbase, MUSB_INTRTXE, 0);
+	musb->intrrxe = 0;
 	musb_writew(mbase, MUSB_INTRRXE, 0);
 
 	/* off */
@@ -1062,12 +1040,12 @@ static void musb_shutdown(struct platform_device *pdev)
 	|| defined(CONFIG_USB_MUSB_AM35X_MODULE)	\
 	|| defined(CONFIG_USB_MUSB_DSPS)		\
 	|| defined(CONFIG_USB_MUSB_DSPS_MODULE)
-static ushort __devinitdata fifo_mode = 4;
+static ushort fifo_mode = 4;
 #elif defined(CONFIG_USB_MUSB_UX500)			\
 	|| defined(CONFIG_USB_MUSB_UX500_MODULE)
-static ushort __devinitdata fifo_mode = 5;
+static ushort fifo_mode = 5;
 #else
-static ushort __devinitdata fifo_mode = 2;
+static ushort fifo_mode = 2;
 #endif
 
 /* "modprobe ... fifo_mode=1" etc */
@@ -1080,7 +1058,7 @@ MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration");
  */
 
 /* mode 0 - fits in 2KB */
-static struct musb_fifo_cfg __devinitdata mode_0_cfg[] = {
+static struct musb_fifo_cfg mode_0_cfg[] = {
 { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, },
 { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, },
 { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, },
@@ -1089,7 +1067,7 @@ static struct musb_fifo_cfg __devinitdata mode_0_cfg[] = {
 };
 
 /* mode 1 - fits in 4KB */
-static struct musb_fifo_cfg __devinitdata mode_1_cfg[] = {
+static struct musb_fifo_cfg mode_1_cfg[] = {
 { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, },
@@ -1098,7 +1076,7 @@ static struct musb_fifo_cfg __devinitdata mode_1_cfg[] = {
 };
 
 /* mode 2 - fits in 4KB */
-static struct musb_fifo_cfg __devinitdata mode_2_cfg[] = {
+static struct musb_fifo_cfg mode_2_cfg[] = {
 { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, },
 { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, },
 { .hw_ep_num = 2, .style = FIFO_TX,   .maxpacket = 512, },
@@ -1108,7 +1086,7 @@ static struct musb_fifo_cfg __devinitdata mode_2_cfg[] = {
 };
 
 /* mode 3 - fits in 4KB */
-static struct musb_fifo_cfg __devinitdata mode_3_cfg[] = {
+static struct musb_fifo_cfg mode_3_cfg[] = {
 { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 { .hw_ep_num = 2, .style = FIFO_TX,   .maxpacket = 512, },
@@ -1118,7 +1096,7 @@ static struct musb_fifo_cfg __devinitdata mode_3_cfg[] = {
 };
 
 /* mode 4 - fits in 16KB */
-static struct musb_fifo_cfg __devinitdata mode_4_cfg[] = {
+static struct musb_fifo_cfg mode_4_cfg[] = {
 { .hw_ep_num =  1, .style = FIFO_TX,   .maxpacket = 512, },
 { .hw_ep_num =  1, .style = FIFO_RX,   .maxpacket = 512, },
 { .hw_ep_num =  2, .style = FIFO_TX,   .maxpacket = 512, },
@@ -1149,7 +1127,7 @@ static struct musb_fifo_cfg __devinitdata mode_4_cfg[] = {
 };
 
 /* mode 5 - fits in 8KB */
-static struct musb_fifo_cfg __devinitdata mode_5_cfg[] = {
+static struct musb_fifo_cfg mode_5_cfg[] = {
 { .hw_ep_num =  1, .style = FIFO_TX,   .maxpacket = 512, },
 { .hw_ep_num =  1, .style = FIFO_RX,   .maxpacket = 512, },
 { .hw_ep_num =  2, .style = FIFO_TX,   .maxpacket = 512, },
@@ -1185,7 +1163,7 @@ static struct musb_fifo_cfg __devinitdata mode_5_cfg[] = {
  *
  * returns negative errno or offset for next fifo.
  */
-static int __devinit
+static int
 fifo_setup(struct musb *musb, struct musb_hw_ep  *hw_ep,
 		const struct musb_fifo_cfg *cfg, u16 offset)
 {
@@ -1256,11 +1234,11 @@ fifo_setup(struct musb *musb, struct musb_hw_ep  *hw_ep,
 	return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0));
 }
 
-static struct musb_fifo_cfg __devinitdata ep0_cfg = {
+static struct musb_fifo_cfg ep0_cfg = {
 	.style = FIFO_RXTX, .maxpacket = 64,
 };
 
-static int __devinit ep_config_from_table(struct musb *musb)
+static int ep_config_from_table(struct musb *musb)
 {
 	const struct musb_fifo_cfg	*cfg;
 	unsigned		i, n;
@@ -1351,7 +1329,7 @@ done:
  * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false
  * @param musb the controller
  */
-static int __devinit ep_config_from_hw(struct musb *musb)
+static int ep_config_from_hw(struct musb *musb)
 {
 	u8 epnum = 0;
 	struct musb_hw_ep *hw_ep;
@@ -1398,7 +1376,7 @@ enum { MUSB_CONTROLLER_MHDRC, MUSB_CONTROLLER_HDRC, };
 /* Initialize MUSB (M)HDRC part of the USB hardware subsystem;
  * configure endpoints, or take their config from silicon
  */
-static int __devinit musb_core_init(u16 musb_type, struct musb *musb)
+static int musb_core_init(u16 musb_type, struct musb *musb)
 {
 	u8 reg;
 	char *type;
@@ -1523,33 +1501,6 @@ static int __devinit musb_core_init(u16 musb_type, struct musb *musb)
 
 /*-------------------------------------------------------------------------*/
 
-#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \
-	defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500)
-
-static irqreturn_t generic_interrupt(int irq, void *__hci)
-{
-	unsigned long	flags;
-	irqreturn_t	retval = IRQ_NONE;
-	struct musb	*musb = __hci;
-
-	spin_lock_irqsave(&musb->lock, flags);
-
-	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
-	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
-	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
-
-	if (musb->int_usb || musb->int_tx || musb->int_rx)
-		retval = musb_interrupt(musb);
-
-	spin_unlock_irqrestore(&musb->lock, flags);
-
-	return retval;
-}
-
-#else
-#define generic_interrupt	NULL
-#endif
-
 /*
  * handle all the irqs defined by the HDRC core. for now we expect:  other
  * irq sources (phy, dma, etc) will be handled first, musb->int_* values
@@ -1560,12 +1511,11 @@ static irqreturn_t generic_interrupt(int irq, void *__hci)
 irqreturn_t musb_interrupt(struct musb *musb)
 {
 	irqreturn_t	retval = IRQ_NONE;
-	u8		devctl, power;
+	u8		devctl;
 	int		ep_num;
 	u32		reg;
 
 	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
-	power = musb_readb(musb->mregs, MUSB_POWER);
 
 	dev_dbg(musb->controller, "** IRQ %s usb%04x tx%04x rx%04x\n",
 		(devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral",
@@ -1576,7 +1526,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
 	 */
 	if (musb->int_usb)
 		retval |= musb_stage0_irq(musb, musb->int_usb,
-				devctl, power);
+				devctl);
 
 	/* "stage 1" is handling endpoint irqs */
 
@@ -1628,7 +1578,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
 EXPORT_SYMBOL_GPL(musb_interrupt);
 
 #ifndef CONFIG_MUSB_PIO_ONLY
-static bool __devinitdata use_dma = 1;
+static bool use_dma = 1;
 
 /* "modprobe ... use_dma=0" etc */
 module_param(use_dma, bool, 0);
@@ -1809,8 +1759,7 @@ static void musb_irq_work(struct work_struct *data)
  * Init support
  */
 
-static struct musb *__devinit
-allocate_instance(struct device *dev,
+static struct musb *allocate_instance(struct device *dev,
 		struct musb_hdrc_config *config, void __iomem *mbase)
 {
 	struct musb		*musb;
@@ -1885,7 +1834,7 @@ static void musb_free(struct musb *musb)
  * @ctrl: virtual address of controller registers,
  *	not yet corrected for platform-specific offsets
  */
-static int __devinit
+static int
 musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 {
 	int			status;
@@ -1919,7 +1868,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 	musb->ops = plat->platform_ops;
 
 	/* The musb_platform_init() call:
-	 *   - adjusts musb->mregs and musb->isr if needed,
+	 *   - adjusts musb->mregs
+	 *   - sets the musb->isr
 	 *   - may initialize an integrated tranceiver
 	 *   - initializes musb->xceiv, usually by otg_get_phy()
 	 *   - stops powering VBUS
@@ -1929,7 +1879,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 	 * external/discrete ones in various flavors (twl4030 family,
 	 * isp1504, non-OTG, etc) mostly hooking up through ULPI.
 	 */
-	musb->isr = generic_interrupt;
 	status = musb_platform_init(musb);
 	if (status < 0)
 		goto fail1;
@@ -2060,7 +2009,7 @@ fail0:
 /* all implementations (PCI bridge to FPGA, VLYNQ, etc) should just
  * bridge to a platform device; this driver then suffices.
  */
-static int __devinit musb_probe(struct platform_device *pdev)
+static int musb_probe(struct platform_device *pdev)
 {
 	struct device	*dev = &pdev->dev;
 	int		irq = platform_get_irq_byname(pdev, "mc");
@@ -2085,7 +2034,7 @@ static int __devinit musb_probe(struct platform_device *pdev)
 	return status;
 }
 
-static int __devexit musb_remove(struct platform_device *pdev)
+static int musb_remove(struct platform_device *pdev)
 {
 	struct device	*dev = &pdev->dev;
 	struct musb	*musb = dev_to_musb(dev);
@@ -2120,8 +2069,6 @@ static void musb_save_context(struct musb *musb)
 	musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE);
 	musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs);
 	musb->context.power = musb_readb(musb_base, MUSB_POWER);
-	musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE);
-	musb->context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE);
 	musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE);
 	musb->context.index = musb_readb(musb_base, MUSB_INDEX);
 	musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL);
@@ -2194,8 +2141,8 @@ static void musb_restore_context(struct musb *musb)
 	musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
 	musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);
 	musb_writeb(musb_base, MUSB_POWER, musb->context.power);
-	musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe);
-	musb_writew(musb_base, MUSB_INTRRXE, musb->context.intrrxe);
+	musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe);
+	musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe);
 	musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe);
 	musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl);
 
@@ -2340,7 +2287,7 @@ static struct platform_driver musb_driver = {
 		.pm		= MUSB_DEV_PM_OPS,
 	},
 	.probe		= musb_probe,
-	.remove		= __devexit_p(musb_remove),
+	.remove		= musb_remove,
 	.shutdown	= musb_shutdown,
 };
 
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index c158aac..7fb4819 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -288,7 +288,6 @@ struct musb_csr_regs {
 struct musb_context_registers {
 
 	u8 power;
-	u16 intrtxe, intrrxe;
 	u8 intrusbe;
 	u16 frame;
 	u8 index, testmode;
@@ -313,6 +312,8 @@ struct musb {
 	struct work_struct	irq_work;
 	u16			hwvers;
 
+	u16			intrrxe;
+	u16			intrtxe;
 /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
 #define MUSB_PORT_STAT_RESUME	(1 << 31)
 
@@ -521,8 +522,6 @@ extern const char musb_driver_name[];
 
 extern void musb_start(struct musb *musb);
 extern void musb_stop(struct musb *musb);
-extern int musb_get_id(struct device *dev, gfp_t gfp_mask);
-extern void musb_put_id(struct device *dev, int id);
 
 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_debugfs.c b/drivers/usb/musb/musb_debugfs.c
index 1d6e8af..4c21679 100644
--- a/drivers/usb/musb/musb_debugfs.c
+++ b/drivers/usb/musb/musb_debugfs.c
@@ -233,7 +233,7 @@ static const struct file_operations musb_test_mode_fops = {
 	.release		= single_release,
 };
 
-int __devinit musb_init_debugfs(struct musb *musb)
+int musb_init_debugfs(struct musb *musb)
 {
 	struct dentry		*root;
 	struct dentry		*file;
diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
index 24d3921..1b6b827 100644
--- a/drivers/usb/musb/musb_dma.h
+++ b/drivers/usb/musb/musb_dma.h
@@ -178,8 +178,7 @@ struct dma_controller {
 extern void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit);
 
 
-extern struct dma_controller *__devinit
-dma_controller_create(struct musb *, void __iomem *);
+extern struct dma_controller *dma_controller_create(struct musb *, void __iomem *);
 
 extern void dma_controller_destroy(struct dma_controller *);
 
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index ff5f112..e6f2ae8 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -38,13 +38,12 @@
 #include <linux/pm_runtime.h>
 #include <linux/module.h>
 #include <linux/usb/nop-usb-xceiv.h>
+#include <linux/platform_data/usb-omap.h>
 
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_address.h>
 
-#include <plat/usb.h>
-
 #include "musb_core.h"
 
 #ifdef CONFIG_OF
@@ -124,8 +123,44 @@ struct dsps_glue {
 	const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
 	struct timer_list timer[2];	/* otg_workaround timer */
 	unsigned long last_timer[2];    /* last timer data for each instance */
+	u32 __iomem *usb_ctrl[2];
 };
 
+#define	DSPS_AM33XX_CONTROL_MODULE_PHYS_0	0x44e10620
+#define	DSPS_AM33XX_CONTROL_MODULE_PHYS_1	0x44e10628
+
+static const resource_size_t dsps_control_module_phys[] = {
+	DSPS_AM33XX_CONTROL_MODULE_PHYS_0,
+	DSPS_AM33XX_CONTROL_MODULE_PHYS_1,
+};
+
+/**
+ * musb_dsps_phy_control - phy on/off
+ * @glue: struct dsps_glue *
+ * @id: musb instance
+ * @on: flag for phy to be switched on or off
+ *
+ * This is to enable the PHY using usb_ctrl register in system control
+ * module space.
+ *
+ * XXX: This function will be removed once we have a seperate driver for
+ * control module
+ */
+static void musb_dsps_phy_control(struct dsps_glue *glue, u8 id, u8 on)
+{
+	u32 usbphycfg;
+
+	usbphycfg = readl(glue->usb_ctrl[id]);
+
+	if (on) {
+		usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN);
+		usbphycfg |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN;
+	} else {
+		usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
+	}
+
+	writel(usbphycfg, glue->usb_ctrl[id]);
+}
 /**
  * dsps_musb_enable - enable interrupts
  */
@@ -296,7 +331,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 	 * Also, DRVVBUS pulses for SRP (but not at 5V) ...
 	 */
 	if (usbintr & MUSB_INTR_BABBLE)
-		pr_info("CAUTION: musb: Babble Interrupt Occured\n");
+		pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
 
 	if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
 		int drvvbus = dsps_readl(reg_base, wrp->status);
@@ -365,11 +400,9 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 static int dsps_musb_init(struct musb *musb)
 {
 	struct device *dev = musb->controller;
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
 	struct platform_device *pdev = to_platform_device(dev);
 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
 	const struct dsps_musb_wrapper *wrp = glue->wrp;
-	struct omap_musb_board_data *data = plat->board_data;
 	void __iomem *reg_base = musb->ctrl_base;
 	u32 rev, val;
 	int status;
@@ -377,7 +410,8 @@ static int dsps_musb_init(struct musb *musb)
 	/* mentor core register starts at offset of 0x400 from musb base */
 	musb->mregs += wrp->musb_core_offset;
 
-	/* Get the NOP PHY */
+	/* NOP driver needs change if supporting dual instance */
+	usb_nop_xceiv_register();
 	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (IS_ERR_OR_NULL(musb->xceiv))
 		return -ENODEV;
@@ -395,8 +429,7 @@ static int dsps_musb_init(struct musb *musb)
 	dsps_writel(reg_base, wrp->control, (1 << wrp->reset));
 
 	/* Start the on-chip PHY and its PLL. */
-	if (data->set_phy_power)
-		data->set_phy_power(1);
+	musb_dsps_phy_control(glue, pdev->id, 1);
 
 	musb->isr = dsps_interrupt;
 
@@ -418,16 +451,13 @@ err0:
 static int dsps_musb_exit(struct musb *musb)
 {
 	struct device *dev = musb->controller;
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
-	struct omap_musb_board_data *data = plat->board_data;
 	struct platform_device *pdev = to_platform_device(dev);
 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
 
 	del_timer_sync(&glue->timer[pdev->id]);
 
 	/* Shutdown the on-chip PHY and its PLL. */
-	if (data->set_phy_power)
-		data->set_phy_power(0);
+	musb_dsps_phy_control(glue, pdev->id, 0);
 
 	/* NOP driver needs change if supporting dual instance */
 	usb_put_phy(musb->xceiv);
@@ -448,7 +478,7 @@ static struct musb_platform_ops dsps_ops = {
 
 static u64 musb_dmamask = DMA_BIT_MASK(32);
 
-static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
+static int dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
 {
 	struct device *dev = glue->dev;
 	struct platform_device *pdev = to_platform_device(dev);
@@ -459,24 +489,33 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
 	struct resource *res;
 	struct resource	resources[2];
 	char res_name[11];
-	int ret, musbid;
+	int ret;
 
-	/* get memory resource */
-	snprintf(res_name, sizeof(res_name), "musb%d", id);
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
+	resources[0].start = dsps_control_module_phys[id];
+	resources[0].end = resources[0].start + SZ_4 - 1;
+	resources[0].flags = IORESOURCE_MEM;
+
+	glue->usb_ctrl[id] = devm_request_and_ioremap(&pdev->dev, resources);
+	if (glue->usb_ctrl[id] == NULL) {
+		dev_err(dev, "Failed to obtain usb_ctrl%d memory\n", id);
+		ret = -ENODEV;
+		goto err0;
+	}
+
+	/* first resource is for usbss, so start index from 1 */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, id + 1);
 	if (!res) {
-		dev_err(dev, "%s get mem resource failed\n", res_name);
+		dev_err(dev, "failed to get memory for instance %d\n", id);
 		ret = -ENODEV;
 		goto err0;
 	}
 	res->parent = NULL;
 	resources[0] = *res;
 
-	/* get irq resource */
-	snprintf(res_name, sizeof(res_name), "musb%d-irq", id);
-	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
+	/* first resource is for usbss, so start index from 1 */
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, id + 1);
 	if (!res) {
-		dev_err(dev, "%s get irq resource failed\n", res_name);
+		dev_err(dev, "failed to get irq for instance %d\n", id);
 		ret = -ENODEV;
 		goto err0;
 	}
@@ -484,22 +523,14 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
 	resources[1] = *res;
 	resources[1].name = "mc";
 
-	/* get the musb id */
-	musbid = musb_get_id(dev, GFP_KERNEL);
-	if (musbid < 0) {
-		dev_err(dev, "failed to allocate musb id\n");
-		ret = -ENOMEM;
-		goto err0;
-	}
 	/* allocate the child platform device */
-	musb = platform_device_alloc("musb-hdrc", musbid);
+	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
 	if (!musb) {
 		dev_err(dev, "failed to allocate musb device\n");
 		ret = -ENOMEM;
-		goto err1;
+		goto err0;
 	}
 
-	musb->id			= musbid;
 	musb->dev.parent		= dev;
 	musb->dev.dma_mask		= &musb_dmamask;
 	musb->dev.coherent_dma_mask	= musb_dmamask;
@@ -556,20 +587,11 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
 
 err2:
 	platform_device_put(musb);
-err1:
-	musb_put_id(dev, musbid);
 err0:
 	return ret;
 }
 
-static void dsps_delete_musb_pdev(struct dsps_glue *glue, u8 id)
-{
-	musb_put_id(glue->dev, glue->musb[id]->id);
-	platform_device_del(glue->musb[id]);
-	platform_device_put(glue->musb[id]);
-}
-
-static int __devinit dsps_probe(struct platform_device *pdev)
+static int dsps_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	const struct of_device_id *match;
@@ -628,7 +650,7 @@ static int __devinit dsps_probe(struct platform_device *pdev)
 			dev_err(&pdev->dev, "failed to create child pdev\n");
 			/* release resources of previously created instances */
 			for (i--; i >= 0 ; i--)
-				dsps_delete_musb_pdev(glue, i);
+				platform_device_unregister(glue->musb[i]);
 			goto err3;
 		}
 	}
@@ -645,7 +667,7 @@ err1:
 err0:
 	return ret;
 }
-static int __devexit dsps_remove(struct platform_device *pdev)
+static int dsps_remove(struct platform_device *pdev)
 {
 	struct dsps_glue *glue = platform_get_drvdata(pdev);
 	const struct dsps_musb_wrapper *wrp = glue->wrp;
@@ -653,7 +675,7 @@ static int __devexit dsps_remove(struct platform_device *pdev)
 
 	/* delete the child platform device */
 	for (i = 0; i < wrp->instances ; i++)
-		dsps_delete_musb_pdev(glue, i);
+		platform_device_unregister(glue->musb[i]);
 
 	/* disable usbss clocks */
 	pm_runtime_put(&pdev->dev);
@@ -666,24 +688,26 @@ static int __devexit dsps_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM_SLEEP
 static int dsps_suspend(struct device *dev)
 {
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
-	struct omap_musb_board_data *data = plat->board_data;
+	struct platform_device *pdev = to_platform_device(dev->parent);
+	struct dsps_glue *glue = platform_get_drvdata(pdev);
+	const struct dsps_musb_wrapper *wrp = glue->wrp;
+	int i;
 
-	/* Shutdown the on-chip PHY and its PLL. */
-	if (data->set_phy_power)
-		data->set_phy_power(0);
+	for (i = 0; i < wrp->instances; i++)
+		musb_dsps_phy_control(glue, i, 0);
 
 	return 0;
 }
 
 static int dsps_resume(struct device *dev)
 {
-	struct musb_hdrc_platform_data *plat = dev->platform_data;
-	struct omap_musb_board_data *data = plat->board_data;
+	struct platform_device *pdev = to_platform_device(dev->parent);
+	struct dsps_glue *glue = platform_get_drvdata(pdev);
+	const struct dsps_musb_wrapper *wrp = glue->wrp;
+	int i;
 
-	/* Start the on-chip PHY and its PLL. */
-	if (data->set_phy_power)
-		data->set_phy_power(1);
+	for (i = 0; i < wrp->instances; i++)
+		musb_dsps_phy_control(glue, i, 1);
 
 	return 0;
 }
@@ -691,7 +715,7 @@ static int dsps_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
 
-static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = {
+static const struct dsps_musb_wrapper ti81xx_driver_data = {
 	.revision		= 0x00,
 	.control		= 0x14,
 	.status			= 0x18,
@@ -719,10 +743,10 @@ static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = {
 	.rxep_bitmap		= (0xfffe << 16),
 	.musb_core_offset	= 0x400,
 	.poll_seconds		= 2,
-	.instances		= 2,
+	.instances		= 1,
 };
 
-static const struct platform_device_id musb_dsps_id_table[] __devinitconst = {
+static const struct platform_device_id musb_dsps_id_table[] = {
 	{
 		.name	= "musb-ti81xx",
 		.driver_data	= (kernel_ulong_t) &ti81xx_driver_data,
@@ -732,7 +756,7 @@ static const struct platform_device_id musb_dsps_id_table[] __devinitconst = {
 MODULE_DEVICE_TABLE(platform, musb_dsps_id_table);
 
 #ifdef CONFIG_OF
-static const struct of_device_id musb_dsps_of_match[] __devinitconst = {
+static const struct of_device_id musb_dsps_of_match[] = {
 	{ .compatible = "ti,musb-am33xx",
 		.data = (void *) &ti81xx_driver_data, },
 	{  },
@@ -742,7 +766,7 @@ MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
 
 static struct platform_driver dsps_usbss_driver = {
 	.probe		= dsps_probe,
-	.remove         = __devexit_p(dsps_remove),
+	.remove         = dsps_remove,
 	.driver         = {
 		.name   = "musb-dsps",
 		.pm	= &dsps_pm_ops,
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index b6b84da..8767874 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -1090,7 +1090,6 @@ static int musb_gadget_enable(struct usb_ep *ep,
 	 */
 	musb_ep_select(mbase, epnum);
 	if (usb_endpoint_dir_in(desc)) {
-		u16 int_txe = musb_readw(mbase, MUSB_INTRTXE);
 
 		if (hw_ep->is_shared_fifo)
 			musb_ep->is_in = 1;
@@ -1102,8 +1101,8 @@ static int musb_gadget_enable(struct usb_ep *ep,
 			goto fail;
 		}
 
-		int_txe |= (1 << epnum);
-		musb_writew(mbase, MUSB_INTRTXE, int_txe);
+		musb->intrtxe |= (1 << epnum);
+		musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe);
 
 		/* REVISIT if can_bulk_split(), use by updating "tmp";
 		 * likewise high bandwidth periodic tx
@@ -1130,7 +1129,6 @@ static int musb_gadget_enable(struct usb_ep *ep,
 		musb_writew(regs, MUSB_TXCSR, csr);
 
 	} else {
-		u16 int_rxe = musb_readw(mbase, MUSB_INTRRXE);
 
 		if (hw_ep->is_shared_fifo)
 			musb_ep->is_in = 0;
@@ -1142,8 +1140,8 @@ static int musb_gadget_enable(struct usb_ep *ep,
 			goto fail;
 		}
 
-		int_rxe |= (1 << epnum);
-		musb_writew(mbase, MUSB_INTRRXE, int_rxe);
+		musb->intrrxe |= (1 << epnum);
+		musb_writew(mbase, MUSB_INTRRXE, musb->intrrxe);
 
 		/* REVISIT if can_bulk_combine() use by updating "tmp"
 		 * likewise high bandwidth periodic rx
@@ -1231,14 +1229,12 @@ static int musb_gadget_disable(struct usb_ep *ep)
 
 	/* zero the endpoint sizes */
 	if (musb_ep->is_in) {
-		u16 int_txe = musb_readw(musb->mregs, MUSB_INTRTXE);
-		int_txe &= ~(1 << epnum);
-		musb_writew(musb->mregs, MUSB_INTRTXE, int_txe);
+		musb->intrtxe &= ~(1 << epnum);
+		musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe);
 		musb_writew(epio, MUSB_TXMAXP, 0);
 	} else {
-		u16 int_rxe = musb_readw(musb->mregs, MUSB_INTRRXE);
-		int_rxe &= ~(1 << epnum);
-		musb_writew(musb->mregs, MUSB_INTRRXE, int_rxe);
+		musb->intrrxe &= ~(1 << epnum);
+		musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe);
 		musb_writew(epio, MUSB_RXMAXP, 0);
 	}
 
@@ -1554,7 +1550,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
 	void __iomem	*epio = musb->endpoints[epnum].regs;
 	void __iomem	*mbase;
 	unsigned long	flags;
-	u16		csr, int_txe;
+	u16		csr;
 
 	mbase = musb->mregs;
 
@@ -1562,8 +1558,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
 	musb_ep_select(mbase, (u8) epnum);
 
 	/* disable interrupts */
-	int_txe = musb_readw(mbase, MUSB_INTRTXE);
-	musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
+	musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe & ~(1 << epnum));
 
 	if (musb_ep->is_in) {
 		csr = musb_readw(epio, MUSB_TXCSR);
@@ -1587,7 +1582,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
 	}
 
 	/* re-enable interrupt */
-	musb_writew(mbase, MUSB_INTRTXE, int_txe);
+	musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe);
 	spin_unlock_irqrestore(&musb->lock, flags);
 }
 
@@ -1792,7 +1787,7 @@ static void musb_gadget_release(struct device *dev)
 }
 
 
-static void __devinit
+static void
 init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
 {
 	struct musb_hw_ep	*hw_ep = musb->endpoints + epnum;
@@ -1829,7 +1824,7 @@ init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
  * Initialize the endpoints exposed to peripheral drivers, with backlinks
  * to the rest of the driver state.
  */
-static inline void __devinit musb_g_init_endpoints(struct musb *musb)
+static inline void musb_g_init_endpoints(struct musb *musb)
 {
 	u8			epnum;
 	struct musb_hw_ep	*hw_ep;
@@ -1862,7 +1857,7 @@ static inline void __devinit musb_g_init_endpoints(struct musb *musb)
 /* called once during driver setup to initialize and link into
  * the driver model; memory is zeroed.
  */
-int __devinit musb_gadget_setup(struct musb *musb)
+int musb_gadget_setup(struct musb *musb)
 {
 	int status;
 
@@ -2176,10 +2171,9 @@ __acquires(musb->lock)
 	u8		devctl = musb_readb(mbase, MUSB_DEVCTL);
 	u8		power;
 
-	dev_dbg(musb->controller, "<== %s addr=%x driver '%s'\n",
+	dev_dbg(musb->controller, "<== %s driver '%s'\n",
 			(devctl & MUSB_DEVCTL_BDEVICE)
 				? "B-Device" : "A-Device",
-			musb_readb(mbase, MUSB_FADDR),
 			musb->gadget_driver
 				? musb->gadget_driver->driver.name
 				: NULL
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
index e40d764..c9c1ac4 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -673,10 +673,8 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
 	csr = musb_readw(regs, MUSB_CSR0);
 	len = musb_readb(regs, MUSB_COUNT0);
 
-	dev_dbg(musb->controller, "csr %04x, count %d, myaddr %d, ep0stage %s\n",
-			csr, len,
-			musb_readb(mbase, MUSB_FADDR),
-			decode_ep0stage(musb->ep0_state));
+	dev_dbg(musb->controller, "csr %04x, count %d, ep0stage %s\n",
+			csr, len, decode_ep0stage(musb->ep0_state));
 
 	if (csr & MUSB_CSR0_P_DATAEND) {
 		/*
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 3df6a76..e9f0fd9 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -740,7 +740,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
 		csr = musb_readw(epio, MUSB_TXCSR);
 
 		/* disable interrupt in case we flush */
-		int_txe = musb_readw(mbase, MUSB_INTRTXE);
+		int_txe = musb->intrtxe;
 		musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
 
 		/* general endpoint setup */
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 0fc6ca6..3d1fd52 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -380,8 +380,7 @@ void dma_controller_destroy(struct dma_controller *c)
 	kfree(controller);
 }
 
-struct dma_controller *__devinit
-dma_controller_create(struct musb *musb, void __iomem *base)
+struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *base)
 {
 	struct musb_dma_controller *controller;
 	struct device *dev = musb->controller;
diff --git a/drivers/usb/musb/musbhsdma.h b/drivers/usb/musb/musbhsdma.h
index 320fd4a..f7b13fd2 100644
--- a/drivers/usb/musb/musbhsdma.h
+++ b/drivers/usb/musb/musbhsdma.h
@@ -31,10 +31,6 @@
  *
  */
 
-#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430)
-#include "omap2430.h"
-#endif
-
 #ifndef CONFIG_BLACKFIN
 
 #define MUSB_HSDMA_BASE		0x200
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index a538fe1..da00af4 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -333,6 +333,26 @@ static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
 	omap_musb_set_mailbox(glue);
 }
 
+static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci)
+{
+	unsigned long   flags;
+	irqreturn_t     retval = IRQ_NONE;
+	struct musb     *musb = __hci;
+
+	spin_lock_irqsave(&musb->lock, flags);
+
+	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
+	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
+	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
+
+	if (musb->int_usb || musb->int_tx || musb->int_rx)
+		retval = musb_interrupt(musb);
+
+	spin_unlock_irqrestore(&musb->lock, flags);
+
+	return retval;
+}
+
 static int omap2430_musb_init(struct musb *musb)
 {
 	u32 l;
@@ -352,6 +372,8 @@ static int omap2430_musb_init(struct musb *musb)
 		return -ENODEV;
 	}
 
+	musb->isr = omap2430_musb_interrupt;
+
 	status = pm_runtime_get_sync(dev);
 	if (status < 0) {
 		dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
@@ -468,7 +490,7 @@ static const struct musb_platform_ops omap2430_ops = {
 
 static u64 omap2430_dmamask = DMA_BIT_MASK(32);
 
-static int __devinit omap2430_probe(struct platform_device *pdev)
+static int omap2430_probe(struct platform_device *pdev)
 {
 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
 	struct omap_musb_board_data	*data;
@@ -478,7 +500,6 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
 	struct musb_hdrc_config		*config;
 	struct resource			*res;
 	int				ret = -ENOMEM;
-	int				musbid;
 
 	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
@@ -486,21 +507,12 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
 		goto err0;
 	}
 
-	/* get the musb id */
-	musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
-	if (musbid < 0) {
-		dev_err(&pdev->dev, "failed to allocate musb id\n");
-		ret = -ENOMEM;
-		goto err0;
-	}
-
-	musb = platform_device_alloc("musb-hdrc", musbid);
+	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
 	if (!musb) {
 		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err1;
+		goto err0;
 	}
 
-	musb->id			= musbid;
 	musb->dev.parent		= &pdev->dev;
 	musb->dev.dma_mask		= &omap2430_dmamask;
 	musb->dev.coherent_dma_mask	= omap2430_dmamask;
@@ -521,7 +533,7 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
 			dev_err(&pdev->dev,
 				"failed to allocate musb platfrom data\n");
 			ret = -ENOMEM;
-			goto err1;
+			goto err2;
 		}
 
 		data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
@@ -529,14 +541,14 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
 			dev_err(&pdev->dev,
 					"failed to allocate musb board data\n");
 			ret = -ENOMEM;
-			goto err1;
+			goto err2;
 		}
 
 		config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
 		if (!data) {
 			dev_err(&pdev->dev,
 				"failed to allocate musb hdrc config\n");
-			goto err1;
+			goto err2;
 		}
 
 		of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
@@ -589,19 +601,15 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
 err2:
 	platform_device_put(musb);
 
-err1:
-	musb_put_id(&pdev->dev, musbid);
-
 err0:
 	return ret;
 }
 
-static int __devexit omap2430_remove(struct platform_device *pdev)
+static int omap2430_remove(struct platform_device *pdev)
 {
 	struct omap2430_glue		*glue = platform_get_drvdata(pdev);
 
 	cancel_work_sync(&glue->omap_musb_mailbox_work);
-	musb_put_id(&pdev->dev, glue->musb->id);
 	platform_device_unregister(glue->musb);
 
 	return 0;
@@ -666,7 +674,7 @@ MODULE_DEVICE_TABLE(of, omap2430_id_table);
 
 static struct platform_driver omap2430_driver = {
 	.probe		= omap2430_probe,
-	.remove		= __devexit_p(omap2430_remove),
+	.remove		= omap2430_remove,
 	.driver		= {
 		.name	= "musb-omap2430",
 		.pm	= DEV_PM_OPS,
diff --git a/drivers/usb/musb/omap2430.h b/drivers/usb/musb/omap2430.h
index b85f397..8ef6566 100644
--- a/drivers/usb/musb/omap2430.h
+++ b/drivers/usb/musb/omap2430.h
@@ -10,7 +10,7 @@
 #ifndef __MUSB_OMAP243X_H__
 #define __MUSB_OMAP243X_H__
 
-#include <plat/usb.h>
+#include <linux/platform_data/usb-omap.h>
 
 /*
  * OMAP2430-specific definitions
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index dc4d75e..8bde6fc 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -1153,14 +1153,13 @@ static const struct musb_platform_ops tusb_ops = {
 
 static u64 tusb_dmamask = DMA_BIT_MASK(32);
 
-static int __devinit tusb_probe(struct platform_device *pdev)
+static int tusb_probe(struct platform_device *pdev)
 {
 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
 	struct platform_device		*musb;
 	struct tusb6010_glue		*glue;
 
 	int				ret = -ENOMEM;
-	int				musbid;
 
 	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
 	if (!glue) {
@@ -1168,21 +1167,12 @@ static int __devinit tusb_probe(struct platform_device *pdev)
 		goto err0;
 	}
 
-	/* get the musb id */
-	musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
-	if (musbid < 0) {
-		dev_err(&pdev->dev, "failed to allocate musb id\n");
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	musb = platform_device_alloc("musb-hdrc", musbid);
+	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
 	if (!musb) {
 		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err2;
+		goto err1;
 	}
 
-	musb->id			= musbid;
 	musb->dev.parent		= &pdev->dev;
 	musb->dev.dma_mask		= &tusb_dmamask;
 	musb->dev.coherent_dma_mask	= tusb_dmamask;
@@ -1218,9 +1208,6 @@ static int __devinit tusb_probe(struct platform_device *pdev)
 err3:
 	platform_device_put(musb);
 
-err2:
-	musb_put_id(&pdev->dev, musbid);
-
 err1:
 	kfree(glue);
 
@@ -1228,13 +1215,11 @@ err0:
 	return ret;
 }
 
-static int __devexit tusb_remove(struct platform_device *pdev)
+static int tusb_remove(struct platform_device *pdev)
 {
 	struct tusb6010_glue		*glue = platform_get_drvdata(pdev);
 
-	musb_put_id(&pdev->dev, glue->musb->id);
-	platform_device_del(glue->musb);
-	platform_device_put(glue->musb);
+	platform_device_unregister(glue->musb);
 	kfree(glue);
 
 	return 0;
@@ -1242,7 +1227,7 @@ static int __devexit tusb_remove(struct platform_device *pdev)
 
 static struct platform_driver tusb_driver = {
 	.probe		= tusb_probe,
-	.remove		= __devexit_p(tusb_remove),
+	.remove		= tusb_remove,
 	.driver		= {
 		.name	= "musb-tusb",
 	},
@@ -1251,15 +1236,4 @@ static struct platform_driver tusb_driver = {
 MODULE_DESCRIPTION("TUSB6010 MUSB Glue Layer");
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
 MODULE_LICENSE("GPL v2");
-
-static int __init tusb_init(void)
-{
-	return platform_driver_register(&tusb_driver);
-}
-module_init(tusb_init);
-
-static void __exit tusb_exit(void)
-{
-	platform_driver_unregister(&tusb_driver);
-}
-module_exit(tusb_exit);
+module_platform_driver(tusb_driver);
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 7a62b95..9716850 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -16,7 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 
 #include "musb_core.h"
 #include "tusb6010.h"
@@ -25,6 +25,13 @@
 
 #define MAX_DMAREQ		5	/* REVISIT: Really 6, but req5 not OK */
 
+#define OMAP24XX_DMA_EXT_DMAREQ0	2
+#define OMAP24XX_DMA_EXT_DMAREQ1	3
+#define OMAP242X_DMA_EXT_DMAREQ2	14
+#define OMAP242X_DMA_EXT_DMAREQ3	15
+#define OMAP242X_DMA_EXT_DMAREQ4	16
+#define OMAP242X_DMA_EXT_DMAREQ5	64
+
 struct tusb_omap_dma_ch {
 	struct musb		*musb;
 	void __iomem		*tbase;
@@ -661,8 +668,7 @@ void dma_controller_destroy(struct dma_controller *c)
 	kfree(tusb_dma);
 }
 
-struct dma_controller *__devinit
-dma_controller_create(struct musb *musb, void __iomem *base)
+struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *base)
 {
 	void __iomem		*tbase = musb->ctrl_base;
 	struct tusb_omap_dma	*tusb_dma;
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index 0e62f50..a27ca1a 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -36,6 +36,26 @@ struct ux500_glue {
 };
 #define glue_to_musb(g)	platform_get_drvdata(g->musb)
 
+static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)
+{
+	unsigned long   flags;
+	irqreturn_t     retval = IRQ_NONE;
+	struct musb     *musb = __hci;
+
+	spin_lock_irqsave(&musb->lock, flags);
+
+	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
+	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
+	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
+
+	if (musb->int_usb || musb->int_tx || musb->int_rx)
+		retval = musb_interrupt(musb);
+
+	spin_unlock_irqrestore(&musb->lock, flags);
+
+	return retval;
+}
+
 static int ux500_musb_init(struct musb *musb)
 {
 	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
@@ -44,6 +64,8 @@ static int ux500_musb_init(struct musb *musb)
 		return -ENODEV;
 	}
 
+	musb->isr = ux500_musb_interrupt;
+
 	return 0;
 }
 
@@ -59,13 +81,12 @@ static const struct musb_platform_ops ux500_ops = {
 	.exit		= ux500_musb_exit,
 };
 
-static int __devinit ux500_probe(struct platform_device *pdev)
+static int ux500_probe(struct platform_device *pdev)
 {
 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
 	struct platform_device		*musb;
 	struct ux500_glue		*glue;
 	struct clk			*clk;
-	int				musbid;
 	int				ret = -ENOMEM;
 
 	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
@@ -74,18 +95,10 @@ static int __devinit ux500_probe(struct platform_device *pdev)
 		goto err0;
 	}
 
-	/* get the musb id */
-	musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
-	if (musbid < 0) {
-		dev_err(&pdev->dev, "failed to allocate musb id\n");
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	musb = platform_device_alloc("musb-hdrc", musbid);
+	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
 	if (!musb) {
 		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err2;
+		goto err1;
 	}
 
 	clk = clk_get(&pdev->dev, "usb");
@@ -101,7 +114,6 @@ static int __devinit ux500_probe(struct platform_device *pdev)
 		goto err4;
 	}
 
-	musb->id			= musbid;
 	musb->dev.parent		= &pdev->dev;
 	musb->dev.dma_mask		= pdev->dev.dma_mask;
 	musb->dev.coherent_dma_mask	= pdev->dev.coherent_dma_mask;
@@ -144,9 +156,6 @@ err4:
 err3:
 	platform_device_put(musb);
 
-err2:
-	musb_put_id(&pdev->dev, musbid);
-
 err1:
 	kfree(glue);
 
@@ -154,13 +163,11 @@ err0:
 	return ret;
 }
 
-static int __devexit ux500_remove(struct platform_device *pdev)
+static int ux500_remove(struct platform_device *pdev)
 {
 	struct ux500_glue	*glue = platform_get_drvdata(pdev);
 
-	musb_put_id(&pdev->dev, glue->musb->id);
-	platform_device_del(glue->musb);
-	platform_device_put(glue->musb);
+	platform_device_unregister(glue->musb);
 	clk_disable(glue->clk);
 	clk_put(glue->clk);
 	kfree(glue);
@@ -209,7 +216,7 @@ static const struct dev_pm_ops ux500_pm_ops = {
 
 static struct platform_driver ux500_driver = {
 	.probe		= ux500_probe,
-	.remove		= __devexit_p(ux500_remove),
+	.remove		= ux500_remove,
 	.driver		= {
 		.name	= "musb-ux500",
 		.pm	= DEV_PM_OPS,
@@ -219,15 +226,4 @@ static struct platform_driver ux500_driver = {
 MODULE_DESCRIPTION("UX500 MUSB Glue Layer");
 MODULE_AUTHOR("Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>");
 MODULE_LICENSE("GPL v2");
-
-static int __init ux500_init(void)
-{
-	return platform_driver_register(&ux500_driver);
-}
-module_init(ux500_init);
-
-static void __exit ux500_exit(void)
-{
-	platform_driver_unregister(&ux500_driver);
-}
-module_exit(ux500_exit);
+module_platform_driver(ux500_driver);
diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c
index f1059e7..039e567 100644
--- a/drivers/usb/musb/ux500_dma.c
+++ b/drivers/usb/musb/ux500_dma.c
@@ -364,8 +364,7 @@ void dma_controller_destroy(struct dma_controller *c)
 	kfree(controller);
 }
 
-struct dma_controller *__devinit
-dma_controller_create(struct musb *musb, void __iomem *base)
+struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *base)
 {
 	struct ux500_dma_controller *controller;
 	struct platform_device *pdev = to_platform_device(musb->controller);
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c
index ae8ad56..2d86f26 100644
--- a/drivers/usb/otg/ab8500-usb.c
+++ b/drivers/usb/otg/ab8500-usb.c
@@ -468,7 +468,7 @@ static int ab8500_usb_v2_res_setup(struct platform_device *pdev,
 	return 0;
 }
 
-static int __devinit ab8500_usb_probe(struct platform_device *pdev)
+static int ab8500_usb_probe(struct platform_device *pdev)
 {
 	struct ab8500_usb	*ab;
 	struct usb_otg		*otg;
@@ -546,7 +546,7 @@ fail0:
 	return err;
 }
 
-static int __devexit ab8500_usb_remove(struct platform_device *pdev)
+static int ab8500_usb_remove(struct platform_device *pdev)
 {
 	struct ab8500_usb *ab = platform_get_drvdata(pdev);
 
@@ -571,7 +571,7 @@ static int __devexit ab8500_usb_remove(struct platform_device *pdev)
 
 static struct platform_driver ab8500_usb_driver = {
 	.probe		= ab8500_usb_probe,
-	.remove		= __devexit_p(ab8500_usb_remove),
+	.remove		= ab8500_usb_remove,
 	.driver		= {
 		.name	= "ab8500-usb",
 		.owner	= THIS_MODULE,
diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c
index c19d1d7..d16adb4 100644
--- a/drivers/usb/otg/fsl_otg.c
+++ b/drivers/usb/otg/fsl_otg.c
@@ -1110,7 +1110,7 @@ static const struct file_operations otg_fops = {
 	.release = fsl_otg_release,
 };
 
-static int __devinit fsl_otg_probe(struct platform_device *pdev)
+static int fsl_otg_probe(struct platform_device *pdev)
 {
 	int ret;
 
@@ -1144,7 +1144,7 @@ static int __devinit fsl_otg_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit fsl_otg_remove(struct platform_device *pdev)
+static int fsl_otg_remove(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
 
@@ -1169,7 +1169,7 @@ static int __devexit fsl_otg_remove(struct platform_device *pdev)
 
 struct platform_driver fsl_otg_driver = {
 	.probe = fsl_otg_probe,
-	.remove = __devexit_p(fsl_otg_remove),
+	.remove = fsl_otg_remove,
 	.driver = {
 		.name = driver_name,
 		.owner = THIS_MODULE,
diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c
index ceee211..af9cb11 100644
--- a/drivers/usb/otg/isp1301_omap.c
+++ b/drivers/usb/otg/isp1301_omap.c
@@ -1493,7 +1493,7 @@ isp1301_start_hnp(struct usb_otg *otg)
 
 /*-------------------------------------------------------------------------*/
 
-static int __devinit
+static int
 isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
 {
 	int			status;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 9f5fc90..3b9f0d9 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1606,7 +1606,7 @@ free_motg:
 	return ret;
 }
 
-static int __devexit msm_otg_remove(struct platform_device *pdev)
+static int msm_otg_remove(struct platform_device *pdev)
 {
 	struct msm_otg *motg = platform_get_drvdata(pdev);
 	struct usb_phy *phy = &motg->phy;
@@ -1746,7 +1746,7 @@ static const struct dev_pm_ops msm_otg_dev_pm_ops = {
 #endif
 
 static struct platform_driver msm_otg_driver = {
-	.remove = __devexit_p(msm_otg_remove),
+	.remove = msm_otg_remove,
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c
index 3f124e8..1dd5750 100644
--- a/drivers/usb/otg/mv_otg.c
+++ b/drivers/usb/otg/mv_otg.c
@@ -958,16 +958,4 @@ static struct platform_driver mv_otg_driver = {
 	.resume = mv_otg_resume,
 #endif
 };
-
-static int __init mv_otg_init(void)
-{
-	return platform_driver_register(&mv_otg_driver);
-}
-
-static void __exit mv_otg_exit(void)
-{
-	platform_driver_unregister(&mv_otg_driver);
-}
-
-module_init(mv_otg_init);
-module_exit(mv_otg_exit);
+module_platform_driver(mv_otg_driver);
diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/otg/mxs-phy.c
index 88db976..7630272 100644
--- a/drivers/usb/otg/mxs-phy.c
+++ b/drivers/usb/otg/mxs-phy.c
@@ -20,7 +20,6 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/io.h>
-#include <linux/workqueue.h>
 
 #define DRIVER_NAME "mxs_phy"
 
@@ -35,16 +34,9 @@
 #define BM_USBPHY_CTRL_ENUTMILEVEL2		BIT(14)
 #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT	BIT(1)
 
-/*
- * Amount of delay in miliseconds to safely enable ENHOSTDISCONDETECT bit
- * so that connection and reset processing can be completed for the root hub.
- */
-#define MXY_PHY_ENHOSTDISCONDETECT_DELAY	250
-
 struct mxs_phy {
 	struct usb_phy phy;
 	struct clk *clk;
-	struct delayed_work enhostdiscondetect_work;
 };
 
 #define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
@@ -70,7 +62,6 @@ static int mxs_phy_init(struct usb_phy *phy)
 
 	clk_prepare_enable(mxs_phy->clk);
 	mxs_phy_hw_init(mxs_phy);
-	INIT_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work, NULL);
 
 	return 0;
 }
@@ -85,46 +76,28 @@ static void mxs_phy_shutdown(struct usb_phy *phy)
 	clk_disable_unprepare(mxs_phy->clk);
 }
 
-static void mxs_phy_enhostdiscondetect_delay(struct work_struct *ws)
+static int mxs_phy_on_connect(struct usb_phy *phy,
+		enum usb_device_speed speed)
 {
-	struct mxs_phy *mxs_phy = container_of(ws, struct mxs_phy,
-						enhostdiscondetect_work.work);
-
-	/* Enable HOSTDISCONDETECT after delay. */
-	dev_dbg(mxs_phy->phy.dev, "Setting ENHOSTDISCONDETECT\n");
-	writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
-				mxs_phy->phy.io_priv + HW_USBPHY_CTRL_SET);
-}
-
-static int mxs_phy_on_connect(struct usb_phy *phy, int port)
-{
-	struct mxs_phy *mxs_phy = to_mxs_phy(phy);
-
-	dev_dbg(phy->dev, "Connect on port %d\n", port);
-
-	mxs_phy_hw_init(mxs_phy);
+	dev_dbg(phy->dev, "%s speed device has connected\n",
+		(speed == USB_SPEED_HIGH) ? "high" : "non-high");
 
-	/*
-	 * Delay enabling ENHOSTDISCONDETECT so that connection and
-	 * reset processing can be completed for the root hub.
-	 */
-	dev_dbg(phy->dev, "Delaying setting ENHOSTDISCONDETECT\n");
-	PREPARE_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work,
-			mxs_phy_enhostdiscondetect_delay);
-	schedule_delayed_work(&mxs_phy->enhostdiscondetect_work,
-			msecs_to_jiffies(MXY_PHY_ENHOSTDISCONDETECT_DELAY));
+	if (speed == USB_SPEED_HIGH)
+		writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+				phy->io_priv + HW_USBPHY_CTRL_SET);
 
 	return 0;
 }
 
-static int mxs_phy_on_disconnect(struct usb_phy *phy, int port)
+static int mxs_phy_on_disconnect(struct usb_phy *phy,
+		enum usb_device_speed speed)
 {
-	dev_dbg(phy->dev, "Disconnect on port %d\n", port);
+	dev_dbg(phy->dev, "%s speed device has disconnected\n",
+		(speed == USB_SPEED_HIGH) ? "high" : "non-high");
 
-	/* No need to delay before clearing ENHOSTDISCONDETECT. */
-	dev_dbg(phy->dev, "Clearing ENHOSTDISCONDETECT\n");
-	writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
-			phy->io_priv + HW_USBPHY_CTRL_CLR);
+	if (speed == USB_SPEED_HIGH)
+		writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+				phy->io_priv + HW_USBPHY_CTRL_CLR);
 
 	return 0;
 }
@@ -176,7 +149,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit mxs_phy_remove(struct platform_device *pdev)
+static int mxs_phy_remove(struct platform_device *pdev)
 {
 	platform_set_drvdata(pdev, NULL);
 
@@ -191,7 +164,7 @@ MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);
 
 static struct platform_driver mxs_phy_driver = {
 	.probe = mxs_phy_probe,
-	.remove = __devexit_p(mxs_phy_remove),
+	.remove = mxs_phy_remove,
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner	= THIS_MODULE,
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
index e52e35e..a3ce24b 100644
--- a/drivers/usb/otg/nop-usb-xceiv.c
+++ b/drivers/usb/otg/nop-usb-xceiv.c
@@ -93,7 +93,7 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
 	return 0;
 }
 
-static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev)
+static int nop_usb_xceiv_probe(struct platform_device *pdev)
 {
 	struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data;
 	struct nop_usb_xceiv	*nop;
@@ -141,7 +141,7 @@ exit:
 	return err;
 }
 
-static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev)
+static int nop_usb_xceiv_remove(struct platform_device *pdev)
 {
 	struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
 
@@ -156,7 +156,7 @@ static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev)
 
 static struct platform_driver nop_usb_xceiv_driver = {
 	.probe		= nop_usb_xceiv_probe,
-	.remove		= __devexit_p(nop_usb_xceiv_remove),
+	.remove		= nop_usb_xceiv_remove,
 	.driver		= {
 		.name	= "nop_usb_xceiv",
 		.owner	= THIS_MODULE,
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index f0d2e75..0a70193 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -123,10 +123,10 @@
 #define PHY_CLK_CTRL_STS		0xFF
 #define PHY_DPLL_CLK			(1 << 0)
 
-/* In module TWL4030_MODULE_PM_MASTER */
+/* In module TWL_MODULE_PM_MASTER */
 #define STS_HW_CONDITIONS		0x0F
 
-/* In module TWL4030_MODULE_PM_RECEIVER */
+/* In module TWL_MODULE_PM_RECEIVER */
 #define VUSB_DEDICATED1			0x7D
 #define VUSB_DEDICATED2			0x7E
 #define VUSB1V5_DEV_GRP			0x71
@@ -195,14 +195,14 @@ static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl,
 }
 
 #define twl4030_usb_write_verify(twl, address, data)	\
-	twl4030_i2c_write_u8_verify(twl, TWL4030_MODULE_USB, (data), (address))
+	twl4030_i2c_write_u8_verify(twl, TWL_MODULE_USB, (data), (address))
 
 static inline int twl4030_usb_write(struct twl4030_usb *twl,
 		u8 address, u8 data)
 {
 	int ret = 0;
 
-	ret = twl_i2c_write_u8(TWL4030_MODULE_USB, data, address);
+	ret = twl_i2c_write_u8(TWL_MODULE_USB, data, address);
 	if (ret < 0)
 		dev_dbg(twl->dev,
 			"TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
@@ -227,7 +227,7 @@ static inline int twl4030_readb(struct twl4030_usb *twl, u8 module, u8 address)
 
 static inline int twl4030_usb_read(struct twl4030_usb *twl, u8 address)
 {
-	return twl4030_readb(twl, TWL4030_MODULE_USB, address);
+	return twl4030_readb(twl, TWL_MODULE_USB, address);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -264,8 +264,7 @@ static enum omap_musb_vbus_id_status
 	 * signal is active, the OTG module is activated, and
 	 * its interrupt may be raised (may wake the system).
 	 */
-	status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER,
-			STS_HW_CONDITIONS);
+	status = twl4030_readb(twl, TWL_MODULE_PM_MASTER, STS_HW_CONDITIONS);
 	if (status < 0)
 		dev_err(twl->dev, "USB link status err %d\n", status);
 	else if (status & (BIT(7) | BIT(2))) {
@@ -372,8 +371,7 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on)
 		 * SLEEP. We work around this by clearing the bit after usv3v1
 		 * is re-activated. This ensures that VUSB3V1 is really active.
 		 */
-		twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0,
-							VUSB_DEDICATED2);
+		twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);
 		regulator_enable(twl->usb1v5);
 		__twl4030_phy_power(twl, 1);
 		twl4030_usb_write(twl, PHY_CLK_CTRL,
@@ -419,50 +417,48 @@ static void twl4030_phy_resume(struct twl4030_usb *twl)
 static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
 {
 	/* Enable writing to power configuration registers */
-	twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
-			TWL4030_PM_MASTER_KEY_CFG1,
-			TWL4030_PM_MASTER_PROTECT_KEY);
+	twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
+			 TWL4030_PM_MASTER_PROTECT_KEY);
 
-	twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
-			TWL4030_PM_MASTER_KEY_CFG2,
-			TWL4030_PM_MASTER_PROTECT_KEY);
+	twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
+			 TWL4030_PM_MASTER_PROTECT_KEY);
 
 	/* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/
-	/*twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/
+	/*twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/
 
 	/* input to VUSB3V1 LDO is from VBAT, not VBUS */
-	twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
+	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
 
 	/* Initialize 3.1V regulator */
-	twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
+	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
 
 	twl->usb3v1 = regulator_get(twl->dev, "usb3v1");
 	if (IS_ERR(twl->usb3v1))
 		return -ENODEV;
 
-	twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
+	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
 
 	/* Initialize 1.5V regulator */
-	twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
+	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
 
 	twl->usb1v5 = regulator_get(twl->dev, "usb1v5");
 	if (IS_ERR(twl->usb1v5))
 		goto fail1;
 
-	twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
+	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
 
 	/* Initialize 1.8V regulator */
-	twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
+	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
 
 	twl->usb1v8 = regulator_get(twl->dev, "usb1v8");
 	if (IS_ERR(twl->usb1v8))
 		goto fail2;
 
-	twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
+	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
 
 	/* disable access to power configuration registers */
-	twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0,
-			TWL4030_PM_MASTER_PROTECT_KEY);
+	twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
+			 TWL4030_PM_MASTER_PROTECT_KEY);
 
 	return 0;
 
@@ -579,7 +575,7 @@ static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host)
 	return 0;
 }
 
-static int __devinit twl4030_usb_probe(struct platform_device *pdev)
+static int twl4030_usb_probe(struct platform_device *pdev)
 {
 	struct twl4030_usb_data *pdata = pdev->dev.platform_data;
 	struct twl4030_usb	*twl;
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index fcadef7..8cd6cf4 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -310,7 +310,7 @@ static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled)
 	return 0;
 }
 
-static int __devinit twl6030_usb_probe(struct platform_device *pdev)
+static int twl6030_usb_probe(struct platform_device *pdev)
 {
 	u32 ret;
 	struct twl6030_usb	*twl;
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 63c339b..7eb73c5 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -32,3 +32,15 @@ config MV_U3D_PHY
 	help
 	  Enable this to support Marvell USB 3.0 phy controller for Marvell
 	  SoC.
+
+config USB_RCAR_PHY
+	tristate "Renesas R-Car USB phy support"
+	depends on USB || USB_GADGET
+	select USB_OTG_UTILS
+	help
+	  Say Y here to add support for the Renesas R-Car USB phy driver.
+	  This chip is typically used as USB phy for USB host, gadget.
+	  This driver supports: R8A7779
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called rcar-phy.
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index b069f29..1a579a8 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_OMAP_USB2)			+= omap-usb2.o
 obj-$(CONFIG_USB_ISP1301)		+= isp1301.o
 obj-$(CONFIG_MV_U3D_PHY)		+= mv_u3d_phy.o
 obj-$(CONFIG_USB_EHCI_TEGRA)	+= tegra_usb_phy.o
+obj-$(CONFIG_USB_RCAR_PHY)		+= rcar-phy.o
diff --git a/drivers/usb/phy/mv_u3d_phy.c b/drivers/usb/phy/mv_u3d_phy.c
index 9f1c5d3..eaddbe3 100644
--- a/drivers/usb/phy/mv_u3d_phy.c
+++ b/drivers/usb/phy/mv_u3d_phy.c
@@ -262,7 +262,7 @@ calstart:
 	return 0;
 }
 
-static int __devinit mv_u3d_phy_probe(struct platform_device *pdev)
+static int mv_u3d_phy_probe(struct platform_device *pdev)
 {
 	struct mv_u3d_phy *mv_u3d_phy;
 	struct mv_usb_platform_data *pdata;
@@ -331,7 +331,7 @@ static int __exit mv_u3d_phy_remove(struct platform_device *pdev)
 
 static struct platform_driver mv_u3d_phy_driver = {
 	.probe		= mv_u3d_phy_probe,
-	.remove		= __devexit_p(mv_u3d_phy_remove),
+	.remove		= mv_u3d_phy_remove,
 	.driver		= {
 		.name	= "mv-u3d-phy",
 		.owner	= THIS_MODULE,
diff --git a/drivers/usb/phy/omap-usb2.c b/drivers/usb/phy/omap-usb2.c
index 15ab3d6..26ae8f4 100644
--- a/drivers/usb/phy/omap-usb2.c
+++ b/drivers/usb/phy/omap-usb2.c
@@ -141,7 +141,7 @@ static int omap_usb2_suspend(struct usb_phy *x, int suspend)
 	return 0;
 }
 
-static int __devinit omap_usb2_probe(struct platform_device *pdev)
+static int omap_usb2_probe(struct platform_device *pdev)
 {
 	struct omap_usb			*phy;
 	struct usb_otg			*otg;
@@ -199,7 +199,7 @@ static int __devinit omap_usb2_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit omap_usb2_remove(struct platform_device *pdev)
+static int omap_usb2_remove(struct platform_device *pdev)
 {
 	struct omap_usb	*phy = platform_get_drvdata(pdev);
 
@@ -254,7 +254,7 @@ MODULE_DEVICE_TABLE(of, omap_usb2_id_table);
 
 static struct platform_driver omap_usb2_driver = {
 	.probe		= omap_usb2_probe,
-	.remove		= __devexit_p(omap_usb2_remove),
+	.remove		= omap_usb2_remove,
 	.driver		= {
 		.name	= "omap-usb2",
 		.owner	= THIS_MODULE,
diff --git a/drivers/usb/phy/rcar-phy.c b/drivers/usb/phy/rcar-phy.c
new file mode 100644
index 0000000..a35681b
--- /dev/null
+++ b/drivers/usb/phy/rcar-phy.c
@@ -0,0 +1,220 @@
+/*
+ * Renesas R-Car USB phy driver
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/usb/otg.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+
+/* USBH common register */
+#define USBPCTRL0	0x0800
+#define USBPCTRL1	0x0804
+#define USBST		0x0808
+#define USBEH0		0x080C
+#define USBOH0		0x081C
+#define USBCTL0		0x0858
+#define EIIBC1		0x0094
+#define EIIBC2		0x009C
+
+/* USBPCTRL1 */
+#define PHY_RST		(1 << 2)
+#define PLL_ENB		(1 << 1)
+#define PHY_ENB		(1 << 0)
+
+/* USBST */
+#define ST_ACT		(1 << 31)
+#define ST_PLL		(1 << 30)
+
+struct rcar_usb_phy_priv {
+	struct usb_phy phy;
+	spinlock_t lock;
+
+	void __iomem *reg0;
+	void __iomem *reg1;
+	int counter;
+};
+
+#define usb_phy_to_priv(p) container_of(p, struct rcar_usb_phy_priv, phy)
+
+
+/*
+ * USB initial/install operation.
+ *
+ * This function setup USB phy.
+ * The used value and setting order came from
+ * [USB :: Initial setting] on datasheet.
+ */
+static int rcar_usb_phy_init(struct usb_phy *phy)
+{
+	struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
+	struct device *dev = phy->dev;
+	void __iomem *reg0 = priv->reg0;
+	void __iomem *reg1 = priv->reg1;
+	int i;
+	u32 val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (priv->counter++ == 0) {
+
+		/*
+		 * USB phy start-up
+		 */
+
+		/* (1) USB-PHY standby release */
+		iowrite32(PHY_ENB, (reg0 + USBPCTRL1));
+
+		/* (2) start USB-PHY internal PLL */
+		iowrite32(PHY_ENB | PLL_ENB, (reg0 + USBPCTRL1));
+
+		/* (3) USB module status check */
+		for (i = 0; i < 1024; i++) {
+			udelay(10);
+			val = ioread32(reg0 + USBST);
+			if (val == (ST_ACT | ST_PLL))
+				break;
+		}
+
+		if (val != (ST_ACT | ST_PLL)) {
+			dev_err(dev, "USB phy not ready\n");
+			goto phy_init_end;
+		}
+
+		/* (4) USB-PHY reset clear */
+		iowrite32(PHY_ENB | PLL_ENB | PHY_RST, (reg0 + USBPCTRL1));
+
+		/* set platform specific port settings */
+		iowrite32(0x00000000, (reg0 + USBPCTRL0));
+
+		/*
+		 * EHCI IP internal buffer setting
+		 * EHCI IP internal buffer enable
+		 *
+		 * These are recommended value of a datasheet
+		 * see [USB :: EHCI internal buffer setting]
+		 */
+		iowrite32(0x00ff0040, (reg0 + EIIBC1));
+		iowrite32(0x00ff0040, (reg1 + EIIBC1));
+
+		iowrite32(0x00000001, (reg0 + EIIBC2));
+		iowrite32(0x00000001, (reg1 + EIIBC2));
+
+		/*
+		 * Bus alignment settings
+		 */
+
+		/* (1) EHCI bus alignment (little endian) */
+		iowrite32(0x00000000, (reg0 + USBEH0));
+
+		/* (1) OHCI bus alignment (little endian) */
+		iowrite32(0x00000000, (reg0 + USBOH0));
+	}
+
+phy_init_end:
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+
+static void rcar_usb_phy_shutdown(struct usb_phy *phy)
+{
+	struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
+	void __iomem *reg0 = priv->reg0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	if (priv->counter-- == 1) { /* last user */
+		iowrite32(0x00000000, (reg0 + USBPCTRL0));
+		iowrite32(0x00000000, (reg0 + USBPCTRL1));
+	}
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int rcar_usb_phy_probe(struct platform_device *pdev)
+{
+	struct rcar_usb_phy_priv *priv;
+	struct resource *res0, *res1;
+	struct device *dev = &pdev->dev;
+	void __iomem *reg0, *reg1;
+	int ret;
+
+	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res0 || !res1) {
+		dev_err(dev, "Not enough platform resources\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * CAUTION
+	 *
+	 * Because this phy address is also mapped under OHCI/EHCI address area,
+	 * this driver can't use devm_request_and_ioremap(dev, res) here
+	 */
+	reg0 = devm_ioremap_nocache(dev, res0->start, resource_size(res0));
+	reg1 = devm_ioremap_nocache(dev, res1->start, resource_size(res1));
+	if (!reg0 || !reg1) {
+		dev_err(dev, "ioremap error\n");
+		return -ENOMEM;
+	}
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(dev, "priv data allocation error\n");
+		return -ENOMEM;
+	}
+
+	priv->reg0		= reg0;
+	priv->reg1		= reg1;
+	priv->counter		= 0;
+	priv->phy.dev		= dev;
+	priv->phy.label		= dev_name(dev);
+	priv->phy.init		= rcar_usb_phy_init;
+	priv->phy.shutdown	= rcar_usb_phy_shutdown;
+	spin_lock_init(&priv->lock);
+
+	ret = usb_add_phy(&priv->phy, USB_PHY_TYPE_USB2);
+	if (ret < 0) {
+		dev_err(dev, "usb phy addition error\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	return ret;
+}
+
+static int rcar_usb_phy_remove(struct platform_device *pdev)
+{
+	struct rcar_usb_phy_priv *priv = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&priv->phy);
+
+	return 0;
+}
+
+static struct platform_driver rcar_usb_phy_driver = {
+	.driver		= {
+		.name	= "rcar_usb_phy",
+	},
+	.probe		= rcar_usb_phy_probe,
+	.remove		= rcar_usb_phy_remove,
+};
+
+module_platform_driver(rcar_usb_phy_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Renesas R-Car USB phy");
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
diff --git a/drivers/usb/phy/tegra_usb_phy.c b/drivers/usb/phy/tegra_usb_phy.c
index 987116f9..9d13c81 100644
--- a/drivers/usb/phy/tegra_usb_phy.c
+++ b/drivers/usb/phy/tegra_usb_phy.c
@@ -29,7 +29,9 @@
 #include <linux/usb/ulpi.h>
 #include <asm/mach-types.h>
 #include <linux/usb/tegra_usb_phy.h>
-#include <mach/iomap.h>
+
+#define TEGRA_USB_BASE		0xC5000000
+#define TEGRA_USB_SIZE		SZ_16K
 
 #define ULPI_VIEWPORT		0x170
 
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index 072edc1..38bce04 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -132,6 +132,11 @@ void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable)
 	usbhs_bset(priv, SYSCFG, mask, enable ? val : 0);
 }
 
+void usbhs_sys_function_pullup(struct usbhs_priv *priv, int enable)
+{
+	usbhs_bset(priv, SYSCFG, DPRPU, enable ? DPRPU : 0);
+}
+
 void usbhs_sys_set_test_mode(struct usbhs_priv *priv, u16 mode)
 {
 	usbhs_write(priv, TESTMODE, mode);
@@ -551,7 +556,7 @@ probe_end_pipe_exit:
 	return ret;
 }
 
-static int __devexit usbhs_remove(struct platform_device *pdev)
+static int usbhs_remove(struct platform_device *pdev)
 {
 	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
 	struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;
@@ -631,7 +636,7 @@ static struct platform_driver renesas_usbhs_driver = {
 		.pm	= &usbhsc_pm_ops,
 	},
 	.probe		= usbhs_probe,
-	.remove		= __devexit_p(usbhs_remove),
+	.remove		= usbhs_remove,
 };
 
 module_platform_driver(renesas_usbhs_driver);
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h
index dddf40a..c69dd2f 100644
--- a/drivers/usb/renesas_usbhs/common.h
+++ b/drivers/usb/renesas_usbhs/common.h
@@ -285,6 +285,7 @@ void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data);
  */
 void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable);
 void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable);
+void usbhs_sys_function_pullup(struct usbhs_priv *priv, int enable);
 void usbhs_sys_set_test_mode(struct usbhs_priv *priv, u16 mode);
 
 /*
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index c021b20..9538f0f 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -163,7 +163,7 @@ static int usbhsf_pkt_handler(struct usbhs_pipe *pipe, int type)
 		func = pkt->handler->dma_done;
 		break;
 	default:
-		dev_err(dev, "unknown pkt hander\n");
+		dev_err(dev, "unknown pkt handler\n");
 		goto __usbhs_pkt_handler_end;
 	}
 
@@ -192,8 +192,8 @@ void usbhs_pkt_start(struct usbhs_pipe *pipe)
 /*
  *		irq enable/disable function
  */
-#define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, bempsts, e)
-#define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, brdysts, e)
+#define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, irq_bempsts, e)
+#define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, irq_brdysts, e)
 #define usbhsf_irq_callback_ctrl(pipe, status, enable)			\
 	({								\
 		struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);	\
@@ -202,9 +202,9 @@ void usbhs_pkt_start(struct usbhs_pipe *pipe)
 		if (!mod)						\
 			return;						\
 		if (enable)						\
-			mod->irq_##status |= status;			\
+			mod->status |= status;				\
 		else							\
-			mod->irq_##status &= ~status;			\
+			mod->status &= ~status;				\
 		usbhs_irq_callback_update(priv, mod);			\
 	})
 
@@ -488,6 +488,8 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done)
 	usbhs_pipe_data_sequence(pipe, pkt->sequence);
 	pkt->sequence = -1; /* -1 sequence will be ignored */
 
+	usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length);
+
 	ret = usbhsf_fifo_select(pipe, fifo, 1);
 	if (ret < 0)
 		return 0;
@@ -594,6 +596,7 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
 	usbhs_pipe_data_sequence(pipe, pkt->sequence);
 	pkt->sequence = -1; /* -1 sequence will be ignored */
 
+	usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length);
 	usbhs_pipe_enable(pipe);
 	usbhsf_rx_irq_ctrl(pipe, 1);
 
@@ -795,6 +798,7 @@ static void xfer_work(struct work_struct *work)
 	dev_dbg(dev, "  %s %d (%d/ %d)\n",
 		fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
 
+	usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);
 	usbhs_pipe_enable(pipe);
 	usbhsf_dma_start(pipe, fifo);
 	dma_async_issue_pending(chan);
diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c
index 61933a9..6a030b9 100644
--- a/drivers/usb/renesas_usbhs/mod.c
+++ b/drivers/usb/renesas_usbhs/mod.c
@@ -151,7 +151,7 @@ int usbhs_mod_probe(struct usbhs_priv *priv)
 		goto mod_init_host_err;
 
 	/* irq settings */
-	ret = request_irq(priv->irq, usbhs_interrupt,
+	ret = devm_request_irq(dev, priv->irq, usbhs_interrupt,
 			  priv->irqflags, dev_name(dev), priv);
 	if (ret) {
 		dev_err(dev, "irq request err\n");
@@ -172,7 +172,6 @@ void usbhs_mod_remove(struct usbhs_priv *priv)
 {
 	usbhs_mod_host_remove(priv);
 	usbhs_mod_gadget_remove(priv);
-	free_irq(priv->irq, priv);
 }
 
 /*
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 28478ce..dd41f61 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -883,6 +883,16 @@ static int usbhsg_get_frame(struct usb_gadget *gadget)
 	return usbhs_frame_get_num(priv);
 }
 
+static int usbhsg_pullup(struct usb_gadget *gadget, int is_on)
+{
+	struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
+	struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
+
+	usbhs_sys_function_pullup(priv, is_on);
+
+	return 0;
+}
+
 static int usbhsg_set_selfpowered(struct usb_gadget *gadget, int is_self)
 {
 	struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
@@ -900,6 +910,7 @@ static struct usb_gadget_ops usbhsg_gadget_ops = {
 	.set_selfpowered	= usbhsg_set_selfpowered,
 	.udc_start		= usbhsg_gadget_start,
 	.udc_stop		= usbhsg_gadget_stop,
+	.pullup			= usbhsg_pullup,
 };
 
 static int usbhsg_start(struct usbhs_priv *priv)
diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c
index 069cd76..3d3cd6c 100644
--- a/drivers/usb/renesas_usbhs/mod_host.c
+++ b/drivers/usb/renesas_usbhs/mod_host.c
@@ -85,6 +85,7 @@ struct usbhsh_ep {
 	struct usbhsh_device	*udev;   /* attached udev */
 	struct usb_host_endpoint *ep;
 	struct list_head	ep_list; /* list to usbhsh_device */
+	unsigned int		counter; /* pipe attach counter */
 };
 
 #define USBHSH_DEVICE_MAX	10 /* see DEVADDn / DCPMAXP / PIPEMAXP */
@@ -271,8 +272,12 @@ static int usbhsh_pipe_attach(struct usbhsh_hpriv *hpriv,
 	/********************  spin lock ********************/
 	usbhs_lock(priv, flags);
 
-	if (unlikely(usbhsh_uep_to_pipe(uep))) {
-		dev_err(dev, "uep already has pipe\n");
+	/*
+	 * if uep has been attached to pipe,
+	 * reuse it
+	 */
+	if (usbhsh_uep_to_pipe(uep)) {
+		ret = 0;
 		goto usbhsh_pipe_attach_done;
 	}
 
@@ -320,6 +325,9 @@ static int usbhsh_pipe_attach(struct usbhsh_hpriv *hpriv,
 	}
 
 usbhsh_pipe_attach_done:
+	if (0 == ret)
+		uep->counter++;
+
 	usbhs_unlock(priv, flags);
 	/********************  spin unlock ******************/
 
@@ -346,7 +354,7 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv,
 
 	if (unlikely(!pipe)) {
 		dev_err(dev, "uep doens't have pipe\n");
-	} else {
+	} else if (1 == uep->counter--) { /* last user */
 		struct usb_host_endpoint *ep = usbhsh_uep_to_ep(uep);
 		struct usbhsh_device *udev = usbhsh_uep_to_udev(uep);
 
@@ -391,6 +399,7 @@ static int usbhsh_endpoint_attach(struct usbhsh_hpriv *hpriv,
 	/*
 	 * init endpoint
 	 */
+	uep->counter = 0;
 	INIT_LIST_HEAD(&uep->ep_list);
 	list_add_tail(&uep->ep_list, &udev->ep_list_head);
 
@@ -686,9 +695,9 @@ static int usbhsh_queue_push(struct usb_hcd *hcd,
 	}
 
 	if (usb_pipein(urb->pipe))
-		pipe->handler = &usbhs_fifo_pio_pop_handler;
+		pipe->handler = &usbhs_fifo_dma_pop_handler;
 	else
-		pipe->handler = &usbhs_fifo_pio_push_handler;
+		pipe->handler = &usbhs_fifo_dma_push_handler;
 
 	buf = (void *)(urb->transfer_buffer + urb->actual_length);
 	len = urb->transfer_buffer_length - urb->actual_length;
@@ -921,6 +930,19 @@ static int usbhsh_dcp_queue_push(struct usb_hcd *hcd,
  */
 static int usbhsh_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
 {
+	if (map) {
+		struct usbhsh_request *ureq = usbhsh_pkt_to_ureq(pkt);
+		struct urb *urb = ureq->urb;
+
+		/* it can not use scatter/gather */
+		if (urb->num_sgs)
+			return -EINVAL;
+
+		pkt->dma = urb->transfer_dma;
+		if (!pkt->dma)
+			return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -946,7 +968,6 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
 	struct usb_host_endpoint *ep = urb->ep;
 	struct usbhsh_device *new_udev = NULL;
 	int is_dir_in = usb_pipein(urb->pipe);
-	int i;
 	int ret;
 
 	dev_dbg(dev, "%s (%s)\n", __func__, is_dir_in ? "in" : "out");
@@ -992,13 +1013,7 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
 	 * attach pipe to endpoint
 	 * see [image of mod_host]
 	 */
-	for (i = 0; i < 1024; i++) {
-		ret = usbhsh_pipe_attach(hpriv, urb);
-		if (ret < 0)
-			msleep(100);
-		else
-			break;
-	}
+	ret = usbhsh_pipe_attach(hpriv, urb);
 	if (ret < 0) {
 		dev_err(dev, "pipe attach failed\n");
 		goto usbhsh_urb_enqueue_error_free_endpoint;
@@ -1072,8 +1087,6 @@ static void usbhsh_endpoint_disable(struct usb_hcd *hcd,
 static int usbhsh_hub_status_data(struct usb_hcd *hcd, char *buf)
 {
 	struct usbhsh_hpriv *hpriv = usbhsh_hcd_to_hpriv(hcd);
-	struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
-	struct device *dev = usbhs_priv_to_dev(priv);
 	int roothub_id = 1; /* only 1 root hub */
 
 	/*
@@ -1085,8 +1098,6 @@ static int usbhsh_hub_status_data(struct usb_hcd *hcd, char *buf)
 	else
 		*buf = 0;
 
-	dev_dbg(dev, "%s (%02x)\n", __func__, *buf);
-
 	return !!(*buf);
 }
 
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c
index 122526c..7926e1c 100644
--- a/drivers/usb/renesas_usbhs/pipe.c
+++ b/drivers/usb/renesas_usbhs/pipe.c
@@ -93,6 +93,82 @@ static void usbhsp_pipe_cfg_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
 }
 
 /*
+ *		PIPEnTRN/PIPEnTRE functions
+ */
+static void usbhsp_pipe_trn_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
+{
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	struct device *dev = usbhs_priv_to_dev(priv);
+	int num = usbhs_pipe_number(pipe);
+	u16 reg;
+
+	/*
+	 * It is impossible to calculate address,
+	 * since PIPEnTRN addresses were mapped randomly.
+	 */
+#define CASE_PIPExTRN(a)		\
+	case 0x ## a:			\
+		reg = PIPE ## a ## TRN;	\
+		break;
+
+	switch (num) {
+	CASE_PIPExTRN(1);
+	CASE_PIPExTRN(2);
+	CASE_PIPExTRN(3);
+	CASE_PIPExTRN(4);
+	CASE_PIPExTRN(5);
+	CASE_PIPExTRN(B);
+	CASE_PIPExTRN(C);
+	CASE_PIPExTRN(D);
+	CASE_PIPExTRN(E);
+	CASE_PIPExTRN(F);
+	CASE_PIPExTRN(9);
+	CASE_PIPExTRN(A);
+	default:
+		dev_err(dev, "unknown pipe (%d)\n", num);
+		return;
+	}
+	__usbhsp_pipe_xxx_set(pipe, 0, reg, mask, val);
+}
+
+static void usbhsp_pipe_tre_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
+{
+	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+	struct device *dev = usbhs_priv_to_dev(priv);
+	int num = usbhs_pipe_number(pipe);
+	u16 reg;
+
+	/*
+	 * It is impossible to calculate address,
+	 * since PIPEnTRE addresses were mapped randomly.
+	 */
+#define CASE_PIPExTRE(a)			\
+	case 0x ## a:				\
+		reg = PIPE ## a ## TRE;		\
+		break;
+
+	switch (num) {
+	CASE_PIPExTRE(1);
+	CASE_PIPExTRE(2);
+	CASE_PIPExTRE(3);
+	CASE_PIPExTRE(4);
+	CASE_PIPExTRE(5);
+	CASE_PIPExTRE(B);
+	CASE_PIPExTRE(C);
+	CASE_PIPExTRE(D);
+	CASE_PIPExTRE(E);
+	CASE_PIPExTRE(F);
+	CASE_PIPExTRE(9);
+	CASE_PIPExTRE(A);
+	default:
+		dev_err(dev, "unknown pipe (%d)\n", num);
+		return;
+	}
+
+	__usbhsp_pipe_xxx_set(pipe, 0, reg, mask, val);
+}
+
+/*
  *		PIPEBUF
  */
 static void usbhsp_pipe_buf_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
@@ -264,6 +340,31 @@ int usbhs_pipe_is_stall(struct usbhs_pipe *pipe)
 	return (int)(pid == PID_STALL10 || pid == PID_STALL11);
 }
 
+void usbhs_pipe_set_trans_count_if_bulk(struct usbhs_pipe *pipe, int len)
+{
+	if (!usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK))
+		return;
+
+	/*
+	 * clear and disable transfer counter for IN/OUT pipe
+	 */
+	usbhsp_pipe_tre_set(pipe, TRCLR | TRENB, TRCLR);
+
+	/*
+	 * Only IN direction bulk pipe can use transfer count.
+	 * Without using this function,
+	 * received data will break if it was large data size.
+	 * see PIPEnTRN/PIPEnTRE for detail
+	 */
+	if (usbhs_pipe_is_dir_in(pipe)) {
+		int maxp = usbhs_pipe_get_maxpacket(pipe);
+
+		usbhsp_pipe_trn_set(pipe, 0xffff, DIV_ROUND_UP(len, maxp));
+		usbhsp_pipe_tre_set(pipe, TRENB, TRENB); /* enable */
+	}
+}
+
+
 /*
  *		pipe setup
  */
diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h
index 3d80c7b..b476fde 100644
--- a/drivers/usb/renesas_usbhs/pipe.h
+++ b/drivers/usb/renesas_usbhs/pipe.h
@@ -88,6 +88,7 @@ void usbhs_pipe_enable(struct usbhs_pipe *pipe);
 void usbhs_pipe_disable(struct usbhs_pipe *pipe);
 void usbhs_pipe_stall(struct usbhs_pipe *pipe);
 int usbhs_pipe_is_stall(struct usbhs_pipe *pipe);
+void usbhs_pipe_set_trans_count_if_bulk(struct usbhs_pipe *pipe, int len);
 void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo);
 void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 devsel,
 			      u16 epnum, u16 maxp);
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index 54e1bb6..6d110a3 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -68,10 +68,6 @@
 #define THROTTLED		0x01
 #define ACTUALLY_THROTTLED	0x02
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v2.0"
 #define DRIVER_AUTHOR "Naranjo, Manuel Francisco <naranjo.manuel@gmail.com>, Johan Hovold <jhovold@gmail.com>"
 #define DRIVER_DESC "AIRcable USB Driver"
 
@@ -192,5 +188,4 @@ module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index bd50a8a4..a88882c 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -37,11 +37,6 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 
-/*
- * Version information
- */
-
-#define DRIVER_VERSION "v0.7"
 #define DRIVER_AUTHOR "Bart Hartgers <bart.hartgers+ark3116@gmail.com>"
 #define DRIVER_DESC "USB ARK3116 serial/IrDA driver"
 #define DRIVER_DEV_DESC "ARK3116 RS232/IrDA"
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index ea29556..b72a4c1 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -37,10 +37,6 @@
 #include <linux/usb/serial.h>
 #include "belkin_sa.h"
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.3"
 #define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>"
 #define DRIVER_DESC "USB Belkin Serial converter driver"
 
@@ -509,5 +505,4 @@ module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index c15f2e7..37decb1 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -121,7 +121,6 @@ static int usb_serial_device_remove(struct device *dev)
 	return retval;
 }
 
-#ifdef CONFIG_HOTPLUG
 static ssize_t store_new_id(struct device_driver *driver,
 			    const char *buf, size_t count)
 {
@@ -159,15 +158,6 @@ static void free_dynids(struct usb_serial_driver *drv)
 	spin_unlock(&drv->dynids.lock);
 }
 
-#else
-static struct driver_attribute drv_attrs[] = {
-	__ATTR_NULL,
-};
-static inline void free_dynids(struct usb_serial_driver *drv)
-{
-}
-#endif
-
 struct bus_type usb_serial_bus_type = {
 	.name =		"usb-serial",
 	.match =	usb_serial_device_match,
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index eb033fc..f14736f 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -24,10 +24,6 @@
 #include <linux/uaccess.h>
 #include <linux/usb/serial.h>
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.09"
 #define DRIVER_DESC "Silicon Labs CP210x RS232 serial adaptor driver"
 
 /*
@@ -35,8 +31,7 @@
  */
 static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *);
 static void cp210x_close(struct usb_serial_port *);
-static void cp210x_get_termios(struct tty_struct *,
-	struct usb_serial_port *port);
+static void cp210x_get_termios(struct tty_struct *, struct usb_serial_port *);
 static void cp210x_get_termios_port(struct usb_serial_port *port,
 	unsigned int *cflagp, unsigned int *baudp);
 static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *,
@@ -118,6 +113,7 @@ static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */
 	{ USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */
 	{ USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */
+	{ USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */
 	{ USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */
 	{ USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
 	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
@@ -169,7 +165,7 @@ struct cp210x_serial_private {
 static struct usb_serial_driver cp210x_device = {
 	.driver = {
 		.owner =	THIS_MODULE,
-		.name = 	"cp210x",
+		.name =		"cp210x",
 	},
 	.id_table		= id_table,
 	.num_ports		= 1,
@@ -179,7 +175,7 @@ static struct usb_serial_driver cp210x_device = {
 	.close			= cp210x_close,
 	.break_ctl		= cp210x_break_ctl,
 	.set_termios		= cp210x_set_termios,
-	.tiocmget 		= cp210x_tiocmget,
+	.tiocmget		= cp210x_tiocmget,
 	.tiocmset		= cp210x_tiocmset,
 	.attach			= cp210x_startup,
 	.release		= cp210x_release,
@@ -281,7 +277,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
 	int result, i, length;
 
 	/* Number of integers required to contain the array */
-	length = (((size - 1) | 3) + 1)/4;
+	length = (((size - 1) | 3) + 1) / 4;
 
 	buf = kcalloc(length, sizeof(__le32), GFP_KERNEL);
 	if (!buf) {
@@ -328,12 +324,11 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
 	int result, i, length;
 
 	/* Number of integers required to contain the array */
-	length = (((size - 1) | 3) + 1)/4;
+	length = (((size - 1) | 3) + 1) / 4;
 
 	buf = kmalloc(length * sizeof(__le32), GFP_KERNEL);
 	if (!buf) {
-		dev_err(&port->dev, "%s - out of memory.\n",
-				__func__);
+		dev_err(&port->dev, "%s - out of memory.\n", __func__);
 		return -ENOMEM;
 	}
 
@@ -384,7 +379,8 @@ static inline int cp210x_set_config_single(struct usb_serial_port *port,
  * cp210x_quantise_baudrate
  * Quantises the baud rate as per AN205 Table 1
  */
-static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
+static unsigned int cp210x_quantise_baudrate(unsigned int baud)
+{
 	if (baud <= 300)
 		baud = 300;
 	else if (baud <= 600)      baud = 600;
@@ -467,9 +463,7 @@ static void cp210x_get_termios(struct tty_struct *tty,
 		cp210x_get_termios_port(tty->driver_data,
 			&tty->termios.c_cflag, &baud);
 		tty_encode_baud_rate(tty, baud, baud);
-	}
-
-	else {
+	} else {
 		unsigned int cflag;
 		cflag = 0;
 		cp210x_get_termios_port(port, &cflag, &baud);
@@ -693,8 +687,8 @@ static void cp210x_set_termios(struct tty_struct *tty,
 			break;*/
 		default:
 			dev_dbg(dev, "cp210x driver does not support the number of bits requested, using 8 bit mode\n");
-				bits |= BITS_DATA_8;
-				break;
+			bits |= BITS_DATA_8;
+			break;
 		}
 		if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
 			dev_dbg(dev, "Number of data bits requested not supported by device\n");
@@ -767,7 +761,7 @@ static void cp210x_set_termios(struct tty_struct *tty,
 
 }
 
-static int cp210x_tiocmset (struct tty_struct *tty,
+static int cp210x_tiocmset(struct tty_struct *tty,
 		unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -809,7 +803,7 @@ static void cp210x_dtr_rts(struct usb_serial_port *p, int on)
 		cp210x_tiocmset_port(p, 0, TIOCM_DTR|TIOCM_RTS);
 }
 
-static int cp210x_tiocmget (struct tty_struct *tty)
+static int cp210x_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	unsigned int control;
@@ -829,7 +823,7 @@ static int cp210x_tiocmget (struct tty_struct *tty)
 	return result;
 }
 
-static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
+static void cp210x_break_ctl(struct tty_struct *tty, int break_state)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	unsigned int state;
@@ -874,5 +868,4 @@ static void cp210x_release(struct usb_serial *serial)
 module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 4ee77dc..69a4fa1 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -43,10 +43,6 @@
 
 #define CYBERJACK_LOCAL_BUF_SIZE 32
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.01"
 #define DRIVER_AUTHOR "Matthias Bruestle"
 #define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver"
 
@@ -441,5 +437,4 @@ module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index f0da127..fd8c35f 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -50,10 +50,6 @@ static bool stats;
 static int interval;
 static bool unstable_bauds;
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.10"
 #define DRIVER_AUTHOR "Lonnie Mendez <dignome@gmail.com>, Neil Whelchel <koyama@firstlight.net>"
 #define DRIVER_DESC "Cypress USB to Serial Driver"
 
@@ -1303,7 +1299,6 @@ module_usb_serial_driver(serial_drivers, id_table_combined);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
 module_param(stats, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index b50fa1c..45d4af6 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -32,10 +32,6 @@
 
 /* Defines */
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.80.1.2"
 #define DRIVER_AUTHOR "Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>"
 #define DRIVER_DESC "Digi AccelePort USB-2/USB-4 Serial Converter driver"
 
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 43ede4a..0f65861 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -28,10 +28,6 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.3"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Gary Brubaker <xavyer@ix.netcom.com>"
 #define DRIVER_DESC "USB Empeg Mark I/II Driver"
 
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index be84587..0a373b3 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -73,7 +73,6 @@ struct ftdi_private {
 	char prev_status;        /* Used for TIOCMIWAIT */
 	bool dev_gone;        /* Used to abort TIOCMIWAIT */
 	char transmit_empty;	/* If transmitter is empty or not */
-	struct usb_serial_port *port;
 	__u16 interface;	/* FT2232C, FT2232H or FT4232H port interface
 				   (0 for FT232/245) */
 
@@ -192,6 +191,7 @@ static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) },
+	{ USB_DEVICE(NEWPORT_VID, NEWPORT_AGILIS_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SPROG_II) },
@@ -923,6 +923,9 @@ static int ftdi_get_icount(struct tty_struct *tty,
 static int  ftdi_ioctl(struct tty_struct *tty,
 			unsigned int cmd, unsigned long arg);
 static void ftdi_break_ctl(struct tty_struct *tty, int break_state);
+static int ftdi_chars_in_buffer(struct tty_struct *tty);
+static int ftdi_get_modem_status(struct tty_struct *tty,
+						unsigned char status[2]);
 
 static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base);
 static unsigned short int ftdi_232am_baud_to_divisor(int baud);
@@ -957,6 +960,7 @@ static struct usb_serial_driver ftdi_sio_device = {
 	.ioctl =		ftdi_ioctl,
 	.set_termios =		ftdi_set_termios,
 	.break_ctl =		ftdi_break_ctl,
+	.chars_in_buffer =      ftdi_chars_in_buffer,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -1090,6 +1094,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set,
 			__func__,
 			(set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged",
 			(set & TIOCM_RTS) ? "HIGH" : (clear & TIOCM_RTS) ? "LOW" : "unchanged");
+		rv = usb_translate_errors(rv);
 	} else {
 		dev_dbg(dev, "%s - DTR %s, RTS %s\n", __func__,
 			(set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged",
@@ -1682,7 +1687,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
 
 	kref_init(&priv->kref);
 	mutex_init(&priv->cfg_lock);
-	memset(&priv->icount, 0x00, sizeof(priv->icount));
 	init_waitqueue_head(&priv->delta_msr_wait);
 
 	priv->flags = ASYNC_LOW_LATENCY;
@@ -1691,7 +1695,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
 	if (quirk && quirk->port_probe)
 		quirk->port_probe(priv);
 
-	priv->port = port;
 	usb_set_serial_port_data(port, priv);
 
 	ftdi_determine_type(port);
@@ -1781,7 +1784,7 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial)
 	struct usb_device *udev = serial->dev;
 
 	if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ||
-	    (udev->product && !strcmp(udev->product, "BeagleBone/XDS100")))
+	    (udev->product && !strcmp(udev->product, "BeagleBone/XDS100V2")))
 		return ftdi_jtag_probe(serial);
 
 	return 0;
@@ -2089,6 +2092,29 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
 
 }
 
+static int ftdi_chars_in_buffer(struct tty_struct *tty)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	int chars;
+	unsigned char buf[2];
+	int ret;
+
+	chars = usb_serial_generic_chars_in_buffer(tty);
+	if (chars)
+		goto out;
+
+	/* Check if hardware buffer is empty. */
+	ret = ftdi_get_modem_status(tty, buf);
+	if (ret == 2) {
+		if (!(buf[1] & FTDI_RS_TEMT))
+			chars = 1;
+	}
+out:
+	dev_dbg(&port->dev, "%s - %d\n", __func__, chars);
+
+	return chars;
+}
+
 /* old_termios contains the original termios settings and tty->termios contains
  * the new setting to be used
  * WARNING: set_termios calls this with old_termios in kernel space
@@ -2272,7 +2298,14 @@ no_c_cflag_changes:
 	}
 }
 
-static int ftdi_tiocmget(struct tty_struct *tty)
+/*
+ * Get modem-control status.
+ *
+ * Returns the number of status bytes retrieved (device dependant), or
+ * negative error code.
+ */
+static int ftdi_get_modem_status(struct tty_struct *tty,
+						unsigned char status[2])
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -2312,16 +2345,43 @@ static int ftdi_tiocmget(struct tty_struct *tty)
 			FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
 			0, priv->interface,
 			buf, len, WDR_TIMEOUT);
-	if (ret < 0)
+	if (ret < 0) {
+		dev_err(&port->dev, "failed to get modem status: %d\n", ret);
+		ret = usb_translate_errors(ret);
 		goto out;
+	}
 
-	ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
-		(buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
-		(buf[0]  & FTDI_SIO_RI_MASK  ? TIOCM_RI  : 0) |
-		(buf[0]  & FTDI_SIO_RLSD_MASK ? TIOCM_CD  : 0) |
-		priv->last_dtr_rts;
+	status[0] = buf[0];
+	if (ret > 1)
+		status[1] = buf[1];
+	else
+		status[1] = 0;
+
+	dev_dbg(&port->dev, "%s - 0x%02x%02x\n", __func__, status[0],
+								status[1]);
 out:
 	kfree(buf);
+
+	return ret;
+}
+
+static int ftdi_tiocmget(struct tty_struct *tty)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
+	unsigned char buf[2];
+	int ret;
+
+	ret = ftdi_get_modem_status(tty, buf);
+	if (ret < 0)
+		return ret;
+
+	ret =	(buf[0] & FTDI_SIO_DSR_MASK  ? TIOCM_DSR : 0) |
+		(buf[0] & FTDI_SIO_CTS_MASK  ? TIOCM_CTS : 0) |
+		(buf[0] & FTDI_SIO_RI_MASK   ? TIOCM_RI  : 0) |
+		(buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD  : 0) |
+		priv->last_dtr_rts;
+
 	return ret;
 }
 
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 57c12ef..049b6e7 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -752,6 +752,12 @@
 #define TTI_VID			0x103E	/* Vendor Id */
 #define TTI_QL355P_PID		0x03E8	/* TTi QL355P power supply */
 
+/*
+ * Newport Cooperation (www.newport.com)
+ */
+#define NEWPORT_VID			0x104D
+#define NEWPORT_AGILIS_PID		0x3000
+
 /* Interbiometrics USB I/O Board */
 /* Developed for Interbiometrics by Rudolf Gugler */
 #define INTERBIOMETRICS_VID              0x1209
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 2966121..2ea70a6 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -262,6 +262,7 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
 	dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
 	return chars;
 }
+EXPORT_SYMBOL_GPL(usb_serial_generic_chars_in_buffer);
 
 static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,
 						int index, gfp_t mem_flags)
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index 0bbaf21..2cba60d 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -20,10 +20,6 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.00"
 #define DRIVER_DESC "HP4x (48/49) Generic Serial driver"
 
 #define HP_VENDOR_ID 0x03f0
@@ -52,5 +48,4 @@ static struct usb_serial_driver * const serial_drivers[] = {
 module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 5acc0d1..7b770c7 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -51,10 +51,6 @@
 #include "io_ionsp.h"		/* info for the iosp messages */
 #include "io_16654.h"		/* 16654 UART defines */
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v2.7"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
 #define DRIVER_DESC "Edgeport USB Serial Driver"
 
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 60023c2..58184f3 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -40,10 +40,6 @@
 #include "io_usbvend.h"
 #include "io_ti.h"
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.7mode043006"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
 #define DRIVER_DESC "Edgeport USB Serial Driver"
 
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 1068bf2..76c9a84 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -25,11 +25,6 @@
 
 #define KP_RETRIES	100
 
-/*
- * Version Information
- */
-
-#define DRIVER_VERSION "v1.0"
 #define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>"
 #define DRIVER_DESC "USB PocketPC PDA driver"
 
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 4264821..155eab1 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -49,10 +49,6 @@
 #include <linux/uaccess.h>
 #include "usb-wwan.h"
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION	"v0.4"
 #define DRIVER_AUTHOR	"Roelf Diedericks"
 #define DRIVER_DESC	"IPWireless tty driver"
 
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index cd5533e..1e1fbed 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -32,10 +32,6 @@
 #include "iuu_phoenix.h"
 #include <linux/random.h>
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.12"
 #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver"
 
 static const struct usb_device_id id_table[] = {
@@ -1164,7 +1160,7 @@ static ssize_t store_vcc_mode(struct device *dev,
 	struct iuu_private *priv = usb_get_serial_port_data(port);
 	unsigned long v;
 
-	if (strict_strtoul(buf, 10, &v)) {
+	if (kstrtoul(buf, 10, &v)) {
 		dev_err(dev, "%s - vcc_mode: %s is not a unsigned long\n",
 				__func__, buf);
 		goto fail_store_vcc_mode;
@@ -1232,8 +1228,6 @@ MODULE_AUTHOR("Alain Degreffe eczema@ecze.com");
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-MODULE_VERSION(DRIVER_VERSION);
-
 module_param(xmas, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(xmas, "Xmas colors enabled or not");
 
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index cff8dd5..97bc49f 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -44,10 +44,6 @@
 #include <linux/usb/ezusb.h>
 #include "keyspan.h"
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.1.5"
 #define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
 #define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
 
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index bb87e29..41b0109 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -42,10 +42,6 @@
 	#undef XIRCOM
 #endif
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.1"
 #define DRIVER_AUTHOR "Brian Warner <warner@lothar.com>"
 #define DRIVER_DESC "USB Keyspan PDA Converter driver"
 
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 1f45178..fc9e14a 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -49,10 +49,6 @@
 #include <linux/usb/serial.h>
 #include "kl5kusb105.h"
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.4"
 #define DRIVER_AUTHOR "Utz-Uwe Haus <haus@uuhaus.de>, Johan Hovold <jhovold@gmail.com>"
 #define DRIVER_DESC "KLSI KL5KUSB105 chipset USB->Serial Converter driver"
 
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index c9ca7a5..b747ba6 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -38,8 +38,6 @@
 #include <linux/ioctl.h>
 #include "kobil_sct.h"
 
-/* Version Information */
-#define DRIVER_VERSION "21/05/2004"
 #define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com"
 #define DRIVER_DESC "KOBIL USB Smart Card Terminal Driver (experimental)"
 
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 8a20810..b691175 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -38,10 +38,6 @@
 #include <linux/ioctl.h>
 #include "mct_u232.h"
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "z2.1"		/* Linux in-kernel version */
 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
 #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
 
diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c
index 6f29c74..3d25844 100644
--- a/drivers/usb/serial/metro-usb.c
+++ b/drivers/usb/serial/metro-usb.c
@@ -20,8 +20,6 @@
 #include <linux/uaccess.h>
 #include <linux/usb/serial.h>
 
-/* Version Information */
-#define DRIVER_VERSION "v1.2.0.0"
 #define DRIVER_DESC "Metrologic Instruments Inc. - USB-POS driver"
 
 /* Product information. */
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 7526742..f57a6b1 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -36,10 +36,6 @@
 #include <linux/uaccess.h>
 #include <linux/parport.h>
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "2.1"
 #define DRIVER_AUTHOR "Aspire Communications pvt Ltd."
 #define DRIVER_DESC "Moschip USB Serial Driver"
 
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 1cf3375..66d9e08 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -35,10 +35,6 @@
 #include <linux/usb/serial.h>
 #include <linux/uaccess.h>
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "1.3.2"
 #define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver"
 
 /*
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 9ab73d2..7818af9 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -23,10 +23,6 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.1"
 #define DRIVER_AUTHOR "Alessandro Zummo"
 #define DRIVER_DESC "USB ZyXEL omni.net LCD PLUS Driver"
 
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index 6aba731..c6bfb83 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -1,6 +1,7 @@
 /*
  * Opticon USB barcode to serial driver
  *
+ * Copyright (C) 2011 - 2012 Johan Hovold <jhovold@gmail.com>
  * Copyright (C) 2011 Martin Jansen <martin.jansen@opticon.com>
  * Copyright (C) 2008 - 2009 Greg Kroah-Hartman <gregkh@suse.de>
  * Copyright (C) 2008 - 2009 Novell Inc.
@@ -40,114 +41,70 @@ MODULE_DEVICE_TABLE(usb, id_table);
 
 /* This structure holds all of the individual device information */
 struct opticon_private {
-	struct usb_device *udev;
-	struct usb_serial *serial;
-	struct usb_serial_port *port;
-	unsigned char *bulk_in_buffer;
-	struct urb *bulk_read_urb;
-	int buffer_size;
-	u8 bulk_address;
 	spinlock_t lock;	/* protects the following flags */
-	bool throttled;
-	bool actually_throttled;
 	bool rts;
 	bool cts;
 	int outstanding_urbs;
 };
 
 
-
-static void opticon_read_bulk_callback(struct urb *urb)
+static void opticon_process_data_packet(struct usb_serial_port *port,
+					const unsigned char *buf, size_t len)
 {
-	struct opticon_private *priv = urb->context;
-	unsigned char *data = urb->transfer_buffer;
-	struct usb_serial_port *port = priv->port;
-	int status = urb->status;
 	struct tty_struct *tty;
-	int result;
-	int data_length;
+
+	tty = tty_port_tty_get(&port->port);
+	if (!tty)
+		return;
+
+	tty_insert_flip_string(tty, buf, len);
+	tty_flip_buffer_push(tty);
+	tty_kref_put(tty);
+}
+
+static void opticon_process_status_packet(struct usb_serial_port *port,
+					const unsigned char *buf, size_t len)
+{
+	struct opticon_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 
-	switch (status) {
-	case 0:
-		/* success */
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* this urb is terminated, clean up */
-		dev_dbg(&priv->udev->dev, "%s - urb shutting down with status: %d\n",
-			__func__, status);
+	spin_lock_irqsave(&priv->lock, flags);
+	if (buf[0] == 0x00)
+		priv->cts = false;
+	else
+		priv->cts = true;
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void opticon_process_read_urb(struct urb *urb)
+{
+	struct usb_serial_port *port = urb->context;
+	const unsigned char *hdr = urb->transfer_buffer;
+	const unsigned char *data = hdr + 2;
+	size_t data_len = urb->actual_length - 2;
+
+	if (urb->actual_length <= 2) {
+		dev_dbg(&port->dev, "malformed packet received: %d bytes\n",
+							urb->actual_length);
 		return;
-	default:
-		dev_dbg(&priv->udev->dev, "%s - nonzero urb status received: %d\n",
-			__func__, status);
-		goto exit;
 	}
-
-	usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
-
-	if (urb->actual_length > 2) {
-		data_length = urb->actual_length - 2;
-
-		/*
-		 * Data from the device comes with a 2 byte header:
-		 *
-		 * <0x00><0x00>data...
-		 *	This is real data to be sent to the tty layer
-		 * <0x00><0x01)level
-		 *	This is a CTS level change, the third byte is the CTS
-		 *	value (0 for low, 1 for high).
-		 */
-		if ((data[0] == 0x00) && (data[1] == 0x00)) {
-			/* real data, send it to the tty layer */
-			tty = tty_port_tty_get(&port->port);
-			if (tty) {
-				tty_insert_flip_string(tty, data + 2,
-						       data_length);
-				tty_flip_buffer_push(tty);
-				tty_kref_put(tty);
-			}
-		} else {
-			if ((data[0] == 0x00) && (data[1] == 0x01)) {
-				spin_lock_irqsave(&priv->lock, flags);
-				/* CTS status information package */
-				if (data[2] == 0x00)
-					priv->cts = false;
-				else
-					priv->cts = true;
-				spin_unlock_irqrestore(&priv->lock, flags);
-			} else {
-				dev_dbg(&priv->udev->dev,
-					"Unknown data packet received from the device:"
-					" %2x %2x\n",
-					data[0], data[1]);
-			}
-		}
+	/*
+	 * Data from the device comes with a 2 byte header:
+	 *
+	 * <0x00><0x00>data...
+	 *      This is real data to be sent to the tty layer
+	 * <0x00><0x01>level
+	 *      This is a CTS level change, the third byte is the CTS
+	 *      value (0 for low, 1 for high).
+	 */
+	if ((hdr[0] == 0x00) && (hdr[1] == 0x00)) {
+		opticon_process_data_packet(port, data, data_len);
+	} else if ((hdr[0] == 0x00) && (hdr[1] == 0x01)) {
+		opticon_process_status_packet(port, data, data_len);
 	} else {
-		dev_dbg(&priv->udev->dev,
-			"Improper amount of data received from the device, "
-			"%d bytes", urb->actual_length);
+		dev_dbg(&port->dev, "unknown packet received: %02x %02x\n",
+							hdr[0], hdr[1]);
 	}
-
-exit:
-	spin_lock(&priv->lock);
-
-	/* Continue trying to always read if we should */
-	if (!priv->throttled) {
-		usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev,
-				  usb_rcvbulkpipe(priv->udev,
-						  priv->bulk_address),
-				  priv->bulk_in_buffer, priv->buffer_size,
-				  opticon_read_bulk_callback, priv);
-		result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC);
-		if (result)
-			dev_err(&port->dev,
-			    "%s - failed resubmitting read urb, error %d\n",
-							__func__, result);
-	} else
-		priv->actually_throttled = true;
-	spin_unlock(&priv->lock);
 }
 
 static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
@@ -175,52 +132,35 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
 
 static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
-	struct opticon_private *priv = usb_get_serial_data(port->serial);
+	struct opticon_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
-	int result = 0;
+	int res;
 
 	spin_lock_irqsave(&priv->lock, flags);
-	priv->throttled = false;
-	priv->actually_throttled = false;
-	priv->port = port;
 	priv->rts = false;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* Clear RTS line */
 	send_control_msg(port, CONTROL_RTS, 0);
 
-	/* Setup the read URB and start reading from the device */
-	usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev,
-			  usb_rcvbulkpipe(priv->udev,
-					  priv->bulk_address),
-			  priv->bulk_in_buffer, priv->buffer_size,
-			  opticon_read_bulk_callback, priv);
-
 	/* clear the halt status of the enpoint */
-	usb_clear_halt(priv->udev, priv->bulk_read_urb->pipe);
+	usb_clear_halt(port->serial->dev, port->read_urb->pipe);
+
+	res = usb_serial_generic_open(tty, port);
+	if (!res)
+		return res;
 
-	result = usb_submit_urb(priv->bulk_read_urb, GFP_KERNEL);
-	if (result)
-		dev_err(&port->dev,
-			"%s - failed resubmitting read urb, error %d\n",
-			__func__, result);
 	/* Request CTS line state, sometimes during opening the current
 	 * CTS state can be missed. */
 	send_control_msg(port, RESEND_CTS_STATE, 1);
-	return result;
-}
-
-static void opticon_close(struct usb_serial_port *port)
-{
-	struct opticon_private *priv = usb_get_serial_data(port->serial);
 
-	/* shutdown our urbs */
-	usb_kill_urb(priv->bulk_read_urb);
+	return res;
 }
 
 static void opticon_write_control_callback(struct urb *urb)
 {
-	struct opticon_private *priv = urb->context;
+	struct usb_serial_port *port = urb->context;
+	struct opticon_private *priv = usb_get_serial_port_data(port);
 	int status = urb->status;
 	unsigned long flags;
 
@@ -231,20 +171,21 @@ static void opticon_write_control_callback(struct urb *urb)
 	kfree(urb->setup_packet);
 
 	if (status)
-		dev_dbg(&priv->udev->dev, "%s - nonzero write bulk status received: %d\n",
+		dev_dbg(&port->dev,
+			"%s - non-zero urb status received: %d\n",
 			__func__, status);
 
 	spin_lock_irqsave(&priv->lock, flags);
 	--priv->outstanding_urbs;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	usb_serial_port_softint(priv->port);
+	usb_serial_port_softint(port);
 }
 
 static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
 			 const unsigned char *buf, int count)
 {
-	struct opticon_private *priv = usb_get_serial_data(port->serial);
+	struct opticon_private *priv = usb_get_serial_port_data(port);
 	struct usb_serial *serial = port->serial;
 	struct urb *urb;
 	unsigned char *buffer;
@@ -298,7 +239,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
 	usb_fill_control_urb(urb, serial->dev,
 		usb_sndctrlpipe(serial->dev, 0),
 		(unsigned char *)dr, buffer, count,
-		opticon_write_control_callback, priv);
+		opticon_write_control_callback, port);
 
 	/* send it down the pipe */
 	status = usb_submit_urb(urb, GFP_ATOMIC);
@@ -331,7 +272,7 @@ error_no_buffer:
 static int opticon_write_room(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
-	struct opticon_private *priv = usb_get_serial_data(port->serial);
+	struct opticon_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 
 	/*
@@ -350,44 +291,10 @@ static int opticon_write_room(struct tty_struct *tty)
 	return 2048;
 }
 
-static void opticon_throttle(struct tty_struct *tty)
-{
-	struct usb_serial_port *port = tty->driver_data;
-	struct opticon_private *priv = usb_get_serial_data(port->serial);
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	priv->throttled = true;
-	spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-
-static void opticon_unthrottle(struct tty_struct *tty)
-{
-	struct usb_serial_port *port = tty->driver_data;
-	struct opticon_private *priv = usb_get_serial_data(port->serial);
-	unsigned long flags;
-	int result, was_throttled;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	priv->throttled = false;
-	was_throttled = priv->actually_throttled;
-	priv->actually_throttled = false;
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	if (was_throttled) {
-		result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC);
-		if (result)
-			dev_err(&port->dev,
-				"%s - failed submitting read urb, error %d\n",
-							__func__, result);
-	}
-}
-
 static int opticon_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
-	struct opticon_private *priv = usb_get_serial_data(port->serial);
+	struct opticon_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	int result = 0;
 
@@ -407,7 +314,7 @@ static int opticon_tiocmset(struct tty_struct *tty,
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = port->serial;
-	struct opticon_private *priv = usb_get_serial_data(port->serial);
+	struct opticon_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	bool rts;
 	bool changed = false;
@@ -438,7 +345,7 @@ static int opticon_tiocmset(struct tty_struct *tty,
 	return ret;
 }
 
-static int get_serial_info(struct opticon_private *priv,
+static int get_serial_info(struct usb_serial_port *port,
 			   struct serial_struct __user *serial)
 {
 	struct serial_struct tmp;
@@ -450,7 +357,7 @@ static int get_serial_info(struct opticon_private *priv,
 
 	/* fake emulate a 16550 uart to make userspace code happy */
 	tmp.type		= PORT_16550A;
-	tmp.line		= priv->serial->minor;
+	tmp.line		= port->serial->minor;
 	tmp.port		= 0;
 	tmp.irq			= 0;
 	tmp.flags		= ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
@@ -468,13 +375,12 @@ static int opticon_ioctl(struct tty_struct *tty,
 			 unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
-	struct opticon_private *priv = usb_get_serial_data(port->serial);
 
 	dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd);
 
 	switch (cmd) {
 	case TIOCGSERIAL:
-		return get_serial_info(priv,
+		return get_serial_info(port,
 				       (struct serial_struct __user *)arg);
 	}
 
@@ -483,106 +389,36 @@ static int opticon_ioctl(struct tty_struct *tty,
 
 static int opticon_startup(struct usb_serial *serial)
 {
-	struct opticon_private *priv;
-	struct usb_host_interface *intf;
-	int i;
-	int retval = -ENOMEM;
-	bool bulk_in_found = false;
-
-	/* create our private serial structure */
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (priv == NULL) {
-		dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
-		return -ENOMEM;
-	}
-	spin_lock_init(&priv->lock);
-	priv->serial = serial;
-	priv->port = serial->port[0];
-	priv->udev = serial->dev;
-	priv->outstanding_urbs = 0;	/* Init the outstanding urbs */
-
-	/* find our bulk endpoint */
-	intf = serial->interface->altsetting;
-	for (i = 0; i < intf->desc.bNumEndpoints; ++i) {
-		struct usb_endpoint_descriptor *endpoint;
-
-		endpoint = &intf->endpoint[i].desc;
-		if (!usb_endpoint_is_bulk_in(endpoint))
-			continue;
-
-		priv->bulk_read_urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!priv->bulk_read_urb) {
-			dev_err(&priv->udev->dev, "out of memory\n");
-			goto error;
-		}
-
-		priv->buffer_size = usb_endpoint_maxp(endpoint) * 2;
-		priv->bulk_in_buffer = kmalloc(priv->buffer_size, GFP_KERNEL);
-		if (!priv->bulk_in_buffer) {
-			dev_err(&priv->udev->dev, "out of memory\n");
-			goto error;
-		}
-
-		priv->bulk_address = endpoint->bEndpointAddress;
-
-		bulk_in_found = true;
-		break;
-		}
-
-	if (!bulk_in_found) {
-		dev_err(&priv->udev->dev,
-			"Error - the proper endpoints were not found!\n");
-		goto error;
+	if (!serial->num_bulk_in) {
+		dev_err(&serial->dev->dev, "no bulk in endpoint\n");
+		return -ENODEV;
 	}
 
-	usb_set_serial_data(serial, priv);
 	return 0;
-
-error:
-	usb_free_urb(priv->bulk_read_urb);
-	kfree(priv->bulk_in_buffer);
-	kfree(priv);
-	return retval;
 }
 
-static void opticon_disconnect(struct usb_serial *serial)
+static int opticon_port_probe(struct usb_serial_port *port)
 {
-	struct opticon_private *priv = usb_get_serial_data(serial);
-
-	usb_kill_urb(priv->bulk_read_urb);
-	usb_free_urb(priv->bulk_read_urb);
-}
+	struct opticon_private *priv;
 
-static void opticon_release(struct usb_serial *serial)
-{
-	struct opticon_private *priv = usb_get_serial_data(serial);
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
 
-	kfree(priv->bulk_in_buffer);
-	kfree(priv);
-}
+	spin_lock_init(&priv->lock);
 
-static int opticon_suspend(struct usb_serial *serial, pm_message_t message)
-{
-	struct opticon_private *priv = usb_get_serial_data(serial);
+	usb_set_serial_port_data(port, priv);
 
-	usb_kill_urb(priv->bulk_read_urb);
 	return 0;
 }
 
-static int opticon_resume(struct usb_serial *serial)
+static int opticon_port_remove(struct usb_serial_port *port)
 {
-	struct opticon_private *priv = usb_get_serial_data(serial);
-	struct usb_serial_port *port = serial->port[0];
-	int result;
-
-	mutex_lock(&port->port.mutex);
-	/* This is protected by the port mutex against close/open */
-	if (test_bit(ASYNCB_INITIALIZED, &port->port.flags))
-		result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO);
-	else
-		result = 0;
-	mutex_unlock(&port->port.mutex);
-	return result;
+	struct opticon_private *priv = usb_get_serial_port_data(port);
+
+	kfree(priv);
+
+	return 0;
 }
 
 static struct usb_serial_driver opticon_device = {
@@ -592,20 +428,19 @@ static struct usb_serial_driver opticon_device = {
 	},
 	.id_table =		id_table,
 	.num_ports =		1,
+	.bulk_in_size =		256,
 	.attach =		opticon_startup,
+	.port_probe =		opticon_port_probe,
+	.port_remove =		opticon_port_remove,
 	.open =			opticon_open,
-	.close =		opticon_close,
 	.write =		opticon_write,
 	.write_room = 		opticon_write_room,
-	.disconnect =		opticon_disconnect,
-	.release =		opticon_release,
-	.throttle = 		opticon_throttle,
-	.unthrottle =		opticon_unthrottle,
+	.throttle =		usb_serial_generic_throttle,
+	.unthrottle =		usb_serial_generic_unthrottle,
 	.ioctl =		opticon_ioctl,
 	.tiocmget =		opticon_tiocmget,
 	.tiocmset =		opticon_tiocmset,
-	.suspend = 		opticon_suspend,
-	.resume =		opticon_resume,
+	.process_read_urb =	opticon_process_read_urb,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index edc64bb..e6f87b7 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -28,7 +28,6 @@
   device features.
 */
 
-#define DRIVER_VERSION "v0.7.2"
 #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
 #define DRIVER_DESC "USB Driver for GSM modems"
 
@@ -81,6 +80,7 @@ static void option_instat_callback(struct urb *urb);
 #define OPTION_PRODUCT_GTM380_MODEM		0x7201
 
 #define HUAWEI_VENDOR_ID			0x12D1
+#define HUAWEI_PRODUCT_E173			0x140C
 #define HUAWEI_PRODUCT_K4505			0x1464
 #define HUAWEI_PRODUCT_K3765			0x1465
 #define HUAWEI_PRODUCT_K4605			0x14C6
@@ -553,6 +553,8 @@ static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) },
 	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) },
 	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t) &net_intf1_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff),
 		.driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff),
@@ -741,23 +743,23 @@ static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
 	{ USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
 	{ USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1005) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1006) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1007) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1008) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1009) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100A) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100B) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100C) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100D) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100E) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100F) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1010) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1011) },
-	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1005, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1006, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1007, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1008, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1009, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100A, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100B, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100C, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100D, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100E, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100F, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1010, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1011, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012, 0xff) },
 	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
 	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
 	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
@@ -884,6 +886,10 @@ static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff),
 		.driver_info = (kernel_ulong_t)&net_intf5_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0135, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0136, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0137, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0139, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0144, 0xff, 0xff, 0xff) },
@@ -904,20 +910,34 @@ static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0189, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0196, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0197, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0199, 0xff, 0xff, 0xff), /* ZTE MF820S */
 	  .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0200, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0201, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0254, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */
 	  .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff),
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0330, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0395, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0414, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0417, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff),
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff),
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff),
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1021, 0xff, 0xff, 0xff),
 	  .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) },
@@ -1097,6 +1117,10 @@ static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1301, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1302, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1303, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1333, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff),
 		.driver_info = (kernel_ulong_t)&net_intf2_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff),
@@ -1174,22 +1198,22 @@ static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
 	{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
 	/* Pirelli  */
-	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1)},
-	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2)},
-	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1004)},
-	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1005)},
-	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1006)},
-	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1007)},
-	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1008)},
-	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1009)},
-	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100A)},
-	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100B) },
-	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100C) },
-	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100D) },
-	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100E) },
-	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F) },
-	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)},
-	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)},
+	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1004, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1005, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1006, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1007, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1008, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1009, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100A, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100B, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100C, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100D, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100E, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011, 0xff) },
+	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012, 0xff) },
 	/* Cinterion */
 	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },
 	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
@@ -1350,20 +1374,10 @@ static int option_probe(struct usb_serial *serial,
 				&serial->interface->cur_altsetting->desc;
 	struct usb_device_descriptor *dev_desc = &serial->dev->descriptor;
 
-	/*
-	 * D-Link DWM 652 still exposes CD-Rom emulation interface in modem
-	 * mode.
-	 */
-	if (dev_desc->idVendor == DLINK_VENDOR_ID &&
-		dev_desc->idProduct == DLINK_PRODUCT_DWM_652 &&
-		iface_desc->bInterfaceClass == 0x08)
+	/* Never bind to the CD-Rom emulation interface	*/
+	if (iface_desc->bInterfaceClass == 0x08)
 		return -ENODEV;
 
-	/* Bandrich modem and AT command interface is 0xff */
-	if ((dev_desc->idVendor == BANDRICH_VENDOR_ID ||
-		dev_desc->idVendor == PIRELLI_VENDOR_ID) &&
-		iface_desc->bInterfaceClass != 0xff)
-		return -ENODEV;
 	/*
 	 * Don't bind reserved interfaces (like network ones) which often have
 	 * the same class/subclass/protocol as the serial interfaces.  Look at
@@ -1378,9 +1392,9 @@ static int option_probe(struct usb_serial *serial,
 	 * Don't bind network interface on Samsung GT-B3730, it is handled by
 	 * a separate module.
 	 */
-	if (dev_desc->idVendor == SAMSUNG_VENDOR_ID &&
-		dev_desc->idProduct == SAMSUNG_PRODUCT_GT_B3730 &&
-		iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
+	if (dev_desc->idVendor == cpu_to_le16(SAMSUNG_VENDOR_ID) &&
+	    dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) &&
+	    iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
 		return -ENODEV;
 
 	/* Store device id so we can use it during attach. */
@@ -1518,5 +1532,4 @@ static int option_send_setup(struct usb_serial_port *port)
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index cee9a52..d217fd6 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -57,7 +57,6 @@
 #define OTI6858_DESCRIPTION \
 	"Ours Technology Inc. OTi-6858 USB to serial adapter driver"
 #define OTI6858_AUTHOR "Tomasz Michal Lukaszewski <FIXME@FIXME>"
-#define OTI6858_VERSION "0.2"
 
 static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(OTI6858_VENDOR_ID, OTI6858_PRODUCT_ID) },
@@ -899,5 +898,4 @@ module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_DESCRIPTION(OTI6858_DESCRIPTION);
 MODULE_AUTHOR(OTI6858_AUTHOR);
-MODULE_VERSION(OTI6858_VERSION);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
index ffcfc96..d152be9 100644
--- a/drivers/usb/serial/quatech2.c
+++ b/drivers/usb/serial/quatech2.c
@@ -65,8 +65,6 @@
 #define QT2_WRITE_BUFFER_SIZE   512  /* size of write buffer */
 #define QT2_WRITE_CONTROL_SIZE  5    /* control bytes used for a write */
 
-/* Version Information */
-#define DRIVER_VERSION "v0.1"
 #define DRIVER_DESC "Quatech 2nd gen USB to Serial Driver"
 
 #define	USB_VENDOR_ID_QUATECH	0x061d
diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c
index e4a1787..a76b1ae5 100644
--- a/drivers/usb/serial/siemens_mpi.c
+++ b/drivers/usb/serial/siemens_mpi.c
@@ -16,8 +16,6 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
-/* Version Information */
-#define DRIVER_VERSION "Version 0.1 09/26/2005"
 #define DRIVER_AUTHOR "Thomas Hergenhahn@web.de http://libnodave.sf.net"
 #define DRIVER_DESC "Driver for Siemens USB/MPI adapter"
 
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 270860f..af06f2f 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -18,7 +18,7 @@
 */
 /* Uncomment to log function calls */
 /* #define DEBUG */
-#define DRIVER_VERSION "v.1.7.16"
+
 #define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer"
 #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
 
@@ -1078,7 +1078,6 @@ module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
 module_param(nmea, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 769c137..a42536a 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -28,9 +28,6 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
-
-/* Version Information */
-#define DRIVER_VERSION	"v0.10"
 #define DRIVER_DESC 	"SPCP8x5 USB to serial adaptor driver"
 
 #define SPCP8x5_007_VID		0x04FC
@@ -651,5 +648,4 @@ static struct usb_serial_driver * const serial_drivers[] = {
 module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index 868d1e6..4543ea3 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -46,8 +46,6 @@
 #define FULLPWRBIT          0x00000080
 #define NEXT_BOARD_POWER_BIT        0x00000004
 
-/* Version Information */
-#define DRIVER_VERSION "v0.1"
 #define DRIVER_DESC "Quatech SSU-100 USB to Serial Driver"
 
 #define	USB_VENDOR_ID_QUATECH	0x061d	/* Quatech VID */
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 73b8e05..64bda13 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -597,6 +597,7 @@ static void port_release(struct device *dev)
 	kfifo_free(&port->write_fifo);
 	kfree(port->interrupt_in_buffer);
 	kfree(port->interrupt_out_buffer);
+	tty_port_destroy(&port->port);
 	kfree(port);
 }
 
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index a3e9c09..01c94aa 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -19,7 +19,6 @@
   - controlling the baud rate doesn't make sense
 */
 
-#define DRIVER_VERSION "v0.7.2"
 #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
 #define DRIVER_DESC "USB Driver for GSM modems"
 
@@ -710,5 +709,4 @@ EXPORT_SYMBOL(usb_wwan_resume);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/vivopay-serial.c b/drivers/usb/serial/vivopay-serial.c
index 0c0aa87..6299526 100644
--- a/drivers/usb/serial/vivopay-serial.c
+++ b/drivers/usb/serial/vivopay-serial.c
@@ -10,8 +10,6 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
-
-#define DRIVER_VERSION "v1.0"
 #define DRIVER_DESC "ViVOpay USB Serial Driver"
 
 #define VIVOPAY_VENDOR_ID 0x1d5f
@@ -42,5 +40,4 @@ module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR("Forest Bond <forest.bond@outpostembedded.com>");
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 0ae7bb6..eab04a6 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -203,7 +203,7 @@ config USB_STORAGE_ENE_UB6250
 
 config USB_UAS
 	tristate "USB Attached SCSI"
-	depends on USB && SCSI
+	depends on USB && SCSI && BROKEN
 	help
 	  The USB Attached SCSI protocol is supported by some USB
 	  storage devices.  It permits higher performance by supporting
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
index d36446d..6c3586a 100644
--- a/drivers/usb/storage/realtek_cr.c
+++ b/drivers/usb/storage/realtek_cr.c
@@ -455,7 +455,7 @@ static int rts51x_check_status(struct us_data *us, u8 lun)
 	u8 buf[16];
 
 	retval = rts51x_read_status(us, lun, buf, 16, &(chip->status_len));
-	if (retval < 0)
+	if (retval != STATUS_SUCCESS)
 		return -EIO;
 
 	US_DEBUGP("chip->status_len = %d\n", chip->status_len);
@@ -883,7 +883,7 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
 		} else {
 			US_DEBUGP("%s: NOT working scsi, not SS\n", __func__);
 			chip->proto_handler_backup(srb, us);
-			/* Check wether card is plugged in */
+			/* Check whether card is plugged in */
 			if (srb->cmnd[0] == TEST_UNIT_READY) {
 				if (srb->result == SAM_STAT_GOOD) {
 					SET_LUN_READY(chip, srb->device->lun);
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 12aa726..31b3e1a 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -925,7 +925,6 @@ int usb_stor_probe1(struct us_data **pus,
 	host->max_cmd_len = 16;
 	host->sg_tablesize = usb_stor_sg_tablesize(intf);
 	*pus = us = host_to_us(host);
-	memset(us, 0, sizeof(struct us_data));
 	mutex_init(&(us->dev_mutex));
 	us_set_lock_class(&us->dev_mutex, intf);
 	init_completion(&us->cmnd_ready);
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 0616f23..ce31017 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -105,20 +105,15 @@ static int skel_open(struct inode *inode, struct file *file)
 		goto exit;
 	}
 
-	/* increment our usage count for the device */
-	kref_get(&dev->kref);
-
-	/* lock the device to allow correctly handling errors
-	 * in resumption */
-	mutex_lock(&dev->io_mutex);
-
 	retval = usb_autopm_get_interface(interface);
 	if (retval)
-		goto out_err;
+		goto exit;
+
+	/* increment our usage count for the device */
+	kref_get(&dev->kref);
 
 	/* save our object in the file's private structure */
 	file->private_data = dev;
-	mutex_unlock(&dev->io_mutex);
 
 exit:
 	return retval;
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c
index 231009a..1d36531 100644
--- a/drivers/usb/wusbcore/devconnect.c
+++ b/drivers/usb/wusbcore/devconnect.c
@@ -847,19 +847,6 @@ static void wusb_dev_bos_rm(struct wusb_dev *wusb_dev)
 	wusb_dev->wusb_cap_descr = NULL;
 };
 
-static struct usb_wireless_cap_descriptor wusb_cap_descr_default = {
-	.bLength = sizeof(wusb_cap_descr_default),
-	.bDescriptorType = USB_DT_DEVICE_CAPABILITY,
-	.bDevCapabilityType = USB_CAP_TYPE_WIRELESS_USB,
-
-	.bmAttributes = USB_WIRELESS_BEACON_NONE,
-	.wPHYRates = cpu_to_le16(USB_WIRELESS_PHY_53),
-	.bmTFITXPowerInfo = 0,
-	.bmFFITXPowerInfo = 0,
-	.bmBandGroup = cpu_to_le16(0x0001),	/* WUSB1.0[7.4.1] bottom */
-	.bReserved = 0
-};
-
 /*
  * USB stack's device addition Notifier Callback
  *
diff --git a/drivers/uwb/Kconfig b/drivers/uwb/Kconfig
index d100f54..2431eed 100644
--- a/drivers/uwb/Kconfig
+++ b/drivers/uwb/Kconfig
@@ -3,8 +3,7 @@
 #
 
 menuconfig UWB
-	tristate "Ultra Wideband devices (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	tristate "Ultra Wideband devices"
 	depends on PCI
 	default n
 	help
diff --git a/drivers/uwb/reset.c b/drivers/uwb/reset.c
index 7032285..8b47c9c 100644
--- a/drivers/uwb/reset.c
+++ b/drivers/uwb/reset.c
@@ -97,6 +97,7 @@ int uwb_rc_cmd_async(struct uwb_rc *rc, const char *cmd_name,
 	neh = uwb_rc_neh_add(rc, cmd, expected_type, expected_event, cb, arg);
 	if (IS_ERR(neh)) {
 		result = PTR_ERR(neh);
+		uwb_dev_unlock(&rc->uwb_dev);
 		goto out;
 	}
 
diff --git a/drivers/uwb/umc-bus.c b/drivers/uwb/umc-bus.c
index 82a84d5..5c5b3fc 100644
--- a/drivers/uwb/umc-bus.c
+++ b/drivers/uwb/umc-bus.c
@@ -63,7 +63,7 @@ int umc_controller_reset(struct umc_dev *umc)
 	struct device *parent = umc->dev.parent;
 	int ret = 0;
 
-	if (device_trylock(parent))
+	if (!device_trylock(parent))
 		return -EAGAIN;
 	ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper);
 	if (ret >= 0)
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 6c11994..b28e66c 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -43,6 +43,10 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
 	u16 cmd;
 	u8 msix_pos;
 
+	ret = pci_enable_device(pdev);
+	if (ret)
+		return ret;
+
 	vdev->reset_works = (pci_reset_function(pdev) == 0);
 	pci_save_state(pdev);
 	vdev->pci_saved_state = pci_store_saved_state(pdev);
@@ -51,8 +55,11 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
 			 __func__, dev_name(&pdev->dev));
 
 	ret = vfio_config_init(vdev);
-	if (ret)
-		goto out;
+	if (ret) {
+		pci_load_and_free_saved_state(pdev, &vdev->pci_saved_state);
+		pci_disable_device(pdev);
+		return ret;
+	}
 
 	if (likely(!nointxmask))
 		vdev->pci_2_3 = pci_intx_mask_supported(pdev);
@@ -77,24 +84,15 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
 	} else
 		vdev->msix_bar = 0xFF;
 
-	ret = pci_enable_device(pdev);
-	if (ret)
-		goto out;
-
-	return ret;
-
-out:
-	kfree(vdev->pci_saved_state);
-	vdev->pci_saved_state = NULL;
-	vfio_config_free(vdev);
-	return ret;
+	return 0;
 }
 
 static void vfio_pci_disable(struct vfio_pci_device *vdev)
 {
+	struct pci_dev *pdev = vdev->pdev;
 	int bar;
 
-	pci_disable_device(vdev->pdev);
+	pci_disable_device(pdev);
 
 	vfio_pci_set_irqs_ioctl(vdev, VFIO_IRQ_SET_DATA_NONE |
 				VFIO_IRQ_SET_ACTION_TRIGGER,
@@ -104,22 +102,40 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev)
 
 	vfio_config_free(vdev);
 
-	pci_reset_function(vdev->pdev);
-
-	if (pci_load_and_free_saved_state(vdev->pdev,
-					  &vdev->pci_saved_state) == 0)
-		pci_restore_state(vdev->pdev);
-	else
-		pr_info("%s: Couldn't reload %s saved state\n",
-			__func__, dev_name(&vdev->pdev->dev));
-
 	for (bar = PCI_STD_RESOURCES; bar <= PCI_STD_RESOURCE_END; bar++) {
 		if (!vdev->barmap[bar])
 			continue;
-		pci_iounmap(vdev->pdev, vdev->barmap[bar]);
-		pci_release_selected_regions(vdev->pdev, 1 << bar);
+		pci_iounmap(pdev, vdev->barmap[bar]);
+		pci_release_selected_regions(pdev, 1 << bar);
 		vdev->barmap[bar] = NULL;
 	}
+
+	/*
+	 * If we have saved state, restore it.  If we can reset the device,
+	 * even better.  Resetting with current state seems better than
+	 * nothing, but saving and restoring current state without reset
+	 * is just busy work.
+	 */
+	if (pci_load_and_free_saved_state(pdev, &vdev->pci_saved_state)) {
+		pr_info("%s: Couldn't reload %s saved state\n",
+			__func__, dev_name(&pdev->dev));
+
+		if (!vdev->reset_works)
+			return;
+
+		pci_save_state(pdev);
+	}
+
+	/*
+	 * Disable INTx and MSI, presumably to avoid spurious interrupts
+	 * during reset.  Stolen from pci_reset_function()
+	 */
+	pci_write_config_word(pdev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);
+
+	if (vdev->reset_works)
+		__pci_reset_function(pdev);
+
+	pci_restore_state(pdev);
 }
 
 static void vfio_pci_release(void *device_data)
@@ -327,15 +343,10 @@ static long vfio_pci_ioctl(void *device_data,
 			    hdr.count > vfio_pci_get_irq_count(vdev, hdr.index))
 				return -EINVAL;
 
-			data = kmalloc(hdr.count * size, GFP_KERNEL);
-			if (!data)
-				return -ENOMEM;
-
-			if (copy_from_user(data, (void __user *)(arg + minsz),
-					   hdr.count * size)) {
-				kfree(data);
-				return -EFAULT;
-			}
+			data = memdup_user((void __user *)(arg + minsz),
+					   hdr.count * size);
+			if (IS_ERR(data))
+				return PTR_ERR(data);
 		}
 
 		mutex_lock(&vdev->igate);
@@ -562,9 +573,9 @@ static int __init vfio_pci_init(void)
 
 	return 0;
 
-out_virqfd:
-	vfio_pci_virqfd_exit();
 out_driver:
+	vfio_pci_virqfd_exit();
+out_virqfd:
 	vfio_pci_uninit_perm_bits();
 	return ret;
 }
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 56097c6..12c264d 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -191,6 +191,17 @@ static void vfio_container_put(struct vfio_container *container)
 	kref_put(&container->kref, vfio_container_release);
 }
 
+static void vfio_group_unlock_and_free(struct vfio_group *group)
+{
+	mutex_unlock(&vfio.group_lock);
+	/*
+	 * Unregister outside of lock.  A spurious callback is harmless now
+	 * that the group is no longer in vfio.group_list.
+	 */
+	iommu_group_unregister_notifier(group->iommu_group, &group->nb);
+	kfree(group);
+}
+
 /**
  * Group objects - create, release, get, put, search
  */
@@ -229,8 +240,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
 
 	minor = vfio_alloc_group_minor(group);
 	if (minor < 0) {
-		mutex_unlock(&vfio.group_lock);
-		kfree(group);
+		vfio_group_unlock_and_free(group);
 		return ERR_PTR(minor);
 	}
 
@@ -239,8 +249,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
 		if (tmp->iommu_group == iommu_group) {
 			vfio_group_get(tmp);
 			vfio_free_group_minor(minor);
-			mutex_unlock(&vfio.group_lock);
-			kfree(group);
+			vfio_group_unlock_and_free(group);
 			return tmp;
 		}
 	}
@@ -249,8 +258,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
 			    group, "%d", iommu_group_id(iommu_group));
 	if (IS_ERR(dev)) {
 		vfio_free_group_minor(minor);
-		mutex_unlock(&vfio.group_lock);
-		kfree(group);
+		vfio_group_unlock_and_free(group);
 		return (struct vfio_group *)dev; /* ERR_PTR */
 	}
 
@@ -274,16 +282,7 @@ static void vfio_group_release(struct kref *kref)
 	device_destroy(vfio.class, MKDEV(MAJOR(vfio.devt), group->minor));
 	list_del(&group->vfio_next);
 	vfio_free_group_minor(group->minor);
-
-	mutex_unlock(&vfio.group_lock);
-
-	/*
-	 * Unregister outside of lock.  A spurious callback is harmless now
-	 * that the group is no longer in vfio.group_list.
-	 */
-	iommu_group_unregister_notifier(group->iommu_group, &group->nb);
-
-	kfree(group);
+	vfio_group_unlock_and_free(group);
 }
 
 static void vfio_group_put(struct vfio_group *group)
@@ -466,8 +465,9 @@ static int vfio_dev_viable(struct device *dev, void *data)
 {
 	struct vfio_group *group = data;
 	struct vfio_device *device;
+	struct device_driver *drv = ACCESS_ONCE(dev->driver);
 
-	if (!dev->driver || vfio_whitelisted_driver(dev->driver))
+	if (!drv || vfio_whitelisted_driver(drv))
 		return 0;
 
 	device = vfio_group_get_device(group, dev);
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 7f93f34..67898fa 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -42,6 +42,21 @@ MODULE_PARM_DESC(experimental_zcopytx, "Enable Experimental Zero Copy TX");
 #define VHOST_MAX_PEND 128
 #define VHOST_GOODCOPY_LEN 256
 
+/*
+ * For transmit, used buffer len is unused; we override it to track buffer
+ * status internally; used for zerocopy tx only.
+ */
+/* Lower device DMA failed */
+#define VHOST_DMA_FAILED_LEN	3
+/* Lower device DMA done */
+#define VHOST_DMA_DONE_LEN	2
+/* Lower device DMA in progress */
+#define VHOST_DMA_IN_PROGRESS	1
+/* Buffer unused */
+#define VHOST_DMA_CLEAR_LEN	0
+
+#define VHOST_DMA_IS_DONE(len) ((len) >= VHOST_DMA_DONE_LEN)
+
 enum {
 	VHOST_NET_VQ_RX = 0,
 	VHOST_NET_VQ_TX = 1,
@@ -62,8 +77,33 @@ struct vhost_net {
 	 * We only do this when socket buffer fills up.
 	 * Protected by tx vq lock. */
 	enum vhost_net_poll_state tx_poll_state;
+	/* Number of TX recently submitted.
+	 * Protected by tx vq lock. */
+	unsigned tx_packets;
+	/* Number of times zerocopy TX recently failed.
+	 * Protected by tx vq lock. */
+	unsigned tx_zcopy_err;
 };
 
+static void vhost_net_tx_packet(struct vhost_net *net)
+{
+	++net->tx_packets;
+	if (net->tx_packets < 1024)
+		return;
+	net->tx_packets = 0;
+	net->tx_zcopy_err = 0;
+}
+
+static void vhost_net_tx_err(struct vhost_net *net)
+{
+	++net->tx_zcopy_err;
+}
+
+static bool vhost_net_tx_select_zcopy(struct vhost_net *net)
+{
+	return net->tx_packets / 64 >= net->tx_zcopy_err;
+}
+
 static bool vhost_sock_zcopy(struct socket *sock)
 {
 	return unlikely(experimental_zcopytx) &&
@@ -126,6 +166,55 @@ static void tx_poll_start(struct vhost_net *net, struct socket *sock)
 	net->tx_poll_state = VHOST_NET_POLL_STARTED;
 }
 
+/* In case of DMA done not in order in lower device driver for some reason.
+ * upend_idx is used to track end of used idx, done_idx is used to track head
+ * of used idx. Once lower device DMA done contiguously, we will signal KVM
+ * guest used idx.
+ */
+static int vhost_zerocopy_signal_used(struct vhost_net *net,
+				      struct vhost_virtqueue *vq)
+{
+	int i;
+	int j = 0;
+
+	for (i = vq->done_idx; i != vq->upend_idx; i = (i + 1) % UIO_MAXIOV) {
+		if (vq->heads[i].len == VHOST_DMA_FAILED_LEN)
+			vhost_net_tx_err(net);
+		if (VHOST_DMA_IS_DONE(vq->heads[i].len)) {
+			vq->heads[i].len = VHOST_DMA_CLEAR_LEN;
+			vhost_add_used_and_signal(vq->dev, vq,
+						  vq->heads[i].id, 0);
+			++j;
+		} else
+			break;
+	}
+	if (j)
+		vq->done_idx = i;
+	return j;
+}
+
+static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)
+{
+	struct vhost_ubuf_ref *ubufs = ubuf->ctx;
+	struct vhost_virtqueue *vq = ubufs->vq;
+	int cnt = atomic_read(&ubufs->kref.refcount);
+
+	/*
+	 * Trigger polling thread if guest stopped submitting new buffers:
+	 * in this case, the refcount after decrement will eventually reach 1
+	 * so here it is 2.
+	 * We also trigger polling periodically after each 16 packets
+	 * (the value 16 here is more or less arbitrary, it's tuned to trigger
+	 * less than 10% of times).
+	 */
+	if (cnt <= 2 || !(cnt % 16))
+		vhost_poll_queue(&vq->poll);
+	/* set len to mark this desc buffers done DMA */
+	vq->heads[ubuf->desc].len = success ?
+		VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN;
+	vhost_ubuf_put(ubufs);
+}
+
 /* Expects to be always run from workqueue - which acts as
  * read-size critical section for our kind of RCU. */
 static void handle_tx(struct vhost_net *net)
@@ -172,7 +261,7 @@ static void handle_tx(struct vhost_net *net)
 	for (;;) {
 		/* Release DMAs done buffers first */
 		if (zcopy)
-			vhost_zerocopy_signal_used(vq);
+			vhost_zerocopy_signal_used(net, vq);
 
 		head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
 					 ARRAY_SIZE(vq->iov),
@@ -227,7 +316,8 @@ static void handle_tx(struct vhost_net *net)
 		/* use msg_control to pass vhost zerocopy ubuf info to skb */
 		if (zcopy) {
 			vq->heads[vq->upend_idx].id = head;
-			if (len < VHOST_GOODCOPY_LEN) {
+			if (!vhost_net_tx_select_zcopy(net) ||
+			    len < VHOST_GOODCOPY_LEN) {
 				/* copy don't need to wait for DMA done */
 				vq->heads[vq->upend_idx].len =
 							VHOST_DMA_DONE_LEN;
@@ -237,7 +327,8 @@ static void handle_tx(struct vhost_net *net)
 			} else {
 				struct ubuf_info *ubuf = &vq->ubuf_info[head];
 
-				vq->heads[vq->upend_idx].len = len;
+				vq->heads[vq->upend_idx].len =
+					VHOST_DMA_IN_PROGRESS;
 				ubuf->callback = vhost_zerocopy_callback;
 				ubuf->ctx = vq->ubufs;
 				ubuf->desc = vq->upend_idx;
@@ -268,8 +359,9 @@ static void handle_tx(struct vhost_net *net)
 		if (!zcopy)
 			vhost_add_used_and_signal(&net->dev, vq, head, 0);
 		else
-			vhost_zerocopy_signal_used(vq);
+			vhost_zerocopy_signal_used(net, vq);
 		total_len += len;
+		vhost_net_tx_packet(net);
 		if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
 			vhost_poll_queue(&vq->poll);
 			break;
@@ -594,9 +686,18 @@ static int vhost_net_release(struct inode *inode, struct file *f)
 	struct vhost_net *n = f->private_data;
 	struct socket *tx_sock;
 	struct socket *rx_sock;
+	int i;
 
 	vhost_net_stop(n, &tx_sock, &rx_sock);
 	vhost_net_flush(n);
+	vhost_dev_stop(&n->dev);
+	for (i = 0; i < n->dev.nvqs; ++i) {
+		/* Wait for all lower device DMAs done. */
+		if (n->dev.vqs[i].ubufs)
+			vhost_ubuf_put_and_wait(n->dev.vqs[i].ubufs);
+
+		vhost_zerocopy_signal_used(n, &n->dev.vqs[i]);
+	}
 	vhost_dev_cleanup(&n->dev, false);
 	if (tx_sock)
 		fput(tx_sock->file);
@@ -729,7 +830,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
 	if (oldubufs) {
 		vhost_ubuf_put_and_wait(oldubufs);
 		mutex_lock(&vq->mutex);
-		vhost_zerocopy_signal_used(vq);
+		vhost_zerocopy_signal_used(n, vq);
 		mutex_unlock(&vq->mutex);
 	}
 
diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c
index aa31692..98dd4c0 100644
--- a/drivers/vhost/tcm_vhost.c
+++ b/drivers/vhost/tcm_vhost.c
@@ -34,7 +34,6 @@
 #include <linux/ctype.h>
 #include <linux/compat.h>
 #include <linux/eventfd.h>
-#include <linux/vhost.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <asm/unaligned.h>
@@ -231,7 +230,7 @@ static struct se_node_acl *tcm_vhost_alloc_fabric_acl(
 
 	nacl = kzalloc(sizeof(struct tcm_vhost_nacl), GFP_KERNEL);
 	if (!nacl) {
-		pr_err("Unable to alocate struct tcm_vhost_nacl\n");
+		pr_err("Unable to allocate struct tcm_vhost_nacl\n");
 		return NULL;
 	}
 
@@ -541,10 +540,6 @@ static void tcm_vhost_submission_work(struct work_struct *work)
 
 	if (tv_cmd->tvc_sgl_count) {
 		sg_ptr = tv_cmd->tvc_sgl;
-		/*
-		 * For BIDI commands, pass in the extra READ buffer
-		 * to transport_generic_map_mem_to_cmd() below..
-		 */
 /* FIXME: Fix BIDI operation in tcm_vhost_submission_work() */
 #if 0
 		if (se_cmd->se_cmd_flags & SCF_BIDI) {
@@ -895,6 +890,7 @@ static int vhost_scsi_release(struct inode *inode, struct file *f)
 		vhost_scsi_clear_endpoint(s, &backend);
 	}
 
+	vhost_dev_stop(&s->dev);
 	vhost_dev_cleanup(&s->dev, false);
 	kfree(s);
 	return 0;
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 99ac2cb..5a3d0f1 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -26,10 +26,6 @@
 #include <linux/kthread.h>
 #include <linux/cgroup.h>
 
-#include <linux/net.h>
-#include <linux/if_packet.h>
-#include <linux/if_arp.h>
-
 #include "vhost.h"
 
 enum {
@@ -414,28 +410,16 @@ long vhost_dev_reset_owner(struct vhost_dev *dev)
 	return 0;
 }
 
-/* In case of DMA done not in order in lower device driver for some reason.
- * upend_idx is used to track end of used idx, done_idx is used to track head
- * of used idx. Once lower device DMA done contiguously, we will signal KVM
- * guest used idx.
- */
-int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq)
+void vhost_dev_stop(struct vhost_dev *dev)
 {
 	int i;
-	int j = 0;
-
-	for (i = vq->done_idx; i != vq->upend_idx; i = (i + 1) % UIO_MAXIOV) {
-		if ((vq->heads[i].len == VHOST_DMA_DONE_LEN)) {
-			vq->heads[i].len = VHOST_DMA_CLEAR_LEN;
-			vhost_add_used_and_signal(vq->dev, vq,
-						  vq->heads[i].id, 0);
-			++j;
-		} else
-			break;
+
+	for (i = 0; i < dev->nvqs; ++i) {
+		if (dev->vqs[i].kick && dev->vqs[i].handle_kick) {
+			vhost_poll_stop(&dev->vqs[i].poll);
+			vhost_poll_flush(&dev->vqs[i].poll);
+		}
 	}
-	if (j)
-		vq->done_idx = i;
-	return j;
 }
 
 /* Caller should have device mutex if and only if locked is set */
@@ -444,17 +428,6 @@ void vhost_dev_cleanup(struct vhost_dev *dev, bool locked)
 	int i;
 
 	for (i = 0; i < dev->nvqs; ++i) {
-		if (dev->vqs[i].kick && dev->vqs[i].handle_kick) {
-			vhost_poll_stop(&dev->vqs[i].poll);
-			vhost_poll_flush(&dev->vqs[i].poll);
-		}
-		/* Wait for all lower device DMAs done. */
-		if (dev->vqs[i].ubufs)
-			vhost_ubuf_put_and_wait(dev->vqs[i].ubufs);
-
-		/* Signal guest as appropriate. */
-		vhost_zerocopy_signal_used(&dev->vqs[i]);
-
 		if (dev->vqs[i].error_ctx)
 			eventfd_ctx_put(dev->vqs[i].error_ctx);
 		if (dev->vqs[i].error)
@@ -1076,7 +1049,7 @@ static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len,
 		}
 		_iov = iov + ret;
 		size = reg->memory_size - addr + reg->guest_phys_addr;
-		_iov->iov_len = min((u64)len, size);
+		_iov->iov_len = min((u64)len - s, size);
 		_iov->iov_base = (void __user *)(unsigned long)
 			(reg->userspace_addr + addr - reg->guest_phys_addr);
 		s += size;
@@ -1599,14 +1572,3 @@ void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *ubufs)
 	wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount));
 	kfree(ubufs);
 }
-
-void vhost_zerocopy_callback(struct ubuf_info *ubuf)
-{
-	struct vhost_ubuf_ref *ubufs = ubuf->ctx;
-	struct vhost_virtqueue *vq = ubufs->vq;
-
-	vhost_poll_queue(&vq->poll);
-	/* set len = 1 to mark this desc buffers done DMA */
-	vq->heads[ubuf->desc].len = VHOST_DMA_DONE_LEN;
-	kref_put(&ubufs->kref, vhost_zerocopy_done_signal);
-}
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 1125af3..5e19e3d 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -7,17 +7,11 @@
 #include <linux/mutex.h>
 #include <linux/poll.h>
 #include <linux/file.h>
-#include <linux/skbuff.h>
 #include <linux/uio.h>
 #include <linux/virtio_config.h>
 #include <linux/virtio_ring.h>
 #include <linux/atomic.h>
 
-/* This is for zerocopy, used buffer len is set to 1 when lower device DMA
- * done */
-#define VHOST_DMA_DONE_LEN	1
-#define VHOST_DMA_CLEAR_LEN	0
-
 struct vhost_device;
 
 struct vhost_work;
@@ -70,6 +64,8 @@ struct vhost_ubuf_ref *vhost_ubuf_alloc(struct vhost_virtqueue *, bool zcopy);
 void vhost_ubuf_put(struct vhost_ubuf_ref *);
 void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *);
 
+struct ubuf_info;
+
 /* The virtqueue structure describes a queue attached to a device. */
 struct vhost_virtqueue {
 	struct vhost_dev *dev;
@@ -167,6 +163,7 @@ long vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue *vqs, int nvqs);
 long vhost_dev_check_owner(struct vhost_dev *);
 long vhost_dev_reset_owner(struct vhost_dev *);
 void vhost_dev_cleanup(struct vhost_dev *, bool locked);
+void vhost_dev_stop(struct vhost_dev *);
 long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, unsigned long arg);
 int vhost_vq_access_ok(struct vhost_virtqueue *vq);
 int vhost_log_access_ok(struct vhost_dev *);
@@ -191,8 +188,6 @@ bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
 
 int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
 		    unsigned int log_num, u64 len);
-void vhost_zerocopy_callback(struct ubuf_info *);
-int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq);
 
 #define vq_err(vq, fmt, ...) do {                                  \
 		pr_debug(pr_fmt(fmt), ##__VA_ARGS__);       \
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index d08d799..50740a8 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2140,14 +2140,16 @@ config FB_UDL
 	  To compile as a module, choose M here: the module name is udlfb.
 
 config FB_IBM_GXT4500
-	tristate "Framebuffer support for IBM GXT4500P adaptor"
+	tristate "Framebuffer support for IBM GXT4000P/4500P/6000P/6500P adaptors"
 	depends on FB && PPC
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
 	---help---
-	  Say Y here to enable support for the IBM GXT4500P display
-	  adaptor, found on some IBM System P (pSeries) machines.
+	  Say Y here to enable support for the IBM GXT4000P/6000P and
+	  GXT4500P/6500P display adaptor based on Raster Engine RC1000,
+	  found on some IBM System P (pSeries) machines. This driver
+	  doesn't use Geometry Engine GT1000.
 
 config FB_PS3
 	tristate "PS3 GPU framebuffer driver"
@@ -2442,4 +2444,19 @@ config FB_SH_MOBILE_MERAM
 	  Up to 4 memory channels can be configured, allowing 4 RGB or
 	  2 YCbCr framebuffers to be configured.
 
+config FB_SSD1307
+	tristate "Solomon SSD1307 framebuffer support"
+	depends on FB && I2C
+	depends on OF
+	depends on GENERIC_GPIO
+	select FB_SYS_FOPS
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_DEFERRED_IO
+	select PWM
+	help
+	  This driver implements support for the Solomon SSD1307
+	  OLED controller over I2C.
+
 endmenu
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 23e948e..768a137 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -161,6 +161,7 @@ obj-$(CONFIG_FB_BFIN_7393)        += bfin_adv7393fb.o
 obj-$(CONFIG_FB_MX3)		  += mx3fb.o
 obj-$(CONFIG_FB_DA8XX)		  += da8xx-fb.o
 obj-$(CONFIG_FB_MXS)		  += mxsfb.o
+obj-$(CONFIG_FB_SSD1307)	  += ssd1307fb.o
 
 # the test framebuffer is last
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 94cac9f..12cf5f3 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -19,8 +19,8 @@
 #include <linux/backlight.h>
 #include <linux/gfp.h>
 #include <linux/module.h>
+#include <linux/platform_data/atmel.h>
 
-#include <mach/board.h>
 #include <mach/cpu.h>
 #include <asm/gpio.h>
 
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c
index b7ec34c..c072ed9 100644
--- a/drivers/video/backlight/88pm860x_bl.c
+++ b/drivers/video/backlight/88pm860x_bl.c
@@ -117,8 +117,8 @@ static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
 	data->current_brightness = value;
 	return 0;
 out:
-	dev_dbg(chip->dev, "set brightness %d failure with return "
-		"value:%d\n", value, ret);
+	dev_dbg(chip->dev, "set brightness %d failure with return value: %d\n",
+		value, ret);
 	return ret;
 }
 
@@ -208,22 +208,19 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
 	res = platform_get_resource_byname(pdev, IORESOURCE_REG, "duty cycle");
 	if (!res) {
 		dev_err(&pdev->dev, "No REG resource for duty cycle\n");
-		ret = -ENXIO;
-		goto out;
+		return -ENXIO;
 	}
 	data->reg_duty_cycle = res->start;
 	res = platform_get_resource_byname(pdev, IORESOURCE_REG, "always on");
 	if (!res) {
 		dev_err(&pdev->dev, "No REG resorce for always on\n");
-		ret = -ENXIO;
-		goto out;
+		return -ENXIO;
 	}
 	data->reg_always_on = res->start;
 	res = platform_get_resource_byname(pdev, IORESOURCE_REG, "current");
 	if (!res) {
 		dev_err(&pdev->dev, "No REG resource for current\n");
-		ret = -ENXIO;
-		goto out;
+		return -ENXIO;
 	}
 	data->reg_current = res->start;
 
@@ -231,8 +228,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
 	sprintf(name, "backlight-%d", pdev->id);
 	data->port = pdev->id;
 	data->chip = chip;
-	data->i2c = (chip->id == CHIP_PM8606) ? chip->client	\
-			: chip->companion;
+	data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
 	data->current_brightness = MAX_BRIGHTNESS;
 	if (pm860x_backlight_dt_init(pdev, data, name)) {
 		if (pdata) {
@@ -263,8 +259,6 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
 	return 0;
 out_brt:
 	backlight_device_unregister(bl);
-out:
-	devm_kfree(&pdev->dev, data);
 	return ret;
 }
 
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
index df5db99..a1e41d4 100644
--- a/drivers/video/backlight/adp5520_bl.c
+++ b/drivers/video/backlight/adp5520_bl.c
@@ -282,7 +282,7 @@ static const struct attribute_group adp5520_bl_attr_group = {
 	.attrs = adp5520_bl_attributes,
 };
 
-static int __devinit adp5520_bl_probe(struct platform_device *pdev)
+static int adp5520_bl_probe(struct platform_device *pdev)
 {
 	struct backlight_properties props;
 	struct backlight_device *bl;
@@ -333,7 +333,7 @@ static int __devinit adp5520_bl_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit adp5520_bl_remove(struct platform_device *pdev)
+static int adp5520_bl_remove(struct platform_device *pdev)
 {
 	struct backlight_device *bl = platform_get_drvdata(pdev);
 	struct adp5520_bl *data = bl_get_data(bl);
@@ -375,7 +375,7 @@ static struct platform_driver adp5520_bl_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= adp5520_bl_probe,
-	.remove		= __devexit_p(adp5520_bl_remove),
+	.remove		= adp5520_bl_remove,
 	.suspend	= adp5520_bl_suspend,
 	.resume		= adp5520_bl_resume,
 };
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index 77d1fdb..6bb72c0 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -213,7 +213,7 @@ static int adp8860_led_setup(struct adp8860_led *led)
 	return ret;
 }
 
-static int __devinit adp8860_led_probe(struct i2c_client *client)
+static int adp8860_led_probe(struct i2c_client *client)
 {
 	struct adp8860_backlight_platform_data *pdata =
 		client->dev.platform_data;
@@ -295,7 +295,7 @@ static int __devinit adp8860_led_probe(struct i2c_client *client)
 	return ret;
 }
 
-static int __devexit adp8860_led_remove(struct i2c_client *client)
+static int adp8860_led_remove(struct i2c_client *client)
 {
 	struct adp8860_backlight_platform_data *pdata =
 		client->dev.platform_data;
@@ -310,12 +310,12 @@ static int __devexit adp8860_led_remove(struct i2c_client *client)
 	return 0;
 }
 #else
-static int __devinit adp8860_led_probe(struct i2c_client *client)
+static int adp8860_led_probe(struct i2c_client *client)
 {
 	return 0;
 }
 
-static int __devexit adp8860_led_remove(struct i2c_client *client)
+static int adp8860_led_remove(struct i2c_client *client)
 {
 	return 0;
 }
@@ -650,7 +650,7 @@ static const struct attribute_group adp8860_bl_attr_group = {
 	.attrs = adp8860_bl_attributes,
 };
 
-static int __devinit adp8860_probe(struct i2c_client *client,
+static int adp8860_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	struct backlight_device *bl;
@@ -755,7 +755,7 @@ out1:
 	return ret;
 }
 
-static int __devexit adp8860_remove(struct i2c_client *client)
+static int adp8860_remove(struct i2c_client *client)
 {
 	struct adp8860_bl *data = i2c_get_clientdata(client);
 
@@ -805,7 +805,7 @@ static struct i2c_driver adp8860_driver = {
 		.name = KBUILD_MODNAME,
 	},
 	.probe    = adp8860_probe,
-	.remove   = __devexit_p(adp8860_remove),
+	.remove   = adp8860_remove,
 	.suspend = adp8860_i2c_suspend,
 	.resume  = adp8860_i2c_resume,
 	.id_table = adp8860_id,
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
index edf7f91..63c882b 100644
--- a/drivers/video/backlight/adp8870_bl.c
+++ b/drivers/video/backlight/adp8870_bl.c
@@ -235,7 +235,7 @@ static int adp8870_led_setup(struct adp8870_led *led)
 	return ret;
 }
 
-static int __devinit adp8870_led_probe(struct i2c_client *client)
+static int adp8870_led_probe(struct i2c_client *client)
 {
 	struct adp8870_backlight_platform_data *pdata =
 		client->dev.platform_data;
@@ -320,7 +320,7 @@ static int __devinit adp8870_led_probe(struct i2c_client *client)
 	return ret;
 }
 
-static int __devexit adp8870_led_remove(struct i2c_client *client)
+static int adp8870_led_remove(struct i2c_client *client)
 {
 	struct adp8870_backlight_platform_data *pdata =
 		client->dev.platform_data;
@@ -335,12 +335,12 @@ static int __devexit adp8870_led_remove(struct i2c_client *client)
 	return 0;
 }
 #else
-static int __devinit adp8870_led_probe(struct i2c_client *client)
+static int adp8870_led_probe(struct i2c_client *client)
 {
 	return 0;
 }
 
-static int __devexit adp8870_led_remove(struct i2c_client *client)
+static int adp8870_led_remove(struct i2c_client *client)
 {
 	return 0;
 }
@@ -839,7 +839,7 @@ static const struct attribute_group adp8870_bl_attr_group = {
 	.attrs = adp8870_bl_attributes,
 };
 
-static int __devinit adp8870_probe(struct i2c_client *client,
+static int adp8870_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	struct backlight_properties props;
@@ -929,7 +929,7 @@ out1:
 	return ret;
 }
 
-static int __devexit adp8870_remove(struct i2c_client *client)
+static int adp8870_remove(struct i2c_client *client)
 {
 	struct adp8870_bl *data = i2c_get_clientdata(client);
 
@@ -977,7 +977,7 @@ static struct i2c_driver adp8870_driver = {
 		.name = KBUILD_MODNAME,
 	},
 	.probe    = adp8870_probe,
-	.remove   = __devexit_p(adp8870_remove),
+	.remove   = adp8870_remove,
 	.suspend = adp8870_i2c_suspend,
 	.resume  = adp8870_i2c_resume,
 	.id_table = adp8870_id,
diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c
index 3729238..f57e190 100644
--- a/drivers/video/backlight/ams369fg06.c
+++ b/drivers/video/backlight/ams369fg06.c
@@ -474,7 +474,7 @@ static const struct backlight_ops ams369fg06_backlight_ops = {
 	.update_status = ams369fg06_set_brightness,
 };
 
-static int __devinit ams369fg06_probe(struct spi_device *spi)
+static int ams369fg06_probe(struct spi_device *spi)
 {
 	int ret = 0;
 	struct ams369fg06 *lcd = NULL;
@@ -548,7 +548,7 @@ out_lcd_unregister:
 	return ret;
 }
 
-static int __devexit ams369fg06_remove(struct spi_device *spi)
+static int ams369fg06_remove(struct spi_device *spi)
 {
 	struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev);
 
@@ -617,7 +617,7 @@ static struct spi_driver ams369fg06_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= ams369fg06_probe,
-	.remove		= __devexit_p(ams369fg06_remove),
+	.remove		= ams369fg06_remove,
 	.shutdown	= ams369fg06_shutdown,
 	.suspend	= ams369fg06_suspend,
 	.resume		= ams369fg06_resume,
diff --git a/drivers/video/backlight/apple_bl.c b/drivers/video/backlight/apple_bl.c
index 9dc73ac..f088d4c 100644
--- a/drivers/video/backlight/apple_bl.c
+++ b/drivers/video/backlight/apple_bl.c
@@ -137,7 +137,7 @@ static const struct hw_data nvidia_chipset_data = {
 	.set_brightness = nvidia_chipset_set_brightness,
 };
 
-static int __devinit apple_bl_add(struct acpi_device *dev)
+static int apple_bl_add(struct acpi_device *dev)
 {
 	struct backlight_properties props;
 	struct pci_dev *host;
@@ -196,7 +196,7 @@ static int __devinit apple_bl_add(struct acpi_device *dev)
 	return 0;
 }
 
-static int __devexit apple_bl_remove(struct acpi_device *dev, int type)
+static int apple_bl_remove(struct acpi_device *dev, int type)
 {
 	backlight_device_unregister(apple_backlight_device);
 
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
index df1cbb7..de5e5e7 100644
--- a/drivers/video/backlight/atmel-pwm-bl.c
+++ b/drivers/video/backlight/atmel-pwm-bl.c
@@ -106,10 +106,9 @@ static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl)
 	pwm_channel_writel(&pwmbl->pwmc, PWM_CPRD,
 			pwmbl->pdata->pwm_compare_max);
 
-	dev_info(&pwmbl->pdev->dev, "Atmel PWM backlight driver "
-			"(%lu Hz)\n", pwmbl->pwmc.mck /
-			pwmbl->pdata->pwm_compare_max /
-			(1 << prescale));
+	dev_info(&pwmbl->pdev->dev, "Atmel PWM backlight driver (%lu Hz)\n",
+		pwmbl->pwmc.mck / pwmbl->pdata->pwm_compare_max /
+		(1 << prescale));
 
 	return pwm_channel_enable(&pwmbl->pwmc);
 }
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 297db2f..345f666 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -370,6 +370,35 @@ void backlight_device_unregister(struct backlight_device *bd)
 }
 EXPORT_SYMBOL(backlight_device_unregister);
 
+#ifdef CONFIG_OF
+static int of_parent_match(struct device *dev, void *data)
+{
+	return dev->parent && dev->parent->of_node == data;
+}
+
+/**
+ * of_find_backlight_by_node() - find backlight device by device-tree node
+ * @node: device-tree node of the backlight device
+ *
+ * Returns a pointer to the backlight device corresponding to the given DT
+ * node or NULL if no such backlight device exists or if the device hasn't
+ * been probed yet.
+ *
+ * This function obtains a reference on the backlight device and it is the
+ * caller's responsibility to drop the reference by calling put_device() on
+ * the backlight device's .dev field.
+ */
+struct backlight_device *of_find_backlight_by_node(struct device_node *node)
+{
+	struct device *dev;
+
+	dev = class_find_device(backlight_class, NULL, node, of_parent_match);
+
+	return dev ? to_backlight_device(dev) : NULL;
+}
+EXPORT_SYMBOL(of_find_backlight_by_node);
+#endif
+
 static void __exit backlight_class_exit(void)
 {
 	class_destroy(backlight_class);
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
index c781768..e2e1b62 100644
--- a/drivers/video/backlight/corgi_lcd.c
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -6,8 +6,8 @@
  *  Based on Sharp's 2.4 Backlight Driver
  *
  *  Copyright (c) 2008 Marvell International Ltd.
- *  	Converted to SPI device based LCD/Backlight device driver
- *  	by Eric Miao <eric.miao@marvell.com>
+ *	Converted to SPI device based LCD/Backlight device driver
+ *	by Eric Miao <eric.miao@marvell.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -192,7 +192,7 @@ static void lcdtg_set_phadadj(struct corgi_lcd *lcd, int mode)
 {
 	int adj;
 
-	switch(mode) {
+	switch (mode) {
 	case CORGI_LCD_MODE_VGA:
 		/* Setting for VGA */
 		adj = sharpsl_param.phadadj;
@@ -495,8 +495,9 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd,
 		err = devm_gpio_request(&spi->dev, pdata->gpio_backlight_on,
 					"BL_ON");
 		if (err) {
-			dev_err(&spi->dev, "failed to request GPIO%d for "
-				"backlight_on\n", pdata->gpio_backlight_on);
+			dev_err(&spi->dev,
+				"failed to request GPIO%d for backlight_on\n",
+				pdata->gpio_backlight_on);
 			return err;
 		}
 
@@ -508,8 +509,9 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd,
 		err = devm_gpio_request(&spi->dev, pdata->gpio_backlight_cont,
 					"BL_CONT");
 		if (err) {
-			dev_err(&spi->dev, "failed to request GPIO%d for "
-				"backlight_cont\n", pdata->gpio_backlight_cont);
+			dev_err(&spi->dev,
+				"failed to request GPIO%d for backlight_cont\n",
+				pdata->gpio_backlight_cont);
 			return err;
 		}
 
@@ -529,7 +531,7 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd,
 	return 0;
 }
 
-static int __devinit corgi_lcd_probe(struct spi_device *spi)
+static int corgi_lcd_probe(struct spi_device *spi)
 {
 	struct backlight_properties props;
 	struct corgi_lcd_platform_data *pdata = spi->dev.platform_data;
@@ -590,7 +592,7 @@ err_unregister_lcd:
 	return ret;
 }
 
-static int __devexit corgi_lcd_remove(struct spi_device *spi)
+static int corgi_lcd_remove(struct spi_device *spi)
 {
 	struct corgi_lcd *lcd = dev_get_drvdata(&spi->dev);
 
@@ -611,7 +613,7 @@ static struct spi_driver corgi_lcd_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= corgi_lcd_probe,
-	.remove		= __devexit_p(corgi_lcd_remove),
+	.remove		= corgi_lcd_remove,
 	.suspend	= corgi_lcd_suspend,
 	.resume		= corgi_lcd_resume,
 };
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c
index 573c7ec..8179cef 100644
--- a/drivers/video/backlight/da903x_bl.c
+++ b/drivers/video/backlight/da903x_bl.c
@@ -2,10 +2,10 @@
  * Backlight driver for Dialog Semiconductor DA9030/DA9034
  *
  * Copyright (C) 2008 Compulab, Ltd.
- * 	Mike Rapoport <mike@compulab.co.il>
+ *	Mike Rapoport <mike@compulab.co.il>
  *
  * Copyright (C) 2006-2008 Marvell International Ltd.
- * 	Eric Miao <eric.miao@marvell.com>
+ *	Eric Miao <eric.miao@marvell.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -164,15 +164,14 @@ static int da903x_backlight_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int da903x_backlight_suspend(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct backlight_device *bl = platform_get_drvdata(pdev);
+	struct backlight_device *bl = dev_get_drvdata(dev);
+
 	return da903x_backlight_set(bl, 0);
 }
 
 static int da903x_backlight_resume(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct backlight_device *bl = platform_get_drvdata(pdev);
+	struct backlight_device *bl = dev_get_drvdata(dev);
 
 	backlight_update_status(bl);
 	return 0;
@@ -199,7 +198,7 @@ static struct platform_driver da903x_backlight_driver = {
 module_platform_driver(da903x_backlight_driver);
 
 MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034");
-MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
-	      "Mike Rapoport <mike@compulab.co.il>");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
+MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:da903x-backlight");
diff --git a/drivers/video/backlight/da9052_bl.c b/drivers/video/backlight/da9052_bl.c
index ac19618..842da5a 100644
--- a/drivers/video/backlight/da9052_bl.c
+++ b/drivers/video/backlight/da9052_bl.c
@@ -34,7 +34,7 @@ enum {
 	DA9052_TYPE_WLED3,
 };
 
-static unsigned char wled_bank[] = {
+static const unsigned char wled_bank[] = {
 	DA9052_LED1_CONF_REG,
 	DA9052_LED2_CONF_REG,
 	DA9052_LED3_CONF_REG,
diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c
index 08214e1..f50b580 100644
--- a/drivers/video/backlight/ep93xx_bl.c
+++ b/drivers/video/backlight/ep93xx_bl.c
@@ -60,7 +60,7 @@ static const struct backlight_ops ep93xxbl_ops = {
 	.get_brightness	= ep93xxbl_get_brightness,
 };
 
-static int __init ep93xxbl_probe(struct platform_device *dev)
+static int __devinit ep93xxbl_probe(struct platform_device *dev)
 {
 	struct ep93xxbl *ep93xxbl;
 	struct backlight_device *bl;
@@ -106,7 +106,7 @@ static int __init ep93xxbl_probe(struct platform_device *dev)
 	return 0;
 }
 
-static int ep93xxbl_remove(struct platform_device *dev)
+static int __devexit ep93xxbl_remove(struct platform_device *dev)
 {
 	struct backlight_device *bl = platform_get_drvdata(dev);
 
@@ -141,7 +141,7 @@ static struct platform_driver ep93xxbl_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= ep93xxbl_probe,
-	.remove		= __devexit_p(ep93xxbl_remove),
+	.remove		= ep93xxbl_remove,
 	.suspend	= ep93xxbl_suspend,
 	.resume		= ep93xxbl_resume,
 };
diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c
index 8c660fc..0ae155b 100644
--- a/drivers/video/backlight/generic_bl.c
+++ b/drivers/video/backlight/generic_bl.c
@@ -97,8 +97,8 @@ static int genericbl_probe(struct platform_device *pdev)
 	props.max_brightness = machinfo->max_intensity;
 	bd = backlight_device_register(name, &pdev->dev, NULL, &genericbl_ops,
 				       &props);
-	if (IS_ERR (bd))
-		return PTR_ERR (bd);
+	if (IS_ERR(bd))
+		return PTR_ERR(bd);
 
 	platform_set_drvdata(pdev, bd);
 
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index 38aa002..7f70390 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -26,7 +26,7 @@
 #define HP680_DEFAULT_INTENSITY 10
 
 static int hp680bl_suspended;
-static int current_intensity = 0;
+static int current_intensity;
 static DEFINE_SPINLOCK(bl_lock);
 
 static void hp680bl_send_intensity(struct backlight_device *bd)
@@ -103,7 +103,7 @@ static const struct backlight_ops hp680bl_ops = {
 	.update_status  = hp680bl_set_intensity,
 };
 
-static int __devinit hp680bl_probe(struct platform_device *pdev)
+static int hp680bl_probe(struct platform_device *pdev)
 {
 	struct backlight_properties props;
 	struct backlight_device *bd;
@@ -124,7 +124,7 @@ static int __devinit hp680bl_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int hp680bl_remove(struct platform_device *pdev)
+static int __devexit hp680bl_remove(struct platform_device *pdev)
 {
 	struct backlight_device *bd = platform_get_drvdata(pdev);
 
@@ -139,7 +139,7 @@ static int hp680bl_remove(struct platform_device *pdev)
 
 static struct platform_driver hp680bl_driver = {
 	.probe		= hp680bl_probe,
-	.remove		= hp680bl_remove,
+	.remove		= __devexit_p(hp680bl_remove),
 	.suspend	= hp680bl_suspend,
 	.resume		= hp680bl_resume,
 	.driver		= {
@@ -168,7 +168,7 @@ static int __init hp680bl_init(void)
 static void __exit hp680bl_exit(void)
 {
 	platform_device_unregister(hp680bl_device);
- 	platform_driver_unregister(&hp680bl_driver);
+	platform_driver_unregister(&hp680bl_driver);
 }
 
 module_init(hp680bl_init);
diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c
index 9327cd1..26b0df9 100644
--- a/drivers/video/backlight/ili9320.c
+++ b/drivers/video/backlight/ili9320.c
@@ -45,7 +45,7 @@ static inline int ili9320_write_spi(struct ili9320 *ili,
 	/* second message is the data to transfer */
 
 	data[0] = spi->id | ILI9320_SPI_DATA  | ILI9320_SPI_WRITE;
- 	data[1] = value >> 8;
+	data[1] = value >> 8;
 	data[2] = value;
 
 	return spi_sync(spi->dev, &spi->message);
@@ -56,11 +56,10 @@ int ili9320_write(struct ili9320 *ili, unsigned int reg, unsigned int value)
 	dev_dbg(ili->dev, "write: reg=%02x, val=%04x\n", reg, value);
 	return ili->write(ili, reg, value);
 }
-
 EXPORT_SYMBOL_GPL(ili9320_write);
 
 int ili9320_write_regs(struct ili9320 *ili,
-		       struct ili9320_reg *values,
+		       const struct ili9320_reg *values,
 		       int nr_values)
 {
 	int index;
@@ -74,7 +73,6 @@ int ili9320_write_regs(struct ili9320 *ili,
 
 	return 0;
 }
-
 EXPORT_SYMBOL_GPL(ili9320_write_regs);
 
 static void ili9320_reset(struct ili9320 *lcd)
@@ -171,7 +169,7 @@ static struct lcd_ops ili9320_ops = {
 	.set_power	= ili9320_set_power,
 };
 
-static void __devinit ili9320_setup_spi(struct ili9320 *ili,
+static void ili9320_setup_spi(struct ili9320 *ili,
 					struct spi_device *dev)
 {
 	struct ili9320_spi *spi = &ili->access.spi;
@@ -197,7 +195,7 @@ static void __devinit ili9320_setup_spi(struct ili9320 *ili,
 	spi_message_add_tail(&spi->xfer[1], &spi->message);
 }
 
-int __devinit ili9320_probe_spi(struct spi_device *spi,
+int ili9320_probe_spi(struct spi_device *spi,
 				struct ili9320_client *client)
 {
 	struct ili9320_platdata *cfg = spi->dev.platform_data;
@@ -260,10 +258,9 @@ int __devinit ili9320_probe_spi(struct spi_device *spi,
 
 	return ret;
 }
-
 EXPORT_SYMBOL_GPL(ili9320_probe_spi);
 
-int ili9320_remove(struct ili9320 *ili)
+int __devexit ili9320_remove(struct ili9320 *ili)
 {
 	ili9320_power(ili, FB_BLANK_POWERDOWN);
 
@@ -271,7 +268,6 @@ int ili9320_remove(struct ili9320 *ili)
 
 	return 0;
 }
-
 EXPORT_SYMBOL_GPL(ili9320_remove);
 
 #ifdef CONFIG_PM
@@ -296,20 +292,17 @@ int ili9320_suspend(struct ili9320 *lcd, pm_message_t state)
 
 	return 0;
 }
-
 EXPORT_SYMBOL_GPL(ili9320_suspend);
 
 int ili9320_resume(struct ili9320 *lcd)
 {
 	dev_info(lcd->dev, "resuming from power state %d\n", lcd->power);
 
-	if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) {
+	if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP)
 		ili9320_write(lcd, ILI9320_POWER1, 0x00);
-	}
 
 	return ili9320_power(lcd, FB_BLANK_UNBLANK);
 }
-
 EXPORT_SYMBOL_GPL(ili9320_resume);
 #endif
 
@@ -318,7 +311,6 @@ void ili9320_shutdown(struct ili9320 *lcd)
 {
 	ili9320_power(lcd, FB_BLANK_POWERDOWN);
 }
-
 EXPORT_SYMBOL_GPL(ili9320_shutdown);
 
 MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
diff --git a/drivers/video/backlight/ili9320.h b/drivers/video/backlight/ili9320.h
index e388eca..e0db738 100644
--- a/drivers/video/backlight/ili9320.h
+++ b/drivers/video/backlight/ili9320.h
@@ -63,7 +63,7 @@ extern int ili9320_write(struct ili9320 *ili,
 			 unsigned int reg, unsigned int value);
 
 extern int ili9320_write_regs(struct ili9320 *ili,
-			      struct ili9320_reg *values,
+			      const struct ili9320_reg *values,
 			      int nr_values);
 
 /* Device probe */
diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c
index 16f593b..c23801c 100644
--- a/drivers/video/backlight/jornada720_bl.c
+++ b/drivers/video/backlight/jornada720_bl.c
@@ -48,7 +48,7 @@ static int jornada_bl_get_brightness(struct backlight_device *bd)
 
 	jornada_ssp_end();
 
-	return (BL_MAX_BRIGHT - ret);
+	return BL_MAX_BRIGHT - ret;
 }
 
 static int jornada_bl_update_status(struct backlight_device *bd)
@@ -58,7 +58,8 @@ static int jornada_bl_update_status(struct backlight_device *bd)
 	jornada_ssp_start();
 
 	/* If backlight is off then really turn it off */
-	if ((bd->props.power != FB_BLANK_UNBLANK) || (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
+	if ((bd->props.power != FB_BLANK_UNBLANK) ||
+		(bd->props.fb_blank != FB_BLANK_UNBLANK)) {
 		ret = jornada_ssp_byte(BRIGHTNESSOFF);
 		if (ret != TXDUMMY) {
 			pr_info("brightness off timeout\n");
@@ -77,18 +78,23 @@ static int jornada_bl_update_status(struct backlight_device *bd)
 			goto out;
 		}
 
-		/* at this point we expect that the mcu has accepted
-		   our command and is waiting for our new value
-		   please note that maximum brightness is 255,
-		   but due to physical layout it is equal to 0, so we simply
-		   invert the value (MAX VALUE - NEW VALUE). */
-		if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness) != TXDUMMY) {
+		/*
+		 * at this point we expect that the mcu has accepted
+		 * our command and is waiting for our new value
+		 * please note that maximum brightness is 255,
+		 * but due to physical layout it is equal to 0, so we simply
+		 * invert the value (MAX VALUE - NEW VALUE).
+		 */
+		if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness)
+			!= TXDUMMY) {
 			pr_err("set brightness failed\n");
 			ret = -ETIMEDOUT;
 		}
 
-		/* If infact we get an TXDUMMY as output we are happy and dont
-		   make any further comments about it */
+		/*
+		 * If infact we get an TXDUMMY as output we are happy and dont
+		 * make any further comments about it
+		 */
 out:
 	jornada_ssp_end();
 
@@ -121,9 +127,11 @@ static int jornada_bl_probe(struct platform_device *pdev)
 
 	bd->props.power = FB_BLANK_UNBLANK;
 	bd->props.brightness = BL_DEF_BRIGHT;
-	/* note. make sure max brightness is set otherwise
-	   you will get seemingly non-related errors when
-	   trying to change brightness */
+	/*
+	 * note. make sure max brightness is set otherwise
+	 * you will get seemingly non-related errors when
+	 * trying to change brightness
+	 */
 	jornada_bl_update_status(bd);
 
 	platform_set_drvdata(pdev, bd);
diff --git a/drivers/video/backlight/jornada720_lcd.c b/drivers/video/backlight/jornada720_lcd.c
index 635b305..4b412cb 100644
--- a/drivers/video/backlight/jornada720_lcd.c
+++ b/drivers/video/backlight/jornada720_lcd.c
@@ -101,7 +101,8 @@ static int jornada_lcd_probe(struct platform_device *pdev)
 	struct lcd_device *lcd_device;
 	int ret;
 
-	lcd_device = lcd_device_register(S1D_DEVICENAME, &pdev->dev, NULL, &jornada_lcd_props);
+	lcd_device = lcd_device_register(S1D_DEVICENAME, &pdev->dev, NULL,
+					&jornada_lcd_props);
 
 	if (IS_ERR(lcd_device)) {
 		ret = PTR_ERR(lcd_device);
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
index 2d90c06..9a35196 100644
--- a/drivers/video/backlight/l4f00242t03.c
+++ b/drivers/video/backlight/l4f00242t03.c
@@ -4,7 +4,7 @@
  * Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved.
  *
  * Copyright (c) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
- * 	Inspired by Marek Vasut work in l4f00242t03.c
+ *	Inspired by Marek Vasut work in l4f00242t03.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
@@ -33,7 +33,6 @@ struct l4f00242t03_priv {
 	struct regulator *core_reg;
 };
 
-
 static void l4f00242t03_reset(unsigned int gpio)
 {
 	pr_debug("l4f00242t03_reset.\n");
@@ -150,7 +149,7 @@ static struct lcd_ops l4f_ops = {
 	.get_power	= l4f00242t03_lcd_power_get,
 };
 
-static int __devinit l4f00242t03_probe(struct spi_device *spi)
+static int l4f00242t03_probe(struct spi_device *spi)
 {
 	struct l4f00242t03_priv *priv;
 	struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
@@ -230,7 +229,7 @@ err1:
 	return ret;
 }
 
-static int __devexit l4f00242t03_remove(struct spi_device *spi)
+static int l4f00242t03_remove(struct spi_device *spi)
 {
 	struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev);
 
@@ -260,7 +259,7 @@ static struct spi_driver l4f00242t03_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= l4f00242t03_probe,
-	.remove		= __devexit_p(l4f00242t03_remove),
+	.remove		= l4f00242t03_remove,
 	.shutdown	= l4f00242t03_shutdown,
 };
 
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index a5d0d02..34fb6bd 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -108,7 +108,7 @@ static ssize_t lcd_show_power(struct device *dev, struct device_attribute *attr,
 static ssize_t lcd_store_power(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
-	int rc = -ENXIO;
+	int rc;
 	struct lcd_device *ld = to_lcd_device(dev);
 	unsigned long power;
 
@@ -116,6 +116,8 @@ static ssize_t lcd_store_power(struct device *dev,
 	if (rc)
 		return rc;
 
+	rc = -ENXIO;
+
 	mutex_lock(&ld->ops_lock);
 	if (ld->ops && ld->ops->set_power) {
 		pr_debug("set power to %lu\n", power);
@@ -144,7 +146,7 @@ static ssize_t lcd_show_contrast(struct device *dev,
 static ssize_t lcd_store_contrast(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
-	int rc = -ENXIO;
+	int rc;
 	struct lcd_device *ld = to_lcd_device(dev);
 	unsigned long contrast;
 
@@ -152,6 +154,8 @@ static ssize_t lcd_store_contrast(struct device *dev,
 	if (rc)
 		return rc;
 
+	rc = -ENXIO;
+
 	mutex_lock(&ld->ops_lock);
 	if (ld->ops && ld->ops->set_contrast) {
 		pr_debug("set contrast to %lu\n", contrast);
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
index 58f517f..1cb3524 100644
--- a/drivers/video/backlight/ld9040.c
+++ b/drivers/video/backlight/ld9040.c
@@ -788,7 +788,7 @@ out_free_regulator:
 	return ret;
 }
 
-static int __devexit ld9040_remove(struct spi_device *spi)
+static int ld9040_remove(struct spi_device *spi)
 {
 	struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
 
@@ -847,7 +847,7 @@ static struct spi_driver ld9040_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= ld9040_probe,
-	.remove		= __devexit_p(ld9040_remove),
+	.remove		= ld9040_remove,
 	.shutdown	= ld9040_shutdown,
 	.suspend	= ld9040_suspend,
 	.resume		= ld9040_resume,
diff --git a/drivers/video/backlight/lm3533_bl.c b/drivers/video/backlight/lm3533_bl.c
index 18dca0c..5d18d4d 100644
--- a/drivers/video/backlight/lm3533_bl.c
+++ b/drivers/video/backlight/lm3533_bl.c
@@ -257,7 +257,7 @@ static struct attribute_group lm3533_bl_attribute_group = {
 	.attrs		= lm3533_bl_attributes
 };
 
-static int __devinit lm3533_bl_setup(struct lm3533_bl *bl,
+static int lm3533_bl_setup(struct lm3533_bl *bl,
 					struct lm3533_bl_platform_data *pdata)
 {
 	int ret;
@@ -269,7 +269,7 @@ static int __devinit lm3533_bl_setup(struct lm3533_bl *bl,
 	return lm3533_ctrlbank_set_pwm(&bl->cb, pdata->pwm);
 }
 
-static int __devinit lm3533_bl_probe(struct platform_device *pdev)
+static int lm3533_bl_probe(struct platform_device *pdev)
 {
 	struct lm3533 *lm3533;
 	struct lm3533_bl_platform_data *pdata;
@@ -351,7 +351,7 @@ err_unregister:
 	return ret;
 }
 
-static int __devexit lm3533_bl_remove(struct platform_device *pdev)
+static int lm3533_bl_remove(struct platform_device *pdev)
 {
 	struct lm3533_bl *bl = platform_get_drvdata(pdev);
 	struct backlight_device *bd = bl->bd;
@@ -406,7 +406,7 @@ static struct platform_driver lm3533_bl_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= lm3533_bl_probe,
-	.remove		= __devexit_p(lm3533_bl_remove),
+	.remove		= lm3533_bl_remove,
 	.shutdown	= lm3533_bl_shutdown,
 	.suspend	= lm3533_bl_suspend,
 	.resume		= lm3533_bl_resume,
diff --git a/drivers/video/backlight/lm3630_bl.c b/drivers/video/backlight/lm3630_bl.c
index dc19144..a6d637b 100644
--- a/drivers/video/backlight/lm3630_bl.c
+++ b/drivers/video/backlight/lm3630_bl.c
@@ -37,7 +37,7 @@ enum lm3630_leds {
 	BLED_2
 };
 
-static const char *bled_name[] = {
+static const char * const bled_name[] = {
 	[BLED_ALL] = "lm3630_bled",	/*Bank1 controls all string */
 	[BLED_1] = "lm3630_bled1",	/*Bank1 controls bled1 */
 	[BLED_2] = "lm3630_bled2",	/*Bank1 or 2 controls bled2 */
@@ -55,7 +55,7 @@ struct lm3630_chip_data {
 };
 
 /* initialize chip */
-static int __devinit lm3630_chip_init(struct lm3630_chip_data *pchip)
+static int lm3630_chip_init(struct lm3630_chip_data *pchip)
 {
 	int ret;
 	unsigned int reg_val;
@@ -349,7 +349,7 @@ static const struct regmap_config lm3630_regmap = {
 	.max_register = REG_MAX,
 };
 
-static int __devinit lm3630_probe(struct i2c_client *client,
+static int lm3630_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
 	struct lm3630_platform_data *pdata = client->dev.platform_data;
@@ -429,7 +429,7 @@ err_chip_init:
 	return ret;
 }
 
-static int __devexit lm3630_remove(struct i2c_client *client)
+static int lm3630_remove(struct i2c_client *client)
 {
 	int ret;
 	struct lm3630_chip_data *pchip = i2c_get_clientdata(client);
@@ -463,7 +463,7 @@ static struct i2c_driver lm3630_i2c_driver = {
 		   .name = LM3630_NAME,
 		   },
 	.probe = lm3630_probe,
-	.remove = __devexit_p(lm3630_remove),
+	.remove = lm3630_remove,
 	.id_table = lm3630_id,
 };
 
diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c
index 585949b..7ab2d2a 100644
--- a/drivers/video/backlight/lm3639_bl.c
+++ b/drivers/video/backlight/lm3639_bl.c
@@ -48,7 +48,7 @@ struct lm3639_chip_data {
 };
 
 /* initialize chip */
-static int __devinit lm3639_chip_init(struct lm3639_chip_data *pchip)
+static int lm3639_chip_init(struct lm3639_chip_data *pchip)
 {
 	int ret;
 	unsigned int reg_val;
@@ -214,7 +214,7 @@ out_input:
 
 }
 
-static DEVICE_ATTR(bled_mode, 0666, NULL, lm3639_bled_mode_store);
+static DEVICE_ATTR(bled_mode, S_IWUSR, NULL, lm3639_bled_mode_store);
 
 /* torch */
 static void lm3639_torch_brightness_set(struct led_classdev *cdev,
@@ -299,7 +299,7 @@ static const struct regmap_config lm3639_regmap = {
 	.max_register = REG_MAX,
 };
 
-static int __devinit lm3639_probe(struct i2c_client *client,
+static int lm3639_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
 	int ret;
@@ -397,7 +397,7 @@ err_out:
 	return ret;
 }
 
-static int __devexit lm3639_remove(struct i2c_client *client)
+static int lm3639_remove(struct i2c_client *client)
 {
 	struct lm3639_chip_data *pchip = i2c_get_clientdata(client);
 
@@ -425,7 +425,7 @@ static struct i2c_driver lm3639_i2c_driver = {
 		   .name = LM3639_NAME,
 		   },
 	.probe = lm3639_probe,
-	.remove = __devexit_p(lm3639_remove),
+	.remove = lm3639_remove,
 	.id_table = lm3639_id,
 };
 
diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c
index ea43f22..55819b3 100644
--- a/drivers/video/backlight/lms283gf05.c
+++ b/drivers/video/backlight/lms283gf05.c
@@ -31,7 +31,7 @@ struct lms283gf05_seq {
 };
 
 /* Magic sequences supplied by manufacturer, for details refer to datasheet */
-static struct lms283gf05_seq disp_initseq[] = {
+static const struct lms283gf05_seq disp_initseq[] = {
 	/* REG, VALUE, DELAY */
 	{ 0x07, 0x0000, 0 },
 	{ 0x13, 0x0000, 10 },
@@ -78,7 +78,7 @@ static struct lms283gf05_seq disp_initseq[] = {
 	{ 0x22, 0x0000, 0 }
 };
 
-static struct lms283gf05_seq disp_pdwnseq[] = {
+static const struct lms283gf05_seq disp_pdwnseq[] = {
 	{ 0x07, 0x0016, 30 },
 
 	{ 0x07, 0x0004, 0 },
@@ -104,7 +104,7 @@ static void lms283gf05_reset(unsigned long gpio, bool inverted)
 }
 
 static void lms283gf05_toggle(struct spi_device *spi,
-			struct lms283gf05_seq *seq, int sz)
+				const struct lms283gf05_seq *seq, int sz)
 {
 	char buf[3];
 	int i;
@@ -150,7 +150,7 @@ static struct lcd_ops lms_ops = {
 	.get_power	= NULL,
 };
 
-static int __devinit lms283gf05_probe(struct spi_device *spi)
+static int lms283gf05_probe(struct spi_device *spi)
 {
 	struct lms283gf05_state *st;
 	struct lms283gf05_pdata *pdata = spi->dev.platform_data;
@@ -158,13 +158,10 @@ static int __devinit lms283gf05_probe(struct spi_device *spi)
 	int ret = 0;
 
 	if (pdata != NULL) {
-		ret = devm_gpio_request(&spi->dev, pdata->reset_gpio,
-					"LMS285GF05 RESET");
-		if (ret)
-			return ret;
-
-		ret = gpio_direction_output(pdata->reset_gpio,
-						!pdata->reset_inverted);
+		ret = devm_gpio_request_one(&spi->dev, pdata->reset_gpio,
+				GPIOF_DIR_OUT | (!pdata->reset_inverted ?
+				GPIOF_INIT_HIGH : GPIOF_INIT_LOW),
+				"LMS285GF05 RESET");
 		if (ret)
 			return ret;
 	}
@@ -193,7 +190,7 @@ static int __devinit lms283gf05_probe(struct spi_device *spi)
 	return 0;
 }
 
-static int __devexit lms283gf05_remove(struct spi_device *spi)
+static int lms283gf05_remove(struct spi_device *spi)
 {
 	struct lms283gf05_state *st = dev_get_drvdata(&spi->dev);
 
@@ -208,7 +205,7 @@ static struct spi_driver lms283gf05_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= lms283gf05_probe,
-	.remove		= __devexit_p(lms283gf05_remove),
+	.remove		= lms283gf05_remove,
 };
 
 module_spi_driver(lms283gf05_driver);
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index 3a6d541..4cfa87b 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -33,19 +33,25 @@ static unsigned long locomolcd_flags;
 
 static void locomolcd_on(int comadj)
 {
-	locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHA_ON, 0);
-	locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHA_ON, 1);
+	locomo_gpio_set_dir(locomolcd_dev->dev.parent,
+			LOCOMO_GPIO_LCD_VSHA_ON, 0);
+	locomo_gpio_write(locomolcd_dev->dev.parent,
+			LOCOMO_GPIO_LCD_VSHA_ON, 1);
 	mdelay(2);
 
-	locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHD_ON, 0);
-	locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHD_ON, 1);
+	locomo_gpio_set_dir(locomolcd_dev->dev.parent,
+			LOCOMO_GPIO_LCD_VSHD_ON, 0);
+	locomo_gpio_write(locomolcd_dev->dev.parent,
+			LOCOMO_GPIO_LCD_VSHD_ON, 1);
 	mdelay(2);
 
 	locomo_m62332_senddata(locomolcd_dev, comadj, 0);
 	mdelay(5);
 
-	locomo_gpio_set_dir(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VEE_ON, 0);
-	locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VEE_ON, 1);
+	locomo_gpio_set_dir(locomolcd_dev->dev.parent,
+			LOCOMO_GPIO_LCD_VEE_ON, 0);
+	locomo_gpio_write(locomolcd_dev->dev.parent,
+			LOCOMO_GPIO_LCD_VEE_ON, 1);
 	mdelay(10);
 
 	/* TFTCRST | CPSOUT=0 | CPSEN */
@@ -68,16 +74,19 @@ static void locomolcd_off(int comadj)
 	locomo_writel(0x06, locomolcd_dev->mapbase + LOCOMO_TC);
 	mdelay(1);
 
-	locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHA_ON, 0);
+	locomo_gpio_write(locomolcd_dev->dev.parent,
+			LOCOMO_GPIO_LCD_VSHA_ON, 0);
 	mdelay(110);
 
-	locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VEE_ON, 0);
+	locomo_gpio_write(locomolcd_dev->dev.parent,
+			LOCOMO_GPIO_LCD_VEE_ON, 0);
 	mdelay(700);
 
 	/* TFTCRST=0 | CPSOUT=0 | CPSEN = 0 */
 	locomo_writel(0, locomolcd_dev->mapbase + LOCOMO_TC);
 	locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_MOD, 0);
-	locomo_gpio_write(locomolcd_dev->dev.parent, LOCOMO_GPIO_LCD_VSHD_ON, 0);
+	locomo_gpio_write(locomolcd_dev->dev.parent,
+			LOCOMO_GPIO_LCD_VSHD_ON, 0);
 }
 
 void locomolcd_power(int on)
@@ -107,7 +116,6 @@ void locomolcd_power(int on)
 }
 EXPORT_SYMBOL(locomolcd_power);
 
-
 static int current_intensity;
 
 static int locomolcd_set_intensity(struct backlight_device *bd)
@@ -122,13 +130,25 @@ static int locomolcd_set_intensity(struct backlight_device *bd)
 		intensity = 0;
 
 	switch (intensity) {
-	/* AC and non-AC are handled differently, but produce same results in sharp code? */
-	case 0: locomo_frontlight_set(locomolcd_dev, 0, 0, 161); break;
-	case 1: locomo_frontlight_set(locomolcd_dev, 117, 0, 161); break;
-	case 2: locomo_frontlight_set(locomolcd_dev, 163, 0, 148); break;
-	case 3: locomo_frontlight_set(locomolcd_dev, 194, 0, 161); break;
-	case 4: locomo_frontlight_set(locomolcd_dev, 194, 1, 161); break;
-
+	/*
+	 * AC and non-AC are handled differently,
+	 * but produce same results in sharp code?
+	 */
+	case 0:
+		locomo_frontlight_set(locomolcd_dev, 0, 0, 161);
+		break;
+	case 1:
+		locomo_frontlight_set(locomolcd_dev, 117, 0, 161);
+		break;
+	case 2:
+		locomo_frontlight_set(locomolcd_dev, 163, 0, 148);
+		break;
+	case 3:
+		locomo_frontlight_set(locomolcd_dev, 194, 0, 161);
+		break;
+	case 4:
+		locomo_frontlight_set(locomolcd_dev, 194, 1, 161);
+		break;
 	default:
 		return -ENODEV;
 	}
@@ -175,9 +195,11 @@ static int locomolcd_probe(struct locomo_dev *ldev)
 
 	locomo_gpio_set_dir(ldev->dev.parent, LOCOMO_GPIO_FL_VR, 0);
 
-	/* the poodle_lcd_power function is called for the first time
+	/*
+	 * the poodle_lcd_power function is called for the first time
 	 * from fs_initcall, which is before locomo is activated.
-	 * We need to recall poodle_lcd_power here*/
+	 * We need to recall poodle_lcd_power here
+	 */
 	if (machine_is_poodle())
 		locomolcd_power(1);
 
@@ -190,8 +212,8 @@ static int locomolcd_probe(struct locomo_dev *ldev)
 							&ldev->dev, NULL,
 							&locomobl_data, &props);
 
-	if (IS_ERR (locomolcd_bl_device))
-		return PTR_ERR (locomolcd_bl_device);
+	if (IS_ERR(locomolcd_bl_device))
+		return PTR_ERR(locomolcd_bl_device);
 
 	/* Set up frontlight so that screen is readable */
 	locomolcd_bl_device->props.brightness = 2;
@@ -226,7 +248,6 @@ static struct locomo_driver poodle_lcd_driver = {
 	.resume = locomolcd_resume,
 };
 
-
 static int __init locomolcd_init(void)
 {
 	return locomo_driver_register(&poodle_lcd_driver);
diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
index aa6d4f7..6e4db0c 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -15,6 +15,7 @@
 #include <linux/backlight.h>
 #include <linux/err.h>
 #include <linux/platform_data/lp855x.h>
+#include <linux/pwm.h>
 
 /* Registers */
 #define BRIGHTNESS_CTRL		0x00
@@ -34,22 +35,19 @@ struct lp855x {
 	struct i2c_client *client;
 	struct backlight_device *bl;
 	struct device *dev;
-	struct mutex xfer_lock;
 	struct lp855x_platform_data *pdata;
+	struct pwm_device *pwm;
 };
 
 static int lp855x_read_byte(struct lp855x *lp, u8 reg, u8 *data)
 {
 	int ret;
 
-	mutex_lock(&lp->xfer_lock);
 	ret = i2c_smbus_read_byte_data(lp->client, reg);
 	if (ret < 0) {
-		mutex_unlock(&lp->xfer_lock);
 		dev_err(lp->dev, "failed to read 0x%.2x\n", reg);
 		return ret;
 	}
-	mutex_unlock(&lp->xfer_lock);
 
 	*data = (u8)ret;
 	return 0;
@@ -57,13 +55,7 @@ static int lp855x_read_byte(struct lp855x *lp, u8 reg, u8 *data)
 
 static int lp855x_write_byte(struct lp855x *lp, u8 reg, u8 data)
 {
-	int ret;
-
-	mutex_lock(&lp->xfer_lock);
-	ret = i2c_smbus_write_byte_data(lp->client, reg, data);
-	mutex_unlock(&lp->xfer_lock);
-
-	return ret;
+	return i2c_smbus_write_byte_data(lp->client, reg, data);
 }
 
 static bool lp855x_is_valid_rom_area(struct lp855x *lp, u8 addr)
@@ -121,6 +113,28 @@ static int lp855x_init_registers(struct lp855x *lp)
 	return ret;
 }
 
+static void lp855x_pwm_ctrl(struct lp855x *lp, int br, int max_br)
+{
+	unsigned int period = lp->pdata->period_ns;
+	unsigned int duty = br * period / max_br;
+	struct pwm_device *pwm;
+
+	/* request pwm device with the consumer name */
+	if (!lp->pwm) {
+		pwm = devm_pwm_get(lp->dev, lp->chipname);
+		if (IS_ERR(pwm))
+			return;
+
+		lp->pwm = pwm;
+	}
+
+	pwm_config(lp->pwm, duty, period);
+	if (duty)
+		pwm_enable(lp->pwm);
+	else
+		pwm_disable(lp->pwm);
+}
+
 static int lp855x_bl_update_status(struct backlight_device *bl)
 {
 	struct lp855x *lp = bl_get_data(bl);
@@ -130,12 +144,10 @@ static int lp855x_bl_update_status(struct backlight_device *bl)
 		bl->props.brightness = 0;
 
 	if (mode == PWM_BASED) {
-		struct lp855x_pwm_data *pd = &lp->pdata->pwm_data;
 		int br = bl->props.brightness;
 		int max_br = bl->props.max_brightness;
 
-		if (pd->pwm_set_intensity)
-			pd->pwm_set_intensity(br, max_br);
+		lp855x_pwm_ctrl(lp, br, max_br);
 
 	} else if (mode == REGISTER_BASED) {
 		u8 val = bl->props.brightness;
@@ -150,14 +162,7 @@ static int lp855x_bl_get_brightness(struct backlight_device *bl)
 	struct lp855x *lp = bl_get_data(bl);
 	enum lp855x_brightness_ctrl_mode mode = lp->pdata->mode;
 
-	if (mode == PWM_BASED) {
-		struct lp855x_pwm_data *pd = &lp->pdata->pwm_data;
-		int max_br = bl->props.max_brightness;
-
-		if (pd->pwm_get_intensity)
-			bl->props.brightness = pd->pwm_get_intensity(max_br);
-
-	} else if (mode == REGISTER_BASED) {
+	if (mode == REGISTER_BASED) {
 		u8 val = 0;
 
 		lp855x_read_byte(lp, BRIGHTNESS_CTRL, &val);
@@ -266,8 +271,6 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 	lp->chip_id = id->driver_data;
 	i2c_set_clientdata(cl, lp);
 
-	mutex_init(&lp->xfer_lock);
-
 	ret = lp855x_init_registers(lp);
 	if (ret) {
 		dev_err(lp->dev, "i2c communication err: %d", ret);
@@ -297,7 +300,7 @@ err_dev:
 	return ret;
 }
 
-static int __devexit lp855x_remove(struct i2c_client *cl)
+static int lp855x_remove(struct i2c_client *cl)
 {
 	struct lp855x *lp = i2c_get_clientdata(cl);
 
@@ -324,7 +327,7 @@ static struct i2c_driver lp855x_driver = {
 		   .name = "lp855x",
 		   },
 	.probe = lp855x_probe,
-	.remove = __devexit_p(lp855x_remove),
+	.remove = lp855x_remove,
 	.id_table = lp855x_ids,
 };
 
diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c
index 4066a5b..226d813 100644
--- a/drivers/video/backlight/ltv350qv.c
+++ b/drivers/video/backlight/ltv350qv.c
@@ -226,7 +226,7 @@ static struct lcd_ops ltv_ops = {
 	.set_power	= ltv350qv_set_power,
 };
 
-static int __devinit ltv350qv_probe(struct spi_device *spi)
+static int ltv350qv_probe(struct spi_device *spi)
 {
 	struct ltv350qv *lcd;
 	struct lcd_device *ld;
@@ -261,7 +261,7 @@ out_unregister:
 	return ret;
 }
 
-static int __devexit ltv350qv_remove(struct spi_device *spi)
+static int ltv350qv_remove(struct spi_device *spi)
 {
 	struct ltv350qv *lcd = dev_get_drvdata(&spi->dev);
 
@@ -305,7 +305,7 @@ static struct spi_driver ltv350qv_driver = {
 	},
 
 	.probe		= ltv350qv_probe,
-	.remove		= __devexit_p(ltv350qv_remove),
+	.remove		= ltv350qv_remove,
 	.shutdown	= ltv350qv_shutdown,
 	.suspend	= ltv350qv_suspend,
 	.resume		= ltv350qv_resume,
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
index f72ba54..2c9bce0 100644
--- a/drivers/video/backlight/max8925_bl.c
+++ b/drivers/video/backlight/max8925_bl.c
@@ -101,7 +101,7 @@ static const struct backlight_ops max8925_backlight_ops = {
 	.get_brightness	= max8925_backlight_get_brightness,
 };
 
-static int __devinit max8925_backlight_probe(struct platform_device *pdev)
+static int max8925_backlight_probe(struct platform_device *pdev)
 {
 	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
 	struct max8925_backlight_pdata *pdata = pdev->dev.platform_data;
@@ -120,15 +120,13 @@ static int __devinit max8925_backlight_probe(struct platform_device *pdev)
 	res = platform_get_resource(pdev, IORESOURCE_REG, 0);
 	if (!res) {
 		dev_err(&pdev->dev, "No REG resource for mode control!\n");
-		ret = -ENXIO;
-		goto out;
+		return -ENXIO;
 	}
 	data->reg_mode_cntl = res->start;
 	res = platform_get_resource(pdev, IORESOURCE_REG, 1);
 	if (!res) {
 		dev_err(&pdev->dev, "No REG resource for control!\n");
-		ret = -ENXIO;
-		goto out;
+		return -ENXIO;
 	}
 	data->reg_cntl = res->start;
 
@@ -142,8 +140,7 @@ static int __devinit max8925_backlight_probe(struct platform_device *pdev)
 					&max8925_backlight_ops, &props);
 	if (IS_ERR(bl)) {
 		dev_err(&pdev->dev, "failed to register backlight\n");
-		ret = PTR_ERR(bl);
-		goto out;
+		return PTR_ERR(bl);
 	}
 	bl->props.brightness = MAX_BRIGHTNESS;
 
@@ -166,12 +163,10 @@ static int __devinit max8925_backlight_probe(struct platform_device *pdev)
 	return 0;
 out_brt:
 	backlight_device_unregister(bl);
-out:
-	devm_kfree(&pdev->dev, data);
 	return ret;
 }
 
-static int __devexit max8925_backlight_remove(struct platform_device *pdev)
+static int max8925_backlight_remove(struct platform_device *pdev)
 {
 	struct backlight_device *bl = platform_get_drvdata(pdev);
 
@@ -185,7 +180,7 @@ static struct platform_driver max8925_backlight_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= max8925_backlight_probe,
-	.remove		= __devexit_p(max8925_backlight_remove),
+	.remove		= max8925_backlight_remove,
 };
 
 module_platform_driver(max8925_backlight_driver);
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c
index 9a046a4..af31c26 100644
--- a/drivers/video/backlight/omap1_bl.c
+++ b/drivers/video/backlight/omap1_bl.c
@@ -42,12 +42,12 @@ struct omap_backlight {
 	struct omap_backlight_config *pdata;
 };
 
-static void inline omapbl_send_intensity(int intensity)
+static inline void omapbl_send_intensity(int intensity)
 {
 	omap_writeb(intensity, OMAP_PWL_ENABLE);
 }
 
-static void inline omapbl_send_enable(int enable)
+static inline void omapbl_send_enable(int enable)
 {
 	omap_writeb(enable, OMAP_PWL_CLK_ENABLE);
 }
diff --git a/drivers/video/backlight/pandora_bl.c b/drivers/video/backlight/pandora_bl.c
index 4ec3074..633b0a2 100644
--- a/drivers/video/backlight/pandora_bl.c
+++ b/drivers/video/backlight/pandora_bl.c
@@ -71,8 +71,7 @@ static int pandora_backlight_update_status(struct backlight_device *bl)
 		 * set PWM duty cycle to max. TPS61161 seems to use this
 		 * to calibrate it's PWM sensitivity when it starts.
 		 */
-		twl_i2c_write_u8(TWL4030_MODULE_PWM0, MAX_VALUE,
-					TWL_PWM0_OFF);
+		twl_i2c_write_u8(TWL_MODULE_PWM, MAX_VALUE, TWL_PWM0_OFF);
 
 		/* first enable clock, then PWM0 out */
 		twl_i2c_read_u8(TWL4030_MODULE_INTBR, &r, TWL_INTBR_GPBR1);
@@ -90,8 +89,7 @@ static int pandora_backlight_update_status(struct backlight_device *bl)
 		usleep_range(2000, 10000);
 	}
 
-	twl_i2c_write_u8(TWL4030_MODULE_PWM0, MIN_VALUE + brightness,
-				TWL_PWM0_OFF);
+	twl_i2c_write_u8(TWL_MODULE_PWM, MIN_VALUE + brightness, TWL_PWM0_OFF);
 
 done:
 	if (brightness != 0)
@@ -132,7 +130,7 @@ static int pandora_backlight_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, bl);
 
 	/* 64 cycle period, ON position 0 */
-	twl_i2c_write_u8(TWL4030_MODULE_PWM0, 0x80, TWL_PWM0_ON);
+	twl_i2c_write_u8(TWL_MODULE_PWM, 0x80, TWL_PWM0_ON);
 
 	bl->props.state |= PANDORABL_WAS_OFF;
 	bl->props.brightness = MAX_USER_VALUE;
diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c
index c092159..e87c7a3 100644
--- a/drivers/video/backlight/pcf50633-backlight.c
+++ b/drivers/video/backlight/pcf50633-backlight.c
@@ -52,7 +52,7 @@ int pcf50633_bl_set_brightness_limit(struct pcf50633 *pcf, unsigned int limit)
 	pcf_bl->brightness_limit = limit & 0x3f;
 	backlight_update_status(pcf_bl->bl);
 
-    return 0;
+	return 0;
 }
 
 static int pcf50633_bl_update_status(struct backlight_device *bl)
@@ -99,7 +99,7 @@ static const struct backlight_ops pcf50633_bl_ops = {
 	.options	= BL_CORE_SUSPENDRESUME,
 };
 
-static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
+static int pcf50633_bl_probe(struct platform_device *pdev)
 {
 	struct pcf50633_bl *pcf_bl;
 	struct device *parent = pdev->dev.parent;
@@ -136,8 +136,10 @@ static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
 
 	pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM, pdata->ramp_time);
 
-	/* Should be different from bl_props.brightness, so we do not exit
-	 * update_status early the first time it's called */
+	/*
+	 * Should be different from bl_props.brightness, so we do not exit
+	 * update_status early the first time it's called
+	 */
 	pcf_bl->brightness = pcf_bl->bl->props.brightness + 1;
 
 	backlight_update_status(pcf_bl->bl);
@@ -145,7 +147,7 @@ static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit pcf50633_bl_remove(struct platform_device *pdev)
+static int pcf50633_bl_remove(struct platform_device *pdev)
 {
 	struct pcf50633_bl *pcf_bl = platform_get_drvdata(pdev);
 
@@ -158,7 +160,7 @@ static int __devexit pcf50633_bl_remove(struct platform_device *pdev)
 
 static struct platform_driver pcf50633_bl_driver = {
 	.probe =	pcf50633_bl_probe,
-	.remove =	__devexit_p(pcf50633_bl_remove),
+	.remove =	pcf50633_bl_remove,
 	.driver = {
 		.name = "pcf50633-backlight",
 	},
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
index ca4f5d7..17a6b83 100644
--- a/drivers/video/backlight/platform_lcd.c
+++ b/drivers/video/backlight/platform_lcd.c
@@ -27,7 +27,7 @@ struct platform_lcd {
 	struct plat_lcd_data	*pdata;
 
 	unsigned int		 power;
-	unsigned int		 suspended : 1;
+	unsigned int		 suspended:1;
 };
 
 static inline struct platform_lcd *to_our_lcd(struct lcd_device *lcd)
@@ -73,7 +73,7 @@ static struct lcd_ops platform_lcd_ops = {
 	.check_fb	= platform_lcd_match,
 };
 
-static int __devinit platform_lcd_probe(struct platform_device *pdev)
+static int platform_lcd_probe(struct platform_device *pdev)
 {
 	struct plat_lcd_data *pdata;
 	struct platform_lcd *plcd;
@@ -112,7 +112,7 @@ static int __devinit platform_lcd_probe(struct platform_device *pdev)
 	return err;
 }
 
-static int __devexit platform_lcd_remove(struct platform_device *pdev)
+static int platform_lcd_remove(struct platform_device *pdev)
 {
 	struct platform_lcd *plcd = platform_get_drvdata(pdev);
 
@@ -164,7 +164,7 @@ static struct platform_driver platform_lcd_driver = {
 		.of_match_table = of_match_ptr(platform_lcd_of_match),
 	},
 	.probe		= platform_lcd_probe,
-	.remove		= __devexit_p(platform_lcd_remove),
+	.remove		= platform_lcd_remove,
 };
 
 module_platform_driver(platform_lcd_driver);
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
index 6437ae4..3e1c113 100644
--- a/drivers/video/backlight/s6e63m0.c
+++ b/drivers/video/backlight/s6e63m0.c
@@ -733,7 +733,7 @@ static ssize_t s6e63m0_sysfs_show_gamma_table(struct device *dev,
 static DEVICE_ATTR(gamma_table, 0444,
 		s6e63m0_sysfs_show_gamma_table, NULL);
 
-static int __devinit s6e63m0_probe(struct spi_device *spi)
+static int s6e63m0_probe(struct spi_device *spi)
 {
 	int ret = 0;
 	struct s6e63m0 *lcd = NULL;
@@ -757,7 +757,7 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
 	lcd->spi = spi;
 	lcd->dev = &spi->dev;
 
-	lcd->lcd_pd = (struct lcd_platform_data *)spi->dev.platform_data;
+	lcd->lcd_pd = spi->dev.platform_data;
 	if (!lcd->lcd_pd) {
 		dev_err(&spi->dev, "platform data is NULL.\n");
 		return -EFAULT;
@@ -825,7 +825,7 @@ out_lcd_unregister:
 	return ret;
 }
 
-static int __devexit s6e63m0_remove(struct spi_device *spi)
+static int s6e63m0_remove(struct spi_device *spi)
 {
 	struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev);
 
@@ -897,7 +897,7 @@ static struct spi_driver s6e63m0_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= s6e63m0_probe,
-	.remove		= __devexit_p(s6e63m0_remove),
+	.remove		= s6e63m0_remove,
 	.shutdown	= s6e63m0_shutdown,
 	.suspend	= s6e63m0_suspend,
 	.resume		= s6e63m0_resume,
diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c
index 02444d0..ad2325f 100644
--- a/drivers/video/backlight/tdo24m.c
+++ b/drivers/video/backlight/tdo24m.c
@@ -2,7 +2,7 @@
  * tdo24m - SPI-based drivers for Toppoly TDO24M series LCD panels
  *
  * Copyright (C) 2008 Marvell International Ltd.
- * 	Eric Miao <eric.miao@marvell.com>
+ *	Eric Miao <eric.miao@marvell.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -47,7 +47,7 @@ struct tdo24m {
 			((x1) << 9) | 0x100 | (x2))
 #define CMD_NULL	(-1)
 
-static uint32_t lcd_panel_reset[] = {
+static const uint32_t lcd_panel_reset[] = {
 	CMD0(0x1), /* reset */
 	CMD0(0x0), /* nop */
 	CMD0(0x0), /* nop */
@@ -55,7 +55,7 @@ static uint32_t lcd_panel_reset[] = {
 	CMD_NULL,
 };
 
-static uint32_t lcd_panel_on[] = {
+static const uint32_t lcd_panel_on[] = {
 	CMD0(0x29),		/* Display ON */
 	CMD2(0xB8, 0xFF, 0xF9),	/* Output Control */
 	CMD0(0x11),		/* Sleep out */
@@ -63,7 +63,7 @@ static uint32_t lcd_panel_on[] = {
 	CMD_NULL,
 };
 
-static uint32_t lcd_panel_off[] = {
+static const uint32_t lcd_panel_off[] = {
 	CMD0(0x28),		/* Display OFF */
 	CMD2(0xB8, 0x80, 0x02),	/* Output Control */
 	CMD0(0x10),		/* Sleep in */
@@ -71,7 +71,7 @@ static uint32_t lcd_panel_off[] = {
 	CMD_NULL,
 };
 
-static uint32_t lcd_vga_pass_through_tdo24m[] = {
+static const uint32_t lcd_vga_pass_through_tdo24m[] = {
 	CMD1(0xB0, 0x16),
 	CMD1(0xBC, 0x80),
 	CMD1(0xE1, 0x00),
@@ -80,7 +80,7 @@ static uint32_t lcd_vga_pass_through_tdo24m[] = {
 	CMD_NULL,
 };
 
-static uint32_t lcd_qvga_pass_through_tdo24m[] = {
+static const uint32_t lcd_qvga_pass_through_tdo24m[] = {
 	CMD1(0xB0, 0x16),
 	CMD1(0xBC, 0x81),
 	CMD1(0xE1, 0x00),
@@ -89,8 +89,8 @@ static uint32_t lcd_qvga_pass_through_tdo24m[] = {
 	CMD_NULL,
 };
 
-static uint32_t lcd_vga_transfer_tdo24m[] = {
-	CMD1(0xcf, 0x02), 	/* Blanking period control (1) */
+static const uint32_t lcd_vga_transfer_tdo24m[] = {
+	CMD1(0xcf, 0x02),	/* Blanking period control (1) */
 	CMD2(0xd0, 0x08, 0x04),	/* Blanking period control (2) */
 	CMD1(0xd1, 0x01),	/* CKV timing control on/off */
 	CMD2(0xd2, 0x14, 0x00),	/* CKV 1,2 timing control */
@@ -102,7 +102,7 @@ static uint32_t lcd_vga_transfer_tdo24m[] = {
 	CMD_NULL,
 };
 
-static uint32_t lcd_qvga_transfer[] = {
+static const uint32_t lcd_qvga_transfer[] = {
 	CMD1(0xd6, 0x02),	/* Blanking period control (1) */
 	CMD2(0xd7, 0x08, 0x04),	/* Blanking period control (2) */
 	CMD1(0xd8, 0x01),	/* CKV timing control on/off */
@@ -115,7 +115,7 @@ static uint32_t lcd_qvga_transfer[] = {
 	CMD_NULL,
 };
 
-static uint32_t lcd_vga_pass_through_tdo35s[] = {
+static const uint32_t lcd_vga_pass_through_tdo35s[] = {
 	CMD1(0xB0, 0x16),
 	CMD1(0xBC, 0x80),
 	CMD1(0xE1, 0x00),
@@ -123,7 +123,7 @@ static uint32_t lcd_vga_pass_through_tdo35s[] = {
 	CMD_NULL,
 };
 
-static uint32_t lcd_qvga_pass_through_tdo35s[] = {
+static const uint32_t lcd_qvga_pass_through_tdo35s[] = {
 	CMD1(0xB0, 0x16),
 	CMD1(0xBC, 0x81),
 	CMD1(0xE1, 0x00),
@@ -131,8 +131,8 @@ static uint32_t lcd_qvga_pass_through_tdo35s[] = {
 	CMD_NULL,
 };
 
-static uint32_t lcd_vga_transfer_tdo35s[] = {
-	CMD1(0xcf, 0x02), 	/* Blanking period control (1) */
+static const uint32_t lcd_vga_transfer_tdo35s[] = {
+	CMD1(0xcf, 0x02),	/* Blanking period control (1) */
 	CMD2(0xd0, 0x08, 0x04),	/* Blanking period control (2) */
 	CMD1(0xd1, 0x01),	/* CKV timing control on/off */
 	CMD2(0xd2, 0x00, 0x1e),	/* CKV 1,2 timing control */
@@ -144,7 +144,7 @@ static uint32_t lcd_vga_transfer_tdo35s[] = {
 	CMD_NULL,
 };
 
-static uint32_t lcd_panel_config[] = {
+static const uint32_t lcd_panel_config[] = {
 	CMD2(0xb8, 0xff, 0xf9),	/* Output control */
 	CMD0(0x11),		/* sleep out */
 	CMD1(0xba, 0x01),	/* Display mode (1) */
@@ -175,10 +175,11 @@ static uint32_t lcd_panel_config[] = {
 	CMD_NULL,
 };
 
-static int tdo24m_writes(struct tdo24m *lcd, uint32_t *array)
+static int tdo24m_writes(struct tdo24m *lcd, const uint32_t *array)
 {
 	struct spi_transfer *x = &lcd->xfer;
-	uint32_t data, *p = array;
+	const uint32_t *p = array;
+	uint32_t data;
 	int nparams, err = 0;
 
 	for (; *p != CMD_NULL; p++) {
@@ -328,7 +329,7 @@ static struct lcd_ops tdo24m_ops = {
 	.set_mode	= tdo24m_set_mode,
 };
 
-static int __devinit tdo24m_probe(struct spi_device *spi)
+static int tdo24m_probe(struct spi_device *spi)
 {
 	struct tdo24m *lcd;
 	struct spi_message *m;
@@ -401,7 +402,7 @@ out_unregister:
 	return err;
 }
 
-static int __devexit tdo24m_remove(struct spi_device *spi)
+static int tdo24m_remove(struct spi_device *spi)
 {
 	struct tdo24m *lcd = dev_get_drvdata(&spi->dev);
 
@@ -444,7 +445,7 @@ static struct spi_driver tdo24m_driver = {
 		.owner		= THIS_MODULE,
 	},
 	.probe		= tdo24m_probe,
-	.remove		= __devexit_p(tdo24m_remove),
+	.remove		= tdo24m_remove,
 	.shutdown	= tdo24m_shutdown,
 	.suspend	= tdo24m_suspend,
 	.resume		= tdo24m_resume,
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
index 49342e1..9ee9054 100644
--- a/drivers/video/backlight/tosa_bl.c
+++ b/drivers/video/backlight/tosa_bl.c
@@ -78,7 +78,7 @@ static const struct backlight_ops bl_ops = {
 	.update_status		= tosa_bl_update_status,
 };
 
-static int __devinit tosa_bl_probe(struct i2c_client *client,
+static int tosa_bl_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	struct backlight_properties props;
@@ -90,16 +90,15 @@ static int __devinit tosa_bl_probe(struct i2c_client *client,
 	if (!data)
 		return -ENOMEM;
 
-	data->comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj;
+	data->comadj = sharpsl_param.comadj == -1 ?
+			COMADJ_DEFAULT : sharpsl_param.comadj;
 
-	ret = devm_gpio_request(&client->dev, TOSA_GPIO_BL_C20MA, "backlight");
+	ret = devm_gpio_request_one(&client->dev, TOSA_GPIO_BL_C20MA,
+				GPIOF_OUT_INIT_LOW, "backlight");
 	if (ret) {
 		dev_dbg(&data->bl->dev, "Unable to request gpio!\n");
 		return ret;
 	}
-	ret = gpio_direction_output(TOSA_GPIO_BL_C20MA, 0);
-	if (ret)
-		return ret;
 
 	i2c_set_clientdata(client, data);
 	data->i2c = client;
@@ -126,7 +125,7 @@ err_reg:
 	return ret;
 }
 
-static int __devexit tosa_bl_remove(struct i2c_client *client)
+static int tosa_bl_remove(struct i2c_client *client)
 {
 	struct tosa_bl_data *data = i2c_get_clientdata(client);
 
@@ -163,14 +162,13 @@ static const struct i2c_device_id tosa_bl_id[] = {
 	{ },
 };
 
-
 static struct i2c_driver tosa_bl_driver = {
 	.driver = {
 		.name		= "tosa-bl",
 		.owner		= THIS_MODULE,
 	},
 	.probe		= tosa_bl_probe,
-	.remove		= __devexit_p(tosa_bl_remove),
+	.remove		= tosa_bl_remove,
 	.suspend	= tosa_bl_suspend,
 	.resume		= tosa_bl_resume,
 	.id_table	= tosa_bl_id,
diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c
index 33047a66..96bae94 100644
--- a/drivers/video/backlight/tosa_lcd.c
+++ b/drivers/video/backlight/tosa_lcd.c
@@ -63,7 +63,7 @@ static int tosa_tg_send(struct spi_device *spi, int adrs, uint8_t data)
 int tosa_bl_enable(struct spi_device *spi, int enable)
 {
 	/* bl_enable GP04=1 otherwise GP04=0*/
-	return tosa_tg_send(spi, TG_GPODR2, enable? 0x01 : 0x00);
+	return tosa_tg_send(spi, TG_GPODR2, enable ? 0x01 : 0x00);
 }
 EXPORT_SYMBOL(tosa_bl_enable);
 
@@ -91,15 +91,17 @@ static void tosa_lcd_tg_on(struct tosa_lcd_data *data)
 	tosa_tg_send(spi, TG_PNLCTL, value);
 
 	/* TG LCD pannel power up */
-	tosa_tg_send(spi, TG_PINICTL,0x4);
+	tosa_tg_send(spi, TG_PINICTL, 0x4);
 	mdelay(50);
 
 	/* TG LCD GVSS */
-	tosa_tg_send(spi, TG_PINICTL,0x0);
+	tosa_tg_send(spi, TG_PINICTL, 0x0);
 
 	if (!data->i2c) {
-		/* after the pannel is powered up the first time, we can access the i2c bus */
-		/* so probe for the DAC */
+		/*
+		 * after the pannel is powered up the first time,
+		 * we can access the i2c bus so probe for the DAC
+		 */
 		struct i2c_adapter *adap = i2c_get_adapter(0);
 		struct i2c_board_info info = {
 			.type	= "tosa-bl",
@@ -115,11 +117,11 @@ static void tosa_lcd_tg_off(struct tosa_lcd_data *data)
 	struct spi_device *spi = data->spi;
 
 	/* TG LCD VHSA off */
-	tosa_tg_send(spi, TG_PINICTL,0x4);
+	tosa_tg_send(spi, TG_PINICTL, 0x4);
 	mdelay(50);
 
 	/* TG LCD signal off */
-	tosa_tg_send(spi, TG_PINICTL,0x6);
+	tosa_tg_send(spi, TG_PINICTL, 0x6);
 	mdelay(50);
 
 	/* TG Off */
@@ -169,7 +171,7 @@ static struct lcd_ops tosa_lcd_ops = {
 	.set_mode = tosa_lcd_set_mode,
 };
 
-static int __devinit tosa_lcd_probe(struct spi_device *spi)
+static int tosa_lcd_probe(struct spi_device *spi)
 {
 	int ret;
 	struct tosa_lcd_data *data;
@@ -193,17 +195,13 @@ static int __devinit tosa_lcd_probe(struct spi_device *spi)
 	data->spi = spi;
 	dev_set_drvdata(&spi->dev, data);
 
-	ret = devm_gpio_request(&spi->dev, TOSA_GPIO_TG_ON, "tg #pwr");
+	ret = devm_gpio_request_one(&spi->dev, TOSA_GPIO_TG_ON,
+				GPIOF_OUT_INIT_LOW, "tg #pwr");
 	if (ret < 0)
 		goto err_gpio_tg;
 
 	mdelay(60);
 
-	ret = gpio_direction_output(TOSA_GPIO_TG_ON, 0);
-	if (ret < 0)
-		goto err_gpio_tg;
-
-	mdelay(60);
 	tosa_lcd_tg_init(data);
 
 	tosa_lcd_tg_on(data);
@@ -226,7 +224,7 @@ err_gpio_tg:
 	return ret;
 }
 
-static int __devexit tosa_lcd_remove(struct spi_device *spi)
+static int tosa_lcd_remove(struct spi_device *spi)
 {
 	struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev);
 
@@ -275,7 +273,7 @@ static struct spi_driver tosa_lcd_driver = {
 		.owner		= THIS_MODULE,
 	},
 	.probe		= tosa_lcd_probe,
-	.remove		= __devexit_p(tosa_lcd_remove),
+	.remove		= tosa_lcd_remove,
 	.suspend	= tosa_lcd_suspend,
 	.resume		= tosa_lcd_resume,
 };
diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c
index b617fae..45e81b4 100644
--- a/drivers/video/backlight/vgg2432a4.c
+++ b/drivers/video/backlight/vgg2432a4.c
@@ -26,7 +26,7 @@
 
 /* Device initialisation sequences */
 
-static struct ili9320_reg vgg_init1[] = {
+static const struct ili9320_reg vgg_init1[] = {
 	{
 		.address = ILI9320_POWER1,
 		.value	 = ILI9320_POWER1_AP(0) | ILI9320_POWER1_BT(0),
@@ -43,7 +43,7 @@ static struct ili9320_reg vgg_init1[] = {
 	},
 };
 
-static struct ili9320_reg vgg_init2[] = {
+static const struct ili9320_reg vgg_init2[] = {
 	{
 		.address = ILI9320_POWER1,
 		.value   = (ILI9320_POWER1_AP(3) | ILI9320_POWER1_APE |
@@ -54,7 +54,7 @@ static struct ili9320_reg vgg_init2[] = {
 	}
 };
 
-static struct ili9320_reg vgg_gamma[] = {
+static const struct ili9320_reg vgg_gamma[] = {
 	{
 		.address = ILI9320_GAMMA1,
 		.value	 = 0x0000,
@@ -89,7 +89,7 @@ static struct ili9320_reg vgg_gamma[] = {
 
 };
 
-static struct ili9320_reg vgg_init0[] = {
+static const struct ili9320_reg vgg_init0[] = {
 	[0]	= {
 		/* set direction and scan mode gate */
 		.address = ILI9320_DRIVER,
@@ -217,7 +217,7 @@ static int vgg2432a4_resume(struct spi_device *spi)
 }
 #else
 #define vgg2432a4_suspend	NULL
-#define vgg2432a4_resume 	NULL
+#define vgg2432a4_resume	NULL
 #endif
 
 static struct ili9320_client vgg2432a4_client = {
@@ -227,7 +227,7 @@ static struct ili9320_client vgg2432a4_client = {
 
 /* Device probe */
 
-static int __devinit vgg2432a4_probe(struct spi_device *spi)
+static int vgg2432a4_probe(struct spi_device *spi)
 {
 	int ret;
 
@@ -240,7 +240,7 @@ static int __devinit vgg2432a4_probe(struct spi_device *spi)
 	return 0;
 }
 
-static int __devexit vgg2432a4_remove(struct spi_device *spi)
+static int vgg2432a4_remove(struct spi_device *spi)
 {
 	return ili9320_remove(dev_get_drvdata(&spi->dev));
 }
@@ -256,7 +256,7 @@ static struct spi_driver vgg2432a4_driver = {
 		.owner		= THIS_MODULE,
 	},
 	.probe		= vgg2432a4_probe,
-	.remove		= __devexit_p(vgg2432a4_remove),
+	.remove		= vgg2432a4_remove,
 	.shutdown	= vgg2432a4_shutdown,
 	.suspend	= vgg2432a4_suspend,
 	.resume		= vgg2432a4_resume,
diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c
index f994c8b..63ecdf8 100644
--- a/drivers/video/clps711xfb.c
+++ b/drivers/video/clps711xfb.c
@@ -22,19 +22,15 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/fb.h>
 #include <linux/init.h>
-#include <linux/proc_fs.h>
 #include <linux/delay.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <linux/uaccess.h>
 
-#include <mach/syspld.h>
-
 struct fb_info	*cfb;
 
 #define CMAP_MAX_SIZE	16
@@ -162,44 +158,12 @@ clps7111fb_set_par(struct fb_info *info)
 
 static int clps7111fb_blank(int blank, struct fb_info *info)
 {
-    	if (blank) {
-		if (machine_is_edb7211()) {
-			/* Turn off the LCD backlight. */
-			clps_writeb(clps_readb(PDDR) & ~EDB_PD3_LCDBL, PDDR);
-
-			/* Power off the LCD DC-DC converter. */
-			clps_writeb(clps_readb(PDDR) & ~EDB_PD1_LCD_DC_DC_EN, PDDR);
-
-			/* Delay for a little while (half a second). */
-			udelay(100);
-
-			/* Power off the LCD panel. */
-			clps_writeb(clps_readb(PDDR) & ~EDB_PD2_LCDEN, PDDR);
-
-			/* Power off the LCD controller. */
-			clps_writel(clps_readl(SYSCON1) & ~SYSCON1_LCDEN, 
-					SYSCON1);
-		}
-	} else {
-		if (machine_is_edb7211()) {
-			/* Power up the LCD controller. */
-			clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN,
-					SYSCON1);
-
-			/* Power up the LCD panel. */
-			clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
-
-			/* Delay for a little while. */
-			udelay(100);
+	/* Enable/Disable LCD controller. */
+	if (blank)
+		clps_writel(clps_readl(SYSCON1) & ~SYSCON1_LCDEN, SYSCON1);
+	else
+		clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN, SYSCON1);
 
-			/* Power up the LCD DC-DC converter. */
-			clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN,
-					PDDR);
-
-			/* Turn on the LCD backlight. */
-			clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
-		}
-	}
 	return 0;
 }
 
@@ -214,63 +178,7 @@ static struct fb_ops clps7111fb_ops = {
 	.fb_imageblit	= cfb_imageblit,
 };
 
-static int backlight_proc_show(struct seq_file *m, void *v)
-{
-	if (machine_is_edb7211()) {
-		seq_printf(m, "%d\n",
-				(clps_readb(PDDR) & EDB_PD3_LCDBL) ? 1 : 0);
-	}
-
-	return 0;
-}
-
-static int backlight_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, backlight_proc_show, NULL);
-}
-
-static ssize_t backlight_proc_write(struct file *file, const char *buffer,
-				    size_t count, loff_t *pos)
-{
-	unsigned char char_value;
-	int value;
-
-	if (count < 1) {
-		return -EINVAL;
-	}
-
-	if (copy_from_user(&char_value, buffer, 1)) 
-		return -EFAULT;
-
-	value = char_value - '0';
-
-	if (machine_is_edb7211()) {
-		unsigned char port_d;
-
-		port_d = clps_readb(PDDR);
-
-		if (value) {
-			port_d |= EDB_PD3_LCDBL;
-		} else {
-			port_d &= ~EDB_PD3_LCDBL;
-		}
-
-		clps_writeb(port_d, PDDR);
-	}
-
-	return count;
-}
-
-static const struct file_operations backlight_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= backlight_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-	.write		= backlight_proc_write,
-};
-
-static void __init clps711x_guess_lcd_params(struct fb_info *info)
+static void __devinit clps711x_guess_lcd_params(struct fb_info *info)
 {
 	unsigned int lcdcon, syscon, size;
 	unsigned long phys_base = PAGE_OFFSET;
@@ -358,7 +266,7 @@ static void __init clps711x_guess_lcd_params(struct fb_info *info)
 	info->fix.type       = FB_TYPE_PACKED_PIXELS;
 }
 
-int __init clps711xfb_init(void)
+static int __devinit clps711x_fb_probe(struct platform_device *pdev)
 {
 	int err = -ENOMEM;
 
@@ -378,55 +286,29 @@ int __init clps711xfb_init(void)
 
 	fb_alloc_cmap(&cfb->cmap, CMAP_MAX_SIZE, 0);
 
-	if (!proc_create("backlight", 0444, NULL, &backlight_proc_fops)) {
-		printk("Couldn't create the /proc entry for the backlight.\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * Power up the LCD
-	 */
-	if (machine_is_p720t()) {
-		PLD_LCDEN = PLD_LCDEN_EN;
-		PLD_PWR |= (PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
-	}
-
-	if (machine_is_edb7211()) {
-		/* Power up the LCD panel. */
-		clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
-
-		/* Delay for a little while. */
-		udelay(100);
-
-		/* Power up the LCD DC-DC converter. */
-		clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN, PDDR);
-
-		/* Turn on the LCD backlight. */
-		clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
-	}
-
 	err = register_framebuffer(cfb);
 
 out:	return err;
 }
 
-static void __exit clps711xfb_exit(void)
+static int __devexit clps711x_fb_remove(struct platform_device *pdev)
 {
 	unregister_framebuffer(cfb);
 	kfree(cfb);
 
-	/*
-	 * Power down the LCD
-	 */
-	if (machine_is_p720t()) {
-		PLD_LCDEN = 0;
-		PLD_PWR &= ~(PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
-	}
+	return 0;
 }
 
-module_init(clps711xfb_init);
-module_exit(clps711xfb_exit);
+static struct platform_driver clps711x_fb_driver = {
+	.driver	= {
+		.name	= "video-clps711x",
+		.owner	= THIS_MODULE,
+	},
+	.probe	= clps711x_fb_probe,
+	.remove	= __devexit_p(clps711x_fb_remove),
+};
+module_platform_driver(clps711x_fb_driver);
 
 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-MODULE_DESCRIPTION("CLPS711x framebuffer driver");
+MODULE_DESCRIPTION("CLPS711X framebuffer driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c
index 25f835b..46dd8f5 100644
--- a/drivers/video/console/softcursor.c
+++ b/drivers/video/console/softcursor.c
@@ -35,8 +35,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
 	dsize = s_pitch * cursor->image.height;
 
 	if (dsize + sizeof(struct fb_image) != ops->cursor_size) {
-		if (ops->cursor_src != NULL)
-			kfree(ops->cursor_src);
+		kfree(ops->cursor_src);
 		ops->cursor_size = dsize + sizeof(struct fb_image);
 
 		ops->cursor_src = kmalloc(ops->cursor_size, GFP_ATOMIC);
diff --git a/drivers/video/gxt4500.c b/drivers/video/gxt4500.c
index 0e9afa4..4bdea6e 100644
--- a/drivers/video/gxt4500.c
+++ b/drivers/video/gxt4500.c
@@ -1,5 +1,6 @@
 /*
- * Frame buffer device for IBM GXT4500P and GXT6000P display adaptors
+ * Frame buffer device for IBM GXT4500P/6500P and GXT4000P/6000P
+ * display adaptors
  *
  * Copyright (C) 2006 Paul Mackerras, IBM Corp. <paulus@samba.org>
  */
@@ -14,6 +15,8 @@
 #include <linux/string.h>
 
 #define PCI_DEVICE_ID_IBM_GXT4500P	0x21c
+#define PCI_DEVICE_ID_IBM_GXT6500P	0x21b
+#define PCI_DEVICE_ID_IBM_GXT4000P	0x16e
 #define PCI_DEVICE_ID_IBM_GXT6000P	0x170
 
 /* GXT4500P registers */
@@ -173,6 +176,8 @@ static const struct fb_videomode defaultmode __devinitconst = {
 /* List of supported cards */
 enum gxt_cards {
 	GXT4500P,
+	GXT6500P,
+	GXT4000P,
 	GXT6000P
 };
 
@@ -182,6 +187,8 @@ static const struct cardinfo {
 	const char *cardname;
 } cardinfo[] = {
 	[GXT4500P] = { .refclk_ps = 9259, .cardname = "IBM GXT4500P" },
+	[GXT6500P] = { .refclk_ps = 9259, .cardname = "IBM GXT6500P" },
+	[GXT4000P] = { .refclk_ps = 40000, .cardname = "IBM GXT4000P" },
 	[GXT6000P] = { .refclk_ps = 40000, .cardname = "IBM GXT6000P" },
 };
 
@@ -736,6 +743,10 @@ static void __devexit gxt4500_remove(struct pci_dev *pdev)
 static const struct pci_device_id gxt4500_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT4500P),
 	  .driver_data = GXT4500P },
+	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT6500P),
+	  .driver_data = GXT6500P },
+	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT4000P),
+	  .driver_data = GXT4000P },
 	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT6000P),
 	  .driver_data = GXT6000P },
 	{ 0 }
@@ -768,7 +779,7 @@ static void __exit gxt4500_exit(void)
 module_exit(gxt4500_exit);
 
 MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
-MODULE_DESCRIPTION("FBDev driver for IBM GXT4500P/6000P");
+MODULE_DESCRIPTION("FBDev driver for IBM GXT4500P/6500P and GXT4000P/6000P");
 MODULE_LICENSE("GPL");
 module_param(mode_option, charp, 0);
 MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index cf2688d..e501dbc 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -33,7 +33,6 @@
 #include <linux/math64.h>
 
 #include <linux/platform_data/video-imxfb.h>
-#include <mach/hardware.h>
 
 /*
  * Complain if VAR is out of range.
@@ -53,8 +52,8 @@
 #define LCDC_SIZE	0x04
 #define SIZE_XMAX(x)	((((x) >> 4) & 0x3f) << 20)
 
-#define YMAX_MASK       (cpu_is_mx1() ? 0x1ff : 0x3ff)
-#define SIZE_YMAX(y)	((y) & YMAX_MASK)
+#define YMAX_MASK_IMX1	0x1ff
+#define YMAX_MASK_IMX21	0x3ff
 
 #define LCDC_VPW	0x08
 #define VPW_VPW(x)	((x) & 0x3ff)
@@ -128,12 +127,18 @@ struct imxfb_rgb {
 	struct fb_bitfield	transp;
 };
 
+enum imxfb_type {
+	IMX1_FB,
+	IMX21_FB,
+};
+
 struct imxfb_info {
 	struct platform_device  *pdev;
 	void __iomem		*regs;
 	struct clk		*clk_ipg;
 	struct clk		*clk_ahb;
 	struct clk		*clk_per;
+	enum imxfb_type		devtype;
 
 	/*
 	 * These are the addresses we mapped
@@ -168,6 +173,24 @@ struct imxfb_info {
 	void (*backlight_power)(int);
 };
 
+static struct platform_device_id imxfb_devtype[] = {
+	{
+		.name = "imx1-fb",
+		.driver_data = IMX1_FB,
+	}, {
+		.name = "imx21-fb",
+		.driver_data = IMX21_FB,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, imxfb_devtype);
+
+static inline int is_imx1_fb(struct imxfb_info *fbi)
+{
+	return fbi->devtype == IMX1_FB;
+}
+
 #define IMX_NAME	"IMX"
 
 /*
@@ -366,7 +389,7 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 		break;
 	case 16:
 	default:
-		if (cpu_is_mx1())
+		if (is_imx1_fb(fbi))
 			pcr |= PCR_BPIX_12;
 		else
 			pcr |= PCR_BPIX_16;
@@ -596,6 +619,7 @@ static struct fb_ops imxfb_ops = {
 static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
 	struct imxfb_info *fbi = info->par;
+	u32 ymax_mask = is_imx1_fb(fbi) ? YMAX_MASK_IMX1 : YMAX_MASK_IMX21;
 
 	pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
 		var->xres, var->hsync_len,
@@ -617,7 +641,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
 	if (var->right_margin > 255)
 		printk(KERN_ERR "%s: invalid right_margin %d\n",
 			info->fix.id, var->right_margin);
-	if (var->yres < 1 || var->yres > YMAX_MASK)
+	if (var->yres < 1 || var->yres > ymax_mask)
 		printk(KERN_ERR "%s: invalid yres %d\n",
 			info->fix.id, var->yres);
 	if (var->vsync_len > 100)
@@ -645,7 +669,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
 		VCR_V_WAIT_2(var->upper_margin),
 		fbi->regs + LCDC_VCR);
 
-	writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres),
+	writel(SIZE_XMAX(var->xres) | (var->yres & ymax_mask),
 			fbi->regs + LCDC_SIZE);
 
 	writel(fbi->pcr, fbi->regs + LCDC_PCR);
@@ -765,6 +789,7 @@ static int __init imxfb_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	fbi = info->par;
+	fbi->devtype = pdev->id_entry->driver_data;
 
 	if (!fb_mode)
 		fb_mode = pdata->mode[0].mode.name;
@@ -939,6 +964,7 @@ static struct platform_driver imxfb_driver = {
 	.driver		= {
 		.name	= DRIVER_NAME,
 	},
+	.id_table	= imxfb_devtype,
 };
 
 static int imxfb_setup(void)
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index ce1d452..7368872 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -26,10 +26,9 @@
 #include <linux/console.h>
 #include <linux/clk.h>
 #include <linux/mutex.h>
+#include <linux/dma/ipu-dma.h>
 
 #include <linux/platform_data/dma-imx.h>
-#include <mach/hardware.h>
-#include <mach/ipu.h>
 #include <linux/platform_data/video-mx3fb.h>
 
 #include <asm/io.h>
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
index b38b1dd..2ee4232 100644
--- a/drivers/video/omap/lcd_inn1510.c
+++ b/drivers/video/omap/lcd_inn1510.c
@@ -23,7 +23,8 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
-#include <plat/fpga.h>
+#include <mach/hardware.h>
+
 #include "omapfb.h"
 
 static int innovator1510_panel_init(struct lcd_panel *panel,
@@ -38,13 +39,13 @@ static void innovator1510_panel_cleanup(struct lcd_panel *panel)
 
 static int innovator1510_panel_enable(struct lcd_panel *panel)
 {
-	fpga_write(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+	__raw_writeb(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
 	return 0;
 }
 
 static void innovator1510_panel_disable(struct lcd_panel *panel)
 {
-	fpga_write(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+	__raw_writeb(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
 }
 
 static unsigned long innovator1510_panel_get_caps(struct lcd_panel *panel)
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
index 7767338..c39d6e4 100644
--- a/drivers/video/omap/lcdc.c
+++ b/drivers/video/omap/lcdc.c
@@ -31,7 +31,7 @@
 #include <linux/gfp.h>
 
 #include <mach/lcdc.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 
 #include <asm/mach-types.h>
 
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index 4351c43..1b5ee8e 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -30,7 +30,7 @@
 #include <linux/uaccess.h>
 #include <linux/module.h>
 
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 
 #include "omapfb.h"
 #include "lcdc.h"
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
index f79c137..c510a44 100644
--- a/drivers/video/omap/sossi.c
+++ b/drivers/video/omap/sossi.c
@@ -25,7 +25,7 @@
 #include <linux/io.h>
 #include <linux/interrupt.h>
 
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
 
 #include "omapfb.h"
 #include "lcdc.h"
diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
index d877c36..346d67d 100644
--- a/drivers/video/omap2/Kconfig
+++ b/drivers/video/omap2/Kconfig
@@ -1,6 +1,3 @@
-config OMAP2_VRAM
-	bool
-
 config OMAP2_VRFB
 	bool
 
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
index 5ddef12..5ea7cb9 100644
--- a/drivers/video/omap2/Makefile
+++ b/drivers/video/omap2/Makefile
@@ -1,4 +1,3 @@
-obj-$(CONFIG_OMAP2_VRAM) += vram.o
 obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
 
 obj-$(CONFIG_OMAP2_DSS) += dss/
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index c835aa7..65eb76c 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -710,27 +710,6 @@ static void acx_panel_disable(struct omap_dss_device *dssdev)
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 
-static int acx_panel_suspend(struct omap_dss_device *dssdev)
-{
-	dev_dbg(&dssdev->dev, "%s\n", __func__);
-	acx_panel_power_off(dssdev);
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-	return 0;
-}
-
-static int acx_panel_resume(struct omap_dss_device *dssdev)
-{
-	int r;
-
-	dev_dbg(&dssdev->dev, "%s\n", __func__);
-	r = acx_panel_power_on(dssdev);
-	if (r)
-		return r;
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-	return 0;
-}
-
 static void acx_panel_set_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 {
@@ -752,8 +731,6 @@ static struct omap_dss_driver acx_panel_driver = {
 
 	.enable		= acx_panel_enable,
 	.disable	= acx_panel_disable,
-	.suspend	= acx_panel_suspend,
-	.resume		= acx_panel_resume,
 
 	.set_timings	= acx_panel_set_timings,
 	.check_timings	= acx_panel_check_timings,
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 88295c5..54ca8ae 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -688,40 +688,6 @@ static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
 	mutex_unlock(&drv_data->lock);
 }
 
-static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
-
-	mutex_lock(&drv_data->lock);
-
-	generic_dpi_panel_power_off(dssdev);
-
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-	mutex_unlock(&drv_data->lock);
-
-	return 0;
-}
-
-static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
-	int r;
-
-	mutex_lock(&drv_data->lock);
-
-	r = generic_dpi_panel_power_on(dssdev);
-	if (r)
-		goto err;
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-err:
-	mutex_unlock(&drv_data->lock);
-
-	return r;
-}
-
 static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 {
@@ -769,8 +735,6 @@ static struct omap_dss_driver dpi_driver = {
 
 	.enable		= generic_dpi_panel_enable,
 	.disable	= generic_dpi_panel_disable,
-	.suspend	= generic_dpi_panel_suspend,
-	.resume		= generic_dpi_panel_resume,
 
 	.set_timings	= generic_dpi_panel_set_timings,
 	.get_timings	= generic_dpi_panel_get_timings,
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
index 90c1cab..ace419b 100644
--- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
+++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
@@ -143,46 +143,12 @@ static void lb035q02_panel_disable(struct omap_dss_device *dssdev)
 	mutex_unlock(&ld->lock);
 }
 
-static int lb035q02_panel_suspend(struct omap_dss_device *dssdev)
-{
-	struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
-
-	mutex_lock(&ld->lock);
-
-	lb035q02_panel_power_off(dssdev);
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-	mutex_unlock(&ld->lock);
-	return 0;
-}
-
-static int lb035q02_panel_resume(struct omap_dss_device *dssdev)
-{
-	struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
-	int r;
-
-	mutex_lock(&ld->lock);
-
-	r = lb035q02_panel_power_on(dssdev);
-	if (r)
-		goto err;
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	mutex_unlock(&ld->lock);
-	return 0;
-err:
-	mutex_unlock(&ld->lock);
-	return r;
-}
-
 static struct omap_dss_driver lb035q02_driver = {
 	.probe		= lb035q02_panel_probe,
 	.remove		= lb035q02_panel_remove,
 
 	.enable		= lb035q02_panel_enable,
 	.disable	= lb035q02_panel_disable,
-	.suspend	= lb035q02_panel_suspend,
-	.resume		= lb035q02_panel_resume,
 
 	.driver         = {
 		.name   = "lgphilips_lb035q02_panel",
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
index 3fc5ad0..d1cb722 100644
--- a/drivers/video/omap2/displays/panel-n8x0.c
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -574,54 +574,6 @@ static void n8x0_panel_disable(struct omap_dss_device *dssdev)
 	mutex_unlock(&ddata->lock);
 }
 
-static int n8x0_panel_suspend(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = get_drv_data(dssdev);
-
-	dev_dbg(&dssdev->dev, "suspend\n");
-
-	mutex_lock(&ddata->lock);
-
-	rfbi_bus_lock();
-
-	n8x0_panel_power_off(dssdev);
-
-	rfbi_bus_unlock();
-
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-	mutex_unlock(&ddata->lock);
-
-	return 0;
-}
-
-static int n8x0_panel_resume(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = get_drv_data(dssdev);
-	int r;
-
-	dev_dbg(&dssdev->dev, "resume\n");
-
-	mutex_lock(&ddata->lock);
-
-	rfbi_bus_lock();
-
-	r = n8x0_panel_power_on(dssdev);
-
-	rfbi_bus_unlock();
-
-	if (r) {
-		mutex_unlock(&ddata->lock);
-		return r;
-	}
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	mutex_unlock(&ddata->lock);
-
-	return 0;
-}
-
 static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
 		u16 *xres, u16 *yres)
 {
@@ -683,8 +635,6 @@ static struct omap_dss_driver n8x0_panel_driver = {
 
 	.enable		= n8x0_panel_enable,
 	.disable	= n8x0_panel_disable,
-	.suspend	= n8x0_panel_suspend,
-	.resume		= n8x0_panel_resume,
 
 	.update		= n8x0_panel_update,
 	.sync		= n8x0_panel_sync,
@@ -702,18 +652,25 @@ static struct omap_dss_driver n8x0_panel_driver = {
 
 static int mipid_spi_probe(struct spi_device *spi)
 {
+	int r;
+
 	dev_dbg(&spi->dev, "mipid_spi_probe\n");
 
 	spi->mode = SPI_MODE_0;
 
 	s_drv_data.spidev = spi;
 
-	return 0;
+	r = omap_dss_register_driver(&n8x0_panel_driver);
+	if (r)
+		pr_err("n8x0_panel: dss driver registration failed\n");
+
+	return r;
 }
 
 static int mipid_spi_remove(struct spi_device *spi)
 {
 	dev_dbg(&spi->dev, "mipid_spi_remove\n");
+	omap_dss_unregister_driver(&n8x0_panel_driver);
 	return 0;
 }
 
@@ -725,34 +682,6 @@ static struct spi_driver mipid_spi_driver = {
 	.probe	= mipid_spi_probe,
 	.remove	= __devexit_p(mipid_spi_remove),
 };
+module_spi_driver(mipid_spi_driver);
 
-static int __init n8x0_panel_drv_init(void)
-{
-	int r;
-
-	r = spi_register_driver(&mipid_spi_driver);
-	if (r) {
-		pr_err("n8x0_panel: spi driver registration failed\n");
-		return r;
-	}
-
-	r = omap_dss_register_driver(&n8x0_panel_driver);
-	if (r) {
-		pr_err("n8x0_panel: dss driver registration failed\n");
-		spi_unregister_driver(&mipid_spi_driver);
-		return r;
-	}
-
-	return 0;
-}
-
-static void __exit n8x0_panel_drv_exit(void)
-{
-	spi_unregister_driver(&mipid_spi_driver);
-
-	omap_dss_unregister_driver(&n8x0_panel_driver);
-}
-
-module_init(n8x0_panel_drv_init);
-module_exit(n8x0_panel_drv_exit);
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
index 908fd26..2a79c28 100644
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -236,28 +236,6 @@ static void nec_8048_panel_disable(struct omap_dss_device *dssdev)
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 
-static int nec_8048_panel_suspend(struct omap_dss_device *dssdev)
-{
-	nec_8048_panel_power_off(dssdev);
-
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-	return 0;
-}
-
-static int nec_8048_panel_resume(struct omap_dss_device *dssdev)
-{
-	int r;
-
-	r = nec_8048_panel_power_on(dssdev);
-	if (r)
-		return r;
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	return 0;
-}
-
 static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev)
 {
 	return 16;
@@ -268,8 +246,6 @@ static struct omap_dss_driver nec_8048_driver = {
 	.remove			= nec_8048_panel_remove,
 	.enable			= nec_8048_panel_enable,
 	.disable		= nec_8048_panel_disable,
-	.suspend		= nec_8048_panel_suspend,
-	.resume			= nec_8048_panel_resume,
 	.get_recommended_bpp	= nec_8048_recommended_bpp,
 
 	.driver		= {
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c
index 9df8764..e3a6c19 100644
--- a/drivers/video/omap2/displays/panel-picodlp.c
+++ b/drivers/video/omap2/displays/panel-picodlp.c
@@ -503,47 +503,6 @@ static void picodlp_panel_disable(struct omap_dss_device *dssdev)
 	dev_dbg(&dssdev->dev, "disabling picodlp panel\n");
 }
 
-static int picodlp_panel_suspend(struct omap_dss_device *dssdev)
-{
-	struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
-
-	mutex_lock(&picod->lock);
-	/* Turn off DLP Power */
-	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
-		mutex_unlock(&picod->lock);
-		dev_err(&dssdev->dev, "unable to suspend picodlp panel,"
-					" panel is not ACTIVE\n");
-		return -EINVAL;
-	}
-
-	picodlp_panel_power_off(dssdev);
-
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-	mutex_unlock(&picod->lock);
-
-	dev_dbg(&dssdev->dev, "suspending picodlp panel\n");
-	return 0;
-}
-
-static int picodlp_panel_resume(struct omap_dss_device *dssdev)
-{
-	struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
-	int r;
-
-	mutex_lock(&picod->lock);
-	if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
-		mutex_unlock(&picod->lock);
-		dev_err(&dssdev->dev, "unable to resume picodlp panel,"
-			" panel is not ACTIVE\n");
-		return -EINVAL;
-	}
-
-	r = picodlp_panel_power_on(dssdev);
-	mutex_unlock(&picod->lock);
-	dev_dbg(&dssdev->dev, "resuming picodlp panel\n");
-	return r;
-}
-
 static void picodlp_get_resolution(struct omap_dss_device *dssdev,
 					u16 *xres, u16 *yres)
 {
@@ -560,9 +519,6 @@ static struct omap_dss_driver picodlp_driver = {
 
 	.get_resolution	= picodlp_get_resolution,
 
-	.suspend	= picodlp_panel_suspend,
-	.resume		= picodlp_panel_resume,
-
 	.driver		= {
 		.name	= "picodlp_panel",
 		.owner	= THIS_MODULE,
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
index 1ec3b27..cada8c6 100644
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -194,29 +194,12 @@ static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 
-static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
-{
-	sharp_ls_power_off(dssdev);
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-	return 0;
-}
-
-static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
-{
-	int r;
-	r = sharp_ls_power_on(dssdev);
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-	return r;
-}
-
 static struct omap_dss_driver sharp_ls_driver = {
 	.probe		= sharp_ls_panel_probe,
 	.remove		= __exit_p(sharp_ls_panel_remove),
 
 	.enable		= sharp_ls_panel_enable,
 	.disable	= sharp_ls_panel_disable,
-	.suspend	= sharp_ls_panel_suspend,
-	.resume		= sharp_ls_panel_resume,
 
 	.driver         = {
 		.name   = "sharp_ls_panel",
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index f2f6446..a32407a 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -1245,76 +1245,6 @@ static void taal_disable(struct omap_dss_device *dssdev)
 	mutex_unlock(&td->lock);
 }
 
-static int taal_suspend(struct omap_dss_device *dssdev)
-{
-	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-	int r;
-
-	dev_dbg(&dssdev->dev, "suspend\n");
-
-	mutex_lock(&td->lock);
-
-	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
-		r = -EINVAL;
-		goto err;
-	}
-
-	taal_cancel_ulps_work(dssdev);
-	taal_cancel_esd_work(dssdev);
-
-	dsi_bus_lock(dssdev);
-
-	r = taal_wake_up(dssdev);
-	if (!r)
-		taal_power_off(dssdev);
-
-	dsi_bus_unlock(dssdev);
-
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-	mutex_unlock(&td->lock);
-
-	return 0;
-err:
-	mutex_unlock(&td->lock);
-	return r;
-}
-
-static int taal_resume(struct omap_dss_device *dssdev)
-{
-	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-	int r;
-
-	dev_dbg(&dssdev->dev, "resume\n");
-
-	mutex_lock(&td->lock);
-
-	if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
-		r = -EINVAL;
-		goto err;
-	}
-
-	dsi_bus_lock(dssdev);
-
-	r = taal_power_on(dssdev);
-
-	dsi_bus_unlock(dssdev);
-
-	if (r) {
-		dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-	} else {
-		dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-		taal_queue_esd_work(dssdev);
-	}
-
-	mutex_unlock(&td->lock);
-
-	return r;
-err:
-	mutex_unlock(&td->lock);
-	return r;
-}
-
 static void taal_framedone_cb(int err, void *data)
 {
 	struct omap_dss_device *dssdev = data;
@@ -1818,8 +1748,6 @@ static struct omap_dss_driver taal_driver = {
 
 	.enable		= taal_enable,
 	.disable	= taal_disable,
-	.suspend	= taal_suspend,
-	.resume		= taal_resume,
 
 	.update		= taal_update,
 	.sync		= taal_sync,
diff --git a/drivers/video/omap2/displays/panel-tfp410.c b/drivers/video/omap2/displays/panel-tfp410.c
index 383811c..8281baa 100644
--- a/drivers/video/omap2/displays/panel-tfp410.c
+++ b/drivers/video/omap2/displays/panel-tfp410.c
@@ -189,37 +189,6 @@ static void tfp410_disable(struct omap_dss_device *dssdev)
 	mutex_unlock(&ddata->lock);
 }
 
-static int tfp410_suspend(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
-
-	mutex_lock(&ddata->lock);
-
-	tfp410_power_off(dssdev);
-
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-	mutex_unlock(&ddata->lock);
-
-	return 0;
-}
-
-static int tfp410_resume(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
-	int r;
-
-	mutex_lock(&ddata->lock);
-
-	r = tfp410_power_on(dssdev);
-	if (r == 0)
-		dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	mutex_unlock(&ddata->lock);
-
-	return r;
-}
-
 static void tfp410_set_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 {
@@ -355,8 +324,6 @@ static struct omap_dss_driver tfp410_driver = {
 
 	.enable		= tfp410_enable,
 	.disable	= tfp410_disable,
-	.suspend	= tfp410_suspend,
-	.resume		= tfp410_resume,
 
 	.set_timings	= tfp410_set_timings,
 	.get_timings	= tfp410_get_timings,
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index b5e6dbc..316b3da 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -401,24 +401,6 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev)
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 
-static int tpo_td043_suspend(struct omap_dss_device *dssdev)
-{
-	dev_dbg(&dssdev->dev, "suspend\n");
-
-	tpo_td043_disable_dss(dssdev);
-
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-	return 0;
-}
-
-static int tpo_td043_resume(struct omap_dss_device *dssdev)
-{
-	dev_dbg(&dssdev->dev, "resume\n");
-
-	return tpo_td043_enable_dss(dssdev);
-}
-
 static int tpo_td043_probe(struct omap_dss_device *dssdev)
 {
 	struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
@@ -500,8 +482,6 @@ static struct omap_dss_driver tpo_td043_driver = {
 
 	.enable		= tpo_td043_enable,
 	.disable	= tpo_td043_disable,
-	.suspend	= tpo_td043_suspend,
-	.resume		= tpo_td043_resume,
 	.set_mirror	= tpo_td043_set_hmirror,
 	.get_mirror	= tpo_td043_get_hmirror,
 
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 80f5390..cb0f145 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -1,33 +1,30 @@
 menuconfig OMAP2_DSS
         tristate "OMAP2+ Display Subsystem support"
-        depends on ARCH_OMAP2PLUS
         help
 	  OMAP2+ Display Subsystem support.
 
 if OMAP2_DSS
 
-config OMAP2_VRAM_SIZE
-	int "VRAM size (MB)"
-	range 0 32
-	default 0
+config OMAP2_DSS_DEBUG
+	bool "Debug support"
+	default n
 	help
-	  The amount of SDRAM to reserve at boot time for video RAM use.
-	  This VRAM will be used by omapfb and other drivers that need
-	  large continuous RAM area for video use.
+	  This enables printing of debug messages. Alternatively, debug messages
+	  can also be enabled by setting CONFIG_DYNAMIC_DEBUG and then setting
+	  appropriate flags in <debugfs>/dynamic_debug/control.
 
-	  You can also set this with "vram=<bytes>" kernel argument, or
-	  in the board file.
-
-config OMAP2_DSS_DEBUG_SUPPORT
-        bool "Debug support"
-	default y
+config OMAP2_DSS_DEBUGFS
+	bool "Debugfs filesystem support"
+	depends on DEBUG_FS
+	default n
 	help
-	  This enables debug messages. You need to enable printing
-	  with 'debug' module parameter.
+	  This enables debugfs for OMAPDSS at <debugfs>/omapdss. This enables
+	  querying about clock configuration and register configuration of dss,
+	  dispc, dsi, hdmi and rfbi.
 
 config OMAP2_DSS_COLLECT_IRQ_STATS
 	bool "Collect DSS IRQ statistics"
-	depends on OMAP2_DSS_DEBUG_SUPPORT
+	depends on OMAP2_DSS_DEBUGFS
 	default n
 	help
 	  Collect DSS IRQ statistics, printable via debugfs.
@@ -62,7 +59,6 @@ config OMAP2_DSS_VENC
 
 config OMAP4_DSS_HDMI
 	bool "HDMI support"
-	depends on ARCH_OMAP4
         default y
 	help
 	  HDMI Interface. This adds the High Definition Multimedia Interface.
@@ -70,11 +66,9 @@ config OMAP4_DSS_HDMI
 
 config OMAP4_DSS_HDMI_AUDIO
 	bool
-	depends on OMAP4_DSS_HDMI
 
 config OMAP2_DSS_SDI
 	bool "SDI support"
-	depends on ARCH_OMAP3
         default n
 	help
 	  SDI (Serial Display Interface) support.
@@ -84,7 +78,6 @@ config OMAP2_DSS_SDI
 
 config OMAP2_DSS_DSI
 	bool "DSI support"
-	depends on ARCH_OMAP3 || ARCH_OMAP4 || ARCH_OMAP5
         default n
 	help
 	  MIPI DSI (Display Serial Interface) support.
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index 4549869..4070191 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -8,3 +8,4 @@ omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
 omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
 omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
 				    hdmi_panel.o ti_hdmi_4xxx_ip.o
+ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 19d66f4..4a5cc5c 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -70,7 +70,6 @@ struct ovl_priv_data {
 	bool shadow_extra_info_dirty;
 
 	bool enabled;
-	enum omap_channel channel;
 	u32 fifo_low, fifo_high;
 
 	/*
@@ -414,8 +413,6 @@ static void wait_pending_extra_info_updates(void)
 	r = wait_for_completion_timeout(&extra_updated_completion, t);
 	if (r == 0)
 		DSSWARN("timeout in wait_pending_extra_info_updates\n");
-	else if (r < 0)
-		DSSERR("wait_pending_extra_info_updates failed: %d\n", r);
 }
 
 int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
@@ -573,7 +570,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
 	struct mgr_priv_data *mp;
 	int r;
 
-	DSSDBGF("%d", ovl->id);
+	DSSDBG("writing ovl %d regs", ovl->id);
 
 	if (!op->enabled || !op->info_dirty)
 		return;
@@ -608,7 +605,7 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	struct mgr_priv_data *mp;
 
-	DSSDBGF("%d", ovl->id);
+	DSSDBG("writing ovl %d regs extra", ovl->id);
 
 	if (!op->extra_info_dirty)
 		return;
@@ -617,7 +614,6 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
 	 * disabled */
 
 	dispc_ovl_enable(ovl->id, op->enabled);
-	dispc_ovl_set_channel_out(ovl->id, op->channel);
 	dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
 
 	mp = get_mgr_priv(ovl->manager);
@@ -632,7 +628,7 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	struct omap_overlay *ovl;
 
-	DSSDBGF("%d", mgr->id);
+	DSSDBG("writing mgr %d regs", mgr->id);
 
 	if (!mp->enabled)
 		return;
@@ -658,7 +654,7 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
 {
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 
-	DSSDBGF("%d", mgr->id);
+	DSSDBG("writing mgr %d regs extra", mgr->id);
 
 	if (!mp->extra_info_dirty)
 		return;
@@ -666,22 +662,8 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
 	dispc_mgr_set_timings(mgr->id, &mp->timings);
 
 	/* lcd_config parameters */
-	if (dss_mgr_is_lcd(mgr->id)) {
-		dispc_mgr_set_io_pad_mode(mp->lcd_config.io_pad_mode);
-
-		dispc_mgr_enable_stallmode(mgr->id, mp->lcd_config.stallmode);
-		dispc_mgr_enable_fifohandcheck(mgr->id,
-			mp->lcd_config.fifohandcheck);
-
-		dispc_mgr_set_clock_div(mgr->id, &mp->lcd_config.clock_info);
-
-		dispc_mgr_set_tft_data_lines(mgr->id,
-			mp->lcd_config.video_port_width);
-
-		dispc_lcd_enable_signal_polarity(mp->lcd_config.lcden_sig_polarity);
-
-		dispc_mgr_set_lcd_type_tft(mgr->id);
-	}
+	if (dss_mgr_is_lcd(mgr->id))
+		dispc_mgr_set_lcd_config(mgr->id, &mp->lcd_config);
 
 	mp->extra_info_dirty = false;
 	if (mp->updating)
@@ -786,9 +768,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
 	if (!dss_data.irq_enabled && need_isr())
 		dss_register_vsync_isr();
 
-	dispc_mgr_enable(mgr->id, true);
-
-	mgr_clear_shadow_dirty(mgr);
+	dispc_mgr_enable_sync(mgr->id);
 
 	spin_unlock_irqrestore(&data_lock, flags);
 }
@@ -845,7 +825,6 @@ static void dss_apply_irq_handler(void *data, u32 mask)
 	for (i = 0; i < num_mgrs; i++) {
 		struct omap_overlay_manager *mgr;
 		struct mgr_priv_data *mp;
-		bool was_updating;
 
 		mgr = omap_dss_get_overlay_manager(i);
 		mp = get_mgr_priv(mgr);
@@ -853,7 +832,6 @@ static void dss_apply_irq_handler(void *data, u32 mask)
 		if (!mp->enabled)
 			continue;
 
-		was_updating = mp->updating;
 		mp->updating = dispc_mgr_is_enabled(i);
 
 		if (!mgr_manual_update(mgr)) {
@@ -1035,10 +1013,13 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
 	if (!mgr_manual_update(mgr))
 		mp->updating = true;
 
+	if (!dss_data.irq_enabled && need_isr())
+		dss_register_vsync_isr();
+
 	spin_unlock_irqrestore(&data_lock, flags);
 
 	if (!mgr_manual_update(mgr))
-		dispc_mgr_enable(mgr->id, true);
+		dispc_mgr_enable_sync(mgr->id);
 
 out:
 	mutex_unlock(&apply_lock);
@@ -1063,7 +1044,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
 		goto out;
 
 	if (!mgr_manual_update(mgr))
-		dispc_mgr_enable(mgr->id, false);
+		dispc_mgr_disable_sync(mgr->id);
 
 	spin_lock_irqsave(&data_lock, flags);
 
@@ -1289,39 +1270,34 @@ int dss_ovl_set_manager(struct omap_overlay *ovl,
 		goto err;
 	}
 
+	r = dispc_runtime_get();
+	if (r)
+		goto err;
+
 	spin_lock_irqsave(&data_lock, flags);
 
 	if (op->enabled) {
 		spin_unlock_irqrestore(&data_lock, flags);
 		DSSERR("overlay has to be disabled to change the manager\n");
 		r = -EINVAL;
-		goto err;
+		goto err1;
 	}
 
-	op->channel = mgr->id;
-	op->extra_info_dirty = true;
+	dispc_ovl_set_channel_out(ovl->id, mgr->id);
 
 	ovl->manager = mgr;
 	list_add_tail(&ovl->list, &mgr->overlays);
 
 	spin_unlock_irqrestore(&data_lock, flags);
 
-	/* XXX: When there is an overlay on a DSI manual update display, and
-	 * the overlay is first disabled, then moved to tv, and enabled, we
-	 * seem to get SYNC_LOST_DIGIT error.
-	 *
-	 * Waiting doesn't seem to help, but updating the manual update display
-	 * after disabling the overlay seems to fix this. This hints that the
-	 * overlay is perhaps somehow tied to the LCD output until the output
-	 * is updated.
-	 *
-	 * Userspace workaround for this is to update the LCD after disabling
-	 * the overlay, but before moving the overlay to TV.
-	 */
+	dispc_runtime_put();
 
 	mutex_unlock(&apply_lock);
 
 	return 0;
+
+err1:
+	dispc_runtime_put();
 err:
 	mutex_unlock(&apply_lock);
 	return r;
@@ -1355,9 +1331,24 @@ int dss_ovl_unset_manager(struct omap_overlay *ovl)
 	/* wait for pending extra_info updates to ensure the ovl is disabled */
 	wait_pending_extra_info_updates();
 
+	/*
+	 * For a manual update display, there is no guarantee that the overlay
+	 * is really disabled in HW, we may need an extra update from this
+	 * manager before the configurations can go in. Return an error if the
+	 * overlay needed an update from the manager.
+	 *
+	 * TODO: Instead of returning an error, try to do a dummy manager update
+	 * here to disable the overlay in hardware. Use the *GATED fields in
+	 * the DISPC_CONFIG registers to do a dummy update.
+	 */
 	spin_lock_irqsave(&data_lock, flags);
 
-	op->channel = -1;
+	if (ovl_manual_update(ovl) && op->extra_info_dirty) {
+		spin_unlock_irqrestore(&data_lock, flags);
+		DSSERR("need an update to change the manager\n");
+		r = -EINVAL;
+		goto err;
+	}
 
 	ovl->manager = NULL;
 	list_del(&ovl->list);
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index b2af72d..b1a9ce1 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -53,15 +53,18 @@ static char *def_disp_name;
 module_param_named(def_disp, def_disp_name, charp, 0);
 MODULE_PARM_DESC(def_disp, "default display name");
 
-#ifdef DEBUG
-bool dss_debug;
-module_param_named(debug, dss_debug, bool, 0644);
-#endif
-
-const char *dss_get_default_display_name(void)
+const char *omapdss_get_default_display_name(void)
 {
 	return core.default_display_name;
 }
+EXPORT_SYMBOL(omapdss_get_default_display_name);
+
+enum omapdss_version omapdss_get_version(void)
+{
+	struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
+	return pdata->version;
+}
+EXPORT_SYMBOL(omapdss_get_version);
 
 /* REGULATORS */
 
@@ -122,7 +125,7 @@ void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask)
 {
 	struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
 
-	if (!board_data->dsi_enable_pads)
+	if (!board_data->dsi_disable_pads)
 		return;
 
 	return board_data->dsi_disable_pads(dsi_id, lane_mask);
@@ -138,7 +141,7 @@ int dss_set_min_bus_tput(struct device *dev, unsigned long tput)
 		return 0;
 }
 
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
 static int dss_debug_show(struct seq_file *s, void *unused)
 {
 	void (*func)(struct seq_file *) = s->private;
@@ -193,7 +196,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
 
 	return 0;
 }
-#else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
+#else /* CONFIG_OMAP2_DSS_DEBUGFS */
 static inline int dss_initialize_debugfs(void)
 {
 	return 0;
@@ -205,7 +208,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
 {
 	return 0;
 }
-#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
+#endif /* CONFIG_OMAP2_DSS_DEBUGFS */
 
 /* PLATFORM DEVICE */
 static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d)
@@ -237,7 +240,7 @@ static int __init omap_dss_probe(struct platform_device *pdev)
 
 	core.pdev = pdev;
 
-	dss_features_init();
+	dss_features_init(omapdss_get_version());
 
 	dss_apply_init();
 
@@ -507,6 +510,9 @@ static int __init omap_dss_bus_register(void)
 
 /* INIT */
 static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
+#ifdef CONFIG_OMAP2_DSS_DSI
+	dsi_init_platform_driver,
+#endif
 #ifdef CONFIG_OMAP2_DSS_DPI
 	dpi_init_platform_driver,
 #endif
@@ -519,15 +525,15 @@ static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
 #ifdef CONFIG_OMAP2_DSS_VENC
 	venc_init_platform_driver,
 #endif
-#ifdef CONFIG_OMAP2_DSS_DSI
-	dsi_init_platform_driver,
-#endif
 #ifdef CONFIG_OMAP4_DSS_HDMI
 	hdmi_init_platform_driver,
 #endif
 };
 
 static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
+#ifdef CONFIG_OMAP2_DSS_DSI
+	dsi_uninit_platform_driver,
+#endif
 #ifdef CONFIG_OMAP2_DSS_DPI
 	dpi_uninit_platform_driver,
 #endif
@@ -540,9 +546,6 @@ static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
 #ifdef CONFIG_OMAP2_DSS_VENC
 	venc_uninit_platform_driver,
 #endif
-#ifdef CONFIG_OMAP2_DSS_DSI
-	dsi_uninit_platform_driver,
-#endif
 #ifdef CONFIG_OMAP4_DSS_HDMI
 	hdmi_uninit_platform_driver,
 #endif
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index b43477a..3d0ff5b 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -36,8 +36,7 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
-
-#include <plat/cpu.h>
+#include <linux/sizes.h>
 
 #include <video/omapdss.h>
 
@@ -88,6 +87,10 @@ struct dispc_features {
 	u16 sw_max;
 	u16 vp_max;
 	u16 hp_max;
+	u8 mgr_width_start;
+	u8 mgr_height_start;
+	u16 mgr_width_max;
+	u16 mgr_height_max;
 	int (*calc_scaling) (enum omap_plane plane,
 		const struct omap_video_timings *mgr_timings,
 		u16 width, u16 height, u16 out_width, u16 out_height,
@@ -498,7 +501,7 @@ static void dispc_restore_context(void)
 	if (dss_has_feature(FEAT_MGR_LCD3))
 		RR(CONTROL3);
 	/* clear spurious SYNC_LOST_DIGIT interrupts */
-	dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
+	dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT);
 
 	/*
 	 * enable last so IRQs won't trigger before
@@ -543,6 +546,11 @@ u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
 	return mgr_desc[channel].framedone_irq;
 }
 
+u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel)
+{
+	return mgr_desc[channel].sync_lost_irq;
+}
+
 u32 dispc_wb_get_framedone_irq(void)
 {
 	return DISPC_IRQ_FRAMEDONEWB;
@@ -1042,7 +1050,7 @@ static void dispc_configure_burst_sizes(void)
 	const int burst_size = BURST_SIZE_X8;
 
 	/* Configure burst size always to maximum size */
-	for (i = 0; i < omap_dss_get_num_overlays(); ++i)
+	for (i = 0; i < dss_feat_get_num_ovls(); ++i)
 		dispc_ovl_set_burst_size(i, burst_size);
 }
 
@@ -1076,7 +1084,7 @@ static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
 }
 
 static void dispc_mgr_set_cpr_coef(enum omap_channel channel,
-		struct omap_dss_cpr_coefs *coefs)
+		const struct omap_dss_cpr_coefs *coefs)
 {
 	u32 coef_r, coef_g, coef_b;
 
@@ -1124,7 +1132,9 @@ static void dispc_mgr_set_size(enum omap_channel channel, u16 width,
 {
 	u32 val;
 
-	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+	val = FLD_VAL(height - 1, dispc.feat->mgr_height_start, 16) |
+		FLD_VAL(width - 1, dispc.feat->mgr_width_start, 0);
+
 	dispc_write_reg(DISPC_SIZE_MGR(channel), val);
 }
 
@@ -1246,7 +1256,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
 
 	if (use_fifomerge) {
 		total_fifo_size = 0;
-		for (i = 0; i < omap_dss_get_num_overlays(); ++i)
+		for (i = 0; i < dss_feat_get_num_ovls(); ++i)
 			total_fifo_size += dispc_ovl_get_fifo_size(i);
 	} else {
 		total_fifo_size = ovl_fifo_size;
@@ -1995,7 +2005,7 @@ static int check_horiz_timing_omap3(enum omap_plane plane,
 		const struct omap_video_timings *t, u16 pos_x,
 		u16 width, u16 height, u16 out_width, u16 out_height)
 {
-	int DS = DIV_ROUND_UP(height, out_height);
+	const int ds = DIV_ROUND_UP(height, out_height);
 	unsigned long nonactive;
 	static const u8 limits[3] = { 8, 10, 20 };
 	u64 val, blank;
@@ -2022,8 +2032,8 @@ static int check_horiz_timing_omap3(enum omap_plane plane,
 	 */
 	val = div_u64((u64)(nonactive - pos_x) * lclk, pclk);
 	DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n",
-		val, max(0, DS - 2) * width);
-	if (val < max(0, DS - 2) * width)
+		val, max(0, ds - 2) * width);
+	if (val < max(0, ds - 2) * width)
 		return -EINVAL;
 
 	/*
@@ -2033,8 +2043,8 @@ static int check_horiz_timing_omap3(enum omap_plane plane,
 	 */
 	val =  div_u64((u64)nonactive * lclk, pclk);
 	DSSDBG("nonactive * pcd  = %llu, max(0, DS - 1) * width = %d\n",
-		val, max(0, DS - 1) * width);
-	if (val < max(0, DS - 1) * width)
+		val, max(0, ds - 1) * width);
+	if (val < max(0, ds - 1) * width)
 		return -EINVAL;
 
 	return 0;
@@ -2260,14 +2270,16 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
 	u16 in_height = DIV_ROUND_UP(height, *decim_y);
 	const int maxsinglelinewidth =
 				dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
-	unsigned long pclk = dispc_plane_pclk_rate(plane);
 	const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
 
-	if (mem_to_mem)
-		in_width_max = DIV_ROUND_UP(out_width, maxdownscale);
-	else
+	if (mem_to_mem) {
+		in_width_max = out_width * maxdownscale;
+	} else {
+		unsigned long pclk = dispc_plane_pclk_rate(plane);
+
 		in_width_max = dispc_core_clk_rate() /
 					DIV_ROUND_UP(pclk, out_width);
+	}
 
 	*decim_x = DIV_ROUND_UP(width, in_width_max);
 
@@ -2309,9 +2321,14 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
 	if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
 		return -EINVAL;
 
-	*x_predecim = max_decim_limit;
-	*y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
-			dss_has_feature(FEAT_BURST_2D)) ? 2 : max_decim_limit;
+	if (plane == OMAP_DSS_WB) {
+		*x_predecim = *y_predecim = 1;
+	} else {
+		*x_predecim = max_decim_limit;
+		*y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
+				dss_has_feature(FEAT_BURST_2D)) ?
+				2 : max_decim_limit;
+	}
 
 	if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
 	    color_mode == OMAP_DSS_COLOR_CLUT2 ||
@@ -2370,7 +2387,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
 	unsigned offset0, offset1;
 	s32 row_inc;
 	s32 pix_inc;
-	u16 frame_height = height;
+	u16 frame_width, frame_height;
 	unsigned int field_offset = 0;
 	u16 in_height = height;
 	u16 in_width = width;
@@ -2438,20 +2455,28 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
 	row_inc = 0;
 	pix_inc = 0;
 
+	if (plane == OMAP_DSS_WB) {
+		frame_width = out_width;
+		frame_height = out_height;
+	} else {
+		frame_width = in_width;
+		frame_height = height;
+	}
+
 	if (rotation_type == OMAP_DSS_ROT_TILER)
-		calc_tiler_rotation_offset(screen_width, in_width,
+		calc_tiler_rotation_offset(screen_width, frame_width,
 				color_mode, fieldmode, field_offset,
 				&offset0, &offset1, &row_inc, &pix_inc,
 				x_predecim, y_predecim);
 	else if (rotation_type == OMAP_DSS_ROT_DMA)
-		calc_dma_rotation_offset(rotation, mirror,
-				screen_width, in_width, frame_height,
+		calc_dma_rotation_offset(rotation, mirror, screen_width,
+				frame_width, frame_height,
 				color_mode, fieldmode, field_offset,
 				&offset0, &offset1, &row_inc, &pix_inc,
 				x_predecim, y_predecim);
 	else
 		calc_vrfb_rotation_offset(rotation, mirror,
-				screen_width, in_width, frame_height,
+				screen_width, frame_width, frame_height,
 				color_mode, fieldmode, field_offset,
 				&offset0, &offset1, &row_inc, &pix_inc,
 				x_predecim, y_predecim);
@@ -2505,7 +2530,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
 		bool mem_to_mem)
 {
 	int r;
-	struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+	enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
 	enum omap_channel channel;
 
 	channel = dispc_ovl_get_channel_out(plane);
@@ -2516,7 +2541,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
 		oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
 		oi->color_mode, oi->rotation, oi->mirror, channel, replication);
 
-	r = dispc_ovl_setup_common(plane, ovl->caps, oi->paddr, oi->p_uv_addr,
+	r = dispc_ovl_setup_common(plane, caps, oi->paddr, oi->p_uv_addr,
 		oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
 		oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
 		oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
@@ -2585,147 +2610,195 @@ int dispc_ovl_enable(enum omap_plane plane, bool enable)
 	return 0;
 }
 
-static void dispc_disable_isr(void *data, u32 mask)
+bool dispc_ovl_enabled(enum omap_plane plane)
+{
+	return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
+}
+
+static void dispc_mgr_disable_isr(void *data, u32 mask)
 {
 	struct completion *compl = data;
 	complete(compl);
 }
 
-static void _enable_lcd_out(enum omap_channel channel, bool enable)
+void dispc_mgr_enable(enum omap_channel channel, bool enable)
 {
 	mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable);
 	/* flush posted write */
 	mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
 }
 
-static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
+bool dispc_mgr_is_enabled(enum omap_channel channel)
 {
-	struct completion frame_done_completion;
-	bool is_on;
+	return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
+}
+
+static void dispc_mgr_enable_lcd_out(enum omap_channel channel)
+{
+	dispc_mgr_enable(channel, true);
+}
+
+static void dispc_mgr_disable_lcd_out(enum omap_channel channel)
+{
+	DECLARE_COMPLETION_ONSTACK(framedone_compl);
 	int r;
 	u32 irq;
 
-	/* When we disable LCD output, we need to wait until frame is done.
-	 * Otherwise the DSS is still working, and turning off the clocks
-	 * prevents DSS from going to OFF mode */
-	is_on = mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
+	if (dispc_mgr_is_enabled(channel) == false)
+		return;
 
-	irq = mgr_desc[channel].framedone_irq;
+	/*
+	 * When we disable LCD output, we need to wait for FRAMEDONE to know
+	 * that DISPC has finished with the LCD output.
+	 */
 
-	if (!enable && is_on) {
-		init_completion(&frame_done_completion);
+	irq = dispc_mgr_get_framedone_irq(channel);
 
-		r = omap_dispc_register_isr(dispc_disable_isr,
-				&frame_done_completion, irq);
+	r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
+			irq);
+	if (r)
+		DSSERR("failed to register FRAMEDONE isr\n");
 
-		if (r)
-			DSSERR("failed to register FRAMEDONE isr\n");
+	dispc_mgr_enable(channel, false);
+
+	/* if we couldn't register for framedone, just sleep and exit */
+	if (r) {
+		msleep(100);
+		return;
 	}
 
-	_enable_lcd_out(channel, enable);
+	if (!wait_for_completion_timeout(&framedone_compl,
+				msecs_to_jiffies(100)))
+		DSSERR("timeout waiting for FRAME DONE\n");
 
-	if (!enable && is_on) {
-		if (!wait_for_completion_timeout(&frame_done_completion,
-					msecs_to_jiffies(100)))
-			DSSERR("timeout waiting for FRAME DONE\n");
+	r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
+			irq);
+	if (r)
+		DSSERR("failed to unregister FRAMEDONE isr\n");
+}
 
-		r = omap_dispc_unregister_isr(dispc_disable_isr,
-				&frame_done_completion, irq);
+static void dispc_digit_out_enable_isr(void *data, u32 mask)
+{
+	struct completion *compl = data;
 
-		if (r)
-			DSSERR("failed to unregister FRAMEDONE isr\n");
-	}
+	/* ignore any sync lost interrupts */
+	if (mask & (DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD))
+		complete(compl);
 }
 
-static void _enable_digit_out(bool enable)
+static void dispc_mgr_enable_digit_out(void)
 {
-	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
-	/* flush posted write */
-	dispc_read_reg(DISPC_CONTROL);
+	DECLARE_COMPLETION_ONSTACK(vsync_compl);
+	int r;
+	u32 irq_mask;
+
+	if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == true)
+		return;
+
+	/*
+	 * Digit output produces some sync lost interrupts during the first
+	 * frame when enabling. Those need to be ignored, so we register for the
+	 * sync lost irq to prevent the error handler from triggering.
+	 */
+
+	irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT) |
+		dispc_mgr_get_sync_lost_irq(OMAP_DSS_CHANNEL_DIGIT);
+
+	r = omap_dispc_register_isr(dispc_digit_out_enable_isr, &vsync_compl,
+			irq_mask);
+	if (r) {
+		DSSERR("failed to register %x isr\n", irq_mask);
+		return;
+	}
+
+	dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, true);
+
+	/* wait for the first evsync */
+	if (!wait_for_completion_timeout(&vsync_compl, msecs_to_jiffies(100)))
+		DSSERR("timeout waiting for digit out to start\n");
+
+	r = omap_dispc_unregister_isr(dispc_digit_out_enable_isr, &vsync_compl,
+			irq_mask);
+	if (r)
+		DSSERR("failed to unregister %x isr\n", irq_mask);
 }
 
-static void dispc_mgr_enable_digit_out(bool enable)
+static void dispc_mgr_disable_digit_out(void)
 {
-	struct completion frame_done_completion;
+	DECLARE_COMPLETION_ONSTACK(framedone_compl);
 	enum dss_hdmi_venc_clk_source_select src;
 	int r, i;
 	u32 irq_mask;
 	int num_irqs;
 
-	if (REG_GET(DISPC_CONTROL, 1, 1) == enable)
+	if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == false)
 		return;
 
 	src = dss_get_hdmi_venc_clk_source();
 
-	if (enable) {
-		unsigned long flags;
-		/* When we enable digit output, we'll get an extra digit
-		 * sync lost interrupt, that we need to ignore */
-		spin_lock_irqsave(&dispc.irq_lock, flags);
-		dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
-		_omap_dispc_set_irqs();
-		spin_unlock_irqrestore(&dispc.irq_lock, flags);
-	}
-
-	/* When we disable digit output, we need to wait until fields are done.
-	 * Otherwise the DSS is still working, and turning off the clocks
-	 * prevents DSS from going to OFF mode. And when enabling, we need to
-	 * wait for the extra sync losts */
-	init_completion(&frame_done_completion);
+	/*
+	 * When we disable the digit output, we need to wait for FRAMEDONE to
+	 * know that DISPC has finished with the output. For analog tv out we'll
+	 * use vsync, as omap2/3 don't have framedone for TV.
+	 */
 
-	if (src == DSS_HDMI_M_PCLK && enable == false) {
+	if (src == DSS_HDMI_M_PCLK) {
 		irq_mask = DISPC_IRQ_FRAMEDONETV;
 		num_irqs = 1;
 	} else {
-		irq_mask = DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD;
-		/* XXX I understand from TRM that we should only wait for the
-		 * current field to complete. But it seems we have to wait for
-		 * both fields */
+		irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT);
+		/*
+		 * We need to wait for both even and odd vsyncs. Note that this
+		 * is not totally reliable, as we could get a vsync interrupt
+		 * before we disable the output, which leads to timeout in the
+		 * wait_for_completion.
+		 */
 		num_irqs = 2;
 	}
 
-	r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
+	r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
 			irq_mask);
 	if (r)
 		DSSERR("failed to register %x isr\n", irq_mask);
 
-	_enable_digit_out(enable);
+	dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, false);
+
+	/* if we couldn't register the irq, just sleep and exit */
+	if (r) {
+		msleep(100);
+		return;
+	}
 
 	for (i = 0; i < num_irqs; ++i) {
-		if (!wait_for_completion_timeout(&frame_done_completion,
+		if (!wait_for_completion_timeout(&framedone_compl,
 					msecs_to_jiffies(100)))
-			DSSERR("timeout waiting for digit out to %s\n",
-					enable ? "start" : "stop");
+			DSSERR("timeout waiting for digit out to stop\n");
 	}
 
-	r = omap_dispc_unregister_isr(dispc_disable_isr, &frame_done_completion,
+	r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
 			irq_mask);
 	if (r)
 		DSSERR("failed to unregister %x isr\n", irq_mask);
-
-	if (enable) {
-		unsigned long flags;
-		spin_lock_irqsave(&dispc.irq_lock, flags);
-		dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST_DIGIT;
-		dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
-		_omap_dispc_set_irqs();
-		spin_unlock_irqrestore(&dispc.irq_lock, flags);
-	}
 }
 
-bool dispc_mgr_is_enabled(enum omap_channel channel)
+void dispc_mgr_enable_sync(enum omap_channel channel)
 {
-	return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
+	if (dss_mgr_is_lcd(channel))
+		dispc_mgr_enable_lcd_out(channel);
+	else if (channel == OMAP_DSS_CHANNEL_DIGIT)
+		dispc_mgr_enable_digit_out();
+	else
+		WARN_ON(1);
 }
 
-void dispc_mgr_enable(enum omap_channel channel, bool enable)
+void dispc_mgr_disable_sync(enum omap_channel channel)
 {
 	if (dss_mgr_is_lcd(channel))
-		dispc_mgr_enable_lcd_out(channel, enable);
+		dispc_mgr_disable_lcd_out(channel);
 	else if (channel == OMAP_DSS_CHANNEL_DIGIT)
-		dispc_mgr_enable_digit_out(enable);
+		dispc_mgr_disable_digit_out();
 	else
-		BUG();
+		WARN_ON(1);
 }
 
 void dispc_wb_enable(bool enable)
@@ -2742,7 +2815,7 @@ void dispc_wb_enable(bool enable)
 	if (!enable && is_on) {
 		init_completion(&frame_done_completion);
 
-		r = omap_dispc_register_isr(dispc_disable_isr,
+		r = omap_dispc_register_isr(dispc_mgr_disable_isr,
 				&frame_done_completion, irq);
 		if (r)
 			DSSERR("failed to register FRAMEDONEWB isr\n");
@@ -2755,7 +2828,7 @@ void dispc_wb_enable(bool enable)
 					msecs_to_jiffies(100)))
 			DSSERR("timeout waiting for FRAMEDONEWB\n");
 
-		r = omap_dispc_unregister_isr(dispc_disable_isr,
+		r = omap_dispc_unregister_isr(dispc_mgr_disable_isr,
 				&frame_done_completion, irq);
 		if (r)
 			DSSERR("failed to unregister FRAMEDONEWB isr\n");
@@ -2769,7 +2842,7 @@ bool dispc_wb_is_enabled(void)
 	return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
 }
 
-void dispc_lcd_enable_signal_polarity(bool act_high)
+static void dispc_lcd_enable_signal_polarity(bool act_high)
 {
 	if (!dss_has_feature(FEAT_LCDENABLEPOL))
 		return;
@@ -2793,13 +2866,13 @@ void dispc_pck_free_enable(bool enable)
 	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
 }
 
-void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
+static void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
 {
 	mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable);
 }
 
 
-void dispc_mgr_set_lcd_type_tft(enum omap_channel channel)
+static void dispc_mgr_set_lcd_type_tft(enum omap_channel channel)
 {
 	mgr_fld_write(channel, DISPC_MGR_FLD_STNTFT, 1);
 }
@@ -2842,7 +2915,7 @@ static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch,
 }
 
 void dispc_mgr_setup(enum omap_channel channel,
-		struct omap_overlay_manager_info *info)
+		const struct omap_overlay_manager_info *info)
 {
 	dispc_mgr_set_default_color(channel, info->default_color);
 	dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key);
@@ -2855,7 +2928,7 @@ void dispc_mgr_setup(enum omap_channel channel,
 	}
 }
 
-void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
+static void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
 {
 	int code;
 
@@ -2880,7 +2953,7 @@ void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
 	mgr_fld_write(channel, DISPC_MGR_FLD_TFTDATALINES, code);
 }
 
-void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
+static void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
 {
 	u32 l;
 	int gpout0, gpout1;
@@ -2909,15 +2982,32 @@ void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
 	dispc_write_reg(DISPC_CONTROL, l);
 }
 
-void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
+static void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
 {
 	mgr_fld_write(channel, DISPC_MGR_FLD_STALLMODE, enable);
 }
 
+void dispc_mgr_set_lcd_config(enum omap_channel channel,
+		const struct dss_lcd_mgr_config *config)
+{
+	dispc_mgr_set_io_pad_mode(config->io_pad_mode);
+
+	dispc_mgr_enable_stallmode(channel, config->stallmode);
+	dispc_mgr_enable_fifohandcheck(channel, config->fifohandcheck);
+
+	dispc_mgr_set_clock_div(channel, &config->clock_info);
+
+	dispc_mgr_set_tft_data_lines(channel, config->video_port_width);
+
+	dispc_lcd_enable_signal_polarity(config->lcden_sig_polarity);
+
+	dispc_mgr_set_lcd_type_tft(channel);
+}
+
 static bool _dispc_mgr_size_ok(u16 width, u16 height)
 {
-	return width <= dss_feat_get_param_max(FEAT_PARAM_MGR_WIDTH) &&
-		height <= dss_feat_get_param_max(FEAT_PARAM_MGR_HEIGHT);
+	return width <= dispc.feat->mgr_width_max &&
+		height <= dispc.feat->mgr_height_max;
 }
 
 static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -3012,7 +3102,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
 
 /* change name to mode? */
 void dispc_mgr_set_timings(enum omap_channel channel,
-		struct omap_video_timings *timings)
+		const struct omap_video_timings *timings)
 {
 	unsigned xtot, ytot;
 	unsigned long ht, vt;
@@ -3103,28 +3193,32 @@ unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
 	unsigned long r;
 	u32 l;
 
-	l = dispc_read_reg(DISPC_DIVISORo(channel));
+	if (dss_mgr_is_lcd(channel)) {
+		l = dispc_read_reg(DISPC_DIVISORo(channel));
 
-	lcd = FLD_GET(l, 23, 16);
+		lcd = FLD_GET(l, 23, 16);
 
-	switch (dss_get_lcd_clk_source(channel)) {
-	case OMAP_DSS_CLK_SRC_FCK:
-		r = clk_get_rate(dispc.dss_clk);
-		break;
-	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
-		dsidev = dsi_get_dsidev_from_id(0);
-		r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
-		break;
-	case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
-		dsidev = dsi_get_dsidev_from_id(1);
-		r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
-		break;
-	default:
-		BUG();
-		return 0;
-	}
+		switch (dss_get_lcd_clk_source(channel)) {
+		case OMAP_DSS_CLK_SRC_FCK:
+			r = clk_get_rate(dispc.dss_clk);
+			break;
+		case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
+			dsidev = dsi_get_dsidev_from_id(0);
+			r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+			break;
+		case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
+			dsidev = dsi_get_dsidev_from_id(1);
+			r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+			break;
+		default:
+			BUG();
+			return 0;
+		}
 
-	return r / lcd;
+		return r / lcd;
+	} else {
+		return dispc_fclk_rate();
+	}
 }
 
 unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
@@ -3183,12 +3277,9 @@ static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
 {
 	enum omap_channel channel = dispc_ovl_get_channel_out(plane);
 
-	if (dss_mgr_is_lcd(channel))
-		return dispc_mgr_lclk_rate(channel);
-	else
-		return dispc_fclk_rate();
-
+	return dispc_mgr_lclk_rate(channel);
 }
+
 static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
 {
 	int lcd, pcd;
@@ -3247,7 +3338,7 @@ void dispc_dump_clocks(struct seq_file *s)
 }
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-void dispc_dump_irqs(struct seq_file *s)
+static void dispc_dump_irqs(struct seq_file *s)
 {
 	unsigned long flags;
 	struct dispc_irq_stats stats;
@@ -3353,7 +3444,7 @@ static void dispc_dump_regs(struct seq_file *s)
 
 #define DISPC_REG(i, name) name(i)
 #define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
-	48 - strlen(#r) - strlen(p_names[i]), " ", \
+	(int)(48 - strlen(#r) - strlen(p_names[i])), " ", \
 	dispc_read_reg(DISPC_REG(i, r)))
 
 	p_names = mgr_names;
@@ -3430,7 +3521,7 @@ static void dispc_dump_regs(struct seq_file *s)
 #define DISPC_REG(plane, name, i) name(plane, i)
 #define DUMPREG(plane, name, i) \
 	seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \
-	46 - strlen(#name) - strlen(p_names[plane]), " ", \
+	(int)(46 - strlen(#name) - strlen(p_names[plane])), " ", \
 	dispc_read_reg(DISPC_REG(plane, name, i)))
 
 	/* Video pipeline coefficient registers */
@@ -3533,7 +3624,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
 }
 
 void dispc_mgr_set_clock_div(enum omap_channel channel,
-		struct dispc_clock_info *cinfo)
+		const struct dispc_clock_info *cinfo)
 {
 	DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
 	DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
@@ -3557,11 +3648,35 @@ int dispc_mgr_get_clock_div(enum omap_channel channel,
 	return 0;
 }
 
+u32 dispc_read_irqstatus(void)
+{
+	return dispc_read_reg(DISPC_IRQSTATUS);
+}
+
+void dispc_clear_irqstatus(u32 mask)
+{
+	dispc_write_reg(DISPC_IRQSTATUS, mask);
+}
+
+u32 dispc_read_irqenable(void)
+{
+	return dispc_read_reg(DISPC_IRQENABLE);
+}
+
+void dispc_write_irqenable(u32 mask)
+{
+	u32 old_mask = dispc_read_reg(DISPC_IRQENABLE);
+
+	/* clear the irqstatus for newly enabled irqs */
+	dispc_clear_irqstatus((mask ^ old_mask) & mask);
+
+	dispc_write_reg(DISPC_IRQENABLE, mask);
+}
+
 /* dispc.irq_lock has to be locked by the caller */
 static void _omap_dispc_set_irqs(void)
 {
 	u32 mask;
-	u32 old_mask;
 	int i;
 	struct omap_dispc_isr_data *isr_data;
 
@@ -3576,11 +3691,7 @@ static void _omap_dispc_set_irqs(void)
 		mask |= isr_data->mask;
 	}
 
-	old_mask = dispc_read_reg(DISPC_IRQENABLE);
-	/* clear the irqstatus for newly enabled irqs */
-	dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
-
-	dispc_write_reg(DISPC_IRQENABLE, mask);
+	dispc_write_irqenable(mask);
 }
 
 int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
@@ -3671,34 +3782,26 @@ int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
 }
 EXPORT_SYMBOL(omap_dispc_unregister_isr);
 
-#ifdef DEBUG
 static void print_irq_status(u32 status)
 {
 	if ((status & dispc.irq_error_mask) == 0)
 		return;
 
-	printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
-
-#define PIS(x) \
-	if (status & DISPC_IRQ_##x) \
-		printk(#x " ");
-	PIS(GFX_FIFO_UNDERFLOW);
-	PIS(OCP_ERR);
-	PIS(VID1_FIFO_UNDERFLOW);
-	PIS(VID2_FIFO_UNDERFLOW);
-	if (dss_feat_get_num_ovls() > 3)
-		PIS(VID3_FIFO_UNDERFLOW);
-	PIS(SYNC_LOST);
-	PIS(SYNC_LOST_DIGIT);
-	if (dss_has_feature(FEAT_MGR_LCD2))
-		PIS(SYNC_LOST2);
-	if (dss_has_feature(FEAT_MGR_LCD3))
-		PIS(SYNC_LOST3);
+#define PIS(x) (status & DISPC_IRQ_##x) ? (#x " ") : ""
+
+	pr_debug("DISPC IRQ: 0x%x: %s%s%s%s%s%s%s%s%s\n",
+		status,
+		PIS(OCP_ERR),
+		PIS(GFX_FIFO_UNDERFLOW),
+		PIS(VID1_FIFO_UNDERFLOW),
+		PIS(VID2_FIFO_UNDERFLOW),
+		dss_feat_get_num_ovls() > 3 ? PIS(VID3_FIFO_UNDERFLOW) : "",
+		PIS(SYNC_LOST),
+		PIS(SYNC_LOST_DIGIT),
+		dss_has_feature(FEAT_MGR_LCD2) ? PIS(SYNC_LOST2) : "",
+		dss_has_feature(FEAT_MGR_LCD3) ? PIS(SYNC_LOST3) : "");
 #undef PIS
-
-	printk("\n");
 }
-#endif
 
 /* Called from dss.c. Note that we don't touch clocks here,
  * but we presume they are on because we got an IRQ. However,
@@ -3715,8 +3818,8 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
 
 	spin_lock(&dispc.irq_lock);
 
-	irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
-	irqenable = dispc_read_reg(DISPC_IRQENABLE);
+	irqstatus = dispc_read_irqstatus();
+	irqenable = dispc_read_irqenable();
 
 	/* IRQ is not for us */
 	if (!(irqstatus & irqenable)) {
@@ -3731,15 +3834,13 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
 	spin_unlock(&dispc.irq_stats_lock);
 #endif
 
-#ifdef DEBUG
-	if (dss_debug)
-		print_irq_status(irqstatus);
-#endif
+	print_irq_status(irqstatus);
+
 	/* Ack the interrupt. Do it here before clocks are possibly turned
 	 * off */
-	dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
+	dispc_clear_irqstatus(irqstatus);
 	/* flush posted write */
-	dispc_read_reg(DISPC_IRQSTATUS);
+	dispc_read_irqstatus();
 
 	/* make a copy and unlock, so that isrs can unregister
 	 * themselves */
@@ -3821,30 +3922,24 @@ static void dispc_error_worker(struct work_struct *work)
 		bit = mgr_desc[i].sync_lost_irq;
 
 		if (bit & errors) {
-			struct omap_dss_device *dssdev = mgr->get_device(mgr);
-			bool enable;
+			int j;
 
 			DSSERR("SYNC_LOST on channel %s, restarting the output "
 					"with video overlays disabled\n",
 					mgr->name);
 
-			enable = dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
-			dssdev->driver->disable(dssdev);
+			dss_mgr_disable(mgr);
 
-			for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+			for (j = 0; j < omap_dss_get_num_overlays(); ++j) {
 				struct omap_overlay *ovl;
-				ovl = omap_dss_get_overlay(i);
+				ovl = omap_dss_get_overlay(j);
 
 				if (ovl->id != OMAP_DSS_GFX &&
 						ovl->manager == mgr)
-					dispc_ovl_enable(ovl->id, false);
+					ovl->disable(ovl);
 			}
 
-			dispc_mgr_go(mgr->id);
-			msleep(50);
-
-			if (enable)
-				dssdev->driver->enable(dssdev);
+			dss_mgr_enable(mgr);
 		}
 	}
 
@@ -3852,13 +3947,9 @@ static void dispc_error_worker(struct work_struct *work)
 		DSSERR("OCP_ERR\n");
 		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
 			struct omap_overlay_manager *mgr;
-			struct omap_dss_device *dssdev;
 
 			mgr = omap_dss_get_overlay_manager(i);
-			dssdev = mgr->get_device(mgr);
-
-			if (dssdev && dssdev->driver)
-				dssdev->driver->disable(dssdev);
+			dss_mgr_disable(mgr);
 		}
 	}
 
@@ -3893,9 +3984,6 @@ int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
 	if (timeout == 0)
 		return -ETIMEDOUT;
 
-	if (timeout == -ERESTARTSYS)
-		return -ERESTARTSYS;
-
 	return 0;
 }
 
@@ -3948,7 +4036,7 @@ static void _omap_dispc_initialize_irq(void)
 
 	/* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
 	 * so clear it */
-	dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
+	dispc_clear_irqstatus(dispc_read_irqstatus());
 
 	_omap_dispc_set_irqs();
 
@@ -4000,6 +4088,10 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = {
 	.sw_max			=	64,
 	.vp_max			=	255,
 	.hp_max			=	256,
+	.mgr_width_start	=	10,
+	.mgr_height_start	=	26,
+	.mgr_width_max		=	2048,
+	.mgr_height_max		=	2048,
 	.calc_scaling		=	dispc_ovl_calc_scaling_24xx,
 	.calc_core_clk		=	calc_core_clk_24xx,
 	.num_fifos		=	3,
@@ -4012,6 +4104,10 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
 	.sw_max			=	64,
 	.vp_max			=	255,
 	.hp_max			=	256,
+	.mgr_width_start	=	10,
+	.mgr_height_start	=	26,
+	.mgr_width_max		=	2048,
+	.mgr_height_max		=	2048,
 	.calc_scaling		=	dispc_ovl_calc_scaling_34xx,
 	.calc_core_clk		=	calc_core_clk_34xx,
 	.num_fifos		=	3,
@@ -4024,6 +4120,10 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
 	.sw_max			=	256,
 	.vp_max			=	4095,
 	.hp_max			=	4096,
+	.mgr_width_start	=	10,
+	.mgr_height_start	=	26,
+	.mgr_width_max		=	2048,
+	.mgr_height_max		=	2048,
 	.calc_scaling		=	dispc_ovl_calc_scaling_34xx,
 	.calc_core_clk		=	calc_core_clk_34xx,
 	.num_fifos		=	3,
@@ -4036,35 +4136,70 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
 	.sw_max			=	256,
 	.vp_max			=	4095,
 	.hp_max			=	4096,
+	.mgr_width_start	=	10,
+	.mgr_height_start	=	26,
+	.mgr_width_max		=	2048,
+	.mgr_height_max		=	2048,
 	.calc_scaling		=	dispc_ovl_calc_scaling_44xx,
 	.calc_core_clk		=	calc_core_clk_44xx,
 	.num_fifos		=	5,
 	.gfx_fifo_workaround	=	true,
 };
 
-static int __init dispc_init_features(struct device *dev)
+static const struct dispc_features omap54xx_dispc_feats __initconst = {
+	.sw_start		=	7,
+	.fp_start		=	19,
+	.bp_start		=	31,
+	.sw_max			=	256,
+	.vp_max			=	4095,
+	.hp_max			=	4096,
+	.mgr_width_start	=	11,
+	.mgr_height_start	=	27,
+	.mgr_width_max		=	4096,
+	.mgr_height_max		=	4096,
+	.calc_scaling		=	dispc_ovl_calc_scaling_44xx,
+	.calc_core_clk		=	calc_core_clk_44xx,
+	.num_fifos		=	5,
+	.gfx_fifo_workaround	=	true,
+};
+
+static int __init dispc_init_features(struct platform_device *pdev)
 {
 	const struct dispc_features *src;
 	struct dispc_features *dst;
 
-	dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
+	dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
 	if (!dst) {
-		dev_err(dev, "Failed to allocate DISPC Features\n");
+		dev_err(&pdev->dev, "Failed to allocate DISPC Features\n");
 		return -ENOMEM;
 	}
 
-	if (cpu_is_omap24xx()) {
+	switch (omapdss_get_version()) {
+	case OMAPDSS_VER_OMAP24xx:
 		src = &omap24xx_dispc_feats;
-	} else if (cpu_is_omap34xx()) {
-		if (omap_rev() < OMAP3430_REV_ES3_0)
-			src = &omap34xx_rev1_0_dispc_feats;
-		else
-			src = &omap34xx_rev3_0_dispc_feats;
-	} else if (cpu_is_omap44xx()) {
-		src = &omap44xx_dispc_feats;
-	} else if (soc_is_omap54xx()) {
+		break;
+
+	case OMAPDSS_VER_OMAP34xx_ES1:
+		src = &omap34xx_rev1_0_dispc_feats;
+		break;
+
+	case OMAPDSS_VER_OMAP34xx_ES3:
+	case OMAPDSS_VER_OMAP3630:
+	case OMAPDSS_VER_AM35xx:
+		src = &omap34xx_rev3_0_dispc_feats;
+		break;
+
+	case OMAPDSS_VER_OMAP4430_ES1:
+	case OMAPDSS_VER_OMAP4430_ES2:
+	case OMAPDSS_VER_OMAP4:
 		src = &omap44xx_dispc_feats;
-	} else {
+		break;
+
+	case OMAPDSS_VER_OMAP5:
+		src = &omap54xx_dispc_feats;
+		break;
+
+	default:
 		return -ENODEV;
 	}
 
@@ -4084,7 +4219,7 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
 
 	dispc.pdev = pdev;
 
-	r = dispc_init_features(&dispc.pdev->dev);
+	r = dispc_init_features(dispc.pdev);
 	if (r)
 		return r;
 
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index ccf8550..6d33112 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -320,86 +320,21 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,
 }
 EXPORT_SYMBOL(omapdss_default_get_timings);
 
-/*
- * Connect dssdev to a manager if the manager is free or if force is specified.
- * Connect all overlays to that manager if they are free or if force is
- * specified.
- */
-static int dss_init_connections(struct omap_dss_device *dssdev, bool force)
+int dss_init_device(struct platform_device *pdev,
+		struct omap_dss_device *dssdev)
 {
+	struct device_attribute *attr;
 	struct omap_dss_output *out;
-	struct omap_overlay_manager *mgr;
 	int i, r;
 
 	out = omapdss_get_output_from_dssdev(dssdev);
 
-	WARN_ON(dssdev->output);
-	WARN_ON(out->device);
-
 	r = omapdss_output_set_device(out, dssdev);
 	if (r) {
 		DSSERR("failed to connect output to new device\n");
 		return r;
 	}
 
-	mgr = omap_dss_get_overlay_manager(dssdev->channel);
-
-	if (mgr->output && !force)
-		return 0;
-
-	if (mgr->output)
-		mgr->unset_output(mgr);
-
-	r = mgr->set_output(mgr, out);
-	if (r) {
-		DSSERR("failed to connect manager to output of new device\n");
-
-		/* remove the output-device connection we just made */
-		omapdss_output_unset_device(out);
-		return r;
-	}
-
-	for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
-		struct omap_overlay *ovl = omap_dss_get_overlay(i);
-
-		if (!ovl->manager || force) {
-			if (ovl->manager)
-				ovl->unset_manager(ovl);
-
-			r = ovl->set_manager(ovl, mgr);
-			if (r) {
-				DSSERR("failed to set initial overlay\n");
-				return r;
-			}
-		}
-	}
-
-	return 0;
-}
-
-static void dss_uninit_connections(struct omap_dss_device *dssdev)
-{
-	if (dssdev->output) {
-		struct omap_overlay_manager *mgr = dssdev->output->manager;
-
-		if (mgr)
-			mgr->unset_output(mgr);
-
-		omapdss_output_unset_device(dssdev->output);
-	}
-}
-
-int dss_init_device(struct platform_device *pdev,
-		struct omap_dss_device *dssdev)
-{
-	struct device_attribute *attr;
-	int i, r;
-	const char *def_disp_name = dss_get_default_display_name();
-	bool force;
-
-	force = def_disp_name && strcmp(def_disp_name, dssdev->name) == 0;
-	dss_init_connections(dssdev, force);
-
 	/* create device sysfs files */
 	i = 0;
 	while ((attr = display_sysfs_attrs[i++]) != NULL) {
@@ -410,7 +345,7 @@ int dss_init_device(struct platform_device *pdev,
 				device_remove_file(&dssdev->dev, attr);
 			}
 
-			dss_uninit_connections(dssdev);
+			omapdss_output_unset_device(dssdev->output);
 
 			DSSERR("failed to create sysfs file\n");
 			return r;
@@ -424,7 +359,7 @@ int dss_init_device(struct platform_device *pdev,
 		while ((attr = display_sysfs_attrs[i++]) != NULL)
 			device_remove_file(&dssdev->dev, attr);
 
-		dss_uninit_connections(dssdev);
+		omapdss_output_unset_device(dssdev->output);
 
 		DSSERR("failed to create sysfs display link\n");
 		return r;
@@ -444,12 +379,12 @@ void dss_uninit_device(struct platform_device *pdev,
 	while ((attr = display_sysfs_attrs[i++]) != NULL)
 		device_remove_file(&dssdev->dev, attr);
 
-	dss_uninit_connections(dssdev);
+	if (dssdev->output)
+		omapdss_output_unset_device(dssdev->output);
 }
 
 static int dss_suspend_device(struct device *dev, void *data)
 {
-	int r;
 	struct omap_dss_device *dssdev = to_dss_device(dev);
 
 	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
@@ -457,15 +392,7 @@ static int dss_suspend_device(struct device *dev, void *data)
 		return 0;
 	}
 
-	if (!dssdev->driver->suspend) {
-		DSSERR("display '%s' doesn't implement suspend\n",
-				dssdev->name);
-		return -ENOSYS;
-	}
-
-	r = dssdev->driver->suspend(dssdev);
-	if (r)
-		return r;
+	dssdev->driver->disable(dssdev);
 
 	dssdev->activate_after_resume = true;
 
@@ -492,8 +419,8 @@ static int dss_resume_device(struct device *dev, void *data)
 	int r;
 	struct omap_dss_device *dssdev = to_dss_device(dev);
 
-	if (dssdev->activate_after_resume && dssdev->driver->resume) {
-		r = dssdev->driver->resume(dssdev);
+	if (dssdev->activate_after_resume) {
+		r = dssdev->driver->enable(dssdev);
 		if (r)
 			return r;
 	}
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 56748cf..1e103b3 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -49,34 +49,37 @@ static struct {
 	struct omap_dss_output output;
 } dpi;
 
-static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
+static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
 {
-	int dsi_module;
-
-	dsi_module = clk == OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ? 0 : 1;
-
-	return dsi_get_dsidev_from_id(dsi_module);
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return dsi_get_dsidev_from_id(0);
+	case OMAP_DSS_CHANNEL_LCD2:
+		return dsi_get_dsidev_from_id(1);
+	default:
+		return NULL;
+	}
 }
 
-static bool dpi_use_dsi_pll(struct omap_dss_device *dssdev)
+static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
 {
-	if (dssdev->clocks.dispc.dispc_fclk_src ==
-			OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ||
-			dssdev->clocks.dispc.dispc_fclk_src ==
-			OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC ||
-			dssdev->clocks.dispc.channel.lcd_clk_src ==
-			OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ||
-			dssdev->clocks.dispc.channel.lcd_clk_src ==
-			OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC)
-		return true;
-	else
-		return false;
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
+	default:
+		/* this shouldn't happen */
+		WARN_ON(1);
+		return OMAP_DSS_CLK_SRC_FCK;
+	}
 }
 
 static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
 		unsigned long pck_req, unsigned long *fck, int *lck_div,
 		int *pck_div)
 {
+	struct omap_overlay_manager *mgr = dssdev->output->manager;
 	struct dsi_clock_info dsi_cinfo;
 	struct dispc_clock_info dispc_cinfo;
 	int r;
@@ -90,7 +93,8 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
 	if (r)
 		return r;
 
-	dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
+	dss_select_lcd_clk_source(mgr->id,
+			dpi_get_alt_clk_src(mgr->id));
 
 	dpi.mgr_config.clock_info = dispc_cinfo;
 
@@ -135,7 +139,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
 	unsigned long pck;
 	int r = 0;
 
-	if (dpi_use_dsi_pll(dssdev))
+	if (dpi.dsidev)
 		r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck,
 				&lck_div, &pck_div);
 	else
@@ -214,7 +218,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 	if (r)
 		goto err_src_sel;
 
-	if (dpi_use_dsi_pll(dssdev)) {
+	if (dpi.dsidev) {
 		r = dsi_runtime_get(dpi.dsidev);
 		if (r)
 			goto err_get_dsi;
@@ -242,10 +246,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 
 err_mgr_enable:
 err_set_mode:
-	if (dpi_use_dsi_pll(dssdev))
+	if (dpi.dsidev)
 		dsi_pll_uninit(dpi.dsidev, true);
 err_dsi_pll_init:
-	if (dpi_use_dsi_pll(dssdev))
+	if (dpi.dsidev)
 		dsi_runtime_put(dpi.dsidev);
 err_get_dsi:
 err_src_sel:
@@ -271,8 +275,8 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
 
 	dss_mgr_disable(mgr);
 
-	if (dpi_use_dsi_pll(dssdev)) {
-		dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
+	if (dpi.dsidev) {
+		dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
 		dsi_pll_uninit(dpi.dsidev, true);
 		dsi_runtime_put(dpi.dsidev);
 	}
@@ -317,7 +321,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
 	if (timings->pixel_clock == 0)
 		return -EINVAL;
 
-	if (dpi_use_dsi_pll(dssdev)) {
+	if (dpi.dsidev) {
 		struct dsi_clock_info dsi_cinfo;
 		r = dsi_pll_calc_clock_div_pck(dpi.dsidev,
 				timings->pixel_clock * 1000,
@@ -359,8 +363,32 @@ void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
 }
 EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
 
+static int __init dpi_verify_dsi_pll(struct platform_device *dsidev)
+{
+	int r;
+
+	/* do initial setup with the PLL to see if it is operational */
+
+	r = dsi_runtime_get(dsidev);
+	if (r)
+		return r;
+
+	r = dsi_pll_init(dsidev, 0, 1);
+	if (r) {
+		dsi_runtime_put(dsidev);
+		return r;
+	}
+
+	dsi_pll_uninit(dsidev, true);
+	dsi_runtime_put(dsidev);
+
+	return 0;
+}
+
 static int __init dpi_init_display(struct omap_dss_device *dssdev)
 {
+	struct platform_device *dsidev;
+
 	DSSDBG("init_display\n");
 
 	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) &&
@@ -377,19 +405,30 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
 		dpi.vdds_dsi_reg = vdds_dsi;
 	}
 
-	if (dpi_use_dsi_pll(dssdev)) {
-		enum omap_dss_clk_source dispc_fclk_src =
-			dssdev->clocks.dispc.dispc_fclk_src;
-		dpi.dsidev = dpi_get_dsidev(dispc_fclk_src);
+	/*
+	 * XXX We shouldn't need dssdev->channel for this. The dsi pll clock
+	 * source for DPI is SoC integration detail, not something that should
+	 * be configured in the dssdev
+	 */
+	dsidev = dpi_get_dsidev(dssdev->channel);
+
+	if (dpi_verify_dsi_pll(dsidev)) {
+		dsidev = NULL;
+		DSSWARN("DSI PLL not operational\n");
 	}
 
+	if (dsidev)
+		DSSDBG("using DSI PLL for DPI clock\n");
+
+	dpi.dsidev = dsidev;
+
 	return 0;
 }
 
 static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
 {
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-	const char *def_disp_name = dss_get_default_display_name();
+	const char *def_disp_name = omapdss_get_default_display_name();
 	struct omap_dss_device *def_dssdev;
 	int i;
 
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index bee9284..cf32dc7 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -45,7 +45,6 @@
 #include "dss.h"
 #include "dss_features.h"
 
-/*#define VERBOSE_IRQ*/
 #define DSI_CATCH_MISSING_TE
 
 struct dsi_reg { u16 idx; };
@@ -535,42 +534,38 @@ static inline void dsi_perf_show(struct platform_device *dsidev,
 }
 #endif
 
+static int verbose_irq;
+
 static void print_irq_status(u32 status)
 {
 	if (status == 0)
 		return;
 
-#ifndef VERBOSE_IRQ
-	if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
+	if (!verbose_irq && (status & ~DSI_IRQ_CHANNEL_MASK) == 0)
 		return;
-#endif
-	printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status);
 
-#define PIS(x) \
-	if (status & DSI_IRQ_##x) \
-		printk(#x " ");
-#ifdef VERBOSE_IRQ
-	PIS(VC0);
-	PIS(VC1);
-	PIS(VC2);
-	PIS(VC3);
-#endif
-	PIS(WAKEUP);
-	PIS(RESYNC);
-	PIS(PLL_LOCK);
-	PIS(PLL_UNLOCK);
-	PIS(PLL_RECALL);
-	PIS(COMPLEXIO_ERR);
-	PIS(HS_TX_TIMEOUT);
-	PIS(LP_RX_TIMEOUT);
-	PIS(TE_TRIGGER);
-	PIS(ACK_TRIGGER);
-	PIS(SYNC_LOST);
-	PIS(LDO_POWER_GOOD);
-	PIS(TA_TIMEOUT);
+#define PIS(x) (status & DSI_IRQ_##x) ? (#x " ") : ""
+
+	pr_debug("DSI IRQ: 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+		status,
+		verbose_irq ? PIS(VC0) : "",
+		verbose_irq ? PIS(VC1) : "",
+		verbose_irq ? PIS(VC2) : "",
+		verbose_irq ? PIS(VC3) : "",
+		PIS(WAKEUP),
+		PIS(RESYNC),
+		PIS(PLL_LOCK),
+		PIS(PLL_UNLOCK),
+		PIS(PLL_RECALL),
+		PIS(COMPLEXIO_ERR),
+		PIS(HS_TX_TIMEOUT),
+		PIS(LP_RX_TIMEOUT),
+		PIS(TE_TRIGGER),
+		PIS(ACK_TRIGGER),
+		PIS(SYNC_LOST),
+		PIS(LDO_POWER_GOOD),
+		PIS(TA_TIMEOUT));
 #undef PIS
-
-	printk("\n");
 }
 
 static void print_irq_status_vc(int channel, u32 status)
@@ -578,28 +573,24 @@ static void print_irq_status_vc(int channel, u32 status)
 	if (status == 0)
 		return;
 
-#ifndef VERBOSE_IRQ
-	if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
+	if (!verbose_irq && (status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
 		return;
-#endif
-	printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status);
 
-#define PIS(x) \
-	if (status & DSI_VC_IRQ_##x) \
-		printk(#x " ");
-	PIS(CS);
-	PIS(ECC_CORR);
-#ifdef VERBOSE_IRQ
-	PIS(PACKET_SENT);
-#endif
-	PIS(FIFO_TX_OVF);
-	PIS(FIFO_RX_OVF);
-	PIS(BTA);
-	PIS(ECC_NO_CORR);
-	PIS(FIFO_TX_UDF);
-	PIS(PP_BUSY_CHANGE);
+#define PIS(x) (status & DSI_VC_IRQ_##x) ? (#x " ") : ""
+
+	pr_debug("DSI VC(%d) IRQ 0x%x: %s%s%s%s%s%s%s%s%s\n",
+		channel,
+		status,
+		PIS(CS),
+		PIS(ECC_CORR),
+		PIS(ECC_NO_CORR),
+		verbose_irq ? PIS(PACKET_SENT) : "",
+		PIS(BTA),
+		PIS(FIFO_TX_OVF),
+		PIS(FIFO_RX_OVF),
+		PIS(FIFO_TX_UDF),
+		PIS(PP_BUSY_CHANGE));
 #undef PIS
-	printk("\n");
 }
 
 static void print_irq_status_cio(u32 status)
@@ -607,34 +598,31 @@ static void print_irq_status_cio(u32 status)
 	if (status == 0)
 		return;
 
-	printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
-
-#define PIS(x) \
-	if (status & DSI_CIO_IRQ_##x) \
-		printk(#x " ");
-	PIS(ERRSYNCESC1);
-	PIS(ERRSYNCESC2);
-	PIS(ERRSYNCESC3);
-	PIS(ERRESC1);
-	PIS(ERRESC2);
-	PIS(ERRESC3);
-	PIS(ERRCONTROL1);
-	PIS(ERRCONTROL2);
-	PIS(ERRCONTROL3);
-	PIS(STATEULPS1);
-	PIS(STATEULPS2);
-	PIS(STATEULPS3);
-	PIS(ERRCONTENTIONLP0_1);
-	PIS(ERRCONTENTIONLP1_1);
-	PIS(ERRCONTENTIONLP0_2);
-	PIS(ERRCONTENTIONLP1_2);
-	PIS(ERRCONTENTIONLP0_3);
-	PIS(ERRCONTENTIONLP1_3);
-	PIS(ULPSACTIVENOT_ALL0);
-	PIS(ULPSACTIVENOT_ALL1);
+#define PIS(x) (status & DSI_CIO_IRQ_##x) ? (#x " ") : ""
+
+	pr_debug("DSI CIO IRQ 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+		status,
+		PIS(ERRSYNCESC1),
+		PIS(ERRSYNCESC2),
+		PIS(ERRSYNCESC3),
+		PIS(ERRESC1),
+		PIS(ERRESC2),
+		PIS(ERRESC3),
+		PIS(ERRCONTROL1),
+		PIS(ERRCONTROL2),
+		PIS(ERRCONTROL3),
+		PIS(STATEULPS1),
+		PIS(STATEULPS2),
+		PIS(STATEULPS3),
+		PIS(ERRCONTENTIONLP0_1),
+		PIS(ERRCONTENTIONLP1_1),
+		PIS(ERRCONTENTIONLP0_2),
+		PIS(ERRCONTENTIONLP1_2),
+		PIS(ERRCONTENTIONLP0_3),
+		PIS(ERRCONTENTIONLP1_3),
+		PIS(ULPSACTIVENOT_ALL0),
+		PIS(ULPSACTIVENOT_ALL1));
 #undef PIS
-
-	printk("\n");
 }
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -1116,28 +1104,16 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
 	}
 }
 
-#ifdef DEBUG
 static void _dsi_print_reset_status(struct platform_device *dsidev)
 {
 	u32 l;
 	int b0, b1, b2;
 
-	if (!dss_debug)
-		return;
-
 	/* A dummy read using the SCP interface to any DSIPHY register is
 	 * required after DSIPHY reset to complete the reset of the DSI complex
 	 * I/O. */
 	l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
 
-	printk(KERN_DEBUG "DSI resets: ");
-
-	l = dsi_read_reg(dsidev, DSI_PLL_STATUS);
-	printk("PLL (%d) ", FLD_GET(l, 0, 0));
-
-	l = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
-	printk("CIO (%d) ", FLD_GET(l, 29, 29));
-
 	if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
 		b0 = 28;
 		b1 = 27;
@@ -1148,18 +1124,21 @@ static void _dsi_print_reset_status(struct platform_device *dsidev)
 		b2 = 26;
 	}
 
-	l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
-	printk("PHY (%x%x%x, %d, %d, %d)\n",
-			FLD_GET(l, b0, b0),
-			FLD_GET(l, b1, b1),
-			FLD_GET(l, b2, b2),
-			FLD_GET(l, 29, 29),
-			FLD_GET(l, 30, 30),
-			FLD_GET(l, 31, 31));
+#define DSI_FLD_GET(fld, start, end)\
+	FLD_GET(dsi_read_reg(dsidev, DSI_##fld), start, end)
+
+	pr_debug("DSI resets: PLL (%d) CIO (%d) PHY (%x%x%x, %d, %d, %d)\n",
+		DSI_FLD_GET(PLL_STATUS, 0, 0),
+		DSI_FLD_GET(COMPLEXIO_CFG1, 29, 29),
+		DSI_FLD_GET(DSIPHY_CFG5, b0, b0),
+		DSI_FLD_GET(DSIPHY_CFG5, b1, b1),
+		DSI_FLD_GET(DSIPHY_CFG5, b2, b2),
+		DSI_FLD_GET(DSIPHY_CFG5, 29, 29),
+		DSI_FLD_GET(DSIPHY_CFG5, 30, 30),
+		DSI_FLD_GET(DSIPHY_CFG5, 31, 31));
+
+#undef DSI_FLD_GET
 }
-#else
-#define _dsi_print_reset_status(x)
-#endif
 
 static inline int dsi_if_enable(struct platform_device *dsidev, bool enable)
 {
@@ -1407,6 +1386,11 @@ retry:
 				cur.dsi_pll_hsdiv_dispc_clk =
 					cur.clkin4ddr / cur.regm_dispc;
 
+				if (cur.regm_dispc > 1 &&
+						cur.regm_dispc % 2 != 0 &&
+						req_pck >= 1000000)
+					continue;
+
 				/* this will narrow down the search a bit,
 				 * but still give pixclocks below what was
 				 * requested */
@@ -1621,7 +1605,7 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
 	u8 regn_start, regn_end, regm_start, regm_end;
 	u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
 
-	DSSDBGF();
+	DSSDBG("DSI PLL clock config starts");
 
 	dsi->current_cinfo.clkin = cinfo->clkin;
 	dsi->current_cinfo.fint = cinfo->fint;
@@ -1757,11 +1741,21 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
 
 	DSSDBG("PLL init\n");
 
+	/*
+	 * It seems that on many OMAPs we need to enable both to have a
+	 * functional HSDivider.
+	 */
+	enable_hsclk = enable_hsdiv = true;
+
 	if (dsi->vdds_dsi_reg == NULL) {
 		struct regulator *vdds_dsi;
 
 		vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
 
+		/* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
+		if (IS_ERR(vdds_dsi))
+			vdds_dsi = regulator_get(&dsi->pdev->dev, "VCXIO");
+
 		if (IS_ERR(vdds_dsi)) {
 			DSSERR("can't get VDDS_DSI regulator\n");
 			return PTR_ERR(vdds_dsi);
@@ -2440,7 +2434,7 @@ static int dsi_cio_init(struct platform_device *dsidev)
 	int r;
 	u32 l;
 
-	DSSDBGF();
+	DSSDBG("DSI CIO init starts");
 
 	r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
 	if (r)
@@ -2791,7 +2785,7 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
 {
 	u32 r;
 
-	DSSDBGF("%d", channel);
+	DSSDBG("Initial config of virtual channel %d", channel);
 
 	r = dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
 
@@ -2823,7 +2817,7 @@ static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
 	if (dsi->vc[channel].source == source)
 		return 0;
 
-	DSSDBGF("%d", channel);
+	DSSDBG("Source config of virtual channel %d", channel);
 
 	dsi_sync_vc(dsidev, channel);
 
@@ -3581,7 +3575,7 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
 	int r, i;
 	unsigned mask;
 
-	DSSDBGF();
+	DSSDBG("Entering ULPS");
 
 	WARN_ON(!dsi_bus_is_locked(dsidev));
 
@@ -4285,7 +4279,7 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
 	unsigned long pck;
 	int r;
 
-	DSSDBGF("ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
+	DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
 
 	mutex_lock(&dsi->lock);
 
@@ -4730,7 +4724,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
 	if (r)
 		goto err1;
 
-	dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
 	dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src);
 	dss_select_lcd_clk_source(mgr->id,
 			dssdev->clocks.dispc.channel.lcd_clk_src);
@@ -4765,7 +4758,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
 err3:
 	dsi_cio_uninit(dsidev);
 err2:
-	dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
 	dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
 	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
 
@@ -4792,7 +4784,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
 	dsi_vc_enable(dsidev, 2, 0);
 	dsi_vc_enable(dsidev, 3, 0);
 
-	dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
 	dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
 	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
 	dsi_cio_uninit(dsidev);
@@ -4981,6 +4972,10 @@ static int __init dsi_init_display(struct omap_dss_device *dssdev)
 
 		vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
 
+		/* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
+		if (IS_ERR(vdds_dsi))
+			vdds_dsi = regulator_get(&dsi->pdev->dev, "VCXIO");
+
 		if (IS_ERR(vdds_dsi)) {
 			DSSERR("can't get VDDS_DSI regulator\n");
 			return PTR_ERR(vdds_dsi);
@@ -5121,7 +5116,7 @@ static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *p
 {
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
 	struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
-	const char *def_disp_name = dss_get_default_display_name();
+	const char *def_disp_name = omapdss_get_default_display_name();
 	struct omap_dss_device *def_dssdev;
 	int i;
 
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 5f6eea8..6ca69d5 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -32,11 +32,10 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/gfp.h>
+#include <linux/sizes.h>
 
 #include <video/omapdss.h>
 
-#include <plat/cpu.h>
-
 #include "dss.h"
 #include "dss_features.h"
 
@@ -98,6 +97,8 @@ static const char * const dss_generic_clk_source_names[] = {
 	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "DSI_PLL_HSDIV_DISPC",
 	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]	= "DSI_PLL_HSDIV_DSI",
 	[OMAP_DSS_CLK_SRC_FCK]			= "DSS_FCK",
+	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC]	= "DSI_PLL2_HSDIV_DISPC",
+	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI]	= "DSI_PLL2_HSDIV_DSI",
 };
 
 static inline void dss_write_reg(const struct dss_reg idx, u32 val)
@@ -303,7 +304,7 @@ static void dss_dump_regs(struct seq_file *s)
 #undef DUMPREG
 }
 
-void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
+static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
 {
 	struct platform_device *dsidev;
 	int b;
@@ -374,8 +375,10 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
 	struct platform_device *dsidev;
 	int b, ix, pos;
 
-	if (!dss_has_feature(FEAT_LCD_CLK_SRC))
+	if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
+		dss_select_dispc_clk_source(clk_src);
 		return;
+	}
 
 	switch (clk_src) {
 	case OMAP_DSS_CLK_SRC_FCK:
@@ -431,6 +434,29 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
 	}
 }
 
+/* calculate clock rates using dividers in cinfo */
+int dss_calc_clock_rates(struct dss_clock_info *cinfo)
+{
+	if (dss.dpll4_m4_ck) {
+		unsigned long prate;
+
+		if (cinfo->fck_div > dss.feat->fck_div_max ||
+				cinfo->fck_div == 0)
+			return -EINVAL;
+
+		prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
+
+		cinfo->fck = prate / cinfo->fck_div *
+			dss.feat->dss_fck_multiplier;
+	} else {
+		if (cinfo->fck_div != 0)
+			return -EINVAL;
+		cinfo->fck = clk_get_rate(dss.dss_clk);
+	}
+
+	return 0;
+}
+
 int dss_set_clock_div(struct dss_clock_info *cinfo)
 {
 	if (dss.dpll4_m4_ck) {
@@ -461,6 +487,36 @@ unsigned long dss_get_dpll4_rate(void)
 		return 0;
 }
 
+static int dss_setup_default_clock(void)
+{
+	unsigned long max_dss_fck, prate;
+	unsigned fck_div;
+	struct dss_clock_info dss_cinfo = { 0 };
+	int r;
+
+	if (dss.dpll4_m4_ck == NULL)
+		return 0;
+
+	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+
+	prate = dss_get_dpll4_rate();
+
+	fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
+			max_dss_fck);
+
+	dss_cinfo.fck_div = fck_div;
+
+	r = dss_calc_clock_rates(&dss_cinfo);
+	if (r)
+		return r;
+
+	r = dss_set_clock_div(&dss_cinfo);
+	if (r)
+		return r;
+
+	return 0;
+}
+
 int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
 		struct dispc_clock_info *dispc_cinfo)
 {
@@ -750,7 +806,7 @@ static void dss_runtime_put(void)
 }
 
 /* DEBUGFS */
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
 void dss_debug_dump_clocks(struct seq_file *s)
 {
 	dss_dump_clocks(s);
@@ -796,29 +852,45 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
 	.dpi_select_source	=	&dss_dpi_select_source_omap5,
 };
 
-static int __init dss_init_features(struct device *dev)
+static int __init dss_init_features(struct platform_device *pdev)
 {
 	const struct dss_features *src;
 	struct dss_features *dst;
 
-	dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
+	dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
 	if (!dst) {
-		dev_err(dev, "Failed to allocate local DSS Features\n");
+		dev_err(&pdev->dev, "Failed to allocate local DSS Features\n");
 		return -ENOMEM;
 	}
 
-	if (cpu_is_omap24xx())
+	switch (omapdss_get_version()) {
+	case OMAPDSS_VER_OMAP24xx:
 		src = &omap24xx_dss_feats;
-	else if (cpu_is_omap3630())
-		src = &omap3630_dss_feats;
-	else if (cpu_is_omap34xx())
+		break;
+
+	case OMAPDSS_VER_OMAP34xx_ES1:
+	case OMAPDSS_VER_OMAP34xx_ES3:
+	case OMAPDSS_VER_AM35xx:
 		src = &omap34xx_dss_feats;
-	else if (cpu_is_omap44xx())
+		break;
+
+	case OMAPDSS_VER_OMAP3630:
+		src = &omap3630_dss_feats;
+		break;
+
+	case OMAPDSS_VER_OMAP4430_ES1:
+	case OMAPDSS_VER_OMAP4430_ES2:
+	case OMAPDSS_VER_OMAP4:
 		src = &omap44xx_dss_feats;
-	else if (soc_is_omap54xx())
+		break;
+
+	case OMAPDSS_VER_OMAP5:
 		src = &omap54xx_dss_feats;
-	else
+		break;
+
+	default:
 		return -ENODEV;
+	}
 
 	memcpy(dst, src, sizeof(*dst));
 	dss.feat = dst;
@@ -835,7 +907,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
 
 	dss.pdev = pdev;
 
-	r = dss_init_features(&dss.pdev->dev);
+	r = dss_init_features(dss.pdev);
 	if (r)
 		return r;
 
@@ -856,6 +928,10 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
 	if (r)
 		return r;
 
+	r = dss_setup_default_clock();
+	if (r)
+		goto err_setup_clocks;
+
 	pm_runtime_enable(&pdev->dev);
 
 	r = dss_runtime_get();
@@ -865,6 +941,8 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
 	/* Select DPLL */
 	REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
 
+	dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
+
 #ifdef CONFIG_OMAP2_DSS_VENC
 	REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);	/* venc dac demen */
 	REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);	/* venc clock 4x enable */
@@ -888,6 +966,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
 
 err_runtime_get:
 	pm_runtime_disable(&pdev->dev);
+err_setup_clocks:
 	dss_put_clocks();
 	return r;
 }
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 6728892..84a7f6a 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -23,44 +23,18 @@
 #ifndef __OMAP2_DSS_H
 #define __OMAP2_DSS_H
 
-#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT
-#define DEBUG
+#ifdef pr_fmt
+#undef pr_fmt
 #endif
 
-#ifdef DEBUG
-extern bool dss_debug;
 #ifdef DSS_SUBSYS_NAME
-#define DSSDBG(format, ...) \
-	if (dss_debug) \
-		printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \
-		## __VA_ARGS__)
+#define pr_fmt(fmt) DSS_SUBSYS_NAME ": " fmt
 #else
-#define DSSDBG(format, ...) \
-	if (dss_debug) \
-		printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__)
-#endif
-
-#ifdef DSS_SUBSYS_NAME
-#define DSSDBGF(format, ...) \
-	if (dss_debug) \
-		printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \
-				": %s(" format ")\n", \
-				__func__, \
-				## __VA_ARGS__)
-#else
-#define DSSDBGF(format, ...) \
-	if (dss_debug) \
-		printk(KERN_DEBUG "omapdss: " \
-				": %s(" format ")\n", \
-				__func__, \
-				## __VA_ARGS__)
-#endif
-
-#else /* DEBUG */
-#define DSSDBG(format, ...)
-#define DSSDBGF(format, ...)
+#define pr_fmt(fmt) fmt
 #endif
 
+#define DSSDBG(format, ...) \
+	pr_debug(format, ## __VA_ARGS__)
 
 #ifdef DSS_SUBSYS_NAME
 #define DSSERR(format, ...) \
@@ -186,7 +160,6 @@ struct seq_file;
 struct platform_device;
 
 /* core */
-const char *dss_get_default_display_name(void);
 struct bus_type *dss_get_bus(void);
 struct regulator *dss_get_vdds_dsi(void);
 struct regulator *dss_get_vdds_sdi(void);
@@ -217,9 +190,6 @@ int dss_mgr_set_info(struct omap_overlay_manager *mgr,
 		struct omap_overlay_manager_info *info);
 void dss_mgr_get_info(struct omap_overlay_manager *mgr,
 		struct omap_overlay_manager_info *info);
-int dss_mgr_set_device(struct omap_overlay_manager *mgr,
-		struct omap_dss_device *dssdev);
-int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
 int dss_mgr_set_output(struct omap_overlay_manager *mgr,
 		struct omap_dss_output *output);
 int dss_mgr_unset_output(struct omap_overlay_manager *mgr);
@@ -305,7 +275,7 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
 const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
 void dss_dump_clocks(struct seq_file *s);
 
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
 void dss_debug_dump_clocks(struct seq_file *s);
 #endif
 
@@ -313,7 +283,6 @@ void dss_sdi_init(int datapairs);
 int dss_sdi_enable(void);
 void dss_sdi_disable(void);
 
-void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src);
 void dss_select_dsi_clk_source(int dsi_module,
 		enum omap_dss_clk_source clk_src);
 void dss_select_lcd_clk_source(enum omap_channel channel,
@@ -326,6 +295,7 @@ void dss_set_venc_output(enum omap_dss_venc_type type);
 void dss_set_dac_pwrdn_bgz(bool enable);
 
 unsigned long dss_get_dpll4_rate(void);
+int dss_calc_clock_rates(struct dss_clock_info *cinfo);
 int dss_set_clock_div(struct dss_clock_info *cinfo);
 int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
 		struct dispc_clock_info *dispc_cinfo);
@@ -427,7 +397,10 @@ void dpi_uninit_platform_driver(void) __exit;
 int dispc_init_platform_driver(void) __init;
 void dispc_uninit_platform_driver(void) __exit;
 void dispc_dump_clocks(struct seq_file *s);
-void dispc_irq_handler(void);
+u32 dispc_read_irqstatus(void);
+void dispc_clear_irqstatus(u32 mask);
+u32 dispc_read_irqenable(void);
+void dispc_write_irqenable(u32 mask);
 
 int dispc_runtime_get(void);
 void dispc_runtime_put(void);
@@ -435,7 +408,6 @@ void dispc_runtime_put(void);
 void dispc_enable_sidle(void);
 void dispc_disable_sidle(void);
 
-void dispc_lcd_enable_signal_polarity(bool act_high);
 void dispc_lcd_enable_signal(bool enable);
 void dispc_pck_free_enable(bool enable);
 void dispc_enable_fifomerge(bool enable);
@@ -459,32 +431,33 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
 		bool replication, const struct omap_video_timings *mgr_timings,
 		bool mem_to_mem);
 int dispc_ovl_enable(enum omap_plane plane, bool enable);
+bool dispc_ovl_enabled(enum omap_plane plane);
 void dispc_ovl_set_channel_out(enum omap_plane plane,
 		enum omap_channel channel);
 
-void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable);
 u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
 u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
+u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel);
 bool dispc_mgr_go_busy(enum omap_channel channel);
 void dispc_mgr_go(enum omap_channel channel);
-bool dispc_mgr_is_enabled(enum omap_channel channel);
 void dispc_mgr_enable(enum omap_channel channel, bool enable);
+bool dispc_mgr_is_enabled(enum omap_channel channel);
+void dispc_mgr_enable_sync(enum omap_channel channel);
+void dispc_mgr_disable_sync(enum omap_channel channel);
 bool dispc_mgr_is_channel_enabled(enum omap_channel channel);
-void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode);
-void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable);
-void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
-void dispc_mgr_set_lcd_type_tft(enum omap_channel channel);
+void dispc_mgr_set_lcd_config(enum omap_channel channel,
+		const struct dss_lcd_mgr_config *config);
 void dispc_mgr_set_timings(enum omap_channel channel,
-		struct omap_video_timings *timings);
+		const struct omap_video_timings *timings);
 unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
 unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
 unsigned long dispc_core_clk_rate(void);
 void dispc_mgr_set_clock_div(enum omap_channel channel,
-		struct dispc_clock_info *cinfo);
+		const struct dispc_clock_info *cinfo);
 int dispc_mgr_get_clock_div(enum omap_channel channel,
 		struct dispc_clock_info *cinfo);
 void dispc_mgr_setup(enum omap_channel channel,
-		struct omap_overlay_manager_info *info);
+		const struct omap_overlay_manager_info *info);
 
 u32 dispc_wb_get_framedone_irq(void);
 bool dispc_wb_go_busy(void);
@@ -536,6 +509,8 @@ static inline unsigned long hdmi_get_pixel_clock(void)
 #endif
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
+int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev);
+void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev);
 void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings);
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index acbc1e1..1d125c6 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -23,7 +23,6 @@
 #include <linux/slab.h>
 
 #include <video/omapdss.h>
-#include <plat/cpu.h>
 
 #include "dss.h"
 #include "dss_features.h"
@@ -430,8 +429,6 @@ static const struct dss_param_range omap2_dss_param_range[] = {
 	 * scaler cannot scale a image with width more than 768.
 	 */
 	[FEAT_PARAM_LINEWIDTH]			= { 1, 768 },
-	[FEAT_PARAM_MGR_WIDTH]			= { 1, 2048 },
-	[FEAT_PARAM_MGR_HEIGHT]			= { 1, 2048 },
 };
 
 static const struct dss_param_range omap3_dss_param_range[] = {
@@ -446,8 +443,6 @@ static const struct dss_param_range omap3_dss_param_range[] = {
 	[FEAT_PARAM_DSI_FCK]			= { 0, 173000000 },
 	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
 	[FEAT_PARAM_LINEWIDTH]			= { 1, 1024 },
-	[FEAT_PARAM_MGR_WIDTH]			= { 1, 2048 },
-	[FEAT_PARAM_MGR_HEIGHT]			= { 1, 2048 },
 };
 
 static const struct dss_param_range omap4_dss_param_range[] = {
@@ -462,8 +457,6 @@ static const struct dss_param_range omap4_dss_param_range[] = {
 	[FEAT_PARAM_DSI_FCK]			= { 0, 170000000 },
 	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
 	[FEAT_PARAM_LINEWIDTH]			= { 1, 2048 },
-	[FEAT_PARAM_MGR_WIDTH]			= { 1, 2048 },
-	[FEAT_PARAM_MGR_HEIGHT]			= { 1, 2048 },
 };
 
 static const struct dss_param_range omap5_dss_param_range[] = {
@@ -478,8 +471,6 @@ static const struct dss_param_range omap5_dss_param_range[] = {
 	[FEAT_PARAM_DSI_FCK]			= { 0, 170000000 },
 	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
 	[FEAT_PARAM_LINEWIDTH]			= { 1, 2048 },
-	[FEAT_PARAM_MGR_WIDTH]			= { 1, 2048 },
-	[FEAT_PARAM_MGR_HEIGHT]			= { 1, 2048 },
 };
 
 static const enum dss_feat_id omap2_dss_feat_list[] = {
@@ -821,14 +812,25 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
 	.audio_start		=       ti_hdmi_4xxx_audio_start,
 	.audio_stop		=       ti_hdmi_4xxx_audio_stop,
 	.audio_config		=	ti_hdmi_4xxx_audio_config,
+	.audio_get_dma_port	=	ti_hdmi_4xxx_audio_get_dma_port,
 #endif
 
 };
 
-void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data)
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data,
+		enum omapdss_version version)
 {
-	if (cpu_is_omap44xx())
+	switch (version) {
+	case OMAPDSS_VER_OMAP4430_ES1:
+	case OMAPDSS_VER_OMAP4430_ES2:
+	case OMAPDSS_VER_OMAP4:
 		ip_data->ops = &omap4_hdmi_functions;
+		break;
+	default:
+		ip_data->ops = NULL;
+	}
+
+	WARN_ON(ip_data->ops == NULL);
 }
 #endif
 
@@ -929,29 +931,44 @@ bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type)
 	return omap_current_dss_features->supported_rotation_types & rot_type;
 }
 
-void dss_features_init(void)
+void dss_features_init(enum omapdss_version version)
 {
-	if (cpu_is_omap24xx())
+	switch (version) {
+	case OMAPDSS_VER_OMAP24xx:
 		omap_current_dss_features = &omap2_dss_features;
-	else if (cpu_is_omap3630())
+		break;
+
+	case OMAPDSS_VER_OMAP34xx_ES1:
+	case OMAPDSS_VER_OMAP34xx_ES3:
+		omap_current_dss_features = &omap3430_dss_features;
+		break;
+
+	case OMAPDSS_VER_OMAP3630:
 		omap_current_dss_features = &omap3630_dss_features;
-	else if (cpu_is_omap34xx()) {
-		if (soc_is_am35xx()) {
-			omap_current_dss_features = &am35xx_dss_features;
-		} else {
-			omap_current_dss_features = &omap3430_dss_features;
-		}
-	}
-	else if (omap_rev() == OMAP4430_REV_ES1_0)
+		break;
+
+	case OMAPDSS_VER_OMAP4430_ES1:
 		omap_current_dss_features = &omap4430_es1_0_dss_features;
-	else if (omap_rev() == OMAP4430_REV_ES2_0 ||
-		omap_rev() == OMAP4430_REV_ES2_1 ||
-		omap_rev() == OMAP4430_REV_ES2_2)
+		break;
+
+	case OMAPDSS_VER_OMAP4430_ES2:
 		omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
-	else if (cpu_is_omap44xx())
+		break;
+
+	case OMAPDSS_VER_OMAP4:
 		omap_current_dss_features = &omap4_dss_features;
-	else if (soc_is_omap54xx())
+		break;
+
+	case OMAPDSS_VER_OMAP5:
 		omap_current_dss_features = &omap5_dss_features;
-	else
+		break;
+
+	case OMAPDSS_VER_AM35xx:
+		omap_current_dss_features = &am35xx_dss_features;
+		break;
+
+	default:
 		DSSWARN("Unsupported OMAP version");
+		break;
+	}
 }
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 9218113..385b0af 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -98,8 +98,6 @@ enum dss_range_param {
 	FEAT_PARAM_DSI_FCK,
 	FEAT_PARAM_DOWNSCALE,
 	FEAT_PARAM_LINEWIDTH,
-	FEAT_PARAM_MGR_WIDTH,
-	FEAT_PARAM_MGR_HEIGHT,
 };
 
 /* DSS Feature Functions */
@@ -123,8 +121,9 @@ bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type);
 
 bool dss_has_feature(enum dss_feat_id id);
 void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
-void dss_features_init(void);
+void dss_features_init(enum omapdss_version version);
 #if defined(CONFIG_OMAP4_DSS_HDMI)
-void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data);
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data,
+		enum omapdss_version version);
 #endif
 #endif
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 8c9b8b3..24a2eef 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -60,6 +60,7 @@
 static struct {
 	struct mutex lock;
 	struct platform_device *pdev;
+
 	struct hdmi_ip_data ip_data;
 
 	struct clk *sys_clk;
@@ -295,6 +296,12 @@ static const struct hdmi_config vesa_timings[] = {
 			false, },
 		{ 0x55, HDMI_DVI },
 	},
+	{
+		{ 1920, 1200, 154000, 32, 48, 80, 6, 3, 26,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x44, HDMI_DVI },
+	},
 };
 
 static int hdmi_runtime_get(void)
@@ -333,13 +340,17 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
 
 	DSSDBG("init_display\n");
 
-	dss_init_hdmi_ip_ops(&hdmi.ip_data);
+	dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version());
 
 	if (hdmi.vdda_hdmi_dac_reg == NULL) {
 		struct regulator *reg;
 
 		reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
 
+		/* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */
+		if (IS_ERR(reg))
+			reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC");
+
 		if (IS_ERR(reg)) {
 			DSSERR("can't get VDDA_HDMI_DAC regulator\n");
 			return PTR_ERR(reg);
@@ -355,7 +366,7 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
 	return 0;
 }
 
-static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev)
+static void hdmi_uninit_display(struct omap_dss_device *dssdev)
 {
 	DSSDBG("uninit_display\n");
 
@@ -398,7 +409,8 @@ static bool hdmi_timings_compare(struct omap_video_timings *timing1,
 {
 	int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
 
-	if ((timing2->pixel_clock == timing1->pixel_clock) &&
+	if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) ==
+			DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) &&
 		(timing2->x_res == timing1->x_res) &&
 		(timing2->y_res == timing1->y_res)) {
 
@@ -500,12 +512,9 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
 	DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
 }
 
-static int hdmi_power_on(struct omap_dss_device *dssdev)
+static int hdmi_power_on_core(struct omap_dss_device *dssdev)
 {
 	int r;
-	struct omap_video_timings *p;
-	struct omap_overlay_manager *mgr = dssdev->output->manager;
-	unsigned long phy;
 
 	gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
 	gpio_set_value(hdmi.ls_oe_gpio, 1);
@@ -521,6 +530,38 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 	if (r)
 		goto err_runtime_get;
 
+	/* Make selection of HDMI in DSS */
+	dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
+
+	return 0;
+
+err_runtime_get:
+	regulator_disable(hdmi.vdda_hdmi_dac_reg);
+err_vdac_enable:
+	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
+	gpio_set_value(hdmi.ls_oe_gpio, 0);
+	return r;
+}
+
+static void hdmi_power_off_core(struct omap_dss_device *dssdev)
+{
+	hdmi_runtime_put();
+	regulator_disable(hdmi.vdda_hdmi_dac_reg);
+	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
+	gpio_set_value(hdmi.ls_oe_gpio, 0);
+}
+
+static int hdmi_power_on_full(struct omap_dss_device *dssdev)
+{
+	int r;
+	struct omap_video_timings *p;
+	struct omap_overlay_manager *mgr = dssdev->output->manager;
+	unsigned long phy;
+
+	r = hdmi_power_on_core(dssdev);
+	if (r)
+		return r;
+
 	dss_mgr_disable(mgr);
 
 	p = &hdmi.ip_data.cfg.timings;
@@ -548,17 +589,6 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 
 	hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
 
-	/* Make selection of HDMI in DSS */
-	dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
-
-	/* Select the dispc clock source as PRCM clock, to ensure that it is not
-	 * DSI PLL source as the clock selected by DSI PLL might not be
-	 * sufficient for the resolution selected / that can be changed
-	 * dynamically by user. This can be moved to single location , say
-	 * Boardfile.
-	 */
-	dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
-
 	/* bypass TV gamma table */
 	dispc_enable_gamma_table(0);
 
@@ -582,16 +612,11 @@ err_vid_enable:
 err_phy_enable:
 	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
 err_pll_enable:
-	hdmi_runtime_put();
-err_runtime_get:
-	regulator_disable(hdmi.vdda_hdmi_dac_reg);
-err_vdac_enable:
-	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
-	gpio_set_value(hdmi.ls_oe_gpio, 0);
+	hdmi_power_off_core(dssdev);
 	return -EIO;
 }
 
-static void hdmi_power_off(struct omap_dss_device *dssdev)
+static void hdmi_power_off_full(struct omap_dss_device *dssdev)
 {
 	struct omap_overlay_manager *mgr = dssdev->output->manager;
 
@@ -600,12 +625,8 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
 	hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
 	hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
 	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
-	hdmi_runtime_put();
-
-	regulator_disable(hdmi.vdda_hdmi_dac_reg);
 
-	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
-	gpio_set_value(hdmi.ls_oe_gpio, 0);
+	hdmi_power_off_core(dssdev);
 }
 
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -715,7 +736,7 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
 		goto err0;
 	}
 
-	r = hdmi_power_on(dssdev);
+	r = hdmi_power_on_full(dssdev);
 	if (r) {
 		DSSERR("failed to power on device\n");
 		goto err1;
@@ -737,13 +758,48 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
 
 	mutex_lock(&hdmi.lock);
 
-	hdmi_power_off(dssdev);
+	hdmi_power_off_full(dssdev);
 
 	omap_dss_stop_device(dssdev);
 
 	mutex_unlock(&hdmi.lock);
 }
 
+int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev)
+{
+	int r = 0;
+
+	DSSDBG("ENTER omapdss_hdmi_core_enable\n");
+
+	mutex_lock(&hdmi.lock);
+
+	hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
+
+	r = hdmi_power_on_core(dssdev);
+	if (r) {
+		DSSERR("failed to power on device\n");
+		goto err0;
+	}
+
+	mutex_unlock(&hdmi.lock);
+	return 0;
+
+err0:
+	mutex_unlock(&hdmi.lock);
+	return r;
+}
+
+void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev)
+{
+	DSSDBG("Enter omapdss_hdmi_core_disable\n");
+
+	mutex_lock(&hdmi.lock);
+
+	hdmi_power_off_core(dssdev);
+
+	mutex_unlock(&hdmi.lock);
+}
+
 static int hdmi_get_clocks(struct platform_device *pdev)
 {
 	struct clk *clk;
@@ -912,7 +968,7 @@ int hdmi_audio_config(struct omap_dss_audio *audio)
 static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
 {
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-	const char *def_disp_name = dss_get_default_display_name();
+	const char *def_disp_name = omapdss_get_default_display_name();
 	struct omap_dss_device *def_dssdev;
 	int i;
 
@@ -973,6 +1029,7 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
 	r = dss_add_device(dssdev);
 	if (r) {
 		DSSERR("device %s register failed: %d\n", dssdev->name, r);
+		hdmi_uninit_display(dssdev);
 		dss_put_device(dssdev);
 		return;
 	}
@@ -999,22 +1056,22 @@ static void __exit hdmi_uninit_output(struct platform_device *pdev)
 /* HDMI HW IP initialisation */
 static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
 {
-	struct resource *hdmi_mem;
+	struct resource *res;
 	int r;
 
 	hdmi.pdev = pdev;
 
 	mutex_init(&hdmi.lock);
+	mutex_init(&hdmi.ip_data.lock);
 
-	hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
-	if (!hdmi_mem) {
+	res = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
+	if (!res) {
 		DSSERR("can't get IORESOURCE_MEM HDMI\n");
 		return -EINVAL;
 	}
 
 	/* Base address taken from platform */
-	hdmi.ip_data.base_wp = ioremap(hdmi_mem->start,
-						resource_size(hdmi_mem));
+	hdmi.ip_data.base_wp = devm_request_and_ioremap(&pdev->dev, res);
 	if (!hdmi.ip_data.base_wp) {
 		DSSERR("can't ioremap WP\n");
 		return -ENOMEM;
@@ -1022,7 +1079,7 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
 
 	r = hdmi_get_clocks(pdev);
 	if (r) {
-		iounmap(hdmi.ip_data.base_wp);
+		DSSERR("can't get clocks\n");
 		return r;
 	}
 
@@ -1033,9 +1090,11 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
 	hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
 	hdmi.ip_data.phy_offset = HDMI_PHY;
 
-	mutex_init(&hdmi.ip_data.lock);
-
-	hdmi_panel_init();
+	r = hdmi_panel_init();
+	if (r) {
+		DSSERR("can't init panel\n");
+		goto err_panel_init;
+	}
 
 	dss_debugfs_create_file("hdmi", hdmi_dump_regs);
 
@@ -1044,6 +1103,10 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
 	hdmi_probe_pdata(pdev);
 
 	return 0;
+
+err_panel_init:
+	hdmi_put_clocks();
+	return r;
 }
 
 static int __exit hdmi_remove_child(struct device *dev, void *data)
@@ -1067,8 +1130,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
 
 	hdmi_put_clocks();
 
-	iounmap(hdmi.ip_data.base_wp);
-
 	return 0;
 }
 
diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
index 69fb115..dfb8eda 100644
--- a/drivers/video/omap2/dss/hdmi_panel.c
+++ b/drivers/video/omap2/dss/hdmi_panel.c
@@ -280,58 +280,6 @@ static void hdmi_panel_disable(struct omap_dss_device *dssdev)
 	mutex_unlock(&hdmi.lock);
 }
 
-static int hdmi_panel_suspend(struct omap_dss_device *dssdev)
-{
-	int r = 0;
-
-	mutex_lock(&hdmi.lock);
-
-	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
-		r = -EINVAL;
-		goto err;
-	}
-
-	/*
-	 * TODO: notify audio users that the display was suspended. For now,
-	 * disable audio locally to not break our audio state machine.
-	 */
-	hdmi_panel_audio_disable(dssdev);
-
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-	omapdss_hdmi_display_disable(dssdev);
-
-err:
-	mutex_unlock(&hdmi.lock);
-
-	return r;
-}
-
-static int hdmi_panel_resume(struct omap_dss_device *dssdev)
-{
-	int r = 0;
-
-	mutex_lock(&hdmi.lock);
-
-	if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
-		r = -EINVAL;
-		goto err;
-	}
-
-	r = omapdss_hdmi_display_enable(dssdev);
-	if (r) {
-		DSSERR("failed to power on\n");
-		goto err;
-	}
-	/* TODO: notify audio users that the panel resumed. */
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-err:
-	mutex_unlock(&hdmi.lock);
-
-	return r;
-}
-
 static void hdmi_get_timings(struct omap_dss_device *dssdev,
 			struct omap_video_timings *timings)
 {
@@ -379,20 +327,22 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
 static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
 {
 	int r;
+	bool need_enable;
 
 	mutex_lock(&hdmi.lock);
 
-	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
-		r = omapdss_hdmi_display_enable(dssdev);
+	need_enable = dssdev->state == OMAP_DSS_DISPLAY_DISABLED;
+
+	if (need_enable) {
+		r = omapdss_hdmi_core_enable(dssdev);
 		if (r)
 			goto err;
 	}
 
 	r = omapdss_hdmi_read_edid(buf, len);
 
-	if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
-			dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
-		omapdss_hdmi_display_disable(dssdev);
+	if (need_enable)
+		omapdss_hdmi_core_disable(dssdev);
 err:
 	mutex_unlock(&hdmi.lock);
 
@@ -402,20 +352,22 @@ err:
 static bool hdmi_detect(struct omap_dss_device *dssdev)
 {
 	int r;
+	bool need_enable;
 
 	mutex_lock(&hdmi.lock);
 
-	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
-		r = omapdss_hdmi_display_enable(dssdev);
+	need_enable = dssdev->state == OMAP_DSS_DISPLAY_DISABLED;
+
+	if (need_enable) {
+		r = omapdss_hdmi_core_enable(dssdev);
 		if (r)
 			goto err;
 	}
 
 	r = omapdss_hdmi_detect();
 
-	if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
-			dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
-		omapdss_hdmi_display_disable(dssdev);
+	if (need_enable)
+		omapdss_hdmi_core_disable(dssdev);
 err:
 	mutex_unlock(&hdmi.lock);
 
@@ -427,8 +379,6 @@ static struct omap_dss_driver hdmi_driver = {
 	.remove		= hdmi_panel_remove,
 	.enable		= hdmi_panel_enable,
 	.disable	= hdmi_panel_disable,
-	.suspend	= hdmi_panel_suspend,
-	.resume		= hdmi_panel_resume,
 	.get_timings	= hdmi_get_timings,
 	.set_timings	= hdmi_set_timings,
 	.check_timings	= hdmi_check_timings,
@@ -454,9 +404,7 @@ int hdmi_panel_init(void)
 	spin_lock_init(&hdmi.audio_lock);
 #endif
 
-	omap_dss_register_driver(&hdmi_driver);
-
-	return 0;
+	return omap_dss_register_driver(&hdmi_driver);
 }
 
 void hdmi_panel_exit(void)
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 7282e5a..7bfeb13 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -950,7 +950,7 @@ static int __init rfbi_init_display(struct omap_dss_device *dssdev)
 static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
 {
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-	const char *def_disp_name = dss_get_default_display_name();
+	const char *def_disp_name = omapdss_get_default_display_name();
 	struct omap_dss_device *def_dssdev;
 	int i;
 
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 7760851..882ce89 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -205,7 +205,7 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev)
 static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev)
 {
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-	const char *def_disp_name = dss_get_default_display_name();
+	const char *def_disp_name = omapdss_get_default_display_name();
 	struct omap_dss_device *def_dssdev;
 	int i;
 
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h
index b046c20..216aa70 100644
--- a/drivers/video/omap2/dss/ti_hdmi.h
+++ b/drivers/video/omap2/dss/ti_hdmi.h
@@ -102,6 +102,8 @@ struct ti_hdmi_ip_ops {
 
 	int (*audio_config)(struct hdmi_ip_data *ip_data,
 		struct omap_dss_audio *audio);
+
+	int (*audio_get_dma_port)(u32 *offset, u32 *size);
 #endif
 
 };
@@ -183,5 +185,6 @@ int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data);
 void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data);
 int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
 		struct omap_dss_audio *audio);
+int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size);
 #endif
 #endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
index c23b85a..e18b222 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
@@ -899,7 +899,7 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
 #define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\
 		hdmi_read_reg(hdmi_av_base(ip_data), r))
 #define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
-		(i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \
+		(i < 10) ? 32 - (int)strlen(#r) : 31 - (int)strlen(#r), " ", \
 		hdmi_read_reg(hdmi_av_base(ip_data), CORE_REG(i, r)))
 
 	DUMPCORE(HDMI_CORE_SYS_VND_IDL);
@@ -1418,4 +1418,13 @@ void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data)
 	REG_FLD_MOD(hdmi_wp_base(ip_data),
 		    HDMI_WP_AUDIO_CTRL, false, 30, 30);
 }
+
+int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size)
+{
+	if (!offset || !size)
+		return -EINVAL;
+	*offset = HDMI_WP_AUDIO_DATA;
+	*size = 4;
+	return 0;
+}
 #endif
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 56efa3b..e8fddc9 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -744,7 +744,7 @@ static void venc_put_clocks(void)
 static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
 {
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-	const char *def_disp_name = dss_get_default_display_name();
+	const char *def_disp_name = omapdss_get_default_display_name();
 	struct omap_dss_device *def_dssdev;
 	int i;
 
diff --git a/drivers/video/omap2/dss/venc_panel.c b/drivers/video/omap2/dss/venc_panel.c
index d55b878..0d2b1a0 100644
--- a/drivers/video/omap2/dss/venc_panel.c
+++ b/drivers/video/omap2/dss/venc_panel.c
@@ -157,12 +157,6 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
 	if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
 		goto end;
 
-	if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
-		/* suspended is the same as disabled with venc */
-		dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-		goto end;
-	}
-
 	omapdss_venc_display_disable(dssdev);
 
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
@@ -170,17 +164,6 @@ end:
 	mutex_unlock(&venc_panel.lock);
 }
 
-static int venc_panel_suspend(struct omap_dss_device *dssdev)
-{
-	venc_panel_disable(dssdev);
-	return 0;
-}
-
-static int venc_panel_resume(struct omap_dss_device *dssdev)
-{
-	return venc_panel_enable(dssdev);
-}
-
 static void venc_panel_set_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 {
@@ -222,8 +205,6 @@ static struct omap_dss_driver venc_driver = {
 
 	.enable		= venc_panel_enable,
 	.disable	= venc_panel_disable,
-	.suspend	= venc_panel_suspend,
-	.resume		= venc_panel_resume,
 
 	.get_resolution	= omapdss_default_get_resolution,
 	.get_recommended_bpp = omapdss_default_get_recommended_bpp,
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
index 4ea17dc..4cb12ce 100644
--- a/drivers/video/omap2/omapfb/Kconfig
+++ b/drivers/video/omap2/omapfb/Kconfig
@@ -2,7 +2,6 @@ menuconfig FB_OMAP2
         tristate "OMAP2+ frame buffer support"
         depends on FB && OMAP2_DSS && !DRM_OMAP
 
-	select OMAP2_VRAM
 	select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
         select FB_CFB_FILLRECT
         select FB_CFB_COPYAREA
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index d630b26..8b1e9e3 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -28,10 +28,10 @@
 #include <linux/omapfb.h>
 #include <linux/vmalloc.h>
 #include <linux/export.h>
+#include <linux/sizes.h>
 
 #include <video/omapdss.h>
-#include <plat/vrfb.h>
-#include <plat/vram.h>
+#include <video/omapvrfb.h>
 
 #include "omapfb.h"
 
@@ -853,14 +853,15 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
 		break;
 
 	case OMAPFB_GET_VRAM_INFO: {
-		unsigned long vram, free, largest;
-
 		DBG("ioctl GET_VRAM_INFO\n");
 
-		omap_vram_get_info(&vram, &free, &largest);
-		p.vram_info.total = vram;
-		p.vram_info.free = free;
-		p.vram_info.largest_free_block = largest;
+		/*
+		 * We don't have the ability to get this vram info anymore.
+		 * Fill in something that should keep the applications working.
+		 */
+		p.vram_info.total = SZ_1M * 64;
+		p.vram_info.free = SZ_1M * 64;
+		p.vram_info.largest_free_block = SZ_1M * 64;
 
 		if (copy_to_user((void __user *)arg, &p.vram_info,
 					sizeof(p.vram_info)))
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 16db158..1a69d7c 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -31,9 +31,7 @@
 #include <linux/omapfb.h>
 
 #include <video/omapdss.h>
-#include <plat/cpu.h>
-#include <plat/vram.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
 
 #include "omapfb.h"
 
@@ -1259,11 +1257,10 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
 
 	switch (blank) {
 	case FB_BLANK_UNBLANK:
-		if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
+		if (display->state == OMAP_DSS_DISPLAY_ACTIVE)
 			goto exit;
 
-		if (display->driver->resume)
-			r = display->driver->resume(display);
+		r = display->driver->enable(display);
 
 		if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
 				d->update_mode == OMAPFB_AUTO_UPDATE &&
@@ -1284,8 +1281,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
 		if (d->auto_update_work_enabled)
 			omapfb_stop_auto_update(fbdev, display);
 
-		if (display->driver->suspend)
-			r = display->driver->suspend(display);
+		display->driver->disable(display);
 
 		break;
 
@@ -1336,24 +1332,25 @@ static void omapfb_free_fbmem(struct fb_info *fbi)
 
 	rg = ofbi->region;
 
-	WARN_ON(atomic_read(&rg->map_count));
-
-	if (rg->paddr)
-		if (omap_vram_free(rg->paddr, rg->size))
-			dev_err(fbdev->dev, "VRAM FREE failed\n");
+	if (rg->token == NULL)
+		return;
 
-	if (rg->vaddr)
-		iounmap(rg->vaddr);
+	WARN_ON(atomic_read(&rg->map_count));
 
 	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
 		/* unmap the 0 angle rotation */
 		if (rg->vrfb.vaddr[0]) {
 			iounmap(rg->vrfb.vaddr[0]);
-			omap_vrfb_release_ctx(&rg->vrfb);
 			rg->vrfb.vaddr[0] = NULL;
 		}
+
+		omap_vrfb_release_ctx(&rg->vrfb);
 	}
 
+	dma_free_attrs(fbdev->dev, rg->size, rg->token, rg->dma_handle,
+			&rg->attrs);
+
+	rg->token = NULL;
 	rg->vaddr = NULL;
 	rg->paddr = 0;
 	rg->alloc = 0;
@@ -1388,7 +1385,9 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct omapfb2_device *fbdev = ofbi->fbdev;
 	struct omapfb2_mem_region *rg;
-	void __iomem *vaddr;
+	void *token;
+	DEFINE_DMA_ATTRS(attrs);
+	dma_addr_t dma_handle;
 	int r;
 
 	rg = ofbi->region;
@@ -1403,42 +1402,43 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
 
 	size = PAGE_ALIGN(size);
 
-	if (!paddr) {
-		DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
-		r = omap_vram_alloc(size, &paddr);
-	} else {
-		DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
-				ofbi->id);
-		r = omap_vram_reserve(paddr, size);
-	}
+	WARN_ONCE(paddr,
+		"reserving memory at predefined address not supported\n");
 
-	if (r) {
+	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
+
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+		dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
+
+	DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
+
+	token = dma_alloc_attrs(fbdev->dev, size, &dma_handle,
+			GFP_KERNEL, &attrs);
+
+	if (token == NULL) {
 		dev_err(fbdev->dev, "failed to allocate framebuffer\n");
 		return -ENOMEM;
 	}
 
-	if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
-		vaddr = ioremap_wc(paddr, size);
+	DBG("allocated VRAM paddr %lx, vaddr %p\n",
+			(unsigned long)dma_handle, token);
 
-		if (!vaddr) {
-			dev_err(fbdev->dev, "failed to ioremap framebuffer\n");
-			omap_vram_free(paddr, size);
-			return -ENOMEM;
-		}
-
-		DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
-	} else {
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
 		r = omap_vrfb_request_ctx(&rg->vrfb);
 		if (r) {
+			dma_free_attrs(fbdev->dev, size, token, dma_handle,
+					&attrs);
 			dev_err(fbdev->dev, "vrfb create ctx failed\n");
 			return r;
 		}
-
-		vaddr = NULL;
 	}
 
-	rg->paddr = paddr;
-	rg->vaddr = vaddr;
+	rg->attrs = attrs;
+	rg->token = token;
+	rg->dma_handle = dma_handle;
+
+	rg->paddr = (unsigned long)dma_handle;
+	rg->vaddr = (void __iomem *)token;
 	rg->size = size;
 	rg->alloc = 1;
 
@@ -2259,7 +2259,7 @@ static int omapfb_find_best_mode(struct omap_dss_device *display,
 {
 	struct fb_monspecs *specs;
 	u8 *edid;
-	int r, i, best_xres, best_idx, len;
+	int r, i, best_idx, len;
 
 	if (!display->driver->read_edid)
 		return -ENODEV;
@@ -2275,10 +2275,6 @@ static int omapfb_find_best_mode(struct omap_dss_device *display,
 
 	fb_edid_to_monspecs(edid, specs);
 
-	if (edid[126] > 0)
-		fb_edid_add_monspecs(edid + 0x80, specs);
-
-	best_xres = 0;
 	best_idx = -1;
 
 	for (i = 0; i < specs->modedb_len; ++i) {
@@ -2294,16 +2290,20 @@ static int omapfb_find_best_mode(struct omap_dss_device *display,
 		if (m->xres == 2880 || m->xres == 1440)
 			continue;
 
+		if (m->vmode & FB_VMODE_INTERLACED ||
+				m->vmode & FB_VMODE_DOUBLE)
+			continue;
+
 		fb_videomode_to_omap_timings(m, display, &t);
 
 		r = display->driver->check_timings(display, &t);
-		if (r == 0 && best_xres < m->xres) {
-			best_xres = m->xres;
+		if (r == 0) {
 			best_idx = i;
+			break;
 		}
 	}
 
-	if (best_xres == 0) {
+	if (best_idx == -1) {
 		r = -ENOENT;
 		goto err2;
 	}
@@ -2372,15 +2372,52 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
 	return 0;
 }
 
+static int omapfb_init_connections(struct omapfb2_device *fbdev,
+		struct omap_dss_device *dssdev)
+{
+	int i, r;
+	struct omap_overlay_manager *mgr = NULL;
+
+	for (i = 0; i < fbdev->num_managers; i++) {
+		mgr = fbdev->managers[i];
+
+		if (dssdev->channel == mgr->id)
+			break;
+	}
+
+	if (i == fbdev->num_managers)
+		return -ENODEV;
+
+	if (mgr->output)
+		mgr->unset_output(mgr);
+
+	r = mgr->set_output(mgr, dssdev->output);
+	if (r)
+		return r;
+
+	for (i = 0; i < fbdev->num_overlays; i++) {
+		struct omap_overlay *ovl = fbdev->overlays[i];
+
+		if (ovl->manager)
+			ovl->unset_manager(ovl);
+
+		r = ovl->set_manager(ovl, mgr);
+		if (r)
+			dev_warn(fbdev->dev,
+					"failed to connect overlay %s to manager %s\n",
+					ovl->name, mgr->name);
+	}
+
+	return 0;
+}
+
 static int __init omapfb_probe(struct platform_device *pdev)
 {
 	struct omapfb2_device *fbdev = NULL;
 	int r = 0;
 	int i;
-	struct omap_overlay *ovl;
 	struct omap_dss_device *def_display;
 	struct omap_dss_device *dssdev;
-	struct omap_dss_device *ovl_device;
 
 	DBG("omapfb_probe\n");
 
@@ -2396,10 +2433,7 @@ static int __init omapfb_probe(struct platform_device *pdev)
 		goto err0;
 	}
 
-	/* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE
-	*	 available for OMAP2 and OMAP3
-	*/
-	if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) {
+	if (def_vrfb && !omap_vrfb_supported()) {
 		def_vrfb = 0;
 		dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
 				"ignoring the module parameter vrfb=y\n");
@@ -2411,7 +2445,6 @@ static int __init omapfb_probe(struct platform_device *pdev)
 	fbdev->dev = &pdev->dev;
 	platform_set_drvdata(pdev, fbdev);
 
-	r = 0;
 	fbdev->num_displays = 0;
 	dssdev = NULL;
 	for_each_dss_dev(dssdev) {
@@ -2434,9 +2467,6 @@ static int __init omapfb_probe(struct platform_device *pdev)
 			d->update_mode = OMAPFB_AUTO_UPDATE;
 	}
 
-	if (r)
-		goto cleanup;
-
 	if (fbdev->num_displays == 0) {
 		dev_err(&pdev->dev, "no displays\n");
 		r = -EINVAL;
@@ -2451,15 +2481,33 @@ static int __init omapfb_probe(struct platform_device *pdev)
 	for (i = 0; i < fbdev->num_managers; i++)
 		fbdev->managers[i] = omap_dss_get_overlay_manager(i);
 
-	/* gfx overlay should be the default one. find a display
-	 * connected to that, and use it as default display */
-	ovl = omap_dss_get_overlay(0);
-	ovl_device = ovl->get_device(ovl);
-	if (ovl_device) {
-		def_display = ovl_device;
-	} else {
-		dev_warn(&pdev->dev, "cannot find default display\n");
-		def_display = NULL;
+	def_display = NULL;
+
+	for (i = 0; i < fbdev->num_displays; ++i) {
+		struct omap_dss_device *dssdev;
+		const char *def_name;
+
+		def_name = omapdss_get_default_display_name();
+
+		dssdev = fbdev->displays[i].dssdev;
+
+		if (def_name == NULL ||
+			(dssdev->name && strcmp(def_name, dssdev->name) == 0)) {
+			def_display = dssdev;
+			break;
+		}
+	}
+
+	if (def_display == NULL) {
+		dev_err(fbdev->dev, "failed to find default display\n");
+		r = -EINVAL;
+		goto cleanup;
+	}
+
+	r = omapfb_init_connections(fbdev, def_display);
+	if (r) {
+		dev_err(fbdev->dev, "failed to init overlay connections\n");
+		goto cleanup;
 	}
 
 	if (def_mode && strlen(def_mode) > 0) {
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index e8d8cc7..17aa174 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -30,7 +30,7 @@
 #include <linux/omapfb.h>
 
 #include <video/omapdss.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
 
 #include "omapfb.h"
 
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index 5ced9b3..5f72bf9 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -28,6 +28,8 @@
 #endif
 
 #include <linux/rwsem.h>
+#include <linux/dma-attrs.h>
+#include <linux/dma-mapping.h>
 
 #include <video/omapdss.h>
 
@@ -49,6 +51,9 @@ extern bool omapfb_debug;
 
 struct omapfb2_mem_region {
 	int             id;
+	struct dma_attrs attrs;
+	void		*token;
+	dma_addr_t	dma_handle;
 	u32		paddr;
 	void __iomem	*vaddr;
 	struct vrfb	vrfb;
diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c
deleted file mode 100644
index f2b15c4..0000000
--- a/drivers/video/omap2/vram.c
+++ /dev/null
@@ -1,514 +0,0 @@
-/*
- * VRAM manager for OMAP
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*#define DEBUG*/
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/seq_file.h>
-#include <linux/memblock.h>
-#include <linux/completion.h>
-#include <linux/debugfs.h>
-#include <linux/jiffies.h>
-#include <linux/module.h>
-
-#include <asm/setup.h>
-
-#include <plat/vram.h>
-
-#ifdef DEBUG
-#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__)
-#else
-#define DBG(format, ...)
-#endif
-
-/* postponed regions are used to temporarily store region information at boot
- * time when we cannot yet allocate the region list */
-#define MAX_POSTPONED_REGIONS 10
-
-static bool vram_initialized;
-static int postponed_cnt;
-static struct {
-	unsigned long paddr;
-	size_t size;
-} postponed_regions[MAX_POSTPONED_REGIONS];
-
-struct vram_alloc {
-	struct list_head list;
-	unsigned long paddr;
-	unsigned pages;
-};
-
-struct vram_region {
-	struct list_head list;
-	struct list_head alloc_list;
-	unsigned long paddr;
-	unsigned pages;
-};
-
-static DEFINE_MUTEX(region_mutex);
-static LIST_HEAD(region_list);
-
-static struct vram_region *omap_vram_create_region(unsigned long paddr,
-		unsigned pages)
-{
-	struct vram_region *rm;
-
-	rm = kzalloc(sizeof(*rm), GFP_KERNEL);
-
-	if (rm) {
-		INIT_LIST_HEAD(&rm->alloc_list);
-		rm->paddr = paddr;
-		rm->pages = pages;
-	}
-
-	return rm;
-}
-
-#if 0
-static void omap_vram_free_region(struct vram_region *vr)
-{
-	list_del(&vr->list);
-	kfree(vr);
-}
-#endif
-
-static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr,
-		unsigned long paddr, unsigned pages)
-{
-	struct vram_alloc *va;
-	struct vram_alloc *new;
-
-	new = kzalloc(sizeof(*va), GFP_KERNEL);
-
-	if (!new)
-		return NULL;
-
-	new->paddr = paddr;
-	new->pages = pages;
-
-	list_for_each_entry(va, &vr->alloc_list, list) {
-		if (va->paddr > new->paddr)
-			break;
-	}
-
-	list_add_tail(&new->list, &va->list);
-
-	return new;
-}
-
-static void omap_vram_free_allocation(struct vram_alloc *va)
-{
-	list_del(&va->list);
-	kfree(va);
-}
-
-int omap_vram_add_region(unsigned long paddr, size_t size)
-{
-	struct vram_region *rm;
-	unsigned pages;
-
-	if (vram_initialized) {
-		DBG("adding region paddr %08lx size %d\n",
-				paddr, size);
-
-		size &= PAGE_MASK;
-		pages = size >> PAGE_SHIFT;
-
-		rm = omap_vram_create_region(paddr, pages);
-		if (rm == NULL)
-			return -ENOMEM;
-
-		list_add(&rm->list, &region_list);
-	} else {
-		if (postponed_cnt == MAX_POSTPONED_REGIONS)
-			return -ENOMEM;
-
-		postponed_regions[postponed_cnt].paddr = paddr;
-		postponed_regions[postponed_cnt].size = size;
-
-		++postponed_cnt;
-	}
-	return 0;
-}
-
-int omap_vram_free(unsigned long paddr, size_t size)
-{
-	struct vram_region *rm;
-	struct vram_alloc *alloc;
-	unsigned start, end;
-
-	DBG("free mem paddr %08lx size %d\n", paddr, size);
-
-	size = PAGE_ALIGN(size);
-
-	mutex_lock(&region_mutex);
-
-	list_for_each_entry(rm, &region_list, list) {
-		list_for_each_entry(alloc, &rm->alloc_list, list) {
-			start = alloc->paddr;
-			end = alloc->paddr + (alloc->pages >> PAGE_SHIFT);
-
-			if (start >= paddr && end < paddr + size)
-				goto found;
-		}
-	}
-
-	mutex_unlock(&region_mutex);
-	return -EINVAL;
-
-found:
-	omap_vram_free_allocation(alloc);
-
-	mutex_unlock(&region_mutex);
-	return 0;
-}
-EXPORT_SYMBOL(omap_vram_free);
-
-static int _omap_vram_reserve(unsigned long paddr, unsigned pages)
-{
-	struct vram_region *rm;
-	struct vram_alloc *alloc;
-	size_t size;
-
-	size = pages << PAGE_SHIFT;
-
-	list_for_each_entry(rm, &region_list, list) {
-		unsigned long start, end;
-
-		DBG("checking region %lx %d\n", rm->paddr, rm->pages);
-
-		start = rm->paddr;
-		end = start + (rm->pages << PAGE_SHIFT) - 1;
-		if (start > paddr || end < paddr + size - 1)
-			continue;
-
-		DBG("block ok, checking allocs\n");
-
-		list_for_each_entry(alloc, &rm->alloc_list, list) {
-			end = alloc->paddr - 1;
-
-			if (start <= paddr && end >= paddr + size - 1)
-				goto found;
-
-			start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
-		}
-
-		end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1;
-
-		if (!(start <= paddr && end >= paddr + size - 1))
-			continue;
-found:
-		DBG("found area start %lx, end %lx\n", start, end);
-
-		if (omap_vram_create_allocation(rm, paddr, pages) == NULL)
-			return -ENOMEM;
-
-		return 0;
-	}
-
-	return -ENOMEM;
-}
-
-int omap_vram_reserve(unsigned long paddr, size_t size)
-{
-	unsigned pages;
-	int r;
-
-	DBG("reserve mem paddr %08lx size %d\n", paddr, size);
-
-	size = PAGE_ALIGN(size);
-	pages = size >> PAGE_SHIFT;
-
-	mutex_lock(&region_mutex);
-
-	r = _omap_vram_reserve(paddr, pages);
-
-	mutex_unlock(&region_mutex);
-
-	return r;
-}
-EXPORT_SYMBOL(omap_vram_reserve);
-
-static int _omap_vram_alloc(unsigned pages, unsigned long *paddr)
-{
-	struct vram_region *rm;
-	struct vram_alloc *alloc;
-
-	list_for_each_entry(rm, &region_list, list) {
-		unsigned long start, end;
-
-		DBG("checking region %lx %d\n", rm->paddr, rm->pages);
-
-		start = rm->paddr;
-
-		list_for_each_entry(alloc, &rm->alloc_list, list) {
-			end = alloc->paddr;
-
-			if (end - start >= pages << PAGE_SHIFT)
-				goto found;
-
-			start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
-		}
-
-		end = rm->paddr + (rm->pages << PAGE_SHIFT);
-found:
-		if (end - start < pages << PAGE_SHIFT)
-			continue;
-
-		DBG("found %lx, end %lx\n", start, end);
-
-		alloc = omap_vram_create_allocation(rm, start, pages);
-		if (alloc == NULL)
-			return -ENOMEM;
-
-		*paddr = start;
-
-		return 0;
-	}
-
-	return -ENOMEM;
-}
-
-int omap_vram_alloc(size_t size, unsigned long *paddr)
-{
-	unsigned pages;
-	int r;
-
-	BUG_ON(!size);
-
-	DBG("alloc mem size %d\n", size);
-
-	size = PAGE_ALIGN(size);
-	pages = size >> PAGE_SHIFT;
-
-	mutex_lock(&region_mutex);
-
-	r = _omap_vram_alloc(pages, paddr);
-
-	mutex_unlock(&region_mutex);
-
-	return r;
-}
-EXPORT_SYMBOL(omap_vram_alloc);
-
-void omap_vram_get_info(unsigned long *vram,
-		unsigned long *free_vram,
-		unsigned long *largest_free_block)
-{
-	struct vram_region *vr;
-	struct vram_alloc *va;
-
-	*vram = 0;
-	*free_vram = 0;
-	*largest_free_block = 0;
-
-	mutex_lock(&region_mutex);
-
-	list_for_each_entry(vr, &region_list, list) {
-		unsigned free;
-		unsigned long pa;
-
-		pa = vr->paddr;
-		*vram += vr->pages << PAGE_SHIFT;
-
-		list_for_each_entry(va, &vr->alloc_list, list) {
-			free = va->paddr - pa;
-			*free_vram += free;
-			if (free > *largest_free_block)
-				*largest_free_block = free;
-			pa = va->paddr + (va->pages << PAGE_SHIFT);
-		}
-
-		free = vr->paddr + (vr->pages << PAGE_SHIFT) - pa;
-		*free_vram += free;
-		if (free > *largest_free_block)
-			*largest_free_block = free;
-	}
-
-	mutex_unlock(&region_mutex);
-}
-EXPORT_SYMBOL(omap_vram_get_info);
-
-#if defined(CONFIG_DEBUG_FS)
-static int vram_debug_show(struct seq_file *s, void *unused)
-{
-	struct vram_region *vr;
-	struct vram_alloc *va;
-	unsigned size;
-
-	mutex_lock(&region_mutex);
-
-	list_for_each_entry(vr, &region_list, list) {
-		size = vr->pages << PAGE_SHIFT;
-		seq_printf(s, "%08lx-%08lx (%d bytes)\n",
-				vr->paddr, vr->paddr + size - 1,
-				size);
-
-		list_for_each_entry(va, &vr->alloc_list, list) {
-			size = va->pages << PAGE_SHIFT;
-			seq_printf(s, "    %08lx-%08lx (%d bytes)\n",
-					va->paddr, va->paddr + size - 1,
-					size);
-		}
-	}
-
-	mutex_unlock(&region_mutex);
-
-	return 0;
-}
-
-static int vram_debug_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, vram_debug_show, inode->i_private);
-}
-
-static const struct file_operations vram_debug_fops = {
-	.open           = vram_debug_open,
-	.read           = seq_read,
-	.llseek         = seq_lseek,
-	.release        = single_release,
-};
-
-static int __init omap_vram_create_debugfs(void)
-{
-	struct dentry *d;
-
-	d = debugfs_create_file("vram", S_IRUGO, NULL,
-			NULL, &vram_debug_fops);
-	if (IS_ERR(d))
-		return PTR_ERR(d);
-
-	return 0;
-}
-#endif
-
-static __init int omap_vram_init(void)
-{
-	int i;
-
-	vram_initialized = 1;
-
-	for (i = 0; i < postponed_cnt; i++)
-		omap_vram_add_region(postponed_regions[i].paddr,
-				postponed_regions[i].size);
-
-#ifdef CONFIG_DEBUG_FS
-	if (omap_vram_create_debugfs())
-		pr_err("VRAM: Failed to create debugfs file\n");
-#endif
-
-	return 0;
-}
-
-arch_initcall(omap_vram_init);
-
-/* boottime vram alloc stuff */
-
-/* set from board file */
-static u32 omap_vram_sdram_start __initdata;
-static u32 omap_vram_sdram_size __initdata;
-
-/* set from kernel cmdline */
-static u32 omap_vram_def_sdram_size __initdata;
-static u32 omap_vram_def_sdram_start __initdata;
-
-static int __init omap_vram_early_vram(char *p)
-{
-	omap_vram_def_sdram_size = memparse(p, &p);
-	if (*p == ',')
-		omap_vram_def_sdram_start = simple_strtoul(p + 1, &p, 16);
-	return 0;
-}
-early_param("vram", omap_vram_early_vram);
-
-/*
- * Called from map_io. We need to call to this early enough so that we
- * can reserve the fixed SDRAM regions before VM could get hold of them.
- */
-void __init omap_vram_reserve_sdram_memblock(void)
-{
-	u32 paddr;
-	u32 size = 0;
-
-	/* cmdline arg overrides the board file definition */
-	if (omap_vram_def_sdram_size) {
-		size = omap_vram_def_sdram_size;
-		paddr = omap_vram_def_sdram_start;
-	}
-
-	if (!size) {
-		size = omap_vram_sdram_size;
-		paddr = omap_vram_sdram_start;
-	}
-
-#ifdef CONFIG_OMAP2_VRAM_SIZE
-	if (!size) {
-		size = CONFIG_OMAP2_VRAM_SIZE * 1024 * 1024;
-		paddr = 0;
-	}
-#endif
-
-	if (!size)
-		return;
-
-	size = ALIGN(size, SZ_2M);
-
-	if (paddr) {
-		if (paddr & ~PAGE_MASK) {
-			pr_err("VRAM start address 0x%08x not page aligned\n",
-					paddr);
-			return;
-		}
-
-		if (!memblock_is_region_memory(paddr, size)) {
-			pr_err("Illegal SDRAM region 0x%08x..0x%08x for VRAM\n",
-					paddr, paddr + size - 1);
-			return;
-		}
-
-		if (memblock_is_region_reserved(paddr, size)) {
-			pr_err("FB: failed to reserve VRAM - busy\n");
-			return;
-		}
-
-		if (memblock_reserve(paddr, size) < 0) {
-			pr_err("FB: failed to reserve VRAM - no memory\n");
-			return;
-		}
-	} else {
-		paddr = memblock_alloc(size, SZ_2M);
-	}
-
-	memblock_free(paddr, size);
-	memblock_remove(paddr, size);
-
-	omap_vram_add_region(paddr, size);
-
-	pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
-}
-
-void __init omap_vram_set_sdram_vram(u32 size, u32 start)
-{
-	omap_vram_sdram_start = start;
-	omap_vram_sdram_size = size;
-}
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
index 7e99022..5d8fdac 100644
--- a/drivers/video/omap2/vrfb.c
+++ b/drivers/video/omap2/vrfb.c
@@ -26,9 +26,9 @@
 #include <linux/io.h>
 #include <linux/bitops.h>
 #include <linux/mutex.h>
+#include <linux/platform_device.h>
 
-#include <plat/vrfb.h>
-#include <plat/sdrc.h>
+#include <video/omapvrfb.h>
 
 #ifdef DEBUG
 #define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
@@ -36,10 +36,10 @@
 #define DBG(format, ...)
 #endif
 
-#define SMS_ROT_VIRT_BASE(context, rot) \
-	(((context >= 4) ? 0xD0000000 : 0x70000000) \
-	 + (0x4000000 * (context)) \
-	 + (0x1000000 * (rot)))
+#define SMS_ROT_CONTROL(context)	(0x0 + 0x10 * context)
+#define SMS_ROT_SIZE(context)		(0x4 + 0x10 * context)
+#define SMS_ROT_PHYSICAL_BA(context)	(0x8 + 0x10 * context)
+#define SMS_ROT_VIRT_BASE(rot)		(0x1000000 * (rot))
 
 #define OMAP_VRFB_SIZE			(2048 * 2048 * 4)
 
@@ -53,10 +53,16 @@
 #define SMS_PW_OFFSET		4
 #define SMS_PS_OFFSET		0
 
-#define VRFB_NUM_CTXS 12
 /* bitmap of reserved contexts */
 static unsigned long ctx_map;
 
+struct vrfb_ctx {
+	u32 base;
+	u32 physical_ba;
+	u32 control;
+	u32 size;
+};
+
 static DEFINE_MUTEX(ctx_lock);
 
 /*
@@ -65,17 +71,34 @@ static DEFINE_MUTEX(ctx_lock);
  * we don't need locking, since no drivers will run until after the wake-up
  * has finished.
  */
-static struct {
-	u32 physical_ba;
-	u32 control;
-	u32 size;
-} vrfb_hw_context[VRFB_NUM_CTXS];
+
+static void __iomem *vrfb_base;
+
+static int num_ctxs;
+static struct vrfb_ctx *ctxs;
+
+static bool vrfb_loaded;
+
+static void omap2_sms_write_rot_control(u32 val, unsigned ctx)
+{
+	__raw_writel(val, vrfb_base + SMS_ROT_CONTROL(ctx));
+}
+
+static void omap2_sms_write_rot_size(u32 val, unsigned ctx)
+{
+	__raw_writel(val, vrfb_base + SMS_ROT_SIZE(ctx));
+}
+
+static void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
+{
+	__raw_writel(val, vrfb_base + SMS_ROT_PHYSICAL_BA(ctx));
+}
 
 static inline void restore_hw_context(int ctx)
 {
-	omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx);
-	omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx);
-	omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx);
+	omap2_sms_write_rot_control(ctxs[ctx].control, ctx);
+	omap2_sms_write_rot_size(ctxs[ctx].size, ctx);
+	omap2_sms_write_rot_physical_ba(ctxs[ctx].physical_ba, ctx);
 }
 
 static u32 get_image_width_roundup(u16 width, u8 bytespp)
@@ -196,9 +219,9 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
 	control |= VRFB_PAGE_WIDTH_EXP  << SMS_PW_OFFSET;
 	control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
 
-	vrfb_hw_context[ctx].physical_ba = paddr;
-	vrfb_hw_context[ctx].size = size;
-	vrfb_hw_context[ctx].control = control;
+	ctxs[ctx].physical_ba = paddr;
+	ctxs[ctx].size = size;
+	ctxs[ctx].control = control;
 
 	omap2_sms_write_rot_physical_ba(paddr, ctx);
 	omap2_sms_write_rot_size(size, ctx);
@@ -274,11 +297,11 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
 
 	mutex_lock(&ctx_lock);
 
-	for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
+	for (ctx = 0; ctx < num_ctxs; ++ctx)
 		if ((ctx_map & (1 << ctx)) == 0)
 			break;
 
-	if (ctx == VRFB_NUM_CTXS) {
+	if (ctx == num_ctxs) {
 		pr_err("vrfb: no free contexts\n");
 		r = -EBUSY;
 		goto out;
@@ -293,7 +316,7 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
 	vrfb->context = ctx;
 
 	for (rot = 0; rot < 4; ++rot) {
-		paddr = SMS_ROT_VIRT_BASE(ctx, rot);
+		paddr = ctxs[ctx].base + SMS_ROT_VIRT_BASE(rot);
 		if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
 			pr_err("vrfb: failed to reserve VRFB "
 					"area for ctx %d, rotation %d\n",
@@ -314,3 +337,80 @@ out:
 	return r;
 }
 EXPORT_SYMBOL(omap_vrfb_request_ctx);
+
+bool omap_vrfb_supported(void)
+{
+	return vrfb_loaded;
+}
+EXPORT_SYMBOL(omap_vrfb_supported);
+
+static int __init vrfb_probe(struct platform_device *pdev)
+{
+	struct resource *mem;
+	int i;
+
+	/* first resource is the register res, the rest are vrfb contexts */
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "can't get vrfb base address\n");
+		return -EINVAL;
+	}
+
+	vrfb_base = devm_request_and_ioremap(&pdev->dev, mem);
+	if (!vrfb_base) {
+		dev_err(&pdev->dev, "can't ioremap vrfb memory\n");
+		return -ENOMEM;
+	}
+
+	num_ctxs = pdev->num_resources - 1;
+
+	ctxs = devm_kzalloc(&pdev->dev,
+			sizeof(struct vrfb_ctx) * num_ctxs,
+			GFP_KERNEL);
+
+	if (!ctxs)
+		return -ENOMEM;
+
+	for (i = 0; i < num_ctxs; ++i) {
+		mem = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
+		if (!mem) {
+			dev_err(&pdev->dev, "can't get vrfb ctx %d address\n",
+					i);
+			return -EINVAL;
+		}
+
+		ctxs[i].base = mem->start;
+	}
+
+	vrfb_loaded = true;
+
+	return 0;
+}
+
+static void __exit vrfb_remove(struct platform_device *pdev)
+{
+	vrfb_loaded = false;
+}
+
+static struct platform_driver vrfb_driver = {
+	.driver.name	= "omapvrfb",
+	.remove		= __exit_p(vrfb_remove),
+};
+
+static int __init vrfb_init(void)
+{
+	return platform_driver_probe(&vrfb_driver, &vrfb_probe);
+}
+
+static void __exit vrfb_exit(void)
+{
+	platform_driver_unregister(&vrfb_driver);
+}
+
+module_init(vrfb_init);
+module_exit(vrfb_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("OMAP VRFB");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c
new file mode 100644
index 0000000..6101f5c
--- /dev/null
+++ b/drivers/video/ssd1307fb.c
@@ -0,0 +1,396 @@
+/*
+ * Driver for the Solomon SSD1307 OLED controler
+ *
+ * Copyright 2012 Free Electrons
+ *
+ * Licensed under the GPLv2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/uaccess.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pwm.h>
+#include <linux/delay.h>
+
+#define SSD1307FB_WIDTH			96
+#define SSD1307FB_HEIGHT		16
+
+#define SSD1307FB_DATA			0x40
+#define SSD1307FB_COMMAND		0x80
+
+#define SSD1307FB_CONTRAST		0x81
+#define SSD1307FB_SEG_REMAP_ON		0xa1
+#define SSD1307FB_DISPLAY_OFF		0xae
+#define SSD1307FB_DISPLAY_ON		0xaf
+#define SSD1307FB_START_PAGE_ADDRESS	0xb0
+
+struct ssd1307fb_par {
+	struct i2c_client *client;
+	struct fb_info *info;
+	struct pwm_device *pwm;
+	u32 pwm_period;
+	int reset;
+};
+
+static struct fb_fix_screeninfo ssd1307fb_fix __devinitdata = {
+	.id		= "Solomon SSD1307",
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_MONO10,
+	.xpanstep	= 0,
+	.ypanstep	= 0,
+	.ywrapstep	= 0,
+	.line_length	= SSD1307FB_WIDTH / 8,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo ssd1307fb_var __devinitdata = {
+	.xres		= SSD1307FB_WIDTH,
+	.yres		= SSD1307FB_HEIGHT,
+	.xres_virtual	= SSD1307FB_WIDTH,
+	.yres_virtual	= SSD1307FB_HEIGHT,
+	.bits_per_pixel	= 1,
+};
+
+static int ssd1307fb_write_array(struct i2c_client *client, u8 type, u8 *cmd, u32 len)
+{
+	u8 *buf;
+	int ret = 0;
+
+	buf = kzalloc(len + 1, GFP_KERNEL);
+	if (!buf) {
+		dev_err(&client->dev, "Couldn't allocate sending buffer.\n");
+		return -ENOMEM;
+	}
+
+	buf[0] = type;
+	memcpy(buf + 1, cmd, len);
+
+	ret = i2c_master_send(client, buf, len + 1);
+	if (ret != len + 1) {
+		dev_err(&client->dev, "Couldn't send I2C command.\n");
+		goto error;
+	}
+
+error:
+	kfree(buf);
+	return ret;
+}
+
+static inline int ssd1307fb_write_cmd_array(struct i2c_client *client, u8 *cmd, u32 len)
+{
+	return ssd1307fb_write_array(client, SSD1307FB_COMMAND, cmd, len);
+}
+
+static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd)
+{
+	return ssd1307fb_write_cmd_array(client, &cmd, 1);
+}
+
+static inline int ssd1307fb_write_data_array(struct i2c_client *client, u8 *cmd, u32 len)
+{
+	return ssd1307fb_write_array(client, SSD1307FB_DATA, cmd, len);
+}
+
+static inline int ssd1307fb_write_data(struct i2c_client *client, u8 data)
+{
+	return ssd1307fb_write_data_array(client, &data, 1);
+}
+
+static void ssd1307fb_update_display(struct ssd1307fb_par *par)
+{
+	u8 *vmem = par->info->screen_base;
+	int i, j, k;
+
+	/*
+	 * The screen is divided in pages, each having a height of 8
+	 * pixels, and the width of the screen. When sending a byte of
+	 * data to the controller, it gives the 8 bits for the current
+	 * column. I.e, the first byte are the 8 bits of the first
+	 * column, then the 8 bits for the second column, etc.
+	 *
+	 *
+	 * Representation of the screen, assuming it is 5 bits
+	 * wide. Each letter-number combination is a bit that controls
+	 * one pixel.
+	 *
+	 * A0 A1 A2 A3 A4
+	 * B0 B1 B2 B3 B4
+	 * C0 C1 C2 C3 C4
+	 * D0 D1 D2 D3 D4
+	 * E0 E1 E2 E3 E4
+	 * F0 F1 F2 F3 F4
+	 * G0 G1 G2 G3 G4
+	 * H0 H1 H2 H3 H4
+	 *
+	 * If you want to update this screen, you need to send 5 bytes:
+	 *  (1) A0 B0 C0 D0 E0 F0 G0 H0
+	 *  (2) A1 B1 C1 D1 E1 F1 G1 H1
+	 *  (3) A2 B2 C2 D2 E2 F2 G2 H2
+	 *  (4) A3 B3 C3 D3 E3 F3 G3 H3
+	 *  (5) A4 B4 C4 D4 E4 F4 G4 H4
+	 */
+
+	for (i = 0; i < (SSD1307FB_HEIGHT / 8); i++) {
+		ssd1307fb_write_cmd(par->client, SSD1307FB_START_PAGE_ADDRESS + (i + 1));
+		ssd1307fb_write_cmd(par->client, 0x00);
+		ssd1307fb_write_cmd(par->client, 0x10);
+
+		for (j = 0; j < SSD1307FB_WIDTH; j++) {
+			u8 buf = 0;
+			for (k = 0; k < 8; k++) {
+				u32 page_length = SSD1307FB_WIDTH * i;
+				u32 index = page_length + (SSD1307FB_WIDTH * k + j) / 8;
+				u8 byte = *(vmem + index);
+				u8 bit = byte & (1 << (7 - (j % 8)));
+				bit = bit >> (7 - (j % 8));
+				buf |= bit << k;
+			}
+			ssd1307fb_write_data(par->client, buf);
+		}
+	}
+}
+
+
+static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	struct ssd1307fb_par *par = info->par;
+	unsigned long total_size;
+	unsigned long p = *ppos;
+	u8 __iomem *dst;
+
+	total_size = info->fix.smem_len;
+
+	if (p > total_size)
+		return -EINVAL;
+
+	if (count + p > total_size)
+		count = total_size - p;
+
+	if (!count)
+		return -EINVAL;
+
+	dst = (void __force *) (info->screen_base + p);
+
+	if (copy_from_user(dst, buf, count))
+		return -EFAULT;
+
+	ssd1307fb_update_display(par);
+
+	*ppos += count;
+
+	return count;
+}
+
+static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct ssd1307fb_par *par = info->par;
+	sys_fillrect(info, rect);
+	ssd1307fb_update_display(par);
+}
+
+static void ssd1307fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct ssd1307fb_par *par = info->par;
+	sys_copyarea(info, area);
+	ssd1307fb_update_display(par);
+}
+
+static void ssd1307fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct ssd1307fb_par *par = info->par;
+	sys_imageblit(info, image);
+	ssd1307fb_update_display(par);
+}
+
+static struct fb_ops ssd1307fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_read	= fb_sys_read,
+	.fb_write	= ssd1307fb_write,
+	.fb_fillrect	= ssd1307fb_fillrect,
+	.fb_copyarea	= ssd1307fb_copyarea,
+	.fb_imageblit	= ssd1307fb_imageblit,
+};
+
+static void ssd1307fb_deferred_io(struct fb_info *info,
+				struct list_head *pagelist)
+{
+	ssd1307fb_update_display(info->par);
+}
+
+static struct fb_deferred_io ssd1307fb_defio = {
+	.delay		= HZ,
+	.deferred_io	= ssd1307fb_deferred_io,
+};
+
+static int __devinit ssd1307fb_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	struct fb_info *info;
+	u32 vmem_size = SSD1307FB_WIDTH * SSD1307FB_HEIGHT / 8;
+	struct ssd1307fb_par *par;
+	u8 *vmem;
+	int ret;
+
+	if (!client->dev.of_node) {
+		dev_err(&client->dev, "No device tree data found!\n");
+		return -EINVAL;
+	}
+
+	info = framebuffer_alloc(sizeof(struct ssd1307fb_par), &client->dev);
+	if (!info) {
+		dev_err(&client->dev, "Couldn't allocate framebuffer.\n");
+		return -ENOMEM;
+	}
+
+	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
+	if (!vmem) {
+		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
+		ret = -ENOMEM;
+		goto fb_alloc_error;
+	}
+
+	info->fbops = &ssd1307fb_ops;
+	info->fix = ssd1307fb_fix;
+	info->fbdefio = &ssd1307fb_defio;
+
+	info->var = ssd1307fb_var;
+	info->var.red.length = 1;
+	info->var.red.offset = 0;
+	info->var.green.length = 1;
+	info->var.green.offset = 0;
+	info->var.blue.length = 1;
+	info->var.blue.offset = 0;
+
+	info->screen_base = (u8 __force __iomem *)vmem;
+	info->fix.smem_start = (unsigned long)vmem;
+	info->fix.smem_len = vmem_size;
+
+	fb_deferred_io_init(info);
+
+	par = info->par;
+	par->info = info;
+	par->client = client;
+
+	par->reset = of_get_named_gpio(client->dev.of_node,
+					 "reset-gpios", 0);
+	if (!gpio_is_valid(par->reset)) {
+		ret = -EINVAL;
+		goto reset_oled_error;
+	}
+
+	ret = devm_gpio_request_one(&client->dev, par->reset,
+				    GPIOF_OUT_INIT_HIGH,
+				    "oled-reset");
+	if (ret) {
+		dev_err(&client->dev,
+			"failed to request gpio %d: %d\n",
+			par->reset, ret);
+		goto reset_oled_error;
+	}
+
+	par->pwm = pwm_get(&client->dev, NULL);
+	if (IS_ERR(par->pwm)) {
+		dev_err(&client->dev, "Could not get PWM from device tree!\n");
+		ret = PTR_ERR(par->pwm);
+		goto pwm_error;
+	}
+
+	par->pwm_period = pwm_get_period(par->pwm);
+
+	dev_dbg(&client->dev, "Using PWM%d with a %dns period.\n", par->pwm->pwm, par->pwm_period);
+
+	ret = register_framebuffer(info);
+	if (ret) {
+		dev_err(&client->dev, "Couldn't register the framebuffer\n");
+		goto fbreg_error;
+	}
+
+	i2c_set_clientdata(client, info);
+
+	/* Reset the screen */
+	gpio_set_value(par->reset, 0);
+	udelay(4);
+	gpio_set_value(par->reset, 1);
+	udelay(4);
+
+	/* Enable the PWM */
+	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
+	pwm_enable(par->pwm);
+
+	/* Map column 127 of the OLED to segment 0 */
+	ret = ssd1307fb_write_cmd(client, SSD1307FB_SEG_REMAP_ON);
+	if (ret < 0) {
+		dev_err(&client->dev, "Couldn't remap the screen.\n");
+		goto remap_error;
+	}
+
+	/* Turn on the display */
+	ret = ssd1307fb_write_cmd(client, SSD1307FB_DISPLAY_ON);
+	if (ret < 0) {
+		dev_err(&client->dev, "Couldn't turn the display on.\n");
+		goto remap_error;
+	}
+
+	dev_info(&client->dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n", info->node, info->fix.id, vmem_size);
+
+	return 0;
+
+remap_error:
+	unregister_framebuffer(info);
+	pwm_disable(par->pwm);
+fbreg_error:
+	pwm_put(par->pwm);
+pwm_error:
+reset_oled_error:
+	fb_deferred_io_cleanup(info);
+fb_alloc_error:
+	framebuffer_release(info);
+	return ret;
+}
+
+static int __devexit ssd1307fb_remove(struct i2c_client *client)
+{
+	struct fb_info *info = i2c_get_clientdata(client);
+	struct ssd1307fb_par *par = info->par;
+
+	unregister_framebuffer(info);
+	pwm_disable(par->pwm);
+	pwm_put(par->pwm);
+	fb_deferred_io_cleanup(info);
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static const struct i2c_device_id ssd1307fb_i2c_id[] = {
+	{ "ssd1307fb", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id);
+
+static const struct of_device_id ssd1307fb_of_match[] = {
+	{ .compatible = "solomon,ssd1307fb-i2c" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
+
+static struct i2c_driver ssd1307fb_driver = {
+	.probe = ssd1307fb_probe,
+	.remove = __devexit_p(ssd1307fb_remove),
+	.id_table = ssd1307fb_i2c_id,
+	.driver = {
+		.name = "ssd1307fb",
+		.of_match_table = of_match_ptr(ssd1307fb_of_match),
+		.owner = THIS_MODULE,
+	},
+};
+
+module_i2c_driver(ssd1307fb_driver);
+
+MODULE_DESCRIPTION("FB driver for the Solomon SSD1307 OLED controler");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
index 2dcdbc9..99ebdde 100644
--- a/drivers/virt/Kconfig
+++ b/drivers/virt/Kconfig
@@ -15,6 +15,7 @@ if VIRT_DRIVERS
 config FSL_HV_MANAGER
 	tristate "Freescale hypervisor management driver"
 	depends on FSL_SOC
+	select EPAPR_PARAVIRT
 	help
           The Freescale hypervisor management driver provides several services
 	  to drivers and applications related to the Freescale hypervisor:
diff --git a/drivers/virt/fsl_hypervisor.c b/drivers/virt/fsl_hypervisor.c
index 4939e0c..d294f67 100644
--- a/drivers/virt/fsl_hypervisor.c
+++ b/drivers/virt/fsl_hypervisor.c
@@ -796,9 +796,6 @@ static int has_fsl_hypervisor(void)
 	struct device_node *node;
 	int ret;
 
-	if (!(mfmsr() & MSR_GS))
-		return 0;
-
 	node = of_find_node_by_path("/hypervisor");
 	if (!node)
 		return 0;
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 8d5bddb..c6683f2 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -8,8 +8,8 @@ config VIRTIO
 menu "Virtio drivers"
 
 config VIRTIO_PCI
-	tristate "PCI driver for virtio devices (EXPERIMENTAL)"
-	depends on PCI && EXPERIMENTAL
+	tristate "PCI driver for virtio devices"
+	depends on PCI
 	select VIRTIO
 	---help---
 	  This drivers provides support for virtio based paravirtual device
@@ -32,8 +32,8 @@ config VIRTIO_BALLOON
 	 If unsure, say M.
 
  config VIRTIO_MMIO
- 	tristate "Platform bus driver for memory mapped virtio devices (EXPERIMENTAL)"
- 	depends on HAS_IOMEM && EXPERIMENTAL
+	tristate "Platform bus driver for memory mapped virtio devices"
+	depends on HAS_IOMEM
  	select VIRTIO
  	---help---
  	 This drivers provides support for memory mapped virtio
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 0908e60..7363084 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -27,13 +27,15 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/balloon_compaction.h>
 
 /*
  * Balloon device works in 4K page units.  So each page is pointed to by
  * multiple balloon pages.  All memory counters in this driver are in balloon
  * page units.
  */
-#define VIRTIO_BALLOON_PAGES_PER_PAGE (PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT)
+#define VIRTIO_BALLOON_PAGES_PER_PAGE (unsigned)(PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT)
+#define VIRTIO_BALLOON_ARRAY_PFNS_MAX 256
 
 struct virtio_balloon
 {
@@ -52,15 +54,19 @@ struct virtio_balloon
 	/* Number of balloon pages we've told the Host we're not using. */
 	unsigned int num_pages;
 	/*
-	 * The pages we've told the Host we're not using.
+	 * The pages we've told the Host we're not using are enqueued
+	 * at vb_dev_info->pages list.
 	 * Each page on this list adds VIRTIO_BALLOON_PAGES_PER_PAGE
 	 * to num_pages above.
 	 */
-	struct list_head pages;
+	struct balloon_dev_info *vb_dev_info;
+
+	/* Synchronize access/update to this struct virtio_balloon elements */
+	struct mutex balloon_lock;
 
 	/* The array of pfns we tell the Host about. */
 	unsigned int num_pfns;
-	u32 pfns[256];
+	u32 pfns[VIRTIO_BALLOON_ARRAY_PFNS_MAX];
 
 	/* Memory statistics */
 	int need_stats_update;
@@ -122,18 +128,20 @@ static void set_page_pfns(u32 pfns[], struct page *page)
 
 static void fill_balloon(struct virtio_balloon *vb, size_t num)
 {
+	struct balloon_dev_info *vb_dev_info = vb->vb_dev_info;
+
 	/* We can only do one array worth at a time. */
 	num = min(num, ARRAY_SIZE(vb->pfns));
 
+	mutex_lock(&vb->balloon_lock);
 	for (vb->num_pfns = 0; vb->num_pfns < num;
 	     vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
-		struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY |
-					__GFP_NOMEMALLOC | __GFP_NOWARN);
+		struct page *page = balloon_page_enqueue(vb_dev_info);
+
 		if (!page) {
-			if (printk_ratelimit())
-				dev_printk(KERN_INFO, &vb->vdev->dev,
-					   "Out of puff! Can't get %zu pages\n",
-					   num);
+			dev_info_ratelimited(&vb->vdev->dev,
+					   "Out of puff! Can't get %u pages\n",
+					     VIRTIO_BALLOON_PAGES_PER_PAGE);
 			/* Sleep for at least 1/5 of a second before retry. */
 			msleep(200);
 			break;
@@ -141,14 +149,12 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num)
 		set_page_pfns(vb->pfns + vb->num_pfns, page);
 		vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
 		totalram_pages--;
-		list_add(&page->lru, &vb->pages);
 	}
 
-	/* Didn't get any?  Oh well. */
-	if (vb->num_pfns == 0)
-		return;
-
-	tell_host(vb, vb->inflate_vq);
+	/* Did we get any? */
+	if (vb->num_pfns != 0)
+		tell_host(vb, vb->inflate_vq);
+	mutex_unlock(&vb->balloon_lock);
 }
 
 static void release_pages_by_pfn(const u32 pfns[], unsigned int num)
@@ -157,7 +163,7 @@ static void release_pages_by_pfn(const u32 pfns[], unsigned int num)
 
 	/* Find pfns pointing at start of each page, get pages and free them. */
 	for (i = 0; i < num; i += VIRTIO_BALLOON_PAGES_PER_PAGE) {
-		__free_page(balloon_pfn_to_page(pfns[i]));
+		balloon_page_free(balloon_pfn_to_page(pfns[i]));
 		totalram_pages++;
 	}
 }
@@ -165,14 +171,17 @@ static void release_pages_by_pfn(const u32 pfns[], unsigned int num)
 static void leak_balloon(struct virtio_balloon *vb, size_t num)
 {
 	struct page *page;
+	struct balloon_dev_info *vb_dev_info = vb->vb_dev_info;
 
 	/* We can only do one array worth at a time. */
 	num = min(num, ARRAY_SIZE(vb->pfns));
 
+	mutex_lock(&vb->balloon_lock);
 	for (vb->num_pfns = 0; vb->num_pfns < num;
 	     vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
-		page = list_first_entry(&vb->pages, struct page, lru);
-		list_del(&page->lru);
+		page = balloon_page_dequeue(vb_dev_info);
+		if (!page)
+			break;
 		set_page_pfns(vb->pfns + vb->num_pfns, page);
 		vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE;
 	}
@@ -183,6 +192,7 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num)
 	 * is true, we *have* to do it in this order
 	 */
 	tell_host(vb, vb->deflate_vq);
+	mutex_unlock(&vb->balloon_lock);
 	release_pages_by_pfn(vb->pfns, vb->num_pfns);
 }
 
@@ -339,9 +349,84 @@ static int init_vqs(struct virtio_balloon *vb)
 	return 0;
 }
 
+static const struct address_space_operations virtio_balloon_aops;
+#ifdef CONFIG_BALLOON_COMPACTION
+/*
+ * virtballoon_migratepage - perform the balloon page migration on behalf of
+ *			     a compation thread.     (called under page lock)
+ * @mapping: the page->mapping which will be assigned to the new migrated page.
+ * @newpage: page that will replace the isolated page after migration finishes.
+ * @page   : the isolated (old) page that is about to be migrated to newpage.
+ * @mode   : compaction mode -- not used for balloon page migration.
+ *
+ * After a ballooned page gets isolated by compaction procedures, this is the
+ * function that performs the page migration on behalf of a compaction thread
+ * The page migration for virtio balloon is done in a simple swap fashion which
+ * follows these two macro steps:
+ *  1) insert newpage into vb->pages list and update the host about it;
+ *  2) update the host about the old page removed from vb->pages list;
+ *
+ * This function preforms the balloon page migration task.
+ * Called through balloon_mapping->a_ops->migratepage
+ */
+int virtballoon_migratepage(struct address_space *mapping,
+		struct page *newpage, struct page *page, enum migrate_mode mode)
+{
+	struct balloon_dev_info *vb_dev_info = balloon_page_device(page);
+	struct virtio_balloon *vb;
+	unsigned long flags;
+
+	BUG_ON(!vb_dev_info);
+
+	vb = vb_dev_info->balloon_device;
+
+	/*
+	 * In order to avoid lock contention while migrating pages concurrently
+	 * to leak_balloon() or fill_balloon() we just give up the balloon_lock
+	 * this turn, as it is easier to retry the page migration later.
+	 * This also prevents fill_balloon() getting stuck into a mutex
+	 * recursion in the case it ends up triggering memory compaction
+	 * while it is attempting to inflate the ballon.
+	 */
+	if (!mutex_trylock(&vb->balloon_lock))
+		return -EAGAIN;
+
+	/* balloon's page migration 1st step  -- inflate "newpage" */
+	spin_lock_irqsave(&vb_dev_info->pages_lock, flags);
+	balloon_page_insert(newpage, mapping, &vb_dev_info->pages);
+	vb_dev_info->isolated_pages--;
+	spin_unlock_irqrestore(&vb_dev_info->pages_lock, flags);
+	vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
+	set_page_pfns(vb->pfns, newpage);
+	tell_host(vb, vb->inflate_vq);
+
+	/*
+	 * balloon's page migration 2nd step -- deflate "page"
+	 *
+	 * It's safe to delete page->lru here because this page is at
+	 * an isolated migration list, and this step is expected to happen here
+	 */
+	balloon_page_delete(page);
+	vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
+	set_page_pfns(vb->pfns, page);
+	tell_host(vb, vb->deflate_vq);
+
+	mutex_unlock(&vb->balloon_lock);
+
+	return MIGRATEPAGE_BALLOON_SUCCESS;
+}
+
+/* define the balloon_mapping->a_ops callback to allow balloon page migration */
+static const struct address_space_operations virtio_balloon_aops = {
+			.migratepage = virtballoon_migratepage,
+};
+#endif /* CONFIG_BALLOON_COMPACTION */
+
 static int virtballoon_probe(struct virtio_device *vdev)
 {
 	struct virtio_balloon *vb;
+	struct address_space *vb_mapping;
+	struct balloon_dev_info *vb_devinfo;
 	int err;
 
 	vdev->priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL);
@@ -350,16 +435,37 @@ static int virtballoon_probe(struct virtio_device *vdev)
 		goto out;
 	}
 
-	INIT_LIST_HEAD(&vb->pages);
 	vb->num_pages = 0;
+	mutex_init(&vb->balloon_lock);
 	init_waitqueue_head(&vb->config_change);
 	init_waitqueue_head(&vb->acked);
 	vb->vdev = vdev;
 	vb->need_stats_update = 0;
 
+	vb_devinfo = balloon_devinfo_alloc(vb);
+	if (IS_ERR(vb_devinfo)) {
+		err = PTR_ERR(vb_devinfo);
+		goto out_free_vb;
+	}
+
+	vb_mapping = balloon_mapping_alloc(vb_devinfo,
+					   (balloon_compaction_check()) ?
+					   &virtio_balloon_aops : NULL);
+	if (IS_ERR(vb_mapping)) {
+		/*
+		 * IS_ERR(vb_mapping) && PTR_ERR(vb_mapping) == -EOPNOTSUPP
+		 * This means !CONFIG_BALLOON_COMPACTION, otherwise we get off.
+		 */
+		err = PTR_ERR(vb_mapping);
+		if (err != -EOPNOTSUPP)
+			goto out_free_vb_devinfo;
+	}
+
+	vb->vb_dev_info = vb_devinfo;
+
 	err = init_vqs(vb);
 	if (err)
-		goto out_free_vb;
+		goto out_free_vb_mapping;
 
 	vb->thread = kthread_run(balloon, vb, "vballoon");
 	if (IS_ERR(vb->thread)) {
@@ -371,6 +477,10 @@ static int virtballoon_probe(struct virtio_device *vdev)
 
 out_del_vqs:
 	vdev->config->del_vqs(vdev);
+out_free_vb_mapping:
+	balloon_mapping_free(vb_mapping);
+out_free_vb_devinfo:
+	balloon_devinfo_free(vb_devinfo);
 out_free_vb:
 	kfree(vb);
 out:
@@ -396,6 +506,8 @@ static void __devexit virtballoon_remove(struct virtio_device *vdev)
 
 	kthread_stop(vb->thread);
 	remove_common(vb);
+	balloon_mapping_free(vb->vb_dev_info->mapping);
+	balloon_devinfo_free(vb->vb_dev_info);
 	kfree(vb);
 }
 
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 6b1b7e1..634f80b 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -225,7 +225,7 @@ static void vm_notify(struct virtqueue *vq)
 
 	/* We write the queue's selector into the notification register to
 	 * signal the other end */
-	writel(virtqueue_get_queue_index(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY);
+	writel(vq->index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY);
 }
 
 /* Notify all virtqueues on an interrupt. */
@@ -266,7 +266,7 @@ static void vm_del_vq(struct virtqueue *vq)
 	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev);
 	struct virtio_mmio_vq_info *info = vq->priv;
 	unsigned long flags, size;
-	unsigned int index = virtqueue_get_queue_index(vq);
+	unsigned int index = vq->index;
 
 	spin_lock_irqsave(&vm_dev->lock, flags);
 	list_del(&info->node);
@@ -521,25 +521,33 @@ static int vm_cmdline_set(const char *device,
 	int err;
 	struct resource resources[2] = {};
 	char *str;
-	long long int base;
+	long long int base, size;
+	unsigned int irq;
 	int processed, consumed = 0;
 	struct platform_device *pdev;
 
-	resources[0].flags = IORESOURCE_MEM;
-	resources[1].flags = IORESOURCE_IRQ;
-
-	resources[0].end = memparse(device, &str) - 1;
+	/* Consume "size" part of the command line parameter */
+	size = memparse(device, &str);
 
+	/* Get "@<base>:<irq>[:<id>]" chunks */
 	processed = sscanf(str, "@%lli:%u%n:%d%n",
-			&base, &resources[1].start, &consumed,
+			&base, &irq, &consumed,
 			&vm_cmdline_id, &consumed);
 
-	if (processed < 2 || processed > 3 || str[consumed])
+	/*
+	 * sscanf() must processes at least 2 chunks; also there
+	 * must be no extra characters after the last chunk, so
+	 * str[consumed] must be '\0'
+	 */
+	if (processed < 2 || str[consumed])
 		return -EINVAL;
 
+	resources[0].flags = IORESOURCE_MEM;
 	resources[0].start = base;
-	resources[0].end += base;
-	resources[1].end = resources[1].start;
+	resources[0].end = base + size - 1;
+
+	resources[1].flags = IORESOURCE_IRQ;
+	resources[1].start = resources[1].end = irq;
 
 	if (!vm_cmdline_parent_registered) {
 		err = device_register(&vm_cmdline_parent);
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index c33aea3..e3ecc94 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -203,8 +203,7 @@ static void vp_notify(struct virtqueue *vq)
 
 	/* we write the queue's selector into the notification register to
 	 * signal the other end */
-	iowrite16(virtqueue_get_queue_index(vq),
-		  vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
+	iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
 }
 
 /* Handle a configuration change: Tell driver if it wants to know. */
@@ -479,8 +478,7 @@ static void vp_del_vq(struct virtqueue *vq)
 	list_del(&info->node);
 	spin_unlock_irqrestore(&vp_dev->lock, flags);
 
-	iowrite16(virtqueue_get_queue_index(vq),
-		vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
+	iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
 
 	if (vp_dev->msix_enabled) {
 		iowrite16(VIRTIO_MSI_NO_VECTOR,
@@ -830,16 +828,4 @@ static struct pci_driver virtio_pci_driver = {
 #endif
 };
 
-static int __init virtio_pci_init(void)
-{
-	return pci_register_driver(&virtio_pci_driver);
-}
-
-module_init(virtio_pci_init);
-
-static void __exit virtio_pci_exit(void)
-{
-	pci_unregister_driver(&virtio_pci_driver);
-}
-
-module_exit(virtio_pci_exit);
+module_pci_driver(virtio_pci_driver);
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index e639584..ffd7e7d 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -93,8 +93,6 @@ struct vring_virtqueue
 	/* Host publishes avail event idx */
 	bool event;
 
-	/* Number of free buffers */
-	unsigned int num_free;
 	/* Head of free buffer list. */
 	unsigned int free_head;
 	/* Number we've added since last sync. */
@@ -106,9 +104,6 @@ struct vring_virtqueue
 	/* How to notify other side. FIXME: commonalize hcalls! */
 	void (*notify)(struct virtqueue *vq);
 
-	/* Index of the queue */
-	int queue_index;
-
 #ifdef DEBUG
 	/* They're supposed to lock for us. */
 	unsigned int in_use;
@@ -135,6 +130,13 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
 	unsigned head;
 	int i;
 
+	/*
+	 * We require lowmem mappings for the descriptors because
+	 * otherwise virt_to_phys will give us bogus addresses in the
+	 * virtqueue.
+	 */
+	gfp &= ~(__GFP_HIGHMEM | __GFP_HIGH);
+
 	desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp);
 	if (!desc)
 		return -ENOMEM;
@@ -160,7 +162,7 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
 	desc[i-1].next = 0;
 
 	/* We're about to use a buffer */
-	vq->num_free--;
+	vq->vq.num_free--;
 
 	/* Use a single buffer which doesn't continue */
 	head = vq->free_head;
@@ -174,13 +176,6 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
 	return head;
 }
 
-int virtqueue_get_queue_index(struct virtqueue *_vq)
-{
-	struct vring_virtqueue *vq = to_vvq(_vq);
-	return vq->queue_index;
-}
-EXPORT_SYMBOL_GPL(virtqueue_get_queue_index);
-
 /**
  * virtqueue_add_buf - expose buffer to other end
  * @vq: the struct virtqueue we're talking about.
@@ -193,10 +188,7 @@ EXPORT_SYMBOL_GPL(virtqueue_get_queue_index);
  * Caller must ensure we don't call this with other virtqueue operations
  * at the same time (except where noted).
  *
- * Returns remaining capacity of queue or a negative error
- * (ie. ENOSPC).  Note that it only really makes sense to treat all
- * positive return values as "available": indirect buffers mean that
- * we can put an entire sg[] array inside a single queue entry.
+ * Returns zero or a negative error (ie. ENOSPC, ENOMEM).
  */
 int virtqueue_add_buf(struct virtqueue *_vq,
 		      struct scatterlist sg[],
@@ -228,7 +220,7 @@ int virtqueue_add_buf(struct virtqueue *_vq,
 
 	/* If the host supports indirect descriptor tables, and we have multiple
 	 * buffers, then go indirect. FIXME: tune this threshold */
-	if (vq->indirect && (out + in) > 1 && vq->num_free) {
+	if (vq->indirect && (out + in) > 1 && vq->vq.num_free) {
 		head = vring_add_indirect(vq, sg, out, in, gfp);
 		if (likely(head >= 0))
 			goto add_head;
@@ -237,9 +229,9 @@ int virtqueue_add_buf(struct virtqueue *_vq,
 	BUG_ON(out + in > vq->vring.num);
 	BUG_ON(out + in == 0);
 
-	if (vq->num_free < out + in) {
+	if (vq->vq.num_free < out + in) {
 		pr_debug("Can't add buf len %i - avail = %i\n",
-			 out + in, vq->num_free);
+			 out + in, vq->vq.num_free);
 		/* FIXME: for historical reasons, we force a notify here if
 		 * there are outgoing parts to the buffer.  Presumably the
 		 * host should service the ring ASAP. */
@@ -250,7 +242,7 @@ int virtqueue_add_buf(struct virtqueue *_vq,
 	}
 
 	/* We're about to use some buffers from the free list. */
-	vq->num_free -= out + in;
+	vq->vq.num_free -= out + in;
 
 	head = vq->free_head;
 	for (i = vq->free_head; out; i = vq->vring.desc[i].next, out--) {
@@ -296,7 +288,7 @@ add_head:
 	pr_debug("Added buffer head %i to %p\n", head, vq);
 	END_USE(vq);
 
-	return vq->num_free;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(virtqueue_add_buf);
 
@@ -393,13 +385,13 @@ static void detach_buf(struct vring_virtqueue *vq, unsigned int head)
 
 	while (vq->vring.desc[i].flags & VRING_DESC_F_NEXT) {
 		i = vq->vring.desc[i].next;
-		vq->num_free++;
+		vq->vq.num_free++;
 	}
 
 	vq->vring.desc[i].next = vq->free_head;
 	vq->free_head = head;
 	/* Plus final descriptor */
-	vq->num_free++;
+	vq->vq.num_free++;
 }
 
 static inline bool more_used(const struct vring_virtqueue *vq)
@@ -599,7 +591,7 @@ void *virtqueue_detach_unused_buf(struct virtqueue *_vq)
 		return buf;
 	}
 	/* That should have freed everything. */
-	BUG_ON(vq->num_free != vq->vring.num);
+	BUG_ON(vq->vq.num_free != vq->vring.num);
 
 	END_USE(vq);
 	return NULL;
@@ -653,12 +645,13 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
 	vq->vq.callback = callback;
 	vq->vq.vdev = vdev;
 	vq->vq.name = name;
+	vq->vq.num_free = num;
+	vq->vq.index = index;
 	vq->notify = notify;
 	vq->weak_barriers = weak_barriers;
 	vq->broken = false;
 	vq->last_used_idx = 0;
 	vq->num_added = 0;
-	vq->queue_index = index;
 	list_add_tail(&vq->vq.list, &vdev->vqs);
 #ifdef DEBUG
 	vq->in_use = false;
@@ -673,7 +666,6 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
 		vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
 
 	/* Put everything in free lists. */
-	vq->num_free = num;
 	vq->free_head = 0;
 	for (i = 0; i < num-1; i++) {
 		vq->vring.desc[i].next = i+1;
diff --git a/drivers/vme/boards/vme_vmivme7805.c b/drivers/vme/boards/vme_vmivme7805.c
index 8e05bb4..dd22b50 100644
--- a/drivers/vme/boards/vme_vmivme7805.c
+++ b/drivers/vme/boards/vme_vmivme7805.c
@@ -19,10 +19,8 @@
 
 #include "vme_vmivme7805.h"
 
-static int __init vmic_init(void);
 static int vmic_probe(struct pci_dev *, const struct pci_device_id *);
 static void vmic_remove(struct pci_dev *);
-static void __exit vmic_exit(void);
 
 /** Base address to access FPGA register */
 static void *vmic_base;
@@ -41,11 +39,6 @@ static struct pci_driver vmic_driver = {
 	.remove = vmic_remove,
 };
 
-static int __init vmic_init(void)
-{
-	return pci_register_driver(&vmic_driver);
-}
-
 static int vmic_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	int retval;
@@ -109,15 +102,9 @@ static void vmic_remove(struct pci_dev *pdev)
 
 }
 
-static void __exit vmic_exit(void)
-{
-	pci_unregister_driver(&vmic_driver);
-}
+module_pci_driver(vmic_driver);
 
 MODULE_DESCRIPTION("VMIVME-7805 board support driver");
 MODULE_AUTHOR("Arthur Benilov <arthur.benilov@iba-group.com>");
 MODULE_LICENSE("GPL");
 
-module_init(vmic_init);
-module_exit(vmic_exit);
-
diff --git a/drivers/vme/bridges/vme_ca91cx42.c b/drivers/vme/bridges/vme_ca91cx42.c
index 1425d22c..64bfea3 100644
--- a/drivers/vme/bridges/vme_ca91cx42.c
+++ b/drivers/vme/bridges/vme_ca91cx42.c
@@ -34,10 +34,8 @@
 #include "../vme_bridge.h"
 #include "vme_ca91cx42.h"
 
-static int __init ca91cx42_init(void);
 static int ca91cx42_probe(struct pci_dev *, const struct pci_device_id *);
 static void ca91cx42_remove(struct pci_dev *);
-static void __exit ca91cx42_exit(void);
 
 /* Module parameters */
 static int geoid;
@@ -1523,11 +1521,6 @@ static void ca91cx42_free_consistent(struct device *parent, size_t size,
 	pci_free_consistent(pdev, size, vaddr, dma);
 }
 
-static int __init ca91cx42_init(void)
-{
-	return pci_register_driver(&ca91cx42_driver);
-}
-
 /*
  * Configure CR/CSR space
  *
@@ -1944,16 +1937,10 @@ static void ca91cx42_remove(struct pci_dev *pdev)
 	kfree(ca91cx42_bridge);
 }
 
-static void __exit ca91cx42_exit(void)
-{
-	pci_unregister_driver(&ca91cx42_driver);
-}
+module_pci_driver(ca91cx42_driver);
 
 MODULE_PARM_DESC(geoid, "Override geographical addressing");
 module_param(geoid, int, 0);
 
 MODULE_DESCRIPTION("VME driver for the Tundra Universe II VME bridge");
 MODULE_LICENSE("GPL");
-
-module_init(ca91cx42_init);
-module_exit(ca91cx42_exit);
diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c
index 5fbd08f..9c1aa4d 100644
--- a/drivers/vme/bridges/vme_tsi148.c
+++ b/drivers/vme/bridges/vme_tsi148.c
@@ -35,10 +35,8 @@
 #include "../vme_bridge.h"
 #include "vme_tsi148.h"
 
-static int __init tsi148_init(void);
 static int tsi148_probe(struct pci_dev *, const struct pci_device_id *);
 static void tsi148_remove(struct pci_dev *);
-static void __exit tsi148_exit(void);
 
 
 /* Module parameter */
@@ -2244,11 +2242,6 @@ static void tsi148_free_consistent(struct device *parent, size_t size,
 	pci_free_consistent(pdev, size, vaddr, dma);
 }
 
-static int __init tsi148_init(void)
-{
-	return pci_register_driver(&tsi148_driver);
-}
-
 /*
  * Configure CR/CSR space
  *
@@ -2754,10 +2747,7 @@ static void tsi148_remove(struct pci_dev *pdev)
 	kfree(tsi148_bridge);
 }
 
-static void __exit tsi148_exit(void)
-{
-	pci_unregister_driver(&tsi148_driver);
-}
+module_pci_driver(tsi148_driver);
 
 MODULE_PARM_DESC(err_chk, "Check for VME errors on reads and writes");
 module_param(err_chk, bool, 0);
@@ -2767,6 +2757,3 @@ module_param(geoid, int, 0);
 
 MODULE_DESCRIPTION("VME driver for the Tundra Tempe VME bridge");
 MODULE_LICENSE("GPL");
-
-module_init(tsi148_init);
-module_exit(tsi148_exit);
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig
index 7e98403..c433a74 100644
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -26,7 +26,7 @@ config W1_MASTER_DS2490
 
 config W1_MASTER_DS2482
 	tristate "Maxim DS2482 I2C to 1-Wire bridge"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for the Maxim DS2482
 	  I2C to 1-Wire bridge.
diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c
index e5f7441..6429b9e 100644
--- a/drivers/w1/masters/ds2482.c
+++ b/drivers/w1/masters/ds2482.c
@@ -505,19 +505,8 @@ static int ds2482_remove(struct i2c_client *client)
 	return 0;
 }
 
-static int __init sensors_ds2482_init(void)
-{
-	return i2c_add_driver(&ds2482_driver);
-}
-
-static void __exit sensors_ds2482_exit(void)
-{
-	i2c_del_driver(&ds2482_driver);
-}
+module_i2c_driver(ds2482_driver);
 
 MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
 MODULE_DESCRIPTION("DS2482 driver");
 MODULE_LICENSE("GPL");
-
-module_init(sensors_ds2482_init);
-module_exit(sensors_ds2482_exit);
diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c
index f667c26..d8667b0 100644
--- a/drivers/w1/masters/matrox_w1.c
+++ b/drivers/w1/masters/matrox_w1.c
@@ -48,14 +48,14 @@ static struct pci_device_id matrox_w1_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, matrox_w1_tbl);
 
-static int __devinit matrox_w1_probe(struct pci_dev *, const struct pci_device_id *);
-static void __devexit matrox_w1_remove(struct pci_dev *);
+static int matrox_w1_probe(struct pci_dev *, const struct pci_device_id *);
+static void matrox_w1_remove(struct pci_dev *);
 
 static struct pci_driver matrox_w1_pci_driver = {
 	.name = "matrox_w1",
 	.id_table = matrox_w1_tbl,
 	.probe = matrox_w1_probe,
-	.remove = __devexit_p(matrox_w1_remove),
+	.remove = matrox_w1_remove,
 };
 
 /*
@@ -152,7 +152,7 @@ static void matrox_w1_hw_init(struct matrox_device *dev)
 	matrox_w1_write_reg(dev, MATROX_GET_CONTROL, 0x00);
 }
 
-static int __devinit matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct matrox_device *dev;
 	int err;
@@ -220,7 +220,7 @@ err_out_free_device:
 	return err;
 }
 
-static void __devexit matrox_w1_remove(struct pci_dev *pdev)
+static void matrox_w1_remove(struct pci_dev *pdev)
 {
 	struct matrox_device *dev = pci_get_drvdata(pdev);
 
diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c
index 1cc61a7..d338b56 100644
--- a/drivers/w1/masters/mxc_w1.c
+++ b/drivers/w1/masters/mxc_w1.c
@@ -103,7 +103,7 @@ static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit)
 	return ((__raw_readb(ctrl_addr)) >> 3) & 0x1;
 }
 
-static int __devinit mxc_w1_probe(struct platform_device *pdev)
+static int mxc_w1_probe(struct platform_device *pdev)
 {
 	struct mxc_w1_device *mdev;
 	struct resource *res;
@@ -117,9 +117,9 @@ static int __devinit mxc_w1_probe(struct platform_device *pdev)
 	if (!mdev)
 		return -ENOMEM;
 
-	mdev->clk = clk_get(&pdev->dev, "owire");
-	if (!mdev->clk) {
-		err = -ENODEV;
+	mdev->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(mdev->clk)) {
+		err = PTR_ERR(mdev->clk);
 		goto failed_clk;
 	}
 
@@ -134,7 +134,7 @@ static int __devinit mxc_w1_probe(struct platform_device *pdev)
 
 	mdev->regs = ioremap(res->start, resource_size(res));
 	if (!mdev->regs) {
-		printk(KERN_ERR "Cannot map frame buffer registers\n");
+		dev_err(&pdev->dev, "Cannot map mxc_w1 registers\n");
 		goto failed_ioremap;
 	}
 
@@ -167,7 +167,7 @@ failed_clk:
 /*
  * disassociate the w1 device from the driver
  */
-static int __devexit mxc_w1_remove(struct platform_device *pdev)
+static int mxc_w1_remove(struct platform_device *pdev)
 {
 	struct mxc_w1_device *mdev = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -191,21 +191,9 @@ static struct platform_driver mxc_w1_driver = {
 		   .name = "mxc_w1",
 	},
 	.probe = mxc_w1_probe,
-	.remove = mxc_w1_remove,
+	.remove = __devexit_p(mxc_w1_remove),
 };
-
-static int __init mxc_w1_init(void)
-{
-	return platform_driver_register(&mxc_w1_driver);
-}
-
-static void mxc_w1_exit(void)
-{
-	platform_driver_unregister(&mxc_w1_driver);
-}
-
-module_init(mxc_w1_init);
-module_exit(mxc_w1_exit);
+module_platform_driver(mxc_w1_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Freescale Semiconductors Inc");
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
index ca8e60b..184dbce 100644
--- a/drivers/w1/masters/omap_hdq.c
+++ b/drivers/w1/masters/omap_hdq.c
@@ -69,12 +69,12 @@ struct hdq_data {
 	int			init_trans;
 };
 
-static int __devinit omap_hdq_probe(struct platform_device *pdev);
-static int __devexit omap_hdq_remove(struct platform_device *pdev);
+static int omap_hdq_probe(struct platform_device *pdev);
+static int omap_hdq_remove(struct platform_device *pdev);
 
 static struct platform_driver omap_hdq_driver = {
 	.probe =	omap_hdq_probe,
-	.remove =	__devexit_p(omap_hdq_remove),
+	.remove =	omap_hdq_remove,
 	.driver =	{
 		.name =	"omap_hdq",
 	},
@@ -537,7 +537,7 @@ static void omap_w1_write_byte(void *_hdq, u8 byte)
 	}
 }
 
-static int __devinit omap_hdq_probe(struct platform_device *pdev)
+static int omap_hdq_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct hdq_data *hdq_data;
@@ -613,7 +613,7 @@ err_w1:
 	return ret;
 }
 
-static int __devexit omap_hdq_remove(struct platform_device *pdev)
+static int omap_hdq_remove(struct platform_device *pdev)
 {
 	struct hdq_data *hdq_data = platform_get_drvdata(pdev);
 
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
index 6012c4e..85b363a 100644
--- a/drivers/w1/masters/w1-gpio.c
+++ b/drivers/w1/masters/w1-gpio.c
@@ -16,6 +16,9 @@
 #include <linux/gpio.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/err.h>
+#include <linux/of.h>
 
 #include "../w1.h"
 #include "../w1_int.h"
@@ -44,7 +47,6 @@ static u8 w1_gpio_read_bit(void *data)
 	return gpio_get_value(pdata->pin) ? 1 : 0;
 }
 
-#ifdef CONFIG_OF
 static struct of_device_id w1_gpio_dt_ids[] = {
 	{ .compatible = "w1-gpio" },
 	{}
@@ -55,11 +57,6 @@ static int w1_gpio_probe_dt(struct platform_device *pdev)
 {
 	struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
 	struct device_node *np = pdev->dev.of_node;
-	const struct of_device_id *of_id =
-			of_match_device(w1_gpio_dt_ids, &pdev->dev);
-
-	if (!of_id)
-		return 0;
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
@@ -74,41 +71,53 @@ static int w1_gpio_probe_dt(struct platform_device *pdev)
 
 	return 0;
 }
-#else
-static int w1_gpio_probe_dt(struct platform_device *pdev)
-{
-	return 0;
-}
-#endif
 
 static int __init w1_gpio_probe(struct platform_device *pdev)
 {
 	struct w1_bus_master *master;
 	struct w1_gpio_platform_data *pdata;
+	struct pinctrl *pinctrl;
 	int err;
 
-	err = w1_gpio_probe_dt(pdev);
-	if (err < 0)
-		return err;
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev, "unable to select pin group\n");
+
+	if (of_have_populated_dt()) {
+		err = w1_gpio_probe_dt(pdev);
+		if (err < 0) {
+			dev_err(&pdev->dev, "Failed to parse DT\n");
+			return err;
+		}
+	}
 
 	pdata = pdev->dev.platform_data;
 
-	if (!pdata)
+	if (!pdata) {
+		dev_err(&pdev->dev, "No configuration data\n");
 		return -ENXIO;
+	}
 
 	master = kzalloc(sizeof(struct w1_bus_master), GFP_KERNEL);
-	if (!master)
+	if (!master) {
+		dev_err(&pdev->dev, "Out of memory\n");
 		return -ENOMEM;
+	}
 
 	err = gpio_request(pdata->pin, "w1");
-	if (err)
+	if (err) {
+		dev_err(&pdev->dev, "gpio_request (pin) failed\n");
 		goto free_master;
+	}
 
 	if (gpio_is_valid(pdata->ext_pullup_enable_pin)) {
 		err = gpio_request_one(pdata->ext_pullup_enable_pin,
 				       GPIOF_INIT_LOW, "w1 pullup");
-		if (err < 0)
+		if (err < 0) {
+			dev_err(&pdev->dev, "gpio_request_one "
+					"(ext_pullup_enable_pin) failed\n");
 			goto free_gpio;
+		}
 	}
 
 	master->data = pdata;
@@ -123,8 +132,10 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
 	}
 
 	err = w1_add_master_device(master);
-	if (err)
+	if (err) {
+		dev_err(&pdev->dev, "w1_add_master device failed\n");
 		goto free_gpio_ext_pu;
+	}
 
 	if (pdata->enable_external_pullup)
 		pdata->enable_external_pullup(1);
@@ -198,23 +209,13 @@ static struct platform_driver w1_gpio_driver = {
 		.owner	= THIS_MODULE,
 		.of_match_table = of_match_ptr(w1_gpio_dt_ids),
 	},
+	.probe = w1_gpio_probe,
 	.remove	= __exit_p(w1_gpio_remove),
 	.suspend = w1_gpio_suspend,
 	.resume = w1_gpio_resume,
 };
 
-static int __init w1_gpio_init(void)
-{
-	return platform_driver_probe(&w1_gpio_driver, w1_gpio_probe);
-}
-
-static void __exit w1_gpio_exit(void)
-{
-	platform_driver_unregister(&w1_gpio_driver);
-}
-
-module_init(w1_gpio_init);
-module_exit(w1_gpio_exit);
+module_platform_driver(w1_gpio_driver);
 
 MODULE_DESCRIPTION("GPIO w1 bus master driver");
 MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>");
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 1a57437..7994d933 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -551,7 +551,6 @@ void w1_destroy_master_attributes(struct w1_master *master)
 	sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
 }
 
-#ifdef CONFIG_HOTPLUG
 static int w1_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
 	struct w1_master *md = NULL;
@@ -587,12 +586,6 @@ static int w1_uevent(struct device *dev, struct kobj_uevent_env *env)
 end:
 	return err;
 }
-#else
-static int w1_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-	return 0;
-}
-#endif
 
 static int __w1_attach_slave_device(struct w1_slave *sl)
 {
diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c
index 4397881..24a5177 100644
--- a/drivers/watchdog/acquirewdt.c
+++ b/drivers/watchdog/acquirewdt.c
@@ -240,7 +240,7 @@ static struct miscdevice acq_miscdev = {
  *	Init & exit routines
  */
 
-static int __devinit acq_probe(struct platform_device *dev)
+static int acq_probe(struct platform_device *dev)
 {
 	int ret;
 
@@ -275,7 +275,7 @@ out:
 	return ret;
 }
 
-static int __devexit acq_remove(struct platform_device *dev)
+static int acq_remove(struct platform_device *dev)
 {
 	misc_deregister(&acq_miscdev);
 	release_region(wdt_start, 1);
@@ -293,7 +293,7 @@ static void acq_shutdown(struct platform_device *dev)
 
 static struct platform_driver acquirewdt_driver = {
 	.probe		= acq_probe,
-	.remove		= __devexit_p(acq_remove),
+	.remove		= acq_remove,
 	.shutdown	= acq_shutdown,
 	.driver		= {
 		.owner	= THIS_MODULE,
diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c
index 64ae9e9..cc6702f 100644
--- a/drivers/watchdog/advantechwdt.c
+++ b/drivers/watchdog/advantechwdt.c
@@ -238,7 +238,7 @@ static struct miscdevice advwdt_miscdev = {
  *	Init & exit routines
  */
 
-static int __devinit advwdt_probe(struct platform_device *dev)
+static int advwdt_probe(struct platform_device *dev)
 {
 	int ret;
 
@@ -282,7 +282,7 @@ unreg_stop:
 	goto out;
 }
 
-static int __devexit advwdt_remove(struct platform_device *dev)
+static int advwdt_remove(struct platform_device *dev)
 {
 	misc_deregister(&advwdt_miscdev);
 	release_region(wdt_start, 1);
@@ -300,7 +300,7 @@ static void advwdt_shutdown(struct platform_device *dev)
 
 static struct platform_driver advwdt_driver = {
 	.probe		= advwdt_probe,
-	.remove		= __devexit_p(advwdt_remove),
+	.remove		= advwdt_remove,
 	.shutdown	= advwdt_shutdown,
 	.driver		= {
 		.owner	= THIS_MODULE,
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
index dc30dbd..3003e2a 100644
--- a/drivers/watchdog/ar7_wdt.c
+++ b/drivers/watchdog/ar7_wdt.c
@@ -274,7 +274,7 @@ static struct miscdevice ar7_wdt_miscdev = {
 	.fops		= &ar7_wdt_fops,
 };
 
-static int __devinit ar7_wdt_probe(struct platform_device *pdev)
+static int ar7_wdt_probe(struct platform_device *pdev)
 {
 	int rc;
 
@@ -314,7 +314,7 @@ out:
 	return rc;
 }
 
-static int __devexit ar7_wdt_remove(struct platform_device *pdev)
+static int ar7_wdt_remove(struct platform_device *pdev)
 {
 	misc_deregister(&ar7_wdt_miscdev);
 	clk_put(vbus_clk);
@@ -330,7 +330,7 @@ static void ar7_wdt_shutdown(struct platform_device *pdev)
 
 static struct platform_driver ar7_wdt_driver = {
 	.probe = ar7_wdt_probe,
-	.remove = __devexit_p(ar7_wdt_remove),
+	.remove = ar7_wdt_remove,
 	.shutdown = ar7_wdt_shutdown,
 	.driver = {
 		.owner = THIS_MODULE,
diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c
index 7ef99a1..89831ed 100644
--- a/drivers/watchdog/at91rm9200_wdt.c
+++ b/drivers/watchdog/at91rm9200_wdt.c
@@ -199,7 +199,7 @@ static struct miscdevice at91wdt_miscdev = {
 	.fops		= &at91wdt_fops,
 };
 
-static int __devinit at91wdt_probe(struct platform_device *pdev)
+static int at91wdt_probe(struct platform_device *pdev)
 {
 	int res;
 
@@ -216,7 +216,7 @@ static int __devinit at91wdt_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit at91wdt_remove(struct platform_device *pdev)
+static int at91wdt_remove(struct platform_device *pdev)
 {
 	int res;
 
@@ -254,7 +254,7 @@ static int at91wdt_resume(struct platform_device *pdev)
 
 static struct platform_driver at91wdt_driver = {
 	.probe		= at91wdt_probe,
-	.remove		= __devexit_p(at91wdt_remove),
+	.remove		= at91wdt_remove,
 	.shutdown	= at91wdt_shutdown,
 	.suspend	= at91wdt_suspend,
 	.resume		= at91wdt_resume,
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
index 05e1be8..dc42e44 100644
--- a/drivers/watchdog/at91sam9_wdt.c
+++ b/drivers/watchdog/at91sam9_wdt.c
@@ -32,6 +32,7 @@
 #include <linux/timer.h>
 #include <linux/bitops.h>
 #include <linux/uaccess.h>
+#include <linux/of.h>
 
 #include "at91sam9_wdt.h"
 
@@ -302,11 +303,21 @@ static int __exit at91wdt_remove(struct platform_device *pdev)
 	return res;
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id at91_wdt_dt_ids[] __initconst = {
+	{ .compatible = "atmel,at91sam9260-wdt" },
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, at91_wdt_dt_ids);
+#endif
+
 static struct platform_driver at91wdt_driver = {
 	.remove		= __exit_p(at91wdt_remove),
 	.driver		= {
 		.name	= "at91_wdt",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(at91_wdt_dt_ids),
 	},
 };
 
diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c
index 1f9371f..7c8ede7 100644
--- a/drivers/watchdog/ath79_wdt.c
+++ b/drivers/watchdog/ath79_wdt.c
@@ -224,7 +224,7 @@ static struct miscdevice ath79_wdt_miscdev = {
 	.fops = &ath79_wdt_fops,
 };
 
-static int __devinit ath79_wdt_probe(struct platform_device *pdev)
+static int ath79_wdt_probe(struct platform_device *pdev)
 {
 	u32 ctrl;
 	int err;
@@ -270,7 +270,7 @@ err_clk_put:
 	return err;
 }
 
-static int __devexit ath79_wdt_remove(struct platform_device *pdev)
+static int ath79_wdt_remove(struct platform_device *pdev)
 {
 	misc_deregister(&ath79_wdt_miscdev);
 	clk_disable(wdt_clk);
@@ -284,7 +284,7 @@ static void ath97_wdt_shutdown(struct platform_device *pdev)
 }
 
 static struct platform_driver ath79_wdt_driver = {
-	.remove		= __devexit_p(ath79_wdt_remove),
+	.remove		= ath79_wdt_remove,
 	.shutdown	= ath97_wdt_shutdown,
 	.driver		= {
 		.name	= DRIVER_NAME,
diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
index 551880b..b2b80d4 100644
--- a/drivers/watchdog/bcm63xx_wdt.c
+++ b/drivers/watchdog/bcm63xx_wdt.c
@@ -236,7 +236,7 @@ static struct miscdevice bcm63xx_wdt_miscdev = {
 };
 
 
-static int __devinit bcm63xx_wdt_probe(struct platform_device *pdev)
+static int bcm63xx_wdt_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct resource *r;
@@ -286,7 +286,7 @@ unmap:
 	return ret;
 }
 
-static int __devexit bcm63xx_wdt_remove(struct platform_device *pdev)
+static int bcm63xx_wdt_remove(struct platform_device *pdev)
 {
 	if (!nowayout)
 		bcm63xx_wdt_pause();
@@ -304,7 +304,7 @@ static void bcm63xx_wdt_shutdown(struct platform_device *pdev)
 
 static struct platform_driver bcm63xx_wdt_driver = {
 	.probe	= bcm63xx_wdt_probe,
-	.remove = __devexit_p(bcm63xx_wdt_remove),
+	.remove = bcm63xx_wdt_remove,
 	.shutdown = bcm63xx_wdt_shutdown,
 	.driver = {
 		.owner = THIS_MODULE,
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
index 38bc383..5d36d6f 100644
--- a/drivers/watchdog/bfin_wdt.c
+++ b/drivers/watchdog/bfin_wdt.c
@@ -356,7 +356,7 @@ static const struct watchdog_info bfin_wdt_info = {
  *	Registers the misc device.  Actual device
  *	initialization is handled by bfin_wdt_open().
  */
-static int __devinit bfin_wdt_probe(struct platform_device *pdev)
+static int bfin_wdt_probe(struct platform_device *pdev)
 {
 	int ret;
 
@@ -379,7 +379,7 @@ static int __devinit bfin_wdt_probe(struct platform_device *pdev)
  *	Unregisters the misc device.  Actual device
  *	deinitialization is handled by bfin_wdt_close().
  */
-static int __devexit bfin_wdt_remove(struct platform_device *pdev)
+static int bfin_wdt_remove(struct platform_device *pdev)
 {
 	misc_deregister(&bfin_wdt_miscdev);
 	return 0;
@@ -401,7 +401,7 @@ static struct platform_device *bfin_wdt_device;
 
 static struct platform_driver bfin_wdt_driver = {
 	.probe     = bfin_wdt_probe,
-	.remove    = __devexit_p(bfin_wdt_remove),
+	.remove    = bfin_wdt_remove,
 	.shutdown  = bfin_wdt_shutdown,
 	.suspend   = bfin_wdt_suspend,
 	.resume    = bfin_wdt_resume,
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
index 5b06d31..c0bc92d 100644
--- a/drivers/watchdog/booke_wdt.c
+++ b/drivers/watchdog/booke_wdt.c
@@ -212,7 +212,7 @@ static long booke_wdt_ioctl(struct file *file,
 	return 0;
 }
 
-/* wdt_is_active stores wether or not the /dev/watchdog device is opened */
+/* wdt_is_active stores whether or not the /dev/watchdog device is opened */
 static unsigned long wdt_is_active;
 
 static int booke_wdt_open(struct inode *inode, struct file *file)
diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c
index 7e88839..cd87758 100644
--- a/drivers/watchdog/cpu5wdt.c
+++ b/drivers/watchdog/cpu5wdt.c
@@ -215,7 +215,7 @@ static struct miscdevice cpu5wdt_misc = {
 
 /* init/exit function */
 
-static int __devinit cpu5wdt_init(void)
+static int cpu5wdt_init(void)
 {
 	unsigned int val;
 	int err;
@@ -256,12 +256,12 @@ no_port:
 	return err;
 }
 
-static int __devinit cpu5wdt_init_module(void)
+static int cpu5wdt_init_module(void)
 {
 	return cpu5wdt_init();
 }
 
-static void __devexit cpu5wdt_exit(void)
+static void cpu5wdt_exit(void)
 {
 	if (cpu5wdt_device.queue) {
 		cpu5wdt_device.queue = 0;
@@ -274,7 +274,7 @@ static void __devexit cpu5wdt_exit(void)
 
 }
 
-static void __devexit cpu5wdt_exit_module(void)
+static void cpu5wdt_exit_module(void)
 {
 	cpu5wdt_exit();
 }
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
index 95b1b95..11d55ce 100644
--- a/drivers/watchdog/cpwd.c
+++ b/drivers/watchdog/cpwd.c
@@ -528,7 +528,7 @@ static const struct file_operations cpwd_fops = {
 	.llseek =		no_llseek,
 };
 
-static int __devinit cpwd_probe(struct platform_device *op)
+static int cpwd_probe(struct platform_device *op)
 {
 	struct device_node *options;
 	const char *str_prop;
@@ -640,7 +640,7 @@ out_free:
 	goto out;
 }
 
-static int __devexit cpwd_remove(struct platform_device *op)
+static int cpwd_remove(struct platform_device *op)
 {
 	struct cpwd *p = dev_get_drvdata(&op->dev);
 	int i;
@@ -684,7 +684,7 @@ static struct platform_driver cpwd_driver = {
 		.of_match_table = cpwd_match,
 	},
 	.probe		= cpwd_probe,
-	.remove		= __devexit_p(cpwd_remove),
+	.remove		= cpwd_remove,
 };
 
 module_platform_driver(cpwd_driver);
diff --git a/drivers/watchdog/da9052_wdt.c b/drivers/watchdog/da9052_wdt.c
index f7abbae..8be70d8 100644
--- a/drivers/watchdog/da9052_wdt.c
+++ b/drivers/watchdog/da9052_wdt.c
@@ -179,7 +179,7 @@ static const struct watchdog_ops da9052_wdt_ops = {
 };
 
 
-static int __devinit da9052_wdt_probe(struct platform_device *pdev)
+static int da9052_wdt_probe(struct platform_device *pdev)
 {
 	struct da9052 *da9052 = dev_get_drvdata(pdev->dev.parent);
 	struct da9052_wdt_data *driver_data;
@@ -224,7 +224,7 @@ err:
 	return ret;
 }
 
-static int __devexit da9052_wdt_remove(struct platform_device *pdev)
+static int da9052_wdt_remove(struct platform_device *pdev)
 {
 	struct da9052_wdt_data *driver_data = dev_get_drvdata(&pdev->dev);
 
@@ -236,7 +236,7 @@ static int __devexit da9052_wdt_remove(struct platform_device *pdev)
 
 static struct platform_driver da9052_wdt_driver = {
 	.probe = da9052_wdt_probe,
-	.remove = __devexit_p(da9052_wdt_remove),
+	.remove = da9052_wdt_remove,
 	.driver = {
 		.name	= "da9052-watchdog",
 	},
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
index c8c5c80..6000aea 100644
--- a/drivers/watchdog/davinci_wdt.c
+++ b/drivers/watchdog/davinci_wdt.c
@@ -199,7 +199,7 @@ static struct miscdevice davinci_wdt_miscdev = {
 	.fops = &davinci_wdt_fops,
 };
 
-static int __devinit davinci_wdt_probe(struct platform_device *pdev)
+static int davinci_wdt_probe(struct platform_device *pdev)
 {
 	int ret = 0, size;
 	struct device *dev = &pdev->dev;
@@ -208,7 +208,7 @@ static int __devinit davinci_wdt_probe(struct platform_device *pdev)
 	if (WARN_ON(IS_ERR(wdt_clk)))
 		return PTR_ERR(wdt_clk);
 
-	clk_enable(wdt_clk);
+	clk_prepare_enable(wdt_clk);
 
 	if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
 		heartbeat = DEFAULT_HEARTBEAT;
@@ -248,7 +248,7 @@ static int __devinit davinci_wdt_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit davinci_wdt_remove(struct platform_device *pdev)
+static int davinci_wdt_remove(struct platform_device *pdev)
 {
 	misc_deregister(&davinci_wdt_miscdev);
 	if (wdt_mem) {
@@ -256,7 +256,7 @@ static int __devexit davinci_wdt_remove(struct platform_device *pdev)
 		wdt_mem = NULL;
 	}
 
-	clk_disable(wdt_clk);
+	clk_disable_unprepare(wdt_clk);
 	clk_put(wdt_clk);
 
 	return 0;
@@ -268,7 +268,7 @@ static struct platform_driver platform_wdt_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe = davinci_wdt_probe,
-	.remove = __devexit_p(davinci_wdt_remove),
+	.remove = davinci_wdt_remove,
 };
 
 module_platform_driver(platform_wdt_driver);
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
index 06de121..a0eba3c 100644
--- a/drivers/watchdog/dw_wdt.c
+++ b/drivers/watchdog/dw_wdt.c
@@ -293,7 +293,7 @@ static struct miscdevice dw_wdt_miscdev = {
 	.minor		= WATCHDOG_MINOR,
 };
 
-static int __devinit dw_wdt_drv_probe(struct platform_device *pdev)
+static int dw_wdt_drv_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -333,7 +333,7 @@ out_put_clk:
 	return ret;
 }
 
-static int __devexit dw_wdt_drv_remove(struct platform_device *pdev)
+static int dw_wdt_drv_remove(struct platform_device *pdev)
 {
 	misc_deregister(&dw_wdt_miscdev);
 
@@ -345,7 +345,7 @@ static int __devexit dw_wdt_drv_remove(struct platform_device *pdev)
 
 static struct platform_driver dw_wdt_driver = {
 	.probe		= dw_wdt_drv_probe,
-	.remove		= __devexit_p(dw_wdt_drv_remove),
+	.remove		= dw_wdt_drv_remove,
 	.driver		= {
 		.name	= "dw_wdt",
 		.owner	= THIS_MODULE,
diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c
index 7705003..e057484 100644
--- a/drivers/watchdog/ep93xx_wdt.c
+++ b/drivers/watchdog/ep93xx_wdt.c
@@ -112,7 +112,7 @@ static struct watchdog_device ep93xx_wdt_wdd = {
 	.ops		= &ep93xx_wdt_ops,
 };
 
-static int __devinit ep93xx_wdt_probe(struct platform_device *pdev)
+static int ep93xx_wdt_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	unsigned long val;
@@ -156,7 +156,7 @@ static int __devinit ep93xx_wdt_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit ep93xx_wdt_remove(struct platform_device *pdev)
+static int ep93xx_wdt_remove(struct platform_device *pdev)
 {
 	watchdog_unregister_device(&ep93xx_wdt_wdd);
 	return 0;
@@ -168,7 +168,7 @@ static struct platform_driver ep93xx_wdt_driver = {
 		.name	= "ep93xx-wdt",
 	},
 	.probe		= ep93xx_wdt_probe,
-	.remove		= __devexit_p(ep93xx_wdt_remove),
+	.remove		= ep93xx_wdt_remove,
 };
 
 module_platform_driver(ep93xx_wdt_driver);
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
index 17f4cae..b9c5b58 100644
--- a/drivers/watchdog/gef_wdt.c
+++ b/drivers/watchdog/gef_wdt.c
@@ -262,7 +262,7 @@ static struct miscdevice gef_wdt_miscdev = {
 };
 
 
-static int __devinit gef_wdt_probe(struct platform_device *dev)
+static int gef_wdt_probe(struct platform_device *dev)
 {
 	int timeout = 10;
 	u32 freq;
@@ -285,7 +285,7 @@ static int __devinit gef_wdt_probe(struct platform_device *dev)
 	return misc_register(&gef_wdt_miscdev);
 }
 
-static int __devexit gef_wdt_remove(struct platform_device *dev)
+static int gef_wdt_remove(struct platform_device *dev)
 {
 	misc_deregister(&gef_wdt_miscdev);
 
diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c
index dc563b6..fcd599d 100644
--- a/drivers/watchdog/geodewdt.c
+++ b/drivers/watchdog/geodewdt.c
@@ -215,7 +215,7 @@ static struct miscdevice geodewdt_miscdev = {
 	.fops = &geodewdt_fops,
 };
 
-static int __devinit geodewdt_probe(struct platform_device *dev)
+static int geodewdt_probe(struct platform_device *dev)
 {
 	int ret;
 
@@ -243,7 +243,7 @@ static int __devinit geodewdt_probe(struct platform_device *dev)
 	return ret;
 }
 
-static int __devexit geodewdt_remove(struct platform_device *dev)
+static int geodewdt_remove(struct platform_device *dev)
 {
 	misc_deregister(&geodewdt_miscdev);
 	return 0;
@@ -256,7 +256,7 @@ static void geodewdt_shutdown(struct platform_device *dev)
 
 static struct platform_driver geodewdt_driver = {
 	.probe		= geodewdt_probe,
-	.remove		= __devexit_p(geodewdt_remove),
+	.remove		= geodewdt_remove,
 	.shutdown	= geodewdt_shutdown,
 	.driver		= {
 		.owner	= THIS_MODULE,
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index ae60406..8717255 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -212,7 +212,7 @@ asm(".text                          \n\t"
  *	0        :  SUCCESS
  *	<0       :  FAILURE
  */
-static int __devinit cru_detect(unsigned long map_entry,
+static int cru_detect(unsigned long map_entry,
 	unsigned long map_offset)
 {
 	void *bios32_map;
@@ -268,7 +268,7 @@ static int __devinit cru_detect(unsigned long map_entry,
 /*
  *	bios_checksum
  */
-static int __devinit bios_checksum(const char __iomem *ptr, int len)
+static int bios_checksum(const char __iomem *ptr, int len)
 {
 	char sum = 0;
 	int i;
@@ -293,7 +293,7 @@ static int __devinit bios_checksum(const char __iomem *ptr, int len)
  *	0        :  SUCCESS
  *	<0       :  FAILURE
  */
-static int __devinit bios32_present(const char __iomem *p)
+static int bios32_present(const char __iomem *p)
 {
 	struct bios32_service_dir *bios_32_ptr;
 	int length;
@@ -323,7 +323,7 @@ static int __devinit bios32_present(const char __iomem *p)
 	return -ENODEV;
 }
 
-static int __devinit detect_cru_service(void)
+static int detect_cru_service(void)
 {
 	char __iomem *p, *q;
 	int rc = -1;
@@ -395,7 +395,7 @@ asm(".text                      \n\t"
  *	This function checks whether or not a SMBIOS/DMI record is
  *	the 64bit CRU info or not
  */
-static void __devinit dmi_find_cru(const struct dmi_header *dm, void *dummy)
+static void dmi_find_cru(const struct dmi_header *dm, void *dummy)
 {
 	struct smbios_cru64_info *smbios_cru64_ptr;
 	unsigned long cru_physical_address;
@@ -414,7 +414,7 @@ static void __devinit dmi_find_cru(const struct dmi_header *dm, void *dummy)
 	}
 }
 
-static int __devinit detect_cru_service(void)
+static int detect_cru_service(void)
 {
 	cru_rom_addr = NULL;
 
@@ -647,7 +647,7 @@ static struct miscdevice hpwdt_miscdev = {
 
 #ifdef CONFIG_HPWDT_NMI_DECODING
 #ifdef CONFIG_X86_LOCAL_APIC
-static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
+static void hpwdt_check_nmi_decoding(struct pci_dev *dev)
 {
 	/*
 	 * If nmi_watchdog is turned off then we can turn on
@@ -656,7 +656,7 @@ static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
 	hpwdt_nmi_decoding = 1;
 }
 #else
-static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
+static void hpwdt_check_nmi_decoding(struct pci_dev *dev)
 {
 	dev_warn(&dev->dev, "NMI decoding is disabled. "
 		"Your kernel does not support a NMI Watchdog.\n");
@@ -671,7 +671,7 @@ static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
  *	This check is independent of architecture and needs to be made for
  *	any ProLiant system.
  */
-static void __devinit dmi_find_icru(const struct dmi_header *dm, void *dummy)
+static void dmi_find_icru(const struct dmi_header *dm, void *dummy)
 {
 	struct smbios_proliant_info *smbios_proliant_ptr;
 
@@ -682,7 +682,7 @@ static void __devinit dmi_find_icru(const struct dmi_header *dm, void *dummy)
 	}
 }
 
-static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
+static int hpwdt_init_nmi_decoding(struct pci_dev *dev)
 {
 	int retval;
 
@@ -762,11 +762,11 @@ static void hpwdt_exit_nmi_decoding(void)
 		iounmap(cru_rom_addr);
 }
 #else /* !CONFIG_HPWDT_NMI_DECODING */
-static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
+static void hpwdt_check_nmi_decoding(struct pci_dev *dev)
 {
 }
 
-static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
+static int hpwdt_init_nmi_decoding(struct pci_dev *dev)
 {
 	return 0;
 }
@@ -776,7 +776,7 @@ static void hpwdt_exit_nmi_decoding(void)
 }
 #endif /* CONFIG_HPWDT_NMI_DECODING */
 
-static int __devinit hpwdt_init_one(struct pci_dev *dev,
+static int hpwdt_init_one(struct pci_dev *dev,
 					const struct pci_device_id *ent)
 {
 	int retval;
@@ -848,7 +848,7 @@ error_pci_iomap:
 	return retval;
 }
 
-static void __devexit hpwdt_exit(struct pci_dev *dev)
+static void hpwdt_exit(struct pci_dev *dev)
 {
 	if (!nowayout)
 		hpwdt_stop();
@@ -863,7 +863,7 @@ static struct pci_driver hpwdt_driver = {
 	.name = "hpwdt",
 	.id_table = hpwdt_devices,
 	.probe = hpwdt_init_one,
-	.remove = __devexit_p(hpwdt_exit),
+	.remove = hpwdt_exit,
 };
 
 MODULE_AUTHOR("Tom Mingarelli");
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
index 276877d..2b2ea13 100644
--- a/drivers/watchdog/i6300esb.c
+++ b/drivers/watchdog/i6300esb.c
@@ -344,7 +344,7 @@ MODULE_DEVICE_TABLE(pci, esb_pci_tbl);
  *      Init & exit routines
  */
 
-static unsigned char __devinit esb_getdevice(struct pci_dev *pdev)
+static unsigned char esb_getdevice(struct pci_dev *pdev)
 {
 	if (pci_enable_device(pdev)) {
 		pr_err("failed to enable device\n");
@@ -375,7 +375,7 @@ err_devput:
 	return 0;
 }
 
-static void __devinit esb_initdevice(void)
+static void esb_initdevice(void)
 {
 	u8 val1;
 	u16 val2;
@@ -416,7 +416,7 @@ static void __devinit esb_initdevice(void)
 	esb_timer_set_heartbeat(heartbeat);
 }
 
-static int __devinit esb_probe(struct pci_dev *pdev,
+static int esb_probe(struct pci_dev *pdev,
 		const struct pci_device_id *ent)
 {
 	int ret;
@@ -465,7 +465,7 @@ err_unmap:
 	return ret;
 }
 
-static void __devexit esb_remove(struct pci_dev *pdev)
+static void esb_remove(struct pci_dev *pdev)
 {
 	/* Stop the timer before we leave */
 	if (!nowayout)
@@ -488,7 +488,7 @@ static struct pci_driver esb_driver = {
 	.name		= ESB_MODULE_NAME,
 	.id_table	= esb_pci_tbl,
 	.probe          = esb_probe,
-	.remove         = __devexit_p(esb_remove),
+	.remove         = esb_remove,
 	.shutdown       = esb_shutdown,
 };
 
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 545d387..6130321 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -364,7 +364,7 @@ static struct watchdog_device iTCO_wdt_watchdog_dev = {
  *	Init & exit routines
  */
 
-static void __devexit iTCO_wdt_cleanup(void)
+static void iTCO_wdt_cleanup(void)
 {
 	/* Stop the timer before we leave */
 	if (!nowayout)
@@ -390,7 +390,7 @@ static void __devexit iTCO_wdt_cleanup(void)
 	iTCO_wdt_private.gcs = NULL;
 }
 
-static int __devinit iTCO_wdt_probe(struct platform_device *dev)
+static int iTCO_wdt_probe(struct platform_device *dev)
 {
 	int ret = -ENODEV;
 	unsigned long val32;
@@ -533,7 +533,7 @@ out:
 	return ret;
 }
 
-static int __devexit iTCO_wdt_remove(struct platform_device *dev)
+static int iTCO_wdt_remove(struct platform_device *dev)
 {
 	if (iTCO_wdt_private.tco_res || iTCO_wdt_private.smi_res)
 		iTCO_wdt_cleanup();
@@ -548,7 +548,7 @@ static void iTCO_wdt_shutdown(struct platform_device *dev)
 
 static struct platform_driver iTCO_wdt_driver = {
 	.probe          = iTCO_wdt_probe,
-	.remove         = __devexit_p(iTCO_wdt_remove),
+	.remove         = iTCO_wdt_remove,
 	.shutdown       = iTCO_wdt_shutdown,
 	.driver         = {
 		.owner  = THIS_MODULE,
diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c
index 184c0bf..eb6b5cc 100644
--- a/drivers/watchdog/ib700wdt.c
+++ b/drivers/watchdog/ib700wdt.c
@@ -277,7 +277,7 @@ static struct miscdevice ibwdt_miscdev = {
  *	Init & exit routines
  */
 
-static int __devinit ibwdt_probe(struct platform_device *dev)
+static int ibwdt_probe(struct platform_device *dev)
 {
 	int res;
 
@@ -319,7 +319,7 @@ out_nostopreg:
 	return res;
 }
 
-static int __devexit ibwdt_remove(struct platform_device *dev)
+static int ibwdt_remove(struct platform_device *dev)
 {
 	misc_deregister(&ibwdt_miscdev);
 	release_region(WDT_START, 1);
@@ -337,7 +337,7 @@ static void ibwdt_shutdown(struct platform_device *dev)
 
 static struct platform_driver ibwdt_driver = {
 	.probe		= ibwdt_probe,
-	.remove		= __devexit_p(ibwdt_remove),
+	.remove		= ibwdt_remove,
 	.shutdown	= ibwdt_shutdown,
 	.driver		= {
 		.owner	= THIS_MODULE,
diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c
index 8f541b9..e24ef6a 100644
--- a/drivers/watchdog/ie6xx_wdt.c
+++ b/drivers/watchdog/ie6xx_wdt.c
@@ -225,7 +225,7 @@ static const struct file_operations ie6xx_wdt_dbg_operations = {
 	.release	= single_release,
 };
 
-static void __devinit ie6xx_wdt_debugfs_init(void)
+static void ie6xx_wdt_debugfs_init(void)
 {
 	/* /sys/kernel/debug/ie6xx_wdt */
 	ie6xx_wdt_data.debugfs = debugfs_create_file("ie6xx_wdt",
@@ -238,7 +238,7 @@ static void ie6xx_wdt_debugfs_exit(void)
 }
 
 #else
-static void __devinit ie6xx_wdt_debugfs_init(void)
+static void ie6xx_wdt_debugfs_init(void)
 {
 }
 
@@ -247,7 +247,7 @@ static void ie6xx_wdt_debugfs_exit(void)
 }
 #endif
 
-static int __devinit ie6xx_wdt_probe(struct platform_device *pdev)
+static int ie6xx_wdt_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	u8 wdtlr;
@@ -295,7 +295,7 @@ misc_register_error:
 	return ret;
 }
 
-static int __devexit ie6xx_wdt_remove(struct platform_device *pdev)
+static int ie6xx_wdt_remove(struct platform_device *pdev)
 {
 	struct resource *res;
 
@@ -311,7 +311,7 @@ static int __devexit ie6xx_wdt_remove(struct platform_device *pdev)
 
 static struct platform_driver ie6xx_wdt_driver = {
 	.probe		= ie6xx_wdt_probe,
-	.remove		= __devexit_p(ie6xx_wdt_remove),
+	.remove		= ie6xx_wdt_remove,
 	.driver		= {
 		.name	= DRIVER_NAME,
 		.owner	= THIS_MODULE,
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index bcfab2b..9a45d029 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -33,7 +33,6 @@
 #include <linux/uaccess.h>
 #include <linux/timer.h>
 #include <linux/jiffies.h>
-#include <mach/hardware.h>
 
 #define DRIVER_NAME "imx2-wdt"
 
diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c
index 978615e..a61408f 100644
--- a/drivers/watchdog/jz4740_wdt.c
+++ b/drivers/watchdog/jz4740_wdt.c
@@ -144,7 +144,7 @@ static const struct watchdog_ops jz4740_wdt_ops = {
 	.set_timeout = jz4740_wdt_set_timeout,
 };
 
-static int __devinit jz4740_wdt_probe(struct platform_device *pdev)
+static int jz4740_wdt_probe(struct platform_device *pdev)
 {
 	struct jz4740_wdt_drvdata *drvdata;
 	struct watchdog_device *jz4740_wdt;
@@ -197,7 +197,7 @@ err_out:
 	return ret;
 }
 
-static int __devexit jz4740_wdt_remove(struct platform_device *pdev)
+static int jz4740_wdt_remove(struct platform_device *pdev)
 {
 	struct jz4740_wdt_drvdata *drvdata = platform_get_drvdata(pdev);
 
@@ -210,7 +210,7 @@ static int __devexit jz4740_wdt_remove(struct platform_device *pdev)
 
 static struct platform_driver jz4740_wdt_driver = {
 	.probe = jz4740_wdt_probe,
-	.remove = __devexit_p(jz4740_wdt_remove),
+	.remove = jz4740_wdt_remove,
 	.driver = {
 		.name = "jz4740-wdt",
 		.owner	= THIS_MODULE,
diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c
index c1a4d3b..dce9ecf 100644
--- a/drivers/watchdog/ks8695_wdt.c
+++ b/drivers/watchdog/ks8695_wdt.c
@@ -235,7 +235,7 @@ static struct miscdevice ks8695wdt_miscdev = {
 	.fops		= &ks8695wdt_fops,
 };
 
-static int __devinit ks8695wdt_probe(struct platform_device *pdev)
+static int ks8695wdt_probe(struct platform_device *pdev)
 {
 	int res;
 
@@ -252,7 +252,7 @@ static int __devinit ks8695wdt_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit ks8695wdt_remove(struct platform_device *pdev)
+static int ks8695wdt_remove(struct platform_device *pdev)
 {
 	int res;
 
@@ -290,7 +290,7 @@ static int ks8695wdt_resume(struct platform_device *pdev)
 
 static struct platform_driver ks8695wdt_driver = {
 	.probe		= ks8695wdt_probe,
-	.remove		= __devexit_p(ks8695wdt_remove),
+	.remove		= ks8695wdt_remove,
 	.shutdown	= ks8695wdt_shutdown,
 	.suspend	= ks8695wdt_suspend,
 	.resume		= ks8695wdt_resume,
diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c
index 2e74c3a..79fe01b 100644
--- a/drivers/watchdog/lantiq_wdt.c
+++ b/drivers/watchdog/lantiq_wdt.c
@@ -186,7 +186,7 @@ static struct miscdevice ltq_wdt_miscdev = {
 	.fops	= &ltq_wdt_fops,
 };
 
-static int __devinit
+static int
 ltq_wdt_probe(struct platform_device *pdev)
 {
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -220,7 +220,7 @@ ltq_wdt_probe(struct platform_device *pdev)
 	return misc_register(&ltq_wdt_miscdev);
 }
 
-static int __devexit
+static int
 ltq_wdt_remove(struct platform_device *pdev)
 {
 	misc_deregister(&ltq_wdt_miscdev);
@@ -236,7 +236,7 @@ MODULE_DEVICE_TABLE(of, ltq_wdt_match);
 
 static struct platform_driver ltq_wdt_driver = {
 	.probe = ltq_wdt_probe,
-	.remove = __devexit_p(ltq_wdt_remove),
+	.remove = ltq_wdt_remove,
 	.driver = {
 		.name = "wdt",
 		.owner = THIS_MODULE,
diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c
index 8f4a74e..773c661 100644
--- a/drivers/watchdog/max63xx_wdt.c
+++ b/drivers/watchdog/max63xx_wdt.c
@@ -174,7 +174,7 @@ static struct watchdog_device max63xx_wdt_dev = {
 	.ops = &max63xx_wdt_ops,
 };
 
-static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
+static int max63xx_wdt_probe(struct platform_device *pdev)
 {
 	struct resource	*wdt_mem;
 	struct max63xx_timeout *table;
@@ -209,7 +209,7 @@ static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
 	return watchdog_register_device(&max63xx_wdt_dev);
 }
 
-static int __devexit max63xx_wdt_remove(struct platform_device *pdev)
+static int max63xx_wdt_remove(struct platform_device *pdev)
 {
 	watchdog_unregister_device(&max63xx_wdt_dev);
 	return 0;
@@ -228,7 +228,7 @@ MODULE_DEVICE_TABLE(platform, max63xx_id_table);
 
 static struct platform_driver max63xx_wdt_driver = {
 	.probe		= max63xx_wdt_probe,
-	.remove		= __devexit_p(max63xx_wdt_remove),
+	.remove		= max63xx_wdt_remove,
 	.id_table	= max63xx_id_table,
 	.driver		= {
 		.name	= "max63xx_wdt",
diff --git a/drivers/watchdog/mixcomwd.c b/drivers/watchdog/mixcomwd.c
index 37e4b52..97d62ee 100644
--- a/drivers/watchdog/mixcomwd.c
+++ b/drivers/watchdog/mixcomwd.c
@@ -73,7 +73,7 @@
 static struct {
 	int ioport;
 	int id;
-} mixcomwd_io_info[] __devinitdata = {
+} mixcomwd_io_info[] = {
 	/* The Mixcom cards */
 	{0x0d90, MIXCOM_ID},
 	{0x0e90, MIXCOM_ID},
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index e6a038a..da27520 100644
--- a/drivers/watchdog/mpc8xxx_wdt.c
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -188,7 +188,7 @@ static struct miscdevice mpc8xxx_wdt_miscdev = {
 };
 
 static const struct of_device_id mpc8xxx_wdt_match[];
-static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev)
+static int mpc8xxx_wdt_probe(struct platform_device *ofdev)
 {
 	int ret;
 	const struct of_device_id *match;
@@ -245,7 +245,7 @@ err_unmap:
 	return ret;
 }
 
-static int __devexit mpc8xxx_wdt_remove(struct platform_device *ofdev)
+static int mpc8xxx_wdt_remove(struct platform_device *ofdev)
 {
 	mpc8xxx_wdt_pr_warn("watchdog removed");
 	del_timer_sync(&wdt_timer);
@@ -281,7 +281,7 @@ MODULE_DEVICE_TABLE(of, mpc8xxx_wdt_match);
 
 static struct platform_driver mpc8xxx_wdt_driver = {
 	.probe		= mpc8xxx_wdt_probe,
-	.remove		= __devexit_p(mpc8xxx_wdt_remove),
+	.remove		= mpc8xxx_wdt_remove,
 	.driver = {
 		.name = "mpc8xxx_wdt",
 		.owner = THIS_MODULE,
diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c
index 7c741dc..a84eb55 100644
--- a/drivers/watchdog/mpcore_wdt.c
+++ b/drivers/watchdog/mpcore_wdt.c
@@ -327,7 +327,7 @@ static struct miscdevice mpcore_wdt_miscdev = {
 	.fops		= &mpcore_wdt_fops,
 };
 
-static int __devinit mpcore_wdt_probe(struct platform_device *pdev)
+static int mpcore_wdt_probe(struct platform_device *pdev)
 {
 	struct mpcore_wdt *wdt;
 	struct resource *res;
@@ -378,7 +378,7 @@ static int __devinit mpcore_wdt_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit mpcore_wdt_remove(struct platform_device *pdev)
+static int mpcore_wdt_remove(struct platform_device *pdev)
 {
 	platform_set_drvdata(pdev, NULL);
 
@@ -415,7 +415,7 @@ MODULE_ALIAS("platform:mpcore_wdt");
 
 static struct platform_driver mpcore_wdt_driver = {
 	.probe		= mpcore_wdt_probe,
-	.remove		= __devexit_p(mpcore_wdt_remove),
+	.remove		= mpcore_wdt_remove,
 	.suspend	= mpcore_wdt_suspend,
 	.resume		= mpcore_wdt_resume,
 	.shutdown	= mpcore_wdt_shutdown,
diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c
index c29e31d..14dab6f 100644
--- a/drivers/watchdog/mtx-1_wdt.c
+++ b/drivers/watchdog/mtx-1_wdt.c
@@ -204,7 +204,7 @@ static struct miscdevice mtx1_wdt_misc = {
 };
 
 
-static int __devinit mtx1_wdt_probe(struct platform_device *pdev)
+static int mtx1_wdt_probe(struct platform_device *pdev)
 {
 	int ret;
 
@@ -233,7 +233,7 @@ static int __devinit mtx1_wdt_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit mtx1_wdt_remove(struct platform_device *pdev)
+static int mtx1_wdt_remove(struct platform_device *pdev)
 {
 	/* FIXME: do we need to lock this test ? */
 	if (mtx1_wdt_device.queue) {
@@ -248,7 +248,7 @@ static int __devexit mtx1_wdt_remove(struct platform_device *pdev)
 
 static struct platform_driver mtx1_wdt_driver = {
 	.probe = mtx1_wdt_probe,
-	.remove = __devexit_p(mtx1_wdt_remove),
+	.remove = mtx1_wdt_remove,
 	.driver.name = "mtx1-wdt",
 	.driver.owner = THIS_MODULE,
 };
diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c
index c53d025..c7fb878 100644
--- a/drivers/watchdog/mv64x60_wdt.c
+++ b/drivers/watchdog/mv64x60_wdt.c
@@ -253,7 +253,7 @@ static struct miscdevice mv64x60_wdt_miscdev = {
 	.fops = &mv64x60_wdt_fops,
 };
 
-static int __devinit mv64x60_wdt_probe(struct platform_device *dev)
+static int mv64x60_wdt_probe(struct platform_device *dev)
 {
 	struct mv64x60_wdt_pdata *pdata = dev->dev.platform_data;
 	struct resource *r;
@@ -287,7 +287,7 @@ static int __devinit mv64x60_wdt_probe(struct platform_device *dev)
 	return misc_register(&mv64x60_wdt_miscdev);
 }
 
-static int __devexit mv64x60_wdt_remove(struct platform_device *dev)
+static int mv64x60_wdt_remove(struct platform_device *dev)
 {
 	misc_deregister(&mv64x60_wdt_miscdev);
 
@@ -300,7 +300,7 @@ static int __devexit mv64x60_wdt_remove(struct platform_device *dev)
 
 static struct platform_driver mv64x60_wdt_driver = {
 	.probe = mv64x60_wdt_probe,
-	.remove = __devexit_p(mv64x60_wdt_remove),
+	.remove = mv64x60_wdt_remove,
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = MV64x60_WDT_NAME,
diff --git a/drivers/watchdog/nuc900_wdt.c b/drivers/watchdog/nuc900_wdt.c
index ea4c744..04c45a1 100644
--- a/drivers/watchdog/nuc900_wdt.c
+++ b/drivers/watchdog/nuc900_wdt.c
@@ -242,7 +242,7 @@ static struct miscdevice nuc900wdt_miscdev = {
 	.fops		= &nuc900wdt_fops,
 };
 
-static int __devinit nuc900wdt_probe(struct platform_device *pdev)
+static int nuc900wdt_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 
@@ -309,7 +309,7 @@ err_get:
 	return ret;
 }
 
-static int __devexit nuc900wdt_remove(struct platform_device *pdev)
+static int nuc900wdt_remove(struct platform_device *pdev)
 {
 	misc_deregister(&nuc900wdt_miscdev);
 
@@ -328,7 +328,7 @@ static int __devexit nuc900wdt_remove(struct platform_device *pdev)
 
 static struct platform_driver nuc900wdt_driver = {
 	.probe		= nuc900wdt_probe,
-	.remove		= __devexit_p(nuc900wdt_remove),
+	.remove		= nuc900wdt_remove,
 	.driver		= {
 		.name	= "nuc900-wdt",
 		.owner	= THIS_MODULE,
diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c
index 6bbb9ef..59cf19e 100644
--- a/drivers/watchdog/nv_tco.c
+++ b/drivers/watchdog/nv_tco.c
@@ -302,7 +302,7 @@ MODULE_DEVICE_TABLE(pci, tco_pci_tbl);
  *	Init & exit routines
  */
 
-static unsigned char __devinit nv_tco_getdevice(void)
+static unsigned char nv_tco_getdevice(void)
 {
 	struct pci_dev *dev = NULL;
 	u32 val;
@@ -376,7 +376,7 @@ out:
 	return 0;
 }
 
-static int __devinit nv_tco_init(struct platform_device *dev)
+static int nv_tco_init(struct platform_device *dev)
 {
 	int ret;
 
@@ -423,7 +423,7 @@ unreg_region:
 	return ret;
 }
 
-static void __devexit nv_tco_cleanup(void)
+static void nv_tco_cleanup(void)
 {
 	u32 val;
 
@@ -445,7 +445,7 @@ static void __devexit nv_tco_cleanup(void)
 	release_region(tcobase, 0x10);
 }
 
-static int __devexit nv_tco_remove(struct platform_device *dev)
+static int nv_tco_remove(struct platform_device *dev)
 {
 	if (tcobase)
 		nv_tco_cleanup();
@@ -468,7 +468,7 @@ static void nv_tco_shutdown(struct platform_device *dev)
 
 static struct platform_driver nv_tco_driver = {
 	.probe		= nv_tco_init,
-	.remove		= __devexit_p(nv_tco_remove),
+	.remove		= nv_tco_remove,
 	.shutdown	= nv_tco_shutdown,
 	.driver		= {
 		.owner	= THIS_MODULE,
diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
index 294fb4e..2761ddb 100644
--- a/drivers/watchdog/of_xilinx_wdt.c
+++ b/drivers/watchdog/of_xilinx_wdt.c
@@ -289,7 +289,7 @@ static struct miscdevice xwdt_miscdev = {
 	.fops       = &xwdt_fops,
 };
 
-static int __devinit xwdt_probe(struct platform_device *pdev)
+static int xwdt_probe(struct platform_device *pdev)
 {
 	int rc;
 	u32 *tmptr;
@@ -383,7 +383,7 @@ err_out:
 	return rc;
 }
 
-static int __devexit xwdt_remove(struct platform_device *dev)
+static int xwdt_remove(struct platform_device *dev)
 {
 	misc_deregister(&xwdt_miscdev);
 	iounmap(xdev.base);
@@ -393,7 +393,7 @@ static int __devexit xwdt_remove(struct platform_device *dev)
 }
 
 /* Match table for of_platform binding */
-static struct of_device_id __devinitdata xwdt_of_match[] = {
+static struct of_device_id xwdt_of_match[] = {
 	{ .compatible = "xlnx,xps-timebase-wdt-1.01.a", },
 	{},
 };
@@ -401,7 +401,7 @@ MODULE_DEVICE_TABLE(of, xwdt_of_match);
 
 static struct platform_driver xwdt_driver = {
 	.probe       = xwdt_probe,
-	.remove      = __devexit_p(xwdt_remove),
+	.remove      = xwdt_remove,
 	.driver = {
 		.owner = THIS_MODULE,
 		.name  = WATCHDOG_NAME,
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index f5db18db..43cc1a1 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -46,8 +46,8 @@
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <mach/hardware.h>
-#include <plat/cpu.h>
-#include <plat/prcm.h>
+
+#include <linux/platform_data/omap-wd-timer.h>
 
 #include "omap_wdt.h"
 
@@ -202,8 +202,10 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data,
 static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
 						unsigned long arg)
 {
+	struct omap_wd_timer_platform_data *pdata;
 	struct omap_wdt_dev *wdev;
-	int new_margin;
+	u32 rs;
+	int new_margin, bs;
 	static const struct watchdog_info ident = {
 		.identity = "OMAP Watchdog",
 		.options = WDIOF_SETTIMEOUT,
@@ -211,6 +213,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
 	};
 
 	wdev = file->private_data;
+	pdata = wdev->dev->platform_data;
 
 	switch (cmd) {
 	case WDIOC_GETSUPPORT:
@@ -219,17 +222,12 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
 	case WDIOC_GETSTATUS:
 		return put_user(0, (int __user *)arg);
 	case WDIOC_GETBOOTSTATUS:
-#ifdef CONFIG_ARCH_OMAP1
-		if (cpu_is_omap16xx())
-			return put_user(__raw_readw(ARM_SYSST),
-					(int __user *)arg);
-#endif
-#ifdef CONFIG_ARCH_OMAP2PLUS
-		if (cpu_is_omap24xx())
-			return put_user(omap_prcm_get_reset_sources(),
-					(int __user *)arg);
-#endif
-		return put_user(0, (int __user *)arg);
+		if (!pdata || !pdata->read_reset_sources)
+			return put_user(0, (int __user *)arg);
+		rs = pdata->read_reset_sources();
+		bs = (rs & (1 << OMAP_MPU_WD_RST_SRC_ID_SHIFT)) ?
+			WDIOF_CARDRESET : 0;
+		return put_user(bs, (int __user *)arg);
 	case WDIOC_KEEPALIVE:
 		spin_lock(&wdt_lock);
 		omap_wdt_ping(wdev);
@@ -264,7 +262,7 @@ static const struct file_operations omap_wdt_fops = {
 	.llseek = no_llseek,
 };
 
-static int __devinit omap_wdt_probe(struct platform_device *pdev)
+static int omap_wdt_probe(struct platform_device *pdev)
 {
 	struct resource *res, *mem;
 	struct omap_wdt_dev *wdev;
@@ -359,7 +357,7 @@ static void omap_wdt_shutdown(struct platform_device *pdev)
 	}
 }
 
-static int __devexit omap_wdt_remove(struct platform_device *pdev)
+static int omap_wdt_remove(struct platform_device *pdev)
 {
 	struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -426,7 +424,7 @@ MODULE_DEVICE_TABLE(of, omap_wdt_of_match);
 
 static struct platform_driver omap_wdt_driver = {
 	.probe		= omap_wdt_probe,
-	.remove		= __devexit_p(omap_wdt_remove),
+	.remove		= omap_wdt_remove,
 	.shutdown	= omap_wdt_shutdown,
 	.suspend	= omap_wdt_suspend,
 	.resume		= omap_wdt_resume,
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index c20f96b..0478b00 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -142,7 +142,7 @@ static struct watchdog_device orion_wdt = {
 	.ops = &orion_wdt_ops,
 };
 
-static int __devinit orion_wdt_probe(struct platform_device *pdev)
+static int orion_wdt_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	int ret;
@@ -181,7 +181,7 @@ static int __devinit orion_wdt_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit orion_wdt_remove(struct platform_device *pdev)
+static int orion_wdt_remove(struct platform_device *pdev)
 {
 	watchdog_unregister_device(&orion_wdt);
 	clk_disable_unprepare(clk);
@@ -193,7 +193,7 @@ static void orion_wdt_shutdown(struct platform_device *pdev)
 	orion_wdt_stop(&orion_wdt);
 }
 
-static const struct of_device_id orion_wdt_of_match_table[] __devinitdata = {
+static const struct of_device_id orion_wdt_of_match_table[] = {
 	{ .compatible = "marvell,orion-wdt", },
 	{},
 };
@@ -201,7 +201,7 @@ MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table);
 
 static struct platform_driver orion_wdt_driver = {
 	.probe		= orion_wdt_probe,
-	.remove		= __devexit_p(orion_wdt_remove),
+	.remove		= orion_wdt_remove,
 	.shutdown	= orion_wdt_shutdown,
 	.driver		= {
 		.owner	= THIS_MODULE,
diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c
index 75694cf..33e49a7 100644
--- a/drivers/watchdog/pcwd.c
+++ b/drivers/watchdog/pcwd.c
@@ -801,7 +801,7 @@ static inline int get_revision(void)
  *  The initial rate is once per second at board start up, then twice
  *  per second for normal operation.
  */
-static int __devinit pcwd_isa_match(struct device *dev, unsigned int id)
+static int pcwd_isa_match(struct device *dev, unsigned int id)
 {
 	int base_addr = pcwd_ioports[id];
 	int port0, last_port0;	/* Reg 0, in case it's REV A */
@@ -846,7 +846,7 @@ static int __devinit pcwd_isa_match(struct device *dev, unsigned int id)
 	return retval;
 }
 
-static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id)
+static int pcwd_isa_probe(struct device *dev, unsigned int id)
 {
 	int ret;
 
@@ -949,7 +949,7 @@ error_request_region:
 	return ret;
 }
 
-static int __devexit pcwd_isa_remove(struct device *dev, unsigned int id)
+static int pcwd_isa_remove(struct device *dev, unsigned int id)
 {
 	if (debug >= DEBUG)
 		pr_debug("pcwd_isa_remove id=%d\n", id);
@@ -984,7 +984,7 @@ static void pcwd_isa_shutdown(struct device *dev, unsigned int id)
 static struct isa_driver pcwd_isa_driver = {
 	.match		= pcwd_isa_match,
 	.probe		= pcwd_isa_probe,
-	.remove		= __devexit_p(pcwd_isa_remove),
+	.remove		= pcwd_isa_remove,
 	.shutdown	= pcwd_isa_shutdown,
 	.driver		= {
 		.owner	= THIS_MODULE,
diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c
index ee6900d..7890f84 100644
--- a/drivers/watchdog/pcwd_pci.c
+++ b/drivers/watchdog/pcwd_pci.c
@@ -682,7 +682,7 @@ static struct notifier_block pcipcwd_notifier = {
  *	Init & exit routines
  */
 
-static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
+static int pcipcwd_card_init(struct pci_dev *pdev,
 		const struct pci_device_id *ent)
 {
 	int ret = -EIO;
@@ -785,7 +785,7 @@ err_out_disable_device:
 	return ret;
 }
 
-static void __devexit pcipcwd_card_exit(struct pci_dev *pdev)
+static void pcipcwd_card_exit(struct pci_dev *pdev)
 {
 	/* Stop the timer before we leave */
 	if (!nowayout)
@@ -812,7 +812,7 @@ static struct pci_driver pcipcwd_driver = {
 	.name		= WATCHDOG_NAME,
 	.id_table	= pcipcwd_pci_tbl,
 	.probe		= pcipcwd_card_init,
-	.remove		= __devexit_p(pcipcwd_card_exit),
+	.remove		= pcipcwd_card_exit,
 };
 
 module_pci_driver(pcipcwd_driver);
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
index 87722e1..dcba5da 100644
--- a/drivers/watchdog/pnx4008_wdt.c
+++ b/drivers/watchdog/pnx4008_wdt.c
@@ -146,7 +146,7 @@ static struct watchdog_device pnx4008_wdd = {
 	.max_timeout = MAX_HEARTBEAT,
 };
 
-static int __devinit pnx4008_wdt_probe(struct platform_device *pdev)
+static int pnx4008_wdt_probe(struct platform_device *pdev)
 {
 	struct resource *r;
 	int ret = 0;
@@ -192,7 +192,7 @@ out:
 	return ret;
 }
 
-static int __devexit pnx4008_wdt_remove(struct platform_device *pdev)
+static int pnx4008_wdt_remove(struct platform_device *pdev)
 {
 	watchdog_unregister_device(&pnx4008_wdd);
 
@@ -217,7 +217,7 @@ static struct platform_driver platform_wdt_driver = {
 		.of_match_table = of_match_ptr(pnx4008_wdt_match),
 	},
 	.probe = pnx4008_wdt_probe,
-	.remove = __devexit_p(pnx4008_wdt_remove),
+	.remove = pnx4008_wdt_remove,
 };
 
 module_platform_driver(platform_wdt_driver);
diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c
index 547353a..f78bc00 100644
--- a/drivers/watchdog/rc32434_wdt.c
+++ b/drivers/watchdog/rc32434_wdt.c
@@ -260,7 +260,7 @@ static struct miscdevice rc32434_wdt_miscdev = {
 	.fops	= &rc32434_wdt_fops,
 };
 
-static int __devinit rc32434_wdt_probe(struct platform_device *pdev)
+static int rc32434_wdt_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct resource *r;
@@ -306,7 +306,7 @@ unmap:
 	return ret;
 }
 
-static int __devexit rc32434_wdt_remove(struct platform_device *pdev)
+static int rc32434_wdt_remove(struct platform_device *pdev)
 {
 	misc_deregister(&rc32434_wdt_miscdev);
 	iounmap(wdt_reg);
@@ -320,7 +320,7 @@ static void rc32434_wdt_shutdown(struct platform_device *pdev)
 
 static struct platform_driver rc32434_wdt_driver = {
 	.probe		= rc32434_wdt_probe,
-	.remove		= __devexit_p(rc32434_wdt_remove),
+	.remove		= rc32434_wdt_remove,
 	.shutdown	= rc32434_wdt_shutdown,
 	.driver		= {
 			.name = "rc32434_wdt",
diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c
index 042ccc5..b0f116c 100644
--- a/drivers/watchdog/rdc321x_wdt.c
+++ b/drivers/watchdog/rdc321x_wdt.c
@@ -225,7 +225,7 @@ static struct miscdevice rdc321x_wdt_misc = {
 	.fops	= &rdc321x_wdt_fops,
 };
 
-static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
+static int rdc321x_wdt_probe(struct platform_device *pdev)
 {
 	int err;
 	struct resource *r;
@@ -272,7 +272,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit rdc321x_wdt_remove(struct platform_device *pdev)
+static int rdc321x_wdt_remove(struct platform_device *pdev)
 {
 	if (rdc321x_wdt_device.queue) {
 		rdc321x_wdt_device.queue = 0;
@@ -286,7 +286,7 @@ static int __devexit rdc321x_wdt_remove(struct platform_device *pdev)
 
 static struct platform_driver rdc321x_wdt_driver = {
 	.probe = rdc321x_wdt_probe,
-	.remove = __devexit_p(rdc321x_wdt_remove),
+	.remove = rdc321x_wdt_remove,
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = "rdc321x-wdt",
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
index 49e1b1c..0040451 100644
--- a/drivers/watchdog/riowd.c
+++ b/drivers/watchdog/riowd.c
@@ -174,7 +174,7 @@ static struct miscdevice riowd_miscdev = {
 	.fops	= &riowd_fops
 };
 
-static int __devinit riowd_probe(struct platform_device *op)
+static int riowd_probe(struct platform_device *op)
 {
 	struct riowd *p;
 	int err = -EINVAL;
@@ -220,7 +220,7 @@ out:
 	return err;
 }
 
-static int __devexit riowd_remove(struct platform_device *op)
+static int riowd_remove(struct platform_device *op)
 {
 	struct riowd *p = dev_get_drvdata(&op->dev);
 
@@ -246,7 +246,7 @@ static struct platform_driver riowd_driver = {
 		.of_match_table = riowd_match,
 	},
 	.probe		= riowd_probe,
-	.remove		= __devexit_p(riowd_remove),
+	.remove		= riowd_remove,
 };
 
 module_platform_driver(riowd_driver);
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index 9245b4d..b0dab10 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -303,7 +303,7 @@ static inline void s3c2410wdt_cpufreq_deregister(void)
 }
 #endif
 
-static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
+static int s3c2410wdt_probe(struct platform_device *pdev)
 {
 	struct device *dev;
 	unsigned int wtcon;
@@ -437,7 +437,7 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit s3c2410wdt_remove(struct platform_device *dev)
+static int s3c2410wdt_remove(struct platform_device *dev)
 {
 	watchdog_unregister_device(&s3c2410_wdd);
 
@@ -508,7 +508,7 @@ MODULE_DEVICE_TABLE(of, s3c2410_wdt_match);
 
 static struct platform_driver s3c2410wdt_driver = {
 	.probe		= s3c2410wdt_probe,
-	.remove		= __devexit_p(s3c2410wdt_remove),
+	.remove		= s3c2410wdt_remove,
 	.shutdown	= s3c2410wdt_shutdown,
 	.suspend	= s3c2410wdt_suspend,
 	.resume		= s3c2410wdt_resume,
diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c
index 9681ada..af7b136 100644
--- a/drivers/watchdog/sch311x_wdt.c
+++ b/drivers/watchdog/sch311x_wdt.c
@@ -356,7 +356,7 @@ static struct miscdevice sch311x_wdt_miscdev = {
  *	Init & exit routines
  */
 
-static int __devinit sch311x_wdt_probe(struct platform_device *pdev)
+static int sch311x_wdt_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	int err;
@@ -429,7 +429,7 @@ exit:
 	return err;
 }
 
-static int __devexit sch311x_wdt_remove(struct platform_device *pdev)
+static int sch311x_wdt_remove(struct platform_device *pdev)
 {
 	/* Stop the timer before we leave */
 	if (!nowayout)
@@ -451,7 +451,7 @@ static void sch311x_wdt_shutdown(struct platform_device *dev)
 
 static struct platform_driver sch311x_wdt_driver = {
 	.probe		= sch311x_wdt_probe,
-	.remove		= __devexit_p(sch311x_wdt_remove),
+	.remove		= sch311x_wdt_remove,
 	.shutdown	= sch311x_wdt_shutdown,
 	.driver		= {
 		.owner = THIS_MODULE,
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
index e5b59be..6a89e40 100644
--- a/drivers/watchdog/shwdt.c
+++ b/drivers/watchdog/shwdt.c
@@ -217,7 +217,7 @@ static struct watchdog_device sh_wdt_dev = {
 	.ops	= &sh_wdt_ops,
 };
 
-static int __devinit sh_wdt_probe(struct platform_device *pdev)
+static int sh_wdt_probe(struct platform_device *pdev)
 {
 	struct sh_wdt *wdt;
 	struct resource *res;
@@ -298,7 +298,7 @@ err:
 	return rc;
 }
 
-static int __devexit sh_wdt_remove(struct platform_device *pdev)
+static int sh_wdt_remove(struct platform_device *pdev)
 {
 	struct sh_wdt *wdt = platform_get_drvdata(pdev);
 
@@ -324,7 +324,7 @@ static struct platform_driver sh_wdt_driver = {
 	},
 
 	.probe		= sh_wdt_probe,
-	.remove		= __devexit_p(sh_wdt_remove),
+	.remove		= sh_wdt_remove,
 	.shutdown	= sh_wdt_shutdown,
 };
 
diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c
index ae5e82c..b387681 100644
--- a/drivers/watchdog/sp5100_tco.c
+++ b/drivers/watchdog/sp5100_tco.c
@@ -271,7 +271,7 @@ MODULE_DEVICE_TABLE(pci, sp5100_tco_pci_tbl);
  * Init & exit routines
  */
 
-static unsigned char __devinit sp5100_tco_setupdevice(void)
+static unsigned char sp5100_tco_setupdevice(void)
 {
 	struct pci_dev *dev = NULL;
 	u32 val;
@@ -361,7 +361,7 @@ exit:
 	return 0;
 }
 
-static int __devinit sp5100_tco_init(struct platform_device *dev)
+static int sp5100_tco_init(struct platform_device *dev)
 {
 	int ret;
 	u32 val;
@@ -412,7 +412,7 @@ exit:
 	return ret;
 }
 
-static void __devexit sp5100_tco_cleanup(void)
+static void sp5100_tco_cleanup(void)
 {
 	/* Stop the timer before we leave */
 	if (!nowayout)
@@ -425,7 +425,7 @@ static void __devexit sp5100_tco_cleanup(void)
 	release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
 }
 
-static int __devexit sp5100_tco_remove(struct platform_device *dev)
+static int sp5100_tco_remove(struct platform_device *dev)
 {
 	if (tcobase)
 		sp5100_tco_cleanup();
@@ -439,7 +439,7 @@ static void sp5100_tco_shutdown(struct platform_device *dev)
 
 static struct platform_driver sp5100_tco_driver = {
 	.probe		= sp5100_tco_init,
-	.remove		= __devexit_p(sp5100_tco_remove),
+	.remove		= sp5100_tco_remove,
 	.shutdown	= sp5100_tco_shutdown,
 	.driver		= {
 		.owner	= THIS_MODULE,
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
index e4841c3..76c73cb 100644
--- a/drivers/watchdog/sp805_wdt.c
+++ b/drivers/watchdog/sp805_wdt.c
@@ -210,7 +210,7 @@ static const struct watchdog_ops wdt_ops = {
 	.get_timeleft	= wdt_timeleft,
 };
 
-static int __devinit
+static int
 sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	struct sp805_wdt *wdt;
@@ -272,7 +272,7 @@ err:
 	return ret;
 }
 
-static int __devexit sp805_wdt_remove(struct amba_device *adev)
+static int sp805_wdt_remove(struct amba_device *adev)
 {
 	struct sp805_wdt *wdt = amba_get_drvdata(adev);
 
@@ -284,8 +284,7 @@ static int __devexit sp805_wdt_remove(struct amba_device *adev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int sp805_wdt_suspend(struct device *dev)
+static int __maybe_unused sp805_wdt_suspend(struct device *dev)
 {
 	struct sp805_wdt *wdt = dev_get_drvdata(dev);
 
@@ -295,7 +294,7 @@ static int sp805_wdt_suspend(struct device *dev)
 	return 0;
 }
 
-static int sp805_wdt_resume(struct device *dev)
+static int __maybe_unused sp805_wdt_resume(struct device *dev)
 {
 	struct sp805_wdt *wdt = dev_get_drvdata(dev);
 
@@ -304,7 +303,6 @@ static int sp805_wdt_resume(struct device *dev)
 
 	return 0;
 }
-#endif /* CONFIG_PM */
 
 static SIMPLE_DEV_PM_OPS(sp805_wdt_dev_pm_ops, sp805_wdt_suspend,
 		sp805_wdt_resume);
@@ -326,7 +324,7 @@ static struct amba_driver sp805_wdt_driver = {
 	},
 	.id_table	= sp805_wdt_ids,
 	.probe		= sp805_wdt_probe,
-	.remove = __devexit_p(sp805_wdt_remove),
+	.remove = sp805_wdt_remove,
 };
 
 module_amba_driver(sp805_wdt_driver);
diff --git a/drivers/watchdog/stmp3xxx_wdt.c b/drivers/watchdog/stmp3xxx_wdt.c
index 21d96b9..1f4f697 100644
--- a/drivers/watchdog/stmp3xxx_wdt.c
+++ b/drivers/watchdog/stmp3xxx_wdt.c
@@ -204,7 +204,7 @@ static struct miscdevice stmp3xxx_wdt_miscdev = {
 	.fops = &stmp3xxx_wdt_fops,
 };
 
-static int __devinit stmp3xxx_wdt_probe(struct platform_device *pdev)
+static int stmp3xxx_wdt_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 
@@ -229,7 +229,7 @@ static int __devinit stmp3xxx_wdt_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit stmp3xxx_wdt_remove(struct platform_device *pdev)
+static int stmp3xxx_wdt_remove(struct platform_device *pdev)
 {
 	misc_deregister(&stmp3xxx_wdt_miscdev);
 	return 0;
@@ -269,7 +269,7 @@ static struct platform_driver platform_wdt_driver = {
 		.name = "stmp3xxx_wdt",
 	},
 	.probe = stmp3xxx_wdt_probe,
-	.remove = __devexit_p(stmp3xxx_wdt_remove),
+	.remove = stmp3xxx_wdt_remove,
 	.suspend = stmp3xxx_wdt_suspend,
 	.resume = stmp3xxx_wdt_resume,
 };
diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c
index 8df050d..b8a9245 100644
--- a/drivers/watchdog/ts72xx_wdt.c
+++ b/drivers/watchdog/ts72xx_wdt.c
@@ -390,7 +390,7 @@ static struct miscdevice ts72xx_wdt_miscdev = {
 	.fops		= &ts72xx_wdt_fops,
 };
 
-static __devinit int ts72xx_wdt_probe(struct platform_device *pdev)
+static int ts72xx_wdt_probe(struct platform_device *pdev)
 {
 	struct ts72xx_wdt *wdt;
 	struct resource *r1, *r2;
@@ -476,7 +476,7 @@ fail:
 	return error;
 }
 
-static __devexit int ts72xx_wdt_remove(struct platform_device *pdev)
+static int ts72xx_wdt_remove(struct platform_device *pdev)
 {
 	struct ts72xx_wdt *wdt = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -499,7 +499,7 @@ static __devexit int ts72xx_wdt_remove(struct platform_device *pdev)
 
 static struct platform_driver ts72xx_wdt_driver = {
 	.probe		= ts72xx_wdt_probe,
-	.remove		= __devexit_p(ts72xx_wdt_remove),
+	.remove		= ts72xx_wdt_remove,
 	.driver		= {
 		.name	= "ts72xx-wdt",
 		.owner	= THIS_MODULE,
diff --git a/drivers/watchdog/twl4030_wdt.c b/drivers/watchdog/twl4030_wdt.c
index 249f113..9f54b1d 100644
--- a/drivers/watchdog/twl4030_wdt.c
+++ b/drivers/watchdog/twl4030_wdt.c
@@ -170,7 +170,7 @@ static const struct file_operations twl4030_wdt_fops = {
 	.write		= twl4030_wdt_write_fop,
 };
 
-static int __devinit twl4030_wdt_probe(struct platform_device *pdev)
+static int twl4030_wdt_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 	struct twl4030_wdt *wdt;
@@ -204,7 +204,7 @@ static int __devinit twl4030_wdt_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit twl4030_wdt_remove(struct platform_device *pdev)
+static int twl4030_wdt_remove(struct platform_device *pdev)
 {
 	struct twl4030_wdt *wdt = platform_get_drvdata(pdev);
 
@@ -247,7 +247,7 @@ static int twl4030_wdt_resume(struct platform_device *pdev)
 
 static struct platform_driver twl4030_wdt_driver = {
 	.probe		= twl4030_wdt_probe,
-	.remove		= __devexit_p(twl4030_wdt_remove),
+	.remove		= twl4030_wdt_remove,
 	.suspend	= twl4030_wdt_suspend,
 	.resume		= twl4030_wdt_resume,
 	.driver		= {
diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c
index aa50da3..1a68f76 100644
--- a/drivers/watchdog/via_wdt.c
+++ b/drivers/watchdog/via_wdt.c
@@ -155,7 +155,7 @@ static struct watchdog_device wdt_dev = {
 	.max_timeout =	WDT_TIMEOUT_MAX,
 };
 
-static int __devinit wdt_probe(struct pci_dev *pdev,
+static int wdt_probe(struct pci_dev *pdev,
 			       const struct pci_device_id *ent)
 {
 	unsigned char conf;
@@ -229,7 +229,7 @@ err_out_disable_device:
 	return ret;
 }
 
-static void __devexit wdt_remove(struct pci_dev *pdev)
+static void wdt_remove(struct pci_dev *pdev)
 {
 	watchdog_unregister_device(&wdt_dev);
 	del_timer(&timer);
@@ -250,7 +250,7 @@ static struct pci_driver wdt_driver = {
 	.name		= "via_wdt",
 	.id_table	= wdt_pci_table,
 	.probe		= wdt_probe,
-	.remove		= __devexit_p(wdt_remove),
+	.remove		= wdt_remove,
 };
 
 module_pci_driver(wdt_driver);
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c
index e32654e..36a54c0 100644
--- a/drivers/watchdog/wdt_pci.c
+++ b/drivers/watchdog/wdt_pci.c
@@ -605,7 +605,7 @@ static struct notifier_block wdtpci_notifier = {
 };
 
 
-static int __devinit wdtpci_init_one(struct pci_dev *dev,
+static int wdtpci_init_one(struct pci_dev *dev,
 					const struct pci_device_id *ent)
 {
 	int ret = -EIO;
@@ -705,7 +705,7 @@ out_pci:
 }
 
 
-static void __devexit wdtpci_remove_one(struct pci_dev *pdev)
+static void wdtpci_remove_one(struct pci_dev *pdev)
 {
 	/* here we assume only one device will ever have
 	 * been picked up and registered by probe function */
@@ -736,7 +736,7 @@ static struct pci_driver wdtpci_driver = {
 	.name		= "wdt_pci",
 	.id_table	= wdtpci_pci_tbl,
 	.probe		= wdtpci_init_one,
-	.remove		= __devexit_p(wdtpci_remove_one),
+	.remove		= wdtpci_remove_one,
 };
 
 module_pci_driver(wdtpci_driver);
diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c
index 87d66d2..9dcb6d0 100644
--- a/drivers/watchdog/wm831x_wdt.c
+++ b/drivers/watchdog/wm831x_wdt.c
@@ -181,7 +181,7 @@ static const struct watchdog_ops wm831x_wdt_ops = {
 	.set_timeout = wm831x_wdt_set_timeout,
 };
 
-static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
+static int wm831x_wdt_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 	struct wm831x_pdata *chip_pdata;
@@ -292,7 +292,7 @@ err:
 	return ret;
 }
 
-static int __devexit wm831x_wdt_remove(struct platform_device *pdev)
+static int wm831x_wdt_remove(struct platform_device *pdev)
 {
 	struct wm831x_wdt_drvdata *driver_data = dev_get_drvdata(&pdev->dev);
 
@@ -306,7 +306,7 @@ static int __devexit wm831x_wdt_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_wdt_driver = {
 	.probe = wm831x_wdt_probe,
-	.remove = __devexit_p(wm831x_wdt_remove),
+	.remove = wm831x_wdt_remove,
 	.driver = {
 		.name = "wm831x-watchdog",
 	},
diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c
index 3c76693..34d272a 100644
--- a/drivers/watchdog/wm8350_wdt.c
+++ b/drivers/watchdog/wm8350_wdt.c
@@ -140,7 +140,7 @@ static struct watchdog_device wm8350_wdt = {
 	.max_timeout = 4,
 };
 
-static int __devinit wm8350_wdt_probe(struct platform_device *pdev)
+static int wm8350_wdt_probe(struct platform_device *pdev)
 {
 	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
 
@@ -158,7 +158,7 @@ static int __devinit wm8350_wdt_probe(struct platform_device *pdev)
 	return watchdog_register_device(&wm8350_wdt);
 }
 
-static int __devexit wm8350_wdt_remove(struct platform_device *pdev)
+static int wm8350_wdt_remove(struct platform_device *pdev)
 {
 	watchdog_unregister_device(&wm8350_wdt);
 	return 0;
@@ -166,7 +166,7 @@ static int __devexit wm8350_wdt_remove(struct platform_device *pdev)
 
 static struct platform_driver wm8350_wdt_driver = {
 	.probe = wm8350_wdt_probe,
-	.remove = __devexit_p(wm8350_wdt_remove),
+	.remove = wm8350_wdt_remove,
 	.driver = {
 		.name = "wm8350-wdt",
 	},
diff --git a/drivers/watchdog/xen_wdt.c b/drivers/watchdog/xen_wdt.c
index e4a25b5..92ad33d 100644
--- a/drivers/watchdog/xen_wdt.c
+++ b/drivers/watchdog/xen_wdt.c
@@ -244,7 +244,7 @@ static struct miscdevice xen_wdt_miscdev = {
 	.fops =		&xen_wdt_fops,
 };
 
-static int __devinit xen_wdt_probe(struct platform_device *dev)
+static int xen_wdt_probe(struct platform_device *dev)
 {
 	struct sched_watchdog wd = { .id = ~0 };
 	int ret = HYPERVISOR_sched_op(SCHEDOP_watchdog, &wd);
@@ -280,7 +280,7 @@ static int __devinit xen_wdt_probe(struct platform_device *dev)
 	return ret;
 }
 
-static int __devexit xen_wdt_remove(struct platform_device *dev)
+static int xen_wdt_remove(struct platform_device *dev)
 {
 	/* Stop the timer before we leave */
 	if (!nowayout)
@@ -315,7 +315,7 @@ static int xen_wdt_resume(struct platform_device *dev)
 
 static struct platform_driver xen_wdt_driver = {
 	.probe          = xen_wdt_probe,
-	.remove         = __devexit_p(xen_wdt_remove),
+	.remove         = xen_wdt_remove,
 	.shutdown       = xen_wdt_shutdown,
 	.suspend        = xen_wdt_suspend,
 	.resume         = xen_wdt_resume,
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index 126d8ce..cabfa97 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -206,4 +206,7 @@ config XEN_MCE_LOG
 	  Allow kernel fetching MCE error from Xen platform and
 	  converting it into Linux mcelog format for mcelog tools
 
+config XEN_HAVE_PVMMU
+       bool
+
 endmenu
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index 7435470..fb213cf 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -1,9 +1,9 @@
 ifneq ($(CONFIG_ARM),y)
-obj-y	+= manage.o balloon.o
+obj-y	+= manage.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= cpu_hotplug.o
 endif
 obj-$(CONFIG_X86)			+= fallback.o
-obj-y	+= grant-table.o features.o events.o
+obj-y	+= grant-table.o features.o events.o balloon.o
 obj-y	+= xenbus/
 
 nostackp := $(call cc-option, -fno-stack-protector)
@@ -11,7 +11,8 @@ CFLAGS_features.o			:= $(nostackp)
 
 dom0-$(CONFIG_PCI) += pci.o
 dom0-$(CONFIG_USB_SUPPORT) += dbgp.o
-dom0-$(CONFIG_ACPI) += acpi.o
+dom0-$(CONFIG_ACPI) += acpi.o $(xen-pad-y)
+xen-pad-$(CONFIG_X86) += xen-acpi-pad.o
 dom0-$(CONFIG_X86) += pcpu.o
 obj-$(CONFIG_XEN_DOM0)			+= $(dom0-y)
 obj-$(CONFIG_BLOCK)			+= biomerge.o
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index d6886d9..d42da3b 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -359,8 +359,11 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
 
 		set_phys_to_machine(pfn, frame_list[i]);
 
+#ifdef CONFIG_XEN_HAVE_PVMMU
 		/* Link back into the page tables if not highmem. */
-		if (xen_pv_domain() && !PageHighMem(page)) {
+		if (xen_pv_domain() && !PageHighMem(page) &&
+		    !xen_feature(XENFEAT_auto_translated_physmap)) {
+
 			int ret;
 			ret = HYPERVISOR_update_va_mapping(
 				(unsigned long)__va(pfn << PAGE_SHIFT),
@@ -368,6 +371,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
 				0);
 			BUG_ON(ret);
 		}
+#endif
 
 		/* Relinquish the page back to the allocator. */
 		ClearPageReserved(page);
@@ -416,13 +420,16 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
 
 		scrub_page(page);
 
+#ifdef CONFIG_XEN_HAVE_PVMMU
 		if (xen_pv_domain() && !PageHighMem(page)) {
-			ret = HYPERVISOR_update_va_mapping(
-				(unsigned long)__va(pfn << PAGE_SHIFT),
-				__pte_ma(0), 0);
-			BUG_ON(ret);
+			if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+				ret = HYPERVISOR_update_va_mapping(
+					(unsigned long)__va(pfn << PAGE_SHIFT),
+					__pte_ma(0), 0);
+				BUG_ON(ret);
+			}
 		}
-
+#endif
 	}
 
 	/* Ensure that ballooned highmem pages don't have kmaps. */
diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c
index 4dcfced..de6bcf9 100644
--- a/drivers/xen/cpu_hotplug.c
+++ b/drivers/xen/cpu_hotplug.c
@@ -2,6 +2,7 @@
 
 #include <xen/xen.h>
 #include <xen/xenbus.h>
+#include <xen/features.h>
 
 #include <asm/xen/hypervisor.h>
 #include <asm/cpu.h>
@@ -100,7 +101,8 @@ static int __init setup_vcpu_hotplug_event(void)
 	static struct notifier_block xsn_cpu = {
 		.notifier_call = setup_cpu_watcher };
 
-	if (!xen_pv_domain())
+	/* PVH TBD/FIXME: future work */
+	if (!xen_pv_domain() || xen_feature(XENFEAT_auto_translated_physmap))
 		return -ENODEV;
 
 	register_xenstore_notifier(&xsn_cpu);
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 0be4df3..4293c57 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -1778,7 +1778,7 @@ int xen_set_callback_via(uint64_t via)
 }
 EXPORT_SYMBOL_GPL(xen_set_callback_via);
 
-#ifdef CONFIG_XEN_PVHVM
+#ifdef CONFIG_X86
 /* Vector callbacks are better than PCI interrupts to receive event
  * channel notifications because we can receive vector callbacks on any
  * vcpu and we don't need PCI support or APIC interactions. */
@@ -1839,6 +1839,13 @@ void __init xen_init_IRQ(void)
 		if (xen_initial_domain())
 			pci_xen_initial_domain();
 
+		if (xen_feature(XENFEAT_hvm_callback_vector)) {
+			xen_callback_vector();
+			return;
+		}
+
+		/* PVH: TBD/FIXME: debug and fix eio map to work with pvh */
+
 		pirq_eoi_map = (void *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
 		eoi_gmfn.gmfn = virt_to_mfn(pirq_eoi_map);
 		rc = HYPERVISOR_physdev_op(PHYSDEVOP_pirq_eoi_gmfn_v2, &eoi_gmfn);
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 2e22df2..1a077a3 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -805,7 +805,8 @@ static int __init gntdev_init(void)
 	if (!xen_domain())
 		return -ENODEV;
 
-	use_ptemod = xen_pv_domain();
+	use_ptemod = xen_pv_domain() &&
+		     !xen_feature(XENFEAT_auto_translated_physmap);
 
 	err = misc_register(&gntdev_miscdev);
 	if (err != 0) {
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index b91f14e..043bf07 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -38,7 +38,6 @@
 #include <linux/vmalloc.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
-#include <linux/delay.h>
 #include <linux/hardirq.h>
 
 #include <xen/xen.h>
@@ -824,52 +823,6 @@ unsigned int gnttab_max_grant_frames(void)
 }
 EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
 
-/* Handling of paged out grant targets (GNTST_eagain) */
-#define MAX_DELAY 256
-static inline void
-gnttab_retry_eagain_gop(unsigned int cmd, void *gop, int16_t *status,
-						const char *func)
-{
-	unsigned delay = 1;
-
-	do {
-		BUG_ON(HYPERVISOR_grant_table_op(cmd, gop, 1));
-		if (*status == GNTST_eagain)
-			msleep(delay++);
-	} while ((*status == GNTST_eagain) && (delay < MAX_DELAY));
-
-	if (delay >= MAX_DELAY) {
-		printk(KERN_ERR "%s: %s eagain grant\n", func, current->comm);
-		*status = GNTST_bad_page;
-	}
-}
-
-void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count)
-{
-	struct gnttab_map_grant_ref *op;
-
-	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, batch, count))
-		BUG();
-	for (op = batch; op < batch + count; op++)
-		if (op->status == GNTST_eagain)
-			gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, op,
-						&op->status, __func__);
-}
-EXPORT_SYMBOL_GPL(gnttab_batch_map);
-
-void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count)
-{
-	struct gnttab_copy *op;
-
-	if (HYPERVISOR_grant_table_op(GNTTABOP_copy, batch, count))
-		BUG();
-	for (op = batch; op < batch + count; op++)
-		if (op->status == GNTST_eagain)
-			gnttab_retry_eagain_gop(GNTTABOP_copy, op,
-						&op->status, __func__);
-}
-EXPORT_SYMBOL_GPL(gnttab_batch_copy);
-
 int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
 		    struct gnttab_map_grant_ref *kmap_ops,
 		    struct page **pages, unsigned int count)
@@ -883,12 +836,6 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
 	if (ret)
 		return ret;
 
-	/* Retry eagain maps */
-	for (i = 0; i < count; i++)
-		if (map_ops[i].status == GNTST_eagain)
-			gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i,
-						&map_ops[i].status, __func__);
-
 	if (xen_feature(XENFEAT_auto_translated_physmap))
 		return ret;
 
@@ -1029,14 +976,20 @@ static void gnttab_unmap_frames_v2(void)
 static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
 {
 	struct gnttab_setup_table setup;
+	unsigned long start_gpfn;
 	xen_pfn_t *frames;
 	unsigned int nr_gframes = end_idx + 1;
 	int rc;
 
-	if (xen_hvm_domain()) {
+	if (xen_hvm_domain() || xen_feature(XENFEAT_auto_translated_physmap)) {
 		struct xen_add_to_physmap xatp;
 		unsigned int i = end_idx;
 		rc = 0;
+
+		if (xen_hvm_domain())
+			start_gpfn = xen_hvm_resume_frames >> PAGE_SHIFT;
+		else
+			start_gpfn = virt_to_pfn(gnttab_shared.addr);
 		/*
 		 * Loop backwards, so that the first hypercall has the largest
 		 * index, ensuring that the table will grow only once.
@@ -1045,7 +998,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
 			xatp.domid = DOMID_SELF;
 			xatp.idx = i;
 			xatp.space = XENMAPSPACE_grant_table;
-			xatp.gpfn = (xen_hvm_resume_frames >> PAGE_SHIFT) + i;
+			xatp.gpfn = start_gpfn + i;
 			rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
 			if (rc != 0) {
 				printk(KERN_WARNING
@@ -1108,7 +1061,7 @@ static void gnttab_request_version(void)
 	int rc;
 	struct gnttab_set_version gsv;
 
-	if (xen_hvm_domain())
+	if (xen_hvm_domain() || xen_feature(XENFEAT_auto_translated_physmap))
 		gsv.version = 1;
 	else
 		gsv.version = 2;
@@ -1136,12 +1089,25 @@ static void gnttab_request_version(void)
 int gnttab_resume(void)
 {
 	unsigned int max_nr_gframes;
+	char *kmsg = "Failed to kmalloc pages for pv in hvm grant frames\n";
 
 	gnttab_request_version();
 	max_nr_gframes = gnttab_max_grant_frames();
 	if (max_nr_gframes < nr_grant_frames)
 		return -ENOSYS;
 
+	/* PVH note: xen will free existing kmalloc'd mfn in
+	 * XENMEM_add_to_physmap. TBD/FIXME: use xen ballooning instead of
+	 * kmalloc(). */
+	if (xen_pv_domain() && xen_feature(XENFEAT_auto_translated_physmap) &&
+	    !gnttab_shared.addr) {
+		gnttab_shared.addr =
+			kmalloc(max_nr_gframes * PAGE_SIZE, GFP_KERNEL);
+		if (!gnttab_shared.addr) {
+			pr_warn("%s", kmsg);
+			return -ENOMEM;
+		}
+	}
 	if (xen_pv_domain())
 		return gnttab_map(0, nr_grant_frames - 1);
 
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 71f5c45..3421f0d 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -33,11 +33,14 @@
 #include <xen/features.h>
 #include <xen/page.h>
 #include <xen/xen-ops.h>
+#include <xen/balloon.h>
 
 #include "privcmd.h"
 
 MODULE_LICENSE("GPL");
 
+#define PRIV_VMA_LOCKED ((void *)1)
+
 #ifndef HAVE_ARCH_PRIVCMD_MMAP
 static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma);
 #endif
@@ -178,7 +181,7 @@ static int mmap_mfn_range(void *data, void *state)
 					msg->va & PAGE_MASK,
 					msg->mfn, msg->npages,
 					vma->vm_page_prot,
-					st->domain);
+					st->domain, NULL);
 	if (rc < 0)
 		return rc;
 
@@ -199,6 +202,10 @@ static long privcmd_ioctl_mmap(void __user *udata)
 	if (!xen_initial_domain())
 		return -EPERM;
 
+	/* We only support privcmd_ioctl_mmap_batch for auto translated. */
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return -ENOSYS;
+
 	if (copy_from_user(&mmapcmd, udata, sizeof(mmapcmd)))
 		return -EFAULT;
 
@@ -246,6 +253,7 @@ struct mmap_batch_state {
 	domid_t domain;
 	unsigned long va;
 	struct vm_area_struct *vma;
+	int index;
 	/* A tristate:
 	 *      0 for no errors
 	 *      1 if at least one error has happened (and no
@@ -260,14 +268,24 @@ struct mmap_batch_state {
 	xen_pfn_t __user *user_mfn;
 };
 
+/* auto translated dom0 note: if domU being created is PV, then mfn is
+ * mfn(addr on bus). If it's auto xlated, then mfn is pfn (input to HAP).
+ */
 static int mmap_batch_fn(void *data, void *state)
 {
 	xen_pfn_t *mfnp = data;
 	struct mmap_batch_state *st = state;
+	struct vm_area_struct *vma = st->vma;
+	struct page **pages = vma->vm_private_data;
+	struct page *cur_page = NULL;
 	int ret;
 
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		cur_page = pages[st->index++];
+
 	ret = xen_remap_domain_mfn_range(st->vma, st->va & PAGE_MASK, *mfnp, 1,
-					 st->vma->vm_page_prot, st->domain);
+					 st->vma->vm_page_prot, st->domain,
+					 &cur_page);
 
 	/* Store error code for second pass. */
 	*(st->err++) = ret;
@@ -303,6 +321,32 @@ static int mmap_return_errors_v1(void *data, void *state)
 	return __put_user(*mfnp, st->user_mfn++);
 }
 
+/* Allocate pfns that are then mapped with gmfns from foreign domid. Update
+ * the vma with the page info to use later.
+ * Returns: 0 if success, otherwise -errno
+ */
+static int alloc_empty_pages(struct vm_area_struct *vma, int numpgs)
+{
+	int rc;
+	struct page **pages;
+
+	pages = kcalloc(numpgs, sizeof(pages[0]), GFP_KERNEL);
+	if (pages == NULL)
+		return -ENOMEM;
+
+	rc = alloc_xenballooned_pages(numpgs, pages, 0);
+	if (rc != 0) {
+		pr_warn("%s Could not alloc %d pfns rc:%d\n", __func__,
+			numpgs, rc);
+		kfree(pages);
+		return -ENOMEM;
+	}
+	BUG_ON(vma->vm_private_data != PRIV_VMA_LOCKED);
+	vma->vm_private_data = pages;
+
+	return 0;
+}
+
 static struct vm_operations_struct privcmd_vm_ops;
 
 static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
@@ -370,10 +414,18 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
 		ret = -EINVAL;
 		goto out;
 	}
+	if (xen_feature(XENFEAT_auto_translated_physmap)) {
+		ret = alloc_empty_pages(vma, m.num);
+		if (ret < 0) {
+			up_write(&mm->mmap_sem);
+			goto out;
+		}
+	}
 
 	state.domain        = m.dom;
 	state.vma           = vma;
 	state.va            = m.addr;
+	state.index         = 0;
 	state.global_error  = 0;
 	state.err           = err_array;
 
@@ -442,6 +494,19 @@ static long privcmd_ioctl(struct file *file,
 	return ret;
 }
 
+static void privcmd_close(struct vm_area_struct *vma)
+{
+	struct page **pages = vma->vm_private_data;
+	int numpgs = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+
+	if (!xen_feature(XENFEAT_auto_translated_physmap) || !numpgs || !pages)
+		return;
+
+	xen_unmap_domain_mfn_range(vma, numpgs, pages);
+	free_xenballooned_pages(numpgs, pages);
+	kfree(pages);
+}
+
 static int privcmd_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	printk(KERN_DEBUG "privcmd_fault: vma=%p %lx-%lx, pgoff=%lx, uv=%p\n",
@@ -452,6 +517,7 @@ static int privcmd_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 }
 
 static struct vm_operations_struct privcmd_vm_ops = {
+	.close = privcmd_close,
 	.fault = privcmd_fault
 };
 
@@ -469,7 +535,7 @@ static int privcmd_mmap(struct file *file, struct vm_area_struct *vma)
 
 static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma)
 {
-	return (xchg(&vma->vm_private_data, (void *)1) == NULL);
+	return !cmpxchg(&vma->vm_private_data, NULL, PRIV_VMA_LOCKED);
 }
 
 const struct file_operations xen_privcmd_fops = {
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 58db6df..af47e75 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -338,9 +338,8 @@ dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
 				enum dma_data_direction dir,
 				struct dma_attrs *attrs)
 {
-	phys_addr_t phys = page_to_phys(page) + offset;
+	phys_addr_t map, phys = page_to_phys(page) + offset;
 	dma_addr_t dev_addr = xen_phys_to_bus(phys);
-	void *map;
 
 	BUG_ON(dir == DMA_NONE);
 	/*
@@ -356,10 +355,10 @@ dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
 	 * Oh well, have to allocate and map a bounce buffer.
 	 */
 	map = swiotlb_tbl_map_single(dev, start_dma_addr, phys, size, dir);
-	if (!map)
+	if (map == SWIOTLB_MAP_ERROR)
 		return DMA_ERROR_CODE;
 
-	dev_addr = xen_virt_to_bus(map);
+	dev_addr = xen_phys_to_bus(map);
 
 	/*
 	 * Ensure that the address returned is DMA'ble
@@ -389,7 +388,7 @@ static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
 
 	/* NOTE: We use dev_addr here, not paddr! */
 	if (is_xen_swiotlb_buffer(dev_addr)) {
-		swiotlb_tbl_unmap_single(hwdev, phys_to_virt(paddr), size, dir);
+		swiotlb_tbl_unmap_single(hwdev, paddr, size, dir);
 		return;
 	}
 
@@ -434,8 +433,7 @@ xen_swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
 
 	/* NOTE: We use dev_addr here, not paddr! */
 	if (is_xen_swiotlb_buffer(dev_addr)) {
-		swiotlb_tbl_sync_single(hwdev, phys_to_virt(paddr), size, dir,
-				       target);
+		swiotlb_tbl_sync_single(hwdev, paddr, size, dir, target);
 		return;
 	}
 
@@ -494,11 +492,12 @@ xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
 		if (swiotlb_force ||
 		    !dma_capable(hwdev, dev_addr, sg->length) ||
 		    range_straddles_page_boundary(paddr, sg->length)) {
-			void *map = swiotlb_tbl_map_single(hwdev,
-							   start_dma_addr,
-							   sg_phys(sg),
-							   sg->length, dir);
-			if (!map) {
+			phys_addr_t map = swiotlb_tbl_map_single(hwdev,
+								 start_dma_addr,
+								 sg_phys(sg),
+								 sg->length,
+								 dir);
+			if (map == SWIOTLB_MAP_ERROR) {
 				/* Don't panic here, we expect map_sg users
 				   to do proper error handling. */
 				xen_swiotlb_unmap_sg_attrs(hwdev, sgl, i, dir,
@@ -506,7 +505,7 @@ xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
 				sgl[0].dma_length = 0;
 				return DMA_ERROR_CODE;
 			}
-			sg->dma_address = xen_virt_to_bus(map);
+			sg->dma_address = xen_phys_to_bus(map);
 		} else
 			sg->dma_address = dev_addr;
 		sg->dma_length = sg->length;
diff --git a/drivers/xen/xen-acpi-pad.c b/drivers/xen/xen-acpi-pad.c
new file mode 100644
index 0000000..da39191
--- /dev/null
+++ b/drivers/xen/xen-acpi-pad.c
@@ -0,0 +1,182 @@
+/*
+ * xen-acpi-pad.c - Xen pad interface
+ *
+ * Copyright (c) 2012, Intel Corporation.
+ *    Author: Liu, Jinsong <jinsong.liu@intel.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+#include <asm/xen/hypercall.h>
+#include <xen/interface/version.h>
+#include <xen/xen-ops.h>
+
+#define ACPI_PROCESSOR_AGGREGATOR_CLASS	"acpi_pad"
+#define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator"
+#define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80
+static DEFINE_MUTEX(xen_cpu_lock);
+
+static int xen_acpi_pad_idle_cpus(unsigned int idle_nums)
+{
+	struct xen_platform_op op;
+
+	op.cmd = XENPF_core_parking;
+	op.u.core_parking.type = XEN_CORE_PARKING_SET;
+	op.u.core_parking.idle_nums = idle_nums;
+
+	return HYPERVISOR_dom0_op(&op);
+}
+
+static int xen_acpi_pad_idle_cpus_num(void)
+{
+	struct xen_platform_op op;
+
+	op.cmd = XENPF_core_parking;
+	op.u.core_parking.type = XEN_CORE_PARKING_GET;
+
+	return HYPERVISOR_dom0_op(&op)
+	       ?: op.u.core_parking.idle_nums;
+}
+
+/*
+ * Query firmware how many CPUs should be idle
+ * return -1 on failure
+ */
+static int acpi_pad_pur(acpi_handle handle)
+{
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object *package;
+	int num = -1;
+
+	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer)))
+		return num;
+
+	if (!buffer.length || !buffer.pointer)
+		return num;
+
+	package = buffer.pointer;
+
+	if (package->type == ACPI_TYPE_PACKAGE &&
+		package->package.count == 2 &&
+		package->package.elements[0].integer.value == 1) /* rev 1 */
+		num = package->package.elements[1].integer.value;
+
+	kfree(buffer.pointer);
+	return num;
+}
+
+/* Notify firmware how many CPUs are idle */
+static void acpi_pad_ost(acpi_handle handle, int stat,
+	uint32_t idle_nums)
+{
+	union acpi_object params[3] = {
+		{.type = ACPI_TYPE_INTEGER,},
+		{.type = ACPI_TYPE_INTEGER,},
+		{.type = ACPI_TYPE_BUFFER,},
+	};
+	struct acpi_object_list arg_list = {3, params};
+
+	params[0].integer.value = ACPI_PROCESSOR_AGGREGATOR_NOTIFY;
+	params[1].integer.value =  stat;
+	params[2].buffer.length = 4;
+	params[2].buffer.pointer = (void *)&idle_nums;
+	acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
+}
+
+static void acpi_pad_handle_notify(acpi_handle handle)
+{
+	int idle_nums;
+
+	mutex_lock(&xen_cpu_lock);
+	idle_nums = acpi_pad_pur(handle);
+	if (idle_nums < 0) {
+		mutex_unlock(&xen_cpu_lock);
+		return;
+	}
+
+	idle_nums = xen_acpi_pad_idle_cpus(idle_nums)
+		    ?: xen_acpi_pad_idle_cpus_num();
+	if (idle_nums >= 0)
+		acpi_pad_ost(handle, 0, idle_nums);
+	mutex_unlock(&xen_cpu_lock);
+}
+
+static void acpi_pad_notify(acpi_handle handle, u32 event,
+	void *data)
+{
+	switch (event) {
+	case ACPI_PROCESSOR_AGGREGATOR_NOTIFY:
+		acpi_pad_handle_notify(handle);
+		break;
+	default:
+		pr_warn("Unsupported event [0x%x]\n", event);
+		break;
+	}
+}
+
+static int acpi_pad_add(struct acpi_device *device)
+{
+	acpi_status status;
+
+	strcpy(acpi_device_name(device), ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME);
+	strcpy(acpi_device_class(device), ACPI_PROCESSOR_AGGREGATOR_CLASS);
+
+	status = acpi_install_notify_handler(device->handle,
+		ACPI_DEVICE_NOTIFY, acpi_pad_notify, device);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	return 0;
+}
+
+static int acpi_pad_remove(struct acpi_device *device,
+	int type)
+{
+	mutex_lock(&xen_cpu_lock);
+	xen_acpi_pad_idle_cpus(0);
+	mutex_unlock(&xen_cpu_lock);
+
+	acpi_remove_notify_handler(device->handle,
+		ACPI_DEVICE_NOTIFY, acpi_pad_notify);
+	return 0;
+}
+
+static const struct acpi_device_id pad_device_ids[] = {
+	{"ACPI000C", 0},
+	{"", 0},
+};
+
+static struct acpi_driver acpi_pad_driver = {
+	.name = "processor_aggregator",
+	.class = ACPI_PROCESSOR_AGGREGATOR_CLASS,
+	.ids = pad_device_ids,
+	.ops = {
+		.add = acpi_pad_add,
+		.remove = acpi_pad_remove,
+	},
+};
+
+static int __init xen_acpi_pad_init(void)
+{
+	/* Only DOM0 is responsible for Xen acpi pad */
+	if (!xen_initial_domain())
+		return -ENODEV;
+
+	/* Only Xen4.2 or later support Xen acpi pad */
+	if (!xen_running_on_version_or_later(4, 2))
+		return -ENODEV;
+
+	return acpi_bus_register_driver(&acpi_pad_driver);
+}
+subsys_initcall(xen_acpi_pad_init);
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 961d664..cd50d25 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -142,7 +142,8 @@ static struct pcistub_device *pcistub_device_find(int domain, int bus,
 		if (psdev->dev != NULL
 		    && domain == pci_domain_nr(psdev->dev->bus)
 		    && bus == psdev->dev->bus->number
-		    && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
+		    && slot == PCI_SLOT(psdev->dev->devfn)
+		    && func == PCI_FUNC(psdev->dev->devfn)) {
 			pcistub_device_get(psdev);
 			goto out;
 		}
@@ -191,7 +192,8 @@ struct pci_dev *pcistub_get_pci_dev_by_slot(struct xen_pcibk_device *pdev,
 		if (psdev->dev != NULL
 		    && domain == pci_domain_nr(psdev->dev->bus)
 		    && bus == psdev->dev->bus->number
-		    && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
+		    && slot == PCI_SLOT(psdev->dev->devfn)
+		    && func == PCI_FUNC(psdev->dev->devfn)) {
 			found_dev = pcistub_device_get_pci_dev(pdev, psdev);
 			break;
 		}
@@ -360,7 +362,7 @@ static int __devinit pcistub_init_device(struct pci_dev *dev)
 	if (!dev_data->pci_saved_state)
 		dev_err(&dev->dev, "Could not store PCI conf saved state!\n");
 	else {
-		dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n");
+		dev_dbg(&dev->dev, "resetting (FLR, D3, etc) the device\n");
 		__pci_reset_function_locked(dev);
 		pci_restore_state(dev);
 	}
@@ -897,42 +899,35 @@ static struct pci_driver xen_pcibk_pci_driver = {
 static inline int str_to_slot(const char *buf, int *domain, int *bus,
 			      int *slot, int *func)
 {
-	int err;
-	char wc = '*';
+	int parsed = 0;
 
-	err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func);
-	switch (err) {
+	switch (sscanf(buf, " %x:%x:%x.%x %n", domain, bus, slot, func,
+		       &parsed)) {
 	case 3:
 		*func = -1;
-		err = sscanf(buf, " %x:%x:%x.%c", domain, bus, slot, &wc);
+		sscanf(buf, " %x:%x:%x.* %n", domain, bus, slot, &parsed);
 		break;
 	case 2:
 		*slot = *func = -1;
-		err = sscanf(buf, " %x:%x:*.%c", domain, bus, &wc);
-		if (err >= 2)
-			++err;
+		sscanf(buf, " %x:%x:*.* %n", domain, bus, &parsed);
 		break;
 	}
-	if (err == 4 && wc == '*')
+	if (parsed && !buf[parsed])
 		return 0;
-	else if (err < 0)
-		return -EINVAL;
 
 	/* try again without domain */
 	*domain = 0;
-	wc = '*';
-	err = sscanf(buf, " %x:%x.%x", bus, slot, func);
-	switch (err) {
+	switch (sscanf(buf, " %x:%x.%x %n", bus, slot, func, &parsed)) {
 	case 2:
 		*func = -1;
-		err = sscanf(buf, " %x:%x.%c", bus, slot, &wc);
+		sscanf(buf, " %x:%x.* %n", bus, slot, &parsed);
 		break;
 	case 1:
 		*slot = *func = -1;
-		err = sscanf(buf, " %x:*.%c", bus, &wc) + 1;
+		sscanf(buf, " %x:*.* %n", bus, &parsed);
 		break;
 	}
-	if (err == 3 && wc == '*')
+	if (parsed && !buf[parsed])
 		return 0;
 
 	return -EINVAL;
@@ -941,13 +936,20 @@ static inline int str_to_slot(const char *buf, int *domain, int *bus,
 static inline int str_to_quirk(const char *buf, int *domain, int *bus, int
 			       *slot, int *func, int *reg, int *size, int *mask)
 {
-	int err;
+	int parsed = 0;
 
-	err =
-	    sscanf(buf, " %04x:%02x:%02x.%d-%08x:%1x:%08x", domain, bus, slot,
-		   func, reg, size, mask);
-	if (err == 7)
+	sscanf(buf, " %x:%x:%x.%x-%x:%x:%x %n", domain, bus, slot, func,
+	       reg, size, mask, &parsed);
+	if (parsed && !buf[parsed])
 		return 0;
+
+	/* try again without domain */
+	*domain = 0;
+	sscanf(buf, " %x:%x.%x-%x:%x:%x %n", bus, slot, func, reg, size,
+	       mask, &parsed);
+	if (parsed && !buf[parsed])
+		return 0;
+
 	return -EINVAL;
 }
 
@@ -955,7 +957,7 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func)
 {
 	struct pcistub_device_id *pci_dev_id;
 	unsigned long flags;
-	int rc = 0;
+	int rc = 0, devfn = PCI_DEVFN(slot, func);
 
 	if (slot < 0) {
 		for (slot = 0; !rc && slot < 32; ++slot)
@@ -969,13 +971,24 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func)
 		return rc;
 	}
 
+	if ((
+#if !defined(MODULE) /* pci_domains_supported is not being exported */ \
+    || !defined(CONFIG_PCI_DOMAINS)
+	     !pci_domains_supported ? domain :
+#endif
+	     domain < 0 || domain > 0xffff)
+	    || bus < 0 || bus > 0xff
+	    || PCI_SLOT(devfn) != slot
+	    || PCI_FUNC(devfn) != func)
+		return -EINVAL;
+
 	pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
 	if (!pci_dev_id)
 		return -ENOMEM;
 
 	pci_dev_id->domain = domain;
 	pci_dev_id->bus = bus;
-	pci_dev_id->devfn = PCI_DEVFN(slot, func);
+	pci_dev_id->devfn = devfn;
 
 	pr_debug(DRV_NAME ": wants to seize %04x:%02x:%02x.%d\n",
 		 domain, bus, slot, func);
@@ -1016,14 +1029,18 @@ static int pcistub_device_id_remove(int domain, int bus, int slot, int func)
 	return err;
 }
 
-static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg,
-			   int size, int mask)
+static int pcistub_reg_add(int domain, int bus, int slot, int func,
+			   unsigned int reg, unsigned int size,
+			   unsigned int mask)
 {
 	int err = 0;
 	struct pcistub_device *psdev;
 	struct pci_dev *dev;
 	struct config_field *field;
 
+	if (reg > 0xfff || (size < 4 && (mask >> (size * 8))))
+		return -EINVAL;
+
 	psdev = pcistub_device_find(domain, bus, slot, func);
 	if (!psdev) {
 		err = -ENODEV;
@@ -1254,13 +1271,11 @@ static ssize_t permissive_add(struct device_driver *drv, const char *buf,
 	int err;
 	struct pcistub_device *psdev;
 	struct xen_pcibk_dev_data *dev_data;
+
 	err = str_to_slot(buf, &domain, &bus, &slot, &func);
 	if (err)
 		goto out;
-	if (slot < 0 || func < 0) {
-		err = -EINVAL;
-		goto out;
-	}
+
 	psdev = pcistub_device_find(domain, bus, slot, func);
 	if (!psdev) {
 		err = -ENODEV;
@@ -1339,8 +1354,6 @@ static int __init pcistub_init(void)
 
 	if (pci_devs_to_hide && *pci_devs_to_hide) {
 		do {
-			char wc = '*';
-
 			parsed = 0;
 
 			err = sscanf(pci_devs_to_hide + pos,
@@ -1349,51 +1362,48 @@ static int __init pcistub_init(void)
 			switch (err) {
 			case 3:
 				func = -1;
-				err = sscanf(pci_devs_to_hide + pos,
-					     " (%x:%x:%x.%c) %n",
-					     &domain, &bus, &slot, &wc,
-					     &parsed);
+				sscanf(pci_devs_to_hide + pos,
+				       " (%x:%x:%x.*) %n",
+				       &domain, &bus, &slot, &parsed);
 				break;
 			case 2:
 				slot = func = -1;
-				err = sscanf(pci_devs_to_hide + pos,
-					     " (%x:%x:*.%c) %n",
-					     &domain, &bus, &wc, &parsed) + 1;
+				sscanf(pci_devs_to_hide + pos,
+				       " (%x:%x:*.*) %n",
+				       &domain, &bus, &parsed);
 				break;
 			}
 
-			if (err != 4 || wc != '*') {
+			if (!parsed) {
 				domain = 0;
-				wc = '*';
 				err = sscanf(pci_devs_to_hide + pos,
 					     " (%x:%x.%x) %n",
 					     &bus, &slot, &func, &parsed);
 				switch (err) {
 				case 2:
 					func = -1;
-					err = sscanf(pci_devs_to_hide + pos,
-						     " (%x:%x.%c) %n",
-						     &bus, &slot, &wc,
-						     &parsed);
+					sscanf(pci_devs_to_hide + pos,
+					       " (%x:%x.*) %n",
+					       &bus, &slot, &parsed);
 					break;
 				case 1:
 					slot = func = -1;
-					err = sscanf(pci_devs_to_hide + pos,
-						     " (%x:*.%c) %n",
-						     &bus, &wc, &parsed) + 1;
+					sscanf(pci_devs_to_hide + pos,
+					       " (%x:*.*) %n",
+					       &bus, &parsed);
 					break;
 				}
-				if (err != 3 || wc != '*')
-					goto parse_error;
 			}
 
+			if (parsed <= 0)
+				goto parse_error;
+
 			err = pcistub_device_id_add(domain, bus, slot, func);
 			if (err)
 				goto out;
 
-			/* if parsed<=0, we've reached the end of the string */
 			pos += parsed;
-		} while (parsed > 0 && pci_devs_to_hide[pos]);
+		} while (pci_devs_to_hide[pos]);
 	}
 
 	/* If we're the first PCI Device Driver to register, we're the
diff --git a/drivers/xen/xen-selfballoon.c b/drivers/xen/xen-selfballoon.c
index 7d041cb..2552d3e 100644
--- a/drivers/xen/xen-selfballoon.c
+++ b/drivers/xen/xen-selfballoon.c
@@ -222,7 +222,7 @@ static void selfballoon_process(struct work_struct *work)
 	if (xen_selfballooning_enabled) {
 		cur_pages = totalram_pages;
 		tgt_pages = cur_pages; /* default is no change */
-		goal_pages = percpu_counter_read_positive(&vm_committed_as) +
+		goal_pages = vm_memory_committed() +
 				totalreserve_pages +
 				MB2PAGES(selfballoon_reserved_mb);
 #ifdef CONFIG_FRONTSWAP
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
index bcf3ba4..1bac743 100644
--- a/drivers/xen/xenbus/xenbus_client.c
+++ b/drivers/xen/xenbus/xenbus_client.c
@@ -44,6 +44,7 @@
 #include <xen/grant_table.h>
 #include <xen/xenbus.h>
 #include <xen/xen.h>
+#include <xen/features.h>
 
 #include "xenbus_probe.h"
 
@@ -490,7 +491,8 @@ static int xenbus_map_ring_valloc_pv(struct xenbus_device *dev,
 
 	op.host_addr = arbitrary_virt_to_machine(pte).maddr;
 
-	gnttab_batch_map(&op, 1);
+	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+		BUG();
 
 	if (op.status != GNTST_okay) {
 		free_vm_area(area);
@@ -571,7 +573,8 @@ int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref,
 	gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map, gnt_ref,
 			  dev->otherend_id);
 
-	gnttab_batch_map(&op, 1);
+	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+		BUG();
 
 	if (op.status != GNTST_okay) {
 		xenbus_dev_fatal(dev, op.status,
@@ -741,7 +744,7 @@ static const struct xenbus_ring_ops ring_ops_hvm = {
 
 void __init xenbus_ring_ops_init(void)
 {
-	if (xen_pv_domain())
+	if (xen_pv_domain() && !xen_feature(XENFEAT_auto_translated_physmap))
 		ring_ops = &ring_ops_pv;
 	else
 		ring_ops = &ring_ops_hvm;
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
index acedeab..88e677b 100644
--- a/drivers/xen/xenbus/xenbus_xs.c
+++ b/drivers/xen/xenbus/xenbus_xs.c
@@ -48,7 +48,6 @@
 #include <xen/xenbus.h>
 #include <xen/xen.h>
 #include "xenbus_comms.h"
-#include <asm/xen/hypervisor.h>
 
 struct xs_stored_msg {
 	struct list_head list;
diff --git a/firmware/Makefile b/firmware/Makefile
index eeb1403..cbb09ce 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -97,7 +97,6 @@ fw-shipped-$(CONFIG_TEHUTI) += tehuti/bdx.bin
 fw-shipped-$(CONFIG_TIGON3) += tigon/tg3.bin tigon/tg3_tso.bin \
 			       tigon/tg3_tso5.bin
 fw-shipped-$(CONFIG_TYPHOON) += 3com/typhoon.bin
-fw-shipped-$(CONFIG_USB_DABUSB) += dabusb/firmware.fw dabusb/bitstream.bin
 fw-shipped-$(CONFIG_USB_EMI26) += emi26/loader.fw emi26/firmware.fw \
 				  emi26/bitstream.fw
 fw-shipped-$(CONFIG_USB_EMI62) += emi62/loader.fw emi62/bitstream.fw \
diff --git a/firmware/dabusb/bitstream.bin.ihex b/firmware/dabusb/bitstream.bin.ihex
deleted file mode 100644
index 5021a4b..0000000
--- a/firmware/dabusb/bitstream.bin.ihex
+++ /dev/null
@@ -1,761 +0,0 @@
-:1000000000090FF00FF00FF00FF000000161000D7C
-:1000100064616275736274722E6E63640062000BB9
-:10002000733130786C76713130300063000B3139C8
-:1000300039392F30392F32340064000931303A34E5
-:10004000323A3436006500002EC0FF20175F9F5BF8
-:10005000FEFBBBB7BBBBFBBFAFEFFBDFB7FBFB7F61
-:10006000BFB7EFF2FFFBFEFFFFEFFFFEFFBFFFFF9B
-:10007000FFFFAFFFFAFFFFFFC9FFFFFFDFFFFFFF3B
-:10008000FFFFFFFFFFFFFFFFFFFFFFFBFFA3FFFBE4
-:10009000FEFFBFEFE3FEFFBFE3FEFFBF6FFBF6FF18
-:1000A000BFFF47FFFF9FEEF9FECF9FEFFBCF9BEE19
-:1000B000F8FEEF8FEEFBFE0BFFFFFFFFFFFFFFFFE2
-:1000C000FFFFBFFFFFFBFFFFBFFFFFFC17FFFFFFAF
-:1000D000FFFFFF7FFFFFFF7FFFFFFBFFFF7FFFFFB4
-:1000E000FC3FFFFFFFFFFFFFFFFFFFFBFFFFFFFFE7
-:1000F000FFFFFFFFFFFE5FFFFFFDFFFFDBFFFDFFD9
-:1001000077FFFDFFFFDFFEFDFFFFF2FFFFFFFFFFB9
-:10011000FFFDFFFFFFFDFFFFFFFFFFFFFFFFFFE111
-:100120007FFFFFFFFFFFFFFFFFFFFFFFFF3FFFFF1F
-:10013000FFFFFFFFE3FFFFFFFFFFFFFFFFFFFFBF2B
-:10014000FFFEFFFFFFFFFFFFFF67FFFFFFFFFFFF58
-:100150007FFFFFFF7FFFFFFFFFFFDFFFFFFF2FFF9F
-:10016000F3FDFF7FDEF7FDFF7FF77DFF7FDFF7BD4C
-:10017000FF7FFF1FFFEFFBFEFFBFEFFBFEFFEFFB6D
-:10018000FEFFBFEFFBFEFFFF3FFE7F9FE7F9FE7F15
-:100190009FE7FA7F9FE7F9FE7F9FE7FFFC7FBFBFE6
-:1001A000EFFBFEFFBFEFFBB7BFEFFBFEFFBFEFFBB9
-:1001B000FFE0FDF9FE7F9FE7F9FE7F9DF9FE7D9D43
-:1001C000E7F9FE7F9FEDEDFFFDFF7FDFF7FDFF7F8E
-:1001D000DFFDFF7FDFF7FDFF7FDFFF9BFFEFFBFE14
-:1001E000FBBFEFBBFEFFAFBBBEFFBFEFFBFEFFFFE2
-:1001F000B7BFDBF6BDBF6BDBF6F9BF5BD6F9BF6FF0
-:10020000DBF6FDBFFF0EFFFFFFFF5FFFF7FFFF7F86
-:10021000F7BDFFFFFFFFFFFFFFDF9FFFFFFFFEFFB9
-:10022000FFEFFEFEFFFF77FFFBFBFFFFFFFFF83F47
-:10023000FFFDFFFFFFFDFFFFFFFFFFFFFFFFFFFFD2
-:10024000FFFFFFF47FFFFEFDBEFFDFFEFFFFEF7F3E
-:10025000FFCFFFCFFFFFFFDFE6FFFF7FDFF7DD7F91
-:100260007FDFF7FF7FDFD7FDFF7FDFF7FFCDFFF2F7
-:10027000FFFF4F7FF4FFFFFFE7EFFFFFFFFFFFFFF1
-:10028000FFFFBBFFEFFFFEFFFFFFEFFFFFEFFFFBF7
-:10029000FFFFFFFFFFFFFF65EFFFFF7FFFFDEFFFAA
-:1002A000FFFFFEFFFFFFFFFFFFFFFFFECFDFFEFFB1
-:1002B000FFFBFFFFFFFFF3FFFFFFFFFFFFFFFFFF5E
-:1002C000FEDFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F
-:1002D000FFFFFFFFFFFEBFFFFFFFE37FFFFFFFFF0B
-:1002E000FFFFEFEBFFFEBFFFEBFFFC7FFFFFFFEE2B
-:1002F000FFFFFFFFFFFFDDFFD6FFFDBFFFFBFFFEA0
-:10030000FDFFFFFDEFFFFFFFFFFFFFDEFFFFFFFF32
-:10031000FFFFBFFFFDFF7FBFFF5FDFFFFFBF77FF77
-:10032000FFFF7FD7FFFFFFFFFFC3FFFFFFFFDFEFF1
-:10033000FFFFFEFBFFFFDFBFFFFFFFFFEDFFB7FF8C
-:10034000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD
-:10035000FFFFFFAF7FFFFFFFFFFFFFFFFFFFFFFF7D
-:10036000FFFFFFFFFFFFFFFFDFBFDFF3FDFBFF5BD3
-:10037000FDFFBFEFF7FFFF7DFFFFFFFFF83BFFBF74
-:100380006FFFFEFFBFFFEB7DFFEFFBFEFFFFFFFFF9
-:10039000FFF27FFCFF3FDFEDFEFFFFFFFFEF5FF7A8
-:1003A000B5FFEFFFFFFFE03F9F9EFFFFEFFFDFFF87
-:1003B000BF5FBFCFF3FFFFFFFFFFFF69AF33FDFF5D
-:1003C000FBFFFFFFFFFCFF7FD9FFDFFFFFFFFFF514
-:1003D000A3DF6EDEFFFFBDFFFFFEFFFFFFFEE7FDB9
-:1003E000FFFFFFF9EFC6FEB7ADE5F9FFFFFFCFFF57
-:1003F000FFFFCDFB7FFFFFFFF9F60FDFECCF7FFFA5
-:10040000FB7FFFFFFFFDFFFEF9FD7FFF7FFFF95B35
-:10041000FF73DCFD7BDFFFFFFF7BFFFFF753D6FFA2
-:10042000FFFFFFD89FFEFFEF7FEEFFFFFFFBEDED2D
-:10043000FDFFFEFFFFFB7FFFE27FFF6FD857F7FF57
-:10044000FFFFDFFFE8FFFFFDFFFFFC7FFFE4FFFB97
-:10045000EFFBFEDFB7EDFFFEDF7FFFFE7FB7FFFFA5
-:10046000FFFF89FFFFCFF3FE7FFFEFFFFE7E7FFBE5
-:10047000FFFFFFFFFFFFFFF1FFEB7AD5BF6FDBBE92
-:10048000FDB7D8F6E5BF6FFBFEF5BD7E06FFDFF7D3
-:10049000FBF6FF3FFFDBFFFF6FFBF7FFFFFFFBFEFE
-:1004A000F7AFFFB7EDEFF7FEFFFFDFFFFEFFEFFF58
-:1004B000FFFFFFBFF7FC1FEEFBFEBDFF7F5FD7FD19
-:1004C000FB43FFFFFDFF5FFFF7FFF93FFFCFF3FDAA
-:1004D000F77EEFA7F9FE8FA7E9F37E9FFBF8FFFFFA
-:1004E0003FFD7F5FDFFDFFFF5FFFFD5FFFFF7FFDE4
-:1004F0007FFD9FFFE0FFFAF8BE6F9FE6F8BE3F9AD0
-:10050000F9BE6F9FE2F9FE6F9FF9FFF5FD7FCFDF28
-:10051000FDFD7FFFF5FFFFFFF7F5FD0FDBFFD3FFCD
-:10052000EBFAFFFFBFFFFAFFFFCBFBFEFFFFEBFA8B
-:10053000FEFFFFB7FFFFFFFFBFFFDFF5FFFFD7FFA6
-:10054000FFFFDFD7F5FF7FFE4FFFFDFF7F7FFFAD92
-:10055000EBFBFFADFFFFFFFFAFEBFBFFFC0DFFFF72
-:10056000DFD2FDFFFFFDF6FFFF7FFFFF1FFFFFFF55
-:10057000FFFB3F7DEB32FEBF2FEBFAAEBDE0FA7E14
-:10058000BFADEBFAFEBFF57FFFDEFEE3FBFFFFFF33
-:10059000DFEF4FDFFF7FDFFFF7FFFFF87FFFFFEFAA
-:1005A000FBFFFFFFEFFFFFDFEDFBDFFFBFFFFFFF05
-:1005B00081FFFFFFFF3FFFFFFFFFFEDDFEEFFDFFBF
-:1005C000FFFBFEF7FF93FDFB7EFFFE87E9FF7FB396
-:1005D0009FFEFEFFAFFDFE7E3FFE67FFFFF7FFFFC2
-:1005E000FCF7DFFDFF7FFFFF7F6DFFFFFEFFFF2FAB
-:1005F000FFBFFFFFEEFFBEFFFFFEFFEFFFFFFEFFAF
-:10060000EFFFFFFA5FFFFFFBFFFFEFFFFBFEFDFFCA
-:10061000FEFFFBFFFFFF7FFFFEBFDFFFFBFFFFF7DC
-:10062000FCFDFFFFFFFFFF7FFFFFFFFFFFF27FFFEC
-:10063000FFFFFF7FFFFFFFFFF3FFFFFFEFFBFFFF6A
-:10064000FFDFE2FFFFFBFFFFFFFFFFFFFBE7FFFD19
-:10065000FFFFFFBFFFFFFFEDEFFDFFFFDFD7F5FD62
-:100660007F5DFDFF7FDF97F4FD7B5FFFC9FFFBFE32
-:10067000FFBFFF5FFFFFF7FFEFFDFFEFFFFFFFFF94
-:10068000FFF7FFD7FD7D7FFFFFFFFFEFDFF7FDFFE8
-:10069000BBFFFF7FFFFEE3FFF9FE7FBFEFFBFEFF27
-:1006A000BFF9FEFF9FEFF9FEFFBFF3DAFF37CDF38F
-:1006B0007CDF37CDF37F37CDF37CDF37CCF37F5A48
-:1006C000BDF6FDBF6FDBF6FDBF6FDEFDBF6FDBF676
-:1006D000FDBF6FFEF16FEB7ADEB7ADEB7ADEB7AF41
-:1006E0007ADEB7ADEB7ADEB7FF7EFFFECDB36CDB13
-:1006F00036CDB36CDECDB36CDB36CDB36CDFC9BFAA
-:10070000F7BDEF7A9EA7A9EA7AB7BDEA7BDEA7BD5F
-:10071000CA728D91FFEFFBFEFFBFEFFBFEF7EFFB11
-:10072000FEFFBFEFFBFEFFFE87FFF6FDBF6FDBF6B0
-:10073000FDBF6FF6FDBF6FDBF6FDBF6FFE4FFFBF66
-:10074000EFBBEEFBBEEFBBEFBEEFBBEEFBBEEFBB06
-:10075000EFFC5FFFFFFF3FCFF3FCFF3FCFFCFF3F0E
-:10076000CFF3FCFF3FCFFD9FFEBFAFEBFAFEBFAF65
-:10077000EBFEBFAFEBFAFEBFAFEBFFE16FFDFF7F1C
-:10078000DFF7FDFF7FDFFDFF7FDFF7FDFF7FDFFF8F
-:100790007ABFFBFEDFB7EDFB7EDFB7FB7EDFB7ED99
-:1007A000FB7EDFB7FFC9FFFFBFEFFBFEFFBFEFFB25
-:1007B000FFBFEFFBFEFFBFEEFBFEBBFFFEFFBFEF89
-:1007C000FBFEFFBFEFFEFFBFEFFBFEFF3FCFFFE7EC
-:1007D000FEFFF5FD775DD735DD77D7F5CD7B5DD7AE
-:1007E000F5DD77FE27FFFF8BE2F8BE2F8BE2F9AF36
-:1007F0008BE2F8BE2F8BE2F9FE1FFF5FD7F5FD7F7E
-:100800005FD7F5FF5FD7F5FD7F5FD7F5FFFA3FFEB6
-:10081000BFAFEBFAFEBFAFEBECBFAFEBFAFEBFAF83
-:10082000EBFFFE7FFD7FFFFFFFFFFFFFFFFFFFFFEF
-:10083000FFFFFFFFFFFFFFE6FFFADFF7FDFF7FDFB0
-:10084000F7FCFFDFF7FDFF7FDFF7FDFFF5FFFFFFA1
-:10085000FFFFFFFFFFFFFBFFFFFFFFFFFFFFFFFFAC
-:10086000FF02FFFEBFABEBFABEBF23EBDE1FAFEA1A
-:10087000FAFEAFAFEBFD97FFF3FC7B1FCFF1FC7FE0
-:100880001FF1FC771FCDF1FCFF1FFE87FFAFEFFAD2
-:10089000FEFFAFEFFAFDBF2BFB7EBFBFEBFBFBFB09
-:1008A000DFFFFBF7FFFF7FF7F7FFFDDFFEFCDFFF5A
-:1008B000DFFFFDFFDABFFFBBEFFBF9FFBEEFFBFB86
-:1008C000BFEFFBFEFFBFEFFBFFF77FFDD7FFFF7F13
-:1008D000FFFFFFFEF7FFFEFFF7FFFF7FFFFFECFFCD
-:1008E000FFFEDFBFFFFBFEFFBB68AE1FAEFBFBFFE3
-:1008F000FFBFFFD5FF7FFFFFF7FEFEFFBFEF9FFDAE
-:100900007FFFCBFFFFDFFFFFBBF7BFFFFFFFFFDF77
-:10091000FFBFFBFFFFFFDE3FFFFFFFFFFFA7FFFF64
-:10092000FFFFEFFF7FFBFDFB7FFFFFFFFFCFF37CB0
-:10093000FF7F8D7FFFFFFFFFFBFFF7FBFEFDFFFF4C
-:10094000FFFFF7FDFF7FFD1FFDFFFFFFFFBFDFFF85
-:10095000FFFE5CFF6DFF7FABE7F1FFFD9FFFFFAD8B
-:10096000EB7A3F1FFFFFFEBFAFF3DEF5FF8FFBDF2C
-:10097000E67FFFDFF3FDFF7EFFFFFFFFFFFDF7F3E5
-:100980007FDFF7EFFFF63F9FDFFFFFEEFFFFEFFB9D
-:10099000FFFFF9FBFE4FBFEFBBFF69AFAFFCFF3FAF
-:1009A000DDFFFCBF8FFFFDF3BFED9EFCBF6FF5D3F6
-:1009B000DFFFDBD6F5EFFDFEFFB9FF1FD2A9AFFFCA
-:1009C000DBF7BFEF46FFFFADEB7ADFEFF7FF7FF717
-:1009D0009FEDFF7FFFADEB7FF56FFFFDFBD6F4F7DB
-:1009E000FBF97E7FFF5FC2FEBFFDFB33DFF95BFFDC
-:1009F000FFDD677DCFEFDBECFF77DDF7FDFFFFDE8F
-:100A0000A7BFD49FFFFFBFEFFEFFDFEFBBFFFFEFEE
-:100A1000EBFAFFEFBDFBFFE27FFFDFDFF7FDBFBBC0
-:100A200073F7FD7FDFDEF7BFEADBF6FFD6FFFF6679
-:100A3000FFBEFFBF6BD9F6DFFFFB7E7FB77EFFFEF9
-:100A4000FFCDFFFE7FFFFCFD3FFBFBF7FFFFFBF64B
-:100A50007DFE7FFFFCFFB9FFF9FAFEBFAF5BD6ED6D
-:100A6000AD7BF6F9BFEFF8FAFEBFFEE6FFFFF7FD3C
-:100A7000FF7FBFEFF3FFFF6FF7FEFFFFF7FDFEF70E
-:100A8000EFFFFBEFFB7EDEFEFFBFFFFEFFFFFBFF86
-:100A9000FFEFFB6FFC1FFEE7FFFFFFEFFFD3B4BBD1
-:100AA000FFFFFDBF6FE3FEFFBFFCBFF7CFF7FDFF0A
-:100AB0002FDFABEAFFDFE7EA9AAFEFFBFEFFF53F80
-:100AC000FD7EFFD7F5FBFFFDF7FF7FFEF7FDFFD7AC
-:100AD000FFD77FEE7FFA79FE2F8BE6F9FE3F9EF976
-:100AE000BE2F0BE7F9FE2F9FFDFFFE7D7F5FD7FF37
-:100AF000FF7FFFFDFF7F5F97FFFD7F5FFFE3FFFF4E
-:100B0000FAFEBFAFFBFBFFFFCFEBFEBFAFFFFAFE6E
-:100B1000BFFF87FFFFF5FFFFFFFFFDFF7FFFFFFF29
-:100B2000FBFFFFF5FFFFFE0FFFFDEBFFFFF7FFEF02
-:100B30007BDFFEFFFFDFF7FDEB7FDFFF5FFFFFFFE8
-:100B4000FFFDBFFF7EFABFC7DBF7BD3FFBFFF6FF30
-:100B5000FAAFFFEBFAFE3F2FEAFA3EADC9BAF6ADA7
-:100B6000AFEBFAF6BFFE7FFFFFFDFFF17F3FCFF156
-:100B7000EFFF7FFFBCDFDFF7DDFFE07FFFFFFEFF62
-:100B8000FAECBB7F5FFFFBECFFEFB7FFF7FFFFB5B2
-:100B9000FFFF7FFFFFFFEEDF5FDFDEFFAEE777FFE8
-:100BA000FFDFF7FFE3FFFABBFEFFAFFDFBFEBFABCE
-:100BB000F9FEFFBF7FBFFEBDFED7FF9FFDFFBEEF6B
-:100BC000FFEEFDBB5BEFFF7FEFFFEFFF7FFF4FFF10
-:100BD000EFFBBCFCFFFFFFFEFEFDFAFEFBFFFDF39B
-:100BE000FBFFF85FFFFFD7F5FDDFEFFFF3DC5FCE24
-:100BF000F5BDFFFFD7FFFFF93FFFDFF7FFFEFFFD6A
-:100C0000FFFBFFF7B97DFEDFFFFFFFFFF97FFFFE70
-:100C1000FFFF7FFFFEFFFFF7F6FFBFF1F8FFFFFFCB
-:100C2000FFE0FFFFFFFFF9FFFFFFFFFFEFEFFFFF19
-:100C30009BFB7FFFFFFFC1FFDFFF3F5FD7BFEFBB26
-:100C4000DEEEFF7FDFFFFEF57FDFFF99FFFFFAFF9C
-:100C5000BFFDEB7AFFB7FEFEFFFFEFFFFFFDBFFF1B
-:100C600097FFFDF7FF7FF7FFFFFD5FFEF3F9DFDF83
-:100C7000FFFFFCFFFF83FFFFFEFF9EECFBEEFF9FED
-:100C8000BFEFFFFEED7BFFFFFFF15AFFFFFDFF7C93
-:100C9000693BDFFF7F1FDFFFFDBAFFFFFBFF5BBD8F
-:100CA000FFFFFFFFD7B6EDE9FFD6BD6F5FFBFFEF9C
-:100CB000FF5FFEF66FFFFFFFFFF7EB7ADFFF9F7F1F
-:100CC0007FFFB7FFFFFEDFFF6CFFFBFFBB6FEBFE9D
-:100CD000CCF7A5FA5CF575BBB7DFFE6F5FC5BFFD4E
-:100CE0007BFEFF95E729CF4FF591EE6BDFEFFD54CB
-:100CF000F5BDB1FFEFEEFBBEBFAFFEDEBD6FDAF2BA
-:100D0000FFAFBEFFFFFD7EA7FFF7FFBFEF7BF6FD46
-:100D1000BD4AF28585BF5BFEB5FDFAFF4FFFFEDFE2
-:100D2000FFEDFFBFFFBF7FFEFFB76DFFF7BFBFEF58
-:100D3000FD1FFFFE7DFF67FFFFFF3F7FFEBFFFE759
-:100D4000DFE7FFEF6BFC1FFFBFEFFBFEDEBFAFFA7D
-:100D5000FFB6EFF9FEFF8FEFDBEFAB6FFBFEFFFFA0
-:100D6000EFFDFF7FFFFFDEFFFFEFFFFFFF3FFF6CA9
-:100D7000FFBFFBFFFEFFFBFEDFFFFFEFFFFFBFFF3D
-:100D8000FFFEFBFFD57FFFFFEFFBFFFFBFEF43B58C
-:100D9000FD6FCFD6BE3F7FDBFEC3FFFDFFAFEBFB9A
-:100DA000FCFF3EEFE8FABDCDAAFEFE7DCFFFB7FF08
-:100DB000F7FFFFFFFDFF75CD52D7FDFBF7DDFBEF22
-:100DC000EBFFFF4FFFBF9FE7F9FC7F8BC3F9AF8FAE
-:100DD000E7E9BE7F9FE6F9FC5FFFFFF7FDFF7A5F63
-:100DE000D7EDFFFFD7FFDD7FE7FFFCFFFC3FFFFFF5
-:100DF000FFFBFFFEBFAFFFFDFFEFFFEBFFFFFFFFBE
-:100E0000FFF77FFF7FDFFFFDFD7FFEF7FD7FDFFF49
-:100E1000FDFFFFDFFBFFEEFFFBFFF7FDFF7ADFF5D6
-:100E2000FDFADFF7FCFF7FDFBFEDFFC9FFDFFFBF8C
-:100E30002FFBFFBCADFFF7FFFFEFD3FF7DBF6FFFC1
-:100E4000FAFFFEBFAEEAFABEADA5EBCEBFA7EB5AE6
-:100E5000DEBDAF6BFD57FFFFF47F1F7FFDFF7F36C9
-:100E6000F0DF79FFFFFFF7FDBFFF87FFFBF3FCFF1C
-:100E7000FFFFFF7EFFBFDFFFFFFFFFFFFDBFF89F0C
-:100E8000FFFFFFFFBFFFFFFDF7FCBDFFFEFFFFFF02
-:100E9000FFFFFBF9BFFFFFEBE2FEFFBFEFA9BA2F99
-:100EA000EBF9FE77DFF7FFFFF97FFFFF7FEFD7FF5B
-:100EB000FDFFFBF5FFBF6FDFFFFFFDFFFFF0FFFF53
-:100EC000FF3FCFFFBAEE9BBFEED7FECDEFFFDFBFF8
-:100ED000FFFFC5FFFFFD7F4FFDF6D9FF4FD6FDBFDA
-:100EE0006EFFFFF47FFF7F8BFFFFFFFFF7FFF9FE31
-:100EF00037FFD9FBF5AFFDFFFFFBFFFF07FFFFFF4C
-:100F0000FBF7FFFDFF7CFA7E4FFCDF1DC7FFFFFFF5
-:100F1000FFAEFFFFFFFFFDFBFFFFFEFEFCFF7F7F3D
-:100F2000BFEFFEFFFFFF5FFDFFFFFFFD6F5AD77BA7
-:100F3000BE5FFE39FFF7FFF7FDFEAA1FFFFFFFFFB1
-:100F4000FEFEABAFFDFEBFFFF7FF7FFE8FE3FBEEC4
-:100F50007FFFFFFFFFEBFBFFFDBFEFDFFFFFFFFFAB
-:100F6000FFFFFFFBE43FFFDFFFFFFFFFF3EFBBFBF4
-:100F7000BFEFBBFFD7BFFFFFFF29AFF7FFFFFBFFAF
-:100F8000FBE6FF0FFB3FDF0FFFAFFFFFFFF5C3DF08
-:100F90005FFFFFFFFE6BCABEBCFF9FF2BFFFFEFA02
-:100FA000FFFFEF16FFFFFFFFFFFCDF97FD79FF3725
-:100FB000E77FFFFFB5FFFFF62FFFFDFBFEFFFFFD05
-:100FC0005F575FFFDB52DFFFFDBFFFFFFCDBFF7BF7
-:100FD000B5FD7FFF719C6EFFF635A59BFFFFFDFF02
-:100FE000FFDB9E7FFEEFFBFFFFBDEFFFDEB7F94BA0
-:100FF000FFF5EFFFFFFFE87EFFEADFF7FFFD695B2C
-:10100000FC9FEF78D6FFEBEFFFFFFFE8FFFFEDFF60
-:10101000FFFFFFE3F9F6BFFFFFFEDFFF7FFFFFFFEC
-:10102000D1FFFFE7FFFFFFFFE7F9FFBF7FD9FFFD1C
-:10103000FE7FFFFEFFF9FFFBD6DFBFEF5BD6FFBFF2
-:10104000FBF6FFBFEFF8F6DDBEFE16FFBFEFFFFEBB
-:10105000FFBFEFFFFFFF6FFBFFFFFF6FF3FFF7EF38
-:10106000FBFFBFFFEFFEFFBFFFFFFFBEBFFFEFFFB6
-:101070007FEFFFFD17FB7BFFFFFD7FDBF6F47FFAC1
-:10108000FEF5BFEBE3F7FFFFE9BFFFAFF7FDF37E30
-:101090008FA3EAFFCBF3EEFFBFEFF7F9FFFE7FFF71
-:1010A000FFFFFFF5FBF6FFF52FFEFBD7BFFFBEDF0F
-:1010B0009FFFF0FFFFF9FE7F8FA3F8FE6F9FF9F609
-:1010C0002F9FE7F9FE2F9FE1FFFFFF7FDFF7F5FD81
-:1010D0007F7FF5FF9F5FFBFEFF7FFFFFCBFFFFFBE7
-:1010E000FEFFBFAFFBFEFFDFFEFEBFF7FFFFFFFF10
-:1010F000FFC7FFFFFDFF7FDDF7FDFFFFD7FFFD7F90
-:10110000FFFBFDFFFFFEEF7FFDEFFBFEFBFDFF7F23
-:10111000DFFDFF7ADFF7FDFFFFFFFF1FFFFFD3F7C4
-:10112000FFFF6FDBFFFFEFCBF4FFFFFFFFFFFFFED3
-:1011300029FFE8DA769FAF6ADAFE35EBDAD6BFAB85
-:10114000EB7ADEBFD77FFFFEFFBFEFFDDF77BFFD8E
-:1011500037EFFFEFFF3FFFFFFFFE7FFFFFFFF77E51
-:10116000DFFFFFFFFAB77FFFFFFEFFFFFFFF89FFF3
-:10117000FFFFFFFFFFFFFFFFFF9FFBFFFFFFE7FFFB
-:10118000FFFFFFAAFFABFBFAEFBFFFDFFA7BB9FE61
-:10119000FEFFFDFFF7FE3FFFB7FFF7EEFF7FEFFF1C
-:1011A000FF7FFF1FFBFFBFFBFEFFBDFFFF2FFFBF4A
-:1011B000FF7FDFFAFFFFFCEEF5F3BEFB0FEFF3BEA0
-:1011C000EFFC5FFF5AFFF7DFFFFFFED5FC5FFBF28E
-:1011D000FFFF2FBBF3FFFFBFFFEFFFEFFFFFFFFF9F
-:1011E000BFFFFFFD7BFFDFB9FFFBFFD87FFFFFFFE6
-:1011F000FBFFFC7F1FBFE0DFF7EFFFFD7FFEDFFFA0
-:10120000E0FFFFFDEFFBFFFEF7DFFFEB5FFFF7FF08
-:10121000FFFFFFBFFFFDFFFDFFFFFFF7FDFF3BDC13
-:10122000FD6D7B5F57F5FD7F5FFFB1FFEBFFFFFFBC
-:10123000FBFBFEFFBFFBBEFFBFEFFBFEFFAFFEF7FA
-:10124000DFDFFFFFFF7FCFF3F8FFD7FBFF5FBFF7C5
-:10125000FBFF7FFE23FFFFFE7FF3FFFBFEFFFFF39D
-:10126000FFFFF5F9FF3FFFFFF09AFFBE7FFFFCF99C
-:10127000FFFDAFEBFEBFFFCFF3FE7FFFFF5BBDFFC8
-:10128000BCEBFFD7D4AFAFFDFFCFF7FDFF7FDFF79C
-:10129000FDFEFF6FFFFBFFFFFFFD7F5EFDBFDBF687
-:1012A000FDBF6FFBEEFDFF7AFFFAFBFF3FFBB75F71
-:1012B000D6F71F71DC771DC731DC77DFF9BFF55B2F
-:1012C000F4D79DAEFFBFFDBFDBF6FDBF6FDBF6FEC3
-:1012D0003D81FFEBFEFEFEFFEB7ADF7D777DF5794A
-:1012E000DF57DDF57D7EE6FFD63FBF7FFFD4F53FBC
-:1012F000BFFBBEEFB3EEFB9EEFBBFE8BFFFEDFB787
-:10130000EDFFF7FDFEFFEFBBEEFFBEEFBBEEEBFC2C
-:101310001FFFFFFDFFE7FFF7FDFFEFFEFFBFEFFB46
-:10132000FEFFBFEBFA1FFFB7EF5BFEFFAFEBDDE7A2
-:10133000DE779DE779DE779DBFE66FFFFEFFBFEFAB
-:10134000FBFEFDBF6FF6FDBF6FDBF6FDBFFF7EFF4F
-:10135000FFFBFEFEFFEFFBFDEF7EF7BDEF7BDEF751
-:10136000BDEFFFD5FFBFFFEFFEFFFC3F0FE7FE7FA6
-:101370009FE7F9FE7F9FE7FEF3FFFEDFADDF67EE3D
-:10138000FBBFEFFEFFBFEFFBFEFFBFEFFF23FFFF43
-:10139000FFFF7FFFF3BCDBFEFBFFFBBEF7FBFF7F26
-:1013A000DFFFCFFBFF9FE3F9BE3F8FE779FF9DE7AC
-:1013B000F9FE7F9FE7F9FE5FFFCFF7FFFFFFDFF743
-:1013C000FE7FE7F9FE7FFFFFFBFEFFFFBFFFBFBF12
-:1013D000FFFEFFBFEFFFFDFFFFFFFFFFFFF7FDFF7A
-:1013E000FF3FFFBFFFF7FFFF7FDFFFFFFFFFFFFFB5
-:1013F000FFFFFFFFFFE8EFFF5FF7BFF9FEDFB7FD7D
-:10140000FFDFF7FDFF7FDFF7FDFFDDFFF2FFBFFF2F
-:10141000FFBFFFFF2FF2FFBF2F7BD2F7BF2FFFBB16
-:10142000FFEE8FAFEBFAFE3FA769CE8FA4EAFAEE8C
-:10143000B7AEEBFDC7FFF7F7FFFFFFFFFF7F3EF300
-:1014400074FF3F4FFFE7FF3FFEA7FFFFDFF7B7FF48
-:10145000F7FFBAEF37EBFBFEBFFBFEF3FFF9DFFF51
-:10146000BFFFFFFFBFFFFFFFFDDFFFFDFFFFFBFE35
-:10147000FDFFFBBFFE3FEDFFDFBE3DA7FBFA3FE6F2
-:10148000E1FEFE3FEFE3DFF57FFEFF7EFFFFFFFFA4
-:10149000EF6FF6FF7DEFD7DEFF7DEFFFF2FFFFFF7F
-:1014A000FFFFFF7BDEFBE6EEEF376EF37EEB37EF01
-:1014B000FFC1FFFEFFF7EFFFFFFFBF3FD2DFBF2FF0
-:1014C0007BE2FFFE3BBDDBFFFEFFFFFFFFFFEFFE0A
-:1014D000FFFBFFFFBFFFFBDFFFBFFFB7FFFFBFEF5C
-:1014E000FFFFFFFFFFFF0FFF7FFF1FEFF1FDFFF685
-:1014F000AFFFFFFFFFFFEFFFFFFFFE9FFFFFFF7745
-:10150000EFF7FBFFFE5FFFFFBFCFFBF7DDF7F5FF58
-:101510005FD5F5FD7F5FD7F5FFFB0FFFFFA9EA7AE7
-:10152000FFAF8FFEDFAFEFFBFEFFBFEFFBDFE55F3F
-:10153000FFFFFFFFFFBD57FFFF6F77BFF7FBFF7F89
-:10154000BFF7FFFCBFFF9FFFFFEFFFFEFFFFFF1F87
-:10155000CFFFFCFFFFFFFFFB65AFF37CFF3FDFFF2B
-:10156000FDE9FE7FE7FFFE7FFFFFFFFFFDE3DFFBFF
-:10157000DBF6FDEF5BFBFFDFFCFF3FDFF3FDFF7FF3
-:10158000DFEF66FFDFADEB7ADEF7F7E7D9FD9F67A8
-:10159000D9F67D9FE7DFF547FD655BD6F4FEFFEFEB
-:1015A000FF6DF6DDB76DDB76DCB77DFA9BF66D9DE2
-:1015B0006759DFF7DDFFEBFEBFAFEBFAFEBFAFE32E
-:1015C000D19FFFBDBFEFFEF7BFBFF7D77FDDF79D10
-:1015D000DF7FDFF7FFE07FFDC1DFF7FDC77F7FFB28
-:1015E000FFBBECFB3EFFBFECFBFFD87FBF6CFFBE39
-:1015F000FFBFEDFFEFFEFBBFEFFBFEFFBFEEFFC542
-:10160000FFAF6FFFFCFD3FE7FFFEFFEFFBFEFFBFFD
-:10161000EFFBFEBF89FEFABAFEBFAFFBF6F5D97D40
-:101620009765D9745D9765D3FED6FFBFF7FDFF7F41
-:10163000BFCFFBFEFFEFFBFEFFBFEFFBFFF68FFB15
-:10164000FFEFFB7EDBFEFFBEEFEEFBBEEFBBEEFB74
-:10165000BEFFFFDFFF43FFFFFBEF5FB7FE7FE7F952
-:10166000FE7F9FE7F9FE7FF9BFFEAF77FDFF2FAF4B
-:10167000A7FEFFEFFBFEFFBFEFFBFEFFF17FEFDFFB
-:10168000FF97F5EFFFDFFFFFBFFFBFFFFFFEFFFF8D
-:10169000FFE0FFFFF9FE2F8BE3F8BE779FF9DA77C3
-:1016A0009DE779DE779FDDFFFDFD7F5FD7FDFF7F43
-:1016B000E7FE7F97E7FBFEFFBFEFFFABFFEFFAFE12
-:1016C000BFAFFFFAFFFFDFFFFBFFF7FDFF7FDFFF8D
-:1016D00067FFF7F5FFFFFFDFFDFFFFFFFFFFFFFFE6
-:1016E000FFFFFFFFFFEFFFBDEBFFFFF7ADEBFFDFFE
-:1016F000FDFF3FDFF7FDFF7FDFFF5FFFF7FFFFFD30
-:10170000BFFFCBF4FF7FD3F7FD3F7FD3F7FFFC3F55
-:10171000FFEAFABEAFABEBBAF4956B52D4AD2F4AE9
-:10172000D2F6BFD27FF73FFFFFF37FFFFFF7FFBA8D
-:10173000DFFBFDFFBFFFFBFFF87FEAFFFEFEDFFFE1
-:10174000F7FF7FBBFFFFBFDFFBFFFFBFFFB17FFFE7
-:10175000FBEFFFFFFFFFFFBFCFFEFFFFEFFFF7FF36
-:10176000FFFFF1FF69BEFABFAFE2FFFEFDAFF3FE80
-:10177000FFBFEFFBFCFFFF07FD95DBDF7FDFAFFF68
-:10178000F7AF36FEBF65EBF6FE9F6FFE07FFCFFF9C
-:10179000F8FEFFCFFFF6FAE7FBFEFFBBEDF9FFFF18
-:1017A000FF5FFFFFFF75FFEF7EFDE0E85ED3E5F929
-:1017B0003E5FD7F7FFFA2FFBFFFFFFFFFEFFFF7F24
-:1017C0007FD7F57D5F57D5F5EFFFF37FFC7FFFC730
-:1017D000F1FFFF1FCFB0FF3FCFF3FCFF3FCEFFE491
-:1017E000FFDF7FFEF7BBFFFFDFEFEEFFBFEFFBFE8C
-:1017F000BFBFEFFFD1FFFFFFFDFBFFFDFFFB9FE939
-:10180000FE7F9FE7F9FE7FBFFFB3FFFFF7FFFFAF4C
-:10181000F7FFB63FEBFAFEBFAFEBFAFEBFFEA7FF46
-:10182000FFFFFFFFF7FFFFFFFE9FF7F9FF7F9FE737
-:10183000FFFFFEAF6FFFFFFF9FFFDFFF7D5FDDFF5D
-:10184000FBBFE7BBFFFBDF6D5F7EFFFFFFFFFFFF1F
-:10185000EBF7FFE7EFF7FFFF7FFFF7FFFC8FFFEFEF
-:10186000FDFEFFBEF4F27DD7CFFF3FFFFFFFFFFF7E
-:10187000FFCF6BFFBF3FFBF2FC7FEBFF9FFAFFFF49
-:101880003FFFF3FFFFFD70F7FFFFBFFFFBD7FEF544
-:1018900077FF15DD77FDFF7FDFF7FBCDBFFFFDFF96
-:1018A000FFDF37CDF9ECFEEFBBF4FB3F4FB3FFFD9D
-:1018B000CBFFE97E549FE54BB7FFDD7DC771DD7738
-:1018C0005DD775CD7FD6FFD3F6F93F6D95AF7FFE1F
-:1018D000FFEFFBFEFFBFEFFBFEF6C7FFAD7BCAFFCE
-:1018E000BFBFEFFDE3DFB7EDFB7EDF37EDE3FBDFEF
-:1018F000FF525C15FDCF7FDFFEEFEFFBFEFFBFEC7D
-:101900007BFEFFFE3E7FDAF7FDFF7FFFFFFBEFBBB5
-:101910006FFBFEFFBFEFFBFFF77DFFD8FFFDBF7F33
-:10192000FBFFFF9FFBFE7F9FE7F9FE7F9FEA7FF6AD
-:10193000BFBD6A5AF6E5BF775F6DDD775DD775DDB0
-:1019400077FFA5BFCFFBFFFFBFCFFBFDFFBFF3FEC0
-:10195000FFBFEFFBFEFFFDABFFBFBFFFFBFF7FEF56
-:10196000FFBEFBEEFBBEEFBBEEFBBFFFB5FFD0BC87
-:10197000FD2F4BF7FFFF9FF9FE7F9FE7F9FE7F9F4B
-:10198000FA8FFDABFADABFAFB3FDFFBFFBFEFFBFBF
-:10199000EFFBFEF7BFFF9FFF77F7BDFD77DFFF7E11
-:1019A000DFEDBBFEFFBEEFFBFEFFFA3FFFBE6F8F1A
-:1019B000E6F9FE7F9FC7FE7F9FE7F9FE7F9FE7FB6B
-:1019C0007FFF7FCFFFFDFFFFDFFBAFBFEFFFFEFF1E
-:1019D0009FEFFBFFFCFFFBFEFFFFFFFFFEFFFFF79C
-:1019E000FFFFFFFFFFFFFFFFFFF5FFFFFF3FDFF7F9
-:1019F000FFFF7FEFFEFFBFFFFBFFFFBFEFFFB37FE8
-:101A0000FF7B5EF7FDFF7B7FF7FF7FDFF7FDFF7F4B
-:101A1000DFF7FF17FFFFFF7FFFFFDDF6FCBFCBF215
-:101A2000BCBF2FCBF2FCBFFE8FFFFA7EBFA7EBDA65
-:101A3000FCBFAF7AFEBFAFEAFAFEBFAFF4DFFEFF36
-:101A4000F33C7F3EFFCFF8BF8FE3F8FE3F8FE7E820
-:101A5000FFFC9FFFFFCFEBB3E7FB7BF3FEFFCFDB8A
-:101A6000FBFBBF6F6FDFEC7FFFFFF7FDFDFFFFFFAD
-:101A7000FFB2BFFFDEFDBDEFFBF6DFEAE7DBFEBB3B
-:101A8000FFEBFBBF9F8FE8FE3F8FA3F8FE3F8FFF6A
-:101A9000F87EFDFD7FFFFBCDFFFDFF5FEFFDFFFF4C
-:101AA000DFF7FDFFBE90FFFFEEFF3FBFF3BBFEB7CA
-:101AB000ABFAFEAFADEAFADEABFF63FFFEF2FFB3B7
-:101AC000FFDFEE7DFF03F1F43F1FC3F1EC7FFE6FFC
-:101AD000FFFBFBFF9FFFBFFF7B5FFDFFDFF7FDFD10
-:101AE0007F7FDFFECFFBFFFFAFFBFF1FEFA5FDBF3B
-:101AF000DFFB7DFFBFDFFBFFFD3BFFFFFFFFFFFDC8
-:101B0000AFF3FFFB7FBFD7FBBF7FBBF7FFF87FFFC4
-:101B1000FA5FD7FFDF7FEFFFFF7FDBF7FDFF7FDFA0
-:101B2000B7FBECFFFFF7BFEFFDFCFBFFEFF0FE3F65
-:101B30008FE3F8FE3F8FEF8DFFFFEF7FBFFFFBFFCF
-:101B4000DBBFFFFFFFFFFFFFFFFFFFEFD8FF2E7F91
-:101B5000BEEFFE6EFFBFF9FFFFF3FFFFFFFFFFFFCA
-:101B6000FC66BE47F37FDFFE879FFFFFFFFFE7FFB7
-:101B7000FFFFFFFFFFD66F7CFB4FD2FFFD2BFEFF69
-:101B8000FFFD5FD7D5F57DFFFFFFBF9BFFFFDFB7F1
-:101B9000FFFFDFFF3FCFFE7FBFEFFBFCFF3FFFD923
-:101BA000BFFE97EC8FB7FE9B7DFDB7DD771DC7713C
-:101BB000DD775DD7F36FFD3F73DDAFFD7AFFFFAFDC
-:101BC000FEFDBFEFFBFEFFBFEF667FFFFFBFBFFF66
-:101BD000FBFFF7DFFDFB7DDFB7CDF37C5F3F913F80
-:101BE000FF3DEF7BFFFCFFCAEFFEFFBDEFFB1EE7F3
-:101BF000BBEC7FB3FFFD9FFFFFFEFFFF7FBFFBFE40
-:101C0000FFBFEFFBEEFBBFDF67FFFFBFEFDBFFBCFC
-:101C1000FE7FFBFF9FEFF9FE7F9FE7F9FE87FFEE58
-:101C2000FBBEE5BFEFF9D765F7DDE77DDF775DD771
-:101C30007FF89BFEFFBFEFFBFFFFBFEFFBFF7FCFF8
-:101C4000F3FCFFBFEFFFDB3FEFFBFEFFDFFFFEFB21
-:101C5000BBEFBFEFBBEEFBBEEFBBFFFC7FFD3B5B13
-:101C6000D6E5FD4FC3FBFFBFEFFBFEFFBFEFFBFF62
-:101C7000B4FFFABC8FB2E9D22ECFFBFFBFEFFBFE61
-:101C8000FFBFEFFBFFECFFFDFD7FDFF7E4DF5FFF52
-:101C9000FFFBFFFFFFFFFFFFFFFFC3FFEFE6F8FEC5
-:101CA0003F8B83F9FE7FE7F9FE7F9FE7F9FE7F1701
-:101CB000FDFFFFFF7F5FF72CFFFFFFFE7FFFE7F9D0
-:101CC000FE7F9FFE2FFFFFEFFFFEBFEFADFFFF7F09
-:101CD000FFFFFFFFFFFFFFFFFEDFFFDFFFFDFD7FD9
-:101CE000DFF7FFFFFFFFFFFFFFFFFFFFFFFA3FFEF2
-:101CF000F7FDEF7AFFB1BDFF7FF7FDFF7FDFF7FD57
-:101D0000FF7FF327FFDFFFDDFFFC9BFFCBFCBF2F37
-:101D1000CBF2FCBF2FC9FFDEFFDFAFEBDAFEBBAFBC
-:101D2000EBF8F7AFE8FAFEBFAFEBF2FFFDFFFFEF16
-:101D3000BDD7BFFFFFDE8FB8DE378DA378DA3F8FC8
-:101D4000FFA1FFFFFBFBFFFFFFFFA7BDFB76FDBF72
-:101D5000EFDBFEBBBFFE277FFFFEFEFDF5FFEFF5CD
-:101D6000DF1FE7FDFF7FDFF7FDFFFFCDFDAEFFFAD1
-:101D70003E3FABFDF87E8FE3F8FE3E8FE3F8FFFEBB
-:101D80001FEFDFBFFEDEDFD9FFDFBCFFFF7FFFEF0E
-:101D9000FD7FDFF7F93FFEFFFF6FFEDEBFF7EDEAE5
-:101DA000FD8F83F8EA3F8FEFFFF47FFFEFEF7BF3C8
-:101DB000F15FFFFFF13B7FDFF7FDFFFFFFFFE0FF7C
-:101DC000FFFFF7FF6FFF7FFFFFF7DEF7BFEFFBF7C8
-:101DD000FDFFFFF5FAFFFFFBE7FFF3F87FF3DFFFFF
-:101DE000FFFFFFFFFFFF1FEFBBFFFFFFFFFFFFFD39
-:101DF000FF7FFF9FFFFFFFFFFFFFFFCFFF37FFFFCB
-:101E00007FDF775DE7FCFFBFF7F5FBFFFFD7F5FB53
-:101E1000FFFF45FD7FEAFDBEBFDFF7FFFFDBFBFEF7
-:101E2000FFBFEFFFFFFFFB5F7FFFFEFFFFFFFFFF37
-:101E3000FFFEFFEFFDFF7FDFFFEFFBF80FF3FFF982
-:101E40002EFBFEFCF3EFFFFFBFFFFBE7FFFE7EFF75
-:101E5000C06BCFFF34DFF1FDFFEFFFFFFFDFF7FDCA
-:101E6000CF7F9CFDFD6CF7FFF6FDEB2B9FFFFCFE8B
-:101E70007EFFFFFFFFD7F3F7FFFBE1BFFFEB7ADE4B
-:101E8000D7FBFFF9FEFFFFF3DE7FFDE77FFFFDBB22
-:101E9000FFFF7ECCF6AF5F7FFEF47DF7FDBB6EDB10
-:101EA000B7FFF7DF66FFFFF73DCFDEBDFFFFDEDBED
-:101EB0008DF77EDFB7EF7FFFF687FFFFEFFEDEBF18
-:101EC000FFFFFFBBEFFDFF7BDEF73FFFBFFBDBFF4D
-:101ED000F2B6FDBD7FE7FFFFFF6FF7FFFFFFFE7765
-:101EE000FFBFF8AFFFDFBFFFBF7FFBFFFFFFDBFEE2
-:101EF000FFBFFFFAFFFDFFF67FFF9FFFFF3FEFF8F9
-:101F0000EE7E9FBAFEBF8FEFFEFEF9FFFA7FFE7EE8
-:101F1000BFAFFB96FD9FEF5E65BEEF5BB6FFBEE316
-:101F2000FFB5BFFFFDFF7FFFEFDFFEFFBFFBFEFF43
-:101F3000BFCFFFFFFFFD9BFFFEFBFEDFFF7FFFF735
-:101F4000FEFFDFFBFBFEFFFFFFFFFFB7FEFAFFAB6D
-:101F5000EFFFFDB57B7FFBF7FDFFFFDDFFEF8FFFA1
-:101F60002FFFFB7CFF3FDF73EBFE3FFFEFFBFEFF2E
-:101F7000EFFDFFBFFD0FFFFFFFF5F9FF7FD7FDFF6F
-:101F8000DFFFF7FBFF7FBFFFFFF09FFFFE7F8BE3CD
-:101F9000F9DE279BE6BE7F9BC3F8DE7F9DE7FE7FD1
-:101FA000FFFF5FD7FFFFFF4FFBFFFF7FFFAFFF9FED
-:101FB0007FFBFFE8FFFFFEBFAFFFFFFEBFEFF7FFB6
-:101FC000BFFFFFFFFFFFF7FFFCFFFFFD7FFFFFFFEE
-:101FD000FD3FCFFFFFFFFFF7FFFD7FFFFF93FFFFF9
-:101FE0007ADFF7FFFF7B7FB7EFFFFFFDBFFDFBFF52
-:101FF000F7FFD7FFFFFFFC9F6FCBFFF4BBDFD6FDE2
-:10200000BF2FD3F7FFDFFFCFFFFABEBDAF6ADABE47
-:10201000BBAB3ABE2DAEEBDAF63FADF5DDFFCFF14F
-:10202000FFF97FFF73FEFFCFC3F4F72FF3FFFCFF31
-:102030007C1FFF3F4FFF7EFFEFBDF6FEFF2BEFDC67
-:10204000FBFDFFFBFFEA7BFFFFFFFFFFFBF7DFFF6F
-:10205000E37DFFB7FFBFFFFFDFFFF8FFBFFFBFEB71
-:10206000E7FAFE3DBFE9FCBFFFFAFBFEFFFFFFD929
-:10207000FFFFFFF67FFFF67DFFDFCFFDBFFBEF7EAB
-:10208000FF7FFFFFD3FFFDFBFFFBFFFFFFEFFFBF66
-:10209000FEFFF7EFFFFFFFFBFF87FFFDFFFFFFFFE7
-:1020A0007BFEFFFE3BF7F7FF3FFFFFFFFFFF0FFF4A
-:1020B000FFFFFFFBFFFFFFF7FFFFADFFFEF7FFFF97
-:1020C0005FFFFFDFFFFDFFF5FFDFFFBDFFE9FFC79C
-:1020D000F3FFFFF7FFF3FFF83BFFFF7BDFBFFBEFF3
-:1020E000FBFFFBF7F7BBFFFFFFFFFBFFFE7FF37F6D
-:1020F0005EB7BFFD7FFFF97FFBFFEBFD7F7FFFEF4B
-:10210000FBE03FFEBFBFDFFF7EFFF7FFFFFEBFFF2D
-:10211000DB78FFFFFFEEA1BFF5DEFBF7FFFBFFFF64
-:10212000FFFFFBFFFFD7FFFFFFFFEFF0FFFFFFF316
-:10213000F7FFEFFFE7CFFFFBFFEFFFFF9F9FEFFCF6
-:1021400016BFFEF3E4FFFFC6FFE7FFFFFDFFBFFF83
-:10215000FF3FFFBFD6AF7FFE6B7E7FFFAFFFFFBFAE
-:10216000FF5FFFFEFFFFFEFFFFBDDBFFFE5FF2FF35
-:10217000FF5FFFFFFFFFFFFFEF7FFFFFFFFFDEBF00
-:10218000FFFFEFFB77FEBD7F5FFFFFFFDF6FEDFF20
-:10219000FDFF7FFD6FFFFF77DACFFD5FFFBFFFFF22
-:1021A000DF7FFFFBFFFFFFFF667FFFFEBFE7BFFA9A
-:1021B000FFFEFFFFFFDFFF59EFFFEFFB7F89FFFF10
-:1021C000E9FF6FFFF5FFFFFFFFFF7FF2F7FFFFEF74
-:1021D000F87FFBFFFDFFFFD9FFEFBBFFFFFFBFEF66
-:1021E000DEFFFF9F7FDFFFF7FFFFFFFFDFFFFFAF98
-:1021F000FFFFF73FEB9FFE7F9E7F9FFE87FFEDDB9C
-:1022000056FFBFAF0BD2FFEFDB6E7DBD6FF8FE3F19
-:10221000FA5BFFFDBFEFFFBF6FDBE6FFFF3FFFDFB6
-:10222000FEFFFFFFFFDA3FFFFBFEFEFFFFDFF7BD14
-:10223000FFFDFFFEFFFBFFFFFFFFF15FFD9FDFFDE7
-:10224000FFFD7FFFFFFFFF76FAFFFF7FE3F8FFAEA2
-:10225000FFFB7E9D73FFFA7FDFFFFF7FFFFBCDFF5C
-:102260007FEFFBFFFDFFF77F7FEFFFEDFFFFFFB588
-:10227000FFBFFFBFFDEFDBF7FF93FFEFE2F9BE7F8C
-:102280008BE7F9FE6BE7F9FE7F9FE7F9FE7F47FFDB
-:10229000FFFDFF9FFFD7FFFFFFFFF5FF9FFFF7FE4B
-:1022A000FFBFFE6FFFFFFBFFFFFFAFFFFFFF7FFBE7
-:1022B000FFFEFFFFFFFFFFFDDFFFFFF7FFFFFFDF79
-:1022C000FFFFFF5FFFFFFFFF5FFBFEFFF837FFFF32
-:1022D000EFFF7FFEBFFFFFFEBFFFFF7FFFBFFDFFE2
-:1022E0007FFA7FFFFF6FFFFF7DFFCFFFFFFF4FFFF5
-:1022F000F2FFFFFFFFFFFABFFFAEEBFAFEBBADEB55
-:10230000FAF7AF6BFAF6BF25E9F27F45FFFFFDF75D
-:10231000F7BFFFDFFFFFBFFBFFDFF3FFF73FCFFF9D
-:10232000A1FFFFBFE7FFFF7FFF3DFFFFFFF7FF2F8D
-:10233000FFFBF57FFE57FFFFFFFFFFFFFFFFFFF7EC
-:102340003FFFFEFFFFFFFDFEF7EEAFFEEEE7FAFFF9
-:10235000FE9DF95EFEFFEBFFFFDFA7FFFFFFFCDB4B
-:10236000FFFFFF7EFBFFFFEFFBFDFFDBFFFFFFEF4C
-:10237000FFFFFFFDBFFEBFFF6F7FFFF7FFFFF9FF0E
-:10238000F7FFBFDEF7FFFFFFFA7FFDBF5FFFFFBF75
-:10239000FFEDFFF7BFFFFFEFFFDFFFFFFFE6FFFBF4
-:1023A0007FFFFFFFFFFFF7FFFFFFFFFFFFFFEBFFD9
-:1023B000FDFFF5FFF67FDFBDCFFFFFFFFFDFFFFF74
-:1023C000FFF9FFFFFFFFFFE3FFEEBFFF7DEFFEFF23
-:1023D000FFFFBFFFFFFFFFFEFFFFFFFFE7FFB5AE01
-:1023E000FFFFB6FEBFFFFFBFFFFFFFFFFFFFFFFFC7
-:1023F000FF27FFEFFE7FDFFF7EFFFFFFFFFFFFFFF7
-:10240000FFFFFDFFF7F99FFF5FFFFFFFFFFFFF7F6C
-:10241000FFFFFEFFFFFFFFFFFFFFFF0FFFE7BFFE16
-:10242000FFBFFFFFFFFFFCBFFFFFFEFFFFFFFFC47B
-:102430006BFF291FFBAFFFFFFFFFFFEF1BFEFFFC42
-:102440006FFFFFFD6AF7D7F5BFFFFEFFFFFFFFFF3E
-:10245000FEBFFFFFFAFFFFF7FBDDBFFFE7FFFFFF58
-:10246000FFFFFFFFFFFD7FFFFFF5FFFFF7FDB3EF6E
-:10247000FD7E5DFFFDFFFFFFFD7FD2F5FB7ECBB74D
-:10248000FFFFFFC6FFFDEE63FFFFFFFFFFF6FD65E9
-:102490005BDFFFD5FFFFFFF6E7BFF7A9FFFFEDFF0B
-:1024A000FFFFFFFFEBFFFFFFAFFFFFFFF81BFFE3A7
-:1024B000D0BFFFE1FFFFFFFFFFD7FFFFFF5FFFFF81
-:1024C000FFFFAFFFDB76BFFF7FFFBFEFFEFFBFEF7A
-:1024D000FBFEFFFFFFBFF27FFF9FFEBDFE7FFFFF02
-:1024E000FFFFFFFFFFFFFFFFFFF73FEC7FF695BB0E
-:1024F000EFF8FEFCBF2FDAFCBF2FCBF2FCBFEFFFE3
-:10250000A9BFCFFBFFFFFFFEDDB76DF6D9B66D9B10
-:1025100076D9BFFBFDA3FFBFEFFFEFFFFFFF7FDF1C
-:10252000FDEF7BDEF7FDEF7FFFFF05FFFAFE7FEF9C
-:10253000E3FFFFFD7FFFFFFFFF5FFFFFFD7FFBAFBF
-:10254000FF63C8FFBFEFFFFFFA7FFFFFFFFE9FF7AC
-:10255000FFFABFFE9FFB7FFFFFEFD7FFFFF5FFFFF7
-:10256000FFFFFD7FFFFFBFFFF9BFFFBE279FE7F91A
-:10257000FE7F8BE7FE7F9FE2F9FE7F9FE7F17FFF03
-:10258000FFFFFBFEFFFFFFD7FFFFFFFFF5FFFFFF92
-:10259000D7FFFAFFFEFFFFFFFDFFFFFFAFF7FFFFD3
-:1025A000FFEBFFFFFFAFFFC4FFF7FFFFEFFFFFFFF2
-:1025B000FF5FFFFFFFFFD7FFFFFFFFFFEBFFFB7A90
-:1025C000DFF7FDFFFFFEBFFFFF7FFFAFFFFFFFF75E
-:1025D000EFE3FFDDD2FFDFFFFFF2FCBFCBF6FDBF75
-:1025E0002FCBFF7FDFDEAFFFDAEEBFAFE9FAF4BD3E
-:1025F000AF5AAEBBAB6BDADEBFADD75EFFFFBFFC41
-:10260000FFDFFDFFFFFFFFDFF7FFFFFFFFFDFFFA2B
-:102610001FFFFEFBEFBFFDFFFDBD77FFFFFFFF9D2F
-:10262000EFFFFFFFEF7DFFFBFEEFFFFFFFFFFFF779
-:10263000FFFFFFFFFFFFFFEEBFE4FBFFFE3FFEFFDC
-:10264000FFFFFFAFEAFEBFAFEBFAFEFFFFFF55F65D
-:10265000FFFEF7FF7FFFEBF75FC5FD7F5FD7F5FF5D
-:102660006FFBFF8AFFFFFFFFEBFFFFFFFFFBBFBF1B
-:10267000EFFBFFFFFFFFFBFF77DFFBFFFD7FEFFFC0
-:10268000FFFFBF7FFFDFBFFFFBFFFFFFFEEFDFFFAF
-:10269000FEFF9FEF7DFFF7FF7FFFFFDFF7FDFFEFFF
-:1026A000DFFFDFFFFFFFFFFFFFFFFFFFFDFFFFFB80
-:1026B000FDFFBFDFD1FFF83BFFFFFFFFFFFFFFFF85
-:1026C0007EDBFDFF77DBB77DBFFBFFF87FED7B5E39
-:1026D000FFFEFFFF4FD7FD7FDFD7F5FF7FFFFFFF37
-:1026E000F23FFEFFBFFFFFFFFFBFEFFEFF3BEEFF2E
-:1026F000FCEFFFFFFF85FFFDFEFFF5FFFFFEFFDFA5
-:10270000FBFF5FBFFFFDFFFFFFFFA8FFFF9F9EFFD7
-:10271000FFFF7FF3FFFFCFFFF7FDFF7FFFFFFC16FB
-:10272000BFCFA3E5EF7FFFF3E4FFCF93FCFF3FCFE5
-:10273000FFFFFFD60F7DBF6EFBF4FCAF6DDB77B7FD
-:102740006DDBF6FDBFFFFFFFBF9BFADEB7B7EDF90C
-:102750007EB7ACEBD6B3ADEB7ADFFFFFFFD8BFFFA0
-:10276000B7ED9F6FDDF768DB37B36CDB36CDB37F3A
-:10277000FF7FF56FFDEF793DF793E47A9EADEA7A3E
-:102780009EF7BDEFFFFFFF767FFBC6FFBBEFDAFED4
-:10279000FDBFFBFEFFBFEFFBFFFFFBFFA5FFFDAB98
-:1027A0006F78DE178F79DFFDFF7FDFF7FDFFFFFB1F
-:1027B000FFFBFFEFFBEFFBFEFFBBDAF3EF3BCEF3DC
-:1027C000BCEF3FCFDFFFB7FFFFFFCF73FFBFEFFFD0
-:1027D000F3FF3FCFF3FCFF3DCF9FFE07FFAFEBFEC4
-:1027E000FDBFEFEBFAFFAFEBFAFEBFAFFBFE3FFB27
-:1027F0009BFF7FDFFFF3FEFFDEF7BF7BDEF7BDEF62
-:102800007BFEFFFFDF3FFEFFB7FFEFF7FFBFEDFEF1
-:10281000DFB7EDFB7EDFFFFFFFFD5FEFEBFAFEF5BD
-:10282000BF6FFFFFFFFFFFFFFFFFFFFEF8FFA8FFE7
-:10283000FFBFEFFB6AFBB7EFFBFFBFEFFBFEFFBF86
-:10284000EFFBFFE0FFFFFD7F5CD77DDFF35CF5CDA5
-:10285000735ED7B5FD7FEFFFDBFFFFE2F8BE2F8F82
-:10286000E7F8BE6BE2F8BE2F8BE2F9FE7FE7FFD7F9
-:10287000F5FD7FFFF7F5FD7FD7F5FD7F5FD7F5FF0E
-:10288000FFFF8FFFAFEBFAFFFFBFEBFAFF2FEBFA73
-:10289000FEBFAFEBFFFFFE5FFF5FFFFFFDFFFFD758
-:1028A000FFFFFFFFFFFFFFFFFFFFFFFFBFFEB7FDC3
-:1028B000FF7EDFF7ADFF7FF7FDFF7FDFF7FDFF7FD7
-:1028C000F67FFFFFFFDBF6FCAFFFFFFFFFF7FFFF29
-:1028D000FFFFFFFFFFECBFFFAFEBFAF6AB8FEBFAAA
-:1028E000F7A5EBFABEBFAFEBFAFF6DFFFF7FDF335B
-:1028F000DDFF7FFEF7FC7FFBFFFFFFFFFFFFFFA970
-:10290000FFFDFFFFFEFFFFDFFFFFEFEFFDFF7FFF9C
-:10291000FFFFFFFEA7FFFFFF77DFF7FD9F7FFE773B
-:10292000EFFFFFFFFFFFFFFFFFAFBFAFFFF9BEBF2E
-:102930008FFBFEFEEFFBFEFFBFEFFBFFFFFDDF6F38
-:10294000EFFF7FFFBFBFDFFFFCFFDFF7FDEF7FDFA4
-:10295000FFFFFF3FF6FFCFFFDBFBF7FFEB7AFFFF49
-:10296000FFBFEFFBFFFFFFFE6DFDFF5FFBFFFFF70C
-:10297000FF5FF5FFFFFFFFFFFFFFFFFFF8FFFBFF1C
-:10298000FFFDFFFFFFFFE7F6BFFFFFFFFFFBFFFFBE
-:10299000FFC9FFFFFFBDFFBFAFEFEF3FD1FC7FFBE4
-:1029A000C7FFFFFFFFFFE3FFFFFFFFFDFFFF77FF15
-:1029B000DFB7FDF7FDF7FFFFFFFFFF57FFF7A5FDAF
-:1029C0003FDFBFBFFE7FFFFFFFDFFAFDFFFFFFFE20
-:1029D00087FFE9FFFEEFBFEFFEFEFFEFFFFFFFFF08
-:1029E000FFFFFFFFFA9FFF3FFFFDFD57DFFDF3FFF6
-:1029F000DFFDFF5FDFF5FDFFFFF98FFFFFFFEE7FDC
-:102A0000FFFFBF5EFEECFB3F7F9FEFF9FFFFCD6B4B
-:102A1000FFFFFFC5F3FCFA38FFAF3FEE7F9FFFD902
-:102A2000FFFFFD7AF7FFF3FFAF6FDBF2B9E9FBFFC2
-:102A3000FFFFFEFFFFEFFFFBC5BFFFEFFF5EB7AD80
-:102A4000CD797CFFFFFFFFFFFFFFFFFFFD93FFEF4F
-:102A5000EAFEBFEF5BD2CDF56D77DFF7FDFF7FDFDD
-:102A6000FFFF66FFD5657D5F759D657FD6FB4FFFD8
-:102A7000FFFFFFFFFFFFF6C7FFBFEFFAFEFFBFEB51
-:102A8000FFDFFF7EFFFFEFFD7ED7FF78DFFF5FDF19
-:102A9000F5BF7FDFC5FF3FF67EFF0FEFF23EBFFFC2
-:102AA000FB3FFFFB7FFFB3FEFBF6FDFFDAF7FDFF09
-:102AB0007FDFF7BFFFFA7FFFFFFFFF9FFFF3DCF928
-:102AC000BFCEE7F9FE7F9FE7FFFFE27FFEFFBFEF8C
-:102AD000EBFAFF9F671EFF8FE7F8FE7F8FEFFFBDCA
-:102AE000BFFFFBFFFFDFF7FFFCFFBFFFFFFFFFFFA5
-:102AF000FFFFFFFDB3FFFFEFFFFFBFEDFFFBEEFEAC
-:102B0000FFFFEFFFFEFFFFFFFFB5FFB7FDFD6EFF0D
-:102B1000FFFEFD2FD8FEBF8FEBF9FE3FFFFACFFF80
-:102B2000E7D9FABFDF77FCFB3FABFEFFBFEFFBFE51
-:102B3000FFFFEE1FFFDFF7FFFFFF5F9735BF5EFE72
-:102B4000BFEFFFF7FDFFFFFABFFFBE6F9FE7F8BEC5
-:102B50002F8B66947D9DE7F9FE7F9FE7F17FFFFF56
-:102B6000FFF7F5FD7F5FFBFD9EFFFBFEFFFFEFFF25
-:102B7000FFA0FFFFFFBFEFEBFAFEBFB7F7F7FFFFC6
-:102B8000FDFFFFFFFFFFDDFFFDFFFFFFD7FFFFFFA3
-:102B90007FF5FFFFEFFFFFFFBFFFFFABFEFBFEFF79
-:102BA000F7AFFFFFDEF7EB5FDFF7FDFF7FDFFFFF34
-:102BB000B3FFC9FEFFFFFFFFD6FFFFCBFFFFDFFF25
-:102BC000FFFFFFFFFC8FFFBABEBFAFEB78FEB7ADD4
-:102BD0003AFEB7AFEB7AFEBFAFFF9FFFFFDFFCFF10
-:102BE000FFFEC3FEFFFF33FCFFBFDFF3FFFFBB9F12
-:102BF000FFFFFFEBDFFFFFAFF76FF9BFEFFDFFFF59
-:102C0000FFFFFFE37FFFFFFFFBFFFFBFFDFBF7FFC2
-:102C1000DFF7FFFEEF5FBDFFFAFFF8FFBFAFFBFE80
-:102C2000FE3FEFE8FFDFF3FDFFFFFFFFFFEDFFFBE0
-:102C3000FDFFAFFFFFFEFEBFDBFFFFFFBFFFDFFFBC
-:102C4000FDFFCBFFFFFFFFFFBF6FFF7FB7B3FFFFAE
-:102C5000DFFFFBEFFFFFFF07FFFBFFFFFFEDFFF5D0
-:102C60007CFF7FFEFFFFEFCFFFFBFFFF2FFFFFFF8C
-:102C7000FFF3FFFBFFFEFFFFFFFFFFFFBFFFFFFFB5
-:102C8000FD1BFFFFFFFFFFFFFFFFFE7CFFFFFFFFBE
-:102C9000EFFFFFFFFFFBBF7FFDFFFFFFFFFFFFFF1A
-:102CA000DBFFFFFFFFFFFFFDFFFFF07FFFFFFFFFE9
-:102CB000FFFFFFFFFFFBFFDFFFFFFFFFFFFDBFFE8B
-:102CC0007FFFFFFFFFFFFFFFFFEFFEFFBFFFFFFFE5
-:102CD000FFFFEFFAB5FFFFFFF7F7FFFFFFFFDFFB97
-:102CE000FCFFFFFEFF7FDFBFFFCBBFF9FE7F9FE74B
-:102CF000F9FE7F97E1FE799FE7FDFE7FDFFE37FF5C
-:102D0000FBDEDEBDEFF3FEFBAFEBFEFFFFCFFFFE12
-:102D1000FFBFFF8FFFEFFBFEFFBFE7F95E7FEFFB1B
-:102D2000DAFFBFEFFBFEFFFD1FFFFFFFFFFFFFDF2F
-:102D3000FFFF7FFFFFF7FB7FFFFFFFFFFC3FFFBFB2
-:102D4000EFFBFEFFBFEF7B7FBFEFFBFEFFB5EFFBAF
-:102D5000BFFA7FFCFF3FCFF3FCFF3FCFBCFF3FEF4D
-:102D6000F3FCFE3FCFFFEEEFFBFEFFBFEFFB6AD7AA
-:102D7000B7FBF8FFB7EFBAFEFFBF7FE9FFF97E5F51
-:102D800097E5F9FE7FBFF97E5F9FE5FBFE5FB7FF2A
-:102D9000A3FFF7FDFF7FDFF7FDFF5EF77DFF77DF26
-:102DA000F7FDFF7FFFD7FFFFFFFFFFFFFDDFFB7F8B
-:102DB000FFFFEFFFFEFBFFFFBFFE8FFFDFF7FDFD15
-:102DC0007FDFF7FD3EDFF5BDFF7FDFF7FDF7FF9FFC
-:102DD000FFFFFFFFFFFFFFFFFFFDFFBEFFFFFFFF46
-:102DE000FFFFFFFD3FFFDFF7FDFF7FDFF7FDFFCFB9
-:102DF00077FCFF5FDFF7FDFFF47FFFFFFFFFFFFFC3
-:102E0000FFFFFFFFFFFFFFFFFFFDFFFFFFEEFFFFE5
-:102E1000FFFFFFFFFFFFFFFFEDFBFFFFBFFFFFFF18
-:102E2000FFFFE9FFFFFFFFFFFFFBFFFFFFD3FFFFF8
-:102E3000BF3FFBFFFFFFFBF3FFFFFFFFFFFFFFFFB6
-:102E4000FFFFFFFFFFFEFFF7FFFFFFFF17FFFFFF83
-:102E5000DFFFFDFFFFFFFFFFDFDFFFFDFFFFDFF70E
-:102E6000FF4FFFFFFFFFFFFFFFFFFFFEFFFFFFFD25
-:102E7000FFFFFFFFFEFF9FFFFFFFFFFFFFFFFFFFC3
-:102E8000FDFFFFFFFFFF7FFFFFFF7A3FFFFFFFFF19
-:102E9000FFFFFF7FFFFFFFFFFFFFFFFFFFFFFFF2CF
-:102EA0007FFFFBFEFFBFEFF8FEFFBFFBFEFF8FECD7
-:102EB000FBFEFFBFF8F7FEFFBFEFFBFEFDBFCFEC51
-:102EC000FF3FEFDBF8FFBFCFFFF9FFFFBFFFFBFFC7
-:102ED000FFFFEFFBDFFFFFFFFFFFBFFFFFFFBBFFBA
-:102EE000EFFBFEEFBFEEEBFBFEFFEFFEEEBFFEEBF8
-:102EF000FFEFFF17FF7EEBBBFEBFBEFBEF5BF7BD37
-:0A2F0000FBCFBFBFBBFB7ECCEFFF91
-:00000001FF
-
- * Copyright (C) 1999 BayCom GmbH
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
diff --git a/firmware/dabusb/firmware.HEX b/firmware/dabusb/firmware.HEX
deleted file mode 100644
index 7c258df..0000000
--- a/firmware/dabusb/firmware.HEX
+++ /dev/null
@@ -1,649 +0,0 @@
-:02000000215786
-:0300030002016691
-:03000B0002016689
-:0300130002016681
-:03001B0002016679
-:0300230002016671
-:03002B0002016669
-:0300330002030FB6
-:03003B0002016659
-:03004300020100B7
-:03004B0002016649
-:0300530002016641
-:03005B000204BDDF
-:0300630002016730
-:03010000020C5A94
-:030104000201ED08
-:030108000202519F
-:03010C0002027C70
-:030110000202E404
-:0101140032B8
-:0101180032B4
-:03011C000205FDDC
-:03012000020000DA
-:03012400020000D6
-:0301280002043C92
-:03012C0002046A60
-:03013000020000CA
-:03013400020000C6
-:03013800020000C2
-:03013C00020000BE
-:03014000020000BA
-:03014400020000B6
-:03014800020000B2
-:03014C00020000AE
-:03015000020000AA
-:03015400020000A6
-:0A01570075817FE5826003020161FB
-:0501610012076F21648C
-:010166003266
-:0E016700C0D0C086C082C083C0E0907F97E009
-:0E0175004480F0907F69F0F0F0F0F0F0F0F0D0
-:0E018300F0F0F0F0F0F0F0F0F0F0F0F0F0F04E
-:0E019100F0F0F0F0F0F0F0F0F0F0907F97E07A
-:03019F00557FF099
-:0E01A200907F9AE030E423907F68F0F0F0F058
-:0E01B000F0F0F0F0F0F0F0F0F0F0F0F0F0F021
-:0E01BE00F0F0F0F0F0F0F0F0F0F0F0F0F0F013
-:0E01CC00E5D8C2E3F5D8D0E0D083D082D0864B
-:0301DA00D0D03250
-:0801DD0075860090FFC37C054C
-:0701E500A3E582458370F9D8
-:0101EC0022F0
-:0E01ED00C0E0C0F0C082C083C002C003C0D01A
-:0E01FB0075D000C086758600E591C2E4F591CE
-:0D020900908800E0F541907FAB7402F0900A
-:090216007FAB7402F0E5326021B7
-:04021F007A007B00E6
-:0B022300C3EA9418EB64809480501232
-:0E022E00907F69F0F0F0F0F0F0F0F00ABA0006
-:02023C00010BB4
-:02023E0080E35B
-:02024000D08666
-:0E024200D0D0D003D002D083D082D0F0D0E054
-:01025000327B
-:0E025100C0E0C0F0C082C083C0D075D000C035
-:0E025F0086758600E591C2E4F591907FAB7440
-:04026D0004F0D08643
-:0B027100D0D0D083D082D0F0D0E0329B
-:0E027C00C0E0C0F0C082C083C002C003C00456
-:0E028A00C005C006C007C000C001C0D075D0BE
-:0D02980000C086758600E591C2E4F59190E6
-:0C02A5007FAB7408F0756E00756F0212DC
-:0602B1001144757039755F
-:0602B700710C75720212C9
-:0C02BD001175907FD6E4F075D820D08633
-:0E02C900D0D0D001D000D007D006D005D00490
-:0D02D700D003D002D083D082D0F0D0E0322E
-:0E02E400C0E0C0F0C082C083C0D075D000C0A2
-:0E02F20086758600E591C2E4F591907FAB74AD
-:0403000010F0D086A3
-:0B030400D0D0D083D082D0F0D0E03207
-:0E030F00C0E0C0F0C082C083C002C003C004C2
-:0E031D00C005C006C007C000C001C0D075D02A
-:0C032B0000C086758600756E00756F02BC
-:0703370012114475704075BE
-:06033E00710C7572021241
-:0E0344001175907FD67402F0907FD67406F08B
-:0503520075D810D086F3
-:0E035700D0D0D001D000D007D006D005D00401
-:0D036500D003D002D083D082D0F0D0E0329F
-:0D037200907FA57480F0907FA6749AF01221
-:0C037F00101B907FA6E542F012101B90AE
-:0D038B007FA6E543F012101B907FA5744083
-:01039800F074
-:010399002241
-:0D039A00907FA57480F0907FA6749AF012F9
-:0C03A700101B907FA6E544F012101B9084
-:0C03B3007FA6E545F012101B907FA6E528
-:0B03BF0046F012101B907FA57440F068
-:0103CA002210
-:0A03CB0075440275450075460012E6
-:0903D500039A75420375430012FE
-:0203DE000372A8
-:0103E00022FA
-:0C03E100908800E536F09088007410252C
-:0903ED0036F01201DD75420175C4
-:0903F600431812037275440275EC
-:0903FF00450075460012039A75D1
-:08040800420375434412037224
-:0104100022C9
-:0E041100C0E0C0F0C082C083C0D075D000C073
-:0E041F0086758600E591C2E4F591907FAA747F
-:04042D0002F0D08683
-:0B043100D0D0D083D082D0F0D0E032D9
-:0E043C00C0E0C0F0C082C083C0D075D000C048
-:0E044A0086758600E591C2E4F591907FA97455
-:0704580004F0753001D086AD
-:0B045F00D0D0D083D082D0F0D0E032AB
-:0E046A00C0E0C0F0C082C083C0D075D000C01A
-:0E04780086758600E591C2E4F591907FAA7426
-:0704860004F0753101D0867E
-:0B048D00D0D0D083D082D0F0D0E0327D
-:0E049800C0E0C0F0C082C083C0D075D000C0EC
-:0C04A60086758600E591C2E5F591D086D0
-:0B04B200D0D0D083D082D0F0D0E03258
-:0E04BD00C0E0C0F0C082C083C0D075D000C0C7
-:0C04CB0086758600E591C2E7F591D086A9
-:0B04D700D0D0D083D082D0F0D0E03233
-:0C04E200907FEAE0FA8A20907F96E4F018
-:0104EE0022EB
-:0704EF00907FEAE0FA8A2188
-:0104F60022E3
-:0E04F700901713E0FA901715E0FB74802AFAB4
-:0E05050074802BFBEA0303543FFCEAC423542A
-:0E0513001FFA2CFAEB0303543FFCEBC42354F5
-:0B0521001FFB2CFB90170AE0FC60029F
-:02052C007A0053
-:07052E0090170CE0FC6002D5
-:020535007B0049
-:0B053700EA2BFCC313F53A7544028B5D
-:07054200458A4612039A7579
-:090549006E08756F001211447573
-:040552007047757108
-:080556000C757202121175858B
-:05055E003A731211A028
-:010563002275
-:0E056400907F96E0FA907F9674806502F0908A
-:0E0572007FEBE0FA907FEAE0FB907FEFE0FC89
-:0E0580003395E0FD8C057C00907FEEE0FE33AD
-:0E058E0095E0FFEC2EFCED3FFD907FE9E0FED6
-:05059C00BE0102800316
-:0305A1000205F957
-:0605A400BC0121BD001E98
-:0E05AA00EAC40354F8FCEB25E0FD2C2400FC11
-:0E05B800E43417FD907EC0E0FE8C828D83F04F
-:0205C600803182
-:0E05C800EAC40354F8FAEB25E0FB2AFA2400FB
-:0E05D600FBE43417FC907EC0E0FD8B828C832A
-:0E05E400F074012A2400FAE43417FB907EC163
-:0705F200E0FC8A828B83F01C
-:0305F90075380151
-:0105FC0022DC
-:0E05FD00C0E0C0F0C082C083C002C003C004D2
-:0E060B00C005C006C007C000C001C0D075D039
-:0D06190000C086758600E591C2E4F5919061
-:0D0626007FAA7401F0120564753700D086BC
-:0E063300D0D0D001D000D007D006D005D00422
-:0D064100D003D002D083D082D0F0D0E032C0
-:0E064E00907FEBE0FA907FEAE0FB907FEEE019
-:0E065C00FC3395E0FD907F96E0FE907F967453
-:0E066A00806506F0907F007401F0EAC403542E
-:0E067800F8FEEB25E0FB2EFE2400FBE4341719
-:0E068600FF8B828F83E0FB74012E2400FEE4C4
-:0E0694003417FF8E828F83E0FE907FE9E0FF37
-:0306A200BF810A0B
-:0A06A500907F00EBF0907F01EEF073
-:0806AF00907FE9E0FBBB821A19
-:0306B700BA010C79
-:0C06BA00907F00E4F0907F01E4F0800BE2
-:0B06C600907F00E4F0907F0174B5F01D
-:0806D100907FE9E0FBBB831BF5
-:0306D900BA010D56
-:0D06DC00907F007401F0907F01E4F0800B2E
-:0B06E900907F00E4F0907F017412F09D
-:0806F400907FE9E0FBBB841CD0
-:0306FC00BA010D33
-:0D06FF00907F007401F0907F01E4F0800C0A
-:0C070C00907F007480F0907F017401F079
-:05071800907FB5ECF03C
-:01071D0022B9
-:0C071E0075360D908800741DF0756B801E
-:0A072A00756C3C1210E2756B8075CF
-:090734006C0F1210E2756B807568
-:09073D006C061210E2756B807568
-:070746006C011210E27A00C1
-:03074D00BAFF00F0
-:02075000500A4D
-:0A075200C0021201DDD0020A80F19E
-:0A075C00756B80756C3C1210E2759D
-:080766006B80756C0F1210E2AC
-:01076E002268
-:0E076F00907FA1E4F0907FAF7401F0907F9234
-:0E077D007402F0758E3175892175880075C87B
-:0E078B0000758D4075984075C04075870075EB
-:0907990020007521007522007595
-:0507A200230075470073
-:0707A700C3E5479420501147
-:0D07AE00E5472400F582E43417F583E4F0FC
-:0407BB00054780E886
-:0907BF00E4F540F53FE4F53CF5DA
-:0707C8003BE4F53EF53D7531
-:0B07CF003200753700753900907F93F1
-:0E07DA00743CF0907F9C74FFF0907F967480CA
-:0E07E800F0907F947470F0907F9D748FF0906D
-:0E07F6007F97E4F0907F9574C2F0907F987426
-:0E08040028F0907F9E7428F0907FF0E4F09032
-:0E0812007FF1E4F0907FF2E4F0907FF3E4F0E9
-:0E082000907FF4E4F0907FF5E4F0907FF6E432
-:0E082E00F0907FF7E4F0907FF8E4F0907FF90F
-:0E083C007438F0907FFA74A0F0907FFB74A0E7
-:0E084A00F0907FFC74A0F0907FFD74A0F09001
-:0E0858007FFE74A0F0907FFF74A0F0907FE010
-:0E0866007403F0907FE17401F0907FDD7480E8
-:0B087400F012124312071E7A007B00F6
-:09087F00C3EA941EEB940050172B
-:0C088800908800E0F54790880BE0F547F1
-:09089400907F68F00ABA00010B24
-:02089D0080E0F9
-:0C089F001203E1907FD6E4F07A007B00A9
-:0D08AB008A048B05C3EA94E0EB942E501AEA
-:0E08B800C002C003C004C0051201DDD005D08F
-:0A08C60004D003D0020ABA00010BAF
-:0208D00080D9CD
-:0D08D200907FD67402F0907FD67406F090EF
-:0E08DF007FDE7405F0907FDF7405F0907FAC33
-:0E08ED00E4F0907FAD7405F075A88075F810EA
-:0D08FB00907FAE740BF0907FE27488F09057
-:0C0908007FAB7408F075E81175320175C2
-:0C0914003100753000C004C0051204F76B
-:0A092000D005D004753400753501D0
-:0D092A00907FAE7403F08C02BA00028003CF
-:03093700020A3F72
-:0C093A00853334907F9D748FF0907F9780
-:0E0946007408F0907F9D7488F0907F9AE0FA1C
-:0C09540074055AF533907F9D748FF0906D
-:0D0960007F977402F0907F9D7482F0E53364
-:0D096D0025E0FA907F9AE05405FB4AF5332F
-:02097A00600C0F
-:0C097C00907F96E0FA907F9674804AF01D
-:0B098800756E00756F00C004C0051202
-:0E0993001144D005D004901713E0FA74802AA6
-:0609A100FAE533B404295D
-:0309A700BAA000F3
-:0209AA005024D7
-:0D09AC00901713E004FB0B901713EBF09075
-:0E09B9001713E0FB901715F0C002C004C00534
-:0909C7001204F7D005D004D0029F
-:0509D000E533B402262E
-:0609D500C374049A5020D7
-:0D09DB00901713E0FA1A1A901713EAF09023
-:0D09E8001713E0FA901715F0C004C00512B7
-:0609F50004F7D005D00458
-:0509FB00E533B4081D06
-:040A0000E534701950
-:0A0A040074012535540FF5358535D2
-:0C0A0E0075757600C004C0051213FED000
-:030A1A0005D00400
-:050A1D00E533B4011DEA
-:040A2200E53470192E
-:0A0A2600E53524FF540FF535853542
-:0C0A300075757600C004C0051213FED0DE
-:030A3C0005D004DE
-:0E0A3F00C004C0051201DDD005D004907F96E2
-:0E0A4D00E0FA907F96747F5AF0907F977408BD
-:0A0A5B00F0C3EC9400ED9402400893
-:080A6500907F96E0FA20E608FC
-:080A6D00C3E49C74089D5013C2
-:0E0A7500907F96E0FA907F9674406502F07CC8
-:050A8300007D0080056C
-:050A88000CBC00010D93
-:050A8D00E538B4010E84
-:0D0A9200C004C0051204F7D005D00475386B
-:010A9F000056
-:070AA000E531700302092A91
-:0A0AA700907FC9E0FA7003020C2DE5
-:0E0AB100907F96E0FA907F9674806502F09038
-:090ABF007DC0E0FABA2C028003AC
-:030AC800020B36E8
-:050ACB007532007B0004
-:030AD000BB640004
-:020AD300501CB5
-:0E0AD500C002C003C004C0051201DDD005D070
-:0D0AE30004D003D00290880FE0F5470B808F
-:010AF000DF26
-:0D0AF100C002C004C00512071E1203E1126E
-:0C0AFE0004F7D005D004D002756E00751E
-:0D0B0A006F01C002C004C005121144D005E7
-:090B1700D004D00275704D757117
-:0B0B20000C757202C002C004C0051278
-:0B0B2B001175D005D004D002020C2D83
-:030B3600BA2A3B9D
-:0D0B3900907F987420F0C002C004C0051227
-:0E0B460001DDD005D004D002907F987428F015
-:020B54007B0024
-:030B5600BB0A00D7
-:050B59004003020C2D19
-:0E0B5E00C002C003C004C0051201DDD005D0E6
-:080B6C0004D003D0020B80E26B
-:030B7400BA2B1A7F
-:080B7700907FC9E0FBBB4012B6
-:0E0B7F00C002C004C005121205D005D004D07B
-:040B8D0002020C2D27
-:030B9100BA101F78
-:0E0B9400907F96E0FB907F9674806503F0C022
-:0E0BA20002C004C00512103DD005D004D002E0
-:030BB000020C2D07
-:030BB300BA111262
-:0E0BB600C002C004C00512106AD005D004D0E1
-:040BC40002020C2DF0
-:030BC800BA12124C
-:0E0BCB00C002C004C00512108FD005D004D0A7
-:040BD90002020C2DDB
-:030BDD00BA130B3D
-:0B0BE000907DC1E0FB908800F0804297
-:030BEB00BA141128
-:0E0BEE00C002C004C0051211DDD005D004D035
-:030BFC0002802E46
-:030BFF00BA151D07
-:0C0C0200907DC1E0F575907DC2E0F576B4
-:0E0C0E00C002C004C0051213FED005D004D0F1
-:030C1C0002800E45
-:030C1F00BA160BF7
-:0B0C2200C004C0051213A3D005D004CD
-:0B0C2D00907FC9E4F075310002092A35
-:010C38002299
-:070C3900535550454E4400E5
-:070C4000524553554D4500DC
-:060C470020566F6C200036
-:0D0C4D004441425553422076312E30300094
-:0E0C5A00C0E0C0F0C082C083C002C003C0046E
-:0E0C6800C005C006C007C000C001C0D075D0D6
-:0D0C760000C086758600E591C2E4F59190FE
-:0E0C83007FAB7401F0907FE8E0FA907FE9E02B
-:060C9100FBBB0002800322
-:030C9700020D3813
-:030C9A00BA801409
-:0E0C9D00907F007401F0907F01E4F0907FB52D
-:060CAB007402F0020ECD00
-:050CB100BA820280037D
-:030CB600020D1D0F
-:080CB900907FECE0FCBC01009F
-:020CC1004021D0
-:060CC300C374079C401BF6
-:0E0CC900EC24FF25E0FD24C6F582E4347FF51F
-:0D0CD70083E0FD530501907F00EDF0802BC0
-:030CE400BC8100D0
-:020CE7004021AA
-:060CE900C374879C401B50
-:0E0CEF00EC247F25E0FC24B6F582E4347FF58A
-:0D0CFD0083E0FC530401907F00ECF08005C3
-:050D0A00907F00E4F001
-:0E0D0F00907F01E4F0907FB57402F0020ECDEB
-:050D1D00BA8102800311
-:030D2200020EC5F9
-:0E0D2500907F00E4F0907F01E4F0907FB574C1
-:050D330002F0020ECDEC
-:030D3800BB012DCF
-:060D3B00BA0003020ECD18
-:030D4100BA0211E2
-:0D0D4400755900C002C003120EF0D003D09C
-:040D510002020ECDBF
-:050D5500BA2102800339
-:030D5A00020ECDB9
-:0B0D5D00753701907FC5E4F0020ECD59
-:030D6800BB031FAB
-:060D6B00BA0003020ECDE8
-:050D7100BA020280033C
-:030D7600020ECD9D
-:0D0D7900755901C002C003120EF0D003D066
-:040D860002020ECD8A
-:030D8A00BB065451
-:050D8D00BA80028003A2
-:030D9200020EC589
-:080D9500907FEBE0FCBC0115AE
-:0C0D9D007CFB7D0F8D067F00907FD4EE64
-:090DA900F0907FD5ECF0020ECDB4
-:0A0DB200907FEBE0FCBC020280031E
-:030DBC00020EC55F
-:0A0DBF00907FEAE0FCBC0002800314
-:030DC900020EC552
-:0C0DCC007C3B7D0F8D067F00907FD4EEF5
-:090DD800F0907FD5ECF0020ECD85
-:060DE100BB0703020EC572
-:030DE700BB081036
-:0D0DEA00AC48907F00ECF0907FB57401F0F4
-:030DF700020ECD1C
-:030DFA00BB093101
-:050DFD00BA00028003B2
-:030E0200020EC518
-:0E0E0500907FEAE0FCC374019C5003020EC50E
-:080E1300907FEAE0FCBC000A3C
-:0A0E1B00901721E4F0901722E4F094
-:090E2500907FEAE0F548020ECDD1
-:030E2E00BB0A27D5
-:050E3100BA81028003FC
-:030E3600020EC5E4
-:0E0E3900907FECE0FA2420FAE43417FC8A8261
-:0E0E47008C83E0FA907F00F0907FB57401F08C
-:030E5500020ECDBD
-:050E5800BB0B0280034A
-:030E5D00020EA9D9
-:0D0E6000901720E4F0907FECE0FABA011A40
-:080E6D00907FEDE0FABA0012DB
-:0E0E7500907FEAE0FA901721F0C0031204E229
-:040E8300D0038046D2
-:080E8700907FECE0FABA023E94
-:080E8F00907FEDE0FABA003695
-:0D0E9700C0031204EFD003907FEAE0FA9050
-:050EA4001722F080247C
-:050EA900BB12028017DE
-:050EAE00BB8102800D74
-:050EB300BB8302800872
-:050EB800BB8202800373
-:030EBD00BB8405EE
-:050EC00012064E80083F
-:080EC500907FB47403F0800675
-:060ECD00907FB47402F0F6
-:020ED300D086C7
-:0E0ED500D0D0D001D000D007D006D005D00478
-:0D0EE300D003D002D083D082D0F0D0E03216
-:0B0EF000907FECE0F55AC39401401D18
-:070EFB00C37407955A40166D
-:0D0F0200E55A24FF25E0FA24C6F582E43408
-:090F0F007FF583AA59EAF0802263
-:070F1800C3E55A9481401B60
-:070F1F00C37487955A4014CA
-:0D0F2600E55A24FF25E0FA24B6F582E434F4
-:070F33007FF583AA59EAF0E3
-:010F3A002294
-:0E0F3B000902BA000301004000090400000092
-:0E0F49000101000009240100013D0001010C1E
-:0E0F570024020110070002030000000D240612
-:0E0F650003010215000300030000092403022B
-:0E0F7300010100010009240304020300030031
-:0E0F8100092403050306000100090401000015
-:0E0F8F00010200000904010101010200000737
-:0E0F9D002401020101000B24020102021001D6
-:0E0FAB0080BB00090588050001010000072534
-:0E0FB900010000000009040200020000000018
-:0E0FC7000705820240000007050202400000FC
-:0E0FD50009040201030000000007058202402B
-:0E0FE30000000705020240000009058905A074
-:0A0FF1000101000000FFFFFFFF00F8
-:0E0FFB00120100010000004047059999000115
-:0E10090000000001000000000000000902BA13
-:0410170000030100D1
-:02101B007A0059
-:03101D00BA050011
-:02102000501767
-:08102200907FA5E0FB30E00522
-:05102A00900001800DA3
-:0A102F00C0021201DDD0020A80E4C5
-:0310390090000123
-:01103C002291
-:0E103D00907DC1E0F9A3E0FAA3E0FB7C007D0A
-:04104B007EEB6012C6
-:0E104F0089828A83E0A3A982AA838C828D8382
-:04105D00F00CDBEECA
-:08106100907DC3E0907FB9F01F
-:011069002264
-:0E106A00907DC1E0F9A3E0FAA3E0FB7CC47D19
-:041078007DEB60E5C7
-:0E107C008C828D83E00C89828A83F0A3A98286
-:04108A00AA83DBEE6C
-:01108E00223F
-:0E108F00907FA57480F00586907DC1E00586F7
-:0E109D00A3F012101B907FA60586A3A3E0F916
-:0510AB006016A305869C
-:0D10B000907FA60586E0A30586F0C0011222
-:0610BD00101BD001D9ED6B
-:0610C300907FA57440F0CF
-:0110C9002204
-:0810CA009088027401F07A0025
-:0310D200BAFF0062
-:0210D500500ABF
-:0A10D700C0021201DDD0020A80F110
-:0110E10022EC
-:0510E200E56BB4C0083D
-:0810E700908803E56CF080061F
-:0610EF00908802E56CF0A0
-:0410F5007A007B0002
-:0B10F900C3EA9432EB6480948050073F
-:051104000ABA00010B16
-:0211090080EE76
-:01110B0022C1
-:0A110C00908803E56DF005397A00C4
-:03111600BA2800F4
-:02111900500381
-:03111B000A80F84F
-:05111E00E539B41008E2
-:0811230090880274C0F0800EF8
-:05112B00E539B42009C4
-:091130009088027480F07539000A
-:021139007A003A
-:03113B00BA2800CF
-:02113E0050035C
-:031140000A80F82A
-:011143002289
-:04114400E56F6002F1
-:0211480080071E
-:07114A007A007539008005F1
-:051151007A4075391021
-:09115600E56E2AFAE56E2539F573
-:0A115F003990880274802AF07A00AB
-:08116900C3EA648094A850035E
-:031171000A80F5FC
-:011174002258
-:06117500AA70AB71AC7220
-:0C117B008A828B838CF01214EEFD601849
-:0D1187008D6DC002C003C00412110CD00415
-:09119400D003D0020ABA00010BDD
-:02119D0080DCF4
-:01119F00222D
-:0D11A000E573C4540FFA53020FC374099A8B
-:0211AD005006EA
-:0611AF0074372AFB8004E6
-:0411B50074302AFB6D
-:0C11B9008B6DC00312110CD003AA7353FD
-:0811C500020FC374099A5006E1
-:0611CD0074372AFB8004C8
-:0411D30074302AFB4F
-:0511D7008B6D12110CEC
-:0111DC0022F0
-:0711DD00907DC3E0FA600FF2
-:0C11E400907DC1E0F56E907DC2E0F56FDB
-:0311F00012114495
-:0C11F300907DFFE4F07570C475717D758F
-:0511FF007201121175E0
-:0112040022C7
-:021205007A0469
-:03120700BA4000EA
-:02120A0050365C
-:0E120C00EA24C0F582E4347DF583E0FB7C002B
-:03121A00BC08000D
-:02121D0050205F
-:06121F008B05ED30E70B2A
-:0B122500907F967442F074C3F08008C4
-:08123000907F96E4F07481F058
-:07123800EB25E0FB0C80DB5D
-:03123F000A80C55D
-:011242002289
-:041243007A007BEFC3
-:03124700BA1000DA
-:02124A00502032
-:0E124C0074112BFB2400FCE43418FD8C828D01
-:0E125A0083E4F0EA2400F582E43419F583E41D
-:04126800F00A80DB2D
-:01126C00225F
-:0E126D0074F82400F58274033484F583E4F0F1
-:0E127B0074F92400F58274033484F583E4F0E2
-:0E12890074FA2400F58274033484F583E4F0D3
-:0E12970074FB2400F58274033484F583E4F0C4
-:0E12A50074FF2400F58274033484F583E4F0B2
-:0112B3002218
-:0E12B4001203CB12126D7AC07B877C0174018D
-:0E12C2002AFDE43BFE8C078A828B838CF0743D
-:0E12D000011214BF2DFAE43EFB8F048D828EB6
-:0E12DE00838FF074061214BF74012AFDE43BE6
-:0E12EC00FE8C078A828B838CF0E41214BF7490
-:0E12FA00012DFAE43EFB8F048D828E838FF06F
-:0E130800740B1214BF74012AFDE43BFE8C0727
-:0E1316008A828B838CF074081214BF74012D30
-:0E132400FAE43EFB8F048D828E838FF07401FD
-:0E1332001214BF2AFDE43BFE8C078A828B83D7
-:0E1340008CF0E41214BF74012DFAE43EFB8F12
-:0E134E00048D828E838FF074031214BF7D0015
-:03135C00BD0600CB
-:02135F0050122A
-:0B1361008A828B838CF00ABA00010B1B
-:07136C00E41214BF0D80E93B
-:0D1373008A828B838CF0E5741214BF74F92C
-:0E1380002400F58274033484F583740FF07436
-:0E138E00FE2400F58274033484F5837401F0AC
-:06139C001203E11204F748
-:0113A2002228
-:0D13A300907DC1E0FA2400FBE43419FC90B9
-:0E13B0007DC2E0FD8B828C83F075F011EAA403
-:0313BE00FA7B00B7
-:0313C100BB10005E
-:0213C4005024B3
-:0E13C600EA2400FCE43418FDEB2CFCE43DFDB1
-:0E13D40074042B24C0F582E4347DF583E0FE22
-:0813E2008C828D83F00B80D793
-:0E13EA00EA2400FAE43418FB74102AF582E4B9
-:0513F8003BF583E4F069
-:0113FD0022CD
-:0413FE00E57660022E
-:02140200801652
-:0C140400740F5575FA8A752400F582E417
-:0A1410003419F583E0F5741212B4EC
-:0A141A001210CA756E00756F001203
-:0614240011447570B9755A
-:06142A007114757202123C
-:0B1430001175E576B402047401800120
-:01143B00E4CC
-:03143C00FA700F34
-:0C143F0074012575F573C0021211A0D0D5
-:03144B0002800A12
-:0A144E00857573C0021211A0D002D0
-:0C145800756E00756F01C002121144D0C7
-:0414640002EA701A0E
-:0D14680075F011E575A4FA2400FAE43418BB
-:09147500FB8A708B717572011283
-:04147E00117580362E
-:021482007A00EE
-:03148400BA10009B
-:02148700502FE4
-:0D148900EA2400F582E43419F583E0FBE568
-:0414960075B5031B0A
-:0E149A0075F011EAA4FB2400FBE43418FC8B6F
-:0914A800708C71757201C0021212
-:0414B1001175D002DF
-:0314B5000A80CCDE
-:0114B8002211
-:0614B90050726F67200075
-:0E14BF00C8C0E0C8C0E0E5F0600B14600F1478
-:0714CD00601114601280158C
-:0714D400D0E0A882F6800EB3
-:0514DB00D0E0F08009E3
-:0414E000D0E08005D3
-:0514E400D0E0A882F237
-:0414E900C8D0E0C8BF
-:0114ED0022DC
-:0E14EE00C8C0E0E5F0600D14600F14600F142C
-:0614FC00601074FF800F78
-:05150200A882E6800A4A
-:03150700E080077A
-:04150A00E4938003E3
-:03150E00A882E2CE
-:04151100F8D0E0C866
-:0115150022B3
-:00000001FF
-
- * Copyright (C) 1999 BayCom GmbH
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
diff --git a/fs/Kconfig b/fs/Kconfig
index f95ae3a..fc1bc21 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -68,16 +68,6 @@ source "fs/quota/Kconfig"
 source "fs/autofs4/Kconfig"
 source "fs/fuse/Kconfig"
 
-config CUSE
-	tristate "Character device in Userspace support"
-	depends on FUSE_FS
-	help
-	  This FUSE extension allows character devices to be
-	  implemented in userspace.
-
-	  If you want to develop or use userspace character device
-	  based on CUSE, answer Y or M.
-
 config GENERIC_ACL
 	bool
 	select FS_POSIX_ACL
@@ -220,6 +210,7 @@ source "fs/pstore/Kconfig"
 source "fs/sysv/Kconfig"
 source "fs/ufs/Kconfig"
 source "fs/exofs/Kconfig"
+source "fs/f2fs/Kconfig"
 
 endif # MISC_FILESYSTEMS
 
diff --git a/fs/Makefile b/fs/Makefile
index 1d7af79..9d53192 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -123,6 +123,7 @@ obj-$(CONFIG_DEBUG_FS)		+= debugfs/
 obj-$(CONFIG_OCFS2_FS)		+= ocfs2/
 obj-$(CONFIG_BTRFS_FS)		+= btrfs/
 obj-$(CONFIG_GFS2_FS)           += gfs2/
+obj-$(CONFIG_F2FS_FS)		+= f2fs/
 obj-y				+= exofs/ # Multiple modules
 obj-$(CONFIG_CEPH_FS)		+= ceph/
 obj-$(CONFIG_PSTORE)		+= pstore/
diff --git a/fs/attr.c b/fs/attr.c
index cce7df5..86ca9e9 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -49,14 +49,15 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
 	/* Make sure a caller can chown. */
 	if ((ia_valid & ATTR_UID) &&
 	    (!uid_eq(current_fsuid(), inode->i_uid) ||
-	     !uid_eq(attr->ia_uid, inode->i_uid)) && !capable(CAP_CHOWN))
+	     !uid_eq(attr->ia_uid, inode->i_uid)) &&
+	    !inode_capable(inode, CAP_CHOWN))
 		return -EPERM;
 
 	/* Make sure caller can chgrp. */
 	if ((ia_valid & ATTR_GID) &&
 	    (!uid_eq(current_fsuid(), inode->i_uid) ||
 	    (!in_group_p(attr->ia_gid) && !gid_eq(attr->ia_gid, inode->i_gid))) &&
-	    !capable(CAP_CHOWN))
+	    !inode_capable(inode, CAP_CHOWN))
 		return -EPERM;
 
 	/* Make sure a caller can chmod. */
@@ -65,7 +66,8 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
 			return -EPERM;
 		/* Also check the setgid bit! */
 		if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
-				inode->i_gid) && !capable(CAP_FSETID))
+				inode->i_gid) &&
+		    !inode_capable(inode, CAP_FSETID))
 			attr->ia_mode &= ~S_ISGID;
 	}
 
@@ -157,7 +159,8 @@ void setattr_copy(struct inode *inode, const struct iattr *attr)
 	if (ia_valid & ATTR_MODE) {
 		umode_t mode = attr->ia_mode;
 
-		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+		if (!in_group_p(inode->i_gid) &&
+		    !inode_capable(inode, CAP_FSETID))
 			mode &= ~S_ISGID;
 		inode->i_mode = mode;
 	}
@@ -184,6 +187,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
 			inode_inc_iversion(inode);
 	}
 
+	if ((ia_valid & ATTR_SIZE) && IS_I_VERSION(inode)) {
+		if (attr->ia_size != inode->i_size)
+			inode_inc_iversion(inode);
+	}
+
 	if ((ia_valid & ATTR_MODE)) {
 		umode_t amode = attr->ia_mode;
 		/* Flag setting protected by i_mutex */
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 908e184..b785e77 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -74,8 +74,8 @@ struct autofs_info {
 	unsigned long last_used;
 	atomic_t count;
 
-	uid_t uid;
-	gid_t gid;
+	kuid_t uid;
+	kgid_t gid;
 };
 
 #define AUTOFS_INF_EXPIRING	(1<<0) /* dentry is in the process of expiring */
@@ -89,8 +89,8 @@ struct autofs_wait_queue {
 	struct qstr name;
 	u32 dev;
 	u64 ino;
-	uid_t uid;
-	gid_t gid;
+	kuid_t uid;
+	kgid_t gid;
 	pid_t pid;
 	pid_t tgid;
 	/* This is for status reporting upon return */
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index a162141..9f68a37 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -437,8 +437,8 @@ static int autofs_dev_ioctl_requester(struct file *fp,
 		err = 0;
 		autofs4_expire_wait(path.dentry);
 		spin_lock(&sbi->fs_lock);
-		param->requester.uid = ino->uid;
-		param->requester.gid = ino->gid;
+		param->requester.uid = from_kuid_munged(current_user_ns(), ino->uid);
+		param->requester.gid = from_kgid_munged(current_user_ns(), ino->gid);
 		spin_unlock(&sbi->fs_lock);
 	}
 	path_put(&path);
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 8a4fed8..b104726 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -36,8 +36,8 @@ struct autofs_info *autofs4_new_ino(struct autofs_sb_info *sbi)
 
 void autofs4_clean_ino(struct autofs_info *ino)
 {
-	ino->uid = 0;
-	ino->gid = 0;
+	ino->uid = GLOBAL_ROOT_UID;
+	ino->gid = GLOBAL_ROOT_GID;
 	ino->last_used = jiffies;
 }
 
@@ -79,10 +79,12 @@ static int autofs4_show_options(struct seq_file *m, struct dentry *root)
 		return 0;
 
 	seq_printf(m, ",fd=%d", sbi->pipefd);
-	if (root_inode->i_uid != 0)
-		seq_printf(m, ",uid=%u", root_inode->i_uid);
-	if (root_inode->i_gid != 0)
-		seq_printf(m, ",gid=%u", root_inode->i_gid);
+	if (!uid_eq(root_inode->i_uid, GLOBAL_ROOT_UID))
+		seq_printf(m, ",uid=%u",
+			from_kuid_munged(&init_user_ns, root_inode->i_uid));
+	if (!gid_eq(root_inode->i_gid, GLOBAL_ROOT_GID))
+		seq_printf(m, ",gid=%u",
+			from_kgid_munged(&init_user_ns, root_inode->i_gid));
 	seq_printf(m, ",pgrp=%d", sbi->oz_pgrp);
 	seq_printf(m, ",timeout=%lu", sbi->exp_timeout/HZ);
 	seq_printf(m, ",minproto=%d", sbi->min_proto);
@@ -126,7 +128,7 @@ static const match_table_t tokens = {
 	{Opt_err, NULL}
 };
 
-static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
+static int parse_options(char *options, int *pipefd, kuid_t *uid, kgid_t *gid,
 		pid_t *pgrp, unsigned int *type, int *minproto, int *maxproto)
 {
 	char *p;
@@ -159,12 +161,16 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
 		case Opt_uid:
 			if (match_int(args, &option))
 				return 1;
-			*uid = option;
+			*uid = make_kuid(current_user_ns(), option);
+			if (!uid_valid(*uid))
+				return 1;
 			break;
 		case Opt_gid:
 			if (match_int(args, &option))
 				return 1;
-			*gid = option;
+			*gid = make_kgid(current_user_ns(), option);
+			if (!gid_valid(*gid))
+				return 1;
 			break;
 		case Opt_pgrp:
 			if (match_int(args, &option))
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 91b1165..13c21b1 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -583,7 +583,7 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
 	
 	/* This allows root to remove symlinks */
 	if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN))
-		return -EACCES;
+		return -EPERM;
 
 	if (atomic_dec_and_test(&ino->count)) {
 		p_ino = autofs4_dentry_ino(dentry->d_parent);
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index dce436e..03bc1d3 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -154,6 +154,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
 	case autofs_ptype_expire_direct:
 	{
 		struct autofs_v5_packet *packet = &pkt.v5_pkt.v5_packet;
+		struct user_namespace *user_ns = sbi->pipe->f_cred->user_ns;
 
 		pktsz = sizeof(*packet);
 
@@ -163,8 +164,8 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
 		packet->name[wq->name.len] = '\0';
 		packet->dev = wq->dev;
 		packet->ino = wq->ino;
-		packet->uid = wq->uid;
-		packet->gid = wq->gid;
+		packet->uid = from_kuid_munged(user_ns, wq->uid);
+		packet->gid = from_kgid_munged(user_ns, wq->gid);
 		packet->pid = wq->pid;
 		packet->tgid = wq->tgid;
 		break;
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 0e7a6f8..6043567 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -30,7 +30,7 @@
 #include <asm/cacheflush.h>
 #include <asm/a.out-core.h>
 
-static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
+static int load_aout_binary(struct linux_binprm *);
 static int load_aout_library(struct file*);
 
 #ifdef CONFIG_COREDUMP
@@ -201,8 +201,9 @@ static unsigned long __user *create_aout_tables(char __user *p, struct linux_bin
  * libraries.  There is no binary dependent code anywhere else.
  */
 
-static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+static int load_aout_binary(struct linux_binprm * bprm)
 {
+	struct pt_regs *regs = current_pt_regs();
 	struct exec ex;
 	unsigned long error;
 	unsigned long fd_offset;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index fbd9f60..9b67173 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -44,7 +44,7 @@
 #define user_siginfo_t siginfo_t
 #endif
 
-static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
+static int load_elf_binary(struct linux_binprm *bprm);
 static int load_elf_library(struct file *);
 static unsigned long elf_map(struct file *, unsigned long, struct elf_phdr *,
 				int, int, unsigned long);
@@ -139,6 +139,25 @@ static int padzero(unsigned long elf_bss)
 #define ELF_BASE_PLATFORM NULL
 #endif
 
+/*
+ * Use get_random_int() to implement AT_RANDOM while avoiding depletion
+ * of the entropy pool.
+ */
+static void get_atrandom_bytes(unsigned char *buf, size_t nbytes)
+{
+	unsigned char *p = buf;
+
+	while (nbytes) {
+		unsigned int random_variable;
+		size_t chunk = min(nbytes, sizeof(random_variable));
+
+		random_variable = get_random_int();
+		memcpy(p, &random_variable, chunk);
+		p += chunk;
+		nbytes -= chunk;
+	}
+}
+
 static int
 create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
 		unsigned long load_addr, unsigned long interp_load_addr)
@@ -200,7 +219,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
 	/*
 	 * Generate 16 random bytes for userspace PRNG seeding.
 	 */
-	get_random_bytes(k_rand_bytes, sizeof(k_rand_bytes));
+	get_atrandom_bytes(k_rand_bytes, sizeof(k_rand_bytes));
 	u_rand_bytes = (elf_addr_t __user *)
 		       STACK_ALLOC(p, sizeof(k_rand_bytes));
 	if (__copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes)))
@@ -558,7 +577,7 @@ static unsigned long randomize_stack_top(unsigned long stack_top)
 #endif
 }
 
-static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+static int load_elf_binary(struct linux_binprm *bprm)
 {
 	struct file *interpreter = NULL; /* to shut gcc up */
  	unsigned long load_addr = 0, load_bias = 0;
@@ -575,6 +594,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 	unsigned long reloc_func_desc __maybe_unused = 0;
 	int executable_stack = EXSTACK_DEFAULT;
 	unsigned long def_flags = 0;
+	struct pt_regs *regs = current_pt_regs();
 	struct {
 		struct elfhdr elf_ex;
 		struct elfhdr interp_elf_ex;
@@ -1600,8 +1620,10 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
 	info->thread = NULL;
 
 	psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL);
-	if (psinfo == NULL)
+	if (psinfo == NULL) {
+		info->psinfo.data = NULL; /* So we don't free this wrongly */
 		return 0;
+	}
 
 	fill_note(&info->psinfo, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo);
 
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index a460491..dc84732 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -56,7 +56,7 @@ typedef char *elf_caddr_t;
 
 MODULE_LICENSE("GPL");
 
-static int load_elf_fdpic_binary(struct linux_binprm *, struct pt_regs *);
+static int load_elf_fdpic_binary(struct linux_binprm *);
 static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *, struct file *);
 static int elf_fdpic_map_file(struct elf_fdpic_params *, struct file *,
 			      struct mm_struct *, const char *);
@@ -164,10 +164,10 @@ static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params,
 /*
  * load an fdpic binary into various bits of memory
  */
-static int load_elf_fdpic_binary(struct linux_binprm *bprm,
-				 struct pt_regs *regs)
+static int load_elf_fdpic_binary(struct linux_binprm *bprm)
 {
 	struct elf_fdpic_params exec_params, interp_params;
+	struct pt_regs *regs = current_pt_regs();
 	struct elf_phdr *phdr;
 	unsigned long stack_size, entryaddr;
 #ifdef ELF_FDPIC_PLAT_INIT
diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c
index 2790c7e..037a3e2 100644
--- a/fs/binfmt_em86.c
+++ b/fs/binfmt_em86.c
@@ -22,7 +22,7 @@
 #define EM86_INTERP	"/usr/bin/em86"
 #define EM86_I_NAME	"em86"
 
-static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
+static int load_em86(struct linux_binprm *bprm)
 {
 	char *interp, *i_name, *i_arg;
 	struct file * file;
@@ -42,7 +42,6 @@ static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
 			return -ENOEXEC;
 	}
 
-	bprm->recursion_depth++; /* Well, the bang-shell is implicit... */
 	allow_write_access(bprm->file);
 	fput(bprm->file);
 	bprm->file = NULL;
@@ -90,7 +89,7 @@ static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
 	if (retval < 0)
 		return retval;
 
-	return search_binary_handler(bprm, regs);
+	return search_binary_handler(bprm);
 }
 
 static struct linux_binfmt em86_format = {
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index e280352..b563719 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -88,7 +88,7 @@ struct lib_info {
 static int load_flat_shared_library(int id, struct lib_info *p);
 #endif
 
-static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
+static int load_flat_binary(struct linux_binprm *);
 static int flat_core_dump(struct coredump_params *cprm);
 
 static struct linux_binfmt flat_format = {
@@ -858,9 +858,10 @@ out:
  * libraries.  There is no binary dependent code anywhere else.
  */
 
-static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+static int load_flat_binary(struct linux_binprm * bprm)
 {
 	struct lib_info libinfo;
+	struct pt_regs *regs = current_pt_regs();
 	unsigned long p = bprm->p;
 	unsigned long stack_len;
 	unsigned long start_addr;
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 790b3cd..0c8869f 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -104,7 +104,7 @@ static Node *check_file(struct linux_binprm *bprm)
 /*
  * the loader itself
  */
-static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+static int load_misc_binary(struct linux_binprm *bprm)
 {
 	Node *fmt;
 	struct file * interp_file = NULL;
@@ -117,10 +117,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 	if (!enabled)
 		goto _ret;
 
-	retval = -ENOEXEC;
-	if (bprm->recursion_depth > BINPRM_MAX_RECURSION)
-		goto _ret;
-
 	/* to keep locking time low, we copy the interpreter string */
 	read_lock(&entries_lock);
 	fmt = check_file(bprm);
@@ -176,7 +172,10 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 		goto _error;
 	bprm->argc ++;
 
-	bprm->interp = iname;	/* for binfmt_script */
+	/* Update interp in case binfmt_script needs it. */
+	retval = bprm_change_interp(iname, bprm);
+	if (retval < 0)
+		goto _error;
 
 	interp_file = open_exec (iname);
 	retval = PTR_ERR (interp_file);
@@ -197,9 +196,7 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 	if (retval < 0)
 		goto _error;
 
-	bprm->recursion_depth++;
-
-	retval = search_binary_handler (bprm, regs);
+	retval = search_binary_handler(bprm);
 	if (retval < 0)
 		goto _error;
 
diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c
index d3b8c1f..5027a3e 100644
--- a/fs/binfmt_script.c
+++ b/fs/binfmt_script.c
@@ -14,7 +14,7 @@
 #include <linux/err.h>
 #include <linux/fs.h>
 
-static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
+static int load_script(struct linux_binprm *bprm)
 {
 	const char *i_arg, *i_name;
 	char *cp;
@@ -22,15 +22,13 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
 	char interp[BINPRM_BUF_SIZE];
 	int retval;
 
-	if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') ||
-	    (bprm->recursion_depth > BINPRM_MAX_RECURSION))
+	if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
 		return -ENOEXEC;
 	/*
 	 * This section does the #! interpretation.
 	 * Sorta complicated, but hopefully it will work.  -TYT
 	 */
 
-	bprm->recursion_depth++;
 	allow_write_access(bprm->file);
 	fput(bprm->file);
 	bprm->file = NULL;
@@ -82,7 +80,9 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
 	retval = copy_strings_kernel(1, &i_name, bprm);
 	if (retval) return retval; 
 	bprm->argc++;
-	bprm->interp = interp;
+	retval = bprm_change_interp(interp, bprm);
+	if (retval < 0)
+		return retval;
 
 	/*
 	 * OK, now restart the process with the interpreter's dentry.
@@ -95,7 +95,7 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
 	retval = prepare_binprm(bprm);
 	if (retval < 0)
 		return retval;
-	return search_binary_handler(bprm,regs);
+	return search_binary_handler(bprm);
 }
 
 static struct linux_binfmt script_format = {
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c
index 4517aaf..4e00ed6 100644
--- a/fs/binfmt_som.c
+++ b/fs/binfmt_som.c
@@ -35,7 +35,7 @@
 
 #include <linux/elf.h>
 
-static int load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs);
+static int load_som_binary(struct linux_binprm * bprm);
 static int load_som_library(struct file *);
 
 /*
@@ -180,13 +180,14 @@ out:
  */
 
 static int
-load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+load_som_binary(struct linux_binprm * bprm)
 {
 	int retval;
 	unsigned int size;
 	unsigned long som_entry;
 	struct som_hdr *som_ex;
 	struct som_exec_auxhdr *hpuxhdr;
+	struct pt_regs *regs = current_pt_regs();
 
 	/* Get the exec-header */
 	som_ex = (struct som_hdr *) bprm->buf;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 1a1e5e3..eb0553c 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -695,11 +695,9 @@ void bd_forget(struct inode *inode)
 	struct block_device *bdev = NULL;
 
 	spin_lock(&bdev_lock);
-	if (inode->i_bdev) {
-		if (!sb_is_blkdev_sb(inode->i_sb))
-			bdev = inode->i_bdev;
-		__bd_forget(inode);
-	}
+	if (!sb_is_blkdev_sb(inode->i_sb))
+		bdev = inode->i_bdev;
+	__bd_forget(inode);
 	spin_unlock(&bdev_lock);
 
 	if (bdev)
@@ -1073,6 +1071,7 @@ int revalidate_disk(struct gendisk *disk)
 
 	mutex_lock(&bdev->bd_mutex);
 	check_disk_size_change(disk, bdev);
+	bdev->bd_invalidated = 0;
 	mutex_unlock(&bdev->bd_mutex);
 	bdput(bdev);
 	return ret;
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index c72ead8..596617e 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -413,7 +413,7 @@ struct btrfs_root_backup {
 	__le64 bytes_used;
 	__le64 num_devices;
 	/* future */
-	__le64 unsed_64[4];
+	__le64 unused_64[4];
 
 	u8 tree_root_level;
 	u8 chunk_root_level;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 7cda519..22a0439 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3416,8 +3416,8 @@ void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr)
 	num_dirty = root->fs_info->dirty_metadata_bytes;
 
 	if (num_dirty > thresh) {
-		balance_dirty_pages_ratelimited_nr(
-				   root->fs_info->btree_inode->i_mapping, 1);
+		balance_dirty_pages_ratelimited(
+				   root->fs_info->btree_inode->i_mapping);
 	}
 	return;
 }
@@ -3437,8 +3437,8 @@ void __btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr)
 	num_dirty = root->fs_info->dirty_metadata_bytes;
 
 	if (num_dirty > thresh) {
-		balance_dirty_pages_ratelimited_nr(
-				   root->fs_info->btree_inode->i_mapping, 1);
+		balance_dirty_pages_ratelimited(
+				   root->fs_info->btree_inode->i_mapping);
 	}
 	return;
 }
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 3d3e2c1..06b2635 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3888,7 +3888,7 @@ static int flush_space(struct btrfs_root *root,
  * @root - the root we're allocating for
  * @block_rsv - the block_rsv we're allocating for
  * @orig_bytes - the number of bytes we want
- * @flush - wether or not we can flush to make our reservation
+ * @flush - whether or not we can flush to make our reservation
  *
  * This will reserve orgi_bytes number of bytes from the space info associated
  * with the block_rsv.  If there is not enough space it will make an attempt to
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index b8cbc8d..ce9f792 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -234,12 +234,11 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
 }
 
 /**
- * unpint_extent_cache - unpin an extent from the cache
+ * unpin_extent_cache - unpin an extent from the cache
  * @tree:	tree to unpin the extent in
  * @start:	logical offset in the file
  * @len:	length of the extent
  * @gen:	generation that this extent has been modified in
- * @prealloc:	if this is set we need to clear the prealloc flag
  *
  * Called after an extent has been written to disk properly.  Set the generation
  * to the generation that actually added the file item to the inode so we know
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 9ab1bed..a8ee75c 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1346,8 +1346,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
 
 		cond_resched();
 
-		balance_dirty_pages_ratelimited_nr(inode->i_mapping,
-						   dirty_pages);
+		balance_dirty_pages_ratelimited(inode->i_mapping);
 		if (dirty_pages < (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
 			btrfs_btree_balance_dirty(root, 1);
 
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 8fcf9a5..5b3429a 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1225,7 +1225,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
 		}
 
 		defrag_count += ret;
-		balance_dirty_pages_ratelimited_nr(inode->i_mapping, ret);
+		balance_dirty_pages_ratelimited(inode->i_mapping);
 		mutex_unlock(&inode->i_mutex);
 
 		if (newer_than) {
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h
index dd27a0b..853fc7b 100644
--- a/fs/btrfs/ordered-data.h
+++ b/fs/btrfs/ordered-data.h
@@ -76,7 +76,7 @@ struct btrfs_ordered_sum {
 
 #define BTRFS_ORDERED_IOERR 6 /* We had an io error when writing this out */
 
-#define BTRFS_ORDERED_UPDATED_ISIZE 7 /* indicates wether this ordered extent
+#define BTRFS_ORDERED_UPDATED_ISIZE 7 /* indicates whether this ordered extent
 				       * has done its due diligence in updating
 				       * the isize. */
 
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 0f5ebb7..e3c6ee3 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -4294,7 +4294,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
 
 			rcu_read_lock();
 			name = rcu_dereference(dev->name);
-			pr_debug("btrfs_map_bio: rw %d, secor=%llu, dev=%lu "
+			pr_debug("btrfs_map_bio: rw %d, sector=%llu, dev=%lu "
 				 "(%s id %llu), size=%u\n", rw,
 				 (u64)bio->bi_sector, (u_long)dev->bdev->bd_dev,
 				 name->str, dev->devid, bio->bi_size);
diff --git a/fs/buffer.c b/fs/buffer.c
index b5f0442..7f86e0d 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -46,8 +46,7 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
 
 #define BH_ENTRY(list) list_entry((list), struct buffer_head, b_assoc_buffers)
 
-inline void
-init_buffer(struct buffer_head *bh, bh_end_io_t *handler, void *private)
+void init_buffer(struct buffer_head *bh, bh_end_io_t *handler, void *private)
 {
 	bh->b_end_io = handler;
 	bh->b_private = private;
@@ -555,7 +554,7 @@ void emergency_thaw_all(void)
  */
 int sync_mapping_buffers(struct address_space *mapping)
 {
-	struct address_space *buffer_mapping = mapping->assoc_mapping;
+	struct address_space *buffer_mapping = mapping->private_data;
 
 	if (buffer_mapping == NULL || list_empty(&mapping->private_list))
 		return 0;
@@ -588,10 +587,10 @@ void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode)
 	struct address_space *buffer_mapping = bh->b_page->mapping;
 
 	mark_buffer_dirty(bh);
-	if (!mapping->assoc_mapping) {
-		mapping->assoc_mapping = buffer_mapping;
+	if (!mapping->private_data) {
+		mapping->private_data = buffer_mapping;
 	} else {
-		BUG_ON(mapping->assoc_mapping != buffer_mapping);
+		BUG_ON(mapping->private_data != buffer_mapping);
 	}
 	if (!bh->b_assoc_map) {
 		spin_lock(&buffer_mapping->private_lock);
@@ -788,7 +787,7 @@ void invalidate_inode_buffers(struct inode *inode)
 	if (inode_has_buffers(inode)) {
 		struct address_space *mapping = &inode->i_data;
 		struct list_head *list = &mapping->private_list;
-		struct address_space *buffer_mapping = mapping->assoc_mapping;
+		struct address_space *buffer_mapping = mapping->private_data;
 
 		spin_lock(&buffer_mapping->private_lock);
 		while (!list_empty(list))
@@ -811,7 +810,7 @@ int remove_inode_buffers(struct inode *inode)
 	if (inode_has_buffers(inode)) {
 		struct address_space *mapping = &inode->i_data;
 		struct list_head *list = &mapping->private_list;
-		struct address_space *buffer_mapping = mapping->assoc_mapping;
+		struct address_space *buffer_mapping = mapping->private_data;
 
 		spin_lock(&buffer_mapping->private_lock);
 		while (!list_empty(list)) {
@@ -850,13 +849,10 @@ try_again:
 		if (!bh)
 			goto no_grow;
 
-		bh->b_bdev = NULL;
 		bh->b_this_page = head;
 		bh->b_blocknr = -1;
 		head = bh;
 
-		bh->b_state = 0;
-		atomic_set(&bh->b_count, 0);
 		bh->b_size = size;
 
 		/* Link the buffer to its page */
diff --git a/fs/ceph/Kconfig b/fs/ceph/Kconfig
index 9eb134e..49bc782 100644
--- a/fs/ceph/Kconfig
+++ b/fs/ceph/Kconfig
@@ -1,6 +1,6 @@
 config CEPH_FS
-        tristate "Ceph distributed file system (EXPERIMENTAL)"
-	depends on INET && EXPERIMENTAL
+	tristate "Ceph distributed file system"
+	depends on INET
 	select CEPH_LIB
 	select LIBCRC32C
 	select CRYPTO_AES
diff --git a/fs/ceph/export.c b/fs/ceph/export.c
index 9349bb3..ca3ab3f 100644
--- a/fs/ceph/export.c
+++ b/fs/ceph/export.c
@@ -56,13 +56,15 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
 	struct ceph_nfs_confh *cfh = (void *)rawfh;
 	int connected_handle_length = sizeof(*cfh)/4;
 	int handle_length = sizeof(*fh)/4;
-	struct dentry *dentry = d_find_alias(inode);
+	struct dentry *dentry;
 	struct dentry *parent;
 
 	/* don't re-export snaps */
 	if (ceph_snap(inode) != CEPH_NOSNAP)
 		return -EINVAL;
 
+	dentry = d_find_alias(inode);
+
 	/* if we found an alias, generate a connectable fh */
 	if (*max_len >= connected_handle_length && dentry) {
 		dout("encode_fh %p connectable\n", dentry);
diff --git a/fs/cifs/README b/fs/cifs/README
index 22ab7b5..2d5622f 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -480,7 +480,7 @@ A partial list of the supported mount options follows:
 		Unicode on the wire.
  nomapchars     Do not translate any of these seven characters (default).
  nocase         Request case insensitive path name matching (case
-		sensitive is the default if the server suports it).
+		sensitive is the default if the server supports it).
 		(mount option "ignorecase" is identical to "nocase")
  posixpaths     If CIFS Unix extensions are supported, attempt to
 		negotiate posix path name support which allows certain
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 0fb15bb..0b24312 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -42,7 +42,7 @@ static const struct cifs_sid sid_authusers = {
 /* group users */
 static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
 
-const struct cred *root_cred;
+static const struct cred *root_cred;
 
 static void
 shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem,
@@ -187,7 +187,7 @@ cifs_idmap_key_destroy(struct key *key)
 	kfree(key->payload.data);
 }
 
-struct key_type cifs_idmap_key_type = {
+static struct key_type cifs_idmap_key_type = {
 	.name        = "cifs.idmap",
 	.instantiate = cifs_idmap_key_instantiate,
 	.destroy     = cifs_idmap_key_destroy,
@@ -199,36 +199,89 @@ static void
 sid_to_str(struct cifs_sid *sidptr, char *sidstr)
 {
 	int i;
-	unsigned long saval;
+	unsigned int saval;
 	char *strptr;
 
 	strptr = sidstr;
 
-	sprintf(strptr, "%s", "S");
+	sprintf(strptr, "S-%hhu", sidptr->revision);
 	strptr = sidstr + strlen(sidstr);
 
-	sprintf(strptr, "-%d", sidptr->revision);
-	strptr = sidstr + strlen(sidstr);
-
-	for (i = 0; i < 6; ++i) {
+	for (i = 0; i < NUM_AUTHS; ++i) {
 		if (sidptr->authority[i]) {
-			sprintf(strptr, "-%d", sidptr->authority[i]);
+			sprintf(strptr, "-%hhu", sidptr->authority[i]);
 			strptr = sidstr + strlen(sidstr);
 		}
 	}
 
 	for (i = 0; i < sidptr->num_subauth; ++i) {
 		saval = le32_to_cpu(sidptr->sub_auth[i]);
-		sprintf(strptr, "-%ld", saval);
+		sprintf(strptr, "-%u", saval);
 		strptr = sidstr + strlen(sidstr);
 	}
 }
 
+/*
+ * if the two SIDs (roughly equivalent to a UUID for a user or group) are
+ * the same returns zero, if they do not match returns non-zero.
+ */
+static int
+compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
+{
+	int i;
+	int num_subauth, num_sat, num_saw;
+
+	if ((!ctsid) || (!cwsid))
+		return 1;
+
+	/* compare the revision */
+	if (ctsid->revision != cwsid->revision) {
+		if (ctsid->revision > cwsid->revision)
+			return 1;
+		else
+			return -1;
+	}
+
+	/* compare all of the six auth values */
+	for (i = 0; i < NUM_AUTHS; ++i) {
+		if (ctsid->authority[i] != cwsid->authority[i]) {
+			if (ctsid->authority[i] > cwsid->authority[i])
+				return 1;
+			else
+				return -1;
+		}
+	}
+
+	/* compare all of the subauth values if any */
+	num_sat = ctsid->num_subauth;
+	num_saw = cwsid->num_subauth;
+	num_subauth = num_sat < num_saw ? num_sat : num_saw;
+	if (num_subauth) {
+		for (i = 0; i < num_subauth; ++i) {
+			if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
+				if (le32_to_cpu(ctsid->sub_auth[i]) >
+					le32_to_cpu(cwsid->sub_auth[i]))
+					return 1;
+				else
+					return -1;
+			}
+		}
+	}
+
+	return 0; /* sids compare/match */
+}
+
 static void
 cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
 {
-	memcpy(dst, src, sizeof(*dst));
-	dst->num_subauth = min_t(u8, src->num_subauth, NUM_SUBAUTHS);
+	int i;
+
+	dst->revision = src->revision;
+	dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
+	for (i = 0; i < NUM_AUTHS; ++i)
+		dst->authority[i] = src->authority[i];
+	for (i = 0; i < dst->num_subauth; ++i)
+		dst->sub_auth[i] = src->sub_auth[i];
 }
 
 static void
@@ -327,7 +380,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
 		if (!npsidid)
 			return -ENOMEM;
 
-		npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL);
+		npsidid->sidstr = kmalloc(SID_STRING_MAX, GFP_KERNEL);
 		if (!npsidid->sidstr) {
 			kfree(npsidid);
 			return -ENOMEM;
@@ -377,7 +430,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
 		if (IS_ERR(sidkey)) {
 			rc = -EINVAL;
 			cFYI(1, "%s: Can't map and id to a SID", __func__);
-		} else if (sidkey->datalen < sizeof(struct cifs_sid)) {
+		} else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
 			rc = -EIO;
 			cFYI(1, "%s: Downcall contained malformed key "
 				"(datalen=%hu)", __func__, sidkey->datalen);
@@ -444,7 +497,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
 		if (!npsidid)
 			return -ENOMEM;
 
-		npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL);
+		npsidid->sidstr = kmalloc(SID_STRING_MAX, GFP_KERNEL);
 		if (!npsidid->sidstr) {
 			kfree(npsidid);
 			return -ENOMEM;
@@ -544,19 +597,15 @@ init_cifs_idmap(void)
 	if (!cred)
 		return -ENOMEM;
 
-	keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred,
-			    (KEY_POS_ALL & ~KEY_POS_SETATTR) |
-			    KEY_USR_VIEW | KEY_USR_READ,
-			    KEY_ALLOC_NOT_IN_QUOTA);
+	keyring = keyring_alloc(".cifs_idmap", 0, 0, cred,
+				(KEY_POS_ALL & ~KEY_POS_SETATTR) |
+				KEY_USR_VIEW | KEY_USR_READ,
+				KEY_ALLOC_NOT_IN_QUOTA, NULL);
 	if (IS_ERR(keyring)) {
 		ret = PTR_ERR(keyring);
 		goto failed_put_cred;
 	}
 
-	ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
-	if (ret < 0)
-		goto failed_put_key;
-
 	ret = register_key_type(&cifs_idmap_key_type);
 	if (ret < 0)
 		goto failed_put_key;
@@ -630,54 +679,6 @@ cifs_destroy_idmaptrees(void)
 	spin_unlock(&gidsidlock);
 }
 
-/* if the two SIDs (roughly equivalent to a UUID for a user or group) are
-   the same returns 1, if they do not match returns 0 */
-int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
-{
-	int i;
-	int num_subauth, num_sat, num_saw;
-
-	if ((!ctsid) || (!cwsid))
-		return 1;
-
-	/* compare the revision */
-	if (ctsid->revision != cwsid->revision) {
-		if (ctsid->revision > cwsid->revision)
-			return 1;
-		else
-			return -1;
-	}
-
-	/* compare all of the six auth values */
-	for (i = 0; i < 6; ++i) {
-		if (ctsid->authority[i] != cwsid->authority[i]) {
-			if (ctsid->authority[i] > cwsid->authority[i])
-				return 1;
-			else
-				return -1;
-		}
-	}
-
-	/* compare all of the subauth values if any */
-	num_sat = ctsid->num_subauth;
-	num_saw = cwsid->num_subauth;
-	num_subauth = num_sat < num_saw ? num_sat : num_saw;
-	if (num_subauth) {
-		for (i = 0; i < num_subauth; ++i) {
-			if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
-				if (le32_to_cpu(ctsid->sub_auth[i]) >
-					le32_to_cpu(cwsid->sub_auth[i]))
-					return 1;
-				else
-					return -1;
-			}
-		}
-	}
-
-	return 0; /* sids compare/match */
-}
-
-
 /* copy ntsd, owner sid, and group sid from a security descriptor to another */
 static void copy_sec_desc(const struct cifs_ntsd *pntsd,
 				struct cifs_ntsd *pnntsd, __u32 sidsoffset)
@@ -811,7 +812,7 @@ static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
 
 	pntace->sid.revision = psid->revision;
 	pntace->sid.num_subauth = psid->num_subauth;
-	for (i = 0; i < 6; i++)
+	for (i = 0; i < NUM_AUTHS; i++)
 		pntace->sid.authority[i] = psid->authority[i];
 	for (i = 0; i < psid->num_subauth; i++)
 		pntace->sid.sub_auth[i] = psid->sub_auth[i];
@@ -987,8 +988,8 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
 		return -EINVAL;
 	}
 
-	if (psid->num_subauth) {
 #ifdef CONFIG_CIFS_DEBUG2
+	if (psid->num_subauth) {
 		int i;
 		cFYI(1, "SID revision %d num_auth %d",
 			psid->revision, psid->num_subauth);
@@ -1002,8 +1003,8 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
 			num auths and therefore go off the end */
 		cFYI(1, "RID 0x%x",
 			le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
-#endif
 	}
+#endif
 
 	return 0;
 }
@@ -1307,42 +1308,39 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
 
 	/* Get the security descriptor */
 	pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
-
-	/* Add three ACEs for owner, group, everyone getting rid of
-	   other ACEs as chmod disables ACEs and set the security descriptor */
-
 	if (IS_ERR(pntsd)) {
 		rc = PTR_ERR(pntsd);
 		cERROR(1, "%s: error %d getting sec desc", __func__, rc);
-	} else {
-		/* allocate memory for the smb header,
-		   set security descriptor request security descriptor
-		   parameters, and secuirty descriptor itself */
-
-		secdesclen = secdesclen < DEFSECDESCLEN ?
-					DEFSECDESCLEN : secdesclen;
-		pnntsd = kmalloc(secdesclen, GFP_KERNEL);
-		if (!pnntsd) {
-			cERROR(1, "Unable to allocate security descriptor");
-			kfree(pntsd);
-			return -ENOMEM;
-		}
+		goto out;
+	}
 
-		rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
-					&aclflag);
+	/*
+	 * Add three ACEs for owner, group, everyone getting rid of other ACEs
+	 * as chmod disables ACEs and set the security descriptor. Allocate
+	 * memory for the smb header, set security descriptor request security
+	 * descriptor parameters, and secuirty descriptor itself
+	 */
+	secdesclen = max_t(u32, secdesclen, DEFSECDESCLEN);
+	pnntsd = kmalloc(secdesclen, GFP_KERNEL);
+	if (!pnntsd) {
+		cERROR(1, "Unable to allocate security descriptor");
+		kfree(pntsd);
+		return -ENOMEM;
+	}
 
-		cFYI(DBG2, "build_sec_desc rc: %d", rc);
+	rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
+				&aclflag);
 
-		if (!rc) {
-			/* Set the security descriptor */
-			rc = set_cifs_acl(pnntsd, secdesclen, inode,
-						path, aclflag);
-			cFYI(DBG2, "set_cifs_acl rc: %d", rc);
-		}
+	cFYI(DBG2, "build_sec_desc rc: %d", rc);
 
-		kfree(pnntsd);
-		kfree(pntsd);
+	if (!rc) {
+		/* Set the security descriptor */
+		rc = set_cifs_acl(pnntsd, secdesclen, inode, path, aclflag);
+		cFYI(DBG2, "set_cifs_acl rc: %d", rc);
 	}
 
+	kfree(pnntsd);
+	kfree(pntsd);
+out:
 	return rc;
 }
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
index 5c902c7..249c94f 100644
--- a/fs/cifs/cifsacl.h
+++ b/fs/cifs/cifsacl.h
@@ -24,7 +24,7 @@
 
 
 #define NUM_AUTHS 6 /* number of authority fields */
-#define NUM_SUBAUTHS 5 /* number of sub authority fields */
+#define SID_MAX_SUB_AUTHORITIES (15) /* max number of sub authority fields */
 #define NUM_WK_SIDS 7 /* number of well known sids */
 #define SIDNAMELENGTH 20 /* long enough for the ones we care about */
 #define DEFSECDESCLEN 192 /* sec desc len contaiting a dacl with three aces */
@@ -41,7 +41,20 @@
 
 #define SIDOWNER 1
 #define SIDGROUP 2
-#define SIDLEN 150 /* S- 1 revision- 6 authorities- max 5 sub authorities */
+
+/*
+ * Maximum size of a string representation of a SID:
+ *
+ * The fields are unsigned values in decimal. So:
+ *
+ * u8:  max 3 bytes in decimal
+ * u32: max 10 bytes in decimal
+ *
+ * "S-" + 3 bytes for version field + 4 bytes for each authority field (3 bytes
+ * per number + 1 for '-') + 11 bytes for each subauthority field (10 bytes
+ * per number + 1 for '-') + NULL terminator.
+ */
+#define SID_STRING_MAX (195)
 
 #define SID_ID_MAPPED 0
 #define SID_ID_PENDING 1
@@ -60,10 +73,13 @@ struct cifs_ntsd {
 struct cifs_sid {
 	__u8 revision; /* revision level */
 	__u8 num_subauth;
-	__u8 authority[6];
-	__le32 sub_auth[5]; /* sub_auth[num_subauth] */
+	__u8 authority[NUM_AUTHS];
+	__le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */
 } __attribute__((packed));
 
+/* size of a struct cifs_sid, sans sub_auth array */
+#define CIFS_SID_BASE_SIZE (1 + 1 + NUM_AUTHS)
+
 struct cifs_acl {
 	__le16 revision; /* revision level */
 	__le16 size;
@@ -93,11 +109,4 @@ struct cifs_sid_id {
 	struct cifs_sid sid;
 };
 
-#ifdef __KERNEL__
-extern struct key_type cifs_idmap_key_type;
-extern const struct cred *root_cred;
-#endif /* KERNEL */
-
-extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *);
-
 #endif /* _CIFSACL_H */
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index e7931cc..07a8ab52 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -64,24 +64,23 @@ unsigned int global_secflags = CIFSSEC_DEF;
 unsigned int sign_CIFS_PDUs = 1;
 static const struct super_operations cifs_super_ops;
 unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
-module_param(CIFSMaxBufSize, int, 0);
+module_param(CIFSMaxBufSize, uint, 0);
 MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header). "
 				 "Default: 16384 Range: 8192 to 130048");
 unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
-module_param(cifs_min_rcv, int, 0);
+module_param(cifs_min_rcv, uint, 0);
 MODULE_PARM_DESC(cifs_min_rcv, "Network buffers in pool. Default: 4 Range: "
 				"1 to 64");
 unsigned int cifs_min_small = 30;
-module_param(cifs_min_small, int, 0);
+module_param(cifs_min_small, uint, 0);
 MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 "
 				 "Range: 2 to 256");
 unsigned int cifs_max_pending = CIFS_MAX_REQ;
-module_param(cifs_max_pending, int, 0444);
+module_param(cifs_max_pending, uint, 0444);
 MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. "
 				   "Default: 32767 Range: 2 to 32767.");
 module_param(enable_oplocks, bool, 0644);
-MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks (bool). Default:"
-				 "y/Y/1");
+MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks. Default: y/Y/1");
 
 extern mempool_t *cifs_sm_req_poolp;
 extern mempool_t *cifs_req_poolp;
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index f5af252..2cd5ea2 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1362,7 +1362,7 @@ require use of the stronger protocol */
 #define   CIFSSEC_MUST_SEAL	0x40040 /* not supported yet */
 #define   CIFSSEC_MUST_NTLMSSP	0x80080 /* raw ntlmssp with ntlmv2 */
 
-#define   CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_NTLMSSP)
+#define   CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLMSSP)
 #define   CIFSSEC_MAX (CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2)
 #define   CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP)
 /*
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 5c670b9..a483872 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1799,6 +1799,11 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 		goto cifs_parse_mount_err;
 	}
 #endif
+	if (!vol->UNC) {
+		cERROR(1, "CIFS mount error: No UNC path (e.g. -o "
+			"unc=\\\\192.168.1.100\\public) specified");
+		goto cifs_parse_mount_err;
+	}
 
 	if (vol->UNCip == NULL)
 		vol->UNCip = &vol->UNC[2];
@@ -2070,17 +2075,6 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
 			rc = -EINVAL;
 			goto out_err;
 		}
-	} else if (volume_info->UNCip) {
-		/* BB using ip addr as tcp_ses name to connect to the
-		   DFS root below */
-		cERROR(1, "Connecting to DFS root not implemented yet");
-		rc = -EINVAL;
-		goto out_err;
-	} else /* which tcp_sess DFS root would we conect to */ {
-		cERROR(1, "CIFS mount error: No UNC path (e.g. -o "
-			"unc=//192.168.1.100/public) specified");
-		rc = -EINVAL;
-		goto out_err;
 	}
 
 	/* see if we already have a matching tcp_ses */
@@ -2397,8 +2391,6 @@ cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
 }
 #endif /* CONFIG_KEYS */
 
-static bool warned_on_ntlm;  /* globals init to false automatically */
-
 static struct cifs_ses *
 cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
 {
@@ -2475,14 +2467,6 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
 	ses->cred_uid = volume_info->cred_uid;
 	ses->linux_uid = volume_info->linux_uid;
 
-	/* ntlmv2 is much stronger than ntlm security, and has been broadly
-	supported for many years, time to update default security mechanism */
-	if ((volume_info->secFlg == 0) && warned_on_ntlm == false) {
-		warned_on_ntlm = true;
-		cERROR(1, "default security mechanism requested.  The default "
-			"security mechanism will be upgraded from ntlm to "
-			"ntlmv2 in kernel release 3.3");
-	}
 	ses->overrideSecFlg = volume_info->secFlg;
 
 	mutex_lock(&ses->session_mutex);
@@ -2736,9 +2720,6 @@ cifs_match_super(struct super_block *sb, void *data)
 
 	volume_info = mnt_data->vol;
 
-	if (!volume_info->UNCip || !volume_info->UNC)
-		goto out;
-
 	rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
 				volume_info->UNCip,
 				strlen(volume_info->UNCip),
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index edb25b4..70b6f4c 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1794,7 +1794,6 @@ static int cifs_writepages(struct address_space *mapping,
 	struct TCP_Server_Info *server;
 	struct page *page;
 	int rc = 0;
-	loff_t isize = i_size_read(mapping->host);
 
 	/*
 	 * If wsize is smaller than the page cache size, default to writing
@@ -1899,7 +1898,7 @@ retry:
 			 */
 			set_page_writeback(page);
 
-			if (page_offset(page) >= isize) {
+			if (page_offset(page) >= i_size_read(mapping->host)) {
 				done = true;
 				unlock_page(page);
 				end_page_writeback(page);
@@ -1932,7 +1931,8 @@ retry:
 		wdata->offset = page_offset(wdata->pages[0]);
 		wdata->pagesz = PAGE_CACHE_SIZE;
 		wdata->tailsz =
-			min(isize - page_offset(wdata->pages[nr_pages - 1]),
+			min(i_size_read(mapping->host) -
+			    page_offset(wdata->pages[nr_pages - 1]),
 			    (loff_t)PAGE_CACHE_SIZE);
 		wdata->bytes = ((nr_pages - 1) * PAGE_CACHE_SIZE) +
 					wdata->tailsz;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index afdff79..ed6208f 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1791,11 +1791,12 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
 	stat->ino = CIFS_I(inode)->uniqueid;
 
 	/*
-	 * If on a multiuser mount without unix extensions, and the admin hasn't
-	 * overridden them, set the ownership to the fsuid/fsgid of the current
-	 * process.
+	 * If on a multiuser mount without unix extensions or cifsacl being
+	 * enabled, and the admin hasn't overridden them, set the ownership
+	 * to the fsuid/fsgid of the current process.
 	 */
 	if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
+	    !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
 	    !tcon->unix_ext) {
 		if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
 			stat->uid = current_fsuid();
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 56cc4be..34cea27 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -766,7 +766,6 @@ smb_set_file_info(struct inode *inode, const char *full_path,
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
 	struct tcon_link *tlink = NULL;
 	struct cifs_tcon *tcon;
-	FILE_BASIC_INFO info_buf;
 
 	/* if the file is already open for write, just use that fileid */
 	open_file = find_writable_file(cinode, true);
@@ -817,7 +816,7 @@ smb_set_file_info(struct inode *inode, const char *full_path,
 	netpid = current->tgid;
 
 set_via_filehandle:
-	rc = CIFSSMBSetFileInfo(xid, tcon, &info_buf, netfid, netpid);
+	rc = CIFSSMBSetFileInfo(xid, tcon, buf, netfid, netpid);
 	if (!rc)
 		cinode->cifsAttrs = le32_to_cpu(buf->Attributes);
 
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 4c6285f..e2f57a0 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -844,6 +844,9 @@ COMPATIBLE_IOCTL(TIOCGDEV)
 COMPATIBLE_IOCTL(TIOCCBRK)
 COMPATIBLE_IOCTL(TIOCGSID)
 COMPATIBLE_IOCTL(TIOCGICOUNT)
+COMPATIBLE_IOCTL(TIOCGPKT)
+COMPATIBLE_IOCTL(TIOCGPTLCK)
+COMPATIBLE_IOCTL(TIOCGEXCL)
 /* Little t */
 COMPATIBLE_IOCTL(TIOCGETD)
 COMPATIBLE_IOCTL(TIOCSETD)
diff --git a/fs/coredump.c b/fs/coredump.c
index ce47379..1774932 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -458,7 +458,7 @@ static int umh_pipe_setup(struct subprocess_info *info, struct cred *new)
 	return err;
 }
 
-void do_coredump(siginfo_t *siginfo, struct pt_regs *regs)
+void do_coredump(siginfo_t *siginfo)
 {
 	struct core_state core_state;
 	struct core_name cn;
@@ -474,7 +474,7 @@ void do_coredump(siginfo_t *siginfo, struct pt_regs *regs)
 	static atomic_t core_dump_count = ATOMIC_INIT(0);
 	struct coredump_params cprm = {
 		.siginfo = siginfo,
-		.regs = regs,
+		.regs = signal_pt_regs(),
 		.limit = rlimit(RLIMIT_CORE),
 		/*
 		 * We must use the same mm->flags while dumping core to avoid
diff --git a/fs/dcache.c b/fs/dcache.c
index 3a463d0..0d0adb6 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1583,7 +1583,7 @@ EXPORT_SYMBOL(d_find_any_alias);
  */
 struct dentry *d_obtain_alias(struct inode *inode)
 {
-	static const struct qstr anonstring = { .name = "" };
+	static const struct qstr anonstring = QSTR_INIT("/", 1);
 	struct dentry *tmp;
 	struct dentry *res;
 
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index b607d92..153bb1e 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -59,7 +59,6 @@ static struct inode *debugfs_get_inode(struct super_block *sb, umode_t mode, dev
 		case S_IFDIR:
 			inode->i_op = &simple_dir_inode_operations;
 			inode->i_fop = &simple_dir_operations;
-			inode->i_private = NULL;
 
 			/* directory inodes start off with i_nlink == 2
 			 * (for "." entry) */
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 14afbab..472e6be 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -545,37 +545,38 @@ void devpts_kill_index(struct inode *ptmx_inode, int idx)
 	mutex_unlock(&allocated_ptys_lock);
 }
 
-int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)
+/**
+ * devpts_pty_new -- create a new inode in /dev/pts/
+ * @ptmx_inode: inode of the master
+ * @device: major+minor of the node to be created
+ * @index: used as a name of the node
+ * @priv: what's given back by devpts_get_priv
+ *
+ * The created inode is returned. Remove it from /dev/pts/ by devpts_pty_kill.
+ */
+struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index,
+		void *priv)
 {
-	/* tty layer puts index from devpts_new_index() in here */
-	int number = tty->index;
-	struct tty_driver *driver = tty->driver;
-	dev_t device = MKDEV(driver->major, driver->minor_start+number);
 	struct dentry *dentry;
 	struct super_block *sb = pts_sb_from_inode(ptmx_inode);
-	struct inode *inode = new_inode(sb);
+	struct inode *inode;
 	struct dentry *root = sb->s_root;
 	struct pts_fs_info *fsi = DEVPTS_SB(sb);
 	struct pts_mount_opts *opts = &fsi->mount_opts;
-	int ret = 0;
 	char s[12];
 
-	/* We're supposed to be given the slave end of a pty */
-	BUG_ON(driver->type != TTY_DRIVER_TYPE_PTY);
-	BUG_ON(driver->subtype != PTY_TYPE_SLAVE);
-
+	inode = new_inode(sb);
 	if (!inode)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
-	inode->i_ino = number + 3;
+	inode->i_ino = index + 3;
 	inode->i_uid = opts->setuid ? opts->uid : current_fsuid();
 	inode->i_gid = opts->setgid ? opts->gid : current_fsgid();
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	init_special_inode(inode, S_IFCHR|opts->mode, device);
-	inode->i_private = tty;
-	tty->driver_data = inode;
+	inode->i_private = priv;
 
-	sprintf(s, "%d", number);
+	sprintf(s, "%d", index);
 
 	mutex_lock(&root->d_inode->i_mutex);
 
@@ -585,18 +586,24 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)
 		fsnotify_create(root->d_inode, dentry);
 	} else {
 		iput(inode);
-		ret = -ENOMEM;
+		inode = ERR_PTR(-ENOMEM);
 	}
 
 	mutex_unlock(&root->d_inode->i_mutex);
 
-	return ret;
+	return inode;
 }
 
-struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number)
+/**
+ * devpts_get_priv -- get private data for a slave
+ * @pts_inode: inode of the slave
+ *
+ * Returns whatever was passed as priv in devpts_pty_new for a given inode.
+ */
+void *devpts_get_priv(struct inode *pts_inode)
 {
 	struct dentry *dentry;
-	struct tty_struct *tty;
+	void *priv = NULL;
 
 	BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
 
@@ -605,18 +612,22 @@ struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number)
 	if (!dentry)
 		return NULL;
 
-	tty = NULL;
 	if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
-		tty = (struct tty_struct *)pts_inode->i_private;
+		priv = pts_inode->i_private;
 
 	dput(dentry);
 
-	return tty;
+	return priv;
 }
 
-void devpts_pty_kill(struct tty_struct *tty)
+/**
+ * devpts_pty_kill -- remove inode form /dev/pts/
+ * @inode: inode of the slave to be removed
+ *
+ * This is an inverse operation of devpts_pty_new.
+ */
+void devpts_pty_kill(struct inode *inode)
 {
-	struct inode *inode = tty->driver_data;
 	struct super_block *sb = pts_sb_from_inode(inode);
 	struct dentry *root = sb->s_root;
 	struct dentry *dentry;
diff --git a/fs/dlm/Kconfig b/fs/dlm/Kconfig
index 1897eb1..e4242c3 100644
--- a/fs/dlm/Kconfig
+++ b/fs/dlm/Kconfig
@@ -1,6 +1,6 @@
 menuconfig DLM
 	tristate "Distributed Lock Manager (DLM)"
-	depends on EXPERIMENTAL && INET
+	depends on INET
 	depends on SYSFS && CONFIGFS_FS && (IPV6 || IPV6=n)
 	select IP_SCTP
 	help
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
index a0387dd..7d58d5b 100644
--- a/fs/dlm/config.c
+++ b/fs/dlm/config.c
@@ -158,7 +158,7 @@ static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field,
 	unsigned int x;
 
 	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
+		return -EPERM;
 
 	x = simple_strtoul(buf, NULL, 0);
 
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 871c1ab..77c0f70 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -337,6 +337,7 @@ enum rsb_flags {
 	RSB_NEW_MASTER2,
 	RSB_RECOVER_CONVERT,
 	RSB_RECOVER_GRANT,
+	RSB_RECOVER_LVB_INVAL,
 };
 
 static inline void rsb_set_flag(struct dlm_rsb *r, enum rsb_flags flag)
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index b569507..a579f30 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -5393,6 +5393,13 @@ static void purge_dead_list(struct dlm_ls *ls, struct dlm_rsb *r,
 		if ((lkb->lkb_nodeid == nodeid_gone) ||
 		    dlm_is_removed(ls, lkb->lkb_nodeid)) {
 
+			/* tell recover_lvb to invalidate the lvb
+			   because a node holding EX/PW failed */
+			if ((lkb->lkb_exflags & DLM_LKF_VALBLK) &&
+			    (lkb->lkb_grmode >= DLM_LOCK_PW)) {
+				rsb_set_flag(r, RSB_RECOVER_LVB_INVAL);
+			}
+
 			del_lkb(r, lkb);
 
 			/* this put should free the lkb */
@@ -6025,15 +6032,18 @@ static int orphan_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb)
 	return error;
 }
 
-/* The force flag allows the unlock to go ahead even if the lkb isn't granted.
-   Regardless of what rsb queue the lock is on, it's removed and freed. */
+/* The FORCEUNLOCK flag allows the unlock to go ahead even if the lkb isn't
+   granted.  Regardless of what rsb queue the lock is on, it's removed and
+   freed.  The IVVALBLK flag causes the lvb on the resource to be invalidated
+   if our lock is PW/EX (it's ignored if our granted mode is smaller.) */
 
 static int unlock_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb)
 {
 	struct dlm_args args;
 	int error;
 
-	set_unlock_args(DLM_LKF_FORCEUNLOCK, lkb->lkb_ua, &args);
+	set_unlock_args(DLM_LKF_FORCEUNLOCK | DLM_LKF_IVVALBLK,
+			lkb->lkb_ua, &args);
 
 	error = unlock_lock(ls, lkb, &args);
 	if (error == -DLM_EUNLOCK)
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 331ea4f..dd87a31 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -1385,7 +1385,6 @@ void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc)
 	struct connection *con;
 	struct writequeue_entry *e;
 	int offset = 0;
-	int users = 0;
 
 	con = nodeid2con(nodeid, allocation);
 	if (!con)
@@ -1399,7 +1398,7 @@ void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc)
 	} else {
 		offset = e->end;
 		e->end += len;
-		users = e->users++;
+		e->users++;
 	}
 	spin_unlock(&con->writequeue_lock);
 
@@ -1414,7 +1413,7 @@ void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc)
 		spin_lock(&con->writequeue_lock);
 		offset = e->end;
 		e->end += len;
-		users = e->users++;
+		e->users++;
 		list_add_tail(&e->list, &con->writequeue);
 		spin_unlock(&con->writequeue_lock);
 		goto got_one;
diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c
index 4a7a76e..aedea28 100644
--- a/fs/dlm/recover.c
+++ b/fs/dlm/recover.c
@@ -717,8 +717,14 @@ void dlm_recovered_lock(struct dlm_rsb *r)
  * the VALNOTVALID flag if necessary, and determining the correct lvb contents
  * based on the lvb's of the locks held on the rsb.
  *
- * RSB_VALNOTVALID is set if there are only NL/CR locks on the rsb.  If it
- * was already set prior to recovery, it's not cleared, regardless of locks.
+ * RSB_VALNOTVALID is set in two cases:
+ *
+ * 1. we are master, but not new, and we purged an EX/PW lock held by a
+ * failed node (in dlm_recover_purge which set RSB_RECOVER_LVB_INVAL)
+ *
+ * 2. we are a new master, and there are only NL/CR locks left.
+ * (We could probably improve this by only invaliding in this way when
+ * the previous master left uncleanly.  VMS docs mention that.)
  *
  * The LVB contents are only considered for changing when this is a new master
  * of the rsb (NEW_MASTER2).  Then, the rsb's lvb is taken from any lkb with
@@ -734,6 +740,19 @@ static void recover_lvb(struct dlm_rsb *r)
 	int big_lock_exists = 0;
 	int lvblen = r->res_ls->ls_lvblen;
 
+	if (!rsb_flag(r, RSB_NEW_MASTER2) &&
+	    rsb_flag(r, RSB_RECOVER_LVB_INVAL)) {
+		/* case 1 above */
+		rsb_set_flag(r, RSB_VALNOTVALID);
+		return;
+	}
+
+	if (!rsb_flag(r, RSB_NEW_MASTER2))
+		return;
+
+	/* we are the new master, so figure out if VALNOTVALID should
+	   be set, and set the rsb lvb from the best lkb available. */
+
 	list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
 		if (!(lkb->lkb_exflags & DLM_LKF_VALBLK))
 			continue;
@@ -772,13 +791,10 @@ static void recover_lvb(struct dlm_rsb *r)
 	if (!lock_lvb_exists)
 		goto out;
 
+	/* lvb is invalidated if only NL/CR locks remain */
 	if (!big_lock_exists)
 		rsb_set_flag(r, RSB_VALNOTVALID);
 
-	/* don't mess with the lvb unless we're the new master */
-	if (!rsb_flag(r, RSB_NEW_MASTER2))
-		goto out;
-
 	if (!r->res_lvbptr) {
 		r->res_lvbptr = dlm_allocate_lvb(r->res_ls);
 		if (!r->res_lvbptr)
@@ -852,12 +868,19 @@ void dlm_recover_rsbs(struct dlm_ls *ls)
 		if (is_master(r)) {
 			if (rsb_flag(r, RSB_RECOVER_CONVERT))
 				recover_conversion(r);
+
+			/* recover lvb before granting locks so the updated
+			   lvb/VALNOTVALID is presented in the completion */
+			recover_lvb(r);
+
 			if (rsb_flag(r, RSB_NEW_MASTER2))
 				recover_grant(r);
-			recover_lvb(r);
 			count++;
+		} else {
+			rsb_clear_flag(r, RSB_VALNOTVALID);
 		}
 		rsb_clear_flag(r, RSB_RECOVER_CONVERT);
+		rsb_clear_flag(r, RSB_RECOVER_LVB_INVAL);
 		rsb_clear_flag(r, RSB_NEW_MASTER2);
 		unlock_rsb(r);
 	}
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
index c00e055..f23d2a7 100644
--- a/fs/drop_caches.c
+++ b/fs/drop_caches.c
@@ -58,6 +58,8 @@ int drop_caches_sysctl_handler(ctl_table *table, int write,
 	if (ret)
 		return ret;
 	if (write) {
+		printk(KERN_NOTICE "%s (%d): dropped kernel caches: %d\n",
+		       current->comm, task_pid_nr(current), sysctl_drop_caches);
 		if (sysctl_drop_caches & 1)
 			iterate_supers(drop_pagecache_sb, NULL);
 		if (sysctl_drop_caches & 2)
diff --git a/fs/ecryptfs/Kconfig b/fs/ecryptfs/Kconfig
index cc16562..e15ef38 100644
--- a/fs/ecryptfs/Kconfig
+++ b/fs/ecryptfs/Kconfig
@@ -1,6 +1,6 @@
 config ECRYPT_FS
-	tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && KEYS && CRYPTO && (ENCRYPTED_KEYS || ENCRYPTED_KEYS=n)
+	tristate "eCrypt filesystem layer support"
+	depends on KEYS && CRYPTO && (ENCRYPTED_KEYS || ENCRYPTED_KEYS=n)
 	select CRYPTO_ECB
 	select CRYPTO_CBC
 	select CRYPTO_MD5
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index bd1d57f..564a1fa 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -338,7 +338,8 @@ static int ecryptfs_write_begin(struct file *file,
 			if (prev_page_end_size
 			    >= i_size_read(page->mapping->host)) {
 				zero_user(page, 0, PAGE_CACHE_SIZE);
-			} else {
+				SetPageUptodate(page);
+			} else if (len < PAGE_CACHE_SIZE) {
 				rc = ecryptfs_decrypt_page(page);
 				if (rc) {
 					printk(KERN_ERR "%s: Error decrypting "
@@ -348,8 +349,8 @@ static int ecryptfs_write_begin(struct file *file,
 					ClearPageUptodate(page);
 					goto out;
 				}
+				SetPageUptodate(page);
 			}
-			SetPageUptodate(page);
 		}
 	}
 	/* If creating a page or more of holes, zero them out via truncate.
@@ -499,6 +500,13 @@ static int ecryptfs_write_end(struct file *file,
 		}
 		goto out;
 	}
+	if (!PageUptodate(page)) {
+		if (copied < PAGE_CACHE_SIZE) {
+			rc = 0;
+			goto out;
+		}
+		SetPageUptodate(page);
+	}
 	/* Fills in zeros if 'to' goes beyond inode size */
 	rc = fill_zeros_to_end_of_page(page, to);
 	if (rc) {
diff --git a/fs/eventfd.c b/fs/eventfd.c
index d81b9f6..35470d9 100644
--- a/fs/eventfd.c
+++ b/fs/eventfd.c
@@ -19,6 +19,8 @@
 #include <linux/export.h>
 #include <linux/kref.h>
 #include <linux/eventfd.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 struct eventfd_ctx {
 	struct kref kref;
@@ -284,7 +286,25 @@ static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t c
 	return res;
 }
 
+#ifdef CONFIG_PROC_FS
+static int eventfd_show_fdinfo(struct seq_file *m, struct file *f)
+{
+	struct eventfd_ctx *ctx = f->private_data;
+	int ret;
+
+	spin_lock_irq(&ctx->wqh.lock);
+	ret = seq_printf(m, "eventfd-count: %16llx\n",
+			 (unsigned long long)ctx->count);
+	spin_unlock_irq(&ctx->wqh.lock);
+
+	return ret;
+}
+#endif
+
 static const struct file_operations eventfd_fops = {
+#ifdef CONFIG_PROC_FS
+	.show_fdinfo	= eventfd_show_fdinfo,
+#endif
 	.release	= eventfd_release,
 	.poll		= eventfd_poll,
 	.read		= eventfd_read,
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index cd96649..573179d 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -38,6 +38,8 @@
 #include <asm/io.h>
 #include <asm/mman.h>
 #include <linux/atomic.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 /*
  * LOCKING:
@@ -346,7 +348,7 @@ static inline struct epitem *ep_item_from_epqueue(poll_table *p)
 /* Tells if the epoll_ctl(2) operation needs an event copy from userspace */
 static inline int ep_op_has_event(int op)
 {
-	return op != EPOLL_CTL_DEL;
+	return op == EPOLL_CTL_ADD || op == EPOLL_CTL_MOD;
 }
 
 /* Initialize the poll safe wake up structure */
@@ -676,6 +678,36 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
 	return 0;
 }
 
+/*
+ * Disables a "struct epitem" in the eventpoll set. Returns -EBUSY if the item
+ * had no event flags set, indicating that another thread may be currently
+ * handling that item's events (in the case that EPOLLONESHOT was being
+ * used). Otherwise a zero result indicates that the item has been disabled
+ * from receiving events. A disabled item may be re-enabled via
+ * EPOLL_CTL_MOD. Must be called with "mtx" held.
+ */
+static int ep_disable(struct eventpoll *ep, struct epitem *epi)
+{
+	int result = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ep->lock, flags);
+	if (epi->event.events & EPOLLONESHOT) {
+		if (epi->event.events & ~EP_PRIVATE_BITS) {
+			if (ep_is_linked(&epi->rdllink))
+				list_del_init(&epi->rdllink);
+			/* Ensure ep_poll_callback will not add epi back onto
+			   ready list: */
+			epi->event.events &= EP_PRIVATE_BITS;
+		} else
+			result = -EBUSY;
+	} else
+		result = -EINVAL;
+	spin_unlock_irqrestore(&ep->lock, flags);
+
+	return result;
+}
+
 static void ep_free(struct eventpoll *ep)
 {
 	struct rb_node *rbp;
@@ -783,8 +815,34 @@ static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait)
 	return pollflags != -1 ? pollflags : 0;
 }
 
+#ifdef CONFIG_PROC_FS
+static int ep_show_fdinfo(struct seq_file *m, struct file *f)
+{
+	struct eventpoll *ep = f->private_data;
+	struct rb_node *rbp;
+	int ret = 0;
+
+	mutex_lock(&ep->mtx);
+	for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) {
+		struct epitem *epi = rb_entry(rbp, struct epitem, rbn);
+
+		ret = seq_printf(m, "tfd: %8d events: %8x data: %16llx\n",
+				 epi->ffd.fd, epi->event.events,
+				 (long long)epi->event.data);
+		if (ret)
+			break;
+	}
+	mutex_unlock(&ep->mtx);
+
+	return ret;
+}
+#endif
+
 /* File callbacks that implement the eventpoll file behaviour */
 static const struct file_operations eventpoll_fops = {
+#ifdef CONFIG_PROC_FS
+	.show_fdinfo	= ep_show_fdinfo,
+#endif
 	.release	= ep_eventpoll_release,
 	.poll		= ep_eventpoll_poll,
 	.llseek		= noop_llseek,
@@ -1020,8 +1078,6 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
 	rb_insert_color(&epi->rbn, &ep->rbr);
 }
 
-
-
 #define PATH_ARR_SIZE 5
 /*
  * These are the number paths of length 1 to 5, that we are allowing to emanate
@@ -1787,6 +1843,12 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
 		} else
 			error = -ENOENT;
 		break;
+	case EPOLL_CTL_DISABLE:
+		if (epi)
+			error = ep_disable(ep, epi);
+		else
+			error = -ENOENT;
+		break;
 	}
 	mutex_unlock(&ep->mtx);
 
diff --git a/fs/exec.c b/fs/exec.c
index 0039055..237d534 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1175,9 +1175,24 @@ void free_bprm(struct linux_binprm *bprm)
 		mutex_unlock(&current->signal->cred_guard_mutex);
 		abort_creds(bprm->cred);
 	}
+	/* If a binfmt changed the interp, free it. */
+	if (bprm->interp != bprm->filename)
+		kfree(bprm->interp);
 	kfree(bprm);
 }
 
+int bprm_change_interp(char *interp, struct linux_binprm *bprm)
+{
+	/* If a binfmt changed the interp, free it first. */
+	if (bprm->interp != bprm->filename)
+		kfree(bprm->interp);
+	bprm->interp = kstrdup(interp, GFP_KERNEL);
+	if (!bprm->interp)
+		return -ENOMEM;
+	return 0;
+}
+EXPORT_SYMBOL(bprm_change_interp);
+
 /*
  * install the new credentials for this executable
  */
@@ -1266,14 +1281,13 @@ int prepare_binprm(struct linux_binprm *bprm)
 	bprm->cred->egid = current_egid();
 
 	if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) &&
-	    !current->no_new_privs) {
+	    !current->no_new_privs &&
+	    kuid_has_mapping(bprm->cred->user_ns, inode->i_uid) &&
+	    kgid_has_mapping(bprm->cred->user_ns, inode->i_gid)) {
 		/* Set-uid? */
 		if (mode & S_ISUID) {
-			if (!kuid_has_mapping(bprm->cred->user_ns, inode->i_uid))
-				return -EPERM;
 			bprm->per_clear |= PER_CLEAR_ON_SETID;
 			bprm->cred->euid = inode->i_uid;
-
 		}
 
 		/* Set-gid? */
@@ -1283,8 +1297,6 @@ int prepare_binprm(struct linux_binprm *bprm)
 		 * executable.
 		 */
 		if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
-			if (!kgid_has_mapping(bprm->cred->user_ns, inode->i_gid))
-				return -EPERM;
 			bprm->per_clear |= PER_CLEAR_ON_SETID;
 			bprm->cred->egid = inode->i_gid;
 		}
@@ -1349,13 +1361,17 @@ EXPORT_SYMBOL(remove_arg_zero);
 /*
  * cycle the list of binary formats handler, until one recognizes the image
  */
-int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
+int search_binary_handler(struct linux_binprm *bprm)
 {
 	unsigned int depth = bprm->recursion_depth;
 	int try,retval;
 	struct linux_binfmt *fmt;
 	pid_t old_pid, old_vpid;
 
+	/* This allows 4 levels of binfmt rewrites before failing hard. */
+	if (depth > 5)
+		return -ELOOP;
+
 	retval = security_bprm_check(bprm);
 	if (retval)
 		return retval;
@@ -1374,18 +1390,14 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
 	for (try=0; try<2; try++) {
 		read_lock(&binfmt_lock);
 		list_for_each_entry(fmt, &formats, lh) {
-			int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
+			int (*fn)(struct linux_binprm *) = fmt->load_binary;
 			if (!fn)
 				continue;
 			if (!try_module_get(fmt->module))
 				continue;
 			read_unlock(&binfmt_lock);
-			retval = fn(bprm, regs);
-			/*
-			 * Restore the depth counter to its starting value
-			 * in this call, so we don't have to rely on every
-			 * load_binary function to restore it on return.
-			 */
+			bprm->recursion_depth = depth + 1;
+			retval = fn(bprm);
 			bprm->recursion_depth = depth;
 			if (retval >= 0) {
 				if (depth == 0) {
@@ -1439,8 +1451,7 @@ EXPORT_SYMBOL(search_binary_handler);
  */
 static int do_execve_common(const char *filename,
 				struct user_arg_ptr argv,
-				struct user_arg_ptr envp,
-				struct pt_regs *regs)
+				struct user_arg_ptr envp)
 {
 	struct linux_binprm *bprm;
 	struct file *file;
@@ -1524,7 +1535,7 @@ static int do_execve_common(const char *filename,
 	if (retval < 0)
 		goto out;
 
-	retval = search_binary_handler(bprm,regs);
+	retval = search_binary_handler(bprm);
 	if (retval < 0)
 		goto out;
 
@@ -1566,19 +1577,17 @@ out_ret:
 
 int do_execve(const char *filename,
 	const char __user *const __user *__argv,
-	const char __user *const __user *__envp,
-	struct pt_regs *regs)
+	const char __user *const __user *__envp)
 {
 	struct user_arg_ptr argv = { .ptr.native = __argv };
 	struct user_arg_ptr envp = { .ptr.native = __envp };
-	return do_execve_common(filename, argv, envp, regs);
+	return do_execve_common(filename, argv, envp);
 }
 
 #ifdef CONFIG_COMPAT
-int compat_do_execve(const char *filename,
+static int compat_do_execve(const char *filename,
 	const compat_uptr_t __user *__argv,
-	const compat_uptr_t __user *__envp,
-	struct pt_regs *regs)
+	const compat_uptr_t __user *__envp)
 {
 	struct user_arg_ptr argv = {
 		.is_compat = true,
@@ -1588,7 +1597,7 @@ int compat_do_execve(const char *filename,
 		.is_compat = true,
 		.ptr.compat = __envp,
 	};
-	return do_execve_common(filename, argv, envp, regs);
+	return do_execve_common(filename, argv, envp);
 }
 #endif
 
@@ -1669,7 +1678,7 @@ SYSCALL_DEFINE3(execve,
 	struct filename *path = getname(filename);
 	int error = PTR_ERR(path);
 	if (!IS_ERR(path)) {
-		error = do_execve(path->name, argv, envp, current_pt_regs());
+		error = do_execve(path->name, argv, envp);
 		putname(path);
 	}
 	return error;
@@ -1682,8 +1691,7 @@ asmlinkage long compat_sys_execve(const char __user * filename,
 	struct filename *path = getname(filename);
 	int error = PTR_ERR(path);
 	if (!IS_ERR(path)) {
-		error = compat_do_execve(path->name, argv, envp,
-							current_pt_regs());
+		error = compat_do_execve(path->name, argv, envp);
 		putname(path);
 	}
 	return error;
@@ -1696,12 +1704,9 @@ int kernel_execve(const char *filename,
 		  const char *const argv[],
 		  const char *const envp[])
 {
-	struct pt_regs *p = current_pt_regs();
-	int ret;
-
-	ret = do_execve(filename,
+	int ret = do_execve(filename,
 			(const char __user *const __user *)argv,
-			(const char __user *const __user *)envp, p);
+			(const char __user *const __user *)envp);
 	if (ret < 0)
 		return ret;
 
@@ -1709,6 +1714,6 @@ int kernel_execve(const char *filename,
 	 * We were successful.  We won't be returning to our caller, but
 	 * instead to user space by manipulating the kernel stack.
 	 */
-	ret_from_kernel_execve(p);
+	ret_from_kernel_execve(current_pt_regs());
 }
 #endif
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 29ab099..5df4bb4 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -322,10 +322,10 @@ static int export_encode_fh(struct inode *inode, struct fid *fid,
 
 	if (parent && (len < 4)) {
 		*max_len = 4;
-		return 255;
+		return FILEID_INVALID;
 	} else if (len < 2) {
 		*max_len = 2;
-		return 255;
+		return FILEID_INVALID;
 	}
 
 	len = 2;
@@ -341,10 +341,21 @@ static int export_encode_fh(struct inode *inode, struct fid *fid,
 	return type;
 }
 
+int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid,
+			     int *max_len, struct inode *parent)
+{
+	const struct export_operations *nop = inode->i_sb->s_export_op;
+
+	if (nop && nop->encode_fh)
+		return nop->encode_fh(inode, fid->raw, max_len, parent);
+
+	return export_encode_fh(inode, fid, max_len, parent);
+}
+EXPORT_SYMBOL_GPL(exportfs_encode_inode_fh);
+
 int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len,
 		int connectable)
 {
-	const struct export_operations *nop = dentry->d_sb->s_export_op;
 	int error;
 	struct dentry *p = NULL;
 	struct inode *inode = dentry->d_inode, *parent = NULL;
@@ -357,10 +368,8 @@ int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len,
 		 */
 		parent = p->d_inode;
 	}
-	if (nop->encode_fh)
-		error = nop->encode_fh(inode, fid->raw, max_len, parent);
-	else
-		error = export_encode_fh(inode, fid, max_len, parent);
+
+	error = exportfs_encode_inode_fh(inode, fid, max_len, parent);
 	dput(p);
 
 	return error;
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 7e87e37..b176d42 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1071,8 +1071,7 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode *inode,
 	 * mapped. 0 in case of a HOLE.
 	 */
 	if (err > 0) {
-		if (err > 1)
-			WARN_ON(1);
+		WARN_ON(err > 1);
 		err = 0;
 	}
 	*errp = err;
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 5366393..6e50223 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -1661,9 +1661,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 		return -ENOMEM;
 	}
 	sb->s_fs_info = sbi;
-	sbi->s_mount_opt = 0;
-	sbi->s_resuid = make_kuid(&init_user_ns, EXT3_DEF_RESUID);
-	sbi->s_resgid = make_kgid(&init_user_ns, EXT3_DEF_RESGID);
 	sbi->s_sb_block = sb_block;
 
 	blocksize = sb_min_blocksize(sb, EXT3_MIN_BLOCK_SIZE);
diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
index 56fd8f86..41f22be 100644
--- a/fs/ext4/Makefile
+++ b/fs/ext4/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_EXT4_FS) += ext4.o
 ext4-y	:= balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \
 		ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
 		ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \
-		mmp.o indirect.o
+		mmp.o indirect.o extents_status.o
 
 ext4-$(CONFIG_EXT4_FS_XATTR)		+= xattr.o xattr_user.o xattr_trusted.o
 ext4-$(CONFIG_EXT4_FS_POSIX_ACL)	+= acl.o
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index d3c5b88..e6e0d98 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -423,8 +423,10 @@ ext4_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
 
 retry:
 	handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
-	if (IS_ERR(handle))
-		return PTR_ERR(handle);
+	if (IS_ERR(handle)) {
+		error = PTR_ERR(handle);
+		goto release_and_out;
+	}
 	error = ext4_set_acl(handle, inode, type, acl);
 	ext4_journal_stop(handle);
 	if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 3c20de1..23007b5 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -811,6 +811,8 @@ struct ext4_ext_cache {
 	__u32		ec_len; /* must be 32bit to return holes */
 };
 
+#include "extents_status.h"
+
 /*
  * fourth extended file system inode data in memory
  */
@@ -888,6 +890,10 @@ struct ext4_inode_info {
 	struct list_head i_prealloc_list;
 	spinlock_t i_prealloc_lock;
 
+	/* extents status tree */
+	struct ext4_es_tree i_es_tree;
+	rwlock_t i_es_lock;
+
 	/* ialloc */
 	ext4_group_t	i_last_alloc_group;
 
@@ -2445,17 +2451,13 @@ enum ext4_state_bits {
 				 * never, ever appear in a buffer_head's state
 				 * flag. See EXT4_MAP_FROM_CLUSTER to see where
 				 * this is used. */
-	BH_Da_Mapped,	/* Delayed allocated block that now has a mapping. This
-			 * flag is set when ext4_map_blocks is called on a
-			 * delayed allocated block to get its real mapping. */
 };
 
 BUFFER_FNS(Uninit, uninit)
 TAS_BUFFER_FNS(Uninit, uninit)
-BUFFER_FNS(Da_Mapped, da_mapped)
 
 /*
- * Add new method to test wether block and inode bitmaps are properly
+ * Add new method to test whether block and inode bitmaps are properly
  * initialized. With uninit_bg reading the block from disk is not enough
  * to mark the bitmap uptodate. We need to also zero-out the bitmap
  */
diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
index cb1b2c9..603bb11 100644
--- a/fs/ext4/ext4_extents.h
+++ b/fs/ext4/ext4_extents.h
@@ -314,7 +314,6 @@ extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
 							struct ext4_ext_path *);
 extern void ext4_ext_drop_refs(struct ext4_ext_path *);
 extern int ext4_ext_check_inode(struct inode *inode);
-extern int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk,
-				      int search_hint_reverse);
+extern int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk);
 #endif /* _EXT4_EXTENTS */
 
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index 56d258c..7177f9b 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -254,13 +254,6 @@ static inline void ext4_handle_sync(handle_t *handle)
 		handle->h_sync = 1;
 }
 
-static inline void ext4_handle_release_buffer(handle_t *handle,
-						struct buffer_head *bh)
-{
-	if (ext4_handle_valid(handle))
-		jbd2_journal_release_buffer(handle, bh);
-}
-
 static inline int ext4_handle_is_aborted(handle_t *handle)
 {
 	if (ext4_handle_valid(handle))
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 7011ac9..d3dd618 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3461,115 +3461,34 @@ out:
 /**
  * ext4_find_delalloc_range: find delayed allocated block in the given range.
  *
- * Goes through the buffer heads in the range [lblk_start, lblk_end] and returns
- * whether there are any buffers marked for delayed allocation. It returns '1'
- * on the first delalloc'ed buffer head found. If no buffer head in the given
- * range is marked for delalloc, it returns 0.
- * lblk_start should always be <= lblk_end.
- * search_hint_reverse is to indicate that searching in reverse from lblk_end to
- * lblk_start might be more efficient (i.e., we will likely hit the delalloc'ed
- * block sooner). This is useful when blocks are truncated sequentially from
- * lblk_start towards lblk_end.
+ * Return 1 if there is a delalloc block in the range, otherwise 0.
  */
 static int ext4_find_delalloc_range(struct inode *inode,
 				    ext4_lblk_t lblk_start,
-				    ext4_lblk_t lblk_end,
-				    int search_hint_reverse)
+				    ext4_lblk_t lblk_end)
 {
-	struct address_space *mapping = inode->i_mapping;
-	struct buffer_head *head, *bh = NULL;
-	struct page *page;
-	ext4_lblk_t i, pg_lblk;
-	pgoff_t index;
-
-	if (!test_opt(inode->i_sb, DELALLOC))
-		return 0;
+	struct extent_status es;
 
-	/* reverse search wont work if fs block size is less than page size */
-	if (inode->i_blkbits < PAGE_CACHE_SHIFT)
-		search_hint_reverse = 0;
-
-	if (search_hint_reverse)
-		i = lblk_end;
+	es.start = lblk_start;
+	ext4_es_find_extent(inode, &es);
+	if (es.len == 0)
+		return 0; /* there is no delay extent in this tree */
+	else if (es.start <= lblk_start && lblk_start < es.start + es.len)
+		return 1;
+	else if (lblk_start <= es.start && es.start <= lblk_end)
+		return 1;
 	else
-		i = lblk_start;
-
-	index = i >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
-
-	while ((i >= lblk_start) && (i <= lblk_end)) {
-		page = find_get_page(mapping, index);
-		if (!page)
-			goto nextpage;
-
-		if (!page_has_buffers(page))
-			goto nextpage;
-
-		head = page_buffers(page);
-		if (!head)
-			goto nextpage;
-
-		bh = head;
-		pg_lblk = index << (PAGE_CACHE_SHIFT -
-						inode->i_blkbits);
-		do {
-			if (unlikely(pg_lblk < lblk_start)) {
-				/*
-				 * This is possible when fs block size is less
-				 * than page size and our cluster starts/ends in
-				 * middle of the page. So we need to skip the
-				 * initial few blocks till we reach the 'lblk'
-				 */
-				pg_lblk++;
-				continue;
-			}
-
-			/* Check if the buffer is delayed allocated and that it
-			 * is not yet mapped. (when da-buffers are mapped during
-			 * their writeout, their da_mapped bit is set.)
-			 */
-			if (buffer_delay(bh) && !buffer_da_mapped(bh)) {
-				page_cache_release(page);
-				trace_ext4_find_delalloc_range(inode,
-						lblk_start, lblk_end,
-						search_hint_reverse,
-						1, i);
-				return 1;
-			}
-			if (search_hint_reverse)
-				i--;
-			else
-				i++;
-		} while ((i >= lblk_start) && (i <= lblk_end) &&
-				((bh = bh->b_this_page) != head));
-nextpage:
-		if (page)
-			page_cache_release(page);
-		/*
-		 * Move to next page. 'i' will be the first lblk in the next
-		 * page.
-		 */
-		if (search_hint_reverse)
-			index--;
-		else
-			index++;
-		i = index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
-	}
-
-	trace_ext4_find_delalloc_range(inode, lblk_start, lblk_end,
-					search_hint_reverse, 0, 0);
-	return 0;
+		return 0;
 }
 
-int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk,
-			       int search_hint_reverse)
+int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk)
 {
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 	ext4_lblk_t lblk_start, lblk_end;
 	lblk_start = lblk & (~(sbi->s_cluster_ratio - 1));
 	lblk_end = lblk_start + sbi->s_cluster_ratio - 1;
 
-	return ext4_find_delalloc_range(inode, lblk_start, lblk_end,
-					search_hint_reverse);
+	return ext4_find_delalloc_range(inode, lblk_start, lblk_end);
 }
 
 /**
@@ -3630,7 +3549,7 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
 		lblk_from = lblk_start & (~(sbi->s_cluster_ratio - 1));
 		lblk_to = lblk_from + c_offset - 1;
 
-		if (ext4_find_delalloc_range(inode, lblk_from, lblk_to, 0))
+		if (ext4_find_delalloc_range(inode, lblk_from, lblk_to))
 			allocated_clusters--;
 	}
 
@@ -3640,7 +3559,7 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
 		lblk_from = lblk_start + num_blks;
 		lblk_to = lblk_from + (sbi->s_cluster_ratio - c_offset) - 1;
 
-		if (ext4_find_delalloc_range(inode, lblk_from, lblk_to, 0))
+		if (ext4_find_delalloc_range(inode, lblk_from, lblk_to))
 			allocated_clusters--;
 	}
 
@@ -3663,8 +3582,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
 		  flags, allocated);
 	ext4_ext_show_leaf(inode, path);
 
-	trace_ext4_ext_handle_uninitialized_extents(inode, map, allocated,
-						    newblock);
+	trace_ext4_ext_handle_uninitialized_extents(inode, map, flags,
+						    allocated, newblock);
 
 	/* get_block() before submit the IO, split the extent */
 	if ((flags & EXT4_GET_BLOCKS_PRE_IO)) {
@@ -3911,7 +3830,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 	struct ext4_extent newex, *ex, *ex2;
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 	ext4_fsblk_t newblock = 0;
-	int free_on_err = 0, err = 0, depth, ret;
+	int free_on_err = 0, err = 0, depth;
 	unsigned int allocated = 0, offset = 0;
 	unsigned int allocated_clusters = 0;
 	struct ext4_allocation_request ar;
@@ -3927,7 +3846,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 	if (ext4_ext_in_cache(inode, map->m_lblk, &newex)) {
 		if (!newex.ee_start_lo && !newex.ee_start_hi) {
 			if ((sbi->s_cluster_ratio > 1) &&
-			    ext4_find_delalloc_cluster(inode, map->m_lblk, 0))
+			    ext4_find_delalloc_cluster(inode, map->m_lblk))
 				map->m_flags |= EXT4_MAP_FROM_CLUSTER;
 
 			if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
@@ -4007,15 +3926,15 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 					ee_len, ee_start);
 				goto out;
 			}
-			ret = ext4_ext_handle_uninitialized_extents(
+			allocated = ext4_ext_handle_uninitialized_extents(
 				handle, inode, map, path, flags,
 				allocated, newblock);
-			return ret;
+			goto out3;
 		}
 	}
 
 	if ((sbi->s_cluster_ratio > 1) &&
-	    ext4_find_delalloc_cluster(inode, map->m_lblk, 0))
+	    ext4_find_delalloc_cluster(inode, map->m_lblk))
 		map->m_flags |= EXT4_MAP_FROM_CLUSTER;
 
 	/*
@@ -4284,8 +4203,8 @@ out2:
 		kfree(path);
 	}
 
-	trace_ext4_ext_map_blocks_exit(inode, map->m_lblk,
-		newblock, map->m_len, err ? err : allocated);
+out3:
+	trace_ext4_ext_map_blocks_exit(inode, map, err ? err : allocated);
 
 	return err ? err : allocated;
 }
@@ -4344,6 +4263,8 @@ void ext4_ext_truncate(struct inode *inode)
 
 	last_block = (inode->i_size + sb->s_blocksize - 1)
 			>> EXT4_BLOCK_SIZE_BITS(sb);
+	err = ext4_es_remove_extent(inode, last_block,
+				    EXT_MAX_BLOCKS - last_block);
 	err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1);
 
 	/* In a multi-transaction truncate, we only make the final
@@ -4578,193 +4499,51 @@ static int ext4_ext_fiemap_cb(struct inode *inode, ext4_lblk_t next,
 		       struct ext4_ext_cache *newex, struct ext4_extent *ex,
 		       void *data)
 {
+	struct extent_status es;
 	__u64	logical;
 	__u64	physical;
 	__u64	length;
 	__u32	flags = 0;
+	ext4_lblk_t next_del;
 	int		ret = 0;
 	struct fiemap_extent_info *fieinfo = data;
 	unsigned char blksize_bits;
 
-	blksize_bits = inode->i_sb->s_blocksize_bits;
-	logical = (__u64)newex->ec_block << blksize_bits;
+	es.start = newex->ec_block;
+	next_del = ext4_es_find_extent(inode, &es);
 
+	next = min(next_del, next);
 	if (newex->ec_start == 0) {
 		/*
 		 * No extent in extent-tree contains block @newex->ec_start,
 		 * then the block may stay in 1)a hole or 2)delayed-extent.
-		 *
-		 * Holes or delayed-extents are processed as follows.
-		 * 1. lookup dirty pages with specified range in pagecache.
-		 *    If no page is got, then there is no delayed-extent and
-		 *    return with EXT_CONTINUE.
-		 * 2. find the 1st mapped buffer,
-		 * 3. check if the mapped buffer is both in the request range
-		 *    and a delayed buffer. If not, there is no delayed-extent,
-		 *    then return.
-		 * 4. a delayed-extent is found, the extent will be collected.
 		 */
-		ext4_lblk_t	end = 0;
-		pgoff_t		last_offset;
-		pgoff_t		offset;
-		pgoff_t		index;
-		pgoff_t		start_index = 0;
-		struct page	**pages = NULL;
-		struct buffer_head *bh = NULL;
-		struct buffer_head *head = NULL;
-		unsigned int nr_pages = PAGE_SIZE / sizeof(struct page *);
-
-		pages = kmalloc(PAGE_SIZE, GFP_KERNEL);
-		if (pages == NULL)
-			return -ENOMEM;
-
-		offset = logical >> PAGE_SHIFT;
-repeat:
-		last_offset = offset;
-		head = NULL;
-		ret = find_get_pages_tag(inode->i_mapping, &offset,
-					PAGECACHE_TAG_DIRTY, nr_pages, pages);
-
-		if (!(flags & FIEMAP_EXTENT_DELALLOC)) {
-			/* First time, try to find a mapped buffer. */
-			if (ret == 0) {
-out:
-				for (index = 0; index < ret; index++)
-					page_cache_release(pages[index]);
-				/* just a hole. */
-				kfree(pages);
-				return EXT_CONTINUE;
-			}
-			index = 0;
-
-next_page:
-			/* Try to find the 1st mapped buffer. */
-			end = ((__u64)pages[index]->index << PAGE_SHIFT) >>
-				  blksize_bits;
-			if (!page_has_buffers(pages[index]))
-				goto out;
-			head = page_buffers(pages[index]);
-			if (!head)
-				goto out;
-
-			index++;
-			bh = head;
-			do {
-				if (end >= newex->ec_block +
-					newex->ec_len)
-					/* The buffer is out of
-					 * the request range.
-					 */
-					goto out;
-
-				if (buffer_mapped(bh) &&
-				    end >= newex->ec_block) {
-					start_index = index - 1;
-					/* get the 1st mapped buffer. */
-					goto found_mapped_buffer;
-				}
-
-				bh = bh->b_this_page;
-				end++;
-			} while (bh != head);
-
-			/* No mapped buffer in the range found in this page,
-			 * We need to look up next page.
-			 */
-			if (index >= ret) {
-				/* There is no page left, but we need to limit
-				 * newex->ec_len.
-				 */
-				newex->ec_len = end - newex->ec_block;
-				goto out;
-			}
-			goto next_page;
-		} else {
-			/*Find contiguous delayed buffers. */
-			if (ret > 0 && pages[0]->index == last_offset)
-				head = page_buffers(pages[0]);
-			bh = head;
-			index = 1;
-			start_index = 0;
-		}
-
-found_mapped_buffer:
-		if (bh != NULL && buffer_delay(bh)) {
-			/* 1st or contiguous delayed buffer found. */
-			if (!(flags & FIEMAP_EXTENT_DELALLOC)) {
-				/*
-				 * 1st delayed buffer found, record
-				 * the start of extent.
-				 */
-				flags |= FIEMAP_EXTENT_DELALLOC;
-				newex->ec_block = end;
-				logical = (__u64)end << blksize_bits;
-			}
-			/* Find contiguous delayed buffers. */
-			do {
-				if (!buffer_delay(bh))
-					goto found_delayed_extent;
-				bh = bh->b_this_page;
-				end++;
-			} while (bh != head);
-
-			for (; index < ret; index++) {
-				if (!page_has_buffers(pages[index])) {
-					bh = NULL;
-					break;
-				}
-				head = page_buffers(pages[index]);
-				if (!head) {
-					bh = NULL;
-					break;
-				}
-
-				if (pages[index]->index !=
-				    pages[start_index]->index + index
-				    - start_index) {
-					/* Blocks are not contiguous. */
-					bh = NULL;
-					break;
-				}
-				bh = head;
-				do {
-					if (!buffer_delay(bh))
-						/* Delayed-extent ends. */
-						goto found_delayed_extent;
-					bh = bh->b_this_page;
-					end++;
-				} while (bh != head);
-			}
-		} else if (!(flags & FIEMAP_EXTENT_DELALLOC))
-			/* a hole found. */
-			goto out;
-
-found_delayed_extent:
-		newex->ec_len = min(end - newex->ec_block,
-						(ext4_lblk_t)EXT_INIT_MAX_LEN);
-		if (ret == nr_pages && bh != NULL &&
-			newex->ec_len < EXT_INIT_MAX_LEN &&
-			buffer_delay(bh)) {
-			/* Have not collected an extent and continue. */
-			for (index = 0; index < ret; index++)
-				page_cache_release(pages[index]);
-			goto repeat;
+		if (es.len == 0)
+			/* A hole found. */
+			return EXT_CONTINUE;
+
+		if (es.start > newex->ec_block) {
+			/* A hole found. */
+			newex->ec_len = min(es.start - newex->ec_block,
+					    newex->ec_len);
+			return EXT_CONTINUE;
 		}
 
-		for (index = 0; index < ret; index++)
-			page_cache_release(pages[index]);
-		kfree(pages);
+		flags |= FIEMAP_EXTENT_DELALLOC;
+		newex->ec_len = es.start + es.len - newex->ec_block;
 	}
 
-	physical = (__u64)newex->ec_start << blksize_bits;
-	length =   (__u64)newex->ec_len << blksize_bits;
-
 	if (ex && ext4_ext_is_uninitialized(ex))
 		flags |= FIEMAP_EXTENT_UNWRITTEN;
 
 	if (next == EXT_MAX_BLOCKS)
 		flags |= FIEMAP_EXTENT_LAST;
 
+	blksize_bits = inode->i_sb->s_blocksize_bits;
+	logical = (__u64)newex->ec_block << blksize_bits;
+	physical = (__u64)newex->ec_start << blksize_bits;
+	length =   (__u64)newex->ec_len << blksize_bits;
+
 	ret = fiemap_fill_next_extent(fieinfo, logical, physical,
 					length, flags);
 	if (ret < 0)
@@ -4971,6 +4750,8 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length)
 	ext4_ext_invalidate_cache(inode);
 	ext4_discard_preallocations(inode);
 
+	err = ext4_es_remove_extent(inode, first_block,
+				    stop_block - first_block);
 	err = ext4_ext_remove_space(inode, first_block, stop_block - 1);
 
 	ext4_ext_invalidate_cache(inode);
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
new file mode 100644
index 0000000..564d981
--- /dev/null
+++ b/fs/ext4/extents_status.c
@@ -0,0 +1,500 @@
+/*
+ *  fs/ext4/extents_status.c
+ *
+ * Written by Yongqiang Yang <xiaoqiangnk@gmail.com>
+ * Modified by
+ *	Allison Henderson <achender@linux.vnet.ibm.com>
+ *	Hugh Dickins <hughd@google.com>
+ *	Zheng Liu <wenqing.lz@taobao.com>
+ *
+ * Ext4 extents status tree core functions.
+ */
+#include <linux/rbtree.h>
+#include "ext4.h"
+#include "extents_status.h"
+#include "ext4_extents.h"
+
+#include <trace/events/ext4.h>
+
+/*
+ * According to previous discussion in Ext4 Developer Workshop, we
+ * will introduce a new structure called io tree to track all extent
+ * status in order to solve some problems that we have met
+ * (e.g. Reservation space warning), and provide extent-level locking.
+ * Delay extent tree is the first step to achieve this goal.  It is
+ * original built by Yongqiang Yang.  At that time it is called delay
+ * extent tree, whose goal is only track delay extent in memory to
+ * simplify the implementation of fiemap and bigalloc, and introduce
+ * lseek SEEK_DATA/SEEK_HOLE support.  That is why it is still called
+ * delay extent tree at the following comment.  But for better
+ * understand what it does, it has been rename to extent status tree.
+ *
+ * Currently the first step has been done.  All delay extents are
+ * tracked in the tree.  It maintains the delay extent when a delay
+ * allocation is issued, and the delay extent is written out or
+ * invalidated.  Therefore the implementation of fiemap and bigalloc
+ * are simplified, and SEEK_DATA/SEEK_HOLE are introduced.
+ *
+ * The following comment describes the implemenmtation of extent
+ * status tree and future works.
+ */
+
+/*
+ * extents status tree implementation for ext4.
+ *
+ *
+ * ==========================================================================
+ * Extents status encompass delayed extents and extent locks
+ *
+ * 1. Why delayed extent implementation ?
+ *
+ * Without delayed extent, ext4 identifies a delayed extent by looking
+ * up page cache, this has several deficiencies - complicated, buggy,
+ * and inefficient code.
+ *
+ * FIEMAP, SEEK_HOLE/DATA, bigalloc, punch hole and writeout all need
+ * to know if a block or a range of blocks are belonged to a delayed
+ * extent.
+ *
+ * Let us have a look at how they do without delayed extents implementation.
+ *   --	FIEMAP
+ *	FIEMAP looks up page cache to identify delayed allocations from holes.
+ *
+ *   --	SEEK_HOLE/DATA
+ *	SEEK_HOLE/DATA has the same problem as FIEMAP.
+ *
+ *   --	bigalloc
+ *	bigalloc looks up page cache to figure out if a block is
+ *	already under delayed allocation or not to determine whether
+ *	quota reserving is needed for the cluster.
+ *
+ *   -- punch hole
+ *	punch hole looks up page cache to identify a delayed extent.
+ *
+ *   --	writeout
+ *	Writeout looks up whole page cache to see if a buffer is
+ *	mapped, If there are not very many delayed buffers, then it is
+ *	time comsuming.
+ *
+ * With delayed extents implementation, FIEMAP, SEEK_HOLE/DATA,
+ * bigalloc and writeout can figure out if a block or a range of
+ * blocks is under delayed allocation(belonged to a delayed extent) or
+ * not by searching the delayed extent tree.
+ *
+ *
+ * ==========================================================================
+ * 2. ext4 delayed extents impelmentation
+ *
+ *   --	delayed extent
+ *	A delayed extent is a range of blocks which are contiguous
+ *	logically and under delayed allocation.  Unlike extent in
+ *	ext4, delayed extent in ext4 is a in-memory struct, there is
+ *	no corresponding on-disk data.  There is no limit on length of
+ *	delayed extent, so a delayed extent can contain as many blocks
+ *	as they are contiguous logically.
+ *
+ *   --	delayed extent tree
+ *	Every inode has a delayed extent tree and all under delayed
+ *	allocation blocks are added to the tree as delayed extents.
+ *	Delayed extents in the tree are ordered by logical block no.
+ *
+ *   --	operations on a delayed extent tree
+ *	There are three operations on a delayed extent tree: find next
+ *	delayed extent, adding a space(a range of blocks) and removing
+ *	a space.
+ *
+ *   --	race on a delayed extent tree
+ *	Delayed extent tree is protected inode->i_es_lock.
+ *
+ *
+ * ==========================================================================
+ * 3. performance analysis
+ *   --	overhead
+ *	1. There is a cache extent for write access, so if writes are
+ *	not very random, adding space operaions are in O(1) time.
+ *
+ *   --	gain
+ *	2. Code is much simpler, more readable, more maintainable and
+ *	more efficient.
+ *
+ *
+ * ==========================================================================
+ * 4. TODO list
+ *   -- Track all extent status
+ *
+ *   -- Improve get block process
+ *
+ *   -- Extent-level locking
+ */
+
+static struct kmem_cache *ext4_es_cachep;
+
+int __init ext4_init_es(void)
+{
+	ext4_es_cachep = KMEM_CACHE(extent_status, SLAB_RECLAIM_ACCOUNT);
+	if (ext4_es_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+void ext4_exit_es(void)
+{
+	if (ext4_es_cachep)
+		kmem_cache_destroy(ext4_es_cachep);
+}
+
+void ext4_es_init_tree(struct ext4_es_tree *tree)
+{
+	tree->root = RB_ROOT;
+	tree->cache_es = NULL;
+}
+
+#ifdef ES_DEBUG__
+static void ext4_es_print_tree(struct inode *inode)
+{
+	struct ext4_es_tree *tree;
+	struct rb_node *node;
+
+	printk(KERN_DEBUG "status extents for inode %lu:", inode->i_ino);
+	tree = &EXT4_I(inode)->i_es_tree;
+	node = rb_first(&tree->root);
+	while (node) {
+		struct extent_status *es;
+		es = rb_entry(node, struct extent_status, rb_node);
+		printk(KERN_DEBUG " [%u/%u)", es->start, es->len);
+		node = rb_next(node);
+	}
+	printk(KERN_DEBUG "\n");
+}
+#else
+#define ext4_es_print_tree(inode)
+#endif
+
+static inline ext4_lblk_t extent_status_end(struct extent_status *es)
+{
+	BUG_ON(es->start + es->len < es->start);
+	return es->start + es->len - 1;
+}
+
+/*
+ * search through the tree for an delayed extent with a given offset.  If
+ * it can't be found, try to find next extent.
+ */
+static struct extent_status *__es_tree_search(struct rb_root *root,
+					      ext4_lblk_t offset)
+{
+	struct rb_node *node = root->rb_node;
+	struct extent_status *es = NULL;
+
+	while (node) {
+		es = rb_entry(node, struct extent_status, rb_node);
+		if (offset < es->start)
+			node = node->rb_left;
+		else if (offset > extent_status_end(es))
+			node = node->rb_right;
+		else
+			return es;
+	}
+
+	if (es && offset < es->start)
+		return es;
+
+	if (es && offset > extent_status_end(es)) {
+		node = rb_next(&es->rb_node);
+		return node ? rb_entry(node, struct extent_status, rb_node) :
+			      NULL;
+	}
+
+	return NULL;
+}
+
+/*
+ * ext4_es_find_extent: find the 1st delayed extent covering @es->start
+ * if it exists, otherwise, the next extent after @es->start.
+ *
+ * @inode: the inode which owns delayed extents
+ * @es: delayed extent that we found
+ *
+ * Returns the first block of the next extent after es, otherwise
+ * EXT_MAX_BLOCKS if no delay extent is found.
+ * Delayed extent is returned via @es.
+ */
+ext4_lblk_t ext4_es_find_extent(struct inode *inode, struct extent_status *es)
+{
+	struct ext4_es_tree *tree = NULL;
+	struct extent_status *es1 = NULL;
+	struct rb_node *node;
+	ext4_lblk_t ret = EXT_MAX_BLOCKS;
+
+	trace_ext4_es_find_extent_enter(inode, es->start);
+
+	read_lock(&EXT4_I(inode)->i_es_lock);
+	tree = &EXT4_I(inode)->i_es_tree;
+
+	/* find delay extent in cache firstly */
+	if (tree->cache_es) {
+		es1 = tree->cache_es;
+		if (in_range(es->start, es1->start, es1->len)) {
+			es_debug("%u cached by [%u/%u)\n",
+				 es->start, es1->start, es1->len);
+			goto out;
+		}
+	}
+
+	es->len = 0;
+	es1 = __es_tree_search(&tree->root, es->start);
+
+out:
+	if (es1) {
+		tree->cache_es = es1;
+		es->start = es1->start;
+		es->len = es1->len;
+		node = rb_next(&es1->rb_node);
+		if (node) {
+			es1 = rb_entry(node, struct extent_status, rb_node);
+			ret = es1->start;
+		}
+	}
+
+	read_unlock(&EXT4_I(inode)->i_es_lock);
+
+	trace_ext4_es_find_extent_exit(inode, es, ret);
+	return ret;
+}
+
+static struct extent_status *
+ext4_es_alloc_extent(ext4_lblk_t start, ext4_lblk_t len)
+{
+	struct extent_status *es;
+	es = kmem_cache_alloc(ext4_es_cachep, GFP_ATOMIC);
+	if (es == NULL)
+		return NULL;
+	es->start = start;
+	es->len = len;
+	return es;
+}
+
+static void ext4_es_free_extent(struct extent_status *es)
+{
+	kmem_cache_free(ext4_es_cachep, es);
+}
+
+static struct extent_status *
+ext4_es_try_to_merge_left(struct ext4_es_tree *tree, struct extent_status *es)
+{
+	struct extent_status *es1;
+	struct rb_node *node;
+
+	node = rb_prev(&es->rb_node);
+	if (!node)
+		return es;
+
+	es1 = rb_entry(node, struct extent_status, rb_node);
+	if (es->start == extent_status_end(es1) + 1) {
+		es1->len += es->len;
+		rb_erase(&es->rb_node, &tree->root);
+		ext4_es_free_extent(es);
+		es = es1;
+	}
+
+	return es;
+}
+
+static struct extent_status *
+ext4_es_try_to_merge_right(struct ext4_es_tree *tree, struct extent_status *es)
+{
+	struct extent_status *es1;
+	struct rb_node *node;
+
+	node = rb_next(&es->rb_node);
+	if (!node)
+		return es;
+
+	es1 = rb_entry(node, struct extent_status, rb_node);
+	if (es1->start == extent_status_end(es) + 1) {
+		es->len += es1->len;
+		rb_erase(node, &tree->root);
+		ext4_es_free_extent(es1);
+	}
+
+	return es;
+}
+
+static int __es_insert_extent(struct ext4_es_tree *tree, ext4_lblk_t offset,
+			      ext4_lblk_t len)
+{
+	struct rb_node **p = &tree->root.rb_node;
+	struct rb_node *parent = NULL;
+	struct extent_status *es;
+	ext4_lblk_t end = offset + len - 1;
+
+	BUG_ON(end < offset);
+	es = tree->cache_es;
+	if (es && offset == (extent_status_end(es) + 1)) {
+		es_debug("cached by [%u/%u)\n", es->start, es->len);
+		es->len += len;
+		es = ext4_es_try_to_merge_right(tree, es);
+		goto out;
+	} else if (es && es->start == end + 1) {
+		es_debug("cached by [%u/%u)\n", es->start, es->len);
+		es->start = offset;
+		es->len += len;
+		es = ext4_es_try_to_merge_left(tree, es);
+		goto out;
+	} else if (es && es->start <= offset &&
+		   end <= extent_status_end(es)) {
+		es_debug("cached by [%u/%u)\n", es->start, es->len);
+		goto out;
+	}
+
+	while (*p) {
+		parent = *p;
+		es = rb_entry(parent, struct extent_status, rb_node);
+
+		if (offset < es->start) {
+			if (es->start == end + 1) {
+				es->start = offset;
+				es->len += len;
+				es = ext4_es_try_to_merge_left(tree, es);
+				goto out;
+			}
+			p = &(*p)->rb_left;
+		} else if (offset > extent_status_end(es)) {
+			if (offset == extent_status_end(es) + 1) {
+				es->len += len;
+				es = ext4_es_try_to_merge_right(tree, es);
+				goto out;
+			}
+			p = &(*p)->rb_right;
+		} else {
+			if (extent_status_end(es) <= end)
+				es->len = offset - es->start + len;
+			goto out;
+		}
+	}
+
+	es = ext4_es_alloc_extent(offset, len);
+	if (!es)
+		return -ENOMEM;
+	rb_link_node(&es->rb_node, parent, p);
+	rb_insert_color(&es->rb_node, &tree->root);
+
+out:
+	tree->cache_es = es;
+	return 0;
+}
+
+/*
+ * ext4_es_insert_extent() adds a space to a delayed extent tree.
+ * Caller holds inode->i_es_lock.
+ *
+ * ext4_es_insert_extent is called by ext4_da_write_begin and
+ * ext4_es_remove_extent.
+ *
+ * Return 0 on success, error code on failure.
+ */
+int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t offset,
+			  ext4_lblk_t len)
+{
+	struct ext4_es_tree *tree;
+	int err = 0;
+
+	trace_ext4_es_insert_extent(inode, offset, len);
+	es_debug("add [%u/%u) to extent status tree of inode %lu\n",
+		 offset, len, inode->i_ino);
+
+	write_lock(&EXT4_I(inode)->i_es_lock);
+	tree = &EXT4_I(inode)->i_es_tree;
+	err = __es_insert_extent(tree, offset, len);
+	write_unlock(&EXT4_I(inode)->i_es_lock);
+
+	ext4_es_print_tree(inode);
+
+	return err;
+}
+
+/*
+ * ext4_es_remove_extent() removes a space from a delayed extent tree.
+ * Caller holds inode->i_es_lock.
+ *
+ * Return 0 on success, error code on failure.
+ */
+int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t offset,
+			  ext4_lblk_t len)
+{
+	struct rb_node *node;
+	struct ext4_es_tree *tree;
+	struct extent_status *es;
+	struct extent_status orig_es;
+	ext4_lblk_t len1, len2, end;
+	int err = 0;
+
+	trace_ext4_es_remove_extent(inode, offset, len);
+	es_debug("remove [%u/%u) from extent status tree of inode %lu\n",
+		 offset, len, inode->i_ino);
+
+	end = offset + len - 1;
+	BUG_ON(end < offset);
+	write_lock(&EXT4_I(inode)->i_es_lock);
+	tree = &EXT4_I(inode)->i_es_tree;
+	es = __es_tree_search(&tree->root, offset);
+	if (!es)
+		goto out;
+	if (es->start > end)
+		goto out;
+
+	/* Simply invalidate cache_es. */
+	tree->cache_es = NULL;
+
+	orig_es.start = es->start;
+	orig_es.len = es->len;
+	len1 = offset > es->start ? offset - es->start : 0;
+	len2 = extent_status_end(es) > end ?
+	       extent_status_end(es) - end : 0;
+	if (len1 > 0)
+		es->len = len1;
+	if (len2 > 0) {
+		if (len1 > 0) {
+			err = __es_insert_extent(tree, end + 1, len2);
+			if (err) {
+				es->start = orig_es.start;
+				es->len = orig_es.len;
+				goto out;
+			}
+		} else {
+			es->start = end + 1;
+			es->len = len2;
+		}
+		goto out;
+	}
+
+	if (len1 > 0) {
+		node = rb_next(&es->rb_node);
+		if (node)
+			es = rb_entry(node, struct extent_status, rb_node);
+		else
+			es = NULL;
+	}
+
+	while (es && extent_status_end(es) <= end) {
+		node = rb_next(&es->rb_node);
+		rb_erase(&es->rb_node, &tree->root);
+		ext4_es_free_extent(es);
+		if (!node) {
+			es = NULL;
+			break;
+		}
+		es = rb_entry(node, struct extent_status, rb_node);
+	}
+
+	if (es && es->start < end + 1) {
+		len1 = extent_status_end(es) - end;
+		es->start = end + 1;
+		es->len = len1;
+	}
+
+out:
+	write_unlock(&EXT4_I(inode)->i_es_lock);
+	ext4_es_print_tree(inode);
+	return err;
+}
diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
new file mode 100644
index 0000000..077f82d
--- /dev/null
+++ b/fs/ext4/extents_status.h
@@ -0,0 +1,45 @@
+/*
+ *  fs/ext4/extents_status.h
+ *
+ * Written by Yongqiang Yang <xiaoqiangnk@gmail.com>
+ * Modified by
+ *	Allison Henderson <achender@linux.vnet.ibm.com>
+ *	Zheng Liu <wenqing.lz@taobao.com>
+ *
+ */
+
+#ifndef _EXT4_EXTENTS_STATUS_H
+#define _EXT4_EXTENTS_STATUS_H
+
+/*
+ * Turn on ES_DEBUG__ to get lots of info about extent status operations.
+ */
+#ifdef ES_DEBUG__
+#define es_debug(fmt, ...)	printk(fmt, ##__VA_ARGS__)
+#else
+#define es_debug(fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
+#endif
+
+struct extent_status {
+	struct rb_node rb_node;
+	ext4_lblk_t start;	/* first block extent covers */
+	ext4_lblk_t len;	/* length of extent in block */
+};
+
+struct ext4_es_tree {
+	struct rb_root root;
+	struct extent_status *cache_es;	/* recently accessed extent */
+};
+
+extern int __init ext4_init_es(void);
+extern void ext4_exit_es(void);
+extern void ext4_es_init_tree(struct ext4_es_tree *tree);
+
+extern int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t start,
+				 ext4_lblk_t len);
+extern int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t start,
+				 ext4_lblk_t len);
+extern ext4_lblk_t ext4_es_find_extent(struct inode *inode,
+				struct extent_status *es);
+
+#endif /* _EXT4_EXTENTS_STATUS_H */
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index bf3966b..2f5759e 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -24,6 +24,7 @@
 #include <linux/mount.h>
 #include <linux/path.h>
 #include <linux/quotaops.h>
+#include <linux/pagevec.h>
 #include "ext4.h"
 #include "ext4_jbd2.h"
 #include "xattr.h"
@@ -286,6 +287,324 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
 }
 
 /*
+ * Here we use ext4_map_blocks() to get a block mapping for a extent-based
+ * file rather than ext4_ext_walk_space() because we can introduce
+ * SEEK_DATA/SEEK_HOLE for block-mapped and extent-mapped file at the same
+ * function.  When extent status tree has been fully implemented, it will
+ * track all extent status for a file and we can directly use it to
+ * retrieve the offset for SEEK_DATA/SEEK_HOLE.
+ */
+
+/*
+ * When we retrieve the offset for SEEK_DATA/SEEK_HOLE, we would need to
+ * lookup page cache to check whether or not there has some data between
+ * [startoff, endoff] because, if this range contains an unwritten extent,
+ * we determine this extent as a data or a hole according to whether the
+ * page cache has data or not.
+ */
+static int ext4_find_unwritten_pgoff(struct inode *inode,
+				     int origin,
+				     struct ext4_map_blocks *map,
+				     loff_t *offset)
+{
+	struct pagevec pvec;
+	unsigned int blkbits;
+	pgoff_t index;
+	pgoff_t end;
+	loff_t endoff;
+	loff_t startoff;
+	loff_t lastoff;
+	int found = 0;
+
+	blkbits = inode->i_sb->s_blocksize_bits;
+	startoff = *offset;
+	lastoff = startoff;
+	endoff = (map->m_lblk + map->m_len) << blkbits;
+
+	index = startoff >> PAGE_CACHE_SHIFT;
+	end = endoff >> PAGE_CACHE_SHIFT;
+
+	pagevec_init(&pvec, 0);
+	do {
+		int i, num;
+		unsigned long nr_pages;
+
+		num = min_t(pgoff_t, end - index, PAGEVEC_SIZE);
+		nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index,
+					  (pgoff_t)num);
+		if (nr_pages == 0) {
+			if (origin == SEEK_DATA)
+				break;
+
+			BUG_ON(origin != SEEK_HOLE);
+			/*
+			 * If this is the first time to go into the loop and
+			 * offset is not beyond the end offset, it will be a
+			 * hole at this offset
+			 */
+			if (lastoff == startoff || lastoff < endoff)
+				found = 1;
+			break;
+		}
+
+		/*
+		 * If this is the first time to go into the loop and
+		 * offset is smaller than the first page offset, it will be a
+		 * hole at this offset.
+		 */
+		if (lastoff == startoff && origin == SEEK_HOLE &&
+		    lastoff < page_offset(pvec.pages[0])) {
+			found = 1;
+			break;
+		}
+
+		for (i = 0; i < nr_pages; i++) {
+			struct page *page = pvec.pages[i];
+			struct buffer_head *bh, *head;
+
+			/*
+			 * If the current offset is not beyond the end of given
+			 * range, it will be a hole.
+			 */
+			if (lastoff < endoff && origin == SEEK_HOLE &&
+			    page->index > end) {
+				found = 1;
+				*offset = lastoff;
+				goto out;
+			}
+
+			lock_page(page);
+
+			if (unlikely(page->mapping != inode->i_mapping)) {
+				unlock_page(page);
+				continue;
+			}
+
+			if (!page_has_buffers(page)) {
+				unlock_page(page);
+				continue;
+			}
+
+			if (page_has_buffers(page)) {
+				lastoff = page_offset(page);
+				bh = head = page_buffers(page);
+				do {
+					if (buffer_uptodate(bh) ||
+					    buffer_unwritten(bh)) {
+						if (origin == SEEK_DATA)
+							found = 1;
+					} else {
+						if (origin == SEEK_HOLE)
+							found = 1;
+					}
+					if (found) {
+						*offset = max_t(loff_t,
+							startoff, lastoff);
+						unlock_page(page);
+						goto out;
+					}
+					lastoff += bh->b_size;
+					bh = bh->b_this_page;
+				} while (bh != head);
+			}
+
+			lastoff = page_offset(page) + PAGE_SIZE;
+			unlock_page(page);
+		}
+
+		/*
+		 * The no. of pages is less than our desired, that would be a
+		 * hole in there.
+		 */
+		if (nr_pages < num && origin == SEEK_HOLE) {
+			found = 1;
+			*offset = lastoff;
+			break;
+		}
+
+		index = pvec.pages[i - 1]->index + 1;
+		pagevec_release(&pvec);
+	} while (index <= end);
+
+out:
+	pagevec_release(&pvec);
+	return found;
+}
+
+/*
+ * ext4_seek_data() retrieves the offset for SEEK_DATA.
+ */
+static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize)
+{
+	struct inode *inode = file->f_mapping->host;
+	struct ext4_map_blocks map;
+	struct extent_status es;
+	ext4_lblk_t start, last, end;
+	loff_t dataoff, isize;
+	int blkbits;
+	int ret = 0;
+
+	mutex_lock(&inode->i_mutex);
+
+	isize = i_size_read(inode);
+	if (offset >= isize) {
+		mutex_unlock(&inode->i_mutex);
+		return -ENXIO;
+	}
+
+	blkbits = inode->i_sb->s_blocksize_bits;
+	start = offset >> blkbits;
+	last = start;
+	end = isize >> blkbits;
+	dataoff = offset;
+
+	do {
+		map.m_lblk = last;
+		map.m_len = end - last + 1;
+		ret = ext4_map_blocks(NULL, inode, &map, 0);
+		if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) {
+			if (last != start)
+				dataoff = last << blkbits;
+			break;
+		}
+
+		/*
+		 * If there is a delay extent at this offset,
+		 * it will be as a data.
+		 */
+		es.start = last;
+		(void)ext4_es_find_extent(inode, &es);
+		if (last >= es.start &&
+		    last < es.start + es.len) {
+			if (last != start)
+				dataoff = last << blkbits;
+			break;
+		}
+
+		/*
+		 * If there is a unwritten extent at this offset,
+		 * it will be as a data or a hole according to page
+		 * cache that has data or not.
+		 */
+		if (map.m_flags & EXT4_MAP_UNWRITTEN) {
+			int unwritten;
+			unwritten = ext4_find_unwritten_pgoff(inode, SEEK_DATA,
+							      &map, &dataoff);
+			if (unwritten)
+				break;
+		}
+
+		last++;
+		dataoff = last << blkbits;
+	} while (last <= end);
+
+	mutex_unlock(&inode->i_mutex);
+
+	if (dataoff > isize)
+		return -ENXIO;
+
+	if (dataoff < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
+		return -EINVAL;
+	if (dataoff > maxsize)
+		return -EINVAL;
+
+	if (dataoff != file->f_pos) {
+		file->f_pos = dataoff;
+		file->f_version = 0;
+	}
+
+	return dataoff;
+}
+
+/*
+ * ext4_seek_hole() retrieves the offset for SEEK_HOLE.
+ */
+static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize)
+{
+	struct inode *inode = file->f_mapping->host;
+	struct ext4_map_blocks map;
+	struct extent_status es;
+	ext4_lblk_t start, last, end;
+	loff_t holeoff, isize;
+	int blkbits;
+	int ret = 0;
+
+	mutex_lock(&inode->i_mutex);
+
+	isize = i_size_read(inode);
+	if (offset >= isize) {
+		mutex_unlock(&inode->i_mutex);
+		return -ENXIO;
+	}
+
+	blkbits = inode->i_sb->s_blocksize_bits;
+	start = offset >> blkbits;
+	last = start;
+	end = isize >> blkbits;
+	holeoff = offset;
+
+	do {
+		map.m_lblk = last;
+		map.m_len = end - last + 1;
+		ret = ext4_map_blocks(NULL, inode, &map, 0);
+		if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) {
+			last += ret;
+			holeoff = last << blkbits;
+			continue;
+		}
+
+		/*
+		 * If there is a delay extent at this offset,
+		 * we will skip this extent.
+		 */
+		es.start = last;
+		(void)ext4_es_find_extent(inode, &es);
+		if (last >= es.start &&
+		    last < es.start + es.len) {
+			last = es.start + es.len;
+			holeoff = last << blkbits;
+			continue;
+		}
+
+		/*
+		 * If there is a unwritten extent at this offset,
+		 * it will be as a data or a hole according to page
+		 * cache that has data or not.
+		 */
+		if (map.m_flags & EXT4_MAP_UNWRITTEN) {
+			int unwritten;
+			unwritten = ext4_find_unwritten_pgoff(inode, SEEK_HOLE,
+							      &map, &holeoff);
+			if (!unwritten) {
+				last += ret;
+				holeoff = last << blkbits;
+				continue;
+			}
+		}
+
+		/* find a hole */
+		break;
+	} while (last <= end);
+
+	mutex_unlock(&inode->i_mutex);
+
+	if (holeoff > isize)
+		holeoff = isize;
+
+	if (holeoff < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
+		return -EINVAL;
+	if (holeoff > maxsize)
+		return -EINVAL;
+
+	if (holeoff != file->f_pos) {
+		file->f_pos = holeoff;
+		file->f_version = 0;
+	}
+
+	return holeoff;
+}
+
+/*
  * ext4_llseek() handles both block-mapped and extent-mapped maxbytes values
  * by calling generic_file_llseek_size() with the appropriate maxbytes
  * value for each.
@@ -300,8 +619,19 @@ loff_t ext4_llseek(struct file *file, loff_t offset, int origin)
 	else
 		maxbytes = inode->i_sb->s_maxbytes;
 
-	return generic_file_llseek_size(file, offset, origin,
-					maxbytes, i_size_read(inode));
+	switch (origin) {
+	case SEEK_SET:
+	case SEEK_CUR:
+	case SEEK_END:
+		return generic_file_llseek_size(file, offset, origin,
+						maxbytes, i_size_read(inode));
+	case SEEK_DATA:
+		return ext4_seek_data(file, offset, maxbytes);
+	case SEEK_HOLE:
+		return ext4_seek_hole(file, offset, maxbytes);
+	}
+
+	return -EINVAL;
 }
 
 const struct file_operations ext4_file_operations = {
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index 792e388..f6663c3 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -755,8 +755,7 @@ cleanup:
 		partial--;
 	}
 out:
-	trace_ext4_ind_map_blocks_exit(inode, map->m_lblk,
-				map->m_pblk, map->m_len, err);
+	trace_ext4_ind_map_blocks_exit(inode, map, err);
 	return err;
 }
 
@@ -1412,6 +1411,7 @@ void ext4_ind_truncate(struct inode *inode)
 	down_write(&ei->i_data_sem);
 
 	ext4_discard_preallocations(inode);
+	ext4_es_remove_extent(inode, last_block, EXT_MAX_BLOCKS - last_block);
 
 	/*
 	 * The orphan list entry will now protect us from any crash which
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index b3c243b..cf5d30a 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -484,49 +484,6 @@ static pgoff_t ext4_num_dirty_pages(struct inode *inode, pgoff_t idx,
 }
 
 /*
- * Sets the BH_Da_Mapped bit on the buffer heads corresponding to the given map.
- */
-static void set_buffers_da_mapped(struct inode *inode,
-				   struct ext4_map_blocks *map)
-{
-	struct address_space *mapping = inode->i_mapping;
-	struct pagevec pvec;
-	int i, nr_pages;
-	pgoff_t index, end;
-
-	index = map->m_lblk >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
-	end = (map->m_lblk + map->m_len - 1) >>
-		(PAGE_CACHE_SHIFT - inode->i_blkbits);
-
-	pagevec_init(&pvec, 0);
-	while (index <= end) {
-		nr_pages = pagevec_lookup(&pvec, mapping, index,
-					  min(end - index + 1,
-					      (pgoff_t)PAGEVEC_SIZE));
-		if (nr_pages == 0)
-			break;
-		for (i = 0; i < nr_pages; i++) {
-			struct page *page = pvec.pages[i];
-			struct buffer_head *bh, *head;
-
-			if (unlikely(page->mapping != mapping) ||
-			    !PageDirty(page))
-				break;
-
-			if (page_has_buffers(page)) {
-				bh = head = page_buffers(page);
-				do {
-					set_buffer_da_mapped(bh);
-					bh = bh->b_this_page;
-				} while (bh != head);
-			}
-			index++;
-		}
-		pagevec_release(&pvec);
-	}
-}
-
-/*
  * The ext4_map_blocks() function tries to look up the requested blocks,
  * and returns if the blocks are already mapped.
  *
@@ -574,7 +531,16 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
 		up_read((&EXT4_I(inode)->i_data_sem));
 
 	if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
-		int ret = check_block_validity(inode, map);
+		int ret;
+		if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) {
+			/* delayed alloc may be allocated by fallocate and
+			 * coverted to initialized by directIO.
+			 * we need to handle delayed extent here.
+			 */
+			down_write((&EXT4_I(inode)->i_data_sem));
+			goto delayed_mapped;
+		}
+		ret = check_block_validity(inode, map);
 		if (ret != 0)
 			return ret;
 	}
@@ -652,12 +618,15 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
 	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) {
 		ext4_clear_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED);
 
-		/* If we have successfully mapped the delayed allocated blocks,
-		 * set the BH_Da_Mapped bit on them. Its important to do this
-		 * under the protection of i_data_sem.
-		 */
-		if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED)
-			set_buffers_da_mapped(inode, map);
+		if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
+			int ret;
+delayed_mapped:
+			/* delayed allocation blocks has been allocated */
+			ret = ext4_es_remove_extent(inode, map->m_lblk,
+						    map->m_len);
+			if (ret < 0)
+				retval = ret;
+		}
 	}
 
 	up_write((&EXT4_I(inode)->i_data_sem));
@@ -683,7 +652,7 @@ static int _ext4_get_block(struct inode *inode, sector_t iblock,
 	map.m_lblk = iblock;
 	map.m_len = bh->b_size >> inode->i_blkbits;
 
-	if (flags && !handle) {
+	if (flags && !(flags & EXT4_GET_BLOCKS_NO_LOCK) && !handle) {
 		/* Direct IO write... */
 		if (map.m_len > DIO_MAX_BLOCKS)
 			map.m_len = DIO_MAX_BLOCKS;
@@ -880,6 +849,8 @@ static int do_journal_get_write_access(handle_t *handle,
 
 static int ext4_get_block_write(struct inode *inode, sector_t iblock,
 		   struct buffer_head *bh_result, int create);
+static int ext4_get_block_write_nolock(struct inode *inode, sector_t iblock,
+		   struct buffer_head *bh_result, int create);
 static int ext4_write_begin(struct file *file, struct address_space *mapping,
 			    loff_t pos, unsigned len, unsigned flags,
 			    struct page **pagep, void **fsdata)
@@ -1301,6 +1272,7 @@ static void ext4_da_page_release_reservation(struct page *page,
 	struct inode *inode = page->mapping->host;
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 	int num_clusters;
+	ext4_fsblk_t lblk;
 
 	head = page_buffers(page);
 	bh = head;
@@ -1310,20 +1282,23 @@ static void ext4_da_page_release_reservation(struct page *page,
 		if ((offset <= curr_off) && (buffer_delay(bh))) {
 			to_release++;
 			clear_buffer_delay(bh);
-			clear_buffer_da_mapped(bh);
 		}
 		curr_off = next_off;
 	} while ((bh = bh->b_this_page) != head);
 
+	if (to_release) {
+		lblk = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
+		ext4_es_remove_extent(inode, lblk, to_release);
+	}
+
 	/* If we have released all the blocks belonging to a cluster, then we
 	 * need to release the reserved space for that cluster. */
 	num_clusters = EXT4_NUM_B2C(sbi, to_release);
 	while (num_clusters > 0) {
-		ext4_fsblk_t lblk;
 		lblk = (page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits)) +
 			((num_clusters - 1) << sbi->s_cluster_bits);
 		if (sbi->s_cluster_ratio == 1 ||
-		    !ext4_find_delalloc_cluster(inode, lblk, 1))
+		    !ext4_find_delalloc_cluster(inode, lblk))
 			ext4_da_release_space(inode, 1);
 
 		num_clusters--;
@@ -1429,8 +1404,6 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
 						clear_buffer_delay(bh);
 						bh->b_blocknr = pblock;
 					}
-					if (buffer_da_mapped(bh))
-						clear_buffer_da_mapped(bh);
 					if (buffer_unwritten(bh) ||
 					    buffer_mapped(bh))
 						BUG_ON(bh->b_blocknr != pblock);
@@ -1500,9 +1473,16 @@ static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd)
 	struct pagevec pvec;
 	struct inode *inode = mpd->inode;
 	struct address_space *mapping = inode->i_mapping;
+	ext4_lblk_t start, last;
 
 	index = mpd->first_page;
 	end   = mpd->next_page - 1;
+
+	start = index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
+	last = end << (PAGE_CACHE_SHIFT - inode->i_blkbits);
+	ext4_es_remove_extent(inode, start, last - start + 1);
+
+	pagevec_init(&pvec, 0);
 	while (index <= end) {
 		nr_pages = pagevec_lookup(&pvec, mapping, index, PAGEVEC_SIZE);
 		if (nr_pages == 0)
@@ -1656,15 +1636,6 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd)
 
 		for (i = 0; i < map.m_len; i++)
 			unmap_underlying_metadata(bdev, map.m_pblk + i);
-
-		if (ext4_should_order_data(mpd->inode)) {
-			err = ext4_jbd2_file_inode(handle, mpd->inode);
-			if (err) {
-				/* Only if the journal is aborted */
-				mpd->retval = err;
-				goto submit_io;
-			}
-		}
 	}
 
 	/*
@@ -1814,6 +1785,10 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
 				goto out_unlock;
 		}
 
+		retval = ext4_es_insert_extent(inode, map->m_lblk, map->m_len);
+		if (retval)
+			goto out_unlock;
+
 		/* Clear EXT4_MAP_FROM_CLUSTER flag since its purpose is served
 		 * and it should not appear on the bh->b_state.
 		 */
@@ -2608,17 +2583,8 @@ static int ext4_da_write_end(struct file *file,
 	if (copied && new_i_size > EXT4_I(inode)->i_disksize) {
 		if (ext4_da_should_update_i_disksize(page, end)) {
 			down_write(&EXT4_I(inode)->i_data_sem);
-			if (new_i_size > EXT4_I(inode)->i_disksize) {
-				/*
-				 * Updating i_disksize when extending file
-				 * without needing block allocation
-				 */
-				if (ext4_should_order_data(inode))
-					ret = ext4_jbd2_file_inode(handle,
-								   inode);
-
+			if (new_i_size > EXT4_I(inode)->i_disksize)
 				EXT4_I(inode)->i_disksize = new_i_size;
-			}
 			up_write(&EXT4_I(inode)->i_data_sem);
 			/* We need to mark inode dirty even if
 			 * new_i_size is less that inode->i_size
@@ -2850,29 +2816,12 @@ static int ext4_get_block_write(struct inode *inode, sector_t iblock,
 }
 
 static int ext4_get_block_write_nolock(struct inode *inode, sector_t iblock,
-		   struct buffer_head *bh_result, int flags)
+		   struct buffer_head *bh_result, int create)
 {
-	handle_t *handle = ext4_journal_current_handle();
-	struct ext4_map_blocks map;
-	int ret = 0;
-
-	ext4_debug("ext4_get_block_write_nolock: inode %lu, flag %d\n",
-		   inode->i_ino, flags);
-
-	flags = EXT4_GET_BLOCKS_NO_LOCK;
-
-	map.m_lblk = iblock;
-	map.m_len = bh_result->b_size >> inode->i_blkbits;
-
-	ret = ext4_map_blocks(handle, inode, &map, flags);
-	if (ret > 0) {
-		map_bh(bh_result, inode->i_sb, map.m_pblk);
-		bh_result->b_state = (bh_result->b_state & ~EXT4_MAP_FLAGS) |
-					map.m_flags;
-		bh_result->b_size = inode->i_sb->s_blocksize * map.m_len;
-		ret = 0;
-	}
-	return ret;
+	ext4_debug("ext4_get_block_write_nolock: inode %lu, create flag %d\n",
+		   inode->i_ino, create);
+	return _ext4_get_block(inode, iblock, bh_result,
+			       EXT4_GET_BLOCKS_NO_LOCK);
 }
 
 static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
@@ -3003,6 +2952,8 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
 	loff_t final_size = offset + count;
 	if (rw == WRITE && final_size <= inode->i_size) {
 		int overwrite = 0;
+		get_block_t *get_block_func = NULL;
+		int dio_flags = 0;
 
 		BUG_ON(iocb->private == NULL);
 
@@ -3056,22 +3007,20 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
 			ext4_inode_aio_set(inode, io_end);
 		}
 
-		if (overwrite)
-			ret = __blockdev_direct_IO(rw, iocb, inode,
-						 inode->i_sb->s_bdev, iov,
-						 offset, nr_segs,
-						 ext4_get_block_write_nolock,
-						 ext4_end_io_dio,
-						 NULL,
-						 0);
-		else
-			ret = __blockdev_direct_IO(rw, iocb, inode,
-						 inode->i_sb->s_bdev, iov,
-						 offset, nr_segs,
-						 ext4_get_block_write,
-						 ext4_end_io_dio,
-						 NULL,
-						 DIO_LOCKING);
+		if (overwrite) {
+			get_block_func = ext4_get_block_write_nolock;
+		} else {
+			get_block_func = ext4_get_block_write;
+			dio_flags = DIO_LOCKING;
+		}
+		ret = __blockdev_direct_IO(rw, iocb, inode,
+					 inode->i_sb->s_bdev, iov,
+					 offset, nr_segs,
+					 get_block_func,
+					 ext4_end_io_dio,
+					 NULL,
+					 dio_flags);
+
 		if (iocb->private)
 			ext4_inode_aio_set(inode, NULL);
 		/*
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 526e553..1bf6fe7 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -1373,7 +1373,7 @@ static int mb_find_extent(struct ext4_buddy *e4b, int block,
 	ex->fe_start += next;
 
 	while (needed > ex->fe_len &&
-	       (buddy = mb_find_buddy(e4b, order, &max))) {
+	       mb_find_buddy(e4b, order, &max)) {
 
 		if (block + 1 >= max)
 			break;
@@ -2607,9 +2607,17 @@ static void ext4_free_data_callback(struct super_block *sb,
 	mb_debug(1, "gonna free %u blocks in group %u (0x%p):",
 		 entry->efd_count, entry->efd_group, entry);
 
-	if (test_opt(sb, DISCARD))
-		ext4_issue_discard(sb, entry->efd_group,
-				   entry->efd_start_cluster, entry->efd_count);
+	if (test_opt(sb, DISCARD)) {
+		err = ext4_issue_discard(sb, entry->efd_group,
+					 entry->efd_start_cluster,
+					 entry->efd_count);
+		if (err && err != -EOPNOTSUPP)
+			ext4_msg(sb, KERN_WARNING, "discard request in"
+				 " group:%d block:%d count:%d failed"
+				 " with %d", entry->efd_group,
+				 entry->efd_start_cluster,
+				 entry->efd_count, err);
+	}
 
 	err = ext4_mb_load_buddy(sb, entry->efd_group, &e4b);
 	/* we expect to find existing buddy because it's pinned */
@@ -4310,8 +4318,10 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
 repeat:
 		/* allocate space in core */
 		*errp = ext4_mb_regular_allocator(ac);
-		if (*errp)
+		if (*errp) {
+			ext4_discard_allocated_blocks(ac);
 			goto errout;
+		}
 
 		/* as we've just preallocated more space than
 		 * user requested orinally, we store allocated
@@ -4333,10 +4343,10 @@ repeat:
 			ac->ac_b_ex.fe_len = 0;
 			ac->ac_status = AC_STATUS_CONTINUE;
 			goto repeat;
-		} else if (*errp)
-		errout:
+		} else if (*errp) {
 			ext4_discard_allocated_blocks(ac);
-		else {
+			goto errout;
+		} else {
 			block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex);
 			ar->len = ac->ac_b_ex.fe_len;
 		}
@@ -4347,6 +4357,7 @@ repeat:
 		*errp = -ENOSPC;
 	}
 
+errout:
 	if (*errp) {
 		ac->ac_b_ex.fe_len = 0;
 		ar->len = 0;
@@ -4656,8 +4667,16 @@ do_more:
 		 * with group lock held. generate_buddy look at
 		 * them with group lock_held
 		 */
-		if (test_opt(sb, DISCARD))
-			ext4_issue_discard(sb, block_group, bit, count);
+		if (test_opt(sb, DISCARD)) {
+			err = ext4_issue_discard(sb, block_group, bit, count);
+			if (err && err != -EOPNOTSUPP)
+				ext4_msg(sb, KERN_WARNING, "discard request in"
+					 " group:%d block:%d count:%lu failed"
+					 " with %d", block_group, bit, count,
+					 err);
+		}
+
+
 		ext4_lock_group(sb, block_group);
 		mb_clear_bits(bitmap_bh->b_data, bit, count_clusters);
 		mb_free_blocks(inode, &e4b, bit, count_clusters);
@@ -4851,10 +4870,11 @@ error_return:
  * one will allocate those blocks, mark it as used in buddy bitmap. This must
  * be called with under the group lock.
  */
-static void ext4_trim_extent(struct super_block *sb, int start, int count,
+static int ext4_trim_extent(struct super_block *sb, int start, int count,
 			     ext4_group_t group, struct ext4_buddy *e4b)
 {
 	struct ext4_free_extent ex;
+	int ret = 0;
 
 	trace_ext4_trim_extent(sb, group, start, count);
 
@@ -4870,9 +4890,10 @@ static void ext4_trim_extent(struct super_block *sb, int start, int count,
 	 */
 	mb_mark_used(e4b, &ex);
 	ext4_unlock_group(sb, group);
-	ext4_issue_discard(sb, group, start, count);
+	ret = ext4_issue_discard(sb, group, start, count);
 	ext4_lock_group(sb, group);
 	mb_free_blocks(NULL, e4b, start, ex.fe_len);
+	return ret;
 }
 
 /**
@@ -4901,7 +4922,7 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
 	void *bitmap;
 	ext4_grpblk_t next, count = 0, free_count = 0;
 	struct ext4_buddy e4b;
-	int ret;
+	int ret = 0;
 
 	trace_ext4_trim_all_free(sb, group, start, max);
 
@@ -4928,8 +4949,11 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
 		next = mb_find_next_bit(bitmap, max + 1, start);
 
 		if ((next - start) >= minblocks) {
-			ext4_trim_extent(sb, start,
-					 next - start, group, &e4b);
+			ret = ext4_trim_extent(sb, start,
+					       next - start, group, &e4b);
+			if (ret && ret != -EOPNOTSUPP)
+				break;
+			ret = 0;
 			count += next - start;
 		}
 		free_count += next - start;
@@ -4950,8 +4974,10 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
 			break;
 	}
 
-	if (!ret)
+	if (!ret) {
+		ret = count;
 		EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info);
+	}
 out:
 	ext4_unlock_group(sb, group);
 	ext4_mb_unload_buddy(&e4b);
@@ -4959,7 +4985,7 @@ out:
 	ext4_debug("trimmed %d blocks in the group %d\n",
 		count, group);
 
-	return count;
+	return ret;
 }
 
 /**
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 6d600a6..88e9a2c 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -261,6 +261,12 @@ static __le32 ext4_dirent_csum(struct inode *inode,
 	return cpu_to_le32(csum);
 }
 
+static void warn_no_space_for_csum(struct inode *inode)
+{
+	ext4_warning(inode->i_sb, "no space in directory inode %lu leaf for "
+		     "checksum.  Please run e2fsck -D.", inode->i_ino);
+}
+
 int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent)
 {
 	struct ext4_dir_entry_tail *t;
@@ -271,8 +277,7 @@ int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent)
 
 	t = get_dirent_tail(inode, dirent);
 	if (!t) {
-		EXT4_ERROR_INODE(inode, "metadata_csum set but no space in dir "
-				 "leaf for checksum.  Please run e2fsck -D.");
+		warn_no_space_for_csum(inode);
 		return 0;
 	}
 
@@ -294,8 +299,7 @@ static void ext4_dirent_csum_set(struct inode *inode,
 
 	t = get_dirent_tail(inode, dirent);
 	if (!t) {
-		EXT4_ERROR_INODE(inode, "metadata_csum set but no space in dir "
-				 "leaf for checksum.  Please run e2fsck -D.");
+		warn_no_space_for_csum(inode);
 		return;
 	}
 
@@ -377,8 +381,7 @@ static int ext4_dx_csum_verify(struct inode *inode,
 	count = le16_to_cpu(c->count);
 	if (count_offset + (limit * sizeof(struct dx_entry)) >
 	    EXT4_BLOCK_SIZE(inode->i_sb) - sizeof(struct dx_tail)) {
-		EXT4_ERROR_INODE(inode, "metadata_csum set but no space for "
-				 "tree checksum found.  Run e2fsck -D.");
+		warn_no_space_for_csum(inode);
 		return 1;
 	}
 	t = (struct dx_tail *)(((struct dx_entry *)c) + limit);
@@ -408,8 +411,7 @@ static void ext4_dx_csum_set(struct inode *inode, struct ext4_dir_entry *dirent)
 	count = le16_to_cpu(c->count);
 	if (count_offset + (limit * sizeof(struct dx_entry)) >
 	    EXT4_BLOCK_SIZE(inode->i_sb) - sizeof(struct dx_tail)) {
-		EXT4_ERROR_INODE(inode, "metadata_csum set but no space for "
-				 "tree checksum.  Run e2fsck -D.");
+		warn_no_space_for_csum(inode);
 		return;
 	}
 	t = (struct dx_tail *)(((struct dx_entry *)c) + limit);
@@ -1144,6 +1146,21 @@ static inline int search_dirblock(struct buffer_head *bh,
 	return 0;
 }
 
+static int is_dx_internal_node(struct inode *dir, ext4_lblk_t block,
+			       struct ext4_dir_entry *de)
+{
+	struct super_block *sb = dir->i_sb;
+
+	if (!is_dx(dir))
+		return 0;
+	if (block == 0)
+		return 1;
+	if (de->inode == 0 &&
+	    ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize) ==
+			sb->s_blocksize)
+		return 1;
+	return 0;
+}
 
 /*
  *	ext4_find_entry()
@@ -1244,6 +1261,8 @@ restart:
 			goto next;
 		}
 		if (!buffer_verified(bh) &&
+		    !is_dx_internal_node(dir, block,
+					 (struct ext4_dir_entry *)bh->b_data) &&
 		    !ext4_dirent_csum_verify(dir,
 				(struct ext4_dir_entry *)bh->b_data)) {
 			EXT4_ERROR_INODE(dir, "checksumming directory "
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index 68e896e..0fd16e6 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -111,7 +111,7 @@ static int ext4_end_io(ext4_io_end_t *io)
 		inode_dio_done(inode);
 	/* Wake up anyone waiting on unwritten extent conversion */
 	if (atomic_dec_and_test(&EXT4_I(inode)->i_unwritten))
-		wake_up_all(ext4_ioend_wq(io->inode));
+		wake_up_all(ext4_ioend_wq(inode));
 	return ret;
 }
 
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 47bf06a..d99387b 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -783,7 +783,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
 
 	err = ext4_journal_get_write_access(handle, gdb_bh);
 	if (unlikely(err))
-		goto exit_sbh;
+		goto exit_dind;
 
 	err = ext4_journal_get_write_access(handle, dind);
 	if (unlikely(err))
@@ -792,7 +792,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
 	/* ext4_reserve_inode_write() gets a reference on the iloc */
 	err = ext4_reserve_inode_write(handle, inode, &iloc);
 	if (unlikely(err))
-		goto exit_dindj;
+		goto exit_dind;
 
 	n_group_desc = ext4_kvmalloc((gdb_num + 1) *
 				     sizeof(struct buffer_head *),
@@ -846,12 +846,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
 
 exit_inode:
 	ext4_kvfree(n_group_desc);
-	/* ext4_handle_release_buffer(handle, iloc.bh); */
 	brelse(iloc.bh);
-exit_dindj:
-	/* ext4_handle_release_buffer(handle, dind); */
-exit_sbh:
-	/* ext4_handle_release_buffer(handle, EXT4_SB(sb)->s_sbh); */
 exit_dind:
 	brelse(dind);
 exit_bh:
@@ -969,14 +964,8 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
 	}
 
 	for (i = 0; i < reserved_gdb; i++) {
-		if ((err = ext4_journal_get_write_access(handle, primary[i]))) {
-			/*
-			int j;
-			for (j = 0; j < i; j++)
-				ext4_handle_release_buffer(handle, primary[j]);
-			 */
+		if ((err = ext4_journal_get_write_access(handle, primary[i])))
 			goto exit_bh;
-		}
 	}
 
 	if ((err = ext4_reserve_inode_write(handle, inode, &iloc)))
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 80928f7..ad6cd8a 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -50,6 +50,7 @@
 #include "xattr.h"
 #include "acl.h"
 #include "mballoc.h"
+#include "ext4_extents.h"
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/ext4.h>
@@ -943,6 +944,8 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
 	memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache));
 	INIT_LIST_HEAD(&ei->i_prealloc_list);
 	spin_lock_init(&ei->i_prealloc_lock);
+	ext4_es_init_tree(&ei->i_es_tree);
+	rwlock_init(&ei->i_es_lock);
 	ei->i_reserved_data_blocks = 0;
 	ei->i_reserved_meta_blocks = 0;
 	ei->i_allocated_meta_blocks = 0;
@@ -1031,6 +1034,7 @@ void ext4_clear_inode(struct inode *inode)
 	clear_inode(inode);
 	dquot_drop(inode);
 	ext4_discard_preallocations(inode);
+	ext4_es_remove_extent(inode, 0, EXT_MAX_BLOCKS);
 	if (EXT4_I(inode)->jinode) {
 		jbd2_journal_release_jbd_inode(EXT4_JOURNAL(inode),
 					       EXT4_I(inode)->jinode);
@@ -3256,7 +3260,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	unsigned int i;
 	int needs_recovery, has_huge_files, has_bigalloc;
 	__u64 blocks_count;
-	int err;
+	int err = 0;
 	unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
 	ext4_group_t first_not_zeroed;
 
@@ -3272,9 +3276,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	}
 	sb->s_fs_info = sbi;
 	sbi->s_sb = sb;
-	sbi->s_mount_opt = 0;
-	sbi->s_resuid = make_kuid(&init_user_ns, EXT4_DEF_RESUID);
-	sbi->s_resgid = make_kgid(&init_user_ns, EXT4_DEF_RESGID);
 	sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS;
 	sbi->s_sb_block = sb_block;
 	if (sb->s_bdev->bd_part)
@@ -3285,6 +3286,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	for (cp = sb->s_id; (cp = strchr(cp, '/'));)
 		*cp = '!';
 
+	/* -EINVAL is default */
 	ret = -EINVAL;
 	blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE);
 	if (!blocksize) {
@@ -3662,7 +3664,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 			 " too large to mount safely on this system");
 		if (sizeof(sector_t) < 8)
 			ext4_msg(sb, KERN_WARNING, "CONFIG_LBDAF not enabled");
-		ret = err;
 		goto failed_mount;
 	}
 
@@ -3770,7 +3771,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	}
 	if (err) {
 		ext4_msg(sb, KERN_ERR, "insufficient memory");
-		ret = err;
 		goto failed_mount3;
 	}
 
@@ -3897,8 +3897,8 @@ no_journal:
 	if (es->s_overhead_clusters)
 		sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters);
 	else {
-		ret = ext4_calculate_overhead(sb);
-		if (ret)
+		err = ext4_calculate_overhead(sb);
+		if (err)
 			goto failed_mount_wq;
 	}
 
@@ -3910,6 +3910,7 @@ no_journal:
 		alloc_workqueue("ext4-dio-unwritten", WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
 	if (!EXT4_SB(sb)->dio_unwritten_wq) {
 		printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n");
+		ret = -ENOMEM;
 		goto failed_mount_wq;
 	}
 
@@ -4012,12 +4013,20 @@ no_journal:
 	/* Enable quota usage during mount. */
 	if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) &&
 	    !(sb->s_flags & MS_RDONLY)) {
-		ret = ext4_enable_quotas(sb);
-		if (ret)
+		err = ext4_enable_quotas(sb);
+		if (err)
 			goto failed_mount7;
 	}
 #endif  /* CONFIG_QUOTA */
 
+	if (test_opt(sb, DISCARD)) {
+		struct request_queue *q = bdev_get_queue(sb->s_bdev);
+		if (!blk_queue_discard(q))
+			ext4_msg(sb, KERN_WARNING,
+				 "mounting with \"discard\" option, but "
+				 "the device does not support discard");
+	}
+
 	ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
 		 "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
 		 *sbi->s_es->s_mount_opts ? "; " : "", orig_data);
@@ -4084,7 +4093,7 @@ out_fail:
 	kfree(sbi);
 out_free_orig:
 	kfree(orig_data);
-	return ret;
+	return err ? err : ret;
 }
 
 /*
@@ -4790,7 +4799,7 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
 
 	buf->f_type = EXT4_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
-	buf->f_blocks = ext4_blocks_count(es) - EXT4_C2B(sbi, sbi->s_overhead);
+	buf->f_blocks = ext4_blocks_count(es) - EXT4_C2B(sbi, overhead);
 	bfree = percpu_counter_sum_positive(&sbi->s_freeclusters_counter) -
 		percpu_counter_sum_positive(&sbi->s_dirtyclusters_counter);
 	/* prevent underflow in case that few free space is available */
@@ -5289,9 +5298,14 @@ static int __init ext4_init_fs(void)
 		init_waitqueue_head(&ext4__ioend_wq[i]);
 	}
 
-	err = ext4_init_pageio();
+	err = ext4_init_es();
 	if (err)
 		return err;
+
+	err = ext4_init_pageio();
+	if (err)
+		goto out7;
+
 	err = ext4_init_system_zone();
 	if (err)
 		goto out6;
@@ -5341,6 +5355,9 @@ out5:
 	ext4_exit_system_zone();
 out6:
 	ext4_exit_pageio();
+out7:
+	ext4_exit_es();
+
 	return err;
 }
 
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 2cdb98d..b1adda1 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -794,7 +794,6 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
 			int offset = (char *)s->here - bs->bh->b_data;
 
 			unlock_buffer(bs->bh);
-			ext4_handle_release_buffer(handle, bs->bh);
 			if (ce) {
 				mb_cache_entry_release(ce);
 				ce = NULL;
diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
new file mode 100644
index 0000000..37a6b8e
--- /dev/null
+++ b/fs/f2fs/Kconfig
@@ -0,0 +1,52 @@
+config F2FS_FS
+	tristate "F2FS filesystem support (EXPERIMENTAL)"
+	help
+	  F2FS is based on Log-structured File System (LFS), which supports
+	  versatile "flash-friendly" features. The design has been focused on
+	  addressing the fundamental issues in LFS, which are snowball effect
+	  of wandering tree and high cleaning overhead.
+
+	  Since flash-based storages show different characteristics according to
+	  the internal geometry or flash memory management schemes aka FTL, F2FS
+	  and tools support various parameters not only for configuring on-disk
+	  layout, but also for selecting allocation and cleaning algorithms.
+
+	  If unsure, say N.
+
+config F2FS_STAT_FS
+	bool "F2FS Status Information"
+	depends on F2FS_FS && DEBUG_FS
+	default y
+	help
+	  /sys/kernel/debug/f2fs/ contains information about all the partitions
+	  mounted as f2fs. Each file shows the whole f2fs information.
+
+	  /sys/kernel/debug/f2fs/status includes:
+	    - major file system information managed by f2fs currently
+	    - average SIT information about whole segments
+	    - current memory footprint consumed by f2fs.
+
+config F2FS_FS_XATTR
+	bool "F2FS extended attributes"
+	depends on F2FS_FS
+	default y
+	help
+	  Extended attributes are name:value pairs associated with inodes by
+	  the kernel or by users (see the attr(5) manual page, or visit
+	  <http://acl.bestbits.at/> for details).
+
+	  If unsure, say N.
+
+config F2FS_FS_POSIX_ACL
+	bool "F2FS Access Control Lists"
+	depends on F2FS_FS_XATTR
+	select FS_POSIX_ACL
+	default y
+	help
+	  Posix Access Control Lists (ACLs) support permissions for users and
+	  gourps beyond the owner/group/world scheme.
+
+	  To learn more about Access Control Lists, visit the POSIX ACLs for
+	  Linux website <http://acl.bestbits.at/>.
+
+	  If you don't know what Access Control Lists are, say N
diff --git a/fs/f2fs/Makefile b/fs/f2fs/Makefile
new file mode 100644
index 0000000..27a0820
--- /dev/null
+++ b/fs/f2fs/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_F2FS_FS) += f2fs.o
+
+f2fs-y		:= dir.o file.o inode.o namei.o hash.o super.o
+f2fs-y		+= checkpoint.o gc.o data.o node.o segment.o recovery.o
+f2fs-$(CONFIG_F2FS_STAT_FS) += debug.o
+f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o
+f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
new file mode 100644
index 0000000..dff2a2b
--- /dev/null
+++ b/fs/f2fs/acl.c
@@ -0,0 +1,465 @@
+/**
+ * fs/f2fs/acl.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Portions of this code from linux/fs/ext2/acl.c
+ *
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.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/f2fs_fs.h>
+#include "f2fs.h"
+#include "xattr.h"
+#include "acl.h"
+
+#define get_inode_mode(i)	((is_inode_flag_set(F2FS_I(i), FI_ACL_MODE)) ? \
+					(F2FS_I(i)->i_acl_mode) : ((i)->i_mode))
+
+static inline size_t f2fs_acl_size(int count)
+{
+	if (count <= 4) {
+		return sizeof(struct f2fs_acl_header) +
+			count * sizeof(struct f2fs_acl_entry_short);
+	} else {
+		return sizeof(struct f2fs_acl_header) +
+			4 * sizeof(struct f2fs_acl_entry_short) +
+			(count - 4) * sizeof(struct f2fs_acl_entry);
+	}
+}
+
+static inline int f2fs_acl_count(size_t size)
+{
+	ssize_t s;
+	size -= sizeof(struct f2fs_acl_header);
+	s = size - 4 * sizeof(struct f2fs_acl_entry_short);
+	if (s < 0) {
+		if (size % sizeof(struct f2fs_acl_entry_short))
+			return -1;
+		return size / sizeof(struct f2fs_acl_entry_short);
+	} else {
+		if (s % sizeof(struct f2fs_acl_entry))
+			return -1;
+		return s / sizeof(struct f2fs_acl_entry) + 4;
+	}
+}
+
+static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size)
+{
+	int i, count;
+	struct posix_acl *acl;
+	struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value;
+	struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1);
+	const char *end = value + size;
+
+	if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION))
+		return ERR_PTR(-EINVAL);
+
+	count = f2fs_acl_count(size);
+	if (count < 0)
+		return ERR_PTR(-EINVAL);
+	if (count == 0)
+		return NULL;
+
+	acl = posix_acl_alloc(count, GFP_KERNEL);
+	if (!acl)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < count; i++) {
+
+		if ((char *)entry > end)
+			goto fail;
+
+		acl->a_entries[i].e_tag  = le16_to_cpu(entry->e_tag);
+		acl->a_entries[i].e_perm = le16_to_cpu(entry->e_perm);
+
+		switch (acl->a_entries[i].e_tag) {
+		case ACL_USER_OBJ:
+		case ACL_GROUP_OBJ:
+		case ACL_MASK:
+		case ACL_OTHER:
+			acl->a_entries[i].e_id = ACL_UNDEFINED_ID;
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry_short));
+			break;
+
+		case ACL_USER:
+			acl->a_entries[i].e_uid =
+				make_kuid(&init_user_ns,
+						le32_to_cpu(entry->e_id));
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry));
+			break;
+		case ACL_GROUP:
+			acl->a_entries[i].e_gid =
+				make_kgid(&init_user_ns,
+						le32_to_cpu(entry->e_id));
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry));
+			break;
+		default:
+			goto fail;
+		}
+	}
+	if ((char *)entry != end)
+		goto fail;
+	return acl;
+fail:
+	posix_acl_release(acl);
+	return ERR_PTR(-EINVAL);
+}
+
+static void *f2fs_acl_to_disk(const struct posix_acl *acl, size_t *size)
+{
+	struct f2fs_acl_header *f2fs_acl;
+	struct f2fs_acl_entry *entry;
+	int i;
+
+	f2fs_acl = kmalloc(sizeof(struct f2fs_acl_header) + acl->a_count *
+			sizeof(struct f2fs_acl_entry), GFP_KERNEL);
+	if (!f2fs_acl)
+		return ERR_PTR(-ENOMEM);
+
+	f2fs_acl->a_version = cpu_to_le32(F2FS_ACL_VERSION);
+	entry = (struct f2fs_acl_entry *)(f2fs_acl + 1);
+
+	for (i = 0; i < acl->a_count; i++) {
+
+		entry->e_tag  = cpu_to_le16(acl->a_entries[i].e_tag);
+		entry->e_perm = cpu_to_le16(acl->a_entries[i].e_perm);
+
+		switch (acl->a_entries[i].e_tag) {
+		case ACL_USER:
+			entry->e_id = cpu_to_le32(
+					from_kuid(&init_user_ns,
+						acl->a_entries[i].e_uid));
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry));
+			break;
+		case ACL_GROUP:
+			entry->e_id = cpu_to_le32(
+					from_kgid(&init_user_ns,
+						acl->a_entries[i].e_gid));
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry));
+			break;
+		case ACL_USER_OBJ:
+		case ACL_GROUP_OBJ:
+		case ACL_MASK:
+		case ACL_OTHER:
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry_short));
+			break;
+		default:
+			goto fail;
+		}
+	}
+	*size = f2fs_acl_size(acl->a_count);
+	return (void *)f2fs_acl;
+
+fail:
+	kfree(f2fs_acl);
+	return ERR_PTR(-EINVAL);
+}
+
+struct posix_acl *f2fs_get_acl(struct inode *inode, int type)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	int name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT;
+	void *value = NULL;
+	struct posix_acl *acl;
+	int retval;
+
+	if (!test_opt(sbi, POSIX_ACL))
+		return NULL;
+
+	acl = get_cached_acl(inode, type);
+	if (acl != ACL_NOT_CACHED)
+		return acl;
+
+	if (type == ACL_TYPE_ACCESS)
+		name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
+
+	retval = f2fs_getxattr(inode, name_index, "", NULL, 0);
+	if (retval > 0) {
+		value = kmalloc(retval, GFP_KERNEL);
+		if (!value)
+			return ERR_PTR(-ENOMEM);
+		retval = f2fs_getxattr(inode, name_index, "", value, retval);
+	}
+
+	if (retval < 0) {
+		if (retval == -ENODATA)
+			acl = NULL;
+		else
+			acl = ERR_PTR(retval);
+	} else {
+		acl = f2fs_acl_from_disk(value, retval);
+	}
+	kfree(value);
+	if (!IS_ERR(acl))
+		set_cached_acl(inode, type, acl);
+
+	return acl;
+}
+
+static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct f2fs_inode_info *fi = F2FS_I(inode);
+	int name_index;
+	void *value = NULL;
+	size_t size = 0;
+	int error;
+
+	if (!test_opt(sbi, POSIX_ACL))
+		return 0;
+	if (S_ISLNK(inode->i_mode))
+		return -EOPNOTSUPP;
+
+	switch (type) {
+	case ACL_TYPE_ACCESS:
+		name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
+		if (acl) {
+			error = posix_acl_equiv_mode(acl, &inode->i_mode);
+			if (error < 0)
+				return error;
+			set_acl_inode(fi, inode->i_mode);
+			if (error == 0)
+				acl = NULL;
+		}
+		break;
+
+	case ACL_TYPE_DEFAULT:
+		name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT;
+		if (!S_ISDIR(inode->i_mode))
+			return acl ? -EACCES : 0;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (acl) {
+		value = f2fs_acl_to_disk(acl, &size);
+		if (IS_ERR(value)) {
+			cond_clear_inode_flag(fi, FI_ACL_MODE);
+			return (int)PTR_ERR(value);
+		}
+	}
+
+	error = f2fs_setxattr(inode, name_index, "", value, size);
+
+	kfree(value);
+	if (!error)
+		set_cached_acl(inode, type, acl);
+
+	cond_clear_inode_flag(fi, FI_ACL_MODE);
+	return error;
+}
+
+int f2fs_init_acl(struct inode *inode, struct inode *dir)
+{
+	struct posix_acl *acl = NULL;
+	struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
+	int error = 0;
+
+	if (!S_ISLNK(inode->i_mode)) {
+		if (test_opt(sbi, POSIX_ACL)) {
+			acl = f2fs_get_acl(dir, ACL_TYPE_DEFAULT);
+			if (IS_ERR(acl))
+				return PTR_ERR(acl);
+		}
+		if (!acl)
+			inode->i_mode &= ~current_umask();
+	}
+
+	if (test_opt(sbi, POSIX_ACL) && acl) {
+
+		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);
+	}
+cleanup:
+	posix_acl_release(acl);
+	return error;
+}
+
+int f2fs_acl_chmod(struct inode *inode)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct posix_acl *acl;
+	int error;
+	mode_t mode = get_inode_mode(inode);
+
+	if (!test_opt(sbi, POSIX_ACL))
+		return 0;
+	if (S_ISLNK(mode))
+		return -EOPNOTSUPP;
+
+	acl = f2fs_get_acl(inode, ACL_TYPE_ACCESS);
+	if (IS_ERR(acl) || !acl)
+		return PTR_ERR(acl);
+
+	error = posix_acl_chmod(&acl, GFP_KERNEL, mode);
+	if (error)
+		return error;
+	error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl);
+	posix_acl_release(acl);
+	return error;
+}
+
+static size_t f2fs_xattr_list_acl(struct dentry *dentry, char *list,
+		size_t list_size, const char *name, size_t name_len, int type)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+	const char *xname = POSIX_ACL_XATTR_DEFAULT;
+	size_t size;
+
+	if (!test_opt(sbi, POSIX_ACL))
+		return 0;
+
+	if (type == ACL_TYPE_ACCESS)
+		xname = POSIX_ACL_XATTR_ACCESS;
+
+	size = strlen(xname) + 1;
+	if (list && size <= list_size)
+		memcpy(list, xname, size);
+	return size;
+}
+
+static int f2fs_xattr_get_acl(struct dentry *dentry, const char *name,
+		void *buffer, size_t size, int type)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+	struct posix_acl *acl;
+	int error;
+
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	if (!test_opt(sbi, POSIX_ACL))
+		return -EOPNOTSUPP;
+
+	acl = f2fs_get_acl(dentry->d_inode, type);
+	if (IS_ERR(acl))
+		return PTR_ERR(acl);
+	if (!acl)
+		return -ENODATA;
+	error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
+	posix_acl_release(acl);
+
+	return error;
+}
+
+static int f2fs_xattr_set_acl(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+	struct inode *inode = dentry->d_inode;
+	struct posix_acl *acl = NULL;
+	int error;
+
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	if (!test_opt(sbi, POSIX_ACL))
+		return -EOPNOTSUPP;
+	if (!inode_owner_or_capable(inode))
+		return -EPERM;
+
+	if (value) {
+		acl = posix_acl_from_xattr(&init_user_ns, value, size);
+		if (IS_ERR(acl))
+			return PTR_ERR(acl);
+		if (acl) {
+			error = posix_acl_valid(acl);
+			if (error)
+				goto release_and_out;
+		}
+	} else {
+		acl = NULL;
+	}
+
+	error = f2fs_set_acl(inode, type, acl);
+
+release_and_out:
+	posix_acl_release(acl);
+	return error;
+}
+
+const struct xattr_handler f2fs_xattr_acl_default_handler = {
+	.prefix = POSIX_ACL_XATTR_DEFAULT,
+	.flags = ACL_TYPE_DEFAULT,
+	.list = f2fs_xattr_list_acl,
+	.get = f2fs_xattr_get_acl,
+	.set = f2fs_xattr_set_acl,
+};
+
+const struct xattr_handler f2fs_xattr_acl_access_handler = {
+	.prefix = POSIX_ACL_XATTR_ACCESS,
+	.flags = ACL_TYPE_ACCESS,
+	.list = f2fs_xattr_list_acl,
+	.get = f2fs_xattr_get_acl,
+	.set = f2fs_xattr_set_acl,
+};
+
+static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
+		size_t list_size, const char *name, size_t name_len, int type)
+{
+	const char *xname = F2FS_SYSTEM_ADVISE_PREFIX;
+	size_t size;
+
+	if (type != F2FS_XATTR_INDEX_ADVISE)
+		return 0;
+
+	size = strlen(xname) + 1;
+	if (list && size <= list_size)
+		memcpy(list, xname, size);
+	return size;
+}
+
+static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
+		void *buffer, size_t size, int type)
+{
+	struct inode *inode = dentry->d_inode;
+
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+
+	*((char *)buffer) = F2FS_I(inode)->i_advise;
+	return sizeof(char);
+}
+
+static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
+{
+	struct inode *inode = dentry->d_inode;
+
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	if (!inode_owner_or_capable(inode))
+		return -EPERM;
+	if (value == NULL)
+		return -EINVAL;
+
+	F2FS_I(inode)->i_advise |= *(char *)value;
+	return 0;
+}
+
+const struct xattr_handler f2fs_xattr_advise_handler = {
+	.prefix = F2FS_SYSTEM_ADVISE_PREFIX,
+	.flags	= F2FS_XATTR_INDEX_ADVISE,
+	.list   = f2fs_xattr_advise_list,
+	.get    = f2fs_xattr_advise_get,
+	.set    = f2fs_xattr_advise_set,
+};
diff --git a/fs/f2fs/acl.h b/fs/f2fs/acl.h
new file mode 100644
index 0000000..c97675e
--- /dev/null
+++ b/fs/f2fs/acl.h
@@ -0,0 +1,57 @@
+/**
+ * fs/f2fs/acl.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Portions of this code from linux/fs/ext2/acl.h
+ *
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __F2FS_ACL_H__
+#define __F2FS_ACL_H__
+
+#include <linux/posix_acl_xattr.h>
+
+#define F2FS_ACL_VERSION	0x0001
+
+struct f2fs_acl_entry {
+	__le16 e_tag;
+	__le16 e_perm;
+	__le32 e_id;
+};
+
+struct f2fs_acl_entry_short {
+	__le16 e_tag;
+	__le16 e_perm;
+};
+
+struct f2fs_acl_header {
+	__le32 a_version;
+};
+
+#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);
+#else
+#define f2fs_check_acl	NULL
+#define f2fs_get_acl	NULL
+#define f2fs_set_acl	NULL
+
+static inline int f2fs_acl_chmod(struct inode *inode)
+{
+	return 0;
+}
+
+static inline int f2fs_init_acl(struct inode *inode, struct inode *dir)
+{
+	return 0;
+}
+#endif
+#endif /* __F2FS_ACL_H__ */
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
new file mode 100644
index 0000000..ab743f9
--- /dev/null
+++ b/fs/f2fs/checkpoint.c
@@ -0,0 +1,792 @@
+/**
+ * fs/f2fs/checkpoint.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/fs.h>
+#include <linux/bio.h>
+#include <linux/mpage.h>
+#include <linux/writeback.h>
+#include <linux/blkdev.h>
+#include <linux/f2fs_fs.h>
+#include <linux/pagevec.h>
+#include <linux/swap.h>
+
+#include "f2fs.h"
+#include "node.h"
+#include "segment.h"
+
+static struct kmem_cache *orphan_entry_slab;
+static struct kmem_cache *inode_entry_slab;
+
+/**
+ * We guarantee no failure on the returned page.
+ */
+struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
+{
+	struct address_space *mapping = sbi->meta_inode->i_mapping;
+	struct page *page = NULL;
+repeat:
+	page = grab_cache_page(mapping, index);
+	if (!page) {
+		cond_resched();
+		goto repeat;
+	}
+
+	/* We wait writeback only inside grab_meta_page() */
+	wait_on_page_writeback(page);
+	SetPageUptodate(page);
+	return page;
+}
+
+/**
+ * We guarantee no failure on the returned page.
+ */
+struct page *get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
+{
+	struct address_space *mapping = sbi->meta_inode->i_mapping;
+	struct page *page;
+repeat:
+	page = grab_cache_page(mapping, index);
+	if (!page) {
+		cond_resched();
+		goto repeat;
+	}
+	if (f2fs_readpage(sbi, page, index, READ_SYNC)) {
+		f2fs_put_page(page, 1);
+		goto repeat;
+	}
+	mark_page_accessed(page);
+
+	/* We do not allow returning an errorneous page */
+	return page;
+}
+
+static int f2fs_write_meta_page(struct page *page,
+				struct writeback_control *wbc)
+{
+	struct inode *inode = page->mapping->host;
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	int err;
+
+	wait_on_page_writeback(page);
+
+	err = write_meta_page(sbi, page, wbc);
+	if (err) {
+		wbc->pages_skipped++;
+		set_page_dirty(page);
+	}
+
+	dec_page_count(sbi, F2FS_DIRTY_META);
+
+	/* In this case, we should not unlock this page */
+	if (err != AOP_WRITEPAGE_ACTIVATE)
+		unlock_page(page);
+	return err;
+}
+
+static int f2fs_write_meta_pages(struct address_space *mapping,
+				struct writeback_control *wbc)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
+	struct block_device *bdev = sbi->sb->s_bdev;
+	long written;
+
+	if (wbc->for_kupdate)
+		return 0;
+
+	if (get_pages(sbi, F2FS_DIRTY_META) == 0)
+		return 0;
+
+	/* if mounting is failed, skip writing node pages */
+	mutex_lock(&sbi->cp_mutex);
+	written = sync_meta_pages(sbi, META, bio_get_nr_vecs(bdev));
+	mutex_unlock(&sbi->cp_mutex);
+	wbc->nr_to_write -= written;
+	return 0;
+}
+
+long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
+						long nr_to_write)
+{
+	struct address_space *mapping = sbi->meta_inode->i_mapping;
+	pgoff_t index = 0, end = LONG_MAX;
+	struct pagevec pvec;
+	long nwritten = 0;
+	struct writeback_control wbc = {
+		.for_reclaim = 0,
+	};
+
+	pagevec_init(&pvec, 0);
+
+	while (index <= end) {
+		int i, nr_pages;
+		nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
+				PAGECACHE_TAG_DIRTY,
+				min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
+		if (nr_pages == 0)
+			break;
+
+		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));
+			clear_page_dirty_for_io(page);
+			f2fs_write_meta_page(page, &wbc);
+			if (nwritten++ >= nr_to_write)
+				break;
+		}
+		pagevec_release(&pvec);
+		cond_resched();
+	}
+
+	if (nwritten)
+		f2fs_submit_bio(sbi, type, nr_to_write == LONG_MAX);
+
+	return nwritten;
+}
+
+static int f2fs_set_meta_page_dirty(struct page *page)
+{
+	struct address_space *mapping = page->mapping;
+	struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
+
+	SetPageUptodate(page);
+	if (!PageDirty(page)) {
+		__set_page_dirty_nobuffers(page);
+		inc_page_count(sbi, F2FS_DIRTY_META);
+		F2FS_SET_SB_DIRT(sbi);
+		return 1;
+	}
+	return 0;
+}
+
+const struct address_space_operations f2fs_meta_aops = {
+	.writepage	= f2fs_write_meta_page,
+	.writepages	= f2fs_write_meta_pages,
+	.set_page_dirty	= f2fs_set_meta_page_dirty,
+};
+
+int check_orphan_space(struct f2fs_sb_info *sbi)
+{
+	unsigned int max_orphans;
+	int err = 0;
+
+	/*
+	 * considering 512 blocks in a segment 5 blocks are needed for cp
+	 * and log segment summaries. Remaining blocks are used to keep
+	 * orphan entries with the limitation one reserved segment
+	 * for cp pack we can have max 1020*507 orphan entries
+	 */
+	max_orphans = (sbi->blocks_per_seg - 5) * F2FS_ORPHANS_PER_BLOCK;
+	mutex_lock(&sbi->orphan_inode_mutex);
+	if (sbi->n_orphans >= max_orphans)
+		err = -ENOSPC;
+	mutex_unlock(&sbi->orphan_inode_mutex);
+	return err;
+}
+
+void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
+{
+	struct list_head *head, *this;
+	struct orphan_inode_entry *new = NULL, *orphan = NULL;
+
+	mutex_lock(&sbi->orphan_inode_mutex);
+	head = &sbi->orphan_inode_list;
+	list_for_each(this, head) {
+		orphan = list_entry(this, struct orphan_inode_entry, list);
+		if (orphan->ino == ino)
+			goto out;
+		if (orphan->ino > ino)
+			break;
+		orphan = NULL;
+	}
+retry:
+	new = kmem_cache_alloc(orphan_entry_slab, GFP_ATOMIC);
+	if (!new) {
+		cond_resched();
+		goto retry;
+	}
+	new->ino = ino;
+	INIT_LIST_HEAD(&new->list);
+
+	/* add new_oentry into list which is sorted by inode number */
+	if (orphan) {
+		struct orphan_inode_entry *prev;
+
+		/* get previous entry */
+		prev = list_entry(orphan->list.prev, typeof(*prev), list);
+		if (&prev->list != head)
+			/* insert new orphan inode entry */
+			list_add(&new->list, &prev->list);
+		else
+			list_add(&new->list, head);
+	} else {
+		list_add_tail(&new->list, head);
+	}
+	sbi->n_orphans++;
+out:
+	mutex_unlock(&sbi->orphan_inode_mutex);
+}
+
+void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
+{
+	struct list_head *this, *next, *head;
+	struct orphan_inode_entry *orphan;
+
+	mutex_lock(&sbi->orphan_inode_mutex);
+	head = &sbi->orphan_inode_list;
+	list_for_each_safe(this, next, head) {
+		orphan = list_entry(this, struct orphan_inode_entry, list);
+		if (orphan->ino == ino) {
+			list_del(&orphan->list);
+			kmem_cache_free(orphan_entry_slab, orphan);
+			sbi->n_orphans--;
+			break;
+		}
+	}
+	mutex_unlock(&sbi->orphan_inode_mutex);
+}
+
+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));
+	clear_nlink(inode);
+
+	/* truncate all the data during iput */
+	iput(inode);
+}
+
+int recover_orphan_inodes(struct f2fs_sb_info *sbi)
+{
+	block_t start_blk, orphan_blkaddr, i, j;
+
+	if (!(F2FS_CKPT(sbi)->ckpt_flags & CP_ORPHAN_PRESENT_FLAG))
+		return 0;
+
+	sbi->por_doing = 1;
+	start_blk = __start_cp_addr(sbi) + 1;
+	orphan_blkaddr = __start_sum_addr(sbi) - 1;
+
+	for (i = 0; i < orphan_blkaddr; i++) {
+		struct page *page = get_meta_page(sbi, start_blk + i);
+		struct f2fs_orphan_block *orphan_blk;
+
+		orphan_blk = (struct f2fs_orphan_block *)page_address(page);
+		for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) {
+			nid_t ino = le32_to_cpu(orphan_blk->ino[j]);
+			recover_orphan_inode(sbi, ino);
+		}
+		f2fs_put_page(page, 1);
+	}
+	/* clear Orphan Flag */
+	F2FS_CKPT(sbi)->ckpt_flags &= (~CP_ORPHAN_PRESENT_FLAG);
+	sbi->por_doing = 0;
+	return 0;
+}
+
+static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
+{
+	struct list_head *head, *this, *next;
+	struct f2fs_orphan_block *orphan_blk = NULL;
+	struct page *page = NULL;
+	unsigned int nentries = 0;
+	unsigned short index = 1;
+	unsigned short orphan_blocks;
+
+	orphan_blocks = (unsigned short)((sbi->n_orphans +
+		(F2FS_ORPHANS_PER_BLOCK - 1)) / F2FS_ORPHANS_PER_BLOCK);
+
+	mutex_lock(&sbi->orphan_inode_mutex);
+	head = &sbi->orphan_inode_list;
+
+	/* loop for each orphan inode entry and write them in Jornal block */
+	list_for_each_safe(this, next, head) {
+		struct orphan_inode_entry *orphan;
+
+		orphan = list_entry(this, struct orphan_inode_entry, list);
+
+		if (nentries == F2FS_ORPHANS_PER_BLOCK) {
+			/*
+			 * an orphan block is full of 1020 entries,
+			 * then we need to flush current orphan blocks
+			 * and bring another one in memory
+			 */
+			orphan_blk->blk_addr = cpu_to_le16(index);
+			orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
+			orphan_blk->entry_count = cpu_to_le32(nentries);
+			set_page_dirty(page);
+			f2fs_put_page(page, 1);
+			index++;
+			start_blk++;
+			nentries = 0;
+			page = NULL;
+		}
+		if (page)
+			goto page_exist;
+
+		page = grab_meta_page(sbi, start_blk);
+		orphan_blk = (struct f2fs_orphan_block *)page_address(page);
+		memset(orphan_blk, 0, sizeof(*orphan_blk));
+page_exist:
+		orphan_blk->ino[nentries++] = cpu_to_le32(orphan->ino);
+	}
+	if (!page)
+		goto end;
+
+	orphan_blk->blk_addr = cpu_to_le16(index);
+	orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
+	orphan_blk->entry_count = cpu_to_le32(nentries);
+	set_page_dirty(page);
+	f2fs_put_page(page, 1);
+end:
+	mutex_unlock(&sbi->orphan_inode_mutex);
+}
+
+static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
+				block_t cp_addr, unsigned long long *version)
+{
+	struct page *cp_page_1, *cp_page_2 = NULL;
+	unsigned long blk_size = sbi->blocksize;
+	struct f2fs_checkpoint *cp_block;
+	unsigned long long cur_version = 0, pre_version = 0;
+	unsigned int crc = 0;
+	size_t crc_offset;
+
+	/* Read the 1st cp block in this CP pack */
+	cp_page_1 = get_meta_page(sbi, cp_addr);
+
+	/* get the version number */
+	cp_block = (struct f2fs_checkpoint *)page_address(cp_page_1);
+	crc_offset = le32_to_cpu(cp_block->checksum_offset);
+	if (crc_offset >= blk_size)
+		goto invalid_cp1;
+
+	crc = *(unsigned int *)((unsigned char *)cp_block + crc_offset);
+	if (!f2fs_crc_valid(crc, cp_block, crc_offset))
+		goto invalid_cp1;
+
+	pre_version = le64_to_cpu(cp_block->checkpoint_ver);
+
+	/* Read the 2nd cp block in this CP pack */
+	cp_addr += le64_to_cpu(cp_block->cp_pack_total_block_count) - 1;
+	cp_page_2 = get_meta_page(sbi, cp_addr);
+
+	cp_block = (struct f2fs_checkpoint *)page_address(cp_page_2);
+	crc_offset = le32_to_cpu(cp_block->checksum_offset);
+	if (crc_offset >= blk_size)
+		goto invalid_cp2;
+
+	crc = *(unsigned int *)((unsigned char *)cp_block + crc_offset);
+	if (!f2fs_crc_valid(crc, cp_block, crc_offset))
+		goto invalid_cp2;
+
+	cur_version = le64_to_cpu(cp_block->checkpoint_ver);
+
+	if (cur_version == pre_version) {
+		*version = cur_version;
+		f2fs_put_page(cp_page_2, 1);
+		return cp_page_1;
+	}
+invalid_cp2:
+	f2fs_put_page(cp_page_2, 1);
+invalid_cp1:
+	f2fs_put_page(cp_page_1, 1);
+	return NULL;
+}
+
+int get_valid_checkpoint(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_checkpoint *cp_block;
+	struct f2fs_super_block *fsb = sbi->raw_super;
+	struct page *cp1, *cp2, *cur_page;
+	unsigned long blk_size = sbi->blocksize;
+	unsigned long long cp1_version = 0, cp2_version = 0;
+	unsigned long long cp_start_blk_no;
+
+	sbi->ckpt = kzalloc(blk_size, GFP_KERNEL);
+	if (!sbi->ckpt)
+		return -ENOMEM;
+	/*
+	 * Finding out valid cp block involves read both
+	 * sets( cp pack1 and cp pack 2)
+	 */
+	cp_start_blk_no = le32_to_cpu(fsb->cp_blkaddr);
+	cp1 = validate_checkpoint(sbi, cp_start_blk_no, &cp1_version);
+
+	/* The second checkpoint pack should start at the next segment */
+	cp_start_blk_no += 1 << le32_to_cpu(fsb->log_blocks_per_seg);
+	cp2 = validate_checkpoint(sbi, cp_start_blk_no, &cp2_version);
+
+	if (cp1 && cp2) {
+		if (ver_after(cp2_version, cp1_version))
+			cur_page = cp2;
+		else
+			cur_page = cp1;
+	} else if (cp1) {
+		cur_page = cp1;
+	} else if (cp2) {
+		cur_page = cp2;
+	} else {
+		goto fail_no_cp;
+	}
+
+	cp_block = (struct f2fs_checkpoint *)page_address(cur_page);
+	memcpy(sbi->ckpt, cp_block, blk_size);
+
+	f2fs_put_page(cp1, 1);
+	f2fs_put_page(cp2, 1);
+	return 0;
+
+fail_no_cp:
+	kfree(sbi->ckpt);
+	return -EINVAL;
+}
+
+void set_dirty_dir_page(struct inode *inode, struct page *page)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct list_head *head = &sbi->dir_inode_list;
+	struct dir_inode_entry *new;
+	struct list_head *this;
+
+	if (!S_ISDIR(inode->i_mode))
+		return;
+retry:
+	new = kmem_cache_alloc(inode_entry_slab, GFP_NOFS);
+	if (!new) {
+		cond_resched();
+		goto retry;
+	}
+	new->inode = inode;
+	INIT_LIST_HEAD(&new->list);
+
+	spin_lock(&sbi->dir_inode_lock);
+	list_for_each(this, head) {
+		struct dir_inode_entry *entry;
+		entry = list_entry(this, struct dir_inode_entry, list);
+		if (entry->inode == inode) {
+			kmem_cache_free(inode_entry_slab, new);
+			goto out;
+		}
+	}
+	list_add_tail(&new->list, head);
+	sbi->n_dirty_dirs++;
+
+	BUG_ON(!S_ISDIR(inode->i_mode));
+out:
+	inc_page_count(sbi, F2FS_DIRTY_DENTS);
+	inode_inc_dirty_dents(inode);
+	SetPagePrivate(page);
+
+	spin_unlock(&sbi->dir_inode_lock);
+}
+
+void remove_dirty_dir_inode(struct inode *inode)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct list_head *head = &sbi->dir_inode_list;
+	struct list_head *this;
+
+	if (!S_ISDIR(inode->i_mode))
+		return;
+
+	spin_lock(&sbi->dir_inode_lock);
+	if (atomic_read(&F2FS_I(inode)->dirty_dents))
+		goto out;
+
+	list_for_each(this, head) {
+		struct dir_inode_entry *entry;
+		entry = list_entry(this, struct dir_inode_entry, list);
+		if (entry->inode == inode) {
+			list_del(&entry->list);
+			kmem_cache_free(inode_entry_slab, entry);
+			sbi->n_dirty_dirs--;
+			break;
+		}
+	}
+out:
+	spin_unlock(&sbi->dir_inode_lock);
+}
+
+void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi)
+{
+	struct list_head *head = &sbi->dir_inode_list;
+	struct dir_inode_entry *entry;
+	struct inode *inode;
+retry:
+	spin_lock(&sbi->dir_inode_lock);
+	if (list_empty(head)) {
+		spin_unlock(&sbi->dir_inode_lock);
+		return;
+	}
+	entry = list_entry(head->next, struct dir_inode_entry, list);
+	inode = igrab(entry->inode);
+	spin_unlock(&sbi->dir_inode_lock);
+	if (inode) {
+		filemap_flush(inode->i_mapping);
+		iput(inode);
+	} else {
+		/*
+		 * We should submit bio, since it exists several
+		 * wribacking dentry pages in the freeing inode.
+		 */
+		f2fs_submit_bio(sbi, DATA, true);
+	}
+	goto retry;
+}
+
+/**
+ * Freeze all the FS-operations for checkpoint.
+ */
+void block_operations(struct f2fs_sb_info *sbi)
+{
+	int t;
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_ALL,
+		.nr_to_write = LONG_MAX,
+		.for_reclaim = 0,
+	};
+
+	/* Stop renaming operation */
+	mutex_lock_op(sbi, RENAME);
+	mutex_lock_op(sbi, DENTRY_OPS);
+
+retry_dents:
+	/* write all the dirty dentry pages */
+	sync_dirty_dir_inodes(sbi);
+
+	mutex_lock_op(sbi, DATA_WRITE);
+	if (get_pages(sbi, F2FS_DIRTY_DENTS)) {
+		mutex_unlock_op(sbi, DATA_WRITE);
+		goto retry_dents;
+	}
+
+	/* block all the operations */
+	for (t = DATA_NEW; t <= NODE_TRUNC; t++)
+		mutex_lock_op(sbi, t);
+
+	mutex_lock(&sbi->write_inode);
+
+	/*
+	 * POR: we should ensure that there is no dirty node pages
+	 * until finishing nat/sit flush.
+	 */
+retry:
+	sync_node_pages(sbi, 0, &wbc);
+
+	mutex_lock_op(sbi, NODE_WRITE);
+
+	if (get_pages(sbi, F2FS_DIRTY_NODES)) {
+		mutex_unlock_op(sbi, NODE_WRITE);
+		goto retry;
+	}
+	mutex_unlock(&sbi->write_inode);
+}
+
+static void unblock_operations(struct f2fs_sb_info *sbi)
+{
+	int t;
+	for (t = NODE_WRITE; t >= RENAME; t--)
+		mutex_unlock_op(sbi, t);
+}
+
+static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
+{
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	nid_t last_nid = 0;
+	block_t start_blk;
+	struct page *cp_page;
+	unsigned int data_sum_blocks, orphan_blocks;
+	void *kaddr;
+	__u32 crc32 = 0;
+	int i;
+
+	/* Flush all the NAT/SIT pages */
+	while (get_pages(sbi, F2FS_DIRTY_META))
+		sync_meta_pages(sbi, META, LONG_MAX);
+
+	next_free_nid(sbi, &last_nid);
+
+	/*
+	 * modify checkpoint
+	 * version number is already updated
+	 */
+	ckpt->elapsed_time = cpu_to_le64(get_mtime(sbi));
+	ckpt->valid_block_count = cpu_to_le64(valid_user_blocks(sbi));
+	ckpt->free_segment_count = cpu_to_le32(free_segments(sbi));
+	for (i = 0; i < 3; i++) {
+		ckpt->cur_node_segno[i] =
+			cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_NODE));
+		ckpt->cur_node_blkoff[i] =
+			cpu_to_le16(curseg_blkoff(sbi, i + CURSEG_HOT_NODE));
+		ckpt->alloc_type[i + CURSEG_HOT_NODE] =
+				curseg_alloc_type(sbi, i + CURSEG_HOT_NODE);
+	}
+	for (i = 0; i < 3; i++) {
+		ckpt->cur_data_segno[i] =
+			cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_DATA));
+		ckpt->cur_data_blkoff[i] =
+			cpu_to_le16(curseg_blkoff(sbi, i + CURSEG_HOT_DATA));
+		ckpt->alloc_type[i + CURSEG_HOT_DATA] =
+				curseg_alloc_type(sbi, i + CURSEG_HOT_DATA);
+	}
+
+	ckpt->valid_node_count = cpu_to_le32(valid_node_count(sbi));
+	ckpt->valid_inode_count = cpu_to_le32(valid_inode_count(sbi));
+	ckpt->next_free_nid = cpu_to_le32(last_nid);
+
+	/* 2 cp  + n data seg summary + orphan inode blocks */
+	data_sum_blocks = npages_for_summary_flush(sbi);
+	if (data_sum_blocks < 3)
+		ckpt->ckpt_flags |= CP_COMPACT_SUM_FLAG;
+	else
+		ckpt->ckpt_flags &= (~CP_COMPACT_SUM_FLAG);
+
+	orphan_blocks = (sbi->n_orphans + F2FS_ORPHANS_PER_BLOCK - 1)
+					/ F2FS_ORPHANS_PER_BLOCK;
+	ckpt->cp_pack_start_sum = 1 + orphan_blocks;
+	ckpt->cp_pack_total_block_count = 2 + data_sum_blocks + orphan_blocks;
+
+	if (is_umount) {
+		ckpt->ckpt_flags |= CP_UMOUNT_FLAG;
+		ckpt->cp_pack_total_block_count += NR_CURSEG_NODE_TYPE;
+	} else {
+		ckpt->ckpt_flags &= (~CP_UMOUNT_FLAG);
+	}
+
+	if (sbi->n_orphans)
+		ckpt->ckpt_flags |= CP_ORPHAN_PRESENT_FLAG;
+	else
+		ckpt->ckpt_flags &= (~CP_ORPHAN_PRESENT_FLAG);
+
+	/* update SIT/NAT bitmap */
+	get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP));
+	get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP));
+
+	crc32 = f2fs_crc32(ckpt, le32_to_cpu(ckpt->checksum_offset));
+	*(__u32 *)((unsigned char *)ckpt +
+				le32_to_cpu(ckpt->checksum_offset))
+				= cpu_to_le32(crc32);
+
+	start_blk = __start_cp_addr(sbi);
+
+	/* write out checkpoint buffer at block 0 */
+	cp_page = grab_meta_page(sbi, start_blk++);
+	kaddr = page_address(cp_page);
+	memcpy(kaddr, ckpt, (1 << sbi->log_blocksize));
+	set_page_dirty(cp_page);
+	f2fs_put_page(cp_page, 1);
+
+	if (sbi->n_orphans) {
+		write_orphan_inodes(sbi, start_blk);
+		start_blk += orphan_blocks;
+	}
+
+	write_data_summaries(sbi, start_blk);
+	start_blk += data_sum_blocks;
+	if (is_umount) {
+		write_node_summaries(sbi, start_blk);
+		start_blk += NR_CURSEG_NODE_TYPE;
+	}
+
+	/* writeout checkpoint block */
+	cp_page = grab_meta_page(sbi, start_blk);
+	kaddr = page_address(cp_page);
+	memcpy(kaddr, ckpt, (1 << sbi->log_blocksize));
+	set_page_dirty(cp_page);
+	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);
+
+	filemap_fdatawait_range(sbi->node_inode->i_mapping, 0, LONG_MAX);
+	filemap_fdatawait_range(sbi->meta_inode->i_mapping, 0, LONG_MAX);
+
+	/* update user_block_counts */
+	sbi->last_valid_block_count = sbi->total_valid_block_count;
+	sbi->alloc_valid_block_count = 0;
+
+	/* Here, we only have one bio having CP pack */
+	if (sbi->ckpt->ckpt_flags & CP_ERROR_FLAG)
+		sbi->sb->s_flags |= MS_RDONLY;
+	else
+		sync_meta_pages(sbi, META_FLUSH, LONG_MAX);
+
+	clear_prefree_segments(sbi);
+	F2FS_RESET_SB_DIRT(sbi);
+}
+
+/**
+ * We guarantee that this checkpoint procedure should not fail.
+ */
+void write_checkpoint(struct f2fs_sb_info *sbi, bool blocked, bool is_umount)
+{
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	unsigned long long ckpt_ver;
+
+	if (!blocked) {
+		mutex_lock(&sbi->cp_mutex);
+		block_operations(sbi);
+	}
+
+	f2fs_submit_bio(sbi, DATA, true);
+	f2fs_submit_bio(sbi, NODE, true);
+	f2fs_submit_bio(sbi, META, true);
+
+	/*
+	 * update checkpoint pack index
+	 * Increase the version number so that
+	 * SIT entries and seg summaries are written at correct place
+	 */
+	ckpt_ver = le64_to_cpu(ckpt->checkpoint_ver);
+	ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver);
+
+	/* write cached NAT/SIT entries to NAT/SIT area */
+	flush_nat_entries(sbi);
+	flush_sit_entries(sbi);
+
+	reset_victim_segmap(sbi);
+
+	/* unlock all the fs_lock[] in do_checkpoint() */
+	do_checkpoint(sbi, is_umount);
+
+	unblock_operations(sbi);
+	mutex_unlock(&sbi->cp_mutex);
+}
+
+void init_orphan_info(struct f2fs_sb_info *sbi)
+{
+	mutex_init(&sbi->orphan_inode_mutex);
+	INIT_LIST_HEAD(&sbi->orphan_inode_list);
+	sbi->n_orphans = 0;
+}
+
+int create_checkpoint_caches(void)
+{
+	orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry",
+			sizeof(struct orphan_inode_entry), NULL);
+	if (unlikely(!orphan_entry_slab))
+		return -ENOMEM;
+	inode_entry_slab = f2fs_kmem_cache_create("f2fs_dirty_dir_entry",
+			sizeof(struct dir_inode_entry), NULL);
+	if (unlikely(!inode_entry_slab)) {
+		kmem_cache_destroy(orphan_entry_slab);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+void destroy_checkpoint_caches(void)
+{
+	kmem_cache_destroy(orphan_entry_slab);
+	kmem_cache_destroy(inode_entry_slab);
+}
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
new file mode 100644
index 0000000..c2fd0a8
--- /dev/null
+++ b/fs/f2fs/data.c
@@ -0,0 +1,701 @@
+/**
+ * fs/f2fs/data.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/buffer_head.h>
+#include <linux/mpage.h>
+#include <linux/writeback.h>
+#include <linux/backing-dev.h>
+#include <linux/blkdev.h>
+#include <linux/bio.h>
+
+#include "f2fs.h"
+#include "node.h"
+#include "segment.h"
+
+/**
+ * Lock ordering for the change of data block address:
+ * ->data_page
+ *  ->node_page
+ *    update block addresses in the node page
+ */
+static void __set_data_blkaddr(struct dnode_of_data *dn, block_t new_addr)
+{
+	struct f2fs_node *rn;
+	__le32 *addr_array;
+	struct page *node_page = dn->node_page;
+	unsigned int ofs_in_node = dn->ofs_in_node;
+
+	wait_on_page_writeback(node_page);
+
+	rn = (struct f2fs_node *)page_address(node_page);
+
+	/* Get physical address of data block */
+	addr_array = blkaddr_in_node(rn);
+	addr_array[ofs_in_node] = cpu_to_le32(new_addr);
+	set_page_dirty(node_page);
+}
+
+int reserve_new_block(struct dnode_of_data *dn)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
+
+	if (is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC))
+		return -EPERM;
+	if (!inc_valid_block_count(sbi, dn->inode, 1))
+		return -ENOSPC;
+
+	__set_data_blkaddr(dn, NEW_ADDR);
+	dn->data_blkaddr = NEW_ADDR;
+	sync_inode_page(dn);
+	return 0;
+}
+
+static int check_extent_cache(struct inode *inode, pgoff_t pgofs,
+					struct buffer_head *bh_result)
+{
+	struct f2fs_inode_info *fi = F2FS_I(inode);
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	pgoff_t start_fofs, end_fofs;
+	block_t start_blkaddr;
+
+	read_lock(&fi->ext.ext_lock);
+	if (fi->ext.len == 0) {
+		read_unlock(&fi->ext.ext_lock);
+		return 0;
+	}
+
+	sbi->total_hit_ext++;
+	start_fofs = fi->ext.fofs;
+	end_fofs = fi->ext.fofs + fi->ext.len - 1;
+	start_blkaddr = fi->ext.blk_addr;
+
+	if (pgofs >= start_fofs && pgofs <= end_fofs) {
+		unsigned int blkbits = inode->i_sb->s_blocksize_bits;
+		size_t count;
+
+		clear_buffer_new(bh_result);
+		map_bh(bh_result, inode->i_sb,
+				start_blkaddr + pgofs - start_fofs);
+		count = end_fofs - pgofs + 1;
+		if (count < (UINT_MAX >> blkbits))
+			bh_result->b_size = (count << blkbits);
+		else
+			bh_result->b_size = UINT_MAX;
+
+		sbi->read_hit_ext++;
+		read_unlock(&fi->ext.ext_lock);
+		return 1;
+	}
+	read_unlock(&fi->ext.ext_lock);
+	return 0;
+}
+
+void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn)
+{
+	struct f2fs_inode_info *fi = F2FS_I(dn->inode);
+	pgoff_t fofs, start_fofs, end_fofs;
+	block_t start_blkaddr, end_blkaddr;
+
+	BUG_ON(blk_addr == NEW_ADDR);
+	fofs = start_bidx_of_node(ofs_of_node(dn->node_page)) + dn->ofs_in_node;
+
+	/* Update the page address in the parent node */
+	__set_data_blkaddr(dn, blk_addr);
+
+	write_lock(&fi->ext.ext_lock);
+
+	start_fofs = fi->ext.fofs;
+	end_fofs = fi->ext.fofs + fi->ext.len - 1;
+	start_blkaddr = fi->ext.blk_addr;
+	end_blkaddr = fi->ext.blk_addr + fi->ext.len - 1;
+
+	/* Drop and initialize the matched extent */
+	if (fi->ext.len == 1 && fofs == start_fofs)
+		fi->ext.len = 0;
+
+	/* Initial extent */
+	if (fi->ext.len == 0) {
+		if (blk_addr != NULL_ADDR) {
+			fi->ext.fofs = fofs;
+			fi->ext.blk_addr = blk_addr;
+			fi->ext.len = 1;
+		}
+		goto end_update;
+	}
+
+	/* Frone merge */
+	if (fofs == start_fofs - 1 && blk_addr == start_blkaddr - 1) {
+		fi->ext.fofs--;
+		fi->ext.blk_addr--;
+		fi->ext.len++;
+		goto end_update;
+	}
+
+	/* Back merge */
+	if (fofs == end_fofs + 1 && blk_addr == end_blkaddr + 1) {
+		fi->ext.len++;
+		goto end_update;
+	}
+
+	/* Split the existing extent */
+	if (fi->ext.len > 1 &&
+		fofs >= start_fofs && fofs <= end_fofs) {
+		if ((end_fofs - fofs) < (fi->ext.len >> 1)) {
+			fi->ext.len = fofs - start_fofs;
+		} else {
+			fi->ext.fofs = fofs + 1;
+			fi->ext.blk_addr = start_blkaddr +
+					fofs - start_fofs + 1;
+			fi->ext.len -= fofs - start_fofs + 1;
+		}
+		goto end_update;
+	}
+	write_unlock(&fi->ext.ext_lock);
+	return;
+
+end_update:
+	write_unlock(&fi->ext.ext_lock);
+	sync_inode_page(dn);
+	return;
+}
+
+struct page *find_data_page(struct inode *inode, pgoff_t index)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct address_space *mapping = inode->i_mapping;
+	struct dnode_of_data dn;
+	struct page *page;
+	int err;
+
+	page = find_get_page(mapping, index);
+	if (page && PageUptodate(page))
+		return page;
+	f2fs_put_page(page, 0);
+
+	set_new_dnode(&dn, inode, NULL, NULL, 0);
+	err = get_dnode_of_data(&dn, index, RDONLY_NODE);
+	if (err)
+		return ERR_PTR(err);
+	f2fs_put_dnode(&dn);
+
+	if (dn.data_blkaddr == NULL_ADDR)
+		return ERR_PTR(-ENOENT);
+
+	/* By fallocate(), there is no cached page, but with NEW_ADDR */
+	if (dn.data_blkaddr == NEW_ADDR)
+		return ERR_PTR(-EINVAL);
+
+	page = grab_cache_page(mapping, index);
+	if (!page)
+		return ERR_PTR(-ENOMEM);
+
+	err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
+	if (err) {
+		f2fs_put_page(page, 1);
+		return ERR_PTR(err);
+	}
+	unlock_page(page);
+	return page;
+}
+
+/**
+ * If it tries to access a hole, return an error.
+ * Because, the callers, functions in dir.c and GC, should be able to know
+ * whether this page exists or not.
+ */
+struct page *get_lock_data_page(struct inode *inode, pgoff_t index)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct address_space *mapping = inode->i_mapping;
+	struct dnode_of_data dn;
+	struct page *page;
+	int err;
+
+	set_new_dnode(&dn, inode, NULL, NULL, 0);
+	err = get_dnode_of_data(&dn, index, RDONLY_NODE);
+	if (err)
+		return ERR_PTR(err);
+	f2fs_put_dnode(&dn);
+
+	if (dn.data_blkaddr == NULL_ADDR)
+		return ERR_PTR(-ENOENT);
+
+	page = grab_cache_page(mapping, index);
+	if (!page)
+		return ERR_PTR(-ENOMEM);
+
+	if (PageUptodate(page))
+		return page;
+
+	BUG_ON(dn.data_blkaddr == NEW_ADDR);
+	BUG_ON(dn.data_blkaddr == NULL_ADDR);
+
+	err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
+	if (err) {
+		f2fs_put_page(page, 1);
+		return ERR_PTR(err);
+	}
+	return page;
+}
+
+/**
+ * Caller ensures that this data page is never allocated.
+ * A new zero-filled data page is allocated in the page cache.
+ */
+struct page *get_new_data_page(struct inode *inode, pgoff_t index,
+						bool new_i_size)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct address_space *mapping = inode->i_mapping;
+	struct page *page;
+	struct dnode_of_data dn;
+	int err;
+
+	set_new_dnode(&dn, inode, NULL, NULL, 0);
+	err = get_dnode_of_data(&dn, index, 0);
+	if (err)
+		return ERR_PTR(err);
+
+	if (dn.data_blkaddr == NULL_ADDR) {
+		if (reserve_new_block(&dn)) {
+			f2fs_put_dnode(&dn);
+			return ERR_PTR(-ENOSPC);
+		}
+	}
+	f2fs_put_dnode(&dn);
+
+	page = grab_cache_page(mapping, index);
+	if (!page)
+		return ERR_PTR(-ENOMEM);
+
+	if (PageUptodate(page))
+		return page;
+
+	if (dn.data_blkaddr == NEW_ADDR) {
+		zero_user_segment(page, 0, PAGE_CACHE_SIZE);
+	} else {
+		err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
+		if (err) {
+			f2fs_put_page(page, 1);
+			return ERR_PTR(err);
+		}
+	}
+	SetPageUptodate(page);
+
+	if (new_i_size &&
+		i_size_read(inode) < ((index + 1) << PAGE_CACHE_SHIFT)) {
+		i_size_write(inode, ((index + 1) << PAGE_CACHE_SHIFT));
+		mark_inode_dirty_sync(inode);
+	}
+	return page;
+}
+
+static void read_end_io(struct bio *bio, int err)
+{
+	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+
+	do {
+		struct page *page = bvec->bv_page;
+
+		if (--bvec >= bio->bi_io_vec)
+			prefetchw(&bvec->bv_page->flags);
+
+		if (uptodate) {
+			SetPageUptodate(page);
+		} else {
+			ClearPageUptodate(page);
+			SetPageError(page);
+		}
+		unlock_page(page);
+	} while (bvec >= bio->bi_io_vec);
+	kfree(bio->bi_private);
+	bio_put(bio);
+}
+
+/**
+ * Fill the locked page with data located in the block address.
+ * Read operation is synchronous, and caller must unlock the page.
+ */
+int f2fs_readpage(struct f2fs_sb_info *sbi, struct page *page,
+					block_t blk_addr, int type)
+{
+	struct block_device *bdev = sbi->sb->s_bdev;
+	bool sync = (type == READ_SYNC);
+	struct bio *bio;
+
+	/* This page can be already read by other threads */
+	if (PageUptodate(page)) {
+		if (!sync)
+			unlock_page(page);
+		return 0;
+	}
+
+	down_read(&sbi->bio_sem);
+
+	/* Allocate a new bio */
+	bio = f2fs_bio_alloc(bdev, blk_addr << (sbi->log_blocksize - 9),
+				1, GFP_NOFS | __GFP_HIGH);
+
+	/* Initialize the bio */
+	bio->bi_end_io = read_end_io;
+	if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) {
+		kfree(bio->bi_private);
+		bio_put(bio);
+		up_read(&sbi->bio_sem);
+		return -EFAULT;
+	}
+
+	submit_bio(type, bio);
+	up_read(&sbi->bio_sem);
+
+	/* wait for read completion if sync */
+	if (sync) {
+		lock_page(page);
+		if (PageError(page))
+			return -EIO;
+	}
+	return 0;
+}
+
+/**
+ * This function should be used by the data read flow only where it
+ * does not check the "create" flag that indicates block allocation.
+ * The reason for this special functionality is to exploit VFS readahead
+ * mechanism.
+ */
+static int get_data_block_ro(struct inode *inode, sector_t iblock,
+			struct buffer_head *bh_result, int create)
+{
+	unsigned int blkbits = inode->i_sb->s_blocksize_bits;
+	unsigned maxblocks = bh_result->b_size >> blkbits;
+	struct dnode_of_data dn;
+	pgoff_t pgofs;
+	int err;
+
+	/* Get the page offset from the block offset(iblock) */
+	pgofs =	(pgoff_t)(iblock >> (PAGE_CACHE_SHIFT - blkbits));
+
+	if (check_extent_cache(inode, pgofs, bh_result))
+		return 0;
+
+	/* When reading holes, we need its node page */
+	set_new_dnode(&dn, inode, NULL, NULL, 0);
+	err = get_dnode_of_data(&dn, pgofs, RDONLY_NODE);
+	if (err)
+		return (err == -ENOENT) ? 0 : err;
+
+	/* It does not support data allocation */
+	BUG_ON(create);
+
+	if (dn.data_blkaddr != NEW_ADDR && dn.data_blkaddr != NULL_ADDR) {
+		int i;
+		unsigned int end_offset;
+
+		end_offset = IS_INODE(dn.node_page) ?
+				ADDRS_PER_INODE :
+				ADDRS_PER_BLOCK;
+
+		clear_buffer_new(bh_result);
+
+		/* Give more consecutive addresses for the read ahead */
+		for (i = 0; i < end_offset - dn.ofs_in_node; i++)
+			if (((datablock_addr(dn.node_page,
+							dn.ofs_in_node + i))
+				!= (dn.data_blkaddr + i)) || maxblocks == i)
+				break;
+		map_bh(bh_result, inode->i_sb, dn.data_blkaddr);
+		bh_result->b_size = (i << blkbits);
+	}
+	f2fs_put_dnode(&dn);
+	return 0;
+}
+
+static int f2fs_read_data_page(struct file *file, struct page *page)
+{
+	return mpage_readpage(page, get_data_block_ro);
+}
+
+static int f2fs_read_data_pages(struct file *file,
+			struct address_space *mapping,
+			struct list_head *pages, unsigned nr_pages)
+{
+	return mpage_readpages(mapping, pages, nr_pages, get_data_block_ro);
+}
+
+int do_write_data_page(struct page *page)
+{
+	struct inode *inode = page->mapping->host;
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	block_t old_blk_addr, new_blk_addr;
+	struct dnode_of_data dn;
+	int err = 0;
+
+	set_new_dnode(&dn, inode, NULL, NULL, 0);
+	err = get_dnode_of_data(&dn, page->index, RDONLY_NODE);
+	if (err)
+		return err;
+
+	old_blk_addr = dn.data_blkaddr;
+
+	/* This page is already truncated */
+	if (old_blk_addr == NULL_ADDR)
+		goto out_writepage;
+
+	set_page_writeback(page);
+
+	/*
+	 * If current allocation needs SSR,
+	 * it had better in-place writes for updated data.
+	 */
+	if (old_blk_addr != NEW_ADDR && !is_cold_data(page) &&
+				need_inplace_update(inode)) {
+		rewrite_data_page(F2FS_SB(inode->i_sb), page,
+						old_blk_addr);
+	} else {
+		write_data_page(inode, page, &dn,
+				old_blk_addr, &new_blk_addr);
+		update_extent_cache(new_blk_addr, &dn);
+		F2FS_I(inode)->data_version =
+			le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver);
+	}
+out_writepage:
+	f2fs_put_dnode(&dn);
+	return err;
+}
+
+static int f2fs_write_data_page(struct page *page,
+					struct writeback_control *wbc)
+{
+	struct inode *inode = page->mapping->host;
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	loff_t i_size = i_size_read(inode);
+	const pgoff_t end_index = ((unsigned long long) i_size)
+							>> PAGE_CACHE_SHIFT;
+	unsigned offset;
+	int err = 0;
+
+	if (page->index < end_index)
+		goto out;
+
+	/*
+	 * If the offset is out-of-range of file size,
+	 * this page does not have to be written to disk.
+	 */
+	offset = i_size & (PAGE_CACHE_SIZE - 1);
+	if ((page->index >= end_index + 1) || !offset) {
+		if (S_ISDIR(inode->i_mode)) {
+			dec_page_count(sbi, F2FS_DIRTY_DENTS);
+			inode_dec_dirty_dents(inode);
+		}
+		goto unlock_out;
+	}
+
+	zero_user_segment(page, offset, PAGE_CACHE_SIZE);
+out:
+	if (sbi->por_doing)
+		goto redirty_out;
+
+	if (wbc->for_reclaim && !S_ISDIR(inode->i_mode) && !is_cold_data(page))
+		goto redirty_out;
+
+	mutex_lock_op(sbi, DATA_WRITE);
+	if (S_ISDIR(inode->i_mode)) {
+		dec_page_count(sbi, F2FS_DIRTY_DENTS);
+		inode_dec_dirty_dents(inode);
+	}
+	err = do_write_data_page(page);
+	if (err && err != -ENOENT) {
+		wbc->pages_skipped++;
+		set_page_dirty(page);
+	}
+	mutex_unlock_op(sbi, DATA_WRITE);
+
+	if (wbc->for_reclaim)
+		f2fs_submit_bio(sbi, DATA, true);
+
+	if (err == -ENOENT)
+		goto unlock_out;
+
+	clear_cold_data(page);
+	unlock_page(page);
+
+	if (!wbc->for_reclaim && !S_ISDIR(inode->i_mode))
+		f2fs_balance_fs(sbi);
+	return 0;
+
+unlock_out:
+	unlock_page(page);
+	return (err == -ENOENT) ? 0 : err;
+
+redirty_out:
+	wbc->pages_skipped++;
+	set_page_dirty(page);
+	return AOP_WRITEPAGE_ACTIVATE;
+}
+
+#define MAX_DESIRED_PAGES_WP	4096
+
+int f2fs_write_data_pages(struct address_space *mapping,
+			    struct writeback_control *wbc)
+{
+	struct inode *inode = mapping->host;
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	int ret;
+	long excess_nrtw = 0, desired_nrtw;
+
+	if (wbc->nr_to_write < MAX_DESIRED_PAGES_WP) {
+		desired_nrtw = MAX_DESIRED_PAGES_WP;
+		excess_nrtw = desired_nrtw - wbc->nr_to_write;
+		wbc->nr_to_write = desired_nrtw;
+	}
+
+	if (!S_ISDIR(inode->i_mode))
+		mutex_lock(&sbi->writepages);
+	ret = generic_writepages(mapping, wbc);
+	if (!S_ISDIR(inode->i_mode))
+		mutex_unlock(&sbi->writepages);
+	f2fs_submit_bio(sbi, DATA, (wbc->sync_mode == WB_SYNC_ALL));
+
+	remove_dirty_dir_inode(inode);
+
+	wbc->nr_to_write -= excess_nrtw;
+	return ret;
+}
+
+static int f2fs_write_begin(struct file *file, struct address_space *mapping,
+		loff_t pos, unsigned len, unsigned flags,
+		struct page **pagep, void **fsdata)
+{
+	struct inode *inode = mapping->host;
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct page *page;
+	pgoff_t index = ((unsigned long long) pos) >> PAGE_CACHE_SHIFT;
+	struct dnode_of_data dn;
+	int err = 0;
+
+	/* for nobh_write_end */
+	*fsdata = NULL;
+
+	f2fs_balance_fs(sbi);
+
+	page = grab_cache_page_write_begin(mapping, index, flags);
+	if (!page)
+		return -ENOMEM;
+	*pagep = page;
+
+	mutex_lock_op(sbi, DATA_NEW);
+
+	set_new_dnode(&dn, inode, NULL, NULL, 0);
+	err = get_dnode_of_data(&dn, index, 0);
+	if (err) {
+		mutex_unlock_op(sbi, DATA_NEW);
+		f2fs_put_page(page, 1);
+		return err;
+	}
+
+	if (dn.data_blkaddr == NULL_ADDR) {
+		err = reserve_new_block(&dn);
+		if (err) {
+			f2fs_put_dnode(&dn);
+			mutex_unlock_op(sbi, DATA_NEW);
+			f2fs_put_page(page, 1);
+			return err;
+		}
+	}
+	f2fs_put_dnode(&dn);
+
+	mutex_unlock_op(sbi, DATA_NEW);
+
+	if ((len == PAGE_CACHE_SIZE) || PageUptodate(page))
+		return 0;
+
+	if ((pos & PAGE_CACHE_MASK) >= i_size_read(inode)) {
+		unsigned start = pos & (PAGE_CACHE_SIZE - 1);
+		unsigned end = start + len;
+
+		/* Reading beyond i_size is simple: memset to zero */
+		zero_user_segments(page, 0, start, end, PAGE_CACHE_SIZE);
+		return 0;
+	}
+
+	if (dn.data_blkaddr == NEW_ADDR) {
+		zero_user_segment(page, 0, PAGE_CACHE_SIZE);
+	} else {
+		err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
+		if (err) {
+			f2fs_put_page(page, 1);
+			return err;
+		}
+	}
+	SetPageUptodate(page);
+	clear_cold_data(page);
+	return 0;
+}
+
+static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb,
+		const struct iovec *iov, loff_t offset, unsigned long nr_segs)
+{
+	struct file *file = iocb->ki_filp;
+	struct inode *inode = file->f_mapping->host;
+
+	if (rw == WRITE)
+		return 0;
+
+	/* Needs synchronization with the cleaner */
+	return blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
+						  get_data_block_ro);
+}
+
+static void f2fs_invalidate_data_page(struct page *page, unsigned long offset)
+{
+	struct inode *inode = page->mapping->host;
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	if (S_ISDIR(inode->i_mode) && PageDirty(page)) {
+		dec_page_count(sbi, F2FS_DIRTY_DENTS);
+		inode_dec_dirty_dents(inode);
+	}
+	ClearPagePrivate(page);
+}
+
+static int f2fs_release_data_page(struct page *page, gfp_t wait)
+{
+	ClearPagePrivate(page);
+	return 0;
+}
+
+static int f2fs_set_data_page_dirty(struct page *page)
+{
+	struct address_space *mapping = page->mapping;
+	struct inode *inode = mapping->host;
+
+	SetPageUptodate(page);
+	if (!PageDirty(page)) {
+		__set_page_dirty_nobuffers(page);
+		set_dirty_dir_page(inode, page);
+		return 1;
+	}
+	return 0;
+}
+
+const struct address_space_operations f2fs_dblock_aops = {
+	.readpage	= f2fs_read_data_page,
+	.readpages	= f2fs_read_data_pages,
+	.writepage	= f2fs_write_data_page,
+	.writepages	= f2fs_write_data_pages,
+	.write_begin	= f2fs_write_begin,
+	.write_end	= nobh_write_end,
+	.set_page_dirty	= f2fs_set_data_page_dirty,
+	.invalidatepage	= f2fs_invalidate_data_page,
+	.releasepage	= f2fs_release_data_page,
+	.direct_IO	= f2fs_direct_IO,
+};
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
new file mode 100644
index 0000000..a56181c
--- /dev/null
+++ b/fs/f2fs/debug.c
@@ -0,0 +1,361 @@
+/**
+ * f2fs debugging statistics
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ * Copyright (c) 2012 Linux Foundation
+ * Copyright (c) 2012 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/fs.h>
+#include <linux/backing-dev.h>
+#include <linux/proc_fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/blkdev.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include "f2fs.h"
+#include "node.h"
+#include "segment.h"
+#include "gc.h"
+
+static LIST_HEAD(f2fs_stat_list);
+static struct dentry *debugfs_root;
+
+void update_general_status(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_stat_info *si = sbi->stat_info;
+	int i;
+
+	/* valid check of the segment numbers */
+	si->hit_ext = sbi->read_hit_ext;
+	si->total_ext = sbi->total_hit_ext;
+	si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
+	si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS);
+	si->ndirty_dirs = sbi->n_dirty_dirs;
+	si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META);
+	si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
+	si->rsvd_segs = reserved_segments(sbi);
+	si->overp_segs = overprovision_segments(sbi);
+	si->valid_count = valid_user_blocks(sbi);
+	si->valid_node_count = valid_node_count(sbi);
+	si->valid_inode_count = valid_inode_count(sbi);
+	si->utilization = utilization(sbi);
+
+	si->free_segs = free_segments(sbi);
+	si->free_secs = free_sections(sbi);
+	si->prefree_count = prefree_segments(sbi);
+	si->dirty_count = dirty_segments(sbi);
+	si->node_pages = sbi->node_inode->i_mapping->nrpages;
+	si->meta_pages = sbi->meta_inode->i_mapping->nrpages;
+	si->nats = NM_I(sbi)->nat_cnt;
+	si->sits = SIT_I(sbi)->dirty_sentries;
+	si->fnids = NM_I(sbi)->fcnt;
+	si->bg_gc = sbi->bg_gc;
+	si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg)
+		* 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
+		/ 2;
+	si->util_valid = (int)(written_block_count(sbi) >>
+						sbi->log_blocks_per_seg)
+		* 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
+		/ 2;
+	si->util_invalid = 50 - si->util_free - si->util_valid;
+	for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_NODE; i++) {
+		struct curseg_info *curseg = CURSEG_I(sbi, i);
+		si->curseg[i] = curseg->segno;
+		si->cursec[i] = curseg->segno / sbi->segs_per_sec;
+		si->curzone[i] = si->cursec[i] / sbi->secs_per_zone;
+	}
+
+	for (i = 0; i < 2; i++) {
+		si->segment_count[i] = sbi->segment_count[i];
+		si->block_count[i] = sbi->block_count[i];
+	}
+}
+
+/**
+ * This function calculates BDF of every segments
+ */
+static void update_sit_info(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_stat_info *si = sbi->stat_info;
+	unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist;
+	struct sit_info *sit_i = SIT_I(sbi);
+	unsigned int segno, vblocks;
+	int ndirty = 0;
+
+	bimodal = 0;
+	total_vblocks = 0;
+	blks_per_sec = sbi->segs_per_sec * (1 << sbi->log_blocks_per_seg);
+	hblks_per_sec = blks_per_sec / 2;
+	mutex_lock(&sit_i->sentry_lock);
+	for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) {
+		vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec);
+		dist = abs(vblocks - hblks_per_sec);
+		bimodal += dist * dist;
+
+		if (vblocks > 0 && vblocks < blks_per_sec) {
+			total_vblocks += vblocks;
+			ndirty++;
+		}
+	}
+	mutex_unlock(&sit_i->sentry_lock);
+	dist = sbi->total_sections * hblks_per_sec * hblks_per_sec / 100;
+	si->bimodal = bimodal / dist;
+	if (si->dirty_count)
+		si->avg_vblocks = total_vblocks / ndirty;
+	else
+		si->avg_vblocks = 0;
+}
+
+/**
+ * This function calculates memory footprint.
+ */
+static void update_mem_info(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_stat_info *si = sbi->stat_info;
+	unsigned npages;
+
+	if (si->base_mem)
+		goto get_cache;
+
+	si->base_mem = sizeof(struct f2fs_sb_info) + sbi->sb->s_blocksize;
+	si->base_mem += 2 * sizeof(struct f2fs_inode_info);
+	si->base_mem += sizeof(*sbi->ckpt);
+
+	/* build sm */
+	si->base_mem += sizeof(struct f2fs_sm_info);
+
+	/* build sit */
+	si->base_mem += sizeof(struct sit_info);
+	si->base_mem += TOTAL_SEGS(sbi) * sizeof(struct seg_entry);
+	si->base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
+	si->base_mem += 2 * SIT_VBLOCK_MAP_SIZE * TOTAL_SEGS(sbi);
+	if (sbi->segs_per_sec > 1)
+		si->base_mem += sbi->total_sections *
+			sizeof(struct sec_entry);
+	si->base_mem += __bitmap_size(sbi, SIT_BITMAP);
+
+	/* build free segmap */
+	si->base_mem += sizeof(struct free_segmap_info);
+	si->base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
+	si->base_mem += f2fs_bitmap_size(sbi->total_sections);
+
+	/* build curseg */
+	si->base_mem += sizeof(struct curseg_info) * NR_CURSEG_TYPE;
+	si->base_mem += PAGE_CACHE_SIZE * NR_CURSEG_TYPE;
+
+	/* build dirty segmap */
+	si->base_mem += sizeof(struct dirty_seglist_info);
+	si->base_mem += NR_DIRTY_TYPE * f2fs_bitmap_size(TOTAL_SEGS(sbi));
+	si->base_mem += 2 * f2fs_bitmap_size(TOTAL_SEGS(sbi));
+
+	/* buld nm */
+	si->base_mem += sizeof(struct f2fs_nm_info);
+	si->base_mem += __bitmap_size(sbi, NAT_BITMAP);
+
+	/* build gc */
+	si->base_mem += sizeof(struct f2fs_gc_kthread);
+
+get_cache:
+	/* free nids */
+	si->cache_mem = NM_I(sbi)->fcnt;
+	si->cache_mem += NM_I(sbi)->nat_cnt;
+	npages = sbi->node_inode->i_mapping->nrpages;
+	si->cache_mem += npages << PAGE_CACHE_SHIFT;
+	npages = sbi->meta_inode->i_mapping->nrpages;
+	si->cache_mem += npages << PAGE_CACHE_SHIFT;
+	si->cache_mem += sbi->n_orphans * sizeof(struct orphan_inode_entry);
+	si->cache_mem += sbi->n_dirty_dirs * sizeof(struct dir_inode_entry);
+}
+
+static int stat_show(struct seq_file *s, void *v)
+{
+	struct f2fs_stat_info *si, *next;
+	int i = 0;
+	int j;
+
+	list_for_each_entry_safe(si, next, &f2fs_stat_list, stat_list) {
+
+		mutex_lock(&si->stat_lock);
+		if (!si->sbi) {
+			mutex_unlock(&si->stat_lock);
+			continue;
+		}
+		update_general_status(si->sbi);
+
+		seq_printf(s, "\n=====[ partition info. #%d ]=====\n", i++);
+		seq_printf(s, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
+			   si->nat_area_segs, si->sit_area_segs);
+		seq_printf(s, "[SSA: %d] [MAIN: %d",
+			   si->ssa_area_segs, si->main_area_segs);
+		seq_printf(s, "(OverProv:%d Resv:%d)]\n\n",
+			   si->overp_segs, si->rsvd_segs);
+		seq_printf(s, "Utilization: %d%% (%d valid blocks)\n",
+			   si->utilization, si->valid_count);
+		seq_printf(s, "  - Node: %u (Inode: %u, ",
+			   si->valid_node_count, si->valid_inode_count);
+		seq_printf(s, "Other: %u)\n  - Data: %u\n",
+			   si->valid_node_count - si->valid_inode_count,
+			   si->valid_count - si->valid_node_count);
+		seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n",
+			   si->main_area_segs, si->main_area_sections,
+			   si->main_area_zones);
+		seq_printf(s, "  - COLD  data: %d, %d, %d\n",
+			   si->curseg[CURSEG_COLD_DATA],
+			   si->cursec[CURSEG_COLD_DATA],
+			   si->curzone[CURSEG_COLD_DATA]);
+		seq_printf(s, "  - WARM  data: %d, %d, %d\n",
+			   si->curseg[CURSEG_WARM_DATA],
+			   si->cursec[CURSEG_WARM_DATA],
+			   si->curzone[CURSEG_WARM_DATA]);
+		seq_printf(s, "  - HOT   data: %d, %d, %d\n",
+			   si->curseg[CURSEG_HOT_DATA],
+			   si->cursec[CURSEG_HOT_DATA],
+			   si->curzone[CURSEG_HOT_DATA]);
+		seq_printf(s, "  - Dir   dnode: %d, %d, %d\n",
+			   si->curseg[CURSEG_HOT_NODE],
+			   si->cursec[CURSEG_HOT_NODE],
+			   si->curzone[CURSEG_HOT_NODE]);
+		seq_printf(s, "  - File   dnode: %d, %d, %d\n",
+			   si->curseg[CURSEG_WARM_NODE],
+			   si->cursec[CURSEG_WARM_NODE],
+			   si->curzone[CURSEG_WARM_NODE]);
+		seq_printf(s, "  - Indir nodes: %d, %d, %d\n",
+			   si->curseg[CURSEG_COLD_NODE],
+			   si->cursec[CURSEG_COLD_NODE],
+			   si->curzone[CURSEG_COLD_NODE]);
+		seq_printf(s, "\n  - Valid: %d\n  - Dirty: %d\n",
+			   si->main_area_segs - si->dirty_count -
+			   si->prefree_count - si->free_segs,
+			   si->dirty_count);
+		seq_printf(s, "  - Prefree: %d\n  - Free: %d (%d)\n\n",
+			   si->prefree_count, si->free_segs, si->free_secs);
+		seq_printf(s, "GC calls: %d (BG: %d)\n",
+			   si->call_count, si->bg_gc);
+		seq_printf(s, "  - data segments : %d\n", si->data_segs);
+		seq_printf(s, "  - node segments : %d\n", si->node_segs);
+		seq_printf(s, "Try to move %d blocks\n", si->tot_blks);
+		seq_printf(s, "  - data blocks : %d\n", si->data_blks);
+		seq_printf(s, "  - node blocks : %d\n", si->node_blks);
+		seq_printf(s, "\nExtent Hit Ratio: %d / %d\n",
+			   si->hit_ext, si->total_ext);
+		seq_printf(s, "\nBalancing F2FS Async:\n");
+		seq_printf(s, "  - nodes %4d in %4d\n",
+			   si->ndirty_node, si->node_pages);
+		seq_printf(s, "  - dents %4d in dirs:%4d\n",
+			   si->ndirty_dent, si->ndirty_dirs);
+		seq_printf(s, "  - meta %4d in %4d\n",
+			   si->ndirty_meta, si->meta_pages);
+		seq_printf(s, "  - NATs %5d > %lu\n",
+			   si->nats, NM_WOUT_THRESHOLD);
+		seq_printf(s, "  - SITs: %5d\n  - free_nids: %5d\n",
+			   si->sits, si->fnids);
+		seq_printf(s, "\nDistribution of User Blocks:");
+		seq_printf(s, " [ valid | invalid | free ]\n");
+		seq_printf(s, "  [");
+
+		for (j = 0; j < si->util_valid; j++)
+			seq_printf(s, "-");
+		seq_printf(s, "|");
+
+		for (j = 0; j < si->util_invalid; j++)
+			seq_printf(s, "-");
+		seq_printf(s, "|");
+
+		for (j = 0; j < si->util_free; j++)
+			seq_printf(s, "-");
+		seq_printf(s, "]\n\n");
+		seq_printf(s, "SSR: %u blocks in %u segments\n",
+			   si->block_count[SSR], si->segment_count[SSR]);
+		seq_printf(s, "LFS: %u blocks in %u segments\n",
+			   si->block_count[LFS], si->segment_count[LFS]);
+
+		/* segment usage info */
+		update_sit_info(si->sbi);
+		seq_printf(s, "\nBDF: %u, avg. vblocks: %u\n",
+			   si->bimodal, si->avg_vblocks);
+
+		/* memory footprint */
+		update_mem_info(si->sbi);
+		seq_printf(s, "\nMemory: %u KB = static: %u + cached: %u\n",
+				(si->base_mem + si->cache_mem) >> 10,
+				si->base_mem >> 10, si->cache_mem >> 10);
+		mutex_unlock(&si->stat_lock);
+	}
+	return 0;
+}
+
+static int stat_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, stat_show, inode->i_private);
+}
+
+static const struct file_operations stat_fops = {
+	.open = stat_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int init_stats(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
+	struct f2fs_stat_info *si;
+
+	sbi->stat_info = kzalloc(sizeof(struct f2fs_stat_info), GFP_KERNEL);
+	if (!sbi->stat_info)
+		return -ENOMEM;
+
+	si = sbi->stat_info;
+	mutex_init(&si->stat_lock);
+	list_add_tail(&si->stat_list, &f2fs_stat_list);
+
+	si->all_area_segs = le32_to_cpu(raw_super->segment_count);
+	si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
+	si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
+	si->ssa_area_segs = le32_to_cpu(raw_super->segment_count_ssa);
+	si->main_area_segs = le32_to_cpu(raw_super->segment_count_main);
+	si->main_area_sections = le32_to_cpu(raw_super->section_count);
+	si->main_area_zones = si->main_area_sections /
+				le32_to_cpu(raw_super->secs_per_zone);
+	si->sbi = sbi;
+	return 0;
+}
+
+int f2fs_build_stats(struct f2fs_sb_info *sbi)
+{
+	int retval;
+
+	retval = init_stats(sbi);
+	if (retval)
+		return retval;
+
+	if (!debugfs_root)
+		debugfs_root = debugfs_create_dir("f2fs", NULL);
+
+	debugfs_create_file("status", S_IRUGO, debugfs_root, NULL, &stat_fops);
+	return 0;
+}
+
+void f2fs_destroy_stats(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_stat_info *si = sbi->stat_info;
+
+	list_del(&si->stat_list);
+	mutex_lock(&si->stat_lock);
+	si->sbi = NULL;
+	mutex_unlock(&si->stat_lock);
+	kfree(sbi->stat_info);
+}
+
+void destroy_root_stats(void)
+{
+	debugfs_remove_recursive(debugfs_root);
+	debugfs_root = NULL;
+}
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
new file mode 100644
index 0000000..5975568
--- /dev/null
+++ b/fs/f2fs/dir.c
@@ -0,0 +1,672 @@
+/**
+ * fs/f2fs/dir.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/fs.h>
+#include <linux/f2fs_fs.h>
+#include "f2fs.h"
+#include "acl.h"
+
+static unsigned long dir_blocks(struct inode *inode)
+{
+	return ((unsigned long long) (i_size_read(inode) + PAGE_CACHE_SIZE - 1))
+							>> PAGE_CACHE_SHIFT;
+}
+
+static unsigned int dir_buckets(unsigned int level)
+{
+	if (level < MAX_DIR_HASH_DEPTH / 2)
+		return 1 << level;
+	else
+		return 1 << ((MAX_DIR_HASH_DEPTH / 2) - 1);
+}
+
+static unsigned int bucket_blocks(unsigned int level)
+{
+	if (level < MAX_DIR_HASH_DEPTH / 2)
+		return 2;
+	else
+		return 4;
+}
+
+static unsigned char f2fs_filetype_table[F2FS_FT_MAX] = {
+	[F2FS_FT_UNKNOWN]	= DT_UNKNOWN,
+	[F2FS_FT_REG_FILE]	= DT_REG,
+	[F2FS_FT_DIR]		= DT_DIR,
+	[F2FS_FT_CHRDEV]	= DT_CHR,
+	[F2FS_FT_BLKDEV]	= DT_BLK,
+	[F2FS_FT_FIFO]		= DT_FIFO,
+	[F2FS_FT_SOCK]		= DT_SOCK,
+	[F2FS_FT_SYMLINK]	= DT_LNK,
+};
+
+#define S_SHIFT 12
+static unsigned char f2fs_type_by_mode[S_IFMT >> S_SHIFT] = {
+	[S_IFREG >> S_SHIFT]	= F2FS_FT_REG_FILE,
+	[S_IFDIR >> S_SHIFT]	= F2FS_FT_DIR,
+	[S_IFCHR >> S_SHIFT]	= F2FS_FT_CHRDEV,
+	[S_IFBLK >> S_SHIFT]	= F2FS_FT_BLKDEV,
+	[S_IFIFO >> S_SHIFT]	= F2FS_FT_FIFO,
+	[S_IFSOCK >> S_SHIFT]	= F2FS_FT_SOCK,
+	[S_IFLNK >> S_SHIFT]	= F2FS_FT_SYMLINK,
+};
+
+static void set_de_type(struct f2fs_dir_entry *de, struct inode *inode)
+{
+	mode_t mode = inode->i_mode;
+	de->file_type = f2fs_type_by_mode[(mode & S_IFMT) >> S_SHIFT];
+}
+
+static unsigned long dir_block_index(unsigned int level, unsigned int idx)
+{
+	unsigned long i;
+	unsigned long bidx = 0;
+
+	for (i = 0; i < level; i++)
+		bidx += dir_buckets(i) * bucket_blocks(i);
+	bidx += idx * bucket_blocks(level);
+	return bidx;
+}
+
+static bool early_match_name(const char *name, int namelen,
+			f2fs_hash_t namehash, struct f2fs_dir_entry *de)
+{
+	if (le16_to_cpu(de->name_len) != namelen)
+		return false;
+
+	if (le32_to_cpu(de->hash_code) != namehash)
+		return false;
+
+	return true;
+}
+
+static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
+			const char *name, int namelen, int *max_slots,
+			f2fs_hash_t namehash, struct page **res_page)
+{
+	struct f2fs_dir_entry *de;
+	unsigned long bit_pos, end_pos, next_pos;
+	struct f2fs_dentry_block *dentry_blk = kmap(dentry_page);
+	int slots;
+
+	bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
+					NR_DENTRY_IN_BLOCK, 0);
+	while (bit_pos < NR_DENTRY_IN_BLOCK) {
+		de = &dentry_blk->dentry[bit_pos];
+		slots = (le16_to_cpu(de->name_len) + F2FS_NAME_LEN - 1) /
+							F2FS_NAME_LEN;
+
+		if (early_match_name(name, namelen, namehash, de)) {
+			if (!memcmp(dentry_blk->filename[bit_pos],
+							name, namelen)) {
+				*res_page = dentry_page;
+				goto found;
+			}
+		}
+		next_pos = bit_pos + slots;
+		bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
+				NR_DENTRY_IN_BLOCK, next_pos);
+		if (bit_pos >= NR_DENTRY_IN_BLOCK)
+			end_pos = NR_DENTRY_IN_BLOCK;
+		else
+			end_pos = bit_pos;
+		if (*max_slots < end_pos - next_pos)
+			*max_slots = end_pos - next_pos;
+	}
+
+	de = NULL;
+	kunmap(dentry_page);
+found:
+	return de;
+}
+
+static struct f2fs_dir_entry *find_in_level(struct inode *dir,
+		unsigned int level, const char *name, int namelen,
+			f2fs_hash_t namehash, struct page **res_page)
+{
+	int s = (namelen + F2FS_NAME_LEN - 1) / F2FS_NAME_LEN;
+	unsigned int nbucket, nblock;
+	unsigned int bidx, end_block;
+	struct page *dentry_page;
+	struct f2fs_dir_entry *de = NULL;
+	bool room = false;
+	int max_slots = 0;
+
+	BUG_ON(level > MAX_DIR_HASH_DEPTH);
+
+	nbucket = dir_buckets(level);
+	nblock = bucket_blocks(level);
+
+	bidx = dir_block_index(level, namehash % nbucket);
+	end_block = bidx + nblock;
+
+	for (; bidx < end_block; bidx++) {
+		/* no need to allocate new dentry pages to all the indices */
+		dentry_page = find_data_page(dir, bidx);
+		if (IS_ERR(dentry_page)) {
+			room = true;
+			continue;
+		}
+
+		de = find_in_block(dentry_page, name, namelen,
+					&max_slots, namehash, res_page);
+		if (de)
+			break;
+
+		if (max_slots >= s)
+			room = true;
+		f2fs_put_page(dentry_page, 0);
+	}
+
+	if (!de && room && F2FS_I(dir)->chash != namehash) {
+		F2FS_I(dir)->chash = namehash;
+		F2FS_I(dir)->clevel = level;
+	}
+
+	return de;
+}
+
+/*
+ * Find an entry in the specified directory with the wanted name.
+ * It returns the page where the entry was found (as a parameter - res_page),
+ * and the entry itself. Page is returned mapped and unlocked.
+ * Entry is guaranteed to be valid.
+ */
+struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
+			struct qstr *child, struct page **res_page)
+{
+	const char *name = child->name;
+	int namelen = child->len;
+	unsigned long npages = dir_blocks(dir);
+	struct f2fs_dir_entry *de = NULL;
+	f2fs_hash_t name_hash;
+	unsigned int max_depth;
+	unsigned int level;
+
+	if (npages == 0)
+		return NULL;
+
+	*res_page = NULL;
+
+	name_hash = f2fs_dentry_hash(name, namelen);
+	max_depth = F2FS_I(dir)->i_current_depth;
+
+	for (level = 0; level < max_depth; level++) {
+		de = find_in_level(dir, level, name,
+				namelen, name_hash, res_page);
+		if (de)
+			break;
+	}
+	if (!de && F2FS_I(dir)->chash != name_hash) {
+		F2FS_I(dir)->chash = name_hash;
+		F2FS_I(dir)->clevel = level - 1;
+	}
+	return de;
+}
+
+struct f2fs_dir_entry *f2fs_parent_dir(struct inode *dir, struct page **p)
+{
+	struct page *page = NULL;
+	struct f2fs_dir_entry *de = NULL;
+	struct f2fs_dentry_block *dentry_blk = NULL;
+
+	page = get_lock_data_page(dir, 0);
+	if (IS_ERR(page))
+		return NULL;
+
+	dentry_blk = kmap(page);
+	de = &dentry_blk->dentry[1];
+	*p = page;
+	unlock_page(page);
+	return de;
+}
+
+ino_t f2fs_inode_by_name(struct inode *dir, struct qstr *qstr)
+{
+	ino_t res = 0;
+	struct f2fs_dir_entry *de;
+	struct page *page;
+
+	de = f2fs_find_entry(dir, qstr, &page);
+	if (de) {
+		res = le32_to_cpu(de->ino);
+		kunmap(page);
+		f2fs_put_page(page, 0);
+	}
+
+	return res;
+}
+
+void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de,
+		struct page *page, struct inode *inode)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
+
+	mutex_lock_op(sbi, DENTRY_OPS);
+	lock_page(page);
+	wait_on_page_writeback(page);
+	de->ino = cpu_to_le32(inode->i_ino);
+	set_de_type(de, inode);
+	kunmap(page);
+	set_page_dirty(page);
+	dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+	mark_inode_dirty(dir);
+	f2fs_put_page(page, 1);
+	mutex_unlock_op(sbi, DENTRY_OPS);
+}
+
+void init_dent_inode(struct dentry *dentry, struct page *ipage)
+{
+	struct inode *dir = dentry->d_parent->d_inode;
+	struct f2fs_node *rn;
+
+	if (IS_ERR(ipage))
+		return;
+
+	wait_on_page_writeback(ipage);
+
+	/* copy dentry info. to this inode page */
+	rn = (struct f2fs_node *)page_address(ipage);
+	rn->i.i_pino = cpu_to_le32(dir->i_ino);
+	rn->i.i_namelen = cpu_to_le32(dentry->d_name.len);
+	memcpy(rn->i.i_name, dentry->d_name.name, dentry->d_name.len);
+	set_page_dirty(ipage);
+}
+
+static int init_inode_metadata(struct inode *inode, struct dentry *dentry)
+{
+	struct inode *dir = dentry->d_parent->d_inode;
+
+	if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) {
+		int err;
+		err = new_inode_page(inode, dentry);
+		if (err)
+			return err;
+
+		if (S_ISDIR(inode->i_mode)) {
+			err = f2fs_make_empty(inode, dir);
+			if (err) {
+				remove_inode_page(inode);
+				return err;
+			}
+		}
+
+		err = f2fs_init_acl(inode, dir);
+		if (err) {
+			remove_inode_page(inode);
+			return err;
+		}
+	} else {
+		struct page *ipage;
+		ipage = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino);
+		if (IS_ERR(ipage))
+			return PTR_ERR(ipage);
+		init_dent_inode(dentry, ipage);
+		f2fs_put_page(ipage, 1);
+	}
+	if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) {
+		inc_nlink(inode);
+		f2fs_write_inode(inode, NULL);
+	}
+	return 0;
+}
+
+static void update_parent_metadata(struct inode *dir, struct inode *inode,
+						unsigned int current_depth)
+{
+	bool need_dir_update = false;
+
+	if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) {
+		if (S_ISDIR(inode->i_mode)) {
+			inc_nlink(dir);
+			need_dir_update = true;
+		}
+		clear_inode_flag(F2FS_I(inode), FI_NEW_INODE);
+	}
+	dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+	if (F2FS_I(dir)->i_current_depth != current_depth) {
+		F2FS_I(dir)->i_current_depth = current_depth;
+		need_dir_update = true;
+	}
+
+	if (need_dir_update)
+		f2fs_write_inode(dir, NULL);
+	else
+		mark_inode_dirty(dir);
+
+	if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK))
+		clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
+}
+
+static int room_for_filename(struct f2fs_dentry_block *dentry_blk, int slots)
+{
+	int bit_start = 0;
+	int zero_start, zero_end;
+next:
+	zero_start = find_next_zero_bit_le(&dentry_blk->dentry_bitmap,
+						NR_DENTRY_IN_BLOCK,
+						bit_start);
+	if (zero_start >= NR_DENTRY_IN_BLOCK)
+		return NR_DENTRY_IN_BLOCK;
+
+	zero_end = find_next_bit_le(&dentry_blk->dentry_bitmap,
+						NR_DENTRY_IN_BLOCK,
+						zero_start);
+	if (zero_end - zero_start >= slots)
+		return zero_start;
+
+	bit_start = zero_end + 1;
+
+	if (zero_end + 1 >= NR_DENTRY_IN_BLOCK)
+		return NR_DENTRY_IN_BLOCK;
+	goto next;
+}
+
+int f2fs_add_link(struct dentry *dentry, struct inode *inode)
+{
+	unsigned int bit_pos;
+	unsigned int level;
+	unsigned int current_depth;
+	unsigned long bidx, block;
+	f2fs_hash_t dentry_hash;
+	struct f2fs_dir_entry *de;
+	unsigned int nbucket, nblock;
+	struct inode *dir = dentry->d_parent->d_inode;
+	struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
+	const char *name = dentry->d_name.name;
+	int namelen = dentry->d_name.len;
+	struct page *dentry_page = NULL;
+	struct f2fs_dentry_block *dentry_blk = NULL;
+	int slots = (namelen + F2FS_NAME_LEN - 1) / F2FS_NAME_LEN;
+	int err = 0;
+	int i;
+
+	dentry_hash = f2fs_dentry_hash(name, dentry->d_name.len);
+	level = 0;
+	current_depth = F2FS_I(dir)->i_current_depth;
+	if (F2FS_I(dir)->chash == dentry_hash) {
+		level = F2FS_I(dir)->clevel;
+		F2FS_I(dir)->chash = 0;
+	}
+
+start:
+	if (current_depth == MAX_DIR_HASH_DEPTH)
+		return -ENOSPC;
+
+	/* Increase the depth, if required */
+	if (level == current_depth)
+		++current_depth;
+
+	nbucket = dir_buckets(level);
+	nblock = bucket_blocks(level);
+
+	bidx = dir_block_index(level, (dentry_hash % nbucket));
+
+	for (block = bidx; block <= (bidx + nblock - 1); block++) {
+		mutex_lock_op(sbi, DENTRY_OPS);
+		dentry_page = get_new_data_page(dir, block, true);
+		if (IS_ERR(dentry_page)) {
+			mutex_unlock_op(sbi, DENTRY_OPS);
+			return PTR_ERR(dentry_page);
+		}
+
+		dentry_blk = kmap(dentry_page);
+		bit_pos = room_for_filename(dentry_blk, slots);
+		if (bit_pos < NR_DENTRY_IN_BLOCK)
+			goto add_dentry;
+
+		kunmap(dentry_page);
+		f2fs_put_page(dentry_page, 1);
+		mutex_unlock_op(sbi, DENTRY_OPS);
+	}
+
+	/* Move to next level to find the empty slot for new dentry */
+	++level;
+	goto start;
+add_dentry:
+	err = init_inode_metadata(inode, dentry);
+	if (err)
+		goto fail;
+
+	wait_on_page_writeback(dentry_page);
+
+	de = &dentry_blk->dentry[bit_pos];
+	de->hash_code = cpu_to_le32(dentry_hash);
+	de->name_len = cpu_to_le16(namelen);
+	memcpy(dentry_blk->filename[bit_pos], name, namelen);
+	de->ino = cpu_to_le32(inode->i_ino);
+	set_de_type(de, inode);
+	for (i = 0; i < slots; i++)
+		test_and_set_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
+	set_page_dirty(dentry_page);
+	update_parent_metadata(dir, inode, current_depth);
+fail:
+	kunmap(dentry_page);
+	f2fs_put_page(dentry_page, 1);
+	mutex_unlock_op(sbi, DENTRY_OPS);
+	return err;
+}
+
+/**
+ * It only removes the dentry from the dentry page,corresponding name
+ * entry in name page does not need to be touched during deletion.
+ */
+void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
+						struct inode *inode)
+{
+	struct	f2fs_dentry_block *dentry_blk;
+	unsigned int bit_pos;
+	struct address_space *mapping = page->mapping;
+	struct inode *dir = mapping->host;
+	struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
+	int slots = (le16_to_cpu(dentry->name_len) + F2FS_NAME_LEN - 1) /
+							F2FS_NAME_LEN;
+	void *kaddr = page_address(page);
+	int i;
+
+	mutex_lock_op(sbi, DENTRY_OPS);
+
+	lock_page(page);
+	wait_on_page_writeback(page);
+
+	dentry_blk = (struct f2fs_dentry_block *)kaddr;
+	bit_pos = dentry - (struct f2fs_dir_entry *)dentry_blk->dentry;
+	for (i = 0; i < slots; i++)
+		test_and_clear_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
+
+	/* Let's check and deallocate this dentry page */
+	bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
+			NR_DENTRY_IN_BLOCK,
+			0);
+	kunmap(page); /* kunmap - pair of f2fs_find_entry */
+	set_page_dirty(page);
+
+	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+
+	if (inode && S_ISDIR(inode->i_mode)) {
+		drop_nlink(dir);
+		f2fs_write_inode(dir, NULL);
+	} else {
+		mark_inode_dirty(dir);
+	}
+
+	if (inode) {
+		inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+		drop_nlink(inode);
+		if (S_ISDIR(inode->i_mode)) {
+			drop_nlink(inode);
+			i_size_write(inode, 0);
+		}
+		f2fs_write_inode(inode, NULL);
+		if (inode->i_nlink == 0)
+			add_orphan_inode(sbi, inode->i_ino);
+	}
+
+	if (bit_pos == NR_DENTRY_IN_BLOCK) {
+		loff_t page_offset;
+		truncate_hole(dir, page->index, page->index + 1);
+		clear_page_dirty_for_io(page);
+		ClearPageUptodate(page);
+		dec_page_count(sbi, F2FS_DIRTY_DENTS);
+		inode_dec_dirty_dents(dir);
+		page_offset = page->index << PAGE_CACHE_SHIFT;
+		f2fs_put_page(page, 1);
+	} else {
+		f2fs_put_page(page, 1);
+	}
+	mutex_unlock_op(sbi, DENTRY_OPS);
+}
+
+int f2fs_make_empty(struct inode *inode, struct inode *parent)
+{
+	struct page *dentry_page;
+	struct f2fs_dentry_block *dentry_blk;
+	struct f2fs_dir_entry *de;
+	void *kaddr;
+
+	dentry_page = get_new_data_page(inode, 0, true);
+	if (IS_ERR(dentry_page))
+		return PTR_ERR(dentry_page);
+
+	kaddr = kmap_atomic(dentry_page);
+	dentry_blk = (struct f2fs_dentry_block *)kaddr;
+
+	de = &dentry_blk->dentry[0];
+	de->name_len = cpu_to_le16(1);
+	de->hash_code = 0;
+	de->ino = cpu_to_le32(inode->i_ino);
+	memcpy(dentry_blk->filename[0], ".", 1);
+	set_de_type(de, inode);
+
+	de = &dentry_blk->dentry[1];
+	de->hash_code = 0;
+	de->name_len = cpu_to_le16(2);
+	de->ino = cpu_to_le32(parent->i_ino);
+	memcpy(dentry_blk->filename[1], "..", 2);
+	set_de_type(de, inode);
+
+	test_and_set_bit_le(0, &dentry_blk->dentry_bitmap);
+	test_and_set_bit_le(1, &dentry_blk->dentry_bitmap);
+	kunmap_atomic(kaddr);
+
+	set_page_dirty(dentry_page);
+	f2fs_put_page(dentry_page, 1);
+	return 0;
+}
+
+bool f2fs_empty_dir(struct inode *dir)
+{
+	unsigned long bidx;
+	struct page *dentry_page;
+	unsigned int bit_pos;
+	struct	f2fs_dentry_block *dentry_blk;
+	unsigned long nblock = dir_blocks(dir);
+
+	for (bidx = 0; bidx < nblock; bidx++) {
+		void *kaddr;
+		dentry_page = get_lock_data_page(dir, bidx);
+		if (IS_ERR(dentry_page)) {
+			if (PTR_ERR(dentry_page) == -ENOENT)
+				continue;
+			else
+				return false;
+		}
+
+		kaddr = kmap_atomic(dentry_page);
+		dentry_blk = (struct f2fs_dentry_block *)kaddr;
+		if (bidx == 0)
+			bit_pos = 2;
+		else
+			bit_pos = 0;
+		bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
+						NR_DENTRY_IN_BLOCK,
+						bit_pos);
+		kunmap_atomic(kaddr);
+
+		f2fs_put_page(dentry_page, 1);
+
+		if (bit_pos < NR_DENTRY_IN_BLOCK)
+			return false;
+	}
+	return true;
+}
+
+static int f2fs_readdir(struct file *file, void *dirent, filldir_t filldir)
+{
+	unsigned long pos = file->f_pos;
+	struct inode *inode = file->f_dentry->d_inode;
+	unsigned long npages = dir_blocks(inode);
+	unsigned char *types = NULL;
+	unsigned int bit_pos = 0, start_bit_pos = 0;
+	int over = 0;
+	struct f2fs_dentry_block *dentry_blk = NULL;
+	struct f2fs_dir_entry *de = NULL;
+	struct page *dentry_page = NULL;
+	unsigned int n = 0;
+	unsigned char d_type = DT_UNKNOWN;
+	int slots;
+
+	types = f2fs_filetype_table;
+	bit_pos = (pos % NR_DENTRY_IN_BLOCK);
+	n = (pos / NR_DENTRY_IN_BLOCK);
+
+	for ( ; n < npages; n++) {
+		dentry_page = get_lock_data_page(inode, n);
+		if (IS_ERR(dentry_page))
+			continue;
+
+		start_bit_pos = bit_pos;
+		dentry_blk = kmap(dentry_page);
+		while (bit_pos < NR_DENTRY_IN_BLOCK) {
+			d_type = DT_UNKNOWN;
+			bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
+							NR_DENTRY_IN_BLOCK,
+							bit_pos);
+			if (bit_pos >= NR_DENTRY_IN_BLOCK)
+				break;
+
+			de = &dentry_blk->dentry[bit_pos];
+			if (types && de->file_type < F2FS_FT_MAX)
+				d_type = types[de->file_type];
+
+			over = filldir(dirent,
+					dentry_blk->filename[bit_pos],
+					le16_to_cpu(de->name_len),
+					(n * NR_DENTRY_IN_BLOCK) + bit_pos,
+					le32_to_cpu(de->ino), d_type);
+			if (over) {
+				file->f_pos += bit_pos - start_bit_pos;
+				goto success;
+			}
+			slots = (le16_to_cpu(de->name_len) + F2FS_NAME_LEN - 1)
+								/ F2FS_NAME_LEN;
+			bit_pos += slots;
+		}
+		bit_pos = 0;
+		file->f_pos = (n + 1) * NR_DENTRY_IN_BLOCK;
+		kunmap(dentry_page);
+		f2fs_put_page(dentry_page, 1);
+		dentry_page = NULL;
+	}
+success:
+	if (dentry_page && !IS_ERR(dentry_page)) {
+		kunmap(dentry_page);
+		f2fs_put_page(dentry_page, 1);
+	}
+
+	return 0;
+}
+
+const struct file_operations f2fs_dir_operations = {
+	.llseek		= generic_file_llseek,
+	.read		= generic_read_dir,
+	.readdir	= f2fs_readdir,
+	.fsync		= f2fs_sync_file,
+	.unlocked_ioctl	= f2fs_ioctl,
+};
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
new file mode 100644
index 0000000..d3f5a70
--- /dev/null
+++ b/fs/f2fs/f2fs.h
@@ -0,0 +1,1061 @@
+/**
+ * fs/f2fs/f2fs.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _LINUX_F2FS_H
+#define _LINUX_F2FS_H
+
+#include <linux/types.h>
+#include <linux/page-flags.h>
+#include <linux/buffer_head.h>
+#include <linux/slab.h>
+#include <linux/crc32.h>
+#include <linux/magic.h>
+
+/*
+ * For mount options
+ */
+#define F2FS_MOUNT_BG_GC		0x00000001
+#define F2FS_MOUNT_DISABLE_ROLL_FORWARD	0x00000002
+#define F2FS_MOUNT_DISCARD		0x00000004
+#define F2FS_MOUNT_NOHEAP		0x00000008
+#define F2FS_MOUNT_XATTR_USER		0x00000010
+#define F2FS_MOUNT_POSIX_ACL		0x00000020
+#define F2FS_MOUNT_DISABLE_EXT_IDENTIFY	0x00000040
+
+#define clear_opt(sbi, option)	(sbi->mount_opt.opt &= ~F2FS_MOUNT_##option)
+#define set_opt(sbi, option)	(sbi->mount_opt.opt |= F2FS_MOUNT_##option)
+#define test_opt(sbi, option)	(sbi->mount_opt.opt & F2FS_MOUNT_##option)
+
+#define ver_after(a, b)	(typecheck(unsigned long long, a) &&		\
+		typecheck(unsigned long long, b) &&			\
+		((long long)((a) - (b)) > 0))
+
+typedef u64 block_t;
+typedef u32 nid_t;
+
+struct f2fs_mount_info {
+	unsigned int	opt;
+};
+
+static inline __u32 f2fs_crc32(void *buff, size_t len)
+{
+	return crc32_le(F2FS_SUPER_MAGIC, buff, len);
+}
+
+static inline bool f2fs_crc_valid(__u32 blk_crc, void *buff, size_t buff_size)
+{
+	return f2fs_crc32(buff, buff_size) == blk_crc;
+}
+
+/*
+ * For checkpoint manager
+ */
+enum {
+	NAT_BITMAP,
+	SIT_BITMAP
+};
+
+/* for the list of orphan inodes */
+struct orphan_inode_entry {
+	struct list_head list;	/* list head */
+	nid_t ino;		/* inode number */
+};
+
+/* for the list of directory inodes */
+struct dir_inode_entry {
+	struct list_head list;	/* list head */
+	struct inode *inode;	/* vfs inode pointer */
+};
+
+/* for the list of fsync inodes, used only during recovery */
+struct fsync_inode_entry {
+	struct list_head list;	/* list head */
+	struct inode *inode;	/* vfs inode pointer */
+	block_t blkaddr;	/* block address locating the last inode */
+};
+
+#define nats_in_cursum(sum)		(le16_to_cpu(sum->n_nats))
+#define sits_in_cursum(sum)		(le16_to_cpu(sum->n_sits))
+
+#define nat_in_journal(sum, i)		(sum->nat_j.entries[i].ne)
+#define nid_in_journal(sum, i)		(sum->nat_j.entries[i].nid)
+#define sit_in_journal(sum, i)		(sum->sit_j.entries[i].se)
+#define segno_in_journal(sum, i)	(sum->sit_j.entries[i].segno)
+
+static inline int update_nats_in_cursum(struct f2fs_summary_block *rs, int i)
+{
+	int before = nats_in_cursum(rs);
+	rs->n_nats = cpu_to_le16(before + i);
+	return before;
+}
+
+static inline int update_sits_in_cursum(struct f2fs_summary_block *rs, int i)
+{
+	int before = sits_in_cursum(rs);
+	rs->n_sits = cpu_to_le16(before + i);
+	return before;
+}
+
+/*
+ * For INODE and NODE manager
+ */
+#define XATTR_NODE_OFFSET	(-1)	/*
+					 * store xattrs to one node block per
+					 * file keeping -1 as its node offset to
+					 * distinguish from index node blocks.
+					 */
+#define RDONLY_NODE		1	/*
+					 * specify a read-only mode when getting
+					 * a node block. 0 is read-write mode.
+					 * used by get_dnode_of_data().
+					 */
+#define F2FS_LINK_MAX		32000	/* maximum link count per file */
+
+/* for in-memory extent cache entry */
+struct extent_info {
+	rwlock_t ext_lock;	/* rwlock for consistency */
+	unsigned int fofs;	/* start offset in a file */
+	u32 blk_addr;		/* start block address of the extent */
+	unsigned int len;	/* lenth of the extent */
+};
+
+/*
+ * i_advise uses FADVISE_XXX_BIT. We can add additional hints later.
+ */
+#define FADVISE_COLD_BIT	0x01
+
+struct f2fs_inode_info {
+	struct inode vfs_inode;		/* serve a vfs inode */
+	unsigned long i_flags;		/* keep an inode flags for ioctl */
+	unsigned char i_advise;		/* use to give file attribute hints */
+	unsigned int i_current_depth;	/* use only in directory structure */
+	umode_t i_acl_mode;		/* keep file acl mode temporarily */
+
+	/* Use below internally in f2fs*/
+	unsigned long flags;		/* use to pass per-file flags */
+	unsigned long long data_version;/* lastes version of data for fsync */
+	atomic_t dirty_dents;		/* # of dirty dentry pages */
+	f2fs_hash_t chash;		/* hash value of given file name */
+	unsigned int clevel;		/* maximum level of given file name */
+	nid_t i_xattr_nid;		/* node id that contains xattrs */
+	struct extent_info ext;		/* in-memory extent cache entry */
+};
+
+static inline void get_extent_info(struct extent_info *ext,
+					struct f2fs_extent i_ext)
+{
+	write_lock(&ext->ext_lock);
+	ext->fofs = le32_to_cpu(i_ext.fofs);
+	ext->blk_addr = le32_to_cpu(i_ext.blk_addr);
+	ext->len = le32_to_cpu(i_ext.len);
+	write_unlock(&ext->ext_lock);
+}
+
+static inline void set_raw_extent(struct extent_info *ext,
+					struct f2fs_extent *i_ext)
+{
+	read_lock(&ext->ext_lock);
+	i_ext->fofs = cpu_to_le32(ext->fofs);
+	i_ext->blk_addr = cpu_to_le32(ext->blk_addr);
+	i_ext->len = cpu_to_le32(ext->len);
+	read_unlock(&ext->ext_lock);
+}
+
+struct f2fs_nm_info {
+	block_t nat_blkaddr;		/* base disk address of NAT */
+	nid_t max_nid;			/* maximum possible node ids */
+	nid_t init_scan_nid;		/* the first nid to be scanned */
+	nid_t next_scan_nid;		/* the next nid to be scanned */
+
+	/* NAT cache management */
+	struct radix_tree_root nat_root;/* root of the nat entry cache */
+	rwlock_t nat_tree_lock;		/* protect nat_tree_lock */
+	unsigned int nat_cnt;		/* the # of cached nat entries */
+	struct list_head nat_entries;	/* cached nat entry list (clean) */
+	struct list_head dirty_nat_entries; /* cached nat entry list (dirty) */
+
+	/* free node ids management */
+	struct list_head free_nid_list;	/* a list for free nids */
+	spinlock_t free_nid_list_lock;	/* protect free nid list */
+	unsigned int fcnt;		/* the number of free node id */
+	struct mutex build_lock;	/* lock for build free nids */
+
+	/* for checkpoint */
+	char *nat_bitmap;		/* NAT bitmap pointer */
+	int bitmap_size;		/* bitmap size */
+};
+
+/*
+ * this structure is used as one of function parameters.
+ * all the information are dedicated to a given direct node block determined
+ * by the data offset in a file.
+ */
+struct dnode_of_data {
+	struct inode *inode;		/* vfs inode pointer */
+	struct page *inode_page;	/* its inode page, NULL is possible */
+	struct page *node_page;		/* cached direct node page */
+	nid_t nid;			/* node id of the direct node block */
+	unsigned int ofs_in_node;	/* data offset in the node page */
+	bool inode_page_locked;		/* inode page is locked or not */
+	block_t	data_blkaddr;		/* block address of the node block */
+};
+
+static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
+		struct page *ipage, struct page *npage, nid_t nid)
+{
+	dn->inode = inode;
+	dn->inode_page = ipage;
+	dn->node_page = npage;
+	dn->nid = nid;
+	dn->inode_page_locked = 0;
+}
+
+/*
+ * For SIT manager
+ *
+ * By default, there are 6 active log areas across the whole main area.
+ * When considering hot and cold data separation to reduce cleaning overhead,
+ * we split 3 for data logs and 3 for node logs as hot, warm, and cold types,
+ * respectively.
+ * In the current design, you should not change the numbers intentionally.
+ * Instead, as a mount option such as active_logs=x, you can use 2, 4, and 6
+ * logs individually according to the underlying devices. (default: 6)
+ * Just in case, on-disk layout covers maximum 16 logs that consist of 8 for
+ * data and 8 for node logs.
+ */
+#define	NR_CURSEG_DATA_TYPE	(3)
+#define NR_CURSEG_NODE_TYPE	(3)
+#define NR_CURSEG_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
+
+enum {
+	CURSEG_HOT_DATA	= 0,	/* directory entry blocks */
+	CURSEG_WARM_DATA,	/* data blocks */
+	CURSEG_COLD_DATA,	/* multimedia or GCed data blocks */
+	CURSEG_HOT_NODE,	/* direct node blocks of directory files */
+	CURSEG_WARM_NODE,	/* direct node blocks of normal files */
+	CURSEG_COLD_NODE,	/* indirect node blocks */
+	NO_CHECK_TYPE
+};
+
+struct f2fs_sm_info {
+	struct sit_info *sit_info;		/* whole segment information */
+	struct free_segmap_info *free_info;	/* free segment information */
+	struct dirty_seglist_info *dirty_info;	/* dirty segment information */
+	struct curseg_info *curseg_array;	/* active segment information */
+
+	struct list_head wblist_head;	/* list of under-writeback pages */
+	spinlock_t wblist_lock;		/* lock for checkpoint */
+
+	block_t seg0_blkaddr;		/* block address of 0'th segment */
+	block_t main_blkaddr;		/* start block address of main area */
+	block_t ssa_blkaddr;		/* start block address of SSA area */
+
+	unsigned int segment_count;	/* total # of segments */
+	unsigned int main_segments;	/* # of segments in main area */
+	unsigned int reserved_segments;	/* # of reserved segments */
+	unsigned int ovp_segments;	/* # of overprovision segments */
+};
+
+/*
+ * For directory operation
+ */
+#define	NODE_DIR1_BLOCK		(ADDRS_PER_INODE + 1)
+#define	NODE_DIR2_BLOCK		(ADDRS_PER_INODE + 2)
+#define	NODE_IND1_BLOCK		(ADDRS_PER_INODE + 3)
+#define	NODE_IND2_BLOCK		(ADDRS_PER_INODE + 4)
+#define	NODE_DIND_BLOCK		(ADDRS_PER_INODE + 5)
+
+/*
+ * For superblock
+ */
+/*
+ * COUNT_TYPE for monitoring
+ *
+ * f2fs monitors the number of several block types such as on-writeback,
+ * dirty dentry blocks, dirty node blocks, and dirty meta blocks.
+ */
+enum count_type {
+	F2FS_WRITEBACK,
+	F2FS_DIRTY_DENTS,
+	F2FS_DIRTY_NODES,
+	F2FS_DIRTY_META,
+	NR_COUNT_TYPE,
+};
+
+/*
+ * FS_LOCK nesting subclasses for the lock validator:
+ *
+ * The locking order between these classes is
+ * RENAME -> DENTRY_OPS -> DATA_WRITE -> DATA_NEW
+ *    -> DATA_TRUNC -> NODE_WRITE -> NODE_NEW -> NODE_TRUNC
+ */
+enum lock_type {
+	RENAME,		/* for renaming operations */
+	DENTRY_OPS,	/* for directory operations */
+	DATA_WRITE,	/* for data write */
+	DATA_NEW,	/* for data allocation */
+	DATA_TRUNC,	/* for data truncate */
+	NODE_NEW,	/* for node allocation */
+	NODE_TRUNC,	/* for node truncate */
+	NODE_WRITE,	/* for node write */
+	NR_LOCK_TYPE,
+};
+
+/*
+ * 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.
+ * NODE			Node pages. It operates as async mode.
+ * META			FS metadata pages such as SIT, NAT, CP.
+ * NR_PAGE_TYPE		The number of page types.
+ * META_FLUSH		Make sure the previous pages are written
+ *			with waiting the bio's completion
+ * ...			Only can be used with META.
+ */
+enum page_type {
+	DATA,
+	NODE,
+	META,
+	NR_PAGE_TYPE,
+	META_FLUSH,
+};
+
+struct f2fs_sb_info {
+	struct super_block *sb;			/* pointer to VFS super block */
+	struct buffer_head *raw_super_buf;	/* buffer head of raw sb */
+	struct f2fs_super_block *raw_super;	/* raw super block pointer */
+	int s_dirty;				/* dirty flag for checkpoint */
+
+	/* for node-related operations */
+	struct f2fs_nm_info *nm_info;		/* node manager */
+	struct inode *node_inode;		/* cache node blocks */
+
+	/* for segment-related operations */
+	struct f2fs_sm_info *sm_info;		/* segment manager */
+	struct bio *bio[NR_PAGE_TYPE];		/* bios to merge */
+	sector_t last_block_in_bio[NR_PAGE_TYPE];	/* last block number */
+	struct rw_semaphore bio_sem;		/* IO semaphore */
+
+	/* for checkpoint */
+	struct f2fs_checkpoint *ckpt;		/* raw checkpoint pointer */
+	struct inode *meta_inode;		/* cache meta blocks */
+	struct mutex cp_mutex;			/* for checkpoint procedure */
+	struct mutex fs_lock[NR_LOCK_TYPE];	/* for blocking FS operations */
+	struct mutex write_inode;		/* mutex for write inode */
+	struct mutex writepages;		/* mutex for writepages() */
+	int por_doing;				/* recovery is doing or not */
+
+	/* for orphan inode management */
+	struct list_head orphan_inode_list;	/* orphan inode list */
+	struct mutex orphan_inode_mutex;	/* for orphan inode list */
+	unsigned int n_orphans;			/* # of orphan inodes */
+
+	/* for directory inode management */
+	struct list_head dir_inode_list;	/* dir inode list */
+	spinlock_t dir_inode_lock;		/* for dir inode list lock */
+	unsigned int n_dirty_dirs;		/* # of dir inodes */
+
+	/* basic file system units */
+	unsigned int log_sectors_per_block;	/* log2 sectors per block */
+	unsigned int log_blocksize;		/* log2 block size */
+	unsigned int blocksize;			/* block size */
+	unsigned int root_ino_num;		/* root inode number*/
+	unsigned int node_ino_num;		/* node inode number*/
+	unsigned int meta_ino_num;		/* meta inode number*/
+	unsigned int log_blocks_per_seg;	/* log2 blocks per segment */
+	unsigned int blocks_per_seg;		/* blocks per segment */
+	unsigned int segs_per_sec;		/* segments per section */
+	unsigned int secs_per_zone;		/* sections per zone */
+	unsigned int total_sections;		/* total section count */
+	unsigned int total_node_count;		/* total node block count */
+	unsigned int total_valid_node_count;	/* valid node block count */
+	unsigned int total_valid_inode_count;	/* valid inode count */
+	int active_logs;			/* # of active logs */
+
+	block_t user_block_count;		/* # of user blocks */
+	block_t total_valid_block_count;	/* # of valid blocks */
+	block_t alloc_valid_block_count;	/* # of allocated blocks */
+	block_t last_valid_block_count;		/* for recovery */
+	u32 s_next_generation;			/* for NFS support */
+	atomic_t nr_pages[NR_COUNT_TYPE];	/* # of pages, see count_type */
+
+	struct f2fs_mount_info mount_opt;	/* mount options */
+
+	/* for cleaning operations */
+	struct mutex gc_mutex;			/* mutex for GC */
+	struct f2fs_gc_kthread	*gc_thread;	/* GC thread */
+
+	/*
+	 * for stat information.
+	 * one is for the LFS mode, and the other is for the SSR mode.
+	 */
+	struct f2fs_stat_info *stat_info;	/* FS status information */
+	unsigned int segment_count[2];		/* # of allocated segments */
+	unsigned int block_count[2];		/* # of allocated blocks */
+	unsigned int last_victim[2];		/* last victim segment # */
+	int total_hit_ext, read_hit_ext;	/* extent cache hit ratio */
+	int bg_gc;				/* background gc calls */
+	spinlock_t stat_lock;			/* lock for stat operations */
+};
+
+/*
+ * Inline functions
+ */
+static inline struct f2fs_inode_info *F2FS_I(struct inode *inode)
+{
+	return container_of(inode, struct f2fs_inode_info, vfs_inode);
+}
+
+static inline struct f2fs_sb_info *F2FS_SB(struct super_block *sb)
+{
+	return sb->s_fs_info;
+}
+
+static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi)
+{
+	return (struct f2fs_super_block *)(sbi->raw_super);
+}
+
+static inline struct f2fs_checkpoint *F2FS_CKPT(struct f2fs_sb_info *sbi)
+{
+	return (struct f2fs_checkpoint *)(sbi->ckpt);
+}
+
+static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi)
+{
+	return (struct f2fs_nm_info *)(sbi->nm_info);
+}
+
+static inline struct f2fs_sm_info *SM_I(struct f2fs_sb_info *sbi)
+{
+	return (struct f2fs_sm_info *)(sbi->sm_info);
+}
+
+static inline struct sit_info *SIT_I(struct f2fs_sb_info *sbi)
+{
+	return (struct sit_info *)(SM_I(sbi)->sit_info);
+}
+
+static inline struct free_segmap_info *FREE_I(struct f2fs_sb_info *sbi)
+{
+	return (struct free_segmap_info *)(SM_I(sbi)->free_info);
+}
+
+static inline struct dirty_seglist_info *DIRTY_I(struct f2fs_sb_info *sbi)
+{
+	return (struct dirty_seglist_info *)(SM_I(sbi)->dirty_info);
+}
+
+static inline void F2FS_SET_SB_DIRT(struct f2fs_sb_info *sbi)
+{
+	sbi->s_dirty = 1;
+}
+
+static inline void F2FS_RESET_SB_DIRT(struct f2fs_sb_info *sbi)
+{
+	sbi->s_dirty = 0;
+}
+
+static inline void mutex_lock_op(struct f2fs_sb_info *sbi, enum lock_type t)
+{
+	mutex_lock_nested(&sbi->fs_lock[t], t);
+}
+
+static inline void mutex_unlock_op(struct f2fs_sb_info *sbi, enum lock_type t)
+{
+	mutex_unlock(&sbi->fs_lock[t]);
+}
+
+/*
+ * Check whether the given nid is within node id range.
+ */
+static inline void check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
+{
+	BUG_ON((nid >= NM_I(sbi)->max_nid));
+}
+
+#define F2FS_DEFAULT_ALLOCATED_BLOCKS	1
+
+/*
+ * Check whether the inode has blocks or not
+ */
+static inline int F2FS_HAS_BLOCKS(struct inode *inode)
+{
+	if (F2FS_I(inode)->i_xattr_nid)
+		return (inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS + 1);
+	else
+		return (inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS);
+}
+
+static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
+				 struct inode *inode, blkcnt_t count)
+{
+	block_t	valid_block_count;
+
+	spin_lock(&sbi->stat_lock);
+	valid_block_count =
+		sbi->total_valid_block_count + (block_t)count;
+	if (valid_block_count > sbi->user_block_count) {
+		spin_unlock(&sbi->stat_lock);
+		return false;
+	}
+	inode->i_blocks += count;
+	sbi->total_valid_block_count = valid_block_count;
+	sbi->alloc_valid_block_count += (block_t)count;
+	spin_unlock(&sbi->stat_lock);
+	return true;
+}
+
+static inline int dec_valid_block_count(struct f2fs_sb_info *sbi,
+						struct inode *inode,
+						blkcnt_t count)
+{
+	spin_lock(&sbi->stat_lock);
+	BUG_ON(sbi->total_valid_block_count < (block_t) count);
+	BUG_ON(inode->i_blocks < count);
+	inode->i_blocks -= count;
+	sbi->total_valid_block_count -= (block_t)count;
+	spin_unlock(&sbi->stat_lock);
+	return 0;
+}
+
+static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
+{
+	atomic_inc(&sbi->nr_pages[count_type]);
+	F2FS_SET_SB_DIRT(sbi);
+}
+
+static inline void inode_inc_dirty_dents(struct inode *inode)
+{
+	atomic_inc(&F2FS_I(inode)->dirty_dents);
+}
+
+static inline void dec_page_count(struct f2fs_sb_info *sbi, int count_type)
+{
+	atomic_dec(&sbi->nr_pages[count_type]);
+}
+
+static inline void inode_dec_dirty_dents(struct inode *inode)
+{
+	atomic_dec(&F2FS_I(inode)->dirty_dents);
+}
+
+static inline int get_pages(struct f2fs_sb_info *sbi, int count_type)
+{
+	return atomic_read(&sbi->nr_pages[count_type]);
+}
+
+static inline block_t valid_user_blocks(struct f2fs_sb_info *sbi)
+{
+	block_t ret;
+	spin_lock(&sbi->stat_lock);
+	ret = sbi->total_valid_block_count;
+	spin_unlock(&sbi->stat_lock);
+	return ret;
+}
+
+static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag)
+{
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+
+	/* return NAT or SIT bitmap */
+	if (flag == NAT_BITMAP)
+		return le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
+	else if (flag == SIT_BITMAP)
+		return le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
+
+	return 0;
+}
+
+static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
+{
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	int offset = (flag == NAT_BITMAP) ? ckpt->sit_ver_bitmap_bytesize : 0;
+	return &ckpt->sit_nat_version_bitmap + offset;
+}
+
+static inline block_t __start_cp_addr(struct f2fs_sb_info *sbi)
+{
+	block_t start_addr;
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	unsigned long long ckpt_version = le64_to_cpu(ckpt->checkpoint_ver);
+
+	start_addr = le64_to_cpu(F2FS_RAW_SUPER(sbi)->cp_blkaddr);
+
+	/*
+	 * odd numbered checkpoint should at cp segment 0
+	 * and even segent must be at cp segment 1
+	 */
+	if (!(ckpt_version & 1))
+		start_addr += sbi->blocks_per_seg;
+
+	return start_addr;
+}
+
+static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi)
+{
+	return le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
+}
+
+static inline bool inc_valid_node_count(struct f2fs_sb_info *sbi,
+						struct inode *inode,
+						unsigned int count)
+{
+	block_t	valid_block_count;
+	unsigned int valid_node_count;
+
+	spin_lock(&sbi->stat_lock);
+
+	valid_block_count = sbi->total_valid_block_count + (block_t)count;
+	sbi->alloc_valid_block_count += (block_t)count;
+	valid_node_count = sbi->total_valid_node_count + count;
+
+	if (valid_block_count > sbi->user_block_count) {
+		spin_unlock(&sbi->stat_lock);
+		return false;
+	}
+
+	if (valid_node_count > sbi->total_node_count) {
+		spin_unlock(&sbi->stat_lock);
+		return false;
+	}
+
+	if (inode)
+		inode->i_blocks += count;
+	sbi->total_valid_node_count = valid_node_count;
+	sbi->total_valid_block_count = valid_block_count;
+	spin_unlock(&sbi->stat_lock);
+
+	return true;
+}
+
+static inline void dec_valid_node_count(struct f2fs_sb_info *sbi,
+						struct inode *inode,
+						unsigned int count)
+{
+	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);
+
+	inode->i_blocks -= count;
+	sbi->total_valid_node_count -= count;
+	sbi->total_valid_block_count -= (block_t)count;
+
+	spin_unlock(&sbi->stat_lock);
+}
+
+static inline unsigned int valid_node_count(struct f2fs_sb_info *sbi)
+{
+	unsigned int ret;
+	spin_lock(&sbi->stat_lock);
+	ret = sbi->total_valid_node_count;
+	spin_unlock(&sbi->stat_lock);
+	return ret;
+}
+
+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);
+	sbi->total_valid_inode_count++;
+	spin_unlock(&sbi->stat_lock);
+}
+
+static inline int dec_valid_inode_count(struct f2fs_sb_info *sbi)
+{
+	spin_lock(&sbi->stat_lock);
+	BUG_ON(!sbi->total_valid_inode_count);
+	sbi->total_valid_inode_count--;
+	spin_unlock(&sbi->stat_lock);
+	return 0;
+}
+
+static inline unsigned int valid_inode_count(struct f2fs_sb_info *sbi)
+{
+	unsigned int ret;
+	spin_lock(&sbi->stat_lock);
+	ret = sbi->total_valid_inode_count;
+	spin_unlock(&sbi->stat_lock);
+	return ret;
+}
+
+static inline void f2fs_put_page(struct page *page, int unlock)
+{
+	if (!page || IS_ERR(page))
+		return;
+
+	if (unlock) {
+		BUG_ON(!PageLocked(page));
+		unlock_page(page);
+	}
+	page_cache_release(page);
+}
+
+static inline void f2fs_put_dnode(struct dnode_of_data *dn)
+{
+	if (dn->node_page)
+		f2fs_put_page(dn->node_page, 1);
+	if (dn->inode_page && dn->node_page != dn->inode_page)
+		f2fs_put_page(dn->inode_page, 0);
+	dn->node_page = NULL;
+	dn->inode_page = NULL;
+}
+
+static inline struct kmem_cache *f2fs_kmem_cache_create(const char *name,
+					size_t size, void (*ctor)(void *))
+{
+	return kmem_cache_create(name, size, 0, SLAB_RECLAIM_ACCOUNT, ctor);
+}
+
+#define RAW_IS_INODE(p)	((p)->footer.nid == (p)->footer.ino)
+
+static inline bool IS_INODE(struct page *page)
+{
+	struct f2fs_node *p = (struct f2fs_node *)page_address(page);
+	return RAW_IS_INODE(p);
+}
+
+static inline __le32 *blkaddr_in_node(struct f2fs_node *node)
+{
+	return RAW_IS_INODE(node) ? node->i.i_addr : node->dn.addr;
+}
+
+static inline block_t datablock_addr(struct page *node_page,
+		unsigned int offset)
+{
+	struct f2fs_node *raw_node;
+	__le32 *addr_array;
+	raw_node = (struct f2fs_node *)page_address(node_page);
+	addr_array = blkaddr_in_node(raw_node);
+	return le32_to_cpu(addr_array[offset]);
+}
+
+static inline int f2fs_test_bit(unsigned int nr, char *addr)
+{
+	int mask;
+
+	addr += (nr >> 3);
+	mask = 1 << (7 - (nr & 0x07));
+	return mask & *addr;
+}
+
+static inline int f2fs_set_bit(unsigned int nr, char *addr)
+{
+	int mask;
+	int ret;
+
+	addr += (nr >> 3);
+	mask = 1 << (7 - (nr & 0x07));
+	ret = mask & *addr;
+	*addr |= mask;
+	return ret;
+}
+
+static inline int f2fs_clear_bit(unsigned int nr, char *addr)
+{
+	int mask;
+	int ret;
+
+	addr += (nr >> 3);
+	mask = 1 << (7 - (nr & 0x07));
+	ret = mask & *addr;
+	*addr &= ~mask;
+	return ret;
+}
+
+/* used for f2fs_inode_info->flags */
+enum {
+	FI_NEW_INODE,		/* indicate newly allocated inode */
+	FI_NEED_CP,		/* need to do checkpoint during fsync */
+	FI_INC_LINK,		/* need to increment i_nlink */
+	FI_ACL_MODE,		/* indicate acl mode */
+	FI_NO_ALLOC,		/* should not allocate any blocks */
+};
+
+static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag)
+{
+	set_bit(flag, &fi->flags);
+}
+
+static inline int is_inode_flag_set(struct f2fs_inode_info *fi, int flag)
+{
+	return test_bit(flag, &fi->flags);
+}
+
+static inline void clear_inode_flag(struct f2fs_inode_info *fi, int flag)
+{
+	clear_bit(flag, &fi->flags);
+}
+
+static inline void set_acl_inode(struct f2fs_inode_info *fi, umode_t mode)
+{
+	fi->i_acl_mode = mode;
+	set_inode_flag(fi, FI_ACL_MODE);
+}
+
+static inline int cond_clear_inode_flag(struct f2fs_inode_info *fi, int flag)
+{
+	if (is_inode_flag_set(fi, FI_ACL_MODE)) {
+		clear_inode_flag(fi, FI_ACL_MODE);
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * file.c
+ */
+int f2fs_sync_file(struct file *, loff_t, loff_t, int);
+void truncate_data_blocks(struct dnode_of_data *);
+void f2fs_truncate(struct inode *);
+int f2fs_setattr(struct dentry *, struct iattr *);
+int truncate_hole(struct inode *, pgoff_t, pgoff_t);
+long f2fs_ioctl(struct file *, unsigned int, unsigned long);
+
+/*
+ * inode.c
+ */
+void f2fs_set_inode_flags(struct inode *);
+struct inode *f2fs_iget_nowait(struct super_block *, unsigned long);
+struct inode *f2fs_iget(struct super_block *, unsigned long);
+void update_inode(struct inode *, struct page *);
+int f2fs_write_inode(struct inode *, struct writeback_control *);
+void f2fs_evict_inode(struct inode *);
+
+/*
+ * namei.c
+ */
+struct dentry *f2fs_get_parent(struct dentry *child);
+
+/*
+ * dir.c
+ */
+struct f2fs_dir_entry *f2fs_find_entry(struct inode *, struct qstr *,
+							struct page **);
+struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **);
+ino_t f2fs_inode_by_name(struct inode *, struct qstr *);
+void f2fs_set_link(struct inode *, struct f2fs_dir_entry *,
+				struct page *, struct inode *);
+void init_dent_inode(struct dentry *, struct page *);
+int f2fs_add_link(struct dentry *, struct inode *);
+void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *);
+int f2fs_make_empty(struct inode *, struct inode *);
+bool f2fs_empty_dir(struct inode *);
+
+/*
+ * super.c
+ */
+int f2fs_sync_fs(struct super_block *, int);
+
+/*
+ * hash.c
+ */
+f2fs_hash_t f2fs_dentry_hash(const char *, int);
+
+/*
+ * node.c
+ */
+struct dnode_of_data;
+struct node_info;
+
+int is_checkpointed_node(struct f2fs_sb_info *, nid_t);
+void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *);
+int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int);
+int truncate_inode_blocks(struct inode *, pgoff_t);
+int remove_inode_page(struct inode *);
+int new_inode_page(struct inode *, struct dentry *);
+struct page *new_node_page(struct dnode_of_data *, unsigned int);
+void ra_node_page(struct f2fs_sb_info *, nid_t);
+struct page *get_node_page(struct f2fs_sb_info *, pgoff_t);
+struct page *get_node_page_ra(struct page *, int);
+void sync_inode_page(struct dnode_of_data *);
+int sync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *);
+bool alloc_nid(struct f2fs_sb_info *, nid_t *);
+void alloc_nid_done(struct f2fs_sb_info *, nid_t);
+void alloc_nid_failed(struct f2fs_sb_info *, nid_t);
+void recover_node_page(struct f2fs_sb_info *, struct page *,
+		struct f2fs_summary *, struct node_info *, block_t);
+int recover_inode_page(struct f2fs_sb_info *, struct page *);
+int restore_node_summary(struct f2fs_sb_info *, unsigned int,
+				struct f2fs_summary_block *);
+void flush_nat_entries(struct f2fs_sb_info *);
+int build_node_manager(struct f2fs_sb_info *);
+void destroy_node_manager(struct f2fs_sb_info *);
+int create_node_manager_caches(void);
+void destroy_node_manager_caches(void);
+
+/*
+ * segment.c
+ */
+void f2fs_balance_fs(struct f2fs_sb_info *);
+void invalidate_blocks(struct f2fs_sb_info *, block_t);
+void locate_dirty_segment(struct f2fs_sb_info *, unsigned int);
+void clear_prefree_segments(struct f2fs_sb_info *);
+int npages_for_summary_flush(struct f2fs_sb_info *);
+void allocate_new_segments(struct f2fs_sb_info *);
+struct page *get_sum_page(struct f2fs_sb_info *, unsigned int);
+struct bio *f2fs_bio_alloc(struct block_device *, sector_t, int, gfp_t);
+void f2fs_submit_bio(struct f2fs_sb_info *, enum page_type, bool sync);
+int write_meta_page(struct f2fs_sb_info *, struct page *,
+					struct writeback_control *);
+void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int,
+					block_t, block_t *);
+void write_data_page(struct inode *, struct page *, struct dnode_of_data*,
+					block_t, block_t *);
+void rewrite_data_page(struct f2fs_sb_info *, struct page *, block_t);
+void recover_data_page(struct f2fs_sb_info *, struct page *,
+				struct f2fs_summary *, block_t, block_t);
+void rewrite_node_page(struct f2fs_sb_info *, struct page *,
+				struct f2fs_summary *, block_t, block_t);
+void write_data_summaries(struct f2fs_sb_info *, block_t);
+void write_node_summaries(struct f2fs_sb_info *, block_t);
+int lookup_journal_in_cursum(struct f2fs_summary_block *,
+					int, unsigned int, int);
+void flush_sit_entries(struct f2fs_sb_info *);
+int build_segment_manager(struct f2fs_sb_info *);
+void reset_victim_segmap(struct f2fs_sb_info *);
+void destroy_segment_manager(struct f2fs_sb_info *);
+
+/*
+ * checkpoint.c
+ */
+struct page *grab_meta_page(struct f2fs_sb_info *, pgoff_t);
+struct page *get_meta_page(struct f2fs_sb_info *, pgoff_t);
+long sync_meta_pages(struct f2fs_sb_info *, enum page_type, long);
+int check_orphan_space(struct f2fs_sb_info *);
+void add_orphan_inode(struct f2fs_sb_info *, nid_t);
+void remove_orphan_inode(struct f2fs_sb_info *, nid_t);
+int recover_orphan_inodes(struct f2fs_sb_info *);
+int get_valid_checkpoint(struct f2fs_sb_info *);
+void set_dirty_dir_page(struct inode *, struct page *);
+void remove_dirty_dir_inode(struct inode *);
+void sync_dirty_dir_inodes(struct f2fs_sb_info *);
+void block_operations(struct f2fs_sb_info *);
+void write_checkpoint(struct f2fs_sb_info *, bool, bool);
+void init_orphan_info(struct f2fs_sb_info *);
+int create_checkpoint_caches(void);
+void destroy_checkpoint_caches(void);
+
+/*
+ * data.c
+ */
+int reserve_new_block(struct dnode_of_data *);
+void update_extent_cache(block_t, struct dnode_of_data *);
+struct page *find_data_page(struct inode *, pgoff_t);
+struct page *get_lock_data_page(struct inode *, pgoff_t);
+struct page *get_new_data_page(struct inode *, pgoff_t, bool);
+int f2fs_readpage(struct f2fs_sb_info *, struct page *, block_t, int);
+int do_write_data_page(struct page *);
+
+/*
+ * gc.c
+ */
+int start_gc_thread(struct f2fs_sb_info *);
+void stop_gc_thread(struct f2fs_sb_info *);
+block_t start_bidx_of_node(unsigned int);
+int f2fs_gc(struct f2fs_sb_info *, int);
+void build_gc_manager(struct f2fs_sb_info *);
+int create_gc_caches(void);
+void destroy_gc_caches(void);
+
+/*
+ * recovery.c
+ */
+void recover_fsync_data(struct f2fs_sb_info *);
+bool space_for_roll_forward(struct f2fs_sb_info *);
+
+/*
+ * debug.c
+ */
+#ifdef CONFIG_F2FS_STAT_FS
+struct f2fs_stat_info {
+	struct list_head stat_list;
+	struct f2fs_sb_info *sbi;
+	struct mutex stat_lock;
+	int all_area_segs, sit_area_segs, nat_area_segs, ssa_area_segs;
+	int main_area_segs, main_area_sections, main_area_zones;
+	int hit_ext, total_ext;
+	int ndirty_node, ndirty_dent, ndirty_dirs, ndirty_meta;
+	int nats, sits, fnids;
+	int total_count, utilization;
+	int bg_gc;
+	unsigned int valid_count, valid_node_count, valid_inode_count;
+	unsigned int bimodal, avg_vblocks;
+	int util_free, util_valid, util_invalid;
+	int rsvd_segs, overp_segs;
+	int dirty_count, node_pages, meta_pages;
+	int prefree_count, call_count;
+	int tot_segs, node_segs, data_segs, free_segs, free_secs;
+	int tot_blks, data_blks, node_blks;
+	int curseg[NR_CURSEG_TYPE];
+	int cursec[NR_CURSEG_TYPE];
+	int curzone[NR_CURSEG_TYPE];
+
+	unsigned int segment_count[2];
+	unsigned int block_count[2];
+	unsigned base_mem, cache_mem;
+};
+
+#define stat_inc_call_count(si)	((si)->call_count++)
+
+#define stat_inc_seg_count(sbi, type)					\
+	do {								\
+		struct f2fs_stat_info *si = sbi->stat_info;		\
+		(si)->tot_segs++;					\
+		if (type == SUM_TYPE_DATA)				\
+			si->data_segs++;				\
+		else							\
+			si->node_segs++;				\
+	} while (0)
+
+#define stat_inc_tot_blk_count(si, blks)				\
+	(si->tot_blks += (blks))
+
+#define stat_inc_data_blk_count(sbi, blks)				\
+	do {								\
+		struct f2fs_stat_info *si = sbi->stat_info;		\
+		stat_inc_tot_blk_count(si, blks);			\
+		si->data_blks += (blks);				\
+	} while (0)
+
+#define stat_inc_node_blk_count(sbi, blks)				\
+	do {								\
+		struct f2fs_stat_info *si = sbi->stat_info;		\
+		stat_inc_tot_blk_count(si, blks);			\
+		si->node_blks += (blks);				\
+	} while (0)
+
+int f2fs_build_stats(struct f2fs_sb_info *);
+void f2fs_destroy_stats(struct f2fs_sb_info *);
+void destroy_root_stats(void);
+#else
+#define stat_inc_call_count(si)
+#define stat_inc_seg_count(si, type)
+#define stat_inc_tot_blk_count(si, blks)
+#define stat_inc_data_blk_count(si, blks)
+#define stat_inc_node_blk_count(sbi, blks)
+
+static inline int f2fs_build_stats(struct f2fs_sb_info *sbi) { return 0; }
+static inline void f2fs_destroy_stats(struct f2fs_sb_info *sbi) { }
+static inline void destroy_root_stats(void) { }
+#endif
+
+extern const struct file_operations f2fs_dir_operations;
+extern const struct file_operations f2fs_file_operations;
+extern const struct inode_operations f2fs_file_inode_operations;
+extern const struct address_space_operations f2fs_dblock_aops;
+extern const struct address_space_operations f2fs_node_aops;
+extern const struct address_space_operations f2fs_meta_aops;
+extern const struct inode_operations f2fs_dir_inode_operations;
+extern const struct inode_operations f2fs_symlink_inode_operations;
+extern const struct inode_operations f2fs_special_inode_operations;
+#endif
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
new file mode 100644
index 0000000..f5ae36d
--- /dev/null
+++ b/fs/f2fs/file.c
@@ -0,0 +1,637 @@
+/**
+ * fs/f2fs/file.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/stat.h>
+#include <linux/buffer_head.h>
+#include <linux/writeback.h>
+#include <linux/falloc.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/mount.h>
+
+#include "f2fs.h"
+#include "node.h"
+#include "segment.h"
+#include "xattr.h"
+#include "acl.h"
+
+static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma,
+						struct vm_fault *vmf)
+{
+	struct page *page = vmf->page;
+	struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct page *node_page;
+	block_t old_blk_addr;
+	struct dnode_of_data dn;
+	int err;
+
+	f2fs_balance_fs(sbi);
+
+	sb_start_pagefault(inode->i_sb);
+
+	mutex_lock_op(sbi, DATA_NEW);
+
+	/* block allocation */
+	set_new_dnode(&dn, inode, NULL, NULL, 0);
+	err = get_dnode_of_data(&dn, page->index, 0);
+	if (err) {
+		mutex_unlock_op(sbi, DATA_NEW);
+		goto out;
+	}
+
+	old_blk_addr = dn.data_blkaddr;
+	node_page = dn.node_page;
+
+	if (old_blk_addr == NULL_ADDR) {
+		err = reserve_new_block(&dn);
+		if (err) {
+			f2fs_put_dnode(&dn);
+			mutex_unlock_op(sbi, DATA_NEW);
+			goto out;
+		}
+	}
+	f2fs_put_dnode(&dn);
+
+	mutex_unlock_op(sbi, DATA_NEW);
+
+	lock_page(page);
+	if (page->mapping != inode->i_mapping ||
+			page_offset(page) >= i_size_read(inode) ||
+			!PageUptodate(page)) {
+		unlock_page(page);
+		err = -EFAULT;
+		goto out;
+	}
+
+	/*
+	 * check to see if the page is mapped already (no holes)
+	 */
+	if (PageMappedToDisk(page))
+		goto out;
+
+	/* fill the page */
+	wait_on_page_writeback(page);
+
+	/* page is wholly or partially inside EOF */
+	if (((page->index + 1) << PAGE_CACHE_SHIFT) > i_size_read(inode)) {
+		unsigned offset;
+		offset = i_size_read(inode) & ~PAGE_CACHE_MASK;
+		zero_user_segment(page, offset, PAGE_CACHE_SIZE);
+	}
+	set_page_dirty(page);
+	SetPageUptodate(page);
+
+	file_update_time(vma->vm_file);
+out:
+	sb_end_pagefault(inode->i_sb);
+	return block_page_mkwrite_return(err);
+}
+
+static const struct vm_operations_struct f2fs_file_vm_ops = {
+	.fault        = filemap_fault,
+	.page_mkwrite = f2fs_vm_page_mkwrite,
+};
+
+static int need_to_sync_dir(struct f2fs_sb_info *sbi, struct inode *inode)
+{
+	struct dentry *dentry;
+	nid_t pino;
+
+	inode = igrab(inode);
+	dentry = d_find_any_alias(inode);
+	if (!dentry) {
+		iput(inode);
+		return 0;
+	}
+	pino = dentry->d_parent->d_inode->i_ino;
+	dput(dentry);
+	iput(inode);
+	return !is_checkpointed_node(sbi, pino);
+}
+
+int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
+{
+	struct inode *inode = file->f_mapping->host;
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	unsigned long long cur_version;
+	int ret = 0;
+	bool need_cp = false;
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_ALL,
+		.nr_to_write = LONG_MAX,
+		.for_reclaim = 0,
+	};
+
+	ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+	if (ret)
+		return ret;
+
+	mutex_lock(&inode->i_mutex);
+
+	if (inode->i_sb->s_flags & MS_RDONLY)
+		goto out;
+	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+		goto out;
+
+	mutex_lock(&sbi->cp_mutex);
+	cur_version = le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver);
+	mutex_unlock(&sbi->cp_mutex);
+
+	if (F2FS_I(inode)->data_version != cur_version &&
+					!(inode->i_state & I_DIRTY))
+		goto out;
+	F2FS_I(inode)->data_version--;
+
+	if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1)
+		need_cp = true;
+	if (is_inode_flag_set(F2FS_I(inode), FI_NEED_CP))
+		need_cp = true;
+	if (!space_for_roll_forward(sbi))
+		need_cp = true;
+	if (need_to_sync_dir(sbi, inode))
+		need_cp = true;
+
+	f2fs_write_inode(inode, NULL);
+
+	if (need_cp) {
+		/* all the dirty node pages should be flushed for POR */
+		ret = f2fs_sync_fs(inode->i_sb, 1);
+		clear_inode_flag(F2FS_I(inode), FI_NEED_CP);
+	} else {
+		while (sync_node_pages(sbi, inode->i_ino, &wbc) == 0)
+			f2fs_write_inode(inode, NULL);
+		filemap_fdatawait_range(sbi->node_inode->i_mapping,
+							0, LONG_MAX);
+	}
+out:
+	mutex_unlock(&inode->i_mutex);
+	return ret;
+}
+
+static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	file_accessed(file);
+	vma->vm_ops = &f2fs_file_vm_ops;
+	return 0;
+}
+
+static int truncate_data_blocks_range(struct dnode_of_data *dn, int count)
+{
+	int nr_free = 0, ofs = dn->ofs_in_node;
+	struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
+	struct f2fs_node *raw_node;
+	__le32 *addr;
+
+	raw_node = page_address(dn->node_page);
+	addr = blkaddr_in_node(raw_node) + ofs;
+
+	for ( ; count > 0; count--, addr++, dn->ofs_in_node++) {
+		block_t blkaddr = le32_to_cpu(*addr);
+		if (blkaddr == NULL_ADDR)
+			continue;
+
+		update_extent_cache(NULL_ADDR, dn);
+		invalidate_blocks(sbi, blkaddr);
+		dec_valid_block_count(sbi, dn->inode, 1);
+		nr_free++;
+	}
+	if (nr_free) {
+		set_page_dirty(dn->node_page);
+		sync_inode_page(dn);
+	}
+	dn->ofs_in_node = ofs;
+	return nr_free;
+}
+
+void truncate_data_blocks(struct dnode_of_data *dn)
+{
+	truncate_data_blocks_range(dn, ADDRS_PER_BLOCK);
+}
+
+static void truncate_partial_data_page(struct inode *inode, u64 from)
+{
+	unsigned offset = from & (PAGE_CACHE_SIZE - 1);
+	struct page *page;
+
+	if (!offset)
+		return;
+
+	page = find_data_page(inode, from >> PAGE_CACHE_SHIFT);
+	if (IS_ERR(page))
+		return;
+
+	lock_page(page);
+	wait_on_page_writeback(page);
+	zero_user(page, offset, PAGE_CACHE_SIZE - offset);
+	set_page_dirty(page);
+	f2fs_put_page(page, 1);
+}
+
+static int truncate_blocks(struct inode *inode, u64 from)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	unsigned int blocksize = inode->i_sb->s_blocksize;
+	struct dnode_of_data dn;
+	pgoff_t free_from;
+	int count = 0;
+	int err;
+
+	free_from = (pgoff_t)
+			((from + blocksize - 1) >> (sbi->log_blocksize));
+
+	mutex_lock_op(sbi, DATA_TRUNC);
+
+	set_new_dnode(&dn, inode, NULL, NULL, 0);
+	err = get_dnode_of_data(&dn, free_from, RDONLY_NODE);
+	if (err) {
+		if (err == -ENOENT)
+			goto free_next;
+		mutex_unlock_op(sbi, DATA_TRUNC);
+		return err;
+	}
+
+	if (IS_INODE(dn.node_page))
+		count = ADDRS_PER_INODE;
+	else
+		count = ADDRS_PER_BLOCK;
+
+	count -= dn.ofs_in_node;
+	BUG_ON(count < 0);
+	if (dn.ofs_in_node || IS_INODE(dn.node_page)) {
+		truncate_data_blocks_range(&dn, count);
+		free_from += count;
+	}
+
+	f2fs_put_dnode(&dn);
+free_next:
+	err = truncate_inode_blocks(inode, free_from);
+	mutex_unlock_op(sbi, DATA_TRUNC);
+
+	/* lastly zero out the first data page */
+	truncate_partial_data_page(inode, from);
+
+	return err;
+}
+
+void f2fs_truncate(struct inode *inode)
+{
+	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+				S_ISLNK(inode->i_mode)))
+		return;
+
+	if (!truncate_blocks(inode, i_size_read(inode))) {
+		inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		mark_inode_dirty(inode);
+	}
+
+	f2fs_balance_fs(F2FS_SB(inode->i_sb));
+}
+
+static int f2fs_getattr(struct vfsmount *mnt,
+			 struct dentry *dentry, struct kstat *stat)
+{
+	struct inode *inode = dentry->d_inode;
+	generic_fillattr(inode, stat);
+	stat->blocks <<= 3;
+	return 0;
+}
+
+#ifdef CONFIG_F2FS_FS_POSIX_ACL
+static void __setattr_copy(struct inode *inode, const struct iattr *attr)
+{
+	struct f2fs_inode_info *fi = F2FS_I(inode);
+	unsigned int ia_valid = attr->ia_valid;
+
+	if (ia_valid & ATTR_UID)
+		inode->i_uid = attr->ia_uid;
+	if (ia_valid & ATTR_GID)
+		inode->i_gid = attr->ia_gid;
+	if (ia_valid & ATTR_ATIME)
+		inode->i_atime = timespec_trunc(attr->ia_atime,
+						inode->i_sb->s_time_gran);
+	if (ia_valid & ATTR_MTIME)
+		inode->i_mtime = timespec_trunc(attr->ia_mtime,
+						inode->i_sb->s_time_gran);
+	if (ia_valid & ATTR_CTIME)
+		inode->i_ctime = timespec_trunc(attr->ia_ctime,
+						inode->i_sb->s_time_gran);
+	if (ia_valid & ATTR_MODE) {
+		umode_t mode = attr->ia_mode;
+
+		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+			mode &= ~S_ISGID;
+		set_acl_inode(fi, mode);
+	}
+}
+#else
+#define __setattr_copy setattr_copy
+#endif
+
+int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+	struct inode *inode = dentry->d_inode;
+	struct f2fs_inode_info *fi = F2FS_I(inode);
+	int err;
+
+	err = inode_change_ok(inode, attr);
+	if (err)
+		return err;
+
+	if ((attr->ia_valid & ATTR_SIZE) &&
+			attr->ia_size != i_size_read(inode)) {
+		truncate_setsize(inode, attr->ia_size);
+		f2fs_truncate(inode);
+	}
+
+	__setattr_copy(inode, attr);
+
+	if (attr->ia_valid & ATTR_MODE) {
+		err = f2fs_acl_chmod(inode);
+		if (err || is_inode_flag_set(fi, FI_ACL_MODE)) {
+			inode->i_mode = fi->i_acl_mode;
+			clear_inode_flag(fi, FI_ACL_MODE);
+		}
+	}
+
+	mark_inode_dirty(inode);
+	return err;
+}
+
+const struct inode_operations f2fs_file_inode_operations = {
+	.getattr	= f2fs_getattr,
+	.setattr	= f2fs_setattr,
+	.get_acl	= f2fs_get_acl,
+#ifdef CONFIG_F2FS_FS_XATTR
+	.setxattr	= generic_setxattr,
+	.getxattr	= generic_getxattr,
+	.listxattr	= f2fs_listxattr,
+	.removexattr	= generic_removexattr,
+#endif
+};
+
+static void fill_zero(struct inode *inode, pgoff_t index,
+					loff_t start, loff_t len)
+{
+	struct page *page;
+
+	if (!len)
+		return;
+
+	page = get_new_data_page(inode, index, false);
+
+	if (!IS_ERR(page)) {
+		wait_on_page_writeback(page);
+		zero_user(page, start, len);
+		set_page_dirty(page);
+		f2fs_put_page(page, 1);
+	}
+}
+
+int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end)
+{
+	pgoff_t index;
+	int err;
+
+	for (index = pg_start; index < pg_end; index++) {
+		struct dnode_of_data dn;
+		struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+
+		mutex_lock_op(sbi, DATA_TRUNC);
+		set_new_dnode(&dn, inode, NULL, NULL, 0);
+		err = get_dnode_of_data(&dn, index, RDONLY_NODE);
+		if (err) {
+			mutex_unlock_op(sbi, DATA_TRUNC);
+			if (err == -ENOENT)
+				continue;
+			return err;
+		}
+
+		if (dn.data_blkaddr != NULL_ADDR)
+			truncate_data_blocks_range(&dn, 1);
+		f2fs_put_dnode(&dn);
+		mutex_unlock_op(sbi, DATA_TRUNC);
+	}
+	return 0;
+}
+
+static int punch_hole(struct inode *inode, loff_t offset, loff_t len, int mode)
+{
+	pgoff_t pg_start, pg_end;
+	loff_t off_start, off_end;
+	int ret = 0;
+
+	pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT;
+	pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT;
+
+	off_start = offset & (PAGE_CACHE_SIZE - 1);
+	off_end = (offset + len) & (PAGE_CACHE_SIZE - 1);
+
+	if (pg_start == pg_end) {
+		fill_zero(inode, pg_start, off_start,
+						off_end - off_start);
+	} else {
+		if (off_start)
+			fill_zero(inode, pg_start++, off_start,
+					PAGE_CACHE_SIZE - off_start);
+		if (off_end)
+			fill_zero(inode, pg_end, 0, off_end);
+
+		if (pg_start < pg_end) {
+			struct address_space *mapping = inode->i_mapping;
+			loff_t blk_start, blk_end;
+
+			blk_start = pg_start << PAGE_CACHE_SHIFT;
+			blk_end = pg_end << PAGE_CACHE_SHIFT;
+			truncate_inode_pages_range(mapping, blk_start,
+					blk_end - 1);
+			ret = truncate_hole(inode, pg_start, pg_end);
+		}
+	}
+
+	if (!(mode & FALLOC_FL_KEEP_SIZE) &&
+		i_size_read(inode) <= (offset + len)) {
+		i_size_write(inode, offset);
+		mark_inode_dirty(inode);
+	}
+
+	return ret;
+}
+
+static int expand_inode_data(struct inode *inode, loff_t offset,
+					loff_t len, int mode)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	pgoff_t index, pg_start, pg_end;
+	loff_t new_size = i_size_read(inode);
+	loff_t off_start, off_end;
+	int ret = 0;
+
+	ret = inode_newsize_ok(inode, (len + offset));
+	if (ret)
+		return ret;
+
+	pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT;
+	pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT;
+
+	off_start = offset & (PAGE_CACHE_SIZE - 1);
+	off_end = (offset + len) & (PAGE_CACHE_SIZE - 1);
+
+	for (index = pg_start; index <= pg_end; index++) {
+		struct dnode_of_data dn;
+
+		mutex_lock_op(sbi, DATA_NEW);
+
+		set_new_dnode(&dn, inode, NULL, NULL, 0);
+		ret = get_dnode_of_data(&dn, index, 0);
+		if (ret) {
+			mutex_unlock_op(sbi, DATA_NEW);
+			break;
+		}
+
+		if (dn.data_blkaddr == NULL_ADDR) {
+			ret = reserve_new_block(&dn);
+			if (ret) {
+				f2fs_put_dnode(&dn);
+				mutex_unlock_op(sbi, DATA_NEW);
+				break;
+			}
+		}
+		f2fs_put_dnode(&dn);
+
+		mutex_unlock_op(sbi, DATA_NEW);
+
+		if (pg_start == pg_end)
+			new_size = offset + len;
+		else if (index == pg_start && off_start)
+			new_size = (index + 1) << PAGE_CACHE_SHIFT;
+		else if (index == pg_end)
+			new_size = (index << PAGE_CACHE_SHIFT) + off_end;
+		else
+			new_size += PAGE_CACHE_SIZE;
+	}
+
+	if (!(mode & FALLOC_FL_KEEP_SIZE) &&
+		i_size_read(inode) < new_size) {
+		i_size_write(inode, new_size);
+		mark_inode_dirty(inode);
+	}
+
+	return ret;
+}
+
+static long f2fs_fallocate(struct file *file, int mode,
+				loff_t offset, loff_t len)
+{
+	struct inode *inode = file->f_path.dentry->d_inode;
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	long ret;
+
+	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
+		return -EOPNOTSUPP;
+
+	if (mode & FALLOC_FL_PUNCH_HOLE)
+		ret = punch_hole(inode, offset, len, mode);
+	else
+		ret = expand_inode_data(inode, offset, len, mode);
+
+	f2fs_balance_fs(sbi);
+	return ret;
+}
+
+#define F2FS_REG_FLMASK		(~(FS_DIRSYNC_FL | FS_TOPDIR_FL))
+#define F2FS_OTHER_FLMASK	(FS_NODUMP_FL | FS_NOATIME_FL)
+
+static inline __u32 f2fs_mask_flags(umode_t mode, __u32 flags)
+{
+	if (S_ISDIR(mode))
+		return flags;
+	else if (S_ISREG(mode))
+		return flags & F2FS_REG_FLMASK;
+	else
+		return flags & F2FS_OTHER_FLMASK;
+}
+
+long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct f2fs_inode_info *fi = F2FS_I(inode);
+	unsigned int flags;
+	int ret;
+
+	switch (cmd) {
+	case FS_IOC_GETFLAGS:
+		flags = fi->i_flags & FS_FL_USER_VISIBLE;
+		return put_user(flags, (int __user *) arg);
+	case FS_IOC_SETFLAGS:
+	{
+		unsigned int oldflags;
+
+		ret = mnt_want_write(filp->f_path.mnt);
+		if (ret)
+			return ret;
+
+		if (!inode_owner_or_capable(inode)) {
+			ret = -EACCES;
+			goto out;
+		}
+
+		if (get_user(flags, (int __user *) arg)) {
+			ret = -EFAULT;
+			goto out;
+		}
+
+		flags = f2fs_mask_flags(inode->i_mode, flags);
+
+		mutex_lock(&inode->i_mutex);
+
+		oldflags = fi->i_flags;
+
+		if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
+			if (!capable(CAP_LINUX_IMMUTABLE)) {
+				mutex_unlock(&inode->i_mutex);
+				ret = -EPERM;
+				goto out;
+			}
+		}
+
+		flags = flags & FS_FL_USER_MODIFIABLE;
+		flags |= oldflags & ~FS_FL_USER_MODIFIABLE;
+		fi->i_flags = flags;
+		mutex_unlock(&inode->i_mutex);
+
+		f2fs_set_inode_flags(inode);
+		inode->i_ctime = CURRENT_TIME;
+		mark_inode_dirty(inode);
+out:
+		mnt_drop_write(filp->f_path.mnt);
+		return ret;
+	}
+	default:
+		return -ENOTTY;
+	}
+}
+
+const struct file_operations f2fs_file_operations = {
+	.llseek		= generic_file_llseek,
+	.read		= do_sync_read,
+	.write		= do_sync_write,
+	.aio_read	= generic_file_aio_read,
+	.aio_write	= generic_file_aio_write,
+	.open		= generic_file_open,
+	.mmap		= f2fs_file_mmap,
+	.fsync		= f2fs_sync_file,
+	.fallocate	= f2fs_fallocate,
+	.unlocked_ioctl	= f2fs_ioctl,
+	.splice_read	= generic_file_splice_read,
+	.splice_write	= generic_file_splice_write,
+};
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
new file mode 100644
index 0000000..46774ce
--- /dev/null
+++ b/fs/f2fs/gc.c
@@ -0,0 +1,742 @@
+/**
+ * fs/f2fs/gc.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/backing-dev.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/f2fs_fs.h>
+#include <linux/kthread.h>
+#include <linux/delay.h>
+#include <linux/freezer.h>
+#include <linux/blkdev.h>
+
+#include "f2fs.h"
+#include "node.h"
+#include "segment.h"
+#include "gc.h"
+
+static struct kmem_cache *winode_slab;
+
+static int gc_thread_func(void *data)
+{
+	struct f2fs_sb_info *sbi = data;
+	wait_queue_head_t *wq = &sbi->gc_thread->gc_wait_queue_head;
+	long wait_ms;
+
+	wait_ms = GC_THREAD_MIN_SLEEP_TIME;
+
+	do {
+		if (try_to_freeze())
+			continue;
+		else
+			wait_event_interruptible_timeout(*wq,
+						kthread_should_stop(),
+						msecs_to_jiffies(wait_ms));
+		if (kthread_should_stop())
+			break;
+
+		f2fs_balance_fs(sbi);
+
+		if (!test_opt(sbi, BG_GC))
+			continue;
+
+		/*
+		 * [GC triggering condition]
+		 * 0. GC is not conducted currently.
+		 * 1. There are enough dirty segments.
+		 * 2. IO subsystem is idle by checking the # of writeback pages.
+		 * 3. IO subsystem is idle by checking the # of requests in
+		 *    bdev's request list.
+		 *
+		 * Note) We have to avoid triggering GCs too much frequently.
+		 * Because it is possible that some segments can be
+		 * invalidated soon after by user update or deletion.
+		 * So, I'd like to wait some time to collect dirty segments.
+		 */
+		if (!mutex_trylock(&sbi->gc_mutex))
+			continue;
+
+		if (!is_idle(sbi)) {
+			wait_ms = increase_sleep_time(wait_ms);
+			mutex_unlock(&sbi->gc_mutex);
+			continue;
+		}
+
+		if (has_enough_invalid_blocks(sbi))
+			wait_ms = decrease_sleep_time(wait_ms);
+		else
+			wait_ms = increase_sleep_time(wait_ms);
+
+		sbi->bg_gc++;
+
+		if (f2fs_gc(sbi, 1) == GC_NONE)
+			wait_ms = GC_THREAD_NOGC_SLEEP_TIME;
+		else if (wait_ms == GC_THREAD_NOGC_SLEEP_TIME)
+			wait_ms = GC_THREAD_MAX_SLEEP_TIME;
+
+	} while (!kthread_should_stop());
+	return 0;
+}
+
+int start_gc_thread(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_gc_kthread *gc_th = NULL;
+
+	gc_th = kmalloc(sizeof(struct f2fs_gc_kthread), GFP_KERNEL);
+	if (!gc_th)
+		return -ENOMEM;
+
+	sbi->gc_thread = gc_th;
+	init_waitqueue_head(&sbi->gc_thread->gc_wait_queue_head);
+	sbi->gc_thread->f2fs_gc_task = kthread_run(gc_thread_func, sbi,
+				GC_THREAD_NAME);
+	if (IS_ERR(gc_th->f2fs_gc_task)) {
+		kfree(gc_th);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+void stop_gc_thread(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_gc_kthread *gc_th = sbi->gc_thread;
+	if (!gc_th)
+		return;
+	kthread_stop(gc_th->f2fs_gc_task);
+	kfree(gc_th);
+	sbi->gc_thread = NULL;
+}
+
+static int select_gc_type(int gc_type)
+{
+	return (gc_type == BG_GC) ? GC_CB : GC_GREEDY;
+}
+
+static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
+			int type, struct victim_sel_policy *p)
+{
+	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+
+	if (p->alloc_mode) {
+		p->gc_mode = GC_GREEDY;
+		p->dirty_segmap = dirty_i->dirty_segmap[type];
+		p->ofs_unit = 1;
+	} else {
+		p->gc_mode = select_gc_type(gc_type);
+		p->dirty_segmap = dirty_i->dirty_segmap[DIRTY];
+		p->ofs_unit = sbi->segs_per_sec;
+	}
+	p->offset = sbi->last_victim[p->gc_mode];
+}
+
+static unsigned int get_max_cost(struct f2fs_sb_info *sbi,
+				struct victim_sel_policy *p)
+{
+	if (p->gc_mode == GC_GREEDY)
+		return (1 << sbi->log_blocks_per_seg) * p->ofs_unit;
+	else if (p->gc_mode == GC_CB)
+		return UINT_MAX;
+	else /* No other gc_mode */
+		return 0;
+}
+
+static unsigned int check_bg_victims(struct f2fs_sb_info *sbi)
+{
+	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+	unsigned int segno;
+
+	/*
+	 * If the gc_type is FG_GC, we can select victim segments
+	 * selected by background GC before.
+	 * Those segments guarantee they have small valid blocks.
+	 */
+	segno = find_next_bit(dirty_i->victim_segmap[BG_GC],
+						TOTAL_SEGS(sbi), 0);
+	if (segno < TOTAL_SEGS(sbi)) {
+		clear_bit(segno, dirty_i->victim_segmap[BG_GC]);
+		return segno;
+	}
+	return NULL_SEGNO;
+}
+
+static unsigned int get_cb_cost(struct f2fs_sb_info *sbi, unsigned int segno)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	unsigned int secno = GET_SECNO(sbi, segno);
+	unsigned int start = secno * sbi->segs_per_sec;
+	unsigned long long mtime = 0;
+	unsigned int vblocks;
+	unsigned char age = 0;
+	unsigned char u;
+	unsigned int i;
+
+	for (i = 0; i < sbi->segs_per_sec; i++)
+		mtime += get_seg_entry(sbi, start + i)->mtime;
+	vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec);
+
+	mtime = div_u64(mtime, sbi->segs_per_sec);
+	vblocks = div_u64(vblocks, sbi->segs_per_sec);
+
+	u = (vblocks * 100) >> sbi->log_blocks_per_seg;
+
+	/* Handle if the system time is changed by user */
+	if (mtime < sit_i->min_mtime)
+		sit_i->min_mtime = mtime;
+	if (mtime > sit_i->max_mtime)
+		sit_i->max_mtime = mtime;
+	if (sit_i->max_mtime != sit_i->min_mtime)
+		age = 100 - div64_u64(100 * (mtime - sit_i->min_mtime),
+				sit_i->max_mtime - sit_i->min_mtime);
+
+	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)
+{
+	if (p->alloc_mode == SSR)
+		return get_seg_entry(sbi, segno)->ckpt_valid_blocks;
+
+	/* alloc_mode == LFS */
+	if (p->gc_mode == GC_GREEDY)
+		return get_valid_blocks(sbi, segno, sbi->segs_per_sec);
+	else
+		return get_cb_cost(sbi, segno);
+}
+
+/**
+ * This function is called from two pathes.
+ * One is garbage collection and the other is SSR segment selection.
+ * When it is called during GC, it just gets a victim segment
+ * and it does not remove it from dirty seglist.
+ * When it is called from SSR segment selection, it finds a segment
+ * which has minimum valid blocks and removes it from dirty seglist.
+ */
+static int get_victim_by_default(struct f2fs_sb_info *sbi,
+		unsigned int *result, int gc_type, int type, char alloc_mode)
+{
+	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+	struct victim_sel_policy p;
+	unsigned int segno;
+	int nsearched = 0;
+
+	p.alloc_mode = alloc_mode;
+	select_policy(sbi, gc_type, type, &p);
+
+	p.min_segno = NULL_SEGNO;
+	p.min_cost = get_max_cost(sbi, &p);
+
+	mutex_lock(&dirty_i->seglist_lock);
+
+	if (p.alloc_mode == LFS && gc_type == FG_GC) {
+		p.min_segno = check_bg_victims(sbi);
+		if (p.min_segno != NULL_SEGNO)
+			goto got_it;
+	}
+
+	while (1) {
+		unsigned long cost;
+
+		segno = find_next_bit(p.dirty_segmap,
+						TOTAL_SEGS(sbi), p.offset);
+		if (segno >= TOTAL_SEGS(sbi)) {
+			if (sbi->last_victim[p.gc_mode]) {
+				sbi->last_victim[p.gc_mode] = 0;
+				p.offset = 0;
+				continue;
+			}
+			break;
+		}
+		p.offset = ((segno / p.ofs_unit) * p.ofs_unit) + p.ofs_unit;
+
+		if (test_bit(segno, dirty_i->victim_segmap[FG_GC]))
+			continue;
+		if (gc_type == BG_GC &&
+				test_bit(segno, dirty_i->victim_segmap[BG_GC]))
+			continue;
+		if (IS_CURSEC(sbi, GET_SECNO(sbi, segno)))
+			continue;
+
+		cost = get_gc_cost(sbi, segno, &p);
+
+		if (p.min_cost > cost) {
+			p.min_segno = segno;
+			p.min_cost = cost;
+		}
+
+		if (cost == get_max_cost(sbi, &p))
+			continue;
+
+		if (nsearched++ >= MAX_VICTIM_SEARCH) {
+			sbi->last_victim[p.gc_mode] = segno;
+			break;
+		}
+	}
+got_it:
+	if (p.min_segno != NULL_SEGNO) {
+		*result = (p.min_segno / p.ofs_unit) * p.ofs_unit;
+		if (p.alloc_mode == LFS) {
+			int i;
+			for (i = 0; i < p.ofs_unit; i++)
+				set_bit(*result + i,
+					dirty_i->victim_segmap[gc_type]);
+		}
+	}
+	mutex_unlock(&dirty_i->seglist_lock);
+
+	return (p.min_segno == NULL_SEGNO) ? 0 : 1;
+}
+
+static const struct victim_selection default_v_ops = {
+	.get_victim = get_victim_by_default,
+};
+
+static struct inode *find_gc_inode(nid_t ino, struct list_head *ilist)
+{
+	struct list_head *this;
+	struct inode_entry *ie;
+
+	list_for_each(this, ilist) {
+		ie = list_entry(this, struct inode_entry, list);
+		if (ie->inode->i_ino == ino)
+			return ie->inode;
+	}
+	return NULL;
+}
+
+static void add_gc_inode(struct inode *inode, struct list_head *ilist)
+{
+	struct list_head *this;
+	struct inode_entry *new_ie, *ie;
+
+	list_for_each(this, ilist) {
+		ie = list_entry(this, struct inode_entry, list);
+		if (ie->inode == inode) {
+			iput(inode);
+			return;
+		}
+	}
+repeat:
+	new_ie = kmem_cache_alloc(winode_slab, GFP_NOFS);
+	if (!new_ie) {
+		cond_resched();
+		goto repeat;
+	}
+	new_ie->inode = inode;
+	list_add_tail(&new_ie->list, ilist);
+}
+
+static void put_gc_inode(struct list_head *ilist)
+{
+	struct inode_entry *ie, *next_ie;
+	list_for_each_entry_safe(ie, next_ie, ilist, list) {
+		iput(ie->inode);
+		list_del(&ie->list);
+		kmem_cache_free(winode_slab, ie);
+	}
+}
+
+static int check_valid_map(struct f2fs_sb_info *sbi,
+				unsigned int segno, int offset)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	struct seg_entry *sentry;
+	int ret;
+
+	mutex_lock(&sit_i->sentry_lock);
+	sentry = get_seg_entry(sbi, segno);
+	ret = f2fs_test_bit(offset, sentry->cur_valid_map);
+	mutex_unlock(&sit_i->sentry_lock);
+	return ret ? GC_OK : GC_NEXT;
+}
+
+/**
+ * This function compares node address got in summary with that in NAT.
+ * On validity, copy that node with cold status, otherwise (invalid node)
+ * ignore that.
+ */
+static int gc_node_segment(struct f2fs_sb_info *sbi,
+		struct f2fs_summary *sum, unsigned int segno, int gc_type)
+{
+	bool initial = true;
+	struct f2fs_summary *entry;
+	int off;
+
+next_step:
+	entry = sum;
+	for (off = 0; off < sbi->blocks_per_seg; off++, entry++) {
+		nid_t nid = le32_to_cpu(entry->nid);
+		struct page *node_page;
+		int err;
+
+		/*
+		 * It makes sure that free segments are able to write
+		 * all the dirty node pages before CP after this CP.
+		 * So let's check the space of dirty node pages.
+		 */
+		if (should_do_checkpoint(sbi)) {
+			mutex_lock(&sbi->cp_mutex);
+			block_operations(sbi);
+			return GC_BLOCKED;
+		}
+
+		err = check_valid_map(sbi, segno, off);
+		if (err == GC_ERROR)
+			return err;
+		else if (err == GC_NEXT)
+			continue;
+
+		if (initial) {
+			ra_node_page(sbi, nid);
+			continue;
+		}
+		node_page = get_node_page(sbi, nid);
+		if (IS_ERR(node_page))
+			continue;
+
+		/* set page dirty and write it */
+		if (!PageWriteback(node_page))
+			set_page_dirty(node_page);
+		f2fs_put_page(node_page, 1);
+		stat_inc_node_blk_count(sbi, 1);
+	}
+	if (initial) {
+		initial = false;
+		goto next_step;
+	}
+
+	if (gc_type == FG_GC) {
+		struct writeback_control wbc = {
+			.sync_mode = WB_SYNC_ALL,
+			.nr_to_write = LONG_MAX,
+			.for_reclaim = 0,
+		};
+		sync_node_pages(sbi, 0, &wbc);
+	}
+	return GC_DONE;
+}
+
+/**
+ * Calculate start block index that this node page contains
+ */
+block_t start_bidx_of_node(unsigned int node_ofs)
+{
+	block_t start_bidx;
+	unsigned int bidx, indirect_blks;
+	int dec;
+
+	indirect_blks = 2 * NIDS_PER_BLOCK + 4;
+
+	start_bidx = 1;
+	if (node_ofs == 0) {
+		start_bidx = 0;
+	} else if (node_ofs <= 2) {
+		bidx = node_ofs - 1;
+	} else if (node_ofs <= indirect_blks) {
+		dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1);
+		bidx = node_ofs - 2 - dec;
+	} else {
+		dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);
+		bidx = node_ofs - 5 - dec;
+	}
+
+	if (start_bidx)
+		start_bidx = bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE;
+	return start_bidx;
+}
+
+static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
+		struct node_info *dni, block_t blkaddr, unsigned int *nofs)
+{
+	struct page *node_page;
+	nid_t nid;
+	unsigned int ofs_in_node;
+	block_t source_blkaddr;
+
+	nid = le32_to_cpu(sum->nid);
+	ofs_in_node = le16_to_cpu(sum->ofs_in_node);
+
+	node_page = get_node_page(sbi, nid);
+	if (IS_ERR(node_page))
+		return GC_NEXT;
+
+	get_node_info(sbi, nid, dni);
+
+	if (sum->version != dni->version) {
+		f2fs_put_page(node_page, 1);
+		return GC_NEXT;
+	}
+
+	*nofs = ofs_of_node(node_page);
+	source_blkaddr = datablock_addr(node_page, ofs_in_node);
+	f2fs_put_page(node_page, 1);
+
+	if (source_blkaddr != blkaddr)
+		return GC_NEXT;
+	return GC_OK;
+}
+
+static void move_data_page(struct inode *inode, struct page *page, int gc_type)
+{
+	if (page->mapping != inode->i_mapping)
+		goto out;
+
+	if (inode != page->mapping->host)
+		goto out;
+
+	if (PageWriteback(page))
+		goto out;
+
+	if (gc_type == BG_GC) {
+		set_page_dirty(page);
+		set_cold_data(page);
+	} else {
+		struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+		mutex_lock_op(sbi, DATA_WRITE);
+		if (clear_page_dirty_for_io(page) &&
+			S_ISDIR(inode->i_mode)) {
+			dec_page_count(sbi, F2FS_DIRTY_DENTS);
+			inode_dec_dirty_dents(inode);
+		}
+		set_cold_data(page);
+		do_write_data_page(page);
+		mutex_unlock_op(sbi, DATA_WRITE);
+		clear_cold_data(page);
+	}
+out:
+	f2fs_put_page(page, 1);
+}
+
+/**
+ * This function tries to get parent node of victim data block, and identifies
+ * data block validity. If the block is valid, copy that with cold status and
+ * modify parent node.
+ * If the parent node is not valid or the data block address is different,
+ * the victim data block is ignored.
+ */
+static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
+		struct list_head *ilist, unsigned int segno, int gc_type)
+{
+	struct super_block *sb = sbi->sb;
+	struct f2fs_summary *entry;
+	block_t start_addr;
+	int err, off;
+	int phase = 0;
+
+	start_addr = START_BLOCK(sbi, segno);
+
+next_step:
+	entry = sum;
+	for (off = 0; off < sbi->blocks_per_seg; off++, entry++) {
+		struct page *data_page;
+		struct inode *inode;
+		struct node_info dni; /* dnode info for the data */
+		unsigned int ofs_in_node, nofs;
+		block_t start_bidx;
+
+		/*
+		 * It makes sure that free segments are able to write
+		 * all the dirty node pages before CP after this CP.
+		 * So let's check the space of dirty node pages.
+		 */
+		if (should_do_checkpoint(sbi)) {
+			mutex_lock(&sbi->cp_mutex);
+			block_operations(sbi);
+			err = GC_BLOCKED;
+			goto stop;
+		}
+
+		err = check_valid_map(sbi, segno, off);
+		if (err == GC_ERROR)
+			goto stop;
+		else if (err == GC_NEXT)
+			continue;
+
+		if (phase == 0) {
+			ra_node_page(sbi, le32_to_cpu(entry->nid));
+			continue;
+		}
+
+		/* Get an inode by ino with checking validity */
+		err = check_dnode(sbi, entry, &dni, start_addr + off, &nofs);
+		if (err == GC_ERROR)
+			goto stop;
+		else if (err == GC_NEXT)
+			continue;
+
+		if (phase == 1) {
+			ra_node_page(sbi, dni.ino);
+			continue;
+		}
+
+		start_bidx = start_bidx_of_node(nofs);
+		ofs_in_node = le16_to_cpu(entry->ofs_in_node);
+
+		if (phase == 2) {
+			inode = f2fs_iget_nowait(sb, dni.ino);
+			if (IS_ERR(inode))
+				continue;
+
+			data_page = find_data_page(inode,
+					start_bidx + ofs_in_node);
+			if (IS_ERR(data_page))
+				goto next_iput;
+
+			f2fs_put_page(data_page, 0);
+			add_gc_inode(inode, ilist);
+		} else {
+			inode = find_gc_inode(dni.ino, ilist);
+			if (inode) {
+				data_page = get_lock_data_page(inode,
+						start_bidx + ofs_in_node);
+				if (IS_ERR(data_page))
+					continue;
+				move_data_page(inode, data_page, gc_type);
+				stat_inc_data_blk_count(sbi, 1);
+			}
+		}
+		continue;
+next_iput:
+		iput(inode);
+	}
+	if (++phase < 4)
+		goto next_step;
+	err = GC_DONE;
+stop:
+	if (gc_type == FG_GC)
+		f2fs_submit_bio(sbi, DATA, true);
+	return err;
+}
+
+static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim,
+						int gc_type, int type)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	int ret;
+	mutex_lock(&sit_i->sentry_lock);
+	ret = DIRTY_I(sbi)->v_ops->get_victim(sbi, victim, gc_type, type, LFS);
+	mutex_unlock(&sit_i->sentry_lock);
+	return ret;
+}
+
+static int do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno,
+				struct list_head *ilist, int gc_type)
+{
+	struct page *sum_page;
+	struct f2fs_summary_block *sum;
+	int ret = GC_DONE;
+
+	/* read segment summary of victim */
+	sum_page = get_sum_page(sbi, segno);
+	if (IS_ERR(sum_page))
+		return GC_ERROR;
+
+	/*
+	 * CP needs to lock sum_page. In this time, we don't need
+	 * to lock this page, because this summary page is not gone anywhere.
+	 * Also, this page is not gonna be updated before GC is done.
+	 */
+	unlock_page(sum_page);
+	sum = page_address(sum_page);
+
+	switch (GET_SUM_TYPE((&sum->footer))) {
+	case SUM_TYPE_NODE:
+		ret = gc_node_segment(sbi, sum->entries, segno, gc_type);
+		break;
+	case SUM_TYPE_DATA:
+		ret = gc_data_segment(sbi, sum->entries, ilist, segno, gc_type);
+		break;
+	}
+	stat_inc_seg_count(sbi, GET_SUM_TYPE((&sum->footer)));
+	stat_inc_call_count(sbi->stat_info);
+
+	f2fs_put_page(sum_page, 0);
+	return ret;
+}
+
+int f2fs_gc(struct f2fs_sb_info *sbi, int nGC)
+{
+	unsigned int segno;
+	int old_free_secs, cur_free_secs;
+	int gc_status, nfree;
+	struct list_head ilist;
+	int gc_type = BG_GC;
+
+	INIT_LIST_HEAD(&ilist);
+gc_more:
+	nfree = 0;
+	gc_status = GC_NONE;
+
+	if (has_not_enough_free_secs(sbi))
+		old_free_secs = reserved_sections(sbi);
+	else
+		old_free_secs = free_sections(sbi);
+
+	while (sbi->sb->s_flags & MS_ACTIVE) {
+		int i;
+		if (has_not_enough_free_secs(sbi))
+			gc_type = FG_GC;
+
+		cur_free_secs = free_sections(sbi) + nfree;
+
+		/* We got free space successfully. */
+		if (nGC < cur_free_secs - old_free_secs)
+			break;
+
+		if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE))
+			break;
+
+		for (i = 0; i < sbi->segs_per_sec; i++) {
+			/*
+			 * do_garbage_collect will give us three gc_status:
+			 * GC_ERROR, GC_DONE, and GC_BLOCKED.
+			 * If GC is finished uncleanly, we have to return
+			 * the victim to dirty segment list.
+			 */
+			gc_status = do_garbage_collect(sbi, segno + i,
+					&ilist, gc_type);
+			if (gc_status != GC_DONE)
+				goto stop;
+			nfree++;
+		}
+	}
+stop:
+	if (has_not_enough_free_secs(sbi) || gc_status == GC_BLOCKED) {
+		write_checkpoint(sbi, (gc_status == GC_BLOCKED), false);
+		if (nfree)
+			goto gc_more;
+	}
+	mutex_unlock(&sbi->gc_mutex);
+
+	put_gc_inode(&ilist);
+	BUG_ON(!list_empty(&ilist));
+	return gc_status;
+}
+
+void build_gc_manager(struct f2fs_sb_info *sbi)
+{
+	DIRTY_I(sbi)->v_ops = &default_v_ops;
+}
+
+int create_gc_caches(void)
+{
+	winode_slab = f2fs_kmem_cache_create("f2fs_gc_inodes",
+			sizeof(struct inode_entry), NULL);
+	if (!winode_slab)
+		return -ENOMEM;
+	return 0;
+}
+
+void destroy_gc_caches(void)
+{
+	kmem_cache_destroy(winode_slab);
+}
diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h
new file mode 100644
index 0000000..cf42a55
--- /dev/null
+++ b/fs/f2fs/gc.h
@@ -0,0 +1,117 @@
+/**
+ * fs/f2fs/gc.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#define GC_THREAD_NAME	"f2fs_gc_task"
+#define GC_THREAD_MIN_WB_PAGES		1	/*
+						 * a threshold to determine
+						 * whether IO subsystem is idle
+						 * or not
+						 */
+#define GC_THREAD_MIN_SLEEP_TIME	10000 /* milliseconds */
+#define GC_THREAD_MAX_SLEEP_TIME	30000
+#define GC_THREAD_NOGC_SLEEP_TIME	10000
+#define LIMIT_INVALID_BLOCK	40 /* percentage over total user space */
+#define LIMIT_FREE_BLOCK	40 /* percentage over invalid + free space */
+
+/* Search max. number of dirty segments to select a victim segment */
+#define MAX_VICTIM_SEARCH	20
+
+enum {
+	GC_NONE = 0,
+	GC_ERROR,
+	GC_OK,
+	GC_NEXT,
+	GC_BLOCKED,
+	GC_DONE,
+};
+
+struct f2fs_gc_kthread {
+	struct task_struct *f2fs_gc_task;
+	wait_queue_head_t gc_wait_queue_head;
+};
+
+struct inode_entry {
+	struct list_head list;
+	struct inode *inode;
+};
+
+/**
+ * inline functions
+ */
+static inline block_t free_user_blocks(struct f2fs_sb_info *sbi)
+{
+	if (free_segments(sbi) < overprovision_segments(sbi))
+		return 0;
+	else
+		return (free_segments(sbi) - overprovision_segments(sbi))
+			<< sbi->log_blocks_per_seg;
+}
+
+static inline block_t limit_invalid_user_blocks(struct f2fs_sb_info *sbi)
+{
+	return (long)(sbi->user_block_count * LIMIT_INVALID_BLOCK) / 100;
+}
+
+static inline block_t limit_free_user_blocks(struct f2fs_sb_info *sbi)
+{
+	block_t reclaimable_user_blocks = sbi->user_block_count -
+		written_block_count(sbi);
+	return (long)(reclaimable_user_blocks * LIMIT_FREE_BLOCK) / 100;
+}
+
+static inline long increase_sleep_time(long wait)
+{
+	wait += GC_THREAD_MIN_SLEEP_TIME;
+	if (wait > GC_THREAD_MAX_SLEEP_TIME)
+		wait = GC_THREAD_MAX_SLEEP_TIME;
+	return wait;
+}
+
+static inline long decrease_sleep_time(long wait)
+{
+	wait -= GC_THREAD_MIN_SLEEP_TIME;
+	if (wait <= GC_THREAD_MIN_SLEEP_TIME)
+		wait = GC_THREAD_MIN_SLEEP_TIME;
+	return wait;
+}
+
+static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)
+{
+	block_t invalid_user_blocks = sbi->user_block_count -
+					written_block_count(sbi);
+	/*
+	 * Background GC is triggered with the following condition.
+	 * 1. There are a number of invalid blocks.
+	 * 2. There is not enough free space.
+	 */
+	if (invalid_user_blocks > limit_invalid_user_blocks(sbi) &&
+			free_user_blocks(sbi) < limit_free_user_blocks(sbi))
+		return true;
+	return false;
+}
+
+static inline int is_idle(struct f2fs_sb_info *sbi)
+{
+	struct block_device *bdev = sbi->sb->s_bdev;
+	struct request_queue *q = bdev_get_queue(bdev);
+	struct request_list *rl = &q->root_rl;
+	return !(rl->count[BLK_RW_SYNC]) && !(rl->count[BLK_RW_ASYNC]);
+}
+
+static inline bool should_do_checkpoint(struct f2fs_sb_info *sbi)
+{
+	unsigned int pages_per_sec = sbi->segs_per_sec *
+					(1 << sbi->log_blocks_per_seg);
+	int node_secs = ((get_pages(sbi, F2FS_DIRTY_NODES) + pages_per_sec - 1)
+			>> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
+	int dent_secs = ((get_pages(sbi, F2FS_DIRTY_DENTS) + pages_per_sec - 1)
+			>> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
+	return free_sections(sbi) <= (node_secs + 2 * dent_secs + 2);
+}
diff --git a/fs/f2fs/hash.c b/fs/f2fs/hash.c
new file mode 100644
index 0000000..098a196
--- /dev/null
+++ b/fs/f2fs/hash.c
@@ -0,0 +1,98 @@
+/**
+ * fs/f2fs/hash.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Portions of this code from linux/fs/ext3/hash.c
+ *
+ * Copyright (C) 2002 by Theodore Ts'o
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/cryptohash.h>
+#include <linux/pagemap.h>
+
+#include "f2fs.h"
+
+/*
+ * Hashing code copied from ext3
+ */
+#define DELTA 0x9E3779B9
+
+static void TEA_transform(unsigned int buf[4], unsigned int const in[])
+{
+	__u32 sum = 0;
+	__u32 b0 = buf[0], b1 = buf[1];
+	__u32 a = in[0], b = in[1], c = in[2], d = in[3];
+	int n = 16;
+
+	do {
+		sum += DELTA;
+		b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
+		b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
+	} while (--n);
+
+	buf[0] += b0;
+	buf[1] += b1;
+}
+
+static void str2hashbuf(const char *msg, int len, unsigned int *buf, int num)
+{
+	unsigned pad, val;
+	int i;
+
+	pad = (__u32)len | ((__u32)len << 8);
+	pad |= pad << 16;
+
+	val = pad;
+	if (len > num * 4)
+		len = num * 4;
+	for (i = 0; i < len; i++) {
+		if ((i % 4) == 0)
+			val = pad;
+		val = msg[i] + (val << 8);
+		if ((i % 4) == 3) {
+			*buf++ = val;
+			val = pad;
+			num--;
+		}
+	}
+	if (--num >= 0)
+		*buf++ = val;
+	while (--num >= 0)
+		*buf++ = pad;
+}
+
+f2fs_hash_t f2fs_dentry_hash(const char *name, int len)
+{
+	__u32 hash, minor_hash;
+	f2fs_hash_t f2fs_hash;
+	const char *p;
+	__u32 in[8], buf[4];
+
+	/* Initialize the default seed for the hash checksum functions */
+	buf[0] = 0x67452301;
+	buf[1] = 0xefcdab89;
+	buf[2] = 0x98badcfe;
+	buf[3] = 0x10325476;
+
+	p = name;
+	while (len > 0) {
+		str2hashbuf(p, len, in, 4);
+		TEA_transform(buf, in);
+		len -= 16;
+		p += 16;
+	}
+	hash = buf[0];
+	minor_hash = buf[1];
+
+	f2fs_hash = hash;
+	f2fs_hash &= ~F2FS_HASH_COL_BIT;
+	return f2fs_hash;
+}
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
new file mode 100644
index 0000000..94f13d2
--- /dev/null
+++ b/fs/f2fs/inode.c
@@ -0,0 +1,266 @@
+/**
+ * fs/f2fs/inode.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/buffer_head.h>
+#include <linux/writeback.h>
+
+#include "f2fs.h"
+#include "node.h"
+
+struct f2fs_iget_args {
+	u64 ino;
+	int on_free;
+};
+
+void f2fs_set_inode_flags(struct inode *inode)
+{
+	unsigned int flags = F2FS_I(inode)->i_flags;
+
+	inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE |
+			S_NOATIME | S_DIRSYNC);
+
+	if (flags & FS_SYNC_FL)
+		inode->i_flags |= S_SYNC;
+	if (flags & FS_APPEND_FL)
+		inode->i_flags |= S_APPEND;
+	if (flags & FS_IMMUTABLE_FL)
+		inode->i_flags |= S_IMMUTABLE;
+	if (flags & FS_NOATIME_FL)
+		inode->i_flags |= S_NOATIME;
+	if (flags & FS_DIRSYNC_FL)
+		inode->i_flags |= S_DIRSYNC;
+}
+
+static int f2fs_iget_test(struct inode *inode, void *data)
+{
+	struct f2fs_iget_args *args = data;
+
+	if (inode->i_ino != args->ino)
+		return 0;
+	if (inode->i_state & (I_FREEING | I_WILL_FREE)) {
+		args->on_free = 1;
+		return 0;
+	}
+	return 1;
+}
+
+struct inode *f2fs_iget_nowait(struct super_block *sb, unsigned long ino)
+{
+	struct f2fs_iget_args args = {
+		.ino = ino,
+		.on_free = 0
+	};
+	struct inode *inode = ilookup5(sb, ino, f2fs_iget_test, &args);
+
+	if (inode)
+		return inode;
+	if (!args.on_free)
+		return f2fs_iget(sb, ino);
+	return ERR_PTR(-ENOENT);
+}
+
+static int do_read_inode(struct inode *inode)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct f2fs_inode_info *fi = F2FS_I(inode);
+	struct page *node_page;
+	struct f2fs_node *rn;
+	struct f2fs_inode *ri;
+
+	/* Check if ino is within scope */
+	check_nid_range(sbi, inode->i_ino);
+
+	node_page = get_node_page(sbi, inode->i_ino);
+	if (IS_ERR(node_page))
+		return PTR_ERR(node_page);
+
+	rn = page_address(node_page);
+	ri = &(rn->i);
+
+	inode->i_mode = le16_to_cpu(ri->i_mode);
+	i_uid_write(inode, le32_to_cpu(ri->i_uid));
+	i_gid_write(inode, le32_to_cpu(ri->i_gid));
+	set_nlink(inode, le32_to_cpu(ri->i_links));
+	inode->i_size = le64_to_cpu(ri->i_size);
+	inode->i_blocks = le64_to_cpu(ri->i_blocks);
+
+	inode->i_atime.tv_sec = le64_to_cpu(ri->i_atime);
+	inode->i_ctime.tv_sec = le64_to_cpu(ri->i_ctime);
+	inode->i_mtime.tv_sec = le64_to_cpu(ri->i_mtime);
+	inode->i_atime.tv_nsec = le32_to_cpu(ri->i_atime_nsec);
+	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);
+
+	fi->i_current_depth = le32_to_cpu(ri->i_current_depth);
+	fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid);
+	fi->i_flags = le32_to_cpu(ri->i_flags);
+	fi->flags = 0;
+	fi->data_version = le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver) - 1;
+	fi->i_advise = ri->i_advise;
+	get_extent_info(&fi->ext, ri->i_ext);
+	f2fs_put_page(node_page, 1);
+	return 0;
+}
+
+struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(sb);
+	struct inode *inode;
+	int ret;
+
+	inode = iget_locked(sb, ino);
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+	if (!(inode->i_state & I_NEW))
+		return inode;
+	if (ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi))
+		goto make_now;
+
+	ret = do_read_inode(inode);
+	if (ret)
+		goto bad_inode;
+
+	if (!sbi->por_doing && inode->i_nlink == 0) {
+		ret = -ENOENT;
+		goto bad_inode;
+	}
+
+make_now:
+	if (ino == F2FS_NODE_INO(sbi)) {
+		inode->i_mapping->a_ops = &f2fs_node_aops;
+		mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);
+	} else if (ino == F2FS_META_INO(sbi)) {
+		inode->i_mapping->a_ops = &f2fs_meta_aops;
+		mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);
+	} else if (S_ISREG(inode->i_mode)) {
+		inode->i_op = &f2fs_file_inode_operations;
+		inode->i_fop = &f2fs_file_operations;
+		inode->i_mapping->a_ops = &f2fs_dblock_aops;
+	} else if (S_ISDIR(inode->i_mode)) {
+		inode->i_op = &f2fs_dir_inode_operations;
+		inode->i_fop = &f2fs_dir_operations;
+		inode->i_mapping->a_ops = &f2fs_dblock_aops;
+		mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER_MOVABLE |
+				__GFP_ZERO);
+	} else if (S_ISLNK(inode->i_mode)) {
+		inode->i_op = &f2fs_symlink_inode_operations;
+		inode->i_mapping->a_ops = &f2fs_dblock_aops;
+	} else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
+			S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
+		inode->i_op = &f2fs_special_inode_operations;
+		init_special_inode(inode, inode->i_mode, inode->i_rdev);
+	} else {
+		ret = -EIO;
+		goto bad_inode;
+	}
+	unlock_new_inode(inode);
+
+	return inode;
+
+bad_inode:
+	iget_failed(inode);
+	return ERR_PTR(ret);
+}
+
+void update_inode(struct inode *inode, struct page *node_page)
+{
+	struct f2fs_node *rn;
+	struct f2fs_inode *ri;
+
+	wait_on_page_writeback(node_page);
+
+	rn = page_address(node_page);
+	ri = &(rn->i);
+
+	ri->i_mode = cpu_to_le16(inode->i_mode);
+	ri->i_advise = F2FS_I(inode)->i_advise;
+	ri->i_uid = cpu_to_le32(i_uid_read(inode));
+	ri->i_gid = cpu_to_le32(i_gid_read(inode));
+	ri->i_links = cpu_to_le32(inode->i_nlink);
+	ri->i_size = cpu_to_le64(i_size_read(inode));
+	ri->i_blocks = cpu_to_le64(inode->i_blocks);
+	set_raw_extent(&F2FS_I(inode)->ext, &ri->i_ext);
+
+	ri->i_atime = cpu_to_le64(inode->i_atime.tv_sec);
+	ri->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
+	ri->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec);
+	ri->i_atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec);
+	ri->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
+	ri->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
+	ri->i_current_depth = cpu_to_le32(F2FS_I(inode)->i_current_depth);
+	ri->i_xattr_nid = cpu_to_le32(F2FS_I(inode)->i_xattr_nid);
+	ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags);
+	ri->i_generation = cpu_to_le32(inode->i_generation);
+	set_page_dirty(node_page);
+}
+
+int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct page *node_page;
+	bool need_lock = false;
+
+	if (inode->i_ino == F2FS_NODE_INO(sbi) ||
+			inode->i_ino == F2FS_META_INO(sbi))
+		return 0;
+
+	node_page = get_node_page(sbi, inode->i_ino);
+	if (IS_ERR(node_page))
+		return PTR_ERR(node_page);
+
+	if (!PageDirty(node_page)) {
+		need_lock = true;
+		f2fs_put_page(node_page, 1);
+		mutex_lock(&sbi->write_inode);
+		node_page = get_node_page(sbi, inode->i_ino);
+		if (IS_ERR(node_page)) {
+			mutex_unlock(&sbi->write_inode);
+			return PTR_ERR(node_page);
+		}
+	}
+	update_inode(inode, node_page);
+	f2fs_put_page(node_page, 1);
+	if (need_lock)
+		mutex_unlock(&sbi->write_inode);
+	return 0;
+}
+
+/**
+ * Called at the last iput() if i_nlink is zero
+ */
+void f2fs_evict_inode(struct inode *inode)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+
+	truncate_inode_pages(&inode->i_data, 0);
+
+	if (inode->i_ino == F2FS_NODE_INO(sbi) ||
+			inode->i_ino == F2FS_META_INO(sbi))
+		goto no_delete;
+
+	BUG_ON(atomic_read(&F2FS_I(inode)->dirty_dents));
+	remove_dirty_dir_inode(inode);
+
+	if (inode->i_nlink || is_bad_inode(inode))
+		goto no_delete;
+
+	set_inode_flag(F2FS_I(inode), FI_NO_ALLOC);
+	i_size_write(inode, 0);
+
+	if (F2FS_HAS_BLOCKS(inode))
+		f2fs_truncate(inode);
+
+	remove_inode_page(inode);
+no_delete:
+	clear_inode(inode);
+}
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
new file mode 100644
index 0000000..aec362f
--- /dev/null
+++ b/fs/f2fs/namei.c
@@ -0,0 +1,504 @@
+/**
+ * fs/f2fs/namei.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/pagemap.h>
+#include <linux/sched.h>
+#include <linux/ctype.h>
+
+#include "f2fs.h"
+#include "xattr.h"
+#include "acl.h"
+
+static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
+{
+	struct super_block *sb = dir->i_sb;
+	struct f2fs_sb_info *sbi = F2FS_SB(sb);
+	nid_t ino;
+	struct inode *inode;
+	bool nid_free = false;
+	int err;
+
+	inode = new_inode(sb);
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+
+	mutex_lock_op(sbi, NODE_NEW);
+	if (!alloc_nid(sbi, &ino)) {
+		mutex_unlock_op(sbi, NODE_NEW);
+		err = -ENOSPC;
+		goto fail;
+	}
+	mutex_unlock_op(sbi, NODE_NEW);
+
+	inode->i_uid = current_fsuid();
+
+	if (dir->i_mode & S_ISGID) {
+		inode->i_gid = dir->i_gid;
+		if (S_ISDIR(mode))
+			mode |= S_ISGID;
+	} else {
+		inode->i_gid = current_fsgid();
+	}
+
+	inode->i_ino = ino;
+	inode->i_mode = mode;
+	inode->i_blocks = 0;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+	inode->i_generation = sbi->s_next_generation++;
+
+	err = insert_inode_locked(inode);
+	if (err) {
+		err = -EINVAL;
+		nid_free = true;
+		goto out;
+	}
+
+	mark_inode_dirty(inode);
+	return inode;
+
+out:
+	clear_nlink(inode);
+	unlock_new_inode(inode);
+fail:
+	iput(inode);
+	if (nid_free)
+		alloc_nid_failed(sbi, ino);
+	return ERR_PTR(err);
+}
+
+static int is_multimedia_file(const unsigned char *s, const char *sub)
+{
+	int slen = strlen(s);
+	int sublen = strlen(sub);
+	int ret;
+
+	if (sublen > slen)
+		return 1;
+
+	ret = memcmp(s + slen - sublen, sub, sublen);
+	if (ret) {	/* compare upper case */
+		int i;
+		char upper_sub[8];
+		for (i = 0; i < sublen && i < sizeof(upper_sub); i++)
+			upper_sub[i] = toupper(sub[i]);
+		return memcmp(s + slen - sublen, upper_sub, sublen);
+	}
+
+	return ret;
+}
+
+/**
+ * Set multimedia files as cold files for hot/cold data separation
+ */
+static inline void set_cold_file(struct f2fs_sb_info *sbi, struct inode *inode,
+		const unsigned char *name)
+{
+	int i;
+	__u8 (*extlist)[8] = sbi->raw_super->extension_list;
+
+	int count = le32_to_cpu(sbi->raw_super->extension_count);
+	for (i = 0; i < count; i++) {
+		if (!is_multimedia_file(name, extlist[i])) {
+			F2FS_I(inode)->i_advise |= FADVISE_COLD_BIT;
+			break;
+		}
+	}
+}
+
+static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+						bool excl)
+{
+	struct super_block *sb = dir->i_sb;
+	struct f2fs_sb_info *sbi = F2FS_SB(sb);
+	struct inode *inode;
+	nid_t ino = 0;
+	int err;
+
+	inode = f2fs_new_inode(dir, mode);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+
+	if (!test_opt(sbi, DISABLE_EXT_IDENTIFY))
+		set_cold_file(sbi, inode, dentry->d_name.name);
+
+	inode->i_op = &f2fs_file_inode_operations;
+	inode->i_fop = &f2fs_file_operations;
+	inode->i_mapping->a_ops = &f2fs_dblock_aops;
+	ino = inode->i_ino;
+
+	err = f2fs_add_link(dentry, inode);
+	if (err)
+		goto out;
+
+	alloc_nid_done(sbi, ino);
+
+	if (!sbi->por_doing)
+		d_instantiate(dentry, inode);
+	unlock_new_inode(inode);
+
+	f2fs_balance_fs(sbi);
+	return 0;
+out:
+	clear_nlink(inode);
+	unlock_new_inode(inode);
+	iput(inode);
+	alloc_nid_failed(sbi, ino);
+	return err;
+}
+
+static int f2fs_link(struct dentry *old_dentry, struct inode *dir,
+		struct dentry *dentry)
+{
+	struct inode *inode = old_dentry->d_inode;
+	struct super_block *sb = dir->i_sb;
+	struct f2fs_sb_info *sbi = F2FS_SB(sb);
+	int err;
+
+	inode->i_ctime = CURRENT_TIME;
+	atomic_inc(&inode->i_count);
+
+	set_inode_flag(F2FS_I(inode), FI_INC_LINK);
+	err = f2fs_add_link(dentry, inode);
+	if (err)
+		goto out;
+
+	d_instantiate(dentry, inode);
+
+	f2fs_balance_fs(sbi);
+	return 0;
+out:
+	clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
+	iput(inode);
+	return err;
+}
+
+struct dentry *f2fs_get_parent(struct dentry *child)
+{
+	struct qstr dotdot = QSTR_INIT("..", 2);
+	unsigned long ino = f2fs_inode_by_name(child->d_inode, &dotdot);
+	if (!ino)
+		return ERR_PTR(-ENOENT);
+	return d_obtain_alias(f2fs_iget(child->d_inode->i_sb, ino));
+}
+
+static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
+		unsigned int flags)
+{
+	struct inode *inode = NULL;
+	struct f2fs_dir_entry *de;
+	struct page *page;
+
+	if (dentry->d_name.len > F2FS_MAX_NAME_LEN)
+		return ERR_PTR(-ENAMETOOLONG);
+
+	de = f2fs_find_entry(dir, &dentry->d_name, &page);
+	if (de) {
+		nid_t ino = le32_to_cpu(de->ino);
+		kunmap(page);
+		f2fs_put_page(page, 0);
+
+		inode = f2fs_iget(dir->i_sb, ino);
+		if (IS_ERR(inode))
+			return ERR_CAST(inode);
+	}
+
+	return d_splice_alias(inode, dentry);
+}
+
+static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
+{
+	struct super_block *sb = dir->i_sb;
+	struct f2fs_sb_info *sbi = F2FS_SB(sb);
+	struct inode *inode = dentry->d_inode;
+	struct f2fs_dir_entry *de;
+	struct page *page;
+	int err = -ENOENT;
+
+	de = f2fs_find_entry(dir, &dentry->d_name, &page);
+	if (!de)
+		goto fail;
+
+	err = check_orphan_space(sbi);
+	if (err) {
+		kunmap(page);
+		f2fs_put_page(page, 0);
+		goto fail;
+	}
+
+	f2fs_delete_entry(de, page, inode);
+
+	/* In order to evict this inode,  we set it dirty */
+	mark_inode_dirty(inode);
+	f2fs_balance_fs(sbi);
+fail:
+	return err;
+}
+
+static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
+					const char *symname)
+{
+	struct super_block *sb = dir->i_sb;
+	struct f2fs_sb_info *sbi = F2FS_SB(sb);
+	struct inode *inode;
+	unsigned symlen = strlen(symname) + 1;
+	int err;
+
+	inode = f2fs_new_inode(dir, S_IFLNK | S_IRWXUGO);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+
+	inode->i_op = &f2fs_symlink_inode_operations;
+	inode->i_mapping->a_ops = &f2fs_dblock_aops;
+
+	err = f2fs_add_link(dentry, inode);
+	if (err)
+		goto out;
+
+	err = page_symlink(inode, symname, symlen);
+	alloc_nid_done(sbi, inode->i_ino);
+
+	d_instantiate(dentry, inode);
+	unlock_new_inode(inode);
+
+	f2fs_balance_fs(sbi);
+
+	return err;
+out:
+	clear_nlink(inode);
+	unlock_new_inode(inode);
+	iput(inode);
+	alloc_nid_failed(sbi, inode->i_ino);
+	return err;
+}
+
+static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
+	struct inode *inode;
+	int err;
+
+	inode = f2fs_new_inode(dir, S_IFDIR | mode);
+	err = PTR_ERR(inode);
+	if (IS_ERR(inode))
+		return err;
+
+	inode->i_op = &f2fs_dir_inode_operations;
+	inode->i_fop = &f2fs_dir_operations;
+	inode->i_mapping->a_ops = &f2fs_dblock_aops;
+	mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS | __GFP_ZERO);
+
+	set_inode_flag(F2FS_I(inode), FI_INC_LINK);
+	err = f2fs_add_link(dentry, inode);
+	if (err)
+		goto out_fail;
+
+	alloc_nid_done(sbi, inode->i_ino);
+
+	d_instantiate(dentry, inode);
+	unlock_new_inode(inode);
+
+	f2fs_balance_fs(sbi);
+	return 0;
+
+out_fail:
+	clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
+	clear_nlink(inode);
+	unlock_new_inode(inode);
+	iput(inode);
+	alloc_nid_failed(sbi, inode->i_ino);
+	return err;
+}
+
+static int f2fs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	struct inode *inode = dentry->d_inode;
+	if (f2fs_empty_dir(inode))
+		return f2fs_unlink(dir, dentry);
+	return -ENOTEMPTY;
+}
+
+static int f2fs_mknod(struct inode *dir, struct dentry *dentry,
+				umode_t mode, dev_t rdev)
+{
+	struct super_block *sb = dir->i_sb;
+	struct f2fs_sb_info *sbi = F2FS_SB(sb);
+	struct inode *inode;
+	int err = 0;
+
+	if (!new_valid_dev(rdev))
+		return -EINVAL;
+
+	inode = f2fs_new_inode(dir, mode);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+
+	init_special_inode(inode, inode->i_mode, rdev);
+	inode->i_op = &f2fs_special_inode_operations;
+
+	err = f2fs_add_link(dentry, inode);
+	if (err)
+		goto out;
+
+	alloc_nid_done(sbi, inode->i_ino);
+	d_instantiate(dentry, inode);
+	unlock_new_inode(inode);
+
+	f2fs_balance_fs(sbi);
+
+	return 0;
+out:
+	clear_nlink(inode);
+	unlock_new_inode(inode);
+	iput(inode);
+	alloc_nid_failed(sbi, inode->i_ino);
+	return err;
+}
+
+static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
+			struct inode *new_dir, struct dentry *new_dentry)
+{
+	struct super_block *sb = old_dir->i_sb;
+	struct f2fs_sb_info *sbi = F2FS_SB(sb);
+	struct inode *old_inode = old_dentry->d_inode;
+	struct inode *new_inode = new_dentry->d_inode;
+	struct page *old_dir_page;
+	struct page *old_page;
+	struct f2fs_dir_entry *old_dir_entry = NULL;
+	struct f2fs_dir_entry *old_entry;
+	struct f2fs_dir_entry *new_entry;
+	int err = -ENOENT;
+
+	old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page);
+	if (!old_entry)
+		goto out;
+
+	if (S_ISDIR(old_inode->i_mode)) {
+		err = -EIO;
+		old_dir_entry = f2fs_parent_dir(old_inode, &old_dir_page);
+		if (!old_dir_entry)
+			goto out_old;
+	}
+
+	mutex_lock_op(sbi, RENAME);
+
+	if (new_inode) {
+		struct page *new_page;
+
+		err = -ENOTEMPTY;
+		if (old_dir_entry && !f2fs_empty_dir(new_inode))
+			goto out_dir;
+
+		err = -ENOENT;
+		new_entry = f2fs_find_entry(new_dir, &new_dentry->d_name,
+						&new_page);
+		if (!new_entry)
+			goto out_dir;
+
+		f2fs_set_link(new_dir, new_entry, new_page, old_inode);
+
+		new_inode->i_ctime = CURRENT_TIME;
+		if (old_dir_entry)
+			drop_nlink(new_inode);
+		drop_nlink(new_inode);
+		if (!new_inode->i_nlink)
+			add_orphan_inode(sbi, new_inode->i_ino);
+		f2fs_write_inode(new_inode, NULL);
+	} else {
+		err = f2fs_add_link(new_dentry, old_inode);
+		if (err)
+			goto out_dir;
+
+		if (old_dir_entry) {
+			inc_nlink(new_dir);
+			f2fs_write_inode(new_dir, NULL);
+		}
+	}
+
+	old_inode->i_ctime = CURRENT_TIME;
+	set_inode_flag(F2FS_I(old_inode), FI_NEED_CP);
+	mark_inode_dirty(old_inode);
+
+	f2fs_delete_entry(old_entry, old_page, NULL);
+
+	if (old_dir_entry) {
+		if (old_dir != new_dir) {
+			f2fs_set_link(old_inode, old_dir_entry,
+						old_dir_page, new_dir);
+		} else {
+			kunmap(old_dir_page);
+			f2fs_put_page(old_dir_page, 0);
+		}
+		drop_nlink(old_dir);
+		f2fs_write_inode(old_dir, NULL);
+	}
+
+	mutex_unlock_op(sbi, RENAME);
+
+	f2fs_balance_fs(sbi);
+	return 0;
+
+out_dir:
+	if (old_dir_entry) {
+		kunmap(old_dir_page);
+		f2fs_put_page(old_dir_page, 0);
+	}
+	mutex_unlock_op(sbi, RENAME);
+out_old:
+	kunmap(old_page);
+	f2fs_put_page(old_page, 0);
+out:
+	return err;
+}
+
+const struct inode_operations f2fs_dir_inode_operations = {
+	.create		= f2fs_create,
+	.lookup		= f2fs_lookup,
+	.link		= f2fs_link,
+	.unlink		= f2fs_unlink,
+	.symlink	= f2fs_symlink,
+	.mkdir		= f2fs_mkdir,
+	.rmdir		= f2fs_rmdir,
+	.mknod		= f2fs_mknod,
+	.rename		= f2fs_rename,
+	.setattr	= f2fs_setattr,
+	.get_acl	= f2fs_get_acl,
+#ifdef CONFIG_F2FS_FS_XATTR
+	.setxattr	= generic_setxattr,
+	.getxattr	= generic_getxattr,
+	.listxattr	= f2fs_listxattr,
+	.removexattr	= generic_removexattr,
+#endif
+};
+
+const struct inode_operations f2fs_symlink_inode_operations = {
+	.readlink       = generic_readlink,
+	.follow_link    = page_follow_link_light,
+	.put_link       = page_put_link,
+	.setattr	= f2fs_setattr,
+#ifdef CONFIG_F2FS_FS_XATTR
+	.setxattr	= generic_setxattr,
+	.getxattr	= generic_getxattr,
+	.listxattr	= f2fs_listxattr,
+	.removexattr	= generic_removexattr,
+#endif
+};
+
+const struct inode_operations f2fs_special_inode_operations = {
+	.setattr        = f2fs_setattr,
+	.get_acl	= f2fs_get_acl,
+#ifdef CONFIG_F2FS_FS_XATTR
+	.setxattr       = generic_setxattr,
+	.getxattr       = generic_getxattr,
+	.listxattr	= f2fs_listxattr,
+	.removexattr    = generic_removexattr,
+#endif
+};
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
new file mode 100644
index 0000000..216f04d
--- /dev/null
+++ b/fs/f2fs/node.c
@@ -0,0 +1,1763 @@
+/**
+ * fs/f2fs/node.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/mpage.h>
+#include <linux/backing-dev.h>
+#include <linux/blkdev.h>
+#include <linux/pagevec.h>
+#include <linux/swap.h>
+
+#include "f2fs.h"
+#include "node.h"
+#include "segment.h"
+
+static struct kmem_cache *nat_entry_slab;
+static struct kmem_cache *free_nid_slab;
+
+static void clear_node_page_dirty(struct page *page)
+{
+	struct address_space *mapping = page->mapping;
+	struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
+	unsigned int long flags;
+
+	if (PageDirty(page)) {
+		spin_lock_irqsave(&mapping->tree_lock, flags);
+		radix_tree_tag_clear(&mapping->page_tree,
+				page_index(page),
+				PAGECACHE_TAG_DIRTY);
+		spin_unlock_irqrestore(&mapping->tree_lock, flags);
+
+		clear_page_dirty_for_io(page);
+		dec_page_count(sbi, F2FS_DIRTY_NODES);
+	}
+	ClearPageUptodate(page);
+}
+
+static struct page *get_current_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
+{
+	pgoff_t index = current_nat_addr(sbi, nid);
+	return get_meta_page(sbi, index);
+}
+
+static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
+{
+	struct page *src_page;
+	struct page *dst_page;
+	pgoff_t src_off;
+	pgoff_t dst_off;
+	void *src_addr;
+	void *dst_addr;
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+
+	src_off = current_nat_addr(sbi, nid);
+	dst_off = next_nat_addr(sbi, src_off);
+
+	/* get current nat block page with lock */
+	src_page = get_meta_page(sbi, src_off);
+
+	/* Dirty src_page means that it is already the new target NAT page. */
+	if (PageDirty(src_page))
+		return src_page;
+
+	dst_page = grab_meta_page(sbi, dst_off);
+
+	src_addr = page_address(src_page);
+	dst_addr = page_address(dst_page);
+	memcpy(dst_addr, src_addr, PAGE_CACHE_SIZE);
+	set_page_dirty(dst_page);
+	f2fs_put_page(src_page, 1);
+
+	set_to_next_nat(nm_i, nid);
+
+	return dst_page;
+}
+
+/**
+ * Readahead NAT pages
+ */
+static void ra_nat_pages(struct f2fs_sb_info *sbi, int nid)
+{
+	struct address_space *mapping = sbi->meta_inode->i_mapping;
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	struct page *page;
+	pgoff_t index;
+	int i;
+
+	for (i = 0; i < FREE_NID_PAGES; i++, nid += NAT_ENTRY_PER_BLOCK) {
+		if (nid >= nm_i->max_nid)
+			nid = 0;
+		index = current_nat_addr(sbi, nid);
+
+		page = grab_cache_page(mapping, index);
+		if (!page)
+			continue;
+		if (f2fs_readpage(sbi, page, index, READ)) {
+			f2fs_put_page(page, 1);
+			continue;
+		}
+		page_cache_release(page);
+	}
+}
+
+static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n)
+{
+	return radix_tree_lookup(&nm_i->nat_root, n);
+}
+
+static unsigned int __gang_lookup_nat_cache(struct f2fs_nm_info *nm_i,
+		nid_t start, unsigned int nr, struct nat_entry **ep)
+{
+	return radix_tree_gang_lookup(&nm_i->nat_root, (void **)ep, start, nr);
+}
+
+static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e)
+{
+	list_del(&e->list);
+	radix_tree_delete(&nm_i->nat_root, nat_get_nid(e));
+	nm_i->nat_cnt--;
+	kmem_cache_free(nat_entry_slab, e);
+}
+
+int is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid)
+{
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	struct nat_entry *e;
+	int is_cp = 1;
+
+	read_lock(&nm_i->nat_tree_lock);
+	e = __lookup_nat_cache(nm_i, nid);
+	if (e && !e->checkpointed)
+		is_cp = 0;
+	read_unlock(&nm_i->nat_tree_lock);
+	return is_cp;
+}
+
+static struct nat_entry *grab_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid)
+{
+	struct nat_entry *new;
+
+	new = kmem_cache_alloc(nat_entry_slab, GFP_ATOMIC);
+	if (!new)
+		return NULL;
+	if (radix_tree_insert(&nm_i->nat_root, nid, new)) {
+		kmem_cache_free(nat_entry_slab, new);
+		return NULL;
+	}
+	memset(new, 0, sizeof(struct nat_entry));
+	nat_set_nid(new, nid);
+	list_add_tail(&new->list, &nm_i->nat_entries);
+	nm_i->nat_cnt++;
+	return new;
+}
+
+static void cache_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid,
+						struct f2fs_nat_entry *ne)
+{
+	struct nat_entry *e;
+retry:
+	write_lock(&nm_i->nat_tree_lock);
+	e = __lookup_nat_cache(nm_i, nid);
+	if (!e) {
+		e = grab_nat_entry(nm_i, nid);
+		if (!e) {
+			write_unlock(&nm_i->nat_tree_lock);
+			goto retry;
+		}
+		nat_set_blkaddr(e, le32_to_cpu(ne->block_addr));
+		nat_set_ino(e, le32_to_cpu(ne->ino));
+		nat_set_version(e, ne->version);
+		e->checkpointed = true;
+	}
+	write_unlock(&nm_i->nat_tree_lock);
+}
+
+static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
+			block_t new_blkaddr)
+{
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	struct nat_entry *e;
+retry:
+	write_lock(&nm_i->nat_tree_lock);
+	e = __lookup_nat_cache(nm_i, ni->nid);
+	if (!e) {
+		e = grab_nat_entry(nm_i, ni->nid);
+		if (!e) {
+			write_unlock(&nm_i->nat_tree_lock);
+			goto retry;
+		}
+		e->ni = *ni;
+		e->checkpointed = true;
+		BUG_ON(ni->blk_addr == NEW_ADDR);
+	} else if (new_blkaddr == NEW_ADDR) {
+		/*
+		 * when nid is reallocated,
+		 * previous nat entry can be remained in nat cache.
+		 * So, reinitialize it with new information.
+		 */
+		e->ni = *ni;
+		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 &&
+			new_blkaddr == NULL_ADDR);
+	BUG_ON(nat_get_blkaddr(e) == NEW_ADDR &&
+			new_blkaddr == NEW_ADDR);
+	BUG_ON(nat_get_blkaddr(e) != NEW_ADDR &&
+			nat_get_blkaddr(e) != NULL_ADDR &&
+			new_blkaddr == NEW_ADDR);
+
+	/* increament version no as node is removed */
+	if (nat_get_blkaddr(e) != NEW_ADDR && new_blkaddr == NULL_ADDR) {
+		unsigned char version = nat_get_version(e);
+		nat_set_version(e, inc_node_version(version));
+	}
+
+	/* change address */
+	nat_set_blkaddr(e, new_blkaddr);
+	__set_nat_cache_dirty(nm_i, e);
+	write_unlock(&nm_i->nat_tree_lock);
+}
+
+static int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
+{
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+
+	if (nm_i->nat_cnt < 2 * NM_WOUT_THRESHOLD)
+		return 0;
+
+	write_lock(&nm_i->nat_tree_lock);
+	while (nr_shrink && !list_empty(&nm_i->nat_entries)) {
+		struct nat_entry *ne;
+		ne = list_first_entry(&nm_i->nat_entries,
+					struct nat_entry, list);
+		__del_from_nat_cache(nm_i, ne);
+		nr_shrink--;
+	}
+	write_unlock(&nm_i->nat_tree_lock);
+	return nr_shrink;
+}
+
+/**
+ * This function returns always success
+ */
+void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni)
+{
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
+	struct f2fs_summary_block *sum = curseg->sum_blk;
+	nid_t start_nid = START_NID(nid);
+	struct f2fs_nat_block *nat_blk;
+	struct page *page = NULL;
+	struct f2fs_nat_entry ne;
+	struct nat_entry *e;
+	int i;
+
+	ni->nid = nid;
+
+	/* Check nat cache */
+	read_lock(&nm_i->nat_tree_lock);
+	e = __lookup_nat_cache(nm_i, nid);
+	if (e) {
+		ni->ino = nat_get_ino(e);
+		ni->blk_addr = nat_get_blkaddr(e);
+		ni->version = nat_get_version(e);
+	}
+	read_unlock(&nm_i->nat_tree_lock);
+	if (e)
+		return;
+
+	/* Check current segment summary */
+	mutex_lock(&curseg->curseg_mutex);
+	i = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 0);
+	if (i >= 0) {
+		ne = nat_in_journal(sum, i);
+		node_info_from_raw_nat(ni, &ne);
+	}
+	mutex_unlock(&curseg->curseg_mutex);
+	if (i >= 0)
+		goto cache;
+
+	/* Fill node_info from nat page */
+	page = get_current_nat_page(sbi, start_nid);
+	nat_blk = (struct f2fs_nat_block *)page_address(page);
+	ne = nat_blk->entries[nid - start_nid];
+	node_info_from_raw_nat(ni, &ne);
+	f2fs_put_page(page, 1);
+cache:
+	/* cache nat entry */
+	cache_nat_entry(NM_I(sbi), nid, &ne);
+}
+
+/**
+ * The maximum depth is four.
+ * Offset[0] will have raw inode offset.
+ */
+static int get_node_path(long block, int offset[4], unsigned int noffset[4])
+{
+	const long direct_index = ADDRS_PER_INODE;
+	const long direct_blks = ADDRS_PER_BLOCK;
+	const long dptrs_per_blk = NIDS_PER_BLOCK;
+	const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
+	const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK;
+	int n = 0;
+	int level = 0;
+
+	noffset[0] = 0;
+
+	if (block < direct_index) {
+		offset[n++] = block;
+		level = 0;
+		goto got;
+	}
+	block -= direct_index;
+	if (block < direct_blks) {
+		offset[n++] = NODE_DIR1_BLOCK;
+		noffset[n] = 1;
+		offset[n++] = block;
+		level = 1;
+		goto got;
+	}
+	block -= direct_blks;
+	if (block < direct_blks) {
+		offset[n++] = NODE_DIR2_BLOCK;
+		noffset[n] = 2;
+		offset[n++] = block;
+		level = 1;
+		goto got;
+	}
+	block -= direct_blks;
+	if (block < indirect_blks) {
+		offset[n++] = NODE_IND1_BLOCK;
+		noffset[n] = 3;
+		offset[n++] = block / direct_blks;
+		noffset[n] = 4 + offset[n - 1];
+		offset[n++] = block % direct_blks;
+		level = 2;
+		goto got;
+	}
+	block -= indirect_blks;
+	if (block < indirect_blks) {
+		offset[n++] = NODE_IND2_BLOCK;
+		noffset[n] = 4 + dptrs_per_blk;
+		offset[n++] = block / direct_blks;
+		noffset[n] = 5 + dptrs_per_blk + offset[n - 1];
+		offset[n++] = block % direct_blks;
+		level = 2;
+		goto got;
+	}
+	block -= indirect_blks;
+	if (block < dindirect_blks) {
+		offset[n++] = NODE_DIND_BLOCK;
+		noffset[n] = 5 + (dptrs_per_blk * 2);
+		offset[n++] = block / indirect_blks;
+		noffset[n] = 6 + (dptrs_per_blk * 2) +
+			      offset[n - 1] * (dptrs_per_blk + 1);
+		offset[n++] = (block / direct_blks) % dptrs_per_blk;
+		noffset[n] = 7 + (dptrs_per_blk * 2) +
+			      offset[n - 2] * (dptrs_per_blk + 1) +
+			      offset[n - 1];
+		offset[n++] = block % direct_blks;
+		level = 3;
+		goto got;
+	} else {
+		BUG();
+	}
+got:
+	return level;
+}
+
+/*
+ * Caller should call f2fs_put_dnode(dn).
+ */
+int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int ro)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
+	struct page *npage[4];
+	struct page *parent;
+	int offset[4];
+	unsigned int noffset[4];
+	nid_t nids[4];
+	int level, i;
+	int err = 0;
+
+	level = get_node_path(index, offset, noffset);
+
+	nids[0] = dn->inode->i_ino;
+	npage[0] = get_node_page(sbi, nids[0]);
+	if (IS_ERR(npage[0]))
+		return PTR_ERR(npage[0]);
+
+	parent = npage[0];
+	nids[1] = get_nid(parent, offset[0], true);
+	dn->inode_page = npage[0];
+	dn->inode_page_locked = true;
+
+	/* get indirect or direct nodes */
+	for (i = 1; i <= level; i++) {
+		bool done = false;
+
+		if (!nids[i] && !ro) {
+			mutex_lock_op(sbi, NODE_NEW);
+
+			/* alloc new node */
+			if (!alloc_nid(sbi, &(nids[i]))) {
+				mutex_unlock_op(sbi, NODE_NEW);
+				err = -ENOSPC;
+				goto release_pages;
+			}
+
+			dn->nid = nids[i];
+			npage[i] = new_node_page(dn, noffset[i]);
+			if (IS_ERR(npage[i])) {
+				alloc_nid_failed(sbi, nids[i]);
+				mutex_unlock_op(sbi, NODE_NEW);
+				err = PTR_ERR(npage[i]);
+				goto release_pages;
+			}
+
+			set_nid(parent, offset[i - 1], nids[i], i == 1);
+			alloc_nid_done(sbi, nids[i]);
+			mutex_unlock_op(sbi, NODE_NEW);
+			done = true;
+		} else if (ro && i == level && level > 1) {
+			npage[i] = get_node_page_ra(parent, offset[i - 1]);
+			if (IS_ERR(npage[i])) {
+				err = PTR_ERR(npage[i]);
+				goto release_pages;
+			}
+			done = true;
+		}
+		if (i == 1) {
+			dn->inode_page_locked = false;
+			unlock_page(parent);
+		} else {
+			f2fs_put_page(parent, 1);
+		}
+
+		if (!done) {
+			npage[i] = get_node_page(sbi, nids[i]);
+			if (IS_ERR(npage[i])) {
+				err = PTR_ERR(npage[i]);
+				f2fs_put_page(npage[0], 0);
+				goto release_out;
+			}
+		}
+		if (i < level) {
+			parent = npage[i];
+			nids[i + 1] = get_nid(parent, offset[i], false);
+		}
+	}
+	dn->nid = nids[level];
+	dn->ofs_in_node = offset[level];
+	dn->node_page = npage[level];
+	dn->data_blkaddr = datablock_addr(dn->node_page, dn->ofs_in_node);
+	return 0;
+
+release_pages:
+	f2fs_put_page(parent, 1);
+	if (i > 1)
+		f2fs_put_page(npage[0], 0);
+release_out:
+	dn->inode_page = NULL;
+	dn->node_page = NULL;
+	return err;
+}
+
+static void truncate_node(struct dnode_of_data *dn)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
+	struct node_info ni;
+
+	get_node_info(sbi, dn->nid, &ni);
+	BUG_ON(ni.blk_addr == NULL_ADDR);
+
+	if (ni.blk_addr != NULL_ADDR)
+		invalidate_blocks(sbi, ni.blk_addr);
+
+	/* Deallocate node address */
+	dec_valid_node_count(sbi, dn->inode, 1);
+	set_node_addr(sbi, &ni, NULL_ADDR);
+
+	if (dn->nid == dn->inode->i_ino) {
+		remove_orphan_inode(sbi, dn->nid);
+		dec_valid_inode_count(sbi);
+	} else {
+		sync_inode_page(dn);
+	}
+
+	clear_node_page_dirty(dn->node_page);
+	F2FS_SET_SB_DIRT(sbi);
+
+	f2fs_put_page(dn->node_page, 1);
+	dn->node_page = NULL;
+}
+
+static int truncate_dnode(struct dnode_of_data *dn)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
+	struct page *page;
+
+	if (dn->nid == 0)
+		return 1;
+
+	/* get direct node */
+	page = get_node_page(sbi, dn->nid);
+	if (IS_ERR(page) && PTR_ERR(page) == -ENOENT)
+		return 1;
+	else if (IS_ERR(page))
+		return PTR_ERR(page);
+
+	/* Make dnode_of_data for parameter */
+	dn->node_page = page;
+	dn->ofs_in_node = 0;
+	truncate_data_blocks(dn);
+	truncate_node(dn);
+	return 1;
+}
+
+static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
+						int ofs, int depth)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
+	struct dnode_of_data rdn = *dn;
+	struct page *page;
+	struct f2fs_node *rn;
+	nid_t child_nid;
+	unsigned int child_nofs;
+	int freed = 0;
+	int i, ret;
+
+	if (dn->nid == 0)
+		return NIDS_PER_BLOCK + 1;
+
+	page = get_node_page(sbi, dn->nid);
+	if (IS_ERR(page))
+		return PTR_ERR(page);
+
+	rn = (struct f2fs_node *)page_address(page);
+	if (depth < 3) {
+		for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) {
+			child_nid = le32_to_cpu(rn->in.nid[i]);
+			if (child_nid == 0)
+				continue;
+			rdn.nid = child_nid;
+			ret = truncate_dnode(&rdn);
+			if (ret < 0)
+				goto out_err;
+			set_nid(page, i, 0, false);
+		}
+	} else {
+		child_nofs = nofs + ofs * (NIDS_PER_BLOCK + 1) + 1;
+		for (i = ofs; i < NIDS_PER_BLOCK; i++) {
+			child_nid = le32_to_cpu(rn->in.nid[i]);
+			if (child_nid == 0) {
+				child_nofs += NIDS_PER_BLOCK + 1;
+				continue;
+			}
+			rdn.nid = child_nid;
+			ret = truncate_nodes(&rdn, child_nofs, 0, depth - 1);
+			if (ret == (NIDS_PER_BLOCK + 1)) {
+				set_nid(page, i, 0, false);
+				child_nofs += ret;
+			} else if (ret < 0 && ret != -ENOENT) {
+				goto out_err;
+			}
+		}
+		freed = child_nofs;
+	}
+
+	if (!ofs) {
+		/* remove current indirect node */
+		dn->node_page = page;
+		truncate_node(dn);
+		freed++;
+	} else {
+		f2fs_put_page(page, 1);
+	}
+	return freed;
+
+out_err:
+	f2fs_put_page(page, 1);
+	return ret;
+}
+
+static int truncate_partial_nodes(struct dnode_of_data *dn,
+			struct f2fs_inode *ri, int *offset, int depth)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
+	struct page *pages[2];
+	nid_t nid[3];
+	nid_t child_nid;
+	int err = 0;
+	int i;
+	int idx = depth - 2;
+
+	nid[0] = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]);
+	if (!nid[0])
+		return 0;
+
+	/* get indirect nodes in the path */
+	for (i = 0; i < depth - 1; i++) {
+		/* refernece count'll be increased */
+		pages[i] = get_node_page(sbi, nid[i]);
+		if (IS_ERR(pages[i])) {
+			depth = i + 1;
+			err = PTR_ERR(pages[i]);
+			goto fail;
+		}
+		nid[i + 1] = get_nid(pages[i], offset[i + 1], false);
+	}
+
+	/* free direct nodes linked to a partial indirect node */
+	for (i = offset[depth - 1]; i < NIDS_PER_BLOCK; i++) {
+		child_nid = get_nid(pages[idx], i, false);
+		if (!child_nid)
+			continue;
+		dn->nid = child_nid;
+		err = truncate_dnode(dn);
+		if (err < 0)
+			goto fail;
+		set_nid(pages[idx], i, 0, false);
+	}
+
+	if (offset[depth - 1] == 0) {
+		dn->node_page = pages[idx];
+		dn->nid = nid[idx];
+		truncate_node(dn);
+	} else {
+		f2fs_put_page(pages[idx], 1);
+	}
+	offset[idx]++;
+	offset[depth - 1] = 0;
+fail:
+	for (i = depth - 3; i >= 0; i--)
+		f2fs_put_page(pages[i], 1);
+	return err;
+}
+
+/**
+ * All the block addresses of data and nodes should be nullified.
+ */
+int truncate_inode_blocks(struct inode *inode, pgoff_t from)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	int err = 0, cont = 1;
+	int level, offset[4], noffset[4];
+	unsigned int nofs;
+	struct f2fs_node *rn;
+	struct dnode_of_data dn;
+	struct page *page;
+
+	level = get_node_path(from, offset, noffset);
+
+	page = get_node_page(sbi, inode->i_ino);
+	if (IS_ERR(page))
+		return PTR_ERR(page);
+
+	set_new_dnode(&dn, inode, page, NULL, 0);
+	unlock_page(page);
+
+	rn = page_address(page);
+	switch (level) {
+	case 0:
+	case 1:
+		nofs = noffset[1];
+		break;
+	case 2:
+		nofs = noffset[1];
+		if (!offset[level - 1])
+			goto skip_partial;
+		err = truncate_partial_nodes(&dn, &rn->i, offset, level);
+		if (err < 0 && err != -ENOENT)
+			goto fail;
+		nofs += 1 + NIDS_PER_BLOCK;
+		break;
+	case 3:
+		nofs = 5 + 2 * NIDS_PER_BLOCK;
+		if (!offset[level - 1])
+			goto skip_partial;
+		err = truncate_partial_nodes(&dn, &rn->i, offset, level);
+		if (err < 0 && err != -ENOENT)
+			goto fail;
+		break;
+	default:
+		BUG();
+	}
+
+skip_partial:
+	while (cont) {
+		dn.nid = le32_to_cpu(rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK]);
+		switch (offset[0]) {
+		case NODE_DIR1_BLOCK:
+		case NODE_DIR2_BLOCK:
+			err = truncate_dnode(&dn);
+			break;
+
+		case NODE_IND1_BLOCK:
+		case NODE_IND2_BLOCK:
+			err = truncate_nodes(&dn, nofs, offset[1], 2);
+			break;
+
+		case NODE_DIND_BLOCK:
+			err = truncate_nodes(&dn, nofs, offset[1], 3);
+			cont = 0;
+			break;
+
+		default:
+			BUG();
+		}
+		if (err < 0 && err != -ENOENT)
+			goto fail;
+		if (offset[1] == 0 &&
+				rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK]) {
+			lock_page(page);
+			wait_on_page_writeback(page);
+			rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK] = 0;
+			set_page_dirty(page);
+			unlock_page(page);
+		}
+		offset[1] = 0;
+		offset[0]++;
+		nofs += err;
+	}
+fail:
+	f2fs_put_page(page, 0);
+	return err > 0 ? 0 : err;
+}
+
+int remove_inode_page(struct inode *inode)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct page *page;
+	nid_t ino = inode->i_ino;
+	struct dnode_of_data dn;
+
+	mutex_lock_op(sbi, NODE_TRUNC);
+	page = get_node_page(sbi, ino);
+	if (IS_ERR(page)) {
+		mutex_unlock_op(sbi, NODE_TRUNC);
+		return PTR_ERR(page);
+	}
+
+	if (F2FS_I(inode)->i_xattr_nid) {
+		nid_t nid = F2FS_I(inode)->i_xattr_nid;
+		struct page *npage = get_node_page(sbi, nid);
+
+		if (IS_ERR(npage)) {
+			mutex_unlock_op(sbi, NODE_TRUNC);
+			return PTR_ERR(npage);
+		}
+
+		F2FS_I(inode)->i_xattr_nid = 0;
+		set_new_dnode(&dn, inode, page, npage, nid);
+		dn.inode_page_locked = 1;
+		truncate_node(&dn);
+	}
+	if (inode->i_blocks == 1) {
+		/* inernally call f2fs_put_page() */
+		set_new_dnode(&dn, inode, page, page, ino);
+		truncate_node(&dn);
+	} else if (inode->i_blocks == 0) {
+		struct node_info ni;
+		get_node_info(sbi, inode->i_ino, &ni);
+
+		/* called after f2fs_new_inode() is failed */
+		BUG_ON(ni.blk_addr != NULL_ADDR);
+		f2fs_put_page(page, 1);
+	} else {
+		BUG();
+	}
+	mutex_unlock_op(sbi, NODE_TRUNC);
+	return 0;
+}
+
+int new_inode_page(struct inode *inode, struct dentry *dentry)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct page *page;
+	struct dnode_of_data dn;
+
+	/* allocate inode page for new inode */
+	set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino);
+	mutex_lock_op(sbi, NODE_NEW);
+	page = new_node_page(&dn, 0);
+	init_dent_inode(dentry, page);
+	mutex_unlock_op(sbi, NODE_NEW);
+	if (IS_ERR(page))
+		return PTR_ERR(page);
+	f2fs_put_page(page, 1);
+	return 0;
+}
+
+struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
+	struct address_space *mapping = sbi->node_inode->i_mapping;
+	struct node_info old_ni, new_ni;
+	struct page *page;
+	int err;
+
+	if (is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC))
+		return ERR_PTR(-EPERM);
+
+	page = grab_cache_page(mapping, dn->nid);
+	if (!page)
+		return ERR_PTR(-ENOMEM);
+
+	get_node_info(sbi, dn->nid, &old_ni);
+
+	SetPageUptodate(page);
+	fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true);
+
+	/* Reinitialize old_ni with new node page */
+	BUG_ON(old_ni.blk_addr != NULL_ADDR);
+	new_ni = old_ni;
+	new_ni.ino = dn->inode->i_ino;
+
+	if (!inc_valid_node_count(sbi, dn->inode, 1)) {
+		err = -ENOSPC;
+		goto fail;
+	}
+	set_node_addr(sbi, &new_ni, NEW_ADDR);
+
+	dn->node_page = page;
+	sync_inode_page(dn);
+	set_page_dirty(page);
+	set_cold_node(dn->inode, page);
+	if (ofs == 0)
+		inc_valid_inode_count(sbi);
+
+	return page;
+
+fail:
+	f2fs_put_page(page, 1);
+	return ERR_PTR(err);
+}
+
+static int read_node_page(struct page *page, int type)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
+	struct node_info ni;
+
+	get_node_info(sbi, page->index, &ni);
+
+	if (ni.blk_addr == NULL_ADDR)
+		return -ENOENT;
+	return f2fs_readpage(sbi, page, ni.blk_addr, type);
+}
+
+/**
+ * Readahead a node page
+ */
+void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid)
+{
+	struct address_space *mapping = sbi->node_inode->i_mapping;
+	struct page *apage;
+
+	apage = find_get_page(mapping, nid);
+	if (apage && PageUptodate(apage))
+		goto release_out;
+	f2fs_put_page(apage, 0);
+
+	apage = grab_cache_page(mapping, nid);
+	if (!apage)
+		return;
+
+	if (read_node_page(apage, READA))
+		goto unlock_out;
+
+	page_cache_release(apage);
+	return;
+
+unlock_out:
+	unlock_page(apage);
+release_out:
+	page_cache_release(apage);
+}
+
+struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid)
+{
+	int err;
+	struct page *page;
+	struct address_space *mapping = sbi->node_inode->i_mapping;
+
+	page = grab_cache_page(mapping, nid);
+	if (!page)
+		return ERR_PTR(-ENOMEM);
+
+	err = read_node_page(page, READ_SYNC);
+	if (err) {
+		f2fs_put_page(page, 1);
+		return ERR_PTR(err);
+	}
+
+	BUG_ON(nid != nid_of_node(page));
+	mark_page_accessed(page);
+	return page;
+}
+
+/**
+ * Return a locked page for the desired node page.
+ * And, readahead MAX_RA_NODE number of node pages.
+ */
+struct page *get_node_page_ra(struct page *parent, int start)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(parent->mapping->host->i_sb);
+	struct address_space *mapping = sbi->node_inode->i_mapping;
+	int i, end;
+	int err = 0;
+	nid_t nid;
+	struct page *page;
+
+	/* First, try getting the desired direct node. */
+	nid = get_nid(parent, start, false);
+	if (!nid)
+		return ERR_PTR(-ENOENT);
+
+	page = find_get_page(mapping, nid);
+	if (page && PageUptodate(page))
+		goto page_hit;
+	f2fs_put_page(page, 0);
+
+repeat:
+	page = grab_cache_page(mapping, nid);
+	if (!page)
+		return ERR_PTR(-ENOMEM);
+
+	err = read_node_page(page, READA);
+	if (err) {
+		f2fs_put_page(page, 1);
+		return ERR_PTR(err);
+	}
+
+	/* Then, try readahead for siblings of the desired node */
+	end = start + MAX_RA_NODE;
+	end = min(end, NIDS_PER_BLOCK);
+	for (i = start + 1; i < end; i++) {
+		nid = get_nid(parent, i, false);
+		if (!nid)
+			continue;
+		ra_node_page(sbi, nid);
+	}
+
+page_hit:
+	lock_page(page);
+	if (PageError(page)) {
+		f2fs_put_page(page, 1);
+		return ERR_PTR(-EIO);
+	}
+
+	/* Has the page been truncated? */
+	if (page->mapping != mapping) {
+		f2fs_put_page(page, 1);
+		goto repeat;
+	}
+	return page;
+}
+
+void sync_inode_page(struct dnode_of_data *dn)
+{
+	if (IS_INODE(dn->node_page) || dn->inode_page == dn->node_page) {
+		update_inode(dn->inode, dn->node_page);
+	} else if (dn->inode_page) {
+		if (!dn->inode_page_locked)
+			lock_page(dn->inode_page);
+		update_inode(dn->inode, dn->inode_page);
+		if (!dn->inode_page_locked)
+			unlock_page(dn->inode_page);
+	} else {
+		f2fs_write_inode(dn->inode, NULL);
+	}
+}
+
+int sync_node_pages(struct f2fs_sb_info *sbi, nid_t ino,
+					struct writeback_control *wbc)
+{
+	struct address_space *mapping = sbi->node_inode->i_mapping;
+	pgoff_t index, end;
+	struct pagevec pvec;
+	int step = ino ? 2 : 0;
+	int nwritten = 0, wrote = 0;
+
+	pagevec_init(&pvec, 0);
+
+next_step:
+	index = 0;
+	end = LONG_MAX;
+
+	while (index <= end) {
+		int i, nr_pages;
+		nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
+				PAGECACHE_TAG_DIRTY,
+				min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
+		if (nr_pages == 0)
+			break;
+
+		for (i = 0; i < nr_pages; i++) {
+			struct page *page = pvec.pages[i];
+
+			/*
+			 * flushing sequence with step:
+			 * 0. indirect nodes
+			 * 1. dentry dnodes
+			 * 2. file dnodes
+			 */
+			if (step == 0 && IS_DNODE(page))
+				continue;
+			if (step == 1 && (!IS_DNODE(page) ||
+						is_cold_node(page)))
+				continue;
+			if (step == 2 && (!IS_DNODE(page) ||
+						!is_cold_node(page)))
+				continue;
+
+			/*
+			 * If an fsync mode,
+			 * we should not skip writing node pages.
+			 */
+			if (ino && ino_of_node(page) == ino)
+				lock_page(page);
+			else if (!trylock_page(page))
+				continue;
+
+			if (unlikely(page->mapping != mapping)) {
+continue_unlock:
+				unlock_page(page);
+				continue;
+			}
+			if (ino && ino_of_node(page) != ino)
+				goto continue_unlock;
+
+			if (!PageDirty(page)) {
+				/* someone wrote it for us */
+				goto continue_unlock;
+			}
+
+			if (!clear_page_dirty_for_io(page))
+				goto continue_unlock;
+
+			/* called by fsync() */
+			if (ino && IS_DNODE(page)) {
+				int mark = !is_checkpointed_node(sbi, ino);
+				set_fsync_mark(page, 1);
+				if (IS_INODE(page))
+					set_dentry_mark(page, mark);
+				nwritten++;
+			} else {
+				set_fsync_mark(page, 0);
+				set_dentry_mark(page, 0);
+			}
+			mapping->a_ops->writepage(page, wbc);
+			wrote++;
+
+			if (--wbc->nr_to_write == 0)
+				break;
+		}
+		pagevec_release(&pvec);
+		cond_resched();
+
+		if (wbc->nr_to_write == 0) {
+			step = 2;
+			break;
+		}
+	}
+
+	if (step < 2) {
+		step++;
+		goto next_step;
+	}
+
+	if (wrote)
+		f2fs_submit_bio(sbi, NODE, wbc->sync_mode == WB_SYNC_ALL);
+
+	return nwritten;
+}
+
+static int f2fs_write_node_page(struct page *page,
+				struct writeback_control *wbc)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
+	nid_t nid;
+	unsigned int nofs;
+	block_t new_addr;
+	struct node_info ni;
+
+	if (wbc->for_reclaim) {
+		dec_page_count(sbi, F2FS_DIRTY_NODES);
+		wbc->pages_skipped++;
+		set_page_dirty(page);
+		return AOP_WRITEPAGE_ACTIVATE;
+	}
+
+	wait_on_page_writeback(page);
+
+	mutex_lock_op(sbi, NODE_WRITE);
+
+	/* get old block addr of this node page */
+	nid = nid_of_node(page);
+	nofs = ofs_of_node(page);
+	BUG_ON(page->index != nid);
+
+	get_node_info(sbi, nid, &ni);
+
+	/* This page is already truncated */
+	if (ni.blk_addr == NULL_ADDR)
+		return 0;
+
+	set_page_writeback(page);
+
+	/* insert node offset */
+	write_node_page(sbi, page, nid, ni.blk_addr, &new_addr);
+	set_node_addr(sbi, &ni, new_addr);
+	dec_page_count(sbi, F2FS_DIRTY_NODES);
+
+	mutex_unlock_op(sbi, NODE_WRITE);
+	unlock_page(page);
+	return 0;
+}
+
+static int f2fs_write_node_pages(struct address_space *mapping,
+			    struct writeback_control *wbc)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
+	struct block_device *bdev = sbi->sb->s_bdev;
+	long nr_to_write = wbc->nr_to_write;
+
+	if (wbc->for_kupdate)
+		return 0;
+
+	if (get_pages(sbi, F2FS_DIRTY_NODES) == 0)
+		return 0;
+
+	if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) {
+		write_checkpoint(sbi, false, false);
+		return 0;
+	}
+
+	/* if mounting is failed, skip writing node pages */
+	wbc->nr_to_write = bio_get_nr_vecs(bdev);
+	sync_node_pages(sbi, 0, wbc);
+	wbc->nr_to_write = nr_to_write -
+		(bio_get_nr_vecs(bdev) - wbc->nr_to_write);
+	return 0;
+}
+
+static int f2fs_set_node_page_dirty(struct page *page)
+{
+	struct address_space *mapping = page->mapping;
+	struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
+
+	SetPageUptodate(page);
+	if (!PageDirty(page)) {
+		__set_page_dirty_nobuffers(page);
+		inc_page_count(sbi, F2FS_DIRTY_NODES);
+		SetPagePrivate(page);
+		return 1;
+	}
+	return 0;
+}
+
+static void f2fs_invalidate_node_page(struct page *page, unsigned long offset)
+{
+	struct inode *inode = page->mapping->host;
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	if (PageDirty(page))
+		dec_page_count(sbi, F2FS_DIRTY_NODES);
+	ClearPagePrivate(page);
+}
+
+static int f2fs_release_node_page(struct page *page, gfp_t wait)
+{
+	ClearPagePrivate(page);
+	return 0;
+}
+
+/**
+ * Structure of the f2fs node operations
+ */
+const struct address_space_operations f2fs_node_aops = {
+	.writepage	= f2fs_write_node_page,
+	.writepages	= f2fs_write_node_pages,
+	.set_page_dirty	= f2fs_set_node_page_dirty,
+	.invalidatepage	= f2fs_invalidate_node_page,
+	.releasepage	= f2fs_release_node_page,
+};
+
+static struct free_nid *__lookup_free_nid_list(nid_t n, struct list_head *head)
+{
+	struct list_head *this;
+	struct free_nid *i = NULL;
+	list_for_each(this, head) {
+		i = list_entry(this, struct free_nid, list);
+		if (i->nid == n)
+			break;
+		i = NULL;
+	}
+	return i;
+}
+
+static void __del_from_free_nid_list(struct free_nid *i)
+{
+	list_del(&i->list);
+	kmem_cache_free(free_nid_slab, i);
+}
+
+static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid)
+{
+	struct free_nid *i;
+
+	if (nm_i->fcnt > 2 * MAX_FREE_NIDS)
+		return 0;
+retry:
+	i = kmem_cache_alloc(free_nid_slab, GFP_NOFS);
+	if (!i) {
+		cond_resched();
+		goto retry;
+	}
+	i->nid = nid;
+	i->state = NID_NEW;
+
+	spin_lock(&nm_i->free_nid_list_lock);
+	if (__lookup_free_nid_list(nid, &nm_i->free_nid_list)) {
+		spin_unlock(&nm_i->free_nid_list_lock);
+		kmem_cache_free(free_nid_slab, i);
+		return 0;
+	}
+	list_add_tail(&i->list, &nm_i->free_nid_list);
+	nm_i->fcnt++;
+	spin_unlock(&nm_i->free_nid_list_lock);
+	return 1;
+}
+
+static void remove_free_nid(struct f2fs_nm_info *nm_i, nid_t nid)
+{
+	struct free_nid *i;
+	spin_lock(&nm_i->free_nid_list_lock);
+	i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
+	if (i && i->state == NID_NEW) {
+		__del_from_free_nid_list(i);
+		nm_i->fcnt--;
+	}
+	spin_unlock(&nm_i->free_nid_list_lock);
+}
+
+static int scan_nat_page(struct f2fs_nm_info *nm_i,
+			struct page *nat_page, nid_t start_nid)
+{
+	struct f2fs_nat_block *nat_blk = page_address(nat_page);
+	block_t blk_addr;
+	int fcnt = 0;
+	int i;
+
+	/* 0 nid should not be used */
+	if (start_nid == 0)
+		++start_nid;
+
+	i = start_nid % NAT_ENTRY_PER_BLOCK;
+
+	for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) {
+		blk_addr  = le32_to_cpu(nat_blk->entries[i].block_addr);
+		BUG_ON(blk_addr == NEW_ADDR);
+		if (blk_addr == NULL_ADDR)
+			fcnt += add_free_nid(nm_i, start_nid);
+	}
+	return fcnt;
+}
+
+static void build_free_nids(struct f2fs_sb_info *sbi)
+{
+	struct free_nid *fnid, *next_fnid;
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
+	struct f2fs_summary_block *sum = curseg->sum_blk;
+	nid_t nid = 0;
+	bool is_cycled = false;
+	int fcnt = 0;
+	int i;
+
+	nid = nm_i->next_scan_nid;
+	nm_i->init_scan_nid = nid;
+
+	ra_nat_pages(sbi, nid);
+
+	while (1) {
+		struct page *page = get_current_nat_page(sbi, nid);
+
+		fcnt += scan_nat_page(nm_i, page, nid);
+		f2fs_put_page(page, 1);
+
+		nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK));
+
+		if (nid >= nm_i->max_nid) {
+			nid = 0;
+			is_cycled = true;
+		}
+		if (fcnt > MAX_FREE_NIDS)
+			break;
+		if (is_cycled && nm_i->init_scan_nid <= nid)
+			break;
+	}
+
+	nm_i->next_scan_nid = nid;
+
+	/* find free nids from current sum_pages */
+	mutex_lock(&curseg->curseg_mutex);
+	for (i = 0; i < nats_in_cursum(sum); i++) {
+		block_t addr = le32_to_cpu(nat_in_journal(sum, i).block_addr);
+		nid = le32_to_cpu(nid_in_journal(sum, i));
+		if (addr == NULL_ADDR)
+			add_free_nid(nm_i, nid);
+		else
+			remove_free_nid(nm_i, nid);
+	}
+	mutex_unlock(&curseg->curseg_mutex);
+
+	/* remove the free nids from current allocated nids */
+	list_for_each_entry_safe(fnid, next_fnid, &nm_i->free_nid_list, list) {
+		struct nat_entry *ne;
+
+		read_lock(&nm_i->nat_tree_lock);
+		ne = __lookup_nat_cache(nm_i, fnid->nid);
+		if (ne && nat_get_blkaddr(ne) != NULL_ADDR)
+			remove_free_nid(nm_i, fnid->nid);
+		read_unlock(&nm_i->nat_tree_lock);
+	}
+}
+
+/*
+ * If this function returns success, caller can obtain a new nid
+ * from second parameter of this function.
+ * The returned nid could be used ino as well as nid when inode is created.
+ */
+bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid)
+{
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	struct free_nid *i = NULL;
+	struct list_head *this;
+retry:
+	mutex_lock(&nm_i->build_lock);
+	if (!nm_i->fcnt) {
+		/* scan NAT in order to build free nid list */
+		build_free_nids(sbi);
+		if (!nm_i->fcnt) {
+			mutex_unlock(&nm_i->build_lock);
+			return false;
+		}
+	}
+	mutex_unlock(&nm_i->build_lock);
+
+	/*
+	 * We check fcnt again since previous check is racy as
+	 * we didn't hold free_nid_list_lock. So other thread
+	 * could consume all of free nids.
+	 */
+	spin_lock(&nm_i->free_nid_list_lock);
+	if (!nm_i->fcnt) {
+		spin_unlock(&nm_i->free_nid_list_lock);
+		goto retry;
+	}
+
+	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);
+	*nid = i->nid;
+	i->state = NID_ALLOC;
+	nm_i->fcnt--;
+	spin_unlock(&nm_i->free_nid_list_lock);
+	return true;
+}
+
+/**
+ * alloc_nid() should be called prior to this function.
+ */
+void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid)
+{
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	struct free_nid *i;
+
+	spin_lock(&nm_i->free_nid_list_lock);
+	i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
+	if (i) {
+		BUG_ON(i->state != NID_ALLOC);
+		__del_from_free_nid_list(i);
+	}
+	spin_unlock(&nm_i->free_nid_list_lock);
+}
+
+/**
+ * alloc_nid() should be called prior to this function.
+ */
+void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
+{
+	alloc_nid_done(sbi, nid);
+	add_free_nid(NM_I(sbi), nid);
+}
+
+void recover_node_page(struct f2fs_sb_info *sbi, struct page *page,
+		struct f2fs_summary *sum, struct node_info *ni,
+		block_t new_blkaddr)
+{
+	rewrite_node_page(sbi, page, sum, ni->blk_addr, new_blkaddr);
+	set_node_addr(sbi, ni, new_blkaddr);
+	clear_node_page_dirty(page);
+}
+
+int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
+{
+	struct address_space *mapping = sbi->node_inode->i_mapping;
+	struct f2fs_node *src, *dst;
+	nid_t ino = ino_of_node(page);
+	struct node_info old_ni, new_ni;
+	struct page *ipage;
+
+	ipage = grab_cache_page(mapping, ino);
+	if (!ipage)
+		return -ENOMEM;
+
+	/* Should not use this inode  from free nid list */
+	remove_free_nid(NM_I(sbi), ino);
+
+	get_node_info(sbi, ino, &old_ni);
+	SetPageUptodate(ipage);
+	fill_node_footer(ipage, ino, ino, 0, true);
+
+	src = (struct f2fs_node *)page_address(page);
+	dst = (struct f2fs_node *)page_address(ipage);
+
+	memcpy(dst, src, (unsigned long)&src->i.i_ext - (unsigned long)&src->i);
+	dst->i.i_size = 0;
+	dst->i.i_blocks = 1;
+	dst->i.i_links = 1;
+	dst->i.i_xattr_nid = 0;
+
+	new_ni = old_ni;
+	new_ni.ino = ino;
+
+	set_node_addr(sbi, &new_ni, NEW_ADDR);
+	inc_valid_inode_count(sbi);
+
+	f2fs_put_page(ipage, 1);
+	return 0;
+}
+
+int restore_node_summary(struct f2fs_sb_info *sbi,
+			unsigned int segno, struct f2fs_summary_block *sum)
+{
+	struct f2fs_node *rn;
+	struct f2fs_summary *sum_entry;
+	struct page *page;
+	block_t addr;
+	int i, last_offset;
+
+	/* alloc temporal page for read node */
+	page = alloc_page(GFP_NOFS | __GFP_ZERO);
+	if (IS_ERR(page))
+		return PTR_ERR(page);
+	lock_page(page);
+
+	/* scan the node segment */
+	last_offset = sbi->blocks_per_seg;
+	addr = START_BLOCK(sbi, segno);
+	sum_entry = &sum->entries[0];
+
+	for (i = 0; i < last_offset; i++, sum_entry++) {
+		if (f2fs_readpage(sbi, page, addr, READ_SYNC))
+			goto out;
+
+		rn = (struct f2fs_node *)page_address(page);
+		sum_entry->nid = rn->footer.nid;
+		sum_entry->version = 0;
+		sum_entry->ofs_in_node = 0;
+		addr++;
+
+		/*
+		 * In order to read next node page,
+		 * we must clear PageUptodate flag.
+		 */
+		ClearPageUptodate(page);
+	}
+out:
+	unlock_page(page);
+	__free_pages(page, 0);
+	return 0;
+}
+
+static bool flush_nats_in_journal(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
+	struct f2fs_summary_block *sum = curseg->sum_blk;
+	int i;
+
+	mutex_lock(&curseg->curseg_mutex);
+
+	if (nats_in_cursum(sum) < NAT_JOURNAL_ENTRIES) {
+		mutex_unlock(&curseg->curseg_mutex);
+		return false;
+	}
+
+	for (i = 0; i < nats_in_cursum(sum); i++) {
+		struct nat_entry *ne;
+		struct f2fs_nat_entry raw_ne;
+		nid_t nid = le32_to_cpu(nid_in_journal(sum, i));
+
+		raw_ne = nat_in_journal(sum, i);
+retry:
+		write_lock(&nm_i->nat_tree_lock);
+		ne = __lookup_nat_cache(nm_i, nid);
+		if (ne) {
+			__set_nat_cache_dirty(nm_i, ne);
+			write_unlock(&nm_i->nat_tree_lock);
+			continue;
+		}
+		ne = grab_nat_entry(nm_i, nid);
+		if (!ne) {
+			write_unlock(&nm_i->nat_tree_lock);
+			goto retry;
+		}
+		nat_set_blkaddr(ne, le32_to_cpu(raw_ne.block_addr));
+		nat_set_ino(ne, le32_to_cpu(raw_ne.ino));
+		nat_set_version(ne, raw_ne.version);
+		__set_nat_cache_dirty(nm_i, ne);
+		write_unlock(&nm_i->nat_tree_lock);
+	}
+	update_nats_in_cursum(sum, -i);
+	mutex_unlock(&curseg->curseg_mutex);
+	return true;
+}
+
+/**
+ * This function is called during the checkpointing process.
+ */
+void flush_nat_entries(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
+	struct f2fs_summary_block *sum = curseg->sum_blk;
+	struct list_head *cur, *n;
+	struct page *page = NULL;
+	struct f2fs_nat_block *nat_blk = NULL;
+	nid_t start_nid = 0, end_nid = 0;
+	bool flushed;
+
+	flushed = flush_nats_in_journal(sbi);
+
+	if (!flushed)
+		mutex_lock(&curseg->curseg_mutex);
+
+	/* 1) flush dirty nat caches */
+	list_for_each_safe(cur, n, &nm_i->dirty_nat_entries) {
+		struct nat_entry *ne;
+		nid_t nid;
+		struct f2fs_nat_entry raw_ne;
+		int offset = -1;
+		block_t old_blkaddr, new_blkaddr;
+
+		ne = list_entry(cur, struct nat_entry, list);
+		nid = nat_get_nid(ne);
+
+		if (nat_get_blkaddr(ne) == NEW_ADDR)
+			continue;
+		if (flushed)
+			goto to_nat_page;
+
+		/* if there is room for nat enries in curseg->sumpage */
+		offset = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 1);
+		if (offset >= 0) {
+			raw_ne = nat_in_journal(sum, offset);
+			old_blkaddr = le32_to_cpu(raw_ne.block_addr);
+			goto flush_now;
+		}
+to_nat_page:
+		if (!page || (start_nid > nid || nid > end_nid)) {
+			if (page) {
+				f2fs_put_page(page, 1);
+				page = NULL;
+			}
+			start_nid = START_NID(nid);
+			end_nid = start_nid + NAT_ENTRY_PER_BLOCK - 1;
+
+			/*
+			 * get nat block with dirty flag, increased reference
+			 * count, mapped and lock
+			 */
+			page = get_next_nat_page(sbi, start_nid);
+			nat_blk = page_address(page);
+		}
+
+		BUG_ON(!nat_blk);
+		raw_ne = nat_blk->entries[nid - start_nid];
+		old_blkaddr = le32_to_cpu(raw_ne.block_addr);
+flush_now:
+		new_blkaddr = nat_get_blkaddr(ne);
+
+		raw_ne.ino = cpu_to_le32(nat_get_ino(ne));
+		raw_ne.block_addr = cpu_to_le32(new_blkaddr);
+		raw_ne.version = nat_get_version(ne);
+
+		if (offset < 0) {
+			nat_blk->entries[nid - start_nid] = raw_ne;
+		} else {
+			nat_in_journal(sum, offset) = raw_ne;
+			nid_in_journal(sum, offset) = cpu_to_le32(nid);
+		}
+
+		if (nat_get_blkaddr(ne) == NULL_ADDR) {
+			write_lock(&nm_i->nat_tree_lock);
+			__del_from_nat_cache(nm_i, ne);
+			write_unlock(&nm_i->nat_tree_lock);
+
+			/* We can reuse this freed nid at this point */
+			add_free_nid(NM_I(sbi), nid);
+		} else {
+			write_lock(&nm_i->nat_tree_lock);
+			__clear_nat_cache_dirty(nm_i, ne);
+			ne->checkpointed = true;
+			write_unlock(&nm_i->nat_tree_lock);
+		}
+	}
+	if (!flushed)
+		mutex_unlock(&curseg->curseg_mutex);
+	f2fs_put_page(page, 1);
+
+	/* 2) shrink nat caches if necessary */
+	try_to_free_nats(sbi, nm_i->nat_cnt - NM_WOUT_THRESHOLD);
+}
+
+static int init_node_manager(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_super_block *sb_raw = F2FS_RAW_SUPER(sbi);
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	unsigned char *version_bitmap;
+	unsigned int nat_segs, nat_blocks;
+
+	nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr);
+
+	/* segment_count_nat includes pair segment so divide to 2. */
+	nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1;
+	nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg);
+	nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks;
+	nm_i->fcnt = 0;
+	nm_i->nat_cnt = 0;
+
+	INIT_LIST_HEAD(&nm_i->free_nid_list);
+	INIT_RADIX_TREE(&nm_i->nat_root, GFP_ATOMIC);
+	INIT_LIST_HEAD(&nm_i->nat_entries);
+	INIT_LIST_HEAD(&nm_i->dirty_nat_entries);
+
+	mutex_init(&nm_i->build_lock);
+	spin_lock_init(&nm_i->free_nid_list_lock);
+	rwlock_init(&nm_i->nat_tree_lock);
+
+	nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP);
+	nm_i->init_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid);
+	nm_i->next_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid);
+
+	nm_i->nat_bitmap = kzalloc(nm_i->bitmap_size, GFP_KERNEL);
+	if (!nm_i->nat_bitmap)
+		return -ENOMEM;
+	version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP);
+	if (!version_bitmap)
+		return -EFAULT;
+
+	/* copy version bitmap */
+	memcpy(nm_i->nat_bitmap, version_bitmap, nm_i->bitmap_size);
+	return 0;
+}
+
+int build_node_manager(struct f2fs_sb_info *sbi)
+{
+	int err;
+
+	sbi->nm_info = kzalloc(sizeof(struct f2fs_nm_info), GFP_KERNEL);
+	if (!sbi->nm_info)
+		return -ENOMEM;
+
+	err = init_node_manager(sbi);
+	if (err)
+		return err;
+
+	build_free_nids(sbi);
+	return 0;
+}
+
+void destroy_node_manager(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	struct free_nid *i, *next_i;
+	struct nat_entry *natvec[NATVEC_SIZE];
+	nid_t nid = 0;
+	unsigned int found;
+
+	if (!nm_i)
+		return;
+
+	/* 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);
+		__del_from_free_nid_list(i);
+		nm_i->fcnt--;
+	}
+	BUG_ON(nm_i->fcnt);
+	spin_unlock(&nm_i->free_nid_list_lock);
+
+	/* destroy nat cache */
+	write_lock(&nm_i->nat_tree_lock);
+	while ((found = __gang_lookup_nat_cache(nm_i,
+					nid, NATVEC_SIZE, natvec))) {
+		unsigned idx;
+		for (idx = 0; idx < found; idx++) {
+			struct nat_entry *e = natvec[idx];
+			nid = nat_get_nid(e) + 1;
+			__del_from_nat_cache(nm_i, e);
+		}
+	}
+	BUG_ON(nm_i->nat_cnt);
+	write_unlock(&nm_i->nat_tree_lock);
+
+	kfree(nm_i->nat_bitmap);
+	sbi->nm_info = NULL;
+	kfree(nm_i);
+}
+
+int create_node_manager_caches(void)
+{
+	nat_entry_slab = f2fs_kmem_cache_create("nat_entry",
+			sizeof(struct nat_entry), NULL);
+	if (!nat_entry_slab)
+		return -ENOMEM;
+
+	free_nid_slab = f2fs_kmem_cache_create("free_nid",
+			sizeof(struct free_nid), NULL);
+	if (!free_nid_slab) {
+		kmem_cache_destroy(nat_entry_slab);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+void destroy_node_manager_caches(void)
+{
+	kmem_cache_destroy(free_nid_slab);
+	kmem_cache_destroy(nat_entry_slab);
+}
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
new file mode 100644
index 0000000..5d525ed
--- /dev/null
+++ b/fs/f2fs/node.h
@@ -0,0 +1,353 @@
+/**
+ * fs/f2fs/node.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/* start node id of a node block dedicated to the given node id */
+#define	START_NID(nid) ((nid / NAT_ENTRY_PER_BLOCK) * NAT_ENTRY_PER_BLOCK)
+
+/* node block offset on the NAT area dedicated to the given start node id */
+#define	NAT_BLOCK_OFFSET(start_nid) (start_nid / NAT_ENTRY_PER_BLOCK)
+
+/* # of pages to perform readahead before building free nids */
+#define FREE_NID_PAGES 4
+
+/* maximum # of free node ids to produce during build_free_nids */
+#define MAX_FREE_NIDS (NAT_ENTRY_PER_BLOCK * FREE_NID_PAGES)
+
+/* maximum readahead size for node during getting data blocks */
+#define MAX_RA_NODE		128
+
+/* maximum cached nat entries to manage memory footprint */
+#define NM_WOUT_THRESHOLD	(64 * NAT_ENTRY_PER_BLOCK)
+
+/* vector size for gang look-up from nat cache that consists of radix tree */
+#define NATVEC_SIZE	64
+
+/*
+ * For node information
+ */
+struct node_info {
+	nid_t nid;		/* node id */
+	nid_t ino;		/* inode number of the node's owner */
+	block_t	blk_addr;	/* block address of the node */
+	unsigned char version;	/* version of the node */
+};
+
+struct nat_entry {
+	struct list_head list;	/* for clean or dirty nat list */
+	bool checkpointed;	/* whether it is checkpointed or not */
+	struct node_info ni;	/* in-memory node information */
+};
+
+#define nat_get_nid(nat)		(nat->ni.nid)
+#define nat_set_nid(nat, n)		(nat->ni.nid = n)
+#define nat_get_blkaddr(nat)		(nat->ni.blk_addr)
+#define nat_set_blkaddr(nat, b)		(nat->ni.blk_addr = b)
+#define nat_get_ino(nat)		(nat->ni.ino)
+#define nat_set_ino(nat, i)		(nat->ni.ino = i)
+#define nat_get_version(nat)		(nat->ni.version)
+#define nat_set_version(nat, v)		(nat->ni.version = v)
+
+#define __set_nat_cache_dirty(nm_i, ne)					\
+	list_move_tail(&ne->list, &nm_i->dirty_nat_entries);
+#define __clear_nat_cache_dirty(nm_i, ne)				\
+	list_move_tail(&ne->list, &nm_i->nat_entries);
+#define inc_node_version(version)	(++version)
+
+static inline void node_info_from_raw_nat(struct node_info *ni,
+						struct f2fs_nat_entry *raw_ne)
+{
+	ni->ino = le32_to_cpu(raw_ne->ino);
+	ni->blk_addr = le32_to_cpu(raw_ne->block_addr);
+	ni->version = raw_ne->version;
+}
+
+/*
+ * For free nid mangement
+ */
+enum nid_state {
+	NID_NEW,	/* newly added to free nid list */
+	NID_ALLOC	/* it is allocated */
+};
+
+struct free_nid {
+	struct list_head list;	/* for free node id list */
+	nid_t nid;		/* node id */
+	int state;		/* in use or not: NID_NEW or NID_ALLOC */
+};
+
+static inline int next_free_nid(struct f2fs_sb_info *sbi, nid_t *nid)
+{
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	struct free_nid *fnid;
+
+	if (nm_i->fcnt <= 0)
+		return -1;
+	spin_lock(&nm_i->free_nid_list_lock);
+	fnid = list_entry(nm_i->free_nid_list.next, struct free_nid, list);
+	*nid = fnid->nid;
+	spin_unlock(&nm_i->free_nid_list_lock);
+	return 0;
+}
+
+/*
+ * inline functions
+ */
+static inline void get_nat_bitmap(struct f2fs_sb_info *sbi, void *addr)
+{
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	memcpy(addr, nm_i->nat_bitmap, nm_i->bitmap_size);
+}
+
+static inline pgoff_t current_nat_addr(struct f2fs_sb_info *sbi, nid_t start)
+{
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	pgoff_t block_off;
+	pgoff_t block_addr;
+	int seg_off;
+
+	block_off = NAT_BLOCK_OFFSET(start);
+	seg_off = block_off >> sbi->log_blocks_per_seg;
+
+	block_addr = (pgoff_t)(nm_i->nat_blkaddr +
+		(seg_off << sbi->log_blocks_per_seg << 1) +
+		(block_off & ((1 << sbi->log_blocks_per_seg) - 1)));
+
+	if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
+		block_addr += sbi->blocks_per_seg;
+
+	return block_addr;
+}
+
+static inline pgoff_t next_nat_addr(struct f2fs_sb_info *sbi,
+						pgoff_t block_addr)
+{
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+
+	block_addr -= nm_i->nat_blkaddr;
+	if ((block_addr >> sbi->log_blocks_per_seg) % 2)
+		block_addr -= sbi->blocks_per_seg;
+	else
+		block_addr += sbi->blocks_per_seg;
+
+	return block_addr + nm_i->nat_blkaddr;
+}
+
+static inline void set_to_next_nat(struct f2fs_nm_info *nm_i, nid_t start_nid)
+{
+	unsigned int block_off = NAT_BLOCK_OFFSET(start_nid);
+
+	if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
+		f2fs_clear_bit(block_off, nm_i->nat_bitmap);
+	else
+		f2fs_set_bit(block_off, nm_i->nat_bitmap);
+}
+
+static inline void fill_node_footer(struct page *page, nid_t nid,
+				nid_t ino, unsigned int ofs, bool reset)
+{
+	void *kaddr = page_address(page);
+	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	if (reset)
+		memset(rn, 0, sizeof(*rn));
+	rn->footer.nid = cpu_to_le32(nid);
+	rn->footer.ino = cpu_to_le32(ino);
+	rn->footer.flag = cpu_to_le32(ofs << OFFSET_BIT_SHIFT);
+}
+
+static inline void copy_node_footer(struct page *dst, struct page *src)
+{
+	void *src_addr = page_address(src);
+	void *dst_addr = page_address(dst);
+	struct f2fs_node *src_rn = (struct f2fs_node *)src_addr;
+	struct f2fs_node *dst_rn = (struct f2fs_node *)dst_addr;
+	memcpy(&dst_rn->footer, &src_rn->footer, sizeof(struct node_footer));
+}
+
+static inline void fill_node_footer_blkaddr(struct page *page, block_t blkaddr)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	void *kaddr = page_address(page);
+	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	rn->footer.cp_ver = ckpt->checkpoint_ver;
+	rn->footer.next_blkaddr = blkaddr;
+}
+
+static inline nid_t ino_of_node(struct page *node_page)
+{
+	void *kaddr = page_address(node_page);
+	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	return le32_to_cpu(rn->footer.ino);
+}
+
+static inline nid_t nid_of_node(struct page *node_page)
+{
+	void *kaddr = page_address(node_page);
+	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	return le32_to_cpu(rn->footer.nid);
+}
+
+static inline unsigned int ofs_of_node(struct page *node_page)
+{
+	void *kaddr = page_address(node_page);
+	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	unsigned flag = le32_to_cpu(rn->footer.flag);
+	return flag >> OFFSET_BIT_SHIFT;
+}
+
+static inline unsigned long long cpver_of_node(struct page *node_page)
+{
+	void *kaddr = page_address(node_page);
+	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	return le64_to_cpu(rn->footer.cp_ver);
+}
+
+static inline block_t next_blkaddr_of_node(struct page *node_page)
+{
+	void *kaddr = page_address(node_page);
+	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	return le32_to_cpu(rn->footer.next_blkaddr);
+}
+
+/*
+ * f2fs assigns the following node offsets described as (num).
+ * N = NIDS_PER_BLOCK
+ *
+ *  Inode block (0)
+ *    |- direct node (1)
+ *    |- direct node (2)
+ *    |- indirect node (3)
+ *    |            `- direct node (4 => 4 + N - 1)
+ *    |- indirect node (4 + N)
+ *    |            `- direct node (5 + N => 5 + 2N - 1)
+ *    `- double indirect node (5 + 2N)
+ *                 `- indirect node (6 + 2N)
+ *                       `- direct node (x(N + 1))
+ */
+static inline bool IS_DNODE(struct page *node_page)
+{
+	unsigned int ofs = ofs_of_node(node_page);
+	if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK ||
+			ofs == 5 + 2 * NIDS_PER_BLOCK)
+		return false;
+	if (ofs >= 6 + 2 * NIDS_PER_BLOCK) {
+		ofs -= 6 + 2 * NIDS_PER_BLOCK;
+		if ((long int)ofs % (NIDS_PER_BLOCK + 1))
+			return false;
+	}
+	return true;
+}
+
+static inline void set_nid(struct page *p, int off, nid_t nid, bool i)
+{
+	struct f2fs_node *rn = (struct f2fs_node *)page_address(p);
+
+	wait_on_page_writeback(p);
+
+	if (i)
+		rn->i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid);
+	else
+		rn->in.nid[off] = cpu_to_le32(nid);
+	set_page_dirty(p);
+}
+
+static inline nid_t get_nid(struct page *p, int off, bool i)
+{
+	struct f2fs_node *rn = (struct f2fs_node *)page_address(p);
+	if (i)
+		return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]);
+	return le32_to_cpu(rn->in.nid[off]);
+}
+
+/*
+ * Coldness identification:
+ *  - Mark cold files in f2fs_inode_info
+ *  - Mark cold node blocks in their node footer
+ *  - Mark cold data pages in page cache
+ */
+static inline int is_cold_file(struct inode *inode)
+{
+	return F2FS_I(inode)->i_advise & FADVISE_COLD_BIT;
+}
+
+static inline int is_cold_data(struct page *page)
+{
+	return PageChecked(page);
+}
+
+static inline void set_cold_data(struct page *page)
+{
+	SetPageChecked(page);
+}
+
+static inline void clear_cold_data(struct page *page)
+{
+	ClearPageChecked(page);
+}
+
+static inline int is_cold_node(struct page *page)
+{
+	void *kaddr = page_address(page);
+	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	unsigned int flag = le32_to_cpu(rn->footer.flag);
+	return flag & (0x1 << COLD_BIT_SHIFT);
+}
+
+static inline unsigned char is_fsync_dnode(struct page *page)
+{
+	void *kaddr = page_address(page);
+	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	unsigned int flag = le32_to_cpu(rn->footer.flag);
+	return flag & (0x1 << FSYNC_BIT_SHIFT);
+}
+
+static inline unsigned char is_dent_dnode(struct page *page)
+{
+	void *kaddr = page_address(page);
+	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	unsigned int flag = le32_to_cpu(rn->footer.flag);
+	return flag & (0x1 << DENT_BIT_SHIFT);
+}
+
+static inline void set_cold_node(struct inode *inode, struct page *page)
+{
+	struct f2fs_node *rn = (struct f2fs_node *)page_address(page);
+	unsigned int flag = le32_to_cpu(rn->footer.flag);
+
+	if (S_ISDIR(inode->i_mode))
+		flag &= ~(0x1 << COLD_BIT_SHIFT);
+	else
+		flag |= (0x1 << COLD_BIT_SHIFT);
+	rn->footer.flag = cpu_to_le32(flag);
+}
+
+static inline void set_fsync_mark(struct page *page, int mark)
+{
+	void *kaddr = page_address(page);
+	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	unsigned int flag = le32_to_cpu(rn->footer.flag);
+	if (mark)
+		flag |= (0x1 << FSYNC_BIT_SHIFT);
+	else
+		flag &= ~(0x1 << FSYNC_BIT_SHIFT);
+	rn->footer.flag = cpu_to_le32(flag);
+}
+
+static inline void set_dentry_mark(struct page *page, int mark)
+{
+	void *kaddr = page_address(page);
+	struct f2fs_node *rn = (struct f2fs_node *)kaddr;
+	unsigned int flag = le32_to_cpu(rn->footer.flag);
+	if (mark)
+		flag |= (0x1 << DENT_BIT_SHIFT);
+	else
+		flag &= ~(0x1 << DENT_BIT_SHIFT);
+	rn->footer.flag = cpu_to_le32(flag);
+}
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
new file mode 100644
index 0000000..7a43df0
--- /dev/null
+++ b/fs/f2fs/recovery.c
@@ -0,0 +1,375 @@
+/**
+ * fs/f2fs/recovery.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/fs.h>
+#include <linux/f2fs_fs.h>
+#include "f2fs.h"
+#include "node.h"
+#include "segment.h"
+
+static struct kmem_cache *fsync_entry_slab;
+
+bool space_for_roll_forward(struct f2fs_sb_info *sbi)
+{
+	if (sbi->last_valid_block_count + sbi->alloc_valid_block_count
+			> sbi->user_block_count)
+		return false;
+	return true;
+}
+
+static struct fsync_inode_entry *get_fsync_inode(struct list_head *head,
+								nid_t ino)
+{
+	struct list_head *this;
+	struct fsync_inode_entry *entry;
+
+	list_for_each(this, head) {
+		entry = list_entry(this, struct fsync_inode_entry, list);
+		if (entry->inode->i_ino == ino)
+			return entry;
+	}
+	return NULL;
+}
+
+static int recover_dentry(struct page *ipage, struct inode *inode)
+{
+	struct f2fs_node *raw_node = (struct f2fs_node *)kmap(ipage);
+	struct f2fs_inode *raw_inode = &(raw_node->i);
+	struct dentry dent, parent;
+	struct f2fs_dir_entry *de;
+	struct page *page;
+	struct inode *dir;
+	int err = 0;
+
+	if (!is_dent_dnode(ipage))
+		goto out;
+
+	dir = f2fs_iget(inode->i_sb, le32_to_cpu(raw_inode->i_pino));
+	if (IS_ERR(dir)) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	parent.d_inode = dir;
+	dent.d_parent = &parent;
+	dent.d_name.len = le32_to_cpu(raw_inode->i_namelen);
+	dent.d_name.name = raw_inode->i_name;
+
+	de = f2fs_find_entry(dir, &dent.d_name, &page);
+	if (de) {
+		kunmap(page);
+		f2fs_put_page(page, 0);
+	} else {
+		f2fs_add_link(&dent, inode);
+	}
+	iput(dir);
+out:
+	kunmap(ipage);
+	return err;
+}
+
+static int recover_inode(struct inode *inode, struct page *node_page)
+{
+	void *kaddr = page_address(node_page);
+	struct f2fs_node *raw_node = (struct f2fs_node *)kaddr;
+	struct f2fs_inode *raw_inode = &(raw_node->i);
+
+	inode->i_mode = le32_to_cpu(raw_inode->i_mode);
+	i_size_write(inode, le64_to_cpu(raw_inode->i_size));
+	inode->i_atime.tv_sec = le64_to_cpu(raw_inode->i_mtime);
+	inode->i_ctime.tv_sec = le64_to_cpu(raw_inode->i_ctime);
+	inode->i_mtime.tv_sec = le64_to_cpu(raw_inode->i_mtime);
+	inode->i_atime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec);
+	inode->i_ctime.tv_nsec = le32_to_cpu(raw_inode->i_ctime_nsec);
+	inode->i_mtime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec);
+
+	return recover_dentry(node_page, inode);
+}
+
+static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)
+{
+	unsigned long long cp_ver = le64_to_cpu(sbi->ckpt->checkpoint_ver);
+	struct curseg_info *curseg;
+	struct page *page;
+	block_t blkaddr;
+	int err = 0;
+
+	/* get node pages in the current segment */
+	curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
+	blkaddr = START_BLOCK(sbi, curseg->segno) + curseg->next_blkoff;
+
+	/* read node page */
+	page = alloc_page(GFP_F2FS_ZERO);
+	if (IS_ERR(page))
+		return PTR_ERR(page);
+	lock_page(page);
+
+	while (1) {
+		struct fsync_inode_entry *entry;
+
+		if (f2fs_readpage(sbi, page, blkaddr, READ_SYNC))
+			goto out;
+
+		if (cp_ver != cpver_of_node(page))
+			goto out;
+
+		if (!is_fsync_dnode(page))
+			goto next;
+
+		entry = get_fsync_inode(head, ino_of_node(page));
+		if (entry) {
+			entry->blkaddr = blkaddr;
+			if (IS_INODE(page) && is_dent_dnode(page))
+				set_inode_flag(F2FS_I(entry->inode),
+							FI_INC_LINK);
+		} else {
+			if (IS_INODE(page) && is_dent_dnode(page)) {
+				if (recover_inode_page(sbi, page)) {
+					err = -ENOMEM;
+					goto out;
+				}
+			}
+
+			/* add this fsync inode to the list */
+			entry = kmem_cache_alloc(fsync_entry_slab, GFP_NOFS);
+			if (!entry) {
+				err = -ENOMEM;
+				goto out;
+			}
+
+			INIT_LIST_HEAD(&entry->list);
+			list_add_tail(&entry->list, head);
+
+			entry->inode = f2fs_iget(sbi->sb, ino_of_node(page));
+			if (IS_ERR(entry->inode)) {
+				err = PTR_ERR(entry->inode);
+				goto out;
+			}
+			entry->blkaddr = blkaddr;
+		}
+		if (IS_INODE(page)) {
+			err = recover_inode(entry->inode, page);
+			if (err)
+				goto out;
+		}
+next:
+		/* check next segment */
+		blkaddr = next_blkaddr_of_node(page);
+		ClearPageUptodate(page);
+	}
+out:
+	unlock_page(page);
+	__free_pages(page, 0);
+	return err;
+}
+
+static void destroy_fsync_dnodes(struct f2fs_sb_info *sbi,
+					struct list_head *head)
+{
+	struct list_head *this;
+	struct fsync_inode_entry *entry;
+	list_for_each(this, head) {
+		entry = list_entry(this, struct fsync_inode_entry, list);
+		iput(entry->inode);
+		list_del(&entry->list);
+		kmem_cache_free(fsync_entry_slab, entry);
+	}
+}
+
+static void check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
+						block_t blkaddr)
+{
+	struct seg_entry *sentry;
+	unsigned int segno = GET_SEGNO(sbi, blkaddr);
+	unsigned short blkoff = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) &
+					(sbi->blocks_per_seg - 1);
+	struct f2fs_summary sum;
+	nid_t ino;
+	void *kaddr;
+	struct inode *inode;
+	struct page *node_page;
+	block_t bidx;
+	int i;
+
+	sentry = get_seg_entry(sbi, segno);
+	if (!f2fs_test_bit(blkoff, sentry->cur_valid_map))
+		return;
+
+	/* Get the previous summary */
+	for (i = CURSEG_WARM_DATA; i <= CURSEG_COLD_DATA; i++) {
+		struct curseg_info *curseg = CURSEG_I(sbi, i);
+		if (curseg->segno == segno) {
+			sum = curseg->sum_blk->entries[blkoff];
+			break;
+		}
+	}
+	if (i > CURSEG_COLD_DATA) {
+		struct page *sum_page = get_sum_page(sbi, segno);
+		struct f2fs_summary_block *sum_node;
+		kaddr = page_address(sum_page);
+		sum_node = (struct f2fs_summary_block *)kaddr;
+		sum = sum_node->entries[blkoff];
+		f2fs_put_page(sum_page, 1);
+	}
+
+	/* Get the node page */
+	node_page = get_node_page(sbi, le32_to_cpu(sum.nid));
+	bidx = start_bidx_of_node(ofs_of_node(node_page)) +
+				le16_to_cpu(sum.ofs_in_node);
+	ino = ino_of_node(node_page);
+	f2fs_put_page(node_page, 1);
+
+	/* Deallocate previous index in the node page */
+	inode = f2fs_iget_nowait(sbi->sb, ino);
+	truncate_hole(inode, bidx, bidx + 1);
+	iput(inode);
+}
+
+static void do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
+					struct page *page, block_t blkaddr)
+{
+	unsigned int start, end;
+	struct dnode_of_data dn;
+	struct f2fs_summary sum;
+	struct node_info ni;
+
+	start = start_bidx_of_node(ofs_of_node(page));
+	if (IS_INODE(page))
+		end = start + ADDRS_PER_INODE;
+	else
+		end = start + ADDRS_PER_BLOCK;
+
+	set_new_dnode(&dn, inode, NULL, NULL, 0);
+	if (get_dnode_of_data(&dn, start, 0))
+		return;
+
+	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));
+
+	for (; start < end; start++) {
+		block_t src, dest;
+
+		src = datablock_addr(dn.node_page, dn.ofs_in_node);
+		dest = datablock_addr(page, dn.ofs_in_node);
+
+		if (src != dest && dest != NEW_ADDR && dest != NULL_ADDR) {
+			if (src == NULL_ADDR) {
+				int err = reserve_new_block(&dn);
+				/* We should not get -ENOSPC */
+				BUG_ON(err);
+			}
+
+			/* Check the previous node page having this index */
+			check_index_in_prev_nodes(sbi, dest);
+
+			set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version);
+
+			/* write dummy data page */
+			recover_data_page(sbi, NULL, &sum, src, dest);
+			update_extent_cache(dest, &dn);
+		}
+		dn.ofs_in_node++;
+	}
+
+	/* write node page in place */
+	set_summary(&sum, dn.nid, 0, 0);
+	if (IS_INODE(dn.node_page))
+		sync_inode_page(&dn);
+
+	copy_node_footer(dn.node_page, page);
+	fill_node_footer(dn.node_page, dn.nid, ni.ino,
+					ofs_of_node(page), false);
+	set_page_dirty(dn.node_page);
+
+	recover_node_page(sbi, dn.node_page, &sum, &ni, blkaddr);
+	f2fs_put_dnode(&dn);
+}
+
+static void recover_data(struct f2fs_sb_info *sbi,
+				struct list_head *head, int type)
+{
+	unsigned long long cp_ver = le64_to_cpu(sbi->ckpt->checkpoint_ver);
+	struct curseg_info *curseg;
+	struct page *page;
+	block_t blkaddr;
+
+	/* get node pages in the current segment */
+	curseg = CURSEG_I(sbi, type);
+	blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
+
+	/* read node page */
+	page = alloc_page(GFP_NOFS | __GFP_ZERO);
+	if (IS_ERR(page))
+		return;
+	lock_page(page);
+
+	while (1) {
+		struct fsync_inode_entry *entry;
+
+		if (f2fs_readpage(sbi, page, blkaddr, READ_SYNC))
+			goto out;
+
+		if (cp_ver != cpver_of_node(page))
+			goto out;
+
+		entry = get_fsync_inode(head, ino_of_node(page));
+		if (!entry)
+			goto next;
+
+		do_recover_data(sbi, entry->inode, page, blkaddr);
+
+		if (entry->blkaddr == blkaddr) {
+			iput(entry->inode);
+			list_del(&entry->list);
+			kmem_cache_free(fsync_entry_slab, entry);
+		}
+next:
+		/* check next segment */
+		blkaddr = next_blkaddr_of_node(page);
+		ClearPageUptodate(page);
+	}
+out:
+	unlock_page(page);
+	__free_pages(page, 0);
+
+	allocate_new_segments(sbi);
+}
+
+void recover_fsync_data(struct f2fs_sb_info *sbi)
+{
+	struct list_head inode_list;
+
+	fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry",
+			sizeof(struct fsync_inode_entry), NULL);
+	if (unlikely(!fsync_entry_slab))
+		return;
+
+	INIT_LIST_HEAD(&inode_list);
+
+	/* step #1: find fsynced inode numbers */
+	if (find_fsync_dnodes(sbi, &inode_list))
+		goto out;
+
+	if (list_empty(&inode_list))
+		goto out;
+
+	/* step #2: recover data */
+	sbi->por_doing = 1;
+	recover_data(sbi, &inode_list, CURSEG_WARM_NODE);
+	sbi->por_doing = 0;
+	BUG_ON(!list_empty(&inode_list));
+out:
+	destroy_fsync_dnodes(sbi, &inode_list);
+	kmem_cache_destroy(fsync_entry_slab);
+	write_checkpoint(sbi, false, false);
+}
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
new file mode 100644
index 0000000..ed7c079
--- /dev/null
+++ b/fs/f2fs/segment.c
@@ -0,0 +1,1798 @@
+/**
+ * fs/f2fs/segment.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/fs.h>
+#include <linux/f2fs_fs.h>
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <linux/vmalloc.h>
+
+#include "f2fs.h"
+#include "segment.h"
+#include "node.h"
+
+static int need_to_flush(struct f2fs_sb_info *sbi)
+{
+	unsigned int pages_per_sec = (1 << sbi->log_blocks_per_seg) *
+			sbi->segs_per_sec;
+	int node_secs = ((get_pages(sbi, F2FS_DIRTY_NODES) + pages_per_sec - 1)
+		>> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
+	int dent_secs = ((get_pages(sbi, F2FS_DIRTY_DENTS) + pages_per_sec - 1)
+		>> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
+
+	if (sbi->por_doing)
+		return 0;
+
+	if (free_sections(sbi) <= (node_secs + 2 * dent_secs +
+						reserved_sections(sbi)))
+		return 1;
+	return 0;
+}
+
+/**
+ * This function balances dirty node and dentry pages.
+ * In addition, it controls garbage collection.
+ */
+void f2fs_balance_fs(struct f2fs_sb_info *sbi)
+{
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_ALL,
+		.nr_to_write = LONG_MAX,
+		.for_reclaim = 0,
+	};
+
+	if (sbi->por_doing)
+		return;
+
+	/*
+	 * We should do checkpoint when there are so many dirty node pages
+	 * with enough free segments. After then, we should do GC.
+	 */
+	if (need_to_flush(sbi)) {
+		sync_dirty_dir_inodes(sbi);
+		sync_node_pages(sbi, 0, &wbc);
+	}
+
+	if (has_not_enough_free_secs(sbi)) {
+		mutex_lock(&sbi->gc_mutex);
+		f2fs_gc(sbi, 1);
+	}
+}
+
+static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
+		enum dirty_type dirty_type)
+{
+	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+
+	/* need not be added */
+	if (IS_CURSEG(sbi, segno))
+		return;
+
+	if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type]))
+		dirty_i->nr_dirty[dirty_type]++;
+
+	if (dirty_type == DIRTY) {
+		struct seg_entry *sentry = get_seg_entry(sbi, segno);
+		dirty_type = sentry->type;
+		if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type]))
+			dirty_i->nr_dirty[dirty_type]++;
+	}
+}
+
+static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
+		enum dirty_type dirty_type)
+{
+	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+
+	if (test_and_clear_bit(segno, dirty_i->dirty_segmap[dirty_type]))
+		dirty_i->nr_dirty[dirty_type]--;
+
+	if (dirty_type == DIRTY) {
+		struct seg_entry *sentry = get_seg_entry(sbi, segno);
+		dirty_type = sentry->type;
+		if (test_and_clear_bit(segno,
+					dirty_i->dirty_segmap[dirty_type]))
+			dirty_i->nr_dirty[dirty_type]--;
+		clear_bit(segno, dirty_i->victim_segmap[FG_GC]);
+		clear_bit(segno, dirty_i->victim_segmap[BG_GC]);
+	}
+}
+
+/**
+ * Should not occur error such as -ENOMEM.
+ * Adding dirty entry into seglist is not critical operation.
+ * If a given segment is one of current working segments, it won't be added.
+ */
+void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno)
+{
+	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+	unsigned short valid_blocks;
+
+	if (segno == NULL_SEGNO || IS_CURSEG(sbi, segno))
+		return;
+
+	mutex_lock(&dirty_i->seglist_lock);
+
+	valid_blocks = get_valid_blocks(sbi, segno, 0);
+
+	if (valid_blocks == 0) {
+		__locate_dirty_segment(sbi, segno, PRE);
+		__remove_dirty_segment(sbi, segno, DIRTY);
+	} else if (valid_blocks < sbi->blocks_per_seg) {
+		__locate_dirty_segment(sbi, segno, DIRTY);
+	} else {
+		/* Recovery routine with SSR needs this */
+		__remove_dirty_segment(sbi, segno, DIRTY);
+	}
+
+	mutex_unlock(&dirty_i->seglist_lock);
+	return;
+}
+
+/**
+ * Should call clear_prefree_segments after checkpoint is done.
+ */
+static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi)
+{
+	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+	unsigned int segno, offset = 0;
+	unsigned int total_segs = TOTAL_SEGS(sbi);
+
+	mutex_lock(&dirty_i->seglist_lock);
+	while (1) {
+		segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs,
+				offset);
+		if (segno >= total_segs)
+			break;
+		__set_test_and_free(sbi, segno);
+		offset = segno + 1;
+	}
+	mutex_unlock(&dirty_i->seglist_lock);
+}
+
+void clear_prefree_segments(struct f2fs_sb_info *sbi)
+{
+	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+	unsigned int segno, offset = 0;
+	unsigned int total_segs = TOTAL_SEGS(sbi);
+
+	mutex_lock(&dirty_i->seglist_lock);
+	while (1) {
+		segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs,
+				offset);
+		if (segno >= total_segs)
+			break;
+
+		offset = segno + 1;
+		if (test_and_clear_bit(segno, dirty_i->dirty_segmap[PRE]))
+			dirty_i->nr_dirty[PRE]--;
+
+		/* 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);
+	}
+	mutex_unlock(&dirty_i->seglist_lock);
+}
+
+static void __mark_sit_entry_dirty(struct f2fs_sb_info *sbi, unsigned int segno)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	if (!__test_and_set_bit(segno, sit_i->dirty_sentries_bitmap))
+		sit_i->dirty_sentries++;
+}
+
+static void __set_sit_entry_type(struct f2fs_sb_info *sbi, int type,
+					unsigned int segno, int modified)
+{
+	struct seg_entry *se = get_seg_entry(sbi, segno);
+	se->type = type;
+	if (modified)
+		__mark_sit_entry_dirty(sbi, segno);
+}
+
+static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
+{
+	struct seg_entry *se;
+	unsigned int segno, offset;
+	long int new_vblocks;
+
+	segno = GET_SEGNO(sbi, blkaddr);
+
+	se = get_seg_entry(sbi, segno);
+	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) ||
+				(new_vblocks > sbi->blocks_per_seg)));
+
+	se->valid_blocks = new_vblocks;
+	se->mtime = get_mtime(sbi);
+	SIT_I(sbi)->max_mtime = se->mtime;
+
+	/* Update valid block bitmap */
+	if (del > 0) {
+		if (f2fs_set_bit(offset, se->cur_valid_map))
+			BUG();
+	} else {
+		if (!f2fs_clear_bit(offset, se->cur_valid_map))
+			BUG();
+	}
+	if (!f2fs_test_bit(offset, se->ckpt_valid_map))
+		se->ckpt_valid_blocks += del;
+
+	__mark_sit_entry_dirty(sbi, segno);
+
+	/* update total number of valid blocks to be written in ckpt area */
+	SIT_I(sbi)->written_valid_blocks += del;
+
+	if (sbi->segs_per_sec > 1)
+		get_sec_entry(sbi, segno)->valid_blocks += del;
+}
+
+static void refresh_sit_entry(struct f2fs_sb_info *sbi,
+			block_t old_blkaddr, block_t new_blkaddr)
+{
+	update_sit_entry(sbi, new_blkaddr, 1);
+	if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
+		update_sit_entry(sbi, old_blkaddr, -1);
+}
+
+void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr)
+{
+	unsigned int segno = GET_SEGNO(sbi, addr);
+	struct sit_info *sit_i = SIT_I(sbi);
+
+	BUG_ON(addr == NULL_ADDR);
+	if (addr == NEW_ADDR)
+		return;
+
+	/* add it into sit main buffer */
+	mutex_lock(&sit_i->sentry_lock);
+
+	update_sit_entry(sbi, addr, -1);
+
+	/* add it into dirty seglist */
+	locate_dirty_segment(sbi, segno);
+
+	mutex_unlock(&sit_i->sentry_lock);
+}
+
+/**
+ * This function should be resided under the curseg_mutex lock
+ */
+static void __add_sum_entry(struct f2fs_sb_info *sbi, int type,
+		struct f2fs_summary *sum, unsigned short offset)
+{
+	struct curseg_info *curseg = CURSEG_I(sbi, type);
+	void *addr = curseg->sum_blk;
+	addr += offset * sizeof(struct f2fs_summary);
+	memcpy(addr, sum, sizeof(struct f2fs_summary));
+	return;
+}
+
+/**
+ * Calculate the number of current summary pages for writing
+ */
+int npages_for_summary_flush(struct f2fs_sb_info *sbi)
+{
+	int total_size_bytes = 0;
+	int valid_sum_count = 0;
+	int i, sum_space;
+
+	for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
+		if (sbi->ckpt->alloc_type[i] == SSR)
+			valid_sum_count += sbi->blocks_per_seg;
+		else
+			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)
+		return 1;
+	else if (total_size_bytes < 2 * sum_space)
+		return 2;
+	return 3;
+}
+
+/**
+ * Caller should put this summary page
+ */
+struct page *get_sum_page(struct f2fs_sb_info *sbi, unsigned int segno)
+{
+	return get_meta_page(sbi, GET_SUM_BLOCK(sbi, segno));
+}
+
+static void write_sum_page(struct f2fs_sb_info *sbi,
+			struct f2fs_summary_block *sum_blk, block_t blk_addr)
+{
+	struct page *page = grab_meta_page(sbi, blk_addr);
+	void *kaddr = page_address(page);
+	memcpy(kaddr, sum_blk, PAGE_CACHE_SIZE);
+	set_page_dirty(page);
+	f2fs_put_page(page, 1);
+}
+
+static unsigned int check_prefree_segments(struct f2fs_sb_info *sbi,
+					int ofs_unit, int type)
+{
+	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+	unsigned long *prefree_segmap = dirty_i->dirty_segmap[PRE];
+	unsigned int segno, next_segno, i;
+	int ofs = 0;
+
+	/*
+	 * If there is not enough reserved sections,
+	 * we should not reuse prefree segments.
+	 */
+	if (has_not_enough_free_secs(sbi))
+		return NULL_SEGNO;
+
+	/*
+	 * NODE page should not reuse prefree segment,
+	 * since those information is used for SPOR.
+	 */
+	if (IS_NODESEG(type))
+		return NULL_SEGNO;
+next:
+	segno = find_next_bit(prefree_segmap, TOTAL_SEGS(sbi), ofs++);
+	ofs = ((segno / ofs_unit) * ofs_unit) + ofs_unit;
+	if (segno < TOTAL_SEGS(sbi)) {
+		/* skip intermediate segments in a section */
+		if (segno % ofs_unit)
+			goto next;
+
+		/* skip if whole section is not prefree */
+		next_segno = find_next_zero_bit(prefree_segmap,
+						TOTAL_SEGS(sbi), segno + 1);
+		if (next_segno - segno < ofs_unit)
+			goto next;
+
+		/* skip if whole section was not free at the last checkpoint */
+		for (i = 0; i < ofs_unit; i++)
+			if (get_seg_entry(sbi, segno)->ckpt_valid_blocks)
+				goto next;
+		return segno;
+	}
+	return NULL_SEGNO;
+}
+
+/**
+ * Find a new segment from the free segments bitmap to right order
+ * This function should be returned with success, otherwise BUG
+ */
+static void get_new_segment(struct f2fs_sb_info *sbi,
+			unsigned int *newseg, bool new_sec, int dir)
+{
+	struct free_segmap_info *free_i = FREE_I(sbi);
+	unsigned int total_secs = sbi->total_sections;
+	unsigned int segno, secno, zoneno;
+	unsigned int total_zones = sbi->total_sections / sbi->secs_per_zone;
+	unsigned int hint = *newseg / sbi->segs_per_sec;
+	unsigned int old_zoneno = GET_ZONENO_FROM_SEGNO(sbi, *newseg);
+	unsigned int left_start = hint;
+	bool init = true;
+	int go_left = 0;
+	int i;
+
+	write_lock(&free_i->segmap_lock);
+
+	if (!new_sec && ((*newseg + 1) % sbi->segs_per_sec)) {
+		segno = find_next_zero_bit(free_i->free_segmap,
+					TOTAL_SEGS(sbi), *newseg + 1);
+		if (segno < TOTAL_SEGS(sbi))
+			goto got_it;
+	}
+find_other_zone:
+	secno = find_next_zero_bit(free_i->free_secmap, total_secs, hint);
+	if (secno >= total_secs) {
+		if (dir == ALLOC_RIGHT) {
+			secno = find_next_zero_bit(free_i->free_secmap,
+						total_secs, 0);
+			BUG_ON(secno >= total_secs);
+		} else {
+			go_left = 1;
+			left_start = hint - 1;
+		}
+	}
+	if (go_left == 0)
+		goto skip_left;
+
+	while (test_bit(left_start, free_i->free_secmap)) {
+		if (left_start > 0) {
+			left_start--;
+			continue;
+		}
+		left_start = find_next_zero_bit(free_i->free_secmap,
+						total_secs, 0);
+		BUG_ON(left_start >= total_secs);
+		break;
+	}
+	secno = left_start;
+skip_left:
+	hint = secno;
+	segno = secno * sbi->segs_per_sec;
+	zoneno = secno / sbi->secs_per_zone;
+
+	/* give up on finding another zone */
+	if (!init)
+		goto got_it;
+	if (sbi->secs_per_zone == 1)
+		goto got_it;
+	if (zoneno == old_zoneno)
+		goto got_it;
+	if (dir == ALLOC_LEFT) {
+		if (!go_left && zoneno + 1 >= total_zones)
+			goto got_it;
+		if (go_left && zoneno == 0)
+			goto got_it;
+	}
+	for (i = 0; i < NR_CURSEG_TYPE; i++)
+		if (CURSEG_I(sbi, i)->zone == zoneno)
+			break;
+
+	if (i < NR_CURSEG_TYPE) {
+		/* zone is in user, try another */
+		if (go_left)
+			hint = zoneno * sbi->secs_per_zone - 1;
+		else if (zoneno + 1 >= total_zones)
+			hint = 0;
+		else
+			hint = (zoneno + 1) * sbi->secs_per_zone;
+		init = false;
+		goto find_other_zone;
+	}
+got_it:
+	/* set it as dirty segment in free segmap */
+	BUG_ON(test_bit(segno, free_i->free_segmap));
+	__set_inuse(sbi, segno);
+	*newseg = segno;
+	write_unlock(&free_i->segmap_lock);
+}
+
+static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
+{
+	struct curseg_info *curseg = CURSEG_I(sbi, type);
+	struct summary_footer *sum_footer;
+
+	curseg->segno = curseg->next_segno;
+	curseg->zone = GET_ZONENO_FROM_SEGNO(sbi, curseg->segno);
+	curseg->next_blkoff = 0;
+	curseg->next_segno = NULL_SEGNO;
+
+	sum_footer = &(curseg->sum_blk->footer);
+	memset(sum_footer, 0, sizeof(struct summary_footer));
+	if (IS_DATASEG(type))
+		SET_SUM_TYPE(sum_footer, SUM_TYPE_DATA);
+	if (IS_NODESEG(type))
+		SET_SUM_TYPE(sum_footer, SUM_TYPE_NODE);
+	__set_sit_entry_type(sbi, type, curseg->segno, modified);
+}
+
+/**
+ * Allocate a current working segment.
+ * This function always allocates a free segment in LFS manner.
+ */
+static void new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec)
+{
+	struct curseg_info *curseg = CURSEG_I(sbi, type);
+	unsigned int segno = curseg->segno;
+	int dir = ALLOC_LEFT;
+
+	write_sum_page(sbi, curseg->sum_blk,
+				GET_SUM_BLOCK(sbi, curseg->segno));
+	if (type == CURSEG_WARM_DATA || type == CURSEG_COLD_DATA)
+		dir = ALLOC_RIGHT;
+
+	if (test_opt(sbi, NOHEAP))
+		dir = ALLOC_RIGHT;
+
+	get_new_segment(sbi, &segno, new_sec, dir);
+	curseg->next_segno = segno;
+	reset_curseg(sbi, type, 1);
+	curseg->alloc_type = LFS;
+}
+
+static void __next_free_blkoff(struct f2fs_sb_info *sbi,
+			struct curseg_info *seg, block_t start)
+{
+	struct seg_entry *se = get_seg_entry(sbi, seg->segno);
+	block_t ofs;
+	for (ofs = start; ofs < sbi->blocks_per_seg; ofs++) {
+		if (!f2fs_test_bit(ofs, se->ckpt_valid_map)
+			&& !f2fs_test_bit(ofs, se->cur_valid_map))
+			break;
+	}
+	seg->next_blkoff = ofs;
+}
+
+/**
+ * If a segment is written by LFS manner, next block offset is just obtained
+ * by increasing the current block offset. However, if a segment is written by
+ * SSR manner, next block offset obtained by calling __next_free_blkoff
+ */
+static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
+				struct curseg_info *seg)
+{
+	if (seg->alloc_type == SSR)
+		__next_free_blkoff(sbi, seg, seg->next_blkoff + 1);
+	else
+		seg->next_blkoff++;
+}
+
+/**
+ * This function always allocates a used segment (from dirty seglist) by SSR
+ * manner, so it should recover the existing segment information of valid blocks
+ */
+static void change_curseg(struct f2fs_sb_info *sbi, int type, bool reuse)
+{
+	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+	struct curseg_info *curseg = CURSEG_I(sbi, type);
+	unsigned int new_segno = curseg->next_segno;
+	struct f2fs_summary_block *sum_node;
+	struct page *sum_page;
+
+	write_sum_page(sbi, curseg->sum_blk,
+				GET_SUM_BLOCK(sbi, curseg->segno));
+	__set_test_and_inuse(sbi, new_segno);
+
+	mutex_lock(&dirty_i->seglist_lock);
+	__remove_dirty_segment(sbi, new_segno, PRE);
+	__remove_dirty_segment(sbi, new_segno, DIRTY);
+	mutex_unlock(&dirty_i->seglist_lock);
+
+	reset_curseg(sbi, type, 1);
+	curseg->alloc_type = SSR;
+	__next_free_blkoff(sbi, curseg, 0);
+
+	if (reuse) {
+		sum_page = get_sum_page(sbi, new_segno);
+		sum_node = (struct f2fs_summary_block *)page_address(sum_page);
+		memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE);
+		f2fs_put_page(sum_page, 1);
+	}
+}
+
+/*
+ * flush out current segment and replace it with new segment
+ * This function should be returned with success, otherwise BUG
+ */
+static void allocate_segment_by_default(struct f2fs_sb_info *sbi,
+						int type, bool force)
+{
+	struct curseg_info *curseg = CURSEG_I(sbi, type);
+	unsigned int ofs_unit;
+
+	if (force) {
+		new_curseg(sbi, type, true);
+		goto out;
+	}
+
+	ofs_unit = need_SSR(sbi) ? 1 : sbi->segs_per_sec;
+	curseg->next_segno = check_prefree_segments(sbi, ofs_unit, type);
+
+	if (curseg->next_segno != NULL_SEGNO)
+		change_curseg(sbi, type, false);
+	else if (type == CURSEG_WARM_NODE)
+		new_curseg(sbi, type, false);
+	else if (need_SSR(sbi) && get_ssr_segment(sbi, type))
+		change_curseg(sbi, type, true);
+	else
+		new_curseg(sbi, type, false);
+out:
+	sbi->segment_count[curseg->alloc_type]++;
+}
+
+void allocate_new_segments(struct f2fs_sb_info *sbi)
+{
+	struct curseg_info *curseg;
+	unsigned int old_curseg;
+	int i;
+
+	for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
+		curseg = CURSEG_I(sbi, i);
+		old_curseg = curseg->segno;
+		SIT_I(sbi)->s_ops->allocate_segment(sbi, i, true);
+		locate_dirty_segment(sbi, old_curseg);
+	}
+}
+
+static const struct segment_allocation default_salloc_ops = {
+	.allocate_segment = allocate_segment_by_default,
+};
+
+static void f2fs_end_io_write(struct bio *bio, int err)
+{
+	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+	struct bio_private *p = bio->bi_private;
+
+	do {
+		struct page *page = bvec->bv_page;
+
+		if (--bvec >= bio->bi_io_vec)
+			prefetchw(&bvec->bv_page->flags);
+		if (!uptodate) {
+			SetPageError(page);
+			if (page->mapping)
+				set_bit(AS_EIO, &page->mapping->flags);
+			p->sbi->ckpt->ckpt_flags |= CP_ERROR_FLAG;
+			set_page_dirty(page);
+		}
+		end_page_writeback(page);
+		dec_page_count(p->sbi, F2FS_WRITEBACK);
+	} while (bvec >= bio->bi_io_vec);
+
+	if (p->is_sync)
+		complete(p->wait);
+	kfree(p);
+	bio_put(bio);
+}
+
+struct bio *f2fs_bio_alloc(struct block_device *bdev, sector_t first_sector,
+					int nr_vecs, gfp_t gfp_flags)
+{
+	struct bio *bio;
+repeat:
+	/* allocate new bio */
+	bio = bio_alloc(gfp_flags, nr_vecs);
+
+	if (bio == NULL && (current->flags & PF_MEMALLOC)) {
+		while (!bio && (nr_vecs /= 2))
+			bio = bio_alloc(gfp_flags, nr_vecs);
+	}
+	if (bio) {
+		bio->bi_bdev = bdev;
+		bio->bi_sector = first_sector;
+retry:
+		bio->bi_private = kmalloc(sizeof(struct bio_private),
+						GFP_NOFS | __GFP_HIGH);
+		if (!bio->bi_private) {
+			cond_resched();
+			goto retry;
+		}
+	}
+	if (bio == NULL) {
+		cond_resched();
+		goto repeat;
+	}
+	return bio;
+}
+
+static void do_submit_bio(struct f2fs_sb_info *sbi,
+				enum page_type type, bool sync)
+{
+	int rw = sync ? WRITE_SYNC : WRITE;
+	enum page_type btype = type > META ? META : type;
+
+	if (type >= META_FLUSH)
+		rw = WRITE_FLUSH_FUA;
+
+	if (sbi->bio[btype]) {
+		struct bio_private *p = sbi->bio[btype]->bi_private;
+		p->sbi = sbi;
+		sbi->bio[btype]->bi_end_io = f2fs_end_io_write;
+		if (type == META_FLUSH) {
+			DECLARE_COMPLETION_ONSTACK(wait);
+			p->is_sync = true;
+			p->wait = &wait;
+			submit_bio(rw, sbi->bio[btype]);
+			wait_for_completion(&wait);
+		} else {
+			p->is_sync = false;
+			submit_bio(rw, sbi->bio[btype]);
+		}
+		sbi->bio[btype] = NULL;
+	}
+}
+
+void f2fs_submit_bio(struct f2fs_sb_info *sbi, enum page_type type, bool sync)
+{
+	down_write(&sbi->bio_sem);
+	do_submit_bio(sbi, type, sync);
+	up_write(&sbi->bio_sem);
+}
+
+static void submit_write_page(struct f2fs_sb_info *sbi, struct page *page,
+				block_t blk_addr, enum page_type type)
+{
+	struct block_device *bdev = sbi->sb->s_bdev;
+
+	verify_block_addr(sbi, blk_addr);
+
+	down_write(&sbi->bio_sem);
+
+	inc_page_count(sbi, F2FS_WRITEBACK);
+
+	if (sbi->bio[type] && sbi->last_block_in_bio[type] != blk_addr - 1)
+		do_submit_bio(sbi, type, false);
+alloc_new:
+	if (sbi->bio[type] == NULL)
+		sbi->bio[type] = f2fs_bio_alloc(bdev,
+				blk_addr << (sbi->log_blocksize - 9),
+				bio_get_nr_vecs(bdev), GFP_NOFS | __GFP_HIGH);
+
+	if (bio_add_page(sbi->bio[type], page, PAGE_CACHE_SIZE, 0) <
+							PAGE_CACHE_SIZE) {
+		do_submit_bio(sbi, type, false);
+		goto alloc_new;
+	}
+
+	sbi->last_block_in_bio[type] = blk_addr;
+
+	up_write(&sbi->bio_sem);
+}
+
+static bool __has_curseg_space(struct f2fs_sb_info *sbi, int type)
+{
+	struct curseg_info *curseg = CURSEG_I(sbi, type);
+	if (curseg->next_blkoff < sbi->blocks_per_seg)
+		return true;
+	return false;
+}
+
+static int __get_segment_type_2(struct page *page, enum page_type p_type)
+{
+	if (p_type == DATA)
+		return CURSEG_HOT_DATA;
+	else
+		return CURSEG_HOT_NODE;
+}
+
+static int __get_segment_type_4(struct page *page, enum page_type p_type)
+{
+	if (p_type == DATA) {
+		struct inode *inode = page->mapping->host;
+
+		if (S_ISDIR(inode->i_mode))
+			return CURSEG_HOT_DATA;
+		else
+			return CURSEG_COLD_DATA;
+	} else {
+		if (IS_DNODE(page) && !is_cold_node(page))
+			return CURSEG_HOT_NODE;
+		else
+			return CURSEG_COLD_NODE;
+	}
+}
+
+static int __get_segment_type_6(struct page *page, enum page_type p_type)
+{
+	if (p_type == DATA) {
+		struct inode *inode = page->mapping->host;
+
+		if (S_ISDIR(inode->i_mode))
+			return CURSEG_HOT_DATA;
+		else if (is_cold_data(page) || is_cold_file(inode))
+			return CURSEG_COLD_DATA;
+		else
+			return CURSEG_WARM_DATA;
+	} else {
+		if (IS_DNODE(page))
+			return is_cold_node(page) ? CURSEG_WARM_NODE :
+						CURSEG_HOT_NODE;
+		else
+			return CURSEG_COLD_NODE;
+	}
+}
+
+static int __get_segment_type(struct page *page, enum page_type p_type)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
+	switch (sbi->active_logs) {
+	case 2:
+		return __get_segment_type_2(page, p_type);
+	case 4:
+		return __get_segment_type_4(page, p_type);
+	case 6:
+		return __get_segment_type_6(page, p_type);
+	default:
+		BUG();
+	}
+}
+
+static void do_write_page(struct f2fs_sb_info *sbi, struct page *page,
+			block_t old_blkaddr, block_t *new_blkaddr,
+			struct f2fs_summary *sum, enum page_type p_type)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	struct curseg_info *curseg;
+	unsigned int old_cursegno;
+	int type;
+
+	type = __get_segment_type(page, p_type);
+	curseg = CURSEG_I(sbi, type);
+
+	mutex_lock(&curseg->curseg_mutex);
+
+	*new_blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
+	old_cursegno = curseg->segno;
+
+	/*
+	 * __add_sum_entry should be resided under the curseg_mutex
+	 * because, this function updates a summary entry in the
+	 * current summary block.
+	 */
+	__add_sum_entry(sbi, type, sum, curseg->next_blkoff);
+
+	mutex_lock(&sit_i->sentry_lock);
+	__refresh_next_blkoff(sbi, curseg);
+	sbi->block_count[curseg->alloc_type]++;
+
+	/*
+	 * SIT information should be updated before segment allocation,
+	 * since SSR needs latest valid block information.
+	 */
+	refresh_sit_entry(sbi, old_blkaddr, *new_blkaddr);
+
+	if (!__has_curseg_space(sbi, type))
+		sit_i->s_ops->allocate_segment(sbi, type, false);
+
+	locate_dirty_segment(sbi, old_cursegno);
+	locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
+	mutex_unlock(&sit_i->sentry_lock);
+
+	if (p_type == NODE)
+		fill_node_footer_blkaddr(page, NEXT_FREE_BLKADDR(sbi, curseg));
+
+	/* writeout dirty page into bdev */
+	submit_write_page(sbi, page, *new_blkaddr, p_type);
+
+	mutex_unlock(&curseg->curseg_mutex);
+}
+
+int write_meta_page(struct f2fs_sb_info *sbi, struct page *page,
+			struct writeback_control *wbc)
+{
+	if (wbc->for_reclaim)
+		return AOP_WRITEPAGE_ACTIVATE;
+
+	set_page_writeback(page);
+	submit_write_page(sbi, page, page->index, META);
+	return 0;
+}
+
+void write_node_page(struct f2fs_sb_info *sbi, struct page *page,
+		unsigned int nid, block_t old_blkaddr, block_t *new_blkaddr)
+{
+	struct f2fs_summary sum;
+	set_summary(&sum, nid, 0, 0);
+	do_write_page(sbi, page, old_blkaddr, new_blkaddr, &sum, NODE);
+}
+
+void write_data_page(struct inode *inode, struct page *page,
+		struct dnode_of_data *dn, block_t old_blkaddr,
+		block_t *new_blkaddr)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct f2fs_summary sum;
+	struct node_info ni;
+
+	BUG_ON(old_blkaddr == NULL_ADDR);
+	get_node_info(sbi, dn->nid, &ni);
+	set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
+
+	do_write_page(sbi, page, old_blkaddr,
+			new_blkaddr, &sum, DATA);
+}
+
+void rewrite_data_page(struct f2fs_sb_info *sbi, struct page *page,
+					block_t old_blk_addr)
+{
+	submit_write_page(sbi, page, old_blk_addr, DATA);
+}
+
+void recover_data_page(struct f2fs_sb_info *sbi,
+			struct page *page, struct f2fs_summary *sum,
+			block_t old_blkaddr, block_t new_blkaddr)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	struct curseg_info *curseg;
+	unsigned int segno, old_cursegno;
+	struct seg_entry *se;
+	int type;
+
+	segno = GET_SEGNO(sbi, new_blkaddr);
+	se = get_seg_entry(sbi, segno);
+	type = se->type;
+
+	if (se->valid_blocks == 0 && !IS_CURSEG(sbi, segno)) {
+		if (old_blkaddr == NULL_ADDR)
+			type = CURSEG_COLD_DATA;
+		else
+			type = CURSEG_WARM_DATA;
+	}
+	curseg = CURSEG_I(sbi, type);
+
+	mutex_lock(&curseg->curseg_mutex);
+	mutex_lock(&sit_i->sentry_lock);
+
+	old_cursegno = curseg->segno;
+
+	/* change the current segment */
+	if (segno != curseg->segno) {
+		curseg->next_segno = segno;
+		change_curseg(sbi, type, true);
+	}
+
+	curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) &
+					(sbi->blocks_per_seg - 1);
+	__add_sum_entry(sbi, type, sum, curseg->next_blkoff);
+
+	refresh_sit_entry(sbi, old_blkaddr, new_blkaddr);
+
+	locate_dirty_segment(sbi, old_cursegno);
+	locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
+
+	mutex_unlock(&sit_i->sentry_lock);
+	mutex_unlock(&curseg->curseg_mutex);
+}
+
+void rewrite_node_page(struct f2fs_sb_info *sbi,
+			struct page *page, struct f2fs_summary *sum,
+			block_t old_blkaddr, block_t new_blkaddr)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	int type = CURSEG_WARM_NODE;
+	struct curseg_info *curseg;
+	unsigned int segno, old_cursegno;
+	block_t next_blkaddr = next_blkaddr_of_node(page);
+	unsigned int next_segno = GET_SEGNO(sbi, next_blkaddr);
+
+	curseg = CURSEG_I(sbi, type);
+
+	mutex_lock(&curseg->curseg_mutex);
+	mutex_lock(&sit_i->sentry_lock);
+
+	segno = GET_SEGNO(sbi, new_blkaddr);
+	old_cursegno = curseg->segno;
+
+	/* change the current segment */
+	if (segno != curseg->segno) {
+		curseg->next_segno = segno;
+		change_curseg(sbi, type, true);
+	}
+	curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) &
+					(sbi->blocks_per_seg - 1);
+	__add_sum_entry(sbi, type, sum, curseg->next_blkoff);
+
+	/* change the current log to the next block addr in advance */
+	if (next_segno != segno) {
+		curseg->next_segno = next_segno;
+		change_curseg(sbi, type, true);
+	}
+	curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, next_blkaddr) &
+					(sbi->blocks_per_seg - 1);
+
+	/* rewrite node page */
+	set_page_writeback(page);
+	submit_write_page(sbi, page, new_blkaddr, NODE);
+	f2fs_submit_bio(sbi, NODE, true);
+	refresh_sit_entry(sbi, old_blkaddr, new_blkaddr);
+
+	locate_dirty_segment(sbi, old_cursegno);
+	locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
+
+	mutex_unlock(&sit_i->sentry_lock);
+	mutex_unlock(&curseg->curseg_mutex);
+}
+
+static int read_compacted_summaries(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	struct curseg_info *seg_i;
+	unsigned char *kaddr;
+	struct page *page;
+	block_t start;
+	int i, j, offset;
+
+	start = start_sum_block(sbi);
+
+	page = get_meta_page(sbi, start++);
+	kaddr = (unsigned char *)page_address(page);
+
+	/* Step 1: restore nat cache */
+	seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
+	memcpy(&seg_i->sum_blk->n_nats, kaddr, SUM_JOURNAL_SIZE);
+
+	/* Step 2: restore sit cache */
+	seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA);
+	memcpy(&seg_i->sum_blk->n_sits, kaddr + SUM_JOURNAL_SIZE,
+						SUM_JOURNAL_SIZE);
+	offset = 2 * SUM_JOURNAL_SIZE;
+
+	/* Step 3: restore summary entries */
+	for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
+		unsigned short blk_off;
+		unsigned int segno;
+
+		seg_i = CURSEG_I(sbi, i);
+		segno = le32_to_cpu(ckpt->cur_data_segno[i]);
+		blk_off = le16_to_cpu(ckpt->cur_data_blkoff[i]);
+		seg_i->next_segno = segno;
+		reset_curseg(sbi, i, 0);
+		seg_i->alloc_type = ckpt->alloc_type[i];
+		seg_i->next_blkoff = blk_off;
+
+		if (seg_i->alloc_type == SSR)
+			blk_off = sbi->blocks_per_seg;
+
+		for (j = 0; j < blk_off; j++) {
+			struct f2fs_summary *s;
+			s = (struct f2fs_summary *)(kaddr + offset);
+			seg_i->sum_blk->entries[j] = *s;
+			offset += SUMMARY_SIZE;
+			if (offset + SUMMARY_SIZE <= PAGE_CACHE_SIZE -
+						SUM_FOOTER_SIZE)
+				continue;
+
+			f2fs_put_page(page, 1);
+			page = NULL;
+
+			page = get_meta_page(sbi, start++);
+			kaddr = (unsigned char *)page_address(page);
+			offset = 0;
+		}
+	}
+	f2fs_put_page(page, 1);
+	return 0;
+}
+
+static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
+{
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	struct f2fs_summary_block *sum;
+	struct curseg_info *curseg;
+	struct page *new;
+	unsigned short blk_off;
+	unsigned int segno = 0;
+	block_t blk_addr = 0;
+
+	/* get segment number and block addr */
+	if (IS_DATASEG(type)) {
+		segno = le32_to_cpu(ckpt->cur_data_segno[type]);
+		blk_off = le16_to_cpu(ckpt->cur_data_blkoff[type -
+							CURSEG_HOT_DATA]);
+		if (ckpt->ckpt_flags & CP_UMOUNT_FLAG)
+			blk_addr = sum_blk_addr(sbi, NR_CURSEG_TYPE, type);
+		else
+			blk_addr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, type);
+	} else {
+		segno = le32_to_cpu(ckpt->cur_node_segno[type -
+							CURSEG_HOT_NODE]);
+		blk_off = le16_to_cpu(ckpt->cur_node_blkoff[type -
+							CURSEG_HOT_NODE]);
+		if (ckpt->ckpt_flags & CP_UMOUNT_FLAG)
+			blk_addr = sum_blk_addr(sbi, NR_CURSEG_NODE_TYPE,
+							type - CURSEG_HOT_NODE);
+		else
+			blk_addr = GET_SUM_BLOCK(sbi, segno);
+	}
+
+	new = get_meta_page(sbi, blk_addr);
+	sum = (struct f2fs_summary_block *)page_address(new);
+
+	if (IS_NODESEG(type)) {
+		if (ckpt->ckpt_flags & CP_UMOUNT_FLAG) {
+			struct f2fs_summary *ns = &sum->entries[0];
+			int i;
+			for (i = 0; i < sbi->blocks_per_seg; i++, ns++) {
+				ns->version = 0;
+				ns->ofs_in_node = 0;
+			}
+		} else {
+			if (restore_node_summary(sbi, segno, sum)) {
+				f2fs_put_page(new, 1);
+				return -EINVAL;
+			}
+		}
+	}
+
+	/* set uncompleted segment to curseg */
+	curseg = CURSEG_I(sbi, type);
+	mutex_lock(&curseg->curseg_mutex);
+	memcpy(curseg->sum_blk, sum, PAGE_CACHE_SIZE);
+	curseg->next_segno = segno;
+	reset_curseg(sbi, type, 0);
+	curseg->alloc_type = ckpt->alloc_type[type];
+	curseg->next_blkoff = blk_off;
+	mutex_unlock(&curseg->curseg_mutex);
+	f2fs_put_page(new, 1);
+	return 0;
+}
+
+static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
+{
+	int type = CURSEG_HOT_DATA;
+
+	if (sbi->ckpt->ckpt_flags & CP_COMPACT_SUM_FLAG) {
+		/* restore for compacted data summary */
+		if (read_compacted_summaries(sbi))
+			return -EINVAL;
+		type = CURSEG_HOT_NODE;
+	}
+
+	for (; type <= CURSEG_COLD_NODE; type++)
+		if (read_normal_summaries(sbi, type))
+			return -EINVAL;
+	return 0;
+}
+
+static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
+{
+	struct page *page;
+	unsigned char *kaddr;
+	struct f2fs_summary *summary;
+	struct curseg_info *seg_i;
+	int written_size = 0;
+	int i, j;
+
+	page = grab_meta_page(sbi, blkaddr++);
+	kaddr = (unsigned char *)page_address(page);
+
+	/* Step 1: write nat cache */
+	seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
+	memcpy(kaddr, &seg_i->sum_blk->n_nats, SUM_JOURNAL_SIZE);
+	written_size += SUM_JOURNAL_SIZE;
+
+	/* Step 2: write sit cache */
+	seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA);
+	memcpy(kaddr + written_size, &seg_i->sum_blk->n_sits,
+						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;
+		seg_i = CURSEG_I(sbi, i);
+		if (sbi->ckpt->alloc_type[i] == SSR)
+			blkoff = sbi->blocks_per_seg;
+		else
+			blkoff = curseg_blkoff(sbi, i);
+
+		for (j = 0; j < blkoff; j++) {
+			if (!page) {
+				page = grab_meta_page(sbi, blkaddr++);
+				kaddr = (unsigned char *)page_address(page);
+				written_size = 0;
+			}
+			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;
+
+			f2fs_put_page(page, 1);
+			page = NULL;
+		}
+	}
+	if (page)
+		f2fs_put_page(page, 1);
+}
+
+static void write_normal_summaries(struct f2fs_sb_info *sbi,
+					block_t blkaddr, int type)
+{
+	int i, end;
+	if (IS_DATASEG(type))
+		end = type + NR_CURSEG_DATA_TYPE;
+	else
+		end = type + NR_CURSEG_NODE_TYPE;
+
+	for (i = type; i < end; i++) {
+		struct curseg_info *sum = CURSEG_I(sbi, i);
+		mutex_lock(&sum->curseg_mutex);
+		write_sum_page(sbi, sum->sum_blk, blkaddr + (i - type));
+		mutex_unlock(&sum->curseg_mutex);
+	}
+}
+
+void write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
+{
+	if (sbi->ckpt->ckpt_flags & CP_COMPACT_SUM_FLAG)
+		write_compacted_summaries(sbi, start_blk);
+	else
+		write_normal_summaries(sbi, start_blk, CURSEG_HOT_DATA);
+}
+
+void write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
+{
+	if (sbi->ckpt->ckpt_flags & CP_UMOUNT_FLAG)
+		write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE);
+	return;
+}
+
+int lookup_journal_in_cursum(struct f2fs_summary_block *sum, int type,
+					unsigned int val, int alloc)
+{
+	int i;
+
+	if (type == NAT_JOURNAL) {
+		for (i = 0; i < nats_in_cursum(sum); i++) {
+			if (le32_to_cpu(nid_in_journal(sum, i)) == val)
+				return i;
+		}
+		if (alloc && nats_in_cursum(sum) < NAT_JOURNAL_ENTRIES)
+			return update_nats_in_cursum(sum, 1);
+	} else if (type == SIT_JOURNAL) {
+		for (i = 0; i < sits_in_cursum(sum); i++)
+			if (le32_to_cpu(segno_in_journal(sum, i)) == val)
+				return i;
+		if (alloc && sits_in_cursum(sum) < SIT_JOURNAL_ENTRIES)
+			return update_sits_in_cursum(sum, 1);
+	}
+	return -1;
+}
+
+static struct page *get_current_sit_page(struct f2fs_sb_info *sbi,
+					unsigned int segno)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	unsigned int offset = SIT_BLOCK_OFFSET(sit_i, segno);
+	block_t blk_addr = sit_i->sit_base_addr + offset;
+
+	check_seg_range(sbi, segno);
+
+	/* calculate sit block address */
+	if (f2fs_test_bit(offset, sit_i->sit_bitmap))
+		blk_addr += sit_i->sit_blocks;
+
+	return get_meta_page(sbi, blk_addr);
+}
+
+static struct page *get_next_sit_page(struct f2fs_sb_info *sbi,
+					unsigned int start)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	struct page *src_page, *dst_page;
+	pgoff_t src_off, dst_off;
+	void *src_addr, *dst_addr;
+
+	src_off = current_sit_addr(sbi, start);
+	dst_off = next_sit_addr(sbi, src_off);
+
+	/* 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));
+
+	src_addr = page_address(src_page);
+	dst_addr = page_address(dst_page);
+	memcpy(dst_addr, src_addr, PAGE_CACHE_SIZE);
+
+	set_page_dirty(dst_page);
+	f2fs_put_page(src_page, 1);
+
+	set_to_next_sit(sit_i, start);
+
+	return dst_page;
+}
+
+static bool flush_sits_in_journal(struct f2fs_sb_info *sbi)
+{
+	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
+	struct f2fs_summary_block *sum = curseg->sum_blk;
+	int i;
+
+	/*
+	 * If the journal area in the current summary is full of sit entries,
+	 * all the sit entries will be flushed. Otherwise the sit entries
+	 * are not able to replace with newly hot sit entries.
+	 */
+	if (sits_in_cursum(sum) >= SIT_JOURNAL_ENTRIES) {
+		for (i = sits_in_cursum(sum) - 1; i >= 0; i--) {
+			unsigned int segno;
+			segno = le32_to_cpu(segno_in_journal(sum, i));
+			__mark_sit_entry_dirty(sbi, segno);
+		}
+		update_sits_in_cursum(sum, -sits_in_cursum(sum));
+		return 1;
+	}
+	return 0;
+}
+
+/**
+ * CP calls this function, which flushes SIT entries including sit_journal,
+ * and moves prefree segs to free segs.
+ */
+void flush_sit_entries(struct f2fs_sb_info *sbi)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	unsigned long *bitmap = sit_i->dirty_sentries_bitmap;
+	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
+	struct f2fs_summary_block *sum = curseg->sum_blk;
+	unsigned long nsegs = TOTAL_SEGS(sbi);
+	struct page *page = NULL;
+	struct f2fs_sit_block *raw_sit = NULL;
+	unsigned int start = 0, end = 0;
+	unsigned int segno = -1;
+	bool flushed;
+
+	mutex_lock(&curseg->curseg_mutex);
+	mutex_lock(&sit_i->sentry_lock);
+
+	/*
+	 * "flushed" indicates whether sit entries in journal are flushed
+	 * to the SIT area or not.
+	 */
+	flushed = flush_sits_in_journal(sbi);
+
+	while ((segno = find_next_bit(bitmap, nsegs, segno + 1)) < nsegs) {
+		struct seg_entry *se = get_seg_entry(sbi, segno);
+		int sit_offset, offset;
+
+		sit_offset = SIT_ENTRY_OFFSET(sit_i, segno);
+
+		if (flushed)
+			goto to_sit_page;
+
+		offset = lookup_journal_in_cursum(sum, SIT_JOURNAL, segno, 1);
+		if (offset >= 0) {
+			segno_in_journal(sum, offset) = cpu_to_le32(segno);
+			seg_info_to_raw_sit(se, &sit_in_journal(sum, offset));
+			goto flush_done;
+		}
+to_sit_page:
+		if (!page || (start > segno) || (segno > end)) {
+			if (page) {
+				f2fs_put_page(page, 1);
+				page = NULL;
+			}
+
+			start = START_SEGNO(sit_i, segno);
+			end = start + SIT_ENTRY_PER_BLOCK - 1;
+
+			/* read sit block that will be updated */
+			page = get_next_sit_page(sbi, start);
+			raw_sit = page_address(page);
+		}
+
+		/* udpate entry in SIT block */
+		seg_info_to_raw_sit(se, &raw_sit->entries[sit_offset]);
+flush_done:
+		__clear_bit(segno, bitmap);
+		sit_i->dirty_sentries--;
+	}
+	mutex_unlock(&sit_i->sentry_lock);
+	mutex_unlock(&curseg->curseg_mutex);
+
+	/* writeout last modified SIT block */
+	f2fs_put_page(page, 1);
+
+	set_prefree_as_free_segments(sbi);
+}
+
+static int build_sit_info(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	struct sit_info *sit_i;
+	unsigned int sit_segs, start;
+	char *src_bitmap, *dst_bitmap;
+	unsigned int bitmap_size;
+
+	/* allocate memory for SIT information */
+	sit_i = kzalloc(sizeof(struct sit_info), GFP_KERNEL);
+	if (!sit_i)
+		return -ENOMEM;
+
+	SM_I(sbi)->sit_info = sit_i;
+
+	sit_i->sentries = vzalloc(TOTAL_SEGS(sbi) * sizeof(struct seg_entry));
+	if (!sit_i->sentries)
+		return -ENOMEM;
+
+	bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
+	sit_i->dirty_sentries_bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+	if (!sit_i->dirty_sentries_bitmap)
+		return -ENOMEM;
+
+	for (start = 0; start < TOTAL_SEGS(sbi); start++) {
+		sit_i->sentries[start].cur_valid_map
+			= kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL);
+		sit_i->sentries[start].ckpt_valid_map
+			= kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL);
+		if (!sit_i->sentries[start].cur_valid_map
+				|| !sit_i->sentries[start].ckpt_valid_map)
+			return -ENOMEM;
+	}
+
+	if (sbi->segs_per_sec > 1) {
+		sit_i->sec_entries = vzalloc(sbi->total_sections *
+					sizeof(struct sec_entry));
+		if (!sit_i->sec_entries)
+			return -ENOMEM;
+	}
+
+	/* get information related with SIT */
+	sit_segs = le32_to_cpu(raw_super->segment_count_sit) >> 1;
+
+	/* setup SIT bitmap from ckeckpoint pack */
+	bitmap_size = __bitmap_size(sbi, SIT_BITMAP);
+	src_bitmap = __bitmap_ptr(sbi, SIT_BITMAP);
+
+	dst_bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+	if (!dst_bitmap)
+		return -ENOMEM;
+	memcpy(dst_bitmap, src_bitmap, bitmap_size);
+
+	/* init SIT information */
+	sit_i->s_ops = &default_salloc_ops;
+
+	sit_i->sit_base_addr = le32_to_cpu(raw_super->sit_blkaddr);
+	sit_i->sit_blocks = sit_segs << sbi->log_blocks_per_seg;
+	sit_i->written_valid_blocks = le64_to_cpu(ckpt->valid_block_count);
+	sit_i->sit_bitmap = dst_bitmap;
+	sit_i->bitmap_size = bitmap_size;
+	sit_i->dirty_sentries = 0;
+	sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK;
+	sit_i->elapsed_time = le64_to_cpu(sbi->ckpt->elapsed_time);
+	sit_i->mounted_time = CURRENT_TIME_SEC.tv_sec;
+	mutex_init(&sit_i->sentry_lock);
+	return 0;
+}
+
+static int build_free_segmap(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_sm_info *sm_info = SM_I(sbi);
+	struct free_segmap_info *free_i;
+	unsigned int bitmap_size, sec_bitmap_size;
+
+	/* allocate memory for free segmap information */
+	free_i = kzalloc(sizeof(struct free_segmap_info), GFP_KERNEL);
+	if (!free_i)
+		return -ENOMEM;
+
+	SM_I(sbi)->free_info = free_i;
+
+	bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
+	free_i->free_segmap = kmalloc(bitmap_size, GFP_KERNEL);
+	if (!free_i->free_segmap)
+		return -ENOMEM;
+
+	sec_bitmap_size = f2fs_bitmap_size(sbi->total_sections);
+	free_i->free_secmap = kmalloc(sec_bitmap_size, GFP_KERNEL);
+	if (!free_i->free_secmap)
+		return -ENOMEM;
+
+	/* set all segments as dirty temporarily */
+	memset(free_i->free_segmap, 0xff, bitmap_size);
+	memset(free_i->free_secmap, 0xff, sec_bitmap_size);
+
+	/* init free segmap information */
+	free_i->start_segno =
+		(unsigned int) GET_SEGNO_FROM_SEG0(sbi, sm_info->main_blkaddr);
+	free_i->free_segments = 0;
+	free_i->free_sections = 0;
+	rwlock_init(&free_i->segmap_lock);
+	return 0;
+}
+
+static int build_curseg(struct f2fs_sb_info *sbi)
+{
+	struct curseg_info *array = NULL;
+	int i;
+
+	array = kzalloc(sizeof(*array) * NR_CURSEG_TYPE, GFP_KERNEL);
+	if (!array)
+		return -ENOMEM;
+
+	SM_I(sbi)->curseg_array = array;
+
+	for (i = 0; i < NR_CURSEG_TYPE; i++) {
+		mutex_init(&array[i].curseg_mutex);
+		array[i].sum_blk = kzalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
+		if (!array[i].sum_blk)
+			return -ENOMEM;
+		array[i].segno = NULL_SEGNO;
+		array[i].next_blkoff = 0;
+	}
+	return restore_curseg_summaries(sbi);
+}
+
+static void build_sit_entries(struct f2fs_sb_info *sbi)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
+	struct f2fs_summary_block *sum = curseg->sum_blk;
+	unsigned int start;
+
+	for (start = 0; start < TOTAL_SEGS(sbi); start++) {
+		struct seg_entry *se = &sit_i->sentries[start];
+		struct f2fs_sit_block *sit_blk;
+		struct f2fs_sit_entry sit;
+		struct page *page;
+		int i;
+
+		mutex_lock(&curseg->curseg_mutex);
+		for (i = 0; i < sits_in_cursum(sum); i++) {
+			if (le32_to_cpu(segno_in_journal(sum, i)) == start) {
+				sit = sit_in_journal(sum, i);
+				mutex_unlock(&curseg->curseg_mutex);
+				goto got_it;
+			}
+		}
+		mutex_unlock(&curseg->curseg_mutex);
+		page = get_current_sit_page(sbi, start);
+		sit_blk = (struct f2fs_sit_block *)page_address(page);
+		sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)];
+		f2fs_put_page(page, 1);
+got_it:
+		check_block_count(sbi, start, &sit);
+		seg_info_from_raw_sit(se, &sit);
+		if (sbi->segs_per_sec > 1) {
+			struct sec_entry *e = get_sec_entry(sbi, start);
+			e->valid_blocks += se->valid_blocks;
+		}
+	}
+}
+
+static void init_free_segmap(struct f2fs_sb_info *sbi)
+{
+	unsigned int start;
+	int type;
+
+	for (start = 0; start < TOTAL_SEGS(sbi); start++) {
+		struct seg_entry *sentry = get_seg_entry(sbi, start);
+		if (!sentry->valid_blocks)
+			__set_free(sbi, start);
+	}
+
+	/* set use the current segments */
+	for (type = CURSEG_HOT_DATA; type <= CURSEG_COLD_NODE; type++) {
+		struct curseg_info *curseg_t = CURSEG_I(sbi, type);
+		__set_test_and_inuse(sbi, curseg_t->segno);
+	}
+}
+
+static void init_dirty_segmap(struct f2fs_sb_info *sbi)
+{
+	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+	struct free_segmap_info *free_i = FREE_I(sbi);
+	unsigned int segno = 0, offset = 0;
+	unsigned short valid_blocks;
+
+	while (segno < TOTAL_SEGS(sbi)) {
+		/* find dirty segment based on free segmap */
+		segno = find_next_inuse(free_i, TOTAL_SEGS(sbi), offset);
+		if (segno >= TOTAL_SEGS(sbi))
+			break;
+		offset = segno + 1;
+		valid_blocks = get_valid_blocks(sbi, segno, 0);
+		if (valid_blocks >= sbi->blocks_per_seg || !valid_blocks)
+			continue;
+		mutex_lock(&dirty_i->seglist_lock);
+		__locate_dirty_segment(sbi, segno, DIRTY);
+		mutex_unlock(&dirty_i->seglist_lock);
+	}
+}
+
+static int init_victim_segmap(struct f2fs_sb_info *sbi)
+{
+	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+	unsigned int bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
+
+	dirty_i->victim_segmap[FG_GC] = kzalloc(bitmap_size, GFP_KERNEL);
+	dirty_i->victim_segmap[BG_GC] = kzalloc(bitmap_size, GFP_KERNEL);
+	if (!dirty_i->victim_segmap[FG_GC] || !dirty_i->victim_segmap[BG_GC])
+		return -ENOMEM;
+	return 0;
+}
+
+static int build_dirty_segmap(struct f2fs_sb_info *sbi)
+{
+	struct dirty_seglist_info *dirty_i;
+	unsigned int bitmap_size, i;
+
+	/* allocate memory for dirty segments list information */
+	dirty_i = kzalloc(sizeof(struct dirty_seglist_info), GFP_KERNEL);
+	if (!dirty_i)
+		return -ENOMEM;
+
+	SM_I(sbi)->dirty_info = dirty_i;
+	mutex_init(&dirty_i->seglist_lock);
+
+	bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
+
+	for (i = 0; i < NR_DIRTY_TYPE; i++) {
+		dirty_i->dirty_segmap[i] = kzalloc(bitmap_size, GFP_KERNEL);
+		dirty_i->nr_dirty[i] = 0;
+		if (!dirty_i->dirty_segmap[i])
+			return -ENOMEM;
+	}
+
+	init_dirty_segmap(sbi);
+	return init_victim_segmap(sbi);
+}
+
+/**
+ * Update min, max modified time for cost-benefit GC algorithm
+ */
+static void init_min_max_mtime(struct f2fs_sb_info *sbi)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	unsigned int segno;
+
+	mutex_lock(&sit_i->sentry_lock);
+
+	sit_i->min_mtime = LLONG_MAX;
+
+	for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) {
+		unsigned int i;
+		unsigned long long mtime = 0;
+
+		for (i = 0; i < sbi->segs_per_sec; i++)
+			mtime += get_seg_entry(sbi, segno + i)->mtime;
+
+		mtime = div_u64(mtime, sbi->segs_per_sec);
+
+		if (sit_i->min_mtime > mtime)
+			sit_i->min_mtime = mtime;
+	}
+	sit_i->max_mtime = get_mtime(sbi);
+	mutex_unlock(&sit_i->sentry_lock);
+}
+
+int build_segment_manager(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
+	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+	struct f2fs_sm_info *sm_info = NULL;
+	int err;
+
+	sm_info = kzalloc(sizeof(struct f2fs_sm_info), GFP_KERNEL);
+	if (!sm_info)
+		return -ENOMEM;
+
+	/* init sm info */
+	sbi->sm_info = sm_info;
+	INIT_LIST_HEAD(&sm_info->wblist_head);
+	spin_lock_init(&sm_info->wblist_lock);
+	sm_info->seg0_blkaddr = le32_to_cpu(raw_super->segment0_blkaddr);
+	sm_info->main_blkaddr = le32_to_cpu(raw_super->main_blkaddr);
+	sm_info->segment_count = le32_to_cpu(raw_super->segment_count);
+	sm_info->reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
+	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);
+
+	err = build_sit_info(sbi);
+	if (err)
+		return err;
+	err = build_free_segmap(sbi);
+	if (err)
+		return err;
+	err = build_curseg(sbi);
+	if (err)
+		return err;
+
+	/* reinit free segmap based on SIT */
+	build_sit_entries(sbi);
+
+	init_free_segmap(sbi);
+	err = build_dirty_segmap(sbi);
+	if (err)
+		return err;
+
+	init_min_max_mtime(sbi);
+	return 0;
+}
+
+static void discard_dirty_segmap(struct f2fs_sb_info *sbi,
+		enum dirty_type dirty_type)
+{
+	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+
+	mutex_lock(&dirty_i->seglist_lock);
+	kfree(dirty_i->dirty_segmap[dirty_type]);
+	dirty_i->nr_dirty[dirty_type] = 0;
+	mutex_unlock(&dirty_i->seglist_lock);
+}
+
+void reset_victim_segmap(struct f2fs_sb_info *sbi)
+{
+	unsigned int bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
+	memset(DIRTY_I(sbi)->victim_segmap[FG_GC], 0, bitmap_size);
+}
+
+static void destroy_victim_segmap(struct f2fs_sb_info *sbi)
+{
+	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+
+	kfree(dirty_i->victim_segmap[FG_GC]);
+	kfree(dirty_i->victim_segmap[BG_GC]);
+}
+
+static void destroy_dirty_segmap(struct f2fs_sb_info *sbi)
+{
+	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+	int i;
+
+	if (!dirty_i)
+		return;
+
+	/* discard pre-free/dirty segments list */
+	for (i = 0; i < NR_DIRTY_TYPE; i++)
+		discard_dirty_segmap(sbi, i);
+
+	destroy_victim_segmap(sbi);
+	SM_I(sbi)->dirty_info = NULL;
+	kfree(dirty_i);
+}
+
+static void destroy_curseg(struct f2fs_sb_info *sbi)
+{
+	struct curseg_info *array = SM_I(sbi)->curseg_array;
+	int i;
+
+	if (!array)
+		return;
+	SM_I(sbi)->curseg_array = NULL;
+	for (i = 0; i < NR_CURSEG_TYPE; i++)
+		kfree(array[i].sum_blk);
+	kfree(array);
+}
+
+static void destroy_free_segmap(struct f2fs_sb_info *sbi)
+{
+	struct free_segmap_info *free_i = SM_I(sbi)->free_info;
+	if (!free_i)
+		return;
+	SM_I(sbi)->free_info = NULL;
+	kfree(free_i->free_segmap);
+	kfree(free_i->free_secmap);
+	kfree(free_i);
+}
+
+static void destroy_sit_info(struct f2fs_sb_info *sbi)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	unsigned int start;
+
+	if (!sit_i)
+		return;
+
+	if (sit_i->sentries) {
+		for (start = 0; start < TOTAL_SEGS(sbi); start++) {
+			kfree(sit_i->sentries[start].cur_valid_map);
+			kfree(sit_i->sentries[start].ckpt_valid_map);
+		}
+	}
+	vfree(sit_i->sentries);
+	vfree(sit_i->sec_entries);
+	kfree(sit_i->dirty_sentries_bitmap);
+
+	SM_I(sbi)->sit_info = NULL;
+	kfree(sit_i->sit_bitmap);
+	kfree(sit_i);
+}
+
+void destroy_segment_manager(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_sm_info *sm_info = SM_I(sbi);
+	destroy_dirty_segmap(sbi);
+	destroy_curseg(sbi);
+	destroy_free_segmap(sbi);
+	destroy_sit_info(sbi);
+	sbi->sm_info = NULL;
+	kfree(sm_info);
+}
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
new file mode 100644
index 0000000..e380a8e
--- /dev/null
+++ b/fs/f2fs/segment.h
@@ -0,0 +1,615 @@
+/**
+ * fs/f2fs/segment.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/* constant macro */
+#define NULL_SEGNO			((unsigned int)(~0))
+
+/* V: 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)
+
+#define IS_DATASEG(t)							\
+	((t == CURSEG_HOT_DATA) || (t == CURSEG_COLD_DATA) ||		\
+	(t == CURSEG_WARM_DATA))
+
+#define IS_NODESEG(t)							\
+	((t == CURSEG_HOT_NODE) || (t == CURSEG_COLD_NODE) ||		\
+	(t == CURSEG_WARM_NODE))
+
+#define IS_CURSEG(sbi, segno)						\
+	((segno == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) ||	\
+	 (segno == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) ||	\
+	 (segno == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno) ||	\
+	 (segno == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno) ||	\
+	 (segno == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno) ||	\
+	 (segno == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno))
+
+#define IS_CURSEC(sbi, secno)						\
+	((secno == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno /		\
+	  sbi->segs_per_sec) ||	\
+	 (secno == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno /		\
+	  sbi->segs_per_sec) ||	\
+	 (secno == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno /		\
+	  sbi->segs_per_sec) ||	\
+	 (secno == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno /		\
+	  sbi->segs_per_sec) ||	\
+	 (secno == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno /		\
+	  sbi->segs_per_sec) ||	\
+	 (secno == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno /		\
+	  sbi->segs_per_sec))	\
+
+#define START_BLOCK(sbi, segno)						\
+	(SM_I(sbi)->seg0_blkaddr +					\
+	 (GET_R2L_SEGNO(FREE_I(sbi), segno) << sbi->log_blocks_per_seg))
+#define NEXT_FREE_BLKADDR(sbi, curseg)					\
+	(START_BLOCK(sbi, curseg->segno) + curseg->next_blkoff)
+
+#define MAIN_BASE_BLOCK(sbi)	(SM_I(sbi)->main_blkaddr)
+
+#define GET_SEGOFF_FROM_SEG0(sbi, blk_addr)				\
+	((blk_addr) - SM_I(sbi)->seg0_blkaddr)
+#define GET_SEGNO_FROM_SEG0(sbi, blk_addr)				\
+	(GET_SEGOFF_FROM_SEG0(sbi, blk_addr) >> sbi->log_blocks_per_seg)
+#define GET_SEGNO(sbi, blk_addr)					\
+	(((blk_addr == NULL_ADDR) || (blk_addr == NEW_ADDR)) ?		\
+	NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi),			\
+		GET_SEGNO_FROM_SEG0(sbi, blk_addr)))
+#define GET_SECNO(sbi, segno)					\
+	((segno) / sbi->segs_per_sec)
+#define GET_ZONENO_FROM_SEGNO(sbi, segno)				\
+	((segno / sbi->segs_per_sec) / sbi->secs_per_zone)
+
+#define GET_SUM_BLOCK(sbi, segno)				\
+	((sbi->sm_info->ssa_blkaddr) + segno)
+
+#define GET_SUM_TYPE(footer) ((footer)->entry_type)
+#define SET_SUM_TYPE(footer, type) ((footer)->entry_type = type)
+
+#define SIT_ENTRY_OFFSET(sit_i, segno)					\
+	(segno % sit_i->sents_per_block)
+#define SIT_BLOCK_OFFSET(sit_i, segno)					\
+	(segno / SIT_ENTRY_PER_BLOCK)
+#define	START_SEGNO(sit_i, segno)		\
+	(SIT_BLOCK_OFFSET(sit_i, segno) * SIT_ENTRY_PER_BLOCK)
+#define f2fs_bitmap_size(nr)			\
+	(BITS_TO_LONGS(nr) * sizeof(unsigned long))
+#define TOTAL_SEGS(sbi)	(SM_I(sbi)->main_segments)
+
+/* during checkpoint, bio_private is used to synchronize the last bio */
+struct bio_private {
+	struct f2fs_sb_info *sbi;
+	bool is_sync;
+	void *wait;
+};
+
+/*
+ * indicate a block allocation direction: RIGHT and LEFT.
+ * RIGHT means allocating new sections towards the end of volume.
+ * LEFT means the opposite direction.
+ */
+enum {
+	ALLOC_RIGHT = 0,
+	ALLOC_LEFT
+};
+
+/*
+ * In the victim_sel_policy->alloc_mode, there are two block allocation modes.
+ * LFS writes data sequentially with cleaning operations.
+ * SSR (Slack Space Recycle) reuses obsolete space without cleaning operations.
+ */
+enum {
+	LFS = 0,
+	SSR
+};
+
+/*
+ * In the victim_sel_policy->gc_mode, there are two gc, aka cleaning, modes.
+ * GC_CB is based on cost-benefit algorithm.
+ * GC_GREEDY is based on greedy algorithm.
+ */
+enum {
+	GC_CB = 0,
+	GC_GREEDY
+};
+
+/*
+ * BG_GC means the background cleaning job.
+ * FG_GC means the on-demand cleaning job.
+ */
+enum {
+	BG_GC = 0,
+	FG_GC
+};
+
+/* for a function parameter to select a victim segment */
+struct victim_sel_policy {
+	int alloc_mode;			/* LFS or SSR */
+	int gc_mode;			/* GC_CB or GC_GREEDY */
+	unsigned long *dirty_segmap;	/* dirty segment bitmap */
+	unsigned int offset;		/* last scanned bitmap offset */
+	unsigned int ofs_unit;		/* bitmap search unit */
+	unsigned int min_cost;		/* minimum cost */
+	unsigned int min_segno;		/* segment # having min. cost */
+};
+
+struct seg_entry {
+	unsigned short valid_blocks;	/* # of valid blocks */
+	unsigned char *cur_valid_map;	/* validity bitmap of blocks */
+	/*
+	 * # of valid blocks and the validity bitmap stored in the the last
+	 * checkpoint pack. This information is used by the SSR mode.
+	 */
+	unsigned short ckpt_valid_blocks;
+	unsigned char *ckpt_valid_map;
+	unsigned char type;		/* segment type like CURSEG_XXX_TYPE */
+	unsigned long long mtime;	/* modification time of the segment */
+};
+
+struct sec_entry {
+	unsigned int valid_blocks;	/* # of valid blocks in a section */
+};
+
+struct segment_allocation {
+	void (*allocate_segment)(struct f2fs_sb_info *, int, bool);
+};
+
+struct sit_info {
+	const struct segment_allocation *s_ops;
+
+	block_t sit_base_addr;		/* start block address of SIT area */
+	block_t sit_blocks;		/* # of blocks used by SIT area */
+	block_t written_valid_blocks;	/* # of valid blocks in main area */
+	char *sit_bitmap;		/* SIT bitmap pointer */
+	unsigned int bitmap_size;	/* SIT bitmap size */
+
+	unsigned long *dirty_sentries_bitmap;	/* bitmap for dirty sentries */
+	unsigned int dirty_sentries;		/* # of dirty sentries */
+	unsigned int sents_per_block;		/* # of SIT entries per block */
+	struct mutex sentry_lock;		/* to protect SIT cache */
+	struct seg_entry *sentries;		/* SIT segment-level cache */
+	struct sec_entry *sec_entries;		/* SIT section-level cache */
+
+	/* for cost-benefit algorithm in cleaning procedure */
+	unsigned long long elapsed_time;	/* elapsed time after mount */
+	unsigned long long mounted_time;	/* mount time */
+	unsigned long long min_mtime;		/* min. modification time */
+	unsigned long long max_mtime;		/* max. modification time */
+};
+
+struct free_segmap_info {
+	unsigned int start_segno;	/* start segment number logically */
+	unsigned int free_segments;	/* # of free segments */
+	unsigned int free_sections;	/* # of free sections */
+	rwlock_t segmap_lock;		/* free segmap lock */
+	unsigned long *free_segmap;	/* free segment bitmap */
+	unsigned long *free_secmap;	/* free section bitmap */
+};
+
+/* Notice: The order of dirty type is same with CURSEG_XXX in f2fs.h */
+enum dirty_type {
+	DIRTY_HOT_DATA,		/* dirty segments assigned as hot data logs */
+	DIRTY_WARM_DATA,	/* dirty segments assigned as warm data logs */
+	DIRTY_COLD_DATA,	/* dirty segments assigned as cold data logs */
+	DIRTY_HOT_NODE,		/* dirty segments assigned as hot node logs */
+	DIRTY_WARM_NODE,	/* dirty segments assigned as warm node logs */
+	DIRTY_COLD_NODE,	/* dirty segments assigned as cold node logs */
+	DIRTY,			/* to count # of dirty segments */
+	PRE,			/* to count # of entirely obsolete segments */
+	NR_DIRTY_TYPE
+};
+
+struct dirty_seglist_info {
+	const struct victim_selection *v_ops;	/* victim selction operation */
+	unsigned long *dirty_segmap[NR_DIRTY_TYPE];
+	struct mutex seglist_lock;		/* lock for segment bitmaps */
+	int nr_dirty[NR_DIRTY_TYPE];		/* # of dirty segments */
+	unsigned long *victim_segmap[2];	/* BG_GC, FG_GC */
+};
+
+/* victim selection function for cleaning and SSR */
+struct victim_selection {
+	int (*get_victim)(struct f2fs_sb_info *, unsigned int *,
+							int, int, char);
+};
+
+/* for active log information */
+struct curseg_info {
+	struct mutex curseg_mutex;		/* lock for consistency */
+	struct f2fs_summary_block *sum_blk;	/* cached summary block */
+	unsigned char alloc_type;		/* current allocation type */
+	unsigned int segno;			/* current segment number */
+	unsigned short next_blkoff;		/* next block offset to write */
+	unsigned int zone;			/* current zone number */
+	unsigned int next_segno;		/* preallocated segment */
+};
+
+/*
+ * inline functions
+ */
+static inline struct curseg_info *CURSEG_I(struct f2fs_sb_info *sbi, int type)
+{
+	return (struct curseg_info *)(SM_I(sbi)->curseg_array + type);
+}
+
+static inline struct seg_entry *get_seg_entry(struct f2fs_sb_info *sbi,
+						unsigned int segno)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	return &sit_i->sentries[segno];
+}
+
+static inline struct sec_entry *get_sec_entry(struct f2fs_sb_info *sbi,
+						unsigned int segno)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	return &sit_i->sec_entries[GET_SECNO(sbi, segno)];
+}
+
+static inline unsigned int get_valid_blocks(struct f2fs_sb_info *sbi,
+				unsigned int segno, int section)
+{
+	/*
+	 * In order to get # of valid blocks in a section instantly from many
+	 * segments, f2fs manages two counting structures separately.
+	 */
+	if (section > 1)
+		return get_sec_entry(sbi, segno)->valid_blocks;
+	else
+		return get_seg_entry(sbi, segno)->valid_blocks;
+}
+
+static inline void seg_info_from_raw_sit(struct seg_entry *se,
+					struct f2fs_sit_entry *rs)
+{
+	se->valid_blocks = GET_SIT_VBLOCKS(rs);
+	se->ckpt_valid_blocks = GET_SIT_VBLOCKS(rs);
+	memcpy(se->cur_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
+	memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
+	se->type = GET_SIT_TYPE(rs);
+	se->mtime = le64_to_cpu(rs->mtime);
+}
+
+static inline void seg_info_to_raw_sit(struct seg_entry *se,
+					struct f2fs_sit_entry *rs)
+{
+	unsigned short raw_vblocks = (se->type << SIT_VBLOCKS_SHIFT) |
+					se->valid_blocks;
+	rs->vblocks = cpu_to_le16(raw_vblocks);
+	memcpy(rs->valid_map, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE);
+	memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
+	se->ckpt_valid_blocks = se->valid_blocks;
+	rs->mtime = cpu_to_le64(se->mtime);
+}
+
+static inline unsigned int find_next_inuse(struct free_segmap_info *free_i,
+		unsigned int max, unsigned int segno)
+{
+	unsigned int ret;
+	read_lock(&free_i->segmap_lock);
+	ret = find_next_bit(free_i->free_segmap, max, segno);
+	read_unlock(&free_i->segmap_lock);
+	return ret;
+}
+
+static inline void __set_free(struct f2fs_sb_info *sbi, unsigned int segno)
+{
+	struct free_segmap_info *free_i = FREE_I(sbi);
+	unsigned int secno = segno / sbi->segs_per_sec;
+	unsigned int start_segno = secno * sbi->segs_per_sec;
+	unsigned int next;
+
+	write_lock(&free_i->segmap_lock);
+	clear_bit(segno, free_i->free_segmap);
+	free_i->free_segments++;
+
+	next = find_next_bit(free_i->free_segmap, TOTAL_SEGS(sbi), start_segno);
+	if (next >= start_segno + sbi->segs_per_sec) {
+		clear_bit(secno, free_i->free_secmap);
+		free_i->free_sections++;
+	}
+	write_unlock(&free_i->segmap_lock);
+}
+
+static inline void __set_inuse(struct f2fs_sb_info *sbi,
+		unsigned int segno)
+{
+	struct free_segmap_info *free_i = FREE_I(sbi);
+	unsigned int secno = segno / sbi->segs_per_sec;
+	set_bit(segno, free_i->free_segmap);
+	free_i->free_segments--;
+	if (!test_and_set_bit(secno, free_i->free_secmap))
+		free_i->free_sections--;
+}
+
+static inline void __set_test_and_free(struct f2fs_sb_info *sbi,
+		unsigned int segno)
+{
+	struct free_segmap_info *free_i = FREE_I(sbi);
+	unsigned int secno = segno / sbi->segs_per_sec;
+	unsigned int start_segno = secno * sbi->segs_per_sec;
+	unsigned int next;
+
+	write_lock(&free_i->segmap_lock);
+	if (test_and_clear_bit(segno, free_i->free_segmap)) {
+		free_i->free_segments++;
+
+		next = find_next_bit(free_i->free_segmap, TOTAL_SEGS(sbi),
+								start_segno);
+		if (next >= start_segno + sbi->segs_per_sec) {
+			if (test_and_clear_bit(secno, free_i->free_secmap))
+				free_i->free_sections++;
+		}
+	}
+	write_unlock(&free_i->segmap_lock);
+}
+
+static inline void __set_test_and_inuse(struct f2fs_sb_info *sbi,
+		unsigned int segno)
+{
+	struct free_segmap_info *free_i = FREE_I(sbi);
+	unsigned int secno = segno / sbi->segs_per_sec;
+	write_lock(&free_i->segmap_lock);
+	if (!test_and_set_bit(segno, free_i->free_segmap)) {
+		free_i->free_segments--;
+		if (!test_and_set_bit(secno, free_i->free_secmap))
+			free_i->free_sections--;
+	}
+	write_unlock(&free_i->segmap_lock);
+}
+
+static inline void get_sit_bitmap(struct f2fs_sb_info *sbi,
+		void *dst_addr)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	memcpy(dst_addr, sit_i->sit_bitmap, sit_i->bitmap_size);
+}
+
+static inline block_t written_block_count(struct f2fs_sb_info *sbi)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	block_t vblocks;
+
+	mutex_lock(&sit_i->sentry_lock);
+	vblocks = sit_i->written_valid_blocks;
+	mutex_unlock(&sit_i->sentry_lock);
+
+	return vblocks;
+}
+
+static inline unsigned int free_segments(struct f2fs_sb_info *sbi)
+{
+	struct free_segmap_info *free_i = FREE_I(sbi);
+	unsigned int free_segs;
+
+	read_lock(&free_i->segmap_lock);
+	free_segs = free_i->free_segments;
+	read_unlock(&free_i->segmap_lock);
+
+	return free_segs;
+}
+
+static inline int reserved_segments(struct f2fs_sb_info *sbi)
+{
+	return SM_I(sbi)->reserved_segments;
+}
+
+static inline unsigned int free_sections(struct f2fs_sb_info *sbi)
+{
+	struct free_segmap_info *free_i = FREE_I(sbi);
+	unsigned int free_secs;
+
+	read_lock(&free_i->segmap_lock);
+	free_secs = free_i->free_sections;
+	read_unlock(&free_i->segmap_lock);
+
+	return free_secs;
+}
+
+static inline unsigned int prefree_segments(struct f2fs_sb_info *sbi)
+{
+	return DIRTY_I(sbi)->nr_dirty[PRE];
+}
+
+static inline unsigned int dirty_segments(struct f2fs_sb_info *sbi)
+{
+	return DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_DATA] +
+		DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_DATA] +
+		DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_DATA] +
+		DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_NODE] +
+		DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_NODE] +
+		DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_NODE];
+}
+
+static inline int overprovision_segments(struct f2fs_sb_info *sbi)
+{
+	return SM_I(sbi)->ovp_segments;
+}
+
+static inline int overprovision_sections(struct f2fs_sb_info *sbi)
+{
+	return ((unsigned int) overprovision_segments(sbi)) / sbi->segs_per_sec;
+}
+
+static inline int reserved_sections(struct f2fs_sb_info *sbi)
+{
+	return ((unsigned int) reserved_segments(sbi)) / sbi->segs_per_sec;
+}
+
+static inline bool need_SSR(struct f2fs_sb_info *sbi)
+{
+	return (free_sections(sbi) < overprovision_sections(sbi));
+}
+
+static inline int get_ssr_segment(struct f2fs_sb_info *sbi, int type)
+{
+	struct curseg_info *curseg = CURSEG_I(sbi, type);
+	return DIRTY_I(sbi)->v_ops->get_victim(sbi,
+				&(curseg)->next_segno, BG_GC, type, SSR);
+}
+
+static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi)
+{
+	return free_sections(sbi) <= reserved_sections(sbi);
+}
+
+static inline int utilization(struct f2fs_sb_info *sbi)
+{
+	return (long int)valid_user_blocks(sbi) * 100 /
+			(long int)sbi->user_block_count;
+}
+
+/*
+ * Sometimes f2fs may be better to drop out-of-place update policy.
+ * So, if fs utilization is over MIN_IPU_UTIL, then f2fs tries to write
+ * data in the original place likewise other traditional file systems.
+ * But, currently set 100 in percentage, which means it is disabled.
+ * See below need_inplace_update().
+ */
+#define MIN_IPU_UTIL		100
+static inline bool need_inplace_update(struct inode *inode)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	if (S_ISDIR(inode->i_mode))
+		return false;
+	if (need_SSR(sbi) && utilization(sbi) > MIN_IPU_UTIL)
+		return true;
+	return false;
+}
+
+static inline unsigned int curseg_segno(struct f2fs_sb_info *sbi,
+		int type)
+{
+	struct curseg_info *curseg = CURSEG_I(sbi, type);
+	return curseg->segno;
+}
+
+static inline unsigned char curseg_alloc_type(struct f2fs_sb_info *sbi,
+		int type)
+{
+	struct curseg_info *curseg = CURSEG_I(sbi, type);
+	return curseg->alloc_type;
+}
+
+static inline unsigned short curseg_blkoff(struct f2fs_sb_info *sbi, int type)
+{
+	struct curseg_info *curseg = CURSEG_I(sbi, type);
+	return curseg->next_blkoff;
+}
+
+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);
+	block_t total_blks = sm_info->segment_count << sbi->log_blocks_per_seg;
+	block_t start_addr = sm_info->seg0_blkaddr;
+	block_t end_addr = start_addr + total_blks - 1;
+	BUG_ON(blk_addr < start_addr);
+	BUG_ON(blk_addr > end_addr);
+}
+
+/*
+ * Summary block is always treated as invalid block
+ */
+static inline void check_block_count(struct f2fs_sb_info *sbi,
+		int segno, struct f2fs_sit_entry *raw_sit)
+{
+	struct f2fs_sm_info *sm_info = SM_I(sbi);
+	unsigned int end_segno = sm_info->segment_count - 1;
+	int valid_blocks = 0;
+	int i;
+
+	/* check segment usage */
+	BUG_ON(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg);
+
+	/* check boundary of a given segment number */
+	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++;
+	BUG_ON(GET_SIT_VBLOCKS(raw_sit) != valid_blocks);
+}
+
+static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi,
+						unsigned int start)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	unsigned int offset = SIT_BLOCK_OFFSET(sit_i, start);
+	block_t blk_addr = sit_i->sit_base_addr + offset;
+
+	check_seg_range(sbi, start);
+
+	/* calculate sit block address */
+	if (f2fs_test_bit(offset, sit_i->sit_bitmap))
+		blk_addr += sit_i->sit_blocks;
+
+	return blk_addr;
+}
+
+static inline pgoff_t next_sit_addr(struct f2fs_sb_info *sbi,
+						pgoff_t block_addr)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	block_addr -= sit_i->sit_base_addr;
+	if (block_addr < sit_i->sit_blocks)
+		block_addr += sit_i->sit_blocks;
+	else
+		block_addr -= sit_i->sit_blocks;
+
+	return block_addr + sit_i->sit_base_addr;
+}
+
+static inline void set_to_next_sit(struct sit_info *sit_i, unsigned int start)
+{
+	unsigned int block_off = SIT_BLOCK_OFFSET(sit_i, start);
+
+	if (f2fs_test_bit(block_off, sit_i->sit_bitmap))
+		f2fs_clear_bit(block_off, sit_i->sit_bitmap);
+	else
+		f2fs_set_bit(block_off, sit_i->sit_bitmap);
+}
+
+static inline unsigned long long get_mtime(struct f2fs_sb_info *sbi)
+{
+	struct sit_info *sit_i = SIT_I(sbi);
+	return sit_i->elapsed_time + CURRENT_TIME_SEC.tv_sec -
+						sit_i->mounted_time;
+}
+
+static inline void set_summary(struct f2fs_summary *sum, nid_t nid,
+			unsigned int ofs_in_node, unsigned char version)
+{
+	sum->nid = cpu_to_le32(nid);
+	sum->ofs_in_node = cpu_to_le16(ofs_in_node);
+	sum->version = version;
+}
+
+static inline block_t start_sum_block(struct f2fs_sb_info *sbi)
+{
+	return __start_cp_addr(sbi) +
+		le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
+}
+
+static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type)
+{
+	return __start_cp_addr(sbi) +
+		le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_total_block_count)
+				- (base + 1) + type;
+}
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
new file mode 100644
index 0000000..8661c93
--- /dev/null
+++ b/fs/f2fs/super.c
@@ -0,0 +1,656 @@
+/**
+ * fs/f2fs/super.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/statfs.h>
+#include <linux/proc_fs.h>
+#include <linux/buffer_head.h>
+#include <linux/backing-dev.h>
+#include <linux/kthread.h>
+#include <linux/parser.h>
+#include <linux/mount.h>
+#include <linux/seq_file.h>
+#include <linux/random.h>
+#include <linux/exportfs.h>
+#include <linux/f2fs_fs.h>
+
+#include "f2fs.h"
+#include "node.h"
+#include "xattr.h"
+
+static struct kmem_cache *f2fs_inode_cachep;
+
+enum {
+	Opt_gc_background_off,
+	Opt_disable_roll_forward,
+	Opt_discard,
+	Opt_noheap,
+	Opt_nouser_xattr,
+	Opt_noacl,
+	Opt_active_logs,
+	Opt_disable_ext_identify,
+	Opt_err,
+};
+
+static match_table_t f2fs_tokens = {
+	{Opt_gc_background_off, "background_gc_off"},
+	{Opt_disable_roll_forward, "disable_roll_forward"},
+	{Opt_discard, "discard"},
+	{Opt_noheap, "no_heap"},
+	{Opt_nouser_xattr, "nouser_xattr"},
+	{Opt_noacl, "noacl"},
+	{Opt_active_logs, "active_logs=%u"},
+	{Opt_disable_ext_identify, "disable_ext_identify"},
+	{Opt_err, NULL},
+};
+
+static void init_once(void *foo)
+{
+	struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo;
+
+	memset(fi, 0, sizeof(*fi));
+	inode_init_once(&fi->vfs_inode);
+}
+
+static struct inode *f2fs_alloc_inode(struct super_block *sb)
+{
+	struct f2fs_inode_info *fi;
+
+	fi = kmem_cache_alloc(f2fs_inode_cachep, GFP_NOFS | __GFP_ZERO);
+	if (!fi)
+		return NULL;
+
+	init_once((void *) fi);
+
+	/* Initilize f2fs-specific inode info */
+	fi->vfs_inode.i_version = 1;
+	atomic_set(&fi->dirty_dents, 0);
+	fi->i_current_depth = 1;
+	fi->i_advise = 0;
+	rwlock_init(&fi->ext.ext_lock);
+
+	set_inode_flag(fi, FI_NEW_INODE);
+
+	return &fi->vfs_inode;
+}
+
+static void f2fs_i_callback(struct rcu_head *head)
+{
+	struct inode *inode = container_of(head, struct inode, i_rcu);
+	kmem_cache_free(f2fs_inode_cachep, F2FS_I(inode));
+}
+
+void f2fs_destroy_inode(struct inode *inode)
+{
+	call_rcu(&inode->i_rcu, f2fs_i_callback);
+}
+
+static void f2fs_put_super(struct super_block *sb)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(sb);
+
+	f2fs_destroy_stats(sbi);
+	stop_gc_thread(sbi);
+
+	write_checkpoint(sbi, false, true);
+
+	iput(sbi->node_inode);
+	iput(sbi->meta_inode);
+
+	/* destroy f2fs internal modules */
+	destroy_node_manager(sbi);
+	destroy_segment_manager(sbi);
+
+	kfree(sbi->ckpt);
+
+	sb->s_fs_info = NULL;
+	brelse(sbi->raw_super_buf);
+	kfree(sbi);
+}
+
+int f2fs_sync_fs(struct super_block *sb, int sync)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(sb);
+	int ret = 0;
+
+	if (!sbi->s_dirty && !get_pages(sbi, F2FS_DIRTY_NODES))
+		return 0;
+
+	if (sync)
+		write_checkpoint(sbi, false, false);
+
+	return ret;
+}
+
+static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+	struct super_block *sb = dentry->d_sb;
+	struct f2fs_sb_info *sbi = F2FS_SB(sb);
+	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
+	block_t total_count, user_block_count, start_count, ovp_count;
+
+	total_count = le64_to_cpu(sbi->raw_super->block_count);
+	user_block_count = sbi->user_block_count;
+	start_count = le32_to_cpu(sbi->raw_super->segment0_blkaddr);
+	ovp_count = SM_I(sbi)->ovp_segments << sbi->log_blocks_per_seg;
+	buf->f_type = F2FS_SUPER_MAGIC;
+	buf->f_bsize = sbi->blocksize;
+
+	buf->f_blocks = total_count - start_count;
+	buf->f_bfree = buf->f_blocks - valid_user_blocks(sbi) - ovp_count;
+	buf->f_bavail = user_block_count - valid_user_blocks(sbi);
+
+	buf->f_files = valid_inode_count(sbi);
+	buf->f_ffree = sbi->total_node_count - valid_node_count(sbi);
+
+	buf->f_namelen = F2FS_MAX_NAME_LEN;
+	buf->f_fsid.val[0] = (u32)id;
+	buf->f_fsid.val[1] = (u32)(id >> 32);
+
+	return 0;
+}
+
+static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(root->d_sb);
+
+	if (test_opt(sbi, BG_GC))
+		seq_puts(seq, ",background_gc_on");
+	else
+		seq_puts(seq, ",background_gc_off");
+	if (test_opt(sbi, DISABLE_ROLL_FORWARD))
+		seq_puts(seq, ",disable_roll_forward");
+	if (test_opt(sbi, DISCARD))
+		seq_puts(seq, ",discard");
+	if (test_opt(sbi, NOHEAP))
+		seq_puts(seq, ",no_heap_alloc");
+#ifdef CONFIG_F2FS_FS_XATTR
+	if (test_opt(sbi, XATTR_USER))
+		seq_puts(seq, ",user_xattr");
+	else
+		seq_puts(seq, ",nouser_xattr");
+#endif
+#ifdef CONFIG_F2FS_FS_POSIX_ACL
+	if (test_opt(sbi, POSIX_ACL))
+		seq_puts(seq, ",acl");
+	else
+		seq_puts(seq, ",noacl");
+#endif
+	if (test_opt(sbi, DISABLE_EXT_IDENTIFY))
+		seq_puts(seq, ",disable_ext_indentify");
+
+	seq_printf(seq, ",active_logs=%u", sbi->active_logs);
+
+	return 0;
+}
+
+static struct super_operations f2fs_sops = {
+	.alloc_inode	= f2fs_alloc_inode,
+	.destroy_inode	= f2fs_destroy_inode,
+	.write_inode	= f2fs_write_inode,
+	.show_options	= f2fs_show_options,
+	.evict_inode	= f2fs_evict_inode,
+	.put_super	= f2fs_put_super,
+	.sync_fs	= f2fs_sync_fs,
+	.statfs		= f2fs_statfs,
+};
+
+static struct inode *f2fs_nfs_get_inode(struct super_block *sb,
+		u64 ino, u32 generation)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(sb);
+	struct inode *inode;
+
+	if (ino < F2FS_ROOT_INO(sbi))
+		return ERR_PTR(-ESTALE);
+
+	/*
+	 * f2fs_iget isn't quite right if the inode is currently unallocated!
+	 * However f2fs_iget currently does appropriate checks to handle stale
+	 * inodes so everything is OK.
+	 */
+	inode = f2fs_iget(sb, ino);
+	if (IS_ERR(inode))
+		return ERR_CAST(inode);
+	if (generation && inode->i_generation != generation) {
+		/* we didn't find the right inode.. */
+		iput(inode);
+		return ERR_PTR(-ESTALE);
+	}
+	return inode;
+}
+
+static struct dentry *f2fs_fh_to_dentry(struct super_block *sb, struct fid *fid,
+		int fh_len, int fh_type)
+{
+	return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+				    f2fs_nfs_get_inode);
+}
+
+static struct dentry *f2fs_fh_to_parent(struct super_block *sb, struct fid *fid,
+		int fh_len, int fh_type)
+{
+	return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+				    f2fs_nfs_get_inode);
+}
+
+static const struct export_operations f2fs_export_ops = {
+	.fh_to_dentry = f2fs_fh_to_dentry,
+	.fh_to_parent = f2fs_fh_to_parent,
+	.get_parent = f2fs_get_parent,
+};
+
+static int parse_options(struct f2fs_sb_info *sbi, char *options)
+{
+	substring_t args[MAX_OPT_ARGS];
+	char *p;
+	int arg = 0;
+
+	if (!options)
+		return 0;
+
+	while ((p = strsep(&options, ",")) != NULL) {
+		int token;
+		if (!*p)
+			continue;
+		/*
+		 * Initialize args struct so we know whether arg was
+		 * found; some options take optional arguments.
+		 */
+		args[0].to = args[0].from = NULL;
+		token = match_token(p, f2fs_tokens, args);
+
+		switch (token) {
+		case Opt_gc_background_off:
+			clear_opt(sbi, BG_GC);
+			break;
+		case Opt_disable_roll_forward:
+			set_opt(sbi, DISABLE_ROLL_FORWARD);
+			break;
+		case Opt_discard:
+			set_opt(sbi, DISCARD);
+			break;
+		case Opt_noheap:
+			set_opt(sbi, NOHEAP);
+			break;
+#ifdef CONFIG_F2FS_FS_XATTR
+		case Opt_nouser_xattr:
+			clear_opt(sbi, XATTR_USER);
+			break;
+#else
+		case Opt_nouser_xattr:
+			pr_info("nouser_xattr options not supported\n");
+			break;
+#endif
+#ifdef CONFIG_F2FS_FS_POSIX_ACL
+		case Opt_noacl:
+			clear_opt(sbi, POSIX_ACL);
+			break;
+#else
+		case Opt_noacl:
+			pr_info("noacl options not supported\n");
+			break;
+#endif
+		case Opt_active_logs:
+			if (args->from && match_int(args, &arg))
+				return -EINVAL;
+			if (arg != 2 && arg != 4 && arg != 6)
+				return -EINVAL;
+			sbi->active_logs = arg;
+			break;
+		case Opt_disable_ext_identify:
+			set_opt(sbi, DISABLE_EXT_IDENTIFY);
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static loff_t max_file_size(unsigned bits)
+{
+	loff_t result = ADDRS_PER_INODE;
+	loff_t leaf_count = ADDRS_PER_BLOCK;
+
+	/* two direct node blocks */
+	result += (leaf_count * 2);
+
+	/* two indirect node blocks */
+	leaf_count *= NIDS_PER_BLOCK;
+	result += (leaf_count * 2);
+
+	/* one double indirect node block */
+	leaf_count *= NIDS_PER_BLOCK;
+	result += leaf_count;
+
+	result <<= bits;
+	return result;
+}
+
+static int sanity_check_raw_super(struct f2fs_super_block *raw_super)
+{
+	unsigned int blocksize;
+
+	if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic))
+		return 1;
+
+	/* Currently, support only 4KB block size */
+	blocksize = 1 << le32_to_cpu(raw_super->log_blocksize);
+	if (blocksize != PAGE_CACHE_SIZE)
+		return 1;
+	if (le32_to_cpu(raw_super->log_sectorsize) !=
+					F2FS_LOG_SECTOR_SIZE)
+		return 1;
+	if (le32_to_cpu(raw_super->log_sectors_per_block) !=
+					F2FS_LOG_SECTORS_PER_BLOCK)
+		return 1;
+	return 0;
+}
+
+static int sanity_check_ckpt(struct f2fs_super_block *raw_super,
+				struct f2fs_checkpoint *ckpt)
+{
+	unsigned int total, fsmeta;
+
+	total = le32_to_cpu(raw_super->segment_count);
+	fsmeta = le32_to_cpu(raw_super->segment_count_ckpt);
+	fsmeta += le32_to_cpu(raw_super->segment_count_sit);
+	fsmeta += le32_to_cpu(raw_super->segment_count_nat);
+	fsmeta += le32_to_cpu(ckpt->rsvd_segment_count);
+	fsmeta += le32_to_cpu(raw_super->segment_count_ssa);
+
+	if (fsmeta >= total)
+		return 1;
+	return 0;
+}
+
+static void init_sb_info(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_super_block *raw_super = sbi->raw_super;
+	int i;
+
+	sbi->log_sectors_per_block =
+		le32_to_cpu(raw_super->log_sectors_per_block);
+	sbi->log_blocksize = le32_to_cpu(raw_super->log_blocksize);
+	sbi->blocksize = 1 << sbi->log_blocksize;
+	sbi->log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
+	sbi->blocks_per_seg = 1 << sbi->log_blocks_per_seg;
+	sbi->segs_per_sec = le32_to_cpu(raw_super->segs_per_sec);
+	sbi->secs_per_zone = le32_to_cpu(raw_super->secs_per_zone);
+	sbi->total_sections = le32_to_cpu(raw_super->section_count);
+	sbi->total_node_count =
+		(le32_to_cpu(raw_super->segment_count_nat) / 2)
+			* sbi->blocks_per_seg * NAT_ENTRY_PER_BLOCK;
+	sbi->root_ino_num = le32_to_cpu(raw_super->root_ino);
+	sbi->node_ino_num = le32_to_cpu(raw_super->node_ino);
+	sbi->meta_ino_num = le32_to_cpu(raw_super->meta_ino);
+
+	for (i = 0; i < NR_COUNT_TYPE; i++)
+		atomic_set(&sbi->nr_pages[i], 0);
+}
+
+static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
+{
+	struct f2fs_sb_info *sbi;
+	struct f2fs_super_block *raw_super;
+	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);
+	if (!sbi)
+		return -ENOMEM;
+
+	/* set a temporary block size */
+	if (!sb_set_blocksize(sb, F2FS_BLKSIZE))
+		goto free_sbi;
+
+	/* read f2fs raw super block */
+	raw_super_buf = sb_bread(sb, 0);
+	if (!raw_super_buf) {
+		err = -EIO;
+		goto free_sbi;
+	}
+	raw_super = (struct f2fs_super_block *)
+			((char *)raw_super_buf->b_data + F2FS_SUPER_OFFSET);
+
+	/* init some FS parameters */
+	sbi->active_logs = NR_CURSEG_TYPE;
+
+	set_opt(sbi, BG_GC);
+
+#ifdef CONFIG_F2FS_FS_XATTR
+	set_opt(sbi, XATTR_USER);
+#endif
+#ifdef CONFIG_F2FS_FS_POSIX_ACL
+	set_opt(sbi, POSIX_ACL);
+#endif
+	/* parse mount options */
+	if (parse_options(sbi, (char *)data))
+		goto free_sb_buf;
+
+	/* sanity checking of raw super */
+	if (sanity_check_raw_super(raw_super))
+		goto free_sb_buf;
+
+	sb->s_maxbytes = max_file_size(raw_super->log_blocksize);
+	sb->s_max_links = F2FS_LINK_MAX;
+	get_random_bytes(&sbi->s_next_generation, sizeof(u32));
+
+	sb->s_op = &f2fs_sops;
+	sb->s_xattr = f2fs_xattr_handlers;
+	sb->s_export_op = &f2fs_export_ops;
+	sb->s_magic = F2FS_SUPER_MAGIC;
+	sb->s_fs_info = sbi;
+	sb->s_time_gran = 1;
+	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+		(test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0);
+	memcpy(sb->s_uuid, raw_super->uuid, sizeof(raw_super->uuid));
+
+	/* init f2fs-specific super block info */
+	sbi->sb = sb;
+	sbi->raw_super = raw_super;
+	sbi->raw_super_buf = raw_super_buf;
+	mutex_init(&sbi->gc_mutex);
+	mutex_init(&sbi->write_inode);
+	mutex_init(&sbi->writepages);
+	mutex_init(&sbi->cp_mutex);
+	for (i = 0; i < NR_LOCK_TYPE; i++)
+		mutex_init(&sbi->fs_lock[i]);
+	sbi->por_doing = 0;
+	spin_lock_init(&sbi->stat_lock);
+	init_rwsem(&sbi->bio_sem);
+	init_sb_info(sbi);
+
+	/* get an inode for meta space */
+	sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi));
+	if (IS_ERR(sbi->meta_inode)) {
+		err = PTR_ERR(sbi->meta_inode);
+		goto free_sb_buf;
+	}
+
+	err = get_valid_checkpoint(sbi);
+	if (err)
+		goto free_meta_inode;
+
+	/* sanity checking of checkpoint */
+	err = -EINVAL;
+	if (sanity_check_ckpt(raw_super, sbi->ckpt))
+		goto free_cp;
+
+	sbi->total_valid_node_count =
+				le32_to_cpu(sbi->ckpt->valid_node_count);
+	sbi->total_valid_inode_count =
+				le32_to_cpu(sbi->ckpt->valid_inode_count);
+	sbi->user_block_count = le64_to_cpu(sbi->ckpt->user_block_count);
+	sbi->total_valid_block_count =
+				le64_to_cpu(sbi->ckpt->valid_block_count);
+	sbi->last_valid_block_count = sbi->total_valid_block_count;
+	sbi->alloc_valid_block_count = 0;
+	INIT_LIST_HEAD(&sbi->dir_inode_list);
+	spin_lock_init(&sbi->dir_inode_lock);
+
+	/* init super block */
+	if (!sb_set_blocksize(sb, sbi->blocksize))
+		goto free_cp;
+
+	init_orphan_info(sbi);
+
+	/* setup f2fs internal modules */
+	err = build_segment_manager(sbi);
+	if (err)
+		goto free_sm;
+	err = build_node_manager(sbi);
+	if (err)
+		goto free_nm;
+
+	build_gc_manager(sbi);
+
+	/* get an inode for node space */
+	sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi));
+	if (IS_ERR(sbi->node_inode)) {
+		err = PTR_ERR(sbi->node_inode);
+		goto free_nm;
+	}
+
+	/* if there are nt orphan nodes free them */
+	err = -EINVAL;
+	if (!(sbi->ckpt->ckpt_flags & CP_UMOUNT_FLAG) &&
+				recover_orphan_inodes(sbi))
+		goto free_node_inode;
+
+	/* read root inode and dentry */
+	root = f2fs_iget(sb, F2FS_ROOT_INO(sbi));
+	if (IS_ERR(root)) {
+		err = PTR_ERR(root);
+		goto free_node_inode;
+	}
+	if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size)
+		goto free_root_inode;
+
+	sb->s_root = d_make_root(root); /* allocate root dentry */
+	if (!sb->s_root) {
+		err = -ENOMEM;
+		goto free_root_inode;
+	}
+
+	/* recover fsynced data */
+	if (!(sbi->ckpt->ckpt_flags & CP_UMOUNT_FLAG) &&
+				!test_opt(sbi, DISABLE_ROLL_FORWARD))
+		recover_fsync_data(sbi);
+
+	/* After POR, we can run background GC thread */
+	err = start_gc_thread(sbi);
+	if (err)
+		goto fail;
+
+	err = f2fs_build_stats(sbi);
+	if (err)
+		goto fail;
+
+	return 0;
+fail:
+	stop_gc_thread(sbi);
+free_root_inode:
+	dput(sb->s_root);
+	sb->s_root = NULL;
+free_node_inode:
+	iput(sbi->node_inode);
+free_nm:
+	destroy_node_manager(sbi);
+free_sm:
+	destroy_segment_manager(sbi);
+free_cp:
+	kfree(sbi->ckpt);
+free_meta_inode:
+	make_bad_inode(sbi->meta_inode);
+	iput(sbi->meta_inode);
+free_sb_buf:
+	brelse(raw_super_buf);
+free_sbi:
+	kfree(sbi);
+	return err;
+}
+
+static struct dentry *f2fs_mount(struct file_system_type *fs_type, int flags,
+			const char *dev_name, void *data)
+{
+	return mount_bdev(fs_type, flags, dev_name, data, f2fs_fill_super);
+}
+
+static struct file_system_type f2fs_fs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "f2fs",
+	.mount		= f2fs_mount,
+	.kill_sb	= kill_block_super,
+	.fs_flags	= FS_REQUIRES_DEV,
+};
+
+static int init_inodecache(void)
+{
+	f2fs_inode_cachep = f2fs_kmem_cache_create("f2fs_inode_cache",
+			sizeof(struct f2fs_inode_info), NULL);
+	if (f2fs_inode_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+static void destroy_inodecache(void)
+{
+	/*
+	 * Make sure all delayed rcu free inodes are flushed before we
+	 * destroy cache.
+	 */
+	rcu_barrier();
+	kmem_cache_destroy(f2fs_inode_cachep);
+}
+
+static int __init init_f2fs_fs(void)
+{
+	int err;
+
+	err = init_inodecache();
+	if (err)
+		goto fail;
+	err = create_node_manager_caches();
+	if (err)
+		goto fail;
+	err = create_gc_caches();
+	if (err)
+		goto fail;
+	err = create_checkpoint_caches();
+	if (err)
+		goto fail;
+	return register_filesystem(&f2fs_fs_type);
+fail:
+	return err;
+}
+
+static void __exit exit_f2fs_fs(void)
+{
+	destroy_root_stats();
+	unregister_filesystem(&f2fs_fs_type);
+	destroy_checkpoint_caches();
+	destroy_gc_caches();
+	destroy_node_manager_caches();
+	destroy_inodecache();
+}
+
+module_init(init_f2fs_fs)
+module_exit(exit_f2fs_fs)
+
+MODULE_AUTHOR("Samsung Electronics's Praesto Team");
+MODULE_DESCRIPTION("Flash Friendly File System");
+MODULE_LICENSE("GPL");
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
new file mode 100644
index 0000000..aca50fe
--- /dev/null
+++ b/fs/f2fs/xattr.c
@@ -0,0 +1,389 @@
+/**
+ * fs/f2fs/xattr.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Portions of this code from linux/fs/ext2/xattr.c
+ *
+ * Copyright (C) 2001-2003 Andreas Gruenbacher <agruen@suse.de>
+ *
+ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
+ * Extended attributes for symlinks and special files added per
+ *  suggestion of Luka Renko <luka.renko@hermes.si>.
+ * xattr consolidation Copyright (c) 2004 James Morris <jmorris@redhat.com>,
+ *  Red Hat 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/rwsem.h>
+#include <linux/f2fs_fs.h>
+#include "f2fs.h"
+#include "xattr.h"
+
+static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
+		size_t list_size, const char *name, size_t name_len, int type)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+	int total_len, prefix_len = 0;
+	const char *prefix = NULL;
+
+	switch (type) {
+	case F2FS_XATTR_INDEX_USER:
+		if (!test_opt(sbi, XATTR_USER))
+			return -EOPNOTSUPP;
+		prefix = XATTR_USER_PREFIX;
+		prefix_len = XATTR_USER_PREFIX_LEN;
+		break;
+	case F2FS_XATTR_INDEX_TRUSTED:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		prefix = XATTR_TRUSTED_PREFIX;
+		prefix_len = XATTR_TRUSTED_PREFIX_LEN;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	total_len = prefix_len + name_len + 1;
+	if (list && total_len <= list_size) {
+		memcpy(list, prefix, prefix_len);
+		memcpy(list+prefix_len, name, name_len);
+		list[prefix_len + name_len] = '\0';
+	}
+	return total_len;
+}
+
+static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
+		void *buffer, size_t size, int type)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+
+	switch (type) {
+	case F2FS_XATTR_INDEX_USER:
+		if (!test_opt(sbi, XATTR_USER))
+			return -EOPNOTSUPP;
+		break;
+	case F2FS_XATTR_INDEX_TRUSTED:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return f2fs_getxattr(dentry->d_inode, type, name,
+			buffer, size);
+}
+
+static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+
+	switch (type) {
+	case F2FS_XATTR_INDEX_USER:
+		if (!test_opt(sbi, XATTR_USER))
+			return -EOPNOTSUPP;
+		break;
+	case F2FS_XATTR_INDEX_TRUSTED:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+
+	return f2fs_setxattr(dentry->d_inode, type, name, value, size);
+}
+
+const struct xattr_handler f2fs_xattr_user_handler = {
+	.prefix	= XATTR_USER_PREFIX,
+	.flags	= F2FS_XATTR_INDEX_USER,
+	.list	= f2fs_xattr_generic_list,
+	.get	= f2fs_xattr_generic_get,
+	.set	= f2fs_xattr_generic_set,
+};
+
+const struct xattr_handler f2fs_xattr_trusted_handler = {
+	.prefix	= XATTR_TRUSTED_PREFIX,
+	.flags	= F2FS_XATTR_INDEX_TRUSTED,
+	.list	= f2fs_xattr_generic_list,
+	.get	= f2fs_xattr_generic_get,
+	.set	= f2fs_xattr_generic_set,
+};
+
+static const struct xattr_handler *f2fs_xattr_handler_map[] = {
+	[F2FS_XATTR_INDEX_USER] = &f2fs_xattr_user_handler,
+#ifdef CONFIG_F2FS_FS_POSIX_ACL
+	[F2FS_XATTR_INDEX_POSIX_ACL_ACCESS] = &f2fs_xattr_acl_access_handler,
+	[F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &f2fs_xattr_acl_default_handler,
+#endif
+	[F2FS_XATTR_INDEX_TRUSTED] = &f2fs_xattr_trusted_handler,
+	[F2FS_XATTR_INDEX_ADVISE] = &f2fs_xattr_advise_handler,
+};
+
+const struct xattr_handler *f2fs_xattr_handlers[] = {
+	&f2fs_xattr_user_handler,
+#ifdef CONFIG_F2FS_FS_POSIX_ACL
+	&f2fs_xattr_acl_access_handler,
+	&f2fs_xattr_acl_default_handler,
+#endif
+	&f2fs_xattr_trusted_handler,
+	&f2fs_xattr_advise_handler,
+	NULL,
+};
+
+static inline const struct xattr_handler *f2fs_xattr_handler(int name_index)
+{
+	const struct xattr_handler *handler = NULL;
+
+	if (name_index > 0 && name_index < ARRAY_SIZE(f2fs_xattr_handler_map))
+		handler = f2fs_xattr_handler_map[name_index];
+	return handler;
+}
+
+int f2fs_getxattr(struct inode *inode, int name_index, const char *name,
+		void *buffer, size_t buffer_size)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct f2fs_inode_info *fi = F2FS_I(inode);
+	struct f2fs_xattr_entry *entry;
+	struct page *page;
+	void *base_addr;
+	int error = 0, found = 0;
+	int value_len, name_len;
+
+	if (name == NULL)
+		return -EINVAL;
+	name_len = strlen(name);
+
+	if (!fi->i_xattr_nid)
+		return -ENODATA;
+
+	page = get_node_page(sbi, fi->i_xattr_nid);
+	base_addr = page_address(page);
+
+	list_for_each_xattr(entry, base_addr) {
+		if (entry->e_name_index != name_index)
+			continue;
+		if (entry->e_name_len != name_len)
+			continue;
+		if (!memcmp(entry->e_name, name, name_len)) {
+			found = 1;
+			break;
+		}
+	}
+	if (!found) {
+		error = -ENODATA;
+		goto cleanup;
+	}
+
+	value_len = le16_to_cpu(entry->e_value_size);
+
+	if (buffer && value_len > buffer_size) {
+		error = -ERANGE;
+		goto cleanup;
+	}
+
+	if (buffer) {
+		char *pval = entry->e_name + entry->e_name_len;
+		memcpy(buffer, pval, value_len);
+	}
+	error = value_len;
+
+cleanup:
+	f2fs_put_page(page, 1);
+	return error;
+}
+
+ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
+{
+	struct inode *inode = dentry->d_inode;
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct f2fs_inode_info *fi = F2FS_I(inode);
+	struct f2fs_xattr_entry *entry;
+	struct page *page;
+	void *base_addr;
+	int error = 0;
+	size_t rest = buffer_size;
+
+	if (!fi->i_xattr_nid)
+		return 0;
+
+	page = get_node_page(sbi, fi->i_xattr_nid);
+	base_addr = page_address(page);
+
+	list_for_each_xattr(entry, base_addr) {
+		const struct xattr_handler *handler =
+			f2fs_xattr_handler(entry->e_name_index);
+		size_t size;
+
+		if (!handler)
+			continue;
+
+		size = handler->list(dentry, buffer, rest, entry->e_name,
+				entry->e_name_len, handler->flags);
+		if (buffer && size > rest) {
+			error = -ERANGE;
+			goto cleanup;
+		}
+
+		if (buffer)
+			buffer += size;
+		rest -= size;
+	}
+	error = buffer_size - rest;
+cleanup:
+	f2fs_put_page(page, 1);
+	return error;
+}
+
+int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
+					const void *value, size_t value_len)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	struct f2fs_inode_info *fi = F2FS_I(inode);
+	struct f2fs_xattr_header *header = NULL;
+	struct f2fs_xattr_entry *here, *last;
+	struct page *page;
+	void *base_addr;
+	int error, found, free, name_len, newsize;
+	char *pval;
+
+	if (name == NULL)
+		return -EINVAL;
+	name_len = strlen(name);
+
+	if (value == NULL)
+		value_len = 0;
+
+	if (name_len > 255 || value_len > MAX_VALUE_LEN)
+		return -ERANGE;
+
+	mutex_lock_op(sbi, NODE_NEW);
+	if (!fi->i_xattr_nid) {
+		/* Allocate new attribute block */
+		struct dnode_of_data dn;
+
+		if (!alloc_nid(sbi, &fi->i_xattr_nid)) {
+			mutex_unlock_op(sbi, NODE_NEW);
+			return -ENOSPC;
+		}
+		set_new_dnode(&dn, inode, NULL, NULL, fi->i_xattr_nid);
+		mark_inode_dirty(inode);
+
+		page = new_node_page(&dn, XATTR_NODE_OFFSET);
+		if (IS_ERR(page)) {
+			alloc_nid_failed(sbi, fi->i_xattr_nid);
+			fi->i_xattr_nid = 0;
+			mutex_unlock_op(sbi, NODE_NEW);
+			return PTR_ERR(page);
+		}
+
+		alloc_nid_done(sbi, fi->i_xattr_nid);
+		base_addr = page_address(page);
+		header = XATTR_HDR(base_addr);
+		header->h_magic = cpu_to_le32(F2FS_XATTR_MAGIC);
+		header->h_refcount = cpu_to_le32(1);
+	} else {
+		/* The inode already has an extended attribute block. */
+		page = get_node_page(sbi, fi->i_xattr_nid);
+		if (IS_ERR(page)) {
+			mutex_unlock_op(sbi, NODE_NEW);
+			return PTR_ERR(page);
+		}
+
+		base_addr = page_address(page);
+		header = XATTR_HDR(base_addr);
+	}
+
+	if (le32_to_cpu(header->h_magic) != F2FS_XATTR_MAGIC) {
+		error = -EIO;
+		goto cleanup;
+	}
+
+	/* find entry with wanted name. */
+	found = 0;
+	list_for_each_xattr(here, base_addr) {
+		if (here->e_name_index != name_index)
+			continue;
+		if (here->e_name_len != name_len)
+			continue;
+		if (!memcmp(here->e_name, name, name_len)) {
+			found = 1;
+			break;
+		}
+	}
+
+	last = here;
+
+	while (!IS_XATTR_LAST_ENTRY(last))
+		last = XATTR_NEXT_ENTRY(last);
+
+	newsize = XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) +
+			name_len + value_len);
+
+	/* 1. Check space */
+	if (value) {
+		/* If value is NULL, it is remove operation.
+		 * In case of update operation, we caculate free.
+		 */
+		free = MIN_OFFSET - ((char *)last - (char *)header);
+		if (found)
+			free = free - ENTRY_SIZE(here);
+
+		if (free < newsize) {
+			error = -ENOSPC;
+			goto cleanup;
+		}
+	}
+
+	/* 2. Remove old entry */
+	if (found) {
+		/* If entry is found, remove old entry.
+		 * If not found, remove operation is not needed.
+		 */
+		struct f2fs_xattr_entry *next = XATTR_NEXT_ENTRY(here);
+		int oldsize = ENTRY_SIZE(here);
+
+		memmove(here, next, (char *)last - (char *)next);
+		last = (struct f2fs_xattr_entry *)((char *)last - oldsize);
+		memset(last, 0, oldsize);
+	}
+
+	/* 3. Write new entry */
+	if (value) {
+		/* Before we come here, old entry is removed.
+		 * We just write new entry. */
+		memset(last, 0, newsize);
+		last->e_name_index = name_index;
+		last->e_name_len = name_len;
+		memcpy(last->e_name, name, name_len);
+		pval = last->e_name + name_len;
+		memcpy(pval, value, value_len);
+		last->e_value_size = cpu_to_le16(value_len);
+	}
+
+	set_page_dirty(page);
+	f2fs_put_page(page, 1);
+
+	if (is_inode_flag_set(fi, FI_ACL_MODE)) {
+		inode->i_mode = fi->i_acl_mode;
+		inode->i_ctime = CURRENT_TIME;
+		clear_inode_flag(fi, FI_ACL_MODE);
+	}
+	f2fs_write_inode(inode, NULL);
+	mutex_unlock_op(sbi, NODE_NEW);
+
+	return 0;
+cleanup:
+	f2fs_put_page(page, 1);
+	mutex_unlock_op(sbi, NODE_NEW);
+	return error;
+}
diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h
new file mode 100644
index 0000000..29b0a08
--- /dev/null
+++ b/fs/f2fs/xattr.h
@@ -0,0 +1,145 @@
+/**
+ * fs/f2fs/xattr.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Portions of this code from linux/fs/ext2/xattr.h
+ *
+ * On-disk format of extended attributes for the ext2 filesystem.
+ *
+ * (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.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 __F2FS_XATTR_H__
+#define __F2FS_XATTR_H__
+
+#include <linux/init.h>
+#include <linux/xattr.h>
+
+/* Magic value in attribute blocks */
+#define F2FS_XATTR_MAGIC                0xF2F52011
+
+/* Maximum number of references to one attribute block */
+#define F2FS_XATTR_REFCOUNT_MAX         1024
+
+/* Name indexes */
+#define F2FS_SYSTEM_ADVISE_PREFIX		"system.advise"
+#define F2FS_XATTR_INDEX_USER			1
+#define F2FS_XATTR_INDEX_POSIX_ACL_ACCESS	2
+#define F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT	3
+#define F2FS_XATTR_INDEX_TRUSTED		4
+#define F2FS_XATTR_INDEX_LUSTRE			5
+#define F2FS_XATTR_INDEX_SECURITY		6
+#define F2FS_XATTR_INDEX_ADVISE			7
+
+struct f2fs_xattr_header {
+	__le32  h_magic;        /* magic number for identification */
+	__le32  h_refcount;     /* reference count */
+	__u32   h_reserved[4];  /* zero right now */
+};
+
+struct f2fs_xattr_entry {
+	__u8    e_name_index;
+	__u8    e_name_len;
+	__le16  e_value_size;   /* size of attribute value */
+	char    e_name[0];      /* attribute name */
+};
+
+#define XATTR_HDR(ptr)		((struct f2fs_xattr_header *)(ptr))
+#define XATTR_ENTRY(ptr)	((struct f2fs_xattr_entry *)(ptr))
+#define XATTR_FIRST_ENTRY(ptr)	(XATTR_ENTRY(XATTR_HDR(ptr)+1))
+#define XATTR_ROUND		(3)
+
+#define XATTR_ALIGN(size)	((size + XATTR_ROUND) & ~XATTR_ROUND)
+
+#define ENTRY_SIZE(entry) (XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) + \
+			entry->e_name_len + le16_to_cpu(entry->e_value_size)))
+
+#define XATTR_NEXT_ENTRY(entry)	((struct f2fs_xattr_entry *)((char *)(entry) +\
+			ENTRY_SIZE(entry)))
+
+#define IS_XATTR_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
+
+#define list_for_each_xattr(entry, addr) \
+		for (entry = XATTR_FIRST_ENTRY(addr);\
+				!IS_XATTR_LAST_ENTRY(entry);\
+				entry = XATTR_NEXT_ENTRY(entry))
+
+
+#define MIN_OFFSET	XATTR_ALIGN(PAGE_SIZE - \
+			sizeof(struct node_footer) - \
+			sizeof(__u32))
+
+#define MAX_VALUE_LEN	(MIN_OFFSET - sizeof(struct f2fs_xattr_header) - \
+			sizeof(struct f2fs_xattr_entry))
+
+/**
+ * On-disk structure of f2fs_xattr
+ * We use only 1 block for xattr.
+ *
+ * +--------------------+
+ * | f2fs_xattr_header  |
+ * |                    |
+ * +--------------------+
+ * | f2fs_xattr_entry   |
+ * | .e_name_index = 1  |
+ * | .e_name_len = 3    |
+ * | .e_value_size = 14 |
+ * | .e_name = "foo"    |
+ * | "value_of_xattr"   |<- value_offs = e_name + e_name_len
+ * +--------------------+
+ * | f2fs_xattr_entry   |
+ * | .e_name_index = 4  |
+ * | .e_name = "bar"    |
+ * +--------------------+
+ * |                    |
+ * |        Free        |
+ * |                    |
+ * +--------------------+<- MIN_OFFSET
+ * |   node_footer      |
+ * | (nid, ino, offset) |
+ * +--------------------+
+ *
+ **/
+
+#ifdef CONFIG_F2FS_FS_XATTR
+extern const struct xattr_handler f2fs_xattr_user_handler;
+extern const struct xattr_handler f2fs_xattr_trusted_handler;
+extern const struct xattr_handler f2fs_xattr_acl_access_handler;
+extern const struct xattr_handler f2fs_xattr_acl_default_handler;
+extern const struct xattr_handler f2fs_xattr_advise_handler;
+
+extern const struct xattr_handler *f2fs_xattr_handlers[];
+
+extern int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
+		const void *value, size_t value_len);
+extern int f2fs_getxattr(struct inode *inode, int name_index, const char *name,
+		void *buffer, size_t buffer_size);
+extern ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer,
+		size_t buffer_size);
+
+#else
+
+#define f2fs_xattr_handlers	NULL
+static inline int f2fs_setxattr(struct inode *inode, int name_index,
+	const char *name, const void *value, size_t value_len)
+{
+	return -EOPNOTSUPP;
+}
+static inline int f2fs_getxattr(struct inode *inode, int name_index,
+		const char *name, void *buffer, size_t buffer_size)
+{
+	return -EOPNOTSUPP;
+}
+static inline ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer,
+		size_t buffer_size)
+{
+	return -EOPNOTSUPP;
+}
+#endif
+
+#endif /* __F2FS_XATTR_H__ */
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index 623f36f..12701a5 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -29,6 +29,7 @@ struct fat_mount_options {
 	unsigned short fs_fmask;
 	unsigned short fs_dmask;
 	unsigned short codepage;   /* Codepage for shortname conversions */
+	int time_offset;	   /* Offset of timestamps from UTC (in minutes) */
 	char *iocharset;           /* Charset used for filename input/display */
 	unsigned short shortname;  /* flags for shortname display/create rule */
 	unsigned char name_check;  /* r = relaxed, n = normal, s = strict */
@@ -45,7 +46,7 @@ struct fat_mount_options {
 		 flush:1,	   /* write things quickly */
 		 nocase:1,	   /* Does this need case conversion? 0=need case conversion*/
 		 usefree:1,	   /* Use free_clusters for FAT32 */
-		 tz_utc:1,	   /* Filesystem timestamps are in UTC */
+		 tz_set:1,	   /* Filesystem timestamps' offset set */
 		 rodir:1,	   /* allow ATTR_RO for directory */
 		 discard:1,	   /* Issue discard requests on deletions */
 		 nfs:1;		   /* Do extra work needed for NFS export */
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 5bafaad..3580681 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -26,6 +26,7 @@
 #include <linux/writeback.h>
 #include <linux/log2.h>
 #include <linux/hash.h>
+#include <linux/blkdev.h>
 #include <asm/unaligned.h>
 #include "fat.h"
 
@@ -725,7 +726,8 @@ static int fat_show_options(struct seq_file *m, struct dentry *root)
 	if (opts->allow_utime)
 		seq_printf(m, ",allow_utime=%04o", opts->allow_utime);
 	if (sbi->nls_disk)
-		seq_printf(m, ",codepage=%s", sbi->nls_disk->charset);
+		/* strip "cp" prefix from displayed option */
+		seq_printf(m, ",codepage=%s", &sbi->nls_disk->charset[2]);
 	if (isvfat) {
 		if (sbi->nls_io)
 			seq_printf(m, ",iocharset=%s", sbi->nls_io->charset);
@@ -777,8 +779,12 @@ static int fat_show_options(struct seq_file *m, struct dentry *root)
 	}
 	if (opts->flush)
 		seq_puts(m, ",flush");
-	if (opts->tz_utc)
-		seq_puts(m, ",tz=UTC");
+	if (opts->tz_set) {
+		if (opts->time_offset)
+			seq_printf(m, ",time_offset=%d", opts->time_offset);
+		else
+			seq_puts(m, ",tz=UTC");
+	}
 	if (opts->errors == FAT_ERRORS_CONT)
 		seq_puts(m, ",errors=continue");
 	else if (opts->errors == FAT_ERRORS_PANIC)
@@ -800,7 +806,8 @@ enum {
 	Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
 	Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
 	Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont,
-	Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_err,
+	Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_time_offset,
+	Opt_err,
 };
 
 static const match_table_t fat_tokens = {
@@ -825,6 +832,7 @@ static const match_table_t fat_tokens = {
 	{Opt_immutable, "sys_immutable"},
 	{Opt_flush, "flush"},
 	{Opt_tz_utc, "tz=UTC"},
+	{Opt_time_offset, "time_offset=%d"},
 	{Opt_err_cont, "errors=continue"},
 	{Opt_err_panic, "errors=panic"},
 	{Opt_err_ro, "errors=remount-ro"},
@@ -909,7 +917,7 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat,
 	opts->utf8 = opts->unicode_xlate = 0;
 	opts->numtail = 1;
 	opts->usefree = opts->nocase = 0;
-	opts->tz_utc = 0;
+	opts->tz_set = 0;
 	opts->nfs = 0;
 	opts->errors = FAT_ERRORS_RO;
 	*debug = 0;
@@ -965,48 +973,57 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat,
 			break;
 		case Opt_uid:
 			if (match_int(&args[0], &option))
-				return 0;
+				return -EINVAL;
 			opts->fs_uid = make_kuid(current_user_ns(), option);
 			if (!uid_valid(opts->fs_uid))
-				return 0;
+				return -EINVAL;
 			break;
 		case Opt_gid:
 			if (match_int(&args[0], &option))
-				return 0;
+				return -EINVAL;
 			opts->fs_gid = make_kgid(current_user_ns(), option);
 			if (!gid_valid(opts->fs_gid))
-				return 0;
+				return -EINVAL;
 			break;
 		case Opt_umask:
 			if (match_octal(&args[0], &option))
-				return 0;
+				return -EINVAL;
 			opts->fs_fmask = opts->fs_dmask = option;
 			break;
 		case Opt_dmask:
 			if (match_octal(&args[0], &option))
-				return 0;
+				return -EINVAL;
 			opts->fs_dmask = option;
 			break;
 		case Opt_fmask:
 			if (match_octal(&args[0], &option))
-				return 0;
+				return -EINVAL;
 			opts->fs_fmask = option;
 			break;
 		case Opt_allow_utime:
 			if (match_octal(&args[0], &option))
-				return 0;
+				return -EINVAL;
 			opts->allow_utime = option & (S_IWGRP | S_IWOTH);
 			break;
 		case Opt_codepage:
 			if (match_int(&args[0], &option))
-				return 0;
+				return -EINVAL;
 			opts->codepage = option;
 			break;
 		case Opt_flush:
 			opts->flush = 1;
 			break;
+		case Opt_time_offset:
+			if (match_int(&args[0], &option))
+				return -EINVAL;
+			if (option < -12 * 60 || option > 12 * 60)
+				return -EINVAL;
+			opts->tz_set = 1;
+			opts->time_offset = option;
+			break;
 		case Opt_tz_utc:
-			opts->tz_utc = 1;
+			opts->tz_set = 1;
+			opts->time_offset = 0;
 			break;
 		case Opt_err_cont:
 			opts->errors = FAT_ERRORS_CONT;
@@ -1431,6 +1448,14 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
 		goto out_fail;
 	}
 
+	if (sbi->options.discard) {
+		struct request_queue *q = bdev_get_queue(sb->s_bdev);
+		if (!blk_queue_discard(q))
+			fat_msg(sb, KERN_WARNING,
+					"mounting with \"discard\" option, but "
+					"the device does not support discard");
+	}
+
 	return 0;
 
 out_invalid:
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 6d93360..5eb600d 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -212,8 +212,10 @@ void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts,
 		   + days_in_year[month] + day
 		   + DAYS_DELTA) * SECS_PER_DAY;
 
-	if (!sbi->options.tz_utc)
+	if (!sbi->options.tz_set)
 		second += sys_tz.tz_minuteswest * SECS_PER_MIN;
+	else
+		second -= sbi->options.time_offset * SECS_PER_MIN;
 
 	if (time_cs) {
 		ts->tv_sec = second + (time_cs / 100);
@@ -229,8 +231,9 @@ void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts,
 		       __le16 *time, __le16 *date, u8 *time_cs)
 {
 	struct tm tm;
-	time_to_tm(ts->tv_sec, sbi->options.tz_utc ? 0 :
-		   -sys_tz.tz_minuteswest * 60, &tm);
+	time_to_tm(ts->tv_sec,
+		   (sbi->options.tz_set ? sbi->options.time_offset :
+		   -sys_tz.tz_minuteswest) * SECS_PER_MIN, &tm);
 
 	/*  FAT can only support year between 1980 to 2107 */
 	if (tm.tm_year < 1980 - 1900) {
diff --git a/fs/fhandle.c b/fs/fhandle.c
index f775bfd..999ff5c 100644
--- a/fs/fhandle.c
+++ b/fs/fhandle.c
@@ -22,7 +22,7 @@ static long do_sys_name_to_handle(struct path *path,
 	struct file_handle *handle = NULL;
 
 	/*
-	 * We need t make sure wether the file system
+	 * We need to make sure whether the file system
 	 * support decoding of the file handle
 	 */
 	if (!path->dentry->d_sb->s_export_op ||
@@ -40,7 +40,7 @@ static long do_sys_name_to_handle(struct path *path,
 	if (!handle)
 		return -ENOMEM;
 
-	/* convert handle size to  multiple of sizeof(u32) */
+	/* convert handle size to multiple of sizeof(u32) */
 	handle_dwords = f_handle.handle_bytes >> 2;
 
 	/* we ask for a non connected handle */
@@ -52,7 +52,7 @@ static long do_sys_name_to_handle(struct path *path,
 	handle_bytes = handle_dwords * sizeof(u32);
 	handle->handle_bytes = handle_bytes;
 	if ((handle->handle_bytes > f_handle.handle_bytes) ||
-	    (retval == 255) || (retval == -ENOSPC)) {
+	    (retval == FILEID_INVALID) || (retval == -ENOSPC)) {
 		/* As per old exportfs_encode_fh documentation
 		 * we could return ENOSPC to indicate overflow
 		 * But file system returned 255 always. So handle
diff --git a/fs/file.c b/fs/file.c
index 7cb71b9..7272a1c 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -519,12 +519,6 @@ struct files_struct init_files = {
 	.file_lock	= __SPIN_LOCK_UNLOCKED(init_task.file_lock),
 };
 
-void daemonize_descriptors(void)
-{
-	atomic_inc(&init_files.count);
-	reset_files_struct(&init_files);
-}
-
 /*
  * allocate a file descriptor, mark it busy.
  */
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 51ea267..310972b 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -228,6 +228,8 @@ static void requeue_io(struct inode *inode, struct bdi_writeback *wb)
 static void inode_sync_complete(struct inode *inode)
 {
 	inode->i_state &= ~I_SYNC;
+	/* If inode is clean an unused, put it into LRU now... */
+	inode_add_lru(inode);
 	/* Waiters must see I_SYNC cleared before being woken up */
 	smp_mb();
 	wake_up_bit(&inode->i_state, __I_SYNC);
@@ -1032,7 +1034,7 @@ int bdi_writeback_thread(void *data)
 	while (!kthread_freezable_should_stop(NULL)) {
 		/*
 		 * Remove own delayed wake-up timer, since we are already awake
-		 * and we'll take care of the preriodic write-back.
+		 * and we'll take care of the periodic write-back.
 		 */
 		del_timer(&wb->wakeup_timer);
 
diff --git a/fs/fs_struct.c b/fs/fs_struct.c
index 5df4775..fe6ca58 100644
--- a/fs/fs_struct.c
+++ b/fs/fs_struct.c
@@ -164,27 +164,3 @@ struct fs_struct init_fs = {
 	.seq		= SEQCNT_ZERO,
 	.umask		= 0022,
 };
-
-void daemonize_fs_struct(void)
-{
-	struct fs_struct *fs = current->fs;
-
-	if (fs) {
-		int kill;
-
-		task_lock(current);
-
-		spin_lock(&init_fs.lock);
-		init_fs.users++;
-		spin_unlock(&init_fs.lock);
-
-		spin_lock(&fs->lock);
-		current->fs = &init_fs;
-		kill = !--fs->users;
-		spin_unlock(&fs->lock);
-
-		task_unlock(current);
-		if (kill)
-			free_fs_struct(fs);
-	}
-}
diff --git a/fs/fuse/Kconfig b/fs/fuse/Kconfig
index 0cf160a..1b2f6c2 100644
--- a/fs/fuse/Kconfig
+++ b/fs/fuse/Kconfig
@@ -4,12 +4,24 @@ config FUSE_FS
 	  With FUSE it is possible to implement a fully functional filesystem
 	  in a userspace program.
 
-	  There's also companion library: libfuse.  This library along with
-	  utilities is available from the FUSE homepage:
+	  There's also a companion library: libfuse2.  This library is available
+	  from the FUSE homepage:
 	  <http://fuse.sourceforge.net/>
+	  although chances are your distribution already has that library
+	  installed if you've installed the "fuse" package itself.
 
 	  See <file:Documentation/filesystems/fuse.txt> for more information.
 	  See <file:Documentation/Changes> for needed library/utility version.
 
 	  If you want to develop a userspace FS, or if you want to use
 	  a filesystem based on FUSE, answer Y or M.
+
+config CUSE
+	tristate "Character device in Userspace support"
+	depends on FUSE_FS
+	help
+	  This FUSE extension allows character devices to be
+	  implemented in userspace.
+
+	  If you want to develop or use a userspace character device
+	  based on CUSE, answer Y or M.
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index ee8d550..65ce10a 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -45,7 +45,6 @@
 #include <linux/miscdevice.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/spinlock.h>
 #include <linux/stat.h>
 #include <linux/module.h>
 
@@ -63,7 +62,7 @@ struct cuse_conn {
 	bool			unrestricted_ioctl;
 };
 
-static DEFINE_SPINLOCK(cuse_lock);		/* protects cuse_conntbl */
+static DEFINE_MUTEX(cuse_lock);		/* protects registration */
 static struct list_head cuse_conntbl[CUSE_CONNTBL_LEN];
 static struct class *cuse_class;
 
@@ -92,19 +91,22 @@ static ssize_t cuse_read(struct file *file, char __user *buf, size_t count,
 			 loff_t *ppos)
 {
 	loff_t pos = 0;
+	struct iovec iov = { .iov_base = buf, .iov_len = count };
 
-	return fuse_direct_io(file, buf, count, &pos, 0);
+	return fuse_direct_io(file, &iov, 1, count, &pos, 0);
 }
 
 static ssize_t cuse_write(struct file *file, const char __user *buf,
 			  size_t count, loff_t *ppos)
 {
 	loff_t pos = 0;
+	struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count };
+
 	/*
 	 * No locking or generic_write_checks(), the server is
 	 * responsible for locking and sanity checks.
 	 */
-	return fuse_direct_io(file, buf, count, &pos, 1);
+	return fuse_direct_io(file, &iov, 1, count, &pos, 1);
 }
 
 static int cuse_open(struct inode *inode, struct file *file)
@@ -114,14 +116,14 @@ static int cuse_open(struct inode *inode, struct file *file)
 	int rc;
 
 	/* look up and get the connection */
-	spin_lock(&cuse_lock);
+	mutex_lock(&cuse_lock);
 	list_for_each_entry(pos, cuse_conntbl_head(devt), list)
 		if (pos->dev->devt == devt) {
 			fuse_conn_get(&pos->fc);
 			cc = pos;
 			break;
 		}
-	spin_unlock(&cuse_lock);
+	mutex_unlock(&cuse_lock);
 
 	/* dead? */
 	if (!cc)
@@ -305,14 +307,14 @@ static void cuse_gendev_release(struct device *dev)
  */
 static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
 {
-	struct cuse_conn *cc = fc_to_cc(fc);
+	struct cuse_conn *cc = fc_to_cc(fc), *pos;
 	struct cuse_init_out *arg = req->out.args[0].value;
 	struct page *page = req->pages[0];
 	struct cuse_devinfo devinfo = { };
 	struct device *dev;
 	struct cdev *cdev;
 	dev_t devt;
-	int rc;
+	int rc, i;
 
 	if (req->out.h.error ||
 	    arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) {
@@ -356,15 +358,24 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
 	dev_set_drvdata(dev, cc);
 	dev_set_name(dev, "%s", devinfo.name);
 
+	mutex_lock(&cuse_lock);
+
+	/* make sure the device-name is unique */
+	for (i = 0; i < CUSE_CONNTBL_LEN; ++i) {
+		list_for_each_entry(pos, &cuse_conntbl[i], list)
+			if (!strcmp(dev_name(pos->dev), dev_name(dev)))
+				goto err_unlock;
+	}
+
 	rc = device_add(dev);
 	if (rc)
-		goto err_device;
+		goto err_unlock;
 
 	/* register cdev */
 	rc = -ENOMEM;
 	cdev = cdev_alloc();
 	if (!cdev)
-		goto err_device;
+		goto err_unlock;
 
 	cdev->owner = THIS_MODULE;
 	cdev->ops = &cuse_frontend_fops;
@@ -377,9 +388,8 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
 	cc->cdev = cdev;
 
 	/* make the device available */
-	spin_lock(&cuse_lock);
 	list_add(&cc->list, cuse_conntbl_head(devt));
-	spin_unlock(&cuse_lock);
+	mutex_unlock(&cuse_lock);
 
 	/* announce device availability */
 	dev_set_uevent_suppress(dev, 0);
@@ -391,7 +401,8 @@ out:
 
 err_cdev:
 	cdev_del(cdev);
-err_device:
+err_unlock:
+	mutex_unlock(&cuse_lock);
 	put_device(dev);
 err_region:
 	unregister_chrdev_region(devt, 1);
@@ -411,7 +422,7 @@ static int cuse_send_init(struct cuse_conn *cc)
 
 	BUILD_BUG_ON(CUSE_INIT_INFO_MAX > PAGE_SIZE);
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req(fc, 1);
 	if (IS_ERR(req)) {
 		rc = PTR_ERR(req);
 		goto err;
@@ -441,6 +452,7 @@ static int cuse_send_init(struct cuse_conn *cc)
 	req->out.argvar = 1;
 	req->out.argpages = 1;
 	req->pages[0] = page;
+	req->page_descs[0].length = req->out.args[1].size;
 	req->num_pages = 1;
 	req->end = cuse_process_init_reply;
 	fuse_request_send_background(fc, req);
@@ -520,9 +532,9 @@ static int cuse_channel_release(struct inode *inode, struct file *file)
 	int rc;
 
 	/* remove from the conntbl, no more access from this point on */
-	spin_lock(&cuse_lock);
+	mutex_lock(&cuse_lock);
 	list_del_init(&cc->list);
-	spin_unlock(&cuse_lock);
+	mutex_unlock(&cuse_lock);
 
 	/* remove device */
 	if (cc->dev)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 8c23fa7..cbae09e 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -34,34 +34,67 @@ static struct fuse_conn *fuse_get_conn(struct file *file)
 	return file->private_data;
 }
 
-static void fuse_request_init(struct fuse_req *req)
+static void fuse_request_init(struct fuse_req *req, struct page **pages,
+			      struct fuse_page_desc *page_descs,
+			      unsigned npages)
 {
 	memset(req, 0, sizeof(*req));
+	memset(pages, 0, sizeof(*pages) * npages);
+	memset(page_descs, 0, sizeof(*page_descs) * npages);
 	INIT_LIST_HEAD(&req->list);
 	INIT_LIST_HEAD(&req->intr_entry);
 	init_waitqueue_head(&req->waitq);
 	atomic_set(&req->count, 1);
+	req->pages = pages;
+	req->page_descs = page_descs;
+	req->max_pages = npages;
 }
 
-struct fuse_req *fuse_request_alloc(void)
+static struct fuse_req *__fuse_request_alloc(unsigned npages, gfp_t flags)
 {
-	struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, GFP_KERNEL);
-	if (req)
-		fuse_request_init(req);
+	struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, flags);
+	if (req) {
+		struct page **pages;
+		struct fuse_page_desc *page_descs;
+
+		if (npages <= FUSE_REQ_INLINE_PAGES) {
+			pages = req->inline_pages;
+			page_descs = req->inline_page_descs;
+		} else {
+			pages = kmalloc(sizeof(struct page *) * npages, flags);
+			page_descs = kmalloc(sizeof(struct fuse_page_desc) *
+					     npages, flags);
+		}
+
+		if (!pages || !page_descs) {
+			kfree(pages);
+			kfree(page_descs);
+			kmem_cache_free(fuse_req_cachep, req);
+			return NULL;
+		}
+
+		fuse_request_init(req, pages, page_descs, npages);
+	}
 	return req;
 }
+
+struct fuse_req *fuse_request_alloc(unsigned npages)
+{
+	return __fuse_request_alloc(npages, GFP_KERNEL);
+}
 EXPORT_SYMBOL_GPL(fuse_request_alloc);
 
-struct fuse_req *fuse_request_alloc_nofs(void)
+struct fuse_req *fuse_request_alloc_nofs(unsigned npages)
 {
-	struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, GFP_NOFS);
-	if (req)
-		fuse_request_init(req);
-	return req;
+	return __fuse_request_alloc(npages, GFP_NOFS);
 }
 
 void fuse_request_free(struct fuse_req *req)
 {
+	if (req->pages != req->inline_pages) {
+		kfree(req->pages);
+		kfree(req->page_descs);
+	}
 	kmem_cache_free(fuse_req_cachep, req);
 }
 
@@ -92,12 +125,12 @@ static void __fuse_put_request(struct fuse_req *req)
 
 static void fuse_req_init_context(struct fuse_req *req)
 {
-	req->in.h.uid = current_fsuid();
-	req->in.h.gid = current_fsgid();
+	req->in.h.uid = from_kuid_munged(&init_user_ns, current_fsuid());
+	req->in.h.gid = from_kgid_munged(&init_user_ns, current_fsgid());
 	req->in.h.pid = current->pid;
 }
 
-struct fuse_req *fuse_get_req(struct fuse_conn *fc)
+struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages)
 {
 	struct fuse_req *req;
 	sigset_t oldset;
@@ -116,7 +149,7 @@ struct fuse_req *fuse_get_req(struct fuse_conn *fc)
 	if (!fc->connected)
 		goto out;
 
-	req = fuse_request_alloc();
+	req = fuse_request_alloc(npages);
 	err = -ENOMEM;
 	if (!req)
 		goto out;
@@ -165,7 +198,7 @@ static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req)
 	struct fuse_file *ff = file->private_data;
 
 	spin_lock(&fc->lock);
-	fuse_request_init(req);
+	fuse_request_init(req, req->pages, req->page_descs, req->max_pages);
 	BUG_ON(ff->reserved_req);
 	ff->reserved_req = req;
 	wake_up_all(&fc->reserved_req_waitq);
@@ -186,13 +219,14 @@ static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req)
  * filesystem should not have it's own file open.  If deadlock is
  * intentional, it can still be broken by "aborting" the filesystem.
  */
-struct fuse_req *fuse_get_req_nofail(struct fuse_conn *fc, struct file *file)
+struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc,
+					     struct file *file)
 {
 	struct fuse_req *req;
 
 	atomic_inc(&fc->num_waiting);
 	wait_event(fc->blocked_waitq, !fc->blocked);
-	req = fuse_request_alloc();
+	req = fuse_request_alloc(0);
 	if (!req)
 		req = get_reserved_req(fc, file);
 
@@ -491,6 +525,25 @@ void fuse_request_send_background_locked(struct fuse_conn *fc,
 	fuse_request_send_nowait_locked(fc, req);
 }
 
+void fuse_force_forget(struct file *file, u64 nodeid)
+{
+	struct inode *inode = file->f_path.dentry->d_inode;
+	struct fuse_conn *fc = get_fuse_conn(inode);
+	struct fuse_req *req;
+	struct fuse_forget_in inarg;
+
+	memset(&inarg, 0, sizeof(inarg));
+	inarg.nlookup = 1;
+	req = fuse_get_req_nofail_nopages(fc, file);
+	req->in.h.opcode = FUSE_FORGET;
+	req->in.h.nodeid = nodeid;
+	req->in.numargs = 1;
+	req->in.args[0].size = sizeof(inarg);
+	req->in.args[0].value = &inarg;
+	req->isreply = 0;
+	fuse_request_send_nowait(fc, req);
+}
+
 /*
  * Lock the request.  Up to the next unlock_request() there mustn't be
  * anything that could cause a page-fault.  If the request was already
@@ -692,8 +745,6 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
 	struct page *oldpage = *pagep;
 	struct page *newpage;
 	struct pipe_buffer *buf = cs->pipebufs;
-	struct address_space *mapping;
-	pgoff_t index;
 
 	unlock_request(cs->fc, cs->req);
 	fuse_copy_finish(cs);
@@ -724,9 +775,6 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
 	if (fuse_check_page(newpage) != 0)
 		goto out_fallback_unlock;
 
-	mapping = oldpage->mapping;
-	index = oldpage->index;
-
 	/*
 	 * This is a new and locked page, it shouldn't be mapped or
 	 * have any special flags on it
@@ -855,11 +903,11 @@ static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes,
 {
 	unsigned i;
 	struct fuse_req *req = cs->req;
-	unsigned offset = req->page_offset;
-	unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset);
 
 	for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) {
 		int err;
+		unsigned offset = req->page_descs[i].offset;
+		unsigned count = min(nbytes, req->page_descs[i].length);
 
 		err = fuse_copy_page(cs, &req->pages[i], offset, count,
 				     zeroing);
@@ -867,8 +915,6 @@ static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes,
 			return err;
 
 		nbytes -= count;
-		count = min(nbytes, (unsigned) PAGE_SIZE);
-		offset = 0;
 	}
 	return 0;
 }
@@ -1541,29 +1587,34 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
 	unsigned int num;
 	unsigned int offset;
 	size_t total_len = 0;
+	int num_pages;
+
+	offset = outarg->offset & ~PAGE_CACHE_MASK;
+	file_size = i_size_read(inode);
+
+	num = outarg->size;
+	if (outarg->offset > file_size)
+		num = 0;
+	else if (outarg->offset + num > file_size)
+		num = file_size - outarg->offset;
+
+	num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	num_pages = min(num_pages, FUSE_MAX_PAGES_PER_REQ);
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req(fc, num_pages);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
-	offset = outarg->offset & ~PAGE_CACHE_MASK;
-
 	req->in.h.opcode = FUSE_NOTIFY_REPLY;
 	req->in.h.nodeid = outarg->nodeid;
 	req->in.numargs = 2;
 	req->in.argpages = 1;
-	req->page_offset = offset;
+	req->page_descs[0].offset = offset;
 	req->end = fuse_retrieve_end;
 
 	index = outarg->offset >> PAGE_CACHE_SHIFT;
-	file_size = i_size_read(inode);
-	num = outarg->size;
-	if (outarg->offset > file_size)
-		num = 0;
-	else if (outarg->offset + num > file_size)
-		num = file_size - outarg->offset;
 
-	while (num && req->num_pages < FUSE_MAX_PAGES_PER_REQ) {
+	while (num && req->num_pages < num_pages) {
 		struct page *page;
 		unsigned int this_num;
 
@@ -1573,6 +1624,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
 
 		this_num = min_t(unsigned, num, PAGE_CACHE_SIZE - offset);
 		req->pages[req->num_pages] = page;
+		req->page_descs[req->num_pages].length = this_num;
 		req->num_pages++;
 
 		offset = 0;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 324bc08..ed8f8c5 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -178,7 +178,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
 			return -ECHILD;
 
 		fc = get_fuse_conn(inode);
-		req = fuse_get_req(fc);
+		req = fuse_get_req_nopages(fc);
 		if (IS_ERR(req))
 			return 0;
 
@@ -271,7 +271,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
 	if (name->len > FUSE_NAME_MAX)
 		goto out;
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	err = PTR_ERR(req);
 	if (IS_ERR(req))
 		goto out;
@@ -391,7 +391,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
 	if (!forget)
 		goto out_err;
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	err = PTR_ERR(req);
 	if (IS_ERR(req))
 		goto out_put_forget_req;
@@ -592,7 +592,7 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
 {
 	struct fuse_mknod_in inarg;
 	struct fuse_conn *fc = get_fuse_conn(dir);
-	struct fuse_req *req = fuse_get_req(fc);
+	struct fuse_req *req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -623,7 +623,7 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
 {
 	struct fuse_mkdir_in inarg;
 	struct fuse_conn *fc = get_fuse_conn(dir);
-	struct fuse_req *req = fuse_get_req(fc);
+	struct fuse_req *req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -647,7 +647,7 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
 {
 	struct fuse_conn *fc = get_fuse_conn(dir);
 	unsigned len = strlen(link) + 1;
-	struct fuse_req *req = fuse_get_req(fc);
+	struct fuse_req *req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -664,7 +664,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
 {
 	int err;
 	struct fuse_conn *fc = get_fuse_conn(dir);
-	struct fuse_req *req = fuse_get_req(fc);
+	struct fuse_req *req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -696,7 +696,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
 {
 	int err;
 	struct fuse_conn *fc = get_fuse_conn(dir);
-	struct fuse_req *req = fuse_get_req(fc);
+	struct fuse_req *req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -723,7 +723,7 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent,
 	int err;
 	struct fuse_rename_in inarg;
 	struct fuse_conn *fc = get_fuse_conn(olddir);
-	struct fuse_req *req = fuse_get_req(fc);
+	struct fuse_req *req = fuse_get_req_nopages(fc);
 
 	if (IS_ERR(req))
 		return PTR_ERR(req);
@@ -776,7 +776,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
 	struct fuse_link_in inarg;
 	struct inode *inode = entry->d_inode;
 	struct fuse_conn *fc = get_fuse_conn(inode);
-	struct fuse_req *req = fuse_get_req(fc);
+	struct fuse_req *req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -818,8 +818,8 @@ static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
 	stat->ino = attr->ino;
 	stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
 	stat->nlink = attr->nlink;
-	stat->uid = attr->uid;
-	stat->gid = attr->gid;
+	stat->uid = make_kuid(&init_user_ns, attr->uid);
+	stat->gid = make_kgid(&init_user_ns, attr->gid);
 	stat->rdev = inode->i_rdev;
 	stat->atime.tv_sec = attr->atime;
 	stat->atime.tv_nsec = attr->atimensec;
@@ -848,7 +848,7 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
 	struct fuse_req *req;
 	u64 attr_version;
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -1007,12 +1007,12 @@ int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
 	rcu_read_lock();
 	ret = 0;
 	cred = __task_cred(task);
-	if (cred->euid == fc->user_id &&
-	    cred->suid == fc->user_id &&
-	    cred->uid  == fc->user_id &&
-	    cred->egid == fc->group_id &&
-	    cred->sgid == fc->group_id &&
-	    cred->gid  == fc->group_id)
+	if (uid_eq(cred->euid, fc->user_id) &&
+	    uid_eq(cred->suid, fc->user_id) &&
+	    uid_eq(cred->uid,  fc->user_id) &&
+	    gid_eq(cred->egid, fc->group_id) &&
+	    gid_eq(cred->sgid, fc->group_id) &&
+	    gid_eq(cred->gid,  fc->group_id))
 		ret = 1;
 	rcu_read_unlock();
 
@@ -1029,7 +1029,7 @@ static int fuse_access(struct inode *inode, int mask)
 	if (fc->no_access)
 		return 0;
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -1155,6 +1155,143 @@ static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
 	return 0;
 }
 
+static int fuse_direntplus_link(struct file *file,
+				struct fuse_direntplus *direntplus,
+				u64 attr_version)
+{
+	int err;
+	struct fuse_entry_out *o = &direntplus->entry_out;
+	struct fuse_dirent *dirent = &direntplus->dirent;
+	struct dentry *parent = file->f_path.dentry;
+	struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
+	struct dentry *dentry;
+	struct dentry *alias;
+	struct inode *dir = parent->d_inode;
+	struct fuse_conn *fc;
+	struct inode *inode;
+
+	if (!o->nodeid) {
+		/*
+		 * Unlike in the case of fuse_lookup, zero nodeid does not mean
+		 * ENOENT. Instead, it only means the userspace filesystem did
+		 * not want to return attributes/handle for this entry.
+		 *
+		 * So do nothing.
+		 */
+		return 0;
+	}
+
+	if (name.name[0] == '.') {
+		/*
+		 * We could potentially refresh the attributes of the directory
+		 * and its parent?
+		 */
+		if (name.len == 1)
+			return 0;
+		if (name.name[1] == '.' && name.len == 2)
+			return 0;
+	}
+	fc = get_fuse_conn(dir);
+
+	name.hash = full_name_hash(name.name, name.len);
+	dentry = d_lookup(parent, &name);
+	if (dentry && dentry->d_inode) {
+		inode = dentry->d_inode;
+		if (get_node_id(inode) == o->nodeid) {
+			struct fuse_inode *fi;
+			fi = get_fuse_inode(inode);
+			spin_lock(&fc->lock);
+			fi->nlookup++;
+			spin_unlock(&fc->lock);
+
+			/*
+			 * The other branch to 'found' comes via fuse_iget()
+			 * which bumps nlookup inside
+			 */
+			goto found;
+		}
+		err = d_invalidate(dentry);
+		if (err)
+			goto out;
+		dput(dentry);
+		dentry = NULL;
+	}
+
+	dentry = d_alloc(parent, &name);
+	err = -ENOMEM;
+	if (!dentry)
+		goto out;
+
+	inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
+			  &o->attr, entry_attr_timeout(o), attr_version);
+	if (!inode)
+		goto out;
+
+	alias = d_materialise_unique(dentry, inode);
+	err = PTR_ERR(alias);
+	if (IS_ERR(alias))
+		goto out;
+	if (alias) {
+		dput(dentry);
+		dentry = alias;
+	}
+
+found:
+	fuse_change_attributes(inode, &o->attr, entry_attr_timeout(o),
+			       attr_version);
+
+	fuse_change_entry_timeout(dentry, o);
+
+	err = 0;
+out:
+	if (dentry)
+		dput(dentry);
+	return err;
+}
+
+static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
+			     void *dstbuf, filldir_t filldir, u64 attr_version)
+{
+	struct fuse_direntplus *direntplus;
+	struct fuse_dirent *dirent;
+	size_t reclen;
+	int over = 0;
+	int ret;
+
+	while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
+		direntplus = (struct fuse_direntplus *) buf;
+		dirent = &direntplus->dirent;
+		reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
+
+		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
+			return -EIO;
+		if (reclen > nbytes)
+			break;
+
+		if (!over) {
+			/* We fill entries into dstbuf only as much as
+			   it can hold. But we still continue iterating
+			   over remaining entries to link them. If not,
+			   we need to send a FORGET for each of those
+			   which we did not link.
+			*/
+			over = filldir(dstbuf, dirent->name, dirent->namelen,
+				       file->f_pos, dirent->ino,
+				       dirent->type);
+			file->f_pos = dirent->off;
+		}
+
+		buf += reclen;
+		nbytes -= reclen;
+
+		ret = fuse_direntplus_link(file, direntplus, attr_version);
+		if (ret)
+			fuse_force_forget(file, direntplus->entry_out.nodeid);
+	}
+
+	return 0;
+}
+
 static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
 {
 	int err;
@@ -1163,11 +1300,12 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
 	struct inode *inode = file->f_path.dentry->d_inode;
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	struct fuse_req *req;
+	u64 attr_version = 0;
 
 	if (is_bad_inode(inode))
 		return -EIO;
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req(fc, 1);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -1179,14 +1317,29 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
 	req->out.argpages = 1;
 	req->num_pages = 1;
 	req->pages[0] = page;
-	fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, FUSE_READDIR);
+	req->page_descs[0].length = PAGE_SIZE;
+	if (fc->do_readdirplus) {
+		attr_version = fuse_get_attr_version(fc);
+		fuse_read_fill(req, file, file->f_pos, PAGE_SIZE,
+			       FUSE_READDIRPLUS);
+	} else {
+		fuse_read_fill(req, file, file->f_pos, PAGE_SIZE,
+			       FUSE_READDIR);
+	}
 	fuse_request_send(fc, req);
 	nbytes = req->out.args[0].size;
 	err = req->out.h.error;
 	fuse_put_request(fc, req);
-	if (!err)
-		err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
-				    filldir);
+	if (!err) {
+		if (fc->do_readdirplus) {
+			err = parse_dirplusfile(page_address(page), nbytes,
+						file, dstbuf, filldir,
+						attr_version);
+		} else {
+			err = parse_dirfile(page_address(page), nbytes, file,
+					    dstbuf, filldir);
+		}
+	}
 
 	__free_page(page);
 	fuse_invalidate_attr(inode); /* atime changed */
@@ -1197,7 +1350,7 @@ static char *read_link(struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
 	struct fuse_conn *fc = get_fuse_conn(inode);
-	struct fuse_req *req = fuse_get_req(fc);
+	struct fuse_req *req = fuse_get_req_nopages(fc);
 	char *link;
 
 	if (IS_ERR(req))
@@ -1306,9 +1459,9 @@ static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
 	if (ivalid & ATTR_MODE)
 		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;
 	if (ivalid & ATTR_UID)
-		arg->valid |= FATTR_UID,    arg->uid = iattr->ia_uid;
+		arg->valid |= FATTR_UID,    arg->uid = from_kuid(&init_user_ns, iattr->ia_uid);
 	if (ivalid & ATTR_GID)
-		arg->valid |= FATTR_GID,    arg->gid = iattr->ia_gid;
+		arg->valid |= FATTR_GID,    arg->gid = from_kgid(&init_user_ns, iattr->ia_gid);
 	if (ivalid & ATTR_SIZE)
 		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;
 	if (ivalid & ATTR_ATIME) {
@@ -1410,7 +1563,7 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
 	if (attr->ia_valid & ATTR_SIZE)
 		is_truncate = true;
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -1518,7 +1671,7 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
 	if (fc->no_setxattr)
 		return -EOPNOTSUPP;
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -1557,7 +1710,7 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
 	if (fc->no_getxattr)
 		return -EOPNOTSUPP;
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -1609,7 +1762,7 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
 	if (fc->no_listxattr)
 		return -EOPNOTSUPP;
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -1654,7 +1807,7 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
 	if (fc->no_removexattr)
 		return -EOPNOTSUPP;
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 78d2837..19b50e7 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -25,7 +25,7 @@ static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
 	struct fuse_req *req;
 	int err;
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -57,7 +57,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
 		return NULL;
 
 	ff->fc = fc;
-	ff->reserved_req = fuse_request_alloc();
+	ff->reserved_req = fuse_request_alloc(0);
 	if (unlikely(!ff->reserved_req)) {
 		kfree(ff);
 		return NULL;
@@ -368,7 +368,7 @@ static int fuse_flush(struct file *file, fl_owner_t id)
 	if (fc->no_flush)
 		return 0;
 
-	req = fuse_get_req_nofail(fc, file);
+	req = fuse_get_req_nofail_nopages(fc, file);
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.fh = ff->fh;
 	inarg.lock_owner = fuse_lock_owner_id(fc, id);
@@ -436,7 +436,7 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
 
 	fuse_sync_writes(inode);
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req)) {
 		err = PTR_ERR(req);
 		goto out;
@@ -544,7 +544,7 @@ static int fuse_readpage(struct file *file, struct page *page)
 	 */
 	fuse_wait_on_page_writeback(inode, page->index);
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req(fc, 1);
 	err = PTR_ERR(req);
 	if (IS_ERR(req))
 		goto out;
@@ -555,6 +555,7 @@ static int fuse_readpage(struct file *file, struct page *page)
 	req->out.argpages = 1;
 	req->num_pages = 1;
 	req->pages[0] = page;
+	req->page_descs[0].length = count;
 	num_read = fuse_send_read(req, file, pos, count, NULL);
 	err = req->out.h.error;
 	fuse_put_request(fc, req);
@@ -641,6 +642,7 @@ struct fuse_fill_data {
 	struct fuse_req *req;
 	struct file *file;
 	struct inode *inode;
+	unsigned nr_pages;
 };
 
 static int fuse_readpages_fill(void *_data, struct page *page)
@@ -656,16 +658,26 @@ static int fuse_readpages_fill(void *_data, struct page *page)
 	    (req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
 	     (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
 	     req->pages[req->num_pages - 1]->index + 1 != page->index)) {
+		int nr_alloc = min_t(unsigned, data->nr_pages,
+				     FUSE_MAX_PAGES_PER_REQ);
 		fuse_send_readpages(req, data->file);
-		data->req = req = fuse_get_req(fc);
+		data->req = req = fuse_get_req(fc, nr_alloc);
 		if (IS_ERR(req)) {
 			unlock_page(page);
 			return PTR_ERR(req);
 		}
 	}
+
+	if (WARN_ON(req->num_pages >= req->max_pages)) {
+		fuse_put_request(fc, req);
+		return -EIO;
+	}
+
 	page_cache_get(page);
 	req->pages[req->num_pages] = page;
+	req->page_descs[req->num_pages].length = PAGE_SIZE;
 	req->num_pages++;
+	data->nr_pages--;
 	return 0;
 }
 
@@ -676,6 +688,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	struct fuse_fill_data data;
 	int err;
+	int nr_alloc = min_t(unsigned, nr_pages, FUSE_MAX_PAGES_PER_REQ);
 
 	err = -EIO;
 	if (is_bad_inode(inode))
@@ -683,7 +696,8 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
 
 	data.file = file;
 	data.inode = inode;
-	data.req = fuse_get_req(fc);
+	data.req = fuse_get_req(fc, nr_alloc);
+	data.nr_pages = nr_pages;
 	err = PTR_ERR(data.req);
 	if (IS_ERR(data.req))
 		goto out;
@@ -786,7 +800,7 @@ static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file,
 
 	res = fuse_send_write(req, file, pos, count, NULL);
 
-	offset = req->page_offset;
+	offset = req->page_descs[0].offset;
 	count = res;
 	for (i = 0; i < req->num_pages; i++) {
 		struct page *page = req->pages[i];
@@ -817,7 +831,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
 	int err;
 
 	req->in.argpages = 1;
-	req->page_offset = offset;
+	req->page_descs[0].offset = offset;
 
 	do {
 		size_t tmp;
@@ -857,6 +871,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
 
 		err = 0;
 		req->pages[req->num_pages] = page;
+		req->page_descs[req->num_pages].length = tmp;
 		req->num_pages++;
 
 		iov_iter_advance(ii, tmp);
@@ -869,11 +884,19 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
 		if (!fc->big_writes)
 			break;
 	} while (iov_iter_count(ii) && count < fc->max_write &&
-		 req->num_pages < FUSE_MAX_PAGES_PER_REQ && offset == 0);
+		 req->num_pages < req->max_pages && offset == 0);
 
 	return count > 0 ? count : err;
 }
 
+static inline unsigned fuse_wr_pages(loff_t pos, size_t len)
+{
+	return min_t(unsigned,
+		     ((pos + len - 1) >> PAGE_CACHE_SHIFT) -
+		     (pos >> PAGE_CACHE_SHIFT) + 1,
+		     FUSE_MAX_PAGES_PER_REQ);
+}
+
 static ssize_t fuse_perform_write(struct file *file,
 				  struct address_space *mapping,
 				  struct iov_iter *ii, loff_t pos)
@@ -889,8 +912,9 @@ static ssize_t fuse_perform_write(struct file *file,
 	do {
 		struct fuse_req *req;
 		ssize_t count;
+		unsigned nr_pages = fuse_wr_pages(pos, iov_iter_count(ii));
 
-		req = fuse_get_req(fc);
+		req = fuse_get_req(fc, nr_pages);
 		if (IS_ERR(req)) {
 			err = PTR_ERR(req);
 			break;
@@ -1023,47 +1047,110 @@ static void fuse_release_user_pages(struct fuse_req *req, int write)
 	}
 }
 
-static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
+static inline void fuse_page_descs_length_init(struct fuse_req *req,
+		unsigned index, unsigned nr_pages)
+{
+	int i;
+
+	for (i = index; i < index + nr_pages; i++)
+		req->page_descs[i].length = PAGE_SIZE -
+			req->page_descs[i].offset;
+}
+
+static inline unsigned long fuse_get_user_addr(const struct iov_iter *ii)
+{
+	return (unsigned long)ii->iov->iov_base + ii->iov_offset;
+}
+
+static inline size_t fuse_get_frag_size(const struct iov_iter *ii,
+					size_t max_size)
+{
+	return min(iov_iter_single_seg_count(ii), max_size);
+}
+
+static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii,
 			       size_t *nbytesp, int write)
 {
-	size_t nbytes = *nbytesp;
-	unsigned long user_addr = (unsigned long) buf;
-	unsigned offset = user_addr & ~PAGE_MASK;
-	int npages;
+	size_t nbytes = 0;  /* # bytes already packed in req */
 
 	/* Special case for kernel I/O: can copy directly into the buffer */
 	if (segment_eq(get_fs(), KERNEL_DS)) {
+		unsigned long user_addr = fuse_get_user_addr(ii);
+		size_t frag_size = fuse_get_frag_size(ii, *nbytesp);
+
 		if (write)
 			req->in.args[1].value = (void *) user_addr;
 		else
 			req->out.args[0].value = (void *) user_addr;
 
+		iov_iter_advance(ii, frag_size);
+		*nbytesp = frag_size;
 		return 0;
 	}
 
-	nbytes = min_t(size_t, nbytes, FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT);
-	npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	npages = clamp(npages, 1, FUSE_MAX_PAGES_PER_REQ);
-	npages = get_user_pages_fast(user_addr, npages, !write, req->pages);
-	if (npages < 0)
-		return npages;
+	while (nbytes < *nbytesp && req->num_pages < req->max_pages) {
+		unsigned npages;
+		unsigned long user_addr = fuse_get_user_addr(ii);
+		unsigned offset = user_addr & ~PAGE_MASK;
+		size_t frag_size = fuse_get_frag_size(ii, *nbytesp - nbytes);
+		int ret;
+
+		unsigned n = req->max_pages - req->num_pages;
+		frag_size = min_t(size_t, frag_size, n << PAGE_SHIFT);
+
+		npages = (frag_size + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+		npages = clamp(npages, 1U, n);
+
+		ret = get_user_pages_fast(user_addr, npages, !write,
+					  &req->pages[req->num_pages]);
+		if (ret < 0)
+			return ret;
 
-	req->num_pages = npages;
-	req->page_offset = offset;
+		npages = ret;
+		frag_size = min_t(size_t, frag_size,
+				  (npages << PAGE_SHIFT) - offset);
+		iov_iter_advance(ii, frag_size);
+
+		req->page_descs[req->num_pages].offset = offset;
+		fuse_page_descs_length_init(req, req->num_pages, npages);
+
+		req->num_pages += npages;
+		req->page_descs[req->num_pages - 1].length -=
+			(npages << PAGE_SHIFT) - offset - frag_size;
+
+		nbytes += frag_size;
+	}
 
 	if (write)
 		req->in.argpages = 1;
 	else
 		req->out.argpages = 1;
 
-	nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset;
-	*nbytesp = min(*nbytesp, nbytes);
+	*nbytesp = nbytes;
 
 	return 0;
 }
 
-ssize_t fuse_direct_io(struct file *file, const char __user *buf,
-		       size_t count, loff_t *ppos, int write)
+static inline int fuse_iter_npages(const struct iov_iter *ii_p)
+{
+	struct iov_iter ii = *ii_p;
+	int npages = 0;
+
+	while (iov_iter_count(&ii) && npages < FUSE_MAX_PAGES_PER_REQ) {
+		unsigned long user_addr = fuse_get_user_addr(&ii);
+		unsigned offset = user_addr & ~PAGE_MASK;
+		size_t frag_size = iov_iter_single_seg_count(&ii);
+
+		npages += (frag_size + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+		iov_iter_advance(&ii, frag_size);
+	}
+
+	return min(npages, FUSE_MAX_PAGES_PER_REQ);
+}
+
+ssize_t fuse_direct_io(struct file *file, const struct iovec *iov,
+		       unsigned long nr_segs, size_t count, loff_t *ppos,
+		       int write)
 {
 	struct fuse_file *ff = file->private_data;
 	struct fuse_conn *fc = ff->fc;
@@ -1071,8 +1158,11 @@ ssize_t fuse_direct_io(struct file *file, const char __user *buf,
 	loff_t pos = *ppos;
 	ssize_t res = 0;
 	struct fuse_req *req;
+	struct iov_iter ii;
+
+	iov_iter_init(&ii, iov, nr_segs, count, 0);
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req(fc, fuse_iter_npages(&ii));
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -1080,7 +1170,7 @@ ssize_t fuse_direct_io(struct file *file, const char __user *buf,
 		size_t nres;
 		fl_owner_t owner = current->files;
 		size_t nbytes = min(count, nmax);
-		int err = fuse_get_user_pages(req, buf, &nbytes, write);
+		int err = fuse_get_user_pages(req, &ii, &nbytes, write);
 		if (err) {
 			res = err;
 			break;
@@ -1103,12 +1193,11 @@ ssize_t fuse_direct_io(struct file *file, const char __user *buf,
 		count -= nres;
 		res += nres;
 		pos += nres;
-		buf += nres;
 		if (nres != nbytes)
 			break;
 		if (count) {
 			fuse_put_request(fc, req);
-			req = fuse_get_req(fc);
+			req = fuse_get_req(fc, fuse_iter_npages(&ii));
 			if (IS_ERR(req))
 				break;
 		}
@@ -1122,8 +1211,8 @@ ssize_t fuse_direct_io(struct file *file, const char __user *buf,
 }
 EXPORT_SYMBOL_GPL(fuse_direct_io);
 
-static ssize_t fuse_direct_read(struct file *file, char __user *buf,
-				     size_t count, loff_t *ppos)
+static ssize_t __fuse_direct_read(struct file *file, const struct iovec *iov,
+				  unsigned long nr_segs, loff_t *ppos)
 {
 	ssize_t res;
 	struct inode *inode = file->f_path.dentry->d_inode;
@@ -1131,22 +1220,31 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf,
 	if (is_bad_inode(inode))
 		return -EIO;
 
-	res = fuse_direct_io(file, buf, count, ppos, 0);
+	res = fuse_direct_io(file, iov, nr_segs, iov_length(iov, nr_segs),
+			     ppos, 0);
 
 	fuse_invalidate_attr(inode);
 
 	return res;
 }
 
-static ssize_t __fuse_direct_write(struct file *file, const char __user *buf,
-				   size_t count, loff_t *ppos)
+static ssize_t fuse_direct_read(struct file *file, char __user *buf,
+				     size_t count, loff_t *ppos)
+{
+	struct iovec iov = { .iov_base = buf, .iov_len = count };
+	return __fuse_direct_read(file, &iov, 1, ppos);
+}
+
+static ssize_t __fuse_direct_write(struct file *file, const struct iovec *iov,
+				   unsigned long nr_segs, loff_t *ppos)
 {
 	struct inode *inode = file->f_path.dentry->d_inode;
+	size_t count = iov_length(iov, nr_segs);
 	ssize_t res;
 
 	res = generic_write_checks(file, ppos, &count, 0);
 	if (!res) {
-		res = fuse_direct_io(file, buf, count, ppos, 1);
+		res = fuse_direct_io(file, iov, nr_segs, count, ppos, 1);
 		if (res > 0)
 			fuse_write_update_size(inode, *ppos);
 	}
@@ -1159,6 +1257,7 @@ static ssize_t __fuse_direct_write(struct file *file, const char __user *buf,
 static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
 				 size_t count, loff_t *ppos)
 {
+	struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count };
 	struct inode *inode = file->f_path.dentry->d_inode;
 	ssize_t res;
 
@@ -1167,7 +1266,7 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
 
 	/* Don't allow parallel writes to the same file */
 	mutex_lock(&inode->i_mutex);
-	res = __fuse_direct_write(file, buf, count, ppos);
+	res = __fuse_direct_write(file, &iov, 1, ppos);
 	mutex_unlock(&inode->i_mutex);
 
 	return res;
@@ -1272,7 +1371,7 @@ static int fuse_writepage_locked(struct page *page)
 
 	set_page_writeback(page);
 
-	req = fuse_request_alloc_nofs();
+	req = fuse_request_alloc_nofs(1);
 	if (!req)
 		goto err;
 
@@ -1293,7 +1392,8 @@ static int fuse_writepage_locked(struct page *page)
 	req->in.argpages = 1;
 	req->num_pages = 1;
 	req->pages[0] = tmp_page;
-	req->page_offset = 0;
+	req->page_descs[0].offset = 0;
+	req->page_descs[0].length = PAGE_SIZE;
 	req->end = fuse_writepage_end;
 	req->inode = inode;
 
@@ -1471,7 +1571,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
 	struct fuse_lk_out outarg;
 	int err;
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -1506,7 +1606,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
 	if (fl->fl_flags & FL_CLOSE)
 		return 0;
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -1575,7 +1675,7 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
 	if (!inode->i_sb->s_bdev || fc->no_bmap)
 		return 0;
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return 0;
 
@@ -1873,7 +1973,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
 		num_pages++;
 	}
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req(fc, num_pages);
 	if (IS_ERR(req)) {
 		err = PTR_ERR(req);
 		req = NULL;
@@ -1881,6 +1981,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
 	}
 	memcpy(req->pages, pages, sizeof(req->pages[0]) * num_pages);
 	req->num_pages = num_pages;
+	fuse_page_descs_length_init(req, 0, req->num_pages);
 
 	/* okay, let's send it to the client */
 	req->in.h.opcode = FUSE_IOCTL;
@@ -2076,7 +2177,7 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait)
 		fuse_register_polled_file(fc, ff);
 	}
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return POLLERR;
 
@@ -2126,41 +2227,6 @@ int fuse_notify_poll_wakeup(struct fuse_conn *fc,
 	return 0;
 }
 
-static ssize_t fuse_loop_dio(struct file *filp, const struct iovec *iov,
-			     unsigned long nr_segs, loff_t *ppos, int rw)
-{
-	const struct iovec *vector = iov;
-	ssize_t ret = 0;
-
-	while (nr_segs > 0) {
-		void __user *base;
-		size_t len;
-		ssize_t nr;
-
-		base = vector->iov_base;
-		len = vector->iov_len;
-		vector++;
-		nr_segs--;
-
-		if (rw == WRITE)
-			nr = __fuse_direct_write(filp, base, len, ppos);
-		else
-			nr = fuse_direct_read(filp, base, len, ppos);
-
-		if (nr < 0) {
-			if (!ret)
-				ret = nr;
-			break;
-		}
-		ret += nr;
-		if (nr != len)
-			break;
-	}
-
-	return ret;
-}
-
-
 static ssize_t
 fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
 			loff_t offset, unsigned long nr_segs)
@@ -2172,13 +2238,16 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
 	file = iocb->ki_filp;
 	pos = offset;
 
-	ret = fuse_loop_dio(file, iov, nr_segs, &pos, rw);
+	if (rw == WRITE)
+		ret = __fuse_direct_write(file, iov, nr_segs, &pos);
+	else
+		ret = __fuse_direct_read(file, iov, nr_segs, &pos);
 
 	return ret;
 }
 
-long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
-			    loff_t length)
+static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
+				loff_t length)
 {
 	struct fuse_file *ff = file->private_data;
 	struct fuse_conn *fc = ff->fc;
@@ -2194,7 +2263,7 @@ long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
 	if (fc->no_fallocate)
 		return -EOPNOTSUPP;
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -2213,7 +2282,6 @@ long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
 
 	return err;
 }
-EXPORT_SYMBOL_GPL(fuse_file_fallocate);
 
 static const struct file_operations fuse_file_operations = {
 	.llseek		= fuse_file_llseek,
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index e24dd74..13befcd 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -44,6 +44,9 @@
     doing the mount will be allowed to access the filesystem */
 #define FUSE_ALLOW_OTHER         (1 << 1)
 
+/** Number of page pointers embedded in fuse_req */
+#define FUSE_REQ_INLINE_PAGES 1
+
 /** List of active connections */
 extern struct list_head fuse_conn_list;
 
@@ -200,6 +203,12 @@ struct fuse_out {
 	struct fuse_arg args[3];
 };
 
+/** FUSE page descriptor */
+struct fuse_page_desc {
+	unsigned int length;
+	unsigned int offset;
+};
+
 /** The request state */
 enum fuse_req_state {
 	FUSE_REQ_INIT = 0,
@@ -291,14 +300,23 @@ struct fuse_req {
 	} misc;
 
 	/** page vector */
-	struct page *pages[FUSE_MAX_PAGES_PER_REQ];
+	struct page **pages;
+
+	/** page-descriptor vector */
+	struct fuse_page_desc *page_descs;
+
+	/** size of the 'pages' array */
+	unsigned max_pages;
+
+	/** inline page vector */
+	struct page *inline_pages[FUSE_REQ_INLINE_PAGES];
+
+	/** inline page-descriptor vector */
+	struct fuse_page_desc inline_page_descs[FUSE_REQ_INLINE_PAGES];
 
 	/** number of pages in vector */
 	unsigned num_pages;
 
-	/** offset of data on first page */
-	unsigned page_offset;
-
 	/** File used in the request (or NULL) */
 	struct fuse_file *ff;
 
@@ -333,10 +351,10 @@ struct fuse_conn {
 	atomic_t count;
 
 	/** The user id for this mount */
-	uid_t user_id;
+	kuid_t user_id;
 
 	/** The group id for this mount */
-	gid_t group_id;
+	kgid_t group_id;
 
 	/** The fuse mount flags for this mount */
 	unsigned flags;
@@ -487,6 +505,9 @@ struct fuse_conn {
 	/** Use enhanced/automatic page cache invalidation. */
 	unsigned auto_inval_data:1;
 
+	/** Does the filesystem support readdir-plus? */
+	unsigned do_readdirplus:1;
+
 	/** The number of requests waiting for completion */
 	atomic_t num_waiting;
 
@@ -578,6 +599,9 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget,
 
 struct fuse_forget_link *fuse_alloc_forget(void);
 
+/* Used by READDIRPLUS */
+void fuse_force_forget(struct file *file, u64 nodeid);
+
 /**
  * Initialize READ or READDIR request
  */
@@ -658,9 +682,9 @@ void fuse_ctl_cleanup(void);
 /**
  * Allocate a request
  */
-struct fuse_req *fuse_request_alloc(void);
+struct fuse_req *fuse_request_alloc(unsigned npages);
 
-struct fuse_req *fuse_request_alloc_nofs(void);
+struct fuse_req *fuse_request_alloc_nofs(unsigned npages);
 
 /**
  * Free a request
@@ -668,14 +692,25 @@ struct fuse_req *fuse_request_alloc_nofs(void);
 void fuse_request_free(struct fuse_req *req);
 
 /**
- * Get a request, may fail with -ENOMEM
+ * Get a request, may fail with -ENOMEM,
+ * caller should specify # elements in req->pages[] explicitly
  */
-struct fuse_req *fuse_get_req(struct fuse_conn *fc);
+struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages);
+
+/**
+ * Get a request, may fail with -ENOMEM,
+ * useful for callers who doesn't use req->pages[]
+ */
+static inline struct fuse_req *fuse_get_req_nopages(struct fuse_conn *fc)
+{
+	return fuse_get_req(fc, 0);
+}
 
 /**
  * Gets a requests for a file operation, always succeeds
  */
-struct fuse_req *fuse_get_req_nofail(struct fuse_conn *fc, struct file *file);
+struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc,
+					     struct file *file);
 
 /**
  * Decrement reference count of a request.  If count goes to zero free
@@ -776,8 +811,9 @@ int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
 
 int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
 		 bool isdir);
-ssize_t fuse_direct_io(struct file *file, const char __user *buf,
-		       size_t count, loff_t *ppos, int write);
+ssize_t fuse_direct_io(struct file *file, const struct iovec *iov,
+		       unsigned long nr_segs, size_t count, loff_t *ppos,
+		       int write);
 long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
 		   unsigned int flags);
 long fuse_ioctl_common(struct file *file, unsigned int cmd,
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index f0eda12..9d95a5a 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -60,8 +60,8 @@ MODULE_PARM_DESC(max_user_congthresh,
 struct fuse_mount_data {
 	int fd;
 	unsigned rootmode;
-	unsigned user_id;
-	unsigned group_id;
+	kuid_t user_id;
+	kgid_t group_id;
 	unsigned fd_present:1;
 	unsigned rootmode_present:1;
 	unsigned user_id_present:1;
@@ -164,8 +164,8 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
 	inode->i_ino     = fuse_squash_ino(attr->ino);
 	inode->i_mode    = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
 	set_nlink(inode, attr->nlink);
-	inode->i_uid     = attr->uid;
-	inode->i_gid     = attr->gid;
+	inode->i_uid     = make_kuid(&init_user_ns, attr->uid);
+	inode->i_gid     = make_kgid(&init_user_ns, attr->gid);
 	inode->i_blocks  = attr->blocks;
 	inode->i_atime.tv_sec   = attr->atime;
 	inode->i_atime.tv_nsec  = attr->atimensec;
@@ -413,7 +413,7 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
 		return 0;
 	}
 
-	req = fuse_get_req(fc);
+	req = fuse_get_req_nopages(fc);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -492,14 +492,18 @@ static int parse_fuse_opt(char *opt, struct fuse_mount_data *d, int is_bdev)
 		case OPT_USER_ID:
 			if (match_int(&args[0], &value))
 				return 0;
-			d->user_id = value;
+			d->user_id = make_kuid(current_user_ns(), value);
+			if (!uid_valid(d->user_id))
+				return 0;
 			d->user_id_present = 1;
 			break;
 
 		case OPT_GROUP_ID:
 			if (match_int(&args[0], &value))
 				return 0;
-			d->group_id = value;
+			d->group_id = make_kgid(current_user_ns(), value);
+			if (!gid_valid(d->group_id))
+				return 0;
 			d->group_id_present = 1;
 			break;
 
@@ -540,8 +544,8 @@ static int fuse_show_options(struct seq_file *m, struct dentry *root)
 	struct super_block *sb = root->d_sb;
 	struct fuse_conn *fc = get_fuse_conn_super(sb);
 
-	seq_printf(m, ",user_id=%u", fc->user_id);
-	seq_printf(m, ",group_id=%u", fc->group_id);
+	seq_printf(m, ",user_id=%u", from_kuid_munged(&init_user_ns, fc->user_id));
+	seq_printf(m, ",group_id=%u", from_kgid_munged(&init_user_ns, fc->group_id));
 	if (fc->flags & FUSE_DEFAULT_PERMISSIONS)
 		seq_puts(m, ",default_permissions");
 	if (fc->flags & FUSE_ALLOW_OTHER)
@@ -859,6 +863,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
 				fc->dont_mask = 1;
 			if (arg->flags & FUSE_AUTO_INVAL_DATA)
 				fc->auto_inval_data = 1;
+			if (arg->flags & FUSE_DO_READDIRPLUS)
+				fc->do_readdirplus = 1;
 		} else {
 			ra_pages = fc->max_read / PAGE_CACHE_SIZE;
 			fc->no_lock = 1;
@@ -885,7 +891,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
 	arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |
 		FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK |
 		FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ |
-		FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA;
+		FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA |
+		FUSE_DO_READDIRPLUS;
 	req->in.h.opcode = FUSE_INIT;
 	req->in.numargs = 1;
 	req->in.args[0].size = sizeof(*arg);
@@ -989,7 +996,8 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
 	if (!file)
 		goto err;
 
-	if (file->f_op != &fuse_dev_operations)
+	if ((file->f_op != &fuse_dev_operations) ||
+	    (file->f_cred->user_ns != &init_user_ns))
 		goto err_fput;
 
 	fc = kmalloc(sizeof(*fc), GFP_KERNEL);
@@ -1029,12 +1037,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
 	/* only now - we want root dentry with NULL ->d_op */
 	sb->s_d_op = &fuse_dentry_operations;
 
-	init_req = fuse_request_alloc();
+	init_req = fuse_request_alloc(0);
 	if (!init_req)
 		goto err_put_root;
 
 	if (is_bdev) {
-		fc->destroy_req = fuse_request_alloc();
+		fc->destroy_req = fuse_request_alloc(0);
 		if (!fc->destroy_req)
 			goto err_free_init_req;
 	}
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 01c4975..30de4f2 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -643,7 +643,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
 			goto out_unlock;
 
 		requested = data_blocks + ind_blocks;
-		error = gfs2_inplace_reserve(ip, requested);
+		error = gfs2_inplace_reserve(ip, requested, 0);
 		if (error)
 			goto out_qunlock;
 	}
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 1fd3ae2..a68e91b 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -991,6 +991,41 @@ unlock:
 	return err;
 }
 
+/**
+ * gfs2_journaled_truncate - Wrapper for truncate_pagecache for jdata files
+ * @inode: The inode being truncated
+ * @oldsize: The original (larger) size
+ * @newsize: The new smaller size
+ *
+ * With jdata files, we have to journal a revoke for each block which is
+ * truncated. As a result, we need to split this into separate transactions
+ * if the number of pages being truncated gets too large.
+ */
+
+#define GFS2_JTRUNC_REVOKES 8192
+
+static int gfs2_journaled_truncate(struct inode *inode, u64 oldsize, u64 newsize)
+{
+	struct gfs2_sbd *sdp = GFS2_SB(inode);
+	u64 max_chunk = GFS2_JTRUNC_REVOKES * sdp->sd_vfs->s_blocksize;
+	u64 chunk;
+	int error;
+
+	while (oldsize != newsize) {
+		chunk = oldsize - newsize;
+		if (chunk > max_chunk)
+			chunk = max_chunk;
+		truncate_pagecache(inode, oldsize, oldsize - chunk);
+		oldsize -= chunk;
+		gfs2_trans_end(sdp);
+		error = gfs2_trans_begin(sdp, RES_DINODE, GFS2_JTRUNC_REVOKES);
+		if (error)
+			return error;
+	}
+
+	return 0;
+}
+
 static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize)
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
@@ -1000,8 +1035,10 @@ static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize)
 	int journaled = gfs2_is_jdata(ip);
 	int error;
 
-	error = gfs2_trans_begin(sdp,
-				 RES_DINODE + (journaled ? RES_JDATA : 0), 0);
+	if (journaled)
+		error = gfs2_trans_begin(sdp, RES_DINODE + RES_JDATA, GFS2_JTRUNC_REVOKES);
+	else
+		error = gfs2_trans_begin(sdp, RES_DINODE, 0);
 	if (error)
 		return error;
 
@@ -1026,7 +1063,16 @@ static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize)
 	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 	gfs2_dinode_out(ip, dibh->b_data);
 
-	truncate_pagecache(inode, oldsize, newsize);
+	if (journaled)
+		error = gfs2_journaled_truncate(inode, oldsize, newsize);
+	else
+		truncate_pagecache(inode, oldsize, newsize);
+
+	if (error) {
+		brelse(dibh);
+		return error;
+	}
+
 out_brelse:
 	brelse(dibh);
 out:
@@ -1178,7 +1224,7 @@ static int do_grow(struct inode *inode, u64 size)
 		if (error)
 			return error;
 
-		error = gfs2_inplace_reserve(ip, 1);
+		error = gfs2_inplace_reserve(ip, 1, 0);
 		if (error)
 			goto do_grow_qunlock;
 		unstuff = 1;
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 259b088..9a35670 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -1676,16 +1676,11 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
 				be16_add_cpu(&leaf->lf_entries, 1);
 			}
 			brelse(bh);
-			error = gfs2_meta_inode_buffer(ip, &bh);
-			if (error)
-				break;
-			gfs2_trans_add_bh(ip->i_gl, bh, 1);
 			ip->i_entries++;
 			ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 			if (S_ISDIR(nip->i_inode.i_mode))
 				inc_nlink(&ip->i_inode);
-			gfs2_dinode_out(ip, bh->b_data);
-			brelse(bh);
+			mark_inode_dirty(inode);
 			error = 0;
 			break;
 		}
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index e056b4c..dfe2d8c 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -432,7 +432,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 	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);
+	ret = gfs2_inplace_reserve(ip, data_blocks + ind_blocks, 0);
 	if (ret)
 		goto out_quota_unlock;
 
@@ -825,7 +825,7 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
 retry:
 		gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks);
 
-		error = gfs2_inplace_reserve(ip, data_blocks + ind_blocks);
+		error = gfs2_inplace_reserve(ip, data_blocks + ind_blocks, 0);
 		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 e6c2fd5..992c5c0 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -55,8 +55,6 @@ struct gfs2_glock_iter {
 
 typedef void (*glock_examiner) (struct gfs2_glock * gl);
 
-static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl);
-#define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { __dump_glock(NULL, gl); BUG(); } } while(0)
 static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target);
 
 static struct dentry *gfs2_root;
@@ -107,10 +105,12 @@ static void gfs2_glock_dealloc(struct rcu_head *rcu)
 {
 	struct gfs2_glock *gl = container_of(rcu, struct gfs2_glock, gl_rcu);
 
-	if (gl->gl_ops->go_flags & GLOF_ASPACE)
+	if (gl->gl_ops->go_flags & GLOF_ASPACE) {
 		kmem_cache_free(gfs2_glock_aspace_cachep, gl);
-	else
+	} else {
+		kfree(gl->gl_lksb.sb_lvbptr);
 		kmem_cache_free(gfs2_glock_cachep, gl);
+	}
 }
 
 void gfs2_glock_free(struct gfs2_glock *gl)
@@ -537,8 +537,8 @@ __acquires(&gl->gl_spin)
 	    (lck_flags & (LM_FLAG_TRY|LM_FLAG_TRY_1CB)))
 		clear_bit(GLF_BLOCKING, &gl->gl_flags);
 	spin_unlock(&gl->gl_spin);
-	if (glops->go_xmote_th)
-		glops->go_xmote_th(gl);
+	if (glops->go_sync)
+		glops->go_sync(gl);
 	if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags))
 		glops->go_inval(gl, target == LM_ST_DEFERRED ? 0 : DIO_METADATA);
 	clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags);
@@ -547,7 +547,10 @@ __acquires(&gl->gl_spin)
 	if (sdp->sd_lockstruct.ls_ops->lm_lock)	{
 		/* lock_dlm */
 		ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags);
-		GLOCK_BUG_ON(gl, ret);
+		if (ret) {
+			printk(KERN_ERR "GFS2: lm_lock ret %d\n", ret);
+			GLOCK_BUG_ON(gl, 1);
+		}
 	} else { /* lock_nolock */
 		finish_xmote(gl, target);
 		if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
@@ -736,6 +739,16 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 	if (!gl)
 		return -ENOMEM;
 
+	memset(&gl->gl_lksb, 0, sizeof(struct dlm_lksb));
+
+	if (glops->go_flags & GLOF_LVB) {
+		gl->gl_lksb.sb_lvbptr = kzalloc(GFS2_MIN_LVB_SIZE, GFP_KERNEL);
+		if (!gl->gl_lksb.sb_lvbptr) {
+			kmem_cache_free(cachep, gl);
+			return -ENOMEM;
+		}
+	}
+
 	atomic_inc(&sdp->sd_glock_disposal);
 	gl->gl_sbd = sdp;
 	gl->gl_flags = 0;
@@ -753,9 +766,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 	preempt_enable();
 	gl->gl_stats.stats[GFS2_LKS_DCOUNT] = 0;
 	gl->gl_stats.stats[GFS2_LKS_QCOUNT] = 0;
-	memset(&gl->gl_lksb, 0, sizeof(struct dlm_lksb));
-	memset(gl->gl_lvb, 0, 32 * sizeof(char));
-	gl->gl_lksb.sb_lvbptr = gl->gl_lvb;
 	gl->gl_tchange = jiffies;
 	gl->gl_object = NULL;
 	gl->gl_hold_time = GL_GLOCK_DFT_HOLD;
@@ -768,7 +778,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 		mapping->host = s->s_bdev->bd_inode;
 		mapping->flags = 0;
 		mapping_set_gfp_mask(mapping, GFP_NOFS);
-		mapping->assoc_mapping = NULL;
+		mapping->private_data = NULL;
 		mapping->backing_dev_info = s->s_bdi;
 		mapping->writeback_index = 0;
 	}
@@ -777,6 +787,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 	tmp = search_bucket(hash, sdp, &name);
 	if (tmp) {
 		spin_unlock_bucket(hash);
+		kfree(gl->gl_lksb.sb_lvbptr);
 		kmem_cache_free(cachep, gl);
 		atomic_dec(&sdp->sd_glock_disposal);
 		gl = tmp;
@@ -1013,7 +1024,7 @@ trap_recursive:
 	printk(KERN_ERR "pid: %d\n", pid_nr(gh->gh_owner_pid));
 	printk(KERN_ERR "lock type: %d req lock state : %d\n",
 	       gh->gh_gl->gl_name.ln_type, gh->gh_state);
-	__dump_glock(NULL, gl);
+	gfs2_dump_glock(NULL, gl);
 	BUG();
 }
 
@@ -1508,7 +1519,7 @@ static int dump_glock(struct seq_file *seq, struct gfs2_glock *gl)
 {
 	int ret;
 	spin_lock(&gl->gl_spin);
-	ret = __dump_glock(seq, gl);
+	ret = gfs2_dump_glock(seq, gl);
 	spin_unlock(&gl->gl_spin);
 	return ret;
 }
@@ -1528,6 +1539,7 @@ static void dump_glock_func(struct gfs2_glock *gl)
 
 void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
 {
+	set_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags);
 	glock_hash_walk(clear_glock, sdp);
 	flush_workqueue(glock_workqueue);
 	wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0);
@@ -1655,7 +1667,7 @@ static const char *gflags2str(char *buf, const struct gfs2_glock *gl)
 }
 
 /**
- * __dump_glock - print information about a glock
+ * gfs2_dump_glock - print information about a glock
  * @seq: The seq_file struct
  * @gl: the glock
  *
@@ -1672,7 +1684,7 @@ static const char *gflags2str(char *buf, const struct gfs2_glock *gl)
  * Returns: 0 on success, -ENOBUFS when we run out of space
  */
 
-static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl)
+int gfs2_dump_glock(struct seq_file *seq, const struct gfs2_glock *gl)
 {
 	const struct gfs2_glock_operations *glops = gl->gl_ops;
 	unsigned long long dtime;
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index 307ac31..fd580b7 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -178,33 +178,33 @@ static inline struct address_space *gfs2_glock2aspace(struct gfs2_glock *gl)
 	return NULL;
 }
 
-int gfs2_glock_get(struct gfs2_sbd *sdp,
-		   u64 number, const struct gfs2_glock_operations *glops,
-		   int create, struct gfs2_glock **glp);
-void gfs2_glock_hold(struct gfs2_glock *gl);
-void gfs2_glock_put_nolock(struct gfs2_glock *gl);
-void gfs2_glock_put(struct gfs2_glock *gl);
-void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags,
-		      struct gfs2_holder *gh);
-void gfs2_holder_reinit(unsigned int state, unsigned flags,
-			struct gfs2_holder *gh);
-void gfs2_holder_uninit(struct gfs2_holder *gh);
-int gfs2_glock_nq(struct gfs2_holder *gh);
-int gfs2_glock_poll(struct gfs2_holder *gh);
-int gfs2_glock_wait(struct gfs2_holder *gh);
-void gfs2_glock_dq(struct gfs2_holder *gh);
-void gfs2_glock_dq_wait(struct gfs2_holder *gh);
-
-void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
-int gfs2_glock_nq_num(struct gfs2_sbd *sdp,
-		      u64 number, const struct gfs2_glock_operations *glops,
-		      unsigned int state, int flags, struct gfs2_holder *gh);
-
-int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs);
-void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs);
-void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);
-
-__printf(2, 3)
+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);
+extern void gfs2_holder_reinit(unsigned int state, unsigned flags,
+			       struct gfs2_holder *gh);
+extern void gfs2_holder_uninit(struct gfs2_holder *gh);
+extern int gfs2_glock_nq(struct gfs2_holder *gh);
+extern int gfs2_glock_poll(struct gfs2_holder *gh);
+extern int gfs2_glock_wait(struct gfs2_holder *gh);
+extern void gfs2_glock_dq(struct gfs2_holder *gh);
+extern void gfs2_glock_dq_wait(struct gfs2_holder *gh);
+extern void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
+extern int gfs2_glock_nq_num(struct gfs2_sbd *sdp, u64 number,
+			     const struct gfs2_glock_operations *glops,
+			     unsigned int state, int flags,
+			     struct gfs2_holder *gh);
+extern int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs);
+extern void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs);
+extern void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);
+extern int gfs2_dump_glock(struct seq_file *seq, const struct gfs2_glock *gl);
+#define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { gfs2_dump_glock(NULL, gl); BUG(); } } while(0)
+extern __printf(2, 3)
 void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...);
 
 /**
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 32cc4fd..78d4184 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -74,7 +74,7 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 
 		gfs2_trans_add_revoke(sdp, bd);
 	}
-	BUG_ON(!fsync && atomic_read(&gl->gl_ail_count));
+	GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count));
 	spin_unlock(&sdp->sd_ail_lock);
 	gfs2_log_unlock(sdp);
 }
@@ -96,7 +96,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
 	tr.tr_ip = (unsigned long)__builtin_return_address(0);
 	sb_start_intwrite(sdp->sd_vfs);
 	gfs2_log_reserve(sdp, tr.tr_reserved);
-	BUG_ON(current->journal_info);
+	WARN_ON_ONCE(current->journal_info);
 	current->journal_info = &tr;
 
 	__gfs2_ail_flush(gl, 0);
@@ -139,7 +139,7 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
 
 	if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
 		return;
-	BUG_ON(gl->gl_state != LM_ST_EXCLUSIVE);
+	GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
 
 	gfs2_log_flush(gl->gl_sbd, gl);
 	filemap_fdatawrite(metamapping);
@@ -168,7 +168,7 @@ static void rgrp_go_inval(struct gfs2_glock *gl, int flags)
 {
 	struct address_space *mapping = gfs2_glock2aspace(gl);
 
-	BUG_ON(!(flags & DIO_METADATA));
+	WARN_ON_ONCE(!(flags & DIO_METADATA));
 	gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count));
 	truncate_inode_pages(mapping, 0);
 
@@ -197,7 +197,7 @@ static void inode_go_sync(struct gfs2_glock *gl)
 	if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
 		return;
 
-	BUG_ON(gl->gl_state != LM_ST_EXCLUSIVE);
+	GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
 
 	gfs2_log_flush(gl->gl_sbd, gl);
 	filemap_fdatawrite(metamapping);
@@ -536,7 +536,7 @@ const struct gfs2_glock_operations gfs2_meta_glops = {
 };
 
 const struct gfs2_glock_operations gfs2_inode_glops = {
-	.go_xmote_th = inode_go_sync,
+	.go_sync = inode_go_sync,
 	.go_inval = inode_go_inval,
 	.go_demote_ok = inode_go_demote_ok,
 	.go_lock = inode_go_lock,
@@ -546,17 +546,17 @@ const struct gfs2_glock_operations gfs2_inode_glops = {
 };
 
 const struct gfs2_glock_operations gfs2_rgrp_glops = {
-	.go_xmote_th = rgrp_go_sync,
+	.go_sync = rgrp_go_sync,
 	.go_inval = rgrp_go_inval,
 	.go_lock = gfs2_rgrp_go_lock,
 	.go_unlock = gfs2_rgrp_go_unlock,
 	.go_dump = gfs2_rgrp_dump,
 	.go_type = LM_TYPE_RGRP,
-	.go_flags = GLOF_ASPACE,
+	.go_flags = GLOF_ASPACE | GLOF_LVB,
 };
 
 const struct gfs2_glock_operations gfs2_trans_glops = {
-	.go_xmote_th = trans_go_sync,
+	.go_sync = trans_go_sync,
 	.go_xmote_bh = trans_go_xmote_bh,
 	.go_demote_ok = trans_go_demote_ok,
 	.go_type = LM_TYPE_NONDISK,
@@ -577,6 +577,7 @@ const struct gfs2_glock_operations gfs2_nondisk_glops = {
 
 const struct gfs2_glock_operations gfs2_quota_glops = {
 	.go_type = LM_TYPE_QUOTA,
+	.go_flags = GLOF_LVB,
 };
 
 const struct gfs2_glock_operations gfs2_journal_glops = {
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 3d469d3..c373a24 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -205,7 +205,7 @@ struct lm_lockname {
 
 
 struct gfs2_glock_operations {
-	void (*go_xmote_th) (struct gfs2_glock *gl);
+	void (*go_sync) (struct gfs2_glock *gl);
 	int (*go_xmote_bh) (struct gfs2_glock *gl, struct gfs2_holder *gh);
 	void (*go_inval) (struct gfs2_glock *gl, int flags);
 	int (*go_demote_ok) (const struct gfs2_glock *gl);
@@ -216,6 +216,7 @@ struct gfs2_glock_operations {
 	const int go_type;
 	const unsigned long go_flags;
 #define GLOF_ASPACE 1
+#define GLOF_LVB    2
 };
 
 enum {
@@ -321,7 +322,6 @@ struct gfs2_glock {
 	ktime_t gl_dstamp;
 	struct gfs2_lkstats gl_stats;
 	struct dlm_lksb gl_lksb;
-	char gl_lvb[32];
 	unsigned long gl_tchange;
 	void *gl_object;
 
@@ -539,6 +539,7 @@ enum {
 	SDF_DEMOTE		= 5,
 	SDF_NOJOURNALID		= 6,
 	SDF_RORECOVERY		= 7, /* read only recovery */
+	SDF_SKIP_DLM_UNLOCK	= 8,
 };
 
 #define GFS2_FSNAME_LEN		256
@@ -621,6 +622,7 @@ struct gfs2_sbd {
 	u32 sd_hash_bsize_shift;
 	u32 sd_hash_ptrs;	/* Number of pointers in a hash block */
 	u32 sd_qc_per_block;
+	u32 sd_blocks_per_bitmap;
 	u32 sd_max_dirres;	/* Max blocks needed to add a directory entry */
 	u32 sd_max_height;	/* Max height of a file's metadata tree */
 	u64 sd_heightsize[GFS2_MAX_META_HEIGHT + 1];
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 381893c..2b6f569 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -364,34 +364,34 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name,
 	return 0;
 }
 
-static void munge_mode_uid_gid(struct gfs2_inode *dip, umode_t *mode,
-			       unsigned int *uid, unsigned int *gid)
+static void munge_mode_uid_gid(const struct gfs2_inode *dip,
+			       struct inode *inode)
 {
 	if (GFS2_SB(&dip->i_inode)->sd_args.ar_suiddir &&
 	    (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) {
-		if (S_ISDIR(*mode))
-			*mode |= S_ISUID;
+		if (S_ISDIR(inode->i_mode))
+			inode->i_mode |= S_ISUID;
 		else if (dip->i_inode.i_uid != current_fsuid())
-			*mode &= ~07111;
-		*uid = dip->i_inode.i_uid;
+			inode->i_mode &= ~07111;
+		inode->i_uid = dip->i_inode.i_uid;
 	} else
-		*uid = current_fsuid();
+		inode->i_uid = current_fsuid();
 
 	if (dip->i_inode.i_mode & S_ISGID) {
-		if (S_ISDIR(*mode))
-			*mode |= S_ISGID;
-		*gid = dip->i_inode.i_gid;
+		if (S_ISDIR(inode->i_mode))
+			inode->i_mode |= S_ISGID;
+		inode->i_gid = dip->i_inode.i_gid;
 	} else
-		*gid = current_fsgid();
+		inode->i_gid = current_fsgid();
 }
 
-static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
+static int alloc_dinode(struct gfs2_inode *ip, u32 flags)
 {
-	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
+	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	int error;
 	int dblocks = 1;
 
-	error = gfs2_inplace_reserve(dip, RES_DINODE);
+	error = gfs2_inplace_reserve(ip, RES_DINODE, flags);
 	if (error)
 		goto out;
 
@@ -399,12 +399,15 @@ static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
 	if (error)
 		goto out_ipreserv;
 
-	error = gfs2_alloc_blocks(dip, no_addr, &dblocks, 1, generation);
+	error = gfs2_alloc_blocks(ip, &ip->i_no_addr, &dblocks, 1, &ip->i_generation);
+	ip->i_no_formal_ino = ip->i_generation;
+	ip->i_inode.i_ino = ip->i_no_addr;
+	ip->i_goal = ip->i_no_addr;
 
 	gfs2_trans_end(sdp);
 
 out_ipreserv:
-	gfs2_inplace_release(dip);
+	gfs2_inplace_release(ip);
 out:
 	return error;
 }
@@ -429,52 +432,42 @@ static void gfs2_init_dir(struct buffer_head *dibh,
 /**
  * init_dinode - Fill in a new dinode structure
  * @dip: The directory this inode is being created in
- * @gl: The glock covering the new inode
- * @inum: The inode number
- * @mode: The file permissions
- * @uid: The uid of the new inode
- * @gid: The gid of the new inode
- * @generation: The generation number of the new inode
- * @dev: The device number (if a device node)
+ * @ip: The inode
  * @symname: The symlink destination (if a symlink)
- * @size: The inode size (ignored for directories)
  * @bhp: The buffer head (returned to caller)
  *
  */
 
-static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
-			const struct gfs2_inum_host *inum, umode_t mode,
-			unsigned int uid, unsigned int gid,
-			const u64 *generation, dev_t dev, const char *symname,
-			unsigned size, struct buffer_head **bhp)
+static void init_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip,
+			const char *symname, struct buffer_head **bhp)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
 	struct gfs2_dinode *di;
 	struct buffer_head *dibh;
 	struct timespec tv = CURRENT_TIME;
 
-	dibh = gfs2_meta_new(gl, inum->no_addr);
-	gfs2_trans_add_bh(gl, dibh, 1);
+	dibh = gfs2_meta_new(ip->i_gl, ip->i_no_addr);
+	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 	gfs2_metatype_set(dibh, GFS2_METATYPE_DI, GFS2_FORMAT_DI);
 	gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
 	di = (struct gfs2_dinode *)dibh->b_data;
 
-	di->di_num.no_formal_ino = cpu_to_be64(inum->no_formal_ino);
-	di->di_num.no_addr = cpu_to_be64(inum->no_addr);
-	di->di_mode = cpu_to_be32(mode);
-	di->di_uid = cpu_to_be32(uid);
-	di->di_gid = cpu_to_be32(gid);
+	di->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
+	di->di_num.no_addr = cpu_to_be64(ip->i_no_addr);
+	di->di_mode = cpu_to_be32(ip->i_inode.i_mode);
+	di->di_uid = cpu_to_be32(ip->i_inode.i_uid);
+	di->di_gid = cpu_to_be32(ip->i_inode.i_gid);
 	di->di_nlink = 0;
-	di->di_size = cpu_to_be64(size);
+	di->di_size = cpu_to_be64(ip->i_inode.i_size);
 	di->di_blocks = cpu_to_be64(1);
 	di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec);
-	di->di_major = cpu_to_be32(MAJOR(dev));
-	di->di_minor = cpu_to_be32(MINOR(dev));
-	di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr);
-	di->di_generation = cpu_to_be64(*generation);
+	di->di_major = cpu_to_be32(MAJOR(ip->i_inode.i_rdev));
+	di->di_minor = cpu_to_be32(MINOR(ip->i_inode.i_rdev));
+	di->di_goal_meta = di->di_goal_data = cpu_to_be64(ip->i_no_addr);
+	di->di_generation = cpu_to_be64(ip->i_generation);
 	di->di_flags = 0;
 	di->__pad1 = 0;
-	di->di_payload_format = cpu_to_be32(S_ISDIR(mode) ? GFS2_FORMAT_DE : 0);
+	di->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) ? GFS2_FORMAT_DE : 0);
 	di->di_height = 0;
 	di->__pad2 = 0;
 	di->__pad3 = 0;
@@ -487,7 +480,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
 	di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec);
 	memset(&di->di_reserved, 0, sizeof(di->di_reserved));
 
-	switch(mode & S_IFMT) {	
+	switch(ip->i_inode.i_mode & S_IFMT) {
 	case S_IFREG:
 		if ((dip->i_diskflags & GFS2_DIF_INHERIT_JDATA) ||
 		    gfs2_tune_get(sdp, gt_new_files_jdata))
@@ -502,7 +495,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
 		gfs2_init_dir(dibh, dip);
 		break;
 	case S_IFLNK:
-		memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname, size);
+		memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname, ip->i_inode.i_size);
 		break;
 	}
 
@@ -511,25 +504,22 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
 	*bhp = dibh;
 }
 
-static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
-		       umode_t mode, const struct gfs2_inum_host *inum,
-		       const u64 *generation, dev_t dev, const char *symname,
-		       unsigned int size, struct buffer_head **bhp)
+static int make_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip,
+		       const char *symname, struct buffer_head **bhp)
 {
+	struct inode *inode = &ip->i_inode;
 	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
-	unsigned int uid, gid;
 	int error;
 
-	munge_mode_uid_gid(dip, &mode, &uid, &gid);
 	error = gfs2_rindex_update(sdp);
 	if (error)
 		return error;
 
-	error = gfs2_quota_lock(dip, uid, gid);
+	error = gfs2_quota_lock(dip, inode->i_uid, inode->i_gid);
 	if (error)
 		return error;
 
-	error = gfs2_quota_check(dip, uid, gid);
+	error = gfs2_quota_check(dip, inode->i_uid, inode->i_gid);
 	if (error)
 		goto out_quota;
 
@@ -537,8 +527,8 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
 	if (error)
 		goto out_quota;
 
-	init_dinode(dip, gl, inum, mode, uid, gid, generation, dev, symname, size, bhp);
-	gfs2_quota_change(dip, +1, uid, gid);
+	init_dinode(dip, ip, symname, bhp);
+	gfs2_quota_change(dip, +1, inode->i_uid, inode->i_gid);
 	gfs2_trans_end(sdp);
 
 out_quota:
@@ -570,7 +560,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
 		if (error)
 			goto fail_quota_locks;
 
-		error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres);
+		error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres, 0);
 		if (error)
 			goto fail_quota_locks;
 
@@ -657,19 +647,14 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 	struct inode *inode = NULL;
 	struct gfs2_inode *dip = GFS2_I(dir), *ip;
 	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
-	struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 };
+	struct gfs2_glock *io_gl;
 	int error;
-	u64 generation;
 	struct buffer_head *bh = NULL;
+	u32 aflags = 0;
 
 	if (!name->len || name->len > GFS2_FNAMESIZE)
 		return -ENAMETOOLONG;
 
-	/* We need a reservation to allocate the new dinode block. The
-	   directory ip temporarily points to the reservation, but this is
-	   being done to get a set of contiguous blocks for the new dinode.
-	   Since this is a create, we don't have a sizehint yet, so it will
-	   have to use the minimum reservation size. */
 	error = gfs2_rs_alloc(dip);
 	if (error)
 		return error;
@@ -688,45 +673,72 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 	if (error)
 		goto fail_gunlock;
 
-	error = alloc_dinode(dip, &inum.no_addr, &generation);
+	inode = new_inode(sdp->sd_vfs);
+	if (!inode) {
+		gfs2_glock_dq_uninit(ghs);
+		return -ENOMEM;
+	}
+	ip = GFS2_I(inode);
+	error = gfs2_rs_alloc(ip);
 	if (error)
-		goto fail_gunlock;
-	inum.no_formal_ino = generation;
+		goto fail_free_inode;
+
+	set_bit(GIF_INVALID, &ip->i_flags);
+	inode->i_mode = mode;
+	inode->i_rdev = dev;
+	inode->i_size = size;
+	munge_mode_uid_gid(dip, inode);
+	ip->i_goal = dip->i_goal;
 
-	error = gfs2_glock_nq_num(sdp, inum.no_addr, &gfs2_inode_glops,
-				  LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1);
+	if ((GFS2_I(sdp->sd_root_dir->d_inode) == dip) ||
+	    (dip->i_diskflags & GFS2_DIF_TOPDIR))
+		aflags |= GFS2_AF_ORLOV;
+
+	error = alloc_dinode(ip, aflags);
 	if (error)
-		goto fail_gunlock;
+		goto fail_free_inode;
 
-	error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev, symname, size, &bh);
+	error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
 	if (error)
-		goto fail_gunlock2;
+		goto fail_free_inode;
 
-	inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), inum.no_addr,
-				  inum.no_formal_ino, 0);
-	if (IS_ERR(inode))
+	ip->i_gl->gl_object = ip;
+	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1);
+	if (error)
+		goto fail_free_inode;
+
+	error = make_dinode(dip, ip, symname, &bh);
+	if (error)
 		goto fail_gunlock2;
 
-	ip = GFS2_I(inode);
-	error = gfs2_inode_refresh(ip);
+	error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
 	if (error)
 		goto fail_gunlock2;
 
-	error = gfs2_rs_alloc(ip);
+	error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
 	if (error)
 		goto fail_gunlock2;
 
+	ip->i_iopen_gh.gh_gl->gl_object = ip;
+	gfs2_glock_put(io_gl);
+	gfs2_set_iop(inode);
+	insert_inode_hash(inode);
+
+	error = gfs2_inode_refresh(ip);
+	if (error)
+		goto fail_gunlock3;
+
 	error = gfs2_acl_create(dip, inode);
 	if (error)
-		goto fail_gunlock2;
+		goto fail_gunlock3;
 
 	error = gfs2_security_init(dip, ip, name);
 	if (error)
-		goto fail_gunlock2;
+		goto fail_gunlock3;
 
 	error = link_dinode(dip, name, ip);
 	if (error)
-		goto fail_gunlock2;
+		goto fail_gunlock3;
 
 	if (bh)
 		brelse(bh);
@@ -739,8 +751,20 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 	d_instantiate(dentry, inode);
 	return 0;
 
+fail_gunlock3:
+	gfs2_glock_dq_uninit(ghs + 1);
+	if (ip->i_gl)
+		gfs2_glock_put(ip->i_gl);
+	goto fail_gunlock;
+
 fail_gunlock2:
 	gfs2_glock_dq_uninit(ghs + 1);
+fail_free_inode:
+	if (ip->i_gl)
+		gfs2_glock_put(ip->i_gl);
+	gfs2_rs_delete(ip);
+	free_inode_nonrcu(inode);
+	inode = NULL;
 fail_gunlock:
 	gfs2_glock_dq_uninit(ghs);
 	if (inode && !IS_ERR(inode)) {
@@ -748,7 +772,6 @@ fail_gunlock:
 		iput(inode);
 	}
 fail:
-	gfs2_rs_delete(dip);
 	if (bh)
 		brelse(bh);
 	return error;
@@ -884,7 +907,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
 		if (error)
 			goto out_gunlock;
 
-		error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres);
+		error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres, 0);
 		if (error)
 			goto out_gunlock_q;
 
@@ -977,7 +1000,6 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
  * gfs2_unlink_inode - Removes an inode from its parent dir and unlinks it
  * @dip: The parent directory
  * @name: The name of the entry in the parent directory
- * @bh: The inode buffer for the inode to be removed
  * @inode: The inode to be removed
  *
  * Called with all the locks and in a transaction. This will only be
@@ -987,8 +1009,7 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
  */
 
 static int gfs2_unlink_inode(struct gfs2_inode *dip,
-			     const struct dentry *dentry,
-			     struct buffer_head *bh)
+			     const struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
 	struct gfs2_inode *ip = GFS2_I(inode);
@@ -1028,7 +1049,6 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
 	struct gfs2_sbd *sdp = GFS2_SB(dir);
 	struct inode *inode = dentry->d_inode;
 	struct gfs2_inode *ip = GFS2_I(inode);
-	struct buffer_head *bh;
 	struct gfs2_holder ghs[3];
 	struct gfs2_rgrpd *rgd;
 	int error;
@@ -1077,14 +1097,9 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
 
 	error = gfs2_trans_begin(sdp, 2*RES_DINODE + 3*RES_LEAF + RES_RG_BIT, 0);
 	if (error)
-		goto out_gunlock;
-
-	error = gfs2_meta_inode_buffer(ip, &bh);
-	if (error)
 		goto out_end_trans;
 
-	error = gfs2_unlink_inode(dip, dentry, bh);
-	brelse(bh);
+	error = gfs2_unlink_inode(dip, dentry);
 
 out_end_trans:
 	gfs2_trans_end(sdp);
@@ -1365,7 +1380,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
 		if (error)
 			goto out_gunlock;
 
-		error = gfs2_inplace_reserve(ndip, sdp->sd_max_dirres);
+		error = gfs2_inplace_reserve(ndip, sdp->sd_max_dirres, 0);
 		if (error)
 			goto out_gunlock_q;
 
@@ -1384,14 +1399,8 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
 
 	/* Remove the target file, if it exists */
 
-	if (nip) {
-		struct buffer_head *bh;
-		error = gfs2_meta_inode_buffer(nip, &bh);
-		if (error)
-			goto out_end_trans;
-		error = gfs2_unlink_inode(ndip, ndentry, bh);
-		brelse(bh);
-	}
+	if (nip)
+		error = gfs2_unlink_inode(ndip, ndentry);
 
 	if (dir_rename) {
 		error = gfs2_dir_mvino(ip, &gfs2_qdotdot, ndip, DT_DIR);
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
index 0fb6539..8dad6b0 100644
--- a/fs/gfs2/lock_dlm.c
+++ b/fs/gfs2/lock_dlm.c
@@ -120,8 +120,8 @@ static void gdlm_ast(void *arg)
 	gfs2_update_reply_times(gl);
 	BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED);
 
-	if (gl->gl_lksb.sb_flags & DLM_SBF_VALNOTVALID)
-		memset(gl->gl_lvb, 0, GDLM_LVB_SIZE);
+	if ((gl->gl_lksb.sb_flags & DLM_SBF_VALNOTVALID) && gl->gl_lksb.sb_lvbptr)
+		memset(gl->gl_lksb.sb_lvbptr, 0, GDLM_LVB_SIZE);
 
 	switch (gl->gl_lksb.sb_status) {
 	case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */
@@ -203,8 +203,10 @@ static int make_mode(const unsigned int lmstate)
 static u32 make_flags(struct gfs2_glock *gl, const unsigned int gfs_flags,
 		      const int req)
 {
-	u32 lkf = DLM_LKF_VALBLK;
-	u32 lkid = gl->gl_lksb.sb_lkid;
+	u32 lkf = 0;
+
+	if (gl->gl_lksb.sb_lvbptr)
+		lkf |= DLM_LKF_VALBLK;
 
 	if (gfs_flags & LM_FLAG_TRY)
 		lkf |= DLM_LKF_NOQUEUE;
@@ -228,7 +230,7 @@ static u32 make_flags(struct gfs2_glock *gl, const unsigned int gfs_flags,
 			BUG();
 	}
 
-	if (lkid != 0) {
+	if (gl->gl_lksb.sb_lkid != 0) {
 		lkf |= DLM_LKF_CONVERT;
 		if (test_bit(GLF_BLOCKING, &gl->gl_flags))
 			lkf |= DLM_LKF_QUECVT;
@@ -289,6 +291,14 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
 	gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT);
 	gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT);
 	gfs2_update_request_times(gl);
+
+	/* don't want to skip dlm_unlock writing the lvb when lock is ex */
+	if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) &&
+	    gl->gl_lksb.sb_lvbptr && (gl->gl_state != LM_ST_EXCLUSIVE)) {
+		gfs2_glock_free(gl);
+		return;
+	}
+
 	error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_VALBLK,
 			   NULL, gl);
 	if (error) {
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index e443966..0e3554e 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -278,6 +278,9 @@ static int gfs2_read_sb(struct gfs2_sbd *sdp, int silent)
 	sdp->sd_qc_per_block = (sdp->sd_sb.sb_bsize -
 				sizeof(struct gfs2_meta_header)) /
 			        sizeof(struct gfs2_quota_change);
+	sdp->sd_blocks_per_bitmap = (sdp->sd_sb.sb_bsize -
+				     sizeof(struct gfs2_meta_header))
+		* GFS2_NBBY; /* not the rgrp bitmap, subsequent bitmaps only */
 
 	/* Compute maximum reservation required to add a entry to a directory */
 
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index c5af8e1..ae55e24 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -816,7 +816,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
 	blocks = num_qd * data_blocks + RES_DINODE + num_qd + 3;
 
 	reserved = 1 + (nalloc * (data_blocks + ind_blocks));
-	error = gfs2_inplace_reserve(ip, reserved);
+	error = gfs2_inplace_reserve(ip, reserved, 0);
 	if (error)
 		goto out_alloc;
 
@@ -869,7 +869,7 @@ static int update_qd(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd)
 	if (error < 0)
 		return error;
 
-	qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
+	qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr;
 	qlvb->qb_magic = cpu_to_be32(GFS2_MAGIC);
 	qlvb->__pad = 0;
 	qlvb->qb_limit = q.qu_limit;
@@ -893,7 +893,7 @@ restart:
 	if (error)
 		return error;
 
-	qd->qd_qb = *(struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
+	qd->qd_qb = *(struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr;
 
 	if (force_refresh || qd->qd_qb.qb_magic != cpu_to_be32(GFS2_MAGIC)) {
 		gfs2_glock_dq_uninit(q_gh);
@@ -1506,7 +1506,7 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,
 	if (error)
 		goto out;
 
-	qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
+	qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr;
 	fdq->d_version = FS_DQUOT_VERSION;
 	fdq->d_flags = (type == QUOTA_USER) ? FS_USER_QUOTA : FS_GROUP_QUOTA;
 	fdq->d_id = from_kqid(&init_user_ns, qid);
@@ -1605,7 +1605,7 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,
 		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);
+		error = gfs2_inplace_reserve(ip, blocks, 0);
 		if (error)
 			goto out_i;
 		blocks += gfs2_rg_blocks(ip, blocks);
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 38fe18f..37ee061 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -16,6 +16,7 @@
 #include <linux/prefetch.h>
 #include <linux/blkdev.h>
 #include <linux/rbtree.h>
+#include <linux/random.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -251,22 +252,25 @@ static u32 gfs2_bitfit(const u8 *buf, const unsigned int len,
 static int gfs2_rbm_from_block(struct gfs2_rbm *rbm, u64 block)
 {
 	u64 rblock = block - rbm->rgd->rd_data0;
-	u32 goal = (u32)rblock;
-	int x;
+	u32 x;
 
 	if (WARN_ON_ONCE(rblock > UINT_MAX))
 		return -EINVAL;
 	if (block >= rbm->rgd->rd_data0 + rbm->rgd->rd_data)
 		return -E2BIG;
 
-	for (x = 0; x < rbm->rgd->rd_length; x++) {
-		rbm->bi = rbm->rgd->rd_bits + x;
-		if (goal < (rbm->bi->bi_start + rbm->bi->bi_len) * GFS2_NBBY) {
-			rbm->offset = goal - (rbm->bi->bi_start * GFS2_NBBY);
-			break;
-		}
-	}
+	rbm->bi = rbm->rgd->rd_bits;
+	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)
+		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;
 	return 0;
 }
 
@@ -875,7 +879,7 @@ static int read_rindex_entry(struct gfs2_inode *ip)
 		goto fail;
 
 	rgd->rd_gl->gl_object = rgd;
-	rgd->rd_rgl = (struct gfs2_rgrp_lvb *)rgd->rd_gl->gl_lvb;
+	rgd->rd_rgl = (struct gfs2_rgrp_lvb *)rgd->rd_gl->gl_lksb.sb_lvbptr;
 	rgd->rd_flags &= ~GFS2_RDF_UPTODATE;
 	if (rgd->rd_data > sdp->sd_max_rg_data)
 		sdp->sd_max_rg_data = rgd->rd_data;
@@ -1678,13 +1682,105 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip
 	return;
 }
 
+/**
+ * gfs2_rgrp_congested - Use stats to figure out whether an rgrp is congested
+ * @rgd: The rgrp in question
+ * @loops: An indication of how picky we can be (0=very, 1=less so)
+ *
+ * This function uses the recently added glock statistics in order to
+ * figure out whether a parciular resource group is suffering from
+ * contention from multiple nodes. This is done purely on the basis
+ * of timings, since this is the only data we have to work with and
+ * our aim here is to reject a resource group which is highly contended
+ * but (very important) not to do this too often in order to ensure that
+ * we do not land up introducing fragmentation by changing resource
+ * groups when not actually required.
+ *
+ * The calculation is fairly simple, we want to know whether the SRTTB
+ * (i.e. smoothed round trip time for blocking operations) to acquire
+ * the lock for this rgrp's glock is significantly greater than the
+ * time taken for resource groups on average. We introduce a margin in
+ * the form of the variable @var which is computed as the sum of the two
+ * respective variences, and multiplied by a factor depending on @loops
+ * and whether we have a lot of data to base the decision on. This is
+ * then tested against the square difference of the means in order to
+ * decide whether the result is statistically significant or not.
+ *
+ * Returns: A boolean verdict on the congestion status
+ */
+
+static bool gfs2_rgrp_congested(const struct gfs2_rgrpd *rgd, int loops)
+{
+	const struct gfs2_glock *gl = rgd->rd_gl;
+	const struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_lkstats *st;
+	s64 r_dcount, l_dcount;
+	s64 r_srttb, l_srttb;
+	s64 srttb_diff;
+	s64 sqr_diff;
+	s64 var;
+
+	preempt_disable();
+	st = &this_cpu_ptr(sdp->sd_lkstats)->lkstats[LM_TYPE_RGRP];
+	r_srttb = st->stats[GFS2_LKS_SRTTB];
+	r_dcount = st->stats[GFS2_LKS_DCOUNT];
+	var = st->stats[GFS2_LKS_SRTTVARB] +
+	      gl->gl_stats.stats[GFS2_LKS_SRTTVARB];
+	preempt_enable();
+
+	l_srttb = gl->gl_stats.stats[GFS2_LKS_SRTTB];
+	l_dcount = gl->gl_stats.stats[GFS2_LKS_DCOUNT];
+
+	if ((l_dcount < 1) || (r_dcount < 1) || (r_srttb == 0))
+		return false;
+
+	srttb_diff = r_srttb - l_srttb;
+	sqr_diff = srttb_diff * srttb_diff;
+
+	var *= 2;
+	if (l_dcount < 8 || r_dcount < 8)
+		var *= 2;
+	if (loops == 1)
+		var *= 2;
+
+	return ((srttb_diff < 0) && (sqr_diff > var));
+}
+
+/**
+ * gfs2_rgrp_used_recently
+ * @rs: The block reservation with the rgrp to test
+ * @msecs: The time limit in milliseconds
+ *
+ * Returns: True if the rgrp glock has been used within the time limit
+ */
+static bool gfs2_rgrp_used_recently(const struct gfs2_blkreserv *rs,
+				    u64 msecs)
+{
+	u64 tdiff;
+
+	tdiff = ktime_to_ns(ktime_sub(ktime_get_real(),
+                            rs->rs_rbm.rgd->rd_gl->gl_dstamp));
+
+	return tdiff > (msecs * 1000 * 1000);
+}
+
+static u32 gfs2_orlov_skip(const struct gfs2_inode *ip)
+{
+	const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+	u32 skip;
+
+	get_random_bytes(&skip, sizeof(skip));
+	return skip % sdp->sd_rgrps;
+}
+
 static bool gfs2_select_rgrp(struct gfs2_rgrpd **pos, const struct gfs2_rgrpd *begin)
 {
 	struct gfs2_rgrpd *rgd = *pos;
+	struct gfs2_sbd *sdp = rgd->rd_sbd;
 
 	rgd = gfs2_rgrpd_get_next(rgd);
 	if (rgd == NULL)
-		rgd = gfs2_rgrpd_get_next(NULL);
+		rgd = gfs2_rgrpd_get_first(sdp);
 	*pos = rgd;
 	if (rgd != begin) /* If we didn't wrap */
 		return true;
@@ -1699,14 +1795,15 @@ static bool gfs2_select_rgrp(struct gfs2_rgrpd **pos, const struct gfs2_rgrpd *b
  * Returns: errno
  */
 
-int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested)
+int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested, u32 aflags)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_rgrpd *begin = NULL;
 	struct gfs2_blkreserv *rs = ip->i_res;
-	int error = 0, rg_locked, flags = LM_FLAG_TRY;
+	int error = 0, rg_locked, flags = 0;
 	u64 last_unlinked = NO_BLOCK;
 	int loops = 0;
+	u32 skip = 0;
 
 	if (sdp->sd_args.ar_rgrplvb)
 		flags |= GL_SKIP;
@@ -1720,6 +1817,8 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested)
 	} 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))
+		skip = gfs2_orlov_skip(ip);
 	if (rs->rs_rbm.rgd == NULL)
 		return -EBADSLT;
 
@@ -1728,13 +1827,20 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested)
 
 		if (!gfs2_glock_is_locked_by_me(rs->rs_rbm.rgd->rd_gl)) {
 			rg_locked = 0;
+			if (skip && skip--)
+				goto next_rgrp;
+			if (!gfs2_rs_active(rs) && (loops < 2) &&
+			     gfs2_rgrp_used_recently(rs, 1000) &&
+			     gfs2_rgrp_congested(rs->rs_rbm.rgd, loops))
+				goto next_rgrp;
 			error = gfs2_glock_nq_init(rs->rs_rbm.rgd->rd_gl,
 						   LM_ST_EXCLUSIVE, flags,
 						   &rs->rs_rgd_gh);
-			if (error == GLR_TRYFAILED)
-				goto next_rgrp;
 			if (unlikely(error))
 				return error;
+			if (!gfs2_rs_active(rs) && (loops < 2) &&
+			    gfs2_rgrp_congested(rs->rs_rbm.rgd, loops))
+				goto skip_rgrp;
 			if (sdp->sd_args.ar_rgrplvb) {
 				error = update_rgrp_lvb(rs->rs_rbm.rgd);
 				if (unlikely(error)) {
@@ -1781,12 +1887,13 @@ next_rgrp:
 		/* Find the next rgrp, and continue looking */
 		if (gfs2_select_rgrp(&rs->rs_rbm.rgd, begin))
 			continue;
+		if (skip)
+			continue;
 
 		/* If we've scanned all the rgrps, but found no free blocks
 		 * then this checks for some less likely conditions before
 		 * trying again.
 		 */
-		flags &= ~LM_FLAG_TRY;
 		loops++;
 		/* Check that fs hasn't grown if writing to rindex */
 		if (ip == GFS2_I(sdp->sd_rindex) && !sdp->sd_rindex_uptodate) {
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index 2407795..8421858 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -39,7 +39,8 @@ extern void gfs2_rgrp_go_unlock(struct gfs2_holder *gh);
 
 extern struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip);
 
-extern int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested);
+#define GFS2_AF_ORLOV 1
+extern int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested, u32 flags);
 extern void gfs2_inplace_release(struct gfs2_inode *ip);
 
 extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n,
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
index 8056b7b..0acbe2f 100644
--- a/fs/gfs2/sys.c
+++ b/fs/gfs2/sys.c
@@ -107,7 +107,7 @@ static ssize_t freeze_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
 	int n = simple_strtol(buf, NULL, 0);
 
 	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
+		return -EPERM;
 
 	switch (n) {
 	case 0:
@@ -135,7 +135,7 @@ static ssize_t withdraw_show(struct gfs2_sbd *sdp, char *buf)
 static ssize_t withdraw_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
 {
 	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
+		return -EPERM;
 
 	if (simple_strtol(buf, NULL, 0) != 1)
 		return -EINVAL;
@@ -150,7 +150,7 @@ static ssize_t statfs_sync_store(struct gfs2_sbd *sdp, const char *buf,
 				 size_t len)
 {
 	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
+		return -EPERM;
 
 	if (simple_strtol(buf, NULL, 0) != 1)
 		return -EINVAL;
@@ -163,7 +163,7 @@ static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf,
 				size_t len)
 {
 	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
+		return -EPERM;
 
 	if (simple_strtol(buf, NULL, 0) != 1)
 		return -EINVAL;
@@ -179,7 +179,7 @@ static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf,
 	u32 id;
 
 	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
+		return -EPERM;
 
 	id = simple_strtoul(buf, NULL, 0);
 
@@ -194,7 +194,7 @@ static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf,
 	u32 id;
 
 	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
+		return -EPERM;
 
 	id = simple_strtoul(buf, NULL, 0);
 
@@ -213,7 +213,7 @@ static ssize_t demote_rq_store(struct gfs2_sbd *sdp, const char *buf, size_t len
 	int rv;
 
 	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
+		return -EPERM;
 
 	rv = sscanf(buf, "%u:%llu %15s", &gltype, &glnum,
 		    mode);
@@ -502,7 +502,7 @@ static ssize_t quota_scale_store(struct gfs2_sbd *sdp, const char *buf,
 	unsigned int x, y;
 
 	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
+		return -EPERM;
 
 	if (sscanf(buf, "%u %u", &x, &y) != 2 || !y)
 		return -EINVAL;
@@ -521,7 +521,7 @@ static ssize_t tune_set(struct gfs2_sbd *sdp, unsigned int *field,
 	unsigned int x;
 
 	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
+		return -EPERM;
 
 	x = simple_strtoul(buf, NULL, 0);
 
diff --git a/fs/gfs2/trace_gfs2.h b/fs/gfs2/trace_gfs2.h
index bbdc78a..2ee13e8 100644
--- a/fs/gfs2/trace_gfs2.h
+++ b/fs/gfs2/trace_gfs2.h
@@ -486,7 +486,7 @@ TRACE_EVENT(gfs2_block_alloc,
 	),
 
 	TP_fast_assign(
-		__entry->dev		= ip->i_gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev		= rgd->rd_gl->gl_sbd->sd_vfs->s_dev;
 		__entry->start		= block;
 		__entry->inum		= ip->i_no_addr;
 		__entry->len		= len;
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index db330e5..76c144b 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -734,7 +734,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
 	if (error)
 		return error;
 
-	error = gfs2_inplace_reserve(ip, blks);
+	error = gfs2_inplace_reserve(ip, blks, 0);
 	if (error)
 		goto out_gunlock_q;
 
diff --git a/fs/hfsplus/Makefile b/fs/hfsplus/Makefile
index 3cc0df7..09d278b 100644
--- a/fs/hfsplus/Makefile
+++ b/fs/hfsplus/Makefile
@@ -5,5 +5,5 @@
 obj-$(CONFIG_HFSPLUS_FS) += hfsplus.o
 
 hfsplus-objs := super.o options.o inode.o ioctl.o extents.o catalog.o dir.o btree.o \
-		bnode.o brec.o bfind.o tables.o unicode.o wrapper.o bitmap.o part_tbl.o
-
+		bnode.o brec.o bfind.o tables.o unicode.o wrapper.o bitmap.o part_tbl.o \
+		attributes.o xattr.o xattr_user.o xattr_security.o xattr_trusted.o
diff --git a/fs/hfsplus/attributes.c b/fs/hfsplus/attributes.c
new file mode 100644
index 0000000..8d691f1
--- /dev/null
+++ b/fs/hfsplus/attributes.c
@@ -0,0 +1,399 @@
+/*
+ * linux/fs/hfsplus/attributes.c
+ *
+ * Vyacheslav Dubeyko <slava@dubeyko.com>
+ *
+ * Handling of records in attributes tree
+ */
+
+#include "hfsplus_fs.h"
+#include "hfsplus_raw.h"
+
+static struct kmem_cache *hfsplus_attr_tree_cachep;
+
+int hfsplus_create_attr_tree_cache(void)
+{
+	if (hfsplus_attr_tree_cachep)
+		return -EEXIST;
+
+	hfsplus_attr_tree_cachep =
+		kmem_cache_create("hfsplus_attr_cache",
+			sizeof(hfsplus_attr_entry), 0,
+			SLAB_HWCACHE_ALIGN, NULL);
+	if (!hfsplus_attr_tree_cachep)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void hfsplus_destroy_attr_tree_cache(void)
+{
+	kmem_cache_destroy(hfsplus_attr_tree_cachep);
+}
+
+int hfsplus_attr_bin_cmp_key(const hfsplus_btree_key *k1,
+				const hfsplus_btree_key *k2)
+{
+	__be32 k1_cnid, k2_cnid;
+
+	k1_cnid = k1->attr.cnid;
+	k2_cnid = k2->attr.cnid;
+	if (k1_cnid != k2_cnid)
+		return be32_to_cpu(k1_cnid) < be32_to_cpu(k2_cnid) ? -1 : 1;
+
+	return hfsplus_strcmp(
+			(const struct hfsplus_unistr *)&k1->attr.key_name,
+			(const struct hfsplus_unistr *)&k2->attr.key_name);
+}
+
+int hfsplus_attr_build_key(struct super_block *sb, hfsplus_btree_key *key,
+			u32 cnid, const char *name)
+{
+	int len;
+
+	memset(key, 0, sizeof(struct hfsplus_attr_key));
+	key->attr.cnid = cpu_to_be32(cnid);
+	if (name) {
+		len = strlen(name);
+		if (len > HFSPLUS_ATTR_MAX_STRLEN) {
+			printk(KERN_ERR "hfs: invalid xattr name's length\n");
+			return -EINVAL;
+		}
+		hfsplus_asc2uni(sb,
+				(struct hfsplus_unistr *)&key->attr.key_name,
+				HFSPLUS_ATTR_MAX_STRLEN, name, len);
+		len = be16_to_cpu(key->attr.key_name.length);
+	} else {
+		key->attr.key_name.length = 0;
+		len = 0;
+	}
+
+	/* The length of the key, as stored in key_len field, does not include
+	 * the size of the key_len field itself.
+	 * So, offsetof(hfsplus_attr_key, key_name) is a trick because
+	 * it takes into consideration key_len field (__be16) of
+	 * hfsplus_attr_key structure instead of length field (__be16) of
+	 * hfsplus_attr_unistr structure.
+	 */
+	key->key_len =
+		cpu_to_be16(offsetof(struct hfsplus_attr_key, key_name) +
+				2 * len);
+
+	return 0;
+}
+
+void hfsplus_attr_build_key_uni(hfsplus_btree_key *key,
+					u32 cnid,
+					struct hfsplus_attr_unistr *name)
+{
+	int ustrlen;
+
+	memset(key, 0, sizeof(struct hfsplus_attr_key));
+	ustrlen = be16_to_cpu(name->length);
+	key->attr.cnid = cpu_to_be32(cnid);
+	key->attr.key_name.length = cpu_to_be16(ustrlen);
+	ustrlen *= 2;
+	memcpy(key->attr.key_name.unicode, name->unicode, ustrlen);
+
+	/* The length of the key, as stored in key_len field, does not include
+	 * the size of the key_len field itself.
+	 * So, offsetof(hfsplus_attr_key, key_name) is a trick because
+	 * it takes into consideration key_len field (__be16) of
+	 * hfsplus_attr_key structure instead of length field (__be16) of
+	 * hfsplus_attr_unistr structure.
+	 */
+	key->key_len =
+		cpu_to_be16(offsetof(struct hfsplus_attr_key, key_name) +
+				ustrlen);
+}
+
+hfsplus_attr_entry *hfsplus_alloc_attr_entry(void)
+{
+	return kmem_cache_alloc(hfsplus_attr_tree_cachep, GFP_KERNEL);
+}
+
+void hfsplus_destroy_attr_entry(hfsplus_attr_entry *entry)
+{
+	if (entry)
+		kmem_cache_free(hfsplus_attr_tree_cachep, entry);
+}
+
+#define HFSPLUS_INVALID_ATTR_RECORD -1
+
+static int hfsplus_attr_build_record(hfsplus_attr_entry *entry, int record_type,
+				u32 cnid, const void *value, size_t size)
+{
+	if (record_type == HFSPLUS_ATTR_FORK_DATA) {
+		/*
+		 * Mac OS X supports only inline data attributes.
+		 * Do nothing
+		 */
+		memset(entry, 0, sizeof(*entry));
+		return sizeof(struct hfsplus_attr_fork_data);
+	} else if (record_type == HFSPLUS_ATTR_EXTENTS) {
+		/*
+		 * Mac OS X supports only inline data attributes.
+		 * Do nothing.
+		 */
+		memset(entry, 0, sizeof(*entry));
+		return sizeof(struct hfsplus_attr_extents);
+	} else if (record_type == HFSPLUS_ATTR_INLINE_DATA) {
+		u16 len;
+
+		memset(entry, 0, sizeof(struct hfsplus_attr_inline_data));
+		entry->inline_data.record_type = cpu_to_be32(record_type);
+		if (size <= HFSPLUS_MAX_INLINE_DATA_SIZE)
+			len = size;
+		else
+			return HFSPLUS_INVALID_ATTR_RECORD;
+		entry->inline_data.length = cpu_to_be16(len);
+		memcpy(entry->inline_data.raw_bytes, value, len);
+		/*
+		 * Align len on two-byte boundary.
+		 * It needs to add pad byte if we have odd len.
+		 */
+		len = round_up(len, 2);
+		return offsetof(struct hfsplus_attr_inline_data, raw_bytes) +
+					len;
+	} else /* invalid input */
+		memset(entry, 0, sizeof(*entry));
+
+	return HFSPLUS_INVALID_ATTR_RECORD;
+}
+
+int hfsplus_find_attr(struct super_block *sb, u32 cnid,
+			const char *name, struct hfs_find_data *fd)
+{
+	int err = 0;
+
+	dprint(DBG_ATTR_MOD, "find_attr: %s,%d\n", name ? name : NULL, cnid);
+
+	if (!HFSPLUS_SB(sb)->attr_tree) {
+		printk(KERN_ERR "hfs: attributes file doesn't exist\n");
+		return -EINVAL;
+	}
+
+	if (name) {
+		err = hfsplus_attr_build_key(sb, fd->search_key, cnid, name);
+		if (err)
+			goto failed_find_attr;
+		err = hfs_brec_find(fd, hfs_find_rec_by_key);
+		if (err)
+			goto failed_find_attr;
+	} else {
+		err = hfsplus_attr_build_key(sb, fd->search_key, cnid, NULL);
+		if (err)
+			goto failed_find_attr;
+		err = hfs_brec_find(fd, hfs_find_1st_rec_by_cnid);
+		if (err)
+			goto failed_find_attr;
+	}
+
+failed_find_attr:
+	return err;
+}
+
+int hfsplus_attr_exists(struct inode *inode, const char *name)
+{
+	int err = 0;
+	struct super_block *sb = inode->i_sb;
+	struct hfs_find_data fd;
+
+	if (!HFSPLUS_SB(sb)->attr_tree)
+		return 0;
+
+	err = hfs_find_init(HFSPLUS_SB(sb)->attr_tree, &fd);
+	if (err)
+		return 0;
+
+	err = hfsplus_find_attr(sb, inode->i_ino, name, &fd);
+	if (err)
+		goto attr_not_found;
+
+	hfs_find_exit(&fd);
+	return 1;
+
+attr_not_found:
+	hfs_find_exit(&fd);
+	return 0;
+}
+
+int hfsplus_create_attr(struct inode *inode,
+				const char *name,
+				const void *value, size_t size)
+{
+	struct super_block *sb = inode->i_sb;
+	struct hfs_find_data fd;
+	hfsplus_attr_entry *entry_ptr;
+	int entry_size;
+	int err;
+
+	dprint(DBG_ATTR_MOD, "create_attr: %s,%ld\n",
+		name ? name : NULL, inode->i_ino);
+
+	if (!HFSPLUS_SB(sb)->attr_tree) {
+		printk(KERN_ERR "hfs: attributes file doesn't exist\n");
+		return -EINVAL;
+	}
+
+	entry_ptr = hfsplus_alloc_attr_entry();
+	if (!entry_ptr)
+		return -ENOMEM;
+
+	err = hfs_find_init(HFSPLUS_SB(sb)->attr_tree, &fd);
+	if (err)
+		goto failed_init_create_attr;
+
+	if (name) {
+		err = hfsplus_attr_build_key(sb, fd.search_key,
+						inode->i_ino, name);
+		if (err)
+			goto failed_create_attr;
+	} else {
+		err = -EINVAL;
+		goto failed_create_attr;
+	}
+
+	/* Mac OS X supports only inline data attributes. */
+	entry_size = hfsplus_attr_build_record(entry_ptr,
+					HFSPLUS_ATTR_INLINE_DATA,
+					inode->i_ino,
+					value, size);
+	if (entry_size == HFSPLUS_INVALID_ATTR_RECORD) {
+		err = -EINVAL;
+		goto failed_create_attr;
+	}
+
+	err = hfs_brec_find(&fd, hfs_find_rec_by_key);
+	if (err != -ENOENT) {
+		if (!err)
+			err = -EEXIST;
+		goto failed_create_attr;
+	}
+
+	err = hfs_brec_insert(&fd, entry_ptr, entry_size);
+	if (err)
+		goto failed_create_attr;
+
+	hfsplus_mark_inode_dirty(inode, HFSPLUS_I_ATTR_DIRTY);
+
+failed_create_attr:
+	hfs_find_exit(&fd);
+
+failed_init_create_attr:
+	hfsplus_destroy_attr_entry(entry_ptr);
+	return err;
+}
+
+static int __hfsplus_delete_attr(struct inode *inode, u32 cnid,
+					struct hfs_find_data *fd)
+{
+	int err = 0;
+	__be32 found_cnid, record_type;
+
+	hfs_bnode_read(fd->bnode, &found_cnid,
+			fd->keyoffset +
+			offsetof(struct hfsplus_attr_key, cnid),
+			sizeof(__be32));
+	if (cnid != be32_to_cpu(found_cnid))
+		return -ENOENT;
+
+	hfs_bnode_read(fd->bnode, &record_type,
+			fd->entryoffset, sizeof(record_type));
+
+	switch (be32_to_cpu(record_type)) {
+	case HFSPLUS_ATTR_INLINE_DATA:
+		/* All is OK. Do nothing. */
+		break;
+	case HFSPLUS_ATTR_FORK_DATA:
+	case HFSPLUS_ATTR_EXTENTS:
+		printk(KERN_ERR "hfs: only inline data xattr are supported\n");
+		return -EOPNOTSUPP;
+	default:
+		printk(KERN_ERR "hfs: invalid extended attribute record\n");
+		return -ENOENT;
+	}
+
+	err = hfs_brec_remove(fd);
+	if (err)
+		return err;
+
+	hfsplus_mark_inode_dirty(inode, HFSPLUS_I_ATTR_DIRTY);
+	return err;
+}
+
+int hfsplus_delete_attr(struct inode *inode, const char *name)
+{
+	int err = 0;
+	struct super_block *sb = inode->i_sb;
+	struct hfs_find_data fd;
+
+	dprint(DBG_ATTR_MOD, "delete_attr: %s,%ld\n",
+		name ? name : NULL, inode->i_ino);
+
+	if (!HFSPLUS_SB(sb)->attr_tree) {
+		printk(KERN_ERR "hfs: attributes file doesn't exist\n");
+		return -EINVAL;
+	}
+
+	err = hfs_find_init(HFSPLUS_SB(sb)->attr_tree, &fd);
+	if (err)
+		return err;
+
+	if (name) {
+		err = hfsplus_attr_build_key(sb, fd.search_key,
+						inode->i_ino, name);
+		if (err)
+			goto out;
+	} else {
+		printk(KERN_ERR "hfs: invalid extended attribute name\n");
+		err = -EINVAL;
+		goto out;
+	}
+
+	err = hfs_brec_find(&fd, hfs_find_rec_by_key);
+	if (err)
+		goto out;
+
+	err = __hfsplus_delete_attr(inode, inode->i_ino, &fd);
+	if (err)
+		goto out;
+
+out:
+	hfs_find_exit(&fd);
+	return err;
+}
+
+int hfsplus_delete_all_attrs(struct inode *dir, u32 cnid)
+{
+	int err = 0;
+	struct hfs_find_data fd;
+
+	dprint(DBG_ATTR_MOD, "delete_all_attrs: %d\n", cnid);
+
+	if (!HFSPLUS_SB(dir->i_sb)->attr_tree) {
+		printk(KERN_ERR "hfs: attributes file doesn't exist\n");
+		return -EINVAL;
+	}
+
+	err = hfs_find_init(HFSPLUS_SB(dir->i_sb)->attr_tree, &fd);
+	if (err)
+		return err;
+
+	for (;;) {
+		err = hfsplus_find_attr(dir->i_sb, cnid, NULL, &fd);
+		if (err) {
+			if (err != -ENOENT)
+				printk(KERN_ERR "hfs: xattr search failed.\n");
+			goto end_delete_all;
+		}
+
+		err = __hfsplus_delete_attr(dir, cnid, &fd);
+		if (err)
+			goto end_delete_all;
+	}
+
+end_delete_all:
+	hfs_find_exit(&fd);
+	return err;
+}
diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
index 5d799c1..d73c98d 100644
--- a/fs/hfsplus/bfind.c
+++ b/fs/hfsplus/bfind.c
@@ -24,7 +24,19 @@ int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd)
 	fd->key = ptr + tree->max_key_len + 2;
 	dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n",
 		tree->cnid, __builtin_return_address(0));
-	mutex_lock(&tree->tree_lock);
+	switch (tree->cnid) {
+	case HFSPLUS_CAT_CNID:
+		mutex_lock_nested(&tree->tree_lock, CATALOG_BTREE_MUTEX);
+		break;
+	case HFSPLUS_EXT_CNID:
+		mutex_lock_nested(&tree->tree_lock, EXTENTS_BTREE_MUTEX);
+		break;
+	case HFSPLUS_ATTR_CNID:
+		mutex_lock_nested(&tree->tree_lock, ATTR_BTREE_MUTEX);
+		break;
+	default:
+		BUG();
+	}
 	return 0;
 }
 
@@ -38,15 +50,73 @@ void hfs_find_exit(struct hfs_find_data *fd)
 	fd->tree = NULL;
 }
 
-/* Find the record in bnode that best matches key (not greater than...)*/
-int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
+int hfs_find_1st_rec_by_cnid(struct hfs_bnode *bnode,
+				struct hfs_find_data *fd,
+				int *begin,
+				int *end,
+				int *cur_rec)
+{
+	__be32 cur_cnid, search_cnid;
+
+	if (bnode->tree->cnid == HFSPLUS_EXT_CNID) {
+		cur_cnid = fd->key->ext.cnid;
+		search_cnid = fd->search_key->ext.cnid;
+	} else if (bnode->tree->cnid == HFSPLUS_CAT_CNID) {
+		cur_cnid = fd->key->cat.parent;
+		search_cnid = fd->search_key->cat.parent;
+	} else if (bnode->tree->cnid == HFSPLUS_ATTR_CNID) {
+		cur_cnid = fd->key->attr.cnid;
+		search_cnid = fd->search_key->attr.cnid;
+	} else
+		BUG();
+
+	if (cur_cnid == search_cnid) {
+		(*end) = (*cur_rec);
+		if ((*begin) == (*end))
+			return 1;
+	} else {
+		if (be32_to_cpu(cur_cnid) < be32_to_cpu(search_cnid))
+			(*begin) = (*cur_rec) + 1;
+		else
+			(*end) = (*cur_rec) - 1;
+	}
+
+	return 0;
+}
+
+int hfs_find_rec_by_key(struct hfs_bnode *bnode,
+				struct hfs_find_data *fd,
+				int *begin,
+				int *end,
+				int *cur_rec)
 {
 	int cmpval;
+
+	cmpval = bnode->tree->keycmp(fd->key, fd->search_key);
+	if (!cmpval) {
+		(*end) = (*cur_rec);
+		return 1;
+	}
+	if (cmpval < 0)
+		(*begin) = (*cur_rec) + 1;
+	else
+		*(end) = (*cur_rec) - 1;
+
+	return 0;
+}
+
+/* Find the record in bnode that best matches key (not greater than...)*/
+int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd,
+					search_strategy_t rec_found)
+{
 	u16 off, len, keylen;
 	int rec;
 	int b, e;
 	int res;
 
+	if (!rec_found)
+		BUG();
+
 	b = 0;
 	e = bnode->num_recs - 1;
 	res = -ENOENT;
@@ -59,17 +129,12 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
 			goto fail;
 		}
 		hfs_bnode_read(bnode, fd->key, off, keylen);
-		cmpval = bnode->tree->keycmp(fd->key, fd->search_key);
-		if (!cmpval) {
-			e = rec;
+		if (rec_found(bnode, fd, &b, &e, &rec)) {
 			res = 0;
 			goto done;
 		}
-		if (cmpval < 0)
-			b = rec + 1;
-		else
-			e = rec - 1;
 	} while (b <= e);
+
 	if (rec != e && e >= 0) {
 		len = hfs_brec_lenoff(bnode, e, &off);
 		keylen = hfs_brec_keylen(bnode, e);
@@ -79,19 +144,21 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
 		}
 		hfs_bnode_read(bnode, fd->key, off, keylen);
 	}
+
 done:
 	fd->record = e;
 	fd->keyoffset = off;
 	fd->keylength = keylen;
 	fd->entryoffset = off + keylen;
 	fd->entrylength = len - keylen;
+
 fail:
 	return res;
 }
 
 /* Traverse a B*Tree from the root to a leaf finding best fit to key */
 /* Return allocated copy of node found, set recnum to best record */
-int hfs_brec_find(struct hfs_find_data *fd)
+int hfs_brec_find(struct hfs_find_data *fd, search_strategy_t do_key_compare)
 {
 	struct hfs_btree *tree;
 	struct hfs_bnode *bnode;
@@ -122,7 +189,7 @@ int hfs_brec_find(struct hfs_find_data *fd)
 			goto invalid;
 		bnode->parent = parent;
 
-		res = __hfs_brec_find(bnode, fd);
+		res = __hfs_brec_find(bnode, fd, do_key_compare);
 		if (!height)
 			break;
 		if (fd->record < 0)
@@ -149,7 +216,7 @@ int hfs_brec_read(struct hfs_find_data *fd, void *rec, int rec_len)
 {
 	int res;
 
-	res = hfs_brec_find(fd);
+	res = hfs_brec_find(fd, hfs_find_rec_by_key);
 	if (res)
 		return res;
 	if (fd->entrylength > rec_len)
diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c
index 4cfbe2e..6feefc0 100644
--- a/fs/hfsplus/bitmap.c
+++ b/fs/hfsplus/bitmap.c
@@ -176,12 +176,14 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
 	dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count);
 	/* are all of the bits in range? */
 	if ((offset + count) > sbi->total_blocks)
-		return -2;
+		return -ENOENT;
 
 	mutex_lock(&sbi->alloc_mutex);
 	mapping = sbi->alloc_file->i_mapping;
 	pnr = offset / PAGE_CACHE_BITS;
 	page = read_mapping_page(mapping, pnr, NULL);
+	if (IS_ERR(page))
+		goto kaboom;
 	pptr = kmap(page);
 	curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
 	end = pptr + PAGE_CACHE_BITS / 32;
@@ -214,6 +216,8 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
 		set_page_dirty(page);
 		kunmap(page);
 		page = read_mapping_page(mapping, ++pnr, NULL);
+		if (IS_ERR(page))
+			goto kaboom;
 		pptr = kmap(page);
 		curr = pptr;
 		end = pptr + PAGE_CACHE_BITS / 32;
@@ -232,4 +236,11 @@ out:
 	mutex_unlock(&sbi->alloc_mutex);
 
 	return 0;
+
+kaboom:
+	printk(KERN_CRIT "hfsplus: unable to mark blocks free: error %ld\n",
+			PTR_ERR(page));
+	mutex_unlock(&sbi->alloc_mutex);
+
+	return -EIO;
 }
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 1c42cc5..5c125ce 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -62,7 +62,8 @@ void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off)
 
 	tree = node->tree;
 	if (node->type == HFS_NODE_LEAF ||
-	    tree->attributes & HFS_TREE_VARIDXKEYS)
+	    tree->attributes & HFS_TREE_VARIDXKEYS ||
+	    node->tree->cnid == HFSPLUS_ATTR_CNID)
 		key_len = hfs_bnode_read_u16(node, off) + 2;
 	else
 		key_len = tree->max_key_len + 2;
@@ -314,7 +315,8 @@ void hfs_bnode_dump(struct hfs_bnode *node)
 		if (i && node->type == HFS_NODE_INDEX) {
 			int tmp;
 
-			if (node->tree->attributes & HFS_TREE_VARIDXKEYS)
+			if (node->tree->attributes & HFS_TREE_VARIDXKEYS ||
+					node->tree->cnid == HFSPLUS_ATTR_CNID)
 				tmp = hfs_bnode_read_u16(node, key_off) + 2;
 			else
 				tmp = node->tree->max_key_len + 2;
diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c
index 2a734cf..298d4e4 100644
--- a/fs/hfsplus/brec.c
+++ b/fs/hfsplus/brec.c
@@ -36,7 +36,8 @@ u16 hfs_brec_keylen(struct hfs_bnode *node, u16 rec)
 		return 0;
 
 	if ((node->type == HFS_NODE_INDEX) &&
-	   !(node->tree->attributes & HFS_TREE_VARIDXKEYS)) {
+	   !(node->tree->attributes & HFS_TREE_VARIDXKEYS) &&
+	   (node->tree->cnid != HFSPLUS_ATTR_CNID)) {
 		retval = node->tree->max_key_len + 2;
 	} else {
 		recoff = hfs_bnode_read_u16(node,
@@ -151,12 +152,13 @@ skip:
 
 		/* get index key */
 		hfs_bnode_read_key(new_node, fd->search_key, 14);
-		__hfs_brec_find(fd->bnode, fd);
+		__hfs_brec_find(fd->bnode, fd, hfs_find_rec_by_key);
 
 		hfs_bnode_put(new_node);
 		new_node = NULL;
 
-		if (tree->attributes & HFS_TREE_VARIDXKEYS)
+		if ((tree->attributes & HFS_TREE_VARIDXKEYS) ||
+				(tree->cnid == HFSPLUS_ATTR_CNID))
 			key_len = be16_to_cpu(fd->search_key->key_len) + 2;
 		else {
 			fd->search_key->key_len =
@@ -201,7 +203,7 @@ again:
 		hfs_bnode_put(node);
 		node = fd->bnode = parent;
 
-		__hfs_brec_find(node, fd);
+		__hfs_brec_find(node, fd, hfs_find_rec_by_key);
 		goto again;
 	}
 	hfs_bnode_write_u16(node,
@@ -367,12 +369,13 @@ again:
 	parent = hfs_bnode_find(tree, node->parent);
 	if (IS_ERR(parent))
 		return PTR_ERR(parent);
-	__hfs_brec_find(parent, fd);
+	__hfs_brec_find(parent, fd, hfs_find_rec_by_key);
 	hfs_bnode_dump(parent);
 	rec = fd->record;
 
 	/* size difference between old and new key */
-	if (tree->attributes & HFS_TREE_VARIDXKEYS)
+	if ((tree->attributes & HFS_TREE_VARIDXKEYS) ||
+				(tree->cnid == HFSPLUS_ATTR_CNID))
 		newkeylen = hfs_bnode_read_u16(node, 14) + 2;
 	else
 		fd->keylength = newkeylen = tree->max_key_len + 2;
@@ -427,7 +430,7 @@ skip:
 		hfs_bnode_read_key(new_node, fd->search_key, 14);
 		cnid = cpu_to_be32(new_node->this);
 
-		__hfs_brec_find(fd->bnode, fd);
+		__hfs_brec_find(fd->bnode, fd, hfs_find_rec_by_key);
 		hfs_brec_insert(fd, &cnid, sizeof(cnid));
 		hfs_bnode_put(fd->bnode);
 		hfs_bnode_put(new_node);
@@ -495,13 +498,15 @@ static int hfs_btree_inc_height(struct hfs_btree *tree)
 		/* insert old root idx into new root */
 		node->parent = tree->root;
 		if (node->type == HFS_NODE_LEAF ||
-		    tree->attributes & HFS_TREE_VARIDXKEYS)
+				tree->attributes & HFS_TREE_VARIDXKEYS ||
+				tree->cnid == HFSPLUS_ATTR_CNID)
 			key_size = hfs_bnode_read_u16(node, 14) + 2;
 		else
 			key_size = tree->max_key_len + 2;
 		hfs_bnode_copy(new_node, 14, node, 14, key_size);
 
-		if (!(tree->attributes & HFS_TREE_VARIDXKEYS)) {
+		if (!(tree->attributes & HFS_TREE_VARIDXKEYS) &&
+				(tree->cnid != HFSPLUS_ATTR_CNID)) {
 			key_size = tree->max_key_len + 2;
 			hfs_bnode_write_u16(new_node, 14, tree->max_key_len);
 		}
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index 21023d9..44294af 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -98,6 +98,14 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
 			set_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
 		}
 		break;
+	case HFSPLUS_ATTR_CNID:
+		if (tree->max_key_len != HFSPLUS_ATTR_KEYLEN - sizeof(u16)) {
+			printk(KERN_ERR "hfs: invalid attributes max_key_len %d\n",
+				tree->max_key_len);
+			goto fail_page;
+		}
+		tree->keycmp = hfsplus_attr_bin_cmp_key;
+		break;
 	default:
 		printk(KERN_ERR "hfs: unknown B*Tree requested\n");
 		goto fail_page;
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 798d9c4..840d71e 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -45,7 +45,8 @@ void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *key,
 
 	key->cat.parent = cpu_to_be32(parent);
 	if (str) {
-		hfsplus_asc2uni(sb, &key->cat.name, str->name, str->len);
+		hfsplus_asc2uni(sb, &key->cat.name, HFSPLUS_MAX_STRLEN,
+					str->name, str->len);
 		len = be16_to_cpu(key->cat.name.length);
 	} else {
 		key->cat.name.length = 0;
@@ -167,7 +168,8 @@ static int hfsplus_fill_cat_thread(struct super_block *sb,
 	entry->type = cpu_to_be16(type);
 	entry->thread.reserved = 0;
 	entry->thread.parentID = cpu_to_be32(parentid);
-	hfsplus_asc2uni(sb, &entry->thread.nodeName, str->name, str->len);
+	hfsplus_asc2uni(sb, &entry->thread.nodeName, HFSPLUS_MAX_STRLEN,
+				str->name, str->len);
 	return 10 + be16_to_cpu(entry->thread.nodeName.length) * 2;
 }
 
@@ -198,7 +200,7 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid,
 	hfsplus_cat_build_key_uni(fd->search_key,
 		be32_to_cpu(tmp.thread.parentID),
 		&tmp.thread.nodeName);
-	return hfs_brec_find(fd);
+	return hfs_brec_find(fd, hfs_find_rec_by_key);
 }
 
 int hfsplus_create_cat(u32 cnid, struct inode *dir,
@@ -221,7 +223,7 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir,
 		S_ISDIR(inode->i_mode) ?
 			HFSPLUS_FOLDER_THREAD : HFSPLUS_FILE_THREAD,
 		dir->i_ino, str);
-	err = hfs_brec_find(&fd);
+	err = hfs_brec_find(&fd, hfs_find_rec_by_key);
 	if (err != -ENOENT) {
 		if (!err)
 			err = -EEXIST;
@@ -233,7 +235,7 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir,
 
 	hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, str);
 	entry_size = hfsplus_cat_build_record(&entry, cnid, inode);
-	err = hfs_brec_find(&fd);
+	err = hfs_brec_find(&fd, hfs_find_rec_by_key);
 	if (err != -ENOENT) {
 		/* panic? */
 		if (!err)
@@ -253,7 +255,7 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir,
 
 err1:
 	hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
-	if (!hfs_brec_find(&fd))
+	if (!hfs_brec_find(&fd, hfs_find_rec_by_key))
 		hfs_brec_remove(&fd);
 err2:
 	hfs_find_exit(&fd);
@@ -279,7 +281,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
 		int len;
 
 		hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
-		err = hfs_brec_find(&fd);
+		err = hfs_brec_find(&fd, hfs_find_rec_by_key);
 		if (err)
 			goto out;
 
@@ -296,7 +298,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
 	} else
 		hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, str);
 
-	err = hfs_brec_find(&fd);
+	err = hfs_brec_find(&fd, hfs_find_rec_by_key);
 	if (err)
 		goto out;
 
@@ -326,7 +328,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
 		goto out;
 
 	hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
-	err = hfs_brec_find(&fd);
+	err = hfs_brec_find(&fd, hfs_find_rec_by_key);
 	if (err)
 		goto out;
 
@@ -337,6 +339,12 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
 	dir->i_size--;
 	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
 	hfsplus_mark_inode_dirty(dir, HFSPLUS_I_CAT_DIRTY);
+
+	if (type == HFSPLUS_FILE || type == HFSPLUS_FOLDER) {
+		if (HFSPLUS_SB(sb)->attr_tree)
+			hfsplus_delete_all_attrs(dir, cnid);
+	}
+
 out:
 	hfs_find_exit(&fd);
 
@@ -363,7 +371,7 @@ int hfsplus_rename_cat(u32 cnid,
 
 	/* find the old dir entry and read the data */
 	hfsplus_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name);
-	err = hfs_brec_find(&src_fd);
+	err = hfs_brec_find(&src_fd, hfs_find_rec_by_key);
 	if (err)
 		goto out;
 	if (src_fd.entrylength > sizeof(entry) || src_fd.entrylength < 0) {
@@ -376,7 +384,7 @@ int hfsplus_rename_cat(u32 cnid,
 
 	/* create new dir entry with the data from the old entry */
 	hfsplus_cat_build_key(sb, dst_fd.search_key, dst_dir->i_ino, dst_name);
-	err = hfs_brec_find(&dst_fd);
+	err = hfs_brec_find(&dst_fd, hfs_find_rec_by_key);
 	if (err != -ENOENT) {
 		if (!err)
 			err = -EEXIST;
@@ -391,7 +399,7 @@ int hfsplus_rename_cat(u32 cnid,
 
 	/* finally remove the old entry */
 	hfsplus_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name);
-	err = hfs_brec_find(&src_fd);
+	err = hfs_brec_find(&src_fd, hfs_find_rec_by_key);
 	if (err)
 		goto out;
 	err = hfs_brec_remove(&src_fd);
@@ -402,7 +410,7 @@ int hfsplus_rename_cat(u32 cnid,
 
 	/* remove old thread entry */
 	hfsplus_cat_build_key(sb, src_fd.search_key, cnid, NULL);
-	err = hfs_brec_find(&src_fd);
+	err = hfs_brec_find(&src_fd, hfs_find_rec_by_key);
 	if (err)
 		goto out;
 	type = hfs_bnode_read_u16(src_fd.bnode, src_fd.entryoffset);
@@ -414,7 +422,7 @@ int hfsplus_rename_cat(u32 cnid,
 	hfsplus_cat_build_key(sb, dst_fd.search_key, cnid, NULL);
 	entry_size = hfsplus_fill_cat_thread(sb, &entry, type,
 		dst_dir->i_ino, dst_name);
-	err = hfs_brec_find(&dst_fd);
+	err = hfs_brec_find(&dst_fd, hfs_find_rec_by_key);
 	if (err != -ENOENT) {
 		if (!err)
 			err = -EEXIST;
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 6b9f921..47699d8 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -15,6 +15,7 @@
 
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
+#include "xattr.h"
 
 static inline void hfsplus_instantiate(struct dentry *dentry,
 				       struct inode *inode, u32 cnid)
@@ -138,7 +139,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
 	if (err)
 		return err;
 	hfsplus_cat_build_key(sb, fd.search_key, inode->i_ino, NULL);
-	err = hfs_brec_find(&fd);
+	err = hfs_brec_find(&fd, hfs_find_rec_by_key);
 	if (err)
 		goto out;
 
@@ -421,6 +422,15 @@ static int hfsplus_symlink(struct inode *dir, struct dentry *dentry,
 	if (res)
 		goto out_err;
 
+	res = hfsplus_init_inode_security(inode, dir, &dentry->d_name);
+	if (res == -EOPNOTSUPP)
+		res = 0; /* Operation is not supported. */
+	else if (res) {
+		/* Try to delete anyway without error analysis. */
+		hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name);
+		goto out_err;
+	}
+
 	hfsplus_instantiate(dentry, inode, inode->i_ino);
 	mark_inode_dirty(inode);
 	goto out;
@@ -450,15 +460,26 @@ static int hfsplus_mknod(struct inode *dir, struct dentry *dentry,
 		init_special_inode(inode, mode, rdev);
 
 	res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
-	if (res) {
-		clear_nlink(inode);
-		hfsplus_delete_inode(inode);
-		iput(inode);
-		goto out;
+	if (res)
+		goto failed_mknod;
+
+	res = hfsplus_init_inode_security(inode, dir, &dentry->d_name);
+	if (res == -EOPNOTSUPP)
+		res = 0; /* Operation is not supported. */
+	else if (res) {
+		/* Try to delete anyway without error analysis. */
+		hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name);
+		goto failed_mknod;
 	}
 
 	hfsplus_instantiate(dentry, inode, inode->i_ino);
 	mark_inode_dirty(inode);
+	goto out;
+
+failed_mknod:
+	clear_nlink(inode);
+	hfsplus_delete_inode(inode);
+	iput(inode);
 out:
 	mutex_unlock(&sbi->vh_mutex);
 	return res;
@@ -499,15 +520,19 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry,
 }
 
 const struct inode_operations hfsplus_dir_inode_operations = {
-	.lookup		= hfsplus_lookup,
-	.create		= hfsplus_create,
-	.link		= hfsplus_link,
-	.unlink		= hfsplus_unlink,
-	.mkdir		= hfsplus_mkdir,
-	.rmdir		= hfsplus_rmdir,
-	.symlink	= hfsplus_symlink,
-	.mknod		= hfsplus_mknod,
-	.rename		= hfsplus_rename,
+	.lookup			= hfsplus_lookup,
+	.create			= hfsplus_create,
+	.link			= hfsplus_link,
+	.unlink			= hfsplus_unlink,
+	.mkdir			= hfsplus_mkdir,
+	.rmdir			= hfsplus_rmdir,
+	.symlink		= hfsplus_symlink,
+	.mknod			= hfsplus_mknod,
+	.rename			= hfsplus_rename,
+	.setxattr		= generic_setxattr,
+	.getxattr		= generic_getxattr,
+	.listxattr		= hfsplus_listxattr,
+	.removexattr		= hfsplus_removexattr,
 };
 
 const struct file_operations hfsplus_dir_operations = {
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index 5849e3e..a94f0f7 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -95,7 +95,7 @@ static void __hfsplus_ext_write_extent(struct inode *inode,
 			      HFSPLUS_IS_RSRC(inode) ?
 				HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA);
 
-	res = hfs_brec_find(fd);
+	res = hfs_brec_find(fd, hfs_find_rec_by_key);
 	if (hip->extent_state & HFSPLUS_EXT_NEW) {
 		if (res != -ENOENT)
 			return;
@@ -154,7 +154,7 @@ static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd,
 
 	hfsplus_ext_build_key(fd->search_key, cnid, block, type);
 	fd->key->ext.cnid = 0;
-	res = hfs_brec_find(fd);
+	res = hfs_brec_find(fd, hfs_find_rec_by_key);
 	if (res && res != -ENOENT)
 		return res;
 	if (fd->key->ext.cnid != fd->search_key->ext.cnid ||
@@ -329,6 +329,7 @@ static int hfsplus_free_extents(struct super_block *sb,
 {
 	u32 count, start;
 	int i;
+	int err = 0;
 
 	hfsplus_dump_extent(extent);
 	for (i = 0; i < 8; extent++, i++) {
@@ -345,18 +346,33 @@ found:
 	for (;;) {
 		start = be32_to_cpu(extent->start_block);
 		if (count <= block_nr) {
-			hfsplus_block_free(sb, start, count);
+			err = hfsplus_block_free(sb, start, count);
+			if (err) {
+				printk(KERN_ERR "hfs: can't free extent\n");
+				dprint(DBG_EXTENT, " start: %u count: %u\n",
+					start, count);
+			}
 			extent->block_count = 0;
 			extent->start_block = 0;
 			block_nr -= count;
 		} else {
 			count -= block_nr;
-			hfsplus_block_free(sb, start + count, block_nr);
+			err = hfsplus_block_free(sb, start + count, block_nr);
+			if (err) {
+				printk(KERN_ERR "hfs: can't free extent\n");
+				dprint(DBG_EXTENT, " start: %u count: %u\n",
+					start, count);
+			}
 			extent->block_count = cpu_to_be32(count);
 			block_nr = 0;
 		}
-		if (!block_nr || !i)
-			return 0;
+		if (!block_nr || !i) {
+			/*
+			 * Try to free all extents and
+			 * return only last error
+			 */
+			return err;
+		}
 		i--;
 		extent--;
 		count = be32_to_cpu(extent->block_count);
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index c571de2..ae68eff 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -23,6 +23,7 @@
 #define DBG_SUPER	0x00000010
 #define DBG_EXTENT	0x00000020
 #define DBG_BITMAP	0x00000040
+#define DBG_ATTR_MOD	0x00000080
 
 #if 0
 #define DBG_MASK	(DBG_EXTENT|DBG_INODE|DBG_BNODE_MOD)
@@ -46,6 +47,13 @@ typedef int (*btree_keycmp)(const hfsplus_btree_key *,
 
 #define NODE_HASH_SIZE	256
 
+/* B-tree mutex nested subclasses */
+enum hfsplus_btree_mutex_classes {
+	CATALOG_BTREE_MUTEX,
+	EXTENTS_BTREE_MUTEX,
+	ATTR_BTREE_MUTEX,
+};
+
 /* An HFS+ BTree held in memory */
 struct hfs_btree {
 	struct super_block *sb;
@@ -223,6 +231,7 @@ struct hfsplus_inode_info {
 #define HFSPLUS_I_CAT_DIRTY	1	/* has changes in the catalog tree */
 #define HFSPLUS_I_EXT_DIRTY	2	/* has changes in the extent tree */
 #define HFSPLUS_I_ALLOC_DIRTY	3	/* has changes in the allocation file */
+#define HFSPLUS_I_ATTR_DIRTY	4	/* has changes in the attributes tree */
 
 #define HFSPLUS_IS_RSRC(inode) \
 	test_bit(HFSPLUS_I_RSRC, &HFSPLUS_I(inode)->flags)
@@ -302,7 +311,7 @@ static inline unsigned short hfsplus_min_io_size(struct super_block *sb)
 #define hfs_brec_remove hfsplus_brec_remove
 #define hfs_find_init hfsplus_find_init
 #define hfs_find_exit hfsplus_find_exit
-#define __hfs_brec_find __hplusfs_brec_find
+#define __hfs_brec_find __hfsplus_brec_find
 #define hfs_brec_find hfsplus_brec_find
 #define hfs_brec_read hfsplus_brec_read
 #define hfs_brec_goto hfsplus_brec_goto
@@ -324,10 +333,33 @@ static inline unsigned short hfsplus_min_io_size(struct super_block *sb)
  */
 #define HFSPLUS_IOC_BLESS _IO('h', 0x80)
 
+typedef int (*search_strategy_t)(struct hfs_bnode *,
+				struct hfs_find_data *,
+				int *, int *, int *);
+
 /*
  * Functions in any *.c used in other files
  */
 
+/* attributes.c */
+int hfsplus_create_attr_tree_cache(void);
+void hfsplus_destroy_attr_tree_cache(void);
+hfsplus_attr_entry *hfsplus_alloc_attr_entry(void);
+void hfsplus_destroy_attr_entry(hfsplus_attr_entry *entry_p);
+int hfsplus_attr_bin_cmp_key(const hfsplus_btree_key *,
+		const hfsplus_btree_key *);
+int hfsplus_attr_build_key(struct super_block *, hfsplus_btree_key *,
+			u32, const char *);
+void hfsplus_attr_build_key_uni(hfsplus_btree_key *key,
+					u32 cnid,
+					struct hfsplus_attr_unistr *name);
+int hfsplus_find_attr(struct super_block *, u32,
+			const char *, struct hfs_find_data *);
+int hfsplus_attr_exists(struct inode *inode, const char *name);
+int hfsplus_create_attr(struct inode *, const char *, const void *, size_t);
+int hfsplus_delete_attr(struct inode *, const char *);
+int hfsplus_delete_all_attrs(struct inode *dir, u32 cnid);
+
 /* bitmap.c */
 int hfsplus_block_allocate(struct super_block *, u32, u32, u32 *);
 int hfsplus_block_free(struct super_block *, u32, u32);
@@ -369,8 +401,15 @@ int hfs_brec_remove(struct hfs_find_data *);
 /* bfind.c */
 int hfs_find_init(struct hfs_btree *, struct hfs_find_data *);
 void hfs_find_exit(struct hfs_find_data *);
-int __hfs_brec_find(struct hfs_bnode *, struct hfs_find_data *);
-int hfs_brec_find(struct hfs_find_data *);
+int hfs_find_1st_rec_by_cnid(struct hfs_bnode *,
+				struct hfs_find_data *,
+				int *, int *, int *);
+int hfs_find_rec_by_key(struct hfs_bnode *,
+				struct hfs_find_data *,
+				int *, int *, int *);
+int __hfs_brec_find(struct hfs_bnode *, struct hfs_find_data *,
+				search_strategy_t);
+int hfs_brec_find(struct hfs_find_data *, search_strategy_t);
 int hfs_brec_read(struct hfs_find_data *, void *, int);
 int hfs_brec_goto(struct hfs_find_data *, int);
 
@@ -417,11 +456,6 @@ int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
 
 /* ioctl.c */
 long hfsplus_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
-int hfsplus_setxattr(struct dentry *dentry, const char *name,
-		     const void *value, size_t size, int flags);
-ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
-			 void *value, size_t size);
-ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size);
 
 /* options.c */
 int hfsplus_parse_options(char *, struct hfsplus_sb_info *);
@@ -446,7 +480,7 @@ int hfsplus_strcmp(const struct hfsplus_unistr *,
 int hfsplus_uni2asc(struct super_block *,
 		const struct hfsplus_unistr *, char *, int *);
 int hfsplus_asc2uni(struct super_block *,
-		struct hfsplus_unistr *, const char *, int);
+		struct hfsplus_unistr *, int, const char *, int);
 int hfsplus_hash_dentry(const struct dentry *dentry,
 		const struct inode *inode, struct qstr *str);
 int hfsplus_compare_dentry(const struct dentry *parent,
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h
index 921967e..452ede0 100644
--- a/fs/hfsplus/hfsplus_raw.h
+++ b/fs/hfsplus/hfsplus_raw.h
@@ -52,13 +52,23 @@
 typedef __be32 hfsplus_cnid;
 typedef __be16 hfsplus_unichr;
 
+#define HFSPLUS_MAX_STRLEN 255
+#define HFSPLUS_ATTR_MAX_STRLEN 127
+
 /* A "string" as used in filenames, etc. */
 struct hfsplus_unistr {
 	__be16 length;
-	hfsplus_unichr unicode[255];
+	hfsplus_unichr unicode[HFSPLUS_MAX_STRLEN];
 } __packed;
 
-#define HFSPLUS_MAX_STRLEN 255
+/*
+ * A "string" is used in attributes file
+ * for name of extended attribute
+ */
+struct hfsplus_attr_unistr {
+	__be16 length;
+	hfsplus_unichr unicode[HFSPLUS_ATTR_MAX_STRLEN];
+} __packed;
 
 /* POSIX permissions */
 struct hfsplus_perm {
@@ -291,6 +301,8 @@ struct hfsplus_cat_file {
 /* File attribute bits */
 #define HFSPLUS_FILE_LOCKED		0x0001
 #define HFSPLUS_FILE_THREAD_EXISTS	0x0002
+#define HFSPLUS_XATTR_EXISTS		0x0004
+#define HFSPLUS_ACL_EXISTS		0x0008
 
 /* HFS+ catalog thread (part of a cat_entry) */
 struct hfsplus_cat_thread {
@@ -327,11 +339,63 @@ struct hfsplus_ext_key {
 
 #define HFSPLUS_EXT_KEYLEN	sizeof(struct hfsplus_ext_key)
 
+#define HFSPLUS_XATTR_FINDER_INFO_NAME "com.apple.FinderInfo"
+#define HFSPLUS_XATTR_ACL_NAME "com.apple.system.Security"
+
+#define HFSPLUS_ATTR_INLINE_DATA 0x10
+#define HFSPLUS_ATTR_FORK_DATA   0x20
+#define HFSPLUS_ATTR_EXTENTS     0x30
+
+/* HFS+ attributes tree key */
+struct hfsplus_attr_key {
+	__be16 key_len;
+	__be16 pad;
+	hfsplus_cnid cnid;
+	__be32 start_block;
+	struct hfsplus_attr_unistr key_name;
+} __packed;
+
+#define HFSPLUS_ATTR_KEYLEN	sizeof(struct hfsplus_attr_key)
+
+/* HFS+ fork data attribute */
+struct hfsplus_attr_fork_data {
+	__be32 record_type;
+	__be32 reserved;
+	struct hfsplus_fork_raw the_fork;
+} __packed;
+
+/* HFS+ extension attribute */
+struct hfsplus_attr_extents {
+	__be32 record_type;
+	__be32 reserved;
+	struct hfsplus_extent extents;
+} __packed;
+
+#define HFSPLUS_MAX_INLINE_DATA_SIZE 3802
+
+/* HFS+ attribute inline data */
+struct hfsplus_attr_inline_data {
+	__be32 record_type;
+	__be32 reserved1;
+	u8 reserved2[6];
+	__be16 length;
+	u8 raw_bytes[HFSPLUS_MAX_INLINE_DATA_SIZE];
+} __packed;
+
+/* A data record in the attributes tree */
+typedef union {
+	__be32 record_type;
+	struct hfsplus_attr_fork_data fork_data;
+	struct hfsplus_attr_extents extents;
+	struct hfsplus_attr_inline_data inline_data;
+} __packed hfsplus_attr_entry;
+
 /* HFS+ generic BTree key */
 typedef union {
 	__be16 key_len;
 	struct hfsplus_cat_key cat;
 	struct hfsplus_ext_key ext;
+	struct hfsplus_attr_key attr;
 } __packed hfsplus_btree_key;
 
 #endif
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 2172aa5..f1bf56e6 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -17,6 +17,7 @@
 
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
+#include "xattr.h"
 
 static int hfsplus_readpage(struct file *file, struct page *page)
 {
@@ -342,6 +343,18 @@ int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
 			error = error2;
 	}
 
+	if (test_and_clear_bit(HFSPLUS_I_ATTR_DIRTY, &hip->flags)) {
+		if (sbi->attr_tree) {
+			error2 =
+				filemap_write_and_wait(
+					    sbi->attr_tree->inode->i_mapping);
+			if (!error)
+				error = error2;
+		} else {
+			printk(KERN_ERR "hfs: sync non-existent attributes tree\n");
+		}
+	}
+
 	if (test_and_clear_bit(HFSPLUS_I_ALLOC_DIRTY, &hip->flags)) {
 		error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping);
 		if (!error)
@@ -360,9 +373,10 @@ static const struct inode_operations hfsplus_file_inode_operations = {
 	.lookup		= hfsplus_file_lookup,
 	.truncate	= hfsplus_file_truncate,
 	.setattr	= hfsplus_setattr,
-	.setxattr	= hfsplus_setxattr,
-	.getxattr	= hfsplus_getxattr,
+	.setxattr	= generic_setxattr,
+	.getxattr	= generic_getxattr,
 	.listxattr	= hfsplus_listxattr,
+	.removexattr	= hfsplus_removexattr,
 };
 
 static const struct file_operations hfsplus_file_operations = {
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
index 09addc8..83a434d 100644
--- a/fs/hfsplus/ioctl.c
+++ b/fs/hfsplus/ioctl.c
@@ -16,7 +16,6 @@
 #include <linux/fs.h>
 #include <linux/mount.h>
 #include <linux/sched.h>
-#include <linux/xattr.h>
 #include <asm/uaccess.h>
 #include "hfsplus_fs.h"
 
@@ -151,110 +150,3 @@ long hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		return -ENOTTY;
 	}
 }
-
-int hfsplus_setxattr(struct dentry *dentry, const char *name,
-		     const void *value, size_t size, int flags)
-{
-	struct inode *inode = dentry->d_inode;
-	struct hfs_find_data fd;
-	hfsplus_cat_entry entry;
-	struct hfsplus_cat_file *file;
-	int res;
-
-	if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode))
-		return -EOPNOTSUPP;
-
-	res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
-	if (res)
-		return res;
-	res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
-	if (res)
-		goto out;
-	hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
-			sizeof(struct hfsplus_cat_file));
-	file = &entry.file;
-
-	if (!strcmp(name, "hfs.type")) {
-		if (size == 4)
-			memcpy(&file->user_info.fdType, value, 4);
-		else
-			res = -ERANGE;
-	} else if (!strcmp(name, "hfs.creator")) {
-		if (size == 4)
-			memcpy(&file->user_info.fdCreator, value, 4);
-		else
-			res = -ERANGE;
-	} else
-		res = -EOPNOTSUPP;
-	if (!res) {
-		hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
-				sizeof(struct hfsplus_cat_file));
-		hfsplus_mark_inode_dirty(inode, HFSPLUS_I_CAT_DIRTY);
-	}
-out:
-	hfs_find_exit(&fd);
-	return res;
-}
-
-ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
-			 void *value, size_t size)
-{
-	struct inode *inode = dentry->d_inode;
-	struct hfs_find_data fd;
-	hfsplus_cat_entry entry;
-	struct hfsplus_cat_file *file;
-	ssize_t res = 0;
-
-	if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode))
-		return -EOPNOTSUPP;
-
-	if (size) {
-		res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
-		if (res)
-			return res;
-		res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
-		if (res)
-			goto out;
-		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
-				sizeof(struct hfsplus_cat_file));
-	}
-	file = &entry.file;
-
-	if (!strcmp(name, "hfs.type")) {
-		if (size >= 4) {
-			memcpy(value, &file->user_info.fdType, 4);
-			res = 4;
-		} else
-			res = size ? -ERANGE : 4;
-	} else if (!strcmp(name, "hfs.creator")) {
-		if (size >= 4) {
-			memcpy(value, &file->user_info.fdCreator, 4);
-			res = 4;
-		} else
-			res = size ? -ERANGE : 4;
-	} else
-		res = -EOPNOTSUPP;
-out:
-	if (size)
-		hfs_find_exit(&fd);
-	return res;
-}
-
-#define HFSPLUS_ATTRLIST_SIZE (sizeof("hfs.creator")+sizeof("hfs.type"))
-
-ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
-{
-	struct inode *inode = dentry->d_inode;
-
-	if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode))
-		return -EOPNOTSUPP;
-
-	if (!buffer || !size)
-		return HFSPLUS_ATTRLIST_SIZE;
-	if (size < HFSPLUS_ATTRLIST_SIZE)
-		return -ERANGE;
-	strcpy(buffer, "hfs.type");
-	strcpy(buffer + sizeof("hfs.type"), "hfs.creator");
-
-	return HFSPLUS_ATTRLIST_SIZE;
-}
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 811a84d..2cae269 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -20,6 +20,7 @@ static struct inode *hfsplus_alloc_inode(struct super_block *sb);
 static void hfsplus_destroy_inode(struct inode *inode);
 
 #include "hfsplus_fs.h"
+#include "xattr.h"
 
 static int hfsplus_system_read_inode(struct inode *inode)
 {
@@ -118,6 +119,7 @@ static int hfsplus_system_write_inode(struct inode *inode)
 	case HFSPLUS_ATTR_CNID:
 		fork = &vhdr->attr_file;
 		tree = sbi->attr_tree;
+		break;
 	default:
 		return -EIO;
 	}
@@ -185,6 +187,12 @@ static int hfsplus_sync_fs(struct super_block *sb, int wait)
 	error2 = filemap_write_and_wait(sbi->ext_tree->inode->i_mapping);
 	if (!error)
 		error = error2;
+	if (sbi->attr_tree) {
+		error2 =
+		    filemap_write_and_wait(sbi->attr_tree->inode->i_mapping);
+		if (!error)
+			error = error2;
+	}
 	error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping);
 	if (!error)
 		error = error2;
@@ -272,6 +280,7 @@ static void hfsplus_put_super(struct super_block *sb)
 		hfsplus_sync_fs(sb, 1);
 	}
 
+	hfs_btree_close(sbi->attr_tree);
 	hfs_btree_close(sbi->cat_tree);
 	hfs_btree_close(sbi->ext_tree);
 	iput(sbi->alloc_file);
@@ -468,12 +477,20 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
 		printk(KERN_ERR "hfs: failed to load catalog file\n");
 		goto out_close_ext_tree;
 	}
+	if (vhdr->attr_file.total_blocks != 0) {
+		sbi->attr_tree = hfs_btree_open(sb, HFSPLUS_ATTR_CNID);
+		if (!sbi->attr_tree) {
+			printk(KERN_ERR "hfs: failed to load attributes file\n");
+			goto out_close_cat_tree;
+		}
+	}
+	sb->s_xattr = hfsplus_xattr_handlers;
 
 	inode = hfsplus_iget(sb, HFSPLUS_ALLOC_CNID);
 	if (IS_ERR(inode)) {
 		printk(KERN_ERR "hfs: failed to load allocation file\n");
 		err = PTR_ERR(inode);
-		goto out_close_cat_tree;
+		goto out_close_attr_tree;
 	}
 	sbi->alloc_file = inode;
 
@@ -533,10 +550,27 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
 			}
 			err = hfsplus_create_cat(sbi->hidden_dir->i_ino, root,
 						 &str, sbi->hidden_dir);
-			mutex_unlock(&sbi->vh_mutex);
-			if (err)
+			if (err) {
+				mutex_unlock(&sbi->vh_mutex);
+				goto out_put_hidden_dir;
+			}
+
+			err = hfsplus_init_inode_security(sbi->hidden_dir,
+								root, &str);
+			if (err == -EOPNOTSUPP)
+				err = 0; /* Operation is not supported. */
+			else if (err) {
+				/*
+				 * Try to delete anyway without
+				 * error analysis.
+				 */
+				hfsplus_delete_cat(sbi->hidden_dir->i_ino,
+							root, &str);
+				mutex_unlock(&sbi->vh_mutex);
 				goto out_put_hidden_dir;
+			}
 
+			mutex_unlock(&sbi->vh_mutex);
 			hfsplus_mark_inode_dirty(sbi->hidden_dir,
 						 HFSPLUS_I_CAT_DIRTY);
 		}
@@ -553,6 +587,8 @@ out_put_root:
 	sb->s_root = NULL;
 out_put_alloc_file:
 	iput(sbi->alloc_file);
+out_close_attr_tree:
+	hfs_btree_close(sbi->attr_tree);
 out_close_cat_tree:
 	hfs_btree_close(sbi->cat_tree);
 out_close_ext_tree:
@@ -626,9 +662,20 @@ static int __init init_hfsplus_fs(void)
 		hfsplus_init_once);
 	if (!hfsplus_inode_cachep)
 		return -ENOMEM;
+	err = hfsplus_create_attr_tree_cache();
+	if (err)
+		goto destroy_inode_cache;
 	err = register_filesystem(&hfsplus_fs_type);
 	if (err)
-		kmem_cache_destroy(hfsplus_inode_cachep);
+		goto destroy_attr_tree_cache;
+	return 0;
+
+destroy_attr_tree_cache:
+	hfsplus_destroy_attr_tree_cache();
+
+destroy_inode_cache:
+	kmem_cache_destroy(hfsplus_inode_cachep);
+
 	return err;
 }
 
@@ -641,6 +688,7 @@ static void __exit exit_hfsplus_fs(void)
 	 * destroy cache.
 	 */
 	rcu_barrier();
+	hfsplus_destroy_attr_tree_cache();
 	kmem_cache_destroy(hfsplus_inode_cachep);
 }
 
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index a32998f2..2c2e47d 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -295,7 +295,8 @@ static inline u16 *decompose_unichar(wchar_t uc, int *size)
 	return hfsplus_decompose_table + (off / 4);
 }
 
-int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr,
+int hfsplus_asc2uni(struct super_block *sb,
+		    struct hfsplus_unistr *ustr, int max_unistr_len,
 		    const char *astr, int len)
 {
 	int size, dsize, decompose;
@@ -303,7 +304,7 @@ int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr,
 	wchar_t c;
 
 	decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
-	while (outlen < HFSPLUS_MAX_STRLEN && len > 0) {
+	while (outlen < max_unistr_len && len > 0) {
 		size = asc2unichar(sb, astr, len, &c);
 
 		if (decompose)
@@ -311,7 +312,7 @@ int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr,
 		else
 			dstr = NULL;
 		if (dstr) {
-			if (outlen + dsize > HFSPLUS_MAX_STRLEN)
+			if (outlen + dsize > max_unistr_len)
 				break;
 			do {
 				ustr->unicode[outlen++] = cpu_to_be16(*dstr++);
diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
new file mode 100644
index 0000000..e8a4b08
--- /dev/null
+++ b/fs/hfsplus/xattr.c
@@ -0,0 +1,709 @@
+/*
+ * linux/fs/hfsplus/xattr.c
+ *
+ * Vyacheslav Dubeyko <slava@dubeyko.com>
+ *
+ * Logic of processing extended attributes
+ */
+
+#include "hfsplus_fs.h"
+#include "xattr.h"
+
+const struct xattr_handler *hfsplus_xattr_handlers[] = {
+	&hfsplus_xattr_osx_handler,
+	&hfsplus_xattr_user_handler,
+	&hfsplus_xattr_trusted_handler,
+	&hfsplus_xattr_security_handler,
+	NULL
+};
+
+static int strcmp_xattr_finder_info(const char *name)
+{
+	if (name) {
+		return strncmp(name, HFSPLUS_XATTR_FINDER_INFO_NAME,
+				sizeof(HFSPLUS_XATTR_FINDER_INFO_NAME));
+	}
+	return -1;
+}
+
+static int strcmp_xattr_acl(const char *name)
+{
+	if (name) {
+		return strncmp(name, HFSPLUS_XATTR_ACL_NAME,
+				sizeof(HFSPLUS_XATTR_ACL_NAME));
+	}
+	return -1;
+}
+
+static inline int is_known_namespace(const char *name)
+{
+	if (strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) &&
+	    strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) &&
+	    strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) &&
+	    strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
+		return false;
+
+	return true;
+}
+
+static int can_set_xattr(struct inode *inode, const char *name,
+				const void *value, size_t value_len)
+{
+	if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
+		return -EOPNOTSUPP; /* TODO: implement ACL support */
+
+	if (!strncmp(name, XATTR_MAC_OSX_PREFIX, XATTR_MAC_OSX_PREFIX_LEN)) {
+		/*
+		 * This makes sure that we aren't trying to set an
+		 * attribute in a different namespace by prefixing it
+		 * with "osx."
+		 */
+		if (is_known_namespace(name + XATTR_MAC_OSX_PREFIX_LEN))
+			return -EOPNOTSUPP;
+
+		return 0;
+	}
+
+	/*
+	 * Don't allow setting an attribute in an unknown namespace.
+	 */
+	if (strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) &&
+	    strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) &&
+	    strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
+		return -EOPNOTSUPP;
+
+	return 0;
+}
+
+int __hfsplus_setxattr(struct inode *inode, const char *name,
+			const void *value, size_t size, int flags)
+{
+	int err = 0;
+	struct hfs_find_data cat_fd;
+	hfsplus_cat_entry entry;
+	u16 cat_entry_flags, cat_entry_type;
+	u16 folder_finderinfo_len = sizeof(struct DInfo) +
+					sizeof(struct DXInfo);
+	u16 file_finderinfo_len = sizeof(struct FInfo) +
+					sizeof(struct FXInfo);
+
+	if ((!S_ISREG(inode->i_mode) &&
+			!S_ISDIR(inode->i_mode)) ||
+				HFSPLUS_IS_RSRC(inode))
+		return -EOPNOTSUPP;
+
+	err = can_set_xattr(inode, name, value, size);
+	if (err)
+		return err;
+
+	if (strncmp(name, XATTR_MAC_OSX_PREFIX,
+				XATTR_MAC_OSX_PREFIX_LEN) == 0)
+		name += XATTR_MAC_OSX_PREFIX_LEN;
+
+	if (value == NULL) {
+		value = "";
+		size = 0;
+	}
+
+	err = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &cat_fd);
+	if (err) {
+		printk(KERN_ERR "hfs: can't init xattr find struct\n");
+		return err;
+	}
+
+	err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &cat_fd);
+	if (err) {
+		printk(KERN_ERR "hfs: catalog searching failed\n");
+		goto end_setxattr;
+	}
+
+	if (!strcmp_xattr_finder_info(name)) {
+		if (flags & XATTR_CREATE) {
+			printk(KERN_ERR "hfs: xattr exists yet\n");
+			err = -EOPNOTSUPP;
+			goto end_setxattr;
+		}
+		hfs_bnode_read(cat_fd.bnode, &entry, cat_fd.entryoffset,
+					sizeof(hfsplus_cat_entry));
+		if (be16_to_cpu(entry.type) == HFSPLUS_FOLDER) {
+			if (size == folder_finderinfo_len) {
+				memcpy(&entry.folder.user_info, value,
+						folder_finderinfo_len);
+				hfs_bnode_write(cat_fd.bnode, &entry,
+					cat_fd.entryoffset,
+					sizeof(struct hfsplus_cat_folder));
+				hfsplus_mark_inode_dirty(inode,
+						HFSPLUS_I_CAT_DIRTY);
+			} else {
+				err = -ERANGE;
+				goto end_setxattr;
+			}
+		} else if (be16_to_cpu(entry.type) == HFSPLUS_FILE) {
+			if (size == file_finderinfo_len) {
+				memcpy(&entry.file.user_info, value,
+						file_finderinfo_len);
+				hfs_bnode_write(cat_fd.bnode, &entry,
+					cat_fd.entryoffset,
+					sizeof(struct hfsplus_cat_file));
+				hfsplus_mark_inode_dirty(inode,
+						HFSPLUS_I_CAT_DIRTY);
+			} else {
+				err = -ERANGE;
+				goto end_setxattr;
+			}
+		} else {
+			err = -EOPNOTSUPP;
+			goto end_setxattr;
+		}
+		goto end_setxattr;
+	}
+
+	if (!HFSPLUS_SB(inode->i_sb)->attr_tree) {
+		err = -EOPNOTSUPP;
+		goto end_setxattr;
+	}
+
+	if (hfsplus_attr_exists(inode, name)) {
+		if (flags & XATTR_CREATE) {
+			printk(KERN_ERR "hfs: xattr exists yet\n");
+			err = -EOPNOTSUPP;
+			goto end_setxattr;
+		}
+		err = hfsplus_delete_attr(inode, name);
+		if (err)
+			goto end_setxattr;
+		err = hfsplus_create_attr(inode, name, value, size);
+		if (err)
+			goto end_setxattr;
+	} else {
+		if (flags & XATTR_REPLACE) {
+			printk(KERN_ERR "hfs: cannot replace xattr\n");
+			err = -EOPNOTSUPP;
+			goto end_setxattr;
+		}
+		err = hfsplus_create_attr(inode, name, value, size);
+		if (err)
+			goto end_setxattr;
+	}
+
+	cat_entry_type = hfs_bnode_read_u16(cat_fd.bnode, cat_fd.entryoffset);
+	if (cat_entry_type == HFSPLUS_FOLDER) {
+		cat_entry_flags = hfs_bnode_read_u16(cat_fd.bnode,
+				    cat_fd.entryoffset +
+				    offsetof(struct hfsplus_cat_folder, flags));
+		cat_entry_flags |= HFSPLUS_XATTR_EXISTS;
+		if (!strcmp_xattr_acl(name))
+			cat_entry_flags |= HFSPLUS_ACL_EXISTS;
+		hfs_bnode_write_u16(cat_fd.bnode, cat_fd.entryoffset +
+				offsetof(struct hfsplus_cat_folder, flags),
+				cat_entry_flags);
+		hfsplus_mark_inode_dirty(inode, HFSPLUS_I_CAT_DIRTY);
+	} else if (cat_entry_type == HFSPLUS_FILE) {
+		cat_entry_flags = hfs_bnode_read_u16(cat_fd.bnode,
+				    cat_fd.entryoffset +
+				    offsetof(struct hfsplus_cat_file, flags));
+		cat_entry_flags |= HFSPLUS_XATTR_EXISTS;
+		if (!strcmp_xattr_acl(name))
+			cat_entry_flags |= HFSPLUS_ACL_EXISTS;
+		hfs_bnode_write_u16(cat_fd.bnode, cat_fd.entryoffset +
+				    offsetof(struct hfsplus_cat_file, flags),
+				    cat_entry_flags);
+		hfsplus_mark_inode_dirty(inode, HFSPLUS_I_CAT_DIRTY);
+	} else {
+		printk(KERN_ERR "hfs: invalid catalog entry type\n");
+		err = -EIO;
+		goto end_setxattr;
+	}
+
+end_setxattr:
+	hfs_find_exit(&cat_fd);
+	return err;
+}
+
+static inline int is_osx_xattr(const char *xattr_name)
+{
+	return !is_known_namespace(xattr_name);
+}
+
+static int name_len(const char *xattr_name, int xattr_name_len)
+{
+	int len = xattr_name_len + 1;
+
+	if (is_osx_xattr(xattr_name))
+		len += XATTR_MAC_OSX_PREFIX_LEN;
+
+	return len;
+}
+
+static int copy_name(char *buffer, const char *xattr_name, int name_len)
+{
+	int len = name_len;
+	int offset = 0;
+
+	if (is_osx_xattr(xattr_name)) {
+		strncpy(buffer, XATTR_MAC_OSX_PREFIX, XATTR_MAC_OSX_PREFIX_LEN);
+		offset += XATTR_MAC_OSX_PREFIX_LEN;
+		len += XATTR_MAC_OSX_PREFIX_LEN;
+	}
+
+	strncpy(buffer + offset, xattr_name, name_len);
+	memset(buffer + offset + name_len, 0, 1);
+	len += 1;
+
+	return len;
+}
+
+static ssize_t hfsplus_getxattr_finder_info(struct dentry *dentry,
+						void *value, size_t size)
+{
+	ssize_t res = 0;
+	struct inode *inode = dentry->d_inode;
+	struct hfs_find_data fd;
+	u16 entry_type;
+	u16 folder_rec_len = sizeof(struct DInfo) + sizeof(struct DXInfo);
+	u16 file_rec_len = sizeof(struct FInfo) + sizeof(struct FXInfo);
+	u16 record_len = max(folder_rec_len, file_rec_len);
+	u8 folder_finder_info[sizeof(struct DInfo) + sizeof(struct DXInfo)];
+	u8 file_finder_info[sizeof(struct FInfo) + sizeof(struct FXInfo)];
+
+	if (size >= record_len) {
+		res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
+		if (res) {
+			printk(KERN_ERR "hfs: can't init xattr find struct\n");
+			return res;
+		}
+		res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
+		if (res)
+			goto end_getxattr_finder_info;
+		entry_type = hfs_bnode_read_u16(fd.bnode, fd.entryoffset);
+
+		if (entry_type == HFSPLUS_FOLDER) {
+			hfs_bnode_read(fd.bnode, folder_finder_info,
+				fd.entryoffset +
+				offsetof(struct hfsplus_cat_folder, user_info),
+				folder_rec_len);
+			memcpy(value, folder_finder_info, folder_rec_len);
+			res = folder_rec_len;
+		} else if (entry_type == HFSPLUS_FILE) {
+			hfs_bnode_read(fd.bnode, file_finder_info,
+				fd.entryoffset +
+				offsetof(struct hfsplus_cat_file, user_info),
+				file_rec_len);
+			memcpy(value, file_finder_info, file_rec_len);
+			res = file_rec_len;
+		} else {
+			res = -EOPNOTSUPP;
+			goto end_getxattr_finder_info;
+		}
+	} else
+		res = size ? -ERANGE : record_len;
+
+end_getxattr_finder_info:
+	if (size >= record_len)
+		hfs_find_exit(&fd);
+	return res;
+}
+
+ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
+			 void *value, size_t size)
+{
+	struct inode *inode = dentry->d_inode;
+	struct hfs_find_data fd;
+	hfsplus_attr_entry *entry;
+	__be32 xattr_record_type;
+	u32 record_type;
+	u16 record_length = 0;
+	ssize_t res = 0;
+
+	if ((!S_ISREG(inode->i_mode) &&
+			!S_ISDIR(inode->i_mode)) ||
+				HFSPLUS_IS_RSRC(inode))
+		return -EOPNOTSUPP;
+
+	if (strncmp(name, XATTR_MAC_OSX_PREFIX,
+				XATTR_MAC_OSX_PREFIX_LEN) == 0) {
+		/* skip "osx." prefix */
+		name += XATTR_MAC_OSX_PREFIX_LEN;
+		/*
+		 * Don't allow retrieving properly prefixed attributes
+		 * by prepending them with "osx."
+		 */
+		if (is_known_namespace(name))
+			return -EOPNOTSUPP;
+	}
+
+	if (!strcmp_xattr_finder_info(name))
+		return hfsplus_getxattr_finder_info(dentry, value, size);
+
+	if (!HFSPLUS_SB(inode->i_sb)->attr_tree)
+		return -EOPNOTSUPP;
+
+	entry = hfsplus_alloc_attr_entry();
+	if (!entry) {
+		printk(KERN_ERR "hfs: can't allocate xattr entry\n");
+		return -ENOMEM;
+	}
+
+	res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->attr_tree, &fd);
+	if (res) {
+		printk(KERN_ERR "hfs: can't init xattr find struct\n");
+		goto failed_getxattr_init;
+	}
+
+	res = hfsplus_find_attr(inode->i_sb, inode->i_ino, name, &fd);
+	if (res) {
+		if (res == -ENOENT)
+			res = -ENODATA;
+		else
+			printk(KERN_ERR "hfs: xattr searching failed\n");
+		goto out;
+	}
+
+	hfs_bnode_read(fd.bnode, &xattr_record_type,
+			fd.entryoffset, sizeof(xattr_record_type));
+	record_type = be32_to_cpu(xattr_record_type);
+	if (record_type == HFSPLUS_ATTR_INLINE_DATA) {
+		record_length = hfs_bnode_read_u16(fd.bnode,
+				fd.entryoffset +
+				offsetof(struct hfsplus_attr_inline_data,
+				length));
+		if (record_length > HFSPLUS_MAX_INLINE_DATA_SIZE) {
+			printk(KERN_ERR "hfs: invalid xattr record size\n");
+			res = -EIO;
+			goto out;
+		}
+	} else if (record_type == HFSPLUS_ATTR_FORK_DATA ||
+			record_type == HFSPLUS_ATTR_EXTENTS) {
+		printk(KERN_ERR "hfs: only inline data xattr are supported\n");
+		res = -EOPNOTSUPP;
+		goto out;
+	} else {
+		printk(KERN_ERR "hfs: invalid xattr record\n");
+		res = -EIO;
+		goto out;
+	}
+
+	if (size) {
+		hfs_bnode_read(fd.bnode, entry, fd.entryoffset,
+				offsetof(struct hfsplus_attr_inline_data,
+					raw_bytes) + record_length);
+	}
+
+	if (size >= record_length) {
+		memcpy(value, entry->inline_data.raw_bytes, record_length);
+		res = record_length;
+	} else
+		res = size ? -ERANGE : record_length;
+
+out:
+	hfs_find_exit(&fd);
+
+failed_getxattr_init:
+	hfsplus_destroy_attr_entry(entry);
+	return res;
+}
+
+static inline int can_list(const char *xattr_name)
+{
+	if (!xattr_name)
+		return 0;
+
+	return strncmp(xattr_name, XATTR_TRUSTED_PREFIX,
+			XATTR_TRUSTED_PREFIX_LEN) ||
+				capable(CAP_SYS_ADMIN);
+}
+
+static ssize_t hfsplus_listxattr_finder_info(struct dentry *dentry,
+						char *buffer, size_t size)
+{
+	ssize_t res = 0;
+	struct inode *inode = dentry->d_inode;
+	struct hfs_find_data fd;
+	u16 entry_type;
+	u8 folder_finder_info[sizeof(struct DInfo) + sizeof(struct DXInfo)];
+	u8 file_finder_info[sizeof(struct FInfo) + sizeof(struct FXInfo)];
+	unsigned long len, found_bit;
+	int xattr_name_len, symbols_count;
+
+	res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd);
+	if (res) {
+		printk(KERN_ERR "hfs: can't init xattr find struct\n");
+		return res;
+	}
+
+	res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
+	if (res)
+		goto end_listxattr_finder_info;
+
+	entry_type = hfs_bnode_read_u16(fd.bnode, fd.entryoffset);
+	if (entry_type == HFSPLUS_FOLDER) {
+		len = sizeof(struct DInfo) + sizeof(struct DXInfo);
+		hfs_bnode_read(fd.bnode, folder_finder_info,
+				fd.entryoffset +
+				offsetof(struct hfsplus_cat_folder, user_info),
+				len);
+		found_bit = find_first_bit((void *)folder_finder_info, len*8);
+	} else if (entry_type == HFSPLUS_FILE) {
+		len = sizeof(struct FInfo) + sizeof(struct FXInfo);
+		hfs_bnode_read(fd.bnode, file_finder_info,
+				fd.entryoffset +
+				offsetof(struct hfsplus_cat_file, user_info),
+				len);
+		found_bit = find_first_bit((void *)file_finder_info, len*8);
+	} else {
+		res = -EOPNOTSUPP;
+		goto end_listxattr_finder_info;
+	}
+
+	if (found_bit >= (len*8))
+		res = 0;
+	else {
+		symbols_count = sizeof(HFSPLUS_XATTR_FINDER_INFO_NAME) - 1;
+		xattr_name_len =
+			name_len(HFSPLUS_XATTR_FINDER_INFO_NAME, symbols_count);
+		if (!buffer || !size) {
+			if (can_list(HFSPLUS_XATTR_FINDER_INFO_NAME))
+				res = xattr_name_len;
+		} else if (can_list(HFSPLUS_XATTR_FINDER_INFO_NAME)) {
+			if (size < xattr_name_len)
+				res = -ERANGE;
+			else {
+				res = copy_name(buffer,
+						HFSPLUS_XATTR_FINDER_INFO_NAME,
+						symbols_count);
+			}
+		}
+	}
+
+end_listxattr_finder_info:
+	hfs_find_exit(&fd);
+
+	return res;
+}
+
+ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+	ssize_t err;
+	ssize_t res = 0;
+	struct inode *inode = dentry->d_inode;
+	struct hfs_find_data fd;
+	u16 key_len = 0;
+	struct hfsplus_attr_key attr_key;
+	char strbuf[HFSPLUS_ATTR_MAX_STRLEN +
+			XATTR_MAC_OSX_PREFIX_LEN + 1] = {0};
+	int xattr_name_len;
+
+	if ((!S_ISREG(inode->i_mode) &&
+			!S_ISDIR(inode->i_mode)) ||
+				HFSPLUS_IS_RSRC(inode))
+		return -EOPNOTSUPP;
+
+	res = hfsplus_listxattr_finder_info(dentry, buffer, size);
+	if (res < 0)
+		return res;
+	else if (!HFSPLUS_SB(inode->i_sb)->attr_tree)
+		return (res == 0) ? -EOPNOTSUPP : res;
+
+	err = hfs_find_init(HFSPLUS_SB(inode->i_sb)->attr_tree, &fd);
+	if (err) {
+		printk(KERN_ERR "hfs: can't init xattr find struct\n");
+		return err;
+	}
+
+	err = hfsplus_find_attr(inode->i_sb, inode->i_ino, NULL, &fd);
+	if (err) {
+		if (err == -ENOENT) {
+			if (res == 0)
+				res = -ENODATA;
+			goto end_listxattr;
+		} else {
+			res = err;
+			goto end_listxattr;
+		}
+	}
+
+	for (;;) {
+		key_len = hfs_bnode_read_u16(fd.bnode, fd.keyoffset);
+		if (key_len == 0 || key_len > fd.tree->max_key_len) {
+			printk(KERN_ERR "hfs: invalid xattr key length: %d\n",
+							key_len);
+			res = -EIO;
+			goto end_listxattr;
+		}
+
+		hfs_bnode_read(fd.bnode, &attr_key,
+				fd.keyoffset, key_len + sizeof(key_len));
+
+		if (be32_to_cpu(attr_key.cnid) != inode->i_ino)
+			goto end_listxattr;
+
+		xattr_name_len = HFSPLUS_ATTR_MAX_STRLEN;
+		if (hfsplus_uni2asc(inode->i_sb,
+			(const struct hfsplus_unistr *)&fd.key->attr.key_name,
+					strbuf, &xattr_name_len)) {
+			printk(KERN_ERR "hfs: unicode conversion failed\n");
+			res = -EIO;
+			goto end_listxattr;
+		}
+
+		if (!buffer || !size) {
+			if (can_list(strbuf))
+				res += name_len(strbuf, xattr_name_len);
+		} else if (can_list(strbuf)) {
+			if (size < (res + name_len(strbuf, xattr_name_len))) {
+				res = -ERANGE;
+				goto end_listxattr;
+			} else
+				res += copy_name(buffer + res,
+						strbuf, xattr_name_len);
+		}
+
+		if (hfs_brec_goto(&fd, 1))
+			goto end_listxattr;
+	}
+
+end_listxattr:
+	hfs_find_exit(&fd);
+	return res;
+}
+
+int hfsplus_removexattr(struct dentry *dentry, const char *name)
+{
+	int err = 0;
+	struct inode *inode = dentry->d_inode;
+	struct hfs_find_data cat_fd;
+	u16 flags;
+	u16 cat_entry_type;
+	int is_xattr_acl_deleted = 0;
+	int is_all_xattrs_deleted = 0;
+
+	if ((!S_ISREG(inode->i_mode) &&
+			!S_ISDIR(inode->i_mode)) ||
+				HFSPLUS_IS_RSRC(inode))
+		return -EOPNOTSUPP;
+
+	if (!HFSPLUS_SB(inode->i_sb)->attr_tree)
+		return -EOPNOTSUPP;
+
+	err = can_set_xattr(inode, name, NULL, 0);
+	if (err)
+		return err;
+
+	if (strncmp(name, XATTR_MAC_OSX_PREFIX,
+				XATTR_MAC_OSX_PREFIX_LEN) == 0)
+		name += XATTR_MAC_OSX_PREFIX_LEN;
+
+	if (!strcmp_xattr_finder_info(name))
+		return -EOPNOTSUPP;
+
+	err = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &cat_fd);
+	if (err) {
+		printk(KERN_ERR "hfs: can't init xattr find struct\n");
+		return err;
+	}
+
+	err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &cat_fd);
+	if (err) {
+		printk(KERN_ERR "hfs: catalog searching failed\n");
+		goto end_removexattr;
+	}
+
+	err = hfsplus_delete_attr(inode, name);
+	if (err)
+		goto end_removexattr;
+
+	is_xattr_acl_deleted = !strcmp_xattr_acl(name);
+	is_all_xattrs_deleted = !hfsplus_attr_exists(inode, NULL);
+
+	if (!is_xattr_acl_deleted && !is_all_xattrs_deleted)
+		goto end_removexattr;
+
+	cat_entry_type = hfs_bnode_read_u16(cat_fd.bnode, cat_fd.entryoffset);
+
+	if (cat_entry_type == HFSPLUS_FOLDER) {
+		flags = hfs_bnode_read_u16(cat_fd.bnode, cat_fd.entryoffset +
+				offsetof(struct hfsplus_cat_folder, flags));
+		if (is_xattr_acl_deleted)
+			flags &= ~HFSPLUS_ACL_EXISTS;
+		if (is_all_xattrs_deleted)
+			flags &= ~HFSPLUS_XATTR_EXISTS;
+		hfs_bnode_write_u16(cat_fd.bnode, cat_fd.entryoffset +
+				offsetof(struct hfsplus_cat_folder, flags),
+				flags);
+		hfsplus_mark_inode_dirty(inode, HFSPLUS_I_CAT_DIRTY);
+	} else if (cat_entry_type == HFSPLUS_FILE) {
+		flags = hfs_bnode_read_u16(cat_fd.bnode, cat_fd.entryoffset +
+				offsetof(struct hfsplus_cat_file, flags));
+		if (is_xattr_acl_deleted)
+			flags &= ~HFSPLUS_ACL_EXISTS;
+		if (is_all_xattrs_deleted)
+			flags &= ~HFSPLUS_XATTR_EXISTS;
+		hfs_bnode_write_u16(cat_fd.bnode, cat_fd.entryoffset +
+				offsetof(struct hfsplus_cat_file, flags),
+				flags);
+		hfsplus_mark_inode_dirty(inode, HFSPLUS_I_CAT_DIRTY);
+	} else {
+		printk(KERN_ERR "hfs: invalid catalog entry type\n");
+		err = -EIO;
+		goto end_removexattr;
+	}
+
+end_removexattr:
+	hfs_find_exit(&cat_fd);
+	return err;
+}
+
+static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name,
+					void *buffer, size_t size, int type)
+{
+	char xattr_name[HFSPLUS_ATTR_MAX_STRLEN +
+				XATTR_MAC_OSX_PREFIX_LEN + 1] = {0};
+	size_t len = strlen(name);
+
+	if (!strcmp(name, ""))
+		return -EINVAL;
+
+	if (len > HFSPLUS_ATTR_MAX_STRLEN)
+		return -EOPNOTSUPP;
+
+	strcpy(xattr_name, XATTR_MAC_OSX_PREFIX);
+	strcpy(xattr_name + XATTR_MAC_OSX_PREFIX_LEN, name);
+
+	return hfsplus_getxattr(dentry, xattr_name, buffer, size);
+}
+
+static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
+		const void *buffer, size_t size, int flags, int type)
+{
+	char xattr_name[HFSPLUS_ATTR_MAX_STRLEN +
+				XATTR_MAC_OSX_PREFIX_LEN + 1] = {0};
+	size_t len = strlen(name);
+
+	if (!strcmp(name, ""))
+		return -EINVAL;
+
+	if (len > HFSPLUS_ATTR_MAX_STRLEN)
+		return -EOPNOTSUPP;
+
+	strcpy(xattr_name, XATTR_MAC_OSX_PREFIX);
+	strcpy(xattr_name + XATTR_MAC_OSX_PREFIX_LEN, name);
+
+	return hfsplus_setxattr(dentry, xattr_name, buffer, size, flags);
+}
+
+static size_t hfsplus_osx_listxattr(struct dentry *dentry, char *list,
+		size_t list_size, const char *name, size_t name_len, int type)
+{
+	/*
+	 * This method is not used.
+	 * It is used hfsplus_listxattr() instead of generic_listxattr().
+	 */
+	return -EOPNOTSUPP;
+}
+
+const struct xattr_handler hfsplus_xattr_osx_handler = {
+	.prefix	= XATTR_MAC_OSX_PREFIX,
+	.list	= hfsplus_osx_listxattr,
+	.get	= hfsplus_osx_getxattr,
+	.set	= hfsplus_osx_setxattr,
+};
diff --git a/fs/hfsplus/xattr.h b/fs/hfsplus/xattr.h
new file mode 100644
index 0000000..847b695
--- /dev/null
+++ b/fs/hfsplus/xattr.h
@@ -0,0 +1,60 @@
+/*
+ * linux/fs/hfsplus/xattr.h
+ *
+ * Vyacheslav Dubeyko <slava@dubeyko.com>
+ *
+ * Logic of processing extended attributes
+ */
+
+#ifndef _LINUX_HFSPLUS_XATTR_H
+#define _LINUX_HFSPLUS_XATTR_H
+
+#include <linux/xattr.h>
+
+extern const struct xattr_handler hfsplus_xattr_osx_handler;
+extern const struct xattr_handler hfsplus_xattr_user_handler;
+extern const struct xattr_handler hfsplus_xattr_trusted_handler;
+/*extern const struct xattr_handler hfsplus_xattr_acl_access_handler;*/
+/*extern const struct xattr_handler hfsplus_xattr_acl_default_handler;*/
+extern const struct xattr_handler hfsplus_xattr_security_handler;
+
+extern const struct xattr_handler *hfsplus_xattr_handlers[];
+
+int __hfsplus_setxattr(struct inode *inode, const char *name,
+			const void *value, size_t size, int flags);
+
+static inline int hfsplus_setxattr(struct dentry *dentry, const char *name,
+			const void *value, size_t size, int flags)
+{
+	return __hfsplus_setxattr(dentry->d_inode, name, value, size, flags);
+}
+
+ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
+			void *value, size_t size);
+
+ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size);
+
+int hfsplus_removexattr(struct dentry *dentry, const char *name);
+
+int hfsplus_init_security(struct inode *inode, struct inode *dir,
+				const struct qstr *qstr);
+
+static inline int hfsplus_init_acl(struct inode *inode, struct inode *dir)
+{
+	/*TODO: implement*/
+	return 0;
+}
+
+static inline int hfsplus_init_inode_security(struct inode *inode,
+						struct inode *dir,
+						const struct qstr *qstr)
+{
+	int err;
+
+	err = hfsplus_init_acl(inode, dir);
+	if (!err)
+		err = hfsplus_init_security(inode, dir, qstr);
+	return err;
+}
+
+#endif
diff --git a/fs/hfsplus/xattr_security.c b/fs/hfsplus/xattr_security.c
new file mode 100644
index 0000000..83b842f
--- /dev/null
+++ b/fs/hfsplus/xattr_security.c
@@ -0,0 +1,104 @@
+/*
+ * linux/fs/hfsplus/xattr_trusted.c
+ *
+ * Vyacheslav Dubeyko <slava@dubeyko.com>
+ *
+ * Handler for storing security labels as extended attributes.
+ */
+
+#include <linux/security.h>
+#include "hfsplus_fs.h"
+#include "xattr.h"
+
+static int hfsplus_security_getxattr(struct dentry *dentry, const char *name,
+					void *buffer, size_t size, int type)
+{
+	char xattr_name[HFSPLUS_ATTR_MAX_STRLEN + 1] = {0};
+	size_t len = strlen(name);
+
+	if (!strcmp(name, ""))
+		return -EINVAL;
+
+	if (len + XATTR_SECURITY_PREFIX_LEN > HFSPLUS_ATTR_MAX_STRLEN)
+		return -EOPNOTSUPP;
+
+	strcpy(xattr_name, XATTR_SECURITY_PREFIX);
+	strcpy(xattr_name + XATTR_SECURITY_PREFIX_LEN, name);
+
+	return hfsplus_getxattr(dentry, xattr_name, buffer, size);
+}
+
+static int hfsplus_security_setxattr(struct dentry *dentry, const char *name,
+		const void *buffer, size_t size, int flags, int type)
+{
+	char xattr_name[HFSPLUS_ATTR_MAX_STRLEN + 1] = {0};
+	size_t len = strlen(name);
+
+	if (!strcmp(name, ""))
+		return -EINVAL;
+
+	if (len + XATTR_SECURITY_PREFIX_LEN > HFSPLUS_ATTR_MAX_STRLEN)
+		return -EOPNOTSUPP;
+
+	strcpy(xattr_name, XATTR_SECURITY_PREFIX);
+	strcpy(xattr_name + XATTR_SECURITY_PREFIX_LEN, name);
+
+	return hfsplus_setxattr(dentry, xattr_name, buffer, size, flags);
+}
+
+static size_t hfsplus_security_listxattr(struct dentry *dentry, char *list,
+		size_t list_size, const char *name, size_t name_len, int type)
+{
+	/*
+	 * This method is not used.
+	 * It is used hfsplus_listxattr() instead of generic_listxattr().
+	 */
+	return -EOPNOTSUPP;
+}
+
+static int hfsplus_initxattrs(struct inode *inode,
+				const struct xattr *xattr_array,
+				void *fs_info)
+{
+	const struct xattr *xattr;
+	char xattr_name[HFSPLUS_ATTR_MAX_STRLEN + 1] = {0};
+	size_t xattr_name_len;
+	int err = 0;
+
+	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+		xattr_name_len = strlen(xattr->name);
+
+		if (xattr_name_len == 0)
+			continue;
+
+		if (xattr_name_len + XATTR_SECURITY_PREFIX_LEN >
+				HFSPLUS_ATTR_MAX_STRLEN)
+			return -EOPNOTSUPP;
+
+		strcpy(xattr_name, XATTR_SECURITY_PREFIX);
+		strcpy(xattr_name +
+			XATTR_SECURITY_PREFIX_LEN, xattr->name);
+		memset(xattr_name +
+			XATTR_SECURITY_PREFIX_LEN + xattr_name_len, 0, 1);
+
+		err = __hfsplus_setxattr(inode, xattr_name,
+					xattr->value, xattr->value_len, 0);
+		if (err)
+			break;
+	}
+	return err;
+}
+
+int hfsplus_init_security(struct inode *inode, struct inode *dir,
+				const struct qstr *qstr)
+{
+	return security_inode_init_security(inode, dir, qstr,
+					&hfsplus_initxattrs, NULL);
+}
+
+const struct xattr_handler hfsplus_xattr_security_handler = {
+	.prefix	= XATTR_SECURITY_PREFIX,
+	.list	= hfsplus_security_listxattr,
+	.get	= hfsplus_security_getxattr,
+	.set	= hfsplus_security_setxattr,
+};
diff --git a/fs/hfsplus/xattr_trusted.c b/fs/hfsplus/xattr_trusted.c
new file mode 100644
index 0000000..426cee2
--- /dev/null
+++ b/fs/hfsplus/xattr_trusted.c
@@ -0,0 +1,63 @@
+/*
+ * linux/fs/hfsplus/xattr_trusted.c
+ *
+ * Vyacheslav Dubeyko <slava@dubeyko.com>
+ *
+ * Handler for trusted extended attributes.
+ */
+
+#include "hfsplus_fs.h"
+#include "xattr.h"
+
+static int hfsplus_trusted_getxattr(struct dentry *dentry, const char *name,
+					void *buffer, size_t size, int type)
+{
+	char xattr_name[HFSPLUS_ATTR_MAX_STRLEN + 1] = {0};
+	size_t len = strlen(name);
+
+	if (!strcmp(name, ""))
+		return -EINVAL;
+
+	if (len + XATTR_TRUSTED_PREFIX_LEN > HFSPLUS_ATTR_MAX_STRLEN)
+		return -EOPNOTSUPP;
+
+	strcpy(xattr_name, XATTR_TRUSTED_PREFIX);
+	strcpy(xattr_name + XATTR_TRUSTED_PREFIX_LEN, name);
+
+	return hfsplus_getxattr(dentry, xattr_name, buffer, size);
+}
+
+static int hfsplus_trusted_setxattr(struct dentry *dentry, const char *name,
+		const void *buffer, size_t size, int flags, int type)
+{
+	char xattr_name[HFSPLUS_ATTR_MAX_STRLEN + 1] = {0};
+	size_t len = strlen(name);
+
+	if (!strcmp(name, ""))
+		return -EINVAL;
+
+	if (len + XATTR_TRUSTED_PREFIX_LEN > HFSPLUS_ATTR_MAX_STRLEN)
+		return -EOPNOTSUPP;
+
+	strcpy(xattr_name, XATTR_TRUSTED_PREFIX);
+	strcpy(xattr_name + XATTR_TRUSTED_PREFIX_LEN, name);
+
+	return hfsplus_setxattr(dentry, xattr_name, buffer, size, flags);
+}
+
+static size_t hfsplus_trusted_listxattr(struct dentry *dentry, char *list,
+		size_t list_size, const char *name, size_t name_len, int type)
+{
+	/*
+	 * This method is not used.
+	 * It is used hfsplus_listxattr() instead of generic_listxattr().
+	 */
+	return -EOPNOTSUPP;
+}
+
+const struct xattr_handler hfsplus_xattr_trusted_handler = {
+	.prefix	= XATTR_TRUSTED_PREFIX,
+	.list	= hfsplus_trusted_listxattr,
+	.get	= hfsplus_trusted_getxattr,
+	.set	= hfsplus_trusted_setxattr,
+};
diff --git a/fs/hfsplus/xattr_user.c b/fs/hfsplus/xattr_user.c
new file mode 100644
index 0000000..e340165
--- /dev/null
+++ b/fs/hfsplus/xattr_user.c
@@ -0,0 +1,63 @@
+/*
+ * linux/fs/hfsplus/xattr_user.c
+ *
+ * Vyacheslav Dubeyko <slava@dubeyko.com>
+ *
+ * Handler for user extended attributes.
+ */
+
+#include "hfsplus_fs.h"
+#include "xattr.h"
+
+static int hfsplus_user_getxattr(struct dentry *dentry, const char *name,
+					void *buffer, size_t size, int type)
+{
+	char xattr_name[HFSPLUS_ATTR_MAX_STRLEN + 1] = {0};
+	size_t len = strlen(name);
+
+	if (!strcmp(name, ""))
+		return -EINVAL;
+
+	if (len + XATTR_USER_PREFIX_LEN > HFSPLUS_ATTR_MAX_STRLEN)
+		return -EOPNOTSUPP;
+
+	strcpy(xattr_name, XATTR_USER_PREFIX);
+	strcpy(xattr_name + XATTR_USER_PREFIX_LEN, name);
+
+	return hfsplus_getxattr(dentry, xattr_name, buffer, size);
+}
+
+static int hfsplus_user_setxattr(struct dentry *dentry, const char *name,
+		const void *buffer, size_t size, int flags, int type)
+{
+	char xattr_name[HFSPLUS_ATTR_MAX_STRLEN + 1] = {0};
+	size_t len = strlen(name);
+
+	if (!strcmp(name, ""))
+		return -EINVAL;
+
+	if (len + XATTR_USER_PREFIX_LEN > HFSPLUS_ATTR_MAX_STRLEN)
+		return -EOPNOTSUPP;
+
+	strcpy(xattr_name, XATTR_USER_PREFIX);
+	strcpy(xattr_name + XATTR_USER_PREFIX_LEN, name);
+
+	return hfsplus_setxattr(dentry, xattr_name, buffer, size, flags);
+}
+
+static size_t hfsplus_user_listxattr(struct dentry *dentry, char *list,
+		size_t list_size, const char *name, size_t name_len, int type)
+{
+	/*
+	 * This method is not used.
+	 * It is used hfsplus_listxattr() instead of generic_listxattr().
+	 */
+	return -EOPNOTSUPP;
+}
+
+const struct xattr_handler hfsplus_xattr_user_handler = {
+	.prefix	= XATTR_USER_PREFIX,
+	.list	= hfsplus_user_listxattr,
+	.get	= hfsplus_user_getxattr,
+	.set	= hfsplus_user_setxattr,
+};
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c
index 78f21f8..43b315f 100644
--- a/fs/hppfs/hppfs.c
+++ b/fs/hppfs/hppfs.c
@@ -710,7 +710,7 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent)
 	struct vfsmount *proc_mnt;
 	int err = -ENOENT;
 
-	proc_mnt = mntget(current->nsproxy->pid_ns->proc_mnt);
+	proc_mnt = mntget(task_active_pid_ns(current)->proc_mnt);
 	if (IS_ERR(proc_mnt))
 		goto out;
 
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index c5bc355..4a55f35 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -151,8 +151,8 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
-	unsigned long start_addr;
 	struct hstate *h = hstate_file(file);
+	struct vm_unmapped_area_info info;
 
 	if (len & ~huge_page_mask(h))
 		return -EINVAL;
@@ -173,39 +173,13 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
 			return addr;
 	}
 
-	if (len > mm->cached_hole_size)
-		start_addr = mm->free_area_cache;
-	else {
-		start_addr = TASK_UNMAPPED_BASE;
-		mm->cached_hole_size = 0;
-	}
-
-full_search:
-	addr = ALIGN(start_addr, huge_page_size(h));
-
-	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
-		/* At this point:  (!vma || addr < vma->vm_end). */
-		if (TASK_SIZE - len < addr) {
-			/*
-			 * Start a new search - just in case we missed
-			 * some holes.
-			 */
-			if (start_addr != TASK_UNMAPPED_BASE) {
-				start_addr = TASK_UNMAPPED_BASE;
-				mm->cached_hole_size = 0;
-				goto full_search;
-			}
-			return -ENOMEM;
-		}
-
-		if (!vma || addr + len <= vma->vm_start) {
-			mm->free_area_cache = addr + len;
-			return addr;
-		}
-		if (addr + mm->cached_hole_size < vma->vm_start)
-			mm->cached_hole_size = vma->vm_start - addr;
-		addr = ALIGN(vma->vm_end, huge_page_size(h));
-	}
+	info.flags = 0;
+	info.length = len;
+	info.low_limit = TASK_UNMAPPED_BASE;
+	info.high_limit = TASK_SIZE;
+	info.align_mask = PAGE_MASK & ~huge_page_mask(h);
+	info.align_offset = 0;
+	return vm_unmapped_area(&info);
 }
 #endif
 
@@ -608,11 +582,11 @@ static int hugetlbfs_migrate_page(struct address_space *mapping,
 	int rc;
 
 	rc = migrate_huge_page_move_mapping(mapping, newpage, page);
-	if (rc)
+	if (rc != MIGRATEPAGE_SUCCESS)
 		return rc;
 	migrate_page_copy(newpage, page);
 
-	return 0;
+	return MIGRATEPAGE_SUCCESS;
 }
 
 static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -923,7 +897,7 @@ static struct file_system_type hugetlbfs_fs_type = {
 	.kill_sb	= kill_litter_super,
 };
 
-static struct vfsmount *hugetlbfs_vfsmount;
+static struct vfsmount *hugetlbfs_vfsmount[HUGE_MAX_HSTATE];
 
 static int can_do_hugetlb_shm(void)
 {
@@ -932,9 +906,22 @@ static int can_do_hugetlb_shm(void)
 	return capable(CAP_IPC_LOCK) || in_group_p(shm_group);
 }
 
+static int get_hstate_idx(int page_size_log)
+{
+	struct hstate *h;
+
+	if (!page_size_log)
+		return default_hstate_idx;
+	h = size_to_hstate(1 << page_size_log);
+	if (!h)
+		return -1;
+	return h - hstates;
+}
+
 struct file *hugetlb_file_setup(const char *name, unsigned long addr,
 				size_t size, vm_flags_t acctflag,
-				struct user_struct **user, int creat_flags)
+				struct user_struct **user,
+				int creat_flags, int page_size_log)
 {
 	int error = -ENOMEM;
 	struct file *file;
@@ -944,9 +931,14 @@ struct file *hugetlb_file_setup(const char *name, unsigned long addr,
 	struct qstr quick_string;
 	struct hstate *hstate;
 	unsigned long num_pages;
+	int hstate_idx;
+
+	hstate_idx = get_hstate_idx(page_size_log);
+	if (hstate_idx < 0)
+		return ERR_PTR(-ENODEV);
 
 	*user = NULL;
-	if (!hugetlbfs_vfsmount)
+	if (!hugetlbfs_vfsmount[hstate_idx])
 		return ERR_PTR(-ENOENT);
 
 	if (creat_flags == HUGETLB_SHMFS_INODE && !can_do_hugetlb_shm()) {
@@ -963,7 +955,7 @@ struct file *hugetlb_file_setup(const char *name, unsigned long addr,
 		}
 	}
 
-	root = hugetlbfs_vfsmount->mnt_root;
+	root = hugetlbfs_vfsmount[hstate_idx]->mnt_root;
 	quick_string.name = name;
 	quick_string.len = strlen(quick_string.name);
 	quick_string.hash = 0;
@@ -971,7 +963,7 @@ struct file *hugetlb_file_setup(const char *name, unsigned long addr,
 	if (!path.dentry)
 		goto out_shm_unlock;
 
-	path.mnt = mntget(hugetlbfs_vfsmount);
+	path.mnt = mntget(hugetlbfs_vfsmount[hstate_idx]);
 	error = -ENOSPC;
 	inode = hugetlbfs_get_inode(root->d_sb, NULL, S_IFREG | S_IRWXUGO, 0);
 	if (!inode)
@@ -1011,8 +1003,9 @@ out_shm_unlock:
 
 static int __init init_hugetlbfs_fs(void)
 {
+	struct hstate *h;
 	int error;
-	struct vfsmount *vfsmount;
+	int i;
 
 	error = bdi_init(&hugetlbfs_backing_dev_info);
 	if (error)
@@ -1029,14 +1022,26 @@ static int __init init_hugetlbfs_fs(void)
 	if (error)
 		goto out;
 
-	vfsmount = kern_mount(&hugetlbfs_fs_type);
+	i = 0;
+	for_each_hstate(h) {
+		char buf[50];
+		unsigned ps_kb = 1U << (h->order + PAGE_SHIFT - 10);
 
-	if (!IS_ERR(vfsmount)) {
-		hugetlbfs_vfsmount = vfsmount;
-		return 0;
-	}
+		snprintf(buf, sizeof(buf), "pagesize=%uK", ps_kb);
+		hugetlbfs_vfsmount[i] = kern_mount_data(&hugetlbfs_fs_type,
+							buf);
 
-	error = PTR_ERR(vfsmount);
+		if (IS_ERR(hugetlbfs_vfsmount[i])) {
+			pr_err("hugetlb: Cannot mount internal hugetlbfs for "
+				"page size %uK", ps_kb);
+			error = PTR_ERR(hugetlbfs_vfsmount[i]);
+			hugetlbfs_vfsmount[i] = NULL;
+		}
+		i++;
+	}
+	/* Non default hstates are optional */
+	if (!IS_ERR_OR_NULL(hugetlbfs_vfsmount[default_hstate_idx]))
+		return 0;
 
  out:
 	kmem_cache_destroy(hugetlbfs_inode_cachep);
@@ -1047,13 +1052,19 @@ static int __init init_hugetlbfs_fs(void)
 
 static void __exit exit_hugetlbfs_fs(void)
 {
+	struct hstate *h;
+	int i;
+
+
 	/*
 	 * Make sure all delayed rcu free inodes are flushed before we
 	 * destroy cache.
 	 */
 	rcu_barrier();
 	kmem_cache_destroy(hugetlbfs_inode_cachep);
-	kern_unmount(hugetlbfs_vfsmount);
+	i = 0;
+	for_each_hstate(h)
+		kern_unmount(hugetlbfs_vfsmount[i++]);
 	unregister_filesystem(&hugetlbfs_fs_type);
 	bdi_destroy(&hugetlbfs_backing_dev_info);
 }
diff --git a/fs/inode.c b/fs/inode.c
index b03c719..14084b7 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -165,7 +165,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
 	mapping->host = inode;
 	mapping->flags = 0;
 	mapping_set_gfp_mask(mapping, GFP_HIGHUSER_MOVABLE);
-	mapping->assoc_mapping = NULL;
+	mapping->private_data = NULL;
 	mapping->backing_dev_info = &default_backing_dev_info;
 	mapping->writeback_index = 0;
 
@@ -408,6 +408,19 @@ static void inode_lru_list_add(struct inode *inode)
 	spin_unlock(&inode->i_sb->s_inode_lru_lock);
 }
 
+/*
+ * Add inode to LRU if needed (inode is unused and clean).
+ *
+ * Needs inode->i_lock held.
+ */
+void inode_add_lru(struct inode *inode)
+{
+	if (!(inode->i_state & (I_DIRTY | I_SYNC | I_FREEING | I_WILL_FREE)) &&
+	    !atomic_read(&inode->i_count) && inode->i_sb->s_flags & MS_ACTIVE)
+		inode_lru_list_add(inode);
+}
+
+
 static void inode_lru_list_del(struct inode *inode)
 {
 	spin_lock(&inode->i_sb->s_inode_lru_lock);
@@ -1390,8 +1403,7 @@ static void iput_final(struct inode *inode)
 
 	if (!drop && (sb->s_flags & MS_ACTIVE)) {
 		inode->i_state |= I_REFERENCED;
-		if (!(inode->i_state & (I_DIRTY|I_SYNC)))
-			inode_lru_list_add(inode);
+		inode_add_lru(inode);
 		spin_unlock(&inode->i_lock);
 		return;
 	}
diff --git a/fs/internal.h b/fs/internal.h
index 916b7cb..2f6af7f 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -110,6 +110,7 @@ extern int open_check_o_direct(struct file *f);
  * inode.c
  */
 extern spinlock_t inode_sb_list_lock;
+extern void inode_add_lru(struct inode *inode);
 
 /*
  * fs-writeback.c
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 78b7f84..071d690 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -1259,7 +1259,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
 		goto not_jbd;
 	}
 
-	/* keep track of wether or not this transaction modified us */
+	/* keep track of whether or not this transaction modified us */
 	was_modified = jh->b_modified;
 
 	/*
@@ -1961,7 +1961,9 @@ retry:
 			spin_unlock(&journal->j_list_lock);
 			jbd_unlock_bh_state(bh);
 			spin_unlock(&journal->j_state_lock);
+			unlock_buffer(bh);
 			log_wait_commit(journal, tid);
+			lock_buffer(bh);
 			goto retry;
 		}
 		/*
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 484b8d1..dbf41f9 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -60,7 +60,6 @@ EXPORT_SYMBOL(jbd2_journal_get_create_access);
 EXPORT_SYMBOL(jbd2_journal_get_undo_access);
 EXPORT_SYMBOL(jbd2_journal_set_triggers);
 EXPORT_SYMBOL(jbd2_journal_dirty_metadata);
-EXPORT_SYMBOL(jbd2_journal_release_buffer);
 EXPORT_SYMBOL(jbd2_journal_forget);
 #if 0
 EXPORT_SYMBOL(journal_sync_buffer);
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index a74ba46..42f6615 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -1207,17 +1207,6 @@ out:
 	return ret;
 }
 
-/*
- * jbd2_journal_release_buffer: undo a get_write_access without any buffer
- * updates, if the update decided in the end that it didn't need access.
- *
- */
-void
-jbd2_journal_release_buffer(handle_t *handle, struct buffer_head *bh)
-{
-	BUFFER_TRACE(bh, "entry");
-}
-
 /**
  * void jbd2_journal_forget() - bforget() for potentially-journaled buffers.
  * @handle: transaction handle
@@ -1261,7 +1250,7 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
 		goto not_jbd;
 	}
 
-	/* keep track of wether or not this transaction modified us */
+	/* keep track of whether or not this transaction modified us */
 	was_modified = jh->b_modified;
 
 	/*
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 0c96eb5..0331072 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -417,14 +417,16 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
 			spin_unlock(&c->erase_completion_lock);
 
 			ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
-			if (ret)
-				return ret;
+
 			/* Just lock it again and continue. Nothing much can change because
 			   we hold c->alloc_sem anyway. In fact, it's not entirely clear why
 			   we hold c->erase_completion_lock in the majority of this function...
 			   but that's a question for another (more caffeine-rich) day. */
 			spin_lock(&c->erase_completion_lock);
 
+			if (ret)
+				return ret;
+
 			waste = jeb->free_size;
 			jffs2_link_node_ref(c, jeb,
 					    (jeb->offset + c->sector_size - waste) | REF_OBSOLETE,
diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c
index 13ad153..00ec0b9 100644
--- a/fs/lockd/clnt4xdr.c
+++ b/fs/lockd/clnt4xdr.c
@@ -64,10 +64,6 @@ static void nlm4_compute_offsets(const struct nlm_lock *lock,
 {
 	const struct file_lock *fl = &lock->fl;
 
-	BUG_ON(fl->fl_start > NLM4_OFFSET_MAX);
-	BUG_ON(fl->fl_end > NLM4_OFFSET_MAX &&
-				fl->fl_end != OFFSET_MAX);
-
 	*l_offset = loff_t_to_s64(fl->fl_start);
 	if (fl->fl_end == OFFSET_MAX)
 		*l_len = 0;
@@ -122,7 +118,6 @@ static void encode_netobj(struct xdr_stream *xdr,
 {
 	__be32 *p;
 
-	BUG_ON(length > XDR_MAX_NETOBJ);
 	p = xdr_reserve_space(xdr, 4 + length);
 	xdr_encode_opaque(p, data, length);
 }
@@ -156,7 +151,6 @@ out_overflow:
 static void encode_cookie(struct xdr_stream *xdr,
 			  const struct nlm_cookie *cookie)
 {
-	BUG_ON(cookie->len > NLM_MAXCOOKIELEN);
 	encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
 }
 
@@ -198,7 +192,6 @@ out_overflow:
  */
 static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh)
 {
-	BUG_ON(fh->size > NFS3_FHSIZE);
 	encode_netobj(xdr, (u8 *)&fh->data, fh->size);
 }
 
@@ -336,7 +329,6 @@ static void encode_caller_name(struct xdr_stream *xdr, const char *name)
 	u32 length = strlen(name);
 	__be32 *p;
 
-	BUG_ON(length > NLM_MAXSTRLEN);
 	p = xdr_reserve_space(xdr, 4 + length);
 	xdr_encode_opaque(p, name, length);
 }
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 05d2912..54f9e6c 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -141,7 +141,7 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
 
 static void nlmclnt_release_lockargs(struct nlm_rqst *req)
 {
-	BUG_ON(req->a_args.lock.fl.fl_ops != NULL);
+	WARN_ON_ONCE(req->a_args.lock.fl.fl_ops != NULL);
 }
 
 /**
@@ -465,7 +465,6 @@ static const struct file_lock_operations nlmclnt_lock_ops = {
 
 static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host)
 {
-	BUG_ON(fl->fl_ops != NULL);
 	fl->fl_u.nfs_fl.state = 0;
 	fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner);
 	INIT_LIST_HEAD(&fl->fl_u.nfs_fl.list);
diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c
index 982d2676..18d0c34 100644
--- a/fs/lockd/clntxdr.c
+++ b/fs/lockd/clntxdr.c
@@ -60,10 +60,6 @@ static void nlm_compute_offsets(const struct nlm_lock *lock,
 {
 	const struct file_lock *fl = &lock->fl;
 
-	BUG_ON(fl->fl_start > NLM_OFFSET_MAX);
-	BUG_ON(fl->fl_end > NLM_OFFSET_MAX &&
-				fl->fl_end != OFFSET_MAX);
-
 	*l_offset = loff_t_to_s32(fl->fl_start);
 	if (fl->fl_end == OFFSET_MAX)
 		*l_len = 0;
@@ -119,7 +115,6 @@ static void encode_netobj(struct xdr_stream *xdr,
 {
 	__be32 *p;
 
-	BUG_ON(length > XDR_MAX_NETOBJ);
 	p = xdr_reserve_space(xdr, 4 + length);
 	xdr_encode_opaque(p, data, length);
 }
@@ -153,7 +148,6 @@ out_overflow:
 static void encode_cookie(struct xdr_stream *xdr,
 			  const struct nlm_cookie *cookie)
 {
-	BUG_ON(cookie->len > NLM_MAXCOOKIELEN);
 	encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
 }
 
@@ -195,7 +189,6 @@ out_overflow:
  */
 static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh)
 {
-	BUG_ON(fh->size != NFS2_FHSIZE);
 	encode_netobj(xdr, (u8 *)&fh->data, NFS2_FHSIZE);
 }
 
@@ -330,7 +323,6 @@ static void encode_caller_name(struct xdr_stream *xdr, const char *name)
 	u32 length = strlen(name);
 	__be32 *p;
 
-	BUG_ON(length > NLM_MAXSTRLEN);
 	p = xdr_reserve_space(xdr, 4 + length);
 	xdr_encode_opaque(p, name, length);
 }
@@ -620,6 +612,7 @@ static struct rpc_stat		nlm_rpc_stats;
 
 const struct rpc_program	nlm_program = {
 		.name		= "lockd",
+		.service_name	= "nlockmgr",
 		.number		= NLM_PROGRAM,
 		.nrvers		= ARRAY_SIZE(nlm_versions),
 		.version	= nlm_versions,
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index f9b22e5..0e17090 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -177,9 +177,6 @@ static void nlm_destroy_host_locked(struct nlm_host *host)
 
 	dprintk("lockd: destroy host %s\n", host->h_name);
 
-	BUG_ON(!list_empty(&host->h_lockowners));
-	BUG_ON(atomic_read(&host->h_count));
-
 	hlist_del_init(&host->h_hash);
 
 	nsm_unmonitor(host);
@@ -289,13 +286,12 @@ void nlmclnt_release_host(struct nlm_host *host)
 
 	dprintk("lockd: release client host %s\n", host->h_name);
 
-	BUG_ON(atomic_read(&host->h_count) < 0);
-	BUG_ON(host->h_server);
+	WARN_ON_ONCE(host->h_server);
 
 	if (atomic_dec_and_test(&host->h_count)) {
-		BUG_ON(!list_empty(&host->h_lockowners));
-		BUG_ON(!list_empty(&host->h_granted));
-		BUG_ON(!list_empty(&host->h_reclaim));
+		WARN_ON_ONCE(!list_empty(&host->h_lockowners));
+		WARN_ON_ONCE(!list_empty(&host->h_granted));
+		WARN_ON_ONCE(!list_empty(&host->h_reclaim));
 
 		mutex_lock(&nlm_host_mutex);
 		nlm_destroy_host_locked(host);
@@ -412,8 +408,7 @@ void nlmsvc_release_host(struct nlm_host *host)
 
 	dprintk("lockd: release server host %s\n", host->h_name);
 
-	BUG_ON(atomic_read(&host->h_count) < 0);
-	BUG_ON(!host->h_server);
+	WARN_ON_ONCE(!host->h_server);
 	atomic_dec(&host->h_count);
 }
 
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 3d7e09b..24408cb 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -154,8 +154,6 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
 		.rpc_resp	= res,
 	};
 
-	BUG_ON(clnt == NULL);
-
 	memset(res, 0, sizeof(*res));
 
 	msg.rpc_proc = &clnt->cl_procinfo[proc];
@@ -466,7 +464,6 @@ static void encode_nsm_string(struct xdr_stream *xdr, const char *string)
 	const u32 len = strlen(string);
 	__be32 *p;
 
-	BUG_ON(len > SM_MAXSTRLEN);
 	p = xdr_reserve_space(xdr, 4 + len);
 	xdr_encode_opaque(p, string, len);
 }
@@ -608,6 +605,7 @@ static struct rpc_stat		nsm_stats;
 
 static const struct rpc_program nsm_program = {
 		.name		= "statd",
+		.service_name	= "status",
 		.number		= NSM_PROGRAM,
 		.nrvers		= ARRAY_SIZE(nsm_version),
 		.version	= nsm_version,
diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c
index 9c50144..427bb73 100644
--- a/fs/logfs/dev_mtd.c
+++ b/fs/logfs/dev_mtd.c
@@ -245,8 +245,8 @@ static int logfs_mtd_can_write_buf(struct super_block *sb, u64 ofs)
 		goto out;
 	if (memchr_inv(buf, 0xff, super->s_writesize))
 		err = -EIO;
-	kfree(buf);
 out:
+	kfree(buf);
 	return err;
 }
 
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
index adb9011..af49e2d 100644
--- a/fs/logfs/inode.c
+++ b/fs/logfs/inode.c
@@ -33,7 +33,7 @@
  * are being written out - and waiting for GC to make progress, naturally.
  *
  * So we cannot just call iget() or some variant of it, but first have to check
- * wether the inode in question might be in I_FREEING state.  Therefore we
+ * whether the inode in question might be in I_FREEING state.  Therefore we
  * maintain our own per-sb list of "almost deleted" inodes and check against
  * that list first.  Normally this should be at most 1-2 entries long.
  *
diff --git a/fs/logfs/super.c b/fs/logfs/super.c
index 345c24b..e726eb1 100644
--- a/fs/logfs/super.c
+++ b/fs/logfs/super.c
@@ -287,14 +287,14 @@ static int logfs_make_writeable(struct super_block *sb)
 	if (err)
 		return err;
 
+	/* Do one GC pass before any data gets dirtied */
+	logfs_gc_pass(sb);
+
 	/* Check areas for trailing unaccounted data */
 	err = logfs_check_areas(sb);
 	if (err)
 		return err;
 
-	/* Do one GC pass before any data gets dirtied */
-	logfs_gc_pass(sb);
-
 	/* after all initializations are done, replay the journal
 	 * for rw-mounts, if necessary */
 	err = logfs_replay_journal(sb);
diff --git a/fs/mount.h b/fs/mount.h
index 4f291f9..cd50079 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -4,8 +4,11 @@
 
 struct mnt_namespace {
 	atomic_t		count;
+	unsigned int		proc_inum;
 	struct mount *	root;
 	struct list_head	list;
+	struct user_namespace	*user_ns;
+	u64			seq;	/* Sequence number to prevent loops */
 	wait_queue_head_t poll;
 	int event;
 };
diff --git a/fs/namespace.c b/fs/namespace.c
index 2496062..c1bbe86 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -12,6 +12,7 @@
 #include <linux/export.h>
 #include <linux/capability.h>
 #include <linux/mnt_namespace.h>
+#include <linux/user_namespace.h>
 #include <linux/namei.h>
 #include <linux/security.h>
 #include <linux/idr.h>
@@ -20,6 +21,7 @@
 #include <linux/fs_struct.h>	/* get_fs_root et.al. */
 #include <linux/fsnotify.h>	/* fsnotify_vfsmount_delete */
 #include <linux/uaccess.h>
+#include <linux/proc_fs.h>
 #include "pnode.h"
 #include "internal.h"
 
@@ -784,7 +786,7 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
 	if (!mnt)
 		return ERR_PTR(-ENOMEM);
 
-	if (flag & (CL_SLAVE | CL_PRIVATE))
+	if (flag & (CL_SLAVE | CL_PRIVATE | CL_SHARED_TO_SLAVE))
 		mnt->mnt_group_id = 0; /* not a peer of original */
 	else
 		mnt->mnt_group_id = old->mnt_group_id;
@@ -805,7 +807,8 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
 	list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
 	br_write_unlock(&vfsmount_lock);
 
-	if (flag & CL_SLAVE) {
+	if ((flag & CL_SLAVE) ||
+	    ((flag & CL_SHARED_TO_SLAVE) && IS_MNT_SHARED(old))) {
 		list_add(&mnt->mnt_slave, &old->mnt_slave_list);
 		mnt->mnt_master = old;
 		CLEAR_MNT_SHARED(mnt);
@@ -1266,7 +1269,7 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
 		goto dput_and_out;
 
 	retval = -EPERM;
-	if (!capable(CAP_SYS_ADMIN))
+	if (!ns_capable(mnt->mnt_ns->user_ns, CAP_SYS_ADMIN))
 		goto dput_and_out;
 
 	retval = do_umount(mnt, flags);
@@ -1292,7 +1295,7 @@ SYSCALL_DEFINE1(oldumount, char __user *, name)
 
 static int mount_is_safe(struct path *path)
 {
-	if (capable(CAP_SYS_ADMIN))
+	if (ns_capable(real_mount(path->mnt)->mnt_ns->user_ns, CAP_SYS_ADMIN))
 		return 0;
 	return -EPERM;
 #ifdef notyet
@@ -1308,6 +1311,26 @@ static int mount_is_safe(struct path *path)
 #endif
 }
 
+static bool mnt_ns_loop(struct path *path)
+{
+	/* Could bind mounting the mount namespace inode cause a
+	 * mount namespace loop?
+	 */
+	struct inode *inode = path->dentry->d_inode;
+	struct proc_inode *ei;
+	struct mnt_namespace *mnt_ns;
+
+	if (!proc_ns_inode(inode))
+		return false;
+
+	ei = PROC_I(inode);
+	if (ei->ns_ops != &mntns_operations)
+		return false;
+
+	mnt_ns = ei->ns;
+	return current->nsproxy->mnt_ns->seq >= mnt_ns->seq;
+}
+
 struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
 					int flag)
 {
@@ -1610,7 +1633,7 @@ static int do_change_type(struct path *path, int flag)
 	int type;
 	int err = 0;
 
-	if (!capable(CAP_SYS_ADMIN))
+	if (!ns_capable(mnt->mnt_ns->user_ns, CAP_SYS_ADMIN))
 		return -EPERM;
 
 	if (path->dentry != path->mnt->mnt_root)
@@ -1655,6 +1678,10 @@ static int do_loopback(struct path *path, const char *old_name,
 	if (err)
 		return err;
 
+	err = -EINVAL;
+	if (mnt_ns_loop(&old_path))
+		goto out; 
+
 	err = lock_mount(path);
 	if (err)
 		goto out;
@@ -1770,7 +1797,7 @@ static int do_move_mount(struct path *path, const char *old_name)
 	struct mount *p;
 	struct mount *old;
 	int err = 0;
-	if (!capable(CAP_SYS_ADMIN))
+	if (!ns_capable(real_mount(path->mnt)->mnt_ns->user_ns, CAP_SYS_ADMIN))
 		return -EPERM;
 	if (!old_name || !*old_name)
 		return -EINVAL;
@@ -1857,21 +1884,6 @@ static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype)
 	return ERR_PTR(err);
 }
 
-static struct vfsmount *
-do_kern_mount(const char *fstype, int flags, const char *name, void *data)
-{
-	struct file_system_type *type = get_fs_type(fstype);
-	struct vfsmount *mnt;
-	if (!type)
-		return ERR_PTR(-ENODEV);
-	mnt = vfs_kern_mount(type, flags, name, data);
-	if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
-	    !mnt->mnt_sb->s_subtype)
-		mnt = fs_set_subtype(mnt, fstype);
-	put_filesystem(type);
-	return mnt;
-}
-
 /*
  * add a mount into a namespace's mount tree
  */
@@ -1917,20 +1929,46 @@ unlock:
  * create a new mount for userspace and request it to be added into the
  * namespace's tree
  */
-static int do_new_mount(struct path *path, const char *type, int flags,
+static int do_new_mount(struct path *path, const char *fstype, int flags,
 			int mnt_flags, const char *name, void *data)
 {
+	struct file_system_type *type;
+	struct user_namespace *user_ns;
 	struct vfsmount *mnt;
 	int err;
 
-	if (!type)
+	if (!fstype)
 		return -EINVAL;
 
 	/* we need capabilities... */
-	if (!capable(CAP_SYS_ADMIN))
+	user_ns = real_mount(path->mnt)->mnt_ns->user_ns;
+	if (!ns_capable(user_ns, CAP_SYS_ADMIN))
 		return -EPERM;
 
-	mnt = do_kern_mount(type, flags, name, data);
+	type = get_fs_type(fstype);
+	if (!type)
+		return -ENODEV;
+
+	if (user_ns != &init_user_ns) {
+		if (!(type->fs_flags & FS_USERNS_MOUNT)) {
+			put_filesystem(type);
+			return -EPERM;
+		}
+		/* Only in special cases allow devices from mounts
+		 * created outside the initial user namespace.
+		 */
+		if (!(type->fs_flags & FS_USERNS_DEV_MOUNT)) {
+			flags |= MS_NODEV;
+			mnt_flags |= MNT_NODEV;
+		}
+	}
+
+	mnt = vfs_kern_mount(type, flags, name, data);
+	if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
+	    !mnt->mnt_sb->s_subtype)
+		mnt = fs_set_subtype(mnt, fstype);
+
+	put_filesystem(type);
 	if (IS_ERR(mnt))
 		return PTR_ERR(mnt);
 
@@ -2261,18 +2299,42 @@ dput_out:
 	return retval;
 }
 
-static struct mnt_namespace *alloc_mnt_ns(void)
+static void free_mnt_ns(struct mnt_namespace *ns)
+{
+	proc_free_inum(ns->proc_inum);
+	put_user_ns(ns->user_ns);
+	kfree(ns);
+}
+
+/*
+ * Assign a sequence number so we can detect when we attempt to bind
+ * mount a reference to an older mount namespace into the current
+ * mount namespace, preventing reference counting loops.  A 64bit
+ * number incrementing at 10Ghz will take 12,427 years to wrap which
+ * is effectively never, so we can ignore the possibility.
+ */
+static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1);
+
+static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
 {
 	struct mnt_namespace *new_ns;
+	int ret;
 
 	new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
 	if (!new_ns)
 		return ERR_PTR(-ENOMEM);
+	ret = proc_alloc_inum(&new_ns->proc_inum);
+	if (ret) {
+		kfree(new_ns);
+		return ERR_PTR(ret);
+	}
+	new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
 	atomic_set(&new_ns->count, 1);
 	new_ns->root = NULL;
 	INIT_LIST_HEAD(&new_ns->list);
 	init_waitqueue_head(&new_ns->poll);
 	new_ns->event = 0;
+	new_ns->user_ns = get_user_ns(user_ns);
 	return new_ns;
 }
 
@@ -2281,24 +2343,28 @@ static struct mnt_namespace *alloc_mnt_ns(void)
  * copied from the namespace of the passed in task structure.
  */
 static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
-		struct fs_struct *fs)
+		struct user_namespace *user_ns, struct fs_struct *fs)
 {
 	struct mnt_namespace *new_ns;
 	struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
 	struct mount *p, *q;
 	struct mount *old = mnt_ns->root;
 	struct mount *new;
+	int copy_flags;
 
-	new_ns = alloc_mnt_ns();
+	new_ns = alloc_mnt_ns(user_ns);
 	if (IS_ERR(new_ns))
 		return new_ns;
 
 	down_write(&namespace_sem);
 	/* First pass: copy the tree topology */
-	new = copy_tree(old, old->mnt.mnt_root, CL_COPY_ALL | CL_EXPIRE);
+	copy_flags = CL_COPY_ALL | CL_EXPIRE;
+	if (user_ns != mnt_ns->user_ns)
+		copy_flags |= CL_SHARED_TO_SLAVE;
+	new = copy_tree(old, old->mnt.mnt_root, copy_flags);
 	if (IS_ERR(new)) {
 		up_write(&namespace_sem);
-		kfree(new_ns);
+		free_mnt_ns(new_ns);
 		return ERR_CAST(new);
 	}
 	new_ns->root = new;
@@ -2339,7 +2405,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
 }
 
 struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
-		struct fs_struct *new_fs)
+		struct user_namespace *user_ns, struct fs_struct *new_fs)
 {
 	struct mnt_namespace *new_ns;
 
@@ -2349,7 +2415,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
 	if (!(flags & CLONE_NEWNS))
 		return ns;
 
-	new_ns = dup_mnt_ns(ns, new_fs);
+	new_ns = dup_mnt_ns(ns, user_ns, new_fs);
 
 	put_mnt_ns(ns);
 	return new_ns;
@@ -2361,7 +2427,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
  */
 static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
 {
-	struct mnt_namespace *new_ns = alloc_mnt_ns();
+	struct mnt_namespace *new_ns = alloc_mnt_ns(&init_user_ns);
 	if (!IS_ERR(new_ns)) {
 		struct mount *mnt = real_mount(m);
 		mnt->mnt_ns = new_ns;
@@ -2501,7 +2567,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 	struct mount *new_mnt, *root_mnt;
 	int error;
 
-	if (!capable(CAP_SYS_ADMIN))
+	if (!ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN))
 		return -EPERM;
 
 	error = user_path_dir(new_root, &new);
@@ -2583,8 +2649,13 @@ static void __init init_mount_tree(void)
 	struct vfsmount *mnt;
 	struct mnt_namespace *ns;
 	struct path root;
+	struct file_system_type *type;
 
-	mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
+	type = get_fs_type("rootfs");
+	if (!type)
+		panic("Can't find rootfs type");
+	mnt = vfs_kern_mount(type, 0, "rootfs", NULL);
+	put_filesystem(type);
 	if (IS_ERR(mnt))
 		panic("Can't create rootfs");
 
@@ -2647,7 +2718,7 @@ void put_mnt_ns(struct mnt_namespace *ns)
 	br_write_unlock(&vfsmount_lock);
 	up_write(&namespace_sem);
 	release_mounts(&umount_list);
-	kfree(ns);
+	free_mnt_ns(ns);
 }
 
 struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
@@ -2681,3 +2752,71 @@ bool our_mnt(struct vfsmount *mnt)
 {
 	return check_mnt(real_mount(mnt));
 }
+
+static void *mntns_get(struct task_struct *task)
+{
+	struct mnt_namespace *ns = NULL;
+	struct nsproxy *nsproxy;
+
+	rcu_read_lock();
+	nsproxy = task_nsproxy(task);
+	if (nsproxy) {
+		ns = nsproxy->mnt_ns;
+		get_mnt_ns(ns);
+	}
+	rcu_read_unlock();
+
+	return ns;
+}
+
+static void mntns_put(void *ns)
+{
+	put_mnt_ns(ns);
+}
+
+static int mntns_install(struct nsproxy *nsproxy, void *ns)
+{
+	struct fs_struct *fs = current->fs;
+	struct mnt_namespace *mnt_ns = ns;
+	struct path root;
+
+	if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||
+	    !nsown_capable(CAP_SYS_CHROOT))
+		return -EPERM;
+
+	if (fs->users != 1)
+		return -EINVAL;
+
+	get_mnt_ns(mnt_ns);
+	put_mnt_ns(nsproxy->mnt_ns);
+	nsproxy->mnt_ns = mnt_ns;
+
+	/* Find the root */
+	root.mnt    = &mnt_ns->root->mnt;
+	root.dentry = mnt_ns->root->mnt.mnt_root;
+	path_get(&root);
+	while(d_mountpoint(root.dentry) && follow_down_one(&root))
+		;
+
+	/* Update the pwd and root */
+	set_fs_pwd(fs, &root);
+	set_fs_root(fs, &root);
+
+	path_put(&root);
+	return 0;
+}
+
+static unsigned int mntns_inum(void *ns)
+{
+	struct mnt_namespace *mnt_ns = ns;
+	return mnt_ns->proc_inum;
+}
+
+const struct proc_ns_operations mntns_operations = {
+	.name		= "mnt",
+	.type		= CLONE_NEWNS,
+	.get		= mntns_get,
+	.put		= mntns_put,
+	.install	= mntns_install,
+	.inum		= mntns_inum,
+};
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index 6958adf..24a05ba 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -819,7 +819,7 @@ long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	case NCP_IOC_CONN_LOGGED_IN:
 	case NCP_IOC_SETROOT:
 		if (!capable(CAP_SYS_ADMIN)) {
-			ret = -EACCES;
+			ret = -EPERM;
 			goto out;
 		}
 		break;
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index b7db608..cce2c05 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -24,7 +24,7 @@ nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o
 	  delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \
 	  nfs4namespace.o nfs4getroot.o nfs4client.o
 nfsv4-$(CONFIG_SYSCTL)	+= nfs4sysctl.o
-nfsv4-$(CONFIG_NFS_V4_1)	+= pnfs.o pnfs_dev.o
+nfsv4-$(CONFIG_NFS_V4_1)	+= nfs4session.o pnfs.o pnfs_dev.o
 
 obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o
 nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
index f1027b0..4fa788c 100644
--- a/fs/nfs/blocklayout/blocklayout.c
+++ b/fs/nfs/blocklayout/blocklayout.c
@@ -40,6 +40,7 @@
 #include <linux/pagevec.h>
 
 #include "../pnfs.h"
+#include "../nfs4session.h"
 #include "../internal.h"
 #include "blocklayout.h"
 
diff --git a/fs/nfs/cache_lib.c b/fs/nfs/cache_lib.c
index dded263..862a2f1 100644
--- a/fs/nfs/cache_lib.c
+++ b/fs/nfs/cache_lib.c
@@ -118,7 +118,6 @@ int nfs_cache_register_sb(struct super_block *sb, struct cache_detail *cd)
 	struct dentry *dir;
 
 	dir = rpc_d_lookup_sb(sb, "cache");
-	BUG_ON(dir == NULL);
 	ret = sunrpc_cache_register_pipefs(dir, cd->name, 0600, cd);
 	dput(dir);
 	return ret;
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index 4251c2a..efd54f0a 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -142,7 +142,7 @@ extern __be32 nfs4_callback_recallany(struct cb_recallanyargs *args,
 
 struct cb_recallslotargs {
 	struct sockaddr	*crsa_addr;
-	uint32_t	crsa_target_max_slots;
+	uint32_t	crsa_target_highest_slotid;
 };
 extern __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args,
 					 void *dummy,
@@ -167,8 +167,6 @@ extern __be32 nfs4_callback_layoutrecall(
 	struct cb_layoutrecallargs *args,
 	void *dummy, struct cb_process_state *cps);
 
-extern void nfs4_check_drain_bc_complete(struct nfs4_session *ses);
-
 struct cb_devicenotifyitem {
 	uint32_t		cbd_notify_type;
 	uint32_t		cbd_layout_type;
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 76b4a7a..c89b26b 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -14,6 +14,7 @@
 #include "delegation.h"
 #include "internal.h"
 #include "pnfs.h"
+#include "nfs4session.h"
 
 #ifdef NFS_DEBUG
 #define NFSDBG_FACILITY NFSDBG_CALLBACK
@@ -216,7 +217,6 @@ static u32 initiate_bulk_draining(struct nfs_client *clp,
 			}
 			pnfs_get_layout_hdr(lo);
 			spin_unlock(&ino->i_lock);
-			BUG_ON(!list_empty(&lo->plh_bulk_recall));
 			list_add(&lo->plh_bulk_recall, &recall_list);
 		}
 	}
@@ -562,23 +562,16 @@ __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy,
 	if (!cps->clp) /* set in cb_sequence */
 		goto out;
 
-	dprintk_rcu("NFS: CB_RECALL_SLOT request from %s target max slots %d\n",
+	dprintk_rcu("NFS: CB_RECALL_SLOT request from %s target highest slotid %d\n",
 		rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR),
-		args->crsa_target_max_slots);
+		args->crsa_target_highest_slotid);
 
 	fc_tbl = &cps->clp->cl_session->fc_slot_table;
 
-	status = htonl(NFS4ERR_BAD_HIGH_SLOT);
-	if (args->crsa_target_max_slots > fc_tbl->max_slots ||
-	    args->crsa_target_max_slots < 1)
-		goto out;
-
 	status = htonl(NFS4_OK);
-	if (args->crsa_target_max_slots == fc_tbl->max_slots)
-		goto out;
 
-	fc_tbl->target_max_slots = args->crsa_target_max_slots;
-	nfs41_handle_recall_slot(cps->clp);
+	nfs41_set_target_slotid(fc_tbl, args->crsa_target_highest_slotid);
+	nfs41_server_notify_target_slotid_update(cps->clp);
 out:
 	dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
 	return status;
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 742ff4f..59461c9 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -16,6 +16,7 @@
 #include "nfs4_fs.h"
 #include "callback.h"
 #include "internal.h"
+#include "nfs4session.h"
 
 #define CB_OP_TAGLEN_MAXSZ	(512)
 #define CB_OP_HDR_RES_MAXSZ	(2 + CB_OP_TAGLEN_MAXSZ)
@@ -520,7 +521,7 @@ static __be32 decode_recallslot_args(struct svc_rqst *rqstp,
 	p = read_buf(xdr, 4);
 	if (unlikely(p == NULL))
 		return htonl(NFS4ERR_BADXDR);
-	args->crsa_target_max_slots = ntohl(*p++);
+	args->crsa_target_highest_slotid = ntohl(*p++);
 	return 0;
 }
 
@@ -762,7 +763,7 @@ static void nfs4_callback_free_slot(struct nfs4_session *session)
 	 * A single slot, so highest used slotid is either 0 or -1
 	 */
 	tbl->highest_used_slotid = NFS4_NO_SLOT;
-	nfs4_check_drain_bc_complete(session);
+	nfs4_session_drain_complete(session, tbl);
 	spin_unlock(&tbl->slot_tbl_lock);
 }
 
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 8b39a42..d3918b0 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -72,6 +72,7 @@ static const struct rpc_version *nfs_version[5] = {
 
 const struct rpc_program nfs_program = {
 	.name			= "nfs",
+	.service_name		= "nfs",
 	.number			= NFS_PROGRAM,
 	.nrvers			= ARRAY_SIZE(nfs_version),
 	.version		= nfs_version,
@@ -277,7 +278,7 @@ void nfs_put_client(struct nfs_client *clp)
 		nfs_cb_idr_remove_locked(clp);
 		spin_unlock(&nn->nfs_client_lock);
 
-		BUG_ON(!list_empty(&clp->cl_superblocks));
+		WARN_ON_ONCE(!list_empty(&clp->cl_superblocks));
 
 		clp->rpc_ops->free_client(clp);
 	}
@@ -1061,10 +1062,6 @@ struct nfs_server *nfs_create_server(struct nfs_mount_info *mount_info,
 	if (error < 0)
 		goto error;
 
-	BUG_ON(!server->nfs_client);
-	BUG_ON(!server->nfs_client->rpc_ops);
-	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
-
 	/* Probe the root fh to retrieve its FSID */
 	error = nfs_probe_fsinfo(server, mount_info->mntfh, fattr);
 	if (error < 0)
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 9cc4a3f..bc3968f 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -193,19 +193,15 @@ static int nfs_idmap_init_keyring(void)
 	if (!cred)
 		return -ENOMEM;
 
-	keyring = key_alloc(&key_type_keyring, ".id_resolver", 0, 0, cred,
-			     (KEY_POS_ALL & ~KEY_POS_SETATTR) |
-			     KEY_USR_VIEW | KEY_USR_READ,
-			     KEY_ALLOC_NOT_IN_QUOTA);
+	keyring = keyring_alloc(".id_resolver", 0, 0, cred,
+				(KEY_POS_ALL & ~KEY_POS_SETATTR) |
+				KEY_USR_VIEW | KEY_USR_READ,
+				KEY_ALLOC_NOT_IN_QUOTA, NULL);
 	if (IS_ERR(keyring)) {
 		ret = PTR_ERR(keyring);
 		goto failed_put_cred;
 	}
 
-	ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
-	if (ret < 0)
-		goto failed_put_key;
-
 	ret = register_key_type(&key_type_id_resolver);
 	if (ret < 0)
 		goto failed_put_key;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 6fa01ae..117183b 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -112,8 +112,8 @@ void nfs_clear_inode(struct inode *inode)
 	/*
 	 * The following should never happen...
 	 */
-	BUG_ON(nfs_have_writebacks(inode));
-	BUG_ON(!list_empty(&NFS_I(inode)->open_files));
+	WARN_ON_ONCE(nfs_have_writebacks(inode));
+	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);
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 05521ca..fb99447 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -18,27 +18,6 @@ struct nfs_string;
  */
 #define NFS_MAX_READAHEAD	(RPC_DEF_SLOT_TABLE - 1)
 
-/*
- * Determine if sessions are in use.
- */
-static inline int nfs4_has_session(const struct nfs_client *clp)
-{
-#ifdef CONFIG_NFS_V4_1
-	if (clp->cl_session)
-		return 1;
-#endif /* CONFIG_NFS_V4_1 */
-	return 0;
-}
-
-static inline int nfs4_has_persistent_session(const struct nfs_client *clp)
-{
-#ifdef CONFIG_NFS_V4_1
-	if (nfs4_has_session(clp))
-		return (clp->cl_session->flags & SESSION4_PERSIST);
-#endif /* CONFIG_NFS_V4_1 */
-	return 0;
-}
-
 static inline void nfs_attr_check_mountpoint(struct super_block *parent, struct nfs_fattr *fattr)
 {
 	if (!nfs_fsid_equal(&NFS_SB(parent)->fsid, &fattr->fsid))
@@ -276,8 +255,6 @@ extern const u32 nfs41_maxwrite_overhead;
 extern struct rpc_procinfo nfs4_procedures[];
 #endif
 
-extern int nfs4_init_ds_session(struct nfs_client *, unsigned long);
-
 /* proc.c */
 void nfs_close_context(struct nfs_open_context *ctx, int is_sync);
 extern struct nfs_client *nfs_init_client(struct nfs_client *clp,
@@ -474,18 +451,6 @@ extern struct nfs_client *nfs4_init_client(struct nfs_client *clp,
 			    const struct rpc_timeout *timeparms,
 			    const char *ip_addr,
 			    rpc_authflavor_t authflavour);
-extern int _nfs4_call_sync(struct rpc_clnt *clnt,
-			   struct nfs_server *server,
-			   struct rpc_message *msg,
-			   struct nfs4_sequence_args *args,
-			   struct nfs4_sequence_res *res,
-			   int cache_reply);
-extern int _nfs4_call_sync_session(struct rpc_clnt *clnt,
-				   struct nfs_server *server,
-				   struct rpc_message *msg,
-				   struct nfs4_sequence_args *args,
-				   struct nfs4_sequence_res *res,
-				   int cache_reply);
 extern int nfs40_walk_client_list(struct nfs_client *clp,
 				struct nfs_client **result,
 				struct rpc_cred *cred);
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index 015f71f..01dedb4 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -169,6 +169,9 @@ int nfs_mount(struct nfs_mount_request *info)
 		(info->hostname ? info->hostname : "server"),
 			info->dirpath);
 
+	if (strlen(info->dirpath) > MNTPATHLEN)
+		return -ENAMETOOLONG;
+
 	if (info->noresvport)
 		args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
 
@@ -242,6 +245,9 @@ void nfs_umount(const struct nfs_mount_request *info)
 	struct rpc_clnt *clnt;
 	int status;
 
+	if (strlen(info->dirpath) > MNTPATHLEN)
+		return;
+
 	if (info->noresvport)
 		args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
 
@@ -283,7 +289,6 @@ static void encode_mntdirpath(struct xdr_stream *xdr, const char *pathname)
 	const u32 pathname_len = strlen(pathname);
 	__be32 *p;
 
-	BUG_ON(pathname_len > MNTPATHLEN);
 	p = xdr_reserve_space(xdr, 4 + pathname_len);
 	xdr_encode_opaque(p, pathname, pathname_len);
 }
@@ -511,6 +516,7 @@ static struct rpc_stat mnt_stats;
 
 static const struct rpc_program mnt_program = {
 	.name		= "mount",
+	.service_name	= "mountd",
 	.number		= NFS_MNT_PROGRAM,
 	.nrvers		= ARRAY_SIZE(mnt_version),
 	.version	= mnt_version,
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index d04f0df..06b9df4 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -195,7 +195,6 @@ static void encode_fhandle(struct xdr_stream *xdr, const struct nfs_fh *fh)
 {
 	__be32 *p;
 
-	BUG_ON(fh->size != NFS2_FHSIZE);
 	p = xdr_reserve_space(xdr, NFS2_FHSIZE);
 	memcpy(p, fh->data, NFS2_FHSIZE);
 }
@@ -388,7 +387,7 @@ static void encode_filename(struct xdr_stream *xdr,
 {
 	__be32 *p;
 
-	BUG_ON(length > NFS2_MAXNAMLEN);
+	WARN_ON_ONCE(length > NFS2_MAXNAMLEN);
 	p = xdr_reserve_space(xdr, 4 + length);
 	xdr_encode_opaque(p, name, length);
 }
@@ -428,7 +427,6 @@ static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length)
 {
 	__be32 *p;
 
-	BUG_ON(length > NFS2_MAXPATHLEN);
 	p = xdr_reserve_space(xdr, 4);
 	*p = cpu_to_be32(length);
 	xdr_write_pages(xdr, pages, 0, length);
diff --git a/fs/nfs/nfs3client.c b/fs/nfs/nfs3client.c
index b3fc65e..551c00f 100644
--- a/fs/nfs/nfs3client.c
+++ b/fs/nfs/nfs3client.c
@@ -10,6 +10,8 @@ static const struct rpc_version *nfsacl_version[] = {
 
 const struct rpc_program nfsacl_program = {
 	.name			= "nfsacl",
+	.service_name		= "nfs",	/* nfsacl belongs to the nfs
+						 * service on the server. */
 	.number			= NFS_ACL_PROGRAM,
 	.nrvers			= ARRAY_SIZE(nfsacl_version),
 	.version		= nfsacl_version,
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 6cbe894..bffc324 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -198,7 +198,7 @@ static void encode_filename3(struct xdr_stream *xdr,
 {
 	__be32 *p;
 
-	BUG_ON(length > NFS3_MAXNAMLEN);
+	WARN_ON_ONCE(length > NFS3_MAXNAMLEN);
 	p = xdr_reserve_space(xdr, 4 + length);
 	xdr_encode_opaque(p, name, length);
 }
@@ -238,7 +238,6 @@ out_overflow:
 static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages,
 			    const u32 length)
 {
-	BUG_ON(length > NFS3_MAXPATHLEN);
 	encode_uint32(xdr, length);
 	xdr_write_pages(xdr, pages, 0, length);
 }
@@ -388,7 +387,6 @@ out_overflow:
  */
 static void encode_ftype3(struct xdr_stream *xdr, const u32 type)
 {
-	BUG_ON(type > NF3FIFO);
 	encode_uint32(xdr, type);
 }
 
@@ -443,7 +441,7 @@ static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh)
 {
 	__be32 *p;
 
-	BUG_ON(fh->size > NFS3_FHSIZE);
+	WARN_ON_ONCE(fh->size > NFS3_FHSIZE);
 	p = xdr_reserve_space(xdr, 4 + fh->size);
 	xdr_encode_opaque(p, fh->data, fh->size);
 }
@@ -1339,6 +1337,7 @@ static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req,
 	error = nfsacl_encode(xdr->buf, base, args->inode,
 			    (args->mask & NFS_ACL) ?
 			    args->acl_access : NULL, 1, 0);
+	/* FIXME: this is just broken */
 	BUG_ON(error < 0);
 	error = nfsacl_encode(xdr->buf, base + error, args->inode,
 			    (args->mask & NFS_DFACL) ?
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index a525fde..a3f488b 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -11,6 +11,8 @@
 
 #if IS_ENABLED(CONFIG_NFS_V4)
 
+#define NFS4_MAX_LOOP_ON_RECOVER (10)
+
 struct idmap;
 
 enum nfs4_client_state {
@@ -21,18 +23,12 @@ enum nfs4_client_state {
 	NFS4CLNT_RECLAIM_NOGRACE,
 	NFS4CLNT_DELEGRETURN,
 	NFS4CLNT_SESSION_RESET,
-	NFS4CLNT_RECALL_SLOT,
 	NFS4CLNT_LEASE_CONFIRM,
 	NFS4CLNT_SERVER_SCOPE_MISMATCH,
 	NFS4CLNT_PURGE_STATE,
 	NFS4CLNT_BIND_CONN_TO_SESSION,
 };
 
-enum nfs4_session_state {
-	NFS4_SESSION_INITING,
-	NFS4_SESSION_DRAINING,
-};
-
 #define NFS4_RENEW_TIMEOUT		0x01
 #define NFS4_RENEW_DELEGATION_CB	0x02
 
@@ -43,8 +39,7 @@ struct nfs4_minor_version_ops {
 			struct nfs_server *server,
 			struct rpc_message *msg,
 			struct nfs4_sequence_args *args,
-			struct nfs4_sequence_res *res,
-			int cache_reply);
+			struct nfs4_sequence_res *res);
 	bool	(*match_stateid)(const nfs4_stateid *,
 			const nfs4_stateid *);
 	int	(*find_root_sec)(struct nfs_server *, struct nfs_fh *,
@@ -241,18 +236,14 @@ static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *ser
 	return server->nfs_client->cl_session;
 }
 
-extern bool nfs4_set_task_privileged(struct rpc_task *task, void *dummy);
 extern int nfs4_setup_sequence(const struct nfs_server *server,
 		struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
 		struct rpc_task *task);
 extern int nfs41_setup_sequence(struct nfs4_session *session,
 		struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
 		struct rpc_task *task);
-extern void nfs4_destroy_session(struct nfs4_session *session);
-extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp);
 extern int nfs4_proc_create_session(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_proc_destroy_session(struct nfs4_session *, struct rpc_cred *);
-extern int nfs4_init_session(struct nfs_server *server);
 extern int nfs4_proc_get_lease_time(struct nfs_client *clp,
 		struct nfs_fsinfo *fsinfo);
 extern int nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data,
@@ -280,11 +271,7 @@ static inline int nfs4_setup_sequence(const struct nfs_server *server,
 		struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
 		struct rpc_task *task)
 {
-	return 0;
-}
-
-static inline int nfs4_init_session(struct nfs_server *server)
-{
+	rpc_call_start(task);
 	return 0;
 }
 
@@ -321,17 +308,20 @@ extern void nfs4_renew_state(struct work_struct *);
 
 /* nfs4state.c */
 struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp);
+struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp);
 struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp);
 int nfs4_discover_server_trunking(struct nfs_client *clp,
 			struct nfs_client **);
 int nfs40_discover_server_trunking(struct nfs_client *clp,
 			struct nfs_client **, struct rpc_cred *);
 #if defined(CONFIG_NFS_V4_1)
-struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp);
 struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp);
 int nfs41_discover_server_trunking(struct nfs_client *clp,
 			struct nfs_client **, struct rpc_cred *);
 extern void nfs4_schedule_session_recovery(struct nfs4_session *, int);
+extern void nfs41_server_notify_target_slotid_update(struct nfs_client *clp);
+extern void nfs41_server_notify_highest_slotid_update(struct nfs_client *clp);
+
 #else
 static inline void nfs4_schedule_session_recovery(struct nfs4_session *session, int err)
 {
@@ -349,11 +339,12 @@ extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);
 extern void nfs_inode_find_state_and_recover(struct inode *inode,
 		const nfs4_stateid *stateid);
 extern void nfs4_schedule_lease_recovery(struct nfs_client *);
+extern int nfs4_wait_clnt_recover(struct nfs_client *clp);
+extern int nfs4_client_recover_expired_lease(struct nfs_client *clp);
 extern void nfs4_schedule_state_manager(struct nfs_client *);
 extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp);
 extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *);
 extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
-extern void nfs41_handle_recall_slot(struct nfs_client *clp);
 extern void nfs41_handle_server_scope(struct nfs_client *,
 				      struct nfs41_server_scope **);
 extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 6bacfde..acc3472 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -12,6 +12,7 @@
 #include "internal.h"
 #include "callback.h"
 #include "delegation.h"
+#include "nfs4session.h"
 #include "pnfs.h"
 #include "netns.h"
 
@@ -713,10 +714,6 @@ static int nfs4_server_common_setup(struct nfs_server *server,
 	struct nfs_fattr *fattr;
 	int error;
 
-	BUG_ON(!server->nfs_client);
-	BUG_ON(!server->nfs_client->rpc_ops);
-	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
-
 	/* data servers support only a subset of NFSv4.1 */
 	if (is_ds_only_client(server->nfs_client))
 		return -EPROTONOSUPPORT;
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
index afddd66..e769930 100644
--- a/fs/nfs/nfs4file.c
+++ b/fs/nfs/nfs4file.c
@@ -20,7 +20,6 @@ nfs4_file_open(struct inode *inode, struct file *filp)
 	struct iattr attr;
 	int err;
 
-	BUG_ON(inode != dentry->d_inode);
 	/*
 	 * If no cached dentry exists or if it's negative, NFSv4 handled the
 	 * opens in ->lookup() or ->create().
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 2e45fd9..1e42413 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -35,6 +35,7 @@
 
 #include <linux/sunrpc/metrics.h>
 
+#include "nfs4session.h"
 #include "internal.h"
 #include "delegation.h"
 #include "nfs4filelayout.h"
@@ -306,12 +307,10 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data)
 	}
 	rdata->read_done_cb = filelayout_read_done_cb;
 
-	if (nfs41_setup_sequence(rdata->ds_clp->cl_session,
-				&rdata->args.seq_args, &rdata->res.seq_res,
-				task))
-		return;
-
-	rpc_call_start(task);
+	nfs41_setup_sequence(rdata->ds_clp->cl_session,
+			&rdata->args.seq_args,
+			&rdata->res.seq_res,
+			task);
 }
 
 static void filelayout_read_call_done(struct rpc_task *task, void *data)
@@ -408,12 +407,10 @@ static void filelayout_write_prepare(struct rpc_task *task, void *data)
 		rpc_exit(task, 0);
 		return;
 	}
-	if (nfs41_setup_sequence(wdata->ds_clp->cl_session,
-				&wdata->args.seq_args, &wdata->res.seq_res,
-				task))
-		return;
-
-	rpc_call_start(task);
+	nfs41_setup_sequence(wdata->ds_clp->cl_session,
+			&wdata->args.seq_args,
+			&wdata->res.seq_res,
+			task);
 }
 
 static void filelayout_write_call_done(struct rpc_task *task, void *data)
@@ -449,12 +446,10 @@ static void filelayout_commit_prepare(struct rpc_task *task, void *data)
 {
 	struct nfs_commit_data *wdata = data;
 
-	if (nfs41_setup_sequence(wdata->ds_clp->cl_session,
-				&wdata->args.seq_args, &wdata->res.seq_res,
-				task))
-		return;
-
-	rpc_call_start(task);
+	nfs41_setup_sequence(wdata->ds_clp->cl_session,
+			&wdata->args.seq_args,
+			&wdata->res.seq_res,
+			task);
 }
 
 static void filelayout_write_commit_done(struct rpc_task *task, void *data)
@@ -512,7 +507,6 @@ filelayout_read_pagelist(struct nfs_read_data *data)
 	loff_t offset = data->args.offset;
 	u32 j, idx;
 	struct nfs_fh *fh;
-	int status;
 
 	dprintk("--> %s ino %lu pgbase %u req %Zu@%llu\n",
 		__func__, hdr->inode->i_ino,
@@ -538,9 +532,8 @@ filelayout_read_pagelist(struct nfs_read_data *data)
 	data->mds_offset = offset;
 
 	/* Perform an asynchronous read to ds */
-	status = nfs_initiate_read(ds->ds_clp->cl_rpcclient, data,
+	nfs_initiate_read(ds->ds_clp->cl_rpcclient, data,
 				  &filelayout_read_call_ops, RPC_TASK_SOFTCONN);
-	BUG_ON(status != 0);
 	return PNFS_ATTEMPTED;
 }
 
@@ -554,7 +547,6 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync)
 	loff_t offset = data->args.offset;
 	u32 j, idx;
 	struct nfs_fh *fh;
-	int status;
 
 	/* Retrieve the correct rpc_client for the byte range */
 	j = nfs4_fl_calc_j_index(lseg, offset);
@@ -579,10 +571,9 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync)
 	data->args.offset = filelayout_get_dserver_offset(lseg, offset);
 
 	/* Perform an asynchronous write */
-	status = nfs_initiate_write(ds->ds_clp->cl_rpcclient, data,
+	nfs_initiate_write(ds->ds_clp->cl_rpcclient, data,
 				    &filelayout_write_call_ops, sync,
 				    RPC_TASK_SOFTCONN);
-	BUG_ON(status != 0);
 	return PNFS_ATTEMPTED;
 }
 
@@ -909,7 +900,7 @@ static void
 filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio,
 			struct nfs_page *req)
 {
-	BUG_ON(pgio->pg_lseg != NULL);
+	WARN_ON_ONCE(pgio->pg_lseg != NULL);
 
 	if (req->wb_offset != req->wb_pgbase) {
 		/*
@@ -939,7 +930,7 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
 	struct nfs_commit_info cinfo;
 	int status;
 
-	BUG_ON(pgio->pg_lseg != NULL);
+	WARN_ON_ONCE(pgio->pg_lseg != NULL);
 
 	if (req->wb_offset != req->wb_pgbase)
 		goto out_mds;
@@ -1187,7 +1178,6 @@ static void filelayout_recover_commit_reqs(struct list_head *dst,
 	 */
 	for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) {
 		if (transfer_commit_list(&b->written, dst, cinfo, 0)) {
-			BUG_ON(!list_empty(&b->written));
 			pnfs_put_lseg(b->wlseg);
 			b->wlseg = NULL;
 		}
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index a8eaa9b..b720064 100644
--- a/fs/nfs/nfs4filelayoutdev.c
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -33,6 +33,7 @@
 #include <linux/module.h>
 
 #include "internal.h"
+#include "nfs4session.h"
 #include "nfs4filelayout.h"
 
 #define NFSDBG_FACILITY		NFSDBG_PNFS_LD
@@ -162,8 +163,6 @@ nfs4_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds)
 	dprintk("--> %s DS %s au_flavor %d\n", __func__, ds->ds_remotestr,
 		mds_srv->nfs_client->cl_rpcclient->cl_auth->au_flavor);
 
-	BUG_ON(list_empty(&ds->ds_addrs));
-
 	list_for_each_entry(da, &ds->ds_addrs, da_node) {
 		dprintk("%s: DS %s: trying address %s\n",
 			__func__, ds->ds_remotestr, da->da_remotestr);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 5eec442..99d99a5 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -52,7 +52,6 @@
 #include <linux/mount.h>
 #include <linux/module.h>
 #include <linux/nfs_idmap.h>
-#include <linux/sunrpc/bc_xprt.h>
 #include <linux/xattr.h>
 #include <linux/utsname.h>
 #include <linux/freezer.h>
@@ -64,14 +63,14 @@
 #include "callback.h"
 #include "pnfs.h"
 #include "netns.h"
+#include "nfs4session.h"
+
 
 #define NFSDBG_FACILITY		NFSDBG_PROC
 
 #define NFS4_POLL_RETRY_MIN	(HZ/10)
 #define NFS4_POLL_RETRY_MAX	(15*HZ)
 
-#define NFS4_MAX_LOOP_ON_RECOVER (10)
-
 struct nfs4_opendata;
 static int _nfs4_proc_open(struct nfs4_opendata *data);
 static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
@@ -206,7 +205,6 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
 {
 	__be32 *start, *p;
 
-	BUG_ON(readdir->count < 80);
 	if (cookie > 2) {
 		readdir->cookie = cookie;
 		memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier));
@@ -256,22 +254,6 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
 	kunmap_atomic(start);
 }
 
-static int nfs4_wait_clnt_recover(struct nfs_client *clp)
-{
-	int res;
-
-	might_sleep();
-
-	res = wait_on_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING,
-			nfs_wait_bit_killable, TASK_KILLABLE);
-	if (res)
-		return res;
-
-	if (clp->cl_cons_state < 0)
-		return clp->cl_cons_state;
-	return 0;
-}
-
 static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
 {
 	int res = 0;
@@ -397,97 +379,46 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp
 
 #if defined(CONFIG_NFS_V4_1)
 
-/*
- * nfs4_free_slot - free a slot and efficiently update slot table.
- *
- * freeing a slot is trivially done by clearing its respective bit
- * in the bitmap.
- * If the freed slotid equals highest_used_slotid we want to update it
- * so that the server would be able to size down the slot table if needed,
- * otherwise we know that the highest_used_slotid is still in use.
- * When updating highest_used_slotid there may be "holes" in the bitmap
- * so we need to scan down from highest_used_slotid to 0 looking for the now
- * highest slotid in use.
- * If none found, highest_used_slotid is set to NFS4_NO_SLOT.
- *
- * Must be called while holding tbl->slot_tbl_lock
- */
-static void
-nfs4_free_slot(struct nfs4_slot_table *tbl, u32 slotid)
-{
-	BUG_ON(slotid >= NFS4_MAX_SLOT_TABLE);
-	/* clear used bit in bitmap */
-	__clear_bit(slotid, tbl->used_slots);
-
-	/* update highest_used_slotid when it is freed */
-	if (slotid == tbl->highest_used_slotid) {
-		slotid = find_last_bit(tbl->used_slots, tbl->max_slots);
-		if (slotid < tbl->max_slots)
-			tbl->highest_used_slotid = slotid;
-		else
-			tbl->highest_used_slotid = NFS4_NO_SLOT;
-	}
-	dprintk("%s: slotid %u highest_used_slotid %d\n", __func__,
-		slotid, tbl->highest_used_slotid);
-}
-
-bool nfs4_set_task_privileged(struct rpc_task *task, void *dummy)
-{
-	rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
-	return true;
-}
-
-/*
- * Signal state manager thread if session fore channel is drained
- */
-static void nfs4_check_drain_fc_complete(struct nfs4_session *ses)
-{
-	if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state)) {
-		rpc_wake_up_first(&ses->fc_slot_table.slot_tbl_waitq,
-				nfs4_set_task_privileged, NULL);
-		return;
-	}
-
-	if (ses->fc_slot_table.highest_used_slotid != NFS4_NO_SLOT)
-		return;
-
-	dprintk("%s COMPLETE: Session Fore Channel Drained\n", __func__);
-	complete(&ses->fc_slot_table.complete);
-}
-
-/*
- * Signal state manager thread if session back channel is drained
- */
-void nfs4_check_drain_bc_complete(struct nfs4_session *ses)
-{
-	if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state) ||
-	    ses->bc_slot_table.highest_used_slotid != NFS4_NO_SLOT)
-		return;
-	dprintk("%s COMPLETE: Session Back Channel Drained\n", __func__);
-	complete(&ses->bc_slot_table.complete);
-}
-
 static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
 {
+	struct nfs4_session *session;
 	struct nfs4_slot_table *tbl;
+	bool send_new_highest_used_slotid = false;
 
-	tbl = &res->sr_session->fc_slot_table;
 	if (!res->sr_slot) {
 		/* just wake up the next guy waiting since
 		 * we may have not consumed a slot after all */
 		dprintk("%s: No slot\n", __func__);
 		return;
 	}
+	tbl = res->sr_slot->table;
+	session = tbl->session;
 
 	spin_lock(&tbl->slot_tbl_lock);
-	nfs4_free_slot(tbl, res->sr_slot - tbl->slots);
-	nfs4_check_drain_fc_complete(res->sr_session);
+	/* Be nice to the server: try to ensure that the last transmitted
+	 * value for highest_user_slotid <= target_highest_slotid
+	 */
+	if (tbl->highest_used_slotid > tbl->target_highest_slotid)
+		send_new_highest_used_slotid = true;
+
+	nfs4_free_slot(tbl, res->sr_slot);
+
+	if (tbl->highest_used_slotid != NFS4_NO_SLOT)
+		send_new_highest_used_slotid = false;
+	if (!nfs4_session_draining(session)) {
+		if (rpc_wake_up_next(&tbl->slot_tbl_waitq) != NULL)
+			send_new_highest_used_slotid = false;
+	}
 	spin_unlock(&tbl->slot_tbl_lock);
 	res->sr_slot = NULL;
+	if (send_new_highest_used_slotid)
+		nfs41_server_notify_highest_slotid_update(session->clp);
 }
 
 static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
 {
+	struct nfs4_session *session;
+	struct nfs4_slot *slot;
 	unsigned long timestamp;
 	struct nfs_client *clp;
 
@@ -504,31 +435,35 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
 	if (!RPC_WAS_SENT(task))
 		goto out;
 
+	slot = res->sr_slot;
+	session = slot->table->session;
+
 	/* Check the SEQUENCE operation status */
 	switch (res->sr_status) {
 	case 0:
 		/* Update the slot's sequence and clientid lease timer */
-		++res->sr_slot->seq_nr;
-		timestamp = res->sr_renewal_time;
-		clp = res->sr_session->clp;
+		++slot->seq_nr;
+		timestamp = slot->renewal_time;
+		clp = session->clp;
 		do_renew_lease(clp, timestamp);
 		/* Check sequence flags */
 		if (res->sr_status_flags != 0)
 			nfs4_schedule_lease_recovery(clp);
+		nfs41_update_target_slotid(slot->table, slot, res);
 		break;
 	case -NFS4ERR_DELAY:
 		/* The server detected a resend of the RPC call and
 		 * returned NFS4ERR_DELAY as per Section 2.10.6.2
 		 * of RFC5661.
 		 */
-		dprintk("%s: slot=%td seq=%d: Operation in progress\n",
+		dprintk("%s: slot=%u seq=%u: Operation in progress\n",
 			__func__,
-			res->sr_slot - res->sr_session->fc_slot_table.slots,
-			res->sr_slot->seq_nr);
+			slot->slot_nr,
+			slot->seq_nr);
 		goto out_retry;
 	default:
 		/* Just update the slot sequence no. */
-		++res->sr_slot->seq_nr;
+		++slot->seq_nr;
 	}
 out:
 	/* The session may be reset by one of the error handlers. */
@@ -545,55 +480,27 @@ out_retry:
 static int nfs4_sequence_done(struct rpc_task *task,
 			       struct nfs4_sequence_res *res)
 {
-	if (res->sr_session == NULL)
+	if (res->sr_slot == NULL)
 		return 1;
 	return nfs41_sequence_done(task, res);
 }
 
-/*
- * nfs4_find_slot - efficiently look for a free slot
- *
- * nfs4_find_slot looks for an unset bit in the used_slots bitmap.
- * If found, we mark the slot as used, update the highest_used_slotid,
- * and respectively set up the sequence operation args.
- * The slot number is returned if found, or NFS4_NO_SLOT otherwise.
- *
- * Note: must be called with under the slot_tbl_lock.
- */
-static u32
-nfs4_find_slot(struct nfs4_slot_table *tbl)
-{
-	u32 slotid;
-	u32 ret_id = NFS4_NO_SLOT;
-
-	dprintk("--> %s used_slots=%04lx highest_used=%u max_slots=%u\n",
-		__func__, tbl->used_slots[0], tbl->highest_used_slotid,
-		tbl->max_slots);
-	slotid = find_first_zero_bit(tbl->used_slots, tbl->max_slots);
-	if (slotid >= tbl->max_slots)
-		goto out;
-	__set_bit(slotid, tbl->used_slots);
-	if (slotid > tbl->highest_used_slotid ||
-			tbl->highest_used_slotid == NFS4_NO_SLOT)
-		tbl->highest_used_slotid = slotid;
-	ret_id = slotid;
-out:
-	dprintk("<-- %s used_slots=%04lx highest_used=%d slotid=%d \n",
-		__func__, tbl->used_slots[0], tbl->highest_used_slotid, ret_id);
-	return ret_id;
-}
-
 static void nfs41_init_sequence(struct nfs4_sequence_args *args,
 		struct nfs4_sequence_res *res, int cache_reply)
 {
-	args->sa_session = NULL;
+	args->sa_slot = NULL;
 	args->sa_cache_this = 0;
+	args->sa_privileged = 0;
 	if (cache_reply)
 		args->sa_cache_this = 1;
-	res->sr_session = NULL;
 	res->sr_slot = NULL;
 }
 
+static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args)
+{
+	args->sa_privileged = 1;
+}
+
 int nfs41_setup_sequence(struct nfs4_session *session,
 				struct nfs4_sequence_args *args,
 				struct nfs4_sequence_res *res,
@@ -601,59 +508,58 @@ int nfs41_setup_sequence(struct nfs4_session *session,
 {
 	struct nfs4_slot *slot;
 	struct nfs4_slot_table *tbl;
-	u32 slotid;
 
 	dprintk("--> %s\n", __func__);
 	/* slot already allocated? */
 	if (res->sr_slot != NULL)
-		return 0;
+		goto out_success;
 
 	tbl = &session->fc_slot_table;
 
+	task->tk_timeout = 0;
+
 	spin_lock(&tbl->slot_tbl_lock);
 	if (test_bit(NFS4_SESSION_DRAINING, &session->session_state) &&
-	    !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) {
+	    !args->sa_privileged) {
 		/* The state manager will wait until the slot table is empty */
-		rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
-		spin_unlock(&tbl->slot_tbl_lock);
 		dprintk("%s session is draining\n", __func__);
-		return -EAGAIN;
-	}
-
-	if (!rpc_queue_empty(&tbl->slot_tbl_waitq) &&
-	    !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) {
-		rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
-		spin_unlock(&tbl->slot_tbl_lock);
-		dprintk("%s enforce FIFO order\n", __func__);
-		return -EAGAIN;
+		goto out_sleep;
 	}
 
-	slotid = nfs4_find_slot(tbl);
-	if (slotid == NFS4_NO_SLOT) {
-		rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
-		spin_unlock(&tbl->slot_tbl_lock);
+	slot = nfs4_alloc_slot(tbl);
+	if (IS_ERR(slot)) {
+		/* If out of memory, try again in 1/4 second */
+		if (slot == ERR_PTR(-ENOMEM))
+			task->tk_timeout = HZ >> 2;
 		dprintk("<-- %s: no free slots\n", __func__);
-		return -EAGAIN;
+		goto out_sleep;
 	}
 	spin_unlock(&tbl->slot_tbl_lock);
 
-	rpc_task_set_priority(task, RPC_PRIORITY_NORMAL);
-	slot = tbl->slots + slotid;
-	args->sa_session = session;
-	args->sa_slotid = slotid;
+	args->sa_slot = slot;
 
-	dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr);
+	dprintk("<-- %s slotid=%d seqid=%d\n", __func__,
+			slot->slot_nr, slot->seq_nr);
 
-	res->sr_session = session;
 	res->sr_slot = slot;
-	res->sr_renewal_time = jiffies;
 	res->sr_status_flags = 0;
 	/*
 	 * sr_status is only set in decode_sequence, and so will remain
 	 * set to 1 if an rpc level failure occurs.
 	 */
 	res->sr_status = 1;
+out_success:
+	rpc_call_start(task);
 	return 0;
+out_sleep:
+	/* Privileged tasks are queued with top priority */
+	if (args->sa_privileged)
+		rpc_sleep_on_priority(&tbl->slot_tbl_waitq, task,
+				NULL, RPC_PRIORITY_PRIVILEGED);
+	else
+		rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
+	spin_unlock(&tbl->slot_tbl_lock);
+	return -EAGAIN;
 }
 EXPORT_SYMBOL_GPL(nfs41_setup_sequence);
 
@@ -665,12 +571,14 @@ int nfs4_setup_sequence(const struct nfs_server *server,
 	struct nfs4_session *session = nfs4_get_session(server);
 	int ret = 0;
 
-	if (session == NULL)
+	if (session == NULL) {
+		rpc_call_start(task);
 		goto out;
+	}
 
-	dprintk("--> %s clp %p session %p sr_slot %td\n",
+	dprintk("--> %s clp %p session %p sr_slot %d\n",
 		__func__, session->clp, session, res->sr_slot ?
-			res->sr_slot - session->fc_slot_table.slots : -1);
+			res->sr_slot->slot_nr : -1);
 
 	ret = nfs41_setup_sequence(session, args, res, task);
 out:
@@ -687,19 +595,11 @@ struct nfs41_call_sync_data {
 static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata)
 {
 	struct nfs41_call_sync_data *data = calldata;
+	struct nfs4_session *session = nfs4_get_session(data->seq_server);
 
 	dprintk("--> %s data->seq_server %p\n", __func__, data->seq_server);
 
-	if (nfs4_setup_sequence(data->seq_server, data->seq_args,
-				data->seq_res, task))
-		return;
-	rpc_call_start(task);
-}
-
-static void nfs41_call_priv_sync_prepare(struct rpc_task *task, void *calldata)
-{
-	rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
-	nfs41_call_sync_prepare(task, calldata);
+	nfs41_setup_sequence(session, data->seq_args, data->seq_res, task);
 }
 
 static void nfs41_call_sync_done(struct rpc_task *task, void *calldata)
@@ -714,17 +614,11 @@ static const struct rpc_call_ops nfs41_call_sync_ops = {
 	.rpc_call_done = nfs41_call_sync_done,
 };
 
-static const struct rpc_call_ops nfs41_call_priv_sync_ops = {
-	.rpc_call_prepare = nfs41_call_priv_sync_prepare,
-	.rpc_call_done = nfs41_call_sync_done,
-};
-
 static int nfs4_call_sync_sequence(struct rpc_clnt *clnt,
 				   struct nfs_server *server,
 				   struct rpc_message *msg,
 				   struct nfs4_sequence_args *args,
-				   struct nfs4_sequence_res *res,
-				   int privileged)
+				   struct nfs4_sequence_res *res)
 {
 	int ret;
 	struct rpc_task *task;
@@ -740,8 +634,6 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt,
 		.callback_data = &data
 	};
 
-	if (privileged)
-		task_setup.callback_ops = &nfs41_call_priv_sync_ops;
 	task = rpc_run_task(&task_setup);
 	if (IS_ERR(task))
 		ret = PTR_ERR(task);
@@ -752,24 +644,18 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt,
 	return ret;
 }
 
-int _nfs4_call_sync_session(struct rpc_clnt *clnt,
-			    struct nfs_server *server,
-			    struct rpc_message *msg,
-			    struct nfs4_sequence_args *args,
-			    struct nfs4_sequence_res *res,
-			    int cache_reply)
-{
-	nfs41_init_sequence(args, res, cache_reply);
-	return nfs4_call_sync_sequence(clnt, server, msg, args, res, 0);
-}
-
 #else
-static inline
+static
 void nfs41_init_sequence(struct nfs4_sequence_args *args,
 		struct nfs4_sequence_res *res, int cache_reply)
 {
 }
 
+static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args)
+{
+}
+
+
 static int nfs4_sequence_done(struct rpc_task *task,
 			       struct nfs4_sequence_res *res)
 {
@@ -777,18 +663,17 @@ static int nfs4_sequence_done(struct rpc_task *task,
 }
 #endif /* CONFIG_NFS_V4_1 */
 
+static
 int _nfs4_call_sync(struct rpc_clnt *clnt,
 		    struct nfs_server *server,
 		    struct rpc_message *msg,
 		    struct nfs4_sequence_args *args,
-		    struct nfs4_sequence_res *res,
-		    int cache_reply)
+		    struct nfs4_sequence_res *res)
 {
-	nfs41_init_sequence(args, res, cache_reply);
 	return rpc_call_sync(clnt, msg, 0);
 }
 
-static inline
+static
 int nfs4_call_sync(struct rpc_clnt *clnt,
 		   struct nfs_server *server,
 		   struct rpc_message *msg,
@@ -796,8 +681,9 @@ int nfs4_call_sync(struct rpc_clnt *clnt,
 		   struct nfs4_sequence_res *res,
 		   int cache_reply)
 {
+	nfs41_init_sequence(args, res, cache_reply);
 	return server->nfs_client->cl_mvops->call_sync(clnt, server, msg,
-						args, res, cache_reply);
+						args, res);
 }
 
 static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
@@ -1574,20 +1460,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
 				&data->o_res.seq_res,
 				task) != 0)
 		nfs_release_seqid(data->o_arg.seqid);
-	else
-		rpc_call_start(task);
 	return;
 unlock_no_action:
 	rcu_read_unlock();
 out_no_action:
 	task->tk_action = NULL;
-
-}
-
-static void nfs4_recover_open_prepare(struct rpc_task *task, void *calldata)
-{
-	rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
-	nfs4_open_prepare(task, calldata);
 }
 
 static void nfs4_open_done(struct rpc_task *task, void *calldata)
@@ -1648,12 +1525,6 @@ static const struct rpc_call_ops nfs4_open_ops = {
 	.rpc_release = nfs4_open_release,
 };
 
-static const struct rpc_call_ops nfs4_recover_open_ops = {
-	.rpc_call_prepare = nfs4_recover_open_prepare,
-	.rpc_call_done = nfs4_open_done,
-	.rpc_release = nfs4_open_release,
-};
-
 static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
 {
 	struct inode *dir = data->dir->d_inode;
@@ -1683,7 +1554,7 @@ static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
 	data->rpc_status = 0;
 	data->cancelled = 0;
 	if (isrecover)
-		task_setup_data.callback_ops = &nfs4_recover_open_ops;
+		nfs4_set_sequence_privileged(&o_arg->seq_args);
 	task = rpc_run_task(&task_setup_data);
         if (IS_ERR(task))
                 return PTR_ERR(task);
@@ -1789,24 +1660,6 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
 	return 0;
 }
 
-static int nfs4_client_recover_expired_lease(struct nfs_client *clp)
-{
-	unsigned int loop;
-	int ret;
-
-	for (loop = NFS4_MAX_LOOP_ON_RECOVER; loop != 0; loop--) {
-		ret = nfs4_wait_clnt_recover(clp);
-		if (ret != 0)
-			break;
-		if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) &&
-		    !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state))
-			break;
-		nfs4_schedule_state_manager(clp);
-		ret = -EIO;
-	}
-	return ret;
-}
-
 static int nfs4_recover_expired_lease(struct nfs_server *server)
 {
 	return nfs4_client_recover_expired_lease(server->nfs_client);
@@ -2299,8 +2152,6 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
 				&calldata->res.seq_res,
 				task) != 0)
 		nfs_release_seqid(calldata->arg.seqid);
-	else
-		rpc_call_start(task);
 out:
 	dprintk("%s: done!\n", __func__);
 }
@@ -2533,7 +2384,8 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
 	rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS];
 
 	len = rpcauth_list_flavors(flav_array, ARRAY_SIZE(flav_array));
-	BUG_ON(len < 0);
+	if (len < 0)
+		return len;
 
 	for (i = 0; i < len; i++) {
 		/* AUTH_UNIX is the default flavor if none was specified,
@@ -3038,12 +2890,10 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
 
 static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data)
 {
-	if (nfs4_setup_sequence(NFS_SERVER(data->dir),
-				&data->args.seq_args,
-				&data->res.seq_res,
-				task))
-		return;
-	rpc_call_start(task);
+	nfs4_setup_sequence(NFS_SERVER(data->dir),
+			&data->args.seq_args,
+			&data->res.seq_res,
+			task);
 }
 
 static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
@@ -3071,12 +2921,10 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
 
 static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data)
 {
-	if (nfs4_setup_sequence(NFS_SERVER(data->old_dir),
-				&data->args.seq_args,
-				&data->res.seq_res,
-				task))
-		return;
-	rpc_call_start(task);
+	nfs4_setup_sequence(NFS_SERVER(data->old_dir),
+			&data->args.seq_args,
+			&data->res.seq_res,
+			task);
 }
 
 static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
@@ -3362,9 +3210,6 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
 	int mode = sattr->ia_mode;
 	int status = -ENOMEM;
 
-	BUG_ON(!(sattr->ia_valid & ATTR_MODE));
-	BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode));
-
 	data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4SOCK);
 	if (data == NULL)
 		goto out;
@@ -3380,10 +3225,13 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
 		data->arg.ftype = NF4CHR;
 		data->arg.u.device.specdata1 = MAJOR(rdev);
 		data->arg.u.device.specdata2 = MINOR(rdev);
+	} else if (!S_ISSOCK(mode)) {
+		status = -EINVAL;
+		goto out_free;
 	}
 	
 	status = nfs4_do_create(dir, dentry, data);
-
+out_free:
 	nfs4_free_createdata(data);
 out:
 	return status;
@@ -3565,12 +3413,10 @@ static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message
 
 static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data)
 {
-	if (nfs4_setup_sequence(NFS_SERVER(data->header->inode),
-				&data->args.seq_args,
-				&data->res.seq_res,
-				task))
-		return;
-	rpc_call_start(task);
+	nfs4_setup_sequence(NFS_SERVER(data->header->inode),
+			&data->args.seq_args,
+			&data->res.seq_res,
+			task);
 }
 
 static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data)
@@ -3631,22 +3477,18 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag
 
 static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data)
 {
-	if (nfs4_setup_sequence(NFS_SERVER(data->header->inode),
-				&data->args.seq_args,
-				&data->res.seq_res,
-				task))
-		return;
-	rpc_call_start(task);
+	nfs4_setup_sequence(NFS_SERVER(data->header->inode),
+			&data->args.seq_args,
+			&data->res.seq_res,
+			task);
 }
 
 static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
 {
-	if (nfs4_setup_sequence(NFS_SERVER(data->inode),
-				&data->args.seq_args,
-				&data->res.seq_res,
-				task))
-		return;
-	rpc_call_start(task);
+	nfs4_setup_sequence(NFS_SERVER(data->inode),
+			&data->args.seq_args,
+			&data->res.seq_res,
+			task);
 }
 
 static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *data)
@@ -4293,11 +4135,10 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data)
 
 	d_data = (struct nfs4_delegreturndata *)data;
 
-	if (nfs4_setup_sequence(d_data->res.server,
-				&d_data->args.seq_args,
-				&d_data->res.seq_res, task))
-		return;
-	rpc_call_start(task);
+	nfs4_setup_sequence(d_data->res.server,
+			&d_data->args.seq_args,
+			&d_data->res.seq_res,
+			task);
 }
 #endif /* CONFIG_NFS_V4_1 */
 
@@ -4551,8 +4392,6 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
 				&calldata->res.seq_res,
 				task) != 0)
 		nfs_release_seqid(calldata->arg.seqid);
-	else
-		rpc_call_start(task);
 }
 
 static const struct rpc_call_ops nfs4_locku_ops = {
@@ -4696,8 +4535,9 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
 		return;
 	/* Do we need to do an open_to_lock_owner? */
 	if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
-		if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0)
+		if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) {
 			goto out_release_lock_seqid;
+		}
 		data->arg.open_stateid = &state->stateid;
 		data->arg.new_lock_owner = 1;
 		data->res.open_seqid = data->arg.open_seqid;
@@ -4707,20 +4547,12 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
 	if (nfs4_setup_sequence(data->server,
 				&data->arg.seq_args,
 				&data->res.seq_res,
-				task) == 0) {
-		rpc_call_start(task);
+				task) == 0)
 		return;
-	}
 	nfs_release_seqid(data->arg.open_seqid);
 out_release_lock_seqid:
 	nfs_release_seqid(data->arg.lock_seqid);
-	dprintk("%s: done!, ret = %d\n", __func__, task->tk_status);
-}
-
-static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata)
-{
-	rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
-	nfs4_lock_prepare(task, calldata);
+	dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
 }
 
 static void nfs4_lock_done(struct rpc_task *task, void *calldata)
@@ -4775,12 +4607,6 @@ static const struct rpc_call_ops nfs4_lock_ops = {
 	.rpc_release = nfs4_lock_release,
 };
 
-static const struct rpc_call_ops nfs4_recover_lock_ops = {
-	.rpc_call_prepare = nfs4_recover_lock_prepare,
-	.rpc_call_done = nfs4_lock_done,
-	.rpc_release = nfs4_lock_release,
-};
-
 static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error)
 {
 	switch (error) {
@@ -4823,15 +4649,15 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
 		return -ENOMEM;
 	if (IS_SETLKW(cmd))
 		data->arg.block = 1;
-	if (recovery_type > NFS_LOCK_NEW) {
-		if (recovery_type == NFS_LOCK_RECLAIM)
-			data->arg.reclaim = NFS_LOCK_RECLAIM;
-		task_setup_data.callback_ops = &nfs4_recover_lock_ops;
-	}
 	nfs41_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1);
 	msg.rpc_argp = &data->arg;
 	msg.rpc_resp = &data->res;
 	task_setup_data.callback_data = data;
+	if (recovery_type > NFS_LOCK_NEW) {
+		if (recovery_type == NFS_LOCK_RECLAIM)
+			data->arg.reclaim = NFS_LOCK_RECLAIM;
+		nfs4_set_sequence_privileged(&data->arg.seq_args);
+	}
 	task = rpc_run_task(&task_setup_data);
 	if (IS_ERR(task))
 		return PTR_ERR(task);
@@ -5357,7 +5183,6 @@ int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred
 	};
 
 	dprintk("--> %s\n", __func__);
-	BUG_ON(clp == NULL);
 
 	res.session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS);
 	if (unlikely(res.session == NULL)) {
@@ -5569,20 +5394,16 @@ struct nfs4_get_lease_time_data {
 static void nfs4_get_lease_time_prepare(struct rpc_task *task,
 					void *calldata)
 {
-	int ret;
 	struct nfs4_get_lease_time_data *data =
 			(struct nfs4_get_lease_time_data *)calldata;
 
 	dprintk("--> %s\n", __func__);
-	rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
 	/* just setup sequence, do not trigger session recovery
 	   since we're invoked within one */
-	ret = nfs41_setup_sequence(data->clp->cl_session,
-				   &data->args->la_seq_args,
-				   &data->res->lr_seq_res, task);
-
-	BUG_ON(ret == -EAGAIN);
-	rpc_call_start(task);
+	nfs41_setup_sequence(data->clp->cl_session,
+			&data->args->la_seq_args,
+			&data->res->lr_seq_res,
+			task);
 	dprintk("<-- %s\n", __func__);
 }
 
@@ -5644,6 +5465,7 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
 	int status;
 
 	nfs41_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0);
+	nfs4_set_sequence_privileged(&args.la_seq_args);
 	dprintk("--> %s\n", __func__);
 	task = rpc_run_task(&task_setup);
 
@@ -5658,145 +5480,6 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
 	return status;
 }
 
-static struct nfs4_slot *nfs4_alloc_slots(u32 max_slots, gfp_t gfp_flags)
-{
-	return kcalloc(max_slots, sizeof(struct nfs4_slot), gfp_flags);
-}
-
-static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl,
-		struct nfs4_slot *new,
-		u32 max_slots,
-		u32 ivalue)
-{
-	struct nfs4_slot *old = NULL;
-	u32 i;
-
-	spin_lock(&tbl->slot_tbl_lock);
-	if (new) {
-		old = tbl->slots;
-		tbl->slots = new;
-		tbl->max_slots = max_slots;
-	}
-	tbl->highest_used_slotid = NFS4_NO_SLOT;
-	for (i = 0; i < tbl->max_slots; i++)
-		tbl->slots[i].seq_nr = ivalue;
-	spin_unlock(&tbl->slot_tbl_lock);
-	kfree(old);
-}
-
-/*
- * (re)Initialise a slot table
- */
-static int nfs4_realloc_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs,
-				 u32 ivalue)
-{
-	struct nfs4_slot *new = NULL;
-	int ret = -ENOMEM;
-
-	dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__,
-		max_reqs, tbl->max_slots);
-
-	/* Does the newly negotiated max_reqs match the existing slot table? */
-	if (max_reqs != tbl->max_slots) {
-		new = nfs4_alloc_slots(max_reqs, GFP_NOFS);
-		if (!new)
-			goto out;
-	}
-	ret = 0;
-
-	nfs4_add_and_init_slots(tbl, new, max_reqs, ivalue);
-	dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
-		tbl, tbl->slots, tbl->max_slots);
-out:
-	dprintk("<-- %s: return %d\n", __func__, ret);
-	return ret;
-}
-
-/* Destroy the slot table */
-static void nfs4_destroy_slot_tables(struct nfs4_session *session)
-{
-	if (session->fc_slot_table.slots != NULL) {
-		kfree(session->fc_slot_table.slots);
-		session->fc_slot_table.slots = NULL;
-	}
-	if (session->bc_slot_table.slots != NULL) {
-		kfree(session->bc_slot_table.slots);
-		session->bc_slot_table.slots = NULL;
-	}
-	return;
-}
-
-/*
- * Initialize or reset the forechannel and backchannel tables
- */
-static int nfs4_setup_session_slot_tables(struct nfs4_session *ses)
-{
-	struct nfs4_slot_table *tbl;
-	int status;
-
-	dprintk("--> %s\n", __func__);
-	/* Fore channel */
-	tbl = &ses->fc_slot_table;
-	status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1);
-	if (status) /* -ENOMEM */
-		return status;
-	/* Back channel */
-	tbl = &ses->bc_slot_table;
-	status = nfs4_realloc_slot_table(tbl, ses->bc_attrs.max_reqs, 0);
-	if (status && tbl->slots == NULL)
-		/* Fore and back channel share a connection so get
-		 * both slot tables or neither */
-		nfs4_destroy_slot_tables(ses);
-	return status;
-}
-
-struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
-{
-	struct nfs4_session *session;
-	struct nfs4_slot_table *tbl;
-
-	session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS);
-	if (!session)
-		return NULL;
-
-	tbl = &session->fc_slot_table;
-	tbl->highest_used_slotid = NFS4_NO_SLOT;
-	spin_lock_init(&tbl->slot_tbl_lock);
-	rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table");
-	init_completion(&tbl->complete);
-
-	tbl = &session->bc_slot_table;
-	tbl->highest_used_slotid = NFS4_NO_SLOT;
-	spin_lock_init(&tbl->slot_tbl_lock);
-	rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table");
-	init_completion(&tbl->complete);
-
-	session->session_state = 1<<NFS4_SESSION_INITING;
-
-	session->clp = clp;
-	return session;
-}
-
-void nfs4_destroy_session(struct nfs4_session *session)
-{
-	struct rpc_xprt *xprt;
-	struct rpc_cred *cred;
-
-	cred = nfs4_get_exchange_id_cred(session->clp);
-	nfs4_proc_destroy_session(session, cred);
-	if (cred)
-		put_rpccred(cred);
-
-	rcu_read_lock();
-	xprt = rcu_dereference(session->clp->cl_rpcclient->cl_xprt);
-	rcu_read_unlock();
-	dprintk("%s Destroy backchannel for xprt %p\n",
-		__func__, xprt);
-	xprt_destroy_backchannel(xprt, NFS41_BC_MIN_CALLBACKS);
-	nfs4_destroy_slot_tables(session);
-	kfree(session);
-}
-
 /*
  * Initialize the values to be used by the client in CREATE_SESSION
  * If nfs4_init_session set the fore channel request and response sizes,
@@ -5809,8 +5492,8 @@ void nfs4_destroy_session(struct nfs4_session *session)
 static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
 {
 	struct nfs4_session *session = args->client->cl_session;
-	unsigned int mxrqst_sz = session->fc_attrs.max_rqst_sz,
-		     mxresp_sz = session->fc_attrs.max_resp_sz;
+	unsigned int mxrqst_sz = session->fc_target_max_rqst_sz,
+		     mxresp_sz = session->fc_target_max_resp_sz;
 
 	if (mxrqst_sz == 0)
 		mxrqst_sz = NFS_MAX_FILE_IO_SIZE;
@@ -5919,10 +5602,9 @@ static int _nfs4_proc_create_session(struct nfs_client *clp,
 
 	status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
 
-	if (!status)
+	if (!status) {
 		/* Verify the session's negotiated channel_attrs values */
 		status = nfs4_verify_channel_attrs(&args, session);
-	if (!status) {
 		/* Increment the clientid slot sequence id */
 		clp->cl_seqid++;
 	}
@@ -5992,83 +5674,6 @@ int nfs4_proc_destroy_session(struct nfs4_session *session,
 }
 
 /*
- * With sessions, the client is not marked ready until after a
- * successful EXCHANGE_ID and CREATE_SESSION.
- *
- * Map errors cl_cons_state errors to EPROTONOSUPPORT to indicate
- * other versions of NFS can be tried.
- */
-static int nfs41_check_session_ready(struct nfs_client *clp)
-{
-	int ret;
-	
-	if (clp->cl_cons_state == NFS_CS_SESSION_INITING) {
-		ret = nfs4_client_recover_expired_lease(clp);
-		if (ret)
-			return ret;
-	}
-	if (clp->cl_cons_state < NFS_CS_READY)
-		return -EPROTONOSUPPORT;
-	smp_rmb();
-	return 0;
-}
-
-int nfs4_init_session(struct nfs_server *server)
-{
-	struct nfs_client *clp = server->nfs_client;
-	struct nfs4_session *session;
-	unsigned int rsize, wsize;
-
-	if (!nfs4_has_session(clp))
-		return 0;
-
-	session = clp->cl_session;
-	spin_lock(&clp->cl_lock);
-	if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) {
-
-		rsize = server->rsize;
-		if (rsize == 0)
-			rsize = NFS_MAX_FILE_IO_SIZE;
-		wsize = server->wsize;
-		if (wsize == 0)
-			wsize = NFS_MAX_FILE_IO_SIZE;
-
-		session->fc_attrs.max_rqst_sz = wsize + nfs41_maxwrite_overhead;
-		session->fc_attrs.max_resp_sz = rsize + nfs41_maxread_overhead;
-	}
-	spin_unlock(&clp->cl_lock);
-
-	return nfs41_check_session_ready(clp);
-}
-
-int nfs4_init_ds_session(struct nfs_client *clp, unsigned long lease_time)
-{
-	struct nfs4_session *session = clp->cl_session;
-	int ret;
-
-	spin_lock(&clp->cl_lock);
-	if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) {
-		/*
-		 * Do not set NFS_CS_CHECK_LEASE_TIME instead set the
-		 * DS lease to be equal to the MDS lease.
-		 */
-		clp->cl_lease_time = lease_time;
-		clp->cl_last_renewal = jiffies;
-	}
-	spin_unlock(&clp->cl_lock);
-
-	ret = nfs41_check_session_ready(clp);
-	if (ret)
-		return ret;
-	/* Test for the DS role */
-	if (!is_ds_client(clp))
-		return -ENODEV;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(nfs4_init_ds_session);
-
-
-/*
  * Renew the cl_session lease.
  */
 struct nfs4_sequence_data {
@@ -6133,9 +5738,7 @@ static void nfs41_sequence_prepare(struct rpc_task *task, void *data)
 	args = task->tk_msg.rpc_argp;
 	res = task->tk_msg.rpc_resp;
 
-	if (nfs41_setup_sequence(clp->cl_session, args, res, task))
-		return;
-	rpc_call_start(task);
+	nfs41_setup_sequence(clp->cl_session, args, res, task);
 }
 
 static const struct rpc_call_ops nfs41_sequence_ops = {
@@ -6144,7 +5747,9 @@ static const struct rpc_call_ops nfs41_sequence_ops = {
 	.rpc_release = nfs41_sequence_release,
 };
 
-static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
+static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp,
+		struct rpc_cred *cred,
+		bool is_privileged)
 {
 	struct nfs4_sequence_data *calldata;
 	struct rpc_message msg = {
@@ -6166,6 +5771,8 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_
 		return ERR_PTR(-ENOMEM);
 	}
 	nfs41_init_sequence(&calldata->args, &calldata->res, 0);
+	if (is_privileged)
+		nfs4_set_sequence_privileged(&calldata->args);
 	msg.rpc_argp = &calldata->args;
 	msg.rpc_resp = &calldata->res;
 	calldata->clp = clp;
@@ -6181,7 +5788,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr
 
 	if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0)
 		return 0;
-	task = _nfs41_proc_sequence(clp, cred);
+	task = _nfs41_proc_sequence(clp, cred, false);
 	if (IS_ERR(task))
 		ret = PTR_ERR(task);
 	else
@@ -6195,7 +5802,7 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
 	struct rpc_task *task;
 	int ret;
 
-	task = _nfs41_proc_sequence(clp, cred);
+	task = _nfs41_proc_sequence(clp, cred, true);
 	if (IS_ERR(task)) {
 		ret = PTR_ERR(task);
 		goto out;
@@ -6224,13 +5831,10 @@ static void nfs4_reclaim_complete_prepare(struct rpc_task *task, void *data)
 {
 	struct nfs4_reclaim_complete_data *calldata = data;
 
-	rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
-	if (nfs41_setup_sequence(calldata->clp->cl_session,
-				&calldata->arg.seq_args,
-				&calldata->res.seq_res, task))
-		return;
-
-	rpc_call_start(task);
+	nfs41_setup_sequence(calldata->clp->cl_session,
+			&calldata->arg.seq_args,
+			&calldata->res.seq_res,
+			task);
 }
 
 static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nfs_client *clp)
@@ -6307,6 +5911,7 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp)
 	calldata->arg.one_fs = 0;
 
 	nfs41_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0);
+	nfs4_set_sequence_privileged(&calldata->arg.seq_args);
 	msg.rpc_argp = &calldata->arg;
 	msg.rpc_resp = &calldata->res;
 	task_setup_data.callback_data = calldata;
@@ -6330,6 +5935,7 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata)
 {
 	struct nfs4_layoutget *lgp = calldata;
 	struct nfs_server *server = NFS_SERVER(lgp->args.inode);
+	struct nfs4_session *session = nfs4_get_session(server);
 
 	dprintk("--> %s\n", __func__);
 	/* Note the is a race here, where a CB_LAYOUTRECALL can come in
@@ -6337,16 +5943,14 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata)
 	 * However, that is not so catastrophic, and there seems
 	 * to be no way to prevent it completely.
 	 */
-	if (nfs4_setup_sequence(server, &lgp->args.seq_args,
+	if (nfs41_setup_sequence(session, &lgp->args.seq_args,
 				&lgp->res.seq_res, task))
 		return;
 	if (pnfs_choose_layoutget_stateid(&lgp->args.stateid,
 					  NFS_I(lgp->args.inode)->layout,
 					  lgp->args.ctx->state)) {
 		rpc_exit(task, NFS4_OK);
-		return;
 	}
-	rpc_call_start(task);
 }
 
 static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
@@ -6359,7 +5963,7 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
 
 	dprintk("--> %s\n", __func__);
 
-	if (!nfs4_sequence_done(task, &lgp->res.seq_res))
+	if (!nfs41_sequence_done(task, &lgp->res.seq_res))
 		goto out;
 
 	switch (task->tk_status) {
@@ -6510,10 +6114,10 @@ nfs4_layoutreturn_prepare(struct rpc_task *task, void *calldata)
 	struct nfs4_layoutreturn *lrp = calldata;
 
 	dprintk("--> %s\n", __func__);
-	if (nfs41_setup_sequence(lrp->clp->cl_session, &lrp->args.seq_args,
-				&lrp->res.seq_res, task))
-		return;
-	rpc_call_start(task);
+	nfs41_setup_sequence(lrp->clp->cl_session,
+			&lrp->args.seq_args,
+			&lrp->res.seq_res,
+			task);
 }
 
 static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
@@ -6523,7 +6127,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
 
 	dprintk("--> %s\n", __func__);
 
-	if (!nfs4_sequence_done(task, &lrp->res.seq_res))
+	if (!nfs41_sequence_done(task, &lrp->res.seq_res))
 		return;
 
 	server = NFS_SERVER(lrp->args.inode);
@@ -6672,11 +6276,12 @@ static void nfs4_layoutcommit_prepare(struct rpc_task *task, void *calldata)
 {
 	struct nfs4_layoutcommit_data *data = calldata;
 	struct nfs_server *server = NFS_SERVER(data->args.inode);
+	struct nfs4_session *session = nfs4_get_session(server);
 
-	if (nfs4_setup_sequence(server, &data->args.seq_args,
-				&data->res.seq_res, task))
-		return;
-	rpc_call_start(task);
+	nfs41_setup_sequence(session,
+			&data->args.seq_args,
+			&data->res.seq_res,
+			task);
 }
 
 static void
@@ -6685,7 +6290,7 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
 	struct nfs4_layoutcommit_data *data = calldata;
 	struct nfs_server *server = NFS_SERVER(data->args.inode);
 
-	if (!nfs4_sequence_done(task, &data->res.seq_res))
+	if (!nfs41_sequence_done(task, &data->res.seq_res))
 		return;
 
 	switch (task->tk_status) { /* Just ignore these failures */
@@ -6873,7 +6478,9 @@ static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid)
 
 	dprintk("NFS call  test_stateid %p\n", stateid);
 	nfs41_init_sequence(&args.seq_args, &res.seq_res, 0);
-	status = nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 1);
+	nfs4_set_sequence_privileged(&args.seq_args);
+	status = nfs4_call_sync_sequence(server->client, server, &msg,
+			&args.seq_args, &res.seq_res);
 	if (status != NFS_OK) {
 		dprintk("NFS reply test_stateid: failed, %d\n", status);
 		return status;
@@ -6920,8 +6527,9 @@ static int _nfs4_free_stateid(struct nfs_server *server, nfs4_stateid *stateid)
 
 	dprintk("NFS call  free_stateid %p\n", stateid);
 	nfs41_init_sequence(&args.seq_args, &res.seq_res, 0);
+	nfs4_set_sequence_privileged(&args.seq_args);
 	status = nfs4_call_sync_sequence(server->client, server, &msg,
-					 &args.seq_args, &res.seq_res, 1);
+			&args.seq_args, &res.seq_res);
 	dprintk("NFS reply free_stateid: %d\n", status);
 	return status;
 }
@@ -7041,7 +6649,7 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = {
 #if defined(CONFIG_NFS_V4_1)
 static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {
 	.minor_version = 1,
-	.call_sync = _nfs4_call_sync_session,
+	.call_sync = nfs4_call_sync_sequence,
 	.match_stateid = nfs41_match_stateid,
 	.find_root_sec = nfs41_find_root_sec,
 	.reboot_recovery_ops = &nfs41_reboot_recovery_ops,
diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c
new file mode 100644
index 0000000..7011702
--- /dev/null
+++ b/fs/nfs/nfs4session.c
@@ -0,0 +1,436 @@
+/*
+ * fs/nfs/nfs4session.c
+ *
+ * Copyright (c) 2012 Trond Myklebust <Trond.Myklebust@netapp.com>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+#include <linux/sunrpc/sched.h>
+#include <linux/sunrpc/bc_xprt.h>
+#include <linux/nfs.h>
+#include <linux/nfs4.h>
+#include <linux/nfs_fs.h>
+#include <linux/module.h>
+
+#include "nfs4_fs.h"
+#include "internal.h"
+#include "nfs4session.h"
+#include "callback.h"
+
+#define NFSDBG_FACILITY		NFSDBG_STATE
+
+/*
+ * nfs4_shrink_slot_table - free retired slots from the slot table
+ */
+static void nfs4_shrink_slot_table(struct nfs4_slot_table  *tbl, u32 newsize)
+{
+	struct nfs4_slot **p;
+	if (newsize >= tbl->max_slots)
+		return;
+
+	p = &tbl->slots;
+	while (newsize--)
+		p = &(*p)->next;
+	while (*p) {
+		struct nfs4_slot *slot = *p;
+
+		*p = slot->next;
+		kfree(slot);
+		tbl->max_slots--;
+	}
+}
+
+/*
+ * nfs4_free_slot - free a slot and efficiently update slot table.
+ *
+ * freeing a slot is trivially done by clearing its respective bit
+ * in the bitmap.
+ * If the freed slotid equals highest_used_slotid we want to update it
+ * so that the server would be able to size down the slot table if needed,
+ * otherwise we know that the highest_used_slotid is still in use.
+ * When updating highest_used_slotid there may be "holes" in the bitmap
+ * so we need to scan down from highest_used_slotid to 0 looking for the now
+ * highest slotid in use.
+ * If none found, highest_used_slotid is set to NFS4_NO_SLOT.
+ *
+ * Must be called while holding tbl->slot_tbl_lock
+ */
+void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot)
+{
+	u32 slotid = slot->slot_nr;
+
+	/* clear used bit in bitmap */
+	__clear_bit(slotid, tbl->used_slots);
+
+	/* update highest_used_slotid when it is freed */
+	if (slotid == tbl->highest_used_slotid) {
+		u32 new_max = find_last_bit(tbl->used_slots, slotid);
+		if (new_max < slotid)
+			tbl->highest_used_slotid = new_max;
+		else {
+			tbl->highest_used_slotid = NFS4_NO_SLOT;
+			nfs4_session_drain_complete(tbl->session, tbl);
+		}
+	}
+	dprintk("%s: slotid %u highest_used_slotid %d\n", __func__,
+		slotid, tbl->highest_used_slotid);
+}
+
+static struct nfs4_slot *nfs4_new_slot(struct nfs4_slot_table  *tbl,
+		u32 slotid, u32 seq_init, gfp_t gfp_mask)
+{
+	struct nfs4_slot *slot;
+
+	slot = kzalloc(sizeof(*slot), gfp_mask);
+	if (slot) {
+		slot->table = tbl;
+		slot->slot_nr = slotid;
+		slot->seq_nr = seq_init;
+	}
+	return slot;
+}
+
+static struct nfs4_slot *nfs4_find_or_create_slot(struct nfs4_slot_table  *tbl,
+		u32 slotid, u32 seq_init, gfp_t gfp_mask)
+{
+	struct nfs4_slot **p, *slot;
+
+	p = &tbl->slots;
+	for (;;) {
+		if (*p == NULL) {
+			*p = nfs4_new_slot(tbl, tbl->max_slots,
+					seq_init, gfp_mask);
+			if (*p == NULL)
+				break;
+			tbl->max_slots++;
+		}
+		slot = *p;
+		if (slot->slot_nr == slotid)
+			return slot;
+		p = &slot->next;
+	}
+	return ERR_PTR(-ENOMEM);
+}
+
+/*
+ * nfs4_alloc_slot - efficiently look for a free slot
+ *
+ * nfs4_alloc_slot looks for an unset bit in the used_slots bitmap.
+ * If found, we mark the slot as used, update the highest_used_slotid,
+ * and respectively set up the sequence operation args.
+ *
+ * Note: must be called with under the slot_tbl_lock.
+ */
+struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl)
+{
+	struct nfs4_slot *ret = ERR_PTR(-EBUSY);
+	u32 slotid;
+
+	dprintk("--> %s used_slots=%04lx highest_used=%u max_slots=%u\n",
+		__func__, tbl->used_slots[0], tbl->highest_used_slotid,
+		tbl->max_slotid + 1);
+	slotid = find_first_zero_bit(tbl->used_slots, tbl->max_slotid + 1);
+	if (slotid > tbl->max_slotid)
+		goto out;
+	ret = nfs4_find_or_create_slot(tbl, slotid, 1, GFP_NOWAIT);
+	if (IS_ERR(ret))
+		goto out;
+	__set_bit(slotid, tbl->used_slots);
+	if (slotid > tbl->highest_used_slotid ||
+			tbl->highest_used_slotid == NFS4_NO_SLOT)
+		tbl->highest_used_slotid = slotid;
+	ret->renewal_time = jiffies;
+	ret->generation = tbl->generation;
+
+out:
+	dprintk("<-- %s used_slots=%04lx highest_used=%d slotid=%d \n",
+		__func__, tbl->used_slots[0], tbl->highest_used_slotid,
+		!IS_ERR(ret) ? ret->slot_nr : -1);
+	return ret;
+}
+
+static int nfs4_grow_slot_table(struct nfs4_slot_table *tbl,
+		 u32 max_reqs, u32 ivalue)
+{
+	if (max_reqs <= tbl->max_slots)
+		return 0;
+	if (!IS_ERR(nfs4_find_or_create_slot(tbl, max_reqs - 1, ivalue, GFP_NOFS)))
+		return 0;
+	return -ENOMEM;
+}
+
+static void nfs4_reset_slot_table(struct nfs4_slot_table *tbl,
+		u32 server_highest_slotid,
+		u32 ivalue)
+{
+	struct nfs4_slot **p;
+
+	nfs4_shrink_slot_table(tbl, server_highest_slotid + 1);
+	p = &tbl->slots;
+	while (*p) {
+		(*p)->seq_nr = ivalue;
+		p = &(*p)->next;
+	}
+	tbl->highest_used_slotid = NFS4_NO_SLOT;
+	tbl->target_highest_slotid = server_highest_slotid;
+	tbl->server_highest_slotid = server_highest_slotid;
+	tbl->max_slotid = server_highest_slotid;
+}
+
+/*
+ * (re)Initialise a slot table
+ */
+static int nfs4_realloc_slot_table(struct nfs4_slot_table *tbl,
+		u32 max_reqs, u32 ivalue)
+{
+	int ret;
+
+	dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__,
+		max_reqs, tbl->max_slots);
+
+	if (max_reqs > NFS4_MAX_SLOT_TABLE)
+		max_reqs = NFS4_MAX_SLOT_TABLE;
+
+	ret = nfs4_grow_slot_table(tbl, max_reqs, ivalue);
+	if (ret)
+		goto out;
+
+	spin_lock(&tbl->slot_tbl_lock);
+	nfs4_reset_slot_table(tbl, max_reqs - 1, ivalue);
+	spin_unlock(&tbl->slot_tbl_lock);
+
+	dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
+		tbl, tbl->slots, tbl->max_slots);
+out:
+	dprintk("<-- %s: return %d\n", __func__, ret);
+	return ret;
+}
+
+/* Destroy the slot table */
+static void nfs4_destroy_slot_tables(struct nfs4_session *session)
+{
+	nfs4_shrink_slot_table(&session->fc_slot_table, 0);
+	nfs4_shrink_slot_table(&session->bc_slot_table, 0);
+}
+
+/* Update the client's idea of target_highest_slotid */
+static void nfs41_set_target_slotid_locked(struct nfs4_slot_table *tbl,
+		u32 target_highest_slotid)
+{
+	unsigned int max_slotid, i;
+
+	if (tbl->target_highest_slotid == target_highest_slotid)
+		return;
+	tbl->target_highest_slotid = target_highest_slotid;
+	tbl->generation++;
+
+	max_slotid = min(NFS4_MAX_SLOT_TABLE - 1, tbl->target_highest_slotid);
+	for (i = tbl->max_slotid + 1; i <= max_slotid; i++)
+		rpc_wake_up_next(&tbl->slot_tbl_waitq);
+	tbl->max_slotid = max_slotid;
+}
+
+void nfs41_set_target_slotid(struct nfs4_slot_table *tbl,
+		u32 target_highest_slotid)
+{
+	spin_lock(&tbl->slot_tbl_lock);
+	nfs41_set_target_slotid_locked(tbl, target_highest_slotid);
+	spin_unlock(&tbl->slot_tbl_lock);
+}
+
+static void nfs41_set_server_slotid_locked(struct nfs4_slot_table *tbl,
+		u32 highest_slotid)
+{
+	if (tbl->server_highest_slotid == highest_slotid)
+		return;
+	if (tbl->highest_used_slotid > highest_slotid)
+		return;
+	/* Deallocate slots */
+	nfs4_shrink_slot_table(tbl, highest_slotid + 1);
+	tbl->server_highest_slotid = highest_slotid;
+}
+
+void nfs41_update_target_slotid(struct nfs4_slot_table *tbl,
+		struct nfs4_slot *slot,
+		struct nfs4_sequence_res *res)
+{
+	spin_lock(&tbl->slot_tbl_lock);
+	if (tbl->generation != slot->generation)
+		goto out;
+	nfs41_set_server_slotid_locked(tbl, res->sr_highest_slotid);
+	nfs41_set_target_slotid_locked(tbl, res->sr_target_highest_slotid);
+out:
+	spin_unlock(&tbl->slot_tbl_lock);
+}
+
+/*
+ * Initialize or reset the forechannel and backchannel tables
+ */
+int nfs4_setup_session_slot_tables(struct nfs4_session *ses)
+{
+	struct nfs4_slot_table *tbl;
+	int status;
+
+	dprintk("--> %s\n", __func__);
+	/* Fore channel */
+	tbl = &ses->fc_slot_table;
+	tbl->session = ses;
+	status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1);
+	if (status) /* -ENOMEM */
+		return status;
+	/* Back channel */
+	tbl = &ses->bc_slot_table;
+	tbl->session = ses;
+	status = nfs4_realloc_slot_table(tbl, ses->bc_attrs.max_reqs, 0);
+	if (status && tbl->slots == NULL)
+		/* Fore and back channel share a connection so get
+		 * both slot tables or neither */
+		nfs4_destroy_slot_tables(ses);
+	return status;
+}
+
+struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
+{
+	struct nfs4_session *session;
+	struct nfs4_slot_table *tbl;
+
+	session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS);
+	if (!session)
+		return NULL;
+
+	tbl = &session->fc_slot_table;
+	tbl->highest_used_slotid = NFS4_NO_SLOT;
+	spin_lock_init(&tbl->slot_tbl_lock);
+	rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table");
+	init_completion(&tbl->complete);
+
+	tbl = &session->bc_slot_table;
+	tbl->highest_used_slotid = NFS4_NO_SLOT;
+	spin_lock_init(&tbl->slot_tbl_lock);
+	rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table");
+	init_completion(&tbl->complete);
+
+	session->session_state = 1<<NFS4_SESSION_INITING;
+
+	session->clp = clp;
+	return session;
+}
+
+void nfs4_destroy_session(struct nfs4_session *session)
+{
+	struct rpc_xprt *xprt;
+	struct rpc_cred *cred;
+
+	cred = nfs4_get_exchange_id_cred(session->clp);
+	nfs4_proc_destroy_session(session, cred);
+	if (cred)
+		put_rpccred(cred);
+
+	rcu_read_lock();
+	xprt = rcu_dereference(session->clp->cl_rpcclient->cl_xprt);
+	rcu_read_unlock();
+	dprintk("%s Destroy backchannel for xprt %p\n",
+		__func__, xprt);
+	xprt_destroy_backchannel(xprt, NFS41_BC_MIN_CALLBACKS);
+	nfs4_destroy_slot_tables(session);
+	kfree(session);
+}
+
+/*
+ * With sessions, the client is not marked ready until after a
+ * successful EXCHANGE_ID and CREATE_SESSION.
+ *
+ * Map errors cl_cons_state errors to EPROTONOSUPPORT to indicate
+ * other versions of NFS can be tried.
+ */
+static int nfs41_check_session_ready(struct nfs_client *clp)
+{
+	int ret;
+	
+	if (clp->cl_cons_state == NFS_CS_SESSION_INITING) {
+		ret = nfs4_client_recover_expired_lease(clp);
+		if (ret)
+			return ret;
+	}
+	if (clp->cl_cons_state < NFS_CS_READY)
+		return -EPROTONOSUPPORT;
+	smp_rmb();
+	return 0;
+}
+
+int nfs4_init_session(struct nfs_server *server)
+{
+	struct nfs_client *clp = server->nfs_client;
+	struct nfs4_session *session;
+	unsigned int target_max_rqst_sz = NFS_MAX_FILE_IO_SIZE;
+	unsigned int target_max_resp_sz = NFS_MAX_FILE_IO_SIZE;
+
+	if (!nfs4_has_session(clp))
+		return 0;
+
+	if (server->rsize != 0)
+		target_max_resp_sz = server->rsize;
+	target_max_resp_sz += nfs41_maxread_overhead;
+
+	if (server->wsize != 0)
+		target_max_rqst_sz = server->wsize;
+	target_max_rqst_sz += nfs41_maxwrite_overhead;
+
+	session = clp->cl_session;
+	spin_lock(&clp->cl_lock);
+	if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) {
+		/* Initialise targets and channel attributes */
+		session->fc_target_max_rqst_sz = target_max_rqst_sz;
+		session->fc_attrs.max_rqst_sz = target_max_rqst_sz;
+		session->fc_target_max_resp_sz = target_max_resp_sz;
+		session->fc_attrs.max_resp_sz = target_max_resp_sz;
+	} else {
+		/* Just adjust the targets */
+		if (target_max_rqst_sz > session->fc_target_max_rqst_sz) {
+			session->fc_target_max_rqst_sz = target_max_rqst_sz;
+			set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
+		}
+		if (target_max_resp_sz > session->fc_target_max_resp_sz) {
+			session->fc_target_max_resp_sz = target_max_resp_sz;
+			set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
+		}
+	}
+	spin_unlock(&clp->cl_lock);
+
+	if (test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state))
+		nfs4_schedule_lease_recovery(clp);
+
+	return nfs41_check_session_ready(clp);
+}
+
+int nfs4_init_ds_session(struct nfs_client *clp, unsigned long lease_time)
+{
+	struct nfs4_session *session = clp->cl_session;
+	int ret;
+
+	spin_lock(&clp->cl_lock);
+	if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) {
+		/*
+		 * Do not set NFS_CS_CHECK_LEASE_TIME instead set the
+		 * DS lease to be equal to the MDS lease.
+		 */
+		clp->cl_lease_time = lease_time;
+		clp->cl_last_renewal = jiffies;
+	}
+	spin_unlock(&clp->cl_lock);
+
+	ret = nfs41_check_session_ready(clp);
+	if (ret)
+		return ret;
+	/* Test for the DS role */
+	if (!is_ds_client(clp))
+		return -ENODEV;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(nfs4_init_ds_session);
+
+
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h
new file mode 100644
index 0000000..bdd14a6
--- /dev/null
+++ b/fs/nfs/nfs4session.h
@@ -0,0 +1,136 @@
+/*
+ * fs/nfs/nfs4session.h
+ *
+ * Copyright (c) 2012 Trond Myklebust <Trond.Myklebust@netapp.com>
+ *
+ */
+#ifndef __LINUX_FS_NFS_NFS4SESSION_H
+#define __LINUX_FS_NFS_NFS4SESSION_H
+
+/* maximum number of slots to use */
+#define NFS4_DEF_SLOT_TABLE_SIZE (16U)
+#define NFS4_MAX_SLOT_TABLE (1024U)
+#define NFS4_NO_SLOT ((u32)-1)
+
+#if IS_ENABLED(CONFIG_NFS_V4)
+
+/* Sessions slot seqid */
+struct nfs4_slot {
+	struct nfs4_slot_table	*table;
+	struct nfs4_slot	*next;
+	unsigned long		generation;
+	unsigned long		renewal_time;
+	u32			slot_nr;
+	u32		 	seq_nr;
+};
+
+/* Sessions */
+#define SLOT_TABLE_SZ DIV_ROUND_UP(NFS4_MAX_SLOT_TABLE, 8*sizeof(long))
+struct nfs4_slot_table {
+	struct nfs4_session *session;		/* Parent session */
+	struct nfs4_slot *slots;		/* seqid per slot */
+	unsigned long   used_slots[SLOT_TABLE_SZ]; /* used/unused bitmap */
+	spinlock_t	slot_tbl_lock;
+	struct rpc_wait_queue	slot_tbl_waitq;	/* allocators may wait here */
+	u32		max_slots;		/* # slots in table */
+	u32		max_slotid;		/* Max allowed slotid value */
+	u32		highest_used_slotid;	/* sent to server on each SEQ.
+						 * op for dynamic resizing */
+	u32		target_highest_slotid;	/* Server max_slot target */
+	u32		server_highest_slotid;	/* Server highest slotid */
+	unsigned long	generation;		/* Generation counter for
+						   target_highest_slotid */
+	struct completion complete;
+};
+
+/*
+ * Session related parameters
+ */
+struct nfs4_session {
+	struct nfs4_sessionid		sess_id;
+	u32				flags;
+	unsigned long			session_state;
+	u32				hash_alg;
+	u32				ssv_len;
+
+	/* The fore and back channel */
+	struct nfs4_channel_attrs	fc_attrs;
+	struct nfs4_slot_table		fc_slot_table;
+	struct nfs4_channel_attrs	bc_attrs;
+	struct nfs4_slot_table		bc_slot_table;
+	struct nfs_client		*clp;
+	/* Create session arguments */
+	unsigned int			fc_target_max_rqst_sz;
+	unsigned int			fc_target_max_resp_sz;
+};
+
+enum nfs4_session_state {
+	NFS4_SESSION_INITING,
+	NFS4_SESSION_DRAINING,
+};
+
+#if defined(CONFIG_NFS_V4_1)
+extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl);
+extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
+
+extern void nfs41_set_target_slotid(struct nfs4_slot_table *tbl,
+		u32 target_highest_slotid);
+extern void nfs41_update_target_slotid(struct nfs4_slot_table *tbl,
+		struct nfs4_slot *slot,
+		struct nfs4_sequence_res *res);
+
+extern int nfs4_setup_session_slot_tables(struct nfs4_session *ses);
+
+extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp);
+extern void nfs4_destroy_session(struct nfs4_session *session);
+extern int nfs4_init_session(struct nfs_server *server);
+extern int nfs4_init_ds_session(struct nfs_client *, unsigned long);
+
+extern void nfs4_session_drain_complete(struct nfs4_session *session,
+		struct nfs4_slot_table *tbl);
+
+static inline bool nfs4_session_draining(struct nfs4_session *session)
+{
+	return !!test_bit(NFS4_SESSION_DRAINING, &session->session_state);
+}
+
+/*
+ * Determine if sessions are in use.
+ */
+static inline int nfs4_has_session(const struct nfs_client *clp)
+{
+	if (clp->cl_session)
+		return 1;
+	return 0;
+}
+
+static inline int nfs4_has_persistent_session(const struct nfs_client *clp)
+{
+	if (nfs4_has_session(clp))
+		return (clp->cl_session->flags & SESSION4_PERSIST);
+	return 0;
+}
+
+#else /* defined(CONFIG_NFS_V4_1) */
+
+static inline int nfs4_init_session(struct nfs_server *server)
+{
+	return 0;
+}
+
+/*
+ * Determine if sessions are in use.
+ */
+static inline int nfs4_has_session(const struct nfs_client *clp)
+{
+	return 0;
+}
+
+static inline int nfs4_has_persistent_session(const struct nfs_client *clp)
+{
+	return 0;
+}
+
+#endif /* defined(CONFIG_NFS_V4_1) */
+#endif /* IS_ENABLED(CONFIG_NFS_V4) */
+#endif /* __LINUX_FS_NFS_NFS4SESSION_H */
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index c351e6b..7d73df5 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -57,6 +57,7 @@
 #include "callback.h"
 #include "delegation.h"
 #include "internal.h"
+#include "nfs4session.h"
 #include "pnfs.h"
 #include "netns.h"
 
@@ -254,24 +255,31 @@ static void nfs4_end_drain_session(struct nfs_client *clp)
 {
 	struct nfs4_session *ses = clp->cl_session;
 	struct nfs4_slot_table *tbl;
-	int max_slots;
+	unsigned int i;
 
 	if (ses == NULL)
 		return;
 	tbl = &ses->fc_slot_table;
 	if (test_and_clear_bit(NFS4_SESSION_DRAINING, &ses->session_state)) {
 		spin_lock(&tbl->slot_tbl_lock);
-		max_slots = tbl->max_slots;
-		while (max_slots--) {
-			if (rpc_wake_up_first(&tbl->slot_tbl_waitq,
-						nfs4_set_task_privileged,
-						NULL) == NULL)
+		for (i = 0; i <= tbl->max_slotid; i++) {
+			if (rpc_wake_up_next(&tbl->slot_tbl_waitq) == NULL)
 				break;
 		}
 		spin_unlock(&tbl->slot_tbl_lock);
 	}
 }
 
+/*
+ * Signal state manager thread if session fore channel is drained
+ */
+void nfs4_session_drain_complete(struct nfs4_session *session,
+		struct nfs4_slot_table *tbl)
+{
+	if (nfs4_session_draining(session))
+		complete(&tbl->complete);
+}
+
 static int nfs4_wait_on_slot_tbl(struct nfs4_slot_table *tbl)
 {
 	spin_lock(&tbl->slot_tbl_lock);
@@ -303,7 +311,6 @@ static void nfs41_finish_session_reset(struct nfs_client *clp)
 	clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
 	clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
 	/* create_session negotiated new slot table */
-	clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
 	clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state);
 	nfs41_setup_state_renewal(clp);
 }
@@ -1086,7 +1093,6 @@ void nfs_free_seqid(struct nfs_seqid *seqid)
  */
 static void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
 {
-	BUG_ON(list_first_entry(&seqid->sequence->list, struct nfs_seqid, list) != seqid);
 	switch (status) {
 		case 0:
 			break;
@@ -1209,6 +1215,40 @@ void nfs4_schedule_lease_recovery(struct nfs_client *clp)
 }
 EXPORT_SYMBOL_GPL(nfs4_schedule_lease_recovery);
 
+int nfs4_wait_clnt_recover(struct nfs_client *clp)
+{
+	int res;
+
+	might_sleep();
+
+	res = wait_on_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING,
+			nfs_wait_bit_killable, TASK_KILLABLE);
+	if (res)
+		return res;
+
+	if (clp->cl_cons_state < 0)
+		return clp->cl_cons_state;
+	return 0;
+}
+
+int nfs4_client_recover_expired_lease(struct nfs_client *clp)
+{
+	unsigned int loop;
+	int ret;
+
+	for (loop = NFS4_MAX_LOOP_ON_RECOVER; loop != 0; loop--) {
+		ret = nfs4_wait_clnt_recover(clp);
+		if (ret != 0)
+			break;
+		if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) &&
+		    !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state))
+			break;
+		nfs4_schedule_state_manager(clp);
+		ret = -EIO;
+	}
+	return ret;
+}
+
 /*
  * nfs40_handle_cb_pathdown - return all delegations after NFS4ERR_CB_PATH_DOWN
  * @clp: client to process
@@ -1907,14 +1947,23 @@ void nfs4_schedule_session_recovery(struct nfs4_session *session, int err)
 }
 EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery);
 
-void nfs41_handle_recall_slot(struct nfs_client *clp)
+static void nfs41_ping_server(struct nfs_client *clp)
 {
-	set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
-	dprintk("%s: scheduling slot recall for server %s\n", __func__,
-			clp->cl_hostname);
+	/* Use CHECK_LEASE to ping the server with a SEQUENCE */
+	set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
 	nfs4_schedule_state_manager(clp);
 }
 
+void nfs41_server_notify_target_slotid_update(struct nfs_client *clp)
+{
+	nfs41_ping_server(clp);
+}
+
+void nfs41_server_notify_highest_slotid_update(struct nfs_client *clp)
+{
+	nfs41_ping_server(clp);
+}
+
 static void nfs4_reset_all_state(struct nfs_client *clp)
 {
 	if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) {
@@ -2024,35 +2073,6 @@ out:
 	return status;
 }
 
-static int nfs4_recall_slot(struct nfs_client *clp)
-{
-	struct nfs4_slot_table *fc_tbl;
-	struct nfs4_slot *new, *old;
-	int i;
-
-	if (!nfs4_has_session(clp))
-		return 0;
-	nfs4_begin_drain_session(clp);
-	fc_tbl = &clp->cl_session->fc_slot_table;
-	new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot),
-		      GFP_NOFS);
-        if (!new)
-		return -ENOMEM;
-
-	spin_lock(&fc_tbl->slot_tbl_lock);
-	for (i = 0; i < fc_tbl->target_max_slots; i++)
-		new[i].seq_nr = fc_tbl->slots[i].seq_nr;
-	old = fc_tbl->slots;
-	fc_tbl->slots = new;
-	fc_tbl->max_slots = fc_tbl->target_max_slots;
-	fc_tbl->target_max_slots = 0;
-	clp->cl_session->fc_attrs.max_reqs = fc_tbl->max_slots;
-	spin_unlock(&fc_tbl->slot_tbl_lock);
-
-	kfree(old);
-	return 0;
-}
-
 static int nfs4_bind_conn_to_session(struct nfs_client *clp)
 {
 	struct rpc_cred *cred;
@@ -2083,7 +2103,6 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp)
 #else /* CONFIG_NFS_V4_1 */
 static int nfs4_reset_session(struct nfs_client *clp) { return 0; }
 static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; }
-static int nfs4_recall_slot(struct nfs_client *clp) { return 0; }
 
 static int nfs4_bind_conn_to_session(struct nfs_client *clp)
 {
@@ -2115,15 +2134,6 @@ static void nfs4_state_manager(struct nfs_client *clp)
 			continue;
 		}
 
-		if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
-			section = "check lease";
-			status = nfs4_check_lease(clp);
-			if (status < 0)
-				goto out_error;
-			if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
-				continue;
-		}
-
 		/* Initialize or reset the session */
 		if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) {
 			section = "reset session";
@@ -2144,10 +2154,9 @@ static void nfs4_state_manager(struct nfs_client *clp)
 			continue;
 		}
 
-		/* Recall session slots */
-		if (test_and_clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state)) {
-			section = "recall slot";
-			status = nfs4_recall_slot(clp);
+		if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
+			section = "check lease";
+			status = nfs4_check_lease(clp);
 			if (status < 0)
 				goto out_error;
 			continue;
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 40836ee..26b1439 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -56,6 +56,7 @@
 
 #include "nfs4_fs.h"
 #include "internal.h"
+#include "nfs4session.h"
 #include "pnfs.h"
 #include "netns.h"
 
@@ -270,6 +271,8 @@ static int nfs4_stat_to_errno(int);
 
 #if defined(CONFIG_NFS_V4_1)
 #define NFS4_MAX_MACHINE_NAME_LEN (64)
+#define IMPL_NAME_LIMIT (sizeof(utsname()->sysname) + sizeof(utsname()->release) + \
+			 sizeof(utsname()->version) + sizeof(utsname()->machine) + 8)
 
 #define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \
 				encode_verifier_maxsz + \
@@ -282,7 +285,7 @@ static int nfs4_stat_to_errno(int);
 				1 /* nii_domain */ + \
 				XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
 				1 /* nii_name */ + \
-				XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
+				XDR_QUADLEN(IMPL_NAME_LIMIT) + \
 				3 /* nii_date */)
 #define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \
 				2 /* eir_clientid */ + \
@@ -936,7 +939,7 @@ static void encode_compound_hdr(struct xdr_stream *xdr,
 	 * but this is not required as a MUST for the server to do so. */
 	hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen;
 
-	BUG_ON(hdr->taglen > NFS4_MAXTAGLEN);
+	WARN_ON_ONCE(hdr->taglen > NFS4_MAXTAGLEN);
 	encode_string(xdr, hdr->taglen, hdr->tag);
 	p = reserve_space(xdr, 8);
 	*p++ = cpu_to_be32(hdr->minorversion);
@@ -955,7 +958,7 @@ static void encode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 op,
 
 static void encode_nops(struct compound_hdr *hdr)
 {
-	BUG_ON(hdr->nops > NFS4_MAX_OPS);
+	WARN_ON_ONCE(hdr->nops > NFS4_MAX_OPS);
 	*hdr->nops_p = htonl(hdr->nops);
 }
 
@@ -1403,7 +1406,6 @@ static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *a
 		*p = cpu_to_be32(NFS4_OPEN_NOCREATE);
 		break;
 	default:
-		BUG_ON(arg->claim != NFS4_OPEN_CLAIM_NULL);
 		*p = cpu_to_be32(NFS4_OPEN_CREATE);
 		encode_createmode(xdr, arg);
 	}
@@ -1621,7 +1623,6 @@ encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compoun
 	p = reserve_space(xdr, 2*4);
 	*p++ = cpu_to_be32(1);
 	*p = cpu_to_be32(FATTR4_WORD0_ACL);
-	BUG_ON(arg->acl_len % 4);
 	p = reserve_space(xdr, 4);
 	*p = cpu_to_be32(arg->acl_len);
 	xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
@@ -1713,7 +1714,7 @@ static void encode_exchange_id(struct xdr_stream *xdr,
 			       struct compound_hdr *hdr)
 {
 	__be32 *p;
-	char impl_name[NFS4_OPAQUE_LIMIT];
+	char impl_name[IMPL_NAME_LIMIT];
 	int len = 0;
 
 	encode_op_hdr(xdr, OP_EXCHANGE_ID, decode_exchange_id_maxsz, hdr);
@@ -1728,7 +1729,7 @@ static void encode_exchange_id(struct xdr_stream *xdr,
 	if (send_implementation_id &&
 	    sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 &&
 	    sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN)
-		<= NFS4_OPAQUE_LIMIT + 1)
+		<= sizeof(impl_name) + 1)
 		len = snprintf(impl_name, sizeof(impl_name), "%s %s %s %s",
 			       utsname()->sysname, utsname()->release,
 			       utsname()->version, utsname()->machine);
@@ -1835,18 +1836,16 @@ static void encode_sequence(struct xdr_stream *xdr,
 			    struct compound_hdr *hdr)
 {
 #if defined(CONFIG_NFS_V4_1)
-	struct nfs4_session *session = args->sa_session;
+	struct nfs4_session *session;
 	struct nfs4_slot_table *tp;
-	struct nfs4_slot *slot;
+	struct nfs4_slot *slot = args->sa_slot;
 	__be32 *p;
 
-	if (!session)
+	if (slot == NULL)
 		return;
 
-	tp = &session->fc_slot_table;
-
-	WARN_ON(args->sa_slotid == NFS4_MAX_SLOT_TABLE);
-	slot = tp->slots + args->sa_slotid;
+	tp = slot->table;
+	session = tp->session;
 
 	encode_op_hdr(xdr, OP_SEQUENCE, decode_sequence_maxsz, hdr);
 
@@ -1860,12 +1859,12 @@ static void encode_sequence(struct xdr_stream *xdr,
 		((u32 *)session->sess_id.data)[1],
 		((u32 *)session->sess_id.data)[2],
 		((u32 *)session->sess_id.data)[3],
-		slot->seq_nr, args->sa_slotid,
+		slot->seq_nr, slot->slot_nr,
 		tp->highest_used_slotid, args->sa_cache_this);
 	p = reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 16);
 	p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
 	*p++ = cpu_to_be32(slot->seq_nr);
-	*p++ = cpu_to_be32(args->sa_slotid);
+	*p++ = cpu_to_be32(slot->slot_nr);
 	*p++ = cpu_to_be32(tp->highest_used_slotid);
 	*p = cpu_to_be32(args->sa_cache_this);
 #endif /* CONFIG_NFS_V4_1 */
@@ -2027,8 +2026,9 @@ static void encode_free_stateid(struct xdr_stream *xdr,
 static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args)
 {
 #if defined(CONFIG_NFS_V4_1)
-	if (args->sa_session)
-		return args->sa_session->clp->cl_mvops->minor_version;
+
+	if (args->sa_slot)
+		return args->sa_slot->table->session->clp->cl_mvops->minor_version;
 #endif /* CONFIG_NFS_V4_1 */
 	return 0;
 }
@@ -5509,12 +5509,13 @@ static int decode_sequence(struct xdr_stream *xdr,
 			   struct rpc_rqst *rqstp)
 {
 #if defined(CONFIG_NFS_V4_1)
+	struct nfs4_session *session;
 	struct nfs4_sessionid id;
 	u32 dummy;
 	int status;
 	__be32 *p;
 
-	if (!res->sr_session)
+	if (res->sr_slot == NULL)
 		return 0;
 
 	status = decode_op_hdr(xdr, OP_SEQUENCE);
@@ -5528,8 +5529,9 @@ static int decode_sequence(struct xdr_stream *xdr,
 	 * sequence number, the server is looney tunes.
 	 */
 	status = -EREMOTEIO;
+	session = res->sr_slot->table->session;
 
-	if (memcmp(id.data, res->sr_session->sess_id.data,
+	if (memcmp(id.data, session->sess_id.data,
 		   NFS4_MAX_SESSIONID_LEN)) {
 		dprintk("%s Invalid session id\n", __func__);
 		goto out_err;
@@ -5547,14 +5549,14 @@ static int decode_sequence(struct xdr_stream *xdr,
 	}
 	/* slot id */
 	dummy = be32_to_cpup(p++);
-	if (dummy != res->sr_slot - res->sr_session->fc_slot_table.slots) {
+	if (dummy != res->sr_slot->slot_nr) {
 		dprintk("%s Invalid slot id\n", __func__);
 		goto out_err;
 	}
-	/* highest slot id - currently not processed */
-	dummy = be32_to_cpup(p++);
-	/* target highest slot id - currently not processed */
-	dummy = be32_to_cpup(p++);
+	/* highest slot id */
+	res->sr_highest_slotid = be32_to_cpup(p++);
+	/* target highest slot id */
+	res->sr_target_highest_slotid = be32_to_cpup(p++);
 	/* result flags */
 	res->sr_status_flags = be32_to_cpup(p);
 	status = 0;
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c
index 8746135..a9ebd81 100644
--- a/fs/nfs/objlayout/objlayout.c
+++ b/fs/nfs/objlayout/objlayout.c
@@ -148,17 +148,6 @@ end_offset(u64 start, u64 len)
 	return end >= start ? end : NFS4_MAX_UINT64;
 }
 
-/* last octet in a range */
-static inline u64
-last_byte_offset(u64 start, u64 len)
-{
-	u64 end;
-
-	BUG_ON(!len);
-	end = start + len;
-	return end > start ? end - 1 : NFS4_MAX_UINT64;
-}
-
 static void _fix_verify_io_params(struct pnfs_layout_segment *lseg,
 			   struct page ***p_pages, unsigned *p_pgbase,
 			   u64 offset, unsigned long count)
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 2878f97..e7165d9 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -369,17 +369,6 @@ end_offset(u64 start, u64 len)
 	return end >= start ? end : NFS4_MAX_UINT64;
 }
 
-/* last octet in a range */
-static inline u64
-last_byte_offset(u64 start, u64 len)
-{
-	u64 end;
-
-	BUG_ON(!len);
-	end = start + len;
-	return end > start ? end - 1 : NFS4_MAX_UINT64;
-}
-
 /*
  * is l2 fully contained in l1?
  *   start1                             end1
@@ -645,7 +634,6 @@ send_layoutget(struct pnfs_layout_hdr *lo,
 
 	dprintk("--> %s\n", __func__);
 
-	BUG_ON(ctx == NULL);
 	lgp = kzalloc(sizeof(*lgp), gfp_flags);
 	if (lgp == NULL)
 		return NULL;
@@ -1126,7 +1114,6 @@ pnfs_update_layout(struct inode *ino,
 		 * chance of a CB_LAYOUTRECALL(FILE) coming in.
 		 */
 		spin_lock(&clp->cl_lock);
-		BUG_ON(!list_empty(&lo->plh_layouts));
 		list_add_tail(&lo->plh_layouts, &server->layouts);
 		spin_unlock(&clp->cl_lock);
 	}
@@ -1222,7 +1209,7 @@ pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *r
 {
 	u64 rd_size = req->wb_bytes;
 
-	BUG_ON(pgio->pg_lseg != NULL);
+	WARN_ON_ONCE(pgio->pg_lseg != NULL);
 
 	if (req->wb_offset != req->wb_pgbase) {
 		nfs_pageio_reset_read_mds(pgio);
@@ -1251,7 +1238,7 @@ void
 pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
 			   struct nfs_page *req, u64 wb_size)
 {
-	BUG_ON(pgio->pg_lseg != NULL);
+	WARN_ON_ONCE(pgio->pg_lseg != NULL);
 
 	if (req->wb_offset != req->wb_pgbase) {
 		nfs_pageio_reset_write_mds(pgio);
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 652d3f7..e12cea4 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -64,6 +64,7 @@
 #include "iostat.h"
 #include "internal.h"
 #include "fscache.h"
+#include "nfs4session.h"
 #include "pnfs.h"
 #include "nfs.h"
 
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 9347ab7..49e0cbf 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -239,21 +239,18 @@ int nfs_congestion_kb;
 #define NFS_CONGESTION_OFF_THRESH	\
 	(NFS_CONGESTION_ON_THRESH - (NFS_CONGESTION_ON_THRESH >> 2))
 
-static int nfs_set_page_writeback(struct page *page)
+static void nfs_set_page_writeback(struct page *page)
 {
+	struct nfs_server *nfss = NFS_SERVER(page_file_mapping(page)->host);
 	int ret = test_set_page_writeback(page);
 
-	if (!ret) {
-		struct inode *inode = page_file_mapping(page)->host;
-		struct nfs_server *nfss = NFS_SERVER(inode);
+	WARN_ON_ONCE(ret != 0);
 
-		if (atomic_long_inc_return(&nfss->writeback) >
-				NFS_CONGESTION_ON_THRESH) {
-			set_bdi_congested(&nfss->backing_dev_info,
-						BLK_RW_ASYNC);
-		}
+	if (atomic_long_inc_return(&nfss->writeback) >
+			NFS_CONGESTION_ON_THRESH) {
+		set_bdi_congested(&nfss->backing_dev_info,
+					BLK_RW_ASYNC);
 	}
-	return ret;
 }
 
 static void nfs_end_page_writeback(struct page *page)
@@ -315,10 +312,10 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
 	if (IS_ERR(req))
 		goto out;
 
-	ret = nfs_set_page_writeback(page);
-	BUG_ON(ret != 0);
-	BUG_ON(test_bit(PG_CLEAN, &req->wb_flags));
+	nfs_set_page_writeback(page);
+	WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags));
 
+	ret = 0;
 	if (!nfs_pageio_add_request(pgio, req)) {
 		nfs_redirty_request(req);
 		ret = pgio->pg_error;
@@ -451,8 +448,6 @@ static void nfs_inode_remove_request(struct nfs_page *req)
 	struct inode *inode = req->wb_context->dentry->d_inode;
 	struct nfs_inode *nfsi = NFS_I(inode);
 
-	BUG_ON (!NFS_WBACK_BUSY(req));
-
 	spin_lock(&inode->i_lock);
 	if (likely(!PageSwapCache(req->wb_page))) {
 		set_page_private(req->wb_page, 0);
@@ -1727,7 +1722,6 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page)
 	struct nfs_page *req;
 	int ret = 0;
 
-	BUG_ON(!PageLocked(page));
 	for (;;) {
 		wait_on_page_writeback(page);
 		req = nfs_page_find_request(page);
@@ -1829,7 +1823,7 @@ int __init nfs_init_writepagecache(void)
 		goto out_destroy_write_mempool;
 
 	nfs_commit_mempool = mempool_create_slab_pool(MIN_POOL_COMMIT,
-						      nfs_wdata_cachep);
+						      nfs_cdata_cachep);
 	if (nfs_commit_mempool == NULL)
 		goto out_destroy_commit_cache;
 
diff --git a/fs/nfsd/fault_inject.c b/fs/nfsd/fault_inject.c
index e6c3815..0278112 100644
--- a/fs/nfsd/fault_inject.c
+++ b/fs/nfsd/fault_inject.c
@@ -10,7 +10,6 @@
 #include <linux/module.h>
 
 #include "state.h"
-#include "fault_inject.h"
 
 struct nfsd_fault_inject_op {
 	char *file;
diff --git a/fs/nfsd/fault_inject.h b/fs/nfsd/fault_inject.h
deleted file mode 100644
index 90bd057..0000000
--- a/fs/nfsd/fault_inject.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2011 Bryan Schumaker <bjschuma@netapp.com>
- *
- * Function definitions for fault injection
- */
-
-#ifndef LINUX_NFSD_FAULT_INJECT_H
-#define LINUX_NFSD_FAULT_INJECT_H
-
-#ifdef CONFIG_NFSD_FAULT_INJECTION
-int nfsd_fault_inject_init(void);
-void nfsd_fault_inject_cleanup(void);
-void nfsd_forget_clients(u64);
-void nfsd_forget_locks(u64);
-void nfsd_forget_openowners(u64);
-void nfsd_forget_delegations(u64);
-void nfsd_recall_delegations(u64);
-#else /* CONFIG_NFSD_FAULT_INJECTION */
-static inline int nfsd_fault_inject_init(void) { return 0; }
-static inline void nfsd_fault_inject_cleanup(void) {}
-static inline void nfsd_forget_clients(u64 num) {}
-static inline void nfsd_forget_locks(u64 num) {}
-static inline void nfsd_forget_openowners(u64 num) {}
-static inline void nfsd_forget_delegations(u64 num) {}
-static inline void nfsd_recall_delegations(u64 num) {}
-#endif /* CONFIG_NFSD_FAULT_INJECTION */
-
-#endif /* LINUX_NFSD_FAULT_INJECT_H */
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 65c2431..2c4b2e2 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -24,6 +24,16 @@
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 
+/* Hash tables for nfs4_clientid state */
+#define CLIENT_HASH_BITS                 4
+#define CLIENT_HASH_SIZE                (1 << CLIENT_HASH_BITS)
+#define CLIENT_HASH_MASK                (CLIENT_HASH_SIZE - 1)
+
+#define LOCKOWNER_INO_HASH_BITS		8
+#define LOCKOWNER_INO_HASH_SIZE		(1 << LOCKOWNER_INO_HASH_BITS)
+
+#define SESSION_HASH_SIZE	512
+
 struct cld_net;
 
 struct nfsd_net {
@@ -38,6 +48,48 @@ struct nfsd_net {
 	struct lock_manager nfsd4_manager;
 	bool grace_ended;
 	time_t boot_time;
+
+	/*
+	 * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
+	 * used in reboot/reset lease grace period processing
+	 *
+	 * conf_id_hashtbl[], and conf_name_tree hold confirmed
+	 * setclientid_confirmed info.
+	 *
+	 * unconf_str_hastbl[] and unconf_name_tree hold unconfirmed
+	 * setclientid info.
+	 */
+	struct list_head *reclaim_str_hashtbl;
+	int reclaim_str_hashtbl_size;
+	struct list_head *conf_id_hashtbl;
+	struct rb_root conf_name_tree;
+	struct list_head *unconf_id_hashtbl;
+	struct rb_root unconf_name_tree;
+	struct list_head *ownerstr_hashtbl;
+	struct list_head *lockowner_ino_hashtbl;
+	struct list_head *sessionid_hashtbl;
+	/*
+	 * client_lru holds client queue ordered by nfs4_client.cl_time
+	 * for lease renewal.
+	 *
+	 * close_lru holds (open) stateowner queue ordered by nfs4_stateowner.so_time
+	 * for last close replay.
+	 *
+	 * All of the above fields are protected by the client_mutex.
+	 */
+	struct list_head client_lru;
+	struct list_head close_lru;
+
+	struct delayed_work laundromat_work;
+
+	/* client_lock protects the client lru list and session hash table */
+	spinlock_t client_lock;
+
+	struct file *rec_file;
+	bool in_grace;
+
+	time_t nfsd4_lease;
+	time_t nfsd4_grace;
 };
 
 extern int nfsd_net_id;
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index bdf29c9..f8dbb7a 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -36,6 +36,7 @@
 #include <linux/slab.h>
 #include "nfsd.h"
 #include "state.h"
+#include "netns.h"
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
@@ -618,6 +619,7 @@ static struct rpc_stat cb_stats = {
 #define NFS4_CALLBACK 0x40000000
 static const struct rpc_program cb_program = {
 	.name			= "nfs4_cb",
+	.service_name		= "nfs",	/* See RFC3530, Section 3.4 */
 	.number			= NFS4_CALLBACK,
 	.nrvers			= ARRAY_SIZE(nfs_cb_version),
 	.version		= nfs_cb_version,
@@ -625,20 +627,46 @@ static const struct rpc_program cb_program = {
 	.pipe_dir_name		= "nfsd4_cb",
 };
 
-static int max_cb_time(void)
+static int max_cb_time(struct net *net)
 {
-	return max(nfsd4_lease/10, (time_t)1) * HZ;
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+	return max(nn->nfsd4_lease/10, (time_t)1) * HZ;
 }
 
+static struct rpc_cred *callback_cred;
+
+int set_callback_cred(void)
+{
+	if (callback_cred)
+		return 0;
+	callback_cred = rpc_lookup_machine_cred("nfs");
+	if (!callback_cred)
+		return -ENOMEM;
+	return 0;
+}
+
+static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses)
+{
+	if (clp->cl_minorversion == 0) {
+		return get_rpccred(callback_cred);
+	} else {
+		struct rpc_auth *auth = client->cl_auth;
+		struct auth_cred acred = {};
+
+		acred.uid = ses->se_cb_sec.uid;
+		acred.gid = ses->se_cb_sec.gid;
+		return auth->au_ops->lookup_cred(client->cl_auth, &acred, 0);
+	}
+}
 
 static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
 {
 	struct rpc_timeout	timeparms = {
-		.to_initval	= max_cb_time(),
+		.to_initval	= max_cb_time(clp->net),
 		.to_retries	= 0,
 	};
 	struct rpc_create_args args = {
-		.net		= &init_net,
+		.net		= clp->net,
 		.address	= (struct sockaddr *) &conn->cb_addr,
 		.addrsize	= conn->cb_addrlen,
 		.saddress	= (struct sockaddr *) &conn->cb_saddr,
@@ -648,6 +676,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
 		.flags		= (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
 	};
 	struct rpc_clnt *client;
+	struct rpc_cred *cred;
 
 	if (clp->cl_minorversion == 0) {
 		if (!clp->cl_cred.cr_principal &&
@@ -666,7 +695,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
 		args.bc_xprt = conn->cb_xprt;
 		args.prognumber = clp->cl_cb_session->se_cb_prog;
 		args.protocol = XPRT_TRANSPORT_BC_TCP;
-		args.authflavor = RPC_AUTH_UNIX;
+		args.authflavor = ses->se_cb_sec.flavor;
 	}
 	/* Create RPC client */
 	client = rpc_create(&args);
@@ -675,9 +704,14 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
 			PTR_ERR(client));
 		return PTR_ERR(client);
 	}
+	cred = get_backchannel_cred(clp, client, ses);
+	if (IS_ERR(cred)) {
+		rpc_shutdown_client(client);
+		return PTR_ERR(cred);
+	}
 	clp->cl_cb_client = client;
+	clp->cl_cb_cred = cred;
 	return 0;
-
 }
 
 static void warn_no_callback_path(struct nfs4_client *clp, int reason)
@@ -714,18 +748,6 @@ static const struct rpc_call_ops nfsd4_cb_probe_ops = {
 	.rpc_call_done = nfsd4_cb_probe_done,
 };
 
-static struct rpc_cred *callback_cred;
-
-int set_callback_cred(void)
-{
-	if (callback_cred)
-		return 0;
-	callback_cred = rpc_lookup_machine_cred("nfs");
-	if (!callback_cred)
-		return -ENOMEM;
-	return 0;
-}
-
 static struct workqueue_struct *callback_wq;
 
 static void run_nfsd4_cb(struct nfsd4_callback *cb)
@@ -743,7 +765,6 @@ static void do_probe_callback(struct nfs4_client *clp)
 	cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL];
 	cb->cb_msg.rpc_argp = NULL;
 	cb->cb_msg.rpc_resp = NULL;
-	cb->cb_msg.rpc_cred = callback_cred;
 
 	cb->cb_ops = &nfsd4_cb_probe_ops;
 
@@ -962,6 +983,8 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
 	if (clp->cl_cb_client) {
 		rpc_shutdown_client(clp->cl_cb_client);
 		clp->cl_cb_client = NULL;
+		put_rpccred(clp->cl_cb_cred);
+		clp->cl_cb_cred = NULL;
 	}
 	if (clp->cl_cb_conn.cb_xprt) {
 		svc_xprt_put(clp->cl_cb_conn.cb_xprt);
@@ -995,7 +1018,7 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
 		run_nfsd4_cb(cb);
 }
 
-void nfsd4_do_callback_rpc(struct work_struct *w)
+static void nfsd4_do_callback_rpc(struct work_struct *w)
 {
 	struct nfsd4_callback *cb = container_of(w, struct nfsd4_callback, cb_work);
 	struct nfs4_client *clp = cb->cb_clp;
@@ -1010,10 +1033,16 @@ void nfsd4_do_callback_rpc(struct work_struct *w)
 		nfsd4_release_cb(cb);
 		return;
 	}
+	cb->cb_msg.rpc_cred = clp->cl_cb_cred;
 	rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
 			cb->cb_ops, cb);
 }
 
+void nfsd4_init_callback(struct nfsd4_callback *cb)
+{
+	INIT_WORK(&cb->cb_work, nfsd4_do_callback_rpc);
+}
+
 void nfsd4_cb_recall(struct nfs4_delegation *dp)
 {
 	struct nfsd4_callback *cb = &dp->dl_recall;
@@ -1025,7 +1054,6 @@ void nfsd4_cb_recall(struct nfs4_delegation *dp)
 	cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL];
 	cb->cb_msg.rpc_argp = cb;
 	cb->cb_msg.rpc_resp = cb;
-	cb->cb_msg.rpc_cred = callback_cred;
 
 	cb->cb_ops = &nfsd4_cb_recall_ops;
 
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 6c9a4b2..87d24e5 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -40,6 +40,7 @@
 #include "xdr4.h"
 #include "vfs.h"
 #include "current_stateid.h"
+#include "netns.h"
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
@@ -304,6 +305,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 {
 	__be32 status;
 	struct nfsd4_compoundres *resp;
+	struct net *net = SVC_NET(rqstp);
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
 	dprintk("NFSD: nfsd4_open filename %.*s op_openowner %p\n",
 		(int)open->op_fname.len, open->op_fname.data,
@@ -331,7 +334,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
 	/* check seqid for replay. set nfs4_owner */
 	resp = rqstp->rq_resp;
-	status = nfsd4_process_open1(&resp->cstate, open);
+	status = nfsd4_process_open1(&resp->cstate, open, nn);
 	if (status == nfserr_replay_me) {
 		struct nfs4_replay *rp = &open->op_openowner->oo_owner.so_replay;
 		fh_put(&cstate->current_fh);
@@ -354,10 +357,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	/* Openowner is now set, so sequence id will get bumped.  Now we need
 	 * these checks before we do any creates: */
 	status = nfserr_grace;
-	if (locks_in_grace(SVC_NET(rqstp)) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
+	if (locks_in_grace(net) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
 		goto out;
 	status = nfserr_no_grace;
-	if (!locks_in_grace(SVC_NET(rqstp)) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+	if (!locks_in_grace(net) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
 		goto out;
 
 	switch (open->op_claim_type) {
@@ -370,7 +373,9 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 			break;
 		case NFS4_OPEN_CLAIM_PREVIOUS:
 			open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
-			status = nfs4_check_open_reclaim(&open->op_clientid, cstate->minorversion);
+			status = nfs4_check_open_reclaim(&open->op_clientid,
+							 cstate->minorversion,
+							 nn);
 			if (status)
 				goto out;
 		case NFS4_OPEN_CLAIM_FH:
@@ -876,6 +881,24 @@ out:
 	return status;
 }
 
+static int fill_in_write_vector(struct kvec *vec, struct nfsd4_write *write)
+{
+        int i = 1;
+        int buflen = write->wr_buflen;
+
+        vec[0].iov_base = write->wr_head.iov_base;
+        vec[0].iov_len = min_t(int, buflen, write->wr_head.iov_len);
+        buflen -= vec[0].iov_len;
+
+        while (buflen) {
+                vec[i].iov_base = page_address(write->wr_pagelist[i - 1]);
+                vec[i].iov_len = min_t(int, PAGE_SIZE, buflen);
+                buflen -= vec[i].iov_len;
+                i++;
+        }
+        return i;
+}
+
 static __be32
 nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	    struct nfsd4_write *write)
@@ -884,6 +907,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	struct file *filp = NULL;
 	__be32 status = nfs_ok;
 	unsigned long cnt;
+	int nvecs;
 
 	/* no need to check permission - this will be done in nfsd_write() */
 
@@ -906,8 +930,11 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	write->wr_how_written = write->wr_stable_how;
 	gen_boot_verifier(&write->wr_verifier);
 
+	nvecs = fill_in_write_vector(rqstp->rq_vec, write);
+	WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec));
+
 	status =  nfsd_write(rqstp, &cstate->current_fh, filp,
-			     write->wr_offset, rqstp->rq_vec, write->wr_vlen,
+			     write->wr_offset, rqstp->rq_vec, nvecs,
 			     &cnt, &write->wr_how_written);
 	if (filp)
 		fput(filp);
@@ -1666,6 +1693,12 @@ static struct nfsd4_operation nfsd4_ops[] = {
 		.op_name = "OP_EXCHANGE_ID",
 		.op_rsize_bop = (nfsd4op_rsize)nfsd4_exchange_id_rsize,
 	},
+	[OP_BACKCHANNEL_CTL] = {
+		.op_func = (nfsd4op_func)nfsd4_backchannel_ctl,
+		.op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING,
+		.op_name = "OP_BACKCHANNEL_CTL",
+		.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
+	},
 	[OP_BIND_CONN_TO_SESSION] = {
 		.op_func = (nfsd4op_func)nfsd4_bind_conn_to_session,
 		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 43295d4..359793f 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -58,11 +58,10 @@ struct nfsd4_client_tracking_ops {
 	void (*create)(struct nfs4_client *);
 	void (*remove)(struct nfs4_client *);
 	int (*check)(struct nfs4_client *);
-	void (*grace_done)(struct net *, time_t);
+	void (*grace_done)(struct nfsd_net *, time_t);
 };
 
 /* Globals */
-static struct file *rec_file;
 static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
 static struct nfsd4_client_tracking_ops *client_tracking_ops;
 
@@ -102,33 +101,39 @@ md5_to_hex(char *out, char *md5)
 	*out = '\0';
 }
 
-__be32
-nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
+static int
+nfs4_make_rec_clidname(char *dname, const struct xdr_netobj *clname)
 {
 	struct xdr_netobj cksum;
 	struct hash_desc desc;
 	struct scatterlist sg;
-	__be32 status = nfserr_jukebox;
+	int status;
 
 	dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
 			clname->len, clname->data);
 	desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
 	desc.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(desc.tfm))
+	if (IS_ERR(desc.tfm)) {
+		status = PTR_ERR(desc.tfm);
 		goto out_no_tfm;
+	}
+
 	cksum.len = crypto_hash_digestsize(desc.tfm);
 	cksum.data = kmalloc(cksum.len, GFP_KERNEL);
-	if (cksum.data == NULL)
+	if (cksum.data == NULL) {
+		status = -ENOMEM;
  		goto out;
+	}
 
 	sg_init_one(&sg, clname->data, clname->len);
 
-	if (crypto_hash_digest(&desc, &sg, sg.length, cksum.data))
+	status = crypto_hash_digest(&desc, &sg, sg.length, cksum.data);
+	if (status)
 		goto out;
 
 	md5_to_hex(dname, cksum.data);
 
-	status = nfs_ok;
+	status = 0;
 out:
 	kfree(cksum.data);
 	crypto_free_hash(desc.tfm);
@@ -136,29 +141,61 @@ out_no_tfm:
 	return status;
 }
 
+/*
+ * If we had an error generating the recdir name for the legacy tracker
+ * then warn the admin. If the error doesn't appear to be transient,
+ * then disable recovery tracking.
+ */
+static void
+legacy_recdir_name_error(int error)
+{
+	printk(KERN_ERR "NFSD: unable to generate recoverydir "
+			"name (%d).\n", error);
+
+	/*
+	 * if the algorithm just doesn't exist, then disable the recovery
+	 * tracker altogether. The crypto libs will generally return this if
+	 * FIPS is enabled as well.
+	 */
+	if (error == -ENOENT) {
+		printk(KERN_ERR "NFSD: disabling legacy clientid tracking. "
+			"Reboot recovery will not function correctly!\n");
+
+		/* the argument is ignored by the legacy exit function */
+		nfsd4_client_tracking_exit(NULL);
+	}
+}
+
 static void
 nfsd4_create_clid_dir(struct nfs4_client *clp)
 {
 	const struct cred *original_cred;
-	char *dname = clp->cl_recdir;
+	char dname[HEXDIR_LEN];
 	struct dentry *dir, *dentry;
+	struct nfs4_client_reclaim *crp;
 	int status;
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
 	dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
 
 	if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
 		return;
-	if (!rec_file)
+	if (!nn->rec_file)
 		return;
+
+	status = nfs4_make_rec_clidname(dname, &clp->cl_name);
+	if (status)
+		return legacy_recdir_name_error(status);
+
 	status = nfs4_save_creds(&original_cred);
 	if (status < 0)
 		return;
 
-	status = mnt_want_write_file(rec_file);
+	status = mnt_want_write_file(nn->rec_file);
 	if (status)
 		return;
 
-	dir = rec_file->f_path.dentry;
+	dir = nn->rec_file->f_path.dentry;
 	/* lock the parent */
 	mutex_lock(&dir->d_inode->i_mutex);
 
@@ -182,18 +219,24 @@ out_put:
 	dput(dentry);
 out_unlock:
 	mutex_unlock(&dir->d_inode->i_mutex);
-	if (status == 0)
-		vfs_fsync(rec_file, 0);
-	else
+	if (status == 0) {
+		if (nn->in_grace) {
+			crp = nfs4_client_to_reclaim(dname, nn);
+			if (crp)
+				crp->cr_clp = clp;
+		}
+		vfs_fsync(nn->rec_file, 0);
+	} else {
 		printk(KERN_ERR "NFSD: failed to write recovery record"
 				" (err %d); please check that %s exists"
 				" and is writeable", status,
 				user_recovery_dirname);
-	mnt_drop_write_file(rec_file);
+	}
+	mnt_drop_write_file(nn->rec_file);
 	nfs4_reset_creds(original_cred);
 }
 
-typedef int (recdir_func)(struct dentry *, struct dentry *);
+typedef int (recdir_func)(struct dentry *, struct dentry *, struct nfsd_net *);
 
 struct name_list {
 	char name[HEXDIR_LEN];
@@ -219,10 +262,10 @@ nfsd4_build_namelist(void *arg, const char *name, int namlen,
 }
 
 static int
-nfsd4_list_rec_dir(recdir_func *f)
+nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
 {
 	const struct cred *original_cred;
-	struct dentry *dir = rec_file->f_path.dentry;
+	struct dentry *dir = nn->rec_file->f_path.dentry;
 	LIST_HEAD(names);
 	int status;
 
@@ -230,13 +273,13 @@ nfsd4_list_rec_dir(recdir_func *f)
 	if (status < 0)
 		return status;
 
-	status = vfs_llseek(rec_file, 0, SEEK_SET);
+	status = vfs_llseek(nn->rec_file, 0, SEEK_SET);
 	if (status < 0) {
 		nfs4_reset_creds(original_cred);
 		return status;
 	}
 
-	status = vfs_readdir(rec_file, nfsd4_build_namelist, &names);
+	status = vfs_readdir(nn->rec_file, nfsd4_build_namelist, &names);
 	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
 	while (!list_empty(&names)) {
 		struct name_list *entry;
@@ -248,7 +291,7 @@ nfsd4_list_rec_dir(recdir_func *f)
 				status = PTR_ERR(dentry);
 				break;
 			}
-			status = f(dir, dentry);
+			status = f(dir, dentry, nn);
 			dput(dentry);
 		}
 		list_del(&entry->list);
@@ -260,14 +303,14 @@ nfsd4_list_rec_dir(recdir_func *f)
 }
 
 static int
-nfsd4_unlink_clid_dir(char *name, int namlen)
+nfsd4_unlink_clid_dir(char *name, int namlen, struct nfsd_net *nn)
 {
 	struct dentry *dir, *dentry;
 	int status;
 
 	dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
 
-	dir = rec_file->f_path.dentry;
+	dir = nn->rec_file->f_path.dentry;
 	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
 	dentry = lookup_one_len(name, dir, namlen);
 	if (IS_ERR(dentry)) {
@@ -289,37 +332,52 @@ static void
 nfsd4_remove_clid_dir(struct nfs4_client *clp)
 {
 	const struct cred *original_cred;
+	struct nfs4_client_reclaim *crp;
+	char dname[HEXDIR_LEN];
 	int status;
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
-	if (!rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
+	if (!nn->rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
 		return;
 
-	status = mnt_want_write_file(rec_file);
+	status = nfs4_make_rec_clidname(dname, &clp->cl_name);
+	if (status)
+		return legacy_recdir_name_error(status);
+
+	status = mnt_want_write_file(nn->rec_file);
 	if (status)
 		goto out;
 	clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
 
 	status = nfs4_save_creds(&original_cred);
 	if (status < 0)
-		goto out;
+		goto out_drop_write;
 
-	status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
+	status = nfsd4_unlink_clid_dir(dname, HEXDIR_LEN-1, nn);
 	nfs4_reset_creds(original_cred);
-	if (status == 0)
-		vfs_fsync(rec_file, 0);
-	mnt_drop_write_file(rec_file);
+	if (status == 0) {
+		vfs_fsync(nn->rec_file, 0);
+		if (nn->in_grace) {
+			/* remove reclaim record */
+			crp = nfsd4_find_reclaim_client(dname, nn);
+			if (crp)
+				nfs4_remove_reclaim_record(crp, nn);
+		}
+	}
+out_drop_write:
+	mnt_drop_write_file(nn->rec_file);
 out:
 	if (status)
 		printk("NFSD: Failed to remove expired client state directory"
-				" %.*s\n", HEXDIR_LEN, clp->cl_recdir);
+				" %.*s\n", HEXDIR_LEN, dname);
 }
 
 static int
-purge_old(struct dentry *parent, struct dentry *child)
+purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
 {
 	int status;
 
-	if (nfs4_has_reclaimed_state(child->d_name.name, false))
+	if (nfs4_has_reclaimed_state(child->d_name.name, nn))
 		return 0;
 
 	status = vfs_rmdir(parent->d_inode, child);
@@ -331,27 +389,29 @@ purge_old(struct dentry *parent, struct dentry *child)
 }
 
 static void
-nfsd4_recdir_purge_old(struct net *net, time_t boot_time)
+nfsd4_recdir_purge_old(struct nfsd_net *nn, time_t boot_time)
 {
 	int status;
 
-	if (!rec_file)
+	nn->in_grace = false;
+	if (!nn->rec_file)
 		return;
-	status = mnt_want_write_file(rec_file);
+	status = mnt_want_write_file(nn->rec_file);
 	if (status)
 		goto out;
-	status = nfsd4_list_rec_dir(purge_old);
+	status = nfsd4_list_rec_dir(purge_old, nn);
 	if (status == 0)
-		vfs_fsync(rec_file, 0);
-	mnt_drop_write_file(rec_file);
+		vfs_fsync(nn->rec_file, 0);
+	mnt_drop_write_file(nn->rec_file);
 out:
+	nfs4_release_reclaim(nn);
 	if (status)
 		printk("nfsd4: failed to purge old clients from recovery"
-			" directory %s\n", rec_file->f_path.dentry->d_name.name);
+			" directory %s\n", nn->rec_file->f_path.dentry->d_name.name);
 }
 
 static int
-load_recdir(struct dentry *parent, struct dentry *child)
+load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
 {
 	if (child->d_name.len != HEXDIR_LEN - 1) {
 		printk("nfsd4: illegal name %s in recovery directory\n",
@@ -359,21 +419,22 @@ load_recdir(struct dentry *parent, struct dentry *child)
 		/* Keep trying; maybe the others are OK: */
 		return 0;
 	}
-	nfs4_client_to_reclaim(child->d_name.name);
+	nfs4_client_to_reclaim(child->d_name.name, nn);
 	return 0;
 }
 
 static int
-nfsd4_recdir_load(void) {
+nfsd4_recdir_load(struct net *net) {
 	int status;
+	struct nfsd_net *nn =  net_generic(net, nfsd_net_id);
 
-	if (!rec_file)
+	if (!nn->rec_file)
 		return 0;
 
-	status = nfsd4_list_rec_dir(load_recdir);
+	status = nfsd4_list_rec_dir(load_recdir, nn);
 	if (status)
 		printk("nfsd4: failed loading clients from recovery"
-			" directory %s\n", rec_file->f_path.dentry->d_name.name);
+			" directory %s\n", nn->rec_file->f_path.dentry->d_name.name);
 	return status;
 }
 
@@ -382,15 +443,16 @@ nfsd4_recdir_load(void) {
  */
 
 static int
-nfsd4_init_recdir(void)
+nfsd4_init_recdir(struct net *net)
 {
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 	const struct cred *original_cred;
 	int status;
 
 	printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
 			user_recovery_dirname);
 
-	BUG_ON(rec_file);
+	BUG_ON(nn->rec_file);
 
 	status = nfs4_save_creds(&original_cred);
 	if (status < 0) {
@@ -400,23 +462,65 @@ nfsd4_init_recdir(void)
 		return status;
 	}
 
-	rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0);
-	if (IS_ERR(rec_file)) {
+	nn->rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0);
+	if (IS_ERR(nn->rec_file)) {
 		printk("NFSD: unable to find recovery directory %s\n",
 				user_recovery_dirname);
-		status = PTR_ERR(rec_file);
-		rec_file = NULL;
+		status = PTR_ERR(nn->rec_file);
+		nn->rec_file = NULL;
 	}
 
 	nfs4_reset_creds(original_cred);
+	if (!status)
+		nn->in_grace = true;
 	return status;
 }
 
+
+static int
+nfs4_legacy_state_init(struct net *net)
+{
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+	int i;
+
+	nn->reclaim_str_hashtbl = kmalloc(sizeof(struct list_head) *
+					  CLIENT_HASH_SIZE, GFP_KERNEL);
+	if (!nn->reclaim_str_hashtbl)
+		return -ENOMEM;
+
+	for (i = 0; i < CLIENT_HASH_SIZE; i++)
+		INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]);
+	nn->reclaim_str_hashtbl_size = 0;
+
+	return 0;
+}
+
+static void
+nfs4_legacy_state_shutdown(struct net *net)
+{
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+	kfree(nn->reclaim_str_hashtbl);
+}
+
 static int
 nfsd4_load_reboot_recovery_data(struct net *net)
 {
 	int status;
 
+	status = nfsd4_init_recdir(net);
+	if (!status)
+		status = nfsd4_recdir_load(net);
+	if (status)
+		printk(KERN_ERR "NFSD: Failure reading reboot recovery data\n");
+	return status;
+}
+
+static int
+nfsd4_legacy_tracking_init(struct net *net)
+{
+	int status;
+
 	/* XXX: The legacy code won't work in a container */
 	if (net != &init_net) {
 		WARN(1, KERN_ERR "NFSD: attempt to initialize legacy client "
@@ -424,30 +528,37 @@ nfsd4_load_reboot_recovery_data(struct net *net)
 		return -EINVAL;
 	}
 
-	nfs4_lock_state();
-	status = nfsd4_init_recdir();
-	if (!status)
-		status = nfsd4_recdir_load();
-	nfs4_unlock_state();
+	status = nfs4_legacy_state_init(net);
 	if (status)
-		printk(KERN_ERR "NFSD: Failure reading reboot recovery data\n");
+		return status;
+
+	status = nfsd4_load_reboot_recovery_data(net);
+	if (status)
+		goto err;
+	return 0;
+
+err:
+	nfs4_legacy_state_shutdown(net);
 	return status;
 }
 
 static void
-nfsd4_shutdown_recdir(void)
+nfsd4_shutdown_recdir(struct nfsd_net *nn)
 {
-	if (!rec_file)
+	if (!nn->rec_file)
 		return;
-	fput(rec_file);
-	rec_file = NULL;
+	fput(nn->rec_file);
+	nn->rec_file = NULL;
 }
 
 static void
 nfsd4_legacy_tracking_exit(struct net *net)
 {
-	nfs4_release_reclaim();
-	nfsd4_shutdown_recdir();
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+	nfs4_release_reclaim(nn);
+	nfsd4_shutdown_recdir(nn);
+	nfs4_legacy_state_shutdown(net);
 }
 
 /*
@@ -480,13 +591,26 @@ nfs4_recoverydir(void)
 static int
 nfsd4_check_legacy_client(struct nfs4_client *clp)
 {
+	int status;
+	char dname[HEXDIR_LEN];
+	struct nfs4_client_reclaim *crp;
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
 	/* did we already find that this client is stable? */
 	if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
 		return 0;
 
+	status = nfs4_make_rec_clidname(dname, &clp->cl_name);
+	if (status) {
+		legacy_recdir_name_error(status);
+		return status;
+	}
+
 	/* look for it in the reclaim hashtable otherwise */
-	if (nfsd4_find_reclaim_client(clp)) {
+	crp = nfsd4_find_reclaim_client(dname, nn);
+	if (crp) {
 		set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
+		crp->cr_clp = clp;
 		return 0;
 	}
 
@@ -494,7 +618,7 @@ nfsd4_check_legacy_client(struct nfs4_client *clp)
 }
 
 static struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = {
-	.init		= nfsd4_load_reboot_recovery_data,
+	.init		= nfsd4_legacy_tracking_init,
 	.exit		= nfsd4_legacy_tracking_exit,
 	.create		= nfsd4_create_clid_dir,
 	.remove		= nfsd4_remove_clid_dir,
@@ -785,8 +909,7 @@ nfsd4_cld_create(struct nfs4_client *clp)
 {
 	int ret;
 	struct cld_upcall *cup;
-	/* FIXME: determine net from clp */
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 	struct cld_net *cn = nn->cld_net;
 
 	/* Don't upcall if it's already stored */
@@ -823,8 +946,7 @@ nfsd4_cld_remove(struct nfs4_client *clp)
 {
 	int ret;
 	struct cld_upcall *cup;
-	/* FIXME: determine net from clp */
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 	struct cld_net *cn = nn->cld_net;
 
 	/* Don't upcall if it's already removed */
@@ -861,8 +983,7 @@ nfsd4_cld_check(struct nfs4_client *clp)
 {
 	int ret;
 	struct cld_upcall *cup;
-	/* FIXME: determine net from clp */
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 	struct cld_net *cn = nn->cld_net;
 
 	/* Don't upcall if one was already stored during this grace pd */
@@ -892,11 +1013,10 @@ nfsd4_cld_check(struct nfs4_client *clp)
 }
 
 static void
-nfsd4_cld_grace_done(struct net *net, time_t boot_time)
+nfsd4_cld_grace_done(struct nfsd_net *nn, time_t boot_time)
 {
 	int ret;
 	struct cld_upcall *cup;
-	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 	struct cld_net *cn = nn->cld_net;
 
 	cup = alloc_cld_upcall(cn);
@@ -926,23 +1046,255 @@ static struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = {
 	.grace_done	= nfsd4_cld_grace_done,
 };
 
+/* upcall via usermodehelper */
+static char cltrack_prog[PATH_MAX] = "/sbin/nfsdcltrack";
+module_param_string(cltrack_prog, cltrack_prog, sizeof(cltrack_prog),
+			S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(cltrack_prog, "Path to the nfsdcltrack upcall program");
+
+static bool cltrack_legacy_disable;
+module_param(cltrack_legacy_disable, bool, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(cltrack_legacy_disable,
+		"Disable legacy recoverydir conversion. Default: false");
+
+#define LEGACY_TOPDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_TOPDIR="
+#define LEGACY_RECDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_RECDIR="
+
+static char *
+nfsd4_cltrack_legacy_topdir(void)
+{
+	int copied;
+	size_t len;
+	char *result;
+
+	if (cltrack_legacy_disable)
+		return NULL;
+
+	len = strlen(LEGACY_TOPDIR_ENV_PREFIX) +
+		strlen(nfs4_recoverydir()) + 1;
+
+	result = kmalloc(len, GFP_KERNEL);
+	if (!result)
+		return result;
+
+	copied = snprintf(result, len, LEGACY_TOPDIR_ENV_PREFIX "%s",
+				nfs4_recoverydir());
+	if (copied >= len) {
+		/* just return nothing if output was truncated */
+		kfree(result);
+		return NULL;
+	}
+
+	return result;
+}
+
+static char *
+nfsd4_cltrack_legacy_recdir(const struct xdr_netobj *name)
+{
+	int copied;
+	size_t len;
+	char *result;
+
+	if (cltrack_legacy_disable)
+		return NULL;
+
+	/* +1 is for '/' between "topdir" and "recdir" */
+	len = strlen(LEGACY_RECDIR_ENV_PREFIX) +
+		strlen(nfs4_recoverydir()) + 1 + HEXDIR_LEN;
+
+	result = kmalloc(len, GFP_KERNEL);
+	if (!result)
+		return result;
+
+	copied = snprintf(result, len, LEGACY_RECDIR_ENV_PREFIX "%s/",
+				nfs4_recoverydir());
+	if (copied > (len - HEXDIR_LEN)) {
+		/* just return nothing if output will be truncated */
+		kfree(result);
+		return NULL;
+	}
+
+	copied = nfs4_make_rec_clidname(result + copied, name);
+	if (copied) {
+		kfree(result);
+		return NULL;
+	}
+
+	return result;
+}
+
+static int
+nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *legacy)
+{
+	char *envp[2];
+	char *argv[4];
+	int ret;
+
+	if (unlikely(!cltrack_prog[0])) {
+		dprintk("%s: cltrack_prog is disabled\n", __func__);
+		return -EACCES;
+	}
+
+	dprintk("%s: cmd: %s\n", __func__, cmd);
+	dprintk("%s: arg: %s\n", __func__, arg ? arg : "(null)");
+	dprintk("%s: legacy: %s\n", __func__, legacy ? legacy : "(null)");
+
+	envp[0] = legacy;
+	envp[1] = NULL;
+
+	argv[0] = (char *)cltrack_prog;
+	argv[1] = cmd;
+	argv[2] = arg;
+	argv[3] = NULL;
+
+	ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
+	/*
+	 * Disable the upcall mechanism if we're getting an ENOENT or EACCES
+	 * error. The admin can re-enable it on the fly by using sysfs
+	 * once the problem has been fixed.
+	 */
+	if (ret == -ENOENT || ret == -EACCES) {
+		dprintk("NFSD: %s was not found or isn't executable (%d). "
+			"Setting cltrack_prog to blank string!",
+			cltrack_prog, ret);
+		cltrack_prog[0] = '\0';
+	}
+	dprintk("%s: %s return value: %d\n", __func__, cltrack_prog, ret);
+
+	return ret;
+}
+
+static char *
+bin_to_hex_dup(const unsigned char *src, int srclen)
+{
+	int i;
+	char *buf, *hex;
+
+	/* +1 for terminating NULL */
+	buf = kmalloc((srclen * 2) + 1, GFP_KERNEL);
+	if (!buf)
+		return buf;
+
+	hex = buf;
+	for (i = 0; i < srclen; i++) {
+		sprintf(hex, "%2.2x", *src++);
+		hex += 2;
+	}
+	return buf;
+}
+
+static int
+nfsd4_umh_cltrack_init(struct net __attribute__((unused)) *net)
+{
+	return nfsd4_umh_cltrack_upcall("init", NULL, NULL);
+}
+
+static void
+nfsd4_umh_cltrack_create(struct nfs4_client *clp)
+{
+	char *hexid;
+
+	hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
+	if (!hexid) {
+		dprintk("%s: can't allocate memory for upcall!\n", __func__);
+		return;
+	}
+	nfsd4_umh_cltrack_upcall("create", hexid, NULL);
+	kfree(hexid);
+}
+
+static void
+nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
+{
+	char *hexid;
+
+	hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
+	if (!hexid) {
+		dprintk("%s: can't allocate memory for upcall!\n", __func__);
+		return;
+	}
+	nfsd4_umh_cltrack_upcall("remove", hexid, NULL);
+	kfree(hexid);
+}
+
+static int
+nfsd4_umh_cltrack_check(struct nfs4_client *clp)
+{
+	int ret;
+	char *hexid, *legacy;
+
+	hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
+	if (!hexid) {
+		dprintk("%s: can't allocate memory for upcall!\n", __func__);
+		return -ENOMEM;
+	}
+	legacy = nfsd4_cltrack_legacy_recdir(&clp->cl_name);
+	ret = nfsd4_umh_cltrack_upcall("check", hexid, legacy);
+	kfree(legacy);
+	kfree(hexid);
+	return ret;
+}
+
+static void
+nfsd4_umh_cltrack_grace_done(struct nfsd_net __attribute__((unused)) *nn,
+				time_t boot_time)
+{
+	char *legacy;
+	char timestr[22]; /* FIXME: better way to determine max size? */
+
+	sprintf(timestr, "%ld", boot_time);
+	legacy = nfsd4_cltrack_legacy_topdir();
+	nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy);
+	kfree(legacy);
+}
+
+static struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = {
+	.init		= nfsd4_umh_cltrack_init,
+	.exit		= NULL,
+	.create		= nfsd4_umh_cltrack_create,
+	.remove		= nfsd4_umh_cltrack_remove,
+	.check		= nfsd4_umh_cltrack_check,
+	.grace_done	= nfsd4_umh_cltrack_grace_done,
+};
+
 int
 nfsd4_client_tracking_init(struct net *net)
 {
 	int status;
 	struct path path;
 
-	if (!client_tracking_ops) {
-		client_tracking_ops = &nfsd4_cld_tracking_ops;
-		status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path);
-		if (!status) {
-			if (S_ISDIR(path.dentry->d_inode->i_mode))
-				client_tracking_ops =
-						&nfsd4_legacy_tracking_ops;
-			path_put(&path);
-		}
+	/* just run the init if it the method is already decided */
+	if (client_tracking_ops)
+		goto do_init;
+
+	/*
+	 * First, try a UMH upcall. It should succeed or fail quickly, so
+	 * there's little harm in trying that first.
+	 */
+	client_tracking_ops = &nfsd4_umh_tracking_ops;
+	status = client_tracking_ops->init(net);
+	if (!status)
+		return status;
+
+	/*
+	 * See if the recoverydir exists and is a directory. If it is,
+	 * then use the legacy ops.
+	 */
+	client_tracking_ops = &nfsd4_legacy_tracking_ops;
+	status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path);
+	if (!status) {
+		status = S_ISDIR(path.dentry->d_inode->i_mode);
+		path_put(&path);
+		if (status)
+			goto do_init;
 	}
 
+	/* Finally, try to use nfsdcld */
+	client_tracking_ops = &nfsd4_cld_tracking_ops;
+	printk(KERN_WARNING "NFSD: the nfsdcld client tracking upcall will be "
+			"removed in 3.10. Please transition to using "
+			"nfsdcltrack.\n");
+do_init:
 	status = client_tracking_ops->init(net);
 	if (status) {
 		printk(KERN_WARNING "NFSD: Unable to initialize client "
@@ -956,7 +1308,8 @@ void
 nfsd4_client_tracking_exit(struct net *net)
 {
 	if (client_tracking_ops) {
-		client_tracking_ops->exit(net);
+		if (client_tracking_ops->exit)
+			client_tracking_ops->exit(net);
 		client_tracking_ops = NULL;
 	}
 }
@@ -985,10 +1338,10 @@ nfsd4_client_record_check(struct nfs4_client *clp)
 }
 
 void
-nfsd4_record_grace_done(struct net *net, time_t boot_time)
+nfsd4_record_grace_done(struct nfsd_net *nn, time_t boot_time)
 {
 	if (client_tracking_ops)
-		client_tracking_ops->grace_done(net, boot_time);
+		client_tracking_ops->grace_done(nn, boot_time);
 }
 
 static int
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index d0237f8..b1aa577 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -44,16 +44,11 @@
 #include "xdr4.h"
 #include "vfs.h"
 #include "current_stateid.h"
-#include "fault_inject.h"
 
 #include "netns.h"
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
-/* Globals */
-time_t nfsd4_lease = 90;     /* default lease time */
-time_t nfsd4_grace = 90;
-
 #define all_ones {{~0,~0},~0}
 static const stateid_t one_stateid = {
 	.si_generation = ~0,
@@ -176,8 +171,6 @@ static unsigned int ownerstr_hashval(u32 clientid, struct xdr_netobj *ownername)
 	return ret & OWNER_HASH_MASK;
 }
 
-static struct list_head	ownerstr_hashtbl[OWNER_HASH_SIZE];
-
 /* hash table for nfs4_file */
 #define FILE_HASH_BITS                   8
 #define FILE_HASH_SIZE                  (1 << FILE_HASH_BITS)
@@ -192,7 +185,7 @@ static struct list_head file_hashtbl[FILE_HASH_SIZE];
 
 static void __nfs4_file_get_access(struct nfs4_file *fp, int oflag)
 {
-	BUG_ON(!(fp->fi_fds[oflag] || fp->fi_fds[O_RDWR]));
+	WARN_ON_ONCE(!(fp->fi_fds[oflag] || fp->fi_fds[O_RDWR]));
 	atomic_inc(&fp->fi_access[oflag]);
 }
 
@@ -251,7 +244,7 @@ static inline int get_new_stid(struct nfs4_stid *stid)
 	 * preallocations that can exist at a time, but the state lock
 	 * prevents anyone from using ours before we get here:
 	 */
-	BUG_ON(error);
+	WARN_ON_ONCE(error);
 	/*
 	 * It shouldn't be a problem to reuse an opaque stateid value.
 	 * I don't think it is for 4.1.  But with 4.0 I worry that, for
@@ -340,7 +333,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct sv
 	fh_copy_shallow(&dp->dl_fh, &current_fh->fh_handle);
 	dp->dl_time = 0;
 	atomic_set(&dp->dl_count, 1);
-	INIT_WORK(&dp->dl_recall.cb_work, nfsd4_do_callback_rpc);
+	nfsd4_init_callback(&dp->dl_recall);
 	return dp;
 }
 
@@ -390,14 +383,6 @@ unhash_delegation(struct nfs4_delegation *dp)
  * SETCLIENTID state 
  */
 
-/* client_lock protects the client lru list and session hash table */
-static DEFINE_SPINLOCK(client_lock);
-
-/* Hash tables for nfs4_clientid state */
-#define CLIENT_HASH_BITS                 4
-#define CLIENT_HASH_SIZE                (1 << CLIENT_HASH_BITS)
-#define CLIENT_HASH_MASK                (CLIENT_HASH_SIZE - 1)
-
 static unsigned int clientid_hashval(u32 id)
 {
 	return id & CLIENT_HASH_MASK;
@@ -409,31 +394,6 @@ static unsigned int clientstr_hashval(const char *name)
 }
 
 /*
- * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
- * used in reboot/reset lease grace period processing
- *
- * conf_id_hashtbl[], and conf_str_hashtbl[] hold confirmed
- * setclientid_confirmed info. 
- *
- * unconf_str_hastbl[] and unconf_id_hashtbl[] hold unconfirmed 
- * setclientid info.
- *
- * client_lru holds client queue ordered by nfs4_client.cl_time
- * for lease renewal.
- *
- * close_lru holds (open) stateowner queue ordered by nfs4_stateowner.so_time
- * for last close replay.
- */
-static struct list_head	reclaim_str_hashtbl[CLIENT_HASH_SIZE];
-static int reclaim_str_hashtbl_size = 0;
-static struct list_head	conf_id_hashtbl[CLIENT_HASH_SIZE];
-static struct list_head	conf_str_hashtbl[CLIENT_HASH_SIZE];
-static struct list_head	unconf_str_hashtbl[CLIENT_HASH_SIZE];
-static struct list_head	unconf_id_hashtbl[CLIENT_HASH_SIZE];
-static struct list_head client_lru;
-static struct list_head close_lru;
-
-/*
  * We store the NONE, READ, WRITE, and BOTH bits separately in the
  * st_{access,deny}_bmap field of the stateid, in order to track not
  * only what share bits are currently in force, but also what
@@ -526,7 +486,8 @@ static int nfs4_access_to_omode(u32 access)
 	case NFS4_SHARE_ACCESS_BOTH:
 		return O_RDWR;
 	}
-	BUG();
+	WARN_ON_ONCE(1);
+	return O_RDONLY;
 }
 
 /* release all access and file references for a given stateid */
@@ -652,9 +613,6 @@ static void release_openowner(struct nfs4_openowner *oo)
 	nfs4_free_openowner(oo);
 }
 
-#define SESSION_HASH_SIZE	512
-static struct list_head sessionid_hashtbl[SESSION_HASH_SIZE];
-
 static inline int
 hash_sessionid(struct nfs4_sessionid *sessionid)
 {
@@ -906,18 +864,23 @@ static void __free_session(struct nfsd4_session *ses)
 static void free_session(struct kref *kref)
 {
 	struct nfsd4_session *ses;
+	struct nfsd_net *nn;
 
-	lockdep_assert_held(&client_lock);
 	ses = container_of(kref, struct nfsd4_session, se_ref);
+	nn = net_generic(ses->se_client->net, nfsd_net_id);
+
+	lockdep_assert_held(&nn->client_lock);
 	nfsd4_del_conns(ses);
 	__free_session(ses);
 }
 
 void nfsd4_put_session(struct nfsd4_session *ses)
 {
-	spin_lock(&client_lock);
+	struct nfsd_net *nn = net_generic(ses->se_client->net, nfsd_net_id);
+
+	spin_lock(&nn->client_lock);
 	nfsd4_put_session_locked(ses);
-	spin_unlock(&client_lock);
+	spin_unlock(&nn->client_lock);
 }
 
 static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan)
@@ -945,9 +908,10 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan)
 	return new;
 }
 
-static struct nfsd4_session *init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses)
+static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses)
 {
 	int idx;
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	new->se_client = clp;
 	gen_sessionid(new);
@@ -957,14 +921,15 @@ static struct nfsd4_session *init_session(struct svc_rqst *rqstp, struct nfsd4_s
 	new->se_cb_seq_nr = 1;
 	new->se_flags = cses->flags;
 	new->se_cb_prog = cses->callback_prog;
+	new->se_cb_sec = cses->cb_sec;
 	kref_init(&new->se_ref);
 	idx = hash_sessionid(&new->se_sessionid);
-	spin_lock(&client_lock);
-	list_add(&new->se_hash, &sessionid_hashtbl[idx]);
+	spin_lock(&nn->client_lock);
+	list_add(&new->se_hash, &nn->sessionid_hashtbl[idx]);
 	spin_lock(&clp->cl_lock);
 	list_add(&new->se_perclnt, &clp->cl_sessions);
 	spin_unlock(&clp->cl_lock);
-	spin_unlock(&client_lock);
+	spin_unlock(&nn->client_lock);
 
 	if (cses->flags & SESSION4_BACK_CHAN) {
 		struct sockaddr *sa = svc_addr(rqstp);
@@ -978,20 +943,20 @@ static struct nfsd4_session *init_session(struct svc_rqst *rqstp, struct nfsd4_s
 		rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa);
 		clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
 	}
-	return new;
 }
 
 /* caller must hold client_lock */
 static struct nfsd4_session *
-find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid)
+find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid, struct net *net)
 {
 	struct nfsd4_session *elem;
 	int idx;
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
 	dump_sessionid(__func__, sessionid);
 	idx = hash_sessionid(sessionid);
 	/* Search in the appropriate list */
-	list_for_each_entry(elem, &sessionid_hashtbl[idx], se_hash) {
+	list_for_each_entry(elem, &nn->sessionid_hashtbl[idx], se_hash) {
 		if (!memcmp(elem->se_sessionid.data, sessionid->data,
 			    NFS4_MAX_SESSIONID_LEN)) {
 			return elem;
@@ -1016,6 +981,8 @@ unhash_session(struct nfsd4_session *ses)
 static inline void
 renew_client_locked(struct nfs4_client *clp)
 {
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
 	if (is_client_expired(clp)) {
 		WARN_ON(1);
 		printk("%s: client (clientid %08x/%08x) already expired\n",
@@ -1028,16 +995,18 @@ renew_client_locked(struct nfs4_client *clp)
 	dprintk("renewing client (clientid %08x/%08x)\n", 
 			clp->cl_clientid.cl_boot, 
 			clp->cl_clientid.cl_id);
-	list_move_tail(&clp->cl_lru, &client_lru);
+	list_move_tail(&clp->cl_lru, &nn->client_lru);
 	clp->cl_time = get_seconds();
 }
 
 static inline void
 renew_client(struct nfs4_client *clp)
 {
-	spin_lock(&client_lock);
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+	spin_lock(&nn->client_lock);
 	renew_client_locked(clp);
-	spin_unlock(&client_lock);
+	spin_unlock(&nn->client_lock);
 }
 
 /* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */
@@ -1075,7 +1044,9 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
 static inline void
 free_client(struct nfs4_client *clp)
 {
-	lockdep_assert_held(&client_lock);
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+	lockdep_assert_held(&nn->client_lock);
 	while (!list_empty(&clp->cl_sessions)) {
 		struct nfsd4_session *ses;
 		ses = list_entry(clp->cl_sessions.next, struct nfsd4_session,
@@ -1092,15 +1063,16 @@ void
 release_session_client(struct nfsd4_session *session)
 {
 	struct nfs4_client *clp = session->se_client;
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
-	if (!atomic_dec_and_lock(&clp->cl_refcount, &client_lock))
+	if (!atomic_dec_and_lock(&clp->cl_refcount, &nn->client_lock))
 		return;
 	if (is_client_expired(clp)) {
 		free_client(clp);
 		session->se_client = NULL;
 	} else
 		renew_client_locked(clp);
-	spin_unlock(&client_lock);
+	spin_unlock(&nn->client_lock);
 }
 
 /* must be called under the client_lock */
@@ -1123,6 +1095,7 @@ destroy_client(struct nfs4_client *clp)
 	struct nfs4_openowner *oo;
 	struct nfs4_delegation *dp;
 	struct list_head reaplist;
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
 	INIT_LIST_HEAD(&reaplist);
 	spin_lock(&recall_lock);
@@ -1144,12 +1117,15 @@ destroy_client(struct nfs4_client *clp)
 	if (clp->cl_cb_conn.cb_xprt)
 		svc_xprt_put(clp->cl_cb_conn.cb_xprt);
 	list_del(&clp->cl_idhash);
-	list_del(&clp->cl_strhash);
-	spin_lock(&client_lock);
+	if (test_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags))
+		rb_erase(&clp->cl_namenode, &nn->conf_name_tree);
+	else
+		rb_erase(&clp->cl_namenode, &nn->unconf_name_tree);
+	spin_lock(&nn->client_lock);
 	unhash_client_locked(clp);
 	if (atomic_read(&clp->cl_refcount) == 0)
 		free_client(clp);
-	spin_unlock(&client_lock);
+	spin_unlock(&nn->client_lock);
 }
 
 static void expire_client(struct nfs4_client *clp)
@@ -1187,6 +1163,17 @@ static int copy_cred(struct svc_cred *target, struct svc_cred *source)
 	return 0;
 }
 
+static long long
+compare_blob(const struct xdr_netobj *o1, const struct xdr_netobj *o2)
+{
+	long long res;
+
+	res = o1->len - o2->len;
+	if (res)
+		return res;
+	return (long long)memcmp(o1->data, o2->data, o1->len);
+}
+
 static int same_name(const char *n1, const char *n2)
 {
 	return 0 == memcmp(n1, n2, HEXDIR_LEN);
@@ -1247,10 +1234,9 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
 	return 0 == strcmp(cr1->cr_principal, cr2->cr_principal);
 }
 
-static void gen_clid(struct nfs4_client *clp)
+static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn)
 {
 	static u32 current_clientid = 1;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
 	clp->cl_clientid.cl_boot = nn->boot_time;
 	clp->cl_clientid.cl_id = current_clientid++; 
@@ -1283,12 +1269,14 @@ static struct nfs4_stid *find_stateid_by_type(struct nfs4_client *cl, stateid_t
 	return NULL;
 }
 
-static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
+static struct nfs4_client *create_client(struct xdr_netobj name,
 		struct svc_rqst *rqstp, nfs4_verifier *verf)
 {
 	struct nfs4_client *clp;
 	struct sockaddr *sa = svc_addr(rqstp);
 	int ret;
+	struct net *net = SVC_NET(rqstp);
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
 	clp = alloc_client(name);
 	if (clp == NULL)
@@ -1297,23 +1285,21 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
 	INIT_LIST_HEAD(&clp->cl_sessions);
 	ret = copy_cred(&clp->cl_cred, &rqstp->rq_cred);
 	if (ret) {
-		spin_lock(&client_lock);
+		spin_lock(&nn->client_lock);
 		free_client(clp);
-		spin_unlock(&client_lock);
+		spin_unlock(&nn->client_lock);
 		return NULL;
 	}
 	idr_init(&clp->cl_stateids);
-	memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
 	atomic_set(&clp->cl_refcount, 0);
 	clp->cl_cb_state = NFSD4_CB_UNKNOWN;
 	INIT_LIST_HEAD(&clp->cl_idhash);
-	INIT_LIST_HEAD(&clp->cl_strhash);
 	INIT_LIST_HEAD(&clp->cl_openowners);
 	INIT_LIST_HEAD(&clp->cl_delegations);
 	INIT_LIST_HEAD(&clp->cl_lru);
 	INIT_LIST_HEAD(&clp->cl_callbacks);
 	spin_lock_init(&clp->cl_lock);
-	INIT_WORK(&clp->cl_cb_null.cb_work, nfsd4_do_callback_rpc);
+	nfsd4_init_callback(&clp->cl_cb_null);
 	clp->cl_time = get_seconds();
 	clear_bit(0, &clp->cl_cb_slot_busy);
 	rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table");
@@ -1321,17 +1307,60 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
 	rpc_copy_addr((struct sockaddr *) &clp->cl_addr, sa);
 	gen_confirm(clp);
 	clp->cl_cb_session = NULL;
+	clp->net = net;
 	return clp;
 }
 
 static void
-add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
+add_clp_to_name_tree(struct nfs4_client *new_clp, struct rb_root *root)
+{
+	struct rb_node **new = &(root->rb_node), *parent = NULL;
+	struct nfs4_client *clp;
+
+	while (*new) {
+		clp = rb_entry(*new, struct nfs4_client, cl_namenode);
+		parent = *new;
+
+		if (compare_blob(&clp->cl_name, &new_clp->cl_name) > 0)
+			new = &((*new)->rb_left);
+		else
+			new = &((*new)->rb_right);
+	}
+
+	rb_link_node(&new_clp->cl_namenode, parent, new);
+	rb_insert_color(&new_clp->cl_namenode, root);
+}
+
+static struct nfs4_client *
+find_clp_in_name_tree(struct xdr_netobj *name, struct rb_root *root)
+{
+	long long cmp;
+	struct rb_node *node = root->rb_node;
+	struct nfs4_client *clp;
+
+	while (node) {
+		clp = rb_entry(node, struct nfs4_client, cl_namenode);
+		cmp = compare_blob(&clp->cl_name, name);
+		if (cmp > 0)
+			node = node->rb_left;
+		else if (cmp < 0)
+			node = node->rb_right;
+		else
+			return clp;
+	}
+	return NULL;
+}
+
+static void
+add_to_unconfirmed(struct nfs4_client *clp)
 {
 	unsigned int idhashval;
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
-	list_add(&clp->cl_strhash, &unconf_str_hashtbl[strhashval]);
+	clear_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags);
+	add_clp_to_name_tree(clp, &nn->unconf_name_tree);
 	idhashval = clientid_hashval(clp->cl_clientid.cl_id);
-	list_add(&clp->cl_idhash, &unconf_id_hashtbl[idhashval]);
+	list_add(&clp->cl_idhash, &nn->unconf_id_hashtbl[idhashval]);
 	renew_client(clp);
 }
 
@@ -1339,22 +1368,23 @@ static void
 move_to_confirmed(struct nfs4_client *clp)
 {
 	unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id);
-	unsigned int strhashval;
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
 	dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp);
-	list_move(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
-	strhashval = clientstr_hashval(clp->cl_recdir);
-	list_move(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
+	list_move(&clp->cl_idhash, &nn->conf_id_hashtbl[idhashval]);
+	rb_erase(&clp->cl_namenode, &nn->unconf_name_tree);
+	add_clp_to_name_tree(clp, &nn->conf_name_tree);
+	set_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags);
 	renew_client(clp);
 }
 
 static struct nfs4_client *
-find_confirmed_client(clientid_t *clid, bool sessions)
+find_confirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
 {
 	struct nfs4_client *clp;
 	unsigned int idhashval = clientid_hashval(clid->cl_id);
 
-	list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
+	list_for_each_entry(clp, &nn->conf_id_hashtbl[idhashval], cl_idhash) {
 		if (same_clid(&clp->cl_clientid, clid)) {
 			if ((bool)clp->cl_minorversion != sessions)
 				return NULL;
@@ -1366,12 +1396,12 @@ find_confirmed_client(clientid_t *clid, bool sessions)
 }
 
 static struct nfs4_client *
-find_unconfirmed_client(clientid_t *clid, bool sessions)
+find_unconfirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
 {
 	struct nfs4_client *clp;
 	unsigned int idhashval = clientid_hashval(clid->cl_id);
 
-	list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
+	list_for_each_entry(clp, &nn->unconf_id_hashtbl[idhashval], cl_idhash) {
 		if (same_clid(&clp->cl_clientid, clid)) {
 			if ((bool)clp->cl_minorversion != sessions)
 				return NULL;
@@ -1387,27 +1417,15 @@ static bool clp_used_exchangeid(struct nfs4_client *clp)
 } 
 
 static struct nfs4_client *
-find_confirmed_client_by_str(const char *dname, unsigned int hashval)
+find_confirmed_client_by_name(struct xdr_netobj *name, struct nfsd_net *nn)
 {
-	struct nfs4_client *clp;
-
-	list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) {
-		if (same_name(clp->cl_recdir, dname))
-			return clp;
-	}
-	return NULL;
+	return find_clp_in_name_tree(name, &nn->conf_name_tree);
 }
 
 static struct nfs4_client *
-find_unconfirmed_client_by_str(const char *dname, unsigned int hashval)
+find_unconfirmed_client_by_name(struct xdr_netobj *name, struct nfsd_net *nn)
 {
-	struct nfs4_client *clp;
-
-	list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) {
-		if (same_name(clp->cl_recdir, dname))
-			return clp;
-	}
-	return NULL;
+	return find_clp_in_name_tree(name, &nn->unconf_name_tree);
 }
 
 static void
@@ -1428,7 +1446,7 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, struct svc_r
 	else
 		goto out_err;
 
-	conn->cb_addrlen = rpc_uaddr2sockaddr(&init_net, se->se_callback_addr_val,
+	conn->cb_addrlen = rpc_uaddr2sockaddr(clp->net, se->se_callback_addr_val,
 					    se->se_callback_addr_len,
 					    (struct sockaddr *)&conn->cb_addr,
 					    sizeof(conn->cb_addr));
@@ -1572,12 +1590,11 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
 {
 	struct nfs4_client *unconf, *conf, *new;
 	__be32 status;
-	unsigned int		strhashval;
-	char			dname[HEXDIR_LEN];
 	char			addr_str[INET6_ADDRSTRLEN];
 	nfs4_verifier		verf = exid->verifier;
 	struct sockaddr		*sa = svc_addr(rqstp);
 	bool	update = exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A;
+	struct nfsd_net		*nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	rpc_ntop(sa, addr_str, sizeof(addr_str));
 	dprintk("%s rqstp=%p exid=%p clname.len=%u clname.data=%p "
@@ -1592,24 +1609,16 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
 	switch (exid->spa_how) {
 	case SP4_NONE:
 		break;
+	default:				/* checked by xdr code */
+		WARN_ON_ONCE(1);
 	case SP4_SSV:
-		return nfserr_serverfault;
-	default:
-		BUG();				/* checked by xdr code */
 	case SP4_MACH_CRED:
 		return nfserr_serverfault;	/* no excuse :-/ */
 	}
 
-	status = nfs4_make_rec_clidname(dname, &exid->clname);
-
-	if (status)
-		return status;
-
-	strhashval = clientstr_hashval(dname);
-
 	/* Cases below refer to rfc 5661 section 18.35.4: */
 	nfs4_lock_state();
-	conf = find_confirmed_client_by_str(dname, strhashval);
+	conf = find_confirmed_client_by_name(&exid->clname, nn);
 	if (conf) {
 		bool creds_match = same_creds(&conf->cl_cred, &rqstp->rq_cred);
 		bool verfs_match = same_verf(&verf, &conf->cl_verifier);
@@ -1654,21 +1663,21 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
 		goto out;
 	}
 
-	unconf  = find_unconfirmed_client_by_str(dname, strhashval);
+	unconf  = find_unconfirmed_client_by_name(&exid->clname, nn);
 	if (unconf) /* case 4, possible retry or client restart */
 		expire_client(unconf);
 
 	/* case 1 (normal case) */
 out_new:
-	new = create_client(exid->clname, dname, rqstp, &verf);
+	new = create_client(exid->clname, rqstp, &verf);
 	if (new == NULL) {
 		status = nfserr_jukebox;
 		goto out;
 	}
 	new->cl_minorversion = 1;
 
-	gen_clid(new);
-	add_to_unconfirmed(new, strhashval);
+	gen_clid(new, nn);
+	add_to_unconfirmed(new);
 out_copy:
 	exid->clientid.cl_boot = new->cl_clientid.cl_boot;
 	exid->clientid.cl_id = new->cl_clientid.cl_id;
@@ -1761,6 +1770,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 	struct nfsd4_conn *conn;
 	struct nfsd4_clid_slot *cs_slot = NULL;
 	__be32 status = 0;
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	if (cr_ses->flags & ~SESSION4_FLAG_MASK_A)
 		return nfserr_inval;
@@ -1775,8 +1785,8 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 		goto out_free_session;
 
 	nfs4_lock_state();
-	unconf = find_unconfirmed_client(&cr_ses->clientid, true);
-	conf = find_confirmed_client(&cr_ses->clientid, true);
+	unconf = find_unconfirmed_client(&cr_ses->clientid, true, nn);
+	conf = find_confirmed_client(&cr_ses->clientid, true, nn);
 
 	if (conf) {
 		cs_slot = &conf->cl_cs_slot;
@@ -1789,7 +1799,6 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 			goto out_free_conn;
 		}
 	} else if (unconf) {
-		unsigned int hash;
 		struct nfs4_client *old;
 		if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) ||
 		    !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) {
@@ -1803,8 +1812,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 			status = nfserr_seq_misordered;
 			goto out_free_conn;
 		}
-		hash = clientstr_hashval(unconf->cl_recdir);
-		old = find_confirmed_client_by_str(unconf->cl_recdir, hash);
+		old = find_confirmed_client_by_name(&unconf->cl_name, nn);
 		if (old)
 			expire_client(old);
 		move_to_confirmed(unconf);
@@ -1865,24 +1873,40 @@ static __be32 nfsd4_map_bcts_dir(u32 *dir)
 	return nfserr_inval;
 }
 
+__be32 nfsd4_backchannel_ctl(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_backchannel_ctl *bc)
+{
+	struct nfsd4_session *session = cstate->session;
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+
+	spin_lock(&nn->client_lock);
+	session->se_cb_prog = bc->bc_cb_program;
+	session->se_cb_sec = bc->bc_cb_sec;
+	spin_unlock(&nn->client_lock);
+
+	nfsd4_probe_callback(session->se_client);
+
+	return nfs_ok;
+}
+
 __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
 		     struct nfsd4_compound_state *cstate,
 		     struct nfsd4_bind_conn_to_session *bcts)
 {
 	__be32 status;
 	struct nfsd4_conn *conn;
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	if (!nfsd4_last_compound_op(rqstp))
 		return nfserr_not_only_op;
-	spin_lock(&client_lock);
-	cstate->session = find_in_sessionid_hashtbl(&bcts->sessionid);
+	spin_lock(&nn->client_lock);
+	cstate->session = find_in_sessionid_hashtbl(&bcts->sessionid, SVC_NET(rqstp));
 	/* Sorta weird: we only need the refcnt'ing because new_conn acquires
 	 * client_lock iself: */
 	if (cstate->session) {
 		nfsd4_get_session(cstate->session);
 		atomic_inc(&cstate->session->se_client->cl_refcount);
 	}
-	spin_unlock(&client_lock);
+	spin_unlock(&nn->client_lock);
 	if (!cstate->session)
 		return nfserr_badsession;
 
@@ -1910,6 +1934,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
 {
 	struct nfsd4_session *ses;
 	__be32 status = nfserr_badsession;
+	struct nfsd_net *nn = net_generic(SVC_NET(r), nfsd_net_id);
 
 	/* Notes:
 	 * - The confirmed nfs4_client->cl_sessionid holds destroyed sessinid
@@ -1923,24 +1948,24 @@ nfsd4_destroy_session(struct svc_rqst *r,
 			return nfserr_not_only_op;
 	}
 	dump_sessionid(__func__, &sessionid->sessionid);
-	spin_lock(&client_lock);
-	ses = find_in_sessionid_hashtbl(&sessionid->sessionid);
+	spin_lock(&nn->client_lock);
+	ses = find_in_sessionid_hashtbl(&sessionid->sessionid, SVC_NET(r));
 	if (!ses) {
-		spin_unlock(&client_lock);
+		spin_unlock(&nn->client_lock);
 		goto out;
 	}
 
 	unhash_session(ses);
-	spin_unlock(&client_lock);
+	spin_unlock(&nn->client_lock);
 
 	nfs4_lock_state();
 	nfsd4_probe_callback_sync(ses->se_client);
 	nfs4_unlock_state();
 
-	spin_lock(&client_lock);
+	spin_lock(&nn->client_lock);
 	nfsd4_del_conns(ses);
 	nfsd4_put_session_locked(ses);
-	spin_unlock(&client_lock);
+	spin_unlock(&nn->client_lock);
 	status = nfs_ok;
 out:
 	dprintk("%s returns %d\n", __func__, ntohl(status));
@@ -2006,6 +2031,7 @@ nfsd4_sequence(struct svc_rqst *rqstp,
 	struct nfsd4_slot *slot;
 	struct nfsd4_conn *conn;
 	__be32 status;
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	if (resp->opcnt != 1)
 		return nfserr_sequence_pos;
@@ -2018,9 +2044,9 @@ nfsd4_sequence(struct svc_rqst *rqstp,
 	if (!conn)
 		return nfserr_jukebox;
 
-	spin_lock(&client_lock);
+	spin_lock(&nn->client_lock);
 	status = nfserr_badsession;
-	session = find_in_sessionid_hashtbl(&seq->sessionid);
+	session = find_in_sessionid_hashtbl(&seq->sessionid, SVC_NET(rqstp));
 	if (!session)
 		goto out;
 
@@ -2094,7 +2120,7 @@ out:
 		}
 	}
 	kfree(conn);
-	spin_unlock(&client_lock);
+	spin_unlock(&nn->client_lock);
 	dprintk("%s: return %d\n", __func__, ntohl(status));
 	return status;
 }
@@ -2104,10 +2130,11 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
 {
 	struct nfs4_client *conf, *unconf, *clp;
 	__be32 status = 0;
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	nfs4_lock_state();
-	unconf = find_unconfirmed_client(&dc->clientid, true);
-	conf = find_confirmed_client(&dc->clientid, true);
+	unconf = find_unconfirmed_client(&dc->clientid, true, nn);
+	conf = find_confirmed_client(&dc->clientid, true, nn);
 
 	if (conf) {
 		clp = conf;
@@ -2181,20 +2208,13 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 {
 	struct xdr_netobj 	clname = setclid->se_name;
 	nfs4_verifier		clverifier = setclid->se_verf;
-	unsigned int 		strhashval;
 	struct nfs4_client	*conf, *unconf, *new;
 	__be32 			status;
-	char                    dname[HEXDIR_LEN];
-	
-	status = nfs4_make_rec_clidname(dname, &clname);
-	if (status)
-		return status;
-
-	strhashval = clientstr_hashval(dname);
+	struct nfsd_net		*nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	/* Cases below refer to rfc 3530 section 14.2.33: */
 	nfs4_lock_state();
-	conf = find_confirmed_client_by_str(dname, strhashval);
+	conf = find_confirmed_client_by_name(&clname, nn);
 	if (conf) {
 		/* case 0: */
 		status = nfserr_clid_inuse;
@@ -2209,21 +2229,21 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 			goto out;
 		}
 	}
-	unconf = find_unconfirmed_client_by_str(dname, strhashval);
+	unconf = find_unconfirmed_client_by_name(&clname, nn);
 	if (unconf)
 		expire_client(unconf);
 	status = nfserr_jukebox;
-	new = create_client(clname, dname, rqstp, &clverifier);
+	new = create_client(clname, rqstp, &clverifier);
 	if (new == NULL)
 		goto out;
 	if (conf && same_verf(&conf->cl_verifier, &clverifier))
 		/* case 1: probable callback update */
 		copy_clid(new, conf);
 	else /* case 4 (new client) or cases 2, 3 (client reboot): */
-		gen_clid(new);
+		gen_clid(new, nn);
 	new->cl_minorversion = 0;
 	gen_callback(new, setclid, rqstp);
-	add_to_unconfirmed(new, strhashval);
+	add_to_unconfirmed(new);
 	setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot;
 	setclid->se_clientid.cl_id = new->cl_clientid.cl_id;
 	memcpy(setclid->se_confirm.data, new->cl_confirm.data, sizeof(setclid->se_confirm.data));
@@ -2243,14 +2263,14 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
 	nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
 	clientid_t * clid = &setclientid_confirm->sc_clientid;
 	__be32 status;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	struct nfsd_net	*nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	if (STALE_CLIENTID(clid, nn))
 		return nfserr_stale_clientid;
 	nfs4_lock_state();
 
-	conf = find_confirmed_client(clid, false);
-	unconf = find_unconfirmed_client(clid, false);
+	conf = find_confirmed_client(clid, false, nn);
+	unconf = find_unconfirmed_client(clid, false, nn);
 	/*
 	 * We try hard to give out unique clientid's, so if we get an
 	 * attempt to confirm the same clientid with a different cred,
@@ -2276,9 +2296,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
 		nfsd4_probe_callback(conf);
 		expire_client(unconf);
 	} else { /* case 3: normal case; new or rebooted client */
-		unsigned int hash = clientstr_hashval(unconf->cl_recdir);
-
-		conf = find_confirmed_client_by_str(unconf->cl_recdir, hash);
+		conf = find_confirmed_client_by_name(&unconf->cl_name, nn);
 		if (conf)
 			expire_client(conf);
 		move_to_confirmed(unconf);
@@ -2340,7 +2358,7 @@ nfsd4_init_slabs(void)
 	if (openowner_slab == NULL)
 		goto out_nomem;
 	lockowner_slab = kmem_cache_create("nfsd4_lockowners",
-			sizeof(struct nfs4_openowner), 0, 0, NULL);
+			sizeof(struct nfs4_lockowner), 0, 0, NULL);
 	if (lockowner_slab == NULL)
 		goto out_nomem;
 	file_slab = kmem_cache_create("nfsd4_files",
@@ -2404,7 +2422,9 @@ static inline void *alloc_stateowner(struct kmem_cache *slab, struct xdr_netobj
 
 static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval)
 {
-	list_add(&oo->oo_owner.so_strhash, &ownerstr_hashtbl[strhashval]);
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+	list_add(&oo->oo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]);
 	list_add(&oo->oo_perclient, &clp->cl_openowners);
 }
 
@@ -2444,11 +2464,13 @@ static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
 }
 
 static void
-move_to_close_lru(struct nfs4_openowner *oo)
+move_to_close_lru(struct nfs4_openowner *oo, struct net *net)
 {
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
 	dprintk("NFSD: move_to_close_lru nfs4_openowner %p\n", oo);
 
-	list_move_tail(&oo->oo_close_lru, &close_lru);
+	list_move_tail(&oo->oo_close_lru, &nn->close_lru);
 	oo->oo_time = get_seconds();
 }
 
@@ -2462,13 +2484,14 @@ same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner,
 }
 
 static struct nfs4_openowner *
-find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, bool sessions)
+find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open,
+			bool sessions, struct nfsd_net *nn)
 {
 	struct nfs4_stateowner *so;
 	struct nfs4_openowner *oo;
 	struct nfs4_client *clp;
 
-	list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) {
+	list_for_each_entry(so, &nn->ownerstr_hashtbl[hashval], so_strhash) {
 		if (!so->so_is_open_owner)
 			continue;
 		if (same_owner_str(so, &open->op_owner, &open->op_clientid)) {
@@ -2555,9 +2578,14 @@ static void nfsd_break_deleg_cb(struct file_lock *fl)
 	struct nfs4_file *fp = (struct nfs4_file *)fl->fl_owner;
 	struct nfs4_delegation *dp;
 
-	BUG_ON(!fp);
-	/* We assume break_lease is only called once per lease: */
-	BUG_ON(fp->fi_had_conflict);
+	if (!fp) {
+		WARN(1, "(%p)->fl_owner NULL\n", fl);
+		return;
+	}
+	if (fp->fi_had_conflict) {
+		WARN(1, "duplicate break on %p\n", fp);
+		return;
+	}
 	/*
 	 * We don't want the locks code to timeout the lease for us;
 	 * we'll remove it ourself if a delegation isn't returned
@@ -2599,14 +2627,13 @@ static __be32 nfsd4_check_seqid(struct nfsd4_compound_state *cstate, struct nfs4
 
 __be32
 nfsd4_process_open1(struct nfsd4_compound_state *cstate,
-		    struct nfsd4_open *open)
+		    struct nfsd4_open *open, struct nfsd_net *nn)
 {
 	clientid_t *clientid = &open->op_clientid;
 	struct nfs4_client *clp = NULL;
 	unsigned int strhashval;
 	struct nfs4_openowner *oo = NULL;
 	__be32 status;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
 	if (STALE_CLIENTID(&open->op_clientid, nn))
 		return nfserr_stale_clientid;
@@ -2619,10 +2646,11 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate,
 		return nfserr_jukebox;
 
 	strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner);
-	oo = find_openstateowner_str(strhashval, open, cstate->minorversion);
+	oo = find_openstateowner_str(strhashval, open, cstate->minorversion, nn);
 	open->op_openowner = oo;
 	if (!oo) {
-		clp = find_confirmed_client(clientid, cstate->minorversion);
+		clp = find_confirmed_client(clientid, cstate->minorversion,
+					    nn);
 		if (clp == NULL)
 			return nfserr_expired;
 		goto new_owner;
@@ -2891,7 +2919,7 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
 			open->op_why_no_deleg = WND4_CANCELLED;
 			break;
 		case NFS4_SHARE_WANT_NO_DELEG:
-			BUG();	/* not supposed to get here */
+			WARN_ON_ONCE(1);
 		}
 	}
 }
@@ -3110,7 +3138,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 {
 	struct nfs4_client *clp;
 	__be32 status;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	nfs4_lock_state();
 	dprintk("process_renew(%08x/%08x): starting\n", 
@@ -3118,7 +3146,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	status = nfserr_stale_clientid;
 	if (STALE_CLIENTID(clid, nn))
 		goto out;
-	clp = find_confirmed_client(clid, cstate->minorversion);
+	clp = find_confirmed_client(clid, cstate->minorversion, nn);
 	status = nfserr_expired;
 	if (clp == NULL) {
 		/* We assume the client took too long to RENEW. */
@@ -3136,44 +3164,42 @@ out:
 }
 
 static void
-nfsd4_end_grace(struct net *net)
+nfsd4_end_grace(struct nfsd_net *nn)
 {
-	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
-
 	/* do nothing if grace period already ended */
 	if (nn->grace_ended)
 		return;
 
 	dprintk("NFSD: end of grace period\n");
 	nn->grace_ended = true;
-	nfsd4_record_grace_done(net, nn->boot_time);
+	nfsd4_record_grace_done(nn, nn->boot_time);
 	locks_end_grace(&nn->nfsd4_manager);
 	/*
 	 * Now that every NFSv4 client has had the chance to recover and
 	 * to see the (possibly new, possibly shorter) lease time, we
 	 * can safely set the next grace time to the current lease time:
 	 */
-	nfsd4_grace = nfsd4_lease;
+	nn->nfsd4_grace = nn->nfsd4_lease;
 }
 
 static time_t
-nfs4_laundromat(void)
+nfs4_laundromat(struct nfsd_net *nn)
 {
 	struct nfs4_client *clp;
 	struct nfs4_openowner *oo;
 	struct nfs4_delegation *dp;
 	struct list_head *pos, *next, reaplist;
-	time_t cutoff = get_seconds() - nfsd4_lease;
-	time_t t, clientid_val = nfsd4_lease;
-	time_t u, test_val = nfsd4_lease;
+	time_t cutoff = get_seconds() - nn->nfsd4_lease;
+	time_t t, clientid_val = nn->nfsd4_lease;
+	time_t u, test_val = nn->nfsd4_lease;
 
 	nfs4_lock_state();
 
 	dprintk("NFSD: laundromat service - starting\n");
-	nfsd4_end_grace(&init_net);
+	nfsd4_end_grace(nn);
 	INIT_LIST_HEAD(&reaplist);
-	spin_lock(&client_lock);
-	list_for_each_safe(pos, next, &client_lru) {
+	spin_lock(&nn->client_lock);
+	list_for_each_safe(pos, next, &nn->client_lru) {
 		clp = list_entry(pos, struct nfs4_client, cl_lru);
 		if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
 			t = clp->cl_time - cutoff;
@@ -3189,7 +3215,7 @@ nfs4_laundromat(void)
 		unhash_client_locked(clp);
 		list_add(&clp->cl_lru, &reaplist);
 	}
-	spin_unlock(&client_lock);
+	spin_unlock(&nn->client_lock);
 	list_for_each_safe(pos, next, &reaplist) {
 		clp = list_entry(pos, struct nfs4_client, cl_lru);
 		dprintk("NFSD: purging unused client (clientid %08x)\n",
@@ -3199,6 +3225,8 @@ nfs4_laundromat(void)
 	spin_lock(&recall_lock);
 	list_for_each_safe(pos, next, &del_recall_lru) {
 		dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
+		if (net_generic(dp->dl_stid.sc_client->net, nfsd_net_id) != nn)
+			continue;
 		if (time_after((unsigned long)dp->dl_time, (unsigned long)cutoff)) {
 			u = dp->dl_time - cutoff;
 			if (test_val > u)
@@ -3212,8 +3240,8 @@ nfs4_laundromat(void)
 		dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
 		unhash_delegation(dp);
 	}
-	test_val = nfsd4_lease;
-	list_for_each_safe(pos, next, &close_lru) {
+	test_val = nn->nfsd4_lease;
+	list_for_each_safe(pos, next, &nn->close_lru) {
 		oo = container_of(pos, struct nfs4_openowner, oo_close_lru);
 		if (time_after((unsigned long)oo->oo_time, (unsigned long)cutoff)) {
 			u = oo->oo_time - cutoff;
@@ -3231,16 +3259,19 @@ nfs4_laundromat(void)
 
 static struct workqueue_struct *laundry_wq;
 static void laundromat_main(struct work_struct *);
-static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main);
 
 static void
-laundromat_main(struct work_struct *not_used)
+laundromat_main(struct work_struct *laundry)
 {
 	time_t t;
+	struct delayed_work *dwork = container_of(laundry, struct delayed_work,
+						  work);
+	struct nfsd_net *nn = container_of(dwork, struct nfsd_net,
+					   laundromat_work);
 
-	t = nfs4_laundromat();
+	t = nfs4_laundromat(nn);
 	dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t);
-	queue_delayed_work(laundry_wq, &laundromat_work, t*HZ);
+	queue_delayed_work(laundry_wq, &nn->laundromat_work, t*HZ);
 }
 
 static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_ol_stateid *stp)
@@ -3385,16 +3416,17 @@ static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
 	return nfs_ok;
 }
 
-static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s, bool sessions)
+static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask,
+				   struct nfs4_stid **s, bool sessions,
+				   struct nfsd_net *nn)
 {
 	struct nfs4_client *cl;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
 	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
 		return nfserr_bad_stateid;
 	if (STALE_STATEID(stateid, nn))
 		return nfserr_stale_stateid;
-	cl = find_confirmed_client(&stateid->si_opaque.so_clid, sessions);
+	cl = find_confirmed_client(&stateid->si_opaque.so_clid, sessions, nn);
 	if (!cl)
 		return nfserr_expired;
 	*s = find_stateid_by_type(cl, stateid, typemask);
@@ -3416,6 +3448,7 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
 	struct nfs4_delegation *dp = NULL;
 	struct svc_fh *current_fh = &cstate->current_fh;
 	struct inode *ino = current_fh->fh_dentry->d_inode;
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 	__be32 status;
 
 	if (filpp)
@@ -3427,7 +3460,8 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
 	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
 		return check_special_stateids(net, current_fh, stateid, flags);
 
-	status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s, cstate->minorversion);
+	status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID,
+				      &s, cstate->minorversion, nn);
 	if (status)
 		return status;
 	status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate));
@@ -3441,7 +3475,11 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
 			goto out;
 		if (filpp) {
 			*filpp = dp->dl_file->fi_deleg_file;
-			BUG_ON(!*filpp);
+			if (!*filpp) {
+				WARN_ON_ONCE(1);
+				status = nfserr_serverfault;
+				goto out;
+			}
 		}
 		break;
 	case NFS4_OPEN_STID:
@@ -3568,7 +3606,8 @@ static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_
 static __be32
 nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
 			 stateid_t *stateid, char typemask,
-			 struct nfs4_ol_stateid **stpp)
+			 struct nfs4_ol_stateid **stpp,
+			 struct nfsd_net *nn)
 {
 	__be32 status;
 	struct nfs4_stid *s;
@@ -3577,7 +3616,8 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
 		seqid, STATEID_VAL(stateid));
 
 	*stpp = NULL;
-	status = nfsd4_lookup_stateid(stateid, typemask, &s, cstate->minorversion);
+	status = nfsd4_lookup_stateid(stateid, typemask, &s,
+				      cstate->minorversion, nn);
 	if (status)
 		return status;
 	*stpp = openlockstateid(s);
@@ -3586,13 +3626,14 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
 	return nfs4_seqid_op_checks(cstate, stateid, seqid, *stpp);
 }
 
-static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid, stateid_t *stateid, struct nfs4_ol_stateid **stpp)
+static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
+						 stateid_t *stateid, struct nfs4_ol_stateid **stpp, struct nfsd_net *nn)
 {
 	__be32 status;
 	struct nfs4_openowner *oo;
 
 	status = nfs4_preprocess_seqid_op(cstate, seqid, stateid,
-						NFS4_OPEN_STID, stpp);
+						NFS4_OPEN_STID, stpp, nn);
 	if (status)
 		return status;
 	oo = openowner((*stpp)->st_stateowner);
@@ -3608,6 +3649,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	__be32 status;
 	struct nfs4_openowner *oo;
 	struct nfs4_ol_stateid *stp;
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	dprintk("NFSD: nfsd4_open_confirm on file %.*s\n",
 			(int)cstate->current_fh.fh_dentry->d_name.len,
@@ -3621,7 +3663,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
 	status = nfs4_preprocess_seqid_op(cstate,
 					oc->oc_seqid, &oc->oc_req_stateid,
-					NFS4_OPEN_STID, &stp);
+					NFS4_OPEN_STID, &stp, nn);
 	if (status)
 		goto out;
 	oo = openowner(stp->st_stateowner);
@@ -3664,7 +3706,7 @@ static inline void nfs4_stateid_downgrade(struct nfs4_ol_stateid *stp, u32 to_ac
 	case NFS4_SHARE_ACCESS_BOTH:
 		break;
 	default:
-		BUG();
+		WARN_ON_ONCE(1);
 	}
 }
 
@@ -3685,6 +3727,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
 {
 	__be32 status;
 	struct nfs4_ol_stateid *stp;
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n", 
 			(int)cstate->current_fh.fh_dentry->d_name.len,
@@ -3697,7 +3740,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
 
 	nfs4_lock_state();
 	status = nfs4_preprocess_confirmed_seqid_op(cstate, od->od_seqid,
-					&od->od_stateid, &stp);
+					&od->od_stateid, &stp, nn);
 	if (status)
 		goto out; 
 	status = nfserr_inval;
@@ -3760,6 +3803,8 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	__be32 status;
 	struct nfs4_openowner *oo;
 	struct nfs4_ol_stateid *stp;
+	struct net *net = SVC_NET(rqstp);
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
 	dprintk("NFSD: nfsd4_close on file %.*s\n", 
 			(int)cstate->current_fh.fh_dentry->d_name.len,
@@ -3769,7 +3814,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	status = nfs4_preprocess_seqid_op(cstate, close->cl_seqid,
 					&close->cl_stateid,
 					NFS4_OPEN_STID|NFS4_CLOSED_STID,
-					&stp);
+					&stp, nn);
 	if (status)
 		goto out; 
 	oo = openowner(stp->st_stateowner);
@@ -3791,7 +3836,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 			 * little while to handle CLOSE replay.
 			 */
 			if (list_empty(&oo->oo_owner.so_stateids))
-				move_to_close_lru(oo);
+				move_to_close_lru(oo, SVC_NET(rqstp));
 		}
 	}
 out:
@@ -3807,15 +3852,15 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	struct nfs4_delegation *dp;
 	stateid_t *stateid = &dr->dr_stateid;
 	struct nfs4_stid *s;
-	struct inode *inode;
 	__be32 status;
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
 		return status;
-	inode = cstate->current_fh.fh_dentry->d_inode;
 
 	nfs4_lock_state();
-	status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s, cstate->minorversion);
+	status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s,
+				      cstate->minorversion, nn);
 	if (status)
 		goto out;
 	dp = delegstateid(s);
@@ -3833,8 +3878,6 @@ out:
 
 #define LOFF_OVERFLOW(start, len)      ((u64)(len) > ~(u64)(start))
 
-#define LOCKOWNER_INO_HASH_BITS 8
-#define LOCKOWNER_INO_HASH_SIZE (1 << LOCKOWNER_INO_HASH_BITS)
 #define LOCKOWNER_INO_HASH_MASK (LOCKOWNER_INO_HASH_SIZE - 1)
 
 static inline u64
@@ -3852,7 +3895,7 @@ last_byte_offset(u64 start, u64 len)
 {
 	u64 end;
 
-	BUG_ON(!len);
+	WARN_ON_ONCE(!len);
 	end = start + len;
 	return end > start ? end - 1: NFS4_MAX_UINT64;
 }
@@ -3864,8 +3907,6 @@ static unsigned int lockowner_ino_hashval(struct inode *inode, u32 cl_id, struct
 		& LOCKOWNER_INO_HASH_MASK;
 }
 
-static struct list_head lockowner_ino_hashtbl[LOCKOWNER_INO_HASH_SIZE];
-
 /*
  * TODO: Linux file offsets are _signed_ 64-bit quantities, which means that
  * we can't properly handle lock requests that go beyond the (2^63 - 1)-th
@@ -3931,12 +3972,12 @@ static bool same_lockowner_ino(struct nfs4_lockowner *lo, struct inode *inode, c
 
 static struct nfs4_lockowner *
 find_lockowner_str(struct inode *inode, clientid_t *clid,
-		struct xdr_netobj *owner)
+		   struct xdr_netobj *owner, struct nfsd_net *nn)
 {
 	unsigned int hashval = lockowner_ino_hashval(inode, clid->cl_id, owner);
 	struct nfs4_lockowner *lo;
 
-	list_for_each_entry(lo, &lockowner_ino_hashtbl[hashval], lo_owner_ino_hash) {
+	list_for_each_entry(lo, &nn->lockowner_ino_hashtbl[hashval], lo_owner_ino_hash) {
 		if (same_lockowner_ino(lo, inode, clid, owner))
 			return lo;
 	}
@@ -3948,9 +3989,10 @@ static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, s
 	struct inode *inode = open_stp->st_file->fi_inode;
 	unsigned int inohash = lockowner_ino_hashval(inode,
 			clp->cl_clientid.cl_id, &lo->lo_owner.so_owner);
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
-	list_add(&lo->lo_owner.so_strhash, &ownerstr_hashtbl[strhashval]);
-	list_add(&lo->lo_owner_ino_hash, &lockowner_ino_hashtbl[inohash]);
+	list_add(&lo->lo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]);
+	list_add(&lo->lo_owner_ino_hash, &nn->lockowner_ino_hashtbl[inohash]);
 	list_add(&lo->lo_perstateid, &open_stp->st_lockowners);
 }
 
@@ -4024,8 +4066,10 @@ static __be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, s
 	struct nfs4_client *cl = oo->oo_owner.so_client;
 	struct nfs4_lockowner *lo;
 	unsigned int strhashval;
+	struct nfsd_net *nn = net_generic(cl->net, nfsd_net_id);
 
-	lo = find_lockowner_str(fi->fi_inode, &cl->cl_clientid, &lock->v.new.owner);
+	lo = find_lockowner_str(fi->fi_inode, &cl->cl_clientid,
+				&lock->v.new.owner, nn);
 	if (lo) {
 		if (!cstate->minorversion)
 			return nfserr_bad_seqid;
@@ -4065,7 +4109,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	bool new_state = false;
 	int lkflg;
 	int err;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	struct net *net = SVC_NET(rqstp);
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
 	dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
 		(long long) lock->lk_offset,
@@ -4099,7 +4144,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		status = nfs4_preprocess_confirmed_seqid_op(cstate,
 				        lock->lk_new_open_seqid,
 		                        &lock->lk_new_open_stateid,
-					&open_stp);
+					&open_stp, nn);
 		if (status)
 			goto out;
 		open_sop = openowner(open_stp->st_stateowner);
@@ -4113,7 +4158,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		status = nfs4_preprocess_seqid_op(cstate,
 				       lock->lk_old_lock_seqid,
 				       &lock->lk_old_lock_stateid,
-				       NFS4_LOCK_STID, &lock_stp);
+				       NFS4_LOCK_STID, &lock_stp, nn);
 	if (status)
 		goto out;
 	lock_sop = lockowner(lock_stp->st_stateowner);
@@ -4124,10 +4169,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		goto out;
 
 	status = nfserr_grace;
-	if (locks_in_grace(SVC_NET(rqstp)) && !lock->lk_reclaim)
+	if (locks_in_grace(net) && !lock->lk_reclaim)
 		goto out;
 	status = nfserr_no_grace;
-	if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim)
+	if (!locks_in_grace(net) && lock->lk_reclaim)
 		goto out;
 
 	file_lock = locks_alloc_lock();
@@ -4238,7 +4283,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	struct file_lock *file_lock = NULL;
 	struct nfs4_lockowner *lo;
 	__be32 status;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	if (locks_in_grace(SVC_NET(rqstp)))
 		return nfserr_grace;
@@ -4278,7 +4323,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		goto out;
 	}
 
-	lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner);
+	lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner, nn);
 	if (lo)
 		file_lock->fl_owner = (fl_owner_t)lo;
 	file_lock->fl_pid = current->tgid;
@@ -4313,7 +4358,8 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	struct file_lock *file_lock = NULL;
 	__be32 status;
 	int err;
-						        
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+
 	dprintk("NFSD: nfsd4_locku: start=%Ld length=%Ld\n",
 		(long long) locku->lu_offset,
 		(long long) locku->lu_length);
@@ -4324,7 +4370,8 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	nfs4_lock_state();
 									        
 	status = nfs4_preprocess_seqid_op(cstate, locku->lu_seqid,
-					&locku->lu_stateid, NFS4_LOCK_STID, &stp);
+					&locku->lu_stateid, NFS4_LOCK_STID,
+					&stp, nn);
 	if (status)
 		goto out;
 	filp = find_any_file(stp->st_file);
@@ -4414,7 +4461,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
 	struct list_head matches;
 	unsigned int hashval = ownerstr_hashval(clid->cl_id, owner);
 	__be32 status;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
 		clid->cl_boot, clid->cl_id);
@@ -4430,7 +4477,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
 	status = nfserr_locks_held;
 	INIT_LIST_HEAD(&matches);
 
-	list_for_each_entry(sop, &ownerstr_hashtbl[hashval], so_strhash) {
+	list_for_each_entry(sop, &nn->ownerstr_hashtbl[hashval], so_strhash) {
 		if (sop->so_is_open_owner)
 			continue;
 		if (!same_owner_str(sop, owner, clid))
@@ -4466,73 +4513,74 @@ alloc_reclaim(void)
 	return kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL);
 }
 
-int
-nfs4_has_reclaimed_state(const char *name, bool use_exchange_id)
+bool
+nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn)
 {
-	unsigned int strhashval = clientstr_hashval(name);
-	struct nfs4_client *clp;
+	struct nfs4_client_reclaim *crp;
 
-	clp = find_confirmed_client_by_str(name, strhashval);
-	if (!clp)
-		return 0;
-	return test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
+	crp = nfsd4_find_reclaim_client(name, nn);
+	return (crp && crp->cr_clp);
 }
 
 /*
  * failure => all reset bets are off, nfserr_no_grace...
  */
-int
-nfs4_client_to_reclaim(const char *name)
+struct nfs4_client_reclaim *
+nfs4_client_to_reclaim(const char *name, struct nfsd_net *nn)
 {
 	unsigned int strhashval;
-	struct nfs4_client_reclaim *crp = NULL;
+	struct nfs4_client_reclaim *crp;
 
 	dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", HEXDIR_LEN, name);
 	crp = alloc_reclaim();
-	if (!crp)
-		return 0;
-	strhashval = clientstr_hashval(name);
-	INIT_LIST_HEAD(&crp->cr_strhash);
-	list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]);
-	memcpy(crp->cr_recdir, name, HEXDIR_LEN);
-	reclaim_str_hashtbl_size++;
-	return 1;
+	if (crp) {
+		strhashval = clientstr_hashval(name);
+		INIT_LIST_HEAD(&crp->cr_strhash);
+		list_add(&crp->cr_strhash, &nn->reclaim_str_hashtbl[strhashval]);
+		memcpy(crp->cr_recdir, name, HEXDIR_LEN);
+		crp->cr_clp = NULL;
+		nn->reclaim_str_hashtbl_size++;
+	}
+	return crp;
 }
 
 void
-nfs4_release_reclaim(void)
+nfs4_remove_reclaim_record(struct nfs4_client_reclaim *crp, struct nfsd_net *nn)
+{
+	list_del(&crp->cr_strhash);
+	kfree(crp);
+	nn->reclaim_str_hashtbl_size--;
+}
+
+void
+nfs4_release_reclaim(struct nfsd_net *nn)
 {
 	struct nfs4_client_reclaim *crp = NULL;
 	int i;
 
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
-		while (!list_empty(&reclaim_str_hashtbl[i])) {
-			crp = list_entry(reclaim_str_hashtbl[i].next,
+		while (!list_empty(&nn->reclaim_str_hashtbl[i])) {
+			crp = list_entry(nn->reclaim_str_hashtbl[i].next,
 			                struct nfs4_client_reclaim, cr_strhash);
-			list_del(&crp->cr_strhash);
-			kfree(crp);
-			reclaim_str_hashtbl_size--;
+			nfs4_remove_reclaim_record(crp, nn);
 		}
 	}
-	BUG_ON(reclaim_str_hashtbl_size);
+	WARN_ON_ONCE(nn->reclaim_str_hashtbl_size);
 }
 
 /*
  * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
 struct nfs4_client_reclaim *
-nfsd4_find_reclaim_client(struct nfs4_client *clp)
+nfsd4_find_reclaim_client(const char *recdir, struct nfsd_net *nn)
 {
 	unsigned int strhashval;
 	struct nfs4_client_reclaim *crp = NULL;
 
-	dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n",
-		            clp->cl_name.len, clp->cl_name.data,
-			    clp->cl_recdir);
+	dprintk("NFSD: nfs4_find_reclaim_client for recdir %s\n", recdir);
 
-	/* find clp->cl_name in reclaim_str_hashtbl */
-	strhashval = clientstr_hashval(clp->cl_recdir);
-	list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) {
-		if (same_name(crp->cr_recdir, clp->cl_recdir)) {
+	strhashval = clientstr_hashval(recdir);
+	list_for_each_entry(crp, &nn->reclaim_str_hashtbl[strhashval], cr_strhash) {
+		if (same_name(crp->cr_recdir, recdir)) {
 			return crp;
 		}
 	}
@@ -4543,12 +4591,12 @@ nfsd4_find_reclaim_client(struct nfs4_client *clp)
 * Called from OPEN. Look for clientid in reclaim list.
 */
 __be32
-nfs4_check_open_reclaim(clientid_t *clid, bool sessions)
+nfs4_check_open_reclaim(clientid_t *clid, bool sessions, struct nfsd_net *nn)
 {
 	struct nfs4_client *clp;
 
 	/* find clientid in conf_id_hashtbl */
-	clp = find_confirmed_client(clid, sessions);
+	clp = find_confirmed_client(clid, sessions, nn);
 	if (clp == NULL)
 		return nfserr_reclaim_bad;
 
@@ -4561,9 +4609,10 @@ void nfsd_forget_clients(u64 num)
 {
 	struct nfs4_client *clp, *next;
 	int count = 0;
+	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, nfsd_net_id);
 
 	nfs4_lock_state();
-	list_for_each_entry_safe(clp, next, &client_lru, cl_lru) {
+	list_for_each_entry_safe(clp, next, &nn->client_lru, cl_lru) {
 		expire_client(clp);
 		if (++count == num)
 			break;
@@ -4584,13 +4633,14 @@ static void release_openowner_sop(struct nfs4_stateowner *sop)
 }
 
 static int nfsd_release_n_owners(u64 num, bool is_open_owner,
-				void (*release_sop)(struct nfs4_stateowner *))
+				void (*release_sop)(struct nfs4_stateowner *),
+				struct nfsd_net *nn)
 {
 	int i, count = 0;
 	struct nfs4_stateowner *sop, *next;
 
 	for (i = 0; i < OWNER_HASH_SIZE; i++) {
-		list_for_each_entry_safe(sop, next, &ownerstr_hashtbl[i], so_strhash) {
+		list_for_each_entry_safe(sop, next, &nn->ownerstr_hashtbl[i], so_strhash) {
 			if (sop->so_is_open_owner != is_open_owner)
 				continue;
 			release_sop(sop);
@@ -4604,9 +4654,10 @@ static int nfsd_release_n_owners(u64 num, bool is_open_owner,
 void nfsd_forget_locks(u64 num)
 {
 	int count;
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
 	nfs4_lock_state();
-	count = nfsd_release_n_owners(num, false, release_lockowner_sop);
+	count = nfsd_release_n_owners(num, false, release_lockowner_sop, nn);
 	nfs4_unlock_state();
 
 	printk(KERN_INFO "NFSD: Forgot %d locks", count);
@@ -4615,9 +4666,10 @@ void nfsd_forget_locks(u64 num)
 void nfsd_forget_openowners(u64 num)
 {
 	int count;
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
 	nfs4_lock_state();
-	count = nfsd_release_n_owners(num, true, release_openowner_sop);
+	count = nfsd_release_n_owners(num, true, release_openowner_sop, nn);
 	nfs4_unlock_state();
 
 	printk(KERN_INFO "NFSD: Forgot %d open owners", count);
@@ -4686,27 +4738,10 @@ nfs4_state_init(void)
 {
 	int i;
 
-	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
-		INIT_LIST_HEAD(&conf_id_hashtbl[i]);
-		INIT_LIST_HEAD(&conf_str_hashtbl[i]);
-		INIT_LIST_HEAD(&unconf_str_hashtbl[i]);
-		INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
-		INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
-	}
-	for (i = 0; i < SESSION_HASH_SIZE; i++)
-		INIT_LIST_HEAD(&sessionid_hashtbl[i]);
 	for (i = 0; i < FILE_HASH_SIZE; i++) {
 		INIT_LIST_HEAD(&file_hashtbl[i]);
 	}
-	for (i = 0; i < OWNER_HASH_SIZE; i++) {
-		INIT_LIST_HEAD(&ownerstr_hashtbl[i]);
-	}
-	for (i = 0; i < LOCKOWNER_INO_HASH_SIZE; i++)
-		INIT_LIST_HEAD(&lockowner_ino_hashtbl[i]);
-	INIT_LIST_HEAD(&close_lru);
-	INIT_LIST_HEAD(&client_lru);
 	INIT_LIST_HEAD(&del_recall_lru);
-	reclaim_str_hashtbl_size = 0;
 }
 
 /*
@@ -4730,12 +4765,100 @@ set_max_delegations(void)
 	max_delegations = nr_free_buffer_pages() >> (20 - 2 - PAGE_SHIFT);
 }
 
-/* initialization to perform when the nfsd service is started: */
+static int nfs4_state_create_net(struct net *net)
+{
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+	int i;
+
+	nn->conf_id_hashtbl = kmalloc(sizeof(struct list_head) *
+			CLIENT_HASH_SIZE, GFP_KERNEL);
+	if (!nn->conf_id_hashtbl)
+		goto err;
+	nn->unconf_id_hashtbl = kmalloc(sizeof(struct list_head) *
+			CLIENT_HASH_SIZE, GFP_KERNEL);
+	if (!nn->unconf_id_hashtbl)
+		goto err_unconf_id;
+	nn->ownerstr_hashtbl = kmalloc(sizeof(struct list_head) *
+			OWNER_HASH_SIZE, GFP_KERNEL);
+	if (!nn->ownerstr_hashtbl)
+		goto err_ownerstr;
+	nn->lockowner_ino_hashtbl = kmalloc(sizeof(struct list_head) *
+			LOCKOWNER_INO_HASH_SIZE, GFP_KERNEL);
+	if (!nn->lockowner_ino_hashtbl)
+		goto err_lockowner_ino;
+	nn->sessionid_hashtbl = kmalloc(sizeof(struct list_head) *
+			SESSION_HASH_SIZE, GFP_KERNEL);
+	if (!nn->sessionid_hashtbl)
+		goto err_sessionid;
+
+	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
+		INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]);
+		INIT_LIST_HEAD(&nn->unconf_id_hashtbl[i]);
+	}
+	for (i = 0; i < OWNER_HASH_SIZE; i++)
+		INIT_LIST_HEAD(&nn->ownerstr_hashtbl[i]);
+	for (i = 0; i < LOCKOWNER_INO_HASH_SIZE; i++)
+		INIT_LIST_HEAD(&nn->lockowner_ino_hashtbl[i]);
+	for (i = 0; i < SESSION_HASH_SIZE; i++)
+		INIT_LIST_HEAD(&nn->sessionid_hashtbl[i]);
+	nn->conf_name_tree = RB_ROOT;
+	nn->unconf_name_tree = RB_ROOT;
+	INIT_LIST_HEAD(&nn->client_lru);
+	INIT_LIST_HEAD(&nn->close_lru);
+	spin_lock_init(&nn->client_lock);
+
+	INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main);
+	get_net(net);
+
+	return 0;
+
+err_sessionid:
+	kfree(nn->lockowner_ino_hashtbl);
+err_lockowner_ino:
+	kfree(nn->ownerstr_hashtbl);
+err_ownerstr:
+	kfree(nn->unconf_id_hashtbl);
+err_unconf_id:
+	kfree(nn->conf_id_hashtbl);
+err:
+	return -ENOMEM;
+}
+
+static void
+nfs4_state_destroy_net(struct net *net)
+{
+	int i;
+	struct nfs4_client *clp = NULL;
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+	struct rb_node *node, *tmp;
+
+	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
+		while (!list_empty(&nn->conf_id_hashtbl[i])) {
+			clp = list_entry(nn->conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
+			destroy_client(clp);
+		}
+	}
+
+	node = rb_first(&nn->unconf_name_tree);
+	while (node != NULL) {
+		tmp = node;
+		node = rb_next(tmp);
+		clp = rb_entry(tmp, struct nfs4_client, cl_namenode);
+		rb_erase(tmp, &nn->unconf_name_tree);
+		destroy_client(clp);
+	}
+
+	kfree(nn->sessionid_hashtbl);
+	kfree(nn->lockowner_ino_hashtbl);
+	kfree(nn->ownerstr_hashtbl);
+	kfree(nn->unconf_id_hashtbl);
+	kfree(nn->conf_id_hashtbl);
+	put_net(net);
+}
 
 int
-nfs4_state_start(void)
+nfs4_state_start_net(struct net *net)
 {
-	struct net *net = &init_net;
 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 	int ret;
 
@@ -4746,18 +4869,32 @@ nfs4_state_start(void)
 	 * to that instead and then do most of the rest of this on a per-net
 	 * basis.
 	 */
-	get_net(net);
+	if (net != &init_net)
+		return -EINVAL;
+
+	ret = nfs4_state_create_net(net);
+	if (ret)
+		return ret;
 	nfsd4_client_tracking_init(net);
 	nn->boot_time = get_seconds();
 	locks_start_grace(net, &nn->nfsd4_manager);
 	nn->grace_ended = false;
-	printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
-	       nfsd4_grace);
+	printk(KERN_INFO "NFSD: starting %ld-second grace period (net %p)\n",
+	       nn->nfsd4_grace, net);
+	queue_delayed_work(laundry_wq, &nn->laundromat_work, nn->nfsd4_grace * HZ);
+	return 0;
+}
+
+/* initialization to perform when the nfsd service is started: */
+
+int
+nfs4_state_start(void)
+{
+	int ret;
+
 	ret = set_callback_cred();
-	if (ret) {
-		ret = -ENOMEM;
-		goto out_recovery;
-	}
+	if (ret)
+		return -ENOMEM;
 	laundry_wq = create_singlethread_workqueue("nfsd4");
 	if (laundry_wq == NULL) {
 		ret = -ENOMEM;
@@ -4766,39 +4903,34 @@ nfs4_state_start(void)
 	ret = nfsd4_create_callback_queue();
 	if (ret)
 		goto out_free_laundry;
-	queue_delayed_work(laundry_wq, &laundromat_work, nfsd4_grace * HZ);
+
 	set_max_delegations();
+
 	return 0;
+
 out_free_laundry:
 	destroy_workqueue(laundry_wq);
 out_recovery:
-	nfsd4_client_tracking_exit(net);
-	put_net(net);
 	return ret;
 }
 
-static void
-__nfs4_state_shutdown(void)
+/* should be called with the state lock held */
+void
+nfs4_state_shutdown_net(struct net *net)
 {
-	int i;
-	struct nfs4_client *clp = NULL;
 	struct nfs4_delegation *dp = NULL;
 	struct list_head *pos, *next, reaplist;
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+	cancel_delayed_work_sync(&nn->laundromat_work);
+	locks_end_grace(&nn->nfsd4_manager);
 
-	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
-		while (!list_empty(&conf_id_hashtbl[i])) {
-			clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
-			destroy_client(clp);
-		}
-		while (!list_empty(&unconf_str_hashtbl[i])) {
-			clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash);
-			destroy_client(clp);
-		}
-	}
 	INIT_LIST_HEAD(&reaplist);
 	spin_lock(&recall_lock);
 	list_for_each_safe(pos, next, &del_recall_lru) {
 		dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
+		if (dp->dl_stid.sc_client->net != net)
+			continue;
 		list_move(&dp->dl_recall_lru, &reaplist);
 	}
 	spin_unlock(&recall_lock);
@@ -4807,22 +4939,14 @@ __nfs4_state_shutdown(void)
 		unhash_delegation(dp);
 	}
 
-	nfsd4_client_tracking_exit(&init_net);
-	put_net(&init_net);
+	nfsd4_client_tracking_exit(net);
+	nfs4_state_destroy_net(net);
 }
 
 void
 nfs4_state_shutdown(void)
 {
-	struct net *net = &init_net;
-	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
-
-	cancel_delayed_work_sync(&laundromat_work);
 	destroy_workqueue(laundry_wq);
-	locks_end_grace(&nn->nfsd4_manager);
-	nfs4_lock_state();
-	__nfs4_state_shutdown();
-	nfs4_unlock_state();
 	nfsd4_destroy_callback_queue();
 }
 
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index fd548d1..b775366 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -53,6 +53,7 @@
 #include "vfs.h"
 #include "state.h"
 #include "cache.h"
+#include "netns.h"
 
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
 
@@ -65,17 +66,17 @@
 #define NFS4_REFERRAL_FSID_MINOR	0x8000000ULL
 
 static __be32
-check_filename(char *str, int len, __be32 err)
+check_filename(char *str, int len)
 {
 	int i;
 
 	if (len == 0)
 		return nfserr_inval;
 	if (isdotent(str, len))
-		return err;
+		return nfserr_badname;
 	for (i = 0; i < len; i++)
 		if (str[i] == '/')
-			return err;
+			return nfserr_badname;
 	return 0;
 }
 
@@ -422,6 +423,86 @@ nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access
 	DECODE_TAIL;
 }
 
+static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs)
+{
+	DECODE_HEAD;
+	u32 dummy, uid, gid;
+	char *machine_name;
+	int i;
+	int nr_secflavs;
+
+	/* callback_sec_params4 */
+	READ_BUF(4);
+	READ32(nr_secflavs);
+	cbs->flavor = (u32)(-1);
+	for (i = 0; i < nr_secflavs; ++i) {
+		READ_BUF(4);
+		READ32(dummy);
+		switch (dummy) {
+		case RPC_AUTH_NULL:
+			/* Nothing to read */
+			if (cbs->flavor == (u32)(-1))
+				cbs->flavor = RPC_AUTH_NULL;
+			break;
+		case RPC_AUTH_UNIX:
+			READ_BUF(8);
+			/* stamp */
+			READ32(dummy);
+
+			/* machine name */
+			READ32(dummy);
+			READ_BUF(dummy);
+			SAVEMEM(machine_name, dummy);
+
+			/* uid, gid */
+			READ_BUF(8);
+			READ32(uid);
+			READ32(gid);
+
+			/* more gids */
+			READ_BUF(4);
+			READ32(dummy);
+			READ_BUF(dummy * 4);
+			if (cbs->flavor == (u32)(-1)) {
+				cbs->uid = uid;
+				cbs->gid = gid;
+				cbs->flavor = RPC_AUTH_UNIX;
+			}
+			break;
+		case RPC_AUTH_GSS:
+			dprintk("RPC_AUTH_GSS callback secflavor "
+				"not supported!\n");
+			READ_BUF(8);
+			/* gcbp_service */
+			READ32(dummy);
+			/* gcbp_handle_from_server */
+			READ32(dummy);
+			READ_BUF(dummy);
+			p += XDR_QUADLEN(dummy);
+			/* gcbp_handle_from_client */
+			READ_BUF(4);
+			READ32(dummy);
+			READ_BUF(dummy);
+			break;
+		default:
+			dprintk("Illegal callback secflavor\n");
+			return nfserr_inval;
+		}
+	}
+	DECODE_TAIL;
+}
+
+static __be32 nfsd4_decode_backchannel_ctl(struct nfsd4_compoundargs *argp, struct nfsd4_backchannel_ctl *bc)
+{
+	DECODE_HEAD;
+
+	READ_BUF(4);
+	READ32(bc->bc_cb_program);
+	nfsd4_decode_cb_sec(argp, &bc->bc_cb_sec);
+
+	DECODE_TAIL;
+}
+
 static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts)
 {
 	DECODE_HEAD;
@@ -490,7 +571,7 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
 	READ32(create->cr_namelen);
 	READ_BUF(create->cr_namelen);
 	SAVEMEM(create->cr_name, create->cr_namelen);
-	if ((status = check_filename(create->cr_name, create->cr_namelen, nfserr_inval)))
+	if ((status = check_filename(create->cr_name, create->cr_namelen)))
 		return status;
 
 	status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
@@ -522,7 +603,7 @@ nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link)
 	READ32(link->li_namelen);
 	READ_BUF(link->li_namelen);
 	SAVEMEM(link->li_name, link->li_namelen);
-	if ((status = check_filename(link->li_name, link->li_namelen, nfserr_inval)))
+	if ((status = check_filename(link->li_name, link->li_namelen)))
 		return status;
 
 	DECODE_TAIL;
@@ -616,7 +697,7 @@ nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup
 	READ32(lookup->lo_len);
 	READ_BUF(lookup->lo_len);
 	SAVEMEM(lookup->lo_name, lookup->lo_len);
-	if ((status = check_filename(lookup->lo_name, lookup->lo_len, nfserr_noent)))
+	if ((status = check_filename(lookup->lo_name, lookup->lo_len)))
 		return status;
 
 	DECODE_TAIL;
@@ -780,7 +861,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 		READ32(open->op_fname.len);
 		READ_BUF(open->op_fname.len);
 		SAVEMEM(open->op_fname.data, open->op_fname.len);
-		if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval)))
+		if ((status = check_filename(open->op_fname.data, open->op_fname.len)))
 			return status;
 		break;
 	case NFS4_OPEN_CLAIM_PREVIOUS:
@@ -795,7 +876,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 		READ32(open->op_fname.len);
 		READ_BUF(open->op_fname.len);
 		SAVEMEM(open->op_fname.data, open->op_fname.len);
-		if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval)))
+		if ((status = check_filename(open->op_fname.data, open->op_fname.len)))
 			return status;
 		break;
 	case NFS4_OPEN_CLAIM_FH:
@@ -907,7 +988,7 @@ nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove
 	READ32(remove->rm_namelen);
 	READ_BUF(remove->rm_namelen);
 	SAVEMEM(remove->rm_name, remove->rm_namelen);
-	if ((status = check_filename(remove->rm_name, remove->rm_namelen, nfserr_noent)))
+	if ((status = check_filename(remove->rm_name, remove->rm_namelen)))
 		return status;
 
 	DECODE_TAIL;
@@ -925,9 +1006,9 @@ nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename
 	READ32(rename->rn_tnamelen);
 	READ_BUF(rename->rn_tnamelen);
 	SAVEMEM(rename->rn_tname, rename->rn_tnamelen);
-	if ((status = check_filename(rename->rn_sname, rename->rn_snamelen, nfserr_noent)))
+	if ((status = check_filename(rename->rn_sname, rename->rn_snamelen)))
 		return status;
-	if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen, nfserr_inval)))
+	if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen)))
 		return status;
 
 	DECODE_TAIL;
@@ -954,8 +1035,7 @@ nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
 	READ32(secinfo->si_namelen);
 	READ_BUF(secinfo->si_namelen);
 	SAVEMEM(secinfo->si_name, secinfo->si_namelen);
-	status = check_filename(secinfo->si_name, secinfo->si_namelen,
-								nfserr_noent);
+	status = check_filename(secinfo->si_name, secinfo->si_namelen);
 	if (status)
 		return status;
 	DECODE_TAIL;
@@ -1063,7 +1143,6 @@ static __be32
 nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
 {
 	int avail;
-	int v;
 	int len;
 	DECODE_HEAD;
 
@@ -1087,27 +1166,26 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
 				__FILE__, __LINE__);
 		goto xdr_error;
 	}
-	argp->rqstp->rq_vec[0].iov_base = p;
-	argp->rqstp->rq_vec[0].iov_len = avail;
-	v = 0;
-	len = write->wr_buflen;
-	while (len > argp->rqstp->rq_vec[v].iov_len) {
-		len -= argp->rqstp->rq_vec[v].iov_len;
-		v++;
-		argp->rqstp->rq_vec[v].iov_base = page_address(argp->pagelist[0]);
-		argp->pagelist++;
-		if (argp->pagelen >= PAGE_SIZE) {
-			argp->rqstp->rq_vec[v].iov_len = PAGE_SIZE;
-			argp->pagelen -= PAGE_SIZE;
-		} else {
-			argp->rqstp->rq_vec[v].iov_len = argp->pagelen;
-			argp->pagelen -= len;
-		}
+	write->wr_head.iov_base = p;
+	write->wr_head.iov_len = avail;
+	WARN_ON(avail != (XDR_QUADLEN(avail) << 2));
+	write->wr_pagelist = argp->pagelist;
+
+	len = XDR_QUADLEN(write->wr_buflen) << 2;
+	if (len >= avail) {
+		int pages;
+
+		len -= avail;
+
+		pages = len >> PAGE_SHIFT;
+		argp->pagelist += pages;
+		argp->pagelen -= pages * PAGE_SIZE;
+		len -= pages * PAGE_SIZE;
+
+		argp->p = (__be32 *)page_address(argp->pagelist[0]);
+		argp->end = argp->p + XDR_QUADLEN(PAGE_SIZE);
 	}
-	argp->end = (__be32*) (argp->rqstp->rq_vec[v].iov_base + argp->rqstp->rq_vec[v].iov_len);
-	argp->p = (__be32*)  (argp->rqstp->rq_vec[v].iov_base + (XDR_QUADLEN(len) << 2));
-	argp->rqstp->rq_vec[v].iov_len = len;
-	write->wr_vlen = v+1;
+	argp->p += XDR_QUADLEN(len);
 
 	DECODE_TAIL;
 }
@@ -1237,11 +1315,7 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
 			    struct nfsd4_create_session *sess)
 {
 	DECODE_HEAD;
-
 	u32 dummy;
-	char *machine_name;
-	int i;
-	int nr_secflavs;
 
 	READ_BUF(16);
 	COPYMEM(&sess->clientid, 8);
@@ -1282,58 +1356,9 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
 		goto xdr_error;
 	}
 
-	READ_BUF(8);
+	READ_BUF(4);
 	READ32(sess->callback_prog);
-
-	/* callback_sec_params4 */
-	READ32(nr_secflavs);
-	for (i = 0; i < nr_secflavs; ++i) {
-		READ_BUF(4);
-		READ32(dummy);
-		switch (dummy) {
-		case RPC_AUTH_NULL:
-			/* Nothing to read */
-			break;
-		case RPC_AUTH_UNIX:
-			READ_BUF(8);
-			/* stamp */
-			READ32(dummy);
-
-			/* machine name */
-			READ32(dummy);
-			READ_BUF(dummy);
-			SAVEMEM(machine_name, dummy);
-
-			/* uid, gid */
-			READ_BUF(8);
-			READ32(sess->uid);
-			READ32(sess->gid);
-
-			/* more gids */
-			READ_BUF(4);
-			READ32(dummy);
-			READ_BUF(dummy * 4);
-			break;
-		case RPC_AUTH_GSS:
-			dprintk("RPC_AUTH_GSS callback secflavor "
-				"not supported!\n");
-			READ_BUF(8);
-			/* gcbp_service */
-			READ32(dummy);
-			/* gcbp_handle_from_server */
-			READ32(dummy);
-			READ_BUF(dummy);
-			p += XDR_QUADLEN(dummy);
-			/* gcbp_handle_from_client */
-			READ_BUF(4);
-			READ32(dummy);
-			READ_BUF(dummy);
-			break;
-		default:
-			dprintk("Illegal callback secflavor\n");
-			return nfserr_inval;
-		}
-	}
+	nfsd4_decode_cb_sec(argp, &sess->cb_sec);
 	DECODE_TAIL;
 }
 
@@ -1528,7 +1553,7 @@ static nfsd4_dec nfsd41_dec_ops[] = {
 	[OP_RELEASE_LOCKOWNER]	= (nfsd4_dec)nfsd4_decode_notsupp,
 
 	/* new operations for NFSv4.1 */
-	[OP_BACKCHANNEL_CTL]	= (nfsd4_dec)nfsd4_decode_notsupp,
+	[OP_BACKCHANNEL_CTL]	= (nfsd4_dec)nfsd4_decode_backchannel_ctl,
 	[OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_bind_conn_to_session,
 	[OP_EXCHANGE_ID]	= (nfsd4_dec)nfsd4_decode_exchange_id,
 	[OP_CREATE_SESSION]	= (nfsd4_dec)nfsd4_decode_create_session,
@@ -1568,12 +1593,6 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
 	bool cachethis = false;
 	int i;
 
-	/*
-	 * XXX: According to spec, we should check the tag
-	 * for UTF-8 compliance.  I'm postponing this for
-	 * now because it seems that some clients do use
-	 * binary tags.
-	 */
 	READ_BUF(4);
 	READ32(argp->taglen);
 	READ_BUF(argp->taglen + 8);
@@ -1603,38 +1622,8 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
 		op = &argp->ops[i];
 		op->replay = NULL;
 
-		/*
-		 * We can't use READ_BUF() here because we need to handle
-		 * a missing opcode as an OP_WRITE + 1. So we need to check
-		 * to see if we're truly at the end of our buffer or if there
-		 * is another page we need to flip to.
-		 */
-
-		if (argp->p == argp->end) {
-			if (argp->pagelen < 4) {
-				/* There isn't an opcode still on the wire */
-				op->opnum = OP_WRITE + 1;
-				op->status = nfserr_bad_xdr;
-				argp->opcnt = i+1;
-				break;
-			}
-
-			/*
-			 * False alarm. We just hit a page boundary, but there
-			 * is still data available.  Move pointer across page
-			 * boundary.  *snip from READ_BUF*
-			 */
-			argp->p = page_address(argp->pagelist[0]);
-			argp->pagelist++;
-			if (argp->pagelen < PAGE_SIZE) {
-				argp->end = argp->p + (argp->pagelen>>2);
-				argp->pagelen = 0;
-			} else {
-				argp->end = argp->p + (PAGE_SIZE>>2);
-				argp->pagelen -= PAGE_SIZE;
-			}
-		}
-		op->opnum = ntohl(*argp->p++);
+		READ_BUF(4);
+		READ32(op->opnum);
 
 		if (op->opnum >= FIRST_NFS4_OP && op->opnum <= LAST_NFS4_OP)
 			op->status = ops->decoders[op->opnum](argp, &op->u);
@@ -2014,6 +2003,22 @@ static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
 	return 0;
 }
 
+
+static int get_parent_attributes(struct svc_export *exp, struct kstat *stat)
+{
+	struct path path = exp->ex_path;
+	int err;
+
+	path_get(&path);
+	while (follow_up(&path)) {
+		if (path.dentry != path.mnt->mnt_root)
+			break;
+	}
+	err = vfs_getattr(path.mnt, path.dentry, stat);
+	path_put(&path);
+	return err;
+}
+
 /*
  * Note: @fhp can be NULL; in this case, we might have to compose the filehandle
  * ourselves.
@@ -2048,6 +2053,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
 		.mnt	= exp->ex_path.mnt,
 		.dentry	= dentry,
 	};
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
 	BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion));
@@ -2208,7 +2214,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
 	if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
 		if ((buflen -= 4) < 0)
 			goto out_resource;
-		WRITE32(nfsd4_lease);
+		WRITE32(nn->nfsd4_lease);
 	}
 	if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
 		if ((buflen -= 4) < 0)
@@ -2430,18 +2436,8 @@ out_acl:
 		 * and this is the root of a cross-mounted filesystem.
 		 */
 		if (ignore_crossmnt == 0 &&
-		    dentry == exp->ex_path.mnt->mnt_root) {
-			struct path path = exp->ex_path;
-			path_get(&path);
-			while (follow_up(&path)) {
-				if (path.dentry != path.mnt->mnt_root)
-					break;
-			}
-			err = vfs_getattr(path.mnt, path.dentry, &stat);
-			path_put(&path);
-			if (err)
-				goto out_nfserr;
-		}
+		    dentry == exp->ex_path.mnt->mnt_root)
+			get_parent_attributes(exp, &stat);
 		WRITE64(stat.ino);
 	}
 	if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index dab350d..e13cbdd 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -19,7 +19,7 @@
 #include "idmap.h"
 #include "nfsd.h"
 #include "cache.h"
-#include "fault_inject.h"
+#include "state.h"
 #include "netns.h"
 
 /*
@@ -186,9 +186,6 @@ static struct file_operations supported_enctypes_ops = {
 };
 #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
 
-extern int nfsd_pool_stats_open(struct inode *inode, struct file *file);
-extern int nfsd_pool_stats_release(struct inode *inode, struct file *file);
-
 static const struct file_operations pool_stats_operations = {
 	.open		= nfsd_pool_stats_open,
 	.read		= seq_read,
@@ -912,7 +909,8 @@ static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_
  */
 static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
 {
-	return nfsd4_write_time(file, buf, size, &nfsd4_lease);
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease);
 }
 
 /**
@@ -927,7 +925,8 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
  */
 static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
 {
-	return nfsd4_write_time(file, buf, size, &nfsd4_grace);
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace);
 }
 
 static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
@@ -1063,6 +1062,7 @@ int nfsd_net_id;
 static __net_init int nfsd_init_net(struct net *net)
 {
 	int retval;
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
 	retval = nfsd_export_init(net);
 	if (retval)
@@ -1070,6 +1070,8 @@ static __net_init int nfsd_init_net(struct net *net)
 	retval = nfsd_idmap_init(net);
 	if (retval)
 		goto out_idmap_error;
+	nn->nfsd4_lease = 90;	/* default lease time */
+	nn->nfsd4_grace = 90;
 	return 0;
 
 out_idmap_error:
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 80d5ce4..5eea0f5 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -121,7 +121,9 @@ void nfs4_state_init(void);
 int nfsd4_init_slabs(void);
 void nfsd4_free_slabs(void);
 int nfs4_state_start(void);
+int nfs4_state_start_net(struct net *net);
 void nfs4_state_shutdown(void);
+void nfs4_state_shutdown_net(struct net *net);
 void nfs4_reset_lease(time_t leasetime);
 int nfs4_reset_recoverydir(char *recdir);
 char * nfs4_recoverydir(void);
@@ -130,7 +132,9 @@ static inline void nfs4_state_init(void) { }
 static inline int nfsd4_init_slabs(void) { return 0; }
 static inline void nfsd4_free_slabs(void) { }
 static inline int nfs4_state_start(void) { return 0; }
+static inline int nfs4_state_start_net(struct net *net) { return 0; }
 static inline void nfs4_state_shutdown(void) { }
+static inline void nfs4_state_shutdown_net(struct net *net) { }
 static inline void nfs4_reset_lease(time_t leasetime) { }
 static inline int nfs4_reset_recoverydir(char *recdir) { return 0; }
 static inline char * nfs4_recoverydir(void) {return NULL; }
@@ -272,9 +276,6 @@ extern struct timeval	nfssvc_boot;
 
 #ifdef CONFIG_NFSD_V4
 
-extern time_t nfsd4_lease;
-extern time_t nfsd4_grace;
-
 /* before processing a COMPOUND operation, we have to check that there
  * is enough space in the buffer for XDR encode to succeed.  otherwise,
  * we might process an operation with side effects, and be unable to
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 032af38..814afaa 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -572,7 +572,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
 
 		if (inode)
 			_fh_update(fhp, exp, dentry);
-		if (fhp->fh_handle.fh_fileid_type == 255) {
+		if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) {
 			fh_put(fhp);
 			return nfserr_opnotsupp;
 		}
@@ -603,7 +603,7 @@ fh_update(struct svc_fh *fhp)
 			goto out;
 
 		_fh_update(fhp, fhp->fh_export, dentry);
-		if (fhp->fh_handle.fh_fileid_type == 255)
+		if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID)
 			return nfserr_opnotsupp;
 	}
 out:
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 2013aa00..b34a67d 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -207,6 +207,7 @@ static bool nfsd_up = false;
 static int nfsd_startup(int nrservs)
 {
 	int ret;
+	struct net *net = &init_net;
 
 	if (nfsd_up)
 		return 0;
@@ -221,14 +222,21 @@ static int nfsd_startup(int nrservs)
 	ret = nfsd_init_socks();
 	if (ret)
 		goto out_racache;
-	ret = lockd_up(&init_net);
+	ret = lockd_up(net);
 	if (ret)
 		goto out_racache;
 	ret = nfs4_state_start();
 	if (ret)
 		goto out_lockd;
+
+	ret = nfs4_state_start_net(net);
+	if (ret)
+		goto out_net_state;
+
 	nfsd_up = true;
 	return 0;
+out_net_state:
+	nfs4_state_shutdown();
 out_lockd:
 	lockd_down(&init_net);
 out_racache:
@@ -238,6 +246,8 @@ out_racache:
 
 static void nfsd_shutdown(void)
 {
+	struct net *net = &init_net;
+
 	/*
 	 * write_ports can create the server without actually starting
 	 * any threads--if we get shut down before any threads are
@@ -246,8 +256,9 @@ static void nfsd_shutdown(void)
 	 */
 	if (!nfsd_up)
 		return;
+	nfs4_state_shutdown_net(net);
 	nfs4_state_shutdown();
-	lockd_down(&init_net);
+	lockd_down(net);
 	nfsd_racache_shutdown();
 	nfsd_up = false;
 }
@@ -640,7 +651,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 	}
 
 	/* Store reply in cache. */
-	nfsd_cache_update(rqstp, proc->pc_cachetype, statp + 1);
+	nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);
 	return 1;
 }
 
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index e036894..b542bf2 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -150,6 +150,12 @@ struct nfsd4_channel_attrs {
 	u32		rdma_attrs;
 };
 
+struct nfsd4_cb_sec {
+	u32	flavor; /* (u32)(-1) used to mean "no valid flavor" */
+	u32	uid;
+	u32	gid;
+};
+
 struct nfsd4_create_session {
 	clientid_t			clientid;
 	struct nfs4_sessionid		sessionid;
@@ -158,8 +164,12 @@ struct nfsd4_create_session {
 	struct nfsd4_channel_attrs	fore_channel;
 	struct nfsd4_channel_attrs	back_channel;
 	u32				callback_prog;
-	u32				uid;
-	u32				gid;
+	struct nfsd4_cb_sec		cb_sec;
+};
+
+struct nfsd4_backchannel_ctl {
+	u32	bc_cb_program;
+	struct nfsd4_cb_sec		bc_cb_sec;
 };
 
 struct nfsd4_bind_conn_to_session {
@@ -192,6 +202,7 @@ struct nfsd4_session {
 	struct nfs4_sessionid	se_sessionid;
 	struct nfsd4_channel_attrs se_fchannel;
 	struct nfsd4_channel_attrs se_bchannel;
+	struct nfsd4_cb_sec	se_cb_sec;
 	struct list_head	se_conns;
 	u32			se_cb_prog;
 	u32			se_cb_seq_nr;
@@ -221,13 +232,12 @@ struct nfsd4_sessionid {
  */
 struct nfs4_client {
 	struct list_head	cl_idhash; 	/* hash by cl_clientid.id */
-	struct list_head	cl_strhash; 	/* hash by cl_name */
+	struct rb_node		cl_namenode;	/* link into by-name trees */
 	struct list_head	cl_openowners;
 	struct idr		cl_stateids;	/* stateid lookup */
 	struct list_head	cl_delegations;
 	struct list_head        cl_lru;         /* tail queue */
 	struct xdr_netobj	cl_name; 	/* id generated by client */
-	char                    cl_recdir[HEXDIR_LEN]; /* recovery dir */
 	nfs4_verifier		cl_verifier; 	/* generated by client */
 	time_t                  cl_time;        /* time of last lease renewal */
 	struct sockaddr_storage	cl_addr; 	/* client ipaddress */
@@ -242,9 +252,11 @@ struct nfs4_client {
 #define NFSD4_CLIENT_CB_KILL		(1)
 #define NFSD4_CLIENT_STABLE		(2)	/* client on stable storage */
 #define NFSD4_CLIENT_RECLAIM_COMPLETE	(3)	/* reclaim_complete done */
+#define NFSD4_CLIENT_CONFIRMED		(4)	/* client is confirmed */
 #define NFSD4_CLIENT_CB_FLAG_MASK	(1 << NFSD4_CLIENT_CB_UPDATE | \
 					 1 << NFSD4_CLIENT_CB_KILL)
 	unsigned long		cl_flags;
+	struct rpc_cred		*cl_cb_cred;
 	struct rpc_clnt		*cl_cb_client;
 	u32			cl_cb_ident;
 #define NFSD4_CB_UP		0
@@ -271,6 +283,7 @@ struct nfs4_client {
 	unsigned long		cl_cb_slot_busy;
 	struct rpc_wait_queue	cl_cb_waitq;	/* backchannel callers may */
 						/* wait here for slots */
+	struct net		*net;
 };
 
 static inline void
@@ -292,6 +305,7 @@ is_client_expired(struct nfs4_client *clp)
  */
 struct nfs4_client_reclaim {
 	struct list_head	cr_strhash;	/* hash by cr_name */
+	struct nfs4_client	*cr_clp;	/* pointer to associated clp */
 	char			cr_recdir[HEXDIR_LEN]; /* recover dir */
 };
 
@@ -452,25 +466,26 @@ extern __be32 nfs4_preprocess_stateid_op(struct net *net,
 		stateid_t *stateid, int flags, struct file **filp);
 extern void nfs4_lock_state(void);
 extern void nfs4_unlock_state(void);
-extern int nfs4_in_grace(void);
-extern void nfs4_release_reclaim(void);
-extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp);
-extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions);
+void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *, struct nfsd_net *);
+extern void nfs4_release_reclaim(struct nfsd_net *);
+extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir,
+							struct nfsd_net *nn);
+extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions, struct nfsd_net *nn);
 extern void nfs4_free_openowner(struct nfs4_openowner *);
 extern void nfs4_free_lockowner(struct nfs4_lockowner *);
 extern int set_callback_cred(void);
+extern void nfsd4_init_callback(struct nfsd4_callback *);
 extern void nfsd4_probe_callback(struct nfs4_client *clp);
 extern void nfsd4_probe_callback_sync(struct nfs4_client *clp);
 extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
-extern void nfsd4_do_callback_rpc(struct work_struct *);
 extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
 extern int nfsd4_create_callback_queue(void);
 extern void nfsd4_destroy_callback_queue(void);
 extern void nfsd4_shutdown_callback(struct nfs4_client *);
 extern void nfs4_put_delegation(struct nfs4_delegation *dp);
-extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
-extern int nfs4_client_to_reclaim(const char *name);
-extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id);
+extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name,
+							struct nfsd_net *nn);
+extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn);
 extern void release_session_client(struct nfsd4_session *);
 extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);
 
@@ -480,5 +495,20 @@ extern void nfsd4_client_tracking_exit(struct net *net);
 extern void nfsd4_client_record_create(struct nfs4_client *clp);
 extern void nfsd4_client_record_remove(struct nfs4_client *clp);
 extern int nfsd4_client_record_check(struct nfs4_client *clp);
-extern void nfsd4_record_grace_done(struct net *net, time_t boot_time);
+extern void nfsd4_record_grace_done(struct nfsd_net *nn, time_t boot_time);
+
+/* nfs fault injection functions */
+#ifdef CONFIG_NFSD_FAULT_INJECTION
+int nfsd_fault_inject_init(void);
+void nfsd_fault_inject_cleanup(void);
+void nfsd_forget_clients(u64);
+void nfsd_forget_locks(u64);
+void nfsd_forget_openowners(u64);
+void nfsd_forget_delegations(u64);
+void nfsd_recall_delegations(u64);
+#else /* CONFIG_NFSD_FAULT_INJECTION */
+static inline int nfsd_fault_inject_init(void) { return 0; }
+static inline void nfsd_fault_inject_cleanup(void) {}
+#endif /* CONFIG_NFSD_FAULT_INJECTION */
+
 #endif   /* NFSD4_STATE_H */
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index c120b48..b584205 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1020,28 +1020,10 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
 	inode = dentry->d_inode;
 	exp   = fhp->fh_export;
 
-	/*
-	 * Request sync writes if
-	 *  -	the sync export option has been set, or
-	 *  -	the client requested O_SYNC behavior (NFSv3 feature).
-	 *  -   The file system doesn't support fsync().
-	 * When NFSv2 gathered writes have been configured for this volume,
-	 * flushing the data to disk is handled separately below.
-	 */
 	use_wgather = (rqstp->rq_vers == 2) && EX_WGATHER(exp);
 
-	if (!file->f_op->fsync) {/* COMMIT3 cannot work */
-	       stable = 2;
-	       *stablep = 2; /* FILE_SYNC */
-	}
-
 	if (!EX_ISSYNC(exp))
 		stable = 0;
-	if (stable && !use_wgather) {
-		spin_lock(&file->f_lock);
-		file->f_flags |= O_SYNC;
-		spin_unlock(&file->f_lock);
-	}
 
 	/* Write the data. */
 	oldfs = get_fs(); set_fs(KERNEL_DS);
@@ -1057,8 +1039,12 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
 	if (inode->i_mode & (S_ISUID | S_ISGID))
 		kill_suid(dentry);
 
-	if (stable && use_wgather)
-		host_err = wait_for_concurrent_writes(file);
+	if (stable) {
+		if (use_wgather)
+			host_err = wait_for_concurrent_writes(file);
+		else
+			host_err = vfs_fsync_range(file, offset, offset+*cnt, 0);
+	}
 
 out_nfserr:
 	dprintk("nfsd: write complete host_err=%d\n", host_err);
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index acd127d..331f8a3 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -385,7 +385,8 @@ struct nfsd4_write {
 	u64		wr_offset;          /* request */
 	u32		wr_stable_how;      /* request */
 	u32		wr_buflen;          /* request */
-	int		wr_vlen;
+	struct kvec	wr_head;
+	struct page **	wr_pagelist;        /* request */
 
 	u32		wr_bytes_written;   /* response */
 	u32		wr_how_written;     /* response */
@@ -462,6 +463,7 @@ struct nfsd4_op {
 
 		/* NFSv4.1 */
 		struct nfsd4_exchange_id	exchange_id;
+		struct nfsd4_backchannel_ctl	backchannel_ctl;
 		struct nfsd4_bind_conn_to_session bind_conn_to_session;
 		struct nfsd4_create_session	create_session;
 		struct nfsd4_destroy_session	destroy_session;
@@ -566,6 +568,7 @@ extern __be32 nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp,
 		struct nfsd4_sequence *seq);
 extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp,
 		struct nfsd4_compound_state *, struct nfsd4_exchange_id *);
+extern __be32 nfsd4_backchannel_ctl(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_backchannel_ctl *);
 extern __be32 nfsd4_bind_conn_to_session(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_bind_conn_to_session *);
 extern __be32 nfsd4_create_session(struct svc_rqst *,
 		struct nfsd4_compound_state *,
@@ -579,7 +582,7 @@ extern __be32 nfsd4_destroy_session(struct svc_rqst *,
 extern __be32 nfsd4_destroy_clientid(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_destroy_clientid *);
 __be32 nfsd4_reclaim_complete(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_reclaim_complete *);
 extern __be32 nfsd4_process_open1(struct nfsd4_compound_state *,
-		struct nfsd4_open *open);
+		struct nfsd4_open *open, struct nfsd_net *nn);
 extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp,
 		struct svc_fh *current_fh, struct nfsd4_open *open);
 extern void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status);
diff --git a/fs/nilfs2/Kconfig b/fs/nilfs2/Kconfig
index 251da07..80da8eb 100644
--- a/fs/nilfs2/Kconfig
+++ b/fs/nilfs2/Kconfig
@@ -1,6 +1,5 @@
 config NILFS2_FS
-	tristate "NILFS2 file system support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	tristate "NILFS2 file system support"
 	select CRC32
 	help
 	  NILFS2 is a log-structured file system (LFS) supporting continuous
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index 3e7b2a0..07f76db 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -431,7 +431,7 @@ void nilfs_mapping_init(struct address_space *mapping, struct inode *inode,
 	mapping->host = inode;
 	mapping->flags = 0;
 	mapping_set_gfp_mask(mapping, GFP_NOFS);
-	mapping->assoc_mapping = NULL;
+	mapping->private_data = NULL;
 	mapping->backing_dev_info = bdi;
 	mapping->a_ops = &empty_aops;
 }
diff --git a/fs/notify/Makefile b/fs/notify/Makefile
index ae5f33a..96d3420 100644
--- a/fs/notify/Makefile
+++ b/fs/notify/Makefile
@@ -1,5 +1,5 @@
 obj-$(CONFIG_FSNOTIFY)		+= fsnotify.o notification.o group.o inode_mark.o \
-				   mark.o vfsmount_mark.o
+				   mark.o vfsmount_mark.o fdinfo.o
 
 obj-y			+= dnotify/
 obj-y			+= inotify/
diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c
index 3344bdd..08b886f 100644
--- a/fs/notify/dnotify/dnotify.c
+++ b/fs/notify/dnotify/dnotify.c
@@ -201,7 +201,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id)
 
 	/* nothing else could have found us thanks to the dnotify_mark_mutex */
 	if (dn_mark->dn == NULL)
-		fsnotify_destroy_mark(fsn_mark);
+		fsnotify_destroy_mark(fsn_mark, dnotify_group);
 
 	mutex_unlock(&dnotify_mark_mutex);
 
@@ -385,7 +385,7 @@ out:
 	spin_unlock(&fsn_mark->lock);
 
 	if (destroy)
-		fsnotify_destroy_mark(fsn_mark);
+		fsnotify_destroy_mark(fsn_mark, dnotify_group);
 
 	mutex_unlock(&dnotify_mark_mutex);
 	fsnotify_put_mark(fsn_mark);
diff --git a/fs/notify/fanotify/Kconfig b/fs/notify/fanotify/Kconfig
index 7dceff0..e5f911b 100644
--- a/fs/notify/fanotify/Kconfig
+++ b/fs/notify/fanotify/Kconfig
@@ -4,7 +4,7 @@ config FANOTIFY
 	select ANON_INODES
 	default n
 	---help---
-	   Say Y here to enable fanotify suport.  fanotify is a file access
+	   Say Y here to enable fanotify support.  fanotify is a file access
 	   notification system which differs from inotify in that it sends
 	   an open file descriptor to the userspace listener along with
 	   the event.
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index a506360..0c2f912 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -18,6 +18,12 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new)
 	    old->tgid == new->tgid) {
 		switch (old->data_type) {
 		case (FSNOTIFY_EVENT_PATH):
+#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+			/* dont merge two permission events */
+			if ((old->mask & FAN_ALL_PERM_EVENTS) &&
+			    (new->mask & FAN_ALL_PERM_EVENTS))
+				return false;
+#endif
 			if ((old->path.mnt == new->path.mnt) &&
 			    (old->path.dentry == new->path.dentry))
 				return true;
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 6fcaeb8..9ff4a5e 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -17,6 +17,7 @@
 #include <asm/ioctls.h>
 
 #include "../../mount.h"
+#include "../fdinfo.h"
 
 #define FANOTIFY_DEFAULT_MAX_EVENTS	16384
 #define FANOTIFY_DEFAULT_MAX_MARKS	8192
@@ -396,8 +397,12 @@ static int fanotify_release(struct inode *ignored, struct file *file)
 
 	wake_up(&group->fanotify_data.access_waitq);
 #endif
+
+	if (file->f_flags & FASYNC)
+		fsnotify_fasync(-1, file, 0);
+
 	/* matches the fanotify_init->fsnotify_alloc_group */
-	fsnotify_put_group(group);
+	fsnotify_destroy_group(group);
 
 	return 0;
 }
@@ -428,6 +433,7 @@ static long fanotify_ioctl(struct file *file, unsigned int cmd, unsigned long ar
 }
 
 static const struct file_operations fanotify_fops = {
+	.show_fdinfo	= fanotify_show_fdinfo,
 	.poll		= fanotify_poll,
 	.read		= fanotify_read,
 	.write		= fanotify_write,
@@ -491,7 +497,8 @@ out:
 
 static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
 					    __u32 mask,
-					    unsigned int flags)
+					    unsigned int flags,
+					    int *destroy)
 {
 	__u32 oldmask;
 
@@ -505,8 +512,7 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
 	}
 	spin_unlock(&fsn_mark->lock);
 
-	if (!(oldmask & ~mask))
-		fsnotify_destroy_mark(fsn_mark);
+	*destroy = !(oldmask & ~mask);
 
 	return mask & oldmask;
 }
@@ -517,12 +523,17 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
 {
 	struct fsnotify_mark *fsn_mark = NULL;
 	__u32 removed;
+	int destroy_mark;
 
 	fsn_mark = fsnotify_find_vfsmount_mark(group, mnt);
 	if (!fsn_mark)
 		return -ENOENT;
 
-	removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags);
+	removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags,
+						 &destroy_mark);
+	if (destroy_mark)
+		fsnotify_destroy_mark(fsn_mark, group);
+
 	fsnotify_put_mark(fsn_mark);
 	if (removed & real_mount(mnt)->mnt_fsnotify_mask)
 		fsnotify_recalc_vfsmount_mask(mnt);
@@ -536,12 +547,16 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group,
 {
 	struct fsnotify_mark *fsn_mark = NULL;
 	__u32 removed;
+	int destroy_mark;
 
 	fsn_mark = fsnotify_find_inode_mark(group, inode);
 	if (!fsn_mark)
 		return -ENOENT;
 
-	removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags);
+	removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags,
+						 &destroy_mark);
+	if (destroy_mark)
+		fsnotify_destroy_mark(fsn_mark, group);
 	/* matches the fsnotify_find_inode_mark() */
 	fsnotify_put_mark(fsn_mark);
 	if (removed & inode->i_fsnotify_mask)
@@ -708,13 +723,13 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 		break;
 	default:
 		fd = -EINVAL;
-		goto out_put_group;
+		goto out_destroy_group;
 	}
 
 	if (flags & FAN_UNLIMITED_QUEUE) {
 		fd = -EPERM;
 		if (!capable(CAP_SYS_ADMIN))
-			goto out_put_group;
+			goto out_destroy_group;
 		group->max_events = UINT_MAX;
 	} else {
 		group->max_events = FANOTIFY_DEFAULT_MAX_EVENTS;
@@ -723,7 +738,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 	if (flags & FAN_UNLIMITED_MARKS) {
 		fd = -EPERM;
 		if (!capable(CAP_SYS_ADMIN))
-			goto out_put_group;
+			goto out_destroy_group;
 		group->fanotify_data.max_marks = UINT_MAX;
 	} else {
 		group->fanotify_data.max_marks = FANOTIFY_DEFAULT_MAX_MARKS;
@@ -731,12 +746,12 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 
 	fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
 	if (fd < 0)
-		goto out_put_group;
+		goto out_destroy_group;
 
 	return fd;
 
-out_put_group:
-	fsnotify_put_group(group);
+out_destroy_group:
+	fsnotify_destroy_group(group);
 	return fd;
 }
 
diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c
new file mode 100644
index 0000000..ca48131
--- /dev/null
+++ b/fs/notify/fdinfo.c
@@ -0,0 +1,150 @@
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/fsnotify_backend.h>
+#include <linux/idr.h>
+#include <linux/init.h>
+#include <linux/inotify.h>
+#include <linux/kernel.h>
+#include <linux/namei.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
+#include <linux/exportfs.h>
+
+#include "inotify/inotify.h"
+#include "../fs/mount.h"
+
+#if defined(CONFIG_PROC_FS)
+
+#if defined(CONFIG_INOTIFY_USER) || defined(CONFIG_FANOTIFY)
+
+static int show_fdinfo(struct seq_file *m, struct file *f,
+		       int (*show)(struct seq_file *m, struct fsnotify_mark *mark))
+{
+	struct fsnotify_group *group = f->private_data;
+	struct fsnotify_mark *mark;
+	int ret = 0;
+
+	mutex_lock(&group->mark_mutex);
+	list_for_each_entry(mark, &group->marks_list, g_list) {
+		ret = show(m, mark);
+		if (ret)
+			break;
+	}
+	mutex_unlock(&group->mark_mutex);
+	return ret;
+}
+
+#if defined(CONFIG_EXPORTFS)
+static int show_mark_fhandle(struct seq_file *m, struct inode *inode)
+{
+	struct {
+		struct file_handle handle;
+		u8 pad[64];
+	} f;
+	int size, ret, i;
+
+	f.handle.handle_bytes = sizeof(f.pad);
+	size = f.handle.handle_bytes >> 2;
+
+	ret = exportfs_encode_inode_fh(inode, (struct fid *)f.handle.f_handle, &size, 0);
+	if ((ret == 255) || (ret == -ENOSPC)) {
+		WARN_ONCE(1, "Can't encode file handler for inotify: %d\n", ret);
+		return 0;
+	}
+
+	f.handle.handle_type = ret;
+	f.handle.handle_bytes = size * sizeof(u32);
+
+	ret = seq_printf(m, "fhandle-bytes:%x fhandle-type:%x f_handle:",
+			 f.handle.handle_bytes, f.handle.handle_type);
+
+	for (i = 0; i < f.handle.handle_bytes; i++)
+		ret |= seq_printf(m, "%02x", (int)f.handle.f_handle[i]);
+
+	return ret;
+}
+#else
+static int show_mark_fhandle(struct seq_file *m, struct inode *inode)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_INOTIFY_USER
+
+static int inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
+{
+	struct inotify_inode_mark *inode_mark;
+	struct inode *inode;
+	int ret = 0;
+
+	if (!(mark->flags & (FSNOTIFY_MARK_FLAG_ALIVE | FSNOTIFY_MARK_FLAG_INODE)))
+		return 0;
+
+	inode_mark = container_of(mark, struct inotify_inode_mark, fsn_mark);
+	inode = igrab(mark->i.inode);
+	if (inode) {
+		ret = seq_printf(m, "inotify wd:%x ino:%lx sdev:%x "
+				 "mask:%x ignored_mask:%x ",
+				 inode_mark->wd, inode->i_ino,
+				 inode->i_sb->s_dev,
+				 mark->mask, mark->ignored_mask);
+		ret |= show_mark_fhandle(m, inode);
+		ret |= seq_putc(m, '\n');
+		iput(inode);
+	}
+
+	return ret;
+}
+
+int inotify_show_fdinfo(struct seq_file *m, struct file *f)
+{
+	return show_fdinfo(m, f, inotify_fdinfo);
+}
+
+#endif /* CONFIG_INOTIFY_USER */
+
+#ifdef CONFIG_FANOTIFY
+
+static int fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
+{
+	struct inode *inode;
+	int ret = 0;
+
+	if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE))
+		return 0;
+
+	if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) {
+		inode = igrab(mark->i.inode);
+		if (!inode)
+			goto out;
+		ret = seq_printf(m, "fanotify ino:%lx sdev:%x "
+				 "mask:%x ignored_mask:%x ",
+				 inode->i_ino, inode->i_sb->s_dev,
+				 mark->mask, mark->ignored_mask);
+		ret |= show_mark_fhandle(m, inode);
+		ret |= seq_putc(m, '\n');
+		iput(inode);
+	} else if (mark->flags & FSNOTIFY_MARK_FLAG_VFSMOUNT) {
+		struct mount *mnt = real_mount(mark->m.mnt);
+
+		ret = seq_printf(m, "fanotify mnt_id:%x mask:%x "
+				 "ignored_mask:%x\n",
+				 mnt->mnt_id, mark->mask, mark->ignored_mask);
+	}
+out:
+	return ret;
+}
+
+int fanotify_show_fdinfo(struct seq_file *m, struct file *f)
+{
+	return show_fdinfo(m, f, fanotify_fdinfo);
+}
+
+#endif /* CONFIG_FANOTIFY */
+
+#endif /* CONFIG_INOTIFY_USER || CONFIG_FANOTIFY */
+
+#endif /* CONFIG_PROC_FS */
diff --git a/fs/notify/fdinfo.h b/fs/notify/fdinfo.h
new file mode 100644
index 0000000..556afda
--- /dev/null
+++ b/fs/notify/fdinfo.h
@@ -0,0 +1,27 @@
+#ifndef __FSNOTIFY_FDINFO_H__
+#define __FSNOTIFY_FDINFO_H__
+
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+
+struct seq_file;
+struct file;
+
+#ifdef CONFIG_PROC_FS
+
+#ifdef CONFIG_INOTIFY_USER
+extern int inotify_show_fdinfo(struct seq_file *m, struct file *f);
+#endif
+
+#ifdef CONFIG_FANOTIFY
+extern int fanotify_show_fdinfo(struct seq_file *m, struct file *f);
+#endif
+
+#else /* CONFIG_PROC_FS */
+
+#define inotify_show_fdinfo	NULL
+#define fanotify_show_fdinfo	NULL
+
+#endif /* CONFIG_PROC_FS */
+
+#endif /* __FSNOTIFY_FDINFO_H__ */
diff --git a/fs/notify/group.c b/fs/notify/group.c
index 63fc294..bd2625b 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -33,9 +33,6 @@
  */
 void fsnotify_final_destroy_group(struct fsnotify_group *group)
 {
-	/* clear the notification queue of all events */
-	fsnotify_flush_notify(group);
-
 	if (group->ops->free_group_priv)
 		group->ops->free_group_priv(group);
 
@@ -43,23 +40,30 @@ void fsnotify_final_destroy_group(struct fsnotify_group *group)
 }
 
 /*
- * Trying to get rid of a group.  We need to first get rid of any outstanding
- * allocations and then free the group.  Remember that fsnotify_clear_marks_by_group
- * could miss marks that are being freed by inode and those marks could still
- * hold a reference to this group (via group->num_marks)  If we get into that
- * situtation, the fsnotify_final_destroy_group will get called when that final
- * mark is freed.
+ * Trying to get rid of a group. Remove all marks, flush all events and release
+ * the group reference.
+ * Note that another thread calling fsnotify_clear_marks_by_group() may still
+ * hold a ref to the group.
  */
-static void fsnotify_destroy_group(struct fsnotify_group *group)
+void fsnotify_destroy_group(struct fsnotify_group *group)
 {
 	/* clear all inode marks for this group */
 	fsnotify_clear_marks_by_group(group);
 
 	synchronize_srcu(&fsnotify_mark_srcu);
 
-	/* past the point of no return, matches the initial value of 1 */
-	if (atomic_dec_and_test(&group->num_marks))
-		fsnotify_final_destroy_group(group);
+	/* clear the notification queue of all events */
+	fsnotify_flush_notify(group);
+
+	fsnotify_put_group(group);
+}
+
+/*
+ * Get reference to a group.
+ */
+void fsnotify_get_group(struct fsnotify_group *group)
+{
+	atomic_inc(&group->refcnt);
 }
 
 /*
@@ -68,7 +72,7 @@ static void fsnotify_destroy_group(struct fsnotify_group *group)
 void fsnotify_put_group(struct fsnotify_group *group)
 {
 	if (atomic_dec_and_test(&group->refcnt))
-		fsnotify_destroy_group(group);
+		fsnotify_final_destroy_group(group);
 }
 
 /*
@@ -84,21 +88,24 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
 
 	/* set to 0 when there a no external references to this group */
 	atomic_set(&group->refcnt, 1);
-	/*
-	 * hits 0 when there are no external references AND no marks for
-	 * this group
-	 */
-	atomic_set(&group->num_marks, 1);
+	atomic_set(&group->num_marks, 0);
 
 	mutex_init(&group->notification_mutex);
 	INIT_LIST_HEAD(&group->notification_list);
 	init_waitqueue_head(&group->notification_waitq);
 	group->max_events = UINT_MAX;
 
-	spin_lock_init(&group->mark_lock);
+	mutex_init(&group->mark_mutex);
 	INIT_LIST_HEAD(&group->marks_list);
 
 	group->ops = ops;
 
 	return group;
 }
+
+int fsnotify_fasync(int fd, struct file *file, int on)
+{
+	struct fsnotify_group *group = file->private_data;
+
+	return fasync_helper(fd, file, on, &group->fsn_fa) >= 0 ? 0 : -EIO;
+}
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c
index b13c00a..2123020 100644
--- a/fs/notify/inode_mark.c
+++ b/fs/notify/inode_mark.c
@@ -63,8 +63,8 @@ void fsnotify_destroy_inode_mark(struct fsnotify_mark *mark)
 {
 	struct inode *inode = mark->i.inode;
 
+	BUG_ON(!mutex_is_locked(&mark->group->mark_mutex));
 	assert_spin_locked(&mark->lock);
-	assert_spin_locked(&mark->group->mark_lock);
 
 	spin_lock(&inode->i_lock);
 
@@ -99,8 +99,16 @@ void fsnotify_clear_marks_by_inode(struct inode *inode)
 	spin_unlock(&inode->i_lock);
 
 	list_for_each_entry_safe(mark, lmark, &free_list, i.free_i_list) {
-		fsnotify_destroy_mark(mark);
+		struct fsnotify_group *group;
+
+		spin_lock(&mark->lock);
+		fsnotify_get_group(mark->group);
+		group = mark->group;
+		spin_unlock(&mark->lock);
+
+		fsnotify_destroy_mark(mark, group);
 		fsnotify_put_mark(mark);
+		fsnotify_put_group(group);
 	}
 }
 
@@ -191,8 +199,8 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
 
 	mark->flags |= FSNOTIFY_MARK_FLAG_INODE;
 
+	BUG_ON(!mutex_is_locked(&group->mark_mutex));
 	assert_spin_locked(&mark->lock);
-	assert_spin_locked(&group->mark_lock);
 
 	spin_lock(&inode->i_lock);
 
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
index e3cbd74..871569c 100644
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@ -118,6 +118,7 @@ static int inotify_handle_event(struct fsnotify_group *group,
 
 	fsn_event_priv = &event_priv->fsnotify_event_priv_data;
 
+	fsnotify_get_group(group);
 	fsn_event_priv->group = group;
 	event_priv->wd = wd;
 
@@ -131,7 +132,7 @@ static int inotify_handle_event(struct fsnotify_group *group,
 	}
 
 	if (inode_mark->mask & IN_ONESHOT)
-		fsnotify_destroy_mark(inode_mark);
+		fsnotify_destroy_mark(inode_mark, group);
 
 	return ret;
 }
@@ -210,6 +211,7 @@ void inotify_free_event_priv(struct fsnotify_event_private_data *fsn_event_priv)
 	event_priv = container_of(fsn_event_priv, struct inotify_event_private_data,
 				  fsnotify_event_priv_data);
 
+	fsnotify_put_group(fsn_event_priv->group);
 	kmem_cache_free(event_priv_cachep, event_priv);
 }
 
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index c311dda..228a2c2 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -40,6 +40,7 @@
 #include <linux/wait.h>
 
 #include "inotify.h"
+#include "../fdinfo.h"
 
 #include <asm/ioctls.h>
 
@@ -264,7 +265,7 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
 		ret = -EAGAIN;
 		if (file->f_flags & O_NONBLOCK)
 			break;
-		ret = -EINTR;
+		ret = -ERESTARTSYS;
 		if (signal_pending(current))
 			break;
 
@@ -280,23 +281,17 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
 	return ret;
 }
 
-static int inotify_fasync(int fd, struct file *file, int on)
-{
-	struct fsnotify_group *group = file->private_data;
-
-	return fasync_helper(fd, file, on, &group->inotify_data.fa) >= 0 ? 0 : -EIO;
-}
-
 static int inotify_release(struct inode *ignored, struct file *file)
 {
 	struct fsnotify_group *group = file->private_data;
 
 	pr_debug("%s: group=%p\n", __func__, group);
 
-	fsnotify_clear_marks_by_group(group);
+	if (file->f_flags & FASYNC)
+		fsnotify_fasync(-1, file, 0);
 
 	/* free this group, matching get was inotify_init->fsnotify_obtain_group */
-	fsnotify_put_group(group);
+	fsnotify_destroy_group(group);
 
 	return 0;
 }
@@ -335,9 +330,10 @@ static long inotify_ioctl(struct file *file, unsigned int cmd,
 }
 
 static const struct file_operations inotify_fops = {
+	.show_fdinfo	= inotify_show_fdinfo,
 	.poll		= inotify_poll,
 	.read		= inotify_read,
-	.fasync		= inotify_fasync,
+	.fasync		= fsnotify_fasync,
 	.release	= inotify_release,
 	.unlocked_ioctl	= inotify_ioctl,
 	.compat_ioctl	= inotify_ioctl,
@@ -519,13 +515,13 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
 	struct fsnotify_event_private_data *fsn_event_priv;
 	int ret;
 
+	i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
+
 	ignored_event = fsnotify_create_event(NULL, FS_IN_IGNORED, NULL,
 					      FSNOTIFY_EVENT_NONE, NULL, 0,
 					      GFP_NOFS);
 	if (!ignored_event)
-		return;
-
-	i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
+		goto skip_send_ignore;
 
 	event_priv = kmem_cache_alloc(event_priv_cachep, GFP_NOFS);
 	if (unlikely(!event_priv))
@@ -533,6 +529,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
 
 	fsn_event_priv = &event_priv->fsnotify_event_priv_data;
 
+	fsnotify_get_group(group);
 	fsn_event_priv->group = group;
 	event_priv->wd = i_mark->wd;
 
@@ -546,9 +543,9 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
 	}
 
 skip_send_ignore:
-
 	/* matches the reference taken when the event was created */
-	fsnotify_put_event(ignored_event);
+	if (ignored_event)
+		fsnotify_put_event(ignored_event);
 
 	/* remove this mark from the idr */
 	inotify_remove_from_idr(group, i_mark);
@@ -707,12 +704,11 @@ static struct fsnotify_group *inotify_new_group(unsigned int max_events)
 	spin_lock_init(&group->inotify_data.idr_lock);
 	idr_init(&group->inotify_data.idr);
 	group->inotify_data.last_wd = 0;
-	group->inotify_data.fa = NULL;
 	group->inotify_data.user = get_current_user();
 
 	if (atomic_inc_return(&group->inotify_data.user->inotify_devs) >
 	    inotify_max_user_instances) {
-		fsnotify_put_group(group);
+		fsnotify_destroy_group(group);
 		return ERR_PTR(-EMFILE);
 	}
 
@@ -741,7 +737,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
 	ret = anon_inode_getfd("inotify", &inotify_fops, group,
 				  O_RDONLY | flags);
 	if (ret < 0)
-		fsnotify_put_group(group);
+		fsnotify_destroy_group(group);
 
 	return ret;
 }
@@ -817,7 +813,7 @@ SYSCALL_DEFINE2(inotify_rm_watch, int, fd, __s32, wd)
 
 	ret = 0;
 
-	fsnotify_destroy_mark(&i_mark->fsn_mark);
+	fsnotify_destroy_mark(&i_mark->fsn_mark, group);
 
 	/* match ref taken by inotify_idr_find */
 	fsnotify_put_mark(&i_mark->fsn_mark);
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index f104d56..fc6b49b 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -109,8 +109,11 @@ void fsnotify_get_mark(struct fsnotify_mark *mark)
 
 void fsnotify_put_mark(struct fsnotify_mark *mark)
 {
-	if (atomic_dec_and_test(&mark->refcnt))
+	if (atomic_dec_and_test(&mark->refcnt)) {
+		if (mark->group)
+			fsnotify_put_group(mark->group);
 		mark->free_mark(mark);
+	}
 }
 
 /*
@@ -118,14 +121,14 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
  * The caller had better be holding a reference to this mark so we don't actually
  * do the final put under the mark->lock
  */
-void fsnotify_destroy_mark(struct fsnotify_mark *mark)
+void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark,
+				  struct fsnotify_group *group)
 {
-	struct fsnotify_group *group;
 	struct inode *inode = NULL;
 
-	spin_lock(&mark->lock);
+	BUG_ON(!mutex_is_locked(&group->mark_mutex));
 
-	group = mark->group;
+	spin_lock(&mark->lock);
 
 	/* something else already called this function on this mark */
 	if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) {
@@ -135,8 +138,6 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
 
 	mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE;
 
-	spin_lock(&group->mark_lock);
-
 	if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) {
 		inode = mark->i.inode;
 		fsnotify_destroy_inode_mark(mark);
@@ -147,13 +148,22 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
 
 	list_del_init(&mark->g_list);
 
-	spin_unlock(&group->mark_lock);
 	spin_unlock(&mark->lock);
 
+	if (inode && (mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED))
+		iput(inode);
+	/* release lock temporarily */
+	mutex_unlock(&group->mark_mutex);
+
 	spin_lock(&destroy_lock);
 	list_add(&mark->destroy_list, &destroy_list);
 	spin_unlock(&destroy_lock);
 	wake_up(&destroy_waitq);
+	/*
+	 * We don't necessarily have a ref on mark from caller so the above destroy
+	 * may have actually freed it, unless this group provides a 'freeing_mark'
+	 * function which must be holding a reference.
+	 */
 
 	/*
 	 * Some groups like to know that marks are being freed.  This is a
@@ -175,21 +185,17 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
 	 * is just a lazy update (and could be a perf win...)
 	 */
 
-	if (inode && (mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED))
-		iput(inode);
+	atomic_dec(&group->num_marks);
 
-	/*
-	 * We don't necessarily have a ref on mark from caller so the above iput
-	 * may have already destroyed it.  Don't touch from now on.
-	 */
+	mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
+}
 
-	/*
-	 * it's possible that this group tried to destroy itself, but this
-	 * this mark was simultaneously being freed by inode.  If that's the
-	 * case, we finish freeing the group here.
-	 */
-	if (unlikely(atomic_dec_and_test(&group->num_marks)))
-		fsnotify_final_destroy_group(group);
+void fsnotify_destroy_mark(struct fsnotify_mark *mark,
+			   struct fsnotify_group *group)
+{
+	mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
+	fsnotify_destroy_mark_locked(mark, group);
+	mutex_unlock(&group->mark_mutex);
 }
 
 void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
@@ -214,26 +220,26 @@ void fsnotify_set_mark_ignored_mask_locked(struct fsnotify_mark *mark, __u32 mas
  * These marks may be used for the fsnotify backend to determine which
  * event types should be delivered to which group.
  */
-int fsnotify_add_mark(struct fsnotify_mark *mark,
-		      struct fsnotify_group *group, struct inode *inode,
-		      struct vfsmount *mnt, int allow_dups)
+int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
+			     struct fsnotify_group *group, struct inode *inode,
+			     struct vfsmount *mnt, int allow_dups)
 {
 	int ret = 0;
 
 	BUG_ON(inode && mnt);
 	BUG_ON(!inode && !mnt);
+	BUG_ON(!mutex_is_locked(&group->mark_mutex));
 
 	/*
 	 * LOCKING ORDER!!!!
+	 * group->mark_mutex
 	 * mark->lock
-	 * group->mark_lock
 	 * inode->i_lock
 	 */
 	spin_lock(&mark->lock);
-	spin_lock(&group->mark_lock);
-
 	mark->flags |= FSNOTIFY_MARK_FLAG_ALIVE;
 
+	fsnotify_get_group(group);
 	mark->group = group;
 	list_add(&mark->g_list, &group->marks_list);
 	atomic_inc(&group->num_marks);
@@ -251,11 +257,8 @@ int fsnotify_add_mark(struct fsnotify_mark *mark,
 		BUG();
 	}
 
-	spin_unlock(&group->mark_lock);
-
 	/* this will pin the object if appropriate */
 	fsnotify_set_mark_mask_locked(mark, mark->mask);
-
 	spin_unlock(&mark->lock);
 
 	if (inode)
@@ -265,10 +268,10 @@ int fsnotify_add_mark(struct fsnotify_mark *mark,
 err:
 	mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE;
 	list_del_init(&mark->g_list);
+	fsnotify_put_group(group);
 	mark->group = NULL;
 	atomic_dec(&group->num_marks);
 
-	spin_unlock(&group->mark_lock);
 	spin_unlock(&mark->lock);
 
 	spin_lock(&destroy_lock);
@@ -279,6 +282,16 @@ err:
 	return ret;
 }
 
+int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group,
+		      struct inode *inode, struct vfsmount *mnt, int allow_dups)
+{
+	int ret;
+	mutex_lock(&group->mark_mutex);
+	ret = fsnotify_add_mark_locked(mark, group, inode, mnt, allow_dups);
+	mutex_unlock(&group->mark_mutex);
+	return ret;
+}
+
 /*
  * clear any marks in a group in which mark->flags & flags is true
  */
@@ -286,22 +299,16 @@ void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group,
 					 unsigned int flags)
 {
 	struct fsnotify_mark *lmark, *mark;
-	LIST_HEAD(free_list);
 
-	spin_lock(&group->mark_lock);
+	mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
 	list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) {
 		if (mark->flags & flags) {
-			list_add(&mark->free_g_list, &free_list);
-			list_del_init(&mark->g_list);
 			fsnotify_get_mark(mark);
+			fsnotify_destroy_mark_locked(mark, group);
+			fsnotify_put_mark(mark);
 		}
 	}
-	spin_unlock(&group->mark_lock);
-
-	list_for_each_entry_safe(mark, lmark, &free_list, free_g_list) {
-		fsnotify_destroy_mark(mark);
-		fsnotify_put_mark(mark);
-	}
+	mutex_unlock(&group->mark_mutex);
 }
 
 /*
@@ -317,6 +324,8 @@ void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *ol
 	assert_spin_locked(&old->lock);
 	new->i.inode = old->i.inode;
 	new->m.mnt = old->m.mnt;
+	if (old->group)
+		fsnotify_get_group(old->group);
 	new->group = old->group;
 	new->mask = old->mask;
 	new->free_mark = old->free_mark;
diff --git a/fs/notify/notification.c b/fs/notify/notification.c
index c887b13..7b51b05 100644
--- a/fs/notify/notification.c
+++ b/fs/notify/notification.c
@@ -18,7 +18,7 @@
 
 /*
  * Basic idea behind the notification queue: An fsnotify group (like inotify)
- * sends the userspace notification about events asyncronously some time after
+ * sends the userspace notification about events asynchronously some time after
  * the event happened.  When inotify gets an event it will need to add that
  * event to the group notify queue.  Since a single event might need to be on
  * multiple group's notification queues we can't add the event directly to each
@@ -225,6 +225,7 @@ alloc_holder:
 	mutex_unlock(&group->notification_mutex);
 
 	wake_up(&group->notification_waitq);
+	kill_fasync(&group->fsn_fa, SIGIO, POLL_IN);
 	return return_event;
 }
 
diff --git a/fs/notify/vfsmount_mark.c b/fs/notify/vfsmount_mark.c
index b7b4b0e..4df58b8 100644
--- a/fs/notify/vfsmount_mark.c
+++ b/fs/notify/vfsmount_mark.c
@@ -46,8 +46,16 @@ void fsnotify_clear_marks_by_mount(struct vfsmount *mnt)
 	spin_unlock(&mnt->mnt_root->d_lock);
 
 	list_for_each_entry_safe(mark, lmark, &free_list, m.free_m_list) {
-		fsnotify_destroy_mark(mark);
+		struct fsnotify_group *group;
+
+		spin_lock(&mark->lock);
+		fsnotify_get_group(mark->group);
+		group = mark->group;
+		spin_unlock(&mark->lock);
+
+		fsnotify_destroy_mark(mark, group);
 		fsnotify_put_mark(mark);
+		fsnotify_put_group(group);
 	}
 }
 
@@ -88,8 +96,8 @@ void fsnotify_destroy_vfsmount_mark(struct fsnotify_mark *mark)
 {
 	struct vfsmount *mnt = mark->m.mnt;
 
+	BUG_ON(!mutex_is_locked(&mark->group->mark_mutex));
 	assert_spin_locked(&mark->lock);
-	assert_spin_locked(&mark->group->mark_lock);
 
 	spin_lock(&mnt->mnt_root->d_lock);
 
@@ -151,8 +159,8 @@ int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark,
 
 	mark->flags |= FSNOTIFY_MARK_FLAG_VFSMOUNT;
 
+	BUG_ON(!mutex_is_locked(&group->mark_mutex));
 	assert_spin_locked(&mark->lock);
-	assert_spin_locked(&group->mark_lock);
 
 	spin_lock(&mnt->mnt_root->d_lock);
 
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index f7c648d..ff753bb 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -35,6 +35,7 @@
 #include <linux/time.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/bitmap.h>
 
 #include "heartbeat.h"
 #include "tcp.h"
@@ -282,15 +283,6 @@ struct o2hb_bio_wait_ctxt {
 	int               wc_error;
 };
 
-static int o2hb_pop_count(void *map, int count)
-{
-	int i = -1, pop = 0;
-
-	while ((i = find_next_bit(map, count, i + 1)) < count)
-		pop++;
-	return pop;
-}
-
 static void o2hb_write_timeout(struct work_struct *work)
 {
 	int failed, quorum;
@@ -307,9 +299,9 @@ static void o2hb_write_timeout(struct work_struct *work)
 		spin_lock_irqsave(&o2hb_live_lock, flags);
 		if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
 			set_bit(reg->hr_region_num, o2hb_failed_region_bitmap);
-		failed = o2hb_pop_count(&o2hb_failed_region_bitmap,
+		failed = bitmap_weight(o2hb_failed_region_bitmap,
 					O2NM_MAX_REGIONS);
-		quorum = o2hb_pop_count(&o2hb_quorum_region_bitmap,
+		quorum = bitmap_weight(o2hb_quorum_region_bitmap,
 					O2NM_MAX_REGIONS);
 		spin_unlock_irqrestore(&o2hb_live_lock, flags);
 
@@ -771,7 +763,7 @@ static void o2hb_set_quorum_device(struct o2hb_region *reg)
 	 * If global heartbeat active, unpin all regions if the
 	 * region count > CUT_OFF
 	 */
-	if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
+	if (bitmap_weight(o2hb_quorum_region_bitmap,
 			   O2NM_MAX_REGIONS) > O2HB_PIN_CUT_OFF)
 		o2hb_region_unpin(NULL);
 unlock:
@@ -956,23 +948,9 @@ out:
 	return changed;
 }
 
-/* This could be faster if we just implmented a find_last_bit, but I
- * don't think the circumstances warrant it. */
-static int o2hb_highest_node(unsigned long *nodes,
-			     int numbits)
+static int o2hb_highest_node(unsigned long *nodes, int numbits)
 {
-	int highest, node;
-
-	highest = numbits;
-	node = -1;
-	while ((node = find_next_bit(nodes, numbits, node + 1)) != -1) {
-		if (node >= numbits)
-			break;
-
-		highest = node;
-	}
-
-	return highest;
+	return find_last_bit(nodes, numbits);
 }
 
 static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
@@ -1833,7 +1811,7 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
 	live_threshold = O2HB_LIVE_THRESHOLD;
 	if (o2hb_global_heartbeat_active()) {
 		spin_lock(&o2hb_live_lock);
-		if (o2hb_pop_count(&o2hb_region_bitmap, O2NM_MAX_REGIONS) == 1)
+		if (bitmap_weight(o2hb_region_bitmap, O2NM_MAX_REGIONS) == 1)
 			live_threshold <<= 1;
 		spin_unlock(&o2hb_live_lock);
 	}
@@ -2184,7 +2162,7 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group,
 	if (!o2hb_dependent_users)
 		goto unlock;
 
-	if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
+	if (bitmap_weight(o2hb_quorum_region_bitmap,
 			   O2NM_MAX_REGIONS) <= O2HB_PIN_CUT_OFF)
 		o2hb_region_pin(NULL);
 
@@ -2478,7 +2456,7 @@ static int o2hb_region_inc_user(const char *region_uuid)
 	if (o2hb_dependent_users > 1)
 		goto unlock;
 
-	if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
+	if (bitmap_weight(o2hb_quorum_region_bitmap,
 			   O2NM_MAX_REGIONS) <= O2HB_PIN_CUT_OFF)
 		ret = o2hb_region_pin(NULL);
 
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h
index baa2b9e..2260fb9 100644
--- a/fs/ocfs2/cluster/masklog.h
+++ b/fs/ocfs2/cluster/masklog.h
@@ -199,7 +199,8 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits;
 #define mlog_errno(st) do {						\
 	int _st = (st);							\
 	if (_st != -ERESTARTSYS && _st != -EINTR &&			\
-	    _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC)		\
+	    _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC &&		\
+	    _st != -EDQUOT)						\
 		mlog(ML_ERROR, "status = %lld\n", (long long)_st);	\
 } while (0)
 
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 005261c..3d09a94 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -1888,8 +1888,10 @@ ok:
 			 * up nodes that this node contacted */
 			while ((nn = find_next_bit (mle->response_map, O2NM_MAX_NODES,
 						    nn+1)) < O2NM_MAX_NODES) {
-				if (nn != dlm->node_num && nn != assert->node_idx)
+				if (nn != dlm->node_num && nn != assert->node_idx) {
 					master_request = 1;
+					break;
+				}
 			}
 		}
 		mle->master = assert->node_idx;
@@ -2020,7 +2022,7 @@ int dlm_dispatch_assert_master(struct dlm_ctxt *dlm,
 			       int ignore_higher, u8 request_from, u32 flags)
 {
 	struct dlm_work_item *item;
-	item = kzalloc(sizeof(*item), GFP_NOFS);
+	item = kzalloc(sizeof(*item), GFP_ATOMIC);
 	if (!item)
 		return -ENOMEM;
 
@@ -2357,6 +2359,10 @@ static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,
 
 	assert_spin_locked(&res->spinlock);
 
+	/* delay migration when the lockres is in MIGRATING state */
+	if (res->state & DLM_LOCK_RES_MIGRATING)
+		return 0;
+
 	if (res->owner != dlm->node_num)
 		return 0;
 
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 01ebfd0..15d81ad 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -1887,6 +1887,13 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
 
 		if (ml->type == LKM_NLMODE)
 			goto skip_lvb;
+		
+		/*
+		 * If the lock is in the blocked list it can't have a valid lvb,
+		 * so skip it
+		 */
+		if (ml->list == DLM_BLOCKED_LIST)
+			goto skip_lvb;
 
 		if (!dlm_lvb_is_empty(mres->lvb)) {
 			if (lksb->flags & DLM_LKSB_PUT_LVB) {
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 5a4ee77..dda0898 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2513,18 +2513,15 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
 		ret = sd.num_spliced;
 
 	if (ret > 0) {
-		unsigned long nr_pages;
 		int err;
 
-		nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-
 		err = generic_write_sync(out, *ppos, ret);
 		if (err)
 			ret = err;
 		else
 			*ppos += ret;
 
-		balance_dirty_pages_ratelimited_nr(mapping, nr_pages);
+		balance_dirty_pages_ratelimited(mapping);
 	}
 
 	return ret;
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c
index f1fbb4b..66edce7 100644
--- a/fs/ocfs2/symlink.c
+++ b/fs/ocfs2/symlink.c
@@ -57,7 +57,7 @@
 static int ocfs2_fast_symlink_readpage(struct file *unused, struct page *page)
 {
 	struct inode *inode = page->mapping->host;
-	struct buffer_head *bh;
+	struct buffer_head *bh = NULL;
 	int status = ocfs2_read_inode_block(inode, &bh);
 	struct ocfs2_dinode *fe;
 	const char *link;
diff --git a/fs/open.c b/fs/open.c
index 59071f5..182d866 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -435,7 +435,7 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename)
 		goto dput_and_out;
 
 	error = -EPERM;
-	if (!capable(CAP_SYS_CHROOT))
+	if (!nsown_capable(CAP_SYS_CHROOT))
 		goto dput_and_out;
 	error = security_path_chroot(&path);
 	if (error)
diff --git a/fs/pnode.h b/fs/pnode.h
index 65c6097..19b853a3 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -22,6 +22,7 @@
 #define CL_COPY_ALL 		0x04
 #define CL_MAKE_SHARED 		0x08
 #define CL_PRIVATE 		0x10
+#define CL_SHARED_TO_SLAVE	0x20
 
 static inline void set_mnt_shared(struct mount *mnt)
 {
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index 99349ef..981b056 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -21,6 +21,7 @@ proc-y	+= uptime.o
 proc-y	+= version.o
 proc-y	+= softirqs.o
 proc-y	+= namespaces.o
+proc-y	+= self.o
 proc-$(CONFIG_PROC_SYSCTL)	+= proc_sysctl.o
 proc-$(CONFIG_NET)		+= proc_net.o
 proc-$(CONFIG_PROC_KCORE)	+= kcore.o
diff --git a/fs/proc/array.c b/fs/proc/array.c
index c1c207c..d3b8b71 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -162,7 +162,7 @@ static inline const char *get_task_state(struct task_struct *tsk)
 static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
 				struct pid *pid, struct task_struct *p)
 {
-	struct user_namespace *user_ns = current_user_ns();
+	struct user_namespace *user_ns = seq_user_ns(m);
 	struct group_info *group_info;
 	int g;
 	struct fdtable *fdt = NULL;
@@ -212,7 +212,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
 	group_info = cred->group_info;
 	task_unlock(p);
 
-	for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++)
+	for (g = 0; g < group_info->ngroups; g++)
 		seq_printf(m, "%d ",
 			   from_kgid_munged(user_ns, GROUP_AT(group_info, g)));
 	put_cred(cred);
@@ -220,7 +220,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
 	seq_putc(m, '\n');
 }
 
-static void render_sigset_t(struct seq_file *m, const char *header,
+void render_sigset_t(struct seq_file *m, const char *header,
 				sigset_t *set)
 {
 	int i;
@@ -308,6 +308,10 @@ static void render_cap_t(struct seq_file *m, const char *header,
 	seq_putc(m, '\n');
 }
 
+/* Remove non-existent capabilities */
+#define NORM_CAPS(v) (v.cap[CAP_TO_INDEX(CAP_LAST_CAP)] &= \
+				CAP_TO_MASK(CAP_LAST_CAP + 1) - 1)
+
 static inline void task_cap(struct seq_file *m, struct task_struct *p)
 {
 	const struct cred *cred;
@@ -321,12 +325,24 @@ static inline void task_cap(struct seq_file *m, struct task_struct *p)
 	cap_bset	= cred->cap_bset;
 	rcu_read_unlock();
 
+	NORM_CAPS(cap_inheritable);
+	NORM_CAPS(cap_permitted);
+	NORM_CAPS(cap_effective);
+	NORM_CAPS(cap_bset);
+
 	render_cap_t(m, "CapInh:\t", &cap_inheritable);
 	render_cap_t(m, "CapPrm:\t", &cap_permitted);
 	render_cap_t(m, "CapEff:\t", &cap_effective);
 	render_cap_t(m, "CapBnd:\t", &cap_bset);
 }
 
+static inline void task_seccomp(struct seq_file *m, struct task_struct *p)
+{
+#ifdef CONFIG_SECCOMP
+	seq_printf(m, "Seccomp:\t%d\n", p->seccomp.mode);
+#endif
+}
+
 static inline void task_context_switch_counts(struct seq_file *m,
 						struct task_struct *p)
 {
@@ -360,6 +376,7 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
 	}
 	task_sig(m, task);
 	task_cap(m, task);
+	task_seccomp(m, task);
 	task_cpus_allowed(m, task);
 	cpuset_task_status_allowed(m, task);
 	task_context_switch_counts(m, task);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 3c231ad..a512a1f 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -985,7 +985,7 @@ static ssize_t oom_score_adj_read(struct file *file, char __user *buf,
 {
 	struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
 	char buffer[PROC_NUMBUF];
-	int oom_score_adj = OOM_SCORE_ADJ_MIN;
+	short oom_score_adj = OOM_SCORE_ADJ_MIN;
 	unsigned long flags;
 	size_t len;
 
@@ -996,7 +996,7 @@ static ssize_t oom_score_adj_read(struct file *file, char __user *buf,
 		unlock_task_sighand(task, &flags);
 	}
 	put_task_struct(task);
-	len = snprintf(buffer, sizeof(buffer), "%d\n", oom_score_adj);
+	len = snprintf(buffer, sizeof(buffer), "%hd\n", oom_score_adj);
 	return simple_read_from_buffer(buf, count, ppos, buffer, len);
 }
 
@@ -1043,15 +1043,15 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf,
 		goto err_task_lock;
 	}
 
-	if (oom_score_adj < task->signal->oom_score_adj_min &&
+	if ((short)oom_score_adj < task->signal->oom_score_adj_min &&
 			!capable(CAP_SYS_RESOURCE)) {
 		err = -EACCES;
 		goto err_sighand;
 	}
 
-	task->signal->oom_score_adj = oom_score_adj;
+	task->signal->oom_score_adj = (short)oom_score_adj;
 	if (has_capability_noaudit(current, CAP_SYS_RESOURCE))
-		task->signal->oom_score_adj_min = oom_score_adj;
+		task->signal->oom_score_adj_min = (short)oom_score_adj;
 	trace_oom_score_adj_update(task);
 
 err_sighand:
@@ -1272,81 +1272,6 @@ static const struct file_operations proc_pid_sched_operations = {
 
 #endif
 
-#ifdef CONFIG_SCHED_AUTOGROUP
-/*
- * Print out autogroup related information:
- */
-static int sched_autogroup_show(struct seq_file *m, void *v)
-{
-	struct inode *inode = m->private;
-	struct task_struct *p;
-
-	p = get_proc_task(inode);
-	if (!p)
-		return -ESRCH;
-	proc_sched_autogroup_show_task(p, m);
-
-	put_task_struct(p);
-
-	return 0;
-}
-
-static ssize_t
-sched_autogroup_write(struct file *file, const char __user *buf,
-	    size_t count, loff_t *offset)
-{
-	struct inode *inode = file->f_path.dentry->d_inode;
-	struct task_struct *p;
-	char buffer[PROC_NUMBUF];
-	int nice;
-	int err;
-
-	memset(buffer, 0, sizeof(buffer));
-	if (count > sizeof(buffer) - 1)
-		count = sizeof(buffer) - 1;
-	if (copy_from_user(buffer, buf, count))
-		return -EFAULT;
-
-	err = kstrtoint(strstrip(buffer), 0, &nice);
-	if (err < 0)
-		return err;
-
-	p = get_proc_task(inode);
-	if (!p)
-		return -ESRCH;
-
-	err = proc_sched_autogroup_set_nice(p, nice);
-	if (err)
-		count = err;
-
-	put_task_struct(p);
-
-	return count;
-}
-
-static int sched_autogroup_open(struct inode *inode, struct file *filp)
-{
-	int ret;
-
-	ret = single_open(filp, sched_autogroup_show, NULL);
-	if (!ret) {
-		struct seq_file *m = filp->private_data;
-
-		m->private = inode;
-	}
-	return ret;
-}
-
-static const struct file_operations proc_pid_sched_autogroup_operations = {
-	.open		= sched_autogroup_open,
-	.read		= seq_read,
-	.write		= sched_autogroup_write,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-#endif /* CONFIG_SCHED_AUTOGROUP */
-
 static ssize_t comm_write(struct file *file, const char __user *buf,
 				size_t count, loff_t *offset)
 {
@@ -1718,7 +1643,7 @@ static int map_files_d_revalidate(struct dentry *dentry, unsigned int flags)
 		return -ECHILD;
 
 	if (!capable(CAP_SYS_ADMIN)) {
-		status = -EACCES;
+		status = -EPERM;
 		goto out_notask;
 	}
 
@@ -1851,7 +1776,7 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
 	struct dentry *result;
 	struct mm_struct *mm;
 
-	result = ERR_PTR(-EACCES);
+	result = ERR_PTR(-EPERM);
 	if (!capable(CAP_SYS_ADMIN))
 		goto out;
 
@@ -1877,8 +1802,9 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
 	if (!vma)
 		goto out_no_vma;
 
-	result = proc_map_files_instantiate(dir, dentry, task,
-			(void *)(unsigned long)vma->vm_file->f_mode);
+	if (vma->vm_file)
+		result = proc_map_files_instantiate(dir, dentry, task,
+				(void *)(unsigned long)vma->vm_file->f_mode);
 
 out_no_vma:
 	up_read(&mm->mmap_sem);
@@ -1906,7 +1832,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir)
 	ino_t ino;
 	int ret;
 
-	ret = -EACCES;
+	ret = -EPERM;
 	if (!capable(CAP_SYS_ADMIN))
 		goto out;
 
@@ -2344,146 +2270,6 @@ static const struct file_operations proc_coredump_filter_operations = {
 };
 #endif
 
-/*
- * /proc/self:
- */
-static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
-			      int buflen)
-{
-	struct pid_namespace *ns = dentry->d_sb->s_fs_info;
-	pid_t tgid = task_tgid_nr_ns(current, ns);
-	char tmp[PROC_NUMBUF];
-	if (!tgid)
-		return -ENOENT;
-	sprintf(tmp, "%d", tgid);
-	return vfs_readlink(dentry,buffer,buflen,tmp);
-}
-
-static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
-	struct pid_namespace *ns = dentry->d_sb->s_fs_info;
-	pid_t tgid = task_tgid_nr_ns(current, ns);
-	char *name = ERR_PTR(-ENOENT);
-	if (tgid) {
-		/* 11 for max length of signed int in decimal + NULL term */
-		name = kmalloc(12, GFP_KERNEL);
-		if (!name)
-			name = ERR_PTR(-ENOMEM);
-		else
-			sprintf(name, "%d", tgid);
-	}
-	nd_set_link(nd, name);
-	return NULL;
-}
-
-static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd,
-				void *cookie)
-{
-	char *s = nd_get_link(nd);
-	if (!IS_ERR(s))
-		kfree(s);
-}
-
-static const struct inode_operations proc_self_inode_operations = {
-	.readlink	= proc_self_readlink,
-	.follow_link	= proc_self_follow_link,
-	.put_link	= proc_self_put_link,
-};
-
-/*
- * proc base
- *
- * These are the directory entries in the root directory of /proc
- * that properly belong to the /proc filesystem, as they describe
- * describe something that is process related.
- */
-static const struct pid_entry proc_base_stuff[] = {
-	NOD("self", S_IFLNK|S_IRWXUGO,
-		&proc_self_inode_operations, NULL, {}),
-};
-
-static struct dentry *proc_base_instantiate(struct inode *dir,
-	struct dentry *dentry, struct task_struct *task, const void *ptr)
-{
-	const struct pid_entry *p = ptr;
-	struct inode *inode;
-	struct proc_inode *ei;
-	struct dentry *error;
-
-	/* Allocate the inode */
-	error = ERR_PTR(-ENOMEM);
-	inode = new_inode(dir->i_sb);
-	if (!inode)
-		goto out;
-
-	/* Initialize the inode */
-	ei = PROC_I(inode);
-	inode->i_ino = get_next_ino();
-	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-
-	/*
-	 * grab the reference to the task.
-	 */
-	ei->pid = get_task_pid(task, PIDTYPE_PID);
-	if (!ei->pid)
-		goto out_iput;
-
-	inode->i_mode = p->mode;
-	if (S_ISDIR(inode->i_mode))
-		set_nlink(inode, 2);
-	if (S_ISLNK(inode->i_mode))
-		inode->i_size = 64;
-	if (p->iop)
-		inode->i_op = p->iop;
-	if (p->fop)
-		inode->i_fop = p->fop;
-	ei->op = p->op;
-	d_add(dentry, inode);
-	error = NULL;
-out:
-	return error;
-out_iput:
-	iput(inode);
-	goto out;
-}
-
-static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
-{
-	struct dentry *error;
-	struct task_struct *task = get_proc_task(dir);
-	const struct pid_entry *p, *last;
-
-	error = ERR_PTR(-ENOENT);
-
-	if (!task)
-		goto out_no_task;
-
-	/* Lookup the directory entry */
-	last = &proc_base_stuff[ARRAY_SIZE(proc_base_stuff) - 1];
-	for (p = proc_base_stuff; p <= last; p++) {
-		if (p->len != dentry->d_name.len)
-			continue;
-		if (!memcmp(dentry->d_name.name, p->name, p->len))
-			break;
-	}
-	if (p > last)
-		goto out;
-
-	error = proc_base_instantiate(dir, dentry, task, p);
-
-out:
-	put_task_struct(task);
-out_no_task:
-	return error;
-}
-
-static int proc_base_fill_cache(struct file *filp, void *dirent,
-	filldir_t filldir, struct task_struct *task, const struct pid_entry *p)
-{
-	return proc_fill_cache(filp, dirent, filldir, p->name, p->len,
-				proc_base_instantiate, task, p);
-}
-
 #ifdef CONFIG_TASK_IO_ACCOUNTING
 static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
 {
@@ -2657,9 +2443,6 @@ static const struct pid_entry tgid_base_stuff[] = {
 #ifdef CONFIG_SCHED_DEBUG
 	REG("sched",      S_IRUGO|S_IWUSR, proc_pid_sched_operations),
 #endif
-#ifdef CONFIG_SCHED_AUTOGROUP
-	REG("autogroup",  S_IRUGO|S_IWUSR, proc_pid_sched_autogroup_operations),
-#endif
 	REG("comm",      S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
 #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
 	INF("syscall",    S_IRUGO, proc_pid_syscall),
@@ -2838,10 +2621,6 @@ void proc_flush_task(struct task_struct *task)
 		proc_flush_task_mnt(upid->ns->proc_mnt, upid->nr,
 					tgid->numbers[i].nr);
 	}
-
-	upid = &pid->numbers[pid->level];
-	if (upid->nr == 1)
-		pid_ns_release_proc(upid->ns);
 }
 
 static struct dentry *proc_pid_instantiate(struct inode *dir,
@@ -2875,15 +2654,11 @@ out:
 
 struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
 {
-	struct dentry *result;
+	struct dentry *result = NULL;
 	struct task_struct *task;
 	unsigned tgid;
 	struct pid_namespace *ns;
 
-	result = proc_base_lookup(dir, dentry);
-	if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT)
-		goto out;
-
 	tgid = name_to_int(dentry);
 	if (tgid == ~0U)
 		goto out;
@@ -2946,7 +2721,7 @@ retry:
 	return iter;
 }
 
-#define TGID_OFFSET (FIRST_PROCESS_ENTRY + ARRAY_SIZE(proc_base_stuff))
+#define TGID_OFFSET (FIRST_PROCESS_ENTRY)
 
 static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
 	struct tgid_iter iter)
@@ -2966,25 +2741,12 @@ static int fake_filldir(void *buf, const char *name, int namelen,
 /* for the /proc/ directory itself, after non-process stuff has been done */
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
-	unsigned int nr;
-	struct task_struct *reaper;
 	struct tgid_iter iter;
 	struct pid_namespace *ns;
 	filldir_t __filldir;
 
 	if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET)
-		goto out_no_task;
-	nr = filp->f_pos - FIRST_PROCESS_ENTRY;
-
-	reaper = get_proc_task(filp->f_path.dentry->d_inode);
-	if (!reaper)
-		goto out_no_task;
-
-	for (; nr < ARRAY_SIZE(proc_base_stuff); filp->f_pos++, nr++) {
-		const struct pid_entry *p = &proc_base_stuff[nr];
-		if (proc_base_fill_cache(filp, dirent, filldir, reaper, p) < 0)
-			goto out;
-	}
+		goto out;
 
 	ns = filp->f_dentry->d_sb->s_fs_info;
 	iter.task = NULL;
@@ -3005,8 +2767,6 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
 	}
 	filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET;
 out:
-	put_task_struct(reaper);
-out_no_task:
 	return 0;
 }
 
diff --git a/fs/proc/fd.c b/fs/proc/fd.c
index f28a875..d7a4a28 100644
--- a/fs/proc/fd.c
+++ b/fs/proc/fd.c
@@ -50,6 +50,8 @@ static int seq_show(struct seq_file *m, void *v)
 	if (!ret) {
                 seq_printf(m, "pos:\t%lli\nflags:\t0%o\n",
 			   (long long)file->f_pos, f_flags);
+		if (file->f_op->show_fdinfo)
+			ret = file->f_op->show_fdinfo(m, file);
 		fput(file);
 	}
 
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 0d80cef..7b3ae3c 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -350,14 +350,14 @@ static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */
  * Return an inode number between PROC_DYNAMIC_FIRST and
  * 0xffffffff, or zero on failure.
  */
-static unsigned int get_inode_number(void)
+int proc_alloc_inum(unsigned int *inum)
 {
 	unsigned int i;
 	int error;
 
 retry:
-	if (ida_pre_get(&proc_inum_ida, GFP_KERNEL) == 0)
-		return 0;
+	if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL))
+		return -ENOMEM;
 
 	spin_lock(&proc_inum_lock);
 	error = ida_get_new(&proc_inum_ida, &i);
@@ -365,18 +365,19 @@ retry:
 	if (error == -EAGAIN)
 		goto retry;
 	else if (error)
-		return 0;
+		return error;
 
 	if (i > UINT_MAX - PROC_DYNAMIC_FIRST) {
 		spin_lock(&proc_inum_lock);
 		ida_remove(&proc_inum_ida, i);
 		spin_unlock(&proc_inum_lock);
-		return 0;
+		return -ENOSPC;
 	}
-	return PROC_DYNAMIC_FIRST + i;
+	*inum = PROC_DYNAMIC_FIRST + i;
+	return 0;
 }
 
-static void release_inode_number(unsigned int inum)
+void proc_free_inum(unsigned int inum)
 {
 	spin_lock(&proc_inum_lock);
 	ida_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
@@ -554,13 +555,12 @@ static const struct inode_operations proc_dir_inode_operations = {
 
 static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
 {
-	unsigned int i;
 	struct proc_dir_entry *tmp;
+	int ret;
 	
-	i = get_inode_number();
-	if (i == 0)
-		return -EAGAIN;
-	dp->low_ino = i;
+	ret = proc_alloc_inum(&dp->low_ino);
+	if (ret)
+		return ret;
 
 	if (S_ISDIR(dp->mode)) {
 		if (dp->proc_iops == NULL) {
@@ -764,7 +764,7 @@ EXPORT_SYMBOL(proc_create_data);
 
 static void free_proc_entry(struct proc_dir_entry *de)
 {
-	release_inode_number(de->low_ino);
+	proc_free_inum(de->low_ino);
 
 	if (S_ISLNK(de->mode))
 		kfree(de->data);
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 3b22bbd..439ae688 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -31,6 +31,7 @@ static void proc_evict_inode(struct inode *inode)
 	struct proc_dir_entry *de;
 	struct ctl_table_header *head;
 	const struct proc_ns_operations *ns_ops;
+	void *ns;
 
 	truncate_inode_pages(&inode->i_data, 0);
 	clear_inode(inode);
@@ -49,8 +50,9 @@ static void proc_evict_inode(struct inode *inode)
 	}
 	/* Release any associated namespace */
 	ns_ops = PROC_I(inode)->ns_ops;
-	if (ns_ops && ns_ops->put)
-		ns_ops->put(PROC_I(inode)->ns);
+	ns = PROC_I(inode)->ns;
+	if (ns_ops && ns)
+		ns_ops->put(ns);
 }
 
 static struct kmem_cache * proc_inode_cachep;
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 43973b0..252544c 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -15,6 +15,7 @@ struct  ctl_table_header;
 struct  mempolicy;
 
 extern struct proc_dir_entry proc_root;
+extern void proc_self_init(void);
 #ifdef CONFIG_PROC_SYSCTL
 extern int proc_sys_init(void);
 extern void sysctl_head_put(struct ctl_table_header *head);
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index 86c67ee..e96d4f1 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -249,7 +249,7 @@ static int kcore_update_ram(void)
 	/* Not inialized....update now */
 	/* find out "max pfn" */
 	end_pfn = 0;
-	for_each_node_state(nid, N_HIGH_MEMORY) {
+	for_each_node_state(nid, N_MEMORY) {
 		unsigned long node_end;
 		node_end  = NODE_DATA(nid)->node_start_pfn +
 			NODE_DATA(nid)->node_spanned_pages;
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index b178ed7..b7a4719 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -11,6 +11,7 @@
 #include <net/net_namespace.h>
 #include <linux/ipc_namespace.h>
 #include <linux/pid_namespace.h>
+#include <linux/user_namespace.h>
 #include "internal.h"
 
 
@@ -24,12 +25,168 @@ static const struct proc_ns_operations *ns_entries[] = {
 #ifdef CONFIG_IPC_NS
 	&ipcns_operations,
 #endif
+#ifdef CONFIG_PID_NS
+	&pidns_operations,
+#endif
+#ifdef CONFIG_USER_NS
+	&userns_operations,
+#endif
+	&mntns_operations,
 };
 
 static const struct file_operations ns_file_operations = {
 	.llseek		= no_llseek,
 };
 
+static const struct inode_operations ns_inode_operations = {
+	.setattr	= proc_setattr,
+};
+
+static int ns_delete_dentry(const struct dentry *dentry)
+{
+	/* Don't cache namespace inodes when not in use */
+	return 1;
+}
+
+static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
+{
+	struct inode *inode = dentry->d_inode;
+	const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
+
+	return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
+		ns_ops->name, inode->i_ino);
+}
+
+const struct dentry_operations ns_dentry_operations =
+{
+	.d_delete	= ns_delete_dentry,
+	.d_dname	= ns_dname,
+};
+
+static struct dentry *proc_ns_get_dentry(struct super_block *sb,
+	struct task_struct *task, const struct proc_ns_operations *ns_ops)
+{
+	struct dentry *dentry, *result;
+	struct inode *inode;
+	struct proc_inode *ei;
+	struct qstr qname = { .name = "", };
+	void *ns;
+
+	ns = ns_ops->get(task);
+	if (!ns)
+		return ERR_PTR(-ENOENT);
+
+	dentry = d_alloc_pseudo(sb, &qname);
+	if (!dentry) {
+		ns_ops->put(ns);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	inode = iget_locked(sb, ns_ops->inum(ns));
+	if (!inode) {
+		dput(dentry);
+		ns_ops->put(ns);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	ei = PROC_I(inode);
+	if (inode->i_state & I_NEW) {
+		inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+		inode->i_op = &ns_inode_operations;
+		inode->i_mode = S_IFREG | S_IRUGO;
+		inode->i_fop = &ns_file_operations;
+		ei->ns_ops = ns_ops;
+		ei->ns = ns;
+		unlock_new_inode(inode);
+	} else {
+		ns_ops->put(ns);
+	}
+
+	d_set_d_op(dentry, &ns_dentry_operations);
+	result = d_instantiate_unique(dentry, inode);
+	if (result) {
+		dput(dentry);
+		dentry = result;
+	}
+
+	return dentry;
+}
+
+static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+	struct inode *inode = dentry->d_inode;
+	struct super_block *sb = inode->i_sb;
+	struct proc_inode *ei = PROC_I(inode);
+	struct task_struct *task;
+	struct dentry *ns_dentry;
+	void *error = ERR_PTR(-EACCES);
+
+	task = get_proc_task(inode);
+	if (!task)
+		goto out;
+
+	if (!ptrace_may_access(task, PTRACE_MODE_READ))
+		goto out_put_task;
+
+	ns_dentry = proc_ns_get_dentry(sb, task, ei->ns_ops);
+	if (IS_ERR(ns_dentry)) {
+		error = ERR_CAST(ns_dentry);
+		goto out_put_task;
+	}
+
+	dput(nd->path.dentry);
+	nd->path.dentry = ns_dentry;
+	error = NULL;
+
+out_put_task:
+	put_task_struct(task);
+out:
+	return error;
+}
+
+static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen)
+{
+	struct inode *inode = dentry->d_inode;
+	struct proc_inode *ei = PROC_I(inode);
+	const struct proc_ns_operations *ns_ops = ei->ns_ops;
+	struct task_struct *task;
+	void *ns;
+	char name[50];
+	int len = -EACCES;
+
+	task = get_proc_task(inode);
+	if (!task)
+		goto out;
+
+	if (!ptrace_may_access(task, PTRACE_MODE_READ))
+		goto out_put_task;
+
+	len = -ENOENT;
+	ns = ns_ops->get(task);
+	if (!ns)
+		goto out_put_task;
+
+	snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns));
+	len = strlen(name);
+
+	if (len > buflen)
+		len = buflen;
+	if (copy_to_user(buffer, name, len))
+		len = -EFAULT;
+
+	ns_ops->put(ns);
+out_put_task:
+	put_task_struct(task);
+out:
+	return len;
+}
+
+static const struct inode_operations proc_ns_link_inode_operations = {
+	.readlink	= proc_ns_readlink,
+	.follow_link	= proc_ns_follow_link,
+	.setattr	= proc_setattr,
+};
+
 static struct dentry *proc_ns_instantiate(struct inode *dir,
 	struct dentry *dentry, struct task_struct *task, const void *ptr)
 {
@@ -37,21 +194,15 @@ static struct dentry *proc_ns_instantiate(struct inode *dir,
 	struct inode *inode;
 	struct proc_inode *ei;
 	struct dentry *error = ERR_PTR(-ENOENT);
-	void *ns;
 
 	inode = proc_pid_make_inode(dir->i_sb, task);
 	if (!inode)
 		goto out;
 
-	ns = ns_ops->get(task);
-	if (!ns)
-		goto out_iput;
-
 	ei = PROC_I(inode);
-	inode->i_mode = S_IFREG|S_IRUSR;
-	inode->i_fop  = &ns_file_operations;
-	ei->ns_ops    = ns_ops;
-	ei->ns	      = ns;
+	inode->i_mode = S_IFLNK|S_IRWXUGO;
+	inode->i_op = &proc_ns_link_inode_operations;
+	ei->ns_ops = ns_ops;
 
 	d_set_d_op(dentry, &pid_dentry_operations);
 	d_add(dentry, inode);
@@ -60,9 +211,6 @@ static struct dentry *proc_ns_instantiate(struct inode *dir,
 		error = NULL;
 out:
 	return error;
-out_iput:
-	iput(inode);
-	goto out;
 }
 
 static int proc_ns_fill_cache(struct file *filp, void *dirent,
@@ -89,10 +237,6 @@ static int proc_ns_dir_readdir(struct file *filp, void *dirent,
 	if (!task)
 		goto out_no_task;
 
-	ret = -EPERM;
-	if (!ptrace_may_access(task, PTRACE_MODE_READ))
-		goto out;
-
 	ret = 0;
 	i = filp->f_pos;
 	switch (i) {
@@ -152,10 +296,6 @@ static struct dentry *proc_ns_dir_lookup(struct inode *dir,
 	if (!task)
 		goto out_no_task;
 
-	error = ERR_PTR(-EPERM);
-	if (!ptrace_may_access(task, PTRACE_MODE_READ))
-		goto out;
-
 	last = &ns_entries[ARRAY_SIZE(ns_entries)];
 	for (entry = ns_entries; entry < last; entry++) {
 		if (strlen((*entry)->name) != len)
@@ -163,7 +303,6 @@ static struct dentry *proc_ns_dir_lookup(struct inode *dir,
 		if (!memcmp(dentry->d_name.name, (*entry)->name, len))
 			break;
 	}
-	error = ERR_PTR(-ENOENT);
 	if (entry == last)
 		goto out;
 
@@ -198,3 +337,7 @@ out_invalid:
 	return ERR_PTR(-EINVAL);
 }
 
+bool proc_ns_inode(struct inode *inode)
+{
+	return inode->i_fop == &ns_file_operations;
+}
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index df7dd08..de20ec4 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -195,11 +195,7 @@ void proc_device_tree_add_node(struct device_node *np,
 	set_node_proc_entry(np, de);
 	for (child = NULL; (child = of_get_next_child(np, child));) {
 		/* Use everything after the last slash, or the full name */
-		p = strrchr(child->full_name, '/');
-		if (!p)
-			p = child->full_name;
-		else
-			++p;
+		p = kbasename(child->full_name);
 
 		if (duplicate_name(de, p))
 			p = fixup_name(np, de, p);
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index a781bdf..701580d 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -378,12 +378,13 @@ static int test_perm(int mode, int op)
 	return -EACCES;
 }
 
-static int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
+static int sysctl_perm(struct ctl_table_header *head, struct ctl_table *table, int op)
 {
+	struct ctl_table_root *root = head->root;
 	int mode;
 
 	if (root->permissions)
-		mode = root->permissions(root, current->nsproxy, table);
+		mode = root->permissions(head, table);
 	else
 		mode = table->mode;
 
@@ -491,7 +492,7 @@ static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,
 	 * and won't be until we finish.
 	 */
 	error = -EPERM;
-	if (sysctl_perm(head->root, table, write ? MAY_WRITE : MAY_READ))
+	if (sysctl_perm(head, table, write ? MAY_WRITE : MAY_READ))
 		goto out;
 
 	/* if that can happen at all, it should be -EINVAL, not -EISDIR */
@@ -717,7 +718,7 @@ static int proc_sys_permission(struct inode *inode, int mask)
 	if (!table) /* global root - r-xr-xr-x */
 		error = mask & MAY_WRITE ? -EACCES : 0;
 	else /* Use the permissions on the sysctl table entry */
-		error = sysctl_perm(head->root, table, mask & ~MAY_NOT_BLOCK);
+		error = sysctl_perm(head, table, mask & ~MAY_NOT_BLOCK);
 
 	sysctl_head_finish(head);
 	return error;
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 9889a92..c6e9fac 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -100,14 +100,13 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
 	int err;
 	struct super_block *sb;
 	struct pid_namespace *ns;
-	struct proc_inode *ei;
 	char *options;
 
 	if (flags & MS_KERNMOUNT) {
 		ns = (struct pid_namespace *)data;
 		options = NULL;
 	} else {
-		ns = current->nsproxy->pid_ns;
+		ns = task_active_pid_ns(current);
 		options = data;
 	}
 
@@ -130,13 +129,6 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
 		sb->s_flags |= MS_ACTIVE;
 	}
 
-	ei = PROC_I(sb->s_root->d_inode);
-	if (!ei->pid) {
-		rcu_read_lock();
-		ei->pid = get_pid(find_pid_ns(1, ns));
-		rcu_read_unlock();
-	}
-
 	return dget(sb->s_root);
 }
 
@@ -153,6 +145,7 @@ static struct file_system_type proc_fs_type = {
 	.name		= "proc",
 	.mount		= proc_mount,
 	.kill_sb	= proc_kill_sb,
+	.fs_flags	= FS_USERNS_MOUNT,
 };
 
 void __init proc_root_init(void)
@@ -163,12 +156,8 @@ void __init proc_root_init(void)
 	err = register_filesystem(&proc_fs_type);
 	if (err)
 		return;
-	err = pid_ns_prepare_proc(&init_pid_ns);
-	if (err) {
-		unregister_filesystem(&proc_fs_type);
-		return;
-	}
 
+	proc_self_init();
 	proc_symlink("mounts", NULL, "self/mounts");
 
 	proc_net_init();
diff --git a/fs/proc/self.c b/fs/proc/self.c
new file mode 100644
index 0000000..aa5cc3b
--- /dev/null
+++ b/fs/proc/self.c
@@ -0,0 +1,59 @@
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/namei.h>
+
+/*
+ * /proc/self:
+ */
+static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
+			      int buflen)
+{
+	struct pid_namespace *ns = dentry->d_sb->s_fs_info;
+	pid_t tgid = task_tgid_nr_ns(current, ns);
+	char tmp[PROC_NUMBUF];
+	if (!tgid)
+		return -ENOENT;
+	sprintf(tmp, "%d", tgid);
+	return vfs_readlink(dentry,buffer,buflen,tmp);
+}
+
+static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+	struct pid_namespace *ns = dentry->d_sb->s_fs_info;
+	pid_t tgid = task_tgid_nr_ns(current, ns);
+	char *name = ERR_PTR(-ENOENT);
+	if (tgid) {
+		/* 11 for max length of signed int in decimal + NULL term */
+		name = kmalloc(12, GFP_KERNEL);
+		if (!name)
+			name = ERR_PTR(-ENOMEM);
+		else
+			sprintf(name, "%d", tgid);
+	}
+	nd_set_link(nd, name);
+	return NULL;
+}
+
+static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd,
+				void *cookie)
+{
+	char *s = nd_get_link(nd);
+	if (!IS_ERR(s))
+		kfree(s);
+}
+
+static const struct inode_operations proc_self_inode_operations = {
+	.readlink	= proc_self_readlink,
+	.follow_link	= proc_self_follow_link,
+	.put_link	= proc_self_put_link,
+};
+
+void __init proc_self_init(void)
+{
+	struct proc_dir_entry *proc_self_symlink;
+	mode_t mode;
+
+	mode = S_IFLNK | S_IRWXUGO;
+	proc_self_symlink = proc_create("self", mode, NULL, NULL );
+	proc_self_symlink->proc_iops = &proc_self_inode_operations;
+}
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 90c63f9..448455b 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -526,6 +526,57 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
 	return 0;
 }
 
+static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
+{
+	/*
+	 * Don't forget to update Documentation/ on changes.
+	 */
+	static const char mnemonics[BITS_PER_LONG][2] = {
+		/*
+		 * In case if we meet a flag we don't know about.
+		 */
+		[0 ... (BITS_PER_LONG-1)] = "??",
+
+		[ilog2(VM_READ)]	= "rd",
+		[ilog2(VM_WRITE)]	= "wr",
+		[ilog2(VM_EXEC)]	= "ex",
+		[ilog2(VM_SHARED)]	= "sh",
+		[ilog2(VM_MAYREAD)]	= "mr",
+		[ilog2(VM_MAYWRITE)]	= "mw",
+		[ilog2(VM_MAYEXEC)]	= "me",
+		[ilog2(VM_MAYSHARE)]	= "ms",
+		[ilog2(VM_GROWSDOWN)]	= "gd",
+		[ilog2(VM_PFNMAP)]	= "pf",
+		[ilog2(VM_DENYWRITE)]	= "dw",
+		[ilog2(VM_LOCKED)]	= "lo",
+		[ilog2(VM_IO)]		= "io",
+		[ilog2(VM_SEQ_READ)]	= "sr",
+		[ilog2(VM_RAND_READ)]	= "rr",
+		[ilog2(VM_DONTCOPY)]	= "dc",
+		[ilog2(VM_DONTEXPAND)]	= "de",
+		[ilog2(VM_ACCOUNT)]	= "ac",
+		[ilog2(VM_NORESERVE)]	= "nr",
+		[ilog2(VM_HUGETLB)]	= "ht",
+		[ilog2(VM_NONLINEAR)]	= "nl",
+		[ilog2(VM_ARCH_1)]	= "ar",
+		[ilog2(VM_DONTDUMP)]	= "dd",
+		[ilog2(VM_MIXEDMAP)]	= "mm",
+		[ilog2(VM_HUGEPAGE)]	= "hg",
+		[ilog2(VM_NOHUGEPAGE)]	= "nh",
+		[ilog2(VM_MERGEABLE)]	= "mg",
+	};
+	size_t i;
+
+	seq_puts(m, "VmFlags: ");
+	for (i = 0; i < BITS_PER_LONG; i++) {
+		if (vma->vm_flags & (1UL << i)) {
+			seq_printf(m, "%c%c ",
+				   mnemonics[i][0], mnemonics[i][1]);
+		}
+	}
+	seq_putc(m, '\n');
+}
+
 static int show_smap(struct seq_file *m, void *v, int is_pid)
 {
 	struct proc_maps_private *priv = m->private;
@@ -581,6 +632,8 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
 		seq_printf(m, "Nonlinear:      %8lu kB\n",
 				mss.nonlinear >> 10);
 
+	show_smap_vma_flags(m, vma);
+
 	if (m->count < m->size)  /* vma is copied successfully */
 		m->version = (vma != get_gate_vma(task->mm))
 			? vma->vm_start : 0;
@@ -643,7 +696,7 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
 	spinlock_t *ptl;
 	struct page *page;
 
-	split_huge_page_pmd(walk->mm, pmd);
+	split_huge_page_pmd(vma, addr, pmd);
 	if (pmd_trans_unstable(pmd))
 		return 0;
 
@@ -1126,7 +1179,7 @@ static struct page *can_gather_numa_stats(pte_t pte, struct vm_area_struct *vma,
 		return NULL;
 
 	nid = page_to_nid(page);
-	if (!node_isset(nid, node_states[N_HIGH_MEMORY]))
+	if (!node_isset(nid, node_states[N_MEMORY]))
 		return NULL;
 
 	return page;
@@ -1279,7 +1332,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
 	if (md->writeback)
 		seq_printf(m, " writeback=%lu", md->writeback);
 
-	for_each_node_state(n, N_HIGH_MEMORY)
+	for_each_node_state(n, N_MEMORY)
 		if (md->node[n])
 			seq_printf(m, " N%d=%lu", n, md->node[n]);
 out:
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index 4ab572e..ed1d8c7 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -49,6 +49,7 @@ struct pstore_private {
 	struct pstore_info *psi;
 	enum pstore_type_id type;
 	u64	id;
+	int	count;
 	ssize_t	size;
 	char	data[];
 };
@@ -175,7 +176,8 @@ static int pstore_unlink(struct inode *dir, struct dentry *dentry)
 	struct pstore_private *p = dentry->d_inode->i_private;
 
 	if (p->psi->erase)
-		p->psi->erase(p->type, p->id, p->psi);
+		p->psi->erase(p->type, p->id, p->count,
+			      dentry->d_inode->i_ctime, p->psi);
 
 	return simple_unlink(dir, dentry);
 }
@@ -270,7 +272,7 @@ int pstore_is_mounted(void)
  * Load it up with "size" bytes of data from "buf".
  * Set the mtime & ctime to the date that this record was originally stored.
  */
-int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,
+int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count,
 		  char *data, size_t size, struct timespec time,
 		  struct pstore_info *psi)
 {
@@ -306,6 +308,7 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,
 		goto fail_alloc;
 	private->type = type;
 	private->id = id;
+	private->count = count;
 	private->psi = psi;
 
 	switch (type) {
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
index 4847f58..937d820 100644
--- a/fs/pstore/internal.h
+++ b/fs/pstore/internal.h
@@ -50,7 +50,7 @@ extern struct pstore_info *psinfo;
 extern void	pstore_set_kmsg_bytes(int);
 extern void	pstore_get_records(int);
 extern int	pstore_mkfile(enum pstore_type_id, char *psname, u64 id,
-			      char *data, size_t size,
+			      int count, char *data, size_t size,
 			      struct timespec time, struct pstore_info *psi);
 extern int	pstore_is_mounted(void);
 
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 947fbe0..5ea2e77 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -136,7 +136,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
 			break;
 
 		ret = psinfo->write(PSTORE_TYPE_DMESG, reason, &id, part,
-				    hsize + len, psinfo);
+				    oopscount, hsize + len, psinfo);
 		if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted())
 			pstore_new_entry = 1;
 
@@ -173,7 +173,7 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
 			spin_lock_irqsave(&psinfo->buf_lock, flags);
 		}
 		memcpy(psinfo->buf, s, c);
-		psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, c, psinfo);
+		psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, 0, c, psinfo);
 		spin_unlock_irqrestore(&psinfo->buf_lock, flags);
 		s += c;
 		c = e - s;
@@ -197,7 +197,7 @@ static void pstore_register_console(void) {}
 
 static int pstore_write_compat(enum pstore_type_id type,
 			       enum kmsg_dump_reason reason,
-			       u64 *id, unsigned int part,
+			       u64 *id, unsigned int part, int count,
 			       size_t size, struct pstore_info *psi)
 {
 	return psi->write_buf(type, reason, id, part, psinfo->buf, size, psi);
@@ -267,6 +267,7 @@ void pstore_get_records(int quiet)
 	char			*buf = NULL;
 	ssize_t			size;
 	u64			id;
+	int			count;
 	enum pstore_type_id	type;
 	struct timespec		time;
 	int			failed = 0, rc;
@@ -278,9 +279,9 @@ void pstore_get_records(int quiet)
 	if (psi->open && psi->open(psi))
 		goto out;
 
-	while ((size = psi->read(&id, &type, &time, &buf, psi)) > 0) {
-		rc = pstore_mkfile(type, psi->name, id, buf, (size_t)size,
-				  time, psi);
+	while ((size = psi->read(&id, &type, &count, &time, &buf, psi)) > 0) {
+		rc = pstore_mkfile(type, psi->name, id, count, buf,
+				  (size_t)size, time, psi);
 		kfree(buf);
 		buf = NULL;
 		if (rc && (rc != -EEXIST || !quiet))
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 1a4f6da..c0f6b5c 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -132,9 +132,8 @@ ramoops_get_next_prz(struct persistent_ram_zone *przs[], uint *c, uint max,
 }
 
 static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
-				   struct timespec *time,
-				   char **buf,
-				   struct pstore_info *psi)
+				   int *count, struct timespec *time,
+				   char **buf, struct pstore_info *psi)
 {
 	ssize_t size;
 	struct ramoops_context *cxt = psi->data;
@@ -236,8 +235,8 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
 	return 0;
 }
 
-static int ramoops_pstore_erase(enum pstore_type_id type, u64 id,
-				struct pstore_info *psi)
+static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count,
+				struct timespec time, struct pstore_info *psi)
 {
 	struct ramoops_context *cxt = psi->data;
 	struct persistent_ram_zone *prz;
@@ -287,8 +286,9 @@ static void ramoops_free_przs(struct ramoops_context *cxt)
 	kfree(cxt->przs);
 }
 
-static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
-			      phys_addr_t *paddr, size_t dump_mem_sz)
+static int __devinit ramoops_init_przs(struct device *dev,
+				       struct ramoops_context *cxt,
+				       phys_addr_t *paddr, size_t dump_mem_sz)
 {
 	int err = -ENOMEM;
 	int i;
@@ -326,9 +326,10 @@ fail_prz:
 	return err;
 }
 
-static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
-			    struct persistent_ram_zone **prz,
-			    phys_addr_t *paddr, size_t sz, u32 sig)
+static int __devinit ramoops_init_prz(struct device *dev,
+				      struct ramoops_context *cxt,
+				      struct persistent_ram_zone **prz,
+				      phys_addr_t *paddr, size_t sz, u32 sig)
 {
 	if (!sz)
 		return 0;
@@ -374,10 +375,14 @@ static int __devinit ramoops_probe(struct platform_device *pdev)
 		goto fail_out;
 	}
 
-	pdata->mem_size = rounddown_pow_of_two(pdata->mem_size);
-	pdata->record_size = rounddown_pow_of_two(pdata->record_size);
-	pdata->console_size = rounddown_pow_of_two(pdata->console_size);
-	pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size);
+	if (!is_power_of_2(pdata->mem_size))
+		pdata->mem_size = rounddown_pow_of_two(pdata->mem_size);
+	if (!is_power_of_2(pdata->record_size))
+		pdata->record_size = rounddown_pow_of_two(pdata->record_size);
+	if (!is_power_of_2(pdata->console_size))
+		pdata->console_size = rounddown_pow_of_two(pdata->console_size);
+	if (!is_power_of_2(pdata->ftrace_size))
+		pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size);
 
 	cxt->dump_read_cnt = 0;
 	cxt->size = pdata->mem_size;
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index af1661f..c7314f1 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -307,6 +307,8 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
 	}
 }
 
+#ifdef CONFIG_BLOCK
+
 /* Return 1 if 'cmd' will block on frozen filesystem */
 static int quotactl_cmd_write(int cmd)
 {
@@ -322,6 +324,8 @@ static int quotactl_cmd_write(int cmd)
 	return 1;
 }
 
+#endif /* CONFIG_BLOCK */
+
 /*
  * look up a superblock on which quota ops will be performed
  * - use the name of a block device to find the superblock thereon
diff --git a/fs/signalfd.c b/fs/signalfd.c
index 8bee4e5..b534869 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -29,6 +29,7 @@
 #include <linux/anon_inodes.h>
 #include <linux/signalfd.h>
 #include <linux/syscalls.h>
+#include <linux/proc_fs.h>
 
 void signalfd_cleanup(struct sighand_struct *sighand)
 {
@@ -227,7 +228,24 @@ static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count,
 	return total ? total: ret;
 }
 
+#ifdef CONFIG_PROC_FS
+static int signalfd_show_fdinfo(struct seq_file *m, struct file *f)
+{
+	struct signalfd_ctx *ctx = f->private_data;
+	sigset_t sigmask;
+
+	sigmask = ctx->sigmask;
+	signotset(&sigmask);
+	render_sigset_t(m, "sigmask:\t", &sigmask);
+
+	return 0;
+}
+#endif
+
 static const struct file_operations signalfd_fops = {
+#ifdef CONFIG_PROC_FS
+	.show_fdinfo	= signalfd_show_fdinfo,
+#endif
 	.release	= signalfd_release,
 	.poll		= signalfd_poll,
 	.read		= signalfd_read,
diff --git a/fs/splice.c b/fs/splice.c
index 13e5b47..8890604 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1024,17 +1024,14 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
 		ret = sd.num_spliced;
 
 	if (ret > 0) {
-		unsigned long nr_pages;
 		int err;
 
-		nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-
 		err = generic_write_sync(out, *ppos, ret);
 		if (err)
 			ret = err;
 		else
 			*ppos += ret;
-		balance_dirty_pages_ratelimited_nr(mapping, nr_pages);
+		balance_dirty_pages_ratelimited(mapping);
 	}
 	sb_end_write(inode->i_sb);
 
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 00012e3..602f56d 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -485,8 +485,8 @@ const struct file_operations sysfs_file_operations = {
 	.poll		= sysfs_poll,
 };
 
-int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr,
-		  const void **pns)
+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;
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 71eb7e2..db940a9 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -149,6 +149,7 @@ static struct file_system_type sysfs_fs_type = {
 	.name		= "sysfs",
 	.mount		= sysfs_mount,
 	.kill_sb	= sysfs_kill_sb,
+	.fs_flags	= FS_USERNS_MOUNT,
 };
 
 int __init sysfs_init(void)
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 6291163..12817ff 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -2560,7 +2560,7 @@ static int power_cut_emulated(struct ubifs_info *c, int lnum, int write)
 static int corrupt_data(const struct ubifs_info *c, const void *buf,
 			unsigned int len)
 {
-	unsigned int from, to, i, ffs = chance(1, 2);
+	unsigned int from, to, ffs = chance(1, 2);
 	unsigned char *p = (void *)buf;
 
 	from = random32() % (len + 1);
@@ -2571,11 +2571,9 @@ static int corrupt_data(const struct ubifs_info *c, const void *buf,
 		   ffs ? "0xFFs" : "random data");
 
 	if (ffs)
-		for (i = from; i < to; i++)
-			p[i] = 0xFF;
+		memset(p + from, 0xFF, to - from);
 	else
-		for (i = from; i < to; i++)
-			p[i] = random32() % 0x100;
+		prandom_bytes(p + from, to - from);
 
 	return to;
 }
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 77b5953..63e25fc 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -204,7 +204,7 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		goto out;
 	case UDF_RELOCATE_BLOCKS:
 		if (!capable(CAP_SYS_ADMIN)) {
-			result = -EACCES;
+			result = -EPERM;
 			goto out;
 		}
 		if (get_user(old_block, (long __user *)arg)) {
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index df88b95..cbae1ed 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -587,7 +587,6 @@ out:
 static sector_t inode_getblk(struct inode *inode, sector_t block,
 			     int *err, int *new)
 {
-	static sector_t last_block;
 	struct kernel_long_ad laarr[EXTENT_MERGE_SIZE];
 	struct extent_position prev_epos, cur_epos, next_epos;
 	int count = 0, startnum = 0, endnum = 0;
@@ -601,6 +600,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
 	struct udf_inode_info *iinfo = UDF_I(inode);
 	int goal = 0, pgoal = iinfo->i_location.logicalBlockNum;
 	int lastblock = 0;
+	bool isBeyondEOF;
 
 	*err = 0;
 	*new = 0;
@@ -676,11 +676,10 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
 		return newblock;
 	}
 
-	last_block = block;
 	/* Are we beyond EOF? */
 	if (etype == -1) {
 		int ret;
-
+		isBeyondEOF = 1;
 		if (count) {
 			if (c)
 				laarr[0] = laarr[1];
@@ -718,11 +717,11 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
 			memset(&laarr[c].extLocation, 0x00,
 				sizeof(struct kernel_lb_addr));
 			count++;
-			endnum++;
 		}
 		endnum = c + 1;
 		lastblock = 1;
 	} else {
+		isBeyondEOF = 0;
 		endnum = startnum = ((count > 2) ? 2 : count);
 
 		/* if the current extent is in position 0,
@@ -765,10 +764,13 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
 				goal, err);
 		if (!newblocknum) {
 			brelse(prev_epos.bh);
+			brelse(cur_epos.bh);
+			brelse(next_epos.bh);
 			*err = -ENOSPC;
 			return 0;
 		}
-		iinfo->i_lenExtents += inode->i_sb->s_blocksize;
+		if (isBeyondEOF)
+			iinfo->i_lenExtents += inode->i_sb->s_blocksize;
 	}
 
 	/* if the extent the requsted block is located in contains multiple
@@ -795,6 +797,8 @@ static sector_t inode_getblk(struct inode *inode, sector_t block,
 	udf_update_extents(inode, laarr, startnum, endnum, &prev_epos);
 
 	brelse(prev_epos.bh);
+	brelse(cur_epos.bh);
+	brelse(next_epos.bh);
 
 	newblock = udf_get_pblock(inode->i_sb, newblocknum,
 				iinfo->i_location.partitionReferenceNum, 0);
diff --git a/fs/xfs/Kconfig b/fs/xfs/Kconfig
index 6100ec0..cc33aaf 100644
--- a/fs/xfs/Kconfig
+++ b/fs/xfs/Kconfig
@@ -2,6 +2,7 @@ config XFS_FS
 	tristate "XFS filesystem support"
 	depends on BLOCK
 	select EXPORTFS
+	select LIBCRC32C
 	help
 	  XFS is a high performance journaling filesystem which originated
 	  on the SGI IRIX platform.  It is completely multi-threaded, can
@@ -69,8 +70,8 @@ config XFS_RT
 	  If unsure, say N.
 
 config XFS_DEBUG
-	bool "XFS Debugging support (EXPERIMENTAL)"
-	depends on XFS_FS && EXPERIMENTAL
+	bool "XFS Debugging support"
+	depends on XFS_FS
 	help
 	  Say Y here to get an XFS build with many debugging features,
 	  including ASSERT checks, function wrappers around macros,
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index d2bf974..d02201d 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -37,9 +37,8 @@ xfs-y				+= xfs_aops.o \
 				   xfs_file.o \
 				   xfs_filestream.o \
 				   xfs_fsops.o \
-				   xfs_fs_subr.o \
 				   xfs_globals.o \
-				   xfs_iget.o \
+				   xfs_icache.o \
 				   xfs_ioctl.o \
 				   xfs_iomap.o \
 				   xfs_iops.o \
@@ -47,7 +46,6 @@ xfs-y				+= xfs_aops.o \
 				   xfs_message.o \
 				   xfs_mru_cache.o \
 				   xfs_super.o \
-				   xfs_sync.o \
 				   xfs_xattr.o \
 				   xfs_rename.o \
 				   xfs_utils.o \
diff --git a/fs/xfs/uuid.h b/fs/xfs/uuid.h
index 4732d71..104db0f 100644
--- a/fs/xfs/uuid.h
+++ b/fs/xfs/uuid.h
@@ -26,4 +26,10 @@ extern int uuid_is_nil(uuid_t *uuid);
 extern int uuid_equal(uuid_t *uuid1, uuid_t *uuid2);
 extern void uuid_getnodeuniq(uuid_t *uuid, int fsid [2]);
 
+static inline void
+uuid_copy(uuid_t *dst, uuid_t *src)
+{
+	memcpy(dst, src, sizeof(uuid_t));
+}
+
 #endif	/* __XFS_SUPPORT_UUID_H__ */
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index 44d65c1..f2aeedb 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -108,6 +108,8 @@ typedef struct xfs_agf {
 extern int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
 			xfs_agnumber_t agno, int flags, struct xfs_buf **bpp);
 
+extern const struct xfs_buf_ops xfs_agf_buf_ops;
+
 /*
  * Size of the unlinked inode hash table in the agi.
  */
@@ -161,6 +163,8 @@ typedef struct xfs_agi {
 extern int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp,
 				xfs_agnumber_t agno, struct xfs_buf **bpp);
 
+extern const struct xfs_buf_ops xfs_agi_buf_ops;
+
 /*
  * The third a.g. block contains the a.g. freelist, an array
  * of block pointers to blocks owned by the allocation btree code.
@@ -233,6 +237,7 @@ typedef struct xfs_perag {
 #define XFS_ICI_NO_TAG		(-1)	/* special flag for an untagged lookup
 					   in xfs_inode_ag_iterator */
 #define XFS_ICI_RECLAIM_TAG	0	/* inode is to be reclaimed */
+#define XFS_ICI_EOFBLOCKS_TAG	1	/* inode has blocks beyond EOF */
 
 #define	XFS_AG_MAXLEVELS(mp)		((mp)->m_ag_maxlevels)
 #define	XFS_MIN_FREELIST_RAW(bl,cl,mp)	\
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 335206a..393055f 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -430,6 +430,60 @@ xfs_alloc_fixup_trees(
 	return 0;
 }
 
+static void
+xfs_agfl_verify(
+	struct xfs_buf	*bp)
+{
+#ifdef WHEN_CRCS_COME_ALONG
+	/*
+	 * we cannot actually do any verification of the AGFL because mkfs does
+	 * not initialise the AGFL to zero or NULL. Hence the only valid part of
+	 * the AGFL is what the AGF says is active. We can't get to the AGF, so
+	 * we can't verify just those entries are valid.
+	 *
+	 * This problem goes away when the CRC format change comes along as that
+	 * requires the AGFL to be initialised by mkfs. At that point, we can
+	 * verify the blocks in the agfl -active or not- lie within the bounds
+	 * of the AG. Until then, just leave this check ifdef'd out.
+	 */
+	struct xfs_mount *mp = bp->b_target->bt_mount;
+	struct xfs_agfl	*agfl = XFS_BUF_TO_AGFL(bp);
+	int		agfl_ok = 1;
+
+	int		i;
+
+	for (i = 0; i < XFS_AGFL_SIZE(mp); i++) {
+		if (be32_to_cpu(agfl->agfl_bno[i]) == NULLAGBLOCK ||
+		    be32_to_cpu(agfl->agfl_bno[i]) >= mp->m_sb.sb_agblocks)
+			agfl_ok = 0;
+	}
+
+	if (!agfl_ok) {
+		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, agfl);
+		xfs_buf_ioerror(bp, EFSCORRUPTED);
+	}
+#endif
+}
+
+static void
+xfs_agfl_write_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_agfl_verify(bp);
+}
+
+static void
+xfs_agfl_read_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_agfl_verify(bp);
+}
+
+const struct xfs_buf_ops xfs_agfl_buf_ops = {
+	.verify_read = xfs_agfl_read_verify,
+	.verify_write = xfs_agfl_write_verify,
+};
+
 /*
  * Read in the allocation group free block array.
  */
@@ -447,7 +501,7 @@ xfs_alloc_read_agfl(
 	error = xfs_trans_read_buf(
 			mp, tp, mp->m_ddev_targp,
 			XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)),
-			XFS_FSS_TO_BB(mp, 1), 0, &bp);
+			XFS_FSS_TO_BB(mp, 1), 0, &bp, &xfs_agfl_buf_ops);
 	if (error)
 		return error;
 	ASSERT(!xfs_buf_geterror(bp));
@@ -2091,6 +2145,63 @@ xfs_alloc_put_freelist(
 	return 0;
 }
 
+static void
+xfs_agf_verify(
+	struct xfs_buf	*bp)
+ {
+	struct xfs_mount *mp = bp->b_target->bt_mount;
+	struct xfs_agf	*agf;
+	int		agf_ok;
+
+	agf = XFS_BUF_TO_AGF(bp);
+
+	agf_ok = agf->agf_magicnum == cpu_to_be32(XFS_AGF_MAGIC) &&
+		XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum)) &&
+		be32_to_cpu(agf->agf_freeblks) <= be32_to_cpu(agf->agf_length) &&
+		be32_to_cpu(agf->agf_flfirst) < XFS_AGFL_SIZE(mp) &&
+		be32_to_cpu(agf->agf_fllast) < XFS_AGFL_SIZE(mp) &&
+		be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp);
+
+	/*
+	 * during growfs operations, the perag is not fully initialised,
+	 * so we can't use it for any useful checking. growfs ensures we can't
+	 * use it by using uncached buffers that don't have the perag attached
+	 * so we can detect and avoid this problem.
+	 */
+	if (bp->b_pag)
+		agf_ok = agf_ok && be32_to_cpu(agf->agf_seqno) ==
+						bp->b_pag->pag_agno;
+
+	if (xfs_sb_version_haslazysbcount(&mp->m_sb))
+		agf_ok = agf_ok && be32_to_cpu(agf->agf_btreeblks) <=
+						be32_to_cpu(agf->agf_length);
+
+	if (unlikely(XFS_TEST_ERROR(!agf_ok, mp, XFS_ERRTAG_ALLOC_READ_AGF,
+			XFS_RANDOM_ALLOC_READ_AGF))) {
+		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, agf);
+		xfs_buf_ioerror(bp, EFSCORRUPTED);
+	}
+}
+
+static void
+xfs_agf_read_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_agf_verify(bp);
+}
+
+static void
+xfs_agf_write_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_agf_verify(bp);
+}
+
+const struct xfs_buf_ops xfs_agf_buf_ops = {
+	.verify_read = xfs_agf_read_verify,
+	.verify_write = xfs_agf_write_verify,
+};
+
 /*
  * Read in the allocation group header (free/alloc section).
  */
@@ -2102,44 +2213,19 @@ xfs_read_agf(
 	int			flags,	/* XFS_BUF_ */
 	struct xfs_buf		**bpp)	/* buffer for the ag freelist header */
 {
-	struct xfs_agf	*agf;		/* ag freelist header */
-	int		agf_ok;		/* set if agf is consistent */
 	int		error;
 
 	ASSERT(agno != NULLAGNUMBER);
 	error = xfs_trans_read_buf(
 			mp, tp, mp->m_ddev_targp,
 			XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
-			XFS_FSS_TO_BB(mp, 1), flags, bpp);
+			XFS_FSS_TO_BB(mp, 1), flags, bpp, &xfs_agf_buf_ops);
 	if (error)
 		return error;
 	if (!*bpp)
 		return 0;
 
 	ASSERT(!(*bpp)->b_error);
-	agf = XFS_BUF_TO_AGF(*bpp);
-
-	/*
-	 * Validate the magic number of the agf block.
-	 */
-	agf_ok =
-		agf->agf_magicnum == cpu_to_be32(XFS_AGF_MAGIC) &&
-		XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum)) &&
-		be32_to_cpu(agf->agf_freeblks) <= be32_to_cpu(agf->agf_length) &&
-		be32_to_cpu(agf->agf_flfirst) < XFS_AGFL_SIZE(mp) &&
-		be32_to_cpu(agf->agf_fllast) < XFS_AGFL_SIZE(mp) &&
-		be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp) &&
-		be32_to_cpu(agf->agf_seqno) == agno;
-	if (xfs_sb_version_haslazysbcount(&mp->m_sb))
-		agf_ok = agf_ok && be32_to_cpu(agf->agf_btreeblks) <=
-						be32_to_cpu(agf->agf_length);
-	if (unlikely(XFS_TEST_ERROR(!agf_ok, mp, XFS_ERRTAG_ALLOC_READ_AGF,
-			XFS_RANDOM_ALLOC_READ_AGF))) {
-		XFS_CORRUPTION_ERROR("xfs_alloc_read_agf",
-				     XFS_ERRLEVEL_LOW, mp, agf);
-		xfs_trans_brelse(tp, *bpp);
-		return XFS_ERROR(EFSCORRUPTED);
-	}
 	xfs_buf_set_ref(*bpp, XFS_AGF_REF);
 	return 0;
 }
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h
index feacb06..99d0a61 100644
--- a/fs/xfs/xfs_alloc.h
+++ b/fs/xfs/xfs_alloc.h
@@ -231,4 +231,7 @@ xfs_alloc_get_rec(
 	xfs_extlen_t		*len,	/* output: length of extent */
 	int			*stat);	/* output: success/failure */
 
+extern const struct xfs_buf_ops xfs_agf_buf_ops;
+extern const struct xfs_buf_ops xfs_agfl_buf_ops;
+
 #endif	/* __XFS_ALLOC_H__ */
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index f7876c6..b1ddef6 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -272,6 +272,82 @@ xfs_allocbt_key_diff(
 	return (__int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock;
 }
 
+static void
+xfs_allocbt_verify(
+	struct xfs_buf		*bp)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+	struct xfs_btree_block	*block = XFS_BUF_TO_BLOCK(bp);
+	struct xfs_perag	*pag = bp->b_pag;
+	unsigned int		level;
+	int			sblock_ok; /* block passes checks */
+
+	/*
+	 * magic number and level verification
+	 *
+	 * During growfs operations, we can't verify the exact level as the
+	 * perag is not fully initialised and hence not attached to the buffer.
+	 * In this case, check against the maximum tree depth.
+	 */
+	level = be16_to_cpu(block->bb_level);
+	switch (block->bb_magic) {
+	case cpu_to_be32(XFS_ABTB_MAGIC):
+		if (pag)
+			sblock_ok = level < pag->pagf_levels[XFS_BTNUM_BNOi];
+		else
+			sblock_ok = level < mp->m_ag_maxlevels;
+		break;
+	case cpu_to_be32(XFS_ABTC_MAGIC):
+		if (pag)
+			sblock_ok = level < pag->pagf_levels[XFS_BTNUM_CNTi];
+		else
+			sblock_ok = level < mp->m_ag_maxlevels;
+		break;
+	default:
+		sblock_ok = 0;
+		break;
+	}
+
+	/* numrecs verification */
+	sblock_ok = sblock_ok &&
+		be16_to_cpu(block->bb_numrecs) <= mp->m_alloc_mxr[level != 0];
+
+	/* sibling pointer verification */
+	sblock_ok = sblock_ok &&
+		(block->bb_u.s.bb_leftsib == cpu_to_be32(NULLAGBLOCK) ||
+		 be32_to_cpu(block->bb_u.s.bb_leftsib) < mp->m_sb.sb_agblocks) &&
+		block->bb_u.s.bb_leftsib &&
+		(block->bb_u.s.bb_rightsib == cpu_to_be32(NULLAGBLOCK) ||
+		 be32_to_cpu(block->bb_u.s.bb_rightsib) < mp->m_sb.sb_agblocks) &&
+		block->bb_u.s.bb_rightsib;
+
+	if (!sblock_ok) {
+		trace_xfs_btree_corrupt(bp, _RET_IP_);
+		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, block);
+		xfs_buf_ioerror(bp, EFSCORRUPTED);
+	}
+}
+
+static void
+xfs_allocbt_read_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_allocbt_verify(bp);
+}
+
+static void
+xfs_allocbt_write_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_allocbt_verify(bp);
+}
+
+const struct xfs_buf_ops xfs_allocbt_buf_ops = {
+	.verify_read = xfs_allocbt_read_verify,
+	.verify_write = xfs_allocbt_write_verify,
+};
+
+
 #ifdef DEBUG
 STATIC int
 xfs_allocbt_keys_inorder(
@@ -327,6 +403,7 @@ static const struct xfs_btree_ops xfs_allocbt_ops = {
 	.init_rec_from_cur	= xfs_allocbt_init_rec_from_cur,
 	.init_ptr_from_cur	= xfs_allocbt_init_ptr_from_cur,
 	.key_diff		= xfs_allocbt_key_diff,
+	.buf_ops		= &xfs_allocbt_buf_ops,
 #ifdef DEBUG
 	.keys_inorder		= xfs_allocbt_keys_inorder,
 	.recs_inorder		= xfs_allocbt_recs_inorder,
diff --git a/fs/xfs/xfs_alloc_btree.h b/fs/xfs/xfs_alloc_btree.h
index 359fb86..7e89a2b 100644
--- a/fs/xfs/xfs_alloc_btree.h
+++ b/fs/xfs/xfs_alloc_btree.h
@@ -93,4 +93,6 @@ extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *,
 		xfs_agnumber_t, xfs_btnum_t);
 extern int xfs_allocbt_maxrecs(struct xfs_mount *, int, int);
 
+extern const struct xfs_buf_ops xfs_allocbt_buf_ops;
+
 #endif	/* __XFS_ALLOC_BTREE_H__ */
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index e57e2da..71361da 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -1641,7 +1641,7 @@ xfs_vm_bmap(
 
 	trace_xfs_vm_bmap(XFS_I(inode));
 	xfs_ilock(ip, XFS_IOLOCK_SHARED);
-	xfs_flush_pages(ip, (xfs_off_t)0, -1, 0, FI_REMAPF);
+	filemap_write_and_wait(mapping);
 	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
 	return generic_block_bmap(mapping, block, xfs_get_blocks);
 }
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 0ca1f0b..aaf4725 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -903,11 +903,9 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
 	 */
 	dp = args->dp;
 	args->blkno = 0;
-	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
-					     XFS_ATTR_FORK);
+	error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
 	if (error)
-		return(error);
-	ASSERT(bp != NULL);
+		return error;
 
 	/*
 	 * Look up the given attribute in the leaf block.  Figure out if
@@ -1031,12 +1029,12 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
 		 * Read in the block containing the "old" attr, then
 		 * remove the "old" attr from that block (neat, huh!)
 		 */
-		error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1,
-						     &bp, XFS_ATTR_FORK);
+		error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno,
+					   -1, &bp);
 		if (error)
-			return(error);
-		ASSERT(bp != NULL);
-		(void)xfs_attr_leaf_remove(bp, args);
+			return error;
+
+		xfs_attr_leaf_remove(bp, args);
 
 		/*
 		 * If the result is small enough, shrink it all into the inode.
@@ -1100,20 +1098,17 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
 	 */
 	dp = args->dp;
 	args->blkno = 0;
-	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
-					     XFS_ATTR_FORK);
-	if (error) {
-		return(error);
-	}
+	error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
+	if (error)
+		return error;
 
-	ASSERT(bp != NULL);
 	error = xfs_attr_leaf_lookup_int(bp, args);
 	if (error == ENOATTR) {
 		xfs_trans_brelse(args->trans, bp);
 		return(error);
 	}
 
-	(void)xfs_attr_leaf_remove(bp, args);
+	xfs_attr_leaf_remove(bp, args);
 
 	/*
 	 * If the result is small enough, shrink it all into the inode.
@@ -1155,12 +1150,12 @@ xfs_attr_leaf_get(xfs_da_args_t *args)
 	struct xfs_buf *bp;
 	int error;
 
+	trace_xfs_attr_leaf_get(args);
+
 	args->blkno = 0;
-	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
-					     XFS_ATTR_FORK);
+	error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
 	if (error)
-		return(error);
-	ASSERT(bp != NULL);
+		return error;
 
 	error = xfs_attr_leaf_lookup_int(bp, args);
 	if (error != EEXIST)  {
@@ -1181,22 +1176,15 @@ xfs_attr_leaf_get(xfs_da_args_t *args)
 STATIC int
 xfs_attr_leaf_list(xfs_attr_list_context_t *context)
 {
-	xfs_attr_leafblock_t *leaf;
 	int error;
 	struct xfs_buf *bp;
 
+	trace_xfs_attr_leaf_list(context);
+
 	context->cursor->blkno = 0;
-	error = xfs_da_read_buf(NULL, context->dp, 0, -1, &bp, XFS_ATTR_FORK);
+	error = xfs_attr_leaf_read(NULL, context->dp, 0, -1, &bp);
 	if (error)
 		return XFS_ERROR(error);
-	ASSERT(bp != NULL);
-	leaf = bp->b_addr;
-	if (unlikely(leaf->hdr.info.magic != cpu_to_be16(XFS_ATTR_LEAF_MAGIC))) {
-		XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW,
-				     context->dp->i_mount, leaf);
-		xfs_trans_brelse(NULL, bp);
-		return XFS_ERROR(EFSCORRUPTED);
-	}
 
 	error = xfs_attr_leaf_list_int(bp, context);
 	xfs_trans_brelse(NULL, bp);
@@ -1600,12 +1588,9 @@ xfs_attr_node_removename(xfs_da_args_t *args)
 		ASSERT(state->path.blk[0].bp);
 		state->path.blk[0].bp = NULL;
 
-		error = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
-						     XFS_ATTR_FORK);
+		error = xfs_attr_leaf_read(args->trans, args->dp, 0, -1, &bp);
 		if (error)
 			goto out;
-		ASSERT((((xfs_attr_leafblock_t *)bp->b_addr)->hdr.info.magic) ==
-		       cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 
 		if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
 			xfs_bmap_init(args->flist, args->firstblock);
@@ -1653,6 +1638,8 @@ xfs_attr_fillstate(xfs_da_state_t *state)
 	xfs_da_state_blk_t *blk;
 	int level;
 
+	trace_xfs_attr_fillstate(state->args);
+
 	/*
 	 * Roll down the "path" in the state structure, storing the on-disk
 	 * block number for those buffers in the "path".
@@ -1699,6 +1686,8 @@ xfs_attr_refillstate(xfs_da_state_t *state)
 	xfs_da_state_blk_t *blk;
 	int level, error;
 
+	trace_xfs_attr_refillstate(state->args);
+
 	/*
 	 * Roll down the "path" in the state structure, storing the on-disk
 	 * block number for those buffers in the "path".
@@ -1707,7 +1696,7 @@ xfs_attr_refillstate(xfs_da_state_t *state)
 	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
 	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
 		if (blk->disk_blkno) {
-			error = xfs_da_read_buf(state->args->trans,
+			error = xfs_da_node_read(state->args->trans,
 						state->args->dp,
 						blk->blkno, blk->disk_blkno,
 						&blk->bp, XFS_ATTR_FORK);
@@ -1726,7 +1715,7 @@ xfs_attr_refillstate(xfs_da_state_t *state)
 	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
 	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
 		if (blk->disk_blkno) {
-			error = xfs_da_read_buf(state->args->trans,
+			error = xfs_da_node_read(state->args->trans,
 						state->args->dp,
 						blk->blkno, blk->disk_blkno,
 						&blk->bp, XFS_ATTR_FORK);
@@ -1755,6 +1744,8 @@ xfs_attr_node_get(xfs_da_args_t *args)
 	int error, retval;
 	int i;
 
+	trace_xfs_attr_node_get(args);
+
 	state = xfs_da_state_alloc();
 	state->args = args;
 	state->mp = args->dp->i_mount;
@@ -1804,6 +1795,8 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
 	int error, i;
 	struct xfs_buf *bp;
 
+	trace_xfs_attr_node_list(context);
+
 	cursor = context->cursor;
 	cursor->initted = 1;
 
@@ -1814,7 +1807,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
 	 */
 	bp = NULL;
 	if (cursor->blkno > 0) {
-		error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
+		error = xfs_da_node_read(NULL, context->dp, cursor->blkno, -1,
 					      &bp, XFS_ATTR_FORK);
 		if ((error != 0) && (error != EFSCORRUPTED))
 			return(error);
@@ -1856,17 +1849,11 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
 	if (bp == NULL) {
 		cursor->blkno = 0;
 		for (;;) {
-			error = xfs_da_read_buf(NULL, context->dp,
+			error = xfs_da_node_read(NULL, context->dp,
 						      cursor->blkno, -1, &bp,
 						      XFS_ATTR_FORK);
 			if (error)
 				return(error);
-			if (unlikely(bp == NULL)) {
-				XFS_ERROR_REPORT("xfs_attr_node_list(2)",
-						 XFS_ERRLEVEL_LOW,
-						 context->dp->i_mount);
-				return(XFS_ERROR(EFSCORRUPTED));
-			}
 			node = bp->b_addr;
 			if (node->hdr.info.magic ==
 			    cpu_to_be16(XFS_ATTR_LEAF_MAGIC))
@@ -1907,14 +1894,6 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
 	 */
 	for (;;) {
 		leaf = bp->b_addr;
-		if (unlikely(leaf->hdr.info.magic !=
-			     cpu_to_be16(XFS_ATTR_LEAF_MAGIC))) {
-			XFS_CORRUPTION_ERROR("xfs_attr_node_list(4)",
-					     XFS_ERRLEVEL_LOW,
-					     context->dp->i_mount, leaf);
-			xfs_trans_brelse(NULL, bp);
-			return(XFS_ERROR(EFSCORRUPTED));
-		}
 		error = xfs_attr_leaf_list_int(bp, context);
 		if (error) {
 			xfs_trans_brelse(NULL, bp);
@@ -1924,16 +1903,10 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
 			break;
 		cursor->blkno = be32_to_cpu(leaf->hdr.info.forw);
 		xfs_trans_brelse(NULL, bp);
-		error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
-					      &bp, XFS_ATTR_FORK);
+		error = xfs_attr_leaf_read(NULL, context->dp, cursor->blkno, -1,
+					   &bp);
 		if (error)
-			return(error);
-		if (unlikely((bp == NULL))) {
-			XFS_ERROR_REPORT("xfs_attr_node_list(5)",
-					 XFS_ERRLEVEL_LOW,
-					 context->dp->i_mount);
-			return(XFS_ERROR(EFSCORRUPTED));
-		}
+			return error;
 	}
 	xfs_trans_brelse(NULL, bp);
 	return(0);
@@ -1959,6 +1932,8 @@ xfs_attr_rmtval_get(xfs_da_args_t *args)
 	int nmap, error, tmp, valuelen, blkcnt, i;
 	xfs_dablk_t lblkno;
 
+	trace_xfs_attr_rmtval_get(args);
+
 	ASSERT(!(args->flags & ATTR_KERNOVAL));
 
 	mp = args->dp->i_mount;
@@ -1980,7 +1955,7 @@ xfs_attr_rmtval_get(xfs_da_args_t *args)
 			dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock);
 			blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
 			error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
-						   dblkno, blkcnt, 0, &bp);
+						   dblkno, blkcnt, 0, &bp, NULL);
 			if (error)
 				return(error);
 
@@ -2014,6 +1989,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
 	xfs_dablk_t lblkno;
 	int blkcnt, valuelen, nmap, error, tmp, committed;
 
+	trace_xfs_attr_rmtval_set(args);
+
 	dp = args->dp;
 	mp = dp->i_mount;
 	src = args->value;
@@ -2143,6 +2120,8 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
 	xfs_dablk_t lblkno;
 	int valuelen, blkcnt, nmap, error, done, committed;
 
+	trace_xfs_attr_rmtval_remove(args);
+
 	mp = args->dp->i_mount;
 
 	/*
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 70eec18..ee24993 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -57,7 +57,8 @@ STATIC int xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t which_block,
 				struct xfs_buf **bpp);
 STATIC int xfs_attr_leaf_add_work(struct xfs_buf *leaf_buffer,
 				  xfs_da_args_t *args, int freemap_index);
-STATIC void xfs_attr_leaf_compact(xfs_trans_t *tp, struct xfs_buf *leaf_buffer);
+STATIC void xfs_attr_leaf_compact(struct xfs_da_args *args,
+				  struct xfs_buf *leaf_buffer);
 STATIC void xfs_attr_leaf_rebalance(xfs_da_state_t *state,
 						   xfs_da_state_blk_t *blk1,
 						   xfs_da_state_blk_t *blk2);
@@ -87,6 +88,52 @@ STATIC void xfs_attr_leaf_moveents(xfs_attr_leafblock_t *src_leaf,
 					 xfs_mount_t *mp);
 STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
 
+static void
+xfs_attr_leaf_verify(
+	struct xfs_buf		*bp)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+	struct xfs_attr_leaf_hdr *hdr = bp->b_addr;
+	int			block_ok = 0;
+
+	block_ok = hdr->info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC);
+	if (!block_ok) {
+		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr);
+		xfs_buf_ioerror(bp, EFSCORRUPTED);
+	}
+}
+
+static void
+xfs_attr_leaf_read_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_attr_leaf_verify(bp);
+}
+
+static void
+xfs_attr_leaf_write_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_attr_leaf_verify(bp);
+}
+
+const struct xfs_buf_ops xfs_attr_leaf_buf_ops = {
+	.verify_read = xfs_attr_leaf_read_verify,
+	.verify_write = xfs_attr_leaf_write_verify,
+};
+
+int
+xfs_attr_leaf_read(
+	struct xfs_trans	*tp,
+	struct xfs_inode	*dp,
+	xfs_dablk_t		bno,
+	xfs_daddr_t		mappedbno,
+	struct xfs_buf		**bpp)
+{
+	return xfs_da_read_buf(tp, dp, bno, mappedbno, bpp,
+				XFS_ATTR_FORK, &xfs_attr_leaf_buf_ops);
+}
+
 /*========================================================================
  * Namespace helper routines
  *========================================================================*/
@@ -869,17 +916,16 @@ xfs_attr_leaf_to_node(xfs_da_args_t *args)
 	error = xfs_da_grow_inode(args, &blkno);
 	if (error)
 		goto out;
-	error = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp1,
-					     XFS_ATTR_FORK);
+	error = xfs_attr_leaf_read(args->trans, args->dp, 0, -1, &bp1);
 	if (error)
 		goto out;
-	ASSERT(bp1 != NULL);
+
 	bp2 = NULL;
 	error = xfs_da_get_buf(args->trans, args->dp, blkno, -1, &bp2,
 					    XFS_ATTR_FORK);
 	if (error)
 		goto out;
-	ASSERT(bp2 != NULL);
+	bp2->b_ops = bp1->b_ops;
 	memcpy(bp2->b_addr, bp1->b_addr, XFS_LBSIZE(dp->i_mount));
 	bp1 = NULL;
 	xfs_trans_log_buf(args->trans, bp2, 0, XFS_LBSIZE(dp->i_mount) - 1);
@@ -933,7 +979,7 @@ xfs_attr_leaf_create(
 					    XFS_ATTR_FORK);
 	if (error)
 		return(error);
-	ASSERT(bp != NULL);
+	bp->b_ops = &xfs_attr_leaf_buf_ops;
 	leaf = bp->b_addr;
 	memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount));
 	hdr = &leaf->hdr;
@@ -1071,7 +1117,7 @@ xfs_attr_leaf_add(
 	 * Compact the entries to coalesce free space.
 	 * This may change the hdr->count via dropping INCOMPLETE entries.
 	 */
-	xfs_attr_leaf_compact(args->trans, bp);
+	xfs_attr_leaf_compact(args, bp);
 
 	/*
 	 * After compaction, the block is guaranteed to have only one
@@ -1102,6 +1148,8 @@ xfs_attr_leaf_add_work(
 	xfs_mount_t *mp;
 	int tmp, i;
 
+	trace_xfs_attr_leaf_add_work(args);
+
 	leaf = bp->b_addr;
 	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	hdr = &leaf->hdr;
@@ -1214,15 +1262,17 @@ xfs_attr_leaf_add_work(
  */
 STATIC void
 xfs_attr_leaf_compact(
-	struct xfs_trans *trans,
-	struct xfs_buf	*bp)
+	struct xfs_da_args	*args,
+	struct xfs_buf		*bp)
 {
-	xfs_attr_leafblock_t *leaf_s, *leaf_d;
-	xfs_attr_leaf_hdr_t *hdr_s, *hdr_d;
-	xfs_mount_t *mp;
-	char *tmpbuffer;
+	xfs_attr_leafblock_t	*leaf_s, *leaf_d;
+	xfs_attr_leaf_hdr_t	*hdr_s, *hdr_d;
+	struct xfs_trans	*trans = args->trans;
+	struct xfs_mount	*mp = trans->t_mountp;
+	char			*tmpbuffer;
+
+	trace_xfs_attr_leaf_compact(args);
 
-	mp = trans->t_mountp;
 	tmpbuffer = kmem_alloc(XFS_LBSIZE(mp), KM_SLEEP);
 	ASSERT(tmpbuffer != NULL);
 	memcpy(tmpbuffer, bp->b_addr, XFS_LBSIZE(mp));
@@ -1345,9 +1395,8 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
 		max  = be16_to_cpu(hdr2->firstused)
 						- sizeof(xfs_attr_leaf_hdr_t);
 		max -= be16_to_cpu(hdr2->count) * sizeof(xfs_attr_leaf_entry_t);
-		if (space > max) {
-			xfs_attr_leaf_compact(args->trans, blk2->bp);
-		}
+		if (space > max)
+			xfs_attr_leaf_compact(args, blk2->bp);
 
 		/*
 		 * Move high entries from leaf1 to low end of leaf2.
@@ -1378,9 +1427,8 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
 		max  = be16_to_cpu(hdr1->firstused)
 						- sizeof(xfs_attr_leaf_hdr_t);
 		max -= be16_to_cpu(hdr1->count) * sizeof(xfs_attr_leaf_entry_t);
-		if (space > max) {
-			xfs_attr_leaf_compact(args->trans, blk1->bp);
-		}
+		if (space > max)
+			xfs_attr_leaf_compact(args, blk1->bp);
 
 		/*
 		 * Move low entries from leaf2 to high end of leaf1.
@@ -1577,6 +1625,8 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action)
 	xfs_dablk_t blkno;
 	struct xfs_buf *bp;
 
+	trace_xfs_attr_leaf_toosmall(state->args);
+
 	/*
 	 * Check for the degenerate case of the block being over 50% full.
 	 * If so, it's not worth even looking to see if we might be able
@@ -1636,18 +1686,16 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action)
 			blkno = be32_to_cpu(info->back);
 		if (blkno == 0)
 			continue;
-		error = xfs_da_read_buf(state->args->trans, state->args->dp,
-					blkno, -1, &bp, XFS_ATTR_FORK);
+		error = xfs_attr_leaf_read(state->args->trans, state->args->dp,
+					blkno, -1, &bp);
 		if (error)
 			return(error);
-		ASSERT(bp != NULL);
 
 		leaf = (xfs_attr_leafblock_t *)info;
 		count  = be16_to_cpu(leaf->hdr.count);
 		bytes  = state->blocksize - (state->blocksize>>2);
 		bytes -= be16_to_cpu(leaf->hdr.usedbytes);
 		leaf = bp->b_addr;
-		ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 		count += be16_to_cpu(leaf->hdr.count);
 		bytes -= be16_to_cpu(leaf->hdr.usedbytes);
 		bytes -= count * sizeof(xfs_attr_leaf_entry_t);
@@ -1702,6 +1750,8 @@ xfs_attr_leaf_remove(
 	int tablesize, tmp, i;
 	xfs_mount_t *mp;
 
+	trace_xfs_attr_leaf_remove(args);
+
 	leaf = bp->b_addr;
 	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	hdr = &leaf->hdr;
@@ -2511,15 +2561,11 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args)
 	/*
 	 * Set up the operation.
 	 */
-	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
-					     XFS_ATTR_FORK);
-	if (error) {
+	error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
+	if (error)
 		return(error);
-	}
-	ASSERT(bp != NULL);
 
 	leaf = bp->b_addr;
-	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	ASSERT(args->index < be16_to_cpu(leaf->hdr.count));
 	ASSERT(args->index >= 0);
 	entry = &leaf->entries[ args->index ];
@@ -2576,15 +2622,11 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args)
 	/*
 	 * Set up the operation.
 	 */
-	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
-					     XFS_ATTR_FORK);
-	if (error) {
+	error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
+	if (error)
 		return(error);
-	}
-	ASSERT(bp != NULL);
 
 	leaf = bp->b_addr;
-	ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	ASSERT(args->index < be16_to_cpu(leaf->hdr.count));
 	ASSERT(args->index >= 0);
 	entry = &leaf->entries[ args->index ];
@@ -2633,35 +2675,28 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args)
 	/*
 	 * Read the block containing the "old" attr
 	 */
-	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp1,
-					     XFS_ATTR_FORK);
-	if (error) {
-		return(error);
-	}
-	ASSERT(bp1 != NULL);
+	error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno, -1, &bp1);
+	if (error)
+		return error;
 
 	/*
 	 * Read the block containing the "new" attr, if it is different
 	 */
 	if (args->blkno2 != args->blkno) {
-		error = xfs_da_read_buf(args->trans, args->dp, args->blkno2,
-					-1, &bp2, XFS_ATTR_FORK);
-		if (error) {
-			return(error);
-		}
-		ASSERT(bp2 != NULL);
+		error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno2,
+					   -1, &bp2);
+		if (error)
+			return error;
 	} else {
 		bp2 = bp1;
 	}
 
 	leaf1 = bp1->b_addr;
-	ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	ASSERT(args->index < be16_to_cpu(leaf1->hdr.count));
 	ASSERT(args->index >= 0);
 	entry1 = &leaf1->entries[ args->index ];
 
 	leaf2 = bp2->b_addr;
-	ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
 	ASSERT(args->index2 < be16_to_cpu(leaf2->hdr.count));
 	ASSERT(args->index2 >= 0);
 	entry2 = &leaf2->entries[ args->index2 ];
@@ -2746,7 +2781,7 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp)
 	 * the extents in reverse order the extent containing
 	 * block 0 must still be there.
 	 */
-	error = xfs_da_read_buf(*trans, dp, 0, -1, &bp, XFS_ATTR_FORK);
+	error = xfs_da_node_read(*trans, dp, 0, -1, &bp, XFS_ATTR_FORK);
 	if (error)
 		return(error);
 	blkno = XFS_BUF_ADDR(bp);
@@ -2831,7 +2866,7 @@ xfs_attr_node_inactive(
 		 * traversal of the tree so we may deal with many blocks
 		 * before we come back to this one.
 		 */
-		error = xfs_da_read_buf(*trans, dp, child_fsb, -2, &child_bp,
+		error = xfs_da_node_read(*trans, dp, child_fsb, -2, &child_bp,
 						XFS_ATTR_FORK);
 		if (error)
 			return(error);
@@ -2872,8 +2907,8 @@ xfs_attr_node_inactive(
 		 * child block number.
 		 */
 		if ((i+1) < count) {
-			error = xfs_da_read_buf(*trans, dp, 0, parent_blkno,
-				&bp, XFS_ATTR_FORK);
+			error = xfs_da_node_read(*trans, dp, 0, parent_blkno,
+						 &bp, XFS_ATTR_FORK);
 			if (error)
 				return(error);
 			child_fsb = be32_to_cpu(node->btree[i+1].before);
diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h
index dea1772..77de139 100644
--- a/fs/xfs/xfs_attr_leaf.h
+++ b/fs/xfs/xfs_attr_leaf.h
@@ -261,4 +261,10 @@ int	xfs_attr_leaf_order(struct xfs_buf *leaf1_bp,
 				   struct xfs_buf *leaf2_bp);
 int	xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize,
 					int *local);
+int	xfs_attr_leaf_read(struct xfs_trans *tp, struct xfs_inode *dp,
+			xfs_dablk_t bno, xfs_daddr_t mappedbno,
+			struct xfs_buf **bpp);
+
+extern const struct xfs_buf_ops xfs_attr_leaf_buf_ops;
+
 #endif	/* __XFS_ATTR_LEAF_H__ */
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 83d0cf3..0e92d12 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -2662,8 +2662,9 @@ xfs_bmap_btree_to_extents(
 	if ((error = xfs_btree_check_lptr(cur, cbno, 1)))
 		return error;
 #endif
-	if ((error = xfs_btree_read_bufl(mp, tp, cbno, 0, &cbp,
-			XFS_BMAP_BTREE_REF)))
+	error = xfs_btree_read_bufl(mp, tp, cbno, 0, &cbp, XFS_BMAP_BTREE_REF,
+				&xfs_bmbt_buf_ops);
+	if (error)
 		return error;
 	cblock = XFS_BUF_TO_BLOCK(cbp);
 	if ((error = xfs_btree_check_block(cur, cblock, 0, cbp)))
@@ -3123,6 +3124,7 @@ xfs_bmap_extents_to_btree(
 	/*
 	 * Fill in the child block.
 	 */
+	abp->b_ops = &xfs_bmbt_buf_ops;
 	ablock = XFS_BUF_TO_BLOCK(abp);
 	ablock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
 	ablock->bb_level = 0;
@@ -3269,6 +3271,7 @@ xfs_bmap_local_to_extents(
 		ASSERT(args.len == 1);
 		*firstblock = args.fsbno;
 		bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);
+		bp->b_ops = &xfs_bmbt_buf_ops;
 		memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
 		xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
 		xfs_bmap_forkoff_reset(args.mp, ip, whichfork);
@@ -4078,8 +4081,9 @@ xfs_bmap_read_extents(
 	 * pointer (leftmost) at each level.
 	 */
 	while (level-- > 0) {
-		if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
-				XFS_BMAP_BTREE_REF)))
+		error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
+				XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops);
+		if (error)
 			return error;
 		block = XFS_BUF_TO_BLOCK(bp);
 		XFS_WANT_CORRUPTED_GOTO(
@@ -4124,7 +4128,8 @@ xfs_bmap_read_extents(
 		 */
 		nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
 		if (nextbno != NULLFSBLOCK)
-			xfs_btree_reada_bufl(mp, nextbno, 1);
+			xfs_btree_reada_bufl(mp, nextbno, 1,
+					     &xfs_bmbt_buf_ops);
 		/*
 		 * Copy records into the extent records.
 		 */
@@ -4156,8 +4161,9 @@ xfs_bmap_read_extents(
 		 */
 		if (bno == NULLFSBLOCK)
 			break;
-		if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
-				XFS_BMAP_BTREE_REF)))
+		error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
+				XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops);
+		if (error)
 			return error;
 		block = XFS_BUF_TO_BLOCK(bp);
 	}
@@ -5599,7 +5605,7 @@ xfs_getbmap(
 	xfs_ilock(ip, XFS_IOLOCK_SHARED);
 	if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) {
 		if (ip->i_delayed_blks || XFS_ISIZE(ip) > ip->i_d.di_size) {
-			error = xfs_flush_pages(ip, 0, -1, 0, FI_REMAPF);
+			error = -filemap_write_and_wait(VFS_I(ip)->i_mapping);
 			if (error)
 				goto out_unlock_iolock;
 		}
@@ -5868,15 +5874,16 @@ xfs_bmap_check_leaf_extents(
 	 */
 	while (level-- > 0) {
 		/* See if buf is in cur first */
+		bp_release = 0;
 		bp = xfs_bmap_get_bp(cur, XFS_FSB_TO_DADDR(mp, bno));
-		if (bp) {
-			bp_release = 0;
-		} else {
+		if (!bp) {
 			bp_release = 1;
+			error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp,
+						XFS_BMAP_BTREE_REF,
+						&xfs_bmbt_buf_ops);
+			if (error)
+				goto error_norelse;
 		}
-		if (!bp && (error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp,
-				XFS_BMAP_BTREE_REF)))
-			goto error_norelse;
 		block = XFS_BUF_TO_BLOCK(bp);
 		XFS_WANT_CORRUPTED_GOTO(
 			xfs_bmap_sanity_check(mp, bp, level),
@@ -5953,15 +5960,16 @@ xfs_bmap_check_leaf_extents(
 		if (bno == NULLFSBLOCK)
 			break;
 
+		bp_release = 0;
 		bp = xfs_bmap_get_bp(cur, XFS_FSB_TO_DADDR(mp, bno));
-		if (bp) {
-			bp_release = 0;
-		} else {
+		if (!bp) {
 			bp_release = 1;
+			error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp,
+						XFS_BMAP_BTREE_REF,
+						&xfs_bmbt_buf_ops);
+			if (error)
+				goto error_norelse;
 		}
-		if (!bp && (error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp,
-				XFS_BMAP_BTREE_REF)))
-			goto error_norelse;
 		block = XFS_BUF_TO_BLOCK(bp);
 	}
 	if (bp_release) {
@@ -6052,7 +6060,9 @@ xfs_bmap_count_tree(
 	struct xfs_btree_block	*block, *nextblock;
 	int			numrecs;
 
-	if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp, XFS_BMAP_BTREE_REF)))
+	error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp, XFS_BMAP_BTREE_REF,
+						&xfs_bmbt_buf_ops);
+	if (error)
 		return error;
 	*count += 1;
 	block = XFS_BUF_TO_BLOCK(bp);
@@ -6061,8 +6071,10 @@ xfs_bmap_count_tree(
 		/* Not at node above leaves, count this level of nodes */
 		nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
 		while (nextbno != NULLFSBLOCK) {
-			if ((error = xfs_btree_read_bufl(mp, tp, nextbno,
-				0, &nbp, XFS_BMAP_BTREE_REF)))
+			error = xfs_btree_read_bufl(mp, tp, nextbno, 0, &nbp,
+						XFS_BMAP_BTREE_REF,
+						&xfs_bmbt_buf_ops);
+			if (error)
 				return error;
 			*count += 1;
 			nextblock = XFS_BUF_TO_BLOCK(nbp);
@@ -6091,8 +6103,10 @@ xfs_bmap_count_tree(
 			if (nextbno == NULLFSBLOCK)
 				break;
 			bno = nextbno;
-			if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
-				XFS_BMAP_BTREE_REF)))
+			error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
+						XFS_BMAP_BTREE_REF,
+						&xfs_bmbt_buf_ops);
+			if (error)
 				return error;
 			*count += 1;
 			block = XFS_BUF_TO_BLOCK(bp);
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 862084a..061b45c 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -36,6 +36,7 @@
 #include "xfs_bmap.h"
 #include "xfs_error.h"
 #include "xfs_quota.h"
+#include "xfs_trace.h"
 
 /*
  * Determine the extent state.
@@ -707,6 +708,67 @@ xfs_bmbt_key_diff(
 				      cur->bc_rec.b.br_startoff;
 }
 
+static void
+xfs_bmbt_verify(
+	struct xfs_buf		*bp)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+	struct xfs_btree_block	*block = XFS_BUF_TO_BLOCK(bp);
+	unsigned int		level;
+	int			lblock_ok; /* block passes checks */
+
+	/* magic number and level verification.
+	 *
+	 * We don't know waht fork we belong to, so just verify that the level
+	 * is less than the maximum of the two. Later checks will be more
+	 * precise.
+	 */
+	level = be16_to_cpu(block->bb_level);
+	lblock_ok = block->bb_magic == cpu_to_be32(XFS_BMAP_MAGIC) &&
+		    level < max(mp->m_bm_maxlevels[0], mp->m_bm_maxlevels[1]);
+
+	/* numrecs verification */
+	lblock_ok = lblock_ok &&
+		be16_to_cpu(block->bb_numrecs) <= mp->m_bmap_dmxr[level != 0];
+
+	/* sibling pointer verification */
+	lblock_ok = lblock_ok &&
+		block->bb_u.l.bb_leftsib &&
+		(block->bb_u.l.bb_leftsib == cpu_to_be64(NULLDFSBNO) ||
+		 XFS_FSB_SANITY_CHECK(mp,
+			be64_to_cpu(block->bb_u.l.bb_leftsib))) &&
+		block->bb_u.l.bb_rightsib &&
+		(block->bb_u.l.bb_rightsib == cpu_to_be64(NULLDFSBNO) ||
+		 XFS_FSB_SANITY_CHECK(mp,
+			be64_to_cpu(block->bb_u.l.bb_rightsib)));
+
+	if (!lblock_ok) {
+		trace_xfs_btree_corrupt(bp, _RET_IP_);
+		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, block);
+		xfs_buf_ioerror(bp, EFSCORRUPTED);
+	}
+}
+
+static void
+xfs_bmbt_read_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_bmbt_verify(bp);
+}
+
+static void
+xfs_bmbt_write_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_bmbt_verify(bp);
+}
+
+const struct xfs_buf_ops xfs_bmbt_buf_ops = {
+	.verify_read = xfs_bmbt_read_verify,
+	.verify_write = xfs_bmbt_write_verify,
+};
+
+
 #ifdef DEBUG
 STATIC int
 xfs_bmbt_keys_inorder(
@@ -746,6 +808,7 @@ static const struct xfs_btree_ops xfs_bmbt_ops = {
 	.init_rec_from_cur	= xfs_bmbt_init_rec_from_cur,
 	.init_ptr_from_cur	= xfs_bmbt_init_ptr_from_cur,
 	.key_diff		= xfs_bmbt_key_diff,
+	.buf_ops		= &xfs_bmbt_buf_ops,
 #ifdef DEBUG
 	.keys_inorder		= xfs_bmbt_keys_inorder,
 	.recs_inorder		= xfs_bmbt_recs_inorder,
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index 0e66c4e..88469ca 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -236,5 +236,6 @@ extern int xfs_bmbt_maxrecs(struct xfs_mount *, int blocklen, int leaf);
 extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *,
 		struct xfs_trans *, struct xfs_inode *, int);
 
+extern const struct xfs_buf_ops xfs_bmbt_buf_ops;
 
 #endif	/* __XFS_BMAP_BTREE_H__ */
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index e53e317..db01040 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -266,9 +266,13 @@ xfs_btree_dup_cursor(
 	for (i = 0; i < new->bc_nlevels; i++) {
 		new->bc_ptrs[i] = cur->bc_ptrs[i];
 		new->bc_ra[i] = cur->bc_ra[i];
-		if ((bp = cur->bc_bufs[i])) {
-			if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
-				XFS_BUF_ADDR(bp), mp->m_bsize, 0, &bp))) {
+		bp = cur->bc_bufs[i];
+		if (bp) {
+			error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
+						   XFS_BUF_ADDR(bp), mp->m_bsize,
+						   0, &bp,
+						   cur->bc_ops->buf_ops);
+			if (error) {
 				xfs_btree_del_cursor(new, error);
 				*ncur = NULL;
 				return error;
@@ -609,25 +613,26 @@ xfs_btree_offsets(
  * Get a buffer for the block, return it read in.
  * Long-form addressing.
  */
-int					/* error */
+int
 xfs_btree_read_bufl(
-	xfs_mount_t	*mp,		/* file system mount point */
-	xfs_trans_t	*tp,		/* transaction pointer */
-	xfs_fsblock_t	fsbno,		/* file system block number */
-	uint		lock,		/* lock flags for read_buf */
-	xfs_buf_t	**bpp,		/* buffer for fsbno */
-	int		refval)		/* ref count value for buffer */
-{
-	xfs_buf_t	*bp;		/* return value */
+	struct xfs_mount	*mp,		/* file system mount point */
+	struct xfs_trans	*tp,		/* transaction pointer */
+	xfs_fsblock_t		fsbno,		/* file system block number */
+	uint			lock,		/* lock flags for read_buf */
+	struct xfs_buf		**bpp,		/* buffer for fsbno */
+	int			refval,		/* ref count value for buffer */
+	const struct xfs_buf_ops *ops)
+{
+	struct xfs_buf		*bp;		/* return value */
 	xfs_daddr_t		d;		/* real disk block address */
-	int		error;
+	int			error;
 
 	ASSERT(fsbno != NULLFSBLOCK);
 	d = XFS_FSB_TO_DADDR(mp, fsbno);
-	if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
-			mp->m_bsize, lock, &bp))) {
+	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
+				   mp->m_bsize, lock, &bp, ops);
+	if (error)
 		return error;
-	}
 	ASSERT(!xfs_buf_geterror(bp));
 	if (bp)
 		xfs_buf_set_ref(bp, refval);
@@ -642,15 +647,16 @@ xfs_btree_read_bufl(
 /* ARGSUSED */
 void
 xfs_btree_reada_bufl(
-	xfs_mount_t	*mp,		/* file system mount point */
-	xfs_fsblock_t	fsbno,		/* file system block number */
-	xfs_extlen_t	count)		/* count of filesystem blocks */
+	struct xfs_mount	*mp,		/* file system mount point */
+	xfs_fsblock_t		fsbno,		/* file system block number */
+	xfs_extlen_t		count,		/* count of filesystem blocks */
+	const struct xfs_buf_ops *ops)
 {
 	xfs_daddr_t		d;
 
 	ASSERT(fsbno != NULLFSBLOCK);
 	d = XFS_FSB_TO_DADDR(mp, fsbno);
-	xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count);
+	xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count, ops);
 }
 
 /*
@@ -660,17 +666,18 @@ xfs_btree_reada_bufl(
 /* ARGSUSED */
 void
 xfs_btree_reada_bufs(
-	xfs_mount_t	*mp,		/* file system mount point */
-	xfs_agnumber_t	agno,		/* allocation group number */
-	xfs_agblock_t	agbno,		/* allocation group block number */
-	xfs_extlen_t	count)		/* count of filesystem blocks */
+	struct xfs_mount	*mp,		/* file system mount point */
+	xfs_agnumber_t		agno,		/* allocation group number */
+	xfs_agblock_t		agbno,		/* allocation group block number */
+	xfs_extlen_t		count,		/* count of filesystem blocks */
+	const struct xfs_buf_ops *ops)
 {
 	xfs_daddr_t		d;
 
 	ASSERT(agno != NULLAGNUMBER);
 	ASSERT(agbno != NULLAGBLOCK);
 	d = XFS_AGB_TO_DADDR(mp, agno, agbno);
-	xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count);
+	xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count, ops);
 }
 
 STATIC int
@@ -684,12 +691,14 @@ xfs_btree_readahead_lblock(
 	xfs_dfsbno_t		right = be64_to_cpu(block->bb_u.l.bb_rightsib);
 
 	if ((lr & XFS_BTCUR_LEFTRA) && left != NULLDFSBNO) {
-		xfs_btree_reada_bufl(cur->bc_mp, left, 1);
+		xfs_btree_reada_bufl(cur->bc_mp, left, 1,
+				     cur->bc_ops->buf_ops);
 		rval++;
 	}
 
 	if ((lr & XFS_BTCUR_RIGHTRA) && right != NULLDFSBNO) {
-		xfs_btree_reada_bufl(cur->bc_mp, right, 1);
+		xfs_btree_reada_bufl(cur->bc_mp, right, 1,
+				     cur->bc_ops->buf_ops);
 		rval++;
 	}
 
@@ -709,13 +718,13 @@ xfs_btree_readahead_sblock(
 
 	if ((lr & XFS_BTCUR_LEFTRA) && left != NULLAGBLOCK) {
 		xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno,
-				     left, 1);
+				     left, 1, cur->bc_ops->buf_ops);
 		rval++;
 	}
 
 	if ((lr & XFS_BTCUR_RIGHTRA) && right != NULLAGBLOCK) {
 		xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno,
-				     right, 1);
+				     right, 1, cur->bc_ops->buf_ops);
 		rval++;
 	}
 
@@ -853,18 +862,22 @@ xfs_btree_set_sibling(
 	}
 }
 
-STATIC void
+void
 xfs_btree_init_block(
-	struct xfs_btree_cur	*cur,
-	int			level,
-	int			numrecs,
-	struct xfs_btree_block	*new)	/* new block */
+	struct xfs_mount *mp,
+	struct xfs_buf	*bp,
+	__u32		magic,
+	__u16		level,
+	__u16		numrecs,
+	unsigned int	flags)
 {
-	new->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]);
+	struct xfs_btree_block	*new = XFS_BUF_TO_BLOCK(bp);
+
+	new->bb_magic = cpu_to_be32(magic);
 	new->bb_level = cpu_to_be16(level);
 	new->bb_numrecs = cpu_to_be16(numrecs);
 
-	if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
+	if (flags & XFS_BTREE_LONG_PTRS) {
 		new->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
 		new->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
 	} else {
@@ -873,6 +886,17 @@ xfs_btree_init_block(
 	}
 }
 
+STATIC void
+xfs_btree_init_block_cur(
+	struct xfs_btree_cur	*cur,
+	int			level,
+	int			numrecs,
+	struct xfs_buf		*bp)
+{
+	xfs_btree_init_block(cur->bc_mp, bp, xfs_magics[cur->bc_btnum],
+			       level, numrecs, cur->bc_flags);
+}
+
 /*
  * Return true if ptr is the last record in the btree and
  * we need to track updateѕ to this record.  The decision
@@ -972,6 +996,7 @@ xfs_btree_get_buf_block(
 	if (!*bpp)
 		return ENOMEM;
 
+	(*bpp)->b_ops = cur->bc_ops->buf_ops;
 	*block = XFS_BUF_TO_BLOCK(*bpp);
 	return 0;
 }
@@ -998,19 +1023,15 @@ xfs_btree_read_buf_block(
 
 	d = xfs_btree_ptr_to_daddr(cur, ptr);
 	error = xfs_trans_read_buf(mp, cur->bc_tp, mp->m_ddev_targp, d,
-				   mp->m_bsize, flags, bpp);
+				   mp->m_bsize, flags, bpp,
+				   cur->bc_ops->buf_ops);
 	if (error)
 		return error;
 
 	ASSERT(!xfs_buf_geterror(*bpp));
-
 	xfs_btree_set_refs(cur, *bpp);
 	*block = XFS_BUF_TO_BLOCK(*bpp);
-
-	error = xfs_btree_check_block(cur, *block, level, *bpp);
-	if (error)
-		xfs_trans_brelse(cur->bc_tp, *bpp);
-	return error;
+	return 0;
 }
 
 /*
@@ -2183,7 +2204,7 @@ xfs_btree_split(
 		goto error0;
 
 	/* Fill in the btree header for the new right block. */
-	xfs_btree_init_block(cur, xfs_btree_get_level(left), 0, right);
+	xfs_btree_init_block_cur(cur, xfs_btree_get_level(left), 0, rbp);
 
 	/*
 	 * Split the entries between the old and the new block evenly.
@@ -2492,7 +2513,7 @@ xfs_btree_new_root(
 		nptr = 2;
 	}
 	/* Fill in the new block's btree header and log it. */
-	xfs_btree_init_block(cur, cur->bc_nlevels, 2, new);
+	xfs_btree_init_block_cur(cur, cur->bc_nlevels, 2, nbp);
 	xfs_btree_log_block(cur, nbp, XFS_BB_ALL_BITS);
 	ASSERT(!xfs_btree_ptr_is_null(cur, &lptr) &&
 			!xfs_btree_ptr_is_null(cur, &rptr));
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index 5b240de..f932897 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -188,6 +188,8 @@ struct xfs_btree_ops {
 	__int64_t (*key_diff)(struct xfs_btree_cur *cur,
 			      union xfs_btree_key *key);
 
+	const struct xfs_buf_ops	*buf_ops;
+
 #ifdef DEBUG
 	/* check that k1 is lower than k2 */
 	int	(*keys_inorder)(struct xfs_btree_cur *cur,
@@ -355,7 +357,8 @@ xfs_btree_read_bufl(
 	xfs_fsblock_t		fsbno,	/* file system block number */
 	uint			lock,	/* lock flags for read_buf */
 	struct xfs_buf		**bpp,	/* buffer for fsbno */
-	int			refval);/* ref count value for buffer */
+	int			refval,	/* ref count value for buffer */
+	const struct xfs_buf_ops *ops);
 
 /*
  * Read-ahead the block, don't wait for it, don't return a buffer.
@@ -365,7 +368,8 @@ void					/* error */
 xfs_btree_reada_bufl(
 	struct xfs_mount	*mp,	/* file system mount point */
 	xfs_fsblock_t		fsbno,	/* file system block number */
-	xfs_extlen_t		count);	/* count of filesystem blocks */
+	xfs_extlen_t		count,	/* count of filesystem blocks */
+	const struct xfs_buf_ops *ops);
 
 /*
  * Read-ahead the block, don't wait for it, don't return a buffer.
@@ -376,8 +380,20 @@ xfs_btree_reada_bufs(
 	struct xfs_mount	*mp,	/* file system mount point */
 	xfs_agnumber_t		agno,	/* allocation group number */
 	xfs_agblock_t		agbno,	/* allocation group block number */
-	xfs_extlen_t		count);	/* count of filesystem blocks */
+	xfs_extlen_t		count,	/* count of filesystem blocks */
+	const struct xfs_buf_ops *ops);
 
+/*
+ * Initialise a new btree block header
+ */
+void
+xfs_btree_init_block(
+	struct xfs_mount *mp,
+	struct xfs_buf	*bp,
+	__u32		magic,
+	__u16		level,
+	__u16		numrecs,
+	unsigned int	flags);
 
 /*
  * Common btree core entry points.
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 4b0b8dd..26673a0 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -569,7 +569,9 @@ found:
 	 */
 	if (bp->b_flags & XBF_STALE) {
 		ASSERT((bp->b_flags & _XBF_DELWRI_Q) == 0);
+		ASSERT(bp->b_iodone == NULL);
 		bp->b_flags &= _XBF_KMEM | _XBF_PAGES;
+		bp->b_ops = NULL;
 	}
 
 	trace_xfs_buf_find(bp, flags, _RET_IP_);
@@ -654,7 +656,8 @@ xfs_buf_read_map(
 	struct xfs_buftarg	*target,
 	struct xfs_buf_map	*map,
 	int			nmaps,
-	xfs_buf_flags_t		flags)
+	xfs_buf_flags_t		flags,
+	const struct xfs_buf_ops *ops)
 {
 	struct xfs_buf		*bp;
 
@@ -666,6 +669,7 @@ xfs_buf_read_map(
 
 		if (!XFS_BUF_ISDONE(bp)) {
 			XFS_STATS_INC(xb_get_read);
+			bp->b_ops = ops;
 			_xfs_buf_read(bp, flags);
 		} else if (flags & XBF_ASYNC) {
 			/*
@@ -691,13 +695,14 @@ void
 xfs_buf_readahead_map(
 	struct xfs_buftarg	*target,
 	struct xfs_buf_map	*map,
-	int			nmaps)
+	int			nmaps,
+	const struct xfs_buf_ops *ops)
 {
 	if (bdi_read_congested(target->bt_bdi))
 		return;
 
 	xfs_buf_read_map(target, map, nmaps,
-		     XBF_TRYLOCK|XBF_ASYNC|XBF_READ_AHEAD);
+		     XBF_TRYLOCK|XBF_ASYNC|XBF_READ_AHEAD, ops);
 }
 
 /*
@@ -709,10 +714,10 @@ xfs_buf_read_uncached(
 	struct xfs_buftarg	*target,
 	xfs_daddr_t		daddr,
 	size_t			numblks,
-	int			flags)
+	int			flags,
+	const struct xfs_buf_ops *ops)
 {
-	xfs_buf_t		*bp;
-	int			error;
+	struct xfs_buf		*bp;
 
 	bp = xfs_buf_get_uncached(target, numblks, flags);
 	if (!bp)
@@ -723,13 +728,10 @@ xfs_buf_read_uncached(
 	bp->b_bn = daddr;
 	bp->b_maps[0].bm_bn = daddr;
 	bp->b_flags |= XBF_READ;
+	bp->b_ops = ops;
 
 	xfsbdstrat(target->bt_mount, bp);
-	error = xfs_buf_iowait(bp);
-	if (error) {
-		xfs_buf_relse(bp);
-		return NULL;
-	}
+	xfs_buf_iowait(bp);
 	return bp;
 }
 
@@ -999,27 +1001,37 @@ STATIC void
 xfs_buf_iodone_work(
 	struct work_struct	*work)
 {
-	xfs_buf_t		*bp =
+	struct xfs_buf		*bp =
 		container_of(work, xfs_buf_t, b_iodone_work);
+	bool			read = !!(bp->b_flags & XBF_READ);
+
+	bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD);
+	if (read && bp->b_ops)
+		bp->b_ops->verify_read(bp);
 
 	if (bp->b_iodone)
 		(*(bp->b_iodone))(bp);
 	else if (bp->b_flags & XBF_ASYNC)
 		xfs_buf_relse(bp);
+	else {
+		ASSERT(read && bp->b_ops);
+		complete(&bp->b_iowait);
+	}
 }
 
 void
 xfs_buf_ioend(
-	xfs_buf_t		*bp,
-	int			schedule)
+	struct xfs_buf	*bp,
+	int		schedule)
 {
+	bool		read = !!(bp->b_flags & XBF_READ);
+
 	trace_xfs_buf_iodone(bp, _RET_IP_);
 
-	bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD);
 	if (bp->b_error == 0)
 		bp->b_flags |= XBF_DONE;
 
-	if ((bp->b_iodone) || (bp->b_flags & XBF_ASYNC)) {
+	if (bp->b_iodone || (read && bp->b_ops) || (bp->b_flags & XBF_ASYNC)) {
 		if (schedule) {
 			INIT_WORK(&bp->b_iodone_work, xfs_buf_iodone_work);
 			queue_work(xfslogd_workqueue, &bp->b_iodone_work);
@@ -1027,6 +1039,7 @@ xfs_buf_ioend(
 			xfs_buf_iodone_work(&bp->b_iodone_work);
 		}
 	} else {
+		bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD);
 		complete(&bp->b_iowait);
 	}
 }
@@ -1314,6 +1327,20 @@ _xfs_buf_ioapply(
 			rw |= REQ_FUA;
 		if (bp->b_flags & XBF_FLUSH)
 			rw |= REQ_FLUSH;
+
+		/*
+		 * Run the write verifier callback function if it exists. If
+		 * this function fails it will mark the buffer with an error and
+		 * the IO should not be dispatched.
+		 */
+		if (bp->b_ops) {
+			bp->b_ops->verify_write(bp);
+			if (bp->b_error) {
+				xfs_force_shutdown(bp->b_target->bt_mount,
+						   SHUTDOWN_CORRUPT_INCORE);
+				return;
+			}
+		}
 	} else if (bp->b_flags & XBF_READ_AHEAD) {
 		rw = READA;
 	} else {
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index 7c0b6a0..23f5642 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -100,6 +100,7 @@ typedef struct xfs_buftarg {
 struct xfs_buf;
 typedef void (*xfs_buf_iodone_t)(struct xfs_buf *);
 
+
 #define XB_PAGES	2
 
 struct xfs_buf_map {
@@ -110,6 +111,11 @@ struct xfs_buf_map {
 #define DEFINE_SINGLE_BUF_MAP(map, blkno, numblk) \
 	struct xfs_buf_map (map) = { .bm_bn = (blkno), .bm_len = (numblk) };
 
+struct xfs_buf_ops {
+	void (*verify_read)(struct xfs_buf *);
+	void (*verify_write)(struct xfs_buf *);
+};
+
 typedef struct xfs_buf {
 	/*
 	 * first cacheline holds all the fields needed for an uncontended cache
@@ -153,13 +159,13 @@ typedef struct xfs_buf {
 	unsigned int		b_page_count;	/* size of page array */
 	unsigned int		b_offset;	/* page offset in first page */
 	unsigned short		b_error;	/* error code on I/O */
+	const struct xfs_buf_ops	*b_ops;
 
 #ifdef XFS_BUF_LOCK_TRACKING
 	int			b_last_holder;
 #endif
 } xfs_buf_t;
 
-
 /* Finding and Reading Buffers */
 struct xfs_buf *_xfs_buf_find(struct xfs_buftarg *target,
 			      struct xfs_buf_map *map, int nmaps,
@@ -196,9 +202,11 @@ struct xfs_buf *xfs_buf_get_map(struct xfs_buftarg *target,
 			       xfs_buf_flags_t flags);
 struct xfs_buf *xfs_buf_read_map(struct xfs_buftarg *target,
 			       struct xfs_buf_map *map, int nmaps,
-			       xfs_buf_flags_t flags);
+			       xfs_buf_flags_t flags,
+			       const struct xfs_buf_ops *ops);
 void xfs_buf_readahead_map(struct xfs_buftarg *target,
-			       struct xfs_buf_map *map, int nmaps);
+			       struct xfs_buf_map *map, int nmaps,
+			       const struct xfs_buf_ops *ops);
 
 static inline struct xfs_buf *
 xfs_buf_get(
@@ -216,20 +224,22 @@ xfs_buf_read(
 	struct xfs_buftarg	*target,
 	xfs_daddr_t		blkno,
 	size_t			numblks,
-	xfs_buf_flags_t		flags)
+	xfs_buf_flags_t		flags,
+	const struct xfs_buf_ops *ops)
 {
 	DEFINE_SINGLE_BUF_MAP(map, blkno, numblks);
-	return xfs_buf_read_map(target, &map, 1, flags);
+	return xfs_buf_read_map(target, &map, 1, flags, ops);
 }
 
 static inline void
 xfs_buf_readahead(
 	struct xfs_buftarg	*target,
 	xfs_daddr_t		blkno,
-	size_t			numblks)
+	size_t			numblks,
+	const struct xfs_buf_ops *ops)
 {
 	DEFINE_SINGLE_BUF_MAP(map, blkno, numblks);
-	return xfs_buf_readahead_map(target, &map, 1);
+	return xfs_buf_readahead_map(target, &map, 1, ops);
 }
 
 struct xfs_buf *xfs_buf_get_empty(struct xfs_buftarg *target, size_t numblks);
@@ -239,7 +249,8 @@ int xfs_buf_associate_memory(struct xfs_buf *bp, void *mem, size_t length);
 struct xfs_buf *xfs_buf_get_uncached(struct xfs_buftarg *target, size_t numblks,
 				int flags);
 struct xfs_buf *xfs_buf_read_uncached(struct xfs_buftarg *target,
-				xfs_daddr_t daddr, size_t numblks, int flags);
+				xfs_daddr_t daddr, size_t numblks, int flags,
+				const struct xfs_buf_ops *ops);
 void xfs_buf_hold(struct xfs_buf *bp);
 
 /* Releasing Buffers */
diff --git a/fs/xfs/xfs_cksum.h b/fs/xfs/xfs_cksum.h
new file mode 100644
index 0000000..fad1676
--- /dev/null
+++ b/fs/xfs/xfs_cksum.h
@@ -0,0 +1,63 @@
+#ifndef _XFS_CKSUM_H
+#define _XFS_CKSUM_H 1
+
+#define XFS_CRC_SEED	(~(__uint32_t)0)
+
+/*
+ * Calculate the intermediate checksum for a buffer that has the CRC field
+ * inside it.  The offset of the 32bit crc fields is passed as the
+ * cksum_offset parameter.
+ */
+static inline __uint32_t
+xfs_start_cksum(char *buffer, size_t length, unsigned long cksum_offset)
+{
+	__uint32_t zero = 0;
+	__uint32_t crc;
+
+	/* Calculate CRC up to the checksum. */
+	crc = crc32c(XFS_CRC_SEED, buffer, cksum_offset);
+
+	/* Skip checksum field */
+	crc = crc32c(crc, &zero, sizeof(__u32));
+
+	/* Calculate the rest of the CRC. */
+	return crc32c(crc, &buffer[cksum_offset + sizeof(__be32)],
+		      length - (cksum_offset + sizeof(__be32)));
+}
+
+/*
+ * Convert the intermediate checksum to the final ondisk format.
+ *
+ * The CRC32c calculation uses LE format even on BE machines, but returns the
+ * result in host endian format. Hence we need to byte swap it back to LE format
+ * so that it is consistent on disk.
+ */
+static inline __le32
+xfs_end_cksum(__uint32_t crc)
+{
+	return ~cpu_to_le32(crc);
+}
+
+/*
+ * Helper to generate the checksum for a buffer.
+ */
+static inline void
+xfs_update_cksum(char *buffer, size_t length, unsigned long cksum_offset)
+{
+	__uint32_t crc = xfs_start_cksum(buffer, length, cksum_offset);
+
+	*(__le32 *)(buffer + cksum_offset) = xfs_end_cksum(crc);
+}
+
+/*
+ * Helper to verify the checksum for a buffer.
+ */
+static inline int
+xfs_verify_cksum(char *buffer, size_t length, unsigned long cksum_offset)
+{
+	__uint32_t crc = xfs_start_cksum(buffer, length, cksum_offset);
+
+	return *(__le32 *)(buffer + cksum_offset) == xfs_end_cksum(crc);
+}
+
+#endif /* _XFS_CKSUM_H */
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 7bfb7dd..4d7696a 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -91,6 +91,84 @@ STATIC int	xfs_da_blk_unlink(xfs_da_state_t *state,
 				  xfs_da_state_blk_t *save_blk);
 STATIC void	xfs_da_state_kill_altpath(xfs_da_state_t *state);
 
+static void
+xfs_da_node_verify(
+	struct xfs_buf		*bp)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+	struct xfs_da_node_hdr *hdr = bp->b_addr;
+	int			block_ok = 0;
+
+	block_ok = hdr->info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC);
+	block_ok = block_ok &&
+			be16_to_cpu(hdr->level) > 0 &&
+			be16_to_cpu(hdr->count) > 0 ;
+	if (!block_ok) {
+		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr);
+		xfs_buf_ioerror(bp, EFSCORRUPTED);
+	}
+
+}
+
+static void
+xfs_da_node_write_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_da_node_verify(bp);
+}
+
+/*
+ * leaf/node format detection on trees is sketchy, so a node read can be done on
+ * leaf level blocks when detection identifies the tree as a node format tree
+ * incorrectly. In this case, we need to swap the verifier to match the correct
+ * format of the block being read.
+ */
+static void
+xfs_da_node_read_verify(
+	struct xfs_buf		*bp)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+	struct xfs_da_blkinfo	*info = bp->b_addr;
+
+	switch (be16_to_cpu(info->magic)) {
+		case XFS_DA_NODE_MAGIC:
+			xfs_da_node_verify(bp);
+			break;
+		case XFS_ATTR_LEAF_MAGIC:
+			bp->b_ops = &xfs_attr_leaf_buf_ops;
+			bp->b_ops->verify_read(bp);
+			return;
+		case XFS_DIR2_LEAFN_MAGIC:
+			bp->b_ops = &xfs_dir2_leafn_buf_ops;
+			bp->b_ops->verify_read(bp);
+			return;
+		default:
+			XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
+					     mp, info);
+			xfs_buf_ioerror(bp, EFSCORRUPTED);
+			break;
+	}
+}
+
+const struct xfs_buf_ops xfs_da_node_buf_ops = {
+	.verify_read = xfs_da_node_read_verify,
+	.verify_write = xfs_da_node_write_verify,
+};
+
+
+int
+xfs_da_node_read(
+	struct xfs_trans	*tp,
+	struct xfs_inode	*dp,
+	xfs_dablk_t		bno,
+	xfs_daddr_t		mappedbno,
+	struct xfs_buf		**bpp,
+	int			which_fork)
+{
+	return xfs_da_read_buf(tp, dp, bno, mappedbno, bpp,
+					which_fork, &xfs_da_node_buf_ops);
+}
+
 /*========================================================================
  * Routines used for growing the Btree.
  *========================================================================*/
@@ -125,6 +203,7 @@ xfs_da_node_create(xfs_da_args_t *args, xfs_dablk_t blkno, int level,
 	xfs_trans_log_buf(tp, bp,
 		XFS_DA_LOGRANGE(node, &node->hdr, sizeof(node->hdr)));
 
+	bp->b_ops = &xfs_da_node_buf_ops;
 	*bpp = bp;
 	return(0);
 }
@@ -324,6 +403,8 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
 	}
 	memcpy(node, oldroot, size);
 	xfs_trans_log_buf(tp, bp, 0, size - 1);
+
+	bp->b_ops = blk1->bp->b_ops;
 	blk1->bp = bp;
 	blk1->blkno = blkno;
 
@@ -746,7 +827,7 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk)
 	 */
 	child = be32_to_cpu(oldroot->btree[0].before);
 	ASSERT(child != 0);
-	error = xfs_da_read_buf(args->trans, args->dp, child, -1, &bp,
+	error = xfs_da_node_read(args->trans, args->dp, child, -1, &bp,
 					     args->whichfork);
 	if (error)
 		return(error);
@@ -754,7 +835,14 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk)
 	xfs_da_blkinfo_onlychild_validate(bp->b_addr,
 					be16_to_cpu(oldroot->hdr.level));
 
+	/*
+	 * This could be copying a leaf back into the root block in the case of
+	 * there only being a single leaf block left in the tree. Hence we have
+	 * to update the b_ops pointer as well to match the buffer type change
+	 * that could occur.
+	 */
 	memcpy(root_blk->bp->b_addr, bp->b_addr, state->blocksize);
+	root_blk->bp->b_ops = bp->b_ops;
 	xfs_trans_log_buf(args->trans, root_blk->bp, 0, state->blocksize - 1);
 	error = xfs_da_shrink_inode(args, child, bp);
 	return(error);
@@ -779,6 +867,8 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action)
 	xfs_dablk_t blkno;
 	struct xfs_buf *bp;
 
+	trace_xfs_da_node_toosmall(state->args);
+
 	/*
 	 * Check for the degenerate case of the block being over 50% full.
 	 * If so, it's not worth even looking to see if we might be able
@@ -835,7 +925,7 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action)
 			blkno = be32_to_cpu(info->back);
 		if (blkno == 0)
 			continue;
-		error = xfs_da_read_buf(state->args->trans, state->args->dp,
+		error = xfs_da_node_read(state->args->trans, state->args->dp,
 					blkno, -1, &bp, state->args->whichfork);
 		if (error)
 			return(error);
@@ -900,6 +990,8 @@ xfs_da_fixhashpath(xfs_da_state_t *state, xfs_da_state_path_t *path)
 	xfs_dahash_t lasthash=0;
 	int level, count;
 
+	trace_xfs_da_fixhashpath(state->args);
+
 	level = path->active-1;
 	blk = &path->blk[ level ];
 	switch (blk->magic) {
@@ -1079,7 +1171,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
 		 * Read the next node down in the tree.
 		 */
 		blk->blkno = blkno;
-		error = xfs_da_read_buf(args->trans, args->dp, blkno,
+		error = xfs_da_node_read(args->trans, args->dp, blkno,
 					-1, &blk->bp, args->whichfork);
 		if (error) {
 			blk->blkno = 0;
@@ -1241,7 +1333,7 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
 		new_info->forw = cpu_to_be32(old_blk->blkno);
 		new_info->back = old_info->back;
 		if (old_info->back) {
-			error = xfs_da_read_buf(args->trans, args->dp,
+			error = xfs_da_node_read(args->trans, args->dp,
 						be32_to_cpu(old_info->back),
 						-1, &bp, args->whichfork);
 			if (error)
@@ -1262,7 +1354,7 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
 		new_info->forw = old_info->forw;
 		new_info->back = cpu_to_be32(old_blk->blkno);
 		if (old_info->forw) {
-			error = xfs_da_read_buf(args->trans, args->dp,
+			error = xfs_da_node_read(args->trans, args->dp,
 						be32_to_cpu(old_info->forw),
 						-1, &bp, args->whichfork);
 			if (error)
@@ -1362,7 +1454,7 @@ xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
 		trace_xfs_da_unlink_back(args);
 		save_info->back = drop_info->back;
 		if (drop_info->back) {
-			error = xfs_da_read_buf(args->trans, args->dp,
+			error = xfs_da_node_read(args->trans, args->dp,
 						be32_to_cpu(drop_info->back),
 						-1, &bp, args->whichfork);
 			if (error)
@@ -1379,7 +1471,7 @@ xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
 		trace_xfs_da_unlink_forward(args);
 		save_info->forw = drop_info->forw;
 		if (drop_info->forw) {
-			error = xfs_da_read_buf(args->trans, args->dp,
+			error = xfs_da_node_read(args->trans, args->dp,
 						be32_to_cpu(drop_info->forw),
 						-1, &bp, args->whichfork);
 			if (error)
@@ -1417,6 +1509,8 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
 	xfs_dablk_t blkno=0;
 	int level, error;
 
+	trace_xfs_da_path_shift(state->args);
+
 	/*
 	 * Roll up the Btree looking for the first block where our
 	 * current index is not at the edge of the block.  Note that
@@ -1463,8 +1557,8 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
 		 * Read the next child block.
 		 */
 		blk->blkno = blkno;
-		error = xfs_da_read_buf(args->trans, args->dp, blkno, -1,
-						     &blk->bp, args->whichfork);
+		error = xfs_da_node_read(args->trans, args->dp, blkno, -1,
+					&blk->bp, args->whichfork);
 		if (error)
 			return(error);
 		ASSERT(blk->bp != NULL);
@@ -1727,7 +1821,8 @@ xfs_da_swap_lastblock(
 	 * Read the last block in the btree space.
 	 */
 	last_blkno = (xfs_dablk_t)lastoff - mp->m_dirblkfsbs;
-	if ((error = xfs_da_read_buf(tp, ip, last_blkno, -1, &last_buf, w)))
+	error = xfs_da_node_read(tp, ip, last_blkno, -1, &last_buf, w);
+	if (error)
 		return error;
 	/*
 	 * Copy the last block into the dead buffer and log it.
@@ -1753,7 +1848,8 @@ xfs_da_swap_lastblock(
 	 * If the moved block has a left sibling, fix up the pointers.
 	 */
 	if ((sib_blkno = be32_to_cpu(dead_info->back))) {
-		if ((error = xfs_da_read_buf(tp, ip, sib_blkno, -1, &sib_buf, w)))
+		error = xfs_da_node_read(tp, ip, sib_blkno, -1, &sib_buf, w);
+		if (error)
 			goto done;
 		sib_info = sib_buf->b_addr;
 		if (unlikely(
@@ -1774,7 +1870,8 @@ xfs_da_swap_lastblock(
 	 * If the moved block has a right sibling, fix up the pointers.
 	 */
 	if ((sib_blkno = be32_to_cpu(dead_info->forw))) {
-		if ((error = xfs_da_read_buf(tp, ip, sib_blkno, -1, &sib_buf, w)))
+		error = xfs_da_node_read(tp, ip, sib_blkno, -1, &sib_buf, w);
+		if (error)
 			goto done;
 		sib_info = sib_buf->b_addr;
 		if (unlikely(
@@ -1797,7 +1894,8 @@ xfs_da_swap_lastblock(
 	 * Walk down the tree looking for the parent of the moved block.
 	 */
 	for (;;) {
-		if ((error = xfs_da_read_buf(tp, ip, par_blkno, -1, &par_buf, w)))
+		error = xfs_da_node_read(tp, ip, par_blkno, -1, &par_buf, w);
+		if (error)
 			goto done;
 		par_node = par_buf->b_addr;
 		if (unlikely(par_node->hdr.info.magic !=
@@ -1847,7 +1945,8 @@ xfs_da_swap_lastblock(
 			error = XFS_ERROR(EFSCORRUPTED);
 			goto done;
 		}
-		if ((error = xfs_da_read_buf(tp, ip, par_blkno, -1, &par_buf, w)))
+		error = xfs_da_node_read(tp, ip, par_blkno, -1, &par_buf, w);
+		if (error)
 			goto done;
 		par_node = par_buf->b_addr;
 		if (unlikely(
@@ -2133,7 +2232,8 @@ xfs_da_read_buf(
 	xfs_dablk_t		bno,
 	xfs_daddr_t		mappedbno,
 	struct xfs_buf		**bpp,
-	int			whichfork)
+	int			whichfork,
+	const struct xfs_buf_ops *ops)
 {
 	struct xfs_buf		*bp;
 	struct xfs_buf_map	map;
@@ -2155,7 +2255,7 @@ xfs_da_read_buf(
 
 	error = xfs_trans_read_buf_map(dp->i_mount, trans,
 					dp->i_mount->m_ddev_targp,
-					mapp, nmap, 0, &bp);
+					mapp, nmap, 0, &bp, ops);
 	if (error)
 		goto out_free;
 
@@ -2211,9 +2311,10 @@ xfs_da_reada_buf(
 	struct xfs_trans	*trans,
 	struct xfs_inode	*dp,
 	xfs_dablk_t		bno,
-	int			whichfork)
+	xfs_daddr_t		mappedbno,
+	int			whichfork,
+	const struct xfs_buf_ops *ops)
 {
-	xfs_daddr_t		mappedbno = -1;
 	struct xfs_buf_map	map;
 	struct xfs_buf_map	*mapp;
 	int			nmap;
@@ -2221,7 +2322,7 @@ xfs_da_reada_buf(
 
 	mapp = &map;
 	nmap = 1;
-	error = xfs_dabuf_map(trans, dp, bno, -1, whichfork,
+	error = xfs_dabuf_map(trans, dp, bno, mappedbno, whichfork,
 				&mapp, &nmap);
 	if (error) {
 		/* mapping a hole is not an error, but we don't continue */
@@ -2231,7 +2332,7 @@ xfs_da_reada_buf(
 	}
 
 	mappedbno = mapp[0].bm_bn;
-	xfs_buf_readahead_map(dp->i_mount->m_ddev_targp, mapp, nmap);
+	xfs_buf_readahead_map(dp->i_mount->m_ddev_targp, mapp, nmap, ops);
 
 out_free:
 	if (mapp != &map)
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index 132adaf..ee5170c 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -18,7 +18,6 @@
 #ifndef __XFS_DA_BTREE_H__
 #define	__XFS_DA_BTREE_H__
 
-struct xfs_buf;
 struct xfs_bmap_free;
 struct xfs_inode;
 struct xfs_mount;
@@ -214,6 +213,9 @@ int	xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
  */
 int	xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
 				       xfs_da_state_blk_t *new_blk);
+int	xfs_da_node_read(struct xfs_trans *tp, struct xfs_inode *dp,
+			 xfs_dablk_t bno, xfs_daddr_t mappedbno,
+			 struct xfs_buf **bpp, int which_fork);
 
 /*
  * Utility routines.
@@ -226,9 +228,11 @@ int	xfs_da_get_buf(struct xfs_trans *trans, struct xfs_inode *dp,
 			      struct xfs_buf **bp, int whichfork);
 int	xfs_da_read_buf(struct xfs_trans *trans, struct xfs_inode *dp,
 			       xfs_dablk_t bno, xfs_daddr_t mappedbno,
-			       struct xfs_buf **bpp, int whichfork);
+			       struct xfs_buf **bpp, int whichfork,
+			       const struct xfs_buf_ops *ops);
 xfs_daddr_t	xfs_da_reada_buf(struct xfs_trans *trans, struct xfs_inode *dp,
-			xfs_dablk_t bno, int whichfork);
+				xfs_dablk_t bno, xfs_daddr_t mapped_bno,
+				int whichfork, const struct xfs_buf_ops *ops);
 int	xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
 					  struct xfs_buf *dead_buf);
 
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index b9b8646..d0e9c74 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -246,12 +246,10 @@ xfs_swap_extents(
 		goto out_unlock;
 	}
 
-	if (VN_CACHED(VFS_I(tip)) != 0) {
-		error = xfs_flushinval_pages(tip, 0, -1,
-				FI_REMAPF_LOCKED);
-		if (error)
-			goto out_unlock;
-	}
+	error = -filemap_write_and_wait(VFS_I(ip)->i_mapping);
+	if (error)
+		goto out_unlock;
+	truncate_pagecache_range(VFS_I(ip), 0, -1);
 
 	/* Verify O_DIRECT for ftmp */
 	if (VN_CACHED(VFS_I(tip)) != 0) {
@@ -315,8 +313,7 @@ xfs_swap_extents(
 	 * are safe.  We don't really care if non-io related
 	 * fields change.
 	 */
-
-	xfs_tosspages(ip, 0, -1, FI_REMAPF);
+	truncate_pagecache_range(VFS_I(ip), 0, -1);
 
 	tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT);
 	if ((error = xfs_trans_reserve(tp, 0,
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index e93ca8f..7536faa 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -56,6 +56,214 @@ xfs_dir_startup(void)
 	xfs_dir_hash_dotdot = xfs_da_hashname((unsigned char *)"..", 2);
 }
 
+static void
+xfs_dir2_block_verify(
+	struct xfs_buf		*bp)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+	struct xfs_dir2_data_hdr *hdr = bp->b_addr;
+	int			block_ok = 0;
+
+	block_ok = hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC);
+	block_ok = block_ok && __xfs_dir2_data_check(NULL, bp) == 0;
+
+	if (!block_ok) {
+		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr);
+		xfs_buf_ioerror(bp, EFSCORRUPTED);
+	}
+}
+
+static void
+xfs_dir2_block_read_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_dir2_block_verify(bp);
+}
+
+static void
+xfs_dir2_block_write_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_dir2_block_verify(bp);
+}
+
+const struct xfs_buf_ops xfs_dir2_block_buf_ops = {
+	.verify_read = xfs_dir2_block_read_verify,
+	.verify_write = xfs_dir2_block_write_verify,
+};
+
+static int
+xfs_dir2_block_read(
+	struct xfs_trans	*tp,
+	struct xfs_inode	*dp,
+	struct xfs_buf		**bpp)
+{
+	struct xfs_mount	*mp = dp->i_mount;
+
+	return xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, bpp,
+				XFS_DATA_FORK, &xfs_dir2_block_buf_ops);
+}
+
+static void
+xfs_dir2_block_need_space(
+	struct xfs_dir2_data_hdr	*hdr,
+	struct xfs_dir2_block_tail	*btp,
+	struct xfs_dir2_leaf_entry	*blp,
+	__be16				**tagpp,
+	struct xfs_dir2_data_unused	**dupp,
+	struct xfs_dir2_data_unused	**enddupp,
+	int				*compact,
+	int				len)
+{
+	struct xfs_dir2_data_free	*bf;
+	__be16				*tagp = NULL;
+	struct xfs_dir2_data_unused	*dup = NULL;
+	struct xfs_dir2_data_unused	*enddup = NULL;
+
+	*compact = 0;
+	bf = hdr->bestfree;
+
+	/*
+	 * If there are stale entries we'll use one for the leaf.
+	 */
+	if (btp->stale) {
+		if (be16_to_cpu(bf[0].length) >= len) {
+			/*
+			 * The biggest entry enough to avoid compaction.
+			 */
+			dup = (xfs_dir2_data_unused_t *)
+			      ((char *)hdr + be16_to_cpu(bf[0].offset));
+			goto out;
+		}
+
+		/*
+		 * Will need to compact to make this work.
+		 * Tag just before the first leaf entry.
+		 */
+		*compact = 1;
+		tagp = (__be16 *)blp - 1;
+
+		/* Data object just before the first leaf entry.  */
+		dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
+
+		/*
+		 * If it's not free then the data will go where the
+		 * leaf data starts now, if it works at all.
+		 */
+		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
+			if (be16_to_cpu(dup->length) + (be32_to_cpu(btp->stale) - 1) *
+			    (uint)sizeof(*blp) < len)
+				dup = NULL;
+		} else if ((be32_to_cpu(btp->stale) - 1) * (uint)sizeof(*blp) < len)
+			dup = NULL;
+		else
+			dup = (xfs_dir2_data_unused_t *)blp;
+		goto out;
+	}
+
+	/*
+	 * no stale entries, so just use free space.
+	 * Tag just before the first leaf entry.
+	 */
+	tagp = (__be16 *)blp - 1;
+
+	/* Data object just before the first leaf entry.  */
+	enddup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
+
+	/*
+	 * If it's not free then can't do this add without cleaning up:
+	 * the space before the first leaf entry needs to be free so it
+	 * can be expanded to hold the pointer to the new entry.
+	 */
+	if (be16_to_cpu(enddup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
+		/*
+		 * Check out the biggest freespace and see if it's the same one.
+		 */
+		dup = (xfs_dir2_data_unused_t *)
+		      ((char *)hdr + be16_to_cpu(bf[0].offset));
+		if (dup != enddup) {
+			/*
+			 * Not the same free entry, just check its length.
+			 */
+			if (be16_to_cpu(dup->length) < len)
+				dup = NULL;
+			goto out;
+		}
+
+		/*
+		 * It is the biggest freespace, can it hold the leaf too?
+		 */
+		if (be16_to_cpu(dup->length) < len + (uint)sizeof(*blp)) {
+			/*
+			 * Yes, use the second-largest entry instead if it works.
+			 */
+			if (be16_to_cpu(bf[1].length) >= len)
+				dup = (xfs_dir2_data_unused_t *)
+				      ((char *)hdr + be16_to_cpu(bf[1].offset));
+			else
+				dup = NULL;
+		}
+	}
+out:
+	*tagpp = tagp;
+	*dupp = dup;
+	*enddupp = enddup;
+}
+
+/*
+ * compact the leaf entries.
+ * Leave the highest-numbered stale entry stale.
+ * XXX should be the one closest to mid but mid is not yet computed.
+ */
+static void
+xfs_dir2_block_compact(
+	struct xfs_trans		*tp,
+	struct xfs_buf			*bp,
+	struct xfs_dir2_data_hdr	*hdr,
+	struct xfs_dir2_block_tail	*btp,
+	struct xfs_dir2_leaf_entry	*blp,
+	int				*needlog,
+	int				*lfloghigh,
+	int				*lfloglow)
+{
+	int			fromidx;	/* source leaf index */
+	int			toidx;		/* target leaf index */
+	int			needscan = 0;
+	int			highstale;	/* high stale index */
+
+	fromidx = toidx = be32_to_cpu(btp->count) - 1;
+	highstale = *lfloghigh = -1;
+	for (; fromidx >= 0; fromidx--) {
+		if (blp[fromidx].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) {
+			if (highstale == -1)
+				highstale = toidx;
+			else {
+				if (*lfloghigh == -1)
+					*lfloghigh = toidx;
+				continue;
+			}
+		}
+		if (fromidx < toidx)
+			blp[toidx] = blp[fromidx];
+		toidx--;
+	}
+	*lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1);
+	*lfloghigh -= be32_to_cpu(btp->stale) - 1;
+	be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1));
+	xfs_dir2_data_make_free(tp, bp,
+		(xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr),
+		(xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)),
+		needlog, &needscan);
+	blp += be32_to_cpu(btp->stale) - 1;
+	btp->stale = cpu_to_be32(1);
+	/*
+	 * If we now need to rebuild the bestfree map, do so.
+	 * This needs to happen before the next call to use_free.
+	 */
+	if (needscan)
+		xfs_dir2_data_freescan(tp->t_mountp, hdr, needlog);
+}
+
 /*
  * Add an entry to a block directory.
  */
@@ -63,7 +271,6 @@ int						/* error */
 xfs_dir2_block_addname(
 	xfs_da_args_t		*args)		/* directory op arguments */
 {
-	xfs_dir2_data_free_t	*bf;		/* bestfree table in block */
 	xfs_dir2_data_hdr_t	*hdr;		/* block header */
 	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
 	struct xfs_buf		*bp;		/* buffer for block */
@@ -94,134 +301,44 @@ xfs_dir2_block_addname(
 	dp = args->dp;
 	tp = args->trans;
 	mp = dp->i_mount;
-	/*
-	 * Read the (one and only) directory block into dabuf bp.
-	 */
-	if ((error =
-	    xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, &bp, XFS_DATA_FORK))) {
+
+	/* Read the (one and only) directory block into bp. */
+	error = xfs_dir2_block_read(tp, dp, &bp);
+	if (error)
 		return error;
-	}
-	ASSERT(bp != NULL);
-	hdr = bp->b_addr;
-	/*
-	 * Check the magic number, corrupted if wrong.
-	 */
-	if (unlikely(hdr->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC))) {
-		XFS_CORRUPTION_ERROR("xfs_dir2_block_addname",
-				     XFS_ERRLEVEL_LOW, mp, hdr);
-		xfs_trans_brelse(tp, bp);
-		return XFS_ERROR(EFSCORRUPTED);
-	}
+
 	len = xfs_dir2_data_entsize(args->namelen);
+
 	/*
 	 * Set up pointers to parts of the block.
 	 */
-	bf = hdr->bestfree;
+	hdr = bp->b_addr;
 	btp = xfs_dir2_block_tail_p(mp, hdr);
 	blp = xfs_dir2_block_leaf_p(btp);
+
 	/*
-	 * No stale entries?  Need space for entry and new leaf.
-	 */
-	if (!btp->stale) {
-		/*
-		 * Tag just before the first leaf entry.
-		 */
-		tagp = (__be16 *)blp - 1;
-		/*
-		 * Data object just before the first leaf entry.
-		 */
-		enddup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
-		/*
-		 * If it's not free then can't do this add without cleaning up:
-		 * the space before the first leaf entry needs to be free so it
-		 * can be expanded to hold the pointer to the new entry.
-		 */
-		if (be16_to_cpu(enddup->freetag) != XFS_DIR2_DATA_FREE_TAG)
-			dup = enddup = NULL;
-		/*
-		 * Check out the biggest freespace and see if it's the same one.
-		 */
-		else {
-			dup = (xfs_dir2_data_unused_t *)
-			      ((char *)hdr + be16_to_cpu(bf[0].offset));
-			if (dup == enddup) {
-				/*
-				 * It is the biggest freespace, is it too small
-				 * to hold the new leaf too?
-				 */
-				if (be16_to_cpu(dup->length) < len + (uint)sizeof(*blp)) {
-					/*
-					 * Yes, we use the second-largest
-					 * entry instead if it works.
-					 */
-					if (be16_to_cpu(bf[1].length) >= len)
-						dup = (xfs_dir2_data_unused_t *)
-						      ((char *)hdr +
-						       be16_to_cpu(bf[1].offset));
-					else
-						dup = NULL;
-				}
-			} else {
-				/*
-				 * Not the same free entry,
-				 * just check its length.
-				 */
-				if (be16_to_cpu(dup->length) < len) {
-					dup = NULL;
-				}
-			}
-		}
-		compact = 0;
-	}
-	/*
-	 * If there are stale entries we'll use one for the leaf.
-	 * Is the biggest entry enough to avoid compaction?
-	 */
-	else if (be16_to_cpu(bf[0].length) >= len) {
-		dup = (xfs_dir2_data_unused_t *)
-		      ((char *)hdr + be16_to_cpu(bf[0].offset));
-		compact = 0;
-	}
-	/*
-	 * Will need to compact to make this work.
+	 * Find out if we can reuse stale entries or whether we need extra
+	 * space for entry and new leaf.
 	 */
-	else {
-		/*
-		 * Tag just before the first leaf entry.
-		 */
-		tagp = (__be16 *)blp - 1;
-		/*
-		 * Data object just before the first leaf entry.
-		 */
-		dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
-		/*
-		 * If it's not free then the data will go where the
-		 * leaf data starts now, if it works at all.
-		 */
-		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
-			if (be16_to_cpu(dup->length) + (be32_to_cpu(btp->stale) - 1) *
-			    (uint)sizeof(*blp) < len)
-				dup = NULL;
-		} else if ((be32_to_cpu(btp->stale) - 1) * (uint)sizeof(*blp) < len)
-			dup = NULL;
-		else
-			dup = (xfs_dir2_data_unused_t *)blp;
-		compact = 1;
-	}
+	xfs_dir2_block_need_space(hdr, btp, blp, &tagp, &dup,
+				  &enddup, &compact, len);
+
 	/*
-	 * If this isn't a real add, we're done with the buffer.
+	 * Done everything we need for a space check now.
 	 */
-	if (args->op_flags & XFS_DA_OP_JUSTCHECK)
+	if (args->op_flags & XFS_DA_OP_JUSTCHECK) {
 		xfs_trans_brelse(tp, bp);
+		if (!dup)
+			return XFS_ERROR(ENOSPC);
+		return 0;
+	}
+
 	/*
 	 * If we don't have space for the new entry & leaf ...
 	 */
 	if (!dup) {
-		/*
-		 * Not trying to actually do anything, or don't have
-		 * a space reservation: return no-space.
-		 */
-		if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0)
+		/* Don't have a space reservation: return no-space.  */
+		if (args->total == 0)
 			return XFS_ERROR(ENOSPC);
 		/*
 		 * Convert to the next larger format.
@@ -232,65 +349,24 @@ xfs_dir2_block_addname(
 			return error;
 		return xfs_dir2_leaf_addname(args);
 	}
-	/*
-	 * Just checking, and it would work, so say so.
-	 */
-	if (args->op_flags & XFS_DA_OP_JUSTCHECK)
-		return 0;
+
 	needlog = needscan = 0;
+
 	/*
 	 * If need to compact the leaf entries, do it now.
-	 * Leave the highest-numbered stale entry stale.
-	 * XXX should be the one closest to mid but mid is not yet computed.
-	 */
-	if (compact) {
-		int	fromidx;		/* source leaf index */
-		int	toidx;			/* target leaf index */
-
-		for (fromidx = toidx = be32_to_cpu(btp->count) - 1,
-			highstale = lfloghigh = -1;
-		     fromidx >= 0;
-		     fromidx--) {
-			if (blp[fromidx].address ==
-			    cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) {
-				if (highstale == -1)
-					highstale = toidx;
-				else {
-					if (lfloghigh == -1)
-						lfloghigh = toidx;
-					continue;
-				}
-			}
-			if (fromidx < toidx)
-				blp[toidx] = blp[fromidx];
-			toidx--;
-		}
-		lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1);
-		lfloghigh -= be32_to_cpu(btp->stale) - 1;
-		be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1));
-		xfs_dir2_data_make_free(tp, bp,
-			(xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr),
-			(xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)),
-			&needlog, &needscan);
-		blp += be32_to_cpu(btp->stale) - 1;
-		btp->stale = cpu_to_be32(1);
-		/*
-		 * If we now need to rebuild the bestfree map, do so.
-		 * This needs to happen before the next call to use_free.
-		 */
-		if (needscan) {
-			xfs_dir2_data_freescan(mp, hdr, &needlog);
-			needscan = 0;
-		}
-	}
-	/*
-	 * Set leaf logging boundaries to impossible state.
-	 * For the no-stale case they're set explicitly.
 	 */
+	if (compact)
+		xfs_dir2_block_compact(tp, bp, hdr, btp, blp, &needlog,
+				      &lfloghigh, &lfloglow);
 	else if (btp->stale) {
+		/*
+		 * Set leaf logging boundaries to impossible state.
+		 * For the no-stale case they're set explicitly.
+		 */
 		lfloglow = be32_to_cpu(btp->count);
 		lfloghigh = -1;
 	}
+
 	/*
 	 * Find the slot that's first lower than our hash value, -1 if none.
 	 */
@@ -450,18 +526,13 @@ xfs_dir2_block_getdents(
 	/*
 	 * If the block number in the offset is out of range, we're done.
 	 */
-	if (xfs_dir2_dataptr_to_db(mp, *offset) > mp->m_dirdatablk) {
+	if (xfs_dir2_dataptr_to_db(mp, *offset) > mp->m_dirdatablk)
 		return 0;
-	}
-	/*
-	 * Can't read the block, give up, else get dabuf in bp.
-	 */
-	error = xfs_da_read_buf(NULL, dp, mp->m_dirdatablk, -1,
-				&bp, XFS_DATA_FORK);
+
+	error = xfs_dir2_block_read(NULL, dp, &bp);
 	if (error)
 		return error;
 
-	ASSERT(bp != NULL);
 	/*
 	 * Extract the byte offset we start at from the seek pointer.
 	 * We'll skip entries before this.
@@ -637,14 +708,11 @@ xfs_dir2_block_lookup_int(
 	dp = args->dp;
 	tp = args->trans;
 	mp = dp->i_mount;
-	/*
-	 * Read the buffer, return error if we can't get it.
-	 */
-	if ((error =
-	    xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, &bp, XFS_DATA_FORK))) {
+
+	error = xfs_dir2_block_read(tp, dp, &bp);
+	if (error)
 		return error;
-	}
-	ASSERT(bp != NULL);
+
 	hdr = bp->b_addr;
 	xfs_dir2_data_check(dp, bp);
 	btp = xfs_dir2_block_tail_p(mp, hdr);
@@ -917,10 +985,10 @@ xfs_dir2_leaf_to_block(
 	/*
 	 * Read the data block if we don't already have it, give up if it fails.
 	 */
-	if (dbp == NULL &&
-	    (error = xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, &dbp,
-		    XFS_DATA_FORK))) {
-		return error;
+	if (!dbp) {
+		error = xfs_dir2_data_read(tp, dp, mp->m_dirdatablk, -1, &dbp);
+		if (error)
+			return error;
 	}
 	hdr = dbp->b_addr;
 	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC));
@@ -944,6 +1012,7 @@ xfs_dir2_leaf_to_block(
 	/*
 	 * Start converting it to block form.
 	 */
+	dbp->b_ops = &xfs_dir2_block_buf_ops;
 	hdr->magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC);
 	needlog = 1;
 	needscan = 0;
@@ -1073,6 +1142,7 @@ xfs_dir2_sf_to_block(
 		kmem_free(sfp);
 		return error;
 	}
+	bp->b_ops = &xfs_dir2_block_buf_ops;
 	hdr = bp->b_addr;
 	hdr->magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC);
 	/*
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index 44ffd4d..ffcf177 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -34,14 +34,13 @@
 STATIC xfs_dir2_data_free_t *
 xfs_dir2_data_freefind(xfs_dir2_data_hdr_t *hdr, xfs_dir2_data_unused_t *dup);
 
-#ifdef DEBUG
 /*
  * Check the consistency of the data block.
  * The input can also be a block-format directory.
- * Pop an assert if we find anything bad.
+ * Return 0 is the buffer is good, otherwise an error.
  */
-void
-xfs_dir2_data_check(
+int
+__xfs_dir2_data_check(
 	struct xfs_inode	*dp,		/* incore inode pointer */
 	struct xfs_buf		*bp)		/* data block's buffer */
 {
@@ -64,18 +63,23 @@ xfs_dir2_data_check(
 	int			stale;		/* count of stale leaves */
 	struct xfs_name		name;
 
-	mp = dp->i_mount;
+	mp = bp->b_target->bt_mount;
 	hdr = bp->b_addr;
 	bf = hdr->bestfree;
 	p = (char *)(hdr + 1);
 
-	if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) {
+	switch (hdr->magic) {
+	case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):
 		btp = xfs_dir2_block_tail_p(mp, hdr);
 		lep = xfs_dir2_block_leaf_p(btp);
 		endp = (char *)lep;
-	} else {
-		ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC));
+		break;
+	case cpu_to_be32(XFS_DIR2_DATA_MAGIC):
 		endp = (char *)hdr + mp->m_dirblksize;
+		break;
+	default:
+		XFS_ERROR_REPORT("Bad Magic", XFS_ERRLEVEL_LOW, mp);
+		return EFSCORRUPTED;
 	}
 
 	count = lastfree = freeseen = 0;
@@ -83,19 +87,22 @@ xfs_dir2_data_check(
 	 * Account for zero bestfree entries.
 	 */
 	if (!bf[0].length) {
-		ASSERT(!bf[0].offset);
+		XFS_WANT_CORRUPTED_RETURN(!bf[0].offset);
 		freeseen |= 1 << 0;
 	}
 	if (!bf[1].length) {
-		ASSERT(!bf[1].offset);
+		XFS_WANT_CORRUPTED_RETURN(!bf[1].offset);
 		freeseen |= 1 << 1;
 	}
 	if (!bf[2].length) {
-		ASSERT(!bf[2].offset);
+		XFS_WANT_CORRUPTED_RETURN(!bf[2].offset);
 		freeseen |= 1 << 2;
 	}
-	ASSERT(be16_to_cpu(bf[0].length) >= be16_to_cpu(bf[1].length));
-	ASSERT(be16_to_cpu(bf[1].length) >= be16_to_cpu(bf[2].length));
+
+	XFS_WANT_CORRUPTED_RETURN(be16_to_cpu(bf[0].length) >=
+						be16_to_cpu(bf[1].length));
+	XFS_WANT_CORRUPTED_RETURN(be16_to_cpu(bf[1].length) >=
+						be16_to_cpu(bf[2].length));
 	/*
 	 * Loop over the data/unused entries.
 	 */
@@ -107,17 +114,20 @@ xfs_dir2_data_check(
 		 * doesn't need to be there.
 		 */
 		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
-			ASSERT(lastfree == 0);
-			ASSERT(be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) ==
-			       (char *)dup - (char *)hdr);
+			XFS_WANT_CORRUPTED_RETURN(lastfree == 0);
+			XFS_WANT_CORRUPTED_RETURN(
+				be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) ==
+					       (char *)dup - (char *)hdr);
 			dfp = xfs_dir2_data_freefind(hdr, dup);
 			if (dfp) {
 				i = (int)(dfp - bf);
-				ASSERT((freeseen & (1 << i)) == 0);
+				XFS_WANT_CORRUPTED_RETURN(
+					(freeseen & (1 << i)) == 0);
 				freeseen |= 1 << i;
 			} else {
-				ASSERT(be16_to_cpu(dup->length) <=
-				       be16_to_cpu(bf[2].length));
+				XFS_WANT_CORRUPTED_RETURN(
+					be16_to_cpu(dup->length) <=
+						be16_to_cpu(bf[2].length));
 			}
 			p += be16_to_cpu(dup->length);
 			lastfree = 1;
@@ -130,10 +140,12 @@ xfs_dir2_data_check(
 		 * The linear search is crude but this is DEBUG code.
 		 */
 		dep = (xfs_dir2_data_entry_t *)p;
-		ASSERT(dep->namelen != 0);
-		ASSERT(xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)) == 0);
-		ASSERT(be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep)) ==
-		       (char *)dep - (char *)hdr);
+		XFS_WANT_CORRUPTED_RETURN(dep->namelen != 0);
+		XFS_WANT_CORRUPTED_RETURN(
+			!xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)));
+		XFS_WANT_CORRUPTED_RETURN(
+			be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep)) ==
+					       (char *)dep - (char *)hdr);
 		count++;
 		lastfree = 0;
 		if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) {
@@ -148,27 +160,122 @@ xfs_dir2_data_check(
 				    be32_to_cpu(lep[i].hashval) == hash)
 					break;
 			}
-			ASSERT(i < be32_to_cpu(btp->count));
+			XFS_WANT_CORRUPTED_RETURN(i < be32_to_cpu(btp->count));
 		}
 		p += xfs_dir2_data_entsize(dep->namelen);
 	}
 	/*
 	 * Need to have seen all the entries and all the bestfree slots.
 	 */
-	ASSERT(freeseen == 7);
+	XFS_WANT_CORRUPTED_RETURN(freeseen == 7);
 	if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) {
 		for (i = stale = 0; i < be32_to_cpu(btp->count); i++) {
 			if (lep[i].address ==
 			    cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
 				stale++;
 			if (i > 0)
-				ASSERT(be32_to_cpu(lep[i].hashval) >= be32_to_cpu(lep[i - 1].hashval));
+				XFS_WANT_CORRUPTED_RETURN(
+					be32_to_cpu(lep[i].hashval) >=
+						be32_to_cpu(lep[i - 1].hashval));
 		}
-		ASSERT(count == be32_to_cpu(btp->count) - be32_to_cpu(btp->stale));
-		ASSERT(stale == be32_to_cpu(btp->stale));
+		XFS_WANT_CORRUPTED_RETURN(count ==
+			be32_to_cpu(btp->count) - be32_to_cpu(btp->stale));
+		XFS_WANT_CORRUPTED_RETURN(stale == be32_to_cpu(btp->stale));
 	}
+	return 0;
+}
+
+static void
+xfs_dir2_data_verify(
+	struct xfs_buf		*bp)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+	struct xfs_dir2_data_hdr *hdr = bp->b_addr;
+	int			block_ok = 0;
+
+	block_ok = hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC);
+	block_ok = block_ok && __xfs_dir2_data_check(NULL, bp) == 0;
+
+	if (!block_ok) {
+		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr);
+		xfs_buf_ioerror(bp, EFSCORRUPTED);
+	}
+}
+
+/*
+ * Readahead of the first block of the directory when it is opened is completely
+ * oblivious to the format of the directory. Hence we can either get a block
+ * format buffer or a data format buffer on readahead.
+ */
+static void
+xfs_dir2_data_reada_verify(
+	struct xfs_buf		*bp)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+	struct xfs_dir2_data_hdr *hdr = bp->b_addr;
+
+	switch (hdr->magic) {
+	case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):
+		bp->b_ops = &xfs_dir2_block_buf_ops;
+		bp->b_ops->verify_read(bp);
+		return;
+	case cpu_to_be32(XFS_DIR2_DATA_MAGIC):
+		xfs_dir2_data_verify(bp);
+		return;
+	default:
+		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr);
+		xfs_buf_ioerror(bp, EFSCORRUPTED);
+		break;
+	}
+}
+
+static void
+xfs_dir2_data_read_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_dir2_data_verify(bp);
+}
+
+static void
+xfs_dir2_data_write_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_dir2_data_verify(bp);
+}
+
+const struct xfs_buf_ops xfs_dir2_data_buf_ops = {
+	.verify_read = xfs_dir2_data_read_verify,
+	.verify_write = xfs_dir2_data_write_verify,
+};
+
+static const struct xfs_buf_ops xfs_dir2_data_reada_buf_ops = {
+	.verify_read = xfs_dir2_data_reada_verify,
+	.verify_write = xfs_dir2_data_write_verify,
+};
+
+
+int
+xfs_dir2_data_read(
+	struct xfs_trans	*tp,
+	struct xfs_inode	*dp,
+	xfs_dablk_t		bno,
+	xfs_daddr_t		mapped_bno,
+	struct xfs_buf		**bpp)
+{
+	return xfs_da_read_buf(tp, dp, bno, mapped_bno, bpp,
+				XFS_DATA_FORK, &xfs_dir2_data_buf_ops);
+}
+
+int
+xfs_dir2_data_readahead(
+	struct xfs_trans	*tp,
+	struct xfs_inode	*dp,
+	xfs_dablk_t		bno,
+	xfs_daddr_t		mapped_bno)
+{
+	return xfs_da_reada_buf(tp, dp, bno, mapped_bno,
+				XFS_DATA_FORK, &xfs_dir2_data_reada_buf_ops);
 }
-#endif
 
 /*
  * Given a data block and an unused entry from that block,
@@ -409,10 +516,9 @@ xfs_dir2_data_init(
 	 */
 	error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, blkno), -1, &bp,
 		XFS_DATA_FORK);
-	if (error) {
+	if (error)
 		return error;
-	}
-	ASSERT(bp != NULL);
+	bp->b_ops = &xfs_dir2_data_buf_ops;
 
 	/*
 	 * Initialize the header.
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 0b29625..60cd2fa 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -48,6 +48,83 @@ static void xfs_dir2_leaf_log_bests(struct xfs_trans *tp, struct xfs_buf *bp,
 				    int first, int last);
 static void xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_buf *bp);
 
+static void
+xfs_dir2_leaf_verify(
+	struct xfs_buf		*bp,
+	__be16			magic)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+	struct xfs_dir2_leaf_hdr *hdr = bp->b_addr;
+	int			block_ok = 0;
+
+	block_ok = hdr->info.magic == magic;
+	if (!block_ok) {
+		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr);
+		xfs_buf_ioerror(bp, EFSCORRUPTED);
+	}
+}
+
+static void
+xfs_dir2_leaf1_read_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAF1_MAGIC));
+}
+
+static void
+xfs_dir2_leaf1_write_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAF1_MAGIC));
+}
+
+void
+xfs_dir2_leafn_read_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
+}
+
+void
+xfs_dir2_leafn_write_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
+}
+
+static const struct xfs_buf_ops xfs_dir2_leaf1_buf_ops = {
+	.verify_read = xfs_dir2_leaf1_read_verify,
+	.verify_write = xfs_dir2_leaf1_write_verify,
+};
+
+const struct xfs_buf_ops xfs_dir2_leafn_buf_ops = {
+	.verify_read = xfs_dir2_leafn_read_verify,
+	.verify_write = xfs_dir2_leafn_write_verify,
+};
+
+static int
+xfs_dir2_leaf_read(
+	struct xfs_trans	*tp,
+	struct xfs_inode	*dp,
+	xfs_dablk_t		fbno,
+	xfs_daddr_t		mappedbno,
+	struct xfs_buf		**bpp)
+{
+	return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
+				XFS_DATA_FORK, &xfs_dir2_leaf1_buf_ops);
+}
+
+int
+xfs_dir2_leafn_read(
+	struct xfs_trans	*tp,
+	struct xfs_inode	*dp,
+	xfs_dablk_t		fbno,
+	xfs_daddr_t		mappedbno,
+	struct xfs_buf		**bpp)
+{
+	return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
+				XFS_DATA_FORK, &xfs_dir2_leafn_buf_ops);
+}
 
 /*
  * Convert a block form directory to a leaf form directory.
@@ -125,6 +202,7 @@ xfs_dir2_block_to_leaf(
 	/*
 	 * Fix up the block header, make it a data block.
 	 */
+	dbp->b_ops = &xfs_dir2_data_buf_ops;
 	hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
 	if (needscan)
 		xfs_dir2_data_freescan(mp, hdr, &needlog);
@@ -311,15 +389,11 @@ xfs_dir2_leaf_addname(
 	dp = args->dp;
 	tp = args->trans;
 	mp = dp->i_mount;
-	/*
-	 * Read the leaf block.
-	 */
-	error = xfs_da_read_buf(tp, dp, mp->m_dirleafblk, -1, &lbp,
-		XFS_DATA_FORK);
-	if (error) {
+
+	error = xfs_dir2_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp);
+	if (error)
 		return error;
-	}
-	ASSERT(lbp != NULL);
+
 	/*
 	 * Look up the entry by hash value and name.
 	 * We know it's not there, our caller has already done a lookup.
@@ -494,22 +568,21 @@ xfs_dir2_leaf_addname(
 		hdr = dbp->b_addr;
 		bestsp[use_block] = hdr->bestfree[0].length;
 		grown = 1;
-	}
-	/*
-	 * Already had space in some data block.
-	 * Just read that one in.
-	 */
-	else {
-		if ((error =
-		    xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, use_block),
-			    -1, &dbp, XFS_DATA_FORK))) {
+	} else {
+		/*
+		 * Already had space in some data block.
+		 * Just read that one in.
+		 */
+		error = xfs_dir2_data_read(tp, dp,
+					   xfs_dir2_db_to_da(mp, use_block),
+					   -1, &dbp);
+		if (error) {
 			xfs_trans_brelse(tp, lbp);
 			return error;
 		}
 		hdr = dbp->b_addr;
 		grown = 0;
 	}
-	xfs_dir2_data_check(dp, dbp);
 	/*
 	 * Point to the biggest freespace in our data block.
 	 */
@@ -892,10 +965,9 @@ xfs_dir2_leaf_readbuf(
 	 * Read the directory block starting at the first mapping.
 	 */
 	mip->curdb = xfs_dir2_da_to_db(mp, map->br_startoff);
-	error = xfs_da_read_buf(NULL, dp, map->br_startoff,
+	error = xfs_dir2_data_read(NULL, dp, map->br_startoff,
 			map->br_blockcount >= mp->m_dirblkfsbs ?
-			    XFS_FSB_TO_DADDR(mp, map->br_startblock) : -1,
-			&bp, XFS_DATA_FORK);
+			    XFS_FSB_TO_DADDR(mp, map->br_startblock) : -1, &bp);
 
 	/*
 	 * Should just skip over the data block instead of giving up.
@@ -922,11 +994,11 @@ xfs_dir2_leaf_readbuf(
 		 */
 		if (i > mip->ra_current &&
 		    map[mip->ra_index].br_blockcount >= mp->m_dirblkfsbs) {
-			xfs_buf_readahead(mp->m_ddev_targp,
+			xfs_dir2_data_readahead(NULL, dp,
+				map[mip->ra_index].br_startoff + mip->ra_offset,
 				XFS_FSB_TO_DADDR(mp,
 					map[mip->ra_index].br_startblock +
-							mip->ra_offset),
-				(int)BTOBB(mp->m_dirblksize));
+							mip->ra_offset));
 			mip->ra_current = i;
 		}
 
@@ -935,10 +1007,9 @@ xfs_dir2_leaf_readbuf(
 		 * use our mapping, but this is a very rare case.
 		 */
 		else if (i > mip->ra_current) {
-			xfs_da_reada_buf(NULL, dp,
+			xfs_dir2_data_readahead(NULL, dp,
 					map[mip->ra_index].br_startoff +
-							mip->ra_offset,
-					XFS_DATA_FORK);
+							mip->ra_offset, -1);
 			mip->ra_current = i;
 		}
 
@@ -1177,15 +1248,14 @@ xfs_dir2_leaf_init(
 	 * Get the buffer for the block.
 	 */
 	error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, bno), -1, &bp,
-		XFS_DATA_FORK);
-	if (error) {
+			       XFS_DATA_FORK);
+	if (error)
 		return error;
-	}
-	ASSERT(bp != NULL);
-	leaf = bp->b_addr;
+
 	/*
 	 * Initialize the header.
 	 */
+	leaf = bp->b_addr;
 	leaf->hdr.info.magic = cpu_to_be16(magic);
 	leaf->hdr.info.forw = 0;
 	leaf->hdr.info.back = 0;
@@ -1198,10 +1268,12 @@ xfs_dir2_leaf_init(
 	 * the block.
 	 */
 	if (magic == XFS_DIR2_LEAF1_MAGIC) {
+		bp->b_ops = &xfs_dir2_leaf1_buf_ops;
 		ltp = xfs_dir2_leaf_tail_p(mp, leaf);
 		ltp->bestcount = 0;
 		xfs_dir2_leaf_log_tail(tp, bp);
-	}
+	} else
+		bp->b_ops = &xfs_dir2_leafn_buf_ops;
 	*bpp = bp;
 	return 0;
 }
@@ -1372,13 +1444,11 @@ xfs_dir2_leaf_lookup_int(
 	dp = args->dp;
 	tp = args->trans;
 	mp = dp->i_mount;
-	/*
-	 * Read the leaf block into the buffer.
-	 */
-	error = xfs_da_read_buf(tp, dp, mp->m_dirleafblk, -1, &lbp,
-							XFS_DATA_FORK);
+
+	error = xfs_dir2_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp);
 	if (error)
 		return error;
+
 	*lbpp = lbp;
 	leaf = lbp->b_addr;
 	xfs_dir2_leaf_check(dp, lbp);
@@ -1409,14 +1479,13 @@ xfs_dir2_leaf_lookup_int(
 		if (newdb != curdb) {
 			if (dbp)
 				xfs_trans_brelse(tp, dbp);
-			error = xfs_da_read_buf(tp, dp,
-						xfs_dir2_db_to_da(mp, newdb),
-						-1, &dbp, XFS_DATA_FORK);
+			error = xfs_dir2_data_read(tp, dp,
+						   xfs_dir2_db_to_da(mp, newdb),
+						   -1, &dbp);
 			if (error) {
 				xfs_trans_brelse(tp, lbp);
 				return error;
 			}
-			xfs_dir2_data_check(dp, dbp);
 			curdb = newdb;
 		}
 		/*
@@ -1451,9 +1520,9 @@ xfs_dir2_leaf_lookup_int(
 		ASSERT(cidb != -1);
 		if (cidb != curdb) {
 			xfs_trans_brelse(tp, dbp);
-			error = xfs_da_read_buf(tp, dp,
-						xfs_dir2_db_to_da(mp, cidb),
-						-1, &dbp, XFS_DATA_FORK);
+			error = xfs_dir2_data_read(tp, dp,
+						   xfs_dir2_db_to_da(mp, cidb),
+						   -1, &dbp);
 			if (error) {
 				xfs_trans_brelse(tp, lbp);
 				return error;
@@ -1738,10 +1807,9 @@ xfs_dir2_leaf_trim_data(
 	/*
 	 * Read the offending data block.  We need its buffer.
 	 */
-	if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, db), -1, &dbp,
-			XFS_DATA_FORK))) {
+	error = xfs_dir2_data_read(tp, dp, xfs_dir2_db_to_da(mp, db), -1, &dbp);
+	if (error)
 		return error;
-	}
 
 	leaf = lbp->b_addr;
 	ltp = xfs_dir2_leaf_tail_p(mp, leaf);
@@ -1864,10 +1932,9 @@ xfs_dir2_node_to_leaf(
 	/*
 	 * Read the freespace block.
 	 */
-	if ((error = xfs_da_read_buf(tp, dp, mp->m_dirfreeblk, -1, &fbp,
-			XFS_DATA_FORK))) {
+	error = xfs_dir2_free_read(tp, dp,  mp->m_dirfreeblk, &fbp);
+	if (error)
 		return error;
-	}
 	free = fbp->b_addr;
 	ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
 	ASSERT(!free->hdr.firstdb);
@@ -1890,7 +1957,10 @@ xfs_dir2_node_to_leaf(
 		xfs_dir2_leaf_compact(args, lbp);
 	else
 		xfs_dir2_leaf_log_header(tp, lbp);
+
+	lbp->b_ops = &xfs_dir2_leaf1_buf_ops;
 	leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAF1_MAGIC);
+
 	/*
 	 * Set up the leaf tail from the freespace block.
 	 */
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index 6c70524..5980f9b 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -55,6 +55,74 @@ static int xfs_dir2_leafn_remove(xfs_da_args_t *args, struct xfs_buf *bp,
 static int xfs_dir2_node_addname_int(xfs_da_args_t *args,
 				     xfs_da_state_blk_t *fblk);
 
+static void
+xfs_dir2_free_verify(
+	struct xfs_buf		*bp)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+	struct xfs_dir2_free_hdr *hdr = bp->b_addr;
+	int			block_ok = 0;
+
+	block_ok = hdr->magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC);
+	if (!block_ok) {
+		XFS_CORRUPTION_ERROR("xfs_dir2_free_verify magic",
+				     XFS_ERRLEVEL_LOW, mp, hdr);
+		xfs_buf_ioerror(bp, EFSCORRUPTED);
+	}
+}
+
+static void
+xfs_dir2_free_read_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_dir2_free_verify(bp);
+}
+
+static void
+xfs_dir2_free_write_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_dir2_free_verify(bp);
+}
+
+static const struct xfs_buf_ops xfs_dir2_free_buf_ops = {
+	.verify_read = xfs_dir2_free_read_verify,
+	.verify_write = xfs_dir2_free_write_verify,
+};
+
+
+static int
+__xfs_dir2_free_read(
+	struct xfs_trans	*tp,
+	struct xfs_inode	*dp,
+	xfs_dablk_t		fbno,
+	xfs_daddr_t		mappedbno,
+	struct xfs_buf		**bpp)
+{
+	return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
+				XFS_DATA_FORK, &xfs_dir2_free_buf_ops);
+}
+
+int
+xfs_dir2_free_read(
+	struct xfs_trans	*tp,
+	struct xfs_inode	*dp,
+	xfs_dablk_t		fbno,
+	struct xfs_buf		**bpp)
+{
+	return __xfs_dir2_free_read(tp, dp, fbno, -1, bpp);
+}
+
+static int
+xfs_dir2_free_try_read(
+	struct xfs_trans	*tp,
+	struct xfs_inode	*dp,
+	xfs_dablk_t		fbno,
+	struct xfs_buf		**bpp)
+{
+	return __xfs_dir2_free_read(tp, dp, fbno, -2, bpp);
+}
+
 /*
  * Log entries from a freespace block.
  */
@@ -131,11 +199,12 @@ xfs_dir2_leaf_to_node(
 	/*
 	 * Get the buffer for the new freespace block.
 	 */
-	if ((error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb), -1, &fbp,
-			XFS_DATA_FORK))) {
+	error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb), -1, &fbp,
+				XFS_DATA_FORK);
+	if (error)
 		return error;
-	}
-	ASSERT(fbp != NULL);
+	fbp->b_ops = &xfs_dir2_free_buf_ops;
+
 	free = fbp->b_addr;
 	leaf = lbp->b_addr;
 	ltp = xfs_dir2_leaf_tail_p(mp, leaf);
@@ -157,7 +226,10 @@ xfs_dir2_leaf_to_node(
 		*to = cpu_to_be16(off);
 	}
 	free->hdr.nused = cpu_to_be32(n);
+
+	lbp->b_ops = &xfs_dir2_leafn_buf_ops;
 	leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC);
+
 	/*
 	 * Log everything.
 	 */
@@ -394,12 +466,10 @@ xfs_dir2_leafn_lookup_for_addname(
 				 */
 				if (curbp)
 					xfs_trans_brelse(tp, curbp);
-				/*
-				 * Read the free block.
-				 */
-				error = xfs_da_read_buf(tp, dp,
+
+				error = xfs_dir2_free_read(tp, dp,
 						xfs_dir2_db_to_da(mp, newfdb),
-						-1, &curbp, XFS_DATA_FORK);
+						&curbp);
 				if (error)
 					return error;
 				free = curbp->b_addr;
@@ -534,9 +604,9 @@ xfs_dir2_leafn_lookup_for_entry(
 				ASSERT(state->extravalid);
 				curbp = state->extrablk.bp;
 			} else {
-				error = xfs_da_read_buf(tp, dp,
+				error = xfs_dir2_data_read(tp, dp,
 						xfs_dir2_db_to_da(mp, newdb),
-						-1, &curbp, XFS_DATA_FORK);
+						-1, &curbp);
 				if (error)
 					return error;
 			}
@@ -568,6 +638,7 @@ xfs_dir2_leafn_lookup_for_entry(
 			state->extrablk.index = (int)((char *)dep -
 							(char *)curbp->b_addr);
 			state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
+			curbp->b_ops = &xfs_dir2_data_buf_ops;
 			if (cmp == XFS_CMP_EXACT)
 				return XFS_ERROR(EEXIST);
 		}
@@ -582,6 +653,7 @@ xfs_dir2_leafn_lookup_for_entry(
 			state->extrablk.index = -1;
 			state->extrablk.blkno = curdb;
 			state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
+			curbp->b_ops = &xfs_dir2_data_buf_ops;
 		} else {
 			/* If the curbp is not the CI match block, drop it */
 			if (state->extrablk.bp != curbp)
@@ -825,6 +897,77 @@ xfs_dir2_leafn_rebalance(
 	}
 }
 
+static int
+xfs_dir2_data_block_free(
+	xfs_da_args_t		*args,
+	struct xfs_dir2_data_hdr *hdr,
+	struct xfs_dir2_free	*free,
+	xfs_dir2_db_t		fdb,
+	int			findex,
+	struct xfs_buf		*fbp,
+	int			longest)
+{
+	struct xfs_trans	*tp = args->trans;
+	int			logfree = 0;
+
+	if (!hdr) {
+		/* One less used entry in the free table.  */
+		be32_add_cpu(&free->hdr.nused, -1);
+		xfs_dir2_free_log_header(tp, fbp);
+
+		/*
+		 * If this was the last entry in the table, we can trim the
+		 * table size back.  There might be other entries at the end
+		 * referring to non-existent data blocks, get those too.
+		 */
+		if (findex == be32_to_cpu(free->hdr.nvalid) - 1) {
+			int	i;		/* free entry index */
+
+			for (i = findex - 1; i >= 0; i--) {
+				if (free->bests[i] != cpu_to_be16(NULLDATAOFF))
+					break;
+			}
+			free->hdr.nvalid = cpu_to_be32(i + 1);
+			logfree = 0;
+		} else {
+			/* Not the last entry, just punch it out.  */
+			free->bests[findex] = cpu_to_be16(NULLDATAOFF);
+			logfree = 1;
+		}
+		/*
+		 * If there are no useful entries left in the block,
+		 * get rid of the block if we can.
+		 */
+		if (!free->hdr.nused) {
+			int error;
+
+			error = xfs_dir2_shrink_inode(args, fdb, fbp);
+			if (error == 0) {
+				fbp = NULL;
+				logfree = 0;
+			} else if (error != ENOSPC || args->total != 0)
+				return error;
+			/*
+			 * It's possible to get ENOSPC if there is no
+			 * space reservation.  In this case some one
+			 * else will eventually get rid of this block.
+			 */
+		}
+	} else {
+		/*
+		 * Data block is not empty, just set the free entry to the new
+		 * value.
+		 */
+		free->bests[findex] = cpu_to_be16(longest);
+		logfree = 1;
+	}
+
+	/* Log the free entry that changed, unless we got rid of it.  */
+	if (logfree)
+		xfs_dir2_free_log_bests(tp, fbp, findex, findex);
+	return 0;
+}
+
 /*
  * Remove an entry from a node directory.
  * This removes the leaf entry and the data entry,
@@ -908,17 +1051,16 @@ xfs_dir2_leafn_remove(
 		xfs_dir2_db_t	fdb;		/* freeblock block number */
 		int		findex;		/* index in freeblock entries */
 		xfs_dir2_free_t	*free;		/* freeblock structure */
-		int		logfree;	/* need to log free entry */
 
 		/*
 		 * Convert the data block number to a free block,
 		 * read in the free block.
 		 */
 		fdb = xfs_dir2_db_to_fdb(mp, db);
-		if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb),
-				-1, &fbp, XFS_DATA_FORK))) {
+		error = xfs_dir2_free_read(tp, dp, xfs_dir2_db_to_da(mp, fdb),
+					   &fbp);
+		if (error)
 			return error;
-		}
 		free = fbp->b_addr;
 		ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
 		ASSERT(be32_to_cpu(free->hdr.firstdb) ==
@@ -954,68 +1096,12 @@ xfs_dir2_leafn_remove(
 		 * If we got rid of the data block, we can eliminate that entry
 		 * in the free block.
 		 */
-		if (hdr == NULL) {
-			/*
-			 * One less used entry in the free table.
-			 */
-			be32_add_cpu(&free->hdr.nused, -1);
-			xfs_dir2_free_log_header(tp, fbp);
-			/*
-			 * If this was the last entry in the table, we can
-			 * trim the table size back.  There might be other
-			 * entries at the end referring to non-existent
-			 * data blocks, get those too.
-			 */
-			if (findex == be32_to_cpu(free->hdr.nvalid) - 1) {
-				int	i;		/* free entry index */
-
-				for (i = findex - 1;
-				     i >= 0 &&
-				     free->bests[i] == cpu_to_be16(NULLDATAOFF);
-				     i--)
-					continue;
-				free->hdr.nvalid = cpu_to_be32(i + 1);
-				logfree = 0;
-			}
-			/*
-			 * Not the last entry, just punch it out.
-			 */
-			else {
-				free->bests[findex] = cpu_to_be16(NULLDATAOFF);
-				logfree = 1;
-			}
-			/*
-			 * If there are no useful entries left in the block,
-			 * get rid of the block if we can.
-			 */
-			if (!free->hdr.nused) {
-				error = xfs_dir2_shrink_inode(args, fdb, fbp);
-				if (error == 0) {
-					fbp = NULL;
-					logfree = 0;
-				} else if (error != ENOSPC || args->total != 0)
-					return error;
-				/*
-				 * It's possible to get ENOSPC if there is no
-				 * space reservation.  In this case some one
-				 * else will eventually get rid of this block.
-				 */
-			}
-		}
-		/*
-		 * Data block is not empty, just set the free entry to
-		 * the new value.
-		 */
-		else {
-			free->bests[findex] = cpu_to_be16(longest);
-			logfree = 1;
-		}
-		/*
-		 * Log the free entry that changed, unless we got rid of it.
-		 */
-		if (logfree)
-			xfs_dir2_free_log_bests(tp, fbp, findex, findex);
+		error = xfs_dir2_data_block_free(args, hdr, free,
+						 fdb, findex, fbp, longest);
+		if (error)
+			return error;
 	}
+
 	xfs_dir2_leafn_check(dp, bp);
 	/*
 	 * Return indication of whether this leaf block is empty enough
@@ -1169,12 +1255,11 @@ xfs_dir2_leafn_toosmall(
 		/*
 		 * Read the sibling leaf block.
 		 */
-		if ((error =
-		    xfs_da_read_buf(state->args->trans, state->args->dp, blkno,
-			    -1, &bp, XFS_DATA_FORK))) {
+		error = xfs_dir2_leafn_read(state->args->trans, state->args->dp,
+					    blkno, -1, &bp);
+		if (error)
 			return error;
-		}
-		ASSERT(bp != NULL);
+
 		/*
 		 * Count bytes in the two blocks combined.
 		 */
@@ -1454,14 +1539,13 @@ xfs_dir2_node_addname_int(
 			 * This should be really rare, so there's no reason
 			 * to avoid it.
 			 */
-			if ((error = xfs_da_read_buf(tp, dp,
-					xfs_dir2_db_to_da(mp, fbno), -2, &fbp,
-					XFS_DATA_FORK))) {
+			error = xfs_dir2_free_try_read(tp, dp,
+						xfs_dir2_db_to_da(mp, fbno),
+						&fbp);
+			if (error)
 				return error;
-			}
-			if (unlikely(fbp == NULL)) {
+			if (!fbp)
 				continue;
-			}
 			free = fbp->b_addr;
 			ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
 			findex = 0;
@@ -1520,9 +1604,10 @@ xfs_dir2_node_addname_int(
 		 * that was just allocated.
 		 */
 		fbno = xfs_dir2_db_to_fdb(mp, dbno);
-		if (unlikely(error = xfs_da_read_buf(tp, dp,
-				xfs_dir2_db_to_da(mp, fbno), -2, &fbp,
-				XFS_DATA_FORK)))
+		error = xfs_dir2_free_try_read(tp, dp,
+					       xfs_dir2_db_to_da(mp, fbno),
+					       &fbp);
+		if (error)
 			return error;
 
 		/*
@@ -1561,12 +1646,12 @@ xfs_dir2_node_addname_int(
 			/*
 			 * Get a buffer for the new block.
 			 */
-			if ((error = xfs_da_get_buf(tp, dp,
-						   xfs_dir2_db_to_da(mp, fbno),
-						   -1, &fbp, XFS_DATA_FORK))) {
+			error = xfs_da_get_buf(tp, dp,
+					       xfs_dir2_db_to_da(mp, fbno),
+					       -1, &fbp, XFS_DATA_FORK);
+			if (error)
 				return error;
-			}
-			ASSERT(fbp != NULL);
+			fbp->b_ops = &xfs_dir2_free_buf_ops;
 
 			/*
 			 * Initialize the new block to be empty, and remember
@@ -1630,8 +1715,8 @@ xfs_dir2_node_addname_int(
 		/*
 		 * Read the data block in.
 		 */
-		error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, dbno),
-				-1, &dbp, XFS_DATA_FORK);
+		error = xfs_dir2_data_read(tp, dp, xfs_dir2_db_to_da(mp, dbno),
+					   -1, &dbp);
 		if (error)
 			return error;
 		hdr = dbp->b_addr;
@@ -1917,18 +2002,15 @@ xfs_dir2_node_trim_free(
 	/*
 	 * Read the freespace block.
 	 */
-	if (unlikely(error = xfs_da_read_buf(tp, dp, (xfs_dablk_t)fo, -2, &bp,
-			XFS_DATA_FORK))) {
+	error = xfs_dir2_free_try_read(tp, dp, fo, &bp);
+	if (error)
 		return error;
-	}
-
 	/*
 	 * There can be holes in freespace.  If fo is a hole, there's
 	 * nothing to do.
 	 */
-	if (bp == NULL) {
+	if (!bp)
 		return 0;
-	}
 	free = bp->b_addr;
 	ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
 	/*
diff --git a/fs/xfs/xfs_dir2_priv.h b/fs/xfs/xfs_dir2_priv.h
index 3523d3e..7da79f6 100644
--- a/fs/xfs/xfs_dir2_priv.h
+++ b/fs/xfs/xfs_dir2_priv.h
@@ -30,6 +30,8 @@ extern int xfs_dir_cilookup_result(struct xfs_da_args *args,
 				const unsigned char *name, int len);
 
 /* xfs_dir2_block.c */
+extern const struct xfs_buf_ops xfs_dir2_block_buf_ops;
+
 extern int xfs_dir2_block_addname(struct xfs_da_args *args);
 extern int xfs_dir2_block_getdents(struct xfs_inode *dp, void *dirent,
 		xfs_off_t *offset, filldir_t filldir);
@@ -41,10 +43,19 @@ extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args,
 
 /* xfs_dir2_data.c */
 #ifdef DEBUG
-extern void xfs_dir2_data_check(struct xfs_inode *dp, struct xfs_buf *bp);
+#define	xfs_dir2_data_check(dp,bp) __xfs_dir2_data_check(dp, bp);
 #else
 #define	xfs_dir2_data_check(dp,bp)
 #endif
+
+extern const struct xfs_buf_ops xfs_dir2_data_buf_ops;
+
+extern int __xfs_dir2_data_check(struct xfs_inode *dp, struct xfs_buf *bp);
+extern int xfs_dir2_data_read(struct xfs_trans *tp, struct xfs_inode *dp,
+		xfs_dablk_t bno, xfs_daddr_t mapped_bno, struct xfs_buf **bpp);
+extern int xfs_dir2_data_readahead(struct xfs_trans *tp, struct xfs_inode *dp,
+		xfs_dablk_t bno, xfs_daddr_t mapped_bno);
+
 extern struct xfs_dir2_data_free *
 xfs_dir2_data_freeinsert(struct xfs_dir2_data_hdr *hdr,
 		struct xfs_dir2_data_unused *dup, int *loghead);
@@ -66,6 +77,10 @@ extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_buf *bp,
 		xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp);
 
 /* xfs_dir2_leaf.c */
+extern const struct xfs_buf_ops xfs_dir2_leafn_buf_ops;
+
+extern int xfs_dir2_leafn_read(struct xfs_trans *tp, struct xfs_inode *dp,
+		xfs_dablk_t fbno, xfs_daddr_t mappedbno, struct xfs_buf **bpp);
 extern int xfs_dir2_block_to_leaf(struct xfs_da_args *args,
 		struct xfs_buf *dbp);
 extern int xfs_dir2_leaf_addname(struct xfs_da_args *args);
@@ -115,6 +130,8 @@ extern int xfs_dir2_node_removename(struct xfs_da_args *args);
 extern int xfs_dir2_node_replace(struct xfs_da_args *args);
 extern int xfs_dir2_node_trim_free(struct xfs_da_args *args, xfs_fileoff_t fo,
 		int *rvalp);
+extern int xfs_dir2_free_read(struct xfs_trans *tp, struct xfs_inode *dp,
+		xfs_dablk_t fbno, struct xfs_buf **bpp);
 
 /* xfs_dir2_sf.c */
 extern xfs_ino_t xfs_dir2_sf_get_parent_ino(struct xfs_dir2_sf_hdr *sfp);
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index bf27fcc..9e1bf52 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -248,7 +248,59 @@ xfs_qm_init_dquot_blk(
 	xfs_trans_log_buf(tp, bp, 0, BBTOB(q->qi_dqchunklen) - 1);
 }
 
+static void
+xfs_dquot_buf_verify(
+	struct xfs_buf		*bp)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+	struct xfs_dqblk	*d = (struct xfs_dqblk *)bp->b_addr;
+	struct xfs_disk_dquot	*ddq;
+	xfs_dqid_t		id = 0;
+	int			i;
+
+	/*
+	 * On the first read of the buffer, verify that each dquot is valid.
+	 * We don't know what the id of the dquot is supposed to be, just that
+	 * they should be increasing monotonically within the buffer. If the
+	 * first id is corrupt, then it will fail on the second dquot in the
+	 * buffer so corruptions could point to the wrong dquot in this case.
+	 */
+	for (i = 0; i < mp->m_quotainfo->qi_dqperchunk; i++) {
+		int	error;
+
+		ddq = &d[i].dd_diskdq;
+
+		if (i == 0)
+			id = be32_to_cpu(ddq->d_id);
+
+		error = xfs_qm_dqcheck(mp, ddq, id + i, 0, XFS_QMOPT_DOWARN,
+					"xfs_dquot_read_verify");
+		if (error) {
+			XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, d);
+			xfs_buf_ioerror(bp, EFSCORRUPTED);
+			break;
+		}
+	}
+}
+
+static void
+xfs_dquot_buf_read_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_dquot_buf_verify(bp);
+}
+
+void
+xfs_dquot_buf_write_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_dquot_buf_verify(bp);
+}
 
+const struct xfs_buf_ops xfs_dquot_buf_ops = {
+	.verify_read = xfs_dquot_buf_read_verify,
+	.verify_write = xfs_dquot_buf_write_verify,
+};
 
 /*
  * Allocate a block and fill it with dquots.
@@ -315,6 +367,7 @@ xfs_qm_dqalloc(
 	error = xfs_buf_geterror(bp);
 	if (error)
 		goto error1;
+	bp->b_ops = &xfs_dquot_buf_ops;
 
 	/*
 	 * Make a chunk of dquots out of this buffer and log
@@ -359,6 +412,51 @@ xfs_qm_dqalloc(
 
 	return (error);
 }
+STATIC int
+xfs_qm_dqrepair(
+	struct xfs_mount	*mp,
+	struct xfs_trans	*tp,
+	struct xfs_dquot	*dqp,
+	xfs_dqid_t		firstid,
+	struct xfs_buf		**bpp)
+{
+	int			error;
+	struct xfs_disk_dquot	*ddq;
+	struct xfs_dqblk	*d;
+	int			i;
+
+	/*
+	 * Read the buffer without verification so we get the corrupted
+	 * buffer returned to us. make sure we verify it on write, though.
+	 */
+	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, dqp->q_blkno,
+				   mp->m_quotainfo->qi_dqchunklen,
+				   0, bpp, NULL);
+
+	if (error) {
+		ASSERT(*bpp == NULL);
+		return XFS_ERROR(error);
+	}
+	(*bpp)->b_ops = &xfs_dquot_buf_ops;
+
+	ASSERT(xfs_buf_islocked(*bpp));
+	d = (struct xfs_dqblk *)(*bpp)->b_addr;
+
+	/* Do the actual repair of dquots in this buffer */
+	for (i = 0; i < mp->m_quotainfo->qi_dqperchunk; i++) {
+		ddq = &d[i].dd_diskdq;
+		error = xfs_qm_dqcheck(mp, ddq, firstid + i,
+				       dqp->dq_flags & XFS_DQ_ALLTYPES,
+				       XFS_QMOPT_DQREPAIR, "xfs_qm_dqrepair");
+		if (error) {
+			/* repair failed, we're screwed */
+			xfs_trans_brelse(tp, *bpp);
+			return XFS_ERROR(EIO);
+		}
+	}
+
+	return 0;
+}
 
 /*
  * Maps a dquot to the buffer containing its on-disk version.
@@ -378,7 +476,6 @@ xfs_qm_dqtobp(
 	xfs_buf_t	*bp;
 	xfs_inode_t	*quotip = XFS_DQ_TO_QIP(dqp);
 	xfs_mount_t	*mp = dqp->q_mount;
-	xfs_disk_dquot_t *ddq;
 	xfs_dqid_t	id = be32_to_cpu(dqp->q_core.d_id);
 	xfs_trans_t	*tp = (tpp ? *tpp : NULL);
 
@@ -439,33 +536,24 @@ xfs_qm_dqtobp(
 		error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
 					   dqp->q_blkno,
 					   mp->m_quotainfo->qi_dqchunklen,
-					   0, &bp);
-		if (error || !bp)
-			return XFS_ERROR(error);
-	}
-
-	ASSERT(xfs_buf_islocked(bp));
+					   0, &bp, &xfs_dquot_buf_ops);
 
-	/*
-	 * calculate the location of the dquot inside the buffer.
-	 */
-	ddq = bp->b_addr + dqp->q_bufoffset;
+		if (error == EFSCORRUPTED && (flags & XFS_QMOPT_DQREPAIR)) {
+			xfs_dqid_t firstid = (xfs_dqid_t)map.br_startoff *
+						mp->m_quotainfo->qi_dqperchunk;
+			ASSERT(bp == NULL);
+			error = xfs_qm_dqrepair(mp, tp, dqp, firstid, &bp);
+		}
 
-	/*
-	 * A simple sanity check in case we got a corrupted dquot...
-	 */
-	error = xfs_qm_dqcheck(mp, ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES,
-			   flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN),
-			   "dqtobp");
-	if (error) {
-		if (!(flags & XFS_QMOPT_DQREPAIR)) {
-			xfs_trans_brelse(tp, bp);
-			return XFS_ERROR(EIO);
+		if (error) {
+			ASSERT(bp == NULL);
+			return XFS_ERROR(error);
 		}
 	}
 
+	ASSERT(xfs_buf_islocked(bp));
 	*O_bpp = bp;
-	*O_ddpp = ddq;
+	*O_ddpp = bp->b_addr + dqp->q_bufoffset;
 
 	return (0);
 }
@@ -920,7 +1008,7 @@ xfs_qm_dqflush(
 	 * Get the buffer containing the on-disk dquot
 	 */
 	error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno,
-				   mp->m_quotainfo->qi_dqchunklen, 0, &bp);
+				   mp->m_quotainfo->qi_dqchunklen, 0, &bp, NULL);
 	if (error)
 		goto out_unlock;
 
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index 7d20af2..c694a84 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -161,4 +161,6 @@ static inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp)
 	return dqp;
 }
 
+extern const struct xfs_buf_ops xfs_dquot_buf_ops;
+
 #endif /* __XFS_DQUOT_H__ */
diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c
index 8c6d1d7..a836118 100644
--- a/fs/xfs/xfs_export.c
+++ b/fs/xfs/xfs_export.c
@@ -29,6 +29,7 @@
 #include "xfs_inode.h"
 #include "xfs_inode_item.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 /*
  * Note that we only accept fileids which are long enough rather than allow
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index aa473fa..400b187 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -31,6 +31,8 @@
 #include "xfs_error.h"
 #include "xfs_vnodeops.h"
 #include "xfs_da_btree.h"
+#include "xfs_dir2_format.h"
+#include "xfs_dir2_priv.h"
 #include "xfs_ioctl.h"
 #include "xfs_trace.h"
 
@@ -255,15 +257,14 @@ xfs_file_aio_read(
 		xfs_buftarg_t	*target =
 			XFS_IS_REALTIME_INODE(ip) ?
 				mp->m_rtdev_targp : mp->m_ddev_targp;
-		if ((iocb->ki_pos & target->bt_smask) ||
-		    (size & target->bt_smask)) {
-			if (iocb->ki_pos == i_size_read(inode))
+		if ((pos & target->bt_smask) || (size & target->bt_smask)) {
+			if (pos == i_size_read(inode))
 				return 0;
 			return -XFS_ERROR(EINVAL);
 		}
 	}
 
-	n = mp->m_super->s_maxbytes - iocb->ki_pos;
+	n = mp->m_super->s_maxbytes - pos;
 	if (n <= 0 || size == 0)
 		return 0;
 
@@ -289,20 +290,21 @@ xfs_file_aio_read(
 		xfs_rw_ilock(ip, XFS_IOLOCK_EXCL);
 
 		if (inode->i_mapping->nrpages) {
-			ret = -xfs_flushinval_pages(ip,
-					(iocb->ki_pos & PAGE_CACHE_MASK),
-					-1, FI_REMAPF_LOCKED);
+			ret = -filemap_write_and_wait_range(
+							VFS_I(ip)->i_mapping,
+							pos, -1);
 			if (ret) {
 				xfs_rw_iunlock(ip, XFS_IOLOCK_EXCL);
 				return ret;
 			}
+			truncate_pagecache_range(VFS_I(ip), pos, -1);
 		}
 		xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL);
 	}
 
-	trace_xfs_file_read(ip, size, iocb->ki_pos, ioflags);
+	trace_xfs_file_read(ip, size, pos, ioflags);
 
-	ret = generic_file_aio_read(iocb, iovp, nr_segs, iocb->ki_pos);
+	ret = generic_file_aio_read(iocb, iovp, nr_segs, pos);
 	if (ret > 0)
 		XFS_STATS_ADD(xs_read_bytes, ret);
 
@@ -670,10 +672,11 @@ xfs_file_dio_aio_write(
 		goto out;
 
 	if (mapping->nrpages) {
-		ret = -xfs_flushinval_pages(ip, (pos & PAGE_CACHE_MASK), -1,
-							FI_REMAPF_LOCKED);
+		ret = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
+						    pos, -1);
 		if (ret)
 			goto out;
+		truncate_pagecache_range(VFS_I(ip), pos, -1);
 	}
 
 	/*
@@ -728,16 +731,17 @@ xfs_file_buffered_aio_write(
 write_retry:
 	trace_xfs_file_buffered_write(ip, count, iocb->ki_pos, 0);
 	ret = generic_file_buffered_write(iocb, iovp, nr_segs,
-			pos, &iocb->ki_pos, count, ret);
+			pos, &iocb->ki_pos, count, 0);
+
 	/*
-	 * if we just got an ENOSPC, flush the inode now we aren't holding any
-	 * page locks and retry *once*
+	 * If we just got an ENOSPC, try to write back all dirty inodes to
+	 * convert delalloc space to free up some of the excess reserved
+	 * metadata space.
 	 */
 	if (ret == -ENOSPC && !enospc) {
 		enospc = 1;
-		ret = -xfs_flush_pages(ip, 0, -1, 0, FI_NONE);
-		if (!ret)
-			goto write_retry;
+		xfs_flush_inodes(ip->i_mount);
+		goto write_retry;
 	}
 
 	current->backing_dev_info = NULL;
@@ -889,7 +893,7 @@ xfs_dir_open(
 	 */
 	mode = xfs_ilock_map_shared(ip);
 	if (ip->i_d.di_nextents > 0)
-		xfs_da_reada_buf(NULL, ip, 0, XFS_DATA_FORK);
+		xfs_dir2_data_readahead(NULL, ip, 0, -1);
 	xfs_iunlock(ip, mode);
 	return 0;
 }
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index c13fed8..6dda3f9 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -233,7 +233,8 @@ typedef struct xfs_fsop_resblks {
 #define XFS_FSOP_GEOM_FLAGS_LOGV2	0x0100	/* log format version 2	*/
 #define XFS_FSOP_GEOM_FLAGS_SECTOR	0x0200	/* sector sizes >1BB	*/
 #define XFS_FSOP_GEOM_FLAGS_ATTR2	0x0400	/* inline attributes rework */
-#define XFS_FSOP_GEOM_FLAGS_DIRV2CI	0x1000	/* ASCII only CI names */
+#define XFS_FSOP_GEOM_FLAGS_PROJID32	0x0800  /* 32-bit project IDs	*/
+#define XFS_FSOP_GEOM_FLAGS_DIRV2CI	0x1000	/* ASCII only CI names	*/
 #define XFS_FSOP_GEOM_FLAGS_LAZYSB	0x4000	/* lazy superblock counters */
 
 
@@ -339,6 +340,35 @@ typedef struct xfs_error_injection {
 
 
 /*
+ * Speculative preallocation trimming.
+ */
+#define XFS_EOFBLOCKS_VERSION		1
+struct xfs_eofblocks {
+	__u32		eof_version;
+	__u32		eof_flags;
+	uid_t		eof_uid;
+	gid_t		eof_gid;
+	prid_t		eof_prid;
+	__u32		pad32;
+	__u64		eof_min_file_size;
+	__u64		pad64[12];
+};
+
+/* eof_flags values */
+#define XFS_EOF_FLAGS_SYNC		(1 << 0) /* sync/wait mode scan */
+#define XFS_EOF_FLAGS_UID		(1 << 1) /* filter by uid */
+#define XFS_EOF_FLAGS_GID		(1 << 2) /* filter by gid */
+#define XFS_EOF_FLAGS_PRID		(1 << 3) /* filter by project id */
+#define XFS_EOF_FLAGS_MINFILESIZE	(1 << 4) /* filter by min file size */
+#define XFS_EOF_FLAGS_VALID	\
+	(XFS_EOF_FLAGS_SYNC |	\
+	 XFS_EOF_FLAGS_UID |	\
+	 XFS_EOF_FLAGS_GID |	\
+	 XFS_EOF_FLAGS_PRID |	\
+	 XFS_EOF_FLAGS_MINFILESIZE)
+
+
+/*
  * The user-level Handle Request interface structure.
  */
 typedef struct xfs_fsop_handlereq {
@@ -456,6 +486,7 @@ typedef struct xfs_handle {
 /*	XFS_IOC_GETBIOSIZE ---- deprecated 47	   */
 #define XFS_IOC_GETBMAPX	_IOWR('X', 56, struct getbmap)
 #define XFS_IOC_ZERO_RANGE	_IOW ('X', 57, struct xfs_flock64)
+#define XFS_IOC_FREE_EOFBLOCKS	_IOR ('X', 58, struct xfs_eofblocks)
 
 /*
  * ioctl commands that replace IRIX syssgi()'s
diff --git a/fs/xfs/xfs_fs_subr.c b/fs/xfs/xfs_fs_subr.c
deleted file mode 100644
index 652b875..0000000
--- a/fs/xfs/xfs_fs_subr.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2000-2002,2005-2006 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include "xfs.h"
-#include "xfs_vnodeops.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_inode.h"
-#include "xfs_trace.h"
-
-/*
- * note: all filemap functions return negative error codes. These
- * need to be inverted before returning to the xfs core functions.
- */
-void
-xfs_tosspages(
-	xfs_inode_t	*ip,
-	xfs_off_t	first,
-	xfs_off_t	last,
-	int		fiopt)
-{
-	/* can't toss partial tail pages, so mask them out */
-	last &= ~(PAGE_SIZE - 1);
-	truncate_inode_pages_range(VFS_I(ip)->i_mapping, first, last - 1);
-}
-
-int
-xfs_flushinval_pages(
-	xfs_inode_t	*ip,
-	xfs_off_t	first,
-	xfs_off_t	last,
-	int		fiopt)
-{
-	struct address_space *mapping = VFS_I(ip)->i_mapping;
-	int		ret = 0;
-
-	trace_xfs_pagecache_inval(ip, first, last);
-
-	xfs_iflags_clear(ip, XFS_ITRUNCATED);
-	ret = filemap_write_and_wait_range(mapping, first,
-				last == -1 ? LLONG_MAX : last);
-	if (!ret)
-		truncate_inode_pages_range(mapping, first, last);
-	return -ret;
-}
-
-int
-xfs_flush_pages(
-	xfs_inode_t	*ip,
-	xfs_off_t	first,
-	xfs_off_t	last,
-	uint64_t	flags,
-	int		fiopt)
-{
-	struct address_space *mapping = VFS_I(ip)->i_mapping;
-	int		ret = 0;
-	int		ret2;
-
-	xfs_iflags_clear(ip, XFS_ITRUNCATED);
-	ret = -filemap_fdatawrite_range(mapping, first,
-				last == -1 ? LLONG_MAX : last);
-	if (flags & XBF_ASYNC)
-		return ret;
-	ret2 = xfs_wait_on_pages(ip, first, last);
-	if (!ret)
-		ret = ret2;
-	return ret;
-}
-
-int
-xfs_wait_on_pages(
-	xfs_inode_t	*ip,
-	xfs_off_t	first,
-	xfs_off_t	last)
-{
-	struct address_space *mapping = VFS_I(ip)->i_mapping;
-
-	if (mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK)) {
-		return -filemap_fdatawait_range(mapping, first,
-					last == -1 ? XFS_ISIZE(ip) - 1 : last);
-	}
-	return 0;
-}
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 4beaede..94eaeed 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -97,7 +97,9 @@ xfs_fs_geometry(
 			(xfs_sb_version_haslazysbcount(&mp->m_sb) ?
 				XFS_FSOP_GEOM_FLAGS_LAZYSB : 0) |
 			(xfs_sb_version_hasattr2(&mp->m_sb) ?
-				XFS_FSOP_GEOM_FLAGS_ATTR2 : 0);
+				XFS_FSOP_GEOM_FLAGS_ATTR2 : 0) |
+			(xfs_sb_version_hasprojid32bit(&mp->m_sb) ?
+				XFS_FSOP_GEOM_FLAGS_PROJID32 : 0);
 		geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ?
 				mp->m_sb.sb_logsectsize : BBSIZE;
 		geo->rtsectsize = mp->m_sb.sb_blocksize;
@@ -112,18 +114,40 @@ xfs_fs_geometry(
 	return 0;
 }
 
+static struct xfs_buf *
+xfs_growfs_get_hdr_buf(
+	struct xfs_mount	*mp,
+	xfs_daddr_t		blkno,
+	size_t			numblks,
+	int			flags,
+	const struct xfs_buf_ops *ops)
+{
+	struct xfs_buf		*bp;
+
+	bp = xfs_buf_get_uncached(mp->m_ddev_targp, numblks, flags);
+	if (!bp)
+		return NULL;
+
+	xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
+	bp->b_bn = blkno;
+	bp->b_maps[0].bm_bn = blkno;
+	bp->b_ops = ops;
+
+	return bp;
+}
+
 static int
 xfs_growfs_data_private(
 	xfs_mount_t		*mp,		/* mount point for filesystem */
 	xfs_growfs_data_t	*in)		/* growfs data input struct */
 {
 	xfs_agf_t		*agf;
+	struct xfs_agfl		*agfl;
 	xfs_agi_t		*agi;
 	xfs_agnumber_t		agno;
 	xfs_extlen_t		agsize;
 	xfs_extlen_t		tmpsize;
 	xfs_alloc_rec_t		*arec;
-	struct xfs_btree_block	*block;
 	xfs_buf_t		*bp;
 	int			bucket;
 	int			dpct;
@@ -146,9 +170,14 @@ xfs_growfs_data_private(
 	dpct = pct - mp->m_sb.sb_imax_pct;
 	bp = xfs_buf_read_uncached(mp->m_ddev_targp,
 				XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
-				XFS_FSS_TO_BB(mp, 1), 0);
+				XFS_FSS_TO_BB(mp, 1), 0, NULL);
 	if (!bp)
 		return EIO;
+	if (bp->b_error) {
+		int	error = bp->b_error;
+		xfs_buf_relse(bp);
+		return error;
+	}
 	xfs_buf_relse(bp);
 
 	new = nb;	/* use new as a temporary here */
@@ -186,17 +215,18 @@ xfs_growfs_data_private(
 	nfree = 0;
 	for (agno = nagcount - 1; agno >= oagcount; agno--, new -= agsize) {
 		/*
-		 * AG freelist header block
+		 * AG freespace header block
 		 */
-		bp = xfs_buf_get(mp->m_ddev_targp,
-				 XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
-				 XFS_FSS_TO_BB(mp, 1), 0);
+		bp = xfs_growfs_get_hdr_buf(mp,
+				XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
+				XFS_FSS_TO_BB(mp, 1), 0,
+				&xfs_agf_buf_ops);
 		if (!bp) {
 			error = ENOMEM;
 			goto error0;
 		}
+
 		agf = XFS_BUF_TO_AGF(bp);
-		memset(agf, 0, mp->m_sb.sb_sectsize);
 		agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
 		agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
 		agf->agf_seqno = cpu_to_be32(agno);
@@ -223,17 +253,39 @@ xfs_growfs_data_private(
 			goto error0;
 
 		/*
+		 * AG freelist header block
+		 */
+		bp = xfs_growfs_get_hdr_buf(mp,
+				XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)),
+				XFS_FSS_TO_BB(mp, 1), 0,
+				&xfs_agfl_buf_ops);
+		if (!bp) {
+			error = ENOMEM;
+			goto error0;
+		}
+
+		agfl = XFS_BUF_TO_AGFL(bp);
+		for (bucket = 0; bucket < XFS_AGFL_SIZE(mp); bucket++)
+			agfl->agfl_bno[bucket] = cpu_to_be32(NULLAGBLOCK);
+
+		error = xfs_bwrite(bp);
+		xfs_buf_relse(bp);
+		if (error)
+			goto error0;
+
+		/*
 		 * AG inode header block
 		 */
-		bp = xfs_buf_get(mp->m_ddev_targp,
-				 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
-				 XFS_FSS_TO_BB(mp, 1), 0);
+		bp = xfs_growfs_get_hdr_buf(mp,
+				XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
+				XFS_FSS_TO_BB(mp, 1), 0,
+				&xfs_agi_buf_ops);
 		if (!bp) {
 			error = ENOMEM;
 			goto error0;
 		}
+
 		agi = XFS_BUF_TO_AGI(bp);
-		memset(agi, 0, mp->m_sb.sb_sectsize);
 		agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
 		agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
 		agi->agi_seqno = cpu_to_be32(agno);
@@ -254,24 +306,22 @@ xfs_growfs_data_private(
 		/*
 		 * BNO btree root block
 		 */
-		bp = xfs_buf_get(mp->m_ddev_targp,
-				 XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)),
-				 BTOBB(mp->m_sb.sb_blocksize), 0);
+		bp = xfs_growfs_get_hdr_buf(mp,
+				XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)),
+				BTOBB(mp->m_sb.sb_blocksize), 0,
+				&xfs_allocbt_buf_ops);
+
 		if (!bp) {
 			error = ENOMEM;
 			goto error0;
 		}
-		block = XFS_BUF_TO_BLOCK(bp);
-		memset(block, 0, mp->m_sb.sb_blocksize);
-		block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC);
-		block->bb_level = 0;
-		block->bb_numrecs = cpu_to_be16(1);
-		block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
-		block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
-		arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
+
+		xfs_btree_init_block(mp, bp, XFS_ABTB_MAGIC, 0, 1, 0);
+		arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1);
 		arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
 		arec->ar_blockcount = cpu_to_be32(
 			agsize - be32_to_cpu(arec->ar_startblock));
+
 		error = xfs_bwrite(bp);
 		xfs_buf_relse(bp);
 		if (error)
@@ -280,25 +330,22 @@ xfs_growfs_data_private(
 		/*
 		 * CNT btree root block
 		 */
-		bp = xfs_buf_get(mp->m_ddev_targp,
-				 XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)),
-				 BTOBB(mp->m_sb.sb_blocksize), 0);
+		bp = xfs_growfs_get_hdr_buf(mp,
+				XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)),
+				BTOBB(mp->m_sb.sb_blocksize), 0,
+				&xfs_allocbt_buf_ops);
 		if (!bp) {
 			error = ENOMEM;
 			goto error0;
 		}
-		block = XFS_BUF_TO_BLOCK(bp);
-		memset(block, 0, mp->m_sb.sb_blocksize);
-		block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC);
-		block->bb_level = 0;
-		block->bb_numrecs = cpu_to_be16(1);
-		block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
-		block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
-		arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
+
+		xfs_btree_init_block(mp, bp, XFS_ABTC_MAGIC, 0, 1, 0);
+		arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1);
 		arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
 		arec->ar_blockcount = cpu_to_be32(
 			agsize - be32_to_cpu(arec->ar_startblock));
 		nfree += be32_to_cpu(arec->ar_blockcount);
+
 		error = xfs_bwrite(bp);
 		xfs_buf_relse(bp);
 		if (error)
@@ -307,20 +354,17 @@ xfs_growfs_data_private(
 		/*
 		 * INO btree root block
 		 */
-		bp = xfs_buf_get(mp->m_ddev_targp,
-				 XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)),
-				 BTOBB(mp->m_sb.sb_blocksize), 0);
+		bp = xfs_growfs_get_hdr_buf(mp,
+				XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)),
+				BTOBB(mp->m_sb.sb_blocksize), 0,
+				&xfs_inobt_buf_ops);
 		if (!bp) {
 			error = ENOMEM;
 			goto error0;
 		}
-		block = XFS_BUF_TO_BLOCK(bp);
-		memset(block, 0, mp->m_sb.sb_blocksize);
-		block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC);
-		block->bb_level = 0;
-		block->bb_numrecs = 0;
-		block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
-		block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
+
+		xfs_btree_init_block(mp, bp, XFS_IBT_MAGIC, 0, 0, 0);
+
 		error = xfs_bwrite(bp);
 		xfs_buf_relse(bp);
 		if (error)
@@ -408,14 +452,16 @@ xfs_growfs_data_private(
 		if (agno < oagcount) {
 			error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
 				  XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
-				  XFS_FSS_TO_BB(mp, 1), 0, &bp);
+				  XFS_FSS_TO_BB(mp, 1), 0, &bp,
+				  &xfs_sb_buf_ops);
 		} else {
 			bp = xfs_trans_get_buf(NULL, mp->m_ddev_targp,
 				  XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
 				  XFS_FSS_TO_BB(mp, 1), 0);
-			if (bp)
+			if (bp) {
+				bp->b_ops = &xfs_sb_buf_ops;
 				xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
-			else
+			} else
 				error = ENOMEM;
 		}
 
@@ -426,6 +472,7 @@ xfs_growfs_data_private(
 			break;
 		}
 		xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS);
+
 		/*
 		 * If we get an error writing out the alternate superblocks,
 		 * just issue a warning and continue.  The real work is
diff --git a/fs/xfs/xfs_globals.c b/fs/xfs/xfs_globals.c
index 76e81cf..5399ef2 100644
--- a/fs/xfs/xfs_globals.c
+++ b/fs/xfs/xfs_globals.c
@@ -21,7 +21,8 @@
 /*
  * Tunable XFS parameters.  xfs_params is required even when CONFIG_SYSCTL=n,
  * other XFS code uses these values.  Times are measured in centisecs (i.e.
- * 100ths of a second).
+ * 100ths of a second) with the exception of eofb_timer, which is measured in
+ * seconds.
  */
 xfs_param_t xfs_params = {
 			  /*	MIN		DFLT		MAX	*/
@@ -40,4 +41,5 @@ xfs_param_t xfs_params = {
 	.rotorstep	= {	1,		1,		255	},
 	.inherit_nodfrg	= {	0,		1,		1	},
 	.fstrm_timer	= {	1,		30*100,		3600*100},
+	.eofb_timer	= {	1,		300,		3600*24},
 };
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index c5c4ef4..a815412 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -200,7 +200,8 @@ xfs_ialloc_inode_init(
 		 */
 		d = XFS_AGB_TO_DADDR(mp, agno, agbno + (j * blks_per_cluster));
 		fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
-					 mp->m_bsize * blks_per_cluster, 0);
+					 mp->m_bsize * blks_per_cluster,
+					 XBF_UNMAPPED);
 		if (!fbuf)
 			return ENOMEM;
 		/*
@@ -210,6 +211,7 @@ xfs_ialloc_inode_init(
 		 *	to log a whole cluster of inodes instead of all the
 		 *	individual transactions causing a lot of log traffic.
 		 */
+		fbuf->b_ops = &xfs_inode_buf_ops;
 		xfs_buf_zero(fbuf, 0, ninodes << mp->m_sb.sb_inodelog);
 		for (i = 0; i < ninodes; i++) {
 			int	ioffset = i << mp->m_sb.sb_inodelog;
@@ -877,9 +879,9 @@ error0:
  * This function is designed to be called twice if it has to do an allocation
  * to make more free inodes.  On the first call, *IO_agbp should be set to NULL.
  * If an inode is available without having to performn an allocation, an inode
- * number is returned.  In this case, *IO_agbp would be NULL.  If an allocation
- * needes to be done, xfs_dialloc would return the current AGI buffer in
- * *IO_agbp.  The caller should then commit the current transaction, allocate a
+ * number is returned.  In this case, *IO_agbp is set to NULL.  If an allocation
+ * needs to be done, xfs_dialloc returns the current AGI buffer in *IO_agbp.
+ * The caller should then commit the current transaction, allocate a
  * new transaction, and call xfs_dialloc() again, passing in the previous value
  * of *IO_agbp.  IO_agbp should be held across the transactions. Since the AGI
  * buffer is locked across the two calls, the second call is guaranteed to have
@@ -1472,6 +1474,57 @@ xfs_check_agi_unlinked(
 #define xfs_check_agi_unlinked(agi)
 #endif
 
+static void
+xfs_agi_verify(
+	struct xfs_buf	*bp)
+{
+	struct xfs_mount *mp = bp->b_target->bt_mount;
+	struct xfs_agi	*agi = XFS_BUF_TO_AGI(bp);
+	int		agi_ok;
+
+	/*
+	 * Validate the magic number of the agi block.
+	 */
+	agi_ok = agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC) &&
+		XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum));
+
+	/*
+	 * during growfs operations, the perag is not fully initialised,
+	 * so we can't use it for any useful checking. growfs ensures we can't
+	 * use it by using uncached buffers that don't have the perag attached
+	 * so we can detect and avoid this problem.
+	 */
+	if (bp->b_pag)
+		agi_ok = agi_ok && be32_to_cpu(agi->agi_seqno) ==
+						bp->b_pag->pag_agno;
+
+	if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI,
+			XFS_RANDOM_IALLOC_READ_AGI))) {
+		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, agi);
+		xfs_buf_ioerror(bp, EFSCORRUPTED);
+	}
+	xfs_check_agi_unlinked(agi);
+}
+
+static void
+xfs_agi_read_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_agi_verify(bp);
+}
+
+static void
+xfs_agi_write_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_agi_verify(bp);
+}
+
+const struct xfs_buf_ops xfs_agi_buf_ops = {
+	.verify_read = xfs_agi_read_verify,
+	.verify_write = xfs_agi_write_verify,
+};
+
 /*
  * Read in the allocation group header (inode allocation section)
  */
@@ -1482,38 +1535,18 @@ xfs_read_agi(
 	xfs_agnumber_t		agno,	/* allocation group number */
 	struct xfs_buf		**bpp)	/* allocation group hdr buf */
 {
-	struct xfs_agi		*agi;	/* allocation group header */
-	int			agi_ok;	/* agi is consistent */
 	int			error;
 
 	ASSERT(agno != NULLAGNUMBER);
 
 	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
 			XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
-			XFS_FSS_TO_BB(mp, 1), 0, bpp);
+			XFS_FSS_TO_BB(mp, 1), 0, bpp, &xfs_agi_buf_ops);
 	if (error)
 		return error;
 
 	ASSERT(!xfs_buf_geterror(*bpp));
-	agi = XFS_BUF_TO_AGI(*bpp);
-
-	/*
-	 * Validate the magic number of the agi block.
-	 */
-	agi_ok = agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC) &&
-		XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum)) &&
-		be32_to_cpu(agi->agi_seqno) == agno;
-	if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI,
-			XFS_RANDOM_IALLOC_READ_AGI))) {
-		XFS_CORRUPTION_ERROR("xfs_read_agi", XFS_ERRLEVEL_LOW,
-				     mp, agi);
-		xfs_trans_brelse(tp, *bpp);
-		return XFS_ERROR(EFSCORRUPTED);
-	}
-
 	xfs_buf_set_ref(*bpp, XFS_AGI_REF);
-
-	xfs_check_agi_unlinked(agi);
 	return 0;
 }
 
diff --git a/fs/xfs/xfs_ialloc.h b/fs/xfs/xfs_ialloc.h
index 1fd6ea4..c8da3df 100644
--- a/fs/xfs/xfs_ialloc.h
+++ b/fs/xfs/xfs_ialloc.h
@@ -147,7 +147,9 @@ int xfs_inobt_lookup(struct xfs_btree_cur *cur, xfs_agino_t ino,
 /*
  * Get the data from the pointed-to record.
  */
-extern int xfs_inobt_get_rec(struct xfs_btree_cur *cur,
+int xfs_inobt_get_rec(struct xfs_btree_cur *cur,
 		xfs_inobt_rec_incore_t *rec, int *stat);
 
+extern const struct xfs_buf_ops xfs_agi_buf_ops;
+
 #endif	/* __XFS_IALLOC_H__ */
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c
index 2b8b7a3..bec344b 100644
--- a/fs/xfs/xfs_ialloc_btree.c
+++ b/fs/xfs/xfs_ialloc_btree.c
@@ -33,6 +33,7 @@
 #include "xfs_ialloc.h"
 #include "xfs_alloc.h"
 #include "xfs_error.h"
+#include "xfs_trace.h"
 
 
 STATIC int
@@ -181,6 +182,59 @@ xfs_inobt_key_diff(
 			  cur->bc_rec.i.ir_startino;
 }
 
+void
+xfs_inobt_verify(
+	struct xfs_buf		*bp)
+{
+	struct xfs_mount	*mp = bp->b_target->bt_mount;
+	struct xfs_btree_block	*block = XFS_BUF_TO_BLOCK(bp);
+	unsigned int		level;
+	int			sblock_ok; /* block passes checks */
+
+	/* magic number and level verification */
+	level = be16_to_cpu(block->bb_level);
+	sblock_ok = block->bb_magic == cpu_to_be32(XFS_IBT_MAGIC) &&
+		    level < mp->m_in_maxlevels;
+
+	/* numrecs verification */
+	sblock_ok = sblock_ok &&
+		be16_to_cpu(block->bb_numrecs) <= mp->m_inobt_mxr[level != 0];
+
+	/* sibling pointer verification */
+	sblock_ok = sblock_ok &&
+		(block->bb_u.s.bb_leftsib == cpu_to_be32(NULLAGBLOCK) ||
+		 be32_to_cpu(block->bb_u.s.bb_leftsib) < mp->m_sb.sb_agblocks) &&
+		block->bb_u.s.bb_leftsib &&
+		(block->bb_u.s.bb_rightsib == cpu_to_be32(NULLAGBLOCK) ||
+		 be32_to_cpu(block->bb_u.s.bb_rightsib) < mp->m_sb.sb_agblocks) &&
+		block->bb_u.s.bb_rightsib;
+
+	if (!sblock_ok) {
+		trace_xfs_btree_corrupt(bp, _RET_IP_);
+		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, block);
+		xfs_buf_ioerror(bp, EFSCORRUPTED);
+	}
+}
+
+static void
+xfs_inobt_read_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_inobt_verify(bp);
+}
+
+static void
+xfs_inobt_write_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_inobt_verify(bp);
+}
+
+const struct xfs_buf_ops xfs_inobt_buf_ops = {
+	.verify_read = xfs_inobt_read_verify,
+	.verify_write = xfs_inobt_write_verify,
+};
+
 #ifdef DEBUG
 STATIC int
 xfs_inobt_keys_inorder(
@@ -218,6 +272,7 @@ static const struct xfs_btree_ops xfs_inobt_ops = {
 	.init_rec_from_cur	= xfs_inobt_init_rec_from_cur,
 	.init_ptr_from_cur	= xfs_inobt_init_ptr_from_cur,
 	.key_diff		= xfs_inobt_key_diff,
+	.buf_ops		= &xfs_inobt_buf_ops,
 #ifdef DEBUG
 	.keys_inorder		= xfs_inobt_keys_inorder,
 	.recs_inorder		= xfs_inobt_recs_inorder,
diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h
index f782ad0..25c0239 100644
--- a/fs/xfs/xfs_ialloc_btree.h
+++ b/fs/xfs/xfs_ialloc_btree.h
@@ -109,4 +109,6 @@ extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *,
 		struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t);
 extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int);
 
+extern const struct xfs_buf_ops xfs_inobt_buf_ops;
+
 #endif	/* __XFS_IALLOC_BTREE_H__ */
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
new file mode 100644
index 0000000..96e344e
--- /dev/null
+++ b/fs/xfs/xfs_icache.c
@@ -0,0 +1,1341 @@
+/*
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_types.h"
+#include "xfs_log.h"
+#include "xfs_log_priv.h"
+#include "xfs_inum.h"
+#include "xfs_trans.h"
+#include "xfs_trans_priv.h"
+#include "xfs_sb.h"
+#include "xfs_ag.h"
+#include "xfs_mount.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_inode.h"
+#include "xfs_dinode.h"
+#include "xfs_error.h"
+#include "xfs_filestream.h"
+#include "xfs_vnodeops.h"
+#include "xfs_inode_item.h"
+#include "xfs_quota.h"
+#include "xfs_trace.h"
+#include "xfs_fsops.h"
+#include "xfs_icache.h"
+
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+
+STATIC void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp,
+				struct xfs_perag *pag, struct xfs_inode *ip);
+
+/*
+ * Allocate and initialise an xfs_inode.
+ */
+STATIC struct xfs_inode *
+xfs_inode_alloc(
+	struct xfs_mount	*mp,
+	xfs_ino_t		ino)
+{
+	struct xfs_inode	*ip;
+
+	/*
+	 * if this didn't occur in transactions, we could use
+	 * KM_MAYFAIL and return NULL here on ENOMEM. Set the
+	 * code up to do this anyway.
+	 */
+	ip = kmem_zone_alloc(xfs_inode_zone, KM_SLEEP);
+	if (!ip)
+		return NULL;
+	if (inode_init_always(mp->m_super, VFS_I(ip))) {
+		kmem_zone_free(xfs_inode_zone, ip);
+		return NULL;
+	}
+
+	ASSERT(atomic_read(&ip->i_pincount) == 0);
+	ASSERT(!spin_is_locked(&ip->i_flags_lock));
+	ASSERT(!xfs_isiflocked(ip));
+	ASSERT(ip->i_ino == 0);
+
+	mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
+
+	/* initialise the xfs inode */
+	ip->i_ino = ino;
+	ip->i_mount = mp;
+	memset(&ip->i_imap, 0, sizeof(struct xfs_imap));
+	ip->i_afp = NULL;
+	memset(&ip->i_df, 0, sizeof(xfs_ifork_t));
+	ip->i_flags = 0;
+	ip->i_delayed_blks = 0;
+	memset(&ip->i_d, 0, sizeof(xfs_icdinode_t));
+
+	return ip;
+}
+
+STATIC void
+xfs_inode_free_callback(
+	struct rcu_head		*head)
+{
+	struct inode		*inode = container_of(head, struct inode, i_rcu);
+	struct xfs_inode	*ip = XFS_I(inode);
+
+	kmem_zone_free(xfs_inode_zone, ip);
+}
+
+STATIC void
+xfs_inode_free(
+	struct xfs_inode	*ip)
+{
+	switch (ip->i_d.di_mode & S_IFMT) {
+	case S_IFREG:
+	case S_IFDIR:
+	case S_IFLNK:
+		xfs_idestroy_fork(ip, XFS_DATA_FORK);
+		break;
+	}
+
+	if (ip->i_afp)
+		xfs_idestroy_fork(ip, XFS_ATTR_FORK);
+
+	if (ip->i_itemp) {
+		ASSERT(!(ip->i_itemp->ili_item.li_flags & XFS_LI_IN_AIL));
+		xfs_inode_item_destroy(ip);
+		ip->i_itemp = NULL;
+	}
+
+	/* asserts to verify all state is correct here */
+	ASSERT(atomic_read(&ip->i_pincount) == 0);
+	ASSERT(!spin_is_locked(&ip->i_flags_lock));
+	ASSERT(!xfs_isiflocked(ip));
+
+	/*
+	 * Because we use RCU freeing we need to ensure the inode always
+	 * appears to be reclaimed with an invalid inode number when in the
+	 * free state. The ip->i_flags_lock provides the barrier against lookup
+	 * races.
+	 */
+	spin_lock(&ip->i_flags_lock);
+	ip->i_flags = XFS_IRECLAIM;
+	ip->i_ino = 0;
+	spin_unlock(&ip->i_flags_lock);
+
+	call_rcu(&VFS_I(ip)->i_rcu, xfs_inode_free_callback);
+}
+
+/*
+ * Check the validity of the inode we just found it the cache
+ */
+static int
+xfs_iget_cache_hit(
+	struct xfs_perag	*pag,
+	struct xfs_inode	*ip,
+	xfs_ino_t		ino,
+	int			flags,
+	int			lock_flags) __releases(RCU)
+{
+	struct inode		*inode = VFS_I(ip);
+	struct xfs_mount	*mp = ip->i_mount;
+	int			error;
+
+	/*
+	 * check for re-use of an inode within an RCU grace period due to the
+	 * radix tree nodes not being updated yet. We monitor for this by
+	 * setting the inode number to zero before freeing the inode structure.
+	 * If the inode has been reallocated and set up, then the inode number
+	 * will not match, so check for that, too.
+	 */
+	spin_lock(&ip->i_flags_lock);
+	if (ip->i_ino != ino) {
+		trace_xfs_iget_skip(ip);
+		XFS_STATS_INC(xs_ig_frecycle);
+		error = EAGAIN;
+		goto out_error;
+	}
+
+
+	/*
+	 * If we are racing with another cache hit that is currently
+	 * instantiating this inode or currently recycling it out of
+	 * reclaimabe state, wait for the initialisation to complete
+	 * before continuing.
+	 *
+	 * XXX(hch): eventually we should do something equivalent to
+	 *	     wait_on_inode to wait for these flags to be cleared
+	 *	     instead of polling for it.
+	 */
+	if (ip->i_flags & (XFS_INEW|XFS_IRECLAIM)) {
+		trace_xfs_iget_skip(ip);
+		XFS_STATS_INC(xs_ig_frecycle);
+		error = EAGAIN;
+		goto out_error;
+	}
+
+	/*
+	 * If lookup is racing with unlink return an error immediately.
+	 */
+	if (ip->i_d.di_mode == 0 && !(flags & XFS_IGET_CREATE)) {
+		error = ENOENT;
+		goto out_error;
+	}
+
+	/*
+	 * If IRECLAIMABLE is set, we've torn down the VFS inode already.
+	 * Need to carefully get it back into useable state.
+	 */
+	if (ip->i_flags & XFS_IRECLAIMABLE) {
+		trace_xfs_iget_reclaim(ip);
+
+		/*
+		 * We need to set XFS_IRECLAIM to prevent xfs_reclaim_inode
+		 * from stomping over us while we recycle the inode.  We can't
+		 * clear the radix tree reclaimable tag yet as it requires
+		 * pag_ici_lock to be held exclusive.
+		 */
+		ip->i_flags |= XFS_IRECLAIM;
+
+		spin_unlock(&ip->i_flags_lock);
+		rcu_read_unlock();
+
+		error = -inode_init_always(mp->m_super, inode);
+		if (error) {
+			/*
+			 * Re-initializing the inode failed, and we are in deep
+			 * trouble.  Try to re-add it to the reclaim list.
+			 */
+			rcu_read_lock();
+			spin_lock(&ip->i_flags_lock);
+
+			ip->i_flags &= ~(XFS_INEW | XFS_IRECLAIM);
+			ASSERT(ip->i_flags & XFS_IRECLAIMABLE);
+			trace_xfs_iget_reclaim_fail(ip);
+			goto out_error;
+		}
+
+		spin_lock(&pag->pag_ici_lock);
+		spin_lock(&ip->i_flags_lock);
+
+		/*
+		 * Clear the per-lifetime state in the inode as we are now
+		 * effectively a new inode and need to return to the initial
+		 * state before reuse occurs.
+		 */
+		ip->i_flags &= ~XFS_IRECLAIM_RESET_FLAGS;
+		ip->i_flags |= XFS_INEW;
+		__xfs_inode_clear_reclaim_tag(mp, pag, ip);
+		inode->i_state = I_NEW;
+
+		ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock));
+		mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
+
+		spin_unlock(&ip->i_flags_lock);
+		spin_unlock(&pag->pag_ici_lock);
+	} else {
+		/* If the VFS inode is being torn down, pause and try again. */
+		if (!igrab(inode)) {
+			trace_xfs_iget_skip(ip);
+			error = EAGAIN;
+			goto out_error;
+		}
+
+		/* We've got a live one. */
+		spin_unlock(&ip->i_flags_lock);
+		rcu_read_unlock();
+		trace_xfs_iget_hit(ip);
+	}
+
+	if (lock_flags != 0)
+		xfs_ilock(ip, lock_flags);
+
+	xfs_iflags_clear(ip, XFS_ISTALE | XFS_IDONTCACHE);
+	XFS_STATS_INC(xs_ig_found);
+
+	return 0;
+
+out_error:
+	spin_unlock(&ip->i_flags_lock);
+	rcu_read_unlock();
+	return error;
+}
+
+
+static int
+xfs_iget_cache_miss(
+	struct xfs_mount	*mp,
+	struct xfs_perag	*pag,
+	xfs_trans_t		*tp,
+	xfs_ino_t		ino,
+	struct xfs_inode	**ipp,
+	int			flags,
+	int			lock_flags)
+{
+	struct xfs_inode	*ip;
+	int			error;
+	xfs_agino_t		agino = XFS_INO_TO_AGINO(mp, ino);
+	int			iflags;
+
+	ip = xfs_inode_alloc(mp, ino);
+	if (!ip)
+		return ENOMEM;
+
+	error = xfs_iread(mp, tp, ip, flags);
+	if (error)
+		goto out_destroy;
+
+	trace_xfs_iget_miss(ip);
+
+	if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) {
+		error = ENOENT;
+		goto out_destroy;
+	}
+
+	/*
+	 * Preload the radix tree so we can insert safely under the
+	 * write spinlock. Note that we cannot sleep inside the preload
+	 * region. Since we can be called from transaction context, don't
+	 * recurse into the file system.
+	 */
+	if (radix_tree_preload(GFP_NOFS)) {
+		error = EAGAIN;
+		goto out_destroy;
+	}
+
+	/*
+	 * Because the inode hasn't been added to the radix-tree yet it can't
+	 * be found by another thread, so we can do the non-sleeping lock here.
+	 */
+	if (lock_flags) {
+		if (!xfs_ilock_nowait(ip, lock_flags))
+			BUG();
+	}
+
+	/*
+	 * These values must be set before inserting the inode into the radix
+	 * tree as the moment it is inserted a concurrent lookup (allowed by the
+	 * RCU locking mechanism) can find it and that lookup must see that this
+	 * is an inode currently under construction (i.e. that XFS_INEW is set).
+	 * The ip->i_flags_lock that protects the XFS_INEW flag forms the
+	 * memory barrier that ensures this detection works correctly at lookup
+	 * time.
+	 */
+	iflags = XFS_INEW;
+	if (flags & XFS_IGET_DONTCACHE)
+		iflags |= XFS_IDONTCACHE;
+	ip->i_udquot = ip->i_gdquot = NULL;
+	xfs_iflags_set(ip, iflags);
+
+	/* insert the new inode */
+	spin_lock(&pag->pag_ici_lock);
+	error = radix_tree_insert(&pag->pag_ici_root, agino, ip);
+	if (unlikely(error)) {
+		WARN_ON(error != -EEXIST);
+		XFS_STATS_INC(xs_ig_dup);
+		error = EAGAIN;
+		goto out_preload_end;
+	}
+	spin_unlock(&pag->pag_ici_lock);
+	radix_tree_preload_end();
+
+	*ipp = ip;
+	return 0;
+
+out_preload_end:
+	spin_unlock(&pag->pag_ici_lock);
+	radix_tree_preload_end();
+	if (lock_flags)
+		xfs_iunlock(ip, lock_flags);
+out_destroy:
+	__destroy_inode(VFS_I(ip));
+	xfs_inode_free(ip);
+	return error;
+}
+
+/*
+ * Look up an inode by number in the given file system.
+ * The inode is looked up in the cache held in each AG.
+ * If the inode is found in the cache, initialise the vfs inode
+ * if necessary.
+ *
+ * If it is not in core, read it in from the file system's device,
+ * add it to the cache and initialise the vfs inode.
+ *
+ * The inode is locked according to the value of the lock_flags parameter.
+ * This flag parameter indicates how and if the inode's IO lock and inode lock
+ * should be taken.
+ *
+ * mp -- the mount point structure for the current file system.  It points
+ *       to the inode hash table.
+ * tp -- a pointer to the current transaction if there is one.  This is
+ *       simply passed through to the xfs_iread() call.
+ * ino -- the number of the inode desired.  This is the unique identifier
+ *        within the file system for the inode being requested.
+ * lock_flags -- flags indicating how to lock the inode.  See the comment
+ *		 for xfs_ilock() for a list of valid values.
+ */
+int
+xfs_iget(
+	xfs_mount_t	*mp,
+	xfs_trans_t	*tp,
+	xfs_ino_t	ino,
+	uint		flags,
+	uint		lock_flags,
+	xfs_inode_t	**ipp)
+{
+	xfs_inode_t	*ip;
+	int		error;
+	xfs_perag_t	*pag;
+	xfs_agino_t	agino;
+
+	/*
+	 * xfs_reclaim_inode() uses the ILOCK to ensure an inode
+	 * doesn't get freed while it's being referenced during a
+	 * radix tree traversal here.  It assumes this function
+	 * aqcuires only the ILOCK (and therefore it has no need to
+	 * involve the IOLOCK in this synchronization).
+	 */
+	ASSERT((lock_flags & (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED)) == 0);
+
+	/* reject inode numbers outside existing AGs */
+	if (!ino || XFS_INO_TO_AGNO(mp, ino) >= mp->m_sb.sb_agcount)
+		return EINVAL;
+
+	/* get the perag structure and ensure that it's inode capable */
+	pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ino));
+	agino = XFS_INO_TO_AGINO(mp, ino);
+
+again:
+	error = 0;
+	rcu_read_lock();
+	ip = radix_tree_lookup(&pag->pag_ici_root, agino);
+
+	if (ip) {
+		error = xfs_iget_cache_hit(pag, ip, ino, flags, lock_flags);
+		if (error)
+			goto out_error_or_again;
+	} else {
+		rcu_read_unlock();
+		XFS_STATS_INC(xs_ig_missed);
+
+		error = xfs_iget_cache_miss(mp, pag, tp, ino, &ip,
+							flags, lock_flags);
+		if (error)
+			goto out_error_or_again;
+	}
+	xfs_perag_put(pag);
+
+	*ipp = ip;
+
+	/*
+	 * If we have a real type for an on-disk inode, we can set ops(&unlock)
+	 * now.	 If it's a new inode being created, xfs_ialloc will handle it.
+	 */
+	if (xfs_iflags_test(ip, XFS_INEW) && ip->i_d.di_mode != 0)
+		xfs_setup_inode(ip);
+	return 0;
+
+out_error_or_again:
+	if (error == EAGAIN) {
+		delay(1);
+		goto again;
+	}
+	xfs_perag_put(pag);
+	return error;
+}
+
+/*
+ * The inode lookup is done in batches to keep the amount of lock traffic and
+ * radix tree lookups to a minimum. The batch size is a trade off between
+ * lookup reduction and stack usage. This is in the reclaim path, so we can't
+ * be too greedy.
+ */
+#define XFS_LOOKUP_BATCH	32
+
+STATIC int
+xfs_inode_ag_walk_grab(
+	struct xfs_inode	*ip)
+{
+	struct inode		*inode = VFS_I(ip);
+
+	ASSERT(rcu_read_lock_held());
+
+	/*
+	 * check for stale RCU freed inode
+	 *
+	 * If the inode has been reallocated, it doesn't matter if it's not in
+	 * the AG we are walking - we are walking for writeback, so if it
+	 * passes all the "valid inode" checks and is dirty, then we'll write
+	 * it back anyway.  If it has been reallocated and still being
+	 * initialised, the XFS_INEW check below will catch it.
+	 */
+	spin_lock(&ip->i_flags_lock);
+	if (!ip->i_ino)
+		goto out_unlock_noent;
+
+	/* avoid new or reclaimable inodes. Leave for reclaim code to flush */
+	if (__xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIMABLE | XFS_IRECLAIM))
+		goto out_unlock_noent;
+	spin_unlock(&ip->i_flags_lock);
+
+	/* nothing to sync during shutdown */
+	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+		return EFSCORRUPTED;
+
+	/* If we can't grab the inode, it must on it's way to reclaim. */
+	if (!igrab(inode))
+		return ENOENT;
+
+	if (is_bad_inode(inode)) {
+		IRELE(ip);
+		return ENOENT;
+	}
+
+	/* inode is valid */
+	return 0;
+
+out_unlock_noent:
+	spin_unlock(&ip->i_flags_lock);
+	return ENOENT;
+}
+
+STATIC int
+xfs_inode_ag_walk(
+	struct xfs_mount	*mp,
+	struct xfs_perag	*pag,
+	int			(*execute)(struct xfs_inode *ip,
+					   struct xfs_perag *pag, int flags,
+					   void *args),
+	int			flags,
+	void			*args,
+	int			tag)
+{
+	uint32_t		first_index;
+	int			last_error = 0;
+	int			skipped;
+	int			done;
+	int			nr_found;
+
+restart:
+	done = 0;
+	skipped = 0;
+	first_index = 0;
+	nr_found = 0;
+	do {
+		struct xfs_inode *batch[XFS_LOOKUP_BATCH];
+		int		error = 0;
+		int		i;
+
+		rcu_read_lock();
+
+		if (tag == -1)
+			nr_found = radix_tree_gang_lookup(&pag->pag_ici_root,
+					(void **)batch, first_index,
+					XFS_LOOKUP_BATCH);
+		else
+			nr_found = radix_tree_gang_lookup_tag(
+					&pag->pag_ici_root,
+					(void **) batch, first_index,
+					XFS_LOOKUP_BATCH, tag);
+
+		if (!nr_found) {
+			rcu_read_unlock();
+			break;
+		}
+
+		/*
+		 * Grab the inodes before we drop the lock. if we found
+		 * nothing, nr == 0 and the loop will be skipped.
+		 */
+		for (i = 0; i < nr_found; i++) {
+			struct xfs_inode *ip = batch[i];
+
+			if (done || xfs_inode_ag_walk_grab(ip))
+				batch[i] = NULL;
+
+			/*
+			 * Update the index for the next lookup. Catch
+			 * overflows into the next AG range which can occur if
+			 * we have inodes in the last block of the AG and we
+			 * are currently pointing to the last inode.
+			 *
+			 * Because we may see inodes that are from the wrong AG
+			 * due to RCU freeing and reallocation, only update the
+			 * index if it lies in this AG. It was a race that lead
+			 * us to see this inode, so another lookup from the
+			 * same index will not find it again.
+			 */
+			if (XFS_INO_TO_AGNO(mp, ip->i_ino) != pag->pag_agno)
+				continue;
+			first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
+			if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino))
+				done = 1;
+		}
+
+		/* unlock now we've grabbed the inodes. */
+		rcu_read_unlock();
+
+		for (i = 0; i < nr_found; i++) {
+			if (!batch[i])
+				continue;
+			error = execute(batch[i], pag, flags, args);
+			IRELE(batch[i]);
+			if (error == EAGAIN) {
+				skipped++;
+				continue;
+			}
+			if (error && last_error != EFSCORRUPTED)
+				last_error = error;
+		}
+
+		/* bail out if the filesystem is corrupted.  */
+		if (error == EFSCORRUPTED)
+			break;
+
+		cond_resched();
+
+	} while (nr_found && !done);
+
+	if (skipped) {
+		delay(1);
+		goto restart;
+	}
+	return last_error;
+}
+
+/*
+ * Background scanning to trim post-EOF preallocated space. This is queued
+ * based on the 'background_prealloc_discard_period' tunable (5m by default).
+ */
+STATIC void
+xfs_queue_eofblocks(
+	struct xfs_mount *mp)
+{
+	rcu_read_lock();
+	if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_EOFBLOCKS_TAG))
+		queue_delayed_work(mp->m_eofblocks_workqueue,
+				   &mp->m_eofblocks_work,
+				   msecs_to_jiffies(xfs_eofb_secs * 1000));
+	rcu_read_unlock();
+}
+
+void
+xfs_eofblocks_worker(
+	struct work_struct *work)
+{
+	struct xfs_mount *mp = container_of(to_delayed_work(work),
+				struct xfs_mount, m_eofblocks_work);
+	xfs_icache_free_eofblocks(mp, NULL);
+	xfs_queue_eofblocks(mp);
+}
+
+int
+xfs_inode_ag_iterator(
+	struct xfs_mount	*mp,
+	int			(*execute)(struct xfs_inode *ip,
+					   struct xfs_perag *pag, int flags,
+					   void *args),
+	int			flags,
+	void			*args)
+{
+	struct xfs_perag	*pag;
+	int			error = 0;
+	int			last_error = 0;
+	xfs_agnumber_t		ag;
+
+	ag = 0;
+	while ((pag = xfs_perag_get(mp, ag))) {
+		ag = pag->pag_agno + 1;
+		error = xfs_inode_ag_walk(mp, pag, execute, flags, args, -1);
+		xfs_perag_put(pag);
+		if (error) {
+			last_error = error;
+			if (error == EFSCORRUPTED)
+				break;
+		}
+	}
+	return XFS_ERROR(last_error);
+}
+
+int
+xfs_inode_ag_iterator_tag(
+	struct xfs_mount	*mp,
+	int			(*execute)(struct xfs_inode *ip,
+					   struct xfs_perag *pag, int flags,
+					   void *args),
+	int			flags,
+	void			*args,
+	int			tag)
+{
+	struct xfs_perag	*pag;
+	int			error = 0;
+	int			last_error = 0;
+	xfs_agnumber_t		ag;
+
+	ag = 0;
+	while ((pag = xfs_perag_get_tag(mp, ag, tag))) {
+		ag = pag->pag_agno + 1;
+		error = xfs_inode_ag_walk(mp, pag, execute, flags, args, tag);
+		xfs_perag_put(pag);
+		if (error) {
+			last_error = error;
+			if (error == EFSCORRUPTED)
+				break;
+		}
+	}
+	return XFS_ERROR(last_error);
+}
+
+/*
+ * Queue a new inode reclaim pass if there are reclaimable inodes and there
+ * isn't a reclaim pass already in progress. By default it runs every 5s based
+ * on the xfs periodic sync default of 30s. Perhaps this should have it's own
+ * tunable, but that can be done if this method proves to be ineffective or too
+ * aggressive.
+ */
+static void
+xfs_reclaim_work_queue(
+	struct xfs_mount        *mp)
+{
+
+	rcu_read_lock();
+	if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_RECLAIM_TAG)) {
+		queue_delayed_work(mp->m_reclaim_workqueue, &mp->m_reclaim_work,
+			msecs_to_jiffies(xfs_syncd_centisecs / 6 * 10));
+	}
+	rcu_read_unlock();
+}
+
+/*
+ * This is a fast pass over the inode cache to try to get reclaim moving on as
+ * many inodes as possible in a short period of time. It kicks itself every few
+ * seconds, as well as being kicked by the inode cache shrinker when memory
+ * goes low. It scans as quickly as possible avoiding locked inodes or those
+ * already being flushed, and once done schedules a future pass.
+ */
+void
+xfs_reclaim_worker(
+	struct work_struct *work)
+{
+	struct xfs_mount *mp = container_of(to_delayed_work(work),
+					struct xfs_mount, m_reclaim_work);
+
+	xfs_reclaim_inodes(mp, SYNC_TRYLOCK);
+	xfs_reclaim_work_queue(mp);
+}
+
+static void
+__xfs_inode_set_reclaim_tag(
+	struct xfs_perag	*pag,
+	struct xfs_inode	*ip)
+{
+	radix_tree_tag_set(&pag->pag_ici_root,
+			   XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino),
+			   XFS_ICI_RECLAIM_TAG);
+
+	if (!pag->pag_ici_reclaimable) {
+		/* propagate the reclaim tag up into the perag radix tree */
+		spin_lock(&ip->i_mount->m_perag_lock);
+		radix_tree_tag_set(&ip->i_mount->m_perag_tree,
+				XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino),
+				XFS_ICI_RECLAIM_TAG);
+		spin_unlock(&ip->i_mount->m_perag_lock);
+
+		/* schedule periodic background inode reclaim */
+		xfs_reclaim_work_queue(ip->i_mount);
+
+		trace_xfs_perag_set_reclaim(ip->i_mount, pag->pag_agno,
+							-1, _RET_IP_);
+	}
+	pag->pag_ici_reclaimable++;
+}
+
+/*
+ * We set the inode flag atomically with the radix tree tag.
+ * Once we get tag lookups on the radix tree, this inode flag
+ * can go away.
+ */
+void
+xfs_inode_set_reclaim_tag(
+	xfs_inode_t	*ip)
+{
+	struct xfs_mount *mp = ip->i_mount;
+	struct xfs_perag *pag;
+
+	pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
+	spin_lock(&pag->pag_ici_lock);
+	spin_lock(&ip->i_flags_lock);
+	__xfs_inode_set_reclaim_tag(pag, ip);
+	__xfs_iflags_set(ip, XFS_IRECLAIMABLE);
+	spin_unlock(&ip->i_flags_lock);
+	spin_unlock(&pag->pag_ici_lock);
+	xfs_perag_put(pag);
+}
+
+STATIC void
+__xfs_inode_clear_reclaim(
+	xfs_perag_t	*pag,
+	xfs_inode_t	*ip)
+{
+	pag->pag_ici_reclaimable--;
+	if (!pag->pag_ici_reclaimable) {
+		/* clear the reclaim tag from the perag radix tree */
+		spin_lock(&ip->i_mount->m_perag_lock);
+		radix_tree_tag_clear(&ip->i_mount->m_perag_tree,
+				XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino),
+				XFS_ICI_RECLAIM_TAG);
+		spin_unlock(&ip->i_mount->m_perag_lock);
+		trace_xfs_perag_clear_reclaim(ip->i_mount, pag->pag_agno,
+							-1, _RET_IP_);
+	}
+}
+
+STATIC void
+__xfs_inode_clear_reclaim_tag(
+	xfs_mount_t	*mp,
+	xfs_perag_t	*pag,
+	xfs_inode_t	*ip)
+{
+	radix_tree_tag_clear(&pag->pag_ici_root,
+			XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);
+	__xfs_inode_clear_reclaim(pag, ip);
+}
+
+/*
+ * Grab the inode for reclaim exclusively.
+ * Return 0 if we grabbed it, non-zero otherwise.
+ */
+STATIC int
+xfs_reclaim_inode_grab(
+	struct xfs_inode	*ip,
+	int			flags)
+{
+	ASSERT(rcu_read_lock_held());
+
+	/* quick check for stale RCU freed inode */
+	if (!ip->i_ino)
+		return 1;
+
+	/*
+	 * If we are asked for non-blocking operation, do unlocked checks to
+	 * see if the inode already is being flushed or in reclaim to avoid
+	 * lock traffic.
+	 */
+	if ((flags & SYNC_TRYLOCK) &&
+	    __xfs_iflags_test(ip, XFS_IFLOCK | XFS_IRECLAIM))
+		return 1;
+
+	/*
+	 * The radix tree lock here protects a thread in xfs_iget from racing
+	 * with us starting reclaim on the inode.  Once we have the
+	 * XFS_IRECLAIM flag set it will not touch us.
+	 *
+	 * Due to RCU lookup, we may find inodes that have been freed and only
+	 * have XFS_IRECLAIM set.  Indeed, we may see reallocated inodes that
+	 * aren't candidates for reclaim at all, so we must check the
+	 * XFS_IRECLAIMABLE is set first before proceeding to reclaim.
+	 */
+	spin_lock(&ip->i_flags_lock);
+	if (!__xfs_iflags_test(ip, XFS_IRECLAIMABLE) ||
+	    __xfs_iflags_test(ip, XFS_IRECLAIM)) {
+		/* not a reclaim candidate. */
+		spin_unlock(&ip->i_flags_lock);
+		return 1;
+	}
+	__xfs_iflags_set(ip, XFS_IRECLAIM);
+	spin_unlock(&ip->i_flags_lock);
+	return 0;
+}
+
+/*
+ * Inodes in different states need to be treated differently. The following
+ * table lists the inode states and the reclaim actions necessary:
+ *
+ *	inode state	     iflush ret		required action
+ *      ---------------      ----------         ---------------
+ *	bad			-		reclaim
+ *	shutdown		EIO		unpin and reclaim
+ *	clean, unpinned		0		reclaim
+ *	stale, unpinned		0		reclaim
+ *	clean, pinned(*)	0		requeue
+ *	stale, pinned		EAGAIN		requeue
+ *	dirty, async		-		requeue
+ *	dirty, sync		0		reclaim
+ *
+ * (*) dgc: I don't think the clean, pinned state is possible but it gets
+ * handled anyway given the order of checks implemented.
+ *
+ * Also, because we get the flush lock first, we know that any inode that has
+ * been flushed delwri has had the flush completed by the time we check that
+ * the inode is clean.
+ *
+ * Note that because the inode is flushed delayed write by AIL pushing, the
+ * flush lock may already be held here and waiting on it can result in very
+ * long latencies.  Hence for sync reclaims, where we wait on the flush lock,
+ * the caller should push the AIL first before trying to reclaim inodes to
+ * minimise the amount of time spent waiting.  For background relaim, we only
+ * bother to reclaim clean inodes anyway.
+ *
+ * Hence the order of actions after gaining the locks should be:
+ *	bad		=> reclaim
+ *	shutdown	=> unpin and reclaim
+ *	pinned, async	=> requeue
+ *	pinned, sync	=> unpin
+ *	stale		=> reclaim
+ *	clean		=> reclaim
+ *	dirty, async	=> requeue
+ *	dirty, sync	=> flush, wait and reclaim
+ */
+STATIC int
+xfs_reclaim_inode(
+	struct xfs_inode	*ip,
+	struct xfs_perag	*pag,
+	int			sync_mode)
+{
+	struct xfs_buf		*bp = NULL;
+	int			error;
+
+restart:
+	error = 0;
+	xfs_ilock(ip, XFS_ILOCK_EXCL);
+	if (!xfs_iflock_nowait(ip)) {
+		if (!(sync_mode & SYNC_WAIT))
+			goto out;
+		xfs_iflock(ip);
+	}
+
+	if (is_bad_inode(VFS_I(ip)))
+		goto reclaim;
+	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
+		xfs_iunpin_wait(ip);
+		xfs_iflush_abort(ip, false);
+		goto reclaim;
+	}
+	if (xfs_ipincount(ip)) {
+		if (!(sync_mode & SYNC_WAIT))
+			goto out_ifunlock;
+		xfs_iunpin_wait(ip);
+	}
+	if (xfs_iflags_test(ip, XFS_ISTALE))
+		goto reclaim;
+	if (xfs_inode_clean(ip))
+		goto reclaim;
+
+	/*
+	 * Never flush out dirty data during non-blocking reclaim, as it would
+	 * just contend with AIL pushing trying to do the same job.
+	 */
+	if (!(sync_mode & SYNC_WAIT))
+		goto out_ifunlock;
+
+	/*
+	 * Now we have an inode that needs flushing.
+	 *
+	 * Note that xfs_iflush will never block on the inode buffer lock, as
+	 * xfs_ifree_cluster() can lock the inode buffer before it locks the
+	 * ip->i_lock, and we are doing the exact opposite here.  As a result,
+	 * doing a blocking xfs_imap_to_bp() to get the cluster buffer would
+	 * result in an ABBA deadlock with xfs_ifree_cluster().
+	 *
+	 * As xfs_ifree_cluser() must gather all inodes that are active in the
+	 * cache to mark them stale, if we hit this case we don't actually want
+	 * to do IO here - we want the inode marked stale so we can simply
+	 * reclaim it.  Hence if we get an EAGAIN error here,  just unlock the
+	 * inode, back off and try again.  Hopefully the next pass through will
+	 * see the stale flag set on the inode.
+	 */
+	error = xfs_iflush(ip, &bp);
+	if (error == EAGAIN) {
+		xfs_iunlock(ip, XFS_ILOCK_EXCL);
+		/* backoff longer than in xfs_ifree_cluster */
+		delay(2);
+		goto restart;
+	}
+
+	if (!error) {
+		error = xfs_bwrite(bp);
+		xfs_buf_relse(bp);
+	}
+
+	xfs_iflock(ip);
+reclaim:
+	xfs_ifunlock(ip);
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
+	XFS_STATS_INC(xs_ig_reclaims);
+	/*
+	 * Remove the inode from the per-AG radix tree.
+	 *
+	 * Because radix_tree_delete won't complain even if the item was never
+	 * added to the tree assert that it's been there before to catch
+	 * problems with the inode life time early on.
+	 */
+	spin_lock(&pag->pag_ici_lock);
+	if (!radix_tree_delete(&pag->pag_ici_root,
+				XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino)))
+		ASSERT(0);
+	__xfs_inode_clear_reclaim(pag, ip);
+	spin_unlock(&pag->pag_ici_lock);
+
+	/*
+	 * Here we do an (almost) spurious inode lock in order to coordinate
+	 * with inode cache radix tree lookups.  This is because the lookup
+	 * can reference the inodes in the cache without taking references.
+	 *
+	 * We make that OK here by ensuring that we wait until the inode is
+	 * unlocked after the lookup before we go ahead and free it.
+	 */
+	xfs_ilock(ip, XFS_ILOCK_EXCL);
+	xfs_qm_dqdetach(ip);
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
+	xfs_inode_free(ip);
+	return error;
+
+out_ifunlock:
+	xfs_ifunlock(ip);
+out:
+	xfs_iflags_clear(ip, XFS_IRECLAIM);
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	/*
+	 * We could return EAGAIN here to make reclaim rescan the inode tree in
+	 * a short while. However, this just burns CPU time scanning the tree
+	 * waiting for IO to complete and the reclaim work never goes back to
+	 * the idle state. Instead, return 0 to let the next scheduled
+	 * background reclaim attempt to reclaim the inode again.
+	 */
+	return 0;
+}
+
+/*
+ * Walk the AGs and reclaim the inodes in them. Even if the filesystem is
+ * corrupted, we still want to try to reclaim all the inodes. If we don't,
+ * then a shut down during filesystem unmount reclaim walk leak all the
+ * unreclaimed inodes.
+ */
+STATIC int
+xfs_reclaim_inodes_ag(
+	struct xfs_mount	*mp,
+	int			flags,
+	int			*nr_to_scan)
+{
+	struct xfs_perag	*pag;
+	int			error = 0;
+	int			last_error = 0;
+	xfs_agnumber_t		ag;
+	int			trylock = flags & SYNC_TRYLOCK;
+	int			skipped;
+
+restart:
+	ag = 0;
+	skipped = 0;
+	while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) {
+		unsigned long	first_index = 0;
+		int		done = 0;
+		int		nr_found = 0;
+
+		ag = pag->pag_agno + 1;
+
+		if (trylock) {
+			if (!mutex_trylock(&pag->pag_ici_reclaim_lock)) {
+				skipped++;
+				xfs_perag_put(pag);
+				continue;
+			}
+			first_index = pag->pag_ici_reclaim_cursor;
+		} else
+			mutex_lock(&pag->pag_ici_reclaim_lock);
+
+		do {
+			struct xfs_inode *batch[XFS_LOOKUP_BATCH];
+			int	i;
+
+			rcu_read_lock();
+			nr_found = radix_tree_gang_lookup_tag(
+					&pag->pag_ici_root,
+					(void **)batch, first_index,
+					XFS_LOOKUP_BATCH,
+					XFS_ICI_RECLAIM_TAG);
+			if (!nr_found) {
+				done = 1;
+				rcu_read_unlock();
+				break;
+			}
+
+			/*
+			 * Grab the inodes before we drop the lock. if we found
+			 * nothing, nr == 0 and the loop will be skipped.
+			 */
+			for (i = 0; i < nr_found; i++) {
+				struct xfs_inode *ip = batch[i];
+
+				if (done || xfs_reclaim_inode_grab(ip, flags))
+					batch[i] = NULL;
+
+				/*
+				 * Update the index for the next lookup. Catch
+				 * overflows into the next AG range which can
+				 * occur if we have inodes in the last block of
+				 * the AG and we are currently pointing to the
+				 * last inode.
+				 *
+				 * Because we may see inodes that are from the
+				 * wrong AG due to RCU freeing and
+				 * reallocation, only update the index if it
+				 * lies in this AG. It was a race that lead us
+				 * to see this inode, so another lookup from
+				 * the same index will not find it again.
+				 */
+				if (XFS_INO_TO_AGNO(mp, ip->i_ino) !=
+								pag->pag_agno)
+					continue;
+				first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
+				if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino))
+					done = 1;
+			}
+
+			/* unlock now we've grabbed the inodes. */
+			rcu_read_unlock();
+
+			for (i = 0; i < nr_found; i++) {
+				if (!batch[i])
+					continue;
+				error = xfs_reclaim_inode(batch[i], pag, flags);
+				if (error && last_error != EFSCORRUPTED)
+					last_error = error;
+			}
+
+			*nr_to_scan -= XFS_LOOKUP_BATCH;
+
+			cond_resched();
+
+		} while (nr_found && !done && *nr_to_scan > 0);
+
+		if (trylock && !done)
+			pag->pag_ici_reclaim_cursor = first_index;
+		else
+			pag->pag_ici_reclaim_cursor = 0;
+		mutex_unlock(&pag->pag_ici_reclaim_lock);
+		xfs_perag_put(pag);
+	}
+
+	/*
+	 * if we skipped any AG, and we still have scan count remaining, do
+	 * another pass this time using blocking reclaim semantics (i.e
+	 * waiting on the reclaim locks and ignoring the reclaim cursors). This
+	 * ensure that when we get more reclaimers than AGs we block rather
+	 * than spin trying to execute reclaim.
+	 */
+	if (skipped && (flags & SYNC_WAIT) && *nr_to_scan > 0) {
+		trylock = 0;
+		goto restart;
+	}
+	return XFS_ERROR(last_error);
+}
+
+int
+xfs_reclaim_inodes(
+	xfs_mount_t	*mp,
+	int		mode)
+{
+	int		nr_to_scan = INT_MAX;
+
+	return xfs_reclaim_inodes_ag(mp, mode, &nr_to_scan);
+}
+
+/*
+ * Scan a certain number of inodes for reclaim.
+ *
+ * When called we make sure that there is a background (fast) inode reclaim in
+ * progress, while we will throttle the speed of reclaim via doing synchronous
+ * reclaim of inodes. That means if we come across dirty inodes, we wait for
+ * them to be cleaned, which we hope will not be very long due to the
+ * background walker having already kicked the IO off on those dirty inodes.
+ */
+void
+xfs_reclaim_inodes_nr(
+	struct xfs_mount	*mp,
+	int			nr_to_scan)
+{
+	/* kick background reclaimer and push the AIL */
+	xfs_reclaim_work_queue(mp);
+	xfs_ail_push_all(mp->m_ail);
+
+	xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT, &nr_to_scan);
+}
+
+/*
+ * Return the number of reclaimable inodes in the filesystem for
+ * the shrinker to determine how much to reclaim.
+ */
+int
+xfs_reclaim_inodes_count(
+	struct xfs_mount	*mp)
+{
+	struct xfs_perag	*pag;
+	xfs_agnumber_t		ag = 0;
+	int			reclaimable = 0;
+
+	while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) {
+		ag = pag->pag_agno + 1;
+		reclaimable += pag->pag_ici_reclaimable;
+		xfs_perag_put(pag);
+	}
+	return reclaimable;
+}
+
+STATIC int
+xfs_inode_match_id(
+	struct xfs_inode	*ip,
+	struct xfs_eofblocks	*eofb)
+{
+	if (eofb->eof_flags & XFS_EOF_FLAGS_UID &&
+	    ip->i_d.di_uid != eofb->eof_uid)
+		return 0;
+
+	if (eofb->eof_flags & XFS_EOF_FLAGS_GID &&
+	    ip->i_d.di_gid != eofb->eof_gid)
+		return 0;
+
+	if (eofb->eof_flags & XFS_EOF_FLAGS_PRID &&
+	    xfs_get_projid(ip) != eofb->eof_prid)
+		return 0;
+
+	return 1;
+}
+
+STATIC int
+xfs_inode_free_eofblocks(
+	struct xfs_inode	*ip,
+	struct xfs_perag	*pag,
+	int			flags,
+	void			*args)
+{
+	int ret;
+	struct xfs_eofblocks *eofb = args;
+
+	if (!xfs_can_free_eofblocks(ip, false)) {
+		/* inode could be preallocated or append-only */
+		trace_xfs_inode_free_eofblocks_invalid(ip);
+		xfs_inode_clear_eofblocks_tag(ip);
+		return 0;
+	}
+
+	/*
+	 * If the mapping is dirty the operation can block and wait for some
+	 * time. Unless we are waiting, skip it.
+	 */
+	if (!(flags & SYNC_WAIT) &&
+	    mapping_tagged(VFS_I(ip)->i_mapping, PAGECACHE_TAG_DIRTY))
+		return 0;
+
+	if (eofb) {
+		if (!xfs_inode_match_id(ip, eofb))
+			return 0;
+
+		/* skip the inode if the file size is too small */
+		if (eofb->eof_flags & XFS_EOF_FLAGS_MINFILESIZE &&
+		    XFS_ISIZE(ip) < eofb->eof_min_file_size)
+			return 0;
+	}
+
+	ret = xfs_free_eofblocks(ip->i_mount, ip, true);
+
+	/* don't revisit the inode if we're not waiting */
+	if (ret == EAGAIN && !(flags & SYNC_WAIT))
+		ret = 0;
+
+	return ret;
+}
+
+int
+xfs_icache_free_eofblocks(
+	struct xfs_mount	*mp,
+	struct xfs_eofblocks	*eofb)
+{
+	int flags = SYNC_TRYLOCK;
+
+	if (eofb && (eofb->eof_flags & XFS_EOF_FLAGS_SYNC))
+		flags = SYNC_WAIT;
+
+	return xfs_inode_ag_iterator_tag(mp, xfs_inode_free_eofblocks, flags,
+					 eofb, XFS_ICI_EOFBLOCKS_TAG);
+}
+
+void
+xfs_inode_set_eofblocks_tag(
+	xfs_inode_t	*ip)
+{
+	struct xfs_mount *mp = ip->i_mount;
+	struct xfs_perag *pag;
+	int tagged;
+
+	pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
+	spin_lock(&pag->pag_ici_lock);
+	trace_xfs_inode_set_eofblocks_tag(ip);
+
+	tagged = radix_tree_tagged(&pag->pag_ici_root,
+				   XFS_ICI_EOFBLOCKS_TAG);
+	radix_tree_tag_set(&pag->pag_ici_root,
+			   XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino),
+			   XFS_ICI_EOFBLOCKS_TAG);
+	if (!tagged) {
+		/* propagate the eofblocks tag up into the perag radix tree */
+		spin_lock(&ip->i_mount->m_perag_lock);
+		radix_tree_tag_set(&ip->i_mount->m_perag_tree,
+				   XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino),
+				   XFS_ICI_EOFBLOCKS_TAG);
+		spin_unlock(&ip->i_mount->m_perag_lock);
+
+		/* kick off background trimming */
+		xfs_queue_eofblocks(ip->i_mount);
+
+		trace_xfs_perag_set_eofblocks(ip->i_mount, pag->pag_agno,
+					      -1, _RET_IP_);
+	}
+
+	spin_unlock(&pag->pag_ici_lock);
+	xfs_perag_put(pag);
+}
+
+void
+xfs_inode_clear_eofblocks_tag(
+	xfs_inode_t	*ip)
+{
+	struct xfs_mount *mp = ip->i_mount;
+	struct xfs_perag *pag;
+
+	pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
+	spin_lock(&pag->pag_ici_lock);
+	trace_xfs_inode_clear_eofblocks_tag(ip);
+
+	radix_tree_tag_clear(&pag->pag_ici_root,
+			     XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino),
+			     XFS_ICI_EOFBLOCKS_TAG);
+	if (!radix_tree_tagged(&pag->pag_ici_root, XFS_ICI_EOFBLOCKS_TAG)) {
+		/* clear the eofblocks tag from the perag radix tree */
+		spin_lock(&ip->i_mount->m_perag_lock);
+		radix_tree_tag_clear(&ip->i_mount->m_perag_tree,
+				     XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino),
+				     XFS_ICI_EOFBLOCKS_TAG);
+		spin_unlock(&ip->i_mount->m_perag_lock);
+		trace_xfs_perag_clear_eofblocks(ip->i_mount, pag->pag_agno,
+					       -1, _RET_IP_);
+	}
+
+	spin_unlock(&pag->pag_ici_lock);
+	xfs_perag_put(pag);
+}
+
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
new file mode 100644
index 0000000..e0f138c
--- /dev/null
+++ b/fs/xfs/xfs_icache.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef XFS_SYNC_H
+#define XFS_SYNC_H 1
+
+struct xfs_mount;
+struct xfs_perag;
+
+#define SYNC_WAIT		0x0001	/* wait for i/o to complete */
+#define SYNC_TRYLOCK		0x0002  /* only try to lock inodes */
+
+int xfs_iget(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t ino,
+	     uint flags, uint lock_flags, xfs_inode_t **ipp);
+
+void xfs_reclaim_worker(struct work_struct *work);
+
+int xfs_reclaim_inodes(struct xfs_mount *mp, int mode);
+int xfs_reclaim_inodes_count(struct xfs_mount *mp);
+void xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);
+
+void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
+
+void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip);
+void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip);
+int xfs_icache_free_eofblocks(struct xfs_mount *, struct xfs_eofblocks *);
+void xfs_eofblocks_worker(struct work_struct *);
+
+int xfs_sync_inode_grab(struct xfs_inode *ip);
+int xfs_inode_ag_iterator(struct xfs_mount *mp,
+	int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag,
+		int flags, void *args),
+	int flags, void *args);
+int xfs_inode_ag_iterator_tag(struct xfs_mount *mp,
+	int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag,
+		int flags, void *args),
+	int flags, void *args, int tag);
+
+#endif
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
deleted file mode 100644
index 784a803..0000000
--- a/fs/xfs/xfs_iget.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include "xfs.h"
-#include "xfs_fs.h"
-#include "xfs_types.h"
-#include "xfs_acl.h"
-#include "xfs_log.h"
-#include "xfs_inum.h"
-#include "xfs_trans.h"
-#include "xfs_sb.h"
-#include "xfs_ag.h"
-#include "xfs_mount.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_alloc_btree.h"
-#include "xfs_ialloc_btree.h"
-#include "xfs_dinode.h"
-#include "xfs_inode.h"
-#include "xfs_btree.h"
-#include "xfs_ialloc.h"
-#include "xfs_quota.h"
-#include "xfs_utils.h"
-#include "xfs_trans_priv.h"
-#include "xfs_inode_item.h"
-#include "xfs_bmap.h"
-#include "xfs_trace.h"
-
-
-/*
- * Allocate and initialise an xfs_inode.
- */
-STATIC struct xfs_inode *
-xfs_inode_alloc(
-	struct xfs_mount	*mp,
-	xfs_ino_t		ino)
-{
-	struct xfs_inode	*ip;
-
-	/*
-	 * if this didn't occur in transactions, we could use
-	 * KM_MAYFAIL and return NULL here on ENOMEM. Set the
-	 * code up to do this anyway.
-	 */
-	ip = kmem_zone_alloc(xfs_inode_zone, KM_SLEEP);
-	if (!ip)
-		return NULL;
-	if (inode_init_always(mp->m_super, VFS_I(ip))) {
-		kmem_zone_free(xfs_inode_zone, ip);
-		return NULL;
-	}
-
-	ASSERT(atomic_read(&ip->i_pincount) == 0);
-	ASSERT(!spin_is_locked(&ip->i_flags_lock));
-	ASSERT(!xfs_isiflocked(ip));
-	ASSERT(ip->i_ino == 0);
-
-	mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
-
-	/* initialise the xfs inode */
-	ip->i_ino = ino;
-	ip->i_mount = mp;
-	memset(&ip->i_imap, 0, sizeof(struct xfs_imap));
-	ip->i_afp = NULL;
-	memset(&ip->i_df, 0, sizeof(xfs_ifork_t));
-	ip->i_flags = 0;
-	ip->i_delayed_blks = 0;
-	memset(&ip->i_d, 0, sizeof(xfs_icdinode_t));
-
-	return ip;
-}
-
-STATIC void
-xfs_inode_free_callback(
-	struct rcu_head		*head)
-{
-	struct inode		*inode = container_of(head, struct inode, i_rcu);
-	struct xfs_inode	*ip = XFS_I(inode);
-
-	kmem_zone_free(xfs_inode_zone, ip);
-}
-
-void
-xfs_inode_free(
-	struct xfs_inode	*ip)
-{
-	switch (ip->i_d.di_mode & S_IFMT) {
-	case S_IFREG:
-	case S_IFDIR:
-	case S_IFLNK:
-		xfs_idestroy_fork(ip, XFS_DATA_FORK);
-		break;
-	}
-
-	if (ip->i_afp)
-		xfs_idestroy_fork(ip, XFS_ATTR_FORK);
-
-	if (ip->i_itemp) {
-		ASSERT(!(ip->i_itemp->ili_item.li_flags & XFS_LI_IN_AIL));
-		xfs_inode_item_destroy(ip);
-		ip->i_itemp = NULL;
-	}
-
-	/* asserts to verify all state is correct here */
-	ASSERT(atomic_read(&ip->i_pincount) == 0);
-	ASSERT(!spin_is_locked(&ip->i_flags_lock));
-	ASSERT(!xfs_isiflocked(ip));
-
-	/*
-	 * Because we use RCU freeing we need to ensure the inode always
-	 * appears to be reclaimed with an invalid inode number when in the
-	 * free state. The ip->i_flags_lock provides the barrier against lookup
-	 * races.
-	 */
-	spin_lock(&ip->i_flags_lock);
-	ip->i_flags = XFS_IRECLAIM;
-	ip->i_ino = 0;
-	spin_unlock(&ip->i_flags_lock);
-
-	call_rcu(&VFS_I(ip)->i_rcu, xfs_inode_free_callback);
-}
-
-/*
- * Check the validity of the inode we just found it the cache
- */
-static int
-xfs_iget_cache_hit(
-	struct xfs_perag	*pag,
-	struct xfs_inode	*ip,
-	xfs_ino_t		ino,
-	int			flags,
-	int			lock_flags) __releases(RCU)
-{
-	struct inode		*inode = VFS_I(ip);
-	struct xfs_mount	*mp = ip->i_mount;
-	int			error;
-
-	/*
-	 * check for re-use of an inode within an RCU grace period due to the
-	 * radix tree nodes not being updated yet. We monitor for this by
-	 * setting the inode number to zero before freeing the inode structure.
-	 * If the inode has been reallocated and set up, then the inode number
-	 * will not match, so check for that, too.
-	 */
-	spin_lock(&ip->i_flags_lock);
-	if (ip->i_ino != ino) {
-		trace_xfs_iget_skip(ip);
-		XFS_STATS_INC(xs_ig_frecycle);
-		error = EAGAIN;
-		goto out_error;
-	}
-
-
-	/*
-	 * If we are racing with another cache hit that is currently
-	 * instantiating this inode or currently recycling it out of
-	 * reclaimabe state, wait for the initialisation to complete
-	 * before continuing.
-	 *
-	 * XXX(hch): eventually we should do something equivalent to
-	 *	     wait_on_inode to wait for these flags to be cleared
-	 *	     instead of polling for it.
-	 */
-	if (ip->i_flags & (XFS_INEW|XFS_IRECLAIM)) {
-		trace_xfs_iget_skip(ip);
-		XFS_STATS_INC(xs_ig_frecycle);
-		error = EAGAIN;
-		goto out_error;
-	}
-
-	/*
-	 * If lookup is racing with unlink return an error immediately.
-	 */
-	if (ip->i_d.di_mode == 0 && !(flags & XFS_IGET_CREATE)) {
-		error = ENOENT;
-		goto out_error;
-	}
-
-	/*
-	 * If IRECLAIMABLE is set, we've torn down the VFS inode already.
-	 * Need to carefully get it back into useable state.
-	 */
-	if (ip->i_flags & XFS_IRECLAIMABLE) {
-		trace_xfs_iget_reclaim(ip);
-
-		/*
-		 * We need to set XFS_IRECLAIM to prevent xfs_reclaim_inode
-		 * from stomping over us while we recycle the inode.  We can't
-		 * clear the radix tree reclaimable tag yet as it requires
-		 * pag_ici_lock to be held exclusive.
-		 */
-		ip->i_flags |= XFS_IRECLAIM;
-
-		spin_unlock(&ip->i_flags_lock);
-		rcu_read_unlock();
-
-		error = -inode_init_always(mp->m_super, inode);
-		if (error) {
-			/*
-			 * Re-initializing the inode failed, and we are in deep
-			 * trouble.  Try to re-add it to the reclaim list.
-			 */
-			rcu_read_lock();
-			spin_lock(&ip->i_flags_lock);
-
-			ip->i_flags &= ~(XFS_INEW | XFS_IRECLAIM);
-			ASSERT(ip->i_flags & XFS_IRECLAIMABLE);
-			trace_xfs_iget_reclaim_fail(ip);
-			goto out_error;
-		}
-
-		spin_lock(&pag->pag_ici_lock);
-		spin_lock(&ip->i_flags_lock);
-
-		/*
-		 * Clear the per-lifetime state in the inode as we are now
-		 * effectively a new inode and need to return to the initial
-		 * state before reuse occurs.
-		 */
-		ip->i_flags &= ~XFS_IRECLAIM_RESET_FLAGS;
-		ip->i_flags |= XFS_INEW;
-		__xfs_inode_clear_reclaim_tag(mp, pag, ip);
-		inode->i_state = I_NEW;
-
-		ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock));
-		mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
-
-		spin_unlock(&ip->i_flags_lock);
-		spin_unlock(&pag->pag_ici_lock);
-	} else {
-		/* If the VFS inode is being torn down, pause and try again. */
-		if (!igrab(inode)) {
-			trace_xfs_iget_skip(ip);
-			error = EAGAIN;
-			goto out_error;
-		}
-
-		/* We've got a live one. */
-		spin_unlock(&ip->i_flags_lock);
-		rcu_read_unlock();
-		trace_xfs_iget_hit(ip);
-	}
-
-	if (lock_flags != 0)
-		xfs_ilock(ip, lock_flags);
-
-	xfs_iflags_clear(ip, XFS_ISTALE | XFS_IDONTCACHE);
-	XFS_STATS_INC(xs_ig_found);
-
-	return 0;
-
-out_error:
-	spin_unlock(&ip->i_flags_lock);
-	rcu_read_unlock();
-	return error;
-}
-
-
-static int
-xfs_iget_cache_miss(
-	struct xfs_mount	*mp,
-	struct xfs_perag	*pag,
-	xfs_trans_t		*tp,
-	xfs_ino_t		ino,
-	struct xfs_inode	**ipp,
-	int			flags,
-	int			lock_flags)
-{
-	struct xfs_inode	*ip;
-	int			error;
-	xfs_agino_t		agino = XFS_INO_TO_AGINO(mp, ino);
-	int			iflags;
-
-	ip = xfs_inode_alloc(mp, ino);
-	if (!ip)
-		return ENOMEM;
-
-	error = xfs_iread(mp, tp, ip, flags);
-	if (error)
-		goto out_destroy;
-
-	trace_xfs_iget_miss(ip);
-
-	if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) {
-		error = ENOENT;
-		goto out_destroy;
-	}
-
-	/*
-	 * Preload the radix tree so we can insert safely under the
-	 * write spinlock. Note that we cannot sleep inside the preload
-	 * region. Since we can be called from transaction context, don't
-	 * recurse into the file system.
-	 */
-	if (radix_tree_preload(GFP_NOFS)) {
-		error = EAGAIN;
-		goto out_destroy;
-	}
-
-	/*
-	 * Because the inode hasn't been added to the radix-tree yet it can't
-	 * be found by another thread, so we can do the non-sleeping lock here.
-	 */
-	if (lock_flags) {
-		if (!xfs_ilock_nowait(ip, lock_flags))
-			BUG();
-	}
-
-	/*
-	 * These values must be set before inserting the inode into the radix
-	 * tree as the moment it is inserted a concurrent lookup (allowed by the
-	 * RCU locking mechanism) can find it and that lookup must see that this
-	 * is an inode currently under construction (i.e. that XFS_INEW is set).
-	 * The ip->i_flags_lock that protects the XFS_INEW flag forms the
-	 * memory barrier that ensures this detection works correctly at lookup
-	 * time.
-	 */
-	iflags = XFS_INEW;
-	if (flags & XFS_IGET_DONTCACHE)
-		iflags |= XFS_IDONTCACHE;
-	ip->i_udquot = ip->i_gdquot = NULL;
-	xfs_iflags_set(ip, iflags);
-
-	/* insert the new inode */
-	spin_lock(&pag->pag_ici_lock);
-	error = radix_tree_insert(&pag->pag_ici_root, agino, ip);
-	if (unlikely(error)) {
-		WARN_ON(error != -EEXIST);
-		XFS_STATS_INC(xs_ig_dup);
-		error = EAGAIN;
-		goto out_preload_end;
-	}
-	spin_unlock(&pag->pag_ici_lock);
-	radix_tree_preload_end();
-
-	*ipp = ip;
-	return 0;
-
-out_preload_end:
-	spin_unlock(&pag->pag_ici_lock);
-	radix_tree_preload_end();
-	if (lock_flags)
-		xfs_iunlock(ip, lock_flags);
-out_destroy:
-	__destroy_inode(VFS_I(ip));
-	xfs_inode_free(ip);
-	return error;
-}
-
-/*
- * Look up an inode by number in the given file system.
- * The inode is looked up in the cache held in each AG.
- * If the inode is found in the cache, initialise the vfs inode
- * if necessary.
- *
- * If it is not in core, read it in from the file system's device,
- * add it to the cache and initialise the vfs inode.
- *
- * The inode is locked according to the value of the lock_flags parameter.
- * This flag parameter indicates how and if the inode's IO lock and inode lock
- * should be taken.
- *
- * mp -- the mount point structure for the current file system.  It points
- *       to the inode hash table.
- * tp -- a pointer to the current transaction if there is one.  This is
- *       simply passed through to the xfs_iread() call.
- * ino -- the number of the inode desired.  This is the unique identifier
- *        within the file system for the inode being requested.
- * lock_flags -- flags indicating how to lock the inode.  See the comment
- *		 for xfs_ilock() for a list of valid values.
- */
-int
-xfs_iget(
-	xfs_mount_t	*mp,
-	xfs_trans_t	*tp,
-	xfs_ino_t	ino,
-	uint		flags,
-	uint		lock_flags,
-	xfs_inode_t	**ipp)
-{
-	xfs_inode_t	*ip;
-	int		error;
-	xfs_perag_t	*pag;
-	xfs_agino_t	agino;
-
-	/*
-	 * xfs_reclaim_inode() uses the ILOCK to ensure an inode
-	 * doesn't get freed while it's being referenced during a
-	 * radix tree traversal here.  It assumes this function
-	 * aqcuires only the ILOCK (and therefore it has no need to
-	 * involve the IOLOCK in this synchronization).
-	 */
-	ASSERT((lock_flags & (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED)) == 0);
-
-	/* reject inode numbers outside existing AGs */
-	if (!ino || XFS_INO_TO_AGNO(mp, ino) >= mp->m_sb.sb_agcount)
-		return EINVAL;
-
-	/* get the perag structure and ensure that it's inode capable */
-	pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ino));
-	agino = XFS_INO_TO_AGINO(mp, ino);
-
-again:
-	error = 0;
-	rcu_read_lock();
-	ip = radix_tree_lookup(&pag->pag_ici_root, agino);
-
-	if (ip) {
-		error = xfs_iget_cache_hit(pag, ip, ino, flags, lock_flags);
-		if (error)
-			goto out_error_or_again;
-	} else {
-		rcu_read_unlock();
-		XFS_STATS_INC(xs_ig_missed);
-
-		error = xfs_iget_cache_miss(mp, pag, tp, ino, &ip,
-							flags, lock_flags);
-		if (error)
-			goto out_error_or_again;
-	}
-	xfs_perag_put(pag);
-
-	*ipp = ip;
-
-	/*
-	 * If we have a real type for an on-disk inode, we can set ops(&unlock)
-	 * now.	 If it's a new inode being created, xfs_ialloc will handle it.
-	 */
-	if (xfs_iflags_test(ip, XFS_INEW) && ip->i_d.di_mode != 0)
-		xfs_setup_inode(ip);
-	return 0;
-
-out_error_or_again:
-	if (error == EAGAIN) {
-		delay(1);
-		goto again;
-	}
-	xfs_perag_put(pag);
-	return error;
-}
-
-/*
- * This is a wrapper routine around the xfs_ilock() routine
- * used to centralize some grungy code.  It is used in places
- * that wish to lock the inode solely for reading the extents.
- * The reason these places can't just call xfs_ilock(SHARED)
- * is that the inode lock also guards to bringing in of the
- * extents from disk for a file in b-tree format.  If the inode
- * is in b-tree format, then we need to lock the inode exclusively
- * until the extents are read in.  Locking it exclusively all
- * the time would limit our parallelism unnecessarily, though.
- * What we do instead is check to see if the extents have been
- * read in yet, and only lock the inode exclusively if they
- * have not.
- *
- * The function returns a value which should be given to the
- * corresponding xfs_iunlock_map_shared().  This value is
- * the mode in which the lock was actually taken.
- */
-uint
-xfs_ilock_map_shared(
-	xfs_inode_t	*ip)
-{
-	uint	lock_mode;
-
-	if ((ip->i_d.di_format == XFS_DINODE_FMT_BTREE) &&
-	    ((ip->i_df.if_flags & XFS_IFEXTENTS) == 0)) {
-		lock_mode = XFS_ILOCK_EXCL;
-	} else {
-		lock_mode = XFS_ILOCK_SHARED;
-	}
-
-	xfs_ilock(ip, lock_mode);
-
-	return lock_mode;
-}
-
-/*
- * This is simply the unlock routine to go with xfs_ilock_map_shared().
- * All it does is call xfs_iunlock() with the given lock_mode.
- */
-void
-xfs_iunlock_map_shared(
-	xfs_inode_t	*ip,
-	unsigned int	lock_mode)
-{
-	xfs_iunlock(ip, lock_mode);
-}
-
-/*
- * The xfs inode contains 2 locks: a multi-reader lock called the
- * i_iolock and a multi-reader lock called the i_lock.  This routine
- * allows either or both of the locks to be obtained.
- *
- * The 2 locks should always be ordered so that the IO lock is
- * obtained first in order to prevent deadlock.
- *
- * ip -- the inode being locked
- * lock_flags -- this parameter indicates the inode's locks
- *       to be locked.  It can be:
- *		XFS_IOLOCK_SHARED,
- *		XFS_IOLOCK_EXCL,
- *		XFS_ILOCK_SHARED,
- *		XFS_ILOCK_EXCL,
- *		XFS_IOLOCK_SHARED | XFS_ILOCK_SHARED,
- *		XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL,
- *		XFS_IOLOCK_EXCL | XFS_ILOCK_SHARED,
- *		XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL
- */
-void
-xfs_ilock(
-	xfs_inode_t		*ip,
-	uint			lock_flags)
-{
-	/*
-	 * You can't set both SHARED and EXCL for the same lock,
-	 * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
-	 * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
-	 */
-	ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
-	       (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
-	ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
-	       (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
-	ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
-
-	if (lock_flags & XFS_IOLOCK_EXCL)
-		mrupdate_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags));
-	else if (lock_flags & XFS_IOLOCK_SHARED)
-		mraccess_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags));
-
-	if (lock_flags & XFS_ILOCK_EXCL)
-		mrupdate_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags));
-	else if (lock_flags & XFS_ILOCK_SHARED)
-		mraccess_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags));
-
-	trace_xfs_ilock(ip, lock_flags, _RET_IP_);
-}
-
-/*
- * This is just like xfs_ilock(), except that the caller
- * is guaranteed not to sleep.  It returns 1 if it gets
- * the requested locks and 0 otherwise.  If the IO lock is
- * obtained but the inode lock cannot be, then the IO lock
- * is dropped before returning.
- *
- * ip -- the inode being locked
- * lock_flags -- this parameter indicates the inode's locks to be
- *       to be locked.  See the comment for xfs_ilock() for a list
- *	 of valid values.
- */
-int
-xfs_ilock_nowait(
-	xfs_inode_t		*ip,
-	uint			lock_flags)
-{
-	/*
-	 * You can't set both SHARED and EXCL for the same lock,
-	 * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
-	 * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
-	 */
-	ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
-	       (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
-	ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
-	       (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
-	ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
-
-	if (lock_flags & XFS_IOLOCK_EXCL) {
-		if (!mrtryupdate(&ip->i_iolock))
-			goto out;
-	} else if (lock_flags & XFS_IOLOCK_SHARED) {
-		if (!mrtryaccess(&ip->i_iolock))
-			goto out;
-	}
-	if (lock_flags & XFS_ILOCK_EXCL) {
-		if (!mrtryupdate(&ip->i_lock))
-			goto out_undo_iolock;
-	} else if (lock_flags & XFS_ILOCK_SHARED) {
-		if (!mrtryaccess(&ip->i_lock))
-			goto out_undo_iolock;
-	}
-	trace_xfs_ilock_nowait(ip, lock_flags, _RET_IP_);
-	return 1;
-
- out_undo_iolock:
-	if (lock_flags & XFS_IOLOCK_EXCL)
-		mrunlock_excl(&ip->i_iolock);
-	else if (lock_flags & XFS_IOLOCK_SHARED)
-		mrunlock_shared(&ip->i_iolock);
- out:
-	return 0;
-}
-
-/*
- * xfs_iunlock() is used to drop the inode locks acquired with
- * xfs_ilock() and xfs_ilock_nowait().  The caller must pass
- * in the flags given to xfs_ilock() or xfs_ilock_nowait() so
- * that we know which locks to drop.
- *
- * ip -- the inode being unlocked
- * lock_flags -- this parameter indicates the inode's locks to be
- *       to be unlocked.  See the comment for xfs_ilock() for a list
- *	 of valid values for this parameter.
- *
- */
-void
-xfs_iunlock(
-	xfs_inode_t		*ip,
-	uint			lock_flags)
-{
-	/*
-	 * You can't set both SHARED and EXCL for the same lock,
-	 * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
-	 * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
-	 */
-	ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
-	       (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
-	ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
-	       (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
-	ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
-	ASSERT(lock_flags != 0);
-
-	if (lock_flags & XFS_IOLOCK_EXCL)
-		mrunlock_excl(&ip->i_iolock);
-	else if (lock_flags & XFS_IOLOCK_SHARED)
-		mrunlock_shared(&ip->i_iolock);
-
-	if (lock_flags & XFS_ILOCK_EXCL)
-		mrunlock_excl(&ip->i_lock);
-	else if (lock_flags & XFS_ILOCK_SHARED)
-		mrunlock_shared(&ip->i_lock);
-
-	trace_xfs_iunlock(ip, lock_flags, _RET_IP_);
-}
-
-/*
- * give up write locks.  the i/o lock cannot be held nested
- * if it is being demoted.
- */
-void
-xfs_ilock_demote(
-	xfs_inode_t		*ip,
-	uint			lock_flags)
-{
-	ASSERT(lock_flags & (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL));
-	ASSERT((lock_flags & ~(XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)) == 0);
-
-	if (lock_flags & XFS_ILOCK_EXCL)
-		mrdemote(&ip->i_lock);
-	if (lock_flags & XFS_IOLOCK_EXCL)
-		mrdemote(&ip->i_iolock);
-
-	trace_xfs_ilock_demote(ip, lock_flags, _RET_IP_);
-}
-
-#ifdef DEBUG
-int
-xfs_isilocked(
-	xfs_inode_t		*ip,
-	uint			lock_flags)
-{
-	if (lock_flags & (XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)) {
-		if (!(lock_flags & XFS_ILOCK_SHARED))
-			return !!ip->i_lock.mr_writer;
-		return rwsem_is_locked(&ip->i_lock.mr_lock);
-	}
-
-	if (lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) {
-		if (!(lock_flags & XFS_IOLOCK_SHARED))
-			return !!ip->i_iolock.mr_writer;
-		return rwsem_is_locked(&ip->i_iolock.mr_lock);
-	}
-
-	ASSERT(0);
-	return 0;
-}
-#endif
-
-void
-__xfs_iflock(
-	struct xfs_inode	*ip)
-{
-	wait_queue_head_t *wq = bit_waitqueue(&ip->i_flags, __XFS_IFLOCK_BIT);
-	DEFINE_WAIT_BIT(wait, &ip->i_flags, __XFS_IFLOCK_BIT);
-
-	do {
-		prepare_to_wait_exclusive(wq, &wait.wait, TASK_UNINTERRUPTIBLE);
-		if (xfs_isiflocked(ip))
-			io_schedule();
-	} while (!xfs_iflock_nowait(ip));
-
-	finish_wait(wq, &wait.wait);
-}
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 1938b41..66282dc 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -45,6 +45,7 @@
 #include "xfs_filestream.h"
 #include "xfs_vnodeops.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 kmem_zone_t *xfs_ifork_zone;
 kmem_zone_t *xfs_inode_zone;
@@ -74,6 +75,256 @@ xfs_get_extsz_hint(
 	return 0;
 }
 
+/*
+ * This is a wrapper routine around the xfs_ilock() routine used to centralize
+ * some grungy code.  It is used in places that wish to lock the inode solely
+ * for reading the extents.  The reason these places can't just call
+ * xfs_ilock(SHARED) is that the inode lock also guards to bringing in of the
+ * extents from disk for a file in b-tree format.  If the inode is in b-tree
+ * format, then we need to lock the inode exclusively until the extents are read
+ * in.  Locking it exclusively all the time would limit our parallelism
+ * unnecessarily, though.  What we do instead is check to see if the extents
+ * have been read in yet, and only lock the inode exclusively if they have not.
+ *
+ * The function returns a value which should be given to the corresponding
+ * xfs_iunlock_map_shared().  This value is the mode in which the lock was
+ * actually taken.
+ */
+uint
+xfs_ilock_map_shared(
+	xfs_inode_t	*ip)
+{
+	uint	lock_mode;
+
+	if ((ip->i_d.di_format == XFS_DINODE_FMT_BTREE) &&
+	    ((ip->i_df.if_flags & XFS_IFEXTENTS) == 0)) {
+		lock_mode = XFS_ILOCK_EXCL;
+	} else {
+		lock_mode = XFS_ILOCK_SHARED;
+	}
+
+	xfs_ilock(ip, lock_mode);
+
+	return lock_mode;
+}
+
+/*
+ * This is simply the unlock routine to go with xfs_ilock_map_shared().
+ * All it does is call xfs_iunlock() with the given lock_mode.
+ */
+void
+xfs_iunlock_map_shared(
+	xfs_inode_t	*ip,
+	unsigned int	lock_mode)
+{
+	xfs_iunlock(ip, lock_mode);
+}
+
+/*
+ * The xfs inode contains 2 locks: a multi-reader lock called the
+ * i_iolock and a multi-reader lock called the i_lock.  This routine
+ * allows either or both of the locks to be obtained.
+ *
+ * The 2 locks should always be ordered so that the IO lock is
+ * obtained first in order to prevent deadlock.
+ *
+ * ip -- the inode being locked
+ * lock_flags -- this parameter indicates the inode's locks
+ *       to be locked.  It can be:
+ *		XFS_IOLOCK_SHARED,
+ *		XFS_IOLOCK_EXCL,
+ *		XFS_ILOCK_SHARED,
+ *		XFS_ILOCK_EXCL,
+ *		XFS_IOLOCK_SHARED | XFS_ILOCK_SHARED,
+ *		XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL,
+ *		XFS_IOLOCK_EXCL | XFS_ILOCK_SHARED,
+ *		XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL
+ */
+void
+xfs_ilock(
+	xfs_inode_t		*ip,
+	uint			lock_flags)
+{
+	trace_xfs_ilock(ip, lock_flags, _RET_IP_);
+
+	/*
+	 * You can't set both SHARED and EXCL for the same lock,
+	 * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
+	 * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
+	 */
+	ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
+	       (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
+	ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
+	       (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
+	ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
+
+	if (lock_flags & XFS_IOLOCK_EXCL)
+		mrupdate_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags));
+	else if (lock_flags & XFS_IOLOCK_SHARED)
+		mraccess_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags));
+
+	if (lock_flags & XFS_ILOCK_EXCL)
+		mrupdate_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags));
+	else if (lock_flags & XFS_ILOCK_SHARED)
+		mraccess_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags));
+}
+
+/*
+ * This is just like xfs_ilock(), except that the caller
+ * is guaranteed not to sleep.  It returns 1 if it gets
+ * the requested locks and 0 otherwise.  If the IO lock is
+ * obtained but the inode lock cannot be, then the IO lock
+ * is dropped before returning.
+ *
+ * ip -- the inode being locked
+ * lock_flags -- this parameter indicates the inode's locks to be
+ *       to be locked.  See the comment for xfs_ilock() for a list
+ *	 of valid values.
+ */
+int
+xfs_ilock_nowait(
+	xfs_inode_t		*ip,
+	uint			lock_flags)
+{
+	trace_xfs_ilock_nowait(ip, lock_flags, _RET_IP_);
+
+	/*
+	 * You can't set both SHARED and EXCL for the same lock,
+	 * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
+	 * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
+	 */
+	ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
+	       (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
+	ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
+	       (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
+	ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
+
+	if (lock_flags & XFS_IOLOCK_EXCL) {
+		if (!mrtryupdate(&ip->i_iolock))
+			goto out;
+	} else if (lock_flags & XFS_IOLOCK_SHARED) {
+		if (!mrtryaccess(&ip->i_iolock))
+			goto out;
+	}
+	if (lock_flags & XFS_ILOCK_EXCL) {
+		if (!mrtryupdate(&ip->i_lock))
+			goto out_undo_iolock;
+	} else if (lock_flags & XFS_ILOCK_SHARED) {
+		if (!mrtryaccess(&ip->i_lock))
+			goto out_undo_iolock;
+	}
+	return 1;
+
+ out_undo_iolock:
+	if (lock_flags & XFS_IOLOCK_EXCL)
+		mrunlock_excl(&ip->i_iolock);
+	else if (lock_flags & XFS_IOLOCK_SHARED)
+		mrunlock_shared(&ip->i_iolock);
+ out:
+	return 0;
+}
+
+/*
+ * xfs_iunlock() is used to drop the inode locks acquired with
+ * xfs_ilock() and xfs_ilock_nowait().  The caller must pass
+ * in the flags given to xfs_ilock() or xfs_ilock_nowait() so
+ * that we know which locks to drop.
+ *
+ * ip -- the inode being unlocked
+ * lock_flags -- this parameter indicates the inode's locks to be
+ *       to be unlocked.  See the comment for xfs_ilock() for a list
+ *	 of valid values for this parameter.
+ *
+ */
+void
+xfs_iunlock(
+	xfs_inode_t		*ip,
+	uint			lock_flags)
+{
+	/*
+	 * You can't set both SHARED and EXCL for the same lock,
+	 * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
+	 * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
+	 */
+	ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
+	       (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
+	ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
+	       (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
+	ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
+	ASSERT(lock_flags != 0);
+
+	if (lock_flags & XFS_IOLOCK_EXCL)
+		mrunlock_excl(&ip->i_iolock);
+	else if (lock_flags & XFS_IOLOCK_SHARED)
+		mrunlock_shared(&ip->i_iolock);
+
+	if (lock_flags & XFS_ILOCK_EXCL)
+		mrunlock_excl(&ip->i_lock);
+	else if (lock_flags & XFS_ILOCK_SHARED)
+		mrunlock_shared(&ip->i_lock);
+
+	trace_xfs_iunlock(ip, lock_flags, _RET_IP_);
+}
+
+/*
+ * give up write locks.  the i/o lock cannot be held nested
+ * if it is being demoted.
+ */
+void
+xfs_ilock_demote(
+	xfs_inode_t		*ip,
+	uint			lock_flags)
+{
+	ASSERT(lock_flags & (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL));
+	ASSERT((lock_flags & ~(XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)) == 0);
+
+	if (lock_flags & XFS_ILOCK_EXCL)
+		mrdemote(&ip->i_lock);
+	if (lock_flags & XFS_IOLOCK_EXCL)
+		mrdemote(&ip->i_iolock);
+
+	trace_xfs_ilock_demote(ip, lock_flags, _RET_IP_);
+}
+
+#ifdef DEBUG
+int
+xfs_isilocked(
+	xfs_inode_t		*ip,
+	uint			lock_flags)
+{
+	if (lock_flags & (XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)) {
+		if (!(lock_flags & XFS_ILOCK_SHARED))
+			return !!ip->i_lock.mr_writer;
+		return rwsem_is_locked(&ip->i_lock.mr_lock);
+	}
+
+	if (lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) {
+		if (!(lock_flags & XFS_IOLOCK_SHARED))
+			return !!ip->i_iolock.mr_writer;
+		return rwsem_is_locked(&ip->i_iolock.mr_lock);
+	}
+
+	ASSERT(0);
+	return 0;
+}
+#endif
+
+void
+__xfs_iflock(
+	struct xfs_inode	*ip)
+{
+	wait_queue_head_t *wq = bit_waitqueue(&ip->i_flags, __XFS_IFLOCK_BIT);
+	DEFINE_WAIT_BIT(wait, &ip->i_flags, __XFS_IFLOCK_BIT);
+
+	do {
+		prepare_to_wait_exclusive(wq, &wait.wait, TASK_UNINTERRUPTIBLE);
+		if (xfs_isiflocked(ip))
+			io_schedule();
+	} while (!xfs_iflock_nowait(ip));
+
+	finish_wait(wq, &wait.wait);
+}
+
 #ifdef DEBUG
 /*
  * Make sure that the extents in the given memory buffer
@@ -131,6 +382,65 @@ xfs_inobp_check(
 }
 #endif
 
+static void
+xfs_inode_buf_verify(
+	struct xfs_buf	*bp)
+{
+	struct xfs_mount *mp = bp->b_target->bt_mount;
+	int		i;
+	int		ni;
+
+	/*
+	 * Validate the magic number and version of every inode in the buffer
+	 */
+	ni = XFS_BB_TO_FSB(mp, bp->b_length) * mp->m_sb.sb_inopblock;
+	for (i = 0; i < ni; i++) {
+		int		di_ok;
+		xfs_dinode_t	*dip;
+
+		dip = (struct xfs_dinode *)xfs_buf_offset(bp,
+					(i << mp->m_sb.sb_inodelog));
+		di_ok = dip->di_magic == cpu_to_be16(XFS_DINODE_MAGIC) &&
+			    XFS_DINODE_GOOD_VERSION(dip->di_version);
+		if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
+						XFS_ERRTAG_ITOBP_INOTOBP,
+						XFS_RANDOM_ITOBP_INOTOBP))) {
+			xfs_buf_ioerror(bp, EFSCORRUPTED);
+			XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH,
+					     mp, dip);
+#ifdef DEBUG
+			xfs_emerg(mp,
+				"bad inode magic/vsn daddr %lld #%d (magic=%x)",
+				(unsigned long long)bp->b_bn, i,
+				be16_to_cpu(dip->di_magic));
+			ASSERT(0);
+#endif
+		}
+	}
+	xfs_inobp_check(mp, bp);
+}
+
+
+static void
+xfs_inode_buf_read_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_inode_buf_verify(bp);
+}
+
+static void
+xfs_inode_buf_write_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_inode_buf_verify(bp);
+}
+
+const struct xfs_buf_ops xfs_inode_buf_ops = {
+	.verify_read = xfs_inode_buf_read_verify,
+	.verify_write = xfs_inode_buf_write_verify,
+};
+
+
 /*
  * This routine is called to map an inode to the buffer containing the on-disk
  * version of the inode.  It returns a pointer to the buffer containing the
@@ -145,71 +455,33 @@ xfs_imap_to_bp(
 	struct xfs_mount	*mp,
 	struct xfs_trans	*tp,
 	struct xfs_imap		*imap,
-	struct xfs_dinode	**dipp,
+	struct xfs_dinode       **dipp,
 	struct xfs_buf		**bpp,
 	uint			buf_flags,
 	uint			iget_flags)
 {
 	struct xfs_buf		*bp;
 	int			error;
-	int			i;
-	int			ni;
 
 	buf_flags |= XBF_UNMAPPED;
 	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap->im_blkno,
-				   (int)imap->im_len, buf_flags, &bp);
+				   (int)imap->im_len, buf_flags, &bp,
+				   &xfs_inode_buf_ops);
 	if (error) {
-		if (error != EAGAIN) {
-			xfs_warn(mp,
-				"%s: xfs_trans_read_buf() returned error %d.",
-				__func__, error);
-		} else {
+		if (error == EAGAIN) {
 			ASSERT(buf_flags & XBF_TRYLOCK);
+			return error;
 		}
-		return error;
-	}
-
-	/*
-	 * Validate the magic number and version of every inode in the buffer
-	 * (if DEBUG kernel) or the first inode in the buffer, otherwise.
-	 */
-#ifdef DEBUG
-	ni = BBTOB(imap->im_len) >> mp->m_sb.sb_inodelog;
-#else	/* usual case */
-	ni = 1;
-#endif
 
-	for (i = 0; i < ni; i++) {
-		int		di_ok;
-		xfs_dinode_t	*dip;
+		if (error == EFSCORRUPTED &&
+		    (iget_flags & XFS_IGET_UNTRUSTED))
+			return XFS_ERROR(EINVAL);
 
-		dip = (xfs_dinode_t *)xfs_buf_offset(bp,
-					(i << mp->m_sb.sb_inodelog));
-		di_ok = dip->di_magic == cpu_to_be16(XFS_DINODE_MAGIC) &&
-			    XFS_DINODE_GOOD_VERSION(dip->di_version);
-		if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
-						XFS_ERRTAG_ITOBP_INOTOBP,
-						XFS_RANDOM_ITOBP_INOTOBP))) {
-			if (iget_flags & XFS_IGET_UNTRUSTED) {
-				xfs_trans_brelse(tp, bp);
-				return XFS_ERROR(EINVAL);
-			}
-			XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH,
-					     mp, dip);
-#ifdef DEBUG
-			xfs_emerg(mp,
-				"bad inode magic/vsn daddr %lld #%d (magic=%x)",
-				(unsigned long long)imap->im_blkno, i,
-				be16_to_cpu(dip->di_magic));
-			ASSERT(0);
-#endif
-			xfs_trans_brelse(tp, bp);
-			return XFS_ERROR(EFSCORRUPTED);
-		}
+		xfs_warn(mp, "%s: xfs_trans_read_buf() returned error %d.",
+			__func__, error);
+		return error;
 	}
 
-	xfs_inobp_check(mp, bp);
-
 	*bpp = bp;
 	*dipp = (struct xfs_dinode *)xfs_buf_offset(bp, imap->im_boffset);
 	return 0;
@@ -853,16 +1125,16 @@ xfs_iread_extents(
  * set according to the contents of the given cred structure.
  *
  * Use xfs_dialloc() to allocate the on-disk inode. If xfs_dialloc()
- * has a free inode available, call xfs_iget()
- * to obtain the in-core version of the allocated inode.  Finally,
- * fill in the inode and log its initial contents.  In this case,
- * ialloc_context would be set to NULL and call_again set to false.
+ * has a free inode available, call xfs_iget() to obtain the in-core
+ * version of the allocated inode.  Finally, fill in the inode and
+ * log its initial contents.  In this case, ialloc_context would be
+ * set to NULL.
  *
- * If xfs_dialloc() does not have an available inode,
- * it will replenish its supply by doing an allocation. Since we can
- * only do one allocation within a transaction without deadlocks, we
- * must commit the current transaction before returning the inode itself.
- * In this case, therefore, we will set call_again to true and return.
+ * If xfs_dialloc() does not have an available inode, it will replenish
+ * its supply by doing an allocation. Since we can only do one
+ * allocation within a transaction without deadlocks, we must commit
+ * the current transaction before returning the inode itself.
+ * In this case, therefore, we will set ialloc_context and return.
  * The caller should then commit the current transaction, start a new
  * transaction, and call xfs_ialloc() again to actually get the inode.
  *
@@ -1514,6 +1786,18 @@ xfs_ifree_cluster(
 
 		if (!bp)
 			return ENOMEM;
+
+		/*
+		 * This buffer may not have been correctly initialised as we
+		 * didn't read it from disk. That's not important because we are
+		 * only using to mark the buffer as stale in the log, and to
+		 * attach stale cached inodes on it. That means it will never be
+		 * dispatched for IO. If it is, we want to know about it, and we
+		 * want it to fail. We can acheive this by adding a write
+		 * verifier to the buffer.
+		 */
+		 bp->b_ops = &xfs_inode_buf_ops;
+
 		/*
 		 * Walk the inodes already attached to the buffer and mark them
 		 * stale. These will all have the flush locks held, so an
@@ -3661,3 +3945,40 @@ xfs_iext_irec_update_extoffs(
 		ifp->if_u1.if_ext_irec[i].er_extoff += ext_diff;
 	}
 }
+
+/*
+ * Test whether it is appropriate to check an inode for and free post EOF
+ * blocks. The 'force' parameter determines whether we should also consider
+ * regular files that are marked preallocated or append-only.
+ */
+bool
+xfs_can_free_eofblocks(struct xfs_inode *ip, bool force)
+{
+	/* prealloc/delalloc exists only on regular files */
+	if (!S_ISREG(ip->i_d.di_mode))
+		return false;
+
+	/*
+	 * Zero sized files with no cached pages and delalloc blocks will not
+	 * have speculative prealloc/delalloc blocks to remove.
+	 */
+	if (VFS_I(ip)->i_size == 0 &&
+	    VN_CACHED(VFS_I(ip)) == 0 &&
+	    ip->i_delayed_blks == 0)
+		return false;
+
+	/* If we haven't read in the extent list, then don't do it now. */
+	if (!(ip->i_df.if_flags & XFS_IFEXTENTS))
+		return false;
+
+	/*
+	 * Do not free real preallocated or append-only files unless the file
+	 * has delalloc blocks and we are forced to remove them.
+	 */
+	if (ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND))
+		if (!force || ip->i_delayed_blks == 0)
+			return false;
+
+	return true;
+}
+
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 94b32f9..22baf6e 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -496,11 +496,10 @@ static inline int xfs_isiflocked(struct xfs_inode *ip)
 	(((pip)->i_mount->m_flags & XFS_MOUNT_GRPID) || \
 	 ((pip)->i_d.di_mode & S_ISGID))
 
+
 /*
- * xfs_iget.c prototypes.
+ * xfs_inode.c prototypes.
  */
-int		xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
-			 uint, uint, xfs_inode_t **);
 void		xfs_ilock(xfs_inode_t *, uint);
 int		xfs_ilock_nowait(xfs_inode_t *, uint);
 void		xfs_iunlock(xfs_inode_t *, uint);
@@ -508,11 +507,6 @@ void		xfs_ilock_demote(xfs_inode_t *, uint);
 int		xfs_isilocked(xfs_inode_t *, uint);
 uint		xfs_ilock_map_shared(xfs_inode_t *);
 void		xfs_iunlock_map_shared(xfs_inode_t *, uint);
-void		xfs_inode_free(struct xfs_inode *ip);
-
-/*
- * xfs_inode.c prototypes.
- */
 int		xfs_ialloc(struct xfs_trans *, xfs_inode_t *, umode_t,
 			   xfs_nlink_t, xfs_dev_t, prid_t, int,
 			   struct xfs_buf **, xfs_inode_t **);
@@ -591,6 +585,7 @@ void		xfs_iext_irec_compact(xfs_ifork_t *);
 void		xfs_iext_irec_compact_pages(xfs_ifork_t *);
 void		xfs_iext_irec_compact_full(xfs_ifork_t *);
 void		xfs_iext_irec_update_extoffs(xfs_ifork_t *, int, int);
+bool		xfs_can_free_eofblocks(struct xfs_inode *, bool);
 
 #define xfs_ipincount(ip)	((unsigned int) atomic_read(&ip->i_pincount))
 
@@ -603,5 +598,6 @@ void		xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
 extern struct kmem_zone	*xfs_ifork_zone;
 extern struct kmem_zone	*xfs_inode_zone;
 extern struct kmem_zone	*xfs_ili_zone;
+extern const struct xfs_buf_ops xfs_inode_buf_ops;
 
 #endif	/* __XFS_INODE_H__ */
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index c1df3c6..c1c3ef8 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -42,6 +42,7 @@
 #include "xfs_inode_item.h"
 #include "xfs_export.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 #include <linux/capability.h>
 #include <linux/dcache.h>
@@ -1602,6 +1603,26 @@ xfs_file_ioctl(
 		error = xfs_errortag_clearall(mp, 1);
 		return -error;
 
+	case XFS_IOC_FREE_EOFBLOCKS: {
+		struct xfs_eofblocks eofb;
+
+		if (copy_from_user(&eofb, arg, sizeof(eofb)))
+			return -XFS_ERROR(EFAULT);
+
+		if (eofb.eof_version != XFS_EOFBLOCKS_VERSION)
+			return -XFS_ERROR(EINVAL);
+
+		if (eofb.eof_flags & ~XFS_EOF_FLAGS_VALID)
+			return -XFS_ERROR(EINVAL);
+
+		if (memchr_inv(&eofb.pad32, 0, sizeof(eofb.pad32)) ||
+		    memchr_inv(eofb.pad64, 0, sizeof(eofb.pad64)))
+			return -XFS_ERROR(EINVAL);
+
+		error = xfs_icache_free_eofblocks(mp, &eofb);
+		return -error;
+	}
+
 	default:
 		return -ENOTTY;
 	}
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 7f53766..add06b4 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -41,6 +41,7 @@
 #include "xfs_utils.h"
 #include "xfs_iomap.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 
 #define XFS_WRITEIO_ALIGN(mp,off)	(((off) >> mp->m_writeio_log) \
@@ -373,7 +374,7 @@ xfs_iomap_write_delay(
 	xfs_extlen_t	extsz;
 	int		nimaps;
 	xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS];
-	int		prealloc, flushed = 0;
+	int		prealloc;
 	int		error;
 
 	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
@@ -434,31 +435,29 @@ retry:
 	}
 
 	/*
-	 * If bmapi returned us nothing, we got either ENOSPC or EDQUOT.  For
-	 * ENOSPC, * flush all other inodes with delalloc blocks to free up
-	 * some of the excess reserved metadata space. For both cases, retry
+	 * If bmapi returned us nothing, we got either ENOSPC or EDQUOT. Retry
 	 * without EOF preallocation.
 	 */
 	if (nimaps == 0) {
 		trace_xfs_delalloc_enospc(ip, offset, count);
-		if (flushed)
-			return XFS_ERROR(error ? error : ENOSPC);
-
-		if (error == ENOSPC) {
-			xfs_iunlock(ip, XFS_ILOCK_EXCL);
-			xfs_flush_inodes(ip);
-			xfs_ilock(ip, XFS_ILOCK_EXCL);
+		if (prealloc) {
+			prealloc = 0;
+			error = 0;
+			goto retry;
 		}
-
-		flushed = 1;
-		error = 0;
-		prealloc = 0;
-		goto retry;
+		return XFS_ERROR(error ? error : ENOSPC);
 	}
 
 	if (!(imap[0].br_startblock || XFS_IS_REALTIME_INODE(ip)))
 		return xfs_alert_fsblock_zero(ip, &imap[0]);
 
+	/*
+	 * Tag the inode as speculatively preallocated so we can reclaim this
+	 * space on demand, if necessary.
+	 */
+	if (prealloc)
+		xfs_inode_set_eofblocks_tag(ip);
+
 	*ret_imap = imap[0];
 	return 0;
 }
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 4e00cf0..d82efaa 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -38,6 +38,7 @@
 #include "xfs_vnodeops.h"
 #include "xfs_inode_item.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 #include <linux/capability.h>
 #include <linux/xattr.h>
@@ -779,8 +780,8 @@ xfs_setattr_size(
 	 * care about here.
 	 */
 	if (oldsize != ip->i_d.di_size && newsize > ip->i_d.di_size) {
-		error = xfs_flush_pages(ip, ip->i_d.di_size, newsize, 0,
-					FI_NONE);
+		error = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
+						      ip->i_d.di_size, newsize);
 		if (error)
 			goto out_unlock;
 	}
@@ -854,6 +855,9 @@ xfs_setattr_size(
 		 * and do not wait the usual (long) time for writeout.
 		 */
 		xfs_iflags_set(ip, XFS_ITRUNCATED);
+
+		/* A truncate down always removes post-EOF blocks. */
+		xfs_inode_clear_eofblocks_tag(ip);
 	}
 
 	if (mask & ATTR_CTIME) {
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 01d10a6..2ea7d40 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -34,6 +34,7 @@
 #include "xfs_error.h"
 #include "xfs_btree.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 STATIC int
 xfs_internal_inum(
@@ -395,7 +396,8 @@ xfs_bulkstat(
 					if (xfs_inobt_maskn(chunkidx, nicluster)
 							& ~r.ir_free)
 						xfs_btree_reada_bufs(mp, agno,
-							agbno, nbcluster);
+							agbno, nbcluster,
+							&xfs_inode_buf_ops);
 				}
 				irbp->ir_startino = r.ir_startino;
 				irbp->ir_freecount = r.ir_freecount;
diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h
index 828662f..fe7e4df 100644
--- a/fs/xfs/xfs_linux.h
+++ b/fs/xfs/xfs_linux.h
@@ -44,6 +44,7 @@
 #include <linux/kernel.h>
 #include <linux/blkdev.h>
 #include <linux/slab.h>
+#include <linux/crc32c.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/file.h>
@@ -118,6 +119,7 @@
 #define xfs_rotorstep		xfs_params.rotorstep.val
 #define xfs_inherit_nodefrag	xfs_params.inherit_nodfrg.val
 #define xfs_fstrm_centisecs	xfs_params.fstrm_timer.val
+#define xfs_eofb_secs		xfs_params.eofb_timer.val
 
 #define current_cpu()		(raw_smp_processor_id())
 #define current_pid()		(current->pid)
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 4dad756..c6d6e13 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -34,6 +34,8 @@
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_trace.h"
+#include "xfs_fsops.h"
+#include "xfs_cksum.h"
 
 kmem_zone_t	*xfs_log_ticket_zone;
 
@@ -679,25 +681,29 @@ out:
 }
 
 /*
- * Finish the recovery of the file system.  This is separate from
- * the xfs_log_mount() call, because it depends on the code in
- * xfs_mountfs() to read in the root and real-time bitmap inodes
- * between calling xfs_log_mount() and here.
+ * Finish the recovery of the file system.  This is separate from the
+ * xfs_log_mount() call, because it depends on the code in xfs_mountfs() to read
+ * in the root and real-time bitmap inodes between calling xfs_log_mount() and
+ * here.
  *
- * mp		- ubiquitous xfs mount point structure
+ * If we finish recovery successfully, start the background log work. If we are
+ * not doing recovery, then we have a RO filesystem and we don't need to start
+ * it.
  */
 int
 xfs_log_mount_finish(xfs_mount_t *mp)
 {
-	int	error;
+	int	error = 0;
 
-	if (!(mp->m_flags & XFS_MOUNT_NORECOVERY))
+	if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) {
 		error = xlog_recover_finish(mp->m_log);
-	else {
-		error = 0;
+		if (!error)
+			xfs_log_work_queue(mp);
+	} else {
 		ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
 	}
 
+
 	return error;
 }
 
@@ -850,15 +856,49 @@ xfs_log_unmount_write(xfs_mount_t *mp)
 }	/* xfs_log_unmount_write */
 
 /*
- * Deallocate log structures for unmount/relocation.
+ * Empty the log for unmount/freeze.
+ *
+ * To do this, we first need to shut down the background log work so it is not
+ * trying to cover the log as we clean up. We then need to unpin all objects in
+ * the log so we can then flush them out. Once they have completed their IO and
+ * run the callbacks removing themselves from the AIL, we can write the unmount
+ * record.
+ */
+void
+xfs_log_quiesce(
+	struct xfs_mount	*mp)
+{
+	cancel_delayed_work_sync(&mp->m_log->l_work);
+	xfs_log_force(mp, XFS_LOG_SYNC);
+
+	/*
+	 * The superblock buffer is uncached and while xfs_ail_push_all_sync()
+	 * will push it, xfs_wait_buftarg() will not wait for it. Further,
+	 * xfs_buf_iowait() cannot be used because it was pushed with the
+	 * XBF_ASYNC flag set, so we need to use a lock/unlock pair to wait for
+	 * the IO to complete.
+	 */
+	xfs_ail_push_all_sync(mp->m_ail);
+	xfs_wait_buftarg(mp->m_ddev_targp);
+	xfs_buf_lock(mp->m_sb_bp);
+	xfs_buf_unlock(mp->m_sb_bp);
+
+	xfs_log_unmount_write(mp);
+}
+
+/*
+ * Shut down and release the AIL and Log.
  *
- * We need to stop the aild from running before we destroy
- * and deallocate the log as the aild references the log.
+ * During unmount, we need to ensure we flush all the dirty metadata objects
+ * from the AIL so that the log is empty before we write the unmount record to
+ * the log. Once this is done, we can tear down the AIL and the log.
  */
 void
-xfs_log_unmount(xfs_mount_t *mp)
+xfs_log_unmount(
+	struct xfs_mount	*mp)
 {
-	cancel_delayed_work_sync(&mp->m_sync_work);
+	xfs_log_quiesce(mp);
+
 	xfs_trans_ail_destroy(mp);
 	xlog_dealloc_log(mp->m_log);
 }
@@ -1090,8 +1130,7 @@ xlog_iodone(xfs_buf_t *bp)
 	 * with it being freed after writing the unmount record to the
 	 * log.
 	 */
-
-}	/* xlog_iodone */
+}
 
 /*
  * Return size of each in-core log record buffer.
@@ -1161,6 +1200,40 @@ done:
 }	/* xlog_get_iclog_buffer_size */
 
 
+void
+xfs_log_work_queue(
+	struct xfs_mount        *mp)
+{
+	queue_delayed_work(mp->m_log_workqueue, &mp->m_log->l_work,
+				msecs_to_jiffies(xfs_syncd_centisecs * 10));
+}
+
+/*
+ * Every sync period we need to unpin all items in the AIL and push them to
+ * disk. If there is nothing dirty, then we might need to cover the log to
+ * indicate that the filesystem is idle.
+ */
+void
+xfs_log_worker(
+	struct work_struct	*work)
+{
+	struct xlog		*log = container_of(to_delayed_work(work),
+						struct xlog, l_work);
+	struct xfs_mount	*mp = log->l_mp;
+
+	/* dgc: errors ignored - not fatal and nowhere to report them */
+	if (xfs_log_need_covered(mp))
+		xfs_fs_log_dummy(mp);
+	else
+		xfs_log_force(mp, 0);
+
+	/* start pushing all the metadata that is currently dirty */
+	xfs_ail_push_all(mp->m_ail);
+
+	/* queue us up again */
+	xfs_log_work_queue(mp);
+}
+
 /*
  * This routine initializes some of the log structure for a given mount point.
  * Its primary purpose is to fill in enough, so recovery can occur.  However,
@@ -1195,6 +1268,7 @@ xlog_alloc_log(
 	log->l_logBBsize   = num_bblks;
 	log->l_covered_state = XLOG_STATE_COVER_IDLE;
 	log->l_flags	   |= XLOG_ACTIVE_RECOVERY;
+	INIT_DELAYED_WORK(&log->l_work, xfs_log_worker);
 
 	log->l_prev_block  = -1;
 	/* log->l_tail_lsn = 0x100000000LL; cycle = 1; current block = 0 */
@@ -1417,6 +1491,84 @@ xlog_grant_push_ail(
 }
 
 /*
+ * Stamp cycle number in every block
+ */
+STATIC void
+xlog_pack_data(
+	struct xlog		*log,
+	struct xlog_in_core	*iclog,
+	int			roundoff)
+{
+	int			i, j, k;
+	int			size = iclog->ic_offset + roundoff;
+	__be32			cycle_lsn;
+	xfs_caddr_t		dp;
+
+	cycle_lsn = CYCLE_LSN_DISK(iclog->ic_header.h_lsn);
+
+	dp = iclog->ic_datap;
+	for (i = 0; i < BTOBB(size); i++) {
+		if (i >= (XLOG_HEADER_CYCLE_SIZE / BBSIZE))
+			break;
+		iclog->ic_header.h_cycle_data[i] = *(__be32 *)dp;
+		*(__be32 *)dp = cycle_lsn;
+		dp += BBSIZE;
+	}
+
+	if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
+		xlog_in_core_2_t *xhdr = iclog->ic_data;
+
+		for ( ; i < BTOBB(size); i++) {
+			j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
+			k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
+			xhdr[j].hic_xheader.xh_cycle_data[k] = *(__be32 *)dp;
+			*(__be32 *)dp = cycle_lsn;
+			dp += BBSIZE;
+		}
+
+		for (i = 1; i < log->l_iclog_heads; i++)
+			xhdr[i].hic_xheader.xh_cycle = cycle_lsn;
+	}
+}
+
+/*
+ * Calculate the checksum for a log buffer.
+ *
+ * This is a little more complicated than it should be because the various
+ * headers and the actual data are non-contiguous.
+ */
+__be32
+xlog_cksum(
+	struct xlog		*log,
+	struct xlog_rec_header	*rhead,
+	char			*dp,
+	int			size)
+{
+	__uint32_t		crc;
+
+	/* first generate the crc for the record header ... */
+	crc = xfs_start_cksum((char *)rhead,
+			      sizeof(struct xlog_rec_header),
+			      offsetof(struct xlog_rec_header, h_crc));
+
+	/* ... then for additional cycle data for v2 logs ... */
+	if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
+		union xlog_in_core2 *xhdr = (union xlog_in_core2 *)rhead;
+		int		i;
+
+		for (i = 1; i < log->l_iclog_heads; i++) {
+			crc = crc32c(crc, &xhdr[i].hic_xheader,
+				     sizeof(struct xlog_rec_ext_header));
+		}
+	}
+
+	/* ... and finally for the payload */
+	crc = crc32c(crc, dp, size);
+
+	return xfs_end_cksum(crc);
+}
+
+/*
  * The bdstrat callback function for log bufs. This gives us a central
  * place to trap bufs in case we get hit by a log I/O error and need to
  * shutdown. Actually, in practice, even when we didn't get a log error,
@@ -1476,7 +1628,6 @@ xlog_sync(
 	struct xlog		*log,
 	struct xlog_in_core	*iclog)
 {
-	xfs_caddr_t	dptr;		/* pointer to byte sized element */
 	xfs_buf_t	*bp;
 	int		i;
 	uint		count;		/* byte count of bwrite */
@@ -1485,6 +1636,7 @@ xlog_sync(
 	int		split = 0;	/* split write into two regions */
 	int		error;
 	int		v2 = xfs_sb_version_haslogv2(&log->l_mp->m_sb);
+	int		size;
 
 	XFS_STATS_INC(xs_log_writes);
 	ASSERT(atomic_read(&iclog->ic_refcnt) == 0);
@@ -1515,13 +1667,10 @@ xlog_sync(
 	xlog_pack_data(log, iclog, roundoff); 
 
 	/* real byte length */
-	if (v2) {
-		iclog->ic_header.h_len =
-			cpu_to_be32(iclog->ic_offset + roundoff);
-	} else {
-		iclog->ic_header.h_len =
-			cpu_to_be32(iclog->ic_offset);
-	}
+	size = iclog->ic_offset;
+	if (v2)
+		size += roundoff;
+	iclog->ic_header.h_len = cpu_to_be32(size);
 
 	bp = iclog->ic_bp;
 	XFS_BUF_SET_ADDR(bp, BLOCK_LSN(be64_to_cpu(iclog->ic_header.h_lsn)));
@@ -1530,12 +1679,36 @@ xlog_sync(
 
 	/* Do we need to split this write into 2 parts? */
 	if (XFS_BUF_ADDR(bp) + BTOBB(count) > log->l_logBBsize) {
+		char		*dptr;
+
 		split = count - (BBTOB(log->l_logBBsize - XFS_BUF_ADDR(bp)));
 		count = BBTOB(log->l_logBBsize - XFS_BUF_ADDR(bp));
-		iclog->ic_bwritecnt = 2;	/* split into 2 writes */
+		iclog->ic_bwritecnt = 2;
+
+		/*
+		 * Bump the cycle numbers at the start of each block in the
+		 * part of the iclog that ends up in the buffer that gets
+		 * written to the start of the log.
+		 *
+		 * Watch out for the header magic number case, though.
+		 */
+		dptr = (char *)&iclog->ic_header + count;
+		for (i = 0; i < split; i += BBSIZE) {
+			__uint32_t cycle = be32_to_cpu(*(__be32 *)dptr);
+			if (++cycle == XLOG_HEADER_MAGIC_NUM)
+				cycle++;
+			*(__be32 *)dptr = cpu_to_be32(cycle);
+
+			dptr += BBSIZE;
+		}
 	} else {
 		iclog->ic_bwritecnt = 1;
 	}
+
+	/* calculcate the checksum */
+	iclog->ic_header.h_crc = xlog_cksum(log, &iclog->ic_header,
+					    iclog->ic_datap, size);
+
 	bp->b_io_length = BTOBB(count);
 	bp->b_fspriv = iclog;
 	XFS_BUF_ZEROFLAGS(bp);
@@ -1589,19 +1762,6 @@ xlog_sync(
 		bp->b_flags |= XBF_SYNCIO;
 		if (log->l_mp->m_flags & XFS_MOUNT_BARRIER)
 			bp->b_flags |= XBF_FUA;
-		dptr = bp->b_addr;
-		/*
-		 * Bump the cycle numbers at the start of each block
-		 * since this part of the buffer is at the start of
-		 * a new cycle.  Watch out for the header magic number
-		 * case, though.
-		 */
-		for (i = 0; i < split; i += BBSIZE) {
-			be32_add_cpu((__be32 *)dptr, 1);
-			if (be32_to_cpu(*(__be32 *)dptr) == XLOG_HEADER_MAGIC_NUM)
-				be32_add_cpu((__be32 *)dptr, 1);
-			dptr += BBSIZE;
-		}
 
 		ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1);
 		ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize);
@@ -1618,7 +1778,6 @@ xlog_sync(
 	return 0;
 }	/* xlog_sync */
 
-
 /*
  * Deallocate a log structure
  */
@@ -3713,3 +3872,4 @@ xlog_iclogs_empty(
 	} while (iclog != log->l_iclog);
 	return 1;
 }
+
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index 748d312..5caee96 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -181,5 +181,9 @@ int	xfs_log_commit_cil(struct xfs_mount *mp, struct xfs_trans *tp,
 				xfs_lsn_t *commit_lsn, int flags);
 bool	xfs_log_item_in_current_chkpt(struct xfs_log_item *lip);
 
+void	xfs_log_work_queue(struct xfs_mount *mp);
+void	xfs_log_worker(struct work_struct *work);
+void	xfs_log_quiesce(struct xfs_mount *mp);
+
 #endif
 #endif	/* __XFS_LOG_H__ */
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 18a801d..dc3498b 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -139,7 +139,6 @@ static inline uint xlog_get_client_id(__be32 i)
 /*
  * Flags for log structure
  */
-#define XLOG_CHKSUM_MISMATCH	0x1	/* used only during recovery */
 #define XLOG_ACTIVE_RECOVERY	0x2	/* in the middle of recovery */
 #define	XLOG_RECOVERY_NEEDED	0x4	/* log was recovered */
 #define XLOG_IO_ERROR		0x8	/* log hit an I/O error, and being
@@ -291,7 +290,7 @@ typedef struct xlog_rec_header {
 	__be32	  h_len;	/* len in bytes; should be 64-bit aligned: 4 */
 	__be64	  h_lsn;	/* lsn of this LR			:  8 */
 	__be64	  h_tail_lsn;	/* lsn of 1st LR w/ buffers not committed: 8 */
-	__be32	  h_chksum;	/* may not be used; non-zero if used	:  4 */
+	__le32	  h_crc;	/* crc of log record                    :  4 */
 	__be32	  h_prev_block; /* block number to previous LR		:  4 */
 	__be32	  h_num_logops;	/* number of log operations in this LR	:  4 */
 	__be32	  h_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE];
@@ -495,6 +494,7 @@ struct xlog {
 	struct xfs_buf		*l_xbuf;        /* extra buffer for log
 						 * wrapping */
 	struct xfs_buftarg	*l_targ;        /* buftarg of log */
+	struct delayed_work	l_work;		/* background flush work */
 	uint			l_flags;
 	uint			l_quotaoffs_flag; /* XFS_DQ_*, for QUOTAOFFs */
 	struct list_head	*l_buf_cancel_table;
@@ -554,11 +554,9 @@ xlog_recover(
 extern int
 xlog_recover_finish(
 	struct xlog		*log);
-extern void
-xlog_pack_data(
-	struct xlog		*log,
-	struct xlog_in_core	*iclog,
-	int);
+
+extern __be32	 xlog_cksum(struct xlog *log, struct xlog_rec_header *rhead,
+			    char *dp, int size);
 
 extern kmem_zone_t *xfs_log_ticket_zone;
 struct xlog_ticket *
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index d308749..9c3651c 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -41,7 +41,9 @@
 #include "xfs_trans_priv.h"
 #include "xfs_quota.h"
 #include "xfs_utils.h"
+#include "xfs_cksum.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 STATIC int
 xlog_find_zeroed(
@@ -2143,7 +2145,7 @@ xlog_recover_buffer_pass2(
 		buf_flags |= XBF_UNMAPPED;
 
 	bp = xfs_buf_read(mp->m_ddev_targp, buf_f->blf_blkno, buf_f->blf_len,
-			  buf_flags);
+			  buf_flags, NULL);
 	if (!bp)
 		return XFS_ERROR(ENOMEM);
 	error = bp->b_error;
@@ -2236,7 +2238,8 @@ xlog_recover_inode_pass2(
 	}
 	trace_xfs_log_recover_inode_recover(log, in_f);
 
-	bp = xfs_buf_read(mp->m_ddev_targp, in_f->ilf_blkno, in_f->ilf_len, 0);
+	bp = xfs_buf_read(mp->m_ddev_targp, in_f->ilf_blkno, in_f->ilf_len, 0,
+			  NULL);
 	if (!bp) {
 		error = ENOMEM;
 		goto error;
@@ -2547,7 +2550,8 @@ xlog_recover_dquot_pass2(
 	ASSERT(dq_f->qlf_len == 1);
 
 	error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dq_f->qlf_blkno,
-				   XFS_FSB_TO_BB(mp, dq_f->qlf_len), 0, &bp);
+				   XFS_FSB_TO_BB(mp, dq_f->qlf_len), 0, &bp,
+				   NULL);
 	if (error)
 		return error;
 
@@ -3213,80 +3217,58 @@ xlog_recover_process_iunlinks(
 	mp->m_dmevmask = mp_dmevmask;
 }
 
-
-#ifdef DEBUG
-STATIC void
-xlog_pack_data_checksum(
-	struct xlog		*log,
-	struct xlog_in_core	*iclog,
-	int			size)
-{
-	int		i;
-	__be32		*up;
-	uint		chksum = 0;
-
-	up = (__be32 *)iclog->ic_datap;
-	/* divide length by 4 to get # words */
-	for (i = 0; i < (size >> 2); i++) {
-		chksum ^= be32_to_cpu(*up);
-		up++;
-	}
-	iclog->ic_header.h_chksum = cpu_to_be32(chksum);
-}
-#else
-#define xlog_pack_data_checksum(log, iclog, size)
-#endif
-
 /*
- * Stamp cycle number in every block
+ * Upack the log buffer data and crc check it. If the check fails, issue a
+ * warning if and only if the CRC in the header is non-zero. This makes the
+ * check an advisory warning, and the zero CRC check will prevent failure
+ * warnings from being emitted when upgrading the kernel from one that does not
+ * add CRCs by default.
+ *
+ * When filesystems are CRC enabled, this CRC mismatch becomes a fatal log
+ * corruption failure
  */
-void
-xlog_pack_data(
-	struct xlog		*log,
-	struct xlog_in_core	*iclog,
-	int			roundoff)
+STATIC int
+xlog_unpack_data_crc(
+	struct xlog_rec_header	*rhead,
+	xfs_caddr_t		dp,
+	struct xlog		*log)
 {
-	int			i, j, k;
-	int			size = iclog->ic_offset + roundoff;
-	__be32			cycle_lsn;
-	xfs_caddr_t		dp;
-
-	xlog_pack_data_checksum(log, iclog, size);
-
-	cycle_lsn = CYCLE_LSN_DISK(iclog->ic_header.h_lsn);
-
-	dp = iclog->ic_datap;
-	for (i = 0; i < BTOBB(size) &&
-		i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) {
-		iclog->ic_header.h_cycle_data[i] = *(__be32 *)dp;
-		*(__be32 *)dp = cycle_lsn;
-		dp += BBSIZE;
-	}
-
-	if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
-		xlog_in_core_2_t *xhdr = iclog->ic_data;
-
-		for ( ; i < BTOBB(size); i++) {
-			j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
-			k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
-			xhdr[j].hic_xheader.xh_cycle_data[k] = *(__be32 *)dp;
-			*(__be32 *)dp = cycle_lsn;
-			dp += BBSIZE;
+	__be32			crc;
+
+	crc = xlog_cksum(log, rhead, dp, be32_to_cpu(rhead->h_len));
+	if (crc != rhead->h_crc) {
+		if (rhead->h_crc || xfs_sb_version_hascrc(&log->l_mp->m_sb)) {
+			xfs_alert(log->l_mp,
+		"log record CRC mismatch: found 0x%x, expected 0x%x.\n",
+					be32_to_cpu(rhead->h_crc),
+					be32_to_cpu(crc));
+			xfs_hex_dump(dp, 32);
 		}
 
-		for (i = 1; i < log->l_iclog_heads; i++) {
-			xhdr[i].hic_xheader.xh_cycle = cycle_lsn;
-		}
+		/*
+		 * If we've detected a log record corruption, then we can't
+		 * recover past this point. Abort recovery if we are enforcing
+		 * CRC protection by punting an error back up the stack.
+		 */
+		if (xfs_sb_version_hascrc(&log->l_mp->m_sb))
+			return EFSCORRUPTED;
 	}
+
+	return 0;
 }
 
-STATIC void
+STATIC int
 xlog_unpack_data(
 	struct xlog_rec_header	*rhead,
 	xfs_caddr_t		dp,
 	struct xlog		*log)
 {
 	int			i, j, k;
+	int			error;
+
+	error = xlog_unpack_data_crc(rhead, dp, log);
+	if (error)
+		return error;
 
 	for (i = 0; i < BTOBB(be32_to_cpu(rhead->h_len)) &&
 		  i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) {
@@ -3303,6 +3285,8 @@ xlog_unpack_data(
 			dp += BBSIZE;
 		}
 	}
+
+	return 0;
 }
 
 STATIC int
@@ -3434,9 +3418,13 @@ xlog_do_recovery_pass(
 			if (error)
 				goto bread_err2;
 
-			xlog_unpack_data(rhead, offset, log);
-			if ((error = xlog_recover_process_data(log,
-						rhash, rhead, offset, pass)))
+			error = xlog_unpack_data(rhead, offset, log);
+			if (error)
+				goto bread_err2;
+
+			error = xlog_recover_process_data(log,
+						rhash, rhead, offset, pass);
+			if (error)
 				goto bread_err2;
 			blk_no += bblks + hblks;
 		}
@@ -3546,9 +3534,14 @@ xlog_do_recovery_pass(
 				if (error)
 					goto bread_err2;
 			}
-			xlog_unpack_data(rhead, offset, log);
-			if ((error = xlog_recover_process_data(log, rhash,
-							rhead, offset, pass)))
+
+			error = xlog_unpack_data(rhead, offset, log);
+			if (error)
+				goto bread_err2;
+
+			error = xlog_recover_process_data(log, rhash,
+							rhead, offset, pass);
+			if (error)
 				goto bread_err2;
 			blk_no += bblks;
 		}
@@ -3573,9 +3566,13 @@ xlog_do_recovery_pass(
 			if (error)
 				goto bread_err2;
 
-			xlog_unpack_data(rhead, offset, log);
-			if ((error = xlog_recover_process_data(log, rhash,
-							rhead, offset, pass)))
+			error = xlog_unpack_data(rhead, offset, log);
+			if (error)
+				goto bread_err2;
+
+			error = xlog_recover_process_data(log, rhash,
+							rhead, offset, pass);
+			if (error)
 				goto bread_err2;
 			blk_no += bblks + hblks;
 		}
@@ -3689,13 +3686,14 @@ xlog_do_recover(
 
 	/*
 	 * Now that we've finished replaying all buffer and inode
-	 * updates, re-read in the superblock.
+	 * updates, re-read in the superblock and reverify it.
 	 */
 	bp = xfs_getsb(log->l_mp, 0);
 	XFS_BUF_UNDONE(bp);
 	ASSERT(!(XFS_BUF_ISWRITE(bp)));
 	XFS_BUF_READ(bp);
 	XFS_BUF_UNASYNC(bp);
+	bp->b_ops = &xfs_sb_buf_ops;
 	xfsbdstrat(log->l_mp, bp);
 	error = xfs_buf_iowait(bp);
 	if (error) {
@@ -3707,7 +3705,7 @@ xlog_do_recover(
 
 	/* Convert superblock from on-disk format */
 	sbp = &log->l_mp->m_sb;
-	xfs_sb_from_disk(log->l_mp, XFS_BUF_TO_SBP(bp));
+	xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp));
 	ASSERT(sbp->sb_magicnum == XFS_SB_MAGIC);
 	ASSERT(xfs_sb_good_version(sbp));
 	xfs_buf_relse(bp);
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index b2bd3a0..da50846 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -42,6 +42,7 @@
 #include "xfs_fsops.h"
 #include "xfs_utils.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 
 #ifdef HAVE_PERCPU_SB
@@ -303,9 +304,8 @@ STATIC int
 xfs_mount_validate_sb(
 	xfs_mount_t	*mp,
 	xfs_sb_t	*sbp,
-	int		flags)
+	bool		check_inprogress)
 {
-	int		loud = !(flags & XFS_MFSI_QUIET);
 
 	/*
 	 * If the log device and data device have the
@@ -315,21 +315,18 @@ xfs_mount_validate_sb(
 	 * a volume filesystem in a non-volume manner.
 	 */
 	if (sbp->sb_magicnum != XFS_SB_MAGIC) {
-		if (loud)
-			xfs_warn(mp, "bad magic number");
+		xfs_warn(mp, "bad magic number");
 		return XFS_ERROR(EWRONGFS);
 	}
 
 	if (!xfs_sb_good_version(sbp)) {
-		if (loud)
-			xfs_warn(mp, "bad version");
+		xfs_warn(mp, "bad version");
 		return XFS_ERROR(EWRONGFS);
 	}
 
 	if (unlikely(
 	    sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
-		if (loud)
-			xfs_warn(mp,
+		xfs_warn(mp,
 		"filesystem is marked as having an external log; "
 		"specify logdev on the mount command line.");
 		return XFS_ERROR(EINVAL);
@@ -337,8 +334,7 @@ xfs_mount_validate_sb(
 
 	if (unlikely(
 	    sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) {
-		if (loud)
-			xfs_warn(mp,
+		xfs_warn(mp,
 		"filesystem is marked as having an internal log; "
 		"do not specify logdev on the mount command line.");
 		return XFS_ERROR(EINVAL);
@@ -372,8 +368,7 @@ xfs_mount_validate_sb(
 	    sbp->sb_dblocks == 0					||
 	    sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp)			||
 	    sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp))) {
-		if (loud)
-			XFS_CORRUPTION_ERROR("SB sanity check failed",
+		XFS_CORRUPTION_ERROR("SB sanity check failed",
 				XFS_ERRLEVEL_LOW, mp, sbp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
@@ -382,12 +377,10 @@ xfs_mount_validate_sb(
 	 * Until this is fixed only page-sized or smaller data blocks work.
 	 */
 	if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
-		if (loud) {
-			xfs_warn(mp,
+		xfs_warn(mp,
 		"File system with blocksize %d bytes. "
 		"Only pagesize (%ld) or less will currently work.",
 				sbp->sb_blocksize, PAGE_SIZE);
-		}
 		return XFS_ERROR(ENOSYS);
 	}
 
@@ -401,23 +394,20 @@ xfs_mount_validate_sb(
 	case 2048:
 		break;
 	default:
-		if (loud)
-			xfs_warn(mp, "inode size of %d bytes not supported",
+		xfs_warn(mp, "inode size of %d bytes not supported",
 				sbp->sb_inodesize);
 		return XFS_ERROR(ENOSYS);
 	}
 
 	if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) ||
 	    xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) {
-		if (loud)
-			xfs_warn(mp,
+		xfs_warn(mp,
 		"file system too large to be mounted on this system.");
 		return XFS_ERROR(EFBIG);
 	}
 
-	if (unlikely(sbp->sb_inprogress)) {
-		if (loud)
-			xfs_warn(mp, "file system busy");
+	if (check_inprogress && sbp->sb_inprogress) {
+		xfs_warn(mp, "Offline file system operation in progress!");
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -425,9 +415,7 @@ xfs_mount_validate_sb(
 	 * Version 1 directory format has never worked on Linux.
 	 */
 	if (unlikely(!xfs_sb_version_hasdirv2(sbp))) {
-		if (loud)
-			xfs_warn(mp,
-				"file system using version 1 directory format");
+		xfs_warn(mp, "file system using version 1 directory format");
 		return XFS_ERROR(ENOSYS);
 	}
 
@@ -520,11 +508,9 @@ out_unwind:
 
 void
 xfs_sb_from_disk(
-	struct xfs_mount	*mp,
+	struct xfs_sb	*to,
 	xfs_dsb_t	*from)
 {
-	struct xfs_sb *to = &mp->m_sb;
-
 	to->sb_magicnum = be32_to_cpu(from->sb_magicnum);
 	to->sb_blocksize = be32_to_cpu(from->sb_blocksize);
 	to->sb_dblocks = be64_to_cpu(from->sb_dblocks);
@@ -626,6 +612,72 @@ xfs_sb_to_disk(
 	}
 }
 
+static void
+xfs_sb_verify(
+	struct xfs_buf	*bp)
+{
+	struct xfs_mount *mp = bp->b_target->bt_mount;
+	struct xfs_sb	sb;
+	int		error;
+
+	xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp));
+
+	/*
+	 * Only check the in progress field for the primary superblock as
+	 * mkfs.xfs doesn't clear it from secondary superblocks.
+	 */
+	error = xfs_mount_validate_sb(mp, &sb, bp->b_bn == XFS_SB_DADDR);
+	if (error)
+		xfs_buf_ioerror(bp, error);
+}
+
+static void
+xfs_sb_read_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_sb_verify(bp);
+}
+
+/*
+ * We may be probed for a filesystem match, so we may not want to emit
+ * messages when the superblock buffer is not actually an XFS superblock.
+ * If we find an XFS superblock, the run a normal, noisy mount because we are
+ * really going to mount it and want to know about errors.
+ */
+static void
+xfs_sb_quiet_read_verify(
+	struct xfs_buf	*bp)
+{
+	struct xfs_sb	sb;
+
+	xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp));
+
+	if (sb.sb_magicnum == XFS_SB_MAGIC) {
+		/* XFS filesystem, verify noisily! */
+		xfs_sb_read_verify(bp);
+		return;
+	}
+	/* quietly fail */
+	xfs_buf_ioerror(bp, EFSCORRUPTED);
+}
+
+static void
+xfs_sb_write_verify(
+	struct xfs_buf	*bp)
+{
+	xfs_sb_verify(bp);
+}
+
+const struct xfs_buf_ops xfs_sb_buf_ops = {
+	.verify_read = xfs_sb_read_verify,
+	.verify_write = xfs_sb_write_verify,
+};
+
+static const struct xfs_buf_ops xfs_sb_quiet_buf_ops = {
+	.verify_read = xfs_sb_quiet_read_verify,
+	.verify_write = xfs_sb_write_verify,
+};
+
 /*
  * xfs_readsb
  *
@@ -651,26 +703,27 @@ xfs_readsb(xfs_mount_t *mp, int flags)
 
 reread:
 	bp = xfs_buf_read_uncached(mp->m_ddev_targp, XFS_SB_DADDR,
-					BTOBB(sector_size), 0);
+				   BTOBB(sector_size), 0,
+				   loud ? &xfs_sb_buf_ops
+				        : &xfs_sb_quiet_buf_ops);
 	if (!bp) {
 		if (loud)
 			xfs_warn(mp, "SB buffer read failed");
 		return EIO;
 	}
-
-	/*
-	 * Initialize the mount structure from the superblock.
-	 * But first do some basic consistency checking.
-	 */
-	xfs_sb_from_disk(mp, XFS_BUF_TO_SBP(bp));
-	error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
-	if (error) {
+	if (bp->b_error) {
+		error = bp->b_error;
 		if (loud)
 			xfs_warn(mp, "SB validate failed");
 		goto release_buf;
 	}
 
 	/*
+	 * Initialize the mount structure from the superblock.
+	 */
+	xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp));
+
+	/*
 	 * We must be able to do sector-sized and sector-aligned IO.
 	 */
 	if (sector_size > mp->m_sb.sb_sectsize) {
@@ -1001,7 +1054,7 @@ xfs_check_sizes(xfs_mount_t *mp)
 	}
 	bp = xfs_buf_read_uncached(mp->m_ddev_targp,
 					d - XFS_FSS_TO_BB(mp, 1),
-					XFS_FSS_TO_BB(mp, 1), 0);
+					XFS_FSS_TO_BB(mp, 1), 0, NULL);
 	if (!bp) {
 		xfs_warn(mp, "last sector read failed");
 		return EIO;
@@ -1016,7 +1069,7 @@ xfs_check_sizes(xfs_mount_t *mp)
 		}
 		bp = xfs_buf_read_uncached(mp->m_logdev_targp,
 					d - XFS_FSB_TO_BB(mp, 1),
-					XFS_FSB_TO_BB(mp, 1), 0);
+					XFS_FSB_TO_BB(mp, 1), 0, NULL);
 		if (!bp) {
 			xfs_warn(mp, "log device read failed");
 			return EIO;
@@ -1427,6 +1480,8 @@ xfs_unmountfs(
 	__uint64_t		resblks;
 	int			error;
 
+	cancel_delayed_work_sync(&mp->m_eofblocks_work);
+
 	xfs_qm_unmount_quotas(mp);
 	xfs_rtunmount_inodes(mp);
 	IRELE(mp->m_rootip);
@@ -1450,21 +1505,16 @@ xfs_unmountfs(
 
 	/*
 	 * And reclaim all inodes.  At this point there should be no dirty
-	 * inode, and none should be pinned or locked, but use synchronous
-	 * reclaim just to be sure.
+	 * inodes and none should be pinned or locked, but use synchronous
+	 * reclaim just to be sure. We can stop background inode reclaim
+	 * here as well if it is still running.
 	 */
+	cancel_delayed_work_sync(&mp->m_reclaim_work);
 	xfs_reclaim_inodes(mp, SYNC_WAIT);
 
 	xfs_qm_unmount(mp);
 
 	/*
-	 * Flush out the log synchronously so that we know for sure
-	 * that nothing is pinned.  This is important because bflush()
-	 * will skip pinned buffers.
-	 */
-	xfs_log_force(mp, XFS_LOG_SYNC);
-
-	/*
 	 * Unreserve any blocks we have so that when we unmount we don't account
 	 * the reserved free space as used. This is really only necessary for
 	 * lazy superblock counting because it trusts the incore superblock
@@ -1489,23 +1539,6 @@ xfs_unmountfs(
 		xfs_warn(mp, "Unable to update superblock counters. "
 				"Freespace may not be correct on next mount.");
 
-	/*
-	 * At this point we might have modified the superblock again and thus
-	 * added an item to the AIL, thus flush it again.
-	 */
-	xfs_ail_push_all_sync(mp->m_ail);
-	xfs_wait_buftarg(mp->m_ddev_targp);
-
-	/*
-	 * The superblock buffer is uncached and xfsaild_push() will lock and
-	 * set the XBF_ASYNC flag on the buffer. We cannot do xfs_buf_iowait()
-	 * here but a lock on the superblock buffer will block until iodone()
-	 * has completed.
-	 */
-	xfs_buf_lock(mp->m_sb_bp);
-	xfs_buf_unlock(mp->m_sb_bp);
-
-	xfs_log_unmount_write(mp);
 	xfs_log_unmount(mp);
 	xfs_uuid_unmount(mp);
 
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index deee09e..bab8314 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -51,8 +51,6 @@ typedef struct xfs_trans_reservations {
 
 #else /* __KERNEL__ */
 
-#include "xfs_sync.h"
-
 struct xlog;
 struct xfs_inode;
 struct xfs_mru_cache;
@@ -197,9 +195,9 @@ typedef struct xfs_mount {
 	struct mutex		m_icsb_mutex;	/* balancer sync lock */
 #endif
 	struct xfs_mru_cache	*m_filestream;  /* per-mount filestream data */
-	struct delayed_work	m_sync_work;	/* background sync work */
 	struct delayed_work	m_reclaim_work;	/* background inode reclaim */
-	struct work_struct	m_flush_work;	/* background inode flush */
+	struct delayed_work	m_eofblocks_work; /* background eof blocks
+						     trimming */
 	__int64_t		m_update_flags;	/* sb flags we need to update
 						   on the next remount,rw */
 	struct shrinker		m_inode_shrink;	/* inode reclaim shrinker */
@@ -209,6 +207,9 @@ typedef struct xfs_mount {
 	struct workqueue_struct	*m_data_workqueue;
 	struct workqueue_struct	*m_unwritten_workqueue;
 	struct workqueue_struct	*m_cil_workqueue;
+	struct workqueue_struct	*m_reclaim_workqueue;
+	struct workqueue_struct	*m_log_workqueue;
+	struct workqueue_struct *m_eofblocks_workqueue;
 } xfs_mount_t;
 
 /*
@@ -387,7 +388,9 @@ extern void	xfs_set_low_space_thresholds(struct xfs_mount *);
 extern void	xfs_mod_sb(struct xfs_trans *, __int64_t);
 extern int	xfs_initialize_perag(struct xfs_mount *, xfs_agnumber_t,
 					xfs_agnumber_t *);
-extern void	xfs_sb_from_disk(struct xfs_mount *, struct xfs_dsb *);
+extern void	xfs_sb_from_disk(struct xfs_sb *, struct xfs_dsb *);
 extern void	xfs_sb_to_disk(struct xfs_dsb *, struct xfs_sb *, __int64_t);
 
+extern const struct xfs_buf_ops xfs_sb_buf_ops;
+
 #endif	/* __XFS_MOUNT_H__ */
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 2e86fa0..e6a0af0 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -40,6 +40,7 @@
 #include "xfs_utils.h"
 #include "xfs_qm.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 /*
  * The global quota manager. There is only one of these for the entire
@@ -891,7 +892,8 @@ xfs_qm_dqiter_bufs(
 	while (blkcnt--) {
 		error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
 			      XFS_FSB_TO_DADDR(mp, bno),
-			      mp->m_quotainfo->qi_dqchunklen, 0, &bp);
+			      mp->m_quotainfo->qi_dqchunklen, 0, &bp,
+			      &xfs_dquot_buf_ops);
 		if (error)
 			break;
 
@@ -978,7 +980,8 @@ xfs_qm_dqiterate(
 				while (rablkcnt--) {
 					xfs_buf_readahead(mp->m_ddev_targp,
 					       XFS_FSB_TO_DADDR(mp, rablkno),
-					       mp->m_quotainfo->qi_dqchunklen);
+					       mp->m_quotainfo->qi_dqchunklen,
+					       NULL);
 					rablkno++;
 				}
 			}
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 858a3b1..5f53e75 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -40,6 +40,7 @@
 #include "xfs_utils.h"
 #include "xfs_qm.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 STATIC int	xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint);
 STATIC int	xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
@@ -845,7 +846,8 @@ STATIC int
 xfs_dqrele_inode(
 	struct xfs_inode	*ip,
 	struct xfs_perag	*pag,
-	int			flags)
+	int			flags,
+	void			*args)
 {
 	/* skip quota inodes */
 	if (ip == ip->i_mount->m_quotainfo->qi_uquotaip ||
@@ -881,5 +883,5 @@ xfs_qm_dqrele_all_inodes(
 	uint		 flags)
 {
 	ASSERT(mp->m_quotainfo);
-	xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags);
+	xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags, NULL);
 }
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index ca28a4b..98dc670 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -38,6 +38,7 @@
 #include "xfs_utils.h"
 #include "xfs_trace.h"
 #include "xfs_buf.h"
+#include "xfs_icache.h"
 
 
 /*
@@ -869,7 +870,7 @@ xfs_rtbuf_get(
 	ASSERT(map.br_startblock != NULLFSBLOCK);
 	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
 				   XFS_FSB_TO_DADDR(mp, map.br_startblock),
-				   mp->m_bsize, 0, &bp);
+				   mp->m_bsize, 0, &bp, NULL);
 	if (error)
 		return error;
 	ASSERT(!xfs_buf_geterror(bp));
@@ -1872,9 +1873,14 @@ xfs_growfs_rt(
 	 */
 	bp = xfs_buf_read_uncached(mp->m_rtdev_targp,
 				XFS_FSB_TO_BB(mp, nrblocks - 1),
-				XFS_FSB_TO_BB(mp, 1), 0);
+				XFS_FSB_TO_BB(mp, 1), 0, NULL);
 	if (!bp)
 		return EIO;
+	if (bp->b_error) {
+		error = bp->b_error;
+		xfs_buf_relse(bp);
+		return error;
+	}
 	xfs_buf_relse(bp);
 
 	/*
@@ -2219,9 +2225,11 @@ xfs_rtmount_init(
 	}
 	bp = xfs_buf_read_uncached(mp->m_rtdev_targp,
 					d - XFS_FSB_TO_BB(mp, 1),
-					XFS_FSB_TO_BB(mp, 1), 0);
-	if (!bp) {
+					XFS_FSB_TO_BB(mp, 1), 0, NULL);
+	if (!bp || bp->b_error) {
 		xfs_warn(mp, "realtime device size check failed");
+		if (bp)
+			xfs_buf_relse(bp);
 		return EIO;
 	}
 	xfs_buf_relse(bp);
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index f429d9d..a05b451 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -81,6 +81,7 @@ struct xfs_mount;
 #define XFS_SB_VERSION2_ATTR2BIT	0x00000008	/* Inline attr rework */
 #define XFS_SB_VERSION2_PARENTBIT	0x00000010	/* parent pointers */
 #define XFS_SB_VERSION2_PROJID32BIT	0x00000080	/* 32 bit project id */
+#define XFS_SB_VERSION2_CRCBIT		0x00000100	/* metadata CRCs */
 
 #define	XFS_SB_VERSION2_OKREALFBITS	\
 	(XFS_SB_VERSION2_LAZYSBCOUNTBIT	| \
@@ -503,6 +504,12 @@ static inline int xfs_sb_version_hasprojid32bit(xfs_sb_t *sbp)
 		(sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT);
 }
 
+static inline int xfs_sb_version_hascrc(xfs_sb_t *sbp)
+{
+	return (xfs_sb_version_hasmorebits(sbp) &&
+		(sbp->sb_features2 & XFS_SB_VERSION2_CRCBIT));
+}
+
 /*
  * end of superblock version macros
  */
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 26a09bd..ab8839b 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -49,7 +49,7 @@
 #include "xfs_extfree_item.h"
 #include "xfs_mru_cache.h"
 #include "xfs_inode_item.h"
-#include "xfs_sync.h"
+#include "xfs_icache.h"
 #include "xfs_trace.h"
 
 #include <linux/namei.h>
@@ -863,8 +863,30 @@ xfs_init_mount_workqueues(
 			WQ_MEM_RECLAIM, 0, mp->m_fsname);
 	if (!mp->m_cil_workqueue)
 		goto out_destroy_unwritten;
+
+	mp->m_reclaim_workqueue = alloc_workqueue("xfs-reclaim/%s",
+			WQ_NON_REENTRANT, 0, mp->m_fsname);
+	if (!mp->m_reclaim_workqueue)
+		goto out_destroy_cil;
+
+	mp->m_log_workqueue = alloc_workqueue("xfs-log/%s",
+			WQ_NON_REENTRANT, 0, mp->m_fsname);
+	if (!mp->m_log_workqueue)
+		goto out_destroy_reclaim;
+
+	mp->m_eofblocks_workqueue = alloc_workqueue("xfs-eofblocks/%s",
+			WQ_NON_REENTRANT, 0, mp->m_fsname);
+	if (!mp->m_eofblocks_workqueue)
+		goto out_destroy_log;
+
 	return 0;
 
+out_destroy_log:
+	destroy_workqueue(mp->m_log_workqueue);
+out_destroy_reclaim:
+	destroy_workqueue(mp->m_reclaim_workqueue);
+out_destroy_cil:
+	destroy_workqueue(mp->m_cil_workqueue);
 out_destroy_unwritten:
 	destroy_workqueue(mp->m_unwritten_workqueue);
 out_destroy_data_iodone_queue:
@@ -877,11 +899,32 @@ STATIC void
 xfs_destroy_mount_workqueues(
 	struct xfs_mount	*mp)
 {
+	destroy_workqueue(mp->m_eofblocks_workqueue);
+	destroy_workqueue(mp->m_log_workqueue);
+	destroy_workqueue(mp->m_reclaim_workqueue);
 	destroy_workqueue(mp->m_cil_workqueue);
 	destroy_workqueue(mp->m_data_workqueue);
 	destroy_workqueue(mp->m_unwritten_workqueue);
 }
 
+/*
+ * Flush all dirty data to disk. Must not be called while holding an XFS_ILOCK
+ * or a page lock. We use sync_inodes_sb() here to ensure we block while waiting
+ * for IO to complete so that we effectively throttle multiple callers to the
+ * rate at which IO is completing.
+ */
+void
+xfs_flush_inodes(
+	struct xfs_mount	*mp)
+{
+	struct super_block	*sb = mp->m_super;
+
+	if (down_read_trylock(&sb->s_umount)) {
+		sync_inodes_sb(sb);
+		up_read(&sb->s_umount);
+	}
+}
+
 /* Catch misguided souls that try to use this interface on XFS */
 STATIC struct inode *
 xfs_fs_alloc_inode(
@@ -1006,9 +1049,8 @@ xfs_fs_put_super(
 	struct xfs_mount	*mp = XFS_M(sb);
 
 	xfs_filestream_unmount(mp);
-	cancel_delayed_work_sync(&mp->m_sync_work);
 	xfs_unmountfs(mp);
-	xfs_syncd_stop(mp);
+
 	xfs_freesb(mp);
 	xfs_icsb_destroy_counters(mp);
 	xfs_destroy_mount_workqueues(mp);
@@ -1023,7 +1065,6 @@ xfs_fs_sync_fs(
 	int			wait)
 {
 	struct xfs_mount	*mp = XFS_M(sb);
-	int			error;
 
 	/*
 	 * Doing anything during the async pass would be counterproductive.
@@ -1031,17 +1072,14 @@ xfs_fs_sync_fs(
 	if (!wait)
 		return 0;
 
-	error = xfs_quiesce_data(mp);
-	if (error)
-		return -error;
-
+	xfs_log_force(mp, XFS_LOG_SYNC);
 	if (laptop_mode) {
 		/*
 		 * The disk must be active because we're syncing.
-		 * We schedule xfssyncd now (now that the disk is
+		 * We schedule log work now (now that the disk is
 		 * active) instead of later (when it might not be).
 		 */
-		flush_delayed_work(&mp->m_sync_work);
+		flush_delayed_work(&mp->m_log->l_work);
 	}
 
 	return 0;
@@ -1118,6 +1156,48 @@ xfs_restore_resvblks(struct xfs_mount *mp)
 	xfs_reserve_blocks(mp, &resblks, NULL);
 }
 
+/*
+ * Trigger writeback of all the dirty metadata in the file system.
+ *
+ * This ensures that the metadata is written to their location on disk rather
+ * than just existing in transactions in the log. This means after a quiesce
+ * there is no log replay required to write the inodes to disk - this is the
+ * primary difference between a sync and a quiesce.
+ *
+ * Note: xfs_log_quiesce() stops background log work - the callers must ensure
+ * it is started again when appropriate.
+ */
+void
+xfs_quiesce_attr(
+	struct xfs_mount	*mp)
+{
+	int	error = 0;
+
+	/* wait for all modifications to complete */
+	while (atomic_read(&mp->m_active_trans) > 0)
+		delay(100);
+
+	/* force the log to unpin objects from the now complete transactions */
+	xfs_log_force(mp, XFS_LOG_SYNC);
+
+	/* reclaim inodes to do any IO before the freeze completes */
+	xfs_reclaim_inodes(mp, 0);
+	xfs_reclaim_inodes(mp, SYNC_WAIT);
+
+	/* Push the superblock and write an unmount record */
+	error = xfs_log_sbcount(mp);
+	if (error)
+		xfs_warn(mp, "xfs_attr_quiesce: failed to log sb changes. "
+				"Frozen image may not be consistent.");
+	/*
+	 * Just warn here till VFS can correctly support
+	 * read-only remount without racing.
+	 */
+	WARN_ON(atomic_read(&mp->m_active_trans) != 0);
+
+	xfs_log_quiesce(mp);
+}
+
 STATIC int
 xfs_fs_remount(
 	struct super_block	*sb,
@@ -1198,20 +1278,18 @@ xfs_fs_remount(
 		 * value if it is non-zero, otherwise go with the default.
 		 */
 		xfs_restore_resvblks(mp);
+		xfs_log_work_queue(mp);
 	}
 
 	/* rw -> ro */
 	if (!(mp->m_flags & XFS_MOUNT_RDONLY) && (*flags & MS_RDONLY)) {
 		/*
-		 * After we have synced the data but before we sync the
-		 * metadata, we need to free up the reserve block pool so that
-		 * the used block count in the superblock on disk is correct at
-		 * the end of the remount. Stash the current reserve pool size
-		 * so that if we get remounted rw, we can return it to the same
-		 * size.
+		 * Before we sync the metadata, we need to free up the reserve
+		 * block pool so that the used block count in the superblock on
+		 * disk is correct at the end of the remount. Stash the current
+		 * reserve pool size so that if we get remounted rw, we can
+		 * return it to the same size.
 		 */
-
-		xfs_quiesce_data(mp);
 		xfs_save_resvblks(mp);
 		xfs_quiesce_attr(mp);
 		mp->m_flags |= XFS_MOUNT_RDONLY;
@@ -1243,6 +1321,7 @@ xfs_fs_unfreeze(
 	struct xfs_mount	*mp = XFS_M(sb);
 
 	xfs_restore_resvblks(mp);
+	xfs_log_work_queue(mp);
 	return 0;
 }
 
@@ -1321,6 +1400,8 @@ xfs_fs_fill_super(
 	spin_lock_init(&mp->m_sb_lock);
 	mutex_init(&mp->m_growlock);
 	atomic_set(&mp->m_active_trans, 0);
+	INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);
+	INIT_DELAYED_WORK(&mp->m_eofblocks_work, xfs_eofblocks_worker);
 
 	mp->m_super = sb;
 	sb->s_fs_info = mp;
@@ -1371,10 +1452,6 @@ xfs_fs_fill_super(
 	/*
 	 * we must configure the block size in the superblock before we run the
 	 * full mount process as the mount process can lookup and cache inodes.
-	 * For the same reason we must also initialise the syncd and register
-	 * the inode cache shrinker so that inodes can be reclaimed during
-	 * operations like a quotacheck that iterate all inodes in the
-	 * filesystem.
 	 */
 	sb->s_magic = XFS_SB_MAGIC;
 	sb->s_blocksize = mp->m_sb.sb_blocksize;
@@ -1384,13 +1461,9 @@ xfs_fs_fill_super(
 	sb->s_time_gran = 1;
 	set_posix_acl_flag(sb);
 
-	error = xfs_syncd_init(mp);
-	if (error)
-		goto out_filestream_unmount;
-
 	error = xfs_mountfs(mp);
 	if (error)
-		goto out_syncd_stop;
+		goto out_filestream_unmount;
 
 	root = igrab(VFS_I(mp->m_rootip));
 	if (!root) {
@@ -1408,8 +1481,7 @@ xfs_fs_fill_super(
 	}
 
 	return 0;
- out_syncd_stop:
-	xfs_syncd_stop(mp);
+
  out_filestream_unmount:
 	xfs_filestream_unmount(mp);
  out_free_sb:
@@ -1429,7 +1501,6 @@ out_destroy_workqueues:
  out_unmount:
 	xfs_filestream_unmount(mp);
 	xfs_unmountfs(mp);
-	xfs_syncd_stop(mp);
 	goto out_free_sb;
 }
 
@@ -1625,16 +1696,6 @@ STATIC int __init
 xfs_init_workqueues(void)
 {
 	/*
-	 * We never want to the same work item to run twice, reclaiming inodes
-	 * or idling the log is not going to get any faster by multiple CPUs
-	 * competing for ressources.  Use the default large max_active value
-	 * so that even lots of filesystems can perform these task in parallel.
-	 */
-	xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_NON_REENTRANT, 0);
-	if (!xfs_syncd_wq)
-		return -ENOMEM;
-
-	/*
 	 * The allocation workqueue can be used in memory reclaim situations
 	 * (writepage path), and parallelism is only limited by the number of
 	 * AGs in all the filesystems mounted. Hence use the default large
@@ -1642,20 +1703,15 @@ xfs_init_workqueues(void)
 	 */
 	xfs_alloc_wq = alloc_workqueue("xfsalloc", WQ_MEM_RECLAIM, 0);
 	if (!xfs_alloc_wq)
-		goto out_destroy_syncd;
+		return -ENOMEM;
 
 	return 0;
-
-out_destroy_syncd:
-	destroy_workqueue(xfs_syncd_wq);
-	return -ENOMEM;
 }
 
 STATIC void
 xfs_destroy_workqueues(void)
 {
 	destroy_workqueue(xfs_alloc_wq);
-	destroy_workqueue(xfs_syncd_wq);
 }
 
 STATIC int __init
diff --git a/fs/xfs/xfs_super.h b/fs/xfs/xfs_super.h
index 9de4a92..bbe3d15 100644
--- a/fs/xfs/xfs_super.h
+++ b/fs/xfs/xfs_super.h
@@ -74,6 +74,7 @@ struct block_device;
 
 extern __uint64_t xfs_max_file_offset(unsigned int);
 
+extern void xfs_flush_inodes(struct xfs_mount *mp);
 extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);
 extern xfs_agnumber_t xfs_set_inode32(struct xfs_mount *);
 extern xfs_agnumber_t xfs_set_inode64(struct xfs_mount *);
diff --git a/fs/xfs/xfs_sync.c b/fs/xfs/xfs_sync.c
deleted file mode 100644
index 9500caf..0000000
--- a/fs/xfs/xfs_sync.c
+++ /dev/null
@@ -1,973 +0,0 @@
-/*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include "xfs.h"
-#include "xfs_fs.h"
-#include "xfs_types.h"
-#include "xfs_log.h"
-#include "xfs_inum.h"
-#include "xfs_trans.h"
-#include "xfs_trans_priv.h"
-#include "xfs_sb.h"
-#include "xfs_ag.h"
-#include "xfs_mount.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_inode.h"
-#include "xfs_dinode.h"
-#include "xfs_error.h"
-#include "xfs_filestream.h"
-#include "xfs_vnodeops.h"
-#include "xfs_inode_item.h"
-#include "xfs_quota.h"
-#include "xfs_trace.h"
-#include "xfs_fsops.h"
-
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-
-struct workqueue_struct	*xfs_syncd_wq;	/* sync workqueue */
-
-/*
- * The inode lookup is done in batches to keep the amount of lock traffic and
- * radix tree lookups to a minimum. The batch size is a trade off between
- * lookup reduction and stack usage. This is in the reclaim path, so we can't
- * be too greedy.
- */
-#define XFS_LOOKUP_BATCH	32
-
-STATIC int
-xfs_inode_ag_walk_grab(
-	struct xfs_inode	*ip)
-{
-	struct inode		*inode = VFS_I(ip);
-
-	ASSERT(rcu_read_lock_held());
-
-	/*
-	 * check for stale RCU freed inode
-	 *
-	 * If the inode has been reallocated, it doesn't matter if it's not in
-	 * the AG we are walking - we are walking for writeback, so if it
-	 * passes all the "valid inode" checks and is dirty, then we'll write
-	 * it back anyway.  If it has been reallocated and still being
-	 * initialised, the XFS_INEW check below will catch it.
-	 */
-	spin_lock(&ip->i_flags_lock);
-	if (!ip->i_ino)
-		goto out_unlock_noent;
-
-	/* avoid new or reclaimable inodes. Leave for reclaim code to flush */
-	if (__xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIMABLE | XFS_IRECLAIM))
-		goto out_unlock_noent;
-	spin_unlock(&ip->i_flags_lock);
-
-	/* nothing to sync during shutdown */
-	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
-		return EFSCORRUPTED;
-
-	/* If we can't grab the inode, it must on it's way to reclaim. */
-	if (!igrab(inode))
-		return ENOENT;
-
-	if (is_bad_inode(inode)) {
-		IRELE(ip);
-		return ENOENT;
-	}
-
-	/* inode is valid */
-	return 0;
-
-out_unlock_noent:
-	spin_unlock(&ip->i_flags_lock);
-	return ENOENT;
-}
-
-STATIC int
-xfs_inode_ag_walk(
-	struct xfs_mount	*mp,
-	struct xfs_perag	*pag,
-	int			(*execute)(struct xfs_inode *ip,
-					   struct xfs_perag *pag, int flags),
-	int			flags)
-{
-	uint32_t		first_index;
-	int			last_error = 0;
-	int			skipped;
-	int			done;
-	int			nr_found;
-
-restart:
-	done = 0;
-	skipped = 0;
-	first_index = 0;
-	nr_found = 0;
-	do {
-		struct xfs_inode *batch[XFS_LOOKUP_BATCH];
-		int		error = 0;
-		int		i;
-
-		rcu_read_lock();
-		nr_found = radix_tree_gang_lookup(&pag->pag_ici_root,
-					(void **)batch, first_index,
-					XFS_LOOKUP_BATCH);
-		if (!nr_found) {
-			rcu_read_unlock();
-			break;
-		}
-
-		/*
-		 * Grab the inodes before we drop the lock. if we found
-		 * nothing, nr == 0 and the loop will be skipped.
-		 */
-		for (i = 0; i < nr_found; i++) {
-			struct xfs_inode *ip = batch[i];
-
-			if (done || xfs_inode_ag_walk_grab(ip))
-				batch[i] = NULL;
-
-			/*
-			 * Update the index for the next lookup. Catch
-			 * overflows into the next AG range which can occur if
-			 * we have inodes in the last block of the AG and we
-			 * are currently pointing to the last inode.
-			 *
-			 * Because we may see inodes that are from the wrong AG
-			 * due to RCU freeing and reallocation, only update the
-			 * index if it lies in this AG. It was a race that lead
-			 * us to see this inode, so another lookup from the
-			 * same index will not find it again.
-			 */
-			if (XFS_INO_TO_AGNO(mp, ip->i_ino) != pag->pag_agno)
-				continue;
-			first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
-			if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino))
-				done = 1;
-		}
-
-		/* unlock now we've grabbed the inodes. */
-		rcu_read_unlock();
-
-		for (i = 0; i < nr_found; i++) {
-			if (!batch[i])
-				continue;
-			error = execute(batch[i], pag, flags);
-			IRELE(batch[i]);
-			if (error == EAGAIN) {
-				skipped++;
-				continue;
-			}
-			if (error && last_error != EFSCORRUPTED)
-				last_error = error;
-		}
-
-		/* bail out if the filesystem is corrupted.  */
-		if (error == EFSCORRUPTED)
-			break;
-
-		cond_resched();
-
-	} while (nr_found && !done);
-
-	if (skipped) {
-		delay(1);
-		goto restart;
-	}
-	return last_error;
-}
-
-int
-xfs_inode_ag_iterator(
-	struct xfs_mount	*mp,
-	int			(*execute)(struct xfs_inode *ip,
-					   struct xfs_perag *pag, int flags),
-	int			flags)
-{
-	struct xfs_perag	*pag;
-	int			error = 0;
-	int			last_error = 0;
-	xfs_agnumber_t		ag;
-
-	ag = 0;
-	while ((pag = xfs_perag_get(mp, ag))) {
-		ag = pag->pag_agno + 1;
-		error = xfs_inode_ag_walk(mp, pag, execute, flags);
-		xfs_perag_put(pag);
-		if (error) {
-			last_error = error;
-			if (error == EFSCORRUPTED)
-				break;
-		}
-	}
-	return XFS_ERROR(last_error);
-}
-
-STATIC int
-xfs_sync_inode_data(
-	struct xfs_inode	*ip,
-	struct xfs_perag	*pag,
-	int			flags)
-{
-	struct inode		*inode = VFS_I(ip);
-	struct address_space *mapping = inode->i_mapping;
-	int			error = 0;
-
-	if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
-		return 0;
-
-	if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
-		if (flags & SYNC_TRYLOCK)
-			return 0;
-		xfs_ilock(ip, XFS_IOLOCK_SHARED);
-	}
-
-	error = xfs_flush_pages(ip, 0, -1, (flags & SYNC_WAIT) ?
-				0 : XBF_ASYNC, FI_NONE);
-	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
-	return error;
-}
-
-/*
- * Write out pagecache data for the whole filesystem.
- */
-STATIC int
-xfs_sync_data(
-	struct xfs_mount	*mp,
-	int			flags)
-{
-	int			error;
-
-	ASSERT((flags & ~(SYNC_TRYLOCK|SYNC_WAIT)) == 0);
-
-	error = xfs_inode_ag_iterator(mp, xfs_sync_inode_data, flags);
-	if (error)
-		return XFS_ERROR(error);
-
-	xfs_log_force(mp, (flags & SYNC_WAIT) ? XFS_LOG_SYNC : 0);
-	return 0;
-}
-
-STATIC int
-xfs_sync_fsdata(
-	struct xfs_mount	*mp)
-{
-	struct xfs_buf		*bp;
-	int			error;
-
-	/*
-	 * If the buffer is pinned then push on the log so we won't get stuck
-	 * waiting in the write for someone, maybe ourselves, to flush the log.
-	 *
-	 * Even though we just pushed the log above, we did not have the
-	 * superblock buffer locked at that point so it can become pinned in
-	 * between there and here.
-	 */
-	bp = xfs_getsb(mp, 0);
-	if (xfs_buf_ispinned(bp))
-		xfs_log_force(mp, 0);
-	error = xfs_bwrite(bp);
-	xfs_buf_relse(bp);
-	return error;
-}
-
-/*
- * When remounting a filesystem read-only or freezing the filesystem, we have
- * two phases to execute. This first phase is syncing the data before we
- * quiesce the filesystem, and the second is flushing all the inodes out after
- * we've waited for all the transactions created by the first phase to
- * complete. The second phase ensures that the inodes are written to their
- * location on disk rather than just existing in transactions in the log. This
- * means after a quiesce there is no log replay required to write the inodes to
- * disk (this is the main difference between a sync and a quiesce).
- */
-/*
- * First stage of freeze - no writers will make progress now we are here,
- * so we flush delwri and delalloc buffers here, then wait for all I/O to
- * complete.  Data is frozen at that point. Metadata is not frozen,
- * transactions can still occur here so don't bother emptying the AIL
- * because it'll just get dirty again.
- */
-int
-xfs_quiesce_data(
-	struct xfs_mount	*mp)
-{
-	int			error, error2 = 0;
-
-	/* force out the log */
-	xfs_log_force(mp, XFS_LOG_SYNC);
-
-	/* write superblock and hoover up shutdown errors */
-	error = xfs_sync_fsdata(mp);
-
-	/* mark the log as covered if needed */
-	if (xfs_log_need_covered(mp))
-		error2 = xfs_fs_log_dummy(mp);
-
-	return error ? error : error2;
-}
-
-/*
- * Second stage of a quiesce. The data is already synced, now we have to take
- * care of the metadata. New transactions are already blocked, so we need to
- * wait for any remaining transactions to drain out before proceeding.
- */
-void
-xfs_quiesce_attr(
-	struct xfs_mount	*mp)
-{
-	int	error = 0;
-
-	/* wait for all modifications to complete */
-	while (atomic_read(&mp->m_active_trans) > 0)
-		delay(100);
-
-	/* reclaim inodes to do any IO before the freeze completes */
-	xfs_reclaim_inodes(mp, 0);
-	xfs_reclaim_inodes(mp, SYNC_WAIT);
-
-	/* flush all pending changes from the AIL */
-	xfs_ail_push_all_sync(mp->m_ail);
-
-	/*
-	 * Just warn here till VFS can correctly support
-	 * read-only remount without racing.
-	 */
-	WARN_ON(atomic_read(&mp->m_active_trans) != 0);
-
-	/* Push the superblock and write an unmount record */
-	error = xfs_log_sbcount(mp);
-	if (error)
-		xfs_warn(mp, "xfs_attr_quiesce: failed to log sb changes. "
-				"Frozen image may not be consistent.");
-	xfs_log_unmount_write(mp);
-
-	/*
-	 * At this point we might have modified the superblock again and thus
-	 * added an item to the AIL, thus flush it again.
-	 */
-	xfs_ail_push_all_sync(mp->m_ail);
-
-	/*
-	 * The superblock buffer is uncached and xfsaild_push() will lock and
-	 * set the XBF_ASYNC flag on the buffer. We cannot do xfs_buf_iowait()
-	 * here but a lock on the superblock buffer will block until iodone()
-	 * has completed.
-	 */
-	xfs_buf_lock(mp->m_sb_bp);
-	xfs_buf_unlock(mp->m_sb_bp);
-}
-
-static void
-xfs_syncd_queue_sync(
-	struct xfs_mount        *mp)
-{
-	queue_delayed_work(xfs_syncd_wq, &mp->m_sync_work,
-				msecs_to_jiffies(xfs_syncd_centisecs * 10));
-}
-
-/*
- * Every sync period we need to unpin all items, reclaim inodes and sync
- * disk quotas.  We might need to cover the log to indicate that the
- * filesystem is idle and not frozen.
- */
-STATIC void
-xfs_sync_worker(
-	struct work_struct *work)
-{
-	struct xfs_mount *mp = container_of(to_delayed_work(work),
-					struct xfs_mount, m_sync_work);
-	int		error;
-
-	/*
-	 * We shouldn't write/force the log if we are in the mount/unmount
-	 * process or on a read only filesystem. The workqueue still needs to be
-	 * active in both cases, however, because it is used for inode reclaim
-	 * during these times.  Use the MS_ACTIVE flag to avoid doing anything
-	 * during mount.  Doing work during unmount is avoided by calling
-	 * cancel_delayed_work_sync on this work queue before tearing down
-	 * the ail and the log in xfs_log_unmount.
-	 */
-	if (!(mp->m_super->s_flags & MS_ACTIVE) &&
-	    !(mp->m_flags & XFS_MOUNT_RDONLY)) {
-		/* dgc: errors ignored here */
-		if (mp->m_super->s_writers.frozen == SB_UNFROZEN &&
-		    xfs_log_need_covered(mp))
-			error = xfs_fs_log_dummy(mp);
-		else
-			xfs_log_force(mp, 0);
-
-		/* start pushing all the metadata that is currently
-		 * dirty */
-		xfs_ail_push_all(mp->m_ail);
-	}
-
-	/* queue us up again */
-	xfs_syncd_queue_sync(mp);
-}
-
-/*
- * Queue a new inode reclaim pass if there are reclaimable inodes and there
- * isn't a reclaim pass already in progress. By default it runs every 5s based
- * on the xfs syncd work default of 30s. Perhaps this should have it's own
- * tunable, but that can be done if this method proves to be ineffective or too
- * aggressive.
- */
-static void
-xfs_syncd_queue_reclaim(
-	struct xfs_mount        *mp)
-{
-
-	rcu_read_lock();
-	if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_RECLAIM_TAG)) {
-		queue_delayed_work(xfs_syncd_wq, &mp->m_reclaim_work,
-			msecs_to_jiffies(xfs_syncd_centisecs / 6 * 10));
-	}
-	rcu_read_unlock();
-}
-
-/*
- * This is a fast pass over the inode cache to try to get reclaim moving on as
- * many inodes as possible in a short period of time. It kicks itself every few
- * seconds, as well as being kicked by the inode cache shrinker when memory
- * goes low. It scans as quickly as possible avoiding locked inodes or those
- * already being flushed, and once done schedules a future pass.
- */
-STATIC void
-xfs_reclaim_worker(
-	struct work_struct *work)
-{
-	struct xfs_mount *mp = container_of(to_delayed_work(work),
-					struct xfs_mount, m_reclaim_work);
-
-	xfs_reclaim_inodes(mp, SYNC_TRYLOCK);
-	xfs_syncd_queue_reclaim(mp);
-}
-
-/*
- * Flush delayed allocate data, attempting to free up reserved space
- * from existing allocations.  At this point a new allocation attempt
- * has failed with ENOSPC and we are in the process of scratching our
- * heads, looking about for more room.
- *
- * Queue a new data flush if there isn't one already in progress and
- * wait for completion of the flush. This means that we only ever have one
- * inode flush in progress no matter how many ENOSPC events are occurring and
- * so will prevent the system from bogging down due to every concurrent
- * ENOSPC event scanning all the active inodes in the system for writeback.
- */
-void
-xfs_flush_inodes(
-	struct xfs_inode	*ip)
-{
-	struct xfs_mount	*mp = ip->i_mount;
-
-	queue_work(xfs_syncd_wq, &mp->m_flush_work);
-	flush_work(&mp->m_flush_work);
-}
-
-STATIC void
-xfs_flush_worker(
-	struct work_struct *work)
-{
-	struct xfs_mount *mp = container_of(work,
-					struct xfs_mount, m_flush_work);
-
-	xfs_sync_data(mp, SYNC_TRYLOCK);
-	xfs_sync_data(mp, SYNC_TRYLOCK | SYNC_WAIT);
-}
-
-int
-xfs_syncd_init(
-	struct xfs_mount	*mp)
-{
-	INIT_WORK(&mp->m_flush_work, xfs_flush_worker);
-	INIT_DELAYED_WORK(&mp->m_sync_work, xfs_sync_worker);
-	INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);
-
-	xfs_syncd_queue_sync(mp);
-
-	return 0;
-}
-
-void
-xfs_syncd_stop(
-	struct xfs_mount	*mp)
-{
-	cancel_delayed_work_sync(&mp->m_sync_work);
-	cancel_delayed_work_sync(&mp->m_reclaim_work);
-	cancel_work_sync(&mp->m_flush_work);
-}
-
-void
-__xfs_inode_set_reclaim_tag(
-	struct xfs_perag	*pag,
-	struct xfs_inode	*ip)
-{
-	radix_tree_tag_set(&pag->pag_ici_root,
-			   XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino),
-			   XFS_ICI_RECLAIM_TAG);
-
-	if (!pag->pag_ici_reclaimable) {
-		/* propagate the reclaim tag up into the perag radix tree */
-		spin_lock(&ip->i_mount->m_perag_lock);
-		radix_tree_tag_set(&ip->i_mount->m_perag_tree,
-				XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino),
-				XFS_ICI_RECLAIM_TAG);
-		spin_unlock(&ip->i_mount->m_perag_lock);
-
-		/* schedule periodic background inode reclaim */
-		xfs_syncd_queue_reclaim(ip->i_mount);
-
-		trace_xfs_perag_set_reclaim(ip->i_mount, pag->pag_agno,
-							-1, _RET_IP_);
-	}
-	pag->pag_ici_reclaimable++;
-}
-
-/*
- * We set the inode flag atomically with the radix tree tag.
- * Once we get tag lookups on the radix tree, this inode flag
- * can go away.
- */
-void
-xfs_inode_set_reclaim_tag(
-	xfs_inode_t	*ip)
-{
-	struct xfs_mount *mp = ip->i_mount;
-	struct xfs_perag *pag;
-
-	pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
-	spin_lock(&pag->pag_ici_lock);
-	spin_lock(&ip->i_flags_lock);
-	__xfs_inode_set_reclaim_tag(pag, ip);
-	__xfs_iflags_set(ip, XFS_IRECLAIMABLE);
-	spin_unlock(&ip->i_flags_lock);
-	spin_unlock(&pag->pag_ici_lock);
-	xfs_perag_put(pag);
-}
-
-STATIC void
-__xfs_inode_clear_reclaim(
-	xfs_perag_t	*pag,
-	xfs_inode_t	*ip)
-{
-	pag->pag_ici_reclaimable--;
-	if (!pag->pag_ici_reclaimable) {
-		/* clear the reclaim tag from the perag radix tree */
-		spin_lock(&ip->i_mount->m_perag_lock);
-		radix_tree_tag_clear(&ip->i_mount->m_perag_tree,
-				XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino),
-				XFS_ICI_RECLAIM_TAG);
-		spin_unlock(&ip->i_mount->m_perag_lock);
-		trace_xfs_perag_clear_reclaim(ip->i_mount, pag->pag_agno,
-							-1, _RET_IP_);
-	}
-}
-
-void
-__xfs_inode_clear_reclaim_tag(
-	xfs_mount_t	*mp,
-	xfs_perag_t	*pag,
-	xfs_inode_t	*ip)
-{
-	radix_tree_tag_clear(&pag->pag_ici_root,
-			XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);
-	__xfs_inode_clear_reclaim(pag, ip);
-}
-
-/*
- * Grab the inode for reclaim exclusively.
- * Return 0 if we grabbed it, non-zero otherwise.
- */
-STATIC int
-xfs_reclaim_inode_grab(
-	struct xfs_inode	*ip,
-	int			flags)
-{
-	ASSERT(rcu_read_lock_held());
-
-	/* quick check for stale RCU freed inode */
-	if (!ip->i_ino)
-		return 1;
-
-	/*
-	 * If we are asked for non-blocking operation, do unlocked checks to
-	 * see if the inode already is being flushed or in reclaim to avoid
-	 * lock traffic.
-	 */
-	if ((flags & SYNC_TRYLOCK) &&
-	    __xfs_iflags_test(ip, XFS_IFLOCK | XFS_IRECLAIM))
-		return 1;
-
-	/*
-	 * The radix tree lock here protects a thread in xfs_iget from racing
-	 * with us starting reclaim on the inode.  Once we have the
-	 * XFS_IRECLAIM flag set it will not touch us.
-	 *
-	 * Due to RCU lookup, we may find inodes that have been freed and only
-	 * have XFS_IRECLAIM set.  Indeed, we may see reallocated inodes that
-	 * aren't candidates for reclaim at all, so we must check the
-	 * XFS_IRECLAIMABLE is set first before proceeding to reclaim.
-	 */
-	spin_lock(&ip->i_flags_lock);
-	if (!__xfs_iflags_test(ip, XFS_IRECLAIMABLE) ||
-	    __xfs_iflags_test(ip, XFS_IRECLAIM)) {
-		/* not a reclaim candidate. */
-		spin_unlock(&ip->i_flags_lock);
-		return 1;
-	}
-	__xfs_iflags_set(ip, XFS_IRECLAIM);
-	spin_unlock(&ip->i_flags_lock);
-	return 0;
-}
-
-/*
- * Inodes in different states need to be treated differently. The following
- * table lists the inode states and the reclaim actions necessary:
- *
- *	inode state	     iflush ret		required action
- *      ---------------      ----------         ---------------
- *	bad			-		reclaim
- *	shutdown		EIO		unpin and reclaim
- *	clean, unpinned		0		reclaim
- *	stale, unpinned		0		reclaim
- *	clean, pinned(*)	0		requeue
- *	stale, pinned		EAGAIN		requeue
- *	dirty, async		-		requeue
- *	dirty, sync		0		reclaim
- *
- * (*) dgc: I don't think the clean, pinned state is possible but it gets
- * handled anyway given the order of checks implemented.
- *
- * Also, because we get the flush lock first, we know that any inode that has
- * been flushed delwri has had the flush completed by the time we check that
- * the inode is clean.
- *
- * Note that because the inode is flushed delayed write by AIL pushing, the
- * flush lock may already be held here and waiting on it can result in very
- * long latencies.  Hence for sync reclaims, where we wait on the flush lock,
- * the caller should push the AIL first before trying to reclaim inodes to
- * minimise the amount of time spent waiting.  For background relaim, we only
- * bother to reclaim clean inodes anyway.
- *
- * Hence the order of actions after gaining the locks should be:
- *	bad		=> reclaim
- *	shutdown	=> unpin and reclaim
- *	pinned, async	=> requeue
- *	pinned, sync	=> unpin
- *	stale		=> reclaim
- *	clean		=> reclaim
- *	dirty, async	=> requeue
- *	dirty, sync	=> flush, wait and reclaim
- */
-STATIC int
-xfs_reclaim_inode(
-	struct xfs_inode	*ip,
-	struct xfs_perag	*pag,
-	int			sync_mode)
-{
-	struct xfs_buf		*bp = NULL;
-	int			error;
-
-restart:
-	error = 0;
-	xfs_ilock(ip, XFS_ILOCK_EXCL);
-	if (!xfs_iflock_nowait(ip)) {
-		if (!(sync_mode & SYNC_WAIT))
-			goto out;
-		xfs_iflock(ip);
-	}
-
-	if (is_bad_inode(VFS_I(ip)))
-		goto reclaim;
-	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
-		xfs_iunpin_wait(ip);
-		xfs_iflush_abort(ip, false);
-		goto reclaim;
-	}
-	if (xfs_ipincount(ip)) {
-		if (!(sync_mode & SYNC_WAIT))
-			goto out_ifunlock;
-		xfs_iunpin_wait(ip);
-	}
-	if (xfs_iflags_test(ip, XFS_ISTALE))
-		goto reclaim;
-	if (xfs_inode_clean(ip))
-		goto reclaim;
-
-	/*
-	 * Never flush out dirty data during non-blocking reclaim, as it would
-	 * just contend with AIL pushing trying to do the same job.
-	 */
-	if (!(sync_mode & SYNC_WAIT))
-		goto out_ifunlock;
-
-	/*
-	 * Now we have an inode that needs flushing.
-	 *
-	 * Note that xfs_iflush will never block on the inode buffer lock, as
-	 * xfs_ifree_cluster() can lock the inode buffer before it locks the
-	 * ip->i_lock, and we are doing the exact opposite here.  As a result,
-	 * doing a blocking xfs_imap_to_bp() to get the cluster buffer would
-	 * result in an ABBA deadlock with xfs_ifree_cluster().
-	 *
-	 * As xfs_ifree_cluser() must gather all inodes that are active in the
-	 * cache to mark them stale, if we hit this case we don't actually want
-	 * to do IO here - we want the inode marked stale so we can simply
-	 * reclaim it.  Hence if we get an EAGAIN error here,  just unlock the
-	 * inode, back off and try again.  Hopefully the next pass through will
-	 * see the stale flag set on the inode.
-	 */
-	error = xfs_iflush(ip, &bp);
-	if (error == EAGAIN) {
-		xfs_iunlock(ip, XFS_ILOCK_EXCL);
-		/* backoff longer than in xfs_ifree_cluster */
-		delay(2);
-		goto restart;
-	}
-
-	if (!error) {
-		error = xfs_bwrite(bp);
-		xfs_buf_relse(bp);
-	}
-
-	xfs_iflock(ip);
-reclaim:
-	xfs_ifunlock(ip);
-	xfs_iunlock(ip, XFS_ILOCK_EXCL);
-
-	XFS_STATS_INC(xs_ig_reclaims);
-	/*
-	 * Remove the inode from the per-AG radix tree.
-	 *
-	 * Because radix_tree_delete won't complain even if the item was never
-	 * added to the tree assert that it's been there before to catch
-	 * problems with the inode life time early on.
-	 */
-	spin_lock(&pag->pag_ici_lock);
-	if (!radix_tree_delete(&pag->pag_ici_root,
-				XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino)))
-		ASSERT(0);
-	__xfs_inode_clear_reclaim(pag, ip);
-	spin_unlock(&pag->pag_ici_lock);
-
-	/*
-	 * Here we do an (almost) spurious inode lock in order to coordinate
-	 * with inode cache radix tree lookups.  This is because the lookup
-	 * can reference the inodes in the cache without taking references.
-	 *
-	 * We make that OK here by ensuring that we wait until the inode is
-	 * unlocked after the lookup before we go ahead and free it.
-	 */
-	xfs_ilock(ip, XFS_ILOCK_EXCL);
-	xfs_qm_dqdetach(ip);
-	xfs_iunlock(ip, XFS_ILOCK_EXCL);
-
-	xfs_inode_free(ip);
-	return error;
-
-out_ifunlock:
-	xfs_ifunlock(ip);
-out:
-	xfs_iflags_clear(ip, XFS_IRECLAIM);
-	xfs_iunlock(ip, XFS_ILOCK_EXCL);
-	/*
-	 * We could return EAGAIN here to make reclaim rescan the inode tree in
-	 * a short while. However, this just burns CPU time scanning the tree
-	 * waiting for IO to complete and xfssyncd never goes back to the idle
-	 * state. Instead, return 0 to let the next scheduled background reclaim
-	 * attempt to reclaim the inode again.
-	 */
-	return 0;
-}
-
-/*
- * Walk the AGs and reclaim the inodes in them. Even if the filesystem is
- * corrupted, we still want to try to reclaim all the inodes. If we don't,
- * then a shut down during filesystem unmount reclaim walk leak all the
- * unreclaimed inodes.
- */
-int
-xfs_reclaim_inodes_ag(
-	struct xfs_mount	*mp,
-	int			flags,
-	int			*nr_to_scan)
-{
-	struct xfs_perag	*pag;
-	int			error = 0;
-	int			last_error = 0;
-	xfs_agnumber_t		ag;
-	int			trylock = flags & SYNC_TRYLOCK;
-	int			skipped;
-
-restart:
-	ag = 0;
-	skipped = 0;
-	while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) {
-		unsigned long	first_index = 0;
-		int		done = 0;
-		int		nr_found = 0;
-
-		ag = pag->pag_agno + 1;
-
-		if (trylock) {
-			if (!mutex_trylock(&pag->pag_ici_reclaim_lock)) {
-				skipped++;
-				xfs_perag_put(pag);
-				continue;
-			}
-			first_index = pag->pag_ici_reclaim_cursor;
-		} else
-			mutex_lock(&pag->pag_ici_reclaim_lock);
-
-		do {
-			struct xfs_inode *batch[XFS_LOOKUP_BATCH];
-			int	i;
-
-			rcu_read_lock();
-			nr_found = radix_tree_gang_lookup_tag(
-					&pag->pag_ici_root,
-					(void **)batch, first_index,
-					XFS_LOOKUP_BATCH,
-					XFS_ICI_RECLAIM_TAG);
-			if (!nr_found) {
-				done = 1;
-				rcu_read_unlock();
-				break;
-			}
-
-			/*
-			 * Grab the inodes before we drop the lock. if we found
-			 * nothing, nr == 0 and the loop will be skipped.
-			 */
-			for (i = 0; i < nr_found; i++) {
-				struct xfs_inode *ip = batch[i];
-
-				if (done || xfs_reclaim_inode_grab(ip, flags))
-					batch[i] = NULL;
-
-				/*
-				 * Update the index for the next lookup. Catch
-				 * overflows into the next AG range which can
-				 * occur if we have inodes in the last block of
-				 * the AG and we are currently pointing to the
-				 * last inode.
-				 *
-				 * Because we may see inodes that are from the
-				 * wrong AG due to RCU freeing and
-				 * reallocation, only update the index if it
-				 * lies in this AG. It was a race that lead us
-				 * to see this inode, so another lookup from
-				 * the same index will not find it again.
-				 */
-				if (XFS_INO_TO_AGNO(mp, ip->i_ino) !=
-								pag->pag_agno)
-					continue;
-				first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
-				if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino))
-					done = 1;
-			}
-
-			/* unlock now we've grabbed the inodes. */
-			rcu_read_unlock();
-
-			for (i = 0; i < nr_found; i++) {
-				if (!batch[i])
-					continue;
-				error = xfs_reclaim_inode(batch[i], pag, flags);
-				if (error && last_error != EFSCORRUPTED)
-					last_error = error;
-			}
-
-			*nr_to_scan -= XFS_LOOKUP_BATCH;
-
-			cond_resched();
-
-		} while (nr_found && !done && *nr_to_scan > 0);
-
-		if (trylock && !done)
-			pag->pag_ici_reclaim_cursor = first_index;
-		else
-			pag->pag_ici_reclaim_cursor = 0;
-		mutex_unlock(&pag->pag_ici_reclaim_lock);
-		xfs_perag_put(pag);
-	}
-
-	/*
-	 * if we skipped any AG, and we still have scan count remaining, do
-	 * another pass this time using blocking reclaim semantics (i.e
-	 * waiting on the reclaim locks and ignoring the reclaim cursors). This
-	 * ensure that when we get more reclaimers than AGs we block rather
-	 * than spin trying to execute reclaim.
-	 */
-	if (skipped && (flags & SYNC_WAIT) && *nr_to_scan > 0) {
-		trylock = 0;
-		goto restart;
-	}
-	return XFS_ERROR(last_error);
-}
-
-int
-xfs_reclaim_inodes(
-	xfs_mount_t	*mp,
-	int		mode)
-{
-	int		nr_to_scan = INT_MAX;
-
-	return xfs_reclaim_inodes_ag(mp, mode, &nr_to_scan);
-}
-
-/*
- * Scan a certain number of inodes for reclaim.
- *
- * When called we make sure that there is a background (fast) inode reclaim in
- * progress, while we will throttle the speed of reclaim via doing synchronous
- * reclaim of inodes. That means if we come across dirty inodes, we wait for
- * them to be cleaned, which we hope will not be very long due to the
- * background walker having already kicked the IO off on those dirty inodes.
- */
-void
-xfs_reclaim_inodes_nr(
-	struct xfs_mount	*mp,
-	int			nr_to_scan)
-{
-	/* kick background reclaimer and push the AIL */
-	xfs_syncd_queue_reclaim(mp);
-	xfs_ail_push_all(mp->m_ail);
-
-	xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT, &nr_to_scan);
-}
-
-/*
- * Return the number of reclaimable inodes in the filesystem for
- * the shrinker to determine how much to reclaim.
- */
-int
-xfs_reclaim_inodes_count(
-	struct xfs_mount	*mp)
-{
-	struct xfs_perag	*pag;
-	xfs_agnumber_t		ag = 0;
-	int			reclaimable = 0;
-
-	while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) {
-		ag = pag->pag_agno + 1;
-		reclaimable += pag->pag_ici_reclaimable;
-		xfs_perag_put(pag);
-	}
-	return reclaimable;
-}
-
diff --git a/fs/xfs/xfs_sync.h b/fs/xfs/xfs_sync.h
deleted file mode 100644
index 941202e..0000000
--- a/fs/xfs/xfs_sync.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2000-2006 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef XFS_SYNC_H
-#define XFS_SYNC_H 1
-
-struct xfs_mount;
-struct xfs_perag;
-
-#define SYNC_WAIT		0x0001	/* wait for i/o to complete */
-#define SYNC_TRYLOCK		0x0002  /* only try to lock inodes */
-
-extern struct workqueue_struct	*xfs_syncd_wq;	/* sync workqueue */
-
-int xfs_syncd_init(struct xfs_mount *mp);
-void xfs_syncd_stop(struct xfs_mount *mp);
-
-int xfs_quiesce_data(struct xfs_mount *mp);
-void xfs_quiesce_attr(struct xfs_mount *mp);
-
-void xfs_flush_inodes(struct xfs_inode *ip);
-
-int xfs_reclaim_inodes(struct xfs_mount *mp, int mode);
-int xfs_reclaim_inodes_count(struct xfs_mount *mp);
-void xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);
-
-void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
-void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip);
-void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, struct xfs_perag *pag,
-				struct xfs_inode *ip);
-
-int xfs_sync_inode_grab(struct xfs_inode *ip);
-int xfs_inode_ag_iterator(struct xfs_mount *mp,
-	int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags),
-	int flags);
-
-#endif
diff --git a/fs/xfs/xfs_sysctl.c b/fs/xfs/xfs_sysctl.c
index ee2d2ad..2801b5c 100644
--- a/fs/xfs/xfs_sysctl.c
+++ b/fs/xfs/xfs_sysctl.c
@@ -202,6 +202,15 @@ static ctl_table xfs_table[] = {
 		.extra1		= &xfs_params.fstrm_timer.min,
 		.extra2		= &xfs_params.fstrm_timer.max,
 	},
+	{
+		.procname	= "speculative_prealloc_lifetime",
+		.data		= &xfs_params.eofb_timer.val,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &xfs_params.eofb_timer.min,
+		.extra2		= &xfs_params.eofb_timer.max,
+	},
 	/* please keep this the last entry */
 #ifdef CONFIG_PROC_FS
 	{
diff --git a/fs/xfs/xfs_sysctl.h b/fs/xfs/xfs_sysctl.h
index b9937d4..bd8e157 100644
--- a/fs/xfs/xfs_sysctl.h
+++ b/fs/xfs/xfs_sysctl.h
@@ -47,6 +47,7 @@ typedef struct xfs_param {
 	xfs_sysctl_val_t rotorstep;	/* inode32 AG rotoring control knob */
 	xfs_sysctl_val_t inherit_nodfrg;/* Inherit the "nodefrag" inode flag. */
 	xfs_sysctl_val_t fstrm_timer;	/* Filestream dir-AG assoc'n timeout. */
+	xfs_sysctl_val_t eofb_timer;	/* Interval between eofb scan wakeups */
 } xfs_param_t;
 
 /*
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 7d36ccf..2e137d4 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -96,6 +96,8 @@ DEFINE_ATTR_LIST_EVENT(xfs_attr_list_full);
 DEFINE_ATTR_LIST_EVENT(xfs_attr_list_add);
 DEFINE_ATTR_LIST_EVENT(xfs_attr_list_wrong_blk);
 DEFINE_ATTR_LIST_EVENT(xfs_attr_list_notfound);
+DEFINE_ATTR_LIST_EVENT(xfs_attr_leaf_list);
+DEFINE_ATTR_LIST_EVENT(xfs_attr_node_list);
 
 DECLARE_EVENT_CLASS(xfs_perag_class,
 	TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, int refcount,
@@ -130,6 +132,8 @@ DEFINE_PERAG_REF_EVENT(xfs_perag_get_tag);
 DEFINE_PERAG_REF_EVENT(xfs_perag_put);
 DEFINE_PERAG_REF_EVENT(xfs_perag_set_reclaim);
 DEFINE_PERAG_REF_EVENT(xfs_perag_clear_reclaim);
+DEFINE_PERAG_REF_EVENT(xfs_perag_set_eofblocks);
+DEFINE_PERAG_REF_EVENT(xfs_perag_clear_eofblocks);
 
 TRACE_EVENT(xfs_attr_list_node_descend,
 	TP_PROTO(struct xfs_attr_list_context *ctx,
@@ -585,6 +589,10 @@ DEFINE_INODE_EVENT(xfs_update_time);
 DEFINE_INODE_EVENT(xfs_dquot_dqalloc);
 DEFINE_INODE_EVENT(xfs_dquot_dqdetach);
 
+DEFINE_INODE_EVENT(xfs_inode_set_eofblocks_tag);
+DEFINE_INODE_EVENT(xfs_inode_clear_eofblocks_tag);
+DEFINE_INODE_EVENT(xfs_inode_free_eofblocks_invalid);
+
 DECLARE_EVENT_CLASS(xfs_iref_class,
 	TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip),
 	TP_ARGS(ip, caller_ip),
@@ -1496,8 +1504,42 @@ DEFINE_DIR2_EVENT(xfs_dir2_node_replace);
 DEFINE_DIR2_EVENT(xfs_dir2_node_removename);
 DEFINE_DIR2_EVENT(xfs_dir2_node_to_leaf);
 
+DECLARE_EVENT_CLASS(xfs_attr_class,
+	TP_PROTO(struct xfs_da_args *args),
+	TP_ARGS(args),
+	TP_STRUCT__entry(
+		__field(dev_t, dev)
+		__field(xfs_ino_t, ino)
+		__dynamic_array(char, name, args->namelen)
+		__field(int, namelen)
+		__field(int, valuelen)
+		__field(xfs_dahash_t, hashval)
+		__field(int, op_flags)
+	),
+	TP_fast_assign(
+		__entry->dev = VFS_I(args->dp)->i_sb->s_dev;
+		__entry->ino = args->dp->i_ino;
+		if (args->namelen)
+			memcpy(__get_str(name), args->name, args->namelen);
+		__entry->namelen = args->namelen;
+		__entry->valuelen = args->valuelen;
+		__entry->hashval = args->hashval;
+		__entry->op_flags = args->op_flags;
+	),
+	TP_printk("dev %d:%d ino 0x%llx name %.*s namelen %d valuelen %d "
+		  "hashval 0x%x op_flags %s",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->ino,
+		  __entry->namelen,
+		  __entry->namelen ? __get_str(name) : NULL,
+		  __entry->namelen,
+		  __entry->valuelen,
+		  __entry->hashval,
+		  __print_flags(__entry->op_flags, "|", XFS_DA_OP_FLAGS))
+)
+
 #define DEFINE_ATTR_EVENT(name) \
-DEFINE_EVENT(xfs_da_class, name, \
+DEFINE_EVENT(xfs_attr_class, name, \
 	TP_PROTO(struct xfs_da_args *args), \
 	TP_ARGS(args))
 DEFINE_ATTR_EVENT(xfs_attr_sf_add);
@@ -1511,10 +1553,14 @@ DEFINE_ATTR_EVENT(xfs_attr_sf_to_leaf);
 DEFINE_ATTR_EVENT(xfs_attr_leaf_add);
 DEFINE_ATTR_EVENT(xfs_attr_leaf_add_old);
 DEFINE_ATTR_EVENT(xfs_attr_leaf_add_new);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_add_work);
 DEFINE_ATTR_EVENT(xfs_attr_leaf_addname);
 DEFINE_ATTR_EVENT(xfs_attr_leaf_create);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_compact);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_get);
 DEFINE_ATTR_EVENT(xfs_attr_leaf_lookup);
 DEFINE_ATTR_EVENT(xfs_attr_leaf_replace);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_remove);
 DEFINE_ATTR_EVENT(xfs_attr_leaf_removename);
 DEFINE_ATTR_EVENT(xfs_attr_leaf_split);
 DEFINE_ATTR_EVENT(xfs_attr_leaf_split_before);
@@ -1526,12 +1572,21 @@ DEFINE_ATTR_EVENT(xfs_attr_leaf_to_sf);
 DEFINE_ATTR_EVENT(xfs_attr_leaf_to_node);
 DEFINE_ATTR_EVENT(xfs_attr_leaf_rebalance);
 DEFINE_ATTR_EVENT(xfs_attr_leaf_unbalance);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_toosmall);
 
 DEFINE_ATTR_EVENT(xfs_attr_node_addname);
+DEFINE_ATTR_EVENT(xfs_attr_node_get);
 DEFINE_ATTR_EVENT(xfs_attr_node_lookup);
 DEFINE_ATTR_EVENT(xfs_attr_node_replace);
 DEFINE_ATTR_EVENT(xfs_attr_node_removename);
 
+DEFINE_ATTR_EVENT(xfs_attr_fillstate);
+DEFINE_ATTR_EVENT(xfs_attr_refillstate);
+
+DEFINE_ATTR_EVENT(xfs_attr_rmtval_get);
+DEFINE_ATTR_EVENT(xfs_attr_rmtval_set);
+DEFINE_ATTR_EVENT(xfs_attr_rmtval_remove);
+
 #define DEFINE_DA_EVENT(name) \
 DEFINE_EVENT(xfs_da_class, name, \
 	TP_PROTO(struct xfs_da_args *args), \
@@ -1550,9 +1605,12 @@ DEFINE_DA_EVENT(xfs_da_node_split);
 DEFINE_DA_EVENT(xfs_da_node_remove);
 DEFINE_DA_EVENT(xfs_da_node_rebalance);
 DEFINE_DA_EVENT(xfs_da_node_unbalance);
+DEFINE_DA_EVENT(xfs_da_node_toosmall);
 DEFINE_DA_EVENT(xfs_da_swap_lastblock);
 DEFINE_DA_EVENT(xfs_da_grow_inode);
 DEFINE_DA_EVENT(xfs_da_shrink_inode);
+DEFINE_DA_EVENT(xfs_da_fixhashpath);
+DEFINE_DA_EVENT(xfs_da_path_shift);
 
 DECLARE_EVENT_CLASS(xfs_dir2_space_class,
 	TP_PROTO(struct xfs_da_args *args, int idx),
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index db05654..c6c0601 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -464,10 +464,7 @@ xfs_trans_get_buf(
 	int			numblks,
 	uint			flags)
 {
-	struct xfs_buf_map	map = {
-		.bm_bn = blkno,
-		.bm_len = numblks,
-	};
+	DEFINE_SINGLE_BUF_MAP(map, blkno, numblks);
 	return xfs_trans_get_buf_map(tp, target, &map, 1, flags);
 }
 
@@ -476,7 +473,8 @@ int		xfs_trans_read_buf_map(struct xfs_mount *mp,
 				       struct xfs_buftarg *target,
 				       struct xfs_buf_map *map, int nmaps,
 				       xfs_buf_flags_t flags,
-				       struct xfs_buf **bpp);
+				       struct xfs_buf **bpp,
+				       const struct xfs_buf_ops *ops);
 
 static inline int
 xfs_trans_read_buf(
@@ -486,13 +484,12 @@ xfs_trans_read_buf(
 	xfs_daddr_t		blkno,
 	int			numblks,
 	xfs_buf_flags_t		flags,
-	struct xfs_buf		**bpp)
+	struct xfs_buf		**bpp,
+	const struct xfs_buf_ops *ops)
 {
-	struct xfs_buf_map	map = {
-		.bm_bn = blkno,
-		.bm_len = numblks,
-	};
-	return xfs_trans_read_buf_map(mp, tp, target, &map, 1, flags, bpp);
+	DEFINE_SINGLE_BUF_MAP(map, blkno, numblks);
+	return xfs_trans_read_buf_map(mp, tp, target, &map, 1,
+				      flags, bpp, ops);
 }
 
 struct xfs_buf	*xfs_trans_getsb(xfs_trans_t *, struct xfs_mount *, int);
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index 6311b99..4fc17d4 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -257,7 +257,8 @@ xfs_trans_read_buf_map(
 	struct xfs_buf_map	*map,
 	int			nmaps,
 	xfs_buf_flags_t		flags,
-	struct xfs_buf		**bpp)
+	struct xfs_buf		**bpp,
+	const struct xfs_buf_ops *ops)
 {
 	xfs_buf_t		*bp;
 	xfs_buf_log_item_t	*bip;
@@ -265,7 +266,7 @@ xfs_trans_read_buf_map(
 
 	*bpp = NULL;
 	if (!tp) {
-		bp = xfs_buf_read_map(target, map, nmaps, flags);
+		bp = xfs_buf_read_map(target, map, nmaps, flags, ops);
 		if (!bp)
 			return (flags & XBF_TRYLOCK) ?
 					EAGAIN : XFS_ERROR(ENOMEM);
@@ -312,7 +313,9 @@ xfs_trans_read_buf_map(
 		if (!(XFS_BUF_ISDONE(bp))) {
 			trace_xfs_trans_read_buf_io(bp, _RET_IP_);
 			ASSERT(!XFS_BUF_ISASYNC(bp));
+			ASSERT(bp->b_iodone == NULL);
 			XFS_BUF_READ(bp);
+			bp->b_ops = ops;
 			xfsbdstrat(tp->t_mountp, bp);
 			error = xfs_buf_iowait(bp);
 			if (error) {
@@ -349,7 +352,7 @@ xfs_trans_read_buf_map(
 		return 0;
 	}
 
-	bp = xfs_buf_read_map(target, map, nmaps, flags);
+	bp = xfs_buf_read_map(target, map, nmaps, flags, ops);
 	if (bp == NULL) {
 		*bpp = NULL;
 		return (flags & XBF_TRYLOCK) ?
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 2a5c6373..2688079 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -47,6 +47,7 @@
 #include "xfs_filestream.h"
 #include "xfs_vnodeops.h"
 #include "xfs_trace.h"
+#include "xfs_icache.h"
 
 /*
  * The maximum pathlen is 1024 bytes. Since the minimum file system
@@ -79,7 +80,7 @@ xfs_readlink_bmap(
 		d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
 		byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
 
-		bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0);
+		bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0, NULL);
 		if (!bp)
 			return XFS_ERROR(ENOMEM);
 		error = bp->b_error;
@@ -150,7 +151,7 @@ xfs_readlink(
  * when the link count isn't zero and by xfs_dm_punch_hole() when
  * punching a hole to EOF.
  */
-STATIC int
+int
 xfs_free_eofblocks(
 	xfs_mount_t	*mp,
 	xfs_inode_t	*ip,
@@ -199,7 +200,7 @@ xfs_free_eofblocks(
 		if (need_iolock) {
 			if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) {
 				xfs_trans_cancel(tp, 0);
-				return 0;
+				return EAGAIN;
 			}
 		}
 
@@ -237,6 +238,8 @@ xfs_free_eofblocks(
 		} else {
 			error = xfs_trans_commit(tp,
 						XFS_TRANS_RELEASE_LOG_RES);
+			if (!error)
+				xfs_inode_clear_eofblocks_tag(ip);
 		}
 
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
@@ -425,19 +428,18 @@ xfs_release(
 		truncated = xfs_iflags_test_and_clear(ip, XFS_ITRUNCATED);
 		if (truncated) {
 			xfs_iflags_clear(ip, XFS_IDIRTY_RELEASE);
-			if (VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0)
-				xfs_flush_pages(ip, 0, -1, XBF_ASYNC, FI_NONE);
+			if (VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0) {
+				error = -filemap_flush(VFS_I(ip)->i_mapping);
+				if (error)
+					return error;
+			}
 		}
 	}
 
 	if (ip->i_d.di_nlink == 0)
 		return 0;
 
-	if ((S_ISREG(ip->i_d.di_mode) &&
-	     (VFS_I(ip)->i_size > 0 ||
-	      (VN_CACHED(VFS_I(ip)) > 0 || ip->i_delayed_blks > 0)) &&
-	     (ip->i_df.if_flags & XFS_IFEXTENTS))  &&
-	    (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) {
+	if (xfs_can_free_eofblocks(ip, false)) {
 
 		/*
 		 * If we can't get the iolock just skip truncating the blocks
@@ -464,7 +466,7 @@ xfs_release(
 			return 0;
 
 		error = xfs_free_eofblocks(mp, ip, true);
-		if (error)
+		if (error && error != EAGAIN)
 			return error;
 
 		/* delalloc blocks after truncation means it really is dirty */
@@ -513,13 +515,12 @@ xfs_inactive(
 		goto out;
 
 	if (ip->i_d.di_nlink != 0) {
-		if ((S_ISREG(ip->i_d.di_mode) &&
-		    (VFS_I(ip)->i_size > 0 ||
-		     (VN_CACHED(VFS_I(ip)) > 0 || ip->i_delayed_blks > 0)) &&
-		    (ip->i_df.if_flags & XFS_IFEXTENTS) &&
-		    (!(ip->i_d.di_flags &
-				(XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
-		     ip->i_delayed_blks != 0))) {
+		/*
+		 * force is true because we are evicting an inode from the
+		 * cache. Post-eof blocks must be freed, lest we end up with
+		 * broken free space accounting.
+		 */
+		if (xfs_can_free_eofblocks(ip, true)) {
 			error = xfs_free_eofblocks(mp, ip, false);
 			if (error)
 				return VN_INACTIVE_CACHE;
@@ -777,7 +778,7 @@ xfs_create(
 			XFS_TRANS_PERM_LOG_RES, log_count);
 	if (error == ENOSPC) {
 		/* flush outstanding delalloc blocks and retry */
-		xfs_flush_inodes(dp);
+		xfs_flush_inodes(mp);
 		error = xfs_trans_reserve(tp, resblks, log_res, 0,
 				XFS_TRANS_PERM_LOG_RES, log_count);
 	}
@@ -1957,12 +1958,11 @@ xfs_free_file_space(
 
 	rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
 	ioffset = offset & ~(rounding - 1);
-
-	if (VN_CACHED(VFS_I(ip)) != 0) {
-		error = xfs_flushinval_pages(ip, ioffset, -1, FI_REMAPF_LOCKED);
-		if (error)
-			goto out_unlock_iolock;
-	}
+	error = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
+					      ioffset, -1);
+	if (error)
+		goto out_unlock_iolock;
+	truncate_pagecache_range(VFS_I(ip), ioffset, -1);
 
 	/*
 	 * Need to zero the stuff we're not freeing, on disk.
@@ -2120,7 +2120,7 @@ xfs_change_file_space(
 	xfs_fsize_t	fsize;
 	int		setprealloc;
 	xfs_off_t	startoffset;
-	xfs_off_t	llen;
+	xfs_off_t	end;
 	xfs_trans_t	*tp;
 	struct iattr	iattr;
 	int		prealloc_type;
@@ -2141,12 +2141,30 @@ xfs_change_file_space(
 		return XFS_ERROR(EINVAL);
 	}
 
-	llen = bf->l_len > 0 ? bf->l_len - 1 : bf->l_len;
+	/*
+	 * length of <= 0 for resv/unresv/zero is invalid.  length for
+	 * alloc/free is ignored completely and we have no idea what userspace
+	 * might have set it to, so set it to zero to allow range
+	 * checks to pass.
+	 */
+	switch (cmd) {
+	case XFS_IOC_ZERO_RANGE:
+	case XFS_IOC_RESVSP:
+	case XFS_IOC_RESVSP64:
+	case XFS_IOC_UNRESVSP:
+	case XFS_IOC_UNRESVSP64:
+		if (bf->l_len <= 0)
+			return XFS_ERROR(EINVAL);
+		break;
+	default:
+		bf->l_len = 0;
+		break;
+	}
 
 	if (bf->l_start < 0 ||
 	    bf->l_start > mp->m_super->s_maxbytes ||
-	    bf->l_start + llen < 0 ||
-	    bf->l_start + llen > mp->m_super->s_maxbytes)
+	    bf->l_start + bf->l_len < 0 ||
+	    bf->l_start + bf->l_len >= mp->m_super->s_maxbytes)
 		return XFS_ERROR(EINVAL);
 
 	bf->l_whence = 0;
@@ -2171,7 +2189,9 @@ xfs_change_file_space(
 	switch (cmd) {
 	case XFS_IOC_ZERO_RANGE:
 		prealloc_type |= XFS_BMAPI_CONVERT;
-		xfs_tosspages(ip, startoffset, startoffset + bf->l_len, 0);
+		end = round_down(startoffset + bf->l_len, PAGE_SIZE) - 1;
+		if (startoffset <= end)
+			truncate_pagecache_range(VFS_I(ip), startoffset, end);
 		/* FALLTHRU */
 	case XFS_IOC_RESVSP:
 	case XFS_IOC_RESVSP64:
diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h
index 447e146..91a03fa 100644
--- a/fs/xfs/xfs_vnodeops.h
+++ b/fs/xfs/xfs_vnodeops.h
@@ -48,14 +48,8 @@ int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
 int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
 int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
 		int flags, struct attrlist_cursor_kern *cursor);
-void xfs_tosspages(struct xfs_inode *inode, xfs_off_t first,
-		xfs_off_t last, int fiopt);
-int xfs_flushinval_pages(struct xfs_inode *ip, xfs_off_t first,
-		xfs_off_t last, int fiopt);
-int xfs_flush_pages(struct xfs_inode *ip, xfs_off_t first,
-		xfs_off_t last, uint64_t flags, int fiopt);
-int xfs_wait_on_pages(struct xfs_inode *ip, xfs_off_t first, xfs_off_t last);
 
 int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t);
+int xfs_free_eofblocks(struct xfs_mount *, struct xfs_inode *, bool);
 
 #endif /* _XFS_VNODEOPS_H */
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index 03f1485..0943457 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -241,6 +241,7 @@
  *****************************************************************************/
 
 #define ACPI_DEBUGGER_MAX_ARGS          8	/* Must be max method args + 1 */
+#define ACPI_DB_LINE_BUFFER_SIZE	512
 
 #define ACPI_DEBUGGER_COMMAND_PROMPT    '-'
 #define ACPI_DEBUGGER_EXECUTE_PROMPT    '%'
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
index 1950344..6c3890e 100644
--- a/include/acpi/acexcep.h
+++ b/include/acpi/acexcep.h
@@ -122,7 +122,7 @@
 #define AE_CODE_TBL_MAX                 0x0005
 
 /*
- * AML exceptions.  These are caused by problems with
+ * AML exceptions. These are caused by problems with
  * the actual AML byte stream
  */
 #define AE_AML_BAD_OPCODE               (acpi_status) (0x0001 | AE_CODE_AML)
diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h
index 745dd24e..7665df6 100644
--- a/include/acpi/acnames.h
+++ b/include/acpi/acnames.h
@@ -50,6 +50,7 @@
 #define METHOD_NAME__HID        "_HID"
 #define METHOD_NAME__CID        "_CID"
 #define METHOD_NAME__UID        "_UID"
+#define METHOD_NAME__SUB        "_SUB"
 #define METHOD_NAME__ADR        "_ADR"
 #define METHOD_NAME__INI        "_INI"
 #define METHOD_NAME__STA        "_STA"
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 0daa0fb..7ced5dc 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -144,12 +144,11 @@ struct acpi_device_flags {
 	u32 bus_address:1;
 	u32 removable:1;
 	u32 ejectable:1;
-	u32 lockable:1;
 	u32 suprise_removal_ok:1;
 	u32 power_manageable:1;
 	u32 performance_manageable:1;
 	u32 eject_pending:1;
-	u32 reserved:23;
+	u32 reserved:24;
 };
 
 /* File System */
@@ -180,6 +179,7 @@ struct acpi_device_pnp {
 	acpi_device_name device_name;	/* Driver-determined */
 	acpi_device_class device_class;	/*        "          */
 	union acpi_object *str_obj;	/* unicode string for _STR method */
+	unsigned long sun;		/* _SUN */
 };
 
 #define acpi_device_bid(d)	((d)->pnp.bus_id)
@@ -201,6 +201,7 @@ struct acpi_device_power_flags {
 struct acpi_device_power_state {
 	struct {
 		u8 valid:1;
+		u8 os_accessible:1;
 		u8 explicit_set:1;	/* _PSx present? */
 		u8 reserved:6;
 	} flags;
@@ -339,6 +340,7 @@ acpi_status acpi_bus_get_status_handle(acpi_handle handle,
 				       unsigned long long *sta);
 int acpi_bus_get_status(struct acpi_device *device);
 int acpi_bus_set_power(acpi_handle handle, int state);
+int acpi_device_set_power(struct acpi_device *device, int state);
 int acpi_bus_update_power(acpi_handle handle, int *state_p);
 bool acpi_bus_power_manageable(acpi_handle handle);
 bool acpi_bus_can_wakeup(acpi_handle handle);
@@ -410,36 +412,100 @@ acpi_handle acpi_get_child(acpi_handle, u64);
 int acpi_is_root_bridge(acpi_handle);
 acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int);
 struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle);
-#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle))
+#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)ACPI_HANDLE(dev))
 
 int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);
 int acpi_disable_wakeup_device_power(struct acpi_device *dev);
 
 #ifdef CONFIG_PM
+acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
+				 acpi_notify_handler handler, void *context);
+acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
+				    acpi_notify_handler handler);
+int acpi_device_power_state(struct device *dev, struct acpi_device *adev,
+			    u32 target_state, int d_max_in, int *d_min_p);
 int acpi_pm_device_sleep_state(struct device *, int *, int);
 #else
-static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)
+static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
+					       acpi_notify_handler handler,
+					       void *context)
+{
+	return AE_SUPPORT;
+}
+static inline acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
+						  acpi_notify_handler handler)
+{
+	return AE_SUPPORT;
+}
+static inline int __acpi_device_power_state(int m, int *p)
 {
 	if (p)
 		*p = ACPI_STATE_D0;
 	return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3) ? m : ACPI_STATE_D0;
 }
+static inline int acpi_device_power_state(struct device *dev,
+					  struct acpi_device *adev,
+					  u32 target_state, int d_max_in,
+					  int *d_min_p)
+{
+	return __acpi_device_power_state(d_max_in, d_min_p);
+}
+static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)
+{
+	return __acpi_device_power_state(m, p);
+}
 #endif
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_RUNTIME
+int __acpi_device_run_wake(struct acpi_device *, bool);
 int acpi_pm_device_run_wake(struct device *, bool);
-int acpi_pm_device_sleep_wake(struct device *, bool);
 #else
+static inline int __acpi_device_run_wake(struct acpi_device *adev, bool en)
+{
+	return -ENODEV;
+}
 static inline int acpi_pm_device_run_wake(struct device *dev, bool enable)
 {
 	return -ENODEV;
 }
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+int __acpi_device_sleep_wake(struct acpi_device *, u32, bool);
+int acpi_pm_device_sleep_wake(struct device *, bool);
+#else
+static inline int __acpi_device_sleep_wake(struct acpi_device *adev,
+					   u32 target_state, bool enable)
+{
+	return -ENODEV;
+}
 static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
 {
 	return -ENODEV;
 }
 #endif
 
+#ifdef CONFIG_ACPI_SLEEP
+u32 acpi_target_system_state(void);
+#else
+static inline u32 acpi_target_system_state(void) { return ACPI_STATE_S0; }
+#endif
+
+static inline bool acpi_device_power_manageable(struct acpi_device *adev)
+{
+	return adev->flags.power_manageable;
+}
+
+static inline bool acpi_device_can_wakeup(struct acpi_device *adev)
+{
+	return adev->wakeup.flags.valid;
+}
+
+static inline bool acpi_device_can_poweroff(struct acpi_device *adev)
+{
+	return adev->power.states[ACPI_STATE_D3_COLD].flags.os_accessible;
+}
+
 #else	/* CONFIG_ACPI */
 
 static inline int register_acpi_bus_type(void *bus) { return 0; }
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index bb145e4..8b1d7a6 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -92,8 +92,8 @@ int acpi_pci_link_free_irq(acpi_handle handle);
 
 /* ACPI PCI Interrupt Routing (pci_irq.c) */
 
-int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus);
-void acpi_pci_irq_del_prt(struct pci_bus *bus);
+int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus);
+void acpi_pci_irq_del_prt(int segment, int bus);
 
 /* ACPI PCI Device Binding (pci_bind.c) */
 
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 1222ba9..4315274 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -1,7 +1,6 @@
-
 /******************************************************************************
  *
- * Name: acpiosxf.h - All interfaces to the OS Services Layer (OSL).  These
+ * Name: acpiosxf.h - All interfaces to the OS Services Layer (OSL). These
  *                    interfaces must be implemented by OSL to interface the
  *                    ACPI components to the host operating system.
  *
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 8b891db..3d88395 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Name: acpixf.h - External interfaces to the ACPI subsystem
@@ -47,7 +46,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20120913
+#define ACPI_CA_VERSION                 0x20121018
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
@@ -178,8 +177,7 @@ acpi_status acpi_unload_table_id(acpi_owner_id id);
 
 acpi_status
 acpi_get_table_header(acpi_string signature,
-		      u32 instance,
-		      struct acpi_table_header *out_table_header);
+		      u32 instance, struct acpi_table_header *out_table_header);
 
 acpi_status
 acpi_get_table_with_size(acpi_string signature,
@@ -190,8 +188,7 @@ acpi_get_table(acpi_string signature,
 	       u32 instance, struct acpi_table_header **out_table);
 
 acpi_status
-acpi_get_table_by_index(u32 table_index,
-			struct acpi_table_header **out_table);
+acpi_get_table_by_index(u32 table_index, struct acpi_table_header **out_table);
 
 acpi_status
 acpi_install_table_handler(acpi_tbl_handler handler, void *context);
@@ -274,7 +271,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function);
 
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
 				acpi_install_global_event_handler
-				(ACPI_GBL_EVENT_HANDLER handler, void *context))
+				(acpi_gbl_event_handler handler, void *context))
 
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
 				 acpi_install_fixed_event_handler(u32
@@ -300,10 +297,9 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
 							 u32 gpe_number,
 							 acpi_gpe_handler
 							 address))
-acpi_status
-acpi_install_notify_handler(acpi_handle device,
-			    u32 handler_type,
-			    acpi_notify_handler handler, void *context);
+acpi_status acpi_install_notify_handler(acpi_handle device, u32 handler_type,
+					acpi_notify_handler handler,
+					void *context);
 
 acpi_status
 acpi_remove_notify_handler(acpi_handle device,
diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h
index 8c61b5f..6585141 100644
--- a/include/acpi/actbl3.h
+++ b/include/acpi/actbl3.h
@@ -277,10 +277,10 @@ struct acpi_table_gtdt {
  ******************************************************************************/
 
 #define ACPI_MPST_CHANNEL_INFO \
-	u16                             reserved1; \
 	u8                              channel_id; \
-	u8                              reserved2; \
-	u16                             power_node_count;
+	u8                              reserved1[3]; \
+	u16                             power_node_count; \
+	u16                             reserved2;
 
 /* Main table */
 
@@ -304,9 +304,8 @@ struct acpi_mpst_power_node {
 	u32 length;
 	u64 range_address;
 	u64 range_length;
-	u8 num_power_states;
-	u8 num_physical_components;
-	u16 reserved2;
+	u32 num_power_states;
+	u32 num_physical_components;
 };
 
 /* Values for Flags field above */
@@ -332,10 +331,11 @@ struct acpi_mpst_component {
 
 struct acpi_mpst_data_hdr {
 	u16 characteristics_count;
+	u16 reserved;
 };
 
 struct acpi_mpst_power_data {
-	u8 revision;
+	u8 structure_id;
 	u8 flags;
 	u16 reserved1;
 	u32 average_power;
@@ -356,10 +356,10 @@ struct acpi_mpst_shared {
 	u32 signature;
 	u16 pcc_command;
 	u16 pcc_status;
-	u16 command_register;
-	u16 status_register;
-	u16 power_state_id;
-	u16 power_node_id;
+	u32 command_register;
+	u32 status_register;
+	u32 power_state_id;
+	u32 power_node_id;
 	u64 energy_consumed;
 	u64 average_power;
 };
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index a85bae9..4f43f1f 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -453,10 +453,14 @@ typedef u64 acpi_integer;
 #define ACPI_PHYSADDR_TO_PTR(i)         ACPI_TO_POINTER(i)
 #define ACPI_PTR_TO_PHYSADDR(i)         ACPI_TO_INTEGER(i)
 
+/* Optimizations for 4-character (32-bit) acpi_name manipulation */
+
 #ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
 #define ACPI_COMPARE_NAME(a,b)          (*ACPI_CAST_PTR (u32, (a)) == *ACPI_CAST_PTR (u32, (b)))
+#define ACPI_MOVE_NAME(dest,src)        (*ACPI_CAST_PTR (u32, (dest)) = *ACPI_CAST_PTR (u32, (src)))
 #else
 #define ACPI_COMPARE_NAME(a,b)          (!ACPI_STRNCMP (ACPI_CAST_PTR (char, (a)), ACPI_CAST_PTR (char, (b)), ACPI_NAME_SIZE))
+#define ACPI_MOVE_NAME(dest,src)        (ACPI_STRNCPY (ACPI_CAST_PTR (char, (dest)), ACPI_CAST_PTR (char, (src)), ACPI_NAME_SIZE))
 #endif
 
 /*******************************************************************************
@@ -796,11 +800,11 @@ typedef u8 acpi_adr_space_type;
 
 /* Sleep function dispatch */
 
-typedef acpi_status(*ACPI_SLEEP_FUNCTION) (u8 sleep_state);
+typedef acpi_status(*acpi_sleep_function) (u8 sleep_state);
 
 struct acpi_sleep_functions {
-	ACPI_SLEEP_FUNCTION legacy_function;
-	ACPI_SLEEP_FUNCTION extended_function;
+	acpi_sleep_function legacy_function;
+	acpi_sleep_function extended_function;
 };
 
 /*
@@ -922,7 +926,8 @@ struct acpi_system_info {
 /*
  * Types specific to the OS service interfaces
  */
-typedef u32(ACPI_SYSTEM_XFACE * acpi_osd_handler) (void *context);
+typedef u32
+ (ACPI_SYSTEM_XFACE * acpi_osd_handler) (void *context);
 
 typedef void
  (ACPI_SYSTEM_XFACE * acpi_osd_exec_callback) (void *context);
@@ -931,14 +936,15 @@ typedef void
  * Various handlers and callback procedures
  */
 typedef
-void (*ACPI_GBL_EVENT_HANDLER) (u32 event_type,
+void (*acpi_gbl_event_handler) (u32 event_type,
 			       acpi_handle device,
 			       u32 event_number, void *context);
 
 #define ACPI_EVENT_TYPE_GPE         0
 #define ACPI_EVENT_TYPE_FIXED       1
 
-typedef u32(*acpi_event_handler) (void *context);
+typedef
+u32(*acpi_event_handler) (void *context);
 
 typedef
 u32 (*acpi_gpe_handler) (acpi_handle gpe_device, u32 gpe_number, void *context);
@@ -1018,17 +1024,17 @@ u32 (*acpi_interface_handler) (acpi_string interface_name, u32 supported);
 
 #define ACPI_UUID_LENGTH                16
 
-/* Structures used for device/processor HID, UID, CID */
+/* Structures used for device/processor HID, UID, CID, and SUB */
 
-struct acpica_device_id {
+struct acpi_pnp_device_id {
 	u32 length;		/* Length of string + null */
 	char *string;
 };
 
-struct acpica_device_id_list {
+struct acpi_pnp_device_id_list {
 	u32 count;		/* Number of IDs in Ids array */
 	u32 list_size;		/* Size of list, including ID strings */
-	struct acpica_device_id ids[1];	/* ID array */
+	struct acpi_pnp_device_id ids[1];	/* ID array */
 };
 
 /*
@@ -1046,9 +1052,10 @@ struct acpi_device_info {
 	u8 lowest_dstates[5];	/* _sx_w values: 0xFF indicates not valid */
 	u32 current_status;	/* _STA value */
 	u64 address;	/* _ADR value */
-	struct acpica_device_id hardware_id;	/* _HID value */
-	struct acpica_device_id unique_id;	/* _UID value */
-	struct acpica_device_id_list compatible_id_list;	/* _CID list <must be last> */
+	struct acpi_pnp_device_id hardware_id;	/* _HID value */
+	struct acpi_pnp_device_id unique_id;	/* _UID value */
+	struct acpi_pnp_device_id subsystem_id;	/* _SUB value */
+	struct acpi_pnp_device_id_list compatible_id_list;	/* _CID list <must be last> */
 };
 
 /* Values for Flags field above (acpi_get_object_info) */
@@ -1061,11 +1068,12 @@ struct acpi_device_info {
 #define ACPI_VALID_ADR                  0x02
 #define ACPI_VALID_HID                  0x04
 #define ACPI_VALID_UID                  0x08
-#define ACPI_VALID_CID                  0x10
-#define ACPI_VALID_SXDS                 0x20
-#define ACPI_VALID_SXWS                 0x40
+#define ACPI_VALID_SUB                  0x10
+#define ACPI_VALID_CID                  0x20
+#define ACPI_VALID_SXDS                 0x40
+#define ACPI_VALID_SXWS                 0x80
 
-/* Flags for _STA method */
+/* Flags for _STA return value (current_status above) */
 
 #define ACPI_STA_DEVICE_PRESENT         0x01
 #define ACPI_STA_DEVICE_ENABLED         0x02
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index a9432fc..20ca766 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -5,6 +5,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/of.h>
+#include <linux/pinctrl/pinctrl.h>
 
 #ifdef CONFIG_GPIOLIB
 
@@ -56,6 +57,8 @@ struct device_node;
  *	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
@@ -100,7 +103,8 @@ struct gpio_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,
@@ -134,6 +138,15 @@ struct gpio_chip {
 	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,
@@ -257,4 +270,41 @@ static inline void gpio_unexport(unsigned gpio)
 }
 #endif	/* CONFIG_GPIO_SYSFS */
 
+#ifdef CONFIG_PINCTRL
+
+/**
+ * struct gpio_pin_range - pin range controlled by a gpio chip
+ * @head: list for maintaining set of pin ranges, used internally
+ * @pctldev: pinctrl device which handles corresponding pins
+ * @range: actual range of pins controlled by a gpio controller
+ */
+
+struct gpio_pin_range {
+	struct list_head node;
+	struct pinctrl_dev *pctldev;
+	struct pinctrl_gpio_range range;
+};
+
+int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+			   unsigned int gpio_offset, unsigned int pin_offset,
+			   unsigned int npins);
+void gpiochip_remove_pin_ranges(struct gpio_chip *chip);
+
+#else
+
+static inline int
+gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+		       unsigned int gpio_offset, unsigned int pin_offset,
+		       unsigned int npins)
+{
+	return 0;
+}
+
+static inline void
+gpiochip_remove_pin_ranges(struct gpio_chip *chip)
+{
+}
+
+#endif /* CONFIG_PINCTRL */
+
 #endif /* _ASM_GENERIC_GPIO_H */
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 448303b..616eea5 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -12,7 +12,6 @@
 #define __ASM_GENERIC_IO_H
 
 #include <asm/page.h> /* I/O is all done through memory accesses */
-#include <asm/cacheflush.h>
 #include <linux/types.h>
 
 #ifdef CONFIG_GENERIC_IOMAP
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index b36ce40..d03d0a8 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -219,6 +219,10 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
 #define move_pte(pte, prot, old_addr, new_addr)	(pte)
 #endif
 
+#ifndef pte_accessible
+# define pte_accessible(pte)		((void)(pte),1)
+#endif
+
 #ifndef flush_tlb_fix_spurious_fault
 #define flush_tlb_fix_spurious_fault(vma, address) flush_tlb_page(vma, address)
 #endif
@@ -533,6 +537,61 @@ static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd)
 }
 
 /*
+ * Is this pte used for NUMA scanning?
+ */
+#ifdef CONFIG_ARCH_USES_NUMA_GENERIC_PGPROT
+extern bool pte_numa(struct vm_area_struct *vma, pte_t pte);
+#else
+# ifndef pte_numa
+static inline bool pte_numa(struct vm_area_struct *vma, pte_t pte)
+{
+	return false;
+}
+# endif
+#endif
+
+/*
+ * Turn a pte into a NUMA entry:
+ */
+#ifdef CONFIG_ARCH_USES_NUMA_GENERIC_PGPROT
+extern pte_t pte_mknuma(struct vm_area_struct *vma, pte_t pte);
+#else
+# ifndef pte_mknuma
+static inline pte_t pte_mknuma(struct vm_area_struct *vma, pte_t pte)
+{
+	return pte;
+}
+# endif
+#endif
+
+/*
+ * Is this pmd used for NUMA scanning?
+ */
+#ifdef CONFIG_ARCH_USES_NUMA_GENERIC_PGPROT_HUGEPAGE
+extern bool pmd_numa(struct vm_area_struct *vma, pmd_t pmd);
+#else
+# ifndef pmd_numa
+static inline bool pmd_numa(struct vm_area_struct *vma, pmd_t pmd)
+{
+	return false;
+}
+# endif
+#endif
+
+/*
+ * Some architectures (such as x86) may need to preserve certain pgprot
+ * bits, without complicating generic pgprot code.
+ *
+ * Most architectures don't care:
+ */
+#ifndef pgprot_modify
+static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
+{
+	return newprot;
+}
+#endif
+
+/*
  * This is a noop if Transparent Hugepage Support is not built into
  * the kernel. Otherwise it is equivalent to
  * pmd_none_or_trans_huge_or_clear_bad(), and shall only be called in
diff --git a/include/asm-generic/signal.h b/include/asm-generic/signal.h
index 98caa30..d840c90 100644
--- a/include/asm-generic/signal.h
+++ b/include/asm-generic/signal.h
@@ -10,7 +10,5 @@
 #include <asm/sigcontext.h>
 #undef __HAVE_ARCH_SIG_BITOPS
 
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_GENERIC_SIGNAL_H */
diff --git a/include/asm-generic/syscalls.h b/include/asm-generic/syscalls.h
index d89dec8..7796033 100644
--- a/include/asm-generic/syscalls.h
+++ b/include/asm-generic/syscalls.h
@@ -10,23 +10,15 @@
  */
 #ifndef sys_clone
 asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
-			void __user *parent_tid, void __user *child_tid,
-			struct pt_regs *regs);
+			void __user *parent_tid, void __user *child_tid);
 #endif
 
 #ifndef sys_fork
-asmlinkage long sys_fork(struct pt_regs *regs);
+asmlinkage long sys_fork(void);
 #endif
 
 #ifndef sys_vfork
-asmlinkage long sys_vfork(struct pt_regs *regs);
-#endif
-
-#ifndef sys_execve
-asmlinkage long sys_execve(const char __user *filename,
-			   const char __user *const __user *argv,
-			   const char __user *const __user *envp,
-			   struct pt_regs *regs);
+asmlinkage long sys_vfork(void);
 #endif
 
 #ifndef sys_mmap2
diff --git a/include/asm-generic/trace_clock.h b/include/asm-generic/trace_clock.h
new file mode 100644
index 0000000..6726f1b
--- /dev/null
+++ b/include/asm-generic/trace_clock.h
@@ -0,0 +1,16 @@
+#ifndef _ASM_GENERIC_TRACE_CLOCK_H
+#define _ASM_GENERIC_TRACE_CLOCK_H
+/*
+ * Arch-specific trace clocks.
+ */
+
+/*
+ * Additional trace clocks added to the trace_clocks
+ * array in kernel/trace/trace.c
+ * None if the architecture has not defined it.
+ */
+#ifndef ARCH_TRACE_CLOCKS
+# define ARCH_TRACE_CLOCKS
+#endif
+
+#endif  /* _ASM_GENERIC_TRACE_CLOCK_H */
diff --git a/include/crypto/vmac.h b/include/crypto/vmac.h
index c4467c5..6b700c7 100644
--- a/include/crypto/vmac.h
+++ b/include/crypto/vmac.h
@@ -56,6 +56,8 @@ typedef u64 vmac_t;
 struct vmac_ctx_t {
 	struct crypto_cipher *child;
 	struct vmac_ctx __vmac_ctx;
+	u8 partial[VMAC_NHBYTES];	/* partial block */
+	int partial_size;		/* size of the partial block */
 };
 
 #endif /* __CRYPTO_VMAC_H */
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 3fd8280..fad21c9 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1431,6 +1431,8 @@ extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
 extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
 extern u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
 				     struct timeval *vblanktime);
+extern void drm_send_vblank_event(struct drm_device *dev, int crtc,
+				     struct drm_pending_vblank_event *e);
 extern bool drm_handle_vblank(struct drm_device *dev, int crtc);
 extern int drm_vblank_get(struct drm_device *dev, int crtc);
 extern void drm_vblank_put(struct drm_device *dev, int crtc);
@@ -1503,6 +1505,7 @@ extern unsigned int drm_debug;
 
 extern unsigned int drm_vblank_offdelay;
 extern unsigned int drm_timestamp_precision;
+extern unsigned int drm_timestamp_monotonic;
 
 extern struct class *drm_class;
 extern struct proc_dir_entry *drm_proc_root;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 3fa18b7..c0635b7 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -792,6 +792,7 @@ struct drm_mode_config {
 
 	/* output poll support */
 	bool poll_enabled;
+	bool poll_running;
 	struct delayed_work output_poll_work;
 
 	/* pointers to standard properties */
@@ -887,14 +888,14 @@ extern void drm_mode_remove(struct drm_connector *connector, struct drm_display_
 extern void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src);
 extern struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
 						   const struct drm_display_mode *mode);
-extern void drm_mode_debug_printmodeline(struct drm_display_mode *mode);
+extern void drm_mode_debug_printmodeline(const struct drm_display_mode *mode);
 extern void drm_mode_config_init(struct drm_device *dev);
 extern void drm_mode_config_reset(struct drm_device *dev);
 extern void drm_mode_config_cleanup(struct drm_device *dev);
 extern void drm_mode_set_name(struct drm_display_mode *mode);
-extern bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2);
-extern int drm_mode_width(struct drm_display_mode *mode);
-extern int drm_mode_height(struct drm_display_mode *mode);
+extern bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2);
+extern int drm_mode_width(const struct drm_display_mode *mode);
+extern int drm_mode_height(const struct drm_display_mode *mode);
 
 /* for us by fb module */
 extern int drm_mode_attachmode_crtc(struct drm_device *dev,
@@ -1037,6 +1038,7 @@ extern int drm_mode_gamma_get_ioctl(struct drm_device *dev,
 extern int drm_mode_gamma_set_ioctl(struct drm_device *dev,
 				    void *data, struct drm_file *file_priv);
 extern u8 *drm_find_cea_extension(struct edid *edid);
+extern u8 drm_match_cea_mode(struct drm_display_mode *to_match);
 extern bool drm_detect_hdmi_monitor(struct edid *edid);
 extern bool drm_detect_monitor_audio(struct edid *edid);
 extern int drm_mode_page_flip_ioctl(struct drm_device *dev,
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index e01cc80..f43d556 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -137,6 +137,8 @@ extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
 
 extern void drm_helper_connector_dpms(struct drm_connector *connector, int mode);
 
+extern void drm_helper_move_panel_connectors_to_head(struct drm_device *);
+
 extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
 					  struct drm_mode_fb_cmd2 *mode_cmd);
 
@@ -162,6 +164,7 @@ extern int drm_helper_resume_force_mode(struct drm_device *dev);
 extern void drm_kms_helper_poll_init(struct drm_device *dev);
 extern void drm_kms_helper_poll_fini(struct drm_device *dev);
 extern void drm_helper_hpd_irq_event(struct drm_device *dev);
+extern void drm_kms_helper_hotplug_event(struct drm_device *dev);
 
 extern void drm_kms_helper_poll_disable(struct drm_device *dev);
 extern void drm_kms_helper_poll_enable(struct drm_device *dev);
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index fe06148..e8e1417 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -25,6 +25,7 @@
 
 #include <linux/types.h>
 #include <linux/i2c.h>
+#include <linux/delay.h>
 
 /*
  * Unless otherwise noted, all values are from the DP 1.1a spec.  Note that
@@ -311,6 +312,14 @@
 #define MODE_I2C_READ	4
 #define MODE_I2C_STOP	8
 
+/**
+ * struct i2c_algo_dp_aux_data - driver interface structure for i2c over dp
+ * 				 aux algorithm
+ * @running: set by the algo indicating whether an i2c is ongoing or whether
+ * 	     the i2c bus is quiescent
+ * @address: i2c target address for the currently ongoing transfer
+ * @aux_ch: driver callback to transfer a single byte of the i2c payload
+ */
 struct i2c_algo_dp_aux_data {
 	bool running;
 	u16 address;
@@ -322,4 +331,34 @@ struct i2c_algo_dp_aux_data {
 int
 i2c_dp_aux_add_bus(struct i2c_adapter *adapter);
 
+
+#define DP_LINK_STATUS_SIZE	   6
+bool drm_dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE],
+			  int lane_count);
+bool drm_dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE],
+			      int lane_count);
+u8 drm_dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE],
+				     int lane);
+u8 drm_dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE],
+					  int lane);
+
+#define DP_RECEIVER_CAP_SIZE	0xf
+void drm_dp_link_train_clock_recovery_delay(u8 dpcd[DP_RECEIVER_CAP_SIZE]);
+void drm_dp_link_train_channel_eq_delay(u8 dpcd[DP_RECEIVER_CAP_SIZE]);
+
+u8 drm_dp_link_rate_to_bw_code(int link_rate);
+int drm_dp_bw_code_to_link_rate(u8 link_bw);
+
+static inline int
+drm_dp_max_link_rate(u8 dpcd[DP_RECEIVER_CAP_SIZE])
+{
+	return drm_dp_bw_code_to_link_rate(dpcd[DP_MAX_LINK_RATE]);
+}
+
+static inline u8
+drm_dp_max_lane_count(u8 dpcd[DP_RECEIVER_CAP_SIZE])
+{
+	return dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;
+}
+
 #endif /* _DRM_DP_HELPER_H_ */
diff --git a/include/drm/drm_hashtab.h b/include/drm/drm_hashtab.h
index 3650d5d..fce2ef3 100644
--- a/include/drm/drm_hashtab.h
+++ b/include/drm/drm_hashtab.h
@@ -61,5 +61,19 @@ extern int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key);
 extern int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item);
 extern void drm_ht_remove(struct drm_open_hash *ht);
 
+/*
+ * RCU-safe interface
+ *
+ * The user of this API needs to make sure that two or more instances of the
+ * hash table manipulation functions are never run simultaneously.
+ * The lookup function drm_ht_find_item_rcu may, however, run simultaneously
+ * with any of the manipulation functions as long as it's called from within
+ * an RCU read-locked section.
+ */
+#define drm_ht_insert_item_rcu drm_ht_insert_item
+#define drm_ht_just_insert_please_rcu drm_ht_just_insert_please
+#define drm_ht_remove_key_rcu drm_ht_remove_key
+#define drm_ht_remove_item_rcu drm_ht_remove_item
+#define drm_ht_find_item_rcu drm_ht_find_item
 
 #endif
diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h
index 2e37e9f..6eb76a1 100644
--- a/include/drm/intel-gtt.h
+++ b/include/drm/intel-gtt.h
@@ -3,7 +3,7 @@
 #ifndef _DRM_INTEL_GTT_H
 #define	_DRM_INTEL_GTT_H
 
-const struct intel_gtt {
+struct intel_gtt {
 	/* Size of memory reserved for graphics by the BIOS */
 	unsigned int stolen_size;
 	/* Total number of gtt entries. */
@@ -17,6 +17,7 @@ const struct intel_gtt {
 	unsigned int do_idle_maps : 1;
 	/* Share the scratch page dma with ppgtts. */
 	dma_addr_t scratch_page_dma;
+	struct page *scratch_page;
 	/* for ppgtt PDE access */
 	u32 __iomem *gtt;
 	/* needed for ioremap in drm/i915 */
@@ -39,10 +40,6 @@ void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries);
 #define AGP_DCACHE_MEMORY	1
 #define AGP_PHYS_MEMORY		2
 
-/* New caching attributes for gen6/sandybridge */
-#define AGP_USER_CACHED_MEMORY_LLC_MLC (AGP_USER_TYPES + 2)
-#define AGP_USER_UNCACHED_MEMORY (AGP_USER_TYPES + 4)
-
 /* flag for GFDT type */
 #define AGP_USER_CACHED_MEMORY_GFDT (1 << 3)
 
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
index e8028ad..c6cae73 100644
--- a/include/drm/ttm/ttm_bo_api.h
+++ b/include/drm/ttm/ttm_bo_api.h
@@ -141,8 +141,6 @@ struct ttm_tt;
  * struct ttm_buffer_object
  *
  * @bdev: Pointer to the buffer object device structure.
- * @buffer_start: The virtual user-space start address of ttm_bo_type_user
- * buffers.
  * @type: The bo type.
  * @destroy: Destruction function. If NULL, kfree is used.
  * @num_pages: Actual number of pages.
@@ -172,7 +170,6 @@ struct ttm_tt;
  * @seq_valid: The value of @val_seq is valid. This value is protected by
  * the bo_device::lru_lock.
  * @reserved: Deadlock-free lock used for synchronization state transitions.
- * @sync_obj_arg: Opaque argument to synchronization object function.
  * @sync_obj: Pointer to a synchronization object.
  * @priv_flags: Flags describing buffer object internal state.
  * @vm_rb: Rb node for the vm rb tree.
@@ -200,7 +197,6 @@ struct ttm_buffer_object {
 
 	struct ttm_bo_global *glob;
 	struct ttm_bo_device *bdev;
-	unsigned long buffer_start;
 	enum ttm_bo_type type;
 	void (*destroy) (struct ttm_buffer_object *);
 	unsigned long num_pages;
@@ -255,7 +251,6 @@ struct ttm_buffer_object {
 	 * checking NULL while reserved but not holding the mentioned lock.
 	 */
 
-	void *sync_obj_arg;
 	void *sync_obj;
 	unsigned long priv_flags;
 
@@ -429,8 +424,9 @@ extern void ttm_bo_unlock_delayed_workqueue(struct ttm_bo_device *bdev,
  * @no_wait: Return immediately if buffer is busy.
  *
  * Synchronizes a buffer object for CPU RW access. This means
- * blocking command submission that affects the buffer and
- * waiting for buffer idle. This lock is recursive.
+ * command submission that affects the buffer will return -EBUSY
+ * until ttm_bo_synccpu_write_release is called.
+ *
  * Returns
  * -EBUSY if the buffer is busy and no_wait is true.
  * -ERESTARTSYS if interrupted by a signal.
@@ -472,8 +468,6 @@ size_t ttm_bo_dma_acc_size(struct ttm_bo_device *bdev,
  * @type: Requested type of buffer object.
  * @flags: Initial placement flags.
  * @page_alignment: Data alignment in pages.
- * @buffer_start: Virtual address of user space data backing a
- * user buffer object.
  * @interruptible: If needing to sleep to wait for GPU resources,
  * sleep interruptible.
  * @persistent_swap_storage: Usually the swap storage is deleted for buffers
@@ -505,7 +499,6 @@ extern int ttm_bo_init(struct ttm_bo_device *bdev,
 			enum ttm_bo_type type,
 			struct ttm_placement *placement,
 			uint32_t page_alignment,
-			unsigned long buffer_start,
 			bool interrubtible,
 			struct file *persistent_swap_storage,
 			size_t acc_size,
@@ -521,8 +514,6 @@ extern int ttm_bo_init(struct ttm_bo_device *bdev,
  * @type: Requested type of buffer object.
  * @flags: Initial placement flags.
  * @page_alignment: Data alignment in pages.
- * @buffer_start: Virtual address of user space data backing a
- * user buffer object.
  * @interruptible: If needing to sleep while waiting for GPU resources,
  * sleep interruptible.
  * @persistent_swap_storage: Usually the swap storage is deleted for buffers
@@ -545,7 +536,6 @@ extern int ttm_bo_create(struct ttm_bo_device *bdev,
 				enum ttm_bo_type type,
 				struct ttm_placement *placement,
 				uint32_t page_alignment,
-				unsigned long buffer_start,
 				bool interruptible,
 				struct file *persistent_swap_storage,
 				struct ttm_buffer_object **p_bo);
@@ -736,4 +726,18 @@ extern ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp,
 
 extern void ttm_bo_swapout_all(struct ttm_bo_device *bdev);
 
+/**
+ * ttm_bo_is_reserved - return an indication if a ttm buffer object is reserved
+ *
+ * @bo:     The buffer object to check.
+ *
+ * This function returns an indication if a bo is reserved or not, and should
+ * only be used to print an error when it is not from incorrect api usage, since
+ * there's no guarantee that it is the caller that is holding the reservation.
+ */
+static inline bool ttm_bo_is_reserved(struct ttm_buffer_object *bo)
+{
+	return atomic_read(&bo->reserved);
+}
+
 #endif
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index d803b92..dd96442 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -422,10 +422,10 @@ struct ttm_bo_driver {
 	 * documentation.
 	 */
 
-	bool (*sync_obj_signaled) (void *sync_obj, void *sync_arg);
-	int (*sync_obj_wait) (void *sync_obj, void *sync_arg,
+	bool (*sync_obj_signaled) (void *sync_obj);
+	int (*sync_obj_wait) (void *sync_obj,
 			      bool lazy, bool interruptible);
-	int (*sync_obj_flush) (void *sync_obj, void *sync_arg);
+	int (*sync_obj_flush) (void *sync_obj);
 	void (*sync_obj_unref) (void **sync_obj);
 	void *(*sync_obj_ref) (void *sync_obj);
 
@@ -521,8 +521,6 @@ struct ttm_bo_global {
  * lru_lock: Spinlock that protects the buffer+device lru lists and
  * ddestroy lists.
  * @val_seq: Current validation sequence.
- * @nice_mode: Try nicely to wait for buffer idle when cleaning a manager.
- * If a GPU lockup has been detected, this is forced to 0.
  * @dev_mapping: A pointer to the struct address_space representing the
  * device address space.
  * @wq: Work queue structure for the delayed delete workqueue.
@@ -556,7 +554,6 @@ struct ttm_bo_device {
 	 * Protected by load / firstopen / lastclose /unload sync.
 	 */
 
-	bool nice_mode;
 	struct address_space *dev_mapping;
 
 	/*
@@ -729,20 +726,6 @@ extern void ttm_bo_mem_put(struct ttm_buffer_object *bo,
 extern void ttm_bo_mem_put_locked(struct ttm_buffer_object *bo,
 				  struct ttm_mem_reg *mem);
 
-/**
- * ttm_bo_wait_for_cpu
- *
- * @bo: Pointer to a struct ttm_buffer_object.
- * @no_wait: Don't sleep while waiting.
- *
- * Wait until a buffer object is no longer sync'ed for CPU access.
- * Returns:
- * -EBUSY: Buffer object was sync'ed for CPU access. (only if no_wait == 1).
- * -ERESTARTSYS: An interruptible sleep was interrupted by a signal.
- */
-
-extern int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool no_wait);
-
 extern void ttm_bo_global_release(struct drm_global_reference *ref);
 extern int ttm_bo_global_init(struct drm_global_reference *ref);
 
@@ -973,8 +956,6 @@ extern void ttm_bo_free_old_node(struct ttm_buffer_object *bo);
  *
  * @bo: A pointer to a struct ttm_buffer_object.
  * @sync_obj: A sync object that signals when moving is complete.
- * @sync_obj_arg: An argument to pass to the sync object idle / wait
- * functions.
  * @evict: This is an evict move. Don't return until the buffer is idle.
  * @no_wait_reserve: Return immediately if other buffers are busy.
  * @no_wait_gpu: Return immediately if the GPU is busy.
@@ -990,7 +971,6 @@ extern void ttm_bo_free_old_node(struct ttm_buffer_object *bo);
 
 extern int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
 				     void *sync_obj,
-				     void *sync_obj_arg,
 				     bool evict, bool no_wait_reserve,
 				     bool no_wait_gpu,
 				     struct ttm_mem_reg *new_mem);
diff --git a/include/drm/ttm/ttm_execbuf_util.h b/include/drm/ttm/ttm_execbuf_util.h
index 1926cae..547e19f 100644
--- a/include/drm/ttm/ttm_execbuf_util.h
+++ b/include/drm/ttm/ttm_execbuf_util.h
@@ -39,8 +39,6 @@
  *
  * @head:           list head for thread-private list.
  * @bo:             refcounted buffer object pointer.
- * @new_sync_obj_arg: New sync_obj_arg for @bo, to be used once
- * adding a new sync object.
  * @reserved:       Indicates whether @bo has been reserved for validation.
  * @removed:        Indicates whether @bo has been removed from lru lists.
  * @put_count:      Number of outstanding references on bo::list_kref.
@@ -50,7 +48,6 @@
 struct ttm_validate_buffer {
 	struct list_head head;
 	struct ttm_buffer_object *bo;
-	void *new_sync_obj_arg;
 	bool reserved;
 	bool removed;
 	int put_count;
diff --git a/include/drm/ttm/ttm_memory.h b/include/drm/ttm/ttm_memory.h
index d6d1da4..72dcbe8 100644
--- a/include/drm/ttm/ttm_memory.h
+++ b/include/drm/ttm/ttm_memory.h
@@ -60,7 +60,6 @@ struct ttm_mem_shrink {
  * for the GPU, and this will otherwise block other workqueue tasks(?)
  * At this point we use only a single-threaded workqueue.
  * @work: The workqueue callback for the shrink queue.
- * @queue: Wait queue for processes suspended waiting for memory.
  * @lock: Lock to protect the @shrink - and the memory accounting members,
  * that is, essentially the whole structure with some exceptions.
  * @zones: Array of pointers to accounting zones.
@@ -80,7 +79,6 @@ struct ttm_mem_global {
 	struct ttm_mem_shrink *shrink;
 	struct workqueue_struct *swap_queue;
 	struct work_struct work;
-	wait_queue_head_t queue;
 	spinlock_t lock;
 	struct ttm_mem_zone *zones[TTM_MEM_MAX_ZONES];
 	unsigned int num_zones;
diff --git a/include/drm/ttm/ttm_object.h b/include/drm/ttm/ttm_object.h
index b01c563..fc0cf06 100644
--- a/include/drm/ttm/ttm_object.h
+++ b/include/drm/ttm/ttm_object.h
@@ -40,6 +40,7 @@
 #include <linux/list.h>
 #include <drm/drm_hashtab.h>
 #include <linux/kref.h>
+#include <linux/rcupdate.h>
 #include <ttm/ttm_memory.h>
 
 /**
@@ -120,6 +121,7 @@ struct ttm_object_device;
  */
 
 struct ttm_base_object {
+	struct rcu_head rhead;
 	struct drm_hash_item hash;
 	enum ttm_object_type object_type;
 	bool shareable;
@@ -268,4 +270,6 @@ extern struct ttm_object_device *ttm_object_device_init
 
 extern void ttm_object_device_release(struct ttm_object_device **p_tdev);
 
+#define ttm_base_object_kfree(__object, __base)\
+	kfree_rcu(__object, __base.rhead)
 #endif
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 90be989..179382f 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -25,7 +25,9 @@
 #ifndef _LINUX_ACPI_H
 #define _LINUX_ACPI_H
 
+#include <linux/errno.h>
 #include <linux/ioport.h>	/* for struct resource */
+#include <linux/device.h>
 
 #ifdef	CONFIG_ACPI
 
@@ -76,6 +78,14 @@ typedef int (*acpi_table_handler) (struct acpi_table_header *table);
 
 typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
 
+#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+void acpi_initrd_override(void *data, size_t size);
+#else
+static inline void acpi_initrd_override(void *data, size_t size)
+{
+}
+#endif
+
 char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
 void __acpi_unmap_table(char *map, unsigned long size);
 int early_acpi_boot_init(void);
@@ -250,6 +260,26 @@ extern int pnpacpi_disabled;
 
 #define PXM_INVAL	(-1)
 
+bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res);
+bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res);
+bool acpi_dev_resource_address_space(struct acpi_resource *ares,
+				     struct resource *res);
+bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
+					 struct resource *res);
+unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable);
+bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
+				 struct resource *res);
+
+struct resource_list_entry {
+	struct list_head node;
+	struct resource res;
+};
+
+void acpi_dev_free_resource_list(struct list_head *list);
+int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
+			   int (*preproc)(struct acpi_resource *, void *),
+			   void *preproc_data);
+
 int acpi_check_resource_conflict(const struct resource *res);
 
 int acpi_check_region(resource_size_t start, resource_size_t n,
@@ -257,10 +287,14 @@ int acpi_check_region(resource_size_t start, resource_size_t n,
 
 int acpi_resources_are_enforced(void);
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_HIBERNATION
 void __init acpi_no_s4_hw_signature(void);
+#endif
+
+#ifdef CONFIG_PM_SLEEP
 void __init acpi_old_suspend_ordering(void);
 void __init acpi_nvs_nosave(void);
+void __init acpi_nvs_nosave_s3(void);
 #endif /* CONFIG_PM_SLEEP */
 
 struct acpi_osc_context {
@@ -364,6 +398,17 @@ extern int acpi_nvs_register(__u64 start, __u64 size);
 extern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
 				    void *data);
 
+const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
+					       const struct device *dev);
+
+static inline bool acpi_driver_match_device(struct device *dev,
+					    const struct device_driver *drv)
+{
+	return !!acpi_match_device(drv->acpi_match_table, dev);
+}
+
+#define ACPI_PTR(_ptr)	(_ptr)
+
 #else	/* !CONFIG_ACPI */
 
 #define acpi_disabled 1
@@ -418,6 +463,22 @@ static inline int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
 	return 0;
 }
 
+struct acpi_device_id;
+
+static inline const struct acpi_device_id *acpi_match_device(
+	const struct acpi_device_id *ids, const struct device *dev)
+{
+	return NULL;
+}
+
+static inline bool acpi_driver_match_device(struct device *dev,
+					    const struct device_driver *drv)
+{
+	return false;
+}
+
+#define ACPI_PTR(_ptr)	(NULL)
+
 #endif	/* !CONFIG_ACPI */
 
 #ifdef CONFIG_ACPI
@@ -426,8 +487,96 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
 
 acpi_status acpi_os_prepare_sleep(u8 sleep_state,
 				  u32 pm1a_control, u32 pm1b_control);
+#ifdef CONFIG_X86
+void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
+#else
+static inline void arch_reserve_mem_area(acpi_physical_address addr,
+					  size_t size)
+{
+}
+#endif /* CONFIG_X86 */
 #else
 #define acpi_os_set_prepare_sleep(func, pm1a_ctrl, pm1b_ctrl) do { } while (0)
 #endif
 
+#if defined(CONFIG_ACPI) && defined(CONFIG_PM_RUNTIME)
+int acpi_dev_runtime_suspend(struct device *dev);
+int acpi_dev_runtime_resume(struct device *dev);
+int acpi_subsys_runtime_suspend(struct device *dev);
+int acpi_subsys_runtime_resume(struct device *dev);
+#else
+static inline int acpi_dev_runtime_suspend(struct device *dev) { return 0; }
+static inline int acpi_dev_runtime_resume(struct device *dev) { return 0; }
+static inline int acpi_subsys_runtime_suspend(struct device *dev) { return 0; }
+static inline int acpi_subsys_runtime_resume(struct device *dev) { return 0; }
+#endif
+
+#ifdef CONFIG_ACPI_SLEEP
+int acpi_dev_suspend_late(struct device *dev);
+int acpi_dev_resume_early(struct device *dev);
+int acpi_subsys_prepare(struct device *dev);
+int acpi_subsys_suspend_late(struct device *dev);
+int acpi_subsys_resume_early(struct device *dev);
+#else
+static inline int acpi_dev_suspend_late(struct device *dev) { return 0; }
+static inline int acpi_dev_resume_early(struct device *dev) { return 0; }
+static inline int acpi_subsys_prepare(struct device *dev) { return 0; }
+static inline int acpi_subsys_suspend_late(struct device *dev) { return 0; }
+static inline int acpi_subsys_resume_early(struct device *dev) { return 0; }
+#endif
+
+#if defined(CONFIG_ACPI) && defined(CONFIG_PM)
+int acpi_dev_pm_attach(struct device *dev, bool power_on);
+int acpi_dev_pm_detach(struct device *dev, bool power_off);
+#else
+static inline int acpi_dev_pm_attach(struct device *dev, bool power_on)
+{
+	return -ENODEV;
+}
+static inline void acpi_dev_pm_detach(struct device *dev, bool power_off) {}
+#endif
+
+#ifdef CONFIG_ACPI
+__printf(3, 4)
+void acpi_handle_printk(const char *level, acpi_handle handle,
+			const char *fmt, ...);
+#else	/* !CONFIG_ACPI */
+static inline __printf(3, 4) void
+acpi_handle_printk(const char *level, void *handle, const char *fmt, ...) {}
+#endif	/* !CONFIG_ACPI */
+
+/*
+ * acpi_handle_<level>: Print message with ACPI prefix and object path
+ *
+ * These interfaces acquire the global namespace mutex to obtain an object
+ * path.  In interrupt context, it shows the object path as <n/a>.
+ */
+#define acpi_handle_emerg(handle, fmt, ...)				\
+	acpi_handle_printk(KERN_EMERG, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_alert(handle, fmt, ...)				\
+	acpi_handle_printk(KERN_ALERT, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_crit(handle, fmt, ...)				\
+	acpi_handle_printk(KERN_CRIT, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_err(handle, fmt, ...)				\
+	acpi_handle_printk(KERN_ERR, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_warn(handle, fmt, ...)				\
+	acpi_handle_printk(KERN_WARNING, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_notice(handle, fmt, ...)				\
+	acpi_handle_printk(KERN_NOTICE, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_info(handle, fmt, ...)				\
+	acpi_handle_printk(KERN_INFO, handle, fmt, ##__VA_ARGS__)
+
+/* REVISIT: Support CONFIG_DYNAMIC_DEBUG when necessary */
+#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
+#define acpi_handle_debug(handle, fmt, ...)				\
+	acpi_handle_printk(KERN_DEBUG, handle, fmt, ##__VA_ARGS__)
+#else
+#define acpi_handle_debug(handle, fmt, ...)				\
+({									\
+	if (0)								\
+		acpi_handle_printk(KERN_DEBUG, handle, fmt, ##__VA_ARGS__); \
+	0;								\
+})
+#endif
+
 #endif	/*_LINUX_ACPI_H*/
diff --git a/include/linux/acpi_gpio.h b/include/linux/acpi_gpio.h
new file mode 100644
index 0000000..91615a3
--- /dev/null
+++ b/include/linux/acpi_gpio.h
@@ -0,0 +1,19 @@
+#ifndef _LINUX_ACPI_GPIO_H_
+#define _LINUX_ACPI_GPIO_H_
+
+#include <linux/errno.h>
+
+#ifdef CONFIG_GPIO_ACPI
+
+int acpi_get_gpio(char *path, int pin);
+
+#else /* CONFIG_GPIO_ACPI */
+
+static inline int acpi_get_gpio(char *path, int pin)
+{
+	return -ENODEV;
+}
+
+#endif /* CONFIG_GPIO_ACPI */
+
+#endif /* _LINUX_ACPI_GPIO_H_ */
diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
index 4eb3175..deb0ae5 100644
--- a/include/linux/atmel-ssc.h
+++ b/include/linux/atmel-ssc.h
@@ -5,10 +5,16 @@
 #include <linux/list.h>
 #include <linux/io.h>
 
+struct atmel_ssc_platform_data {
+	int			use_dma;
+};
+
 struct ssc_device {
 	struct list_head	list;
+	resource_size_t		phybase;
 	void __iomem		*regs;
 	struct platform_device	*pdev;
+	struct atmel_ssc_platform_data *pdata;
 	struct clk		*clk;
 	int			user;
 	int			irq;
diff --git a/include/linux/audit.h b/include/linux/audit.h
index bce729a..9d5104d 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -157,7 +157,8 @@ void audit_core_dumps(long signr);
 
 static inline void audit_seccomp(unsigned long syscall, long signr, int code)
 {
-	if (unlikely(!audit_dummy_context()))
+	/* Force a record to be reported if a signal was delivered. */
+	if (signr || unlikely(!audit_dummy_context()))
 		__audit_seccomp(syscall, signr, code);
 }
 
diff --git a/include/linux/backlight.h b/include/linux/backlight.h
index 5ffc6dd..da9a082 100644
--- a/include/linux/backlight.h
+++ b/include/linux/backlight.h
@@ -134,4 +134,14 @@ struct generic_bl_info {
 	void (*kick_battery)(void);
 };
 
+#ifdef CONFIG_OF
+struct backlight_device *of_find_backlight_by_node(struct device_node *node);
+#else
+static inline struct backlight_device *
+of_find_backlight_by_node(struct device_node *node)
+{
+	return NULL;
+}
+#endif
+
 #endif
diff --git a/include/linux/balloon_compaction.h b/include/linux/balloon_compaction.h
new file mode 100644
index 0000000..634a19b
--- /dev/null
+++ b/include/linux/balloon_compaction.h
@@ -0,0 +1,280 @@
+/*
+ * include/linux/balloon_compaction.h
+ *
+ * Common interface definitions for making balloon pages movable by compaction.
+ *
+ * Despite being perfectly possible to perform ballooned pages migration, they
+ * make a special corner case to compaction scans because balloon pages are not
+ * enlisted at any LRU list like the other pages we do compact / migrate.
+ *
+ * As the page isolation scanning step a compaction thread does is a lockless
+ * procedure (from a page standpoint), it might bring some racy situations while
+ * performing balloon page compaction. In order to sort out these racy scenarios
+ * and safely perform balloon's page compaction and migration we must, always,
+ * ensure following these three simple rules:
+ *
+ *   i. when updating a balloon's page ->mapping element, strictly do it under
+ *      the following lock order, independently of the far superior
+ *      locking scheme (lru_lock, balloon_lock):
+ *	    +-page_lock(page);
+ *	      +--spin_lock_irq(&b_dev_info->pages_lock);
+ *	            ... page->mapping updates here ...
+ *
+ *  ii. before isolating or dequeueing a balloon page from the balloon device
+ *      pages list, the page reference counter must be raised by one and the
+ *      extra refcount must be dropped when the page is enqueued back into
+ *      the balloon device page list, thus a balloon page keeps its reference
+ *      counter raised only while it is under our special handling;
+ *
+ * iii. after the lockless scan step have selected a potential balloon page for
+ *      isolation, re-test the page->mapping flags and the page ref counter
+ *      under the proper page lock, to ensure isolating a valid balloon page
+ *      (not yet isolated, nor under release procedure)
+ *
+ * The functions provided by this interface are placed to help on coping with
+ * the aforementioned balloon page corner case, as well as to ensure the simple
+ * set of exposed rules are satisfied while we are dealing with balloon pages
+ * compaction / migration.
+ *
+ * Copyright (C) 2012, Red Hat, Inc.  Rafael Aquini <aquini@redhat.com>
+ */
+#ifndef _LINUX_BALLOON_COMPACTION_H
+#define _LINUX_BALLOON_COMPACTION_H
+#include <linux/pagemap.h>
+#include <linux/migrate.h>
+#include <linux/gfp.h>
+#include <linux/err.h>
+
+/*
+ * Balloon device information descriptor.
+ * This struct is used to allow the common balloon compaction interface
+ * procedures to find the proper balloon device holding memory pages they'll
+ * have to cope for page compaction / migration, as well as it serves the
+ * balloon driver as a page book-keeper for its registered balloon devices.
+ */
+struct balloon_dev_info {
+	void *balloon_device;		/* balloon device descriptor */
+	struct address_space *mapping;	/* balloon special page->mapping */
+	unsigned long isolated_pages;	/* # of isolated pages for migration */
+	spinlock_t pages_lock;		/* Protection to pages list */
+	struct list_head pages;		/* Pages enqueued & handled to Host */
+};
+
+extern struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info);
+extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info);
+extern struct balloon_dev_info *balloon_devinfo_alloc(
+						void *balloon_dev_descriptor);
+
+static inline void balloon_devinfo_free(struct balloon_dev_info *b_dev_info)
+{
+	kfree(b_dev_info);
+}
+
+/*
+ * balloon_page_free - release a balloon page back to the page free lists
+ * @page: ballooned page to be set free
+ *
+ * This function must be used to properly set free an isolated/dequeued balloon
+ * page at the end of a sucessful page migration, or at the balloon driver's
+ * page release procedure.
+ */
+static inline void balloon_page_free(struct page *page)
+{
+	/*
+	 * Balloon pages always get an extra refcount before being isolated
+	 * and before being dequeued to help on sorting out fortuite colisions
+	 * between a thread attempting to isolate and another thread attempting
+	 * to release the very same balloon page.
+	 *
+	 * Before we handle the page back to Buddy, lets drop its extra refcnt.
+	 */
+	put_page(page);
+	__free_page(page);
+}
+
+#ifdef CONFIG_BALLOON_COMPACTION
+extern bool balloon_page_isolate(struct page *page);
+extern void balloon_page_putback(struct page *page);
+extern int balloon_page_migrate(struct page *newpage,
+				struct page *page, enum migrate_mode mode);
+extern struct address_space
+*balloon_mapping_alloc(struct balloon_dev_info *b_dev_info,
+			const struct address_space_operations *a_ops);
+
+static inline void balloon_mapping_free(struct address_space *balloon_mapping)
+{
+	kfree(balloon_mapping);
+}
+
+/*
+ * __balloon_page_flags - helper to perform balloon @page ->flags tests.
+ *
+ * As balloon pages are got from Buddy, and we do not play with page->flags
+ * at driver level (exception made when we get the page lock for compaction),
+ * therefore we can safely identify a ballooned page by checking if the
+ * NR_PAGEFLAGS rightmost bits from the page->flags are all cleared.
+ * This approach also helps on skipping ballooned pages that are locked for
+ * compaction or release, thus mitigating their racy check at
+ * balloon_page_movable()
+ */
+#define BALLOON_PAGE_FLAGS_MASK       ((1UL << NR_PAGEFLAGS) - 1)
+static inline bool __balloon_page_flags(struct page *page)
+{
+	return page->flags & BALLOON_PAGE_FLAGS_MASK ? false : true;
+}
+
+/*
+ * __is_movable_balloon_page - helper to perform @page mapping->flags tests
+ */
+static inline bool __is_movable_balloon_page(struct page *page)
+{
+	struct address_space *mapping = page->mapping;
+	return mapping_balloon(mapping);
+}
+
+/*
+ * balloon_page_movable - test page->mapping->flags to identify balloon pages
+ *			  that can be moved by compaction/migration.
+ *
+ * This function is used at core compaction's page isolation scheme, therefore
+ * most pages exposed to it are not enlisted as balloon pages and so, to avoid
+ * undesired side effects like racing against __free_pages(), we cannot afford
+ * holding the page locked while testing page->mapping->flags here.
+ *
+ * As we might return false positives in the case of a balloon page being just
+ * released under us, the page->mapping->flags need to be re-tested later,
+ * under the proper page lock, at the functions that will be coping with the
+ * balloon page case.
+ */
+static inline bool balloon_page_movable(struct page *page)
+{
+	/*
+	 * Before dereferencing and testing mapping->flags, lets make sure
+	 * this is not a page that uses ->mapping in a different way
+	 */
+	if (__balloon_page_flags(page) && !page_mapped(page) &&
+	    page_count(page) == 1)
+		return __is_movable_balloon_page(page);
+
+	return false;
+}
+
+/*
+ * balloon_page_insert - insert a page into the balloon's page list and make
+ *		         the page->mapping assignment accordingly.
+ * @page    : page to be assigned as a 'balloon page'
+ * @mapping : allocated special 'balloon_mapping'
+ * @head    : balloon's device page list head
+ *
+ * Caller must ensure the page is locked and the spin_lock protecting balloon
+ * pages list is held before inserting a page into the balloon device.
+ */
+static inline void balloon_page_insert(struct page *page,
+				       struct address_space *mapping,
+				       struct list_head *head)
+{
+	page->mapping = mapping;
+	list_add(&page->lru, head);
+}
+
+/*
+ * balloon_page_delete - delete a page from balloon's page list and clear
+ *			 the page->mapping assignement accordingly.
+ * @page    : page to be released from balloon's page list
+ *
+ * Caller must ensure the page is locked and the spin_lock protecting balloon
+ * pages list is held before deleting a page from the balloon device.
+ */
+static inline void balloon_page_delete(struct page *page)
+{
+	page->mapping = NULL;
+	list_del(&page->lru);
+}
+
+/*
+ * balloon_page_device - get the b_dev_info descriptor for the balloon device
+ *			 that enqueues the given page.
+ */
+static inline struct balloon_dev_info *balloon_page_device(struct page *page)
+{
+	struct address_space *mapping = page->mapping;
+	if (likely(mapping))
+		return mapping->private_data;
+
+	return NULL;
+}
+
+static inline gfp_t balloon_mapping_gfp_mask(void)
+{
+	return GFP_HIGHUSER_MOVABLE;
+}
+
+static inline bool balloon_compaction_check(void)
+{
+	return true;
+}
+
+static inline void balloon_event_count(enum vm_event_item item)
+{
+	count_vm_event(item);
+}
+#else /* !CONFIG_BALLOON_COMPACTION */
+
+/* A macro, to avoid generating references to the undefined COMPACTBALLOON* */
+#define balloon_event_count(item) do { } while (0)
+
+static inline void *balloon_mapping_alloc(void *balloon_device,
+				const struct address_space_operations *a_ops)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline void balloon_mapping_free(struct address_space *balloon_mapping)
+{
+	return;
+}
+
+static inline void balloon_page_insert(struct page *page,
+				       struct address_space *mapping,
+				       struct list_head *head)
+{
+	list_add(&page->lru, head);
+}
+
+static inline void balloon_page_delete(struct page *page)
+{
+	list_del(&page->lru);
+}
+
+static inline bool balloon_page_movable(struct page *page)
+{
+	return false;
+}
+
+static inline bool balloon_page_isolate(struct page *page)
+{
+	return false;
+}
+
+static inline void balloon_page_putback(struct page *page)
+{
+	return;
+}
+
+static inline int balloon_page_migrate(struct page *newpage,
+				struct page *page, enum migrate_mode mode)
+{
+	return 0;
+}
+
+static inline gfp_t balloon_mapping_gfp_mask(void)
+{
+	return GFP_HIGHUSER;
+}
+
+static inline bool balloon_compaction_check(void)
+{
+	return false;
+}
+#endif /* CONFIG_BALLOON_COMPACTION */
+#endif /* _LINUX_BALLOON_COMPACTION_H */
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 4180eb7..e0ce311 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -157,6 +157,7 @@ struct bcma_host_ops {
 
 /* Chip IDs of SoCs */
 #define BCMA_CHIP_ID_BCM4706	0x5300
+#define  BCMA_PKG_ID_BCM4706L	1
 #define BCMA_CHIP_ID_BCM4716	0x4716
 #define  BCMA_PKG_ID_BCM4716	8
 #define  BCMA_PKG_ID_BCM4717	9
@@ -166,7 +167,11 @@ struct bcma_host_ops {
 #define BCMA_CHIP_ID_BCM4749	0x4749
 #define BCMA_CHIP_ID_BCM5356	0x5356
 #define BCMA_CHIP_ID_BCM5357	0x5357
+#define  BCMA_PKG_ID_BCM5358	9
+#define  BCMA_PKG_ID_BCM47186	10
+#define  BCMA_PKG_ID_BCM5357	11
 #define BCMA_CHIP_ID_BCM53572	53572
+#define  BCMA_PKG_ID_BCM47188	9
 
 struct bcma_device {
 	struct bcma_bus *bus;
@@ -251,7 +256,7 @@ struct bcma_bus {
 	u8 num;
 
 	struct bcma_drv_cc drv_cc;
-	struct bcma_drv_pci drv_pci;
+	struct bcma_drv_pci drv_pci[2];
 	struct bcma_drv_mips drv_mips;
 	struct bcma_drv_gmac_cmn drv_gmac_cmn;
 
@@ -345,6 +350,7 @@ extern void bcma_core_set_clockmode(struct bcma_device *core,
 				    enum bcma_clkmode clkmode);
 extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status,
 			      bool on);
+extern u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset);
 #define BCMA_DMA_TRANSLATION_MASK	0xC0000000
 #define  BCMA_DMA_TRANSLATION_NONE	0x00000000
 #define  BCMA_DMA_TRANSLATION_DMA32_CMT	0x40000000 /* Client Mode Translation for 32-bit DMA */
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index 1cf1749..a74e33f 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -1,6 +1,8 @@
 #ifndef LINUX_BCMA_DRIVER_CC_H_
 #define LINUX_BCMA_DRIVER_CC_H_
 
+#include <linux/gpio.h>
+
 /** ChipCommon core registers. **/
 #define BCMA_CC_ID			0x0000
 #define  BCMA_CC_ID_ID			0x0000FFFF
@@ -510,6 +512,7 @@ struct bcma_chipcommon_pmu {
 
 #ifdef CONFIG_BCMA_DRIVER_MIPS
 struct bcma_pflash {
+	bool present;
 	u8 buswidth;
 	u32 window;
 	u32 window_size;
@@ -532,6 +535,7 @@ struct mtd_info;
 
 struct bcma_nflash {
 	bool present;
+	bool boot;		/* This is the flash the SoC boots from */
 
 	struct mtd_info *mtd;
 };
@@ -552,6 +556,7 @@ struct bcma_drv_cc {
 	u32 capabilities;
 	u32 capabilities_ext;
 	u8 setup_done:1;
+	u8 early_setup_done:1;
 	/* Fast Powerup Delay constant */
 	u16 fast_pwrup_delay;
 	struct bcma_chipcommon_pmu pmu;
@@ -567,6 +572,12 @@ struct bcma_drv_cc {
 	int nr_serial_ports;
 	struct bcma_serial_port serial_ports[4];
 #endif /* CONFIG_BCMA_DRIVER_MIPS */
+
+	/* Lock for GPIO register access. */
+	spinlock_t gpio_lock;
+#ifdef CONFIG_BCMA_DRIVER_GPIO
+	struct gpio_chip gpio;
+#endif
 };
 
 /* Register access */
@@ -583,6 +594,7 @@ struct bcma_drv_cc {
 	bcma_cc_write32(cc, offset, (bcma_cc_read32(cc, offset) & (mask)) | (set))
 
 extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc);
+extern void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc);
 
 extern void bcma_chipco_suspend(struct bcma_drv_cc *cc);
 extern void bcma_chipco_resume(struct bcma_drv_cc *cc);
@@ -603,9 +615,12 @@ u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value);
 u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value);
 u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value);
 u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value);
+u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value);
+u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value);
 
 /* PMU support */
 extern void bcma_pmu_init(struct bcma_drv_cc *cc);
+extern void bcma_pmu_early_init(struct bcma_drv_cc *cc);
 
 extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset,
 				  u32 value);
diff --git a/include/linux/bcma/bcma_driver_mips.h b/include/linux/bcma/bcma_driver_mips.h
index c004364..0baf8a5 100644
--- a/include/linux/bcma/bcma_driver_mips.h
+++ b/include/linux/bcma/bcma_driver_mips.h
@@ -35,13 +35,16 @@ struct bcma_device;
 struct bcma_drv_mips {
 	struct bcma_device *core;
 	u8 setup_done:1;
+	u8 early_setup_done:1;
 	unsigned int assigned_irqs;
 };
 
 #ifdef CONFIG_BCMA_DRIVER_MIPS
 extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
+extern void bcma_core_mips_early_init(struct bcma_drv_mips *mcore);
 #else
 static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { }
+static inline void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) { }
 #endif
 
 extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore);
diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h
index 6c9cb93..7e8104b 100644
--- a/include/linux/bcma/bcma_regs.h
+++ b/include/linux/bcma/bcma_regs.h
@@ -85,6 +85,9 @@
 							 * (2 ZettaBytes), high 32 bits
 							 */
 
-#define BCMA_SFLASH			0x1c000000
+#define BCMA_SOC_FLASH1			0x1fc00000	/* MIPS Flash Region 1 */
+#define BCMA_SOC_FLASH1_SZ		0x00400000	/* MIPS Size of Flash Region 1 */
+#define BCMA_SOC_FLASH2			0x1c000000	/* Flash Region 2 (region 1 shadowed here) */
+#define BCMA_SOC_FLASH2_SZ		0x02000000	/* Size of Flash Region 2 */
 
 #endif /* LINUX_BCMA_REGS_H_ */
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index cfcc6bf..bdf3965 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -54,8 +54,6 @@ struct linux_binprm {
 #define BINPRM_FLAGS_EXECFD_BIT 1
 #define BINPRM_FLAGS_EXECFD (1 << BINPRM_FLAGS_EXECFD_BIT)
 
-#define BINPRM_MAX_RECURSION 4
-
 /* Function parameter for binfmt->coredump */
 struct coredump_params {
 	siginfo_t *siginfo;
@@ -72,7 +70,7 @@ struct coredump_params {
 struct linux_binfmt {
 	struct list_head lh;
 	struct module *module;
-	int (*load_binary)(struct linux_binprm *, struct  pt_regs * regs);
+	int (*load_binary)(struct linux_binprm *);
 	int (*load_shlib)(struct file *);
 	int (*core_dump)(struct coredump_params *cprm);
 	unsigned long min_coredump;	/* minimal dump size */
@@ -95,7 +93,7 @@ extern void unregister_binfmt(struct linux_binfmt *);
 
 extern int prepare_binprm(struct linux_binprm *);
 extern int __must_check remove_arg_zero(struct linux_binprm *);
-extern int search_binary_handler(struct linux_binprm *, struct pt_regs *);
+extern int search_binary_handler(struct linux_binprm *);
 extern int flush_old_exec(struct linux_binprm * bprm);
 extern void setup_new_exec(struct linux_binprm * bprm);
 extern void would_dump(struct linux_binprm *, struct file *);
@@ -114,6 +112,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm,
 			   unsigned long stack_top,
 			   int executable_stack);
 extern int bprm_mm_init(struct linux_binprm *bprm);
+extern int bprm_change_interp(char *interp, struct linux_binprm *bprm);
 extern int copy_strings_kernel(int argc, const char *const *argv,
 			       struct linux_binprm *bprm);
 extern int prepare_bprm_creds(struct linux_binprm *bprm);
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index 6d6795d..7b74452 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -51,8 +51,8 @@ extern unsigned long free_all_bootmem(void);
 extern void free_bootmem_node(pg_data_t *pgdat,
 			      unsigned long addr,
 			      unsigned long size);
-extern void free_bootmem(unsigned long addr, unsigned long size);
-extern void free_bootmem_late(unsigned long addr, unsigned long size);
+extern void free_bootmem(unsigned long physaddr, unsigned long size);
+extern void free_bootmem_late(unsigned long physaddr, unsigned long size);
 
 /*
  * Flags for reserve_bootmem (also if CONFIG_HAVE_ARCH_BOOTMEM_NODE,
diff --git a/include/linux/bug.h b/include/linux/bug.h
index aaac4bb..b1cf40d 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -15,6 +15,7 @@ struct pt_regs;
 #define BUILD_BUG_ON_NOT_POWER_OF_2(n)
 #define BUILD_BUG_ON_ZERO(e) (0)
 #define BUILD_BUG_ON_NULL(e) ((void*)0)
+#define BUILD_BUG_ON_INVALID(e) (0)
 #define BUILD_BUG_ON(condition)
 #define BUILD_BUG() (0)
 #else /* __CHECKER__ */
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index f8a030c..7d73905 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -12,6 +12,7 @@
 #include <linux/cpumask.h>
 #include <linux/nodemask.h>
 #include <linux/rcupdate.h>
+#include <linux/rculist.h>
 #include <linux/cgroupstats.h>
 #include <linux/prio_heap.h>
 #include <linux/rwsem.h>
@@ -34,7 +35,6 @@ extern int cgroup_lock_is_held(void);
 extern bool cgroup_lock_live_group(struct cgroup *cgrp);
 extern void cgroup_unlock(void);
 extern void cgroup_fork(struct task_struct *p);
-extern void cgroup_fork_callbacks(struct task_struct *p);
 extern void cgroup_post_fork(struct task_struct *p);
 extern void cgroup_exit(struct task_struct *p, int run_callbacks);
 extern int cgroupstats_build(struct cgroupstats *stats,
@@ -66,7 +66,7 @@ struct cgroup_subsys_state {
 	/*
 	 * State maintained by the cgroup system to allow subsystems
 	 * to be "busy". Should be accessed via css_get(),
-	 * css_tryget() and and css_put().
+	 * css_tryget() and css_put().
 	 */
 
 	atomic_t refcnt;
@@ -81,9 +81,8 @@ struct cgroup_subsys_state {
 
 /* bits in struct cgroup_subsys_state flags field */
 enum {
-	CSS_ROOT, /* This CSS is the root of the subsystem */
-	CSS_REMOVED, /* This CSS is dead */
-	CSS_CLEAR_CSS_REFS,		/* @ss->__DEPRECATED_clear_css_refs */
+	CSS_ROOT	= (1 << 0), /* this CSS is the root of the subsystem */
+	CSS_ONLINE	= (1 << 1), /* between ->css_online() and ->css_offline() */
 };
 
 /* Caller must verify that the css is not for root cgroup */
@@ -102,15 +101,10 @@ static inline void __css_get(struct cgroup_subsys_state *css, int count)
 static inline void css_get(struct cgroup_subsys_state *css)
 {
 	/* We don't need to reference count the root state */
-	if (!test_bit(CSS_ROOT, &css->flags))
+	if (!(css->flags & CSS_ROOT))
 		__css_get(css, 1);
 }
 
-static inline bool css_is_removed(struct cgroup_subsys_state *css)
-{
-	return test_bit(CSS_REMOVED, &css->flags);
-}
-
 /*
  * Call css_tryget() to take a reference on a css if your existing
  * (known-valid) reference isn't already ref-counted. Returns false if
@@ -120,7 +114,7 @@ static inline bool css_is_removed(struct cgroup_subsys_state *css)
 extern bool __css_tryget(struct cgroup_subsys_state *css);
 static inline bool css_tryget(struct cgroup_subsys_state *css)
 {
-	if (test_bit(CSS_ROOT, &css->flags))
+	if (css->flags & CSS_ROOT)
 		return true;
 	return __css_tryget(css);
 }
@@ -133,7 +127,7 @@ static inline bool css_tryget(struct cgroup_subsys_state *css)
 extern void __css_put(struct cgroup_subsys_state *css);
 static inline void css_put(struct cgroup_subsys_state *css)
 {
-	if (!test_bit(CSS_ROOT, &css->flags))
+	if (!(css->flags & CSS_ROOT))
 		__css_put(css);
 }
 
@@ -149,13 +143,11 @@ enum {
 	/* Control Group requires release notifications to userspace */
 	CGRP_NOTIFY_ON_RELEASE,
 	/*
-	 * A thread in rmdir() is wating for this cgroup.
-	 */
-	CGRP_WAIT_ON_RMDIR,
-	/*
-	 * Clone cgroup values when creating a new child cgroup
+	 * Clone the parent's configuration when creating a new child
+	 * cpuset cgroup.  For historical reasons, this option can be
+	 * specified at mount time and thus is implemented here.
 	 */
-	CGRP_CLONE_CHILDREN,
+	CGRP_CPUSET_CLONE_CHILDREN,
 };
 
 struct cgroup {
@@ -167,6 +159,8 @@ struct cgroup {
 	 */
 	atomic_t count;
 
+	int id;				/* ida allocated in-hierarchy ID */
+
 	/*
 	 * We link our 'sibling' struct into our parent's 'children'.
 	 * Our children link their 'sibling' into our 'children'.
@@ -176,7 +170,7 @@ struct cgroup {
 	struct list_head files;		/* my files */
 
 	struct cgroup *parent;		/* my parent */
-	struct dentry __rcu *dentry;	/* cgroup fs entry, RCU protected */
+	struct dentry *dentry;		/* cgroup fs entry, RCU protected */
 
 	/* Private pointers for each registered subsystem */
 	struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
@@ -282,7 +276,7 @@ struct cgroup_map_cb {
 
 /* cftype->flags */
 #define CFTYPE_ONLY_ON_ROOT	(1U << 0)	/* only create on root cg */
-#define CFTYPE_NOT_ON_ROOT	(1U << 1)	/* don't create onp root cg */
+#define CFTYPE_NOT_ON_ROOT	(1U << 1)	/* don't create on root cg */
 
 #define MAX_CFTYPE_NAME		64
 
@@ -422,23 +416,6 @@ int cgroup_task_count(const struct cgroup *cgrp);
 int cgroup_is_descendant(const struct cgroup *cgrp, struct task_struct *task);
 
 /*
- * When the subsys has to access css and may add permanent refcnt to css,
- * it should take care of racy conditions with rmdir(). Following set of
- * functions, is for stop/restart rmdir if necessary.
- * Because these will call css_get/put, "css" should be alive css.
- *
- *  cgroup_exclude_rmdir();
- *  ...do some jobs which may access arbitrary empty cgroup
- *  cgroup_release_and_wakeup_rmdir();
- *
- *  When someone removes a cgroup while cgroup_exclude_rmdir() holds it,
- *  it sleeps and cgroup_release_and_wakeup_rmdir() will wake him up.
- */
-
-void cgroup_exclude_rmdir(struct cgroup_subsys_state *css);
-void cgroup_release_and_wakeup_rmdir(struct cgroup_subsys_state *css);
-
-/*
  * Control Group taskset, used to pass around set of tasks to cgroup_subsys
  * methods.
  */
@@ -466,16 +443,17 @@ int cgroup_taskset_size(struct cgroup_taskset *tset);
  */
 
 struct cgroup_subsys {
-	struct cgroup_subsys_state *(*create)(struct cgroup *cgrp);
-	int (*pre_destroy)(struct cgroup *cgrp);
-	void (*destroy)(struct cgroup *cgrp);
+	struct cgroup_subsys_state *(*css_alloc)(struct cgroup *cgrp);
+	int (*css_online)(struct cgroup *cgrp);
+	void (*css_offline)(struct cgroup *cgrp);
+	void (*css_free)(struct cgroup *cgrp);
+
 	int (*can_attach)(struct cgroup *cgrp, struct cgroup_taskset *tset);
 	void (*cancel_attach)(struct cgroup *cgrp, struct cgroup_taskset *tset);
 	void (*attach)(struct cgroup *cgrp, struct cgroup_taskset *tset);
 	void (*fork)(struct task_struct *task);
 	void (*exit)(struct cgroup *cgrp, struct cgroup *old_cgrp,
 		     struct task_struct *task);
-	void (*post_clone)(struct cgroup *cgrp);
 	void (*bind)(struct cgroup *root);
 
 	int subsys_id;
@@ -489,17 +467,6 @@ struct cgroup_subsys {
 	bool use_id;
 
 	/*
-	 * If %true, cgroup removal will try to clear css refs by retrying
-	 * ss->pre_destroy() until there's no css ref left.  This behavior
-	 * is strictly for backward compatibility and will be removed as
-	 * soon as the current user (memcg) is updated.
-	 *
-	 * If %false, ss->pre_destroy() can't fail and cgroup removal won't
-	 * wait for css refs to drop to zero before proceeding.
-	 */
-	bool __DEPRECATED_clear_css_refs;
-
-	/*
 	 * If %false, this subsystem is properly hierarchical -
 	 * configuration, resource accounting and restriction on a parent
 	 * cgroup cover those of its children.  If %true, hierarchy support
@@ -572,6 +539,100 @@ static inline struct cgroup* task_cgroup(struct task_struct *task,
 	return task_subsys_state(task, subsys_id)->cgroup;
 }
 
+/**
+ * cgroup_for_each_child - iterate through children of a cgroup
+ * @pos: the cgroup * to use as the loop cursor
+ * @cgroup: cgroup whose children to walk
+ *
+ * Walk @cgroup's children.  Must be called under rcu_read_lock().  A child
+ * cgroup which hasn't finished ->css_online() or already has finished
+ * ->css_offline() may show up during traversal and it's each subsystem's
+ * responsibility to verify that each @pos is alive.
+ *
+ * If a subsystem synchronizes against the parent in its ->css_online() and
+ * before starting iterating, a cgroup which finished ->css_online() is
+ * guaranteed to be visible in the future iterations.
+ */
+#define cgroup_for_each_child(pos, cgroup)				\
+	list_for_each_entry_rcu(pos, &(cgroup)->children, sibling)
+
+struct cgroup *cgroup_next_descendant_pre(struct cgroup *pos,
+					  struct cgroup *cgroup);
+
+/**
+ * cgroup_for_each_descendant_pre - pre-order walk of a cgroup's descendants
+ * @pos: the cgroup * to use as the loop cursor
+ * @cgroup: cgroup whose descendants to walk
+ *
+ * Walk @cgroup's descendants.  Must be called under rcu_read_lock().  A
+ * descendant cgroup which hasn't finished ->css_online() or already has
+ * finished ->css_offline() may show up during traversal and it's each
+ * subsystem's responsibility to verify that each @pos is alive.
+ *
+ * If a subsystem synchronizes against the parent in its ->css_online() and
+ * before starting iterating, and synchronizes against @pos on each
+ * iteration, any descendant cgroup which finished ->css_offline() is
+ * guaranteed to be visible in the future iterations.
+ *
+ * In other words, the following guarantees that a descendant can't escape
+ * state updates of its ancestors.
+ *
+ * my_online(@cgrp)
+ * {
+ *	Lock @cgrp->parent and @cgrp;
+ *	Inherit state from @cgrp->parent;
+ *	Unlock both.
+ * }
+ *
+ * my_update_state(@cgrp)
+ * {
+ *	Lock @cgrp;
+ *	Update @cgrp's state;
+ *	Unlock @cgrp;
+ *
+ *	cgroup_for_each_descendant_pre(@pos, @cgrp) {
+ *		Lock @pos;
+ *		Verify @pos is alive and inherit state from @pos->parent;
+ *		Unlock @pos;
+ *	}
+ * }
+ *
+ * As long as the inheriting step, including checking the parent state, is
+ * enclosed inside @pos locking, double-locking the parent isn't necessary
+ * while inheriting.  The state update to the parent is guaranteed to be
+ * visible by walking order and, as long as inheriting operations to the
+ * same @pos are atomic to each other, multiple updates racing each other
+ * still result in the correct state.  It's guaranateed that at least one
+ * inheritance happens for any cgroup after the latest update to its
+ * parent.
+ *
+ * If checking parent's state requires locking the parent, each inheriting
+ * iteration should lock and unlock both @pos->parent and @pos.
+ *
+ * Alternatively, a subsystem may choose to use a single global lock to
+ * synchronize ->css_online() and ->css_offline() against tree-walking
+ * operations.
+ */
+#define cgroup_for_each_descendant_pre(pos, cgroup)			\
+	for (pos = cgroup_next_descendant_pre(NULL, (cgroup)); (pos);	\
+	     pos = cgroup_next_descendant_pre((pos), (cgroup)))
+
+struct cgroup *cgroup_next_descendant_post(struct cgroup *pos,
+					   struct cgroup *cgroup);
+
+/**
+ * cgroup_for_each_descendant_post - post-order walk of a cgroup's descendants
+ * @pos: the cgroup * to use as the loop cursor
+ * @cgroup: cgroup whose descendants to walk
+ *
+ * Similar to cgroup_for_each_descendant_pre() but performs post-order
+ * traversal instead.  Note that the walk visibility guarantee described in
+ * pre-order walk doesn't apply the same to post-order walks.
+ */
+#define cgroup_for_each_descendant_post(pos, cgroup)			\
+	for (pos = cgroup_next_descendant_post(NULL, (cgroup)); (pos);	\
+	     pos = cgroup_next_descendant_post((pos), (cgroup)))
+
 /* A cgroup_iter should be treated as an opaque object */
 struct cgroup_iter {
 	struct list_head *cg_link;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index f9f5e9e..d64f31f 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -53,9 +53,13 @@ struct clk_hw;
  * @disable:	Disable the clock atomically. Called with enable_lock held.
  * 		This function must not sleep.
  *
- * @recalc_rate	Recalculate the rate of this clock, by quering hardware.  The
+ * @is_enabled:	Queries the hardware to determine if the clock is enabled.
+ * 		This function must not sleep. Optional, if this op is not
+ * 		set then the enable count will be used.
+ *
+ * @recalc_rate	Recalculate the rate of this clock, by querying hardware. The
  * 		parent rate is an input parameter.  It is up to the caller to
- * 		insure that the prepare_mutex is held across this call.
+ * 		ensure that the prepare_mutex is held across this call.
  * 		Returns the calculated rate.  Optional, but recommended - if
  * 		this op is not set then clock rate will be initialized to 0.
  *
@@ -89,7 +93,7 @@ struct clk_hw;
  * implementations to split any work between atomic (enable) and sleepable
  * (prepare) contexts.  If enabling a clock requires code that might sleep,
  * this must be done in clk_prepare.  Clock enable code that will never be
- * called in a sleepable context may be implement in clk_enable.
+ * called in a sleepable context may be implemented in clk_enable.
  *
  * Typically, drivers will call clk_prepare when a clock may be needed later
  * (eg. when a device is opened), and clk_enable when the clock is actually
@@ -327,19 +331,21 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
  * error code; drivers must test for an error code after calling clk_register.
  */
 struct clk *clk_register(struct device *dev, struct clk_hw *hw);
+struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
 
 void clk_unregister(struct clk *clk);
+void devm_clk_unregister(struct device *dev, struct clk *clk);
 
 /* helper functions */
 const char *__clk_get_name(struct clk *clk);
 struct clk_hw *__clk_get_hw(struct clk *clk);
 u8 __clk_get_num_parents(struct clk *clk);
 struct clk *__clk_get_parent(struct clk *clk);
-int __clk_get_enable_count(struct clk *clk);
-int __clk_get_prepare_count(struct clk *clk);
+unsigned int __clk_get_enable_count(struct clk *clk);
+unsigned int __clk_get_prepare_count(struct clk *clk);
 unsigned long __clk_get_rate(struct clk *clk);
 unsigned long __clk_get_flags(struct clk *clk);
-int __clk_is_enabled(struct clk *clk);
+bool __clk_is_enabled(struct clk *clk);
 struct clk *__clk_lookup(const char *name);
 
 /*
diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h
new file mode 100644
index 0000000..e074fdd
--- /dev/null
+++ b/include/linux/clk/sunxi.h
@@ -0,0 +1,22 @@
+/*
+ * 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/clk/zynq.h b/include/linux/clk/zynq.h
new file mode 100644
index 0000000..56be7cd
--- /dev/null
+++ b/include/linux/clk/zynq.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2012 National Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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_CLK_ZYNQ_H_
+#define __LINUX_CLK_ZYNQ_H_
+
+void __init xilinx_zynq_clocks_init(void __iomem *slcr);
+
+#endif
diff --git a/include/linux/compat.h b/include/linux/compat.h
index d0ced10..e4920bd 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -284,12 +284,8 @@ asmlinkage ssize_t compat_sys_pwritev(unsigned long fd,
 		const struct compat_iovec __user *vec,
 		unsigned long vlen, u32 pos_low, u32 pos_high);
 
-int compat_do_execve(const char *filename, const compat_uptr_t __user *argv,
-		     const compat_uptr_t __user *envp, struct pt_regs *regs);
-#ifdef __ARCH_WANT_SYS_EXECVE
 asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv,
 		     const compat_uptr_t __user *envp);
-#endif
 
 asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
 		compat_ulong_t __user *outp, compat_ulong_t __user *exp,
@@ -592,6 +588,9 @@ asmlinkage ssize_t compat_sys_process_vm_writev(compat_pid_t pid,
 asmlinkage long compat_sys_sendfile(int out_fd, int in_fd,
 				    compat_off_t __user *offset, compat_size_t count);
 
+asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid,
+						 struct compat_timespec __user *interval);
+
 #else
 
 #define is_compat_task() (0)
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index f430e41..b121554 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -10,6 +10,7 @@
 # define __force	__attribute__((force))
 # define __nocast	__attribute__((nocast))
 # define __iomem	__attribute__((noderef, address_space(2)))
+# define __must_hold(x)	__attribute__((context(x,1,1)))
 # define __acquires(x)	__attribute__((context(x,0,1)))
 # define __releases(x)	__attribute__((context(x,1,0)))
 # define __acquire(x)	__context__(x,1)
@@ -33,6 +34,7 @@ extern void __chk_io_ptr(const volatile void __iomem *);
 # define __chk_user_ptr(x) (void)0
 # define __chk_io_ptr(x) (void)0
 # define __builtin_warning(x, y...) (1)
+# define __must_hold(x)
 # define __acquires(x)
 # define __releases(x)
 # define __acquire(x) (void)0
diff --git a/include/linux/context_tracking.h b/include/linux/context_tracking.h
new file mode 100644
index 0000000..e24339c
--- /dev/null
+++ b/include/linux/context_tracking.h
@@ -0,0 +1,18 @@
+#ifndef _LINUX_CONTEXT_TRACKING_H
+#define _LINUX_CONTEXT_TRACKING_H
+
+#ifdef CONFIG_CONTEXT_TRACKING
+#include <linux/sched.h>
+
+extern void user_enter(void);
+extern void user_exit(void);
+extern void context_tracking_task_switch(struct task_struct *prev,
+					 struct task_struct *next);
+#else
+static inline void user_enter(void) { }
+static inline void user_exit(void) { }
+static inline void context_tracking_task_switch(struct task_struct *prev,
+						struct task_struct *next) { }
+#endif /* !CONFIG_CONTEXT_TRACKING */
+
+#endif
diff --git a/include/linux/coredump.h b/include/linux/coredump.h
index 1d73993..a98f1ca 100644
--- a/include/linux/coredump.h
+++ b/include/linux/coredump.h
@@ -13,9 +13,9 @@
 extern int dump_write(struct file *file, const void *addr, int nr);
 extern int dump_seek(struct file *file, loff_t off);
 #ifdef CONFIG_COREDUMP
-extern void do_coredump(siginfo_t *siginfo, struct pt_regs *regs);
+extern void do_coredump(siginfo_t *siginfo);
 #else
-static inline void do_coredump(siginfo_t *siginfo, struct pt_regs *regs) {}
+static inline void do_coredump(siginfo_t *siginfo) {}
 #endif
 
 #endif /* _LINUX_COREDUMP_H */
diff --git a/include/linux/cpu_cooling.h b/include/linux/cpu_cooling.h
index 8515301..40b4ef5 100644
--- a/include/linux/cpu_cooling.h
+++ b/include/linux/cpu_cooling.h
@@ -29,13 +29,13 @@
 #define CPUFREQ_COOLING_START		0
 #define CPUFREQ_COOLING_STOP		1
 
-#ifdef CONFIG_CPU_THERMAL
+#if defined(CONFIG_CPU_THERMAL) || defined(CONFIG_CPU_THERMAL_MODULE)
 /**
  * cpufreq_cooling_register - function to create cpufreq cooling device.
  * @clip_cpus: cpumask of cpus where the frequency constraints will happen
  */
 struct thermal_cooling_device *cpufreq_cooling_register(
-		struct cpumask *clip_cpus);
+		const struct cpumask *clip_cpus);
 
 /**
  * cpufreq_cooling_unregister - function to remove cpufreq cooling device.
@@ -44,7 +44,7 @@ struct thermal_cooling_device *cpufreq_cooling_register(
 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev);
 #else /* !CONFIG_CPU_THERMAL */
 static inline struct thermal_cooling_device *cpufreq_cooling_register(
-	struct cpumask *clip_cpus)
+	const struct cpumask *clip_cpus)
 {
 	return NULL;
 }
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index b60f6ba..a55b88e 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -11,6 +11,7 @@
 #ifndef _LINUX_CPUFREQ_H
 #define _LINUX_CPUFREQ_H
 
+#include <asm/cputime.h>
 #include <linux/mutex.h>
 #include <linux/notifier.h>
 #include <linux/threads.h>
@@ -22,6 +23,8 @@
 #include <asm/div64.h>
 
 #define CPUFREQ_NAME_LEN 16
+/* Print length for names. Extra 1 space for accomodating '\n' in prints */
+#define CPUFREQ_NAME_PLEN (CPUFREQ_NAME_LEN + 1)
 
 
 /*********************************************************************
@@ -404,6 +407,4 @@ void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
 				      unsigned int cpu);
 
 void cpufreq_frequency_table_put_attr(unsigned int cpu);
-
-
 #endif /* _LINUX_CPUFREQ_H */
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 279b1ea..3711b34 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -82,13 +82,6 @@ cpuidle_set_statedata(struct cpuidle_state_usage *st_usage, void *data)
 	st_usage->driver_data = data;
 }
 
-struct cpuidle_state_kobj {
-	struct cpuidle_state *state;
-	struct cpuidle_state_usage *state_usage;
-	struct completion kobj_unregister;
-	struct kobject kobj;
-};
-
 struct cpuidle_device {
 	unsigned int		registered:1;
 	unsigned int		enabled:1;
@@ -98,7 +91,7 @@ struct cpuidle_device {
 	int			state_count;
 	struct cpuidle_state_usage	states_usage[CPUIDLE_STATE_MAX];
 	struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
-
+	struct cpuidle_driver_kobj *kobj_driver;
 	struct list_head 	device_list;
 	struct kobject		kobj;
 	struct completion	kobj_unregister;
@@ -131,6 +124,7 @@ static inline int cpuidle_get_last_residency(struct cpuidle_device *dev)
 struct cpuidle_driver {
 	const char		*name;
 	struct module 		*owner;
+	int                     refcnt;
 
 	unsigned int		power_specified:1;
 	/* set to 1 to use the core cpuidle time keeping (for all states). */
@@ -163,6 +157,10 @@ extern int cpuidle_wrap_enter(struct cpuidle_device *dev,
 					struct cpuidle_driver *drv, int index));
 extern int cpuidle_play_dead(void);
 
+extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev);
+extern int cpuidle_register_cpu_driver(struct cpuidle_driver *drv, int cpu);
+extern void cpuidle_unregister_cpu_driver(struct cpuidle_driver *drv, int cpu);
+
 #else
 static inline void disable_cpuidle(void) { }
 static inline int cpuidle_idle_call(void) { return -ENODEV; }
@@ -189,7 +187,6 @@ static inline int cpuidle_wrap_enter(struct cpuidle_device *dev,
 					struct cpuidle_driver *drv, int index))
 { return -ENODEV; }
 static inline int cpuidle_play_dead(void) {return -ENODEV; }
-
 #endif
 
 #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 838320f..8c8a60d 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -144,7 +144,7 @@ static inline nodemask_t cpuset_mems_allowed(struct task_struct *p)
 	return node_possible_map;
 }
 
-#define cpuset_current_mems_allowed (node_states[N_HIGH_MEMORY])
+#define cpuset_current_mems_allowed (node_states[N_MEMORY])
 static inline void cpuset_init_current_mems_allowed(void) {}
 
 static inline int cpuset_nodemask_valid_mems_allowed(nodemask_t *nodemask)
diff --git a/include/linux/cred.h b/include/linux/cred.h
index ebbed2c..abb2cd5 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -77,21 +77,6 @@ extern int in_group_p(kgid_t);
 extern int in_egroup_p(kgid_t);
 
 /*
- * The common credentials for a thread group
- * - shared by CLONE_THREAD
- */
-#ifdef CONFIG_KEYS
-struct thread_group_cred {
-	atomic_t	usage;
-	pid_t		tgid;			/* thread group process ID */
-	spinlock_t	lock;
-	struct key __rcu *session_keyring;	/* keyring inherited over fork */
-	struct key	*process_keyring;	/* keyring private to this process */
-	struct rcu_head	rcu;			/* RCU deletion hook */
-};
-#endif
-
-/*
  * The security context of a task
  *
  * The parts of the context break down into two categories:
@@ -139,6 +124,8 @@ struct cred {
 #ifdef CONFIG_KEYS
 	unsigned char	jit_keyring;	/* default keyring to attach requested
 					 * keys to */
+	struct key __rcu *session_keyring; /* keyring inherited over fork */
+	struct key	*process_keyring; /* keyring private to this process */
 	struct key	*thread_keyring; /* keyring private to this thread */
 	struct key	*request_key_auth; /* assumed request_key authority */
 	struct thread_group_cred *tgcred; /* thread-group shared credentials */
@@ -357,10 +344,8 @@ static inline void put_cred(const struct cred *_cred)
 extern struct user_namespace init_user_ns;
 #ifdef CONFIG_USER_NS
 #define current_user_ns()	(current_cred_xxx(user_ns))
-#define task_user_ns(task)	(task_cred_xxx((task), user_ns))
 #else
 #define current_user_ns()	(&init_user_ns)
-#define task_user_ns(task)	(&init_user_ns)
 #endif
 
 
diff --git a/include/linux/device.h b/include/linux/device.h
index 86ef6ab..43dcda9 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -190,6 +190,7 @@ extern struct klist *bus_get_device_klist(struct bus_type *bus);
  * @mod_name:	Used for built-in modules.
  * @suppress_bind_attrs: Disables bind/unbind via sysfs.
  * @of_match_table: The open firmware table.
+ * @acpi_match_table: The ACPI match table.
  * @probe:	Called to query the existence of a specific device,
  *		whether this driver can work with it, and bind the driver
  *		to a specific device.
@@ -223,6 +224,7 @@ struct device_driver {
 	bool suppress_bind_attrs;	/* disables bind/unbind via sysfs */
 
 	const struct of_device_id	*of_match_table;
+	const struct acpi_device_id	*acpi_match_table;
 
 	int (*probe) (struct device *dev);
 	int (*remove) (struct device *dev);
@@ -496,6 +498,10 @@ ssize_t device_show_int(struct device *dev, struct device_attribute *attr,
 			char *buf);
 ssize_t device_store_int(struct device *dev, struct device_attribute *attr,
 			 const char *buf, size_t count);
+ssize_t device_show_bool(struct device *dev, struct device_attribute *attr,
+			char *buf);
+ssize_t device_store_bool(struct device *dev, struct device_attribute *attr,
+			 const char *buf, size_t count);
 
 #define DEVICE_ATTR(_name, _mode, _show, _store) \
 	struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
@@ -505,6 +511,9 @@ ssize_t device_store_int(struct device *dev, struct device_attribute *attr,
 #define DEVICE_INT_ATTR(_name, _mode, _var) \
 	struct dev_ext_attribute dev_attr_##_name = \
 		{ __ATTR(_name, _mode, device_show_int, device_store_int), &(_var) }
+#define DEVICE_BOOL_ATTR(_name, _mode, _var) \
+	struct dev_ext_attribute dev_attr_##_name = \
+		{ __ATTR(_name, _mode, device_show_bool, device_store_bool), &(_var) }
 #define DEVICE_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) \
 	struct device_attribute dev_attr_##_name =		\
 		__ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store)
@@ -576,6 +585,12 @@ struct device_dma_parameters {
 	unsigned long segment_boundary_mask;
 };
 
+struct acpi_dev_node {
+#ifdef CONFIG_ACPI
+	void	*handle;
+#endif
+};
+
 /**
  * struct device - The basic device structure
  * @parent:	The device's "parent" device, the device to which it is attached.
@@ -616,6 +631,7 @@ struct device_dma_parameters {
  * @dma_mem:	Internal for coherent mem override.
  * @archdata:	For arch-specific additions.
  * @of_node:	Associated device tree node.
+ * @acpi_node:	Associated ACPI device node.
  * @devt:	For creating the sysfs "dev".
  * @id:		device instance
  * @devres_lock: Spinlock to protect the resource of the device.
@@ -680,6 +696,7 @@ struct device {
 	struct dev_archdata	archdata;
 
 	struct device_node	*of_node; /* associated device tree node */
+	struct acpi_dev_node	acpi_node; /* associated ACPI device node */
 
 	dev_t			devt;	/* dev_t, creates the sysfs "dev" */
 	u32			id;	/* device instance */
@@ -700,6 +717,14 @@ static inline struct device *kobj_to_dev(struct kobject *kobj)
 	return container_of(kobj, struct device, kobj);
 }
 
+#ifdef CONFIG_ACPI
+#define ACPI_HANDLE(dev)	((dev)->acpi_node.handle)
+#define ACPI_HANDLE_SET(dev, _handle_)	(dev)->acpi_node.handle = (_handle_)
+#else
+#define ACPI_HANDLE(dev)	(NULL)
+#define ACPI_HANDLE_SET(dev, _handle_)	do { } while (0)
+#endif
+
 /* Get the wakeup routines, which depend on struct device */
 #include <linux/pm_wakeup.h>
 
diff --git a/include/linux/devpts_fs.h b/include/linux/devpts_fs.h
index 5ce0e5f..251a209 100644
--- a/include/linux/devpts_fs.h
+++ b/include/linux/devpts_fs.h
@@ -20,28 +20,28 @@
 int devpts_new_index(struct inode *ptmx_inode);
 void devpts_kill_index(struct inode *ptmx_inode, int idx);
 /* mknod in devpts */
-int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty);
-/* get tty structure */
-struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number);
+struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index,
+		void *priv);
+/* get private structure */
+void *devpts_get_priv(struct inode *pts_inode);
 /* unlink */
-void devpts_pty_kill(struct tty_struct *tty);
+void devpts_pty_kill(struct inode *inode);
 
 #else
 
 /* Dummy stubs in the no-pty case */
 static inline int devpts_new_index(struct inode *ptmx_inode) { return -EINVAL; }
 static inline void devpts_kill_index(struct inode *ptmx_inode, int idx) { }
-static inline int devpts_pty_new(struct inode *ptmx_inode,
-				struct tty_struct *tty)
+static inline struct inode *devpts_pty_new(struct inode *ptmx_inode,
+		dev_t device, int index, void *priv)
 {
-	return -EINVAL;
+	return ERR_PTR(-EINVAL);
 }
-static inline struct tty_struct *devpts_get_tty(struct inode *pts_inode,
-		int number)
+static inline void *devpts_get_priv(struct inode *pts_inode)
 {
 	return NULL;
 }
-static inline void devpts_pty_kill(struct tty_struct *tty) { }
+static inline void devpts_pty_kill(struct inode *inode) { }
 
 #endif
 
diff --git a/include/linux/dlm.h b/include/linux/dlm.h
index 1d47dcc..d02da2c 100644
--- a/include/linux/dlm.h
+++ b/include/linux/dlm.h
@@ -98,7 +98,7 @@ int dlm_release_lockspace(dlm_lockspace_t *lockspace, int force);
 /*
  * dlm_lock
  *
- * Make an asyncronous request to acquire or convert a lock on a named
+ * Make an asynchronous request to acquire or convert a lock on a named
  * resource.
  *
  * lockspace: context for the request
diff --git a/include/linux/dma-debug.h b/include/linux/dma-debug.h
index 171ad8a..fc0e34c 100644
--- a/include/linux/dma-debug.h
+++ b/include/linux/dma-debug.h
@@ -39,6 +39,8 @@ extern void debug_dma_map_page(struct device *dev, struct page *page,
 			       int direction, dma_addr_t dma_addr,
 			       bool map_single);
 
+extern void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
+
 extern void debug_dma_unmap_page(struct device *dev, dma_addr_t addr,
 				 size_t size, int direction, bool map_single);
 
@@ -105,6 +107,11 @@ static inline void debug_dma_map_page(struct device *dev, struct page *page,
 {
 }
 
+static inline void debug_dma_mapping_error(struct device *dev,
+					  dma_addr_t dma_addr)
+{
+}
+
 static inline void debug_dma_unmap_page(struct device *dev, dma_addr_t addr,
 					size_t size, int direction,
 					bool map_single)
diff --git a/include/linux/dma/ipu-dma.h b/include/linux/dma/ipu-dma.h
new file mode 100644
index 0000000..1803111
--- /dev/null
+++ b/include/linux/dma/ipu-dma.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2008
+ * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
+ *
+ * Copyright (C) 2005-2007 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 __LINUX_DMA_IPU_DMA_H
+#define __LINUX_DMA_IPU_DMA_H
+
+#include <linux/types.h>
+#include <linux/dmaengine.h>
+
+/* IPU DMA Controller channel definitions. */
+enum ipu_channel {
+	IDMAC_IC_0 = 0,		/* IC (encoding task) to memory */
+	IDMAC_IC_1 = 1,		/* IC (viewfinder task) to memory */
+	IDMAC_ADC_0 = 1,
+	IDMAC_IC_2 = 2,
+	IDMAC_ADC_1 = 2,
+	IDMAC_IC_3 = 3,
+	IDMAC_IC_4 = 4,
+	IDMAC_IC_5 = 5,
+	IDMAC_IC_6 = 6,
+	IDMAC_IC_7 = 7,		/* IC (sensor data) to memory */
+	IDMAC_IC_8 = 8,
+	IDMAC_IC_9 = 9,
+	IDMAC_IC_10 = 10,
+	IDMAC_IC_11 = 11,
+	IDMAC_IC_12 = 12,
+	IDMAC_IC_13 = 13,
+	IDMAC_SDC_0 = 14,	/* Background synchronous display data */
+	IDMAC_SDC_1 = 15,	/* Foreground data (overlay) */
+	IDMAC_SDC_2 = 16,
+	IDMAC_SDC_3 = 17,
+	IDMAC_ADC_2 = 18,
+	IDMAC_ADC_3 = 19,
+	IDMAC_ADC_4 = 20,
+	IDMAC_ADC_5 = 21,
+	IDMAC_ADC_6 = 22,
+	IDMAC_ADC_7 = 23,
+	IDMAC_PF_0 = 24,
+	IDMAC_PF_1 = 25,
+	IDMAC_PF_2 = 26,
+	IDMAC_PF_3 = 27,
+	IDMAC_PF_4 = 28,
+	IDMAC_PF_5 = 29,
+	IDMAC_PF_6 = 30,
+	IDMAC_PF_7 = 31,
+};
+
+/* Order significant! */
+enum ipu_channel_status {
+	IPU_CHANNEL_FREE,
+	IPU_CHANNEL_INITIALIZED,
+	IPU_CHANNEL_READY,
+	IPU_CHANNEL_ENABLED,
+};
+
+#define IPU_CHANNELS_NUM 32
+
+enum pixel_fmt {
+	/* 1 byte */
+	IPU_PIX_FMT_GENERIC,
+	IPU_PIX_FMT_RGB332,
+	IPU_PIX_FMT_YUV420P,
+	IPU_PIX_FMT_YUV422P,
+	IPU_PIX_FMT_YUV420P2,
+	IPU_PIX_FMT_YVU422P,
+	/* 2 bytes */
+	IPU_PIX_FMT_RGB565,
+	IPU_PIX_FMT_RGB666,
+	IPU_PIX_FMT_BGR666,
+	IPU_PIX_FMT_YUYV,
+	IPU_PIX_FMT_UYVY,
+	/* 3 bytes */
+	IPU_PIX_FMT_RGB24,
+	IPU_PIX_FMT_BGR24,
+	/* 4 bytes */
+	IPU_PIX_FMT_GENERIC_32,
+	IPU_PIX_FMT_RGB32,
+	IPU_PIX_FMT_BGR32,
+	IPU_PIX_FMT_ABGR32,
+	IPU_PIX_FMT_BGRA32,
+	IPU_PIX_FMT_RGBA32,
+};
+
+enum ipu_color_space {
+	IPU_COLORSPACE_RGB,
+	IPU_COLORSPACE_YCBCR,
+	IPU_COLORSPACE_YUV
+};
+
+/*
+ * Enumeration of IPU rotation modes
+ */
+enum ipu_rotate_mode {
+	/* Note the enum values correspond to BAM value */
+	IPU_ROTATE_NONE = 0,
+	IPU_ROTATE_VERT_FLIP = 1,
+	IPU_ROTATE_HORIZ_FLIP = 2,
+	IPU_ROTATE_180 = 3,
+	IPU_ROTATE_90_RIGHT = 4,
+	IPU_ROTATE_90_RIGHT_VFLIP = 5,
+	IPU_ROTATE_90_RIGHT_HFLIP = 6,
+	IPU_ROTATE_90_LEFT = 7,
+};
+
+/*
+ * Enumeration of DI ports for ADC.
+ */
+enum display_port {
+	DISP0,
+	DISP1,
+	DISP2,
+	DISP3
+};
+
+struct idmac_video_param {
+	unsigned short		in_width;
+	unsigned short		in_height;
+	uint32_t		in_pixel_fmt;
+	unsigned short		out_width;
+	unsigned short		out_height;
+	uint32_t		out_pixel_fmt;
+	unsigned short		out_stride;
+	bool			graphics_combine_en;
+	bool			global_alpha_en;
+	bool			key_color_en;
+	enum display_port	disp;
+	unsigned short		out_left;
+	unsigned short		out_top;
+};
+
+/*
+ * Union of initialization parameters for a logical channel. So far only video
+ * parameters are used.
+ */
+union ipu_channel_param {
+	struct idmac_video_param video;
+};
+
+struct idmac_tx_desc {
+	struct dma_async_tx_descriptor	txd;
+	struct scatterlist		*sg;	/* scatterlist for this */
+	unsigned int			sg_len;	/* tx-descriptor. */
+	struct list_head		list;
+};
+
+struct idmac_channel {
+	struct dma_chan		dma_chan;
+	dma_cookie_t		completed;	/* last completed cookie	   */
+	union ipu_channel_param	params;
+	enum ipu_channel	link;	/* input channel, linked to the output	   */
+	enum ipu_channel_status	status;
+	void			*client;	/* Only one client per channel	   */
+	unsigned int		n_tx_desc;
+	struct idmac_tx_desc	*desc;		/* allocated tx-descriptors	   */
+	struct scatterlist	*sg[2];	/* scatterlist elements in buffer-0 and -1 */
+	struct list_head	free_list;	/* free tx-descriptors		   */
+	struct list_head	queue;		/* queued tx-descriptors	   */
+	spinlock_t		lock;		/* protects sg[0,1], queue	   */
+	struct mutex		chan_mutex; /* protects status, cookie, free_list  */
+	bool			sec_chan_en;
+	int			active_buffer;
+	unsigned int		eof_irq;
+	char			eof_name[16];	/* EOF IRQ name for request_irq()  */
+};
+
+#define to_tx_desc(tx) container_of(tx, struct idmac_tx_desc, txd)
+#define to_idmac_chan(c) container_of(c, struct idmac_channel, dma_chan)
+
+#endif /* __LINUX_DMA_IPU_DMA_H */
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index d3201e4..4c86437 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -849,20 +849,6 @@ static inline bool async_tx_test_ack(struct dma_async_tx_descriptor *tx)
 	return (tx->flags & DMA_CTRL_ACK) == DMA_CTRL_ACK;
 }
 
-#define first_dma_cap(mask) __first_dma_cap(&(mask))
-static inline int __first_dma_cap(const dma_cap_mask_t *srcp)
-{
-	return min_t(int, DMA_TX_TYPE_END,
-		find_first_bit(srcp->bits, DMA_TX_TYPE_END));
-}
-
-#define next_dma_cap(n, mask) __next_dma_cap((n), &(mask))
-static inline int __next_dma_cap(int n, const dma_cap_mask_t *srcp)
-{
-	return min_t(int, DMA_TX_TYPE_END,
-		find_next_bit(srcp->bits, DMA_TX_TYPE_END, n+1));
-}
-
 #define dma_cap_set(tx, mask) __dma_cap_set((tx), &(mask))
 static inline void
 __dma_cap_set(enum dma_transaction_type tx_type, dma_cap_mask_t *dstp)
@@ -891,9 +877,7 @@ __dma_has_cap(enum dma_transaction_type tx_type, dma_cap_mask_t *srcp)
 }
 
 #define for_each_dma_cap_mask(cap, mask) \
-	for ((cap) = first_dma_cap(mask);	\
-		(cap) < DMA_TX_TYPE_END;	\
-		(cap) = next_dma_cap((cap), (mask)))
+	for_each_set_bit(cap, mask.bits, DMA_TX_TYPE_END)
 
 /**
  * dma_async_issue_pending - flush pending transactions to HW
@@ -974,6 +958,7 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
 enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
 void dma_issue_pending_all(void);
 struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param);
+struct dma_chan *dma_request_slave_channel(struct device *dev, char *name);
 void dma_release_channel(struct dma_chan *chan);
 #else
 static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
@@ -988,6 +973,11 @@ static inline struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask,
 {
 	return NULL;
 }
+static inline struct dma_chan *dma_request_slave_channel(struct device *dev,
+							 char *name)
+{
+	return NULL;
+}
 static inline void dma_release_channel(struct dma_chan *chan)
 {
 }
diff --git a/include/linux/drbd.h b/include/linux/drbd.h
index 47e3d48..0c5a18e 100644
--- a/include/linux/drbd.h
+++ b/include/linux/drbd.h
@@ -51,12 +51,11 @@
 
 #endif
 
-
 extern const char *drbd_buildtag(void);
-#define REL_VERSION "8.3.13"
-#define API_VERSION 88
+#define REL_VERSION "8.4.2"
+#define API_VERSION 1
 #define PRO_VERSION_MIN 86
-#define PRO_VERSION_MAX 96
+#define PRO_VERSION_MAX 101
 
 
 enum drbd_io_error_p {
@@ -66,7 +65,8 @@ enum drbd_io_error_p {
 };
 
 enum drbd_fencing_p {
-	FP_DONT_CARE,
+	FP_NOT_AVAIL = -1, /* Not a policy */
+	FP_DONT_CARE = 0,
 	FP_RESOURCE,
 	FP_STONITH
 };
@@ -102,6 +102,20 @@ enum drbd_on_congestion {
 	OC_DISCONNECT,
 };
 
+enum drbd_read_balancing {
+	RB_PREFER_LOCAL,
+	RB_PREFER_REMOTE,
+	RB_ROUND_ROBIN,
+	RB_LEAST_PENDING,
+	RB_CONGESTED_REMOTE,
+	RB_32K_STRIPING,
+	RB_64K_STRIPING,
+	RB_128K_STRIPING,
+	RB_256K_STRIPING,
+	RB_512K_STRIPING,
+	RB_1M_STRIPING,
+};
+
 /* KEEP the order, do not delete or insert. Only append. */
 enum drbd_ret_code {
 	ERR_CODE_BASE		= 100,
@@ -122,7 +136,7 @@ enum drbd_ret_code {
 	ERR_AUTH_ALG		= 120,
 	ERR_AUTH_ALG_ND		= 121,
 	ERR_NOMEM		= 122,
-	ERR_DISCARD		= 123,
+	ERR_DISCARD_IMPOSSIBLE	= 123,
 	ERR_DISK_CONFIGURED	= 124,
 	ERR_NET_CONFIGURED	= 125,
 	ERR_MANDATORY_TAG	= 126,
@@ -130,8 +144,8 @@ enum drbd_ret_code {
 	ERR_INTR		= 129, /* EINTR */
 	ERR_RESIZE_RESYNC	= 130,
 	ERR_NO_PRIMARY		= 131,
-	ERR_SYNC_AFTER		= 132,
-	ERR_SYNC_AFTER_CYCLE	= 133,
+	ERR_RESYNC_AFTER	= 132,
+	ERR_RESYNC_AFTER_CYCLE	= 133,
 	ERR_PAUSE_IS_SET	= 134,
 	ERR_PAUSE_IS_CLEAR	= 135,
 	ERR_PACKET_NR		= 137,
@@ -155,6 +169,14 @@ enum drbd_ret_code {
 	ERR_CONG_NOT_PROTO_A	= 155,
 	ERR_PIC_AFTER_DEP	= 156,
 	ERR_PIC_PEER_DEP	= 157,
+	ERR_RES_NOT_KNOWN	= 158,
+	ERR_RES_IN_USE		= 159,
+	ERR_MINOR_CONFIGURED    = 160,
+	ERR_MINOR_EXISTS	= 161,
+	ERR_INVALID_REQUEST	= 162,
+	ERR_NEED_APV_100	= 163,
+	ERR_NEED_ALLOW_TWO_PRI  = 164,
+	ERR_MD_UNCLEAN          = 165,
 
 	/* insert new ones above this line */
 	AFTER_LAST_ERR_CODE
@@ -296,7 +318,8 @@ enum drbd_state_rv {
 	SS_NOT_SUPPORTED = -17,      /* drbd-8.2 only */
 	SS_IN_TRANSIENT_STATE = -18,  /* Retry after the next state change */
 	SS_CONCURRENT_ST_CHG = -19,   /* Concurrent cluster side state change! */
-	SS_AFTER_LAST_ERROR = -20,    /* Keep this at bottom */
+	SS_O_VOL_PEER_PRI = -20,
+	SS_AFTER_LAST_ERROR = -21,    /* Keep this at bottom */
 };
 
 /* from drbd_strings.c */
@@ -313,7 +336,9 @@ extern const char *drbd_set_st_err_str(enum drbd_state_rv);
 #define MDF_FULL_SYNC		(1 << 3)
 #define MDF_WAS_UP_TO_DATE	(1 << 4)
 #define MDF_PEER_OUT_DATED	(1 << 5)
-#define MDF_CRASHED_PRIMARY     (1 << 6)
+#define MDF_CRASHED_PRIMARY	(1 << 6)
+#define MDF_AL_CLEAN		(1 << 7)
+#define MDF_AL_DISABLED		(1 << 8)
 
 enum drbd_uuid_index {
 	UI_CURRENT,
@@ -333,37 +358,23 @@ enum drbd_timeout_flag {
 
 #define UUID_JUST_CREATED ((__u64)4)
 
+/* magic numbers used in meta data and network packets */
 #define DRBD_MAGIC 0x83740267
-#define BE_DRBD_MAGIC __constant_cpu_to_be32(DRBD_MAGIC)
 #define DRBD_MAGIC_BIG 0x835a
-#define BE_DRBD_MAGIC_BIG __constant_cpu_to_be16(DRBD_MAGIC_BIG)
+#define DRBD_MAGIC_100 0x8620ec20
+
+#define DRBD_MD_MAGIC_07   (DRBD_MAGIC+3)
+#define DRBD_MD_MAGIC_08   (DRBD_MAGIC+4)
+#define DRBD_MD_MAGIC_84_UNCLEAN	(DRBD_MAGIC+5)
+
+
+/* how I came up with this magic?
+ * base64 decode "actlog==" ;) */
+#define DRBD_AL_MAGIC 0x69cb65a2
 
 /* these are of type "int" */
 #define DRBD_MD_INDEX_INTERNAL -1
 #define DRBD_MD_INDEX_FLEX_EXT -2
 #define DRBD_MD_INDEX_FLEX_INT -3
 
-/* Start of the new netlink/connector stuff */
-
-#define DRBD_NL_CREATE_DEVICE 0x01
-#define DRBD_NL_SET_DEFAULTS  0x02
-
-
-/* For searching a vacant cn_idx value */
-#define CN_IDX_STEP			6977
-
-struct drbd_nl_cfg_req {
-	int packet_type;
-	unsigned int drbd_minor;
-	int flags;
-	unsigned short tag_list[];
-};
-
-struct drbd_nl_cfg_reply {
-	int packet_type;
-	unsigned int minor;
-	int ret_code; /* enum ret_code or set_st_err_t */
-	unsigned short tag_list[]; /* only used with get_* calls */
-};
-
 #endif
diff --git a/include/linux/drbd_genl.h b/include/linux/drbd_genl.h
new file mode 100644
index 0000000..d0d8fac
--- /dev/null
+++ b/include/linux/drbd_genl.h
@@ -0,0 +1,378 @@
+/*
+ * General overview:
+ * full generic netlink message:
+ * |nlmsghdr|genlmsghdr|<payload>
+ *
+ * payload:
+ * |optional fixed size family header|<sequence of netlink attributes>
+ *
+ * sequence of netlink attributes:
+ * I chose to have all "top level" attributes NLA_NESTED,
+ * corresponding to some real struct.
+ * So we have a sequence of |tla, len|<nested nla sequence>
+ *
+ * nested nla sequence:
+ * may be empty, or contain a sequence of netlink attributes
+ * representing the struct fields.
+ *
+ * The tag number of any field (regardless of containing struct)
+ * will be available as T_ ## field_name,
+ * so you cannot have the same field name in two differnt structs.
+ *
+ * The tag numbers themselves are per struct, though,
+ * so should always begin at 1 (not 0, that is the special "NLA_UNSPEC" type,
+ * which we won't use here).
+ * The tag numbers are used as index in the respective nla_policy array.
+ *
+ * GENL_struct(tag_name, tag_number, struct name, struct fields) - struct and policy
+ *	genl_magic_struct.h
+ *		generates the struct declaration,
+ *		generates an entry in the tla enum,
+ *	genl_magic_func.h
+ *		generates an entry in the static tla policy
+ *		with .type = NLA_NESTED
+ *		generates the static <struct_name>_nl_policy definition,
+ *		and static conversion functions
+ *
+ *	genl_magic_func.h
+ *
+ * GENL_mc_group(group)
+ *	genl_magic_struct.h
+ *		does nothing
+ *	genl_magic_func.h
+ *		defines and registers the mcast group,
+ *		and provides a send helper
+ *
+ * GENL_notification(op_name, op_num, mcast_group, tla list)
+ *	These are notifications to userspace.
+ *
+ *	genl_magic_struct.h
+ *		generates an entry in the genl_ops enum,
+ *	genl_magic_func.h
+ *		does nothing
+ *
+ *	mcast group: the name of the mcast group this notification should be
+ *	expected on
+ *	tla list: the list of expected top level attributes,
+ *	for documentation and sanity checking.
+ *
+ * GENL_op(op_name, op_num, flags and handler, tla list) - "genl operations"
+ *	These are requests from userspace.
+ *
+ *	_op and _notification share the same "number space",
+ *	op_nr will be assigned to "genlmsghdr->cmd"
+ *
+ *	genl_magic_struct.h
+ *		generates an entry in the genl_ops enum,
+ *	genl_magic_func.h
+ *		generates an entry in the static genl_ops array,
+ *		and static register/unregister functions to
+ *		genl_register_family_with_ops().
+ *
+ *	flags and handler:
+ *		GENL_op_init( .doit = x, .dumpit = y, .flags = something)
+ *		GENL_doit(x) => .dumpit = NULL, .flags = GENL_ADMIN_PERM
+ *	tla list: the list of expected top level attributes,
+ *	for documentation and sanity checking.
+ */
+
+/*
+ * STRUCTS
+ */
+
+/* this is sent kernel -> userland on various error conditions, and contains
+ * informational textual info, which is supposedly human readable.
+ * The computer relevant return code is in the drbd_genlmsghdr.
+ */
+GENL_struct(DRBD_NLA_CFG_REPLY, 1, drbd_cfg_reply,
+		/* "arbitrary" size strings, nla_policy.len = 0 */
+	__str_field(1, DRBD_GENLA_F_MANDATORY,	info_text, 0)
+)
+
+/* Configuration requests typically need a context to operate on.
+ * Possible keys are device minor (fits in the drbd_genlmsghdr),
+ * the replication link (aka connection) name,
+ * and/or the replication group (aka resource) name,
+ * and the volume id within the resource. */
+GENL_struct(DRBD_NLA_CFG_CONTEXT, 2, drbd_cfg_context,
+	__u32_field(1, DRBD_GENLA_F_MANDATORY,	ctx_volume)
+	__str_field(2, DRBD_GENLA_F_MANDATORY,	ctx_resource_name, 128)
+	__bin_field(3, DRBD_GENLA_F_MANDATORY,	ctx_my_addr, 128)
+	__bin_field(4, DRBD_GENLA_F_MANDATORY,	ctx_peer_addr, 128)
+)
+
+GENL_struct(DRBD_NLA_DISK_CONF, 3, disk_conf,
+	__str_field(1, DRBD_F_REQUIRED | DRBD_F_INVARIANT,	backing_dev,	128)
+	__str_field(2, DRBD_F_REQUIRED | DRBD_F_INVARIANT,	meta_dev,	128)
+	__s32_field(3, DRBD_F_REQUIRED | DRBD_F_INVARIANT,	meta_dev_idx)
+
+	/* use the resize command to try and change the disk_size */
+	__u64_field(4, DRBD_GENLA_F_MANDATORY | DRBD_F_INVARIANT,	disk_size)
+	/* we could change the max_bio_bvecs,
+	 * but it won't propagate through the stack */
+	__u32_field(5, DRBD_GENLA_F_MANDATORY | DRBD_F_INVARIANT,	max_bio_bvecs)
+
+	__u32_field_def(6, DRBD_GENLA_F_MANDATORY,	on_io_error, DRBD_ON_IO_ERROR_DEF)
+	__u32_field_def(7, DRBD_GENLA_F_MANDATORY,	fencing, DRBD_FENCING_DEF)
+
+	__u32_field_def(8,	DRBD_GENLA_F_MANDATORY,	resync_rate, DRBD_RESYNC_RATE_DEF)
+	__s32_field_def(9,	DRBD_GENLA_F_MANDATORY,	resync_after, DRBD_MINOR_NUMBER_DEF)
+	__u32_field_def(10,	DRBD_GENLA_F_MANDATORY,	al_extents, DRBD_AL_EXTENTS_DEF)
+	__u32_field_def(11,	DRBD_GENLA_F_MANDATORY,	c_plan_ahead, DRBD_C_PLAN_AHEAD_DEF)
+	__u32_field_def(12,	DRBD_GENLA_F_MANDATORY,	c_delay_target, DRBD_C_DELAY_TARGET_DEF)
+	__u32_field_def(13,	DRBD_GENLA_F_MANDATORY,	c_fill_target, DRBD_C_FILL_TARGET_DEF)
+	__u32_field_def(14,	DRBD_GENLA_F_MANDATORY,	c_max_rate, DRBD_C_MAX_RATE_DEF)
+	__u32_field_def(15,	DRBD_GENLA_F_MANDATORY,	c_min_rate, DRBD_C_MIN_RATE_DEF)
+
+	__flg_field_def(16, DRBD_GENLA_F_MANDATORY,	disk_barrier, DRBD_DISK_BARRIER_DEF)
+	__flg_field_def(17, DRBD_GENLA_F_MANDATORY,	disk_flushes, DRBD_DISK_FLUSHES_DEF)
+	__flg_field_def(18, DRBD_GENLA_F_MANDATORY,	disk_drain, DRBD_DISK_DRAIN_DEF)
+	__flg_field_def(19, DRBD_GENLA_F_MANDATORY,	md_flushes, DRBD_MD_FLUSHES_DEF)
+	__u32_field_def(20,	DRBD_GENLA_F_MANDATORY,	disk_timeout, DRBD_DISK_TIMEOUT_DEF)
+	__u32_field_def(21,	0 /* OPTIONAL */,       read_balancing, DRBD_READ_BALANCING_DEF)
+	/* 9: __u32_field_def(22,	DRBD_GENLA_F_MANDATORY,	unplug_watermark, DRBD_UNPLUG_WATERMARK_DEF) */
+	__flg_field_def(23,     0 /* OPTIONAL */,	al_updates, DRBD_AL_UPDATES_DEF)
+)
+
+GENL_struct(DRBD_NLA_RESOURCE_OPTS, 4, res_opts,
+	__str_field_def(1,	DRBD_GENLA_F_MANDATORY,	cpu_mask,       32)
+	__u32_field_def(2,	DRBD_GENLA_F_MANDATORY,	on_no_data, DRBD_ON_NO_DATA_DEF)
+)
+
+GENL_struct(DRBD_NLA_NET_CONF, 5, net_conf,
+	__str_field_def(1,	DRBD_GENLA_F_MANDATORY | DRBD_F_SENSITIVE,
+						shared_secret,	SHARED_SECRET_MAX)
+	__str_field_def(2,	DRBD_GENLA_F_MANDATORY,	cram_hmac_alg,	SHARED_SECRET_MAX)
+	__str_field_def(3,	DRBD_GENLA_F_MANDATORY,	integrity_alg,	SHARED_SECRET_MAX)
+	__str_field_def(4,	DRBD_GENLA_F_MANDATORY,	verify_alg,     SHARED_SECRET_MAX)
+	__str_field_def(5,	DRBD_GENLA_F_MANDATORY,	csums_alg,	SHARED_SECRET_MAX)
+	__u32_field_def(6,	DRBD_GENLA_F_MANDATORY,	wire_protocol, DRBD_PROTOCOL_DEF)
+	__u32_field_def(7,	DRBD_GENLA_F_MANDATORY,	connect_int, DRBD_CONNECT_INT_DEF)
+	__u32_field_def(8,	DRBD_GENLA_F_MANDATORY,	timeout, DRBD_TIMEOUT_DEF)
+	__u32_field_def(9,	DRBD_GENLA_F_MANDATORY,	ping_int, DRBD_PING_INT_DEF)
+	__u32_field_def(10,	DRBD_GENLA_F_MANDATORY,	ping_timeo, DRBD_PING_TIMEO_DEF)
+	__u32_field_def(11,	DRBD_GENLA_F_MANDATORY,	sndbuf_size, DRBD_SNDBUF_SIZE_DEF)
+	__u32_field_def(12,	DRBD_GENLA_F_MANDATORY,	rcvbuf_size, DRBD_RCVBUF_SIZE_DEF)
+	__u32_field_def(13,	DRBD_GENLA_F_MANDATORY,	ko_count, DRBD_KO_COUNT_DEF)
+	__u32_field_def(14,	DRBD_GENLA_F_MANDATORY,	max_buffers, DRBD_MAX_BUFFERS_DEF)
+	__u32_field_def(15,	DRBD_GENLA_F_MANDATORY,	max_epoch_size, DRBD_MAX_EPOCH_SIZE_DEF)
+	__u32_field_def(16,	DRBD_GENLA_F_MANDATORY,	unplug_watermark, DRBD_UNPLUG_WATERMARK_DEF)
+	__u32_field_def(17,	DRBD_GENLA_F_MANDATORY,	after_sb_0p, DRBD_AFTER_SB_0P_DEF)
+	__u32_field_def(18,	DRBD_GENLA_F_MANDATORY,	after_sb_1p, DRBD_AFTER_SB_1P_DEF)
+	__u32_field_def(19,	DRBD_GENLA_F_MANDATORY,	after_sb_2p, DRBD_AFTER_SB_2P_DEF)
+	__u32_field_def(20,	DRBD_GENLA_F_MANDATORY,	rr_conflict, DRBD_RR_CONFLICT_DEF)
+	__u32_field_def(21,	DRBD_GENLA_F_MANDATORY,	on_congestion, DRBD_ON_CONGESTION_DEF)
+	__u32_field_def(22,	DRBD_GENLA_F_MANDATORY,	cong_fill, DRBD_CONG_FILL_DEF)
+	__u32_field_def(23,	DRBD_GENLA_F_MANDATORY,	cong_extents, DRBD_CONG_EXTENTS_DEF)
+	__flg_field_def(24, DRBD_GENLA_F_MANDATORY,	two_primaries, DRBD_ALLOW_TWO_PRIMARIES_DEF)
+	__flg_field(25, DRBD_GENLA_F_MANDATORY | DRBD_F_INVARIANT,	discard_my_data)
+	__flg_field_def(26, DRBD_GENLA_F_MANDATORY,	tcp_cork, DRBD_TCP_CORK_DEF)
+	__flg_field_def(27, DRBD_GENLA_F_MANDATORY,	always_asbp, DRBD_ALWAYS_ASBP_DEF)
+	__flg_field(28, DRBD_GENLA_F_MANDATORY | DRBD_F_INVARIANT,	tentative)
+	__flg_field_def(29,	DRBD_GENLA_F_MANDATORY,	use_rle, DRBD_USE_RLE_DEF)
+	/* 9: __u32_field_def(30,	DRBD_GENLA_F_MANDATORY,	fencing_policy, DRBD_FENCING_DEF) */
+)
+
+GENL_struct(DRBD_NLA_SET_ROLE_PARMS, 6, set_role_parms,
+	__flg_field(1, DRBD_GENLA_F_MANDATORY,	assume_uptodate)
+)
+
+GENL_struct(DRBD_NLA_RESIZE_PARMS, 7, resize_parms,
+	__u64_field(1, DRBD_GENLA_F_MANDATORY,	resize_size)
+	__flg_field(2, DRBD_GENLA_F_MANDATORY,	resize_force)
+	__flg_field(3, DRBD_GENLA_F_MANDATORY,	no_resync)
+)
+
+GENL_struct(DRBD_NLA_STATE_INFO, 8, state_info,
+	/* the reason of the broadcast,
+	 * if this is an event triggered broadcast. */
+	__u32_field(1, DRBD_GENLA_F_MANDATORY,	sib_reason)
+	__u32_field(2, DRBD_F_REQUIRED,	current_state)
+	__u64_field(3, DRBD_GENLA_F_MANDATORY,	capacity)
+	__u64_field(4, DRBD_GENLA_F_MANDATORY,	ed_uuid)
+
+	/* These are for broadcast from after state change work.
+	 * prev_state and new_state are from the moment the state change took
+	 * place, new_state is not neccessarily the same as current_state,
+	 * there may have been more state changes since.  Which will be
+	 * broadcasted soon, in their respective after state change work.  */
+	__u32_field(5, DRBD_GENLA_F_MANDATORY,	prev_state)
+	__u32_field(6, DRBD_GENLA_F_MANDATORY,	new_state)
+
+	/* if we have a local disk: */
+	__bin_field(7, DRBD_GENLA_F_MANDATORY,	uuids, (UI_SIZE*sizeof(__u64)))
+	__u32_field(8, DRBD_GENLA_F_MANDATORY,	disk_flags)
+	__u64_field(9, DRBD_GENLA_F_MANDATORY,	bits_total)
+	__u64_field(10, DRBD_GENLA_F_MANDATORY,	bits_oos)
+	/* and in case resync or online verify is active */
+	__u64_field(11, DRBD_GENLA_F_MANDATORY,	bits_rs_total)
+	__u64_field(12, DRBD_GENLA_F_MANDATORY,	bits_rs_failed)
+
+	/* for pre and post notifications of helper execution */
+	__str_field(13, DRBD_GENLA_F_MANDATORY,	helper, 32)
+	__u32_field(14, DRBD_GENLA_F_MANDATORY,	helper_exit_code)
+
+	__u64_field(15,                      0, send_cnt)
+	__u64_field(16,                      0, recv_cnt)
+	__u64_field(17,                      0, read_cnt)
+	__u64_field(18,                      0, writ_cnt)
+	__u64_field(19,                      0, al_writ_cnt)
+	__u64_field(20,                      0, bm_writ_cnt)
+	__u32_field(21,                      0, ap_bio_cnt)
+	__u32_field(22,                      0, ap_pending_cnt)
+	__u32_field(23,                      0, rs_pending_cnt)
+)
+
+GENL_struct(DRBD_NLA_START_OV_PARMS, 9, start_ov_parms,
+	__u64_field(1, DRBD_GENLA_F_MANDATORY,	ov_start_sector)
+	__u64_field(2, DRBD_GENLA_F_MANDATORY,	ov_stop_sector)
+)
+
+GENL_struct(DRBD_NLA_NEW_C_UUID_PARMS, 10, new_c_uuid_parms,
+	__flg_field(1, DRBD_GENLA_F_MANDATORY, clear_bm)
+)
+
+GENL_struct(DRBD_NLA_TIMEOUT_PARMS, 11, timeout_parms,
+	__u32_field(1,	DRBD_F_REQUIRED,	timeout_type)
+)
+
+GENL_struct(DRBD_NLA_DISCONNECT_PARMS, 12, disconnect_parms,
+	__flg_field(1, DRBD_GENLA_F_MANDATORY,	force_disconnect)
+)
+
+GENL_struct(DRBD_NLA_DETACH_PARMS, 13, detach_parms,
+	__flg_field(1, DRBD_GENLA_F_MANDATORY,	force_detach)
+)
+
+/*
+ * Notifications and commands (genlmsghdr->cmd)
+ */
+GENL_mc_group(events)
+
+	/* kernel -> userspace announcement of changes */
+GENL_notification(
+	DRBD_EVENT, 1, events,
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)
+	GENL_tla_expected(DRBD_NLA_STATE_INFO, DRBD_F_REQUIRED)
+	GENL_tla_expected(DRBD_NLA_NET_CONF, DRBD_GENLA_F_MANDATORY)
+	GENL_tla_expected(DRBD_NLA_DISK_CONF, DRBD_GENLA_F_MANDATORY)
+	GENL_tla_expected(DRBD_NLA_SYNCER_CONF, DRBD_GENLA_F_MANDATORY)
+)
+
+	/* query kernel for specific or all info */
+GENL_op(
+	DRBD_ADM_GET_STATUS, 2,
+	GENL_op_init(
+		.doit = drbd_adm_get_status,
+		.dumpit = drbd_adm_get_status_all,
+		/* anyone may ask for the status,
+		 * it is broadcasted anyways */
+	),
+	/* To select the object .doit.
+	 * Or a subset of objects in .dumpit. */
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY)
+)
+
+	/* add DRBD minor devices as volumes to resources */
+GENL_op(DRBD_ADM_NEW_MINOR, 5, GENL_doit(drbd_adm_add_minor),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
+GENL_op(DRBD_ADM_DEL_MINOR, 6, GENL_doit(drbd_adm_delete_minor),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
+
+	/* add or delete resources */
+GENL_op(DRBD_ADM_NEW_RESOURCE, 7, GENL_doit(drbd_adm_new_resource),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
+GENL_op(DRBD_ADM_DEL_RESOURCE, 8, GENL_doit(drbd_adm_del_resource),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
+
+GENL_op(DRBD_ADM_RESOURCE_OPTS, 9,
+	GENL_doit(drbd_adm_resource_opts),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)
+	GENL_tla_expected(DRBD_NLA_RESOURCE_OPTS, DRBD_GENLA_F_MANDATORY)
+)
+
+GENL_op(
+	DRBD_ADM_CONNECT, 10,
+	GENL_doit(drbd_adm_connect),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)
+	GENL_tla_expected(DRBD_NLA_NET_CONF, DRBD_F_REQUIRED)
+)
+
+GENL_op(
+	DRBD_ADM_CHG_NET_OPTS, 29,
+	GENL_doit(drbd_adm_net_opts),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)
+	GENL_tla_expected(DRBD_NLA_NET_CONF, DRBD_F_REQUIRED)
+)
+
+GENL_op(DRBD_ADM_DISCONNECT, 11, GENL_doit(drbd_adm_disconnect),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
+
+GENL_op(DRBD_ADM_ATTACH, 12,
+	GENL_doit(drbd_adm_attach),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)
+	GENL_tla_expected(DRBD_NLA_DISK_CONF, DRBD_F_REQUIRED)
+)
+
+GENL_op(DRBD_ADM_CHG_DISK_OPTS, 28,
+	GENL_doit(drbd_adm_disk_opts),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)
+	GENL_tla_expected(DRBD_NLA_DISK_OPTS, DRBD_F_REQUIRED)
+)
+
+GENL_op(
+	DRBD_ADM_RESIZE, 13,
+	GENL_doit(drbd_adm_resize),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)
+	GENL_tla_expected(DRBD_NLA_RESIZE_PARMS, DRBD_GENLA_F_MANDATORY)
+)
+
+GENL_op(
+	DRBD_ADM_PRIMARY, 14,
+	GENL_doit(drbd_adm_set_role),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)
+	GENL_tla_expected(DRBD_NLA_SET_ROLE_PARMS, DRBD_F_REQUIRED)
+)
+
+GENL_op(
+	DRBD_ADM_SECONDARY, 15,
+	GENL_doit(drbd_adm_set_role),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)
+	GENL_tla_expected(DRBD_NLA_SET_ROLE_PARMS, DRBD_F_REQUIRED)
+)
+
+GENL_op(
+	DRBD_ADM_NEW_C_UUID, 16,
+	GENL_doit(drbd_adm_new_c_uuid),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)
+	GENL_tla_expected(DRBD_NLA_NEW_C_UUID_PARMS, DRBD_GENLA_F_MANDATORY)
+)
+
+GENL_op(
+	DRBD_ADM_START_OV, 17,
+	GENL_doit(drbd_adm_start_ov),
+	GENL_tla_expected(DRBD_NLA_START_OV_PARMS, DRBD_GENLA_F_MANDATORY)
+)
+
+GENL_op(DRBD_ADM_DETACH,	18, GENL_doit(drbd_adm_detach),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)
+	GENL_tla_expected(DRBD_NLA_DETACH_PARMS, DRBD_GENLA_F_MANDATORY))
+
+GENL_op(DRBD_ADM_INVALIDATE,	19, GENL_doit(drbd_adm_invalidate),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
+GENL_op(DRBD_ADM_INVAL_PEER,	20, GENL_doit(drbd_adm_invalidate_peer),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
+GENL_op(DRBD_ADM_PAUSE_SYNC,	21, GENL_doit(drbd_adm_pause_sync),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
+GENL_op(DRBD_ADM_RESUME_SYNC,	22, GENL_doit(drbd_adm_resume_sync),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
+GENL_op(DRBD_ADM_SUSPEND_IO,	23, GENL_doit(drbd_adm_suspend_io),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
+GENL_op(DRBD_ADM_RESUME_IO,	24, GENL_doit(drbd_adm_resume_io),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
+GENL_op(DRBD_ADM_OUTDATE,	25, GENL_doit(drbd_adm_outdate),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
+GENL_op(DRBD_ADM_GET_TIMEOUT_TYPE, 26, GENL_doit(drbd_adm_get_timeout_type),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
+GENL_op(DRBD_ADM_DOWN,		27, GENL_doit(drbd_adm_down),
+	GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
diff --git a/include/linux/drbd_genl_api.h b/include/linux/drbd_genl_api.h
new file mode 100644
index 0000000..9ef50d5
--- /dev/null
+++ b/include/linux/drbd_genl_api.h
@@ -0,0 +1,55 @@
+#ifndef DRBD_GENL_STRUCT_H
+#define DRBD_GENL_STRUCT_H
+
+/**
+ * struct drbd_genlmsghdr - DRBD specific header used in NETLINK_GENERIC requests
+ * @minor:
+ *     For admin requests (user -> kernel): which minor device to operate on.
+ *     For (unicast) replies or informational (broadcast) messages
+ *     (kernel -> user): which minor device the information is about.
+ *     If we do not operate on minors, but on connections or resources,
+ *     the minor value shall be (~0), and the attribute DRBD_NLA_CFG_CONTEXT
+ *     is used instead.
+ * @flags: possible operation modifiers (relevant only for user->kernel):
+ *     DRBD_GENL_F_SET_DEFAULTS
+ * @volume:
+ *     When creating a new minor (adding it to a resource), the resource needs
+ *     to know which volume number within the resource this is supposed to be.
+ *     The volume number corresponds to the same volume number on the remote side,
+ *     whereas the minor number on the remote side may be different
+ *     (union with flags).
+ * @ret_code: kernel->userland unicast cfg reply return code (union with flags);
+ */
+struct drbd_genlmsghdr {
+	__u32 minor;
+	union {
+	__u32 flags;
+	__s32 ret_code;
+	};
+};
+
+/* To be used in drbd_genlmsghdr.flags */
+enum {
+	DRBD_GENL_F_SET_DEFAULTS = 1,
+};
+
+enum drbd_state_info_bcast_reason {
+	SIB_GET_STATUS_REPLY = 1,
+	SIB_STATE_CHANGE = 2,
+	SIB_HELPER_PRE = 3,
+	SIB_HELPER_POST = 4,
+	SIB_SYNC_PROGRESS = 5,
+};
+
+/* hack around predefined gcc/cpp "linux=1",
+ * we cannot possibly include <1/drbd_genl.h> */
+#undef linux
+
+#include <linux/drbd.h>
+#define GENL_MAGIC_VERSION	API_VERSION
+#define GENL_MAGIC_FAMILY	drbd
+#define GENL_MAGIC_FAMILY_HDRSZ	sizeof(struct drbd_genlmsghdr)
+#define GENL_MAGIC_INCLUDE_FILE <linux/drbd_genl.h>
+#include <linux/genl_magic_struct.h>
+
+#endif
diff --git a/include/linux/drbd_limits.h b/include/linux/drbd_limits.h
index fb670bf..1fa19c5 100644
--- a/include/linux/drbd_limits.h
+++ b/include/linux/drbd_limits.h
@@ -16,29 +16,37 @@
 #define DEBUG_RANGE_CHECK 0
 
 #define DRBD_MINOR_COUNT_MIN 1
-#define DRBD_MINOR_COUNT_MAX 256
+#define DRBD_MINOR_COUNT_MAX 255
 #define DRBD_MINOR_COUNT_DEF 32
+#define DRBD_MINOR_COUNT_SCALE '1'
+
+#define DRBD_VOLUME_MAX 65535
 
 #define DRBD_DIALOG_REFRESH_MIN 0
 #define DRBD_DIALOG_REFRESH_MAX 600
+#define DRBD_DIALOG_REFRESH_SCALE '1'
 
 /* valid port number */
 #define DRBD_PORT_MIN 1
 #define DRBD_PORT_MAX 0xffff
+#define DRBD_PORT_SCALE '1'
 
 /* startup { */
   /* if you want more than 3.4 days, disable */
 #define DRBD_WFC_TIMEOUT_MIN 0
 #define DRBD_WFC_TIMEOUT_MAX 300000
 #define DRBD_WFC_TIMEOUT_DEF 0
+#define DRBD_WFC_TIMEOUT_SCALE '1'
 
 #define DRBD_DEGR_WFC_TIMEOUT_MIN 0
 #define DRBD_DEGR_WFC_TIMEOUT_MAX 300000
 #define DRBD_DEGR_WFC_TIMEOUT_DEF 0
+#define DRBD_DEGR_WFC_TIMEOUT_SCALE '1'
 
 #define DRBD_OUTDATED_WFC_TIMEOUT_MIN 0
 #define DRBD_OUTDATED_WFC_TIMEOUT_MAX 300000
 #define DRBD_OUTDATED_WFC_TIMEOUT_DEF 0
+#define DRBD_OUTDATED_WFC_TIMEOUT_SCALE '1'
 /* }*/
 
 /* net { */
@@ -47,75 +55,91 @@
 #define DRBD_TIMEOUT_MIN 1
 #define DRBD_TIMEOUT_MAX 600
 #define DRBD_TIMEOUT_DEF 60       /* 6 seconds */
+#define DRBD_TIMEOUT_SCALE '1'
 
  /* If backing disk takes longer than disk_timeout, mark the disk as failed */
 #define DRBD_DISK_TIMEOUT_MIN 0    /* 0 = disabled */
 #define DRBD_DISK_TIMEOUT_MAX 6000 /* 10 Minutes */
 #define DRBD_DISK_TIMEOUT_DEF 0    /* disabled */
+#define DRBD_DISK_TIMEOUT_SCALE '1'
 
   /* active connection retries when C_WF_CONNECTION */
 #define DRBD_CONNECT_INT_MIN 1
 #define DRBD_CONNECT_INT_MAX 120
 #define DRBD_CONNECT_INT_DEF 10   /* seconds */
+#define DRBD_CONNECT_INT_SCALE '1'
 
   /* keep-alive probes when idle */
 #define DRBD_PING_INT_MIN 1
 #define DRBD_PING_INT_MAX 120
 #define DRBD_PING_INT_DEF 10
+#define DRBD_PING_INT_SCALE '1'
 
  /* timeout for the ping packets.*/
 #define DRBD_PING_TIMEO_MIN  1
 #define DRBD_PING_TIMEO_MAX  300
 #define DRBD_PING_TIMEO_DEF  5
+#define DRBD_PING_TIMEO_SCALE '1'
 
   /* max number of write requests between write barriers */
 #define DRBD_MAX_EPOCH_SIZE_MIN 1
 #define DRBD_MAX_EPOCH_SIZE_MAX 20000
 #define DRBD_MAX_EPOCH_SIZE_DEF 2048
+#define DRBD_MAX_EPOCH_SIZE_SCALE '1'
 
   /* I don't think that a tcp send buffer of more than 10M is useful */
 #define DRBD_SNDBUF_SIZE_MIN  0
 #define DRBD_SNDBUF_SIZE_MAX  (10<<20)
 #define DRBD_SNDBUF_SIZE_DEF  0
+#define DRBD_SNDBUF_SIZE_SCALE '1'
 
 #define DRBD_RCVBUF_SIZE_MIN  0
 #define DRBD_RCVBUF_SIZE_MAX  (10<<20)
 #define DRBD_RCVBUF_SIZE_DEF  0
+#define DRBD_RCVBUF_SIZE_SCALE '1'
 
   /* @4k PageSize -> 128kB - 512MB */
 #define DRBD_MAX_BUFFERS_MIN  32
 #define DRBD_MAX_BUFFERS_MAX  131072
 #define DRBD_MAX_BUFFERS_DEF  2048
+#define DRBD_MAX_BUFFERS_SCALE '1'
 
   /* @4k PageSize -> 4kB - 512MB */
 #define DRBD_UNPLUG_WATERMARK_MIN  1
 #define DRBD_UNPLUG_WATERMARK_MAX  131072
 #define DRBD_UNPLUG_WATERMARK_DEF (DRBD_MAX_BUFFERS_DEF/16)
+#define DRBD_UNPLUG_WATERMARK_SCALE '1'
 
   /* 0 is disabled.
    * 200 should be more than enough even for very short timeouts */
 #define DRBD_KO_COUNT_MIN  0
 #define DRBD_KO_COUNT_MAX  200
-#define DRBD_KO_COUNT_DEF  0
+#define DRBD_KO_COUNT_DEF  7
+#define DRBD_KO_COUNT_SCALE '1'
 /* } */
 
 /* syncer { */
   /* FIXME allow rate to be zero? */
-#define DRBD_RATE_MIN 1
+#define DRBD_RESYNC_RATE_MIN 1
 /* channel bonding 10 GbE, or other hardware */
-#define DRBD_RATE_MAX (4 << 20)
-#define DRBD_RATE_DEF 250  /* kb/second */
+#define DRBD_RESYNC_RATE_MAX (4 << 20)
+#define DRBD_RESYNC_RATE_DEF 250
+#define DRBD_RESYNC_RATE_SCALE 'k'  /* kilobytes */
 
   /* less than 7 would hit performance unnecessarily.
-   * 3833 is the largest prime that still does fit
-   * into 64 sectors of activity log */
+   * 919 slots context information per transaction,
+   * 32k activity log, 4k transaction size,
+   * one transaction in flight:
+   * 919 * 7 = 6433 */
 #define DRBD_AL_EXTENTS_MIN  7
-#define DRBD_AL_EXTENTS_MAX  3833
-#define DRBD_AL_EXTENTS_DEF  127
+#define DRBD_AL_EXTENTS_MAX  6433
+#define DRBD_AL_EXTENTS_DEF  1237
+#define DRBD_AL_EXTENTS_SCALE '1'
 
-#define DRBD_AFTER_MIN  -1
-#define DRBD_AFTER_MAX  255
-#define DRBD_AFTER_DEF  -1
+#define DRBD_MINOR_NUMBER_MIN  -1
+#define DRBD_MINOR_NUMBER_MAX  ((1 << 20) - 1)
+#define DRBD_MINOR_NUMBER_DEF  -1
+#define DRBD_MINOR_NUMBER_SCALE '1'
 
 /* } */
 
@@ -124,11 +148,12 @@
  * the upper limit with 64bit kernel, enough ram and flexible meta data
  * is 1 PiB, currently. */
 /* DRBD_MAX_SECTORS */
-#define DRBD_DISK_SIZE_SECT_MIN  0
-#define DRBD_DISK_SIZE_SECT_MAX  (1 * (2LLU << 40))
-#define DRBD_DISK_SIZE_SECT_DEF  0 /* = disabled = no user size... */
+#define DRBD_DISK_SIZE_MIN  0
+#define DRBD_DISK_SIZE_MAX  (1 * (2LLU << 40))
+#define DRBD_DISK_SIZE_DEF  0 /* = disabled = no user size... */
+#define DRBD_DISK_SIZE_SCALE 's'  /* sectors */
 
-#define DRBD_ON_IO_ERROR_DEF EP_PASS_ON
+#define DRBD_ON_IO_ERROR_DEF EP_DETACH
 #define DRBD_FENCING_DEF FP_DONT_CARE
 #define DRBD_AFTER_SB_0P_DEF ASB_DISCONNECT
 #define DRBD_AFTER_SB_1P_DEF ASB_DISCONNECT
@@ -136,38 +161,59 @@
 #define DRBD_RR_CONFLICT_DEF ASB_DISCONNECT
 #define DRBD_ON_NO_DATA_DEF OND_IO_ERROR
 #define DRBD_ON_CONGESTION_DEF OC_BLOCK
+#define DRBD_READ_BALANCING_DEF RB_PREFER_LOCAL
 
 #define DRBD_MAX_BIO_BVECS_MIN 0
 #define DRBD_MAX_BIO_BVECS_MAX 128
 #define DRBD_MAX_BIO_BVECS_DEF 0
+#define DRBD_MAX_BIO_BVECS_SCALE '1'
 
 #define DRBD_C_PLAN_AHEAD_MIN  0
 #define DRBD_C_PLAN_AHEAD_MAX  300
-#define DRBD_C_PLAN_AHEAD_DEF  0 /* RS rate controller disabled by default */
+#define DRBD_C_PLAN_AHEAD_DEF  20
+#define DRBD_C_PLAN_AHEAD_SCALE '1'
 
 #define DRBD_C_DELAY_TARGET_MIN 1
 #define DRBD_C_DELAY_TARGET_MAX 100
 #define DRBD_C_DELAY_TARGET_DEF 10
+#define DRBD_C_DELAY_TARGET_SCALE '1'
 
 #define DRBD_C_FILL_TARGET_MIN 0
 #define DRBD_C_FILL_TARGET_MAX (1<<20) /* 500MByte in sec */
-#define DRBD_C_FILL_TARGET_DEF 0 /* By default disabled -> controlled by delay_target */
+#define DRBD_C_FILL_TARGET_DEF 100 /* Try to place 50KiB in socket send buffer during resync */
+#define DRBD_C_FILL_TARGET_SCALE 's'  /* sectors */
 
-#define DRBD_C_MAX_RATE_MIN     250 /* kByte/sec */
+#define DRBD_C_MAX_RATE_MIN     250
 #define DRBD_C_MAX_RATE_MAX     (4 << 20)
 #define DRBD_C_MAX_RATE_DEF     102400
+#define DRBD_C_MAX_RATE_SCALE	'k'  /* kilobytes */
 
-#define DRBD_C_MIN_RATE_MIN     0 /* kByte/sec */
+#define DRBD_C_MIN_RATE_MIN     0
 #define DRBD_C_MIN_RATE_MAX     (4 << 20)
-#define DRBD_C_MIN_RATE_DEF     4096
+#define DRBD_C_MIN_RATE_DEF     250
+#define DRBD_C_MIN_RATE_SCALE	'k'  /* kilobytes */
 
 #define DRBD_CONG_FILL_MIN	0
 #define DRBD_CONG_FILL_MAX	(10<<21) /* 10GByte in sectors */
 #define DRBD_CONG_FILL_DEF	0
+#define DRBD_CONG_FILL_SCALE	's'  /* sectors */
 
 #define DRBD_CONG_EXTENTS_MIN	DRBD_AL_EXTENTS_MIN
 #define DRBD_CONG_EXTENTS_MAX	DRBD_AL_EXTENTS_MAX
 #define DRBD_CONG_EXTENTS_DEF	DRBD_AL_EXTENTS_DEF
+#define DRBD_CONG_EXTENTS_SCALE DRBD_AL_EXTENTS_SCALE
+
+#define DRBD_PROTOCOL_DEF DRBD_PROT_C
+
+#define DRBD_DISK_BARRIER_DEF	0
+#define DRBD_DISK_FLUSHES_DEF	1
+#define DRBD_DISK_DRAIN_DEF	1
+#define DRBD_MD_FLUSHES_DEF	1
+#define DRBD_TCP_CORK_DEF	1
+#define DRBD_AL_UPDATES_DEF     1
+
+#define DRBD_ALLOW_TWO_PRIMARIES_DEF	0
+#define DRBD_ALWAYS_ASBP_DEF	0
+#define DRBD_USE_RLE_DEF	1
 
-#undef RANGE
 #endif
diff --git a/include/linux/drbd_nl.h b/include/linux/drbd_nl.h
deleted file mode 100644
index a8706f0..0000000
--- a/include/linux/drbd_nl.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
-   PAKET( name,
-	  TYPE ( pn, pr, member )
-	  ...
-   )
-
-   You may never reissue one of the pn arguments
-*/
-
-#if !defined(NL_PACKET) || !defined(NL_STRING) || !defined(NL_INTEGER) || !defined(NL_BIT) || !defined(NL_INT64)
-#error "The macros NL_PACKET, NL_STRING, NL_INTEGER, NL_INT64 and NL_BIT needs to be defined"
-#endif
-
-NL_PACKET(primary, 1,
-       NL_BIT(		1,	T_MAY_IGNORE,	primary_force)
-)
-
-NL_PACKET(secondary, 2, )
-
-NL_PACKET(disk_conf, 3,
-	NL_INT64(	2,	T_MAY_IGNORE,	disk_size)
-	NL_STRING(	3,	T_MANDATORY,	backing_dev,	128)
-	NL_STRING(	4,	T_MANDATORY,	meta_dev,	128)
-	NL_INTEGER(	5,	T_MANDATORY,	meta_dev_idx)
-	NL_INTEGER(	6,	T_MAY_IGNORE,	on_io_error)
-	NL_INTEGER(	7,	T_MAY_IGNORE,	fencing)
-	NL_BIT(		37,	T_MAY_IGNORE,	use_bmbv)
-	NL_BIT(		53,	T_MAY_IGNORE,	no_disk_flush)
-	NL_BIT(		54,	T_MAY_IGNORE,	no_md_flush)
-	  /*  55 max_bio_size was available in 8.2.6rc2 */
-	NL_INTEGER(	56,	T_MAY_IGNORE,	max_bio_bvecs)
-	NL_BIT(		57,	T_MAY_IGNORE,	no_disk_barrier)
-	NL_BIT(		58,	T_MAY_IGNORE,	no_disk_drain)
-	NL_INTEGER(	89,	T_MAY_IGNORE,	disk_timeout)
-)
-
-NL_PACKET(detach, 4,
-	NL_BIT(		88,	T_MANDATORY,	detach_force)
-)
-
-NL_PACKET(net_conf, 5,
-	NL_STRING(	8,	T_MANDATORY,	my_addr,	128)
-	NL_STRING(	9,	T_MANDATORY,	peer_addr,	128)
-	NL_STRING(	10,	T_MAY_IGNORE,	shared_secret,	SHARED_SECRET_MAX)
-	NL_STRING(	11,	T_MAY_IGNORE,	cram_hmac_alg,	SHARED_SECRET_MAX)
-	NL_STRING(	44,	T_MAY_IGNORE,	integrity_alg,	SHARED_SECRET_MAX)
-	NL_INTEGER(	14,	T_MAY_IGNORE,	timeout)
-	NL_INTEGER(	15,	T_MANDATORY,	wire_protocol)
-	NL_INTEGER(	16,	T_MAY_IGNORE,	try_connect_int)
-	NL_INTEGER(	17,	T_MAY_IGNORE,	ping_int)
-	NL_INTEGER(	18,	T_MAY_IGNORE,	max_epoch_size)
-	NL_INTEGER(	19,	T_MAY_IGNORE,	max_buffers)
-	NL_INTEGER(	20,	T_MAY_IGNORE,	unplug_watermark)
-	NL_INTEGER(	21,	T_MAY_IGNORE,	sndbuf_size)
-	NL_INTEGER(	22,	T_MAY_IGNORE,	ko_count)
-	NL_INTEGER(	24,	T_MAY_IGNORE,	after_sb_0p)
-	NL_INTEGER(	25,	T_MAY_IGNORE,	after_sb_1p)
-	NL_INTEGER(	26,	T_MAY_IGNORE,	after_sb_2p)
-	NL_INTEGER(	39,	T_MAY_IGNORE,	rr_conflict)
-	NL_INTEGER(	40,	T_MAY_IGNORE,	ping_timeo)
-	NL_INTEGER(	67,	T_MAY_IGNORE,	rcvbuf_size)
-	NL_INTEGER(	81,	T_MAY_IGNORE,	on_congestion)
-	NL_INTEGER(	82,	T_MAY_IGNORE,	cong_fill)
-	NL_INTEGER(	83,	T_MAY_IGNORE,	cong_extents)
-	  /* 59 addr_family was available in GIT, never released */
-	NL_BIT(		60,	T_MANDATORY,	mind_af)
-	NL_BIT(		27,	T_MAY_IGNORE,	want_lose)
-	NL_BIT(		28,	T_MAY_IGNORE,	two_primaries)
-	NL_BIT(		41,	T_MAY_IGNORE,	always_asbp)
-	NL_BIT(		61,	T_MAY_IGNORE,	no_cork)
-	NL_BIT(		62,	T_MANDATORY,	auto_sndbuf_size)
-	NL_BIT(		70,	T_MANDATORY,	dry_run)
-)
-
-NL_PACKET(disconnect, 6,
-	NL_BIT(		84,	T_MAY_IGNORE,	force)
-)
-
-NL_PACKET(resize, 7,
-	NL_INT64(		29,	T_MAY_IGNORE,	resize_size)
-	NL_BIT(			68,	T_MAY_IGNORE,	resize_force)
-	NL_BIT(			69,	T_MANDATORY,	no_resync)
-)
-
-NL_PACKET(syncer_conf, 8,
-	NL_INTEGER(	30,	T_MAY_IGNORE,	rate)
-	NL_INTEGER(	31,	T_MAY_IGNORE,	after)
-	NL_INTEGER(	32,	T_MAY_IGNORE,	al_extents)
-/*	NL_INTEGER(     71,	T_MAY_IGNORE,	dp_volume)
- *	NL_INTEGER(     72,	T_MAY_IGNORE,	dp_interval)
- *	NL_INTEGER(     73,	T_MAY_IGNORE,	throttle_th)
- *	NL_INTEGER(     74,	T_MAY_IGNORE,	hold_off_th)
- * feature will be reimplemented differently with 8.3.9 */
-	NL_STRING(      52,     T_MAY_IGNORE,   verify_alg,     SHARED_SECRET_MAX)
-	NL_STRING(      51,     T_MAY_IGNORE,   cpu_mask,       32)
-	NL_STRING(	64,	T_MAY_IGNORE,	csums_alg,	SHARED_SECRET_MAX)
-	NL_BIT(         65,     T_MAY_IGNORE,   use_rle)
-	NL_INTEGER(	75,	T_MAY_IGNORE,	on_no_data)
-	NL_INTEGER(	76,	T_MAY_IGNORE,	c_plan_ahead)
-	NL_INTEGER(     77,	T_MAY_IGNORE,	c_delay_target)
-	NL_INTEGER(     78,	T_MAY_IGNORE,	c_fill_target)
-	NL_INTEGER(     79,	T_MAY_IGNORE,	c_max_rate)
-	NL_INTEGER(     80,	T_MAY_IGNORE,	c_min_rate)
-)
-
-NL_PACKET(invalidate, 9, )
-NL_PACKET(invalidate_peer, 10, )
-NL_PACKET(pause_sync, 11, )
-NL_PACKET(resume_sync, 12, )
-NL_PACKET(suspend_io, 13, )
-NL_PACKET(resume_io, 14, )
-NL_PACKET(outdate, 15, )
-NL_PACKET(get_config, 16, )
-NL_PACKET(get_state, 17,
-	NL_INTEGER(	33,	T_MAY_IGNORE,	state_i)
-)
-
-NL_PACKET(get_uuids, 18,
-	NL_STRING(	34,	T_MAY_IGNORE,	uuids,	(UI_SIZE*sizeof(__u64)))
-	NL_INTEGER(	35,	T_MAY_IGNORE,	uuids_flags)
-)
-
-NL_PACKET(get_timeout_flag, 19,
-	NL_BIT(		36,	T_MAY_IGNORE,	use_degraded)
-)
-
-NL_PACKET(call_helper, 20,
-	NL_STRING(	38,	T_MAY_IGNORE,	helper,		32)
-)
-
-/* Tag nr 42 already allocated in drbd-8.1 development. */
-
-NL_PACKET(sync_progress, 23,
-	NL_INTEGER(	43,	T_MAY_IGNORE,	sync_progress)
-)
-
-NL_PACKET(dump_ee, 24,
-	NL_STRING(	45,	T_MAY_IGNORE,	dump_ee_reason, 32)
-	NL_STRING(	46,	T_MAY_IGNORE,	seen_digest, SHARED_SECRET_MAX)
-	NL_STRING(	47,	T_MAY_IGNORE,	calc_digest, SHARED_SECRET_MAX)
-	NL_INT64(	48,	T_MAY_IGNORE,	ee_sector)
-	NL_INT64(	49,	T_MAY_IGNORE,	ee_block_id)
-	NL_STRING(	50,	T_MAY_IGNORE,	ee_data,	32 << 10)
-)
-
-NL_PACKET(start_ov, 25,
-	NL_INT64(	66,	T_MAY_IGNORE,	start_sector)
-)
-
-NL_PACKET(new_c_uuid, 26,
-       NL_BIT(		63,	T_MANDATORY,	clear_bm)
-)
-
-#ifdef NL_RESPONSE
-NL_RESPONSE(return_code_only, 27)
-#endif
-
-#undef NL_PACKET
-#undef NL_INTEGER
-#undef NL_INT64
-#undef NL_BIT
-#undef NL_STRING
-#undef NL_RESPONSE
diff --git a/include/linux/drbd_tag_magic.h b/include/linux/drbd_tag_magic.h
deleted file mode 100644
index 82de1f9..0000000
--- a/include/linux/drbd_tag_magic.h
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef DRBD_TAG_MAGIC_H
-#define DRBD_TAG_MAGIC_H
-
-#define TT_END     0
-#define TT_REMOVED 0xE000
-
-/* declare packet_type enums */
-enum packet_types {
-#define NL_PACKET(name, number, fields) P_ ## name = number,
-#define NL_RESPONSE(name, number) P_ ## name = number,
-#define NL_INTEGER(pn, pr, member)
-#define NL_INT64(pn, pr, member)
-#define NL_BIT(pn, pr, member)
-#define NL_STRING(pn, pr, member, len)
-#include <linux/drbd_nl.h>
-	P_nl_after_last_packet,
-};
-
-/* These struct are used to deduce the size of the tag lists: */
-#define NL_PACKET(name, number, fields)	\
-	struct name ## _tag_len_struct { fields };
-#define NL_INTEGER(pn, pr, member)		\
-	int member; int tag_and_len ## member;
-#define NL_INT64(pn, pr, member)		\
-	__u64 member; int tag_and_len ## member;
-#define NL_BIT(pn, pr, member)		\
-	unsigned char member:1; int tag_and_len ## member;
-#define NL_STRING(pn, pr, member, len)	\
-	unsigned char member[len]; int member ## _len; \
-	int tag_and_len ## member;
-#include <linux/drbd_nl.h>
-
-/* declare tag-list-sizes */
-static const int tag_list_sizes[] = {
-#define NL_PACKET(name, number, fields) 2 fields ,
-#define NL_INTEGER(pn, pr, member)      + 4 + 4
-#define NL_INT64(pn, pr, member)        + 4 + 8
-#define NL_BIT(pn, pr, member)          + 4 + 1
-#define NL_STRING(pn, pr, member, len)  + 4 + (len)
-#include <linux/drbd_nl.h>
-};
-
-/* The two highest bits are used for the tag type */
-#define TT_MASK      0xC000
-#define TT_INTEGER   0x0000
-#define TT_INT64     0x4000
-#define TT_BIT       0x8000
-#define TT_STRING    0xC000
-/* The next bit indicates if processing of the tag is mandatory */
-#define T_MANDATORY  0x2000
-#define T_MAY_IGNORE 0x0000
-#define TN_MASK      0x1fff
-/* The remaining 13 bits are used to enumerate the tags */
-
-#define tag_type(T)   ((T) & TT_MASK)
-#define tag_number(T) ((T) & TN_MASK)
-
-/* declare tag enums */
-#define NL_PACKET(name, number, fields) fields
-enum drbd_tags {
-#define NL_INTEGER(pn, pr, member)     T_ ## member = pn | TT_INTEGER | pr ,
-#define NL_INT64(pn, pr, member)       T_ ## member = pn | TT_INT64   | pr ,
-#define NL_BIT(pn, pr, member)         T_ ## member = pn | TT_BIT     | pr ,
-#define NL_STRING(pn, pr, member, len) T_ ## member = pn | TT_STRING  | pr ,
-#include <linux/drbd_nl.h>
-};
-
-struct tag {
-	const char *name;
-	int type_n_flags;
-	int max_len;
-};
-
-/* declare tag names */
-#define NL_PACKET(name, number, fields) fields
-static const struct tag tag_descriptions[] = {
-#define NL_INTEGER(pn, pr, member)     [ pn ] = { #member, TT_INTEGER | pr, sizeof(int)   },
-#define NL_INT64(pn, pr, member)       [ pn ] = { #member, TT_INT64   | pr, sizeof(__u64) },
-#define NL_BIT(pn, pr, member)         [ pn ] = { #member, TT_BIT     | pr, sizeof(int)   },
-#define NL_STRING(pn, pr, member, len) [ pn ] = { #member, TT_STRING  | pr, (len)         },
-#include <linux/drbd_nl.h>
-};
-
-#endif
diff --git a/include/linux/dvb/Kbuild b/include/linux/dvb/Kbuild
deleted file mode 100644
index e69de29..0000000
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
deleted file mode 100644
index 0be6d8f..0000000
--- a/include/linux/dvb/dmx.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * dmx.h
- *
- * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
- *                  & Ralph  Metzler <ralph@convergence.de>
- *                    for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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 _DVBDMX_H_
-#define _DVBDMX_H_
-
-#include <linux/time.h>
-#include <uapi/linux/dvb/dmx.h>
-
-#endif /*_DVBDMX_H_*/
diff --git a/include/linux/dvb/video.h b/include/linux/dvb/video.h
deleted file mode 100644
index 85c20d9..0000000
--- a/include/linux/dvb/video.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * video.h
- *
- * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
- *                  & Ralph  Metzler <ralph@convergence.de>
- *                    for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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 _DVBVIDEO_H_
-#define _DVBVIDEO_H_
-
-#include <linux/compiler.h>
-#include <uapi/linux/dvb/video.h>
-
-#endif /*_DVBVIDEO_H_*/
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
index e1c8c9e..41766de 100644
--- a/include/linux/dw_dmac.h
+++ b/include/linux/dw_dmac.h
@@ -15,14 +15,38 @@
 #include <linux/dmaengine.h>
 
 /**
+ * struct dw_dma_slave - Controller-specific information about a slave
+ *
+ * @dma_dev: required DMA master device. Depricated.
+ * @bus_id: name of this device channel, not just a device name since
+ *          devices may have more than one channel e.g. "foo_tx"
+ * @cfg_hi: Platform-specific initializer for the CFG_HI register
+ * @cfg_lo: Platform-specific initializer for the CFG_LO register
+ * @src_master: src master for transfers on allocated channel.
+ * @dst_master: dest master for transfers on allocated channel.
+ */
+struct dw_dma_slave {
+	struct device		*dma_dev;
+	const char		*bus_id;
+	u32			cfg_hi;
+	u32			cfg_lo;
+	u8			src_master;
+	u8			dst_master;
+};
+
+/**
  * struct dw_dma_platform_data - Controller configuration parameters
  * @nr_channels: Number of channels supported by hardware (max 8)
  * @is_private: The device channels should be marked as private and not for
  *	by the general purpose DMA channel allocator.
+ * @chan_allocation_order: Allocate channels starting from 0 or 7
+ * @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0.
  * @block_size: Maximum block size supported by the controller
  * @nr_masters: Number of AHB masters supported by the controller
  * @data_width: Maximum data width supported by hardware per AHB master
  *		(0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
+ * @sd: slave specific data. Used for configuring channels
+ * @sd_count: count of slave data structures passed.
  */
 struct dw_dma_platform_data {
 	unsigned int	nr_channels;
@@ -36,6 +60,9 @@ struct dw_dma_platform_data {
 	unsigned short	block_size;
 	unsigned char	nr_masters;
 	unsigned char	data_width[4];
+
+	struct dw_dma_slave *sd;
+	unsigned int sd_count;
 };
 
 /* bursts size */
@@ -50,23 +77,6 @@ enum dw_dma_msize {
 	DW_DMA_MSIZE_256,
 };
 
-/**
- * struct dw_dma_slave - Controller-specific information about a slave
- *
- * @dma_dev: required DMA master device
- * @cfg_hi: Platform-specific initializer for the CFG_HI register
- * @cfg_lo: Platform-specific initializer for the CFG_LO register
- * @src_master: src master for transfers on allocated channel.
- * @dst_master: dest master for transfers on allocated channel.
- */
-struct dw_dma_slave {
-	struct device		*dma_dev;
-	u32			cfg_hi;
-	u32			cfg_lo;
-	u8			src_master;
-	u8			dst_master;
-};
-
 /* Platform-configurable bits in CFG_HI */
 #define DWC_CFGH_FCMODE		(1 << 0)
 #define DWC_CFGH_FIFO_MODE	(1 << 1)
@@ -104,5 +114,6 @@ void dw_dma_cyclic_stop(struct dma_chan *chan);
 dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan);
 
 dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan);
+bool dw_dma_generic_filter(struct dma_chan *chan, void *param);
 
 #endif /* DW_DMAC_H */
diff --git a/include/linux/earlycpio.h b/include/linux/earlycpio.h
new file mode 100644
index 0000000..111f46d
--- /dev/null
+++ b/include/linux/earlycpio.h
@@ -0,0 +1,17 @@
+#ifndef _LINUX_EARLYCPIO_H
+#define _LINUX_EARLYCPIO_H
+
+#include <linux/types.h>
+
+#define MAX_CPIO_FILE_NAME 18
+
+struct cpio_data {
+	void *data;
+	size_t size;
+	char name[MAX_CPIO_FILE_NAME];
+};
+
+struct cpio_data find_cpio_data(const char *path, void *data, size_t len,
+				long *offset);
+
+#endif /* _LINUX_EARLYCPIO_H */
diff --git a/include/linux/edac.h b/include/linux/edac.h
index bab9f84..4784213 100644
--- a/include/linux/edac.h
+++ b/include/linux/edac.h
@@ -14,7 +14,6 @@
 
 #include <linux/atomic.h>
 #include <linux/device.h>
-#include <linux/kobject.h>
 #include <linux/completion.h>
 #include <linux/workqueue.h>
 #include <linux/debugfs.h>
@@ -533,6 +532,7 @@ struct csrow_info {
 
 	u32 ue_count;		/* Uncorrectable Errors for this csrow */
 	u32 ce_count;		/* Correctable Errors for this csrow */
+	u32 nr_pages;		/* combined pages count of all channels */
 
 	struct mem_ctl_info *mci;	/* the parent */
 
@@ -667,6 +667,8 @@ struct mem_ctl_info {
 	u32 fake_inject_ue;
 	u16 fake_inject_count;
 #endif
+	__u8 csbased : 1,	/* csrow-based memory controller */
+	     __resv  : 7;
 };
 
 #endif
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 8670eb1..c47ec36 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -643,6 +643,7 @@ struct efivar_operations {
 	efi_get_variable_t *get_variable;
 	efi_get_next_variable_t *get_next_variable;
 	efi_set_variable_t *set_variable;
+	efi_query_variable_info_t *query_variable_info;
 };
 
 struct efivars {
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index b006ba0..243eea1 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -51,6 +51,26 @@ extern struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs,
 #define alloc_etherdev(sizeof_priv) alloc_etherdev_mq(sizeof_priv, 1)
 #define alloc_etherdev_mq(sizeof_priv, count) alloc_etherdev_mqs(sizeof_priv, count, count)
 
+/* Reserved Ethernet Addresses per IEEE 802.1Q */
+static const u8 eth_reserved_addr_base[ETH_ALEN] __aligned(2) =
+{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
+
+/**
+ * is_link_local_ether_addr - Determine if given Ethernet address is link-local
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if address is link local reserved addr (01:80:c2:00:00:0X) per
+ * IEEE 802.1Q 8.6.3 Frame filtering.
+ */
+static inline bool is_link_local_ether_addr(const u8 *addr)
+{
+	__be16 *a = (__be16 *)addr;
+	static const __be16 *b = (const __be16 *)eth_reserved_addr_base;
+	static const __be16 m = cpu_to_be16(0xfff0);
+
+	return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | ((a[2] ^ b[2]) & m)) == 0;
+}
+
 /**
  * is_zero_ether_addr - Determine if give Ethernet address is all zeros.
  * @addr: Pointer to a six-byte array containing the Ethernet address
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index 12291a7..5b9b5b3 100644
--- a/include/linux/exportfs.h
+++ b/include/linux/exportfs.h
@@ -83,6 +83,11 @@ enum fid_type {
 	 * 64 bit parent inode number.
 	 */
 	FILEID_NILFS_WITH_PARENT = 0x62,
+
+	/*
+	 * Filesystems must not use 0xff file ID.
+	 */
+	FILEID_INVALID = 0xff,
 };
 
 struct fid {
@@ -177,6 +182,8 @@ struct export_operations {
 	int (*commit_metadata)(struct inode *inode);
 };
 
+extern int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid,
+				    int *max_len, struct inode *parent);
 extern int exportfs_encode_fh(struct dentry *dentry, struct fid *fid,
 	int *max_len, int connectable);
 extern struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
diff --git a/include/linux/extcon.h b/include/linux/extcon.h
index 2c26c14..fcb51c8 100644
--- a/include/linux/extcon.h
+++ b/include/linux/extcon.h
@@ -23,7 +23,9 @@
 #ifndef __LINUX_EXTCON_H__
 #define __LINUX_EXTCON_H__
 
+#include <linux/device.h>
 #include <linux/notifier.h>
+#include <linux/sysfs.h>
 
 #define SUPPORTED_CABLE_MAX	32
 #define CABLE_NAME_MAX		30
@@ -74,12 +76,12 @@ struct extcon_cable;
 
 /**
  * struct extcon_dev - An extcon device represents one external connector.
- * @name	The name of this extcon device. Parent device name is used
+ * @name:	The name of this extcon device. Parent device name is used
  *		if NULL.
- * @supported_cable	Array of supported cable names ending with NULL.
+ * @supported_cable:	Array of supported cable names ending with NULL.
  *			If supported_cable is NULL, cable name related APIs
  *			are disabled.
- * @mutually_exclusive	Array of mutually exclusive set of cables that cannot
+ * @mutually_exclusive:	Array of mutually exclusive set of cables that cannot
  *			be attached simultaneously. The array should be
  *			ending with NULL or be NULL (no mutually exclusive
  *			cables). For example, if it is { 0x7, 0x30, 0}, then,
@@ -87,21 +89,21 @@ struct extcon_cable;
  *			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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @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,
@@ -137,12 +139,12 @@ struct extcon_dev {
 
 /**
  * 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
+ * @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
  */
 struct extcon_cable {
 	struct extcon_dev *edev;
@@ -158,11 +160,11 @@ struct extcon_cable {
 /**
  * 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.
- * @cable_index	the target cable.
- * @edev	the target extcon device.
- * @previous_value	the saved previous event value.
+ * @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.
+ * @previous_value:	the saved previous event value.
  */
 struct extcon_specific_cable_nb {
 	struct notifier_block internal_nb;
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
new file mode 100644
index 0000000..1429ece
--- /dev/null
+++ b/include/linux/f2fs_fs.h
@@ -0,0 +1,410 @@
+/**
+ * include/linux/f2fs_fs.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _LINUX_F2FS_FS_H
+#define _LINUX_F2FS_FS_H
+
+#include <linux/pagemap.h>
+#include <linux/types.h>
+
+#define F2FS_SUPER_OFFSET		1024	/* byte-size offset */
+#define F2FS_LOG_SECTOR_SIZE		9	/* 9 bits for 512 byte */
+#define F2FS_LOG_SECTORS_PER_BLOCK	3	/* 4KB: F2FS_BLKSIZE */
+#define F2FS_BLKSIZE			4096	/* support only 4KB block */
+#define F2FS_MAX_EXTENSION		64	/* # of extension entries */
+
+#define NULL_ADDR		0x0U
+#define NEW_ADDR		-1U
+
+#define F2FS_ROOT_INO(sbi)	(sbi->root_ino_num)
+#define F2FS_NODE_INO(sbi)	(sbi->node_ino_num)
+#define F2FS_META_INO(sbi)	(sbi->meta_ino_num)
+
+/* This flag is used by node and meta inodes, and by recovery */
+#define GFP_F2FS_ZERO	(GFP_NOFS | __GFP_ZERO)
+
+/*
+ * For further optimization on multi-head logs, on-disk layout supports maximum
+ * 16 logs by default. The number, 16, is expected to cover all the cases
+ * enoughly. The implementaion currently uses no more than 6 logs.
+ * Half the logs are used for nodes, and the other half are used for data.
+ */
+#define MAX_ACTIVE_LOGS	16
+#define MAX_ACTIVE_NODE_LOGS	8
+#define MAX_ACTIVE_DATA_LOGS	8
+
+/*
+ * For superblock
+ */
+struct f2fs_super_block {
+	__le32 magic;			/* Magic Number */
+	__le16 major_ver;		/* Major Version */
+	__le16 minor_ver;		/* Minor Version */
+	__le32 log_sectorsize;		/* log2 sector size in bytes */
+	__le32 log_sectors_per_block;	/* log2 # of sectors per block */
+	__le32 log_blocksize;		/* log2 block size in bytes */
+	__le32 log_blocks_per_seg;	/* log2 # of blocks per segment */
+	__le32 segs_per_sec;		/* # of segments per section */
+	__le32 secs_per_zone;		/* # of sections per zone */
+	__le32 checksum_offset;		/* checksum offset inside super block */
+	__le64 block_count;		/* total # of user blocks */
+	__le32 section_count;		/* total # of sections */
+	__le32 segment_count;		/* total # of segments */
+	__le32 segment_count_ckpt;	/* # of segments for checkpoint */
+	__le32 segment_count_sit;	/* # of segments for SIT */
+	__le32 segment_count_nat;	/* # of segments for NAT */
+	__le32 segment_count_ssa;	/* # of segments for SSA */
+	__le32 segment_count_main;	/* # of segments for main area */
+	__le32 segment0_blkaddr;	/* start block address of segment 0 */
+	__le32 cp_blkaddr;		/* start block address of checkpoint */
+	__le32 sit_blkaddr;		/* start block address of SIT */
+	__le32 nat_blkaddr;		/* start block address of NAT */
+	__le32 ssa_blkaddr;		/* start block address of SSA */
+	__le32 main_blkaddr;		/* start block address of main area */
+	__le32 root_ino;		/* root inode number */
+	__le32 node_ino;		/* node inode number */
+	__le32 meta_ino;		/* meta inode number */
+	__u8 uuid[16];			/* 128-bit uuid for volume */
+	__le16 volume_name[512];	/* volume name */
+	__le32 extension_count;		/* # of extensions below */
+	__u8 extension_list[F2FS_MAX_EXTENSION][8];	/* extension array */
+} __packed;
+
+/*
+ * For checkpoint
+ */
+#define CP_ERROR_FLAG		0x00000008
+#define CP_COMPACT_SUM_FLAG	0x00000004
+#define CP_ORPHAN_PRESENT_FLAG	0x00000002
+#define CP_UMOUNT_FLAG		0x00000001
+
+struct f2fs_checkpoint {
+	__le64 checkpoint_ver;		/* checkpoint block version number */
+	__le64 user_block_count;	/* # of user blocks */
+	__le64 valid_block_count;	/* # of valid blocks in main area */
+	__le32 rsvd_segment_count;	/* # of reserved segments for gc */
+	__le32 overprov_segment_count;	/* # of overprovision segments */
+	__le32 free_segment_count;	/* # of free segments in main area */
+
+	/* information of current node segments */
+	__le32 cur_node_segno[MAX_ACTIVE_NODE_LOGS];
+	__le16 cur_node_blkoff[MAX_ACTIVE_NODE_LOGS];
+	/* information of current data segments */
+	__le32 cur_data_segno[MAX_ACTIVE_DATA_LOGS];
+	__le16 cur_data_blkoff[MAX_ACTIVE_DATA_LOGS];
+	__le32 ckpt_flags;		/* Flags : umount and journal_present */
+	__le32 cp_pack_total_block_count;	/* total # of one cp pack */
+	__le32 cp_pack_start_sum;	/* start block number of data summary */
+	__le32 valid_node_count;	/* Total number of valid nodes */
+	__le32 valid_inode_count;	/* Total number of valid inodes */
+	__le32 next_free_nid;		/* Next free node number */
+	__le32 sit_ver_bitmap_bytesize;	/* Default value 64 */
+	__le32 nat_ver_bitmap_bytesize; /* Default value 256 */
+	__le32 checksum_offset;		/* checksum offset inside cp block */
+	__le64 elapsed_time;		/* mounted time */
+	/* allocation type of current segment */
+	unsigned char alloc_type[MAX_ACTIVE_LOGS];
+
+	/* SIT and NAT version bitmap */
+	unsigned char sit_nat_version_bitmap[1];
+} __packed;
+
+/*
+ * For orphan inode management
+ */
+#define F2FS_ORPHANS_PER_BLOCK	1020
+
+struct f2fs_orphan_block {
+	__le32 ino[F2FS_ORPHANS_PER_BLOCK];	/* inode numbers */
+	__le32 reserved;	/* reserved */
+	__le16 blk_addr;	/* block index in current CP */
+	__le16 blk_count;	/* Number of orphan inode blocks in CP */
+	__le32 entry_count;	/* Total number of orphan nodes in current CP */
+	__le32 check_sum;	/* CRC32 for orphan inode block */
+} __packed;
+
+/*
+ * For NODE structure
+ */
+struct f2fs_extent {
+	__le32 fofs;		/* start file offset of the extent */
+	__le32 blk_addr;	/* start block address of the extent */
+	__le32 len;		/* lengh of the extent */
+} __packed;
+
+#define F2FS_MAX_NAME_LEN	256
+#define ADDRS_PER_INODE         923	/* Address Pointers in an Inode */
+#define ADDRS_PER_BLOCK         1018	/* Address Pointers in a Direct Block */
+#define NIDS_PER_BLOCK          1018	/* Node IDs in an Indirect Block */
+
+struct f2fs_inode {
+	__le16 i_mode;			/* file mode */
+	__u8 i_advise;			/* file hints */
+	__u8 i_reserved;		/* reserved */
+	__le32 i_uid;			/* user ID */
+	__le32 i_gid;			/* group ID */
+	__le32 i_links;			/* links count */
+	__le64 i_size;			/* file size in bytes */
+	__le64 i_blocks;		/* file size in blocks */
+	__le64 i_atime;			/* access time */
+	__le64 i_ctime;			/* change time */
+	__le64 i_mtime;			/* modification time */
+	__le32 i_atime_nsec;		/* access time in nano scale */
+	__le32 i_ctime_nsec;		/* change time in nano scale */
+	__le32 i_mtime_nsec;		/* modification time in nano scale */
+	__le32 i_generation;		/* file version (for NFS) */
+	__le32 i_current_depth;		/* only for directory depth */
+	__le32 i_xattr_nid;		/* nid to save xattr */
+	__le32 i_flags;			/* file attributes */
+	__le32 i_pino;			/* parent inode number */
+	__le32 i_namelen;		/* file name length */
+	__u8 i_name[F2FS_MAX_NAME_LEN];	/* file name for SPOR */
+
+	struct f2fs_extent i_ext;	/* caching a largest extent */
+
+	__le32 i_addr[ADDRS_PER_INODE];	/* Pointers to data blocks */
+
+	__le32 i_nid[5];		/* direct(2), indirect(2),
+						double_indirect(1) node id */
+} __packed;
+
+struct direct_node {
+	__le32 addr[ADDRS_PER_BLOCK];	/* array of data block address */
+} __packed;
+
+struct indirect_node {
+	__le32 nid[NIDS_PER_BLOCK];	/* array of data block address */
+} __packed;
+
+enum {
+	COLD_BIT_SHIFT = 0,
+	FSYNC_BIT_SHIFT,
+	DENT_BIT_SHIFT,
+	OFFSET_BIT_SHIFT
+};
+
+struct node_footer {
+	__le32 nid;		/* node id */
+	__le32 ino;		/* inode nunmber */
+	__le32 flag;		/* include cold/fsync/dentry marks and offset */
+	__le64 cp_ver;		/* checkpoint version */
+	__le32 next_blkaddr;	/* next node page block address */
+} __packed;
+
+struct f2fs_node {
+	/* can be one of three types: inode, direct, and indirect types */
+	union {
+		struct f2fs_inode i;
+		struct direct_node dn;
+		struct indirect_node in;
+	};
+	struct node_footer footer;
+} __packed;
+
+/*
+ * For NAT entries
+ */
+#define NAT_ENTRY_PER_BLOCK (PAGE_CACHE_SIZE / sizeof(struct f2fs_nat_entry))
+
+struct f2fs_nat_entry {
+	__u8 version;		/* latest version of cached nat entry */
+	__le32 ino;		/* inode number */
+	__le32 block_addr;	/* block address */
+} __packed;
+
+struct f2fs_nat_block {
+	struct f2fs_nat_entry entries[NAT_ENTRY_PER_BLOCK];
+} __packed;
+
+/*
+ * For SIT entries
+ *
+ * Each segment is 2MB in size by default so that a bitmap for validity of
+ * there-in blocks should occupy 64 bytes, 512 bits.
+ * Not allow to change this.
+ */
+#define SIT_VBLOCK_MAP_SIZE 64
+#define SIT_ENTRY_PER_BLOCK (PAGE_CACHE_SIZE / sizeof(struct f2fs_sit_entry))
+
+/*
+ * Note that f2fs_sit_entry->vblocks has the following bit-field information.
+ * [15:10] : allocation type such as CURSEG_XXXX_TYPE
+ * [9:0] : valid block count
+ */
+#define SIT_VBLOCKS_SHIFT	10
+#define SIT_VBLOCKS_MASK	((1 << SIT_VBLOCKS_SHIFT) - 1)
+#define GET_SIT_VBLOCKS(raw_sit)				\
+	(le16_to_cpu((raw_sit)->vblocks) & SIT_VBLOCKS_MASK)
+#define GET_SIT_TYPE(raw_sit)					\
+	((le16_to_cpu((raw_sit)->vblocks) & ~SIT_VBLOCKS_MASK)	\
+	 >> SIT_VBLOCKS_SHIFT)
+
+struct f2fs_sit_entry {
+	__le16 vblocks;				/* reference above */
+	__u8 valid_map[SIT_VBLOCK_MAP_SIZE];	/* bitmap for valid blocks */
+	__le64 mtime;				/* segment age for cleaning */
+} __packed;
+
+struct f2fs_sit_block {
+	struct f2fs_sit_entry entries[SIT_ENTRY_PER_BLOCK];
+} __packed;
+
+/*
+ * For segment summary
+ *
+ * One summary block contains exactly 512 summary entries, which represents
+ * exactly 2MB segment by default. Not allow to change the basic units.
+ *
+ * NOTE: For initializing fields, you must use set_summary
+ *
+ * - If data page, nid represents dnode's nid
+ * - If node page, nid represents the node page's nid.
+ *
+ * The ofs_in_node is used by only data page. It represents offset
+ * from node's page's beginning to get a data block address.
+ * ex) data_blkaddr = (block_t)(nodepage_start_address + ofs_in_node)
+ */
+#define ENTRIES_IN_SUM		512
+#define	SUMMARY_SIZE		(sizeof(struct f2fs_summary))
+#define	SUM_FOOTER_SIZE		(sizeof(struct summary_footer))
+#define SUM_ENTRY_SIZE		(SUMMARY_SIZE * ENTRIES_IN_SUM)
+
+/* a summary entry for a 4KB-sized block in a segment */
+struct f2fs_summary {
+	__le32 nid;		/* parent node id */
+	union {
+		__u8 reserved[3];
+		struct {
+			__u8 version;		/* node version number */
+			__le16 ofs_in_node;	/* block index in parent node */
+		} __packed;
+	};
+} __packed;
+
+/* summary block type, node or data, is stored to the summary_footer */
+#define SUM_TYPE_NODE		(1)
+#define SUM_TYPE_DATA		(0)
+
+struct summary_footer {
+	unsigned char entry_type;	/* SUM_TYPE_XXX */
+	__u32 check_sum;		/* summary checksum */
+} __packed;
+
+#define SUM_JOURNAL_SIZE	(PAGE_CACHE_SIZE - SUM_FOOTER_SIZE -\
+				SUM_ENTRY_SIZE)
+#define NAT_JOURNAL_ENTRIES	((SUM_JOURNAL_SIZE - 2) /\
+				sizeof(struct nat_journal_entry))
+#define NAT_JOURNAL_RESERVED	((SUM_JOURNAL_SIZE - 2) %\
+				sizeof(struct nat_journal_entry))
+#define SIT_JOURNAL_ENTRIES	((SUM_JOURNAL_SIZE - 2) /\
+				sizeof(struct sit_journal_entry))
+#define SIT_JOURNAL_RESERVED	((SUM_JOURNAL_SIZE - 2) %\
+				sizeof(struct sit_journal_entry))
+/*
+ * frequently updated NAT/SIT entries can be stored in the spare area in
+ * summary blocks
+ */
+enum {
+	NAT_JOURNAL = 0,
+	SIT_JOURNAL
+};
+
+struct nat_journal_entry {
+	__le32 nid;
+	struct f2fs_nat_entry ne;
+} __packed;
+
+struct nat_journal {
+	struct nat_journal_entry entries[NAT_JOURNAL_ENTRIES];
+	__u8 reserved[NAT_JOURNAL_RESERVED];
+} __packed;
+
+struct sit_journal_entry {
+	__le32 segno;
+	struct f2fs_sit_entry se;
+} __packed;
+
+struct sit_journal {
+	struct sit_journal_entry entries[SIT_JOURNAL_ENTRIES];
+	__u8 reserved[SIT_JOURNAL_RESERVED];
+} __packed;
+
+/* 4KB-sized summary block structure */
+struct f2fs_summary_block {
+	struct f2fs_summary entries[ENTRIES_IN_SUM];
+	union {
+		__le16 n_nats;
+		__le16 n_sits;
+	};
+	/* spare area is used by NAT or SIT journals */
+	union {
+		struct nat_journal nat_j;
+		struct sit_journal sit_j;
+	};
+	struct summary_footer footer;
+} __packed;
+
+/*
+ * For directory operations
+ */
+#define F2FS_DOT_HASH		0
+#define F2FS_DDOT_HASH		F2FS_DOT_HASH
+#define F2FS_MAX_HASH		(~((0x3ULL) << 62))
+#define F2FS_HASH_COL_BIT	((0x1ULL) << 63)
+
+typedef __le32	f2fs_hash_t;
+
+/* One directory entry slot covers 8bytes-long file name */
+#define F2FS_NAME_LEN		8
+
+/* the number of dentry in a block */
+#define NR_DENTRY_IN_BLOCK	214
+
+/* MAX level for dir lookup */
+#define MAX_DIR_HASH_DEPTH	63
+
+#define SIZE_OF_DIR_ENTRY	11	/* by byte */
+#define SIZE_OF_DENTRY_BITMAP	((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \
+					BITS_PER_BYTE)
+#define SIZE_OF_RESERVED	(PAGE_SIZE - ((SIZE_OF_DIR_ENTRY + \
+				F2FS_NAME_LEN) * \
+				NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP))
+
+/* One directory entry slot representing F2FS_NAME_LEN-sized file name */
+struct f2fs_dir_entry {
+	__le32 hash_code;	/* hash code of file name */
+	__le32 ino;		/* inode number */
+	__le16 name_len;	/* lengh of file name */
+	__u8 file_type;		/* file type */
+} __packed;
+
+/* 4KB-sized directory entry block */
+struct f2fs_dentry_block {
+	/* validity bitmap for directory entries in each block */
+	__u8 dentry_bitmap[SIZE_OF_DENTRY_BITMAP];
+	__u8 reserved[SIZE_OF_RESERVED];
+	struct f2fs_dir_entry dentry[NR_DENTRY_IN_BLOCK];
+	__u8 filename[NR_DENTRY_IN_BLOCK][F2FS_NAME_LEN];
+} __packed;
+
+/* file types used in inode_info->flags */
+enum {
+	F2FS_FT_UNKNOWN,
+	F2FS_FT_REG_FILE,
+	F2FS_FT_DIR,
+	F2FS_FT_CHRDEV,
+	F2FS_FT_BLKDEV,
+	F2FS_FT_FIFO,
+	F2FS_FT_SOCK,
+	F2FS_FT_SYMLINK,
+	F2FS_FT_MAX
+};
+
+#endif  /* _LINUX_F2FS_FS_H */
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
index 45052aa..fb7daca 100644
--- a/include/linux/fdtable.h
+++ b/include/linux/fdtable.h
@@ -95,7 +95,6 @@ struct task_struct;
 struct files_struct *get_files_struct(struct task_struct *);
 void put_files_struct(struct files_struct *fs);
 void reset_files_struct(struct files_struct *);
-void daemonize_descriptors(void);
 int unshare_files(struct files_struct **);
 struct files_struct *dup_fd(struct files_struct *, int *);
 void do_close_on_exec(struct files_struct *);
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 24d251f..c45eabc 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -45,6 +45,7 @@ extern void sk_unattached_filter_destroy(struct sk_filter *fp);
 extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
 extern int sk_detach_filter(struct sock *sk);
 extern int sk_chk_filter(struct sock_filter *filter, unsigned int flen);
+extern int sk_get_filter(struct sock *sk, struct sock_filter __user *filter, unsigned len);
 
 #ifdef CONFIG_BPF_JIT
 extern void bpf_jit_compile(struct sk_filter *fp);
@@ -123,6 +124,8 @@ enum {
 	BPF_S_ANC_CPU,
 	BPF_S_ANC_ALU_XOR_X,
 	BPF_S_ANC_SECCOMP_LD_W,
+	BPF_S_ANC_VLAN_TAG,
+	BPF_S_ANC_VLAN_TAG_PRESENT,
 };
 
 #endif /* __LINUX_FILTER_H__ */
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index d09af4b..e4238ce 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -75,35 +75,68 @@ static inline bool cgroup_freezing(struct task_struct *task)
  */
 
 
-/* Tell the freezer not to count the current task as freezable. */
+/**
+ * freezer_do_not_count - tell freezer to ignore %current
+ *
+ * Tell freezers to ignore the current task when determining whether the
+ * target frozen state is reached.  IOW, the current task will be
+ * considered frozen enough by freezers.
+ *
+ * The caller shouldn't do anything which isn't allowed for a frozen task
+ * until freezer_cont() is called.  Usually, freezer[_do_not]_count() pair
+ * wrap a scheduling operation and nothing much else.
+ */
 static inline void freezer_do_not_count(void)
 {
 	current->flags |= PF_FREEZER_SKIP;
 }
 
-/*
- * Tell the freezer to count the current task as freezable again and try to
- * freeze it.
+/**
+ * freezer_count - tell freezer to stop ignoring %current
+ *
+ * Undo freezer_do_not_count().  It tells freezers that %current should be
+ * considered again and tries to freeze if freezing condition is already in
+ * effect.
  */
 static inline void freezer_count(void)
 {
 	current->flags &= ~PF_FREEZER_SKIP;
+	/*
+	 * If freezing is in progress, the following paired with smp_mb()
+	 * in freezer_should_skip() ensures that either we see %true
+	 * freezing() or freezer_should_skip() sees !PF_FREEZER_SKIP.
+	 */
+	smp_mb();
 	try_to_freeze();
 }
 
-/*
- * Check if the task should be counted as freezable by the freezer
+/**
+ * freezer_should_skip - whether to skip a task when determining frozen
+ *			 state is reached
+ * @p: task in quesion
+ *
+ * This function is used by freezers after establishing %true freezing() to
+ * test whether a task should be skipped when determining the target frozen
+ * state is reached.  IOW, if this function returns %true, @p is considered
+ * frozen enough.
  */
-static inline int freezer_should_skip(struct task_struct *p)
+static inline bool freezer_should_skip(struct task_struct *p)
 {
-	return !!(p->flags & PF_FREEZER_SKIP);
+	/*
+	 * The following smp_mb() paired with the one in freezer_count()
+	 * ensures that either freezer_count() sees %true freezing() or we
+	 * see cleared %PF_FREEZER_SKIP and return %false.  This makes it
+	 * impossible for a task to slip frozen state testing after
+	 * clearing %PF_FREEZER_SKIP.
+	 */
+	smp_mb();
+	return p->flags & PF_FREEZER_SKIP;
 }
 
 /*
- * These macros are intended to be used whenever you want allow a task that's
- * sleeping in TASK_UNINTERRUPTIBLE or TASK_KILLABLE state to be frozen. Note
- * that neither return any clear indication of whether a freeze event happened
- * while in this function.
+ * These macros are intended to be used whenever you want allow a sleeping
+ * task to be frozen. Note that neither return any clear indication of
+ * whether a freeze event happened while in this function.
  */
 
 /* Like schedule(), but should not block the freezer. */
@@ -177,6 +210,7 @@ static inline int freeze_kernel_threads(void) { return -ENOSYS; }
 static inline void thaw_processes(void) {}
 static inline void thaw_kernel_threads(void) {}
 
+static inline bool try_to_freeze_nowarn(void) { return false; }
 static inline bool try_to_freeze(void) { return false; }
 
 static inline void freezer_do_not_count(void) {}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b33cfc9..04d5b12 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -44,6 +44,7 @@ struct vm_area_struct;
 struct vfsmount;
 struct cred;
 struct swap_info_struct;
+struct seq_file;
 
 extern void __init inode_init(void);
 extern void __init inode_init_early(void);
@@ -300,7 +301,7 @@ size_t iov_iter_copy_from_user(struct page *page,
 		struct iov_iter *i, unsigned long offset, size_t bytes);
 void iov_iter_advance(struct iov_iter *i, size_t bytes);
 int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes);
-size_t iov_iter_single_seg_count(struct iov_iter *i);
+size_t iov_iter_single_seg_count(const struct iov_iter *i);
 
 static inline void iov_iter_init(struct iov_iter *i,
 			const struct iovec *iov, unsigned long nr_segs,
@@ -418,7 +419,7 @@ struct address_space {
 	struct backing_dev_info *backing_dev_info; /* device readahead, etc */
 	spinlock_t		private_lock;	/* for use by the address_space */
 	struct list_head	private_list;	/* ditto */
-	struct address_space	*assoc_mapping;	/* ditto */
+	void			*private_data;	/* ditto */
 } __attribute__((aligned(sizeof(long))));
 	/*
 	 * On most architectures that alignment is already the case; but
@@ -1545,6 +1546,7 @@ struct file_operations {
 	int (*setlease)(struct file *, long, struct file_lock **);
 	long (*fallocate)(struct file *file, int mode, loff_t offset,
 			  loff_t len);
+	int (*show_fdinfo)(struct seq_file *m, struct file *f);
 };
 
 struct inode_operations {
@@ -1580,8 +1582,6 @@ struct inode_operations {
 			   umode_t create_mode, int *opened);
 } ____cacheline_aligned;
 
-struct seq_file;
-
 ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
 			      unsigned long nr_segs, unsigned long fast_segs,
 			      struct iovec *fast_pointer,
@@ -1812,6 +1812,8 @@ struct file_system_type {
 #define FS_REQUIRES_DEV		1 
 #define FS_BINARY_MOUNTDATA	2
 #define FS_HAS_SUBTYPE		4
+#define FS_USERNS_MOUNT		8	/* Can be mounted by userns root */
+#define FS_USERNS_DEV_MOUNT	16 /* A userns mount does not imply MNT_NODEV */
 #define FS_REVAL_DOT		16384	/* Check the paths ".", ".." for staleness */
 #define FS_RENAME_DOES_D_MOVE	32768	/* FS will handle d_move() during rename() internally. */
 	struct dentry *(*mount) (struct file_system_type *, int,
diff --git a/include/linux/fs_struct.h b/include/linux/fs_struct.h
index 003dc0f..d0ae3a8 100644
--- a/include/linux/fs_struct.h
+++ b/include/linux/fs_struct.h
@@ -21,7 +21,6 @@ extern void set_fs_root(struct fs_struct *, struct path *);
 extern void set_fs_pwd(struct fs_struct *, struct path *);
 extern struct fs_struct *copy_fs_struct(struct fs_struct *);
 extern void free_fs_struct(struct fs_struct *);
-extern void daemonize_fs_struct(void);
 extern int unshare_fs_struct(void);
 
 static inline void get_fs_root(struct fs_struct *fs, struct path *root)
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 63d966d..d5b0910 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -88,9 +88,10 @@ struct fsnotify_event_private_data;
  *		if the group is interested in this event.
  * handle_event - main call for a group to handle an fs event
  * free_group_priv - called when a group refcnt hits 0 to clean up the private union
- * freeing-mark - this means that a mark has been flagged to die when everything
- *		finishes using it.  The function is supplied with what must be a
- *		valid group and inode to use to clean up.
+ * freeing_mark - called when a mark is being destroyed for some reason.  The group
+ * 		MUST be holding a reference on each mark and that reference must be
+ * 		dropped in this function.  inotify uses this function to send
+ * 		userspace messages that marks have been removed.
  */
 struct fsnotify_ops {
 	bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode,
@@ -141,12 +142,14 @@ struct fsnotify_group {
 	unsigned int priority;
 
 	/* stores all fastpath marks assoc with this group so they can be cleaned on unregister */
-	spinlock_t mark_lock;		/* protect marks_list */
+	struct mutex mark_mutex;	/* protect marks_list */
 	atomic_t num_marks;		/* 1 for each mark and 1 for not being
 					 * past the point of no return when freeing
 					 * a group */
 	struct list_head marks_list;	/* all inode marks for this group */
 
+	struct fasync_struct    *fsn_fa;    /* async notification */
+
 	/* groups can define private fields here or use the void *private */
 	union {
 		void *private;
@@ -155,7 +158,6 @@ struct fsnotify_group {
 			spinlock_t	idr_lock;
 			struct idr      idr;
 			u32             last_wd;
-			struct fasync_struct    *fa;    /* async notification */
 			struct user_struct      *user;
 		} inotify_data;
 #endif
@@ -287,7 +289,6 @@ struct fsnotify_mark {
 		struct fsnotify_inode_mark i;
 		struct fsnotify_vfsmount_mark m;
 	};
-	struct list_head free_g_list;	/* tmp list used when freeing this mark */
 	__u32 ignored_mask;		/* events types to ignore */
 #define FSNOTIFY_MARK_FLAG_INODE		0x01
 #define FSNOTIFY_MARK_FLAG_VFSMOUNT		0x02
@@ -360,11 +361,16 @@ static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode
 
 /* called from fsnotify listeners, such as fanotify or dnotify */
 
-/* get a reference to an existing or create a new group */
+/* create a new group */
 extern struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops);
+/* get reference to a group */
+extern void fsnotify_get_group(struct fsnotify_group *group);
 /* drop reference on a group from fsnotify_alloc_group */
 extern void fsnotify_put_group(struct fsnotify_group *group);
-
+/* destroy group */
+extern void fsnotify_destroy_group(struct fsnotify_group *group);
+/* fasync handler function */
+extern int fsnotify_fasync(int fd, struct file *file, int on);
 /* take a reference to an event */
 extern void fsnotify_get_event(struct fsnotify_event *event);
 extern void fsnotify_put_event(struct fsnotify_event *event);
@@ -405,8 +411,13 @@ extern void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask
 /* attach the mark to both the group and the inode */
 extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group,
 			     struct inode *inode, struct vfsmount *mnt, int allow_dups);
-/* given a mark, flag it to be freed when all references are dropped */
-extern void fsnotify_destroy_mark(struct fsnotify_mark *mark);
+extern int fsnotify_add_mark_locked(struct fsnotify_mark *mark, struct fsnotify_group *group,
+				    struct inode *inode, struct vfsmount *mnt, int allow_dups);
+/* given a group and a mark, flag mark to be freed when all references are dropped */
+extern void fsnotify_destroy_mark(struct fsnotify_mark *mark,
+				  struct fsnotify_group *group);
+extern void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark,
+					 struct fsnotify_group *group);
 /* run all the marks in a group, and clear all of the vfsmount marks */
 extern void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group);
 /* run all the marks in a group, and clear all of the inode marks */
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 642928c..a3d4895 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -86,6 +86,12 @@ struct trace_iterator {
 	cpumask_var_t		started;
 };
 
+enum trace_iter_flags {
+	TRACE_FILE_LAT_FMT	= 1,
+	TRACE_FILE_ANNOTATE	= 2,
+	TRACE_FILE_TIME_IN_NS	= 4,
+};
+
 
 struct trace_event;
 
@@ -127,13 +133,13 @@ trace_current_buffer_lock_reserve(struct ring_buffer **current_buffer,
 void trace_current_buffer_unlock_commit(struct ring_buffer *buffer,
 					struct ring_buffer_event *event,
 					unsigned long flags, int pc);
-void trace_nowake_buffer_unlock_commit(struct ring_buffer *buffer,
-				       struct ring_buffer_event *event,
-					unsigned long flags, int pc);
-void trace_nowake_buffer_unlock_commit_regs(struct ring_buffer *buffer,
-					    struct ring_buffer_event *event,
-					    unsigned long flags, int pc,
-					    struct pt_regs *regs);
+void trace_buffer_unlock_commit(struct ring_buffer *buffer,
+				struct ring_buffer_event *event,
+				unsigned long flags, int pc);
+void trace_buffer_unlock_commit_regs(struct ring_buffer *buffer,
+				     struct ring_buffer_event *event,
+				     unsigned long flags, int pc,
+				     struct pt_regs *regs);
 void trace_current_buffer_discard_commit(struct ring_buffer *buffer,
 					 struct ring_buffer_event *event);
 
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 4f440b3..79b8bba 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -88,10 +88,14 @@ struct disk_stats {
 };
 
 #define PARTITION_META_INFO_VOLNAMELTH	64
-#define PARTITION_META_INFO_UUIDLTH	16
+/*
+ * Enough for the string representation of any kind of UUID plus NULL.
+ * EFI UUID is 36 characters. MSDOS UUID is 11 characters.
+ */
+#define PARTITION_META_INFO_UUIDLTH	37
 
 struct partition_meta_info {
-	u8 uuid[PARTITION_META_INFO_UUIDLTH];	/* always big endian */
+	char uuid[PARTITION_META_INFO_UUIDLTH];
 	u8 volname[PARTITION_META_INFO_VOLNAMELTH];
 };
 
diff --git a/include/linux/genl_magic_func.h b/include/linux/genl_magic_func.h
new file mode 100644
index 0000000..023bc34
--- /dev/null
+++ b/include/linux/genl_magic_func.h
@@ -0,0 +1,422 @@
+#ifndef GENL_MAGIC_FUNC_H
+#define GENL_MAGIC_FUNC_H
+
+#include <linux/genl_magic_struct.h>
+
+/*
+ * Magic: declare tla policy						{{{1
+ * Magic: declare nested policies
+ *									{{{2
+ */
+#undef GENL_mc_group
+#define GENL_mc_group(group)
+
+#undef GENL_notification
+#define GENL_notification(op_name, op_num, mcast_group, tla_list)
+
+#undef GENL_op
+#define GENL_op(op_name, op_num, handler, tla_list)
+
+#undef GENL_struct
+#define GENL_struct(tag_name, tag_number, s_name, s_fields)		\
+	[tag_name] = { .type = NLA_NESTED },
+
+static struct nla_policy CONCAT_(GENL_MAGIC_FAMILY, _tla_nl_policy)[] = {
+#include GENL_MAGIC_INCLUDE_FILE
+};
+
+#undef GENL_struct
+#define GENL_struct(tag_name, tag_number, s_name, s_fields)		\
+static struct nla_policy s_name ## _nl_policy[] __read_mostly =		\
+{ s_fields };
+
+#undef __field
+#define __field(attr_nr, attr_flag, name, nla_type, _type, __get,	\
+		 __put, __is_signed)					\
+	[attr_nr] = { .type = nla_type },
+
+#undef __array
+#define __array(attr_nr, attr_flag, name, nla_type, _type, maxlen,	\
+		__get, __put, __is_signed)				\
+	[attr_nr] = { .type = nla_type,					\
+		      .len = maxlen - (nla_type == NLA_NUL_STRING) },
+
+#include GENL_MAGIC_INCLUDE_FILE
+
+#ifndef __KERNEL__
+#ifndef pr_info
+#define pr_info(args...)	fprintf(stderr, args);
+#endif
+#endif
+
+#ifdef GENL_MAGIC_DEBUG
+static void dprint_field(const char *dir, int nla_type,
+		const char *name, void *valp)
+{
+	__u64 val = valp ? *(__u32 *)valp : 1;
+	switch (nla_type) {
+	case NLA_U8:  val = (__u8)val;
+	case NLA_U16: val = (__u16)val;
+	case NLA_U32: val = (__u32)val;
+		pr_info("%s attr %s: %d 0x%08x\n", dir,
+			name, (int)val, (unsigned)val);
+		break;
+	case NLA_U64:
+		val = *(__u64*)valp;
+		pr_info("%s attr %s: %lld 0x%08llx\n", dir,
+			name, (long long)val, (unsigned long long)val);
+		break;
+	case NLA_FLAG:
+		if (val)
+			pr_info("%s attr %s: set\n", dir, name);
+		break;
+	}
+}
+
+static void dprint_array(const char *dir, int nla_type,
+		const char *name, const char *val, unsigned len)
+{
+	switch (nla_type) {
+	case NLA_NUL_STRING:
+		if (len && val[len-1] == '\0')
+			len--;
+		pr_info("%s attr %s: [len:%u] '%s'\n", dir, name, len, val);
+		break;
+	default:
+		/* we can always show 4 byte,
+		 * thats what nlattr are aligned to. */
+		pr_info("%s attr %s: [len:%u] %02x%02x%02x%02x ...\n",
+			dir, name, len, val[0], val[1], val[2], val[3]);
+	}
+}
+
+#define DPRINT_TLA(a, op, b) pr_info("%s %s %s\n", a, op, b);
+
+/* Name is a member field name of the struct s.
+ * If s is NULL (only parsing, no copy requested in *_from_attrs()),
+ * nla is supposed to point to the attribute containing the information
+ * corresponding to that struct member. */
+#define DPRINT_FIELD(dir, nla_type, name, s, nla)			\
+	do {								\
+		if (s)							\
+			dprint_field(dir, nla_type, #name, &s->name);	\
+		else if (nla)						\
+			dprint_field(dir, nla_type, #name,		\
+				(nla_type == NLA_FLAG) ? NULL		\
+						: nla_data(nla));	\
+	} while (0)
+
+#define	DPRINT_ARRAY(dir, nla_type, name, s, nla)			\
+	do {								\
+		if (s)							\
+			dprint_array(dir, nla_type, #name,		\
+					s->name, s->name ## _len);	\
+		else if (nla)						\
+			dprint_array(dir, nla_type, #name,		\
+					nla_data(nla), nla_len(nla));	\
+	} while (0)
+#else
+#define DPRINT_TLA(a, op, b) do {} while (0)
+#define DPRINT_FIELD(dir, nla_type, name, s, nla) do {} while (0)
+#define	DPRINT_ARRAY(dir, nla_type, name, s, nla) do {} while (0)
+#endif
+
+/*
+ * Magic: provide conversion functions					{{{1
+ * populate struct from attribute table:
+ *									{{{2
+ */
+
+/* processing of generic netlink messages is serialized.
+ * use one static buffer for parsing of nested attributes */
+static struct nlattr *nested_attr_tb[128];
+
+#ifndef BUILD_BUG_ON
+/* Force a compilation error if condition is true */
+#define BUILD_BUG_ON(condition) ((void)BUILD_BUG_ON_ZERO(condition))
+/* Force a compilation error if condition is true, but also produce a
+   result (of value 0 and type size_t), so the expression can be used
+   e.g. in a structure initializer (or where-ever else comma expressions
+   aren't permitted). */
+#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
+#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
+#endif
+
+#undef GENL_struct
+#define GENL_struct(tag_name, tag_number, s_name, s_fields)		\
+/* *_from_attrs functions are static, but potentially unused */		\
+static int __ ## s_name ## _from_attrs(struct s_name *s,		\
+		struct genl_info *info, bool exclude_invariants)	\
+{									\
+	const int maxtype = ARRAY_SIZE(s_name ## _nl_policy)-1;		\
+	struct nlattr *tla = info->attrs[tag_number];			\
+	struct nlattr **ntb = nested_attr_tb;				\
+	struct nlattr *nla;						\
+	int err;							\
+	BUILD_BUG_ON(ARRAY_SIZE(s_name ## _nl_policy) > ARRAY_SIZE(nested_attr_tb));	\
+	if (!tla)							\
+		return -ENOMSG;						\
+	DPRINT_TLA(#s_name, "<=-", #tag_name);				\
+	err = drbd_nla_parse_nested(ntb, maxtype, tla, s_name ## _nl_policy);	\
+	if (err)							\
+		return err;						\
+									\
+	s_fields							\
+	return 0;							\
+}					__attribute__((unused))		\
+static int s_name ## _from_attrs(struct s_name *s,			\
+						struct genl_info *info)	\
+{									\
+	return __ ## s_name ## _from_attrs(s, info, false);		\
+}					__attribute__((unused))		\
+static int s_name ## _from_attrs_for_change(struct s_name *s,		\
+						struct genl_info *info)	\
+{									\
+	return __ ## s_name ## _from_attrs(s, info, true);		\
+}					__attribute__((unused))		\
+
+#define __assign(attr_nr, attr_flag, name, nla_type, type, assignment...)	\
+		nla = ntb[attr_nr];						\
+		if (nla) {						\
+			if (exclude_invariants && ((attr_flag) & DRBD_F_INVARIANT)) {		\
+				pr_info("<< must not change invariant attr: %s\n", #name);	\
+				return -EEXIST;				\
+			}						\
+			assignment;					\
+		} else if (exclude_invariants && ((attr_flag) & DRBD_F_INVARIANT)) {		\
+			/* attribute missing from payload, */		\
+			/* which was expected */			\
+		} else if ((attr_flag) & DRBD_F_REQUIRED) {		\
+			pr_info("<< missing attr: %s\n", #name);	\
+			return -ENOMSG;					\
+		}
+
+#undef __field
+#define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put,	\
+		__is_signed)						\
+	__assign(attr_nr, attr_flag, name, nla_type, type,		\
+			if (s)						\
+				s->name = __get(nla);			\
+			DPRINT_FIELD("<<", nla_type, name, s, nla))
+
+/* validate_nla() already checked nla_len <= maxlen appropriately. */
+#undef __array
+#define __array(attr_nr, attr_flag, name, nla_type, type, maxlen,	\
+		__get, __put, __is_signed)				\
+	__assign(attr_nr, attr_flag, name, nla_type, type,		\
+			if (s)						\
+				s->name ## _len =			\
+					__get(s->name, nla, maxlen);	\
+			DPRINT_ARRAY("<<", nla_type, name, s, nla))
+
+#include GENL_MAGIC_INCLUDE_FILE
+
+#undef GENL_struct
+#define GENL_struct(tag_name, tag_number, s_name, s_fields)
+
+/*
+ * Magic: define op number to op name mapping				{{{1
+ *									{{{2
+ */
+const char *CONCAT_(GENL_MAGIC_FAMILY, _genl_cmd_to_str)(__u8 cmd)
+{
+	switch (cmd) {
+#undef GENL_op
+#define GENL_op(op_name, op_num, handler, tla_list)		\
+	case op_num: return #op_name;
+#include GENL_MAGIC_INCLUDE_FILE
+	default:
+		     return "unknown";
+	}
+}
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+/*
+ * Magic: define genl_ops						{{{1
+ *									{{{2
+ */
+
+#undef GENL_op
+#define GENL_op(op_name, op_num, handler, tla_list)		\
+{								\
+	handler							\
+	.cmd = op_name,						\
+	.policy	= CONCAT_(GENL_MAGIC_FAMILY, _tla_nl_policy),	\
+},
+
+#define ZZZ_genl_ops		CONCAT_(GENL_MAGIC_FAMILY, _genl_ops)
+static struct genl_ops ZZZ_genl_ops[] __read_mostly = {
+#include GENL_MAGIC_INCLUDE_FILE
+};
+
+#undef GENL_op
+#define GENL_op(op_name, op_num, handler, tla_list)
+
+/*
+ * Define the genl_family, multicast groups,				{{{1
+ * and provide register/unregister functions.
+ *									{{{2
+ */
+#define ZZZ_genl_family		CONCAT_(GENL_MAGIC_FAMILY, _genl_family)
+static struct genl_family ZZZ_genl_family __read_mostly = {
+	.id = GENL_ID_GENERATE,
+	.name = __stringify(GENL_MAGIC_FAMILY),
+	.version = GENL_MAGIC_VERSION,
+#ifdef GENL_MAGIC_FAMILY_HDRSZ
+	.hdrsize = NLA_ALIGN(GENL_MAGIC_FAMILY_HDRSZ),
+#endif
+	.maxattr = ARRAY_SIZE(drbd_tla_nl_policy)-1,
+};
+
+/*
+ * Magic: define multicast groups
+ * Magic: define multicast group registration helper
+ */
+#undef GENL_mc_group
+#define GENL_mc_group(group)						\
+static struct genl_multicast_group					\
+CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group) __read_mostly = {		\
+	.name = #group,							\
+};									\
+static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)(	\
+	struct sk_buff *skb, gfp_t flags)				\
+{									\
+	unsigned int group_id =						\
+		CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id;	\
+	if (!group_id)							\
+		return -EINVAL;						\
+	return genlmsg_multicast(skb, 0, group_id, flags);		\
+}
+
+#include GENL_MAGIC_INCLUDE_FILE
+
+int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void)
+{
+	int err = genl_register_family_with_ops(&ZZZ_genl_family,
+		ZZZ_genl_ops, ARRAY_SIZE(ZZZ_genl_ops));
+	if (err)
+		return err;
+#undef GENL_mc_group
+#define GENL_mc_group(group)						\
+	err = genl_register_mc_group(&ZZZ_genl_family,			\
+		&CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group));		\
+	if (err)							\
+		goto fail;						\
+	else								\
+		pr_info("%s: mcg %s: %u\n", #group,			\
+			__stringify(GENL_MAGIC_FAMILY),			\
+			CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id);
+
+#include GENL_MAGIC_INCLUDE_FILE
+
+#undef GENL_mc_group
+#define GENL_mc_group(group)
+	return 0;
+fail:
+	genl_unregister_family(&ZZZ_genl_family);
+	return err;
+}
+
+void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void)
+{
+	genl_unregister_family(&ZZZ_genl_family);
+}
+
+/*
+ * Magic: provide conversion functions					{{{1
+ * populate skb from struct.
+ *									{{{2
+ */
+
+#undef GENL_op
+#define GENL_op(op_name, op_num, handler, tla_list)
+
+#undef GENL_struct
+#define GENL_struct(tag_name, tag_number, s_name, s_fields)		\
+static int s_name ## _to_skb(struct sk_buff *skb, struct s_name *s,	\
+		const bool exclude_sensitive)				\
+{									\
+	struct nlattr *tla = nla_nest_start(skb, tag_number);		\
+	if (!tla)							\
+		goto nla_put_failure;					\
+	DPRINT_TLA(#s_name, "-=>", #tag_name);				\
+	s_fields							\
+	nla_nest_end(skb, tla);						\
+	return 0;							\
+									\
+nla_put_failure:							\
+	if (tla)							\
+		nla_nest_cancel(skb, tla);				\
+        return -EMSGSIZE;						\
+}									\
+static inline int s_name ## _to_priv_skb(struct sk_buff *skb,		\
+		struct s_name *s)					\
+{									\
+	return s_name ## _to_skb(skb, s, 0);				\
+}									\
+static inline int s_name ## _to_unpriv_skb(struct sk_buff *skb,		\
+		struct s_name *s)					\
+{									\
+	return s_name ## _to_skb(skb, s, 1);				\
+}
+
+
+#undef __field
+#define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put,	\
+		__is_signed)						\
+	if (!exclude_sensitive || !((attr_flag) & DRBD_F_SENSITIVE)) {	\
+		DPRINT_FIELD(">>", nla_type, name, s, NULL);		\
+		if (__put(skb, attr_nr, s->name))			\
+			goto nla_put_failure;				\
+	}
+
+#undef __array
+#define __array(attr_nr, attr_flag, name, nla_type, type, maxlen,	\
+		__get, __put, __is_signed)				\
+	if (!exclude_sensitive || !((attr_flag) & DRBD_F_SENSITIVE)) {	\
+		DPRINT_ARRAY(">>",nla_type, name, s, NULL);		\
+		if (__put(skb, attr_nr, min_t(int, maxlen,		\
+			s->name ## _len + (nla_type == NLA_NUL_STRING)),\
+						s->name))		\
+			goto nla_put_failure;				\
+	}
+
+#include GENL_MAGIC_INCLUDE_FILE
+
+
+/* Functions for initializing structs to default values.  */
+
+#undef __field
+#define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put,	\
+		__is_signed)
+#undef __array
+#define __array(attr_nr, attr_flag, name, nla_type, type, maxlen,	\
+		__get, __put, __is_signed)
+#undef __u32_field_def
+#define __u32_field_def(attr_nr, attr_flag, name, default)		\
+	x->name = default;
+#undef __s32_field_def
+#define __s32_field_def(attr_nr, attr_flag, name, default)		\
+	x->name = default;
+#undef __flg_field_def
+#define __flg_field_def(attr_nr, attr_flag, name, default)		\
+	x->name = default;
+#undef __str_field_def
+#define __str_field_def(attr_nr, attr_flag, name, maxlen)		\
+	memset(x->name, 0, sizeof(x->name));				\
+	x->name ## _len = 0;
+#undef GENL_struct
+#define GENL_struct(tag_name, tag_number, s_name, s_fields)		\
+static void set_ ## s_name ## _defaults(struct s_name *x) __attribute__((unused)); \
+static void set_ ## s_name ## _defaults(struct s_name *x) {	\
+s_fields								\
+}
+
+#include GENL_MAGIC_INCLUDE_FILE
+
+#endif /* __KERNEL__ */
+
+/* }}}1 */
+#endif /* GENL_MAGIC_FUNC_H */
+/* vim: set foldmethod=marker foldlevel=1 nofoldenable : */
diff --git a/include/linux/genl_magic_struct.h b/include/linux/genl_magic_struct.h
new file mode 100644
index 0000000..eecd19b
--- /dev/null
+++ b/include/linux/genl_magic_struct.h
@@ -0,0 +1,277 @@
+#ifndef GENL_MAGIC_STRUCT_H
+#define GENL_MAGIC_STRUCT_H
+
+#ifndef GENL_MAGIC_FAMILY
+# error "you need to define GENL_MAGIC_FAMILY before inclusion"
+#endif
+
+#ifndef GENL_MAGIC_VERSION
+# error "you need to define GENL_MAGIC_VERSION before inclusion"
+#endif
+
+#ifndef GENL_MAGIC_INCLUDE_FILE
+# error "you need to define GENL_MAGIC_INCLUDE_FILE before inclusion"
+#endif
+
+#include <linux/genetlink.h>
+#include <linux/types.h>
+
+#define CONCAT__(a,b)	a ## b
+#define CONCAT_(a,b)	CONCAT__(a,b)
+
+extern int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void);
+extern void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void);
+
+/*
+ * Extension of genl attribute validation policies			{{{2
+ */
+
+/*
+ * @DRBD_GENLA_F_MANDATORY: By default, netlink ignores attributes it does not
+ * know about.  This flag can be set in nlattr->nla_type to indicate that this
+ * attribute must not be ignored.
+ *
+ * We check and remove this flag in drbd_nla_check_mandatory() before
+ * validating the attribute types and lengths via nla_parse_nested().
+ */
+#define DRBD_GENLA_F_MANDATORY (1 << 14)
+
+/*
+ * Flags specific to drbd and not visible at the netlink layer, used in
+ * <struct>_from_attrs and <struct>_to_skb:
+ *
+ * @DRBD_F_REQUIRED: Attribute is required; a request without this attribute is
+ * invalid.
+ *
+ * @DRBD_F_SENSITIVE: Attribute includes sensitive information and must not be
+ * included in unpriviledged get requests or broadcasts.
+ *
+ * @DRBD_F_INVARIANT: Attribute is set when an object is initially created, but
+ * cannot subsequently be changed.
+ */
+#define DRBD_F_REQUIRED (1 << 0)
+#define DRBD_F_SENSITIVE (1 << 1)
+#define DRBD_F_INVARIANT (1 << 2)
+
+#define __nla_type(x)	((__u16)((x) & NLA_TYPE_MASK & ~DRBD_GENLA_F_MANDATORY))
+
+/*									}}}1
+ * MAGIC
+ * multi-include macro expansion magic starts here
+ */
+
+/* MAGIC helpers							{{{2 */
+
+/* possible field types */
+#define __flg_field(attr_nr, attr_flag, name) \
+	__field(attr_nr, attr_flag, name, NLA_U8, char, \
+			nla_get_u8, nla_put_u8, false)
+#define __u8_field(attr_nr, attr_flag, name)	\
+	__field(attr_nr, attr_flag, name, NLA_U8, unsigned char, \
+			nla_get_u8, nla_put_u8, false)
+#define __u16_field(attr_nr, attr_flag, name)	\
+	__field(attr_nr, attr_flag, name, NLA_U16, __u16, \
+			nla_get_u16, nla_put_u16, false)
+#define __u32_field(attr_nr, attr_flag, name)	\
+	__field(attr_nr, attr_flag, name, NLA_U32, __u32, \
+			nla_get_u32, nla_put_u32, false)
+#define __s32_field(attr_nr, attr_flag, name)	\
+	__field(attr_nr, attr_flag, name, NLA_U32, __s32, \
+			nla_get_u32, nla_put_u32, true)
+#define __u64_field(attr_nr, attr_flag, name)	\
+	__field(attr_nr, attr_flag, name, NLA_U64, __u64, \
+			nla_get_u64, nla_put_u64, false)
+#define __str_field(attr_nr, attr_flag, name, maxlen) \
+	__array(attr_nr, attr_flag, name, NLA_NUL_STRING, char, maxlen, \
+			nla_strlcpy, nla_put, false)
+#define __bin_field(attr_nr, attr_flag, name, maxlen) \
+	__array(attr_nr, attr_flag, name, NLA_BINARY, char, maxlen, \
+			nla_memcpy, nla_put, false)
+
+/* fields with default values */
+#define __flg_field_def(attr_nr, attr_flag, name, default) \
+	__flg_field(attr_nr, attr_flag, name)
+#define __u32_field_def(attr_nr, attr_flag, name, default) \
+	__u32_field(attr_nr, attr_flag, name)
+#define __s32_field_def(attr_nr, attr_flag, name, default) \
+	__s32_field(attr_nr, attr_flag, name)
+#define __str_field_def(attr_nr, attr_flag, name, maxlen) \
+	__str_field(attr_nr, attr_flag, name, maxlen)
+
+#define GENL_op_init(args...)	args
+#define GENL_doit(handler)		\
+	.doit = handler,		\
+	.flags = GENL_ADMIN_PERM,
+#define GENL_dumpit(handler)		\
+	.dumpit = handler,		\
+	.flags = GENL_ADMIN_PERM,
+
+/*									}}}1
+ * Magic: define the enum symbols for genl_ops
+ * Magic: define the enum symbols for top level attributes
+ * Magic: define the enum symbols for nested attributes
+ *									{{{2
+ */
+
+#undef GENL_struct
+#define GENL_struct(tag_name, tag_number, s_name, s_fields)
+
+#undef GENL_mc_group
+#define GENL_mc_group(group)
+
+#undef GENL_notification
+#define GENL_notification(op_name, op_num, mcast_group, tla_list)	\
+	op_name = op_num,
+
+#undef GENL_op
+#define GENL_op(op_name, op_num, handler, tla_list)			\
+	op_name = op_num,
+
+enum {
+#include GENL_MAGIC_INCLUDE_FILE
+};
+
+#undef GENL_notification
+#define GENL_notification(op_name, op_num, mcast_group, tla_list)
+
+#undef GENL_op
+#define GENL_op(op_name, op_num, handler, attr_list)
+
+#undef GENL_struct
+#define GENL_struct(tag_name, tag_number, s_name, s_fields) \
+		tag_name = tag_number,
+
+enum {
+#include GENL_MAGIC_INCLUDE_FILE
+};
+
+#undef GENL_struct
+#define GENL_struct(tag_name, tag_number, s_name, s_fields)	\
+enum {								\
+	s_fields						\
+};
+
+#undef __field
+#define __field(attr_nr, attr_flag, name, nla_type, type,	\
+		__get, __put, __is_signed)			\
+	T_ ## name = (__u16)(attr_nr | ((attr_flag) & DRBD_GENLA_F_MANDATORY)),
+
+#undef __array
+#define __array(attr_nr, attr_flag, name, nla_type, type,	\
+		maxlen, __get, __put, __is_signed)		\
+	T_ ## name = (__u16)(attr_nr | ((attr_flag) & DRBD_GENLA_F_MANDATORY)),
+
+#include GENL_MAGIC_INCLUDE_FILE
+
+/*									}}}1
+ * Magic: compile time assert unique numbers for operations
+ * Magic: -"- unique numbers for top level attributes
+ * Magic: -"- unique numbers for nested attributes
+ *									{{{2
+ */
+
+#undef GENL_struct
+#define GENL_struct(tag_name, tag_number, s_name, s_fields)
+
+#undef GENL_op
+#define GENL_op(op_name, op_num, handler, attr_list)	\
+	case op_name:
+
+#undef GENL_notification
+#define GENL_notification(op_name, op_num, mcast_group, tla_list)	\
+	case op_name:
+
+static inline void ct_assert_unique_operations(void)
+{
+	switch (0) {
+#include GENL_MAGIC_INCLUDE_FILE
+		;
+	}
+}
+
+#undef GENL_op
+#define GENL_op(op_name, op_num, handler, attr_list)
+
+#undef GENL_notification
+#define GENL_notification(op_name, op_num, mcast_group, tla_list)
+
+#undef GENL_struct
+#define GENL_struct(tag_name, tag_number, s_name, s_fields)		\
+		case tag_number:
+
+static inline void ct_assert_unique_top_level_attributes(void)
+{
+	switch (0) {
+#include GENL_MAGIC_INCLUDE_FILE
+		;
+	}
+}
+
+#undef GENL_struct
+#define GENL_struct(tag_name, tag_number, s_name, s_fields)		\
+static inline void ct_assert_unique_ ## s_name ## _attributes(void)	\
+{									\
+	switch (0) {							\
+		s_fields						\
+			;						\
+	}								\
+}
+
+#undef __field
+#define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put,	\
+		__is_signed)						\
+	case attr_nr:
+
+#undef __array
+#define __array(attr_nr, attr_flag, name, nla_type, type, maxlen,	\
+		__get, __put, __is_signed)				\
+	case attr_nr:
+
+#include GENL_MAGIC_INCLUDE_FILE
+
+/*									}}}1
+ * Magic: declare structs
+ * struct <name> {
+ *	fields
+ * };
+ *									{{{2
+ */
+
+#undef GENL_struct
+#define GENL_struct(tag_name, tag_number, s_name, s_fields)		\
+struct s_name { s_fields };
+
+#undef __field
+#define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put,	\
+		__is_signed)						\
+	type name;
+
+#undef __array
+#define __array(attr_nr, attr_flag, name, nla_type, type, maxlen,	\
+		__get, __put, __is_signed)				\
+	type name[maxlen];	\
+	__u32 name ## _len;
+
+#include GENL_MAGIC_INCLUDE_FILE
+
+#undef GENL_struct
+#define GENL_struct(tag_name, tag_number, s_name, s_fields)		\
+enum {									\
+	s_fields							\
+};
+
+#undef __field
+#define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put,	\
+		is_signed)						\
+	F_ ## name ## _IS_SIGNED = is_signed,
+
+#undef __array
+#define __array(attr_nr, attr_flag, name, nla_type, type, maxlen,	\
+		__get, __put, is_signed)				\
+	F_ ## name ## _IS_SIGNED = is_signed,
+
+#include GENL_MAGIC_INCLUDE_FILE
+
+/* }}}1 */
+#endif /* GENL_MAGIC_STRUCT_H */
+/* vim: set foldmethod=marker nofoldenable : */
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 02c1c97..c0fb4d8 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -30,9 +30,11 @@ struct vm_area_struct;
 #define ___GFP_HARDWALL		0x20000u
 #define ___GFP_THISNODE		0x40000u
 #define ___GFP_RECLAIMABLE	0x80000u
-#define ___GFP_NOTRACK		0x200000u
-#define ___GFP_OTHER_NODE	0x800000u
-#define ___GFP_WRITE		0x1000000u
+#define ___GFP_NOTRACK		0x100000u
+#define ___GFP_OTHER_NODE	0x200000u
+#define ___GFP_WRITE		0x400000u
+#define ___GFP_KMEMCG		0x800000u
+/* If the above are modified, __GFP_BITS_SHIFT may need updating */
 
 /*
  * GFP bitmasks..
@@ -87,14 +89,14 @@ struct vm_area_struct;
 
 #define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */
 #define __GFP_WRITE	((__force gfp_t)___GFP_WRITE)	/* Allocator intends to dirty page */
-
+#define __GFP_KMEMCG	((__force gfp_t)___GFP_KMEMCG) /* Allocation comes from a memcg-accounted resource */
 /*
  * This may seem redundant, but it's a way of annotating false positives vs.
  * allocations that simply cannot be supported (e.g. page tables).
  */
 #define __GFP_NOTRACK_FALSE_POSITIVE (__GFP_NOTRACK)
 
-#define __GFP_BITS_SHIFT 25	/* Room for N __GFP_FOO bits */
+#define __GFP_BITS_SHIFT 24	/* Room for N __GFP_FOO bits */
 #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
 
 /* This equals 0, but use constants in case they ever change */
@@ -263,7 +265,7 @@ static inline enum zone_type gfp_zone(gfp_t flags)
 
 static inline int gfp_zonelist(gfp_t flags)
 {
-	if (NUMA_BUILD && unlikely(flags & __GFP_THISNODE))
+	if (IS_ENABLED(CONFIG_NUMA) && unlikely(flags & __GFP_THISNODE))
 		return 1;
 
 	return 0;
@@ -361,6 +363,9 @@ extern void free_pages(unsigned long addr, unsigned int order);
 extern void free_hot_cold_page(struct page *page, int cold);
 extern void free_hot_cold_page_list(struct list_head *list, int cold);
 
+extern void __free_memcg_kmem_pages(struct page *page, unsigned int order);
+extern void free_memcg_kmem_pages(unsigned long addr, unsigned int order);
+
 #define __free_page(page) __free_pages((page), 0)
 #define free_page(addr) free_pages((addr), 0)
 
diff --git a/include/linux/gpio.h b/include/linux/gpio.h
index 2e31e8b..bfe6656 100644
--- a/include/linux/gpio.h
+++ b/include/linux/gpio.h
@@ -72,9 +72,9 @@ static inline int irq_to_gpio(unsigned int irq)
 	return -EINVAL;
 }
 
-#endif
+#endif /* ! CONFIG_ARCH_HAVE_CUSTOM_GPIO_H */
 
-#else
+#else /* ! CONFIG_GENERIC_GPIO */
 
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -231,6 +231,21 @@ static inline int irq_to_gpio(unsigned irq)
 	return -EINVAL;
 }
 
-#endif
+static inline int
+gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+		       unsigned int gpio_offset, unsigned int pin_offset,
+		       unsigned int npins)
+{
+	WARN_ON(1);
+	return -EINVAL;
+}
+
+static inline void
+gpiochip_remove_pin_ranges(struct gpio_chip *chip)
+{
+	WARN_ON(1);
+}
+
+#endif /* ! CONFIG_GENERIC_GPIO */
 
 #endif /* __LINUX_GPIO_H */
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index cab3da3..624ef3f 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -4,6 +4,7 @@
 #include <linux/preempt.h>
 #include <linux/lockdep.h>
 #include <linux/ftrace_irq.h>
+#include <linux/vtime.h>
 #include <asm/hardirq.h>
 
 /*
@@ -129,16 +130,6 @@ extern void synchronize_irq(unsigned int irq);
 # define synchronize_irq(irq)	barrier()
 #endif
 
-struct task_struct;
-
-#if !defined(CONFIG_VIRT_CPU_ACCOUNTING) && !defined(CONFIG_IRQ_TIME_ACCOUNTING)
-static inline void vtime_account(struct task_struct *tsk)
-{
-}
-#else
-extern void vtime_account(struct task_struct *tsk);
-#endif
-
 #if defined(CONFIG_TINY_RCU) || defined(CONFIG_TINY_PREEMPT_RCU)
 
 static inline void rcu_nmi_enter(void)
@@ -162,7 +153,7 @@ extern void rcu_nmi_exit(void);
  */
 #define __irq_enter()					\
 	do {						\
-		vtime_account(current);		\
+		vtime_account_irq_enter(current);	\
 		add_preempt_count(HARDIRQ_OFFSET);	\
 		trace_hardirq_enter();			\
 	} while (0)
@@ -178,7 +169,7 @@ extern void irq_enter(void);
 #define __irq_exit()					\
 	do {						\
 		trace_hardirq_exit();			\
-		vtime_account(current);		\
+		vtime_account_irq_exit(current);	\
 		sub_preempt_count(HARDIRQ_OFFSET);	\
 	} while (0)
 
diff --git a/include/linux/hdlc/Kbuild b/include/linux/hdlc/Kbuild
index 1fb2644..e69de29 100644
--- a/include/linux/hdlc/Kbuild
+++ b/include/linux/hdlc/Kbuild
@@ -1 +0,0 @@
-header-y += ioctl.h
diff --git a/include/linux/hdlc/ioctl.h b/include/linux/hdlc/ioctl.h
deleted file mode 100644
index 5839723..0000000
--- a/include/linux/hdlc/ioctl.h
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef __HDLC_IOCTL_H__
-#define __HDLC_IOCTL_H__
-
-
-#define GENERIC_HDLC_VERSION 4	/* For synchronization with sethdlc utility */
-
-#define CLOCK_DEFAULT   0	/* Default setting */
-#define CLOCK_EXT	1	/* External TX and RX clock - DTE */
-#define CLOCK_INT	2	/* Internal TX and RX clock - DCE */
-#define CLOCK_TXINT	3	/* Internal TX and external RX clock */
-#define CLOCK_TXFROMRX	4	/* TX clock derived from external RX clock */
-
-
-#define ENCODING_DEFAULT	0 /* Default setting */
-#define ENCODING_NRZ		1
-#define ENCODING_NRZI		2
-#define ENCODING_FM_MARK	3
-#define ENCODING_FM_SPACE	4
-#define ENCODING_MANCHESTER	5
-
-
-#define PARITY_DEFAULT		0 /* Default setting */
-#define PARITY_NONE		1 /* No parity */
-#define PARITY_CRC16_PR0	2 /* CRC16, initial value 0x0000 */
-#define PARITY_CRC16_PR1	3 /* CRC16, initial value 0xFFFF */
-#define PARITY_CRC16_PR0_CCITT	4 /* CRC16, initial 0x0000, ITU-T version */
-#define PARITY_CRC16_PR1_CCITT	5 /* CRC16, initial 0xFFFF, ITU-T version */
-#define PARITY_CRC32_PR0_CCITT	6 /* CRC32, initial value 0x00000000 */
-#define PARITY_CRC32_PR1_CCITT	7 /* CRC32, initial value 0xFFFFFFFF */
-
-#define LMI_DEFAULT		0 /* Default setting */
-#define LMI_NONE		1 /* No LMI, all PVCs are static */
-#define LMI_ANSI		2 /* ANSI Annex D */
-#define LMI_CCITT		3 /* ITU-T Annex A */
-#define LMI_CISCO		4 /* The "original" LMI, aka Gang of Four */
-
-typedef struct { 
-	unsigned int clock_rate; /* bits per second */
-	unsigned int clock_type; /* internal, external, TX-internal etc. */
-	unsigned short loopback;
-} sync_serial_settings;          /* V.35, V.24, X.21 */
-
-typedef struct { 
-	unsigned int clock_rate; /* bits per second */
-	unsigned int clock_type; /* internal, external, TX-internal etc. */
-	unsigned short loopback;
-	unsigned int slot_map;
-} te1_settings;                  /* T1, E1 */
-
-typedef struct {
-	unsigned short encoding;
-	unsigned short parity;
-} raw_hdlc_proto;
-
-typedef struct {
-	unsigned int t391;
-	unsigned int t392;
-	unsigned int n391;
-	unsigned int n392;
-	unsigned int n393;
-	unsigned short lmi;
-	unsigned short dce; /* 1 for DCE (network side) operation */
-} fr_proto;
-
-typedef struct {
-	unsigned int dlci;
-} fr_proto_pvc;          /* for creating/deleting FR PVCs */
-
-typedef struct {
-	unsigned int dlci;
-	char master[IFNAMSIZ];	/* Name of master FRAD device */
-}fr_proto_pvc_info;		/* for returning PVC information only */
-
-typedef struct {
-    unsigned int interval;
-    unsigned int timeout;
-} cisco_proto;
-
-/* PPP doesn't need any info now - supply length = 0 to ioctl */
-
-#endif /* __HDLC_IOCTL_H__ */
diff --git a/include/linux/hid.h b/include/linux/hid.h
index c076041..d2c42dd 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -342,6 +342,7 @@ struct hid_collection {
 struct hid_usage {
 	unsigned  hid;			/* hid usage code */
 	unsigned  collection_index;	/* index into collection array */
+	unsigned  usage_index;		/* index into usage array */
 	/* hidinput data */
 	__u16     code;			/* input driver code */
 	__u8      type;			/* input driver type */
@@ -706,6 +707,7 @@ int hid_input_report(struct hid_device *, int type, u8 *, int, int);
 int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field);
 struct hid_field *hidinput_get_led_field(struct hid_device *hid);
 unsigned int hidinput_count_leds(struct hid_device *hid);
+__s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code);
 void hid_output_report(struct hid_report *report, __u8 *data);
 struct hid_device *hid_allocate_device(void);
 struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
@@ -716,6 +718,7 @@ int hid_connect(struct hid_device *hid, unsigned int connect_mask);
 void hid_disconnect(struct hid_device *hid);
 const struct hid_device_id *hid_match_id(struct hid_device *hdev,
 					 const struct hid_device_id *id);
+s32 hid_snto32(__u32 value, unsigned n);
 
 /**
  * hid_map_usage - map usage input bits
diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
index b31cb7d..b874015 100644
--- a/include/linux/huge_mm.h
+++ b/include/linux/huge_mm.h
@@ -8,6 +8,10 @@ extern int do_huge_pmd_anonymous_page(struct mm_struct *mm,
 extern int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
 			 pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long addr,
 			 struct vm_area_struct *vma);
+extern void huge_pmd_set_accessed(struct mm_struct *mm,
+				  struct vm_area_struct *vma,
+				  unsigned long address, pmd_t *pmd,
+				  pmd_t orig_pmd, int dirty);
 extern int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
 			       unsigned long address, pmd_t *pmd,
 			       pmd_t orig_pmd);
@@ -35,6 +39,7 @@ enum transparent_hugepage_flag {
 	TRANSPARENT_HUGEPAGE_DEFRAG_FLAG,
 	TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG,
 	TRANSPARENT_HUGEPAGE_DEFRAG_KHUGEPAGED_FLAG,
+	TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG,
 #ifdef CONFIG_DEBUG_VM
 	TRANSPARENT_HUGEPAGE_DEBUG_COW_FLAG,
 #endif
@@ -74,6 +79,9 @@ extern bool is_vma_temporary_stack(struct vm_area_struct *vma);
 	 (transparent_hugepage_flags &					\
 	  (1<<TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG) &&		\
 	  (__vma)->vm_flags & VM_HUGEPAGE))
+#define transparent_hugepage_use_zero_page()				\
+	(transparent_hugepage_flags &					\
+	 (1<<TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG))
 #ifdef CONFIG_DEBUG_VM
 #define transparent_hugepage_debug_cow()				\
 	(transparent_hugepage_flags &					\
@@ -91,12 +99,14 @@ extern int handle_pte_fault(struct mm_struct *mm,
 			    struct vm_area_struct *vma, unsigned long address,
 			    pte_t *pte, pmd_t *pmd, unsigned int flags);
 extern int split_huge_page(struct page *page);
-extern void __split_huge_page_pmd(struct mm_struct *mm, pmd_t *pmd);
-#define split_huge_page_pmd(__mm, __pmd)				\
+extern void __split_huge_page_pmd(struct vm_area_struct *vma,
+		unsigned long address, pmd_t *pmd);
+#define split_huge_page_pmd(__vma, __address, __pmd)			\
 	do {								\
 		pmd_t *____pmd = (__pmd);				\
 		if (unlikely(pmd_trans_huge(*____pmd)))			\
-			__split_huge_page_pmd(__mm, ____pmd);		\
+			__split_huge_page_pmd(__vma, __address,		\
+					____pmd);			\
 	}  while (0)
 #define wait_split_huge_page(__anon_vma, __pmd)				\
 	do {								\
@@ -106,6 +116,8 @@ extern void __split_huge_page_pmd(struct mm_struct *mm, pmd_t *pmd);
 		BUG_ON(pmd_trans_splitting(*____pmd) ||			\
 		       pmd_trans_huge(*____pmd));			\
 	} while (0)
+extern void split_huge_page_pmd_mm(struct mm_struct *mm, unsigned long address,
+		pmd_t *pmd);
 #if HPAGE_PMD_ORDER > MAX_ORDER
 #error "hugepages can't be allocated by the buddy allocator"
 #endif
@@ -173,10 +185,12 @@ static inline int split_huge_page(struct page *page)
 {
 	return 0;
 }
-#define split_huge_page_pmd(__mm, __pmd)	\
+#define split_huge_page_pmd(__vma, __address, __pmd)	\
 	do { } while (0)
 #define wait_split_huge_page(__anon_vma, __pmd)	\
 	do { } while (0)
+#define split_huge_page_pmd_mm(__mm, __address, __pmd)	\
+	do { } while (0)
 #define compound_trans_head(page) compound_head(page)
 static inline int hugepage_madvise(struct vm_area_struct *vma,
 				   unsigned long *vm_flags, int advice)
@@ -197,4 +211,16 @@ static inline int pmd_trans_huge_lock(pmd_t *pmd,
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
+#ifdef CONFIG_NUMA_BALANCING_HUGEPAGE
+extern void do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
+				  unsigned long address, pmd_t *pmd,
+				  unsigned int flags, pmd_t orig_pmd);
+#else
+static inline void do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
+					 unsigned long address, pmd_t *pmd,
+					 unsigned int flags, pmd_t orig_pmd)
+{
+}
+#endif
+
 #endif /* _LINUX_HUGE_MM_H */
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 2251648..0c80d3f 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -87,7 +87,7 @@ struct page *follow_huge_pud(struct mm_struct *mm, unsigned long address,
 				pud_t *pud, int write);
 int pmd_huge(pmd_t pmd);
 int pud_huge(pud_t pmd);
-void hugetlb_change_protection(struct vm_area_struct *vma,
+unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
 		unsigned long address, unsigned long end, pgprot_t newprot);
 
 #else /* !CONFIG_HUGETLB_PAGE */
@@ -132,7 +132,11 @@ static inline void copy_huge_page(struct page *dst, struct page *src)
 {
 }
 
-#define hugetlb_change_protection(vma, address, end, newprot)
+static inline unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
+		unsigned long address, unsigned long end, pgprot_t newprot)
+{
+	return 0;
+}
 
 static inline void __unmap_hugepage_range_final(struct mmu_gather *tlb,
 			struct vm_area_struct *vma, unsigned long start,
@@ -183,7 +187,8 @@ extern const struct file_operations hugetlbfs_file_operations;
 extern const struct vm_operations_struct hugetlb_vm_ops;
 struct file *hugetlb_file_setup(const char *name, unsigned long addr,
 				size_t size, vm_flags_t acct,
-				struct user_struct **user, int creat_flags);
+				struct user_struct **user, int creat_flags,
+				int page_size_log);
 
 static inline int is_file_hugepages(struct file *file)
 {
@@ -195,12 +200,14 @@ static inline int is_file_hugepages(struct file *file)
 	return 0;
 }
 
+
 #else /* !CONFIG_HUGETLBFS */
 
 #define is_file_hugepages(file)			0
 static inline struct file *
 hugetlb_file_setup(const char *name, unsigned long addr, size_t size,
-		vm_flags_t acctflag, struct user_struct **user, int creat_flags)
+		vm_flags_t acctflag, struct user_struct **user, int creat_flags,
+		int page_size_log)
 {
 	return ERR_PTR(-ENOSYS);
 }
diff --git a/include/linux/i2c-omap.h b/include/linux/i2c-omap.h
index 92a0dc7..1b25c04 100644
--- a/include/linux/i2c-omap.h
+++ b/include/linux/i2c-omap.h
@@ -21,7 +21,6 @@
 #define OMAP_I2C_FLAG_SIMPLE_CLOCK		BIT(1)
 #define OMAP_I2C_FLAG_16BIT_DATA_REG		BIT(2)
 #define OMAP_I2C_FLAG_RESET_REGS_POSTIDLE	BIT(3)
-#define OMAP_I2C_FLAG_APPLY_ERRATA_I207	BIT(4)
 #define OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK	BIT(5)
 #define OMAP_I2C_FLAG_FORCE_19200_INT_CLK	BIT(6)
 /* how the CPU address bus must be translated for I2C unit access */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 800de22..d0c4db7 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -259,6 +259,7 @@ static inline void i2c_set_clientdata(struct i2c_client *dev, void *data)
  * @platform_data: stored in i2c_client.dev.platform_data
  * @archdata: copied into i2c_client.dev.archdata
  * @of_node: pointer to OpenFirmware device node
+ * @acpi_node: ACPI device node
  * @irq: stored in i2c_client.irq
  *
  * I2C doesn't actually support hardware probing, although controllers and
@@ -279,6 +280,7 @@ struct i2c_board_info {
 	void		*platform_data;
 	struct dev_archdata	*archdata;
 	struct device_node *of_node;
+	struct acpi_dev_node acpi_node;
 	int		irq;
 };
 
@@ -501,4 +503,11 @@ static inline int i2c_adapter_id(struct i2c_adapter *adap)
 			i2c_del_driver)
 
 #endif /* I2C */
+
+#if IS_ENABLED(CONFIG_ACPI_I2C)
+extern void acpi_i2c_register_devices(struct i2c_adapter *adap);
+#else
+static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) {}
+#endif
+
 #endif /* _LINUX_I2C_H */
diff --git a/include/linux/i2c/i2c-hid.h b/include/linux/i2c/i2c-hid.h
new file mode 100644
index 0000000..60e411d
--- /dev/null
+++ b/include/linux/i2c/i2c-hid.h
@@ -0,0 +1,35 @@
+/*
+ * HID over I2C protocol implementation
+ *
+ * Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+ * Copyright (c) 2012 Ecole Nationale de l'Aviation Civile, France
+ *
+ * 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 __LINUX_I2C_HID_H
+#define __LINUX_I2C_HID_H
+
+#include <linux/types.h>
+
+/**
+ * struct i2chid_platform_data - used by hid over i2c implementation.
+ * @hid_descriptor_address: i2c register where the HID descriptor is stored.
+ *
+ * Note that it is the responsibility of the platform driver (or the acpi 5.0
+ * driver) to setup the irq related to the gpio in the struct i2c_board_info.
+ * The platform driver should also setup the gpio according to the device:
+ *
+ * A typical example is the following:
+ *	irq = gpio_to_irq(intr_gpio);
+ *	hkdk4412_i2c_devs5[0].irq = irq; // store the irq in i2c_board_info
+ *	gpio_request(intr_gpio, "elan-irq");
+ *	s3c_gpio_setpull(intr_gpio, S3C_GPIO_PULL_UP);
+ */
+struct i2c_hid_platform_data {
+	u16 hid_descriptor_address;
+};
+
+#endif /* __LINUX_I2C_HID_H */
diff --git a/include/linux/i2c/i2c-sh_mobile.h b/include/linux/i2c/i2c-sh_mobile.h
index beda708..06e3089 100644
--- a/include/linux/i2c/i2c-sh_mobile.h
+++ b/include/linux/i2c/i2c-sh_mobile.h
@@ -5,6 +5,7 @@
 
 struct i2c_sh_mobile_platform_data {
 	unsigned long bus_speed;
+	unsigned int clks_per_count;
 };
 
 #endif /* __I2C_SH_MOBILE_H__ */
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 9a5e284..1ff54b1 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -39,52 +39,51 @@
  * address each module uses within a given i2c slave.
  */
 
-/* Slave 0 (i2c address 0x48) */
-#define TWL4030_MODULE_USB		0x00
-
-/* Slave 1 (i2c address 0x49) */
-#define TWL4030_MODULE_AUDIO_VOICE	0x01
-#define TWL4030_MODULE_GPIO		0x02
-#define TWL4030_MODULE_INTBR		0x03
-#define TWL4030_MODULE_PIH		0x04
-#define TWL4030_MODULE_TEST		0x05
-
-/* Slave 2 (i2c address 0x4a) */
-#define TWL4030_MODULE_KEYPAD		0x06
-#define TWL4030_MODULE_MADC		0x07
-#define TWL4030_MODULE_INTERRUPTS	0x08
-#define TWL4030_MODULE_LED		0x09
-#define TWL4030_MODULE_MAIN_CHARGE	0x0A
-#define TWL4030_MODULE_PRECHARGE	0x0B
-#define TWL4030_MODULE_PWM0		0x0C
-#define TWL4030_MODULE_PWM1		0x0D
-#define TWL4030_MODULE_PWMA		0x0E
-#define TWL4030_MODULE_PWMB		0x0F
-
-#define TWL5031_MODULE_ACCESSORY	0x10
-#define TWL5031_MODULE_INTERRUPTS	0x11
-
-/* Slave 3 (i2c address 0x4b) */
-#define TWL4030_MODULE_BACKUP		0x12
-#define TWL4030_MODULE_INT		0x13
-#define TWL4030_MODULE_PM_MASTER	0x14
-#define TWL4030_MODULE_PM_RECEIVER	0x15
-#define TWL4030_MODULE_RTC		0x16
-#define TWL4030_MODULE_SECURED_REG	0x17
+enum twl4030_module_ids {
+	TWL4030_MODULE_USB = 0,		/* Slave 0 (i2c address 0x48) */
+	TWL4030_MODULE_AUDIO_VOICE,	/* Slave 1 (i2c address 0x49) */
+	TWL4030_MODULE_GPIO,
+	TWL4030_MODULE_INTBR,
+	TWL4030_MODULE_PIH,
+
+	TWL4030_MODULE_TEST,
+	TWL4030_MODULE_KEYPAD,		/* Slave 2 (i2c address 0x4a) */
+	TWL4030_MODULE_MADC,
+	TWL4030_MODULE_INTERRUPTS,
+	TWL4030_MODULE_LED,
+
+	TWL4030_MODULE_MAIN_CHARGE,
+	TWL4030_MODULE_PRECHARGE,
+	TWL4030_MODULE_PWM0,
+	TWL4030_MODULE_PWM1,
+	TWL4030_MODULE_PWMA,
+
+	TWL4030_MODULE_PWMB,
+	TWL5031_MODULE_ACCESSORY,
+	TWL5031_MODULE_INTERRUPTS,
+	TWL4030_MODULE_BACKUP,		/* Slave 3 (i2c address 0x4b) */
+	TWL4030_MODULE_INT,
+
+	TWL4030_MODULE_PM_MASTER,
+	TWL4030_MODULE_PM_RECEIVER,
+	TWL4030_MODULE_RTC,
+	TWL4030_MODULE_SECURED_REG,
+	TWL4030_MODULE_LAST,
+};
 
+/* Similar functionalities implemented in TWL4030/6030 */
 #define TWL_MODULE_USB		TWL4030_MODULE_USB
-#define TWL_MODULE_AUDIO_VOICE	TWL4030_MODULE_AUDIO_VOICE
 #define TWL_MODULE_PIH		TWL4030_MODULE_PIH
-#define TWL_MODULE_MADC		TWL4030_MODULE_MADC
 #define TWL_MODULE_MAIN_CHARGE	TWL4030_MODULE_MAIN_CHARGE
 #define TWL_MODULE_PM_MASTER	TWL4030_MODULE_PM_MASTER
 #define TWL_MODULE_PM_RECEIVER	TWL4030_MODULE_PM_RECEIVER
 #define TWL_MODULE_RTC		TWL4030_MODULE_RTC
 #define TWL_MODULE_PWM		TWL4030_MODULE_PWM0
+#define TWL_MODULE_LED		TWL4030_MODULE_LED
 
-#define TWL6030_MODULE_ID0	0x0D
-#define TWL6030_MODULE_ID1	0x0E
-#define TWL6030_MODULE_ID2	0x0F
+#define TWL6030_MODULE_ID0	13
+#define TWL6030_MODULE_ID1	14
+#define TWL6030_MODULE_ID2	15
 
 #define GPIO_INTR_OFFSET	0
 #define KEYPAD_INTR_OFFSET	1
diff --git a/include/linux/idr.h b/include/linux/idr.h
index 87259a4..de7e190 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -152,4 +152,15 @@ void ida_simple_remove(struct ida *ida, unsigned int id);
 
 void __init idr_init_cache(void);
 
+/**
+ * idr_for_each_entry - iterate over an idr's elements of a given type
+ * @idp:     idr handle
+ * @entry:   the type * to use as cursor
+ * @id:      id entry's key
+ */
+#define idr_for_each_entry(idp, entry, id)				\
+	for (id = 0, entry = (typeof(entry))idr_get_next((idp), &(id)); \
+	     entry != NULL;                                             \
+	     ++id, entry = (typeof(entry))idr_get_next((idp), &(id)))
+
 #endif /* __IDR_H__ */
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 2385119..f9c5a78 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -131,6 +131,8 @@
 
 #define IEEE80211_MAX_MESH_ID_LEN	32
 
+#define IEEE80211_NUM_TIDS		16
+
 #define IEEE80211_QOS_CTL_LEN		2
 /* 1d tag mask */
 #define IEEE80211_QOS_CTL_TAG1D_MASK		0x0007
@@ -666,6 +668,21 @@ struct ieee80211_meshconf_ie {
 } __attribute__ ((packed));
 
 /**
+ * enum mesh_config_capab_flags - Mesh Configuration IE capability field flags
+ *
+ * @IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS: STA is willing to establish
+ *	additional mesh peerings with other mesh STAs
+ * @IEEE80211_MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs
+ * @IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure
+ *	is ongoing
+ */
+enum mesh_config_capab_flags {
+	IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS		= 0x01,
+	IEEE80211_MESHCONF_CAPAB_FORWARDING		= 0x08,
+	IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING		= 0x20,
+};
+
+/**
  * struct ieee80211_rann_ie
  *
  * This structure refers to "Root Announcement information element"
@@ -905,6 +922,38 @@ struct ieee80211_tdls_data {
 	} u;
 } __packed;
 
+/*
+ * Peer-to-Peer IE attribute related definitions.
+ */
+/**
+ * enum ieee80211_p2p_attr_id - identifies type of peer-to-peer attribute.
+ */
+enum ieee80211_p2p_attr_id {
+	IEEE80211_P2P_ATTR_STATUS = 0,
+	IEEE80211_P2P_ATTR_MINOR_REASON,
+	IEEE80211_P2P_ATTR_CAPABILITY,
+	IEEE80211_P2P_ATTR_DEVICE_ID,
+	IEEE80211_P2P_ATTR_GO_INTENT,
+	IEEE80211_P2P_ATTR_GO_CONFIG_TIMEOUT,
+	IEEE80211_P2P_ATTR_LISTEN_CHANNEL,
+	IEEE80211_P2P_ATTR_GROUP_BSSID,
+	IEEE80211_P2P_ATTR_EXT_LISTEN_TIMING,
+	IEEE80211_P2P_ATTR_INTENDED_IFACE_ADDR,
+	IEEE80211_P2P_ATTR_MANAGABILITY,
+	IEEE80211_P2P_ATTR_CHANNEL_LIST,
+	IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
+	IEEE80211_P2P_ATTR_DEVICE_INFO,
+	IEEE80211_P2P_ATTR_GROUP_INFO,
+	IEEE80211_P2P_ATTR_GROUP_ID,
+	IEEE80211_P2P_ATTR_INTERFACE,
+	IEEE80211_P2P_ATTR_OPER_CHANNEL,
+	IEEE80211_P2P_ATTR_INVITE_FLAGS,
+	/* 19 - 220: Reserved */
+	IEEE80211_P2P_ATTR_VENDOR_SPECIFIC = 221,
+
+	IEEE80211_P2P_ATTR_MAX
+};
+
 /**
  * struct ieee80211_bar - HT Block Ack Request
  *
@@ -1107,20 +1156,6 @@ struct ieee80211_ht_operation {
 #define WLAN_HT_SMPS_CONTROL_STATIC	1
 #define WLAN_HT_SMPS_CONTROL_DYNAMIC	3
 
-#define VHT_MCS_SUPPORTED_SET_SIZE      8
-
-struct ieee80211_vht_capabilities {
-	__le32 vht_capabilities_info;
-	u8 vht_supported_mcs_set[VHT_MCS_SUPPORTED_SET_SIZE];
-} __packed;
-
-struct ieee80211_vht_operation {
-	u8 vht_op_info_chwidth;
-	u8 vht_op_info_chan_center_freq_seg1_idx;
-	u8 vht_op_info_chan_center_freq_seg2_idx;
-	__le16 vht_basic_mcs_set;
-} __packed;
-
 /**
  * struct ieee80211_vht_mcs_info - VHT MCS information
  * @rx_mcs_map: RX MCS map 2 bits for each stream, total 8 streams
@@ -1128,11 +1163,13 @@ struct ieee80211_vht_operation {
  *	STA can receive. Rate expressed in units of 1 Mbps.
  *	If this field is 0 this value should not be used to
  *	consider the highest RX data rate supported.
+ *	The top 3 bits of this field are reserved.
  * @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams
  * @tx_highest: Indicates highest long GI VHT PPDU data rate
  *	STA can transmit. Rate expressed in units of 1 Mbps.
  *	If this field is 0 this value should not be used to
  *	consider the highest TX data rate supported.
+ *	The top 3 bits of this field are reserved.
  */
 struct ieee80211_vht_mcs_info {
 	__le16 rx_mcs_map;
@@ -1141,6 +1178,58 @@ struct ieee80211_vht_mcs_info {
 	__le16 tx_highest;
 } __packed;
 
+/**
+ * enum ieee80211_vht_mcs_support - VHT MCS support definitions
+ * @IEEE80211_VHT_MCS_SUPPORT_0_7: MCSes 0-7 are supported for the
+ *	number of streams
+ * @IEEE80211_VHT_MCS_SUPPORT_0_8: MCSes 0-8 are supported
+ * @IEEE80211_VHT_MCS_SUPPORT_0_9: MCSes 0-9 are supported
+ * @IEEE80211_VHT_MCS_NOT_SUPPORTED: This number of streams isn't supported
+ *
+ * These definitions are used in each 2-bit subfield of the @rx_mcs_map
+ * and @tx_mcs_map fields of &struct ieee80211_vht_mcs_info, which are
+ * both split into 8 subfields by number of streams. These values indicate
+ * which MCSes are supported for the number of streams the value appears
+ * for.
+ */
+enum ieee80211_vht_mcs_support {
+	IEEE80211_VHT_MCS_SUPPORT_0_7	= 0,
+	IEEE80211_VHT_MCS_SUPPORT_0_8	= 1,
+	IEEE80211_VHT_MCS_SUPPORT_0_9	= 2,
+	IEEE80211_VHT_MCS_NOT_SUPPORTED	= 3,
+};
+
+/**
+ * struct ieee80211_vht_cap - VHT capabilities
+ *
+ * This structure is the "VHT capabilities element" as
+ * described in 802.11ac D3.0 8.4.2.160
+ * @vht_cap_info: VHT capability info
+ * @supp_mcs: VHT MCS supported rates
+ */
+struct ieee80211_vht_cap {
+	__le32 vht_cap_info;
+	struct ieee80211_vht_mcs_info supp_mcs;
+} __packed;
+
+/**
+ * struct ieee80211_vht_operation - VHT operation IE
+ *
+ * This structure is the "VHT operation element" as
+ * described in 802.11ac D3.0 8.4.2.161
+ * @chan_width: Operating channel width
+ * @center_freq_seg1_idx: center freq segment 1 index
+ * @center_freq_seg2_idx: center freq segment 2 index
+ * @basic_mcs_set: VHT Basic MCS rate set
+ */
+struct ieee80211_vht_operation {
+	u8 chan_width;
+	u8 center_freq_seg1_idx;
+	u8 center_freq_seg2_idx;
+	__le16 basic_mcs_set;
+} __packed;
+
+
 #define IEEE80211_VHT_MCS_ZERO_TO_SEVEN_SUPPORT 0
 #define IEEE80211_VHT_MCS_ZERO_TO_EIGHT_SUPPORT 1
 #define IEEE80211_VHT_MCS_ZERO_TO_NINE_SUPPORT  2
@@ -1440,8 +1529,6 @@ enum ieee80211_eid {
 
 	WLAN_EID_RSN = 48,
 	WLAN_EID_MMIE = 76,
-	WLAN_EID_WPA = 221,
-	WLAN_EID_GENERIC = 221,
 	WLAN_EID_VENDOR_SPECIFIC = 221,
 	WLAN_EID_QOS_PARAMETER = 222,
 
diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h
index 1cc595a..f4e56ec 100644
--- a/include/linux/if_tunnel.h
+++ b/include/linux/if_tunnel.h
@@ -4,5 +4,22 @@
 #include <linux/ip.h>
 #include <linux/in6.h>
 #include <uapi/linux/if_tunnel.h>
+#include <linux/u64_stats_sync.h>
+
+/*
+ * Locking : hash tables are protected by RCU and RTNL
+ */
+
+#define for_each_ip_tunnel_rcu(pos, start) \
+	for (pos = rcu_dereference(start); pos; pos = rcu_dereference(pos->next))
+
+/* often modified stats are per cpu, other are shared (netdev->stats) */
+struct pcpu_tstats {
+	u64	rx_packets;
+	u64	rx_bytes;
+	u64	tx_packets;
+	u64	tx_bytes;
+	struct u64_stats_sync	syncp;
+};
 
 #endif /* _IF_TUNNEL_H_ */
diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h
index c629b3a..f3eea18 100644
--- a/include/linux/iio/buffer.h
+++ b/include/linux/iio/buffer.h
@@ -66,7 +66,8 @@ struct iio_buffer_access_funcs {
  * @stufftoread:	[INTERN] flag to indicate new data.
  * @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.
+ */
 struct iio_buffer {
 	int					length;
 	int					bytes_per_datum;
@@ -81,9 +82,22 @@ struct iio_buffer {
 	const struct attribute_group *attrs;
 	struct list_head			demux_list;
 	unsigned char				*demux_bounce;
+	struct list_head			buffer_list;
 };
 
 /**
+ * iio_update_buffers() - add or remove buffer from active list
+ * @indio_dev:		device to add buffer to
+ * @insert_buffer:	buffer to insert
+ * @remove_buffer:	buffer_to_remove
+ *
+ * Note this will tear down the all buffering and build it up again
+ */
+int iio_update_buffers(struct iio_dev *indio_dev,
+		       struct iio_buffer *insert_buffer,
+		       struct iio_buffer *remove_buffer);
+
+/**
  * iio_buffer_init() - Initialize the buffer structure
  * @buffer:		buffer to be initialized
  **/
@@ -115,11 +129,11 @@ int iio_scan_mask_set(struct iio_dev *indio_dev,
 		      struct iio_buffer *buffer, int bit);
 
 /**
- * iio_push_to_buffer() - push to a registered buffer.
- * @buffer:		IIO buffer structure for device
- * @data:		the data to push to the buffer
+ * iio_push_to_buffers() - push to a registered buffer.
+ * @indio_dev:		iio_dev structure for device.
+ * @data:		Full scan.
  */
-int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data);
+int iio_push_to_buffers(struct iio_dev *indio_dev, unsigned char *data);
 
 int iio_update_demux(struct iio_dev *indio_dev);
 
@@ -181,7 +195,7 @@ bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev,
 #else /* CONFIG_IIO_BUFFER */
 
 static inline int iio_buffer_register(struct iio_dev *indio_dev,
-					   struct iio_chan_spec *channels,
+					   const struct iio_chan_spec *channels,
 					   int num_channels)
 {
 	return 0;
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
index e875bcf..16c35ac 100644
--- a/include/linux/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -9,6 +9,8 @@
  */
 #ifndef _IIO_INKERN_CONSUMER_H_
 #define _IIO_INKERN_CONSUMER_H_
+
+#include <linux/types.h>
 #include <linux/iio/types.h>
 
 struct iio_dev;
@@ -18,10 +20,12 @@ struct iio_chan_spec;
  * struct iio_channel - everything needed for a consumer to use a channel
  * @indio_dev:		Device on which the channel exists.
  * @channel:		Full description of the channel.
+ * @data:		Data about the channel used by consumer.
  */
 struct iio_channel {
 	struct iio_dev *indio_dev;
 	const struct iio_chan_spec *channel;
+	void *data;
 };
 
 /**
@@ -59,6 +63,52 @@ struct iio_channel *iio_channel_get_all(const char *name);
  */
 void iio_channel_release_all(struct iio_channel *chan);
 
+struct iio_cb_buffer;
+/**
+ * iio_channel_get_all_cb() - register callback for triggered capture
+ * @name:		Name of client device.
+ * @cb:			Callback function.
+ * @private:		Private data passed to callback.
+ *
+ * NB right now we have no ability to mux data from multiple devices.
+ * So if the channels requested come from different devices this will
+ * fail.
+ */
+struct iio_cb_buffer *iio_channel_get_all_cb(const char *name,
+					     int (*cb)(u8 *data,
+						       void *private),
+					     void *private);
+/**
+ * iio_channel_release_all_cb() - release and unregister the callback.
+ * @cb_buffer:		The callback buffer that was allocated.
+ */
+void iio_channel_release_all_cb(struct iio_cb_buffer *cb_buffer);
+
+/**
+ * iio_channel_start_all_cb() - start the flow of data through callback.
+ * @cb_buff:		The callback buffer we are starting.
+ */
+int iio_channel_start_all_cb(struct iio_cb_buffer *cb_buff);
+
+/**
+ * iio_channel_stop_all_cb() - stop the flow of data through the callback.
+ * @cb_buff:		The callback buffer we are stopping.
+ */
+void iio_channel_stop_all_cb(struct iio_cb_buffer *cb_buff);
+
+/**
+ * iio_channel_cb_get_channels() - get access to the underlying channels.
+ * @cb_buff:		The callback buffer from whom we want the channel
+ *			information.
+ *
+ * This function allows one to obtain information about the channels.
+ * Whilst this may allow direct reading if all buffers are disabled, the
+ * primary aim is to allow drivers that are consuming a channel to query
+ * things like scaling of the channel.
+ */
+struct iio_channel
+*iio_channel_cb_get_channels(const struct iio_cb_buffer *cb_buffer);
+
 /**
  * iio_read_channel_raw() - read from a given channel
  * @chan:		The channel being queried.
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index 7806c24..da8c776 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -410,6 +410,7 @@ struct iio_buffer_setup_ops {
  *			and owner
  * @event_interface:	[INTERN] event chrdevs associated with interrupt lines
  * @buffer:		[DRIVER] any buffer present
+ * @buffer_list:	[INTERN] list of all buffers currently attached
  * @scan_bytes:		[INTERN] num bytes captured to be fed to buffer demux
  * @mlock:		[INTERN] lock used to prevent simultaneous device state
  *			changes
@@ -448,6 +449,7 @@ struct iio_dev {
 	struct iio_event_interface	*event_interface;
 
 	struct iio_buffer		*buffer;
+	struct list_head		buffer_list;
 	int				scan_bytes;
 	struct mutex			mlock;
 
@@ -618,6 +620,9 @@ static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)
 };
 #endif
 
+int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer,
+	int *fract);
+
 /**
  * IIO_DEGREE_TO_RAD() - Convert degree to rad
  * @deg: A value in degree
diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h
new file mode 100644
index 0000000..ff781dc
--- /dev/null
+++ b/include/linux/iio/imu/adis.h
@@ -0,0 +1,280 @@
+/*
+ * Common library for ADIS16XXX devices
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *   Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __IIO_ADIS_H__
+#define __IIO_ADIS_H__
+
+#include <linux/spi/spi.h>
+#include <linux/interrupt.h>
+#include <linux/iio/types.h>
+
+#define ADIS_WRITE_REG(reg) ((0x80 | (reg)))
+#define ADIS_READ_REG(reg) ((reg) & 0x7f)
+
+#define ADIS_PAGE_SIZE 0x80
+#define ADIS_REG_PAGE_ID 0x00
+
+struct adis;
+
+/**
+ * struct adis_data - ADIS chip variant specific data
+ * @read_delay: SPI delay for read operations in us
+ * @write_delay: SPI delay for write operations in us
+ * @glob_cmd_reg: Register address of the GLOB_CMD register
+ * @msc_ctrl_reg: Register address of the MSC_CTRL register
+ * @diag_stat_reg: Register address of the DIAG_STAT register
+ * @status_error_msgs: Array of error messgaes
+ * @status_error_mask:
+ */
+struct adis_data {
+	unsigned int read_delay;
+	unsigned int write_delay;
+
+	unsigned int glob_cmd_reg;
+	unsigned int msc_ctrl_reg;
+	unsigned int diag_stat_reg;
+
+	unsigned int self_test_mask;
+	unsigned int startup_delay;
+
+	const char * const *status_error_msgs;
+	unsigned int status_error_mask;
+
+	int (*enable_irq)(struct adis *adis, bool enable);
+
+	bool has_paging;
+};
+
+struct adis {
+	struct spi_device	*spi;
+	struct iio_trigger	*trig;
+
+	const struct adis_data	*data;
+
+	struct mutex		txrx_lock;
+	struct spi_message	msg;
+	struct spi_transfer	*xfer;
+	unsigned int		current_page;
+	void			*buffer;
+
+	uint8_t			tx[10] ____cacheline_aligned;
+	uint8_t			rx[4];
+};
+
+int adis_init(struct adis *adis, struct iio_dev *indio_dev,
+	struct spi_device *spi, const struct adis_data *data);
+int adis_reset(struct adis *adis);
+
+int adis_write_reg(struct adis *adis, unsigned int reg,
+	unsigned int val, unsigned int size);
+int adis_read_reg(struct adis *adis, unsigned int reg,
+	unsigned int *val, unsigned int size);
+
+/**
+ * adis_write_reg_8() - Write single byte to a register
+ * @adis: The adis device
+ * @reg: The address of the register to be written
+ * @value: The value to write
+ */
+static inline int adis_write_reg_8(struct adis *adis, unsigned int reg,
+	uint8_t val)
+{
+	return adis_write_reg(adis, reg, val, 1);
+}
+
+/**
+ * adis_write_reg_16() - Write 2 bytes to a pair of registers
+ * @adis: The adis device
+ * @reg: The address of the lower of the two registers
+ * @value: Value to be written
+ */
+static inline int adis_write_reg_16(struct adis *adis, unsigned int reg,
+	uint16_t val)
+{
+	return adis_write_reg(adis, reg, val, 2);
+}
+
+/**
+ * adis_write_reg_32() - write 4 bytes to four registers
+ * @adis: The adis device
+ * @reg: The address of the lower of the four register
+ * @value: Value to be written
+ */
+static inline int adis_write_reg_32(struct adis *adis, unsigned int reg,
+	uint32_t val)
+{
+	return adis_write_reg(adis, reg, val, 4);
+}
+
+/**
+ * adis_read_reg_16() - read 2 bytes from a 16-bit register
+ * @adis: The adis device
+ * @reg: The address of the lower of the two registers
+ * @val: The value read back from the device
+ */
+static inline int adis_read_reg_16(struct adis *adis, unsigned int reg,
+	uint16_t *val)
+{
+	unsigned int tmp;
+	int ret;
+
+	ret = adis_read_reg(adis, reg, &tmp, 2);
+	*val = tmp;
+
+	return ret;
+}
+
+/**
+ * adis_read_reg_32() - read 4 bytes from a 32-bit register
+ * @adis: The adis device
+ * @reg: The address of the lower of the two registers
+ * @val: The value read back from the device
+ */
+static inline int adis_read_reg_32(struct adis *adis, unsigned int reg,
+	uint32_t *val)
+{
+	unsigned int tmp;
+	int ret;
+
+	ret = adis_read_reg(adis, reg, &tmp, 4);
+	*val = tmp;
+
+	return ret;
+}
+
+int adis_enable_irq(struct adis *adis, bool enable);
+int adis_check_status(struct adis *adis);
+
+int adis_initial_startup(struct adis *adis);
+
+int adis_single_conversion(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, unsigned int error_mask,
+	int *val);
+
+#define ADIS_VOLTAGE_CHAN(addr, si, chan, name, bits) { \
+	.type = IIO_VOLTAGE, \
+	.indexed = 1, \
+	.channel = (chan), \
+	.extend_name = name, \
+	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+		IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+	.address = (addr), \
+	.scan_index = (si), \
+	.scan_type = { \
+		.sign = 'u', \
+		.realbits = (bits), \
+		.storagebits = 16, \
+		.endianness = IIO_BE, \
+	}, \
+}
+
+#define ADIS_SUPPLY_CHAN(addr, si, bits) \
+	ADIS_VOLTAGE_CHAN(addr, si, 0, "supply", bits)
+
+#define ADIS_AUX_ADC_CHAN(addr, si, bits) \
+	ADIS_VOLTAGE_CHAN(addr, si, 1, NULL, bits)
+
+#define ADIS_TEMP_CHAN(addr, si, bits) { \
+	.type = IIO_TEMP, \
+	.indexed = 1, \
+	.channel = 0, \
+	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+		IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \
+		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, \
+	.address = (addr), \
+	.scan_index = (si), \
+	.scan_type = { \
+		.sign = 'u', \
+		.realbits = (bits), \
+		.storagebits = 16, \
+		.endianness = IIO_BE, \
+	}, \
+}
+
+#define ADIS_MOD_CHAN(_type, mod, addr, si, info, bits) { \
+	.type = (_type), \
+	.modified = 1, \
+	.channel2 = IIO_MOD_ ## mod, \
+	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+		 IIO_CHAN_INFO_SCALE_SHARED_BIT | \
+		 info, \
+	.address = (addr), \
+	.scan_index = (si), \
+	.scan_type = { \
+		.sign = 's', \
+		.realbits = (bits), \
+		.storagebits = 16, \
+		.endianness = IIO_BE, \
+	}, \
+}
+
+#define ADIS_ACCEL_CHAN(mod, addr, si, info, bits) \
+	ADIS_MOD_CHAN(IIO_ACCEL, mod, addr, si, info, bits)
+
+#define ADIS_GYRO_CHAN(mod, addr, si, info, bits) \
+	ADIS_MOD_CHAN(IIO_ANGL_VEL, mod, addr, si, info, bits)
+
+#define ADIS_INCLI_CHAN(mod, addr, si, info, bits) \
+	ADIS_MOD_CHAN(IIO_INCLI, mod, addr, si, info, bits)
+
+#define ADIS_ROT_CHAN(mod, addr, si, info, bits) \
+	ADIS_MOD_CHAN(IIO_ROT, mod, addr, si, info, bits)
+
+#ifdef CONFIG_IIO_ADIS_LIB_BUFFER
+
+int adis_setup_buffer_and_trigger(struct adis *adis,
+	struct iio_dev *indio_dev, irqreturn_t (*trigger_handler)(int, void *));
+void adis_cleanup_buffer_and_trigger(struct adis *adis,
+	struct iio_dev *indio_dev);
+
+int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev);
+void adis_remove_trigger(struct adis *adis);
+
+int adis_update_scan_mode(struct iio_dev *indio_dev,
+	const unsigned long *scan_mask);
+
+#else /* CONFIG_IIO_BUFFER */
+
+static inline int adis_setup_buffer_and_trigger(struct adis *adis,
+	struct iio_dev *indio_dev, irqreturn_t (*trigger_handler)(int, void *))
+{
+	return 0;
+}
+
+static inline void adis_cleanup_buffer_and_trigger(struct adis *adis,
+	struct iio_dev *indio_dev)
+{
+}
+
+static inline int adis_probe_trigger(struct adis *adis,
+	struct iio_dev *indio_dev)
+{
+	return 0;
+}
+
+static inline void adis_remove_trigger(struct adis *adis)
+{
+}
+
+#define adis_update_scan_mode NULL
+
+#endif /* CONFIG_IIO_BUFFER */
+
+#ifdef CONFIG_DEBUG_FS
+
+int adis_debugfs_reg_access(struct iio_dev *indio_dev,
+	unsigned int reg, unsigned int writeval, unsigned int *readval);
+
+#else
+
+#define adis_debugfs_reg_access NULL
+
+#endif
+
+#endif
diff --git a/include/linux/iio/machine.h b/include/linux/iio/machine.h
index 809a3f0..1601a2a 100644
--- a/include/linux/iio/machine.h
+++ b/include/linux/iio/machine.h
@@ -19,11 +19,13 @@
  * @consumer_dev_name:	Name to uniquely identify the consumer device.
  * @consumer_channel:	Unique name used to identify the channel on the
  *			consumer side.
+ * @consumer_data:	Data about the channel for use by the consumer driver.
  */
 struct iio_map {
 	const char *adc_channel_label;
 	const char *consumer_dev_name;
 	const char *consumer_channel;
+	void *consumer_data;
 };
 
 #endif
diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h
index 5c647ec..88bf0f0 100644
--- a/include/linux/iio/types.h
+++ b/include/linux/iio/types.h
@@ -28,6 +28,7 @@ enum iio_chan_type {
 	IIO_CAPACITANCE,
 	IIO_ALTVOLTAGE,
 	IIO_CCT,
+	IIO_PRESSURE,
 };
 
 enum iio_modifier {
@@ -58,5 +59,6 @@ enum iio_modifier {
 #define IIO_VAL_INT_PLUS_NANO 3
 #define IIO_VAL_INT_PLUS_MICRO_DB 4
 #define IIO_VAL_FRACTIONAL 10
+#define IIO_VAL_FRACTIONAL_LOG2 11
 
 #endif /* _IIO_TYPES_H_ */
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 2c7223d..86c361e 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -18,6 +18,7 @@ extern int ima_bprm_check(struct linux_binprm *bprm);
 extern int ima_file_check(struct file *file, int mask);
 extern void ima_file_free(struct file *file);
 extern int ima_file_mmap(struct file *file, unsigned long prot);
+extern int ima_module_check(struct file *file);
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
@@ -40,6 +41,11 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot)
 	return 0;
 }
 
+static inline int ima_module_check(struct file *file)
+{
+	return 0;
+}
+
 #endif /* CONFIG_IMA_H */
 
 #ifdef CONFIG_IMA_APPRAISE
diff --git a/include/linux/init.h b/include/linux/init.h
index e59041e..1c2746f 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -186,16 +186,16 @@ extern bool initcall_debug;
  * can point at the same handler without causing duplicate-symbol build errors.
  */
 
-#define __define_initcall(level,fn,id) \
+#define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
-	__attribute__((__section__(".initcall" level ".init"))) = fn
+	__attribute__((__section__(".initcall" #id ".init"))) = fn
 
 /*
  * Early initcalls run before initializing SMP.
  *
  * Only for built-in code, not modules.
  */
-#define early_initcall(fn)		__define_initcall("early",fn,early)
+#define early_initcall(fn)		__define_initcall(fn, early)
 
 /*
  * A "pure" initcall has no dependencies on anything else, and purely
@@ -204,23 +204,23 @@ extern bool initcall_debug;
  * This only exists for built-in code, not for modules.
  * Keep main.c:initcall_level_names[] in sync.
  */
-#define pure_initcall(fn)		__define_initcall("0",fn,0)
-
-#define core_initcall(fn)		__define_initcall("1",fn,1)
-#define core_initcall_sync(fn)		__define_initcall("1s",fn,1s)
-#define postcore_initcall(fn)		__define_initcall("2",fn,2)
-#define postcore_initcall_sync(fn)	__define_initcall("2s",fn,2s)
-#define arch_initcall(fn)		__define_initcall("3",fn,3)
-#define arch_initcall_sync(fn)		__define_initcall("3s",fn,3s)
-#define subsys_initcall(fn)		__define_initcall("4",fn,4)
-#define subsys_initcall_sync(fn)	__define_initcall("4s",fn,4s)
-#define fs_initcall(fn)			__define_initcall("5",fn,5)
-#define fs_initcall_sync(fn)		__define_initcall("5s",fn,5s)
-#define rootfs_initcall(fn)		__define_initcall("rootfs",fn,rootfs)
-#define device_initcall(fn)		__define_initcall("6",fn,6)
-#define device_initcall_sync(fn)	__define_initcall("6s",fn,6s)
-#define late_initcall(fn)		__define_initcall("7",fn,7)
-#define late_initcall_sync(fn)		__define_initcall("7s",fn,7s)
+#define pure_initcall(fn)		__define_initcall(fn, 0)
+
+#define core_initcall(fn)		__define_initcall(fn, 1)
+#define core_initcall_sync(fn)		__define_initcall(fn, 1s)
+#define postcore_initcall(fn)		__define_initcall(fn, 2)
+#define postcore_initcall_sync(fn)	__define_initcall(fn, 2s)
+#define arch_initcall(fn)		__define_initcall(fn, 3)
+#define arch_initcall_sync(fn)		__define_initcall(fn, 3s)
+#define subsys_initcall(fn)		__define_initcall(fn, 4)
+#define subsys_initcall_sync(fn)	__define_initcall(fn, 4s)
+#define fs_initcall(fn)			__define_initcall(fn, 5)
+#define fs_initcall_sync(fn)		__define_initcall(fn, 5s)
+#define rootfs_initcall(fn)		__define_initcall(fn, rootfs)
+#define device_initcall(fn)		__define_initcall(fn, 6)
+#define device_initcall_sync(fn)	__define_initcall(fn, 6s)
+#define late_initcall(fn)		__define_initcall(fn, 7)
+#define late_initcall_sync(fn)		__define_initcall(fn, 7s)
 
 #define __initcall(fn) device_initcall(fn)
 
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 6d087c5..ed98982 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -143,6 +143,13 @@ extern struct task_group root_task_group;
 
 #define INIT_TASK_COMM "swapper"
 
+#ifdef CONFIG_NUMA_BALANCING
+# define INIT_TASK_NUMA(tsk)						\
+	.numa_shared = -1,
+#else
+# define INIT_TASK_NUMA(tsk)
+#endif
+
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -210,6 +217,7 @@ extern struct task_group root_task_group;
 	INIT_TRACE_RECURSION						\
 	INIT_TASK_RCU_PREEMPT(tsk)					\
 	INIT_CPUSET_SEQ							\
+	INIT_TASK_NUMA(tsk)						\
 }
 
 
diff --git a/include/linux/input.h b/include/linux/input.h
index cab994b..82ce323 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -112,6 +112,11 @@ struct input_value {
  * @h_list: list of input handles associated with the device. When
  *	accessing the list dev->mutex must be held
  * @node: used to place the device onto input_dev_list
+ * @num_vals: number of values queued in the current frame
+ * @max_vals: maximum number of values queued in a frame
+ * @vals: array of values queued in the current frame
+ * @devres_managed: indicates that devices is managed with devres framework
+ *	and needs not be explicitly unregistered or freed.
  */
 struct input_dev {
 	const char *name;
@@ -180,6 +185,8 @@ struct input_dev {
 	unsigned int num_vals;
 	unsigned int max_vals;
 	struct input_value *vals;
+
+	bool devres_managed;
 };
 #define to_input_dev(d) container_of(d, struct input_dev, dev)
 
@@ -323,7 +330,8 @@ struct input_handle {
 	struct list_head	h_node;
 };
 
-struct input_dev *input_allocate_device(void);
+struct input_dev __must_check *input_allocate_device(void);
+struct input_dev __must_check *devm_input_allocate_device(struct device *);
 void input_free_device(struct input_dev *dev);
 
 static inline struct input_dev *input_get_device(struct input_dev *dev)
diff --git a/include/linux/input/bu21013.h b/include/linux/input/bu21013.h
index 05e0328..6230d76 100644
--- a/include/linux/input/bu21013.h
+++ b/include/linux/input/bu21013.h
@@ -9,13 +9,10 @@
 
 /**
  * struct bu21013_platform_device - Handle the platform data
- * @cs_en:	pointer to the cs enable function
- * @cs_dis:	pointer to the cs disable function
- * @irq_read_val:    pointer to read the pen irq value function
  * @touch_x_max: touch x max
  * @touch_y_max: touch y max
  * @cs_pin: chip select pin
- * @irq: irq pin
+ * @touch_pin: touch gpio pin
  * @ext_clk: external clock flag
  * @x_flip: x flip flag
  * @y_flip: y flip flag
@@ -24,13 +21,10 @@
  * This is used to handle the platform data
  */
 struct bu21013_platform_device {
-	int (*cs_en)(int reset_pin);
-	int (*cs_dis)(int reset_pin);
-	int (*irq_read_val)(void);
 	int touch_x_max;
 	int touch_y_max;
 	unsigned int cs_pin;
-	unsigned int irq;
+	unsigned int touch_pin;
 	bool ext_clk;
 	bool x_flip;
 	bool y_flip;
diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h
index cc5cca7..2e86bd0 100644
--- a/include/linux/input/mt.h
+++ b/include/linux/input/mt.h
@@ -69,6 +69,12 @@ static inline bool input_mt_is_active(const struct input_mt_slot *slot)
 	return input_mt_get_value(slot, ABS_MT_TRACKING_ID) >= 0;
 }
 
+static inline bool input_mt_is_used(const struct input_mt *mt,
+				    const struct input_mt_slot *slot)
+{
+	return slot->frame == mt->frame;
+}
+
 int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
 			unsigned int flags);
 void input_mt_destroy_slots(struct input_dev *dev);
diff --git a/include/linux/input/ti_am335x_tsc.h b/include/linux/input/ti_am335x_tsc.h
new file mode 100644
index 0000000..49269a2
--- /dev/null
+++ b/include/linux/input/ti_am335x_tsc.h
@@ -0,0 +1,23 @@
+#ifndef __LINUX_TI_AM335X_TSC_H
+#define __LINUX_TI_AM335X_TSC_H
+
+/**
+ * struct tsc_data	Touchscreen wire configuration
+ * @wires:		Wires refer to application modes
+ *			i.e. 4/5/8 wire touchscreen support
+ *			on the platform.
+ * @x_plate_resistance:	X plate resistance.
+ * @steps_to_configure:	The sequencer supports a total of
+ *			16 programmable steps.
+ *			A step configured to read a single
+ *			co-ordinate value, can be applied
+ *			more number of times for better results.
+ */
+
+struct tsc_data {
+	int wires;
+	int x_plate_resistance;
+	int steps_to_configure;
+};
+
+#endif
diff --git a/include/linux/input/ti_tscadc.h b/include/linux/input/ti_tscadc.h
deleted file mode 100644
index b10a527..0000000
--- a/include/linux/input/ti_tscadc.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __LINUX_TI_TSCADC_H
-#define __LINUX_TI_TSCADC_H
-
-/**
- * struct tsc_data	Touchscreen wire configuration
- * @wires:		Wires refer to application modes
- *			i.e. 4/5/8 wire touchscreen support
- *			on the platform.
- * @x_plate_resistance:	X plate resistance.
- */
-
-struct tsc_data {
-	int wires;
-	int x_plate_resistance;
-};
-
-#endif
diff --git a/include/linux/ipack.h b/include/linux/ipack.h
new file mode 100644
index 0000000..fea12cb
--- /dev/null
+++ b/include/linux/ipack.h
@@ -0,0 +1,245 @@
+/*
+ * Industry-pack bus.
+ *
+ * Copyright (C) 2011-2012 CERN (www.cern.ch)
+ * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
+ *
+ * This program is free software; 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/mod_devicetable.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+
+#define IPACK_IDPROM_OFFSET_I			0x01
+#define IPACK_IDPROM_OFFSET_P			0x03
+#define IPACK_IDPROM_OFFSET_A			0x05
+#define IPACK_IDPROM_OFFSET_C			0x07
+#define IPACK_IDPROM_OFFSET_MANUFACTURER_ID	0x09
+#define IPACK_IDPROM_OFFSET_MODEL		0x0B
+#define IPACK_IDPROM_OFFSET_REVISION		0x0D
+#define IPACK_IDPROM_OFFSET_RESERVED		0x0F
+#define IPACK_IDPROM_OFFSET_DRIVER_ID_L		0x11
+#define IPACK_IDPROM_OFFSET_DRIVER_ID_H		0x13
+#define IPACK_IDPROM_OFFSET_NUM_BYTES		0x15
+#define IPACK_IDPROM_OFFSET_CRC			0x17
+
+/*
+ * IndustryPack Fromat, Vendor and Device IDs.
+ */
+
+/* ID section format versions */
+#define IPACK_ID_VERSION_INVALID	0x00
+#define IPACK_ID_VERSION_1		0x01
+#define IPACK_ID_VERSION_2		0x02
+
+/* Vendors and devices. Sort key: vendor first, device next. */
+#define IPACK1_VENDOR_ID_RESERVED1	0x00
+#define IPACK1_VENDOR_ID_RESERVED2	0xFF
+#define IPACK1_VENDOR_ID_UNREGISTRED01	0x01
+#define IPACK1_VENDOR_ID_UNREGISTRED02	0x02
+#define IPACK1_VENDOR_ID_UNREGISTRED03	0x03
+#define IPACK1_VENDOR_ID_UNREGISTRED04	0x04
+#define IPACK1_VENDOR_ID_UNREGISTRED05	0x05
+#define IPACK1_VENDOR_ID_UNREGISTRED06	0x06
+#define IPACK1_VENDOR_ID_UNREGISTRED07	0x07
+#define IPACK1_VENDOR_ID_UNREGISTRED08	0x08
+#define IPACK1_VENDOR_ID_UNREGISTRED09	0x09
+#define IPACK1_VENDOR_ID_UNREGISTRED10	0x0A
+#define IPACK1_VENDOR_ID_UNREGISTRED11	0x0B
+#define IPACK1_VENDOR_ID_UNREGISTRED12	0x0C
+#define IPACK1_VENDOR_ID_UNREGISTRED13	0x0D
+#define IPACK1_VENDOR_ID_UNREGISTRED14	0x0E
+#define IPACK1_VENDOR_ID_UNREGISTRED15	0x0F
+
+#define IPACK1_VENDOR_ID_SBS            0xF0
+#define IPACK1_DEVICE_ID_SBS_OCTAL_232  0x22
+#define IPACK1_DEVICE_ID_SBS_OCTAL_422  0x2A
+#define IPACK1_DEVICE_ID_SBS_OCTAL_485  0x48
+
+struct ipack_bus_ops;
+struct ipack_driver;
+
+enum ipack_space {
+	IPACK_IO_SPACE    = 0,
+	IPACK_ID_SPACE,
+	IPACK_INT_SPACE,
+	IPACK_MEM8_SPACE,
+	IPACK_MEM16_SPACE,
+	/* Dummy for counting the number of entries.  Must remain the last
+	 * entry */
+	IPACK_SPACE_COUNT,
+};
+
+/**
+ */
+struct ipack_region {
+	phys_addr_t start;
+	size_t      size;
+};
+
+/**
+ *	struct ipack_device
+ *
+ *	@slot: Slot where the device is plugged in the carrier board
+ *	@bus: ipack_bus_device where the device is plugged to.
+ *	@id_space: Virtual address to ID space.
+ *	@io_space: Virtual address to IO space.
+ *	@mem_space: Virtual address to MEM space.
+ *	@dev: device in kernel representation.
+ *
+ * Warning: Direct access to mapped memory is possible but the endianness
+ * is not the same with PCI carrier or VME carrier. The endianness is managed
+ * by the carrier board throught bus->ops.
+ */
+struct ipack_device {
+	unsigned int slot;
+	struct ipack_bus_device *bus;
+	struct device dev;
+	void (*release) (struct ipack_device *dev);
+	struct ipack_region      region[IPACK_SPACE_COUNT];
+	u8                      *id;
+	size_t			 id_avail;
+	u32			 id_vendor;
+	u32			 id_device;
+	u8			 id_format;
+	unsigned int		 id_crc_correct:1;
+	unsigned int		 speed_8mhz:1;
+	unsigned int		 speed_32mhz:1;
+};
+
+/**
+ * struct ipack_driver_ops -- Callbacks to IPack device driver
+ *
+ * @probe:  Probe function
+ * @remove: Prepare imminent removal of the device.  Services provided by the
+ *          device should be revoked.
+ */
+
+struct ipack_driver_ops {
+	int (*probe) (struct ipack_device *dev);
+	void (*remove) (struct ipack_device *dev);
+};
+
+/**
+ * struct ipack_driver -- Specific data to each ipack device driver
+ *
+ * @driver: Device driver kernel representation
+ * @ops:    Callbacks provided by the IPack device driver
+ */
+struct ipack_driver {
+	struct device_driver driver;
+	const struct ipack_device_id *id_table;
+	const struct ipack_driver_ops *ops;
+};
+
+/**
+ *	struct ipack_bus_ops - available operations on a bridge module
+ *
+ *	@map_space: map IP address space
+ *	@unmap_space: unmap IP address space
+ *	@request_irq: request IRQ
+ *	@free_irq: free IRQ
+ *	@get_clockrate: Returns the clockrate the carrier is currently
+ *		communicating with the device at.
+ *	@set_clockrate: Sets the clock-rate for carrier / module communication.
+ *		Should return -EINVAL if the requested speed is not supported.
+ *	@get_error: Returns the error state for the slot the device is attached
+ *		to.
+ *	@get_timeout: Returns 1 if the communication with the device has
+ *		previously timed out.
+ *	@reset_timeout: Resets the state returned by get_timeout.
+ */
+struct ipack_bus_ops {
+	int (*request_irq) (struct ipack_device *dev,
+			    irqreturn_t (*handler)(void *), void *arg);
+	int (*free_irq) (struct ipack_device *dev);
+	int (*get_clockrate) (struct ipack_device *dev);
+	int (*set_clockrate) (struct ipack_device *dev, int mherz);
+	int (*get_error) (struct ipack_device *dev);
+	int (*get_timeout) (struct ipack_device *dev);
+	int (*reset_timeout) (struct ipack_device *dev);
+};
+
+/**
+ *	struct ipack_bus_device
+ *
+ *	@dev: pointer to carrier device
+ *	@slots: number of slots available
+ *	@bus_nr: ipack bus number
+ *	@ops: bus operations for the mezzanine drivers
+ */
+struct ipack_bus_device {
+	struct device *parent;
+	int slots;
+	int bus_nr;
+	const struct ipack_bus_ops *ops;
+};
+
+/**
+ *	ipack_bus_register -- register a new ipack bus
+ *
+ * @parent: pointer to the parent device, if any.
+ * @slots: number of slots available in the bus device.
+ * @ops: bus operations for the mezzanine drivers.
+ *
+ * The carrier board device should call this function to register itself as
+ * available bus device in ipack.
+ */
+struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots,
+					    const struct ipack_bus_ops *ops);
+
+/**
+ *	ipack_bus_unregister -- unregister an ipack bus
+ */
+int ipack_bus_unregister(struct ipack_bus_device *bus);
+
+/**
+ * ipack_driver_register -- Register a new ipack device driver
+ *
+ * Called by a ipack driver to register itself as a driver
+ * that can manage ipack devices.
+ */
+int ipack_driver_register(struct ipack_driver *edrv, struct module *owner,
+			  const char *name);
+void ipack_driver_unregister(struct ipack_driver *edrv);
+
+/**
+ *	ipack_device_register -- register an IPack device with the kernel
+ *	@dev: the new device to register.
+ *
+ *	Register a new IPack device ("module" in IndustryPack jargon). The call
+ *	is done by the carrier driver.  The carrier should populate the fields
+ *	bus and slot as well as the region array of @dev prior to calling this
+ *	function.  The rest of the fields will be allocated and populated
+ *	during registration.
+ *
+ *	Return zero on success or error code on failure.
+ */
+int ipack_device_register(struct ipack_device *dev);
+void ipack_device_unregister(struct ipack_device *dev);
+
+/**
+ * DEFINE_IPACK_DEVICE_TABLE - macro used to describe a IndustryPack table
+ * @_table: device table name
+ *
+ * This macro is used to create a struct ipack_device_id array (a device table)
+ * in a generic manner.
+ */
+#define DEFINE_IPACK_DEVICE_TABLE(_table) \
+	const struct ipack_device_id _table[]
+/**
+ * IPACK_DEVICE - macro used to describe a specific IndustryPack device
+ * @_format: the format version (currently either 1 or 2, 8 bit value)
+ * @vend:    the 8 or 24 bit IndustryPack Vendor ID
+ * @dev:     the 8 or 16  bit IndustryPack Device ID
+ *
+ * This macro is used to create a struct ipack_device_id that matches a specific
+ * device.
+ */
+#define IPACK_DEVICE(_format, vend, dev) \
+	 .format = (_format), \
+	 .vendor = (vend), \
+	 .device = (dev)
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index 5499c92..ae221a7 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -24,6 +24,7 @@ struct ipc_ids {
 	unsigned short seq_max;
 	struct rw_semaphore rw_mutex;
 	struct idr ipcs_idr;
+	int next_id;
 };
 
 struct ipc_namespace {
@@ -67,6 +68,8 @@ struct ipc_namespace {
 
 	/* user_ns which owns the ipc ns */
 	struct user_namespace *user_ns;
+
+	unsigned int	proc_inum;
 };
 
 extern struct ipc_namespace init_ipc_ns;
@@ -133,7 +136,8 @@ static inline int mq_init_ns(struct ipc_namespace *ns) { return 0; }
 
 #if defined(CONFIG_IPC_NS)
 extern struct ipc_namespace *copy_ipcs(unsigned long flags,
-				       struct task_struct *tsk);
+	struct user_namespace *user_ns, struct ipc_namespace *ns);
+
 static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
 {
 	if (ns)
@@ -144,12 +148,12 @@ static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
 extern void put_ipc_ns(struct ipc_namespace *ns);
 #else
 static inline struct ipc_namespace *copy_ipcs(unsigned long flags,
-					      struct task_struct *tsk)
+	struct user_namespace *user_ns, struct ipc_namespace *ns)
 {
 	if (flags & CLONE_NEWIPC)
 		return ERR_PTR(-EINVAL);
 
-	return tsk->nsproxy->ipc_ns;
+	return ns;
 }
 
 static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns)
diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
index fcb5d44..8ea3fe0 100644
--- a/include/linux/ipmi_smi.h
+++ b/include/linux/ipmi_smi.h
@@ -216,7 +216,7 @@ int ipmi_unregister_smi(ipmi_smi_t intf);
 
 /*
  * The lower layer reports received messages through this interface.
- * The data_size should be zero if this is an asyncronous message.  If
+ * The data_size should be zero if this is an asynchronous message.  If
  * the lower layer gets an error sending a message, it should format
  * an error response in the message response.
  */
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index bcba48a..5e11905 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -47,6 +47,7 @@ struct ipv6_devconf {
 	__s32		disable_ipv6;
 	__s32		accept_dad;
 	__s32		force_tllao;
+	__s32           ndisc_notify;
 	void		*sysctl;
 };
 
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 216b0ba..526f10a 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -392,6 +392,15 @@ static inline void irq_move_masked_irq(struct irq_data *data) { }
 
 extern int no_irq_affinity;
 
+#ifdef CONFIG_HARDIRQS_SW_RESEND
+int irq_set_parent(int irq, int parent_irq);
+#else
+static inline int irq_set_parent(int irq, int parent_irq)
+{
+	return 0;
+}
+#endif
+
 /*
  * Built-in IRQ handlers for various IRQ types,
  * callable via desc->handle_irq()
diff --git a/include/linux/irqchip/spear-shirq.h b/include/linux/irqchip/spear-shirq.h
new file mode 100644
index 0000000..c8be16d
--- /dev/null
+++ b/include/linux/irqchip/spear-shirq.h
@@ -0,0 +1,64 @@
+/*
+ * SPEAr platform shared irq layer header file
+ *
+ * Copyright (C) 2009-2012 ST Microelectronics
+ * Viresh Kumar <viresh.linux@gmail.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 __SPEAR_SHIRQ_H
+#define __SPEAR_SHIRQ_H
+
+#include <linux/irq.h>
+#include <linux/types.h>
+
+/*
+ * struct shirq_regs: shared irq register configuration
+ *
+ * enb_reg: enable register offset
+ * reset_to_enb: val 1 indicates, we need to clear bit for enabling interrupt
+ * status_reg: status register offset
+ * status_reg_mask: status register valid mask
+ * clear_reg: clear register offset
+ * reset_to_clear: val 1 indicates, we need to clear bit for clearing interrupt
+ */
+struct shirq_regs {
+	u32 enb_reg;
+	u32 reset_to_enb;
+	u32 status_reg;
+	u32 clear_reg;
+	u32 reset_to_clear;
+};
+
+/*
+ * struct spear_shirq: shared irq structure
+ *
+ * irq: hardware irq number
+ * irq_base: base irq in linux domain
+ * irq_nr: no. of shared interrupts in a particular block
+ * irq_bit_off: starting bit offset in the status register
+ * invalid_irq: irq group is currently disabled
+ * base: base address of shared irq register
+ * regs: register configuration for shared irq block
+ */
+struct spear_shirq {
+	u32 irq;
+	u32 irq_base;
+	u32 irq_nr;
+	u32 irq_bit_off;
+	int invalid_irq;
+	void __iomem *base;
+	struct shirq_regs regs;
+};
+
+int __init spear300_shirq_of_init(struct device_node *np,
+		struct device_node *parent);
+int __init spear310_shirq_of_init(struct device_node *np,
+		struct device_node *parent);
+int __init spear320_shirq_of_init(struct device_node *np,
+		struct device_node *parent);
+
+#endif /* __SPEAR_SHIRQ_H */
diff --git a/include/linux/irqchip/sunxi.h b/include/linux/irqchip/sunxi.h
new file mode 100644
index 0000000..1fe2c22
--- /dev/null
+++ b/include/linux/irqchip/sunxi.h
@@ -0,0 +1,27 @@
+/*
+ * 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_IRQCHIP_SUNXI_H
+#define __LINUX_IRQCHIP_SUNXI_H
+
+#include <asm/exception.h>
+
+extern void sunxi_init_irq(void);
+
+extern asmlinkage void __exception_irq_entry sunxi_handle_irq(
+	struct pt_regs *regs);
+
+#endif
diff --git a/include/linux/irqchip/versatile-fpga.h b/include/linux/irqchip/versatile-fpga.h
new file mode 100644
index 0000000..1fac965
--- /dev/null
+++ b/include/linux/irqchip/versatile-fpga.h
@@ -0,0 +1,13 @@
+#ifndef PLAT_FPGA_IRQ_H
+#define PLAT_FPGA_IRQ_H
+
+struct device_node;
+struct pt_regs;
+
+void fpga_handle_irq(struct pt_regs *regs);
+void fpga_irq_init(void __iomem *, const char *, int, int, u32,
+		struct device_node *node);
+int fpga_irq_of_init(struct device_node *node,
+		     struct device_node *parent);
+
+#endif
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
index 0ba014c..623325e 100644
--- a/include/linux/irqdesc.h
+++ b/include/linux/irqdesc.h
@@ -11,6 +11,8 @@
 struct irq_affinity_notify;
 struct proc_dir_entry;
 struct module;
+struct irq_desc;
+
 /**
  * struct irq_desc - interrupt descriptor
  * @irq_data:		per irq and chip data passed down to chip functions
@@ -65,6 +67,7 @@ struct irq_desc {
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry	*dir;
 #endif
+	int			parent_irq;
 	struct module		*owner;
 	const char		*name;
 } ____cacheline_internodealigned_in_smp;
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 3efc43f..1be23d9 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -1096,7 +1096,6 @@ extern int	 jbd2_journal_get_undo_access(handle_t *, struct buffer_head *);
 void		 jbd2_journal_set_triggers(struct buffer_head *,
 					   struct jbd2_buffer_trigger_type *type);
 extern int	 jbd2_journal_dirty_metadata (handle_t *, struct buffer_head *);
-extern void	 jbd2_journal_release_buffer (handle_t *, struct buffer_head *);
 extern int	 jbd2_journal_forget (handle_t *, struct buffer_head *);
 extern void	 journal_sync_buffer (struct buffer_head *);
 extern void	 jbd2_journal_invalidatepage(journal_t *,
@@ -1303,15 +1302,21 @@ static inline int jbd_space_needed(journal_t *journal)
 
 extern int jbd_blocks_per_page(struct inode *inode);
 
+/* JBD uses a CRC32 checksum */
+#define JBD_MAX_CHECKSUM_SIZE 4
+
 static inline u32 jbd2_chksum(journal_t *journal, u32 crc,
 			      const void *address, unsigned int length)
 {
 	struct {
 		struct shash_desc shash;
-		char ctx[crypto_shash_descsize(journal->j_chksum_driver)];
+		char ctx[JBD_MAX_CHECKSUM_SIZE];
 	} desc;
 	int err;
 
+	BUG_ON(crypto_shash_descsize(journal->j_chksum_driver) >
+		JBD_MAX_CHECKSUM_SIZE);
+
 	desc.shash.tfm = journal->j_chksum_driver;
 	desc.shash.flags = 0;
 	*(u32 *)desc.ctx = crc;
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index a123b13..9a6bccb 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -220,6 +220,23 @@ int __must_check _kstrtol(const char *s, unsigned int base, long *res);
 
 int __must_check kstrtoull(const char *s, unsigned int base, unsigned long long *res);
 int __must_check kstrtoll(const char *s, unsigned int base, long long *res);
+
+/**
+ * kstrtoul - convert a string to an unsigned long
+ * @s: The start of the string. The string must be null-terminated, and may also
+ *  include a single newline before its terminating null. The first character
+ *  may also be a plus sign, but not a minus sign.
+ * @base: The number base to use. The maximum supported base is 16. If base is
+ *  given as 0, then the base of the string is automatically detected with the
+ *  conventional semantics - If it begins with 0x the number will be parsed as a
+ *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
+ *  parsed as an octal number. Otherwise it will be parsed as a decimal.
+ * @res: Where to write the result of the conversion on success.
+ *
+ * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
+ * Used as a replacement for the obsolete simple_strtoull. Return code must
+ * be checked.
+*/
 static inline int __must_check kstrtoul(const char *s, unsigned int base, unsigned long *res)
 {
 	/*
@@ -233,6 +250,22 @@ static inline int __must_check kstrtoul(const char *s, unsigned int base, unsign
 		return _kstrtoul(s, base, res);
 }
 
+/**
+ * kstrtol - convert a string to a long
+ * @s: The start of the string. The string must be null-terminated, and may also
+ *  include a single newline before its terminating null. The first character
+ *  may also be a plus sign or a minus sign.
+ * @base: The number base to use. The maximum supported base is 16. If base is
+ *  given as 0, then the base of the string is automatically detected with the
+ *  conventional semantics - If it begins with 0x the number will be parsed as a
+ *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
+ *  parsed as an octal number. Otherwise it will be parsed as a decimal.
+ * @res: Where to write the result of the conversion on success.
+ *
+ * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
+ * Used as a replacement for the obsolete simple_strtoull. Return code must
+ * be checked.
+ */
 static inline int __must_check kstrtol(const char *s, unsigned int base, long *res)
 {
 	/*
@@ -527,9 +560,6 @@ __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap);
 
 extern void ftrace_dump(enum ftrace_dump_mode oops_dump_mode);
 #else
-static inline __printf(1, 2)
-int trace_printk(const char *fmt, ...);
-
 static inline void tracing_start(void) { }
 static inline void tracing_stop(void) { }
 static inline void ftrace_off_permanent(void) { }
@@ -539,8 +569,8 @@ static inline void tracing_on(void) { }
 static inline void tracing_off(void) { }
 static inline int tracing_is_on(void) { return 0; }
 
-static inline int
-trace_printk(const char *fmt, ...)
+static inline __printf(1, 2)
+int trace_printk(const char *fmt, ...)
 {
 	return 0;
 }
@@ -687,20 +717,6 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
 /* Trap pasters of __FUNCTION__ at compile-time */
 #define __FUNCTION__ (__func__)
 
-/* This helps us to avoid #ifdef CONFIG_NUMA */
-#ifdef CONFIG_NUMA
-#define NUMA_BUILD 1
-#else
-#define NUMA_BUILD 0
-#endif
-
-/* This helps us avoid #ifdef CONFIG_COMPACTION */
-#ifdef CONFIG_COMPACTION
-#define COMPACTION_BUILD 1
-#else
-#define COMPACTION_BUILD 0
-#endif
-
 /* Rebuild everything on CONFIG_FTRACE_MCOUNT_RECORD */
 #ifdef CONFIG_FTRACE_MCOUNT_RECORD
 # define REBUILD_DUE_TO_FTRACE_MCOUNT_RECORD
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
index 36d12f0..1865b1f 100644
--- a/include/linux/kernel_stat.h
+++ b/include/linux/kernel_stat.h
@@ -7,6 +7,7 @@
 #include <linux/cpumask.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
+#include <linux/vtime.h>
 #include <asm/irq.h>
 #include <asm/cputime.h>
 
@@ -130,12 +131,4 @@ extern void account_process_tick(struct task_struct *, int user);
 extern void account_steal_ticks(unsigned long ticks);
 extern void account_idle_ticks(unsigned long ticks);
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-extern void vtime_task_switch(struct task_struct *prev);
-extern void vtime_account_system(struct task_struct *tsk);
-extern void vtime_account_idle(struct task_struct *tsk);
-#else
-static inline void vtime_task_switch(struct task_struct *prev) { }
-#endif
-
 #endif /* _LINUX_KERNEL_STAT_H */
diff --git a/include/linux/key.h b/include/linux/key.h
index 2393b1c..4dfde11 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -265,6 +265,7 @@ extern int key_unlink(struct key *keyring,
 
 extern struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid,
 				 const struct cred *cred,
+				 key_perm_t perm,
 				 unsigned long flags,
 				 struct key *dest);
 
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 1e57449..939b112 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -203,7 +203,6 @@ extern struct kobject *power_kobj;
 /* The global /sys/firmware/ kobject for people to chain off of */
 extern struct kobject *firmware_kobj;
 
-#if defined(CONFIG_HOTPLUG)
 int kobject_uevent(struct kobject *kobj, enum kobject_action action);
 int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
 			char *envp[]);
@@ -213,22 +212,5 @@ int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...);
 
 int kobject_action_type(const char *buf, size_t count,
 			enum kobject_action *type);
-#else
-static inline int kobject_uevent(struct kobject *kobj,
-				 enum kobject_action action)
-{ return 0; }
-static inline int kobject_uevent_env(struct kobject *kobj,
-				      enum kobject_action action,
-				      char *envp[])
-{ return 0; }
-
-static inline __printf(2, 3)
-int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
-{ return -ENOMEM; }
-
-static inline int kobject_action_type(const char *buf, size_t count,
-				      enum kobject_action *type)
-{ return -EINVAL; }
-#endif
 
 #endif /* _KOBJECT_H_ */
diff --git a/include/linux/kref.h b/include/linux/kref.h
index 65af688..4972e6e 100644
--- a/include/linux/kref.h
+++ b/include/linux/kref.h
@@ -111,4 +111,25 @@ static inline int kref_put_mutex(struct kref *kref,
 	}
 	return 0;
 }
+
+/**
+ * kref_get_unless_zero - Increment refcount for object unless it is zero.
+ * @kref: object.
+ *
+ * Return non-zero if the increment succeeded. Otherwise return 0.
+ *
+ * This function is intended to simplify locking around refcounting for
+ * objects that can be looked up from a lookup structure, and which are
+ * removed from that lookup structure in the object destructor.
+ * Operations on such objects require at least a read lock around
+ * lookup + kref_get, and a write lock around kref_put + remove from lookup
+ * structure. Furthermore, RCU implementations become extremely tricky.
+ * With a lookup followed by a kref_get_unless_zero *with return value check*
+ * locking in the kref_put path can be deferred to the actual removal from
+ * the lookup structure and RCU lookups become trivial.
+ */
+static inline int __must_check kref_get_unless_zero(struct kref *kref)
+{
+	return atomic_add_unless(&kref->refcount, 1, 0);
+}
 #endif /* _KREF_H_ */
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index 06177ba10..e83512f 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -282,6 +282,25 @@ static inline int ktime_equal(const ktime_t cmp1, const ktime_t cmp2)
 	return cmp1.tv64 == cmp2.tv64;
 }
 
+/**
+ * ktime_compare - Compares two ktime_t variables for less, greater or equal
+ * @cmp1:	comparable1
+ * @cmp2:	comparable2
+ *
+ * Returns ...
+ *   cmp1  < cmp2: return <0
+ *   cmp1 == cmp2: return 0
+ *   cmp1  > cmp2: return >0
+ */
+static inline int ktime_compare(const ktime_t cmp1, const ktime_t cmp2)
+{
+	if (cmp1.tv64 < cmp2.tv64)
+		return -1;
+	if (cmp1.tv64 > cmp2.tv64)
+		return 1;
+	return 0;
+}
+
 static inline s64 ktime_to_us(const ktime_t kt)
 {
 	struct timeval tv = ktime_to_timeval(kt);
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index ecc5543..1d31645 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -47,28 +47,40 @@
 
 /*
  * For the normal pfn, the highest 12 bits should be zero,
- * so we can mask these bits to indicate the error.
+ * so we can mask bit 62 ~ bit 52  to indicate the error pfn,
+ * mask bit 63 to indicate the noslot pfn.
  */
-#define KVM_PFN_ERR_MASK	(0xfffULL << 52)
+#define KVM_PFN_ERR_MASK	(0x7ffULL << 52)
+#define KVM_PFN_ERR_NOSLOT_MASK	(0xfffULL << 52)
+#define KVM_PFN_NOSLOT		(0x1ULL << 63)
 
 #define KVM_PFN_ERR_FAULT	(KVM_PFN_ERR_MASK)
 #define KVM_PFN_ERR_HWPOISON	(KVM_PFN_ERR_MASK + 1)
-#define KVM_PFN_ERR_BAD		(KVM_PFN_ERR_MASK + 2)
-#define KVM_PFN_ERR_RO_FAULT	(KVM_PFN_ERR_MASK + 3)
+#define KVM_PFN_ERR_RO_FAULT	(KVM_PFN_ERR_MASK + 2)
 
+/*
+ * error pfns indicate that the gfn is in slot but faild to
+ * translate it to pfn on host.
+ */
 static inline bool is_error_pfn(pfn_t pfn)
 {
 	return !!(pfn & KVM_PFN_ERR_MASK);
 }
 
-static inline bool is_noslot_pfn(pfn_t pfn)
+/*
+ * error_noslot pfns indicate that the gfn can not be
+ * translated to pfn - it is not in slot or failed to
+ * translate it to pfn.
+ */
+static inline bool is_error_noslot_pfn(pfn_t pfn)
 {
-	return pfn == KVM_PFN_ERR_BAD;
+	return !!(pfn & KVM_PFN_ERR_NOSLOT_MASK);
 }
 
-static inline bool is_invalid_pfn(pfn_t pfn)
+/* noslot pfn indicates that the gfn is not in slot. */
+static inline bool is_noslot_pfn(pfn_t pfn)
 {
-	return !is_noslot_pfn(pfn) && is_error_pfn(pfn);
+	return pfn == KVM_PFN_NOSLOT;
 }
 
 #define KVM_HVA_ERR_BAD		(PAGE_OFFSET)
@@ -107,6 +119,7 @@ static inline bool is_error_page(struct page *page)
 #define KVM_REQ_IMMEDIATE_EXIT    15
 #define KVM_REQ_PMU               16
 #define KVM_REQ_PMI               17
+#define KVM_REQ_WATCHDOG          18
 
 #define KVM_USERSPACE_IRQ_SOURCE_ID		0
 #define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID	1
@@ -571,7 +584,6 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id);
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu);
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu);
 
-int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu);
 int kvm_arch_hardware_enable(void *garbage);
 void kvm_arch_hardware_disable(void *garbage);
 int kvm_arch_hardware_setup(void);
@@ -726,7 +738,11 @@ static inline int kvm_deassign_device(struct kvm *kvm,
 static inline void kvm_guest_enter(void)
 {
 	BUG_ON(preemptible());
-	vtime_account(current);
+	/*
+	 * This is running in ioctl context so we can avoid
+	 * the call to vtime_account() with its unnecessary idle check.
+	 */
+	vtime_account_system(current);
 	current->flags |= PF_VCPU;
 	/* KVM does not hold any references to rcu protected data when it
 	 * switches CPU into a guest mode. In fact switching to a guest mode
@@ -740,7 +756,11 @@ static inline void kvm_guest_enter(void)
 
 static inline void kvm_guest_exit(void)
 {
-	vtime_account(current);
+	/*
+	 * This is running in ioctl context so we can avoid
+	 * the call to vtime_account() with its unnecessary idle check.
+	 */
+	vtime_account_system(current);
 	current->flags &= ~PF_VCPU;
 }
 
@@ -830,9 +850,9 @@ extern struct kvm_stats_debugfs_item debugfs_entries[];
 extern struct dentry *kvm_debugfs_dir;
 
 #if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
-static inline int mmu_notifier_retry(struct kvm_vcpu *vcpu, unsigned long mmu_seq)
+static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq)
 {
-	if (unlikely(vcpu->kvm->mmu_notifier_count))
+	if (unlikely(kvm->mmu_notifier_count))
 		return 1;
 	/*
 	 * Ensure the read of mmu_notifier_count happens before the read
@@ -845,7 +865,7 @@ static inline int mmu_notifier_retry(struct kvm_vcpu *vcpu, unsigned long mmu_se
 	 * can't rely on kvm->mmu_lock to keep things ordered.
 	 */
 	smp_rmb();
-	if (vcpu->kvm->mmu_notifier_seq != mmu_seq)
+	if (kvm->mmu_notifier_seq != mmu_seq)
 		return 1;
 	return 0;
 }
@@ -873,10 +893,20 @@ static inline void kvm_free_irq_routing(struct kvm *kvm) {}
 #ifdef CONFIG_HAVE_KVM_EVENTFD
 
 void kvm_eventfd_init(struct kvm *kvm);
+int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args);
+
+#ifdef CONFIG_HAVE_KVM_IRQCHIP
 int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args);
 void kvm_irqfd_release(struct kvm *kvm);
 void kvm_irq_routing_update(struct kvm *, struct kvm_irq_routing_table *);
-int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args);
+#else
+static inline int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args)
+{
+	return -EINVAL;
+}
+
+static inline void kvm_irqfd_release(struct kvm *kvm) {}
+#endif
 
 #else
 
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 6e53bb3..0d9b5ee 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -179,6 +179,23 @@ extern void led_trigger_blink_oneshot(struct led_trigger *trigger,
 				      unsigned long *delay_on,
 				      unsigned long *delay_off,
 				      int invert);
+/**
+ * led_trigger_rename_static - rename a trigger
+ * @name: the new trigger name
+ * @trig: the LED trigger to rename
+ *
+ * Change a LED trigger name by copying the string passed in
+ * name into current trigger name, which MUST be large
+ * enough for the new string.
+ *
+ * Note that name must NOT point to the same string used
+ * during LED registration, as that could lead to races.
+ *
+ * This is meant to be used on triggers with statically
+ * allocated name.
+ */
+extern void led_trigger_rename_static(const char *name,
+				      struct led_trigger *trig);
 
 #else
 
diff --git a/include/linux/loop.h b/include/linux/loop.h
index 6492181..460b60f 100644
--- a/include/linux/loop.h
+++ b/include/linux/loop.h
@@ -53,10 +53,13 @@ struct loop_device {
 
 	spinlock_t		lo_lock;
 	struct bio_list		lo_bio_list;
+	unsigned int		lo_bio_count;
 	int			lo_state;
 	struct mutex		lo_ctl_mutex;
 	struct task_struct	*lo_thread;
 	wait_queue_head_t	lo_event;
+	/* wait queue for incoming requests */
+	wait_queue_head_t	lo_req_wait;
 
 	struct request_queue	*lo_queue;
 	struct gendisk		*lo_disk;
diff --git a/include/linux/lru_cache.h b/include/linux/lru_cache.h
index 7a71ffa..4019013 100644
--- a/include/linux/lru_cache.h
+++ b/include/linux/lru_cache.h
@@ -52,8 +52,8 @@ We replicate IO (more or less synchronously) to local and remote disk.
 
 For crash recovery after replication node failure,
   we need to resync all regions that have been target of in-flight WRITE IO
-  (in use, or "hot", regions), as we don't know wether or not those WRITEs have
-  made it to stable storage.
+  (in use, or "hot", regions), as we don't know whether or not those WRITEs
+  have made it to stable storage.
 
   To avoid a "full resync", we need to persistently track these regions.
 
@@ -166,9 +166,11 @@ struct lc_element {
 	/* if we want to track a larger set of objects,
 	 * it needs to become arch independend u64 */
 	unsigned lc_number;
-
 	/* special label when on free list */
 #define LC_FREE (~0U)
+
+	/* for pending changes */
+	unsigned lc_new_number;
 };
 
 struct lru_cache {
@@ -176,6 +178,7 @@ struct lru_cache {
 	struct list_head lru;
 	struct list_head free;
 	struct list_head in_use;
+	struct list_head to_be_changed;
 
 	/* the pre-created kmem cache to allocate the objects from */
 	struct kmem_cache *lc_cache;
@@ -186,7 +189,7 @@ struct lru_cache {
 	size_t element_off;
 
 	/* number of elements (indices) */
-	unsigned int  nr_elements;
+	unsigned int nr_elements;
 	/* Arbitrary limit on maximum tracked objects. Practical limit is much
 	 * lower due to allocation failures, probably. For typical use cases,
 	 * nr_elements should be a few thousand at most.
@@ -194,18 +197,19 @@ struct lru_cache {
 	 * 8 high bits of .lc_index to be overloaded with flags in the future. */
 #define LC_MAX_ACTIVE	(1<<24)
 
+	/* allow to accumulate a few (index:label) changes,
+	 * but no more than max_pending_changes */
+	unsigned int max_pending_changes;
+	/* number of elements currently on to_be_changed list */
+	unsigned int pending_changes;
+
 	/* statistics */
-	unsigned used; /* number of lelements currently on in_use list */
-	unsigned long hits, misses, starving, dirty, changed;
+	unsigned used; /* number of elements currently on in_use list */
+	unsigned long hits, misses, starving, locked, changed;
 
 	/* see below: flag-bits for lru_cache */
 	unsigned long flags;
 
-	/* when changing the label of an index element */
-	unsigned int  new_number;
-
-	/* for paranoia when changing the label of an index element */
-	struct lc_element *changing_element;
 
 	void  *lc_private;
 	const char *name;
@@ -221,10 +225,15 @@ enum {
 	/* debugging aid, to catch concurrent access early.
 	 * user needs to guarantee exclusive access by proper locking! */
 	__LC_PARANOIA,
-	/* if we need to change the set, but currently there is a changing
-	 * transaction pending, we are "dirty", and must deferr further
-	 * changing requests */
+
+	/* annotate that the set is "dirty", possibly accumulating further
+	 * changes, until a transaction is finally triggered */
 	__LC_DIRTY,
+
+	/* Locked, no further changes allowed.
+	 * Also used to serialize changing transactions. */
+	__LC_LOCKED,
+
 	/* if we need to change the set, but currently there is no free nor
 	 * unused element available, we are "starving", and must not give out
 	 * further references, to guarantee that eventually some refcnt will
@@ -236,9 +245,11 @@ enum {
 };
 #define LC_PARANOIA (1<<__LC_PARANOIA)
 #define LC_DIRTY    (1<<__LC_DIRTY)
+#define LC_LOCKED   (1<<__LC_LOCKED)
 #define LC_STARVING (1<<__LC_STARVING)
 
 extern struct lru_cache *lc_create(const char *name, struct kmem_cache *cache,
+		unsigned max_pending_changes,
 		unsigned e_count, size_t e_size, size_t e_off);
 extern void lc_reset(struct lru_cache *lc);
 extern void lc_destroy(struct lru_cache *lc);
@@ -249,7 +260,7 @@ extern struct lc_element *lc_try_get(struct lru_cache *lc, unsigned int enr);
 extern struct lc_element *lc_find(struct lru_cache *lc, unsigned int enr);
 extern struct lc_element *lc_get(struct lru_cache *lc, unsigned int enr);
 extern unsigned int lc_put(struct lru_cache *lc, struct lc_element *e);
-extern void lc_changed(struct lru_cache *lc, struct lc_element *e);
+extern void lc_committed(struct lru_cache *lc);
 
 struct seq_file;
 extern size_t lc_seq_printf_stats(struct seq_file *seq, struct lru_cache *lc);
@@ -258,32 +269,40 @@ extern void lc_seq_dump_details(struct seq_file *seq, struct lru_cache *lc, char
 				void (*detail) (struct seq_file *, struct lc_element *));
 
 /**
- * lc_try_lock - can be used to stop lc_get() from changing the tracked set
+ * lc_try_lock_for_transaction - can be used to stop lc_get() from changing the tracked set
  * @lc: the lru cache to operate on
  *
- * Note that the reference counts and order on the active and lru lists may
- * still change.  Returns true if we acquired the lock.
+ * Allows (expects) the set to be "dirty".  Note that the reference counts and
+ * order on the active and lru lists may still change.  Used to serialize
+ * changing transactions.  Returns true if we aquired the lock.
  */
-static inline int lc_try_lock(struct lru_cache *lc)
+static inline int lc_try_lock_for_transaction(struct lru_cache *lc)
 {
-	return !test_and_set_bit(__LC_DIRTY, &lc->flags);
+	return !test_and_set_bit(__LC_LOCKED, &lc->flags);
 }
 
 /**
+ * lc_try_lock - variant to stop lc_get() from changing the tracked set
+ * @lc: the lru cache to operate on
+ *
+ * Note that the reference counts and order on the active and lru lists may
+ * still change.  Only works on a "clean" set.  Returns true if we aquired the
+ * lock, which means there are no pending changes, and any further attempt to
+ * change the set will not succeed until the next lc_unlock().
+ */
+extern int lc_try_lock(struct lru_cache *lc);
+
+/**
  * lc_unlock - unlock @lc, allow lc_get() to change the set again
  * @lc: the lru cache to operate on
  */
 static inline void lc_unlock(struct lru_cache *lc)
 {
 	clear_bit(__LC_DIRTY, &lc->flags);
-	smp_mb__after_clear_bit();
+	clear_bit_unlock(__LC_LOCKED, &lc->flags);
 }
 
-static inline int lc_is_used(struct lru_cache *lc, unsigned int enr)
-{
-	struct lc_element *e = lc_find(lc, enr);
-	return e && e->refcnt;
-}
+extern bool lc_is_used(struct lru_cache *lc, unsigned int enr);
 
 #define lc_entry(ptr, type, member) \
 	container_of(ptr, type, member)
diff --git a/include/linux/lzo.h b/include/linux/lzo.h
index d793497..a0848d9 100644
--- a/include/linux/lzo.h
+++ b/include/linux/lzo.h
@@ -4,28 +4,28 @@
  *  LZO Public Kernel Interface
  *  A mini subset of the LZO real-time data compression library
  *
- *  Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *  Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
  *
  *  The full LZO package can be found at:
  *  http://www.oberhumer.com/opensource/lzo/
  *
- *  Changed for kernel use by:
+ *  Changed for Linux kernel use by:
  *  Nitin Gupta <nitingupta910@gmail.com>
  *  Richard Purdie <rpurdie@openedhand.com>
  */
 
-#define LZO1X_MEM_COMPRESS	(16384 * sizeof(unsigned char *))
-#define LZO1X_1_MEM_COMPRESS	LZO1X_MEM_COMPRESS
+#define LZO1X_1_MEM_COMPRESS	(8192 * sizeof(unsigned short))
+#define LZO1X_MEM_COMPRESS	LZO1X_1_MEM_COMPRESS
 
 #define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3)
 
-/* This requires 'workmem' of size LZO1X_1_MEM_COMPRESS */
+/* This requires 'wrkmem' of size LZO1X_1_MEM_COMPRESS */
 int lzo1x_1_compress(const unsigned char *src, size_t src_len,
-			unsigned char *dst, size_t *dst_len, void *wrkmem);
+		     unsigned char *dst, size_t *dst_len, void *wrkmem);
 
 /* safe decompression with overrun testing */
 int lzo1x_decompress_safe(const unsigned char *src, size_t src_len,
-			unsigned char *dst, size_t *dst_len);
+			  unsigned char *dst, size_t *dst_len);
 
 /*
  * Return values (< 0 = Error)
@@ -40,5 +40,6 @@ int lzo1x_decompress_safe(const unsigned char *src, size_t src_len,
 #define LZO_E_EOF_NOT_FOUND		(-7)
 #define LZO_E_INPUT_NOT_CONSUMED	(-8)
 #define LZO_E_NOT_YET_IMPLEMENTED	(-9)
+#define LZO_E_INVALID_ARGUMENT		(-10)
 
 #endif
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 11ddc7f..095d2b4 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -21,11 +21,14 @@
 #define _LINUX_MEMCONTROL_H
 #include <linux/cgroup.h>
 #include <linux/vm_event_item.h>
+#include <linux/hardirq.h>
+#include <linux/jump_label.h>
 
 struct mem_cgroup;
 struct page_cgroup;
 struct page;
 struct mm_struct;
+struct kmem_cache;
 
 /* Stats that can be updated by kernel. */
 enum mem_cgroup_page_stat_item {
@@ -181,7 +184,14 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
 						gfp_t gfp_mask,
 						unsigned long *total_scanned);
 
-void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx);
+void __mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx);
+static inline void mem_cgroup_count_vm_event(struct mm_struct *mm,
+					     enum vm_event_item idx)
+{
+	if (mem_cgroup_disabled() || !mm)
+		return;
+	__mem_cgroup_count_vm_event(mm, idx);
+}
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 void mem_cgroup_split_huge_fixup(struct page *head);
 #endif
@@ -407,5 +417,211 @@ static inline void sock_release_memcg(struct sock *sk)
 {
 }
 #endif /* CONFIG_INET && CONFIG_MEMCG_KMEM */
+
+#ifdef CONFIG_MEMCG_KMEM
+extern struct static_key memcg_kmem_enabled_key;
+
+extern int memcg_limited_groups_array_size;
+
+/*
+ * Helper macro to loop through all memcg-specific caches. Callers must still
+ * check if the cache is valid (it is either valid or NULL).
+ * the slab_mutex must be held when looping through those caches
+ */
+#define for_each_memcg_cache_index(_idx)	\
+	for ((_idx) = 0; i < memcg_limited_groups_array_size; (_idx)++)
+
+static inline bool memcg_kmem_enabled(void)
+{
+	return static_key_false(&memcg_kmem_enabled_key);
+}
+
+/*
+ * In general, we'll do everything in our power to not incur in any overhead
+ * for non-memcg users for the kmem functions. Not even a function call, if we
+ * can avoid it.
+ *
+ * Therefore, we'll inline all those functions so that in the best case, we'll
+ * see that kmemcg is off for everybody and proceed quickly.  If it is on,
+ * we'll still do most of the flag checking inline. We check a lot of
+ * conditions, but because they are pretty simple, they are expected to be
+ * fast.
+ */
+bool __memcg_kmem_newpage_charge(gfp_t gfp, struct mem_cgroup **memcg,
+					int order);
+void __memcg_kmem_commit_charge(struct page *page,
+				       struct mem_cgroup *memcg, int order);
+void __memcg_kmem_uncharge_pages(struct page *page, int order);
+
+int memcg_cache_id(struct mem_cgroup *memcg);
+int memcg_register_cache(struct mem_cgroup *memcg, struct kmem_cache *s,
+			 struct kmem_cache *root_cache);
+void memcg_release_cache(struct kmem_cache *cachep);
+void memcg_cache_list_add(struct mem_cgroup *memcg, struct kmem_cache *cachep);
+
+int memcg_update_cache_size(struct kmem_cache *s, int num_groups);
+void memcg_update_array_size(int num_groups);
+
+struct kmem_cache *
+__memcg_kmem_get_cache(struct kmem_cache *cachep, gfp_t gfp);
+
+void mem_cgroup_destroy_cache(struct kmem_cache *cachep);
+void kmem_cache_destroy_memcg_children(struct kmem_cache *s);
+
+/**
+ * memcg_kmem_newpage_charge: verify if a new kmem allocation is allowed.
+ * @gfp: the gfp allocation flags.
+ * @memcg: a pointer to the memcg this was charged against.
+ * @order: allocation order.
+ *
+ * returns true if the memcg where the current task belongs can hold this
+ * allocation.
+ *
+ * We return true automatically if this allocation is not to be accounted to
+ * any memcg.
+ */
+static inline bool
+memcg_kmem_newpage_charge(gfp_t gfp, struct mem_cgroup **memcg, int order)
+{
+	if (!memcg_kmem_enabled())
+		return true;
+
+	/*
+	 * __GFP_NOFAIL allocations will move on even if charging is not
+	 * possible. Therefore we don't even try, and have this allocation
+	 * unaccounted. We could in theory charge it with
+	 * res_counter_charge_nofail, but we hope those allocations are rare,
+	 * and won't be worth the trouble.
+	 */
+	if (!(gfp & __GFP_KMEMCG) || (gfp & __GFP_NOFAIL))
+		return true;
+	if (in_interrupt() || (!current->mm) || (current->flags & PF_KTHREAD))
+		return true;
+
+	/* If the test is dying, just let it go. */
+	if (unlikely(fatal_signal_pending(current)))
+		return true;
+
+	return __memcg_kmem_newpage_charge(gfp, memcg, order);
+}
+
+/**
+ * memcg_kmem_uncharge_pages: uncharge pages from memcg
+ * @page: pointer to struct page being freed
+ * @order: allocation order.
+ *
+ * there is no need to specify memcg here, since it is embedded in page_cgroup
+ */
+static inline void
+memcg_kmem_uncharge_pages(struct page *page, int order)
+{
+	if (memcg_kmem_enabled())
+		__memcg_kmem_uncharge_pages(page, order);
+}
+
+/**
+ * memcg_kmem_commit_charge: embeds correct memcg in a page
+ * @page: pointer to struct page recently allocated
+ * @memcg: the memcg structure we charged against
+ * @order: allocation order.
+ *
+ * Needs to be called after memcg_kmem_newpage_charge, regardless of success or
+ * failure of the allocation. if @page is NULL, this function will revert the
+ * charges. Otherwise, it will commit the memcg given by @memcg to the
+ * corresponding page_cgroup.
+ */
+static inline void
+memcg_kmem_commit_charge(struct page *page, struct mem_cgroup *memcg, int order)
+{
+	if (memcg_kmem_enabled() && memcg)
+		__memcg_kmem_commit_charge(page, memcg, order);
+}
+
+/**
+ * memcg_kmem_get_cache: selects the correct per-memcg cache for allocation
+ * @cachep: the original global kmem cache
+ * @gfp: allocation flags.
+ *
+ * This function assumes that the task allocating, which determines the memcg
+ * in the page allocator, belongs to the same cgroup throughout the whole
+ * process.  Misacounting can happen if the task calls memcg_kmem_get_cache()
+ * while belonging to a cgroup, and later on changes. This is considered
+ * acceptable, and should only happen upon task migration.
+ *
+ * Before the cache is created by the memcg core, there is also a possible
+ * imbalance: the task belongs to a memcg, but the cache being allocated from
+ * is the global cache, since the child cache is not yet guaranteed to be
+ * ready. This case is also fine, since in this case the GFP_KMEMCG will not be
+ * passed and the page allocator will not attempt any cgroup accounting.
+ */
+static __always_inline struct kmem_cache *
+memcg_kmem_get_cache(struct kmem_cache *cachep, gfp_t gfp)
+{
+	if (!memcg_kmem_enabled())
+		return cachep;
+	if (gfp & __GFP_NOFAIL)
+		return cachep;
+	if (in_interrupt() || (!current->mm) || (current->flags & PF_KTHREAD))
+		return cachep;
+	if (unlikely(fatal_signal_pending(current)))
+		return cachep;
+
+	return __memcg_kmem_get_cache(cachep, gfp);
+}
+#else
+#define for_each_memcg_cache_index(_idx)	\
+	for (; NULL; )
+
+static inline bool memcg_kmem_enabled(void)
+{
+	return false;
+}
+
+static inline bool
+memcg_kmem_newpage_charge(gfp_t gfp, struct mem_cgroup **memcg, int order)
+{
+	return true;
+}
+
+static inline void memcg_kmem_uncharge_pages(struct page *page, int order)
+{
+}
+
+static inline void
+memcg_kmem_commit_charge(struct page *page, struct mem_cgroup *memcg, int order)
+{
+}
+
+static inline int memcg_cache_id(struct mem_cgroup *memcg)
+{
+	return -1;
+}
+
+static inline int
+memcg_register_cache(struct mem_cgroup *memcg, struct kmem_cache *s,
+		     struct kmem_cache *root_cache)
+{
+	return 0;
+}
+
+static inline void memcg_release_cache(struct kmem_cache *cachep)
+{
+}
+
+static inline void memcg_cache_list_add(struct mem_cgroup *memcg,
+					struct kmem_cache *s)
+{
+}
+
+static inline struct kmem_cache *
+memcg_kmem_get_cache(struct kmem_cache *cachep, gfp_t gfp)
+{
+	return cachep;
+}
+
+static inline void kmem_cache_destroy_memcg_children(struct kmem_cache *s)
+{
+}
+#endif /* CONFIG_MEMCG_KMEM */
 #endif /* _LINUX_MEMCONTROL_H */
 
diff --git a/include/linux/memory.h b/include/linux/memory.h
index ff9a9f8..45e93b4 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -53,6 +53,8 @@ int arch_get_memory_phys_device(unsigned long start_pfn);
 struct memory_notify {
 	unsigned long start_pfn;
 	unsigned long nr_pages;
+	int status_change_nid_normal;
+	int status_change_nid_high;
 	int status_change_nid;
 };
 
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 95573ec..4a45c4e 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -26,6 +26,13 @@ enum {
 	MEMORY_HOTPLUG_MAX_BOOTMEM_TYPE = NODE_INFO,
 };
 
+/* Types for control the zone type of onlined memory */
+enum {
+	ONLINE_KEEP,
+	ONLINE_KERNEL,
+	ONLINE_MOVABLE,
+};
+
 /*
  * pgdat resizing functions
  */
@@ -46,6 +53,10 @@ void pgdat_resize_init(struct pglist_data *pgdat)
 }
 /*
  * Zone resizing functions
+ *
+ * Note: any attempt to resize a zone should has pgdat_resize_lock()
+ * zone_span_writelock() both held. This ensure the size of a zone
+ * can't be changed while pgdat_resize_lock() held.
  */
 static inline unsigned zone_span_seqbegin(struct zone *zone)
 {
@@ -71,7 +82,7 @@ extern int zone_grow_free_lists(struct zone *zone, unsigned long new_nr_pages);
 extern int zone_grow_waitqueues(struct zone *zone, unsigned long nr_pages);
 extern int add_one_highpage(struct page *page, int pfn, int bad_ppro);
 /* VM interface that may be used by firmware interface */
-extern int online_pages(unsigned long, unsigned long);
+extern int online_pages(unsigned long, unsigned long, int);
 extern void __offline_isolated_pages(unsigned long, unsigned long);
 
 typedef void (*online_page_callback_t)(struct page *page);
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index e5ccb9d..c511e25 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -198,6 +198,8 @@ static inline int vma_migratable(struct vm_area_struct *vma)
 	return 1;
 }
 
+extern int mpol_misplaced(struct page *, struct vm_area_struct *, unsigned long);
+
 #else
 
 struct mempolicy {};
@@ -323,5 +325,11 @@ static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol,
 	return 0;
 }
 
+static inline int mpol_misplaced(struct page *page, struct vm_area_struct *vma,
+				 unsigned long address)
+{
+	return -1; /* no node preference */
+}
+
 #endif /* CONFIG_NUMA */
 #endif
diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h
index a0ca0dc..478672e 100644
--- a/include/linux/mfd/88pm80x.h
+++ b/include/linux/mfd/88pm80x.h
@@ -364,6 +364,6 @@ static inline int pm80x_dev_resume(struct device *dev)
 #endif
 
 extern int pm80x_init(struct i2c_client *client,
-			     const struct i2c_device_id *id) __devinit;
+		      const struct i2c_device_id *id);
 extern int pm80x_deinit(struct i2c_client *client);
 #endif /* __LINUX_MFD_88PM80X_H */
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
index 5d5298d..2138bd3 100644
--- a/include/linux/mfd/abx500.h
+++ b/include/linux/mfd/abx500.h
@@ -267,39 +267,21 @@ struct abx500_bm_data {
 	int gnd_lift_resistance;
 	const struct abx500_maxim_parameters *maxi;
 	const struct abx500_bm_capacity_levels *cap_levels;
-	const struct abx500_battery_type *bat_type;
+	struct abx500_battery_type *bat_type;
 	const struct abx500_bm_charger_parameters *chg_params;
 	const struct abx500_fg_parameters *fg_params;
 };
 
-struct abx500_chargalg_platform_data {
-	char **supplied_to;
-	size_t num_supplicants;
-};
-
-struct abx500_charger_platform_data {
-	char **supplied_to;
-	size_t num_supplicants;
-	bool autopower_cfg;
-};
+extern struct abx500_bm_data ab8500_bm_data;
 
-struct abx500_btemp_platform_data {
-	char **supplied_to;
-	size_t num_supplicants;
+enum {
+	NTC_EXTERNAL = 0,
+	NTC_INTERNAL,
 };
 
-struct abx500_fg_platform_data {
-	char **supplied_to;
-	size_t num_supplicants;
-};
-
-struct abx500_bm_plat_data {
-	struct abx500_bm_data *battery;
-	struct abx500_charger_platform_data *charger;
-	struct abx500_btemp_platform_data *btemp;
-	struct abx500_fg_platform_data *fg;
-	struct abx500_chargalg_platform_data *chargalg;
-};
+int bmdevs_of_probe(struct device *dev,
+		struct device_node *np,
+		struct abx500_bm_data **battery);
 
 int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
 	u8 value);
diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h
index 1491044..1cb5698 100644
--- a/include/linux/mfd/abx500/ab8500.h
+++ b/include/linux/mfd/abx500/ab8500.h
@@ -291,9 +291,9 @@ struct ab8500_platform_data {
 	struct ab8500_codec_platform_data *codec;
 };
 
-extern int __devinit ab8500_init(struct ab8500 *ab8500,
+extern int ab8500_init(struct ab8500 *ab8500,
 				 enum ab8500_version version);
-extern int __devexit ab8500_exit(struct ab8500 *ab8500);
+extern int ab8500_exit(struct ab8500 *ab8500);
 
 extern int ab8500_suspend(struct ab8500 *ab8500);
 
diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h
index dd231ac..a580363 100644
--- a/include/linux/mfd/arizona/core.h
+++ b/include/linux/mfd/arizona/core.h
@@ -78,6 +78,8 @@ enum arizona_type {
 
 #define ARIZONA_NUM_IRQ                   50
 
+struct snd_soc_dapm_context;
+
 struct arizona {
 	struct regmap *regmap;
 	struct device *dev;
@@ -98,6 +100,8 @@ struct arizona {
 
 	struct mutex clk_lock;
 	int clk32k_ref;
+
+	struct snd_soc_dapm_context *dapm;
 };
 
 int arizona_clk32k_enable(struct arizona *arizona);
diff --git a/include/linux/mfd/arizona/pdata.h b/include/linux/mfd/arizona/pdata.h
index 7ab4429..8b1d1da 100644
--- a/include/linux/mfd/arizona/pdata.h
+++ b/include/linux/mfd/arizona/pdata.h
@@ -62,6 +62,9 @@
 
 #define ARIZONA_MAX_OUTPUT 6
 
+#define ARIZONA_HAP_ACT_ERM 0
+#define ARIZONA_HAP_ACT_LRA 2
+
 #define ARIZONA_MAX_PDM_SPK 2
 
 struct regulator_init_data;
@@ -114,6 +117,9 @@ struct arizona_pdata {
 
 	/** PDM speaker format */
 	unsigned int spk_fmt[ARIZONA_MAX_PDM_SPK];
+
+	/** Haptic actuator type */
+	unsigned int hap_act;
 };
 
 #endif
diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h
index 7671a28..ba26e99 100644
--- a/include/linux/mfd/arizona/registers.h
+++ b/include/linux/mfd/arizona/registers.h
@@ -76,6 +76,7 @@
 #define ARIZONA_RATE_ESTIMATOR_3                 0x154
 #define ARIZONA_RATE_ESTIMATOR_4                 0x155
 #define ARIZONA_RATE_ESTIMATOR_5                 0x156
+#define ARIZONA_DYNAMIC_FREQUENCY_SCALING_1      0x161
 #define ARIZONA_FLL1_CONTROL_1                   0x171
 #define ARIZONA_FLL1_CONTROL_2                   0x172
 #define ARIZONA_FLL1_CONTROL_3                   0x173
@@ -110,6 +111,7 @@
 #define ARIZONA_FLL2_GPIO_CLOCK                  0x1AA
 #define ARIZONA_MIC_CHARGE_PUMP_1                0x200
 #define ARIZONA_LDO1_CONTROL_1                   0x210
+#define ARIZONA_LDO1_CONTROL_2                   0x212
 #define ARIZONA_LDO2_CONTROL_1                   0x213
 #define ARIZONA_MIC_BIAS_CTRL_1                  0x218
 #define ARIZONA_MIC_BIAS_CTRL_2                  0x219
@@ -1574,6 +1576,13 @@
 #define ARIZONA_SAMPLE_RATE_DETECT_D_WIDTH            5  /* SAMPLE_RATE_DETECT_D - [4:0] */
 
 /*
+ * R353 (0x161) - Dynamic Frequency Scaling 1
+ */
+#define ARIZONA_SUBSYS_MAX_FREQ                  0x0001  /* SUBSYS_MAX_FREQ */
+#define ARIZONA_SUBSYS_MAX_FREQ_SHIFT                 0  /* SUBSYS_MAX_FREQ */
+#define ARIZONA_SUBSYS_MAX_FREQ_WIDTH                 1  /* SUBSYS_MAX_FREQ */
+
+/*
  * R369 (0x171) - FLL1 Control 1
  */
 #define ARIZONA_FLL1_FREERUN                     0x0002  /* FLL1_FREERUN */
@@ -1889,6 +1898,13 @@
 #define ARIZONA_LDO1_ENA_WIDTH                        1  /* LDO1_ENA */
 
 /*
+ * R530 (0x212) - LDO1 Control 2
+ */
+#define ARIZONA_LDO1_HI_PWR                      0x0001  /* LDO1_HI_PWR */
+#define ARIZONA_LDO1_HI_PWR_SHIFT                     0  /* LDO1_HI_PWR */
+#define ARIZONA_LDO1_HI_PWR_WIDTH                     1  /* LDO1_HI_PWR */
+
+/*
  * R531 (0x213) - LDO2 Control 1
  */
 #define ARIZONA_LDO2_VSEL_MASK                   0x07E0  /* LDO2_VSEL - [10:5] */
diff --git a/include/linux/mfd/as3711.h b/include/linux/mfd/as3711.h
new file mode 100644
index 0000000..38452ce
--- /dev/null
+++ b/include/linux/mfd/as3711.h
@@ -0,0 +1,126 @@
+/*
+ * AS3711 PMIC MFC driver header
+ *
+ * Copyright (C) 2012 Renesas Electronics Corporation
+ * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License as
+ * published by the Free Software Foundation
+ */
+
+#ifndef MFD_AS3711_H
+#define MFD_AS3711_H
+
+/*
+ * Client data
+ */
+
+/* Register addresses */
+#define AS3711_SD_1_VOLTAGE		0	/* Digital Step-Down */
+#define AS3711_SD_2_VOLTAGE		1
+#define AS3711_SD_3_VOLTAGE		2
+#define AS3711_SD_4_VOLTAGE		3
+#define AS3711_LDO_1_VOLTAGE		4	/* Analog LDO */
+#define AS3711_LDO_2_VOLTAGE		5
+#define AS3711_LDO_3_VOLTAGE		6	/* Digital LDO */
+#define AS3711_LDO_4_VOLTAGE		7
+#define AS3711_LDO_5_VOLTAGE		8
+#define AS3711_LDO_6_VOLTAGE		9
+#define AS3711_LDO_7_VOLTAGE		0xa
+#define AS3711_LDO_8_VOLTAGE		0xb
+#define AS3711_SD_CONTROL		0x10
+#define AS3711_GPIO_SIGNAL_OUT		0x20
+#define AS3711_GPIO_SIGNAL_IN		0x21
+#define AS3711_SD_CONTROL_1		0x30
+#define AS3711_SD_CONTROL_2		0x31
+#define AS3711_CURR_CONTROL		0x40
+#define AS3711_CURR1_VALUE		0x43
+#define AS3711_CURR2_VALUE		0x44
+#define AS3711_CURR3_VALUE		0x45
+#define AS3711_STEPUP_CONTROL_1		0x50
+#define AS3711_STEPUP_CONTROL_2		0x51
+#define AS3711_STEPUP_CONTROL_4		0x53
+#define AS3711_STEPUP_CONTROL_5		0x54
+#define AS3711_REG_STATUS		0x73
+#define AS3711_INTERRUPT_STATUS_1	0x77
+#define AS3711_INTERRUPT_STATUS_2	0x78
+#define AS3711_INTERRUPT_STATUS_3	0x79
+#define AS3711_CHARGER_STATUS_1		0x86
+#define AS3711_CHARGER_STATUS_2		0x87
+#define AS3711_ASIC_ID_1		0x90
+#define AS3711_ASIC_ID_2		0x91
+
+#define AS3711_MAX_REGS			0x92
+
+/* Regulators */
+enum {
+	AS3711_REGULATOR_SD_1,
+	AS3711_REGULATOR_SD_2,
+	AS3711_REGULATOR_SD_3,
+	AS3711_REGULATOR_SD_4,
+	AS3711_REGULATOR_LDO_1,
+	AS3711_REGULATOR_LDO_2,
+	AS3711_REGULATOR_LDO_3,
+	AS3711_REGULATOR_LDO_4,
+	AS3711_REGULATOR_LDO_5,
+	AS3711_REGULATOR_LDO_6,
+	AS3711_REGULATOR_LDO_7,
+	AS3711_REGULATOR_LDO_8,
+
+	AS3711_REGULATOR_MAX,
+};
+
+struct device;
+struct regmap;
+
+struct as3711 {
+	struct device *dev;
+	struct regmap *regmap;
+};
+
+#define AS3711_MAX_STEPDOWN 4
+#define AS3711_MAX_STEPUP 2
+#define AS3711_MAX_LDO 8
+
+enum as3711_su2_feedback {
+	AS3711_SU2_VOLTAGE,
+	AS3711_SU2_CURR1,
+	AS3711_SU2_CURR2,
+	AS3711_SU2_CURR3,
+	AS3711_SU2_CURR_AUTO,
+};
+
+enum as3711_su2_fbprot {
+	AS3711_SU2_LX_SD4,
+	AS3711_SU2_GPIO2,
+	AS3711_SU2_GPIO3,
+	AS3711_SU2_GPIO4,
+};
+
+/*
+ * Platform data
+ */
+
+struct as3711_regulator_pdata {
+	struct regulator_init_data *init_data[AS3711_REGULATOR_MAX];
+};
+
+struct as3711_bl_pdata {
+	const char *su1_fb;
+	int su1_max_uA;
+	const char *su2_fb;
+	int su2_max_uA;
+	enum as3711_su2_feedback su2_feedback;
+	enum as3711_su2_fbprot su2_fbprot;
+	bool su2_auto_curr1;
+	bool su2_auto_curr2;
+	bool su2_auto_curr3;
+};
+
+struct as3711_platform_data {
+	struct as3711_regulator_pdata regulator;
+	struct as3711_bl_pdata backlight;
+};
+
+#endif
diff --git a/include/linux/mfd/da9052/da9052.h b/include/linux/mfd/da9052/da9052.h
index 0507c4c..86dd93d 100644
--- a/include/linux/mfd/da9052/da9052.h
+++ b/include/linux/mfd/da9052/da9052.h
@@ -146,4 +146,14 @@ void da9052_device_exit(struct da9052 *da9052);
 
 extern struct regmap_config da9052_regmap_config;
 
+int da9052_irq_init(struct da9052 *da9052);
+int da9052_irq_exit(struct da9052 *da9052);
+int da9052_request_irq(struct da9052 *da9052, int irq, char *name,
+			   irq_handler_t handler, void *data);
+void da9052_free_irq(struct da9052 *da9052, int irq, void *data);
+
+int da9052_enable_irq(struct da9052 *da9052, int irq);
+int da9052_disable_irq(struct da9052 *da9052, int irq);
+int da9052_disable_irq_nosync(struct da9052 *da9052, int irq);
+
 #endif /* __MFD_DA9052_DA9052_H */
diff --git a/include/linux/mfd/da9055/core.h b/include/linux/mfd/da9055/core.h
index c96ad68..956afa4 100644
--- a/include/linux/mfd/da9055/core.h
+++ b/include/linux/mfd/da9055/core.h
@@ -1,4 +1,4 @@
-﻿/*
+/*
  * da9055 declarations for DA9055 PMICs.
  *
  * Copyright(c) 2012 Dialog Semiconductor Ltd.
diff --git a/include/linux/mfd/da9055/pdata.h b/include/linux/mfd/da9055/pdata.h
index 147293b..04e092b 100644
--- a/include/linux/mfd/da9055/pdata.h
+++ b/include/linux/mfd/da9055/pdata.h
@@ -1,4 +1,4 @@
-﻿/* Copyright (C) 2012 Dialog Semiconductor Ltd.
+/* Copyright (C) 2012 Dialog Semiconductor 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
@@ -25,8 +25,29 @@ struct da9055_pdata {
 	int gpio_base;
 
 	struct regulator_init_data *regulators[DA9055_MAX_REGULATORS];
-	bool reset_enable;		/* Enable RTC in RESET Mode */
-	enum gpio_select *gpio_rsel;	/* Select regulator set thru GPIO 1/2 */
-	enum gpio_select *gpio_ren;	/* Enable regulator thru GPIO 1/2 */
+	/* Enable RTC in RESET Mode */
+	bool reset_enable;
+	/*
+	 * GPI muxed pin to control
+	 * regulator state A/B, 0 if not available.
+	 */
+	int *gpio_ren;
+	/*
+	 * GPI muxed pin to control
+	 * regulator set, 0 if not available.
+	 */
+	int *gpio_rsel;
+	/*
+	 * Regulator mode control bits value (GPI offset) that
+	 * that controls the regulator state, 0 if not available.
+	 */
+	enum gpio_select *reg_ren;
+	/*
+	 * Regulator mode control bits value (GPI offset) that
+	 * controls the regulator set A/B, 0 if  not available.
+	 */
+	enum gpio_select *reg_rsel;
+	/* GPIOs to enable regulator, 0 if not available */
+	int *ena_gpio;
 };
 #endif /* __DA9055_PDATA_H */
diff --git a/include/linux/mfd/da9055/reg.h b/include/linux/mfd/da9055/reg.h
index df237ee..2b592e0 100644
--- a/include/linux/mfd/da9055/reg.h
+++ b/include/linux/mfd/da9055/reg.h
@@ -1,4 +1,4 @@
-﻿/*
+/*
  * DA9055 declarations for DA9055 PMICs.
  *
  * Copyright(c) 2012 Dialog Semiconductor Ltd.
diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h
index b82f6ee..6ee4247 100644
--- a/include/linux/mfd/db8500-prcmu.h
+++ b/include/linux/mfd/db8500-prcmu.h
@@ -515,7 +515,6 @@ enum romcode_read prcmu_get_rc_p2a(void);
 enum ap_pwrst prcmu_get_xp70_current_state(void);
 bool prcmu_has_arm_maxopp(void);
 struct prcmu_fw_version *prcmu_get_fw_version(void);
-int prcmu_request_ape_opp_100_voltage(bool enable);
 int prcmu_release_usb_wakeup_state(void);
 void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
 	struct prcmu_auto_pm_config *idle);
@@ -564,6 +563,7 @@ int db8500_prcmu_set_arm_opp(u8 opp);
 int db8500_prcmu_get_arm_opp(void);
 int db8500_prcmu_set_ape_opp(u8 opp);
 int db8500_prcmu_get_ape_opp(void);
+int db8500_prcmu_request_ape_opp_100_voltage(bool enable);
 int db8500_prcmu_set_ddr_opp(u8 opp);
 int db8500_prcmu_get_ddr_opp(void);
 
@@ -610,7 +610,7 @@ static inline int db8500_prcmu_get_ape_opp(void)
 	return APE_100_OPP;
 }
 
-static inline int prcmu_request_ape_opp_100_voltage(bool enable)
+static inline int db8500_prcmu_request_ape_opp_100_voltage(bool enable)
 {
 	return 0;
 }
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h
index c410d99..c202d6c 100644
--- a/include/linux/mfd/dbx500-prcmu.h
+++ b/include/linux/mfd/dbx500-prcmu.h
@@ -336,6 +336,11 @@ static inline int prcmu_get_ape_opp(void)
 	return db8500_prcmu_get_ape_opp();
 }
 
+static inline int prcmu_request_ape_opp_100_voltage(bool enable)
+{
+	return db8500_prcmu_request_ape_opp_100_voltage(enable);
+}
+
 static inline void prcmu_system_reset(u16 reset_code)
 {
 	return db8500_prcmu_system_reset(reset_code);
@@ -507,6 +512,11 @@ static inline int prcmu_get_ape_opp(void)
 	return APE_100_OPP;
 }
 
+static inline int prcmu_request_ape_opp_100_voltage(bool enable)
+{
+	return 0;
+}
+
 static inline int prcmu_set_arm_opp(u8 opp)
 {
 	return 0;
diff --git a/include/linux/mfd/lp8788.h b/include/linux/mfd/lp8788.h
index cec364b..2a32b16 100644
--- a/include/linux/mfd/lp8788.h
+++ b/include/linux/mfd/lp8788.h
@@ -211,16 +211,16 @@ struct lp8788_chg_param {
 
 /*
  * struct lp8788_charger_platform_data
- * @vbatt_adc         : adc selection id for battery voltage
- * @batt_temp_adc     : adc selection id for battery temperature
+ * @adc_vbatt         : adc channel name for battery voltage
+ * @adc_batt_temp     : adc channel name for battery temperature
  * @max_vbatt_mv      : used for calculating battery capacity
  * @chg_params        : initial charging parameters
  * @num_chg_params    : numbers of charging parameters
  * @charger_event     : the charger event can be reported to the platform side
  */
 struct lp8788_charger_platform_data {
-	enum lp8788_adc_id vbatt_adc;
-	enum lp8788_adc_id batt_temp_adc;
+	const char *adc_vbatt;
+	const char *adc_batt_temp;
 	unsigned int max_vbatt_mv;
 	struct lp8788_chg_param *chg_params;
 	int num_chg_params;
diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
index 830152c..6ae21bf 100644
--- a/include/linux/mfd/max8997-private.h
+++ b/include/linux/mfd/max8997-private.h
@@ -316,6 +316,7 @@ enum max8997_irq {
 #define MAX8997_NUM_GPIO	12
 struct max8997_dev {
 	struct device *dev;
+	struct max8997_platform_data *pdata;
 	struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */
 	struct i2c_client *rtc; /* slave addr 0x0c */
 	struct i2c_client *haptic; /* slave addr 0x90 */
diff --git a/include/linux/mfd/max8997.h b/include/linux/mfd/max8997.h
index 328d8e2..1d4a4fe 100644
--- a/include/linux/mfd/max8997.h
+++ b/include/linux/mfd/max8997.h
@@ -75,6 +75,7 @@ enum max8998_regulators {
 struct max8997_regulator_data {
 	int id;
 	struct regulator_init_data *initdata;
+	struct device_node *reg_node;
 };
 
 enum max8997_muic_usb_type {
diff --git a/include/linux/mfd/menelaus.h b/include/linux/mfd/menelaus.h
new file mode 100644
index 0000000..f097e89
--- /dev/null
+++ b/include/linux/mfd/menelaus.h
@@ -0,0 +1,47 @@
+/*
+ * Functions to access Menelaus power management chip
+ */
+
+#ifndef __ASM_ARCH_MENELAUS_H
+#define __ASM_ARCH_MENELAUS_H
+
+struct device;
+
+struct menelaus_platform_data {
+	int (* late_init)(struct device *dev);
+};
+
+extern int menelaus_register_mmc_callback(void (*callback)(void *data, u8 card_mask),
+					  void *data);
+extern void menelaus_unregister_mmc_callback(void);
+extern int menelaus_set_mmc_opendrain(int slot, int enable);
+extern int menelaus_set_mmc_slot(int slot, int enable, int power, int cd_on);
+
+extern int menelaus_set_vmem(unsigned int mV);
+extern int menelaus_set_vio(unsigned int mV);
+extern int menelaus_set_vmmc(unsigned int mV);
+extern int menelaus_set_vaux(unsigned int mV);
+extern int menelaus_set_vdcdc(int dcdc, unsigned int mV);
+extern int menelaus_set_slot_sel(int enable);
+extern int menelaus_get_slot_pin_states(void);
+extern int menelaus_set_vcore_sw(unsigned int mV);
+extern int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV);
+
+#define EN_VPLL_SLEEP	(1 << 7)
+#define EN_VMMC_SLEEP	(1 << 6)
+#define EN_VAUX_SLEEP	(1 << 5)
+#define EN_VIO_SLEEP	(1 << 4)
+#define EN_VMEM_SLEEP	(1 << 3)
+#define EN_DC3_SLEEP	(1 << 2)
+#define EN_DC2_SLEEP	(1 << 1)
+#define EN_VC_SLEEP	(1 << 0)
+
+extern int menelaus_set_regulator_sleep(int enable, u32 val);
+
+#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_MENELAUS)
+#define omap_has_menelaus()	1
+#else
+#define omap_has_menelaus()	0
+#endif
+
+#endif
diff --git a/include/linux/mfd/pm8xxx/irq.h b/include/linux/mfd/pm8xxx/irq.h
index 4b21769..f83d6b4 100644
--- a/include/linux/mfd/pm8xxx/irq.h
+++ b/include/linux/mfd/pm8xxx/irq.h
@@ -37,21 +37,21 @@ struct pm_irq_chip;
 
 #ifdef CONFIG_MFD_PM8XXX_IRQ
 int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq);
-struct pm_irq_chip * __devinit pm8xxx_irq_init(struct device *dev,
+struct pm_irq_chip *pm8xxx_irq_init(struct device *dev,
 				const struct pm8xxx_irq_platform_data *pdata);
-int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip);
+int pm8xxx_irq_exit(struct pm_irq_chip *chip);
 #else
 static inline int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
 {
 	return -ENXIO;
 }
-static inline struct pm_irq_chip * __devinit pm8xxx_irq_init(
+static inline struct pm_irq_chip *pm8xxx_irq_init(
 				const struct device *dev,
 				const struct pm8xxx_irq_platform_data *pdata)
 {
 	return ERR_PTR(-ENXIO);
 }
-static inline int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip)
+static inline int pm8xxx_irq_exit(struct pm_irq_chip *chip)
 {
 	return -ENXIO;
 }
diff --git a/include/linux/mfd/rc5t583.h b/include/linux/mfd/rc5t583.h
index 36c242e..fd413cc 100644
--- a/include/linux/mfd/rc5t583.h
+++ b/include/linux/mfd/rc5t583.h
@@ -33,6 +33,7 @@
 /* Maximum number of main interrupts */
 #define MAX_MAIN_INTERRUPT		5
 #define RC5T583_MAX_GPEDGE_REG		2
+#define RC5T583_MAX_INTERRUPT_EN_REGS	8
 #define RC5T583_MAX_INTERRUPT_MASK_REGS	9
 
 /* Interrupt enable register */
@@ -304,7 +305,7 @@ struct rc5t583 {
 	uint8_t		intc_inten_reg;
 
 	/* For group interrupt bits and address */
-	uint8_t		irq_en_reg[RC5T583_MAX_INTERRUPT_MASK_REGS];
+	uint8_t		irq_en_reg[RC5T583_MAX_INTERRUPT_EN_REGS];
 
 	/* For gpio edge */
 	uint8_t		gpedge_reg[RC5T583_MAX_GPEDGE_REG];
diff --git a/include/linux/mfd/retu.h b/include/linux/mfd/retu.h
new file mode 100644
index 0000000..1e2715d
--- /dev/null
+++ b/include/linux/mfd/retu.h
@@ -0,0 +1,22 @@
+/*
+ * Retu MFD driver interface
+ *
+ * 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 __LINUX_MFD_RETU_H
+#define __LINUX_MFD_RETU_H
+
+struct retu_dev;
+
+int retu_read(struct retu_dev *, u8);
+int retu_write(struct retu_dev *, u8, u16);
+
+/* Registers */
+#define RETU_REG_WATCHDOG	0x17		/* Watchdog */
+#define RETU_REG_CC1		0x0d		/* Common control register 1 */
+#define RETU_REG_STATUS		0x16		/* Status register */
+
+#endif /* __LINUX_MFD_RETU_H */
diff --git a/include/linux/mfd/rtsx_common.h b/include/linux/mfd/rtsx_common.h
new file mode 100644
index 0000000..a8d393e
--- /dev/null
+++ b/include/linux/mfd/rtsx_common.h
@@ -0,0 +1,48 @@
+/* Driver for Realtek driver-based card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __RTSX_COMMON_H
+#define __RTSX_COMMON_H
+
+#define DRV_NAME_RTSX_PCI		"rtsx_pci"
+#define DRV_NAME_RTSX_PCI_SDMMC		"rtsx_pci_sdmmc"
+#define DRV_NAME_RTSX_PCI_MS		"rtsx_pci_ms"
+
+#define RTSX_REG_PAIR(addr, val)	(((u32)(addr) << 16) | (u8)(val))
+
+#define RTSX_SSC_DEPTH_4M		0x01
+#define RTSX_SSC_DEPTH_2M		0x02
+#define RTSX_SSC_DEPTH_1M		0x03
+#define RTSX_SSC_DEPTH_500K		0x04
+#define RTSX_SSC_DEPTH_250K		0x05
+
+#define RTSX_SD_CARD			0
+#define RTSX_MS_CARD			1
+
+struct platform_device;
+
+struct rtsx_slot {
+	struct platform_device	*p_dev;
+	void			(*card_event)(struct platform_device *p_dev);
+};
+
+#endif
diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h
new file mode 100644
index 0000000..060b721
--- /dev/null
+++ b/include/linux/mfd/rtsx_pci.h
@@ -0,0 +1,794 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __RTSX_PCI_H
+#define __RTSX_PCI_H
+
+#include <linux/sched.h>
+#include <linux/pci.h>
+
+#include "rtsx_common.h"
+
+#define MAX_RW_REG_CNT			1024
+
+/* PCI Operation Register Address */
+#define RTSX_HCBAR			0x00
+#define RTSX_HCBCTLR			0x04
+#define RTSX_HDBAR			0x08
+#define RTSX_HDBCTLR			0x0C
+#define RTSX_HAIMR			0x10
+#define RTSX_BIPR			0x14
+#define RTSX_BIER			0x18
+
+/* Host command buffer control register */
+#define STOP_CMD			(0x01 << 28)
+
+/* Host data buffer control register */
+#define SDMA_MODE			0x00
+#define ADMA_MODE			(0x02 << 26)
+#define STOP_DMA			(0x01 << 28)
+#define TRIG_DMA			(0x01 << 31)
+
+/* Host access internal memory register */
+#define HAIMR_TRANS_START		(0x01 << 31)
+#define HAIMR_READ			0x00
+#define HAIMR_WRITE			(0x01 << 30)
+#define HAIMR_READ_START		(HAIMR_TRANS_START | HAIMR_READ)
+#define HAIMR_WRITE_START		(HAIMR_TRANS_START | HAIMR_WRITE)
+#define HAIMR_TRANS_END			(HAIMR_TRANS_START)
+
+/* Bus interrupt pending register */
+#define CMD_DONE_INT			(1 << 31)
+#define DATA_DONE_INT			(1 << 30)
+#define TRANS_OK_INT			(1 << 29)
+#define TRANS_FAIL_INT			(1 << 28)
+#define XD_INT				(1 << 27)
+#define MS_INT				(1 << 26)
+#define SD_INT				(1 << 25)
+#define GPIO0_INT			(1 << 24)
+#define OC_INT				(1 << 23)
+#define SD_WRITE_PROTECT		(1 << 19)
+#define XD_EXIST			(1 << 18)
+#define MS_EXIST			(1 << 17)
+#define SD_EXIST			(1 << 16)
+#define DELINK_INT			GPIO0_INT
+#define MS_OC_INT			(1 << 23)
+#define SD_OC_INT			(1 << 22)
+
+#define CARD_INT		(XD_INT | MS_INT | SD_INT)
+#define NEED_COMPLETE_INT	(DATA_DONE_INT | TRANS_OK_INT | TRANS_FAIL_INT)
+#define RTSX_INT		(CMD_DONE_INT | NEED_COMPLETE_INT | \
+					CARD_INT | GPIO0_INT | OC_INT)
+
+#define CARD_EXIST		(XD_EXIST | MS_EXIST | SD_EXIST)
+
+/* Bus interrupt enable register */
+#define CMD_DONE_INT_EN		(1 << 31)
+#define DATA_DONE_INT_EN	(1 << 30)
+#define TRANS_OK_INT_EN		(1 << 29)
+#define TRANS_FAIL_INT_EN	(1 << 28)
+#define XD_INT_EN		(1 << 27)
+#define MS_INT_EN		(1 << 26)
+#define SD_INT_EN		(1 << 25)
+#define GPIO0_INT_EN		(1 << 24)
+#define OC_INT_EN		(1 << 23)
+#define DELINK_INT_EN		GPIO0_INT_EN
+#define MS_OC_INT_EN		(1 << 23)
+#define SD_OC_INT_EN		(1 << 22)
+
+#define READ_REG_CMD		0
+#define WRITE_REG_CMD		1
+#define CHECK_REG_CMD		2
+
+/*
+ * macros for easy use
+ */
+#define rtsx_pci_writel(pcr, reg, value) \
+	iowrite32(value, (pcr)->remap_addr + reg)
+#define rtsx_pci_readl(pcr, reg) \
+	ioread32((pcr)->remap_addr + reg)
+#define rtsx_pci_writew(pcr, reg, value) \
+	iowrite16(value, (pcr)->remap_addr + reg)
+#define rtsx_pci_readw(pcr, reg) \
+	ioread16((pcr)->remap_addr + reg)
+#define rtsx_pci_writeb(pcr, reg, value) \
+	iowrite8(value, (pcr)->remap_addr + reg)
+#define rtsx_pci_readb(pcr, reg) \
+	ioread8((pcr)->remap_addr + reg)
+
+#define rtsx_pci_read_config_byte(pcr, where, val) \
+	pci_read_config_byte((pcr)->pci, where, val)
+
+#define rtsx_pci_write_config_byte(pcr, where, val) \
+	pci_write_config_byte((pcr)->pci, where, val)
+
+#define rtsx_pci_read_config_dword(pcr, where, val) \
+	pci_read_config_dword((pcr)->pci, where, val)
+
+#define rtsx_pci_write_config_dword(pcr, where, val) \
+	pci_write_config_dword((pcr)->pci, where, val)
+
+#define STATE_TRANS_NONE	0
+#define STATE_TRANS_CMD		1
+#define STATE_TRANS_BUF		2
+#define STATE_TRANS_SG		3
+
+#define TRANS_NOT_READY		0
+#define TRANS_RESULT_OK		1
+#define TRANS_RESULT_FAIL	2
+#define TRANS_NO_DEVICE		3
+
+#define RTSX_RESV_BUF_LEN	4096
+#define HOST_CMDS_BUF_LEN	1024
+#define HOST_SG_TBL_BUF_LEN	(RTSX_RESV_BUF_LEN - HOST_CMDS_BUF_LEN)
+#define HOST_SG_TBL_ITEMS	(HOST_SG_TBL_BUF_LEN / 8)
+#define MAX_SG_ITEM_LEN		0x80000
+
+#define HOST_TO_DEVICE		0
+#define DEVICE_TO_HOST		1
+
+#define MAX_PHASE		31
+#define RX_TUNING_CNT		3
+
+/* SG descriptor */
+#define SG_INT			0x04
+#define SG_END			0x02
+#define SG_VALID		0x01
+
+#define SG_NO_OP		0x00
+#define SG_TRANS_DATA		(0x02 << 4)
+#define SG_LINK_DESC		(0x03 << 4)
+
+/* SD bank voltage */
+#define SD_IO_3V3		0
+#define SD_IO_1V8		1
+
+
+/* Card Clock Enable Register */
+#define SD_CLK_EN			0x04
+#define MS_CLK_EN			0x08
+
+/* Card Select Register */
+#define SD_MOD_SEL			2
+#define MS_MOD_SEL			3
+
+/* Card Output Enable Register */
+#define SD_OUTPUT_EN			0x04
+#define MS_OUTPUT_EN			0x08
+
+/* CARD_SHARE_MODE */
+#define CARD_SHARE_MASK			0x0F
+#define CARD_SHARE_MULTI_LUN		0x00
+#define	CARD_SHARE_NORMAL		0x00
+#define	CARD_SHARE_48_SD		0x04
+#define	CARD_SHARE_48_MS		0x08
+/* CARD_SHARE_MODE for barossa */
+#define CARD_SHARE_BAROSSA_SD		0x01
+#define CARD_SHARE_BAROSSA_MS		0x02
+
+/* SD30_DRIVE_SEL */
+#define DRIVER_TYPE_A			0x05
+#define DRIVER_TYPE_B			0x03
+#define DRIVER_TYPE_C			0x02
+#define DRIVER_TYPE_D			0x01
+
+/* FPDCTL */
+#define SSC_POWER_DOWN			0x01
+#define SD_OC_POWER_DOWN		0x02
+#define ALL_POWER_DOWN			0x07
+#define OC_POWER_DOWN			0x06
+
+/* CLK_CTL */
+#define CHANGE_CLK			0x01
+
+/* LDO_CTL */
+#define BPP_LDO_POWB			0x03
+#define BPP_LDO_ON			0x00
+#define BPP_LDO_SUSPEND			0x02
+#define BPP_LDO_OFF			0x03
+
+/* CD_PAD_CTL */
+#define CD_DISABLE_MASK			0x07
+#define MS_CD_DISABLE			0x04
+#define SD_CD_DISABLE			0x02
+#define XD_CD_DISABLE			0x01
+#define CD_DISABLE			0x07
+#define CD_ENABLE			0x00
+#define MS_CD_EN_ONLY			0x03
+#define SD_CD_EN_ONLY			0x05
+#define XD_CD_EN_ONLY			0x06
+#define FORCE_CD_LOW_MASK		0x38
+#define FORCE_CD_XD_LOW			0x08
+#define FORCE_CD_SD_LOW			0x10
+#define FORCE_CD_MS_LOW			0x20
+#define CD_AUTO_DISABLE			0x40
+
+/* SD_STAT1 */
+#define	SD_CRC7_ERR			0x80
+#define	SD_CRC16_ERR			0x40
+#define	SD_CRC_WRITE_ERR		0x20
+#define	SD_CRC_WRITE_ERR_MASK		0x1C
+#define	GET_CRC_TIME_OUT		0x02
+#define	SD_TUNING_COMPARE_ERR		0x01
+
+/* SD_STAT2 */
+#define	SD_RSP_80CLK_TIMEOUT		0x01
+
+/* SD_BUS_STAT */
+#define	SD_CLK_TOGGLE_EN		0x80
+#define	SD_CLK_FORCE_STOP	        0x40
+#define	SD_DAT3_STATUS		        0x10
+#define	SD_DAT2_STATUS		        0x08
+#define	SD_DAT1_STATUS		        0x04
+#define	SD_DAT0_STATUS		        0x02
+#define	SD_CMD_STATUS			0x01
+
+/* SD_PAD_CTL */
+#define	SD_IO_USING_1V8		        0x80
+#define	SD_IO_USING_3V3		        0x7F
+#define	TYPE_A_DRIVING		        0x00
+#define	TYPE_B_DRIVING			0x01
+#define	TYPE_C_DRIVING			0x02
+#define	TYPE_D_DRIVING		        0x03
+
+/* SD_SAMPLE_POINT_CTL */
+#define	DDR_FIX_RX_DAT			0x00
+#define	DDR_VAR_RX_DAT			0x80
+#define	DDR_FIX_RX_DAT_EDGE		0x00
+#define	DDR_FIX_RX_DAT_14_DELAY		0x40
+#define	DDR_FIX_RX_CMD			0x00
+#define	DDR_VAR_RX_CMD			0x20
+#define	DDR_FIX_RX_CMD_POS_EDGE		0x00
+#define	DDR_FIX_RX_CMD_14_DELAY		0x10
+#define	SD20_RX_POS_EDGE		0x00
+#define	SD20_RX_14_DELAY		0x08
+#define SD20_RX_SEL_MASK		0x08
+
+/* SD_PUSH_POINT_CTL */
+#define	DDR_FIX_TX_CMD_DAT		0x00
+#define	DDR_VAR_TX_CMD_DAT		0x80
+#define	DDR_FIX_TX_DAT_14_TSU		0x00
+#define	DDR_FIX_TX_DAT_12_TSU		0x40
+#define	DDR_FIX_TX_CMD_NEG_EDGE		0x00
+#define	DDR_FIX_TX_CMD_14_AHEAD		0x20
+#define	SD20_TX_NEG_EDGE		0x00
+#define	SD20_TX_14_AHEAD		0x10
+#define SD20_TX_SEL_MASK		0x10
+#define	DDR_VAR_SDCLK_POL_SWAP		0x01
+
+/* SD_TRANSFER */
+#define	SD_TRANSFER_START		0x80
+#define	SD_TRANSFER_END			0x40
+#define SD_STAT_IDLE			0x20
+#define	SD_TRANSFER_ERR			0x10
+/* SD Transfer Mode definition */
+#define	SD_TM_NORMAL_WRITE		0x00
+#define	SD_TM_AUTO_WRITE_3		0x01
+#define	SD_TM_AUTO_WRITE_4		0x02
+#define	SD_TM_AUTO_READ_3		0x05
+#define	SD_TM_AUTO_READ_4		0x06
+#define	SD_TM_CMD_RSP			0x08
+#define	SD_TM_AUTO_WRITE_1		0x09
+#define	SD_TM_AUTO_WRITE_2		0x0A
+#define	SD_TM_NORMAL_READ		0x0C
+#define	SD_TM_AUTO_READ_1		0x0D
+#define	SD_TM_AUTO_READ_2		0x0E
+#define	SD_TM_AUTO_TUNING		0x0F
+
+/* SD_VPTX_CTL / SD_VPRX_CTL */
+#define PHASE_CHANGE			0x80
+#define PHASE_NOT_RESET			0x40
+
+/* SD_DCMPS_TX_CTL / SD_DCMPS_RX_CTL */
+#define DCMPS_CHANGE			0x80
+#define DCMPS_CHANGE_DONE		0x40
+#define DCMPS_ERROR			0x20
+#define DCMPS_CURRENT_PHASE		0x1F
+
+/* SD Configure 1 Register */
+#define SD_CLK_DIVIDE_0			0x00
+#define	SD_CLK_DIVIDE_256		0xC0
+#define	SD_CLK_DIVIDE_128		0x80
+#define	SD_BUS_WIDTH_1BIT		0x00
+#define	SD_BUS_WIDTH_4BIT		0x01
+#define	SD_BUS_WIDTH_8BIT		0x02
+#define	SD_ASYNC_FIFO_NOT_RST		0x10
+#define	SD_20_MODE			0x00
+#define	SD_DDR_MODE			0x04
+#define	SD_30_MODE			0x08
+
+#define SD_CLK_DIVIDE_MASK		0xC0
+
+/* SD_CMD_STATE */
+#define SD_CMD_IDLE			0x80
+
+/* SD_DATA_STATE */
+#define SD_DATA_IDLE			0x80
+
+/* DCM_DRP_CTL */
+#define DCM_RESET			0x08
+#define DCM_LOCKED			0x04
+#define DCM_208M			0x00
+#define DCM_TX			        0x01
+#define DCM_RX			        0x02
+
+/* DCM_DRP_TRIG */
+#define DRP_START			0x80
+#define DRP_DONE			0x40
+
+/* DCM_DRP_CFG */
+#define DRP_WRITE			0x80
+#define DRP_READ			0x00
+#define DCM_WRITE_ADDRESS_50		0x50
+#define DCM_WRITE_ADDRESS_51		0x51
+#define DCM_READ_ADDRESS_00		0x00
+#define DCM_READ_ADDRESS_51		0x51
+
+/* IRQSTAT0 */
+#define DMA_DONE_INT			0x80
+#define SUSPEND_INT			0x40
+#define LINK_RDY_INT			0x20
+#define LINK_DOWN_INT			0x10
+
+/* DMACTL */
+#define DMA_RST				0x80
+#define DMA_BUSY			0x04
+#define DMA_DIR_TO_CARD			0x00
+#define DMA_DIR_FROM_CARD		0x02
+#define DMA_EN				0x01
+#define DMA_128				(0 << 4)
+#define DMA_256				(1 << 4)
+#define DMA_512				(2 << 4)
+#define DMA_1024			(3 << 4)
+#define DMA_PACK_SIZE_MASK		0x30
+
+/* SSC_CTL1 */
+#define SSC_RSTB			0x80
+#define SSC_8X_EN			0x40
+#define SSC_FIX_FRAC			0x20
+#define SSC_SEL_1M			0x00
+#define SSC_SEL_2M			0x08
+#define SSC_SEL_4M			0x10
+#define SSC_SEL_8M			0x18
+
+/* SSC_CTL2 */
+#define SSC_DEPTH_MASK			0x07
+#define SSC_DEPTH_DISALBE		0x00
+#define SSC_DEPTH_4M			0x01
+#define SSC_DEPTH_2M			0x02
+#define SSC_DEPTH_1M			0x03
+#define SSC_DEPTH_500K			0x04
+#define SSC_DEPTH_250K			0x05
+
+/* System Clock Control Register */
+#define CLK_LOW_FREQ			0x01
+
+/* System Clock Divider Register */
+#define CLK_DIV_1			0x01
+#define CLK_DIV_2			0x02
+#define CLK_DIV_4			0x03
+#define CLK_DIV_8			0x04
+
+/* MS_CFG */
+#define	SAMPLE_TIME_RISING		0x00
+#define	SAMPLE_TIME_FALLING		0x80
+#define	PUSH_TIME_DEFAULT		0x00
+#define	PUSH_TIME_ODD			0x40
+#define	NO_EXTEND_TOGGLE		0x00
+#define	EXTEND_TOGGLE_CHK		0x20
+#define	MS_BUS_WIDTH_1			0x00
+#define	MS_BUS_WIDTH_4			0x10
+#define	MS_BUS_WIDTH_8			0x18
+#define	MS_2K_SECTOR_MODE		0x04
+#define	MS_512_SECTOR_MODE		0x00
+#define	MS_TOGGLE_TIMEOUT_EN		0x00
+#define	MS_TOGGLE_TIMEOUT_DISEN		0x01
+#define MS_NO_CHECK_INT			0x02
+
+/* MS_TRANS_CFG */
+#define	WAIT_INT			0x80
+#define	NO_WAIT_INT			0x00
+#define	NO_AUTO_READ_INT_REG		0x00
+#define	AUTO_READ_INT_REG		0x40
+#define	MS_CRC16_ERR			0x20
+#define	MS_RDY_TIMEOUT			0x10
+#define	MS_INT_CMDNK			0x08
+#define	MS_INT_BREQ			0x04
+#define	MS_INT_ERR			0x02
+#define	MS_INT_CED			0x01
+
+/* MS_TRANSFER */
+#define	MS_TRANSFER_START		0x80
+#define	MS_TRANSFER_END			0x40
+#define	MS_TRANSFER_ERR			0x20
+#define	MS_BS_STATE			0x10
+#define	MS_TM_READ_BYTES		0x00
+#define	MS_TM_NORMAL_READ		0x01
+#define	MS_TM_WRITE_BYTES		0x04
+#define	MS_TM_NORMAL_WRITE		0x05
+#define	MS_TM_AUTO_READ			0x08
+#define	MS_TM_AUTO_WRITE		0x0C
+
+/* SD Configure 2 Register */
+#define	SD_CALCULATE_CRC7		0x00
+#define	SD_NO_CALCULATE_CRC7		0x80
+#define	SD_CHECK_CRC16			0x00
+#define	SD_NO_CHECK_CRC16		0x40
+#define SD_NO_CHECK_WAIT_CRC_TO		0x20
+#define	SD_WAIT_BUSY_END		0x08
+#define	SD_NO_WAIT_BUSY_END		0x00
+#define	SD_CHECK_CRC7			0x00
+#define	SD_NO_CHECK_CRC7		0x04
+#define	SD_RSP_LEN_0			0x00
+#define	SD_RSP_LEN_6			0x01
+#define	SD_RSP_LEN_17			0x02
+/* SD/MMC Response Type Definition */
+#define	SD_RSP_TYPE_R0			0x04
+#define	SD_RSP_TYPE_R1			0x01
+#define	SD_RSP_TYPE_R1b			0x09
+#define	SD_RSP_TYPE_R2			0x02
+#define	SD_RSP_TYPE_R3			0x05
+#define	SD_RSP_TYPE_R4			0x05
+#define	SD_RSP_TYPE_R5			0x01
+#define	SD_RSP_TYPE_R6			0x01
+#define	SD_RSP_TYPE_R7			0x01
+
+/* SD_CONFIURE3 */
+#define	SD_RSP_80CLK_TIMEOUT_EN		0x01
+
+/* Card Transfer Reset Register */
+#define SPI_STOP			0x01
+#define XD_STOP				0x02
+#define SD_STOP				0x04
+#define MS_STOP				0x08
+#define SPI_CLR_ERR			0x10
+#define XD_CLR_ERR			0x20
+#define SD_CLR_ERR			0x40
+#define MS_CLR_ERR			0x80
+
+/* Card Data Source Register */
+#define PINGPONG_BUFFER			0x01
+#define RING_BUFFER			0x00
+
+/* Card Power Control Register */
+#define PMOS_STRG_MASK			0x10
+#define PMOS_STRG_800mA			0x10
+#define PMOS_STRG_400mA			0x00
+#define SD_POWER_OFF			0x03
+#define SD_PARTIAL_POWER_ON		0x01
+#define SD_POWER_ON			0x00
+#define SD_POWER_MASK			0x03
+#define MS_POWER_OFF			0x0C
+#define MS_PARTIAL_POWER_ON		0x04
+#define MS_POWER_ON			0x00
+#define MS_POWER_MASK			0x0C
+#define BPP_POWER_OFF			0x0F
+#define BPP_POWER_5_PERCENT_ON		0x0E
+#define BPP_POWER_10_PERCENT_ON		0x0C
+#define BPP_POWER_15_PERCENT_ON		0x08
+#define BPP_POWER_ON			0x00
+#define BPP_POWER_MASK			0x0F
+
+/* PWR_GATE_CTRL */
+#define PWR_GATE_EN			0x01
+#define LDO3318_PWR_MASK		0x06
+#define LDO_ON				0x00
+#define LDO_SUSPEND			0x04
+#define LDO_OFF				0x06
+
+/* CARD_CLK_SOURCE */
+#define CRC_FIX_CLK			(0x00 << 0)
+#define CRC_VAR_CLK0			(0x01 << 0)
+#define CRC_VAR_CLK1			(0x02 << 0)
+#define SD30_FIX_CLK			(0x00 << 2)
+#define SD30_VAR_CLK0			(0x01 << 2)
+#define SD30_VAR_CLK1			(0x02 << 2)
+#define SAMPLE_FIX_CLK			(0x00 << 4)
+#define SAMPLE_VAR_CLK0			(0x01 << 4)
+#define SAMPLE_VAR_CLK1			(0x02 << 4)
+
+#define MS_CFG				0xFD40
+#define MS_TPC				0xFD41
+#define MS_TRANS_CFG			0xFD42
+#define MS_TRANSFER			0xFD43
+#define MS_INT_REG			0xFD44
+#define MS_BYTE_CNT			0xFD45
+#define MS_SECTOR_CNT_L			0xFD46
+#define MS_SECTOR_CNT_H			0xFD47
+#define MS_DBUS_H			0xFD48
+
+#define SD_CFG1				0xFDA0
+#define SD_CFG2				0xFDA1
+#define SD_CFG3				0xFDA2
+#define SD_STAT1			0xFDA3
+#define SD_STAT2			0xFDA4
+#define SD_BUS_STAT			0xFDA5
+#define SD_PAD_CTL			0xFDA6
+#define SD_SAMPLE_POINT_CTL		0xFDA7
+#define SD_PUSH_POINT_CTL		0xFDA8
+#define SD_CMD0				0xFDA9
+#define SD_CMD1				0xFDAA
+#define SD_CMD2				0xFDAB
+#define SD_CMD3				0xFDAC
+#define SD_CMD4				0xFDAD
+#define SD_CMD5				0xFDAE
+#define SD_BYTE_CNT_L			0xFDAF
+#define SD_BYTE_CNT_H			0xFDB0
+#define SD_BLOCK_CNT_L			0xFDB1
+#define SD_BLOCK_CNT_H			0xFDB2
+#define SD_TRANSFER			0xFDB3
+#define SD_CMD_STATE			0xFDB5
+#define SD_DATA_STATE			0xFDB6
+
+#define SRCTL				0xFC13
+
+#define	DCM_DRP_CTL			0xFC23
+#define	DCM_DRP_TRIG			0xFC24
+#define	DCM_DRP_CFG			0xFC25
+#define	DCM_DRP_WR_DATA_L		0xFC26
+#define	DCM_DRP_WR_DATA_H		0xFC27
+#define	DCM_DRP_RD_DATA_L		0xFC28
+#define	DCM_DRP_RD_DATA_H		0xFC29
+#define SD_VPCLK0_CTL			0xFC2A
+#define SD_VPCLK1_CTL			0xFC2B
+#define SD_DCMPS0_CTL			0xFC2C
+#define SD_DCMPS1_CTL			0xFC2D
+#define SD_VPTX_CTL			SD_VPCLK0_CTL
+#define SD_VPRX_CTL			SD_VPCLK1_CTL
+#define SD_DCMPS_TX_CTL			SD_DCMPS0_CTL
+#define SD_DCMPS_RX_CTL			SD_DCMPS1_CTL
+#define CARD_CLK_SOURCE			0xFC2E
+
+#define CARD_PWR_CTL			0xFD50
+#define CARD_CLK_SWITCH			0xFD51
+#define CARD_SHARE_MODE			0xFD52
+#define CARD_DRIVE_SEL			0xFD53
+#define CARD_STOP			0xFD54
+#define CARD_OE				0xFD55
+#define CARD_AUTO_BLINK			0xFD56
+#define CARD_GPIO_DIR			0xFD57
+#define CARD_GPIO			0xFD58
+#define CARD_DATA_SOURCE		0xFD5B
+#define CARD_SELECT			0xFD5C
+#define SD30_DRIVE_SEL			0xFD5E
+#define CARD_CLK_EN			0xFD69
+#define SDIO_CTRL			0xFD6B
+#define CD_PAD_CTL			0xFD73
+
+#define FPDCTL				0xFC00
+#define PDINFO				0xFC01
+
+#define CLK_CTL				0xFC02
+#define CLK_DIV				0xFC03
+#define CLK_SEL				0xFC04
+
+#define SSC_DIV_N_0			0xFC0F
+#define SSC_DIV_N_1			0xFC10
+#define SSC_CTL1			0xFC11
+#define SSC_CTL2			0xFC12
+
+#define RCCTL				0xFC14
+
+#define FPGA_PULL_CTL			0xFC1D
+#define OLT_LED_CTL			0xFC1E
+#define GPIO_CTL			0xFC1F
+
+#define LDO_CTL				0xFC1E
+#define SYS_VER				0xFC32
+
+#define CARD_PULL_CTL1			0xFD60
+#define CARD_PULL_CTL2			0xFD61
+#define CARD_PULL_CTL3			0xFD62
+#define CARD_PULL_CTL4			0xFD63
+#define CARD_PULL_CTL5			0xFD64
+#define CARD_PULL_CTL6			0xFD65
+
+/* PCI Express Related Registers */
+#define IRQEN0				0xFE20
+#define IRQSTAT0			0xFE21
+#define IRQEN1				0xFE22
+#define IRQSTAT1			0xFE23
+#define TLPRIEN				0xFE24
+#define TLPRISTAT			0xFE25
+#define TLPTIEN				0xFE26
+#define TLPTISTAT			0xFE27
+#define DMATC0				0xFE28
+#define DMATC1				0xFE29
+#define DMATC2				0xFE2A
+#define DMATC3				0xFE2B
+#define DMACTL				0xFE2C
+#define BCTL				0xFE2D
+#define RBBC0				0xFE2E
+#define RBBC1				0xFE2F
+#define RBDAT				0xFE30
+#define RBCTL				0xFE34
+#define CFGADDR0			0xFE35
+#define CFGADDR1			0xFE36
+#define CFGDATA0			0xFE37
+#define CFGDATA1			0xFE38
+#define CFGDATA2			0xFE39
+#define CFGDATA3			0xFE3A
+#define CFGRWCTL			0xFE3B
+#define PHYRWCTL			0xFE3C
+#define PHYDATA0			0xFE3D
+#define PHYDATA1			0xFE3E
+#define PHYADDR				0xFE3F
+#define MSGRXDATA0			0xFE40
+#define MSGRXDATA1			0xFE41
+#define MSGRXDATA2			0xFE42
+#define MSGRXDATA3			0xFE43
+#define MSGTXDATA0			0xFE44
+#define MSGTXDATA1			0xFE45
+#define MSGTXDATA2			0xFE46
+#define MSGTXDATA3			0xFE47
+#define MSGTXCTL			0xFE48
+#define PETXCFG				0xFE49
+
+#define CDRESUMECTL			0xFE52
+#define WAKE_SEL_CTL			0xFE54
+#define PME_FORCE_CTL			0xFE56
+#define ASPM_FORCE_CTL			0xFE57
+#define PM_CLK_FORCE_CTL		0xFE58
+#define PERST_GLITCH_WIDTH		0xFE5C
+#define CHANGE_LINK_STATE		0xFE5B
+#define RESET_LOAD_REG			0xFE5E
+#define EFUSE_CONTENT			0xFE5F
+#define HOST_SLEEP_STATE		0xFE60
+#define SDIO_CFG			0xFE70
+
+#define NFTS_TX_CTRL			0xFE72
+
+#define PWR_GATE_CTRL			0xFE75
+#define PWD_SUSPEND_EN			0xFE76
+#define LDO_PWR_SEL			0xFE78
+
+#define DUMMY_REG_RESET_0		0xFE90
+
+/* Memory mapping */
+#define SRAM_BASE			0xE600
+#define RBUF_BASE			0xF400
+#define PPBUF_BASE1			0xF800
+#define PPBUF_BASE2			0xFA00
+#define IMAGE_FLAG_ADDR0		0xCE80
+#define IMAGE_FLAG_ADDR1		0xCE81
+
+#define rtsx_pci_init_cmd(pcr)		((pcr)->ci = 0)
+
+struct rtsx_pcr;
+
+struct pcr_handle {
+	struct rtsx_pcr			*pcr;
+};
+
+struct pcr_ops {
+	int		(*extra_init_hw)(struct rtsx_pcr *pcr);
+	int		(*optimize_phy)(struct rtsx_pcr *pcr);
+	int		(*turn_on_led)(struct rtsx_pcr *pcr);
+	int		(*turn_off_led)(struct rtsx_pcr *pcr);
+	int		(*enable_auto_blink)(struct rtsx_pcr *pcr);
+	int		(*disable_auto_blink)(struct rtsx_pcr *pcr);
+	int		(*card_power_on)(struct rtsx_pcr *pcr, int card);
+	int		(*card_power_off)(struct rtsx_pcr *pcr, int card);
+	unsigned int	(*cd_deglitch)(struct rtsx_pcr *pcr);
+};
+
+enum PDEV_STAT  {PDEV_STAT_IDLE, PDEV_STAT_RUN};
+
+struct rtsx_pcr {
+	struct pci_dev			*pci;
+	unsigned int			id;
+
+	/* pci resources */
+	unsigned long			addr;
+	void __iomem			*remap_addr;
+	int				irq;
+
+	/* host reserved buffer */
+	void				*rtsx_resv_buf;
+	dma_addr_t			rtsx_resv_buf_addr;
+
+	void				*host_cmds_ptr;
+	dma_addr_t			host_cmds_addr;
+	int				ci;
+
+	void				*host_sg_tbl_ptr;
+	dma_addr_t			host_sg_tbl_addr;
+	int				sgi;
+
+	u32				bier;
+	char				trans_result;
+
+	unsigned int			card_inserted;
+	unsigned int			card_removed;
+
+	struct delayed_work		carddet_work;
+	struct delayed_work		idle_work;
+
+	spinlock_t			lock;
+	struct mutex			pcr_mutex;
+	struct completion		*done;
+	struct completion		*finish_me;
+
+	unsigned int			cur_clock;
+	bool				ms_pmos;
+	bool				remove_pci;
+	bool				msi_en;
+
+#define EXTRA_CAPS_SD_SDR50		(1 << 0)
+#define EXTRA_CAPS_SD_SDR104		(1 << 1)
+#define EXTRA_CAPS_SD_DDR50		(1 << 2)
+#define EXTRA_CAPS_MMC_HSDDR		(1 << 3)
+#define EXTRA_CAPS_MMC_HS200		(1 << 4)
+#define EXTRA_CAPS_MMC_8BIT		(1 << 5)
+	u32				extra_caps;
+
+#define IC_VER_A			0
+#define IC_VER_B			1
+#define IC_VER_C			2
+#define IC_VER_D			3
+	u8				ic_version;
+
+	const u32			*sd_pull_ctl_enable_tbl;
+	const u32			*sd_pull_ctl_disable_tbl;
+	const u32			*ms_pull_ctl_enable_tbl;
+	const u32			*ms_pull_ctl_disable_tbl;
+
+	const struct pcr_ops		*ops;
+	enum PDEV_STAT			state;
+
+	int				num_slots;
+	struct rtsx_slot		*slots;
+};
+
+#define CHK_PCI_PID(pcr, pid)		((pcr)->pci->device == (pid))
+#define PCI_VID(pcr)			((pcr)->pci->vendor)
+#define PCI_PID(pcr)			((pcr)->pci->device)
+
+void rtsx_pci_start_run(struct rtsx_pcr *pcr);
+int rtsx_pci_write_register(struct rtsx_pcr *pcr, u16 addr, u8 mask, u8 data);
+int rtsx_pci_read_register(struct rtsx_pcr *pcr, u16 addr, u8 *data);
+int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val);
+int rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val);
+void rtsx_pci_stop_cmd(struct rtsx_pcr *pcr);
+void rtsx_pci_add_cmd(struct rtsx_pcr *pcr,
+		u8 cmd_type, u16 reg_addr, u8 mask, u8 data);
+void rtsx_pci_send_cmd_no_wait(struct rtsx_pcr *pcr);
+int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout);
+int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+		int num_sg, bool read, int timeout);
+int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len);
+int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len);
+int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card);
+int rtsx_pci_card_pull_ctl_disable(struct rtsx_pcr *pcr, int card);
+int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
+		u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk);
+int rtsx_pci_card_power_on(struct rtsx_pcr *pcr, int card);
+int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card);
+unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr);
+void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr);
+
+static inline u8 *rtsx_pci_get_cmd_data(struct rtsx_pcr *pcr)
+{
+	return (u8 *)(pcr->host_cmds_ptr);
+}
+
+#endif
diff --git a/include/linux/mfd/sta2x11-mfd.h b/include/linux/mfd/sta2x11-mfd.h
index d179227..9a855ac 100644
--- a/include/linux/mfd/sta2x11-mfd.h
+++ b/include/linux/mfd/sta2x11-mfd.h
@@ -26,6 +26,28 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 
+enum sta2x11_mfd_plat_dev {
+	sta2x11_sctl = 0,
+	sta2x11_gpio,
+	sta2x11_scr,
+	sta2x11_time,
+	sta2x11_apbreg,
+	sta2x11_apb_soc_regs,
+	sta2x11_vic,
+	sta2x11_n_mfd_plat_devs,
+};
+
+#define STA2X11_MFD_SCTL_NAME	       "sta2x11-sctl"
+#define STA2X11_MFD_GPIO_NAME	       "sta2x11-gpio"
+#define STA2X11_MFD_SCR_NAME	       "sta2x11-scr"
+#define STA2X11_MFD_TIME_NAME	       "sta2x11-time"
+#define STA2X11_MFD_APBREG_NAME	       "sta2x11-apbreg"
+#define STA2X11_MFD_APB_SOC_REGS_NAME  "sta2x11-apb-soc-regs"
+#define STA2X11_MFD_VIC_NAME	       "sta2x11-vic"
+
+extern u32
+__sta2x11_mfd_mask(struct pci_dev *, u32, u32, u32, enum sta2x11_mfd_plat_dev);
+
 /*
  * The MFD PCI block includes the GPIO peripherals and other register blocks.
  * For GPIO, we have 32*4 bits (I use "gsta" for "gpio sta2x11".)
@@ -182,7 +204,11 @@ struct sta2x11_gpio_pdata {
  * The APB bridge has its own registers, needed by our users as well.
  * They are accessed with the following read/mask/write function.
  */
-u32 sta2x11_apbreg_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val);
+static inline u32
+sta2x11_apbreg_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val)
+{
+	return __sta2x11_mfd_mask(pdev, reg, mask, val, sta2x11_apbreg);
+}
 
 /* CAN and MLB */
 #define APBREG_BSR	0x00	/* Bridge Status Reg */
@@ -211,19 +237,45 @@ u32 sta2x11_apbreg_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val);
  * The system controller has its own registers. Some of these are accessed
  * by out users as well, using the following read/mask/write/function
  */
-u32 sta2x11_sctl_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val);
+static inline
+u32 sta2x11_sctl_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val)
+{
+	return __sta2x11_mfd_mask(pdev, reg, mask, val, sta2x11_sctl);
+}
 
 #define SCTL_SCCTL		0x00	/* System controller control register */
 #define SCTL_ARMCFG		0x04	/* ARM configuration register */
 #define SCTL_SCPLLCTL		0x08	/* PLL control status register */
+
+#define SCTL_SCPLLCTL_AUDIO_PLL_PD	     BIT(1)
+#define SCTL_SCPLLCTL_FRAC_CONTROL	     BIT(3)
+#define SCTL_SCPLLCTL_STRB_BYPASS	     BIT(6)
+#define SCTL_SCPLLCTL_STRB_INPUT	     BIT(8)
+
 #define SCTL_SCPLLFCTRL		0x0c	/* PLL frequency control register */
+
+#define SCTL_SCPLLFCTRL_AUDIO_PLL_NDIV_MASK	0xff
+#define SCTL_SCPLLFCTRL_AUDIO_PLL_NDIV_SHIFT	  10
+#define SCTL_SCPLLFCTRL_AUDIO_PLL_IDF_MASK	   7
+#define SCTL_SCPLLFCTRL_AUDIO_PLL_IDF_SHIFT	  21
+#define SCTL_SCPLLFCTRL_AUDIO_PLL_ODF_MASK	   7
+#define SCTL_SCPLLFCTRL_AUDIO_PLL_ODF_SHIFT	  18
+#define SCTL_SCPLLFCTRL_DITHER_DISABLE_MASK     0x03
+#define SCTL_SCPLLFCTRL_DITHER_DISABLE_SHIFT       4
+
+
 #define SCTL_SCRESFRACT		0x10	/* PLL fractional input register */
+
+#define SCTL_SCRESFRACT_MASK	0x0000ffff
+
+
 #define SCTL_SCRESCTRL1		0x14	/* Peripheral reset control 1 */
 #define SCTL_SCRESXTRL2		0x18	/* Peripheral reset control 2 */
 #define SCTL_SCPEREN0		0x1c	/* Peripheral clock enable register 0 */
 #define SCTL_SCPEREN1		0x20	/* Peripheral clock enable register 1 */
 #define SCTL_SCPEREN2		0x24	/* Peripheral clock enable register 2 */
 #define SCTL_SCGRST		0x28	/* Peripheral global reset */
+#define SCTL_SCPCIECSBRST       0x2c    /* PCIe PAB CSB reset status register */
 #define SCTL_SCPCIPMCR1		0x30	/* PCI power management control 1 */
 #define SCTL_SCPCIPMCR2		0x34	/* PCI power management control 2 */
 #define SCTL_SCPCIPMSR1		0x38	/* PCI power management status 1 */
@@ -321,4 +373,146 @@ u32 sta2x11_sctl_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val);
 #define SCTL_SCPEREN1_I2C3		(1 << 16)
 #define SCTL_SCPEREN1_USB_PHY		(1 << 17)
 
+/*
+ * APB-SOC registers
+ */
+static inline
+u32 sta2x11_apb_soc_regs_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val)
+{
+	return __sta2x11_mfd_mask(pdev, reg, mask, val, sta2x11_apb_soc_regs);
+}
+
+#define PCIE_EP1_FUNC3_0_INTR_REG	0x000
+#define PCIE_EP1_FUNC7_4_INTR_REG	0x004
+#define PCIE_EP2_FUNC3_0_INTR_REG	0x008
+#define PCIE_EP2_FUNC7_4_INTR_REG	0x00c
+#define PCIE_EP3_FUNC3_0_INTR_REG	0x010
+#define PCIE_EP3_FUNC7_4_INTR_REG	0x014
+#define PCIE_EP4_FUNC3_0_INTR_REG	0x018
+#define PCIE_EP4_FUNC7_4_INTR_REG	0x01c
+#define PCIE_INTR_ENABLE0_REG		0x020
+#define PCIE_INTR_ENABLE1_REG		0x024
+#define PCIE_EP1_FUNC_TC_REG		0x028
+#define PCIE_EP2_FUNC_TC_REG		0x02c
+#define PCIE_EP3_FUNC_TC_REG		0x030
+#define PCIE_EP4_FUNC_TC_REG		0x034
+#define PCIE_EP1_FUNC_F_REG		0x038
+#define PCIE_EP2_FUNC_F_REG		0x03c
+#define PCIE_EP3_FUNC_F_REG		0x040
+#define PCIE_EP4_FUNC_F_REG		0x044
+#define PCIE_PAB_AMBA_SW_RST_REG	0x048
+#define PCIE_PM_STATUS_0_PORT_0_4	0x04c
+#define PCIE_PM_STATUS_7_0_EP1		0x050
+#define PCIE_PM_STATUS_7_0_EP2		0x054
+#define PCIE_PM_STATUS_7_0_EP3		0x058
+#define PCIE_PM_STATUS_7_0_EP4		0x05c
+#define PCIE_DEV_ID_0_EP1_REG		0x060
+#define PCIE_CC_REV_ID_0_EP1_REG	0x064
+#define PCIE_DEV_ID_1_EP1_REG		0x068
+#define PCIE_CC_REV_ID_1_EP1_REG	0x06c
+#define PCIE_DEV_ID_2_EP1_REG		0x070
+#define PCIE_CC_REV_ID_2_EP1_REG	0x074
+#define PCIE_DEV_ID_3_EP1_REG		0x078
+#define PCIE_CC_REV_ID_3_EP1_REG	0x07c
+#define PCIE_DEV_ID_4_EP1_REG		0x080
+#define PCIE_CC_REV_ID_4_EP1_REG	0x084
+#define PCIE_DEV_ID_5_EP1_REG		0x088
+#define PCIE_CC_REV_ID_5_EP1_REG	0x08c
+#define PCIE_DEV_ID_6_EP1_REG		0x090
+#define PCIE_CC_REV_ID_6_EP1_REG	0x094
+#define PCIE_DEV_ID_7_EP1_REG		0x098
+#define PCIE_CC_REV_ID_7_EP1_REG	0x09c
+#define PCIE_DEV_ID_0_EP2_REG		0x0a0
+#define PCIE_CC_REV_ID_0_EP2_REG	0x0a4
+#define PCIE_DEV_ID_1_EP2_REG		0x0a8
+#define PCIE_CC_REV_ID_1_EP2_REG	0x0ac
+#define PCIE_DEV_ID_2_EP2_REG		0x0b0
+#define PCIE_CC_REV_ID_2_EP2_REG	0x0b4
+#define PCIE_DEV_ID_3_EP2_REG		0x0b8
+#define PCIE_CC_REV_ID_3_EP2_REG	0x0bc
+#define PCIE_DEV_ID_4_EP2_REG		0x0c0
+#define PCIE_CC_REV_ID_4_EP2_REG	0x0c4
+#define PCIE_DEV_ID_5_EP2_REG		0x0c8
+#define PCIE_CC_REV_ID_5_EP2_REG	0x0cc
+#define PCIE_DEV_ID_6_EP2_REG		0x0d0
+#define PCIE_CC_REV_ID_6_EP2_REG	0x0d4
+#define PCIE_DEV_ID_7_EP2_REG		0x0d8
+#define PCIE_CC_REV_ID_7_EP2_REG	0x0dC
+#define PCIE_DEV_ID_0_EP3_REG		0x0e0
+#define PCIE_CC_REV_ID_0_EP3_REG	0x0e4
+#define PCIE_DEV_ID_1_EP3_REG		0x0e8
+#define PCIE_CC_REV_ID_1_EP3_REG	0x0ec
+#define PCIE_DEV_ID_2_EP3_REG		0x0f0
+#define PCIE_CC_REV_ID_2_EP3_REG	0x0f4
+#define PCIE_DEV_ID_3_EP3_REG		0x0f8
+#define PCIE_CC_REV_ID_3_EP3_REG	0x0fc
+#define PCIE_DEV_ID_4_EP3_REG		0x100
+#define PCIE_CC_REV_ID_4_EP3_REG	0x104
+#define PCIE_DEV_ID_5_EP3_REG		0x108
+#define PCIE_CC_REV_ID_5_EP3_REG	0x10c
+#define PCIE_DEV_ID_6_EP3_REG		0x110
+#define PCIE_CC_REV_ID_6_EP3_REG	0x114
+#define PCIE_DEV_ID_7_EP3_REG		0x118
+#define PCIE_CC_REV_ID_7_EP3_REG	0x11c
+#define PCIE_DEV_ID_0_EP4_REG		0x120
+#define PCIE_CC_REV_ID_0_EP4_REG	0x124
+#define PCIE_DEV_ID_1_EP4_REG		0x128
+#define PCIE_CC_REV_ID_1_EP4_REG	0x12c
+#define PCIE_DEV_ID_2_EP4_REG		0x130
+#define PCIE_CC_REV_ID_2_EP4_REG	0x134
+#define PCIE_DEV_ID_3_EP4_REG		0x138
+#define PCIE_CC_REV_ID_3_EP4_REG	0x13c
+#define PCIE_DEV_ID_4_EP4_REG		0x140
+#define PCIE_CC_REV_ID_4_EP4_REG	0x144
+#define PCIE_DEV_ID_5_EP4_REG		0x148
+#define PCIE_CC_REV_ID_5_EP4_REG	0x14c
+#define PCIE_DEV_ID_6_EP4_REG		0x150
+#define PCIE_CC_REV_ID_6_EP4_REG	0x154
+#define PCIE_DEV_ID_7_EP4_REG		0x158
+#define PCIE_CC_REV_ID_7_EP4_REG	0x15c
+#define PCIE_SUBSYS_VEN_ID_REG		0x160
+#define PCIE_COMMON_CLOCK_CONFIG_0_4_0	0x164
+#define PCIE_MIPHYP_SSC_EN_REG		0x168
+#define PCIE_MIPHYP_ADDR_REG		0x16c
+#define PCIE_L1_ASPM_READY_REG		0x170
+#define PCIE_EXT_CFG_RDY_REG		0x174
+#define PCIE_SoC_INT_ROUTER_STATUS0_REG 0x178
+#define PCIE_SoC_INT_ROUTER_STATUS1_REG 0x17c
+#define PCIE_SoC_INT_ROUTER_STATUS2_REG 0x180
+#define PCIE_SoC_INT_ROUTER_STATUS3_REG 0x184
+#define DMA_IP_CTRL_REG			0x324
+#define DISP_BRIDGE_PU_PD_CTRL_REG	0x328
+#define VIP_PU_PD_CTRL_REG		0x32c
+#define USB_MLB_PU_PD_CTRL_REG		0x330
+#define SDIO_PU_PD_MISCFUNC_CTRL_REG1	0x334
+#define SDIO_PU_PD_MISCFUNC_CTRL_REG2	0x338
+#define UART_PU_PD_CTRL_REG		0x33c
+#define ARM_Lock			0x340
+#define SYS_IO_CHAR_REG1		0x344
+#define SYS_IO_CHAR_REG2		0x348
+#define SATA_CORE_ID_REG		0x34c
+#define SATA_CTRL_REG			0x350
+#define I2C_HSFIX_MISC_REG		0x354
+#define SPARE2_RESERVED			0x358
+#define SPARE3_RESERVED			0x35c
+#define MASTER_LOCK_REG			0x368
+#define SYSTEM_CONFIG_STATUS_REG	0x36c
+#define MSP_CLK_CTRL_REG		0x39c
+#define COMPENSATION_REG1		0x3c4
+#define COMPENSATION_REG2		0x3c8
+#define COMPENSATION_REG3		0x3cc
+#define TEST_CTL_REG			0x3d0
+
+/*
+ * SECR (OTP) registers
+ */
+#define STA2X11_SECR_CR			0x00
+#define STA2X11_SECR_FVR0		0x10
+#define STA2X11_SECR_FVR1		0x14
+
+extern int sta2x11_mfd_get_regs_data(struct platform_device *pdev,
+				     enum sta2x11_mfd_plat_dev index,
+				     void __iomem **regs,
+				     spinlock_t **lock);
+
 #endif /* __STA2X11_MFD_H */
diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h
index f8d5b4d..15dac79 100644
--- a/include/linux/mfd/stmpe.h
+++ b/include/linux/mfd/stmpe.h
@@ -62,6 +62,7 @@ struct stmpe_client_info;
  * @lock: lock protecting I/O operations
  * @irq_lock: IRQ bus lock
  * @dev: device, mostly for dev_dbg()
+ * @irq_domain: IRQ domain
  * @client: client - i2c or spi
  * @ci: client specific information
  * @partnum: part number
@@ -79,6 +80,7 @@ struct stmpe {
 	struct mutex lock;
 	struct mutex irq_lock;
 	struct device *dev;
+	struct irq_domain *domain;
 	void *client;
 	struct stmpe_client_info *ci;
 	enum stmpe_partnum partnum;
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
new file mode 100644
index 0000000..c79ad5d
--- /dev/null
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -0,0 +1,152 @@
+#ifndef __LINUX_TI_AM335X_TSCADC_MFD_H
+#define __LINUX_TI_AM335X_TSCADC_MFD_H
+
+/*
+ * TI Touch Screen / ADC MFD driver
+ *
+ * Copyright (C) 2012 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.
+ */
+
+#include <linux/mfd/core.h>
+
+#define REG_RAWIRQSTATUS	0x024
+#define REG_IRQSTATUS		0x028
+#define REG_IRQENABLE		0x02C
+#define REG_IRQCLR		0x030
+#define REG_IRQWAKEUP		0x034
+#define REG_CTRL		0x040
+#define REG_ADCFSM		0x044
+#define REG_CLKDIV		0x04C
+#define REG_SE			0x054
+#define REG_IDLECONFIG		0x058
+#define REG_CHARGECONFIG	0x05C
+#define REG_CHARGEDELAY		0x060
+#define REG_STEPCONFIG(n)	(0x64 + ((n - 1) * 8))
+#define REG_STEPDELAY(n)	(0x68 + ((n - 1) * 8))
+#define REG_FIFO0CNT		0xE4
+#define REG_FIFO0THR		0xE8
+#define REG_FIFO1CNT		0xF0
+#define REG_FIFO1THR		0xF4
+#define REG_FIFO0		0x100
+#define REG_FIFO1		0x200
+
+/*	Register Bitfields	*/
+/* IRQ wakeup enable */
+#define IRQWKUP_ENB		BIT(0)
+
+/* Step Enable */
+#define STEPENB_MASK		(0x1FFFF << 0)
+#define STEPENB(val)		((val) << 0)
+#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_FIFO1THRES	BIT(5)
+#define IRQENB_PENUP		BIT(9)
+
+/* Step Configuration */
+#define STEPCONFIG_MODE_MASK	(3 << 0)
+#define STEPCONFIG_MODE(val)	((val) << 0)
+#define STEPCONFIG_MODE_HWSYNC	STEPCONFIG_MODE(2)
+#define STEPCONFIG_AVG_MASK	(7 << 2)
+#define STEPCONFIG_AVG(val)	((val) << 2)
+#define STEPCONFIG_AVG_16	STEPCONFIG_AVG(4)
+#define STEPCONFIG_XPP		BIT(5)
+#define STEPCONFIG_XNN		BIT(6)
+#define STEPCONFIG_YPP		BIT(7)
+#define STEPCONFIG_YNN		BIT(8)
+#define STEPCONFIG_XNP		BIT(9)
+#define STEPCONFIG_YPN		BIT(10)
+#define STEPCONFIG_INM_MASK	(0xF << 15)
+#define STEPCONFIG_INM(val)	((val) << 15)
+#define STEPCONFIG_INM_ADCREFM	STEPCONFIG_INM(8)
+#define STEPCONFIG_INP_MASK	(0xF << 19)
+#define STEPCONFIG_INP(val)	((val) << 19)
+#define STEPCONFIG_INP_AN2	STEPCONFIG_INP(2)
+#define STEPCONFIG_INP_AN3	STEPCONFIG_INP(3)
+#define STEPCONFIG_INP_AN4	STEPCONFIG_INP(4)
+#define STEPCONFIG_INP_ADCREFM	STEPCONFIG_INP(8)
+#define STEPCONFIG_FIFO1	BIT(26)
+
+/* Delay register */
+#define STEPDELAY_OPEN_MASK	(0x3FFFF << 0)
+#define STEPDELAY_OPEN(val)	((val) << 0)
+#define STEPCONFIG_OPENDLY	STEPDELAY_OPEN(0x098)
+#define STEPDELAY_SAMPLE_MASK	(0xFF << 24)
+#define STEPDELAY_SAMPLE(val)	((val) << 24)
+#define STEPCONFIG_SAMPLEDLY	STEPDELAY_SAMPLE(0)
+
+/* Charge Config */
+#define STEPCHARGE_RFP_MASK	(7 << 12)
+#define STEPCHARGE_RFP(val)	((val) << 12)
+#define STEPCHARGE_RFP_XPUL	STEPCHARGE_RFP(1)
+#define STEPCHARGE_INM_MASK	(0xF << 15)
+#define STEPCHARGE_INM(val)	((val) << 15)
+#define STEPCHARGE_INM_AN1	STEPCHARGE_INM(1)
+#define STEPCHARGE_INP_MASK	(0xF << 19)
+#define STEPCHARGE_INP(val)	((val) << 19)
+#define STEPCHARGE_INP_AN1	STEPCHARGE_INP(1)
+#define STEPCHARGE_RFM_MASK	(3 << 23)
+#define STEPCHARGE_RFM(val)	((val) << 23)
+#define STEPCHARGE_RFM_XNUR	STEPCHARGE_RFM(1)
+
+/* Charge delay */
+#define CHARGEDLY_OPEN_MASK	(0x3FFFF << 0)
+#define CHARGEDLY_OPEN(val)	((val) << 0)
+#define CHARGEDLY_OPENDLY	CHARGEDLY_OPEN(1)
+
+/* Control register */
+#define CNTRLREG_TSCSSENB	BIT(0)
+#define CNTRLREG_STEPID		BIT(1)
+#define CNTRLREG_STEPCONFIGWRT	BIT(2)
+#define CNTRLREG_POWERDOWN	BIT(4)
+#define CNTRLREG_AFE_CTRL_MASK	(3 << 5)
+#define CNTRLREG_AFE_CTRL(val)	((val) << 5)
+#define CNTRLREG_4WIRE		CNTRLREG_AFE_CTRL(1)
+#define CNTRLREG_5WIRE		CNTRLREG_AFE_CTRL(2)
+#define CNTRLREG_8WIRE		CNTRLREG_AFE_CTRL(3)
+#define CNTRLREG_TSCENB		BIT(7)
+
+#define ADC_CLK			3000000
+#define	MAX_CLK_DIV		7
+#define TOTAL_STEPS		16
+#define TOTAL_CHANNELS		8
+
+#define TSCADC_CELLS		2
+
+enum tscadc_cells {
+	TSC_CELL,
+	ADC_CELL,
+};
+
+struct mfd_tscadc_board {
+	struct tsc_data *tsc_init;
+	struct adc_data *adc_init;
+};
+
+struct ti_tscadc_dev {
+	struct device *dev;
+	struct regmap *regmap_tscadc;
+	void __iomem *tscadc_base;
+	int irq;
+	struct mfd_cell cells[TSCADC_CELLS];
+
+	/* tsc device */
+	struct titsc *tsc;
+
+	/* adc device */
+	struct adc_device *adc;
+};
+
+#endif
diff --git a/include/linux/mfd/tps65090.h b/include/linux/mfd/tps65090.h
index 6bc31d8..6694cf4 100644
--- a/include/linux/mfd/tps65090.h
+++ b/include/linux/mfd/tps65090.h
@@ -23,37 +23,109 @@
 #define __LINUX_MFD_TPS65090_H
 
 #include <linux/irq.h>
+#include <linux/regmap.h>
+
+/* TPS65090 IRQs */
+enum {
+	TPS65090_IRQ_VAC_STATUS_CHANGE,
+	TPS65090_IRQ_VSYS_STATUS_CHANGE,
+	TPS65090_IRQ_BAT_STATUS_CHANGE,
+	TPS65090_IRQ_CHARGING_STATUS_CHANGE,
+	TPS65090_IRQ_CHARGING_COMPLETE,
+	TPS65090_IRQ_OVERLOAD_DCDC1,
+	TPS65090_IRQ_OVERLOAD_DCDC2,
+	TPS65090_IRQ_OVERLOAD_DCDC3,
+	TPS65090_IRQ_OVERLOAD_FET1,
+	TPS65090_IRQ_OVERLOAD_FET2,
+	TPS65090_IRQ_OVERLOAD_FET3,
+	TPS65090_IRQ_OVERLOAD_FET4,
+	TPS65090_IRQ_OVERLOAD_FET5,
+	TPS65090_IRQ_OVERLOAD_FET6,
+	TPS65090_IRQ_OVERLOAD_FET7,
+};
+
+/* TPS65090 Regulator ID */
+enum {
+	TPS65090_REGULATOR_DCDC1,
+	TPS65090_REGULATOR_DCDC2,
+	TPS65090_REGULATOR_DCDC3,
+	TPS65090_REGULATOR_FET1,
+	TPS65090_REGULATOR_FET2,
+	TPS65090_REGULATOR_FET3,
+	TPS65090_REGULATOR_FET4,
+	TPS65090_REGULATOR_FET5,
+	TPS65090_REGULATOR_FET6,
+	TPS65090_REGULATOR_FET7,
+	TPS65090_REGULATOR_LDO1,
+	TPS65090_REGULATOR_LDO2,
+
+	/* Last entry for maximum ID */
+	TPS65090_REGULATOR_MAX,
+};
 
 struct tps65090 {
-	struct mutex		lock;
 	struct device		*dev;
-	struct i2c_client	*client;
 	struct regmap		*rmap;
-	struct irq_chip		irq_chip;
-	struct mutex		irq_lock;
-	int			irq_base;
-	unsigned int		id;
+	struct regmap_irq_chip_data *irq_data;
 };
 
-struct tps65090_subdev_info {
-	int		id;
-	const char	*name;
-	void		*platform_data;
+/*
+ * struct tps65090_regulator_plat_data
+ *
+ * @reg_init_data: The regulator init data.
+ * @enable_ext_control: Enable extrenal control or not. Only available for
+ *     DCDC1, DCDC2 and DCDC3.
+ * @gpio: Gpio number if external control is enabled and controlled through
+ *     gpio.
+ */
+struct tps65090_regulator_plat_data {
+	struct regulator_init_data *reg_init_data;
+	bool enable_ext_control;
+	int gpio;
 };
 
 struct tps65090_platform_data {
 	int irq_base;
-	int num_subdevs;
-	struct tps65090_subdev_info *subdevs;
+	struct tps65090_regulator_plat_data *reg_pdata[TPS65090_REGULATOR_MAX];
 };
 
 /*
  * NOTE: the functions below are not intended for use outside
  * of the TPS65090 sub-device drivers
  */
-extern int tps65090_write(struct device *dev, int reg, uint8_t val);
-extern int tps65090_read(struct device *dev, int reg, uint8_t *val);
-extern int tps65090_set_bits(struct device *dev, int reg, uint8_t bit_num);
-extern int tps65090_clr_bits(struct device *dev, int reg, uint8_t bit_num);
+static inline int tps65090_write(struct device *dev, int reg, uint8_t val)
+{
+	struct tps65090 *tps = dev_get_drvdata(dev);
+
+	return regmap_write(tps->rmap, reg, val);
+}
+
+static inline int tps65090_read(struct device *dev, int reg, uint8_t *val)
+{
+	struct tps65090 *tps = dev_get_drvdata(dev);
+	unsigned int temp_val;
+	int ret;
+
+	ret = regmap_read(tps->rmap, reg, &temp_val);
+	if (!ret)
+		*val = temp_val;
+	return ret;
+}
+
+static inline int tps65090_set_bits(struct device *dev, int reg,
+		uint8_t bit_num)
+{
+	struct tps65090 *tps = dev_get_drvdata(dev);
+
+	return regmap_update_bits(tps->rmap, reg, BIT(bit_num), ~0u);
+}
+
+static inline int tps65090_clr_bits(struct device *dev, int reg,
+		uint8_t bit_num)
+{
+	struct tps65090 *tps = dev_get_drvdata(dev);
+
+	return regmap_update_bits(tps->rmap, reg, BIT(bit_num), 0u);
+}
 
 #endif /*__LINUX_MFD_TPS65090_H */
diff --git a/include/linux/mfd/tps6586x.h b/include/linux/mfd/tps6586x.h
index 2dd1231..8799454 100644
--- a/include/linux/mfd/tps6586x.h
+++ b/include/linux/mfd/tps6586x.h
@@ -29,6 +29,7 @@ enum {
 	TPS6586X_ID_LDO_8,
 	TPS6586X_ID_LDO_9,
 	TPS6586X_ID_LDO_RTC,
+	TPS6586X_ID_MAX_REGULATOR,
 };
 
 enum {
@@ -79,6 +80,8 @@ struct tps6586x_platform_data {
 	int gpio_base;
 	int irq_base;
 	bool pm_off;
+
+	struct regulator_init_data *reg_init_data[TPS6586X_ID_MAX_REGULATOR];
 };
 
 /*
@@ -93,5 +96,6 @@ extern int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask);
 extern int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask);
 extern int tps6586x_update(struct device *dev, int reg, uint8_t val,
 			   uint8_t mask);
+extern int tps6586x_irq_get_virq(struct device *dev, int irq);
 
 #endif /*__LINUX_MFD_TPS6586X_H */
diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h
index 02e894f..0b16903 100644
--- a/include/linux/mfd/tps65910.h
+++ b/include/linux/mfd/tps65910.h
@@ -572,6 +572,49 @@
 #define SPARE_SPARE_MASK				0xFF
 #define SPARE_SPARE_SHIFT				0
 
+#define TPS65910_INT_STS_RTC_PERIOD_IT_MASK			0x80
+#define TPS65910_INT_STS_RTC_PERIOD_IT_SHIFT			7
+#define TPS65910_INT_STS_RTC_ALARM_IT_MASK			0x40
+#define TPS65910_INT_STS_RTC_ALARM_IT_SHIFT			6
+#define TPS65910_INT_STS_HOTDIE_IT_MASK				0x20
+#define TPS65910_INT_STS_HOTDIE_IT_SHIFT			5
+#define TPS65910_INT_STS_PWRHOLD_F_IT_MASK			0x10
+#define TPS65910_INT_STS_PWRHOLD_F_IT_SHIFT			4
+#define TPS65910_INT_STS_PWRON_LP_IT_MASK			0x08
+#define TPS65910_INT_STS_PWRON_LP_IT_SHIFT			3
+#define TPS65910_INT_STS_PWRON_IT_MASK				0x04
+#define TPS65910_INT_STS_PWRON_IT_SHIFT				2
+#define TPS65910_INT_STS_VMBHI_IT_MASK				0x02
+#define TPS65910_INT_STS_VMBHI_IT_SHIFT				1
+#define TPS65910_INT_STS_VMBDCH_IT_MASK				0x01
+#define TPS65910_INT_STS_VMBDCH_IT_SHIFT			0
+
+#define TPS65910_INT_MSK_RTC_PERIOD_IT_MSK_MASK			0x80
+#define TPS65910_INT_MSK_RTC_PERIOD_IT_MSK_SHIFT		7
+#define TPS65910_INT_MSK_RTC_ALARM_IT_MSK_MASK			0x40
+#define TPS65910_INT_MSK_RTC_ALARM_IT_MSK_SHIFT			6
+#define TPS65910_INT_MSK_HOTDIE_IT_MSK_MASK			0x20
+#define TPS65910_INT_MSK_HOTDIE_IT_MSK_SHIFT			5
+#define TPS65910_INT_MSK_PWRHOLD_IT_MSK_MASK			0x10
+#define TPS65910_INT_MSK_PWRHOLD_IT_MSK_SHIFT			4
+#define TPS65910_INT_MSK_PWRON_LP_IT_MSK_MASK			0x08
+#define TPS65910_INT_MSK_PWRON_LP_IT_MSK_SHIFT			3
+#define TPS65910_INT_MSK_PWRON_IT_MSK_MASK			0x04
+#define TPS65910_INT_MSK_PWRON_IT_MSK_SHIFT			2
+#define TPS65910_INT_MSK_VMBHI_IT_MSK_MASK			0x02
+#define TPS65910_INT_MSK_VMBHI_IT_MSK_SHIFT			1
+#define TPS65910_INT_MSK_VMBDCH_IT_MSK_MASK			0x01
+#define TPS65910_INT_MSK_VMBDCH_IT_MSK_SHIFT			0
+
+#define TPS65910_INT_STS2_GPIO0_F_IT_SHIFT			2
+#define TPS65910_INT_STS2_GPIO0_F_IT_MASK			0x02
+#define TPS65910_INT_STS2_GPIO0_R_IT_SHIFT			1
+#define TPS65910_INT_STS2_GPIO0_R_IT_MASK			0x01
+
+#define TPS65910_INT_MSK2_GPIO0_F_IT_MSK_SHIFT			2
+#define TPS65910_INT_MSK2_GPIO0_F_IT_MSK_MASK			0x02
+#define TPS65910_INT_MSK2_GPIO0_R_IT_MSK_SHIFT			1
+#define TPS65910_INT_MSK2_GPIO0_R_IT_MSK_MASK			0x01
 
 /*Register INT_STS  (0x80) register.RegisterDescription */
 #define INT_STS_RTC_PERIOD_IT_MASK			0x80
@@ -580,16 +623,16 @@
 #define INT_STS_RTC_ALARM_IT_SHIFT			6
 #define INT_STS_HOTDIE_IT_MASK				0x20
 #define INT_STS_HOTDIE_IT_SHIFT				5
-#define INT_STS_PWRHOLD_IT_MASK				0x10
-#define INT_STS_PWRHOLD_IT_SHIFT			4
+#define INT_STS_PWRHOLD_R_IT_MASK			0x10
+#define INT_STS_PWRHOLD_R_IT_SHIFT			4
 #define INT_STS_PWRON_LP_IT_MASK			0x08
 #define INT_STS_PWRON_LP_IT_SHIFT			3
 #define INT_STS_PWRON_IT_MASK				0x04
 #define INT_STS_PWRON_IT_SHIFT				2
 #define INT_STS_VMBHI_IT_MASK				0x02
 #define INT_STS_VMBHI_IT_SHIFT				1
-#define INT_STS_VMBDCH_IT_MASK				0x01
-#define INT_STS_VMBDCH_IT_SHIFT				0
+#define INT_STS_PWRHOLD_F_IT_MASK			0x01
+#define INT_STS_PWRHOLD_F_IT_SHIFT			0
 
 
 /*Register INT_MSK  (0x80) register.RegisterDescription */
@@ -599,16 +642,16 @@
 #define INT_MSK_RTC_ALARM_IT_MSK_SHIFT			6
 #define INT_MSK_HOTDIE_IT_MSK_MASK			0x20
 #define INT_MSK_HOTDIE_IT_MSK_SHIFT			5
-#define INT_MSK_PWRHOLD_IT_MSK_MASK			0x10
-#define INT_MSK_PWRHOLD_IT_MSK_SHIFT			4
+#define INT_MSK_PWRHOLD_R_IT_MSK_MASK			0x10
+#define INT_MSK_PWRHOLD_R_IT_MSK_SHIFT			4
 #define INT_MSK_PWRON_LP_IT_MSK_MASK			0x08
 #define INT_MSK_PWRON_LP_IT_MSK_SHIFT			3
 #define INT_MSK_PWRON_IT_MSK_MASK			0x04
 #define INT_MSK_PWRON_IT_MSK_SHIFT			2
 #define INT_MSK_VMBHI_IT_MSK_MASK			0x02
 #define INT_MSK_VMBHI_IT_MSK_SHIFT			1
-#define INT_MSK_VMBDCH_IT_MSK_MASK			0x01
-#define INT_MSK_VMBDCH_IT_MSK_SHIFT			0
+#define INT_MSK_PWRHOLD_F_IT_MSK_MASK			0x01
+#define INT_MSK_PWRHOLD_F_IT_MSK_SHIFT			0
 
 
 /*Register INT_STS2  (0x80) register.RegisterDescription */
@@ -650,6 +693,14 @@
 
 
 /*Register INT_STS3  (0x80) register.RegisterDescription */
+#define INT_STS3_PWRDN_IT_MASK				0x80
+#define INT_STS3_PWRDN_IT_SHIFT				7
+#define INT_STS3_VMBCH2_L_IT_MASK			0x40
+#define INT_STS3_VMBCH2_L_IT_SHIFT			6
+#define INT_STS3_VMBCH2_H_IT_MASK			0x20
+#define INT_STS3_VMBCH2_H_IT_SHIFT			5
+#define INT_STS3_WTCHDG_IT_MASK				0x10
+#define INT_STS3_WTCHDG_IT_SHIFT			4
 #define INT_STS3_GPIO5_F_IT_MASK			0x08
 #define INT_STS3_GPIO5_F_IT_SHIFT			3
 #define INT_STS3_GPIO5_R_IT_MASK			0x04
@@ -661,6 +712,14 @@
 
 
 /*Register INT_MSK3  (0x80) register.RegisterDescription */
+#define INT_MSK3_PWRDN_IT_MSK_MASK			0x80
+#define INT_MSK3_PWRDN_IT_MSK_SHIFT			7
+#define INT_MSK3_VMBCH2_L_IT_MSK_MASK			0x40
+#define INT_MSK3_VMBCH2_L_IT_MSK_SHIFT			6
+#define INT_MSK3_VMBCH2_H_IT_MSK_MASK			0x20
+#define INT_MSK3_VMBCH2_H_IT_MSK_SHIFT			5
+#define INT_MSK3_WTCHDG_IT_MSK_MASK			0x10
+#define INT_MSK3_WTCHDG_IT_MSK_SHIFT			4
 #define INT_MSK3_GPIO5_F_IT_MSK_MASK			0x08
 #define INT_MSK3_GPIO5_F_IT_MSK_SHIFT			3
 #define INT_MSK3_GPIO5_R_IT_MSK_MASK			0x04
@@ -721,34 +780,32 @@
 #define TPS65910_IRQ_GPIO_F				9
 #define TPS65910_NUM_IRQ				10
 
-#define TPS65911_IRQ_VBAT_VMBDCH			0
-#define TPS65911_IRQ_VBAT_VMBDCH2L			1
-#define TPS65911_IRQ_VBAT_VMBDCH2H			2
-#define TPS65911_IRQ_VBAT_VMHI				3
-#define TPS65911_IRQ_PWRON				4
-#define TPS65911_IRQ_PWRON_LP				5
-#define TPS65911_IRQ_PWRHOLD_F				6
-#define TPS65911_IRQ_PWRHOLD_R				7
-#define TPS65911_IRQ_HOTDIE				8
-#define TPS65911_IRQ_RTC_ALARM				9
-#define TPS65911_IRQ_RTC_PERIOD				10
-#define TPS65911_IRQ_GPIO0_R				11
-#define TPS65911_IRQ_GPIO0_F				12
-#define TPS65911_IRQ_GPIO1_R				13
-#define TPS65911_IRQ_GPIO1_F				14
-#define TPS65911_IRQ_GPIO2_R				15
-#define TPS65911_IRQ_GPIO2_F				16
-#define TPS65911_IRQ_GPIO3_R				17
-#define TPS65911_IRQ_GPIO3_F				18
-#define TPS65911_IRQ_GPIO4_R				19
-#define TPS65911_IRQ_GPIO4_F				20
-#define TPS65911_IRQ_GPIO5_R				21
-#define TPS65911_IRQ_GPIO5_F				22
-#define TPS65911_IRQ_WTCHDG				23
-#define TPS65911_IRQ_PWRDN				24
-
-#define TPS65911_NUM_IRQ				25
-
+#define TPS65911_IRQ_PWRHOLD_F				0
+#define TPS65911_IRQ_VBAT_VMHI				1
+#define TPS65911_IRQ_PWRON				2
+#define TPS65911_IRQ_PWRON_LP				3
+#define TPS65911_IRQ_PWRHOLD_R				4
+#define TPS65911_IRQ_HOTDIE				5
+#define TPS65911_IRQ_RTC_ALARM				6
+#define TPS65911_IRQ_RTC_PERIOD				7
+#define TPS65911_IRQ_GPIO0_R				8
+#define TPS65911_IRQ_GPIO0_F				9
+#define TPS65911_IRQ_GPIO1_R				10
+#define TPS65911_IRQ_GPIO1_F				11
+#define TPS65911_IRQ_GPIO2_R				12
+#define TPS65911_IRQ_GPIO2_F				13
+#define TPS65911_IRQ_GPIO3_R				14
+#define TPS65911_IRQ_GPIO3_F				15
+#define TPS65911_IRQ_GPIO4_R				16
+#define TPS65911_IRQ_GPIO4_F				17
+#define TPS65911_IRQ_GPIO5_R				18
+#define TPS65911_IRQ_GPIO5_F				19
+#define TPS65911_IRQ_WTCHDG				20
+#define TPS65911_IRQ_VMBCH2_H				21
+#define TPS65911_IRQ_VMBCH2_L				22
+#define TPS65911_IRQ_PWRDN				23
+
+#define TPS65911_NUM_IRQ				24
 
 /* GPIO Register Definitions */
 #define TPS65910_GPIO_DEB				BIT(2)
@@ -848,11 +905,8 @@ struct tps65910 {
 	struct tps65910_board *of_plat_data;
 
 	/* IRQ Handling */
-	struct mutex irq_lock;
 	int chip_irq;
-	int irq_base;
-	int irq_num;
-	u32 irq_mask;
+	struct regmap_irq_chip_data *irq_data;
 	struct irq_domain *domain;
 };
 
@@ -861,10 +915,6 @@ struct tps65910_platform_data {
 	int irq_base;
 };
 
-int tps65910_irq_init(struct tps65910 *tps65910, int irq,
-		struct tps65910_platform_data *pdata);
-int tps65910_irq_exit(struct tps65910 *tps65910);
-
 static inline int tps65910_chip_id(struct tps65910 *tps65910)
 {
 	return tps65910->id;
@@ -900,4 +950,9 @@ static inline int tps65910_reg_update_bits(struct tps65910 *tps65910, u8 reg,
 	return regmap_update_bits(tps65910->regmap, reg, mask, val);
 }
 
+static inline int tps65910_irq_get_virq(struct tps65910 *tps65910, int irq)
+{
+	return regmap_irq_get_virq(tps65910->irq_data, irq);
+}
+
 #endif /*  __LINUX_MFD_TPS65910_H */
diff --git a/include/linux/mfd/tps80031.h b/include/linux/mfd/tps80031.h
new file mode 100644
index 0000000..2c75c9c
--- /dev/null
+++ b/include/linux/mfd/tps80031.h
@@ -0,0 +1,637 @@
+/*
+ * tps80031.h -- TI TPS80031 and TI TPS80032 PMIC driver.
+ *
+ * Copyright (c) 2012, 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
+ */
+
+#ifndef __LINUX_MFD_TPS80031_H
+#define __LINUX_MFD_TPS80031_H
+
+#include <linux/device.h>
+#include <linux/regmap.h>
+
+/* Pull-ups/Pull-downs */
+#define TPS80031_CFG_INPUT_PUPD1			0xF0
+#define TPS80031_CFG_INPUT_PUPD2			0xF1
+#define TPS80031_CFG_INPUT_PUPD3			0xF2
+#define TPS80031_CFG_INPUT_PUPD4			0xF3
+#define TPS80031_CFG_LDO_PD1				0xF4
+#define TPS80031_CFG_LDO_PD2				0xF5
+#define TPS80031_CFG_SMPS_PD				0xF6
+
+/* Real Time Clock */
+#define TPS80031_SECONDS_REG				0x00
+#define TPS80031_MINUTES_REG				0x01
+#define TPS80031_HOURS_REG				0x02
+#define TPS80031_DAYS_REG				0x03
+#define TPS80031_MONTHS_REG				0x04
+#define TPS80031_YEARS_REG				0x05
+#define TPS80031_WEEKS_REG				0x06
+#define TPS80031_ALARM_SECONDS_REG			0x08
+#define TPS80031_ALARM_MINUTES_REG			0x09
+#define TPS80031_ALARM_HOURS_REG			0x0A
+#define TPS80031_ALARM_DAYS_REG				0x0B
+#define TPS80031_ALARM_MONTHS_REG			0x0C
+#define TPS80031_ALARM_YEARS_REG			0x0D
+#define TPS80031_RTC_CTRL_REG				0x10
+#define TPS80031_RTC_STATUS_REG				0x11
+#define TPS80031_RTC_INTERRUPTS_REG			0x12
+#define TPS80031_RTC_COMP_LSB_REG			0x13
+#define TPS80031_RTC_COMP_MSB_REG			0x14
+#define TPS80031_RTC_RESET_STATUS_REG			0x16
+
+/*PMC Master Module */
+#define TPS80031_PHOENIX_START_CONDITION		0x1F
+#define TPS80031_PHOENIX_MSK_TRANSITION			0x20
+#define TPS80031_STS_HW_CONDITIONS			0x21
+#define TPS80031_PHOENIX_LAST_TURNOFF_STS		0x22
+#define TPS80031_VSYSMIN_LO_THRESHOLD			0x23
+#define TPS80031_VSYSMIN_HI_THRESHOLD			0x24
+#define TPS80031_PHOENIX_DEV_ON				0x25
+#define TPS80031_STS_PWR_GRP_STATE			0x27
+#define TPS80031_PH_CFG_VSYSLOW				0x28
+#define TPS80031_PH_STS_BOOT				0x29
+#define TPS80031_PHOENIX_SENS_TRANSITION		0x2A
+#define TPS80031_PHOENIX_SEQ_CFG			0x2B
+#define TPS80031_PRIMARY_WATCHDOG_CFG			0X2C
+#define TPS80031_KEY_PRESS_DUR_CFG			0X2D
+#define TPS80031_SMPS_LDO_SHORT_STS			0x2E
+
+/* PMC Slave Module - Broadcast */
+#define TPS80031_BROADCAST_ADDR_ALL			0x31
+#define TPS80031_BROADCAST_ADDR_REF			0x32
+#define TPS80031_BROADCAST_ADDR_PROV			0x33
+#define TPS80031_BROADCAST_ADDR_CLK_RST			0x34
+
+/* PMC Slave Module  SMPS Regulators */
+#define TPS80031_SMPS4_CFG_TRANS			0x41
+#define TPS80031_SMPS4_CFG_STATE			0x42
+#define TPS80031_SMPS4_CFG_VOLTAGE			0x44
+#define TPS80031_VIO_CFG_TRANS				0x47
+#define TPS80031_VIO_CFG_STATE				0x48
+#define TPS80031_VIO_CFG_FORCE				0x49
+#define TPS80031_VIO_CFG_VOLTAGE			0x4A
+#define TPS80031_VIO_CFG_STEP				0x48
+#define TPS80031_SMPS1_CFG_TRANS			0x53
+#define TPS80031_SMPS1_CFG_STATE			0x54
+#define TPS80031_SMPS1_CFG_FORCE			0x55
+#define TPS80031_SMPS1_CFG_VOLTAGE			0x56
+#define TPS80031_SMPS1_CFG_STEP				0x57
+#define TPS80031_SMPS2_CFG_TRANS			0x59
+#define TPS80031_SMPS2_CFG_STATE			0x5A
+#define TPS80031_SMPS2_CFG_FORCE			0x5B
+#define TPS80031_SMPS2_CFG_VOLTAGE			0x5C
+#define TPS80031_SMPS2_CFG_STEP				0x5D
+#define TPS80031_SMPS3_CFG_TRANS			0x65
+#define TPS80031_SMPS3_CFG_STATE			0x66
+#define TPS80031_SMPS3_CFG_VOLTAGE			0x68
+
+/* PMC Slave Module  LDO Regulators */
+#define TPS80031_VANA_CFG_TRANS				0x81
+#define TPS80031_VANA_CFG_STATE				0x82
+#define TPS80031_VANA_CFG_VOLTAGE			0x83
+#define TPS80031_LDO2_CFG_TRANS				0x85
+#define TPS80031_LDO2_CFG_STATE				0x86
+#define TPS80031_LDO2_CFG_VOLTAGE			0x87
+#define TPS80031_LDO4_CFG_TRANS				0x89
+#define TPS80031_LDO4_CFG_STATE				0x8A
+#define TPS80031_LDO4_CFG_VOLTAGE			0x8B
+#define TPS80031_LDO3_CFG_TRANS				0x8D
+#define TPS80031_LDO3_CFG_STATE				0x8E
+#define TPS80031_LDO3_CFG_VOLTAGE			0x8F
+#define TPS80031_LDO6_CFG_TRANS				0x91
+#define TPS80031_LDO6_CFG_STATE				0x92
+#define TPS80031_LDO6_CFG_VOLTAGE			0x93
+#define TPS80031_LDOLN_CFG_TRANS			0x95
+#define TPS80031_LDOLN_CFG_STATE			0x96
+#define TPS80031_LDOLN_CFG_VOLTAGE			0x97
+#define TPS80031_LDO5_CFG_TRANS				0x99
+#define TPS80031_LDO5_CFG_STATE				0x9A
+#define TPS80031_LDO5_CFG_VOLTAGE			0x9B
+#define TPS80031_LDO1_CFG_TRANS				0x9D
+#define TPS80031_LDO1_CFG_STATE				0x9E
+#define TPS80031_LDO1_CFG_VOLTAGE			0x9F
+#define TPS80031_LDOUSB_CFG_TRANS			0xA1
+#define TPS80031_LDOUSB_CFG_STATE			0xA2
+#define TPS80031_LDOUSB_CFG_VOLTAGE			0xA3
+#define TPS80031_LDO7_CFG_TRANS				0xA5
+#define TPS80031_LDO7_CFG_STATE				0xA6
+#define TPS80031_LDO7_CFG_VOLTAGE			0xA7
+
+/* PMC Slave Module  External Control */
+#define TPS80031_REGEN1_CFG_TRANS			0xAE
+#define TPS80031_REGEN1_CFG_STATE			0xAF
+#define TPS80031_REGEN2_CFG_TRANS			0xB1
+#define TPS80031_REGEN2_CFG_STATE			0xB2
+#define TPS80031_SYSEN_CFG_TRANS			0xB4
+#define TPS80031_SYSEN_CFG_STATE			0xB5
+
+/* PMC Slave Module  Internal Control */
+#define TPS80031_NRESPWRON_CFG_TRANS			0xB7
+#define TPS80031_NRESPWRON_CFG_STATE			0xB8
+#define TPS80031_CLK32KAO_CFG_TRANS			0xBA
+#define TPS80031_CLK32KAO_CFG_STATE			0xBB
+#define TPS80031_CLK32KG_CFG_TRANS			0xBD
+#define TPS80031_CLK32KG_CFG_STATE			0xBE
+#define TPS80031_CLK32KAUDIO_CFG_TRANS			0xC0
+#define TPS80031_CLK32KAUDIO_CFG_STATE			0xC1
+#define TPS80031_VRTC_CFG_TRANS				0xC3
+#define TPS80031_VRTC_CFG_STATE				0xC4
+#define TPS80031_BIAS_CFG_TRANS				0xC6
+#define TPS80031_BIAS_CFG_STATE				0xC7
+#define TPS80031_VSYSMIN_HI_CFG_TRANS			0xC9
+#define TPS80031_VSYSMIN_HI_CFG_STATE			0xCA
+#define TPS80031_RC6MHZ_CFG_TRANS			0xCC
+#define TPS80031_RC6MHZ_CFG_STATE			0xCD
+#define TPS80031_TMP_CFG_TRANS				0xCF
+#define TPS80031_TMP_CFG_STATE				0xD0
+
+/* PMC Slave Module  resources assignment */
+#define TPS80031_PREQ1_RES_ASS_A			0xD7
+#define TPS80031_PREQ1_RES_ASS_B			0xD8
+#define TPS80031_PREQ1_RES_ASS_C			0xD9
+#define TPS80031_PREQ2_RES_ASS_A			0xDA
+#define TPS80031_PREQ2_RES_ASS_B			0xDB
+#define TPS80031_PREQ2_RES_ASS_C			0xDC
+#define TPS80031_PREQ3_RES_ASS_A			0xDD
+#define TPS80031_PREQ3_RES_ASS_B			0xDE
+#define TPS80031_PREQ3_RES_ASS_C			0xDF
+
+/* PMC Slave Module  Miscellaneous */
+#define TPS80031_SMPS_OFFSET				0xE0
+#define TPS80031_SMPS_MULT				0xE3
+#define TPS80031_MISC1					0xE4
+#define TPS80031_MISC2					0xE5
+#define TPS80031_BBSPOR_CFG				0xE6
+#define TPS80031_TMP_CFG				0xE7
+
+/* Battery Charging Controller and Indicator LED */
+#define TPS80031_CONTROLLER_CTRL2			0xDA
+#define TPS80031_CONTROLLER_VSEL_COMP			0xDB
+#define TPS80031_CHARGERUSB_VSYSREG			0xDC
+#define TPS80031_CHARGERUSB_VICHRG_PC			0xDD
+#define TPS80031_LINEAR_CHRG_STS			0xDE
+#define TPS80031_CONTROLLER_INT_MASK			0xE0
+#define TPS80031_CONTROLLER_CTRL1			0xE1
+#define TPS80031_CONTROLLER_WDG				0xE2
+#define TPS80031_CONTROLLER_STAT1			0xE3
+#define TPS80031_CHARGERUSB_INT_STATUS			0xE4
+#define TPS80031_CHARGERUSB_INT_MASK			0xE5
+#define TPS80031_CHARGERUSB_STATUS_INT1			0xE6
+#define TPS80031_CHARGERUSB_STATUS_INT2			0xE7
+#define TPS80031_CHARGERUSB_CTRL1			0xE8
+#define TPS80031_CHARGERUSB_CTRL2			0xE9
+#define TPS80031_CHARGERUSB_CTRL3			0xEA
+#define TPS80031_CHARGERUSB_STAT1			0xEB
+#define TPS80031_CHARGERUSB_VOREG			0xEC
+#define TPS80031_CHARGERUSB_VICHRG			0xED
+#define TPS80031_CHARGERUSB_CINLIMIT			0xEE
+#define TPS80031_CHARGERUSB_CTRLLIMIT1			0xEF
+#define TPS80031_CHARGERUSB_CTRLLIMIT2			0xF0
+#define TPS80031_LED_PWM_CTRL1				0xF4
+#define TPS80031_LED_PWM_CTRL2				0xF5
+
+/* USB On-The-Go  */
+#define TPS80031_BACKUP_REG				0xFA
+#define TPS80031_USB_VENDOR_ID_LSB			0x00
+#define TPS80031_USB_VENDOR_ID_MSB			0x01
+#define TPS80031_USB_PRODUCT_ID_LSB			0x02
+#define TPS80031_USB_PRODUCT_ID_MSB			0x03
+#define TPS80031_USB_VBUS_CTRL_SET			0x04
+#define TPS80031_USB_VBUS_CTRL_CLR			0x05
+#define TPS80031_USB_ID_CTRL_SET			0x06
+#define TPS80031_USB_ID_CTRL_CLR			0x07
+#define TPS80031_USB_VBUS_INT_SRC			0x08
+#define TPS80031_USB_VBUS_INT_LATCH_SET			0x09
+#define TPS80031_USB_VBUS_INT_LATCH_CLR			0x0A
+#define TPS80031_USB_VBUS_INT_EN_LO_SET			0x0B
+#define TPS80031_USB_VBUS_INT_EN_LO_CLR			0x0C
+#define TPS80031_USB_VBUS_INT_EN_HI_SET			0x0D
+#define TPS80031_USB_VBUS_INT_EN_HI_CLR			0x0E
+#define TPS80031_USB_ID_INT_SRC				0x0F
+#define TPS80031_USB_ID_INT_LATCH_SET			0x10
+#define TPS80031_USB_ID_INT_LATCH_CLR			0x11
+#define TPS80031_USB_ID_INT_EN_LO_SET			0x12
+#define TPS80031_USB_ID_INT_EN_LO_CLR			0x13
+#define TPS80031_USB_ID_INT_EN_HI_SET			0x14
+#define TPS80031_USB_ID_INT_EN_HI_CLR			0x15
+#define TPS80031_USB_OTG_ADP_CTRL			0x16
+#define TPS80031_USB_OTG_ADP_HIGH			0x17
+#define TPS80031_USB_OTG_ADP_LOW			0x18
+#define TPS80031_USB_OTG_ADP_RISE			0x19
+#define TPS80031_USB_OTG_REVISION			0x1A
+
+/* Gas Gauge */
+#define TPS80031_FG_REG_00				0xC0
+#define TPS80031_FG_REG_01				0xC1
+#define TPS80031_FG_REG_02				0xC2
+#define TPS80031_FG_REG_03				0xC3
+#define TPS80031_FG_REG_04				0xC4
+#define TPS80031_FG_REG_05				0xC5
+#define TPS80031_FG_REG_06				0xC6
+#define TPS80031_FG_REG_07				0xC7
+#define TPS80031_FG_REG_08				0xC8
+#define TPS80031_FG_REG_09				0xC9
+#define TPS80031_FG_REG_10				0xCA
+#define TPS80031_FG_REG_11				0xCB
+
+/* General Purpose ADC */
+#define TPS80031_GPADC_CTRL				0x2E
+#define TPS80031_GPADC_CTRL2				0x2F
+#define TPS80031_RTSELECT_LSB				0x32
+#define TPS80031_RTSELECT_ISB				0x33
+#define TPS80031_RTSELECT_MSB				0x34
+#define TPS80031_GPSELECT_ISB				0x35
+#define TPS80031_CTRL_P1				0x36
+#define TPS80031_RTCH0_LSB				0x37
+#define TPS80031_RTCH0_MSB				0x38
+#define TPS80031_RTCH1_LSB				0x39
+#define TPS80031_RTCH1_MSB				0x3A
+#define TPS80031_GPCH0_LSB				0x3B
+#define TPS80031_GPCH0_MSB				0x3C
+
+/* SIM, MMC and Battery Detection */
+#define TPS80031_SIMDEBOUNCING				0xEB
+#define TPS80031_SIMCTRL				0xEC
+#define TPS80031_MMCDEBOUNCING				0xED
+#define TPS80031_MMCCTRL				0xEE
+#define TPS80031_BATDEBOUNCING				0xEF
+
+/* Vibrator Driver and PWMs */
+#define TPS80031_VIBCTRL				0x9B
+#define TPS80031_VIBMODE				0x9C
+#define TPS80031_PWM1ON					0xBA
+#define TPS80031_PWM1OFF				0xBB
+#define TPS80031_PWM2ON					0xBD
+#define TPS80031_PWM2OFF				0xBE
+
+/* Control Interface */
+#define TPS80031_INT_STS_A				0xD0
+#define TPS80031_INT_STS_B				0xD1
+#define TPS80031_INT_STS_C				0xD2
+#define TPS80031_INT_MSK_LINE_A				0xD3
+#define TPS80031_INT_MSK_LINE_B				0xD4
+#define TPS80031_INT_MSK_LINE_C				0xD5
+#define TPS80031_INT_MSK_STS_A				0xD6
+#define TPS80031_INT_MSK_STS_B				0xD7
+#define TPS80031_INT_MSK_STS_C				0xD8
+#define TPS80031_TOGGLE1				0x90
+#define TPS80031_TOGGLE2				0x91
+#define TPS80031_TOGGLE3				0x92
+#define TPS80031_PWDNSTATUS1				0x93
+#define TPS80031_PWDNSTATUS2				0x94
+#define TPS80031_VALIDITY0				0x17
+#define TPS80031_VALIDITY1				0x18
+#define TPS80031_VALIDITY2				0x19
+#define TPS80031_VALIDITY3				0x1A
+#define TPS80031_VALIDITY4				0x1B
+#define TPS80031_VALIDITY5				0x1C
+#define TPS80031_VALIDITY6				0x1D
+#define TPS80031_VALIDITY7				0x1E
+
+/* Version number related register */
+#define TPS80031_JTAGVERNUM				0x87
+#define TPS80031_EPROM_REV				0xDF
+
+/* GPADC Trimming Bits. */
+#define TPS80031_GPADC_TRIM0				0xCC
+#define TPS80031_GPADC_TRIM1				0xCD
+#define TPS80031_GPADC_TRIM2				0xCE
+#define TPS80031_GPADC_TRIM3				0xCF
+#define TPS80031_GPADC_TRIM4				0xD0
+#define TPS80031_GPADC_TRIM5				0xD1
+#define TPS80031_GPADC_TRIM6				0xD2
+#define TPS80031_GPADC_TRIM7				0xD3
+#define TPS80031_GPADC_TRIM8				0xD4
+#define TPS80031_GPADC_TRIM9				0xD5
+#define TPS80031_GPADC_TRIM10				0xD6
+#define TPS80031_GPADC_TRIM11				0xD7
+#define TPS80031_GPADC_TRIM12				0xD8
+#define TPS80031_GPADC_TRIM13				0xD9
+#define TPS80031_GPADC_TRIM14				0xDA
+#define TPS80031_GPADC_TRIM15				0xDB
+#define TPS80031_GPADC_TRIM16				0xDC
+#define TPS80031_GPADC_TRIM17				0xDD
+#define TPS80031_GPADC_TRIM18				0xDE
+
+/* TPS80031_CONTROLLER_STAT1 bit fields */
+#define TPS80031_CONTROLLER_STAT1_BAT_TEMP		0
+#define TPS80031_CONTROLLER_STAT1_BAT_REMOVED		1
+#define TPS80031_CONTROLLER_STAT1_VBUS_DET		2
+#define TPS80031_CONTROLLER_STAT1_VAC_DET		3
+#define TPS80031_CONTROLLER_STAT1_FAULT_WDG		4
+#define TPS80031_CONTROLLER_STAT1_LINCH_GATED		6
+/* TPS80031_CONTROLLER_INT_MASK bit filed */
+#define TPS80031_CONTROLLER_INT_MASK_MVAC_DET		0
+#define TPS80031_CONTROLLER_INT_MASK_MVBUS_DET		1
+#define TPS80031_CONTROLLER_INT_MASK_MBAT_TEMP		2
+#define TPS80031_CONTROLLER_INT_MASK_MFAULT_WDG		3
+#define TPS80031_CONTROLLER_INT_MASK_MBAT_REMOVED	4
+#define TPS80031_CONTROLLER_INT_MASK_MLINCH_GATED	5
+
+#define TPS80031_CHARGE_CONTROL_SUB_INT_MASK		0x3F
+
+/* TPS80031_PHOENIX_DEV_ON bit field */
+#define TPS80031_DEVOFF					0x1
+
+#define TPS80031_EXT_CONTROL_CFG_TRANS			0
+#define TPS80031_EXT_CONTROL_CFG_STATE			1
+
+/* State register field */
+#define TPS80031_STATE_OFF				0x00
+#define TPS80031_STATE_ON				0x01
+#define TPS80031_STATE_MASK				0x03
+
+/* Trans register field */
+#define TPS80031_TRANS_ACTIVE_OFF			0x00
+#define TPS80031_TRANS_ACTIVE_ON			0x01
+#define TPS80031_TRANS_ACTIVE_MASK			0x03
+#define TPS80031_TRANS_SLEEP_OFF			0x00
+#define TPS80031_TRANS_SLEEP_ON				0x04
+#define TPS80031_TRANS_SLEEP_MASK			0x0C
+#define TPS80031_TRANS_OFF_OFF				0x00
+#define TPS80031_TRANS_OFF_ACTIVE			0x10
+#define TPS80031_TRANS_OFF_MASK				0x30
+
+#define TPS80031_EXT_PWR_REQ		(TPS80031_PWR_REQ_INPUT_PREQ1 | \
+					TPS80031_PWR_REQ_INPUT_PREQ2 | \
+					TPS80031_PWR_REQ_INPUT_PREQ3)
+
+/* TPS80031_BBSPOR_CFG bit field */
+#define TPS80031_BBSPOR_CHG_EN				0x8
+#define TPS80031_MAX_REGISTER				0xFF
+
+struct i2c_client;
+
+/* Supported chips */
+enum chips {
+	TPS80031 = 0x00000001,
+	TPS80032 = 0x00000002,
+};
+
+enum {
+	TPS80031_INT_PWRON,
+	TPS80031_INT_RPWRON,
+	TPS80031_INT_SYS_VLOW,
+	TPS80031_INT_RTC_ALARM,
+	TPS80031_INT_RTC_PERIOD,
+	TPS80031_INT_HOT_DIE,
+	TPS80031_INT_VXX_SHORT,
+	TPS80031_INT_SPDURATION,
+	TPS80031_INT_WATCHDOG,
+	TPS80031_INT_BAT,
+	TPS80031_INT_SIM,
+	TPS80031_INT_MMC,
+	TPS80031_INT_RES,
+	TPS80031_INT_GPADC_RT,
+	TPS80031_INT_GPADC_SW2_EOC,
+	TPS80031_INT_CC_AUTOCAL,
+	TPS80031_INT_ID_WKUP,
+	TPS80031_INT_VBUSS_WKUP,
+	TPS80031_INT_ID,
+	TPS80031_INT_VBUS,
+	TPS80031_INT_CHRG_CTRL,
+	TPS80031_INT_EXT_CHRG,
+	TPS80031_INT_INT_CHRG,
+	TPS80031_INT_RES2,
+	TPS80031_INT_BAT_TEMP_OVRANGE,
+	TPS80031_INT_BAT_REMOVED,
+	TPS80031_INT_VBUS_DET,
+	TPS80031_INT_VAC_DET,
+	TPS80031_INT_FAULT_WDG,
+	TPS80031_INT_LINCH_GATED,
+
+	/* Last interrupt id to get the end number */
+	TPS80031_INT_NR,
+};
+
+/* TPS80031 Slave IDs */
+#define TPS80031_NUM_SLAVES				4
+#define TPS80031_SLAVE_ID0				0
+#define TPS80031_SLAVE_ID1				1
+#define TPS80031_SLAVE_ID2				2
+#define TPS80031_SLAVE_ID3				3
+
+/* TPS80031 I2C addresses */
+#define TPS80031_I2C_ID0_ADDR				0x12
+#define TPS80031_I2C_ID1_ADDR				0x48
+#define TPS80031_I2C_ID2_ADDR				0x49
+#define TPS80031_I2C_ID3_ADDR				0x4A
+
+enum {
+	TPS80031_REGULATOR_VIO,
+	TPS80031_REGULATOR_SMPS1,
+	TPS80031_REGULATOR_SMPS2,
+	TPS80031_REGULATOR_SMPS3,
+	TPS80031_REGULATOR_SMPS4,
+	TPS80031_REGULATOR_VANA,
+	TPS80031_REGULATOR_LDO1,
+	TPS80031_REGULATOR_LDO2,
+	TPS80031_REGULATOR_LDO3,
+	TPS80031_REGULATOR_LDO4,
+	TPS80031_REGULATOR_LDO5,
+	TPS80031_REGULATOR_LDO6,
+	TPS80031_REGULATOR_LDO7,
+	TPS80031_REGULATOR_LDOLN,
+	TPS80031_REGULATOR_LDOUSB,
+	TPS80031_REGULATOR_VBUS,
+	TPS80031_REGULATOR_REGEN1,
+	TPS80031_REGULATOR_REGEN2,
+	TPS80031_REGULATOR_SYSEN,
+	TPS80031_REGULATOR_MAX,
+};
+
+/* Different configurations for the rails */
+enum {
+	/* USBLDO input selection */
+	TPS80031_USBLDO_INPUT_VSYS		= 0x00000001,
+	TPS80031_USBLDO_INPUT_PMID		= 0x00000002,
+
+	/* LDO3 output mode */
+	TPS80031_LDO3_OUTPUT_VIB		= 0x00000004,
+
+	/* VBUS configuration */
+	TPS80031_VBUS_DISCHRG_EN_PDN		= 0x00000004,
+	TPS80031_VBUS_SW_ONLY			= 0x00000008,
+	TPS80031_VBUS_SW_N_ID			= 0x00000010,
+};
+
+/* External controls requests */
+enum tps80031_ext_control {
+	TPS80031_PWR_REQ_INPUT_NONE		= 0x00000000,
+	TPS80031_PWR_REQ_INPUT_PREQ1		= 0x00000001,
+	TPS80031_PWR_REQ_INPUT_PREQ2		= 0x00000002,
+	TPS80031_PWR_REQ_INPUT_PREQ3		= 0x00000004,
+	TPS80031_PWR_OFF_ON_SLEEP		= 0x00000008,
+	TPS80031_PWR_ON_ON_SLEEP		= 0x00000010,
+};
+
+enum tps80031_pupd_pins {
+	TPS80031_PREQ1 = 0,
+	TPS80031_PREQ2A,
+	TPS80031_PREQ2B,
+	TPS80031_PREQ2C,
+	TPS80031_PREQ3,
+	TPS80031_NRES_WARM,
+	TPS80031_PWM_FORCE,
+	TPS80031_CHRG_EXT_CHRG_STATZ,
+	TPS80031_SIM,
+	TPS80031_MMC,
+	TPS80031_GPADC_START,
+	TPS80031_DVSI2C_SCL,
+	TPS80031_DVSI2C_SDA,
+	TPS80031_CTLI2C_SCL,
+	TPS80031_CTLI2C_SDA,
+};
+
+enum tps80031_pupd_settings {
+	TPS80031_PUPD_NORMAL,
+	TPS80031_PUPD_PULLDOWN,
+	TPS80031_PUPD_PULLUP,
+};
+
+struct tps80031 {
+	struct device		*dev;
+	unsigned long		chip_info;
+	int			es_version;
+	struct i2c_client	*clients[TPS80031_NUM_SLAVES];
+	struct regmap		*regmap[TPS80031_NUM_SLAVES];
+	struct regmap_irq_chip_data *irq_data;
+};
+
+struct tps80031_pupd_init_data {
+	int input_pin;
+	int setting;
+};
+
+/*
+ * struct tps80031_regulator_platform_data - tps80031 regulator platform data.
+ *
+ * @reg_init_data: The regulator init data.
+ * @ext_ctrl_flag: External control flag for sleep/power request control.
+ * @config_flags: Configuration flag to configure the rails.
+ *		  It should be ORed of config enums.
+ */
+
+struct tps80031_regulator_platform_data {
+	struct regulator_init_data *reg_init_data;
+	unsigned int ext_ctrl_flag;
+	unsigned int config_flags;
+};
+
+struct tps80031_platform_data {
+	int irq_base;
+	bool use_power_off;
+	struct tps80031_pupd_init_data *pupd_init_data;
+	int pupd_init_data_size;
+	struct tps80031_regulator_platform_data
+			*regulator_pdata[TPS80031_REGULATOR_MAX];
+};
+
+static inline int tps80031_write(struct device *dev, int sid,
+		int reg, uint8_t val)
+{
+	struct tps80031 *tps80031 = dev_get_drvdata(dev);
+
+	return regmap_write(tps80031->regmap[sid], reg, val);
+}
+
+static inline int tps80031_writes(struct device *dev, int sid, int reg,
+		int len, uint8_t *val)
+{
+	struct tps80031 *tps80031 = dev_get_drvdata(dev);
+
+	return regmap_bulk_write(tps80031->regmap[sid], reg, val, len);
+}
+
+static inline int tps80031_read(struct device *dev, int sid,
+		int reg, uint8_t *val)
+{
+	struct tps80031 *tps80031 = dev_get_drvdata(dev);
+	unsigned int ival;
+	int ret;
+
+	ret = regmap_read(tps80031->regmap[sid], reg, &ival);
+	if (ret < 0) {
+		dev_err(dev, "failed reading from reg 0x%02x\n", reg);
+		return ret;
+	}
+
+	*val = ival;
+	return ret;
+}
+
+static inline int tps80031_reads(struct device *dev, int sid,
+		int reg, int len, uint8_t *val)
+{
+	struct tps80031 *tps80031 = dev_get_drvdata(dev);
+
+	return regmap_bulk_read(tps80031->regmap[sid], reg, val, len);
+}
+
+static inline int tps80031_set_bits(struct device *dev, int sid,
+		int reg, uint8_t bit_mask)
+{
+	struct tps80031 *tps80031 = dev_get_drvdata(dev);
+
+	return regmap_update_bits(tps80031->regmap[sid], reg,
+				bit_mask, bit_mask);
+}
+
+static inline int tps80031_clr_bits(struct device *dev, int sid,
+		int reg, uint8_t bit_mask)
+{
+	struct tps80031 *tps80031 = dev_get_drvdata(dev);
+
+	return regmap_update_bits(tps80031->regmap[sid], reg, bit_mask, 0);
+}
+
+static inline int tps80031_update(struct device *dev, int sid,
+		int reg, uint8_t val, uint8_t mask)
+{
+	struct tps80031 *tps80031 = dev_get_drvdata(dev);
+
+	return regmap_update_bits(tps80031->regmap[sid], reg, mask, val);
+}
+
+static inline unsigned long tps80031_get_chip_info(struct device *dev)
+{
+	struct tps80031 *tps80031 = dev_get_drvdata(dev);
+
+	return tps80031->chip_info;
+}
+
+static inline int tps80031_get_pmu_version(struct device *dev)
+{
+	struct tps80031 *tps80031 = dev_get_drvdata(dev);
+
+	return tps80031->es_version;
+}
+
+static inline int tps80031_irq_get_virq(struct device *dev, int irq)
+{
+	struct tps80031 *tps80031 = dev_get_drvdata(dev);
+
+	return regmap_irq_get_virq(tps80031->irq_data, irq);
+}
+
+extern int tps80031_ext_power_req_config(struct device *dev,
+		unsigned long ext_ctrl_flag, int preq_bit,
+		int state_reg_add, int trans_reg_add);
+#endif /*__LINUX_MFD_TPS80031_H */
diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h
index a8eff4a..94ac944 100644
--- a/include/linux/mfd/twl6040.h
+++ b/include/linux/mfd/twl6040.h
@@ -207,10 +207,12 @@ struct twl6040_platform_data {
 };
 
 struct regmap;
+struct regmap_irq_chips_data;
 
 struct twl6040 {
 	struct device *dev;
 	struct regmap *regmap;
+	struct regmap_irq_chip_data *irq_data;
 	struct regulator_bulk_data supplies[2]; /* supplies for vio, v2v1 */
 	struct mutex mutex;
 	struct mutex irq_mutex;
@@ -228,9 +230,8 @@ struct twl6040 {
 	unsigned int mclk;
 
 	unsigned int irq;
-	unsigned int irq_base;
-	u8 irq_masks_cur;
-	u8 irq_masks_cache;
+	unsigned int irq_ready;
+	unsigned int irq_th;
 };
 
 int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg);
@@ -245,8 +246,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
 		    unsigned int freq_in, unsigned int freq_out);
 int twl6040_get_pll(struct twl6040 *twl6040);
 unsigned int twl6040_get_sysclk(struct twl6040 *twl6040);
-int twl6040_irq_init(struct twl6040 *twl6040);
-void twl6040_irq_exit(struct twl6040 *twl6040);
+
 /* Get the combined status of the vibra control register */
 int twl6040_get_vibralr_status(struct twl6040 *twl6040);
 
diff --git a/include/linux/mfd/viperboard.h b/include/linux/mfd/viperboard.h
new file mode 100644
index 0000000..1934528
--- /dev/null
+++ b/include/linux/mfd/viperboard.h
@@ -0,0 +1,110 @@
+/*
+ *  include/linux/mfd/viperboard.h
+ *
+ *  Nano River Technologies viperboard definitions
+ *
+ *  (C) 2012 by Lemonage GmbH
+ *  Author: Lars Poeschel <poeschel@lemonage.de>
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef __MFD_VIPERBOARD_H__
+#define __MFD_VIPERBOARD_H__
+
+#include <linux/types.h>
+#include <linux/usb.h>
+
+#define VPRBRD_EP_OUT               0x02
+#define VPRBRD_EP_IN                0x86
+
+#define VPRBRD_I2C_MSG_LEN          512 /* max length of a msg on USB level */
+
+#define VPRBRD_I2C_FREQ_6MHZ        1                        /*   6 MBit/s */
+#define VPRBRD_I2C_FREQ_3MHZ        2                        /*   3 MBit/s */
+#define VPRBRD_I2C_FREQ_1MHZ        3                        /*   1 MBit/s */
+#define VPRBRD_I2C_FREQ_FAST        4                        /* 400 kbit/s */
+#define VPRBRD_I2C_FREQ_400KHZ      VPRBRD_I2C_FREQ_FAST
+#define VPRBRD_I2C_FREQ_200KHZ      5                        /* 200 kbit/s */
+#define VPRBRD_I2C_FREQ_STD         6                        /* 100 kbit/s */
+#define VPRBRD_I2C_FREQ_100KHZ      VPRBRD_I2C_FREQ_STD
+#define VPRBRD_I2C_FREQ_10KHZ       7                        /*  10 kbit/s */
+
+#define VPRBRD_I2C_CMD_WRITE        0x00
+#define VPRBRD_I2C_CMD_READ         0x01
+#define VPRBRD_I2C_CMD_ADDR         0x02
+
+#define VPRBRD_USB_TYPE_OUT	    0x40
+#define VPRBRD_USB_TYPE_IN	    0xc0
+#define VPRBRD_USB_TIMEOUT_MS       100
+#define VPRBRD_USB_REQUEST_I2C_FREQ 0xe6
+#define VPRBRD_USB_REQUEST_I2C      0xe9
+#define VPRBRD_USB_REQUEST_MAJOR    0xea
+#define VPRBRD_USB_REQUEST_MINOR    0xeb
+#define VPRBRD_USB_REQUEST_ADC      0xec
+#define VPRBRD_USB_REQUEST_GPIOA    0xed
+#define VPRBRD_USB_REQUEST_GPIOB    0xdd
+
+struct vprbrd_i2c_write_hdr {
+	u8 cmd;
+	u16 addr;
+	u8 len1;
+	u8 len2;
+	u8 last;
+	u8 chan;
+	u16 spi;
+} __packed;
+
+struct vprbrd_i2c_read_hdr {
+	u8 cmd;
+	u16 addr;
+	u8 len0;
+	u8 len1;
+	u8 len2;
+	u8 len3;
+	u8 len4;
+	u8 len5;
+	u16 tf1;                        /* transfer 1 length */
+	u16 tf2;                        /* transfer 2 length */
+} __packed;
+
+struct vprbrd_i2c_status {
+	u8 unknown[11];
+	u8 status;
+} __packed;
+
+struct vprbrd_i2c_write_msg {
+	struct vprbrd_i2c_write_hdr header;
+	u8 data[VPRBRD_I2C_MSG_LEN
+		- sizeof(struct vprbrd_i2c_write_hdr)];
+} __packed;
+
+struct vprbrd_i2c_read_msg {
+	struct vprbrd_i2c_read_hdr header;
+	u8 data[VPRBRD_I2C_MSG_LEN
+		- sizeof(struct vprbrd_i2c_read_hdr)];
+} __packed;
+
+struct vprbrd_i2c_addr_msg {
+	u8 cmd;
+	u8 addr;
+	u8 unknown1;
+	u16 len;
+	u8 unknown2;
+	u8 unknown3;
+} __packed;
+
+/* Structure to hold all device specific stuff */
+struct vprbrd {
+	struct usb_device *usb_dev; /* the usb device for this device */
+	struct mutex lock;
+	u8 buf[sizeof(struct vprbrd_i2c_write_msg)];
+	struct platform_device pdev;
+};
+
+#endif /* __MFD_VIPERBOARD_H__ */
diff --git a/include/linux/mfd/wm8994/core.h b/include/linux/mfd/wm8994/core.h
index 1f17330..ae5c249 100644
--- a/include/linux/mfd/wm8994/core.h
+++ b/include/linux/mfd/wm8994/core.h
@@ -19,6 +19,8 @@
 #include <linux/interrupt.h>
 #include <linux/regmap.h>
 
+#include <linux/mfd/wm8994/pdata.h>
+
 enum wm8994_type {
 	WM8994 = 0,
 	WM8958 = 1,
@@ -55,6 +57,8 @@ struct regulator_bulk_data;
 struct wm8994 {
 	struct mutex irq_lock;
 
+	struct wm8994_pdata pdata;
+
 	enum wm8994_type type;
 	int revision;
 	int cust_id;
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h
index fc87be4..8e21a09 100644
--- a/include/linux/mfd/wm8994/pdata.h
+++ b/include/linux/mfd/wm8994/pdata.h
@@ -176,6 +176,11 @@ struct wm8994_pdata {
         unsigned int lineout1fb:1;
         unsigned int lineout2fb:1;
 
+	/* Delay between detecting a jack and starting microphone
+	 * detect (specified in ms)
+	 */
+	int micdet_delay;
+
 	/* IRQ for microphone detection if brought out directly as a
 	 * signal.
 	 */
diff --git a/include/linux/micrel_phy.h b/include/linux/micrel_phy.h
index de20120..adfe8c0 100644
--- a/include/linux/micrel_phy.h
+++ b/include/linux/micrel_phy.h
@@ -15,6 +15,7 @@
 
 #define MICREL_PHY_ID_MASK	0x00fffff0
 
+#define PHY_ID_KSZ8873MLL	0x000e7237
 #define PHY_ID_KSZ9021		0x00221610
 #define PHY_ID_KS8737		0x00221720
 #define PHY_ID_KSZ8021		0x00221555
diff --git a/include/linux/migrate.h b/include/linux/migrate.h
index ce7e667..4c8454a 100644
--- a/include/linux/migrate.h
+++ b/include/linux/migrate.h
@@ -7,9 +7,27 @@
 
 typedef struct page *new_page_t(struct page *, unsigned long private, int **);
 
+/*
+ * Return values from addresss_space_operations.migratepage():
+ * - negative errno on page migration failure;
+ * - zero on page migration success;
+ *
+ * The balloon page migration introduces this special case where a 'distinct'
+ * return code is used to flag a successful page migration to unmap_and_move().
+ * This approach is necessary because page migration can race against balloon
+ * deflation procedure, and for such case we could introduce a nasty page leak
+ * if a successfully migrated balloon page gets released concurrently with
+ * migration's unmap_and_move() wrap-up steps.
+ */
+#define MIGRATEPAGE_SUCCESS		0
+#define MIGRATEPAGE_BALLOON_SUCCESS	1 /* special ret code for balloon page
+					   * sucessful migration case.
+					   */
+
 #ifdef CONFIG_MIGRATION
 
 extern void putback_lru_pages(struct list_head *l);
+extern void putback_movable_pages(struct list_head *l);
 extern int migrate_page(struct address_space *,
 			struct page *, struct page *, enum migrate_mode);
 extern int migrate_pages(struct list_head *l, new_page_t x,
@@ -30,9 +48,11 @@ extern int migrate_vmas(struct mm_struct *mm,
 extern void migrate_page_copy(struct page *newpage, struct page *page);
 extern int migrate_huge_page_move_mapping(struct address_space *mapping,
 				  struct page *newpage, struct page *page);
+extern int migrate_misplaced_page(struct page *page, int node);
 #else
 
 static inline void putback_lru_pages(struct list_head *l) {}
+static inline void putback_movable_pages(struct list_head *l) {}
 static inline int migrate_pages(struct list_head *l, new_page_t x,
 		unsigned long private, bool offlining,
 		enum migrate_mode mode) { return -ENOSYS; }
@@ -63,5 +83,11 @@ static inline int migrate_huge_page_move_mapping(struct address_space *mapping,
 #define migrate_page NULL
 #define fail_migrate_page NULL
 
+static inline
+int migrate_misplaced_page(struct page *page, int node)
+{
+	return -EAGAIN; /* can't migrate now */
+}
+
 #endif /* CONFIG_MIGRATION */
 #endif /* _LINUX_MIGRATE_H */
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 6d1acb0..21821da 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -142,6 +142,8 @@ enum {
 	MLX4_DEV_CAP_FLAG_COUNTERS	= 1LL << 48,
 	MLX4_DEV_CAP_FLAG_SENSE_SUPPORT	= 1LL << 55,
 	MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV = 1LL << 59,
+	MLX4_DEV_CAP_FLAG_64B_EQE	= 1LL << 61,
+	MLX4_DEV_CAP_FLAG_64B_CQE	= 1LL << 62
 };
 
 enum {
@@ -151,6 +153,20 @@ enum {
 	MLX4_DEV_CAP_FLAG2_FS_EN		= 1LL <<  3
 };
 
+enum {
+	MLX4_DEV_CAP_64B_EQE_ENABLED	= 1LL << 0,
+	MLX4_DEV_CAP_64B_CQE_ENABLED	= 1LL << 1
+};
+
+enum {
+	MLX4_USER_DEV_CAP_64B_CQE	= 1L << 0
+};
+
+enum {
+	MLX4_FUNC_CAP_64B_EQE_CQE	= 1L << 0
+};
+
+
 #define MLX4_ATTR_EXTENDED_PORT_INFO	cpu_to_be16(0xff90)
 
 enum {
@@ -419,6 +435,11 @@ struct mlx4_caps {
 	u32			max_counters;
 	u8			port_ib_mtu[MLX4_MAX_PORTS + 1];
 	u16			sqp_demux;
+	u32			eqe_size;
+	u32			cqe_size;
+	u8			eqe_factor;
+	u32			userspace_caps; /* userspace must be aware of these */
+	u32			function_caps;  /* VFs must be aware of these */
 };
 
 struct mlx4_buf_list {
diff --git a/include/linux/mm.h b/include/linux/mm.h
index bcaab4e..2984e07 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -516,6 +516,14 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
 }
 #endif
 
+#ifndef my_zero_pfn
+static inline unsigned long my_zero_pfn(unsigned long addr)
+{
+	extern unsigned long zero_pfn;
+	return zero_pfn;
+}
+#endif
+
 /*
  * Multiple processes may "see" the same page. E.g. for untouched
  * mappings of /dev/null, all processes see the same page full of
@@ -581,50 +589,11 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
  * sets it, so none of the operations on it need to be atomic.
  */
 
-
-/*
- * page->flags layout:
- *
- * There are three possibilities for how page->flags get
- * laid out.  The first is for the normal case, without
- * sparsemem.  The second is for sparsemem when there is
- * plenty of space for node and section.  The last is when
- * we have run out of space and have to fall back to an
- * alternate (slower) way of determining the node.
- *
- * No sparsemem or sparsemem vmemmap: |       NODE     | ZONE | ... | FLAGS |
- * classic sparse with space for node:| SECTION | NODE | ZONE | ... | FLAGS |
- * classic sparse no space for node:  | SECTION |     ZONE    | ... | FLAGS |
- */
-#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
-#define SECTIONS_WIDTH		SECTIONS_SHIFT
-#else
-#define SECTIONS_WIDTH		0
-#endif
-
-#define ZONES_WIDTH		ZONES_SHIFT
-
-#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS
-#define NODES_WIDTH		NODES_SHIFT
-#else
-#ifdef CONFIG_SPARSEMEM_VMEMMAP
-#error "Vmemmap: No space for nodes field in page flags"
-#endif
-#define NODES_WIDTH		0
-#endif
-
-/* Page flags: | [SECTION] | [NODE] | ZONE | ... | FLAGS | */
+/* Page flags: | [SECTION] | [NODE] | ZONE | [LAST_CPU] | ... | FLAGS | */
 #define SECTIONS_PGOFF		((sizeof(unsigned long)*8) - SECTIONS_WIDTH)
 #define NODES_PGOFF		(SECTIONS_PGOFF - NODES_WIDTH)
 #define ZONES_PGOFF		(NODES_PGOFF - ZONES_WIDTH)
-
-/*
- * We are going to use the flags for the page to node mapping if its in
- * there.  This includes the case where there is no node, so it is implicit.
- */
-#if !(NODES_WIDTH > 0 || NODES_SHIFT == 0)
-#define NODE_NOT_IN_PAGE_FLAGS
-#endif
+#define LAST_CPU_PGOFF		(ZONES_PGOFF - LAST_CPU_WIDTH)
 
 /*
  * Define the bit shifts to access each section.  For non-existent
@@ -634,6 +603,7 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
 #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_CPU_PGSHIFT	(LAST_CPU_PGOFF * (LAST_CPU_WIDTH != 0))
 
 /* NODE:ZONE or SECTION:ZONE is used to ID a zone for the buddy allocator */
 #ifdef NODE_NOT_IN_PAGE_FLAGS
@@ -655,6 +625,7 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
 #define ZONES_MASK		((1UL << ZONES_WIDTH) - 1)
 #define NODES_MASK		((1UL << NODES_WIDTH) - 1)
 #define SECTIONS_MASK		((1UL << SECTIONS_WIDTH) - 1)
+#define LAST_CPU_MASK		((1UL << LAST_CPU_WIDTH) - 1)
 #define ZONEID_MASK		((1UL << ZONEID_SHIFT) - 1)
 
 static inline enum zone_type page_zonenum(const struct page *page)
@@ -693,6 +664,51 @@ static inline int page_to_nid(const struct page *page)
 }
 #endif
 
+#ifdef CONFIG_NUMA_BALANCING
+#ifdef LAST_CPU_NOT_IN_PAGE_FLAGS
+static inline int page_xchg_last_cpu(struct page *page, int cpu)
+{
+	return xchg(&page->_last_cpu, cpu);
+}
+
+static inline int page_last_cpu(struct page *page)
+{
+	return page->_last_cpu;
+}
+#else
+static inline int page_xchg_last_cpu(struct page *page, int cpu)
+{
+	unsigned long old_flags, flags;
+	int last_cpu;
+
+	do {
+		old_flags = flags = page->flags;
+		last_cpu = (flags >> LAST_CPU_PGSHIFT) & LAST_CPU_MASK;
+
+		flags &= ~(LAST_CPU_MASK << LAST_CPU_PGSHIFT);
+		flags |= (cpu & LAST_CPU_MASK) << LAST_CPU_PGSHIFT;
+	} while (unlikely(cmpxchg(&page->flags, old_flags, flags) != old_flags));
+
+	return last_cpu;
+}
+
+static inline int page_last_cpu(struct page *page)
+{
+	return (page->flags >> LAST_CPU_PGSHIFT) & LAST_CPU_MASK;
+}
+#endif /* LAST_CPU_NOT_IN_PAGE_FLAGS */
+#else /* CONFIG_NUMA_BALANCING */
+static inline int page_xchg_last_cpu(struct page *page, int cpu)
+{
+	return page_to_nid(page);
+}
+
+static inline int page_last_cpu(struct page *page)
+{
+	return page_to_nid(page);
+}
+#endif /* CONFIG_NUMA_BALANCING */
+
 static inline struct zone *page_zone(const struct page *page)
 {
 	return &NODE_DATA(page_to_nid(page))->node_zones[page_zonenum(page)];
@@ -1078,6 +1094,9 @@ extern unsigned long move_page_tables(struct vm_area_struct *vma,
 extern unsigned long do_mremap(unsigned long addr,
 			       unsigned long old_len, unsigned long new_len,
 			       unsigned long flags, unsigned long new_addr);
+extern unsigned long change_protection(struct vm_area_struct *vma, unsigned long start,
+			      unsigned long end, pgprot_t newprot,
+			      int dirty_accountable);
 extern int mprotect_fixup(struct vm_area_struct *vma,
 			  struct vm_area_struct **pprev, unsigned long start,
 			  unsigned long end, unsigned long newflags);
@@ -1456,6 +1475,37 @@ extern unsigned long vm_mmap(struct file *, unsigned long,
         unsigned long, unsigned long,
         unsigned long, unsigned long);
 
+struct vm_unmapped_area_info {
+#define VM_UNMAPPED_AREA_TOPDOWN 1
+	unsigned long flags;
+	unsigned long length;
+	unsigned long low_limit;
+	unsigned long high_limit;
+	unsigned long align_mask;
+	unsigned long align_offset;
+};
+
+extern unsigned long unmapped_area(struct vm_unmapped_area_info *info);
+extern unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info);
+
+/*
+ * Search for an unmapped address range.
+ *
+ * We are looking for a range that:
+ * - does not intersect with any VMA;
+ * - is contained within the [low_limit, high_limit) interval;
+ * - is at least the desired size.
+ * - satisfies (begin_addr & align_mask) == (align_offset & align_mask)
+ */
+static inline unsigned long
+vm_unmapped_area(struct vm_unmapped_area_info *info)
+{
+	if (!(info->flags & VM_UNMAPPED_AREA_TOPDOWN))
+		return unmapped_area(info);
+	else
+		return unmapped_area_topdown(info);
+}
+
 /* truncate.c */
 extern void truncate_inode_pages(struct address_space *, loff_t);
 extern void truncate_inode_pages_range(struct address_space *,
@@ -1548,6 +1598,11 @@ static inline pgprot_t vm_get_page_prot(unsigned long vm_flags)
 }
 #endif
 
+#ifdef CONFIG_ARCH_USES_NUMA_GENERIC_PGPROT
+extern unsigned long
+change_prot_numa(struct vm_area_struct *vma, unsigned long start, unsigned long end);
+#endif
+
 struct vm_area_struct *find_extend_vma(struct mm_struct *, unsigned long addr);
 int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
 			unsigned long pfn, unsigned long size, pgprot_t);
@@ -1569,6 +1624,7 @@ struct page *follow_page(struct vm_area_struct *, unsigned long address,
 #define FOLL_MLOCK	0x40	/* mark page as mlocked */
 #define FOLL_SPLIT	0x80	/* don't return transhuge pages, split them */
 #define FOLL_HWPOISON	0x100	/* check page is hwpoisoned */
+#define FOLL_NUMA	0x200	/* force NUMA hinting page fault */
 
 typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
 			void *data);
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 31f8a3a..b931f8b 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -12,6 +12,7 @@
 #include <linux/cpumask.h>
 #include <linux/page-debug-flags.h>
 #include <linux/uprobes.h>
+#include <linux/page-flags-layout.h>
 #include <asm/page.h>
 #include <asm/mmu.h>
 
@@ -128,10 +129,7 @@ struct page {
 		};
 
 		struct list_head list;	/* slobs list of pages */
-		struct {		/* slab fields */
-			struct kmem_cache *slab_cache;
-			struct slab *slab_page;
-		};
+		struct slab *slab_page; /* slab fields */
 	};
 
 	/* Remainder is not double word aligned */
@@ -146,7 +144,7 @@ struct page {
 #if USE_SPLIT_PTLOCKS
 		spinlock_t ptl;
 #endif
-		struct kmem_cache *slab;	/* SLUB: Pointer to slab */
+		struct kmem_cache *slab_cache;	/* SL[AU]B: Pointer to slab */
 		struct page *first_page;	/* Compound tail pages */
 	};
 
@@ -175,6 +173,10 @@ struct page {
 	 */
 	void *shadow;
 #endif
+
+#ifdef LAST_CPU_NOT_IN_PAGE_FLAGS
+	int _last_cpu;
+#endif
 }
 /*
  * The struct page can be forced to be double word aligned so that atomic ops
@@ -224,7 +226,8 @@ struct vm_region {
  * library, the executable area etc).
  */
 struct vm_area_struct {
-	struct mm_struct * vm_mm;	/* The address space we belong to. */
+	/* The first cache line has the info for VMA tree walking. */
+
 	unsigned long vm_start;		/* Our start address within vm_mm. */
 	unsigned long vm_end;		/* The first byte after our end address
 					   within vm_mm. */
@@ -232,11 +235,22 @@ struct vm_area_struct {
 	/* linked list of VM areas per task, sorted by address */
 	struct vm_area_struct *vm_next, *vm_prev;
 
+	struct rb_node vm_rb;
+
+	/*
+	 * Largest free memory gap in bytes to the left of this VMA.
+	 * Either between this VMA and vma->vm_prev, or between one of the
+	 * VMAs below us in the VMA rbtree and its ->vm_prev. This helps
+	 * get_unmapped_area find a free area of the right size.
+	 */
+	unsigned long rb_subtree_gap;
+
+	/* Second cache line starts here. */
+
+	struct mm_struct *vm_mm;	/* The address space we belong to. */
 	pgprot_t vm_page_prot;		/* Access permissions of this VMA. */
 	unsigned long vm_flags;		/* Flags, see mm.h. */
 
-	struct rb_node vm_rb;
-
 	/*
 	 * For areas with an address space and backing store,
 	 * linkage into the address_space->i_mmap interval tree, or
@@ -322,6 +336,7 @@ struct mm_struct {
 	unsigned long task_size;		/* size of task vm space */
 	unsigned long cached_hole_size; 	/* if non-zero, the largest hole below free_area_cache */
 	unsigned long free_area_cache;		/* first hole of size cached_hole_size or larger */
+	unsigned long highest_vm_end;		/* highest vma end address */
 	pgd_t * pgd;
 	atomic_t mm_users;			/* How many users with user space? */
 	atomic_t mm_count;			/* How many references to "struct mm_struct" (users count as 1) */
@@ -398,6 +413,11 @@ struct mm_struct {
 #ifdef CONFIG_CPUMASK_OFFSTACK
 	struct cpumask cpumask_allocation;
 #endif
+#ifdef CONFIG_NUMA_BALANCING
+	unsigned long numa_next_scan;
+	unsigned long numa_scan_offset;
+	int numa_scan_seq;
+#endif
 	struct uprobes_state uprobes_state;
 };
 
diff --git a/include/linux/mman.h b/include/linux/mman.h
index d09dde1..9aa863d 100644
--- a/include/linux/mman.h
+++ b/include/linux/mman.h
@@ -11,6 +11,8 @@ extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
 extern struct percpu_counter vm_committed_as;
 
+unsigned long vm_memory_committed(void);
+
 static inline void vm_acct_memory(long pages)
 {
 	percpu_counter_add(&vm_committed_as, pages);
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 943550d..5c69315 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -85,6 +85,7 @@ struct mmc_ext_csd {
 	bool			boot_ro_lockable;
 	u8			raw_exception_status;	/* 53 */
 	u8			raw_partition_support;	/* 160 */
+	u8			raw_rpmb_size_mult;	/* 168 */
 	u8			raw_erased_mem_count;	/* 181 */
 	u8			raw_ext_csd_structure;	/* 194 */
 	u8			raw_card_type;		/* 196 */
@@ -206,6 +207,7 @@ struct mmc_part {
 #define MMC_BLK_DATA_AREA_MAIN	(1<<0)
 #define MMC_BLK_DATA_AREA_BOOT	(1<<1)
 #define MMC_BLK_DATA_AREA_GP	(1<<2)
+#define MMC_BLK_DATA_AREA_RPMB	(1<<3)
 };
 
 /*
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 9b9cdaf..5bf7c22 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -170,6 +170,8 @@ extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
 extern unsigned int mmc_calc_max_discard(struct mmc_card *card);
 
 extern int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen);
+extern int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount,
+			      bool is_rel_write);
 extern int mmc_hw_reset(struct mmc_host *host);
 extern int mmc_hw_reset_check(struct mmc_host *host);
 extern int mmc_can_reset(struct mmc_card *card);
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index 9653166..34be4f4 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -229,8 +229,9 @@ struct dw_mci_board {
 	u32 quirks; /* Workaround / Quirk flags */
 	unsigned int bus_hz; /* Clock speed at the cclk_in pad */
 
-	unsigned int caps;	/* Capabilities */
-	unsigned int caps2;	/* More capabilities */
+	u32 caps;	/* Capabilities */
+	u32 caps2;	/* More capabilities */
+	u32 pm_caps;	/* PM capabilities */
 	/*
 	 * Override fifo depth. If 0, autodetect it from the FIFOTH register,
 	 * but note that this may not be reliable after a bootloader has used
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 7abb0e1..23df21e 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -53,12 +53,12 @@ struct mmc_ios {
 #define MMC_TIMING_LEGACY	0
 #define MMC_TIMING_MMC_HS	1
 #define MMC_TIMING_SD_HS	2
-#define MMC_TIMING_UHS_SDR12	MMC_TIMING_LEGACY
-#define MMC_TIMING_UHS_SDR25	MMC_TIMING_SD_HS
-#define MMC_TIMING_UHS_SDR50	3
-#define MMC_TIMING_UHS_SDR104	4
-#define MMC_TIMING_UHS_DDR50	5
-#define MMC_TIMING_MMC_HS200	6
+#define MMC_TIMING_UHS_SDR12	3
+#define MMC_TIMING_UHS_SDR25	4
+#define MMC_TIMING_UHS_SDR50	5
+#define MMC_TIMING_UHS_SDR104	6
+#define MMC_TIMING_UHS_DDR50	7
+#define MMC_TIMING_MMC_HS200	8
 
 #define MMC_SDR_MODE		0
 #define MMC_1_2V_DDR_MODE	1
@@ -211,7 +211,7 @@ struct mmc_host {
 #define MMC_VDD_34_35		0x00400000	/* VDD voltage 3.4 ~ 3.5 */
 #define MMC_VDD_35_36		0x00800000	/* VDD voltage 3.5 ~ 3.6 */
 
-	unsigned long		caps;		/* Host capabilities */
+	u32			caps;		/* Host capabilities */
 
 #define MMC_CAP_4_BIT_DATA	(1 << 0)	/* Can the host do 4 bit transfers */
 #define MMC_CAP_MMC_HIGHSPEED	(1 << 1)	/* Can do MMC high-speed timing */
@@ -241,7 +241,7 @@ struct mmc_host {
 #define MMC_CAP_CMD23		(1 << 30)	/* CMD23 supported. */
 #define MMC_CAP_HW_RESET	(1 << 31)	/* Hardware reset */
 
-	unsigned int		caps2;		/* More host capabilities */
+	u32			caps2;		/* More host capabilities */
 
 #define MMC_CAP2_BOOTPART_NOACC	(1 << 0)	/* Boot partition no access */
 #define MMC_CAP2_CACHE_CTRL	(1 << 1)	/* Allow cache control */
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 01e4b39..94d532e 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -286,6 +286,7 @@ struct _mmc_csd {
 #define EXT_CSD_BKOPS_START		164	/* W */
 #define EXT_CSD_SANITIZE_START		165     /* W */
 #define EXT_CSD_WR_REL_PARAM		166	/* RO */
+#define EXT_CSD_RPMB_MULT		168	/* RO */
 #define EXT_CSD_BOOT_WP			173	/* R/W */
 #define EXT_CSD_ERASE_GROUP_DEF		175	/* R/W */
 #define EXT_CSD_PART_CONFIG		179	/* R/W */
@@ -339,6 +340,7 @@ struct _mmc_csd {
 
 #define EXT_CSD_PART_CONFIG_ACC_MASK	(0x7)
 #define EXT_CSD_PART_CONFIG_ACC_BOOT0	(0x1)
+#define EXT_CSD_PART_CONFIG_ACC_RPMB	(0x3)
 #define EXT_CSD_PART_CONFIG_ACC_GP0	(0x4)
 
 #define EXT_CSD_PART_SUPPORT_PART_EN	(0x1)
diff --git a/include/linux/mmc/mxs-mmc.h b/include/linux/mmc/mxs-mmc.h
deleted file mode 100644
index 7c2ad3a..0000000
--- a/include/linux/mmc/mxs-mmc.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __LINUX_MMC_MXS_MMC_H__
-#define __LINUX_MMC_MXS_MMC_H__
-
-struct mxs_mmc_platform_data {
-	int wp_gpio;	/* write protect pin */
-	unsigned int flags;
-#define SLOTF_4_BIT_CAPABLE	(1 << 0)
-#define SLOTF_8_BIT_CAPABLE	(1 << 1)
-};
-
-#endif /* __LINUX_MMC_MXS_MMC_H__ */
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 1edcb4d..b34f3eb 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -158,8 +158,8 @@ struct sdhci_host {
 
 	struct timer_list timer;	/* Timer for timeouts */
 
-	unsigned int caps;	/* Alternative CAPABILITY_0 */
-	unsigned int caps1;	/* Alternative CAPABILITY_1 */
+	u32 caps;		/* Alternative CAPABILITY_0 */
+	u32 caps1;		/* Alternative CAPABILITY_1 */
 
 	unsigned int            ocr_avail_sdio;	/* OCR bit masks */
 	unsigned int            ocr_avail_sd;
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index a23923b..32bc955 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -15,7 +15,7 @@
 #include <linux/seqlock.h>
 #include <linux/nodemask.h>
 #include <linux/pageblock-flags.h>
-#include <generated/bounds.h>
+#include <linux/page-flags-layout.h>
 #include <linux/atomic.h>
 #include <asm/page.h>
 
@@ -63,10 +63,8 @@ enum {
 
 #ifdef CONFIG_CMA
 #  define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
-#  define cma_wmark_pages(zone)	zone->min_cma_pages
 #else
 #  define is_migrate_cma(migratetype) false
-#  define cma_wmark_pages(zone) 0
 #endif
 
 #define for_each_migratetype_order(order, type) \
@@ -318,16 +316,6 @@ enum zone_type {
  * match the requested limits. See gfp_zone() in include/linux/gfp.h
  */
 
-#if MAX_NR_ZONES < 2
-#define ZONES_SHIFT 0
-#elif MAX_NR_ZONES <= 2
-#define ZONES_SHIFT 1
-#elif MAX_NR_ZONES <= 4
-#define ZONES_SHIFT 2
-#else
-#error ZONES_SHIFT -- too many zones configured adjust calculation
-#endif
-
 struct zone {
 	/* Fields commonly accessed by the page allocator */
 
@@ -383,13 +371,6 @@ struct zone {
 	/* see spanned/present_pages for more description */
 	seqlock_t		span_seqlock;
 #endif
-#ifdef CONFIG_CMA
-	/*
-	 * CMA needs to increase watermark levels during the allocation
-	 * process to make sure that the system is not starved.
-	 */
-	unsigned long		min_cma_pages;
-#endif
 	struct free_area	free_area[MAX_ORDER];
 
 #ifndef CONFIG_SPARSEMEM
@@ -469,17 +450,44 @@ struct zone {
 	unsigned long		zone_start_pfn;
 
 	/*
-	 * zone_start_pfn, spanned_pages and present_pages are all
-	 * protected by span_seqlock.  It is a seqlock because it has
-	 * to be read outside of zone->lock, and it is done in the main
-	 * allocator path.  But, it is written quite infrequently.
+	 * spanned_pages is the total pages spanned by the zone, including
+	 * holes, which is calculated as:
+	 * 	spanned_pages = zone_end_pfn - zone_start_pfn;
 	 *
-	 * The lock is declared along with zone->lock because it is
+	 * present_pages is physical pages existing within the zone, which
+	 * is calculated as:
+	 *	present_pages = spanned_pages - absent_pages(pags in holes);
+	 *
+	 * managed_pages is present pages managed by the buddy system, which
+	 * is calculated as (reserved_pages includes pages allocated by the
+	 * bootmem allocator):
+	 *	managed_pages = present_pages - reserved_pages;
+	 *
+	 * So present_pages may be used by memory hotplug or memory power
+	 * management logic to figure out unmanaged pages by checking
+	 * (present_pages - managed_pages). And managed_pages should be used
+	 * by page allocator and vm scanner to calculate all kinds of watermarks
+	 * and thresholds.
+	 *
+	 * Locking rules:
+	 *
+	 * zone_start_pfn and spanned_pages are protected by span_seqlock.
+	 * It is a seqlock because it has to be read outside of zone->lock,
+	 * and it is done in the main allocator path.  But, it is written
+	 * quite infrequently.
+	 *
+	 * The span_seq lock is declared along with zone->lock because it is
 	 * frequently read in proximity to zone->lock.  It's good to
 	 * give them a chance of being in the same cacheline.
+	 *
+	 * Write access to present_pages and managed_pages at runtime should
+	 * be protected by lock_memory_hotplug()/unlock_memory_hotplug().
+	 * Any reader who can't tolerant drift of present_pages and
+	 * managed_pages should hold memory hotplug lock to get a stable value.
 	 */
-	unsigned long		spanned_pages;	/* total size, including holes */
-	unsigned long		present_pages;	/* amount of memory (excluding holes) */
+	unsigned long		spanned_pages;
+	unsigned long		present_pages;
+	unsigned long		managed_pages;
 
 	/*
 	 * rarely used fields:
@@ -1030,8 +1038,6 @@ static inline unsigned long early_pfn_to_nid(unsigned long pfn)
  * PA_SECTION_SHIFT		physical address to/from section number
  * PFN_SECTION_SHIFT		pfn to/from section number
  */
-#define SECTIONS_SHIFT		(MAX_PHYSMEM_BITS - SECTION_SIZE_BITS)
-
 #define PA_SECTION_SHIFT	(SECTION_SIZE_BITS)
 #define PFN_SECTION_SHIFT	(SECTION_SIZE_BITS - PAGE_SHIFT)
 
diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
index 5a8e390..12b2ab5 100644
--- a/include/linux/mnt_namespace.h
+++ b/include/linux/mnt_namespace.h
@@ -4,9 +4,10 @@
 
 struct mnt_namespace;
 struct fs_struct;
+struct user_namespace;
 
 extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
-		struct fs_struct *);
+		struct user_namespace *, struct fs_struct *);
 extern void put_mnt_ns(struct mnt_namespace *ns);
 
 extern const struct file_operations proc_mounts_operations;
diff --git a/include/linux/msg.h b/include/linux/msg.h
index 7a4b9e9..391af8d 100644
--- a/include/linux/msg.h
+++ b/include/linux/msg.h
@@ -34,7 +34,9 @@ struct msg_queue {
 /* Helper routines for sys_msgsnd and sys_msgrcv */
 extern long do_msgsnd(int msqid, long mtype, void __user *mtext,
 			size_t msgsz, int msgflg);
-extern long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
-			size_t msgsz, long msgtyp, int msgflg);
+extern long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
+		      int msgflg,
+		      long (*msg_fill)(void __user *, struct msg_msg *,
+				       size_t));
 
 #endif /* _LINUX_MSG_H */
diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h
index ed270bd..4eb0a50 100644
--- a/include/linux/mtd/blktrans.h
+++ b/include/linux/mtd/blktrans.h
@@ -23,6 +23,7 @@
 #include <linux/mutex.h>
 #include <linux/kref.h>
 #include <linux/sysfs.h>
+#include <linux/workqueue.h>
 
 struct hd_geometry;
 struct mtd_info;
@@ -43,7 +44,8 @@ struct mtd_blktrans_dev {
 	struct kref ref;
 	struct gendisk *disk;
 	struct attribute_group *disk_attributes;
-	struct task_struct *thread;
+	struct workqueue_struct *wq;
+	struct work_struct work;
 	struct request_queue *rq;
 	spinlock_t queue_lock;
 	void *priv;
diff --git a/include/linux/mtd/doc2000.h b/include/linux/mtd/doc2000.h
index 0f6fea7..407d1e5 100644
--- a/include/linux/mtd/doc2000.h
+++ b/include/linux/mtd/doc2000.h
@@ -92,12 +92,26 @@
  * Others use readb/writeb
  */
 #if defined(__arm__)
-#define ReadDOC_(adr, reg)      ((unsigned char)(*(volatile __u32 *)(((unsigned long)adr)+((reg)<<2))))
-#define WriteDOC_(d, adr, reg)  do{ *(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)) = (__u32)d; wmb();} while(0)
+static inline u8 ReadDOC_(u32 __iomem *addr, unsigned long reg)
+{
+	return __raw_readl(addr + reg);
+}
+static inline void WriteDOC_(u8 data, u32 __iomem *addr, unsigned long reg)
+{
+	__raw_writel(data, addr + reg);
+	wmb();
+}
 #define DOC_IOREMAP_LEN 0x8000
 #elif defined(__ppc__)
-#define ReadDOC_(adr, reg)      ((unsigned char)(*(volatile __u16 *)(((unsigned long)adr)+((reg)<<1))))
-#define WriteDOC_(d, adr, reg)  do{ *(volatile __u16 *)(((unsigned long)adr)+((reg)<<1)) = (__u16)d; wmb();} while(0)
+static inline u8 ReadDOC_(u16 __iomem *addr, unsigned long reg)
+{
+	return __raw_readw(addr + reg);
+}
+static inline void WriteDOC_(u8 data, u16 __iomem *addr, unsigned long reg)
+{
+	__raw_writew(data, addr + reg);
+	wmb();
+}
 #define DOC_IOREMAP_LEN 0x4000
 #else
 #define ReadDOC_(adr, reg)      readb((void __iomem *)(adr) + (reg))
diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h
index b200292..d6ed61e 100644
--- a/include/linux/mtd/fsmc.h
+++ b/include/linux/mtd/fsmc.h
@@ -155,9 +155,6 @@ struct fsmc_nand_platform_data {
 	unsigned int		width;
 	unsigned int		bank;
 
-	/* CLE, ALE offsets */
-	unsigned int		cle_off;
-	unsigned int		ale_off;
 	enum access_mode	mode;
 
 	void			(*select_bank)(uint32_t bank, uint32_t busw);
diff --git a/include/linux/mtd/gpmi-nand.h b/include/linux/mtd/gpmi-nand.h
deleted file mode 100644
index ed3c4e0..0000000
--- a/include/linux/mtd/gpmi-nand.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef __MACH_MXS_GPMI_NAND_H__
-#define __MACH_MXS_GPMI_NAND_H__
-
-/* The size of the resources is fixed. */
-#define GPMI_NAND_RES_SIZE	6
-
-/* Resource names for the GPMI NAND driver. */
-#define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME  "gpmi-nand"
-#define GPMI_NAND_GPMI_INTERRUPT_RES_NAME  "GPMI NAND GPMI Interrupt"
-#define GPMI_NAND_BCH_REGS_ADDR_RES_NAME   "bch"
-#define GPMI_NAND_BCH_INTERRUPT_RES_NAME   "bch"
-#define GPMI_NAND_DMA_CHANNELS_RES_NAME    "GPMI NAND DMA Channels"
-#define GPMI_NAND_DMA_INTERRUPT_RES_NAME   "gpmi-dma"
-
-/**
- * struct gpmi_nand_platform_data - GPMI NAND driver platform data.
- *
- * This structure communicates platform-specific information to the GPMI NAND
- * driver that can't be expressed as resources.
- *
- * @platform_init:           A pointer to a function the driver will call to
- *                           initialize the platform (e.g., set up the pin mux).
- * @min_prop_delay_in_ns:    Minimum propagation delay of GPMI signals to and
- *                           from the NAND Flash device, in nanoseconds.
- * @max_prop_delay_in_ns:    Maximum propagation delay of GPMI signals to and
- *                           from the NAND Flash device, in nanoseconds.
- * @max_chip_count:          The maximum number of chips for which the driver
- *                           should configure the hardware. This value most
- *                           likely reflects the number of pins that are
- *                           connected to a NAND Flash device. If this is
- *                           greater than the SoC hardware can support, the
- *                           driver will print a message and fail to initialize.
- * @partitions:              An optional pointer to an array of partition
- *                           descriptions.
- * @partition_count:         The number of elements in the partitions array.
- */
-struct gpmi_nand_platform_data {
-	/* SoC hardware information. */
-	int		(*platform_init)(void);
-
-	/* NAND Flash information. */
-	unsigned int	min_prop_delay_in_ns;
-	unsigned int	max_prop_delay_in_ns;
-	unsigned int	max_chip_count;
-
-	/* Medium information. */
-	struct		mtd_partition *partitions;
-	unsigned	partition_count;
-};
-#endif
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index 3595a02..f6eb433 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -328,7 +328,7 @@ static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word
 
 static inline map_word map_word_load(struct map_info *map, const void *ptr)
 {
-	map_word r;
+	map_word r = {{0} };
 
 	if (map_bankwidth_is_1(map))
 		r.x[0] = *(unsigned char *)ptr;
@@ -391,7 +391,7 @@ static inline map_word map_word_ff(struct map_info *map)
 
 static inline map_word inline_map_read(struct map_info *map, unsigned long ofs)
 {
-	map_word r;
+	map_word uninitialized_var(r);
 
 	if (map_bankwidth_is_1(map))
 		r.x[0] = __raw_readb(map->virt + ofs);
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 81d61e7..f9ac289 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -98,7 +98,7 @@ struct mtd_oob_ops {
 };
 
 #define MTD_MAX_OOBFREE_ENTRIES_LARGE	32
-#define MTD_MAX_ECCPOS_ENTRIES_LARGE	448
+#define MTD_MAX_ECCPOS_ENTRIES_LARGE	640
 /*
  * Internal ECC layout control structure. For historical reasons, there is a
  * similar, smaller struct nand_ecclayout_user (in mtd-abi.h) that is retained
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 24e9159..9d8a604 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -471,8 +471,8 @@ struct nand_buffers {
  *			non 0 if ONFI supported.
  * @onfi_params:	[INTERN] holds the ONFI page parameter when ONFI is
  *			supported, 0 otherwise.
- * @onfi_set_features	[REPLACEABLE] set the features for ONFI nand
- * @onfi_get_features	[REPLACEABLE] get the features for ONFI nand
+ * @onfi_set_features:	[REPLACEABLE] set the features for ONFI nand
+ * @onfi_get_features:	[REPLACEABLE] get the features for ONFI nand
  * @ecclayout:		[REPLACEABLE] the default ECC placement scheme
  * @bbt:		[INTERN] bad block table pointer
  * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash
diff --git a/include/linux/mtd/sh_flctl.h b/include/linux/mtd/sh_flctl.h
index 01e4b15..1c28f88 100644
--- a/include/linux/mtd/sh_flctl.h
+++ b/include/linux/mtd/sh_flctl.h
@@ -20,6 +20,7 @@
 #ifndef __SH_FLCTL_H__
 #define __SH_FLCTL_H__
 
+#include <linux/completion.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
@@ -107,6 +108,7 @@
 #define ESTERINTE	(0x1 << 24)	/* ECC error interrupt enable */
 #define AC1CLR		(0x1 << 19)	/* ECC FIFO clear */
 #define AC0CLR		(0x1 << 18)	/* Data FIFO clear */
+#define DREQ0EN		(0x1 << 16)	/* FLDTFIFODMA Request Enable */
 #define ECERB		(0x1 << 9)	/* ECC error */
 #define STERB		(0x1 << 8)	/* Status error */
 #define STERINTE	(0x1 << 4)	/* Status error enable */
@@ -138,6 +140,8 @@ enum flctl_ecc_res_t {
 	FL_TIMEOUT
 };
 
+struct dma_chan;
+
 struct sh_flctl {
 	struct mtd_info		mtd;
 	struct nand_chip	chip;
@@ -147,7 +151,7 @@ struct sh_flctl {
 
 	uint8_t	done_buff[2048 + 64];	/* max size 2048 + 64 */
 	int	read_bytes;
-	int	index;
+	unsigned int index;
 	int	seqin_column;		/* column in SEQIN cmd */
 	int	seqin_page_addr;	/* page_addr in SEQIN cmd */
 	uint32_t seqin_read_cmd;		/* read cmd in SEQIN cmd */
@@ -161,6 +165,11 @@ struct sh_flctl {
 	unsigned hwecc:1;	/* Hardware ECC (0 = disabled, 1 = enabled) */
 	unsigned holden:1;	/* Hardware has FLHOLDCR and HOLDEN is set */
 	unsigned qos_request:1;	/* QoS request to prevent deep power shutdown */
+
+	/* DMA related objects */
+	struct dma_chan		*chan_fifo0_rx;
+	struct dma_chan		*chan_fifo0_tx;
+	struct completion	dma_complete;
 };
 
 struct sh_flctl_platform_data {
@@ -170,6 +179,9 @@ struct sh_flctl_platform_data {
 
 	unsigned has_hwecc:1;
 	unsigned use_holden:1;
+
+	unsigned int            slave_id_fifo0_tx;
+	unsigned int            slave_id_fifo0_rx;
 };
 
 static inline struct sh_flctl *mtd_to_flctl(struct mtd_info *mtdinfo)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f8eda02..ce28cc7 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -369,7 +369,7 @@ typedef enum gro_result gro_result_t;
  *
  * If the rx_handler consider the skb should be ignored, it should return
  * RX_HANDLER_EXACT. The skb will only be delivered to protocol handlers that
- * are registred on exact device (ptype->dev == skb->dev).
+ * are registered on exact device (ptype->dev == skb->dev).
  *
  * If the rx_handler didn't changed skb->dev, but want the skb to be normally
  * delivered, it should return RX_HANDLER_PASS.
@@ -887,6 +887,10 @@ struct netdev_fcoe_hbainfo {
  *		       struct net_device *dev, int idx)
  *	Used to add FDB entries to dump requests. Implementers should add
  *	entries to skb and update idx with the number of entries.
+ *
+ * int (*ndo_bridge_setlink)(struct net_device *dev, struct nlmsghdr *nlh)
+ * int (*ndo_bridge_getlink)(struct sk_buff *skb, u32 pid, u32 seq,
+ *			     struct net_device *dev)
  */
 struct net_device_ops {
 	int			(*ndo_init)(struct net_device *dev);
@@ -998,6 +1002,12 @@ struct net_device_ops {
 						struct netlink_callback *cb,
 						struct net_device *dev,
 						int idx);
+
+	int			(*ndo_bridge_setlink)(struct net_device *dev,
+						      struct nlmsghdr *nlh);
+	int			(*ndo_bridge_getlink)(struct sk_buff *skb,
+						      u32 pid, u32 seq,
+						      struct net_device *dev);
 };
 
 /*
@@ -1499,16 +1509,25 @@ struct packet_type {
 					 struct net_device *,
 					 struct packet_type *,
 					 struct net_device *);
+	bool			(*id_match)(struct packet_type *ptype,
+					    struct sock *sk);
+	void			*af_packet_priv;
+	struct list_head	list;
+};
+
+struct offload_callbacks {
 	struct sk_buff		*(*gso_segment)(struct sk_buff *skb,
 						netdev_features_t features);
 	int			(*gso_send_check)(struct sk_buff *skb);
 	struct sk_buff		**(*gro_receive)(struct sk_buff **head,
 					       struct sk_buff *skb);
 	int			(*gro_complete)(struct sk_buff *skb);
-	bool			(*id_match)(struct packet_type *ptype,
-					    struct sock *sk);
-	void			*af_packet_priv;
-	struct list_head	list;
+};
+
+struct packet_offload {
+	__be16			 type;	/* This is really htons(ether_type). */
+	struct offload_callbacks callbacks;
+	struct list_head	 list;
 };
 
 #include <linux/notifier.h>
@@ -1548,6 +1567,8 @@ extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev);
 
 extern rwlock_t				dev_base_lock;		/* Device list lock */
 
+extern seqlock_t	devnet_rename_seq;	/* Device rename lock */
+
 
 #define for_each_netdev(net, d)		\
 		list_for_each_entry(d, &(net)->dev_base_head, dev_list)
@@ -1605,6 +1626,9 @@ extern struct net_device *__dev_getfirstbyhwtype(struct net *net, unsigned short
 extern void		dev_add_pack(struct packet_type *pt);
 extern void		dev_remove_pack(struct packet_type *pt);
 extern void		__dev_remove_pack(struct packet_type *pt);
+extern void		dev_add_offload(struct packet_offload *po);
+extern void		dev_remove_offload(struct packet_offload *po);
+extern void		__dev_remove_offload(struct packet_offload *po);
 
 extern struct net_device	*dev_get_by_flags_rcu(struct net *net, unsigned short flags,
 						      unsigned short mask);
diff --git a/include/linux/nfc/pn544.h b/include/linux/nfc/pn544.h
deleted file mode 100644
index 9890bba..0000000
--- a/include/linux/nfc/pn544.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Driver include for the PN544 NFC chip.
- *
- * Copyright (C) Nokia Corporation
- *
- * Author: Jari Vanhala <ext-jari.vanhala@nokia.com>
- * Contact: Matti Aaltoenn <matti.j.aaltonen@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _PN544_H_
-#define _PN544_H_
-
-#include <linux/i2c.h>
-
-#define PN544_DRIVER_NAME	"pn544"
-#define PN544_MAXWINDOW_SIZE	7
-#define PN544_WINDOW_SIZE	4
-#define PN544_RETRIES		10
-#define PN544_MAX_I2C_TRANSFER	0x0400
-#define PN544_MSG_MAX_SIZE	0x21 /* at normal HCI mode */
-
-/* ioctl */
-#define PN544_CHAR_BASE		'P'
-#define PN544_IOR(num, dtype)	_IOR(PN544_CHAR_BASE, num, dtype)
-#define PN544_IOW(num, dtype)	_IOW(PN544_CHAR_BASE, num, dtype)
-#define PN544_GET_FW_MODE	PN544_IOW(1, unsigned int)
-#define PN544_SET_FW_MODE	PN544_IOW(2, unsigned int)
-#define PN544_GET_DEBUG		PN544_IOW(3, unsigned int)
-#define PN544_SET_DEBUG		PN544_IOW(4, unsigned int)
-
-/* Timing restrictions (ms) */
-#define PN544_RESETVEN_TIME	30 /* 7 */
-#define PN544_PVDDVEN_TIME	0
-#define PN544_VBATVEN_TIME	0
-#define PN544_GPIO4VEN_TIME	0
-#define PN544_WAKEUP_ACK	5
-#define PN544_WAKEUP_GUARD	(PN544_WAKEUP_ACK + 1)
-#define PN544_INACTIVITY_TIME	1000
-#define PN544_INTERFRAME_DELAY	200 /* us */
-#define PN544_BAUDRATE_CHANGE	150 /* us */
-
-/* Debug bits */
-#define PN544_DEBUG_BUF		0x01
-#define PN544_DEBUG_READ	0x02
-#define PN544_DEBUG_WRITE	0x04
-#define PN544_DEBUG_IRQ		0x08
-#define PN544_DEBUG_CALLS	0x10
-#define PN544_DEBUG_MODE	0x20
-
-/* Normal (HCI) mode */
-#define PN544_LLC_HCI_OVERHEAD	3 /* header + crc (to length) */
-#define PN544_LLC_MIN_SIZE	(1 + PN544_LLC_HCI_OVERHEAD) /* length + */
-#define PN544_LLC_MAX_DATA	(PN544_MSG_MAX_SIZE - 2)
-#define PN544_LLC_MAX_HCI_SIZE	(PN544_LLC_MAX_DATA - 2)
-
-struct pn544_llc_packet {
-	unsigned char length; /* of rest of packet */
-	unsigned char header;
-	unsigned char data[PN544_LLC_MAX_DATA]; /* includes crc-ccitt */
-};
-
-/* Firmware upgrade mode */
-#define PN544_FW_HEADER_SIZE	3
-/* max fw transfer is 1024bytes, but I2C limits it to 0xC0 */
-#define PN544_MAX_FW_DATA	(PN544_MAX_I2C_TRANSFER - PN544_FW_HEADER_SIZE)
-
-struct pn544_fw_packet {
-	unsigned char command; /* status in answer */
-	unsigned char length[2]; /* big-endian order (msf) */
-	unsigned char data[PN544_MAX_FW_DATA];
-};
-
-#ifdef __KERNEL__
-enum {
-	NFC_GPIO_ENABLE,
-	NFC_GPIO_FW_RESET,
-	NFC_GPIO_IRQ
-};
-
-/* board config */
-struct pn544_nfc_platform_data {
-	int (*request_resources) (struct i2c_client *client);
-	void (*free_resources) (void);
-	void (*enable) (int fw);
-	int (*test) (void);
-	void (*disable) (void);
-	int (*get_gpio)(int type);
-};
-#endif /* __KERNEL__ */
-
-#endif /* _PN544_H_ */
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index a9e76ee..6c6ed15 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -198,51 +198,4 @@ struct nfs_server {
 #define NFS_CAP_POSIX_LOCK	(1U << 14)
 #define NFS_CAP_UIDGID_NOMAP	(1U << 15)
 
-
-/* maximum number of slots to use */
-#define NFS4_DEF_SLOT_TABLE_SIZE (16U)
-#define NFS4_MAX_SLOT_TABLE (256U)
-#define NFS4_NO_SLOT ((u32)-1)
-
-#if IS_ENABLED(CONFIG_NFS_V4)
-
-/* Sessions */
-#define SLOT_TABLE_SZ DIV_ROUND_UP(NFS4_MAX_SLOT_TABLE, 8*sizeof(long))
-struct nfs4_slot_table {
-	struct nfs4_slot *slots;		/* seqid per slot */
-	unsigned long   used_slots[SLOT_TABLE_SZ]; /* used/unused bitmap */
-	spinlock_t	slot_tbl_lock;
-	struct rpc_wait_queue	slot_tbl_waitq;	/* allocators may wait here */
-	u32		max_slots;		/* # slots in table */
-	u32		highest_used_slotid;	/* sent to server on each SEQ.
-						 * op for dynamic resizing */
-	u32		target_max_slots;	/* Set by CB_RECALL_SLOT as
-						 * the new max_slots */
-	struct completion complete;
-};
-
-static inline int slot_idx(struct nfs4_slot_table *tbl, struct nfs4_slot *sp)
-{
-	return sp - tbl->slots;
-}
-
-/*
- * Session related parameters
- */
-struct nfs4_session {
-	struct nfs4_sessionid		sess_id;
-	u32				flags;
-	unsigned long			session_state;
-	u32				hash_alg;
-	u32				ssv_len;
-
-	/* The fore and back channel */
-	struct nfs4_channel_attrs	fc_attrs;
-	struct nfs4_slot_table		fc_slot_table;
-	struct nfs4_channel_attrs	bc_attrs;
-	struct nfs4_slot_table		bc_slot_table;
-	struct nfs_client		*clp;
-};
-
-#endif /* CONFIG_NFS_V4 */
 #endif
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index a73ea89..baa673e 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -185,23 +185,19 @@ struct nfs4_channel_attrs {
 	u32			max_reqs;
 };
 
-/* nfs41 sessions slot seqid */
-struct nfs4_slot {
-	u32		 	seq_nr;
-};
-
+struct nfs4_slot;
 struct nfs4_sequence_args {
-	struct nfs4_session	*sa_session;
-	u32			sa_slotid;
-	u8			sa_cache_this;
+	struct nfs4_slot	*sa_slot;
+	u8			sa_cache_this : 1,
+				sa_privileged : 1;
 };
 
 struct nfs4_sequence_res {
-	struct nfs4_session	*sr_session;
 	struct nfs4_slot	*sr_slot;	/* slot used to send request */
 	int			sr_status;	/* sequence operation status */
-	unsigned long		sr_renewal_time;
 	u32			sr_status_flags;
+	u32			sr_highest_slotid;
+	u32			sr_target_highest_slotid;
 };
 
 struct nfs4_get_lease_time_args {
diff --git a/include/linux/node.h b/include/linux/node.h
index 624e53c..2115ad5 100644
--- a/include/linux/node.h
+++ b/include/linux/node.h
@@ -27,10 +27,9 @@ struct node {
 };
 
 struct memory_block;
-extern struct node node_devices[];
+extern struct node *node_devices[];
 typedef  void (*node_registration_func_t)(struct node *);
 
-extern int register_node(struct node *, int, struct node *);
 extern void unregister_node(struct node *node);
 #ifdef CONFIG_NUMA
 extern int register_one_node(int nid);
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index 7afc363..4e2cbfa 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -380,6 +380,11 @@ enum node_states {
 #else
 	N_HIGH_MEMORY = N_NORMAL_MEMORY,
 #endif
+#ifdef CONFIG_MOVABLE_NODE
+	N_MEMORY,		/* The node has memory(regular, high, movable) */
+#else
+	N_MEMORY = N_HIGH_MEMORY,
+#endif
 	N_CPU,		/* The node has one or more cpus */
 	NR_NODE_STATES
 };
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index cc37a55..10e5947 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -67,7 +67,7 @@ void exit_task_namespaces(struct task_struct *tsk);
 void switch_task_namespaces(struct task_struct *tsk, struct nsproxy *new);
 void free_nsproxy(struct nsproxy *ns);
 int unshare_nsproxy_namespaces(unsigned long, struct nsproxy **,
-	struct fs_struct *);
+	struct cred *, struct fs_struct *);
 int __init nsproxy_cache_init(void);
 
 static inline void put_nsproxy(struct nsproxy *ns)
diff --git a/include/linux/of.h b/include/linux/of.h
index b4e50d5..aff44da 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -22,6 +22,7 @@
 #include <linux/mod_devicetable.h>
 #include <linux/spinlock.h>
 #include <linux/topology.h>
+#include <linux/notifier.h>
 
 #include <asm/byteorder.h>
 #include <asm/errno.h>
@@ -46,7 +47,7 @@ struct device_node {
 	const char *name;
 	const char *type;
 	phandle phandle;
-	char	*full_name;
+	const char *full_name;
 
 	struct	property *properties;
 	struct	property *deadprops;	/* removed properties */
@@ -60,7 +61,7 @@ struct device_node {
 	unsigned long _flags;
 	void	*data;
 #if defined(CONFIG_SPARC)
-	char	*path_component_name;
+	const char *path_component_name;
 	unsigned int unique_id;
 	struct of_irq_controller *irq_trans;
 #endif
@@ -179,11 +180,22 @@ extern struct device_node *of_find_compatible_node(struct device_node *from,
 #define for_each_compatible_node(dn, type, compatible) \
 	for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
 	     dn = of_find_compatible_node(dn, type, compatible))
-extern struct device_node *of_find_matching_node(struct device_node *from,
-	const struct of_device_id *matches);
+extern struct device_node *of_find_matching_node_and_match(
+	struct device_node *from,
+	const struct of_device_id *matches,
+	const struct of_device_id **match);
+static inline struct device_node *of_find_matching_node(
+	struct device_node *from,
+	const struct of_device_id *matches)
+{
+	return of_find_matching_node_and_match(from, matches, NULL);
+}
 #define for_each_matching_node(dn, matches) \
 	for (dn = of_find_matching_node(NULL, matches); dn; \
 	     dn = of_find_matching_node(dn, matches))
+#define for_each_matching_node_and_match(dn, matches, match) \
+	for (dn = of_find_matching_node_and_match(NULL, matches, match); \
+	     dn; dn = of_find_matching_node_and_match(dn, matches, match))
 extern struct device_node *of_find_node_by_path(const char *path);
 extern struct device_node *of_find_node_by_phandle(phandle handle);
 extern struct device_node *of_get_parent(const struct device_node *node);
@@ -223,6 +235,10 @@ extern struct device_node *of_find_node_with_property(
 extern struct property *of_find_property(const struct device_node *np,
 					 const char *name,
 					 int *lenp);
+extern int of_property_read_u8_array(const struct device_node *np,
+			const char *propname, u8 *out_values, size_t sz);
+extern int of_property_read_u16_array(const struct device_node *np,
+			const char *propname, u16 *out_values, size_t sz);
 extern int of_property_read_u32_array(const struct device_node *np,
 				      const char *propname,
 				      u32 *out_values,
@@ -267,16 +283,28 @@ extern int of_alias_get_id(struct device_node *np, const char *stem);
 
 extern int of_machine_is_compatible(const char *compat);
 
-extern int prom_add_property(struct device_node* np, struct property* prop);
-extern int prom_remove_property(struct device_node *np, struct property *prop);
-extern int prom_update_property(struct device_node *np,
-				struct property *newprop);
+extern int of_add_property(struct device_node *np, struct property *prop);
+extern int of_remove_property(struct device_node *np, struct property *prop);
+extern int of_update_property(struct device_node *np, struct property *newprop);
 
-#if defined(CONFIG_OF_DYNAMIC)
 /* For updating the device tree at runtime */
-extern void of_attach_node(struct device_node *);
-extern void of_detach_node(struct device_node *);
-#endif
+#define OF_RECONFIG_ATTACH_NODE		0x0001
+#define OF_RECONFIG_DETACH_NODE		0x0002
+#define OF_RECONFIG_ADD_PROPERTY	0x0003
+#define OF_RECONFIG_REMOVE_PROPERTY	0x0004
+#define OF_RECONFIG_UPDATE_PROPERTY	0x0005
+
+struct of_prop_reconfig {
+	struct device_node	*dn;
+	struct property		*prop;
+};
+
+extern int of_reconfig_notifier_register(struct notifier_block *);
+extern int of_reconfig_notifier_unregister(struct notifier_block *);
+extern int of_reconfig_notify(unsigned long, void *);
+
+extern int of_attach_node(struct device_node *);
+extern int of_detach_node(struct device_node *);
 
 #define of_match_ptr(_ptr)	(_ptr)
 
@@ -364,6 +392,18 @@ static inline struct device_node *of_find_compatible_node(
 	return NULL;
 }
 
+static inline int of_property_read_u8_array(const struct device_node *np,
+			const char *propname, u8 *out_values, size_t sz)
+{
+	return -ENOSYS;
+}
+
+static inline int of_property_read_u16_array(const struct device_node *np,
+			const char *propname, u16 *out_values, size_t sz)
+{
+	return -ENOSYS;
+}
+
 static inline int of_property_read_u32_array(const struct device_node *np,
 					     const char *propname,
 					     u32 *out_values, size_t sz)
@@ -470,6 +510,20 @@ static inline bool of_property_read_bool(const struct device_node *np,
 	return prop ? true : false;
 }
 
+static inline int of_property_read_u8(const struct device_node *np,
+				       const char *propname,
+				       u8 *out_value)
+{
+	return of_property_read_u8_array(np, propname, out_value, 1);
+}
+
+static inline int of_property_read_u16(const struct device_node *np,
+				       const char *propname,
+				       u16 *out_value)
+{
+	return of_property_read_u16_array(np, propname, out_value, 1);
+}
+
 static inline int of_property_read_u32(const struct device_node *np,
 				       const char *propname,
 				       u32 *out_value)
diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h
new file mode 100644
index 0000000..84b64f8
--- /dev/null
+++ b/include/linux/of_dma.h
@@ -0,0 +1,73 @@
+/*
+ * OF helpers for DMA request / controller
+ *
+ * Based on of_gpio.h
+ *
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef __LINUX_OF_DMA_H
+#define __LINUX_OF_DMA_H
+
+#include <linux/of.h>
+#include <linux/dmaengine.h>
+
+struct device_node;
+
+struct of_dma {
+	struct list_head	of_dma_controllers;
+	struct device_node	*of_node;
+	int			of_dma_nbcells;
+	struct dma_chan		*(*of_dma_xlate)
+				(struct of_phandle_args *, struct of_dma *);
+	void			*of_dma_data;
+	int			use_count;
+};
+
+struct of_dma_filter_info {
+	dma_cap_mask_t	dma_cap;
+	dma_filter_fn	filter_fn;
+};
+
+#ifdef CONFIG_OF
+extern int of_dma_controller_register(struct device_node *np,
+		struct dma_chan *(*of_dma_xlate)
+		(struct of_phandle_args *, struct of_dma *),
+		void *data);
+extern int of_dma_controller_free(struct device_node *np);
+extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
+						     char *name);
+extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
+		struct of_dma *ofdma);
+#else
+static int of_dma_controller_register(struct device_node *np,
+		struct dma_chan *(*of_dma_xlate)
+		(struct of_phandle_args *, struct of_dma *),
+		void *data)
+{
+	return -ENODEV;
+}
+
+static int of_dma_controller_free(struct device_node *np)
+{
+}
+
+static struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
+						     char *name)
+{
+	return NULL;
+}
+
+static struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
+		struct of_dma *ofdma)
+{
+	return NULL;
+}
+
+#endif
+
+#endif /* __LINUX_OF_DMA_H */
diff --git a/include/linux/oom.h b/include/linux/oom.h
index fb98268..da60007 100644
--- a/include/linux/oom.h
+++ b/include/linux/oom.h
@@ -29,8 +29,23 @@ enum oom_scan_t {
 	OOM_SCAN_SELECT,	/* always select this thread first */
 };
 
-extern void compare_swap_oom_score_adj(int old_val, int new_val);
-extern int test_set_oom_score_adj(int new_val);
+/* Thread is the potential origin of an oom condition; kill first on oom */
+#define OOM_FLAG_ORIGIN		((__force oom_flags_t)0x1)
+
+static inline void set_current_oom_origin(void)
+{
+	current->signal->oom_flags |= OOM_FLAG_ORIGIN;
+}
+
+static inline void clear_current_oom_origin(void)
+{
+	current->signal->oom_flags &= ~OOM_FLAG_ORIGIN;
+}
+
+static inline bool oom_task_origin(const struct task_struct *p)
+{
+	return !!(p->signal->oom_flags & OOM_FLAG_ORIGIN);
+}
 
 extern unsigned long oom_badness(struct task_struct *p,
 		struct mem_cgroup *memcg, const nodemask_t *nodemask,
@@ -49,8 +64,6 @@ extern void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask,
 extern enum oom_scan_t oom_scan_process_thread(struct task_struct *task,
 		unsigned long totalpages, const nodemask_t *nodemask,
 		bool force_kill);
-extern void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
-				     int order);
 
 extern void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
 		int order, nodemask_t *mask, bool force_kill);
diff --git a/include/linux/page-flags-layout.h b/include/linux/page-flags-layout.h
new file mode 100644
index 0000000..b258132
--- /dev/null
+++ b/include/linux/page-flags-layout.h
@@ -0,0 +1,83 @@
+#ifndef _LINUX_PAGE_FLAGS_LAYOUT
+#define _LINUX_PAGE_FLAGS_LAYOUT
+
+#include <linux/numa.h>
+#include <generated/bounds.h>
+
+#if MAX_NR_ZONES < 2
+#define ZONES_SHIFT 0
+#elif MAX_NR_ZONES <= 2
+#define ZONES_SHIFT 1
+#elif MAX_NR_ZONES <= 4
+#define ZONES_SHIFT 2
+#else
+#error ZONES_SHIFT -- too many zones configured adjust calculation
+#endif
+
+#ifdef CONFIG_SPARSEMEM
+#include <asm/sparsemem.h>
+
+/* 
+ * SECTION_SHIFT    		#bits space required to store a section #
+ */
+#define SECTIONS_SHIFT         (MAX_PHYSMEM_BITS - SECTION_SIZE_BITS)
+#endif
+
+/*
+ * page->flags layout:
+ *
+ * There are five possibilities for how page->flags get laid out.  The first
+ * (and second) is for the normal case, without sparsemem. The third is for
+ * sparsemem when there is plenty of space for node and section. The last is
+ * when we have run out of space and have to fall back to an alternate (slower)
+ * way of determining the node.
+ *
+ * No sparsemem or sparsemem vmemmap: |       NODE     | ZONE |            ... | FLAGS |
+ *     "      plus space for last_cpu:|       NODE     | ZONE | LAST_CPU | ... | FLAGS |
+ * classic sparse with space for node:| SECTION | NODE | ZONE |            ... | FLAGS |
+ *     "      plus space for last_cpu:| SECTION | NODE | ZONE | LAST_CPU | ... | FLAGS |
+ * classic sparse no space for node:  | SECTION |     ZONE    |            ... | FLAGS |
+ */
+#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
+
+#define SECTIONS_WIDTH		SECTIONS_SHIFT
+#else
+#define SECTIONS_WIDTH		0
+#endif
+
+#define ZONES_WIDTH		ZONES_SHIFT
+
+#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS
+#define NODES_WIDTH		NODES_SHIFT
+#else
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+#error "Vmemmap: No space for nodes field in page flags"
+#endif
+#define NODES_WIDTH		0
+#endif
+
+#ifdef CONFIG_NUMA_BALANCING
+#define LAST_CPU_SHIFT	NR_CPUS_BITS
+#else
+#define LAST_CPU_SHIFT	0
+#endif
+
+#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT+LAST_CPU_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS
+#define LAST_CPU_WIDTH	LAST_CPU_SHIFT
+#else
+#define LAST_CPU_WIDTH	0
+#endif
+
+/*
+ * We are going to use the flags for the page to node mapping if its in
+ * there.  This includes the case where there is no node, so it is implicit.
+ */
+#if !(NODES_WIDTH > 0 || NODES_SHIFT == 0)
+#define NODE_NOT_IN_PAGE_FLAGS
+#endif
+
+#if defined(CONFIG_NUMA_BALANCING) && LAST_CPU_WIDTH == 0
+#define LAST_CPU_NOT_IN_PAGE_FLAGS
+#endif
+
+#endif /* _LINUX_PAGE_FLAGS_LAYOUT */
diff --git a/include/linux/page-isolation.h b/include/linux/page-isolation.h
index 76a9539..a92061e 100644
--- a/include/linux/page-isolation.h
+++ b/include/linux/page-isolation.h
@@ -2,7 +2,8 @@
 #define __LINUX_PAGEISOLATION_H
 
 
-bool has_unmovable_pages(struct zone *zone, struct page *page, int count);
+bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
+			 bool skip_hwpoisoned_pages);
 void set_pageblock_migratetype(struct page *page, int migratetype);
 int move_freepages_block(struct zone *zone, struct page *page,
 				int migratetype);
@@ -21,7 +22,7 @@ int move_freepages(struct zone *zone,
  */
 int
 start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
-			 unsigned migratetype);
+			 unsigned migratetype, bool skip_hwpoisoned_pages);
 
 /*
  * Changes MIGRATE_ISOLATE to MIGRATE_MOVABLE.
@@ -34,12 +35,13 @@ undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
 /*
  * Test all pages in [start_pfn, end_pfn) are isolated or not.
  */
-int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn);
+int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn,
+			bool skip_hwpoisoned_pages);
 
 /*
  * Internal functions. Changes pageblock's migrate type.
  */
-int set_migratetype_isolate(struct page *page);
+int set_migratetype_isolate(struct page *page, bool skip_hwpoisoned_pages);
 void unset_migratetype_isolate(struct page *page, unsigned migratetype);
 struct page *alloc_migrate_target(struct page *page, unsigned long private,
 				int **resultp);
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index e42c762..6da609d 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -24,6 +24,7 @@ enum mapping_flags {
 	AS_ENOSPC	= __GFP_BITS_SHIFT + 1,	/* ENOSPC on async write */
 	AS_MM_ALL_LOCKS	= __GFP_BITS_SHIFT + 2,	/* under mm_take_all_locks() */
 	AS_UNEVICTABLE	= __GFP_BITS_SHIFT + 3,	/* e.g., ramdisk, SHM_LOCK */
+	AS_BALLOON_MAP  = __GFP_BITS_SHIFT + 4, /* balloon page special map */
 };
 
 static inline void mapping_set_error(struct address_space *mapping, int error)
@@ -53,6 +54,21 @@ static inline int mapping_unevictable(struct address_space *mapping)
 	return !!mapping;
 }
 
+static inline void mapping_set_balloon(struct address_space *mapping)
+{
+	set_bit(AS_BALLOON_MAP, &mapping->flags);
+}
+
+static inline void mapping_clear_balloon(struct address_space *mapping)
+{
+	clear_bit(AS_BALLOON_MAP, &mapping->flags);
+}
+
+static inline int mapping_balloon(struct address_space *mapping)
+{
+	return mapping && test_bit(AS_BALLOON_MAP, &mapping->flags);
+}
+
 static inline gfp_t mapping_gfp_mask(struct address_space * mapping)
 {
 	return (__force gfp_t)mapping->flags & __GFP_BITS_MASK;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index ee21795..d536fbf 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -538,6 +538,9 @@ enum pci_ers_result {
 
 	/* Device driver is fully recovered and operational */
 	PCI_ERS_RESULT_RECOVERED = (__force pci_ers_result_t) 5,
+
+	/* No AER capabilities registered for the driver */
+	PCI_ERS_RESULT_NO_AER_DRIVER = (__force pci_ers_result_t) 6,
 };
 
 /* PCI bus error event callbacks */
@@ -573,6 +576,7 @@ struct pci_driver {
 	int  (*resume_early) (struct pci_dev *dev);
 	int  (*resume) (struct pci_dev *dev);	                /* Device woken up */
 	void (*shutdown) (struct pci_dev *dev);
+	int (*sriov_configure) (struct pci_dev *dev, int num_vfs); /* PF pdev */
 	const struct pci_error_handlers *err_handler;
 	struct device_driver	driver;
 	struct pci_dynids dynids;
@@ -588,7 +592,7 @@ struct pci_driver {
  * in a generic manner.
  */
 #define DEFINE_PCI_DEVICE_TABLE(_table) \
-	const struct pci_device_id _table[] __devinitconst
+	const struct pci_device_id _table[]
 
 /**
  * PCI_DEVICE - macro used to describe a specific pci device
@@ -604,6 +608,20 @@ struct pci_driver {
 	.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
 
 /**
+ * PCI_DEVICE_SUB - macro used to describe a specific pci device with subsystem
+ * @vend: the 16 bit PCI Vendor ID
+ * @dev: the 16 bit PCI Device ID
+ * @subvend: the 16 bit PCI Subvendor ID
+ * @subdev: the 16 bit PCI Subdevice ID
+ *
+ * This macro is used to create a struct pci_device_id that matches a
+ * specific device with subsystem information.
+ */
+#define PCI_DEVICE_SUB(vend, dev, subvend, subdev) \
+	.vendor = (vend), .device = (dev), \
+	.subvendor = (subvend), .subdevice = (subdev)
+
+/**
  * PCI_DEVICE_CLASS - macro used to describe a specific pci device class
  * @dev_class: the class, subclass, prog-if triple for this device
  * @dev_class_mask: the class mask for this device
@@ -686,7 +704,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
 int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
 void pci_bus_release_busn_res(struct pci_bus *b);
-struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
+struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
 					     struct pci_ops *ops, void *sysdata,
 					     struct list_head *resources);
 struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
@@ -712,6 +730,8 @@ extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
 extern void pci_dev_put(struct pci_dev *dev);
 extern void pci_remove_bus(struct pci_bus *b);
 extern void pci_stop_and_remove_bus_device(struct pci_dev *dev);
+void pci_stop_root_bus(struct pci_bus *bus);
+void pci_remove_root_bus(struct pci_bus *bus);
 void pci_setup_cardbus(struct pci_bus *bus);
 extern void pci_sort_breadthfirst(void);
 #define dev_is_pci(d) ((d)->bus == &pci_bus_type)
@@ -941,10 +961,8 @@ void set_pcie_hotplug_bridge(struct pci_dev *pdev);
 
 /* Functions for PCI Hotplug drivers to use */
 int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap);
-#ifdef CONFIG_HOTPLUG
 unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge);
 unsigned int pci_rescan_bus(struct pci_bus *bus);
-#endif
 
 /* Vital product data routines */
 ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf);
@@ -958,6 +976,7 @@ void pci_bus_size_bridges(struct pci_bus *bus);
 int pci_claim_resource(struct pci_dev *, int);
 void pci_assign_unassigned_resources(void);
 void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge);
+void pci_assign_unassigned_bus_resources(struct pci_bus *bus);
 void pdev_enable_device(struct pci_dev *);
 int pci_enable_resources(struct pci_dev *, int mask);
 void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
@@ -1580,7 +1599,7 @@ extern int pci_pci_problems;
 
 extern unsigned long pci_cardbus_io_size;
 extern unsigned long pci_cardbus_mem_size;
-extern u8 __devinitdata pci_dfl_cache_line_size;
+extern u8 pci_dfl_cache_line_size;
 extern u8 pci_cache_line_size;
 
 extern unsigned long pci_hotplug_io_size;
@@ -1601,7 +1620,7 @@ static inline void pci_mmcfg_early_init(void) { }
 static inline void pci_mmcfg_late_init(void) { }
 #endif
 
-int pci_ext_cfg_avail(struct pci_dev *dev);
+int pci_ext_cfg_avail(void);
 
 void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar);
 
@@ -1610,6 +1629,8 @@ extern int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
 extern void pci_disable_sriov(struct pci_dev *dev);
 extern irqreturn_t pci_sriov_migration(struct pci_dev *dev);
 extern int pci_num_vf(struct pci_dev *dev);
+extern int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
+extern int pci_sriov_get_totalvfs(struct pci_dev *dev);
 #else
 static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
 {
@@ -1626,6 +1647,14 @@ static inline int pci_num_vf(struct pci_dev *dev)
 {
 	return 0;
 }
+static inline int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
+{
+	return 0;
+}
+static inline int pci_sriov_get_totalvfs(struct pci_dev *dev)
+{
+	return 0;
+}
 #endif
 
 #if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 9d36b82..0f84473 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1985,6 +1985,9 @@
 #define PCI_DEVICE_ID_EXAR_XR17C152	0x0152
 #define PCI_DEVICE_ID_EXAR_XR17C154	0x0154
 #define PCI_DEVICE_ID_EXAR_XR17C158	0x0158
+#define PCI_DEVICE_ID_EXAR_XR17V352	0x0352
+#define PCI_DEVICE_ID_EXAR_XR17V354	0x0354
+#define PCI_DEVICE_ID_EXAR_XR17V358	0x0358
 
 #define PCI_VENDOR_ID_MICROGATE		0x13c0
 #define PCI_DEVICE_ID_MICROGATE_USC	0x0010
@@ -2323,6 +2326,8 @@
 
 #define PCI_VENDOR_ID_TOPSPIN		0x1867
 
+#define PCI_VENDOR_ID_COMMTECH		0x18f7
+
 #define PCI_VENDOR_ID_SILAN		0x1904
 
 #define PCI_VENDOR_ID_RENESAS		0x1912
diff --git a/include/linux/percpu-rwsem.h b/include/linux/percpu-rwsem.h
index 250a4ac..3e88c9a 100644
--- a/include/linux/percpu-rwsem.h
+++ b/include/linux/percpu-rwsem.h
@@ -1,83 +1,34 @@
 #ifndef _LINUX_PERCPU_RWSEM_H
 #define _LINUX_PERCPU_RWSEM_H
 
-#include <linux/mutex.h>
+#include <linux/atomic.h>
+#include <linux/rwsem.h>
 #include <linux/percpu.h>
-#include <linux/rcupdate.h>
-#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/lockdep.h>
 
 struct percpu_rw_semaphore {
-	unsigned __percpu *counters;
-	bool locked;
-	struct mutex mtx;
+	unsigned int __percpu	*fast_read_ctr;
+	atomic_t		write_ctr;
+	struct rw_semaphore	rw_sem;
+	atomic_t		slow_read_ctr;
+	wait_queue_head_t	write_waitq;
 };
 
-#define light_mb()	barrier()
-#define heavy_mb()	synchronize_sched()
+extern void percpu_down_read(struct percpu_rw_semaphore *);
+extern void percpu_up_read(struct percpu_rw_semaphore *);
 
-static inline void percpu_down_read(struct percpu_rw_semaphore *p)
-{
-	rcu_read_lock_sched();
-	if (unlikely(p->locked)) {
-		rcu_read_unlock_sched();
-		mutex_lock(&p->mtx);
-		this_cpu_inc(*p->counters);
-		mutex_unlock(&p->mtx);
-		return;
-	}
-	this_cpu_inc(*p->counters);
-	rcu_read_unlock_sched();
-	light_mb(); /* A, between read of p->locked and read of data, paired with D */
-}
+extern void percpu_down_write(struct percpu_rw_semaphore *);
+extern void percpu_up_write(struct percpu_rw_semaphore *);
 
-static inline void percpu_up_read(struct percpu_rw_semaphore *p)
-{
-	light_mb(); /* B, between read of the data and write to p->counter, paired with C */
-	this_cpu_dec(*p->counters);
-}
+extern int __percpu_init_rwsem(struct percpu_rw_semaphore *,
+				const char *, struct lock_class_key *);
+extern void percpu_free_rwsem(struct percpu_rw_semaphore *);
 
-static inline unsigned __percpu_count(unsigned __percpu *counters)
-{
-	unsigned total = 0;
-	int cpu;
-
-	for_each_possible_cpu(cpu)
-		total += ACCESS_ONCE(*per_cpu_ptr(counters, cpu));
-
-	return total;
-}
-
-static inline void percpu_down_write(struct percpu_rw_semaphore *p)
-{
-	mutex_lock(&p->mtx);
-	p->locked = true;
-	synchronize_sched(); /* make sure that all readers exit the rcu_read_lock_sched region */
-	while (__percpu_count(p->counters))
-		msleep(1);
-	heavy_mb(); /* C, between read of p->counter and write to data, paired with B */
-}
-
-static inline void percpu_up_write(struct percpu_rw_semaphore *p)
-{
-	heavy_mb(); /* D, between write to data and write to p->locked, paired with A */
-	p->locked = false;
-	mutex_unlock(&p->mtx);
-}
-
-static inline int percpu_init_rwsem(struct percpu_rw_semaphore *p)
-{
-	p->counters = alloc_percpu(unsigned);
-	if (unlikely(!p->counters))
-		return -ENOMEM;
-	p->locked = false;
-	mutex_init(&p->mtx);
-	return 0;
-}
-
-static inline void percpu_free_rwsem(struct percpu_rw_semaphore *p)
-{
-	free_percpu(p->counters);
-	p->counters = NULL; /* catch use after free bugs */
-}
+#define percpu_init_rwsem(brw)	\
+({								\
+	static struct lock_class_key rwsem_key;			\
+	__percpu_init_rwsem(brw, #brw, &rwsem_key);		\
+})
 
 #endif
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index 65e3e87..bf28599 100644
--- a/include/linux/pid_namespace.h
+++ b/include/linux/pid_namespace.h
@@ -21,6 +21,7 @@ struct pid_namespace {
 	struct kref kref;
 	struct pidmap pidmap[PIDMAP_ENTRIES];
 	int last_pid;
+	int nr_hashed;
 	struct task_struct *child_reaper;
 	struct kmem_cache *pid_cachep;
 	unsigned int level;
@@ -31,9 +32,12 @@ struct pid_namespace {
 #ifdef CONFIG_BSD_PROCESS_ACCT
 	struct bsd_acct_struct *bacct;
 #endif
+	struct user_namespace *user_ns;
+	struct work_struct proc_work;
 	kgid_t pid_gid;
 	int hide_pid;
 	int reboot;	/* group exit code if this pidns was rebooted */
+	unsigned int proc_inum;
 };
 
 extern struct pid_namespace init_pid_ns;
@@ -46,7 +50,8 @@ static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns)
 	return ns;
 }
 
-extern struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *ns);
+extern struct pid_namespace *copy_pid_ns(unsigned long flags,
+	struct user_namespace *user_ns, struct pid_namespace *ns);
 extern void zap_pid_ns_processes(struct pid_namespace *pid_ns);
 extern int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd);
 extern void put_pid_ns(struct pid_namespace *ns);
@@ -59,8 +64,8 @@ static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns)
 	return ns;
 }
 
-static inline struct pid_namespace *
-copy_pid_ns(unsigned long flags, struct pid_namespace *ns)
+static inline struct pid_namespace *copy_pid_ns(unsigned long flags,
+	struct user_namespace *user_ns, struct pid_namespace *ns)
 {
 	if (flags & CLONE_NEWPID)
 		ns = ERR_PTR(-EINVAL);
diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h
index 4f0abb9..47a1bdd 100644
--- a/include/linux/pinctrl/pinconf-generic.h
+++ b/include/linux/pinctrl/pinconf-generic.h
@@ -46,11 +46,11 @@
  * @PIN_CONFIG_DRIVE_OPEN_SOURCE: the pin will be driven with open source
  *	(open emitter). Sending this config will enabale open drain mode, the
  *	argument is ignored.
+ * @PIN_CONFIG_INPUT_SCHMITT_DISABLE: disable schmitt-trigger mode on the pin.
  * @PIN_CONFIG_INPUT_SCHMITT: this will configure an input pin to run in
  *	schmitt-trigger mode. If the schmitt-trigger has adjustable hysteresis,
  *	the threshold value is given on a custom format as argument when
- *	setting pins to this mode. The argument zero turns the schmitt trigger
- *	off.
+ *	setting pins to this mode.
  * @PIN_CONFIG_INPUT_DEBOUNCE: this will configure the pin to debounce mode,
  *	which means it will wait for signals to settle when reading inputs. The
  *	argument gives the debounce time on a custom format. Setting the
@@ -74,6 +74,7 @@ enum pin_config_param {
 	PIN_CONFIG_DRIVE_PUSH_PULL,
 	PIN_CONFIG_DRIVE_OPEN_DRAIN,
 	PIN_CONFIG_DRIVE_OPEN_SOURCE,
+	PIN_CONFIG_INPUT_SCHMITT_DISABLE,
 	PIN_CONFIG_INPUT_SCHMITT,
 	PIN_CONFIG_INPUT_DEBOUNCE,
 	PIN_CONFIG_POWER_SOURCE,
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
index 7d087f0..04d6700 100644
--- a/include/linux/pinctrl/pinctrl.h
+++ b/include/linux/pinctrl/pinctrl.h
@@ -134,6 +134,25 @@ extern void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
 extern void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
 				struct pinctrl_gpio_range *ranges,
 				unsigned nranges);
+extern void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
+				struct pinctrl_gpio_range *range);
+
+extern struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname,
+		struct pinctrl_gpio_range *range);
+extern struct pinctrl_gpio_range *
+pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev,
+				 unsigned int pin);
+
+#ifdef CONFIG_OF
+extern struct pinctrl_dev *of_pinctrl_get(struct device_node *np);
+#else
+static inline
+struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
+{
+	return NULL;
+}
+#endif /* CONFIG_OF */
+
 extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);
 extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
 #else
diff --git a/include/linux/platform_data/ad5449.h b/include/linux/platform_data/ad5449.h
new file mode 100644
index 0000000..bd712bd
--- /dev/null
+++ b/include/linux/platform_data/ad5449.h
@@ -0,0 +1,40 @@
+/*
+ * AD5415, AD5426, AD5429, AD5432, AD5439, AD5443, AD5449 Digital to Analog
+ * Converter driver.
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *  Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef __LINUX_PLATFORM_DATA_AD5449_H__
+#define __LINUX_PLATFORM_DATA_AD5449_H__
+
+/**
+ * enum ad5449_sdo_mode - AD5449 SDO pin configuration
+ * @AD5449_SDO_DRIVE_FULL: Drive the SDO pin with full strength.
+ * @AD5449_SDO_DRIVE_WEAK: Drive the SDO pin with not full strength.
+ * @AD5449_SDO_OPEN_DRAIN: Operate the SDO pin in open-drain mode.
+ * @AD5449_SDO_DISABLED: Disable the SDO pin, in this mode it is not possible to
+ *			read back from the device.
+ */
+enum ad5449_sdo_mode {
+	AD5449_SDO_DRIVE_FULL = 0x0,
+	AD5449_SDO_DRIVE_WEAK = 0x1,
+	AD5449_SDO_OPEN_DRAIN = 0x2,
+	AD5449_SDO_DISABLED = 0x3,
+};
+
+/**
+ * struct ad5449_platform_data - Platform data for the ad5449 DAC driver
+ * @sdo_mode: SDO pin mode
+ * @hardware_clear_to_midscale: Whether asserting the hardware CLR pin sets the
+ *			outputs to midscale (true) or to zero scale(false).
+ */
+struct ad5449_platform_data {
+	enum ad5449_sdo_mode sdo_mode;
+	bool hardware_clear_to_midscale;
+};
+
+#endif
diff --git a/include/linux/platform_data/ad7298.h b/include/linux/platform_data/ad7298.h
new file mode 100644
index 0000000..fbf8adf
--- /dev/null
+++ b/include/linux/platform_data/ad7298.h
@@ -0,0 +1,20 @@
+/*
+ * AD7298 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef __LINUX_PLATFORM_DATA_AD7298_H__
+#define __LINUX_PLATFORM_DATA_AD7298_H__
+
+/**
+ * struct ad7298_platform_data - Platform data for the ad7298 ADC driver
+ * @ext_ref: Whether to use an external reference voltage.
+ **/
+struct ad7298_platform_data {
+	bool ext_ref;
+};
+
+#endif /* IIO_ADC_AD7298_H_ */
diff --git a/include/linux/platform_data/ad7887.h b/include/linux/platform_data/ad7887.h
new file mode 100644
index 0000000..1e06eac
--- /dev/null
+++ b/include/linux/platform_data/ad7887.h
@@ -0,0 +1,26 @@
+/*
+ * AD7887 SPI ADC driver
+ *
+ * Copyright 2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+#ifndef IIO_ADC_AD7887_H_
+#define IIO_ADC_AD7887_H_
+
+/**
+ * struct ad7887_platform_data - AD7887 ADC driver platform data
+ * @en_dual: Whether to use dual channel mode. If set to true AIN1 becomes the
+ *	second input channel, and Vref is internally connected to Vdd. If set to
+ *	false the device is used in single channel mode and AIN1/Vref is used as
+ *	VREF input.
+ * @use_onchip_ref: Whether to use the onchip reference. If set to true the
+ *	internal 2.5V reference is used. If set to false a external reference is
+ *	used.
+ */
+struct ad7887_platform_data {
+	bool en_dual;
+	bool use_onchip_ref;
+};
+
+#endif /* IIO_ADC_AD7887_H_ */
diff --git a/include/linux/platform_data/ads7828.h b/include/linux/platform_data/ads7828.h
new file mode 100644
index 0000000..3245f45
--- /dev/null
+++ b/include/linux/platform_data/ads7828.h
@@ -0,0 +1,29 @@
+/*
+ * TI ADS7828 A/D Converter platform data definition
+ *
+ * Copyright (c) 2012 Savoir-faire Linux Inc.
+ *          Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+ *
+ * For further information, see the Documentation/hwmon/ads7828 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.
+ */
+
+#ifndef _PDATA_ADS7828_H
+#define _PDATA_ADS7828_H
+
+/**
+ * struct ads7828_platform_data - optional ADS7828 connectivity info
+ * @diff_input:		Differential input mode.
+ * @ext_vref:		Use an external voltage reference.
+ * @vref_mv:		Voltage reference value, if external.
+ */
+struct ads7828_platform_data {
+	bool diff_input;
+	bool ext_vref;
+	unsigned int vref_mv;
+};
+
+#endif /* _PDATA_ADS7828_H */
diff --git a/include/linux/platform_data/asoc-imx-ssi.h b/include/linux/platform_data/asoc-imx-ssi.h
index 63f3c28..92c7fd7 100644
--- a/include/linux/platform_data/asoc-imx-ssi.h
+++ b/include/linux/platform_data/asoc-imx-ssi.h
@@ -17,5 +17,7 @@ struct imx_ssi_platform_data {
 	void (*ac97_warm_reset)(struct snd_ac97 *ac97);
 };
 
+extern int mxc_set_irq_fiq(unsigned int irq, unsigned int type);
+
 #endif /* __MACH_SSI_H */
 
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h
index b0f2c56..6a293b7 100644
--- a/include/linux/platform_data/atmel.h
+++ b/include/linux/platform_data/atmel.h
@@ -8,6 +8,55 @@
 #define __ATMEL_H__
 
 #include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/spi/spi.h>
+#include <linux/usb/atmel_usba_udc.h>
+#include <linux/atmel-mci.h>
+#include <sound/atmel-ac97c.h>
+#include <linux/serial.h>
+#include <linux/platform_data/macb.h>
+
+/*
+ * at91: 6 USARTs and one DBGU port (SAM9260)
+ * avr32: 4
+ */
+#define ATMEL_MAX_UART	7
+
+ /* USB Device */
+struct at91_udc_data {
+	int	vbus_pin;		/* high == host powering us */
+	u8	vbus_active_low;	/* vbus polarity */
+	u8	vbus_polled;		/* Use polling, not interrupt */
+	int	pullup_pin;		/* active == D+ pulled up */
+	u8	pullup_active_low;	/* true == pullup_pin is active low */
+};
+
+ /* Compact Flash */
+struct at91_cf_data {
+	int	irq_pin;		/* I/O IRQ */
+	int	det_pin;		/* Card detect */
+	int	vcc_pin;		/* power switching */
+	int	rst_pin;		/* card reset */
+	u8	chipselect;		/* EBI Chip Select number */
+	u8	flags;
+#define AT91_CF_TRUE_IDE	0x01
+#define AT91_IDE_SWAP_A0_A2	0x02
+};
+
+ /* USB Host */
+#define AT91_MAX_USBH_PORTS	3
+struct at91_usbh_data {
+	int		vbus_pin[AT91_MAX_USBH_PORTS];	/* port power-control pin */
+	int             overcurrent_pin[AT91_MAX_USBH_PORTS];
+	u8		ports;				/* number of ports on root hub */
+	u8              overcurrent_supported;
+	u8              vbus_pin_active_low[AT91_MAX_USBH_PORTS];
+	u8              overcurrent_status[AT91_MAX_USBH_PORTS];
+	u8              overcurrent_changed[AT91_MAX_USBH_PORTS];
+};
 
  /* NAND / SmartMedia */
 struct atmel_nand_data {
@@ -24,4 +73,28 @@ struct atmel_nand_data {
 	unsigned int	num_parts;
 };
 
+ /* Serial */
+struct atmel_uart_data {
+	int			num;		/* port num */
+	short			use_dma_tx;	/* use transmit DMA? */
+	short			use_dma_rx;	/* use receive DMA? */
+	void __iomem		*regs;		/* virt. base address, if any */
+	struct serial_rs485	rs485;		/* rs485 settings */
+};
+
+ /* Touchscreen Controller */
+struct at91_tsadcc_data {
+	unsigned int    adc_clock;
+	u8		pendet_debounce;
+	u8		ts_sample_hold_time;
+};
+
+/* CAN */
+struct at91_can_data {
+	void (*transceiver_switch)(int on);
+};
+
+/* FIXME: this needs a better location, but gets stuff building again */
+extern int at91_suspend_entering_slow_clock(void);
+
 #endif /* __ATMEL_H__ */
diff --git a/include/linux/platform_data/clk-integrator.h b/include/linux/platform_data/clk-integrator.h
index 83fe9c2..280edac 100644
--- a/include/linux/platform_data/clk-integrator.h
+++ b/include/linux/platform_data/clk-integrator.h
@@ -1 +1,3 @@
 void integrator_clk_init(bool is_cp);
+void integrator_impd1_clk_init(void __iomem *base, unsigned int id);
+void integrator_impd1_clk_exit(unsigned int id);
diff --git a/include/linux/platform_data/clocksource-nomadik-mtu.h b/include/linux/platform_data/clocksource-nomadik-mtu.h
new file mode 100644
index 0000000..8008897
--- /dev/null
+++ b/include/linux/platform_data/clocksource-nomadik-mtu.h
@@ -0,0 +1,9 @@
+#ifndef __PLAT_MTU_H
+#define __PLAT_MTU_H
+
+void nmdk_timer_init(void __iomem *base, int irq);
+void nmdk_clkevt_reset(void);
+void nmdk_clksrc_reset(void);
+
+#endif /* __PLAT_MTU_H */
+
diff --git a/include/linux/platform_data/cpsw.h b/include/linux/platform_data/cpsw.h
index c4e23d0..24368a2 100644
--- a/include/linux/platform_data/cpsw.h
+++ b/include/linux/platform_data/cpsw.h
@@ -18,9 +18,7 @@
 #include <linux/if_ether.h>
 
 struct cpsw_slave_data {
-	u32		slave_reg_ofs;
-	u32		sliver_reg_ofs;
-	const char	*phy_id;
+	char		phy_id[MII_BUS_ID_SIZE];
 	int		phy_if;
 	u8		mac_addr[ETH_ALEN];
 };
@@ -28,27 +26,14 @@ struct cpsw_slave_data {
 struct cpsw_platform_data {
 	u32	ss_reg_ofs;	/* Subsystem control register offset */
 	u32	channels;	/* number of cpdma channels (symmetric) */
-	u32	cpdma_reg_ofs;	/* cpdma register offset */
-	u32	cpdma_sram_ofs;	/* cpdma sram offset */
-
 	u32	slaves;		/* number of slave cpgmac ports */
 	struct cpsw_slave_data	*slave_data;
-
-	u32	ale_reg_ofs;	/* address lookup engine reg offset */
+	u32	cpts_active_slave; /* time stamping slave */
+	u32	cpts_clock_mult;  /* convert input clock ticks to nanoseconds */
+	u32	cpts_clock_shift; /* convert input clock ticks to nanoseconds */
 	u32	ale_entries;	/* ale table size */
-
-	u32	host_port_reg_ofs; /* cpsw cpdma host port registers */
-	u32     host_port_num; /* The port number for the host port */
-
-	u32	hw_stats_reg_ofs;  /* cpsw hardware statistics counters */
-
-	u32	bd_ram_ofs;   /* embedded buffer descriptor RAM offset*/
 	u32	bd_ram_size;  /*buffer descriptor ram size */
-	u32	hw_ram_addr; /*if the HW address for BD RAM is different */
-	bool	no_bd_ram; /* no embedded BD ram*/
-
 	u32	rx_descs;	/* Number of Rx Descriptios */
-
 	u32	mac_control;	/* Mac control register */
 };
 
diff --git a/include/linux/platform_data/crypto-ux500.h b/include/linux/platform_data/crypto-ux500.h
index 5b2d081..94df96d 100644
--- a/include/linux/platform_data/crypto-ux500.h
+++ b/include/linux/platform_data/crypto-ux500.h
@@ -7,7 +7,7 @@
 #ifndef _CRYPTO_UX500_H
 #define _CRYPTO_UX500_H
 #include <linux/dmaengine.h>
-#include <plat/ste_dma40.h>
+#include <linux/platform_data/dma-ste-dma40.h>
 
 struct hash_platform_data {
 	void *mem_to_engine;
diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h
index d0c5825..f3d6e4f 100644
--- a/include/linux/platform_data/davinci_asp.h
+++ b/include/linux/platform_data/davinci_asp.h
@@ -16,6 +16,8 @@
 #ifndef __DAVINCI_ASP_H
 #define __DAVINCI_ASP_H
 
+#include <linux/genalloc.h>
+
 struct snd_platform_data {
 	u32 tx_dma_offset;
 	u32 rx_dma_offset;
@@ -30,6 +32,7 @@ struct snd_platform_data {
 	unsigned enable_channel_combine:1;
 	unsigned sram_size_playback;
 	unsigned sram_size_capture;
+	struct gen_pool *sram_pool;
 
 	/*
 	 * If McBSP peripheral gets the clock from an external pin,
diff --git a/include/linux/platform_data/db8500_thermal.h b/include/linux/platform_data/db8500_thermal.h
new file mode 100644
index 0000000..3bf6090
--- /dev/null
+++ b/include/linux/platform_data/db8500_thermal.h
@@ -0,0 +1,38 @@
+/*
+ * db8500_thermal.h - DB8500 Thermal Management Implementation
+ *
+ * Copyright (C) 2012 ST-Ericsson
+ * Copyright (C) 2012 Linaro Ltd.
+ *
+ * Author: Hongbo Zhang <hongbo.zhang@linaro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 _DB8500_THERMAL_H_
+#define _DB8500_THERMAL_H_
+
+#include <linux/thermal.h>
+
+#define COOLING_DEV_MAX 8
+
+struct db8500_trip_point {
+	unsigned long temp;
+	enum thermal_trip_type type;
+	char cdev_name[COOLING_DEV_MAX][THERMAL_NAME_LENGTH];
+};
+
+struct db8500_thsens_platform_data {
+	struct db8500_trip_point trip_points[THERMAL_MAX_TRIPS];
+	int num_trips;
+};
+
+#endif /* _DB8500_THERMAL_H_ */
diff --git a/include/linux/platform_data/dma-imx.h b/include/linux/platform_data/dma-imx.h
index 1b90803..f6d30cc 100644
--- a/include/linux/platform_data/dma-imx.h
+++ b/include/linux/platform_data/dma-imx.h
@@ -61,7 +61,9 @@ static inline int imx_dma_is_ipu(struct dma_chan *chan)
 static inline int imx_dma_is_general_purpose(struct dma_chan *chan)
 {
 	return strstr(dev_name(chan->device->dev), "sdma") ||
-		!strcmp(dev_name(chan->device->dev), "imx-dma");
+		!strcmp(dev_name(chan->device->dev), "imx1-dma") ||
+		!strcmp(dev_name(chan->device->dev), "imx21-dma") ||
+		!strcmp(dev_name(chan->device->dev), "imx27-dma");
 }
 
 #endif
diff --git a/include/linux/platform_data/dma-ste-dma40.h b/include/linux/platform_data/dma-ste-dma40.h
new file mode 100644
index 0000000..9ff93b0
--- /dev/null
+++ b/include/linux/platform_data/dma-ste-dma40.h
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2007-2010
+ * Author: Per Forlin <per.forlin@stericsson.com> for ST-Ericsson
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+
+#ifndef STE_DMA40_H
+#define STE_DMA40_H
+
+#include <linux/dmaengine.h>
+#include <linux/scatterlist.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+
+/*
+ * Maxium size for a single dma descriptor
+ * Size is limited to 16 bits.
+ * Size is in the units of addr-widths (1,2,4,8 bytes)
+ * Larger transfers will be split up to multiple linked desc
+ */
+#define STEDMA40_MAX_SEG_SIZE 0xFFFF
+
+/* dev types for memcpy */
+#define STEDMA40_DEV_DST_MEMORY (-1)
+#define	STEDMA40_DEV_SRC_MEMORY (-1)
+
+enum stedma40_mode {
+	STEDMA40_MODE_LOGICAL = 0,
+	STEDMA40_MODE_PHYSICAL,
+	STEDMA40_MODE_OPERATION,
+};
+
+enum stedma40_mode_opt {
+	STEDMA40_PCHAN_BASIC_MODE = 0,
+	STEDMA40_LCHAN_SRC_LOG_DST_LOG = 0,
+	STEDMA40_PCHAN_MODULO_MODE,
+	STEDMA40_PCHAN_DOUBLE_DST_MODE,
+	STEDMA40_LCHAN_SRC_PHY_DST_LOG,
+	STEDMA40_LCHAN_SRC_LOG_DST_PHY,
+};
+
+#define STEDMA40_ESIZE_8_BIT  0x0
+#define STEDMA40_ESIZE_16_BIT 0x1
+#define STEDMA40_ESIZE_32_BIT 0x2
+#define STEDMA40_ESIZE_64_BIT 0x3
+
+/* The value 4 indicates that PEN-reg shall be set to 0 */
+#define STEDMA40_PSIZE_PHY_1  0x4
+#define STEDMA40_PSIZE_PHY_2  0x0
+#define STEDMA40_PSIZE_PHY_4  0x1
+#define STEDMA40_PSIZE_PHY_8  0x2
+#define STEDMA40_PSIZE_PHY_16 0x3
+
+/*
+ * The number of elements differ in logical and
+ * physical mode
+ */
+#define STEDMA40_PSIZE_LOG_1  STEDMA40_PSIZE_PHY_2
+#define STEDMA40_PSIZE_LOG_4  STEDMA40_PSIZE_PHY_4
+#define STEDMA40_PSIZE_LOG_8  STEDMA40_PSIZE_PHY_8
+#define STEDMA40_PSIZE_LOG_16 STEDMA40_PSIZE_PHY_16
+
+/* Maximum number of possible physical channels */
+#define STEDMA40_MAX_PHYS 32
+
+enum stedma40_flow_ctrl {
+	STEDMA40_NO_FLOW_CTRL,
+	STEDMA40_FLOW_CTRL,
+};
+
+enum stedma40_periph_data_width {
+	STEDMA40_BYTE_WIDTH = STEDMA40_ESIZE_8_BIT,
+	STEDMA40_HALFWORD_WIDTH = STEDMA40_ESIZE_16_BIT,
+	STEDMA40_WORD_WIDTH = STEDMA40_ESIZE_32_BIT,
+	STEDMA40_DOUBLEWORD_WIDTH = STEDMA40_ESIZE_64_BIT
+};
+
+enum stedma40_xfer_dir {
+	STEDMA40_MEM_TO_MEM = 1,
+	STEDMA40_MEM_TO_PERIPH,
+	STEDMA40_PERIPH_TO_MEM,
+	STEDMA40_PERIPH_TO_PERIPH
+};
+
+
+/**
+ * struct stedma40_chan_cfg - dst/src channel configuration
+ *
+ * @big_endian: true if the src/dst should be read as big endian
+ * @data_width: Data width of the src/dst hardware
+ * @p_size: Burst size
+ * @flow_ctrl: Flow control on/off.
+ */
+struct stedma40_half_channel_info {
+	bool big_endian;
+	enum stedma40_periph_data_width data_width;
+	int psize;
+	enum stedma40_flow_ctrl flow_ctrl;
+};
+
+/**
+ * struct stedma40_chan_cfg - Structure to be filled by client drivers.
+ *
+ * @dir: MEM 2 MEM, PERIPH 2 MEM , MEM 2 PERIPH, PERIPH 2 PERIPH
+ * @high_priority: true if high-priority
+ * @realtime: true if realtime mode is to be enabled.  Only available on DMA40
+ * version 3+, i.e DB8500v2+
+ * @mode: channel mode: physical, logical, or operation
+ * @mode_opt: options for the chosen channel mode
+ * @src_dev_type: Src device type
+ * @dst_dev_type: Dst device type
+ * @src_info: Parameters for dst half channel
+ * @dst_info: Parameters for dst half channel
+ * @use_fixed_channel: if true, use physical channel specified by phy_channel
+ * @phy_channel: physical channel to use, only if use_fixed_channel is true
+ *
+ * This structure has to be filled by the client drivers.
+ * It is recommended to do all dma configurations for clients in the machine.
+ *
+ */
+struct stedma40_chan_cfg {
+	enum stedma40_xfer_dir			 dir;
+	bool					 high_priority;
+	bool					 realtime;
+	enum stedma40_mode			 mode;
+	enum stedma40_mode_opt			 mode_opt;
+	int					 src_dev_type;
+	int					 dst_dev_type;
+	struct stedma40_half_channel_info	 src_info;
+	struct stedma40_half_channel_info	 dst_info;
+
+	bool					 use_fixed_channel;
+	int					 phy_channel;
+};
+
+/**
+ * struct stedma40_platform_data - Configuration struct for the dma device.
+ *
+ * @dev_len: length of dev_tx and dev_rx
+ * @dev_tx: mapping between destination event line and io address
+ * @dev_rx: mapping between source event line and io address
+ * @memcpy: list of memcpy event lines
+ * @memcpy_len: length of memcpy
+ * @memcpy_conf_phy: default configuration of physical channel memcpy
+ * @memcpy_conf_log: default configuration of logical channel memcpy
+ * @disabled_channels: A vector, ending with -1, that marks physical channels
+ * that are for different reasons not available for the driver.
+ */
+struct stedma40_platform_data {
+	u32				 dev_len;
+	const dma_addr_t		*dev_tx;
+	const dma_addr_t		*dev_rx;
+	int				*memcpy;
+	u32				 memcpy_len;
+	struct stedma40_chan_cfg	*memcpy_conf_phy;
+	struct stedma40_chan_cfg	*memcpy_conf_log;
+	int				 disabled_channels[STEDMA40_MAX_PHYS];
+	bool				 use_esram_lcla;
+};
+
+#ifdef CONFIG_STE_DMA40
+
+/**
+ * stedma40_filter() - Provides stedma40_chan_cfg to the
+ * ste_dma40 dma driver via the dmaengine framework.
+ * does some checking of what's provided.
+ *
+ * Never directly called by client. It used by dmaengine.
+ * @chan: dmaengine handle.
+ * @data: Must be of type: struct stedma40_chan_cfg and is
+ * the configuration of the framework.
+ *
+ *
+ */
+
+bool stedma40_filter(struct dma_chan *chan, void *data);
+
+/**
+ * stedma40_slave_mem() - Transfers a raw data buffer to or from a slave
+ * (=device)
+ *
+ * @chan: dmaengine handle
+ * @addr: source or destination physicall address.
+ * @size: bytes to transfer
+ * @direction: direction of transfer
+ * @flags: is actually enum dma_ctrl_flags. See dmaengine.h
+ */
+
+static inline struct
+dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan,
+					    dma_addr_t addr,
+					    unsigned int size,
+					    enum dma_transfer_direction direction,
+					    unsigned long flags)
+{
+	struct scatterlist sg;
+	sg_init_table(&sg, 1);
+	sg.dma_address = addr;
+	sg.length = size;
+
+	return dmaengine_prep_slave_sg(chan, &sg, 1, direction, flags);
+}
+
+#else
+static inline bool stedma40_filter(struct dma_chan *chan, void *data)
+{
+	return false;
+}
+
+static inline struct
+dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan,
+					    dma_addr_t addr,
+					    unsigned int size,
+					    enum dma_transfer_direction direction,
+					    unsigned long flags)
+{
+	return NULL;
+}
+#endif
+
+#endif
diff --git a/include/linux/platform_data/gpio-omap.h b/include/linux/platform_data/gpio-omap.h
index e8741c2..5d50b25 100644
--- a/include/linux/platform_data/gpio-omap.h
+++ b/include/linux/platform_data/gpio-omap.h
@@ -26,7 +26,6 @@
 
 #include <linux/io.h>
 #include <linux/platform_device.h>
-#include <mach/irqs.h>
 
 #define OMAP1_MPUIO_BASE			0xfffb5000
 
diff --git a/include/linux/platform_data/i2c-cbus-gpio.h b/include/linux/platform_data/i2c-cbus-gpio.h
new file mode 100644
index 0000000..6faa992
--- /dev/null
+++ b/include/linux/platform_data/i2c-cbus-gpio.h
@@ -0,0 +1,27 @@
+/*
+ * i2c-cbus-gpio.h - CBUS I2C platform_data definition
+ *
+ * Copyright (C) 2004-2009 Nokia Corporation
+ *
+ * Written by Felipe Balbi and Aaro Koskinen.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __INCLUDE_LINUX_I2C_CBUS_GPIO_H
+#define __INCLUDE_LINUX_I2C_CBUS_GPIO_H
+
+struct i2c_cbus_platform_data {
+	int dat_gpio;
+	int clk_gpio;
+	int sel_gpio;
+};
+
+#endif /* __INCLUDE_LINUX_I2C_CBUS_GPIO_H */
diff --git a/include/linux/platform_data/leds-omap.h b/include/linux/platform_data/leds-omap.h
new file mode 100644
index 0000000..56c9b2a
--- /dev/null
+++ b/include/linux/platform_data/leds-omap.h
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (C) 2006 Samsung Electronics
+ *  Kyungmin Park <kyungmin.park@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 ASMARM_ARCH_LED_H
+#define ASMARM_ARCH_LED_H
+
+struct omap_led_config {
+	struct led_classdev	cdev;
+	s16			gpio;
+};
+
+struct omap_led_platform_data {
+	s16			nr_leds;
+	struct omap_led_config	*leds;
+};
+
+#endif
diff --git a/include/linux/platform_data/lp855x.h b/include/linux/platform_data/lp855x.h
index 761f317..e81f62d 100644
--- a/include/linux/platform_data/lp855x.h
+++ b/include/linux/platform_data/lp855x.h
@@ -89,11 +89,6 @@ enum lp8556_brightness_source {
 	LP8556_COMBINED2,	/* pwm + i2c after the shaper block */
 };
 
-struct lp855x_pwm_data {
-	void (*pwm_set_intensity) (int brightness, int max_brightness);
-	int (*pwm_get_intensity) (int max_brightness);
-};
-
 struct lp855x_rom_data {
 	u8 addr;
 	u8 val;
@@ -105,7 +100,7 @@ struct lp855x_rom_data {
  * @mode : brightness control by pwm or lp855x register
  * @device_control : value of DEVICE CONTROL register
  * @initial_brightness : initial value of backlight brightness
- * @pwm_data : platform specific pwm generation functions.
+ * @period_ns : platform specific pwm period value. unit is nano.
 		Only valid when mode is PWM_BASED.
  * @load_new_rom_data :
 	0 : use default configuration data
@@ -118,7 +113,7 @@ struct lp855x_platform_data {
 	enum lp855x_brightness_ctrl_mode mode;
 	u8 device_control;
 	int initial_brightness;
-	struct lp855x_pwm_data pwm_data;
+	unsigned int period_ns;
 	u8 load_new_rom_data;
 	int size_program;
 	struct lp855x_rom_data *rom_data;
diff --git a/include/linux/platform_data/macb.h b/include/linux/platform_data/macb.h
index b081c72..044a124 100644
--- a/include/linux/platform_data/macb.h
+++ b/include/linux/platform_data/macb.h
@@ -12,6 +12,7 @@ struct macb_platform_data {
 	u32		phy_mask;
 	int		phy_irq_pin;	/* PHY IRQ */
 	u8		is_rmii;	/* using RMII interface? */
+	u8		rev_eth_addr;	/* reverse Ethernet address byte order */
 };
 
 #endif /* __MACB_PDATA_H__ */
diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h
new file mode 100644
index 0000000..2bf1b30
--- /dev/null
+++ b/include/linux/platform_data/mmc-omap.h
@@ -0,0 +1,151 @@
+/*
+ * MMC definitions for OMAP2
+ *
+ * Copyright (C) 2006 Nokia 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.
+ */
+
+#define OMAP_MMC_MAX_SLOTS	2
+
+/*
+ * struct omap_mmc_dev_attr.flags possibilities
+ *
+ * OMAP_HSMMC_SUPPORTS_DUAL_VOLT: Some HSMMC controller instances can
+ *    operate with either 1.8Vdc or 3.0Vdc card voltages; this flag
+ *    should be set if this is the case.  See for example Section 22.5.3
+ *    "MMC/SD/SDIO1 Bus Voltage Selection" of the OMAP34xx Multimedia
+ *    Device Silicon Revision 3.1.x Revision ZR (July 2011) (SWPU223R).
+ *
+ * OMAP_HSMMC_BROKEN_MULTIBLOCK_READ: Multiple-block read transfers
+ *    don't work correctly on some MMC controller instances on some
+ *    OMAP3 SoCs; this flag should be set if this is the case.  See
+ *    for example Advisory 2.1.1.128 "MMC: Multiple Block Read
+ *    Operation Issue" in _OMAP3530/3525/3515/3503 Silicon Errata_
+ *    Revision F (October 2010) (SPRZ278F).
+ */
+#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT		BIT(0)
+#define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ	BIT(1)
+
+struct mmc_card;
+
+struct omap_mmc_dev_attr {
+	u8 flags;
+};
+
+struct omap_mmc_platform_data {
+	/* back-link to device */
+	struct device *dev;
+
+	/* number of slots per controller */
+	unsigned nr_slots:2;
+
+	/* set if your board has components or wiring that limits the
+	 * maximum frequency on the MMC bus */
+	unsigned int max_freq;
+
+	/* switch the bus to a new slot */
+	int (*switch_slot)(struct device *dev, int slot);
+	/* initialize board-specific MMC functionality, can be NULL if
+	 * not supported */
+	int (*init)(struct device *dev);
+	void (*cleanup)(struct device *dev);
+	void (*shutdown)(struct device *dev);
+
+	/* To handle board related suspend/resume functionality for MMC */
+	int (*suspend)(struct device *dev, int slot);
+	int (*resume)(struct device *dev, int slot);
+
+	/* Return context loss count due to PM states changing */
+	int (*get_context_loss_count)(struct device *dev);
+
+	/* Integrating attributes from the omap_hwmod layer */
+	u8 controller_flags;
+
+	/* Register offset deviation */
+	u16 reg_offset;
+
+	struct omap_mmc_slot_data {
+
+		/*
+		 * 4/8 wires and any additional host capabilities
+		 * need to OR'd all capabilities (ref. linux/mmc/host.h)
+		 */
+		u8  wires;	/* Used for the MMC driver on omap1 and 2420 */
+		u32 caps;	/* Used for the MMC driver on 2430 and later */
+		u32 pm_caps;	/* PM capabilities of the mmc */
+
+		/*
+		 * nomux means "standard" muxing is wrong on this board, and
+		 * that board-specific code handled it before common init logic.
+		 */
+		unsigned nomux:1;
+
+		/* switch pin can be for card detect (default) or card cover */
+		unsigned cover:1;
+
+		/* use the internal clock */
+		unsigned internal_clock:1;
+
+		/* nonremovable e.g. eMMC */
+		unsigned nonremovable:1;
+
+		/* Try to sleep or power off when possible */
+		unsigned power_saving:1;
+
+		/* If using power_saving and the MMC power is not to go off */
+		unsigned no_off:1;
+
+		/* eMMC does not handle power off when not in sleep state */
+		unsigned no_regulator_off_init:1;
+
+		/* Regulator off remapped to sleep */
+		unsigned vcc_aux_disable_is_sleep:1;
+
+		/* we can put the features above into this variable */
+#define HSMMC_HAS_PBIAS		(1 << 0)
+#define HSMMC_HAS_UPDATED_RESET	(1 << 1)
+#define HSMMC_HAS_HSPE_SUPPORT	(1 << 2)
+#define MMC_OMAP7XX		(1 << 3)
+#define MMC_OMAP15XX		(1 << 4)
+#define MMC_OMAP16XX		(1 << 5)
+		unsigned features;
+
+		int switch_pin;			/* gpio (card detect) */
+		int gpio_wp;			/* gpio (write protect) */
+
+		int (*set_bus_mode)(struct device *dev, int slot, int bus_mode);
+		int (*set_power)(struct device *dev, int slot,
+				 int power_on, int vdd);
+		int (*get_ro)(struct device *dev, int slot);
+		void (*remux)(struct device *dev, int slot, int power_on);
+		/* Call back before enabling / disabling regulators */
+		void (*before_set_reg)(struct device *dev, int slot,
+				       int power_on, int vdd);
+		/* Call back after enabling / disabling regulators */
+		void (*after_set_reg)(struct device *dev, int slot,
+				      int power_on, int vdd);
+		/* if we have special card, init it using this callback */
+		void (*init_card)(struct mmc_card *card);
+
+		/* return MMC cover switch state, can be NULL if not supported.
+		 *
+		 * possible return values:
+		 *   0 - closed
+		 *   1 - open
+		 */
+		int (*get_cover_state)(struct device *dev, int slot);
+
+		const char *name;
+		u32 ocr_mask;
+
+		/* Card detection IRQs */
+		int card_detect_irq;
+		int (*card_detect)(struct device *dev, int slot);
+
+		unsigned int ban_openended:1;
+
+	} slots[OMAP_MMC_MAX_SLOTS];
+};
diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h
index 1a68c1e..24d32ca 100644
--- a/include/linux/platform_data/mtd-nand-omap2.h
+++ b/include/linux/platform_data/mtd-nand-omap2.h
@@ -8,9 +8,13 @@
  * published by the Free Software Foundation.
  */
 
-#include <plat/gpmc.h>
+#ifndef	_MTD_NAND_OMAP2_H
+#define	_MTD_NAND_OMAP2_H
+
 #include <linux/mtd/partitions.h>
 
+#define	GPMC_BCH_NUM_REMAINDER	8
+
 enum nand_io {
 	NAND_OMAP_PREFETCH_POLLED = 0,	/* prefetch polled mode, default */
 	NAND_OMAP_POLLED,		/* polled mode, without prefetch */
@@ -18,10 +22,38 @@ enum nand_io {
 	NAND_OMAP_PREFETCH_IRQ		/* prefetch enabled irq mode */
 };
 
+enum omap_ecc {
+		/* 1-bit ecc: stored at end of spare area */
+	OMAP_ECC_HAMMING_CODE_DEFAULT = 0, /* Default, s/w method */
+	OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */
+		/* 1-bit ecc: stored at beginning of spare area as romcode */
+	OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */
+	OMAP_ECC_BCH4_CODE_HW, /* 4-bit BCH ecc code */
+	OMAP_ECC_BCH8_CODE_HW, /* 8-bit BCH ecc code */
+};
+
+struct gpmc_nand_regs {
+	void __iomem	*gpmc_status;
+	void __iomem	*gpmc_nand_command;
+	void __iomem	*gpmc_nand_address;
+	void __iomem	*gpmc_nand_data;
+	void __iomem	*gpmc_prefetch_config1;
+	void __iomem	*gpmc_prefetch_config2;
+	void __iomem	*gpmc_prefetch_control;
+	void __iomem	*gpmc_prefetch_status;
+	void __iomem	*gpmc_ecc_config;
+	void __iomem	*gpmc_ecc_control;
+	void __iomem	*gpmc_ecc_size_config;
+	void __iomem	*gpmc_ecc1_result;
+	void __iomem	*gpmc_bch_result0[GPMC_BCH_NUM_REMAINDER];
+	void __iomem	*gpmc_bch_result1[GPMC_BCH_NUM_REMAINDER];
+	void __iomem	*gpmc_bch_result2[GPMC_BCH_NUM_REMAINDER];
+	void __iomem	*gpmc_bch_result3[GPMC_BCH_NUM_REMAINDER];
+};
+
 struct omap_nand_platform_data {
 	int			cs;
 	struct mtd_partition	*parts;
-	struct gpmc_timings	*gpmc_t;
 	int			nr_parts;
 	bool			dev_ready;
 	enum nand_io		xfer_type;
@@ -30,14 +62,4 @@ struct omap_nand_platform_data {
 	struct gpmc_nand_regs	reg;
 };
 
-/* minimum size for IO mapping */
-#define	NAND_IO_SIZE	4
-
-#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-extern int gpmc_nand_init(struct omap_nand_platform_data *d);
-#else
-static inline int gpmc_nand_init(struct omap_nand_platform_data *d)
-{
-	return 0;
-}
 #endif
diff --git a/include/linux/platform_data/mtd-nomadik-nand.h b/include/linux/platform_data/mtd-nomadik-nand.h
deleted file mode 100644
index c3c8254..0000000
--- a/include/linux/platform_data/mtd-nomadik-nand.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __ASM_ARCH_NAND_H
-#define __ASM_ARCH_NAND_H
-
-struct nomadik_nand_platform_data {
-	struct mtd_partition *parts;
-	int nparts;
-	int options;
-	int (*init) (void);
-	int (*exit) (void);
-};
-
-#define NAND_IO_DATA	0x40000000
-#define NAND_IO_CMD	0x40800000
-#define NAND_IO_ADDR	0x41000000
-
-#endif				/* __ASM_ARCH_NAND_H */
diff --git a/include/linux/platform_data/mtd-onenand-omap2.h b/include/linux/platform_data/mtd-onenand-omap2.h
index 2858667..685af7e 100644
--- a/include/linux/platform_data/mtd-onenand-omap2.h
+++ b/include/linux/platform_data/mtd-onenand-omap2.h
@@ -9,17 +9,15 @@
  * published by the Free Software Foundation.
  */
 
+#ifndef	__MTD_ONENAND_OMAP2_H
+#define	__MTD_ONENAND_OMAP2_H
+
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
 #define ONENAND_SYNC_READ	(1 << 0)
 #define ONENAND_SYNC_READWRITE	(1 << 1)
-
-struct onenand_freq_info {
-	u16			maf_id;
-	u16			dev_id;
-	u16			ver_id;
-};
+#define	ONENAND_IN_OMAP34XX	(1 << 2)
 
 struct omap_onenand_platform_data {
 	int			cs;
@@ -27,27 +25,9 @@ struct omap_onenand_platform_data {
 	struct mtd_partition	*parts;
 	int			nr_parts;
 	int			(*onenand_setup)(void __iomem *, int *freq_ptr);
-	int		(*get_freq)(const struct onenand_freq_info *freq_info,
-				    bool *clk_dep);
 	int			dma_channel;
 	u8			flags;
 	u8			regulator_can_sleep;
 	u8			skip_initial_unlocking;
 };
-
-#define ONENAND_MAX_PARTITIONS 8
-
-#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
-	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
-
-extern void gpmc_onenand_init(struct omap_onenand_platform_data *d);
-
-#else
-
-#define board_onenand_data	NULL
-
-static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d)
-{
-}
-
 #endif
diff --git a/include/linux/platform_data/omap-wd-timer.h b/include/linux/platform_data/omap-wd-timer.h
new file mode 100644
index 0000000..d75f5f8
--- /dev/null
+++ b/include/linux/platform_data/omap-wd-timer.h
@@ -0,0 +1,38 @@
+/*
+ * OMAP2+ WDTIMER-specific function prototypes
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __LINUX_PLATFORM_DATA_OMAP_WD_TIMER_H
+#define __LINUX_PLATFORM_DATA_OMAP_WD_TIMER_H
+
+#include <linux/types.h>
+
+/*
+ * Standardized OMAP reset source bits
+ *
+ * This is a subset of the ones listed in arch/arm/mach-omap2/prm.h
+ * and are the only ones needed in the watchdog driver.
+ */
+#define OMAP_MPU_WD_RST_SRC_ID_SHIFT				3
+
+/**
+ * struct omap_wd_timer_platform_data - WDTIMER integration to the host SoC
+ * @read_reset_sources - fn ptr for the SoC to indicate the last reset cause
+ *
+ * The function pointed to by @read_reset_sources must return its data
+ * in a standard format - search for RST_SRC_ID_SHIFT in
+ * arch/arm/mach-omap2
+ */
+struct omap_wd_timer_platform_data {
+	u32 (*read_reset_sources)(void);
+};
+
+#endif
diff --git a/include/linux/platform_data/omap_drm.h b/include/linux/platform_data/omap_drm.h
index 3da73bdc..f4e4a23 100644
--- a/include/linux/platform_data/omap_drm.h
+++ b/include/linux/platform_data/omap_drm.h
@@ -46,6 +46,7 @@ struct omap_kms_platform_data {
 };
 
 struct omap_drm_platform_data {
+	uint32_t omaprev;
 	struct omap_kms_platform_data *kms_pdata;
 };
 
diff --git a/include/linux/platform_data/pinctrl-coh901.h b/include/linux/platform_data/pinctrl-coh901.h
index 30dea25..dfbc65d 100644
--- a/include/linux/platform_data/pinctrl-coh901.h
+++ b/include/linux/platform_data/pinctrl-coh901.h
@@ -13,14 +13,10 @@
  * struct u300_gpio_platform - U300 GPIO platform data
  * @ports: number of GPIO block ports
  * @gpio_base: first GPIO number for this block (use a free range)
- * @gpio_irq_base: first GPIO IRQ number for this block (use a free range)
- * @pinctrl_device: pin control device to spawn as child
  */
 struct u300_gpio_platform {
 	u8 ports;
 	int gpio_base;
-	int gpio_irq_base;
-	struct platform_device *pinctrl_device;
 };
 
 #endif /* __MACH_U300_GPIO_U300_H */
diff --git a/include/linux/platform_data/pinctrl-nomadik.h b/include/linux/platform_data/pinctrl-nomadik.h
new file mode 100644
index 0000000..f73b2f0
--- /dev/null
+++ b/include/linux/platform_data/pinctrl-nomadik.h
@@ -0,0 +1,266 @@
+/*
+ * Structures and registers for GPIO access in the Nomadik SoC
+ *
+ * Copyright (C) 2008 STMicroelectronics
+ *     Author: Prafulla WADASKAR <prafulla.wadaskar@st.com>
+ * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PLAT_NOMADIK_GPIO
+#define __PLAT_NOMADIK_GPIO
+
+/*
+ * pin configurations are represented by 32-bit integers:
+ *
+ *	bit  0.. 8 - Pin Number (512 Pins Maximum)
+ *	bit  9..10 - Alternate Function Selection
+ *	bit 11..12 - Pull up/down state
+ *	bit     13 - Sleep mode behaviour
+ *	bit     14 - Direction
+ *	bit     15 - Value (if output)
+ *	bit 16..18 - SLPM pull up/down state
+ *	bit 19..20 - SLPM direction
+ *	bit 21..22 - SLPM Value (if output)
+ *	bit 23..25 - PDIS value (if input)
+ *	bit	26 - Gpio mode
+ *	bit	27 - Sleep mode
+ *
+ * to facilitate the definition, the following macros are provided
+ *
+ * PIN_CFG_DEFAULT - default config (0):
+ *		     pull up/down = disabled
+ *		     sleep mode = input/wakeup
+ *		     direction = input
+ *		     value = low
+ *		     SLPM direction = same as normal
+ *		     SLPM pull = same as normal
+ *		     SLPM value = same as normal
+ *
+ * PIN_CFG	   - default config with alternate function
+ */
+
+typedef unsigned long pin_cfg_t;
+
+#define PIN_NUM_MASK		0x1ff
+#define PIN_NUM(x)		((x) & PIN_NUM_MASK)
+
+#define PIN_ALT_SHIFT		9
+#define PIN_ALT_MASK		(0x3 << PIN_ALT_SHIFT)
+#define PIN_ALT(x)		(((x) & PIN_ALT_MASK) >> PIN_ALT_SHIFT)
+#define PIN_GPIO		(NMK_GPIO_ALT_GPIO << PIN_ALT_SHIFT)
+#define PIN_ALT_A		(NMK_GPIO_ALT_A << PIN_ALT_SHIFT)
+#define PIN_ALT_B		(NMK_GPIO_ALT_B << PIN_ALT_SHIFT)
+#define PIN_ALT_C		(NMK_GPIO_ALT_C << PIN_ALT_SHIFT)
+
+#define PIN_PULL_SHIFT		11
+#define PIN_PULL_MASK		(0x3 << PIN_PULL_SHIFT)
+#define PIN_PULL(x)		(((x) & PIN_PULL_MASK) >> PIN_PULL_SHIFT)
+#define PIN_PULL_NONE		(NMK_GPIO_PULL_NONE << PIN_PULL_SHIFT)
+#define PIN_PULL_UP		(NMK_GPIO_PULL_UP << PIN_PULL_SHIFT)
+#define PIN_PULL_DOWN		(NMK_GPIO_PULL_DOWN << PIN_PULL_SHIFT)
+
+#define PIN_SLPM_SHIFT		13
+#define PIN_SLPM_MASK		(0x1 << PIN_SLPM_SHIFT)
+#define PIN_SLPM(x)		(((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT)
+#define PIN_SLPM_MAKE_INPUT	(NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT)
+#define PIN_SLPM_NOCHANGE	(NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT)
+/* These two replace the above in DB8500v2+ */
+#define PIN_SLPM_WAKEUP_ENABLE	(NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT)
+#define PIN_SLPM_WAKEUP_DISABLE	(NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT)
+#define PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP PIN_SLPM_WAKEUP_DISABLE
+
+#define PIN_SLPM_GPIO  PIN_SLPM_WAKEUP_ENABLE /* In SLPM, pin is a gpio */
+#define PIN_SLPM_ALTFUNC PIN_SLPM_WAKEUP_DISABLE /* In SLPM, pin is altfunc */
+
+#define PIN_DIR_SHIFT		14
+#define PIN_DIR_MASK		(0x1 << PIN_DIR_SHIFT)
+#define PIN_DIR(x)		(((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT)
+#define PIN_DIR_INPUT		(0 << PIN_DIR_SHIFT)
+#define PIN_DIR_OUTPUT		(1 << PIN_DIR_SHIFT)
+
+#define PIN_VAL_SHIFT		15
+#define PIN_VAL_MASK		(0x1 << PIN_VAL_SHIFT)
+#define PIN_VAL(x)		(((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT)
+#define PIN_VAL_LOW		(0 << PIN_VAL_SHIFT)
+#define PIN_VAL_HIGH		(1 << PIN_VAL_SHIFT)
+
+#define PIN_SLPM_PULL_SHIFT	16
+#define PIN_SLPM_PULL_MASK	(0x7 << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL(x)	\
+	(((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_NONE	\
+	((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_UP	\
+	((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_DOWN	\
+	((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT)
+
+#define PIN_SLPM_DIR_SHIFT	19
+#define PIN_SLPM_DIR_MASK	(0x3 << PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR(x)		\
+	(((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR_INPUT	((1 + 0) << PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR_OUTPUT	((1 + 1) << PIN_SLPM_DIR_SHIFT)
+
+#define PIN_SLPM_VAL_SHIFT	21
+#define PIN_SLPM_VAL_MASK	(0x3 << PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL(x)		\
+	(((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL_LOW	((1 + 0) << PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL_HIGH	((1 + 1) << PIN_SLPM_VAL_SHIFT)
+
+#define PIN_SLPM_PDIS_SHIFT		23
+#define PIN_SLPM_PDIS_MASK		(0x3 << PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS(x)	\
+	(((x) & PIN_SLPM_PDIS_MASK) >> PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS_NO_CHANGE		(0 << PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS_DISABLED		(1 << PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS_ENABLED		(2 << PIN_SLPM_PDIS_SHIFT)
+
+#define PIN_LOWEMI_SHIFT	25
+#define PIN_LOWEMI_MASK		(0x1 << PIN_LOWEMI_SHIFT)
+#define PIN_LOWEMI(x)		(((x) & PIN_LOWEMI_MASK) >> PIN_LOWEMI_SHIFT)
+#define PIN_LOWEMI_DISABLED	(0 << PIN_LOWEMI_SHIFT)
+#define PIN_LOWEMI_ENABLED	(1 << PIN_LOWEMI_SHIFT)
+
+#define PIN_GPIOMODE_SHIFT	26
+#define PIN_GPIOMODE_MASK	(0x1 << PIN_GPIOMODE_SHIFT)
+#define PIN_GPIOMODE(x)		(((x) & PIN_GPIOMODE_MASK) >> PIN_GPIOMODE_SHIFT)
+#define PIN_GPIOMODE_DISABLED	(0 << PIN_GPIOMODE_SHIFT)
+#define PIN_GPIOMODE_ENABLED	(1 << PIN_GPIOMODE_SHIFT)
+
+#define PIN_SLEEPMODE_SHIFT	27
+#define PIN_SLEEPMODE_MASK	(0x1 << PIN_SLEEPMODE_SHIFT)
+#define PIN_SLEEPMODE(x)	(((x) & PIN_SLEEPMODE_MASK) >> PIN_SLEEPMODE_SHIFT)
+#define PIN_SLEEPMODE_DISABLED	(0 << PIN_SLEEPMODE_SHIFT)
+#define PIN_SLEEPMODE_ENABLED	(1 << PIN_SLEEPMODE_SHIFT)
+
+
+/* Shortcuts.  Use these instead of separate DIR, PULL, and VAL.  */
+#define PIN_INPUT_PULLDOWN	(PIN_DIR_INPUT | PIN_PULL_DOWN)
+#define PIN_INPUT_PULLUP	(PIN_DIR_INPUT | PIN_PULL_UP)
+#define PIN_INPUT_NOPULL	(PIN_DIR_INPUT | PIN_PULL_NONE)
+#define PIN_OUTPUT_LOW		(PIN_DIR_OUTPUT | PIN_VAL_LOW)
+#define PIN_OUTPUT_HIGH		(PIN_DIR_OUTPUT | PIN_VAL_HIGH)
+
+#define PIN_SLPM_INPUT_PULLDOWN	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN)
+#define PIN_SLPM_INPUT_PULLUP	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP)
+#define PIN_SLPM_INPUT_NOPULL	(PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE)
+#define PIN_SLPM_OUTPUT_LOW	(PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW)
+#define PIN_SLPM_OUTPUT_HIGH	(PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH)
+
+#define PIN_CFG_DEFAULT		(0)
+
+#define PIN_CFG(num, alt)		\
+	(PIN_CFG_DEFAULT |\
+	 (PIN_NUM(num) | PIN_##alt))
+
+#define PIN_CFG_INPUT(num, alt, pull)		\
+	(PIN_CFG_DEFAULT |\
+	 (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull))
+
+#define PIN_CFG_OUTPUT(num, alt, val)		\
+	(PIN_CFG_DEFAULT |\
+	 (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
+
+/*
+ * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
+ * the "gpio" namespace for generic and cross-machine functions
+ */
+
+#define GPIO_BLOCK_SHIFT 5
+#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT)
+
+/* Register in the logic block */
+#define NMK_GPIO_DAT	0x00
+#define NMK_GPIO_DATS	0x04
+#define NMK_GPIO_DATC	0x08
+#define NMK_GPIO_PDIS	0x0c
+#define NMK_GPIO_DIR	0x10
+#define NMK_GPIO_DIRS	0x14
+#define NMK_GPIO_DIRC	0x18
+#define NMK_GPIO_SLPC	0x1c
+#define NMK_GPIO_AFSLA	0x20
+#define NMK_GPIO_AFSLB	0x24
+#define NMK_GPIO_LOWEMI	0x28
+
+#define NMK_GPIO_RIMSC	0x40
+#define NMK_GPIO_FIMSC	0x44
+#define NMK_GPIO_IS	0x48
+#define NMK_GPIO_IC	0x4c
+#define NMK_GPIO_RWIMSC	0x50
+#define NMK_GPIO_FWIMSC	0x54
+#define NMK_GPIO_WKS	0x58
+/* These appear in DB8540 and later ASICs */
+#define NMK_GPIO_EDGELEVEL 0x5C
+#define NMK_GPIO_LEVEL	0x60
+
+/* Alternate functions: function C is set in hw by setting both A and B */
+#define NMK_GPIO_ALT_GPIO	0
+#define NMK_GPIO_ALT_A	1
+#define NMK_GPIO_ALT_B	2
+#define NMK_GPIO_ALT_C	(NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
+
+#define NMK_GPIO_ALT_CX_SHIFT 2
+#define NMK_GPIO_ALT_C1	((1<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C2	((2<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C3	((3<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C4	((4<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+
+/* Pull up/down values */
+enum nmk_gpio_pull {
+	NMK_GPIO_PULL_NONE,
+	NMK_GPIO_PULL_UP,
+	NMK_GPIO_PULL_DOWN,
+};
+
+/* Sleep mode */
+enum nmk_gpio_slpm {
+	NMK_GPIO_SLPM_INPUT,
+	NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
+	NMK_GPIO_SLPM_NOCHANGE,
+	NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
+};
+
+/* Older deprecated pin config API that should go away soon */
+extern int nmk_config_pin(pin_cfg_t cfg, bool sleep);
+extern int nmk_config_pins(pin_cfg_t *cfgs, int num);
+extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num);
+extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
+extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
+#ifdef CONFIG_PINCTRL_NOMADIK
+extern int nmk_gpio_set_mode(int gpio, int gpio_mode);
+#else
+static inline int nmk_gpio_set_mode(int gpio, int gpio_mode)
+{
+	return -ENODEV;
+}
+#endif
+extern int nmk_gpio_get_mode(int gpio);
+
+extern void nmk_gpio_wakeups_suspend(void);
+extern void nmk_gpio_wakeups_resume(void);
+
+extern void nmk_gpio_clocks_enable(void);
+extern void nmk_gpio_clocks_disable(void);
+
+extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
+
+/*
+ * Platform data to register a block: only the initial gpio/irq number.
+ */
+struct nmk_gpio_platform_data {
+	char *name;
+	int first_gpio;
+	int first_irq;
+	int num_gpio;
+	u32 (*get_secondary_status)(unsigned int bank);
+	void (*set_ioforce)(bool enable);
+	bool supports_sleepmode;
+};
+
+#endif /* __PLAT_NOMADIK_GPIO */
diff --git a/include/linux/platform_data/pn544.h b/include/linux/platform_data/pn544.h
new file mode 100644
index 0000000..713bfd7
--- /dev/null
+++ b/include/linux/platform_data/pn544.h
@@ -0,0 +1,44 @@
+/*
+ * Driver include for the PN544 NFC chip.
+ *
+ * Copyright (C) Nokia Corporation
+ *
+ * Author: Jari Vanhala <ext-jari.vanhala@nokia.com>
+ * Contact: Matti Aaltoenn <matti.j.aaltonen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _PN544_H_
+#define _PN544_H_
+
+#include <linux/i2c.h>
+
+enum {
+	NFC_GPIO_ENABLE,
+	NFC_GPIO_FW_RESET,
+	NFC_GPIO_IRQ
+};
+
+/* board config */
+struct pn544_nfc_platform_data {
+	int (*request_resources) (struct i2c_client *client);
+	void (*free_resources) (void);
+	void (*enable) (int fw);
+	int (*test) (void);
+	void (*disable) (void);
+	int (*get_gpio)(int type);
+};
+
+#endif /* _PN544_H_ */
diff --git a/include/linux/platform_data/pxa2xx_udc.h b/include/linux/platform_data/pxa2xx_udc.h
new file mode 100644
index 0000000..c6c5e98
--- /dev/null
+++ b/include/linux/platform_data/pxa2xx_udc.h
@@ -0,0 +1,27 @@
+/*
+ * This supports machine-specific differences in how the PXA2xx
+ * USB Device Controller (UDC) is wired.
+ *
+ * It is set in linux/arch/arm/mach-pxa/<machine>.c or in
+ * linux/arch/mach-ixp4xx/<machine>.c and used in
+ * the probe routine of linux/drivers/usb/gadget/pxa2xx_udc.c
+ */
+#ifndef PXA2XX_UDC_H
+#define PXA2XX_UDC_H
+
+struct pxa2xx_udc_mach_info {
+        int  (*udc_is_connected)(void);		/* do we see host? */
+        void (*udc_command)(int cmd);
+#define	PXA2XX_UDC_CMD_CONNECT		0	/* let host see us */
+#define	PXA2XX_UDC_CMD_DISCONNECT	1	/* so host won't see us */
+
+	/* Boards following the design guidelines in the developer's manual,
+	 * with on-chip GPIOs not Lubbock's weird hardware, can have a sane
+	 * VBUS IRQ and omit the methods above.  Store the GPIO number
+	 * here.  Note that sometimes the signals go through inverters...
+	 */
+	bool	gpio_pullup_inverted;
+	int	gpio_pullup;			/* high == pullup activated */
+};
+
+#endif
diff --git a/include/linux/platform_data/pxa_sdhci.h b/include/linux/platform_data/pxa_sdhci.h
index 59acd98..27d3156 100644
--- a/include/linux/platform_data/pxa_sdhci.h
+++ b/include/linux/platform_data/pxa_sdhci.h
@@ -38,6 +38,7 @@
  * @max_speed: the maximum speed supported
  * @host_caps: Standard MMC host capabilities bit field.
  * @quirks: quirks of platfrom
+ * @quirks2: quirks2 of platfrom
  * @pm_caps: pm_caps of platfrom
  */
 struct sdhci_pxa_platdata {
@@ -48,9 +49,10 @@ struct sdhci_pxa_platdata {
 	unsigned int	ext_cd_gpio;
 	bool		ext_cd_gpio_invert;
 	unsigned int	max_speed;
-	unsigned int	host_caps;
-	unsigned int	host_caps2;
+	u32		host_caps;
+	u32		host_caps2;
 	unsigned int	quirks;
+	unsigned int	quirks2;
 	unsigned int	pm_caps;
 };
 
diff --git a/include/linux/platform_data/sa11x0-serial.h b/include/linux/platform_data/sa11x0-serial.h
new file mode 100644
index 0000000..4504d5d
--- /dev/null
+++ b/include/linux/platform_data/sa11x0-serial.h
@@ -0,0 +1,33 @@
+/*
+ *  Author: Nicolas Pitre
+ *
+ * Moved and changed lots, Russell King
+ *
+ * Low level machine dependent UART functions.
+ */
+#ifndef SA11X0_SERIAL_H
+#define SA11X0_SERIAL_H
+
+struct uart_port;
+struct uart_info;
+
+/*
+ * This is a temporary structure for registering these
+ * functions; it is intended to be discarded after boot.
+ */
+struct sa1100_port_fns {
+	void	(*set_mctrl)(struct uart_port *, u_int);
+	u_int	(*get_mctrl)(struct uart_port *);
+	void	(*pm)(struct uart_port *, u_int, u_int);
+	int	(*set_wake)(struct uart_port *, u_int);
+};
+
+#ifdef CONFIG_SERIAL_SA1100
+void sa1100_register_uart_fns(struct sa1100_port_fns *fns);
+void sa1100_register_uart(int idx, int port);
+#else
+#define sa1100_register_uart_fns(fns) do { } while (0)
+#define sa1100_register_uart(idx,port) do { } while (0)
+#endif
+
+#endif
diff --git a/include/linux/platform_data/spi-omap2-mcspi.h b/include/linux/platform_data/spi-omap2-mcspi.h
index a357eb2..a65572d 100644
--- a/include/linux/platform_data/spi-omap2-mcspi.h
+++ b/include/linux/platform_data/spi-omap2-mcspi.h
@@ -7,9 +7,13 @@
 
 #define OMAP4_MCSPI_REG_OFFSET 0x100
 
+#define MCSPI_PINDIR_D0_IN_D1_OUT	0
+#define MCSPI_PINDIR_D0_OUT_D1_IN	1
+
 struct omap2_mcspi_platform_config {
 	unsigned short	num_cs;
 	unsigned int regs_offset;
+	unsigned int pin_dir:1;
 };
 
 struct omap2_mcspi_dev_attr {
diff --git a/include/linux/platform_data/ti_am335x_adc.h b/include/linux/platform_data/ti_am335x_adc.h
new file mode 100644
index 0000000..e41d583
--- /dev/null
+++ b/include/linux/platform_data/ti_am335x_adc.h
@@ -0,0 +1,14 @@
+#ifndef __LINUX_TI_AM335X_ADC_H
+#define __LINUX_TI_AM335X_ADC_H
+
+/**
+ * struct adc_data	ADC Input information
+ * @adc_channels:	Number of analog inputs
+ *			available for ADC.
+ */
+
+struct adc_data {
+	unsigned int adc_channels;
+};
+
+#endif
diff --git a/include/linux/platform_data/uio_dmem_genirq.h b/include/linux/platform_data/uio_dmem_genirq.h
new file mode 100644
index 0000000..973c1bb
--- /dev/null
+++ b/include/linux/platform_data/uio_dmem_genirq.h
@@ -0,0 +1,26 @@
+/*
+ * include/linux/platform_data/uio_dmem_genirq.h
+ *
+ * Copyright (C) 2012 Damian Hobson-Garcia
+ *
+ * This program is free software; 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 _UIO_DMEM_GENIRQ_H
+#define _UIO_DMEM_GENIRQ_H
+
+#include <linux/uio_driver.h>
+
+struct uio_dmem_genirq_pdata {
+	struct uio_info	uioinfo;
+	unsigned int *dynamic_region_sizes;
+	unsigned int num_dynamic_regions;
+};
+#endif /* _UIO_DMEM_GENIRQ_H */
diff --git a/include/linux/platform_data/uio_pruss.h b/include/linux/platform_data/uio_pruss.h
index f39140a..3d47d21 100644
--- a/include/linux/platform_data/uio_pruss.h
+++ b/include/linux/platform_data/uio_pruss.h
@@ -20,6 +20,7 @@
 
 /* To configure the PRUSS INTC base offset for UIO driver */
 struct uio_pruss_pdata {
-	u32	pintc_base;
+	u32		pintc_base;
+	struct gen_pool *sram_pool;
 };
 #endif /* _UIO_PRUSS_H_ */
diff --git a/include/linux/platform_data/usb-omap.h b/include/linux/platform_data/usb-omap.h
new file mode 100644
index 0000000..8570bcf
--- /dev/null
+++ b/include/linux/platform_data/usb-omap.h
@@ -0,0 +1,80 @@
+/*
+ * usb-omap.h - Platform data for the various OMAP USB IPs
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License ("GPL") version 2, as published by the Free Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define OMAP3_HS_USB_PORTS	3
+
+enum usbhs_omap_port_mode {
+	OMAP_USBHS_PORT_MODE_UNUSED,
+	OMAP_EHCI_PORT_MODE_PHY,
+	OMAP_EHCI_PORT_MODE_TLL,
+	OMAP_EHCI_PORT_MODE_HSIC,
+	OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0,
+	OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM,
+	OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0,
+	OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM,
+	OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0,
+	OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM,
+	OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0,
+	OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM,
+	OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0,
+	OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM
+};
+
+struct usbtll_omap_platform_data {
+	enum usbhs_omap_port_mode		port_mode[OMAP3_HS_USB_PORTS];
+};
+
+struct ehci_hcd_omap_platform_data {
+	enum usbhs_omap_port_mode	port_mode[OMAP3_HS_USB_PORTS];
+	int				reset_gpio_port[OMAP3_HS_USB_PORTS];
+	struct regulator		*regulator[OMAP3_HS_USB_PORTS];
+	unsigned			phy_reset:1;
+};
+
+struct ohci_hcd_omap_platform_data {
+	enum usbhs_omap_port_mode	port_mode[OMAP3_HS_USB_PORTS];
+	unsigned			es2_compatibility:1;
+};
+
+struct usbhs_omap_platform_data {
+	enum usbhs_omap_port_mode		port_mode[OMAP3_HS_USB_PORTS];
+
+	struct ehci_hcd_omap_platform_data	*ehci_data;
+	struct ohci_hcd_omap_platform_data	*ohci_data;
+};
+
+/*-------------------------------------------------------------------------*/
+
+struct omap_musb_board_data {
+	u8	interface_type;
+	u8	mode;
+	u16	power;
+	unsigned extvbus:1;
+	void	(*set_phy_power)(u8 on);
+	void	(*clear_irq)(void);
+	void	(*set_mode)(u8 mode);
+	void	(*reset)(void);
+};
+
+enum musb_interface {
+	MUSB_INTERFACE_ULPI,
+	MUSB_INTERFACE_UTMI
+};
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 5711e95..a9ded9a 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -55,6 +55,7 @@ extern int platform_add_devices(struct platform_device **, int);
 
 struct platform_device_info {
 		struct device *parent;
+		struct acpi_dev_node acpi_node;
 
 		const char *name;
 		int id;
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 007e687..03d7bb1 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -546,10 +546,9 @@ struct dev_pm_info {
 	unsigned long		active_jiffies;
 	unsigned long		suspended_jiffies;
 	unsigned long		accounting_timestamp;
-	struct dev_pm_qos_request *pq_req;
 #endif
 	struct pm_subsys_data	*subsys_data;  /* Owned by the subsystem. */
-	struct pm_qos_constraints *constraints;
+	struct dev_pm_qos	*qos;
 };
 
 extern void update_pm_runtime_accounting(struct device *dev);
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h
index 9924ea1..5a95013 100644
--- a/include/linux/pm_qos.h
+++ b/include/linux/pm_qos.h
@@ -20,6 +20,13 @@ enum {
 	PM_QOS_NUM_CLASSES,
 };
 
+enum pm_qos_flags_status {
+	PM_QOS_FLAGS_UNDEFINED = -1,
+	PM_QOS_FLAGS_NONE,
+	PM_QOS_FLAGS_SOME,
+	PM_QOS_FLAGS_ALL,
+};
+
 #define PM_QOS_DEFAULT_VALUE -1
 
 #define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE	(2000 * USEC_PER_SEC)
@@ -27,14 +34,31 @@ enum {
 #define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE	0
 #define PM_QOS_DEV_LAT_DEFAULT_VALUE		0
 
+#define PM_QOS_FLAG_NO_POWER_OFF	(1 << 0)
+#define PM_QOS_FLAG_REMOTE_WAKEUP	(1 << 1)
+
 struct pm_qos_request {
 	struct plist_node node;
 	int pm_qos_class;
 	struct delayed_work work; /* for pm_qos_update_request_timeout */
 };
 
+struct pm_qos_flags_request {
+	struct list_head node;
+	s32 flags;	/* Do not change to 64 bit */
+};
+
+enum dev_pm_qos_req_type {
+	DEV_PM_QOS_LATENCY = 1,
+	DEV_PM_QOS_FLAGS,
+};
+
 struct dev_pm_qos_request {
-	struct plist_node node;
+	enum dev_pm_qos_req_type type;
+	union {
+		struct plist_node pnode;
+		struct pm_qos_flags_request flr;
+	} data;
 	struct device *dev;
 };
 
@@ -45,8 +69,8 @@ enum pm_qos_type {
 };
 
 /*
- * Note: The lockless read path depends on the CPU accessing
- * target_value atomically.  Atomic access is only guaranteed on all CPU
+ * Note: The lockless read path depends on the CPU accessing target_value
+ * or effective_flags atomically.  Atomic access is only guaranteed on all CPU
  * types linux supports for 32 bit quantites
  */
 struct pm_qos_constraints {
@@ -57,6 +81,18 @@ struct pm_qos_constraints {
 	struct blocking_notifier_head *notifiers;
 };
 
+struct pm_qos_flags {
+	struct list_head list;
+	s32 effective_flags;	/* Do not change to 64 bit */
+};
+
+struct dev_pm_qos {
+	struct pm_qos_constraints latency;
+	struct pm_qos_flags flags;
+	struct dev_pm_qos_request *latency_req;
+	struct dev_pm_qos_request *flags_req;
+};
+
 /* Action requested to pm_qos_update_target */
 enum pm_qos_req_action {
 	PM_QOS_ADD_REQ,		/* Add a new request */
@@ -71,6 +107,9 @@ static inline int dev_pm_qos_request_active(struct dev_pm_qos_request *req)
 
 int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node,
 			 enum pm_qos_req_action action, int value);
+bool pm_qos_update_flags(struct pm_qos_flags *pqf,
+			 struct pm_qos_flags_request *req,
+			 enum pm_qos_req_action action, s32 val);
 void pm_qos_add_request(struct pm_qos_request *req, int pm_qos_class,
 			s32 value);
 void pm_qos_update_request(struct pm_qos_request *req,
@@ -86,10 +125,12 @@ int pm_qos_request_active(struct pm_qos_request *req);
 s32 pm_qos_read_value(struct pm_qos_constraints *c);
 
 #ifdef CONFIG_PM
+enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask);
+enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask);
 s32 __dev_pm_qos_read_value(struct device *dev);
 s32 dev_pm_qos_read_value(struct device *dev);
 int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
-			   s32 value);
+			   enum dev_pm_qos_req_type type, s32 value);
 int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value);
 int dev_pm_qos_remove_request(struct dev_pm_qos_request *req);
 int dev_pm_qos_add_notifier(struct device *dev,
@@ -103,12 +144,19 @@ void dev_pm_qos_constraints_destroy(struct device *dev);
 int dev_pm_qos_add_ancestor_request(struct device *dev,
 				    struct dev_pm_qos_request *req, s32 value);
 #else
+static inline enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev,
+							  s32 mask)
+			{ return PM_QOS_FLAGS_UNDEFINED; }
+static inline enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev,
+							s32 mask)
+			{ return PM_QOS_FLAGS_UNDEFINED; }
 static inline s32 __dev_pm_qos_read_value(struct device *dev)
 			{ return 0; }
 static inline s32 dev_pm_qos_read_value(struct device *dev)
 			{ return 0; }
 static inline int dev_pm_qos_add_request(struct device *dev,
 					 struct dev_pm_qos_request *req,
+					 enum dev_pm_qos_req_type type,
 					 s32 value)
 			{ return 0; }
 static inline int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
@@ -144,10 +192,31 @@ static inline int dev_pm_qos_add_ancestor_request(struct device *dev,
 #ifdef CONFIG_PM_RUNTIME
 int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value);
 void dev_pm_qos_hide_latency_limit(struct device *dev);
+int dev_pm_qos_expose_flags(struct device *dev, s32 value);
+void dev_pm_qos_hide_flags(struct device *dev);
+int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set);
+
+static inline s32 dev_pm_qos_requested_latency(struct device *dev)
+{
+	return dev->power.qos->latency_req->data.pnode.prio;
+}
+
+static inline s32 dev_pm_qos_requested_flags(struct device *dev)
+{
+	return dev->power.qos->flags_req->data.flr.flags;
+}
 #else
 static inline int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
 			{ return 0; }
 static inline void dev_pm_qos_hide_latency_limit(struct device *dev) {}
+static inline int dev_pm_qos_expose_flags(struct device *dev, s32 value)
+			{ return 0; }
+static inline void dev_pm_qos_hide_flags(struct device *dev) {}
+static inline int dev_pm_qos_update_flags(struct device *dev, s32 m, bool set)
+			{ return 0; }
+
+static inline s32 dev_pm_qos_requested_latency(struct device *dev) { return 0; }
+static inline s32 dev_pm_qos_requested_flags(struct device *dev) { return 0; }
 #endif
 
 #endif
diff --git a/include/linux/power/bq2415x_charger.h b/include/linux/power/bq2415x_charger.h
new file mode 100644
index 0000000..97a1665
--- /dev/null
+++ b/include/linux/power/bq2415x_charger.h
@@ -0,0 +1,95 @@
+/*
+ * bq2415x charger driver
+ *
+ * Copyright (C) 2011-2012  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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef BQ2415X_CHARGER_H
+#define BQ2415X_CHARGER_H
+
+/*
+ * This is platform data for bq2415x chip. It contains default board
+ * voltages and currents which can be also later configured via sysfs. If
+ * value is -1 then default chip value (specified in datasheet) will be
+ * used.
+ *
+ * Value resistor_sense is needed for for configuring charge and
+ * termination current. It it is less or equal to zero, configuring charge
+ * and termination current will not be possible.
+ *
+ * Function set_mode_hook is needed for automode (setting correct current
+ * limit when charger is connected/disconnected or setting boost mode).
+ * When is NULL, automode function is disabled. When is not NULL, it must
+ * have this prototype:
+ *
+ *    int (*set_mode_hook)(
+ *      void (*hook)(enum bq2415x_mode mode, void *data),
+ *      void *data)
+ *
+ * hook is hook function (see below) and data is pointer to driver private
+ * data
+ *
+ * bq2415x driver will call it as:
+ *
+ *    platform_data->set_mode_hook(bq2415x_hook_function, bq2415x_device);
+ *
+ * Board/platform function set_mode_hook return non zero value when hook
+ * function was successful registered. Platform code should call that hook
+ * function (which get from pointer, with data) every time when charger
+ * was connected/disconnected or require to enable boost mode. bq2415x
+ * driver then will set correct current limit, enable/disable charger or
+ * boost mode.
+ *
+ * Hook function has this prototype:
+ *
+ *    void hook(enum bq2415x_mode mode, void *data);
+ *
+ * mode is bq2415x mode (charger or boost)
+ * data is pointer to driver private data (which get from
+ * set_charger_type_hook)
+ *
+ * When bq driver is being unloaded, it call function:
+ *
+ *    platform_data->set_mode_hook(NULL, NULL);
+ *
+ * (hook function and driver private data are NULL)
+ *
+ * After that board/platform code must not call driver hook function! It
+ * is possible that pointer to hook function will not be valid and calling
+ * will cause undefined result.
+ */
+
+/* Supported modes with maximal current limit */
+enum bq2415x_mode {
+	BQ2415X_MODE_NONE,		/* unknown or no charger (100mA) */
+	BQ2415X_MODE_HOST_CHARGER,	/* usb host/hub charger (500mA) */
+	BQ2415X_MODE_DEDICATED_CHARGER, /* dedicated charger (unlimited) */
+	BQ2415X_MODE_BOOST,		/* boost mode (charging disabled) */
+};
+
+struct bq2415x_platform_data {
+	int current_limit;		/* mA */
+	int weak_battery_voltage;	/* mV */
+	int battery_regulation_voltage;	/* mV */
+	int charge_current;		/* mA */
+	int termination_current;	/* mA */
+	int resistor_sense;		/* m ohm */
+	int (*set_mode_hook)(void (*hook)(enum bq2415x_mode mode, void *data),
+			     void *data);
+};
+
+#endif
diff --git a/include/linux/power/smartreflex.h b/include/linux/power/smartreflex.h
index 4a496eb..c0f44c2 100644
--- a/include/linux/power/smartreflex.h
+++ b/include/linux/power/smartreflex.h
@@ -260,8 +260,13 @@ struct omap_sr_nvalue_table {
  *
  * @name:		instance name
  * @ip_type:		Smartreflex IP type.
- * @senp_mod:		SENPENABLE value for the sr
- * @senn_mod:		SENNENABLE value for sr
+ * @senp_mod:		SENPENABLE value of the sr CONFIG register
+ * @senn_mod:		SENNENABLE value for sr CONFIG register
+ * @err_weight		ERRWEIGHT value of the sr ERRCONFIG register
+ * @err_maxlimit	ERRMAXLIMIT value of the sr ERRCONFIG register
+ * @accum_data		ACCUMDATA value of the sr CONFIG register
+ * @senn_avgweight	SENNAVGWEIGHT value of the sr AVGWEIGHT register
+ * @senp_avgweight	SENPAVGWEIGHT value of the sr AVGWEIGHT register
  * @nvalue_count:	Number of distinct nvalues in the nvalue table
  * @enable_on_init:	whether this sr module needs to enabled at
  *			boot up or not.
@@ -274,6 +279,11 @@ struct omap_sr_data {
 	int				ip_type;
 	u32				senp_mod;
 	u32				senn_mod;
+	u32				err_weight;
+	u32				err_maxlimit;
+	u32				accum_data;
+	u32				senn_avgweight;
+	u32				senp_avgweight;
 	int				nvalue_count;
 	bool				enable_on_init;
 	struct omap_sr_nvalue_table	*nvalue_table;
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index e5ef458..1f0ab90 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -114,6 +114,8 @@ enum power_supply_property {
 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
+	POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
+	POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
 	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
 	POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN,
 	POWER_SUPPLY_PROP_ENERGY_FULL,
@@ -186,6 +188,7 @@ struct power_supply {
 	struct work_struct changed_work;
 #ifdef CONFIG_THERMAL
 	struct thermal_zone_device *tzd;
+	struct thermal_cooling_device *tcd;
 #endif
 
 #ifdef CONFIG_LEDS_TRIGGERS
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 3fd2e87..32676b3 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -28,7 +28,11 @@ struct mm_struct;
  */
 
 enum {
-	PROC_ROOT_INO = 1,
+	PROC_ROOT_INO		= 1,
+	PROC_IPC_INIT_INO	= 0xEFFFFFFFU,
+	PROC_UTS_INIT_INO	= 0xEFFFFFFEU,
+	PROC_USER_INIT_INO	= 0xEFFFFFFDU,
+	PROC_PID_INIT_INO	= 0xEFFFFFFCU,
 };
 
 /*
@@ -174,7 +178,10 @@ extern struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name,
 	struct proc_dir_entry *parent);
 
 extern struct file *proc_ns_fget(int fd);
+extern bool proc_ns_inode(struct inode *inode);
 
+extern int proc_alloc_inum(unsigned int *pino);
+extern void proc_free_inum(unsigned int inum);
 #else
 
 #define proc_net_fops_create(net, name, mode, fops)  ({ (void)(mode), NULL; })
@@ -229,6 +236,19 @@ static inline struct file *proc_ns_fget(int fd)
 	return ERR_PTR(-EINVAL);
 }
 
+static inline bool proc_ns_inode(struct inode *inode)
+{
+	return false;
+}
+
+static inline int proc_alloc_inum(unsigned int *inum)
+{
+	*inum = 1;
+	return 0;
+}
+static inline void proc_free_inum(unsigned int inum)
+{
+}
 #endif /* CONFIG_PROC_FS */
 
 #if !defined(CONFIG_PROC_KCORE)
@@ -247,10 +267,14 @@ struct proc_ns_operations {
 	void *(*get)(struct task_struct *task);
 	void (*put)(void *ns);
 	int (*install)(struct nsproxy *nsproxy, void *ns);
+	unsigned int (*inum)(void *ns);
 };
 extern const struct proc_ns_operations netns_operations;
 extern const struct proc_ns_operations utsns_operations;
 extern const struct proc_ns_operations ipcns_operations;
+extern const struct proc_ns_operations pidns_operations;
+extern const struct proc_ns_operations userns_operations;
+extern const struct proc_ns_operations mntns_operations;
 
 union proc_op {
 	int (*proc_get_link)(struct dentry *, struct path *);
@@ -290,4 +314,7 @@ static inline struct net *PDE_NET(struct proc_dir_entry *pde)
 	return pde->parent->data;
 }
 
+#include <linux/signal.h>
+
+void render_sigset_t(struct seq_file *m, const char *header, sigset_t *set);
 #endif /* _LINUX_PROC_FS_H */
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index ee3034a..1788909 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -50,16 +50,18 @@ struct pstore_info {
 	int		(*open)(struct pstore_info *psi);
 	int		(*close)(struct pstore_info *psi);
 	ssize_t		(*read)(u64 *id, enum pstore_type_id *type,
-			struct timespec *time, char **buf,
+			int *count, struct timespec *time, char **buf,
 			struct pstore_info *psi);
 	int		(*write)(enum pstore_type_id type,
 			enum kmsg_dump_reason reason, u64 *id,
-			unsigned int part, size_t size, struct pstore_info *psi);
+			unsigned int part, int count, size_t size,
+			struct pstore_info *psi);
 	int		(*write_buf)(enum pstore_type_id type,
 			enum kmsg_dump_reason reason, u64 *id,
 			unsigned int part, const char *buf, size_t size,
 			struct pstore_info *psi);
 	int		(*erase)(enum pstore_type_id type, u64 id,
+			int count, struct timespec time,
 			struct pstore_info *psi);
 	void		*data;
 };
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index e0ff468..addfbe7 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -32,6 +32,8 @@
 #define PT_TRACE_EXIT		PT_EVENT_FLAG(PTRACE_EVENT_EXIT)
 #define PT_TRACE_SECCOMP	PT_EVENT_FLAG(PTRACE_EVENT_SECCOMP)
 
+#define PT_EXITKILL		(PTRACE_O_EXITKILL << PT_OPT_FLAG_SHIFT)
+
 /* single stepping state bits (used on ARM and PA-RISC) */
 #define PT_SINGLESTEP_BIT	31
 #define PT_SINGLESTEP		(1<<PT_SINGLESTEP_BIT)
@@ -329,6 +331,19 @@ static inline void user_single_step_siginfo(struct task_struct *tsk,
 #define current_pt_regs() task_pt_regs(current)
 #endif
 
+#ifndef ptrace_signal_deliver
+#define ptrace_signal_deliver() ((void)0)
+#endif
+
+/*
+ * unlike current_pt_regs(), this one is equal to task_pt_regs(current)
+ * on *all* architectures; the only reason to have a per-arch definition
+ * is optimisation.
+ */
+#ifndef signal_pt_regs
+#define signal_pt_regs() task_pt_regs(current)
+#endif
+
 extern int task_current_syscall(struct task_struct *target, long *callno,
 				unsigned long args[6], unsigned int maxargs,
 				unsigned long *sp, unsigned long *pc);
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index 112b314..6d661f3 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -171,6 +171,9 @@ struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
 					 unsigned int index,
 					 const char *label);
 
+struct pwm_device *of_pwm_xlate_with_flags(struct pwm_chip *pc,
+		const struct of_phandle_args *args);
+
 struct pwm_device *pwm_get(struct device *dev, const char *consumer);
 void pwm_put(struct pwm_device *pwm);
 
diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h
index 640c69c..3156347 100644
--- a/include/linux/raid/pq.h
+++ b/include/linux/raid/pq.h
@@ -109,6 +109,7 @@ struct raid6_recov_calls {
 
 extern const struct raid6_recov_calls raid6_recov_intx1;
 extern const struct raid6_recov_calls raid6_recov_ssse3;
+extern const struct raid6_recov_calls raid6_recov_avx2;
 
 /* Algorithm list */
 extern const struct raid6_calls * const raid6_algos[];
diff --git a/include/linux/random.h b/include/linux/random.h
index 6330ed4..d984608 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -25,10 +25,19 @@ extern const struct file_operations random_fops, urandom_fops;
 unsigned int get_random_int(void);
 unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len);
 
-u32 random32(void);
-void srandom32(u32 seed);
+u32 prandom_u32(void);
+void prandom_bytes(void *buf, int nbytes);
+void prandom_seed(u32 seed);
 
-u32 prandom32(struct rnd_state *);
+/*
+ * These macros are preserved for backward compatibility and should be
+ * removed as soon as a transition is finished.
+ */
+#define random32() prandom_u32()
+#define srandom32(seed) prandom_seed(seed)
+
+u32 prandom_u32_state(struct rnd_state *);
+void prandom_bytes_state(struct rnd_state *state, void *buf, int nbytes);
 
 /*
  * Handle minimum values for seeds
@@ -39,11 +48,11 @@ static inline u32 __seed(u32 x, u32 m)
 }
 
 /**
- * prandom32_seed - set seed for prandom32().
+ * prandom_seed_state - set seed for prandom_u32_state().
  * @state: pointer to state structure to receive the seed.
  * @seed: arbitrary 64-bit value to use as a seed.
  */
-static inline void prandom32_seed(struct rnd_state *state, u64 seed)
+static inline void prandom_seed_state(struct rnd_state *state, u64 seed)
 {
 	u32 i = (seed >> 32) ^ (seed << 10) ^ seed;
 
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index e0f0fab..c92dd28 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -286,23 +286,6 @@ static inline void list_splice_init_rcu(struct list_head *list,
 		&pos->member != (head); \
 		pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
 
-
-/**
- * list_for_each_continue_rcu
- * @pos:	the &struct list_head to use as a loop cursor.
- * @head:	the head for your list.
- *
- * Iterate over an rcu-protected list, continuing after current point.
- *
- * This list-traversal primitive may safely run concurrently with
- * the _rcu list-mutation primitives such as list_add_rcu()
- * as long as the traversal is guarded by rcu_read_lock().
- */
-#define list_for_each_continue_rcu(pos, head) \
-	for ((pos) = rcu_dereference_raw(list_next_rcu(pos)); \
-		(pos) != (head); \
-		(pos) = rcu_dereference_raw(list_next_rcu(pos)))
-
 /**
  * list_for_each_entry_continue_rcu - continue iteration over list of given type
  * @pos:	the type * to use as a loop cursor.
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 7c968e4..275aa3f 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -90,6 +90,25 @@ extern void do_trace_rcu_torture_read(char *rcutorturename,
  * that started after call_rcu() was invoked.  RCU read-side critical
  * sections are delimited by rcu_read_lock() and rcu_read_unlock(),
  * and may be nested.
+ *
+ * Note that all CPUs must agree that the grace period extended beyond
+ * all pre-existing RCU read-side critical section.  On systems with more
+ * than one CPU, this means that when "func()" is invoked, each CPU is
+ * guaranteed to have executed a full memory barrier since the end of its
+ * last RCU read-side critical section whose beginning preceded the call
+ * to call_rcu().  It also means that each CPU executing an RCU read-side
+ * critical section that continues beyond the start of "func()" must have
+ * executed a memory barrier after the call_rcu() but before the beginning
+ * of that RCU read-side critical section.  Note that these guarantees
+ * include CPUs that are offline, idle, or executing in user mode, as
+ * well as CPUs that are executing in the kernel.
+ *
+ * Furthermore, if CPU A invoked call_rcu() and CPU B invoked the
+ * resulting RCU callback function "func()", then both CPU A and CPU B are
+ * guaranteed to execute a full memory barrier during the time interval
+ * between the call to call_rcu() and the invocation of "func()" -- even
+ * if CPU A and CPU B are the same CPU (but again only if the system has
+ * more than one CPU).
  */
 extern void call_rcu(struct rcu_head *head,
 			      void (*func)(struct rcu_head *head));
@@ -118,6 +137,9 @@ extern void call_rcu(struct rcu_head *head,
  *  OR
  *  - rcu_read_lock_bh() and rcu_read_unlock_bh(), if in process context.
  *  These may be nested.
+ *
+ * See the description of call_rcu() for more detailed information on
+ * memory ordering guarantees.
  */
 extern void call_rcu_bh(struct rcu_head *head,
 			void (*func)(struct rcu_head *head));
@@ -137,6 +159,9 @@ extern void call_rcu_bh(struct rcu_head *head,
  *  OR
  *  anything that disables preemption.
  *  These may be nested.
+ *
+ * See the description of call_rcu() for more detailed information on
+ * memory ordering guarantees.
  */
 extern void call_rcu_sched(struct rcu_head *head,
 			   void (*func)(struct rcu_head *rcu));
@@ -197,13 +222,13 @@ extern void rcu_user_enter(void);
 extern void rcu_user_exit(void);
 extern void rcu_user_enter_after_irq(void);
 extern void rcu_user_exit_after_irq(void);
-extern void rcu_user_hooks_switch(struct task_struct *prev,
-				  struct task_struct *next);
 #else
 static inline void rcu_user_enter(void) { }
 static inline void rcu_user_exit(void) { }
 static inline void rcu_user_enter_after_irq(void) { }
 static inline void rcu_user_exit_after_irq(void) { }
+static inline void rcu_user_hooks_switch(struct task_struct *prev,
+					 struct task_struct *next) { }
 #endif /* CONFIG_RCU_USER_QS */
 
 extern void exit_rcu(void);
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index e3bcc3f..b7e95bf 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -19,6 +19,7 @@
 struct module;
 struct device;
 struct i2c_client;
+struct irq_domain;
 struct spi_device;
 struct regmap;
 struct regmap_range_cfg;
@@ -54,6 +55,39 @@ enum regmap_endian {
 };
 
 /**
+ * A register range, used for access related checks
+ * (readable/writeable/volatile/precious checks)
+ *
+ * @range_min: address of first register
+ * @range_max: address of last register
+ */
+struct regmap_range {
+	unsigned int range_min;
+	unsigned int range_max;
+};
+
+/*
+ * A table of ranges including some yes ranges and some no ranges.
+ * If a register belongs to a no_range, the corresponding check function
+ * will return false. If a register belongs to a yes range, the corresponding
+ * check function will return true. "no_ranges" are searched first.
+ *
+ * @yes_ranges : pointer to an array of regmap ranges used as "yes ranges"
+ * @n_yes_ranges: size of the above array
+ * @no_ranges: pointer to an array of regmap ranges used as "no ranges"
+ * @n_no_ranges: size of the above array
+ */
+struct regmap_access_table {
+	const struct regmap_range *yes_ranges;
+	unsigned int n_yes_ranges;
+	const struct regmap_range *no_ranges;
+	unsigned int n_no_ranges;
+};
+
+typedef void (*regmap_lock)(void *);
+typedef void (*regmap_unlock)(void *);
+
+/**
  * Configuration for the register map of a device.
  *
  * @name: Optional name of the regmap. Useful when a device has multiple
@@ -67,16 +101,39 @@ enum regmap_endian {
  * @val_bits: Number of bits in a register value, mandatory.
  *
  * @writeable_reg: Optional callback returning true if the register
- *                 can be written to.
+ *		   can be written to. If this field is NULL but wr_table
+ *		   (see below) is not, the check is performed on such table
+ *                 (a register is writeable if it belongs to one of the ranges
+ *                  specified by wr_table).
  * @readable_reg: Optional callback returning true if the register
- *                can be read from.
+ *		  can be read from. If this field is NULL but rd_table
+ *		   (see below) is not, the check is performed on such table
+ *                 (a register is readable if it belongs to one of the ranges
+ *                  specified by rd_table).
  * @volatile_reg: Optional callback returning true if the register
- *                value can't be cached.
+ *		  value can't be cached. If this field is NULL but
+ *		  volatile_table (see below) is not, the check is performed on
+ *                such table (a register is volatile if it belongs to one of
+ *                the ranges specified by volatile_table).
  * @precious_reg: Optional callback returning true if the rgister
- *                should not be read outside of a call from the driver
- *                (eg, a clear on read interrupt status register).
+ *		  should not be read outside of a call from the driver
+ *		  (eg, a clear on read interrupt status register). If this
+ *                field is NULL but precious_table (see below) is not, the
+ *                check is performed on such table (a register is precious if
+ *                it belongs to one of the ranges specified by precious_table).
+ * @lock:	  Optional lock callback (overrides regmap's default lock
+ *		  function, based on spinlock or mutex).
+ * @unlock:	  As above for unlocking.
+ * @lock_arg:	  this field is passed as the only argument of lock/unlock
+ *		  functions (ignored in case regular lock/unlock functions
+ *		  are not overridden).
  *
  * @max_register: Optional, specifies the maximum valid register index.
+ * @wr_table:     Optional, points to a struct regmap_access_table specifying
+ *                valid ranges for write access.
+ * @rd_table:     As above, for read access.
+ * @volatile_table: As above, for volatile registers.
+ * @precious_table: As above, for precious registers.
  * @reg_defaults: Power on reset values for registers (for use with
  *                register cache support).
  * @num_reg_defaults: Number of elements in reg_defaults.
@@ -116,8 +173,15 @@ struct regmap_config {
 	bool (*readable_reg)(struct device *dev, unsigned int reg);
 	bool (*volatile_reg)(struct device *dev, unsigned int reg);
 	bool (*precious_reg)(struct device *dev, unsigned int reg);
+	regmap_lock lock;
+	regmap_unlock unlock;
+	void *lock_arg;
 
 	unsigned int max_register;
+	const struct regmap_access_table *wr_table;
+	const struct regmap_access_table *rd_table;
+	const struct regmap_access_table *volatile_table;
+	const struct regmap_access_table *precious_table;
 	const struct reg_default *reg_defaults;
 	unsigned int num_reg_defaults;
 	enum regcache_type cache_type;
@@ -133,7 +197,7 @@ struct regmap_config {
 	enum regmap_endian val_format_endian;
 
 	const struct regmap_range_cfg *ranges;
-	unsigned int n_ranges;
+	unsigned int num_ranges;
 };
 
 /**
@@ -142,6 +206,8 @@ struct regmap_config {
  *     1. page selector register update;
  *     2. access through data window registers.
  *
+ * @name: Descriptive name for diagnostics
+ *
  * @range_min: Address of the lowest register address in virtual range.
  * @range_max: Address of the highest register in virtual range.
  *
@@ -153,6 +219,8 @@ struct regmap_config {
  * @window_len: Number of registers in data window.
  */
 struct regmap_range_cfg {
+	const char *name;
+
 	/* Registers of virtual address range */
 	unsigned int range_min;
 	unsigned int range_max;
@@ -181,7 +249,9 @@ typedef void (*regmap_hw_free_context)(void *context);
  * Description of a hardware bus for the register map infrastructure.
  *
  * @fast_io: Register IO is fast. Use a spinlock instead of a mutex
- *           to perform locking.
+ *	     to perform locking. This field is ignored if custom lock/unlock
+ *	     functions are used (see fields lock/unlock of
+ *	     struct regmap_config).
  * @write: Write operation.
  * @gather_write: Write operation with split register/value, return -ENOTSUPP
  *                if not implemented  on a given device.
@@ -262,6 +332,16 @@ void regcache_mark_dirty(struct regmap *map);
 int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
 			  int num_regs);
 
+static inline bool regmap_reg_in_range(unsigned int reg,
+				       const struct regmap_range *range)
+{
+	return reg >= range->range_min && reg <= range->range_max;
+}
+
+bool regmap_reg_in_ranges(unsigned int reg,
+			  const struct regmap_range *ranges,
+			  unsigned int nranges);
+
 /**
  * Description of an IRQ for the generic regmap irq_chip.
  *
@@ -317,6 +397,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
 void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *data);
 int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data);
 int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq);
+struct irq_domain *regmap_irq_get_domain(struct regmap_irq_chip_data *data);
 
 #else
 
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index c43cd35..6c0c2c8 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -358,6 +358,10 @@ static inline void regulator_set_drvdata(struct regulator *regulator,
 {
 }
 
+static inline int regulator_count_voltages(struct regulator *regulator)
+{
+	return 0;
+}
 #endif
 
 static inline int regulator_set_voltage_tol(struct regulator *regulator,
@@ -367,4 +371,12 @@ static inline int regulator_set_voltage_tol(struct regulator *regulator,
 				     new_uV - tol_uV, new_uV + tol_uV);
 }
 
+static inline int regulator_is_supported_voltage_tol(struct regulator *regulator,
+						     int target_uV, int tol_uV)
+{
+	return regulator_is_supported_voltage(regulator,
+					      target_uV - tol_uV,
+					      target_uV + tol_uV);
+}
+
 #endif
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 7932a3b..d10bb0f 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -181,10 +181,13 @@ enum regulator_type {
  * @type: Indicates if the regulator is a voltage or current regulator.
  * @owner: Module providing the regulator, used for refcounting.
  *
+ * @continuous_voltage_range: Indicates if the regulator can set any
+ *                            voltage within constrains range.
  * @n_voltages: Number of selectors available for ops.list_voltage().
  *
  * @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
  * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
  * @volt_table: Voltage mapping table (if table based mapping)
  *
@@ -199,6 +202,7 @@ struct regulator_desc {
 	const char *name;
 	const char *supply_name;
 	int id;
+	bool continuous_voltage_range;
 	unsigned n_voltages;
 	struct regulator_ops *ops;
 	int irq;
@@ -207,6 +211,7 @@ struct regulator_desc {
 
 	unsigned int min_uV;
 	unsigned int uV_step;
+	unsigned int linear_min_sel;
 	unsigned int ramp_delay;
 
 	const unsigned int *volt_table;
diff --git a/include/linux/regulator/max8973-regulator.h b/include/linux/regulator/max8973-regulator.h
new file mode 100644
index 0000000..f8acc05
--- /dev/null
+++ b/include/linux/regulator/max8973-regulator.h
@@ -0,0 +1,72 @@
+/*
+ * max8973-regulator.h -- MAXIM 8973 regulator
+ *
+ * Interface for regulator driver for MAXIM 8973 DC-DC step-down
+ * switching regulator.
+ *
+ * Copyright (C) 2012 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA	02110-1301, USA.
+ *
+ */
+
+#ifndef __LINUX_REGULATOR_MAX8973_H
+#define __LINUX_REGULATOR_MAX8973_H
+
+/*
+ * Control flags for configuration of the device.
+ * Client need to pass this information with ORed
+ */
+#define MAX8973_CONTROL_REMOTE_SENSE_ENABLE			0x00000001
+#define MAX8973_CONTROL_FALLING_SLEW_RATE_ENABLE		0x00000002
+#define MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE		0x00000004
+#define MAX8973_CONTROL_BIAS_ENABLE				0x00000008
+#define MAX8973_CONTROL_PULL_DOWN_ENABLE			0x00000010
+#define MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE			0x00000020
+
+#define MAX8973_CONTROL_CLKADV_TRIP_DISABLED			0x00000000
+#define MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US			0x00010000
+#define MAX8973_CONTROL_CLKADV_TRIP_150mV_PER_US		0x00020000
+#define MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US_HIST_DIS	0x00030000
+
+#define MAX8973_CONTROL_INDUCTOR_VALUE_NOMINAL			0x00000000
+#define MAX8973_CONTROL_INDUCTOR_VALUE_MINUS_30_PER		0x00100000
+#define MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_30_PER		0x00200000
+#define MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_60_PER		0x00300000
+
+/*
+ * struct max8973_regulator_platform_data - max8973 regulator platform data.
+ *
+ * @reg_init_data: The regulator init data.
+ * @control_flags: Control flags which are ORed value of above flags to
+ *		configure device.
+ * @enable_ext_control: Enable the voltage enable/disable through external
+ *		control signal from EN input pin. If it is false then
+ *		voltage output will be enabled/disabled through EN bit of
+ *		device register.
+ * @dvs_gpio: GPIO for dvs. It should be -1 if this is tied with fixed logic.
+ * @dvs_def_state: Default state of dvs. 1 if it is high else 0.
+ */
+struct max8973_regulator_platform_data {
+	struct regulator_init_data *reg_init_data;
+	unsigned long control_flags;
+	bool enable_ext_control;
+	int dvs_gpio;
+	unsigned dvs_def_state:1;
+};
+
+#endif /* __LINUX_REGULATOR_MAX8973_H */
diff --git a/include/linux/regulator/tps51632-regulator.h b/include/linux/regulator/tps51632-regulator.h
new file mode 100644
index 0000000..d00841e
--- /dev/null
+++ b/include/linux/regulator/tps51632-regulator.h
@@ -0,0 +1,47 @@
+/*
+ * tps51632-regulator.h -- TPS51632 regulator
+ *
+ * Interface for regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down
+ * Driverless Controller with serial VID control and DVFS.
+ *
+ * Copyright (C) 2012 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA	02110-1301, USA.
+ *
+ */
+
+#ifndef __LINUX_REGULATOR_TPS51632_H
+#define __LINUX_REGULATOR_TPS51632_H
+
+/*
+ * struct tps51632_regulator_platform_data - tps51632 regulator platform data.
+ *
+ * @reg_init_data: The regulator init data.
+ * @enable_pwm_dvfs: Enable PWM DVFS or not.
+ * @dvfs_step_20mV: Step for DVFS is 20mV or 10mV.
+ * @max_voltage_uV: Maximum possible voltage in PWM-DVFS mode.
+ * @base_voltage_uV: Base voltage when PWM-DVFS enabled.
+ */
+struct tps51632_regulator_platform_data {
+	struct regulator_init_data *reg_init_data;
+	bool enable_pwm_dvfs;
+	bool dvfs_step_20mV;
+	int max_voltage_uV;
+	int base_voltage_uV;
+};
+
+#endif /* __LINUX_REGULATOR_TPS51632_H */
diff --git a/include/linux/regulator/tps65090-regulator.h b/include/linux/regulator/tps65090-regulator.h
deleted file mode 100644
index 0fa04b6..0000000
--- a/include/linux/regulator/tps65090-regulator.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Regulator driver interface for TI TPS65090 PMIC family
- *
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
-
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
-
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __REGULATOR_TPS65090_H
-#define __REGULATOR_TPS65090_H
-
-#include <linux/regulator/machine.h>
-
-#define tps65090_rails(_name) "tps65090_"#_name
-
-enum {
-	TPS65090_ID_DCDC1,
-	TPS65090_ID_DCDC2,
-	TPS65090_ID_DCDC3,
-	TPS65090_ID_FET1,
-	TPS65090_ID_FET2,
-	TPS65090_ID_FET3,
-	TPS65090_ID_FET4,
-	TPS65090_ID_FET5,
-	TPS65090_ID_FET6,
-	TPS65090_ID_FET7,
-};
-
-/*
- * struct tps65090_regulator_platform_data
- *
- * @regulator: The regulator init data.
- * @slew_rate_uV_per_us: Slew rate microvolt per microsec.
- */
-
-struct tps65090_regulator_platform_data {
-	struct regulator_init_data regulator;
-};
-
-#endif	/* __REGULATOR_TPS65090_H */
diff --git a/include/linux/res_counter.h b/include/linux/res_counter.h
index 7d7fbe2..5ae8456 100644
--- a/include/linux/res_counter.h
+++ b/include/linux/res_counter.h
@@ -74,14 +74,9 @@ ssize_t res_counter_read(struct res_counter *counter, int member,
 		const char __user *buf, size_t nbytes, loff_t *pos,
 		int (*read_strategy)(unsigned long long val, char *s));
 
-typedef int (*write_strategy_fn)(const char *buf, unsigned long long *val);
-
 int res_counter_memparse_write_strategy(const char *buf,
 					unsigned long long *res);
 
-int res_counter_write(struct res_counter *counter, int member,
-		      const char *buffer, write_strategy_fn write_strategy);
-
 /*
  * the field descriptors. one for each member of res_counter
  */
@@ -130,14 +125,16 @@ int res_counter_charge_nofail(struct res_counter *counter,
  *
  * these calls check for usage underflow and show a warning on the console
  * _locked call expects the counter->lock to be taken
+ *
+ * returns the total charges still present in @counter.
  */
 
-void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val);
-void res_counter_uncharge(struct res_counter *counter, unsigned long val);
+u64 res_counter_uncharge_locked(struct res_counter *counter, unsigned long val);
+u64 res_counter_uncharge(struct res_counter *counter, unsigned long val);
 
-void res_counter_uncharge_until(struct res_counter *counter,
-				struct res_counter *top,
-				unsigned long val);
+u64 res_counter_uncharge_until(struct res_counter *counter,
+			       struct res_counter *top,
+			       unsigned long val);
 /**
  * res_counter_margin - calculate chargeable space of a counter
  * @cnt: the counter
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index 6c8835f..519777e 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -159,13 +159,14 @@ int ring_buffer_record_is_on(struct ring_buffer *buffer);
 void ring_buffer_record_disable_cpu(struct ring_buffer *buffer, int cpu);
 void ring_buffer_record_enable_cpu(struct ring_buffer *buffer, int cpu);
 
-unsigned long ring_buffer_oldest_event_ts(struct ring_buffer *buffer, int cpu);
+u64 ring_buffer_oldest_event_ts(struct ring_buffer *buffer, int cpu);
 unsigned long ring_buffer_bytes_cpu(struct ring_buffer *buffer, int cpu);
 unsigned long ring_buffer_entries(struct ring_buffer *buffer);
 unsigned long ring_buffer_overruns(struct ring_buffer *buffer);
 unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu);
 unsigned long ring_buffer_overrun_cpu(struct ring_buffer *buffer, int cpu);
 unsigned long ring_buffer_commit_overrun_cpu(struct ring_buffer *buffer, int cpu);
+unsigned long ring_buffer_dropped_events_cpu(struct ring_buffer *buffer, int cpu);
 
 u64 ring_buffer_time_stamp(struct ring_buffer *buffer, int cpu);
 void ring_buffer_normalize_time_stamp(struct ring_buffer *buffer,
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index bfe1f47..1bd87d6 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -35,6 +35,9 @@ struct anon_vma {
 	 * anon_vma if they are the last user on release
 	 */
 	atomic_t refcount;
+#ifdef CONFIG_SWAP
+	atomic_t swapra_miss;
+#endif
 
 	/*
 	 * NOTE: the LSB of the rb_root.rb_node is set by
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 7002bbf..489dd7bb 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -69,4 +69,7 @@ extern int ndo_dflt_fdb_dump(struct sk_buff *skb,
 			     struct netlink_callback *cb,
 			     struct net_device *dev,
 			     int idx);
+
+extern int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+				   struct net_device *dev, u16 mode);
 #endif	/* __LINUX_RTNETLINK_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 0dd42a0..191e4c5 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -109,6 +109,8 @@ extern void update_cpu_load_nohz(void);
 
 extern unsigned long get_parent_ip(unsigned long addr);
 
+extern void dump_cpu_task(int cpu);
+
 struct seq_file;
 struct cfs_rq;
 struct task_group;
@@ -631,9 +633,10 @@ struct signal_struct {
 	struct rw_semaphore group_rwsem;
 #endif
 
-	int oom_score_adj;	/* OOM kill score adjustment */
-	int oom_score_adj_min;	/* OOM kill score adjustment minimum value.
-				 * Only settable by CAP_SYS_RESOURCE. */
+	oom_flags_t oom_flags;
+	short oom_score_adj;		/* OOM kill score adjustment */
+	short oom_score_adj_min;	/* OOM kill score adjustment min value.
+					 * Only settable by CAP_SYS_RESOURCE. */
 
 	struct mutex cred_guard_mutex;	/* guard against foreign influences on
 					 * credential calculations
@@ -823,6 +826,7 @@ enum cpu_idle_type {
 #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);
 
@@ -1061,6 +1065,7 @@ struct sched_class {
 
 #ifdef CONFIG_SMP
 	int  (*select_task_rq)(struct task_struct *p, 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);
 	void (*post_schedule) (struct rq *this_rq);
@@ -1095,6 +1100,18 @@ struct load_weight {
 	unsigned long weight, inv_weight;
 };
 
+struct sched_avg {
+	/*
+	 * These sums represent an infinite geometric series and so are bound
+	 * above by 1024/(1-y).  Thus we only need a u32 to store them for for all
+	 * choices of y < 1-2^(-32)*1024.
+	 */
+	u32 runnable_avg_sum, runnable_avg_period;
+	u64 last_runnable_update;
+	s64 decay_count;
+	unsigned long load_avg_contrib;
+};
+
 #ifdef CONFIG_SCHEDSTATS
 struct sched_statistics {
 	u64			wait_start;
@@ -1155,6 +1172,15 @@ struct sched_entity {
 	/* rq "owned" by this entity/group: */
 	struct cfs_rq		*my_q;
 #endif
+/*
+ * Load-tracking only depends on SMP, FAIR_GROUP_SCHED dependency below may be
+ * removed when useful for applications beyond shares distribution (e.g.
+ * load-balance).
+ */
+#if defined(CONFIG_SMP) && defined(CONFIG_FAIR_GROUP_SCHED)
+	/* Per-entity load-tracking */
+	struct sched_avg	avg;
+#endif
 };
 
 struct sched_rt_entity {
@@ -1479,6 +1505,24 @@ struct task_struct {
 	short il_next;
 	short pref_node_fork;
 #endif
+#ifdef CONFIG_NUMA_BALANCING
+	int numa_shared;
+	int numa_max_node;
+	int numa_scan_seq;
+	int numa_migrate_seq;
+	unsigned int numa_scan_period;
+	u64 node_stamp;			/* migration stamp  */
+	unsigned long numa_weight;
+	unsigned long *numa_faults;
+	unsigned long *numa_faults_curr;
+	struct callback_head numa_work;
+
+	struct task_struct *shared_buddy, *shared_buddy_curr;
+	unsigned long shared_buddy_faults, shared_buddy_faults_curr;
+	int ideal_cpu, ideal_cpu_curr;
+
+#endif /* CONFIG_NUMA_BALANCING */
+
 	struct rcu_head rcu;
 
 	/*
@@ -1541,6 +1585,7 @@ struct task_struct {
 		unsigned long nr_pages;	/* uncharged usage */
 		unsigned long memsw_nr_pages; /* uncharged mem+swap usage */
 	} memcg_batch;
+	unsigned int memcg_kmem_skip_account;
 #endif
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
 	atomic_t ptrace_bp_refcnt;
@@ -1553,6 +1598,26 @@ struct task_struct {
 /* Future-safe accessor for struct task_struct's cpus_allowed. */
 #define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed)
 
+#ifdef CONFIG_NUMA_BALANCING
+extern void task_numa_fault(int node, int cpu, int pages);
+#else
+static inline void task_numa_fault(int node, int cpu, int pages) { }
+#endif /* CONFIG_NUMA_BALANCING */
+
+/*
+ * -1: non-NUMA task
+ *  0: NUMA task with a dominantly 'private' working set
+ *  1: NUMA task with a dominantly 'shared' working set
+ */
+static inline int task_numa_shared(struct task_struct *p)
+{
+#ifdef CONFIG_NUMA_BALANCING
+	return p->numa_shared;
+#else
+	return -1;
+#endif
+}
+
 /*
  * Priority of a process goes from 0..MAX_PRIO-1, valid RT
  * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
@@ -1710,12 +1775,6 @@ static inline int is_global_init(struct task_struct *tsk)
 	return tsk->pid == 1;
 }
 
-/*
- * is_container_init:
- * check whether in the task is init in its own pid namespace.
- */
-extern int is_container_init(struct task_struct *tsk);
-
 extern struct pid *cad_pid;
 
 extern void free_task(struct task_struct *tsk);
@@ -1844,14 +1903,6 @@ static inline void rcu_copy_process(struct task_struct *p)
 
 #endif
 
-static inline void rcu_switch(struct task_struct *prev,
-			      struct task_struct *next)
-{
-#ifdef CONFIG_RCU_USER_QS
-	rcu_user_hooks_switch(prev, next);
-#endif
-}
-
 static inline void tsk_restore_flags(struct task_struct *task,
 				unsigned long orig_flags, unsigned long flags)
 {
@@ -1990,6 +2041,12 @@ enum sched_tunable_scaling {
 };
 extern enum sched_tunable_scaling sysctl_sched_tunable_scaling;
 
+extern unsigned int sysctl_sched_numa_scan_delay;
+extern unsigned int sysctl_sched_numa_scan_period_min;
+extern unsigned int sysctl_sched_numa_scan_period_max;
+extern unsigned int sysctl_sched_numa_scan_size;
+extern unsigned int sysctl_sched_numa_settle_count;
+
 #ifdef CONFIG_SCHED_DEBUG
 extern unsigned int sysctl_sched_migration_cost;
 extern unsigned int sysctl_sched_nr_migrate;
@@ -2000,18 +2057,17 @@ extern unsigned int sysctl_sched_shares_window;
 int sched_proc_update_handler(struct ctl_table *table, int write,
 		void __user *buffer, size_t *length,
 		loff_t *ppos);
-#endif
-#ifdef CONFIG_SCHED_DEBUG
+
 static inline unsigned int get_sysctl_timer_migration(void)
 {
 	return sysctl_timer_migration;
 }
-#else
+#else /* CONFIG_SCHED_DEBUG */
 static inline unsigned int get_sysctl_timer_migration(void)
 {
 	return 1;
 }
-#endif
+#endif /* CONFIG_SCHED_DEBUG */
 extern unsigned int sysctl_sched_rt_period;
 extern int sysctl_sched_rt_runtime;
 
@@ -2271,7 +2327,7 @@ extern void mm_release(struct task_struct *, struct mm_struct *);
 extern struct mm_struct *dup_mm(struct task_struct *tsk);
 
 extern int copy_thread(unsigned long, unsigned long, unsigned long,
-			struct task_struct *, struct pt_regs *);
+			struct task_struct *);
 extern void flush_thread(void);
 extern void exit_thread(void);
 
@@ -2283,14 +2339,13 @@ extern void flush_itimer_signals(void);
 
 extern void do_group_exit(int);
 
-extern void daemonize(const char *, ...);
 extern int allow_signal(int);
 extern int disallow_signal(int);
 
 extern int do_execve(const char *,
 		     const char __user * const __user *,
-		     const char __user * const __user *, struct pt_regs *);
-extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *);
+		     const char __user * const __user *);
+extern long do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *);
 struct task_struct *fork_idle(int);
 #ifdef CONFIG_GENERIC_KERNEL_THREAD
 extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
diff --git a/include/linux/security.h b/include/linux/security.h
index 05e88bd..0f6afc6 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -694,6 +694,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *	userspace to load a kernel module with the given name.
  *	@kmod_name name of the module requested by the kernel
  *	Return 0 if successful.
+ * @kernel_module_from_file:
+ *	Load a kernel module from userspace.
+ *	@file contains the file structure pointing to the file containing
+ *	the kernel module to load. If the module is being loaded from a blob,
+ *	this argument will be NULL.
+ *	Return 0 if permission is granted.
  * @task_fix_setuid:
  *	Update the module's state after setting one or more of the user
  *	identity attributes of the current process.  The @flags parameter
@@ -1508,6 +1514,7 @@ struct security_operations {
 	int (*kernel_act_as)(struct cred *new, u32 secid);
 	int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
 	int (*kernel_module_request)(char *kmod_name);
+	int (*kernel_module_from_file)(struct file *file);
 	int (*task_fix_setuid) (struct cred *new, const struct cred *old,
 				int flags);
 	int (*task_setpgid) (struct task_struct *p, pid_t pgid);
@@ -1765,6 +1772,7 @@ void security_transfer_creds(struct cred *new, const struct cred *old);
 int security_kernel_act_as(struct cred *new, u32 secid);
 int security_kernel_create_files_as(struct cred *new, struct inode *inode);
 int security_kernel_module_request(char *kmod_name);
+int security_kernel_module_from_file(struct file *file);
 int security_task_fix_setuid(struct cred *new, const struct cred *old,
 			     int flags);
 int security_task_setpgid(struct task_struct *p, pid_t pgid);
@@ -2278,6 +2286,11 @@ static inline int security_kernel_module_request(char *kmod_name)
 	return 0;
 }
 
+static inline int security_kernel_module_from_file(struct file *file)
+{
+	return 0;
+}
+
 static inline int security_task_fix_setuid(struct cred *new,
 					   const struct cred *old,
 					   int flags)
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index c174c90..c490d20 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -105,6 +105,8 @@ extern int early_serial_setup(struct uart_port *port);
 
 extern int serial8250_find_port(struct uart_port *p);
 extern int serial8250_find_port_for_earlycon(void);
+extern unsigned int serial8250_early_in(struct uart_port *port, int offset);
+extern void serial8250_early_out(struct uart_port *port, int offset, int value);
 extern int setup_early_serial8250_console(char *cmdline);
 extern void serial8250_do_set_termios(struct uart_port *port,
 		struct ktermios *termios, struct ktermios *old);
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 3c43022..c6690a2 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -46,6 +46,8 @@ struct uart_ops {
 	unsigned int	(*get_mctrl)(struct uart_port *);
 	void		(*stop_tx)(struct uart_port *);
 	void		(*start_tx)(struct uart_port *);
+	void		(*throttle)(struct uart_port *);
+	void		(*unthrottle)(struct uart_port *);
 	void		(*send_xchar)(struct uart_port *, char ch);
 	void		(*stop_rx)(struct uart_port *);
 	void		(*enable_ms)(struct uart_port *);
@@ -163,6 +165,10 @@ struct uart_port {
 #define UPF_BUGGY_UART		((__force upf_t) (1 << 14))
 #define UPF_NO_TXEN_TEST	((__force upf_t) (1 << 15))
 #define UPF_MAGIC_MULTIPLIER	((__force upf_t) (1 << 16))
+/* Port has hardware-assisted h/w flow control (iow, auto-RTS *not* auto-CTS) */
+#define UPF_HARD_FLOW		((__force upf_t) (1 << 21))
+/* Port has hardware-assisted s/w flow control */
+#define UPF_SOFT_FLOW		((__force upf_t) (1 << 22))
 #define UPF_CONS_FLOW		((__force upf_t) (1 << 23))
 #define UPF_SHARE_IRQ		((__force upf_t) (1 << 24))
 #define UPF_EXAR_EFR		((__force upf_t) (1 << 25))
diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h
index 5091091..60c7239 100644
--- a/include/linux/sh_clk.h
+++ b/include/linux/sh_clk.h
@@ -199,4 +199,13 @@ int sh_clk_div6_reparent_register(struct clk *clks, int nr);
 #define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
 #define CLKDEV_ICK_ID(_cid, _did, _clk) { .con_id = _cid, .dev_id = _did, .clk = _clk }
 
+/* .enable_reg will be updated to .mapping on sh_clk_fsidiv_register() */
+#define SH_CLK_FSIDIV(_reg, _parent)		\
+{						\
+	.enable_reg = (void __iomem *)_reg,	\
+	.parent		= _parent,		\
+}
+
+int sh_clk_fsidiv_register(struct clk *clks, int nr);
+
 #endif /* __SH_CLOCK_H */
diff --git a/include/linux/shm.h b/include/linux/shm.h
index bcf8a6a..429c199 100644
--- a/include/linux/shm.h
+++ b/include/linux/shm.h
@@ -29,6 +29,21 @@ struct shmid_kernel /* private to the kernel */
 #define SHM_HUGETLB     04000   /* segment will use huge TLB pages */
 #define SHM_NORESERVE   010000  /* don't check for reservations */
 
+/* Bits [26:31] are reserved */
+
+/*
+ * When SHM_HUGETLB is set bits [26:31] encode the log2 of the huge page size.
+ * This gives us 6 bits, which is enough until someone invents 128 bit address
+ * spaces.
+ *
+ * Assume these are all power of twos.
+ * When 0 use the default page size.
+ */
+#define SHM_HUGE_SHIFT  26
+#define SHM_HUGE_MASK   0x3f
+#define SHM_HUGE_2MB    (21 << SHM_HUGE_SHIFT)
+#define SHM_HUGE_1GB    (30 << SHM_HUGE_SHIFT)
+
 #ifdef CONFIG_SYSVIPC
 long do_shmat(int shmid, char __user *shmaddr, int shmflg, unsigned long *addr,
 	      unsigned long shmlba);
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 6a2c34e..f2af494 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -235,11 +235,13 @@ enum {
 /*
  * The callback notifies userspace to release buffers when skb DMA is done in
  * lower device, the skb last reference should be 0 when calling this.
+ * The zerocopy_success argument is true if zero copy transmit occurred,
+ * false on data copy or out of memory error caused by data copy attempt.
  * The ctx field is used to track device context.
  * The desc field is used to track userspace buffer index.
  */
 struct ubuf_info {
-	void (*callback)(struct ubuf_info *);
+	void (*callback)(struct ubuf_info *, bool zerocopy_success);
 	void *ctx;
 	unsigned long desc;
 };
@@ -566,6 +568,7 @@ static inline struct rtable *skb_rtable(const struct sk_buff *skb)
 }
 
 extern void kfree_skb(struct sk_buff *skb);
+extern void skb_tx_error(struct sk_buff *skb);
 extern void consume_skb(struct sk_buff *skb);
 extern void	       __kfree_skb(struct sk_buff *skb);
 extern struct kmem_cache *skbuff_head_cache;
@@ -643,7 +646,7 @@ extern unsigned int   skb_find_text(struct sk_buff *skb, unsigned int from,
 extern void __skb_get_rxhash(struct sk_buff *skb);
 static inline __u32 skb_get_rxhash(struct sk_buff *skb)
 {
-	if (!skb->rxhash)
+	if (!skb->l4_rxhash)
 		__skb_get_rxhash(skb);
 
 	return skb->rxhash;
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 83d1a14..5d168d7 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -11,6 +11,8 @@
 
 #include <linux/gfp.h>
 #include <linux/types.h>
+#include <linux/workqueue.h>
+
 
 /*
  * Flags to pass to kmem_cache_create().
@@ -116,6 +118,7 @@ struct kmem_cache {
 };
 #endif
 
+struct mem_cgroup;
 /*
  * struct kmem_cache related prototypes
  */
@@ -125,10 +128,12 @@ int slab_is_available(void);
 struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
 			unsigned long,
 			void (*)(void *));
+struct kmem_cache *
+kmem_cache_create_memcg(struct mem_cgroup *, const char *, size_t, size_t,
+			unsigned long, void (*)(void *), struct kmem_cache *);
 void kmem_cache_destroy(struct kmem_cache *);
 int kmem_cache_shrink(struct kmem_cache *);
 void kmem_cache_free(struct kmem_cache *, void *);
-unsigned int kmem_cache_size(struct kmem_cache *);
 
 /*
  * Please use this macro to create slab caches. Simply specify the
@@ -176,6 +181,48 @@ unsigned int kmem_cache_size(struct kmem_cache *);
 #ifndef ARCH_SLAB_MINALIGN
 #define ARCH_SLAB_MINALIGN __alignof__(unsigned long long)
 #endif
+/*
+ * This is the main placeholder for memcg-related information in kmem caches.
+ * struct kmem_cache will hold a pointer to it, so the memory cost while
+ * disabled is 1 pointer. The runtime cost while enabled, gets bigger than it
+ * would otherwise be if that would be bundled in kmem_cache: we'll need an
+ * extra pointer chase. But the trade off clearly lays in favor of not
+ * penalizing non-users.
+ *
+ * Both the root cache and the child caches will have it. For the root cache,
+ * this will hold a dynamically allocated array large enough to hold
+ * information about the currently limited memcgs in the system.
+ *
+ * Child caches will hold extra metadata needed for its operation. Fields are:
+ *
+ * @memcg: pointer to the memcg this cache belongs to
+ * @list: list_head for the list of all caches in this memcg
+ * @root_cache: pointer to the global, root cache, this cache was derived from
+ * @dead: set to true after the memcg dies; the cache may still be around.
+ * @nr_pages: number of pages that belongs to this cache.
+ * @destroy: worker to be called whenever we are ready, or believe we may be
+ *           ready, to destroy this cache.
+ */
+struct memcg_cache_params {
+	bool is_root_cache;
+	union {
+		struct kmem_cache *memcg_caches[0];
+		struct {
+			struct mem_cgroup *memcg;
+			struct list_head list;
+			struct kmem_cache *root_cache;
+			bool dead;
+			atomic_t nr_pages;
+			struct work_struct destroy;
+		};
+	};
+};
+
+int memcg_update_all_caches(int num_memcgs);
+
+struct seq_file;
+int cache_show(struct kmem_cache *s, struct seq_file *m);
+void print_slabinfo_header(struct seq_file *m);
 
 /*
  * Common kmalloc functions provided by all allocators
@@ -388,6 +435,14 @@ static inline void *kzalloc_node(size_t size, gfp_t flags, int node)
 	return kmalloc_node(size, flags | __GFP_ZERO, node);
 }
 
+/*
+ * Determine the size of a slab object
+ */
+static inline unsigned int kmem_cache_size(struct kmem_cache *s)
+{
+	return s->object_size;
+}
+
 void __init kmem_cache_init_late(void);
 
 #endif	/* _LINUX_SLAB_H */
diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h
index cc290f0..b07cc4c 100644
--- a/include/linux/slab_def.h
+++ b/include/linux/slab_def.h
@@ -81,6 +81,9 @@ struct kmem_cache {
 	 */
 	int obj_offset;
 #endif /* CONFIG_DEBUG_SLAB */
+#ifdef CONFIG_MEMCG_KMEM
+	struct memcg_cache_params *memcg_params;
+#endif
 
 /* 6) per-cpu/per-node data, touched during every alloc/free */
 	/*
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index df448ad..9db4825 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -101,6 +101,10 @@ struct kmem_cache {
 #ifdef CONFIG_SYSFS
 	struct kobject kobj;	/* For sysfs */
 #endif
+#ifdef CONFIG_MEMCG_KMEM
+	struct memcg_cache_params *memcg_params;
+	int max_attr_size; /* for propagation, maximum size of a stored attr */
+#endif
 
 #ifdef CONFIG_NUMA
 	/*
@@ -222,7 +226,10 @@ void *__kmalloc(size_t size, gfp_t flags);
 static __always_inline void *
 kmalloc_order(size_t size, gfp_t flags, unsigned int order)
 {
-	void *ret = (void *) __get_free_pages(flags | __GFP_COMP, order);
+	void *ret;
+
+	flags |= (__GFP_COMP | __GFP_KMEMCG);
+	ret = (void *) __get_free_pages(flags, order);
 	kmemleak_alloc(ret, size, 1, flags);
 	return ret;
 }
diff --git a/include/linux/spi/spi-tegra.h b/include/linux/spi/spi-tegra.h
new file mode 100644
index 0000000..786932c
--- /dev/null
+++ b/include/linux/spi/spi-tegra.h
@@ -0,0 +1,40 @@
+/*
+ * spi-tegra.h: SPI interface for Nvidia Tegra20 SLINK controller.
+ *
+ * Copyright (C) 2011 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _LINUX_SPI_TEGRA_H
+#define _LINUX_SPI_TEGRA_H
+
+struct tegra_spi_platform_data {
+	int dma_req_sel;
+	unsigned int spi_max_frequency;
+};
+
+/*
+ * Controller data from device to pass some info like
+ * hw based chip select can be used or not and if yes
+ * then CS hold and setup time.
+ */
+struct tegra_spi_device_controller_data {
+	bool is_hw_based_cs;
+	int cs_setup_clk_count;
+	int cs_hold_clk_count;
+};
+
+#endif /* _LINUX_SPI_TEGRA_H */
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index fa702ae..f629189 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -90,6 +90,7 @@ struct spi_device {
 	void			*controller_state;
 	void			*controller_data;
 	char			modalias[SPI_NAME_SIZE];
+	int			cs_gpio;	/* chip select gpio */
 
 	/*
 	 * likely need more hooks for more protocol options affecting how
@@ -362,6 +363,8 @@ struct spi_master {
 	int (*transfer_one_message)(struct spi_master *master,
 				    struct spi_message *mesg);
 	int (*unprepare_transfer_hardware)(struct spi_master *master);
+	/* gpio chip select */
+	int			*cs_gpios;
 };
 
 static inline void *spi_master_get_devdata(struct spi_master *master)
diff --git a/include/linux/srcu.h b/include/linux/srcu.h
index 55a5c52..6eb691b 100644
--- a/include/linux/srcu.h
+++ b/include/linux/srcu.h
@@ -16,8 +16,10 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
  * Copyright (C) IBM Corporation, 2006
+ * Copyright (C) Fujitsu, 2012
  *
  * Author: Paul McKenney <paulmck@us.ibm.com>
+ *	   Lai Jiangshan <laijs@cn.fujitsu.com>
  *
  * For detailed explanation of Read-Copy Update mechanism see -
  * 		Documentation/RCU/ *.txt
@@ -40,6 +42,8 @@ struct rcu_batch {
 	struct rcu_head *head, **tail;
 };
 
+#define RCU_BATCH_INIT(name) { NULL, &(name.head) }
+
 struct srcu_struct {
 	unsigned completed;
 	struct srcu_struct_array __percpu *per_cpu_ref;
@@ -70,12 +74,42 @@ int __init_srcu_struct(struct srcu_struct *sp, const char *name,
 	__init_srcu_struct((sp), #sp, &__srcu_key); \
 })
 
+#define __SRCU_DEP_MAP_INIT(srcu_name)	.dep_map = { .name = #srcu_name },
 #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
 int init_srcu_struct(struct srcu_struct *sp);
 
+#define __SRCU_DEP_MAP_INIT(srcu_name)
 #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
+void process_srcu(struct work_struct *work);
+
+#define __SRCU_STRUCT_INIT(name)					\
+	{								\
+		.completed = -300,					\
+		.per_cpu_ref = &name##_srcu_array,			\
+		.queue_lock = __SPIN_LOCK_UNLOCKED(name.queue_lock),	\
+		.running = false,					\
+		.batch_queue = RCU_BATCH_INIT(name.batch_queue),	\
+		.batch_check0 = RCU_BATCH_INIT(name.batch_check0),	\
+		.batch_check1 = RCU_BATCH_INIT(name.batch_check1),	\
+		.batch_done = RCU_BATCH_INIT(name.batch_done),		\
+		.work = __DELAYED_WORK_INITIALIZER(name.work, process_srcu, 0),\
+		__SRCU_DEP_MAP_INIT(name)				\
+	}
+
+/*
+ * define and init a srcu struct at build time.
+ * dont't call init_srcu_struct() nor cleanup_srcu_struct() on it.
+ */
+#define DEFINE_SRCU(name)						\
+	static DEFINE_PER_CPU(struct srcu_struct_array, name##_srcu_array);\
+	struct srcu_struct name = __SRCU_STRUCT_INIT(name);
+
+#define DEFINE_STATIC_SRCU(name)					\
+	static DEFINE_PER_CPU(struct srcu_struct_array, name##_srcu_array);\
+	static struct srcu_struct name = __SRCU_STRUCT_INIT(name);
+
 /**
  * call_srcu() - Queue a callback for invocation after an SRCU grace period
  * @sp: srcu_struct in queue the callback
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index bb674c0..3862a5b 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -6,6 +6,7 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/pci.h>
+#include <linux/gpio.h>
 #include <linux/mod_devicetable.h>
 #include <linux/dma-mapping.h>
 
@@ -433,6 +434,9 @@ struct ssb_bus {
 	/* Lock for GPIO register access. */
 	spinlock_t gpio_lock;
 #endif /* EMBEDDED */
+#ifdef CONFIG_SSB_DRIVER_GPIO
+	struct gpio_chip gpio;
+#endif /* DRIVER_GPIO */
 
 	/* Internal-only stuff follows. Do not touch. */
 	struct list_head list;
diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h
index c2b02a5..30b6943 100644
--- a/include/linux/ssb/ssb_driver_chipcommon.h
+++ b/include/linux/ssb/ssb_driver_chipcommon.h
@@ -590,6 +590,7 @@ struct ssb_chipcommon {
 	u32 status;
 	/* Fast Powerup Delay constant */
 	u16 fast_pwrup_delay;
+	spinlock_t gpio_lock;
 	struct ssb_chipcommon_pmu pmu;
 };
 
@@ -644,6 +645,8 @@ u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value);
 u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value);
 u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value);
 u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value);
+u32 ssb_chipco_gpio_pullup(struct ssb_chipcommon *cc, u32 mask, u32 value);
+u32 ssb_chipco_gpio_pulldown(struct ssb_chipcommon *cc, u32 mask, u32 value);
 
 #ifdef CONFIG_SSB_SERIAL
 extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
diff --git a/include/linux/ssb/ssb_driver_extif.h b/include/linux/ssb/ssb_driver_extif.h
index 91161f0..bd23068 100644
--- a/include/linux/ssb/ssb_driver_extif.h
+++ b/include/linux/ssb/ssb_driver_extif.h
@@ -158,6 +158,7 @@
 
 struct ssb_extif {
 	struct ssb_device *dev;
+	spinlock_t gpio_lock;
 };
 
 static inline bool ssb_extif_available(struct ssb_extif *extif)
diff --git a/include/linux/ssb/ssb_driver_mips.h b/include/linux/ssb/ssb_driver_mips.h
index 5f44e97..07a9c7a 100644
--- a/include/linux/ssb/ssb_driver_mips.h
+++ b/include/linux/ssb/ssb_driver_mips.h
@@ -13,6 +13,12 @@ struct ssb_serial_port {
 	unsigned int reg_shift;
 };
 
+struct ssb_pflash {
+	bool present;
+	u8 buswidth;
+	u32 window;
+	u32 window_size;
+};
 
 struct ssb_mipscore {
 	struct ssb_device *dev;
@@ -20,9 +26,7 @@ struct ssb_mipscore {
 	int nr_serial_ports;
 	struct ssb_serial_port serial_ports[4];
 
-	u8 flash_buswidth;
-	u32 flash_window;
-	u32 flash_window_size;
+	struct ssb_pflash pflash;
 };
 
 extern void ssb_mipscore_init(struct ssb_mipscore *mcore);
diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h
index a052501..6ecfa02 100644
--- a/include/linux/ssb/ssb_regs.h
+++ b/include/linux/ssb/ssb_regs.h
@@ -485,7 +485,7 @@
 #define  SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT	4
 #define  SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL	0x0020
 #define  SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT	5
-#define SSB_SPROM8_TEMPDELTA		0x00BA
+#define SSB_SPROM8_TEMPDELTA		0x00BC
 #define  SSB_SPROM8_TEMPDELTA_PHYCAL	0x00ff
 #define  SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT	0
 #define  SSB_SPROM8_TEMPDELTA_PERIOD	0x0f00
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index a1547ea..c1b3ed3 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -61,7 +61,7 @@
 #define STMMAC_CSR_I_16		0xE	/* clk_csr_i/16 */
 #define STMMAC_CSR_I_18		0xF	/* clk_csr_i/18 */
 
-/* AXI DMA Burst length suported */
+/* AXI DMA Burst length supported */
 #define DMA_AXI_BLEN_4		(1 << 1)
 #define DMA_AXI_BLEN_8		(1 << 2)
 #define DMA_AXI_BLEN_16		(1 << 3)
@@ -104,6 +104,7 @@ struct plat_stmmacenet_data {
 	int bugged_jumbo;
 	int pmt;
 	int force_sf_dma_mode;
+	int riwt_off;
 	void (*fix_mac_speed)(void *priv, unsigned int speed);
 	void (*bus_setup)(void __iomem *ioaddr);
 	int (*init)(struct platform_device *pdev);
diff --git a/include/linux/string.h b/include/linux/string.h
index 6301258..ac889c5 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -143,4 +143,15 @@ static inline bool strstarts(const char *str, const char *prefix)
 
 extern size_t memweight(const void *ptr, size_t bytes);
 
+/**
+ * kbasename - return the last part of a pathname.
+ *
+ * @path: path to extract the filename from.
+ */
+static inline const char *kbasename(const char *path)
+{
+	const char *tail = strrchr(path, '/');
+	return tail ? tail + 1 : path;
+}
+
 #endif /* _LINUX_STRING_H_ */
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
index f792794..5dc9ee4 100644
--- a/include/linux/sunrpc/cache.h
+++ b/include/linux/sunrpc/cache.h
@@ -217,6 +217,8 @@ extern int qword_get(char **bpp, char *dest, int bufsize);
 static inline int get_int(char **bpp, int *anint)
 {
 	char buf[50];
+	char *ep;
+	int rv;
 	int len = qword_get(bpp, buf, sizeof(buf));
 
 	if (len < 0)
@@ -224,9 +226,11 @@ static inline int get_int(char **bpp, int *anint)
 	if (len == 0)
 		return -ENOENT;
 
-	if (kstrtoint(buf, 0, anint))
+	rv = simple_strtol(buf, &ep, 0);
+	if (*ep)
 		return -EINVAL;
 
+	*anint = rv;
 	return 0;
 }
 
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 34206b8..d1e4f09 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -70,6 +70,7 @@ struct rpc_clnt {
 #define RPC_MAXVERSION		4
 struct rpc_program {
 	const char *		name;		/* protocol name */
+	const char *		service_name;	/* protocol service name */
 	u32			number;		/* program number */
 	unsigned int		nrvers;		/* number of versions */
 	const struct rpc_version **	version;	/* version array */
diff --git a/include/linux/sunxi_timer.h b/include/linux/sunxi_timer.h
new file mode 100644
index 0000000..b9165bb
--- /dev/null
+++ b/include/linux/sunxi_timer.h
@@ -0,0 +1,24 @@
+/*
+ * 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 __SUNXI_TIMER_H
+#define __SUNXI_TIMER_H
+
+#include <asm/mach/time.h>
+
+extern struct sys_timer sunxi_timer;
+
+#endif
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 8d08b3e..071d62c 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -34,21 +34,25 @@ enum dma_sync_target {
 	SYNC_FOR_CPU = 0,
 	SYNC_FOR_DEVICE = 1,
 };
-extern void *swiotlb_tbl_map_single(struct device *hwdev, dma_addr_t tbl_dma_addr,
-				    phys_addr_t phys, size_t size,
-				    enum dma_data_direction dir);
 
-extern void swiotlb_tbl_unmap_single(struct device *hwdev, char *dma_addr,
+/* define the last possible byte of physical address space as a mapping error */
+#define SWIOTLB_MAP_ERROR (~(phys_addr_t)0x0)
+
+extern phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
+					  dma_addr_t tbl_dma_addr,
+					  phys_addr_t phys, size_t size,
+					  enum dma_data_direction dir);
+
+extern void swiotlb_tbl_unmap_single(struct device *hwdev,
+				     phys_addr_t tlb_addr,
 				     size_t size, enum dma_data_direction dir);
 
-extern void swiotlb_tbl_sync_single(struct device *hwdev, char *dma_addr,
+extern void swiotlb_tbl_sync_single(struct device *hwdev,
+				    phys_addr_t tlb_addr,
 				    size_t size, enum dma_data_direction dir,
 				    enum dma_sync_target target);
 
 /* Accessory functions. */
-extern void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
-			   enum dma_data_direction dir);
-
 extern void
 *swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 			dma_addr_t *dma_handle, gfp_t flags);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 727f0cd..82cbbee 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -833,10 +833,12 @@ int kernel_execve(const char *filename, const char *const argv[], const char *co
 #define kernel_execve(filename, argv, envp) \
 	do_execve(filename, \
 		(const char __user *const __user *)argv, \
-		(const char __user *const __user *)envp, \
-		current_pt_regs())
+		(const char __user *const __user *)envp)
 #endif
 
+asmlinkage long sys_execve(const char __user *filename,
+		const char __user *const __user *argv,
+		const char __user *const __user *envp);
 
 asmlinkage long sys_perf_event_open(
 		struct perf_event_attr __user *attr_uptr,
@@ -868,4 +870,5 @@ asmlinkage long sys_process_vm_writev(pid_t pid,
 
 asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
 			 unsigned long idx1, unsigned long idx2);
+asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags);
 #endif
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index cd844a6..14a8ff2 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -158,8 +158,7 @@ struct ctl_table_root {
 	struct ctl_table_set default_set;
 	struct ctl_table_set *(*lookup)(struct ctl_table_root *root,
 					   struct nsproxy *namespaces);
-	int (*permissions)(struct ctl_table_root *root,
-			struct nsproxy *namespaces, struct ctl_table *table);
+	int (*permissions)(struct ctl_table_header *head, struct ctl_table *table);
 };
 
 /* struct ctl_path describes where in the hierarchy a table is added */
diff --git a/include/linux/tegra-ahb.h b/include/linux/tegra-ahb.h
new file mode 100644
index 0000000..f1cd075
--- /dev/null
+++ b/include/linux/tegra-ahb.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * 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.
+ */
+
+#ifndef __LINUX_AHB_H__
+#define __LINUX_AHB_H__
+
+extern int tegra_ahb_enable_smmu(struct device_node *ahb);
+
+#endif	/* __LINUX_AHB_H__ */
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 91b3481..807f214 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -29,6 +29,26 @@
 #include <linux/device.h>
 #include <linux/workqueue.h>
 
+#define THERMAL_TRIPS_NONE	-1
+#define THERMAL_MAX_TRIPS	12
+#define THERMAL_NAME_LENGTH	20
+
+/* No upper/lower limit requirement */
+#define THERMAL_NO_LIMIT	-1UL
+
+/* Unit conversion macros */
+#define KELVIN_TO_CELSIUS(t)	(long)(((long)t-2732 >= 0) ?	\
+				((long)t-2732+5)/10 : ((long)t-2732-5)/10)
+#define CELSIUS_TO_KELVIN(t)	((t)*10+2732)
+
+/* Adding event notification support elements */
+#define THERMAL_GENL_FAMILY_NAME                "thermal_event"
+#define THERMAL_GENL_VERSION                    0x01
+#define THERMAL_GENL_MCAST_GROUP_NAME           "thermal_mc_group"
+
+/* Default Thermal Governor: Does Linear Throttling */
+#define DEFAULT_THERMAL_GOVERNOR	"step_wise"
+
 struct thermal_zone_device;
 struct thermal_cooling_device;
 
@@ -50,6 +70,30 @@ enum thermal_trend {
 	THERMAL_TREND_DROPPING, /* temperature is dropping */
 };
 
+/* Events supported by Thermal Netlink */
+enum events {
+	THERMAL_AUX0,
+	THERMAL_AUX1,
+	THERMAL_CRITICAL,
+	THERMAL_DEV_FAULT,
+};
+
+/* attributes of thermal_genl_family */
+enum {
+	THERMAL_GENL_ATTR_UNSPEC,
+	THERMAL_GENL_ATTR_EVENT,
+	__THERMAL_GENL_ATTR_MAX,
+};
+#define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1)
+
+/* commands supported by the thermal_genl_family */
+enum {
+	THERMAL_GENL_CMD_UNSPEC,
+	THERMAL_GENL_CMD_EVENT,
+	__THERMAL_GENL_CMD_MAX,
+};
+#define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)
+
 struct thermal_zone_device_ops {
 	int (*bind) (struct thermal_zone_device *,
 		     struct thermal_cooling_device *);
@@ -83,11 +127,6 @@ struct thermal_cooling_device_ops {
 	int (*set_cur_state) (struct thermal_cooling_device *, unsigned long);
 };
 
-#define THERMAL_NO_LIMIT -1UL /* no upper/lower limit requirement */
-
-#define THERMAL_TRIPS_NONE -1
-#define THERMAL_MAX_TRIPS 12
-#define THERMAL_NAME_LENGTH 20
 struct thermal_cooling_device {
 	int id;
 	char type[THERMAL_NAME_LENGTH];
@@ -100,10 +139,6 @@ struct thermal_cooling_device {
 	struct list_head node;
 };
 
-#define KELVIN_TO_CELSIUS(t)	(long)(((long)t-2732 >= 0) ?	\
-				((long)t-2732+5)/10 : ((long)t-2732-5)/10)
-#define CELSIUS_TO_KELVIN(t)	((t)*10+2732)
-
 struct thermal_attr {
 	struct device_attribute attr;
 	char name[THERMAL_NAME_LENGTH];
@@ -125,46 +160,61 @@ struct thermal_zone_device {
 	int passive;
 	unsigned int forced_passive;
 	const struct thermal_zone_device_ops *ops;
+	const struct thermal_zone_params *tzp;
+	struct thermal_governor *governor;
 	struct list_head thermal_instances;
 	struct idr idr;
 	struct mutex lock; /* protect thermal_instances list */
 	struct list_head node;
 	struct delayed_work poll_queue;
 };
-/* Adding event notification support elements */
-#define THERMAL_GENL_FAMILY_NAME                "thermal_event"
-#define THERMAL_GENL_VERSION                    0x01
-#define THERMAL_GENL_MCAST_GROUP_NAME           "thermal_mc_group"
 
-enum events {
-	THERMAL_AUX0,
-	THERMAL_AUX1,
-	THERMAL_CRITICAL,
-	THERMAL_DEV_FAULT,
+/* Structure that holds thermal governor information */
+struct thermal_governor {
+	char name[THERMAL_NAME_LENGTH];
+	int (*throttle)(struct thermal_zone_device *tz, int trip);
+	struct list_head	governor_list;
+	struct module		*owner;
 };
 
-struct thermal_genl_event {
-	u32 orig;
-	enum events event;
+/* Structure that holds binding parameters for a zone */
+struct thermal_bind_params {
+	struct thermal_cooling_device *cdev;
+
+	/*
+	 * This is a measure of 'how effectively these devices can
+	 * cool 'this' thermal zone. The shall be determined by platform
+	 * characterization. This is on a 'percentage' scale.
+	 * See Documentation/thermal/sysfs-api.txt for more information.
+	 */
+	int weight;
+
+	/*
+	 * This is a bit mask that gives the binding relation between this
+	 * thermal zone and cdev, for a particular trip point.
+	 * See Documentation/thermal/sysfs-api.txt for more information.
+	 */
+	int trip_mask;
+	int (*match) (struct thermal_zone_device *tz,
+			struct thermal_cooling_device *cdev);
 };
-/* attributes of thermal_genl_family */
-enum {
-	THERMAL_GENL_ATTR_UNSPEC,
-	THERMAL_GENL_ATTR_EVENT,
-	__THERMAL_GENL_ATTR_MAX,
+
+/* Structure to define Thermal Zone parameters */
+struct thermal_zone_params {
+	char governor_name[THERMAL_NAME_LENGTH];
+	int num_tbps;	/* Number of tbp entries */
+	struct thermal_bind_params *tbp;
 };
-#define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1)
 
-/* commands supported by the thermal_genl_family */
-enum {
-	THERMAL_GENL_CMD_UNSPEC,
-	THERMAL_GENL_CMD_EVENT,
-	__THERMAL_GENL_CMD_MAX,
+struct thermal_genl_event {
+	u32 orig;
+	enum events event;
 };
-#define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)
 
+/* Function declarations */
 struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
-		void *, const struct thermal_zone_device_ops *, int, int);
+		void *, const struct thermal_zone_device_ops *,
+		const struct thermal_zone_params *, int, int);
 void thermal_zone_device_unregister(struct thermal_zone_device *);
 
 int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
@@ -173,10 +223,20 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int,
 				       struct thermal_cooling_device *);
 void thermal_zone_device_update(struct thermal_zone_device *);
+
 struct thermal_cooling_device *thermal_cooling_device_register(char *, void *,
 		const struct thermal_cooling_device_ops *);
 void thermal_cooling_device_unregister(struct thermal_cooling_device *);
 
+int get_tz_trend(struct thermal_zone_device *, int);
+struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
+		struct thermal_cooling_device *, int);
+void thermal_cdev_update(struct thermal_cooling_device *);
+void notify_thermal_framework(struct thermal_zone_device *, int);
+
+int thermal_register_governor(struct thermal_governor *);
+void thermal_unregister_governor(struct thermal_governor *);
+
 #ifdef CONFIG_NET
 extern int thermal_generate_netlink_event(u32 orig, enum events event);
 #else
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index ccc1899..e7e0473 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -61,6 +61,8 @@ extern long do_no_restart_syscall(struct restart_block *parm);
 # define THREADINFO_GFP		(GFP_KERNEL | __GFP_NOTRACK)
 #endif
 
+#define THREADINFO_GFP_ACCOUNTED (THREADINFO_GFP | __GFP_KMEMCG)
+
 /*
  * flag set/clear/test wrappers
  * - pass TIF_xxxx constants to these functions
diff --git a/include/linux/tick.h b/include/linux/tick.h
index f37fceb..1a6567b 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -142,4 +142,10 @@ static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; }
 static inline u64 get_cpu_iowait_time_us(int cpu, u64 *unused) { return -1; }
 # endif /* !NO_HZ */
 
+# ifdef CONFIG_CPU_IDLE_GOV_MENU
+extern void menu_hrtimer_cancel(void);
+# else
+static inline void menu_hrtimer_cancel(void) {}
+# endif /* CONFIG_CPU_IDLE_GOV_MENU */
+
 #endif
diff --git a/include/linux/timecompare.h b/include/linux/timecompare.h
deleted file mode 100644
index 546e223..0000000
--- a/include/linux/timecompare.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Utility code which helps transforming between two different time
- * bases, called "source" and "target" time in this code.
- *
- * Source time has to be provided via the timecounter API while target
- * time is accessed via a function callback whose prototype
- * intentionally matches ktime_get() and ktime_get_real(). These
- * interfaces where chosen like this so that the code serves its
- * initial purpose without additional glue code.
- *
- * This purpose is synchronizing a hardware clock in a NIC with system
- * time, in order to implement the Precision Time Protocol (PTP,
- * IEEE1588) with more accurate hardware assisted time stamping.  In
- * that context only synchronization against system time (=
- * ktime_get_real()) is currently needed. But this utility code might
- * become useful in other situations, which is why it was written as
- * general purpose utility code.
- *
- * The source timecounter is assumed to return monotonically
- * increasing time (but this code does its best to compensate if that
- * is not the case) whereas target time may jump.
- *
- * The target time corresponding to a source time is determined by
- * reading target time, reading source time, reading target time
- * again, then assuming that average target time corresponds to source
- * time. In other words, the assumption is that reading the source
- * time is slow and involves equal time for sending the request and
- * receiving the reply, whereas reading target time is assumed to be
- * fast.
- *
- * Copyright (C) 2009 Intel Corporation.
- * Author: Patrick Ohly <patrick.ohly@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef _LINUX_TIMECOMPARE_H
-#define _LINUX_TIMECOMPARE_H
-
-#include <linux/clocksource.h>
-#include <linux/ktime.h>
-
-/**
- * struct timecompare - stores state and configuration for the two clocks
- *
- * Initialize to zero, then set source/target/num_samples.
- *
- * Transformation between source time and target time is done with:
- * target_time = source_time + offset +
- *               (source_time - last_update) * skew /
- *               TIMECOMPARE_SKEW_RESOLUTION
- *
- * @source:          used to get source time stamps via timecounter_read()
- * @target:          function returning target time (for example, ktime_get
- *                   for monotonic time, or ktime_get_real for wall clock)
- * @num_samples:     number of times that source time and target time are to
- *                   be compared when determining their offset
- * @offset:          (target time - source time) at the time of the last update
- * @skew:            average (target time - source time) / delta source time *
- *                   TIMECOMPARE_SKEW_RESOLUTION
- * @last_update:     last source time stamp when time offset was measured
- */
-struct timecompare {
-	struct timecounter *source;
-	ktime_t (*target)(void);
-	int num_samples;
-
-	s64 offset;
-	s64 skew;
-	u64 last_update;
-};
-
-/**
- * timecompare_transform - transform source time stamp into target time base
- * @sync:            context for time sync
- * @source_tstamp:   the result of timecounter_read() or
- *                   timecounter_cyc2time()
- */
-extern ktime_t timecompare_transform(struct timecompare *sync,
-				     u64 source_tstamp);
-
-/**
- * timecompare_offset - measure current (target time - source time) offset
- * @sync:            context for time sync
- * @offset:          average offset during sample period returned here
- * @source_tstamp:   average source time during sample period returned here
- *
- * Returns number of samples used. Might be zero (= no result) in the
- * unlikely case that target time was monotonically decreasing for all
- * samples (= broken).
- */
-extern int timecompare_offset(struct timecompare *sync,
-			      s64 *offset,
-			      u64 *source_tstamp);
-
-extern void __timecompare_update(struct timecompare *sync,
-				 u64 source_tstamp);
-
-/**
- * timecompare_update - update offset and skew by measuring current offset
- * @sync:            context for time sync
- * @source_tstamp:   the result of timecounter_read() or
- *                   timecounter_cyc2time(), pass zero to force update
- *
- * Updates are only done at most once per second.
- */
-static inline void timecompare_update(struct timecompare *sync,
-				      u64 source_tstamp)
-{
-	if (!source_tstamp ||
-	    (s64)(source_tstamp - sync->last_update) >= NSEC_PER_SEC)
-		__timecompare_update(sync, source_tstamp);
-}
-
-#endif /* _LINUX_TIMECOMPARE_H */
diff --git a/include/linux/trace_clock.h b/include/linux/trace_clock.h
index 4eb4902..d563f37 100644
--- a/include/linux/trace_clock.h
+++ b/include/linux/trace_clock.h
@@ -12,6 +12,8 @@
 #include <linux/compiler.h>
 #include <linux/types.h>
 
+#include <asm/trace_clock.h>
+
 extern u64 notrace trace_clock_local(void);
 extern u64 notrace trace_clock(void);
 extern u64 notrace trace_clock_global(void);
diff --git a/include/linux/tty.h b/include/linux/tty.h
index f0b4eb4..8db1b56 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -188,7 +188,9 @@ struct tty_port_operations {
 };
 	
 struct tty_port {
+	struct tty_bufhead	buf;		/* Locked internally */
 	struct tty_struct	*tty;		/* Back pointer */
+	struct tty_struct	*itty;		/* internal back ptr */
 	const struct tty_port_operations *ops;	/* Port operations */
 	spinlock_t		lock;		/* Lock protecting tty field */
 	int			blocked_open;	/* Waiting to open */
@@ -197,6 +199,9 @@ struct tty_port {
 	wait_queue_head_t	close_wait;	/* Close waiters */
 	wait_queue_head_t	delta_msr_wait;	/* Modem status change */
 	unsigned long		flags;		/* TTY flags ASY_*/
+	unsigned long		iflags;		/* TTYP_ internal flags */
+#define TTYP_FLUSHING			1  /* Flushing to ldisc in progress */
+#define TTYP_FLUSHPENDING		2  /* Queued buffer flush pending */
 	unsigned char		console:1;	/* port is a console */
 	struct mutex		mutex;		/* Locking */
 	struct mutex		buf_mutex;	/* Buffer alloc lock */
@@ -235,6 +240,7 @@ struct tty_struct {
 	struct mutex ldisc_mutex;
 	struct tty_ldisc *ldisc;
 
+	struct mutex atomic_write_lock;
 	struct mutex legacy_mutex;
 	struct mutex termios_mutex;
 	spinlock_t ctrl_lock;
@@ -254,7 +260,6 @@ struct tty_struct {
 
 	struct tty_struct *link;
 	struct fasync_struct *fasync;
-	struct tty_bufhead buf;		/* Locked internally */
 	int alt_speed;		/* For magic substitution of 38400 bps */
 	wait_queue_head_t write_wait;
 	wait_queue_head_t read_wait;
@@ -265,37 +270,10 @@ struct tty_struct {
 
 #define N_TTY_BUF_SIZE 4096
 
-	/*
-	 * The following is data for the N_TTY line discipline.  For
-	 * historical reasons, this is included in the tty structure.
-	 * Mostly locked by the BKL.
-	 */
-	unsigned int column;
-	unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
 	unsigned char closing:1;
-	unsigned char echo_overrun:1;
 	unsigned short minimum_to_wake;
-	unsigned long overrun_time;
-	int num_overrun;
-	unsigned long process_char_map[256/(8*sizeof(unsigned long))];
-	char *read_buf;
-	int read_head;
-	int read_tail;
-	int read_cnt;
-	unsigned long read_flags[N_TTY_BUF_SIZE/(8*sizeof(unsigned long))];
-	unsigned char *echo_buf;
-	unsigned int echo_pos;
-	unsigned int echo_cnt;
-	int canon_data;
-	unsigned long canon_head;
-	unsigned int canon_column;
-	struct mutex atomic_read_lock;
-	struct mutex atomic_write_lock;
-	struct mutex output_lock;
-	struct mutex echo_lock;
 	unsigned char *write_buf;
 	int write_cnt;
-	spinlock_t read_lock;
 	/* If the tty has a pending do_SAK, queue it here - akpm */
 	struct work_struct SAK_work;
 	struct tty_port *port;
@@ -335,8 +313,6 @@ struct tty_file_private {
 #define TTY_PTY_LOCK 		16	/* pty private */
 #define TTY_NO_WRITE_SPLIT 	17	/* Preserve write boundaries to driver */
 #define TTY_HUPPED 		18	/* Post driver->hangup() */
-#define TTY_FLUSHING		19	/* Flushing to ldisc in progress */
-#define TTY_FLUSHPENDING	20	/* Queued buffer flush pending */
 #define TTY_HUPPING 		21	/* ->hangup() in progress */
 
 #define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
@@ -412,9 +388,9 @@ extern void disassociate_ctty(int priv);
 extern void no_tty(void);
 extern void tty_flip_buffer_push(struct tty_struct *tty);
 extern void tty_flush_to_ldisc(struct tty_struct *tty);
-extern void tty_buffer_free_all(struct tty_struct *tty);
+extern void tty_buffer_free_all(struct tty_port *port);
 extern void tty_buffer_flush(struct tty_struct *tty);
-extern void tty_buffer_init(struct tty_struct *tty);
+extern void tty_buffer_init(struct tty_port *port);
 extern speed_t tty_get_baud_rate(struct tty_struct *tty);
 extern speed_t tty_termios_baud_rate(struct ktermios *termios);
 extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);
@@ -479,6 +455,7 @@ extern struct device *tty_port_register_device_attr(struct tty_port *port,
 		const struct attribute_group **attr_grp);
 extern int tty_port_alloc_xmit_buf(struct tty_port *port);
 extern void tty_port_free_xmit_buf(struct tty_port *port);
+extern void tty_port_destroy(struct tty_port *port);
 extern void tty_port_put(struct tty_port *port);
 
 static inline struct tty_port *tty_port_get(struct tty_port *port)
@@ -535,7 +512,7 @@ extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops);
 /* tty_audit.c */
 #ifdef CONFIG_AUDIT
 extern void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
-			       size_t size);
+			       size_t size, unsigned icanon);
 extern void tty_audit_exit(void);
 extern void tty_audit_fork(struct signal_struct *sig);
 extern void tty_audit_tiocsti(struct tty_struct *tty, char ch);
@@ -544,7 +521,7 @@ extern int tty_audit_push_task(struct task_struct *tsk,
 			       kuid_t loginuid, u32 sessionid);
 #else
 static inline void tty_audit_add_data(struct tty_struct *tty,
-				      unsigned char *data, size_t size)
+		unsigned char *data, size_t size, unsigned icanon)
 {
 }
 static inline void tty_audit_tiocsti(struct tty_struct *tty, char ch)
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index 9239d03..2002344 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -11,7 +11,7 @@ void tty_schedule_flip(struct tty_struct *tty);
 static inline int tty_insert_flip_char(struct tty_struct *tty,
 					unsigned char ch, char flag)
 {
-	struct tty_buffer *tb = tty->buf.tail;
+	struct tty_buffer *tb = tty->port->buf.tail;
 	if (tb && tb->used < tb->size) {
 		tb->flag_buf_ptr[tb->used] = flag;
 		tb->char_buf_ptr[tb->used++] = ch;
diff --git a/include/linux/types.h b/include/linux/types.h
index 1cc0e4b..4d118ba 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -156,6 +156,7 @@ typedef u32 dma_addr_t;
 #endif
 typedef unsigned __bitwise__ gfp_t;
 typedef unsigned __bitwise__ fmode_t;
+typedef unsigned __bitwise__ oom_flags_t;
 
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
 typedef u64 phys_addr_t;
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 10278d1..689b14b 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -482,6 +482,7 @@ struct usb3_lpm_parameters {
  * @connect_time: time device was first connected
  * @do_remote_wakeup:  remote wakeup should be enabled
  * @reset_resume: needs reset instead of resume
+ * @port_is_suspended: the upstream port is suspended (L2 or U3)
  * @wusb_dev: if this is a Wireless USB device, link to the WUSB
  *	specific data for the device.
  * @slot_id: Slot ID assigned by xHCI
@@ -560,6 +561,7 @@ struct usb_device {
 
 	unsigned do_remote_wakeup:1;
 	unsigned reset_resume:1;
+	unsigned port_is_suspended:1;
 #endif
 	struct wusb_dev *wusb_dev;
 	int slot_id;
@@ -588,8 +590,9 @@ extern struct usb_device *usb_hub_find_child(struct usb_device *hdev,
  */
 #define usb_hub_for_each_child(hdev, port1, child) \
 	for (port1 = 1,	child =	usb_hub_find_child(hdev, port1); \
-		port1 <= hdev->maxchild; \
-		child = usb_hub_find_child(hdev, ++port1))
+			port1 <= hdev->maxchild; \
+			child = usb_hub_find_child(hdev, ++port1)) \
+		if (!child) continue; else
 
 /* USB device locking */
 #define usb_lock_device(udev)		device_lock(&(udev)->dev)
@@ -805,6 +808,22 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
 	.bcdDevice_hi = (hi)
 
 /**
+ * USB_DEVICE_INTERFACE_CLASS - describe a usb device with a specific interface class
+ * @vend: the 16 bit USB Vendor ID
+ * @prod: the 16 bit USB Product ID
+ * @cl: bInterfaceClass value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific interface class of devices.
+ */
+#define USB_DEVICE_INTERFACE_CLASS(vend, prod, cl) \
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+		       USB_DEVICE_ID_MATCH_INT_CLASS, \
+	.idVendor = (vend), \
+	.idProduct = (prod), \
+	.bInterfaceClass = (cl)
+
+/**
  * USB_DEVICE_INTERFACE_PROTOCOL - describe a usb device with a specific interface protocol
  * @vend: the 16 bit USB Vendor ID
  * @prod: the 16 bit USB Product ID
@@ -1129,8 +1148,8 @@ extern int usb_disabled(void);
  * Note: URB_DIR_IN/OUT is automatically set in usb_submit_urb().
  */
 #define URB_SHORT_NOT_OK	0x0001	/* report short reads as errors */
-#define URB_ISO_ASAP		0x0002	/* iso-only, urb->start_frame
-					 * ignored */
+#define URB_ISO_ASAP		0x0002	/* iso-only; use the first unexpired
+					 * slot in the schedule */
 #define URB_NO_TRANSFER_DMA_MAP	0x0004	/* urb->transfer_dma valid on submit */
 #define URB_NO_FSBR		0x0020	/* UHCI-specific */
 #define URB_ZERO_PACKET		0x0040	/* Finish bulk OUT with short packet */
@@ -1309,15 +1328,20 @@ typedef void (*usb_complete_t)(struct urb *);
  * the transfer interval in the endpoint descriptor is logarithmic.
  * Device drivers must convert that value to linear units themselves.)
  *
- * Isochronous URBs normally use the URB_ISO_ASAP transfer flag, telling
- * the host controller to schedule the transfer as soon as bandwidth
- * utilization allows, and then set start_frame to reflect the actual frame
- * selected during submission.  Otherwise drivers must specify the start_frame
- * and handle the case where the transfer can't begin then.  However, drivers
- * won't know how bandwidth is currently allocated, and while they can
- * find the current frame using usb_get_current_frame_number () they can't
- * know the range for that frame number.  (Ranges for frame counter values
- * are HC-specific, and can go from 256 to 65536 frames from "now".)
+ * If an isochronous endpoint queue isn't already running, the host
+ * controller will schedule a new URB to start as soon as bandwidth
+ * utilization allows.  If the queue is running then a new URB will be
+ * scheduled to start in the first transfer slot following the end of the
+ * preceding URB, if that slot has not already expired.  If the slot has
+ * expired (which can happen when IRQ delivery is delayed for a long time),
+ * the scheduling behavior depends on the URB_ISO_ASAP flag.  If the flag
+ * is clear then the URB will be scheduled to start in the expired slot,
+ * implying that some of its packets will not be transferred; if the flag
+ * is set then the URB will be scheduled in the first unexpired slot,
+ * breaking the queue's synchronization.  Upon URB completion, the
+ * start_frame field will be set to the (micro)frame number in which the
+ * transfer was scheduled.  Ranges for frame counter values are HC-specific
+ * and can go from as low as 256 to as high as 65536 frames.
  *
  * Isochronous URBs have a different data transfer model, in part because
  * the quality of service is only "best effort".  Callers provide specially
diff --git a/include/linux/usb/cdc_ncm.h b/include/linux/usb/cdc_ncm.h
new file mode 100644
index 0000000..3b8f9d4
--- /dev/null
+++ b/include/linux/usb/cdc_ncm.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) ST-Ericsson 2010-2012
+ * Contact: Alexey Orishko <alexey.orishko@stericsson.com>
+ * Original author: Hans Petter Selasky <hans.petter.selasky@stericsson.com>
+ *
+ * USB Host Driver for Network Control Model (NCM)
+ * http://www.usb.org/developers/devclass_docs/NCM10.zip
+ *
+ * The NCM encoding, decoding and initialization logic
+ * derives from FreeBSD 8.x. if_cdce.c and if_cdcereg.h
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose this file to be licensed under the terms
+ * of the GNU General Public License (GPL) Version 2 or the 2-clause
+ * BSD license listed below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define CDC_NCM_COMM_ALTSETTING_NCM		0
+#define CDC_NCM_COMM_ALTSETTING_MBIM		1
+
+#define CDC_NCM_DATA_ALTSETTING_NCM		1
+#define CDC_NCM_DATA_ALTSETTING_MBIM		2
+
+/* CDC NCM subclass 3.2.1 */
+#define USB_CDC_NCM_NDP16_LENGTH_MIN		0x10
+
+/* Maximum NTB length */
+#define	CDC_NCM_NTB_MAX_SIZE_TX			32768	/* bytes */
+#define	CDC_NCM_NTB_MAX_SIZE_RX			32768	/* bytes */
+
+/* Minimum value for MaxDatagramSize, ch. 6.2.9 */
+#define	CDC_NCM_MIN_DATAGRAM_SIZE		1514	/* bytes */
+
+/* Minimum value for MaxDatagramSize, ch. 8.1.3 */
+#define CDC_MBIM_MIN_DATAGRAM_SIZE		2048	/* bytes */
+
+#define	CDC_NCM_MIN_TX_PKT			512	/* bytes */
+
+/* Default value for MaxDatagramSize */
+#define	CDC_NCM_MAX_DATAGRAM_SIZE		8192	/* bytes */
+
+/*
+ * Maximum amount of datagrams in NCM Datagram Pointer Table, not counting
+ * the last NULL entry.
+ */
+#define	CDC_NCM_DPT_DATAGRAMS_MAX		40
+
+/* Restart the timer, if amount of datagrams is less than given value */
+#define	CDC_NCM_RESTART_TIMER_DATAGRAM_CNT	3
+#define	CDC_NCM_TIMER_PENDING_CNT		2
+#define CDC_NCM_TIMER_INTERVAL			(400UL * NSEC_PER_USEC)
+
+/* The following macro defines the minimum header space */
+#define	CDC_NCM_MIN_HDR_SIZE \
+	(sizeof(struct usb_cdc_ncm_nth16) + sizeof(struct usb_cdc_ncm_ndp16) + \
+	(CDC_NCM_DPT_DATAGRAMS_MAX + 1) * sizeof(struct usb_cdc_ncm_dpe16))
+
+#define CDC_NCM_NDP_SIZE \
+	(sizeof(struct usb_cdc_ncm_ndp16) +				\
+	      (CDC_NCM_DPT_DATAGRAMS_MAX + 1) * sizeof(struct usb_cdc_ncm_dpe16))
+
+#define cdc_ncm_comm_intf_is_mbim(x)  ((x)->desc.bInterfaceSubClass == USB_CDC_SUBCLASS_MBIM && \
+				       (x)->desc.bInterfaceProtocol == USB_CDC_PROTO_NONE)
+#define cdc_ncm_data_intf_is_mbim(x)  ((x)->desc.bInterfaceProtocol == USB_CDC_MBIM_PROTO_NTB)
+
+struct cdc_ncm_ctx {
+	struct usb_cdc_ncm_ntb_parameters ncm_parm;
+	struct hrtimer tx_timer;
+	struct tasklet_struct bh;
+
+	const struct usb_cdc_ncm_desc *func_desc;
+	const struct usb_cdc_mbim_desc   *mbim_desc;
+	const struct usb_cdc_header_desc *header_desc;
+	const struct usb_cdc_union_desc *union_desc;
+	const struct usb_cdc_ether_desc *ether_desc;
+
+	struct net_device *netdev;
+	struct usb_device *udev;
+	struct usb_host_endpoint *in_ep;
+	struct usb_host_endpoint *out_ep;
+	struct usb_host_endpoint *status_ep;
+	struct usb_interface *intf;
+	struct usb_interface *control;
+	struct usb_interface *data;
+
+	struct sk_buff *tx_curr_skb;
+	struct sk_buff *tx_rem_skb;
+	__le32 tx_rem_sign;
+
+	spinlock_t mtx;
+	atomic_t stop;
+
+	u32 tx_timer_pending;
+	u32 tx_curr_frame_num;
+	u32 rx_speed;
+	u32 tx_speed;
+	u32 rx_max;
+	u32 tx_max;
+	u32 max_datagram_size;
+	u16 tx_max_datagrams;
+	u16 tx_remainder;
+	u16 tx_modulus;
+	u16 tx_ndp_modulus;
+	u16 tx_seq;
+	u16 rx_seq;
+	u16 connected;
+};
+
+extern int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting);
+extern void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf);
+extern struct sk_buff *cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign);
+extern int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in);
+extern int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset);
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index f8dda06..b09c37e 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -38,6 +38,7 @@
 #include <linux/version.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/log2.h>
 
 /*
  * USB function drivers should return USB_GADGET_DELAYED_STATUS if they
@@ -51,6 +52,7 @@
 /* big enough to hold our biggest descriptor */
 #define USB_COMP_EP0_BUFSIZ	1024
 
+#define USB_MS_TO_HS_INTERVAL(x)	(ilog2((x * 1000 / 125)) + 1)
 struct usb_configuration;
 
 /**
@@ -117,7 +119,7 @@ struct usb_configuration;
 struct usb_function {
 	const char			*name;
 	struct usb_gadget_strings	**strings;
-	struct usb_descriptor_header	**descriptors;
+	struct usb_descriptor_header	**fs_descriptors;
 	struct usb_descriptor_header	**hs_descriptors;
 	struct usb_descriptor_header	**ss_descriptors;
 
diff --git a/include/linux/usb/ehci_pdriver.h b/include/linux/usb/ehci_pdriver.h
index c9d09f8..99238b0 100644
--- a/include/linux/usb/ehci_pdriver.h
+++ b/include/linux/usb/ehci_pdriver.h
@@ -29,6 +29,8 @@
  *			initialization.
  * @port_power_off:	set to 1 if the controller needs to be powered down
  *			after initialization.
+ * @no_io_watchdog:	set to 1 if the controller does not need the I/O
+ *			watchdog to run.
  *
  * These are general configuration options for the EHCI controller. All of
  * these options are activating more or less workarounds for some hardware.
@@ -39,8 +41,7 @@ struct usb_ehci_pdata {
 	unsigned	has_synopsys_hc_bug:1;
 	unsigned	big_endian_desc:1;
 	unsigned	big_endian_mmio:1;
-	unsigned	port_power_on:1;
-	unsigned	port_power_off:1;
+	unsigned	no_io_watchdog:1;
 
 	/* Turn on all power and clocks */
 	int (*power_on)(struct platform_device *pdev);
diff --git a/include/linux/usb/ezusb.h b/include/linux/usb/ezusb.h
index fc618d8..639ee45 100644
--- a/include/linux/usb/ezusb.h
+++ b/include/linux/usb/ezusb.h
@@ -1,16 +1,8 @@
 #ifndef __EZUSB_H
 #define __EZUSB_H
 
-
-extern int ezusb_writememory(struct usb_device *dev, int address,
-			     unsigned char *data, int length, __u8 bRequest);
-
 extern int ezusb_fx1_set_reset(struct usb_device *dev, unsigned char reset_bit);
-extern int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit);
-
 extern int ezusb_fx1_ihex_firmware_download(struct usb_device *dev,
 					    const char *firmware_path);
-extern int ezusb_fx2_ihex_firmware_download(struct usb_device *dev,
-					    const char *firmware_path);
 
 #endif /* __EZUSB_H */
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 5b6e508..0af6569 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -939,6 +939,13 @@ static inline void usb_free_descriptors(struct usb_descriptor_header **v)
 	kfree(v);
 }
 
+struct usb_function;
+int usb_assign_descriptors(struct usb_function *f,
+		struct usb_descriptor_header **fs,
+		struct usb_descriptor_header **hs,
+		struct usb_descriptor_header **ss);
+void usb_free_all_descriptors(struct usb_function *f);
+
 /*-------------------------------------------------------------------------*/
 
 /* utility to simplify map/unmap of usb_requests to/from DMA */
diff --git a/include/linux/usb/ohci_pdriver.h b/include/linux/usb/ohci_pdriver.h
index 74e7755..012f2b7 100644
--- a/include/linux/usb/ohci_pdriver.h
+++ b/include/linux/usb/ohci_pdriver.h
@@ -25,6 +25,7 @@
  * @big_endian_desc:	BE descriptors
  * @big_endian_mmio:	BE registers
  * @no_big_frame_no:	no big endian frame_no shift
+ * @num_ports:		number of ports
  *
  * These are general configuration options for the OHCI controller. All of
  * these options are activating more or less workarounds for some hardware.
@@ -33,6 +34,7 @@ struct usb_ohci_pdata {
 	unsigned	big_endian_desc:1;
 	unsigned	big_endian_mmio:1;
 	unsigned	no_big_frame_no:1;
+	unsigned int	num_ports;
 
 	/* Turn on all power and clocks */
 	int (*power_on)(struct platform_device *pdev);
diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h
index 06b5bae..a29ae1e 100644
--- a/include/linux/usb/phy.h
+++ b/include/linux/usb/phy.h
@@ -10,6 +10,7 @@
 #define __LINUX_USB_PHY_H
 
 #include <linux/notifier.h>
+#include <linux/usb.h>
 
 enum usb_phy_events {
 	USB_EVENT_NONE,         /* no events or cable disconnected */
@@ -99,8 +100,10 @@ struct usb_phy {
 				int suspend);
 
 	/* notify phy connect status change */
-	int	(*notify_connect)(struct usb_phy *x, int port);
-	int	(*notify_disconnect)(struct usb_phy *x, int port);
+	int	(*notify_connect)(struct usb_phy *x,
+			enum usb_device_speed speed);
+	int	(*notify_disconnect)(struct usb_phy *x,
+			enum usb_device_speed speed);
 };
 
 
@@ -189,19 +192,19 @@ usb_phy_set_suspend(struct usb_phy *x, int suspend)
 }
 
 static inline int
-usb_phy_notify_connect(struct usb_phy *x, int port)
+usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed)
 {
 	if (x->notify_connect)
-		return x->notify_connect(x, port);
+		return x->notify_connect(x, speed);
 	else
 		return 0;
 }
 
 static inline int
-usb_phy_notify_disconnect(struct usb_phy *x, int port)
+usb_phy_notify_disconnect(struct usb_phy *x, enum usb_device_speed speed)
 {
 	if (x->notify_disconnect)
-		return x->notify_disconnect(x, port);
+		return x->notify_disconnect(x, speed);
 	else
 		return 0;
 }
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index ddbbb7d..9bbeabf 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -163,6 +163,16 @@ extern int usbnet_resume(struct usb_interface *);
 extern void usbnet_disconnect(struct usb_interface *);
 extern void usbnet_device_suggests_idle(struct usbnet *dev);
 
+extern int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+		    u16 value, u16 index, void *data, u16 size);
+extern int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+		    u16 value, u16 index, const void *data, u16 size);
+extern int usbnet_read_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
+		    u16 value, u16 index, void *data, u16 size);
+extern int usbnet_write_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
+		    u16 value, u16 index, const void *data, u16 size);
+extern int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
+		    u16 value, u16 index, const void *data, u16 size);
 
 /* Drivers that reuse some of the standard USB CDC infrastructure
  * (notably, using multiple interfaces according to the CDC
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 95142ca..b9bd2e6 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -25,6 +25,7 @@ struct user_namespace {
 	struct user_namespace	*parent;
 	kuid_t			owner;
 	kgid_t			group;
+	unsigned int		proc_inum;
 };
 
 extern struct user_namespace init_user_ns;
@@ -39,6 +40,7 @@ static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
 }
 
 extern int create_user_ns(struct cred *new);
+extern int unshare_userns(unsigned long unshare_flags, struct cred **new_cred);
 extern void free_user_ns(struct kref *kref);
 
 static inline void put_user_ns(struct user_namespace *ns)
@@ -66,6 +68,14 @@ static inline int create_user_ns(struct cred *new)
 	return -EINVAL;
 }
 
+static inline int unshare_userns(unsigned long unshare_flags,
+				 struct cred **new_cred)
+{
+	if (unshare_flags & CLONE_NEWUSER)
+		return -EINVAL;
+	return 0;
+}
+
 static inline void put_user_ns(struct user_namespace *ns)
 {
 }
diff --git a/include/linux/utsname.h b/include/linux/utsname.h
index 2b34520..239e277 100644
--- a/include/linux/utsname.h
+++ b/include/linux/utsname.h
@@ -23,6 +23,7 @@ struct uts_namespace {
 	struct kref kref;
 	struct new_utsname name;
 	struct user_namespace *user_ns;
+	unsigned int proc_inum;
 };
 extern struct uts_namespace init_uts_ns;
 
@@ -33,7 +34,7 @@ static inline void get_uts_ns(struct uts_namespace *ns)
 }
 
 extern struct uts_namespace *copy_utsname(unsigned long flags,
-					  struct task_struct *tsk);
+	struct user_namespace *user_ns, struct uts_namespace *old_ns);
 extern void free_uts_ns(struct kref *kref);
 
 static inline void put_uts_ns(struct uts_namespace *ns)
@@ -50,12 +51,12 @@ static inline void put_uts_ns(struct uts_namespace *ns)
 }
 
 static inline struct uts_namespace *copy_utsname(unsigned long flags,
-						 struct task_struct *tsk)
+	struct user_namespace *user_ns, struct uts_namespace *old_ns)
 {
 	if (flags & CLONE_NEWUTS)
 		return ERR_PTR(-EINVAL);
 
-	return tsk->nsproxy->uts_ns;
+	return old_ns;
 }
 #endif
 
diff --git a/include/linux/vexpress.h b/include/linux/vexpress.h
new file mode 100644
index 0000000..c52215f
--- /dev/null
+++ b/include/linux/vexpress.h
@@ -0,0 +1,121 @@
+/*
+ * This program is free software; you can 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#ifndef _LINUX_VEXPRESS_H
+#define _LINUX_VEXPRESS_H
+
+#include <linux/device.h>
+
+#define VEXPRESS_SITE_MB		0
+#define VEXPRESS_SITE_DB1		1
+#define VEXPRESS_SITE_DB2		2
+#define VEXPRESS_SITE_MASTER		0xf
+
+#define VEXPRESS_CONFIG_STATUS_DONE	0
+#define VEXPRESS_CONFIG_STATUS_WAIT	1
+
+#define VEXPRESS_GPIO_MMC_CARDIN	0
+#define VEXPRESS_GPIO_MMC_WPROT		1
+#define VEXPRESS_GPIO_FLASH_WPn		2
+
+#define VEXPRESS_RES_FUNC(_site, _func)	\
+{					\
+	.start = (_site),		\
+	.end = (_func),			\
+	.flags = IORESOURCE_BUS,	\
+}
+
+/* Config bridge API */
+
+/**
+ * struct vexpress_config_bridge_info - description of the platform
+ * configuration infrastructure bridge.
+ *
+ * @name:	Bridge name
+ *
+ * @func_get:	Obtains pointer to a configuration function for a given
+ *		device or a Device Tree node, to be used with @func_put
+ *		and @func_exec. The node pointer should take precedence
+ *		over device pointer when both are passed.
+ *
+ * @func_put:	Tells the bridge that the function will not be used any
+ *		more, so all allocated resources can be released.
+ *
+ * @func_exec:	Executes a configuration function read or write operation.
+ *		The offset selects a 32 bit word of the value accessed.
+ *		Must return VEXPRESS_CONFIG_STATUS_DONE when operation
+ *		is finished immediately, VEXPRESS_CONFIG_STATUS_WAIT when
+ *		will be completed in some time or negative value in case
+ *		of error.
+ */
+struct vexpress_config_bridge_info {
+	const char *name;
+	void *(*func_get)(struct device *dev, struct device_node *node);
+	void (*func_put)(void *func);
+	int (*func_exec)(void *func, int offset, bool write, u32 *data);
+};
+
+struct vexpress_config_bridge;
+
+struct vexpress_config_bridge *vexpress_config_bridge_register(
+		struct device_node *node,
+		struct vexpress_config_bridge_info *info);
+void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge);
+
+void vexpress_config_complete(struct vexpress_config_bridge *bridge,
+		int status);
+
+/* Config function API */
+
+struct vexpress_config_func;
+
+struct vexpress_config_func *__vexpress_config_func_get(struct device *dev,
+		struct device_node *node);
+#define vexpress_config_func_get_by_dev(dev) \
+		__vexpress_config_func_get(dev, NULL)
+#define vexpress_config_func_get_by_node(node) \
+		__vexpress_config_func_get(NULL, node)
+void vexpress_config_func_put(struct vexpress_config_func *func);
+
+/* Both may sleep! */
+int vexpress_config_read(struct vexpress_config_func *func, int offset,
+		u32 *data);
+int vexpress_config_write(struct vexpress_config_func *func, int offset,
+		u32 data);
+
+/* Platform control */
+
+u32 vexpress_get_procid(int site);
+u32 vexpress_get_hbi(int site);
+void *vexpress_get_24mhz_clock_base(void);
+void vexpress_flags_set(u32 data);
+
+#define vexpress_get_site_by_node(node) __vexpress_get_site(NULL, node)
+#define vexpress_get_site_by_dev(dev) __vexpress_get_site(dev, NULL)
+unsigned __vexpress_get_site(struct device *dev, struct device_node *node);
+
+void vexpress_sysreg_early_init(void __iomem *base);
+void vexpress_sysreg_of_early_init(void);
+
+void vexpress_power_off(void);
+void vexpress_restart(char str, const char *cmd);
+
+/* Clocks */
+
+struct clk *vexpress_osc_setup(struct device *dev);
+void vexpress_osc_of_setup(struct device_node *node);
+
+void vexpress_clk_init(void __iomem *sp810_base);
+void vexpress_clk_of_init(void);
+
+#endif
diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h
index 0ee42d9..2c02f3a 100644
--- a/include/linux/vgaarb.h
+++ b/include/linux/vgaarb.h
@@ -78,7 +78,7 @@ extern void vga_set_legacy_decoding(struct pci_dev *pdev,
  *     This function acquires VGA resources for the given
  *     card and mark those resources locked. If the resource requested
  *     are "normal" (and not legacy) resources, the arbiter will first check
- *     wether the card is doing legacy decoding for that type of resource. If
+ *     whether the card is doing legacy decoding for that type of resource. If
  *     yes, the lock is "converted" into a legacy resource lock.
  *     The arbiter will first look for all VGA cards that might conflict
  *     and disable their IOs and/or Memory access, including VGA forwarding
@@ -89,7 +89,7 @@ extern void vga_set_legacy_decoding(struct pci_dev *pdev,
  *     This function will block if some conflicting card is already locking
  *     one of the required resources (or any resource on a different bus
  *     segment, since P2P bridges don't differenciate VGA memory and IO
- *     afaik). You can indicate wether this blocking should be interruptible
+ *     afaik). You can indicate whether this blocking should be interruptible
  *     by a signal (for userland interface) or not.
  *     Must not be called at interrupt time or in atomic context.
  *     If the card already owns the resources, the function succeeds.
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 533b115..25fa1a6 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -16,12 +16,20 @@
  * @name: the name of this virtqueue (mainly for debugging)
  * @vdev: the virtio device this queue was created for.
  * @priv: a pointer for the virtqueue implementation to use.
+ * @index: the zero-based ordinal number for this queue.
+ * @num_free: number of elements we expect to be able to fit.
+ *
+ * A note on @num_free: with indirect buffers, each buffer needs one
+ * element in the queue, otherwise a buffer will need one element per
+ * sg element.
  */
 struct virtqueue {
 	struct list_head list;
 	void (*callback)(struct virtqueue *vq);
 	const char *name;
 	struct virtio_device *vdev;
+	unsigned int index;
+	unsigned int num_free;
 	void *priv;
 };
 
@@ -50,8 +58,6 @@ void *virtqueue_detach_unused_buf(struct virtqueue *vq);
 
 unsigned int virtqueue_get_vring_size(struct virtqueue *vq);
 
-int virtqueue_get_queue_index(struct virtqueue *vq);
-
 /**
  * virtio_device - representation of a device using virtio
  * @index: unique position on the virtio bus
diff --git a/include/linux/virtio_scsi.h b/include/linux/virtio_scsi.h
index d6b4440..4195b97 100644
--- a/include/linux/virtio_scsi.h
+++ b/include/linux/virtio_scsi.h
@@ -1,7 +1,31 @@
+/*
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
 #ifndef _LINUX_VIRTIO_SCSI_H
 #define _LINUX_VIRTIO_SCSI_H
-/* This header is BSD licensed so anyone can use the definitions to implement
- * compatible drivers/servers. */
 
 #define VIRTIO_SCSI_CDB_SIZE   32
 #define VIRTIO_SCSI_SENSE_SIZE 96
diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h
index 3d31145..4278e6c 100644
--- a/include/linux/vm_event_item.h
+++ b/include/linux/vm_event_item.h
@@ -41,7 +41,12 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
 #ifdef CONFIG_COMPACTION
 		COMPACTBLOCKS, COMPACTPAGES, COMPACTPAGEFAILED,
 		COMPACTSTALL, COMPACTFAIL, COMPACTSUCCESS,
-#endif
+#ifdef CONFIG_BALLOON_COMPACTION
+		COMPACTBALLOONISOLATED, /* isolated from balloon pagelist */
+		COMPACTBALLOONMIGRATED, /* balloon page sucessfully migrated */
+		COMPACTBALLOONRETURNED, /* putback to pagelist, not-migrated */
+#endif /* CONFIG_BALLOON_COMPACTION */
+#endif /* CONFIG_COMPACTION */
 #ifdef CONFIG_HUGETLB_PAGE
 		HTLB_BUDDY_PGALLOC, HTLB_BUDDY_PGALLOC_FAIL,
 #endif
@@ -58,6 +63,8 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
 		THP_COLLAPSE_ALLOC,
 		THP_COLLAPSE_ALLOC_FAILED,
 		THP_SPLIT,
+		THP_ZERO_PAGE_ALLOC,
+		THP_ZERO_PAGE_ALLOC_FAILED,
 #endif
 		NR_VM_EVENT_ITEMS
 };
diff --git a/include/linux/vtime.h b/include/linux/vtime.h
new file mode 100644
index 0000000..0c2a2d3
--- /dev/null
+++ b/include/linux/vtime.h
@@ -0,0 +1,47 @@
+#ifndef _LINUX_KERNEL_VTIME_H
+#define _LINUX_KERNEL_VTIME_H
+
+struct task_struct;
+
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+extern void vtime_task_switch(struct task_struct *prev);
+extern void __vtime_account_system(struct task_struct *tsk);
+extern void vtime_account_system(struct task_struct *tsk);
+extern void __vtime_account_idle(struct task_struct *tsk);
+extern void vtime_account(struct task_struct *tsk);
+#else
+static inline void vtime_task_switch(struct task_struct *prev) { }
+static inline void __vtime_account_system(struct task_struct *tsk) { }
+static inline void vtime_account_system(struct task_struct *tsk) { }
+static inline void vtime_account(struct task_struct *tsk) { }
+#endif
+
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
+extern void irqtime_account_irq(struct task_struct *tsk);
+#else
+static inline void irqtime_account_irq(struct task_struct *tsk) { }
+#endif
+
+static inline void vtime_account_irq_enter(struct task_struct *tsk)
+{
+	/*
+	 * Hardirq can interrupt idle task anytime. So we need vtime_account()
+	 * that performs the idle check in CONFIG_VIRT_CPU_ACCOUNTING.
+	 * Softirq can also interrupt idle task directly if it calls
+	 * local_bh_enable(). Such case probably don't exist but we never know.
+	 * Ksoftirqd is not concerned because idle time is flushed on context
+	 * switch. Softirqs in the end of hardirqs are also not a problem because
+	 * the idle time is flushed on hardirq time already.
+	 */
+	vtime_account(tsk);
+	irqtime_account_irq(tsk);
+}
+
+static inline void vtime_account_irq_exit(struct task_struct *tsk)
+{
+	/* On hard|softirq exit we always account to hard|softirq cputime */
+	__vtime_account_system(tsk);
+	irqtime_account_irq(tsk);
+}
+
+#endif /* _LINUX_KERNEL_VTIME_H */
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 168dfe1..62ee600 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -550,6 +550,172 @@ do {									\
 	__ret;								\
 })
 
+
+#define __wait_event_lock_irq(wq, condition, lock, cmd)			\
+do {									\
+	DEFINE_WAIT(__wait);						\
+									\
+	cmd;								\
+	for (;;) {							\
+		prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);	\
+		if (condition)						\
+			break;						\
+		spin_unlock_irq(&lock);					\
+		schedule();						\
+		cmd;							\
+		spin_lock_irq(&lock);					\
+	}								\
+	finish_wait(&wq, &__wait);					\
+} while (0)
+
+/**
+ * wait_event_lock_irq_cmd - sleep until a condition gets true. 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()
+ *	  and cmd reacquired afterwards.
+ * @cmd: a command which is invoked outside the critical section before
+ *	 sleep
+ *
+ * The process is put to sleep (TASK_UNINTERRUPTIBLE) until the
+ * @condition evaluates to true. The @condition is checked each time
+ * the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ *
+ * This is supposed to be called while holding the lock. The lock is
+ * dropped before going to sleep and invoking the cmd and is reacquired
+ * afterwards.
+ */
+#define wait_event_lock_irq_cmd(wq, condition, lock, cmd)		\
+do {									\
+	if (condition)							\
+		break;							\
+	__wait_event_lock_irq(wq, condition, lock, cmd);		\
+} while (0)
+
+/**
+ * wait_event_lock_irq - sleep until a condition gets true. 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()
+ *	  and reacquired afterwards.
+ *
+ * The process is put to sleep (TASK_UNINTERRUPTIBLE) until the
+ * @condition evaluates to true. The @condition is checked each time
+ * the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ *
+ * This is supposed to be called while holding the lock. The lock is
+ * dropped before going to sleep and is reacquired afterwards.
+ */
+#define wait_event_lock_irq(wq, condition, lock)			\
+do {									\
+	if (condition)							\
+		break;							\
+	__wait_event_lock_irq(wq, condition, lock, );			\
+} while (0)
+
+
+#define __wait_event_interruptible_lock_irq(wq, condition,		\
+					    lock, ret, cmd)		\
+do {									\
+	DEFINE_WAIT(__wait);						\
+									\
+	cmd;								\
+	for (;;) {							\
+		prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);	\
+		if (condition)						\
+			break;						\
+		if (signal_pending(current)) {				\
+			ret = -ERESTARTSYS;				\
+			break;						\
+		}							\
+		spin_unlock_irq(&lock);					\
+		schedule();						\
+		cmd;							\
+		spin_lock_irq(&lock);					\
+	}								\
+	finish_wait(&wq, &__wait);					\
+} while (0)
+
+/**
+ * wait_event_interruptible_lock_irq_cmd - sleep until a condition gets true.
+ *		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()
+ *	  and cmd reacquired afterwards.
+ * @cmd: a command which is invoked outside the critical section before
+ *	 sleep
+ *
+ * The process is put to sleep (TASK_INTERRUPTIBLE) until the
+ * @condition evaluates to true or a signal is received. The @condition is
+ * checked each time the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ *
+ * This is supposed to be called while holding the lock. The lock is
+ * dropped before going to sleep and invoking the cmd and is reacquired
+ * afterwards.
+ *
+ * The macro will return -ERESTARTSYS if it was interrupted by a signal
+ * and 0 if @condition evaluated to true.
+ */
+#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 - sleep until a condition gets true.
+ *		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()
+ *	  and reacquired afterwards.
+ *
+ * The process is put to sleep (TASK_INTERRUPTIBLE) until the
+ * @condition evaluates to true or signal is received. The @condition is
+ * checked each time the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ *
+ * This is supposed to be called while holding the lock. The lock is
+ * dropped before going to sleep and is reacquired afterwards.
+ *
+ * The macro will return -ERESTARTSYS if it was interrupted by a signal
+ * and 0 if @condition evaluated to true.
+ */
+#define wait_event_interruptible_lock_irq(wq, condition, lock)		\
+({									\
+	int __ret = 0;							\
+									\
+	if (!(condition))						\
+		__wait_event_interruptible_lock_irq(wq, condition,	\
+						    lock, __ret, );	\
+	__ret;								\
+})
+
+
 /*
  * These are the old interfaces to sleep waiting for an event.
  * They are racy.  DO NOT use them, use the wait_event* interfaces above.
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index b7f45d4..87490ac 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -105,7 +105,7 @@ struct watchdog_device {
 #define WATCHDOG_NOWAYOUT_INIT_STATUS	0
 #endif
 
-/* Use the following function to check wether or not the watchdog is active */
+/* Use the following function to check whether or not the watchdog is active */
 static inline bool watchdog_active(struct watchdog_device *wdd)
 {
 	return test_bit(WDOG_ACTIVE, &wdd->status);
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 50c3e8f..b82a83a 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -161,14 +161,7 @@ void __bdi_update_bandwidth(struct backing_dev_info *bdi,
 			    unsigned long start_time);
 
 void page_writeback_init(void);
-void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
-					unsigned long nr_pages_dirtied);
-
-static inline void
-balance_dirty_pages_ratelimited(struct address_space *mapping)
-{
-	balance_dirty_pages_ratelimited_nr(mapping, 1);
-}
+void balance_dirty_pages_ratelimited(struct address_space *mapping);
 
 typedef int (*writepage_t)(struct page *page, struct writeback_control *wbc,
 				void *data);
diff --git a/include/media/adp1653.h b/include/media/adp1653.h
index 50a1af8..1d9b48a 100644
--- a/include/media/adp1653.h
+++ b/include/media/adp1653.h
@@ -3,10 +3,10 @@
  *
  * Copyright (C) 2008--2011 Nokia Corporation
  *
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * Contributors:
- *	Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *	Sakari Ailus <sakari.ailus@iki.fi>
  *	Tuukka Toivonen <tuukkat76@gmail.com>
  *
  * This program is free software; you can redistribute it and/or
diff --git a/include/media/adv7604.h b/include/media/adv7604.h
index 171b957..dc004bc 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -40,14 +40,6 @@ enum adv7604_op_ch_sel {
 	ADV7604_OP_CH_SEL_RBG = 5,
 };
 
-/* Primary mode (IO register 0x01, [3:0]) */
-enum adv7604_prim_mode {
-	ADV7604_PRIM_MODE_COMP = 1,
-	ADV7604_PRIM_MODE_RGB = 2,
-	ADV7604_PRIM_MODE_HDMI_COMP = 5,
-	ADV7604_PRIM_MODE_HDMI_GR = 6,
-};
-
 /* Input Color Space (IO register 0x02, [7:4]) */
 enum adv7604_inp_color_space {
 	ADV7604_INP_COLOR_SPACE_LIM_RGB = 0,
@@ -103,9 +95,6 @@ struct adv7604_platform_data {
 	/* Bus rotation and reordering */
 	enum adv7604_op_ch_sel op_ch_sel;
 
-	/* Primary mode */
-	enum adv7604_prim_mode prim_mode;
-
 	/* Select output format */
 	enum adv7604_op_format_sel op_format_sel;
 
@@ -142,6 +131,16 @@ struct adv7604_platform_data {
 	u8 i2c_vdp;
 };
 
+/*
+ * Mode of operation.
+ * This is used as the input argument of the s_routing video op.
+ */
+enum adv7604_mode {
+	ADV7604_MODE_COMP,
+	ADV7604_MODE_GR,
+	ADV7604_MODE_HDMI,
+};
+
 #define V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE	(V4L2_CID_DV_CLASS_BASE + 0x1000)
 #define V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL	(V4L2_CID_DV_CLASS_BASE + 0x1001)
 #define V4L2_CID_ADV_RX_FREE_RUN_COLOR		(V4L2_CID_DV_CLASS_BASE + 0x1002)
diff --git a/include/media/davinci/vpbe_display.h b/include/media/davinci/vpbe_display.h
index dbf6b37..8dffffe 100644
--- a/include/media/davinci/vpbe_display.h
+++ b/include/media/davinci/vpbe_display.h
@@ -16,7 +16,7 @@
 /* Header files */
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
-#include <media/videobuf-dma-contig.h>
+#include <media/videobuf2-dma-contig.h>
 #include <media/davinci/vpbe_types.h>
 #include <media/davinci/vpbe_osd.h>
 #include <media/davinci/vpbe.h>
@@ -62,6 +62,11 @@ struct display_layer_info {
 	enum osd_v_exp_ratio v_exp;
 };
 
+struct vpbe_disp_buffer {
+	struct vb2_buffer vb;
+	struct list_head list;
+};
+
 /* vpbe display object structure */
 struct vpbe_layer {
 	/* number of buffers in fbuffers */
@@ -69,13 +74,15 @@ struct vpbe_layer {
 	/* Pointer to the vpbe_display */
 	struct vpbe_display *disp_dev;
 	/* Pointer pointing to current v4l2_buffer */
-	struct videobuf_buffer *cur_frm;
+	struct vpbe_disp_buffer *cur_frm;
 	/* Pointer pointing to next v4l2_buffer */
-	struct videobuf_buffer *next_frm;
+	struct vpbe_disp_buffer *next_frm;
 	/* videobuf specific parameters
 	 * Buffer queue used in video-buf
 	 */
-	struct videobuf_queue buffer_queue;
+	struct vb2_queue buffer_queue;
+	/* allocator-specific contexts for each plane */
+	struct vb2_alloc_ctx *alloc_ctx;
 	/* Queue of filled frames */
 	struct list_head dma_queue;
 	/* Used in video-buf */
diff --git a/include/media/davinci/vpbe_osd.h b/include/media/davinci/vpbe_osd.h
index d7e397a..5ab0d8d 100644
--- a/include/media/davinci/vpbe_osd.h
+++ b/include/media/davinci/vpbe_osd.h
@@ -357,7 +357,7 @@ struct osd_state {
 	spinlock_t lock;
 	struct device *dev;
 	dma_addr_t osd_base_phys;
-	unsigned long osd_base;
+	void __iomem *osd_base;
 	unsigned long osd_size;
 	/* 1-->the isr will toggle the VID0 ping-pong buffer */
 	int pingpong;
diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h
index 768aa77..e221bc7 100644
--- a/include/media/ir-kbd-i2c.h
+++ b/include/media/ir-kbd-i2c.h
@@ -37,7 +37,7 @@ enum ir_kbd_get_key_fn {
 struct IR_i2c_init_data {
 	char			*ir_codes;
 	const char		*name;
-	u64			type; /* RC_TYPE_RC5, etc */
+	u64			type; /* RC_BIT_RC5, etc */
 	u32			polling_interval; /* 0 means DEFAULT_POLLING_INTERVAL */
 
 	/*
diff --git a/include/media/mt9v022.h b/include/media/mt9v022.h
new file mode 100644
index 0000000..4056180
--- /dev/null
+++ b/include/media/mt9v022.h
@@ -0,0 +1,16 @@
+/*
+ * mt9v022 sensor
+ *
+ * This program is free software; you can 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 __MT9V022_H__
+#define __MT9V022_H__
+
+struct mt9v022_platform_data {
+	unsigned short y_skip_top;	/* Lines to skip at the top */
+};
+
+#endif
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index b0c494a..f03445f 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -50,7 +50,7 @@ enum rc_driver_type {
  * @input_dev: the input child device used to communicate events to userspace
  * @driver_type: specifies if protocol decoding is done in hardware or software
  * @idle: used to keep track of RX state
- * @allowed_protos: bitmask with the supported RC_TYPE_* protocols
+ * @allowed_protos: bitmask with the supported RC_BIT_* protocols
  * @scanmask: some hardware decoders are not capable of providing the full
  *	scancode to the application. As this is a hardware limit, we can't do
  *	anything with it. Yet, as the same keycode table can be used with other
@@ -113,7 +113,7 @@ struct rc_dev {
 	u32				max_timeout;
 	u32				rx_resolution;
 	u32				tx_resolution;
-	int				(*change_protocol)(struct rc_dev *dev, u64 rc_type);
+	int				(*change_protocol)(struct rc_dev *dev, u64 *rc_type);
 	int				(*open)(struct rc_dev *dev);
 	void				(*close)(struct rc_dev *dev);
 	int				(*s_tx_mask)(struct rc_dev *dev, u32 mask);
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index cfd5163..74f55a3 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -11,22 +11,54 @@
 
 #include <linux/input.h>
 
-#define RC_TYPE_UNKNOWN	0
-#define RC_TYPE_RC5	(1  << 0)	/* Philips RC5 protocol */
-#define RC_TYPE_NEC	(1  << 1)
-#define RC_TYPE_RC6	(1  << 2)	/* Philips RC6 protocol */
-#define RC_TYPE_JVC	(1  << 3)	/* JVC protocol */
-#define RC_TYPE_SONY	(1  << 4)	/* Sony12/15/20 protocol */
-#define RC_TYPE_RC5_SZ	(1  << 5)	/* RC5 variant used by Streamzap */
-#define RC_TYPE_SANYO   (1  << 6)	/* Sanyo protocol */
-#define RC_TYPE_MCE_KBD	(1  << 29)	/* RC6-ish MCE keyboard/mouse */
-#define RC_TYPE_LIRC	(1  << 30)	/* Pass raw IR to lirc userspace */
-#define RC_TYPE_OTHER	(1u << 31)
+enum rc_type {
+	RC_TYPE_UNKNOWN		= 0,	/* Protocol not known */
+	RC_TYPE_OTHER		= 1,	/* Protocol known but proprietary */
+	RC_TYPE_LIRC		= 2,	/* Pass raw IR to lirc userspace */
+	RC_TYPE_RC5		= 3,	/* Philips RC5 protocol */
+	RC_TYPE_RC5X		= 4,	/* Philips RC5x protocol */
+	RC_TYPE_RC5_SZ		= 5,	/* StreamZap variant of RC5 */
+	RC_TYPE_JVC		= 6,	/* JVC protocol */
+	RC_TYPE_SONY12		= 7,	/* Sony 12 bit protocol */
+	RC_TYPE_SONY15		= 8,	/* Sony 15 bit protocol */
+	RC_TYPE_SONY20		= 9,	/* Sony 20 bit protocol */
+	RC_TYPE_NEC		= 10,	/* NEC protocol */
+	RC_TYPE_SANYO		= 11,	/* Sanyo protocol */
+	RC_TYPE_MCE_KBD		= 12,	/* RC6-ish MCE keyboard/mouse */
+	RC_TYPE_RC6_0		= 13,	/* Philips RC6-0-16 protocol */
+	RC_TYPE_RC6_6A_20	= 14,	/* Philips RC6-6A-20 protocol */
+	RC_TYPE_RC6_6A_24	= 15,	/* Philips RC6-6A-24 protocol */
+	RC_TYPE_RC6_6A_32	= 16,	/* Philips RC6-6A-32 protocol */
+	RC_TYPE_RC6_MCE		= 17,	/* MCE (Philips RC6-6A-32 subtype) protocol */
+};
+
+#define RC_BIT_NONE		0
+#define RC_BIT_UNKNOWN		(1 << RC_TYPE_UNKNOWN)
+#define RC_BIT_OTHER		(1 << RC_TYPE_OTHER)
+#define RC_BIT_LIRC		(1 << RC_TYPE_LIRC)
+#define RC_BIT_RC5		(1 << RC_TYPE_RC5)
+#define RC_BIT_RC5X		(1 << RC_TYPE_RC5X)
+#define RC_BIT_RC5_SZ		(1 << RC_TYPE_RC5_SZ)
+#define RC_BIT_JVC		(1 << RC_TYPE_JVC)
+#define RC_BIT_SONY12		(1 << RC_TYPE_SONY12)
+#define RC_BIT_SONY15		(1 << RC_TYPE_SONY15)
+#define RC_BIT_SONY20		(1 << RC_TYPE_SONY20)
+#define RC_BIT_NEC		(1 << RC_TYPE_NEC)
+#define RC_BIT_SANYO		(1 << RC_TYPE_SANYO)
+#define RC_BIT_MCE_KBD		(1 << RC_TYPE_MCE_KBD)
+#define RC_BIT_RC6_0		(1 << RC_TYPE_RC6_0)
+#define RC_BIT_RC6_6A_20	(1 << RC_TYPE_RC6_6A_20)
+#define RC_BIT_RC6_6A_24	(1 << RC_TYPE_RC6_6A_24)
+#define RC_BIT_RC6_6A_32	(1 << RC_TYPE_RC6_6A_32)
+#define RC_BIT_RC6_MCE		(1 << RC_TYPE_RC6_MCE)
 
-#define RC_TYPE_ALL (RC_TYPE_RC5    | RC_TYPE_NEC   | RC_TYPE_RC6     | \
-		     RC_TYPE_JVC    | RC_TYPE_SONY  | RC_TYPE_LIRC    | \
-		     RC_TYPE_RC5_SZ | RC_TYPE_SANYO | RC_TYPE_MCE_KBD | \
-		     RC_TYPE_OTHER)
+#define RC_BIT_ALL	(RC_BIT_UNKNOWN | RC_BIT_OTHER | RC_BIT_LIRC | \
+			 RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ | \
+			 RC_BIT_JVC | \
+			 RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20 | \
+			 RC_BIT_NEC | RC_BIT_SANYO | RC_BIT_MCE_KBD | \
+			 RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 | \
+			 RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE)
 
 struct rc_map_table {
 	u32	scancode;
@@ -38,7 +70,7 @@ struct rc_map {
 	unsigned int		size;	/* Max number of entries */
 	unsigned int		len;	/* Used number of entries */
 	unsigned int		alloc;	/* Size of *scan in bytes */
-	u64			rc_type;
+	enum rc_type		rc_type;
 	const char		*name;
 	spinlock_t		lock;
 };
diff --git a/include/media/smiapp.h b/include/media/smiapp.h
index 9ab07fd..07f96a8 100644
--- a/include/media/smiapp.h
+++ b/include/media/smiapp.h
@@ -4,7 +4,7 @@
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
  * Copyright (C) 2011--2012 Nokia Corporation
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --git a/include/media/v4l2-event.h b/include/media/v4l2-event.h
index e7c5d17..eff85f9 100644
--- a/include/media/v4l2-event.h
+++ b/include/media/v4l2-event.h
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2009--2010 Nokia Corporation.
  *
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --git a/include/media/v4l2-fh.h b/include/media/v4l2-fh.h
index 52513c2..a62ee18 100644
--- a/include/media/v4l2-fh.h
+++ b/include/media/v4l2-fh.h
@@ -6,7 +6,7 @@
  *
  * Copyright (C) 2009--2010 Nokia Corporation.
  *
- * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ * Contact: Sakari Ailus <sakari.ailus@iki.fi>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index e48b571..4118ad1 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -111,6 +111,8 @@ struct v4l2_ioctl_ops {
 	int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
 	int (*vidioc_querybuf)(struct file *file, void *fh, struct v4l2_buffer *b);
 	int (*vidioc_qbuf)    (struct file *file, void *fh, struct v4l2_buffer *b);
+	int (*vidioc_expbuf)  (struct file *file, void *fh,
+				struct v4l2_exportbuffer *e);
 	int (*vidioc_dqbuf)   (struct file *file, void *fh, struct v4l2_buffer *b);
 
 	int (*vidioc_create_bufs)(struct file *file, void *fh, struct v4l2_create_buffers *b);
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index 131cc4a..7e82d2b 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -111,6 +111,9 @@ int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 		   struct v4l2_buffer *buf);
 
+int v4l2_m2m_expbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+		   struct v4l2_exportbuffer *eb);
+
 int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 		      enum v4l2_buf_type type);
 int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index e04252a..9cfd4ee 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -16,6 +16,7 @@
 #include <linux/mutex.h>
 #include <linux/poll.h>
 #include <linux/videodev2.h>
+#include <linux/dma-buf.h>
 
 struct vb2_alloc_ctx;
 struct vb2_fileio_data;
@@ -41,6 +42,24 @@ struct vb2_fileio_data;
  *		 argument to other ops in this structure
  * @put_userptr: inform the allocator that a USERPTR buffer will no longer
  *		 be used
+ * @attach_dmabuf: attach a shared struct dma_buf for a hardware operation;
+ *		   used for DMABUF memory types; alloc_ctx is the alloc context
+ *		   dbuf is the shared dma_buf; returns NULL on failure;
+ *		   allocator private per-buffer structure on success;
+ *		   this needs to be used for further accesses to the buffer
+ * @detach_dmabuf: inform the exporter of the buffer that the current DMABUF
+ *		   buffer is no longer used; the buf_priv argument is the
+ *		   allocator private per-buffer structure previously returned
+ *		   from the attach_dmabuf callback
+ * @map_dmabuf: request for access to the dmabuf from allocator; the allocator
+ *		of dmabuf is informed that this driver is going to use the
+ *		dmabuf
+ * @unmap_dmabuf: releases access control to the dmabuf - allocator is notified
+ *		  that this driver is done using the dmabuf for now
+ * @prepare:	called every time the buffer is passed from userspace to the
+ *		driver, useful for cache synchronisation, optional
+ * @finish:	called every time the buffer is passed back from the driver
+ *		to the userspace, also optional
  * @vaddr:	return a kernel virtual address to a given memory buffer
  *		associated with the passed private structure or NULL if no
  *		such mapping exists
@@ -56,15 +75,27 @@ struct vb2_fileio_data;
  * Required ops for USERPTR types: get_userptr, put_userptr.
  * Required ops for MMAP types: alloc, put, num_users, mmap.
  * Required ops for read/write access types: alloc, put, num_users, vaddr
+ * Required ops for DMABUF types: attach_dmabuf, detach_dmabuf, map_dmabuf,
+ *				  unmap_dmabuf.
  */
 struct vb2_mem_ops {
 	void		*(*alloc)(void *alloc_ctx, unsigned long size);
 	void		(*put)(void *buf_priv);
+	struct dma_buf *(*get_dmabuf)(void *buf_priv);
 
 	void		*(*get_userptr)(void *alloc_ctx, unsigned long vaddr,
 					unsigned long size, int write);
 	void		(*put_userptr)(void *buf_priv);
 
+	void		(*prepare)(void *buf_priv);
+	void		(*finish)(void *buf_priv);
+
+	void		*(*attach_dmabuf)(void *alloc_ctx, struct dma_buf *dbuf,
+				unsigned long size, int write);
+	void		(*detach_dmabuf)(void *buf_priv);
+	int		(*map_dmabuf)(void *buf_priv);
+	void		(*unmap_dmabuf)(void *buf_priv);
+
 	void		*(*vaddr)(void *buf_priv);
 	void		*(*cookie)(void *buf_priv);
 
@@ -75,6 +106,8 @@ struct vb2_mem_ops {
 
 struct vb2_plane {
 	void			*mem_priv;
+	struct dma_buf		*dbuf;
+	unsigned int		dbuf_mapped;
 };
 
 /**
@@ -83,12 +116,14 @@ struct vb2_plane {
  * @VB2_USERPTR:	driver supports USERPTR with streaming API
  * @VB2_READ:		driver supports read() style access
  * @VB2_WRITE:		driver supports write() style access
+ * @VB2_DMABUF:		driver supports DMABUF with streaming API
  */
 enum vb2_io_modes {
 	VB2_MMAP	= (1 << 0),
 	VB2_USERPTR	= (1 << 1),
 	VB2_READ	= (1 << 2),
 	VB2_WRITE	= (1 << 3),
+	VB2_DMABUF	= (1 << 4),
 };
 
 /**
@@ -329,6 +364,7 @@ int __must_check vb2_queue_init(struct vb2_queue *q);
 void vb2_queue_release(struct vb2_queue *q);
 
 int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
+int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
 int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
 
 int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
@@ -438,6 +474,8 @@ int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
 int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
 int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
 int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
+int vb2_ioctl_expbuf(struct file *file, void *priv,
+	struct v4l2_exportbuffer *p);
 
 /* struct v4l2_file_operations helpers */
 
diff --git a/include/media/videobuf2-memops.h b/include/media/videobuf2-memops.h
index 84e1f6c..f05444c 100644
--- a/include/media/videobuf2-memops.h
+++ b/include/media/videobuf2-memops.h
@@ -33,11 +33,6 @@ extern const struct vm_operations_struct vb2_common_vm_ops;
 int vb2_get_contig_userptr(unsigned long vaddr, unsigned long size,
 			   struct vm_area_struct **res_vma, dma_addr_t *res_pa);
 
-int vb2_mmap_pfn_range(struct vm_area_struct *vma, unsigned long paddr,
-				unsigned long size,
-				const struct vm_operations_struct *vm_ops,
-				void *priv);
-
 struct vm_area_struct *vb2_get_vma(struct vm_area_struct *vma);
 void vb2_put_vma(struct vm_area_struct *vma);
 
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index b5f8988..0a996a3 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -53,7 +53,6 @@ struct unix_sock {
 	struct path		path;
 	struct mutex		readlock;
 	struct sock		*peer;
-	struct sock		*other;
 	struct list_head	link;
 	atomic_long_t		inflight;
 	spinlock_t		lock;
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
index 6a76e0a..42f2176 100644
--- a/include/net/bluetooth/a2mp.h
+++ b/include/net/bluetooth/a2mp.h
@@ -19,13 +19,25 @@
 
 #define A2MP_FEAT_EXT	0x8000
 
+enum amp_mgr_state {
+	READ_LOC_AMP_INFO,
+	READ_LOC_AMP_ASSOC,
+	READ_LOC_AMP_ASSOC_FINAL,
+};
+
 struct amp_mgr {
+	struct list_head	list;
 	struct l2cap_conn	*l2cap_conn;
 	struct l2cap_chan	*a2mp_chan;
+	struct l2cap_chan	*bredr_chan;
 	struct kref		kref;
 	__u8			ident;
 	__u8			handle;
+	enum amp_mgr_state	state;
 	unsigned long		flags;
+
+	struct list_head	amp_ctrls;
+	struct mutex		amp_ctrls_lock;
 };
 
 struct a2mp_cmd {
@@ -118,9 +130,19 @@ struct a2mp_physlink_rsp {
 #define A2MP_STATUS_PHYS_LINK_EXISTS		0x05
 #define A2MP_STATUS_SECURITY_VIOLATION		0x06
 
-void amp_mgr_get(struct amp_mgr *mgr);
+extern struct list_head amp_mgr_list;
+extern struct mutex amp_mgr_list_lock;
+
+struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr);
 int amp_mgr_put(struct amp_mgr *mgr);
+u8 __next_ident(struct amp_mgr *mgr);
 struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
 				       struct sk_buff *skb);
+struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
+void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
+void a2mp_discover_amp(struct l2cap_chan *chan);
+void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
+void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status);
+void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status);
 
 #endif /* __A2MP_H */
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
new file mode 100644
index 0000000..7ea3db7
--- /dev/null
+++ b/include/net/bluetooth/amp.h
@@ -0,0 +1,54 @@
+/*
+   Copyright (c) 2011,2012 Intel Corp.
+
+   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 __AMP_H
+#define __AMP_H
+
+struct amp_ctrl {
+	struct list_head	list;
+	struct kref		kref;
+	__u8			id;
+	__u16			assoc_len_so_far;
+	__u16			assoc_rem_len;
+	__u16			assoc_len;
+	__u8			*assoc;
+};
+
+int amp_ctrl_put(struct amp_ctrl *ctrl);
+void amp_ctrl_get(struct amp_ctrl *ctrl);
+struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id);
+struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id);
+void amp_ctrl_list_flush(struct amp_mgr *mgr);
+
+struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
+			     u8 remote_id, bool out);
+
+int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type);
+
+void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
+void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
+void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
+void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
+				   struct hci_conn *hcon);
+void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+			struct hci_conn *hcon);
+void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+			struct hci_conn *hcon);
+void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle);
+void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle);
+void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon);
+void amp_create_logical_link(struct l2cap_chan *chan);
+void amp_disconnect_logical_link(struct hci_chan *hchan);
+void amp_destroy_logical_link(struct hci_chan *hchan, u8 reason);
+
+#endif /* __AMP_H */
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index ede0369..2554b3f 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -180,7 +180,6 @@ static inline void bacpy(bdaddr_t *dst, bdaddr_t *src)
 }
 
 void baswap(bdaddr_t *dst, bdaddr_t *src);
-char *batostr(bdaddr_t *ba);
 
 /* Common socket structures and functions */
 
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 76b2b6b..45eee08 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -33,6 +33,8 @@
 #define HCI_LINK_KEY_SIZE	16
 #define HCI_AMP_LINK_KEY_SIZE	(2 * HCI_LINK_KEY_SIZE)
 
+#define HCI_MAX_AMP_ASSOC_SIZE	672
+
 /* HCI dev events */
 #define HCI_DEV_REG			1
 #define HCI_DEV_UNREG			2
@@ -113,6 +115,7 @@ enum {
 	HCI_SSP_ENABLED,
 	HCI_HS_ENABLED,
 	HCI_LE_ENABLED,
+	HCI_LE_PERIPHERAL,
 	HCI_CONNECTABLE,
 	HCI_DISCOVERABLE,
 	HCI_LINK_SECURITY,
@@ -151,7 +154,7 @@ enum {
 #define HCI_DISCONN_TIMEOUT	msecs_to_jiffies(2000)	/* 2 seconds */
 #define HCI_PAIRING_TIMEOUT	msecs_to_jiffies(60000)	/* 60 seconds */
 #define HCI_INIT_TIMEOUT	msecs_to_jiffies(10000)	/* 10 seconds */
-#define HCI_CMD_TIMEOUT		msecs_to_jiffies(1000)	/* 1 second */
+#define HCI_CMD_TIMEOUT		msecs_to_jiffies(2000)	/* 2 seconds */
 #define HCI_ACL_TX_TIMEOUT	msecs_to_jiffies(45000)	/* 45 seconds */
 #define HCI_AUTO_OFF_TIMEOUT	msecs_to_jiffies(2000)	/* 2 seconds */
 
@@ -196,6 +199,7 @@ enum {
 #define ACL_START_NO_FLUSH	0x00
 #define ACL_CONT		0x01
 #define ACL_START		0x02
+#define ACL_COMPLETE		0x03
 #define ACL_ACTIVE_BCAST	0x04
 #define ACL_PICO_BCAST		0x08
 
@@ -205,6 +209,7 @@ enum {
 #define ESCO_LINK	0x02
 /* Low Energy links do not have defined link type. Use invented one */
 #define LE_LINK		0x80
+#define AMP_LINK	0x81
 
 /* LMP features */
 #define LMP_3SLOT	0x01
@@ -314,6 +319,9 @@ enum {
 #define HCI_FLOW_CTL_MODE_PACKET_BASED	0x00
 #define HCI_FLOW_CTL_MODE_BLOCK_BASED	0x01
 
+/* The core spec defines 127 as the "not available" value */
+#define HCI_TX_POWER_INVALID	127
+
 /* Extended Inquiry Response field types */
 #define EIR_FLAGS		0x01 /* flags */
 #define EIR_UUID16_SOME		0x02 /* 16-bit UUID, more available */
@@ -330,6 +338,13 @@ enum {
 #define EIR_SSP_RAND_R		0x0F /* Simple Pairing Randomizer R */
 #define EIR_DEVICE_ID		0x10 /* device ID */
 
+/* Low Energy Advertising Flags */
+#define LE_AD_LIMITED		0x01 /* Limited Discoverable */
+#define LE_AD_GENERAL		0x02 /* General Discoverable */
+#define LE_AD_NO_BREDR		0x04 /* BR/EDR not supported */
+#define LE_AD_SIM_LE_BREDR_CTRL	0x08 /* Simultaneous LE & BR/EDR Controller */
+#define LE_AD_SIM_LE_BREDR_HOST	0x10 /* Simultaneous LE & BR/EDR Host */
+
 /* -----  HCI Commands ---- */
 #define HCI_OP_NOP			0x0000
 
@@ -556,12 +571,46 @@ struct hci_cp_accept_phy_link {
 	__u8     key[HCI_AMP_LINK_KEY_SIZE];
 } __packed;
 
-#define HCI_OP_DISCONN_PHY_LINK	0x0437
+#define HCI_OP_DISCONN_PHY_LINK		0x0437
 struct hci_cp_disconn_phy_link {
 	__u8     phy_handle;
 	__u8     reason;
 } __packed;
 
+struct ext_flow_spec {
+	__u8       id;
+	__u8       stype;
+	__le16     msdu;
+	__le32     sdu_itime;
+	__le32     acc_lat;
+	__le32     flush_to;
+} __packed;
+
+#define HCI_OP_CREATE_LOGICAL_LINK	0x0438
+#define HCI_OP_ACCEPT_LOGICAL_LINK	0x0439
+struct hci_cp_create_accept_logical_link {
+	__u8                  phy_handle;
+	struct ext_flow_spec  tx_flow_spec;
+	struct ext_flow_spec  rx_flow_spec;
+} __packed;
+
+#define HCI_OP_DISCONN_LOGICAL_LINK	0x043a
+struct hci_cp_disconn_logical_link {
+	__le16   log_handle;
+} __packed;
+
+#define HCI_OP_LOGICAL_LINK_CANCEL	0x043b
+struct hci_cp_logical_link_cancel {
+	__u8     phy_handle;
+	__u8     flow_spec_id;
+} __packed;
+
+struct hci_rp_logical_link_cancel {
+	__u8     status;
+	__u8     phy_handle;
+	__u8     flow_spec_id;
+} __packed;
+
 #define HCI_OP_SNIFF_MODE		0x0803
 struct hci_cp_sniff_mode {
 	__le16   handle;
@@ -894,6 +943,22 @@ struct hci_rp_le_read_buffer_size {
 	__u8     le_max_pkt;
 } __packed;
 
+#define HCI_OP_LE_READ_ADV_TX_POWER	0x2007
+struct hci_rp_le_read_adv_tx_power {
+	__u8	status;
+	__s8	tx_power;
+} __packed;
+
+#define HCI_MAX_AD_LENGTH		31
+
+#define HCI_OP_LE_SET_ADV_DATA		0x2008
+struct hci_cp_le_set_adv_data {
+	__u8	length;
+	__u8	data[HCI_MAX_AD_LENGTH];
+} __packed;
+
+#define HCI_OP_LE_SET_ADV_ENABLE	0x200a
+
 #define HCI_OP_LE_SET_SCAN_PARAM	0x200b
 struct hci_cp_le_set_scan_param {
 	__u8    type;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index e7d4546..2f2b743 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -73,6 +73,7 @@ struct discovery_state {
 struct hci_conn_hash {
 	struct list_head list;
 	unsigned int     acl_num;
+	unsigned int     amp_num;
 	unsigned int     sco_num;
 	unsigned int     le_num;
 };
@@ -124,6 +125,14 @@ struct le_scan_params {
 
 #define HCI_MAX_SHORT_NAME_LENGTH	10
 
+struct amp_assoc {
+	__u16	len;
+	__u16	offset;
+	__u16	rem_len;
+	__u16	len_so_far;
+	__u8	data[HCI_MAX_AMP_ASSOC_SIZE];
+};
+
 #define NUM_REASSEMBLY 4
 struct hci_dev {
 	struct list_head list;
@@ -177,6 +186,8 @@ struct hci_dev {
 	__u32		amp_max_flush_to;
 	__u32		amp_be_flush_to;
 
+	struct amp_assoc	loc_assoc;
+
 	__u8		flow_ctl_mode;
 
 	unsigned int	auto_accept_delay;
@@ -252,8 +263,6 @@ struct hci_dev {
 
 	struct sk_buff_head	driver_init;
 
-	void			*core_data;
-
 	atomic_t		promisc;
 
 	struct dentry		*debugfs;
@@ -269,6 +278,10 @@ struct hci_dev {
 	struct work_struct	le_scan;
 	struct le_scan_params	le_scan_params;
 
+	__s8			adv_tx_power;
+	__u8			adv_data[HCI_MAX_AD_LENGTH];
+	__u8			adv_data_len;
+
 	int (*open)(struct hci_dev *hdev);
 	int (*close)(struct hci_dev *hdev);
 	int (*flush)(struct hci_dev *hdev);
@@ -277,6 +290,8 @@ struct hci_dev {
 	int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
 };
 
+#define HCI_PHY_HANDLE(handle)	(handle & 0xff)
+
 struct hci_conn {
 	struct list_head list;
 
@@ -310,6 +325,7 @@ struct hci_conn {
 
 	__u8		remote_cap;
 	__u8		remote_auth;
+	__u8		remote_id;
 	bool		flush_key;
 
 	unsigned int	sent;
@@ -339,10 +355,11 @@ struct hci_conn {
 
 struct hci_chan {
 	struct list_head list;
-
+	__u16 handle;
 	struct hci_conn *conn;
 	struct sk_buff_head data_q;
 	unsigned int	sent;
+	__u8		state;
 };
 
 extern struct list_head hci_dev_list;
@@ -359,7 +376,7 @@ extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
 extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb,
 			      u16 flags);
 
-extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
+extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags);
 extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status);
 extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
 extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
@@ -438,6 +455,9 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
 	case ACL_LINK:
 		h->acl_num++;
 		break;
+	case AMP_LINK:
+		h->amp_num++;
+		break;
 	case LE_LINK:
 		h->le_num++;
 		break;
@@ -459,6 +479,9 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
 	case ACL_LINK:
 		h->acl_num--;
 		break;
+	case AMP_LINK:
+		h->amp_num--;
+		break;
 	case LE_LINK:
 		h->le_num--;
 		break;
@@ -475,6 +498,8 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type)
 	switch (type) {
 	case ACL_LINK:
 		return h->acl_num;
+	case AMP_LINK:
+		return h->amp_num;
 	case LE_LINK:
 		return h->le_num;
 	case SCO_LINK:
@@ -552,10 +577,12 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
 int hci_conn_del(struct hci_conn *conn);
 void hci_conn_hash_flush(struct hci_dev *hdev);
 void hci_conn_check_pending(struct hci_dev *hdev);
+void hci_conn_accept(struct hci_conn *conn, int mask);
 
 struct hci_chan *hci_chan_create(struct hci_conn *conn);
 void hci_chan_del(struct hci_chan *chan);
 void hci_chan_list_flush(struct hci_conn *conn);
+struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle);
 
 struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
 			     __u8 dst_type, __u8 sec_level, __u8 auth_type);
@@ -584,7 +611,10 @@ static inline void hci_conn_put(struct hci_conn *conn)
 
 	if (atomic_dec_and_test(&conn->refcnt)) {
 		unsigned long timeo;
-		if (conn->type == ACL_LINK || conn->type == LE_LINK) {
+
+		switch (conn->type) {
+		case ACL_LINK:
+		case LE_LINK:
 			del_timer(&conn->idle_timer);
 			if (conn->state == BT_CONNECTED) {
 				timeo = conn->disc_timeout;
@@ -593,12 +623,20 @@ static inline void hci_conn_put(struct hci_conn *conn)
 			} else {
 				timeo = msecs_to_jiffies(10);
 			}
-		} else {
+			break;
+
+		case AMP_LINK:
+			timeo = conn->disc_timeout;
+			break;
+
+		default:
 			timeo = msecs_to_jiffies(10);
+			break;
 		}
+
 		cancel_delayed_work(&conn->disc_work);
 		queue_delayed_work(conn->hdev->workqueue,
-					&conn->disc_work, timeo);
+				   &conn->disc_work, timeo);
 	}
 }
 
@@ -650,7 +688,7 @@ static inline uint8_t __hci_num_ctrl(void)
 }
 
 struct hci_dev *hci_dev_get(int index);
-struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst);
+struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src);
 
 struct hci_dev *hci_alloc_dev(void);
 void hci_free_dev(struct hci_dev *hdev);
@@ -699,6 +737,8 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
 								u8 *randomizer);
 int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
+int hci_update_ad(struct hci_dev *hdev);
+
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
 
 int hci_recv_frame(struct sk_buff *skb);
@@ -715,22 +755,35 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev))
 
 /* ----- LMP capabilities ----- */
-#define lmp_rswitch_capable(dev)   ((dev)->features[0] & LMP_RSWITCH)
 #define lmp_encrypt_capable(dev)   ((dev)->features[0] & LMP_ENCRYPT)
+#define lmp_rswitch_capable(dev)   ((dev)->features[0] & LMP_RSWITCH)
+#define lmp_hold_capable(dev)      ((dev)->features[0] & LMP_HOLD)
 #define lmp_sniff_capable(dev)     ((dev)->features[0] & LMP_SNIFF)
-#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
+#define lmp_park_capable(dev)      ((dev)->features[1] & LMP_PARK)
+#define lmp_inq_rssi_capable(dev)  ((dev)->features[3] & LMP_RSSI_INQ)
 #define lmp_esco_capable(dev)      ((dev)->features[3] & LMP_ESCO)
+#define lmp_bredr_capable(dev)     (!((dev)->features[4] & LMP_NO_BREDR))
+#define lmp_le_capable(dev)        ((dev)->features[4] & LMP_LE)
+#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
+#define lmp_pause_enc_capable(dev) ((dev)->features[5] & LMP_PAUSE_ENC)
+#define lmp_ext_inq_capable(dev)   ((dev)->features[6] & LMP_EXT_INQ)
+#define lmp_le_br_capable(dev)     !!((dev)->features[6] & LMP_SIMUL_LE_BR)
 #define lmp_ssp_capable(dev)       ((dev)->features[6] & LMP_SIMPLE_PAIR)
 #define lmp_no_flush_capable(dev)  ((dev)->features[6] & LMP_NO_FLUSH)
-#define lmp_le_capable(dev)        ((dev)->features[4] & LMP_LE)
-#define lmp_bredr_capable(dev)     (!((dev)->features[4] & LMP_NO_BREDR))
+#define lmp_lsto_capable(dev)      ((dev)->features[7] & LMP_LSTO)
+#define lmp_inq_tx_pwr_capable(dev) ((dev)->features[7] & LMP_INQ_TX_PWR)
+#define lmp_ext_feat_capable(dev)  ((dev)->features[7] & LMP_EXTFEATURES)
 
 /* ----- Extended LMP capabilities ----- */
-#define lmp_host_le_capable(dev)   ((dev)->host_features[0] & LMP_HOST_LE)
+#define lmp_host_ssp_capable(dev)  ((dev)->host_features[0] & LMP_HOST_SSP)
+#define lmp_host_le_capable(dev)   !!((dev)->host_features[0] & LMP_HOST_LE)
+#define lmp_host_le_br_capable(dev) !!((dev)->host_features[0] & LMP_HOST_LE_BREDR)
 
 /* ----- HCI protocols ----- */
+#define HCI_PROTO_DEFER             0x01
+
 static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
-								__u8 type)
+					__u8 type, __u8 *flags)
 {
 	switch (type) {
 	case ACL_LINK:
@@ -738,7 +791,7 @@ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
 
 	case SCO_LINK:
 	case ESCO_LINK:
-		return sco_connect_ind(hdev, bdaddr);
+		return sco_connect_ind(hdev, bdaddr, flags);
 
 	default:
 		BT_ERR("unknown link type %d", type);
@@ -789,6 +842,10 @@ static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
 		sco_disconn_cfm(conn, reason);
 		break;
 
+	/* L2CAP would be handled for BREDR chan */
+	case AMP_LINK:
+		break;
+
 	default:
 		BT_ERR("unknown link type %d", conn->type);
 		break;
@@ -841,7 +898,7 @@ struct hci_cb {
 
 static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
 {
-	struct list_head *p;
+	struct hci_cb *cb;
 	__u8 encrypt;
 
 	hci_proto_auth_cfm(conn, status);
@@ -852,8 +909,7 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
 	encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
 
 	read_lock(&hci_cb_list_lock);
-	list_for_each(p, &hci_cb_list) {
-		struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+	list_for_each_entry(cb, &hci_cb_list, list) {
 		if (cb->security_cfm)
 			cb->security_cfm(conn, status, encrypt);
 	}
@@ -863,7 +919,7 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
 static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
 								__u8 encrypt)
 {
-	struct list_head *p;
+	struct hci_cb *cb;
 
 	if (conn->sec_level == BT_SECURITY_SDP)
 		conn->sec_level = BT_SECURITY_LOW;
@@ -874,8 +930,7 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
 	hci_proto_encrypt_cfm(conn, status, encrypt);
 
 	read_lock(&hci_cb_list_lock);
-	list_for_each(p, &hci_cb_list) {
-		struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+	list_for_each_entry(cb, &hci_cb_list, list) {
 		if (cb->security_cfm)
 			cb->security_cfm(conn, status, encrypt);
 	}
@@ -884,11 +939,10 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
 
 static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
 {
-	struct list_head *p;
+	struct hci_cb *cb;
 
 	read_lock(&hci_cb_list_lock);
-	list_for_each(p, &hci_cb_list) {
-		struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+	list_for_each_entry(cb, &hci_cb_list, list) {
 		if (cb->key_change_cfm)
 			cb->key_change_cfm(conn, status);
 	}
@@ -898,11 +952,10 @@ static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
 static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
 								__u8 role)
 {
-	struct list_head *p;
+	struct hci_cb *cb;
 
 	read_lock(&hci_cb_list_lock);
-	list_for_each(p, &hci_cb_list) {
-		struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+	list_for_each_entry(cb, &hci_cb_list, list) {
 		if (cb->role_switch_cfm)
 			cb->role_switch_cfm(conn, status, role);
 	}
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 7ed8e35..f57fab0 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -32,13 +32,14 @@
 /* L2CAP defaults */
 #define L2CAP_DEFAULT_MTU		672
 #define L2CAP_DEFAULT_MIN_MTU		48
-#define L2CAP_DEFAULT_FLUSH_TO		0xffff
+#define L2CAP_DEFAULT_FLUSH_TO		0xFFFF
+#define L2CAP_EFS_DEFAULT_FLUSH_TO	0xFFFFFFFF
 #define L2CAP_DEFAULT_TX_WINDOW		63
 #define L2CAP_DEFAULT_EXT_WINDOW	0x3FFF
 #define L2CAP_DEFAULT_MAX_TX		3
 #define L2CAP_DEFAULT_RETRANS_TO	2000    /* 2 seconds */
 #define L2CAP_DEFAULT_MONITOR_TO	12000   /* 12 seconds */
-#define L2CAP_DEFAULT_MAX_PDU_SIZE	1009    /* Sized for 3-DH5 packet */
+#define L2CAP_DEFAULT_MAX_PDU_SIZE	1492    /* Sized for AMP packet */
 #define L2CAP_DEFAULT_ACK_TO		200
 #define L2CAP_DEFAULT_MAX_SDU_SIZE	0xFFFF
 #define L2CAP_DEFAULT_SDU_ITIME		0xFFFFFFFF
@@ -51,6 +52,8 @@
 #define L2CAP_ENC_TIMEOUT		msecs_to_jiffies(5000)
 #define L2CAP_CONN_TIMEOUT		msecs_to_jiffies(40000)
 #define L2CAP_INFO_TIMEOUT		msecs_to_jiffies(4000)
+#define L2CAP_MOVE_TIMEOUT		msecs_to_jiffies(4000)
+#define L2CAP_MOVE_ERTX_TIMEOUT		msecs_to_jiffies(60000)
 
 #define L2CAP_A2MP_DEFAULT_MTU		670
 
@@ -433,6 +436,8 @@ struct l2cap_chan {
 	struct sock *sk;
 
 	struct l2cap_conn	*conn;
+	struct hci_conn		*hs_hcon;
+	struct hci_chan		*hs_hchan;
 	struct kref	kref;
 
 	__u8		state;
@@ -476,6 +481,12 @@ struct l2cap_chan {
 	unsigned long	conn_state;
 	unsigned long	flags;
 
+	__u8		remote_amp_id;
+	__u8		local_amp_id;
+	__u8		move_id;
+	__u8		move_state;
+	__u8		move_role;
+
 	__u16		next_tx_seq;
 	__u16		expected_ack_seq;
 	__u16		expected_tx_seq;
@@ -538,6 +549,7 @@ struct l2cap_ops {
 	void			(*state_change) (struct l2cap_chan *chan,
 						 int state);
 	void			(*ready) (struct l2cap_chan *chan);
+	void			(*defer) (struct l2cap_chan *chan);
 	struct sk_buff		*(*alloc_skb) (struct l2cap_chan *chan,
 					       unsigned long len, int nb);
 };
@@ -640,6 +652,9 @@ enum {
 enum {
 	L2CAP_RX_STATE_RECV,
 	L2CAP_RX_STATE_SREJ_SENT,
+	L2CAP_RX_STATE_MOVE,
+	L2CAP_RX_STATE_WAIT_P,
+	L2CAP_RX_STATE_WAIT_F,
 };
 
 enum {
@@ -670,6 +685,25 @@ enum {
 	L2CAP_EV_RECV_FRAME,
 };
 
+enum {
+	L2CAP_MOVE_ROLE_NONE,
+	L2CAP_MOVE_ROLE_INITIATOR,
+	L2CAP_MOVE_ROLE_RESPONDER,
+};
+
+enum {
+	L2CAP_MOVE_STABLE,
+	L2CAP_MOVE_WAIT_REQ,
+	L2CAP_MOVE_WAIT_RSP,
+	L2CAP_MOVE_WAIT_RSP_SUCCESS,
+	L2CAP_MOVE_WAIT_CONFIRM,
+	L2CAP_MOVE_WAIT_CONFIRM_RSP,
+	L2CAP_MOVE_WAIT_LOGICAL_COMP,
+	L2CAP_MOVE_WAIT_LOGICAL_CFM,
+	L2CAP_MOVE_WAIT_LOCAL_BUSY,
+	L2CAP_MOVE_WAIT_PREPARE,
+};
+
 void l2cap_chan_hold(struct l2cap_chan *c);
 void l2cap_chan_put(struct l2cap_chan *c);
 
@@ -745,6 +779,10 @@ static inline void l2cap_chan_no_ready(struct l2cap_chan *chan)
 {
 }
 
+static inline void l2cap_chan_no_defer(struct l2cap_chan *chan)
+{
+}
+
 extern bool disable_ertm;
 
 int l2cap_init_sockets(void);
@@ -767,6 +805,12 @@ int l2cap_chan_check_security(struct l2cap_chan *chan);
 void l2cap_chan_set_defaults(struct l2cap_chan *chan);
 int l2cap_ertm_init(struct l2cap_chan *chan);
 void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
+void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
 void l2cap_chan_del(struct l2cap_chan *chan, int err);
+void l2cap_send_conn_req(struct l2cap_chan *chan);
+void l2cap_move_start(struct l2cap_chan *chan);
+void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
+		       u8 status);
+void __l2cap_physical_cfm(struct l2cap_chan *chan, int result);
 
 #endif /* __L2CAP_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7d5b600..e78db2c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -306,6 +306,88 @@ struct key_params {
 };
 
 /**
+ * struct cfg80211_chan_def - channel definition
+ * @chan: the (control) channel
+ * @width: channel width
+ * @center_freq1: center frequency of first segment
+ * @center_freq2: center frequency of second segment
+ *	(only with 80+80 MHz)
+ */
+struct cfg80211_chan_def {
+	struct ieee80211_channel *chan;
+	enum nl80211_chan_width width;
+	u32 center_freq1;
+	u32 center_freq2;
+};
+
+/**
+ * cfg80211_get_chandef_type - return old channel type from chandef
+ * @chandef: the channel definition
+ *
+ * Returns the old channel type (NOHT, HT20, HT40+/-) from a given
+ * chandef, which must have a bandwidth allowing this conversion.
+ */
+static inline enum nl80211_channel_type
+cfg80211_get_chandef_type(const struct cfg80211_chan_def *chandef)
+{
+	switch (chandef->width) {
+	case NL80211_CHAN_WIDTH_20_NOHT:
+		return NL80211_CHAN_NO_HT;
+	case NL80211_CHAN_WIDTH_20:
+		return NL80211_CHAN_HT20;
+	case NL80211_CHAN_WIDTH_40:
+		if (chandef->center_freq1 > chandef->chan->center_freq)
+			return NL80211_CHAN_HT40PLUS;
+		return NL80211_CHAN_HT40MINUS;
+	default:
+		WARN_ON(1);
+		return NL80211_CHAN_NO_HT;
+	}
+}
+
+/**
+ * cfg80211_chandef_create - create channel definition using channel type
+ * @chandef: the channel definition struct to fill
+ * @channel: the control channel
+ * @chantype: the channel type
+ *
+ * Given a channel type, create a channel definition.
+ */
+void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
+			     struct ieee80211_channel *channel,
+			     enum nl80211_channel_type chantype);
+
+/**
+ * cfg80211_chandef_identical - check if two channel definitions are identical
+ * @chandef1: first channel definition
+ * @chandef2: second channel definition
+ *
+ * Returns %true if the channels defined by the channel definitions are
+ * identical, %false otherwise.
+ */
+static inline bool
+cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1,
+			   const struct cfg80211_chan_def *chandef2)
+{
+	return (chandef1->chan == chandef2->chan &&
+		chandef1->width == chandef2->width &&
+		chandef1->center_freq1 == chandef2->center_freq1 &&
+		chandef1->center_freq2 == chandef2->center_freq2);
+}
+
+/**
+ * cfg80211_chandef_compatible - check if two channel definitions are compatible
+ * @chandef1: first channel definition
+ * @chandef2: second channel definition
+ *
+ * Returns %NULL if the given channel definitions are incompatible,
+ * chandef1 or chandef2 otherwise.
+ */
+const struct cfg80211_chan_def *
+cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1,
+			    const struct cfg80211_chan_def *chandef2);
+
+/**
  * enum survey_info_flags - survey information flags
  *
  * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in
@@ -426,8 +508,7 @@ struct cfg80211_beacon_data {
  *
  * Used to configure an AP interface.
  *
- * @channel: the channel to start the AP on
- * @channel_type: the channel type to use
+ * @chandef: defines the channel to use
  * @beacon: beacon data
  * @beacon_interval: beacon interval
  * @dtim_period: DTIM period
@@ -441,8 +522,7 @@ struct cfg80211_beacon_data {
  * @inactivity_timeout: time in seconds to determine station's inactivity.
  */
 struct cfg80211_ap_settings {
-	struct ieee80211_channel *channel;
-	enum nl80211_channel_type channel_type;
+	struct cfg80211_chan_def chandef;
 
 	struct cfg80211_beacon_data beacon;
 
@@ -498,6 +578,7 @@ enum station_parameters_apply_mask {
  * @plink_action: plink action to take
  * @plink_state: set the peer link state for a station
  * @ht_capa: HT capabilities of station
+ * @vht_capa: VHT capabilities of station
  * @uapsd_queues: bitmap of queues configured for uapsd. same format
  *	as the AC bitmap in the QoS info field
  * @max_sp: max Service Period. same format as the MAX_SP in the
@@ -517,6 +598,7 @@ struct station_parameters {
 	u8 plink_action;
 	u8 plink_state;
 	struct ieee80211_ht_cap *ht_capa;
+	struct ieee80211_vht_cap *vht_capa;
 	u8 uapsd_queues;
 	u8 max_sp;
 };
@@ -580,16 +662,24 @@ enum station_info_flags {
  * Used by the driver to indicate the specific rate transmission
  * type for 802.11n transmissions.
  *
- * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
- * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_MCS: mcs field filled with HT MCS
+ * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 MHz width transmission
+ * @RATE_INFO_FLAGS_80_MHZ_WIDTH: 80 MHz width transmission
+ * @RATE_INFO_FLAGS_80P80_MHZ_WIDTH: 80+80 MHz width transmission
+ * @RATE_INFO_FLAGS_160_MHZ_WIDTH: 160 MHz width transmission
  * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
- * @RATE_INFO_FLAGS_60G: 60gHz MCS
+ * @RATE_INFO_FLAGS_60G: 60GHz MCS
  */
 enum rate_info_flags {
-	RATE_INFO_FLAGS_MCS		= 1<<0,
-	RATE_INFO_FLAGS_40_MHZ_WIDTH	= 1<<1,
-	RATE_INFO_FLAGS_SHORT_GI	= 1<<2,
-	RATE_INFO_FLAGS_60G		= 1<<3,
+	RATE_INFO_FLAGS_MCS			= BIT(0),
+	RATE_INFO_FLAGS_VHT_MCS			= BIT(1),
+	RATE_INFO_FLAGS_40_MHZ_WIDTH		= BIT(2),
+	RATE_INFO_FLAGS_80_MHZ_WIDTH		= BIT(3),
+	RATE_INFO_FLAGS_80P80_MHZ_WIDTH		= BIT(4),
+	RATE_INFO_FLAGS_160_MHZ_WIDTH		= BIT(5),
+	RATE_INFO_FLAGS_SHORT_GI		= BIT(6),
+	RATE_INFO_FLAGS_60G			= BIT(7),
 };
 
 /**
@@ -600,11 +690,13 @@ enum rate_info_flags {
  * @flags: bitflag of flags from &enum rate_info_flags
  * @mcs: mcs index if struct describes a 802.11n bitrate
  * @legacy: bitrate in 100kbit/s for 802.11abg
+ * @nss: number of streams (VHT only)
  */
 struct rate_info {
 	u8 flags;
 	u8 mcs;
 	u16 legacy;
+	u8 nss;
 };
 
 /**
@@ -907,8 +999,7 @@ struct mesh_config {
 
 /**
  * struct mesh_setup - 802.11s mesh setup configuration
- * @channel: the channel to start the mesh network on
- * @channel_type: the channel type to use
+ * @chandef: defines the channel to use
  * @mesh_id: the mesh ID
  * @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes
  * @sync_method: which synchronization method to use
@@ -923,8 +1014,7 @@ struct mesh_config {
  * These parameters are fixed when the mesh is created.
  */
 struct mesh_setup {
-	struct ieee80211_channel *channel;
-	enum nl80211_channel_type channel_type;
+	struct cfg80211_chan_def chandef;
 	const u8 *mesh_id;
 	u8 mesh_id_len;
 	u8 sync_method;
@@ -1000,8 +1090,10 @@ struct cfg80211_ssid {
  * @n_channels: total number of channels to scan
  * @ie: optional information element(s) to add into Probe Request or %NULL
  * @ie_len: length of ie in octets
+ * @flags: bit field of flags controlling operation
  * @rates: bitmap of rates to advertise for each band
  * @wiphy: the wiphy this was for
+ * @scan_start: time (in jiffies) when the scan started
  * @wdev: the wireless device to scan for
  * @aborted: (internal) scan request was notified as aborted
  * @no_cck: used to send probe requests at non CCK rate in 2GHz band
@@ -1012,6 +1104,7 @@ struct cfg80211_scan_request {
 	u32 n_channels;
 	const u8 *ie;
 	size_t ie_len;
+	u32 flags;
 
 	u32 rates[IEEE80211_NUM_BANDS];
 
@@ -1019,6 +1112,7 @@ struct cfg80211_scan_request {
 
 	/* internal */
 	struct wiphy *wiphy;
+	unsigned long scan_start;
 	bool aborted;
 	bool no_cck;
 
@@ -1044,6 +1138,7 @@ struct cfg80211_match_set {
  * @interval: interval between each scheduled scan cycle
  * @ie: optional information element(s) to add into Probe Request or %NULL
  * @ie_len: length of ie in octets
+ * @flags: bit field of flags controlling operation
  * @match_sets: sets of parameters to be matched for a scan result
  * 	entry to be considered valid and to be passed to the host
  * 	(others are filtered out).
@@ -1061,6 +1156,7 @@ struct cfg80211_sched_scan_request {
 	u32 interval;
 	const u8 *ie;
 	size_t ie_len;
+	u32 flags;
 	struct cfg80211_match_set *match_sets;
 	int n_match_sets;
 	s32 rssi_thold;
@@ -1068,6 +1164,7 @@ struct cfg80211_sched_scan_request {
 	/* internal */
 	struct wiphy *wiphy;
 	struct net_device *dev;
+	unsigned long scan_start;
 
 	/* keep last */
 	struct ieee80211_channel *channels[0];
@@ -1152,6 +1249,9 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
  * @key_len: length of WEP key for shared key authentication
  * @key_idx: index of WEP key for shared key authentication
  * @key: WEP key for shared key authentication
+ * @sae_data: Non-IE data to use with SAE or %NULL. This starts with
+ *	Authentication transaction sequence number field.
+ * @sae_data_len: Length of sae_data buffer in octets
  */
 struct cfg80211_auth_request {
 	struct cfg80211_bss *bss;
@@ -1160,6 +1260,8 @@ struct cfg80211_auth_request {
 	enum nl80211_auth_type auth_type;
 	const u8 *key;
 	u8 key_len, key_idx;
+	const u8 *sae_data;
+	size_t sae_data_len;
 };
 
 /**
@@ -1252,8 +1354,7 @@ struct cfg80211_disassoc_request {
  * @ssid_len: The length of the SSID, will always be non-zero.
  * @bssid: Fixed BSSID requested, maybe be %NULL, if set do not
  *	search for IBSSs with a different BSSID.
- * @channel: The channel to use if no IBSS can be found to join.
- * @channel_type: channel type (HT mode)
+ * @chandef: defines the channel to use if no other IBSS to join can be found
  * @channel_fixed: The channel should be fixed -- do not search for
  *	IBSSs to join on other channels.
  * @ie: information element(s) to include in the beacon
@@ -1271,8 +1372,7 @@ struct cfg80211_disassoc_request {
 struct cfg80211_ibss_params {
 	u8 *ssid;
 	u8 *bssid;
-	struct ieee80211_channel *channel;
-	enum nl80211_channel_type channel_type;
+	struct cfg80211_chan_def chandef;
 	u8 *ie;
 	u8 ssid_len, ie_len;
 	u16 beacon_interval;
@@ -1531,13 +1631,19 @@ struct cfg80211_gtk_rekey_data {
  *	to a merge.
  * @leave_ibss: Leave the IBSS.
  *
+ * @set_mcast_rate: Set the specified multicast rate (only if vif is in ADHOC or
+ *	MESH mode)
+ *
  * @set_wiphy_params: Notify that wiphy parameters have changed;
  *	@changed bitfield (see &enum wiphy_params_flags) describes which values
  *	have changed. The actual parameter values are available in
  *	struct wiphy. If returning an error, no value should be changed.
  *
  * @set_tx_power: set the transmit power according to the parameters,
- *	the power passed is in mBm, to get dBm use MBM_TO_DBM().
+ *	the power passed is in mBm, to get dBm use MBM_TO_DBM(). The
+ *	wdev may be %NULL if power was set for the wiphy, and will
+ *	always be %NULL unless the driver supports per-vif TX power
+ *	(as advertised by the nl80211 feature flag.)
  * @get_tx_power: store the current TX power into the dbm variable;
  *	return 0 if successful
  *
@@ -1708,8 +1814,7 @@ struct cfg80211_ops {
 					     struct ieee80211_channel *chan);
 
 	int	(*set_monitor_channel)(struct wiphy *wiphy,
-				       struct ieee80211_channel *chan,
-				       enum nl80211_channel_type channel_type);
+				       struct cfg80211_chan_def *chandef);
 
 	int	(*scan)(struct wiphy *wiphy,
 			struct cfg80211_scan_request *request);
@@ -1732,11 +1837,15 @@ struct cfg80211_ops {
 			     struct cfg80211_ibss_params *params);
 	int	(*leave_ibss)(struct wiphy *wiphy, struct net_device *dev);
 
+	int	(*set_mcast_rate)(struct wiphy *wiphy, struct net_device *dev,
+				  int rate[IEEE80211_NUM_BANDS]);
+
 	int	(*set_wiphy_params)(struct wiphy *wiphy, u32 changed);
 
-	int	(*set_tx_power)(struct wiphy *wiphy,
+	int	(*set_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
 				enum nl80211_tx_power_setting type, int mbm);
-	int	(*get_tx_power)(struct wiphy *wiphy, int *dbm);
+	int	(*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
+				int *dbm);
 
 	int	(*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
 				const u8 *addr);
@@ -1767,7 +1876,6 @@ struct cfg80211_ops {
 	int	(*remain_on_channel)(struct wiphy *wiphy,
 				     struct wireless_dev *wdev,
 				     struct ieee80211_channel *chan,
-				     enum nl80211_channel_type channel_type,
 				     unsigned int duration,
 				     u64 *cookie);
 	int	(*cancel_remain_on_channel)(struct wiphy *wiphy,
@@ -1776,10 +1884,8 @@ struct cfg80211_ops {
 
 	int	(*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev,
 			  struct ieee80211_channel *chan, bool offchan,
-			  enum nl80211_channel_type channel_type,
-			  bool channel_type_valid, unsigned int wait,
-			  const u8 *buf, size_t len, bool no_cck,
-			  bool dont_wait_for_ack, u64 *cookie);
+			  unsigned int wait, const u8 *buf, size_t len,
+			  bool no_cck, bool dont_wait_for_ack, u64 *cookie);
 	int	(*mgmt_tx_cancel_wait)(struct wiphy *wiphy,
 				       struct wireless_dev *wdev,
 				       u64 cookie);
@@ -1834,10 +1940,9 @@ struct cfg80211_ops {
 	void	(*get_et_strings)(struct wiphy *wiphy, struct net_device *dev,
 				  u32 sset, u8 *data);
 
-	struct ieee80211_channel *
-		(*get_channel)(struct wiphy *wiphy,
+	int	(*get_channel)(struct wiphy *wiphy,
 			       struct wireless_dev *wdev,
-			       enum nl80211_channel_type *type);
+			       struct cfg80211_chan_def *chandef);
 
 	int	(*start_p2p_device)(struct wiphy *wiphy,
 				    struct wireless_dev *wdev);
@@ -2445,8 +2550,7 @@ struct wireless_dev {
 	spinlock_t event_lock;
 
 	struct cfg80211_internal_bss *current_bss; /* associated / joined */
-	struct ieee80211_channel *preset_chan;
-	enum nl80211_channel_type preset_chantype;
+	struct cfg80211_chan_def preset_chandef;
 
 	/* for AP and mesh channel tracking */
 	struct ieee80211_channel *channel;
@@ -3326,14 +3430,12 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason,
  * @wdev: wireless device
  * @cookie: the request cookie
  * @chan: The current channel (from remain_on_channel request)
- * @channel_type: Channel type
  * @duration: Duration in milliseconds that the driver intents to remain on the
  *	channel
  * @gfp: allocation flags
  */
 void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
 			       struct ieee80211_channel *chan,
-			       enum nl80211_channel_type channel_type,
 			       unsigned int duration, gfp_t gfp);
 
 /**
@@ -3341,12 +3443,10 @@ void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
  * @wdev: wireless device
  * @cookie: the request cookie
  * @chan: The current channel (from remain_on_channel request)
- * @channel_type: Channel type
  * @gfp: allocation flags
  */
 void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
 					struct ieee80211_channel *chan,
-					enum nl80211_channel_type channel_type,
 					gfp_t gfp);
 
 
@@ -3536,7 +3636,6 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
  * @len: length of the frame
  * @freq: frequency the frame was received on
  * @sig_dbm: signal strength in mBm, or 0 if unknown
- * @gfp: allocation flags
  *
  * Use this function to report to userspace when a beacon was
  * received. It is not useful to call this when there is no
@@ -3544,31 +3643,47 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
  */
 void cfg80211_report_obss_beacon(struct wiphy *wiphy,
 				 const u8 *frame, size_t len,
-				 int freq, int sig_dbm, gfp_t gfp);
+				 int freq, int sig_dbm);
 
 /**
- * cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used
+ * cfg80211_reg_can_beacon - check if beaconing is allowed
  * @wiphy: the wiphy
- * @chan: main channel
- * @channel_type: HT mode
+ * @chandef: the channel definition
  *
  * This function returns true if there is no secondary channel or the secondary
- * channel can be used for beaconing (i.e. is not a radar channel etc.)
+ * channel(s) can be used for beaconing (i.e. is not a radar channel etc.)
  */
-bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
-				  struct ieee80211_channel *chan,
-				  enum nl80211_channel_type channel_type);
+bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
+			     struct cfg80211_chan_def *chandef);
 
 /*
  * cfg80211_ch_switch_notify - update wdev channel and notify userspace
  * @dev: the device which switched channels
- * @freq: new channel frequency (in MHz)
- * @type: channel type
+ * @chandef: the new channel definition
  *
  * Acquires wdev_lock, so must only be called from sleepable driver context!
  */
-void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
-			       enum nl80211_channel_type type);
+void cfg80211_ch_switch_notify(struct net_device *dev,
+			       struct cfg80211_chan_def *chandef);
+
+/*
+ * cfg80211_tdls_oper_request - request userspace to perform TDLS operation
+ * @dev: the device on which the operation is requested
+ * @peer: the MAC address of the peer device
+ * @oper: the requested TDLS operation (NL80211_TDLS_SETUP or
+ *	NL80211_TDLS_TEARDOWN)
+ * @reason_code: the reason code for teardown request
+ * @gfp: allocation flags
+ *
+ * This function is used to request userspace to perform TDLS operation that
+ * requires knowledge of keys, i.e., link setup or teardown when the AP
+ * connection uses encryption. This is optional mechanism for the driver to use
+ * if it can automatically determine when a TDLS link could be useful (e.g.,
+ * based on traffic and signal strength for a peer).
+ */
+void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
+				enum nl80211_tdls_operation oper,
+				u16 reason_code, gfp_t gfp);
 
 /*
  * cfg80211_calculate_bitrate - calculate actual bitrate (in 100Kbps units)
@@ -3594,6 +3709,26 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate);
  */
 void cfg80211_unregister_wdev(struct wireless_dev *wdev);
 
+/**
+ * cfg80211_get_p2p_attr - find and copy a P2P attribute from IE buffer
+ * @ies: the input IE buffer
+ * @len: the input length
+ * @attr: the attribute ID to find
+ * @buf: output buffer, can be %NULL if the data isn't needed, e.g.
+ *	if the function is only called to get the needed buffer size
+ * @bufsize: size of the output buffer
+ *
+ * The function finds a given P2P attribute in the (vendor) IEs and
+ * copies its contents to the given buffer.
+ *
+ * The return value is a negative error code (-%EILSEQ or -%ENOENT) if
+ * the data is malformed or the attribute can't be found (respectively),
+ * or the length of the found attribute (which can be zero).
+ */
+int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
+			  enum ieee80211_p2p_attr_id attr,
+			  u8 *buf, unsigned int bufsize);
+
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/net/cls_cgroup.h b/include/net/cls_cgroup.h
index b6a6eeb..2581638 100644
--- a/include/net/cls_cgroup.h
+++ b/include/net/cls_cgroup.h
@@ -24,12 +24,12 @@ struct cgroup_cls_state
 	u32 classid;
 };
 
-extern void sock_update_classid(struct sock *sk);
+extern void sock_update_classid(struct sock *sk, struct task_struct *task);
 
 #if IS_BUILTIN(CONFIG_NET_CLS_CGROUP)
 static inline u32 task_cls_classid(struct task_struct *p)
 {
-	int classid;
+	u32 classid;
 
 	if (in_interrupt())
 		return 0;
@@ -61,7 +61,7 @@ static inline u32 task_cls_classid(struct task_struct *p)
 }
 #endif
 #else /* !CGROUP_NET_CLS_CGROUP */
-static inline void sock_update_classid(struct sock *sk)
+static inline void sock_update_classid(struct sock *sk, struct task_struct *task)
 {
 }
 
diff --git a/include/net/ip6_checksum.h b/include/net/ip6_checksum.h
index bc1b0fd..652d3d3 100644
--- a/include/net/ip6_checksum.h
+++ b/include/net/ip6_checksum.h
@@ -31,6 +31,8 @@
 #include <net/ip.h>
 #include <asm/checksum.h>
 #include <linux/in6.h>
+#include <linux/tcp.h>
+#include <linux/ipv6.h>
 
 #ifndef _HAVE_ARCH_IPV6_CSUM
 
@@ -91,4 +93,37 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
 }
 
 #endif
+
+static __inline__ __sum16 tcp_v6_check(int len,
+				   const struct in6_addr *saddr,
+				   const struct in6_addr *daddr,
+				   __wsum base)
+{
+	return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
+}
+
+static inline void __tcp_v6_send_check(struct sk_buff *skb,
+				       const struct in6_addr *saddr,
+				       const struct in6_addr *daddr)
+{
+	struct tcphdr *th = tcp_hdr(skb);
+
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
+		skb->csum_start = skb_transport_header(skb) - skb->head;
+		skb->csum_offset = offsetof(struct tcphdr, check);
+	} else {
+		th->check = tcp_v6_check(skb->len, saddr, daddr,
+					 csum_partial(th, th->doff << 2,
+						      skb->csum));
+	}
+}
+
+static inline void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb)
+{
+	struct ipv6_pinfo *np = inet6_sk(sk);
+
+	__tcp_v6_send_check(skb, &np->saddr, &np->daddr);
+}
+
 #endif
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 8a2a203..fdc48a9 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -47,6 +47,8 @@ struct fib6_config {
 	unsigned long	fc_expires;
 	struct nlattr	*fc_mx;
 	int		fc_mx_len;
+	int		fc_mp_len;
+	struct nlattr	*fc_mp;
 
 	struct nl_info	fc_nlinfo;
 };
@@ -99,6 +101,14 @@ struct rt6_info {
 
 	struct in6_addr			rt6i_gateway;
 
+	/* Multipath routes:
+	 * siblings is a list of rt6_info that have the the same metric/weight,
+	 * destination, but not the same gateway. nsiblings is just a cache
+	 * to speed up lookup.
+	 */
+	struct list_head		rt6i_siblings;
+	unsigned int			rt6i_nsiblings;
+
 	atomic_t			rt6i_ref;
 
 	/* These are in a separate cache line. */
@@ -107,7 +117,6 @@ struct rt6_info {
 	struct rt6key			rt6i_src;
 	struct rt6key			rt6i_prefsrc;
 	u32				rt6i_metric;
-	u32				rt6i_peer_genid;
 
 	struct inet6_dev		*rt6i_idev;
 	unsigned long			_rt6i_peer;
@@ -203,6 +212,15 @@ static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
 	dst_hold(new);
 }
 
+static inline void ip6_rt_put(struct rt6_info *rt)
+{
+	/* dst_release() accepts a NULL parameter.
+	 * We rely on dst being first structure in struct rt6_info
+	 */
+	BUILD_BUG_ON(offsetof(struct rt6_info, dst) != 0);
+	dst_release(&rt->dst);
+}
+
 struct fib6_walker_t {
 	struct list_head lh;
 	struct fib6_node *root, *node;
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 5fa2af0..27d8318 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -1,9 +1,6 @@
 #ifndef _NET_IP6_ROUTE_H
 #define _NET_IP6_ROUTE_H
 
-#define IP6_RT_PRIO_USER	1024
-#define IP6_RT_PRIO_ADDRCONF	256
-
 struct route_info {
 	__u8			type;
 	__u8			length;
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index ee75ccd..68c69d5 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -22,7 +22,10 @@
 #include <linux/ip.h>
 #include <linux/ipv6.h>			/* for struct ipv6hdr */
 #include <net/ipv6.h>
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#if IS_ENABLED(CONFIG_IP_VS_IPV6)
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#endif
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
 #include <net/netfilter/nf_conntrack.h>
 #endif
 #include <net/net_namespace.h>		/* Netw namespace */
@@ -103,30 +106,117 @@ static inline struct net *seq_file_single_net(struct seq_file *seq)
 /* Connections' size value needed by ip_vs_ctl.c */
 extern int ip_vs_conn_tab_size;
 
-
 struct ip_vs_iphdr {
-	int len;
-	__u8 protocol;
+	__u32 len;	/* IPv4 simply where L4 starts
+			   IPv6 where L4 Transport Header starts */
+	__u32 thoff_reasm; /* Transport Header Offset in nfct_reasm skb */
+	__u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/
+	__s16 protocol;
+	__s32 flags;
 	union nf_inet_addr saddr;
 	union nf_inet_addr daddr;
 };
 
+/* Dependency to module: nf_defrag_ipv6 */
+#if defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
+static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
+{
+	return skb->nfct_reasm;
+}
+static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
+				      int len, void *buffer,
+				      const struct ip_vs_iphdr *ipvsh)
+{
+	if (unlikely(ipvsh->fragoffs && skb_nfct_reasm(skb)))
+		return skb_header_pointer(skb_nfct_reasm(skb),
+					  ipvsh->thoff_reasm, len, buffer);
+
+	return skb_header_pointer(skb, offset, len, buffer);
+}
+#else
+static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
+{
+	return NULL;
+}
+static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
+				      int len, void *buffer,
+				      const struct ip_vs_iphdr *ipvsh)
+{
+	return skb_header_pointer(skb, offset, len, buffer);
+}
+#endif
+
 static inline void
-ip_vs_fill_iphdr(int af, const void *nh, struct ip_vs_iphdr *iphdr)
+ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr)
+{
+	const struct iphdr *iph = nh;
+
+	iphdr->len	= iph->ihl * 4;
+	iphdr->fragoffs	= 0;
+	iphdr->protocol	= iph->protocol;
+	iphdr->saddr.ip	= iph->saddr;
+	iphdr->daddr.ip	= iph->daddr;
+}
+
+/* This function handles filling *ip_vs_iphdr, both for IPv4 and IPv6.
+ * IPv6 requires some extra work, as finding proper header position,
+ * depend on the IPv6 extension headers.
+ */
+static inline void
+ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr)
 {
 #ifdef CONFIG_IP_VS_IPV6
 	if (af == AF_INET6) {
-		const struct ipv6hdr *iph = nh;
-		iphdr->len = sizeof(struct ipv6hdr);
-		iphdr->protocol = iph->nexthdr;
+		const struct ipv6hdr *iph =
+			(struct ipv6hdr *)skb_network_header(skb);
 		iphdr->saddr.in6 = iph->saddr;
 		iphdr->daddr.in6 = iph->daddr;
+		/* ipv6_find_hdr() updates len, flags, thoff_reasm */
+		iphdr->thoff_reasm = 0;
+		iphdr->len	 = 0;
+		iphdr->flags	 = 0;
+		iphdr->protocol  = ipv6_find_hdr(skb, &iphdr->len, -1,
+						 &iphdr->fragoffs,
+						 &iphdr->flags);
+		/* get proto from re-assembled packet and it's offset */
+		if (skb_nfct_reasm(skb))
+			iphdr->protocol = ipv6_find_hdr(skb_nfct_reasm(skb),
+							&iphdr->thoff_reasm,
+							-1, NULL, NULL);
+
 	} else
 #endif
 	{
-		const struct iphdr *iph = nh;
-		iphdr->len = iph->ihl * 4;
-		iphdr->protocol = iph->protocol;
+		const struct iphdr *iph =
+			(struct iphdr *)skb_network_header(skb);
+		iphdr->len	= iph->ihl * 4;
+		iphdr->fragoffs	= 0;
+		iphdr->protocol	= iph->protocol;
+		iphdr->saddr.ip	= iph->saddr;
+		iphdr->daddr.ip	= iph->daddr;
+	}
+}
+
+/* This function is a faster version of ip_vs_fill_iph_skb().
+ * Where we only populate {s,d}addr (and avoid calling ipv6_find_hdr()).
+ * This is used by the some of the ip_vs_*_schedule() functions.
+ * (Mostly done to avoid ABI breakage of external schedulers)
+ */
+static inline void
+ip_vs_fill_iph_addr_only(int af, const struct sk_buff *skb,
+			 struct ip_vs_iphdr *iphdr)
+{
+#ifdef CONFIG_IP_VS_IPV6
+	if (af == AF_INET6) {
+		const struct ipv6hdr *iph =
+			(struct ipv6hdr *)skb_network_header(skb);
+		iphdr->saddr.in6 = iph->saddr;
+		iphdr->daddr.in6 = iph->daddr;
+	} else
+#endif
+	{
+		const struct iphdr *iph =
+			(struct iphdr *)skb_network_header(skb);
 		iphdr->saddr.ip = iph->saddr;
 		iphdr->daddr.ip = iph->daddr;
 	}
@@ -165,7 +255,7 @@ static inline const char *ip_vs_dbg_addr(int af, char *buf, size_t buf_len,
 	int len;
 #ifdef CONFIG_IP_VS_IPV6
 	if (af == AF_INET6)
-		len = snprintf(&buf[*idx], buf_len - *idx, "[%pI6]",
+		len = snprintf(&buf[*idx], buf_len - *idx, "[%pI6c]",
 			       &addr->in6) + 1;
 	else
 #endif
@@ -398,27 +488,26 @@ struct ip_vs_protocol {
 
 	int (*conn_schedule)(int af, struct sk_buff *skb,
 			     struct ip_vs_proto_data *pd,
-			     int *verdict, struct ip_vs_conn **cpp);
+			     int *verdict, struct ip_vs_conn **cpp,
+			     struct ip_vs_iphdr *iph);
 
 	struct ip_vs_conn *
 	(*conn_in_get)(int af,
 		       const struct sk_buff *skb,
 		       const struct ip_vs_iphdr *iph,
-		       unsigned int proto_off,
 		       int inverse);
 
 	struct ip_vs_conn *
 	(*conn_out_get)(int af,
 			const struct sk_buff *skb,
 			const struct ip_vs_iphdr *iph,
-			unsigned int proto_off,
 			int inverse);
 
-	int (*snat_handler)(struct sk_buff *skb,
-			    struct ip_vs_protocol *pp, struct ip_vs_conn *cp);
+	int (*snat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp,
+			    struct ip_vs_conn *cp, struct ip_vs_iphdr *iph);
 
-	int (*dnat_handler)(struct sk_buff *skb,
-			    struct ip_vs_protocol *pp, struct ip_vs_conn *cp);
+	int (*dnat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp,
+			    struct ip_vs_conn *cp, struct ip_vs_iphdr *iph);
 
 	int (*csum_check)(int af, struct sk_buff *skb,
 			  struct ip_vs_protocol *pp);
@@ -518,7 +607,7 @@ struct ip_vs_conn {
 	   NF_ACCEPT can be returned when destination is local.
 	 */
 	int (*packet_xmit)(struct sk_buff *skb, struct ip_vs_conn *cp,
-			   struct ip_vs_protocol *pp);
+			   struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
 
 	/* Note: we can group the following members into a structure,
 	   in order to save more space, and the following members are
@@ -769,13 +858,11 @@ struct ip_vs_app {
 
 	struct ip_vs_conn *
 	(*conn_in_get)(const struct sk_buff *skb, struct ip_vs_app *app,
-		       const struct iphdr *iph, unsigned int proto_off,
-		       int inverse);
+		       const struct iphdr *iph, int inverse);
 
 	struct ip_vs_conn *
 	(*conn_out_get)(const struct sk_buff *skb, struct ip_vs_app *app,
-			const struct iphdr *iph, unsigned int proto_off,
-			int inverse);
+			const struct iphdr *iph, int inverse);
 
 	int (*state_transition)(struct ip_vs_conn *cp, int direction,
 				const struct sk_buff *skb,
@@ -1074,14 +1161,12 @@ struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p);
 
 struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
 					    const struct ip_vs_iphdr *iph,
-					    unsigned int proto_off,
 					    int inverse);
 
 struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p);
 
 struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
 					     const struct ip_vs_iphdr *iph,
-					     unsigned int proto_off,
 					     int inverse);
 
 /* put back the conn without restarting its timer */
@@ -1254,9 +1339,10 @@ extern struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
 extern void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
 extern struct ip_vs_conn *
 ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
-	       struct ip_vs_proto_data *pd, int *ignored);
+	       struct ip_vs_proto_data *pd, int *ignored,
+	       struct ip_vs_iphdr *iph);
 extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
-			struct ip_vs_proto_data *pd);
+			struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph);
 
 extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg);
 
@@ -1315,33 +1401,38 @@ extern void ip_vs_read_estimator(struct ip_vs_stats_user *dst,
 /*
  *	Various IPVS packet transmitters (from ip_vs_xmit.c)
  */
-extern int ip_vs_null_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_bypass_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_nat_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_tunnel_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_dr_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_icmp_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp,
- int offset, unsigned int hooknum);
+extern int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+			   struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+extern int ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+			     struct ip_vs_protocol *pp,
+			     struct ip_vs_iphdr *iph);
+extern int ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+			  struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+extern int ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+			     struct ip_vs_protocol *pp,
+			     struct ip_vs_iphdr *iph);
+extern int ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+			 struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+extern int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+			   struct ip_vs_protocol *pp, int offset,
+			   unsigned int hooknum, struct ip_vs_iphdr *iph);
 extern void ip_vs_dst_reset(struct ip_vs_dest *dest);
 
 #ifdef CONFIG_IP_VS_IPV6
-extern int ip_vs_bypass_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_nat_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_tunnel_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_dr_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_icmp_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp,
- int offset, unsigned int hooknum);
+extern int ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+				struct ip_vs_protocol *pp,
+				struct ip_vs_iphdr *iph);
+extern int ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+			     struct ip_vs_protocol *pp,
+			     struct ip_vs_iphdr *iph);
+extern int ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+				struct ip_vs_protocol *pp,
+				struct ip_vs_iphdr *iph);
+extern int ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+			    struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+extern int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+			      struct ip_vs_protocol *pp, int offset,
+			      unsigned int hooknum, struct ip_vs_iphdr *iph);
 #endif
 
 #ifdef CONFIG_SYSCTL
diff --git a/include/net/ipip.h b/include/net/ipip.h
index ddc077c..21947cf 100644
--- a/include/net/ipip.h
+++ b/include/net/ipip.h
@@ -48,25 +48,27 @@ struct ip_tunnel_prl_entry {
 	struct rcu_head			rcu_head;
 };
 
-#define __IPTUNNEL_XMIT(stats1, stats2) do {				\
-	int err;							\
-	int pkt_len = skb->len - skb_transport_offset(skb);		\
-									\
-	skb->ip_summed = CHECKSUM_NONE;					\
-	ip_select_ident(iph, &rt->dst, NULL);				\
-									\
-	err = ip_local_out(skb);					\
-	if (likely(net_xmit_eval(err) == 0)) {				\
-		u64_stats_update_begin(&(stats1)->syncp);		\
-		(stats1)->tx_bytes += pkt_len;				\
-		(stats1)->tx_packets++;					\
-		u64_stats_update_end(&(stats1)->syncp);			\
-	} else {							\
-		(stats2)->tx_errors++;					\
-		(stats2)->tx_aborted_errors++;				\
-	}								\
-} while (0)
+static inline void iptunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	int err;
+	struct iphdr *iph = ip_hdr(skb);
+	int pkt_len = skb->len - skb_transport_offset(skb);
+	struct pcpu_tstats *tstats = this_cpu_ptr(dev->tstats);
 
-#define IPTUNNEL_XMIT() __IPTUNNEL_XMIT(txq, stats)
+	nf_reset(skb);
+	skb->ip_summed = CHECKSUM_NONE;
+	ip_select_ident(iph, skb_dst(skb), NULL);
+
+	err = ip_local_out(skb);
+	if (likely(net_xmit_eval(err) == 0)) {
+		u64_stats_update_begin(&tstats->syncp);
+		tstats->tx_bytes += pkt_len;
+		tstats->tx_packets++;
+		u64_stats_update_end(&tstats->syncp);
+	} else {
+		dev->stats.tx_errors++;
+		dev->stats.tx_aborted_errors++;
+	}
+}
 
 #endif
diff --git a/include/net/irda/irlmp.h b/include/net/irda/irlmp.h
index fff11b7..591f786 100644
--- a/include/net/irda/irlmp.h
+++ b/include/net/irda/irlmp.h
@@ -134,7 +134,7 @@ typedef struct {
 } CACHE_ENTRY;
 
 /*
- *  Information about each registred IrLAP layer
+ *  Information about each registered IrLAP layer
  */
 struct lap_cb {
 	irda_queue_t queue; /* Must be first */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 82558c8..db7680a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -144,6 +144,39 @@ struct ieee80211_low_level_stats {
 };
 
 /**
+ * enum ieee80211_chanctx_change - change flag for channel context
+ * @IEEE80211_CHANCTX_CHANGE_WIDTH: The channel width changed
+ * @IEEE80211_CHANCTX_CHANGE_RX_CHAINS: The number of RX chains changed
+ */
+enum ieee80211_chanctx_change {
+	IEEE80211_CHANCTX_CHANGE_WIDTH		= BIT(0),
+	IEEE80211_CHANCTX_CHANGE_RX_CHAINS	= BIT(1),
+};
+
+/**
+ * struct ieee80211_chanctx_conf - channel context that vifs may be tuned to
+ *
+ * This is the driver-visible part. The ieee80211_chanctx
+ * that contains it is visible in mac80211 only.
+ *
+ * @def: the channel definition
+ * @rx_chains_static: The number of RX chains that must always be
+ *	active on the channel to receive MIMO transmissions
+ * @rx_chains_dynamic: The number of RX chains that must be enabled
+ *	after RTS/CTS handshake to receive SMPS MIMO transmissions;
+ *	this will always be >= @rx_chains_always.
+ * @drv_priv: data area for driver use, will always be aligned to
+ *	sizeof(void *), size is determined in hw information.
+ */
+struct ieee80211_chanctx_conf {
+	struct cfg80211_chan_def def;
+
+	u8 rx_chains_static, rx_chains_dynamic;
+
+	u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
+};
+
+/**
  * enum ieee80211_bss_change - BSS change notification flags
  *
  * These flags are used with the bss_info_changed() callback
@@ -172,6 +205,9 @@ struct ieee80211_low_level_stats {
  * @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode)
  * @BSS_CHANGED_AP_PROBE_RESP: Probe Response changed for this BSS (AP mode)
  * @BSS_CHANGED_PS: PS changed for this BSS (STA mode)
+ * @BSS_CHANGED_TXPOWER: TX power setting changed for this interface
+ * @BSS_CHANGED_P2P_PS: P2P powersave settings (CTWindow, opportunistic PS)
+ *	changed (currently only in P2P client mode, GO mode will be later)
  */
 enum ieee80211_bss_change {
 	BSS_CHANGED_ASSOC		= 1<<0,
@@ -192,6 +228,8 @@ enum ieee80211_bss_change {
 	BSS_CHANGED_SSID		= 1<<15,
 	BSS_CHANGED_AP_PROBE_RESP	= 1<<16,
 	BSS_CHANGED_PS			= 1<<17,
+	BSS_CHANGED_TXPOWER		= 1<<18,
+	BSS_CHANGED_P2P_PS		= 1<<19,
 
 	/* when adding here, make sure to change ieee80211_reconfig */
 };
@@ -223,6 +261,7 @@ enum ieee80211_rssi_event {
  * @assoc: association status
  * @ibss_joined: indicates whether this station is part of an IBSS
  *	or not
+ * @ibss_creator: indicates if a new IBSS network is being created
  * @aid: association ID number, valid only when @assoc is true
  * @use_cts_prot: use CTS protection
  * @use_short_preamble: use 802.11b short preamble;
@@ -247,9 +286,8 @@ enum ieee80211_rssi_event {
  * @mcast_rate: per-band multicast rate index + 1 (0: disabled)
  * @bssid: The BSSID for this BSS
  * @enable_beacon: whether beaconing should be enabled or not
- * @channel_type: Channel type for this BSS -- the hardware might be
- *	configured for HT40+ while this BSS only uses no-HT, for
- *	example.
+ * @chandef: Channel definition for this BSS -- the hardware might be
+ *	configured a higher bandwidth than this BSS uses, for example.
  * @ht_operation_mode: HT operation mode like in &struct ieee80211_ht_operation.
  *	This field is only valid when the channel type is one of the HT types.
  * @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value
@@ -273,11 +311,15 @@ enum ieee80211_rssi_event {
  * @ssid: The SSID of the current vif. Only valid in AP-mode.
  * @ssid_len: Length of SSID given in @ssid.
  * @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode.
+ * @txpower: TX power in dBm
+ * @p2p_ctwindow: P2P CTWindow, only for P2P client interfaces
+ * @p2p_oppps: P2P opportunistic PS is enabled
  */
 struct ieee80211_bss_conf {
 	const u8 *bssid;
 	/* association related data */
 	bool assoc, ibss_joined;
+	bool ibss_creator;
 	u16 aid;
 	/* erp related data */
 	bool use_cts_prot;
@@ -294,7 +336,7 @@ struct ieee80211_bss_conf {
 	u16 ht_operation_mode;
 	s32 cqm_rssi_thold;
 	u32 cqm_rssi_hyst;
-	enum nl80211_channel_type channel_type;
+	struct cfg80211_chan_def chandef;
 	__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
 	u8 arp_addr_cnt;
 	bool arp_filter_enabled;
@@ -304,6 +346,9 @@ struct ieee80211_bss_conf {
 	u8 ssid[IEEE80211_MAX_SSID_LEN];
 	size_t ssid_len;
 	bool hidden_ssid;
+	int txpower;
+	u8 p2p_ctwindow;
+	bool p2p_oppps;
 };
 
 /**
@@ -454,9 +499,14 @@ enum mac80211_tx_control_flags {
  *	This is set if the current BSS requires ERP protection.
  * @IEEE80211_TX_RC_USE_SHORT_PREAMBLE: Use short preamble.
  * @IEEE80211_TX_RC_MCS: HT rate.
+ * @IEEE80211_TX_RC_VHT_MCS: VHT MCS rate, in this case the idx field is split
+ *	into a higher 4 bits (Nss) and lower 4 bits (MCS number)
  * @IEEE80211_TX_RC_GREEN_FIELD: Indicates whether this rate should be used in
  *	Greenfield mode.
  * @IEEE80211_TX_RC_40_MHZ_WIDTH: Indicates if the Channel Width should be 40 MHz.
+ * @IEEE80211_TX_RC_80_MHZ_WIDTH: Indicates 80 MHz transmission
+ * @IEEE80211_TX_RC_160_MHZ_WIDTH: Indicates 160 MHz transmission
+ *	(80+80 isn't supported yet)
  * @IEEE80211_TX_RC_DUP_DATA: The frame should be transmitted on both of the
  *	adjacent 20 MHz channels, if the current channel type is
  *	NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS.
@@ -467,12 +517,15 @@ enum mac80211_rate_control_flags {
 	IEEE80211_TX_RC_USE_CTS_PROTECT		= BIT(1),
 	IEEE80211_TX_RC_USE_SHORT_PREAMBLE	= BIT(2),
 
-	/* rate index is an MCS rate number instead of an index */
+	/* rate index is an HT/VHT MCS instead of an index */
 	IEEE80211_TX_RC_MCS			= BIT(3),
 	IEEE80211_TX_RC_GREEN_FIELD		= BIT(4),
 	IEEE80211_TX_RC_40_MHZ_WIDTH		= BIT(5),
 	IEEE80211_TX_RC_DUP_DATA		= BIT(6),
 	IEEE80211_TX_RC_SHORT_GI		= BIT(7),
+	IEEE80211_TX_RC_VHT_MCS			= BIT(8),
+	IEEE80211_TX_RC_80_MHZ_WIDTH		= BIT(9),
+	IEEE80211_TX_RC_160_MHZ_WIDTH		= BIT(10),
 };
 
 
@@ -515,10 +568,32 @@ enum mac80211_rate_control_flags {
  */
 struct ieee80211_tx_rate {
 	s8 idx;
-	u8 count;
-	u8 flags;
+	u16 count:5,
+	    flags:11;
 } __packed;
 
+#define IEEE80211_MAX_TX_RETRY		31
+
+static inline void ieee80211_rate_set_vht(struct ieee80211_tx_rate *rate,
+					  u8 mcs, u8 nss)
+{
+	WARN_ON(mcs & ~0xF);
+	WARN_ON(nss & ~0x7);
+	rate->idx = (nss << 4) | mcs;
+}
+
+static inline u8
+ieee80211_rate_get_vht_mcs(const struct ieee80211_tx_rate *rate)
+{
+	return rate->idx & 0xF;
+}
+
+static inline u8
+ieee80211_rate_get_vht_nss(const struct ieee80211_tx_rate *rate)
+{
+	return rate->idx >> 4;
+}
+
 /**
  * struct ieee80211_tx_info - skb transmit information
  *
@@ -663,13 +738,20 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
  *	the frame.
  * @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on
  *	the frame.
- * @RX_FLAG_MACTIME_MPDU: The timestamp passed in the RX status (@mactime
+ * @RX_FLAG_MACTIME_START: The timestamp passed in the RX status (@mactime
  *	field) is valid and contains the time the first symbol of the MPDU
  *	was received. This is useful in monitor mode and for proper IBSS
  *	merging.
+ * @RX_FLAG_MACTIME_END: The timestamp passed in the RX status (@mactime
+ *	field) is valid and contains the time the last symbol of the MPDU
+ *	(including FCS) was received.
  * @RX_FLAG_SHORTPRE: Short preamble was used for this frame
  * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
+ * @RX_FLAG_VHT: VHT MCS was used and rate_index is MCS index
  * @RX_FLAG_40MHZ: HT40 (40 MHz) was used
+ * @RX_FLAG_80MHZ: 80 MHz was used
+ * @RX_FLAG_80P80MHZ: 80+80 MHz was used
+ * @RX_FLAG_160MHZ: 160 MHz was used
  * @RX_FLAG_SHORT_GI: Short guard interval was used
  * @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present.
  *	Valid only for data frames (mainly A-MPDU)
@@ -697,7 +779,7 @@ enum mac80211_rx_flags {
 	RX_FLAG_IV_STRIPPED		= BIT(4),
 	RX_FLAG_FAILED_FCS_CRC		= BIT(5),
 	RX_FLAG_FAILED_PLCP_CRC 	= BIT(6),
-	RX_FLAG_MACTIME_MPDU		= BIT(7),
+	RX_FLAG_MACTIME_START		= BIT(7),
 	RX_FLAG_SHORTPRE		= BIT(8),
 	RX_FLAG_HT			= BIT(9),
 	RX_FLAG_40MHZ			= BIT(10),
@@ -711,6 +793,11 @@ enum mac80211_rx_flags {
 	RX_FLAG_AMPDU_IS_LAST		= BIT(18),
 	RX_FLAG_AMPDU_DELIM_CRC_ERROR	= BIT(19),
 	RX_FLAG_AMPDU_DELIM_CRC_KNOWN	= BIT(20),
+	RX_FLAG_MACTIME_END		= BIT(21),
+	RX_FLAG_VHT			= BIT(22),
+	RX_FLAG_80MHZ			= BIT(23),
+	RX_FLAG_80P80MHZ		= BIT(24),
+	RX_FLAG_160MHZ			= BIT(25),
 };
 
 /**
@@ -731,25 +818,39 @@ enum mac80211_rx_flags {
  *	@IEEE80211_HW_SIGNAL_*
  * @antenna: antenna used
  * @rate_idx: index of data rate into band's supported rates or MCS index if
- *	HT rates are use (RX_FLAG_HT)
+ *	HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)
+ * @vht_nss: number of streams (VHT only)
  * @flag: %RX_FLAG_*
  * @rx_flags: internal RX flags for mac80211
  * @ampdu_reference: A-MPDU reference number, must be a different value for
  *	each A-MPDU but the same for each subframe within one A-MPDU
  * @ampdu_delimiter_crc: A-MPDU delimiter CRC
+ * @vendor_radiotap_bitmap: radiotap vendor namespace presence bitmap
+ * @vendor_radiotap_len: radiotap vendor namespace length
+ * @vendor_radiotap_align: radiotap vendor namespace alignment. Note
+ *	that the actual data must be at the start of the SKB data
+ *	already.
+ * @vendor_radiotap_oui: radiotap vendor namespace OUI
+ * @vendor_radiotap_subns: radiotap vendor sub namespace
  */
 struct ieee80211_rx_status {
 	u64 mactime;
 	u32 device_timestamp;
 	u32 ampdu_reference;
 	u32 flag;
+	u32 vendor_radiotap_bitmap;
+	u16 vendor_radiotap_len;
 	u16 freq;
 	u8 rate_idx;
+	u8 vht_nss;
 	u8 rx_flags;
 	u8 band;
 	u8 antenna;
 	s8 signal;
 	u8 ampdu_delimiter_crc;
+	u8 vendor_radiotap_align;
+	u8 vendor_radiotap_oui[3];
+	u8 vendor_radiotap_subns;
 };
 
 /**
@@ -794,6 +895,8 @@ enum ieee80211_conf_flags {
  * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed
  * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed
  * @IEEE80211_CONF_CHANGE_SMPS: Spatial multiplexing powersave mode changed
+ *	Note that this is only valid if channel contexts are not used,
+ *	otherwise each channel context has the number of chains listed.
  */
 enum ieee80211_conf_changed {
 	IEEE80211_CONF_CHANGE_SMPS		= BIT(1),
@@ -845,7 +948,8 @@ enum ieee80211_smps_mode {
  *	powersave documentation below. This variable is valid only when
  *	the CONF_PS flag is set.
  *
- * @power_level: requested transmit power (in dBm)
+ * @power_level: requested transmit power (in dBm), backward compatibility
+ *	value only that is set to the minimum of all interfaces
  *
  * @channel: the channel to tune to
  * @channel_type: the channel (HT) type
@@ -859,7 +963,9 @@ enum ieee80211_smps_mode {
  *
  * @smps_mode: spatial multiplexing powersave mode; note that
  *	%IEEE80211_SMPS_STATIC is used when the device is not
- *	configured for an HT channel
+ *	configured for an HT channel.
+ *	Note that this is only valid if channel contexts are not used,
+ *	otherwise each channel context has the number of chains listed.
  */
 struct ieee80211_conf {
 	u32 flags;
@@ -931,6 +1037,11 @@ enum ieee80211_vif_flags {
  *	at runtime, mac80211 will never touch this field
  * @hw_queue: hardware queue for each AC
  * @cab_queue: content-after-beacon (DTIM beacon really) queue, AP mode only
+ * @chanctx_conf: The channel context this interface is assigned to, or %NULL
+ *	when it is not assigned. This pointer is RCU-protected due to the TX
+ *	path needing to access it; even though the netdev carrier will always
+ *	be off when it is %NULL there can still be races and packets could be
+ *	processed after it switches back to %NULL.
  * @drv_priv: data area for driver use, will always be aligned to
  *	sizeof(void *).
  */
@@ -943,6 +1054,8 @@ struct ieee80211_vif {
 	u8 cab_queue;
 	u8 hw_queue[IEEE80211_NUM_ACS];
 
+	struct ieee80211_chanctx_conf __rcu *chanctx_conf;
+
 	u32 driver_flags;
 
 	/* must be last */
@@ -1076,6 +1189,8 @@ enum ieee80211_sta_state {
  * @aid: AID we assigned to the station if we're an AP
  * @supp_rates: Bitmap of supported rates (per band)
  * @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities
+ * @vht_cap: VHT capabilities of this STA; Not restricting any capabilities
+ * 	of remote STA. Taking as is.
  * @wme: indicates whether the STA supports WME. Only valid during AP-mode.
  * @drv_priv: data area for driver use, will always be aligned to
  *	sizeof(void *), size is determined in hw information.
@@ -1088,6 +1203,7 @@ struct ieee80211_sta {
 	u8 addr[ETH_ALEN];
 	u16 aid;
 	struct ieee80211_sta_ht_cap ht_cap;
+	struct ieee80211_sta_vht_cap vht_cap;
 	bool wme;
 	u8 uapsd_queues;
 	u8 max_sp;
@@ -1325,6 +1441,8 @@ enum ieee80211_hw_flags {
  *	within &struct ieee80211_vif.
  * @sta_data_size: size (in bytes) of the drv_priv data area
  *	within &struct ieee80211_sta.
+ * @chanctx_data_size: size (in bytes) of the drv_priv data area
+ *	within &struct ieee80211_chanctx_conf.
  *
  * @max_rates: maximum number of alternate rate retry stages the hw
  *	can handle.
@@ -1369,6 +1487,7 @@ struct ieee80211_hw {
 	int channel_change_time;
 	int vif_data_size;
 	int sta_data_size;
+	int chanctx_data_size;
 	int napi_weight;
 	u16 queues;
 	u16 max_listen_interval;
@@ -2126,6 +2245,14 @@ enum ieee80211_rate_control_changed {
  * @sta_remove: Notifies low level driver about removal of an associated
  *	station, AP, IBSS/WDS/mesh peer etc. This callback can sleep.
  *
+ * @sta_add_debugfs: Drivers can use this callback to add debugfs files
+ *	when a station is added to mac80211's station list. This callback
+ *	and @sta_remove_debugfs should be within a CONFIG_MAC80211_DEBUGFS
+ *	conditional. This callback can sleep.
+ *
+ * @sta_remove_debugfs: Remove the debugfs files which were added using
+ *	@sta_add_debugfs. This callback can sleep.
+ *
  * @sta_notify: Notifies low level driver about power state transition of an
  *	associated station, AP,  IBSS/WDS/mesh peer etc. For a VIF operating
  *	in AP mode, this callback will not be called when the flag
@@ -2317,6 +2444,27 @@ enum ieee80211_rate_control_changed {
  *	The callback will be called before each transmission and upon return
  *	mac80211 will transmit the frame right away.
  *	The callback is optional and can (should!) sleep.
+ *
+ * @add_chanctx: Notifies device driver about new channel context creation.
+ * @remove_chanctx: Notifies device driver about channel context destruction.
+ * @change_chanctx: Notifies device driver about channel context changes that
+ *	may happen when combining different virtual interfaces on the same
+ *	channel context with different settings
+ * @assign_vif_chanctx: Notifies device driver about channel context being bound
+ *	to vif. Possible use is for hw queue remapping.
+ * @unassign_vif_chanctx: Notifies device driver about channel context being
+ *	unbound from vif.
+ * @start_ap: Start operation on the AP interface, this is called after all the
+ *	information in bss_conf is set and beacon can be retrieved. A channel
+ *	context is bound before this is called. Note that if the driver uses
+ *	software scan or ROC, this (and @stop_ap) isn't called when the AP is
+ *	just "paused" for scanning/ROC, which is indicated by the beacon being
+ *	disabled/enabled via @bss_info_changed.
+ * @stop_ap: Stop operation on the AP interface.
+ *
+ * @restart_complete: Called after a call to ieee80211_restart_hw(), when the
+ *	reconfiguration has completed. This can help the driver implement the
+ *	reconfiguration step. This callback may sleep.
  */
 struct ieee80211_ops {
 	void (*tx)(struct ieee80211_hw *hw,
@@ -2342,6 +2490,9 @@ struct ieee80211_ops {
 				 struct ieee80211_bss_conf *info,
 				 u32 changed);
 
+	int (*start_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+	void (*stop_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+
 	u64 (*prepare_multicast)(struct ieee80211_hw *hw,
 				 struct netdev_hw_addr_list *mc_list);
 	void (*configure_filter)(struct ieee80211_hw *hw,
@@ -2383,6 +2534,16 @@ struct ieee80211_ops {
 		       struct ieee80211_sta *sta);
 	int (*sta_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			  struct ieee80211_sta *sta);
+#ifdef CONFIG_MAC80211_DEBUGFS
+	void (*sta_add_debugfs)(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				struct ieee80211_sta *sta,
+				struct dentry *dir);
+	void (*sta_remove_debugfs)(struct ieee80211_hw *hw,
+				   struct ieee80211_vif *vif,
+				   struct ieee80211_sta *sta,
+				   struct dentry *dir);
+#endif
 	void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			enum sta_notify_cmd, struct ieee80211_sta *sta);
 	int (*sta_state)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
@@ -2424,8 +2585,8 @@ struct ieee80211_ops {
 	int (*get_antenna)(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
 
 	int (*remain_on_channel)(struct ieee80211_hw *hw,
+				 struct ieee80211_vif *vif,
 				 struct ieee80211_channel *chan,
-				 enum nl80211_channel_type channel_type,
 				 int duration);
 	int (*cancel_remain_on_channel)(struct ieee80211_hw *hw);
 	int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx);
@@ -2461,6 +2622,22 @@ struct ieee80211_ops {
 
 	void	(*mgd_prepare_tx)(struct ieee80211_hw *hw,
 				  struct ieee80211_vif *vif);
+
+	int (*add_chanctx)(struct ieee80211_hw *hw,
+			   struct ieee80211_chanctx_conf *ctx);
+	void (*remove_chanctx)(struct ieee80211_hw *hw,
+			       struct ieee80211_chanctx_conf *ctx);
+	void (*change_chanctx)(struct ieee80211_hw *hw,
+			       struct ieee80211_chanctx_conf *ctx,
+			       u32 changed);
+	int (*assign_vif_chanctx)(struct ieee80211_hw *hw,
+				  struct ieee80211_vif *vif,
+				  struct ieee80211_chanctx_conf *ctx);
+	void (*unassign_vif_chanctx)(struct ieee80211_hw *hw,
+				     struct ieee80211_vif *vif,
+				     struct ieee80211_chanctx_conf *ctx);
+
+	void (*restart_complete)(struct ieee80211_hw *hw);
 };
 
 /**
@@ -3145,6 +3322,19 @@ void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
 			    struct sk_buff *skb, u8 *p2k);
 
 /**
+ * ieee80211_aes_cmac_calculate_k1_k2 - calculate the AES-CMAC sub keys
+ *
+ * This function computes the two AES-CMAC sub-keys, based on the
+ * previously installed master key.
+ *
+ * @keyconf: the parameter passed with the set key
+ * @k1: a buffer to be filled with the 1st sub-key
+ * @k2: a buffer to be filled with the 2nd sub-key
+ */
+void ieee80211_aes_cmac_calculate_k1_k2(struct ieee80211_key_conf *keyconf,
+					u8 *k1, u8 *k2);
+
+/**
  * struct ieee80211_key_seq - key sequence counter
  *
  * @tkip: TKIP data, containing IV32 and IV16 in host byte order
@@ -3294,6 +3484,21 @@ void ieee80211_sched_scan_results(struct ieee80211_hw *hw);
 void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw);
 
 /**
+ * enum ieee80211_interface_iteration_flags - interface iteration flags
+ * @IEEE80211_IFACE_ITER_NORMAL: Iterate over all interfaces that have
+ *	been added to the driver; However, note that during hardware
+ *	reconfiguration (after restart_hw) it will iterate over a new
+ *	interface and over all the existing interfaces even if they
+ *	haven't been re-added to the driver yet.
+ * @IEEE80211_IFACE_ITER_RESUME_ALL: During resume, iterate over all
+ *	interfaces, even if they haven't been re-added to the driver yet.
+ */
+enum ieee80211_interface_iteration_flags {
+	IEEE80211_IFACE_ITER_NORMAL	= 0,
+	IEEE80211_IFACE_ITER_RESUME_ALL	= BIT(0),
+};
+
+/**
  * ieee80211_iterate_active_interfaces - iterate active interfaces
  *
  * This function iterates over the interfaces associated with a given
@@ -3301,13 +3506,15 @@ void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw);
  * This function allows the iterator function to sleep, when the iterator
  * function is atomic @ieee80211_iterate_active_interfaces_atomic can
  * be used.
- * Does not iterate over a new interface during add_interface()
+ * Does not iterate over a new interface during add_interface().
  *
  * @hw: the hardware struct of which the interfaces should be iterated over
+ * @iter_flags: iteration flags, see &enum ieee80211_interface_iteration_flags
  * @iterator: the iterator function to call
  * @data: first argument of the iterator function
  */
 void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw,
+					 u32 iter_flags,
 					 void (*iterator)(void *data, u8 *mac,
 						struct ieee80211_vif *vif),
 					 void *data);
@@ -3319,13 +3526,15 @@ void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw,
  * hardware that are currently active and calls the callback for them.
  * This function requires the iterator callback function to be atomic,
  * if that is not desired, use @ieee80211_iterate_active_interfaces instead.
- * Does not iterate over a new interface during add_interface()
+ * Does not iterate over a new interface during add_interface().
  *
  * @hw: the hardware struct of which the interfaces should be iterated over
+ * @iter_flags: iteration flags, see &enum ieee80211_interface_iteration_flags
  * @iterator: the iterator function to call, cannot sleep
  * @data: first argument of the iterator function
  */
 void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw,
+						u32 iter_flags,
 						void (*iterator)(void *data,
 						    u8 *mac,
 						    struct ieee80211_vif *vif),
@@ -3524,6 +3733,27 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
 			 void *iter_data);
 
 /**
+ * ieee80211_iter_chan_contexts_atomic - iterate channel contexts
+ * @hw: pointre obtained from ieee80211_alloc_hw().
+ * @iter: iterator function
+ * @iter_data: data passed to iterator function
+ *
+ * Iterate all active channel contexts. This function is atomic and
+ * doesn't acquire any locks internally that might be held in other
+ * places while calling into the driver.
+ *
+ * The iterator will not find a context that's being added (during
+ * the driver callback to add it) but will find it while it's being
+ * removed.
+ */
+void ieee80211_iter_chan_contexts_atomic(
+	struct ieee80211_hw *hw,
+	void (*iter)(struct ieee80211_hw *hw,
+		     struct ieee80211_chanctx_conf *chanctx_conf,
+		     void *data),
+	void *iter_data);
+
+/**
  * ieee80211_ap_probereq_get - retrieve a Probe Request template
  * @hw: pointer obtained from ieee80211_alloc_hw().
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 95e6466..de644bc 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -23,6 +23,7 @@
 #endif
 #include <net/netns/xfrm.h>
 
+struct user_namespace;
 struct proc_dir_entry;
 struct net_device;
 struct sock;
@@ -53,6 +54,10 @@ struct net {
 	struct list_head	cleanup_list;	/* namespaces on death row */
 	struct list_head	exit_list;	/* Use only net_mutex */
 
+	struct user_namespace   *user_ns;	/* Owning user namespace */
+
+	unsigned int		proc_inum;
+
 	struct proc_dir_entry 	*proc_net;
 	struct proc_dir_entry 	*proc_net_stat;
 
@@ -126,16 +131,21 @@ struct net {
 /* Init's network namespace */
 extern struct net init_net;
 
-#ifdef CONFIG_NET
-extern struct net *copy_net_ns(unsigned long flags, struct net *net_ns);
-
-#else /* CONFIG_NET */
-static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns)
+#ifdef CONFIG_NET_NS
+extern struct net *copy_net_ns(unsigned long flags,
+	struct user_namespace *user_ns, struct net *old_net);
+
+#else /* CONFIG_NET_NS */
+#include <linux/sched.h>
+#include <linux/nsproxy.h>
+static inline struct net *copy_net_ns(unsigned long flags,
+	struct user_namespace *user_ns, struct net *old_net)
 {
-	/* There is nothing to copy so this is a noop */
-	return net_ns;
+	if (flags & CLONE_NEWNET)
+		return ERR_PTR(-EINVAL);
+	return old_net;
 }
-#endif /* CONFIG_NET */
+#endif /* CONFIG_NET_NS */
 
 
 extern struct list_head net_namespace_list;
diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
index 5e5eb1f..3573a81 100644
--- a/include/net/netns/sctp.h
+++ b/include/net/netns/sctp.h
@@ -62,6 +62,9 @@ struct netns_sctp {
 	/* Whether Cookie Preservative is enabled(1) or not(0) */
 	int cookie_preserve_enable;
 
+	/* The namespace default hmac alg */
+	char *sctp_hmac_alg;
+
 	/* Valid.Cookie.Life	    - 60  seconds  */
 	unsigned int valid_cookie_life;
 
diff --git a/include/net/netprio_cgroup.h b/include/net/netprio_cgroup.h
index 2760f4f..1d04b6f 100644
--- a/include/net/netprio_cgroup.h
+++ b/include/net/netprio_cgroup.h
@@ -27,7 +27,6 @@ struct netprio_map {
 
 struct cgroup_netprio_state {
 	struct cgroup_subsys_state css;
-	u32 prioidx;
 };
 
 extern void sock_update_netprioidx(struct sock *sk, struct task_struct *task);
@@ -36,13 +35,12 @@ extern void sock_update_netprioidx(struct sock *sk, struct task_struct *task);
 
 static inline u32 task_netprioidx(struct task_struct *p)
 {
-	struct cgroup_netprio_state *state;
+	struct cgroup_subsys_state *css;
 	u32 idx;
 
 	rcu_read_lock();
-	state = container_of(task_subsys_state(p, net_prio_subsys_id),
-			     struct cgroup_netprio_state, css);
-	idx = state->prioidx;
+	css = task_subsys_state(p, net_prio_subsys_id);
+	idx = css->cgroup->id;
 	rcu_read_unlock();
 	return idx;
 }
@@ -57,8 +55,7 @@ static inline u32 task_netprioidx(struct task_struct *p)
 	rcu_read_lock();
 	css = task_subsys_state(p, net_prio_subsys_id);
 	if (css)
-		idx = container_of(css,
-				   struct cgroup_netprio_state, css)->prioidx;
+		idx = css->cgroup->id;
 	rcu_read_unlock();
 	return idx;
 }
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
index e900072..671953e 100644
--- a/include/net/nfc/hci.h
+++ b/include/net/nfc/hci.h
@@ -24,6 +24,12 @@
 
 #include <net/nfc/nfc.h>
 
+struct nfc_phy_ops {
+	int (*write)(void *dev_id, struct sk_buff *skb);
+	int (*enable)(void *dev_id);
+	void (*disable)(void *dev_id);
+};
+
 struct nfc_hci_dev;
 
 struct nfc_hci_ops {
@@ -38,15 +44,21 @@ struct nfc_hci_ops {
 	int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb);
 	int (*start_poll) (struct nfc_hci_dev *hdev,
 			   u32 im_protocols, u32 tm_protocols);
+	int (*dep_link_up)(struct nfc_hci_dev *hdev, struct nfc_target *target,
+			   u8 comm_mode, u8 *gb, size_t gb_len);
+	int (*dep_link_down)(struct nfc_hci_dev *hdev);
 	int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate,
 				 struct nfc_target *target);
 	int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate,
 					   struct nfc_target *target);
-	int (*data_exchange) (struct nfc_hci_dev *hdev,
+	int (*im_transceive) (struct nfc_hci_dev *hdev,
 			      struct nfc_target *target, struct sk_buff *skb,
 			      data_exchange_cb_t cb, void *cb_context);
+	int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb);
 	int (*check_presence)(struct nfc_hci_dev *hdev,
 			      struct nfc_target *target);
+	void (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event,
+				struct sk_buff *skb);
 };
 
 /* Pipes */
@@ -114,6 +126,9 @@ struct nfc_hci_dev {
 	int async_cb_type;
 	data_exchange_cb_t async_cb;
 	void *async_cb_context;
+
+	u8 *gb;
+	size_t gb_len;
 };
 
 /* hci device allocation */
@@ -134,6 +149,8 @@ void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev);
 
 void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err);
 
+int nfc_hci_result_to_errno(u8 result);
+
 /* Host IDs */
 #define NFC_HCI_HOST_CONTROLLER_ID	0x00
 #define NFC_HCI_TERMINAL_HOST_ID	0x01
@@ -219,5 +236,7 @@ int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 gate, u8 response,
 			  const u8 *param, size_t param_len);
 int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event,
 		       const u8 *param, size_t param_len);
+int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate);
+u32 nfc_hci_sak_to_protocol(u8 sak);
 
 #endif /* __NET_HCI_H */
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index f05b106..fce80b2 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -95,7 +95,7 @@ struct nfc_genl_data {
 };
 
 struct nfc_dev {
-	unsigned int idx;
+	int idx;
 	u32 target_next_idx;
 	struct nfc_target *targets;
 	int n_targets;
diff --git a/include/net/protocol.h b/include/net/protocol.h
index 929528c..047c047 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -25,9 +25,11 @@
 #define _PROTOCOL_H
 
 #include <linux/in6.h>
+#include <linux/skbuff.h>
 #if IS_ENABLED(CONFIG_IPV6)
 #include <linux/ipv6.h>
 #endif
+#include <linux/netdevice.h>
 
 /* This is one larger than the largest protocol value that can be
  * found in an ipv4 or ipv6 header.  Since in both cases the protocol
@@ -40,12 +42,6 @@ struct net_protocol {
 	void			(*early_demux)(struct sk_buff *skb);
 	int			(*handler)(struct sk_buff *skb);
 	void			(*err_handler)(struct sk_buff *skb, u32 info);
-	int			(*gso_send_check)(struct sk_buff *skb);
-	struct sk_buff	       *(*gso_segment)(struct sk_buff *skb,
-					       netdev_features_t features);
-	struct sk_buff	      **(*gro_receive)(struct sk_buff **head,
-					       struct sk_buff *skb);
-	int			(*gro_complete)(struct sk_buff *skb);
 	unsigned int		no_policy:1,
 				netns_ok:1;
 };
@@ -60,23 +56,20 @@ struct inet6_protocol {
 			       struct inet6_skb_parm *opt,
 			       u8 type, u8 code, int offset,
 			       __be32 info);
-
-	int	(*gso_send_check)(struct sk_buff *skb);
-	struct sk_buff *(*gso_segment)(struct sk_buff *skb,
-				       netdev_features_t features);
-	struct sk_buff **(*gro_receive)(struct sk_buff **head,
-					struct sk_buff *skb);
-	int	(*gro_complete)(struct sk_buff *skb);
-
 	unsigned int	flags;	/* INET6_PROTO_xxx */
 };
 
 #define INET6_PROTO_NOPOLICY	0x1
 #define INET6_PROTO_FINAL	0x2
-/* This should be set for any extension header which is compatible with GSO. */
-#define INET6_PROTO_GSO_EXTHDR	0x4
 #endif
 
+struct net_offload {
+	struct offload_callbacks callbacks;
+	unsigned int		 flags;	/* Flags used by IPv6 for now */
+};
+/* This should be set for any extension header which is compatible with GSO. */
+#define INET6_PROTO_GSO_EXTHDR	0x1
+
 /* This is used to register socket interfaces for IP protocols.  */
 struct inet_protosw {
 	struct list_head list;
@@ -96,6 +89,8 @@ struct inet_protosw {
 #define INET_PROTOSW_ICSK      0x04  /* Is this an inet_connection_sock? */
 
 extern const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS];
+extern const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS];
+extern const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS];
 
 #if IS_ENABLED(CONFIG_IPV6)
 extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS];
@@ -103,6 +98,8 @@ extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS];
 
 extern int	inet_add_protocol(const struct net_protocol *prot, unsigned char num);
 extern int	inet_del_protocol(const struct net_protocol *prot, unsigned char num);
+extern int	inet_add_offload(const struct net_offload *prot, unsigned char num);
+extern int	inet_del_offload(const struct net_offload *prot, unsigned char num);
 extern void	inet_register_protosw(struct inet_protosw *p);
 extern void	inet_unregister_protosw(struct inet_protosw *p);
 
@@ -112,5 +109,7 @@ extern int	inet6_del_protocol(const struct inet6_protocol *prot, unsigned char n
 extern int	inet6_register_protosw(struct inet_protosw *p);
 extern void	inet6_unregister_protosw(struct inet_protosw *p);
 #endif
+extern int	inet6_add_offload(const struct net_offload *prot, unsigned char num);
+extern int	inet6_del_offload(const struct net_offload *prot, unsigned char num);
 
 #endif	/* _PROTOCOL_H */
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index b01d8dd..a51dbd1 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -49,13 +49,16 @@ struct request_sock_ops {
 					   struct request_sock *req);
 };
 
+extern int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req);
+
 /* struct request_sock - mini sock to represent a connection request
  */
 struct request_sock {
 	struct request_sock		*dl_next; /* Must be first member! */
 	u16				mss;
-	u8				retrans;
-	u8				cookie_ts; /* syncookie: encode tcpopts in timestamp */
+	u8				num_retrans; /* number of retransmits */
+	u8				cookie_ts:1; /* syncookie: encode tcpopts in timestamp */
+	u8				num_timeout:7; /* number of timeouts */
 	/* The following two fields can be easily recomputed I think -AK */
 	u32				window_clamp; /* window clamp at creation time */
 	u32				rcv_wnd;	  /* rcv_wnd offered first time */
@@ -231,7 +234,7 @@ static inline int reqsk_queue_removed(struct request_sock_queue *queue,
 {
 	struct listen_sock *lopt = queue->listen_opt;
 
-	if (req->retrans == 0)
+	if (req->num_timeout == 0)
 		--lopt->qlen_young;
 
 	return --lopt->qlen;
@@ -269,7 +272,8 @@ static inline void reqsk_queue_hash_req(struct request_sock_queue *queue,
 	struct listen_sock *lopt = queue->listen_opt;
 
 	req->expires = jiffies + timeout;
-	req->retrans = 0;
+	req->num_retrans = 0;
+	req->num_timeout = 0;
 	req->sk = NULL;
 	req->dl_next = lopt->syn_table[hash];
 
diff --git a/include/net/route.h b/include/net/route.h
index bc40b63..2ea40c1 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -198,10 +198,13 @@ struct in_ifaddr;
 extern void fib_add_ifaddr(struct in_ifaddr *);
 extern void fib_del_ifaddr(struct in_ifaddr *, struct in_ifaddr *);
 
-static inline void ip_rt_put(struct rtable * rt)
+static inline void ip_rt_put(struct rtable *rt)
 {
-	if (rt)
-		dst_release(&rt->dst);
+	/* dst_release() accepts a NULL parameter.
+	 * We rely on dst being first structure in struct rtable
+	 */
+	BUILD_BUG_ON(offsetof(struct rtable, dst) != 0);
+	dst_release(&rt->dst);
 }
 
 #define IPTOS_RT_MASK	(IPTOS_TOS_MASK & ~3)
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index 712b3be..3524727 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -130,8 +130,6 @@ typedef union {
 	__be16 err;
 	sctp_state_t state;
 	sctp_event_timeout_t to;
-	unsigned long zero;
-	void *ptr;
 	struct sctp_chunk *chunk;
 	struct sctp_association *asoc;
 	struct sctp_transport *transport;
@@ -154,23 +152,15 @@ typedef union {
  * which takes an __s32 and returns a sctp_arg_t containing the
  * __s32.  So, after foo = SCTP_I32(arg), foo.i32 == arg.
  */
-static inline sctp_arg_t SCTP_NULL(void)
-{
-	sctp_arg_t retval; retval.ptr = NULL; return retval;
-}
-static inline sctp_arg_t SCTP_NOFORCE(void)
-{
-	sctp_arg_t retval = {.zero = 0UL}; retval.i32 = 0; return retval;
-}
-static inline sctp_arg_t SCTP_FORCE(void)
-{
-	sctp_arg_t retval = {.zero = 0UL}; retval.i32 = 1; return retval;
-}
 
 #define SCTP_ARG_CONSTRUCTOR(name, type, elt) \
 static inline sctp_arg_t	\
 SCTP_## name (type arg)		\
-{ sctp_arg_t retval = {.zero = 0UL}; retval.elt = arg; return retval; }
+{ sctp_arg_t retval;\
+  memset(&retval, 0, sizeof(sctp_arg_t));\
+  retval.elt = arg;\
+  return retval;\
+}
 
 SCTP_ARG_CONSTRUCTOR(I32,	__s32, i32)
 SCTP_ARG_CONSTRUCTOR(U32,	__u32, u32)
@@ -181,7 +171,6 @@ SCTP_ARG_CONSTRUCTOR(ERROR,     int, error)
 SCTP_ARG_CONSTRUCTOR(PERR,      __be16, err)	/* protocol error */
 SCTP_ARG_CONSTRUCTOR(STATE,	sctp_state_t, state)
 SCTP_ARG_CONSTRUCTOR(TO,	sctp_event_timeout_t, to)
-SCTP_ARG_CONSTRUCTOR(PTR,	void *, ptr)
 SCTP_ARG_CONSTRUCTOR(CHUNK,	struct sctp_chunk *, chunk)
 SCTP_ARG_CONSTRUCTOR(ASOC,	struct sctp_association *, asoc)
 SCTP_ARG_CONSTRUCTOR(TRANSPORT,	struct sctp_transport *, transport)
@@ -192,6 +181,23 @@ SCTP_ARG_CONSTRUCTOR(PACKET,	struct sctp_packet *, packet)
 SCTP_ARG_CONSTRUCTOR(SACKH,	sctp_sackhdr_t *, sackh)
 SCTP_ARG_CONSTRUCTOR(DATAMSG,	struct sctp_datamsg *, msg)
 
+static inline sctp_arg_t SCTP_FORCE(void)
+{
+	return SCTP_I32(1);
+}
+
+static inline sctp_arg_t SCTP_NOFORCE(void)
+{
+	return SCTP_I32(0);
+}
+
+static inline sctp_arg_t SCTP_NULL(void)
+{
+	sctp_arg_t retval;
+	memset(&retval, 0, sizeof(sctp_arg_t));
+	return retval;
+}
+
 typedef struct {
 	sctp_arg_t obj;
 	sctp_verb_t verb;
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index d053d2e..c29707d 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -312,14 +312,6 @@ enum { SCTP_MAX_GABS = 16 };
 				 * functions simpler to write.
 				 */
 
-#if defined (CONFIG_SCTP_HMAC_MD5)
-#define SCTP_COOKIE_HMAC_ALG "hmac(md5)"
-#elif defined (CONFIG_SCTP_HMAC_SHA1)
-#define SCTP_COOKIE_HMAC_ALG "hmac(sha1)"
-#else
-#define SCTP_COOKIE_HMAC_ALG NULL
-#endif
-
 /* These return values describe the success or failure of a number of
  * routines which form the lower interface to SCTP_outqueue.
  */
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index b5887e1..2a82d13 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -234,6 +234,8 @@ struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *,
 struct sctp_chunk *sctp_make_violation_paramlen(const struct sctp_association *,
 				   const struct sctp_chunk *,
 				   struct sctp_paramhdr *);
+struct sctp_chunk *sctp_make_violation_max_retrans(const struct sctp_association *,
+						   const struct sctp_chunk *);
 struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *,
 				  const struct sctp_transport *);
 struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *,
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 64158aa..2b2f61d 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -177,6 +177,7 @@ struct sctp_sock {
 
 	/* Access to HMAC transform. */
 	struct crypto_hash *hmac;
+	char *sctp_hmac_alg;
 
 	/* What is our base endpointer? */
 	struct sctp_endpoint *ep;
diff --git a/include/net/sctp/ulpqueue.h b/include/net/sctp/ulpqueue.h
index 2e5ee0d..ff1b8ba7 100644
--- a/include/net/sctp/ulpqueue.h
+++ b/include/net/sctp/ulpqueue.h
@@ -72,7 +72,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *, struct sctp_ulpevent *ev);
 void sctp_ulpq_renege(struct sctp_ulpq *, struct sctp_chunk *, gfp_t);
 
 /* Perform partial delivery. */
-void sctp_ulpq_partial_delivery(struct sctp_ulpq *, struct sctp_chunk *, gfp_t);
+void sctp_ulpq_partial_delivery(struct sctp_ulpq *, gfp_t);
 
 /* Abort the partial delivery. */
 void sctp_ulpq_abort_pd(struct sctp_ulpq *, gfp_t);
diff --git a/include/net/sock.h b/include/net/sock.h
index c945fba..a95e075 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -213,7 +213,7 @@ struct cg_proto;
   *	@sk_sndbuf: size of send buffer in bytes
   *	@sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE,
   *		   %SO_OOBINLINE settings, %SO_TIMESTAMPING settings
-  *	@sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets
+  *	@sk_no_check: %SO_NO_CHECK setting, whether or not checkup packets
   *	@sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)
   *	@sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK)
   *	@sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 6feeccd..3202bde 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -369,7 +369,6 @@ extern void tcp_shutdown (struct sock *sk, int how);
 extern void tcp_v4_early_demux(struct sk_buff *skb);
 extern int tcp_v4_rcv(struct sk_buff *skb);
 
-extern struct inet_peer *tcp_v4_get_peer(struct sock *sk);
 extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
 extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 		       size_t size);
diff --git a/include/rdma/Kbuild b/include/rdma/Kbuild
index ea56f76..e69de29 100644
--- a/include/rdma/Kbuild
+++ b/include/rdma/Kbuild
@@ -1,6 +0,0 @@
-header-y += ib_user_cm.h
-header-y += ib_user_mad.h
-header-y += ib_user_sa.h
-header-y += ib_user_verbs.h
-header-y += rdma_netlink.h
-header-y += rdma_user_cm.h
diff --git a/include/rdma/ib_user_cm.h b/include/rdma/ib_user_cm.h
deleted file mode 100644
index f79014a..0000000
--- a/include/rdma/ib_user_cm.h
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (c) 2005 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Intel Corporation.  All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef IB_USER_CM_H
-#define IB_USER_CM_H
-
-#include <linux/types.h>
-#include <rdma/ib_user_sa.h>
-
-#define IB_USER_CM_ABI_VERSION 5
-
-enum {
-	IB_USER_CM_CMD_CREATE_ID,
-	IB_USER_CM_CMD_DESTROY_ID,
-	IB_USER_CM_CMD_ATTR_ID,
-
-	IB_USER_CM_CMD_LISTEN,
-	IB_USER_CM_CMD_NOTIFY,
-
-	IB_USER_CM_CMD_SEND_REQ,
-	IB_USER_CM_CMD_SEND_REP,
-	IB_USER_CM_CMD_SEND_RTU,
-	IB_USER_CM_CMD_SEND_DREQ,
-	IB_USER_CM_CMD_SEND_DREP,
-	IB_USER_CM_CMD_SEND_REJ,
-	IB_USER_CM_CMD_SEND_MRA,
-	IB_USER_CM_CMD_SEND_LAP,
-	IB_USER_CM_CMD_SEND_APR,
-	IB_USER_CM_CMD_SEND_SIDR_REQ,
-	IB_USER_CM_CMD_SEND_SIDR_REP,
-
-	IB_USER_CM_CMD_EVENT,
-	IB_USER_CM_CMD_INIT_QP_ATTR,
-};
-/*
- * command ABI structures.
- */
-struct ib_ucm_cmd_hdr {
-	__u32 cmd;
-	__u16 in;
-	__u16 out;
-};
-
-struct ib_ucm_create_id {
-	__u64 uid;
-	__u64 response;
-};
-
-struct ib_ucm_create_id_resp {
-	__u32 id;
-};
-
-struct ib_ucm_destroy_id {
-	__u64 response;
-	__u32 id;
-	__u32 reserved;
-};
-
-struct ib_ucm_destroy_id_resp {
-	__u32 events_reported;
-};
-
-struct ib_ucm_attr_id {
-	__u64 response;
-	__u32 id;
-	__u32 reserved;
-};
-
-struct ib_ucm_attr_id_resp {
-	__be64 service_id;
-	__be64 service_mask;
-	__be32 local_id;
-	__be32 remote_id;
-};
-
-struct ib_ucm_init_qp_attr {
-	__u64 response;
-	__u32 id;
-	__u32 qp_state;
-};
-
-struct ib_ucm_listen {
-	__be64 service_id;
-	__be64 service_mask;
-	__u32 id;
-	__u32 reserved;
-};
-
-struct ib_ucm_notify {
-	__u32 id;
-	__u32 event;
-};
-
-struct ib_ucm_private_data {
-	__u64 data;
-	__u32 id;
-	__u8  len;
-	__u8  reserved[3];
-};
-
-struct ib_ucm_req {
-	__u32 id;
-	__u32 qpn;
-	__u32 qp_type;
-	__u32 psn;
-	__be64 sid;
-	__u64 data;
-	__u64 primary_path;
-	__u64 alternate_path;
-	__u8  len;
-	__u8  peer_to_peer;
-	__u8  responder_resources;
-	__u8  initiator_depth;
-	__u8  remote_cm_response_timeout;
-	__u8  flow_control;
-	__u8  local_cm_response_timeout;
-	__u8  retry_count;
-	__u8  rnr_retry_count;
-	__u8  max_cm_retries;
-	__u8  srq;
-	__u8  reserved[5];
-};
-
-struct ib_ucm_rep {
-	__u64 uid;
-	__u64 data;
-	__u32 id;
-	__u32 qpn;
-	__u32 psn;
-	__u8  len;
-	__u8  responder_resources;
-	__u8  initiator_depth;
-	__u8  target_ack_delay;
-	__u8  failover_accepted;
-	__u8  flow_control;
-	__u8  rnr_retry_count;
-	__u8  srq;
-	__u8  reserved[4];
-};
-
-struct ib_ucm_info {
-	__u32 id;
-	__u32 status;
-	__u64 info;
-	__u64 data;
-	__u8  info_len;
-	__u8  data_len;
-	__u8  reserved[6];
-};
-
-struct ib_ucm_mra {
-	__u64 data;
-	__u32 id;
-	__u8  len;
-	__u8  timeout;
-	__u8  reserved[2];
-};
-
-struct ib_ucm_lap {
-	__u64 path;
-	__u64 data;
-	__u32 id;
-	__u8  len;
-	__u8  reserved[3];
-};
-
-struct ib_ucm_sidr_req {
-	__u32 id;
-	__u32 timeout;
-	__be64 sid;
-	__u64 data;
-	__u64 path;
-	__u16 reserved_pkey;
-	__u8  len;
-	__u8  max_cm_retries;
-	__u8  reserved[4];
-};
-
-struct ib_ucm_sidr_rep {
-	__u32 id;
-	__u32 qpn;
-	__u32 qkey;
-	__u32 status;
-	__u64 info;
-	__u64 data;
-	__u8  info_len;
-	__u8  data_len;
-	__u8  reserved[6];
-};
-/*
- * event notification ABI structures.
- */
-struct ib_ucm_event_get {
-	__u64 response;
-	__u64 data;
-	__u64 info;
-	__u8  data_len;
-	__u8  info_len;
-	__u8  reserved[6];
-};
-
-struct ib_ucm_req_event_resp {
-	struct ib_user_path_rec primary_path;
-	struct ib_user_path_rec alternate_path;
-	__be64                 remote_ca_guid;
-	__u32                  remote_qkey;
-	__u32                  remote_qpn;
-	__u32                  qp_type;
-	__u32                  starting_psn;
-	__u8  responder_resources;
-	__u8  initiator_depth;
-	__u8  local_cm_response_timeout;
-	__u8  flow_control;
-	__u8  remote_cm_response_timeout;
-	__u8  retry_count;
-	__u8  rnr_retry_count;
-	__u8  srq;
-	__u8  port;
-	__u8  reserved[7];
-};
-
-struct ib_ucm_rep_event_resp {
-	__be64 remote_ca_guid;
-	__u32 remote_qkey;
-	__u32 remote_qpn;
-	__u32 starting_psn;
-	__u8  responder_resources;
-	__u8  initiator_depth;
-	__u8  target_ack_delay;
-	__u8  failover_accepted;
-	__u8  flow_control;
-	__u8  rnr_retry_count;
-	__u8  srq;
-	__u8  reserved[5];
-};
-
-struct ib_ucm_rej_event_resp {
-	__u32 reason;
-	/* ari in ib_ucm_event_get info field. */
-};
-
-struct ib_ucm_mra_event_resp {
-	__u8  timeout;
-	__u8  reserved[3];
-};
-
-struct ib_ucm_lap_event_resp {
-	struct ib_user_path_rec path;
-};
-
-struct ib_ucm_apr_event_resp {
-	__u32 status;
-	/* apr info in ib_ucm_event_get info field. */
-};
-
-struct ib_ucm_sidr_req_event_resp {
-	__u16 pkey;
-	__u8  port;
-	__u8  reserved;
-};
-
-struct ib_ucm_sidr_rep_event_resp {
-	__u32 status;
-	__u32 qkey;
-	__u32 qpn;
-	/* info in ib_ucm_event_get info field. */
-};
-
-#define IB_UCM_PRES_DATA      0x01
-#define IB_UCM_PRES_INFO      0x02
-#define IB_UCM_PRES_PRIMARY   0x04
-#define IB_UCM_PRES_ALTERNATE 0x08
-
-struct ib_ucm_event_resp {
-	__u64 uid;
-	__u32 id;
-	__u32 event;
-	__u32 present;
-	__u32 reserved;
-	union {
-		struct ib_ucm_req_event_resp req_resp;
-		struct ib_ucm_rep_event_resp rep_resp;
-		struct ib_ucm_rej_event_resp rej_resp;
-		struct ib_ucm_mra_event_resp mra_resp;
-		struct ib_ucm_lap_event_resp lap_resp;
-		struct ib_ucm_apr_event_resp apr_resp;
-
-		struct ib_ucm_sidr_req_event_resp sidr_req_resp;
-		struct ib_ucm_sidr_rep_event_resp sidr_rep_resp;
-
-		__u32                             send_status;
-	} u;
-};
-
-#endif /* IB_USER_CM_H */
diff --git a/include/rdma/ib_user_mad.h b/include/rdma/ib_user_mad.h
deleted file mode 100644
index d6fce1c..0000000
--- a/include/rdma/ib_user_mad.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2004 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef IB_USER_MAD_H
-#define IB_USER_MAD_H
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-/*
- * Increment this value if any changes that break userspace ABI
- * compatibility are made.
- */
-#define IB_USER_MAD_ABI_VERSION	5
-
-/*
- * Make sure that all structs defined in this file remain laid out so
- * that they pack the same way on 32-bit and 64-bit architectures (to
- * avoid incompatibility between 32-bit userspace and 64-bit kernels).
- */
-
-/**
- * ib_user_mad_hdr_old - Old version of MAD packet header without pkey_index
- * @id - ID of agent MAD received with/to be sent with
- * @status - 0 on successful receive, ETIMEDOUT if no response
- *   received (transaction ID in data[] will be set to TID of original
- *   request) (ignored on send)
- * @timeout_ms - Milliseconds to wait for response (unset on receive)
- * @retries - Number of automatic retries to attempt
- * @qpn - Remote QP number received from/to be sent to
- * @qkey - Remote Q_Key to be sent with (unset on receive)
- * @lid - Remote lid received from/to be sent to
- * @sl - Service level received with/to be sent with
- * @path_bits - Local path bits received with/to be sent with
- * @grh_present - If set, GRH was received/should be sent
- * @gid_index - Local GID index to send with (unset on receive)
- * @hop_limit - Hop limit in GRH
- * @traffic_class - Traffic class in GRH
- * @gid - Remote GID in GRH
- * @flow_label - Flow label in GRH
- */
-struct ib_user_mad_hdr_old {
-	__u32	id;
-	__u32	status;
-	__u32	timeout_ms;
-	__u32	retries;
-	__u32	length;
-	__be32	qpn;
-	__be32  qkey;
-	__be16	lid;
-	__u8	sl;
-	__u8	path_bits;
-	__u8	grh_present;
-	__u8	gid_index;
-	__u8	hop_limit;
-	__u8	traffic_class;
-	__u8	gid[16];
-	__be32	flow_label;
-};
-
-/**
- * ib_user_mad_hdr - MAD packet header
- *   This layout allows specifying/receiving the P_Key index.  To use
- *   this capability, an application must call the
- *   IB_USER_MAD_ENABLE_PKEY ioctl on the user MAD file handle before
- *   any other actions with the file handle.
- * @id - ID of agent MAD received with/to be sent with
- * @status - 0 on successful receive, ETIMEDOUT if no response
- *   received (transaction ID in data[] will be set to TID of original
- *   request) (ignored on send)
- * @timeout_ms - Milliseconds to wait for response (unset on receive)
- * @retries - Number of automatic retries to attempt
- * @qpn - Remote QP number received from/to be sent to
- * @qkey - Remote Q_Key to be sent with (unset on receive)
- * @lid - Remote lid received from/to be sent to
- * @sl - Service level received with/to be sent with
- * @path_bits - Local path bits received with/to be sent with
- * @grh_present - If set, GRH was received/should be sent
- * @gid_index - Local GID index to send with (unset on receive)
- * @hop_limit - Hop limit in GRH
- * @traffic_class - Traffic class in GRH
- * @gid - Remote GID in GRH
- * @flow_label - Flow label in GRH
- * @pkey_index - P_Key index
- */
-struct ib_user_mad_hdr {
-	__u32	id;
-	__u32	status;
-	__u32	timeout_ms;
-	__u32	retries;
-	__u32	length;
-	__be32	qpn;
-	__be32  qkey;
-	__be16	lid;
-	__u8	sl;
-	__u8	path_bits;
-	__u8	grh_present;
-	__u8	gid_index;
-	__u8	hop_limit;
-	__u8	traffic_class;
-	__u8	gid[16];
-	__be32	flow_label;
-	__u16	pkey_index;
-	__u8	reserved[6];
-};
-
-/**
- * ib_user_mad - MAD packet
- * @hdr - MAD packet header
- * @data - Contents of MAD
- *
- */
-struct ib_user_mad {
-	struct ib_user_mad_hdr hdr;
-	__u64	data[0];
-};
-
-/*
- * Earlier versions of this interface definition declared the
- * method_mask[] member as an array of __u32 but treated it as a
- * bitmap made up of longs in the kernel.  This ambiguity meant that
- * 32-bit big-endian applications that can run on both 32-bit and
- * 64-bit kernels had no consistent ABI to rely on, and 64-bit
- * big-endian applications that treated method_mask as being made up
- * of 32-bit words would have their bitmap misinterpreted.
- *
- * To clear up this confusion, we change the declaration of
- * method_mask[] to use unsigned long and handle the conversion from
- * 32-bit userspace to 64-bit kernel for big-endian systems in the
- * compat_ioctl method.  Unfortunately, to keep the structure layout
- * the same, we need the method_mask[] array to be aligned only to 4
- * bytes even when long is 64 bits, which forces us into this ugly
- * typedef.
- */
-typedef unsigned long __attribute__((aligned(4))) packed_ulong;
-#define IB_USER_MAD_LONGS_PER_METHOD_MASK (128 / (8 * sizeof (long)))
-
-/**
- * ib_user_mad_reg_req - MAD registration request
- * @id - Set by the kernel; used to identify agent in future requests.
- * @qpn - Queue pair number; must be 0 or 1.
- * @method_mask - The caller will receive unsolicited MADs for any method
- *   where @method_mask = 1.
- * @mgmt_class - Indicates which management class of MADs should be receive
- *   by the caller.  This field is only required if the user wishes to
- *   receive unsolicited MADs, otherwise it should be 0.
- * @mgmt_class_version - Indicates which version of MADs for the given
- *   management class to receive.
- * @oui: Indicates IEEE OUI when mgmt_class is a vendor class
- *   in the range from 0x30 to 0x4f. Otherwise not used.
- * @rmpp_version: If set, indicates the RMPP version used.
- *
- */
-struct ib_user_mad_reg_req {
-	__u32	id;
-	packed_ulong method_mask[IB_USER_MAD_LONGS_PER_METHOD_MASK];
-	__u8	qpn;
-	__u8	mgmt_class;
-	__u8	mgmt_class_version;
-	__u8    oui[3];
-	__u8	rmpp_version;
-};
-
-#define IB_IOCTL_MAGIC		0x1b
-
-#define IB_USER_MAD_REGISTER_AGENT	_IOWR(IB_IOCTL_MAGIC, 1, \
-					      struct ib_user_mad_reg_req)
-
-#define IB_USER_MAD_UNREGISTER_AGENT	_IOW(IB_IOCTL_MAGIC, 2, __u32)
-
-#define IB_USER_MAD_ENABLE_PKEY		_IO(IB_IOCTL_MAGIC, 3)
-
-#endif /* IB_USER_MAD_H */
diff --git a/include/rdma/ib_user_sa.h b/include/rdma/ib_user_sa.h
deleted file mode 100644
index cfc7c9b..0000000
--- a/include/rdma/ib_user_sa.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2005 Intel Corporation.  All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef IB_USER_SA_H
-#define IB_USER_SA_H
-
-#include <linux/types.h>
-
-enum {
-	IB_PATH_GMP		= 1,
-	IB_PATH_PRIMARY		= (1<<1),
-	IB_PATH_ALTERNATE	= (1<<2),
-	IB_PATH_OUTBOUND	= (1<<3),
-	IB_PATH_INBOUND		= (1<<4),
-	IB_PATH_INBOUND_REVERSE = (1<<5),
-	IB_PATH_BIDIRECTIONAL	= IB_PATH_OUTBOUND | IB_PATH_INBOUND_REVERSE
-};
-
-struct ib_path_rec_data {
-	__u32	flags;
-	__u32	reserved;
-	__u32	path_rec[16];
-};
-
-struct ib_user_path_rec {
-	__u8	dgid[16];
-	__u8	sgid[16];
-	__be16	dlid;
-	__be16	slid;
-	__u32	raw_traffic;
-	__be32	flow_label;
-	__u32	reversible;
-	__u32	mtu;
-	__be16	pkey;
-	__u8	hop_limit;
-	__u8	traffic_class;
-	__u8	numb_path;
-	__u8	sl;
-	__u8	mtu_selector;
-	__u8	rate_selector;
-	__u8	rate;
-	__u8	packet_life_time_selector;
-	__u8	packet_life_time;
-	__u8	preference;
-};
-
-#endif /* IB_USER_SA_H */
diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h
deleted file mode 100644
index 81aba3a..0000000
--- a/include/rdma/ib_user_verbs.h
+++ /dev/null
@@ -1,734 +0,0 @@
-/*
- * Copyright (c) 2005 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005, 2006 Cisco Systems.  All rights reserved.
- * Copyright (c) 2005 PathScale, Inc.  All rights reserved.
- * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef IB_USER_VERBS_H
-#define IB_USER_VERBS_H
-
-#include <linux/types.h>
-
-/*
- * Increment this value if any changes that break userspace ABI
- * compatibility are made.
- */
-#define IB_USER_VERBS_ABI_VERSION	6
-
-enum {
-	IB_USER_VERBS_CMD_GET_CONTEXT,
-	IB_USER_VERBS_CMD_QUERY_DEVICE,
-	IB_USER_VERBS_CMD_QUERY_PORT,
-	IB_USER_VERBS_CMD_ALLOC_PD,
-	IB_USER_VERBS_CMD_DEALLOC_PD,
-	IB_USER_VERBS_CMD_CREATE_AH,
-	IB_USER_VERBS_CMD_MODIFY_AH,
-	IB_USER_VERBS_CMD_QUERY_AH,
-	IB_USER_VERBS_CMD_DESTROY_AH,
-	IB_USER_VERBS_CMD_REG_MR,
-	IB_USER_VERBS_CMD_REG_SMR,
-	IB_USER_VERBS_CMD_REREG_MR,
-	IB_USER_VERBS_CMD_QUERY_MR,
-	IB_USER_VERBS_CMD_DEREG_MR,
-	IB_USER_VERBS_CMD_ALLOC_MW,
-	IB_USER_VERBS_CMD_BIND_MW,
-	IB_USER_VERBS_CMD_DEALLOC_MW,
-	IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL,
-	IB_USER_VERBS_CMD_CREATE_CQ,
-	IB_USER_VERBS_CMD_RESIZE_CQ,
-	IB_USER_VERBS_CMD_DESTROY_CQ,
-	IB_USER_VERBS_CMD_POLL_CQ,
-	IB_USER_VERBS_CMD_PEEK_CQ,
-	IB_USER_VERBS_CMD_REQ_NOTIFY_CQ,
-	IB_USER_VERBS_CMD_CREATE_QP,
-	IB_USER_VERBS_CMD_QUERY_QP,
-	IB_USER_VERBS_CMD_MODIFY_QP,
-	IB_USER_VERBS_CMD_DESTROY_QP,
-	IB_USER_VERBS_CMD_POST_SEND,
-	IB_USER_VERBS_CMD_POST_RECV,
-	IB_USER_VERBS_CMD_ATTACH_MCAST,
-	IB_USER_VERBS_CMD_DETACH_MCAST,
-	IB_USER_VERBS_CMD_CREATE_SRQ,
-	IB_USER_VERBS_CMD_MODIFY_SRQ,
-	IB_USER_VERBS_CMD_QUERY_SRQ,
-	IB_USER_VERBS_CMD_DESTROY_SRQ,
-	IB_USER_VERBS_CMD_POST_SRQ_RECV,
-	IB_USER_VERBS_CMD_OPEN_XRCD,
-	IB_USER_VERBS_CMD_CLOSE_XRCD,
-	IB_USER_VERBS_CMD_CREATE_XSRQ,
-	IB_USER_VERBS_CMD_OPEN_QP
-};
-
-/*
- * Make sure that all structs defined in this file remain laid out so
- * that they pack the same way on 32-bit and 64-bit architectures (to
- * avoid incompatibility between 32-bit userspace and 64-bit kernels).
- * Specifically:
- *  - Do not use pointer types -- pass pointers in __u64 instead.
- *  - Make sure that any structure larger than 4 bytes is padded to a
- *    multiple of 8 bytes.  Otherwise the structure size will be
- *    different between 32-bit and 64-bit architectures.
- */
-
-struct ib_uverbs_async_event_desc {
-	__u64 element;
-	__u32 event_type;	/* enum ib_event_type */
-	__u32 reserved;
-};
-
-struct ib_uverbs_comp_event_desc {
-	__u64 cq_handle;
-};
-
-/*
- * All commands from userspace should start with a __u32 command field
- * followed by __u16 in_words and out_words fields (which give the
- * length of the command block and response buffer if any in 32-bit
- * words).  The kernel driver will read these fields first and read
- * the rest of the command struct based on these value.
- */
-
-struct ib_uverbs_cmd_hdr {
-	__u32 command;
-	__u16 in_words;
-	__u16 out_words;
-};
-
-struct ib_uverbs_get_context {
-	__u64 response;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_get_context_resp {
-	__u32 async_fd;
-	__u32 num_comp_vectors;
-};
-
-struct ib_uverbs_query_device {
-	__u64 response;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_query_device_resp {
-	__u64 fw_ver;
-	__be64 node_guid;
-	__be64 sys_image_guid;
-	__u64 max_mr_size;
-	__u64 page_size_cap;
-	__u32 vendor_id;
-	__u32 vendor_part_id;
-	__u32 hw_ver;
-	__u32 max_qp;
-	__u32 max_qp_wr;
-	__u32 device_cap_flags;
-	__u32 max_sge;
-	__u32 max_sge_rd;
-	__u32 max_cq;
-	__u32 max_cqe;
-	__u32 max_mr;
-	__u32 max_pd;
-	__u32 max_qp_rd_atom;
-	__u32 max_ee_rd_atom;
-	__u32 max_res_rd_atom;
-	__u32 max_qp_init_rd_atom;
-	__u32 max_ee_init_rd_atom;
-	__u32 atomic_cap;
-	__u32 max_ee;
-	__u32 max_rdd;
-	__u32 max_mw;
-	__u32 max_raw_ipv6_qp;
-	__u32 max_raw_ethy_qp;
-	__u32 max_mcast_grp;
-	__u32 max_mcast_qp_attach;
-	__u32 max_total_mcast_qp_attach;
-	__u32 max_ah;
-	__u32 max_fmr;
-	__u32 max_map_per_fmr;
-	__u32 max_srq;
-	__u32 max_srq_wr;
-	__u32 max_srq_sge;
-	__u16 max_pkeys;
-	__u8  local_ca_ack_delay;
-	__u8  phys_port_cnt;
-	__u8  reserved[4];
-};
-
-struct ib_uverbs_query_port {
-	__u64 response;
-	__u8  port_num;
-	__u8  reserved[7];
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_query_port_resp {
-	__u32 port_cap_flags;
-	__u32 max_msg_sz;
-	__u32 bad_pkey_cntr;
-	__u32 qkey_viol_cntr;
-	__u32 gid_tbl_len;
-	__u16 pkey_tbl_len;
-	__u16 lid;
-	__u16 sm_lid;
-	__u8  state;
-	__u8  max_mtu;
-	__u8  active_mtu;
-	__u8  lmc;
-	__u8  max_vl_num;
-	__u8  sm_sl;
-	__u8  subnet_timeout;
-	__u8  init_type_reply;
-	__u8  active_width;
-	__u8  active_speed;
-	__u8  phys_state;
-	__u8  link_layer;
-	__u8  reserved[2];
-};
-
-struct ib_uverbs_alloc_pd {
-	__u64 response;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_alloc_pd_resp {
-	__u32 pd_handle;
-};
-
-struct ib_uverbs_dealloc_pd {
-	__u32 pd_handle;
-};
-
-struct ib_uverbs_open_xrcd {
-	__u64 response;
-	__u32 fd;
-	__u32 oflags;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_open_xrcd_resp {
-	__u32 xrcd_handle;
-};
-
-struct ib_uverbs_close_xrcd {
-	__u32 xrcd_handle;
-};
-
-struct ib_uverbs_reg_mr {
-	__u64 response;
-	__u64 start;
-	__u64 length;
-	__u64 hca_va;
-	__u32 pd_handle;
-	__u32 access_flags;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_reg_mr_resp {
-	__u32 mr_handle;
-	__u32 lkey;
-	__u32 rkey;
-};
-
-struct ib_uverbs_dereg_mr {
-	__u32 mr_handle;
-};
-
-struct ib_uverbs_create_comp_channel {
-	__u64 response;
-};
-
-struct ib_uverbs_create_comp_channel_resp {
-	__u32 fd;
-};
-
-struct ib_uverbs_create_cq {
-	__u64 response;
-	__u64 user_handle;
-	__u32 cqe;
-	__u32 comp_vector;
-	__s32 comp_channel;
-	__u32 reserved;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_create_cq_resp {
-	__u32 cq_handle;
-	__u32 cqe;
-};
-
-struct ib_uverbs_resize_cq {
-	__u64 response;
-	__u32 cq_handle;
-	__u32 cqe;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_resize_cq_resp {
-	__u32 cqe;
-	__u32 reserved;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_poll_cq {
-	__u64 response;
-	__u32 cq_handle;
-	__u32 ne;
-};
-
-struct ib_uverbs_wc {
-	__u64 wr_id;
-	__u32 status;
-	__u32 opcode;
-	__u32 vendor_err;
-	__u32 byte_len;
-	union {
-		__u32 imm_data;
-		__u32 invalidate_rkey;
-	} ex;
-	__u32 qp_num;
-	__u32 src_qp;
-	__u32 wc_flags;
-	__u16 pkey_index;
-	__u16 slid;
-	__u8 sl;
-	__u8 dlid_path_bits;
-	__u8 port_num;
-	__u8 reserved;
-};
-
-struct ib_uverbs_poll_cq_resp {
-	__u32 count;
-	__u32 reserved;
-	struct ib_uverbs_wc wc[0];
-};
-
-struct ib_uverbs_req_notify_cq {
-	__u32 cq_handle;
-	__u32 solicited_only;
-};
-
-struct ib_uverbs_destroy_cq {
-	__u64 response;
-	__u32 cq_handle;
-	__u32 reserved;
-};
-
-struct ib_uverbs_destroy_cq_resp {
-	__u32 comp_events_reported;
-	__u32 async_events_reported;
-};
-
-struct ib_uverbs_global_route {
-	__u8  dgid[16];
-	__u32 flow_label;
-	__u8  sgid_index;
-	__u8  hop_limit;
-	__u8  traffic_class;
-	__u8  reserved;
-};
-
-struct ib_uverbs_ah_attr {
-	struct ib_uverbs_global_route grh;
-	__u16 dlid;
-	__u8  sl;
-	__u8  src_path_bits;
-	__u8  static_rate;
-	__u8  is_global;
-	__u8  port_num;
-	__u8  reserved;
-};
-
-struct ib_uverbs_qp_attr {
-	__u32	qp_attr_mask;
-	__u32	qp_state;
-	__u32	cur_qp_state;
-	__u32	path_mtu;
-	__u32	path_mig_state;
-	__u32	qkey;
-	__u32	rq_psn;
-	__u32	sq_psn;
-	__u32	dest_qp_num;
-	__u32	qp_access_flags;
-
-	struct ib_uverbs_ah_attr ah_attr;
-	struct ib_uverbs_ah_attr alt_ah_attr;
-
-	/* ib_qp_cap */
-	__u32	max_send_wr;
-	__u32	max_recv_wr;
-	__u32	max_send_sge;
-	__u32	max_recv_sge;
-	__u32	max_inline_data;
-
-	__u16	pkey_index;
-	__u16	alt_pkey_index;
-	__u8	en_sqd_async_notify;
-	__u8	sq_draining;
-	__u8	max_rd_atomic;
-	__u8	max_dest_rd_atomic;
-	__u8	min_rnr_timer;
-	__u8	port_num;
-	__u8	timeout;
-	__u8	retry_cnt;
-	__u8	rnr_retry;
-	__u8	alt_port_num;
-	__u8	alt_timeout;
-	__u8	reserved[5];
-};
-
-struct ib_uverbs_create_qp {
-	__u64 response;
-	__u64 user_handle;
-	__u32 pd_handle;
-	__u32 send_cq_handle;
-	__u32 recv_cq_handle;
-	__u32 srq_handle;
-	__u32 max_send_wr;
-	__u32 max_recv_wr;
-	__u32 max_send_sge;
-	__u32 max_recv_sge;
-	__u32 max_inline_data;
-	__u8  sq_sig_all;
-	__u8  qp_type;
-	__u8  is_srq;
-	__u8  reserved;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_open_qp {
-	__u64 response;
-	__u64 user_handle;
-	__u32 pd_handle;
-	__u32 qpn;
-	__u8  qp_type;
-	__u8  reserved[7];
-	__u64 driver_data[0];
-};
-
-/* also used for open response */
-struct ib_uverbs_create_qp_resp {
-	__u32 qp_handle;
-	__u32 qpn;
-	__u32 max_send_wr;
-	__u32 max_recv_wr;
-	__u32 max_send_sge;
-	__u32 max_recv_sge;
-	__u32 max_inline_data;
-	__u32 reserved;
-};
-
-/*
- * This struct needs to remain a multiple of 8 bytes to keep the
- * alignment of the modify QP parameters.
- */
-struct ib_uverbs_qp_dest {
-	__u8  dgid[16];
-	__u32 flow_label;
-	__u16 dlid;
-	__u16 reserved;
-	__u8  sgid_index;
-	__u8  hop_limit;
-	__u8  traffic_class;
-	__u8  sl;
-	__u8  src_path_bits;
-	__u8  static_rate;
-	__u8  is_global;
-	__u8  port_num;
-};
-
-struct ib_uverbs_query_qp {
-	__u64 response;
-	__u32 qp_handle;
-	__u32 attr_mask;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_query_qp_resp {
-	struct ib_uverbs_qp_dest dest;
-	struct ib_uverbs_qp_dest alt_dest;
-	__u32 max_send_wr;
-	__u32 max_recv_wr;
-	__u32 max_send_sge;
-	__u32 max_recv_sge;
-	__u32 max_inline_data;
-	__u32 qkey;
-	__u32 rq_psn;
-	__u32 sq_psn;
-	__u32 dest_qp_num;
-	__u32 qp_access_flags;
-	__u16 pkey_index;
-	__u16 alt_pkey_index;
-	__u8  qp_state;
-	__u8  cur_qp_state;
-	__u8  path_mtu;
-	__u8  path_mig_state;
-	__u8  sq_draining;
-	__u8  max_rd_atomic;
-	__u8  max_dest_rd_atomic;
-	__u8  min_rnr_timer;
-	__u8  port_num;
-	__u8  timeout;
-	__u8  retry_cnt;
-	__u8  rnr_retry;
-	__u8  alt_port_num;
-	__u8  alt_timeout;
-	__u8  sq_sig_all;
-	__u8  reserved[5];
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_modify_qp {
-	struct ib_uverbs_qp_dest dest;
-	struct ib_uverbs_qp_dest alt_dest;
-	__u32 qp_handle;
-	__u32 attr_mask;
-	__u32 qkey;
-	__u32 rq_psn;
-	__u32 sq_psn;
-	__u32 dest_qp_num;
-	__u32 qp_access_flags;
-	__u16 pkey_index;
-	__u16 alt_pkey_index;
-	__u8  qp_state;
-	__u8  cur_qp_state;
-	__u8  path_mtu;
-	__u8  path_mig_state;
-	__u8  en_sqd_async_notify;
-	__u8  max_rd_atomic;
-	__u8  max_dest_rd_atomic;
-	__u8  min_rnr_timer;
-	__u8  port_num;
-	__u8  timeout;
-	__u8  retry_cnt;
-	__u8  rnr_retry;
-	__u8  alt_port_num;
-	__u8  alt_timeout;
-	__u8  reserved[2];
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_modify_qp_resp {
-};
-
-struct ib_uverbs_destroy_qp {
-	__u64 response;
-	__u32 qp_handle;
-	__u32 reserved;
-};
-
-struct ib_uverbs_destroy_qp_resp {
-	__u32 events_reported;
-};
-
-/*
- * The ib_uverbs_sge structure isn't used anywhere, since we assume
- * the ib_sge structure is packed the same way on 32-bit and 64-bit
- * architectures in both kernel and user space.  It's just here to
- * document the ABI.
- */
-struct ib_uverbs_sge {
-	__u64 addr;
-	__u32 length;
-	__u32 lkey;
-};
-
-struct ib_uverbs_send_wr {
-	__u64 wr_id;
-	__u32 num_sge;
-	__u32 opcode;
-	__u32 send_flags;
-	union {
-		__u32 imm_data;
-		__u32 invalidate_rkey;
-	} ex;
-	union {
-		struct {
-			__u64 remote_addr;
-			__u32 rkey;
-			__u32 reserved;
-		} rdma;
-		struct {
-			__u64 remote_addr;
-			__u64 compare_add;
-			__u64 swap;
-			__u32 rkey;
-			__u32 reserved;
-		} atomic;
-		struct {
-			__u32 ah;
-			__u32 remote_qpn;
-			__u32 remote_qkey;
-			__u32 reserved;
-		} ud;
-	} wr;
-};
-
-struct ib_uverbs_post_send {
-	__u64 response;
-	__u32 qp_handle;
-	__u32 wr_count;
-	__u32 sge_count;
-	__u32 wqe_size;
-	struct ib_uverbs_send_wr send_wr[0];
-};
-
-struct ib_uverbs_post_send_resp {
-	__u32 bad_wr;
-};
-
-struct ib_uverbs_recv_wr {
-	__u64 wr_id;
-	__u32 num_sge;
-	__u32 reserved;
-};
-
-struct ib_uverbs_post_recv {
-	__u64 response;
-	__u32 qp_handle;
-	__u32 wr_count;
-	__u32 sge_count;
-	__u32 wqe_size;
-	struct ib_uverbs_recv_wr recv_wr[0];
-};
-
-struct ib_uverbs_post_recv_resp {
-	__u32 bad_wr;
-};
-
-struct ib_uverbs_post_srq_recv {
-	__u64 response;
-	__u32 srq_handle;
-	__u32 wr_count;
-	__u32 sge_count;
-	__u32 wqe_size;
-	struct ib_uverbs_recv_wr recv[0];
-};
-
-struct ib_uverbs_post_srq_recv_resp {
-	__u32 bad_wr;
-};
-
-struct ib_uverbs_create_ah {
-	__u64 response;
-	__u64 user_handle;
-	__u32 pd_handle;
-	__u32 reserved;
-	struct ib_uverbs_ah_attr attr;
-};
-
-struct ib_uverbs_create_ah_resp {
-	__u32 ah_handle;
-};
-
-struct ib_uverbs_destroy_ah {
-	__u32 ah_handle;
-};
-
-struct ib_uverbs_attach_mcast {
-	__u8  gid[16];
-	__u32 qp_handle;
-	__u16 mlid;
-	__u16 reserved;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_detach_mcast {
-	__u8  gid[16];
-	__u32 qp_handle;
-	__u16 mlid;
-	__u16 reserved;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_create_srq {
-	__u64 response;
-	__u64 user_handle;
-	__u32 pd_handle;
-	__u32 max_wr;
-	__u32 max_sge;
-	__u32 srq_limit;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_create_xsrq {
-	__u64 response;
-	__u64 user_handle;
-	__u32 srq_type;
-	__u32 pd_handle;
-	__u32 max_wr;
-	__u32 max_sge;
-	__u32 srq_limit;
-	__u32 reserved;
-	__u32 xrcd_handle;
-	__u32 cq_handle;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_create_srq_resp {
-	__u32 srq_handle;
-	__u32 max_wr;
-	__u32 max_sge;
-	__u32 srqn;
-};
-
-struct ib_uverbs_modify_srq {
-	__u32 srq_handle;
-	__u32 attr_mask;
-	__u32 max_wr;
-	__u32 srq_limit;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_query_srq {
-	__u64 response;
-	__u32 srq_handle;
-	__u32 reserved;
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_query_srq_resp {
-	__u32 max_wr;
-	__u32 max_sge;
-	__u32 srq_limit;
-	__u32 reserved;
-};
-
-struct ib_uverbs_destroy_srq {
-	__u64 response;
-	__u32 srq_handle;
-	__u32 reserved;
-};
-
-struct ib_uverbs_destroy_srq_resp {
-	__u32 events_reported;
-};
-
-#endif /* IB_USER_VERBS_H */
diff --git a/include/rdma/rdma_netlink.h b/include/rdma/rdma_netlink.h
index bd3d8b2..e38de79 100644
--- a/include/rdma/rdma_netlink.h
+++ b/include/rdma/rdma_netlink.h
@@ -1,41 +1,9 @@
 #ifndef _RDMA_NETLINK_H
 #define _RDMA_NETLINK_H
 
-#include <linux/types.h>
-
-enum {
-	RDMA_NL_RDMA_CM = 1
-};
-
-#define RDMA_NL_GET_CLIENT(type) ((type & (((1 << 6) - 1) << 10)) >> 10)
-#define RDMA_NL_GET_OP(type) (type & ((1 << 10) - 1))
-#define RDMA_NL_GET_TYPE(client, op) ((client << 10) + op)
-
-enum {
-	RDMA_NL_RDMA_CM_ID_STATS = 0,
-	RDMA_NL_RDMA_CM_NUM_OPS
-};
-
-enum {
-	RDMA_NL_RDMA_CM_ATTR_SRC_ADDR = 1,
-	RDMA_NL_RDMA_CM_ATTR_DST_ADDR,
-	RDMA_NL_RDMA_CM_NUM_ATTR,
-};
-
-struct rdma_cm_id_stats {
-	__u32	qp_num;
-	__u32	bound_dev_if;
-	__u32	port_space;
-	__s32	pid;
-	__u8	cm_state;
-	__u8	node_type;
-	__u8	port_num;
-	__u8	qp_type;
-};
-
-#ifdef __KERNEL__
 
 #include <linux/netlink.h>
+#include <uapi/rdma/rdma_netlink.h>
 
 struct ibnl_client_cbs {
 	int (*dump)(struct sk_buff *skb, struct netlink_callback *nlcb);
@@ -88,6 +56,4 @@ void *ibnl_put_msg(struct sk_buff *skb, struct nlmsghdr **nlh, int seq,
 int ibnl_put_attr(struct sk_buff *skb, struct nlmsghdr *nlh,
 		  int len, void *data, int type);
 
-#endif /* __KERNEL__ */
-
 #endif /* _RDMA_NETLINK_H */
diff --git a/include/rdma/rdma_user_cm.h b/include/rdma/rdma_user_cm.h
deleted file mode 100644
index 1ee9239..0000000
--- a/include/rdma/rdma_user_cm.h
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2005-2006 Intel Corporation.  All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef RDMA_USER_CM_H
-#define RDMA_USER_CM_H
-
-#include <linux/types.h>
-#include <linux/in6.h>
-#include <rdma/ib_user_verbs.h>
-#include <rdma/ib_user_sa.h>
-
-#define RDMA_USER_CM_ABI_VERSION	4
-
-#define RDMA_MAX_PRIVATE_DATA		256
-
-enum {
-	RDMA_USER_CM_CMD_CREATE_ID,
-	RDMA_USER_CM_CMD_DESTROY_ID,
-	RDMA_USER_CM_CMD_BIND_ADDR,
-	RDMA_USER_CM_CMD_RESOLVE_ADDR,
-	RDMA_USER_CM_CMD_RESOLVE_ROUTE,
-	RDMA_USER_CM_CMD_QUERY_ROUTE,
-	RDMA_USER_CM_CMD_CONNECT,
-	RDMA_USER_CM_CMD_LISTEN,
-	RDMA_USER_CM_CMD_ACCEPT,
-	RDMA_USER_CM_CMD_REJECT,
-	RDMA_USER_CM_CMD_DISCONNECT,
-	RDMA_USER_CM_CMD_INIT_QP_ATTR,
-	RDMA_USER_CM_CMD_GET_EVENT,
-	RDMA_USER_CM_CMD_GET_OPTION,
-	RDMA_USER_CM_CMD_SET_OPTION,
-	RDMA_USER_CM_CMD_NOTIFY,
-	RDMA_USER_CM_CMD_JOIN_MCAST,
-	RDMA_USER_CM_CMD_LEAVE_MCAST,
-	RDMA_USER_CM_CMD_MIGRATE_ID
-};
-
-/*
- * command ABI structures.
- */
-struct rdma_ucm_cmd_hdr {
-	__u32 cmd;
-	__u16 in;
-	__u16 out;
-};
-
-struct rdma_ucm_create_id {
-	__u64 uid;
-	__u64 response;
-	__u16 ps;
-	__u8  qp_type;
-	__u8  reserved[5];
-};
-
-struct rdma_ucm_create_id_resp {
-	__u32 id;
-};
-
-struct rdma_ucm_destroy_id {
-	__u64 response;
-	__u32 id;
-	__u32 reserved;
-};
-
-struct rdma_ucm_destroy_id_resp {
-	__u32 events_reported;
-};
-
-struct rdma_ucm_bind_addr {
-	__u64 response;
-	struct sockaddr_in6 addr;
-	__u32 id;
-};
-
-struct rdma_ucm_resolve_addr {
-	struct sockaddr_in6 src_addr;
-	struct sockaddr_in6 dst_addr;
-	__u32 id;
-	__u32 timeout_ms;
-};
-
-struct rdma_ucm_resolve_route {
-	__u32 id;
-	__u32 timeout_ms;
-};
-
-struct rdma_ucm_query_route {
-	__u64 response;
-	__u32 id;
-	__u32 reserved;
-};
-
-struct rdma_ucm_query_route_resp {
-	__u64 node_guid;
-	struct ib_user_path_rec ib_route[2];
-	struct sockaddr_in6 src_addr;
-	struct sockaddr_in6 dst_addr;
-	__u32 num_paths;
-	__u8 port_num;
-	__u8 reserved[3];
-};
-
-struct rdma_ucm_conn_param {
-	__u32 qp_num;
-	__u32 reserved;
-	__u8  private_data[RDMA_MAX_PRIVATE_DATA];
-	__u8  private_data_len;
-	__u8  srq;
-	__u8  responder_resources;
-	__u8  initiator_depth;
-	__u8  flow_control;
-	__u8  retry_count;
-	__u8  rnr_retry_count;
-	__u8  valid;
-};
-
-struct rdma_ucm_ud_param {
-	__u32 qp_num;
-	__u32 qkey;
-	struct ib_uverbs_ah_attr ah_attr;
-	__u8  private_data[RDMA_MAX_PRIVATE_DATA];
-	__u8  private_data_len;
-	__u8  reserved[7];
-};
-
-struct rdma_ucm_connect {
-	struct rdma_ucm_conn_param conn_param;
-	__u32 id;
-	__u32 reserved;
-};
-
-struct rdma_ucm_listen {
-	__u32 id;
-	__u32 backlog;
-};
-
-struct rdma_ucm_accept {
-	__u64 uid;
-	struct rdma_ucm_conn_param conn_param;
-	__u32 id;
-	__u32 reserved;
-};
-
-struct rdma_ucm_reject {
-	__u32 id;
-	__u8  private_data_len;
-	__u8  reserved[3];
-	__u8  private_data[RDMA_MAX_PRIVATE_DATA];
-};
-
-struct rdma_ucm_disconnect {
-	__u32 id;
-};
-
-struct rdma_ucm_init_qp_attr {
-	__u64 response;
-	__u32 id;
-	__u32 qp_state;
-};
-
-struct rdma_ucm_notify {
-	__u32 id;
-	__u32 event;
-};
-
-struct rdma_ucm_join_mcast {
-	__u64 response;		/* rdma_ucm_create_id_resp */
-	__u64 uid;
-	struct sockaddr_in6 addr;
-	__u32 id;
-};
-
-struct rdma_ucm_get_event {
-	__u64 response;
-};
-
-struct rdma_ucm_event_resp {
-	__u64 uid;
-	__u32 id;
-	__u32 event;
-	__u32 status;
-	union {
-		struct rdma_ucm_conn_param conn;
-		struct rdma_ucm_ud_param   ud;
-	} param;
-};
-
-/* Option levels */
-enum {
-	RDMA_OPTION_ID		= 0,
-	RDMA_OPTION_IB		= 1
-};
-
-/* Option details */
-enum {
-	RDMA_OPTION_ID_TOS	 = 0,
-	RDMA_OPTION_ID_REUSEADDR = 1,
-	RDMA_OPTION_ID_AFONLY	 = 2,
-	RDMA_OPTION_IB_PATH	 = 1
-};
-
-struct rdma_ucm_set_option {
-	__u64 optval;
-	__u32 id;
-	__u32 level;
-	__u32 optname;
-	__u32 optlen;
-};
-
-struct rdma_ucm_migrate_id {
-	__u64 response;
-	__u32 id;
-	__u32 fd;
-};
-
-struct rdma_ucm_migrate_resp {
-	__u32 events_reported;
-};
-
-#endif /* RDMA_USER_CM_H */
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 55367b0..e65c62e 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -137,6 +137,7 @@ struct scsi_device {
 	unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
 	unsigned no_report_opcodes:1;	/* no REPORT SUPPORTED OPERATION CODES */
 	unsigned no_write_same:1;	/* no WRITE SAME command */
+	unsigned use_16_for_rw:1; /* Use read/write(16) over read/write(10) */
 	unsigned skip_ms_page_8:1;	/* do not use MODE SENSE page 0x08 */
 	unsigned skip_ms_page_3f:1;	/* do not use MODE SENSE page 0x3f */
 	unsigned skip_vpd_pages:1;	/* do not read VPD pages */
diff --git a/include/sound/Kbuild b/include/sound/Kbuild
index 6df30ed..e69de29 100644
--- a/include/sound/Kbuild
+++ b/include/sound/Kbuild
@@ -1,10 +0,0 @@
-header-y += asequencer.h
-header-y += asound.h
-header-y += asound_fm.h
-header-y += emu10k1.h
-header-y += hdsp.h
-header-y += hdspm.h
-header-y += sb16_csp.h
-header-y += sfnt_info.h
-header-y += compress_params.h
-header-y += compress_offload.h
diff --git a/include/sound/asequencer.h b/include/sound/asequencer.h
index 1505e6d..75935ce 100644
--- a/include/sound/asequencer.h
+++ b/include/sound/asequencer.h
@@ -22,294 +22,9 @@
 #ifndef __SOUND_ASEQUENCER_H
 #define __SOUND_ASEQUENCER_H
 
-#ifdef __KERNEL__
 #include <linux/ioctl.h>
 #include <sound/asound.h>
-#endif
-
-/** version of the sequencer */
-#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION (1, 0, 1)
-
-/**
- * definition of sequencer event types
- */
-
-/** system messages
- * event data type = #snd_seq_result
- */
-#define SNDRV_SEQ_EVENT_SYSTEM		0
-#define SNDRV_SEQ_EVENT_RESULT		1
-
-/** note messages (channel specific)
- * event data type = #snd_seq_ev_note
- */
-#define SNDRV_SEQ_EVENT_NOTE		5
-#define SNDRV_SEQ_EVENT_NOTEON		6
-#define SNDRV_SEQ_EVENT_NOTEOFF		7
-#define SNDRV_SEQ_EVENT_KEYPRESS	8
-	
-/** control messages (channel specific)
- * event data type = #snd_seq_ev_ctrl
- */
-#define SNDRV_SEQ_EVENT_CONTROLLER	10
-#define SNDRV_SEQ_EVENT_PGMCHANGE	11
-#define SNDRV_SEQ_EVENT_CHANPRESS	12
-#define SNDRV_SEQ_EVENT_PITCHBEND	13	/**< from -8192 to 8191 */
-#define SNDRV_SEQ_EVENT_CONTROL14	14	/**< 14 bit controller value */
-#define SNDRV_SEQ_EVENT_NONREGPARAM	15	/**< 14 bit NRPN address + 14 bit unsigned value */
-#define SNDRV_SEQ_EVENT_REGPARAM	16	/**< 14 bit RPN address + 14 bit unsigned value */
-
-/** synchronisation messages
- * event data type = #snd_seq_ev_ctrl
- */
-#define SNDRV_SEQ_EVENT_SONGPOS		20	/* Song Position Pointer with LSB and MSB values */
-#define SNDRV_SEQ_EVENT_SONGSEL		21	/* Song Select with song ID number */
-#define SNDRV_SEQ_EVENT_QFRAME		22	/* midi time code quarter frame */
-#define SNDRV_SEQ_EVENT_TIMESIGN	23	/* SMF Time Signature event */
-#define SNDRV_SEQ_EVENT_KEYSIGN		24	/* SMF Key Signature event */
-	        
-/** timer messages
- * event data type = snd_seq_ev_queue_control
- */
-#define SNDRV_SEQ_EVENT_START		30	/* midi Real Time Start message */
-#define SNDRV_SEQ_EVENT_CONTINUE	31	/* midi Real Time Continue message */
-#define SNDRV_SEQ_EVENT_STOP		32	/* midi Real Time Stop message */	
-#define	SNDRV_SEQ_EVENT_SETPOS_TICK	33	/* set tick queue position */
-#define SNDRV_SEQ_EVENT_SETPOS_TIME	34	/* set realtime queue position */
-#define SNDRV_SEQ_EVENT_TEMPO		35	/* (SMF) Tempo event */
-#define SNDRV_SEQ_EVENT_CLOCK		36	/* midi Real Time Clock message */
-#define SNDRV_SEQ_EVENT_TICK		37	/* midi Real Time Tick message */
-#define SNDRV_SEQ_EVENT_QUEUE_SKEW	38	/* skew queue tempo */
-
-/** others
- * event data type = none
- */
-#define SNDRV_SEQ_EVENT_TUNE_REQUEST	40	/* tune request */
-#define SNDRV_SEQ_EVENT_RESET		41	/* reset to power-on state */
-#define SNDRV_SEQ_EVENT_SENSING		42	/* "active sensing" event */
-
-/** echo back, kernel private messages
- * event data type = any type
- */
-#define SNDRV_SEQ_EVENT_ECHO		50	/* echo event */
-#define SNDRV_SEQ_EVENT_OSS		51	/* OSS raw event */
-
-/** system status messages (broadcast for subscribers)
- * event data type = snd_seq_addr
- */
-#define SNDRV_SEQ_EVENT_CLIENT_START	60	/* new client has connected */
-#define SNDRV_SEQ_EVENT_CLIENT_EXIT	61	/* client has left the system */
-#define SNDRV_SEQ_EVENT_CLIENT_CHANGE	62	/* client status/info has changed */
-#define SNDRV_SEQ_EVENT_PORT_START	63	/* new port was created */
-#define SNDRV_SEQ_EVENT_PORT_EXIT	64	/* port was deleted from system */
-#define SNDRV_SEQ_EVENT_PORT_CHANGE	65	/* port status/info has changed */
-
-/** port connection changes
- * event data type = snd_seq_connect
- */
-#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED	66	/* ports connected */
-#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67	/* ports disconnected */
-
-/* 70-89:  synthesizer events - obsoleted */
-
-/** user-defined events with fixed length
- * event data type = any
- */
-#define SNDRV_SEQ_EVENT_USR0		90
-#define SNDRV_SEQ_EVENT_USR1		91
-#define SNDRV_SEQ_EVENT_USR2		92
-#define SNDRV_SEQ_EVENT_USR3		93
-#define SNDRV_SEQ_EVENT_USR4		94
-#define SNDRV_SEQ_EVENT_USR5		95
-#define SNDRV_SEQ_EVENT_USR6		96
-#define SNDRV_SEQ_EVENT_USR7		97
-#define SNDRV_SEQ_EVENT_USR8		98
-#define SNDRV_SEQ_EVENT_USR9		99
-
-/* 100-118: instrument layer - obsoleted */
-/* 119-129: reserved */
-
-/* 130-139: variable length events
- * event data type = snd_seq_ev_ext
- * (SNDRV_SEQ_EVENT_LENGTH_VARIABLE must be set)
- */
-#define SNDRV_SEQ_EVENT_SYSEX		130	/* system exclusive data (variable length) */
-#define SNDRV_SEQ_EVENT_BOUNCE		131	/* error event */
-/* 132-134: reserved */
-#define SNDRV_SEQ_EVENT_USR_VAR0	135
-#define SNDRV_SEQ_EVENT_USR_VAR1	136
-#define SNDRV_SEQ_EVENT_USR_VAR2	137
-#define SNDRV_SEQ_EVENT_USR_VAR3	138
-#define SNDRV_SEQ_EVENT_USR_VAR4	139
-
-/* 150-151: kernel events with quote - DO NOT use in user clients */
-#define SNDRV_SEQ_EVENT_KERNEL_ERROR	150
-#define SNDRV_SEQ_EVENT_KERNEL_QUOTE	151	/* obsolete */
-
-/* 152-191: reserved */
-
-/* 192-254: hardware specific events */
-
-/* 255: special event */
-#define SNDRV_SEQ_EVENT_NONE		255
-
-
-typedef unsigned char snd_seq_event_type_t;
-
-/** event address */
-struct snd_seq_addr {
-	unsigned char client;	/**< Client number:         0..255, 255 = broadcast to all clients */
-	unsigned char port;	/**< Port within client:    0..255, 255 = broadcast to all ports */
-};
-
-/** port connection */
-struct snd_seq_connect {
-	struct snd_seq_addr sender;
-	struct snd_seq_addr dest;
-};
-
-
-#define SNDRV_SEQ_ADDRESS_UNKNOWN	253	/* unknown source */
-#define SNDRV_SEQ_ADDRESS_SUBSCRIBERS	254	/* send event to all subscribed ports */
-#define SNDRV_SEQ_ADDRESS_BROADCAST	255	/* send event to all queues/clients/ports/channels */
-#define SNDRV_SEQ_QUEUE_DIRECT		253	/* direct dispatch */
-
-	/* event mode flag - NOTE: only 8 bits available! */
-#define SNDRV_SEQ_TIME_STAMP_TICK	(0<<0) /* timestamp in clock ticks */
-#define SNDRV_SEQ_TIME_STAMP_REAL	(1<<0) /* timestamp in real time */
-#define SNDRV_SEQ_TIME_STAMP_MASK	(1<<0)
-
-#define SNDRV_SEQ_TIME_MODE_ABS		(0<<1)	/* absolute timestamp */
-#define SNDRV_SEQ_TIME_MODE_REL		(1<<1)	/* relative to current time */
-#define SNDRV_SEQ_TIME_MODE_MASK	(1<<1)
-
-#define SNDRV_SEQ_EVENT_LENGTH_FIXED	(0<<2)	/* fixed event size */
-#define SNDRV_SEQ_EVENT_LENGTH_VARIABLE	(1<<2)	/* variable event size */
-#define SNDRV_SEQ_EVENT_LENGTH_VARUSR	(2<<2)	/* variable event size - user memory space */
-#define SNDRV_SEQ_EVENT_LENGTH_MASK	(3<<2)
-
-#define SNDRV_SEQ_PRIORITY_NORMAL	(0<<4)	/* normal priority */
-#define SNDRV_SEQ_PRIORITY_HIGH		(1<<4)	/* event should be processed before others */
-#define SNDRV_SEQ_PRIORITY_MASK		(1<<4)
-
-
-	/* note event */
-struct snd_seq_ev_note {
-	unsigned char channel;
-	unsigned char note;
-	unsigned char velocity;
-	unsigned char off_velocity;	/* only for SNDRV_SEQ_EVENT_NOTE */
-	unsigned int duration;		/* only for SNDRV_SEQ_EVENT_NOTE */
-};
-
-	/* controller event */
-struct snd_seq_ev_ctrl {
-	unsigned char channel;
-	unsigned char unused1, unused2, unused3;	/* pad */
-	unsigned int param;
-	signed int value;
-};
-
-	/* generic set of bytes (12x8 bit) */
-struct snd_seq_ev_raw8 {
-	unsigned char d[12];	/* 8 bit value */
-};
-
-	/* generic set of integers (3x32 bit) */
-struct snd_seq_ev_raw32 {
-	unsigned int d[3];	/* 32 bit value */
-};
-
-	/* external stored data */
-struct snd_seq_ev_ext {
-	unsigned int len;	/* length of data */
-	void *ptr;		/* pointer to data (note: maybe 64-bit) */
-} __attribute__((packed));
-
-struct snd_seq_result {
-	int event;		/* processed event type */
-	int result;
-};
-
-
-struct snd_seq_real_time {
-	unsigned int tv_sec;	/* seconds */
-	unsigned int tv_nsec;	/* nanoseconds */
-};
-
-typedef unsigned int snd_seq_tick_time_t;	/* midi ticks */
-
-union snd_seq_timestamp {
-	snd_seq_tick_time_t tick;
-	struct snd_seq_real_time time;
-};
-
-struct snd_seq_queue_skew {
-	unsigned int value;
-	unsigned int base;
-};
-
-	/* queue timer control */
-struct snd_seq_ev_queue_control {
-	unsigned char queue;			/* affected queue */
-	unsigned char pad[3];			/* reserved */
-	union {
-		signed int value;		/* affected value (e.g. tempo) */
-		union snd_seq_timestamp time;	/* time */
-		unsigned int position;		/* sync position */
-		struct snd_seq_queue_skew skew;
-		unsigned int d32[2];
-		unsigned char d8[8];
-	} param;
-};
-
-	/* quoted event - inside the kernel only */
-struct snd_seq_ev_quote {
-	struct snd_seq_addr origin;		/* original sender */
-	unsigned short value;		/* optional data */
-	struct snd_seq_event *event;		/* quoted event */
-} __attribute__((packed));
-
-
-	/* sequencer event */
-struct snd_seq_event {
-	snd_seq_event_type_t type;	/* event type */
-	unsigned char flags;		/* event flags */
-	char tag;
-	
-	unsigned char queue;		/* schedule queue */
-	union snd_seq_timestamp time;	/* schedule time */
-
-
-	struct snd_seq_addr source;	/* source address */
-	struct snd_seq_addr dest;	/* destination address */
-
-	union {				/* event data... */
-		struct snd_seq_ev_note note;
-		struct snd_seq_ev_ctrl control;
-		struct snd_seq_ev_raw8 raw8;
-		struct snd_seq_ev_raw32 raw32;
-		struct snd_seq_ev_ext ext;
-		struct snd_seq_ev_queue_control queue;
-		union snd_seq_timestamp time;
-		struct snd_seq_addr addr;
-		struct snd_seq_connect connect;
-		struct snd_seq_result result;
-		struct snd_seq_ev_quote quote;
-	} data;
-};
-
-
-/*
- * bounce event - stored as variable size data
- */
-struct snd_seq_event_bounce {
-	int err;
-	struct snd_seq_event event;
-	/* external data follows here. */
-};
-
-#ifdef __KERNEL__
+#include <uapi/sound/asequencer.h>
 
 /* helper macro */
 #define snd_seq_event_bounce_ext_data(ev) ((void*)((char *)(ev)->data.ext.ptr + sizeof(struct snd_seq_event_bounce)))
@@ -368,311 +83,4 @@ struct snd_seq_event_bounce {
 /* queue sync port */
 #define snd_seq_queue_sync_port(q)	((q) + 16)
 
-#endif /* __KERNEL__ */
-
-	/* system information */
-struct snd_seq_system_info {
-	int queues;			/* maximum queues count */
-	int clients;			/* maximum clients count */
-	int ports;			/* maximum ports per client */
-	int channels;			/* maximum channels per port */
-	int cur_clients;		/* current clients */
-	int cur_queues;			/* current queues */
-	char reserved[24];
-};
-
-
-	/* system running information */
-struct snd_seq_running_info {
-	unsigned char client;		/* client id */
-	unsigned char big_endian;	/* 1 = big-endian */
-	unsigned char cpu_mode;		/* 4 = 32bit, 8 = 64bit */
-	unsigned char pad;		/* reserved */
-	unsigned char reserved[12];
-};
-
-
-	/* known client numbers */
-#define SNDRV_SEQ_CLIENT_SYSTEM		0
-	/* internal client numbers */
-#define SNDRV_SEQ_CLIENT_DUMMY		14	/* midi through */
-#define SNDRV_SEQ_CLIENT_OSS		15	/* oss sequencer emulator */
-
-
-	/* client types */
-typedef int __bitwise snd_seq_client_type_t;
-#define	NO_CLIENT	((__force snd_seq_client_type_t) 0)
-#define	USER_CLIENT	((__force snd_seq_client_type_t) 1)
-#define	KERNEL_CLIENT	((__force snd_seq_client_type_t) 2)
-                        
-	/* event filter flags */
-#define SNDRV_SEQ_FILTER_BROADCAST	(1<<0)	/* accept broadcast messages */
-#define SNDRV_SEQ_FILTER_MULTICAST	(1<<1)	/* accept multicast messages */
-#define SNDRV_SEQ_FILTER_BOUNCE		(1<<2)	/* accept bounce event in error */
-#define SNDRV_SEQ_FILTER_USE_EVENT	(1<<31)	/* use event filter */
-
-struct snd_seq_client_info {
-	int client;			/* client number to inquire */
-	snd_seq_client_type_t type;	/* client type */
-	char name[64];			/* client name */
-	unsigned int filter;		/* filter flags */
-	unsigned char multicast_filter[8]; /* multicast filter bitmap */
-	unsigned char event_filter[32];	/* event filter bitmap */
-	int num_ports;			/* RO: number of ports */
-	int event_lost;			/* number of lost events */
-	char reserved[64];		/* for future use */
-};
-
-
-/* client pool size */
-struct snd_seq_client_pool {
-	int client;			/* client number to inquire */
-	int output_pool;		/* outgoing (write) pool size */
-	int input_pool;			/* incoming (read) pool size */
-	int output_room;		/* minimum free pool size for select/blocking mode */
-	int output_free;		/* unused size */
-	int input_free;			/* unused size */
-	char reserved[64];
-};
-
-
-/* Remove events by specified criteria */
-
-#define SNDRV_SEQ_REMOVE_INPUT		(1<<0)	/* Flush input queues */
-#define SNDRV_SEQ_REMOVE_OUTPUT		(1<<1)	/* Flush output queues */
-#define SNDRV_SEQ_REMOVE_DEST		(1<<2)	/* Restrict by destination q:client:port */
-#define SNDRV_SEQ_REMOVE_DEST_CHANNEL	(1<<3)	/* Restrict by channel */
-#define SNDRV_SEQ_REMOVE_TIME_BEFORE	(1<<4)	/* Restrict to before time */
-#define SNDRV_SEQ_REMOVE_TIME_AFTER	(1<<5)	/* Restrict to time or after */
-#define SNDRV_SEQ_REMOVE_TIME_TICK	(1<<6)	/* Time is in ticks */
-#define SNDRV_SEQ_REMOVE_EVENT_TYPE	(1<<7)	/* Restrict to event type */
-#define SNDRV_SEQ_REMOVE_IGNORE_OFF 	(1<<8)	/* Do not flush off events */
-#define SNDRV_SEQ_REMOVE_TAG_MATCH 	(1<<9)	/* Restrict to events with given tag */
-
-struct snd_seq_remove_events {
-	unsigned int  remove_mode;	/* Flags that determine what gets removed */
-
-	union snd_seq_timestamp time;
-
-	unsigned char queue;	/* Queue for REMOVE_DEST */
-	struct snd_seq_addr dest;	/* Address for REMOVE_DEST */
-	unsigned char channel;	/* Channel for REMOVE_DEST */
-
-	int  type;	/* For REMOVE_EVENT_TYPE */
-	char  tag;	/* Tag for REMOVE_TAG */
-
-	int  reserved[10];	/* To allow for future binary compatibility */
-
-};
-
-
-	/* known port numbers */
-#define SNDRV_SEQ_PORT_SYSTEM_TIMER	0
-#define SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE	1
-
-	/* port capabilities (32 bits) */
-#define SNDRV_SEQ_PORT_CAP_READ		(1<<0)	/* readable from this port */
-#define SNDRV_SEQ_PORT_CAP_WRITE	(1<<1)	/* writable to this port */
-
-#define SNDRV_SEQ_PORT_CAP_SYNC_READ	(1<<2)
-#define SNDRV_SEQ_PORT_CAP_SYNC_WRITE	(1<<3)
-
-#define SNDRV_SEQ_PORT_CAP_DUPLEX	(1<<4)
-
-#define SNDRV_SEQ_PORT_CAP_SUBS_READ	(1<<5)	/* allow read subscription */
-#define SNDRV_SEQ_PORT_CAP_SUBS_WRITE	(1<<6)	/* allow write subscription */
-#define SNDRV_SEQ_PORT_CAP_NO_EXPORT	(1<<7)	/* routing not allowed */
-
-	/* port type */
-#define SNDRV_SEQ_PORT_TYPE_SPECIFIC	(1<<0)	/* hardware specific */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC (1<<1)	/* generic MIDI device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GM	(1<<2)	/* General MIDI compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GS	(1<<3)	/* GS compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_XG	(1<<4)	/* XG compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_MT32	(1<<5)	/* MT-32 compatible device */
-#define SNDRV_SEQ_PORT_TYPE_MIDI_GM2	(1<<6)	/* General MIDI 2 compatible device */
-
-/* other standards...*/
-#define SNDRV_SEQ_PORT_TYPE_SYNTH	(1<<10)	/* Synth device (no MIDI compatible - direct wavetable) */
-#define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11)	/* Sampling device (support sample download) */
-#define SNDRV_SEQ_PORT_TYPE_SAMPLE	(1<<12)	/* Sampling device (sample can be downloaded at any time) */
-/*...*/
-#define SNDRV_SEQ_PORT_TYPE_HARDWARE	(1<<16)	/* driver for a hardware device */
-#define SNDRV_SEQ_PORT_TYPE_SOFTWARE	(1<<17)	/* implemented in software */
-#define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER	(1<<18)	/* generates sound */
-#define SNDRV_SEQ_PORT_TYPE_PORT	(1<<19)	/* connects to other device(s) */
-#define SNDRV_SEQ_PORT_TYPE_APPLICATION	(1<<20)	/* application (sequencer/editor) */
-
-/* misc. conditioning flags */
-#define SNDRV_SEQ_PORT_FLG_GIVEN_PORT	(1<<0)
-#define SNDRV_SEQ_PORT_FLG_TIMESTAMP	(1<<1)
-#define SNDRV_SEQ_PORT_FLG_TIME_REAL	(1<<2)
-
-struct snd_seq_port_info {
-	struct snd_seq_addr addr;	/* client/port numbers */
-	char name[64];			/* port name */
-
-	unsigned int capability;	/* port capability bits */
-	unsigned int type;		/* port type bits */
-	int midi_channels;		/* channels per MIDI port */
-	int midi_voices;		/* voices per MIDI port */
-	int synth_voices;		/* voices per SYNTH port */
-
-	int read_use;			/* R/O: subscribers for output (from this port) */
-	int write_use;			/* R/O: subscribers for input (to this port) */
-
-	void *kernel;			/* reserved for kernel use (must be NULL) */
-	unsigned int flags;		/* misc. conditioning */
-	unsigned char time_queue;	/* queue # for timestamping */
-	char reserved[59];		/* for future use */
-};
-
-
-/* queue flags */
-#define SNDRV_SEQ_QUEUE_FLG_SYNC	(1<<0)	/* sync enabled */
-
-/* queue information */
-struct snd_seq_queue_info {
-	int queue;		/* queue id */
-
-	/*
-	 *  security settings, only owner of this queue can start/stop timer
-	 *  etc. if the queue is locked for other clients
-	 */
-	int owner;		/* client id for owner of the queue */
-	unsigned locked:1;	/* timing queue locked for other queues */
-	char name[64];		/* name of this queue */
-	unsigned int flags;	/* flags */
-	char reserved[60];	/* for future use */
-
-};
-
-/* queue info/status */
-struct snd_seq_queue_status {
-	int queue;			/* queue id */
-	int events;			/* read-only - queue size */
-	snd_seq_tick_time_t tick;	/* current tick */
-	struct snd_seq_real_time time;	/* current time */
-	int running;			/* running state of queue */
-	int flags;			/* various flags */
-	char reserved[64];		/* for the future */
-};
-
-
-/* queue tempo */
-struct snd_seq_queue_tempo {
-	int queue;			/* sequencer queue */
-	unsigned int tempo;		/* current tempo, us/tick */
-	int ppq;			/* time resolution, ticks/quarter */
-	unsigned int skew_value;	/* queue skew */
-	unsigned int skew_base;		/* queue skew base */
-	char reserved[24];		/* for the future */
-};
-
-
-/* sequencer timer sources */
-#define SNDRV_SEQ_TIMER_ALSA		0	/* ALSA timer */
-#define SNDRV_SEQ_TIMER_MIDI_CLOCK	1	/* Midi Clock (CLOCK event) */
-#define SNDRV_SEQ_TIMER_MIDI_TICK	2	/* Midi Timer Tick (TICK event) */
-
-/* queue timer info */
-struct snd_seq_queue_timer {
-	int queue;			/* sequencer queue */
-	int type;			/* source timer type */
-	union {
-		struct {
-			struct snd_timer_id id;	/* ALSA's timer ID */
-			unsigned int resolution;	/* resolution in Hz */
-		} alsa;
-	} u;
-	char reserved[64];		/* for the future use */
-};
-
-
-struct snd_seq_queue_client {
-	int queue;		/* sequencer queue */
-	int client;		/* sequencer client */
-	int used;		/* queue is used with this client
-				   (must be set for accepting events) */
-	/* per client watermarks */
-	char reserved[64];	/* for future use */
-};
-
-
-#define SNDRV_SEQ_PORT_SUBS_EXCLUSIVE	(1<<0)	/* exclusive connection */
-#define SNDRV_SEQ_PORT_SUBS_TIMESTAMP	(1<<1)
-#define SNDRV_SEQ_PORT_SUBS_TIME_REAL	(1<<2)
-
-struct snd_seq_port_subscribe {
-	struct snd_seq_addr sender;	/* sender address */
-	struct snd_seq_addr dest;	/* destination address */
-	unsigned int voices;		/* number of voices to be allocated (0 = don't care) */
-	unsigned int flags;		/* modes */
-	unsigned char queue;		/* input time-stamp queue (optional) */
-	unsigned char pad[3];		/* reserved */
-	char reserved[64];
-};
-
-/* type of query subscription */
-#define SNDRV_SEQ_QUERY_SUBS_READ	0
-#define SNDRV_SEQ_QUERY_SUBS_WRITE	1
-
-struct snd_seq_query_subs {
-	struct snd_seq_addr root;	/* client/port id to be searched */
-	int type;		/* READ or WRITE */
-	int index;		/* 0..N-1 */
-	int num_subs;		/* R/O: number of subscriptions on this port */
-	struct snd_seq_addr addr;	/* R/O: result */
-	unsigned char queue;	/* R/O: result */
-	unsigned int flags;	/* R/O: result */
-	char reserved[64];	/* for future use */
-};
-
-
-/*
- *  IOCTL commands
- */
-
-#define SNDRV_SEQ_IOCTL_PVERSION	_IOR ('S', 0x00, int)
-#define SNDRV_SEQ_IOCTL_CLIENT_ID	_IOR ('S', 0x01, int)
-#define SNDRV_SEQ_IOCTL_SYSTEM_INFO	_IOWR('S', 0x02, struct snd_seq_system_info)
-#define SNDRV_SEQ_IOCTL_RUNNING_MODE	_IOWR('S', 0x03, struct snd_seq_running_info)
-
-#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO	_IOWR('S', 0x10, struct snd_seq_client_info)
-#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO	_IOW ('S', 0x11, struct snd_seq_client_info)
-
-#define SNDRV_SEQ_IOCTL_CREATE_PORT	_IOWR('S', 0x20, struct snd_seq_port_info)
-#define SNDRV_SEQ_IOCTL_DELETE_PORT	_IOW ('S', 0x21, struct snd_seq_port_info)
-#define SNDRV_SEQ_IOCTL_GET_PORT_INFO	_IOWR('S', 0x22, struct snd_seq_port_info)
-#define SNDRV_SEQ_IOCTL_SET_PORT_INFO	_IOW ('S', 0x23, struct snd_seq_port_info)
-
-#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT	_IOW ('S', 0x30, struct snd_seq_port_subscribe)
-#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct snd_seq_port_subscribe)
-
-#define SNDRV_SEQ_IOCTL_CREATE_QUEUE	_IOWR('S', 0x32, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_DELETE_QUEUE	_IOW ('S', 0x33, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO	_IOWR('S', 0x34, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO	_IOWR('S', 0x35, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE	_IOWR('S', 0x36, struct snd_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct snd_seq_queue_status)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO	_IOWR('S', 0x41, struct snd_seq_queue_tempo)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO	_IOW ('S', 0x42, struct snd_seq_queue_tempo)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER	_IOWR('S', 0x43, struct snd_seq_queue_owner)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER	_IOW ('S', 0x44, struct snd_seq_queue_owner)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER	_IOWR('S', 0x45, struct snd_seq_queue_timer)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER	_IOW ('S', 0x46, struct snd_seq_queue_timer)
-/* XXX
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC	_IOWR('S', 0x53, struct snd_seq_queue_sync)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC	_IOW ('S', 0x54, struct snd_seq_queue_sync)
-*/
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT	_IOWR('S', 0x49, struct snd_seq_queue_client)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT	_IOW ('S', 0x4a, struct snd_seq_queue_client)
-#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL	_IOWR('S', 0x4b, struct snd_seq_client_pool)
-#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL	_IOW ('S', 0x4c, struct snd_seq_client_pool)
-#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS	_IOW ('S', 0x4e, struct snd_seq_remove_events)
-#define SNDRV_SEQ_IOCTL_QUERY_SUBS	_IOWR('S', 0x4f, struct snd_seq_query_subs)
-#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION	_IOWR('S', 0x50, struct snd_seq_port_subscribe)
-#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT	_IOWR('S', 0x51, struct snd_seq_client_info)
-#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT	_IOWR('S', 0x52, struct snd_seq_port_info)
-
 #endif /* __SOUND_ASEQUENCER_H */
diff --git a/include/sound/asound.h b/include/sound/asound.h
index dfe7d44..c2dff53 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -19,13 +19,9 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
  */
-
 #ifndef __SOUND_ASOUND_H
 #define __SOUND_ASOUND_H
 
-#include <linux/types.h>
-
-#ifdef __KERNEL__
 #include <linux/ioctl.h>
 #include <linux/time.h>
 #include <asm/byteorder.h>
@@ -40,934 +36,5 @@
 #endif
 #endif
 
-#endif /* __KERNEL__ **/
-
-/*
- *  protocol version
- */
-
-#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
-#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
-#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
-#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
-#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) \
-	(SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || \
-	 (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && \
-	   SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
-
-/****************************************************************************
- *                                                                          *
- *        Digital audio interface					    *
- *                                                                          *
- ****************************************************************************/
-
-struct snd_aes_iec958 {
-	unsigned char status[24];	/* AES/IEC958 channel status bits */
-	unsigned char subcode[147];	/* AES/IEC958 subcode bits */
-	unsigned char pad;		/* nothing */
-	unsigned char dig_subframe[4];	/* AES/IEC958 subframe bits */
-};
-
-/****************************************************************************
- *                                                                          *
- *        CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort		    *
- *                                                                          *
- ****************************************************************************/
-
-struct snd_cea_861_aud_if {
-	unsigned char db1_ct_cc; /* coding type and channel count */
-	unsigned char db2_sf_ss; /* sample frequency and size */
-	unsigned char db3; /* not used, all zeros */
-	unsigned char db4_ca; /* channel allocation code */
-	unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */
-};
-
-/****************************************************************************
- *                                                                          *
- *      Section for driver hardware dependent interface - /dev/snd/hw?      *
- *                                                                          *
- ****************************************************************************/
-
-#define SNDRV_HWDEP_VERSION		SNDRV_PROTOCOL_VERSION(1, 0, 1)
-
-enum {
-	SNDRV_HWDEP_IFACE_OPL2 = 0,
-	SNDRV_HWDEP_IFACE_OPL3,
-	SNDRV_HWDEP_IFACE_OPL4,
-	SNDRV_HWDEP_IFACE_SB16CSP,	/* Creative Signal Processor */
-	SNDRV_HWDEP_IFACE_EMU10K1,	/* FX8010 processor in EMU10K1 chip */
-	SNDRV_HWDEP_IFACE_YSS225,	/* Yamaha FX processor */
-	SNDRV_HWDEP_IFACE_ICS2115,	/* Wavetable synth */
-	SNDRV_HWDEP_IFACE_SSCAPE,	/* Ensoniq SoundScape ISA card (MC68EC000) */
-	SNDRV_HWDEP_IFACE_VX,		/* Digigram VX cards */
-	SNDRV_HWDEP_IFACE_MIXART,	/* Digigram miXart cards */
-	SNDRV_HWDEP_IFACE_USX2Y,	/* Tascam US122, US224 & US428 usb */
-	SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */	
-	SNDRV_HWDEP_IFACE_BLUETOOTH,	/* Bluetooth audio */
-	SNDRV_HWDEP_IFACE_USX2Y_PCM,	/* Tascam US122, US224 & US428 rawusb pcm */
-	SNDRV_HWDEP_IFACE_PCXHR,	/* Digigram PCXHR */
-	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 */
-
-	/* Don't forget to change the following: */
-	SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
-};
-
-struct snd_hwdep_info {
-	unsigned int device;		/* WR: device number */
-	int card;			/* R: card number */
-	unsigned char id[64];		/* ID (user selectable) */
-	unsigned char name[80];		/* hwdep name */
-	int iface;			/* hwdep interface */
-	unsigned char reserved[64];	/* reserved for future */
-};
-
-/* generic DSP loader */
-struct snd_hwdep_dsp_status {
-	unsigned int version;		/* R: driver-specific version */
-	unsigned char id[32];		/* R: driver-specific ID string */
-	unsigned int num_dsps;		/* R: number of DSP images to transfer */
-	unsigned int dsp_loaded;	/* R: bit flags indicating the loaded DSPs */
-	unsigned int chip_ready;	/* R: 1 = initialization finished */
-	unsigned char reserved[16];	/* reserved for future use */
-};
-
-struct snd_hwdep_dsp_image {
-	unsigned int index;		/* W: DSP index */
-	unsigned char name[64];		/* W: ID (e.g. file name) */
-	unsigned char __user *image;	/* W: binary image */
-	size_t length;			/* W: size of image in bytes */
-	unsigned long driver_data;	/* W: driver-specific data */
-};
-
-#define SNDRV_HWDEP_IOCTL_PVERSION	_IOR ('H', 0x00, int)
-#define SNDRV_HWDEP_IOCTL_INFO		_IOR ('H', 0x01, struct snd_hwdep_info)
-#define SNDRV_HWDEP_IOCTL_DSP_STATUS	_IOR('H', 0x02, struct snd_hwdep_dsp_status)
-#define SNDRV_HWDEP_IOCTL_DSP_LOAD	_IOW('H', 0x03, struct snd_hwdep_dsp_image)
-
-/*****************************************************************************
- *                                                                           *
- *             Digital Audio (PCM) interface - /dev/snd/pcm??                *
- *                                                                           *
- *****************************************************************************/
-
-#define SNDRV_PCM_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 10)
-
-typedef unsigned long snd_pcm_uframes_t;
-typedef signed long snd_pcm_sframes_t;
-
-enum {
-	SNDRV_PCM_CLASS_GENERIC = 0,	/* standard mono or stereo device */
-	SNDRV_PCM_CLASS_MULTI,		/* multichannel device */
-	SNDRV_PCM_CLASS_MODEM,		/* software modem class */
-	SNDRV_PCM_CLASS_DIGITIZER,	/* digitizer class */
-	/* Don't forget to change the following: */
-	SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
-};
-
-enum {
-	SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */
-	SNDRV_PCM_SUBCLASS_MULTI_MIX,	/* multichannel subdevices are mixed together */
-	/* Don't forget to change the following: */
-	SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
-};
-
-enum {
-	SNDRV_PCM_STREAM_PLAYBACK = 0,
-	SNDRV_PCM_STREAM_CAPTURE,
-	SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
-};
-
-typedef int __bitwise snd_pcm_access_t;
-#define	SNDRV_PCM_ACCESS_MMAP_INTERLEAVED	((__force snd_pcm_access_t) 0) /* interleaved mmap */
-#define	SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED	((__force snd_pcm_access_t) 1) /* noninterleaved mmap */
-#define	SNDRV_PCM_ACCESS_MMAP_COMPLEX		((__force snd_pcm_access_t) 2) /* complex mmap */
-#define	SNDRV_PCM_ACCESS_RW_INTERLEAVED		((__force snd_pcm_access_t) 3) /* readi/writei */
-#define	SNDRV_PCM_ACCESS_RW_NONINTERLEAVED	((__force snd_pcm_access_t) 4) /* readn/writen */
-#define	SNDRV_PCM_ACCESS_LAST		SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
-
-typedef int __bitwise snd_pcm_format_t;
-#define	SNDRV_PCM_FORMAT_S8	((__force snd_pcm_format_t) 0)
-#define	SNDRV_PCM_FORMAT_U8	((__force snd_pcm_format_t) 1)
-#define	SNDRV_PCM_FORMAT_S16_LE	((__force snd_pcm_format_t) 2)
-#define	SNDRV_PCM_FORMAT_S16_BE	((__force snd_pcm_format_t) 3)
-#define	SNDRV_PCM_FORMAT_U16_LE	((__force snd_pcm_format_t) 4)
-#define	SNDRV_PCM_FORMAT_U16_BE	((__force snd_pcm_format_t) 5)
-#define	SNDRV_PCM_FORMAT_S24_LE	((__force snd_pcm_format_t) 6) /* low three bytes */
-#define	SNDRV_PCM_FORMAT_S24_BE	((__force snd_pcm_format_t) 7) /* low three bytes */
-#define	SNDRV_PCM_FORMAT_U24_LE	((__force snd_pcm_format_t) 8) /* low three bytes */
-#define	SNDRV_PCM_FORMAT_U24_BE	((__force snd_pcm_format_t) 9) /* low three bytes */
-#define	SNDRV_PCM_FORMAT_S32_LE	((__force snd_pcm_format_t) 10)
-#define	SNDRV_PCM_FORMAT_S32_BE	((__force snd_pcm_format_t) 11)
-#define	SNDRV_PCM_FORMAT_U32_LE	((__force snd_pcm_format_t) 12)
-#define	SNDRV_PCM_FORMAT_U32_BE	((__force snd_pcm_format_t) 13)
-#define	SNDRV_PCM_FORMAT_FLOAT_LE	((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
-#define	SNDRV_PCM_FORMAT_FLOAT_BE	((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
-#define	SNDRV_PCM_FORMAT_FLOAT64_LE	((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
-#define	SNDRV_PCM_FORMAT_FLOAT64_BE	((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
-#define	SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */
-#define	SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */
-#define	SNDRV_PCM_FORMAT_MU_LAW		((__force snd_pcm_format_t) 20)
-#define	SNDRV_PCM_FORMAT_A_LAW		((__force snd_pcm_format_t) 21)
-#define	SNDRV_PCM_FORMAT_IMA_ADPCM	((__force snd_pcm_format_t) 22)
-#define	SNDRV_PCM_FORMAT_MPEG		((__force snd_pcm_format_t) 23)
-#define	SNDRV_PCM_FORMAT_GSM		((__force snd_pcm_format_t) 24)
-#define	SNDRV_PCM_FORMAT_SPECIAL	((__force snd_pcm_format_t) 31)
-#define	SNDRV_PCM_FORMAT_S24_3LE	((__force snd_pcm_format_t) 32)	/* in three bytes */
-#define	SNDRV_PCM_FORMAT_S24_3BE	((__force snd_pcm_format_t) 33)	/* in three bytes */
-#define	SNDRV_PCM_FORMAT_U24_3LE	((__force snd_pcm_format_t) 34)	/* in three bytes */
-#define	SNDRV_PCM_FORMAT_U24_3BE	((__force snd_pcm_format_t) 35)	/* in three bytes */
-#define	SNDRV_PCM_FORMAT_S20_3LE	((__force snd_pcm_format_t) 36)	/* in three bytes */
-#define	SNDRV_PCM_FORMAT_S20_3BE	((__force snd_pcm_format_t) 37)	/* in three bytes */
-#define	SNDRV_PCM_FORMAT_U20_3LE	((__force snd_pcm_format_t) 38)	/* in three bytes */
-#define	SNDRV_PCM_FORMAT_U20_3BE	((__force snd_pcm_format_t) 39)	/* in three bytes */
-#define	SNDRV_PCM_FORMAT_S18_3LE	((__force snd_pcm_format_t) 40)	/* in three bytes */
-#define	SNDRV_PCM_FORMAT_S18_3BE	((__force snd_pcm_format_t) 41)	/* in three bytes */
-#define	SNDRV_PCM_FORMAT_U18_3LE	((__force snd_pcm_format_t) 42)	/* in three bytes */
-#define	SNDRV_PCM_FORMAT_U18_3BE	((__force snd_pcm_format_t) 43)	/* in three bytes */
-#define	SNDRV_PCM_FORMAT_G723_24	((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */
-#define	SNDRV_PCM_FORMAT_G723_24_1B	((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
-#define	SNDRV_PCM_FORMAT_G723_40	((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
-#define	SNDRV_PCM_FORMAT_G723_40_1B	((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
-#define	SNDRV_PCM_FORMAT_LAST		SNDRV_PCM_FORMAT_G723_40_1B
-
-#ifdef SNDRV_LITTLE_ENDIAN
-#define	SNDRV_PCM_FORMAT_S16		SNDRV_PCM_FORMAT_S16_LE
-#define	SNDRV_PCM_FORMAT_U16		SNDRV_PCM_FORMAT_U16_LE
-#define	SNDRV_PCM_FORMAT_S24		SNDRV_PCM_FORMAT_S24_LE
-#define	SNDRV_PCM_FORMAT_U24		SNDRV_PCM_FORMAT_U24_LE
-#define	SNDRV_PCM_FORMAT_S32		SNDRV_PCM_FORMAT_S32_LE
-#define	SNDRV_PCM_FORMAT_U32		SNDRV_PCM_FORMAT_U32_LE
-#define	SNDRV_PCM_FORMAT_FLOAT		SNDRV_PCM_FORMAT_FLOAT_LE
-#define	SNDRV_PCM_FORMAT_FLOAT64	SNDRV_PCM_FORMAT_FLOAT64_LE
-#define	SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
-#endif
-#ifdef SNDRV_BIG_ENDIAN
-#define	SNDRV_PCM_FORMAT_S16		SNDRV_PCM_FORMAT_S16_BE
-#define	SNDRV_PCM_FORMAT_U16		SNDRV_PCM_FORMAT_U16_BE
-#define	SNDRV_PCM_FORMAT_S24		SNDRV_PCM_FORMAT_S24_BE
-#define	SNDRV_PCM_FORMAT_U24		SNDRV_PCM_FORMAT_U24_BE
-#define	SNDRV_PCM_FORMAT_S32		SNDRV_PCM_FORMAT_S32_BE
-#define	SNDRV_PCM_FORMAT_U32		SNDRV_PCM_FORMAT_U32_BE
-#define	SNDRV_PCM_FORMAT_FLOAT		SNDRV_PCM_FORMAT_FLOAT_BE
-#define	SNDRV_PCM_FORMAT_FLOAT64	SNDRV_PCM_FORMAT_FLOAT64_BE
-#define	SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
-#endif
-
-typedef int __bitwise snd_pcm_subformat_t;
-#define	SNDRV_PCM_SUBFORMAT_STD		((__force snd_pcm_subformat_t) 0)
-#define	SNDRV_PCM_SUBFORMAT_LAST	SNDRV_PCM_SUBFORMAT_STD
-
-#define SNDRV_PCM_INFO_MMAP		0x00000001	/* hardware supports mmap */
-#define SNDRV_PCM_INFO_MMAP_VALID	0x00000002	/* period data are valid during transfer */
-#define SNDRV_PCM_INFO_DOUBLE		0x00000004	/* Double buffering needed for PCM start/stop */
-#define SNDRV_PCM_INFO_BATCH		0x00000010	/* double buffering */
-#define SNDRV_PCM_INFO_INTERLEAVED	0x00000100	/* channels are interleaved */
-#define SNDRV_PCM_INFO_NONINTERLEAVED	0x00000200	/* channels are not interleaved */
-#define SNDRV_PCM_INFO_COMPLEX		0x00000400	/* complex frame organization (mmap only) */
-#define SNDRV_PCM_INFO_BLOCK_TRANSFER	0x00010000	/* hardware transfer block of samples */
-#define SNDRV_PCM_INFO_OVERRANGE	0x00020000	/* hardware supports ADC (capture) overrange detection */
-#define SNDRV_PCM_INFO_RESUME		0x00040000	/* hardware supports stream resume after suspend */
-#define SNDRV_PCM_INFO_PAUSE		0x00080000	/* pause ioctl is supported */
-#define SNDRV_PCM_INFO_HALF_DUPLEX	0x00100000	/* only half duplex */
-#define SNDRV_PCM_INFO_JOINT_DUPLEX	0x00200000	/* playback and capture stream are somewhat correlated */
-#define SNDRV_PCM_INFO_SYNC_START	0x00400000	/* pcm support some kind of sync go */
-#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP	0x00800000	/* period wakeup can be disabled */
-#define SNDRV_PCM_INFO_FIFO_IN_FRAMES	0x80000000	/* internal kernel flag - FIFO size is in frames */
-
-typedef int __bitwise snd_pcm_state_t;
-#define	SNDRV_PCM_STATE_OPEN		((__force snd_pcm_state_t) 0) /* stream is open */
-#define	SNDRV_PCM_STATE_SETUP		((__force snd_pcm_state_t) 1) /* stream has a setup */
-#define	SNDRV_PCM_STATE_PREPARED	((__force snd_pcm_state_t) 2) /* stream is ready to start */
-#define	SNDRV_PCM_STATE_RUNNING		((__force snd_pcm_state_t) 3) /* stream is running */
-#define	SNDRV_PCM_STATE_XRUN		((__force snd_pcm_state_t) 4) /* stream reached an xrun */
-#define	SNDRV_PCM_STATE_DRAINING	((__force snd_pcm_state_t) 5) /* stream is draining */
-#define	SNDRV_PCM_STATE_PAUSED		((__force snd_pcm_state_t) 6) /* stream is paused */
-#define	SNDRV_PCM_STATE_SUSPENDED	((__force snd_pcm_state_t) 7) /* hardware is suspended */
-#define	SNDRV_PCM_STATE_DISCONNECTED	((__force snd_pcm_state_t) 8) /* hardware is disconnected */
-#define	SNDRV_PCM_STATE_LAST		SNDRV_PCM_STATE_DISCONNECTED
-
-enum {
-	SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
-	SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
-	SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
-};
-
-union snd_pcm_sync_id {
-	unsigned char id[16];
-	unsigned short id16[8];
-	unsigned int id32[4];
-};
-
-struct snd_pcm_info {
-	unsigned int device;		/* RO/WR (control): device number */
-	unsigned int subdevice;		/* RO/WR (control): subdevice number */
-	int stream;			/* RO/WR (control): stream direction */
-	int card;			/* R: card number */
-	unsigned char id[64];		/* ID (user selectable) */
-	unsigned char name[80];		/* name of this device */
-	unsigned char subname[32];	/* subdevice name */
-	int dev_class;			/* SNDRV_PCM_CLASS_* */
-	int dev_subclass;		/* SNDRV_PCM_SUBCLASS_* */
-	unsigned int subdevices_count;
-	unsigned int subdevices_avail;
-	union snd_pcm_sync_id sync;	/* hardware synchronization ID */
-	unsigned char reserved[64];	/* reserved for future... */
-};
-
-typedef int snd_pcm_hw_param_t;
-#define	SNDRV_PCM_HW_PARAM_ACCESS	0	/* Access type */
-#define	SNDRV_PCM_HW_PARAM_FORMAT	1	/* Format */
-#define	SNDRV_PCM_HW_PARAM_SUBFORMAT	2	/* Subformat */
-#define	SNDRV_PCM_HW_PARAM_FIRST_MASK	SNDRV_PCM_HW_PARAM_ACCESS
-#define	SNDRV_PCM_HW_PARAM_LAST_MASK	SNDRV_PCM_HW_PARAM_SUBFORMAT
-
-#define	SNDRV_PCM_HW_PARAM_SAMPLE_BITS	8	/* Bits per sample */
-#define	SNDRV_PCM_HW_PARAM_FRAME_BITS	9	/* Bits per frame */
-#define	SNDRV_PCM_HW_PARAM_CHANNELS	10	/* Channels */
-#define	SNDRV_PCM_HW_PARAM_RATE		11	/* Approx rate */
-#define	SNDRV_PCM_HW_PARAM_PERIOD_TIME	12	/* Approx distance between
-						 * interrupts in us
-						 */
-#define	SNDRV_PCM_HW_PARAM_PERIOD_SIZE	13	/* Approx frames between
-						 * interrupts
-						 */
-#define	SNDRV_PCM_HW_PARAM_PERIOD_BYTES	14	/* Approx bytes between
-						 * interrupts
-						 */
-#define	SNDRV_PCM_HW_PARAM_PERIODS	15	/* Approx interrupts per
-						 * buffer
-						 */
-#define	SNDRV_PCM_HW_PARAM_BUFFER_TIME	16	/* Approx duration of buffer
-						 * in us
-						 */
-#define	SNDRV_PCM_HW_PARAM_BUFFER_SIZE	17	/* Size of buffer in frames */
-#define	SNDRV_PCM_HW_PARAM_BUFFER_BYTES	18	/* Size of buffer in bytes */
-#define	SNDRV_PCM_HW_PARAM_TICK_TIME	19	/* Approx tick duration in us */
-#define	SNDRV_PCM_HW_PARAM_FIRST_INTERVAL	SNDRV_PCM_HW_PARAM_SAMPLE_BITS
-#define	SNDRV_PCM_HW_PARAM_LAST_INTERVAL	SNDRV_PCM_HW_PARAM_TICK_TIME
-
-#define SNDRV_PCM_HW_PARAMS_NORESAMPLE	(1<<0)	/* avoid rate resampling */
-#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER	(1<<1)	/* export buffer */
-#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP	(1<<2)	/* disable period wakeups */
-
-struct snd_interval {
-	unsigned int min, max;
-	unsigned int openmin:1,
-		     openmax:1,
-		     integer:1,
-		     empty:1;
-};
-
-#define SNDRV_MASK_MAX	256
-
-struct snd_mask {
-	__u32 bits[(SNDRV_MASK_MAX+31)/32];
-};
-
-struct snd_pcm_hw_params {
-	unsigned int flags;
-	struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - 
-			       SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
-	struct snd_mask mres[5];	/* reserved masks */
-	struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
-				        SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
-	struct snd_interval ires[9];	/* reserved intervals */
-	unsigned int rmask;		/* W: requested masks */
-	unsigned int cmask;		/* R: changed masks */
-	unsigned int info;		/* R: Info flags for returned setup */
-	unsigned int msbits;		/* R: used most significant bits */
-	unsigned int rate_num;		/* R: rate numerator */
-	unsigned int rate_den;		/* R: rate denominator */
-	snd_pcm_uframes_t fifo_size;	/* R: chip FIFO size in frames */
-	unsigned char reserved[64];	/* reserved for future */
-};
-
-enum {
-	SNDRV_PCM_TSTAMP_NONE = 0,
-	SNDRV_PCM_TSTAMP_ENABLE,
-	SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
-};
-
-struct snd_pcm_sw_params {
-	int tstamp_mode;			/* timestamp mode */
-	unsigned int period_step;
-	unsigned int sleep_min;			/* min ticks to sleep */
-	snd_pcm_uframes_t avail_min;		/* min avail frames for wakeup */
-	snd_pcm_uframes_t xfer_align;		/* obsolete: xfer size need to be a multiple */
-	snd_pcm_uframes_t start_threshold;	/* min hw_avail frames for automatic start */
-	snd_pcm_uframes_t stop_threshold;	/* min avail frames for automatic stop */
-	snd_pcm_uframes_t silence_threshold;	/* min distance from noise for silence filling */
-	snd_pcm_uframes_t silence_size;		/* silence block size */
-	snd_pcm_uframes_t boundary;		/* pointers wrap point */
-	unsigned char reserved[64];		/* reserved for future */
-};
-
-struct snd_pcm_channel_info {
-	unsigned int channel;
-	__kernel_off_t offset;		/* mmap offset */
-	unsigned int first;		/* offset to first sample in bits */
-	unsigned int step;		/* samples distance in bits */
-};
-
-struct snd_pcm_status {
-	snd_pcm_state_t state;		/* stream state */
-	struct timespec trigger_tstamp;	/* time when stream was started/stopped/paused */
-	struct timespec tstamp;		/* reference timestamp */
-	snd_pcm_uframes_t appl_ptr;	/* appl ptr */
-	snd_pcm_uframes_t hw_ptr;	/* hw ptr */
-	snd_pcm_sframes_t delay;	/* current delay in frames */
-	snd_pcm_uframes_t avail;	/* number of frames available */
-	snd_pcm_uframes_t avail_max;	/* max frames available on hw since last status */
-	snd_pcm_uframes_t overrange;	/* count of ADC (capture) overrange detections from last status */
-	snd_pcm_state_t suspended_state; /* suspended stream state */
-	unsigned char reserved[60];	/* must be filled with zero */
-};
-
-struct snd_pcm_mmap_status {
-	snd_pcm_state_t state;		/* RO: state - SNDRV_PCM_STATE_XXXX */
-	int pad1;			/* Needed for 64 bit alignment */
-	snd_pcm_uframes_t hw_ptr;	/* RO: hw ptr (0...boundary-1) */
-	struct timespec tstamp;		/* Timestamp */
-	snd_pcm_state_t suspended_state; /* RO: suspended stream state */
-};
-
-struct snd_pcm_mmap_control {
-	snd_pcm_uframes_t appl_ptr;	/* RW: appl ptr (0...boundary-1) */
-	snd_pcm_uframes_t avail_min;	/* RW: min available frames for wakeup */
-};
-
-#define SNDRV_PCM_SYNC_PTR_HWSYNC	(1<<0)	/* execute hwsync */
-#define SNDRV_PCM_SYNC_PTR_APPL		(1<<1)	/* get appl_ptr from driver (r/w op) */
-#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN	(1<<2)	/* get avail_min from driver */
-
-struct snd_pcm_sync_ptr {
-	unsigned int flags;
-	union {
-		struct snd_pcm_mmap_status status;
-		unsigned char reserved[64];
-	} s;
-	union {
-		struct snd_pcm_mmap_control control;
-		unsigned char reserved[64];
-	} c;
-};
-
-struct snd_xferi {
-	snd_pcm_sframes_t result;
-	void __user *buf;
-	snd_pcm_uframes_t frames;
-};
-
-struct snd_xfern {
-	snd_pcm_sframes_t result;
-	void __user * __user *bufs;
-	snd_pcm_uframes_t frames;
-};
-
-enum {
-	SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0,	/* gettimeofday equivalent */
-	SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,	/* posix_clock_monotonic equivalent */
-	SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
-};
-
-/* channel positions */
-enum {
-	SNDRV_CHMAP_UNKNOWN = 0,
-	SNDRV_CHMAP_NA,		/* N/A, silent */
-	SNDRV_CHMAP_MONO,	/* mono stream */
-	/* this follows the alsa-lib mixer channel value + 3 */
-	SNDRV_CHMAP_FL,		/* front left */
-	SNDRV_CHMAP_FR,		/* front right */
-	SNDRV_CHMAP_RL,		/* rear left */
-	SNDRV_CHMAP_RR,		/* rear right */
-	SNDRV_CHMAP_FC,		/* front center */
-	SNDRV_CHMAP_LFE,	/* LFE */
-	SNDRV_CHMAP_SL,		/* side left */
-	SNDRV_CHMAP_SR,		/* side right */
-	SNDRV_CHMAP_RC,		/* rear center */
-	/* new definitions */
-	SNDRV_CHMAP_FLC,	/* front left center */
-	SNDRV_CHMAP_FRC,	/* front right center */
-	SNDRV_CHMAP_RLC,	/* rear left center */
-	SNDRV_CHMAP_RRC,	/* rear right center */
-	SNDRV_CHMAP_FLW,	/* front left wide */
-	SNDRV_CHMAP_FRW,	/* front right wide */
-	SNDRV_CHMAP_FLH,	/* front left high */
-	SNDRV_CHMAP_FCH,	/* front center high */
-	SNDRV_CHMAP_FRH,	/* front right high */
-	SNDRV_CHMAP_TC,		/* top center */
-	SNDRV_CHMAP_TFL,	/* top front left */
-	SNDRV_CHMAP_TFR,	/* top front right */
-	SNDRV_CHMAP_TFC,	/* top front center */
-	SNDRV_CHMAP_TRL,	/* top rear left */
-	SNDRV_CHMAP_TRR,	/* top rear right */
-	SNDRV_CHMAP_TRC,	/* top rear center */
-	SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC,
-};
-
-#define SNDRV_CHMAP_POSITION_MASK	0xffff
-#define SNDRV_CHMAP_PHASE_INVERSE	(0x01 << 16)
-#define SNDRV_CHMAP_DRIVER_SPEC		(0x02 << 16)
-
-#define SNDRV_PCM_IOCTL_PVERSION	_IOR('A', 0x00, int)
-#define SNDRV_PCM_IOCTL_INFO		_IOR('A', 0x01, struct snd_pcm_info)
-#define SNDRV_PCM_IOCTL_TSTAMP		_IOW('A', 0x02, int)
-#define SNDRV_PCM_IOCTL_TTSTAMP		_IOW('A', 0x03, int)
-#define SNDRV_PCM_IOCTL_HW_REFINE	_IOWR('A', 0x10, struct snd_pcm_hw_params)
-#define SNDRV_PCM_IOCTL_HW_PARAMS	_IOWR('A', 0x11, struct snd_pcm_hw_params)
-#define SNDRV_PCM_IOCTL_HW_FREE		_IO('A', 0x12)
-#define SNDRV_PCM_IOCTL_SW_PARAMS	_IOWR('A', 0x13, struct snd_pcm_sw_params)
-#define SNDRV_PCM_IOCTL_STATUS		_IOR('A', 0x20, struct snd_pcm_status)
-#define SNDRV_PCM_IOCTL_DELAY		_IOR('A', 0x21, snd_pcm_sframes_t)
-#define SNDRV_PCM_IOCTL_HWSYNC		_IO('A', 0x22)
-#define SNDRV_PCM_IOCTL_SYNC_PTR	_IOWR('A', 0x23, struct snd_pcm_sync_ptr)
-#define SNDRV_PCM_IOCTL_CHANNEL_INFO	_IOR('A', 0x32, struct snd_pcm_channel_info)
-#define SNDRV_PCM_IOCTL_PREPARE		_IO('A', 0x40)
-#define SNDRV_PCM_IOCTL_RESET		_IO('A', 0x41)
-#define SNDRV_PCM_IOCTL_START		_IO('A', 0x42)
-#define SNDRV_PCM_IOCTL_DROP		_IO('A', 0x43)
-#define SNDRV_PCM_IOCTL_DRAIN		_IO('A', 0x44)
-#define SNDRV_PCM_IOCTL_PAUSE		_IOW('A', 0x45, int)
-#define SNDRV_PCM_IOCTL_REWIND		_IOW('A', 0x46, snd_pcm_uframes_t)
-#define SNDRV_PCM_IOCTL_RESUME		_IO('A', 0x47)
-#define SNDRV_PCM_IOCTL_XRUN		_IO('A', 0x48)
-#define SNDRV_PCM_IOCTL_FORWARD		_IOW('A', 0x49, snd_pcm_uframes_t)
-#define SNDRV_PCM_IOCTL_WRITEI_FRAMES	_IOW('A', 0x50, struct snd_xferi)
-#define SNDRV_PCM_IOCTL_READI_FRAMES	_IOR('A', 0x51, struct snd_xferi)
-#define SNDRV_PCM_IOCTL_WRITEN_FRAMES	_IOW('A', 0x52, struct snd_xfern)
-#define SNDRV_PCM_IOCTL_READN_FRAMES	_IOR('A', 0x53, struct snd_xfern)
-#define SNDRV_PCM_IOCTL_LINK		_IOW('A', 0x60, int)
-#define SNDRV_PCM_IOCTL_UNLINK		_IO('A', 0x61)
-
-/*****************************************************************************
- *                                                                           *
- *                            MIDI v1.0 interface                            *
- *                                                                           *
- *****************************************************************************/
-
-/*
- *  Raw MIDI section - /dev/snd/midi??
- */
-
-#define SNDRV_RAWMIDI_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 0)
-
-enum {
-	SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
-	SNDRV_RAWMIDI_STREAM_INPUT,
-	SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
-};
-
-#define SNDRV_RAWMIDI_INFO_OUTPUT		0x00000001
-#define SNDRV_RAWMIDI_INFO_INPUT		0x00000002
-#define SNDRV_RAWMIDI_INFO_DUPLEX		0x00000004
-
-struct snd_rawmidi_info {
-	unsigned int device;		/* RO/WR (control): device number */
-	unsigned int subdevice;		/* RO/WR (control): subdevice number */
-	int stream;			/* WR: stream */
-	int card;			/* R: card number */
-	unsigned int flags;		/* SNDRV_RAWMIDI_INFO_XXXX */
-	unsigned char id[64];		/* ID (user selectable) */
-	unsigned char name[80];		/* name of device */
-	unsigned char subname[32];	/* name of active or selected subdevice */
-	unsigned int subdevices_count;
-	unsigned int subdevices_avail;
-	unsigned char reserved[64];	/* reserved for future use */
-};
-
-struct snd_rawmidi_params {
-	int stream;
-	size_t buffer_size;		/* queue size in bytes */
-	size_t avail_min;		/* minimum avail bytes for wakeup */
-	unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */
-	unsigned char reserved[16];	/* reserved for future use */
-};
-
-struct snd_rawmidi_status {
-	int stream;
-	struct timespec tstamp;		/* Timestamp */
-	size_t avail;			/* available bytes */
-	size_t xruns;			/* count of overruns since last status (in bytes) */
-	unsigned char reserved[16];	/* reserved for future use */
-};
-
-#define SNDRV_RAWMIDI_IOCTL_PVERSION	_IOR('W', 0x00, int)
-#define SNDRV_RAWMIDI_IOCTL_INFO	_IOR('W', 0x01, struct snd_rawmidi_info)
-#define SNDRV_RAWMIDI_IOCTL_PARAMS	_IOWR('W', 0x10, struct snd_rawmidi_params)
-#define SNDRV_RAWMIDI_IOCTL_STATUS	_IOWR('W', 0x20, struct snd_rawmidi_status)
-#define SNDRV_RAWMIDI_IOCTL_DROP	_IOW('W', 0x30, int)
-#define SNDRV_RAWMIDI_IOCTL_DRAIN	_IOW('W', 0x31, int)
-
-/*
- *  Timer section - /dev/snd/timer
- */
-
-#define SNDRV_TIMER_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 6)
-
-enum {
-	SNDRV_TIMER_CLASS_NONE = -1,
-	SNDRV_TIMER_CLASS_SLAVE = 0,
-	SNDRV_TIMER_CLASS_GLOBAL,
-	SNDRV_TIMER_CLASS_CARD,
-	SNDRV_TIMER_CLASS_PCM,
-	SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
-};
-
-/* slave timer classes */
-enum {
-	SNDRV_TIMER_SCLASS_NONE = 0,
-	SNDRV_TIMER_SCLASS_APPLICATION,
-	SNDRV_TIMER_SCLASS_SEQUENCER,		/* alias */
-	SNDRV_TIMER_SCLASS_OSS_SEQUENCER,	/* alias */
-	SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
-};
-
-/* global timers (device member) */
-#define SNDRV_TIMER_GLOBAL_SYSTEM	0
-#define SNDRV_TIMER_GLOBAL_RTC		1
-#define SNDRV_TIMER_GLOBAL_HPET		2
-#define SNDRV_TIMER_GLOBAL_HRTIMER	3
-
-/* info flags */
-#define SNDRV_TIMER_FLG_SLAVE		(1<<0)	/* cannot be controlled */
-
-struct snd_timer_id {
-	int dev_class;
-	int dev_sclass;
-	int card;
-	int device;
-	int subdevice;
-};
-
-struct snd_timer_ginfo {
-	struct snd_timer_id tid;	/* requested timer ID */
-	unsigned int flags;		/* timer flags - SNDRV_TIMER_FLG_* */
-	int card;			/* card number */
-	unsigned char id[64];		/* timer identification */
-	unsigned char name[80];		/* timer name */
-	unsigned long reserved0;	/* reserved for future use */
-	unsigned long resolution;	/* average period resolution in ns */
-	unsigned long resolution_min;	/* minimal period resolution in ns */
-	unsigned long resolution_max;	/* maximal period resolution in ns */
-	unsigned int clients;		/* active timer clients */
-	unsigned char reserved[32];
-};
-
-struct snd_timer_gparams {
-	struct snd_timer_id tid;	/* requested timer ID */
-	unsigned long period_num;	/* requested precise period duration (in seconds) - numerator */
-	unsigned long period_den;	/* requested precise period duration (in seconds) - denominator */
-	unsigned char reserved[32];
-};
-
-struct snd_timer_gstatus {
-	struct snd_timer_id tid;	/* requested timer ID */
-	unsigned long resolution;	/* current period resolution in ns */
-	unsigned long resolution_num;	/* precise current period resolution (in seconds) - numerator */
-	unsigned long resolution_den;	/* precise current period resolution (in seconds) - denominator */
-	unsigned char reserved[32];
-};
-
-struct snd_timer_select {
-	struct snd_timer_id id;	/* bind to timer ID */
-	unsigned char reserved[32];	/* reserved */
-};
-
-struct snd_timer_info {
-	unsigned int flags;		/* timer flags - SNDRV_TIMER_FLG_* */
-	int card;			/* card number */
-	unsigned char id[64];		/* timer identificator */
-	unsigned char name[80];		/* timer name */
-	unsigned long reserved0;	/* reserved for future use */
-	unsigned long resolution;	/* average period resolution in ns */
-	unsigned char reserved[64];	/* reserved */
-};
-
-#define SNDRV_TIMER_PSFLG_AUTO		(1<<0)	/* auto start, otherwise one-shot */
-#define SNDRV_TIMER_PSFLG_EXCLUSIVE	(1<<1)	/* exclusive use, precise start/stop/pause/continue */
-#define SNDRV_TIMER_PSFLG_EARLY_EVENT	(1<<2)	/* write early event to the poll queue */
-
-struct snd_timer_params {
-	unsigned int flags;		/* flags - SNDRV_MIXER_PSFLG_* */
-	unsigned int ticks;		/* requested resolution in ticks */
-	unsigned int queue_size;	/* total size of queue (32-1024) */
-	unsigned int reserved0;		/* reserved, was: failure locations */
-	unsigned int filter;		/* event filter (bitmask of SNDRV_TIMER_EVENT_*) */
-	unsigned char reserved[60];	/* reserved */
-};
-
-struct snd_timer_status {
-	struct timespec tstamp;		/* Timestamp - last update */
-	unsigned int resolution;	/* current period resolution in ns */
-	unsigned int lost;		/* counter of master tick lost */
-	unsigned int overrun;		/* count of read queue overruns */
-	unsigned int queue;		/* used queue size */
-	unsigned char reserved[64];	/* reserved */
-};
-
-#define SNDRV_TIMER_IOCTL_PVERSION	_IOR('T', 0x00, int)
-#define SNDRV_TIMER_IOCTL_NEXT_DEVICE	_IOWR('T', 0x01, struct snd_timer_id)
-#define SNDRV_TIMER_IOCTL_TREAD		_IOW('T', 0x02, int)
-#define SNDRV_TIMER_IOCTL_GINFO		_IOWR('T', 0x03, struct snd_timer_ginfo)
-#define SNDRV_TIMER_IOCTL_GPARAMS	_IOW('T', 0x04, struct snd_timer_gparams)
-#define SNDRV_TIMER_IOCTL_GSTATUS	_IOWR('T', 0x05, struct snd_timer_gstatus)
-#define SNDRV_TIMER_IOCTL_SELECT	_IOW('T', 0x10, struct snd_timer_select)
-#define SNDRV_TIMER_IOCTL_INFO		_IOR('T', 0x11, struct snd_timer_info)
-#define SNDRV_TIMER_IOCTL_PARAMS	_IOW('T', 0x12, struct snd_timer_params)
-#define SNDRV_TIMER_IOCTL_STATUS	_IOR('T', 0x14, struct snd_timer_status)
-/* The following four ioctls are changed since 1.0.9 due to confliction */
-#define SNDRV_TIMER_IOCTL_START		_IO('T', 0xa0)
-#define SNDRV_TIMER_IOCTL_STOP		_IO('T', 0xa1)
-#define SNDRV_TIMER_IOCTL_CONTINUE	_IO('T', 0xa2)
-#define SNDRV_TIMER_IOCTL_PAUSE		_IO('T', 0xa3)
-
-struct snd_timer_read {
-	unsigned int resolution;
-	unsigned int ticks;
-};
-
-enum {
-	SNDRV_TIMER_EVENT_RESOLUTION = 0,	/* val = resolution in ns */
-	SNDRV_TIMER_EVENT_TICK,			/* val = ticks */
-	SNDRV_TIMER_EVENT_START,		/* val = resolution in ns */
-	SNDRV_TIMER_EVENT_STOP,			/* val = 0 */
-	SNDRV_TIMER_EVENT_CONTINUE,		/* val = resolution in ns */
-	SNDRV_TIMER_EVENT_PAUSE,		/* val = 0 */
-	SNDRV_TIMER_EVENT_EARLY,		/* val = 0, early event */
-	SNDRV_TIMER_EVENT_SUSPEND,		/* val = 0 */
-	SNDRV_TIMER_EVENT_RESUME,		/* val = resolution in ns */
-	/* master timer events for slave timer instances */
-	SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
-	SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
-	SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
-	SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
-	SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
-	SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
-};
-
-struct snd_timer_tread {
-	int event;
-	struct timespec tstamp;
-	unsigned int val;
-};
-
-/****************************************************************************
- *                                                                          *
- *        Section for driver control interface - /dev/snd/control?          *
- *                                                                          *
- ****************************************************************************/
-
-#define SNDRV_CTL_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 7)
-
-struct snd_ctl_card_info {
-	int card;			/* card number */
-	int pad;			/* reserved for future (was type) */
-	unsigned char id[16];		/* ID of card (user selectable) */
-	unsigned char driver[16];	/* Driver name */
-	unsigned char name[32];		/* Short name of soundcard */
-	unsigned char longname[80];	/* name + info text about soundcard */
-	unsigned char reserved_[16];	/* reserved for future (was ID of mixer) */
-	unsigned char mixername[80];	/* visual mixer identification */
-	unsigned char components[128];	/* card components / fine identification, delimited with one space (AC97 etc..) */
-};
-
-typedef int __bitwise snd_ctl_elem_type_t;
-#define	SNDRV_CTL_ELEM_TYPE_NONE	((__force snd_ctl_elem_type_t) 0) /* invalid */
-#define	SNDRV_CTL_ELEM_TYPE_BOOLEAN	((__force snd_ctl_elem_type_t) 1) /* boolean type */
-#define	SNDRV_CTL_ELEM_TYPE_INTEGER	((__force snd_ctl_elem_type_t) 2) /* integer type */
-#define	SNDRV_CTL_ELEM_TYPE_ENUMERATED	((__force snd_ctl_elem_type_t) 3) /* enumerated type */
-#define	SNDRV_CTL_ELEM_TYPE_BYTES	((__force snd_ctl_elem_type_t) 4) /* byte array */
-#define	SNDRV_CTL_ELEM_TYPE_IEC958	((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */
-#define	SNDRV_CTL_ELEM_TYPE_INTEGER64	((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */
-#define	SNDRV_CTL_ELEM_TYPE_LAST	SNDRV_CTL_ELEM_TYPE_INTEGER64
-
-typedef int __bitwise snd_ctl_elem_iface_t;
-#define	SNDRV_CTL_ELEM_IFACE_CARD	((__force snd_ctl_elem_iface_t) 0) /* global control */
-#define	SNDRV_CTL_ELEM_IFACE_HWDEP	((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */
-#define	SNDRV_CTL_ELEM_IFACE_MIXER	((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */
-#define	SNDRV_CTL_ELEM_IFACE_PCM	((__force snd_ctl_elem_iface_t) 3) /* PCM device */
-#define	SNDRV_CTL_ELEM_IFACE_RAWMIDI	((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */
-#define	SNDRV_CTL_ELEM_IFACE_TIMER	((__force snd_ctl_elem_iface_t) 5) /* timer device */
-#define	SNDRV_CTL_ELEM_IFACE_SEQUENCER	((__force snd_ctl_elem_iface_t) 6) /* sequencer client */
-#define	SNDRV_CTL_ELEM_IFACE_LAST	SNDRV_CTL_ELEM_IFACE_SEQUENCER
-
-#define SNDRV_CTL_ELEM_ACCESS_READ		(1<<0)
-#define SNDRV_CTL_ELEM_ACCESS_WRITE		(1<<1)
-#define SNDRV_CTL_ELEM_ACCESS_READWRITE		(SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
-#define SNDRV_CTL_ELEM_ACCESS_VOLATILE		(1<<2)	/* control value may be changed without a notification */
-#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP		(1<<3)	/* when was control changed */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_READ		(1<<4)	/* TLV read is possible */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE		(1<<5)	/* TLV write is possible */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE	(SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
-#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND	(1<<6)	/* TLV command is possible */
-#define SNDRV_CTL_ELEM_ACCESS_INACTIVE		(1<<8)	/* control does actually nothing, but may be updated */
-#define SNDRV_CTL_ELEM_ACCESS_LOCK		(1<<9)	/* write lock */
-#define SNDRV_CTL_ELEM_ACCESS_OWNER		(1<<10)	/* write lock owner */
-#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK	(1<<28)	/* kernel use a TLV callback */ 
-#define SNDRV_CTL_ELEM_ACCESS_USER		(1<<29) /* user space element */
-/* bits 30 and 31 are obsoleted (for indirect access) */
-
-/* for further details see the ACPI and PCI power management specification */
-#define SNDRV_CTL_POWER_D0		0x0000	/* full On */
-#define SNDRV_CTL_POWER_D1		0x0100	/* partial On */
-#define SNDRV_CTL_POWER_D2		0x0200	/* partial On */
-#define SNDRV_CTL_POWER_D3		0x0300	/* Off */
-#define SNDRV_CTL_POWER_D3hot		(SNDRV_CTL_POWER_D3|0x0000)	/* Off, with power */
-#define SNDRV_CTL_POWER_D3cold		(SNDRV_CTL_POWER_D3|0x0001)	/* Off, without power */
-
-struct snd_ctl_elem_id {
-	unsigned int numid;		/* numeric identifier, zero = invalid */
-	snd_ctl_elem_iface_t iface;	/* interface identifier */
-	unsigned int device;		/* device/client number */
-	unsigned int subdevice;		/* subdevice (substream) number */
-	unsigned char name[44];		/* ASCII name of item */
-	unsigned int index;		/* index of item */
-};
-
-struct snd_ctl_elem_list {
-	unsigned int offset;		/* W: first element ID to get */
-	unsigned int space;		/* W: count of element IDs to get */
-	unsigned int used;		/* R: count of element IDs set */
-	unsigned int count;		/* R: count of all elements */
-	struct snd_ctl_elem_id __user *pids; /* R: IDs */
-	unsigned char reserved[50];
-};
-
-struct snd_ctl_elem_info {
-	struct snd_ctl_elem_id id;	/* W: element ID */
-	snd_ctl_elem_type_t type;	/* R: value type - SNDRV_CTL_ELEM_TYPE_* */
-	unsigned int access;		/* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */
-	unsigned int count;		/* count of values */
-	__kernel_pid_t owner;		/* owner's PID of this control */
-	union {
-		struct {
-			long min;		/* R: minimum value */
-			long max;		/* R: maximum value */
-			long step;		/* R: step (0 variable) */
-		} integer;
-		struct {
-			long long min;		/* R: minimum value */
-			long long max;		/* R: maximum value */
-			long long step;		/* R: step (0 variable) */
-		} integer64;
-		struct {
-			unsigned int items;	/* R: number of items */
-			unsigned int item;	/* W: item number */
-			char name[64];		/* R: value name */
-			__u64 names_ptr;	/* W: names list (ELEM_ADD only) */
-			unsigned int names_length;
-		} enumerated;
-		unsigned char reserved[128];
-	} value;
-	union {
-		unsigned short d[4];		/* dimensions */
-		unsigned short *d_ptr;		/* indirect - obsoleted */
-	} dimen;
-	unsigned char reserved[64-4*sizeof(unsigned short)];
-};
-
-struct snd_ctl_elem_value {
-	struct snd_ctl_elem_id id;	/* W: element ID */
-	unsigned int indirect: 1;	/* W: indirect access - obsoleted */
-	union {
-		union {
-			long value[128];
-			long *value_ptr;	/* obsoleted */
-		} integer;
-		union {
-			long long value[64];
-			long long *value_ptr;	/* obsoleted */
-		} integer64;
-		union {
-			unsigned int item[128];
-			unsigned int *item_ptr;	/* obsoleted */
-		} enumerated;
-		union {
-			unsigned char data[512];
-			unsigned char *data_ptr;	/* obsoleted */
-		} bytes;
-		struct snd_aes_iec958 iec958;
-	} value;		/* RO */
-	struct timespec tstamp;
-	unsigned char reserved[128-sizeof(struct timespec)];
-};
-
-struct snd_ctl_tlv {
-	unsigned int numid;	/* control element numeric identification */
-	unsigned int length;	/* in bytes aligned to 4 */
-	unsigned int tlv[0];	/* first TLV */
-};
-
-#define SNDRV_CTL_IOCTL_PVERSION	_IOR('U', 0x00, int)
-#define SNDRV_CTL_IOCTL_CARD_INFO	_IOR('U', 0x01, struct snd_ctl_card_info)
-#define SNDRV_CTL_IOCTL_ELEM_LIST	_IOWR('U', 0x10, struct snd_ctl_elem_list)
-#define SNDRV_CTL_IOCTL_ELEM_INFO	_IOWR('U', 0x11, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_READ	_IOWR('U', 0x12, struct snd_ctl_elem_value)
-#define SNDRV_CTL_IOCTL_ELEM_WRITE	_IOWR('U', 0x13, struct snd_ctl_elem_value)
-#define SNDRV_CTL_IOCTL_ELEM_LOCK	_IOW('U', 0x14, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_ELEM_UNLOCK	_IOW('U', 0x15, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
-#define SNDRV_CTL_IOCTL_ELEM_ADD	_IOWR('U', 0x17, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_REPLACE	_IOWR('U', 0x18, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_REMOVE	_IOWR('U', 0x19, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_TLV_READ	_IOWR('U', 0x1a, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_TLV_WRITE	_IOWR('U', 0x1b, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_TLV_COMMAND	_IOWR('U', 0x1c, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
-#define SNDRV_CTL_IOCTL_HWDEP_INFO	_IOR('U', 0x21, struct snd_hwdep_info)
-#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE	_IOR('U', 0x30, int)
-#define SNDRV_CTL_IOCTL_PCM_INFO	_IOWR('U', 0x31, struct snd_pcm_info)
-#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
-#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
-#define SNDRV_CTL_IOCTL_RAWMIDI_INFO	_IOWR('U', 0x41, struct snd_rawmidi_info)
-#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
-#define SNDRV_CTL_IOCTL_POWER		_IOWR('U', 0xd0, int)
-#define SNDRV_CTL_IOCTL_POWER_STATE	_IOR('U', 0xd1, int)
-
-/*
- *  Read interface.
- */
-
-enum sndrv_ctl_event_type {
-	SNDRV_CTL_EVENT_ELEM = 0,
-	SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
-};
-
-#define SNDRV_CTL_EVENT_MASK_VALUE	(1<<0)	/* element value was changed */
-#define SNDRV_CTL_EVENT_MASK_INFO	(1<<1)	/* element info was changed */
-#define SNDRV_CTL_EVENT_MASK_ADD	(1<<2)	/* element was added */
-#define SNDRV_CTL_EVENT_MASK_TLV	(1<<3)	/* element TLV tree was changed */
-#define SNDRV_CTL_EVENT_MASK_REMOVE	(~0U)	/* element was removed */
-
-struct snd_ctl_event {
-	int type;	/* event type - SNDRV_CTL_EVENT_* */
-	union {
-		struct {
-			unsigned int mask;
-			struct snd_ctl_elem_id id;
-		} elem;
-		unsigned char data8[60];
-	} data;
-};
-
-/*
- *  Control names
- */
-
-#define SNDRV_CTL_NAME_NONE				""
-#define SNDRV_CTL_NAME_PLAYBACK				"Playback "
-#define SNDRV_CTL_NAME_CAPTURE				"Capture "
-
-#define SNDRV_CTL_NAME_IEC958_NONE			""
-#define SNDRV_CTL_NAME_IEC958_SWITCH			"Switch"
-#define SNDRV_CTL_NAME_IEC958_VOLUME			"Volume"
-#define SNDRV_CTL_NAME_IEC958_DEFAULT			"Default"
-#define SNDRV_CTL_NAME_IEC958_MASK			"Mask"
-#define SNDRV_CTL_NAME_IEC958_CON_MASK			"Con Mask"
-#define SNDRV_CTL_NAME_IEC958_PRO_MASK			"Pro Mask"
-#define SNDRV_CTL_NAME_IEC958_PCM_STREAM		"PCM Stream"
-#define SNDRV_CTL_NAME_IEC958(expl,direction,what)	"IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
-
+#include <uapi/sound/asound.h>
 #endif /* __SOUND_ASOUND_H */
diff --git a/include/sound/asound_fm.h b/include/sound/asound_fm.h
deleted file mode 100644
index c2a4b96..0000000
--- a/include/sound/asound_fm.h
+++ /dev/null
@@ -1,134 +0,0 @@
-#ifndef __SOUND_ASOUND_FM_H
-#define __SOUND_ASOUND_FM_H
-
-/*
- *  Advanced Linux Sound Architecture - ALSA
- *
- *  Interface file between ALSA driver & user space
- *  Copyright (c) 1994-98 by Jaroslav Kysela <perex@perex.cz>,
- *                           4Front Technologies
- *
- *  Direct FM control
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#define SNDRV_DM_FM_MODE_OPL2	0x00
-#define SNDRV_DM_FM_MODE_OPL3	0x01
-
-struct snd_dm_fm_info {
-	unsigned char fm_mode;		/* OPL mode, see SNDRV_DM_FM_MODE_XXX */
-	unsigned char rhythm;		/* percussion mode flag */
-};
-
-/*
- *  Data structure composing an FM "note" or sound event.
- */
-
-struct snd_dm_fm_voice {
-	unsigned char op;		/* operator cell (0 or 1) */
-	unsigned char voice;		/* FM voice (0 to 17) */
-
-	unsigned char am;		/* amplitude modulation */
-	unsigned char vibrato;		/* vibrato effect */
-	unsigned char do_sustain;	/* sustain phase */
-	unsigned char kbd_scale;	/* keyboard scaling */
-	unsigned char harmonic;		/* 4 bits: harmonic and multiplier */
-	unsigned char scale_level;	/* 2 bits: decrease output freq rises */
-	unsigned char volume;		/* 6 bits: volume */
-
-	unsigned char attack;		/* 4 bits: attack rate */
-	unsigned char decay;		/* 4 bits: decay rate */
-	unsigned char sustain;		/* 4 bits: sustain level */
-	unsigned char release;		/* 4 bits: release rate */
-
-	unsigned char feedback;		/* 3 bits: feedback for op0 */
-	unsigned char connection;	/* 0 for serial, 1 for parallel */
-	unsigned char left;		/* stereo left */
-	unsigned char right;		/* stereo right */
-	unsigned char waveform;		/* 3 bits: waveform shape */
-};
-
-/*
- *  This describes an FM note by its voice, octave, frequency number (10bit)
- *  and key on/off.
- */
-
-struct snd_dm_fm_note {
-	unsigned char voice;	/* 0-17 voice channel */
-	unsigned char octave;	/* 3 bits: what octave to play */
-	unsigned int fnum;	/* 10 bits: frequency number */
-	unsigned char key_on;	/* set for active, clear for silent */
-};
-
-/*
- *  FM parameters that apply globally to all voices, and thus are not "notes"
- */
-
-struct snd_dm_fm_params {
-	unsigned char am_depth;		/* amplitude modulation depth (1=hi) */
-	unsigned char vib_depth;	/* vibrato depth (1=hi) */
-	unsigned char kbd_split;	/* keyboard split */
-	unsigned char rhythm;		/* percussion mode select */
-
-	/* This block is the percussion instrument data */
-	unsigned char bass;
-	unsigned char snare;
-	unsigned char tomtom;
-	unsigned char cymbal;
-	unsigned char hihat;
-};
-
-/*
- *  FM mode ioctl settings
- */
-
-#define SNDRV_DM_FM_IOCTL_INFO		_IOR('H', 0x20, struct snd_dm_fm_info)
-#define SNDRV_DM_FM_IOCTL_RESET		_IO ('H', 0x21)
-#define SNDRV_DM_FM_IOCTL_PLAY_NOTE	_IOW('H', 0x22, struct snd_dm_fm_note)
-#define SNDRV_DM_FM_IOCTL_SET_VOICE	_IOW('H', 0x23, struct snd_dm_fm_voice)
-#define SNDRV_DM_FM_IOCTL_SET_PARAMS	_IOW('H', 0x24, struct snd_dm_fm_params)
-#define SNDRV_DM_FM_IOCTL_SET_MODE	_IOW('H', 0x25, int)
-/* for OPL3 only */
-#define SNDRV_DM_FM_IOCTL_SET_CONNECTION	_IOW('H', 0x26, int)
-/* SBI patch management */
-#define SNDRV_DM_FM_IOCTL_CLEAR_PATCHES	_IO ('H', 0x40)
-
-#define SNDRV_DM_FM_OSS_IOCTL_RESET		0x20
-#define SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE		0x21
-#define SNDRV_DM_FM_OSS_IOCTL_SET_VOICE		0x22
-#define SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS	0x23
-#define SNDRV_DM_FM_OSS_IOCTL_SET_MODE		0x24
-#define SNDRV_DM_FM_OSS_IOCTL_SET_OPL		0x25
-
-/*
- * Patch Record - fixed size for write
- */
-
-#define FM_KEY_SBI	"SBI\032"
-#define FM_KEY_2OP	"2OP\032"
-#define FM_KEY_4OP	"4OP\032"
-
-struct sbi_patch {
-	unsigned char prog;
-	unsigned char bank;
-	char key[4];
-	char name[25];
-	char extension[7];
-	unsigned char data[32];
-};
-
-#endif /* __SOUND_ASOUND_FM_H */
diff --git a/include/sound/compress_offload.h b/include/sound/compress_offload.h
deleted file mode 100644
index 05341a4..0000000
--- a/include/sound/compress_offload.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- *  compress_offload.h - compress offload header definations
- *
- *  Copyright (C) 2011 Intel Corporation
- *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
- *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- */
-#ifndef __COMPRESS_OFFLOAD_H
-#define __COMPRESS_OFFLOAD_H
-
-#include <linux/types.h>
-#include <sound/asound.h>
-#include <sound/compress_params.h>
-
-
-#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 0)
-/**
- * struct snd_compressed_buffer: compressed buffer
- * @fragment_size: size of buffer fragment in bytes
- * @fragments: number of such fragments
- */
-struct snd_compressed_buffer {
-	__u32 fragment_size;
-	__u32 fragments;
-};
-
-/**
- * struct snd_compr_params: compressed stream params
- * @buffer: buffer description
- * @codec: codec parameters
- * @no_wake_mode: dont wake on fragment elapsed
- */
-struct snd_compr_params {
-	struct snd_compressed_buffer buffer;
-	struct snd_codec codec;
-	__u8 no_wake_mode;
-};
-
-/**
- * struct snd_compr_tstamp: timestamp descriptor
- * @byte_offset: Byte offset in ring buffer to DSP
- * @copied_total: Total number of bytes copied from/to ring buffer to/by DSP
- * @pcm_frames: Frames decoded or encoded by DSP. This field will evolve by
- *	large steps and should only be used to monitor encoding/decoding
- *	progress. It shall not be used for timing estimates.
- * @pcm_io_frames: Frames rendered or received by DSP into a mixer or an audio
- * output/input. This field should be used for A/V sync or time estimates.
- * @sampling_rate: sampling rate of audio
- */
-struct snd_compr_tstamp {
-	__u32 byte_offset;
-	__u32 copied_total;
-	snd_pcm_uframes_t pcm_frames;
-	snd_pcm_uframes_t pcm_io_frames;
-	__u32 sampling_rate;
-};
-
-/**
- * struct snd_compr_avail: avail descriptor
- * @avail: Number of bytes available in ring buffer for writing/reading
- * @tstamp: timestamp infomation
- */
-struct snd_compr_avail {
-	__u64 avail;
-	struct snd_compr_tstamp tstamp;
-};
-
-enum snd_compr_direction {
-	SND_COMPRESS_PLAYBACK = 0,
-	SND_COMPRESS_CAPTURE
-};
-
-/**
- * struct snd_compr_caps: caps descriptor
- * @codecs: pointer to array of codecs
- * @direction: direction supported. Of type snd_compr_direction
- * @min_fragment_size: minimum fragment supported by DSP
- * @max_fragment_size: maximum fragment supported by DSP
- * @min_fragments: min fragments supported by DSP
- * @max_fragments: max fragments supported by DSP
- * @num_codecs: number of codecs supported
- * @reserved: reserved field
- */
-struct snd_compr_caps {
-	__u32 num_codecs;
-	__u32 direction;
-	__u32 min_fragment_size;
-	__u32 max_fragment_size;
-	__u32 min_fragments;
-	__u32 max_fragments;
-	__u32 codecs[MAX_NUM_CODECS];
-	__u32 reserved[11];
-};
-
-/**
- * struct snd_compr_codec_caps: query capability of codec
- * @codec: codec for which capability is queried
- * @num_descriptors: number of codec descriptors
- * @descriptor: array of codec capability descriptor
- */
-struct snd_compr_codec_caps {
-	__u32 codec;
-	__u32 num_descriptors;
-	struct snd_codec_desc descriptor[MAX_NUM_CODEC_DESCRIPTORS];
-};
-
-/**
- * compress path ioctl definitions
- * SNDRV_COMPRESS_GET_CAPS: Query capability of DSP
- * SNDRV_COMPRESS_GET_CODEC_CAPS: Query capability of a codec
- * SNDRV_COMPRESS_SET_PARAMS: Set codec and stream parameters
- * Note: only codec params can be changed runtime and stream params cant be
- * SNDRV_COMPRESS_GET_PARAMS: Query codec params
- * SNDRV_COMPRESS_TSTAMP: get the current timestamp value
- * SNDRV_COMPRESS_AVAIL: get the current buffer avail value.
- * This also queries the tstamp properties
- * SNDRV_COMPRESS_PAUSE: Pause the running stream
- * SNDRV_COMPRESS_RESUME: resume a paused stream
- * SNDRV_COMPRESS_START: Start a stream
- * SNDRV_COMPRESS_STOP: stop a running stream, discarding ring buffer content
- * and the buffers currently with DSP
- * SNDRV_COMPRESS_DRAIN: Play till end of buffers and stop after that
- * SNDRV_COMPRESS_IOCTL_VERSION: Query the API version
- */
-#define SNDRV_COMPRESS_IOCTL_VERSION	_IOR('C', 0x00, int)
-#define SNDRV_COMPRESS_GET_CAPS		_IOWR('C', 0x10, struct snd_compr_caps)
-#define SNDRV_COMPRESS_GET_CODEC_CAPS	_IOWR('C', 0x11,\
-						struct snd_compr_codec_caps)
-#define SNDRV_COMPRESS_SET_PARAMS	_IOW('C', 0x12, struct snd_compr_params)
-#define SNDRV_COMPRESS_GET_PARAMS	_IOR('C', 0x13, struct snd_codec)
-#define SNDRV_COMPRESS_TSTAMP		_IOR('C', 0x20, struct snd_compr_tstamp)
-#define SNDRV_COMPRESS_AVAIL		_IOR('C', 0x21, struct snd_compr_avail)
-#define SNDRV_COMPRESS_PAUSE		_IO('C', 0x30)
-#define SNDRV_COMPRESS_RESUME		_IO('C', 0x31)
-#define SNDRV_COMPRESS_START		_IO('C', 0x32)
-#define SNDRV_COMPRESS_STOP		_IO('C', 0x33)
-#define SNDRV_COMPRESS_DRAIN		_IO('C', 0x34)
-/*
- * TODO
- * 1. add mmap support
- *
- */
-#define SND_COMPR_TRIGGER_DRAIN 7 /*FIXME move this to pcm.h */
-#endif
diff --git a/include/sound/compress_params.h b/include/sound/compress_params.h
deleted file mode 100644
index 602dc6c..0000000
--- a/include/sound/compress_params.h
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- *  compress_params.h - codec types and parameters for compressed data
- *  streaming interface
- *
- *  Copyright (C) 2011 Intel Corporation
- *  Authors:	Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
- *              Vinod Koul <vinod.koul@linux.intel.com>
- *
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * The definitions in this file are derived from the OpenMAX AL version 1.1
- * and OpenMAX IL v 1.1.2 header files which contain the copyright notice below.
- *
- * Copyright (c) 2007-2010 The Khronos Group Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and/or associated documentation files (the
- * "Materials "), to deal in the Materials without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Materials, and to
- * permit persons to whom the Materials are furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Materials.
- *
- * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
- *
- */
-#ifndef __SND_COMPRESS_PARAMS_H
-#define __SND_COMPRESS_PARAMS_H
-
-#include <linux/types.h>
-
-/* AUDIO CODECS SUPPORTED */
-#define MAX_NUM_CODECS 32
-#define MAX_NUM_CODEC_DESCRIPTORS 32
-#define MAX_NUM_BITRATES 32
-
-/* Codecs are listed linearly to allow for extensibility */
-#define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
-#define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
-#define SND_AUDIOCODEC_AMR                   ((__u32) 0x00000003)
-#define SND_AUDIOCODEC_AMRWB                 ((__u32) 0x00000004)
-#define SND_AUDIOCODEC_AMRWBPLUS             ((__u32) 0x00000005)
-#define SND_AUDIOCODEC_AAC                   ((__u32) 0x00000006)
-#define SND_AUDIOCODEC_WMA                   ((__u32) 0x00000007)
-#define SND_AUDIOCODEC_REAL                  ((__u32) 0x00000008)
-#define SND_AUDIOCODEC_VORBIS                ((__u32) 0x00000009)
-#define SND_AUDIOCODEC_FLAC                  ((__u32) 0x0000000A)
-#define SND_AUDIOCODEC_IEC61937              ((__u32) 0x0000000B)
-#define SND_AUDIOCODEC_G723_1                ((__u32) 0x0000000C)
-#define SND_AUDIOCODEC_G729                  ((__u32) 0x0000000D)
-#define SND_AUDIOCODEC_MAX                   SND_AUDIOCODEC_G729
-
-/*
- * Profile and modes are listed with bit masks. This allows for a
- * more compact representation of fields that will not evolve
- * (in contrast to the list of codecs)
- */
-
-#define SND_AUDIOPROFILE_PCM                 ((__u32) 0x00000001)
-
-/* MP3 modes are only useful for encoders */
-#define SND_AUDIOCHANMODE_MP3_MONO           ((__u32) 0x00000001)
-#define SND_AUDIOCHANMODE_MP3_STEREO         ((__u32) 0x00000002)
-#define SND_AUDIOCHANMODE_MP3_JOINTSTEREO    ((__u32) 0x00000004)
-#define SND_AUDIOCHANMODE_MP3_DUAL           ((__u32) 0x00000008)
-
-#define SND_AUDIOPROFILE_AMR                 ((__u32) 0x00000001)
-
-/* AMR modes are only useful for encoders */
-#define SND_AUDIOMODE_AMR_DTX_OFF            ((__u32) 0x00000001)
-#define SND_AUDIOMODE_AMR_VAD1               ((__u32) 0x00000002)
-#define SND_AUDIOMODE_AMR_VAD2               ((__u32) 0x00000004)
-
-#define SND_AUDIOSTREAMFORMAT_UNDEFINED	     ((__u32) 0x00000000)
-#define SND_AUDIOSTREAMFORMAT_CONFORMANCE    ((__u32) 0x00000001)
-#define SND_AUDIOSTREAMFORMAT_IF1            ((__u32) 0x00000002)
-#define SND_AUDIOSTREAMFORMAT_IF2            ((__u32) 0x00000004)
-#define SND_AUDIOSTREAMFORMAT_FSF            ((__u32) 0x00000008)
-#define SND_AUDIOSTREAMFORMAT_RTPPAYLOAD     ((__u32) 0x00000010)
-#define SND_AUDIOSTREAMFORMAT_ITU            ((__u32) 0x00000020)
-
-#define SND_AUDIOPROFILE_AMRWB               ((__u32) 0x00000001)
-
-/* AMRWB modes are only useful for encoders */
-#define SND_AUDIOMODE_AMRWB_DTX_OFF          ((__u32) 0x00000001)
-#define SND_AUDIOMODE_AMRWB_VAD1             ((__u32) 0x00000002)
-#define SND_AUDIOMODE_AMRWB_VAD2             ((__u32) 0x00000004)
-
-#define SND_AUDIOPROFILE_AMRWBPLUS           ((__u32) 0x00000001)
-
-#define SND_AUDIOPROFILE_AAC                 ((__u32) 0x00000001)
-
-/* AAC modes are required for encoders and decoders */
-#define SND_AUDIOMODE_AAC_MAIN               ((__u32) 0x00000001)
-#define SND_AUDIOMODE_AAC_LC                 ((__u32) 0x00000002)
-#define SND_AUDIOMODE_AAC_SSR                ((__u32) 0x00000004)
-#define SND_AUDIOMODE_AAC_LTP                ((__u32) 0x00000008)
-#define SND_AUDIOMODE_AAC_HE                 ((__u32) 0x00000010)
-#define SND_AUDIOMODE_AAC_SCALABLE           ((__u32) 0x00000020)
-#define SND_AUDIOMODE_AAC_ERLC               ((__u32) 0x00000040)
-#define SND_AUDIOMODE_AAC_LD                 ((__u32) 0x00000080)
-#define SND_AUDIOMODE_AAC_HE_PS              ((__u32) 0x00000100)
-#define SND_AUDIOMODE_AAC_HE_MPS             ((__u32) 0x00000200)
-
-/* AAC formats are required for encoders and decoders */
-#define SND_AUDIOSTREAMFORMAT_MP2ADTS        ((__u32) 0x00000001)
-#define SND_AUDIOSTREAMFORMAT_MP4ADTS        ((__u32) 0x00000002)
-#define SND_AUDIOSTREAMFORMAT_MP4LOAS        ((__u32) 0x00000004)
-#define SND_AUDIOSTREAMFORMAT_MP4LATM        ((__u32) 0x00000008)
-#define SND_AUDIOSTREAMFORMAT_ADIF           ((__u32) 0x00000010)
-#define SND_AUDIOSTREAMFORMAT_MP4FF          ((__u32) 0x00000020)
-#define SND_AUDIOSTREAMFORMAT_RAW            ((__u32) 0x00000040)
-
-#define SND_AUDIOPROFILE_WMA7                ((__u32) 0x00000001)
-#define SND_AUDIOPROFILE_WMA8                ((__u32) 0x00000002)
-#define SND_AUDIOPROFILE_WMA9                ((__u32) 0x00000004)
-#define SND_AUDIOPROFILE_WMA10               ((__u32) 0x00000008)
-
-#define SND_AUDIOMODE_WMA_LEVEL1             ((__u32) 0x00000001)
-#define SND_AUDIOMODE_WMA_LEVEL2             ((__u32) 0x00000002)
-#define SND_AUDIOMODE_WMA_LEVEL3             ((__u32) 0x00000004)
-#define SND_AUDIOMODE_WMA_LEVEL4             ((__u32) 0x00000008)
-#define SND_AUDIOMODE_WMAPRO_LEVELM0         ((__u32) 0x00000010)
-#define SND_AUDIOMODE_WMAPRO_LEVELM1         ((__u32) 0x00000020)
-#define SND_AUDIOMODE_WMAPRO_LEVELM2         ((__u32) 0x00000040)
-#define SND_AUDIOMODE_WMAPRO_LEVELM3         ((__u32) 0x00000080)
-
-#define SND_AUDIOSTREAMFORMAT_WMA_ASF        ((__u32) 0x00000001)
-/*
- * Some implementations strip the ASF header and only send ASF packets
- * to the DSP
- */
-#define SND_AUDIOSTREAMFORMAT_WMA_NOASF_HDR  ((__u32) 0x00000002)
-
-#define SND_AUDIOPROFILE_REALAUDIO           ((__u32) 0x00000001)
-
-#define SND_AUDIOMODE_REALAUDIO_G2           ((__u32) 0x00000001)
-#define SND_AUDIOMODE_REALAUDIO_8            ((__u32) 0x00000002)
-#define SND_AUDIOMODE_REALAUDIO_10           ((__u32) 0x00000004)
-#define SND_AUDIOMODE_REALAUDIO_SURROUND     ((__u32) 0x00000008)
-
-#define SND_AUDIOPROFILE_VORBIS              ((__u32) 0x00000001)
-
-#define SND_AUDIOMODE_VORBIS                 ((__u32) 0x00000001)
-
-#define SND_AUDIOPROFILE_FLAC                ((__u32) 0x00000001)
-
-/*
- * Define quality levels for FLAC encoders, from LEVEL0 (fast)
- * to LEVEL8 (best)
- */
-#define SND_AUDIOMODE_FLAC_LEVEL0            ((__u32) 0x00000001)
-#define SND_AUDIOMODE_FLAC_LEVEL1            ((__u32) 0x00000002)
-#define SND_AUDIOMODE_FLAC_LEVEL2            ((__u32) 0x00000004)
-#define SND_AUDIOMODE_FLAC_LEVEL3            ((__u32) 0x00000008)
-#define SND_AUDIOMODE_FLAC_LEVEL4            ((__u32) 0x00000010)
-#define SND_AUDIOMODE_FLAC_LEVEL5            ((__u32) 0x00000020)
-#define SND_AUDIOMODE_FLAC_LEVEL6            ((__u32) 0x00000040)
-#define SND_AUDIOMODE_FLAC_LEVEL7            ((__u32) 0x00000080)
-#define SND_AUDIOMODE_FLAC_LEVEL8            ((__u32) 0x00000100)
-
-#define SND_AUDIOSTREAMFORMAT_FLAC           ((__u32) 0x00000001)
-#define SND_AUDIOSTREAMFORMAT_FLAC_OGG       ((__u32) 0x00000002)
-
-/* IEC61937 payloads without CUVP and preambles */
-#define SND_AUDIOPROFILE_IEC61937            ((__u32) 0x00000001)
-/* IEC61937 with S/PDIF preambles+CUVP bits in 32-bit containers */
-#define SND_AUDIOPROFILE_IEC61937_SPDIF      ((__u32) 0x00000002)
-
-/*
- * IEC modes are mandatory for decoders. Format autodetection
- * will only happen on the DSP side with mode 0. The PCM mode should
- * not be used, the PCM codec should be used instead.
- */
-#define SND_AUDIOMODE_IEC_REF_STREAM_HEADER  ((__u32) 0x00000000)
-#define SND_AUDIOMODE_IEC_LPCM		     ((__u32) 0x00000001)
-#define SND_AUDIOMODE_IEC_AC3		     ((__u32) 0x00000002)
-#define SND_AUDIOMODE_IEC_MPEG1		     ((__u32) 0x00000004)
-#define SND_AUDIOMODE_IEC_MP3		     ((__u32) 0x00000008)
-#define SND_AUDIOMODE_IEC_MPEG2		     ((__u32) 0x00000010)
-#define SND_AUDIOMODE_IEC_AACLC		     ((__u32) 0x00000020)
-#define SND_AUDIOMODE_IEC_DTS		     ((__u32) 0x00000040)
-#define SND_AUDIOMODE_IEC_ATRAC		     ((__u32) 0x00000080)
-#define SND_AUDIOMODE_IEC_SACD		     ((__u32) 0x00000100)
-#define SND_AUDIOMODE_IEC_EAC3		     ((__u32) 0x00000200)
-#define SND_AUDIOMODE_IEC_DTS_HD	     ((__u32) 0x00000400)
-#define SND_AUDIOMODE_IEC_MLP		     ((__u32) 0x00000800)
-#define SND_AUDIOMODE_IEC_DST		     ((__u32) 0x00001000)
-#define SND_AUDIOMODE_IEC_WMAPRO	     ((__u32) 0x00002000)
-#define SND_AUDIOMODE_IEC_REF_CXT            ((__u32) 0x00004000)
-#define SND_AUDIOMODE_IEC_HE_AAC	     ((__u32) 0x00008000)
-#define SND_AUDIOMODE_IEC_HE_AAC2	     ((__u32) 0x00010000)
-#define SND_AUDIOMODE_IEC_MPEG_SURROUND	     ((__u32) 0x00020000)
-
-#define SND_AUDIOPROFILE_G723_1              ((__u32) 0x00000001)
-
-#define SND_AUDIOMODE_G723_1_ANNEX_A         ((__u32) 0x00000001)
-#define SND_AUDIOMODE_G723_1_ANNEX_B         ((__u32) 0x00000002)
-#define SND_AUDIOMODE_G723_1_ANNEX_C         ((__u32) 0x00000004)
-
-#define SND_AUDIOPROFILE_G729                ((__u32) 0x00000001)
-
-#define SND_AUDIOMODE_G729_ANNEX_A           ((__u32) 0x00000001)
-#define SND_AUDIOMODE_G729_ANNEX_B           ((__u32) 0x00000002)
-
-/* <FIXME: multichannel encoders aren't supported for now. Would need
-   an additional definition of channel arrangement> */
-
-/* VBR/CBR definitions */
-#define SND_RATECONTROLMODE_CONSTANTBITRATE  ((__u32) 0x00000001)
-#define SND_RATECONTROLMODE_VARIABLEBITRATE  ((__u32) 0x00000002)
-
-/* Encoder options */
-
-struct snd_enc_wma {
-	__u32 super_block_align; /* WMA Type-specific data */
-};
-
-
-/**
- * struct snd_enc_vorbis
- * @quality: Sets encoding quality to n, between -1 (low) and 10 (high).
- * In the default mode of operation, the quality level is 3.
- * Normal quality range is 0 - 10.
- * @managed: Boolean. Set  bitrate  management  mode. This turns off the
- * normal VBR encoding, but allows hard or soft bitrate constraints to be
- * enforced by the encoder. This mode can be slower, and may also be
- * lower quality. It is primarily useful for streaming.
- * @max_bit_rate: Enabled only if managed is TRUE
- * @min_bit_rate: Enabled only if managed is TRUE
- * @downmix: Boolean. Downmix input from stereo to mono (has no effect on
- * non-stereo streams). Useful for lower-bitrate encoding.
- *
- * These options were extracted from the OpenMAX IL spec and Gstreamer vorbisenc
- * properties
- *
- * For best quality users should specify VBR mode and set quality levels.
- */
-
-struct snd_enc_vorbis {
-	__s32 quality;
-	__u32 managed;
-	__u32 max_bit_rate;
-	__u32 min_bit_rate;
-	__u32 downmix;
-};
-
-
-/**
- * struct snd_enc_real
- * @quant_bits: number of coupling quantization bits in the stream
- * @start_region: coupling start region in the stream
- * @num_regions: number of regions value
- *
- * These options were extracted from the OpenMAX IL spec
- */
-
-struct snd_enc_real {
-	__u32 quant_bits;
-	__u32 start_region;
-	__u32 num_regions;
-};
-
-/**
- * struct snd_enc_flac
- * @num: serial number, valid only for OGG formats
- *	needs to be set by application
- * @gain: Add replay gain tags
- *
- * These options were extracted from the FLAC online documentation
- * at http://flac.sourceforge.net/documentation_tools_flac.html
- *
- * To make the API simpler, it is assumed that the user will select quality
- * profiles. Additional options that affect encoding quality and speed can
- * be added at a later stage if needed.
- *
- * By default the Subset format is used by encoders.
- *
- * TAGS such as pictures, etc, cannot be handled by an offloaded encoder and are
- * not supported in this API.
- */
-
-struct snd_enc_flac {
-	__u32 num;
-	__u32 gain;
-};
-
-struct snd_enc_generic {
-	__u32 bw;	/* encoder bandwidth */
-	__s32 reserved[15];
-};
-
-union snd_codec_options {
-	struct snd_enc_wma wma;
-	struct snd_enc_vorbis vorbis;
-	struct snd_enc_real real;
-	struct snd_enc_flac flac;
-	struct snd_enc_generic generic;
-};
-
-/** struct snd_codec_desc - description of codec capabilities
- * @max_ch: Maximum number of audio channels
- * @sample_rates: Sampling rates in Hz, use SNDRV_PCM_RATE_xxx for this
- * @bit_rate: Indexed array containing supported bit rates
- * @num_bitrates: Number of valid values in bit_rate array
- * @rate_control: value is specified by SND_RATECONTROLMODE defines.
- * @profiles: Supported profiles. See SND_AUDIOPROFILE defines.
- * @modes: Supported modes. See SND_AUDIOMODE defines
- * @formats: Supported formats. See SND_AUDIOSTREAMFORMAT defines
- * @min_buffer: Minimum buffer size handled by codec implementation
- * @reserved: reserved for future use
- *
- * This structure provides a scalar value for profiles, modes and stream
- * format fields.
- * If an implementation supports multiple combinations, they will be listed as
- * codecs with different descriptors, for example there would be 2 descriptors
- * for AAC-RAW and AAC-ADTS.
- * This entails some redundancy but makes it easier to avoid invalid
- * configurations.
- *
- */
-
-struct snd_codec_desc {
-	__u32 max_ch;
-	__u32 sample_rates;
-	__u32 bit_rate[MAX_NUM_BITRATES];
-	__u32 num_bitrates;
-	__u32 rate_control;
-	__u32 profiles;
-	__u32 modes;
-	__u32 formats;
-	__u32 min_buffer;
-	__u32 reserved[15];
-};
-
-/** struct snd_codec
- * @id: Identifies the supported audio encoder/decoder.
- *		See SND_AUDIOCODEC macros.
- * @ch_in: Number of input audio channels
- * @ch_out: Number of output channels. In case of contradiction between
- *		this field and the channelMode field, the channelMode field
- *		overrides.
- * @sample_rate: Audio sample rate of input data
- * @bit_rate: Bitrate of encoded data. May be ignored by decoders
- * @rate_control: Encoding rate control. See SND_RATECONTROLMODE defines.
- *               Encoders may rely on profiles for quality levels.
- *		 May be ignored by decoders.
- * @profile: Mandatory for encoders, can be mandatory for specific
- *		decoders as well. See SND_AUDIOPROFILE defines.
- * @level: Supported level (Only used by WMA at the moment)
- * @ch_mode: Channel mode for encoder. See SND_AUDIOCHANMODE defines
- * @format: Format of encoded bistream. Mandatory when defined.
- *		See SND_AUDIOSTREAMFORMAT defines.
- * @align: Block alignment in bytes of an audio sample.
- *		Only required for PCM or IEC formats.
- * @options: encoder-specific settings
- * @reserved: reserved for future use
- */
-
-struct snd_codec {
-	__u32 id;
-	__u32 ch_in;
-	__u32 ch_out;
-	__u32 sample_rate;
-	__u32 bit_rate;
-	__u32 rate_control;
-	__u32 profile;
-	__u32 level;
-	__u32 ch_mode;
-	__u32 format;
-	__u32 align;
-	union snd_codec_options options;
-	__u32 reserved[3];
-};
-
-#endif
diff --git a/include/sound/cs4271.h b/include/sound/cs4271.h
index 50a059e..6d9e15e 100644
--- a/include/sound/cs4271.h
+++ b/include/sound/cs4271.h
@@ -19,6 +19,7 @@
 
 struct cs4271_platform_data {
 	int gpio_nreset;	/* GPIO driving Reset pin, if any */
+	int amutec_eq_bmutec:1;	/* flag to enable AMUTEC=BMUTEC */
 };
 
 #endif /* __CS4271_H */
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 1a33f48..f841ba4 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -1,8 +1,3 @@
-#ifndef __SOUND_EMU10K1_H
-#define __SOUND_EMU10K1_H
-
-#include <linux/types.h>
-
 /*
  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
  *		     Creative Labs, Inc.
@@ -24,8 +19,9 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
  */
+#ifndef __SOUND_EMU10K1_H
+#define __SOUND_EMU10K1_H
 
-#ifdef __KERNEL__
 
 #include <sound/pcm.h>
 #include <sound/rawmidi.h>
@@ -36,8 +32,10 @@
 #include <sound/timer.h>
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
+#include <linux/firmware.h>
 
 #include <asm/io.h>
+#include <uapi/sound/emu10k1.h>
 
 /* ------------------- DEFINES -------------------- */
 
@@ -1788,6 +1786,8 @@ struct snd_emu10k1 {
 	unsigned int efx_voices_mask[2];
 	unsigned int next_free_voice;
 
+	const struct firmware *firmware;
+
 #ifdef CONFIG_PM_SLEEP
 	unsigned int *saved_ptr;
 	unsigned int *saved_gpr;
@@ -1796,6 +1796,7 @@ struct snd_emu10k1 {
 	unsigned int *saved_icode;
 	unsigned int *p16v_saved;
 	unsigned int saved_a_iocfg, saved_hcfg;
+	bool suspend;
 #endif
 
 };
@@ -1899,350 +1900,4 @@ int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu,
 int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu,
 					      struct snd_emu10k1_fx8010_irq *irq);
 
-#endif /* __KERNEL__ */
-
-/*
- * ---- FX8010 ----
- */
-
-#define EMU10K1_CARD_CREATIVE			0x00000000
-#define EMU10K1_CARD_EMUAPS			0x00000001
-
-#define EMU10K1_FX8010_PCM_COUNT		8
-
-/* instruction set */
-#define iMAC0	 0x00	/* R = A + (X * Y >> 31)   ; saturation */
-#define iMAC1	 0x01	/* R = A + (-X * Y >> 31)  ; saturation */
-#define iMAC2	 0x02	/* R = A + (X * Y >> 31)   ; wraparound */
-#define iMAC3	 0x03	/* R = A + (-X * Y >> 31)  ; wraparound */
-#define iMACINT0 0x04	/* R = A + X * Y	   ; saturation */
-#define iMACINT1 0x05	/* R = A + X * Y	   ; wraparound (31-bit) */
-#define iACC3	 0x06	/* R = A + X + Y	   ; saturation */
-#define iMACMV   0x07	/* R = A, acc += X * Y >> 31 */
-#define iANDXOR  0x08	/* R = (A & X) ^ Y */
-#define iTSTNEG  0x09	/* R = (A >= Y) ? X : ~X */
-#define iLIMITGE 0x0a	/* R = (A >= Y) ? X : Y */
-#define iLIMITLT 0x0b	/* R = (A < Y) ? X : Y */
-#define iLOG	 0x0c	/* R = linear_data, A (log_data), X (max_exp), Y (format_word) */
-#define iEXP	 0x0d	/* R = log_data, A (linear_data), X (max_exp), Y (format_word) */
-#define iINTERP  0x0e	/* R = A + (X * (Y - A) >> 31)  ; saturation */
-#define iSKIP    0x0f	/* R = A (cc_reg), X (count), Y (cc_test) */
-
-/* GPRs */
-#define FXBUS(x)	(0x00 + (x))	/* x = 0x00 - 0x0f */
-#define EXTIN(x)	(0x10 + (x))	/* x = 0x00 - 0x0f */
-#define EXTOUT(x)	(0x20 + (x))	/* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */
-#define FXBUS2(x)	(0x30 + (x))	/* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */
-					/* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */
-
-#define C_00000000	0x40
-#define C_00000001	0x41
-#define C_00000002	0x42
-#define C_00000003	0x43
-#define C_00000004	0x44
-#define C_00000008	0x45
-#define C_00000010	0x46
-#define C_00000020	0x47
-#define C_00000100	0x48
-#define C_00010000	0x49
-#define C_00080000	0x4a
-#define C_10000000	0x4b
-#define C_20000000	0x4c
-#define C_40000000	0x4d
-#define C_80000000	0x4e
-#define C_7fffffff	0x4f
-#define C_ffffffff	0x50
-#define C_fffffffe	0x51
-#define C_c0000000	0x52
-#define C_4f1bbcdc	0x53
-#define C_5a7ef9db	0x54
-#define C_00100000	0x55		/* ?? */
-#define GPR_ACCU	0x56		/* ACCUM, accumulator */
-#define GPR_COND	0x57		/* CCR, condition register */
-#define GPR_NOISE0	0x58		/* noise source */
-#define GPR_NOISE1	0x59		/* noise source */
-#define GPR_IRQ		0x5a		/* IRQ register */
-#define GPR_DBAC	0x5b		/* TRAM Delay Base Address Counter */
-#define GPR(x)		(FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */
-#define ITRAM_DATA(x)	(TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
-#define ETRAM_DATA(x)	(TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
-#define ITRAM_ADDR(x)	(TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
-#define ETRAM_ADDR(x)	(TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
-
-#define A_ITRAM_DATA(x)	(TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
-#define A_ETRAM_DATA(x)	(TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
-#define A_ITRAM_ADDR(x)	(TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
-#define A_ETRAM_ADDR(x)	(TANKMEMADDRREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
-#define A_ITRAM_CTL(x)	(A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
-#define A_ETRAM_CTL(x)	(A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
-
-#define A_FXBUS(x)	(0x00 + (x))	/* x = 0x00 - 0x3f FX buses */
-#define A_EXTIN(x)	(0x40 + (x))	/* x = 0x00 - 0x0f physical ins */
-#define A_P16VIN(x)	(0x50 + (x))	/* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */
-#define A_EXTOUT(x)	(0x60 + (x))	/* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown   */
-#define A_FXBUS2(x)	(0x80 + (x))	/* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */
-#define A_EMU32OUTH(x)	(0xa0 + (x))	/* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */
-#define A_EMU32OUTL(x)	(0xb0 + (x))	/* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */
-#define A3_EMU32IN(x)	(0x160 + (x))	/* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */
-#define A3_EMU32OUT(x)	(0x1E0 + (x))	/* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */
-#define A_GPR(x)	(A_FXGPREGBASE + (x))
-
-/* cc_reg constants */
-#define CC_REG_NORMALIZED C_00000001
-#define CC_REG_BORROW	C_00000002
-#define CC_REG_MINUS	C_00000004
-#define CC_REG_ZERO	C_00000008
-#define CC_REG_SATURATE	C_00000010
-#define CC_REG_NONZERO	C_00000100
-
-/* FX buses */
-#define FXBUS_PCM_LEFT		0x00
-#define FXBUS_PCM_RIGHT		0x01
-#define FXBUS_PCM_LEFT_REAR	0x02
-#define FXBUS_PCM_RIGHT_REAR	0x03
-#define FXBUS_MIDI_LEFT		0x04
-#define FXBUS_MIDI_RIGHT	0x05
-#define FXBUS_PCM_CENTER	0x06
-#define FXBUS_PCM_LFE		0x07
-#define FXBUS_PCM_LEFT_FRONT	0x08
-#define FXBUS_PCM_RIGHT_FRONT	0x09
-#define FXBUS_MIDI_REVERB	0x0c
-#define FXBUS_MIDI_CHORUS	0x0d
-#define FXBUS_PCM_LEFT_SIDE	0x0e
-#define FXBUS_PCM_RIGHT_SIDE	0x0f
-#define FXBUS_PT_LEFT		0x14
-#define FXBUS_PT_RIGHT		0x15
-
-/* Inputs */
-#define EXTIN_AC97_L	   0x00	/* AC'97 capture channel - left */
-#define EXTIN_AC97_R	   0x01	/* AC'97 capture channel - right */
-#define EXTIN_SPDIF_CD_L   0x02	/* internal S/PDIF CD - onboard - left */
-#define EXTIN_SPDIF_CD_R   0x03	/* internal S/PDIF CD - onboard - right */
-#define EXTIN_ZOOM_L	   0x04	/* Zoom Video I2S - left */
-#define EXTIN_ZOOM_R	   0x05	/* Zoom Video I2S - right */
-#define EXTIN_TOSLINK_L	   0x06	/* LiveDrive - TOSLink Optical - left */
-#define EXTIN_TOSLINK_R    0x07	/* LiveDrive - TOSLink Optical - right */
-#define EXTIN_LINE1_L	   0x08	/* LiveDrive - Line/Mic 1 - left */
-#define EXTIN_LINE1_R	   0x09	/* LiveDrive - Line/Mic 1 - right */
-#define EXTIN_COAX_SPDIF_L 0x0a	/* LiveDrive - Coaxial S/PDIF - left */
-#define EXTIN_COAX_SPDIF_R 0x0b /* LiveDrive - Coaxial S/PDIF - right */
-#define EXTIN_LINE2_L	   0x0c	/* LiveDrive - Line/Mic 2 - left */
-#define EXTIN_LINE2_R	   0x0d	/* LiveDrive - Line/Mic 2 - right */
-
-/* Outputs */
-#define EXTOUT_AC97_L	   0x00	/* AC'97 playback channel - left */
-#define EXTOUT_AC97_R	   0x01	/* AC'97 playback channel - right */
-#define EXTOUT_TOSLINK_L   0x02	/* LiveDrive - TOSLink Optical - left */
-#define EXTOUT_TOSLINK_R   0x03	/* LiveDrive - TOSLink Optical - right */
-#define EXTOUT_AC97_CENTER 0x04	/* SB Live 5.1 - center */
-#define EXTOUT_AC97_LFE	   0x05 /* SB Live 5.1 - LFE */
-#define EXTOUT_HEADPHONE_L 0x06	/* LiveDrive - Headphone - left */
-#define EXTOUT_HEADPHONE_R 0x07	/* LiveDrive - Headphone - right */
-#define EXTOUT_REAR_L	   0x08	/* Rear channel - left */
-#define EXTOUT_REAR_R	   0x09	/* Rear channel - right */
-#define EXTOUT_ADC_CAP_L   0x0a	/* ADC Capture buffer - left */
-#define EXTOUT_ADC_CAP_R   0x0b	/* ADC Capture buffer - right */
-#define EXTOUT_MIC_CAP	   0x0c	/* MIC Capture buffer */
-#define EXTOUT_AC97_REAR_L 0x0d	/* SB Live 5.1 (c) 2003 - Rear Left */
-#define EXTOUT_AC97_REAR_R 0x0e	/* SB Live 5.1 (c) 2003 - Rear Right */
-#define EXTOUT_ACENTER	   0x11 /* Analog Center */
-#define EXTOUT_ALFE	   0x12 /* Analog LFE */
-
-/* Audigy Inputs */
-#define A_EXTIN_AC97_L		0x00	/* AC'97 capture channel - left */
-#define A_EXTIN_AC97_R		0x01	/* AC'97 capture channel - right */
-#define A_EXTIN_SPDIF_CD_L	0x02	/* digital CD left */
-#define A_EXTIN_SPDIF_CD_R	0x03	/* digital CD left */
-#define A_EXTIN_OPT_SPDIF_L     0x04    /* audigy drive Optical SPDIF - left */
-#define A_EXTIN_OPT_SPDIF_R     0x05    /*                              right */ 
-#define A_EXTIN_LINE2_L		0x08	/* audigy drive line2/mic2 - left */
-#define A_EXTIN_LINE2_R		0x09	/*                           right */
-#define A_EXTIN_ADC_L		0x0a    /* Philips ADC - left */
-#define A_EXTIN_ADC_R		0x0b    /*               right */
-#define A_EXTIN_AUX2_L		0x0c	/* audigy drive aux2 - left */
-#define A_EXTIN_AUX2_R		0x0d	/*                   - right */
-
-/* Audigiy Outputs */
-#define A_EXTOUT_FRONT_L	0x00	/* digital front left */
-#define A_EXTOUT_FRONT_R	0x01	/*               right */
-#define A_EXTOUT_CENTER		0x02	/* digital front center */
-#define A_EXTOUT_LFE		0x03	/* digital front lfe */
-#define A_EXTOUT_HEADPHONE_L	0x04	/* headphone audigy drive left */
-#define A_EXTOUT_HEADPHONE_R	0x05	/*                        right */
-#define A_EXTOUT_REAR_L		0x06	/* digital rear left */
-#define A_EXTOUT_REAR_R		0x07	/*              right */
-#define A_EXTOUT_AFRONT_L	0x08	/* analog front left */
-#define A_EXTOUT_AFRONT_R	0x09	/*              right */
-#define A_EXTOUT_ACENTER	0x0a	/* analog center */
-#define A_EXTOUT_ALFE		0x0b	/* analog LFE */
-#define A_EXTOUT_ASIDE_L	0x0c	/* analog side left  - Audigy 2 ZS */
-#define A_EXTOUT_ASIDE_R	0x0d	/*             right - Audigy 2 ZS */
-#define A_EXTOUT_AREAR_L	0x0e	/* analog rear left */
-#define A_EXTOUT_AREAR_R	0x0f	/*             right */
-#define A_EXTOUT_AC97_L		0x10	/* AC97 left (front) */
-#define A_EXTOUT_AC97_R		0x11	/*      right */
-#define A_EXTOUT_ADC_CAP_L	0x16	/* ADC capture buffer left */
-#define A_EXTOUT_ADC_CAP_R	0x17	/*                    right */
-#define A_EXTOUT_MIC_CAP	0x18	/* Mic capture buffer */
-
-/* Audigy constants */
-#define A_C_00000000	0xc0
-#define A_C_00000001	0xc1
-#define A_C_00000002	0xc2
-#define A_C_00000003	0xc3
-#define A_C_00000004	0xc4
-#define A_C_00000008	0xc5
-#define A_C_00000010	0xc6
-#define A_C_00000020	0xc7
-#define A_C_00000100	0xc8
-#define A_C_00010000	0xc9
-#define A_C_00000800	0xca
-#define A_C_10000000	0xcb
-#define A_C_20000000	0xcc
-#define A_C_40000000	0xcd
-#define A_C_80000000	0xce
-#define A_C_7fffffff	0xcf
-#define A_C_ffffffff	0xd0
-#define A_C_fffffffe	0xd1
-#define A_C_c0000000	0xd2
-#define A_C_4f1bbcdc	0xd3
-#define A_C_5a7ef9db	0xd4
-#define A_C_00100000	0xd5
-#define A_GPR_ACCU	0xd6		/* ACCUM, accumulator */
-#define A_GPR_COND	0xd7		/* CCR, condition register */
-#define A_GPR_NOISE0	0xd8		/* noise source */
-#define A_GPR_NOISE1	0xd9		/* noise source */
-#define A_GPR_IRQ	0xda		/* IRQ register */
-#define A_GPR_DBAC	0xdb		/* TRAM Delay Base Address Counter - internal */
-#define A_GPR_DBACE	0xde		/* TRAM Delay Base Address Counter - external */
-
-/* definitions for debug register */
-#define EMU10K1_DBG_ZC			0x80000000	/* zero tram counter */
-#define EMU10K1_DBG_SATURATION_OCCURED	0x02000000	/* saturation control */
-#define EMU10K1_DBG_SATURATION_ADDR	0x01ff0000	/* saturation address */
-#define EMU10K1_DBG_SINGLE_STEP		0x00008000	/* single step mode */
-#define EMU10K1_DBG_STEP		0x00004000	/* start single step */
-#define EMU10K1_DBG_CONDITION_CODE	0x00003e00	/* condition code */
-#define EMU10K1_DBG_SINGLE_STEP_ADDR	0x000001ff	/* single step address */
-
-/* tank memory address line */
-#ifndef __KERNEL__
-#define TANKMEMADDRREG_ADDR_MASK 0x000fffff	/* 20 bit tank address field			*/
-#define TANKMEMADDRREG_CLEAR	 0x00800000	/* Clear tank memory				*/
-#define TANKMEMADDRREG_ALIGN	 0x00400000	/* Align read or write relative to tank access	*/
-#define TANKMEMADDRREG_WRITE	 0x00200000	/* Write to tank memory				*/
-#define TANKMEMADDRREG_READ	 0x00100000	/* Read from tank memory			*/
-#endif
-
-struct snd_emu10k1_fx8010_info {
-	unsigned int internal_tram_size;	/* in samples */
-	unsigned int external_tram_size;	/* in samples */
-	char fxbus_names[16][32];		/* names of FXBUSes */
-	char extin_names[16][32];		/* names of external inputs */
-	char extout_names[32][32];		/* names of external outputs */
-	unsigned int gpr_controls;		/* count of GPR controls */
-};
-
-#define EMU10K1_GPR_TRANSLATION_NONE		0
-#define EMU10K1_GPR_TRANSLATION_TABLE100	1
-#define EMU10K1_GPR_TRANSLATION_BASS		2
-#define EMU10K1_GPR_TRANSLATION_TREBLE		3
-#define EMU10K1_GPR_TRANSLATION_ONOFF		4
-
-struct snd_emu10k1_fx8010_control_gpr {
-	struct snd_ctl_elem_id id;		/* full control ID definition */
-	unsigned int vcount;		/* visible count */
-	unsigned int count;		/* count of GPR (1..16) */
-	unsigned short gpr[32];		/* GPR number(s) */
-	unsigned int value[32];		/* initial values */
-	unsigned int min;		/* minimum range */
-	unsigned int max;		/* maximum range */
-	unsigned int translation;	/* translation type (EMU10K1_GPR_TRANSLATION*) */
-	const unsigned int *tlv;
-};
-
-/* old ABI without TLV support */
-struct snd_emu10k1_fx8010_control_old_gpr {
-	struct snd_ctl_elem_id id;
-	unsigned int vcount;
-	unsigned int count;
-	unsigned short gpr[32];
-	unsigned int value[32];
-	unsigned int min;
-	unsigned int max;
-	unsigned int translation;
-};
-
-struct snd_emu10k1_fx8010_code {
-	char name[128];
-
-	DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */
-	__u32 __user *gpr_map;		/* initializers */
-
-	unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */
-	struct snd_emu10k1_fx8010_control_gpr __user *gpr_add_controls; /* GPR controls to add/replace */
-
-	unsigned int gpr_del_control_count; /* count of GPR controls to remove */
-	struct snd_ctl_elem_id __user *gpr_del_controls; /* IDs of GPR controls to remove */
-
-	unsigned int gpr_list_control_count; /* count of GPR controls to list */
-	unsigned int gpr_list_control_total; /* total count of GPR controls */
-	struct snd_emu10k1_fx8010_control_gpr __user *gpr_list_controls; /* listed GPR controls */
-
-	DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */
-	__u32 __user *tram_data_map;	  /* data initializers */
-	__u32 __user *tram_addr_map;	  /* map initializers */
-
-	DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */
-	__u32 __user *code;		  /* one instruction - 64 bits */
-};
-
-struct snd_emu10k1_fx8010_tram {
-	unsigned int address;		/* 31.bit == 1 -> external TRAM */
-	unsigned int size;		/* size in samples (4 bytes) */
-	unsigned int *samples;		/* pointer to samples (20-bit) */
-					/* NULL->clear memory */
-};
-
-struct snd_emu10k1_fx8010_pcm_rec {
-	unsigned int substream;		/* substream number */
-	unsigned int res1;		/* reserved */
-	unsigned int channels;		/* 16-bit channels count, zero = remove this substream */
-	unsigned int tram_start;	/* ring buffer position in TRAM (in samples) */
-	unsigned int buffer_size;	/* count of buffered samples */
-	unsigned short gpr_size;		/* GPR containing size of ringbuffer in samples (host) */
-	unsigned short gpr_ptr;		/* GPR containing current pointer in the ring buffer (host = reset, FX8010) */
-	unsigned short gpr_count;	/* GPR containing count of samples between two interrupts (host) */
-	unsigned short gpr_tmpcount;	/* GPR containing current count of samples to interrupt (host = set, FX8010) */
-	unsigned short gpr_trigger;	/* GPR containing trigger (activate) information (host) */
-	unsigned short gpr_running;	/* GPR containing info if PCM is running (FX8010) */
-	unsigned char pad;		/* reserved */
-	unsigned char etram[32];	/* external TRAM address & data (one per channel) */
-	unsigned int res2;		/* reserved */
-};
-
-#define SNDRV_EMU10K1_VERSION		SNDRV_PROTOCOL_VERSION(1, 0, 1)
-
-#define SNDRV_EMU10K1_IOCTL_INFO	_IOR ('H', 0x10, struct snd_emu10k1_fx8010_info)
-#define SNDRV_EMU10K1_IOCTL_CODE_POKE	_IOW ('H', 0x11, struct snd_emu10k1_fx8010_code)
-#define SNDRV_EMU10K1_IOCTL_CODE_PEEK	_IOWR('H', 0x12, struct snd_emu10k1_fx8010_code)
-#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP	_IOW ('H', 0x20, int)
-#define SNDRV_EMU10K1_IOCTL_TRAM_POKE	_IOW ('H', 0x21, struct snd_emu10k1_fx8010_tram)
-#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK	_IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram)
-#define SNDRV_EMU10K1_IOCTL_PCM_POKE	_IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec)
-#define SNDRV_EMU10K1_IOCTL_PCM_PEEK	_IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec)
-#define SNDRV_EMU10K1_IOCTL_PVERSION	_IOR ('H', 0x40, int)
-#define SNDRV_EMU10K1_IOCTL_STOP	_IO  ('H', 0x80)
-#define SNDRV_EMU10K1_IOCTL_CONTINUE	_IO  ('H', 0x81)
-#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82)
-#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP	_IOW ('H', 0x83, int)
-#define SNDRV_EMU10K1_IOCTL_DBG_READ	_IOR ('H', 0x84, int)
-
-/* typedefs for compatibility to user-space */
-typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
-typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
-typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
-typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
-typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
-
 #endif	/* __SOUND_EMU10K1_H */
diff --git a/include/sound/hdsp.h b/include/sound/hdsp.h
deleted file mode 100644
index 0909a38..0000000
--- a/include/sound/hdsp.h
+++ /dev/null
@@ -1,110 +0,0 @@
-#ifndef __SOUND_HDSP_H
-#define __SOUND_HDSP_H
-
-/*
- *   Copyright (C) 2003 Thomas Charbonnel (thomas@undata.org)
- *    
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/types.h>
-
-#define HDSP_MATRIX_MIXER_SIZE 2048
-
-enum HDSP_IO_Type {
-	Digiface,
-	Multiface,
-	H9652,
-	H9632,
-	RPM,
-	Undefined,
-};
-
-struct hdsp_peak_rms {
-	__u32 input_peaks[26];
-	__u32 playback_peaks[26];
-	__u32 output_peaks[28];
-	__u64 input_rms[26];
-	__u64 playback_rms[26];
-	/* These are only used for H96xx cards */
-	__u64 output_rms[26];
-};
-
-#define SNDRV_HDSP_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct hdsp_peak_rms)
-
-struct hdsp_config_info {
-	unsigned char pref_sync_ref;
-	unsigned char wordclock_sync_check;
-	unsigned char spdif_sync_check;
-	unsigned char adatsync_sync_check;
-	unsigned char adat_sync_check[3];
-	unsigned char spdif_in;
-	unsigned char spdif_out;
-	unsigned char spdif_professional;
-	unsigned char spdif_emphasis;
-	unsigned char spdif_nonaudio;
-	unsigned int spdif_sample_rate;
-	unsigned int system_sample_rate;
-	unsigned int autosync_sample_rate;
-	unsigned char system_clock_mode;
-	unsigned char clock_source;
-	unsigned char autosync_ref;
-	unsigned char line_out;
-	unsigned char passthru; 
-	unsigned char da_gain;
-	unsigned char ad_gain;
-	unsigned char phone_gain;
-	unsigned char xlr_breakout_cable;
-	unsigned char analog_extension_board;
-};
-
-#define SNDRV_HDSP_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, struct hdsp_config_info)
-
-struct hdsp_firmware {
-	void __user *firmware_data;	/* 24413 x 4 bytes */
-};
-
-#define SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE _IOW('H', 0x42, struct hdsp_firmware)
-
-struct hdsp_version {
-	enum HDSP_IO_Type io_type;
-	unsigned short firmware_rev;
-};
-
-#define SNDRV_HDSP_IOCTL_GET_VERSION _IOR('H', 0x43, struct hdsp_version)
-
-struct hdsp_mixer {
-	unsigned short matrix[HDSP_MATRIX_MIXER_SIZE];
-};
-
-#define SNDRV_HDSP_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdsp_mixer)
-
-struct hdsp_9632_aeb {
-	int aebi;
-	int aebo;
-};
-
-#define SNDRV_HDSP_IOCTL_GET_9632_AEB _IOR('H', 0x45, struct hdsp_9632_aeb)
-
-/* typedefs for compatibility to user-space */
-typedef enum HDSP_IO_Type HDSP_IO_Type;
-typedef struct hdsp_peak_rms hdsp_peak_rms_t;
-typedef struct hdsp_config_info hdsp_config_info_t;
-typedef struct hdsp_firmware hdsp_firmware_t;
-typedef struct hdsp_version hdsp_version_t;
-typedef struct hdsp_mixer hdsp_mixer_t;
-typedef struct hdsp_9632_aeb hdsp_9632_aeb_t;
-
-#endif /* __SOUND_HDSP_H */
diff --git a/include/sound/hdspm.h b/include/sound/hdspm.h
deleted file mode 100644
index 1f59ea2..0000000
--- a/include/sound/hdspm.h
+++ /dev/null
@@ -1,229 +0,0 @@
-#ifndef __SOUND_HDSPM_H
-#define __SOUND_HDSPM_H
-/*
- *   Copyright (C) 2003 Winfried Ritsch (IEM)
- *   based on hdsp.h from Thomas Charbonnel (thomas@undata.org)
- *
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */
-#define HDSPM_MAX_CHANNELS      64
-
-enum hdspm_io_type {
-	MADI,
-	MADIface,
-	AIO,
-	AES32,
-	RayDAT
-};
-
-enum hdspm_speed {
-	ss,
-	ds,
-	qs
-};
-
-/* -------------------- IOCTL Peak/RMS Meters -------------------- */
-
-struct hdspm_peak_rms {
-	uint32_t input_peaks[64];
-	uint32_t playback_peaks[64];
-	uint32_t output_peaks[64];
-
-	uint64_t input_rms[64];
-	uint64_t playback_rms[64];
-	uint64_t output_rms[64];
-
-	uint8_t speed; /* enum {ss, ds, qs} */
-	int status2;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS \
-	_IOR('H', 0x42, struct hdspm_peak_rms)
-
-/* ------------ CONFIG block IOCTL ---------------------- */
-
-struct hdspm_config {
-	unsigned char pref_sync_ref;
-	unsigned char wordclock_sync_check;
-	unsigned char madi_sync_check;
-	unsigned int system_sample_rate;
-	unsigned int autosync_sample_rate;
-	unsigned char system_clock_mode;
-	unsigned char clock_source;
-	unsigned char autosync_ref;
-	unsigned char line_out;
-	unsigned int passthru;
-	unsigned int analog_out;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_CONFIG \
-	_IOR('H', 0x41, struct hdspm_config)
-
-/**
- * If there's a TCO (TimeCode Option) board installed,
- * there are further options and status data available.
- * The hdspm_ltc structure contains the current SMPTE
- * timecode and some status information and can be
- * obtained via SNDRV_HDSPM_IOCTL_GET_LTC or in the
- * hdspm_status struct.
- **/
-
-enum hdspm_ltc_format {
-	format_invalid,
-	fps_24,
-	fps_25,
-	fps_2997,
-	fps_30
-};
-
-enum hdspm_ltc_frame {
-	frame_invalid,
-	drop_frame,
-	full_frame
-};
-
-enum hdspm_ltc_input_format {
-	ntsc,
-	pal,
-	no_video
-};
-
-struct hdspm_ltc {
-	unsigned int ltc;
-
-	enum hdspm_ltc_format format;
-	enum hdspm_ltc_frame frame;
-	enum hdspm_ltc_input_format input_format;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_LTC _IOR('H', 0x46, struct hdspm_mixer_ioctl)
-
-/**
- * The status data reflects the device's current state
- * as determined by the card's configuration and
- * connection status.
- **/
-
-enum hdspm_sync {
-	hdspm_sync_no_lock = 0,
-	hdspm_sync_lock = 1,
-	hdspm_sync_sync = 2
-};
-
-enum hdspm_madi_input {
-	hdspm_input_optical = 0,
-	hdspm_input_coax = 1
-};
-
-enum hdspm_madi_channel_format {
-	hdspm_format_ch_64 = 0,
-	hdspm_format_ch_56 = 1
-};
-
-enum hdspm_madi_frame_format {
-	hdspm_frame_48 = 0,
-	hdspm_frame_96 = 1
-};
-
-enum hdspm_syncsource {
-	syncsource_wc = 0,
-	syncsource_madi = 1,
-	syncsource_tco = 2,
-	syncsource_sync = 3,
-	syncsource_none = 4
-};
-
-struct hdspm_status {
-	uint8_t card_type; /* enum hdspm_io_type */
-	enum hdspm_syncsource autosync_source;
-
-	uint64_t card_clock;
-	uint32_t master_period;
-
-	union {
-		struct {
-			uint8_t sync_wc; /* enum hdspm_sync */
-			uint8_t sync_madi; /* enum hdspm_sync */
-			uint8_t sync_tco; /* enum hdspm_sync */
-			uint8_t sync_in; /* enum hdspm_sync */
-			uint8_t madi_input; /* enum hdspm_madi_input */
-			uint8_t channel_format; /* enum hdspm_madi_channel_format */
-			uint8_t frame_format; /* enum hdspm_madi_frame_format */
-		} madi;
-	} card_specific;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_STATUS \
-	_IOR('H', 0x47, struct hdspm_status)
-
-/**
- * Get information about the card and its add-ons.
- **/
-
-#define HDSPM_ADDON_TCO 1
-
-struct hdspm_version {
-	uint8_t card_type; /* enum hdspm_io_type */
-	char cardname[20];
-	unsigned int serial;
-	unsigned short firmware_rev;
-	int addons;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x48, struct hdspm_version)
-
-/* ------------- get Matrix Mixer IOCTL --------------- */
-
-/* MADI mixer: 64inputs+64playback in 64outputs = 8192 => *4Byte =
- * 32768 Bytes
- */
-
-/* organisation is 64 channelfader in a continuous memory block */
-/* equivalent to hardware definition, maybe for future feature of mmap of
- * them
- */
-/* each of 64 outputs has 64 infader and 64 outfader:
-   Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */
-
-#define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS
-
-struct hdspm_channelfader {
-	unsigned int in[HDSPM_MIXER_CHANNELS];
-	unsigned int pb[HDSPM_MIXER_CHANNELS];
-};
-
-struct hdspm_mixer {
-	struct hdspm_channelfader ch[HDSPM_MIXER_CHANNELS];
-};
-
-struct hdspm_mixer_ioctl {
-	struct hdspm_mixer *mixer;
-};
-
-/* use indirect access due to the limit of ioctl bit size */
-#define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdspm_mixer_ioctl)
-
-/* typedefs for compatibility to user-space */
-typedef struct hdspm_peak_rms hdspm_peak_rms_t;
-typedef struct hdspm_config_info hdspm_config_info_t;
-typedef struct hdspm_version hdspm_version_t;
-typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
-typedef struct hdspm_mixer hdspm_mixer_t;
-
-
-#endif
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 6268a41..45c1981 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -71,6 +71,8 @@ struct snd_pcm_ops {
 	int (*prepare)(struct snd_pcm_substream *substream);
 	int (*trigger)(struct snd_pcm_substream *substream, int cmd);
 	snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream);
+	int (*wall_clock)(struct snd_pcm_substream *substream,
+			  struct timespec *audio_ts);
 	int (*copy)(struct snd_pcm_substream *substream, int channel,
 		    snd_pcm_uframes_t pos,
 		    void __user *buf, snd_pcm_uframes_t count);
@@ -281,6 +283,7 @@ struct snd_pcm_runtime {
 	unsigned long hw_ptr_jiffies;	/* Time when hw_ptr is updated */
 	unsigned long hw_ptr_buffer_jiffies; /* buffer time in jiffies */
 	snd_pcm_sframes_t delay;	/* extra delay; typically FIFO size */
+	u64 hw_ptr_wrap;                /* offset for hw_ptr due to boundary wrap-around */
 
 	/* -- HW params -- */
 	snd_pcm_access_t access;	/* access mode */
diff --git a/include/sound/sb16_csp.h b/include/sound/sb16_csp.h
index 7e95056..c7c7788 100644
--- a/include/sound/sb16_csp.h
+++ b/include/sound/sb16_csp.h
@@ -1,6 +1,3 @@
-#ifndef __SOUND_SB16_CSP_H
-#define __SOUND_SB16_CSP_H
-
 /*
  *  Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si>
  *                        Takashi Iwai <tiwai@suse.de>
@@ -22,106 +19,13 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
  */
+#ifndef __SOUND_SB16_CSP_H
+#define __SOUND_SB16_CSP_H
 
-/* CSP modes */
-#define SNDRV_SB_CSP_MODE_NONE		0x00
-#define SNDRV_SB_CSP_MODE_DSP_READ	0x01	/* Record from DSP */
-#define SNDRV_SB_CSP_MODE_DSP_WRITE	0x02	/* Play to DSP */
-#define SNDRV_SB_CSP_MODE_QSOUND		0x04	/* QSound */
-
-/* CSP load flags */
-#define SNDRV_SB_CSP_LOAD_FROMUSER	0x01
-#define SNDRV_SB_CSP_LOAD_INITBLOCK	0x02
-
-/* CSP sample width */
-#define SNDRV_SB_CSP_SAMPLE_8BIT		0x01
-#define SNDRV_SB_CSP_SAMPLE_16BIT		0x02
-
-/* CSP channels */
-#define SNDRV_SB_CSP_MONO			0x01
-#define SNDRV_SB_CSP_STEREO		0x02
-
-/* CSP rates */
-#define SNDRV_SB_CSP_RATE_8000		0x01
-#define SNDRV_SB_CSP_RATE_11025		0x02
-#define SNDRV_SB_CSP_RATE_22050		0x04
-#define SNDRV_SB_CSP_RATE_44100		0x08
-#define SNDRV_SB_CSP_RATE_ALL		0x0f
-
-/* CSP running state */
-#define SNDRV_SB_CSP_ST_IDLE		0x00
-#define SNDRV_SB_CSP_ST_LOADED		0x01
-#define SNDRV_SB_CSP_ST_RUNNING		0x02
-#define SNDRV_SB_CSP_ST_PAUSED		0x04
-#define SNDRV_SB_CSP_ST_AUTO		0x08
-#define SNDRV_SB_CSP_ST_QSOUND		0x10
-
-/* maximum QSound value (180 degrees right) */
-#define SNDRV_SB_CSP_QSOUND_MAX_RIGHT	0x20
-
-/* maximum microcode RIFF file size */
-#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE	0x3000
-
-/* microcode header */
-struct snd_sb_csp_mc_header {
-	char codec_name[16];		/* id name of codec */
-	unsigned short func_req;	/* requested function */
-};
-
-/* microcode to be loaded */
-struct snd_sb_csp_microcode {
-	struct snd_sb_csp_mc_header info;
-	unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE];
-};
-
-/* start CSP with sample_width in mono/stereo */
-struct snd_sb_csp_start {
-	int sample_width;	/* sample width, look above */
-	int channels;		/* channels, look above */
-};
-
-/* CSP information */
-struct snd_sb_csp_info {
-	char codec_name[16];		/* id name of codec */
-	unsigned short func_nr;		/* function number */
-	unsigned int acc_format;	/* accepted PCM formats */
-	unsigned short acc_channels;	/* accepted channels */
-	unsigned short acc_width;	/* accepted sample width */
-	unsigned short acc_rates;	/* accepted sample rates */
-	unsigned short csp_mode;	/* CSP mode, see above */
-	unsigned short run_channels;	/* current channels  */
-	unsigned short run_width;	/* current sample width */
-	unsigned short version;		/* version id: 0x10 - 0x1f */
-	unsigned short state;		/* state bits */
-};
-
-/* HWDEP controls */
-/* get CSP information */
-#define SNDRV_SB_CSP_IOCTL_INFO		_IOR('H', 0x10, struct snd_sb_csp_info)
-/* load microcode to CSP */
-/* NOTE: struct snd_sb_csp_microcode overflows the max size (13 bits)
- * defined for some architectures like MIPS, and it leads to build errors.
- * (x86 and co have 14-bit size, thus it's valid, though.)
- * As a workaround for skipping the size-limit check, here we don't use the
- * normal _IOW() macro but _IOC() with the manual argument.
- */
-#define SNDRV_SB_CSP_IOCTL_LOAD_CODE	\
-	_IOC(_IOC_WRITE, 'H', 0x11, sizeof(struct snd_sb_csp_microcode))
-/* unload microcode from CSP */
-#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE	_IO('H', 0x12)
-/* start CSP */
-#define SNDRV_SB_CSP_IOCTL_START		_IOW('H', 0x13, struct snd_sb_csp_start)
-/* stop CSP */
-#define SNDRV_SB_CSP_IOCTL_STOP		_IO('H', 0x14)
-/* pause CSP and DMA transfer */
-#define SNDRV_SB_CSP_IOCTL_PAUSE		_IO('H', 0x15)
-/* restart CSP and DMA transfer */
-#define SNDRV_SB_CSP_IOCTL_RESTART	_IO('H', 0x16)
-
-#ifdef __KERNEL__
 #include <sound/sb.h>
 #include <sound/hwdep.h>
 #include <linux/firmware.h>
+#include <uapi/sound/sb16_csp.h>
 
 struct snd_sb_csp;
 
@@ -183,6 +87,4 @@ struct snd_sb_csp {
 };
 
 int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep);
-#endif
-
 #endif /* __SOUND_SB16_CSP */
diff --git a/include/sound/sfnt_info.h b/include/sound/sfnt_info.h
deleted file mode 100644
index 1bce7fd..0000000
--- a/include/sound/sfnt_info.h
+++ /dev/null
@@ -1,212 +0,0 @@
-#ifndef __SOUND_SFNT_INFO_H
-#define __SOUND_SFNT_INFO_H
-
-/*
- *  Patch record compatible with AWE driver on OSS
- *
- *  Copyright (C) 1999-2000 Takashi Iwai
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You 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 <sound/asound.h>
-
-/*
- * patch information record
- */
-
-#ifdef SNDRV_BIG_ENDIAN
-#define SNDRV_OSS_PATCHKEY(id) (0xfd00|id)
-#else
-#define SNDRV_OSS_PATCHKEY(id) ((id<<8)|0xfd)
-#endif
-
-/* patch interface header: 16 bytes */
-struct soundfont_patch_info {
-	unsigned short key;		/* use the key below */
-#define SNDRV_OSS_SOUNDFONT_PATCH		SNDRV_OSS_PATCHKEY(0x07)
-
-	short device_no;		/* synthesizer number */
-	unsigned short sf_id;		/* file id (should be zero) */
-	short optarg;			/* optional argument */
-	int len;			/* data length (without this header) */
-
-	short type;			/* patch operation type */
-#define SNDRV_SFNT_LOAD_INFO		0	/* awe_voice_rec */
-#define SNDRV_SFNT_LOAD_DATA		1	/* awe_sample_info */
-#define SNDRV_SFNT_OPEN_PATCH	2	/* awe_open_parm */
-#define SNDRV_SFNT_CLOSE_PATCH	3	/* none */
-	/* 4 is obsolete */
-#define SNDRV_SFNT_REPLACE_DATA	5	/* awe_sample_info (optarg=#channels)*/
-#define SNDRV_SFNT_MAP_PRESET	6	/* awe_voice_map */
-	/* 7 is not used */
-#define SNDRV_SFNT_PROBE_DATA		8	/* optarg=sample */
-#define SNDRV_SFNT_REMOVE_INFO		9	/* optarg=(bank<<8)|instr */
-
-	short reserved;			/* word alignment data */
-
-	/* the actual patch data begins after this */
-};
-
-
-/*
- * open patch
- */
-
-#define SNDRV_SFNT_PATCH_NAME_LEN	32
-
-struct soundfont_open_parm {
-	unsigned short type;		/* sample type */
-#define SNDRV_SFNT_PAT_TYPE_MISC	0
-#define SNDRV_SFNT_PAT_TYPE_GUS	6
-#define SNDRV_SFNT_PAT_TYPE_MAP	7
-#define SNDRV_SFNT_PAT_LOCKED	0x100	/* lock the samples */
-#define SNDRV_SFNT_PAT_SHARED	0x200	/* sample is shared */
-
-	short reserved;
-	char name[SNDRV_SFNT_PATCH_NAME_LEN];
-};
-
-
-/*
- * raw voice information record
- */
-
-/* wave table envelope & effect parameters to control EMU8000 */
-struct soundfont_voice_parm {
-	unsigned short moddelay;	/* modulation delay (0x8000) */
-	unsigned short modatkhld;	/* modulation attack & hold time (0x7f7f) */
-	unsigned short moddcysus;	/* modulation decay & sustain (0x7f7f) */
-	unsigned short modrelease;	/* modulation release time (0x807f) */
-	short modkeyhold, modkeydecay;	/* envelope change per key (not used) */
-	unsigned short voldelay;	/* volume delay (0x8000) */
-	unsigned short volatkhld;	/* volume attack & hold time (0x7f7f) */
-	unsigned short voldcysus;	/* volume decay & sustain (0x7f7f) */
-	unsigned short volrelease;	/* volume release time (0x807f) */
-	short volkeyhold, volkeydecay;	/* envelope change per key (not used) */
-	unsigned short lfo1delay;	/* LFO1 delay (0x8000) */
-	unsigned short lfo2delay;	/* LFO2 delay (0x8000) */
-	unsigned short pefe;		/* modulation pitch & cutoff (0x0000) */
-	unsigned short fmmod;		/* LFO1 pitch & cutoff (0x0000) */
-	unsigned short tremfrq;		/* LFO1 volume & freq (0x0000) */
-	unsigned short fm2frq2;		/* LFO2 pitch & freq (0x0000) */
-	unsigned char cutoff;		/* initial cutoff (0xff) */
-	unsigned char filterQ;		/* initial filter Q [0-15] (0x0) */
-	unsigned char chorus;		/* chorus send (0x00) */
-	unsigned char reverb;		/* reverb send (0x00) */
-	unsigned short reserved[4];	/* not used */
-};
-
-
-/* wave table parameters: 92 bytes */
-struct soundfont_voice_info {
-	unsigned short sf_id;		/* file id (should be zero) */
-	unsigned short sample;		/* sample id */
-	int start, end;			/* sample offset correction */
-	int loopstart, loopend;		/* loop offset correction */
-	short rate_offset;		/* sample rate pitch offset */
-	unsigned short mode;		/* sample mode */
-#define SNDRV_SFNT_MODE_ROMSOUND		0x8000
-#define SNDRV_SFNT_MODE_STEREO		1
-#define SNDRV_SFNT_MODE_LOOPING		2
-#define SNDRV_SFNT_MODE_NORELEASE		4	/* obsolete */
-#define SNDRV_SFNT_MODE_INIT_PARM		8
-
-	short root;			/* midi root key */
-	short tune;			/* pitch tuning (in cents) */
-	unsigned char low, high;	/* key note range */
-	unsigned char vellow, velhigh;	/* velocity range */
-	signed char fixkey, fixvel;	/* fixed key, velocity */
-	signed char pan, fixpan;	/* panning, fixed panning */
-	short exclusiveClass;		/* exclusive class (0 = none) */
-	unsigned char amplitude;	/* sample volume (127 max) */
-	unsigned char attenuation;	/* attenuation (0.375dB) */
-	short scaleTuning;		/* pitch scale tuning(%), normally 100 */
-	struct soundfont_voice_parm parm;	/* voice envelope parameters */
-	unsigned short sample_mode;	/* sample mode_flag (set by driver) */
-};
-
-
-/* instrument info header: 4 bytes */
-struct soundfont_voice_rec_hdr {
-	unsigned char bank;		/* midi bank number */
-	unsigned char instr;		/* midi preset number */
-	char nvoices;			/* number of voices */
-	char write_mode;		/* write mode; normally 0 */
-#define SNDRV_SFNT_WR_APPEND		0	/* append anyway */
-#define SNDRV_SFNT_WR_EXCLUSIVE		1	/* skip if already exists */
-#define SNDRV_SFNT_WR_REPLACE		2	/* replace if already exists */
-};
-
-
-/*
- * sample wave information
- */
-
-/* wave table sample header: 32 bytes */
-struct soundfont_sample_info {
-	unsigned short sf_id;		/* file id (should be zero) */
-	unsigned short sample;		/* sample id */
-	int start, end;			/* start & end offset */
-	int loopstart, loopend;		/* loop start & end offset */
-	int size;			/* size (0 = ROM) */
-	short dummy;			/* not used */
-	unsigned short mode_flags;	/* mode flags */
-#define SNDRV_SFNT_SAMPLE_8BITS		1	/* wave data is 8bits */
-#define SNDRV_SFNT_SAMPLE_UNSIGNED	2	/* wave data is unsigned */
-#define SNDRV_SFNT_SAMPLE_NO_BLANK	4	/* no blank loop is attached */
-#define SNDRV_SFNT_SAMPLE_SINGLESHOT	8	/* single-shot w/o loop */
-#define SNDRV_SFNT_SAMPLE_BIDIR_LOOP	16	/* bidirectional looping */
-#define SNDRV_SFNT_SAMPLE_STEREO_LEFT	32	/* stereo left sound */
-#define SNDRV_SFNT_SAMPLE_STEREO_RIGHT	64	/* stereo right sound */
-#define SNDRV_SFNT_SAMPLE_REVERSE_LOOP	128	/* reverse looping */
-	unsigned int truesize;		/* used memory size (set by driver) */
-};
-
-
-/*
- * voice preset mapping (aliasing)
- */
-
-struct soundfont_voice_map {
-	int map_bank, map_instr, map_key;	/* key = -1 means all keys */
-	int src_bank, src_instr, src_key;
-};
-
-
-/*
- * ioctls for hwdep
- */
-
-#define SNDRV_EMUX_HWDEP_NAME	"Emux WaveTable"
-
-#define SNDRV_EMUX_VERSION	((1 << 16) | (0 << 8) | 0)	/* 1.0.0 */
-
-struct snd_emux_misc_mode {
-	int port;	/* -1 = all */
-	int mode;
-	int value;
-	int value2;	/* reserved */
-};
-
-#define SNDRV_EMUX_IOCTL_VERSION	_IOR('H', 0x80, unsigned int)
-#define SNDRV_EMUX_IOCTL_LOAD_PATCH	_IOWR('H', 0x81, struct soundfont_patch_info)
-#define SNDRV_EMUX_IOCTL_RESET_SAMPLES	_IO('H', 0x82)
-#define SNDRV_EMUX_IOCTL_REMOVE_LAST_SAMPLES _IO('H', 0x83)
-#define SNDRV_EMUX_IOCTL_MEM_AVAIL	_IOW('H', 0x84, int)
-#define SNDRV_EMUX_IOCTL_MISC_MODE	_IOWR('H', 0x84, struct snd_emux_misc_mode)
-
-#endif /* __SOUND_SFNT_INFO_H */
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h
index 9060103..cc1c919 100644
--- a/include/sound/sh_fsi.h
+++ b/include/sound/sh_fsi.h
@@ -26,6 +26,7 @@
  * A:  inversion
  * B:  format mode
  * C:  chip specific
+ * D:  clock selecter if master mode
  */
 
 /* A: clock inversion */
@@ -44,6 +45,11 @@
 #define SH_FSI_OPTION_MASK	0x00000F00
 #define SH_FSI_ENABLE_STREAM_MODE	(1 << 8) /* for 16bit data */
 
+/* D:  clock selecter if master mode */
+#define SH_FSI_CLK_MASK		0x0000F000
+#define SH_FSI_CLK_EXTERNAL	(0 << 12)
+#define SH_FSI_CLK_CPG		(1 << 12) /* FSIxCK + FSI-DIV */
+
 /*
  * set_rate return value
  *
diff --git a/include/sound/tlv320aic32x4.h b/include/sound/tlv320aic32x4.h
index c009f70..24e5d99 100644
--- a/include/sound/tlv320aic32x4.h
+++ b/include/sound/tlv320aic32x4.h
@@ -26,6 +26,7 @@ struct aic32x4_pdata {
 	u32 power_cfg;
 	u32 micpga_routing;
 	bool swapdacs;
+	int rstn_gpio;
 };
 
 #endif
diff --git a/include/sound/vx_core.h b/include/sound/vx_core.h
index 4f67c76..f634f8f 100644
--- a/include/sound/vx_core.h
+++ b/include/sound/vx_core.h
@@ -27,12 +27,6 @@
 #include <sound/hwdep.h>
 #include <linux/interrupt.h>
 
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
-#if !defined(CONFIG_USE_VXLOADER) && !defined(CONFIG_SND_VX_LIB) /* built-in kernel */
-#define SND_VX_FW_LOADER	/* use the standard firmware loader */
-#endif
-#endif
-
 struct firmware;
 struct device;
 
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
index 2acd540..5079109 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -9,6 +9,8 @@ struct se_subsystem_api {
 	struct list_head sub_api_list;
 
 	char name[16];
+	char inquiry_prod[16];
+	char inquiry_rev[4];
 	struct module *owner;
 
 	u8 transport_type;
@@ -16,46 +18,45 @@ struct se_subsystem_api {
 	int (*attach_hba)(struct se_hba *, u32);
 	void (*detach_hba)(struct se_hba *);
 	int (*pmode_enable_hba)(struct se_hba *, unsigned long);
-	void *(*allocate_virtdevice)(struct se_hba *, const char *);
-	struct se_device *(*create_virtdevice)(struct se_hba *,
-				struct se_subsystem_dev *, void *);
-	void (*free_device)(void *);
+
+	struct se_device *(*alloc_device)(struct se_hba *, const char *);
+	int (*configure_device)(struct se_device *);
+	void (*free_device)(struct se_device *device);
+
+	ssize_t (*set_configfs_dev_params)(struct se_device *,
+					   const char *, ssize_t);
+	ssize_t (*show_configfs_dev_params)(struct se_device *, char *);
+
 	void (*transport_complete)(struct se_cmd *cmd,
 				   struct scatterlist *,
 				   unsigned char *);
 
-	int (*parse_cdb)(struct se_cmd *cmd);
-	ssize_t (*check_configfs_dev_params)(struct se_hba *,
-			struct se_subsystem_dev *);
-	ssize_t (*set_configfs_dev_params)(struct se_hba *,
-			struct se_subsystem_dev *, const char *, ssize_t);
-	ssize_t (*show_configfs_dev_params)(struct se_hba *,
-			struct se_subsystem_dev *, char *);
-	u32 (*get_device_rev)(struct se_device *);
+	sense_reason_t (*parse_cdb)(struct se_cmd *cmd);
 	u32 (*get_device_type)(struct se_device *);
 	sector_t (*get_blocks)(struct se_device *);
 	unsigned char *(*get_sense_buffer)(struct se_cmd *);
 };
 
-struct spc_ops {
-	int (*execute_rw)(struct se_cmd *cmd);
-	int (*execute_sync_cache)(struct se_cmd *cmd);
-	int (*execute_write_same)(struct se_cmd *cmd);
-	int (*execute_unmap)(struct se_cmd *cmd);
+struct sbc_ops {
+	sense_reason_t (*execute_rw)(struct se_cmd *cmd);
+	sense_reason_t (*execute_sync_cache)(struct se_cmd *cmd);
+	sense_reason_t (*execute_write_same)(struct se_cmd *cmd);
+	sense_reason_t (*execute_write_same_unmap)(struct se_cmd *cmd);
+	sense_reason_t (*execute_unmap)(struct se_cmd *cmd);
 };
 
 int	transport_subsystem_register(struct se_subsystem_api *);
 void	transport_subsystem_release(struct se_subsystem_api *);
 
-struct se_device *transport_add_device_to_core_hba(struct se_hba *,
-		struct se_subsystem_api *, struct se_subsystem_dev *, u32,
-		void *, struct se_dev_limits *, const char *, const char *);
-
 void	target_complete_cmd(struct se_cmd *, u8);
 
-int	sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops);
-int	spc_parse_cdb(struct se_cmd *cmd, unsigned int *size);
-int	spc_get_write_same_sectors(struct se_cmd *cmd);
+sense_reason_t	spc_parse_cdb(struct se_cmd *cmd, unsigned int *size);
+sense_reason_t	spc_emulate_report_luns(struct se_cmd *cmd);
+sector_t	spc_get_write_same_sectors(struct se_cmd *cmd);
+
+sense_reason_t	sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops);
+u32	sbc_get_device_rev(struct se_device *dev);
+u32	sbc_get_device_type(struct se_device *dev);
 
 void	transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *);
 int	transport_set_vpd_assoc(struct t10_vpd *, unsigned char *);
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 5be8937..645d90a 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -62,20 +62,6 @@
 
 #define PYX_TRANSPORT_STATUS_INTERVAL		5 /* In seconds */
 
-/*
- * struct se_subsystem_dev->su_dev_flags
-*/
-#define SDF_FIRMWARE_VPD_UNIT_SERIAL		0x00000001
-#define SDF_EMULATED_VPD_UNIT_SERIAL		0x00000002
-#define SDF_USING_UDEV_PATH			0x00000004
-#define SDF_USING_ALIAS				0x00000008
-
-/*
- * struct se_device->dev_flags
- */
-#define DF_SPC2_RESERVATIONS			0x00000001
-#define DF_SPC2_RESERVATIONS_WITH_ISID		0x00000002
-
 /* struct se_dev_attrib sanity values */
 /* Default max_unmap_lba_count */
 #define DA_MAX_UNMAP_LBA_COUNT			0
@@ -85,6 +71,8 @@
 #define DA_UNMAP_GRANULARITY_DEFAULT		0
 /* Default unmap_granularity_alignment */
 #define DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT	0
+/* Default max_write_same_len, disabled by default */
+#define DA_MAX_WRITE_SAME_LEN			0
 /* Default max transfer length */
 #define DA_FABRIC_MAX_SECTORS			8192
 /* Emulation for Direct Page Out */
@@ -107,8 +95,6 @@
  */
 #define DA_EMULATE_TPWS				0
 /* No Emulation for PSCSI by default */
-#define DA_EMULATE_RESERVATIONS			0
-/* No Emulation for PSCSI by default */
 #define DA_EMULATE_ALUA				0
 /* Enforce SCSI Initiator Port TransportID with 'ISID' for PR */
 #define DA_ENFORCE_PR_ISIDS			1
@@ -160,8 +146,6 @@ enum se_cmd_flags_table {
 	SCF_EMULATED_TASK_SENSE		= 0x00000004,
 	SCF_SCSI_DATA_CDB		= 0x00000008,
 	SCF_SCSI_TMR_CDB		= 0x00000010,
-	SCF_SCSI_CDB_EXCEPTION		= 0x00000020,
-	SCF_SCSI_RESERVATION_CONFLICT	= 0x00000040,
 	SCF_FUA				= 0x00000080,
 	SCF_SE_LUN_CMD			= 0x00000100,
 	SCF_BIDI			= 0x00000400,
@@ -182,38 +166,33 @@ enum transport_lunflags_table {
 	TRANSPORT_LUNFLAGS_READ_WRITE		= 0x04,
 };
 
-/* struct se_device->dev_status */
-enum transport_device_status_table {
-	TRANSPORT_DEVICE_ACTIVATED		= 0x01,
-	TRANSPORT_DEVICE_DEACTIVATED		= 0x02,
-	TRANSPORT_DEVICE_QUEUE_FULL		= 0x04,
-	TRANSPORT_DEVICE_SHUTDOWN		= 0x08,
-	TRANSPORT_DEVICE_OFFLINE_ACTIVATED	= 0x10,
-	TRANSPORT_DEVICE_OFFLINE_DEACTIVATED	= 0x20,
-};
-
 /*
- * Used by transport_send_check_condition_and_sense() and se_cmd->scsi_sense_reason
+ * Used by transport_send_check_condition_and_sense()
  * to signal which ASC/ASCQ sense payload should be built.
  */
+typedef unsigned __bitwise__ sense_reason_t;
+
 enum tcm_sense_reason_table {
-	TCM_NON_EXISTENT_LUN			= 0x01,
-	TCM_UNSUPPORTED_SCSI_OPCODE		= 0x02,
-	TCM_INCORRECT_AMOUNT_OF_DATA		= 0x03,
-	TCM_UNEXPECTED_UNSOLICITED_DATA		= 0x04,
-	TCM_SERVICE_CRC_ERROR			= 0x05,
-	TCM_SNACK_REJECTED			= 0x06,
-	TCM_SECTOR_COUNT_TOO_MANY		= 0x07,
-	TCM_INVALID_CDB_FIELD			= 0x08,
-	TCM_INVALID_PARAMETER_LIST		= 0x09,
-	TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE	= 0x0a,
-	TCM_UNKNOWN_MODE_PAGE			= 0x0b,
-	TCM_WRITE_PROTECTED			= 0x0c,
-	TCM_CHECK_CONDITION_ABORT_CMD		= 0x0d,
-	TCM_CHECK_CONDITION_UNIT_ATTENTION	= 0x0e,
-	TCM_CHECK_CONDITION_NOT_READY		= 0x0f,
-	TCM_RESERVATION_CONFLICT		= 0x10,
-	TCM_ADDRESS_OUT_OF_RANGE		= 0x11,
+#define R(x)	(__force sense_reason_t )(x)
+	TCM_NON_EXISTENT_LUN			= R(0x01),
+	TCM_UNSUPPORTED_SCSI_OPCODE		= R(0x02),
+	TCM_INCORRECT_AMOUNT_OF_DATA		= R(0x03),
+	TCM_UNEXPECTED_UNSOLICITED_DATA		= R(0x04),
+	TCM_SERVICE_CRC_ERROR			= R(0x05),
+	TCM_SNACK_REJECTED			= R(0x06),
+	TCM_SECTOR_COUNT_TOO_MANY		= R(0x07),
+	TCM_INVALID_CDB_FIELD			= R(0x08),
+	TCM_INVALID_PARAMETER_LIST		= R(0x09),
+	TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE	= R(0x0a),
+	TCM_UNKNOWN_MODE_PAGE			= R(0x0b),
+	TCM_WRITE_PROTECTED			= R(0x0c),
+	TCM_CHECK_CONDITION_ABORT_CMD		= R(0x0d),
+	TCM_CHECK_CONDITION_UNIT_ATTENTION	= R(0x0e),
+	TCM_CHECK_CONDITION_NOT_READY		= R(0x0f),
+	TCM_RESERVATION_CONFLICT		= R(0x10),
+	TCM_ADDRESS_OUT_OF_RANGE		= R(0x11),
+	TCM_OUT_OF_RESOURCES			= R(0x12),
+#undef R
 };
 
 enum target_sc_flags_table {
@@ -246,30 +225,6 @@ enum tcm_tmrsp_table {
 	TMR_FUNCTION_REJECTED		= 255,
 };
 
-struct se_obj {
-	atomic_t obj_access_count;
-};
-
-/*
- * Used by TCM Core internally to signal if ALUA emulation is enabled or
- * disabled, or running in with TCM/pSCSI passthrough mode
- */
-typedef enum {
-	SPC_ALUA_PASSTHROUGH,
-	SPC2_ALUA_DISABLED,
-	SPC3_ALUA_EMULATED
-} t10_alua_index_t;
-
-/*
- * Used by TCM Core internally to signal if SAM Task Attribute emulation
- * is enabled or disabled, or running in with TCM/pSCSI passthrough mode
- */
-typedef enum {
-	SAM_TASK_ATTR_PASSTHROUGH,
-	SAM_TASK_ATTR_UNTAGGED,
-	SAM_TASK_ATTR_EMULATED
-} t10_task_attr_index_t;
-
 /*
  * Used for target SCSI statistics
  */
@@ -283,17 +238,15 @@ typedef enum {
 struct se_cmd;
 
 struct t10_alua {
-	t10_alua_index_t alua_type;
 	/* ALUA Target Port Group ID */
 	u16	alua_tg_pt_gps_counter;
 	u32	alua_tg_pt_gps_count;
 	spinlock_t tg_pt_gps_lock;
-	struct se_subsystem_dev *t10_sub_dev;
+	struct se_device *t10_dev;
 	/* Used for default ALUA Target Port Group */
 	struct t10_alua_tg_pt_gp *default_tg_pt_gp;
 	/* Used for default ALUA Target Port Group ConfigFS group */
 	struct config_group alua_tg_pt_gps_group;
-	int (*alua_state_check)(struct se_cmd *, unsigned char *, u8 *);
 	struct list_head tg_pt_gps_list;
 };
 
@@ -335,7 +288,7 @@ struct t10_alua_tg_pt_gp {
 	atomic_t tg_pt_gp_ref_cnt;
 	spinlock_t tg_pt_gp_lock;
 	struct mutex tg_pt_gp_md_mutex;
-	struct se_subsystem_dev *tg_pt_gp_su_dev;
+	struct se_device *tg_pt_gp_dev;
 	struct config_group tg_pt_gp_group;
 	struct list_head tg_pt_gp_list;
 	struct list_head tg_pt_gp_mem_list;
@@ -366,23 +319,11 @@ struct t10_wwn {
 	char revision[4];
 	char unit_serial[INQUIRY_VPD_SERIAL_LEN];
 	spinlock_t t10_vpd_lock;
-	struct se_subsystem_dev *t10_sub_dev;
+	struct se_device *t10_dev;
 	struct config_group t10_wwn_group;
 	struct list_head t10_vpd_list;
 };
 
-
-/*
- * Used by TCM Core internally to signal if >= SPC-3 persistent reservations
- * emulation is enabled or disabled, or running in with TCM/pSCSI passthrough
- * mode
- */
-typedef enum {
-	SPC_PASSTHROUGH,
-	SPC2_RESERVATIONS,
-	SPC3_PERSISTENT_RESERVATIONS
-} t10_reservations_index_t;
-
 struct t10_pr_registration {
 	/* Used for fabrics that contain WWN+ISID */
 #define PR_REG_ISID_LEN				16
@@ -424,18 +365,6 @@ struct t10_pr_registration {
 	struct list_head pr_reg_atp_mem_list;
 };
 
-/*
- * This set of function pointer ops is set based upon SPC3_PERSISTENT_RESERVATIONS,
- * SPC2_RESERVATIONS or SPC_PASSTHROUGH in drivers/target/target_core_pr.c:
- * core_setup_reservations()
- */
-struct t10_reservation_ops {
-	int (*t10_reservation_check)(struct se_cmd *, u32 *);
-	int (*t10_seq_non_holder)(struct se_cmd *, unsigned char *, u32);
-	int (*t10_pr_register)(struct se_cmd *);
-	int (*t10_pr_clear)(struct se_cmd *);
-};
-
 struct t10_reservation {
 	/* Reservation effects all target ports */
 	int pr_all_tg_pt;
@@ -446,7 +375,6 @@ struct t10_reservation {
 #define PR_APTPL_BUF_LEN			8192
 	u32 pr_aptpl_buf_len;
 	u32 pr_generation;
-	t10_reservations_index_t res_type;
 	spinlock_t registration_lock;
 	spinlock_t aptpl_reg_lock;
 	/*
@@ -462,7 +390,6 @@ struct t10_reservation {
 	struct se_node_acl *pr_res_holder;
 	struct list_head registration_list;
 	struct list_head aptpl_reg_list;
-	struct t10_reservation_ops pr_ops;
 };
 
 struct se_tmr_req {
@@ -485,7 +412,6 @@ struct se_cmd {
 	u8			scsi_status;
 	u8			scsi_asc;
 	u8			scsi_ascq;
-	u8			scsi_sense_reason;
 	u16			scsi_sense_length;
 	/* Delay for ALUA Active/NonOptimized state access in milliseconds */
 	int			alua_nonop_delay;
@@ -523,7 +449,7 @@ struct se_cmd {
 	struct completion	cmd_wait_comp;
 	struct kref		cmd_kref;
 	struct target_core_fabric_ops *se_tfo;
-	int (*execute_cmd)(struct se_cmd *);
+	sense_reason_t		(*execute_cmd)(struct se_cmd *);
 	void (*transport_complete_callback)(struct se_cmd *);
 
 	unsigned char		*t_task_cdb;
@@ -662,15 +588,6 @@ struct se_dev_entry {
 	struct list_head	ua_list;
 };
 
-struct se_dev_limits {
-	/* Max supported HW queue depth */
-	u32		hw_queue_depth;
-	/* Max supported virtual queue depth */
-	u32		queue_depth;
-	/* From include/linux/blkdev.h for the other HW/SW limits. */
-	struct queue_limits limits;
-};
-
 struct se_dev_attrib {
 	int		emulate_dpo;
 	int		emulate_fua_write;
@@ -680,8 +597,6 @@ struct se_dev_attrib {
 	int		emulate_tas;
 	int		emulate_tpu;
 	int		emulate_tpws;
-	int		emulate_reservations;
-	int		emulate_alua;
 	int		enforce_pr_isids;
 	int		is_nonrot;
 	int		emulate_rest_reord;
@@ -696,7 +611,8 @@ struct se_dev_attrib {
 	u32		max_unmap_block_desc_count;
 	u32		unmap_granularity;
 	u32		unmap_granularity_alignment;
-	struct se_subsystem_dev *da_sub_dev;
+	u32		max_write_same_len;
+	struct se_device *da_dev;
 	struct config_group da_group;
 };
 
@@ -707,48 +623,23 @@ struct se_dev_stat_grps {
 	struct config_group scsi_lu_group;
 };
 
-struct se_subsystem_dev {
-/* Used for struct se_subsystem_dev-->se_dev_alias, must be less than PAGE_SIZE */
-#define SE_DEV_ALIAS_LEN		512
-	unsigned char	se_dev_alias[SE_DEV_ALIAS_LEN];
-/* Used for struct se_subsystem_dev->se_dev_udev_path[], must be less than PAGE_SIZE */
-#define SE_UDEV_PATH_LEN		512
-	unsigned char	se_dev_udev_path[SE_UDEV_PATH_LEN];
-	u32		su_dev_flags;
-	struct se_hba *se_dev_hba;
-	struct se_device *se_dev_ptr;
-	struct se_dev_attrib se_dev_attrib;
-	/* T10 Asymmetric Logical Unit Assignment for Target Ports */
-	struct t10_alua	t10_alua;
-	/* T10 Inquiry and VPD WWN Information */
-	struct t10_wwn	t10_wwn;
-	/* T10 SPC-2 + SPC-3 Reservations */
-	struct t10_reservation t10_pr;
-	spinlock_t      se_dev_lock;
-	void            *se_dev_su_ptr;
-	struct config_group se_dev_group;
-	/* For T10 Reservations */
-	struct config_group se_dev_pr_group;
-	/* For target_core_stat.c groups */
-	struct se_dev_stat_grps dev_stat_grps;
-};
-
 struct se_device {
 	/* RELATIVE TARGET PORT IDENTIFER Counter */
 	u16			dev_rpti_counter;
 	/* Used for SAM Task Attribute ordering */
 	u32			dev_cur_ordered_id;
 	u32			dev_flags;
+#define DF_CONFIGURED				0x00000001
+#define DF_FIRMWARE_VPD_UNIT_SERIAL		0x00000002
+#define DF_EMULATED_VPD_UNIT_SERIAL		0x00000004
+#define DF_USING_UDEV_PATH			0x00000008
+#define DF_USING_ALIAS				0x00000010
 	u32			dev_port_count;
-	/* See transport_device_status_table */
-	u32			dev_status;
 	/* Physical device queue depth */
 	u32			queue_depth;
 	/* Used for SPC-2 reservations enforce of ISIDs */
 	u64			dev_res_bin_isid;
-	t10_task_attr_index_t	dev_task_attr_type;
 	/* Pointer to transport specific device structure */
-	void 			*dev_ptr;
 	u32			dev_index;
 	u64			creation_time;
 	u32			num_resets;
@@ -761,13 +652,13 @@ struct se_device {
 	atomic_t		dev_ordered_id;
 	atomic_t		dev_ordered_sync;
 	atomic_t		dev_qf_count;
-	struct se_obj		dev_obj;
-	struct se_obj		dev_access_obj;
-	struct se_obj		dev_export_obj;
+	int			export_count;
 	spinlock_t		delayed_cmd_lock;
 	spinlock_t		execute_task_lock;
 	spinlock_t		dev_reservation_lock;
-	spinlock_t		dev_status_lock;
+	unsigned int		dev_reservation_flags;
+#define DRF_SPC2_RESERVATIONS			0x00000001
+#define DRF_SPC2_RESERVATIONS_WITH_ISID		0x00000002
 	spinlock_t		se_port_lock;
 	spinlock_t		se_tmr_lock;
 	spinlock_t		qf_cmd_lock;
@@ -786,7 +677,20 @@ struct se_device {
 	struct list_head	qf_cmd_list;
 	/* Pointer to associated SE HBA */
 	struct se_hba		*se_hba;
-	struct se_subsystem_dev *se_sub_dev;
+	/* T10 Inquiry and VPD WWN Information */
+	struct t10_wwn		t10_wwn;
+	/* T10 Asymmetric Logical Unit Assignment for Target Ports */
+	struct t10_alua		t10_alua;
+	/* T10 SPC-2 + SPC-3 Reservations */
+	struct t10_reservation	t10_pr;
+	struct se_dev_attrib	dev_attrib;
+	struct config_group	dev_group;
+	struct config_group	dev_pr_group;
+	struct se_dev_stat_grps dev_stat_grps;
+#define SE_DEV_ALIAS_LEN 512		/* must be less than PAGE_SIZE */
+	unsigned char		dev_alias[SE_DEV_ALIAS_LEN];
+#define SE_UDEV_PATH_LEN 512		/* must be less than PAGE_SIZE */
+	unsigned char		udev_path[SE_UDEV_PATH_LEN];
 	/* Pointer to template of function pointers for transport */
 	struct se_subsystem_api *transport;
 	/* Linked list for struct se_hba struct se_device list */
@@ -803,8 +707,6 @@ struct se_hba {
 	u32			hba_index;
 	/* Pointer to transport specific host structure. */
 	void			*hba_ptr;
-	/* Linked list for struct se_device */
-	struct list_head	hba_dev_list;
 	struct list_head	hba_node;
 	spinlock_t		device_lock;
 	struct config_group	hba_group;
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
index 81ddb4a..9087b20 100644
--- a/include/target/target_core_fabric.h
+++ b/include/target/target_core_fabric.h
@@ -98,8 +98,8 @@ void	transport_deregister_session(struct se_session *);
 
 void	transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *,
 		struct se_session *, u32, int, int, unsigned char *);
-int	transport_lookup_cmd_lun(struct se_cmd *, u32);
-int	target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *);
+sense_reason_t transport_lookup_cmd_lun(struct se_cmd *, u32);
+sense_reason_t target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *);
 int	target_submit_cmd_map_sgls(struct se_cmd *, struct se_session *,
 		unsigned char *, unsigned char *, u32, u32, int, int, int,
 		struct scatterlist *, u32, struct scatterlist *, u32);
@@ -110,9 +110,7 @@ int	target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
 		void *fabric_tmr_ptr, unsigned char tm_type,
 		gfp_t, unsigned int, int);
 int	transport_handle_cdb_direct(struct se_cmd *);
-int	transport_generic_map_mem_to_cmd(struct se_cmd *cmd,
-		struct scatterlist *, u32, struct scatterlist *, u32);
-int	transport_generic_new_cmd(struct se_cmd *);
+sense_reason_t	transport_generic_new_cmd(struct se_cmd *);
 
 void	target_execute_cmd(struct se_cmd *cmd);
 
@@ -120,7 +118,8 @@ void	transport_generic_free_cmd(struct se_cmd *, int);
 
 bool	transport_wait_for_tasks(struct se_cmd *);
 int	transport_check_aborted_status(struct se_cmd *, int);
-int	transport_send_check_condition_and_sense(struct se_cmd *, u8, int);
+int	transport_send_check_condition_and_sense(struct se_cmd *,
+		sense_reason_t, int);
 
 int	target_put_sess_cmd(struct se_session *, struct se_cmd *);
 void	target_sess_cmd_list_set_waiting(struct se_session *);
@@ -131,7 +130,7 @@ int	core_alua_check_nonop_delay(struct se_cmd *);
 int	core_tmr_alloc_req(struct se_cmd *, void *, u8, gfp_t);
 void	core_tmr_release_req(struct se_tmr_req *);
 int	transport_generic_handle_tmr(struct se_cmd *);
-void	transport_generic_request_failure(struct se_cmd *);
+void	transport_generic_request_failure(struct se_cmd *, sense_reason_t);
 int	transport_lookup_tmr_lun(struct se_cmd *, u32);
 
 struct se_node_acl *core_tpg_check_initiator_node_acl(struct se_portal_group *,
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index d49b285..f6372b0 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -15,6 +15,7 @@ struct ext4_inode_info;
 struct mpage_da_data;
 struct ext4_map_blocks;
 struct ext4_extent;
+struct extent_status;
 
 #define EXT4_I(inode) (container_of(inode, struct ext4_inode_info, vfs_inode))
 
@@ -1519,10 +1520,9 @@ DEFINE_EVENT(ext4__map_blocks_enter, ext4_ind_map_blocks_enter,
 );
 
 DECLARE_EVENT_CLASS(ext4__map_blocks_exit,
-	TP_PROTO(struct inode *inode, ext4_lblk_t lblk,
-		 ext4_fsblk_t pblk, unsigned int len, int ret),
+	TP_PROTO(struct inode *inode, struct ext4_map_blocks *map, int ret),
 
-	TP_ARGS(inode, lblk, pblk, len, ret),
+	TP_ARGS(inode, map, ret),
 
 	TP_STRUCT__entry(
 		__field(	dev_t,		dev		)
@@ -1530,37 +1530,37 @@ DECLARE_EVENT_CLASS(ext4__map_blocks_exit,
 		__field(	ext4_fsblk_t,	pblk		)
 		__field(	ext4_lblk_t,	lblk		)
 		__field(	unsigned int,	len		)
+		__field(	unsigned int,	flags		)
 		__field(	int,		ret		)
 	),
 
 	TP_fast_assign(
 		__entry->dev    = inode->i_sb->s_dev;
 		__entry->ino    = inode->i_ino;
-		__entry->pblk	= pblk;
-		__entry->lblk	= lblk;
-		__entry->len	= len;
+		__entry->pblk	= map->m_pblk;
+		__entry->lblk	= map->m_lblk;
+		__entry->len	= map->m_len;
+		__entry->flags	= map->m_flags;
 		__entry->ret	= ret;
 	),
 
-	TP_printk("dev %d,%d ino %lu lblk %u pblk %llu len %u ret %d",
+	TP_printk("dev %d,%d ino %lu lblk %u pblk %llu len %u flags %x ret %d",
 		  MAJOR(__entry->dev), MINOR(__entry->dev),
 		  (unsigned long) __entry->ino,
 		  __entry->lblk, __entry->pblk,
-		  __entry->len, __entry->ret)
+		  __entry->len, __entry->flags, __entry->ret)
 );
 
 DEFINE_EVENT(ext4__map_blocks_exit, ext4_ext_map_blocks_exit,
-	TP_PROTO(struct inode *inode, ext4_lblk_t lblk,
-		 ext4_fsblk_t pblk, unsigned len, int ret),
+	TP_PROTO(struct inode *inode, struct ext4_map_blocks *map, int ret),
 
-	TP_ARGS(inode, lblk, pblk, len, ret)
+	TP_ARGS(inode, map, ret)
 );
 
 DEFINE_EVENT(ext4__map_blocks_exit, ext4_ind_map_blocks_exit,
-	TP_PROTO(struct inode *inode, ext4_lblk_t lblk,
-		 ext4_fsblk_t pblk, unsigned len, int ret),
+	TP_PROTO(struct inode *inode, struct ext4_map_blocks *map, int ret),
 
-	TP_ARGS(inode, lblk, pblk, len, ret)
+	TP_ARGS(inode, map, ret)
 );
 
 TRACE_EVENT(ext4_ext_load_extent,
@@ -1680,10 +1680,10 @@ DEFINE_EVENT(ext4__trim, ext4_trim_all_free,
 );
 
 TRACE_EVENT(ext4_ext_handle_uninitialized_extents,
-	TP_PROTO(struct inode *inode, struct ext4_map_blocks *map,
+	TP_PROTO(struct inode *inode, struct ext4_map_blocks *map, int flags,
 		 unsigned int allocated, ext4_fsblk_t newblock),
 
-	TP_ARGS(inode, map, allocated, newblock),
+	TP_ARGS(inode, map, flags, allocated, newblock),
 
 	TP_STRUCT__entry(
 		__field(	dev_t,		dev		)
@@ -1699,7 +1699,7 @@ TRACE_EVENT(ext4_ext_handle_uninitialized_extents,
 	TP_fast_assign(
 		__entry->dev		= inode->i_sb->s_dev;
 		__entry->ino		= inode->i_ino;
-		__entry->flags		= map->m_flags;
+		__entry->flags		= flags;
 		__entry->lblk		= map->m_lblk;
 		__entry->pblk		= map->m_pblk;
 		__entry->len		= map->m_len;
@@ -1707,7 +1707,7 @@ TRACE_EVENT(ext4_ext_handle_uninitialized_extents,
 		__entry->newblk		= newblock;
 	),
 
-	TP_printk("dev %d,%d ino %lu m_lblk %u m_pblk %llu m_len %u flags %d"
+	TP_printk("dev %d,%d ino %lu m_lblk %u m_pblk %llu m_len %u flags %x "
 		  "allocated %d newblock %llu",
 		  MAJOR(__entry->dev), MINOR(__entry->dev),
 		  (unsigned long) __entry->ino,
@@ -2055,6 +2055,106 @@ TRACE_EVENT(ext4_ext_remove_space_done,
 		  (unsigned short) __entry->eh_entries)
 );
 
+TRACE_EVENT(ext4_es_insert_extent,
+	TP_PROTO(struct inode *inode, ext4_lblk_t start, ext4_lblk_t len),
+
+	TP_ARGS(inode, start, len),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	loff_t,	start			)
+		__field(	loff_t, len			)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->start	= start;
+		__entry->len	= len;
+	),
+
+	TP_printk("dev %d,%d ino %lu es [%lld/%lld)",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  __entry->start, __entry->len)
+);
+
+TRACE_EVENT(ext4_es_remove_extent,
+	TP_PROTO(struct inode *inode, ext4_lblk_t start, ext4_lblk_t len),
+
+	TP_ARGS(inode, start, len),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	loff_t,	start			)
+		__field(	loff_t,	len			)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->start	= start;
+		__entry->len	= len;
+	),
+
+	TP_printk("dev %d,%d ino %lu es [%lld/%lld)",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  __entry->start, __entry->len)
+);
+
+TRACE_EVENT(ext4_es_find_extent_enter,
+	TP_PROTO(struct inode *inode, ext4_lblk_t start),
+
+	TP_ARGS(inode, start),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,		dev		)
+		__field(	ino_t,		ino		)
+		__field(	ext4_lblk_t,	start		)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->start	= start;
+	),
+
+	TP_printk("dev %d,%d ino %lu start %u",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino, __entry->start)
+);
+
+TRACE_EVENT(ext4_es_find_extent_exit,
+	TP_PROTO(struct inode *inode, struct extent_status *es,
+		 ext4_lblk_t ret),
+
+	TP_ARGS(inode, es, ret),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,		dev		)
+		__field(	ino_t,		ino		)
+		__field(	ext4_lblk_t,	start		)
+		__field(	ext4_lblk_t,	len		)
+		__field(	ext4_lblk_t,	ret		)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->start	= es->start;
+		__entry->len	= es->len;
+		__entry->ret	= ret;
+	),
+
+	TP_printk("dev %d,%d ino %lu es [%u/%u) ret %u",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  __entry->start, __entry->len, __entry->ret)
+);
+
 #endif /* _TRACE_EXT4_H */
 
 /* This part must be outside protection */
diff --git a/include/trace/events/filemap.h b/include/trace/events/filemap.h
new file mode 100644
index 0000000..2d36386
--- /dev/null
+++ b/include/trace/events/filemap.h
@@ -0,0 +1,79 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM filemap
+
+#if !defined(_TRACE_FILEMAP_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_FILEMAP_H
+
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+#include <linux/mm.h>
+#include <linux/memcontrol.h>
+#include <linux/device.h>
+#include <linux/kdev_t.h>
+
+TRACE_EVENT(mm_filemap_delete_from_page_cache,
+
+	TP_PROTO(struct page *page),
+
+	TP_ARGS(page),
+
+	TP_STRUCT__entry(
+		__field(struct page *, page)
+		__field(unsigned long, i_ino)
+		__field(unsigned long, index)
+		__field(dev_t, s_dev)
+	),
+
+	TP_fast_assign(
+		__entry->page = page;
+		__entry->i_ino = page->mapping->host->i_ino;
+		__entry->index = page->index;
+		if (page->mapping->host->i_sb)
+			__entry->s_dev = page->mapping->host->i_sb->s_dev;
+		else
+			__entry->s_dev = page->mapping->host->i_rdev;
+	),
+
+	TP_printk("dev %d:%d ino %lx page=%p pfn=%lu ofs=%lu",
+		MAJOR(__entry->s_dev), MINOR(__entry->s_dev),
+		__entry->i_ino,
+		__entry->page,
+		page_to_pfn(__entry->page),
+		__entry->index << PAGE_SHIFT)
+);
+
+TRACE_EVENT(mm_filemap_add_to_page_cache,
+
+	TP_PROTO(struct page *page),
+
+	TP_ARGS(page),
+
+	TP_STRUCT__entry(
+		__field(struct page *, page)
+		__field(unsigned long, i_ino)
+		__field(unsigned long, index)
+		__field(dev_t, s_dev)
+	),
+
+	TP_fast_assign(
+		__entry->page = page;
+		__entry->i_ino = page->mapping->host->i_ino;
+		__entry->index = page->index;
+		if (page->mapping->host->i_sb)
+			__entry->s_dev = page->mapping->host->i_sb->s_dev;
+		else
+			__entry->s_dev = page->mapping->host->i_rdev;
+	),
+
+	TP_printk("dev %d:%d ino %lx page=%p pfn=%lu ofs=%lu",
+		MAJOR(__entry->s_dev), MINOR(__entry->s_dev),
+		__entry->i_ino,
+		__entry->page,
+		page_to_pfn(__entry->page),
+		__entry->index << PAGE_SHIFT)
+);
+
+#endif /* _TRACE_FILEMAP_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/gfpflags.h b/include/trace/events/gfpflags.h
index 9391706..3ee8313 100644
--- a/include/trace/events/gfpflags.h
+++ b/include/trace/events/gfpflags.h
@@ -34,6 +34,7 @@
 	{(unsigned long)__GFP_HARDWALL,		"GFP_HARDWALL"},	\
 	{(unsigned long)__GFP_THISNODE,		"GFP_THISNODE"},	\
 	{(unsigned long)__GFP_RECLAIMABLE,	"GFP_RECLAIMABLE"},	\
+	{(unsigned long)__GFP_KMEMCG,		"GFP_KMEMCG"},		\
 	{(unsigned long)__GFP_MOVABLE,		"GFP_MOVABLE"},		\
 	{(unsigned long)__GFP_NOTRACK,		"GFP_NOTRACK"},		\
 	{(unsigned long)__GFP_OTHER_NODE,	"GFP_OTHER_NODE"}	\
diff --git a/include/trace/events/oom.h b/include/trace/events/oom.h
index dd4ba3b..1e97498 100644
--- a/include/trace/events/oom.h
+++ b/include/trace/events/oom.h
@@ -14,7 +14,7 @@ TRACE_EVENT(oom_score_adj_update,
 	TP_STRUCT__entry(
 		__field(	pid_t,	pid)
 		__array(	char,	comm,	TASK_COMM_LEN )
-		__field(	 int,	oom_score_adj)
+		__field(	short,	oom_score_adj)
 	),
 
 	TP_fast_assign(
@@ -23,7 +23,7 @@ TRACE_EVENT(oom_score_adj_update,
 		__entry->oom_score_adj = task->signal->oom_score_adj;
 	),
 
-	TP_printk("pid=%d comm=%s oom_score_adj=%d",
+	TP_printk("pid=%d comm=%s oom_score_adj=%hd",
 		__entry->pid, __entry->comm, __entry->oom_score_adj)
 );
 
diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h
index 5bde94d..d4f559b 100644
--- a/include/trace/events/rcu.h
+++ b/include/trace/events/rcu.h
@@ -549,6 +549,7 @@ TRACE_EVENT(rcu_torture_read,
  *	"EarlyExit": rcu_barrier_callback() piggybacked, thus early exit.
  *	"Inc1": rcu_barrier_callback() piggyback check counter incremented.
  *	"Offline": rcu_barrier_callback() found offline CPU
+ *	"OnlineNoCB": rcu_barrier_callback() found online no-CBs CPU.
  *	"OnlineQ": rcu_barrier_callback() found online CPU with callbacks.
  *	"OnlineNQ": rcu_barrier_callback() found online CPU, no callbacks.
  *	"IRQ": An rcu_barrier_callback() callback posted on remote CPU.
diff --git a/include/trace/events/task.h b/include/trace/events/task.h
index b53add0..102a646 100644
--- a/include/trace/events/task.h
+++ b/include/trace/events/task.h
@@ -15,7 +15,7 @@ TRACE_EVENT(task_newtask,
 		__field(	pid_t,	pid)
 		__array(	char,	comm, TASK_COMM_LEN)
 		__field( unsigned long, clone_flags)
-		__field(	int,    oom_score_adj)
+		__field(	short,	oom_score_adj)
 	),
 
 	TP_fast_assign(
@@ -25,7 +25,7 @@ TRACE_EVENT(task_newtask,
 		__entry->oom_score_adj = task->signal->oom_score_adj;
 	),
 
-	TP_printk("pid=%d comm=%s clone_flags=%lx oom_score_adj=%d",
+	TP_printk("pid=%d comm=%s clone_flags=%lx oom_score_adj=%hd",
 		__entry->pid, __entry->comm,
 		__entry->clone_flags, __entry->oom_score_adj)
 );
@@ -40,7 +40,7 @@ TRACE_EVENT(task_rename,
 		__field(	pid_t,	pid)
 		__array(	char, oldcomm,  TASK_COMM_LEN)
 		__array(	char, newcomm,  TASK_COMM_LEN)
-		__field(	int, oom_score_adj)
+		__field(	short,	oom_score_adj)
 	),
 
 	TP_fast_assign(
@@ -50,7 +50,7 @@ TRACE_EVENT(task_rename,
 		__entry->oom_score_adj = task->signal->oom_score_adj;
 	),
 
-	TP_printk("pid=%d oldcomm=%s newcomm=%s oom_score_adj=%d",
+	TP_printk("pid=%d oldcomm=%s newcomm=%s oom_score_adj=%hd",
 		__entry->pid, __entry->oldcomm,
 		__entry->newcomm, __entry->oom_score_adj)
 );
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index a763888..40dc5e8 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -545,8 +545,7 @@ ftrace_raw_event_##call(void *__data, proto)				\
 	{ assign; }							\
 									\
 	if (!filter_current_check_discard(buffer, event_call, entry, event)) \
-		trace_nowake_buffer_unlock_commit(buffer,		\
-						  event, irq_flags, pc); \
+		trace_buffer_unlock_commit(buffer, event, irq_flags, pc); \
 }
 /*
  * The ftrace_test_probe is compiled out, it is only here as a build time check
@@ -620,79 +619,6 @@ __attribute__((section("_ftrace_events"))) *__event_##call = &event_##call
 
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
-/*
- * Define the insertion callback to perf events
- *
- * The job is very similar to ftrace_raw_event_<call> except that we don't
- * insert in the ring buffer but in a perf counter.
- *
- * static void ftrace_perf_<call>(proto)
- * {
- *	struct ftrace_data_offsets_<call> __maybe_unused __data_offsets;
- *	struct ftrace_event_call *event_call = &event_<call>;
- *	extern void perf_tp_event(int, u64, u64, void *, int);
- *	struct ftrace_raw_##call *entry;
- *	struct perf_trace_buf *trace_buf;
- *	u64 __addr = 0, __count = 1;
- *	unsigned long irq_flags;
- *	struct trace_entry *ent;
- *	int __entry_size;
- *	int __data_size;
- *	int __cpu
- *	int pc;
- *
- *	pc = preempt_count();
- *
- *	__data_size = ftrace_get_offsets_<call>(&__data_offsets, args);
- *
- *	// Below we want to get the aligned size by taking into account
- *	// the u32 field that will later store the buffer size
- *	__entry_size = ALIGN(__data_size + sizeof(*entry) + sizeof(u32),
- *			     sizeof(u64));
- *	__entry_size -= sizeof(u32);
- *
- *	// Protect the non nmi buffer
- *	// This also protects the rcu read side
- *	local_irq_save(irq_flags);
- *	__cpu = smp_processor_id();
- *
- *	if (in_nmi())
- *		trace_buf = rcu_dereference_sched(perf_trace_buf_nmi);
- *	else
- *		trace_buf = rcu_dereference_sched(perf_trace_buf);
- *
- *	if (!trace_buf)
- *		goto end;
- *
- *	trace_buf = per_cpu_ptr(trace_buf, __cpu);
- *
- * 	// Avoid recursion from perf that could mess up the buffer
- * 	if (trace_buf->recursion++)
- *		goto end_recursion;
- *
- * 	raw_data = trace_buf->buf;
- *
- *	// Make recursion update visible before entering perf_tp_event
- *	// so that we protect from perf recursions.
- *
- *	barrier();
- *
- *	//zero dead bytes from alignment to avoid stack leak to userspace:
- *	*(u64 *)(&raw_data[__entry_size - sizeof(u64)]) = 0ULL;
- *	entry = (struct ftrace_raw_<call> *)raw_data;
- *	ent = &entry->ent;
- *	tracing_generic_entry_update(ent, irq_flags, pc);
- *	ent->type = event_call->id;
- *
- *	<tstruct> <- do some jobs with dynamic arrays
- *
- *	<assign>  <- affect our values
- *
- *	perf_tp_event(event_call->id, __addr, __count, entry,
- *		     __entry_size);  <- submit them to perf counter
- *
- * }
- */
 
 #ifdef CONFIG_PERF_EVENTS
 
diff --git a/include/trace/syscall.h b/include/trace/syscall.h
index 31966a4..84bc419 100644
--- a/include/trace/syscall.h
+++ b/include/trace/syscall.h
@@ -31,27 +31,4 @@ struct syscall_metadata {
 	struct ftrace_event_call *exit_event;
 };
 
-#ifdef CONFIG_FTRACE_SYSCALLS
-extern unsigned long arch_syscall_addr(int nr);
-extern int init_syscall_trace(struct ftrace_event_call *call);
-
-extern int reg_event_syscall_enter(struct ftrace_event_call *call);
-extern void unreg_event_syscall_enter(struct ftrace_event_call *call);
-extern int reg_event_syscall_exit(struct ftrace_event_call *call);
-extern void unreg_event_syscall_exit(struct ftrace_event_call *call);
-extern int
-ftrace_format_syscall(struct ftrace_event_call *call, struct trace_seq *s);
-enum print_line_t print_syscall_enter(struct trace_iterator *iter, int flags,
-				      struct trace_event *event);
-enum print_line_t print_syscall_exit(struct trace_iterator *iter, int flags,
-				     struct trace_event *event);
-#endif
-
-#ifdef CONFIG_PERF_EVENTS
-int perf_sysenter_enable(struct ftrace_event_call *call);
-void perf_sysenter_disable(struct ftrace_event_call *call);
-int perf_sysexit_enable(struct ftrace_event_call *call);
-void perf_sysexit_disable(struct ftrace_event_call *call);
-#endif
-
 #endif /* _TRACE_SYSCALL_H */
diff --git a/include/uapi/asm-generic/ioctls.h b/include/uapi/asm-generic/ioctls.h
index 199975f..143dacb 100644
--- a/include/uapi/asm-generic/ioctls.h
+++ b/include/uapi/asm-generic/ioctls.h
@@ -74,6 +74,9 @@
 #define TCSETXW		0x5435
 #define TIOCSIG		_IOW('T', 0x36, int)  /* pty: generate signal */
 #define TIOCVHANGUP	0x5437
+#define TIOCGPKT	_IOR('T', 0x38, int) /* Get packet mode state */
+#define TIOCGPTLCK	_IOR('T', 0x39, int) /* Get Pty lock state */
+#define TIOCGEXCL	_IOR('T', 0x40, int) /* Get exclusive mode state */
 
 #define FIONCLEX	0x5450
 #define FIOCLEX		0x5451
diff --git a/include/uapi/asm-generic/mman-common.h b/include/uapi/asm-generic/mman-common.h
index d030d2c..4164529 100644
--- a/include/uapi/asm-generic/mman-common.h
+++ b/include/uapi/asm-generic/mman-common.h
@@ -55,4 +55,15 @@
 /* compatibility flags */
 #define MAP_FILE	0
 
+/*
+ * When MAP_HUGETLB is set bits [26:31] encode the log2 of the huge page size.
+ * This gives us 6 bits, which is enough until someone invents 128 bit address
+ * spaces.
+ *
+ * Assume these are all power of twos.
+ * When 0 use the default page size.
+ */
+#define MAP_HUGE_SHIFT	26
+#define MAP_HUGE_MASK	0x3f
+
 #endif /* __ASM_GENERIC_MMAN_COMMON_H */
diff --git a/include/uapi/asm-generic/mman.h b/include/uapi/asm-generic/mman.h
index 32c8bd6..e9fe6fd 100644
--- a/include/uapi/asm-generic/mman.h
+++ b/include/uapi/asm-generic/mman.h
@@ -13,6 +13,8 @@
 #define MAP_STACK	0x20000		/* give out an address that is best suited for process/thread stacks */
 #define MAP_HUGETLB	0x40000		/* create a huge page mapping */
 
+/* Bits [26:31] are reserved, see mman-common.h for MAP_HUGETLB usage */
+
 #define MCL_CURRENT	1		/* lock all current mappings */
 #define MCL_FUTURE	2		/* lock all future mappings */
 
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
index b1bea03..2d32d07 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h
@@ -43,6 +43,7 @@
 /* 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
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 6e595ba..2c531f4 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -690,9 +690,11 @@ __SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \
           compat_sys_process_vm_writev)
 #define __NR_kcmp 272
 __SYSCALL(__NR_kcmp, sys_kcmp)
+#define __NR_finit_module 273
+__SYSCALL(__NR_finit_module, sys_finit_module)
 
 #undef __NR_syscalls
-#define __NR_syscalls 273
+#define __NR_syscalls 274
 
 /*
  * All syscalls below here should go away really,
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index 1e3481e..8d1e2bb 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -778,6 +778,7 @@ struct drm_event_vblank {
 #define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3
 #define DRM_CAP_DUMB_PREFER_SHADOW 0x4
 #define DRM_CAP_PRIME 0x5
+#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
 
 #define DRM_PRIME_CAP_IMPORT 0x1
 #define DRM_PRIME_CAP_EXPORT 0x2
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 4322b1e..b746a3c 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -306,6 +306,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_SEMAPHORES	 20
 #define I915_PARAM_HAS_PRIME_VMAP_FLUSH	 21
 #define I915_PARAM_RSVD_FOR_FUTURE_USE	 22
+#define I915_PARAM_HAS_SECURE_BATCHES	 23
 
 typedef struct drm_i915_getparam {
 	int param;
@@ -671,6 +672,11 @@ struct drm_i915_gem_execbuffer2 {
 /** Resets the SO write offset registers for transform feedback on gen7. */
 #define I915_EXEC_GEN7_SOL_RESET	(1<<8)
 
+/** Request a privileged ("secure") batch buffer. Note only available for
+ * DRM_ROOT_ONLY | DRM_MASTER processes.
+ */
+#define I915_EXEC_SECURE		(1<<9)
+
 #define I915_EXEC_CONTEXT_ID_MASK	(0xffffffff)
 #define i915_execbuffer2_set_context_id(eb2, context) \
 	(eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 76352ac..09a2d94 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -106,6 +106,7 @@
 #define AUDIT_MMAP		1323	/* Record showing descriptor and flags in mmap */
 #define AUDIT_NETFILTER_PKT	1324	/* Packets traversing netfilter chains */
 #define AUDIT_NETFILTER_CFG	1325	/* Netfilter chain modifications */
+#define AUDIT_SECCOMP		1326	/* Secure Computing event */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
diff --git a/include/uapi/linux/eventpoll.h b/include/uapi/linux/eventpoll.h
index 2c267bc..8c99ce7 100644
--- a/include/uapi/linux/eventpoll.h
+++ b/include/uapi/linux/eventpoll.h
@@ -25,6 +25,7 @@
 #define EPOLL_CTL_ADD 1
 #define EPOLL_CTL_DEL 2
 #define EPOLL_CTL_MOD 3
+#define EPOLL_CTL_DISABLE 4
 
 /*
  * Request the handling of system wakeup events so as to prevent system suspends
diff --git a/include/uapi/linux/filter.h b/include/uapi/linux/filter.h
index 3d79224..9cfde69 100644
--- a/include/uapi/linux/filter.h
+++ b/include/uapi/linux/filter.h
@@ -127,7 +127,9 @@ struct sock_fprog {	/* Required for SO_ATTACH_FILTER. */
 #define SKF_AD_RXHASH	32
 #define SKF_AD_CPU	36
 #define SKF_AD_ALU_XOR_X	40
-#define SKF_AD_MAX	44
+#define SKF_AD_VLAN_TAG	44
+#define SKF_AD_VLAN_TAG_PRESENT 48
+#define SKF_AD_MAX	52
 #define SKF_NET_OFF   (-0x100000)
 #define SKF_LL_OFF    (-0x200000)
 
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index d8c713e..5dc1fea 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -193,6 +193,7 @@ struct fuse_file_lock {
 #define FUSE_FLOCK_LOCKS	(1 << 10)
 #define FUSE_HAS_IOCTL_DIR	(1 << 11)
 #define FUSE_AUTO_INVAL_DATA	(1 << 12)
+#define FUSE_DO_READDIRPLUS	(1 << 13)
 
 /**
  * CUSE INIT request/reply flags
@@ -299,6 +300,7 @@ enum fuse_opcode {
 	FUSE_NOTIFY_REPLY  = 41,
 	FUSE_BATCH_FORGET  = 42,
 	FUSE_FALLOCATE     = 43,
+	FUSE_READDIRPLUS   = 44,
 
 	/* CUSE specific operations */
 	CUSE_INIT          = 4096,
@@ -630,6 +632,16 @@ struct fuse_dirent {
 #define FUSE_DIRENT_SIZE(d) \
 	FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
 
+struct fuse_direntplus {
+	struct fuse_entry_out entry_out;
+	struct fuse_dirent dirent;
+};
+
+#define FUSE_NAME_OFFSET_DIRENTPLUS \
+	offsetof(struct fuse_direntplus, dirent.name)
+#define FUSE_DIRENTPLUS_SIZE(d) \
+	FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET_DIRENTPLUS + (d)->dirent.namelen)
+
 struct fuse_notify_inval_inode_out {
 	__u64	ino;
 	__s64	off;
diff --git a/include/uapi/linux/hdlc/Kbuild b/include/uapi/linux/hdlc/Kbuild
index aafaa5a..8c1d2cb 100644
--- a/include/uapi/linux/hdlc/Kbuild
+++ b/include/uapi/linux/hdlc/Kbuild
@@ -1 +1,2 @@
 # UAPI Header export list
+header-y += ioctl.h
diff --git a/include/uapi/linux/hdlc/ioctl.h b/include/uapi/linux/hdlc/ioctl.h
new file mode 100644
index 0000000..04bc027
--- /dev/null
+++ b/include/uapi/linux/hdlc/ioctl.h
@@ -0,0 +1,84 @@
+#ifndef __HDLC_IOCTL_H__
+#define __HDLC_IOCTL_H__
+
+
+#define GENERIC_HDLC_VERSION 4	/* For synchronization with sethdlc utility */
+
+#define CLOCK_DEFAULT   0	/* Default setting */
+#define CLOCK_EXT	1	/* External TX and RX clock - DTE */
+#define CLOCK_INT	2	/* Internal TX and RX clock - DCE */
+#define CLOCK_TXINT	3	/* Internal TX and external RX clock */
+#define CLOCK_TXFROMRX	4	/* TX clock derived from external RX clock */
+
+
+#define ENCODING_DEFAULT	0 /* Default setting */
+#define ENCODING_NRZ		1
+#define ENCODING_NRZI		2
+#define ENCODING_FM_MARK	3
+#define ENCODING_FM_SPACE	4
+#define ENCODING_MANCHESTER	5
+
+
+#define PARITY_DEFAULT		0 /* Default setting */
+#define PARITY_NONE		1 /* No parity */
+#define PARITY_CRC16_PR0	2 /* CRC16, initial value 0x0000 */
+#define PARITY_CRC16_PR1	3 /* CRC16, initial value 0xFFFF */
+#define PARITY_CRC16_PR0_CCITT	4 /* CRC16, initial 0x0000, ITU-T version */
+#define PARITY_CRC16_PR1_CCITT	5 /* CRC16, initial 0xFFFF, ITU-T version */
+#define PARITY_CRC32_PR0_CCITT	6 /* CRC32, initial value 0x00000000 */
+#define PARITY_CRC32_PR1_CCITT	7 /* CRC32, initial value 0xFFFFFFFF */
+
+#define LMI_DEFAULT		0 /* Default setting */
+#define LMI_NONE		1 /* No LMI, all PVCs are static */
+#define LMI_ANSI		2 /* ANSI Annex D */
+#define LMI_CCITT		3 /* ITU-T Annex A */
+#define LMI_CISCO		4 /* The "original" LMI, aka Gang of Four */
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+	unsigned int clock_rate; /* bits per second */
+	unsigned int clock_type; /* internal, external, TX-internal etc. */
+	unsigned short loopback;
+} sync_serial_settings;          /* V.35, V.24, X.21 */
+
+typedef struct {
+	unsigned int clock_rate; /* bits per second */
+	unsigned int clock_type; /* internal, external, TX-internal etc. */
+	unsigned short loopback;
+	unsigned int slot_map;
+} te1_settings;                  /* T1, E1 */
+
+typedef struct {
+	unsigned short encoding;
+	unsigned short parity;
+} raw_hdlc_proto;
+
+typedef struct {
+	unsigned int t391;
+	unsigned int t392;
+	unsigned int n391;
+	unsigned int n392;
+	unsigned int n393;
+	unsigned short lmi;
+	unsigned short dce; /* 1 for DCE (network side) operation */
+} fr_proto;
+
+typedef struct {
+	unsigned int dlci;
+} fr_proto_pvc;          /* for creating/deleting FR PVCs */
+
+typedef struct {
+	unsigned int dlci;
+	char master[IFNAMSIZ];	/* Name of master FRAD device */
+}fr_proto_pvc_info;		/* for returning PVC information only */
+
+typedef struct {
+    unsigned int interval;
+    unsigned int timeout;
+} cisco_proto;
+
+/* PPP doesn't need any info now - supply length = 0 to ioctl */
+
+#endif /* __ASSEMBLY__ */
+#endif /* __HDLC_IOCTL_H__ */
diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
index a8fe954..b388579 100644
--- a/include/uapi/linux/if_bridge.h
+++ b/include/uapi/linux/if_bridge.h
@@ -97,5 +97,23 @@ struct __fdb_entry {
 	__u16 unused;
 };
 
+/* Bridge Flags */
+#define BRIDGE_FLAGS_MASTER	1	/* Bridge command to/from master */
+#define BRIDGE_FLAGS_SELF	2	/* Bridge command to/from lowerdev */
 
+#define BRIDGE_MODE_VEB		0	/* Default loopback mode */
+#define BRIDGE_MODE_VEPA	1	/* 802.1Qbg defined VEPA mode */
+
+/* Bridge management nested attributes
+ * [IFLA_AF_SPEC] = {
+ *     [IFLA_BRIDGE_FLAGS]
+ *     [IFLA_BRIDGE_MODE]
+ * }
+ */
+enum {
+	IFLA_BRIDGE_FLAGS,
+	IFLA_BRIDGE_MODE,
+	__IFLA_BRIDGE_MAX,
+};
+#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
 #endif /* _UAPI_LINUX_IF_BRIDGE_H */
diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
index 0343e1f..67fb87c 100644
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -48,6 +48,7 @@
 #define	ETH_P_BPQ	0x08FF		/* G8BPQ AX.25 Ethernet Packet	[ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_IEEEPUP	0x0a00		/* Xerox IEEE802.3 PUP packet */
 #define ETH_P_IEEEPUPAT	0x0a01		/* Xerox IEEE802.3 PUP Addr Trans packet */
+#define ETH_P_BATMAN	0x4305		/* B.A.T.M.A.N.-Advanced packet [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_DEC       0x6000          /* DEC Assigned proto           */
 #define ETH_P_DNA_DL    0x6001          /* DEC DNA Dump/Load            */
 #define ETH_P_DNA_RC    0x6002          /* DEC DNA Remote Console       */
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 5c80cb1..bb58aeb 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -205,6 +205,23 @@ enum {
 
 #define IFLA_INET6_MAX	(__IFLA_INET6_MAX - 1)
 
+enum {
+	BRIDGE_MODE_UNSPEC,
+	BRIDGE_MODE_HAIRPIN,
+};
+
+enum {
+	IFLA_BRPORT_UNSPEC,
+	IFLA_BRPORT_STATE,	/* Spanning tree state     */
+	IFLA_BRPORT_PRIORITY,	/* "             priority  */
+	IFLA_BRPORT_COST,	/* "             cost      */
+	IFLA_BRPORT_MODE,	/* mode (hairpin)          */
+	IFLA_BRPORT_GUARD,	/* bpdu guard              */
+	IFLA_BRPORT_PROTECT,	/* root port protection    */
+	__IFLA_BRPORT_MAX
+};
+#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
+
 struct ifla_cacheinfo {
 	__u32	max_reasm_len;
 	__u32	tstamp;		/* ipv6InterfaceTable updated timestamp */
@@ -285,6 +302,10 @@ enum {
 	IFLA_VXLAN_AGEING,
 	IFLA_VXLAN_LIMIT,
 	IFLA_VXLAN_PORT_RANGE,
+	IFLA_VXLAN_PROXY,
+	IFLA_VXLAN_RSC,
+	IFLA_VXLAN_L2MISS,
+	IFLA_VXLAN_L3MISS,
 	__IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX	(__IFLA_VXLAN_MAX - 1)
diff --git a/include/uapi/linux/if_packet.h b/include/uapi/linux/if_packet.h
index f379929..f9a6037 100644
--- a/include/uapi/linux/if_packet.h
+++ b/include/uapi/linux/if_packet.h
@@ -50,6 +50,7 @@ struct sockaddr_ll {
 #define PACKET_TX_TIMESTAMP		16
 #define PACKET_TIMESTAMP		17
 #define PACKET_FANOUT			18
+#define PACKET_TX_HAS_OFF		19
 
 #define PACKET_FANOUT_HASH		0
 #define PACKET_FANOUT_LB		1
diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h
index 25a585c..958497a 100644
--- a/include/uapi/linux/if_tun.h
+++ b/include/uapi/linux/if_tun.h
@@ -34,6 +34,7 @@
 #define TUN_ONE_QUEUE	0x0080
 #define TUN_PERSIST 	0x0100	
 #define TUN_VNET_HDR 	0x0200
+#define TUN_TAP_MQ      0x0400
 
 /* Ioctl defines */
 #define TUNSETNOCSUM  _IOW('T', 200, int) 
@@ -53,6 +54,7 @@
 #define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog)
 #define TUNGETVNETHDRSZ _IOR('T', 215, int)
 #define TUNSETVNETHDRSZ _IOW('T', 216, int)
+#define TUNSETQUEUE  _IOW('T', 217, int)
 
 /* TUNSETIFF ifr flags */
 #define IFF_TUN		0x0001
@@ -61,6 +63,9 @@
 #define IFF_ONE_QUEUE	0x2000
 #define IFF_VNET_HDR	0x4000
 #define IFF_TUN_EXCL	0x8000
+#define IFF_MULTI_QUEUE 0x0100
+#define IFF_ATTACH_QUEUE 0x0200
+#define IFF_DETACH_QUEUE 0x0400
 
 /* Features for GSO (TUNSETOFFLOAD). */
 #define TUN_F_CSUM	0x01	/* You can hand me unchecksummed packets. */
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
index 5db5942..aee73d0 100644
--- a/include/uapi/linux/if_tunnel.h
+++ b/include/uapi/linux/if_tunnel.h
@@ -37,6 +37,26 @@ struct ip_tunnel_parm {
 	struct iphdr		iph;
 };
 
+enum {
+	IFLA_IPTUN_UNSPEC,
+	IFLA_IPTUN_LINK,
+	IFLA_IPTUN_LOCAL,
+	IFLA_IPTUN_REMOTE,
+	IFLA_IPTUN_TTL,
+	IFLA_IPTUN_TOS,
+	IFLA_IPTUN_ENCAP_LIMIT,
+	IFLA_IPTUN_FLOWINFO,
+	IFLA_IPTUN_FLAGS,
+	IFLA_IPTUN_PROTO,
+	IFLA_IPTUN_PMTUDISC,
+	IFLA_IPTUN_6RD_PREFIX,
+	IFLA_IPTUN_6RD_RELAY_PREFIX,
+	IFLA_IPTUN_6RD_PREFIXLEN,
+	IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
+	__IFLA_IPTUN_MAX,
+};
+#define IFLA_IPTUN_MAX	(__IFLA_IPTUN_MAX - 1)
+
 /* SIT-mode i_flags */
 #define	SIT_ISATAP	0x0001
 
diff --git a/include/uapi/linux/in6.h b/include/uapi/linux/in6.h
index 1e31599..f79c372 100644
--- a/include/uapi/linux/in6.h
+++ b/include/uapi/linux/in6.h
@@ -240,6 +240,7 @@ struct in6_flowlabel_req {
  *
  * IP6T_SO_GET_REVISION_MATCH	68
  * IP6T_SO_GET_REVISION_TARGET	69
+ * IP6T_SO_ORIGINAL_DST		80
  */
 
 /* RFC5014: Source address selection */
diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h
index 8c469af..bbde90f 100644
--- a/include/uapi/linux/inet_diag.h
+++ b/include/uapi/linux/inet_diag.h
@@ -109,9 +109,10 @@ enum {
 	INET_DIAG_TOS,
 	INET_DIAG_TCLASS,
 	INET_DIAG_SKMEMINFO,
+	INET_DIAG_SHUTDOWN,
 };
 
-#define INET_DIAG_MAX INET_DIAG_SKMEMINFO
+#define INET_DIAG_MAX INET_DIAG_SHUTDOWN
 
 
 /* INET_DIAG_MEM */
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index 5588285..935119c 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -851,6 +851,7 @@ struct input_keymap_entry {
 #define MSC_GESTURE		0x02
 #define MSC_RAW			0x03
 #define MSC_SCAN		0x04
+#define MSC_TIMESTAMP		0x05
 #define MSC_MAX			0x07
 #define MSC_CNT			(MSC_MAX+1)
 
diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h
index a6d7d1c..5a2991c 100644
--- a/include/uapi/linux/ipv6.h
+++ b/include/uapi/linux/ipv6.h
@@ -157,6 +157,7 @@ enum {
 	DEVCONF_DISABLE_IPV6,
 	DEVCONF_ACCEPT_DAD,
 	DEVCONF_FORCE_TLLAO,
+	DEVCONF_NDISC_NOTIFY,
 	DEVCONF_MAX
 };
 
diff --git a/include/uapi/linux/ipv6_route.h b/include/uapi/linux/ipv6_route.h
index 0459664..2be7bd1 100644
--- a/include/uapi/linux/ipv6_route.h
+++ b/include/uapi/linux/ipv6_route.h
@@ -55,4 +55,7 @@ struct in6_rtmsg {
 #define RTMSG_NEWROUTE		0x21
 #define RTMSG_DELROUTE		0x22
 
+#define IP6_RT_PRIO_USER	1024
+#define IP6_RT_PRIO_ADDRCONF	256
+
 #endif /* _UAPI_LINUX_IPV6_ROUTE_H */
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 0a6d6ba..e6e5d4b 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -167,10 +167,15 @@ struct kvm_pit_config {
 #define KVM_EXIT_OSI              18
 #define KVM_EXIT_PAPR_HCALL	  19
 #define KVM_EXIT_S390_UCONTROL	  20
+#define KVM_EXIT_WATCHDOG         21
 
 /* For KVM_EXIT_INTERNAL_ERROR */
-#define KVM_INTERNAL_ERROR_EMULATION 1
-#define KVM_INTERNAL_ERROR_SIMUL_EX 2
+/* Emulate instruction failed. */
+#define KVM_INTERNAL_ERROR_EMULATION	1
+/* Encounter unexpected simultaneous exceptions. */
+#define KVM_INTERNAL_ERROR_SIMUL_EX	2
+/* Encounter unexpected vm-exit due to delivery event. */
+#define KVM_INTERNAL_ERROR_DELIVERY_EV	3
 
 /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
 struct kvm_run {
@@ -477,6 +482,8 @@ struct kvm_ppc_smmu_info {
 	struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
 };
 
+#define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
+
 #define KVMIO 0xAE
 
 /* machine type bits, to be used as argument to KVM_CREATE_VM */
@@ -626,6 +633,8 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_READONLY_MEM 81
 #endif
 #define KVM_CAP_IRQFD_RESAMPLE 82
+#define KVM_CAP_PPC_BOOKE_WATCHDOG 83
+#define KVM_CAP_PPC_HTAB_FD 84
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -848,6 +857,11 @@ struct kvm_s390_ucas_mapping {
 #define KVM_PPC_GET_SMMU_INFO	  _IOR(KVMIO,  0xa6, struct kvm_ppc_smmu_info)
 /* Available with KVM_CAP_PPC_ALLOC_HTAB */
 #define KVM_PPC_ALLOCATE_HTAB	  _IOWR(KVMIO, 0xa7, __u32)
+#define KVM_CREATE_SPAPR_TCE	  _IOW(KVMIO,  0xa8, struct kvm_create_spapr_tce)
+/* Available with KVM_CAP_RMA */
+#define KVM_ALLOCATE_RMA	  _IOR(KVMIO,  0xa9, struct kvm_allocate_rma)
+/* Available with KVM_CAP_PPC_HTAB_FD */
+#define KVM_PPC_GET_HTAB_FD	  _IOW(KVMIO,  0xaa, struct kvm_get_htab_fd)
 
 /*
  * ioctls for vcpu fds
@@ -911,9 +925,6 @@ struct kvm_s390_ucas_mapping {
 /* Available with KVM_CAP_XCRS */
 #define KVM_GET_XCRS		  _IOR(KVMIO,  0xa6, struct kvm_xcrs)
 #define KVM_SET_XCRS		  _IOW(KVMIO,  0xa7, struct kvm_xcrs)
-#define KVM_CREATE_SPAPR_TCE	  _IOW(KVMIO,  0xa8, struct kvm_create_spapr_tce)
-/* Available with KVM_CAP_RMA */
-#define KVM_ALLOCATE_RMA	  _IOR(KVMIO,  0xa9, struct kvm_allocate_rma)
 /* Available with KVM_CAP_SW_TLB */
 #define KVM_DIRTY_TLB		  _IOW(KVMIO,  0xaa, struct kvm_dirty_tlb)
 /* Available with KVM_CAP_ONE_REG */
diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h
index e15192c..66353ff 100644
--- a/include/uapi/linux/magic.h
+++ b/include/uapi/linux/magic.h
@@ -23,6 +23,7 @@
 #define EXT4_SUPER_MAGIC	0xEF53
 #define BTRFS_SUPER_MAGIC	0x9123683E
 #define NILFS_SUPER_MAGIC	0x3434
+#define F2FS_SUPER_MAGIC	0xF2F52010
 #define HPFS_SUPER_MAGIC	0xf995e849
 #define ISOFS_SUPER_MAGIC	0x9660
 #define JFFS2_SUPER_MAGIC	0x72b6
diff --git a/include/uapi/linux/module.h b/include/uapi/linux/module.h
new file mode 100644
index 0000000..38da425
--- /dev/null
+++ b/include/uapi/linux/module.h
@@ -0,0 +1,8 @@
+#ifndef _UAPI_LINUX_MODULE_H
+#define _UAPI_LINUX_MODULE_H
+
+/* Flags for sys_finit_module: */
+#define MODULE_INIT_IGNORE_MODVERSIONS	1
+#define MODULE_INIT_IGNORE_VERMAGIC	2
+
+#endif /* _UAPI_LINUX_MODULE_H */
diff --git a/include/uapi/linux/msg.h b/include/uapi/linux/msg.h
index 78dbd2f..22d95c6 100644
--- a/include/uapi/linux/msg.h
+++ b/include/uapi/linux/msg.h
@@ -10,6 +10,7 @@
 /* msgrcv options */
 #define MSG_NOERROR     010000  /* no error if message is too big */
 #define MSG_EXCEPT      020000  /* recv any msg except of specified type.*/
+#define MSG_COPY        040000  /* copy (not remove) all queue messages */
 
 /* Obsolete, used only for backwards compatibility and libc5 compiles */
 struct msqid_ds {
diff --git a/include/uapi/linux/netconf.h b/include/uapi/linux/netconf.h
new file mode 100644
index 0000000..75dcbc5
--- /dev/null
+++ b/include/uapi/linux/netconf.h
@@ -0,0 +1,23 @@
+#ifndef _UAPI_LINUX_NETCONF_H_
+#define _UAPI_LINUX_NETCONF_H_
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+
+struct netconfmsg {
+	__u8	ncm_family;
+};
+
+enum {
+	NETCONFA_UNSPEC,
+	NETCONFA_IFINDEX,
+	NETCONFA_FORWARDING,
+	NETCONFA_RP_FILTER,
+	__NETCONFA_MAX
+};
+#define NETCONFA_MAX	(__NETCONFA_MAX - 1)
+
+#define NETCONFA_IFINDEX_ALL		-1
+#define NETCONFA_IFINDEX_DEFAULT	-2
+
+#endif /* _UAPI_LINUX_NETCONF_H_ */
diff --git a/include/uapi/linux/netfilter_ipv6/ip6_tables.h b/include/uapi/linux/netfilter_ipv6/ip6_tables.h
index bf1ef65..649c680 100644
--- a/include/uapi/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/uapi/linux/netfilter_ipv6/ip6_tables.h
@@ -178,6 +178,9 @@ struct ip6t_error {
 #define IP6T_SO_GET_REVISION_TARGET	(IP6T_BASE_CTL + 5)
 #define IP6T_SO_GET_MAX			IP6T_SO_GET_REVISION_TARGET
 
+/* obtain original address if REDIRECT'd connection */
+#define IP6T_SO_ORIGINAL_DST            80
+
 /* ICMP matching stuff */
 struct ip6t_icmp {
 	__u8 type;				/* type to match */
diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h
index d908d17..0e63cee 100644
--- a/include/uapi/linux/nfc.h
+++ b/include/uapi/linux/nfc.h
@@ -60,6 +60,13 @@
  *      target mode.
  * @NFC_EVENT_DEVICE_DEACTIVATED: event emitted when the adapter is deactivated
  *      from target mode.
+ * @NFC_CMD_LLC_GET_PARAMS: request LTO, RW, and MIUX parameters for a device
+ * @NFC_CMD_LLC_SET_PARAMS: set one or more of LTO, RW, and MIUX parameters for
+ *	a device. LTO must be set before the link is up otherwise -EINPROGRESS
+ *	is returned. RW and MIUX can be set at anytime and will be passed in
+ *	subsequent CONNECT and CC messages.
+ *	If one of the passed parameters is wrong none is set and -EINVAL is
+ *	returned.
  */
 enum nfc_commands {
 	NFC_CMD_UNSPEC,
@@ -77,6 +84,8 @@ enum nfc_commands {
 	NFC_EVENT_TARGET_LOST,
 	NFC_EVENT_TM_ACTIVATED,
 	NFC_EVENT_TM_DEACTIVATED,
+	NFC_CMD_LLC_GET_PARAMS,
+	NFC_CMD_LLC_SET_PARAMS,
 /* private: internal use only */
 	__NFC_CMD_AFTER_LAST
 };
@@ -102,6 +111,9 @@ enum nfc_commands {
  * @NFC_ATTR_RF_MODE: Initiator or target
  * @NFC_ATTR_IM_PROTOCOLS: Initiator mode protocols to poll for
  * @NFC_ATTR_TM_PROTOCOLS: Target mode protocols to listen for
+ * @NFC_ATTR_LLC_PARAM_LTO: Link TimeOut parameter
+ * @NFC_ATTR_LLC_PARAM_RW: Receive Window size parameter
+ * @NFC_ATTR_LLC_PARAM_MIUX: MIU eXtension parameter
  */
 enum nfc_attrs {
 	NFC_ATTR_UNSPEC,
@@ -119,6 +131,9 @@ enum nfc_attrs {
 	NFC_ATTR_DEVICE_POWERED,
 	NFC_ATTR_IM_PROTOCOLS,
 	NFC_ATTR_TM_PROTOCOLS,
+	NFC_ATTR_LLC_PARAM_LTO,
+	NFC_ATTR_LLC_PARAM_RW,
+	NFC_ATTR_LLC_PARAM_MIUX,
 /* private: internal use only */
 	__NFC_ATTR_AFTER_LAST
 };
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 7df9b50..33a4174 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -118,8 +118,9 @@
  *	to get a list of all present wiphys.
  * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or
  *	%NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME,
- *	%NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ,
- *	%NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT,
+ *	%NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ (and the
+ *	attributes determining the channel width; this is used for setting
+ *	monitor mode channel),  %NL80211_ATTR_WIPHY_RETRY_SHORT,
  *	%NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
  *	and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD.
  *	However, for setting the channel, see %NL80211_CMD_SET_CHANNEL
@@ -171,7 +172,7 @@
  *	%NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY,
  *	%NL80211_ATTR_AUTH_TYPE and %NL80211_ATTR_INACTIVITY_TIMEOUT.
  *	The channel to use can be set on the interface or be given using the
- *	%NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_WIPHY_CHANNEL_TYPE attrs.
+ *	%NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width.
  * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP
  * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface
  * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP
@@ -401,8 +402,7 @@
  *	a response while being associated to an AP on another channel.
  *	%NL80211_ATTR_IFINDEX is used to specify which interface (and thus
  *	radio) is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the
- *	frequency for the operation and %NL80211_ATTR_WIPHY_CHANNEL_TYPE may be
- *	optionally used to specify additional channel parameters.
+ *	frequency for the operation.
  *	%NL80211_ATTR_DURATION is used to specify the duration in milliseconds
  *	to remain on the channel. This command is also used as an event to
  *	notify when the requested duration starts (it may take a while for the
@@ -440,12 +440,11 @@
  *	as an event indicating reception of a frame that was not processed in
  *	kernel code, but is for us (i.e., which may need to be processed in a
  *	user space application). %NL80211_ATTR_FRAME is used to specify the
- *	frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and
- *	optionally %NL80211_ATTR_WIPHY_CHANNEL_TYPE) is used to indicate on
- *	which channel the frame is to be transmitted or was received. If this
- *	channel is not the current channel (remain-on-channel or the
- *	operational channel) the device will switch to the given channel and
- *	transmit the frame, optionally waiting for a response for the time
+ *	frame contents (including header). %NL80211_ATTR_WIPHY_FREQ is used
+ *	to indicate on which channel the frame is to be transmitted or was
+ *	received. If this channel is not the current channel (remain-on-channel
+ *	or the operational channel) the device will switch to the given channel
+ *	and transmit the frame, optionally waiting for a response for the time
  *	specified using %NL80211_ATTR_DURATION. When called, this operation
  *	returns a cookie (%NL80211_ATTR_COOKIE) that will be included with the
  *	TX status event pertaining to the TX request.
@@ -473,8 +472,8 @@
  *	command is used as an event to indicate the that a trigger level was
  *	reached.
  * @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ
- *	and %NL80211_ATTR_WIPHY_CHANNEL_TYPE) the given interface (identifed
- *	by %NL80211_ATTR_IFINDEX) shall operate on.
+ *	and the attributes determining channel width) the given interface
+ *	(identifed by %NL80211_ATTR_IFINDEX) shall operate on.
  *	In case multiple channels are supported by the device, the mechanism
  *	with which it switches channels is implementation-defined.
  *	When a monitor interface is given, it can only switch channel while
@@ -526,6 +525,12 @@
  *	of PMKSA caching dandidates.
  *
  * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup).
+ *	In addition, this can be used as an event to request userspace to take
+ *	actions on TDLS links (set up a new link or tear down an existing one).
+ *	In such events, %NL80211_ATTR_TDLS_OPERATION indicates the requested
+ *	operation, %NL80211_ATTR_MAC contains the peer MAC address, and
+ *	%NL80211_ATTR_REASON_CODE the reason code to be used (only with
+ *	%NL80211_TDLS_TEARDOWN).
  * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame.
  *
  * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP
@@ -562,8 +567,8 @@
  *
  * @NL80211_CMD_CH_SWITCH_NOTIFY: An AP or GO may decide to switch channels
  *	independently of the userspace SME, send this event indicating
- *	%NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ with
- *	%NL80211_ATTR_WIPHY_CHANNEL_TYPE.
+ *	%NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ and the
+ *	attributes determining channel width.
  *
  * @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by
  *	its %NL80211_ATTR_WDEV identifier. It must have been created with
@@ -578,6 +583,9 @@
  *	station, due to particular reason. %NL80211_ATTR_CONN_FAILED_REASON
  *	is used for this.
  *
+ * @NL80211_CMD_SET_MCAST_RATE: Change the rate used to send multicast frames
+ *	for IBSS or MESH vif.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -726,6 +734,8 @@ enum nl80211_commands {
 
 	NL80211_CMD_CONN_FAILED,
 
+	NL80211_CMD_SET_MCAST_RATE,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -762,14 +772,26 @@ enum nl80211_commands {
  *	/sys/class/ieee80211/<phyname>/index
  * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming)
  * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters
- * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz
+ * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz,
+ *	defines the channel together with the (deprecated)
+ *	%NL80211_ATTR_WIPHY_CHANNEL_TYPE attribute or the attributes
+ *	%NL80211_ATTR_CHANNEL_WIDTH and if needed %NL80211_ATTR_CENTER_FREQ1
+ *	and %NL80211_ATTR_CENTER_FREQ2
+ * @NL80211_ATTR_CHANNEL_WIDTH: u32 attribute containing one of the values
+ *	of &enum nl80211_chan_width, describing the channel width. See the
+ *	documentation of the enum for more information.
+ * @NL80211_ATTR_CENTER_FREQ1: Center frequency of the first part of the
+ *	channel, used for anything but 20 MHz bandwidth
+ * @NL80211_ATTR_CENTER_FREQ2: Center frequency of the second part of the
+ *	channel, used only for 80+80 MHz bandwidth
  * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ
- *	if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included):
+ *	if HT20 or HT40 are to be used (i.e., HT disabled if not included):
  *	NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including
  *		this attribute)
  *	NL80211_CHAN_HT20 = HT20 only
  *	NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel
  *	NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel
+ *	This attribute is now deprecated.
  * @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is
  *	less than or equal to the RTS threshold; allowed range: 1..255;
  *	dot11ShortRetryLimit; u8
@@ -1273,6 +1295,14 @@ enum nl80211_commands {
  *	the connection request from a station. nl80211_connect_failed_reason
  *	enum has different reasons of connection failure.
  *
+ * @NL80211_ATTR_SAE_DATA: SAE elements in Authentication frames. This starts
+ *	with the Authentication transaction sequence number field.
+ *
+ * @NL80211_ATTR_VHT_CAPABILITY: VHT Capability information element (from
+ *	association request when used with NL80211_CMD_NEW_STATION)
+ *
+ * @NL80211_ATTR_SCAN_FLAGS: scan request control flags (u32)
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1530,6 +1560,16 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_CONN_FAILED_REASON,
 
+	NL80211_ATTR_SAE_DATA,
+
+	NL80211_ATTR_VHT_CAPABILITY,
+
+	NL80211_ATTR_SCAN_FLAGS,
+
+	NL80211_ATTR_CHANNEL_WIDTH,
+	NL80211_ATTR_CENTER_FREQ1,
+	NL80211_ATTR_CENTER_FREQ2,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -1573,6 +1613,7 @@ enum nl80211_attrs {
 #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY	16
 #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY	24
 #define NL80211_HT_CAPABILITY_LEN		26
+#define NL80211_VHT_CAPABILITY_LEN		12
 
 #define NL80211_MAX_NR_CIPHER_SUITES		5
 #define NL80211_MAX_NR_AKM_SUITES		2
@@ -1693,10 +1734,15 @@ struct nl80211_sta_flag_update {
  * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
  * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
  * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
- * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 MHz dualchannel bitrate
  * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
  * @NL80211_RATE_INFO_BITRATE32: total bitrate (u32, 100kbit/s)
  * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined
+ * @NL80211_RATE_INFO_VHT_MCS: MCS index for VHT (u8)
+ * @NL80211_RATE_INFO_VHT_NSS: number of streams in VHT (u8)
+ * @NL80211_RATE_INFO_80_MHZ_WIDTH: 80 MHz VHT rate
+ * @NL80211_RATE_INFO_80P80_MHZ_WIDTH: 80+80 MHz VHT rate
+ * @NL80211_RATE_INFO_160_MHZ_WIDTH: 160 MHz VHT rate
  * @__NL80211_RATE_INFO_AFTER_LAST: internal use
  */
 enum nl80211_rate_info {
@@ -1706,6 +1752,11 @@ enum nl80211_rate_info {
 	NL80211_RATE_INFO_40_MHZ_WIDTH,
 	NL80211_RATE_INFO_SHORT_GI,
 	NL80211_RATE_INFO_BITRATE32,
+	NL80211_RATE_INFO_VHT_MCS,
+	NL80211_RATE_INFO_VHT_NSS,
+	NL80211_RATE_INFO_80_MHZ_WIDTH,
+	NL80211_RATE_INFO_80P80_MHZ_WIDTH,
+	NL80211_RATE_INFO_160_MHZ_WIDTH,
 
 	/* keep last */
 	__NL80211_RATE_INFO_AFTER_LAST,
@@ -2414,6 +2465,15 @@ enum nl80211_ac {
 #define NL80211_TXQ_Q_BE	NL80211_AC_BE
 #define NL80211_TXQ_Q_BK	NL80211_AC_BK
 
+/**
+ * enum nl80211_channel_type - channel type
+ * @NL80211_CHAN_NO_HT: 20 MHz, non-HT channel
+ * @NL80211_CHAN_HT20: 20 MHz HT channel
+ * @NL80211_CHAN_HT40MINUS: HT40 channel, secondary channel
+ *	below the control channel
+ * @NL80211_CHAN_HT40PLUS: HT40 channel, secondary channel
+ *	above the control channel
+ */
 enum nl80211_channel_type {
 	NL80211_CHAN_NO_HT,
 	NL80211_CHAN_HT20,
@@ -2422,6 +2482,32 @@ enum nl80211_channel_type {
 };
 
 /**
+ * enum nl80211_chan_width - channel width definitions
+ *
+ * These values are used with the %NL80211_ATTR_CHANNEL_WIDTH
+ * attribute.
+ *
+ * @NL80211_CHAN_WIDTH_20_NOHT: 20 MHz, non-HT channel
+ * @NL80211_CHAN_WIDTH_20: 20 MHz HT channel
+ * @NL80211_CHAN_WIDTH_40: 40 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
+ *	attribute must be provided as well
+ * @NL80211_CHAN_WIDTH_80: 80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
+ *	attribute must be provided as well
+ * @NL80211_CHAN_WIDTH_80P80: 80+80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
+ *	and %NL80211_ATTR_CENTER_FREQ2 attributes must be provided as well
+ * @NL80211_CHAN_WIDTH_160: 160 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
+ *	attribute must be provided as well
+ */
+enum nl80211_chan_width {
+	NL80211_CHAN_WIDTH_20_NOHT,
+	NL80211_CHAN_WIDTH_20,
+	NL80211_CHAN_WIDTH_40,
+	NL80211_CHAN_WIDTH_80,
+	NL80211_CHAN_WIDTH_80P80,
+	NL80211_CHAN_WIDTH_160,
+};
+
+/**
  * enum nl80211_bss - netlink attributes for a BSS
  *
  * @__NL80211_BSS_INVALID: invalid
@@ -2489,6 +2575,7 @@ enum nl80211_bss_status {
  * @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only)
  * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r)
  * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP)
+ * @NL80211_AUTHTYPE_SAE: Simultaneous authentication of equals
  * @__NL80211_AUTHTYPE_NUM: internal
  * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
  * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
@@ -2500,6 +2587,7 @@ enum nl80211_auth_type {
 	NL80211_AUTHTYPE_SHARED_KEY,
 	NL80211_AUTHTYPE_FT,
 	NL80211_AUTHTYPE_NETWORK_EAP,
+	NL80211_AUTHTYPE_SAE,
 
 	/* keep last */
 	__NL80211_AUTHTYPE_NUM,
@@ -3028,6 +3116,16 @@ enum nl80211_ap_sme_features {
  *	in the interface combinations, even when it's only used for scan
  *	and remain-on-channel. This could be due to, for example, the
  *	remain-on-channel implementation requiring a channel context.
+ * @NL80211_FEATURE_SAE: This driver supports simultaneous authentication of
+ *	equals (SAE) with user space SME (NL80211_CMD_AUTHENTICATE) in station
+ *	mode
+ * @NL80211_FEATURE_LOW_PRIORITY_SCAN: This driver supports low priority scan
+ * @NL80211_FEATURE_SCAN_FLUSH: Scan flush is supported
+ * @NL80211_FEATURE_AP_SCAN: Support scanning using an AP vif
+ * @NL80211_FEATURE_VIF_TXPOWER: The driver supports per-vif TX power setting
+ * @NL80211_FEATURE_NEED_OBSS_SCAN: The driver expects userspace to perform
+ *	OBSS scans and generate 20/40 BSS coex reports. This flag is used only
+ *	for drivers implementing the CONNECT API, for AUTH/ASSOC it is implied.
  */
 enum nl80211_feature_flags {
 	NL80211_FEATURE_SK_TX_STATUS			= 1 << 0,
@@ -3035,6 +3133,12 @@ enum nl80211_feature_flags {
 	NL80211_FEATURE_INACTIVITY_TIMER		= 1 << 2,
 	NL80211_FEATURE_CELL_BASE_REG_HINTS		= 1 << 3,
 	NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL	= 1 << 4,
+	NL80211_FEATURE_SAE				= 1 << 5,
+	NL80211_FEATURE_LOW_PRIORITY_SCAN		= 1 << 6,
+	NL80211_FEATURE_SCAN_FLUSH			= 1 << 7,
+	NL80211_FEATURE_AP_SCAN				= 1 << 8,
+	NL80211_FEATURE_VIF_TXPOWER			= 1 << 9,
+	NL80211_FEATURE_NEED_OBSS_SCAN			= 1 << 10,
 };
 
 /**
@@ -3069,4 +3173,25 @@ enum nl80211_connect_failed_reason {
 	NL80211_CONN_FAIL_BLOCKED_CLIENT,
 };
 
+/**
+ * enum nl80211_scan_flags -  scan request control flags
+ *
+ * Scan request control flags are used to control the handling
+ * of NL80211_CMD_TRIGGER_SCAN and NL80211_CMD_START_SCHED_SCAN
+ * requests.
+ *
+ * @NL80211_SCAN_FLAG_LOW_PRIORITY: scan request has low priority
+ * @NL80211_SCAN_FLAG_FLUSH: flush cache before scanning
+ * @NL80211_SCAN_FLAG_AP: force a scan even if the interface is configured
+ *	as AP and the beaconing has already been configured. This attribute is
+ *	dangerous because will destroy stations performance as a lot of frames
+ *	will be lost while scanning off-channel, therefore it must be used only
+ *	when really needed
+ */
+enum nl80211_scan_flags {
+	NL80211_SCAN_FLAG_LOW_PRIORITY			= 1<<0,
+	NL80211_SCAN_FLAG_FLUSH				= 1<<1,
+	NL80211_SCAN_FLAG_AP				= 1<<2,
+};
+
 #endif /* __LINUX_NL80211_H */
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index 20ae747..259763d 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -544,9 +544,9 @@
 #define  PCI_EXP_OBFF_WAKE_EN	0x6000	/* OBFF using WAKE# signaling */
 #define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2	44	/* v2 endpoints end here */
 #define PCI_EXP_LNKCAP2		44	/* Link Capability 2 */
-#define  PCI_EXP_LNKCAP2_SLS_2_5GB 0x01	/* Current Link Speed 2.5GT/s */
-#define  PCI_EXP_LNKCAP2_SLS_5_0GB 0x02	/* Current Link Speed 5.0GT/s */
-#define  PCI_EXP_LNKCAP2_SLS_8_0GB 0x04	/* Current Link Speed 8.0GT/s */
+#define  PCI_EXP_LNKCAP2_SLS_2_5GB 0x02	/* Supported Link Speed 2.5GT/s */
+#define  PCI_EXP_LNKCAP2_SLS_5_0GB 0x04	/* Supported Link Speed 5.0GT/s */
+#define  PCI_EXP_LNKCAP2_SLS_8_0GB 0x08	/* Supported Link Speed 8.0GT/s */
 #define  PCI_EXP_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */
 #define PCI_EXP_LNKCTL2		48	/* Link Control 2 */
 #define PCI_EXP_LNKSTA2		50	/* Link Status 2 */
diff --git a/include/uapi/linux/ptp_clock.h b/include/uapi/linux/ptp_clock.h
index 94e981f..b65c834 100644
--- a/include/uapi/linux/ptp_clock.h
+++ b/include/uapi/linux/ptp_clock.h
@@ -67,12 +67,26 @@ struct ptp_perout_request {
 	unsigned int rsv[4];          /* Reserved for future use. */
 };
 
+#define PTP_MAX_SAMPLES 25 /* Maximum allowed offset measurement samples. */
+
+struct ptp_sys_offset {
+	unsigned int n_samples; /* Desired number of measurements. */
+	unsigned int rsv[3];    /* Reserved for future use. */
+	/*
+	 * Array of interleaved system/phc time stamps. The kernel
+	 * will provide 2*n_samples + 1 time stamps, with the last
+	 * one as a system time stamp.
+	 */
+	struct ptp_clock_time ts[2 * PTP_MAX_SAMPLES + 1];
+};
+
 #define PTP_CLK_MAGIC '='
 
 #define PTP_CLOCK_GETCAPS  _IOR(PTP_CLK_MAGIC, 1, struct ptp_clock_caps)
 #define PTP_EXTTS_REQUEST  _IOW(PTP_CLK_MAGIC, 2, struct ptp_extts_request)
 #define PTP_PEROUT_REQUEST _IOW(PTP_CLK_MAGIC, 3, struct ptp_perout_request)
 #define PTP_ENABLE_PPS     _IOW(PTP_CLK_MAGIC, 4, int)
+#define PTP_SYS_OFFSET     _IOW(PTP_CLK_MAGIC, 5, struct ptp_sys_offset)
 
 struct ptp_extts_event {
 	struct ptp_clock_time t; /* Time event occured. */
diff --git a/include/uapi/linux/ptrace.h b/include/uapi/linux/ptrace.h
index 1ef6c05..022ab18 100644
--- a/include/uapi/linux/ptrace.h
+++ b/include/uapi/linux/ptrace.h
@@ -73,7 +73,10 @@
 #define PTRACE_O_TRACEEXIT	(1 << PTRACE_EVENT_EXIT)
 #define PTRACE_O_TRACESECCOMP	(1 << PTRACE_EVENT_SECCOMP)
 
-#define PTRACE_O_MASK		0x000000ff
+/* eventless options */
+#define PTRACE_O_EXITKILL	(1 << 20)
+
+#define PTRACE_O_MASK		(0x000000ff | PTRACE_O_EXITKILL)
 
 #include <asm/ptrace.h>
 
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index fcd768b..3dee071 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -120,6 +120,11 @@ enum {
 	RTM_SETDCB,
 #define RTM_SETDCB RTM_SETDCB
 
+	RTM_NEWNETCONF = 80,
+#define RTM_NEWNETCONF RTM_NEWNETCONF
+	RTM_GETNETCONF = 82,
+#define RTM_GETNETCONF RTM_GETNETCONF
+
 	__RTM_MAX,
 #define RTM_MAX		(((__RTM_MAX + 3) & ~3) - 1)
 };
@@ -587,6 +592,10 @@ enum rtnetlink_groups {
 #define RTNLGRP_PHONET_ROUTE	RTNLGRP_PHONET_ROUTE
 	RTNLGRP_DCB,
 #define RTNLGRP_DCB		RTNLGRP_DCB
+	RTNLGRP_IPV4_NETCONF,
+#define RTNLGRP_IPV4_NETCONF	RTNLGRP_IPV4_NETCONF
+	RTNLGRP_IPV6_NETCONF,
+#define RTNLGRP_IPV6_NETCONF	RTNLGRP_IPV6_NETCONF
 	__RTNLGRP_MAX
 };
 #define RTNLGRP_MAX	(__RTNLGRP_MAX - 1)
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 7e1ab20..78f99d9 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -49,7 +49,8 @@
 #define PORT_XR17D15X	21	/* Exar XR17D15x UART */
 #define PORT_LPC3220	22	/* NXP LPC32xx SoC "Standard" UART */
 #define PORT_8250_CIR	23	/* CIR infrared port, has its own driver */
-#define PORT_MAX_8250	23	/* max port ID */
+#define PORT_XR17V35X	24	/* Exar XR17V35x UARTs */
+#define PORT_MAX_8250	24	/* max port ID */
 
 /*
  * ARM specific type numbers.  These are not currently guaranteed
@@ -215,5 +216,7 @@
 /* Energy Micro efm32 SoC */
 #define PORT_EFMUART   100
 
+/* ARC (Synopsys) on-chip UART */
+#define PORT_ARC       101
 
 #endif /* _UAPILINUX_SERIAL_CORE_H */
diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h
index 5ed325e..e632260 100644
--- a/include/uapi/linux/serial_reg.h
+++ b/include/uapi/linux/serial_reg.h
@@ -367,5 +367,23 @@
 #define UART_OMAP_MDR1_CIR_MODE		0x06	/* CIR mode */
 #define UART_OMAP_MDR1_DISABLE		0x07	/* Disable (default state) */
 
+/*
+ * These are definitions for the Exar XR17V35X and XR17(C|D)15X
+ */
+#define UART_EXAR_8XMODE	0x88	/* 8X sampling rate select */
+#define UART_EXAR_SLEEP		0x8b	/* Sleep mode */
+#define UART_EXAR_DVID		0x8d	/* Device identification */
+
+#define UART_EXAR_FCTR		0x08	/* Feature Control Register */
+#define UART_FCTR_EXAR_IRDA	0x08	/* IrDa data encode select */
+#define UART_FCTR_EXAR_485	0x10	/* Auto 485 half duplex dir ctl */
+#define UART_FCTR_EXAR_TRGA	0x00	/* FIFO trigger table A */
+#define UART_FCTR_EXAR_TRGB	0x60	/* FIFO trigger table B */
+#define UART_FCTR_EXAR_TRGC	0x80	/* FIFO trigger table C */
+#define UART_FCTR_EXAR_TRGD	0xc0	/* FIFO trigger table D programmable */
+
+#define UART_EXAR_TXTRG		0x0a	/* Tx FIFO trigger level write-only */
+#define UART_EXAR_RXTRG		0x0b	/* Rx FIFO trigger level write-only */
+
 #endif /* _LINUX_SERIAL_REG_H */
 
diff --git a/include/uapi/linux/unix_diag.h b/include/uapi/linux/unix_diag.h
index b1d2bf1..b8a2494 100644
--- a/include/uapi/linux/unix_diag.h
+++ b/include/uapi/linux/unix_diag.h
@@ -37,6 +37,7 @@ enum {
 	UNIX_DIAG_ICONS,
 	UNIX_DIAG_RQLEN,
 	UNIX_DIAG_MEMINFO,
+	UNIX_DIAG_SHUTDOWN,
 
 	UNIX_DIAG_MAX,
 };
diff --git a/include/uapi/linux/usb/cdc.h b/include/uapi/linux/usb/cdc.h
index 81a9279..f35aa0a 100644
--- a/include/uapi/linux/usb/cdc.h
+++ b/include/uapi/linux/usb/cdc.h
@@ -19,6 +19,7 @@
 #define USB_CDC_SUBCLASS_OBEX			0x0b
 #define USB_CDC_SUBCLASS_EEM			0x0c
 #define USB_CDC_SUBCLASS_NCM			0x0d
+#define USB_CDC_SUBCLASS_MBIM			0x0e
 
 #define USB_CDC_PROTO_NONE			0
 
@@ -33,6 +34,7 @@
 #define USB_CDC_PROTO_EEM			7
 
 #define USB_CDC_NCM_PROTO_NTB			1
+#define USB_CDC_MBIM_PROTO_NTB			2
 
 /*-------------------------------------------------------------------------*/
 
@@ -53,6 +55,7 @@
 #define USB_CDC_DMM_TYPE		0x14
 #define USB_CDC_OBEX_TYPE		0x15
 #define USB_CDC_NCM_TYPE		0x1a
+#define USB_CDC_MBIM_TYPE		0x1b
 
 /* "Header Functional Descriptor" from CDC spec  5.2.3.1 */
 struct usb_cdc_header_desc {
@@ -187,6 +190,21 @@ struct usb_cdc_ncm_desc {
 	__le16	bcdNcmVersion;
 	__u8	bmNetworkCapabilities;
 } __attribute__ ((packed));
+
+/* "MBIM Control Model Functional Descriptor" */
+struct usb_cdc_mbim_desc {
+	__u8	bLength;
+	__u8	bDescriptorType;
+	__u8	bDescriptorSubType;
+
+	__le16	bcdMBIMVersion;
+	__le16  wMaxControlMessage;
+	__u8    bNumberFilters;
+	__u8    bMaxFilterSize;
+	__le16  wMaxSegmentSize;
+	__u8    bmNetworkCapabilities;
+} __attribute__ ((packed));
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -332,6 +350,11 @@ struct usb_cdc_ncm_nth32 {
 #define USB_CDC_NCM_NDP32_CRC_SIGN	0x316D636E /* ncm1 */
 #define USB_CDC_NCM_NDP32_NOCRC_SIGN	0x306D636E /* ncm0 */
 
+#define USB_CDC_MBIM_NDP16_IPS_SIGN     0x00535049 /* IPS<sessionID> : IPS0 for now */
+#define USB_CDC_MBIM_NDP32_IPS_SIGN     0x00737069 /* ips<sessionID> : ips0 for now */
+#define USB_CDC_MBIM_NDP16_DSS_SIGN     0x00535344 /* DSS<sessionID> */
+#define USB_CDC_MBIM_NDP32_DSS_SIGN     0x00737364 /* dss<sessionID> */
+
 /* 16-bit NCM Datagram Pointer Entry */
 struct usb_cdc_ncm_dpe16 {
 	__le16	wDatagramIndex;
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 57bfa59..3cf3e94 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -186,6 +186,7 @@ enum v4l2_memory {
 	V4L2_MEMORY_MMAP             = 1,
 	V4L2_MEMORY_USERPTR          = 2,
 	V4L2_MEMORY_OVERLAY          = 3,
+	V4L2_MEMORY_DMABUF           = 4,
 };
 
 /* see also http://vektor.theorem.ca/graphics/ycbcr/ */
@@ -602,6 +603,8 @@ struct v4l2_requestbuffers {
  *			should be passed to mmap() called on the video node)
  * @userptr:		when memory is V4L2_MEMORY_USERPTR, a userspace pointer
  *			pointing to this plane
+ * @fd:			when memory is V4L2_MEMORY_DMABUF, a userspace file
+ *			descriptor associated with this plane
  * @data_offset:	offset in the plane to the start of data; usually 0,
  *			unless there is a header in front of the data
  *
@@ -616,6 +619,7 @@ struct v4l2_plane {
 	union {
 		__u32		mem_offset;
 		unsigned long	userptr;
+		__s32		fd;
 	} m;
 	__u32			data_offset;
 	__u32			reserved[11];
@@ -640,6 +644,8 @@ struct v4l2_plane {
  *		(or a "cookie" that should be passed to mmap() as offset)
  * @userptr:	for non-multiplanar buffers with memory == V4L2_MEMORY_USERPTR;
  *		a userspace pointer pointing to this buffer
+ * @fd:		for non-multiplanar buffers with memory == V4L2_MEMORY_DMABUF;
+ *		a userspace file descriptor associated with this buffer
  * @planes:	for multiplanar buffers; userspace pointer to the array of plane
  *		info structs for this buffer
  * @length:	size in bytes of the buffer (NOT its payload) for single-plane
@@ -666,6 +672,7 @@ struct v4l2_buffer {
 		__u32           offset;
 		unsigned long   userptr;
 		struct v4l2_plane *planes;
+		__s32		fd;
 	} m;
 	__u32			length;
 	__u32			reserved2;
@@ -687,6 +694,33 @@ struct v4l2_buffer {
 #define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0800
 #define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x1000
 
+/**
+ * struct v4l2_exportbuffer - export of video buffer as DMABUF file descriptor
+ *
+ * @index:	id number of the buffer
+ * @type:	enum v4l2_buf_type; buffer type (type == *_MPLANE for
+ *		multiplanar buffers);
+ * @plane:	index of the plane to be exported, 0 for single plane queues
+ * @flags:	flags for newly created file, currently only O_CLOEXEC is
+ *		supported, refer to manual of open syscall for more details
+ * @fd:		file descriptor associated with DMABUF (set by driver)
+ *
+ * Contains data used for exporting a video buffer as DMABUF file descriptor.
+ * The buffer is identified by a 'cookie' returned by VIDIOC_QUERYBUF
+ * (identical to the cookie used to mmap() the buffer to userspace). All
+ * reserved fields must be set to zero. The field reserved0 is expected to
+ * become a structure 'type' allowing an alternative layout of the structure
+ * content. Therefore this field should not be used for any other extensions.
+ */
+struct v4l2_exportbuffer {
+	__u32		type; /* enum v4l2_buf_type */
+	__u32		index;
+	__u32		plane;
+	__u32		flags;
+	__s32		fd;
+	__u32		reserved[11];
+};
+
 /*
  *	O V E R L A Y   P R E V I E W
  */
@@ -737,7 +771,7 @@ struct v4l2_window {
 struct v4l2_captureparm {
 	__u32		   capability;	  /*  Supported modes */
 	__u32		   capturemode;	  /*  Current mode */
-	struct v4l2_fract  timeperframe;  /*  Time per frame in .1us units */
+	struct v4l2_fract  timeperframe;  /*  Time per frame in seconds */
 	__u32		   extendedmode;  /*  Driver-specific extensions */
 	__u32              readbuffers;   /*  # of buffers for read */
 	__u32		   reserved[4];
@@ -1888,6 +1922,7 @@ struct v4l2_create_buffers {
 #define VIDIOC_S_FBUF		 _IOW('V', 11, struct v4l2_framebuffer)
 #define VIDIOC_OVERLAY		 _IOW('V', 14, int)
 #define VIDIOC_QBUF		_IOWR('V', 15, struct v4l2_buffer)
+#define VIDIOC_EXPBUF		_IOWR('V', 16, struct v4l2_exportbuffer)
 #define VIDIOC_DQBUF		_IOWR('V', 17, struct v4l2_buffer)
 #define VIDIOC_STREAMON		 _IOW('V', 18, int)
 #define VIDIOC_STREAMOFF	 _IOW('V', 19, int)
diff --git a/include/uapi/linux/xattr.h b/include/uapi/linux/xattr.h
index 26607bd..e4629b9 100644
--- a/include/uapi/linux/xattr.h
+++ b/include/uapi/linux/xattr.h
@@ -15,19 +15,22 @@
 
 /* Namespaces */
 #define XATTR_OS2_PREFIX "os2."
-#define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1)
+#define XATTR_OS2_PREFIX_LEN (sizeof(XATTR_OS2_PREFIX) - 1)
+
+#define XATTR_MAC_OSX_PREFIX "osx."
+#define XATTR_MAC_OSX_PREFIX_LEN (sizeof(XATTR_MAC_OSX_PREFIX) - 1)
 
 #define XATTR_SECURITY_PREFIX	"security."
-#define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1)
+#define XATTR_SECURITY_PREFIX_LEN (sizeof(XATTR_SECURITY_PREFIX) - 1)
 
 #define XATTR_SYSTEM_PREFIX "system."
-#define XATTR_SYSTEM_PREFIX_LEN (sizeof (XATTR_SYSTEM_PREFIX) - 1)
+#define XATTR_SYSTEM_PREFIX_LEN (sizeof(XATTR_SYSTEM_PREFIX) - 1)
 
 #define XATTR_TRUSTED_PREFIX "trusted."
-#define XATTR_TRUSTED_PREFIX_LEN (sizeof (XATTR_TRUSTED_PREFIX) - 1)
+#define XATTR_TRUSTED_PREFIX_LEN (sizeof(XATTR_TRUSTED_PREFIX) - 1)
 
 #define XATTR_USER_PREFIX "user."
-#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1)
+#define XATTR_USER_PREFIX_LEN (sizeof(XATTR_USER_PREFIX) - 1)
 
 /* Security namespace */
 #define XATTR_EVM_SUFFIX "evm"
diff --git a/include/uapi/rdma/Kbuild b/include/uapi/rdma/Kbuild
index aafaa5a..687ae33 100644
--- a/include/uapi/rdma/Kbuild
+++ b/include/uapi/rdma/Kbuild
@@ -1 +1,7 @@
 # UAPI Header export list
+header-y += ib_user_cm.h
+header-y += ib_user_mad.h
+header-y += ib_user_sa.h
+header-y += ib_user_verbs.h
+header-y += rdma_netlink.h
+header-y += rdma_user_cm.h
diff --git a/include/uapi/rdma/ib_user_cm.h b/include/uapi/rdma/ib_user_cm.h
new file mode 100644
index 0000000..f79014a
--- /dev/null
+++ b/include/uapi/rdma/ib_user_cm.h
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef IB_USER_CM_H
+#define IB_USER_CM_H
+
+#include <linux/types.h>
+#include <rdma/ib_user_sa.h>
+
+#define IB_USER_CM_ABI_VERSION 5
+
+enum {
+	IB_USER_CM_CMD_CREATE_ID,
+	IB_USER_CM_CMD_DESTROY_ID,
+	IB_USER_CM_CMD_ATTR_ID,
+
+	IB_USER_CM_CMD_LISTEN,
+	IB_USER_CM_CMD_NOTIFY,
+
+	IB_USER_CM_CMD_SEND_REQ,
+	IB_USER_CM_CMD_SEND_REP,
+	IB_USER_CM_CMD_SEND_RTU,
+	IB_USER_CM_CMD_SEND_DREQ,
+	IB_USER_CM_CMD_SEND_DREP,
+	IB_USER_CM_CMD_SEND_REJ,
+	IB_USER_CM_CMD_SEND_MRA,
+	IB_USER_CM_CMD_SEND_LAP,
+	IB_USER_CM_CMD_SEND_APR,
+	IB_USER_CM_CMD_SEND_SIDR_REQ,
+	IB_USER_CM_CMD_SEND_SIDR_REP,
+
+	IB_USER_CM_CMD_EVENT,
+	IB_USER_CM_CMD_INIT_QP_ATTR,
+};
+/*
+ * command ABI structures.
+ */
+struct ib_ucm_cmd_hdr {
+	__u32 cmd;
+	__u16 in;
+	__u16 out;
+};
+
+struct ib_ucm_create_id {
+	__u64 uid;
+	__u64 response;
+};
+
+struct ib_ucm_create_id_resp {
+	__u32 id;
+};
+
+struct ib_ucm_destroy_id {
+	__u64 response;
+	__u32 id;
+	__u32 reserved;
+};
+
+struct ib_ucm_destroy_id_resp {
+	__u32 events_reported;
+};
+
+struct ib_ucm_attr_id {
+	__u64 response;
+	__u32 id;
+	__u32 reserved;
+};
+
+struct ib_ucm_attr_id_resp {
+	__be64 service_id;
+	__be64 service_mask;
+	__be32 local_id;
+	__be32 remote_id;
+};
+
+struct ib_ucm_init_qp_attr {
+	__u64 response;
+	__u32 id;
+	__u32 qp_state;
+};
+
+struct ib_ucm_listen {
+	__be64 service_id;
+	__be64 service_mask;
+	__u32 id;
+	__u32 reserved;
+};
+
+struct ib_ucm_notify {
+	__u32 id;
+	__u32 event;
+};
+
+struct ib_ucm_private_data {
+	__u64 data;
+	__u32 id;
+	__u8  len;
+	__u8  reserved[3];
+};
+
+struct ib_ucm_req {
+	__u32 id;
+	__u32 qpn;
+	__u32 qp_type;
+	__u32 psn;
+	__be64 sid;
+	__u64 data;
+	__u64 primary_path;
+	__u64 alternate_path;
+	__u8  len;
+	__u8  peer_to_peer;
+	__u8  responder_resources;
+	__u8  initiator_depth;
+	__u8  remote_cm_response_timeout;
+	__u8  flow_control;
+	__u8  local_cm_response_timeout;
+	__u8  retry_count;
+	__u8  rnr_retry_count;
+	__u8  max_cm_retries;
+	__u8  srq;
+	__u8  reserved[5];
+};
+
+struct ib_ucm_rep {
+	__u64 uid;
+	__u64 data;
+	__u32 id;
+	__u32 qpn;
+	__u32 psn;
+	__u8  len;
+	__u8  responder_resources;
+	__u8  initiator_depth;
+	__u8  target_ack_delay;
+	__u8  failover_accepted;
+	__u8  flow_control;
+	__u8  rnr_retry_count;
+	__u8  srq;
+	__u8  reserved[4];
+};
+
+struct ib_ucm_info {
+	__u32 id;
+	__u32 status;
+	__u64 info;
+	__u64 data;
+	__u8  info_len;
+	__u8  data_len;
+	__u8  reserved[6];
+};
+
+struct ib_ucm_mra {
+	__u64 data;
+	__u32 id;
+	__u8  len;
+	__u8  timeout;
+	__u8  reserved[2];
+};
+
+struct ib_ucm_lap {
+	__u64 path;
+	__u64 data;
+	__u32 id;
+	__u8  len;
+	__u8  reserved[3];
+};
+
+struct ib_ucm_sidr_req {
+	__u32 id;
+	__u32 timeout;
+	__be64 sid;
+	__u64 data;
+	__u64 path;
+	__u16 reserved_pkey;
+	__u8  len;
+	__u8  max_cm_retries;
+	__u8  reserved[4];
+};
+
+struct ib_ucm_sidr_rep {
+	__u32 id;
+	__u32 qpn;
+	__u32 qkey;
+	__u32 status;
+	__u64 info;
+	__u64 data;
+	__u8  info_len;
+	__u8  data_len;
+	__u8  reserved[6];
+};
+/*
+ * event notification ABI structures.
+ */
+struct ib_ucm_event_get {
+	__u64 response;
+	__u64 data;
+	__u64 info;
+	__u8  data_len;
+	__u8  info_len;
+	__u8  reserved[6];
+};
+
+struct ib_ucm_req_event_resp {
+	struct ib_user_path_rec primary_path;
+	struct ib_user_path_rec alternate_path;
+	__be64                 remote_ca_guid;
+	__u32                  remote_qkey;
+	__u32                  remote_qpn;
+	__u32                  qp_type;
+	__u32                  starting_psn;
+	__u8  responder_resources;
+	__u8  initiator_depth;
+	__u8  local_cm_response_timeout;
+	__u8  flow_control;
+	__u8  remote_cm_response_timeout;
+	__u8  retry_count;
+	__u8  rnr_retry_count;
+	__u8  srq;
+	__u8  port;
+	__u8  reserved[7];
+};
+
+struct ib_ucm_rep_event_resp {
+	__be64 remote_ca_guid;
+	__u32 remote_qkey;
+	__u32 remote_qpn;
+	__u32 starting_psn;
+	__u8  responder_resources;
+	__u8  initiator_depth;
+	__u8  target_ack_delay;
+	__u8  failover_accepted;
+	__u8  flow_control;
+	__u8  rnr_retry_count;
+	__u8  srq;
+	__u8  reserved[5];
+};
+
+struct ib_ucm_rej_event_resp {
+	__u32 reason;
+	/* ari in ib_ucm_event_get info field. */
+};
+
+struct ib_ucm_mra_event_resp {
+	__u8  timeout;
+	__u8  reserved[3];
+};
+
+struct ib_ucm_lap_event_resp {
+	struct ib_user_path_rec path;
+};
+
+struct ib_ucm_apr_event_resp {
+	__u32 status;
+	/* apr info in ib_ucm_event_get info field. */
+};
+
+struct ib_ucm_sidr_req_event_resp {
+	__u16 pkey;
+	__u8  port;
+	__u8  reserved;
+};
+
+struct ib_ucm_sidr_rep_event_resp {
+	__u32 status;
+	__u32 qkey;
+	__u32 qpn;
+	/* info in ib_ucm_event_get info field. */
+};
+
+#define IB_UCM_PRES_DATA      0x01
+#define IB_UCM_PRES_INFO      0x02
+#define IB_UCM_PRES_PRIMARY   0x04
+#define IB_UCM_PRES_ALTERNATE 0x08
+
+struct ib_ucm_event_resp {
+	__u64 uid;
+	__u32 id;
+	__u32 event;
+	__u32 present;
+	__u32 reserved;
+	union {
+		struct ib_ucm_req_event_resp req_resp;
+		struct ib_ucm_rep_event_resp rep_resp;
+		struct ib_ucm_rej_event_resp rej_resp;
+		struct ib_ucm_mra_event_resp mra_resp;
+		struct ib_ucm_lap_event_resp lap_resp;
+		struct ib_ucm_apr_event_resp apr_resp;
+
+		struct ib_ucm_sidr_req_event_resp sidr_req_resp;
+		struct ib_ucm_sidr_rep_event_resp sidr_rep_resp;
+
+		__u32                             send_status;
+	} u;
+};
+
+#endif /* IB_USER_CM_H */
diff --git a/include/uapi/rdma/ib_user_mad.h b/include/uapi/rdma/ib_user_mad.h
new file mode 100644
index 0000000..d6fce1c
--- /dev/null
+++ b/include/uapi/rdma/ib_user_mad.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef IB_USER_MAD_H
+#define IB_USER_MAD_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+/*
+ * Increment this value if any changes that break userspace ABI
+ * compatibility are made.
+ */
+#define IB_USER_MAD_ABI_VERSION	5
+
+/*
+ * Make sure that all structs defined in this file remain laid out so
+ * that they pack the same way on 32-bit and 64-bit architectures (to
+ * avoid incompatibility between 32-bit userspace and 64-bit kernels).
+ */
+
+/**
+ * ib_user_mad_hdr_old - Old version of MAD packet header without pkey_index
+ * @id - ID of agent MAD received with/to be sent with
+ * @status - 0 on successful receive, ETIMEDOUT if no response
+ *   received (transaction ID in data[] will be set to TID of original
+ *   request) (ignored on send)
+ * @timeout_ms - Milliseconds to wait for response (unset on receive)
+ * @retries - Number of automatic retries to attempt
+ * @qpn - Remote QP number received from/to be sent to
+ * @qkey - Remote Q_Key to be sent with (unset on receive)
+ * @lid - Remote lid received from/to be sent to
+ * @sl - Service level received with/to be sent with
+ * @path_bits - Local path bits received with/to be sent with
+ * @grh_present - If set, GRH was received/should be sent
+ * @gid_index - Local GID index to send with (unset on receive)
+ * @hop_limit - Hop limit in GRH
+ * @traffic_class - Traffic class in GRH
+ * @gid - Remote GID in GRH
+ * @flow_label - Flow label in GRH
+ */
+struct ib_user_mad_hdr_old {
+	__u32	id;
+	__u32	status;
+	__u32	timeout_ms;
+	__u32	retries;
+	__u32	length;
+	__be32	qpn;
+	__be32  qkey;
+	__be16	lid;
+	__u8	sl;
+	__u8	path_bits;
+	__u8	grh_present;
+	__u8	gid_index;
+	__u8	hop_limit;
+	__u8	traffic_class;
+	__u8	gid[16];
+	__be32	flow_label;
+};
+
+/**
+ * ib_user_mad_hdr - MAD packet header
+ *   This layout allows specifying/receiving the P_Key index.  To use
+ *   this capability, an application must call the
+ *   IB_USER_MAD_ENABLE_PKEY ioctl on the user MAD file handle before
+ *   any other actions with the file handle.
+ * @id - ID of agent MAD received with/to be sent with
+ * @status - 0 on successful receive, ETIMEDOUT if no response
+ *   received (transaction ID in data[] will be set to TID of original
+ *   request) (ignored on send)
+ * @timeout_ms - Milliseconds to wait for response (unset on receive)
+ * @retries - Number of automatic retries to attempt
+ * @qpn - Remote QP number received from/to be sent to
+ * @qkey - Remote Q_Key to be sent with (unset on receive)
+ * @lid - Remote lid received from/to be sent to
+ * @sl - Service level received with/to be sent with
+ * @path_bits - Local path bits received with/to be sent with
+ * @grh_present - If set, GRH was received/should be sent
+ * @gid_index - Local GID index to send with (unset on receive)
+ * @hop_limit - Hop limit in GRH
+ * @traffic_class - Traffic class in GRH
+ * @gid - Remote GID in GRH
+ * @flow_label - Flow label in GRH
+ * @pkey_index - P_Key index
+ */
+struct ib_user_mad_hdr {
+	__u32	id;
+	__u32	status;
+	__u32	timeout_ms;
+	__u32	retries;
+	__u32	length;
+	__be32	qpn;
+	__be32  qkey;
+	__be16	lid;
+	__u8	sl;
+	__u8	path_bits;
+	__u8	grh_present;
+	__u8	gid_index;
+	__u8	hop_limit;
+	__u8	traffic_class;
+	__u8	gid[16];
+	__be32	flow_label;
+	__u16	pkey_index;
+	__u8	reserved[6];
+};
+
+/**
+ * ib_user_mad - MAD packet
+ * @hdr - MAD packet header
+ * @data - Contents of MAD
+ *
+ */
+struct ib_user_mad {
+	struct ib_user_mad_hdr hdr;
+	__u64	data[0];
+};
+
+/*
+ * Earlier versions of this interface definition declared the
+ * method_mask[] member as an array of __u32 but treated it as a
+ * bitmap made up of longs in the kernel.  This ambiguity meant that
+ * 32-bit big-endian applications that can run on both 32-bit and
+ * 64-bit kernels had no consistent ABI to rely on, and 64-bit
+ * big-endian applications that treated method_mask as being made up
+ * of 32-bit words would have their bitmap misinterpreted.
+ *
+ * To clear up this confusion, we change the declaration of
+ * method_mask[] to use unsigned long and handle the conversion from
+ * 32-bit userspace to 64-bit kernel for big-endian systems in the
+ * compat_ioctl method.  Unfortunately, to keep the structure layout
+ * the same, we need the method_mask[] array to be aligned only to 4
+ * bytes even when long is 64 bits, which forces us into this ugly
+ * typedef.
+ */
+typedef unsigned long __attribute__((aligned(4))) packed_ulong;
+#define IB_USER_MAD_LONGS_PER_METHOD_MASK (128 / (8 * sizeof (long)))
+
+/**
+ * ib_user_mad_reg_req - MAD registration request
+ * @id - Set by the kernel; used to identify agent in future requests.
+ * @qpn - Queue pair number; must be 0 or 1.
+ * @method_mask - The caller will receive unsolicited MADs for any method
+ *   where @method_mask = 1.
+ * @mgmt_class - Indicates which management class of MADs should be receive
+ *   by the caller.  This field is only required if the user wishes to
+ *   receive unsolicited MADs, otherwise it should be 0.
+ * @mgmt_class_version - Indicates which version of MADs for the given
+ *   management class to receive.
+ * @oui: Indicates IEEE OUI when mgmt_class is a vendor class
+ *   in the range from 0x30 to 0x4f. Otherwise not used.
+ * @rmpp_version: If set, indicates the RMPP version used.
+ *
+ */
+struct ib_user_mad_reg_req {
+	__u32	id;
+	packed_ulong method_mask[IB_USER_MAD_LONGS_PER_METHOD_MASK];
+	__u8	qpn;
+	__u8	mgmt_class;
+	__u8	mgmt_class_version;
+	__u8    oui[3];
+	__u8	rmpp_version;
+};
+
+#define IB_IOCTL_MAGIC		0x1b
+
+#define IB_USER_MAD_REGISTER_AGENT	_IOWR(IB_IOCTL_MAGIC, 1, \
+					      struct ib_user_mad_reg_req)
+
+#define IB_USER_MAD_UNREGISTER_AGENT	_IOW(IB_IOCTL_MAGIC, 2, __u32)
+
+#define IB_USER_MAD_ENABLE_PKEY		_IO(IB_IOCTL_MAGIC, 3)
+
+#endif /* IB_USER_MAD_H */
diff --git a/include/uapi/rdma/ib_user_sa.h b/include/uapi/rdma/ib_user_sa.h
new file mode 100644
index 0000000..cfc7c9b
--- /dev/null
+++ b/include/uapi/rdma/ib_user_sa.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef IB_USER_SA_H
+#define IB_USER_SA_H
+
+#include <linux/types.h>
+
+enum {
+	IB_PATH_GMP		= 1,
+	IB_PATH_PRIMARY		= (1<<1),
+	IB_PATH_ALTERNATE	= (1<<2),
+	IB_PATH_OUTBOUND	= (1<<3),
+	IB_PATH_INBOUND		= (1<<4),
+	IB_PATH_INBOUND_REVERSE = (1<<5),
+	IB_PATH_BIDIRECTIONAL	= IB_PATH_OUTBOUND | IB_PATH_INBOUND_REVERSE
+};
+
+struct ib_path_rec_data {
+	__u32	flags;
+	__u32	reserved;
+	__u32	path_rec[16];
+};
+
+struct ib_user_path_rec {
+	__u8	dgid[16];
+	__u8	sgid[16];
+	__be16	dlid;
+	__be16	slid;
+	__u32	raw_traffic;
+	__be32	flow_label;
+	__u32	reversible;
+	__u32	mtu;
+	__be16	pkey;
+	__u8	hop_limit;
+	__u8	traffic_class;
+	__u8	numb_path;
+	__u8	sl;
+	__u8	mtu_selector;
+	__u8	rate_selector;
+	__u8	rate;
+	__u8	packet_life_time_selector;
+	__u8	packet_life_time;
+	__u8	preference;
+};
+
+#endif /* IB_USER_SA_H */
diff --git a/include/uapi/rdma/ib_user_verbs.h b/include/uapi/rdma/ib_user_verbs.h
new file mode 100644
index 0000000..81aba3a
--- /dev/null
+++ b/include/uapi/rdma/ib_user_verbs.h
@@ -0,0 +1,734 @@
+/*
+ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005, 2006 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2005 PathScale, Inc.  All rights reserved.
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef IB_USER_VERBS_H
+#define IB_USER_VERBS_H
+
+#include <linux/types.h>
+
+/*
+ * Increment this value if any changes that break userspace ABI
+ * compatibility are made.
+ */
+#define IB_USER_VERBS_ABI_VERSION	6
+
+enum {
+	IB_USER_VERBS_CMD_GET_CONTEXT,
+	IB_USER_VERBS_CMD_QUERY_DEVICE,
+	IB_USER_VERBS_CMD_QUERY_PORT,
+	IB_USER_VERBS_CMD_ALLOC_PD,
+	IB_USER_VERBS_CMD_DEALLOC_PD,
+	IB_USER_VERBS_CMD_CREATE_AH,
+	IB_USER_VERBS_CMD_MODIFY_AH,
+	IB_USER_VERBS_CMD_QUERY_AH,
+	IB_USER_VERBS_CMD_DESTROY_AH,
+	IB_USER_VERBS_CMD_REG_MR,
+	IB_USER_VERBS_CMD_REG_SMR,
+	IB_USER_VERBS_CMD_REREG_MR,
+	IB_USER_VERBS_CMD_QUERY_MR,
+	IB_USER_VERBS_CMD_DEREG_MR,
+	IB_USER_VERBS_CMD_ALLOC_MW,
+	IB_USER_VERBS_CMD_BIND_MW,
+	IB_USER_VERBS_CMD_DEALLOC_MW,
+	IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL,
+	IB_USER_VERBS_CMD_CREATE_CQ,
+	IB_USER_VERBS_CMD_RESIZE_CQ,
+	IB_USER_VERBS_CMD_DESTROY_CQ,
+	IB_USER_VERBS_CMD_POLL_CQ,
+	IB_USER_VERBS_CMD_PEEK_CQ,
+	IB_USER_VERBS_CMD_REQ_NOTIFY_CQ,
+	IB_USER_VERBS_CMD_CREATE_QP,
+	IB_USER_VERBS_CMD_QUERY_QP,
+	IB_USER_VERBS_CMD_MODIFY_QP,
+	IB_USER_VERBS_CMD_DESTROY_QP,
+	IB_USER_VERBS_CMD_POST_SEND,
+	IB_USER_VERBS_CMD_POST_RECV,
+	IB_USER_VERBS_CMD_ATTACH_MCAST,
+	IB_USER_VERBS_CMD_DETACH_MCAST,
+	IB_USER_VERBS_CMD_CREATE_SRQ,
+	IB_USER_VERBS_CMD_MODIFY_SRQ,
+	IB_USER_VERBS_CMD_QUERY_SRQ,
+	IB_USER_VERBS_CMD_DESTROY_SRQ,
+	IB_USER_VERBS_CMD_POST_SRQ_RECV,
+	IB_USER_VERBS_CMD_OPEN_XRCD,
+	IB_USER_VERBS_CMD_CLOSE_XRCD,
+	IB_USER_VERBS_CMD_CREATE_XSRQ,
+	IB_USER_VERBS_CMD_OPEN_QP
+};
+
+/*
+ * Make sure that all structs defined in this file remain laid out so
+ * that they pack the same way on 32-bit and 64-bit architectures (to
+ * avoid incompatibility between 32-bit userspace and 64-bit kernels).
+ * Specifically:
+ *  - Do not use pointer types -- pass pointers in __u64 instead.
+ *  - Make sure that any structure larger than 4 bytes is padded to a
+ *    multiple of 8 bytes.  Otherwise the structure size will be
+ *    different between 32-bit and 64-bit architectures.
+ */
+
+struct ib_uverbs_async_event_desc {
+	__u64 element;
+	__u32 event_type;	/* enum ib_event_type */
+	__u32 reserved;
+};
+
+struct ib_uverbs_comp_event_desc {
+	__u64 cq_handle;
+};
+
+/*
+ * All commands from userspace should start with a __u32 command field
+ * followed by __u16 in_words and out_words fields (which give the
+ * length of the command block and response buffer if any in 32-bit
+ * words).  The kernel driver will read these fields first and read
+ * the rest of the command struct based on these value.
+ */
+
+struct ib_uverbs_cmd_hdr {
+	__u32 command;
+	__u16 in_words;
+	__u16 out_words;
+};
+
+struct ib_uverbs_get_context {
+	__u64 response;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_get_context_resp {
+	__u32 async_fd;
+	__u32 num_comp_vectors;
+};
+
+struct ib_uverbs_query_device {
+	__u64 response;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_query_device_resp {
+	__u64 fw_ver;
+	__be64 node_guid;
+	__be64 sys_image_guid;
+	__u64 max_mr_size;
+	__u64 page_size_cap;
+	__u32 vendor_id;
+	__u32 vendor_part_id;
+	__u32 hw_ver;
+	__u32 max_qp;
+	__u32 max_qp_wr;
+	__u32 device_cap_flags;
+	__u32 max_sge;
+	__u32 max_sge_rd;
+	__u32 max_cq;
+	__u32 max_cqe;
+	__u32 max_mr;
+	__u32 max_pd;
+	__u32 max_qp_rd_atom;
+	__u32 max_ee_rd_atom;
+	__u32 max_res_rd_atom;
+	__u32 max_qp_init_rd_atom;
+	__u32 max_ee_init_rd_atom;
+	__u32 atomic_cap;
+	__u32 max_ee;
+	__u32 max_rdd;
+	__u32 max_mw;
+	__u32 max_raw_ipv6_qp;
+	__u32 max_raw_ethy_qp;
+	__u32 max_mcast_grp;
+	__u32 max_mcast_qp_attach;
+	__u32 max_total_mcast_qp_attach;
+	__u32 max_ah;
+	__u32 max_fmr;
+	__u32 max_map_per_fmr;
+	__u32 max_srq;
+	__u32 max_srq_wr;
+	__u32 max_srq_sge;
+	__u16 max_pkeys;
+	__u8  local_ca_ack_delay;
+	__u8  phys_port_cnt;
+	__u8  reserved[4];
+};
+
+struct ib_uverbs_query_port {
+	__u64 response;
+	__u8  port_num;
+	__u8  reserved[7];
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_query_port_resp {
+	__u32 port_cap_flags;
+	__u32 max_msg_sz;
+	__u32 bad_pkey_cntr;
+	__u32 qkey_viol_cntr;
+	__u32 gid_tbl_len;
+	__u16 pkey_tbl_len;
+	__u16 lid;
+	__u16 sm_lid;
+	__u8  state;
+	__u8  max_mtu;
+	__u8  active_mtu;
+	__u8  lmc;
+	__u8  max_vl_num;
+	__u8  sm_sl;
+	__u8  subnet_timeout;
+	__u8  init_type_reply;
+	__u8  active_width;
+	__u8  active_speed;
+	__u8  phys_state;
+	__u8  link_layer;
+	__u8  reserved[2];
+};
+
+struct ib_uverbs_alloc_pd {
+	__u64 response;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_alloc_pd_resp {
+	__u32 pd_handle;
+};
+
+struct ib_uverbs_dealloc_pd {
+	__u32 pd_handle;
+};
+
+struct ib_uverbs_open_xrcd {
+	__u64 response;
+	__u32 fd;
+	__u32 oflags;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_open_xrcd_resp {
+	__u32 xrcd_handle;
+};
+
+struct ib_uverbs_close_xrcd {
+	__u32 xrcd_handle;
+};
+
+struct ib_uverbs_reg_mr {
+	__u64 response;
+	__u64 start;
+	__u64 length;
+	__u64 hca_va;
+	__u32 pd_handle;
+	__u32 access_flags;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_reg_mr_resp {
+	__u32 mr_handle;
+	__u32 lkey;
+	__u32 rkey;
+};
+
+struct ib_uverbs_dereg_mr {
+	__u32 mr_handle;
+};
+
+struct ib_uverbs_create_comp_channel {
+	__u64 response;
+};
+
+struct ib_uverbs_create_comp_channel_resp {
+	__u32 fd;
+};
+
+struct ib_uverbs_create_cq {
+	__u64 response;
+	__u64 user_handle;
+	__u32 cqe;
+	__u32 comp_vector;
+	__s32 comp_channel;
+	__u32 reserved;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_create_cq_resp {
+	__u32 cq_handle;
+	__u32 cqe;
+};
+
+struct ib_uverbs_resize_cq {
+	__u64 response;
+	__u32 cq_handle;
+	__u32 cqe;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_resize_cq_resp {
+	__u32 cqe;
+	__u32 reserved;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_poll_cq {
+	__u64 response;
+	__u32 cq_handle;
+	__u32 ne;
+};
+
+struct ib_uverbs_wc {
+	__u64 wr_id;
+	__u32 status;
+	__u32 opcode;
+	__u32 vendor_err;
+	__u32 byte_len;
+	union {
+		__u32 imm_data;
+		__u32 invalidate_rkey;
+	} ex;
+	__u32 qp_num;
+	__u32 src_qp;
+	__u32 wc_flags;
+	__u16 pkey_index;
+	__u16 slid;
+	__u8 sl;
+	__u8 dlid_path_bits;
+	__u8 port_num;
+	__u8 reserved;
+};
+
+struct ib_uverbs_poll_cq_resp {
+	__u32 count;
+	__u32 reserved;
+	struct ib_uverbs_wc wc[0];
+};
+
+struct ib_uverbs_req_notify_cq {
+	__u32 cq_handle;
+	__u32 solicited_only;
+};
+
+struct ib_uverbs_destroy_cq {
+	__u64 response;
+	__u32 cq_handle;
+	__u32 reserved;
+};
+
+struct ib_uverbs_destroy_cq_resp {
+	__u32 comp_events_reported;
+	__u32 async_events_reported;
+};
+
+struct ib_uverbs_global_route {
+	__u8  dgid[16];
+	__u32 flow_label;
+	__u8  sgid_index;
+	__u8  hop_limit;
+	__u8  traffic_class;
+	__u8  reserved;
+};
+
+struct ib_uverbs_ah_attr {
+	struct ib_uverbs_global_route grh;
+	__u16 dlid;
+	__u8  sl;
+	__u8  src_path_bits;
+	__u8  static_rate;
+	__u8  is_global;
+	__u8  port_num;
+	__u8  reserved;
+};
+
+struct ib_uverbs_qp_attr {
+	__u32	qp_attr_mask;
+	__u32	qp_state;
+	__u32	cur_qp_state;
+	__u32	path_mtu;
+	__u32	path_mig_state;
+	__u32	qkey;
+	__u32	rq_psn;
+	__u32	sq_psn;
+	__u32	dest_qp_num;
+	__u32	qp_access_flags;
+
+	struct ib_uverbs_ah_attr ah_attr;
+	struct ib_uverbs_ah_attr alt_ah_attr;
+
+	/* ib_qp_cap */
+	__u32	max_send_wr;
+	__u32	max_recv_wr;
+	__u32	max_send_sge;
+	__u32	max_recv_sge;
+	__u32	max_inline_data;
+
+	__u16	pkey_index;
+	__u16	alt_pkey_index;
+	__u8	en_sqd_async_notify;
+	__u8	sq_draining;
+	__u8	max_rd_atomic;
+	__u8	max_dest_rd_atomic;
+	__u8	min_rnr_timer;
+	__u8	port_num;
+	__u8	timeout;
+	__u8	retry_cnt;
+	__u8	rnr_retry;
+	__u8	alt_port_num;
+	__u8	alt_timeout;
+	__u8	reserved[5];
+};
+
+struct ib_uverbs_create_qp {
+	__u64 response;
+	__u64 user_handle;
+	__u32 pd_handle;
+	__u32 send_cq_handle;
+	__u32 recv_cq_handle;
+	__u32 srq_handle;
+	__u32 max_send_wr;
+	__u32 max_recv_wr;
+	__u32 max_send_sge;
+	__u32 max_recv_sge;
+	__u32 max_inline_data;
+	__u8  sq_sig_all;
+	__u8  qp_type;
+	__u8  is_srq;
+	__u8  reserved;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_open_qp {
+	__u64 response;
+	__u64 user_handle;
+	__u32 pd_handle;
+	__u32 qpn;
+	__u8  qp_type;
+	__u8  reserved[7];
+	__u64 driver_data[0];
+};
+
+/* also used for open response */
+struct ib_uverbs_create_qp_resp {
+	__u32 qp_handle;
+	__u32 qpn;
+	__u32 max_send_wr;
+	__u32 max_recv_wr;
+	__u32 max_send_sge;
+	__u32 max_recv_sge;
+	__u32 max_inline_data;
+	__u32 reserved;
+};
+
+/*
+ * This struct needs to remain a multiple of 8 bytes to keep the
+ * alignment of the modify QP parameters.
+ */
+struct ib_uverbs_qp_dest {
+	__u8  dgid[16];
+	__u32 flow_label;
+	__u16 dlid;
+	__u16 reserved;
+	__u8  sgid_index;
+	__u8  hop_limit;
+	__u8  traffic_class;
+	__u8  sl;
+	__u8  src_path_bits;
+	__u8  static_rate;
+	__u8  is_global;
+	__u8  port_num;
+};
+
+struct ib_uverbs_query_qp {
+	__u64 response;
+	__u32 qp_handle;
+	__u32 attr_mask;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_query_qp_resp {
+	struct ib_uverbs_qp_dest dest;
+	struct ib_uverbs_qp_dest alt_dest;
+	__u32 max_send_wr;
+	__u32 max_recv_wr;
+	__u32 max_send_sge;
+	__u32 max_recv_sge;
+	__u32 max_inline_data;
+	__u32 qkey;
+	__u32 rq_psn;
+	__u32 sq_psn;
+	__u32 dest_qp_num;
+	__u32 qp_access_flags;
+	__u16 pkey_index;
+	__u16 alt_pkey_index;
+	__u8  qp_state;
+	__u8  cur_qp_state;
+	__u8  path_mtu;
+	__u8  path_mig_state;
+	__u8  sq_draining;
+	__u8  max_rd_atomic;
+	__u8  max_dest_rd_atomic;
+	__u8  min_rnr_timer;
+	__u8  port_num;
+	__u8  timeout;
+	__u8  retry_cnt;
+	__u8  rnr_retry;
+	__u8  alt_port_num;
+	__u8  alt_timeout;
+	__u8  sq_sig_all;
+	__u8  reserved[5];
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_modify_qp {
+	struct ib_uverbs_qp_dest dest;
+	struct ib_uverbs_qp_dest alt_dest;
+	__u32 qp_handle;
+	__u32 attr_mask;
+	__u32 qkey;
+	__u32 rq_psn;
+	__u32 sq_psn;
+	__u32 dest_qp_num;
+	__u32 qp_access_flags;
+	__u16 pkey_index;
+	__u16 alt_pkey_index;
+	__u8  qp_state;
+	__u8  cur_qp_state;
+	__u8  path_mtu;
+	__u8  path_mig_state;
+	__u8  en_sqd_async_notify;
+	__u8  max_rd_atomic;
+	__u8  max_dest_rd_atomic;
+	__u8  min_rnr_timer;
+	__u8  port_num;
+	__u8  timeout;
+	__u8  retry_cnt;
+	__u8  rnr_retry;
+	__u8  alt_port_num;
+	__u8  alt_timeout;
+	__u8  reserved[2];
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_modify_qp_resp {
+};
+
+struct ib_uverbs_destroy_qp {
+	__u64 response;
+	__u32 qp_handle;
+	__u32 reserved;
+};
+
+struct ib_uverbs_destroy_qp_resp {
+	__u32 events_reported;
+};
+
+/*
+ * The ib_uverbs_sge structure isn't used anywhere, since we assume
+ * the ib_sge structure is packed the same way on 32-bit and 64-bit
+ * architectures in both kernel and user space.  It's just here to
+ * document the ABI.
+ */
+struct ib_uverbs_sge {
+	__u64 addr;
+	__u32 length;
+	__u32 lkey;
+};
+
+struct ib_uverbs_send_wr {
+	__u64 wr_id;
+	__u32 num_sge;
+	__u32 opcode;
+	__u32 send_flags;
+	union {
+		__u32 imm_data;
+		__u32 invalidate_rkey;
+	} ex;
+	union {
+		struct {
+			__u64 remote_addr;
+			__u32 rkey;
+			__u32 reserved;
+		} rdma;
+		struct {
+			__u64 remote_addr;
+			__u64 compare_add;
+			__u64 swap;
+			__u32 rkey;
+			__u32 reserved;
+		} atomic;
+		struct {
+			__u32 ah;
+			__u32 remote_qpn;
+			__u32 remote_qkey;
+			__u32 reserved;
+		} ud;
+	} wr;
+};
+
+struct ib_uverbs_post_send {
+	__u64 response;
+	__u32 qp_handle;
+	__u32 wr_count;
+	__u32 sge_count;
+	__u32 wqe_size;
+	struct ib_uverbs_send_wr send_wr[0];
+};
+
+struct ib_uverbs_post_send_resp {
+	__u32 bad_wr;
+};
+
+struct ib_uverbs_recv_wr {
+	__u64 wr_id;
+	__u32 num_sge;
+	__u32 reserved;
+};
+
+struct ib_uverbs_post_recv {
+	__u64 response;
+	__u32 qp_handle;
+	__u32 wr_count;
+	__u32 sge_count;
+	__u32 wqe_size;
+	struct ib_uverbs_recv_wr recv_wr[0];
+};
+
+struct ib_uverbs_post_recv_resp {
+	__u32 bad_wr;
+};
+
+struct ib_uverbs_post_srq_recv {
+	__u64 response;
+	__u32 srq_handle;
+	__u32 wr_count;
+	__u32 sge_count;
+	__u32 wqe_size;
+	struct ib_uverbs_recv_wr recv[0];
+};
+
+struct ib_uverbs_post_srq_recv_resp {
+	__u32 bad_wr;
+};
+
+struct ib_uverbs_create_ah {
+	__u64 response;
+	__u64 user_handle;
+	__u32 pd_handle;
+	__u32 reserved;
+	struct ib_uverbs_ah_attr attr;
+};
+
+struct ib_uverbs_create_ah_resp {
+	__u32 ah_handle;
+};
+
+struct ib_uverbs_destroy_ah {
+	__u32 ah_handle;
+};
+
+struct ib_uverbs_attach_mcast {
+	__u8  gid[16];
+	__u32 qp_handle;
+	__u16 mlid;
+	__u16 reserved;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_detach_mcast {
+	__u8  gid[16];
+	__u32 qp_handle;
+	__u16 mlid;
+	__u16 reserved;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_create_srq {
+	__u64 response;
+	__u64 user_handle;
+	__u32 pd_handle;
+	__u32 max_wr;
+	__u32 max_sge;
+	__u32 srq_limit;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_create_xsrq {
+	__u64 response;
+	__u64 user_handle;
+	__u32 srq_type;
+	__u32 pd_handle;
+	__u32 max_wr;
+	__u32 max_sge;
+	__u32 srq_limit;
+	__u32 reserved;
+	__u32 xrcd_handle;
+	__u32 cq_handle;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_create_srq_resp {
+	__u32 srq_handle;
+	__u32 max_wr;
+	__u32 max_sge;
+	__u32 srqn;
+};
+
+struct ib_uverbs_modify_srq {
+	__u32 srq_handle;
+	__u32 attr_mask;
+	__u32 max_wr;
+	__u32 srq_limit;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_query_srq {
+	__u64 response;
+	__u32 srq_handle;
+	__u32 reserved;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_query_srq_resp {
+	__u32 max_wr;
+	__u32 max_sge;
+	__u32 srq_limit;
+	__u32 reserved;
+};
+
+struct ib_uverbs_destroy_srq {
+	__u64 response;
+	__u32 srq_handle;
+	__u32 reserved;
+};
+
+struct ib_uverbs_destroy_srq_resp {
+	__u32 events_reported;
+};
+
+#endif /* IB_USER_VERBS_H */
diff --git a/include/uapi/rdma/rdma_netlink.h b/include/uapi/rdma/rdma_netlink.h
new file mode 100644
index 0000000..8297285
--- /dev/null
+++ b/include/uapi/rdma/rdma_netlink.h
@@ -0,0 +1,37 @@
+#ifndef _UAPI_RDMA_NETLINK_H
+#define _UAPI_RDMA_NETLINK_H
+
+#include <linux/types.h>
+
+enum {
+	RDMA_NL_RDMA_CM = 1
+};
+
+#define RDMA_NL_GET_CLIENT(type) ((type & (((1 << 6) - 1) << 10)) >> 10)
+#define RDMA_NL_GET_OP(type) (type & ((1 << 10) - 1))
+#define RDMA_NL_GET_TYPE(client, op) ((client << 10) + op)
+
+enum {
+	RDMA_NL_RDMA_CM_ID_STATS = 0,
+	RDMA_NL_RDMA_CM_NUM_OPS
+};
+
+enum {
+	RDMA_NL_RDMA_CM_ATTR_SRC_ADDR = 1,
+	RDMA_NL_RDMA_CM_ATTR_DST_ADDR,
+	RDMA_NL_RDMA_CM_NUM_ATTR,
+};
+
+struct rdma_cm_id_stats {
+	__u32	qp_num;
+	__u32	bound_dev_if;
+	__u32	port_space;
+	__s32	pid;
+	__u8	cm_state;
+	__u8	node_type;
+	__u8	port_num;
+	__u8	qp_type;
+};
+
+
+#endif /* _UAPI_RDMA_NETLINK_H */
diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h
new file mode 100644
index 0000000..1ee9239
--- /dev/null
+++ b/include/uapi/rdma/rdma_user_cm.h
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2005-2006 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef RDMA_USER_CM_H
+#define RDMA_USER_CM_H
+
+#include <linux/types.h>
+#include <linux/in6.h>
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_user_sa.h>
+
+#define RDMA_USER_CM_ABI_VERSION	4
+
+#define RDMA_MAX_PRIVATE_DATA		256
+
+enum {
+	RDMA_USER_CM_CMD_CREATE_ID,
+	RDMA_USER_CM_CMD_DESTROY_ID,
+	RDMA_USER_CM_CMD_BIND_ADDR,
+	RDMA_USER_CM_CMD_RESOLVE_ADDR,
+	RDMA_USER_CM_CMD_RESOLVE_ROUTE,
+	RDMA_USER_CM_CMD_QUERY_ROUTE,
+	RDMA_USER_CM_CMD_CONNECT,
+	RDMA_USER_CM_CMD_LISTEN,
+	RDMA_USER_CM_CMD_ACCEPT,
+	RDMA_USER_CM_CMD_REJECT,
+	RDMA_USER_CM_CMD_DISCONNECT,
+	RDMA_USER_CM_CMD_INIT_QP_ATTR,
+	RDMA_USER_CM_CMD_GET_EVENT,
+	RDMA_USER_CM_CMD_GET_OPTION,
+	RDMA_USER_CM_CMD_SET_OPTION,
+	RDMA_USER_CM_CMD_NOTIFY,
+	RDMA_USER_CM_CMD_JOIN_MCAST,
+	RDMA_USER_CM_CMD_LEAVE_MCAST,
+	RDMA_USER_CM_CMD_MIGRATE_ID
+};
+
+/*
+ * command ABI structures.
+ */
+struct rdma_ucm_cmd_hdr {
+	__u32 cmd;
+	__u16 in;
+	__u16 out;
+};
+
+struct rdma_ucm_create_id {
+	__u64 uid;
+	__u64 response;
+	__u16 ps;
+	__u8  qp_type;
+	__u8  reserved[5];
+};
+
+struct rdma_ucm_create_id_resp {
+	__u32 id;
+};
+
+struct rdma_ucm_destroy_id {
+	__u64 response;
+	__u32 id;
+	__u32 reserved;
+};
+
+struct rdma_ucm_destroy_id_resp {
+	__u32 events_reported;
+};
+
+struct rdma_ucm_bind_addr {
+	__u64 response;
+	struct sockaddr_in6 addr;
+	__u32 id;
+};
+
+struct rdma_ucm_resolve_addr {
+	struct sockaddr_in6 src_addr;
+	struct sockaddr_in6 dst_addr;
+	__u32 id;
+	__u32 timeout_ms;
+};
+
+struct rdma_ucm_resolve_route {
+	__u32 id;
+	__u32 timeout_ms;
+};
+
+struct rdma_ucm_query_route {
+	__u64 response;
+	__u32 id;
+	__u32 reserved;
+};
+
+struct rdma_ucm_query_route_resp {
+	__u64 node_guid;
+	struct ib_user_path_rec ib_route[2];
+	struct sockaddr_in6 src_addr;
+	struct sockaddr_in6 dst_addr;
+	__u32 num_paths;
+	__u8 port_num;
+	__u8 reserved[3];
+};
+
+struct rdma_ucm_conn_param {
+	__u32 qp_num;
+	__u32 reserved;
+	__u8  private_data[RDMA_MAX_PRIVATE_DATA];
+	__u8  private_data_len;
+	__u8  srq;
+	__u8  responder_resources;
+	__u8  initiator_depth;
+	__u8  flow_control;
+	__u8  retry_count;
+	__u8  rnr_retry_count;
+	__u8  valid;
+};
+
+struct rdma_ucm_ud_param {
+	__u32 qp_num;
+	__u32 qkey;
+	struct ib_uverbs_ah_attr ah_attr;
+	__u8  private_data[RDMA_MAX_PRIVATE_DATA];
+	__u8  private_data_len;
+	__u8  reserved[7];
+};
+
+struct rdma_ucm_connect {
+	struct rdma_ucm_conn_param conn_param;
+	__u32 id;
+	__u32 reserved;
+};
+
+struct rdma_ucm_listen {
+	__u32 id;
+	__u32 backlog;
+};
+
+struct rdma_ucm_accept {
+	__u64 uid;
+	struct rdma_ucm_conn_param conn_param;
+	__u32 id;
+	__u32 reserved;
+};
+
+struct rdma_ucm_reject {
+	__u32 id;
+	__u8  private_data_len;
+	__u8  reserved[3];
+	__u8  private_data[RDMA_MAX_PRIVATE_DATA];
+};
+
+struct rdma_ucm_disconnect {
+	__u32 id;
+};
+
+struct rdma_ucm_init_qp_attr {
+	__u64 response;
+	__u32 id;
+	__u32 qp_state;
+};
+
+struct rdma_ucm_notify {
+	__u32 id;
+	__u32 event;
+};
+
+struct rdma_ucm_join_mcast {
+	__u64 response;		/* rdma_ucm_create_id_resp */
+	__u64 uid;
+	struct sockaddr_in6 addr;
+	__u32 id;
+};
+
+struct rdma_ucm_get_event {
+	__u64 response;
+};
+
+struct rdma_ucm_event_resp {
+	__u64 uid;
+	__u32 id;
+	__u32 event;
+	__u32 status;
+	union {
+		struct rdma_ucm_conn_param conn;
+		struct rdma_ucm_ud_param   ud;
+	} param;
+};
+
+/* Option levels */
+enum {
+	RDMA_OPTION_ID		= 0,
+	RDMA_OPTION_IB		= 1
+};
+
+/* Option details */
+enum {
+	RDMA_OPTION_ID_TOS	 = 0,
+	RDMA_OPTION_ID_REUSEADDR = 1,
+	RDMA_OPTION_ID_AFONLY	 = 2,
+	RDMA_OPTION_IB_PATH	 = 1
+};
+
+struct rdma_ucm_set_option {
+	__u64 optval;
+	__u32 id;
+	__u32 level;
+	__u32 optname;
+	__u32 optlen;
+};
+
+struct rdma_ucm_migrate_id {
+	__u64 response;
+	__u32 id;
+	__u32 fd;
+};
+
+struct rdma_ucm_migrate_resp {
+	__u32 events_reported;
+};
+
+#endif /* RDMA_USER_CM_H */
diff --git a/include/uapi/sound/Kbuild b/include/uapi/sound/Kbuild
index aafaa5a..0f7d279 100644
--- a/include/uapi/sound/Kbuild
+++ b/include/uapi/sound/Kbuild
@@ -1 +1,11 @@
 # UAPI Header export list
+header-y += asequencer.h
+header-y += asound.h
+header-y += asound_fm.h
+header-y += compress_offload.h
+header-y += compress_params.h
+header-y += emu10k1.h
+header-y += hdsp.h
+header-y += hdspm.h
+header-y += sb16_csp.h
+header-y += sfnt_info.h
diff --git a/include/uapi/sound/asequencer.h b/include/uapi/sound/asequencer.h
new file mode 100644
index 0000000..09c8a00
--- /dev/null
+++ b/include/uapi/sound/asequencer.h
@@ -0,0 +1,614 @@
+/*
+ *  Main header file for the ALSA sequencer
+ *  Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
+ *            (c) 1998-1999 by Jaroslav Kysela <perex@perex.cz>
+ *
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+#ifndef _UAPI__SOUND_ASEQUENCER_H
+#define _UAPI__SOUND_ASEQUENCER_H
+
+
+/** version of the sequencer */
+#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION (1, 0, 1)
+
+/**
+ * definition of sequencer event types
+ */
+
+/** system messages
+ * event data type = #snd_seq_result
+ */
+#define SNDRV_SEQ_EVENT_SYSTEM		0
+#define SNDRV_SEQ_EVENT_RESULT		1
+
+/** note messages (channel specific)
+ * event data type = #snd_seq_ev_note
+ */
+#define SNDRV_SEQ_EVENT_NOTE		5
+#define SNDRV_SEQ_EVENT_NOTEON		6
+#define SNDRV_SEQ_EVENT_NOTEOFF		7
+#define SNDRV_SEQ_EVENT_KEYPRESS	8
+	
+/** control messages (channel specific)
+ * event data type = #snd_seq_ev_ctrl
+ */
+#define SNDRV_SEQ_EVENT_CONTROLLER	10
+#define SNDRV_SEQ_EVENT_PGMCHANGE	11
+#define SNDRV_SEQ_EVENT_CHANPRESS	12
+#define SNDRV_SEQ_EVENT_PITCHBEND	13	/**< from -8192 to 8191 */
+#define SNDRV_SEQ_EVENT_CONTROL14	14	/**< 14 bit controller value */
+#define SNDRV_SEQ_EVENT_NONREGPARAM	15	/**< 14 bit NRPN address + 14 bit unsigned value */
+#define SNDRV_SEQ_EVENT_REGPARAM	16	/**< 14 bit RPN address + 14 bit unsigned value */
+
+/** synchronisation messages
+ * event data type = #snd_seq_ev_ctrl
+ */
+#define SNDRV_SEQ_EVENT_SONGPOS		20	/* Song Position Pointer with LSB and MSB values */
+#define SNDRV_SEQ_EVENT_SONGSEL		21	/* Song Select with song ID number */
+#define SNDRV_SEQ_EVENT_QFRAME		22	/* midi time code quarter frame */
+#define SNDRV_SEQ_EVENT_TIMESIGN	23	/* SMF Time Signature event */
+#define SNDRV_SEQ_EVENT_KEYSIGN		24	/* SMF Key Signature event */
+	        
+/** timer messages
+ * event data type = snd_seq_ev_queue_control
+ */
+#define SNDRV_SEQ_EVENT_START		30	/* midi Real Time Start message */
+#define SNDRV_SEQ_EVENT_CONTINUE	31	/* midi Real Time Continue message */
+#define SNDRV_SEQ_EVENT_STOP		32	/* midi Real Time Stop message */	
+#define	SNDRV_SEQ_EVENT_SETPOS_TICK	33	/* set tick queue position */
+#define SNDRV_SEQ_EVENT_SETPOS_TIME	34	/* set realtime queue position */
+#define SNDRV_SEQ_EVENT_TEMPO		35	/* (SMF) Tempo event */
+#define SNDRV_SEQ_EVENT_CLOCK		36	/* midi Real Time Clock message */
+#define SNDRV_SEQ_EVENT_TICK		37	/* midi Real Time Tick message */
+#define SNDRV_SEQ_EVENT_QUEUE_SKEW	38	/* skew queue tempo */
+
+/** others
+ * event data type = none
+ */
+#define SNDRV_SEQ_EVENT_TUNE_REQUEST	40	/* tune request */
+#define SNDRV_SEQ_EVENT_RESET		41	/* reset to power-on state */
+#define SNDRV_SEQ_EVENT_SENSING		42	/* "active sensing" event */
+
+/** echo back, kernel private messages
+ * event data type = any type
+ */
+#define SNDRV_SEQ_EVENT_ECHO		50	/* echo event */
+#define SNDRV_SEQ_EVENT_OSS		51	/* OSS raw event */
+
+/** system status messages (broadcast for subscribers)
+ * event data type = snd_seq_addr
+ */
+#define SNDRV_SEQ_EVENT_CLIENT_START	60	/* new client has connected */
+#define SNDRV_SEQ_EVENT_CLIENT_EXIT	61	/* client has left the system */
+#define SNDRV_SEQ_EVENT_CLIENT_CHANGE	62	/* client status/info has changed */
+#define SNDRV_SEQ_EVENT_PORT_START	63	/* new port was created */
+#define SNDRV_SEQ_EVENT_PORT_EXIT	64	/* port was deleted from system */
+#define SNDRV_SEQ_EVENT_PORT_CHANGE	65	/* port status/info has changed */
+
+/** port connection changes
+ * event data type = snd_seq_connect
+ */
+#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED	66	/* ports connected */
+#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67	/* ports disconnected */
+
+/* 70-89:  synthesizer events - obsoleted */
+
+/** user-defined events with fixed length
+ * event data type = any
+ */
+#define SNDRV_SEQ_EVENT_USR0		90
+#define SNDRV_SEQ_EVENT_USR1		91
+#define SNDRV_SEQ_EVENT_USR2		92
+#define SNDRV_SEQ_EVENT_USR3		93
+#define SNDRV_SEQ_EVENT_USR4		94
+#define SNDRV_SEQ_EVENT_USR5		95
+#define SNDRV_SEQ_EVENT_USR6		96
+#define SNDRV_SEQ_EVENT_USR7		97
+#define SNDRV_SEQ_EVENT_USR8		98
+#define SNDRV_SEQ_EVENT_USR9		99
+
+/* 100-118: instrument layer - obsoleted */
+/* 119-129: reserved */
+
+/* 130-139: variable length events
+ * event data type = snd_seq_ev_ext
+ * (SNDRV_SEQ_EVENT_LENGTH_VARIABLE must be set)
+ */
+#define SNDRV_SEQ_EVENT_SYSEX		130	/* system exclusive data (variable length) */
+#define SNDRV_SEQ_EVENT_BOUNCE		131	/* error event */
+/* 132-134: reserved */
+#define SNDRV_SEQ_EVENT_USR_VAR0	135
+#define SNDRV_SEQ_EVENT_USR_VAR1	136
+#define SNDRV_SEQ_EVENT_USR_VAR2	137
+#define SNDRV_SEQ_EVENT_USR_VAR3	138
+#define SNDRV_SEQ_EVENT_USR_VAR4	139
+
+/* 150-151: kernel events with quote - DO NOT use in user clients */
+#define SNDRV_SEQ_EVENT_KERNEL_ERROR	150
+#define SNDRV_SEQ_EVENT_KERNEL_QUOTE	151	/* obsolete */
+
+/* 152-191: reserved */
+
+/* 192-254: hardware specific events */
+
+/* 255: special event */
+#define SNDRV_SEQ_EVENT_NONE		255
+
+
+typedef unsigned char snd_seq_event_type_t;
+
+/** event address */
+struct snd_seq_addr {
+	unsigned char client;	/**< Client number:         0..255, 255 = broadcast to all clients */
+	unsigned char port;	/**< Port within client:    0..255, 255 = broadcast to all ports */
+};
+
+/** port connection */
+struct snd_seq_connect {
+	struct snd_seq_addr sender;
+	struct snd_seq_addr dest;
+};
+
+
+#define SNDRV_SEQ_ADDRESS_UNKNOWN	253	/* unknown source */
+#define SNDRV_SEQ_ADDRESS_SUBSCRIBERS	254	/* send event to all subscribed ports */
+#define SNDRV_SEQ_ADDRESS_BROADCAST	255	/* send event to all queues/clients/ports/channels */
+#define SNDRV_SEQ_QUEUE_DIRECT		253	/* direct dispatch */
+
+	/* event mode flag - NOTE: only 8 bits available! */
+#define SNDRV_SEQ_TIME_STAMP_TICK	(0<<0) /* timestamp in clock ticks */
+#define SNDRV_SEQ_TIME_STAMP_REAL	(1<<0) /* timestamp in real time */
+#define SNDRV_SEQ_TIME_STAMP_MASK	(1<<0)
+
+#define SNDRV_SEQ_TIME_MODE_ABS		(0<<1)	/* absolute timestamp */
+#define SNDRV_SEQ_TIME_MODE_REL		(1<<1)	/* relative to current time */
+#define SNDRV_SEQ_TIME_MODE_MASK	(1<<1)
+
+#define SNDRV_SEQ_EVENT_LENGTH_FIXED	(0<<2)	/* fixed event size */
+#define SNDRV_SEQ_EVENT_LENGTH_VARIABLE	(1<<2)	/* variable event size */
+#define SNDRV_SEQ_EVENT_LENGTH_VARUSR	(2<<2)	/* variable event size - user memory space */
+#define SNDRV_SEQ_EVENT_LENGTH_MASK	(3<<2)
+
+#define SNDRV_SEQ_PRIORITY_NORMAL	(0<<4)	/* normal priority */
+#define SNDRV_SEQ_PRIORITY_HIGH		(1<<4)	/* event should be processed before others */
+#define SNDRV_SEQ_PRIORITY_MASK		(1<<4)
+
+
+	/* note event */
+struct snd_seq_ev_note {
+	unsigned char channel;
+	unsigned char note;
+	unsigned char velocity;
+	unsigned char off_velocity;	/* only for SNDRV_SEQ_EVENT_NOTE */
+	unsigned int duration;		/* only for SNDRV_SEQ_EVENT_NOTE */
+};
+
+	/* controller event */
+struct snd_seq_ev_ctrl {
+	unsigned char channel;
+	unsigned char unused1, unused2, unused3;	/* pad */
+	unsigned int param;
+	signed int value;
+};
+
+	/* generic set of bytes (12x8 bit) */
+struct snd_seq_ev_raw8 {
+	unsigned char d[12];	/* 8 bit value */
+};
+
+	/* generic set of integers (3x32 bit) */
+struct snd_seq_ev_raw32 {
+	unsigned int d[3];	/* 32 bit value */
+};
+
+	/* external stored data */
+struct snd_seq_ev_ext {
+	unsigned int len;	/* length of data */
+	void *ptr;		/* pointer to data (note: maybe 64-bit) */
+} __attribute__((packed));
+
+struct snd_seq_result {
+	int event;		/* processed event type */
+	int result;
+};
+
+
+struct snd_seq_real_time {
+	unsigned int tv_sec;	/* seconds */
+	unsigned int tv_nsec;	/* nanoseconds */
+};
+
+typedef unsigned int snd_seq_tick_time_t;	/* midi ticks */
+
+union snd_seq_timestamp {
+	snd_seq_tick_time_t tick;
+	struct snd_seq_real_time time;
+};
+
+struct snd_seq_queue_skew {
+	unsigned int value;
+	unsigned int base;
+};
+
+	/* queue timer control */
+struct snd_seq_ev_queue_control {
+	unsigned char queue;			/* affected queue */
+	unsigned char pad[3];			/* reserved */
+	union {
+		signed int value;		/* affected value (e.g. tempo) */
+		union snd_seq_timestamp time;	/* time */
+		unsigned int position;		/* sync position */
+		struct snd_seq_queue_skew skew;
+		unsigned int d32[2];
+		unsigned char d8[8];
+	} param;
+};
+
+	/* quoted event - inside the kernel only */
+struct snd_seq_ev_quote {
+	struct snd_seq_addr origin;		/* original sender */
+	unsigned short value;		/* optional data */
+	struct snd_seq_event *event;		/* quoted event */
+} __attribute__((packed));
+
+
+	/* sequencer event */
+struct snd_seq_event {
+	snd_seq_event_type_t type;	/* event type */
+	unsigned char flags;		/* event flags */
+	char tag;
+	
+	unsigned char queue;		/* schedule queue */
+	union snd_seq_timestamp time;	/* schedule time */
+
+
+	struct snd_seq_addr source;	/* source address */
+	struct snd_seq_addr dest;	/* destination address */
+
+	union {				/* event data... */
+		struct snd_seq_ev_note note;
+		struct snd_seq_ev_ctrl control;
+		struct snd_seq_ev_raw8 raw8;
+		struct snd_seq_ev_raw32 raw32;
+		struct snd_seq_ev_ext ext;
+		struct snd_seq_ev_queue_control queue;
+		union snd_seq_timestamp time;
+		struct snd_seq_addr addr;
+		struct snd_seq_connect connect;
+		struct snd_seq_result result;
+		struct snd_seq_ev_quote quote;
+	} data;
+};
+
+
+/*
+ * bounce event - stored as variable size data
+ */
+struct snd_seq_event_bounce {
+	int err;
+	struct snd_seq_event event;
+	/* external data follows here. */
+};
+
+
+	/* system information */
+struct snd_seq_system_info {
+	int queues;			/* maximum queues count */
+	int clients;			/* maximum clients count */
+	int ports;			/* maximum ports per client */
+	int channels;			/* maximum channels per port */
+	int cur_clients;		/* current clients */
+	int cur_queues;			/* current queues */
+	char reserved[24];
+};
+
+
+	/* system running information */
+struct snd_seq_running_info {
+	unsigned char client;		/* client id */
+	unsigned char big_endian;	/* 1 = big-endian */
+	unsigned char cpu_mode;		/* 4 = 32bit, 8 = 64bit */
+	unsigned char pad;		/* reserved */
+	unsigned char reserved[12];
+};
+
+
+	/* known client numbers */
+#define SNDRV_SEQ_CLIENT_SYSTEM		0
+	/* internal client numbers */
+#define SNDRV_SEQ_CLIENT_DUMMY		14	/* midi through */
+#define SNDRV_SEQ_CLIENT_OSS		15	/* oss sequencer emulator */
+
+
+	/* client types */
+typedef int __bitwise snd_seq_client_type_t;
+#define	NO_CLIENT	((__force snd_seq_client_type_t) 0)
+#define	USER_CLIENT	((__force snd_seq_client_type_t) 1)
+#define	KERNEL_CLIENT	((__force snd_seq_client_type_t) 2)
+                        
+	/* event filter flags */
+#define SNDRV_SEQ_FILTER_BROADCAST	(1<<0)	/* accept broadcast messages */
+#define SNDRV_SEQ_FILTER_MULTICAST	(1<<1)	/* accept multicast messages */
+#define SNDRV_SEQ_FILTER_BOUNCE		(1<<2)	/* accept bounce event in error */
+#define SNDRV_SEQ_FILTER_USE_EVENT	(1<<31)	/* use event filter */
+
+struct snd_seq_client_info {
+	int client;			/* client number to inquire */
+	snd_seq_client_type_t type;	/* client type */
+	char name[64];			/* client name */
+	unsigned int filter;		/* filter flags */
+	unsigned char multicast_filter[8]; /* multicast filter bitmap */
+	unsigned char event_filter[32];	/* event filter bitmap */
+	int num_ports;			/* RO: number of ports */
+	int event_lost;			/* number of lost events */
+	char reserved[64];		/* for future use */
+};
+
+
+/* client pool size */
+struct snd_seq_client_pool {
+	int client;			/* client number to inquire */
+	int output_pool;		/* outgoing (write) pool size */
+	int input_pool;			/* incoming (read) pool size */
+	int output_room;		/* minimum free pool size for select/blocking mode */
+	int output_free;		/* unused size */
+	int input_free;			/* unused size */
+	char reserved[64];
+};
+
+
+/* Remove events by specified criteria */
+
+#define SNDRV_SEQ_REMOVE_INPUT		(1<<0)	/* Flush input queues */
+#define SNDRV_SEQ_REMOVE_OUTPUT		(1<<1)	/* Flush output queues */
+#define SNDRV_SEQ_REMOVE_DEST		(1<<2)	/* Restrict by destination q:client:port */
+#define SNDRV_SEQ_REMOVE_DEST_CHANNEL	(1<<3)	/* Restrict by channel */
+#define SNDRV_SEQ_REMOVE_TIME_BEFORE	(1<<4)	/* Restrict to before time */
+#define SNDRV_SEQ_REMOVE_TIME_AFTER	(1<<5)	/* Restrict to time or after */
+#define SNDRV_SEQ_REMOVE_TIME_TICK	(1<<6)	/* Time is in ticks */
+#define SNDRV_SEQ_REMOVE_EVENT_TYPE	(1<<7)	/* Restrict to event type */
+#define SNDRV_SEQ_REMOVE_IGNORE_OFF 	(1<<8)	/* Do not flush off events */
+#define SNDRV_SEQ_REMOVE_TAG_MATCH 	(1<<9)	/* Restrict to events with given tag */
+
+struct snd_seq_remove_events {
+	unsigned int  remove_mode;	/* Flags that determine what gets removed */
+
+	union snd_seq_timestamp time;
+
+	unsigned char queue;	/* Queue for REMOVE_DEST */
+	struct snd_seq_addr dest;	/* Address for REMOVE_DEST */
+	unsigned char channel;	/* Channel for REMOVE_DEST */
+
+	int  type;	/* For REMOVE_EVENT_TYPE */
+	char  tag;	/* Tag for REMOVE_TAG */
+
+	int  reserved[10];	/* To allow for future binary compatibility */
+
+};
+
+
+	/* known port numbers */
+#define SNDRV_SEQ_PORT_SYSTEM_TIMER	0
+#define SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE	1
+
+	/* port capabilities (32 bits) */
+#define SNDRV_SEQ_PORT_CAP_READ		(1<<0)	/* readable from this port */
+#define SNDRV_SEQ_PORT_CAP_WRITE	(1<<1)	/* writable to this port */
+
+#define SNDRV_SEQ_PORT_CAP_SYNC_READ	(1<<2)
+#define SNDRV_SEQ_PORT_CAP_SYNC_WRITE	(1<<3)
+
+#define SNDRV_SEQ_PORT_CAP_DUPLEX	(1<<4)
+
+#define SNDRV_SEQ_PORT_CAP_SUBS_READ	(1<<5)	/* allow read subscription */
+#define SNDRV_SEQ_PORT_CAP_SUBS_WRITE	(1<<6)	/* allow write subscription */
+#define SNDRV_SEQ_PORT_CAP_NO_EXPORT	(1<<7)	/* routing not allowed */
+
+	/* port type */
+#define SNDRV_SEQ_PORT_TYPE_SPECIFIC	(1<<0)	/* hardware specific */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC (1<<1)	/* generic MIDI device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GM	(1<<2)	/* General MIDI compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GS	(1<<3)	/* GS compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_XG	(1<<4)	/* XG compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_MT32	(1<<5)	/* MT-32 compatible device */
+#define SNDRV_SEQ_PORT_TYPE_MIDI_GM2	(1<<6)	/* General MIDI 2 compatible device */
+
+/* other standards...*/
+#define SNDRV_SEQ_PORT_TYPE_SYNTH	(1<<10)	/* Synth device (no MIDI compatible - direct wavetable) */
+#define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11)	/* Sampling device (support sample download) */
+#define SNDRV_SEQ_PORT_TYPE_SAMPLE	(1<<12)	/* Sampling device (sample can be downloaded at any time) */
+/*...*/
+#define SNDRV_SEQ_PORT_TYPE_HARDWARE	(1<<16)	/* driver for a hardware device */
+#define SNDRV_SEQ_PORT_TYPE_SOFTWARE	(1<<17)	/* implemented in software */
+#define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER	(1<<18)	/* generates sound */
+#define SNDRV_SEQ_PORT_TYPE_PORT	(1<<19)	/* connects to other device(s) */
+#define SNDRV_SEQ_PORT_TYPE_APPLICATION	(1<<20)	/* application (sequencer/editor) */
+
+/* misc. conditioning flags */
+#define SNDRV_SEQ_PORT_FLG_GIVEN_PORT	(1<<0)
+#define SNDRV_SEQ_PORT_FLG_TIMESTAMP	(1<<1)
+#define SNDRV_SEQ_PORT_FLG_TIME_REAL	(1<<2)
+
+struct snd_seq_port_info {
+	struct snd_seq_addr addr;	/* client/port numbers */
+	char name[64];			/* port name */
+
+	unsigned int capability;	/* port capability bits */
+	unsigned int type;		/* port type bits */
+	int midi_channels;		/* channels per MIDI port */
+	int midi_voices;		/* voices per MIDI port */
+	int synth_voices;		/* voices per SYNTH port */
+
+	int read_use;			/* R/O: subscribers for output (from this port) */
+	int write_use;			/* R/O: subscribers for input (to this port) */
+
+	void *kernel;			/* reserved for kernel use (must be NULL) */
+	unsigned int flags;		/* misc. conditioning */
+	unsigned char time_queue;	/* queue # for timestamping */
+	char reserved[59];		/* for future use */
+};
+
+
+/* queue flags */
+#define SNDRV_SEQ_QUEUE_FLG_SYNC	(1<<0)	/* sync enabled */
+
+/* queue information */
+struct snd_seq_queue_info {
+	int queue;		/* queue id */
+
+	/*
+	 *  security settings, only owner of this queue can start/stop timer
+	 *  etc. if the queue is locked for other clients
+	 */
+	int owner;		/* client id for owner of the queue */
+	unsigned locked:1;	/* timing queue locked for other queues */
+	char name[64];		/* name of this queue */
+	unsigned int flags;	/* flags */
+	char reserved[60];	/* for future use */
+
+};
+
+/* queue info/status */
+struct snd_seq_queue_status {
+	int queue;			/* queue id */
+	int events;			/* read-only - queue size */
+	snd_seq_tick_time_t tick;	/* current tick */
+	struct snd_seq_real_time time;	/* current time */
+	int running;			/* running state of queue */
+	int flags;			/* various flags */
+	char reserved[64];		/* for the future */
+};
+
+
+/* queue tempo */
+struct snd_seq_queue_tempo {
+	int queue;			/* sequencer queue */
+	unsigned int tempo;		/* current tempo, us/tick */
+	int ppq;			/* time resolution, ticks/quarter */
+	unsigned int skew_value;	/* queue skew */
+	unsigned int skew_base;		/* queue skew base */
+	char reserved[24];		/* for the future */
+};
+
+
+/* sequencer timer sources */
+#define SNDRV_SEQ_TIMER_ALSA		0	/* ALSA timer */
+#define SNDRV_SEQ_TIMER_MIDI_CLOCK	1	/* Midi Clock (CLOCK event) */
+#define SNDRV_SEQ_TIMER_MIDI_TICK	2	/* Midi Timer Tick (TICK event) */
+
+/* queue timer info */
+struct snd_seq_queue_timer {
+	int queue;			/* sequencer queue */
+	int type;			/* source timer type */
+	union {
+		struct {
+			struct snd_timer_id id;	/* ALSA's timer ID */
+			unsigned int resolution;	/* resolution in Hz */
+		} alsa;
+	} u;
+	char reserved[64];		/* for the future use */
+};
+
+
+struct snd_seq_queue_client {
+	int queue;		/* sequencer queue */
+	int client;		/* sequencer client */
+	int used;		/* queue is used with this client
+				   (must be set for accepting events) */
+	/* per client watermarks */
+	char reserved[64];	/* for future use */
+};
+
+
+#define SNDRV_SEQ_PORT_SUBS_EXCLUSIVE	(1<<0)	/* exclusive connection */
+#define SNDRV_SEQ_PORT_SUBS_TIMESTAMP	(1<<1)
+#define SNDRV_SEQ_PORT_SUBS_TIME_REAL	(1<<2)
+
+struct snd_seq_port_subscribe {
+	struct snd_seq_addr sender;	/* sender address */
+	struct snd_seq_addr dest;	/* destination address */
+	unsigned int voices;		/* number of voices to be allocated (0 = don't care) */
+	unsigned int flags;		/* modes */
+	unsigned char queue;		/* input time-stamp queue (optional) */
+	unsigned char pad[3];		/* reserved */
+	char reserved[64];
+};
+
+/* type of query subscription */
+#define SNDRV_SEQ_QUERY_SUBS_READ	0
+#define SNDRV_SEQ_QUERY_SUBS_WRITE	1
+
+struct snd_seq_query_subs {
+	struct snd_seq_addr root;	/* client/port id to be searched */
+	int type;		/* READ or WRITE */
+	int index;		/* 0..N-1 */
+	int num_subs;		/* R/O: number of subscriptions on this port */
+	struct snd_seq_addr addr;	/* R/O: result */
+	unsigned char queue;	/* R/O: result */
+	unsigned int flags;	/* R/O: result */
+	char reserved[64];	/* for future use */
+};
+
+
+/*
+ *  IOCTL commands
+ */
+
+#define SNDRV_SEQ_IOCTL_PVERSION	_IOR ('S', 0x00, int)
+#define SNDRV_SEQ_IOCTL_CLIENT_ID	_IOR ('S', 0x01, int)
+#define SNDRV_SEQ_IOCTL_SYSTEM_INFO	_IOWR('S', 0x02, struct snd_seq_system_info)
+#define SNDRV_SEQ_IOCTL_RUNNING_MODE	_IOWR('S', 0x03, struct snd_seq_running_info)
+
+#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO	_IOWR('S', 0x10, struct snd_seq_client_info)
+#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO	_IOW ('S', 0x11, struct snd_seq_client_info)
+
+#define SNDRV_SEQ_IOCTL_CREATE_PORT	_IOWR('S', 0x20, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_DELETE_PORT	_IOW ('S', 0x21, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_GET_PORT_INFO	_IOWR('S', 0x22, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_SET_PORT_INFO	_IOW ('S', 0x23, struct snd_seq_port_info)
+
+#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT	_IOW ('S', 0x30, struct snd_seq_port_subscribe)
+#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct snd_seq_port_subscribe)
+
+#define SNDRV_SEQ_IOCTL_CREATE_QUEUE	_IOWR('S', 0x32, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_DELETE_QUEUE	_IOW ('S', 0x33, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO	_IOWR('S', 0x34, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO	_IOWR('S', 0x35, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE	_IOWR('S', 0x36, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct snd_seq_queue_status)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO	_IOWR('S', 0x41, struct snd_seq_queue_tempo)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO	_IOW ('S', 0x42, struct snd_seq_queue_tempo)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER	_IOWR('S', 0x43, struct snd_seq_queue_owner)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER	_IOW ('S', 0x44, struct snd_seq_queue_owner)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER	_IOWR('S', 0x45, struct snd_seq_queue_timer)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER	_IOW ('S', 0x46, struct snd_seq_queue_timer)
+/* XXX
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC	_IOWR('S', 0x53, struct snd_seq_queue_sync)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC	_IOW ('S', 0x54, struct snd_seq_queue_sync)
+*/
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT	_IOWR('S', 0x49, struct snd_seq_queue_client)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT	_IOW ('S', 0x4a, struct snd_seq_queue_client)
+#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL	_IOWR('S', 0x4b, struct snd_seq_client_pool)
+#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL	_IOW ('S', 0x4c, struct snd_seq_client_pool)
+#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS	_IOW ('S', 0x4e, struct snd_seq_remove_events)
+#define SNDRV_SEQ_IOCTL_QUERY_SUBS	_IOWR('S', 0x4f, struct snd_seq_query_subs)
+#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION	_IOWR('S', 0x50, struct snd_seq_port_subscribe)
+#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT	_IOWR('S', 0x51, struct snd_seq_client_info)
+#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT	_IOWR('S', 0x52, struct snd_seq_port_info)
+
+#endif /* _UAPI__SOUND_ASEQUENCER_H */
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
new file mode 100644
index 0000000..1774a5c
--- /dev/null
+++ b/include/uapi/sound/asound.h
@@ -0,0 +1,971 @@
+/*
+ *  Advanced Linux Sound Architecture - ALSA - Driver
+ *  Copyright (c) 1994-2003 by Jaroslav Kysela <perex@perex.cz>,
+ *                             Abramo Bagnara <abramo@alsa-project.org>
+ *
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef _UAPI__SOUND_ASOUND_H
+#define _UAPI__SOUND_ASOUND_H
+
+#include <linux/types.h>
+
+
+/*
+ *  protocol version
+ */
+
+#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
+#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
+#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
+#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
+#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) \
+	(SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || \
+	 (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && \
+	   SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
+
+/****************************************************************************
+ *                                                                          *
+ *        Digital audio interface					    *
+ *                                                                          *
+ ****************************************************************************/
+
+struct snd_aes_iec958 {
+	unsigned char status[24];	/* AES/IEC958 channel status bits */
+	unsigned char subcode[147];	/* AES/IEC958 subcode bits */
+	unsigned char pad;		/* nothing */
+	unsigned char dig_subframe[4];	/* AES/IEC958 subframe bits */
+};
+
+/****************************************************************************
+ *                                                                          *
+ *        CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort		    *
+ *                                                                          *
+ ****************************************************************************/
+
+struct snd_cea_861_aud_if {
+	unsigned char db1_ct_cc; /* coding type and channel count */
+	unsigned char db2_sf_ss; /* sample frequency and size */
+	unsigned char db3; /* not used, all zeros */
+	unsigned char db4_ca; /* channel allocation code */
+	unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */
+};
+
+/****************************************************************************
+ *                                                                          *
+ *      Section for driver hardware dependent interface - /dev/snd/hw?      *
+ *                                                                          *
+ ****************************************************************************/
+
+#define SNDRV_HWDEP_VERSION		SNDRV_PROTOCOL_VERSION(1, 0, 1)
+
+enum {
+	SNDRV_HWDEP_IFACE_OPL2 = 0,
+	SNDRV_HWDEP_IFACE_OPL3,
+	SNDRV_HWDEP_IFACE_OPL4,
+	SNDRV_HWDEP_IFACE_SB16CSP,	/* Creative Signal Processor */
+	SNDRV_HWDEP_IFACE_EMU10K1,	/* FX8010 processor in EMU10K1 chip */
+	SNDRV_HWDEP_IFACE_YSS225,	/* Yamaha FX processor */
+	SNDRV_HWDEP_IFACE_ICS2115,	/* Wavetable synth */
+	SNDRV_HWDEP_IFACE_SSCAPE,	/* Ensoniq SoundScape ISA card (MC68EC000) */
+	SNDRV_HWDEP_IFACE_VX,		/* Digigram VX cards */
+	SNDRV_HWDEP_IFACE_MIXART,	/* Digigram miXart cards */
+	SNDRV_HWDEP_IFACE_USX2Y,	/* Tascam US122, US224 & US428 usb */
+	SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */	
+	SNDRV_HWDEP_IFACE_BLUETOOTH,	/* Bluetooth audio */
+	SNDRV_HWDEP_IFACE_USX2Y_PCM,	/* Tascam US122, US224 & US428 rawusb pcm */
+	SNDRV_HWDEP_IFACE_PCXHR,	/* Digigram PCXHR */
+	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 */
+
+	/* Don't forget to change the following: */
+	SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
+};
+
+struct snd_hwdep_info {
+	unsigned int device;		/* WR: device number */
+	int card;			/* R: card number */
+	unsigned char id[64];		/* ID (user selectable) */
+	unsigned char name[80];		/* hwdep name */
+	int iface;			/* hwdep interface */
+	unsigned char reserved[64];	/* reserved for future */
+};
+
+/* generic DSP loader */
+struct snd_hwdep_dsp_status {
+	unsigned int version;		/* R: driver-specific version */
+	unsigned char id[32];		/* R: driver-specific ID string */
+	unsigned int num_dsps;		/* R: number of DSP images to transfer */
+	unsigned int dsp_loaded;	/* R: bit flags indicating the loaded DSPs */
+	unsigned int chip_ready;	/* R: 1 = initialization finished */
+	unsigned char reserved[16];	/* reserved for future use */
+};
+
+struct snd_hwdep_dsp_image {
+	unsigned int index;		/* W: DSP index */
+	unsigned char name[64];		/* W: ID (e.g. file name) */
+	unsigned char __user *image;	/* W: binary image */
+	size_t length;			/* W: size of image in bytes */
+	unsigned long driver_data;	/* W: driver-specific data */
+};
+
+#define SNDRV_HWDEP_IOCTL_PVERSION	_IOR ('H', 0x00, int)
+#define SNDRV_HWDEP_IOCTL_INFO		_IOR ('H', 0x01, struct snd_hwdep_info)
+#define SNDRV_HWDEP_IOCTL_DSP_STATUS	_IOR('H', 0x02, struct snd_hwdep_dsp_status)
+#define SNDRV_HWDEP_IOCTL_DSP_LOAD	_IOW('H', 0x03, struct snd_hwdep_dsp_image)
+
+/*****************************************************************************
+ *                                                                           *
+ *             Digital Audio (PCM) interface - /dev/snd/pcm??                *
+ *                                                                           *
+ *****************************************************************************/
+
+#define SNDRV_PCM_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 11)
+
+typedef unsigned long snd_pcm_uframes_t;
+typedef signed long snd_pcm_sframes_t;
+
+enum {
+	SNDRV_PCM_CLASS_GENERIC = 0,	/* standard mono or stereo device */
+	SNDRV_PCM_CLASS_MULTI,		/* multichannel device */
+	SNDRV_PCM_CLASS_MODEM,		/* software modem class */
+	SNDRV_PCM_CLASS_DIGITIZER,	/* digitizer class */
+	/* Don't forget to change the following: */
+	SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
+};
+
+enum {
+	SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */
+	SNDRV_PCM_SUBCLASS_MULTI_MIX,	/* multichannel subdevices are mixed together */
+	/* Don't forget to change the following: */
+	SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
+};
+
+enum {
+	SNDRV_PCM_STREAM_PLAYBACK = 0,
+	SNDRV_PCM_STREAM_CAPTURE,
+	SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
+};
+
+typedef int __bitwise snd_pcm_access_t;
+#define	SNDRV_PCM_ACCESS_MMAP_INTERLEAVED	((__force snd_pcm_access_t) 0) /* interleaved mmap */
+#define	SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED	((__force snd_pcm_access_t) 1) /* noninterleaved mmap */
+#define	SNDRV_PCM_ACCESS_MMAP_COMPLEX		((__force snd_pcm_access_t) 2) /* complex mmap */
+#define	SNDRV_PCM_ACCESS_RW_INTERLEAVED		((__force snd_pcm_access_t) 3) /* readi/writei */
+#define	SNDRV_PCM_ACCESS_RW_NONINTERLEAVED	((__force snd_pcm_access_t) 4) /* readn/writen */
+#define	SNDRV_PCM_ACCESS_LAST		SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
+
+typedef int __bitwise snd_pcm_format_t;
+#define	SNDRV_PCM_FORMAT_S8	((__force snd_pcm_format_t) 0)
+#define	SNDRV_PCM_FORMAT_U8	((__force snd_pcm_format_t) 1)
+#define	SNDRV_PCM_FORMAT_S16_LE	((__force snd_pcm_format_t) 2)
+#define	SNDRV_PCM_FORMAT_S16_BE	((__force snd_pcm_format_t) 3)
+#define	SNDRV_PCM_FORMAT_U16_LE	((__force snd_pcm_format_t) 4)
+#define	SNDRV_PCM_FORMAT_U16_BE	((__force snd_pcm_format_t) 5)
+#define	SNDRV_PCM_FORMAT_S24_LE	((__force snd_pcm_format_t) 6) /* low three bytes */
+#define	SNDRV_PCM_FORMAT_S24_BE	((__force snd_pcm_format_t) 7) /* low three bytes */
+#define	SNDRV_PCM_FORMAT_U24_LE	((__force snd_pcm_format_t) 8) /* low three bytes */
+#define	SNDRV_PCM_FORMAT_U24_BE	((__force snd_pcm_format_t) 9) /* low three bytes */
+#define	SNDRV_PCM_FORMAT_S32_LE	((__force snd_pcm_format_t) 10)
+#define	SNDRV_PCM_FORMAT_S32_BE	((__force snd_pcm_format_t) 11)
+#define	SNDRV_PCM_FORMAT_U32_LE	((__force snd_pcm_format_t) 12)
+#define	SNDRV_PCM_FORMAT_U32_BE	((__force snd_pcm_format_t) 13)
+#define	SNDRV_PCM_FORMAT_FLOAT_LE	((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
+#define	SNDRV_PCM_FORMAT_FLOAT_BE	((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
+#define	SNDRV_PCM_FORMAT_FLOAT64_LE	((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
+#define	SNDRV_PCM_FORMAT_FLOAT64_BE	((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
+#define	SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */
+#define	SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */
+#define	SNDRV_PCM_FORMAT_MU_LAW		((__force snd_pcm_format_t) 20)
+#define	SNDRV_PCM_FORMAT_A_LAW		((__force snd_pcm_format_t) 21)
+#define	SNDRV_PCM_FORMAT_IMA_ADPCM	((__force snd_pcm_format_t) 22)
+#define	SNDRV_PCM_FORMAT_MPEG		((__force snd_pcm_format_t) 23)
+#define	SNDRV_PCM_FORMAT_GSM		((__force snd_pcm_format_t) 24)
+#define	SNDRV_PCM_FORMAT_SPECIAL	((__force snd_pcm_format_t) 31)
+#define	SNDRV_PCM_FORMAT_S24_3LE	((__force snd_pcm_format_t) 32)	/* in three bytes */
+#define	SNDRV_PCM_FORMAT_S24_3BE	((__force snd_pcm_format_t) 33)	/* in three bytes */
+#define	SNDRV_PCM_FORMAT_U24_3LE	((__force snd_pcm_format_t) 34)	/* in three bytes */
+#define	SNDRV_PCM_FORMAT_U24_3BE	((__force snd_pcm_format_t) 35)	/* in three bytes */
+#define	SNDRV_PCM_FORMAT_S20_3LE	((__force snd_pcm_format_t) 36)	/* in three bytes */
+#define	SNDRV_PCM_FORMAT_S20_3BE	((__force snd_pcm_format_t) 37)	/* in three bytes */
+#define	SNDRV_PCM_FORMAT_U20_3LE	((__force snd_pcm_format_t) 38)	/* in three bytes */
+#define	SNDRV_PCM_FORMAT_U20_3BE	((__force snd_pcm_format_t) 39)	/* in three bytes */
+#define	SNDRV_PCM_FORMAT_S18_3LE	((__force snd_pcm_format_t) 40)	/* in three bytes */
+#define	SNDRV_PCM_FORMAT_S18_3BE	((__force snd_pcm_format_t) 41)	/* in three bytes */
+#define	SNDRV_PCM_FORMAT_U18_3LE	((__force snd_pcm_format_t) 42)	/* in three bytes */
+#define	SNDRV_PCM_FORMAT_U18_3BE	((__force snd_pcm_format_t) 43)	/* in three bytes */
+#define	SNDRV_PCM_FORMAT_G723_24	((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */
+#define	SNDRV_PCM_FORMAT_G723_24_1B	((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
+#define	SNDRV_PCM_FORMAT_G723_40	((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
+#define	SNDRV_PCM_FORMAT_G723_40_1B	((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
+#define	SNDRV_PCM_FORMAT_LAST		SNDRV_PCM_FORMAT_G723_40_1B
+
+#ifdef SNDRV_LITTLE_ENDIAN
+#define	SNDRV_PCM_FORMAT_S16		SNDRV_PCM_FORMAT_S16_LE
+#define	SNDRV_PCM_FORMAT_U16		SNDRV_PCM_FORMAT_U16_LE
+#define	SNDRV_PCM_FORMAT_S24		SNDRV_PCM_FORMAT_S24_LE
+#define	SNDRV_PCM_FORMAT_U24		SNDRV_PCM_FORMAT_U24_LE
+#define	SNDRV_PCM_FORMAT_S32		SNDRV_PCM_FORMAT_S32_LE
+#define	SNDRV_PCM_FORMAT_U32		SNDRV_PCM_FORMAT_U32_LE
+#define	SNDRV_PCM_FORMAT_FLOAT		SNDRV_PCM_FORMAT_FLOAT_LE
+#define	SNDRV_PCM_FORMAT_FLOAT64	SNDRV_PCM_FORMAT_FLOAT64_LE
+#define	SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
+#endif
+#ifdef SNDRV_BIG_ENDIAN
+#define	SNDRV_PCM_FORMAT_S16		SNDRV_PCM_FORMAT_S16_BE
+#define	SNDRV_PCM_FORMAT_U16		SNDRV_PCM_FORMAT_U16_BE
+#define	SNDRV_PCM_FORMAT_S24		SNDRV_PCM_FORMAT_S24_BE
+#define	SNDRV_PCM_FORMAT_U24		SNDRV_PCM_FORMAT_U24_BE
+#define	SNDRV_PCM_FORMAT_S32		SNDRV_PCM_FORMAT_S32_BE
+#define	SNDRV_PCM_FORMAT_U32		SNDRV_PCM_FORMAT_U32_BE
+#define	SNDRV_PCM_FORMAT_FLOAT		SNDRV_PCM_FORMAT_FLOAT_BE
+#define	SNDRV_PCM_FORMAT_FLOAT64	SNDRV_PCM_FORMAT_FLOAT64_BE
+#define	SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
+#endif
+
+typedef int __bitwise snd_pcm_subformat_t;
+#define	SNDRV_PCM_SUBFORMAT_STD		((__force snd_pcm_subformat_t) 0)
+#define	SNDRV_PCM_SUBFORMAT_LAST	SNDRV_PCM_SUBFORMAT_STD
+
+#define SNDRV_PCM_INFO_MMAP		0x00000001	/* hardware supports mmap */
+#define SNDRV_PCM_INFO_MMAP_VALID	0x00000002	/* period data are valid during transfer */
+#define SNDRV_PCM_INFO_DOUBLE		0x00000004	/* Double buffering needed for PCM start/stop */
+#define SNDRV_PCM_INFO_BATCH		0x00000010	/* double buffering */
+#define SNDRV_PCM_INFO_INTERLEAVED	0x00000100	/* channels are interleaved */
+#define SNDRV_PCM_INFO_NONINTERLEAVED	0x00000200	/* channels are not interleaved */
+#define SNDRV_PCM_INFO_COMPLEX		0x00000400	/* complex frame organization (mmap only) */
+#define SNDRV_PCM_INFO_BLOCK_TRANSFER	0x00010000	/* hardware transfer block of samples */
+#define SNDRV_PCM_INFO_OVERRANGE	0x00020000	/* hardware supports ADC (capture) overrange detection */
+#define SNDRV_PCM_INFO_RESUME		0x00040000	/* hardware supports stream resume after suspend */
+#define SNDRV_PCM_INFO_PAUSE		0x00080000	/* pause ioctl is supported */
+#define SNDRV_PCM_INFO_HALF_DUPLEX	0x00100000	/* only half duplex */
+#define SNDRV_PCM_INFO_JOINT_DUPLEX	0x00200000	/* playback and capture stream are somewhat correlated */
+#define SNDRV_PCM_INFO_SYNC_START	0x00400000	/* pcm support some kind of sync go */
+#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP	0x00800000	/* period wakeup can be disabled */
+#define SNDRV_PCM_INFO_HAS_WALL_CLOCK   0x01000000      /* has audio wall clock for audio/system time sync */
+#define SNDRV_PCM_INFO_FIFO_IN_FRAMES	0x80000000	/* internal kernel flag - FIFO size is in frames */
+
+typedef int __bitwise snd_pcm_state_t;
+#define	SNDRV_PCM_STATE_OPEN		((__force snd_pcm_state_t) 0) /* stream is open */
+#define	SNDRV_PCM_STATE_SETUP		((__force snd_pcm_state_t) 1) /* stream has a setup */
+#define	SNDRV_PCM_STATE_PREPARED	((__force snd_pcm_state_t) 2) /* stream is ready to start */
+#define	SNDRV_PCM_STATE_RUNNING		((__force snd_pcm_state_t) 3) /* stream is running */
+#define	SNDRV_PCM_STATE_XRUN		((__force snd_pcm_state_t) 4) /* stream reached an xrun */
+#define	SNDRV_PCM_STATE_DRAINING	((__force snd_pcm_state_t) 5) /* stream is draining */
+#define	SNDRV_PCM_STATE_PAUSED		((__force snd_pcm_state_t) 6) /* stream is paused */
+#define	SNDRV_PCM_STATE_SUSPENDED	((__force snd_pcm_state_t) 7) /* hardware is suspended */
+#define	SNDRV_PCM_STATE_DISCONNECTED	((__force snd_pcm_state_t) 8) /* hardware is disconnected */
+#define	SNDRV_PCM_STATE_LAST		SNDRV_PCM_STATE_DISCONNECTED
+
+enum {
+	SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
+	SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
+	SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
+};
+
+union snd_pcm_sync_id {
+	unsigned char id[16];
+	unsigned short id16[8];
+	unsigned int id32[4];
+};
+
+struct snd_pcm_info {
+	unsigned int device;		/* RO/WR (control): device number */
+	unsigned int subdevice;		/* RO/WR (control): subdevice number */
+	int stream;			/* RO/WR (control): stream direction */
+	int card;			/* R: card number */
+	unsigned char id[64];		/* ID (user selectable) */
+	unsigned char name[80];		/* name of this device */
+	unsigned char subname[32];	/* subdevice name */
+	int dev_class;			/* SNDRV_PCM_CLASS_* */
+	int dev_subclass;		/* SNDRV_PCM_SUBCLASS_* */
+	unsigned int subdevices_count;
+	unsigned int subdevices_avail;
+	union snd_pcm_sync_id sync;	/* hardware synchronization ID */
+	unsigned char reserved[64];	/* reserved for future... */
+};
+
+typedef int snd_pcm_hw_param_t;
+#define	SNDRV_PCM_HW_PARAM_ACCESS	0	/* Access type */
+#define	SNDRV_PCM_HW_PARAM_FORMAT	1	/* Format */
+#define	SNDRV_PCM_HW_PARAM_SUBFORMAT	2	/* Subformat */
+#define	SNDRV_PCM_HW_PARAM_FIRST_MASK	SNDRV_PCM_HW_PARAM_ACCESS
+#define	SNDRV_PCM_HW_PARAM_LAST_MASK	SNDRV_PCM_HW_PARAM_SUBFORMAT
+
+#define	SNDRV_PCM_HW_PARAM_SAMPLE_BITS	8	/* Bits per sample */
+#define	SNDRV_PCM_HW_PARAM_FRAME_BITS	9	/* Bits per frame */
+#define	SNDRV_PCM_HW_PARAM_CHANNELS	10	/* Channels */
+#define	SNDRV_PCM_HW_PARAM_RATE		11	/* Approx rate */
+#define	SNDRV_PCM_HW_PARAM_PERIOD_TIME	12	/* Approx distance between
+						 * interrupts in us
+						 */
+#define	SNDRV_PCM_HW_PARAM_PERIOD_SIZE	13	/* Approx frames between
+						 * interrupts
+						 */
+#define	SNDRV_PCM_HW_PARAM_PERIOD_BYTES	14	/* Approx bytes between
+						 * interrupts
+						 */
+#define	SNDRV_PCM_HW_PARAM_PERIODS	15	/* Approx interrupts per
+						 * buffer
+						 */
+#define	SNDRV_PCM_HW_PARAM_BUFFER_TIME	16	/* Approx duration of buffer
+						 * in us
+						 */
+#define	SNDRV_PCM_HW_PARAM_BUFFER_SIZE	17	/* Size of buffer in frames */
+#define	SNDRV_PCM_HW_PARAM_BUFFER_BYTES	18	/* Size of buffer in bytes */
+#define	SNDRV_PCM_HW_PARAM_TICK_TIME	19	/* Approx tick duration in us */
+#define	SNDRV_PCM_HW_PARAM_FIRST_INTERVAL	SNDRV_PCM_HW_PARAM_SAMPLE_BITS
+#define	SNDRV_PCM_HW_PARAM_LAST_INTERVAL	SNDRV_PCM_HW_PARAM_TICK_TIME
+
+#define SNDRV_PCM_HW_PARAMS_NORESAMPLE	(1<<0)	/* avoid rate resampling */
+#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER	(1<<1)	/* export buffer */
+#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP	(1<<2)	/* disable period wakeups */
+
+struct snd_interval {
+	unsigned int min, max;
+	unsigned int openmin:1,
+		     openmax:1,
+		     integer:1,
+		     empty:1;
+};
+
+#define SNDRV_MASK_MAX	256
+
+struct snd_mask {
+	__u32 bits[(SNDRV_MASK_MAX+31)/32];
+};
+
+struct snd_pcm_hw_params {
+	unsigned int flags;
+	struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - 
+			       SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
+	struct snd_mask mres[5];	/* reserved masks */
+	struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
+				        SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
+	struct snd_interval ires[9];	/* reserved intervals */
+	unsigned int rmask;		/* W: requested masks */
+	unsigned int cmask;		/* R: changed masks */
+	unsigned int info;		/* R: Info flags for returned setup */
+	unsigned int msbits;		/* R: used most significant bits */
+	unsigned int rate_num;		/* R: rate numerator */
+	unsigned int rate_den;		/* R: rate denominator */
+	snd_pcm_uframes_t fifo_size;	/* R: chip FIFO size in frames */
+	unsigned char reserved[64];	/* reserved for future */
+};
+
+enum {
+	SNDRV_PCM_TSTAMP_NONE = 0,
+	SNDRV_PCM_TSTAMP_ENABLE,
+	SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
+};
+
+struct snd_pcm_sw_params {
+	int tstamp_mode;			/* timestamp mode */
+	unsigned int period_step;
+	unsigned int sleep_min;			/* min ticks to sleep */
+	snd_pcm_uframes_t avail_min;		/* min avail frames for wakeup */
+	snd_pcm_uframes_t xfer_align;		/* obsolete: xfer size need to be a multiple */
+	snd_pcm_uframes_t start_threshold;	/* min hw_avail frames for automatic start */
+	snd_pcm_uframes_t stop_threshold;	/* min avail frames for automatic stop */
+	snd_pcm_uframes_t silence_threshold;	/* min distance from noise for silence filling */
+	snd_pcm_uframes_t silence_size;		/* silence block size */
+	snd_pcm_uframes_t boundary;		/* pointers wrap point */
+	unsigned char reserved[64];		/* reserved for future */
+};
+
+struct snd_pcm_channel_info {
+	unsigned int channel;
+	__kernel_off_t offset;		/* mmap offset */
+	unsigned int first;		/* offset to first sample in bits */
+	unsigned int step;		/* samples distance in bits */
+};
+
+struct snd_pcm_status {
+	snd_pcm_state_t state;		/* stream state */
+	struct timespec trigger_tstamp;	/* time when stream was started/stopped/paused */
+	struct timespec tstamp;		/* reference timestamp */
+	snd_pcm_uframes_t appl_ptr;	/* appl ptr */
+	snd_pcm_uframes_t hw_ptr;	/* hw ptr */
+	snd_pcm_sframes_t delay;	/* current delay in frames */
+	snd_pcm_uframes_t avail;	/* number of frames available */
+	snd_pcm_uframes_t avail_max;	/* max frames available on hw since last status */
+	snd_pcm_uframes_t overrange;	/* count of ADC (capture) overrange detections from last status */
+	snd_pcm_state_t suspended_state; /* suspended stream state */
+	__u32 reserved_alignment;	/* must be filled with zero */
+	struct timespec audio_tstamp;	/* from sample counter or wall clock */
+	unsigned char reserved[56-sizeof(struct timespec)]; /* must be filled with zero */
+};
+
+struct snd_pcm_mmap_status {
+	snd_pcm_state_t state;		/* RO: state - SNDRV_PCM_STATE_XXXX */
+	int pad1;			/* Needed for 64 bit alignment */
+	snd_pcm_uframes_t hw_ptr;	/* RO: hw ptr (0...boundary-1) */
+	struct timespec tstamp;		/* Timestamp */
+	snd_pcm_state_t suspended_state; /* RO: suspended stream state */
+	struct timespec audio_tstamp;	/* from sample counter or wall clock */
+};
+
+struct snd_pcm_mmap_control {
+	snd_pcm_uframes_t appl_ptr;	/* RW: appl ptr (0...boundary-1) */
+	snd_pcm_uframes_t avail_min;	/* RW: min available frames for wakeup */
+};
+
+#define SNDRV_PCM_SYNC_PTR_HWSYNC	(1<<0)	/* execute hwsync */
+#define SNDRV_PCM_SYNC_PTR_APPL		(1<<1)	/* get appl_ptr from driver (r/w op) */
+#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN	(1<<2)	/* get avail_min from driver */
+
+struct snd_pcm_sync_ptr {
+	unsigned int flags;
+	union {
+		struct snd_pcm_mmap_status status;
+		unsigned char reserved[64];
+	} s;
+	union {
+		struct snd_pcm_mmap_control control;
+		unsigned char reserved[64];
+	} c;
+};
+
+struct snd_xferi {
+	snd_pcm_sframes_t result;
+	void __user *buf;
+	snd_pcm_uframes_t frames;
+};
+
+struct snd_xfern {
+	snd_pcm_sframes_t result;
+	void __user * __user *bufs;
+	snd_pcm_uframes_t frames;
+};
+
+enum {
+	SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0,	/* gettimeofday equivalent */
+	SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,	/* posix_clock_monotonic equivalent */
+	SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
+};
+
+/* channel positions */
+enum {
+	SNDRV_CHMAP_UNKNOWN = 0,
+	SNDRV_CHMAP_NA,		/* N/A, silent */
+	SNDRV_CHMAP_MONO,	/* mono stream */
+	/* this follows the alsa-lib mixer channel value + 3 */
+	SNDRV_CHMAP_FL,		/* front left */
+	SNDRV_CHMAP_FR,		/* front right */
+	SNDRV_CHMAP_RL,		/* rear left */
+	SNDRV_CHMAP_RR,		/* rear right */
+	SNDRV_CHMAP_FC,		/* front center */
+	SNDRV_CHMAP_LFE,	/* LFE */
+	SNDRV_CHMAP_SL,		/* side left */
+	SNDRV_CHMAP_SR,		/* side right */
+	SNDRV_CHMAP_RC,		/* rear center */
+	/* new definitions */
+	SNDRV_CHMAP_FLC,	/* front left center */
+	SNDRV_CHMAP_FRC,	/* front right center */
+	SNDRV_CHMAP_RLC,	/* rear left center */
+	SNDRV_CHMAP_RRC,	/* rear right center */
+	SNDRV_CHMAP_FLW,	/* front left wide */
+	SNDRV_CHMAP_FRW,	/* front right wide */
+	SNDRV_CHMAP_FLH,	/* front left high */
+	SNDRV_CHMAP_FCH,	/* front center high */
+	SNDRV_CHMAP_FRH,	/* front right high */
+	SNDRV_CHMAP_TC,		/* top center */
+	SNDRV_CHMAP_TFL,	/* top front left */
+	SNDRV_CHMAP_TFR,	/* top front right */
+	SNDRV_CHMAP_TFC,	/* top front center */
+	SNDRV_CHMAP_TRL,	/* top rear left */
+	SNDRV_CHMAP_TRR,	/* top rear right */
+	SNDRV_CHMAP_TRC,	/* top rear center */
+	/* new definitions for UAC2 */
+	SNDRV_CHMAP_TFLC,	/* top front left center */
+	SNDRV_CHMAP_TFRC,	/* top front right center */
+	SNDRV_CHMAP_TSL,	/* top side left */
+	SNDRV_CHMAP_TSR,	/* top side right */
+	SNDRV_CHMAP_LLFE,	/* left LFE */
+	SNDRV_CHMAP_RLFE,	/* right LFE */
+	SNDRV_CHMAP_BC,		/* bottom center */
+	SNDRV_CHMAP_BLC,	/* bottom left center */
+	SNDRV_CHMAP_BRC,	/* bottom right center */
+	SNDRV_CHMAP_LAST = SNDRV_CHMAP_BRC,
+};
+
+#define SNDRV_CHMAP_POSITION_MASK	0xffff
+#define SNDRV_CHMAP_PHASE_INVERSE	(0x01 << 16)
+#define SNDRV_CHMAP_DRIVER_SPEC		(0x02 << 16)
+
+#define SNDRV_PCM_IOCTL_PVERSION	_IOR('A', 0x00, int)
+#define SNDRV_PCM_IOCTL_INFO		_IOR('A', 0x01, struct snd_pcm_info)
+#define SNDRV_PCM_IOCTL_TSTAMP		_IOW('A', 0x02, int)
+#define SNDRV_PCM_IOCTL_TTSTAMP		_IOW('A', 0x03, int)
+#define SNDRV_PCM_IOCTL_HW_REFINE	_IOWR('A', 0x10, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_PARAMS	_IOWR('A', 0x11, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_FREE		_IO('A', 0x12)
+#define SNDRV_PCM_IOCTL_SW_PARAMS	_IOWR('A', 0x13, struct snd_pcm_sw_params)
+#define SNDRV_PCM_IOCTL_STATUS		_IOR('A', 0x20, struct snd_pcm_status)
+#define SNDRV_PCM_IOCTL_DELAY		_IOR('A', 0x21, snd_pcm_sframes_t)
+#define SNDRV_PCM_IOCTL_HWSYNC		_IO('A', 0x22)
+#define SNDRV_PCM_IOCTL_SYNC_PTR	_IOWR('A', 0x23, struct snd_pcm_sync_ptr)
+#define SNDRV_PCM_IOCTL_CHANNEL_INFO	_IOR('A', 0x32, struct snd_pcm_channel_info)
+#define SNDRV_PCM_IOCTL_PREPARE		_IO('A', 0x40)
+#define SNDRV_PCM_IOCTL_RESET		_IO('A', 0x41)
+#define SNDRV_PCM_IOCTL_START		_IO('A', 0x42)
+#define SNDRV_PCM_IOCTL_DROP		_IO('A', 0x43)
+#define SNDRV_PCM_IOCTL_DRAIN		_IO('A', 0x44)
+#define SNDRV_PCM_IOCTL_PAUSE		_IOW('A', 0x45, int)
+#define SNDRV_PCM_IOCTL_REWIND		_IOW('A', 0x46, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_RESUME		_IO('A', 0x47)
+#define SNDRV_PCM_IOCTL_XRUN		_IO('A', 0x48)
+#define SNDRV_PCM_IOCTL_FORWARD		_IOW('A', 0x49, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_WRITEI_FRAMES	_IOW('A', 0x50, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_READI_FRAMES	_IOR('A', 0x51, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_WRITEN_FRAMES	_IOW('A', 0x52, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_READN_FRAMES	_IOR('A', 0x53, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_LINK		_IOW('A', 0x60, int)
+#define SNDRV_PCM_IOCTL_UNLINK		_IO('A', 0x61)
+
+/*****************************************************************************
+ *                                                                           *
+ *                            MIDI v1.0 interface                            *
+ *                                                                           *
+ *****************************************************************************/
+
+/*
+ *  Raw MIDI section - /dev/snd/midi??
+ */
+
+#define SNDRV_RAWMIDI_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 0)
+
+enum {
+	SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
+	SNDRV_RAWMIDI_STREAM_INPUT,
+	SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
+};
+
+#define SNDRV_RAWMIDI_INFO_OUTPUT		0x00000001
+#define SNDRV_RAWMIDI_INFO_INPUT		0x00000002
+#define SNDRV_RAWMIDI_INFO_DUPLEX		0x00000004
+
+struct snd_rawmidi_info {
+	unsigned int device;		/* RO/WR (control): device number */
+	unsigned int subdevice;		/* RO/WR (control): subdevice number */
+	int stream;			/* WR: stream */
+	int card;			/* R: card number */
+	unsigned int flags;		/* SNDRV_RAWMIDI_INFO_XXXX */
+	unsigned char id[64];		/* ID (user selectable) */
+	unsigned char name[80];		/* name of device */
+	unsigned char subname[32];	/* name of active or selected subdevice */
+	unsigned int subdevices_count;
+	unsigned int subdevices_avail;
+	unsigned char reserved[64];	/* reserved for future use */
+};
+
+struct snd_rawmidi_params {
+	int stream;
+	size_t buffer_size;		/* queue size in bytes */
+	size_t avail_min;		/* minimum avail bytes for wakeup */
+	unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */
+	unsigned char reserved[16];	/* reserved for future use */
+};
+
+struct snd_rawmidi_status {
+	int stream;
+	struct timespec tstamp;		/* Timestamp */
+	size_t avail;			/* available bytes */
+	size_t xruns;			/* count of overruns since last status (in bytes) */
+	unsigned char reserved[16];	/* reserved for future use */
+};
+
+#define SNDRV_RAWMIDI_IOCTL_PVERSION	_IOR('W', 0x00, int)
+#define SNDRV_RAWMIDI_IOCTL_INFO	_IOR('W', 0x01, struct snd_rawmidi_info)
+#define SNDRV_RAWMIDI_IOCTL_PARAMS	_IOWR('W', 0x10, struct snd_rawmidi_params)
+#define SNDRV_RAWMIDI_IOCTL_STATUS	_IOWR('W', 0x20, struct snd_rawmidi_status)
+#define SNDRV_RAWMIDI_IOCTL_DROP	_IOW('W', 0x30, int)
+#define SNDRV_RAWMIDI_IOCTL_DRAIN	_IOW('W', 0x31, int)
+
+/*
+ *  Timer section - /dev/snd/timer
+ */
+
+#define SNDRV_TIMER_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 6)
+
+enum {
+	SNDRV_TIMER_CLASS_NONE = -1,
+	SNDRV_TIMER_CLASS_SLAVE = 0,
+	SNDRV_TIMER_CLASS_GLOBAL,
+	SNDRV_TIMER_CLASS_CARD,
+	SNDRV_TIMER_CLASS_PCM,
+	SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
+};
+
+/* slave timer classes */
+enum {
+	SNDRV_TIMER_SCLASS_NONE = 0,
+	SNDRV_TIMER_SCLASS_APPLICATION,
+	SNDRV_TIMER_SCLASS_SEQUENCER,		/* alias */
+	SNDRV_TIMER_SCLASS_OSS_SEQUENCER,	/* alias */
+	SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
+};
+
+/* global timers (device member) */
+#define SNDRV_TIMER_GLOBAL_SYSTEM	0
+#define SNDRV_TIMER_GLOBAL_RTC		1
+#define SNDRV_TIMER_GLOBAL_HPET		2
+#define SNDRV_TIMER_GLOBAL_HRTIMER	3
+
+/* info flags */
+#define SNDRV_TIMER_FLG_SLAVE		(1<<0)	/* cannot be controlled */
+
+struct snd_timer_id {
+	int dev_class;
+	int dev_sclass;
+	int card;
+	int device;
+	int subdevice;
+};
+
+struct snd_timer_ginfo {
+	struct snd_timer_id tid;	/* requested timer ID */
+	unsigned int flags;		/* timer flags - SNDRV_TIMER_FLG_* */
+	int card;			/* card number */
+	unsigned char id[64];		/* timer identification */
+	unsigned char name[80];		/* timer name */
+	unsigned long reserved0;	/* reserved for future use */
+	unsigned long resolution;	/* average period resolution in ns */
+	unsigned long resolution_min;	/* minimal period resolution in ns */
+	unsigned long resolution_max;	/* maximal period resolution in ns */
+	unsigned int clients;		/* active timer clients */
+	unsigned char reserved[32];
+};
+
+struct snd_timer_gparams {
+	struct snd_timer_id tid;	/* requested timer ID */
+	unsigned long period_num;	/* requested precise period duration (in seconds) - numerator */
+	unsigned long period_den;	/* requested precise period duration (in seconds) - denominator */
+	unsigned char reserved[32];
+};
+
+struct snd_timer_gstatus {
+	struct snd_timer_id tid;	/* requested timer ID */
+	unsigned long resolution;	/* current period resolution in ns */
+	unsigned long resolution_num;	/* precise current period resolution (in seconds) - numerator */
+	unsigned long resolution_den;	/* precise current period resolution (in seconds) - denominator */
+	unsigned char reserved[32];
+};
+
+struct snd_timer_select {
+	struct snd_timer_id id;	/* bind to timer ID */
+	unsigned char reserved[32];	/* reserved */
+};
+
+struct snd_timer_info {
+	unsigned int flags;		/* timer flags - SNDRV_TIMER_FLG_* */
+	int card;			/* card number */
+	unsigned char id[64];		/* timer identificator */
+	unsigned char name[80];		/* timer name */
+	unsigned long reserved0;	/* reserved for future use */
+	unsigned long resolution;	/* average period resolution in ns */
+	unsigned char reserved[64];	/* reserved */
+};
+
+#define SNDRV_TIMER_PSFLG_AUTO		(1<<0)	/* auto start, otherwise one-shot */
+#define SNDRV_TIMER_PSFLG_EXCLUSIVE	(1<<1)	/* exclusive use, precise start/stop/pause/continue */
+#define SNDRV_TIMER_PSFLG_EARLY_EVENT	(1<<2)	/* write early event to the poll queue */
+
+struct snd_timer_params {
+	unsigned int flags;		/* flags - SNDRV_MIXER_PSFLG_* */
+	unsigned int ticks;		/* requested resolution in ticks */
+	unsigned int queue_size;	/* total size of queue (32-1024) */
+	unsigned int reserved0;		/* reserved, was: failure locations */
+	unsigned int filter;		/* event filter (bitmask of SNDRV_TIMER_EVENT_*) */
+	unsigned char reserved[60];	/* reserved */
+};
+
+struct snd_timer_status {
+	struct timespec tstamp;		/* Timestamp - last update */
+	unsigned int resolution;	/* current period resolution in ns */
+	unsigned int lost;		/* counter of master tick lost */
+	unsigned int overrun;		/* count of read queue overruns */
+	unsigned int queue;		/* used queue size */
+	unsigned char reserved[64];	/* reserved */
+};
+
+#define SNDRV_TIMER_IOCTL_PVERSION	_IOR('T', 0x00, int)
+#define SNDRV_TIMER_IOCTL_NEXT_DEVICE	_IOWR('T', 0x01, struct snd_timer_id)
+#define SNDRV_TIMER_IOCTL_TREAD		_IOW('T', 0x02, int)
+#define SNDRV_TIMER_IOCTL_GINFO		_IOWR('T', 0x03, struct snd_timer_ginfo)
+#define SNDRV_TIMER_IOCTL_GPARAMS	_IOW('T', 0x04, struct snd_timer_gparams)
+#define SNDRV_TIMER_IOCTL_GSTATUS	_IOWR('T', 0x05, struct snd_timer_gstatus)
+#define SNDRV_TIMER_IOCTL_SELECT	_IOW('T', 0x10, struct snd_timer_select)
+#define SNDRV_TIMER_IOCTL_INFO		_IOR('T', 0x11, struct snd_timer_info)
+#define SNDRV_TIMER_IOCTL_PARAMS	_IOW('T', 0x12, struct snd_timer_params)
+#define SNDRV_TIMER_IOCTL_STATUS	_IOR('T', 0x14, struct snd_timer_status)
+/* The following four ioctls are changed since 1.0.9 due to confliction */
+#define SNDRV_TIMER_IOCTL_START		_IO('T', 0xa0)
+#define SNDRV_TIMER_IOCTL_STOP		_IO('T', 0xa1)
+#define SNDRV_TIMER_IOCTL_CONTINUE	_IO('T', 0xa2)
+#define SNDRV_TIMER_IOCTL_PAUSE		_IO('T', 0xa3)
+
+struct snd_timer_read {
+	unsigned int resolution;
+	unsigned int ticks;
+};
+
+enum {
+	SNDRV_TIMER_EVENT_RESOLUTION = 0,	/* val = resolution in ns */
+	SNDRV_TIMER_EVENT_TICK,			/* val = ticks */
+	SNDRV_TIMER_EVENT_START,		/* val = resolution in ns */
+	SNDRV_TIMER_EVENT_STOP,			/* val = 0 */
+	SNDRV_TIMER_EVENT_CONTINUE,		/* val = resolution in ns */
+	SNDRV_TIMER_EVENT_PAUSE,		/* val = 0 */
+	SNDRV_TIMER_EVENT_EARLY,		/* val = 0, early event */
+	SNDRV_TIMER_EVENT_SUSPEND,		/* val = 0 */
+	SNDRV_TIMER_EVENT_RESUME,		/* val = resolution in ns */
+	/* master timer events for slave timer instances */
+	SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
+	SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
+	SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
+	SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
+	SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
+	SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
+};
+
+struct snd_timer_tread {
+	int event;
+	struct timespec tstamp;
+	unsigned int val;
+};
+
+/****************************************************************************
+ *                                                                          *
+ *        Section for driver control interface - /dev/snd/control?          *
+ *                                                                          *
+ ****************************************************************************/
+
+#define SNDRV_CTL_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 7)
+
+struct snd_ctl_card_info {
+	int card;			/* card number */
+	int pad;			/* reserved for future (was type) */
+	unsigned char id[16];		/* ID of card (user selectable) */
+	unsigned char driver[16];	/* Driver name */
+	unsigned char name[32];		/* Short name of soundcard */
+	unsigned char longname[80];	/* name + info text about soundcard */
+	unsigned char reserved_[16];	/* reserved for future (was ID of mixer) */
+	unsigned char mixername[80];	/* visual mixer identification */
+	unsigned char components[128];	/* card components / fine identification, delimited with one space (AC97 etc..) */
+};
+
+typedef int __bitwise snd_ctl_elem_type_t;
+#define	SNDRV_CTL_ELEM_TYPE_NONE	((__force snd_ctl_elem_type_t) 0) /* invalid */
+#define	SNDRV_CTL_ELEM_TYPE_BOOLEAN	((__force snd_ctl_elem_type_t) 1) /* boolean type */
+#define	SNDRV_CTL_ELEM_TYPE_INTEGER	((__force snd_ctl_elem_type_t) 2) /* integer type */
+#define	SNDRV_CTL_ELEM_TYPE_ENUMERATED	((__force snd_ctl_elem_type_t) 3) /* enumerated type */
+#define	SNDRV_CTL_ELEM_TYPE_BYTES	((__force snd_ctl_elem_type_t) 4) /* byte array */
+#define	SNDRV_CTL_ELEM_TYPE_IEC958	((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */
+#define	SNDRV_CTL_ELEM_TYPE_INTEGER64	((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */
+#define	SNDRV_CTL_ELEM_TYPE_LAST	SNDRV_CTL_ELEM_TYPE_INTEGER64
+
+typedef int __bitwise snd_ctl_elem_iface_t;
+#define	SNDRV_CTL_ELEM_IFACE_CARD	((__force snd_ctl_elem_iface_t) 0) /* global control */
+#define	SNDRV_CTL_ELEM_IFACE_HWDEP	((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */
+#define	SNDRV_CTL_ELEM_IFACE_MIXER	((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */
+#define	SNDRV_CTL_ELEM_IFACE_PCM	((__force snd_ctl_elem_iface_t) 3) /* PCM device */
+#define	SNDRV_CTL_ELEM_IFACE_RAWMIDI	((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */
+#define	SNDRV_CTL_ELEM_IFACE_TIMER	((__force snd_ctl_elem_iface_t) 5) /* timer device */
+#define	SNDRV_CTL_ELEM_IFACE_SEQUENCER	((__force snd_ctl_elem_iface_t) 6) /* sequencer client */
+#define	SNDRV_CTL_ELEM_IFACE_LAST	SNDRV_CTL_ELEM_IFACE_SEQUENCER
+
+#define SNDRV_CTL_ELEM_ACCESS_READ		(1<<0)
+#define SNDRV_CTL_ELEM_ACCESS_WRITE		(1<<1)
+#define SNDRV_CTL_ELEM_ACCESS_READWRITE		(SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
+#define SNDRV_CTL_ELEM_ACCESS_VOLATILE		(1<<2)	/* control value may be changed without a notification */
+#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP		(1<<3)	/* when was control changed */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_READ		(1<<4)	/* TLV read is possible */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE		(1<<5)	/* TLV write is possible */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE	(SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND	(1<<6)	/* TLV command is possible */
+#define SNDRV_CTL_ELEM_ACCESS_INACTIVE		(1<<8)	/* control does actually nothing, but may be updated */
+#define SNDRV_CTL_ELEM_ACCESS_LOCK		(1<<9)	/* write lock */
+#define SNDRV_CTL_ELEM_ACCESS_OWNER		(1<<10)	/* write lock owner */
+#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK	(1<<28)	/* kernel use a TLV callback */ 
+#define SNDRV_CTL_ELEM_ACCESS_USER		(1<<29) /* user space element */
+/* bits 30 and 31 are obsoleted (for indirect access) */
+
+/* for further details see the ACPI and PCI power management specification */
+#define SNDRV_CTL_POWER_D0		0x0000	/* full On */
+#define SNDRV_CTL_POWER_D1		0x0100	/* partial On */
+#define SNDRV_CTL_POWER_D2		0x0200	/* partial On */
+#define SNDRV_CTL_POWER_D3		0x0300	/* Off */
+#define SNDRV_CTL_POWER_D3hot		(SNDRV_CTL_POWER_D3|0x0000)	/* Off, with power */
+#define SNDRV_CTL_POWER_D3cold		(SNDRV_CTL_POWER_D3|0x0001)	/* Off, without power */
+
+struct snd_ctl_elem_id {
+	unsigned int numid;		/* numeric identifier, zero = invalid */
+	snd_ctl_elem_iface_t iface;	/* interface identifier */
+	unsigned int device;		/* device/client number */
+	unsigned int subdevice;		/* subdevice (substream) number */
+	unsigned char name[44];		/* ASCII name of item */
+	unsigned int index;		/* index of item */
+};
+
+struct snd_ctl_elem_list {
+	unsigned int offset;		/* W: first element ID to get */
+	unsigned int space;		/* W: count of element IDs to get */
+	unsigned int used;		/* R: count of element IDs set */
+	unsigned int count;		/* R: count of all elements */
+	struct snd_ctl_elem_id __user *pids; /* R: IDs */
+	unsigned char reserved[50];
+};
+
+struct snd_ctl_elem_info {
+	struct snd_ctl_elem_id id;	/* W: element ID */
+	snd_ctl_elem_type_t type;	/* R: value type - SNDRV_CTL_ELEM_TYPE_* */
+	unsigned int access;		/* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */
+	unsigned int count;		/* count of values */
+	__kernel_pid_t owner;		/* owner's PID of this control */
+	union {
+		struct {
+			long min;		/* R: minimum value */
+			long max;		/* R: maximum value */
+			long step;		/* R: step (0 variable) */
+		} integer;
+		struct {
+			long long min;		/* R: minimum value */
+			long long max;		/* R: maximum value */
+			long long step;		/* R: step (0 variable) */
+		} integer64;
+		struct {
+			unsigned int items;	/* R: number of items */
+			unsigned int item;	/* W: item number */
+			char name[64];		/* R: value name */
+			__u64 names_ptr;	/* W: names list (ELEM_ADD only) */
+			unsigned int names_length;
+		} enumerated;
+		unsigned char reserved[128];
+	} value;
+	union {
+		unsigned short d[4];		/* dimensions */
+		unsigned short *d_ptr;		/* indirect - obsoleted */
+	} dimen;
+	unsigned char reserved[64-4*sizeof(unsigned short)];
+};
+
+struct snd_ctl_elem_value {
+	struct snd_ctl_elem_id id;	/* W: element ID */
+	unsigned int indirect: 1;	/* W: indirect access - obsoleted */
+	union {
+		union {
+			long value[128];
+			long *value_ptr;	/* obsoleted */
+		} integer;
+		union {
+			long long value[64];
+			long long *value_ptr;	/* obsoleted */
+		} integer64;
+		union {
+			unsigned int item[128];
+			unsigned int *item_ptr;	/* obsoleted */
+		} enumerated;
+		union {
+			unsigned char data[512];
+			unsigned char *data_ptr;	/* obsoleted */
+		} bytes;
+		struct snd_aes_iec958 iec958;
+	} value;		/* RO */
+	struct timespec tstamp;
+	unsigned char reserved[128-sizeof(struct timespec)];
+};
+
+struct snd_ctl_tlv {
+	unsigned int numid;	/* control element numeric identification */
+	unsigned int length;	/* in bytes aligned to 4 */
+	unsigned int tlv[0];	/* first TLV */
+};
+
+#define SNDRV_CTL_IOCTL_PVERSION	_IOR('U', 0x00, int)
+#define SNDRV_CTL_IOCTL_CARD_INFO	_IOR('U', 0x01, struct snd_ctl_card_info)
+#define SNDRV_CTL_IOCTL_ELEM_LIST	_IOWR('U', 0x10, struct snd_ctl_elem_list)
+#define SNDRV_CTL_IOCTL_ELEM_INFO	_IOWR('U', 0x11, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_READ	_IOWR('U', 0x12, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_WRITE	_IOWR('U', 0x13, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_LOCK	_IOW('U', 0x14, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_ELEM_UNLOCK	_IOW('U', 0x15, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
+#define SNDRV_CTL_IOCTL_ELEM_ADD	_IOWR('U', 0x17, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REPLACE	_IOWR('U', 0x18, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REMOVE	_IOWR('U', 0x19, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_TLV_READ	_IOWR('U', 0x1a, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_WRITE	_IOWR('U', 0x1b, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_COMMAND	_IOWR('U', 0x1c, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
+#define SNDRV_CTL_IOCTL_HWDEP_INFO	_IOR('U', 0x21, struct snd_hwdep_info)
+#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE	_IOR('U', 0x30, int)
+#define SNDRV_CTL_IOCTL_PCM_INFO	_IOWR('U', 0x31, struct snd_pcm_info)
+#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_INFO	_IOWR('U', 0x41, struct snd_rawmidi_info)
+#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
+#define SNDRV_CTL_IOCTL_POWER		_IOWR('U', 0xd0, int)
+#define SNDRV_CTL_IOCTL_POWER_STATE	_IOR('U', 0xd1, int)
+
+/*
+ *  Read interface.
+ */
+
+enum sndrv_ctl_event_type {
+	SNDRV_CTL_EVENT_ELEM = 0,
+	SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
+};
+
+#define SNDRV_CTL_EVENT_MASK_VALUE	(1<<0)	/* element value was changed */
+#define SNDRV_CTL_EVENT_MASK_INFO	(1<<1)	/* element info was changed */
+#define SNDRV_CTL_EVENT_MASK_ADD	(1<<2)	/* element was added */
+#define SNDRV_CTL_EVENT_MASK_TLV	(1<<3)	/* element TLV tree was changed */
+#define SNDRV_CTL_EVENT_MASK_REMOVE	(~0U)	/* element was removed */
+
+struct snd_ctl_event {
+	int type;	/* event type - SNDRV_CTL_EVENT_* */
+	union {
+		struct {
+			unsigned int mask;
+			struct snd_ctl_elem_id id;
+		} elem;
+		unsigned char data8[60];
+	} data;
+};
+
+/*
+ *  Control names
+ */
+
+#define SNDRV_CTL_NAME_NONE				""
+#define SNDRV_CTL_NAME_PLAYBACK				"Playback "
+#define SNDRV_CTL_NAME_CAPTURE				"Capture "
+
+#define SNDRV_CTL_NAME_IEC958_NONE			""
+#define SNDRV_CTL_NAME_IEC958_SWITCH			"Switch"
+#define SNDRV_CTL_NAME_IEC958_VOLUME			"Volume"
+#define SNDRV_CTL_NAME_IEC958_DEFAULT			"Default"
+#define SNDRV_CTL_NAME_IEC958_MASK			"Mask"
+#define SNDRV_CTL_NAME_IEC958_CON_MASK			"Con Mask"
+#define SNDRV_CTL_NAME_IEC958_PRO_MASK			"Pro Mask"
+#define SNDRV_CTL_NAME_IEC958_PCM_STREAM		"PCM Stream"
+#define SNDRV_CTL_NAME_IEC958(expl,direction,what)	"IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
+
+#endif /* _UAPI__SOUND_ASOUND_H */
diff --git a/include/uapi/sound/asound_fm.h b/include/uapi/sound/asound_fm.h
new file mode 100644
index 0000000..c2a4b96
--- /dev/null
+++ b/include/uapi/sound/asound_fm.h
@@ -0,0 +1,134 @@
+#ifndef __SOUND_ASOUND_FM_H
+#define __SOUND_ASOUND_FM_H
+
+/*
+ *  Advanced Linux Sound Architecture - ALSA
+ *
+ *  Interface file between ALSA driver & user space
+ *  Copyright (c) 1994-98 by Jaroslav Kysela <perex@perex.cz>,
+ *                           4Front Technologies
+ *
+ *  Direct FM control
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#define SNDRV_DM_FM_MODE_OPL2	0x00
+#define SNDRV_DM_FM_MODE_OPL3	0x01
+
+struct snd_dm_fm_info {
+	unsigned char fm_mode;		/* OPL mode, see SNDRV_DM_FM_MODE_XXX */
+	unsigned char rhythm;		/* percussion mode flag */
+};
+
+/*
+ *  Data structure composing an FM "note" or sound event.
+ */
+
+struct snd_dm_fm_voice {
+	unsigned char op;		/* operator cell (0 or 1) */
+	unsigned char voice;		/* FM voice (0 to 17) */
+
+	unsigned char am;		/* amplitude modulation */
+	unsigned char vibrato;		/* vibrato effect */
+	unsigned char do_sustain;	/* sustain phase */
+	unsigned char kbd_scale;	/* keyboard scaling */
+	unsigned char harmonic;		/* 4 bits: harmonic and multiplier */
+	unsigned char scale_level;	/* 2 bits: decrease output freq rises */
+	unsigned char volume;		/* 6 bits: volume */
+
+	unsigned char attack;		/* 4 bits: attack rate */
+	unsigned char decay;		/* 4 bits: decay rate */
+	unsigned char sustain;		/* 4 bits: sustain level */
+	unsigned char release;		/* 4 bits: release rate */
+
+	unsigned char feedback;		/* 3 bits: feedback for op0 */
+	unsigned char connection;	/* 0 for serial, 1 for parallel */
+	unsigned char left;		/* stereo left */
+	unsigned char right;		/* stereo right */
+	unsigned char waveform;		/* 3 bits: waveform shape */
+};
+
+/*
+ *  This describes an FM note by its voice, octave, frequency number (10bit)
+ *  and key on/off.
+ */
+
+struct snd_dm_fm_note {
+	unsigned char voice;	/* 0-17 voice channel */
+	unsigned char octave;	/* 3 bits: what octave to play */
+	unsigned int fnum;	/* 10 bits: frequency number */
+	unsigned char key_on;	/* set for active, clear for silent */
+};
+
+/*
+ *  FM parameters that apply globally to all voices, and thus are not "notes"
+ */
+
+struct snd_dm_fm_params {
+	unsigned char am_depth;		/* amplitude modulation depth (1=hi) */
+	unsigned char vib_depth;	/* vibrato depth (1=hi) */
+	unsigned char kbd_split;	/* keyboard split */
+	unsigned char rhythm;		/* percussion mode select */
+
+	/* This block is the percussion instrument data */
+	unsigned char bass;
+	unsigned char snare;
+	unsigned char tomtom;
+	unsigned char cymbal;
+	unsigned char hihat;
+};
+
+/*
+ *  FM mode ioctl settings
+ */
+
+#define SNDRV_DM_FM_IOCTL_INFO		_IOR('H', 0x20, struct snd_dm_fm_info)
+#define SNDRV_DM_FM_IOCTL_RESET		_IO ('H', 0x21)
+#define SNDRV_DM_FM_IOCTL_PLAY_NOTE	_IOW('H', 0x22, struct snd_dm_fm_note)
+#define SNDRV_DM_FM_IOCTL_SET_VOICE	_IOW('H', 0x23, struct snd_dm_fm_voice)
+#define SNDRV_DM_FM_IOCTL_SET_PARAMS	_IOW('H', 0x24, struct snd_dm_fm_params)
+#define SNDRV_DM_FM_IOCTL_SET_MODE	_IOW('H', 0x25, int)
+/* for OPL3 only */
+#define SNDRV_DM_FM_IOCTL_SET_CONNECTION	_IOW('H', 0x26, int)
+/* SBI patch management */
+#define SNDRV_DM_FM_IOCTL_CLEAR_PATCHES	_IO ('H', 0x40)
+
+#define SNDRV_DM_FM_OSS_IOCTL_RESET		0x20
+#define SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE		0x21
+#define SNDRV_DM_FM_OSS_IOCTL_SET_VOICE		0x22
+#define SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS	0x23
+#define SNDRV_DM_FM_OSS_IOCTL_SET_MODE		0x24
+#define SNDRV_DM_FM_OSS_IOCTL_SET_OPL		0x25
+
+/*
+ * Patch Record - fixed size for write
+ */
+
+#define FM_KEY_SBI	"SBI\032"
+#define FM_KEY_2OP	"2OP\032"
+#define FM_KEY_4OP	"4OP\032"
+
+struct sbi_patch {
+	unsigned char prog;
+	unsigned char bank;
+	char key[4];
+	char name[25];
+	char extension[7];
+	unsigned char data[32];
+};
+
+#endif /* __SOUND_ASOUND_FM_H */
diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h
new file mode 100644
index 0000000..05341a4
--- /dev/null
+++ b/include/uapi/sound/compress_offload.h
@@ -0,0 +1,161 @@
+/*
+ *  compress_offload.h - compress offload header definations
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef __COMPRESS_OFFLOAD_H
+#define __COMPRESS_OFFLOAD_H
+
+#include <linux/types.h>
+#include <sound/asound.h>
+#include <sound/compress_params.h>
+
+
+#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 0)
+/**
+ * struct snd_compressed_buffer: compressed buffer
+ * @fragment_size: size of buffer fragment in bytes
+ * @fragments: number of such fragments
+ */
+struct snd_compressed_buffer {
+	__u32 fragment_size;
+	__u32 fragments;
+};
+
+/**
+ * struct snd_compr_params: compressed stream params
+ * @buffer: buffer description
+ * @codec: codec parameters
+ * @no_wake_mode: dont wake on fragment elapsed
+ */
+struct snd_compr_params {
+	struct snd_compressed_buffer buffer;
+	struct snd_codec codec;
+	__u8 no_wake_mode;
+};
+
+/**
+ * struct snd_compr_tstamp: timestamp descriptor
+ * @byte_offset: Byte offset in ring buffer to DSP
+ * @copied_total: Total number of bytes copied from/to ring buffer to/by DSP
+ * @pcm_frames: Frames decoded or encoded by DSP. This field will evolve by
+ *	large steps and should only be used to monitor encoding/decoding
+ *	progress. It shall not be used for timing estimates.
+ * @pcm_io_frames: Frames rendered or received by DSP into a mixer or an audio
+ * output/input. This field should be used for A/V sync or time estimates.
+ * @sampling_rate: sampling rate of audio
+ */
+struct snd_compr_tstamp {
+	__u32 byte_offset;
+	__u32 copied_total;
+	snd_pcm_uframes_t pcm_frames;
+	snd_pcm_uframes_t pcm_io_frames;
+	__u32 sampling_rate;
+};
+
+/**
+ * struct snd_compr_avail: avail descriptor
+ * @avail: Number of bytes available in ring buffer for writing/reading
+ * @tstamp: timestamp infomation
+ */
+struct snd_compr_avail {
+	__u64 avail;
+	struct snd_compr_tstamp tstamp;
+};
+
+enum snd_compr_direction {
+	SND_COMPRESS_PLAYBACK = 0,
+	SND_COMPRESS_CAPTURE
+};
+
+/**
+ * struct snd_compr_caps: caps descriptor
+ * @codecs: pointer to array of codecs
+ * @direction: direction supported. Of type snd_compr_direction
+ * @min_fragment_size: minimum fragment supported by DSP
+ * @max_fragment_size: maximum fragment supported by DSP
+ * @min_fragments: min fragments supported by DSP
+ * @max_fragments: max fragments supported by DSP
+ * @num_codecs: number of codecs supported
+ * @reserved: reserved field
+ */
+struct snd_compr_caps {
+	__u32 num_codecs;
+	__u32 direction;
+	__u32 min_fragment_size;
+	__u32 max_fragment_size;
+	__u32 min_fragments;
+	__u32 max_fragments;
+	__u32 codecs[MAX_NUM_CODECS];
+	__u32 reserved[11];
+};
+
+/**
+ * struct snd_compr_codec_caps: query capability of codec
+ * @codec: codec for which capability is queried
+ * @num_descriptors: number of codec descriptors
+ * @descriptor: array of codec capability descriptor
+ */
+struct snd_compr_codec_caps {
+	__u32 codec;
+	__u32 num_descriptors;
+	struct snd_codec_desc descriptor[MAX_NUM_CODEC_DESCRIPTORS];
+};
+
+/**
+ * compress path ioctl definitions
+ * SNDRV_COMPRESS_GET_CAPS: Query capability of DSP
+ * SNDRV_COMPRESS_GET_CODEC_CAPS: Query capability of a codec
+ * SNDRV_COMPRESS_SET_PARAMS: Set codec and stream parameters
+ * Note: only codec params can be changed runtime and stream params cant be
+ * SNDRV_COMPRESS_GET_PARAMS: Query codec params
+ * SNDRV_COMPRESS_TSTAMP: get the current timestamp value
+ * SNDRV_COMPRESS_AVAIL: get the current buffer avail value.
+ * This also queries the tstamp properties
+ * SNDRV_COMPRESS_PAUSE: Pause the running stream
+ * SNDRV_COMPRESS_RESUME: resume a paused stream
+ * SNDRV_COMPRESS_START: Start a stream
+ * SNDRV_COMPRESS_STOP: stop a running stream, discarding ring buffer content
+ * and the buffers currently with DSP
+ * SNDRV_COMPRESS_DRAIN: Play till end of buffers and stop after that
+ * SNDRV_COMPRESS_IOCTL_VERSION: Query the API version
+ */
+#define SNDRV_COMPRESS_IOCTL_VERSION	_IOR('C', 0x00, int)
+#define SNDRV_COMPRESS_GET_CAPS		_IOWR('C', 0x10, struct snd_compr_caps)
+#define SNDRV_COMPRESS_GET_CODEC_CAPS	_IOWR('C', 0x11,\
+						struct snd_compr_codec_caps)
+#define SNDRV_COMPRESS_SET_PARAMS	_IOW('C', 0x12, struct snd_compr_params)
+#define SNDRV_COMPRESS_GET_PARAMS	_IOR('C', 0x13, struct snd_codec)
+#define SNDRV_COMPRESS_TSTAMP		_IOR('C', 0x20, struct snd_compr_tstamp)
+#define SNDRV_COMPRESS_AVAIL		_IOR('C', 0x21, struct snd_compr_avail)
+#define SNDRV_COMPRESS_PAUSE		_IO('C', 0x30)
+#define SNDRV_COMPRESS_RESUME		_IO('C', 0x31)
+#define SNDRV_COMPRESS_START		_IO('C', 0x32)
+#define SNDRV_COMPRESS_STOP		_IO('C', 0x33)
+#define SNDRV_COMPRESS_DRAIN		_IO('C', 0x34)
+/*
+ * TODO
+ * 1. add mmap support
+ *
+ */
+#define SND_COMPR_TRIGGER_DRAIN 7 /*FIXME move this to pcm.h */
+#endif
diff --git a/include/uapi/sound/compress_params.h b/include/uapi/sound/compress_params.h
new file mode 100644
index 0000000..602dc6c
--- /dev/null
+++ b/include/uapi/sound/compress_params.h
@@ -0,0 +1,400 @@
+/*
+ *  compress_params.h - codec types and parameters for compressed data
+ *  streaming interface
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *              Vinod Koul <vinod.koul@linux.intel.com>
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The definitions in this file are derived from the OpenMAX AL version 1.1
+ * and OpenMAX IL v 1.1.2 header files which contain the copyright notice below.
+ *
+ * Copyright (c) 2007-2010 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and/or associated documentation files (the
+ * "Materials "), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ */
+#ifndef __SND_COMPRESS_PARAMS_H
+#define __SND_COMPRESS_PARAMS_H
+
+#include <linux/types.h>
+
+/* AUDIO CODECS SUPPORTED */
+#define MAX_NUM_CODECS 32
+#define MAX_NUM_CODEC_DESCRIPTORS 32
+#define MAX_NUM_BITRATES 32
+
+/* Codecs are listed linearly to allow for extensibility */
+#define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
+#define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
+#define SND_AUDIOCODEC_AMR                   ((__u32) 0x00000003)
+#define SND_AUDIOCODEC_AMRWB                 ((__u32) 0x00000004)
+#define SND_AUDIOCODEC_AMRWBPLUS             ((__u32) 0x00000005)
+#define SND_AUDIOCODEC_AAC                   ((__u32) 0x00000006)
+#define SND_AUDIOCODEC_WMA                   ((__u32) 0x00000007)
+#define SND_AUDIOCODEC_REAL                  ((__u32) 0x00000008)
+#define SND_AUDIOCODEC_VORBIS                ((__u32) 0x00000009)
+#define SND_AUDIOCODEC_FLAC                  ((__u32) 0x0000000A)
+#define SND_AUDIOCODEC_IEC61937              ((__u32) 0x0000000B)
+#define SND_AUDIOCODEC_G723_1                ((__u32) 0x0000000C)
+#define SND_AUDIOCODEC_G729                  ((__u32) 0x0000000D)
+#define SND_AUDIOCODEC_MAX                   SND_AUDIOCODEC_G729
+
+/*
+ * Profile and modes are listed with bit masks. This allows for a
+ * more compact representation of fields that will not evolve
+ * (in contrast to the list of codecs)
+ */
+
+#define SND_AUDIOPROFILE_PCM                 ((__u32) 0x00000001)
+
+/* MP3 modes are only useful for encoders */
+#define SND_AUDIOCHANMODE_MP3_MONO           ((__u32) 0x00000001)
+#define SND_AUDIOCHANMODE_MP3_STEREO         ((__u32) 0x00000002)
+#define SND_AUDIOCHANMODE_MP3_JOINTSTEREO    ((__u32) 0x00000004)
+#define SND_AUDIOCHANMODE_MP3_DUAL           ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_AMR                 ((__u32) 0x00000001)
+
+/* AMR modes are only useful for encoders */
+#define SND_AUDIOMODE_AMR_DTX_OFF            ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMR_VAD1               ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMR_VAD2               ((__u32) 0x00000004)
+
+#define SND_AUDIOSTREAMFORMAT_UNDEFINED	     ((__u32) 0x00000000)
+#define SND_AUDIOSTREAMFORMAT_CONFORMANCE    ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_IF1            ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_IF2            ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_FSF            ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_RTPPAYLOAD     ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_ITU            ((__u32) 0x00000020)
+
+#define SND_AUDIOPROFILE_AMRWB               ((__u32) 0x00000001)
+
+/* AMRWB modes are only useful for encoders */
+#define SND_AUDIOMODE_AMRWB_DTX_OFF          ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMRWB_VAD1             ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMRWB_VAD2             ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_AMRWBPLUS           ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_AAC                 ((__u32) 0x00000001)
+
+/* AAC modes are required for encoders and decoders */
+#define SND_AUDIOMODE_AAC_MAIN               ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AAC_LC                 ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AAC_SSR                ((__u32) 0x00000004)
+#define SND_AUDIOMODE_AAC_LTP                ((__u32) 0x00000008)
+#define SND_AUDIOMODE_AAC_HE                 ((__u32) 0x00000010)
+#define SND_AUDIOMODE_AAC_SCALABLE           ((__u32) 0x00000020)
+#define SND_AUDIOMODE_AAC_ERLC               ((__u32) 0x00000040)
+#define SND_AUDIOMODE_AAC_LD                 ((__u32) 0x00000080)
+#define SND_AUDIOMODE_AAC_HE_PS              ((__u32) 0x00000100)
+#define SND_AUDIOMODE_AAC_HE_MPS             ((__u32) 0x00000200)
+
+/* AAC formats are required for encoders and decoders */
+#define SND_AUDIOSTREAMFORMAT_MP2ADTS        ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_MP4ADTS        ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_MP4LOAS        ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_MP4LATM        ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_ADIF           ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_MP4FF          ((__u32) 0x00000020)
+#define SND_AUDIOSTREAMFORMAT_RAW            ((__u32) 0x00000040)
+
+#define SND_AUDIOPROFILE_WMA7                ((__u32) 0x00000001)
+#define SND_AUDIOPROFILE_WMA8                ((__u32) 0x00000002)
+#define SND_AUDIOPROFILE_WMA9                ((__u32) 0x00000004)
+#define SND_AUDIOPROFILE_WMA10               ((__u32) 0x00000008)
+
+#define SND_AUDIOMODE_WMA_LEVEL1             ((__u32) 0x00000001)
+#define SND_AUDIOMODE_WMA_LEVEL2             ((__u32) 0x00000002)
+#define SND_AUDIOMODE_WMA_LEVEL3             ((__u32) 0x00000004)
+#define SND_AUDIOMODE_WMA_LEVEL4             ((__u32) 0x00000008)
+#define SND_AUDIOMODE_WMAPRO_LEVELM0         ((__u32) 0x00000010)
+#define SND_AUDIOMODE_WMAPRO_LEVELM1         ((__u32) 0x00000020)
+#define SND_AUDIOMODE_WMAPRO_LEVELM2         ((__u32) 0x00000040)
+#define SND_AUDIOMODE_WMAPRO_LEVELM3         ((__u32) 0x00000080)
+
+#define SND_AUDIOSTREAMFORMAT_WMA_ASF        ((__u32) 0x00000001)
+/*
+ * Some implementations strip the ASF header and only send ASF packets
+ * to the DSP
+ */
+#define SND_AUDIOSTREAMFORMAT_WMA_NOASF_HDR  ((__u32) 0x00000002)
+
+#define SND_AUDIOPROFILE_REALAUDIO           ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_REALAUDIO_G2           ((__u32) 0x00000001)
+#define SND_AUDIOMODE_REALAUDIO_8            ((__u32) 0x00000002)
+#define SND_AUDIOMODE_REALAUDIO_10           ((__u32) 0x00000004)
+#define SND_AUDIOMODE_REALAUDIO_SURROUND     ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_VORBIS              ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_VORBIS                 ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_FLAC                ((__u32) 0x00000001)
+
+/*
+ * Define quality levels for FLAC encoders, from LEVEL0 (fast)
+ * to LEVEL8 (best)
+ */
+#define SND_AUDIOMODE_FLAC_LEVEL0            ((__u32) 0x00000001)
+#define SND_AUDIOMODE_FLAC_LEVEL1            ((__u32) 0x00000002)
+#define SND_AUDIOMODE_FLAC_LEVEL2            ((__u32) 0x00000004)
+#define SND_AUDIOMODE_FLAC_LEVEL3            ((__u32) 0x00000008)
+#define SND_AUDIOMODE_FLAC_LEVEL4            ((__u32) 0x00000010)
+#define SND_AUDIOMODE_FLAC_LEVEL5            ((__u32) 0x00000020)
+#define SND_AUDIOMODE_FLAC_LEVEL6            ((__u32) 0x00000040)
+#define SND_AUDIOMODE_FLAC_LEVEL7            ((__u32) 0x00000080)
+#define SND_AUDIOMODE_FLAC_LEVEL8            ((__u32) 0x00000100)
+
+#define SND_AUDIOSTREAMFORMAT_FLAC           ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_FLAC_OGG       ((__u32) 0x00000002)
+
+/* IEC61937 payloads without CUVP and preambles */
+#define SND_AUDIOPROFILE_IEC61937            ((__u32) 0x00000001)
+/* IEC61937 with S/PDIF preambles+CUVP bits in 32-bit containers */
+#define SND_AUDIOPROFILE_IEC61937_SPDIF      ((__u32) 0x00000002)
+
+/*
+ * IEC modes are mandatory for decoders. Format autodetection
+ * will only happen on the DSP side with mode 0. The PCM mode should
+ * not be used, the PCM codec should be used instead.
+ */
+#define SND_AUDIOMODE_IEC_REF_STREAM_HEADER  ((__u32) 0x00000000)
+#define SND_AUDIOMODE_IEC_LPCM		     ((__u32) 0x00000001)
+#define SND_AUDIOMODE_IEC_AC3		     ((__u32) 0x00000002)
+#define SND_AUDIOMODE_IEC_MPEG1		     ((__u32) 0x00000004)
+#define SND_AUDIOMODE_IEC_MP3		     ((__u32) 0x00000008)
+#define SND_AUDIOMODE_IEC_MPEG2		     ((__u32) 0x00000010)
+#define SND_AUDIOMODE_IEC_AACLC		     ((__u32) 0x00000020)
+#define SND_AUDIOMODE_IEC_DTS		     ((__u32) 0x00000040)
+#define SND_AUDIOMODE_IEC_ATRAC		     ((__u32) 0x00000080)
+#define SND_AUDIOMODE_IEC_SACD		     ((__u32) 0x00000100)
+#define SND_AUDIOMODE_IEC_EAC3		     ((__u32) 0x00000200)
+#define SND_AUDIOMODE_IEC_DTS_HD	     ((__u32) 0x00000400)
+#define SND_AUDIOMODE_IEC_MLP		     ((__u32) 0x00000800)
+#define SND_AUDIOMODE_IEC_DST		     ((__u32) 0x00001000)
+#define SND_AUDIOMODE_IEC_WMAPRO	     ((__u32) 0x00002000)
+#define SND_AUDIOMODE_IEC_REF_CXT            ((__u32) 0x00004000)
+#define SND_AUDIOMODE_IEC_HE_AAC	     ((__u32) 0x00008000)
+#define SND_AUDIOMODE_IEC_HE_AAC2	     ((__u32) 0x00010000)
+#define SND_AUDIOMODE_IEC_MPEG_SURROUND	     ((__u32) 0x00020000)
+
+#define SND_AUDIOPROFILE_G723_1              ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_G723_1_ANNEX_A         ((__u32) 0x00000001)
+#define SND_AUDIOMODE_G723_1_ANNEX_B         ((__u32) 0x00000002)
+#define SND_AUDIOMODE_G723_1_ANNEX_C         ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_G729                ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_G729_ANNEX_A           ((__u32) 0x00000001)
+#define SND_AUDIOMODE_G729_ANNEX_B           ((__u32) 0x00000002)
+
+/* <FIXME: multichannel encoders aren't supported for now. Would need
+   an additional definition of channel arrangement> */
+
+/* VBR/CBR definitions */
+#define SND_RATECONTROLMODE_CONSTANTBITRATE  ((__u32) 0x00000001)
+#define SND_RATECONTROLMODE_VARIABLEBITRATE  ((__u32) 0x00000002)
+
+/* Encoder options */
+
+struct snd_enc_wma {
+	__u32 super_block_align; /* WMA Type-specific data */
+};
+
+
+/**
+ * struct snd_enc_vorbis
+ * @quality: Sets encoding quality to n, between -1 (low) and 10 (high).
+ * In the default mode of operation, the quality level is 3.
+ * Normal quality range is 0 - 10.
+ * @managed: Boolean. Set  bitrate  management  mode. This turns off the
+ * normal VBR encoding, but allows hard or soft bitrate constraints to be
+ * enforced by the encoder. This mode can be slower, and may also be
+ * lower quality. It is primarily useful for streaming.
+ * @max_bit_rate: Enabled only if managed is TRUE
+ * @min_bit_rate: Enabled only if managed is TRUE
+ * @downmix: Boolean. Downmix input from stereo to mono (has no effect on
+ * non-stereo streams). Useful for lower-bitrate encoding.
+ *
+ * These options were extracted from the OpenMAX IL spec and Gstreamer vorbisenc
+ * properties
+ *
+ * For best quality users should specify VBR mode and set quality levels.
+ */
+
+struct snd_enc_vorbis {
+	__s32 quality;
+	__u32 managed;
+	__u32 max_bit_rate;
+	__u32 min_bit_rate;
+	__u32 downmix;
+};
+
+
+/**
+ * struct snd_enc_real
+ * @quant_bits: number of coupling quantization bits in the stream
+ * @start_region: coupling start region in the stream
+ * @num_regions: number of regions value
+ *
+ * These options were extracted from the OpenMAX IL spec
+ */
+
+struct snd_enc_real {
+	__u32 quant_bits;
+	__u32 start_region;
+	__u32 num_regions;
+};
+
+/**
+ * struct snd_enc_flac
+ * @num: serial number, valid only for OGG formats
+ *	needs to be set by application
+ * @gain: Add replay gain tags
+ *
+ * These options were extracted from the FLAC online documentation
+ * at http://flac.sourceforge.net/documentation_tools_flac.html
+ *
+ * To make the API simpler, it is assumed that the user will select quality
+ * profiles. Additional options that affect encoding quality and speed can
+ * be added at a later stage if needed.
+ *
+ * By default the Subset format is used by encoders.
+ *
+ * TAGS such as pictures, etc, cannot be handled by an offloaded encoder and are
+ * not supported in this API.
+ */
+
+struct snd_enc_flac {
+	__u32 num;
+	__u32 gain;
+};
+
+struct snd_enc_generic {
+	__u32 bw;	/* encoder bandwidth */
+	__s32 reserved[15];
+};
+
+union snd_codec_options {
+	struct snd_enc_wma wma;
+	struct snd_enc_vorbis vorbis;
+	struct snd_enc_real real;
+	struct snd_enc_flac flac;
+	struct snd_enc_generic generic;
+};
+
+/** struct snd_codec_desc - description of codec capabilities
+ * @max_ch: Maximum number of audio channels
+ * @sample_rates: Sampling rates in Hz, use SNDRV_PCM_RATE_xxx for this
+ * @bit_rate: Indexed array containing supported bit rates
+ * @num_bitrates: Number of valid values in bit_rate array
+ * @rate_control: value is specified by SND_RATECONTROLMODE defines.
+ * @profiles: Supported profiles. See SND_AUDIOPROFILE defines.
+ * @modes: Supported modes. See SND_AUDIOMODE defines
+ * @formats: Supported formats. See SND_AUDIOSTREAMFORMAT defines
+ * @min_buffer: Minimum buffer size handled by codec implementation
+ * @reserved: reserved for future use
+ *
+ * This structure provides a scalar value for profiles, modes and stream
+ * format fields.
+ * If an implementation supports multiple combinations, they will be listed as
+ * codecs with different descriptors, for example there would be 2 descriptors
+ * for AAC-RAW and AAC-ADTS.
+ * This entails some redundancy but makes it easier to avoid invalid
+ * configurations.
+ *
+ */
+
+struct snd_codec_desc {
+	__u32 max_ch;
+	__u32 sample_rates;
+	__u32 bit_rate[MAX_NUM_BITRATES];
+	__u32 num_bitrates;
+	__u32 rate_control;
+	__u32 profiles;
+	__u32 modes;
+	__u32 formats;
+	__u32 min_buffer;
+	__u32 reserved[15];
+};
+
+/** struct snd_codec
+ * @id: Identifies the supported audio encoder/decoder.
+ *		See SND_AUDIOCODEC macros.
+ * @ch_in: Number of input audio channels
+ * @ch_out: Number of output channels. In case of contradiction between
+ *		this field and the channelMode field, the channelMode field
+ *		overrides.
+ * @sample_rate: Audio sample rate of input data
+ * @bit_rate: Bitrate of encoded data. May be ignored by decoders
+ * @rate_control: Encoding rate control. See SND_RATECONTROLMODE defines.
+ *               Encoders may rely on profiles for quality levels.
+ *		 May be ignored by decoders.
+ * @profile: Mandatory for encoders, can be mandatory for specific
+ *		decoders as well. See SND_AUDIOPROFILE defines.
+ * @level: Supported level (Only used by WMA at the moment)
+ * @ch_mode: Channel mode for encoder. See SND_AUDIOCHANMODE defines
+ * @format: Format of encoded bistream. Mandatory when defined.
+ *		See SND_AUDIOSTREAMFORMAT defines.
+ * @align: Block alignment in bytes of an audio sample.
+ *		Only required for PCM or IEC formats.
+ * @options: encoder-specific settings
+ * @reserved: reserved for future use
+ */
+
+struct snd_codec {
+	__u32 id;
+	__u32 ch_in;
+	__u32 ch_out;
+	__u32 sample_rate;
+	__u32 bit_rate;
+	__u32 rate_control;
+	__u32 profile;
+	__u32 level;
+	__u32 ch_mode;
+	__u32 format;
+	__u32 align;
+	union snd_codec_options options;
+	__u32 reserved[3];
+};
+
+#endif
diff --git a/include/uapi/sound/emu10k1.h b/include/uapi/sound/emu10k1.h
new file mode 100644
index 0000000..d1bbaf7
--- /dev/null
+++ b/include/uapi/sound/emu10k1.h
@@ -0,0 +1,373 @@
+/*
+ *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
+ *		     Creative Labs, Inc.
+ *  Definitions for EMU10K1 (SB Live!) chips
+ *
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You 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 _UAPI__SOUND_EMU10K1_H
+#define _UAPI__SOUND_EMU10K1_H
+
+#include <linux/types.h>
+
+
+
+/*
+ * ---- FX8010 ----
+ */
+
+#define EMU10K1_CARD_CREATIVE			0x00000000
+#define EMU10K1_CARD_EMUAPS			0x00000001
+
+#define EMU10K1_FX8010_PCM_COUNT		8
+
+/* instruction set */
+#define iMAC0	 0x00	/* R = A + (X * Y >> 31)   ; saturation */
+#define iMAC1	 0x01	/* R = A + (-X * Y >> 31)  ; saturation */
+#define iMAC2	 0x02	/* R = A + (X * Y >> 31)   ; wraparound */
+#define iMAC3	 0x03	/* R = A + (-X * Y >> 31)  ; wraparound */
+#define iMACINT0 0x04	/* R = A + X * Y	   ; saturation */
+#define iMACINT1 0x05	/* R = A + X * Y	   ; wraparound (31-bit) */
+#define iACC3	 0x06	/* R = A + X + Y	   ; saturation */
+#define iMACMV   0x07	/* R = A, acc += X * Y >> 31 */
+#define iANDXOR  0x08	/* R = (A & X) ^ Y */
+#define iTSTNEG  0x09	/* R = (A >= Y) ? X : ~X */
+#define iLIMITGE 0x0a	/* R = (A >= Y) ? X : Y */
+#define iLIMITLT 0x0b	/* R = (A < Y) ? X : Y */
+#define iLOG	 0x0c	/* R = linear_data, A (log_data), X (max_exp), Y (format_word) */
+#define iEXP	 0x0d	/* R = log_data, A (linear_data), X (max_exp), Y (format_word) */
+#define iINTERP  0x0e	/* R = A + (X * (Y - A) >> 31)  ; saturation */
+#define iSKIP    0x0f	/* R = A (cc_reg), X (count), Y (cc_test) */
+
+/* GPRs */
+#define FXBUS(x)	(0x00 + (x))	/* x = 0x00 - 0x0f */
+#define EXTIN(x)	(0x10 + (x))	/* x = 0x00 - 0x0f */
+#define EXTOUT(x)	(0x20 + (x))	/* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */
+#define FXBUS2(x)	(0x30 + (x))	/* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */
+					/* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */
+
+#define C_00000000	0x40
+#define C_00000001	0x41
+#define C_00000002	0x42
+#define C_00000003	0x43
+#define C_00000004	0x44
+#define C_00000008	0x45
+#define C_00000010	0x46
+#define C_00000020	0x47
+#define C_00000100	0x48
+#define C_00010000	0x49
+#define C_00080000	0x4a
+#define C_10000000	0x4b
+#define C_20000000	0x4c
+#define C_40000000	0x4d
+#define C_80000000	0x4e
+#define C_7fffffff	0x4f
+#define C_ffffffff	0x50
+#define C_fffffffe	0x51
+#define C_c0000000	0x52
+#define C_4f1bbcdc	0x53
+#define C_5a7ef9db	0x54
+#define C_00100000	0x55		/* ?? */
+#define GPR_ACCU	0x56		/* ACCUM, accumulator */
+#define GPR_COND	0x57		/* CCR, condition register */
+#define GPR_NOISE0	0x58		/* noise source */
+#define GPR_NOISE1	0x59		/* noise source */
+#define GPR_IRQ		0x5a		/* IRQ register */
+#define GPR_DBAC	0x5b		/* TRAM Delay Base Address Counter */
+#define GPR(x)		(FXGPREGBASE + (x)) /* free GPRs: x = 0x00 - 0xff */
+#define ITRAM_DATA(x)	(TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
+#define ETRAM_DATA(x)	(TANKMEMDATAREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
+#define ITRAM_ADDR(x)	(TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
+#define ETRAM_ADDR(x)	(TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
+
+#define A_ITRAM_DATA(x)	(TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_DATA(x)	(TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+#define A_ITRAM_ADDR(x)	(TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_ADDR(x)	(TANKMEMADDRREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+#define A_ITRAM_CTL(x)	(A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_CTL(x)	(A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+
+#define A_FXBUS(x)	(0x00 + (x))	/* x = 0x00 - 0x3f FX buses */
+#define A_EXTIN(x)	(0x40 + (x))	/* x = 0x00 - 0x0f physical ins */
+#define A_P16VIN(x)	(0x50 + (x))	/* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */
+#define A_EXTOUT(x)	(0x60 + (x))	/* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown   */
+#define A_FXBUS2(x)	(0x80 + (x))	/* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */
+#define A_EMU32OUTH(x)	(0xa0 + (x))	/* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */
+#define A_EMU32OUTL(x)	(0xb0 + (x))	/* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */
+#define A3_EMU32IN(x)	(0x160 + (x))	/* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */
+#define A3_EMU32OUT(x)	(0x1E0 + (x))	/* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */
+#define A_GPR(x)	(A_FXGPREGBASE + (x))
+
+/* cc_reg constants */
+#define CC_REG_NORMALIZED C_00000001
+#define CC_REG_BORROW	C_00000002
+#define CC_REG_MINUS	C_00000004
+#define CC_REG_ZERO	C_00000008
+#define CC_REG_SATURATE	C_00000010
+#define CC_REG_NONZERO	C_00000100
+
+/* FX buses */
+#define FXBUS_PCM_LEFT		0x00
+#define FXBUS_PCM_RIGHT		0x01
+#define FXBUS_PCM_LEFT_REAR	0x02
+#define FXBUS_PCM_RIGHT_REAR	0x03
+#define FXBUS_MIDI_LEFT		0x04
+#define FXBUS_MIDI_RIGHT	0x05
+#define FXBUS_PCM_CENTER	0x06
+#define FXBUS_PCM_LFE		0x07
+#define FXBUS_PCM_LEFT_FRONT	0x08
+#define FXBUS_PCM_RIGHT_FRONT	0x09
+#define FXBUS_MIDI_REVERB	0x0c
+#define FXBUS_MIDI_CHORUS	0x0d
+#define FXBUS_PCM_LEFT_SIDE	0x0e
+#define FXBUS_PCM_RIGHT_SIDE	0x0f
+#define FXBUS_PT_LEFT		0x14
+#define FXBUS_PT_RIGHT		0x15
+
+/* Inputs */
+#define EXTIN_AC97_L	   0x00	/* AC'97 capture channel - left */
+#define EXTIN_AC97_R	   0x01	/* AC'97 capture channel - right */
+#define EXTIN_SPDIF_CD_L   0x02	/* internal S/PDIF CD - onboard - left */
+#define EXTIN_SPDIF_CD_R   0x03	/* internal S/PDIF CD - onboard - right */
+#define EXTIN_ZOOM_L	   0x04	/* Zoom Video I2S - left */
+#define EXTIN_ZOOM_R	   0x05	/* Zoom Video I2S - right */
+#define EXTIN_TOSLINK_L	   0x06	/* LiveDrive - TOSLink Optical - left */
+#define EXTIN_TOSLINK_R    0x07	/* LiveDrive - TOSLink Optical - right */
+#define EXTIN_LINE1_L	   0x08	/* LiveDrive - Line/Mic 1 - left */
+#define EXTIN_LINE1_R	   0x09	/* LiveDrive - Line/Mic 1 - right */
+#define EXTIN_COAX_SPDIF_L 0x0a	/* LiveDrive - Coaxial S/PDIF - left */
+#define EXTIN_COAX_SPDIF_R 0x0b /* LiveDrive - Coaxial S/PDIF - right */
+#define EXTIN_LINE2_L	   0x0c	/* LiveDrive - Line/Mic 2 - left */
+#define EXTIN_LINE2_R	   0x0d	/* LiveDrive - Line/Mic 2 - right */
+
+/* Outputs */
+#define EXTOUT_AC97_L	   0x00	/* AC'97 playback channel - left */
+#define EXTOUT_AC97_R	   0x01	/* AC'97 playback channel - right */
+#define EXTOUT_TOSLINK_L   0x02	/* LiveDrive - TOSLink Optical - left */
+#define EXTOUT_TOSLINK_R   0x03	/* LiveDrive - TOSLink Optical - right */
+#define EXTOUT_AC97_CENTER 0x04	/* SB Live 5.1 - center */
+#define EXTOUT_AC97_LFE	   0x05 /* SB Live 5.1 - LFE */
+#define EXTOUT_HEADPHONE_L 0x06	/* LiveDrive - Headphone - left */
+#define EXTOUT_HEADPHONE_R 0x07	/* LiveDrive - Headphone - right */
+#define EXTOUT_REAR_L	   0x08	/* Rear channel - left */
+#define EXTOUT_REAR_R	   0x09	/* Rear channel - right */
+#define EXTOUT_ADC_CAP_L   0x0a	/* ADC Capture buffer - left */
+#define EXTOUT_ADC_CAP_R   0x0b	/* ADC Capture buffer - right */
+#define EXTOUT_MIC_CAP	   0x0c	/* MIC Capture buffer */
+#define EXTOUT_AC97_REAR_L 0x0d	/* SB Live 5.1 (c) 2003 - Rear Left */
+#define EXTOUT_AC97_REAR_R 0x0e	/* SB Live 5.1 (c) 2003 - Rear Right */
+#define EXTOUT_ACENTER	   0x11 /* Analog Center */
+#define EXTOUT_ALFE	   0x12 /* Analog LFE */
+
+/* Audigy Inputs */
+#define A_EXTIN_AC97_L		0x00	/* AC'97 capture channel - left */
+#define A_EXTIN_AC97_R		0x01	/* AC'97 capture channel - right */
+#define A_EXTIN_SPDIF_CD_L	0x02	/* digital CD left */
+#define A_EXTIN_SPDIF_CD_R	0x03	/* digital CD left */
+#define A_EXTIN_OPT_SPDIF_L     0x04    /* audigy drive Optical SPDIF - left */
+#define A_EXTIN_OPT_SPDIF_R     0x05    /*                              right */ 
+#define A_EXTIN_LINE2_L		0x08	/* audigy drive line2/mic2 - left */
+#define A_EXTIN_LINE2_R		0x09	/*                           right */
+#define A_EXTIN_ADC_L		0x0a    /* Philips ADC - left */
+#define A_EXTIN_ADC_R		0x0b    /*               right */
+#define A_EXTIN_AUX2_L		0x0c	/* audigy drive aux2 - left */
+#define A_EXTIN_AUX2_R		0x0d	/*                   - right */
+
+/* Audigiy Outputs */
+#define A_EXTOUT_FRONT_L	0x00	/* digital front left */
+#define A_EXTOUT_FRONT_R	0x01	/*               right */
+#define A_EXTOUT_CENTER		0x02	/* digital front center */
+#define A_EXTOUT_LFE		0x03	/* digital front lfe */
+#define A_EXTOUT_HEADPHONE_L	0x04	/* headphone audigy drive left */
+#define A_EXTOUT_HEADPHONE_R	0x05	/*                        right */
+#define A_EXTOUT_REAR_L		0x06	/* digital rear left */
+#define A_EXTOUT_REAR_R		0x07	/*              right */
+#define A_EXTOUT_AFRONT_L	0x08	/* analog front left */
+#define A_EXTOUT_AFRONT_R	0x09	/*              right */
+#define A_EXTOUT_ACENTER	0x0a	/* analog center */
+#define A_EXTOUT_ALFE		0x0b	/* analog LFE */
+#define A_EXTOUT_ASIDE_L	0x0c	/* analog side left  - Audigy 2 ZS */
+#define A_EXTOUT_ASIDE_R	0x0d	/*             right - Audigy 2 ZS */
+#define A_EXTOUT_AREAR_L	0x0e	/* analog rear left */
+#define A_EXTOUT_AREAR_R	0x0f	/*             right */
+#define A_EXTOUT_AC97_L		0x10	/* AC97 left (front) */
+#define A_EXTOUT_AC97_R		0x11	/*      right */
+#define A_EXTOUT_ADC_CAP_L	0x16	/* ADC capture buffer left */
+#define A_EXTOUT_ADC_CAP_R	0x17	/*                    right */
+#define A_EXTOUT_MIC_CAP	0x18	/* Mic capture buffer */
+
+/* Audigy constants */
+#define A_C_00000000	0xc0
+#define A_C_00000001	0xc1
+#define A_C_00000002	0xc2
+#define A_C_00000003	0xc3
+#define A_C_00000004	0xc4
+#define A_C_00000008	0xc5
+#define A_C_00000010	0xc6
+#define A_C_00000020	0xc7
+#define A_C_00000100	0xc8
+#define A_C_00010000	0xc9
+#define A_C_00000800	0xca
+#define A_C_10000000	0xcb
+#define A_C_20000000	0xcc
+#define A_C_40000000	0xcd
+#define A_C_80000000	0xce
+#define A_C_7fffffff	0xcf
+#define A_C_ffffffff	0xd0
+#define A_C_fffffffe	0xd1
+#define A_C_c0000000	0xd2
+#define A_C_4f1bbcdc	0xd3
+#define A_C_5a7ef9db	0xd4
+#define A_C_00100000	0xd5
+#define A_GPR_ACCU	0xd6		/* ACCUM, accumulator */
+#define A_GPR_COND	0xd7		/* CCR, condition register */
+#define A_GPR_NOISE0	0xd8		/* noise source */
+#define A_GPR_NOISE1	0xd9		/* noise source */
+#define A_GPR_IRQ	0xda		/* IRQ register */
+#define A_GPR_DBAC	0xdb		/* TRAM Delay Base Address Counter - internal */
+#define A_GPR_DBACE	0xde		/* TRAM Delay Base Address Counter - external */
+
+/* definitions for debug register */
+#define EMU10K1_DBG_ZC			0x80000000	/* zero tram counter */
+#define EMU10K1_DBG_SATURATION_OCCURED	0x02000000	/* saturation control */
+#define EMU10K1_DBG_SATURATION_ADDR	0x01ff0000	/* saturation address */
+#define EMU10K1_DBG_SINGLE_STEP		0x00008000	/* single step mode */
+#define EMU10K1_DBG_STEP		0x00004000	/* start single step */
+#define EMU10K1_DBG_CONDITION_CODE	0x00003e00	/* condition code */
+#define EMU10K1_DBG_SINGLE_STEP_ADDR	0x000001ff	/* single step address */
+
+/* tank memory address line */
+#ifndef __KERNEL__
+#define TANKMEMADDRREG_ADDR_MASK 0x000fffff	/* 20 bit tank address field			*/
+#define TANKMEMADDRREG_CLEAR	 0x00800000	/* Clear tank memory				*/
+#define TANKMEMADDRREG_ALIGN	 0x00400000	/* Align read or write relative to tank access	*/
+#define TANKMEMADDRREG_WRITE	 0x00200000	/* Write to tank memory				*/
+#define TANKMEMADDRREG_READ	 0x00100000	/* Read from tank memory			*/
+#endif
+
+struct snd_emu10k1_fx8010_info {
+	unsigned int internal_tram_size;	/* in samples */
+	unsigned int external_tram_size;	/* in samples */
+	char fxbus_names[16][32];		/* names of FXBUSes */
+	char extin_names[16][32];		/* names of external inputs */
+	char extout_names[32][32];		/* names of external outputs */
+	unsigned int gpr_controls;		/* count of GPR controls */
+};
+
+#define EMU10K1_GPR_TRANSLATION_NONE		0
+#define EMU10K1_GPR_TRANSLATION_TABLE100	1
+#define EMU10K1_GPR_TRANSLATION_BASS		2
+#define EMU10K1_GPR_TRANSLATION_TREBLE		3
+#define EMU10K1_GPR_TRANSLATION_ONOFF		4
+
+struct snd_emu10k1_fx8010_control_gpr {
+	struct snd_ctl_elem_id id;		/* full control ID definition */
+	unsigned int vcount;		/* visible count */
+	unsigned int count;		/* count of GPR (1..16) */
+	unsigned short gpr[32];		/* GPR number(s) */
+	unsigned int value[32];		/* initial values */
+	unsigned int min;		/* minimum range */
+	unsigned int max;		/* maximum range */
+	unsigned int translation;	/* translation type (EMU10K1_GPR_TRANSLATION*) */
+	const unsigned int *tlv;
+};
+
+/* old ABI without TLV support */
+struct snd_emu10k1_fx8010_control_old_gpr {
+	struct snd_ctl_elem_id id;
+	unsigned int vcount;
+	unsigned int count;
+	unsigned short gpr[32];
+	unsigned int value[32];
+	unsigned int min;
+	unsigned int max;
+	unsigned int translation;
+};
+
+struct snd_emu10k1_fx8010_code {
+	char name[128];
+
+	DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */
+	__u32 __user *gpr_map;		/* initializers */
+
+	unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */
+	struct snd_emu10k1_fx8010_control_gpr __user *gpr_add_controls; /* GPR controls to add/replace */
+
+	unsigned int gpr_del_control_count; /* count of GPR controls to remove */
+	struct snd_ctl_elem_id __user *gpr_del_controls; /* IDs of GPR controls to remove */
+
+	unsigned int gpr_list_control_count; /* count of GPR controls to list */
+	unsigned int gpr_list_control_total; /* total count of GPR controls */
+	struct snd_emu10k1_fx8010_control_gpr __user *gpr_list_controls; /* listed GPR controls */
+
+	DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */
+	__u32 __user *tram_data_map;	  /* data initializers */
+	__u32 __user *tram_addr_map;	  /* map initializers */
+
+	DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */
+	__u32 __user *code;		  /* one instruction - 64 bits */
+};
+
+struct snd_emu10k1_fx8010_tram {
+	unsigned int address;		/* 31.bit == 1 -> external TRAM */
+	unsigned int size;		/* size in samples (4 bytes) */
+	unsigned int *samples;		/* pointer to samples (20-bit) */
+					/* NULL->clear memory */
+};
+
+struct snd_emu10k1_fx8010_pcm_rec {
+	unsigned int substream;		/* substream number */
+	unsigned int res1;		/* reserved */
+	unsigned int channels;		/* 16-bit channels count, zero = remove this substream */
+	unsigned int tram_start;	/* ring buffer position in TRAM (in samples) */
+	unsigned int buffer_size;	/* count of buffered samples */
+	unsigned short gpr_size;		/* GPR containing size of ringbuffer in samples (host) */
+	unsigned short gpr_ptr;		/* GPR containing current pointer in the ring buffer (host = reset, FX8010) */
+	unsigned short gpr_count;	/* GPR containing count of samples between two interrupts (host) */
+	unsigned short gpr_tmpcount;	/* GPR containing current count of samples to interrupt (host = set, FX8010) */
+	unsigned short gpr_trigger;	/* GPR containing trigger (activate) information (host) */
+	unsigned short gpr_running;	/* GPR containing info if PCM is running (FX8010) */
+	unsigned char pad;		/* reserved */
+	unsigned char etram[32];	/* external TRAM address & data (one per channel) */
+	unsigned int res2;		/* reserved */
+};
+
+#define SNDRV_EMU10K1_VERSION		SNDRV_PROTOCOL_VERSION(1, 0, 1)
+
+#define SNDRV_EMU10K1_IOCTL_INFO	_IOR ('H', 0x10, struct snd_emu10k1_fx8010_info)
+#define SNDRV_EMU10K1_IOCTL_CODE_POKE	_IOW ('H', 0x11, struct snd_emu10k1_fx8010_code)
+#define SNDRV_EMU10K1_IOCTL_CODE_PEEK	_IOWR('H', 0x12, struct snd_emu10k1_fx8010_code)
+#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP	_IOW ('H', 0x20, int)
+#define SNDRV_EMU10K1_IOCTL_TRAM_POKE	_IOW ('H', 0x21, struct snd_emu10k1_fx8010_tram)
+#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK	_IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram)
+#define SNDRV_EMU10K1_IOCTL_PCM_POKE	_IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec)
+#define SNDRV_EMU10K1_IOCTL_PCM_PEEK	_IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec)
+#define SNDRV_EMU10K1_IOCTL_PVERSION	_IOR ('H', 0x40, int)
+#define SNDRV_EMU10K1_IOCTL_STOP	_IO  ('H', 0x80)
+#define SNDRV_EMU10K1_IOCTL_CONTINUE	_IO  ('H', 0x81)
+#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82)
+#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP	_IOW ('H', 0x83, int)
+#define SNDRV_EMU10K1_IOCTL_DBG_READ	_IOR ('H', 0x84, int)
+
+/* typedefs for compatibility to user-space */
+typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
+typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
+typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
+typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
+typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
+
+#endif /* _UAPI__SOUND_EMU10K1_H */
diff --git a/include/uapi/sound/hdsp.h b/include/uapi/sound/hdsp.h
new file mode 100644
index 0000000..0909a38
--- /dev/null
+++ b/include/uapi/sound/hdsp.h
@@ -0,0 +1,110 @@
+#ifndef __SOUND_HDSP_H
+#define __SOUND_HDSP_H
+
+/*
+ *   Copyright (C) 2003 Thomas Charbonnel (thomas@undata.org)
+ *    
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+
+#define HDSP_MATRIX_MIXER_SIZE 2048
+
+enum HDSP_IO_Type {
+	Digiface,
+	Multiface,
+	H9652,
+	H9632,
+	RPM,
+	Undefined,
+};
+
+struct hdsp_peak_rms {
+	__u32 input_peaks[26];
+	__u32 playback_peaks[26];
+	__u32 output_peaks[28];
+	__u64 input_rms[26];
+	__u64 playback_rms[26];
+	/* These are only used for H96xx cards */
+	__u64 output_rms[26];
+};
+
+#define SNDRV_HDSP_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct hdsp_peak_rms)
+
+struct hdsp_config_info {
+	unsigned char pref_sync_ref;
+	unsigned char wordclock_sync_check;
+	unsigned char spdif_sync_check;
+	unsigned char adatsync_sync_check;
+	unsigned char adat_sync_check[3];
+	unsigned char spdif_in;
+	unsigned char spdif_out;
+	unsigned char spdif_professional;
+	unsigned char spdif_emphasis;
+	unsigned char spdif_nonaudio;
+	unsigned int spdif_sample_rate;
+	unsigned int system_sample_rate;
+	unsigned int autosync_sample_rate;
+	unsigned char system_clock_mode;
+	unsigned char clock_source;
+	unsigned char autosync_ref;
+	unsigned char line_out;
+	unsigned char passthru; 
+	unsigned char da_gain;
+	unsigned char ad_gain;
+	unsigned char phone_gain;
+	unsigned char xlr_breakout_cable;
+	unsigned char analog_extension_board;
+};
+
+#define SNDRV_HDSP_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, struct hdsp_config_info)
+
+struct hdsp_firmware {
+	void __user *firmware_data;	/* 24413 x 4 bytes */
+};
+
+#define SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE _IOW('H', 0x42, struct hdsp_firmware)
+
+struct hdsp_version {
+	enum HDSP_IO_Type io_type;
+	unsigned short firmware_rev;
+};
+
+#define SNDRV_HDSP_IOCTL_GET_VERSION _IOR('H', 0x43, struct hdsp_version)
+
+struct hdsp_mixer {
+	unsigned short matrix[HDSP_MATRIX_MIXER_SIZE];
+};
+
+#define SNDRV_HDSP_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdsp_mixer)
+
+struct hdsp_9632_aeb {
+	int aebi;
+	int aebo;
+};
+
+#define SNDRV_HDSP_IOCTL_GET_9632_AEB _IOR('H', 0x45, struct hdsp_9632_aeb)
+
+/* typedefs for compatibility to user-space */
+typedef enum HDSP_IO_Type HDSP_IO_Type;
+typedef struct hdsp_peak_rms hdsp_peak_rms_t;
+typedef struct hdsp_config_info hdsp_config_info_t;
+typedef struct hdsp_firmware hdsp_firmware_t;
+typedef struct hdsp_version hdsp_version_t;
+typedef struct hdsp_mixer hdsp_mixer_t;
+typedef struct hdsp_9632_aeb hdsp_9632_aeb_t;
+
+#endif /* __SOUND_HDSP_H */
diff --git a/include/uapi/sound/hdspm.h b/include/uapi/sound/hdspm.h
new file mode 100644
index 0000000..1f59ea2
--- /dev/null
+++ b/include/uapi/sound/hdspm.h
@@ -0,0 +1,229 @@
+#ifndef __SOUND_HDSPM_H
+#define __SOUND_HDSPM_H
+/*
+ *   Copyright (C) 2003 Winfried Ritsch (IEM)
+ *   based on hdsp.h from Thomas Charbonnel (thomas@undata.org)
+ *
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */
+#define HDSPM_MAX_CHANNELS      64
+
+enum hdspm_io_type {
+	MADI,
+	MADIface,
+	AIO,
+	AES32,
+	RayDAT
+};
+
+enum hdspm_speed {
+	ss,
+	ds,
+	qs
+};
+
+/* -------------------- IOCTL Peak/RMS Meters -------------------- */
+
+struct hdspm_peak_rms {
+	uint32_t input_peaks[64];
+	uint32_t playback_peaks[64];
+	uint32_t output_peaks[64];
+
+	uint64_t input_rms[64];
+	uint64_t playback_rms[64];
+	uint64_t output_rms[64];
+
+	uint8_t speed; /* enum {ss, ds, qs} */
+	int status2;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS \
+	_IOR('H', 0x42, struct hdspm_peak_rms)
+
+/* ------------ CONFIG block IOCTL ---------------------- */
+
+struct hdspm_config {
+	unsigned char pref_sync_ref;
+	unsigned char wordclock_sync_check;
+	unsigned char madi_sync_check;
+	unsigned int system_sample_rate;
+	unsigned int autosync_sample_rate;
+	unsigned char system_clock_mode;
+	unsigned char clock_source;
+	unsigned char autosync_ref;
+	unsigned char line_out;
+	unsigned int passthru;
+	unsigned int analog_out;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_CONFIG \
+	_IOR('H', 0x41, struct hdspm_config)
+
+/**
+ * If there's a TCO (TimeCode Option) board installed,
+ * there are further options and status data available.
+ * The hdspm_ltc structure contains the current SMPTE
+ * timecode and some status information and can be
+ * obtained via SNDRV_HDSPM_IOCTL_GET_LTC or in the
+ * hdspm_status struct.
+ **/
+
+enum hdspm_ltc_format {
+	format_invalid,
+	fps_24,
+	fps_25,
+	fps_2997,
+	fps_30
+};
+
+enum hdspm_ltc_frame {
+	frame_invalid,
+	drop_frame,
+	full_frame
+};
+
+enum hdspm_ltc_input_format {
+	ntsc,
+	pal,
+	no_video
+};
+
+struct hdspm_ltc {
+	unsigned int ltc;
+
+	enum hdspm_ltc_format format;
+	enum hdspm_ltc_frame frame;
+	enum hdspm_ltc_input_format input_format;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_LTC _IOR('H', 0x46, struct hdspm_mixer_ioctl)
+
+/**
+ * The status data reflects the device's current state
+ * as determined by the card's configuration and
+ * connection status.
+ **/
+
+enum hdspm_sync {
+	hdspm_sync_no_lock = 0,
+	hdspm_sync_lock = 1,
+	hdspm_sync_sync = 2
+};
+
+enum hdspm_madi_input {
+	hdspm_input_optical = 0,
+	hdspm_input_coax = 1
+};
+
+enum hdspm_madi_channel_format {
+	hdspm_format_ch_64 = 0,
+	hdspm_format_ch_56 = 1
+};
+
+enum hdspm_madi_frame_format {
+	hdspm_frame_48 = 0,
+	hdspm_frame_96 = 1
+};
+
+enum hdspm_syncsource {
+	syncsource_wc = 0,
+	syncsource_madi = 1,
+	syncsource_tco = 2,
+	syncsource_sync = 3,
+	syncsource_none = 4
+};
+
+struct hdspm_status {
+	uint8_t card_type; /* enum hdspm_io_type */
+	enum hdspm_syncsource autosync_source;
+
+	uint64_t card_clock;
+	uint32_t master_period;
+
+	union {
+		struct {
+			uint8_t sync_wc; /* enum hdspm_sync */
+			uint8_t sync_madi; /* enum hdspm_sync */
+			uint8_t sync_tco; /* enum hdspm_sync */
+			uint8_t sync_in; /* enum hdspm_sync */
+			uint8_t madi_input; /* enum hdspm_madi_input */
+			uint8_t channel_format; /* enum hdspm_madi_channel_format */
+			uint8_t frame_format; /* enum hdspm_madi_frame_format */
+		} madi;
+	} card_specific;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_STATUS \
+	_IOR('H', 0x47, struct hdspm_status)
+
+/**
+ * Get information about the card and its add-ons.
+ **/
+
+#define HDSPM_ADDON_TCO 1
+
+struct hdspm_version {
+	uint8_t card_type; /* enum hdspm_io_type */
+	char cardname[20];
+	unsigned int serial;
+	unsigned short firmware_rev;
+	int addons;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x48, struct hdspm_version)
+
+/* ------------- get Matrix Mixer IOCTL --------------- */
+
+/* MADI mixer: 64inputs+64playback in 64outputs = 8192 => *4Byte =
+ * 32768 Bytes
+ */
+
+/* organisation is 64 channelfader in a continuous memory block */
+/* equivalent to hardware definition, maybe for future feature of mmap of
+ * them
+ */
+/* each of 64 outputs has 64 infader and 64 outfader:
+   Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */
+
+#define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS
+
+struct hdspm_channelfader {
+	unsigned int in[HDSPM_MIXER_CHANNELS];
+	unsigned int pb[HDSPM_MIXER_CHANNELS];
+};
+
+struct hdspm_mixer {
+	struct hdspm_channelfader ch[HDSPM_MIXER_CHANNELS];
+};
+
+struct hdspm_mixer_ioctl {
+	struct hdspm_mixer *mixer;
+};
+
+/* use indirect access due to the limit of ioctl bit size */
+#define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdspm_mixer_ioctl)
+
+/* typedefs for compatibility to user-space */
+typedef struct hdspm_peak_rms hdspm_peak_rms_t;
+typedef struct hdspm_config_info hdspm_config_info_t;
+typedef struct hdspm_version hdspm_version_t;
+typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
+typedef struct hdspm_mixer hdspm_mixer_t;
+
+
+#endif
diff --git a/include/uapi/sound/sb16_csp.h b/include/uapi/sound/sb16_csp.h
new file mode 100644
index 0000000..3b96907
--- /dev/null
+++ b/include/uapi/sound/sb16_csp.h
@@ -0,0 +1,122 @@
+/*
+ *  Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si>
+ *                        Takashi Iwai <tiwai@suse.de>
+ *
+ *  SB16ASP/AWE32 CSP control
+ *
+ *   This program is free software; you can redistribute it and/or modify 
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You 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 _UAPI__SOUND_SB16_CSP_H
+#define _UAPI__SOUND_SB16_CSP_H
+
+
+/* CSP modes */
+#define SNDRV_SB_CSP_MODE_NONE		0x00
+#define SNDRV_SB_CSP_MODE_DSP_READ	0x01	/* Record from DSP */
+#define SNDRV_SB_CSP_MODE_DSP_WRITE	0x02	/* Play to DSP */
+#define SNDRV_SB_CSP_MODE_QSOUND		0x04	/* QSound */
+
+/* CSP load flags */
+#define SNDRV_SB_CSP_LOAD_FROMUSER	0x01
+#define SNDRV_SB_CSP_LOAD_INITBLOCK	0x02
+
+/* CSP sample width */
+#define SNDRV_SB_CSP_SAMPLE_8BIT		0x01
+#define SNDRV_SB_CSP_SAMPLE_16BIT		0x02
+
+/* CSP channels */
+#define SNDRV_SB_CSP_MONO			0x01
+#define SNDRV_SB_CSP_STEREO		0x02
+
+/* CSP rates */
+#define SNDRV_SB_CSP_RATE_8000		0x01
+#define SNDRV_SB_CSP_RATE_11025		0x02
+#define SNDRV_SB_CSP_RATE_22050		0x04
+#define SNDRV_SB_CSP_RATE_44100		0x08
+#define SNDRV_SB_CSP_RATE_ALL		0x0f
+
+/* CSP running state */
+#define SNDRV_SB_CSP_ST_IDLE		0x00
+#define SNDRV_SB_CSP_ST_LOADED		0x01
+#define SNDRV_SB_CSP_ST_RUNNING		0x02
+#define SNDRV_SB_CSP_ST_PAUSED		0x04
+#define SNDRV_SB_CSP_ST_AUTO		0x08
+#define SNDRV_SB_CSP_ST_QSOUND		0x10
+
+/* maximum QSound value (180 degrees right) */
+#define SNDRV_SB_CSP_QSOUND_MAX_RIGHT	0x20
+
+/* maximum microcode RIFF file size */
+#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE	0x3000
+
+/* microcode header */
+struct snd_sb_csp_mc_header {
+	char codec_name[16];		/* id name of codec */
+	unsigned short func_req;	/* requested function */
+};
+
+/* microcode to be loaded */
+struct snd_sb_csp_microcode {
+	struct snd_sb_csp_mc_header info;
+	unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE];
+};
+
+/* start CSP with sample_width in mono/stereo */
+struct snd_sb_csp_start {
+	int sample_width;	/* sample width, look above */
+	int channels;		/* channels, look above */
+};
+
+/* CSP information */
+struct snd_sb_csp_info {
+	char codec_name[16];		/* id name of codec */
+	unsigned short func_nr;		/* function number */
+	unsigned int acc_format;	/* accepted PCM formats */
+	unsigned short acc_channels;	/* accepted channels */
+	unsigned short acc_width;	/* accepted sample width */
+	unsigned short acc_rates;	/* accepted sample rates */
+	unsigned short csp_mode;	/* CSP mode, see above */
+	unsigned short run_channels;	/* current channels  */
+	unsigned short run_width;	/* current sample width */
+	unsigned short version;		/* version id: 0x10 - 0x1f */
+	unsigned short state;		/* state bits */
+};
+
+/* HWDEP controls */
+/* get CSP information */
+#define SNDRV_SB_CSP_IOCTL_INFO		_IOR('H', 0x10, struct snd_sb_csp_info)
+/* load microcode to CSP */
+/* NOTE: struct snd_sb_csp_microcode overflows the max size (13 bits)
+ * defined for some architectures like MIPS, and it leads to build errors.
+ * (x86 and co have 14-bit size, thus it's valid, though.)
+ * As a workaround for skipping the size-limit check, here we don't use the
+ * normal _IOW() macro but _IOC() with the manual argument.
+ */
+#define SNDRV_SB_CSP_IOCTL_LOAD_CODE	\
+	_IOC(_IOC_WRITE, 'H', 0x11, sizeof(struct snd_sb_csp_microcode))
+/* unload microcode from CSP */
+#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE	_IO('H', 0x12)
+/* start CSP */
+#define SNDRV_SB_CSP_IOCTL_START		_IOW('H', 0x13, struct snd_sb_csp_start)
+/* stop CSP */
+#define SNDRV_SB_CSP_IOCTL_STOP		_IO('H', 0x14)
+/* pause CSP and DMA transfer */
+#define SNDRV_SB_CSP_IOCTL_PAUSE		_IO('H', 0x15)
+/* restart CSP and DMA transfer */
+#define SNDRV_SB_CSP_IOCTL_RESTART	_IO('H', 0x16)
+
+
+#endif /* _UAPI__SOUND_SB16_CSP_H */
diff --git a/include/uapi/sound/sfnt_info.h b/include/uapi/sound/sfnt_info.h
new file mode 100644
index 0000000..1bce7fd
--- /dev/null
+++ b/include/uapi/sound/sfnt_info.h
@@ -0,0 +1,212 @@
+#ifndef __SOUND_SFNT_INFO_H
+#define __SOUND_SFNT_INFO_H
+
+/*
+ *  Patch record compatible with AWE driver on OSS
+ *
+ *  Copyright (C) 1999-2000 Takashi Iwai
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You 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 <sound/asound.h>
+
+/*
+ * patch information record
+ */
+
+#ifdef SNDRV_BIG_ENDIAN
+#define SNDRV_OSS_PATCHKEY(id) (0xfd00|id)
+#else
+#define SNDRV_OSS_PATCHKEY(id) ((id<<8)|0xfd)
+#endif
+
+/* patch interface header: 16 bytes */
+struct soundfont_patch_info {
+	unsigned short key;		/* use the key below */
+#define SNDRV_OSS_SOUNDFONT_PATCH		SNDRV_OSS_PATCHKEY(0x07)
+
+	short device_no;		/* synthesizer number */
+	unsigned short sf_id;		/* file id (should be zero) */
+	short optarg;			/* optional argument */
+	int len;			/* data length (without this header) */
+
+	short type;			/* patch operation type */
+#define SNDRV_SFNT_LOAD_INFO		0	/* awe_voice_rec */
+#define SNDRV_SFNT_LOAD_DATA		1	/* awe_sample_info */
+#define SNDRV_SFNT_OPEN_PATCH	2	/* awe_open_parm */
+#define SNDRV_SFNT_CLOSE_PATCH	3	/* none */
+	/* 4 is obsolete */
+#define SNDRV_SFNT_REPLACE_DATA	5	/* awe_sample_info (optarg=#channels)*/
+#define SNDRV_SFNT_MAP_PRESET	6	/* awe_voice_map */
+	/* 7 is not used */
+#define SNDRV_SFNT_PROBE_DATA		8	/* optarg=sample */
+#define SNDRV_SFNT_REMOVE_INFO		9	/* optarg=(bank<<8)|instr */
+
+	short reserved;			/* word alignment data */
+
+	/* the actual patch data begins after this */
+};
+
+
+/*
+ * open patch
+ */
+
+#define SNDRV_SFNT_PATCH_NAME_LEN	32
+
+struct soundfont_open_parm {
+	unsigned short type;		/* sample type */
+#define SNDRV_SFNT_PAT_TYPE_MISC	0
+#define SNDRV_SFNT_PAT_TYPE_GUS	6
+#define SNDRV_SFNT_PAT_TYPE_MAP	7
+#define SNDRV_SFNT_PAT_LOCKED	0x100	/* lock the samples */
+#define SNDRV_SFNT_PAT_SHARED	0x200	/* sample is shared */
+
+	short reserved;
+	char name[SNDRV_SFNT_PATCH_NAME_LEN];
+};
+
+
+/*
+ * raw voice information record
+ */
+
+/* wave table envelope & effect parameters to control EMU8000 */
+struct soundfont_voice_parm {
+	unsigned short moddelay;	/* modulation delay (0x8000) */
+	unsigned short modatkhld;	/* modulation attack & hold time (0x7f7f) */
+	unsigned short moddcysus;	/* modulation decay & sustain (0x7f7f) */
+	unsigned short modrelease;	/* modulation release time (0x807f) */
+	short modkeyhold, modkeydecay;	/* envelope change per key (not used) */
+	unsigned short voldelay;	/* volume delay (0x8000) */
+	unsigned short volatkhld;	/* volume attack & hold time (0x7f7f) */
+	unsigned short voldcysus;	/* volume decay & sustain (0x7f7f) */
+	unsigned short volrelease;	/* volume release time (0x807f) */
+	short volkeyhold, volkeydecay;	/* envelope change per key (not used) */
+	unsigned short lfo1delay;	/* LFO1 delay (0x8000) */
+	unsigned short lfo2delay;	/* LFO2 delay (0x8000) */
+	unsigned short pefe;		/* modulation pitch & cutoff (0x0000) */
+	unsigned short fmmod;		/* LFO1 pitch & cutoff (0x0000) */
+	unsigned short tremfrq;		/* LFO1 volume & freq (0x0000) */
+	unsigned short fm2frq2;		/* LFO2 pitch & freq (0x0000) */
+	unsigned char cutoff;		/* initial cutoff (0xff) */
+	unsigned char filterQ;		/* initial filter Q [0-15] (0x0) */
+	unsigned char chorus;		/* chorus send (0x00) */
+	unsigned char reverb;		/* reverb send (0x00) */
+	unsigned short reserved[4];	/* not used */
+};
+
+
+/* wave table parameters: 92 bytes */
+struct soundfont_voice_info {
+	unsigned short sf_id;		/* file id (should be zero) */
+	unsigned short sample;		/* sample id */
+	int start, end;			/* sample offset correction */
+	int loopstart, loopend;		/* loop offset correction */
+	short rate_offset;		/* sample rate pitch offset */
+	unsigned short mode;		/* sample mode */
+#define SNDRV_SFNT_MODE_ROMSOUND		0x8000
+#define SNDRV_SFNT_MODE_STEREO		1
+#define SNDRV_SFNT_MODE_LOOPING		2
+#define SNDRV_SFNT_MODE_NORELEASE		4	/* obsolete */
+#define SNDRV_SFNT_MODE_INIT_PARM		8
+
+	short root;			/* midi root key */
+	short tune;			/* pitch tuning (in cents) */
+	unsigned char low, high;	/* key note range */
+	unsigned char vellow, velhigh;	/* velocity range */
+	signed char fixkey, fixvel;	/* fixed key, velocity */
+	signed char pan, fixpan;	/* panning, fixed panning */
+	short exclusiveClass;		/* exclusive class (0 = none) */
+	unsigned char amplitude;	/* sample volume (127 max) */
+	unsigned char attenuation;	/* attenuation (0.375dB) */
+	short scaleTuning;		/* pitch scale tuning(%), normally 100 */
+	struct soundfont_voice_parm parm;	/* voice envelope parameters */
+	unsigned short sample_mode;	/* sample mode_flag (set by driver) */
+};
+
+
+/* instrument info header: 4 bytes */
+struct soundfont_voice_rec_hdr {
+	unsigned char bank;		/* midi bank number */
+	unsigned char instr;		/* midi preset number */
+	char nvoices;			/* number of voices */
+	char write_mode;		/* write mode; normally 0 */
+#define SNDRV_SFNT_WR_APPEND		0	/* append anyway */
+#define SNDRV_SFNT_WR_EXCLUSIVE		1	/* skip if already exists */
+#define SNDRV_SFNT_WR_REPLACE		2	/* replace if already exists */
+};
+
+
+/*
+ * sample wave information
+ */
+
+/* wave table sample header: 32 bytes */
+struct soundfont_sample_info {
+	unsigned short sf_id;		/* file id (should be zero) */
+	unsigned short sample;		/* sample id */
+	int start, end;			/* start & end offset */
+	int loopstart, loopend;		/* loop start & end offset */
+	int size;			/* size (0 = ROM) */
+	short dummy;			/* not used */
+	unsigned short mode_flags;	/* mode flags */
+#define SNDRV_SFNT_SAMPLE_8BITS		1	/* wave data is 8bits */
+#define SNDRV_SFNT_SAMPLE_UNSIGNED	2	/* wave data is unsigned */
+#define SNDRV_SFNT_SAMPLE_NO_BLANK	4	/* no blank loop is attached */
+#define SNDRV_SFNT_SAMPLE_SINGLESHOT	8	/* single-shot w/o loop */
+#define SNDRV_SFNT_SAMPLE_BIDIR_LOOP	16	/* bidirectional looping */
+#define SNDRV_SFNT_SAMPLE_STEREO_LEFT	32	/* stereo left sound */
+#define SNDRV_SFNT_SAMPLE_STEREO_RIGHT	64	/* stereo right sound */
+#define SNDRV_SFNT_SAMPLE_REVERSE_LOOP	128	/* reverse looping */
+	unsigned int truesize;		/* used memory size (set by driver) */
+};
+
+
+/*
+ * voice preset mapping (aliasing)
+ */
+
+struct soundfont_voice_map {
+	int map_bank, map_instr, map_key;	/* key = -1 means all keys */
+	int src_bank, src_instr, src_key;
+};
+
+
+/*
+ * ioctls for hwdep
+ */
+
+#define SNDRV_EMUX_HWDEP_NAME	"Emux WaveTable"
+
+#define SNDRV_EMUX_VERSION	((1 << 16) | (0 << 8) | 0)	/* 1.0.0 */
+
+struct snd_emux_misc_mode {
+	int port;	/* -1 = all */
+	int mode;
+	int value;
+	int value2;	/* reserved */
+};
+
+#define SNDRV_EMUX_IOCTL_VERSION	_IOR('H', 0x80, unsigned int)
+#define SNDRV_EMUX_IOCTL_LOAD_PATCH	_IOWR('H', 0x81, struct soundfont_patch_info)
+#define SNDRV_EMUX_IOCTL_RESET_SAMPLES	_IO('H', 0x82)
+#define SNDRV_EMUX_IOCTL_REMOVE_LAST_SAMPLES _IO('H', 0x83)
+#define SNDRV_EMUX_IOCTL_MEM_AVAIL	_IOW('H', 0x84, int)
+#define SNDRV_EMUX_IOCTL_MISC_MODE	_IOWR('H', 0x84, struct snd_emux_misc_mode)
+
+#endif /* __SOUND_SFNT_INFO_H */
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 3729173..b1248c2 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -158,7 +158,6 @@ enum omap_display_caps {
 enum omap_dss_display_state {
 	OMAP_DSS_DISPLAY_DISABLED = 0,
 	OMAP_DSS_DISPLAY_ACTIVE,
-	OMAP_DSS_DISPLAY_SUSPENDED,
 };
 
 enum omap_dss_audio_state {
@@ -314,6 +313,19 @@ int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel);
 int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel);
 void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel);
 
+enum omapdss_version {
+	OMAPDSS_VER_UNKNOWN = 0,
+	OMAPDSS_VER_OMAP24xx,
+	OMAPDSS_VER_OMAP34xx_ES1,	/* OMAP3430 ES1.0, 2.0 */
+	OMAPDSS_VER_OMAP34xx_ES3,	/* OMAP3430 ES3.0+ */
+	OMAPDSS_VER_OMAP3630,
+	OMAPDSS_VER_AM35xx,
+	OMAPDSS_VER_OMAP4430_ES1,	/* OMAP4430 ES1.0 */
+	OMAPDSS_VER_OMAP4430_ES2,	/* OMAP4430 ES2.0, 2.1, 2.2 */
+	OMAPDSS_VER_OMAP4,		/* All other OMAP4s */
+	OMAPDSS_VER_OMAP5,
+};
+
 /* Board specific data */
 struct omap_dss_board_info {
 	int (*get_context_loss_count)(struct device *dev);
@@ -323,6 +335,7 @@ struct omap_dss_board_info {
 	int (*dsi_enable_pads)(int dsi_id, unsigned lane_mask);
 	void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask);
 	int (*set_min_bus_tput)(struct device *dev, unsigned long r);
+	enum omapdss_version version;
 };
 
 /* Init with the board info */
@@ -607,10 +620,6 @@ struct omap_dss_device {
 	struct {
 		struct omap_video_timings timings;
 
-		int acbi;	/* ac-bias pin transitions per interrupt */
-		/* Unit: line clocks */
-		int acb;	/* ac-bias pin frequency */
-
 		enum omap_dss_dsi_pixel_format dsi_pix_fmt;
 		enum omap_dss_dsi_mode dsi_mode;
 		struct omap_dss_dsi_videomode_timings dsi_vm_timings;
@@ -672,8 +681,6 @@ struct omap_dss_driver {
 
 	int (*enable)(struct omap_dss_device *display);
 	void (*disable)(struct omap_dss_device *display);
-	int (*suspend)(struct omap_dss_device *display);
-	int (*resume)(struct omap_dss_device *display);
 	int (*run_test)(struct omap_dss_device *display, int test);
 
 	int (*update)(struct omap_dss_device *dssdev,
@@ -731,6 +738,8 @@ struct omap_dss_driver {
 
 };
 
+enum omapdss_version omapdss_get_version(void);
+
 int omap_dss_register_driver(struct omap_dss_driver *);
 void omap_dss_unregister_driver(struct omap_dss_driver *);
 
@@ -740,6 +749,7 @@ void omap_dss_put_device(struct omap_dss_device *dssdev);
 struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from);
 struct omap_dss_device *omap_dss_find_device(void *data,
 		int (*match)(struct omap_dss_device *dssdev, void *data));
+const char *omapdss_get_default_display_name(void);
 
 int omap_dss_start_device(struct omap_dss_device *dssdev);
 void omap_dss_stop_device(struct omap_dss_device *dssdev);
diff --git a/include/video/omapvrfb.h b/include/video/omapvrfb.h
new file mode 100644
index 0000000..bb0bd89
--- /dev/null
+++ b/include/video/omapvrfb.h
@@ -0,0 +1,68 @@
+/*
+ * VRFB Rotation Engine
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef __OMAP_VRFB_H__
+#define __OMAP_VRFB_H__
+
+#define OMAP_VRFB_LINE_LEN 2048
+
+struct vrfb {
+	u8 context;
+	void __iomem *vaddr[4];
+	unsigned long paddr[4];
+	u16 xres;
+	u16 yres;
+	u16 xoffset;
+	u16 yoffset;
+	u8 bytespp;
+	bool yuv_mode;
+};
+
+#ifdef CONFIG_OMAP2_VRFB
+extern bool omap_vrfb_supported(void);
+extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
+extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
+extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
+		u8 bytespp);
+extern u32 omap_vrfb_min_phys_size(u16 width, u16 height, u8 bytespp);
+extern u16 omap_vrfb_max_height(u32 phys_size, u16 width, u8 bytespp);
+extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+		u16 width, u16 height,
+		unsigned bytespp, bool yuv_mode);
+extern int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot);
+extern void omap_vrfb_restore_context(void);
+
+#else
+static inline bool omap_vrfb_supported(void) { return false; }
+static inline int omap_vrfb_request_ctx(struct vrfb *vrfb) { return 0; }
+static inline void omap_vrfb_release_ctx(struct vrfb *vrfb) {}
+static inline void omap_vrfb_adjust_size(u16 *width, u16 *height,
+		u8 bytespp) {}
+static inline u32 omap_vrfb_min_phys_size(u16 width, u16 height, u8 bytespp)
+		{ return 0; }
+static inline u16 omap_vrfb_max_height(u32 phys_size, u16 width, u8 bytespp)
+		{ return 0; }
+static inline void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+		u16 width, u16 height, unsigned bytespp, bool yuv_mode) {}
+static inline int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot)
+		{ return 0; }
+static inline void omap_vrfb_restore_context(void) {}
+#endif
+#endif /* __VRFB_H */
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
index 694dcaf..8e39879 100644
--- a/include/xen/grant_table.h
+++ b/include/xen/grant_table.h
@@ -190,16 +190,4 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
 		      struct gnttab_map_grant_ref *kunmap_ops,
 		      struct page **pages, unsigned int count);
 
-/* Perform a batch of grant map/copy operations. Retry every batch slot
- * for which the hypervisor returns GNTST_eagain. This is typically due
- * to paged out target frames.
- *
- * Will retry for 1, 2, ... 255 ms, i.e. 256 times during 32 seconds.
- *
- * Return value in each iand every status field of the batch guaranteed
- * to not be GNTST_eagain.
- */
-void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count);
-void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count);
-
 #endif /* __ASM_GNTTAB_H__ */
diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h
index 90712e2..b40a431 100644
--- a/include/xen/interface/memory.h
+++ b/include/xen/interface/memory.h
@@ -153,6 +153,14 @@ struct xen_machphys_mapping {
 };
 DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mapping_t);
 
+#define XENMAPSPACE_shared_info  0 /* shared info page */
+#define XENMAPSPACE_grant_table  1 /* grant table page */
+#define XENMAPSPACE_gmfn         2 /* GMFN */
+#define XENMAPSPACE_gmfn_range   3 /* GMFN range, XENMEM_add_to_physmap only. */
+#define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another dom,
+				    * XENMEM_add_to_physmap_range only.
+				    */
+
 /*
  * Sets the GPFN at which a particular page appears in the specified guest's
  * pseudophysical address space.
@@ -167,8 +175,6 @@ struct xen_add_to_physmap {
     uint16_t    size;
 
     /* Source mapping space. */
-#define XENMAPSPACE_shared_info 0 /* shared info page */
-#define XENMAPSPACE_grant_table 1 /* grant table page */
     unsigned int space;
 
     /* Index into source mapping space. */
@@ -182,6 +188,24 @@ DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap);
 /*** REMOVED ***/
 /*#define XENMEM_translate_gpfn_list  8*/
 
+#define XENMEM_add_to_physmap_range 23
+struct xen_add_to_physmap_range {
+    /* Which domain to change the mapping for. */
+    domid_t domid;
+    uint16_t space; /* => enum phys_map_space */
+
+    /* Number of pages to go through */
+    uint16_t size;
+    domid_t foreign_domid; /* IFF gmfn_foreign */
+
+    /* Indexes into space being mapped. */
+    GUEST_HANDLE(xen_ulong_t) idxs;
+
+    /* GPFN in domid where the source mapping page should appear. */
+    GUEST_HANDLE(xen_pfn_t) gpfns;
+};
+DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap_range);
+
 /*
  * Returns the pseudo-physical memory map as it was when the domain
  * was started (specified by XENMEM_set_memory_map).
@@ -217,4 +241,20 @@ DEFINE_GUEST_HANDLE_STRUCT(xen_memory_map);
  * during a driver critical region.
  */
 extern spinlock_t xen_reservation_lock;
+
+/*
+ * Unmaps the page appearing at a particular GPFN from the specified guest's
+ * pseudophysical address space.
+ * arg == addr of xen_remove_from_physmap_t.
+ */
+#define XENMEM_remove_from_physmap      15
+struct xen_remove_from_physmap {
+    /* Which domain to change the mapping for. */
+    domid_t domid;
+
+    /* GPFN of the current mapping of the page. */
+    xen_pfn_t gpfn;
+};
+DEFINE_GUEST_HANDLE_STRUCT(xen_remove_from_physmap);
+
 #endif /* __XEN_PUBLIC_MEMORY_H__ */
diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h
index 1844d31..83050d3 100644
--- a/include/xen/interface/physdev.h
+++ b/include/xen/interface/physdev.h
@@ -274,6 +274,16 @@ struct physdev_dbgp_op {
     } u;
 };
 
+#define PHYSDEVOP_map_iomem        30
+struct physdev_map_iomem {
+    /* IN */
+    uint64_t first_gfn;
+    uint64_t first_mfn;
+    uint32_t nr_mfns;
+    uint32_t add_mapping; /* 1 == add mapping;  0 == unmap */
+
+};
+
 /*
  * Notify that some PIRQ-bound event channels have been unmasked.
  * ** This command is obsolete since interface version 0x00030202 and is **
diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h
index 4755b5f..5e36932 100644
--- a/include/xen/interface/platform.h
+++ b/include/xen/interface/platform.h
@@ -324,6 +324,22 @@ struct xenpf_cpu_ol {
 };
 DEFINE_GUEST_HANDLE_STRUCT(xenpf_cpu_ol);
 
+/*
+ * CMD 58 and 59 are reserved for cpu hotadd and memory hotadd,
+ * which are already occupied at Xen hypervisor side.
+ */
+#define XENPF_core_parking     60
+struct xenpf_core_parking {
+	/* IN variables */
+#define XEN_CORE_PARKING_SET   1
+#define XEN_CORE_PARKING_GET   2
+	uint32_t type;
+	/* IN variables:  set cpu nums expected to be idled */
+	/* OUT variables: get cpu nums actually be idled */
+	uint32_t idle_nums;
+};
+DEFINE_GUEST_HANDLE_STRUCT(xenpf_core_parking);
+
 struct xen_platform_op {
 	uint32_t cmd;
 	uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
@@ -341,6 +357,7 @@ struct xen_platform_op {
 		struct xenpf_set_processor_pminfo set_pminfo;
 		struct xenpf_pcpuinfo          pcpu_info;
 		struct xenpf_cpu_ol            cpu_ol;
+		struct xenpf_core_parking      core_parking;
 		uint8_t                        pad[128];
 	} u;
 };
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index 6a198e4..d6fe062 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -2,6 +2,7 @@
 #define INCLUDE_XEN_OPS_H
 
 #include <linux/percpu.h>
+#include <asm/xen/interface.h>
 
 DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
 
@@ -26,7 +27,11 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order);
 struct vm_area_struct;
 int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
 			       unsigned long addr,
-			       unsigned long mfn, int nr,
-			       pgprot_t prot, unsigned domid);
+			       xen_pfn_t mfn, int nr,
+			       pgprot_t prot, unsigned domid,
+			       struct page **pages);
+int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
+			       int numpgs, struct page **pages);
 
+bool xen_running_on_version_or_later(unsigned int major, unsigned int minor);
 #endif /* INCLUDE_XEN_OPS_H */
diff --git a/init/Kconfig b/init/Kconfig
index 6fdd6e3..a552428 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -33,35 +33,8 @@ config BUILDTIME_EXTABLE_SORT
 menu "General setup"
 
 config EXPERIMENTAL
-	bool "Prompt for development and/or incomplete code/drivers"
-	---help---
-	  Some of the various things that Linux supports (such as network
-	  drivers, file systems, network protocols, etc.) can be in a state
-	  of development where the functionality, stability, or the level of
-	  testing is not yet high enough for general use. This is usually
-	  known as the "alpha-test" phase among developers. If a feature is
-	  currently in alpha-test, then the developers usually discourage
-	  uninformed widespread use of this feature by the general public to
-	  avoid "Why doesn't this work?" type mail messages. However, active
-	  testing and use of these systems is welcomed. Just be aware that it
-	  may not meet the normal level of reliability or it may fail to work
-	  in some special cases. Detailed bug reports from people familiar
-	  with the kernel internals are usually welcomed by the developers
-	  (before submitting bug reports, please read the documents
-	  <file:README>, <file:MAINTAINERS>, <file:REPORTING-BUGS>,
-	  <file:Documentation/BUG-HUNTING>, and
-	  <file:Documentation/oops-tracing.txt> in the kernel source).
-
-	  This option will also make obsoleted drivers available. These are
-	  drivers that have been replaced by something else, and/or are
-	  scheduled to be removed in a future kernel release.
-
-	  Unless you intend to help test and develop a feature or driver that
-	  falls into this category, or you have a situation that requires
-	  using these features, you should probably say N here, which will
-	  cause the configurator to present you with fewer choices. If
-	  you say Y here, you will be offered the choice of using features or
-	  drivers that are currently considered to be in the alpha-test phase.
+	bool
+	default y
 
 config BROKEN
 	bool
@@ -247,7 +220,7 @@ config SYSVIPC_SYSCTL
 
 config POSIX_MQUEUE
 	bool "POSIX Message Queues"
-	depends on NET && EXPERIMENTAL
+	depends on NET
 	---help---
 	  POSIX variant of message queues is a part of IPC. In POSIX message
 	  queues every message has a priority which decides about succession
@@ -393,7 +366,7 @@ config BSD_PROCESS_ACCT_V3
 	  at <http://www.gnu.org/software/acct/>.
 
 config TASKSTATS
-	bool "Export task/process statistics through netlink (EXPERIMENTAL)"
+	bool "Export task/process statistics through netlink"
 	depends on NET
 	default n
 	help
@@ -406,7 +379,7 @@ config TASKSTATS
 	  Say N if unsure.
 
 config TASK_DELAY_ACCT
-	bool "Enable per-task delay accounting (EXPERIMENTAL)"
+	bool "Enable per-task delay accounting"
 	depends on TASKSTATS
 	help
 	  Collect information on time spent by a task waiting for system
@@ -417,7 +390,7 @@ config TASK_DELAY_ACCT
 	  Say N if unsure.
 
 config TASK_XACCT
-	bool "Enable extended accounting over taskstats (EXPERIMENTAL)"
+	bool "Enable extended accounting over taskstats"
 	depends on TASKSTATS
 	help
 	  Collect extended task accounting data and send the data
@@ -426,7 +399,7 @@ config TASK_XACCT
 	  Say N if unsure.
 
 config TASK_IO_ACCOUNTING
-	bool "Enable per-task storage I/O accounting (EXPERIMENTAL)"
+	bool "Enable per-task storage I/O accounting"
 	depends on TASK_XACCT
 	help
 	  Collect information on the number of bytes of storage I/O which this
@@ -486,35 +459,35 @@ config PREEMPT_RCU
 	  This option enables preemptible-RCU code that is common between
 	  the TREE_PREEMPT_RCU and TINY_PREEMPT_RCU implementations.
 
+config CONTEXT_TRACKING
+       bool
+
 config RCU_USER_QS
 	bool "Consider userspace as in RCU extended quiescent state"
-	depends on HAVE_RCU_USER_QS && SMP
+	depends on HAVE_CONTEXT_TRACKING && SMP
+	select CONTEXT_TRACKING
 	help
 	  This option sets hooks on kernel / userspace boundaries and
 	  puts RCU in extended quiescent state when the CPU runs in
 	  userspace. It means that when a CPU runs in userspace, it is
 	  excluded from the global RCU state machine and thus doesn't
-	  to keep the timer tick on for RCU.
+	  try to keep the timer tick on for RCU.
 
 	  Unless you want to hack and help the development of the full
-	  tickless feature, you shouldn't enable this option. It adds
-	  unnecessary overhead.
+	  dynticks mode, you shouldn't enable this option.  It also
+	  adds unnecessary overhead.
 
 	  If unsure say N
 
-config RCU_USER_QS_FORCE
-	bool "Force userspace extended QS by default"
-	depends on RCU_USER_QS
+config CONTEXT_TRACKING_FORCE
+	bool "Force context tracking"
+	depends on CONTEXT_TRACKING
 	help
-	  Set the hooks in user/kernel boundaries by default in order to
-	  test this feature that treats userspace as an extended quiescent
-	  state until we have a real user like a full adaptive nohz option.
-
-	  Unless you want to hack and help the development of the full
-	  tickless feature, you shouldn't enable this option. It adds
-	  unnecessary overhead.
-
-	  If unsure say N
+	  Probe on user/kernel boundaries by default in order to
+	  test the features that rely on it such as userspace RCU extended
+	  quiescent states.
+	  This test is there for debugging until we have a real user like the
+	  full dynticks mode.
 
 config RCU_FANOUT
 	int "Tree-based hierarchical RCU fanout value"
@@ -582,14 +555,13 @@ config RCU_FAST_NO_HZ
 	depends on NO_HZ && SMP
 	default n
 	help
-	  This option causes RCU to attempt to accelerate grace periods
-	  in order to allow CPUs to enter dynticks-idle state more
-	  quickly.  On the other hand, this option increases the overhead
-	  of the dynticks-idle checking, particularly on systems with
-	  large numbers of CPUs.
+	  This option causes RCU to attempt to accelerate grace periods in
+	  order to allow CPUs to enter dynticks-idle state more quickly.
+	  On the other hand, this option increases the overhead of the
+	  dynticks-idle checking, thus degrading scheduling latency.
 
-	  Say Y if energy efficiency is critically important, particularly
-	  	if you have relatively few CPUs.
+	  Say Y if energy efficiency is critically important, and you don't
+	  	care about real-time response.
 
 	  Say N if you are unsure.
 
@@ -655,6 +627,28 @@ config RCU_BOOST_DELAY
 
 	  Accept the default if unsure.
 
+config RCU_NOCB_CPU
+	bool "Offload RCU callback processing from boot-selected CPUs"
+	depends on TREE_RCU || TREE_PREEMPT_RCU
+	default n
+	help
+	  Use this option to reduce OS jitter for aggressive HPC or
+	  real-time workloads.	It can also be used to offload RCU
+	  callback invocation to energy-efficient CPUs in battery-powered
+	  asymmetric multiprocessors.
+
+	  This option offloads callback invocation from the set of
+	  CPUs specified at boot time by the rcu_nocbs parameter.
+	  For each such CPU, a kthread ("rcuoN") will be created to
+	  invoke callbacks, where the "N" is the CPU being offloaded.
+	  Nothing prevents this kthread from running on the specified
+	  CPUs, but (1) the kthreads may be preempted between each
+	  callback, and (2) affinity or cgroups can be used to force
+	  the kthreads to run on whatever set of CPUs is desired.
+
+	  Say Y here if you want reduced OS jitter on selected CPUs.
+	  Say N here if you are unsure.
+
 endmenu # "RCU Subsystem"
 
 config IKCONFIG
@@ -696,6 +690,87 @@ config LOG_BUF_SHIFT
 config HAVE_UNSTABLE_SCHED_CLOCK
 	bool
 
+#
+# For architectures that (ab)use NUMA to represent different memory regions
+# all cpu-local but of different latencies, such as SuperH.
+#
+config ARCH_WANTS_NUMA_VARIABLE_LOCALITY
+	bool
+
+#
+# For architectures that want to enable NUMA-affine scheduling
+# and memory placement:
+#
+config ARCH_SUPPORTS_NUMA_BALANCING
+	bool
+
+#
+# For architectures that want to reuse the PROT_NONE bits
+# to implement NUMA protection bits:
+#
+config ARCH_WANTS_NUMA_GENERIC_PGPROT
+	bool
+
+config NUMA_BALANCING
+	bool "NUMA-optimizing scheduler"
+	default n
+	depends on ARCH_SUPPORTS_NUMA_BALANCING
+	depends on !ARCH_WANTS_NUMA_VARIABLE_LOCALITY
+	depends on SMP && NUMA && MIGRATION
+	help
+	  This option enables NUMA-aware, transparent, automatic
+	  placement optimizations of memory, tasks and task groups.
+
+	  The optimizations work by (transparently) runtime sampling the
+	  workload sharing relationship between threads and processes
+	  of long-run workloads, and scheduling them based on these
+	  measured inter-task relationships (or the lack thereof).
+
+	  ("Long-run" means several seconds of CPU runtime at least.)
+
+	  Tasks that predominantly perform their own processing, without
+	  interacting with other tasks much will be independently balanced
+	  to a CPU and their working set memory will migrate to that CPU/node.
+
+	  Tasks that share a lot of data with each other will be attempted to
+	  be scheduled on as few nodes as possible, with their memory
+	  following them there and being distributed between those nodes.
+
+	  This optimization can improve the performance of long-run CPU-bound
+	  workloads by 10% or more. The sampling and migration has a small
+	  but nonzero cost, so if your NUMA workload is already perfectly
+	  placed (for example by use of explicit CPU and memory bindings,
+	  or because the stock scheduler does a good job already) then you
+	  probably don't need this feature.
+
+	  [ On non-NUMA systems this feature will not be active. You can query
+	    whether your system is a NUMA system via looking at the output of
+	    "numactl --hardware". ]
+
+	  Say N if unsure.
+
+#
+# Helper Kconfig switches to express compound feature dependencies
+# and thus make the .h/.c code more readable:
+#
+config NUMA_BALANCING_HUGEPAGE
+	bool
+	default y
+	depends on NUMA_BALANCING
+	depends on TRANSPARENT_HUGEPAGE
+
+config ARCH_USES_NUMA_GENERIC_PGPROT
+	bool
+	default y
+	depends on ARCH_WANTS_NUMA_GENERIC_PGPROT
+	depends on NUMA_BALANCING
+
+config ARCH_USES_NUMA_GENERIC_PGPROT_HUGEPAGE
+	bool
+	default y
+	depends on ARCH_USES_NUMA_GENERIC_PGPROT
+	depends on TRANSPARENT_HUGEPAGE
+
 menuconfig CGROUPS
 	boolean "Control Group support"
 	depends on EVENTFD
@@ -815,9 +890,8 @@ config MEMCG_SWAP_ENABLED
 	  select this option (if, for some reason, they need to disable it
 	  then swapaccount=0 does the trick).
 config MEMCG_KMEM
-	bool "Memory Resource Controller Kernel Memory accounting (EXPERIMENTAL)"
-	depends on MEMCG && EXPERIMENTAL
-	default n
+	bool "Memory Resource Controller Kernel Memory accounting"
+	depends on MEMCG && !SLOB
 	help
 	  The Kernel Memory extension for Memory Resource Controller can limit
 	  the amount of memory used by kernel objects in the system. Those are
@@ -828,7 +902,7 @@ config MEMCG_KMEM
 
 config CGROUP_HUGETLB
 	bool "HugeTLB Resource Controller for Control Groups"
-	depends on RESOURCE_COUNTERS && HUGETLB_PAGE && EXPERIMENTAL
+	depends on RESOURCE_COUNTERS && HUGETLB_PAGE
 	default n
 	help
 	  Provides a cgroup Resource Controller for HugeTLB pages.
@@ -867,7 +941,6 @@ config FAIR_GROUP_SCHED
 
 config CFS_BANDWIDTH
 	bool "CPU bandwidth provisioning for FAIR_GROUP_SCHED"
-	depends on EXPERIMENTAL
 	depends on FAIR_GROUP_SCHED
 	default n
 	help
@@ -879,7 +952,6 @@ config CFS_BANDWIDTH
 
 config RT_GROUP_SCHED
 	bool "Group scheduling for SCHED_RR/FIFO"
-	depends on EXPERIMENTAL
 	depends on CGROUP_SCHED
 	default n
 	help
@@ -961,8 +1033,7 @@ config IPC_NS
 	  different IPC objects in different namespaces.
 
 config USER_NS
-	bool "User namespace (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	bool "User namespace"
 	depends on UIDGID_CONVERTED
 	select UIDGID_STRICT_TYPE_CHECKS
 
@@ -1004,11 +1075,9 @@ config UIDGID_CONVERTED
 	# Filesystems
 	depends on 9P_FS = n
 	depends on AFS_FS = n
-	depends on AUTOFS4_FS = n
 	depends on CEPH_FS = n
 	depends on CIFS = n
 	depends on CODA_FS = n
-	depends on FUSE_FS = n
 	depends on GFS2_FS = n
 	depends on NCP_FS = n
 	depends on NFSD = n
@@ -1545,7 +1614,7 @@ config MODULE_UNLOAD
 
 config MODULE_FORCE_UNLOAD
 	bool "Forced module unloading"
-	depends on MODULE_UNLOAD && EXPERIMENTAL
+	depends on MODULE_UNLOAD
 	help
 	  This option allows you to force a module to unload, even if the
 	  kernel believes it is unsafe: the kernel will remove the module
diff --git a/init/do_mounts.c b/init/do_mounts.c
index f8a6642..1d1b634 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -69,23 +69,28 @@ __setup("ro", readonly);
 __setup("rw", readwrite);
 
 #ifdef CONFIG_BLOCK
+struct uuidcmp {
+	const char *uuid;
+	int len;
+};
+
 /**
  * match_dev_by_uuid - callback for finding a partition using its uuid
  * @dev:	device passed in by the caller
- * @data:	opaque pointer to a 36 byte char array with a UUID
+ * @data:	opaque pointer to the desired struct uuidcmp to match
  *
  * Returns 1 if the device matches, and 0 otherwise.
  */
 static int match_dev_by_uuid(struct device *dev, void *data)
 {
-	u8 *uuid = data;
+	struct uuidcmp *cmp = data;
 	struct hd_struct *part = dev_to_part(dev);
 
 	if (!part->info)
 		goto no_match;
 
-	if (memcmp(uuid, part->info->uuid, sizeof(part->info->uuid)))
-			goto no_match;
+	if (strncasecmp(cmp->uuid, part->info->uuid, cmp->len))
+		goto no_match;
 
 	return 1;
 no_match:
@@ -95,7 +100,7 @@ no_match:
 
 /**
  * devt_from_partuuid - looks up the dev_t of a partition by its UUID
- * @uuid:	min 36 byte char array containing a hex ascii UUID
+ * @uuid:	char array containing ascii UUID
  *
  * The function will return the first partition which contains a matching
  * UUID value in its partition_meta_info struct.  This does not search
@@ -106,38 +111,41 @@ no_match:
  *
  * Returns the matching dev_t on success or 0 on failure.
  */
-static dev_t devt_from_partuuid(char *uuid_str)
+static dev_t devt_from_partuuid(const char *uuid_str)
 {
 	dev_t res = 0;
+	struct uuidcmp cmp;
 	struct device *dev = NULL;
-	u8 uuid[16];
 	struct gendisk *disk;
 	struct hd_struct *part;
 	int offset = 0;
+	bool clear_root_wait = false;
+	char *slash;
 
-	if (strlen(uuid_str) < 36)
-		goto done;
+	cmp.uuid = uuid_str;
 
+	slash = strchr(uuid_str, '/');
 	/* Check for optional partition number offset attributes. */
-	if (uuid_str[36]) {
+	if (slash) {
 		char c = 0;
 		/* Explicitly fail on poor PARTUUID syntax. */
-		if (sscanf(&uuid_str[36],
-			   "/PARTNROFF=%d%c", &offset, &c) != 1) {
-			printk(KERN_ERR "VFS: PARTUUID= is invalid.\n"
-			 "Expected PARTUUID=<valid-uuid-id>[/PARTNROFF=%%d]\n");
-			if (root_wait)
-				printk(KERN_ERR
-				     "Disabling rootwait; root= is invalid.\n");
-			root_wait = 0;
+		if (sscanf(slash + 1,
+			   "PARTNROFF=%d%c", &offset, &c) != 1) {
+			clear_root_wait = true;
 			goto done;
 		}
+		cmp.len = slash - uuid_str;
+	} else {
+		cmp.len = strlen(uuid_str);
 	}
 
-	/* Pack the requested UUID in the expected format. */
-	part_pack_uuid(uuid_str, uuid);
+	if (!cmp.len) {
+		clear_root_wait = true;
+		goto done;
+	}
 
-	dev = class_find_device(&block_class, NULL, uuid, &match_dev_by_uuid);
+	dev = class_find_device(&block_class, NULL, &cmp,
+				&match_dev_by_uuid);
 	if (!dev)
 		goto done;
 
@@ -158,6 +166,13 @@ static dev_t devt_from_partuuid(char *uuid_str)
 no_offset:
 	put_device(dev);
 done:
+	if (clear_root_wait) {
+		pr_err("VFS: PARTUUID= is invalid.\n"
+		       "Expected PARTUUID=<valid-uuid-id>[/PARTNROFF=%%d]\n");
+		if (root_wait)
+			pr_err("Disabling rootwait; root= is invalid.\n");
+		root_wait = 0;
+	}
 	return res;
 }
 #endif
@@ -174,6 +189,10 @@ done:
  *	   used when disk name of partitioned disk ends on a digit.
  *	6) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the
  *	   unique id of a partition if the partition table provides it.
+ *	   The UUID may be either an EFI/GPT UUID, or refer to an MSDOS
+ *	   partition using the format SSSSSSSS-PP, where SSSSSSSS is a zero-
+ *	   filled hex representation of the 32-bit "NT disk signature", and PP
+ *	   is a zero-filled hex representation of the 1-based partition number.
  *	7) PARTUUID=<UUID>/PARTNROFF=<int> to select a partition in relation to
  *	   a partition with a known unique id.
  *
diff --git a/init/main.c b/init/main.c
index e33e09d..baf1f0f 100644
--- a/init/main.c
+++ b/init/main.c
@@ -812,7 +812,6 @@ static int __ref kernel_init(void *unused)
 	system_state = SYSTEM_RUNNING;
 	numa_default_policy();
 
-	current->signal->flags |= SIGNAL_UNKILLABLE;
 	flush_delayed_fput();
 
 	if (ramdisk_execute_command) {
@@ -857,7 +856,7 @@ static void __init kernel_init_freeable(void)
 	/*
 	 * init can allocate pages on any node
 	 */
-	set_mems_allowed(node_states[N_HIGH_MEMORY]);
+	set_mems_allowed(node_states[N_MEMORY]);
 	/*
 	 * init can run on any cpu.
 	 */
diff --git a/init/version.c b/init/version.c
index 86fe0cc..58170f1 100644
--- a/init/version.c
+++ b/init/version.c
@@ -12,6 +12,7 @@
 #include <linux/utsname.h>
 #include <generated/utsrelease.h>
 #include <linux/version.h>
+#include <linux/proc_fs.h>
 
 #ifndef CONFIG_KALLSYMS
 #define version(a) Version_ ## a
@@ -34,6 +35,7 @@ struct uts_namespace init_uts_ns = {
 		.domainname	= UTS_DOMAINNAME,
 	},
 	.user_ns = &init_user_ns,
+	.proc_inum = PROC_UTS_INIT_INO,
 };
 EXPORT_SYMBOL_GPL(init_uts_ns);
 
diff --git a/ipc/compat.c b/ipc/compat.c
index ad9518e..2547f29 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -306,6 +306,20 @@ static long do_compat_semctl(int first, int second, int third, u32 pad)
 	return err;
 }
 
+long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
+{
+	struct compat_msgbuf __user *msgp = dest;
+	size_t msgsz;
+
+	if (put_user(msg->m_type, &msgp->mtype))
+		return -EFAULT;
+
+	msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz;
+	if (store_msg(msgp->mtext, msg, msgsz))
+		return -EFAULT;
+	return msgsz;
+}
+
 #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
 long compat_sys_semctl(int first, int second, int third, void __user *uptr)
 {
@@ -337,10 +351,6 @@ long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)
 long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
 			   int version, void __user *uptr)
 {
-	struct compat_msgbuf __user *up;
-	long type;
-	int err;
-
 	if (first < 0)
 		return -EINVAL;
 	if (second < 0)
@@ -348,23 +358,15 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
 
 	if (!version) {
 		struct compat_ipc_kludge ipck;
-		err = -EINVAL;
 		if (!uptr)
-			goto out;
-		err = -EFAULT;
+			return -EINVAL;
 		if (copy_from_user (&ipck, uptr, sizeof(ipck)))
-			goto out;
+			return -EFAULT;
 		uptr = compat_ptr(ipck.msgp);
 		msgtyp = ipck.msgtyp;
 	}
-	up = uptr;
-	err = do_msgrcv(first, &type, up->mtext, second, msgtyp, third);
-	if (err < 0)
-		goto out;
-	if (put_user(type, &up->mtype))
-		err = -EFAULT;
-out:
-	return err;
+	return do_msgrcv(first, uptr, second, msgtyp, third,
+			 compat_do_msg_fill);
 }
 #else
 long compat_sys_semctl(int semid, int semnum, int cmd, int arg)
@@ -385,16 +387,8 @@ long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp,
 long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp,
 		       compat_ssize_t msgsz, long msgtyp, int msgflg)
 {
-	long err, mtype;
-
-	err =  do_msgrcv(msqid, &mtype, msgp->mtext, (ssize_t)msgsz, msgtyp, msgflg);
-	if (err < 0)
-		goto out;
-
-	if (put_user(mtype, &msgp->mtype))
-		err = -EFAULT;
- out:
-	return err;
+	return do_msgrcv(msqid, msgp, (ssize_t)msgsz, msgtyp, msgflg,
+			 compat_do_msg_fill);
 }
 #endif
 
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index 00fba2b..130dfec 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -158,6 +158,9 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
 
 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[] = {
 	{
@@ -227,6 +230,35 @@ static struct ctl_table ipc_kern_table[] = {
 		.extra1		= &zero,
 		.extra2		= &one,
 	},
+#ifdef CONFIG_CHECKPOINT_RESTORE
+	{
+		.procname	= "sem_next_id",
+		.data		= &init_ipc_ns.ids[IPC_SEM_IDS].next_id,
+		.maxlen		= sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id),
+		.mode		= 0644,
+		.proc_handler	= proc_ipc_dointvec_minmax,
+		.extra1		= &zero,
+		.extra2		= &int_max,
+	},
+	{
+		.procname	= "msg_next_id",
+		.data		= &init_ipc_ns.ids[IPC_MSG_IDS].next_id,
+		.maxlen		= sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id),
+		.mode		= 0644,
+		.proc_handler	= proc_ipc_dointvec_minmax,
+		.extra1		= &zero,
+		.extra2		= &int_max,
+	},
+	{
+		.procname	= "shm_next_id",
+		.data		= &init_ipc_ns.ids[IPC_SHM_IDS].next_id,
+		.maxlen		= sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id),
+		.mode		= 0644,
+		.proc_handler	= proc_ipc_dointvec_minmax,
+		.extra1		= &zero,
+		.extra2		= &int_max,
+	},
+#endif
 	{}
 };
 
diff --git a/ipc/msg.c b/ipc/msg.c
index a71af5a..950572f 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -755,26 +755,91 @@ static inline int convert_mode(long *msgtyp, int msgflg)
 	return SEARCH_EQUAL;
 }
 
-long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
-		size_t msgsz, long msgtyp, int msgflg)
+static long do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
+{
+	struct msgbuf __user *msgp = dest;
+	size_t msgsz;
+
+	if (put_user(msg->m_type, &msgp->mtype))
+		return -EFAULT;
+
+	msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz;
+	if (store_msg(msgp->mtext, msg, msgsz))
+		return -EFAULT;
+	return msgsz;
+}
+
+#ifdef CONFIG_CHECKPOINT_RESTORE
+/*
+ * This function creates new kernel message structure, large enough to store
+ * bufsz message bytes.
+ */
+static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz,
+					   int msgflg, long *msgtyp,
+					   unsigned long *copy_number)
+{
+	struct msg_msg *copy;
+
+	*copy_number = *msgtyp;
+	*msgtyp = 0;
+	/*
+	 * Create dummy message to copy real message to.
+	 */
+	copy = load_msg(buf, bufsz);
+	if (!IS_ERR(copy))
+		copy->m_ts = bufsz;
+	return copy;
+}
+
+static inline void free_copy(struct msg_msg *copy)
+{
+	if (copy)
+		free_msg(copy);
+}
+#else
+static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz,
+					   int msgflg, long *msgtyp,
+					   unsigned long *copy_number)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline void free_copy(struct msg_msg *copy)
+{
+}
+#endif
+
+long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
+	       int msgflg,
+	       long (*msg_handler)(void __user *, struct msg_msg *, size_t))
 {
 	struct msg_queue *msq;
 	struct msg_msg *msg;
 	int mode;
 	struct ipc_namespace *ns;
+	struct msg_msg *copy = NULL;
+	unsigned long copy_number = 0;
 
-	if (msqid < 0 || (long) msgsz < 0)
+	if (msqid < 0 || (long) bufsz < 0)
 		return -EINVAL;
+	if (msgflg & MSG_COPY) {
+		copy = prepare_copy(buf, bufsz, msgflg, &msgtyp, &copy_number);
+		if (IS_ERR(copy))
+			return PTR_ERR(copy);
+	}
 	mode = convert_mode(&msgtyp, msgflg);
 	ns = current->nsproxy->ipc_ns;
 
 	msq = msg_lock_check(ns, msqid);
-	if (IS_ERR(msq))
+	if (IS_ERR(msq)) {
+		free_copy(copy);
 		return PTR_ERR(msq);
+	}
 
 	for (;;) {
 		struct msg_receiver msr_d;
 		struct list_head *tmp;
+		long msg_counter = 0;
 
 		msg = ERR_PTR(-EACCES);
 		if (ipcperms(ns, &msq->q_perm, S_IRUGO))
@@ -793,12 +858,21 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
 				msg = walk_msg;
 				if (mode == SEARCH_LESSEQUAL &&
 						walk_msg->m_type != 1) {
-					msg = walk_msg;
 					msgtyp = walk_msg->m_type - 1;
-				} else {
-					msg = walk_msg;
+				} else if (msgflg & MSG_COPY) {
+					if (copy_number == msg_counter) {
+						/*
+						 * Found requested message.
+						 * Copy it.
+						 */
+						msg = copy_msg(msg, copy);
+						if (IS_ERR(msg))
+							goto out_unlock;
+						break;
+					}
+				} else
 					break;
-				}
+				msg_counter++;
 			}
 			tmp = tmp->next;
 		}
@@ -807,10 +881,16 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
 			 * Found a suitable message.
 			 * Unlink it from the queue.
 			 */
-			if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) {
+			if ((bufsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) {
 				msg = ERR_PTR(-E2BIG);
 				goto out_unlock;
 			}
+			/*
+			 * If we are copying, then do not unlink message and do
+			 * not update queue parameters.
+			 */
+			if (msgflg & MSG_COPY)
+				goto out_unlock;
 			list_del(&msg->m_list);
 			msq->q_qnum--;
 			msq->q_rtime = get_seconds();
@@ -834,7 +914,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
 		if (msgflg & MSG_NOERROR)
 			msr_d.r_maxsize = INT_MAX;
 		else
-			msr_d.r_maxsize = msgsz;
+			msr_d.r_maxsize = bufsz;
 		msr_d.r_msg = ERR_PTR(-EAGAIN);
 		current->state = TASK_INTERRUPTIBLE;
 		msg_unlock(msq);
@@ -894,32 +974,21 @@ out_unlock:
 			break;
 		}
 	}
-	if (IS_ERR(msg))
+	if (IS_ERR(msg)) {
+		free_copy(copy);
 		return PTR_ERR(msg);
+	}
 
-	msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
-	*pmtype = msg->m_type;
-	if (store_msg(mtext, msg, msgsz))
-		msgsz = -EFAULT;
-
+	bufsz = msg_handler(buf, msg, bufsz);
 	free_msg(msg);
 
-	return msgsz;
+	return bufsz;
 }
 
 SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
 		long, msgtyp, int, msgflg)
 {
-	long err, mtype;
-
-	err =  do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg);
-	if (err < 0)
-		goto out;
-
-	if (put_user(mtype, &msgp->mtype))
-		err = -EFAULT;
-out:
-	return err;
+	return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill);
 }
 
 #ifdef CONFIG_PROC_FS
diff --git a/ipc/msgutil.c b/ipc/msgutil.c
index 26143d3..ebfcbfa 100644
--- a/ipc/msgutil.c
+++ b/ipc/msgutil.c
@@ -16,6 +16,7 @@
 #include <linux/msg.h>
 #include <linux/ipc_namespace.h>
 #include <linux/utsname.h>
+#include <linux/proc_fs.h>
 #include <asm/uaccess.h>
 
 #include "util.h"
@@ -30,6 +31,7 @@ DEFINE_SPINLOCK(mq_lock);
 struct ipc_namespace init_ipc_ns = {
 	.count		= ATOMIC_INIT(1),
 	.user_ns = &init_user_ns,
+	.proc_inum = PROC_IPC_INIT_INO,
 };
 
 atomic_t nr_ipc_ns = ATOMIC_INIT(1);
@@ -100,7 +102,50 @@ out_err:
 	free_msg(msg);
 	return ERR_PTR(err);
 }
+#ifdef CONFIG_CHECKPOINT_RESTORE
+struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
+{
+	struct msg_msgseg *dst_pseg, *src_pseg;
+	int len = src->m_ts;
+	int alen;
+
+	BUG_ON(dst == NULL);
+	if (src->m_ts > dst->m_ts)
+		return ERR_PTR(-EINVAL);
 
+	alen = len;
+	if (alen > DATALEN_MSG)
+		alen = DATALEN_MSG;
+
+	dst->next = NULL;
+	dst->security = NULL;
+
+	memcpy(dst + 1, src + 1, alen);
+
+	len -= alen;
+	dst_pseg = dst->next;
+	src_pseg = src->next;
+	while (len > 0) {
+		alen = len;
+		if (alen > DATALEN_SEG)
+			alen = DATALEN_SEG;
+		memcpy(dst_pseg + 1, src_pseg + 1, alen);
+		dst_pseg = dst_pseg->next;
+		len -= alen;
+		src_pseg = src_pseg->next;
+	}
+
+	dst->m_type = src->m_type;
+	dst->m_ts = src->m_ts;
+
+	return dst;
+}
+#else
+struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
+{
+	return ERR_PTR(-ENOSYS);
+}
+#endif
 int store_msg(void __user *dest, struct msg_msg *msg, int len)
 {
 	int alen;
diff --git a/ipc/namespace.c b/ipc/namespace.c
index f362298c..cf3386a 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -16,7 +16,7 @@
 
 #include "util.h"
 
-static struct ipc_namespace *create_ipc_ns(struct task_struct *tsk,
+static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
 					   struct ipc_namespace *old_ns)
 {
 	struct ipc_namespace *ns;
@@ -26,9 +26,16 @@ static struct ipc_namespace *create_ipc_ns(struct task_struct *tsk,
 	if (ns == NULL)
 		return ERR_PTR(-ENOMEM);
 
+	err = proc_alloc_inum(&ns->proc_inum);
+	if (err) {
+		kfree(ns);
+		return ERR_PTR(err);
+	}
+
 	atomic_set(&ns->count, 1);
 	err = mq_init_ns(ns);
 	if (err) {
+		proc_free_inum(ns->proc_inum);
 		kfree(ns);
 		return ERR_PTR(err);
 	}
@@ -46,19 +53,17 @@ static struct ipc_namespace *create_ipc_ns(struct task_struct *tsk,
 	ipcns_notify(IPCNS_CREATED);
 	register_ipcns_notifier(ns);
 
-	ns->user_ns = get_user_ns(task_cred_xxx(tsk, user_ns));
+	ns->user_ns = get_user_ns(user_ns);
 
 	return ns;
 }
 
 struct ipc_namespace *copy_ipcs(unsigned long flags,
-				struct task_struct *tsk)
+	struct user_namespace *user_ns, struct ipc_namespace *ns)
 {
-	struct ipc_namespace *ns = tsk->nsproxy->ipc_ns;
-
 	if (!(flags & CLONE_NEWIPC))
 		return get_ipc_ns(ns);
-	return create_ipc_ns(tsk, ns);
+	return create_ipc_ns(user_ns, ns);
 }
 
 /*
@@ -113,6 +118,7 @@ static void free_ipc_ns(struct ipc_namespace *ns)
 	 */
 	ipcns_notify(IPCNS_REMOVED);
 	put_user_ns(ns->user_ns);
+	proc_free_inum(ns->proc_inum);
 	kfree(ns);
 }
 
@@ -161,8 +167,12 @@ static void ipcns_put(void *ns)
 	return put_ipc_ns(ns);
 }
 
-static int ipcns_install(struct nsproxy *nsproxy, void *ns)
+static int ipcns_install(struct nsproxy *nsproxy, void *new)
 {
+	struct ipc_namespace *ns = new;
+	if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN))
+		return -EPERM;
+
 	/* Ditch state from the old ipc namespace */
 	exit_sem(current);
 	put_ipc_ns(nsproxy->ipc_ns);
@@ -170,10 +180,18 @@ static int ipcns_install(struct nsproxy *nsproxy, void *ns)
 	return 0;
 }
 
+static unsigned int ipcns_inum(void *vp)
+{
+	struct ipc_namespace *ns = vp;
+
+	return ns->proc_inum;
+}
+
 const struct proc_ns_operations ipcns_operations = {
 	.name		= "ipc",
 	.type		= CLONE_NEWIPC,
 	.get		= ipcns_get,
 	.put		= ipcns_put,
 	.install	= ipcns_install,
+	.inum		= ipcns_inum,
 };
diff --git a/ipc/sem.c b/ipc/sem.c
index 58d31f1..ebd8fec 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -61,8 +61,8 @@
  * - A woken up task may not even touch the semaphore array anymore, it may
  *   have been destroyed already by a semctl(RMID).
  * - The synchronizations between wake-ups due to a timeout/signal and a
- *   wake-up due to a completed semaphore operation is achieved by using an
- *   intermediate state (IN_WAKEUP).
+ *   wake-up due to a completed semaphore operation is achieved by using a
+ *   special wakeup scheme (queuewakeup_wait and support functions)
  * - UNDO values are stored in an array (one per process and per
  *   semaphore array, lazily allocated). For backwards compatibility, multiple
  *   modes for the UNDO variables are supported (per process, per thread)
@@ -90,6 +90,135 @@
 #include <asm/uaccess.h>
 #include "util.h"
 
+
+#ifdef CONFIG_PREEMPT_RT_BASE
+	#define SYSVSEM_COMPLETION 1
+#else
+	#define SYSVSEM_CUSTOM 1
+#endif
+
+#ifdef SYSVSEM_COMPLETION
+	/* Using a completion causes some overhead, but avoids a busy loop
+	 * that increases the worst case latency.
+	 */
+	struct queue_done {
+		struct completion done;
+	};
+
+	static void queuewakeup_prepare(void)
+	{
+		/* no preparation necessary */
+	}
+
+	static void queuewakeup_completed(void)
+	{
+		/* empty */
+	}
+
+	static void queuewakeup_block(struct queue_done *qd)
+	{
+		/* empty */
+	}
+
+	static void queuewakeup_handsoff(struct queue_done *qd)
+	{
+		complete_all(&qd->done);
+	}
+
+	static void queuewakeup_init(struct queue_done *qd)
+	{
+		init_completion(&qd->done);
+	}
+
+	static void queuewakeup_wait(struct queue_done *qd)
+	{
+		wait_for_completion(&qd->done);
+	}
+
+#elif defined(SYSVSEM_SPINLOCK)
+	/* Note: Spinlocks do not work because:
+	 * - lockdep complains [could be fixed]
+	 * - only 255 concurrent spin_lock() calls are permitted, then the
+	 *   preempt-counter overflows
+	 */
+#error SYSVSEM_SPINLOCK is a prove of concept, does not work.
+	struct queue_done {
+		spinlock_t done;
+	};
+
+	static void queuewakeup_prepare(void)
+	{
+		/* empty */
+	}
+
+	static void queuewakeup_completed(void)
+	{
+		/* empty */
+	}
+
+	static void queuewakeup_block(struct queue_done *qd)
+	{
+		BUG_ON(spin_is_locked(&qd->done));
+		spin_lock(&qd->done);
+	}
+
+	static void queuewakeup_handsoff(struct queue_done *qd)
+	{
+		spin_unlock(&qd->done);
+	}
+
+	static void queuewakeup_init(struct queue_done *qd)
+	{
+		spin_lock_init(&qd->done);
+	}
+
+	static void queuewakeup_wait(struct queue_done *qd)
+	{
+		spin_unlock_wait(&qd->done);
+	}
+#else
+	struct queue_done {
+		atomic_t done;
+	};
+
+	static void queuewakeup_prepare(void)
+	{
+		preempt_disable();
+	}
+
+	static void queuewakeup_completed(void)
+	{
+		preempt_enable();
+	}
+
+	static void queuewakeup_block(struct queue_done *qd)
+	{
+		BUG_ON(atomic_read(&qd->done) != 1);
+		atomic_set(&qd->done, 2);
+	}
+
+	static void queuewakeup_handsoff(struct queue_done *qd)
+	{
+		BUG_ON(atomic_read(&qd->done) != 2);
+		smp_mb();
+		atomic_set(&qd->done, 1);
+	}
+
+	static void queuewakeup_init(struct queue_done *qd)
+	{
+		atomic_set(&qd->done, 1);
+	}
+
+	static void queuewakeup_wait(struct queue_done *qd)
+	{
+		while (atomic_read(&qd->done) != 1)
+			cpu_relax();
+
+		smp_mb();
+	}
+#endif
+
+
 /* One semaphore structure for each semaphore in the system. */
 struct sem {
 	int	semval;		/* current value */
@@ -108,6 +237,7 @@ struct sem_queue {
 	struct sembuf		*sops;	 /* array of pending operations */
 	int			nsops;	 /* number of operations */
 	int			alter;	 /* does *sops alter the array? */
+	struct queue_done	done;	 /* completion synchronization */
 };
 
 /* Each task has a list of undo requests. They are executed automatically
@@ -245,23 +375,27 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
  * - queue.status is initialized to -EINTR before blocking.
  * - wakeup is performed by
  *	* unlinking the queue entry from sma->sem_pending
- *	* setting queue.status to IN_WAKEUP
- *	  This is the notification for the blocked thread that a
- *	  result value is imminent.
+ *	* setting queue.status to the actual result code
+ *	  This is the notification for the blocked thread that someone
+ *	  (usually: update_queue()) completed the semtimedop() operation.
  *	* call wake_up_process
- *	* set queue.status to the final value.
+ *	* queuewakeup_handsoff(&q->done);
  * - the previously blocked thread checks queue.status:
- *   	* if it's IN_WAKEUP, then it must wait until the value changes
- *   	* if it's not -EINTR, then the operation was completed by
- *   	  update_queue. semtimedop can return queue.status without
- *   	  performing any operation on the sem array.
- *   	* otherwise it must acquire the spinlock and check what's up.
+ *	* if it's not -EINTR, then someone completed the operation.
+ *	  First, queuewakeup_wait() must be called. Afterwards,
+ *	  semtimedop must return queue.status without performing any
+ *	  operation on the sem array.
+ *	  - otherwise it must acquire the spinlock and repeat the test
+ *	  - If it is still -EINTR, then no update_queue() completed the
+ *	    operation, thus semtimedop() can proceed normally.
  *
- * The two-stage algorithm is necessary to protect against the following
+ * queuewakeup_wait() is necessary to protect against the following
  * races:
  * - if queue.status is set after wake_up_process, then the woken up idle
  *   thread could race forward and try (and fail) to acquire sma->lock
- *   before update_queue had a chance to set queue.status
+ *   before update_queue had a chance to set queue.status.
+ *   More importantly, it would mean that wake_up_process must be done
+ *   while holding sma->lock, i.e. this would reduce the scalability.
  * - if queue.status is written before wake_up_process and if the
  *   blocked process is woken up by a signal between writing
  *   queue.status and the wake_up_process, then the woken up
@@ -271,7 +405,6 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
  *   (yes, this happened on s390 with sysv msg).
  *
  */
-#define IN_WAKEUP	1
 
 /**
  * newary - Create a new semaphore set
@@ -461,15 +594,11 @@ undo:
 static void wake_up_sem_queue_prepare(struct list_head *pt,
 				struct sem_queue *q, int error)
 {
-	if (list_empty(pt)) {
-		/*
-		 * Hold preempt off so that we don't get preempted and have the
-		 * wakee busy-wait until we're scheduled back on.
-		 */
-		preempt_disable();
-	}
-	q->status = IN_WAKEUP;
-	q->pid = error;
+	if (list_empty(pt))
+		queuewakeup_prepare();
+
+	queuewakeup_block(&q->done);
+	q->status = error;
 
 	list_add_tail(&q->simple_list, pt);
 }
@@ -480,8 +609,8 @@ static void wake_up_sem_queue_prepare(struct list_head *pt,
  *
  * Do the actual wake-up.
  * The function is called without any locks held, thus the semaphore array
- * could be destroyed already and the tasks can disappear as soon as the
- * status is set to the actual return code.
+ * could be destroyed already and the tasks can disappear as soon as
+ * queuewakeup_handsoff() is called.
  */
 static void wake_up_sem_queue_do(struct list_head *pt)
 {
@@ -491,12 +620,11 @@ static void wake_up_sem_queue_do(struct list_head *pt)
 	did_something = !list_empty(pt);
 	list_for_each_entry_safe(q, t, pt, simple_list) {
 		wake_up_process(q->sleeper);
-		/* q can disappear immediately after writing q->status. */
-		smp_wmb();
-		q->status = q->pid;
+		/* q can disappear immediately after completing q->done */
+		queuewakeup_handsoff(&q->done);
 	}
 	if (did_something)
-		preempt_enable();
+		queuewakeup_completed();
 }
 
 static void unlink_queue(struct sem_array *sma, struct sem_queue *q)
@@ -1302,33 +1430,6 @@ out:
 	return un;
 }
 
-
-/**
- * get_queue_result - Retrieve the result code from sem_queue
- * @q: Pointer to queue structure
- *
- * Retrieve the return code from the pending queue. If IN_WAKEUP is found in
- * q->status, then we must loop until the value is replaced with the final
- * value: This may happen if a task is woken up by an unrelated event (e.g.
- * signal) and in parallel the task is woken up by another task because it got
- * the requested semaphores.
- *
- * The function can be called with or without holding the semaphore spinlock.
- */
-static int get_queue_result(struct sem_queue *q)
-{
-	int error;
-
-	error = q->status;
-	while (unlikely(error == IN_WAKEUP)) {
-		cpu_relax();
-		error = q->status;
-	}
-
-	return error;
-}
-
-
 SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 		unsigned, nsops, const struct timespec __user *, timeout)
 {
@@ -1474,6 +1575,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 
 	queue.status = -EINTR;
 	queue.sleeper = current;
+	queuewakeup_init(&queue.done);
 
 sleep_again:
 	current->state = TASK_INTERRUPTIBLE;
@@ -1484,17 +1586,14 @@ sleep_again:
 	else
 		schedule();
 
-	error = get_queue_result(&queue);
+	error = queue.status;
 
 	if (error != -EINTR) {
 		/* fast path: update_queue already obtained all requested
-		 * resources.
-		 * Perform a smp_mb(): User space could assume that semop()
-		 * is a memory barrier: Without the mb(), the cpu could
-		 * speculatively read in user space stale data that was
-		 * overwritten by the previous owner of the semaphore.
+		 * resources. Just ensure that update_queue completed
+		 * it's access to &queue.
 		 */
-		smp_mb();
+		queuewakeup_wait(&queue.done);
 
 		goto out_free;
 	}
@@ -1504,23 +1603,16 @@ sleep_again:
 	/*
 	 * Wait until it's guaranteed that no wakeup_sem_queue_do() is ongoing.
 	 */
-	error = get_queue_result(&queue);
-
-	/*
-	 * Array removed? If yes, leave without sem_unlock().
-	 */
-	if (IS_ERR(sma)) {
-		goto out_free;
-	}
-
-
-	/*
-	 * If queue.status != -EINTR we are woken up by another process.
-	 * Leave without unlink_queue(), but with sem_unlock().
-	 */
-
+	error = queue.status;
 	if (error != -EINTR) {
-		goto out_unlock_free;
+		/* If there is a return code, then we can leave immediately. */
+		if (!IS_ERR(sma)) {
+			/* sem_lock() succeeded - then unlock */
+			sem_unlock(sma);
+		}
+		/* Except that we must wait for the hands-off */
+		queuewakeup_wait(&queue.done);
+		goto out_free;
 	}
 
 	/*
diff --git a/ipc/shm.c b/ipc/shm.c
index dff40c9..4fa6d8f 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -495,7 +495,8 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
 		if (shmflg & SHM_NORESERVE)
 			acctflag = VM_NORESERVE;
 		file = hugetlb_file_setup(name, 0, size, acctflag,
-					&shp->mlock_user, HUGETLB_SHMFS_INODE);
+				  &shp->mlock_user, HUGETLB_SHMFS_INODE,
+				(shmflg >> SHM_HUGE_SHIFT) & SHM_HUGE_MASK);
 	} else {
 		/*
 		 * Do not allow no accounting for OVERCOMMIT_NEVER, even
diff --git a/ipc/util.c b/ipc/util.c
index 72fd078..74e1d9c 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -122,6 +122,7 @@ void ipc_init_ids(struct ipc_ids *ids)
 
 	ids->in_use = 0;
 	ids->seq = 0;
+	ids->next_id = -1;
 	{
 		int seq_limit = INT_MAX/SEQ_MULTIPLIER;
 		if (seq_limit > USHRT_MAX)
@@ -252,6 +253,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
 	kuid_t euid;
 	kgid_t egid;
 	int id, err;
+	int next_id = ids->next_id;
 
 	if (size > IPCMNI)
 		size = IPCMNI;
@@ -264,7 +266,8 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
 	rcu_read_lock();
 	spin_lock(&new->lock);
 
-	err = idr_get_new(&ids->ipcs_idr, new, &id);
+	err = idr_get_new_above(&ids->ipcs_idr, new,
+				(next_id < 0) ? 0 : ipcid_to_idx(next_id), &id);
 	if (err) {
 		spin_unlock(&new->lock);
 		rcu_read_unlock();
@@ -277,9 +280,14 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
 	new->cuid = new->uid = euid;
 	new->gid = new->cgid = egid;
 
-	new->seq = ids->seq++;
-	if(ids->seq > ids->seq_max)
-		ids->seq = 0;
+	if (next_id < 0) {
+		new->seq = ids->seq++;
+		if (ids->seq > ids->seq_max)
+			ids->seq = 0;
+	} else {
+		new->seq = ipcid_to_seqx(next_id);
+		ids->next_id = -1;
+	}
 
 	new->id = ipc_buildid(id, new->seq);
 	return id;
diff --git a/ipc/util.h b/ipc/util.h
index c8fe2f7..eeb79a1 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -92,6 +92,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
 #define IPC_SHM_IDS	2
 
 #define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER)
+#define ipcid_to_seqx(id) ((id) / SEQ_MULTIPLIER)
 
 /* must be called with ids->rw_mutex acquired for writing */
 int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);
@@ -139,6 +140,7 @@ int ipc_parse_version (int *cmd);
 
 extern void free_msg(struct msg_msg *msg);
 extern struct msg_msg *load_msg(const void __user *src, int len);
+extern struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst);
 extern int store_msg(void __user *dest, struct msg_msg *msg, int len);
 
 extern void recompute_msgmni(struct ipc_namespace *);
diff --git a/kernel/Makefile b/kernel/Makefile
index 86e3285..ac0d533 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -110,6 +110,7 @@ obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o
 obj-$(CONFIG_PADATA) += padata.o
 obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
 obj-$(CONFIG_JUMP_LABEL) += jump_label.o
+obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
 
 $(obj)/configs.o: $(obj)/config_data.h
 
diff --git a/kernel/audit.c b/kernel/audit.c
index 40414e9..a219998 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -272,6 +272,8 @@ static int audit_log_config_change(char *function_name, int new, int old,
 	int rc = 0;
 
 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+	if (unlikely(!ab))
+		return rc;
 	audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new,
 			 old, from_kuid(&init_user_ns, loginuid), sessionid);
 	if (sid) {
@@ -619,6 +621,8 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
 	}
 
 	*ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
+	if (unlikely(!*ab))
+		return rc;
 	audit_log_format(*ab, "pid=%d uid=%u auid=%u ses=%u",
 			 task_tgid_vnr(current),
 			 from_kuid(&init_user_ns, current_uid()),
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index ed206fd..642a89c 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -249,7 +249,7 @@ static void untag_chunk(struct node *p)
 		list_del_rcu(&chunk->hash);
 		spin_unlock(&hash_lock);
 		spin_unlock(&entry->lock);
-		fsnotify_destroy_mark(entry);
+		fsnotify_destroy_mark(entry, audit_tree_group);
 		goto out;
 	}
 
@@ -291,7 +291,7 @@ static void untag_chunk(struct node *p)
 		owner->root = new;
 	spin_unlock(&hash_lock);
 	spin_unlock(&entry->lock);
-	fsnotify_destroy_mark(entry);
+	fsnotify_destroy_mark(entry, audit_tree_group);
 	fsnotify_put_mark(&new->mark);	/* drop initial reference */
 	goto out;
 
@@ -331,7 +331,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree)
 		spin_unlock(&hash_lock);
 		chunk->dead = 1;
 		spin_unlock(&entry->lock);
-		fsnotify_destroy_mark(entry);
+		fsnotify_destroy_mark(entry, audit_tree_group);
 		fsnotify_put_mark(entry);
 		return 0;
 	}
@@ -412,7 +412,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
 		spin_unlock(&chunk_entry->lock);
 		spin_unlock(&old_entry->lock);
 
-		fsnotify_destroy_mark(chunk_entry);
+		fsnotify_destroy_mark(chunk_entry, audit_tree_group);
 
 		fsnotify_put_mark(chunk_entry);
 		fsnotify_put_mark(old_entry);
@@ -443,17 +443,32 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
 	spin_unlock(&hash_lock);
 	spin_unlock(&chunk_entry->lock);
 	spin_unlock(&old_entry->lock);
-	fsnotify_destroy_mark(old_entry);
+	fsnotify_destroy_mark(old_entry, audit_tree_group);
 	fsnotify_put_mark(chunk_entry);	/* drop initial reference */
 	fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */
 	return 0;
 }
 
+static void audit_log_remove_rule(struct audit_krule *rule)
+{
+	struct audit_buffer *ab;
+
+	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+	if (unlikely(!ab))
+		return;
+	audit_log_format(ab, "op=");
+	audit_log_string(ab, "remove rule");
+	audit_log_format(ab, " dir=");
+	audit_log_untrustedstring(ab, rule->tree->pathname);
+	audit_log_key(ab, rule->filterkey);
+	audit_log_format(ab, " list=%d res=1", rule->listnr);
+	audit_log_end(ab);
+}
+
 static void kill_rules(struct audit_tree *tree)
 {
 	struct audit_krule *rule, *next;
 	struct audit_entry *entry;
-	struct audit_buffer *ab;
 
 	list_for_each_entry_safe(rule, next, &tree->rules, rlist) {
 		entry = container_of(rule, struct audit_entry, rule);
@@ -461,14 +476,7 @@ static void kill_rules(struct audit_tree *tree)
 		list_del_init(&rule->rlist);
 		if (rule->tree) {
 			/* not a half-baked one */
-			ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
-			audit_log_format(ab, "op=");
-			audit_log_string(ab, "remove rule");
-			audit_log_format(ab, " dir=");
-			audit_log_untrustedstring(ab, rule->tree->pathname);
-			audit_log_key(ab, rule->filterkey);
-			audit_log_format(ab, " list=%d res=1", rule->listnr);
-			audit_log_end(ab);
+			audit_log_remove_rule(rule);
 			rule->tree = NULL;
 			list_del_rcu(&entry->list);
 			list_del(&entry->rule.list);
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 9a9ae6e..22831c4 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -240,6 +240,8 @@ static void audit_watch_log_rule_change(struct audit_krule *r, struct audit_watc
 	if (audit_enabled) {
 		struct audit_buffer *ab;
 		ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE);
+		if (unlikely(!ab))
+			return;
 		audit_log_format(ab, "auid=%u ses=%u op=",
 				 from_kuid(&init_user_ns, audit_get_loginuid(current)),
 				 audit_get_sessionid(current));
@@ -350,7 +352,7 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
 	}
 	mutex_unlock(&audit_filter_mutex);
 
-	fsnotify_destroy_mark(&parent->mark);
+	fsnotify_destroy_mark(&parent->mark, audit_watch_group);
 }
 
 /* Get path information necessary for adding watches. */
@@ -457,7 +459,7 @@ void audit_remove_watch_rule(struct audit_krule *krule)
 
 		if (list_empty(&parent->watches)) {
 			audit_get_parent(parent);
-			fsnotify_destroy_mark(&parent->mark);
+			fsnotify_destroy_mark(&parent->mark, audit_watch_group);
 			audit_put_parent(parent);
 		}
 	}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 2f186ed..a371f85 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -200,7 +200,6 @@ struct audit_context {
 	struct list_head    names_list;	/* anchor for struct audit_names->list */
 	char *		    filterkey;	/* key for rule that triggered record */
 	struct path	    pwd;
-	struct audit_context *previous; /* For nested syscalls */
 	struct audit_aux_data *aux;
 	struct audit_aux_data *aux_pids;
 	struct sockaddr_storage *sockaddr;
@@ -1091,29 +1090,13 @@ int audit_alloc(struct task_struct *tsk)
 
 static inline void audit_free_context(struct audit_context *context)
 {
-	struct audit_context *previous;
-	int		     count = 0;
-
-	do {
-		previous = context->previous;
-		if (previous || (count &&  count < 10)) {
-			++count;
-			printk(KERN_ERR "audit(:%d): major=%d name_count=%d:"
-			       " freeing multiple contexts (%d)\n",
-			       context->serial, context->major,
-			       context->name_count, count);
-		}
-		audit_free_names(context);
-		unroll_tree_refs(context, NULL, 0);
-		free_tree_refs(context);
-		audit_free_aux(context);
-		kfree(context->filterkey);
-		kfree(context->sockaddr);
-		kfree(context);
-		context  = previous;
-	} while (context);
-	if (count >= 10)
-		printk(KERN_ERR "audit: freed %d contexts\n", count);
+	audit_free_names(context);
+	unroll_tree_refs(context, NULL, 0);
+	free_tree_refs(context);
+	audit_free_aux(context);
+	kfree(context->filterkey);
+	kfree(context->sockaddr);
+	kfree(context);
 }
 
 void audit_log_task_context(struct audit_buffer *ab)
@@ -1159,7 +1142,7 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
 	cred = current_cred();
 
 	spin_lock_irq(&tsk->sighand->siglock);
-	if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
+	if (tsk->signal && tsk->signal->tty)
 		tty = tsk->signal->tty->name;
 	else
 		tty = "(none)";
@@ -1481,14 +1464,14 @@ static void show_special(struct audit_context *context, int *call_panic)
 			audit_log_end(ab);
 			ab = audit_log_start(context, GFP_KERNEL,
 					     AUDIT_IPC_SET_PERM);
+			if (unlikely(!ab))
+				return;
 			audit_log_format(ab,
 				"qbytes=%lx ouid=%u ogid=%u mode=%#ho",
 				context->ipc.qbytes,
 				context->ipc.perm_uid,
 				context->ipc.perm_gid,
 				context->ipc.perm_mode);
-			if (!ab)
-				return;
 		}
 		break; }
 	case AUDIT_MQ_OPEN: {
@@ -1783,42 +1766,6 @@ void __audit_syscall_entry(int arch, int major,
 	if (!context)
 		return;
 
-	/*
-	 * This happens only on certain architectures that make system
-	 * calls in kernel_thread via the entry.S interface, instead of
-	 * with direct calls.  (If you are porting to a new
-	 * architecture, hitting this condition can indicate that you
-	 * got the _exit/_leave calls backward in entry.S.)
-	 *
-	 * i386     no
-	 * x86_64   no
-	 * ppc64    yes (see arch/powerpc/platforms/iseries/misc.S)
-	 *
-	 * This also happens with vm86 emulation in a non-nested manner
-	 * (entries without exits), so this case must be caught.
-	 */
-	if (context->in_syscall) {
-		struct audit_context *newctx;
-
-#if AUDIT_DEBUG
-		printk(KERN_ERR
-		       "audit(:%d) pid=%d in syscall=%d;"
-		       " entering syscall=%d\n",
-		       context->serial, tsk->pid, context->major, major);
-#endif
-		newctx = audit_alloc_context(context->state);
-		if (newctx) {
-			newctx->previous   = context;
-			context		   = newctx;
-			tsk->audit_context = newctx;
-		} else	{
-			/* If we can't alloc a new context, the best we
-			 * can do is to leak memory (any pending putname
-			 * will be lost).  The only other alternative is
-			 * to abandon auditing. */
-			audit_zero_context(context, context->state);
-		}
-	}
 	BUG_ON(context->in_syscall || context->name_count);
 
 	if (!audit_enabled)
@@ -1881,28 +1828,21 @@ void __audit_syscall_exit(int success, long return_code)
 	if (!list_empty(&context->killed_trees))
 		audit_kill_trees(&context->killed_trees);
 
-	if (context->previous) {
-		struct audit_context *new_context = context->previous;
-		context->previous  = NULL;
-		audit_free_context(context);
-		tsk->audit_context = new_context;
-	} else {
-		audit_free_names(context);
-		unroll_tree_refs(context, NULL, 0);
-		audit_free_aux(context);
-		context->aux = NULL;
-		context->aux_pids = NULL;
-		context->target_pid = 0;
-		context->target_sid = 0;
-		context->sockaddr_len = 0;
-		context->type = 0;
-		context->fds[0] = -1;
-		if (context->state != AUDIT_RECORD_CONTEXT) {
-			kfree(context->filterkey);
-			context->filterkey = NULL;
-		}
-		tsk->audit_context = context;
+	audit_free_names(context);
+	unroll_tree_refs(context, NULL, 0);
+	audit_free_aux(context);
+	context->aux = NULL;
+	context->aux_pids = NULL;
+	context->target_pid = 0;
+	context->target_sid = 0;
+	context->sockaddr_len = 0;
+	context->type = 0;
+	context->fds[0] = -1;
+	if (context->state != AUDIT_RECORD_CONTEXT) {
+		kfree(context->filterkey);
+		context->filterkey = NULL;
 	}
+	tsk->audit_context = context;
 }
 
 static inline void handle_one(const struct inode *inode)
@@ -2735,7 +2675,7 @@ void __audit_mmap_fd(int fd, int flags)
 	context->type = AUDIT_MMAP;
 }
 
-static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr)
+static void audit_log_task(struct audit_buffer *ab)
 {
 	kuid_t auid, uid;
 	kgid_t gid;
@@ -2753,6 +2693,11 @@ static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr)
 	audit_log_task_context(ab);
 	audit_log_format(ab, " pid=%d comm=", current->pid);
 	audit_log_untrustedstring(ab, current->comm);
+}
+
+static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr)
+{
+	audit_log_task(ab);
 	audit_log_format(ab, " reason=");
 	audit_log_string(ab, reason);
 	audit_log_format(ab, " sig=%ld", signr);
@@ -2775,6 +2720,8 @@ void audit_core_dumps(long signr)
 		return;
 
 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
+	if (unlikely(!ab))
+		return;
 	audit_log_abend(ab, "memory violation", signr);
 	audit_log_end(ab);
 }
@@ -2783,8 +2730,11 @@ void __audit_seccomp(unsigned long syscall, long signr, int code)
 {
 	struct audit_buffer *ab;
 
-	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
-	audit_log_abend(ab, "seccomp", signr);
+	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SECCOMP);
+	if (unlikely(!ab))
+		return;
+	audit_log_task(ab);
+	audit_log_format(ab, " sig=%ld", signr);
 	audit_log_format(ab, " syscall=%ld", syscall);
 	audit_log_format(ab, " compat=%d", is_compat_task());
 	audit_log_format(ab, " ip=0x%lx", KSTK_EIP(current));
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 @@ void foo(void)
 	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 f24f724..855d8b3 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -138,6 +138,9 @@ struct cgroupfs_root {
 	/* Hierarchy-specific flags */
 	unsigned long flags;
 
+	/* IDs for cgroups in this hierarchy */
+	struct ida cgroup_ida;
+
 	/* The path to use for release notifications. */
 	char release_agent_path[PATH_MAX];
 
@@ -171,8 +174,8 @@ 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_is_removed()
-	 * css_tryget() should be used for avoiding race.
+	 * is called after synchronize_rcu(). But for safe use, css_tryget()
+	 * should be used for avoiding race.
 	 */
 	struct cgroup_subsys_state __rcu *css;
 	/*
@@ -242,6 +245,8 @@ static DEFINE_SPINLOCK(hierarchy_id_lock);
  */
 static int need_forkexit_callback __read_mostly;
 
+static int cgroup_destroy_locked(struct cgroup *cgrp);
+
 #ifdef CONFIG_PROVE_LOCKING
 int cgroup_lock_is_held(void)
 {
@@ -294,11 +299,6 @@ static int notify_on_release(const struct cgroup *cgrp)
 	return test_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
 }
 
-static int clone_children(const struct cgroup *cgrp)
-{
-	return test_bit(CGRP_CLONE_CHILDREN, &cgrp->flags);
-}
-
 /*
  * for_each_subsys() allows you to iterate on each subsystem attached to
  * an active hierarchy
@@ -782,12 +782,12 @@ static struct cgroup *task_cgroup_from_root(struct task_struct *task,
  *	The task_lock() exception
  *
  * The need for this exception arises from the action of
- * cgroup_attach_task(), which overwrites one tasks cgroup pointer with
+ * cgroup_attach_task(), which overwrites one task's cgroup pointer with
  * another.  It does so using cgroup_mutex, however there are
  * several performance critical places that need to reference
  * task->cgroup without the expense of grabbing a system global
  * mutex.  Therefore except as noted below, when dereferencing or, as
- * in cgroup_attach_task(), modifying a task'ss cgroup pointer we use
+ * in cgroup_attach_task(), modifying a task's cgroup pointer we use
  * task_lock(), which acts on a spinlock (task->alloc_lock) already in
  * the task_struct routinely used for such matters.
  *
@@ -854,30 +854,6 @@ static struct inode *cgroup_new_inode(umode_t mode, struct super_block *sb)
 	return inode;
 }
 
-/*
- * Call subsys's pre_destroy handler.
- * This is called before css refcnt check.
- */
-static int cgroup_call_pre_destroy(struct cgroup *cgrp)
-{
-	struct cgroup_subsys *ss;
-	int ret = 0;
-
-	for_each_subsys(cgrp->root, ss) {
-		if (!ss->pre_destroy)
-			continue;
-
-		ret = ss->pre_destroy(cgrp);
-		if (ret) {
-			/* ->pre_destroy() failure is being deprecated */
-			WARN_ON_ONCE(!ss->__DEPRECATED_clear_css_refs);
-			break;
-		}
-	}
-
-	return ret;
-}
-
 static void cgroup_diput(struct dentry *dentry, struct inode *inode)
 {
 	/* is dentry a directory ? if so, kfree() associated cgroup */
@@ -898,7 +874,7 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
 		 * Release the subsystem state objects.
 		 */
 		for_each_subsys(cgrp->root, ss)
-			ss->destroy(cgrp);
+			ss->css_free(cgrp);
 
 		cgrp->root->number_of_cgroups--;
 		mutex_unlock(&cgroup_mutex);
@@ -917,6 +893,7 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
 
 		simple_xattrs_free(&cgrp->xattrs);
 
+		ida_simple_remove(&cgrp->root->cgroup_ida, cgrp->id);
 		kfree_rcu(cgrp, rcu_head);
 	} else {
 		struct cfent *cfe = __d_cfe(dentry);
@@ -1015,33 +992,6 @@ static void cgroup_d_remove_dir(struct dentry *dentry)
 }
 
 /*
- * A queue for waiters to do rmdir() cgroup. A tasks will sleep when
- * cgroup->count == 0 && list_empty(&cgroup->children) && subsys has some
- * reference to css->refcnt. In general, this refcnt is expected to goes down
- * to zero, soon.
- *
- * CGRP_WAIT_ON_RMDIR flag is set under cgroup's inode->i_mutex;
- */
-static DECLARE_WAIT_QUEUE_HEAD(cgroup_rmdir_waitq);
-
-static void cgroup_wakeup_rmdir_waiter(struct cgroup *cgrp)
-{
-	if (unlikely(test_and_clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags)))
-		wake_up_all(&cgroup_rmdir_waitq);
-}
-
-void cgroup_exclude_rmdir(struct cgroup_subsys_state *css)
-{
-	css_get(css);
-}
-
-void cgroup_release_and_wakeup_rmdir(struct cgroup_subsys_state *css)
-{
-	cgroup_wakeup_rmdir_waiter(css->cgroup);
-	css_put(css);
-}
-
-/*
  * Call with cgroup_mutex held. Drops reference counts on modules, including
  * any duplicate ones that parse_cgroupfs_options took. If this function
  * returns an error, no reference counts are touched.
@@ -1150,7 +1100,7 @@ static int cgroup_show_options(struct seq_file *seq, struct dentry *dentry)
 		seq_puts(seq, ",xattr");
 	if (strlen(root->release_agent_path))
 		seq_printf(seq, ",release_agent=%s", root->release_agent_path);
-	if (clone_children(&root->top_cgroup))
+	if (test_bit(CGRP_CPUSET_CLONE_CHILDREN, &root->top_cgroup.flags))
 		seq_puts(seq, ",clone_children");
 	if (strlen(root->name))
 		seq_printf(seq, ",name=%s", root->name);
@@ -1162,7 +1112,7 @@ struct cgroup_sb_opts {
 	unsigned long subsys_mask;
 	unsigned long flags;
 	char *release_agent;
-	bool clone_children;
+	bool cpuset_clone_children;
 	char *name;
 	/* User explicitly requested empty subsystem */
 	bool none;
@@ -1213,7 +1163,7 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
 			continue;
 		}
 		if (!strcmp(token, "clone_children")) {
-			opts->clone_children = true;
+			opts->cpuset_clone_children = true;
 			continue;
 		}
 		if (!strcmp(token, "xattr")) {
@@ -1381,7 +1331,6 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
 	if (ret)
 		goto out_unlock;
 
-	/* See feature-removal-schedule.txt */
 	if (opts.subsys_mask != root->actual_subsys_mask || opts.release_agent)
 		pr_warning("cgroup: option changes via remount are deprecated (pid=%d comm=%s)\n",
 			   task_tgid_nr(current), current->comm);
@@ -1432,6 +1381,7 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp)
 	INIT_LIST_HEAD(&cgrp->children);
 	INIT_LIST_HEAD(&cgrp->files);
 	INIT_LIST_HEAD(&cgrp->css_sets);
+	INIT_LIST_HEAD(&cgrp->allcg_node);
 	INIT_LIST_HEAD(&cgrp->release_list);
 	INIT_LIST_HEAD(&cgrp->pidlists);
 	mutex_init(&cgrp->pidlist_mutex);
@@ -1450,8 +1400,8 @@ static void init_cgroup_root(struct cgroupfs_root *root)
 	root->number_of_cgroups = 1;
 	cgrp->root = root;
 	cgrp->top_cgroup = cgrp;
-	list_add_tail(&cgrp->allcg_node, &root->allcg_list);
 	init_cgroup_housekeeping(cgrp);
+	list_add_tail(&cgrp->allcg_node, &root->allcg_list);
 }
 
 static bool init_root_id(struct cgroupfs_root *root)
@@ -1518,12 +1468,13 @@ static struct cgroupfs_root *cgroup_root_from_opts(struct cgroup_sb_opts *opts)
 
 	root->subsys_mask = opts->subsys_mask;
 	root->flags = opts->flags;
+	ida_init(&root->cgroup_ida);
 	if (opts->release_agent)
 		strcpy(root->release_agent_path, opts->release_agent);
 	if (opts->name)
 		strcpy(root->name, opts->name);
-	if (opts->clone_children)
-		set_bit(CGRP_CLONE_CHILDREN, &root->top_cgroup.flags);
+	if (opts->cpuset_clone_children)
+		set_bit(CGRP_CPUSET_CLONE_CHILDREN, &root->top_cgroup.flags);
 	return root;
 }
 
@@ -1536,6 +1487,7 @@ static void cgroup_drop_root(struct cgroupfs_root *root)
 	spin_lock(&hierarchy_id_lock);
 	ida_remove(&hierarchy_ida, root->hierarchy_id);
 	spin_unlock(&hierarchy_id_lock);
+	ida_destroy(&root->cgroup_ida);
 	kfree(root);
 }
 
@@ -1701,7 +1653,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
 
 		free_cg_links(&tmp_cg_links);
 
-		BUG_ON(!list_empty(&root_cgrp->sibling));
 		BUG_ON(!list_empty(&root_cgrp->children));
 		BUG_ON(root->number_of_cgroups != 1);
 
@@ -1750,7 +1701,6 @@ static void cgroup_kill_sb(struct super_block *sb) {
 
 	BUG_ON(root->number_of_cgroups != 1);
 	BUG_ON(!list_empty(&cgrp->children));
-	BUG_ON(!list_empty(&cgrp->sibling));
 
 	mutex_lock(&cgroup_mutex);
 	mutex_lock(&cgroup_root_mutex);
@@ -1808,9 +1758,11 @@ static struct kobject *cgroup_kobj;
  */
 int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
 {
+	struct dentry *dentry = cgrp->dentry;
 	char *start;
-	struct dentry *dentry = rcu_dereference_check(cgrp->dentry,
-						      cgroup_lock_is_held());
+
+	rcu_lockdep_assert(rcu_read_lock_held() || cgroup_lock_is_held(),
+			   "cgroup_path() called without proper locking");
 
 	if (!dentry || cgrp == dummytop) {
 		/*
@@ -1821,9 +1773,9 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
 		return 0;
 	}
 
-	start = buf + buflen;
+	start = buf + buflen - 1;
 
-	*--start = '\0';
+	*start = '\0';
 	for (;;) {
 		int len = dentry->d_name.len;
 
@@ -1834,8 +1786,7 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
 		if (!cgrp)
 			break;
 
-		dentry = rcu_dereference_check(cgrp->dentry,
-					       cgroup_lock_is_held());
+		dentry = cgrp->dentry;
 		if (!cgrp->parent)
 			continue;
 		if (--start < buf)
@@ -1930,9 +1881,7 @@ EXPORT_SYMBOL_GPL(cgroup_taskset_size);
 /*
  * cgroup_task_migrate - move a task from one cgroup to another.
  *
- * 'guarantee' is set if the caller promises that a new css_set for the task
- * will already exist. If not set, this function might sleep, and can fail with
- * -ENOMEM. Must be called with cgroup_mutex and threadgroup locked.
+ * Must be called with cgroup_mutex and threadgroup locked.
  */
 static void cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp,
 				struct task_struct *tsk, struct css_set *newcg)
@@ -2025,12 +1974,6 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
 	}
 
 	synchronize_rcu();
-
-	/*
-	 * wake up rmdir() waiter. the rmdir should fail since the cgroup
-	 * is no longer empty.
-	 */
-	cgroup_wakeup_rmdir_waiter(cgrp);
 out:
 	if (retval) {
 		for_each_subsys(root, ss) {
@@ -2200,7 +2143,6 @@ static int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
 	 * step 5: success! and cleanup
 	 */
 	synchronize_rcu();
-	cgroup_wakeup_rmdir_waiter(cgrp);
 	retval = 0;
 out_put_css_set_refs:
 	if (retval) {
@@ -2711,10 +2653,17 @@ static int cgroup_create_file(struct dentry *dentry, umode_t mode,
 
 		/* start off with i_nlink == 2 (for "." entry) */
 		inc_nlink(inode);
+		inc_nlink(dentry->d_parent->d_inode);
 
-		/* start with the directory inode held, so that we can
-		 * populate it without racing with another mkdir */
-		mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
+		/*
+		 * Control reaches here with cgroup_mutex held.
+		 * @inode->i_mutex should nest outside cgroup_mutex but we
+		 * want to populate it immediately without releasing
+		 * cgroup_mutex.  As @inode isn't visible to anyone else
+		 * yet, trylock will always succeed without affecting
+		 * lockdep checks.
+		 */
+		WARN_ON_ONCE(!mutex_trylock(&inode->i_mutex));
 	} else if (S_ISREG(mode)) {
 		inode->i_size = 0;
 		inode->i_fop = &cgroup_file_operations;
@@ -2725,32 +2674,6 @@ static int cgroup_create_file(struct dentry *dentry, umode_t mode,
 	return 0;
 }
 
-/*
- * cgroup_create_dir - create a directory for an object.
- * @cgrp: the cgroup we create the directory for. It must have a valid
- *        ->parent field. And we are going to fill its ->dentry field.
- * @dentry: dentry of the new cgroup
- * @mode: mode to set on new directory.
- */
-static int cgroup_create_dir(struct cgroup *cgrp, struct dentry *dentry,
-				umode_t mode)
-{
-	struct dentry *parent;
-	int error = 0;
-
-	parent = cgrp->parent->dentry;
-	error = cgroup_create_file(dentry, S_IFDIR | mode, cgrp->root->sb);
-	if (!error) {
-		dentry->d_fsdata = cgrp;
-		inc_nlink(parent->d_inode);
-		rcu_assign_pointer(cgrp->dentry, dentry);
-		dget(dentry);
-	}
-	dput(dentry);
-
-	return error;
-}
-
 /**
  * cgroup_file_mode - deduce file mode of a control file
  * @cft: the control file in question
@@ -3044,6 +2967,92 @@ static void cgroup_enable_task_cg_lists(void)
 	write_unlock(&css_set_lock);
 }
 
+/**
+ * cgroup_next_descendant_pre - find the next descendant for pre-order walk
+ * @pos: the current position (%NULL to initiate traversal)
+ * @cgroup: cgroup whose descendants to walk
+ *
+ * To be used by cgroup_for_each_descendant_pre().  Find the next
+ * descendant to visit for pre-order traversal of @cgroup's descendants.
+ */
+struct cgroup *cgroup_next_descendant_pre(struct cgroup *pos,
+					  struct cgroup *cgroup)
+{
+	struct cgroup *next;
+
+	WARN_ON_ONCE(!rcu_read_lock_held());
+
+	/* if first iteration, pretend we just visited @cgroup */
+	if (!pos) {
+		if (list_empty(&cgroup->children))
+			return NULL;
+		pos = cgroup;
+	}
+
+	/* visit the first child if exists */
+	next = list_first_or_null_rcu(&pos->children, struct cgroup, sibling);
+	if (next)
+		return next;
+
+	/* no child, visit my or the closest ancestor's next sibling */
+	do {
+		next = list_entry_rcu(pos->sibling.next, struct cgroup,
+				      sibling);
+		if (&next->sibling != &pos->parent->children)
+			return next;
+
+		pos = pos->parent;
+	} while (pos != cgroup);
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(cgroup_next_descendant_pre);
+
+static struct cgroup *cgroup_leftmost_descendant(struct cgroup *pos)
+{
+	struct cgroup *last;
+
+	do {
+		last = pos;
+		pos = list_first_or_null_rcu(&pos->children, struct cgroup,
+					     sibling);
+	} while (pos);
+
+	return last;
+}
+
+/**
+ * cgroup_next_descendant_post - find the next descendant for post-order walk
+ * @pos: the current position (%NULL to initiate traversal)
+ * @cgroup: cgroup whose descendants to walk
+ *
+ * To be used by cgroup_for_each_descendant_post().  Find the next
+ * descendant to visit for post-order traversal of @cgroup's descendants.
+ */
+struct cgroup *cgroup_next_descendant_post(struct cgroup *pos,
+					   struct cgroup *cgroup)
+{
+	struct cgroup *next;
+
+	WARN_ON_ONCE(!rcu_read_lock_held());
+
+	/* if first iteration, visit the leftmost descendant */
+	if (!pos) {
+		next = cgroup_leftmost_descendant(cgroup);
+		return next != cgroup ? next : NULL;
+	}
+
+	/* if there's an unvisited sibling, visit its leftmost descendant */
+	next = list_entry_rcu(pos->sibling.next, struct cgroup, sibling);
+	if (&next->sibling != &pos->parent->children)
+		return cgroup_leftmost_descendant(next);
+
+	/* no sibling left, visit parent */
+	next = pos->parent;
+	return next != cgroup ? next : NULL;
+}
+EXPORT_SYMBOL_GPL(cgroup_next_descendant_post);
+
 void cgroup_iter_start(struct cgroup *cgrp, struct cgroup_iter *it)
 	__acquires(css_set_lock)
 {
@@ -3390,7 +3399,7 @@ static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp,
 {
 	struct cgroup_pidlist *l;
 	/* don't need task_nsproxy() if we're looking at ourself */
-	struct pid_namespace *ns = current->nsproxy->pid_ns;
+	struct pid_namespace *ns = task_active_pid_ns(current);
 
 	/*
 	 * We can't drop the pidlist_mutex before taking the l->mutex in case
@@ -3757,7 +3766,7 @@ static int cgroup_event_wake(wait_queue_t *wait, unsigned mode,
 	if (flags & POLLHUP) {
 		__remove_wait_queue(event->wqh, &event->wait);
 		spin_lock(&cgrp->event_list_lock);
-		list_del(&event->list);
+		list_del_init(&event->list);
 		spin_unlock(&cgrp->event_list_lock);
 		/*
 		 * We are in atomic context, but cgroup_event_remove() may
@@ -3894,7 +3903,7 @@ fail:
 static u64 cgroup_clone_children_read(struct cgroup *cgrp,
 				    struct cftype *cft)
 {
-	return clone_children(cgrp);
+	return test_bit(CGRP_CPUSET_CLONE_CHILDREN, &cgrp->flags);
 }
 
 static int cgroup_clone_children_write(struct cgroup *cgrp,
@@ -3902,9 +3911,9 @@ static int cgroup_clone_children_write(struct cgroup *cgrp,
 				     u64 val)
 {
 	if (val)
-		set_bit(CGRP_CLONE_CHILDREN, &cgrp->flags);
+		set_bit(CGRP_CPUSET_CLONE_CHILDREN, &cgrp->flags);
 	else
-		clear_bit(CGRP_CLONE_CHILDREN, &cgrp->flags);
+		clear_bit(CGRP_CPUSET_CLONE_CHILDREN, &cgrp->flags);
 	return 0;
 }
 
@@ -4017,19 +4026,57 @@ static void init_cgroup_css(struct cgroup_subsys_state *css,
 	css->flags = 0;
 	css->id = NULL;
 	if (cgrp == dummytop)
-		set_bit(CSS_ROOT, &css->flags);
+		css->flags |= CSS_ROOT;
 	BUG_ON(cgrp->subsys[ss->subsys_id]);
 	cgrp->subsys[ss->subsys_id] = css;
 
 	/*
-	 * If !clear_css_refs, css holds an extra ref to @cgrp->dentry
-	 * which is put on the last css_put().  dput() requires process
-	 * context, which css_put() may be called without.  @css->dput_work
-	 * will be used to invoke dput() asynchronously from css_put().
+	 * css holds an extra ref to @cgrp->dentry which is put on the last
+	 * css_put().  dput() requires process context, which css_put() may
+	 * be called without.  @css->dput_work will be used to invoke
+	 * dput() asynchronously from css_put().
 	 */
 	INIT_WORK(&css->dput_work, css_dput_fn);
-	if (ss->__DEPRECATED_clear_css_refs)
-		set_bit(CSS_CLEAR_CSS_REFS, &css->flags);
+}
+
+/* invoke ->post_create() on a new CSS and mark it online if successful */
+static int online_css(struct cgroup_subsys *ss, struct cgroup *cgrp)
+{
+	int ret = 0;
+
+	lockdep_assert_held(&cgroup_mutex);
+
+	if (ss->css_online)
+		ret = ss->css_online(cgrp);
+	if (!ret)
+		cgrp->subsys[ss->subsys_id]->flags |= CSS_ONLINE;
+	return ret;
+}
+
+/* if the CSS is online, invoke ->pre_destory() on it and mark it offline */
+static void offline_css(struct cgroup_subsys *ss, struct cgroup *cgrp)
+	__releases(&cgroup_mutex) __acquires(&cgroup_mutex)
+{
+	struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id];
+
+	lockdep_assert_held(&cgroup_mutex);
+
+	if (!(css->flags & CSS_ONLINE))
+		return;
+
+	/*
+	 * css_offline() should be called with cgroup_mutex unlocked.  See
+	 * 3fa59dfbc3 ("cgroup: fix potential deadlock in pre_destroy") for
+	 * details.  This temporary unlocking should go away once
+	 * cgroup_mutex is unexported from controllers.
+	 */
+	if (ss->css_offline) {
+		mutex_unlock(&cgroup_mutex);
+		ss->css_offline(cgrp);
+		mutex_lock(&cgroup_mutex);
+	}
+
+	cgrp->subsys[ss->subsys_id]->flags &= ~CSS_ONLINE;
 }
 
 /*
@@ -4049,10 +4096,27 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 	struct cgroup_subsys *ss;
 	struct super_block *sb = root->sb;
 
+	/* allocate the cgroup and its ID, 0 is reserved for the root */
 	cgrp = kzalloc(sizeof(*cgrp), GFP_KERNEL);
 	if (!cgrp)
 		return -ENOMEM;
 
+	cgrp->id = ida_simple_get(&root->cgroup_ida, 1, 0, GFP_KERNEL);
+	if (cgrp->id < 0)
+		goto err_free_cgrp;
+
+	/*
+	 * Only live parents can have children.  Note that the liveliness
+	 * check isn't strictly necessary because cgroup_mkdir() and
+	 * cgroup_rmdir() are fully synchronized by i_mutex; however, do it
+	 * anyway so that locking is contained inside cgroup proper and we
+	 * don't get nasty surprises if we ever grow another caller.
+	 */
+	if (!cgroup_lock_live_group(parent)) {
+		err = -ENODEV;
+		goto err_free_id;
+	}
+
 	/* Grab a reference on the superblock so the hierarchy doesn't
 	 * get deleted on unmount if there are child cgroups.  This
 	 * can be done outside cgroup_mutex, since the sb can't
@@ -4060,8 +4124,6 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 	 * fs */
 	atomic_inc(&sb->s_active);
 
-	mutex_lock(&cgroup_mutex);
-
 	init_cgroup_housekeeping(cgrp);
 
 	cgrp->parent = parent;
@@ -4071,26 +4133,23 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 	if (notify_on_release(parent))
 		set_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
 
-	if (clone_children(parent))
-		set_bit(CGRP_CLONE_CHILDREN, &cgrp->flags);
+	if (test_bit(CGRP_CPUSET_CLONE_CHILDREN, &parent->flags))
+		set_bit(CGRP_CPUSET_CLONE_CHILDREN, &cgrp->flags);
 
 	for_each_subsys(root, ss) {
 		struct cgroup_subsys_state *css;
 
-		css = ss->create(cgrp);
+		css = ss->css_alloc(cgrp);
 		if (IS_ERR(css)) {
 			err = PTR_ERR(css);
-			goto err_destroy;
+			goto err_free_all;
 		}
 		init_cgroup_css(css, ss, cgrp);
 		if (ss->use_id) {
 			err = alloc_css_id(ss, parent, cgrp);
 			if (err)
-				goto err_destroy;
+				goto err_free_all;
 		}
-		/* At error, ->destroy() callback has to free assigned ID. */
-		if (clone_children(parent) && ss->post_clone)
-			ss->post_clone(cgrp);
 
 		if (ss->broken_hierarchy && !ss->warned_broken_hierarchy &&
 		    parent->parent) {
@@ -4102,50 +4161,62 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 		}
 	}
 
-	list_add(&cgrp->sibling, &cgrp->parent->children);
-	root->number_of_cgroups++;
-
-	err = cgroup_create_dir(cgrp, dentry, mode);
+	/*
+	 * Create directory.  cgroup_create_file() returns with the new
+	 * directory locked on success so that it can be populated without
+	 * dropping cgroup_mutex.
+	 */
+	err = cgroup_create_file(dentry, S_IFDIR | mode, sb);
 	if (err < 0)
-		goto err_remove;
+		goto err_free_all;
+	lockdep_assert_held(&dentry->d_inode->i_mutex);
 
-	/* If !clear_css_refs, each css holds a ref to the cgroup's dentry */
-	for_each_subsys(root, ss)
-		if (!ss->__DEPRECATED_clear_css_refs)
-			dget(dentry);
+	/* allocation complete, commit to creation */
+	dentry->d_fsdata = cgrp;
+	cgrp->dentry = dentry;
+	list_add_tail(&cgrp->allcg_node, &root->allcg_list);
+	list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children);
+	root->number_of_cgroups++;
 
-	/* The cgroup directory was pre-locked for us */
-	BUG_ON(!mutex_is_locked(&cgrp->dentry->d_inode->i_mutex));
+	/* each css holds a ref to the cgroup's dentry */
+	for_each_subsys(root, ss)
+		dget(dentry);
 
-	list_add_tail(&cgrp->allcg_node, &root->allcg_list);
+	/* creation succeeded, notify subsystems */
+	for_each_subsys(root, ss) {
+		err = online_css(ss, cgrp);
+		if (err)
+			goto err_destroy;
+	}
 
 	err = cgroup_populate_dir(cgrp, true, root->subsys_mask);
-	/* If err < 0, we have a half-filled directory - oh well ;) */
+	if (err)
+		goto err_destroy;
 
 	mutex_unlock(&cgroup_mutex);
 	mutex_unlock(&cgrp->dentry->d_inode->i_mutex);
 
 	return 0;
 
- err_remove:
-
-	list_del(&cgrp->sibling);
-	root->number_of_cgroups--;
-
- err_destroy:
-
+err_free_all:
 	for_each_subsys(root, ss) {
 		if (cgrp->subsys[ss->subsys_id])
-			ss->destroy(cgrp);
+			ss->css_free(cgrp);
 	}
-
 	mutex_unlock(&cgroup_mutex);
-
 	/* Release the reference count that we took on the superblock */
 	deactivate_super(sb);
-
+err_free_id:
+	ida_simple_remove(&root->cgroup_ida, cgrp->id);
+err_free_cgrp:
 	kfree(cgrp);
 	return err;
+
+err_destroy:
+	cgroup_destroy_locked(cgrp);
+	mutex_unlock(&cgroup_mutex);
+	mutex_unlock(&dentry->d_inode->i_mutex);
+	return err;
 }
 
 static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
@@ -4197,153 +4268,60 @@ static int cgroup_has_css_refs(struct cgroup *cgrp)
 	return 0;
 }
 
-/*
- * Atomically mark all (or else none) of the cgroup's CSS objects as
- * CSS_REMOVED. Return true on success, or false if the cgroup has
- * busy subsystems. Call with cgroup_mutex held
- *
- * Depending on whether a subsys has __DEPRECATED_clear_css_refs set or
- * not, cgroup removal behaves differently.
- *
- * If clear is set, css refcnt for the subsystem should be zero before
- * cgroup removal can be committed.  This is implemented by
- * CGRP_WAIT_ON_RMDIR and retry logic around ->pre_destroy(), which may be
- * called multiple times until all css refcnts reach zero and is allowed to
- * veto removal on any invocation.  This behavior is deprecated and will be
- * removed as soon as the existing user (memcg) is updated.
- *
- * If clear is not set, each css holds an extra reference to the cgroup's
- * dentry and cgroup removal proceeds regardless of css refs.
- * ->pre_destroy() will be called at least once and is not allowed to fail.
- * On the last put of each css, whenever that may be, the extra dentry ref
- * is put so that dentry destruction happens only after all css's are
- * released.
- */
-static int cgroup_clear_css_refs(struct cgroup *cgrp)
+static int cgroup_destroy_locked(struct cgroup *cgrp)
+	__releases(&cgroup_mutex) __acquires(&cgroup_mutex)
 {
+	struct dentry *d = cgrp->dentry;
+	struct cgroup *parent = cgrp->parent;
+	DEFINE_WAIT(wait);
+	struct cgroup_event *event, *tmp;
 	struct cgroup_subsys *ss;
-	unsigned long flags;
-	bool failed = false;
+	LIST_HEAD(tmp_list);
+
+	lockdep_assert_held(&d->d_inode->i_mutex);
+	lockdep_assert_held(&cgroup_mutex);
 
-	local_irq_save(flags);
+	if (atomic_read(&cgrp->count) || !list_empty(&cgrp->children))
+		return -EBUSY;
 
 	/*
-	 * Block new css_tryget() by deactivating refcnt.  If all refcnts
-	 * for subsystems w/ clear_css_refs set were 1 at the moment of
-	 * deactivation, we succeeded.
+	 * Block new css_tryget() by deactivating refcnt and mark @cgrp
+	 * removed.  This makes future css_tryget() and child creation
+	 * attempts fail thus maintaining the removal conditions verified
+	 * above.
 	 */
 	for_each_subsys(cgrp->root, ss) {
 		struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id];
 
 		WARN_ON(atomic_read(&css->refcnt) < 0);
 		atomic_add(CSS_DEACT_BIAS, &css->refcnt);
-
-		if (ss->__DEPRECATED_clear_css_refs)
-			failed |= css_refcnt(css) != 1;
 	}
+	set_bit(CGRP_REMOVED, &cgrp->flags);
 
-	/*
-	 * If succeeded, set REMOVED and put all the base refs; otherwise,
-	 * restore refcnts to positive values.  Either way, all in-progress
-	 * css_tryget() will be released.
-	 */
-	for_each_subsys(cgrp->root, ss) {
-		struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id];
-
-		if (!failed) {
-			set_bit(CSS_REMOVED, &css->flags);
-			css_put(css);
-		} else {
-			atomic_sub(CSS_DEACT_BIAS, &css->refcnt);
-		}
-	}
-
-	local_irq_restore(flags);
-	return !failed;
-}
-
-static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry)
-{
-	struct cgroup *cgrp = dentry->d_fsdata;
-	struct dentry *d;
-	struct cgroup *parent;
-	DEFINE_WAIT(wait);
-	struct cgroup_event *event, *tmp;
-	int ret;
-
-	/* the vfs holds both inode->i_mutex already */
-again:
-	mutex_lock(&cgroup_mutex);
-	if (atomic_read(&cgrp->count) != 0) {
-		mutex_unlock(&cgroup_mutex);
-		return -EBUSY;
-	}
-	if (!list_empty(&cgrp->children)) {
-		mutex_unlock(&cgroup_mutex);
-		return -EBUSY;
-	}
-	mutex_unlock(&cgroup_mutex);
-
-	/*
-	 * In general, subsystem has no css->refcnt after pre_destroy(). But
-	 * in racy cases, subsystem may have to get css->refcnt after
-	 * pre_destroy() and it makes rmdir return with -EBUSY. This sometimes
-	 * make rmdir return -EBUSY too often. To avoid that, we use waitqueue
-	 * for cgroup's rmdir. CGRP_WAIT_ON_RMDIR is for synchronizing rmdir
-	 * and subsystem's reference count handling. Please see css_get/put
-	 * and css_tryget() and cgroup_wakeup_rmdir_waiter() implementation.
-	 */
-	set_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags);
+	/* tell subsystems to initate destruction */
+	for_each_subsys(cgrp->root, ss)
+		offline_css(ss, cgrp);
 
 	/*
-	 * Call pre_destroy handlers of subsys. Notify subsystems
-	 * that rmdir() request comes.
+	 * Put all the base refs.  Each css holds an extra reference to the
+	 * cgroup's dentry and cgroup removal proceeds regardless of css
+	 * refs.  On the last put of each css, whenever that may be, the
+	 * extra dentry ref is put so that dentry destruction happens only
+	 * after all css's are released.
 	 */
-	ret = cgroup_call_pre_destroy(cgrp);
-	if (ret) {
-		clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags);
-		return ret;
-	}
-
-	mutex_lock(&cgroup_mutex);
-	parent = cgrp->parent;
-	if (atomic_read(&cgrp->count) || !list_empty(&cgrp->children)) {
-		clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags);
-		mutex_unlock(&cgroup_mutex);
-		return -EBUSY;
-	}
-	prepare_to_wait(&cgroup_rmdir_waitq, &wait, TASK_INTERRUPTIBLE);
-	if (!cgroup_clear_css_refs(cgrp)) {
-		mutex_unlock(&cgroup_mutex);
-		/*
-		 * Because someone may call cgroup_wakeup_rmdir_waiter() before
-		 * prepare_to_wait(), we need to check this flag.
-		 */
-		if (test_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags))
-			schedule();
-		finish_wait(&cgroup_rmdir_waitq, &wait);
-		clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags);
-		if (signal_pending(current))
-			return -EINTR;
-		goto again;
-	}
-	/* NO css_tryget() can success after here. */
-	finish_wait(&cgroup_rmdir_waitq, &wait);
-	clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags);
+	for_each_subsys(cgrp->root, ss)
+		css_put(cgrp->subsys[ss->subsys_id]);
 
 	raw_spin_lock(&release_list_lock);
-	set_bit(CGRP_REMOVED, &cgrp->flags);
 	if (!list_empty(&cgrp->release_list))
 		list_del_init(&cgrp->release_list);
 	raw_spin_unlock(&release_list_lock);
 
 	/* delete this cgroup from parent->children */
-	list_del_init(&cgrp->sibling);
-
+	list_del_rcu(&cgrp->sibling);
 	list_del_init(&cgrp->allcg_node);
 
-	d = dget(cgrp->dentry);
-
+	dget(d);
 	cgroup_d_remove_dir(d);
 	dput(d);
 
@@ -4353,21 +4331,35 @@ again:
 	/*
 	 * Unregister events and notify userspace.
 	 * Notify userspace about cgroup removing only after rmdir of cgroup
-	 * directory to avoid race between userspace and kernelspace
+	 * directory to avoid race between userspace and kernelspace. Use
+	 * a temporary list to avoid a deadlock with cgroup_event_wake(). Since
+	 * cgroup_event_wake() is called with the wait queue head locked,
+	 * remove_wait_queue() cannot be called while holding event_list_lock.
 	 */
 	spin_lock(&cgrp->event_list_lock);
-	list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) {
-		list_del(&event->list);
+	list_splice_init(&cgrp->event_list, &tmp_list);
+	spin_unlock(&cgrp->event_list_lock);
+	list_for_each_entry_safe(event, tmp, &tmp_list, list) {
+		list_del_init(&event->list);
 		remove_wait_queue(event->wqh, &event->wait);
 		eventfd_signal(event->eventfd, 1);
 		schedule_work(&event->remove);
 	}
-	spin_unlock(&cgrp->event_list_lock);
 
-	mutex_unlock(&cgroup_mutex);
 	return 0;
 }
 
+static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry)
+{
+	int ret;
+
+	mutex_lock(&cgroup_mutex);
+	ret = cgroup_destroy_locked(dentry->d_fsdata);
+	mutex_unlock(&cgroup_mutex);
+
+	return ret;
+}
+
 static void __init_or_module cgroup_init_cftsets(struct cgroup_subsys *ss)
 {
 	INIT_LIST_HEAD(&ss->cftsets);
@@ -4388,13 +4380,15 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
 
 	printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name);
 
+	mutex_lock(&cgroup_mutex);
+
 	/* init base cftset */
 	cgroup_init_cftsets(ss);
 
 	/* Create the top cgroup state for this subsystem */
 	list_add(&ss->sibling, &rootnode.subsys_list);
 	ss->root = &rootnode;
-	css = ss->create(dummytop);
+	css = ss->css_alloc(dummytop);
 	/* We don't handle early failures gracefully */
 	BUG_ON(IS_ERR(css));
 	init_cgroup_css(css, ss, dummytop);
@@ -4403,7 +4397,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
 	 * pointer to this state - since the subsystem is
 	 * newly registered, all tasks and hence the
 	 * init_css_set is in the subsystem's top cgroup. */
-	init_css_set.subsys[ss->subsys_id] = dummytop->subsys[ss->subsys_id];
+	init_css_set.subsys[ss->subsys_id] = css;
 
 	need_forkexit_callback |= ss->fork || ss->exit;
 
@@ -4413,6 +4407,9 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
 	BUG_ON(!list_empty(&init_task.tasks));
 
 	ss->active = 1;
+	BUG_ON(online_css(ss, dummytop));
+
+	mutex_unlock(&cgroup_mutex);
 
 	/* this function shouldn't be used with modular subsystems, since they
 	 * need to register a subsys_id, among other things */
@@ -4430,12 +4427,12 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
  */
 int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
 {
-	int i;
 	struct cgroup_subsys_state *css;
+	int i, ret;
 
 	/* check name and function validity */
 	if (ss->name == NULL || strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN ||
-	    ss->create == NULL || ss->destroy == NULL)
+	    ss->css_alloc == NULL || ss->css_free == NULL)
 		return -EINVAL;
 
 	/*
@@ -4464,10 +4461,11 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
 	subsys[ss->subsys_id] = ss;
 
 	/*
-	 * no ss->create seems to need anything important in the ss struct, so
-	 * this can happen first (i.e. before the rootnode attachment).
+	 * no ss->css_alloc seems to need anything important in the ss
+	 * struct, so this can happen first (i.e. before the rootnode
+	 * attachment).
 	 */
-	css = ss->create(dummytop);
+	css = ss->css_alloc(dummytop);
 	if (IS_ERR(css)) {
 		/* failure case - need to deassign the subsys[] slot. */
 		subsys[ss->subsys_id] = NULL;
@@ -4482,14 +4480,9 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
 	init_cgroup_css(css, ss, dummytop);
 	/* init_idr must be after init_cgroup_css because it sets css->id. */
 	if (ss->use_id) {
-		int ret = cgroup_init_idr(ss, css);
-		if (ret) {
-			dummytop->subsys[ss->subsys_id] = NULL;
-			ss->destroy(dummytop);
-			subsys[ss->subsys_id] = NULL;
-			mutex_unlock(&cgroup_mutex);
-			return ret;
-		}
+		ret = cgroup_init_idr(ss, css);
+		if (ret)
+			goto err_unload;
 	}
 
 	/*
@@ -4522,10 +4515,19 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
 	write_unlock(&css_set_lock);
 
 	ss->active = 1;
+	ret = online_css(ss, dummytop);
+	if (ret)
+		goto err_unload;
 
 	/* success! */
 	mutex_unlock(&cgroup_mutex);
 	return 0;
+
+err_unload:
+	mutex_unlock(&cgroup_mutex);
+	/* @ss can't be mounted here as try_module_get() would fail */
+	cgroup_unload_subsys(ss);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(cgroup_load_subsys);
 
@@ -4552,6 +4554,15 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
 	BUG_ON(ss->root != &rootnode);
 
 	mutex_lock(&cgroup_mutex);
+
+	offline_css(ss, dummytop);
+	ss->active = 0;
+
+	if (ss->use_id) {
+		idr_remove_all(&ss->idr);
+		idr_destroy(&ss->idr);
+	}
+
 	/* deassign the subsys_id */
 	subsys[ss->subsys_id] = NULL;
 
@@ -4567,7 +4578,6 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
 		struct css_set *cg = link->cg;
 
 		hlist_del(&cg->hlist);
-		BUG_ON(!cg->subsys[ss->subsys_id]);
 		cg->subsys[ss->subsys_id] = NULL;
 		hhead = css_set_hash(cg->subsys);
 		hlist_add_head(&cg->hlist, hhead);
@@ -4575,12 +4585,12 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
 	write_unlock(&css_set_lock);
 
 	/*
-	 * remove subsystem's css from the dummytop and free it - need to free
-	 * before marking as null because ss->destroy needs the cgrp->subsys
-	 * pointer to find their state. note that this also takes care of
-	 * freeing the css_id.
+	 * remove subsystem's css from the dummytop 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.
 	 */
-	ss->destroy(dummytop);
+	ss->css_free(dummytop);
 	dummytop->subsys[ss->subsys_id] = NULL;
 
 	mutex_unlock(&cgroup_mutex);
@@ -4624,8 +4634,8 @@ int __init cgroup_init_early(void)
 
 		BUG_ON(!ss->name);
 		BUG_ON(strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN);
-		BUG_ON(!ss->create);
-		BUG_ON(!ss->destroy);
+		BUG_ON(!ss->css_alloc);
+		BUG_ON(!ss->css_free);
 		if (ss->subsys_id != i) {
 			printk(KERN_ERR "cgroup: Subsys %s id == %d\n",
 			       ss->name, ss->subsys_id);
@@ -4832,44 +4842,19 @@ void cgroup_fork(struct task_struct *child)
 }
 
 /**
- * cgroup_fork_callbacks - run fork callbacks
- * @child: the new task
- *
- * Called on a new task very soon before adding it to the
- * tasklist. No need to take any locks since no-one can
- * be operating on this task.
- */
-void cgroup_fork_callbacks(struct task_struct *child)
-{
-	if (need_forkexit_callback) {
-		int i;
-		for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
-			struct cgroup_subsys *ss = subsys[i];
-
-			/*
-			 * forkexit callbacks are only supported for
-			 * builtin subsystems.
-			 */
-			if (!ss || ss->module)
-				continue;
-
-			if (ss->fork)
-				ss->fork(child);
-		}
-	}
-}
-
-/**
  * cgroup_post_fork - called on a new task after adding it to the task list
  * @child: the task in question
  *
- * Adds the task to the list running through its css_set if necessary.
- * Has to be after the task is visible on the task list in case we race
- * with the first call to cgroup_iter_start() - to guarantee that the
- * new task ends up on its list.
+ * Adds the task to the list running through its css_set if necessary and
+ * call the subsystem fork() callbacks.  Has to be after the task is
+ * visible on the task list in case we race with the first call to
+ * cgroup_iter_start() - to guarantee that the new task ends up on its
+ * list.
  */
 void cgroup_post_fork(struct task_struct *child)
 {
+	int i;
+
 	/*
 	 * use_task_css_set_links is set to 1 before we walk the tasklist
 	 * under the tasklist_lock and we read it here after we added the child
@@ -4889,7 +4874,30 @@ void cgroup_post_fork(struct task_struct *child)
 		task_unlock(child);
 		write_unlock(&css_set_lock);
 	}
+
+	/*
+	 * Call ss->fork().  This must happen after @child is linked on
+	 * css_set; otherwise, @child might change state between ->fork()
+	 * and addition to css_set.
+	 */
+	if (need_forkexit_callback) {
+		for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+			struct cgroup_subsys *ss = subsys[i];
+
+			/*
+			 * fork/exit callbacks are supported only for
+			 * builtin subsystems and we don't need further
+			 * synchronization as they never go away.
+			 */
+			if (!ss || ss->module)
+				continue;
+
+			if (ss->fork)
+				ss->fork(child);
+		}
+	}
 }
+
 /**
  * cgroup_exit - detach cgroup from exiting task
  * @tsk: pointer to task_struct of exiting process
@@ -5022,15 +5030,17 @@ static void check_for_release(struct cgroup *cgrp)
 /* Caller must verify that the css is not for root cgroup */
 bool __css_tryget(struct cgroup_subsys_state *css)
 {
-	do {
-		int v = css_refcnt(css);
+	while (true) {
+		int t, v;
 
-		if (atomic_cmpxchg(&css->refcnt, v, v + 1) == v)
+		v = css_refcnt(css);
+		t = atomic_cmpxchg(&css->refcnt, v, v + 1);
+		if (likely(t == v))
 			return true;
+		else if (t < 0)
+			return false;
 		cpu_relax();
-	} while (!test_bit(CSS_REMOVED, &css->flags));
-
-	return false;
+	}
 }
 EXPORT_SYMBOL_GPL(__css_tryget);
 
@@ -5049,11 +5059,9 @@ void __css_put(struct cgroup_subsys_state *css)
 			set_bit(CGRP_RELEASABLE, &cgrp->flags);
 			check_for_release(cgrp);
 		}
-		cgroup_wakeup_rmdir_waiter(cgrp);
 		break;
 	case 0:
-		if (!test_bit(CSS_CLEAR_CSS_REFS, &css->flags))
-			schedule_work(&css->dput_work);
+		schedule_work(&css->dput_work);
 		break;
 	}
 	rcu_read_unlock();
@@ -5439,7 +5447,7 @@ struct cgroup_subsys_state *cgroup_css_from_dir(struct file *f, int id)
 }
 
 #ifdef CONFIG_CGROUP_DEBUG
-static struct cgroup_subsys_state *debug_create(struct cgroup *cont)
+static struct cgroup_subsys_state *debug_css_alloc(struct cgroup *cont)
 {
 	struct cgroup_subsys_state *css = kzalloc(sizeof(*css), GFP_KERNEL);
 
@@ -5449,7 +5457,7 @@ static struct cgroup_subsys_state *debug_create(struct cgroup *cont)
 	return css;
 }
 
-static void debug_destroy(struct cgroup *cont)
+static void debug_css_free(struct cgroup *cont)
 {
 	kfree(cont->subsys[debug_subsys_id]);
 }
@@ -5578,8 +5586,8 @@ static struct cftype debug_files[] =  {
 
 struct cgroup_subsys debug_subsys = {
 	.name = "debug",
-	.create = debug_create,
-	.destroy = debug_destroy,
+	.css_alloc = debug_css_alloc,
+	.css_free = debug_css_free,
 	.subsys_id = debug_subsys_id,
 	.base_cftypes = debug_files,
 };
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c
index b1724ce..75dda1e 100644
--- a/kernel/cgroup_freezer.c
+++ b/kernel/cgroup_freezer.c
@@ -22,24 +22,33 @@
 #include <linux/freezer.h>
 #include <linux/seq_file.h>
 
-enum freezer_state {
-	CGROUP_THAWED = 0,
-	CGROUP_FREEZING,
-	CGROUP_FROZEN,
+/*
+ * A cgroup is freezing if any FREEZING flags are set.  FREEZING_SELF is
+ * set if "FROZEN" is written to freezer.state cgroupfs file, and cleared
+ * for "THAWED".  FREEZING_PARENT is set if the parent freezer is FREEZING
+ * for whatever reason.  IOW, a cgroup has FREEZING_PARENT set if one of
+ * its ancestors has FREEZING_SELF set.
+ */
+enum freezer_state_flags {
+	CGROUP_FREEZER_ONLINE	= (1 << 0), /* freezer is fully online */
+	CGROUP_FREEZING_SELF	= (1 << 1), /* this freezer is freezing */
+	CGROUP_FREEZING_PARENT	= (1 << 2), /* the parent freezer is freezing */
+	CGROUP_FROZEN		= (1 << 3), /* this and its descendants frozen */
+
+	/* mask for all FREEZING flags */
+	CGROUP_FREEZING		= CGROUP_FREEZING_SELF | CGROUP_FREEZING_PARENT,
 };
 
 struct freezer {
-	struct cgroup_subsys_state css;
-	enum freezer_state state;
-	spinlock_t lock; /* protects _writes_ to state */
+	struct cgroup_subsys_state	css;
+	unsigned int			state;
+	spinlock_t			lock;
 };
 
-static inline struct freezer *cgroup_freezer(
-		struct cgroup *cgroup)
+static inline struct freezer *cgroup_freezer(struct cgroup *cgroup)
 {
-	return container_of(
-		cgroup_subsys_state(cgroup, freezer_subsys_id),
-		struct freezer, css);
+	return container_of(cgroup_subsys_state(cgroup, freezer_subsys_id),
+			    struct freezer, css);
 }
 
 static inline struct freezer *task_freezer(struct task_struct *task)
@@ -48,14 +57,21 @@ static inline struct freezer *task_freezer(struct task_struct *task)
 			    struct freezer, css);
 }
 
+static struct freezer *parent_freezer(struct freezer *freezer)
+{
+	struct cgroup *pcg = freezer->css.cgroup->parent;
+
+	if (pcg)
+		return cgroup_freezer(pcg);
+	return NULL;
+}
+
 bool cgroup_freezing(struct task_struct *task)
 {
-	enum freezer_state state;
 	bool ret;
 
 	rcu_read_lock();
-	state = task_freezer(task)->state;
-	ret = state == CGROUP_FREEZING || state == CGROUP_FROZEN;
+	ret = task_freezer(task)->state & CGROUP_FREEZING;
 	rcu_read_unlock();
 
 	return ret;
@@ -65,70 +81,18 @@ bool cgroup_freezing(struct task_struct *task)
  * cgroups_write_string() limits the size of freezer state strings to
  * CGROUP_LOCAL_BUFFER_SIZE
  */
-static const char *freezer_state_strs[] = {
-	"THAWED",
-	"FREEZING",
-	"FROZEN",
+static const char *freezer_state_strs(unsigned int state)
+{
+	if (state & CGROUP_FROZEN)
+		return "FROZEN";
+	if (state & CGROUP_FREEZING)
+		return "FREEZING";
+	return "THAWED";
 };
 
-/*
- * State diagram
- * Transitions are caused by userspace writes to the freezer.state file.
- * The values in parenthesis are state labels. The rest are edge labels.
- *
- * (THAWED) --FROZEN--> (FREEZING) --FROZEN--> (FROZEN)
- *    ^ ^                    |                     |
- *    | \_______THAWED_______/                     |
- *    \__________________________THAWED____________/
- */
-
 struct cgroup_subsys freezer_subsys;
 
-/* Locks taken and their ordering
- * ------------------------------
- * cgroup_mutex (AKA cgroup_lock)
- * freezer->lock
- * css_set_lock
- * task->alloc_lock (AKA task_lock)
- * task->sighand->siglock
- *
- * cgroup code forces css_set_lock to be taken before task->alloc_lock
- *
- * freezer_create(), freezer_destroy():
- * cgroup_mutex [ by cgroup core ]
- *
- * freezer_can_attach():
- * cgroup_mutex (held by caller of can_attach)
- *
- * freezer_fork() (preserving fork() performance means can't take cgroup_mutex):
- * freezer->lock
- *  sighand->siglock (if the cgroup is freezing)
- *
- * freezer_read():
- * cgroup_mutex
- *  freezer->lock
- *   write_lock css_set_lock (cgroup iterator start)
- *    task->alloc_lock
- *   read_lock css_set_lock (cgroup iterator start)
- *
- * freezer_write() (freeze):
- * cgroup_mutex
- *  freezer->lock
- *   write_lock css_set_lock (cgroup iterator start)
- *    task->alloc_lock
- *   read_lock css_set_lock (cgroup iterator start)
- *    sighand->siglock (fake signal delivery inside freeze_task())
- *
- * freezer_write() (unfreeze):
- * cgroup_mutex
- *  freezer->lock
- *   write_lock css_set_lock (cgroup iterator start)
- *    task->alloc_lock
- *   read_lock css_set_lock (cgroup iterator start)
- *    task->alloc_lock (inside __thaw_task(), prevents race with refrigerator())
- *     sighand->siglock
- */
-static struct cgroup_subsys_state *freezer_create(struct cgroup *cgroup)
+static struct cgroup_subsys_state *freezer_css_alloc(struct cgroup *cgroup)
 {
 	struct freezer *freezer;
 
@@ -137,160 +101,244 @@ static struct cgroup_subsys_state *freezer_create(struct cgroup *cgroup)
 		return ERR_PTR(-ENOMEM);
 
 	spin_lock_init(&freezer->lock);
-	freezer->state = CGROUP_THAWED;
 	return &freezer->css;
 }
 
-static void freezer_destroy(struct cgroup *cgroup)
+/**
+ * freezer_css_online - commit creation of a freezer cgroup
+ * @cgroup: cgroup being created
+ *
+ * We're committing to creation of @cgroup.  Mark it online and inherit
+ * parent's freezing state while holding both parent's and our
+ * freezer->lock.
+ */
+static int freezer_css_online(struct cgroup *cgroup)
+{
+	struct freezer *freezer = cgroup_freezer(cgroup);
+	struct freezer *parent = parent_freezer(freezer);
+
+	/*
+	 * The following double locking and freezing state inheritance
+	 * guarantee that @cgroup can never escape ancestors' freezing
+	 * states.  See cgroup_for_each_descendant_pre() for details.
+	 */
+	if (parent)
+		spin_lock_irq(&parent->lock);
+	spin_lock_nested(&freezer->lock, SINGLE_DEPTH_NESTING);
+
+	freezer->state |= CGROUP_FREEZER_ONLINE;
+
+	if (parent && (parent->state & CGROUP_FREEZING)) {
+		freezer->state |= CGROUP_FREEZING_PARENT | CGROUP_FROZEN;
+		atomic_inc(&system_freezing_cnt);
+	}
+
+	spin_unlock(&freezer->lock);
+	if (parent)
+		spin_unlock_irq(&parent->lock);
+
+	return 0;
+}
+
+/**
+ * freezer_css_offline - initiate destruction of @cgroup
+ * @cgroup: cgroup being destroyed
+ *
+ * @cgroup is going away.  Mark it dead and decrement system_freezing_count
+ * if it was holding one.
+ */
+static void freezer_css_offline(struct cgroup *cgroup)
 {
 	struct freezer *freezer = cgroup_freezer(cgroup);
 
-	if (freezer->state != CGROUP_THAWED)
+	spin_lock_irq(&freezer->lock);
+
+	if (freezer->state & CGROUP_FREEZING)
 		atomic_dec(&system_freezing_cnt);
-	kfree(freezer);
+
+	freezer->state = 0;
+
+	spin_unlock_irq(&freezer->lock);
 }
 
-/* task is frozen or will freeze immediately when next it gets woken */
-static bool is_task_frozen_enough(struct task_struct *task)
+static void freezer_css_free(struct cgroup *cgroup)
 {
-	return frozen(task) ||
-		(task_is_stopped_or_traced(task) && freezing(task));
+	kfree(cgroup_freezer(cgroup));
 }
 
 /*
- * The call to cgroup_lock() in the freezer.state write method prevents
- * a write to that file racing against an attach, and hence the
- * can_attach() result will remain valid until the attach completes.
+ * Tasks can be migrated into a different freezer anytime regardless of its
+ * current state.  freezer_attach() is responsible for making new tasks
+ * conform to the current state.
+ *
+ * Freezer state changes and task migration are synchronized via
+ * @freezer->lock.  freezer_attach() makes the new tasks conform to the
+ * current state and all following state changes can see the new tasks.
  */
-static int freezer_can_attach(struct cgroup *new_cgroup,
-			      struct cgroup_taskset *tset)
+static void freezer_attach(struct cgroup *new_cgrp, struct cgroup_taskset *tset)
 {
-	struct freezer *freezer;
+	struct freezer *freezer = cgroup_freezer(new_cgrp);
 	struct task_struct *task;
+	bool clear_frozen = false;
+
+	spin_lock_irq(&freezer->lock);
 
 	/*
-	 * Anything frozen can't move or be moved to/from.
+	 * Make the new tasks conform to the current state of @new_cgrp.
+	 * For simplicity, when migrating any task to a FROZEN cgroup, we
+	 * revert it to FREEZING and let update_if_frozen() determine the
+	 * correct state later.
+	 *
+	 * Tasks in @tset are on @new_cgrp but may not conform to its
+	 * current state before executing the following - !frozen tasks may
+	 * be visible in a FROZEN cgroup and frozen tasks in a THAWED one.
 	 */
-	cgroup_taskset_for_each(task, new_cgroup, tset)
-		if (cgroup_freezing(task))
-			return -EBUSY;
+	cgroup_taskset_for_each(task, new_cgrp, tset) {
+		if (!(freezer->state & CGROUP_FREEZING)) {
+			__thaw_task(task);
+		} else {
+			freeze_task(task);
+			freezer->state &= ~CGROUP_FROZEN;
+			clear_frozen = true;
+		}
+	}
 
-	freezer = cgroup_freezer(new_cgroup);
-	if (freezer->state != CGROUP_THAWED)
-		return -EBUSY;
+	spin_unlock_irq(&freezer->lock);
 
-	return 0;
+	/*
+	 * Propagate FROZEN clearing upwards.  We may race with
+	 * update_if_frozen(), but as long as both work bottom-up, either
+	 * update_if_frozen() sees child's FROZEN cleared or we clear the
+	 * parent's FROZEN later.  No parent w/ !FROZEN children can be
+	 * left FROZEN.
+	 */
+	while (clear_frozen && (freezer = parent_freezer(freezer))) {
+		spin_lock_irq(&freezer->lock);
+		freezer->state &= ~CGROUP_FROZEN;
+		clear_frozen = freezer->state & CGROUP_FREEZING;
+		spin_unlock_irq(&freezer->lock);
+	}
 }
 
 static void freezer_fork(struct task_struct *task)
 {
 	struct freezer *freezer;
 
-	/*
-	 * No lock is needed, since the task isn't on tasklist yet,
-	 * so it can't be moved to another cgroup, which means the
-	 * freezer won't be removed and will be valid during this
-	 * function call.  Nevertheless, apply RCU read-side critical
-	 * section to suppress RCU lockdep false positives.
-	 */
 	rcu_read_lock();
 	freezer = task_freezer(task);
-	rcu_read_unlock();
 
 	/*
 	 * The root cgroup is non-freezable, so we can skip the
 	 * following check.
 	 */
 	if (!freezer->css.cgroup->parent)
-		return;
+		goto out;
 
 	spin_lock_irq(&freezer->lock);
-	BUG_ON(freezer->state == CGROUP_FROZEN);
-
-	/* Locking avoids race with FREEZING -> THAWED transitions. */
-	if (freezer->state == CGROUP_FREEZING)
+	if (freezer->state & CGROUP_FREEZING)
 		freeze_task(task);
 	spin_unlock_irq(&freezer->lock);
+out:
+	rcu_read_unlock();
 }
 
-/*
- * caller must hold freezer->lock
+/**
+ * update_if_frozen - update whether a cgroup finished freezing
+ * @cgroup: cgroup of interest
+ *
+ * Once FREEZING is initiated, transition to FROZEN is lazily updated by
+ * calling this function.  If the current state is FREEZING but not FROZEN,
+ * this function checks whether all tasks of this cgroup and the descendant
+ * cgroups finished freezing and, if so, sets FROZEN.
+ *
+ * The caller is responsible for grabbing RCU read lock and calling
+ * update_if_frozen() on all descendants prior to invoking this function.
+ *
+ * Task states and freezer state might disagree while tasks are being
+ * migrated into or out of @cgroup, so we can't verify task states against
+ * @freezer state here.  See freezer_attach() for details.
  */
-static void update_if_frozen(struct cgroup *cgroup,
-				 struct freezer *freezer)
+static void update_if_frozen(struct cgroup *cgroup)
 {
+	struct freezer *freezer = cgroup_freezer(cgroup);
+	struct cgroup *pos;
 	struct cgroup_iter it;
 	struct task_struct *task;
-	unsigned int nfrozen = 0, ntotal = 0;
-	enum freezer_state old_state = freezer->state;
 
-	cgroup_iter_start(cgroup, &it);
-	while ((task = cgroup_iter_next(cgroup, &it))) {
-		ntotal++;
-		if (freezing(task) && is_task_frozen_enough(task))
-			nfrozen++;
+	WARN_ON_ONCE(!rcu_read_lock_held());
+
+	spin_lock_irq(&freezer->lock);
+
+	if (!(freezer->state & CGROUP_FREEZING) ||
+	    (freezer->state & CGROUP_FROZEN))
+		goto out_unlock;
+
+	/* are all (live) children frozen? */
+	cgroup_for_each_child(pos, cgroup) {
+		struct freezer *child = cgroup_freezer(pos);
+
+		if ((child->state & CGROUP_FREEZER_ONLINE) &&
+		    !(child->state & CGROUP_FROZEN))
+			goto out_unlock;
 	}
 
-	if (old_state == CGROUP_THAWED) {
-		BUG_ON(nfrozen > 0);
-	} else if (old_state == CGROUP_FREEZING) {
-		if (nfrozen == ntotal)
-			freezer->state = CGROUP_FROZEN;
-	} else { /* old_state == CGROUP_FROZEN */
-		BUG_ON(nfrozen != ntotal);
+	/* are all tasks frozen? */
+	cgroup_iter_start(cgroup, &it);
+
+	while ((task = cgroup_iter_next(cgroup, &it))) {
+		if (freezing(task)) {
+			/*
+			 * freezer_should_skip() indicates that the task
+			 * should be skipped when determining freezing
+			 * completion.  Consider it frozen in addition to
+			 * the usual frozen condition.
+			 */
+			if (!frozen(task) && !freezer_should_skip(task))
+				goto out_iter_end;
+		}
 	}
 
+	freezer->state |= CGROUP_FROZEN;
+out_iter_end:
 	cgroup_iter_end(cgroup, &it);
+out_unlock:
+	spin_unlock_irq(&freezer->lock);
 }
 
 static int freezer_read(struct cgroup *cgroup, struct cftype *cft,
 			struct seq_file *m)
 {
-	struct freezer *freezer;
-	enum freezer_state state;
+	struct cgroup *pos;
 
-	if (!cgroup_lock_live_group(cgroup))
-		return -ENODEV;
+	rcu_read_lock();
 
-	freezer = cgroup_freezer(cgroup);
-	spin_lock_irq(&freezer->lock);
-	state = freezer->state;
-	if (state == CGROUP_FREEZING) {
-		/* We change from FREEZING to FROZEN lazily if the cgroup was
-		 * only partially frozen when we exitted write. */
-		update_if_frozen(cgroup, freezer);
-		state = freezer->state;
-	}
-	spin_unlock_irq(&freezer->lock);
-	cgroup_unlock();
+	/* update states bottom-up */
+	cgroup_for_each_descendant_post(pos, cgroup)
+		update_if_frozen(pos);
+	update_if_frozen(cgroup);
+
+	rcu_read_unlock();
 
-	seq_puts(m, freezer_state_strs[state]);
+	seq_puts(m, freezer_state_strs(cgroup_freezer(cgroup)->state));
 	seq_putc(m, '\n');
 	return 0;
 }
 
-static int try_to_freeze_cgroup(struct cgroup *cgroup, struct freezer *freezer)
+static void freeze_cgroup(struct freezer *freezer)
 {
+	struct cgroup *cgroup = freezer->css.cgroup;
 	struct cgroup_iter it;
 	struct task_struct *task;
-	unsigned int num_cant_freeze_now = 0;
 
 	cgroup_iter_start(cgroup, &it);
-	while ((task = cgroup_iter_next(cgroup, &it))) {
-		if (!freeze_task(task))
-			continue;
-		if (is_task_frozen_enough(task))
-			continue;
-		if (!freezing(task) && !freezer_should_skip(task))
-			num_cant_freeze_now++;
-	}
+	while ((task = cgroup_iter_next(cgroup, &it)))
+		freeze_task(task);
 	cgroup_iter_end(cgroup, &it);
-
-	return num_cant_freeze_now ? -EBUSY : 0;
 }
 
-static void unfreeze_cgroup(struct cgroup *cgroup, struct freezer *freezer)
+static void unfreeze_cgroup(struct freezer *freezer)
 {
+	struct cgroup *cgroup = freezer->css.cgroup;
 	struct cgroup_iter it;
 	struct task_struct *task;
 
@@ -300,59 +348,111 @@ static void unfreeze_cgroup(struct cgroup *cgroup, struct freezer *freezer)
 	cgroup_iter_end(cgroup, &it);
 }
 
-static int freezer_change_state(struct cgroup *cgroup,
-				enum freezer_state goal_state)
+/**
+ * freezer_apply_state - apply state change to a single cgroup_freezer
+ * @freezer: freezer to apply state change to
+ * @freeze: whether to freeze or unfreeze
+ * @state: CGROUP_FREEZING_* flag to set or clear
+ *
+ * Set or clear @state on @cgroup according to @freeze, and perform
+ * freezing or thawing as necessary.
+ */
+static void freezer_apply_state(struct freezer *freezer, bool freeze,
+				unsigned int state)
 {
-	struct freezer *freezer;
-	int retval = 0;
-
-	freezer = cgroup_freezer(cgroup);
+	/* also synchronizes against task migration, see freezer_attach() */
+	lockdep_assert_held(&freezer->lock);
 
-	spin_lock_irq(&freezer->lock);
+	if (!(freezer->state & CGROUP_FREEZER_ONLINE))
+		return;
 
-	update_if_frozen(cgroup, freezer);
-
-	switch (goal_state) {
-	case CGROUP_THAWED:
-		if (freezer->state != CGROUP_THAWED)
-			atomic_dec(&system_freezing_cnt);
-		freezer->state = CGROUP_THAWED;
-		unfreeze_cgroup(cgroup, freezer);
-		break;
-	case CGROUP_FROZEN:
-		if (freezer->state == CGROUP_THAWED)
+	if (freeze) {
+		if (!(freezer->state & CGROUP_FREEZING))
 			atomic_inc(&system_freezing_cnt);
-		freezer->state = CGROUP_FREEZING;
-		retval = try_to_freeze_cgroup(cgroup, freezer);
-		break;
-	default:
-		BUG();
+		freezer->state |= state;
+		freeze_cgroup(freezer);
+	} else {
+		bool was_freezing = freezer->state & CGROUP_FREEZING;
+
+		freezer->state &= ~state;
+
+		if (!(freezer->state & CGROUP_FREEZING)) {
+			if (was_freezing)
+				atomic_dec(&system_freezing_cnt);
+			freezer->state &= ~CGROUP_FROZEN;
+			unfreeze_cgroup(freezer);
+		}
 	}
+}
 
+/**
+ * freezer_change_state - change the freezing state of a cgroup_freezer
+ * @freezer: freezer of interest
+ * @freeze: whether to freeze or thaw
+ *
+ * Freeze or thaw @freezer according to @freeze.  The operations are
+ * recursive - all descendants of @freezer will be affected.
+ */
+static void freezer_change_state(struct freezer *freezer, bool freeze)
+{
+	struct cgroup *pos;
+
+	/* update @freezer */
+	spin_lock_irq(&freezer->lock);
+	freezer_apply_state(freezer, freeze, CGROUP_FREEZING_SELF);
 	spin_unlock_irq(&freezer->lock);
 
-	return retval;
+	/*
+	 * Update all its descendants in pre-order traversal.  Each
+	 * descendant will try to inherit its parent's FREEZING state as
+	 * CGROUP_FREEZING_PARENT.
+	 */
+	rcu_read_lock();
+	cgroup_for_each_descendant_pre(pos, freezer->css.cgroup) {
+		struct freezer *pos_f = cgroup_freezer(pos);
+		struct freezer *parent = parent_freezer(pos_f);
+
+		/*
+		 * Our update to @parent->state is already visible which is
+		 * all we need.  No need to lock @parent.  For more info on
+		 * synchronization, see freezer_post_create().
+		 */
+		spin_lock_irq(&pos_f->lock);
+		freezer_apply_state(pos_f, parent->state & CGROUP_FREEZING,
+				    CGROUP_FREEZING_PARENT);
+		spin_unlock_irq(&pos_f->lock);
+	}
+	rcu_read_unlock();
 }
 
-static int freezer_write(struct cgroup *cgroup,
-			 struct cftype *cft,
+static int freezer_write(struct cgroup *cgroup, struct cftype *cft,
 			 const char *buffer)
 {
-	int retval;
-	enum freezer_state goal_state;
+	bool freeze;
 
-	if (strcmp(buffer, freezer_state_strs[CGROUP_THAWED]) == 0)
-		goal_state = CGROUP_THAWED;
-	else if (strcmp(buffer, freezer_state_strs[CGROUP_FROZEN]) == 0)
-		goal_state = CGROUP_FROZEN;
+	if (strcmp(buffer, freezer_state_strs(0)) == 0)
+		freeze = false;
+	else if (strcmp(buffer, freezer_state_strs(CGROUP_FROZEN)) == 0)
+		freeze = true;
 	else
 		return -EINVAL;
 
-	if (!cgroup_lock_live_group(cgroup))
-		return -ENODEV;
-	retval = freezer_change_state(cgroup, goal_state);
-	cgroup_unlock();
-	return retval;
+	freezer_change_state(cgroup_freezer(cgroup), freeze);
+	return 0;
+}
+
+static u64 freezer_self_freezing_read(struct cgroup *cgroup, struct cftype *cft)
+{
+	struct freezer *freezer = cgroup_freezer(cgroup);
+
+	return (bool)(freezer->state & CGROUP_FREEZING_SELF);
+}
+
+static u64 freezer_parent_freezing_read(struct cgroup *cgroup, struct cftype *cft)
+{
+	struct freezer *freezer = cgroup_freezer(cgroup);
+
+	return (bool)(freezer->state & CGROUP_FREEZING_PARENT);
 }
 
 static struct cftype files[] = {
@@ -362,23 +462,27 @@ static struct cftype files[] = {
 		.read_seq_string = freezer_read,
 		.write_string = freezer_write,
 	},
+	{
+		.name = "self_freezing",
+		.flags = CFTYPE_NOT_ON_ROOT,
+		.read_u64 = freezer_self_freezing_read,
+	},
+	{
+		.name = "parent_freezing",
+		.flags = CFTYPE_NOT_ON_ROOT,
+		.read_u64 = freezer_parent_freezing_read,
+	},
 	{ }	/* terminate */
 };
 
 struct cgroup_subsys freezer_subsys = {
 	.name		= "freezer",
-	.create		= freezer_create,
-	.destroy	= freezer_destroy,
+	.css_alloc	= freezer_css_alloc,
+	.css_online	= freezer_css_online,
+	.css_offline	= freezer_css_offline,
+	.css_free	= freezer_css_free,
 	.subsys_id	= freezer_subsys_id,
-	.can_attach	= freezer_can_attach,
+	.attach		= freezer_attach,
 	.fork		= freezer_fork,
 	.base_cftypes	= files,
-
-	/*
-	 * freezer subsys doesn't handle hierarchy at all.  Frozen state
-	 * should be inherited through the hierarchy - if a parent is
-	 * frozen, all its children should be frozen.  Fix it and remove
-	 * the following.
-	 */
-	.broken_hierarchy = true,
 };
diff --git a/kernel/compat.c b/kernel/compat.c
index c28a306..f6150e9 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -1215,6 +1215,23 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info)
 	return 0;
 }
 
+#ifdef __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL
+asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid,
+						 struct compat_timespec __user *interval)
+{
+	struct timespec t;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+
+	set_fs(KERNEL_DS);
+	ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
+	set_fs(old_fs);
+	if (put_compat_timespec(&t, interval))
+		return -EFAULT;
+	return ret;
+}
+#endif /* __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL */
+
 /*
  * Allocate user-space memory for the duration of a single system call,
  * in order to marshall parameters inside a compat thunk.
diff --git a/kernel/context_tracking.c b/kernel/context_tracking.c
new file mode 100644
index 0000000..e0e07fd
--- /dev/null
+++ b/kernel/context_tracking.c
@@ -0,0 +1,83 @@
+#include <linux/context_tracking.h>
+#include <linux/rcupdate.h>
+#include <linux/sched.h>
+#include <linux/percpu.h>
+#include <linux/hardirq.h>
+
+struct context_tracking {
+	/*
+	 * When active is false, hooks are not set to
+	 * minimize overhead: TIF flags are cleared
+	 * and calls to user_enter/exit are ignored. This
+	 * may be further optimized using static keys.
+	 */
+	bool active;
+	enum {
+		IN_KERNEL = 0,
+		IN_USER,
+	} state;
+};
+
+static DEFINE_PER_CPU(struct context_tracking, context_tracking) = {
+#ifdef CONFIG_CONTEXT_TRACKING_FORCE
+	.active = true,
+#endif
+};
+
+void user_enter(void)
+{
+	unsigned long flags;
+
+	/*
+	 * Some contexts may involve an exception occuring in an irq,
+	 * leading to that nesting:
+	 * rcu_irq_enter() rcu_user_exit() rcu_user_exit() rcu_irq_exit()
+	 * This would mess up the dyntick_nesting count though. And rcu_irq_*()
+	 * helpers are enough to protect RCU uses inside the exception. So
+	 * just return immediately if we detect we are in an IRQ.
+	 */
+	if (in_interrupt())
+		return;
+
+	WARN_ON_ONCE(!current->mm);
+
+	local_irq_save(flags);
+	if (__this_cpu_read(context_tracking.active) &&
+	    __this_cpu_read(context_tracking.state) != IN_USER) {
+		__this_cpu_write(context_tracking.state, IN_USER);
+		rcu_user_enter();
+	}
+	local_irq_restore(flags);
+}
+
+void user_exit(void)
+{
+	unsigned long flags;
+
+	/*
+	 * Some contexts may involve an exception occuring in an irq,
+	 * leading to that nesting:
+	 * rcu_irq_enter() rcu_user_exit() rcu_user_exit() rcu_irq_exit()
+	 * This would mess up the dyntick_nesting count though. And rcu_irq_*()
+	 * helpers are enough to protect RCU uses inside the exception. So
+	 * just return immediately if we detect we are in an IRQ.
+	 */
+	if (in_interrupt())
+		return;
+
+	local_irq_save(flags);
+	if (__this_cpu_read(context_tracking.state) == IN_USER) {
+		__this_cpu_write(context_tracking.state, IN_KERNEL);
+		rcu_user_exit();
+	}
+	local_irq_restore(flags);
+}
+
+void context_tracking_task_switch(struct task_struct *prev,
+			     struct task_struct *next)
+{
+	if (__this_cpu_read(context_tracking.active)) {
+		clear_tsk_thread_flag(prev, TIF_NOHZ);
+		set_tsk_thread_flag(next, TIF_NOHZ);
+	}
+}
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 42bd331..f45657f 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -348,11 +348,13 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)
 	unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
 	struct task_struct *idle;
 
-	if (cpu_online(cpu) || !cpu_present(cpu))
-		return -EINVAL;
-
 	cpu_hotplug_begin();
 
+	if (cpu_online(cpu) || !cpu_present(cpu)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	idle = idle_thread_get(cpu);
 	if (IS_ERR(idle)) {
 		ret = PTR_ERR(idle);
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index f33c715..7bb63ee 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -302,10 +302,10 @@ static void guarantee_online_cpus(const struct cpuset *cs,
  * are online, with memory.  If none are online with memory, walk
  * up the cpuset hierarchy until we find one that does have some
  * online mems.  If we get all the way to the top and still haven't
- * found any online mems, return node_states[N_HIGH_MEMORY].
+ * found any online mems, return node_states[N_MEMORY].
  *
  * One way or another, we guarantee to return some non-empty subset
- * of node_states[N_HIGH_MEMORY].
+ * of node_states[N_MEMORY].
  *
  * Call with callback_mutex held.
  */
@@ -313,14 +313,14 @@ static void guarantee_online_cpus(const struct cpuset *cs,
 static void guarantee_online_mems(const struct cpuset *cs, nodemask_t *pmask)
 {
 	while (cs && !nodes_intersects(cs->mems_allowed,
-					node_states[N_HIGH_MEMORY]))
+					node_states[N_MEMORY]))
 		cs = cs->parent;
 	if (cs)
 		nodes_and(*pmask, cs->mems_allowed,
-					node_states[N_HIGH_MEMORY]);
+					node_states[N_MEMORY]);
 	else
-		*pmask = node_states[N_HIGH_MEMORY];
-	BUG_ON(!nodes_intersects(*pmask, node_states[N_HIGH_MEMORY]));
+		*pmask = node_states[N_MEMORY];
+	BUG_ON(!nodes_intersects(*pmask, node_states[N_MEMORY]));
 }
 
 /*
@@ -1100,7 +1100,7 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
 		return -ENOMEM;
 
 	/*
-	 * top_cpuset.mems_allowed tracks node_stats[N_HIGH_MEMORY];
+	 * top_cpuset.mems_allowed tracks node_stats[N_MEMORY];
 	 * it's read-only
 	 */
 	if (cs == &top_cpuset) {
@@ -1122,7 +1122,7 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
 			goto done;
 
 		if (!nodes_subset(trialcs->mems_allowed,
-				node_states[N_HIGH_MEMORY])) {
+				node_states[N_MEMORY])) {
 			retval =  -EINVAL;
 			goto done;
 		}
@@ -1784,56 +1784,20 @@ static struct cftype files[] = {
 };
 
 /*
- * post_clone() is called during cgroup_create() when the
- * clone_children mount argument was specified.  The cgroup
- * can not yet have any tasks.
- *
- * Currently we refuse to set up the cgroup - thereby
- * refusing the task to be entered, and as a result refusing
- * the sys_unshare() or clone() which initiated it - if any
- * sibling cpusets have exclusive cpus or mem.
- *
- * If this becomes a problem for some users who wish to
- * allow that scenario, then cpuset_post_clone() could be
- * changed to grant parent->cpus_allowed-sibling_cpus_exclusive
- * (and likewise for mems) to the new cgroup. Called with cgroup_mutex
- * held.
- */
-static void cpuset_post_clone(struct cgroup *cgroup)
-{
-	struct cgroup *parent, *child;
-	struct cpuset *cs, *parent_cs;
-
-	parent = cgroup->parent;
-	list_for_each_entry(child, &parent->children, sibling) {
-		cs = cgroup_cs(child);
-		if (is_mem_exclusive(cs) || is_cpu_exclusive(cs))
-			return;
-	}
-	cs = cgroup_cs(cgroup);
-	parent_cs = cgroup_cs(parent);
-
-	mutex_lock(&callback_mutex);
-	cs->mems_allowed = parent_cs->mems_allowed;
-	cpumask_copy(cs->cpus_allowed, parent_cs->cpus_allowed);
-	mutex_unlock(&callback_mutex);
-	return;
-}
-
-/*
- *	cpuset_create - create a cpuset
+ *	cpuset_css_alloc - allocate a cpuset css
  *	cont:	control group that the new cpuset will be part of
  */
 
-static struct cgroup_subsys_state *cpuset_create(struct cgroup *cont)
+static struct cgroup_subsys_state *cpuset_css_alloc(struct cgroup *cont)
 {
-	struct cpuset *cs;
-	struct cpuset *parent;
+	struct cgroup *parent_cg = cont->parent;
+	struct cgroup *tmp_cg;
+	struct cpuset *parent, *cs;
 
-	if (!cont->parent) {
+	if (!parent_cg)
 		return &top_cpuset.css;
-	}
-	parent = cgroup_cs(cont->parent);
+	parent = cgroup_cs(parent_cg);
+
 	cs = kmalloc(sizeof(*cs), GFP_KERNEL);
 	if (!cs)
 		return ERR_PTR(-ENOMEM);
@@ -1855,7 +1819,36 @@ static struct cgroup_subsys_state *cpuset_create(struct cgroup *cont)
 
 	cs->parent = parent;
 	number_of_cpusets++;
-	return &cs->css ;
+
+	if (!test_bit(CGRP_CPUSET_CLONE_CHILDREN, &cont->flags))
+		goto skip_clone;
+
+	/*
+	 * Clone @parent's configuration if CGRP_CPUSET_CLONE_CHILDREN is
+	 * set.  This flag handling is implemented in cgroup core for
+	 * histrical reasons - the flag may be specified during mount.
+	 *
+	 * Currently, if any sibling cpusets have exclusive cpus or mem, we
+	 * refuse to clone the configuration - thereby refusing the task to
+	 * be entered, and as a result refusing the sys_unshare() or
+	 * clone() which initiated it.  If this becomes a problem for some
+	 * users who wish to allow that scenario, then this could be
+	 * changed to grant parent->cpus_allowed-sibling_cpus_exclusive
+	 * (and likewise for mems) to the new cgroup.
+	 */
+	list_for_each_entry(tmp_cg, &parent_cg->children, sibling) {
+		struct cpuset *tmp_cs = cgroup_cs(tmp_cg);
+
+		if (is_mem_exclusive(tmp_cs) || is_cpu_exclusive(tmp_cs))
+			goto skip_clone;
+	}
+
+	mutex_lock(&callback_mutex);
+	cs->mems_allowed = parent->mems_allowed;
+	cpumask_copy(cs->cpus_allowed, parent->cpus_allowed);
+	mutex_unlock(&callback_mutex);
+skip_clone:
+	return &cs->css;
 }
 
 /*
@@ -1864,7 +1857,7 @@ static struct cgroup_subsys_state *cpuset_create(struct cgroup *cont)
  * will call async_rebuild_sched_domains().
  */
 
-static void cpuset_destroy(struct cgroup *cont)
+static void cpuset_css_free(struct cgroup *cont)
 {
 	struct cpuset *cs = cgroup_cs(cont);
 
@@ -1878,11 +1871,10 @@ static void cpuset_destroy(struct cgroup *cont)
 
 struct cgroup_subsys cpuset_subsys = {
 	.name = "cpuset",
-	.create = cpuset_create,
-	.destroy = cpuset_destroy,
+	.css_alloc = cpuset_css_alloc,
+	.css_free = cpuset_css_free,
 	.can_attach = cpuset_can_attach,
 	.attach = cpuset_attach,
-	.post_clone = cpuset_post_clone,
 	.subsys_id = cpuset_subsys_id,
 	.base_cftypes = files,
 	.early_init = 1,
@@ -2034,7 +2026,7 @@ static struct cpuset *cpuset_next(struct list_head *queue)
  * before dropping down to the next.  It always processes a node before
  * any of its children.
  *
- * In the case of memory hot-unplug, it will remove nodes from N_HIGH_MEMORY
+ * In the case of memory hot-unplug, it will remove nodes from N_MEMORY
  * if all present pages from a node are offlined.
  */
 static void
@@ -2073,7 +2065,7 @@ scan_cpusets_upon_hotplug(struct cpuset *root, enum hotplug_event event)
 
 			/* Continue past cpusets with all mems online */
 			if (nodes_subset(cp->mems_allowed,
-					node_states[N_HIGH_MEMORY]))
+					node_states[N_MEMORY]))
 				continue;
 
 			oldmems = cp->mems_allowed;
@@ -2081,7 +2073,7 @@ scan_cpusets_upon_hotplug(struct cpuset *root, enum hotplug_event event)
 			/* Remove offline mems from this cpuset. */
 			mutex_lock(&callback_mutex);
 			nodes_and(cp->mems_allowed, cp->mems_allowed,
-						node_states[N_HIGH_MEMORY]);
+						node_states[N_MEMORY]);
 			mutex_unlock(&callback_mutex);
 
 			/* Move tasks from the empty cpuset to a parent */
@@ -2134,8 +2126,8 @@ void cpuset_update_active_cpus(bool cpu_online)
 
 #ifdef CONFIG_MEMORY_HOTPLUG
 /*
- * Keep top_cpuset.mems_allowed tracking node_states[N_HIGH_MEMORY].
- * Call this routine anytime after node_states[N_HIGH_MEMORY] changes.
+ * Keep top_cpuset.mems_allowed tracking node_states[N_MEMORY].
+ * Call this routine anytime after node_states[N_MEMORY] changes.
  * See cpuset_update_active_cpus() for CPU hotplug handling.
  */
 static int cpuset_track_online_nodes(struct notifier_block *self,
@@ -2148,7 +2140,7 @@ static int cpuset_track_online_nodes(struct notifier_block *self,
 	case MEM_ONLINE:
 		oldmems = top_cpuset.mems_allowed;
 		mutex_lock(&callback_mutex);
-		top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
+		top_cpuset.mems_allowed = node_states[N_MEMORY];
 		mutex_unlock(&callback_mutex);
 		update_tasks_nodemask(&top_cpuset, &oldmems, NULL);
 		break;
@@ -2177,7 +2169,7 @@ static int cpuset_track_online_nodes(struct notifier_block *self,
 void __init cpuset_init_smp(void)
 {
 	cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask);
-	top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
+	top_cpuset.mems_allowed = node_states[N_MEMORY];
 
 	hotplug_memory_notifier(cpuset_track_online_nodes, 10);
 
@@ -2245,7 +2237,7 @@ void cpuset_init_current_mems_allowed(void)
  *
  * Description: Returns the nodemask_t mems_allowed of the cpuset
  * attached to the specified @tsk.  Guaranteed to return some non-empty
- * subset of node_states[N_HIGH_MEMORY], even if this means going outside the
+ * subset of node_states[N_MEMORY], even if this means going outside the
  * tasks cpuset.
  **/
 
diff --git a/kernel/cred.c b/kernel/cred.c
index 48cea3d..8888afb 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -30,17 +30,6 @@
 static struct kmem_cache *cred_jar;
 
 /*
- * The common credentials for the initial task's thread group
- */
-#ifdef CONFIG_KEYS
-static struct thread_group_cred init_tgcred = {
-	.usage	= ATOMIC_INIT(2),
-	.tgid	= 0,
-	.lock	= __SPIN_LOCK_UNLOCKED(init_cred.tgcred.lock),
-};
-#endif
-
-/*
  * The initial credentials for the initial task
  */
 struct cred init_cred = {
@@ -65,9 +54,6 @@ struct cred init_cred = {
 	.user			= INIT_USER,
 	.user_ns		= &init_user_ns,
 	.group_info		= &init_groups,
-#ifdef CONFIG_KEYS
-	.tgcred			= &init_tgcred,
-#endif
 };
 
 static inline void set_cred_subscribers(struct cred *cred, int n)
@@ -96,36 +82,6 @@ static inline void alter_cred_subscribers(const struct cred *_cred, int n)
 }
 
 /*
- * Dispose of the shared task group credentials
- */
-#ifdef CONFIG_KEYS
-static void release_tgcred_rcu(struct rcu_head *rcu)
-{
-	struct thread_group_cred *tgcred =
-		container_of(rcu, struct thread_group_cred, rcu);
-
-	BUG_ON(atomic_read(&tgcred->usage) != 0);
-
-	key_put(tgcred->session_keyring);
-	key_put(tgcred->process_keyring);
-	kfree(tgcred);
-}
-#endif
-
-/*
- * Release a set of thread group credentials.
- */
-static void release_tgcred(struct cred *cred)
-{
-#ifdef CONFIG_KEYS
-	struct thread_group_cred *tgcred = cred->tgcred;
-
-	if (atomic_dec_and_test(&tgcred->usage))
-		call_rcu(&tgcred->rcu, release_tgcred_rcu);
-#endif
-}
-
-/*
  * The RCU callback to actually dispose of a set of credentials
  */
 static void put_cred_rcu(struct rcu_head *rcu)
@@ -150,9 +106,10 @@ static void put_cred_rcu(struct rcu_head *rcu)
 #endif
 
 	security_cred_free(cred);
+	key_put(cred->session_keyring);
+	key_put(cred->process_keyring);
 	key_put(cred->thread_keyring);
 	key_put(cred->request_key_auth);
-	release_tgcred(cred);
 	if (cred->group_info)
 		put_group_info(cred->group_info);
 	free_uid(cred->user);
@@ -246,15 +203,6 @@ struct cred *cred_alloc_blank(void)
 	if (!new)
 		return NULL;
 
-#ifdef CONFIG_KEYS
-	new->tgcred = kzalloc(sizeof(*new->tgcred), GFP_KERNEL);
-	if (!new->tgcred) {
-		kmem_cache_free(cred_jar, new);
-		return NULL;
-	}
-	atomic_set(&new->tgcred->usage, 1);
-#endif
-
 	atomic_set(&new->usage, 1);
 #ifdef CONFIG_DEBUG_CREDENTIALS
 	new->magic = CRED_MAGIC;
@@ -308,9 +256,10 @@ struct cred *prepare_creds(void)
 	get_user_ns(new->user_ns);
 
 #ifdef CONFIG_KEYS
+	key_get(new->session_keyring);
+	key_get(new->process_keyring);
 	key_get(new->thread_keyring);
 	key_get(new->request_key_auth);
-	atomic_inc(&new->tgcred->usage);
 #endif
 
 #ifdef CONFIG_SECURITY
@@ -334,39 +283,20 @@ EXPORT_SYMBOL(prepare_creds);
  */
 struct cred *prepare_exec_creds(void)
 {
-	struct thread_group_cred *tgcred = NULL;
 	struct cred *new;
 
-#ifdef CONFIG_KEYS
-	tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
-	if (!tgcred)
-		return NULL;
-#endif
-
 	new = prepare_creds();
-	if (!new) {
-		kfree(tgcred);
+	if (!new)
 		return new;
-	}
 
 #ifdef CONFIG_KEYS
 	/* newly exec'd tasks don't get a thread keyring */
 	key_put(new->thread_keyring);
 	new->thread_keyring = NULL;
 
-	/* create a new per-thread-group creds for all this set of threads to
-	 * share */
-	memcpy(tgcred, new->tgcred, sizeof(struct thread_group_cred));
-
-	atomic_set(&tgcred->usage, 1);
-	spin_lock_init(&tgcred->lock);
-
 	/* inherit the session keyring; new process keyring */
-	key_get(tgcred->session_keyring);
-	tgcred->process_keyring = NULL;
-
-	release_tgcred(new);
-	new->tgcred = tgcred;
+	key_put(new->process_keyring);
+	new->process_keyring = NULL;
 #endif
 
 	return new;
@@ -383,9 +313,6 @@ struct cred *prepare_exec_creds(void)
  */
 int copy_creds(struct task_struct *p, unsigned long clone_flags)
 {
-#ifdef CONFIG_KEYS
-	struct thread_group_cred *tgcred;
-#endif
 	struct cred *new;
 	int ret;
 
@@ -425,22 +352,12 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
 			install_thread_keyring_to_cred(new);
 	}
 
-	/* we share the process and session keyrings between all the threads in
-	 * a process - this is slightly icky as we violate COW credentials a
-	 * bit */
+	/* The process keyring is only shared between the threads in a process;
+	 * anything outside of those threads doesn't inherit.
+	 */
 	if (!(clone_flags & CLONE_THREAD)) {
-		tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
-		if (!tgcred) {
-			ret = -ENOMEM;
-			goto error_put;
-		}
-		atomic_set(&tgcred->usage, 1);
-		spin_lock_init(&tgcred->lock);
-		tgcred->process_keyring = NULL;
-		tgcred->session_keyring = key_get(new->tgcred->session_keyring);
-
-		release_tgcred(new);
-		new->tgcred = tgcred;
+		key_put(new->process_keyring);
+		new->process_keyring = NULL;
 	}
 #endif
 
@@ -643,9 +560,6 @@ void __init cred_init(void)
  */
 struct cred *prepare_kernel_cred(struct task_struct *daemon)
 {
-#ifdef CONFIG_KEYS
-	struct thread_group_cred *tgcred;
-#endif
 	const struct cred *old;
 	struct cred *new;
 
@@ -653,14 +567,6 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
 	if (!new)
 		return NULL;
 
-#ifdef CONFIG_KEYS
-	tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
-	if (!tgcred) {
-		kmem_cache_free(cred_jar, new);
-		return NULL;
-	}
-#endif
-
 	kdebug("prepare_kernel_cred() alloc %p", new);
 
 	if (daemon)
@@ -678,13 +584,10 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
 	get_group_info(new->group_info);
 
 #ifdef CONFIG_KEYS
-	atomic_set(&tgcred->usage, 1);
-	spin_lock_init(&tgcred->lock);
-	tgcred->process_keyring = NULL;
-	tgcred->session_keyring = NULL;
-	new->tgcred = tgcred;
-	new->request_key_auth = NULL;
+	new->session_keyring = NULL;
+	new->process_keyring = NULL;
 	new->thread_keyring = NULL;
+	new->request_key_auth = NULL;
 	new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
 #endif
 
diff --git a/kernel/events/core.c b/kernel/events/core.c
index dbccf83..301079d 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6155,7 +6155,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
 
 	event->parent		= parent_event;
 
-	event->ns		= get_pid_ns(current->nsproxy->pid_ns);
+	event->ns		= get_pid_ns(task_active_pid_ns(current));
 	event->id		= atomic64_inc_return(&perf_event_id);
 
 	event->state		= PERF_EVENT_STATE_INACTIVE;
@@ -7434,7 +7434,7 @@ unlock:
 device_initcall(perf_event_sysfs_init);
 
 #ifdef CONFIG_CGROUP_PERF
-static struct cgroup_subsys_state *perf_cgroup_create(struct cgroup *cont)
+static struct cgroup_subsys_state *perf_cgroup_css_alloc(struct cgroup *cont)
 {
 	struct perf_cgroup *jc;
 
@@ -7451,7 +7451,7 @@ static struct cgroup_subsys_state *perf_cgroup_create(struct cgroup *cont)
 	return &jc->css;
 }
 
-static void perf_cgroup_destroy(struct cgroup *cont)
+static void perf_cgroup_css_free(struct cgroup *cont)
 {
 	struct perf_cgroup *jc;
 	jc = container_of(cgroup_subsys_state(cont, perf_subsys_id),
@@ -7492,8 +7492,8 @@ static void perf_cgroup_exit(struct cgroup *cgrp, struct cgroup *old_cgrp,
 struct cgroup_subsys perf_subsys = {
 	.name		= "perf_event",
 	.subsys_id	= perf_subsys_id,
-	.create		= perf_cgroup_create,
-	.destroy	= perf_cgroup_destroy,
+	.css_alloc	= perf_cgroup_css_alloc,
+	.css_free	= perf_cgroup_css_free,
 	.exit		= perf_cgroup_exit,
 	.attach		= perf_cgroup_attach,
 
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
index 9a7b487..fe8a916 100644
--- a/kernel/events/hw_breakpoint.c
+++ b/kernel/events/hw_breakpoint.c
@@ -111,14 +111,16 @@ static unsigned int max_task_bp_pinned(int cpu, enum bp_type_idx type)
  * Count the number of breakpoints of the same type and same task.
  * The given event must be not on the list.
  */
-static int task_bp_pinned(struct perf_event *bp, enum bp_type_idx type)
+static int task_bp_pinned(int cpu, struct perf_event *bp, enum bp_type_idx type)
 {
 	struct task_struct *tsk = bp->hw.bp_target;
 	struct perf_event *iter;
 	int count = 0;
 
 	list_for_each_entry(iter, &bp_task_head, hw.bp_list) {
-		if (iter->hw.bp_target == tsk && find_slot_idx(iter) == type)
+		if (iter->hw.bp_target == tsk &&
+		    find_slot_idx(iter) == type &&
+		    cpu == iter->cpu)
 			count += hw_breakpoint_weight(iter);
 	}
 
@@ -141,7 +143,7 @@ fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp,
 		if (!tsk)
 			slots->pinned += max_task_bp_pinned(cpu, type);
 		else
-			slots->pinned += task_bp_pinned(bp, type);
+			slots->pinned += task_bp_pinned(cpu, bp, type);
 		slots->flexible = per_cpu(nr_bp_flexible[type], cpu);
 
 		return;
@@ -154,7 +156,7 @@ fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp,
 		if (!tsk)
 			nr += max_task_bp_pinned(cpu, type);
 		else
-			nr += task_bp_pinned(bp, type);
+			nr += task_bp_pinned(cpu, bp, type);
 
 		if (nr > slots->pinned)
 			slots->pinned = nr;
@@ -188,7 +190,7 @@ static void toggle_bp_task_slot(struct perf_event *bp, int cpu, bool enable,
 	int old_idx = 0;
 	int idx = 0;
 
-	old_count = task_bp_pinned(bp, type);
+	old_count = task_bp_pinned(cpu, bp, type);
 	old_idx = old_count - 1;
 	idx = old_idx + weight;
 
diff --git a/kernel/exit.c b/kernel/exit.c
index 346616c..a4115ac 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -72,18 +72,6 @@ static void __unhash_process(struct task_struct *p, bool group_dead)
 		list_del_rcu(&p->tasks);
 		list_del_init(&p->sibling);
 		__this_cpu_dec(process_counts);
-		/*
-		 * If we are the last child process in a pid namespace to be
-		 * reaped, notify the reaper sleeping zap_pid_ns_processes().
-		 */
-		if (IS_ENABLED(CONFIG_PID_NS)) {
-			struct task_struct *parent = p->real_parent;
-
-			if ((task_active_pid_ns(parent)->child_reaper == parent) &&
-			    list_empty(&parent->children) &&
-			    (parent->flags & PF_EXITING))
-				wake_up_process(parent);
-		}
 	}
 	list_del_rcu(&p->thread_group);
 }
@@ -322,43 +310,6 @@ kill_orphaned_pgrp(struct task_struct *tsk, struct task_struct *parent)
 	}
 }
 
-/**
- * reparent_to_kthreadd - Reparent the calling kernel thread to kthreadd
- *
- * If a kernel thread is launched as a result of a system call, or if
- * it ever exits, it should generally reparent itself to kthreadd so it
- * isn't in the way of other processes and is correctly cleaned up on exit.
- *
- * The various task state such as scheduling policy and priority may have
- * been inherited from a user process, so we reset them to sane values here.
- *
- * NOTE that reparent_to_kthreadd() gives the caller full capabilities.
- */
-static void reparent_to_kthreadd(void)
-{
-	write_lock_irq(&tasklist_lock);
-
-	ptrace_unlink(current);
-	/* Reparent to init */
-	current->real_parent = current->parent = kthreadd_task;
-	list_move_tail(&current->sibling, &current->real_parent->children);
-
-	/* Set the exit signal to SIGCHLD so we signal init on exit */
-	current->exit_signal = SIGCHLD;
-
-	if (task_nice(current) < 0)
-		set_user_nice(current, 0);
-	/* cpus_allowed? */
-	/* rt_priority? */
-	/* signals? */
-	memcpy(current->signal->rlim, init_task.signal->rlim,
-	       sizeof(current->signal->rlim));
-
-	atomic_inc(&init_cred.usage);
-	commit_creds(&init_cred);
-	write_unlock_irq(&tasklist_lock);
-}
-
 void __set_special_pids(struct pid *pid)
 {
 	struct task_struct *curr = current->group_leader;
@@ -370,13 +321,6 @@ void __set_special_pids(struct pid *pid)
 		change_pid(curr, PIDTYPE_PGID, pid);
 }
 
-static void set_special_pids(struct pid *pid)
-{
-	write_lock_irq(&tasklist_lock);
-	__set_special_pids(pid);
-	write_unlock_irq(&tasklist_lock);
-}
-
 /*
  * Let kernel threads use this to say that they allow a certain signal.
  * Must not be used if kthread was cloned with CLONE_SIGHAND.
@@ -416,54 +360,6 @@ int disallow_signal(int sig)
 
 EXPORT_SYMBOL(disallow_signal);
 
-/*
- *	Put all the gunge required to become a kernel thread without
- *	attached user resources in one place where it belongs.
- */
-
-void daemonize(const char *name, ...)
-{
-	va_list args;
-	sigset_t blocked;
-
-	va_start(args, name);
-	vsnprintf(current->comm, sizeof(current->comm), name, args);
-	va_end(args);
-
-	/*
-	 * If we were started as result of loading a module, close all of the
-	 * user space pages.  We don't need them, and if we didn't close them
-	 * they would be locked into memory.
-	 */
-	exit_mm(current);
-	/*
-	 * We don't want to get frozen, in case system-wide hibernation
-	 * or suspend transition begins right now.
-	 */
-	current->flags |= (PF_NOFREEZE | PF_KTHREAD);
-
-	if (current->nsproxy != &init_nsproxy) {
-		get_nsproxy(&init_nsproxy);
-		switch_task_namespaces(current, &init_nsproxy);
-	}
-	set_special_pids(&init_struct_pid);
-	proc_clear_tty(current);
-
-	/* Block and flush all signals */
-	sigfillset(&blocked);
-	sigprocmask(SIG_BLOCK, &blocked, NULL);
-	flush_signals(current);
-
-	/* Become as one with the init task */
-
-	daemonize_fs_struct();
-	daemonize_descriptors();
-
-	reparent_to_kthreadd();
-}
-
-EXPORT_SYMBOL(daemonize);
-
 #ifdef CONFIG_MM_OWNER
 /*
  * A task is exiting.   If it owned this mm, find a new owner for the mm.
diff --git a/kernel/fork.c b/kernel/fork.c
index 8b20ab7..32d59c9 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -146,7 +146,7 @@ void __weak arch_release_thread_info(struct thread_info *ti)
 static struct thread_info *alloc_thread_info_node(struct task_struct *tsk,
 						  int node)
 {
-	struct page *page = alloc_pages_node(node, THREADINFO_GFP,
+	struct page *page = alloc_pages_node(node, THREADINFO_GFP_ACCOUNTED,
 					     THREAD_SIZE_ORDER);
 
 	return page ? page_address(page) : NULL;
@@ -154,7 +154,7 @@ static struct thread_info *alloc_thread_info_node(struct task_struct *tsk,
 
 static inline void free_thread_info(struct thread_info *ti)
 {
-	free_pages((unsigned long)ti, THREAD_SIZE_ORDER);
+	free_memcg_kmem_pages((unsigned long)ti, THREAD_SIZE_ORDER);
 }
 # else
 static struct kmem_cache *thread_info_cache;
@@ -1039,8 +1039,6 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
 	atomic_set(&sig->live, 1);
 	atomic_set(&sig->sigcnt, 1);
 	init_waitqueue_head(&sig->wait_chldexit);
-	if (clone_flags & CLONE_NEWPID)
-		sig->flags |= SIGNAL_UNKILLABLE;
 	sig->curr_target = tsk;
 	init_sigpending(&sig->shared_pending);
 	INIT_LIST_HEAD(&sig->posix_timers);
@@ -1127,7 +1125,6 @@ static void posix_cpu_timers_init(struct task_struct *tsk)
  */
 static struct task_struct *copy_process(unsigned long clone_flags,
 					unsigned long stack_start,
-					struct pt_regs *regs,
 					unsigned long stack_size,
 					int __user *child_tidptr,
 					struct pid *pid,
@@ -1135,7 +1132,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 {
 	int retval;
 	struct task_struct *p;
-	int cgroup_callbacks_done = 0;
 
 	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
 		return ERR_PTR(-EINVAL);
@@ -1320,7 +1316,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	retval = copy_io(clone_flags, p);
 	if (retval)
 		goto bad_fork_cleanup_namespaces;
-	retval = copy_thread(clone_flags, stack_start, stack_size, p, regs);
+	retval = copy_thread(clone_flags, stack_start, stack_size, p);
 	if (retval)
 		goto bad_fork_cleanup_io;
 
@@ -1393,12 +1389,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	INIT_LIST_HEAD(&p->thread_group);
 	p->task_works = NULL;
 
-	/* Now that the task is set up, run cgroup callbacks if
-	 * necessary. We need to run them before the task is visible
-	 * on the tasklist. */
-	cgroup_fork_callbacks(p);
-	cgroup_callbacks_done = 1;
-
 	/* Need tasklist lock for parent etc handling! */
 	write_lock_irq(&tasklist_lock);
 
@@ -1441,8 +1431,10 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 		ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);
 
 		if (thread_group_leader(p)) {
-			if (is_child_reaper(pid))
-				p->nsproxy->pid_ns->child_reaper = p;
+			if (is_child_reaper(pid)) {
+				ns_of_pid(pid)->child_reaper = p;
+				p->signal->flags |= SIGNAL_UNKILLABLE;
+			}
 
 			p->signal->leader_pid = pid;
 			p->signal->tty = tty_kref_get(current->signal->tty);
@@ -1476,8 +1468,6 @@ bad_fork_cleanup_io:
 	if (p->io_context)
 		exit_io_context(p);
 bad_fork_cleanup_namespaces:
-	if (unlikely(clone_flags & CLONE_NEWPID))
-		pid_ns_release_proc(p->nsproxy->pid_ns);
 	exit_task_namespaces(p);
 bad_fork_cleanup_mm:
 	if (p->mm)
@@ -1503,7 +1493,7 @@ bad_fork_cleanup_cgroup:
 #endif
 	if (clone_flags & CLONE_THREAD)
 		threadgroup_change_end(current);
-	cgroup_exit(p, cgroup_callbacks_done);
+	cgroup_exit(p, 0);
 	delayacct_tsk_free(p);
 	module_put(task_thread_info(p)->exec_domain->module);
 bad_fork_cleanup_count:
@@ -1515,12 +1505,6 @@ fork_out:
 	return ERR_PTR(retval);
 }
 
-noinline struct pt_regs * __cpuinit __attribute__((weak)) idle_regs(struct pt_regs *regs)
-{
-	memset(regs, 0, sizeof(struct pt_regs));
-	return regs;
-}
-
 static inline void init_idle_pids(struct pid_link *links)
 {
 	enum pid_type type;
@@ -1534,10 +1518,7 @@ static inline void init_idle_pids(struct pid_link *links)
 struct task_struct * __cpuinit fork_idle(int cpu)
 {
 	struct task_struct *task;
-	struct pt_regs regs;
-
-	task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL,
-			    &init_struct_pid, 0);
+	task = copy_process(CLONE_VM, 0, 0, NULL, &init_struct_pid, 0);
 	if (!IS_ERR(task)) {
 		init_idle_pids(task->pids);
 		init_idle(task, cpu);
@@ -1554,7 +1535,6 @@ struct task_struct * __cpuinit fork_idle(int cpu)
  */
 long do_fork(unsigned long clone_flags,
 	      unsigned long stack_start,
-	      struct pt_regs *regs,
 	      unsigned long stack_size,
 	      int __user *parent_tidptr,
 	      int __user *child_tidptr)
@@ -1567,15 +1547,9 @@ long do_fork(unsigned long clone_flags,
 	 * Do some preliminary argument and permissions checking before we
 	 * actually start allocating stuff
 	 */
-	if (clone_flags & CLONE_NEWUSER) {
-		if (clone_flags & CLONE_THREAD)
+	if (clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) {
+		if (clone_flags & (CLONE_THREAD|CLONE_PARENT))
 			return -EINVAL;
-		/* hopefully this check will go away when userns support is
-		 * complete
-		 */
-		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SETUID) ||
-				!capable(CAP_SETGID))
-			return -EPERM;
 	}
 
 	/*
@@ -1584,7 +1558,7 @@ long do_fork(unsigned long clone_flags,
 	 * requested, no event is reported; otherwise, report if the event
 	 * for the type of forking is enabled.
 	 */
-	if (!(clone_flags & CLONE_UNTRACED) && likely(user_mode(regs))) {
+	if (!(clone_flags & CLONE_UNTRACED)) {
 		if (clone_flags & CLONE_VFORK)
 			trace = PTRACE_EVENT_VFORK;
 		else if ((clone_flags & CSIGNAL) != SIGCHLD)
@@ -1596,7 +1570,7 @@ long do_fork(unsigned long clone_flags,
 			trace = 0;
 	}
 
-	p = copy_process(clone_flags, stack_start, regs, stack_size,
+	p = copy_process(clone_flags, stack_start, stack_size,
 			 child_tidptr, NULL, trace);
 	/*
 	 * Do this prior waking up the new thread - the thread pointer
@@ -1640,11 +1614,54 @@ long do_fork(unsigned long clone_flags,
  */
 pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 {
-	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn, NULL,
+	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn,
 		(unsigned long)arg, NULL, NULL);
 }
 #endif
 
+#ifdef __ARCH_WANT_SYS_FORK
+SYSCALL_DEFINE0(fork)
+{
+#ifdef CONFIG_MMU
+	return do_fork(SIGCHLD, 0, 0, NULL, NULL);
+#else
+	/* can not support in nommu mode */
+	return(-EINVAL);
+#endif
+}
+#endif
+
+#ifdef __ARCH_WANT_SYS_VFORK
+SYSCALL_DEFINE0(vfork)
+{
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, 
+			0, NULL, NULL);
+}
+#endif
+
+#ifdef __ARCH_WANT_SYS_CLONE
+#ifdef CONFIG_CLONE_BACKWARDS
+SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
+		 int __user *, parent_tidptr,
+		 int, tls_val,
+		 int __user *, child_tidptr)
+#elif defined(CONFIG_CLONE_BACKWARDS2)
+SYSCALL_DEFINE5(clone, unsigned long, newsp, unsigned long, clone_flags,
+		 int __user *, parent_tidptr,
+		 int __user *, child_tidptr,
+		 int, tls_val)
+#else
+SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
+		 int __user *, parent_tidptr,
+		 int __user *, child_tidptr,
+		 int, tls_val)
+#endif
+{
+	return do_fork(clone_flags, newsp, 0,
+		parent_tidptr, child_tidptr);
+}
+#endif
+
 #ifndef ARCH_MIN_MMSTRUCT_ALIGN
 #define ARCH_MIN_MMSTRUCT_ALIGN 0
 #endif
@@ -1694,7 +1711,8 @@ static int check_unshare_flags(unsigned long unshare_flags)
 {
 	if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
 				CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
-				CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET))
+				CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET|
+				CLONE_NEWUSER|CLONE_NEWPID))
 		return -EINVAL;
 	/*
 	 * Not implemented, but pretend it works if there is nothing to
@@ -1761,19 +1779,40 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
 {
 	struct fs_struct *fs, *new_fs = NULL;
 	struct files_struct *fd, *new_fd = NULL;
+	struct cred *new_cred = NULL;
 	struct nsproxy *new_nsproxy = NULL;
 	int do_sysvsem = 0;
 	int err;
 
-	err = check_unshare_flags(unshare_flags);
-	if (err)
-		goto bad_unshare_out;
-
+	/*
+	 * If unsharing a user namespace must also unshare the thread.
+	 */
+	if (unshare_flags & CLONE_NEWUSER)
+		unshare_flags |= CLONE_THREAD;
+	/*
+	 * If unsharing a pid namespace must also unshare the thread.
+	 */
+	if (unshare_flags & CLONE_NEWPID)
+		unshare_flags |= CLONE_THREAD;
+	/*
+	 * If unsharing a thread from a thread group, must also unshare vm.
+	 */
+	if (unshare_flags & CLONE_THREAD)
+		unshare_flags |= CLONE_VM;
+	/*
+	 * If unsharing vm, must also unshare signal handlers.
+	 */
+	if (unshare_flags & CLONE_VM)
+		unshare_flags |= CLONE_SIGHAND;
 	/*
 	 * If unsharing namespace, must also unshare filesystem information.
 	 */
 	if (unshare_flags & CLONE_NEWNS)
 		unshare_flags |= CLONE_FS;
+
+	err = check_unshare_flags(unshare_flags);
+	if (err)
+		goto bad_unshare_out;
 	/*
 	 * CLONE_NEWIPC must also detach from the undolist: after switching
 	 * to a new ipc namespace, the semaphore arrays from the old
@@ -1787,11 +1826,15 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
 	err = unshare_fd(unshare_flags, &new_fd);
 	if (err)
 		goto bad_unshare_cleanup_fs;
-	err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy, new_fs);
+	err = unshare_userns(unshare_flags, &new_cred);
 	if (err)
 		goto bad_unshare_cleanup_fd;
+	err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy,
+					 new_cred, new_fs);
+	if (err)
+		goto bad_unshare_cleanup_cred;
 
-	if (new_fs || new_fd || do_sysvsem || new_nsproxy) {
+	if (new_fs || new_fd || do_sysvsem || new_cred || new_nsproxy) {
 		if (do_sysvsem) {
 			/*
 			 * CLONE_SYSVSEM is equivalent to sys_exit().
@@ -1799,10 +1842,8 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
 			exit_sem(current);
 		}
 
-		if (new_nsproxy) {
+		if (new_nsproxy)
 			switch_task_namespaces(current, new_nsproxy);
-			new_nsproxy = NULL;
-		}
 
 		task_lock(current);
 
@@ -1824,11 +1865,17 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
 		}
 
 		task_unlock(current);
-	}
 
-	if (new_nsproxy)
-		put_nsproxy(new_nsproxy);
+		if (new_cred) {
+			/* Install the new user namespace */
+			commit_creds(new_cred);
+			new_cred = NULL;
+		}
+	}
 
+bad_unshare_cleanup_cred:
+	if (new_cred)
+		put_cred(new_cred);
 bad_unshare_cleanup_fd:
 	if (new_fd)
 		put_files_struct(new_fd);
diff --git a/kernel/freezer.c b/kernel/freezer.c
index 11f82a4..c38893b 100644
--- a/kernel/freezer.c
+++ b/kernel/freezer.c
@@ -116,17 +116,10 @@ bool freeze_task(struct task_struct *p)
 		return false;
 	}
 
-	if (!(p->flags & PF_KTHREAD)) {
+	if (!(p->flags & PF_KTHREAD))
 		fake_signal_wake_up(p);
-		/*
-		 * fake_signal_wake_up() goes through p's scheduler
-		 * lock and guarantees that TASK_STOPPED/TRACED ->
-		 * TASK_RUNNING transition can't race with task state
-		 * testing in try_to_freeze_tasks().
-		 */
-	} else {
+	else
 		wake_up_state(p, TASK_INTERRUPTIBLE);
-	}
 
 	spin_unlock_irqrestore(&freezer_lock, flags);
 	return true;
diff --git a/kernel/futex.c b/kernel/futex.c
index 20ef219..19eb089 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -843,6 +843,9 @@ static void wake_futex(struct futex_q *q)
 {
 	struct task_struct *p = q->task;
 
+	if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n"))
+		return;
+
 	/*
 	 * We set q->lock_ptr = NULL _before_ we wake up the task. If
 	 * a non-futex wake up happens on another CPU then the task
@@ -1078,6 +1081,10 @@ retry_private:
 
 	plist_for_each_entry_safe(this, next, head, list) {
 		if (match_futex (&this->key, &key1)) {
+			if (this->pi_state || this->rt_waiter) {
+				ret = -EINVAL;
+				goto out_unlock;
+			}
 			wake_futex(this);
 			if (++ret >= nr_wake)
 				break;
@@ -1090,6 +1097,10 @@ retry_private:
 		op_ret = 0;
 		plist_for_each_entry_safe(this, next, head, list) {
 			if (match_futex (&this->key, &key2)) {
+				if (this->pi_state || this->rt_waiter) {
+					ret = -EINVAL;
+					goto out_unlock;
+				}
 				wake_futex(this);
 				if (++op_ret >= nr_wake2)
 					break;
@@ -1098,6 +1109,7 @@ retry_private:
 		ret += op_ret;
 	}
 
+out_unlock:
 	double_unlock_hb(hb1, hb2);
 out_put_keys:
 	put_futex_key(&key2);
@@ -1387,9 +1399,13 @@ retry_private:
 		/*
 		 * FUTEX_WAIT_REQEUE_PI and FUTEX_CMP_REQUEUE_PI should always
 		 * be paired with each other and no other futex ops.
+		 *
+		 * We should never be requeueing a futex_q with a pi_state,
+		 * which is awaiting a futex_unlock_pi().
 		 */
 		if ((requeue_pi && !this->rt_waiter) ||
-		    (!requeue_pi && this->rt_waiter)) {
+		    (!requeue_pi && this->rt_waiter) ||
+		    this->pi_state) {
 			ret = -EINVAL;
 			break;
 		}
diff --git a/kernel/gcov/Kconfig b/kernel/gcov/Kconfig
index a920281..d4da55d 100644
--- a/kernel/gcov/Kconfig
+++ b/kernel/gcov/Kconfig
@@ -35,7 +35,7 @@ config GCOV_KERNEL
 config GCOV_PROFILE_ALL
 	bool "Profile entire Kernel"
 	depends on GCOV_KERNEL
-	depends on SUPERH || S390 || X86 || (PPC && EXPERIMENTAL) || MICROBLAZE
+	depends on SUPERH || S390 || X86 || PPC || MICROBLAZE
 	default n
 	---help---
 	This options activates profiling for the entire kernel.
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 57d86d0..3aca9f2 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -272,6 +272,7 @@ void handle_nested_irq(unsigned int irq)
 
 	raw_spin_lock_irq(&desc->lock);
 
+	desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
 	kstat_incr_irqs_this_cpu(irq, desc);
 
 	action = desc->action;
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 4c69326..e49a288 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -616,6 +616,22 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
 	return ret;
 }
 
+#ifdef CONFIG_HARDIRQS_SW_RESEND
+int irq_set_parent(int irq, int parent_irq)
+{
+	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
+
+	if (!desc)
+		return -EINVAL;
+
+	desc->parent_irq = parent_irq;
+
+	irq_put_desc_unlock(desc, flags);
+	return 0;
+}
+#endif
+
 /*
  * Default primary interrupt handler for threaded interrupts. Is
  * assigned as primary handler when request_threaded_irq is called
@@ -716,6 +732,7 @@ static void
 irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)
 {
 	cpumask_var_t mask;
+	bool valid = true;
 
 	if (!test_and_clear_bit(IRQTF_AFFINITY, &action->thread_flags))
 		return;
@@ -730,10 +747,18 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)
 	}
 
 	raw_spin_lock_irq(&desc->lock);
-	cpumask_copy(mask, desc->irq_data.affinity);
+	/*
+	 * This code is triggered unconditionally. Check the affinity
+	 * mask pointer. For CPU_MASK_OFFSTACK=n this is optimized out.
+	 */
+	if (desc->irq_data.affinity)
+		cpumask_copy(mask, desc->irq_data.affinity);
+	else
+		valid = false;
 	raw_spin_unlock_irq(&desc->lock);
 
-	set_cpus_allowed_ptr(current, mask);
+	if (valid)
+		set_cpus_allowed_ptr(current, mask);
 	free_cpumask_var(mask);
 }
 #else
@@ -793,7 +818,7 @@ static void irq_thread_dtor(struct callback_head *unused)
 	action = kthread_data(tsk);
 
 	pr_err("exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n",
-	       tsk->comm ? tsk->comm : "", tsk->pid, action->irq);
+	       tsk->comm, tsk->pid, action->irq);
 
 
 	desc = irq_to_desc(action->irq);
@@ -833,6 +858,8 @@ static int irq_thread(void *data)
 	init_task_work(&on_exit_work, irq_thread_dtor);
 	task_work_add(current, &on_exit_work, false);
 
+	irq_thread_check_affinity(desc, action);
+
 	while (!irq_wait_for_interrupt(action)) {
 		irqreturn_t action_ret;
 
@@ -936,6 +963,16 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 		 */
 		get_task_struct(t);
 		new->thread = t;
+		/*
+		 * Tell the thread to set its affinity. This is
+		 * important for shared interrupt handlers as we do
+		 * not invoke setup_affinity() for the secondary
+		 * handlers as everything is already set up. Even for
+		 * interrupts marked with IRQF_NO_BALANCE this is
+		 * correct as we want the thread to move to the cpu(s)
+		 * on which the requesting code placed the interrupt.
+		 */
+		set_bit(IRQTF_AFFINITY, &new->thread_flags);
 	}
 
 	if (!alloc_cpumask_var(&mask, GFP_KERNEL)) {
diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c
index 6454db7..9065107 100644
--- a/kernel/irq/resend.c
+++ b/kernel/irq/resend.c
@@ -74,6 +74,14 @@ void check_irq_resend(struct irq_desc *desc, unsigned int irq)
 		if (!desc->irq_data.chip->irq_retrigger ||
 		    !desc->irq_data.chip->irq_retrigger(&desc->irq_data)) {
 #ifdef CONFIG_HARDIRQS_SW_RESEND
+			/*
+			 * If the interrupt has a parent irq and runs
+			 * in the thread context of the parent irq,
+			 * retrigger the parent.
+			 */
+			if (desc->parent_irq &&
+			    irq_settings_is_nested_thread(desc))
+				irq = desc->parent_irq;
 			/* Set it pending and activate the softirq: */
 			set_bit(irq, irqs_resend);
 			tasklet_schedule(&resend_tasklet);
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index 4e316e1..6ada93c 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -26,7 +26,6 @@ static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
 static struct kobj_attribute _name##_attr = \
 	__ATTR(_name, 0644, _name##_show, _name##_store)
 
-#if defined(CONFIG_HOTPLUG)
 /* current uevent sequence number */
 static ssize_t uevent_seqnum_show(struct kobject *kobj,
 				  struct kobj_attribute *attr, char *buf)
@@ -54,7 +53,7 @@ static ssize_t uevent_helper_store(struct kobject *kobj,
 	return count;
 }
 KERNEL_ATTR_RW(uevent_helper);
-#endif
+
 
 #ifdef CONFIG_PROFILING
 static ssize_t profiling_show(struct kobject *kobj,
@@ -141,6 +140,23 @@ static ssize_t fscaps_show(struct kobject *kobj,
 }
 KERNEL_ATTR_RO(fscaps);
 
+int rcu_expedited;
+static ssize_t rcu_expedited_show(struct kobject *kobj,
+				  struct kobj_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", rcu_expedited);
+}
+static ssize_t rcu_expedited_store(struct kobject *kobj,
+				   struct kobj_attribute *attr,
+				   const char *buf, size_t count)
+{
+	if (kstrtoint(buf, 0, &rcu_expedited))
+		return -EINVAL;
+
+	return count;
+}
+KERNEL_ATTR_RW(rcu_expedited);
+
 /*
  * Make /sys/kernel/notes give the raw contents of our kernel .notes section.
  */
@@ -169,10 +185,8 @@ EXPORT_SYMBOL_GPL(kernel_kobj);
 
 static struct attribute * kernel_attrs[] = {
 	&fscaps_attr.attr,
-#if defined(CONFIG_HOTPLUG)
 	&uevent_seqnum_attr.attr,
 	&uevent_helper_attr.attr,
-#endif
 #ifdef CONFIG_PROFILING
 	&profiling_attr.attr,
 #endif
@@ -182,6 +196,7 @@ static struct attribute * kernel_attrs[] = {
 	&kexec_crash_size_attr.attr,
 	&vmcoreinfo_attr.attr,
 #endif
+	&rcu_expedited_attr.attr,
 	NULL
 };
 
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 29fb60c..691dc2e 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -428,7 +428,7 @@ int kthreadd(void *unused)
 	set_task_comm(tsk, "kthreadd");
 	ignore_signals(tsk);
 	set_cpus_allowed_ptr(tsk, cpu_all_mask);
-	set_mems_allowed(node_states[N_HIGH_MEMORY]);
+	set_mems_allowed(node_states[N_MEMORY]);
 
 	current->flags |= PF_NOFREEZE;
 
diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c
index 91c32a0..b2c71c5 100644
--- a/kernel/lockdep_proc.c
+++ b/kernel/lockdep_proc.c
@@ -39,7 +39,7 @@ static void l_stop(struct seq_file *m, void *v)
 
 static void print_name(struct seq_file *m, struct lock_class *class)
 {
-	char str[128];
+	char str[KSYM_NAME_LEN];
 	const char *name = class->name;
 
 	if (!name) {
diff --git a/kernel/module.c b/kernel/module.c
index 6e48c3a..c8d9bbf 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -21,6 +21,7 @@
 #include <linux/ftrace_event.h>
 #include <linux/init.h>
 #include <linux/kallsyms.h>
+#include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/sysfs.h>
 #include <linux/kernel.h>
@@ -28,6 +29,7 @@
 #include <linux/vmalloc.h>
 #include <linux/elf.h>
 #include <linux/proc_fs.h>
+#include <linux/security.h>
 #include <linux/seq_file.h>
 #include <linux/syscalls.h>
 #include <linux/fcntl.h>
@@ -59,6 +61,7 @@
 #include <linux/pfn.h>
 #include <linux/bsearch.h>
 #include <linux/fips.h>
+#include <uapi/linux/module.h>
 #include "module-internal.h"
 
 #define CREATE_TRACE_POINTS
@@ -372,9 +375,6 @@ static bool check_symbol(const struct symsearch *syms,
 			printk(KERN_WARNING "Symbol %s is being used "
 			       "by a non-GPL module, which will not "
 			       "be allowed in the future\n", fsa->name);
-			printk(KERN_WARNING "Please see the file "
-			       "Documentation/feature-removal-schedule.txt "
-			       "in the kernel source tree for more details.\n");
 		}
 	}
 
@@ -2425,18 +2425,17 @@ static inline void kmemleak_load_module(const struct module *mod,
 #endif
 
 #ifdef CONFIG_MODULE_SIG
-static int module_sig_check(struct load_info *info,
-			    const void *mod, unsigned long *_len)
+static int module_sig_check(struct load_info *info)
 {
 	int err = -ENOKEY;
-	unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
-	unsigned long len = *_len;
+	const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
+	const void *mod = info->hdr;
 
-	if (len > markerlen &&
-	    memcmp(mod + len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
+	if (info->len > markerlen &&
+	    memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
 		/* We truncate the module to discard the signature */
-		*_len -= markerlen;
-		err = mod_verify_sig(mod, _len);
+		info->len -= markerlen;
+		err = mod_verify_sig(mod, &info->len);
 	}
 
 	if (!err) {
@@ -2454,59 +2453,107 @@ static int module_sig_check(struct load_info *info,
 	return err;
 }
 #else /* !CONFIG_MODULE_SIG */
-static int module_sig_check(struct load_info *info,
-			    void *mod, unsigned long *len)
+static int module_sig_check(struct load_info *info)
 {
 	return 0;
 }
 #endif /* !CONFIG_MODULE_SIG */
 
-/* Sets info->hdr, info->len and info->sig_ok. */
-static int copy_and_check(struct load_info *info,
-			  const void __user *umod, unsigned long len,
-			  const char __user *uargs)
+/* Sanity checks against invalid binaries, wrong arch, weird elf version. */
+static int elf_header_check(struct load_info *info)
+{
+	if (info->len < sizeof(*(info->hdr)))
+		return -ENOEXEC;
+
+	if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0
+	    || info->hdr->e_type != ET_REL
+	    || !elf_check_arch(info->hdr)
+	    || info->hdr->e_shentsize != sizeof(Elf_Shdr))
+		return -ENOEXEC;
+
+	if (info->hdr->e_shoff >= info->len
+	    || (info->hdr->e_shnum * sizeof(Elf_Shdr) >
+		info->len - info->hdr->e_shoff))
+		return -ENOEXEC;
+
+	return 0;
+}
+
+/* Sets info->hdr and info->len. */
+static int copy_module_from_user(const void __user *umod, unsigned long len,
+				  struct load_info *info)
 {
 	int err;
-	Elf_Ehdr *hdr;
 
-	if (len < sizeof(*hdr))
+	info->len = len;
+	if (info->len < sizeof(*(info->hdr)))
 		return -ENOEXEC;
 
+	err = security_kernel_module_from_file(NULL);
+	if (err)
+		return err;
+
 	/* Suck in entire file: we'll want most of it. */
-	if ((hdr = vmalloc(len)) == NULL)
+	info->hdr = vmalloc(info->len);
+	if (!info->hdr)
 		return -ENOMEM;
 
-	if (copy_from_user(hdr, umod, len) != 0) {
-		err = -EFAULT;
-		goto free_hdr;
+	if (copy_from_user(info->hdr, umod, info->len) != 0) {
+		vfree(info->hdr);
+		return -EFAULT;
 	}
 
-	err = module_sig_check(info, hdr, &len);
+	return 0;
+}
+
+/* Sets info->hdr and info->len. */
+static int copy_module_from_fd(int fd, struct load_info *info)
+{
+	struct file *file;
+	int err;
+	struct kstat stat;
+	loff_t pos;
+	ssize_t bytes = 0;
+
+	file = fget(fd);
+	if (!file)
+		return -ENOEXEC;
+
+	err = security_kernel_module_from_file(file);
 	if (err)
-		goto free_hdr;
+		goto out;
 
-	/* Sanity checks against insmoding binaries or wrong arch,
-	   weird elf version */
-	if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0
-	    || hdr->e_type != ET_REL
-	    || !elf_check_arch(hdr)
-	    || hdr->e_shentsize != sizeof(Elf_Shdr)) {
-		err = -ENOEXEC;
-		goto free_hdr;
-	}
+	err = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat);
+	if (err)
+		goto out;
 
-	if (hdr->e_shoff >= len ||
-	    hdr->e_shnum * sizeof(Elf_Shdr) > len - hdr->e_shoff) {
-		err = -ENOEXEC;
-		goto free_hdr;
+	if (stat.size > INT_MAX) {
+		err = -EFBIG;
+		goto out;
+	}
+	info->hdr = vmalloc(stat.size);
+	if (!info->hdr) {
+		err = -ENOMEM;
+		goto out;
 	}
 
-	info->hdr = hdr;
-	info->len = len;
-	return 0;
+	pos = 0;
+	while (pos < stat.size) {
+		bytes = kernel_read(file, pos, (char *)(info->hdr) + pos,
+				    stat.size - pos);
+		if (bytes < 0) {
+			vfree(info->hdr);
+			err = bytes;
+			goto out;
+		}
+		if (bytes == 0)
+			break;
+		pos += bytes;
+	}
+	info->len = pos;
 
-free_hdr:
-	vfree(hdr);
+out:
+	fput(file);
 	return err;
 }
 
@@ -2515,7 +2562,7 @@ static void free_copy(struct load_info *info)
 	vfree(info->hdr);
 }
 
-static int rewrite_section_headers(struct load_info *info)
+static int rewrite_section_headers(struct load_info *info, int flags)
 {
 	unsigned int i;
 
@@ -2543,7 +2590,10 @@ static int rewrite_section_headers(struct load_info *info)
 	}
 
 	/* Track but don't keep modinfo and version sections. */
-	info->index.vers = find_sec(info, "__versions");
+	if (flags & MODULE_INIT_IGNORE_MODVERSIONS)
+		info->index.vers = 0; /* Pretend no __versions section! */
+	else
+		info->index.vers = find_sec(info, "__versions");
 	info->index.info = find_sec(info, ".modinfo");
 	info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC;
 	info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC;
@@ -2558,7 +2608,7 @@ static int rewrite_section_headers(struct load_info *info)
  * Return the temporary module pointer (we'll replace it with the final
  * one when we move the module sections around).
  */
-static struct module *setup_load_info(struct load_info *info)
+static struct module *setup_load_info(struct load_info *info, int flags)
 {
 	unsigned int i;
 	int err;
@@ -2569,7 +2619,7 @@ static struct module *setup_load_info(struct load_info *info)
 	info->secstrings = (void *)info->hdr
 		+ info->sechdrs[info->hdr->e_shstrndx].sh_offset;
 
-	err = rewrite_section_headers(info);
+	err = rewrite_section_headers(info, flags);
 	if (err)
 		return ERR_PTR(err);
 
@@ -2607,11 +2657,14 @@ static struct module *setup_load_info(struct load_info *info)
 	return mod;
 }
 
-static int check_modinfo(struct module *mod, struct load_info *info)
+static int check_modinfo(struct module *mod, struct load_info *info, int flags)
 {
 	const char *modmagic = get_modinfo(info, "vermagic");
 	int err;
 
+	if (flags & MODULE_INIT_IGNORE_VERMAGIC)
+		modmagic = NULL;
+
 	/* This is allowed: modprobe --force will invalidate it. */
 	if (!modmagic) {
 		err = try_to_force_load(mod, "bad vermagic");
@@ -2847,18 +2900,18 @@ int __weak module_frob_arch_sections(Elf_Ehdr *hdr,
 	return 0;
 }
 
-static struct module *layout_and_allocate(struct load_info *info)
+static struct module *layout_and_allocate(struct load_info *info, int flags)
 {
 	/* Module within temporary copy. */
 	struct module *mod;
 	Elf_Shdr *pcpusec;
 	int err;
 
-	mod = setup_load_info(info);
+	mod = setup_load_info(info, flags);
 	if (IS_ERR(mod))
 		return mod;
 
-	err = check_modinfo(mod, info);
+	err = check_modinfo(mod, info, flags);
 	if (err)
 		return ERR_PTR(err);
 
@@ -2945,33 +2998,124 @@ static bool finished_loading(const char *name)
 	return ret;
 }
 
+/* Call module constructors. */
+static void do_mod_ctors(struct module *mod)
+{
+#ifdef CONFIG_CONSTRUCTORS
+	unsigned long i;
+
+	for (i = 0; i < mod->num_ctors; i++)
+		mod->ctors[i]();
+#endif
+}
+
+/* This is where the real work happens */
+static int do_init_module(struct module *mod)
+{
+	int ret = 0;
+
+	blocking_notifier_call_chain(&module_notify_list,
+			MODULE_STATE_COMING, mod);
+
+	/* Set RO and NX regions for core */
+	set_section_ro_nx(mod->module_core,
+				mod->core_text_size,
+				mod->core_ro_size,
+				mod->core_size);
+
+	/* Set RO and NX regions for init */
+	set_section_ro_nx(mod->module_init,
+				mod->init_text_size,
+				mod->init_ro_size,
+				mod->init_size);
+
+	do_mod_ctors(mod);
+	/* Start the module */
+	if (mod->init != NULL)
+		ret = do_one_initcall(mod->init);
+	if (ret < 0) {
+		/* Init routine failed: abort.  Try to protect us from
+                   buggy refcounters. */
+		mod->state = MODULE_STATE_GOING;
+		synchronize_sched();
+		module_put(mod);
+		blocking_notifier_call_chain(&module_notify_list,
+					     MODULE_STATE_GOING, mod);
+		free_module(mod);
+		wake_up_all(&module_wq);
+		return ret;
+	}
+	if (ret > 0) {
+		printk(KERN_WARNING
+"%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n"
+"%s: loading module anyway...\n",
+		       __func__, mod->name, ret,
+		       __func__);
+		dump_stack();
+	}
+
+	/* Now it's a first class citizen! */
+	mod->state = MODULE_STATE_LIVE;
+	blocking_notifier_call_chain(&module_notify_list,
+				     MODULE_STATE_LIVE, mod);
+
+	/* We need to finish all async code before the module init sequence is done */
+	async_synchronize_full();
+
+	mutex_lock(&module_mutex);
+	/* Drop initial reference. */
+	module_put(mod);
+	trim_init_extable(mod);
+#ifdef CONFIG_KALLSYMS
+	mod->num_symtab = mod->core_num_syms;
+	mod->symtab = mod->core_symtab;
+	mod->strtab = mod->core_strtab;
+#endif
+	unset_module_init_ro_nx(mod);
+	module_free(mod, mod->module_init);
+	mod->module_init = NULL;
+	mod->init_size = 0;
+	mod->init_ro_size = 0;
+	mod->init_text_size = 0;
+	mutex_unlock(&module_mutex);
+	wake_up_all(&module_wq);
+
+	return 0;
+}
+
+static int may_init_module(void)
+{
+	if (!capable(CAP_SYS_MODULE) || modules_disabled)
+		return -EPERM;
+
+	return 0;
+}
+
 /* Allocate and load the module: note that size of section 0 is always
    zero, and we rely on this for optional sections. */
-static struct module *load_module(void __user *umod,
-				  unsigned long len,
-				  const char __user *uargs)
+static int load_module(struct load_info *info, const char __user *uargs,
+		       int flags)
 {
-	struct load_info info = { NULL, };
 	struct module *mod, *old;
 	long err;
 
-	pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n",
-	       umod, len, uargs);
+	err = module_sig_check(info);
+	if (err)
+		goto free_copy;
 
-	/* Copy in the blobs from userspace, check they are vaguely sane. */
-	err = copy_and_check(&info, umod, len, uargs);
+	err = elf_header_check(info);
 	if (err)
-		return ERR_PTR(err);
+		goto free_copy;
 
 	/* Figure out module layout, and allocate all the memory. */
-	mod = layout_and_allocate(&info);
+	mod = layout_and_allocate(info, flags);
 	if (IS_ERR(mod)) {
 		err = PTR_ERR(mod);
 		goto free_copy;
 	}
 
 #ifdef CONFIG_MODULE_SIG
-	mod->sig_ok = info.sig_ok;
+	mod->sig_ok = info->sig_ok;
 	if (!mod->sig_ok)
 		add_taint_module(mod, TAINT_FORCED_MODULE);
 #endif
@@ -2983,25 +3127,25 @@ static struct module *load_module(void __user *umod,
 
 	/* Now we've got everything in the final locations, we can
 	 * find optional sections. */
-	find_module_sections(mod, &info);
+	find_module_sections(mod, info);
 
 	err = check_module_license_and_versions(mod);
 	if (err)
 		goto free_unload;
 
 	/* Set up MODINFO_ATTR fields */
-	setup_modinfo(mod, &info);
+	setup_modinfo(mod, info);
 
 	/* Fix up syms, so that st_value is a pointer to location. */
-	err = simplify_symbols(mod, &info);
+	err = simplify_symbols(mod, info);
 	if (err < 0)
 		goto free_modinfo;
 
-	err = apply_relocations(mod, &info);
+	err = apply_relocations(mod, info);
 	if (err < 0)
 		goto free_modinfo;
 
-	err = post_relocation(mod, &info);
+	err = post_relocation(mod, info);
 	if (err < 0)
 		goto free_modinfo;
 
@@ -3041,14 +3185,14 @@ again:
 	}
 
 	/* This has to be done once we're sure module name is unique. */
-	dynamic_debug_setup(info.debug, info.num_debug);
+	dynamic_debug_setup(info->debug, info->num_debug);
 
 	/* Find duplicate symbols */
 	err = verify_export_symbols(mod);
 	if (err < 0)
 		goto ddebug;
 
-	module_bug_finalize(info.hdr, info.sechdrs, mod);
+	module_bug_finalize(info->hdr, info->sechdrs, mod);
 	list_add_rcu(&mod->list, &modules);
 	mutex_unlock(&module_mutex);
 
@@ -3059,16 +3203,17 @@ again:
 		goto unlink;
 
 	/* Link in to syfs. */
-	err = mod_sysfs_setup(mod, &info, mod->kp, mod->num_kp);
+	err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp);
 	if (err < 0)
 		goto unlink;
 
 	/* Get rid of temporary copy. */
-	free_copy(&info);
+	free_copy(info);
 
 	/* Done! */
 	trace_module_load(mod);
-	return mod;
+
+	return do_init_module(mod);
 
  unlink:
 	mutex_lock(&module_mutex);
@@ -3077,7 +3222,7 @@ again:
 	module_bug_cleanup(mod);
 	wake_up_all(&module_wq);
  ddebug:
-	dynamic_debug_remove(info.debug);
+	dynamic_debug_remove(info->debug);
  unlock:
 	mutex_unlock(&module_mutex);
 	synchronize_sched();
@@ -3089,106 +3234,52 @@ again:
  free_unload:
 	module_unload_free(mod);
  free_module:
-	module_deallocate(mod, &info);
+	module_deallocate(mod, info);
  free_copy:
-	free_copy(&info);
-	return ERR_PTR(err);
-}
-
-/* Call module constructors. */
-static void do_mod_ctors(struct module *mod)
-{
-#ifdef CONFIG_CONSTRUCTORS
-	unsigned long i;
-
-	for (i = 0; i < mod->num_ctors; i++)
-		mod->ctors[i]();
-#endif
+	free_copy(info);
+	return err;
 }
 
-/* This is where the real work happens */
 SYSCALL_DEFINE3(init_module, void __user *, umod,
 		unsigned long, len, const char __user *, uargs)
 {
-	struct module *mod;
-	int ret = 0;
+	int err;
+	struct load_info info = { };
 
-	/* Must have permission */
-	if (!capable(CAP_SYS_MODULE) || modules_disabled)
-		return -EPERM;
+	err = may_init_module();
+	if (err)
+		return err;
 
-	/* Do all the hard work */
-	mod = load_module(umod, len, uargs);
-	if (IS_ERR(mod))
-		return PTR_ERR(mod);
+	pr_debug("init_module: umod=%p, len=%lu, uargs=%p\n",
+	       umod, len, uargs);
 
-	blocking_notifier_call_chain(&module_notify_list,
-			MODULE_STATE_COMING, mod);
+	err = copy_module_from_user(umod, len, &info);
+	if (err)
+		return err;
 
-	/* Set RO and NX regions for core */
-	set_section_ro_nx(mod->module_core,
-				mod->core_text_size,
-				mod->core_ro_size,
-				mod->core_size);
+	return load_module(&info, uargs, 0);
+}
 
-	/* Set RO and NX regions for init */
-	set_section_ro_nx(mod->module_init,
-				mod->init_text_size,
-				mod->init_ro_size,
-				mod->init_size);
+SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
+{
+	int err;
+	struct load_info info = { };
 
-	do_mod_ctors(mod);
-	/* Start the module */
-	if (mod->init != NULL)
-		ret = do_one_initcall(mod->init);
-	if (ret < 0) {
-		/* Init routine failed: abort.  Try to protect us from
-                   buggy refcounters. */
-		mod->state = MODULE_STATE_GOING;
-		synchronize_sched();
-		module_put(mod);
-		blocking_notifier_call_chain(&module_notify_list,
-					     MODULE_STATE_GOING, mod);
-		free_module(mod);
-		wake_up_all(&module_wq);
-		return ret;
-	}
-	if (ret > 0) {
-		printk(KERN_WARNING
-"%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n"
-"%s: loading module anyway...\n",
-		       __func__, mod->name, ret,
-		       __func__);
-		dump_stack();
-	}
+	err = may_init_module();
+	if (err)
+		return err;
 
-	/* Now it's a first class citizen! */
-	mod->state = MODULE_STATE_LIVE;
-	blocking_notifier_call_chain(&module_notify_list,
-				     MODULE_STATE_LIVE, mod);
+	pr_debug("finit_module: fd=%d, uargs=%p, flags=%i\n", fd, uargs, flags);
 
-	/* We need to finish all async code before the module init sequence is done */
-	async_synchronize_full();
+	if (flags & ~(MODULE_INIT_IGNORE_MODVERSIONS
+		      |MODULE_INIT_IGNORE_VERMAGIC))
+		return -EINVAL;
 
-	mutex_lock(&module_mutex);
-	/* Drop initial reference. */
-	module_put(mod);
-	trim_init_extable(mod);
-#ifdef CONFIG_KALLSYMS
-	mod->num_symtab = mod->core_num_syms;
-	mod->symtab = mod->core_symtab;
-	mod->strtab = mod->core_strtab;
-#endif
-	unset_module_init_ro_nx(mod);
-	module_free(mod, mod->module_init);
-	mod->module_init = NULL;
-	mod->init_size = 0;
-	mod->init_ro_size = 0;
-	mod->init_text_size = 0;
-	mutex_unlock(&module_mutex);
-	wake_up_all(&module_wq);
+	err = copy_module_from_fd(fd, &info);
+	if (err)
+		return err;
 
-	return 0;
+	return load_module(&info, uargs, flags);
 }
 
 static inline int within(unsigned long addr, void *start, unsigned long size)
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index b576f7f..78e2ecb 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -57,7 +57,8 @@ static inline struct nsproxy *create_nsproxy(void)
  * leave it to the caller to do proper locking and attach it to task.
  */
 static struct nsproxy *create_new_namespaces(unsigned long flags,
-			struct task_struct *tsk, struct fs_struct *new_fs)
+	struct task_struct *tsk, struct user_namespace *user_ns,
+	struct fs_struct *new_fs)
 {
 	struct nsproxy *new_nsp;
 	int err;
@@ -66,31 +67,31 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
 	if (!new_nsp)
 		return ERR_PTR(-ENOMEM);
 
-	new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, new_fs);
+	new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, user_ns, new_fs);
 	if (IS_ERR(new_nsp->mnt_ns)) {
 		err = PTR_ERR(new_nsp->mnt_ns);
 		goto out_ns;
 	}
 
-	new_nsp->uts_ns = copy_utsname(flags, tsk);
+	new_nsp->uts_ns = copy_utsname(flags, user_ns, tsk->nsproxy->uts_ns);
 	if (IS_ERR(new_nsp->uts_ns)) {
 		err = PTR_ERR(new_nsp->uts_ns);
 		goto out_uts;
 	}
 
-	new_nsp->ipc_ns = copy_ipcs(flags, tsk);
+	new_nsp->ipc_ns = copy_ipcs(flags, user_ns, tsk->nsproxy->ipc_ns);
 	if (IS_ERR(new_nsp->ipc_ns)) {
 		err = PTR_ERR(new_nsp->ipc_ns);
 		goto out_ipc;
 	}
 
-	new_nsp->pid_ns = copy_pid_ns(flags, task_active_pid_ns(tsk));
+	new_nsp->pid_ns = copy_pid_ns(flags, user_ns, tsk->nsproxy->pid_ns);
 	if (IS_ERR(new_nsp->pid_ns)) {
 		err = PTR_ERR(new_nsp->pid_ns);
 		goto out_pid;
 	}
 
-	new_nsp->net_ns = copy_net_ns(flags, tsk->nsproxy->net_ns);
+	new_nsp->net_ns = copy_net_ns(flags, user_ns, tsk->nsproxy->net_ns);
 	if (IS_ERR(new_nsp->net_ns)) {
 		err = PTR_ERR(new_nsp->net_ns);
 		goto out_net;
@@ -122,6 +123,7 @@ out_ns:
 int copy_namespaces(unsigned long flags, struct task_struct *tsk)
 {
 	struct nsproxy *old_ns = tsk->nsproxy;
+	struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns);
 	struct nsproxy *new_ns;
 	int err = 0;
 
@@ -134,7 +136,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
 				CLONE_NEWPID | CLONE_NEWNET)))
 		return 0;
 
-	if (!capable(CAP_SYS_ADMIN)) {
+	if (!ns_capable(user_ns, CAP_SYS_ADMIN)) {
 		err = -EPERM;
 		goto out;
 	}
@@ -151,7 +153,8 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
 		goto out;
 	}
 
-	new_ns = create_new_namespaces(flags, tsk, tsk->fs);
+	new_ns = create_new_namespaces(flags, tsk,
+				       task_cred_xxx(tsk, user_ns), tsk->fs);
 	if (IS_ERR(new_ns)) {
 		err = PTR_ERR(new_ns);
 		goto out;
@@ -183,19 +186,21 @@ void free_nsproxy(struct nsproxy *ns)
  * On success, returns the new nsproxy.
  */
 int unshare_nsproxy_namespaces(unsigned long unshare_flags,
-		struct nsproxy **new_nsp, struct fs_struct *new_fs)
+	struct nsproxy **new_nsp, struct cred *new_cred, struct fs_struct *new_fs)
 {
+	struct user_namespace *user_ns;
 	int err = 0;
 
 	if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
-			       CLONE_NEWNET)))
+			       CLONE_NEWNET | CLONE_NEWPID)))
 		return 0;
 
-	if (!capable(CAP_SYS_ADMIN))
+	user_ns = new_cred ? new_cred->user_ns : current_user_ns();
+	if (!ns_capable(user_ns, CAP_SYS_ADMIN))
 		return -EPERM;
 
-	*new_nsp = create_new_namespaces(unshare_flags, current,
-				new_fs ? new_fs : current->fs);
+	*new_nsp = create_new_namespaces(unshare_flags, current, user_ns,
+					 new_fs ? new_fs : current->fs);
 	if (IS_ERR(*new_nsp)) {
 		err = PTR_ERR(*new_nsp);
 		goto out;
@@ -241,9 +246,6 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype)
 	struct file *file;
 	int err;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
 	file = proc_ns_fget(fd);
 	if (IS_ERR(file))
 		return PTR_ERR(file);
@@ -254,7 +256,7 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype)
 	if (nstype && (ops->type != nstype))
 		goto out;
 
-	new_nsproxy = create_new_namespaces(0, tsk, tsk->fs);
+	new_nsproxy = create_new_namespaces(0, tsk, current_user_ns(), tsk->fs);
 	if (IS_ERR(new_nsproxy)) {
 		err = PTR_ERR(new_nsproxy);
 		goto out;
diff --git a/kernel/pid.c b/kernel/pid.c
index aebd4f5..e8750f9 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -36,6 +36,7 @@
 #include <linux/pid_namespace.h>
 #include <linux/init_task.h>
 #include <linux/syscalls.h>
+#include <linux/proc_fs.h>
 
 #define pid_hashfn(nr, ns)	\
 	hash_long((unsigned long)nr + (unsigned long)ns, pidhash_shift)
@@ -78,24 +79,11 @@ struct pid_namespace init_pid_ns = {
 	.last_pid = 0,
 	.level = 0,
 	.child_reaper = &init_task,
+	.user_ns = &init_user_ns,
+	.proc_inum = PROC_PID_INIT_INO,
 };
 EXPORT_SYMBOL_GPL(init_pid_ns);
 
-int is_container_init(struct task_struct *tsk)
-{
-	int ret = 0;
-	struct pid *pid;
-
-	rcu_read_lock();
-	pid = task_pid(tsk);
-	if (pid != NULL && pid->numbers[pid->level].nr == 1)
-		ret = 1;
-	rcu_read_unlock();
-
-	return ret;
-}
-EXPORT_SYMBOL(is_container_init);
-
 /*
  * Note: disable interrupts while the pidmap_lock is held as an
  * interrupt might come in and do read_lock(&tasklist_lock).
@@ -269,8 +257,24 @@ void free_pid(struct pid *pid)
 	unsigned long flags;
 
 	spin_lock_irqsave(&pidmap_lock, flags);
-	for (i = 0; i <= pid->level; i++)
-		hlist_del_rcu(&pid->numbers[i].pid_chain);
+	for (i = 0; i <= pid->level; i++) {
+		struct upid *upid = pid->numbers + i;
+		struct pid_namespace *ns = upid->ns;
+		hlist_del_rcu(&upid->pid_chain);
+		switch(--ns->nr_hashed) {
+		case 1:
+			/* When all that is left in the pid namespace
+			 * is the reaper wake up the reaper.  The reaper
+			 * may be sleeping in zap_pid_ns_processes().
+			 */
+			wake_up_process(ns->child_reaper);
+			break;
+		case 0:
+			ns->nr_hashed = -1;
+			schedule_work(&ns->proc_work);
+			break;
+		}
+	}
 	spin_unlock_irqrestore(&pidmap_lock, flags);
 
 	for (i = 0; i <= pid->level; i++)
@@ -292,6 +296,7 @@ struct pid *alloc_pid(struct pid_namespace *ns)
 		goto out;
 
 	tmp = ns;
+	pid->level = ns->level;
 	for (i = ns->level; i >= 0; i--) {
 		nr = alloc_pidmap(tmp);
 		if (nr < 0)
@@ -302,22 +307,32 @@ struct pid *alloc_pid(struct pid_namespace *ns)
 		tmp = tmp->parent;
 	}
 
+	if (unlikely(is_child_reaper(pid))) {
+		if (pid_ns_prepare_proc(ns))
+			goto out_free;
+	}
+
 	get_pid_ns(ns);
-	pid->level = ns->level;
 	atomic_set(&pid->count, 1);
 	for (type = 0; type < PIDTYPE_MAX; ++type)
 		INIT_HLIST_HEAD(&pid->tasks[type]);
 
 	upid = pid->numbers + ns->level;
 	spin_lock_irq(&pidmap_lock);
-	for ( ; upid >= pid->numbers; --upid)
+	if (ns->nr_hashed < 0)
+		goto out_unlock;
+	for ( ; upid >= pid->numbers; --upid) {
 		hlist_add_head_rcu(&upid->pid_chain,
 				&pid_hash[pid_hashfn(upid->nr, upid->ns)]);
+		upid->ns->nr_hashed++;
+	}
 	spin_unlock_irq(&pidmap_lock);
 
 out:
 	return pid;
 
+out_unlock:
+	spin_unlock(&pidmap_lock);
 out_free:
 	while (++i <= ns->level)
 		free_pidmap(pid->numbers + i);
@@ -344,7 +359,7 @@ EXPORT_SYMBOL_GPL(find_pid_ns);
 
 struct pid *find_vpid(int nr)
 {
-	return find_pid_ns(nr, current->nsproxy->pid_ns);
+	return find_pid_ns(nr, task_active_pid_ns(current));
 }
 EXPORT_SYMBOL_GPL(find_vpid);
 
@@ -428,7 +443,7 @@ struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns)
 
 struct task_struct *find_task_by_vpid(pid_t vnr)
 {
-	return find_task_by_pid_ns(vnr, current->nsproxy->pid_ns);
+	return find_task_by_pid_ns(vnr, task_active_pid_ns(current));
 }
 
 struct pid *get_task_pid(struct task_struct *task, enum pid_type type)
@@ -483,7 +498,7 @@ EXPORT_SYMBOL_GPL(pid_nr_ns);
 
 pid_t pid_vnr(struct pid *pid)
 {
-	return pid_nr_ns(pid, current->nsproxy->pid_ns);
+	return pid_nr_ns(pid, task_active_pid_ns(current));
 }
 EXPORT_SYMBOL_GPL(pid_vnr);
 
@@ -494,7 +509,7 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type,
 
 	rcu_read_lock();
 	if (!ns)
-		ns = current->nsproxy->pid_ns;
+		ns = task_active_pid_ns(current);
 	if (likely(pid_alive(task))) {
 		if (type != PIDTYPE_PID)
 			task = task->group_leader;
@@ -569,6 +584,7 @@ void __init pidmap_init(void)
 	/* Reserve PID 0. We never call free_pidmap(0) */
 	set_bit(0, init_pid_ns.pidmap[0].page);
 	atomic_dec(&init_pid_ns.pidmap[0].nr_free);
+	init_pid_ns.nr_hashed = 1;
 
 	init_pid_ns.pid_cachep = KMEM_CACHE(pid,
 			SLAB_HWCACHE_ALIGN | SLAB_PANIC);
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index 7b07cc0..560da0d 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -10,6 +10,7 @@
 
 #include <linux/pid.h>
 #include <linux/pid_namespace.h>
+#include <linux/user_namespace.h>
 #include <linux/syscalls.h>
 #include <linux/err.h>
 #include <linux/acct.h>
@@ -71,10 +72,17 @@ err_alloc:
 	return NULL;
 }
 
+static void proc_cleanup_work(struct work_struct *work)
+{
+	struct pid_namespace *ns = container_of(work, struct pid_namespace, proc_work);
+	pid_ns_release_proc(ns);
+}
+
 /* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */
 #define MAX_PID_NS_LEVEL 32
 
-static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_pid_ns)
+static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns,
+	struct pid_namespace *parent_pid_ns)
 {
 	struct pid_namespace *ns;
 	unsigned int level = parent_pid_ns->level + 1;
@@ -99,9 +107,15 @@ static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_p
 	if (ns->pid_cachep == NULL)
 		goto out_free_map;
 
+	err = proc_alloc_inum(&ns->proc_inum);
+	if (err)
+		goto out_free_map;
+
 	kref_init(&ns->kref);
 	ns->level = level;
 	ns->parent = get_pid_ns(parent_pid_ns);
+	ns->user_ns = get_user_ns(user_ns);
+	INIT_WORK(&ns->proc_work, proc_cleanup_work);
 
 	set_bit(0, ns->pidmap[0].page);
 	atomic_set(&ns->pidmap[0].nr_free, BITS_PER_PAGE - 1);
@@ -109,14 +123,8 @@ static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_p
 	for (i = 1; i < PIDMAP_ENTRIES; i++)
 		atomic_set(&ns->pidmap[i].nr_free, BITS_PER_PAGE);
 
-	err = pid_ns_prepare_proc(ns);
-	if (err)
-		goto out_put_parent_pid_ns;
-
 	return ns;
 
-out_put_parent_pid_ns:
-	put_pid_ns(parent_pid_ns);
 out_free_map:
 	kfree(ns->pidmap[0].page);
 out_free:
@@ -129,18 +137,21 @@ static void destroy_pid_namespace(struct pid_namespace *ns)
 {
 	int i;
 
+	proc_free_inum(ns->proc_inum);
 	for (i = 0; i < PIDMAP_ENTRIES; i++)
 		kfree(ns->pidmap[i].page);
+	put_user_ns(ns->user_ns);
 	kmem_cache_free(pid_ns_cachep, ns);
 }
 
-struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old_ns)
+struct pid_namespace *copy_pid_ns(unsigned long flags,
+	struct user_namespace *user_ns, struct pid_namespace *old_ns)
 {
 	if (!(flags & CLONE_NEWPID))
 		return get_pid_ns(old_ns);
-	if (flags & (CLONE_THREAD|CLONE_PARENT))
+	if (task_active_pid_ns(current) != old_ns)
 		return ERR_PTR(-EINVAL);
-	return create_pid_namespace(old_ns);
+	return create_pid_namespace(user_ns, old_ns);
 }
 
 static void free_pid_ns(struct kref *kref)
@@ -211,22 +222,15 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
 
 	/*
 	 * sys_wait4() above can't reap the TASK_DEAD children.
-	 * Make sure they all go away, see __unhash_process().
+	 * Make sure they all go away, see free_pid().
 	 */
 	for (;;) {
-		bool need_wait = false;
-
-		read_lock(&tasklist_lock);
-		if (!list_empty(&current->children)) {
-			__set_current_state(TASK_UNINTERRUPTIBLE);
-			need_wait = true;
-		}
-		read_unlock(&tasklist_lock);
-
-		if (!need_wait)
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		if (pid_ns->nr_hashed == 1)
 			break;
 		schedule();
 	}
+	__set_current_state(TASK_RUNNING);
 
 	if (pid_ns->reboot)
 		current->signal->group_exit_code = pid_ns->reboot;
@@ -239,9 +243,10 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
 static int pid_ns_ctl_handler(struct ctl_table *table, int write,
 		void __user *buffer, size_t *lenp, loff_t *ppos)
 {
+	struct pid_namespace *pid_ns = task_active_pid_ns(current);
 	struct ctl_table tmp = *table;
 
-	if (write && !capable(CAP_SYS_ADMIN))
+	if (write && !ns_capable(pid_ns->user_ns, CAP_SYS_ADMIN))
 		return -EPERM;
 
 	/*
@@ -250,7 +255,7 @@ static int pid_ns_ctl_handler(struct ctl_table *table, int write,
 	 * it should synchronize its usage with external means.
 	 */
 
-	tmp.data = &current->nsproxy->pid_ns->last_pid;
+	tmp.data = &pid_ns->last_pid;
 	return proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
 }
 
@@ -299,6 +304,67 @@ int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd)
 	return 0;
 }
 
+static void *pidns_get(struct task_struct *task)
+{
+	struct pid_namespace *ns;
+
+	rcu_read_lock();
+	ns = get_pid_ns(task_active_pid_ns(task));
+	rcu_read_unlock();
+
+	return ns;
+}
+
+static void pidns_put(void *ns)
+{
+	put_pid_ns(ns);
+}
+
+static int pidns_install(struct nsproxy *nsproxy, void *ns)
+{
+	struct pid_namespace *active = task_active_pid_ns(current);
+	struct pid_namespace *ancestor, *new = ns;
+
+	if (!ns_capable(new->user_ns, CAP_SYS_ADMIN))
+		return -EPERM;
+
+	/*
+	 * Only allow entering the current active pid namespace
+	 * or a child of the current active pid namespace.
+	 *
+	 * This is required for fork to return a usable pid value and
+	 * this maintains the property that processes and their
+	 * children can not escape their current pid namespace.
+	 */
+	if (new->level < active->level)
+		return -EINVAL;
+
+	ancestor = new;
+	while (ancestor->level > active->level)
+		ancestor = ancestor->parent;
+	if (ancestor != active)
+		return -EINVAL;
+
+	put_pid_ns(nsproxy->pid_ns);
+	nsproxy->pid_ns = get_pid_ns(new);
+	return 0;
+}
+
+static unsigned int pidns_inum(void *ns)
+{
+	struct pid_namespace *pid_ns = ns;
+	return pid_ns->proc_inum;
+}
+
+const struct proc_ns_operations pidns_operations = {
+	.name		= "pid",
+	.type		= CLONE_NEWPID,
+	.get		= pidns_get,
+	.put		= pidns_put,
+	.install	= pidns_install,
+	.inum		= pidns_inum,
+};
+
 static __init int pid_namespaces_init(void)
 {
 	pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC);
diff --git a/kernel/power/main.c b/kernel/power/main.c
index f458238..1c16f91 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -59,7 +59,7 @@ static ssize_t pm_async_store(struct kobject *kobj, struct kobj_attribute *attr,
 {
 	unsigned long val;
 
-	if (strict_strtoul(buf, 10, &val))
+	if (kstrtoul(buf, 10, &val))
 		return -EINVAL;
 
 	if (val > 1)
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 87da817..d5a258b 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -48,18 +48,7 @@ static int try_to_freeze_tasks(bool user_only)
 			if (p == current || !freeze_task(p))
 				continue;
 
-			/*
-			 * Now that we've done set_freeze_flag, don't
-			 * perturb a task in TASK_STOPPED or TASK_TRACED.
-			 * It is "frozen enough".  If the task does wake
-			 * up, it will immediately call try_to_freeze.
-			 *
-			 * Because freeze_task() goes through p's scheduler lock, it's
-			 * guaranteed that TASK_STOPPED/TRACED -> TASK_RUNNING
-			 * transition can't race with task state testing here.
-			 */
-			if (!task_is_stopped_or_traced(p) &&
-			    !freezer_should_skip(p))
+			if (!freezer_should_skip(p))
 				todo++;
 		} while_each_thread(g, p);
 		read_unlock(&tasklist_lock);
diff --git a/kernel/power/qos.c b/kernel/power/qos.c
index 846bd42..9322ff7 100644
--- a/kernel/power/qos.c
+++ b/kernel/power/qos.c
@@ -213,6 +213,69 @@ int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node,
 }
 
 /**
+ * pm_qos_flags_remove_req - Remove device PM QoS flags request.
+ * @pqf: Device PM QoS flags set to remove the request from.
+ * @req: Request to remove from the set.
+ */
+static void pm_qos_flags_remove_req(struct pm_qos_flags *pqf,
+				    struct pm_qos_flags_request *req)
+{
+	s32 val = 0;
+
+	list_del(&req->node);
+	list_for_each_entry(req, &pqf->list, node)
+		val |= req->flags;
+
+	pqf->effective_flags = val;
+}
+
+/**
+ * pm_qos_update_flags - Update a set of PM QoS flags.
+ * @pqf: Set of flags to update.
+ * @req: Request to add to the set, to modify, or to remove from the set.
+ * @action: Action to take on the set.
+ * @val: Value of the request to add or modify.
+ *
+ * Update the given set of PM QoS flags and call notifiers if the aggregate
+ * value has changed.  Returns 1 if the aggregate constraint value has changed,
+ * 0 otherwise.
+ */
+bool pm_qos_update_flags(struct pm_qos_flags *pqf,
+			 struct pm_qos_flags_request *req,
+			 enum pm_qos_req_action action, s32 val)
+{
+	unsigned long irqflags;
+	s32 prev_value, curr_value;
+
+	spin_lock_irqsave(&pm_qos_lock, irqflags);
+
+	prev_value = list_empty(&pqf->list) ? 0 : pqf->effective_flags;
+
+	switch (action) {
+	case PM_QOS_REMOVE_REQ:
+		pm_qos_flags_remove_req(pqf, req);
+		break;
+	case PM_QOS_UPDATE_REQ:
+		pm_qos_flags_remove_req(pqf, req);
+	case PM_QOS_ADD_REQ:
+		req->flags = val;
+		INIT_LIST_HEAD(&req->node);
+		list_add_tail(&req->node, &pqf->list);
+		pqf->effective_flags |= val;
+		break;
+	default:
+		/* no action */
+		;
+	}
+
+	curr_value = list_empty(&pqf->list) ? 0 : pqf->effective_flags;
+
+	spin_unlock_irqrestore(&pm_qos_lock, irqflags);
+
+	return prev_value != curr_value;
+}
+
+/**
  * pm_qos_request - returns current system wide qos expectation
  * @pm_qos_class: identification of which qos value is requested
  *
@@ -500,7 +563,7 @@ static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
 		} else {
 			ascii_value[count] = '\0';
 		}
-		ret = strict_strtoul(ascii_value, 16, &ulval);
+		ret = kstrtoul(ascii_value, 16, &ulval);
 		if (ret) {
 			pr_debug("%s, 0x%lx, 0x%x\n", ascii_value, ulval, ret);
 			return -EINVAL;
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 3c9d764..7c33ed2 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -126,7 +126,7 @@ static int swsusp_extents_insert(unsigned long swap_offset)
 
 	/* Figure out where to put the new node */
 	while (*new) {
-		ext = container_of(*new, struct swsusp_extent, node);
+		ext = rb_entry(*new, struct swsusp_extent, node);
 		parent = *new;
 		if (swap_offset < ext->start) {
 			/* Try to merge */
diff --git a/kernel/printk.c b/kernel/printk.c
index 2d607f4..19c0d7b 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -87,6 +87,12 @@ static DEFINE_SEMAPHORE(console_sem);
 struct console *console_drivers;
 EXPORT_SYMBOL_GPL(console_drivers);
 
+#ifdef CONFIG_LOCKDEP
+static struct lockdep_map console_lock_dep_map = {
+	.name = "console_lock"
+};
+#endif
+
 /*
  * This is used for debugging the mess that is the VT code by
  * keeping track if we have the console semaphore held. It's
@@ -741,6 +747,21 @@ void __init setup_log_buf(int early)
 		free, (free * 100) / __LOG_BUF_LEN);
 }
 
+static bool __read_mostly ignore_loglevel;
+
+static int __init ignore_loglevel_setup(char *str)
+{
+	ignore_loglevel = 1;
+	printk(KERN_INFO "debug: ignoring loglevel setting.\n");
+
+	return 0;
+}
+
+early_param("ignore_loglevel", ignore_loglevel_setup);
+module_param(ignore_loglevel, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ignore_loglevel, "ignore loglevel setting, to"
+	"print all kernel messages to the console.");
+
 #ifdef CONFIG_BOOT_PRINTK_DELAY
 
 static int boot_delay; /* msecs delay after each printk during bootup */
@@ -764,13 +785,15 @@ static int __init boot_delay_setup(char *str)
 }
 __setup("boot_delay=", boot_delay_setup);
 
-static void boot_delay_msec(void)
+static void boot_delay_msec(int level)
 {
 	unsigned long long k;
 	unsigned long timeout;
 
-	if (boot_delay == 0 || system_state != SYSTEM_BOOTING)
+	if ((boot_delay == 0 || system_state != SYSTEM_BOOTING)
+		|| (level >= console_loglevel && !ignore_loglevel)) {
 		return;
+	}
 
 	k = (unsigned long long)loops_per_msec * boot_delay;
 
@@ -789,7 +812,7 @@ static void boot_delay_msec(void)
 	}
 }
 #else
-static inline void boot_delay_msec(void)
+static inline void boot_delay_msec(int level)
 {
 }
 #endif
@@ -1232,21 +1255,6 @@ SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
 	return do_syslog(type, buf, len, SYSLOG_FROM_CALL);
 }
 
-static bool __read_mostly ignore_loglevel;
-
-static int __init ignore_loglevel_setup(char *str)
-{
-	ignore_loglevel = 1;
-	printk(KERN_INFO "debug: ignoring loglevel setting.\n");
-
-	return 0;
-}
-
-early_param("ignore_loglevel", ignore_loglevel_setup);
-module_param(ignore_loglevel, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(ignore_loglevel, "ignore loglevel setting, to"
-	"print all kernel messages to the console.");
-
 /*
  * Call the console drivers, asking them to write out
  * log_buf[start] to log_buf[end - 1].
@@ -1492,7 +1500,7 @@ asmlinkage int vprintk_emit(int facility, int level,
 	int this_cpu;
 	int printed_len = 0;
 
-	boot_delay_msec();
+	boot_delay_msec(level);
 	printk_delay();
 
 	/* This stops the holder of console_sem just where we want him */
@@ -1908,12 +1916,14 @@ static int __cpuinit console_cpu_notify(struct notifier_block *self,
  */
 void console_lock(void)
 {
-	BUG_ON(in_interrupt());
+	might_sleep();
+
 	down(&console_sem);
 	if (console_suspended)
 		return;
 	console_locked = 1;
 	console_may_schedule = 1;
+	mutex_acquire(&console_lock_dep_map, 0, 0, _RET_IP_);
 }
 EXPORT_SYMBOL(console_lock);
 
@@ -1935,6 +1945,7 @@ int console_trylock(void)
 	}
 	console_locked = 1;
 	console_may_schedule = 0;
+	mutex_acquire(&console_lock_dep_map, 0, 1, _RET_IP_);
 	return 1;
 }
 EXPORT_SYMBOL(console_trylock);
@@ -2095,6 +2106,7 @@ skip:
 		local_irq_restore(flags);
 	}
 	console_locked = 0;
+	mutex_release(&console_lock_dep_map, 1, _RET_IP_);
 
 	/* Release the exclusive_console once it is used */
 	if (unlikely(exclusive_console))
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 1f5e55d..1599157 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -215,8 +215,12 @@ ok:
 	smp_rmb();
 	if (task->mm)
 		dumpable = get_dumpable(task->mm);
-	if (!dumpable  && !ptrace_has_cap(task_user_ns(task), mode))
+	rcu_read_lock();
+	if (!dumpable && !ptrace_has_cap(__task_cred(task)->user_ns, mode)) {
+		rcu_read_unlock();
 		return -EPERM;
+	}
+	rcu_read_unlock();
 
 	return security_ptrace_access_check(task, mode);
 }
@@ -280,8 +284,10 @@ static int ptrace_attach(struct task_struct *task, long request,
 
 	if (seize)
 		flags |= PT_SEIZED;
-	if (ns_capable(task_user_ns(task), CAP_SYS_PTRACE))
+	rcu_read_lock();
+	if (ns_capable(__task_cred(task)->user_ns, CAP_SYS_PTRACE))
 		flags |= PT_PTRACE_CAP;
+	rcu_read_unlock();
 	task->ptrace = flags;
 
 	__ptrace_link(task, current);
@@ -457,6 +463,9 @@ void exit_ptrace(struct task_struct *tracer)
 		return;
 
 	list_for_each_entry_safe(p, n, &tracer->ptraced, ptrace_entry) {
+		if (unlikely(p->ptrace & PT_EXITKILL))
+			send_sig_info(SIGKILL, SEND_SIG_FORCED, p);
+
 		if (__ptrace_detach(tracer, p))
 			list_add(&p->ptrace_entry, &ptrace_dead);
 	}
diff --git a/kernel/rcu.h b/kernel/rcu.h
index 8ba99cd..20dfba5 100644
--- a/kernel/rcu.h
+++ b/kernel/rcu.h
@@ -109,4 +109,6 @@ static inline bool __rcu_reclaim(char *rn, struct rcu_head *head)
 	}
 }
 
+extern int rcu_expedited;
+
 #endif /* __LINUX_RCU_H */
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index 29ca1c6..a2cf761 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -46,12 +46,15 @@
 #include <linux/export.h>
 #include <linux/hardirq.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/rcu.h>
 
 #include "rcu.h"
 
+module_param(rcu_expedited, int, 0);
+
 #ifdef CONFIG_PREEMPT_RCU
 
 /*
diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c
index e4c6a59..e7dce58 100644
--- a/kernel/rcutiny.c
+++ b/kernel/rcutiny.c
@@ -195,7 +195,7 @@ EXPORT_SYMBOL(rcu_is_cpu_idle);
  */
 int rcu_is_cpu_rrupt_from_idle(void)
 {
-	return rcu_dynticks_nesting <= 0;
+	return rcu_dynticks_nesting <= 1;
 }
 
 /*
diff --git a/kernel/rcutiny_plugin.h b/kernel/rcutiny_plugin.h
index 3d01902..f85016a 100644
--- a/kernel/rcutiny_plugin.h
+++ b/kernel/rcutiny_plugin.h
@@ -706,7 +706,10 @@ void synchronize_rcu(void)
 		return;
 
 	/* Once we get past the fastpath checks, same code as rcu_barrier(). */
-	rcu_barrier();
+	if (rcu_expedited)
+		synchronize_rcu_expedited();
+	else
+		rcu_barrier();
 }
 EXPORT_SYMBOL_GPL(synchronize_rcu);
 
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index aaa7b9f..31dea01 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -339,7 +339,6 @@ rcu_stutter_wait(char *title)
 
 struct rcu_torture_ops {
 	void (*init)(void);
-	void (*cleanup)(void);
 	int (*readlock)(void);
 	void (*read_delay)(struct rcu_random_state *rrsp);
 	void (*readunlock)(int idx);
@@ -431,7 +430,6 @@ static void rcu_torture_deferred_free(struct rcu_torture *p)
 
 static struct rcu_torture_ops rcu_ops = {
 	.init		= NULL,
-	.cleanup	= NULL,
 	.readlock	= rcu_torture_read_lock,
 	.read_delay	= rcu_read_delay,
 	.readunlock	= rcu_torture_read_unlock,
@@ -475,7 +473,6 @@ static void rcu_sync_torture_init(void)
 
 static struct rcu_torture_ops rcu_sync_ops = {
 	.init		= rcu_sync_torture_init,
-	.cleanup	= NULL,
 	.readlock	= rcu_torture_read_lock,
 	.read_delay	= rcu_read_delay,
 	.readunlock	= rcu_torture_read_unlock,
@@ -493,7 +490,6 @@ static struct rcu_torture_ops rcu_sync_ops = {
 
 static struct rcu_torture_ops rcu_expedited_ops = {
 	.init		= rcu_sync_torture_init,
-	.cleanup	= NULL,
 	.readlock	= rcu_torture_read_lock,
 	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
 	.readunlock	= rcu_torture_read_unlock,
@@ -536,7 +532,6 @@ static void rcu_bh_torture_deferred_free(struct rcu_torture *p)
 
 static struct rcu_torture_ops rcu_bh_ops = {
 	.init		= NULL,
-	.cleanup	= NULL,
 	.readlock	= rcu_bh_torture_read_lock,
 	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
 	.readunlock	= rcu_bh_torture_read_unlock,
@@ -553,7 +548,6 @@ static struct rcu_torture_ops rcu_bh_ops = {
 
 static struct rcu_torture_ops rcu_bh_sync_ops = {
 	.init		= rcu_sync_torture_init,
-	.cleanup	= NULL,
 	.readlock	= rcu_bh_torture_read_lock,
 	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
 	.readunlock	= rcu_bh_torture_read_unlock,
@@ -570,7 +564,6 @@ static struct rcu_torture_ops rcu_bh_sync_ops = {
 
 static struct rcu_torture_ops rcu_bh_expedited_ops = {
 	.init		= rcu_sync_torture_init,
-	.cleanup	= NULL,
 	.readlock	= rcu_bh_torture_read_lock,
 	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
 	.readunlock	= rcu_bh_torture_read_unlock,
@@ -589,19 +582,7 @@ static struct rcu_torture_ops rcu_bh_expedited_ops = {
  * Definitions for srcu torture testing.
  */
 
-static struct srcu_struct srcu_ctl;
-
-static void srcu_torture_init(void)
-{
-	init_srcu_struct(&srcu_ctl);
-	rcu_sync_torture_init();
-}
-
-static void srcu_torture_cleanup(void)
-{
-	synchronize_srcu(&srcu_ctl);
-	cleanup_srcu_struct(&srcu_ctl);
-}
+DEFINE_STATIC_SRCU(srcu_ctl);
 
 static int srcu_torture_read_lock(void) __acquires(&srcu_ctl)
 {
@@ -672,8 +653,7 @@ static int srcu_torture_stats(char *page)
 }
 
 static struct rcu_torture_ops srcu_ops = {
-	.init		= srcu_torture_init,
-	.cleanup	= srcu_torture_cleanup,
+	.init		= rcu_sync_torture_init,
 	.readlock	= srcu_torture_read_lock,
 	.read_delay	= srcu_read_delay,
 	.readunlock	= srcu_torture_read_unlock,
@@ -687,8 +667,7 @@ static struct rcu_torture_ops srcu_ops = {
 };
 
 static struct rcu_torture_ops srcu_sync_ops = {
-	.init		= srcu_torture_init,
-	.cleanup	= srcu_torture_cleanup,
+	.init		= rcu_sync_torture_init,
 	.readlock	= srcu_torture_read_lock,
 	.read_delay	= srcu_read_delay,
 	.readunlock	= srcu_torture_read_unlock,
@@ -712,8 +691,7 @@ static void srcu_torture_read_unlock_raw(int idx) __releases(&srcu_ctl)
 }
 
 static struct rcu_torture_ops srcu_raw_ops = {
-	.init		= srcu_torture_init,
-	.cleanup	= srcu_torture_cleanup,
+	.init		= rcu_sync_torture_init,
 	.readlock	= srcu_torture_read_lock_raw,
 	.read_delay	= srcu_read_delay,
 	.readunlock	= srcu_torture_read_unlock_raw,
@@ -727,8 +705,7 @@ static struct rcu_torture_ops srcu_raw_ops = {
 };
 
 static struct rcu_torture_ops srcu_raw_sync_ops = {
-	.init		= srcu_torture_init,
-	.cleanup	= srcu_torture_cleanup,
+	.init		= rcu_sync_torture_init,
 	.readlock	= srcu_torture_read_lock_raw,
 	.read_delay	= srcu_read_delay,
 	.readunlock	= srcu_torture_read_unlock_raw,
@@ -747,8 +724,7 @@ static void srcu_torture_synchronize_expedited(void)
 }
 
 static struct rcu_torture_ops srcu_expedited_ops = {
-	.init		= srcu_torture_init,
-	.cleanup	= srcu_torture_cleanup,
+	.init		= rcu_sync_torture_init,
 	.readlock	= srcu_torture_read_lock,
 	.read_delay	= srcu_read_delay,
 	.readunlock	= srcu_torture_read_unlock,
@@ -783,7 +759,6 @@ static void rcu_sched_torture_deferred_free(struct rcu_torture *p)
 
 static struct rcu_torture_ops sched_ops = {
 	.init		= rcu_sync_torture_init,
-	.cleanup	= NULL,
 	.readlock	= sched_torture_read_lock,
 	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
 	.readunlock	= sched_torture_read_unlock,
@@ -799,7 +774,6 @@ static struct rcu_torture_ops sched_ops = {
 
 static struct rcu_torture_ops sched_sync_ops = {
 	.init		= rcu_sync_torture_init,
-	.cleanup	= NULL,
 	.readlock	= sched_torture_read_lock,
 	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
 	.readunlock	= sched_torture_read_unlock,
@@ -814,7 +788,6 @@ static struct rcu_torture_ops sched_sync_ops = {
 
 static struct rcu_torture_ops sched_expedited_ops = {
 	.init		= rcu_sync_torture_init,
-	.cleanup	= NULL,
 	.readlock	= sched_torture_read_lock,
 	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
 	.readunlock	= sched_torture_read_unlock,
@@ -1396,12 +1369,16 @@ rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, char *tag)
 		 "fqs_duration=%d fqs_holdoff=%d fqs_stutter=%d "
 		 "test_boost=%d/%d test_boost_interval=%d "
 		 "test_boost_duration=%d shutdown_secs=%d "
+		 "stall_cpu=%d stall_cpu_holdoff=%d "
+		 "n_barrier_cbs=%d "
 		 "onoff_interval=%d onoff_holdoff=%d\n",
 		 torture_type, tag, nrealreaders, nfakewriters,
 		 stat_interval, verbose, test_no_idle_hz, shuffle_interval,
 		 stutter, irqreader, fqs_duration, fqs_holdoff, fqs_stutter,
 		 test_boost, cur_ops->can_boost,
 		 test_boost_interval, test_boost_duration, shutdown_secs,
+		 stall_cpu, stall_cpu_holdoff,
+		 n_barrier_cbs,
 		 onoff_interval, onoff_holdoff);
 }
 
@@ -1502,6 +1479,7 @@ rcu_torture_onoff(void *arg)
 	unsigned long delta;
 	int maxcpu = -1;
 	DEFINE_RCU_RANDOM(rand);
+	int ret;
 	unsigned long starttime;
 
 	VERBOSE_PRINTK_STRING("rcu_torture_onoff task started");
@@ -1522,7 +1500,13 @@ rcu_torture_onoff(void *arg)
 					 torture_type, cpu);
 			starttime = jiffies;
 			n_offline_attempts++;
-			if (cpu_down(cpu) == 0) {
+			ret = cpu_down(cpu);
+			if (ret) {
+				if (verbose)
+					pr_alert("%s" TORTURE_FLAG
+						 "rcu_torture_onoff task: offline %d failed: errno %d\n",
+						 torture_type, cpu, ret);
+			} else {
 				if (verbose)
 					pr_alert("%s" TORTURE_FLAG
 						 "rcu_torture_onoff task: offlined %d\n",
@@ -1936,8 +1920,6 @@ rcu_torture_cleanup(void)
 
 	rcu_torture_stats_print();  /* -After- the stats thread is stopped! */
 
-	if (cur_ops->cleanup)
-		cur_ops->cleanup();
 	if (atomic_read(&n_rcu_torture_error) || n_rcu_torture_barrier_error)
 		rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");
 	else if (n_online_successes != n_online_attempts ||
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 74df86b..e441b77 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -68,9 +68,9 @@ static struct lock_class_key rcu_fqs_class[RCU_NUM_LVLS];
 	.level = { &sname##_state.node[0] }, \
 	.call = cr, \
 	.fqs_state = RCU_GP_IDLE, \
-	.gpnum = -300, \
-	.completed = -300, \
-	.onofflock = __RAW_SPIN_LOCK_UNLOCKED(&sname##_state.onofflock), \
+	.gpnum = 0UL - 300UL, \
+	.completed = 0UL - 300UL, \
+	.orphan_lock = __RAW_SPIN_LOCK_UNLOCKED(&sname##_state.orphan_lock), \
 	.orphan_nxttail = &sname##_state.orphan_nxtlist, \
 	.orphan_donetail = &sname##_state.orphan_donelist, \
 	.barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \
@@ -207,18 +207,15 @@ EXPORT_SYMBOL_GPL(rcu_note_context_switch);
 DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = {
 	.dynticks_nesting = DYNTICK_TASK_EXIT_IDLE,
 	.dynticks = ATOMIC_INIT(1),
-#if defined(CONFIG_RCU_USER_QS) && !defined(CONFIG_RCU_USER_QS_FORCE)
-	.ignore_user_qs = true,
-#endif
 };
 
-static int blimit = 10;		/* Maximum callbacks per rcu_do_batch. */
-static int qhimark = 10000;	/* If this many pending, ignore blimit. */
-static int qlowmark = 100;	/* Once only this many pending, use blimit. */
+static long blimit = 10;	/* Maximum callbacks per rcu_do_batch. */
+static long qhimark = 10000;	/* If this many pending, ignore blimit. */
+static long qlowmark = 100;	/* Once only this many pending, use blimit. */
 
-module_param(blimit, int, 0444);
-module_param(qhimark, int, 0444);
-module_param(qlowmark, int, 0444);
+module_param(blimit, long, 0444);
+module_param(qhimark, long, 0444);
+module_param(qlowmark, long, 0444);
 
 int rcu_cpu_stall_suppress __read_mostly; /* 1 = suppress stall warnings. */
 int rcu_cpu_stall_timeout __read_mostly = CONFIG_RCU_CPU_STALL_TIMEOUT;
@@ -303,7 +300,8 @@ EXPORT_SYMBOL_GPL(rcu_sched_force_quiescent_state);
 static int
 cpu_has_callbacks_ready_to_invoke(struct rcu_data *rdp)
 {
-	return &rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL];
+	return &rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL] &&
+	       rdp->nxttail[RCU_DONE_TAIL] != NULL;
 }
 
 /*
@@ -312,8 +310,11 @@ cpu_has_callbacks_ready_to_invoke(struct rcu_data *rdp)
 static int
 cpu_needs_another_gp(struct rcu_state *rsp, struct rcu_data *rdp)
 {
-	return *rdp->nxttail[RCU_DONE_TAIL +
-			     ACCESS_ONCE(rsp->completed) != rdp->completed] &&
+	struct rcu_head **ntp;
+
+	ntp = rdp->nxttail[RCU_DONE_TAIL +
+			   (ACCESS_ONCE(rsp->completed) != rdp->completed)];
+	return rdp->nxttail[RCU_DONE_TAIL] && ntp && *ntp &&
 	       !rcu_gp_in_progress(rsp);
 }
 
@@ -416,29 +417,7 @@ EXPORT_SYMBOL_GPL(rcu_idle_enter);
  */
 void rcu_user_enter(void)
 {
-	unsigned long flags;
-	struct rcu_dynticks *rdtp;
-
-	/*
-	 * Some contexts may involve an exception occuring in an irq,
-	 * leading to that nesting:
-	 * rcu_irq_enter() rcu_user_exit() rcu_user_exit() rcu_irq_exit()
-	 * This would mess up the dyntick_nesting count though. And rcu_irq_*()
-	 * helpers are enough to protect RCU uses inside the exception. So
-	 * just return immediately if we detect we are in an IRQ.
-	 */
-	if (in_interrupt())
-		return;
-
-	WARN_ON_ONCE(!current->mm);
-
-	local_irq_save(flags);
-	rdtp = &__get_cpu_var(rcu_dynticks);
-	if (!rdtp->ignore_user_qs && !rdtp->in_user) {
-		rdtp->in_user = true;
-		rcu_eqs_enter(true);
-	}
-	local_irq_restore(flags);
+	rcu_eqs_enter(1);
 }
 
 /**
@@ -575,27 +554,7 @@ EXPORT_SYMBOL_GPL(rcu_idle_exit);
  */
 void rcu_user_exit(void)
 {
-	unsigned long flags;
-	struct rcu_dynticks *rdtp;
-
-	/*
-	 * Some contexts may involve an exception occuring in an irq,
-	 * leading to that nesting:
-	 * rcu_irq_enter() rcu_user_exit() rcu_user_exit() rcu_irq_exit()
-	 * This would mess up the dyntick_nesting count though. And rcu_irq_*()
-	 * helpers are enough to protect RCU uses inside the exception. So
-	 * just return immediately if we detect we are in an IRQ.
-	 */
-	if (in_interrupt())
-		return;
-
-	local_irq_save(flags);
-	rdtp = &__get_cpu_var(rcu_dynticks);
-	if (rdtp->in_user) {
-		rdtp->in_user = false;
-		rcu_eqs_exit(true);
-	}
-	local_irq_restore(flags);
+	rcu_eqs_exit(1);
 }
 
 /**
@@ -718,21 +677,6 @@ int rcu_is_cpu_idle(void)
 }
 EXPORT_SYMBOL(rcu_is_cpu_idle);
 
-#ifdef CONFIG_RCU_USER_QS
-void rcu_user_hooks_switch(struct task_struct *prev,
-			   struct task_struct *next)
-{
-	struct rcu_dynticks *rdtp;
-
-	/* Interrupts are disabled in context switch */
-	rdtp = &__get_cpu_var(rcu_dynticks);
-	if (!rdtp->ignore_user_qs) {
-		clear_tsk_thread_flag(prev, TIF_NOHZ);
-		set_tsk_thread_flag(next, TIF_NOHZ);
-	}
-}
-#endif /* #ifdef CONFIG_RCU_USER_QS */
-
 #if defined(CONFIG_PROVE_RCU) && defined(CONFIG_HOTPLUG_CPU)
 
 /*
@@ -873,6 +817,29 @@ static void record_gp_stall_check_time(struct rcu_state *rsp)
 	rsp->jiffies_stall = jiffies + jiffies_till_stall_check();
 }
 
+/*
+ * Dump stacks of all tasks running on stalled CPUs.  This is a fallback
+ * for architectures that do not implement trigger_all_cpu_backtrace().
+ * The NMI-triggered stack traces are more accurate because they are
+ * printed by the target CPU.
+ */
+static void rcu_dump_cpu_stacks(struct rcu_state *rsp)
+{
+	int cpu;
+	unsigned long flags;
+	struct rcu_node *rnp;
+
+	rcu_for_each_leaf_node(rsp, rnp) {
+		raw_spin_lock_irqsave(&rnp->lock, flags);
+		if (rnp->qsmask != 0) {
+			for (cpu = 0; cpu <= rnp->grphi - rnp->grplo; cpu++)
+				if (rnp->qsmask & (1UL << cpu))
+					dump_cpu_task(rnp->grplo + cpu);
+		}
+		raw_spin_unlock_irqrestore(&rnp->lock, flags);
+	}
+}
+
 static void print_other_cpu_stall(struct rcu_state *rsp)
 {
 	int cpu;
@@ -880,6 +847,7 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
 	unsigned long flags;
 	int ndetected = 0;
 	struct rcu_node *rnp = rcu_get_root(rsp);
+	long totqlen = 0;
 
 	/* Only let one CPU complain about others per time interval. */
 
@@ -924,12 +892,15 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
 	raw_spin_unlock_irqrestore(&rnp->lock, flags);
 
 	print_cpu_stall_info_end();
-	printk(KERN_CONT "(detected by %d, t=%ld jiffies)\n",
-	       smp_processor_id(), (long)(jiffies - rsp->gp_start));
+	for_each_possible_cpu(cpu)
+		totqlen += per_cpu_ptr(rsp->rda, cpu)->qlen;
+	pr_cont("(detected by %d, t=%ld jiffies, g=%lu, c=%lu, q=%lu)\n",
+	       smp_processor_id(), (long)(jiffies - rsp->gp_start),
+	       rsp->gpnum, rsp->completed, totqlen);
 	if (ndetected == 0)
 		printk(KERN_ERR "INFO: Stall ended before state dump start\n");
 	else if (!trigger_all_cpu_backtrace())
-		dump_stack();
+		rcu_dump_cpu_stacks(rsp);
 
 	/* Complain about tasks blocking the grace period. */
 
@@ -940,8 +911,10 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
 
 static void print_cpu_stall(struct rcu_state *rsp)
 {
+	int cpu;
 	unsigned long flags;
 	struct rcu_node *rnp = rcu_get_root(rsp);
+	long totqlen = 0;
 
 	/*
 	 * OK, time to rat on ourselves...
@@ -952,7 +925,10 @@ static void print_cpu_stall(struct rcu_state *rsp)
 	print_cpu_stall_info_begin();
 	print_cpu_stall_info(rsp, smp_processor_id());
 	print_cpu_stall_info_end();
-	printk(KERN_CONT " (t=%lu jiffies)\n", jiffies - rsp->gp_start);
+	for_each_possible_cpu(cpu)
+		totqlen += per_cpu_ptr(rsp->rda, cpu)->qlen;
+	pr_cont(" (t=%lu jiffies g=%lu c=%lu q=%lu)\n",
+		jiffies - rsp->gp_start, rsp->gpnum, rsp->completed, totqlen);
 	if (!trigger_all_cpu_backtrace())
 		dump_stack();
 
@@ -1091,6 +1067,7 @@ static void init_callback_list(struct rcu_data *rdp)
 	rdp->nxtlist = NULL;
 	for (i = 0; i < RCU_NEXT_SIZE; i++)
 		rdp->nxttail[i] = &rdp->nxtlist;
+	init_nocb_callback_list(rdp);
 }
 
 /*
@@ -1404,15 +1381,37 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
 	    !cpu_needs_another_gp(rsp, rdp)) {
 		/*
 		 * Either we have not yet spawned the grace-period
-		 * task or this CPU does not need another grace period.
+		 * task, this CPU does not need another grace period,
+		 * or a grace period is already in progress.
 		 * Either way, don't start a new grace period.
 		 */
 		raw_spin_unlock_irqrestore(&rnp->lock, flags);
 		return;
 	}
 
+	/*
+	 * Because there is no grace period in progress right now,
+	 * any callbacks we have up to this point will be satisfied
+	 * by the next grace period.  So promote all callbacks to be
+	 * handled after the end of the next grace period.  If the
+	 * CPU is not yet aware of the end of the previous grace period,
+	 * we need to allow for the callback advancement that will
+	 * occur when it does become aware.  Deadlock prevents us from
+	 * making it aware at this point: We cannot acquire a leaf
+	 * rcu_node ->lock while holding the root rcu_node ->lock.
+	 */
+	rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
+	if (rdp->completed == rsp->completed)
+		rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
+
 	rsp->gp_flags = RCU_GP_FLAG_INIT;
-	raw_spin_unlock_irqrestore(&rnp->lock, flags);
+	raw_spin_unlock(&rnp->lock); /* Interrupts remain disabled. */
+
+	/* Ensure that CPU is aware of completion of last grace period. */
+	rcu_process_gp_end(rsp, rdp);
+	local_irq_restore(flags);
+
+	/* Wake up rcu_gp_kthread() to start the grace period. */
 	wake_up(&rsp->gp_wq);
 }
 
@@ -1573,16 +1572,20 @@ rcu_check_quiescent_state(struct rcu_state *rsp, struct rcu_data *rdp)
 /*
  * Send the specified CPU's RCU callbacks to the orphanage.  The
  * specified CPU must be offline, and the caller must hold the
- * ->onofflock.
+ * ->orphan_lock.
  */
 static void
 rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
 			  struct rcu_node *rnp, struct rcu_data *rdp)
 {
+	/* No-CBs CPUs do not have orphanable callbacks. */
+	if (is_nocb_cpu(rdp->cpu))
+		return;
+
 	/*
 	 * Orphan the callbacks.  First adjust the counts.  This is safe
-	 * because ->onofflock excludes _rcu_barrier()'s adoption of
-	 * the callbacks, thus no memory barrier is required.
+	 * because _rcu_barrier() excludes CPU-hotplug operations, so it
+	 * cannot be running now.  Thus no memory barrier is required.
 	 */
 	if (rdp->nxtlist != NULL) {
 		rsp->qlen_lazy += rdp->qlen_lazy;
@@ -1623,13 +1626,17 @@ rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
 
 /*
  * Adopt the RCU callbacks from the specified rcu_state structure's
- * orphanage.  The caller must hold the ->onofflock.
+ * orphanage.  The caller must hold the ->orphan_lock.
  */
 static void rcu_adopt_orphan_cbs(struct rcu_state *rsp)
 {
 	int i;
 	struct rcu_data *rdp = __this_cpu_ptr(rsp->rda);
 
+	/* No-CBs CPUs are handled specially. */
+	if (rcu_nocb_adopt_orphan_cbs(rsp, rdp))
+		return;
+
 	/* Do the accounting first. */
 	rdp->qlen_lazy += rsp->qlen_lazy;
 	rdp->qlen += rsp->qlen;
@@ -1702,7 +1709,7 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
 
 	/* Exclude any attempts to start a new grace period. */
 	mutex_lock(&rsp->onoff_mutex);
-	raw_spin_lock_irqsave(&rsp->onofflock, flags);
+	raw_spin_lock_irqsave(&rsp->orphan_lock, flags);
 
 	/* Orphan the dead CPU's callbacks, and adopt them if appropriate. */
 	rcu_send_cbs_to_orphanage(cpu, rsp, rnp, rdp);
@@ -1729,10 +1736,10 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
 	/*
 	 * We still hold the leaf rcu_node structure lock here, and
 	 * irqs are still disabled.  The reason for this subterfuge is
-	 * because invoking rcu_report_unblock_qs_rnp() with ->onofflock
+	 * because invoking rcu_report_unblock_qs_rnp() with ->orphan_lock
 	 * held leads to deadlock.
 	 */
-	raw_spin_unlock(&rsp->onofflock); /* irqs remain disabled. */
+	raw_spin_unlock(&rsp->orphan_lock); /* irqs remain disabled. */
 	rnp = rdp->mynode;
 	if (need_report & RCU_OFL_TASKS_NORM_GP)
 		rcu_report_unblock_qs_rnp(rnp, flags);
@@ -1769,7 +1776,8 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
 {
 	unsigned long flags;
 	struct rcu_head *next, *list, **tail;
-	int bl, count, count_lazy, i;
+	long bl, count, count_lazy;
+	int i;
 
 	/* If no callbacks are ready, just return.*/
 	if (!cpu_has_callbacks_ready_to_invoke(rdp)) {
@@ -2107,9 +2115,15 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp,
 	}
 }
 
+/*
+ * Helper function for call_rcu() and friends.  The cpu argument will
+ * normally be -1, indicating "currently running CPU".  It may specify
+ * a CPU only if that CPU is a no-CBs CPU.  Currently, only _rcu_barrier()
+ * is expected to specify a CPU.
+ */
 static void
 __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
-	   struct rcu_state *rsp, bool lazy)
+	   struct rcu_state *rsp, int cpu, bool lazy)
 {
 	unsigned long flags;
 	struct rcu_data *rdp;
@@ -2129,9 +2143,14 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
 	rdp = this_cpu_ptr(rsp->rda);
 
 	/* Add the callback to our list. */
-	if (unlikely(rdp->nxttail[RCU_NEXT_TAIL] == NULL)) {
+	if (unlikely(rdp->nxttail[RCU_NEXT_TAIL] == NULL) || cpu != -1) {
+		int offline;
+
+		if (cpu != -1)
+			rdp = per_cpu_ptr(rsp->rda, cpu);
+		offline = !__call_rcu_nocb(rdp, head, lazy);
+		WARN_ON_ONCE(offline);
 		/* _call_rcu() is illegal on offline CPU; leak the callback. */
-		WARN_ON_ONCE(1);
 		local_irq_restore(flags);
 		return;
 	}
@@ -2160,7 +2179,7 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
  */
 void call_rcu_sched(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
 {
-	__call_rcu(head, func, &rcu_sched_state, 0);
+	__call_rcu(head, func, &rcu_sched_state, -1, 0);
 }
 EXPORT_SYMBOL_GPL(call_rcu_sched);
 
@@ -2169,7 +2188,7 @@ EXPORT_SYMBOL_GPL(call_rcu_sched);
  */
 void call_rcu_bh(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
 {
-	__call_rcu(head, func, &rcu_bh_state, 0);
+	__call_rcu(head, func, &rcu_bh_state, -1, 0);
 }
 EXPORT_SYMBOL_GPL(call_rcu_bh);
 
@@ -2205,10 +2224,28 @@ static inline int rcu_blocking_is_gp(void)
  * rcu_read_lock_sched().
  *
  * This means that all preempt_disable code sequences, including NMI and
- * hardware-interrupt handlers, in progress on entry will have completed
- * before this primitive returns.  However, this does not guarantee that
- * softirq handlers will have completed, since in some kernels, these
- * handlers can run in process context, and can block.
+ * non-threaded hardware-interrupt handlers, in progress on entry will
+ * have completed before this primitive returns.  However, this does not
+ * guarantee that softirq handlers will have completed, since in some
+ * kernels, these handlers can run in process context, and can block.
+ *
+ * Note that this guarantee implies further memory-ordering guarantees.
+ * On systems with more than one CPU, when synchronize_sched() returns,
+ * each CPU is guaranteed to have executed a full memory barrier since the
+ * end of its last RCU-sched read-side critical section whose beginning
+ * preceded the call to synchronize_sched().  In addition, each CPU having
+ * an RCU read-side critical section that extends beyond the return from
+ * synchronize_sched() is guaranteed to have executed a full memory barrier
+ * after the beginning of synchronize_sched() and before the beginning of
+ * that RCU read-side critical section.  Note that these guarantees include
+ * CPUs that are offline, idle, or executing in user mode, as well as CPUs
+ * that are executing in the kernel.
+ *
+ * Furthermore, if CPU A invoked synchronize_sched(), which returned
+ * to its caller on CPU B, then both CPU A and CPU B are guaranteed
+ * to have executed a full memory barrier during the execution of
+ * synchronize_sched() -- even if CPU A and CPU B are the same CPU (but
+ * again only if the system has more than one CPU).
  *
  * This primitive provides the guarantees made by the (now removed)
  * synchronize_kernel() API.  In contrast, synchronize_rcu() only
@@ -2224,7 +2261,10 @@ void synchronize_sched(void)
 			   "Illegal synchronize_sched() in RCU-sched read-side critical section");
 	if (rcu_blocking_is_gp())
 		return;
-	wait_rcu_gp(call_rcu_sched);
+	if (rcu_expedited)
+		synchronize_sched_expedited();
+	else
+		wait_rcu_gp(call_rcu_sched);
 }
 EXPORT_SYMBOL_GPL(synchronize_sched);
 
@@ -2236,6 +2276,9 @@ EXPORT_SYMBOL_GPL(synchronize_sched);
  * read-side critical sections have completed.  RCU read-side critical
  * sections are delimited by rcu_read_lock_bh() and rcu_read_unlock_bh(),
  * and may be nested.
+ *
+ * See the description of synchronize_sched() for more detailed information
+ * on memory ordering guarantees.
  */
 void synchronize_rcu_bh(void)
 {
@@ -2245,13 +2288,13 @@ void synchronize_rcu_bh(void)
 			   "Illegal synchronize_rcu_bh() in RCU-bh read-side critical section");
 	if (rcu_blocking_is_gp())
 		return;
-	wait_rcu_gp(call_rcu_bh);
+	if (rcu_expedited)
+		synchronize_rcu_bh_expedited();
+	else
+		wait_rcu_gp(call_rcu_bh);
 }
 EXPORT_SYMBOL_GPL(synchronize_rcu_bh);
 
-static atomic_t sync_sched_expedited_started = ATOMIC_INIT(0);
-static atomic_t sync_sched_expedited_done = ATOMIC_INIT(0);
-
 static int synchronize_sched_expedited_cpu_stop(void *data)
 {
 	/*
@@ -2308,10 +2351,32 @@ static int synchronize_sched_expedited_cpu_stop(void *data)
  */
 void synchronize_sched_expedited(void)
 {
-	int firstsnap, s, snap, trycount = 0;
+	long firstsnap, s, snap;
+	int trycount = 0;
+	struct rcu_state *rsp = &rcu_sched_state;
+
+	/*
+	 * If we are in danger of counter wrap, just do synchronize_sched().
+	 * By allowing sync_sched_expedited_started to advance no more than
+	 * ULONG_MAX/8 ahead of sync_sched_expedited_done, we are ensuring
+	 * that more than 3.5 billion CPUs would be required to force a
+	 * counter wrap on a 32-bit system.  Quite a few more CPUs would of
+	 * course be required on a 64-bit system.
+	 */
+	if (ULONG_CMP_GE((ulong)atomic_long_read(&rsp->expedited_start),
+			 (ulong)atomic_long_read(&rsp->expedited_done) +
+			 ULONG_MAX / 8)) {
+		synchronize_sched();
+		atomic_long_inc(&rsp->expedited_wrap);
+		return;
+	}
 
-	/* Note that atomic_inc_return() implies full memory barrier. */
-	firstsnap = snap = atomic_inc_return(&sync_sched_expedited_started);
+	/*
+	 * Take a ticket.  Note that atomic_inc_return() implies a
+	 * full memory barrier.
+	 */
+	snap = atomic_long_inc_return(&rsp->expedited_start);
+	firstsnap = snap;
 	get_online_cpus();
 	WARN_ON_ONCE(cpu_is_offline(raw_smp_processor_id()));
 
@@ -2323,48 +2388,65 @@ void synchronize_sched_expedited(void)
 			     synchronize_sched_expedited_cpu_stop,
 			     NULL) == -EAGAIN) {
 		put_online_cpus();
+		atomic_long_inc(&rsp->expedited_tryfail);
+
+		/* Check to see if someone else did our work for us. */
+		s = atomic_long_read(&rsp->expedited_done);
+		if (ULONG_CMP_GE((ulong)s, (ulong)firstsnap)) {
+			/* ensure test happens before caller kfree */
+			smp_mb__before_atomic_inc(); /* ^^^ */
+			atomic_long_inc(&rsp->expedited_workdone1);
+			return;
+		}
 
 		/* No joy, try again later.  Or just synchronize_sched(). */
 		if (trycount++ < 10) {
 			udelay(trycount * num_online_cpus());
 		} else {
-			synchronize_sched();
+			wait_rcu_gp(call_rcu_sched);
+			atomic_long_inc(&rsp->expedited_normal);
 			return;
 		}
 
-		/* Check to see if someone else did our work for us. */
-		s = atomic_read(&sync_sched_expedited_done);
-		if (UINT_CMP_GE((unsigned)s, (unsigned)firstsnap)) {
-			smp_mb(); /* ensure test happens before caller kfree */
+		/* Recheck to see if someone else did our work for us. */
+		s = atomic_long_read(&rsp->expedited_done);
+		if (ULONG_CMP_GE((ulong)s, (ulong)firstsnap)) {
+			/* ensure test happens before caller kfree */
+			smp_mb__before_atomic_inc(); /* ^^^ */
+			atomic_long_inc(&rsp->expedited_workdone2);
 			return;
 		}
 
 		/*
 		 * Refetching sync_sched_expedited_started allows later
-		 * callers to piggyback on our grace period.  We subtract
-		 * 1 to get the same token that the last incrementer got.
-		 * We retry after they started, so our grace period works
-		 * for them, and they started after our first try, so their
-		 * grace period works for us.
+		 * callers to piggyback on our grace period.  We retry
+		 * after they started, so our grace period works for them,
+		 * and they started after our first try, so their grace
+		 * period works for us.
 		 */
 		get_online_cpus();
-		snap = atomic_read(&sync_sched_expedited_started);
+		snap = atomic_long_read(&rsp->expedited_start);
 		smp_mb(); /* ensure read is before try_stop_cpus(). */
 	}
+	atomic_long_inc(&rsp->expedited_stoppedcpus);
 
 	/*
 	 * Everyone up to our most recent fetch is covered by our grace
 	 * period.  Update the counter, but only if our work is still
 	 * relevant -- which it won't be if someone who started later
-	 * than we did beat us to the punch.
+	 * than we did already did their update.
 	 */
 	do {
-		s = atomic_read(&sync_sched_expedited_done);
-		if (UINT_CMP_GE((unsigned)s, (unsigned)snap)) {
-			smp_mb(); /* ensure test happens before caller kfree */
+		atomic_long_inc(&rsp->expedited_done_tries);
+		s = atomic_long_read(&rsp->expedited_done);
+		if (ULONG_CMP_GE((ulong)s, (ulong)snap)) {
+			/* ensure test happens before caller kfree */
+			smp_mb__before_atomic_inc(); /* ^^^ */
+			atomic_long_inc(&rsp->expedited_done_lost);
 			break;
 		}
-	} while (atomic_cmpxchg(&sync_sched_expedited_done, s, snap) != s);
+	} while (atomic_long_cmpxchg(&rsp->expedited_done, s, snap) != s);
+	atomic_long_inc(&rsp->expedited_done_exit);
 
 	put_online_cpus();
 }
@@ -2558,9 +2640,17 @@ static void _rcu_barrier(struct rcu_state *rsp)
 	 * When that callback is invoked, we will know that all of the
 	 * corresponding CPU's preceding callbacks have been invoked.
 	 */
-	for_each_online_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
+		if (!cpu_online(cpu) && !is_nocb_cpu(cpu))
+			continue;
 		rdp = per_cpu_ptr(rsp->rda, cpu);
-		if (ACCESS_ONCE(rdp->qlen)) {
+		if (is_nocb_cpu(cpu)) {
+			_rcu_barrier_trace(rsp, "OnlineNoCB", cpu,
+					   rsp->n_barrier_done);
+			atomic_inc(&rsp->barrier_cpu_count);
+			__call_rcu(&rdp->barrier_head, rcu_barrier_callback,
+				   rsp, cpu, 0);
+		} else if (ACCESS_ONCE(rdp->qlen)) {
 			_rcu_barrier_trace(rsp, "OnlineQ", cpu,
 					   rsp->n_barrier_done);
 			smp_call_function_single(cpu, rcu_barrier_func, rsp, 1);
@@ -2634,6 +2724,7 @@ rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp)
 #endif
 	rdp->cpu = cpu;
 	rdp->rsp = rsp;
+	rcu_boot_init_nocb_percpu_data(rdp);
 	raw_spin_unlock_irqrestore(&rnp->lock, flags);
 }
 
@@ -2715,6 +2806,7 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
 	struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu);
 	struct rcu_node *rnp = rdp->mynode;
 	struct rcu_state *rsp;
+	int ret = NOTIFY_OK;
 
 	trace_rcu_utilization("Start CPU hotplug");
 	switch (action) {
@@ -2728,7 +2820,10 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
 		rcu_boost_kthread_setaffinity(rnp, -1);
 		break;
 	case CPU_DOWN_PREPARE:
-		rcu_boost_kthread_setaffinity(rnp, cpu);
+		if (nocb_cpu_expendable(cpu))
+			rcu_boost_kthread_setaffinity(rnp, cpu);
+		else
+			ret = NOTIFY_BAD;
 		break;
 	case CPU_DYING:
 	case CPU_DYING_FROZEN:
@@ -2752,7 +2847,7 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
 		break;
 	}
 	trace_rcu_utilization("End CPU hotplug");
-	return NOTIFY_OK;
+	return ret;
 }
 
 /*
@@ -2772,6 +2867,7 @@ static int __init rcu_spawn_gp_kthread(void)
 		raw_spin_lock_irqsave(&rnp->lock, flags);
 		rsp->gp_kthread = t;
 		raw_spin_unlock_irqrestore(&rnp->lock, flags);
+		rcu_spawn_nocb_kthreads(rsp);
 	}
 	return 0;
 }
@@ -2967,6 +3063,7 @@ void __init rcu_init(void)
 	rcu_init_one(&rcu_sched_state, &rcu_sched_data);
 	rcu_init_one(&rcu_bh_state, &rcu_bh_data);
 	__rcu_init_preempt();
+	rcu_init_nocb();
 	 open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
 
 	/*
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index a240f03..4b69291 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -287,6 +287,7 @@ struct rcu_data {
 	long		qlen_last_fqs_check;
 					/* qlen at last check for QS forcing */
 	unsigned long	n_cbs_invoked;	/* count of RCU cbs invoked. */
+	unsigned long	n_nocbs_invoked; /* count of no-CBs RCU cbs invoked. */
 	unsigned long   n_cbs_orphaned; /* RCU cbs orphaned by dying CPU */
 	unsigned long   n_cbs_adopted;  /* RCU cbs adopted from dying CPU */
 	unsigned long	n_force_qs_snap;
@@ -317,6 +318,18 @@ struct rcu_data {
 	struct rcu_head oom_head;
 #endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */
 
+	/* 7) Callback offloading. */
+#ifdef CONFIG_RCU_NOCB_CPU
+	struct rcu_head *nocb_head;	/* CBs waiting for kthread. */
+	struct rcu_head **nocb_tail;
+	atomic_long_t nocb_q_count;	/* # CBs waiting for kthread */
+	atomic_long_t nocb_q_count_lazy; /*  (approximate). */
+	int nocb_p_count;		/* # CBs being invoked by kthread */
+	int nocb_p_count_lazy;		/*  (approximate). */
+	wait_queue_head_t nocb_wq;	/* For nocb kthreads to sleep on. */
+	struct task_struct *nocb_kthread;
+#endif /* #ifdef CONFIG_RCU_NOCB_CPU */
+
 	int cpu;
 	struct rcu_state *rsp;
 };
@@ -369,6 +382,12 @@ struct rcu_state {
 	struct rcu_data __percpu *rda;		/* pointer of percu rcu_data. */
 	void (*call)(struct rcu_head *head,	/* call_rcu() flavor. */
 		     void (*func)(struct rcu_head *head));
+#ifdef CONFIG_RCU_NOCB_CPU
+	void (*call_remote)(struct rcu_head *head,
+		     void (*func)(struct rcu_head *head));
+						/* call_rcu() flavor, but for */
+						/*  placing on remote CPU. */
+#endif /* #ifdef CONFIG_RCU_NOCB_CPU */
 
 	/* The following fields are guarded by the root rcu_node's lock. */
 
@@ -383,9 +402,8 @@ struct rcu_state {
 
 	/* End of fields guarded by root rcu_node's lock. */
 
-	raw_spinlock_t onofflock ____cacheline_internodealigned_in_smp;
-						/* exclude on/offline and */
-						/*  starting new GP. */
+	raw_spinlock_t orphan_lock ____cacheline_internodealigned_in_smp;
+						/* Protect following fields. */
 	struct rcu_head *orphan_nxtlist;	/* Orphaned callbacks that */
 						/*  need a grace period. */
 	struct rcu_head **orphan_nxttail;	/* Tail of above. */
@@ -394,7 +412,7 @@ struct rcu_state {
 	struct rcu_head **orphan_donetail;	/* Tail of above. */
 	long qlen_lazy;				/* Number of lazy callbacks. */
 	long qlen;				/* Total number of callbacks. */
-	/* End of fields guarded by onofflock. */
+	/* End of fields guarded by orphan_lock. */
 
 	struct mutex onoff_mutex;		/* Coordinate hotplug & GPs. */
 
@@ -405,6 +423,18 @@ struct rcu_state {
 						/*  _rcu_barrier(). */
 	/* End of fields guarded by barrier_mutex. */
 
+	atomic_long_t expedited_start;		/* Starting ticket. */
+	atomic_long_t expedited_done;		/* Done ticket. */
+	atomic_long_t expedited_wrap;		/* # near-wrap incidents. */
+	atomic_long_t expedited_tryfail;	/* # acquisition failures. */
+	atomic_long_t expedited_workdone1;	/* # done by others #1. */
+	atomic_long_t expedited_workdone2;	/* # done by others #2. */
+	atomic_long_t expedited_normal;		/* # fallbacks to normal. */
+	atomic_long_t expedited_stoppedcpus;	/* # successful stop_cpus. */
+	atomic_long_t expedited_done_tries;	/* # tries to update _done. */
+	atomic_long_t expedited_done_lost;	/* # times beaten to _done. */
+	atomic_long_t expedited_done_exit;	/* # times exited _done loop. */
+
 	unsigned long jiffies_force_qs;		/* Time at which to invoke */
 						/*  force_quiescent_state(). */
 	unsigned long n_force_qs;		/* Number of calls to */
@@ -428,6 +458,8 @@ struct rcu_state {
 #define RCU_GP_FLAG_FQS  0x2	/* Need grace-period quiescent-state forcing. */
 
 extern struct list_head rcu_struct_flavors;
+
+/* Sequence through rcu_state structures for each RCU flavor. */
 #define for_each_rcu_flavor(rsp) \
 	list_for_each_entry((rsp), &rcu_struct_flavors, flavors)
 
@@ -504,5 +536,32 @@ static void print_cpu_stall_info(struct rcu_state *rsp, int cpu);
 static void print_cpu_stall_info_end(void);
 static void zero_cpu_stall_ticks(struct rcu_data *rdp);
 static void increment_cpu_stall_ticks(void);
+static bool is_nocb_cpu(int cpu);
+static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
+			    bool lazy);
+static bool rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp,
+				      struct rcu_data *rdp);
+static bool nocb_cpu_expendable(int cpu);
+static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp);
+static void rcu_spawn_nocb_kthreads(struct rcu_state *rsp);
+static void init_nocb_callback_list(struct rcu_data *rdp);
+static void __init rcu_init_nocb(void);
 
 #endif /* #ifndef RCU_TREE_NONCORE */
+
+#ifdef CONFIG_RCU_TRACE
+#ifdef CONFIG_RCU_NOCB_CPU
+/* Sum up queue lengths for tracing. */
+static inline void rcu_nocb_q_lengths(struct rcu_data *rdp, long *ql, long *qll)
+{
+	*ql = atomic_long_read(&rdp->nocb_q_count) + rdp->nocb_p_count;
+	*qll = atomic_long_read(&rdp->nocb_q_count_lazy) + rdp->nocb_p_count_lazy;
+}
+#else /* #ifdef CONFIG_RCU_NOCB_CPU */
+static inline void rcu_nocb_q_lengths(struct rcu_data *rdp, long *ql, long *qll)
+{
+	*ql = 0;
+	*qll = 0;
+}
+#endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */
+#endif /* #ifdef CONFIG_RCU_TRACE */
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index f921154..f6e5ec2 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -25,6 +25,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/gfp.h>
 #include <linux/oom.h>
 #include <linux/smpboot.h>
 
@@ -36,6 +37,14 @@
 #define RCU_BOOST_PRIO RCU_KTHREAD_PRIO
 #endif
 
+#ifdef CONFIG_RCU_NOCB_CPU
+static cpumask_var_t rcu_nocb_mask; /* CPUs to have callbacks offloaded. */
+static bool have_rcu_nocb_mask;	    /* Was rcu_nocb_mask allocated? */
+static bool rcu_nocb_poll;	    /* Offload kthread are to poll. */
+module_param(rcu_nocb_poll, bool, 0444);
+static char __initdata nocb_buf[NR_CPUS * 5];
+#endif /* #ifdef CONFIG_RCU_NOCB_CPU */
+
 /*
  * Check the RCU kernel configuration parameters and print informative
  * messages about anything out of the ordinary.  If you like #ifdef, you
@@ -76,6 +85,18 @@ static void __init rcu_bootup_announce_oddness(void)
 		printk(KERN_INFO "\tExperimental boot-time adjustment of leaf fanout to %d.\n", rcu_fanout_leaf);
 	if (nr_cpu_ids != NR_CPUS)
 		printk(KERN_INFO "\tRCU restricting CPUs from NR_CPUS=%d to nr_cpu_ids=%d.\n", NR_CPUS, nr_cpu_ids);
+#ifdef CONFIG_RCU_NOCB_CPU
+	if (have_rcu_nocb_mask) {
+		if (cpumask_test_cpu(0, rcu_nocb_mask)) {
+			cpumask_clear_cpu(0, rcu_nocb_mask);
+			pr_info("\tCPU 0: illegal no-CBs CPU (cleared).\n");
+		}
+		cpulist_scnprintf(nocb_buf, sizeof(nocb_buf), rcu_nocb_mask);
+		pr_info("\tExperimental no-CBs CPUs: %s.\n", nocb_buf);
+		if (rcu_nocb_poll)
+			pr_info("\tExperimental polled no-CBs CPUs.\n");
+	}
+#endif /* #ifdef CONFIG_RCU_NOCB_CPU */
 }
 
 #ifdef CONFIG_TREE_PREEMPT_RCU
@@ -642,7 +663,7 @@ static void rcu_preempt_do_callbacks(void)
  */
 void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
 {
-	__call_rcu(head, func, &rcu_preempt_state, 0);
+	__call_rcu(head, func, &rcu_preempt_state, -1, 0);
 }
 EXPORT_SYMBOL_GPL(call_rcu);
 
@@ -656,7 +677,7 @@ EXPORT_SYMBOL_GPL(call_rcu);
 void kfree_call_rcu(struct rcu_head *head,
 		    void (*func)(struct rcu_head *rcu))
 {
-	__call_rcu(head, func, &rcu_preempt_state, 1);
+	__call_rcu(head, func, &rcu_preempt_state, -1, 1);
 }
 EXPORT_SYMBOL_GPL(kfree_call_rcu);
 
@@ -670,6 +691,9 @@ EXPORT_SYMBOL_GPL(kfree_call_rcu);
  * concurrently with new RCU read-side critical sections that began while
  * synchronize_rcu() was waiting.  RCU read-side critical sections are
  * delimited by rcu_read_lock() and rcu_read_unlock(), and may be nested.
+ *
+ * See the description of synchronize_sched() for more detailed information
+ * on memory ordering guarantees.
  */
 void synchronize_rcu(void)
 {
@@ -679,7 +703,10 @@ void synchronize_rcu(void)
 			   "Illegal synchronize_rcu() in RCU read-side critical section");
 	if (!rcu_scheduler_active)
 		return;
-	wait_rcu_gp(call_rcu);
+	if (rcu_expedited)
+		synchronize_rcu_expedited();
+	else
+		wait_rcu_gp(call_rcu);
 }
 EXPORT_SYMBOL_GPL(synchronize_rcu);
 
@@ -757,7 +784,8 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp,
  * grace period for the specified rcu_node structure.  If there are no such
  * tasks, report it up the rcu_node hierarchy.
  *
- * Caller must hold sync_rcu_preempt_exp_mutex and rsp->onofflock.
+ * Caller must hold sync_rcu_preempt_exp_mutex and must exclude
+ * CPU hotplug operations.
  */
 static void
 sync_rcu_preempt_exp_init(struct rcu_state *rsp, struct rcu_node *rnp)
@@ -831,7 +859,7 @@ void synchronize_rcu_expedited(void)
 			udelay(trycount * num_online_cpus());
 		} else {
 			put_online_cpus();
-			synchronize_rcu();
+			wait_rcu_gp(call_rcu);
 			return;
 		}
 	}
@@ -875,6 +903,11 @@ EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
 
 /**
  * rcu_barrier - Wait until all in-flight call_rcu() callbacks complete.
+ *
+ * Note that this primitive does not necessarily wait for an RCU grace period
+ * to complete.  For example, if there are no RCU callbacks queued anywhere
+ * in the system, then rcu_barrier() is within its rights to return
+ * immediately, without waiting for anything, much less an RCU grace period.
  */
 void rcu_barrier(void)
 {
@@ -1013,7 +1046,7 @@ static void rcu_preempt_check_callbacks(int cpu)
 void kfree_call_rcu(struct rcu_head *head,
 		    void (*func)(struct rcu_head *rcu))
 {
-	__call_rcu(head, func, &rcu_sched_state, 1);
+	__call_rcu(head, func, &rcu_sched_state, -1, 1);
 }
 EXPORT_SYMBOL_GPL(kfree_call_rcu);
 
@@ -2092,3 +2125,373 @@ static void increment_cpu_stall_ticks(void)
 }
 
 #endif /* #else #ifdef CONFIG_RCU_CPU_STALL_INFO */
+
+#ifdef CONFIG_RCU_NOCB_CPU
+
+/*
+ * Offload callback processing from the boot-time-specified set of CPUs
+ * specified by rcu_nocb_mask.  For each CPU in the set, there is a
+ * kthread created that pulls the callbacks from the corresponding CPU,
+ * waits for a grace period to elapse, and invokes the callbacks.
+ * The no-CBs CPUs do a wake_up() on their kthread when they insert
+ * a callback into any empty list, unless the rcu_nocb_poll boot parameter
+ * has been specified, in which case each kthread actively polls its
+ * CPU.  (Which isn't so great for energy efficiency, but which does
+ * reduce RCU's overhead on that CPU.)
+ *
+ * This is intended to be used in conjunction with Frederic Weisbecker's
+ * adaptive-idle work, which would seriously reduce OS jitter on CPUs
+ * running CPU-bound user-mode computations.
+ *
+ * Offloading of callback processing could also in theory be used as
+ * an energy-efficiency measure because CPUs with no RCU callbacks
+ * queued are more aggressive about entering dyntick-idle mode.
+ */
+
+
+/* Parse the boot-time rcu_nocb_mask CPU list from the kernel parameters. */
+static int __init rcu_nocb_setup(char *str)
+{
+	alloc_bootmem_cpumask_var(&rcu_nocb_mask);
+	have_rcu_nocb_mask = true;
+	cpulist_parse(str, rcu_nocb_mask);
+	return 1;
+}
+__setup("rcu_nocbs=", rcu_nocb_setup);
+
+/* Is the specified CPU a no-CPUs CPU? */
+static bool is_nocb_cpu(int cpu)
+{
+	if (have_rcu_nocb_mask)
+		return cpumask_test_cpu(cpu, rcu_nocb_mask);
+	return false;
+}
+
+/*
+ * Enqueue the specified string of rcu_head structures onto the specified
+ * CPU's no-CBs lists.  The CPU is specified by rdp, the head of the
+ * string by rhp, and the tail of the string by rhtp.  The non-lazy/lazy
+ * counts are supplied by rhcount and rhcount_lazy.
+ *
+ * If warranted, also wake up the kthread servicing this CPUs queues.
+ */
+static void __call_rcu_nocb_enqueue(struct rcu_data *rdp,
+				    struct rcu_head *rhp,
+				    struct rcu_head **rhtp,
+				    int rhcount, int rhcount_lazy)
+{
+	int len;
+	struct rcu_head **old_rhpp;
+	struct task_struct *t;
+
+	/* Enqueue the callback on the nocb list and update counts. */
+	old_rhpp = xchg(&rdp->nocb_tail, rhtp);
+	ACCESS_ONCE(*old_rhpp) = rhp;
+	atomic_long_add(rhcount, &rdp->nocb_q_count);
+	atomic_long_add(rhcount_lazy, &rdp->nocb_q_count_lazy);
+
+	/* If we are not being polled and there is a kthread, awaken it ... */
+	t = ACCESS_ONCE(rdp->nocb_kthread);
+	if (rcu_nocb_poll | !t)
+		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;
+	} 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;
+	}
+	return;
+}
+
+/*
+ * This is a helper for __call_rcu(), which invokes this when the normal
+ * callback queue is inoperable.  If this is not a no-CBs CPU, this
+ * function returns failure back to __call_rcu(), which can complain
+ * appropriately.
+ *
+ * Otherwise, this function queues the callback where the corresponding
+ * "rcuo" kthread can find it.
+ */
+static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
+			    bool lazy)
+{
+
+	if (!is_nocb_cpu(rdp->cpu))
+		return 0;
+	__call_rcu_nocb_enqueue(rdp, rhp, &rhp->next, 1, lazy);
+	return 1;
+}
+
+/*
+ * Adopt orphaned callbacks on a no-CBs CPU, or return 0 if this is
+ * not a no-CBs CPU.
+ */
+static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp,
+						     struct rcu_data *rdp)
+{
+	long ql = rsp->qlen;
+	long qll = rsp->qlen_lazy;
+
+	/* If this is not a no-CBs CPU, tell the caller to do it the old way. */
+	if (!is_nocb_cpu(smp_processor_id()))
+		return 0;
+	rsp->qlen = 0;
+	rsp->qlen_lazy = 0;
+
+	/* First, enqueue the donelist, if any.  This preserves CB ordering. */
+	if (rsp->orphan_donelist != NULL) {
+		__call_rcu_nocb_enqueue(rdp, rsp->orphan_donelist,
+					rsp->orphan_donetail, ql, qll);
+		ql = qll = 0;
+		rsp->orphan_donelist = NULL;
+		rsp->orphan_donetail = &rsp->orphan_donelist;
+	}
+	if (rsp->orphan_nxtlist != NULL) {
+		__call_rcu_nocb_enqueue(rdp, rsp->orphan_nxtlist,
+					rsp->orphan_nxttail, ql, qll);
+		ql = qll = 0;
+		rsp->orphan_nxtlist = NULL;
+		rsp->orphan_nxttail = &rsp->orphan_nxtlist;
+	}
+	return 1;
+}
+
+/*
+ * There must be at least one non-no-CBs CPU in operation at any given
+ * time, because no-CBs CPUs are not capable of initiating grace periods
+ * independently.  This function therefore complains if the specified
+ * CPU is the last non-no-CBs CPU, allowing the CPU-hotplug system to
+ * avoid offlining the last such CPU.  (Recursion is a wonderful thing,
+ * but you have to have a base case!)
+ */
+static bool nocb_cpu_expendable(int cpu)
+{
+	cpumask_var_t non_nocb_cpus;
+	int ret;
+
+	/*
+	 * If there are no no-CB CPUs or if this CPU is not a no-CB CPU,
+	 * then offlining this CPU is harmless.  Let it happen.
+	 */
+	if (!have_rcu_nocb_mask || is_nocb_cpu(cpu))
+		return 1;
+
+	/* If no memory, play it safe and keep the CPU around. */
+	if (!alloc_cpumask_var(&non_nocb_cpus, GFP_NOIO))
+		return 0;
+	cpumask_andnot(non_nocb_cpus, cpu_online_mask, rcu_nocb_mask);
+	cpumask_clear_cpu(cpu, non_nocb_cpus);
+	ret = !cpumask_empty(non_nocb_cpus);
+	free_cpumask_var(non_nocb_cpus);
+	return ret;
+}
+
+/*
+ * Helper structure for remote registry of RCU callbacks.
+ * This is needed for when a no-CBs CPU needs to start a grace period.
+ * If it just invokes call_rcu(), the resulting callback will be queued,
+ * which can result in deadlock.
+ */
+struct rcu_head_remote {
+	struct rcu_head *rhp;
+	call_rcu_func_t *crf;
+	void (*func)(struct rcu_head *rhp);
+};
+
+/*
+ * Register a callback as specified by the rcu_head_remote struct.
+ * This function is intended to be invoked via smp_call_function_single().
+ */
+static void call_rcu_local(void *arg)
+{
+	struct rcu_head_remote *rhrp =
+		container_of(arg, struct rcu_head_remote, rhp);
+
+	rhrp->crf(rhrp->rhp, rhrp->func);
+}
+
+/*
+ * Set up an rcu_head_remote structure and the invoke call_rcu_local()
+ * on CPU 0 (which is guaranteed to be a non-no-CBs CPU) via
+ * smp_call_function_single().
+ */
+static void invoke_crf_remote(struct rcu_head *rhp,
+			      void (*func)(struct rcu_head *rhp),
+			      call_rcu_func_t crf)
+{
+	struct rcu_head_remote rhr;
+
+	rhr.rhp = rhp;
+	rhr.crf = crf;
+	rhr.func = func;
+	smp_call_function_single(0, call_rcu_local, &rhr, 1);
+}
+
+/*
+ * Helper functions to be passed to wait_rcu_gp(), each of which
+ * invokes invoke_crf_remote() to register a callback appropriately.
+ */
+static void __maybe_unused
+call_rcu_preempt_remote(struct rcu_head *rhp,
+			void (*func)(struct rcu_head *rhp))
+{
+	invoke_crf_remote(rhp, func, call_rcu);
+}
+static void call_rcu_bh_remote(struct rcu_head *rhp,
+			       void (*func)(struct rcu_head *rhp))
+{
+	invoke_crf_remote(rhp, func, call_rcu_bh);
+}
+static void call_rcu_sched_remote(struct rcu_head *rhp,
+				  void (*func)(struct rcu_head *rhp))
+{
+	invoke_crf_remote(rhp, func, call_rcu_sched);
+}
+
+/*
+ * Per-rcu_data kthread, but only for no-CBs CPUs.  Each kthread invokes
+ * callbacks queued by the corresponding no-CBs CPU.
+ */
+static int rcu_nocb_kthread(void *arg)
+{
+	int c, cl;
+	struct rcu_head *list;
+	struct rcu_head *next;
+	struct rcu_head **tail;
+	struct rcu_data *rdp = arg;
+
+	/* Each pass through this loop invokes one batch of callbacks */
+	for (;;) {
+		/* If not polling, wait for next batch of callbacks. */
+		if (!rcu_nocb_poll)
+			wait_event(rdp->nocb_wq, rdp->nocb_head);
+		list = ACCESS_ONCE(rdp->nocb_head);
+		if (!list) {
+			schedule_timeout_interruptible(1);
+			continue;
+		}
+
+		/*
+		 * Extract queued callbacks, update counts, and wait
+		 * for a grace period to elapse.
+		 */
+		ACCESS_ONCE(rdp->nocb_head) = NULL;
+		tail = xchg(&rdp->nocb_tail, &rdp->nocb_head);
+		c = atomic_long_xchg(&rdp->nocb_q_count, 0);
+		cl = atomic_long_xchg(&rdp->nocb_q_count_lazy, 0);
+		ACCESS_ONCE(rdp->nocb_p_count) += c;
+		ACCESS_ONCE(rdp->nocb_p_count_lazy) += cl;
+		wait_rcu_gp(rdp->rsp->call_remote);
+
+		/* Each pass through the following loop invokes a callback. */
+		trace_rcu_batch_start(rdp->rsp->name, cl, c, -1);
+		c = cl = 0;
+		while (list) {
+			next = list->next;
+			/* Wait for enqueuing to complete, if needed. */
+			while (next == NULL && &list->next != tail) {
+				schedule_timeout_interruptible(1);
+				next = list->next;
+			}
+			debug_rcu_head_unqueue(list);
+			local_bh_disable();
+			if (__rcu_reclaim(rdp->rsp->name, list))
+				cl++;
+			c++;
+			local_bh_enable();
+			list = next;
+		}
+		trace_rcu_batch_end(rdp->rsp->name, c, !!list, 0, 0, 1);
+		ACCESS_ONCE(rdp->nocb_p_count) -= c;
+		ACCESS_ONCE(rdp->nocb_p_count_lazy) -= cl;
+		rdp->n_nocbs_invoked += c;
+	}
+	return 0;
+}
+
+/* Initialize per-rcu_data variables for no-CBs CPUs. */
+static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp)
+{
+	rdp->nocb_tail = &rdp->nocb_head;
+	init_waitqueue_head(&rdp->nocb_wq);
+}
+
+/* Create a kthread for each RCU flavor for each no-CBs CPU. */
+static void __init rcu_spawn_nocb_kthreads(struct rcu_state *rsp)
+{
+	int cpu;
+	struct rcu_data *rdp;
+	struct task_struct *t;
+
+	if (rcu_nocb_mask == NULL)
+		return;
+	for_each_cpu(cpu, rcu_nocb_mask) {
+		rdp = per_cpu_ptr(rsp->rda, cpu);
+		t = kthread_run(rcu_nocb_kthread, rdp, "rcuo%d", cpu);
+		BUG_ON(IS_ERR(t));
+		ACCESS_ONCE(rdp->nocb_kthread) = t;
+	}
+}
+
+/* Prevent __call_rcu() from enqueuing callbacks on no-CBs CPUs */
+static void init_nocb_callback_list(struct rcu_data *rdp)
+{
+	if (rcu_nocb_mask == NULL ||
+	    !cpumask_test_cpu(rdp->cpu, rcu_nocb_mask))
+		return;
+	rdp->nxttail[RCU_NEXT_TAIL] = NULL;
+}
+
+/* Initialize the ->call_remote fields in the rcu_state structures. */
+static void __init rcu_init_nocb(void)
+{
+#ifdef CONFIG_PREEMPT_RCU
+	rcu_preempt_state.call_remote = call_rcu_preempt_remote;
+#endif /* #ifdef CONFIG_PREEMPT_RCU */
+	rcu_bh_state.call_remote = call_rcu_bh_remote;
+	rcu_sched_state.call_remote = call_rcu_sched_remote;
+}
+
+#else /* #ifdef CONFIG_RCU_NOCB_CPU */
+
+static bool is_nocb_cpu(int cpu)
+{
+	return false;
+}
+
+static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
+			    bool lazy)
+{
+	return 0;
+}
+
+static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp,
+						     struct rcu_data *rdp)
+{
+	return 0;
+}
+
+static bool nocb_cpu_expendable(int cpu)
+{
+	return 1;
+}
+
+static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp)
+{
+}
+
+static void __init rcu_spawn_nocb_kthreads(struct rcu_state *rsp)
+{
+}
+
+static void init_nocb_callback_list(struct rcu_data *rdp)
+{
+}
+
+static void __init rcu_init_nocb(void)
+{
+}
+
+#endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */
diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c
index 693513b..0d095dc 100644
--- a/kernel/rcutree_trace.c
+++ b/kernel/rcutree_trace.c
@@ -46,29 +46,58 @@
 #define RCU_TREE_NONCORE
 #include "rcutree.h"
 
-static int show_rcubarrier(struct seq_file *m, void *unused)
+#define ulong2long(a) (*(long *)(&(a)))
+
+static int r_open(struct inode *inode, struct file *file,
+					const struct seq_operations *op)
 {
-	struct rcu_state *rsp;
+	int ret = seq_open(file, op);
+	if (!ret) {
+		struct seq_file *m = (struct seq_file *)file->private_data;
+		m->private = inode->i_private;
+	}
+	return ret;
+}
+
+static void *r_start(struct seq_file *m, loff_t *pos)
+{
+	struct rcu_state *rsp = (struct rcu_state *)m->private;
+	*pos = cpumask_next(*pos - 1, cpu_possible_mask);
+	if ((*pos) < nr_cpu_ids)
+		return per_cpu_ptr(rsp->rda, *pos);
+	return NULL;
+}
 
-	for_each_rcu_flavor(rsp)
-		seq_printf(m, "%s: bcc: %d nbd: %lu\n",
-			   rsp->name,
-			   atomic_read(&rsp->barrier_cpu_count),
-			   rsp->n_barrier_done);
+static void *r_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return r_start(m, pos);
+}
+
+static void r_stop(struct seq_file *m, void *v)
+{
+}
+
+static int show_rcubarrier(struct seq_file *m, void *v)
+{
+	struct rcu_state *rsp = (struct rcu_state *)m->private;
+	seq_printf(m, "bcc: %d nbd: %lu\n",
+		   atomic_read(&rsp->barrier_cpu_count),
+		   rsp->n_barrier_done);
 	return 0;
 }
 
 static int rcubarrier_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, show_rcubarrier, NULL);
+	return single_open(file, show_rcubarrier, inode->i_private);
 }
 
 static const struct file_operations rcubarrier_fops = {
 	.owner = THIS_MODULE,
 	.open = rcubarrier_open,
 	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
+	.llseek = no_llseek,
+	.release = seq_release,
 };
 
 #ifdef CONFIG_RCU_BOOST
@@ -84,12 +113,14 @@ static char convert_kthread_status(unsigned int kthread_status)
 
 static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)
 {
+	long ql, qll;
+
 	if (!rdp->beenonline)
 		return;
-	seq_printf(m, "%3d%cc=%lu g=%lu pq=%d qp=%d",
+	seq_printf(m, "%3d%cc=%ld g=%ld pq=%d qp=%d",
 		   rdp->cpu,
 		   cpu_is_offline(rdp->cpu) ? '!' : ' ',
-		   rdp->completed, rdp->gpnum,
+		   ulong2long(rdp->completed), ulong2long(rdp->gpnum),
 		   rdp->passed_quiesce, rdp->qs_pending);
 	seq_printf(m, " dt=%d/%llx/%d df=%lu",
 		   atomic_read(&rdp->dynticks->dynticks),
@@ -97,8 +128,11 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)
 		   rdp->dynticks->dynticks_nmi_nesting,
 		   rdp->dynticks_fqs);
 	seq_printf(m, " of=%lu", rdp->offline_fqs);
+	rcu_nocb_q_lengths(rdp, &ql, &qll);
+	qll += rdp->qlen_lazy;
+	ql += rdp->qlen;
 	seq_printf(m, " ql=%ld/%ld qs=%c%c%c%c",
-		   rdp->qlen_lazy, rdp->qlen,
+		   qll, ql,
 		   ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] !=
 			rdp->nxttail[RCU_NEXT_TAIL]],
 		   ".R"[rdp->nxttail[RCU_WAIT_TAIL] !=
@@ -114,101 +148,67 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)
 		   per_cpu(rcu_cpu_kthread_loops, rdp->cpu) & 0xffff);
 #endif /* #ifdef CONFIG_RCU_BOOST */
 	seq_printf(m, " b=%ld", rdp->blimit);
-	seq_printf(m, " ci=%lu co=%lu ca=%lu\n",
-		   rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
+	seq_printf(m, " ci=%lu nci=%lu co=%lu ca=%lu\n",
+		   rdp->n_cbs_invoked, rdp->n_nocbs_invoked,
+		   rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
 }
 
-static int show_rcudata(struct seq_file *m, void *unused)
+static int show_rcudata(struct seq_file *m, void *v)
 {
-	int cpu;
-	struct rcu_state *rsp;
-
-	for_each_rcu_flavor(rsp) {
-		seq_printf(m, "%s:\n", rsp->name);
-		for_each_possible_cpu(cpu)
-			print_one_rcu_data(m, per_cpu_ptr(rsp->rda, cpu));
-	}
+	print_one_rcu_data(m, (struct rcu_data *)v);
 	return 0;
 }
 
+static const struct seq_operations rcudate_op = {
+	.start = r_start,
+	.next  = r_next,
+	.stop  = r_stop,
+	.show  = show_rcudata,
+};
+
 static int rcudata_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, show_rcudata, NULL);
+	return r_open(inode, file, &rcudate_op);
 }
 
 static const struct file_operations rcudata_fops = {
 	.owner = THIS_MODULE,
 	.open = rcudata_open,
 	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
+	.llseek = no_llseek,
+	.release = seq_release,
 };
 
-static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp)
-{
-	if (!rdp->beenonline)
-		return;
-	seq_printf(m, "%d,%s,%lu,%lu,%d,%d",
-		   rdp->cpu,
-		   cpu_is_offline(rdp->cpu) ? "\"N\"" : "\"Y\"",
-		   rdp->completed, rdp->gpnum,
-		   rdp->passed_quiesce, rdp->qs_pending);
-	seq_printf(m, ",%d,%llx,%d,%lu",
-		   atomic_read(&rdp->dynticks->dynticks),
-		   rdp->dynticks->dynticks_nesting,
-		   rdp->dynticks->dynticks_nmi_nesting,
-		   rdp->dynticks_fqs);
-	seq_printf(m, ",%lu", rdp->offline_fqs);
-	seq_printf(m, ",%ld,%ld,\"%c%c%c%c\"", rdp->qlen_lazy, rdp->qlen,
-		   ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] !=
-			rdp->nxttail[RCU_NEXT_TAIL]],
-		   ".R"[rdp->nxttail[RCU_WAIT_TAIL] !=
-			rdp->nxttail[RCU_NEXT_READY_TAIL]],
-		   ".W"[rdp->nxttail[RCU_DONE_TAIL] !=
-			rdp->nxttail[RCU_WAIT_TAIL]],
-		   ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]]);
-#ifdef CONFIG_RCU_BOOST
-	seq_printf(m, ",%d,\"%c\"",
-		   per_cpu(rcu_cpu_has_work, rdp->cpu),
-		   convert_kthread_status(per_cpu(rcu_cpu_kthread_status,
-					  rdp->cpu)));
-#endif /* #ifdef CONFIG_RCU_BOOST */
-	seq_printf(m, ",%ld", rdp->blimit);
-	seq_printf(m, ",%lu,%lu,%lu\n",
-		   rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
-}
-
-static int show_rcudata_csv(struct seq_file *m, void *unused)
+static int show_rcuexp(struct seq_file *m, void *v)
 {
-	int cpu;
-	struct rcu_state *rsp;
-
-	seq_puts(m, "\"CPU\",\"Online?\",\"c\",\"g\",\"pq\",\"pq\",");
-	seq_puts(m, "\"dt\",\"dt nesting\",\"dt NMI nesting\",\"df\",");
-	seq_puts(m, "\"of\",\"qll\",\"ql\",\"qs\"");
-#ifdef CONFIG_RCU_BOOST
-	seq_puts(m, "\"kt\",\"ktl\"");
-#endif /* #ifdef CONFIG_RCU_BOOST */
-	seq_puts(m, ",\"b\",\"ci\",\"co\",\"ca\"\n");
-	for_each_rcu_flavor(rsp) {
-		seq_printf(m, "\"%s:\"\n", rsp->name);
-		for_each_possible_cpu(cpu)
-			print_one_rcu_data_csv(m, per_cpu_ptr(rsp->rda, cpu));
-	}
+	struct rcu_state *rsp = (struct rcu_state *)m->private;
+
+	seq_printf(m, "s=%lu d=%lu w=%lu tf=%lu wd1=%lu wd2=%lu n=%lu sc=%lu dt=%lu dl=%lu dx=%lu\n",
+		   atomic_long_read(&rsp->expedited_start),
+		   atomic_long_read(&rsp->expedited_done),
+		   atomic_long_read(&rsp->expedited_wrap),
+		   atomic_long_read(&rsp->expedited_tryfail),
+		   atomic_long_read(&rsp->expedited_workdone1),
+		   atomic_long_read(&rsp->expedited_workdone2),
+		   atomic_long_read(&rsp->expedited_normal),
+		   atomic_long_read(&rsp->expedited_stoppedcpus),
+		   atomic_long_read(&rsp->expedited_done_tries),
+		   atomic_long_read(&rsp->expedited_done_lost),
+		   atomic_long_read(&rsp->expedited_done_exit));
 	return 0;
 }
 
-static int rcudata_csv_open(struct inode *inode, struct file *file)
+static int rcuexp_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, show_rcudata_csv, NULL);
+	return single_open(file, show_rcuexp, inode->i_private);
 }
 
-static const struct file_operations rcudata_csv_fops = {
+static const struct file_operations rcuexp_fops = {
 	.owner = THIS_MODULE,
-	.open = rcudata_csv_open,
+	.open = rcuexp_open,
 	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
+	.llseek = no_llseek,
+	.release = seq_release,
 };
 
 #ifdef CONFIG_RCU_BOOST
@@ -254,27 +254,11 @@ static const struct file_operations rcu_node_boost_fops = {
 	.owner = THIS_MODULE,
 	.open = rcu_node_boost_open,
 	.read = seq_read,
-	.llseek = seq_lseek,
+	.llseek = no_llseek,
 	.release = single_release,
 };
 
-/*
- * Create the rcuboost debugfs entry.  Standard error return.
- */
-static int rcu_boost_trace_create_file(struct dentry *rcudir)
-{
-	return !debugfs_create_file("rcuboost", 0444, rcudir, NULL,
-				    &rcu_node_boost_fops);
-}
-
-#else /* #ifdef CONFIG_RCU_BOOST */
-
-static int rcu_boost_trace_create_file(struct dentry *rcudir)
-{
-	return 0;  /* There cannot be an error if we didn't create it! */
-}
-
-#endif /* #else #ifdef CONFIG_RCU_BOOST */
+#endif /* #ifdef CONFIG_RCU_BOOST */
 
 static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
 {
@@ -283,8 +267,9 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
 	struct rcu_node *rnp;
 
 	gpnum = rsp->gpnum;
-	seq_printf(m, "%s: c=%lu g=%lu s=%d jfq=%ld j=%x ",
-		   rsp->name, rsp->completed, gpnum, rsp->fqs_state,
+	seq_printf(m, "c=%ld g=%ld s=%d jfq=%ld j=%x ",
+		   ulong2long(rsp->completed), ulong2long(gpnum),
+		   rsp->fqs_state,
 		   (long)(rsp->jiffies_force_qs - jiffies),
 		   (int)(jiffies & 0xffff));
 	seq_printf(m, "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n",
@@ -306,26 +291,24 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
 	seq_puts(m, "\n");
 }
 
-static int show_rcuhier(struct seq_file *m, void *unused)
+static int show_rcuhier(struct seq_file *m, void *v)
 {
-	struct rcu_state *rsp;
-
-	for_each_rcu_flavor(rsp)
-		print_one_rcu_state(m, rsp);
+	struct rcu_state *rsp = (struct rcu_state *)m->private;
+	print_one_rcu_state(m, rsp);
 	return 0;
 }
 
 static int rcuhier_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, show_rcuhier, NULL);
+	return single_open(file, show_rcuhier, inode->i_private);
 }
 
 static const struct file_operations rcuhier_fops = {
 	.owner = THIS_MODULE,
 	.open = rcuhier_open,
 	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
+	.llseek = no_llseek,
+	.release = seq_release,
 };
 
 static void show_one_rcugp(struct seq_file *m, struct rcu_state *rsp)
@@ -338,42 +321,42 @@ static void show_one_rcugp(struct seq_file *m, struct rcu_state *rsp)
 	struct rcu_node *rnp = &rsp->node[0];
 
 	raw_spin_lock_irqsave(&rnp->lock, flags);
-	completed = rsp->completed;
-	gpnum = rsp->gpnum;
-	if (rsp->completed == rsp->gpnum)
+	completed = ACCESS_ONCE(rsp->completed);
+	gpnum = ACCESS_ONCE(rsp->gpnum);
+	if (completed == gpnum)
 		gpage = 0;
 	else
 		gpage = jiffies - rsp->gp_start;
 	gpmax = rsp->gp_max;
 	raw_spin_unlock_irqrestore(&rnp->lock, flags);
-	seq_printf(m, "%s: completed=%ld  gpnum=%lu  age=%ld  max=%ld\n",
-		   rsp->name, completed, gpnum, gpage, gpmax);
+	seq_printf(m, "completed=%ld  gpnum=%ld  age=%ld  max=%ld\n",
+		   ulong2long(completed), ulong2long(gpnum), gpage, gpmax);
 }
 
-static int show_rcugp(struct seq_file *m, void *unused)
+static int show_rcugp(struct seq_file *m, void *v)
 {
-	struct rcu_state *rsp;
-
-	for_each_rcu_flavor(rsp)
-		show_one_rcugp(m, rsp);
+	struct rcu_state *rsp = (struct rcu_state *)m->private;
+	show_one_rcugp(m, rsp);
 	return 0;
 }
 
 static int rcugp_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, show_rcugp, NULL);
+	return single_open(file, show_rcugp, inode->i_private);
 }
 
 static const struct file_operations rcugp_fops = {
 	.owner = THIS_MODULE,
 	.open = rcugp_open,
 	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
+	.llseek = no_llseek,
+	.release = seq_release,
 };
 
 static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp)
 {
+	if (!rdp->beenonline)
+		return;
 	seq_printf(m, "%3d%cnp=%ld ",
 		   rdp->cpu,
 		   cpu_is_offline(rdp->cpu) ? '!' : ' ',
@@ -389,34 +372,30 @@ static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp)
 		   rdp->n_rp_need_nothing);
 }
 
-static int show_rcu_pending(struct seq_file *m, void *unused)
+static int show_rcu_pending(struct seq_file *m, void *v)
 {
-	int cpu;
-	struct rcu_data *rdp;
-	struct rcu_state *rsp;
-
-	for_each_rcu_flavor(rsp) {
-		seq_printf(m, "%s:\n", rsp->name);
-		for_each_possible_cpu(cpu) {
-			rdp = per_cpu_ptr(rsp->rda, cpu);
-			if (rdp->beenonline)
-				print_one_rcu_pending(m, rdp);
-		}
-	}
+	print_one_rcu_pending(m, (struct rcu_data *)v);
 	return 0;
 }
 
+static const struct seq_operations rcu_pending_op = {
+	.start = r_start,
+	.next  = r_next,
+	.stop  = r_stop,
+	.show  = show_rcu_pending,
+};
+
 static int rcu_pending_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, show_rcu_pending, NULL);
+	return r_open(inode, file, &rcu_pending_op);
 }
 
 static const struct file_operations rcu_pending_fops = {
 	.owner = THIS_MODULE,
 	.open = rcu_pending_open,
 	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
+	.llseek = no_llseek,
+	.release = seq_release,
 };
 
 static int show_rcutorture(struct seq_file *m, void *unused)
@@ -446,43 +425,58 @@ static struct dentry *rcudir;
 
 static int __init rcutree_trace_init(void)
 {
+	struct rcu_state *rsp;
 	struct dentry *retval;
+	struct dentry *rspdir;
 
 	rcudir = debugfs_create_dir("rcu", NULL);
 	if (!rcudir)
 		goto free_out;
 
-	retval = debugfs_create_file("rcubarrier", 0444, rcudir,
-						NULL, &rcubarrier_fops);
-	if (!retval)
-		goto free_out;
-
-	retval = debugfs_create_file("rcudata", 0444, rcudir,
-						NULL, &rcudata_fops);
-	if (!retval)
-		goto free_out;
-
-	retval = debugfs_create_file("rcudata.csv", 0444, rcudir,
-						NULL, &rcudata_csv_fops);
-	if (!retval)
-		goto free_out;
-
-	if (rcu_boost_trace_create_file(rcudir))
-		goto free_out;
+	for_each_rcu_flavor(rsp) {
+		rspdir = debugfs_create_dir(rsp->name, rcudir);
+		if (!rspdir)
+			goto free_out;
+
+		retval = debugfs_create_file("rcudata", 0444,
+				rspdir, rsp, &rcudata_fops);
+		if (!retval)
+			goto free_out;
+
+		retval = debugfs_create_file("rcuexp", 0444,
+				rspdir, rsp, &rcuexp_fops);
+		if (!retval)
+			goto free_out;
+
+		retval = debugfs_create_file("rcu_pending", 0444,
+				rspdir, rsp, &rcu_pending_fops);
+		if (!retval)
+			goto free_out;
+
+		retval = debugfs_create_file("rcubarrier", 0444,
+				rspdir, rsp, &rcubarrier_fops);
+		if (!retval)
+			goto free_out;
 
-	retval = debugfs_create_file("rcugp", 0444, rcudir, NULL, &rcugp_fops);
-	if (!retval)
-		goto free_out;
+#ifdef CONFIG_RCU_BOOST
+		if (rsp == &rcu_preempt_state) {
+			retval = debugfs_create_file("rcuboost", 0444,
+				rspdir, NULL, &rcu_node_boost_fops);
+			if (!retval)
+				goto free_out;
+		}
+#endif
 
-	retval = debugfs_create_file("rcuhier", 0444, rcudir,
-						NULL, &rcuhier_fops);
-	if (!retval)
-		goto free_out;
+		retval = debugfs_create_file("rcugp", 0444,
+				rspdir, rsp, &rcugp_fops);
+		if (!retval)
+			goto free_out;
 
-	retval = debugfs_create_file("rcu_pending", 0444, rcudir,
-						NULL, &rcu_pending_fops);
-	if (!retval)
-		goto free_out;
+		retval = debugfs_create_file("rcuhier", 0444,
+				rspdir, rsp, &rcuhier_fops);
+		if (!retval)
+			goto free_out;
+	}
 
 	retval = debugfs_create_file("rcutorture", 0444, rcudir,
 						NULL, &rcutorture_fops);
diff --git a/kernel/res_counter.c b/kernel/res_counter.c
index ad581aa..ff55247 100644
--- a/kernel/res_counter.c
+++ b/kernel/res_counter.c
@@ -86,33 +86,39 @@ int res_counter_charge_nofail(struct res_counter *counter, unsigned long val,
 	return __res_counter_charge(counter, val, limit_fail_at, true);
 }
 
-void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val)
+u64 res_counter_uncharge_locked(struct res_counter *counter, unsigned long val)
 {
 	if (WARN_ON(counter->usage < val))
 		val = counter->usage;
 
 	counter->usage -= val;
+	return counter->usage;
 }
 
-void res_counter_uncharge_until(struct res_counter *counter,
-				struct res_counter *top,
-				unsigned long val)
+u64 res_counter_uncharge_until(struct res_counter *counter,
+			       struct res_counter *top,
+			       unsigned long val)
 {
 	unsigned long flags;
 	struct res_counter *c;
+	u64 ret = 0;
 
 	local_irq_save(flags);
 	for (c = counter; c != top; c = c->parent) {
+		u64 r;
 		spin_lock(&c->lock);
-		res_counter_uncharge_locked(c, val);
+		r = res_counter_uncharge_locked(c, val);
+		if (c == counter)
+			ret = r;
 		spin_unlock(&c->lock);
 	}
 	local_irq_restore(flags);
+	return ret;
 }
 
-void res_counter_uncharge(struct res_counter *counter, unsigned long val)
+u64 res_counter_uncharge(struct res_counter *counter, unsigned long val)
 {
-	res_counter_uncharge_until(counter, NULL, val);
+	return res_counter_uncharge_until(counter, NULL, val);
 }
 
 static inline unsigned long long *
@@ -192,25 +198,3 @@ int res_counter_memparse_write_strategy(const char *buf,
 	*res = PAGE_ALIGN(*res);
 	return 0;
 }
-
-int res_counter_write(struct res_counter *counter, int member,
-		      const char *buf, write_strategy_fn write_strategy)
-{
-	char *end;
-	unsigned long flags;
-	unsigned long long tmp, *val;
-
-	if (write_strategy) {
-		if (write_strategy(buf, &tmp))
-			return -EINVAL;
-	} else {
-		tmp = simple_strtoull(buf, &end, 10);
-		if (*end != '\0')
-			return -EINVAL;
-	}
-	spin_lock_irqsave(&counter->lock, flags);
-	val = res_counter_member(counter, member);
-	*val = tmp;
-	spin_unlock_irqrestore(&counter->lock, flags);
-	return 0;
-}
diff --git a/kernel/sched/auto_group.c b/kernel/sched/auto_group.c
index 0984a21..0f1bacb 100644
--- a/kernel/sched/auto_group.c
+++ b/kernel/sched/auto_group.c
@@ -110,6 +110,9 @@ out_fail:
 
 bool task_wants_autogroup(struct task_struct *p, struct task_group *tg)
 {
+	if (!sysctl_sched_autogroup_enabled)
+		return false;
+
 	if (tg != &root_task_group)
 		return false;
 
@@ -143,15 +146,11 @@ autogroup_move_group(struct task_struct *p, struct autogroup *ag)
 
 	p->signal->autogroup = autogroup_kref_get(ag);
 
-	if (!ACCESS_ONCE(sysctl_sched_autogroup_enabled))
-		goto out;
-
 	t = p;
 	do {
 		sched_move_task(t);
 	} while_each_thread(p, t);
 
-out:
 	unlock_task_sighand(p, &flags);
 	autogroup_kref_put(prev);
 }
@@ -159,8 +158,11 @@ out:
 /* Allocates GFP_KERNEL, cannot be called under any spinlock */
 void sched_autogroup_create_attach(struct task_struct *p)
 {
-	struct autogroup *ag = autogroup_create();
+	struct autogroup *ag;
 
+	if (!sysctl_sched_autogroup_enabled)
+		return;
+	ag = autogroup_create();
 	autogroup_move_group(p, ag);
 	/* drop extra reference added by autogroup_create() */
 	autogroup_kref_put(ag);
@@ -176,11 +178,15 @@ EXPORT_SYMBOL(sched_autogroup_detach);
 
 void sched_autogroup_fork(struct signal_struct *sig)
 {
+	if (!sysctl_sched_autogroup_enabled)
+		return;
 	sig->autogroup = autogroup_task_get(current);
 }
 
 void sched_autogroup_exit(struct signal_struct *sig)
 {
+	if (!sysctl_sched_autogroup_enabled)
+		return;
 	autogroup_kref_put(sig->autogroup);
 }
 
@@ -193,58 +199,6 @@ static int __init setup_autogroup(char *str)
 
 __setup("noautogroup", setup_autogroup);
 
-#ifdef CONFIG_PROC_FS
-
-int proc_sched_autogroup_set_nice(struct task_struct *p, int nice)
-{
-	static unsigned long next = INITIAL_JIFFIES;
-	struct autogroup *ag;
-	int err;
-
-	if (nice < -20 || nice > 19)
-		return -EINVAL;
-
-	err = security_task_setnice(current, nice);
-	if (err)
-		return err;
-
-	if (nice < 0 && !can_nice(current, nice))
-		return -EPERM;
-
-	/* this is a heavy operation taking global locks.. */
-	if (!capable(CAP_SYS_ADMIN) && time_before(jiffies, next))
-		return -EAGAIN;
-
-	next = HZ / 10 + jiffies;
-	ag = autogroup_task_get(p);
-
-	down_write(&ag->lock);
-	err = sched_group_set_shares(ag->tg, prio_to_weight[nice + 20]);
-	if (!err)
-		ag->nice = nice;
-	up_write(&ag->lock);
-
-	autogroup_kref_put(ag);
-
-	return err;
-}
-
-void proc_sched_autogroup_show_task(struct task_struct *p, struct seq_file *m)
-{
-	struct autogroup *ag = autogroup_task_get(p);
-
-	if (!task_group_is_autogroup(ag->tg))
-		goto out;
-
-	down_read(&ag->lock);
-	seq_printf(m, "/autogroup-%ld nice %d\n", ag->id, ag->nice);
-	up_read(&ag->lock);
-
-out:
-	autogroup_kref_put(ag);
-}
-#endif /* CONFIG_PROC_FS */
-
 #ifdef CONFIG_SCHED_DEBUG
 int autogroup_path(struct task_group *tg, char *buf, int buflen)
 {
diff --git a/kernel/sched/auto_group.h b/kernel/sched/auto_group.h
index 8bd0471..4552c6b 100644
--- a/kernel/sched/auto_group.h
+++ b/kernel/sched/auto_group.h
@@ -4,11 +4,6 @@
 #include <linux/rwsem.h>
 
 struct autogroup {
-	/*
-	 * reference doesn't mean how many thread attach to this
-	 * autogroup now. It just stands for the number of task
-	 * could use this autogroup.
-	 */
 	struct kref		kref;
 	struct task_group	*tg;
 	struct rw_semaphore	lock;
@@ -29,9 +24,7 @@ extern bool task_wants_autogroup(struct task_struct *p, struct task_group *tg);
 static inline struct task_group *
 autogroup_task_group(struct task_struct *p, struct task_group *tg)
 {
-	int enabled = ACCESS_ONCE(sysctl_sched_autogroup_enabled);
-
-	if (enabled && task_wants_autogroup(p, tg))
+	if (task_wants_autogroup(p, tg))
 		return p->signal->autogroup->tg;
 
 	return tg;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 2d8927f..05c0447 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -72,6 +72,7 @@
 #include <linux/slab.h>
 #include <linux/init_task.h>
 #include <linux/binfmts.h>
+#include <linux/context_tracking.h>
 
 #include <asm/switch_to.h>
 #include <asm/tlb.h>
@@ -952,6 +953,8 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
 	trace_sched_migrate_task(p, new_cpu);
 
 	if (task_cpu(p) != new_cpu) {
+		if (p->sched_class->migrate_task_rq)
+			p->sched_class->migrate_task_rq(p, new_cpu);
 		p->se.nr_migrations++;
 		perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS, 1, NULL, 0);
 	}
@@ -1524,6 +1527,15 @@ static void __sched_fork(struct task_struct *p)
 	p->se.vruntime			= 0;
 	INIT_LIST_HEAD(&p->se.group_node);
 
+/*
+ * Load-tracking only depends on SMP, FAIR_GROUP_SCHED dependency below may be
+ * removed when useful for applications beyond shares distribution (e.g.
+ * load-balance).
+ */
+#if defined(CONFIG_SMP) && defined(CONFIG_FAIR_GROUP_SCHED)
+	p->se.avg.runnable_avg_period = 0;
+	p->se.avg.runnable_avg_sum = 0;
+#endif
 #ifdef CONFIG_SCHEDSTATS
 	memset(&p->se.statistics, 0, sizeof(p->se.statistics));
 #endif
@@ -1533,6 +1545,26 @@ static void __sched_fork(struct task_struct *p)
 #ifdef CONFIG_PREEMPT_NOTIFIERS
 	INIT_HLIST_HEAD(&p->preempt_notifiers);
 #endif
+
+#ifdef CONFIG_NUMA_BALANCING
+	if (p->mm && atomic_read(&p->mm->mm_users) == 1) {
+		p->mm->numa_next_scan = jiffies;
+		p->mm->numa_scan_seq = 0;
+	}
+
+	p->numa_shared = -1;
+	p->node_stamp = 0ULL;
+	p->numa_scan_seq = p->mm ? p->mm->numa_scan_seq : 0;
+	p->numa_migrate_seq = 2;
+	p->numa_faults = NULL;
+	p->numa_scan_period = sysctl_sched_numa_scan_delay;
+	p->numa_work.next = &p->numa_work;
+
+	p->shared_buddy = NULL;
+	p->shared_buddy_faults = 0;
+	p->ideal_cpu = -1;
+	p->ideal_cpu_curr = -1;
+#endif /* CONFIG_NUMA_BALANCING */
 }
 
 /*
@@ -1774,6 +1806,7 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev)
 	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.
@@ -1886,8 +1919,8 @@ context_switch(struct rq *rq, struct task_struct *prev,
 	spin_release(&rq->lock.dep_map, 1, _THIS_IP_);
 #endif
 
+	context_tracking_task_switch(prev, next);
 	/* Here we just switch the register state and the stack. */
-	rcu_switch(prev, next);
 	switch_to(prev, next, prev);
 
 	barrier();
@@ -2911,7 +2944,7 @@ asmlinkage void __sched schedule(void)
 }
 EXPORT_SYMBOL(schedule);
 
-#ifdef CONFIG_RCU_USER_QS
+#ifdef CONFIG_CONTEXT_TRACKING
 asmlinkage void __sched schedule_user(void)
 {
 	/*
@@ -2920,9 +2953,9 @@ asmlinkage void __sched schedule_user(void)
 	 * we haven't yet exited the RCU idle mode. Do it here manually until
 	 * we find a better solution.
 	 */
-	rcu_user_exit();
+	user_exit();
 	schedule();
-	rcu_user_enter();
+	user_enter();
 }
 #endif
 
@@ -3027,7 +3060,7 @@ asmlinkage void __sched preempt_schedule_irq(void)
 	/* Catch callers which need to be fixed */
 	BUG_ON(ti->preempt_count || !irqs_disabled());
 
-	rcu_user_exit();
+	user_exit();
 	do {
 		add_preempt_count(PREEMPT_ACTIVE);
 		local_irq_enable();
@@ -4029,8 +4062,14 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
 		goto out_free_cpus_allowed;
 	}
 	retval = -EPERM;
-	if (!check_same_owner(p) && !ns_capable(task_user_ns(p), CAP_SYS_NICE))
-		goto out_unlock;
+	if (!check_same_owner(p)) {
+		rcu_read_lock();
+		if (!ns_capable(__task_cred(p)->user_ns, CAP_SYS_NICE)) {
+			rcu_read_unlock();
+			goto out_unlock;
+		}
+		rcu_read_unlock();
+	}
 
 	retval = security_task_setscheduler(p);
 	if (retval)
@@ -4474,6 +4513,7 @@ static const char stat_nam[] = TASK_STATE_TO_CHAR_STR;
 void sched_show_task(struct task_struct *p)
 {
 	unsigned long free = 0;
+	int ppid;
 	unsigned state;
 
 	state = p->state ? __ffs(p->state) + 1 : 0;
@@ -4493,8 +4533,11 @@ void sched_show_task(struct task_struct *p)
 #ifdef CONFIG_DEBUG_STACK_USAGE
 	free = stack_not_used(p);
 #endif
+	rcu_read_lock();
+	ppid = task_pid_nr(rcu_dereference(p->real_parent));
+	rcu_read_unlock();
 	printk(KERN_CONT "%5lu %5d %6d 0x%08lx\n", free,
-		task_pid_nr(p), task_pid_nr(rcu_dereference(p->real_parent)),
+		task_pid_nr(p), ppid,
 		(unsigned long)task_thread_info(p)->flags);
 
 	show_stack(p, NULL);
@@ -5484,7 +5527,9 @@ static void destroy_sched_domains(struct sched_domain *sd, int cpu)
 DEFINE_PER_CPU(struct sched_domain *, sd_llc);
 DEFINE_PER_CPU(int, sd_llc_id);
 
-static void update_top_cache_domain(int cpu)
+DEFINE_PER_CPU(struct sched_domain *, sd_node);
+
+static void update_domain_cache(int cpu)
 {
 	struct sched_domain *sd;
 	int id = cpu;
@@ -5495,6 +5540,15 @@ static void update_top_cache_domain(int cpu)
 
 	rcu_assign_pointer(per_cpu(sd_llc, cpu), sd);
 	per_cpu(sd_llc_id, cpu) = id;
+
+	for_each_domain(cpu, sd) {
+		if (cpumask_equal(sched_domain_span(sd),
+				  cpumask_of_node(cpu_to_node(cpu))))
+			goto got_node;
+	}
+	sd = NULL;
+got_node:
+	rcu_assign_pointer(per_cpu(sd_node, cpu), sd);
 }
 
 /*
@@ -5537,7 +5591,7 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu)
 	rcu_assign_pointer(rq->sd, sd);
 	destroy_sched_domains(tmp, cpu);
 
-	update_top_cache_domain(cpu);
+	update_domain_cache(cpu);
 }
 
 /* cpus with isolated domains */
@@ -5959,6 +6013,43 @@ static struct sched_domain_topology_level default_topology[] = {
 
 static struct sched_domain_topology_level *sched_domain_topology = default_topology;
 
+#ifdef CONFIG_NUMA_BALANCING
+/*
+ * Change a task's NUMA state - called from the placement tick.
+ */
+void sched_setnuma(struct task_struct *p, int node, int shared)
+{
+	unsigned long flags;
+	int on_rq, running;
+	struct rq *rq;
+
+	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_shared = shared;
+	p->numa_max_node = node;
+
+	if (running)
+		p->sched_class->set_curr_task(rq);
+	if (on_rq)
+		enqueue_task(rq, p, 0);
+	task_rq_unlock(rq, p, &flags);
+
+	/*
+	 * Reset the scanning period. If the task converges
+	 * on this node then we'll back off again:
+	 */
+	p->numa_scan_period = sysctl_sched_numa_scan_period_min;
+}
+
+#endif /* CONFIG_NUMA_BALANCING */
+
 #ifdef CONFIG_NUMA
 
 static int sched_domains_numa_levels;
@@ -6004,6 +6095,7 @@ sd_numa_init(struct sched_domain_topology_level *tl, int cpu)
 					| 0*SD_SHARE_PKG_RESOURCES
 					| 1*SD_SERIALIZE
 					| 0*SD_PREFER_SIBLING
+					| 1*SD_NUMA
 					| sd_local_flags(level)
 					,
 		.last_balance		= jiffies,
@@ -6858,7 +6950,6 @@ void __init sched_init(void)
 		rq->post_schedule = 0;
 		rq->active_balance = 0;
 		rq->next_balance = jiffies;
-		rq->push_cpu = 0;
 		rq->cpu = i;
 		rq->online = 0;
 		rq->idle_stamp = 0;
@@ -6866,6 +6957,10 @@ void __init sched_init(void)
 
 		INIT_LIST_HEAD(&rq->cfs_tasks);
 
+#ifdef CONFIG_NUMA_BALANCING
+		rq->nr_shared_running = 0;
+#endif
+
 		rq_attach_root(rq, &def_root_domain);
 #ifdef CONFIG_NO_HZ
 		rq->nohz_flags = 0;
@@ -7468,7 +7563,7 @@ static inline struct task_group *cgroup_tg(struct cgroup *cgrp)
 			    struct task_group, css);
 }
 
-static struct cgroup_subsys_state *cpu_cgroup_create(struct cgroup *cgrp)
+static struct cgroup_subsys_state *cpu_cgroup_css_alloc(struct cgroup *cgrp)
 {
 	struct task_group *tg, *parent;
 
@@ -7485,7 +7580,7 @@ static struct cgroup_subsys_state *cpu_cgroup_create(struct cgroup *cgrp)
 	return &tg->css;
 }
 
-static void cpu_cgroup_destroy(struct cgroup *cgrp)
+static void cpu_cgroup_css_free(struct cgroup *cgrp)
 {
 	struct task_group *tg = cgroup_tg(cgrp);
 
@@ -7845,8 +7940,8 @@ static struct cftype cpu_files[] = {
 
 struct cgroup_subsys cpu_cgroup_subsys = {
 	.name		= "cpu",
-	.create		= cpu_cgroup_create,
-	.destroy	= cpu_cgroup_destroy,
+	.css_alloc	= cpu_cgroup_css_alloc,
+	.css_free	= cpu_cgroup_css_free,
 	.can_attach	= cpu_cgroup_can_attach,
 	.attach		= cpu_cgroup_attach,
 	.exit		= cpu_cgroup_exit,
@@ -7869,7 +7964,7 @@ struct cgroup_subsys cpu_cgroup_subsys = {
 struct cpuacct root_cpuacct;
 
 /* create a new cpu accounting group */
-static struct cgroup_subsys_state *cpuacct_create(struct cgroup *cgrp)
+static struct cgroup_subsys_state *cpuacct_css_alloc(struct cgroup *cgrp)
 {
 	struct cpuacct *ca;
 
@@ -7899,7 +7994,7 @@ out:
 }
 
 /* destroy an existing cpu accounting group */
-static void cpuacct_destroy(struct cgroup *cgrp)
+static void cpuacct_css_free(struct cgroup *cgrp)
 {
 	struct cpuacct *ca = cgroup_ca(cgrp);
 
@@ -8070,9 +8165,15 @@ void cpuacct_charge(struct task_struct *tsk, u64 cputime)
 
 struct cgroup_subsys cpuacct_subsys = {
 	.name = "cpuacct",
-	.create = cpuacct_create,
-	.destroy = cpuacct_destroy,
+	.css_alloc = cpuacct_css_alloc,
+	.css_free = cpuacct_css_free,
 	.subsys_id = cpuacct_subsys_id,
 	.base_cftypes = files,
 };
 #endif	/* CONFIG_CGROUP_CPUACCT */
+
+void dump_cpu_task(int cpu)
+{
+	pr_info("Task dump for CPU %d:\n", cpu);
+	sched_show_task(cpu_curr(cpu));
+}
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index 81b763b..8d859da 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -43,7 +43,7 @@ DEFINE_PER_CPU(seqcount_t, irq_time_seq);
  * Called before incrementing preempt_count on {soft,}irq_enter
  * and before decrementing preempt_count on {soft,}irq_exit.
  */
-void vtime_account(struct task_struct *curr)
+void irqtime_account_irq(struct task_struct *curr)
 {
 	unsigned long flags;
 	s64 delta;
@@ -73,7 +73,7 @@ void vtime_account(struct task_struct *curr)
 	irq_time_write_end();
 	local_irq_restore(flags);
 }
-EXPORT_SYMBOL_GPL(vtime_account);
+EXPORT_SYMBOL_GPL(irqtime_account_irq);
 
 static int irqtime_account_hi_update(void)
 {
@@ -433,10 +433,20 @@ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st)
 	*st = cputime.stime;
 }
 
+void vtime_account_system(struct task_struct *tsk)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	__vtime_account_system(tsk);
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(vtime_account_system);
+
 /*
  * Archs that account the whole time spent in the idle task
  * (outside irq) as idle time can rely on this and just implement
- * vtime_account_system() and vtime_account_idle(). Archs that
+ * __vtime_account_system() and __vtime_account_idle(). Archs that
  * have other meaning of the idle time (s390 only includes the
  * time spent by the CPU when it's in low power mode) must override
  * vtime_account().
@@ -449,9 +459,9 @@ void vtime_account(struct task_struct *tsk)
 	local_irq_save(flags);
 
 	if (in_interrupt() || !is_idle_task(tsk))
-		vtime_account_system(tsk);
+		__vtime_account_system(tsk);
 	else
-		vtime_account_idle(tsk);
+		__vtime_account_idle(tsk);
 
 	local_irq_restore(flags);
 }
diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
index 6f79596..2cd3c1b 100644
--- a/kernel/sched/debug.c
+++ b/kernel/sched/debug.c
@@ -61,14 +61,20 @@ static unsigned long nsec_low(unsigned long long nsec)
 static void print_cfs_group_stats(struct seq_file *m, int cpu, struct task_group *tg)
 {
 	struct sched_entity *se = tg->se[cpu];
-	if (!se)
-		return;
 
 #define P(F) \
 	SEQ_printf(m, "  .%-30s: %lld\n", #F, (long long)F)
 #define PN(F) \
 	SEQ_printf(m, "  .%-30s: %lld.%06ld\n", #F, SPLIT_NS((long long)F))
 
+	if (!se) {
+		struct sched_avg *avg = &cpu_rq(cpu)->avg;
+		P(avg->runnable_avg_sum);
+		P(avg->runnable_avg_period);
+		return;
+	}
+
+
 	PN(se->exec_start);
 	PN(se->vruntime);
 	PN(se->sum_exec_runtime);
@@ -85,6 +91,12 @@ static void print_cfs_group_stats(struct seq_file *m, int cpu, struct task_group
 	P(se->statistics.wait_count);
 #endif
 	P(se->load.weight);
+#ifdef CONFIG_SMP
+	P(se->avg.runnable_avg_sum);
+	P(se->avg.runnable_avg_period);
+	P(se->avg.load_avg_contrib);
+	P(se->avg.decay_count);
+#endif
 #undef PN
 #undef P
 }
@@ -206,14 +218,18 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
 	SEQ_printf(m, "  .%-30s: %ld\n", "load", cfs_rq->load.weight);
 #ifdef CONFIG_FAIR_GROUP_SCHED
 #ifdef CONFIG_SMP
-	SEQ_printf(m, "  .%-30s: %Ld.%06ld\n", "load_avg",
-			SPLIT_NS(cfs_rq->load_avg));
-	SEQ_printf(m, "  .%-30s: %Ld.%06ld\n", "load_period",
-			SPLIT_NS(cfs_rq->load_period));
-	SEQ_printf(m, "  .%-30s: %ld\n", "load_contrib",
-			cfs_rq->load_contribution);
-	SEQ_printf(m, "  .%-30s: %d\n", "load_tg",
-			atomic_read(&cfs_rq->tg->load_weight));
+	SEQ_printf(m, "  .%-30s: %lld\n", "runnable_load_avg",
+			cfs_rq->runnable_load_avg);
+	SEQ_printf(m, "  .%-30s: %lld\n", "blocked_load_avg",
+			cfs_rq->blocked_load_avg);
+	SEQ_printf(m, "  .%-30s: %ld\n", "tg_load_avg",
+			atomic64_read(&cfs_rq->tg->load_avg));
+	SEQ_printf(m, "  .%-30s: %lld\n", "tg_load_contrib",
+			cfs_rq->tg_load_contrib);
+	SEQ_printf(m, "  .%-30s: %d\n", "tg_runnable_contrib",
+			cfs_rq->tg_runnable_contrib);
+	SEQ_printf(m, "  .%-30s: %d\n", "tg->runnable_avg",
+			atomic_read(&cfs_rq->tg->runnable_avg));
 #endif
 
 	print_cfs_group_stats(m, cpu, cfs_rq->tg);
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 6b800a1..24a5588 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -18,6 +18,9 @@
  *
  *  Adaptive scheduling granularity, math enhancements by Peter Zijlstra
  *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *
+ *  NUMA placement, statistics and algorithm by Andrea Arcangeli,
+ *  CFS balancing changes by Peter Zijlstra. Copyright (C) 2012 Red Hat, Inc.
  */
 
 #include <linux/latencytop.h>
@@ -26,6 +29,9 @@
 #include <linux/slab.h>
 #include <linux/profile.h>
 #include <linux/interrupt.h>
+#include <linux/random.h>
+#include <linux/mempolicy.h>
+#include <linux/task_work.h>
 
 #include <trace/events/sched.h>
 
@@ -259,6 +265,9 @@ static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
 	return grp->my_q;
 }
 
+static void update_cfs_rq_blocked_load(struct cfs_rq *cfs_rq,
+				       int force_update);
+
 static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
 {
 	if (!cfs_rq->on_list) {
@@ -278,6 +287,8 @@ static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
 		}
 
 		cfs_rq->on_list = 1;
+		/* We should have no load, but we need to update last_decay. */
+		update_cfs_rq_blocked_load(cfs_rq, 0);
 	}
 }
 
@@ -653,9 +664,6 @@ static u64 sched_vslice(struct cfs_rq *cfs_rq, struct sched_entity *se)
 	return calc_delta_fair(sched_slice(cfs_rq, se), se);
 }
 
-static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update);
-static void update_cfs_shares(struct cfs_rq *cfs_rq);
-
 /*
  * Update the current task's runtime statistics. Skip current tasks that
  * are not in our scheduling class.
@@ -675,10 +683,6 @@ __update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr,
 
 	curr->vruntime += delta_exec_weighted;
 	update_min_vruntime(cfs_rq);
-
-#if defined CONFIG_SMP && defined CONFIG_FAIR_GROUP_SCHED
-	cfs_rq->load_unacc_exec_time += delta_exec;
-#endif
 }
 
 static void update_curr(struct cfs_rq *cfs_rq)
@@ -773,100 +777,470 @@ update_stats_curr_start(struct cfs_rq *cfs_rq, struct sched_entity *se)
 }
 
 /**************************************************
- * Scheduling class queueing methods:
+ * Scheduling class numa methods.
+ *
+ * The purpose of the NUMA bits are to maintain compute (task) and data
+ * (memory) locality.
+ *
+ * We keep a faults vector per task and use periodic fault scans to try and
+ * estalish a task<->page relation. This assumes the task<->page relation is a
+ * compute<->data relation, this is false for things like virt. and n:m
+ * threading solutions but its the best we can do given the information we
+ * have.
+ *
+ * We try and migrate such that we increase along the order provided by this
+ * vector while maintaining fairness.
+ *
+ * Tasks start out with their numa status unset (-1) this effectively means
+ * they act !NUMA until we've established the task is busy enough to bother
+ * with placement.
  */
 
-static void
-account_entity_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se)
-{
-	update_load_add(&cfs_rq->load, se->load.weight);
-	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);
+static unsigned long task_h_load(struct task_struct *p);
 #endif
-	cfs_rq->nr_running++;
+
+#ifdef CONFIG_NUMA_BALANCING
+static void account_numa_enqueue(struct rq *rq, struct task_struct *p)
+{
+	if (task_numa_shared(p) != -1) {
+		p->numa_weight = task_h_load(p);
+		rq->nr_numa_running++;
+		rq->nr_shared_running += task_numa_shared(p);
+		rq->nr_ideal_running += (cpu_to_node(task_cpu(p)) == p->numa_max_node);
+		rq->numa_weight += p->numa_weight;
+	}
 }
 
-static void
-account_entity_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se)
+static void account_numa_dequeue(struct rq *rq, struct task_struct *p)
 {
-	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))
-		list_del_init(&se->group_node);
-	cfs_rq->nr_running--;
+	if (task_numa_shared(p) != -1) {
+		rq->nr_numa_running--;
+		rq->nr_shared_running -= task_numa_shared(p);
+		rq->nr_ideal_running -= (cpu_to_node(task_cpu(p)) == p->numa_max_node);
+		rq->numa_weight -= p->numa_weight;
+	}
 }
 
-#ifdef CONFIG_FAIR_GROUP_SCHED
-/* we need this in update_cfs_load and load-balance functions below */
-static inline int throttled_hierarchy(struct cfs_rq *cfs_rq);
-# ifdef CONFIG_SMP
-static void update_cfs_rq_load_contribution(struct cfs_rq *cfs_rq,
-					    int global_update)
+/*
+ * Scan @scan_size MB every @scan_period after an initial @scan_delay.
+ */
+unsigned int sysctl_sched_numa_scan_delay = 1000;	/* ms */
+unsigned int sysctl_sched_numa_scan_period_min = 100;	/* ms */
+unsigned int sysctl_sched_numa_scan_period_max = 100*16;/* ms */
+unsigned int sysctl_sched_numa_scan_size = 256;		/* MB */
+
+/*
+ * Wait for the 2-sample stuff to settle before migrating again
+ */
+unsigned int sysctl_sched_numa_settle_count = 2;
+
+static void task_numa_migrate(struct task_struct *p, int next_cpu)
 {
-	struct task_group *tg = cfs_rq->tg;
-	long load_avg;
+	p->numa_migrate_seq = 0;
+}
 
-	load_avg = div64_u64(cfs_rq->load_avg, cfs_rq->load_period+1);
-	load_avg -= cfs_rq->load_contribution;
+static int task_ideal_cpu(struct task_struct *p)
+{
+	if (!sched_feat(IDEAL_CPU))
+		return -1;
+
+	return p->ideal_cpu;
+}
 
-	if (global_update || abs(load_avg) > cfs_rq->load_contribution / 8) {
-		atomic_add(load_avg, &tg->load_weight);
-		cfs_rq->load_contribution += load_avg;
+/*
+ * Called for every full scan - here we consider switching to a new
+ * shared buddy, if the one we found during this scan is good enough:
+ */
+static void shared_fault_full_scan_done(struct task_struct *p)
+{
+	/*
+	 * If we have a new maximum rate buddy task then pick it
+	 * as our new best friend:
+	 */
+	if (p->shared_buddy_faults_curr > p->shared_buddy_faults) {
+		WARN_ON_ONCE(!p->shared_buddy_curr);
+		p->shared_buddy			= p->shared_buddy_curr;
+		p->shared_buddy_faults		= p->shared_buddy_faults_curr;
+		p->ideal_cpu			= p->ideal_cpu_curr;
+
+		goto clear_buddy;
 	}
+	/*
+	 * If the new buddy is lower rate than the previous average
+	 * fault rate then don't switch buddies yet but lower the average by
+	 * averaging in the new rate, with a 1/3 weight.
+	 *
+	 * Eventually, if the current buddy is not a buddy anymore
+	 * then we'll switch away from it: a higher rate buddy will
+	 * replace it.
+	 */
+	p->shared_buddy_faults *= 3;
+	p->shared_buddy_faults += p->shared_buddy_faults_curr;
+	p->shared_buddy_faults /= 4;
+
+clear_buddy:
+	p->shared_buddy_curr		= NULL;
+	p->shared_buddy_faults_curr	= 0;
+	p->ideal_cpu_curr		= -1;
 }
 
-static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update)
+static void task_numa_placement(struct task_struct *p)
 {
-	u64 period = sysctl_sched_shares_window;
-	u64 now, delta;
-	unsigned long load = cfs_rq->load.weight;
+	int seq = ACCESS_ONCE(p->mm->numa_scan_seq);
+	unsigned long total[2] = { 0, 0 };
+	unsigned long faults, max_faults = 0;
+	int node, priv, shared, max_node = -1;
 
-	if (cfs_rq->tg == &root_task_group || throttled_hierarchy(cfs_rq))
+	if (p->numa_scan_seq == seq)
 		return;
 
-	now = rq_of(cfs_rq)->clock_task;
-	delta = now - cfs_rq->load_stamp;
+	p->numa_scan_seq = seq;
+
+	shared_fault_full_scan_done(p);
+
+	/*
+	 * Update the fault average with the result of the latest
+	 * scan:
+	 */
+	for (node = 0; node < nr_node_ids; node++) {
+		faults = 0;
+		for (priv = 0; priv < 2; priv++) {
+			unsigned int new_faults;
+			unsigned int idx;
+
+			idx = 2*node + priv;
+			new_faults = p->numa_faults_curr[idx];
+			p->numa_faults_curr[idx] = 0;
+
+			/* Keep a simple running average: */
+			p->numa_faults[idx] += new_faults;
+			p->numa_faults[idx] /= 2;
+
+			faults += p->numa_faults[idx];
+			total[priv] += p->numa_faults[idx];
+		}
+		if (faults > max_faults) {
+			max_faults = faults;
+			max_node = node;
+		}
+	}
 
-	/* truncate load history at 4 idle periods */
-	if (cfs_rq->load_stamp > cfs_rq->load_last &&
-	    now - cfs_rq->load_last > 4 * period) {
-		cfs_rq->load_period = 0;
-		cfs_rq->load_avg = 0;
-		delta = period - 1;
+	if (max_node != p->numa_max_node) {
+		sched_setnuma(p, max_node, task_numa_shared(p));
+		goto out_backoff;
 	}
 
-	cfs_rq->load_stamp = now;
-	cfs_rq->load_unacc_exec_time = 0;
-	cfs_rq->load_period += delta;
-	if (load) {
-		cfs_rq->load_last = now;
-		cfs_rq->load_avg += delta * load;
+	p->numa_migrate_seq++;
+	if (sched_feat(NUMA_SETTLE) &&
+	    p->numa_migrate_seq < sysctl_sched_numa_settle_count)
+		return;
+
+	/*
+	 * Note: shared is spread across multiple tasks and in the future
+	 * we might want to consider a different equation below to reduce
+	 * the impact of a little private memory accesses.
+	 */
+	shared = (total[0] >= total[1] / 2);
+	if (shared != task_numa_shared(p)) {
+		sched_setnuma(p, p->numa_max_node, shared);
+		p->numa_migrate_seq = 0;
+		goto out_backoff;
 	}
+	return;
+out_backoff:
+	p->numa_scan_period = min(p->numa_scan_period * 2, sysctl_sched_numa_scan_period_max);
+}
+
+/*
+ * Track our "memory buddies" the tasks we actively share memory with.
+ *
+ * Firstly we establish the identity of some other task that we are
+ * sharing memory with by looking at rq[page::last_cpu].curr - i.e.
+ * we check the task that is running on that CPU right now.
+ *
+ * This is not entirely correct as this task might have scheduled or
+ * migrate ther - but statistically there will be correlation to the
+ * tasks that we share memory with, and correlation is all we need.
+ *
+ * We map out the relation itself by filtering out the highest address
+ * ask that is below our own task address, per working set scan
+ * iteration.
+ *
+ * This creates a natural ordering relation between groups of tasks:
+ *
+ *     t1 < t2 < t3 < t4
+ *
+ *     t1->memory_buddy == NULL
+ *     t2->memory_buddy == t1
+ *     t3->memory_buddy == t2
+ *     t4->memory_buddy == t3
+ *
+ * The load-balancer can then use this information to speed up NUMA
+ * convergence, by moving such tasks together if capacity and load
+ * constraints allow it.
+ *
+ * (This is all statistical so there are no preemption or locking worries.)
+ */
+static void shared_fault_tick(struct task_struct *this_task, int node, int last_cpu, int pages)
+{
+	struct task_struct *last_task;
+	struct rq *last_rq;
+	int last_node;
+	int this_node;
+	int this_cpu;
+
+	last_node = cpu_to_node(last_cpu);
+	this_cpu  = raw_smp_processor_id();
+	this_node = cpu_to_node(this_cpu);
+
+	/* Ignore private memory access faults: */
+	if (last_cpu == this_cpu)
+		return;
 
-	/* consider updating load contribution on each fold or truncate */
-	if (global_update || cfs_rq->load_period > period
-	    || !cfs_rq->load_period)
-		update_cfs_rq_load_contribution(cfs_rq, global_update);
+	/*
+	 * Ignore accesses from foreign nodes to our memory.
+	 *
+	 * Yet still recognize tasks accessing a third node - i.e. one that is
+	 * remote to both of them.
+	 */
+	if (node != this_node)
+		return;
+
+	/* We are in a shared fault - see which task we relate to: */
+	last_rq = cpu_rq(last_cpu);
+	last_task = last_rq->curr;
+
+	/* Task might be gone from that runqueue already: */
+	if (!last_task || last_task == last_rq->idle)
+		return;
+
+	if (last_task == this_task->shared_buddy_curr)
+		goto out_hit;
+
+	/* Order our memory buddies by address: */
+	if (last_task >= this_task)
+		return;
+
+	if (this_task->shared_buddy_curr > last_task)
+		return;
+
+	/* New shared buddy! */
+	this_task->shared_buddy_curr = last_task;
+	this_task->shared_buddy_faults_curr = 0;
+	this_task->ideal_cpu_curr = last_rq->cpu;
+
+out_hit:
+	/*
+	 * Give threads that we share a process with an advantage,
+	 * but don't stop the discovery of process level sharing
+	 * either:
+	 */
+	if (sched_feat(IDEAL_CPU_THREAD_BIAS) && this_task->mm == last_task->mm)
+		pages *= 2;
+
+	this_task->shared_buddy_faults_curr += pages;
+}
+
+/*
+ * Got a PROT_NONE fault for a page on @node.
+ */
+void task_numa_fault(int node, int last_cpu, int pages)
+{
+	struct task_struct *p = current;
+	int priv = (task_cpu(p) == last_cpu);
+	int idx = 2*node + priv;
+
+	if (unlikely(!p->numa_faults)) {
+		int entries = 2*nr_node_ids;
+		int size = sizeof(*p->numa_faults) * entries;
 
-	while (cfs_rq->load_period > period) {
+		p->numa_faults = kzalloc(2*size, GFP_KERNEL);
+		if (!p->numa_faults)
+			return;
 		/*
-		 * Inline assembly required to prevent the compiler
-		 * optimising this loop into a divmod call.
-		 * See __iter_div_u64_rem() for another example of this.
+		 * For efficiency reasons we allocate ->numa_faults[]
+		 * and ->numa_faults_curr[] at once and split the
+		 * buffer we get. They are separate otherwise.
 		 */
-		asm("" : "+rm" (cfs_rq->load_period));
-		cfs_rq->load_period /= 2;
-		cfs_rq->load_avg /= 2;
+		p->numa_faults_curr = p->numa_faults + entries;
+	}
+
+	p->numa_faults_curr[idx] += pages;
+	shared_fault_tick(p, node, last_cpu, pages);
+	task_numa_placement(p);
+}
+
+/*
+ * The expensive part of numa migration is done from task_work context.
+ * Triggered from task_tick_numa().
+ */
+void task_numa_work(struct callback_head *work)
+{
+	long pages_total, pages_left, pages_changed;
+	unsigned long migrate, next_scan, now = jiffies;
+	unsigned long start0, start, end;
+	struct task_struct *p = current;
+	struct mm_struct *mm = p->mm;
+	struct vm_area_struct *vma;
+
+	WARN_ON_ONCE(p != container_of(work, struct task_struct, numa_work));
+
+	work->next = work; /* protect against double add */
+	/*
+	 * Who cares about NUMA placement when they're dying.
+	 *
+	 * NOTE: make sure not to dereference p->mm before this check,
+	 * exit_task_work() happens _after_ exit_mm() so we could be called
+	 * without p->mm even though we still had it when we enqueued this
+	 * work.
+	 */
+	if (p->flags & PF_EXITING)
+		return;
+
+	/*
+	 * Enforce maximal scan/migration frequency..
+	 */
+	migrate = mm->numa_next_scan;
+	if (time_before(now, migrate))
+		return;
+
+	next_scan = now + msecs_to_jiffies(sysctl_sched_numa_scan_period_min);
+	if (cmpxchg(&mm->numa_next_scan, migrate, next_scan) != migrate)
+		return;
+
+	current->numa_scan_period += jiffies_to_msecs(2);
+
+	start0 = start = end = mm->numa_scan_offset;
+	pages_total = sysctl_sched_numa_scan_size;
+	pages_total <<= 20 - PAGE_SHIFT; /* MB in pages */
+	if (!pages_total)
+		return;
+
+	pages_left	= pages_total;
+
+	down_write(&mm->mmap_sem);
+	vma = find_vma(mm, start);
+	if (!vma) {
+		ACCESS_ONCE(mm->numa_scan_seq)++;
+		end = 0;
+		vma = find_vma(mm, end);
 	}
+	for (; vma; vma = vma->vm_next) {
+		if (!vma_migratable(vma))
+			continue;
+
+		do {
+			start = max(end, vma->vm_start);
+			end = ALIGN(start + (pages_left << PAGE_SHIFT), HPAGE_SIZE);
+			end = min(end, vma->vm_end);
+			pages_changed = change_prot_numa(vma, start, end);
+
+			WARN_ON_ONCE(pages_changed > pages_total);
+			BUG_ON(pages_changed < 0);
+
+			pages_left -= pages_changed;
+			if (pages_left <= 0)
+				goto out;
+		} while (end != vma->vm_end);
+	}
+out:
+	mm->numa_scan_offset = end;
+
+	up_write(&mm->mmap_sem);
+}
+
+/*
+ * Drive the periodic memory faults..
+ */
+void task_tick_numa(struct rq *rq, struct task_struct *curr)
+{
+	struct callback_head *work = &curr->numa_work;
+	u64 period, now;
+
+	/*
+	 * We don't care about NUMA placement if we don't have memory.
+	 */
+	if (!curr->mm || (curr->flags & PF_EXITING) || work->next != work)
+		return;
+
+	/*
+	 * Using runtime rather than walltime has the dual advantage that
+	 * we (mostly) drive the selection from busy threads and that the
+	 * task needs to have done some actual work before we bother with
+	 * NUMA placement.
+	 */
+	now = curr->se.sum_exec_runtime;
+	period = (u64)curr->numa_scan_period * NSEC_PER_MSEC;
 
-	if (!cfs_rq->curr && !cfs_rq->nr_running && !cfs_rq->load_avg)
-		list_del_leaf_cfs_rq(cfs_rq);
+	if (now - curr->node_stamp > period) {
+		curr->node_stamp += period;
+		curr->numa_scan_period = sysctl_sched_numa_scan_period_min;
+
+		/*
+		 * We are comparing runtime to wall clock time here, which
+		 * puts a maximum scan frequency limit on the task work.
+		 *
+		 * This, together with the limits in task_numa_work() filters
+		 * us from over-sampling if there are many threads: if all
+		 * threads happen to come in at the same time we don't create a
+		 * spike in overhead.
+		 *
+		 * We also avoid multiple threads scanning at once in parallel to
+		 * each other.
+		 */
+		if (!time_before(jiffies, curr->mm->numa_next_scan)) {
+			init_task_work(work, task_numa_work); /* TODO: move this into sched_fork() */
+			task_work_add(curr, work, true);
+		}
+	}
 }
+#else /* !CONFIG_NUMA_BALANCING: */
+#ifdef CONFIG_SMP
+static inline int task_ideal_cpu(struct task_struct *p)				{ return -1; }
+static inline void account_numa_enqueue(struct rq *rq, struct task_struct *p)	{ }
+#endif
+static inline void account_numa_dequeue(struct rq *rq, struct task_struct *p)	{ }
+static inline void task_tick_numa(struct rq *rq, struct task_struct *curr)	{ }
+static inline void task_numa_migrate(struct task_struct *p, int next_cpu)	{ }
+#endif /* CONFIG_NUMA_BALANCING */
+
+/**************************************************
+ * Scheduling class queueing methods:
+ */
 
+static void
+account_entity_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+	update_load_add(&cfs_rq->load, se->load.weight);
+	if (!parent_entity(se))
+		update_load_add(&rq_of(cfs_rq)->load, se->load.weight);
+#ifdef CONFIG_SMP
+	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 /* CONFIG_SMP */
+	cfs_rq->nr_running++;
+}
+
+static void
+account_entity_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+	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)) {
+		list_del_init(&se->group_node);
+		account_numa_dequeue(rq_of(cfs_rq), task_of(se));
+	}
+	cfs_rq->nr_running--;
+}
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+# ifdef CONFIG_SMP
 static inline long calc_tg_weight(struct task_group *tg, struct cfs_rq *cfs_rq)
 {
 	long tg_weight;
@@ -876,8 +1250,8 @@ static inline long calc_tg_weight(struct task_group *tg, struct cfs_rq *cfs_rq)
 	 * to gain a more accurate current total weight. See
 	 * update_cfs_rq_load_contribution().
 	 */
-	tg_weight = atomic_read(&tg->load_weight);
-	tg_weight -= cfs_rq->load_contribution;
+	tg_weight = atomic64_read(&tg->load_avg);
+	tg_weight -= cfs_rq->tg_load_contrib;
 	tg_weight += cfs_rq->load.weight;
 
 	return tg_weight;
@@ -901,75 +1275,521 @@ static long calc_cfs_shares(struct cfs_rq *cfs_rq, struct task_group *tg)
 
 	return shares;
 }
+# else /* CONFIG_SMP */
+static inline long calc_cfs_shares(struct cfs_rq *cfs_rq, struct task_group *tg)
+{
+	return tg->shares;
+}
+# endif /* CONFIG_SMP */
+static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
+			    unsigned long weight)
+{
+	if (se->on_rq) {
+		/* commit outstanding execution time */
+		if (cfs_rq->curr == se)
+			update_curr(cfs_rq);
+		account_entity_dequeue(cfs_rq, se);
+	}
+
+	update_load_set(&se->load, weight);
+
+	if (se->on_rq)
+		account_entity_enqueue(cfs_rq, se);
+}
+
+static inline int throttled_hierarchy(struct cfs_rq *cfs_rq);
+
+static void update_cfs_shares(struct cfs_rq *cfs_rq)
+{
+	struct task_group *tg;
+	struct sched_entity *se;
+	long shares;
+
+	tg = cfs_rq->tg;
+	se = tg->se[cpu_of(rq_of(cfs_rq))];
+	if (!se || throttled_hierarchy(cfs_rq))
+		return;
+#ifndef CONFIG_SMP
+	if (likely(se->load.weight == tg->shares))
+		return;
+#endif
+	shares = calc_cfs_shares(cfs_rq, tg);
+
+	reweight_entity(cfs_rq_of(se), se, shares);
+}
+#else /* CONFIG_FAIR_GROUP_SCHED */
+static inline void update_cfs_shares(struct cfs_rq *cfs_rq)
+{
+}
+#endif /* CONFIG_FAIR_GROUP_SCHED */
 
-static void update_entity_shares_tick(struct cfs_rq *cfs_rq)
+/* Only depends on SMP, FAIR_GROUP_SCHED may be removed when useful in lb */
+#if defined(CONFIG_SMP) && defined(CONFIG_FAIR_GROUP_SCHED)
+/*
+ * We choose a half-life close to 1 scheduling period.
+ * Note: The tables below are dependent on this value.
+ */
+#define LOAD_AVG_PERIOD 32
+#define LOAD_AVG_MAX 47742 /* maximum possible load avg */
+#define LOAD_AVG_MAX_N 345 /* number of full periods to produce LOAD_MAX_AVG */
+
+/* Precomputed fixed inverse multiplies for multiplication by y^n */
+static const u32 runnable_avg_yN_inv[] = {
+	0xffffffff, 0xfa83b2da, 0xf5257d14, 0xefe4b99a, 0xeac0c6e6, 0xe5b906e6,
+	0xe0ccdeeb, 0xdbfbb796, 0xd744fcc9, 0xd2a81d91, 0xce248c14, 0xc9b9bd85,
+	0xc5672a10, 0xc12c4cc9, 0xbd08a39e, 0xb8fbaf46, 0xb504f333, 0xb123f581,
+	0xad583ee9, 0xa9a15ab4, 0xa5fed6a9, 0xa2704302, 0x9ef5325f, 0x9b8d39b9,
+	0x9837f050, 0x94f4efa8, 0x91c3d373, 0x8ea4398a, 0x8b95c1e3, 0x88980e80,
+	0x85aac367, 0x82cd8698,
+};
+
+/*
+ * Precomputed \Sum y^k { 1<=k<=n }.  These are floor(true_value) to prevent
+ * over-estimates when re-combining.
+ */
+static const u32 runnable_avg_yN_sum[] = {
+	    0, 1002, 1982, 2941, 3880, 4798, 5697, 6576, 7437, 8279, 9103,
+	 9909,10698,11470,12226,12966,13690,14398,15091,15769,16433,17082,
+	17718,18340,18949,19545,20128,20698,21256,21802,22336,22859,23371,
+};
+
+/*
+ * Approximate:
+ *   val * y^n,    where y^32 ~= 0.5 (~1 scheduling period)
+ */
+static __always_inline u64 decay_load(u64 val, u64 n)
 {
-	if (cfs_rq->load_unacc_exec_time > sysctl_sched_shares_window) {
-		update_cfs_load(cfs_rq, 0);
-		update_cfs_shares(cfs_rq);
+	unsigned int local_n;
+
+	if (!n)
+		return val;
+	else if (unlikely(n > LOAD_AVG_PERIOD * 63))
+		return 0;
+
+	/* after bounds checking we can collapse to 32-bit */
+	local_n = n;
+
+	/*
+	 * As y^PERIOD = 1/2, we can combine
+	 *    y^n = 1/2^(n/PERIOD) * k^(n%PERIOD)
+	 * With a look-up table which covers k^n (n<PERIOD)
+	 *
+	 * To achieve constant time decay_load.
+	 */
+	if (unlikely(local_n >= LOAD_AVG_PERIOD)) {
+		val >>= local_n / LOAD_AVG_PERIOD;
+		local_n %= LOAD_AVG_PERIOD;
+	}
+
+	val *= runnable_avg_yN_inv[local_n];
+	/* We don't use SRR here since we always want to round down. */
+	return val >> 32;
+}
+
+/*
+ * For updates fully spanning n periods, the contribution to runnable
+ * average will be: \Sum 1024*y^n
+ *
+ * We can compute this reasonably efficiently by combining:
+ *   y^PERIOD = 1/2 with precomputed \Sum 1024*y^n {for  n <PERIOD}
+ */
+static u32 __compute_runnable_contrib(u64 n)
+{
+	u32 contrib = 0;
+
+	if (likely(n <= LOAD_AVG_PERIOD))
+		return runnable_avg_yN_sum[n];
+	else if (unlikely(n >= LOAD_AVG_MAX_N))
+		return LOAD_AVG_MAX;
+
+	/* Compute \Sum k^n combining precomputed values for k^i, \Sum k^j */
+	do {
+		contrib /= 2; /* y^LOAD_AVG_PERIOD = 1/2 */
+		contrib += runnable_avg_yN_sum[LOAD_AVG_PERIOD];
+
+		n -= LOAD_AVG_PERIOD;
+	} while (n > LOAD_AVG_PERIOD);
+
+	contrib = decay_load(contrib, n);
+	return contrib + runnable_avg_yN_sum[n];
+}
+
+/*
+ * We can represent the historical contribution to runnable average as the
+ * coefficients of a geometric series.  To do this we sub-divide our runnable
+ * history into segments of approximately 1ms (1024us); label the segment that
+ * occurred N-ms ago p_N, with p_0 corresponding to the current period, e.g.
+ *
+ * [<- 1024us ->|<- 1024us ->|<- 1024us ->| ...
+ *      p0            p1           p2
+ *     (now)       (~1ms ago)  (~2ms ago)
+ *
+ * Let u_i denote the fraction of p_i that the entity was runnable.
+ *
+ * We then designate the fractions u_i as our co-efficients, yielding the
+ * following representation of historical load:
+ *   u_0 + u_1*y + u_2*y^2 + u_3*y^3 + ...
+ *
+ * We choose y based on the with of a reasonably scheduling period, fixing:
+ *   y^32 = 0.5
+ *
+ * This means that the contribution to load ~32ms ago (u_32) will be weighted
+ * approximately half as much as the contribution to load within the last ms
+ * (u_0).
+ *
+ * When a period "rolls over" and we have new u_0`, multiplying the previous
+ * sum again by y is sufficient to update:
+ *   load_avg = u_0` + y*(u_0 + u_1*y + u_2*y^2 + ... )
+ *            = u_0 + u_1*y + u_2*y^2 + ... [re-labeling u_i --> u_{i+1}]
+ */
+static __always_inline int __update_entity_runnable_avg(u64 now,
+							struct sched_avg *sa,
+							int runnable)
+{
+	u64 delta, periods;
+	u32 runnable_contrib;
+	int delta_w, decayed = 0;
+
+	delta = now - sa->last_runnable_update;
+	/*
+	 * This should only happen when time goes backwards, which it
+	 * unfortunately does during sched clock init when we swap over to TSC.
+	 */
+	if ((s64)delta < 0) {
+		sa->last_runnable_update = now;
+		return 0;
+	}
+
+	/*
+	 * Use 1024ns as the unit of measurement since it's a reasonable
+	 * approximation of 1us and fast to compute.
+	 */
+	delta >>= 10;
+	if (!delta)
+		return 0;
+	sa->last_runnable_update = now;
+
+	/* delta_w is the amount already accumulated against our next period */
+	delta_w = sa->runnable_avg_period % 1024;
+	if (delta + delta_w >= 1024) {
+		/* period roll-over */
+		decayed = 1;
+
+		/*
+		 * Now that we know we're crossing a period boundary, figure
+		 * out how much from delta we need to complete the current
+		 * period and accrue it.
+		 */
+		delta_w = 1024 - delta_w;
+		if (runnable)
+			sa->runnable_avg_sum += delta_w;
+		sa->runnable_avg_period += delta_w;
+
+		delta -= delta_w;
+
+		/* Figure out how many additional periods this update spans */
+		periods = delta / 1024;
+		delta %= 1024;
+
+		sa->runnable_avg_sum = decay_load(sa->runnable_avg_sum,
+						  periods + 1);
+		sa->runnable_avg_period = decay_load(sa->runnable_avg_period,
+						     periods + 1);
+
+		/* Efficiently calculate \sum (1..n_period) 1024*y^i */
+		runnable_contrib = __compute_runnable_contrib(periods);
+		if (runnable)
+			sa->runnable_avg_sum += runnable_contrib;
+		sa->runnable_avg_period += runnable_contrib;
+	}
+
+	/* Remainder of delta accrued against u_0` */
+	if (runnable)
+		sa->runnable_avg_sum += delta;
+	sa->runnable_avg_period += delta;
+
+	return decayed;
+}
+
+/* Synchronize an entity's decay with its parenting cfs_rq.*/
+static inline u64 __synchronize_entity_decay(struct sched_entity *se)
+{
+	struct cfs_rq *cfs_rq = cfs_rq_of(se);
+	u64 decays = atomic64_read(&cfs_rq->decay_counter);
+
+	decays -= se->avg.decay_count;
+	if (!decays)
+		return 0;
+
+	se->avg.load_avg_contrib = decay_load(se->avg.load_avg_contrib, decays);
+	se->avg.decay_count = 0;
+
+	return decays;
+}
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+static inline void __update_cfs_rq_tg_load_contrib(struct cfs_rq *cfs_rq,
+						 int force_update)
+{
+	struct task_group *tg = cfs_rq->tg;
+	s64 tg_contrib;
+
+	tg_contrib = cfs_rq->runnable_load_avg + cfs_rq->blocked_load_avg;
+	tg_contrib -= cfs_rq->tg_load_contrib;
+
+	if (force_update || abs64(tg_contrib) > cfs_rq->tg_load_contrib / 8) {
+		atomic64_add(tg_contrib, &tg->load_avg);
+		cfs_rq->tg_load_contrib += tg_contrib;
+	}
+}
+
+/*
+ * Aggregate cfs_rq runnable averages into an equivalent task_group
+ * representation for computing load contributions.
+ */
+static inline void __update_tg_runnable_avg(struct sched_avg *sa,
+						  struct cfs_rq *cfs_rq)
+{
+	struct task_group *tg = cfs_rq->tg;
+	long contrib;
+
+	/* The fraction of a cpu used by this cfs_rq */
+	contrib = div_u64(sa->runnable_avg_sum << NICE_0_SHIFT,
+			  sa->runnable_avg_period + 1);
+	contrib -= cfs_rq->tg_runnable_contrib;
+
+	if (abs(contrib) > cfs_rq->tg_runnable_contrib / 64) {
+		atomic_add(contrib, &tg->runnable_avg);
+		cfs_rq->tg_runnable_contrib += contrib;
+	}
+}
+
+static inline void __update_group_entity_contrib(struct sched_entity *se)
+{
+	struct cfs_rq *cfs_rq = group_cfs_rq(se);
+	struct task_group *tg = cfs_rq->tg;
+	int runnable_avg;
+
+	u64 contrib;
+
+	contrib = cfs_rq->tg_load_contrib * tg->shares;
+	se->avg.load_avg_contrib = div64_u64(contrib,
+					     atomic64_read(&tg->load_avg) + 1);
+
+	/*
+	 * For group entities we need to compute a correction term in the case
+	 * that they are consuming <1 cpu so that we would contribute the same
+	 * load as a task of equal weight.
+	 *
+	 * Explicitly co-ordinating this measurement would be expensive, but
+	 * fortunately the sum of each cpus contribution forms a usable
+	 * lower-bound on the true value.
+	 *
+	 * Consider the aggregate of 2 contributions.  Either they are disjoint
+	 * (and the sum represents true value) or they are disjoint and we are
+	 * understating by the aggregate of their overlap.
+	 *
+	 * Extending this to N cpus, for a given overlap, the maximum amount we
+	 * understand is then n_i(n_i+1)/2 * w_i where n_i is the number of
+	 * cpus that overlap for this interval and w_i is the interval width.
+	 *
+	 * On a small machine; the first term is well-bounded which bounds the
+	 * total error since w_i is a subset of the period.  Whereas on a
+	 * larger machine, while this first term can be larger, if w_i is the
+	 * of consequential size guaranteed to see n_i*w_i quickly converge to
+	 * our upper bound of 1-cpu.
+	 */
+	runnable_avg = atomic_read(&tg->runnable_avg);
+	if (runnable_avg < NICE_0_LOAD) {
+		se->avg.load_avg_contrib *= runnable_avg;
+		se->avg.load_avg_contrib >>= NICE_0_SHIFT;
 	}
 }
-# else /* CONFIG_SMP */
-static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update)
+#else
+static inline void __update_cfs_rq_tg_load_contrib(struct cfs_rq *cfs_rq,
+						 int force_update) {}
+static inline void __update_tg_runnable_avg(struct sched_avg *sa,
+						  struct cfs_rq *cfs_rq) {}
+static inline void __update_group_entity_contrib(struct sched_entity *se) {}
+#endif
+
+static inline void __update_task_entity_contrib(struct sched_entity *se)
 {
+	u32 contrib;
+
+	/* avoid overflowing a 32-bit type w/ SCHED_LOAD_SCALE */
+	contrib = se->avg.runnable_avg_sum * scale_load_down(se->load.weight);
+	contrib /= (se->avg.runnable_avg_period + 1);
+	se->avg.load_avg_contrib = scale_load(contrib);
 }
 
-static inline long calc_cfs_shares(struct cfs_rq *cfs_rq, struct task_group *tg)
+/* Compute the current contribution to load_avg by se, return any delta */
+static long __update_entity_load_avg_contrib(struct sched_entity *se)
 {
-	return tg->shares;
+	long old_contrib = se->avg.load_avg_contrib;
+
+	if (entity_is_task(se)) {
+		__update_task_entity_contrib(se);
+	} else {
+		__update_tg_runnable_avg(&se->avg, group_cfs_rq(se));
+		__update_group_entity_contrib(se);
+	}
+
+	return se->avg.load_avg_contrib - old_contrib;
 }
 
-static inline void update_entity_shares_tick(struct cfs_rq *cfs_rq)
+static inline void subtract_blocked_load_contrib(struct cfs_rq *cfs_rq,
+						 long load_contrib)
 {
+	if (likely(load_contrib < cfs_rq->blocked_load_avg))
+		cfs_rq->blocked_load_avg -= load_contrib;
+	else
+		cfs_rq->blocked_load_avg = 0;
 }
-# endif /* CONFIG_SMP */
-static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
-			    unsigned long weight)
+
+static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq);
+
+/* Update a sched_entity's runnable average */
+static inline void update_entity_load_avg(struct sched_entity *se,
+					  int update_cfs_rq)
 {
-	if (se->on_rq) {
-		/* commit outstanding execution time */
-		if (cfs_rq->curr == se)
-			update_curr(cfs_rq);
-		account_entity_dequeue(cfs_rq, se);
-	}
+	struct cfs_rq *cfs_rq = cfs_rq_of(se);
+	long contrib_delta;
+	u64 now;
 
-	update_load_set(&se->load, weight);
+	/*
+	 * For a group entity we need to use their owned cfs_rq_clock_task() in
+	 * case they are the parent of a throttled hierarchy.
+	 */
+	if (entity_is_task(se))
+		now = cfs_rq_clock_task(cfs_rq);
+	else
+		now = cfs_rq_clock_task(group_cfs_rq(se));
+
+	if (!__update_entity_runnable_avg(now, &se->avg, se->on_rq))
+		return;
+
+	contrib_delta = __update_entity_load_avg_contrib(se);
+
+	if (!update_cfs_rq)
+		return;
 
 	if (se->on_rq)
-		account_entity_enqueue(cfs_rq, se);
+		cfs_rq->runnable_load_avg += contrib_delta;
+	else
+		subtract_blocked_load_contrib(cfs_rq, -contrib_delta);
 }
 
-static void update_cfs_shares(struct cfs_rq *cfs_rq)
+/*
+ * Decay the load contributed by all blocked children and account this so that
+ * their contribution may appropriately discounted when they wake up.
+ */
+static void update_cfs_rq_blocked_load(struct cfs_rq *cfs_rq, int force_update)
 {
-	struct task_group *tg;
-	struct sched_entity *se;
-	long shares;
+	u64 now = cfs_rq_clock_task(cfs_rq) >> 20;
+	u64 decays;
 
-	tg = cfs_rq->tg;
-	se = tg->se[cpu_of(rq_of(cfs_rq))];
-	if (!se || throttled_hierarchy(cfs_rq))
-		return;
-#ifndef CONFIG_SMP
-	if (likely(se->load.weight == tg->shares))
+	decays = now - cfs_rq->last_decay;
+	if (!decays && !force_update)
 		return;
-#endif
-	shares = calc_cfs_shares(cfs_rq, tg);
 
-	reweight_entity(cfs_rq_of(se), se, shares);
+	if (atomic64_read(&cfs_rq->removed_load)) {
+		u64 removed_load = atomic64_xchg(&cfs_rq->removed_load, 0);
+		subtract_blocked_load_contrib(cfs_rq, removed_load);
+	}
+
+	if (decays) {
+		cfs_rq->blocked_load_avg = decay_load(cfs_rq->blocked_load_avg,
+						      decays);
+		atomic64_add(decays, &cfs_rq->decay_counter);
+		cfs_rq->last_decay = now;
+	}
+
+	__update_cfs_rq_tg_load_contrib(cfs_rq, force_update);
+	update_cfs_shares(cfs_rq);
 }
-#else /* CONFIG_FAIR_GROUP_SCHED */
-static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update)
+
+static inline void update_rq_runnable_avg(struct rq *rq, int runnable)
 {
+	__update_entity_runnable_avg(rq->clock_task, &rq->avg, runnable);
+	__update_tg_runnable_avg(&rq->avg, &rq->cfs);
 }
 
-static inline void update_cfs_shares(struct cfs_rq *cfs_rq)
+/* Add the load generated by se into cfs_rq's child load-average */
+static inline void enqueue_entity_load_avg(struct cfs_rq *cfs_rq,
+						  struct sched_entity *se,
+						  int wakeup)
 {
+	/*
+	 * We track migrations using entity decay_count <= 0, on a wake-up
+	 * migration we use a negative decay count to track the remote decays
+	 * accumulated while sleeping.
+	 */
+	if (unlikely(se->avg.decay_count <= 0)) {
+		se->avg.last_runnable_update = rq_of(cfs_rq)->clock_task;
+		if (se->avg.decay_count) {
+			/*
+			 * In a wake-up migration we have to approximate the
+			 * time sleeping.  This is because we can't synchronize
+			 * clock_task between the two cpus, and it is not
+			 * guaranteed to be read-safe.  Instead, we can
+			 * approximate this using our carried decays, which are
+			 * explicitly atomically readable.
+			 */
+			se->avg.last_runnable_update -= (-se->avg.decay_count)
+							<< 20;
+			update_entity_load_avg(se, 0);
+			/* Indicate that we're now synchronized and on-rq */
+			se->avg.decay_count = 0;
+		}
+		wakeup = 0;
+	} else {
+		__synchronize_entity_decay(se);
+	}
+
+	/* migrated tasks did not contribute to our blocked load */
+	if (wakeup) {
+		subtract_blocked_load_contrib(cfs_rq, se->avg.load_avg_contrib);
+		update_entity_load_avg(se, 0);
+	}
+
+	cfs_rq->runnable_load_avg += se->avg.load_avg_contrib;
+	/* we force update consideration on load-balancer moves */
+	update_cfs_rq_blocked_load(cfs_rq, !wakeup);
 }
 
-static inline void update_entity_shares_tick(struct cfs_rq *cfs_rq)
+/*
+ * Remove se's load from this cfs_rq child load-average, if the entity is
+ * transitioning to a blocked state we track its projected decay using
+ * blocked_load_avg.
+ */
+static inline void dequeue_entity_load_avg(struct cfs_rq *cfs_rq,
+						  struct sched_entity *se,
+						  int sleep)
 {
+	update_entity_load_avg(se, 1);
+	/* we force update consideration on load-balancer moves */
+	update_cfs_rq_blocked_load(cfs_rq, !sleep);
+
+	cfs_rq->runnable_load_avg -= se->avg.load_avg_contrib;
+	if (sleep) {
+		cfs_rq->blocked_load_avg += se->avg.load_avg_contrib;
+		se->avg.decay_count = atomic64_read(&cfs_rq->decay_counter);
+	} /* migrations, e.g. sleep=0 leave decay_count == 0 */
 }
-#endif /* CONFIG_FAIR_GROUP_SCHED */
+#else
+static inline void update_entity_load_avg(struct sched_entity *se,
+					  int update_cfs_rq) {}
+static inline void update_rq_runnable_avg(struct rq *rq, int runnable) {}
+static inline void enqueue_entity_load_avg(struct cfs_rq *cfs_rq,
+					   struct sched_entity *se,
+					   int wakeup) {}
+static inline void dequeue_entity_load_avg(struct cfs_rq *cfs_rq,
+					   struct sched_entity *se,
+					   int sleep) {}
+static inline void update_cfs_rq_blocked_load(struct cfs_rq *cfs_rq,
+					      int force_update) {}
+#endif
 
 static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)
 {
@@ -1096,9 +1916,8 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 	 * Update run-time statistics of the 'current'.
 	 */
 	update_curr(cfs_rq);
-	update_cfs_load(cfs_rq, 0);
 	account_entity_enqueue(cfs_rq, se);
-	update_cfs_shares(cfs_rq);
+	enqueue_entity_load_avg(cfs_rq, se, flags & ENQUEUE_WAKEUP);
 
 	if (flags & ENQUEUE_WAKEUP) {
 		place_entity(cfs_rq, se, 0);
@@ -1190,9 +2009,8 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 
 	if (se != cfs_rq->curr)
 		__dequeue_entity(cfs_rq, se);
-	se->on_rq = 0;
-	update_cfs_load(cfs_rq, 0);
 	account_entity_dequeue(cfs_rq, se);
+	dequeue_entity_load_avg(cfs_rq, se, flags & DEQUEUE_SLEEP);
 
 	/*
 	 * Normalize the entity after updating the min_vruntime because the
@@ -1206,7 +2024,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 	return_cfs_rq_runtime(cfs_rq);
 
 	update_min_vruntime(cfs_rq);
-	update_cfs_shares(cfs_rq);
+	se->on_rq = 0;
 }
 
 /*
@@ -1340,6 +2158,8 @@ static void put_prev_entity(struct cfs_rq *cfs_rq, struct sched_entity *prev)
 		update_stats_wait_start(cfs_rq, prev);
 		/* Put 'current' back into the tree. */
 		__enqueue_entity(cfs_rq, prev);
+		/* in !on_rq case, update occurred at dequeue */
+		update_entity_load_avg(prev, 1);
 	}
 	cfs_rq->curr = NULL;
 }
@@ -1353,9 +2173,10 @@ entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued)
 	update_curr(cfs_rq);
 
 	/*
-	 * Update share accounting for long-running entities.
+	 * Ensure that runnable average is periodically updated.
 	 */
-	update_entity_shares_tick(cfs_rq);
+	update_entity_load_avg(curr, 1);
+	update_cfs_rq_blocked_load(cfs_rq, 1);
 
 #ifdef CONFIG_SCHED_HRTICK
 	/*
@@ -1448,6 +2269,15 @@ static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg)
 	return &tg->cfs_bandwidth;
 }
 
+/* rq->task_clock normalized against any time this cfs_rq has spent throttled */
+static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq)
+{
+	if (unlikely(cfs_rq->throttle_count))
+		return cfs_rq->throttled_clock_task;
+
+	return rq_of(cfs_rq)->clock_task - cfs_rq->throttled_clock_task_time;
+}
+
 /* returns 0 on failure to allocate runtime */
 static int assign_cfs_rq_runtime(struct cfs_rq *cfs_rq)
 {
@@ -1592,14 +2422,9 @@ static int tg_unthrottle_up(struct task_group *tg, void *data)
 	cfs_rq->throttle_count--;
 #ifdef CONFIG_SMP
 	if (!cfs_rq->throttle_count) {
-		u64 delta = rq->clock_task - cfs_rq->load_stamp;
-
-		/* leaving throttled state, advance shares averaging windows */
-		cfs_rq->load_stamp += delta;
-		cfs_rq->load_last += delta;
-
-		/* update entity weight now that we are on_rq again */
-		update_cfs_shares(cfs_rq);
+		/* adjust cfs_rq_clock_task() */
+		cfs_rq->throttled_clock_task_time += rq->clock_task -
+					     cfs_rq->throttled_clock_task;
 	}
 #endif
 
@@ -1611,9 +2436,9 @@ static int tg_throttle_down(struct task_group *tg, void *data)
 	struct rq *rq = data;
 	struct cfs_rq *cfs_rq = tg->cfs_rq[cpu_of(rq)];
 
-	/* group is entering throttled state, record last load */
+	/* group is entering throttled state, stop time */
 	if (!cfs_rq->throttle_count)
-		update_cfs_load(cfs_rq, 0);
+		cfs_rq->throttled_clock_task = rq->clock_task;
 	cfs_rq->throttle_count++;
 
 	return 0;
@@ -1628,7 +2453,7 @@ static void throttle_cfs_rq(struct cfs_rq *cfs_rq)
 
 	se = cfs_rq->tg->se[cpu_of(rq_of(cfs_rq))];
 
-	/* account load preceding throttle */
+	/* freeze hierarchy runnable averages while throttled */
 	rcu_read_lock();
 	walk_tg_tree_from(cfs_rq->tg, tg_throttle_down, tg_nop, (void *)rq);
 	rcu_read_unlock();
@@ -1652,7 +2477,7 @@ static void throttle_cfs_rq(struct cfs_rq *cfs_rq)
 		rq->nr_running -= task_delta;
 
 	cfs_rq->throttled = 1;
-	cfs_rq->throttled_timestamp = rq->clock;
+	cfs_rq->throttled_clock = rq->clock;
 	raw_spin_lock(&cfs_b->lock);
 	list_add_tail_rcu(&cfs_rq->throttled_list, &cfs_b->throttled_cfs_rq);
 	raw_spin_unlock(&cfs_b->lock);
@@ -1670,10 +2495,9 @@ void unthrottle_cfs_rq(struct cfs_rq *cfs_rq)
 
 	cfs_rq->throttled = 0;
 	raw_spin_lock(&cfs_b->lock);
-	cfs_b->throttled_time += rq->clock - cfs_rq->throttled_timestamp;
+	cfs_b->throttled_time += rq->clock - cfs_rq->throttled_clock;
 	list_del_rcu(&cfs_rq->throttled_list);
 	raw_spin_unlock(&cfs_b->lock);
-	cfs_rq->throttled_timestamp = 0;
 
 	update_rq_clock(rq);
 	/* update hierarchical throttle state */
@@ -2073,8 +2897,13 @@ static void unthrottle_offline_cfs_rqs(struct rq *rq)
 }
 
 #else /* CONFIG_CFS_BANDWIDTH */
-static __always_inline
-void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, unsigned long delta_exec) {}
+static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq)
+{
+	return rq_of(cfs_rq)->clock_task;
+}
+
+static void account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
+				     unsigned long delta_exec) {}
 static void check_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
 static void check_enqueue_throttle(struct cfs_rq *cfs_rq) {}
 static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
@@ -2207,12 +3036,14 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
 		if (cfs_rq_throttled(cfs_rq))
 			break;
 
-		update_cfs_load(cfs_rq, 0);
-		update_cfs_shares(cfs_rq);
+		update_entity_load_avg(se, 1);
+		update_cfs_rq_blocked_load(cfs_rq, 0);
 	}
 
-	if (!se)
+	if (!se) {
+		update_rq_runnable_avg(rq, rq->nr_running);
 		inc_nr_running(rq);
+	}
 	hrtick_update(rq);
 }
 
@@ -2266,12 +3097,14 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
 		if (cfs_rq_throttled(cfs_rq))
 			break;
 
-		update_cfs_load(cfs_rq, 0);
-		update_cfs_shares(cfs_rq);
+		update_entity_load_avg(se, 1);
+		update_cfs_rq_blocked_load(cfs_rq, 0);
 	}
 
-	if (!se)
+	if (!se) {
 		dec_nr_running(rq);
+		update_rq_runnable_avg(rq, 1);
+	}
 	hrtick_update(rq);
 }
 
@@ -2641,6 +3474,13 @@ static int select_idle_sibling(struct task_struct *p, int target)
 	int i;
 
 	/*
+	 * For NUMA tasks constant, reliable placement is more important
+	 * than flipping tasks between siblings:
+	 */
+	if (task_numa_shared(p) >= 0)
+		return target;
+
+	/*
 	 * If the task is going to be woken-up on this cpu and if it is
 	 * already idle, then it is the right target.
 	 */
@@ -2781,6 +3621,45 @@ unlock:
 
 	return new_cpu;
 }
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+static void migrate_task_rq_entity(struct task_struct *p, int next_cpu)
+{
+	struct sched_entity *se = &p->se;
+	struct cfs_rq *cfs_rq = cfs_rq_of(se);
+
+	/*
+	 * Load tracking: accumulate removed load so that it can be processed
+	 * when we next update owning cfs_rq under rq->lock.  Tasks contribute
+	 * to blocked load iff they have a positive decay-count.  It can never
+	 * be negative here since on-rq tasks have decay-count == 0.
+	 */
+	if (se->avg.decay_count) {
+		se->avg.decay_count = -__synchronize_entity_decay(se);
+		atomic64_add(se->avg.load_avg_contrib, &cfs_rq->removed_load);
+	}
+}
+#else
+static void migrate_task_rq_entity(struct task_struct *p, int next_cpu) { }
+#endif
+
+/*
+ * Load-tracking only depends on SMP, FAIR_GROUP_SCHED dependency below may be
+ * removed when useful for applications beyond shares distribution (e.g.
+ * load-balance).
+ */
+/*
+ * Called immediately before a task is migrated to a new cpu; task_cpu(p) and
+ * cfs_rq_of(p) references at time of call are still valid and identify the
+ * previous cpu.  However, the caller only guarantees p->pi_lock is held; no
+ * other assumptions, including the state of rq->lock, should be made.
+ */
+static void
+migrate_task_rq_fair(struct task_struct *p, int next_cpu)
+{
+	migrate_task_rq_entity(p, next_cpu);
+	task_numa_migrate(p, next_cpu);
+}
 #endif /* CONFIG_SMP */
 
 static unsigned long
@@ -2907,7 +3786,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_
 	 * Batch and idle tasks do not preempt non-idle tasks (their preemption
 	 * is driven by the tick):
 	 */
-	if (unlikely(p->policy != SCHED_NORMAL))
+	if (unlikely(p->policy != SCHED_NORMAL) || !sched_feat(WAKEUP_PREEMPTION))
 		return;
 
 	find_matching_se(&se, &pse);
@@ -3033,14 +3912,131 @@ static bool yield_to_task_fair(struct rq *rq, struct task_struct *p, bool preemp
 
 #ifdef CONFIG_SMP
 /**************************************************
- * Fair scheduling class load-balancing methods:
- */
+ * Fair scheduling class load-balancing methods.
+ *
+ * BASICS
+ *
+ * The purpose of load-balancing is to achieve the same basic fairness the
+ * per-cpu scheduler provides, namely provide a proportional amount of compute
+ * time to each task. This is expressed in the following equation:
+ *
+ *   W_i,n/P_i == W_j,n/P_j for all i,j                               (1)
+ *
+ * Where W_i,n is the n-th weight average for cpu i. The instantaneous weight
+ * W_i,0 is defined as:
+ *
+ *   W_i,0 = \Sum_j w_i,j                                             (2)
+ *
+ * Where w_i,j is the weight of the j-th runnable task on cpu i. This weight
+ * is derived from the nice value as per prio_to_weight[].
+ *
+ * The weight average is an exponential decay average of the instantaneous
+ * weight:
+ *
+ *   W'_i,n = (2^n - 1) / 2^n * W_i,n + 1 / 2^n * W_i,0               (3)
+ *
+ * P_i is the cpu power (or compute capacity) of cpu i, typically it is the
+ * fraction of 'recent' time available for SCHED_OTHER task execution. But it
+ * can also include other factors [XXX].
+ *
+ * To achieve this balance we define a measure of imbalance which follows
+ * directly from (1):
+ *
+ *   imb_i,j = max{ avg(W/P), W_i/P_i } - min{ avg(W/P), W_j/P_j }    (4)
+ *
+ * We them move tasks around to minimize the imbalance. In the continuous
+ * function space it is obvious this converges, in the discrete case we get
+ * a few fun cases generally called infeasible weight scenarios.
+ *
+ * [XXX expand on:
+ *     - infeasible weights;
+ *     - local vs global optima in the discrete case. ]
+ *
+ *
+ * SCHED DOMAINS
+ *
+ * In order to solve the imbalance equation (4), and avoid the obvious O(n^2)
+ * for all i,j solution, we create a tree of cpus that follows the hardware
+ * topology where each level pairs two lower groups (or better). This results
+ * in O(log n) layers. Furthermore we reduce the number of cpus going up the
+ * tree to only the first of the previous level and we decrease the frequency
+ * of load-balance at each level inv. proportional to the number of cpus in
+ * the groups.
+ *
+ * This yields:
+ *
+ *     log_2 n     1     n
+ *   \Sum       { --- * --- * 2^i } = O(n)                            (5)
+ *     i = 0      2^i   2^i
+ *                               `- size of each group
+ *         |         |     `- number of cpus doing load-balance
+ *         |         `- freq
+ *         `- sum over all levels
+ *
+ * Coupled with a limit on how many tasks we can migrate every balance pass,
+ * this makes (5) the runtime complexity of the balancer.
+ *
+ * An important property here is that each CPU is still (indirectly) connected
+ * to every other cpu in at most O(log n) steps:
+ *
+ * The adjacency matrix of the resulting graph is given by:
+ *
+ *             log_2 n     
+ *   A_i,j = \Union     (i % 2^k == 0) && i / 2^(k+1) == j / 2^(k+1)  (6)
+ *             k = 0
+ *
+ * And you'll find that:
+ *
+ *   A^(log_2 n)_i,j != 0  for all i,j                                (7)
+ *
+ * Showing there's indeed a path between every cpu in at most O(log n) steps.
+ * The task movement gives a factor of O(m), giving a convergence complexity
+ * of:
+ *
+ *   O(nm log n),  n := nr_cpus, m := nr_tasks                        (8)
+ *
+ *
+ * WORK CONSERVING
+ *
+ * In order to avoid CPUs going idle while there's still work to do, new idle
+ * balancing is more aggressive and has the newly idle cpu iterate up the domain
+ * tree itself instead of relying on other CPUs to bring it work.
+ *
+ * This adds some complexity to both (5) and (8) but it reduces the total idle
+ * time.
+ *
+ * [XXX more?]
+ *
+ *
+ * CGROUPS
+ *
+ * Cgroups make a horror show out of (2), instead of a simple sum we get:
+ *
+ *                                s_k,i
+ *   W_i,0 = \Sum_j \Prod_k w_k * -----                               (9)
+ *                                 S_k
+ *
+ * Where
+ *
+ *   s_k,i = \Sum_j w_i,j,k  and  S_k = \Sum_i s_k,i                 (10)
+ *
+ * w_i,j,k is the weight of the j-th runnable task in the k-th cgroup on cpu i.
+ *
+ * The big problem is S_k, its a global sum needed to compute a local (W_i)
+ * property.
+ *
+ * [XXX write more on how we solve this.. _after_ merging pjt's patches that
+ *      rewrite all of this once again.]
+ */ 
 
 static unsigned long __read_mostly max_load_balance_interval = HZ/10;
 
 #define LBF_ALL_PINNED	0x01
 #define LBF_NEED_BREAK	0x02
-#define LBF_SOME_PINNED 0x04
+#define LBF_SOME_PINNED	0x04
+#define LBF_NUMA_RUN	0x08
+#define LBF_NUMA_SHARED	0x10
+#define LBF_KEEP_SHARED	0x20
 
 struct lb_env {
 	struct sched_domain	*sd;
@@ -3059,10 +4055,15 @@ struct lb_env {
 	struct cpumask		*cpus;
 
 	unsigned int		flags;
+	unsigned int		failed;
+	unsigned int		iteration;
 
 	unsigned int		loop;
 	unsigned int		loop_break;
 	unsigned int		loop_max;
+
+	struct rq *		(*find_busiest_queue)(struct lb_env *,
+						      struct sched_group *);
 };
 
 /*
@@ -3072,16 +4073,93 @@ struct lb_env {
 static void move_task(struct task_struct *p, struct lb_env *env)
 {
 	deactivate_task(env->src_rq, p, 0);
+
 	set_task_cpu(p, env->dst_cpu);
 	activate_task(env->dst_rq, p, 0);
 	check_preempt_curr(env->dst_rq, p, 0);
 }
 
+#ifdef CONFIG_NUMA_BALANCING
+
+static inline unsigned long task_node_faults(struct task_struct *p, int node)
+{
+	return p->numa_faults[2*node] + p->numa_faults[2*node + 1];
+}
+
+static int task_faults_down(struct task_struct *p, struct lb_env *env)
+{
+	int src_node, dst_node, node, down_node = -1;
+	unsigned long faults, src_faults, max_faults = 0;
+
+	if (!sched_feat_numa(NUMA_FAULTS_DOWN) || !p->numa_faults)
+		return 1;
+
+	src_node = cpu_to_node(env->src_cpu);
+	dst_node = cpu_to_node(env->dst_cpu);
+
+	if (src_node == dst_node)
+		return 1;
+
+	src_faults = task_node_faults(p, src_node);
+
+	for (node = 0; node < nr_node_ids; node++) {
+		if (node == src_node)
+			continue;
+
+		faults = task_node_faults(p, node);
+
+		if (faults > max_faults && faults <= src_faults) {
+			max_faults = faults;
+			down_node = node;
+		}
+	}
+
+	if (down_node == dst_node)
+		return 1; /* move towards the next node down */
+
+	return 0; /* stay here */
+}
+
+static int task_faults_up(struct task_struct *p, struct lb_env *env)
+{
+	unsigned long src_faults, dst_faults;
+	int src_node, dst_node;
+
+	if (!sched_feat_numa(NUMA_FAULTS_UP) || !p->numa_faults)
+		return 0; /* can't say it improved */
+
+	src_node = cpu_to_node(env->src_cpu);
+	dst_node = cpu_to_node(env->dst_cpu);
+
+	if (src_node == dst_node)
+		return 0; /* pointless, don't do that */
+
+	src_faults = task_node_faults(p, src_node);
+	dst_faults = task_node_faults(p, dst_node);
+
+	if (dst_faults > src_faults)
+		return 1; /* move to dst */
+
+	return 0; /* stay where we are */
+}
+
+#else /* !CONFIG_NUMA_BALANCING: */
+static inline int task_faults_up(struct task_struct *p, struct lb_env *env)
+{
+	return 0;
+}
+
+static inline int task_faults_down(struct task_struct *p, struct lb_env *env)
+{
+	return 0;
+}
+#endif
+
 /*
  * Is this task likely cache-hot:
  */
 static int
-task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
+task_hot(struct task_struct *p, struct lb_env *env)
 {
 	s64 delta;
 
@@ -3104,80 +4182,172 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
 	if (sysctl_sched_migration_cost == 0)
 		return 0;
 
-	delta = now - p->se.exec_start;
+	delta = env->src_rq->clock_task - p->se.exec_start;
 
 	return delta < (s64)sysctl_sched_migration_cost;
 }
 
 /*
- * can_migrate_task - may task p from runqueue rq be migrated to this_cpu?
+ * We do not migrate tasks that cannot be migrated to this CPU
+ * due to cpus_allowed.
+ *
+ * NOTE: this function has env-> side effects, to help the balancing
+ *       of pinned tasks.
  */
-static
-int can_migrate_task(struct task_struct *p, struct lb_env *env)
+static bool can_migrate_pinned_task(struct task_struct *p, struct lb_env *env)
 {
-	int tsk_cache_hot = 0;
+	int new_dst_cpu;
+
+	if (cpumask_test_cpu(env->dst_cpu, tsk_cpus_allowed(p)))
+		return true;
+
+	schedstat_inc(p, se.statistics.nr_failed_migrations_affine);
+
 	/*
-	 * We do not migrate tasks that are:
-	 * 1) running (obviously), or
-	 * 2) cannot be migrated to this CPU due to cpus_allowed, or
-	 * 3) are cache-hot on their current CPU.
+	 * 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
+	 * meet load balance goals by pulling other tasks on src_cpu.
+	 *
+	 * Also avoid computing new_dst_cpu if we have already computed
+	 * one in current iteration.
 	 */
-	if (!cpumask_test_cpu(env->dst_cpu, tsk_cpus_allowed(p))) {
-		int new_dst_cpu;
+	if (!env->dst_grpmask || (env->flags & LBF_SOME_PINNED))
+		return false;
 
-		schedstat_inc(p, se.statistics.nr_failed_migrations_affine);
+	new_dst_cpu = cpumask_first_and(env->dst_grpmask, tsk_cpus_allowed(p));
+	if (new_dst_cpu < nr_cpu_ids) {
+		env->flags |= LBF_SOME_PINNED;
+		env->new_dst_cpu = new_dst_cpu;
+	}
+	return false;
+}
 
-		/*
-		 * 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
-		 * meet load balance goals by pulling other tasks on src_cpu.
-		 *
-		 * Also avoid computing new_dst_cpu if we have already computed
-		 * one in current iteration.
-		 */
-		if (!env->dst_grpmask || (env->flags & LBF_SOME_PINNED))
-			return 0;
-
-		new_dst_cpu = cpumask_first_and(env->dst_grpmask,
-						tsk_cpus_allowed(p));
-		if (new_dst_cpu < nr_cpu_ids) {
-			env->flags |= LBF_SOME_PINNED;
-			env->new_dst_cpu = new_dst_cpu;
-		}
-		return 0;
+/*
+ * We cannot (easily) migrate tasks that are currently running:
+ */
+static bool can_migrate_running_task(struct task_struct *p, struct lb_env *env)
+{
+	if (!task_running(env->src_rq, p))
+		return true;
+
+	schedstat_inc(p, se.statistics.nr_failed_migrations_running);
+	return false;
+}
+
+/*
+ * Can we migrate a NUMA task? The rules are rather involved:
+ */
+static bool can_migrate_numa_task(struct task_struct *p, struct lb_env *env)
+{
+	/*
+	 * iteration:
+	 *   0		   -- only allow improvement, or !numa
+	 *   1		   -- + worsen !ideal
+	 *   2                         priv
+	 *   3                         shared (everything)
+	 *
+	 * NUMA_HOT_DOWN:
+	 *   1 .. nodes    -- allow getting worse by step
+	 *   nodes+1	   -- punt, everything goes!
+	 *
+	 * LBF_NUMA_RUN    -- numa only, only allow improvement
+	 * LBF_NUMA_SHARED -- shared only
+	 * LBF_NUMA_IDEAL  -- ideal only
+	 *
+	 * LBF_KEEP_SHARED -- do not touch shared tasks
+	 */
+
+	/* a numa run can only move numa tasks about to improve things */
+	if (env->flags & LBF_NUMA_RUN) {
+		if (task_numa_shared(p) < 0 && task_ideal_cpu(p) < 0)
+			return false;
+
+		/* If we are only allowed to pull shared tasks: */
+		if ((env->flags & LBF_NUMA_SHARED) && !task_numa_shared(p))
+			return false;
+	} else {
+		if (task_numa_shared(p) < 0)
+			goto try_migrate;
 	}
 
+	/* can not move shared tasks */
+	if ((env->flags & LBF_KEEP_SHARED) && task_numa_shared(p) == 1)
+		return false;
+
+	if (task_faults_up(p, env))
+		return true; /* memory locality beats cache hotness */
+
+	if (env->iteration < 1)
+		return false;
+
+#ifdef CONFIG_NUMA_BALANCING
+	if (p->numa_max_node != cpu_to_node(task_cpu(p))) /* !ideal */
+		goto demote;
+#endif
+
+	if (env->iteration < 2)
+		return false;
+
+	if (task_numa_shared(p) == 0) /* private */
+		goto demote;
+
+	if (env->iteration < 3)
+		return false;
+
+demote:
+	if (env->iteration < 5)
+		return task_faults_down(p, env);
+
+try_migrate:
+	if (env->failed > env->sd->cache_nice_tries)
+		return true;
+
+	return !task_hot(p, env);
+}
+
+/*
+ * can_migrate_task() - may task p from runqueue rq be migrated to this_cpu?
+ */
+static int can_migrate_task(struct task_struct *p, struct lb_env *env)
+{
+	if (!can_migrate_pinned_task(p, env))
+		return false;
+
 	/* Record that we found atleast one task that could run on dst_cpu */
 	env->flags &= ~LBF_ALL_PINNED;
 
-	if (task_running(env->src_rq, p)) {
-		schedstat_inc(p, se.statistics.nr_failed_migrations_running);
-		return 0;
-	}
+	if (!can_migrate_running_task(p, env))
+		return false;
 
-	/*
-	 * Aggressive migration if:
-	 * 1) task is cache cold, or
-	 * 2) too many balance attempts have failed.
-	 */
+#ifdef CONFIG_NUMA_BALANCING
+	/* If we are only allowed to pull ideal tasks: */
+	if ((task_ideal_cpu(p) >= 0) && (p->shared_buddy_faults > 1000)) {
+		int ideal_node;
+		int dst_node;
 
-	tsk_cache_hot = task_hot(p, env->src_rq->clock_task, env->sd);
-	if (!tsk_cache_hot ||
-		env->sd->nr_balance_failed > env->sd->cache_nice_tries) {
-#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;
-	}
+		BUG_ON(env->dst_cpu < 0);
 
-	if (tsk_cache_hot) {
-		schedstat_inc(p, se.statistics.nr_failed_migrations_hot);
-		return 0;
+		ideal_node = cpu_to_node(p->ideal_cpu);
+		dst_node = cpu_to_node(env->dst_cpu);
+
+		if (ideal_node == dst_node)
+			return true;
+		return false;
 	}
-	return 1;
+#endif
+
+	if (env->sd->flags & SD_NUMA)
+		return can_migrate_numa_task(p, env);
+
+	if (env->failed > env->sd->cache_nice_tries)
+		return true;
+
+	if (!task_hot(p, env))
+		return true;
+
+	schedstat_inc(p, se.statistics.nr_failed_migrations_hot);
+
+	return false;
 }
 
 /*
@@ -3192,6 +4362,7 @@ static int move_one_task(struct lb_env *env)
 	struct task_struct *p, *n;
 
 	list_for_each_entry_safe(p, n, &env->src_rq->cfs_tasks, se.group_node) {
+
 		if (throttled_lb_pair(task_group(p), env->src_rq->cpu, env->dst_cpu))
 			continue;
 
@@ -3199,6 +4370,7 @@ static int move_one_task(struct lb_env *env)
 			continue;
 
 		move_task(p, env);
+
 		/*
 		 * Right now, this is only the second place move_task()
 		 * is called, so we can safely collect move_task()
@@ -3210,8 +4382,6 @@ static int move_one_task(struct lb_env *env)
 	return 0;
 }
 
-static unsigned long task_h_load(struct task_struct *p);
-
 static const unsigned int sched_nr_migrate_break = 32;
 
 /*
@@ -3223,7 +4393,6 @@ static const unsigned int sched_nr_migrate_break = 32;
  */
 static int move_tasks(struct lb_env *env)
 {
-	struct list_head *tasks = &env->src_rq->cfs_tasks;
 	struct task_struct *p;
 	unsigned long load;
 	int pulled = 0;
@@ -3231,8 +4400,8 @@ static int move_tasks(struct lb_env *env)
 	if (env->imbalance <= 0)
 		return 0;
 
-	while (!list_empty(tasks)) {
-		p = list_first_entry(tasks, struct task_struct, se.group_node);
+	while (!list_empty(&env->src_rq->cfs_tasks)) {
+		p = list_first_entry(&env->src_rq->cfs_tasks, struct task_struct, se.group_node);
 
 		env->loop++;
 		/* We've more or less seen every task there is, call it quits */
@@ -3243,7 +4412,7 @@ static int move_tasks(struct lb_env *env)
 		if (env->loop > env->loop_break) {
 			env->loop_break += sched_nr_migrate_break;
 			env->flags |= LBF_NEED_BREAK;
-			break;
+			goto out;
 		}
 
 		if (throttled_lb_pair(task_group(p), env->src_cpu, env->dst_cpu))
@@ -3251,7 +4420,7 @@ static int move_tasks(struct lb_env *env)
 
 		load = task_h_load(p);
 
-		if (sched_feat(LB_MIN) && load < 16 && !env->sd->nr_balance_failed)
+		if (sched_feat(LB_MIN) && load < 16 && !env->failed)
 			goto next;
 
 		if ((load / 2) > env->imbalance)
@@ -3271,7 +4440,7 @@ static int move_tasks(struct lb_env *env)
 		 * the critical section.
 		 */
 		if (env->idle == CPU_NEWLY_IDLE)
-			break;
+			goto out;
 #endif
 
 		/*
@@ -3279,13 +4448,13 @@ static int move_tasks(struct lb_env *env)
 		 * weighted load.
 		 */
 		if (env->imbalance <= 0)
-			break;
+			goto out;
 
 		continue;
 next:
-		list_move_tail(&p->se.group_node, tasks);
+		list_move_tail(&p->se.group_node, &env->src_rq->cfs_tasks);
 	}
-
+out:
 	/*
 	 * Right now, this is one of only two places move_task() is called,
 	 * so we can safely collect move_task() stats here rather than
@@ -3300,52 +4469,58 @@ next:
 /*
  * update tg->load_weight by folding this cpu's load_avg
  */
-static int update_shares_cpu(struct task_group *tg, int cpu)
+static void __update_blocked_averages_cpu(struct task_group *tg, int cpu)
 {
-	struct cfs_rq *cfs_rq;
-	unsigned long flags;
-	struct rq *rq;
-
-	if (!tg->se[cpu])
-		return 0;
-
-	rq = cpu_rq(cpu);
-	cfs_rq = tg->cfs_rq[cpu];
-
-	raw_spin_lock_irqsave(&rq->lock, flags);
-
-	update_rq_clock(rq);
-	update_cfs_load(cfs_rq, 1);
+	struct sched_entity *se = tg->se[cpu];
+	struct cfs_rq *cfs_rq = tg->cfs_rq[cpu];
 
-	/*
-	 * We need to update shares after updating tg->load_weight in
-	 * order to adjust the weight of groups with long running tasks.
-	 */
-	update_cfs_shares(cfs_rq);
+	/* throttled entities do not contribute to load */
+	if (throttled_hierarchy(cfs_rq))
+		return;
 
-	raw_spin_unlock_irqrestore(&rq->lock, flags);
+	update_cfs_rq_blocked_load(cfs_rq, 1);
 
-	return 0;
+	if (se) {
+		update_entity_load_avg(se, 1);
+		/*
+		 * We pivot on our runnable average having decayed to zero for
+		 * list removal.  This generally implies that all our children
+		 * have also been removed (modulo rounding error or bandwidth
+		 * control); however, such cases are rare and we can fix these
+		 * at enqueue.
+		 *
+		 * TODO: fix up out-of-order children on enqueue.
+		 */
+		if (!se->avg.runnable_avg_sum && !cfs_rq->nr_running)
+			list_del_leaf_cfs_rq(cfs_rq);
+	} else {
+		struct rq *rq = rq_of(cfs_rq);
+		update_rq_runnable_avg(rq, rq->nr_running);
+	}
 }
 
-static void update_shares(int cpu)
+static void update_blocked_averages(int cpu)
 {
-	struct cfs_rq *cfs_rq;
 	struct rq *rq = cpu_rq(cpu);
+	struct cfs_rq *cfs_rq;
+	unsigned long flags;
 
-	rcu_read_lock();
+	raw_spin_lock_irqsave(&rq->lock, flags);
+	update_rq_clock(rq);
 	/*
 	 * Iterates the task_group tree in a bottom up fashion, see
 	 * list_add_leaf_cfs_rq() for details.
 	 */
 	for_each_leaf_cfs_rq(rq, cfs_rq) {
-		/* throttled entities do not contribute to load */
-		if (throttled_hierarchy(cfs_rq))
-			continue;
-
-		update_shares_cpu(cfs_rq->tg, cpu);
+		/*
+		 * Note: We may want to consider periodically releasing
+		 * rq->lock about these updates so that creating many task
+		 * groups does not result in continually extending hold time.
+		 */
+		__update_blocked_averages_cpu(cfs_rq->tg, rq->cpu);
 	}
-	rcu_read_unlock();
+
+	raw_spin_unlock_irqrestore(&rq->lock, flags);
 }
 
 /*
@@ -3397,24 +4572,25 @@ static unsigned long task_h_load(struct task_struct *p)
 	return load;
 }
 #else
-static inline void update_shares(int cpu)
+static inline void update_blocked_averages(int cpu)
 {
 }
 
 static inline void update_h_load(long cpu)
 {
 }
-
+#ifdef CONFIG_SMP
 static unsigned long task_h_load(struct task_struct *p)
 {
 	return p->se.load.weight;
 }
 #endif
+#endif
 
 /********** Helpers for find_busiest_group ************************/
 /*
  * sd_lb_stats - Structure to store the statistics of a sched_domain
- * 		during load balancing.
+ *		during load balancing.
  */
 struct sd_lb_stats {
 	struct sched_group *busiest; /* Busiest group in this sd */
@@ -3427,7 +4603,7 @@ struct sd_lb_stats {
 	unsigned long this_load;
 	unsigned long this_load_per_task;
 	unsigned long this_nr_running;
-	unsigned long this_has_capacity;
+	unsigned int  this_has_capacity;
 	unsigned int  this_idle_cpus;
 
 	/* Statistics of the busiest group */
@@ -3436,10 +4612,28 @@ struct sd_lb_stats {
 	unsigned long busiest_load_per_task;
 	unsigned long busiest_nr_running;
 	unsigned long busiest_group_capacity;
-	unsigned long busiest_has_capacity;
+	unsigned int  busiest_has_capacity;
 	unsigned int  busiest_group_weight;
 
 	int group_imb; /* Is there imbalance in this sd */
+
+#ifdef CONFIG_NUMA_BALANCING
+	unsigned long this_numa_running;
+	unsigned long this_numa_weight;
+	unsigned long this_shared_running;
+	unsigned long this_ideal_running;
+	unsigned long this_group_capacity;
+
+	struct sched_group *numa;
+	unsigned long numa_load;
+	unsigned long numa_nr_running;
+	unsigned long numa_numa_running;
+	unsigned long numa_shared_running;
+	unsigned long numa_ideal_running;
+	unsigned long numa_numa_weight;
+	unsigned long numa_group_capacity;
+	unsigned int  numa_has_capacity;
+#endif
 };
 
 /*
@@ -3455,6 +4649,13 @@ struct sg_lb_stats {
 	unsigned long 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 long sum_ideal_running;
+	unsigned long sum_numa_running;
+	unsigned long sum_numa_weight;
+#endif
+	unsigned long sum_shared_running;	/* 0 on non-NUMA */
 };
 
 /**
@@ -3483,6 +4684,155 @@ static inline int get_sd_load_idx(struct sched_domain *sd,
 	return load_idx;
 }
 
+#ifdef CONFIG_NUMA_BALANCING
+
+static inline bool pick_numa_rand(int n)
+{
+	return !(get_random_int() % n);
+}
+
+static inline void update_sg_numa_stats(struct sg_lb_stats *sgs, struct rq *rq)
+{
+	sgs->sum_ideal_running += rq->nr_ideal_running;
+	sgs->sum_shared_running += rq->nr_shared_running;
+	sgs->sum_numa_running += rq->nr_numa_running;
+	sgs->sum_numa_weight += rq->numa_weight;
+}
+
+static inline
+void update_sd_numa_stats(struct sched_domain *sd, struct sched_group *sg,
+			  struct sd_lb_stats *sds, struct sg_lb_stats *sgs,
+			  int local_group)
+{
+	if (!(sd->flags & SD_NUMA))
+		return;
+
+	if (local_group) {
+		sds->this_numa_running   = sgs->sum_numa_running;
+		sds->this_numa_weight    = sgs->sum_numa_weight;
+		sds->this_shared_running = sgs->sum_shared_running;
+		sds->this_ideal_running  = sgs->sum_ideal_running;
+		sds->this_group_capacity = sgs->group_capacity;
+
+	} else if (sgs->sum_numa_running - sgs->sum_ideal_running) {
+		if (!sds->numa || pick_numa_rand(sd->span_weight / sg->group_weight)) {
+			sds->numa = sg;
+			sds->numa_load		 = sgs->avg_load;
+			sds->numa_nr_running     = sgs->sum_nr_running;
+			sds->numa_numa_running   = sgs->sum_numa_running;
+			sds->numa_shared_running = sgs->sum_shared_running;
+			sds->numa_ideal_running  = sgs->sum_ideal_running;
+			sds->numa_numa_weight    = sgs->sum_numa_weight;
+			sds->numa_has_capacity	 = sgs->group_has_capacity;
+			sds->numa_group_capacity = sgs->group_capacity;
+		}
+	}
+}
+
+static struct rq *
+find_busiest_numa_queue(struct lb_env *env, struct sched_group *sg)
+{
+	struct rq *rq, *busiest = NULL;
+	int cpu;
+
+	for_each_cpu_and(cpu, sched_group_cpus(sg), env->cpus) {
+		rq = cpu_rq(cpu);
+
+		if (!rq->nr_numa_running)
+			continue;
+
+		if (!(rq->nr_numa_running - rq->nr_ideal_running))
+			continue;
+
+		if ((env->flags & LBF_KEEP_SHARED) && !(rq->nr_running - rq->nr_shared_running))
+			continue;
+
+		if (!busiest || pick_numa_rand(sg->group_weight))
+			busiest = rq;
+	}
+
+	return busiest;
+}
+
+static bool can_do_numa_run(struct lb_env *env, struct sd_lb_stats *sds)
+{
+	/*
+	 * if we're overloaded; don't pull when:
+	 *   - the other guy isn't
+	 *   - imbalance would become too great
+	 */
+	if (!sds->this_has_capacity) {
+		if (sds->numa_has_capacity)
+			return false;
+	}
+
+	/*
+	 * pull if we got easy trade
+	 */
+	if (sds->this_nr_running - sds->this_numa_running)
+		return true;
+
+	/*
+	 * If we got capacity allow stacking up on shared tasks.
+	 */
+	if ((sds->this_shared_running < sds->this_group_capacity) && sds->numa_shared_running) {
+		/* There's no point in trying to move if all are here already: */
+		if (sds->numa_shared_running == sds->this_shared_running)
+			return false;
+
+		env->flags |= LBF_NUMA_SHARED;
+		return true;
+	}
+
+	/*
+	 * pull if we could possibly trade
+	 */
+	if (sds->this_numa_running - sds->this_ideal_running)
+		return true;
+
+	return false;
+}
+
+/*
+ * introduce some controlled imbalance to perturb the state so we allow the
+ * state to improve should be tightly controlled/co-ordinated with
+ * can_migrate_task()
+ */
+static int check_numa_busiest_group(struct lb_env *env, struct sd_lb_stats *sds)
+{
+	if (!sds->numa || !sds->numa_numa_running)
+		return 0;
+
+	if (!can_do_numa_run(env, sds))
+		return 0;
+
+	env->flags |= LBF_NUMA_RUN;
+	env->flags &= ~LBF_KEEP_SHARED;
+	env->imbalance = sds->numa_numa_weight / sds->numa_numa_running;
+	sds->busiest = sds->numa;
+	env->find_busiest_queue = find_busiest_numa_queue;
+
+	return 1;
+}
+
+#else /* !CONFIG_NUMA_BALANCING: */
+static inline
+void update_sd_numa_stats(struct sched_domain *sd, struct sched_group *sg,
+			  struct sd_lb_stats *sds, struct sg_lb_stats *sgs,
+			  int local_group)
+{
+}
+
+static inline void update_sg_numa_stats(struct sg_lb_stats *sgs, struct rq *rq)
+{
+}
+
+static inline int check_numa_busiest_group(struct lb_env *env, struct sd_lb_stats *sds)
+{
+	return 0;
+}
+#endif
+
 unsigned long default_scale_freq_power(struct sched_domain *sd, int cpu)
 {
 	return SCHED_POWER_SCALE;
@@ -3696,6 +5046,9 @@ static inline void update_sg_lb_stats(struct lb_env *env,
 		sgs->group_load += load;
 		sgs->sum_nr_running += nr_running;
 		sgs->sum_weighted_load += weighted_cpuload(i);
+
+		update_sg_numa_stats(sgs, rq);
+
 		if (idle_cpu(i))
 			sgs->idle_cpus++;
 	}
@@ -3787,6 +5140,13 @@ static bool update_sd_pick_busiest(struct lb_env *env,
 	return false;
 }
 
+static void update_src_keep_shared(struct lb_env *env, bool keep_shared)
+{
+	env->flags &= ~LBF_KEEP_SHARED;
+	if (keep_shared)
+		env->flags |= LBF_KEEP_SHARED;
+}
+
 /**
  * update_sd_lb_stats - Update sched_domain's statistics for load balancing.
  * @env: The load balancing environment.
@@ -3819,6 +5179,7 @@ static inline void update_sd_lb_stats(struct lb_env *env,
 		sds->total_load += sgs.group_load;
 		sds->total_pwr += sg->sgp->power;
 
+#ifdef CONFIG_NUMA_BALANCING
 		/*
 		 * In case the child domain prefers tasks go to siblings
 		 * first, lower the sg capacity to one so that we'll try
@@ -3829,8 +5190,11 @@ static inline void update_sd_lb_stats(struct lb_env *env,
 		 * 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->this_has_capacity)
-			sgs.group_capacity = min(sgs.group_capacity, 1UL);
+		if (0 && prefer_sibling && !local_group && sds->this_has_capacity) {
+			sgs.group_capacity = clamp_val(sgs.sum_shared_running,
+					1UL, sgs.group_capacity);
+		}
+#endif
 
 		if (local_group) {
 			sds->this_load = sgs.avg_load;
@@ -3849,8 +5213,13 @@ static inline void update_sd_lb_stats(struct lb_env *env,
 			sds->busiest_has_capacity = sgs.group_has_capacity;
 			sds->busiest_group_weight = sgs.group_weight;
 			sds->group_imb = sgs.group_imb;
+
+			update_src_keep_shared(env,
+				sgs.sum_shared_running <= sgs.group_capacity);
 		}
 
+		update_sd_numa_stats(env->sd, sg, sds, &sgs, local_group);
+
 		sg = sg->next;
 	} while (sg != env->sd->groups);
 }
@@ -4103,14 +5472,14 @@ find_busiest_group(struct lb_env *env, int *balance)
 	 * don't try and pull any tasks.
 	 */
 	if (sds.this_load >= sds.max_load)
-		goto out_balanced;
+		goto out_imbalanced;
 
 	/*
 	 * Don't pull any tasks if this group is already above the domain
 	 * average load.
 	 */
 	if (sds.this_load >= sds.avg_load)
-		goto out_balanced;
+		goto out_imbalanced;
 
 	if (env->idle == CPU_IDLE) {
 		/*
@@ -4136,9 +5505,18 @@ force_balance:
 	calculate_imbalance(env, &sds);
 	return sds.busiest;
 
+out_imbalanced:
+	/* if we've got capacity allow for secondary placement preference */
+	if (!sds.this_has_capacity)
+		goto ret;
+
 out_balanced:
+	if (check_numa_busiest_group(env, &sds))
+		return sds.busiest;
+
 ret:
 	env->imbalance = 0;
+
 	return NULL;
 }
 
@@ -4174,6 +5552,9 @@ static struct rq *find_busiest_queue(struct lb_env *env,
 		if (capacity && rq->nr_running == 1 && wl > env->imbalance)
 			continue;
 
+		if ((env->flags & LBF_KEEP_SHARED) && !(rq->nr_running - rq->nr_shared_running))
+			continue;
+
 		/*
 		 * For the load comparisons with the other cpu's, consider
 		 * the weighted_cpuload() scaled with the cpu power, so that
@@ -4200,25 +5581,40 @@ static struct rq *find_busiest_queue(struct lb_env *env,
 /* Working cpumask for load_balance and load_balance_newidle. */
 DEFINE_PER_CPU(cpumask_var_t, load_balance_tmpmask);
 
-static int need_active_balance(struct lb_env *env)
-{
-	struct sched_domain *sd = env->sd;
-
-	if (env->idle == CPU_NEWLY_IDLE) {
+static int active_load_balance_cpu_stop(void *data);
 
+static void update_sd_failed(struct lb_env *env, int ld_moved)
+{
+	if (!ld_moved) {
+		schedstat_inc(env->sd, lb_failed[env->idle]);
 		/*
-		 * ASYM_PACKING needs to force migrate tasks from busy but
-		 * higher numbered CPUs in order to pack all tasks in the
-		 * lowest numbered CPUs.
+		 * Increment the failure counter only on periodic balance.
+		 * We do not want newidle balance, which can be very
+		 * frequent, pollute the failure counter causing
+		 * excessive cache_hot migrations and active balances.
 		 */
-		if ((sd->flags & SD_ASYM_PACKING) && env->src_cpu > env->dst_cpu)
-			return 1;
-	}
-
-	return unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2);
+		if (env->idle != CPU_NEWLY_IDLE && !(env->flags & LBF_NUMA_RUN))
+			env->sd->nr_balance_failed++;
+	} else
+		env->sd->nr_balance_failed = 0;
 }
 
-static int active_load_balance_cpu_stop(void *data);
+/*
+ * See can_migrate_numa_task()
+ */
+static int lb_max_iteration(struct lb_env *env)
+{
+	if (!(env->sd->flags & SD_NUMA))
+		return 0;
+
+	if (env->flags & LBF_NUMA_RUN)
+		return 0; /* NUMA_RUN may only improve */
+
+	if (sched_feat_numa(NUMA_FAULTS_DOWN))
+		return 5; /* nodes^2 would suck */
+
+	return 3;
+}
 
 /*
  * Check this_cpu to ensure it is balanced within domain. Attempt to move
@@ -4236,13 +5632,16 @@ static int load_balance(int this_cpu, struct rq *this_rq,
 	struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask);
 
 	struct lb_env env = {
-		.sd		= sd,
-		.dst_cpu	= this_cpu,
-		.dst_rq		= this_rq,
-		.dst_grpmask    = sched_group_cpus(sd->groups),
-		.idle		= idle,
-		.loop_break	= sched_nr_migrate_break,
-		.cpus		= cpus,
+		.sd		    = sd,
+		.dst_cpu	    = this_cpu,
+		.dst_rq		    = this_rq,
+		.dst_grpmask        = sched_group_cpus(sd->groups),
+		.idle		    = idle,
+		.loop_break	    = sched_nr_migrate_break,
+		.cpus		    = cpus,
+		.find_busiest_queue = find_busiest_queue,
+		.failed             = sd->nr_balance_failed,
+		.iteration          = 0,
 	};
 
 	cpumask_copy(cpus, cpu_active_mask);
@@ -4261,11 +5660,13 @@ redo:
 		goto out_balanced;
 	}
 
-	busiest = find_busiest_queue(&env, group);
+	busiest = env.find_busiest_queue(&env, group);
 	if (!busiest) {
 		schedstat_inc(sd, lb_nobusyq[idle]);
 		goto out_balanced;
 	}
+	env.src_rq  = busiest;
+	env.src_cpu = busiest->cpu;
 
 	BUG_ON(busiest == env.dst_rq);
 
@@ -4345,92 +5746,72 @@ more_balance:
 		}
 
 		/* All tasks on this runqueue were pinned by CPU affinity */
-		if (unlikely(env.flags & LBF_ALL_PINNED)) {
-			cpumask_clear_cpu(cpu_of(busiest), cpus);
-			if (!cpumask_empty(cpus)) {
-				env.loop = 0;
-				env.loop_break = sched_nr_migrate_break;
-				goto redo;
-			}
-			goto out_balanced;
+		if (unlikely(env.flags & LBF_ALL_PINNED))
+			goto out_pinned;
+
+		if (!ld_moved && env.iteration < lb_max_iteration(&env)) {
+			env.iteration++;
+			env.loop = 0;
+			goto more_balance;
 		}
 	}
 
-	if (!ld_moved) {
-		schedstat_inc(sd, lb_failed[idle]);
+	if (!ld_moved && idle != CPU_NEWLY_IDLE) {
+		raw_spin_lock_irqsave(&busiest->lock, flags);
+
 		/*
-		 * Increment the failure counter only on periodic balance.
-		 * We do not want newidle balance, which can be very
-		 * frequent, pollute the failure counter causing
-		 * excessive cache_hot migrations and active balances.
+		 * Don't kick the active_load_balance_cpu_stop,
+		 * if the curr task on busiest cpu can't be
+		 * moved to this_cpu
 		 */
-		if (idle != CPU_NEWLY_IDLE)
-			sd->nr_balance_failed++;
-
-		if (need_active_balance(&env)) {
-			raw_spin_lock_irqsave(&busiest->lock, flags);
-
-			/* don't kick the active_load_balance_cpu_stop,
-			 * if the curr task on busiest cpu can't be
-			 * moved to this_cpu
-			 */
-			if (!cpumask_test_cpu(this_cpu,
-					tsk_cpus_allowed(busiest->curr))) {
-				raw_spin_unlock_irqrestore(&busiest->lock,
-							    flags);
-				env.flags |= LBF_ALL_PINNED;
-				goto out_one_pinned;
-			}
-
-			/*
-			 * ->active_balance synchronizes accesses to
-			 * ->active_balance_work.  Once set, it's cleared
-			 * only after active load balance is finished.
-			 */
-			if (!busiest->active_balance) {
-				busiest->active_balance = 1;
-				busiest->push_cpu = this_cpu;
-				active_balance = 1;
-			}
+		if (!cpumask_test_cpu(this_cpu, tsk_cpus_allowed(busiest->curr))) {
 			raw_spin_unlock_irqrestore(&busiest->lock, flags);
-
-			if (active_balance) {
-				stop_one_cpu_nowait(cpu_of(busiest),
-					active_load_balance_cpu_stop, busiest,
-					&busiest->active_balance_work);
-			}
-
-			/*
-			 * We've kicked active balancing, reset the failure
-			 * counter.
-			 */
-			sd->nr_balance_failed = sd->cache_nice_tries+1;
+			env.flags |= LBF_ALL_PINNED;
+			goto out_pinned;
 		}
-	} else
-		sd->nr_balance_failed = 0;
 
-	if (likely(!active_balance)) {
-		/* We were unbalanced, so reset the balancing interval */
-		sd->balance_interval = sd->min_interval;
-	} else {
 		/*
-		 * If we've begun active balancing, start to back off. This
-		 * case may not be covered by the all_pinned logic if there
-		 * is only 1 task on the busy runqueue (because we don't call
-		 * move_tasks).
+		 * ->active_balance synchronizes accesses to
+		 * ->active_balance_work.  Once set, it's cleared
+		 * only after active load balance is finished.
 		 */
-		if (sd->balance_interval < sd->max_interval)
-			sd->balance_interval *= 2;
+		if (!busiest->active_balance) {
+			busiest->active_balance	= 1;
+			busiest->ab_dst_cpu	= this_cpu;
+			busiest->ab_flags	= env.flags;
+			busiest->ab_failed	= env.failed;
+			busiest->ab_idle	= env.idle;
+			active_balance		= 1;
+		}
+		raw_spin_unlock_irqrestore(&busiest->lock, flags);
+
+		if (active_balance) {
+			stop_one_cpu_nowait(cpu_of(busiest),
+					active_load_balance_cpu_stop, busiest,
+					&busiest->ab_work);
+		}
 	}
 
-	goto out;
+	if (!active_balance)
+		update_sd_failed(&env, ld_moved);
+
+	sd->balance_interval = sd->min_interval;
+out:
+	return ld_moved;
+
+out_pinned:
+	cpumask_clear_cpu(cpu_of(busiest), cpus);
+	if (!cpumask_empty(cpus)) {
+		env.loop = 0;
+		env.loop_break = sched_nr_migrate_break;
+		goto redo;
+	}
 
 out_balanced:
 	schedstat_inc(sd, lb_balanced[idle]);
 
 	sd->nr_balance_failed = 0;
 
-out_one_pinned:
 	/* tune up the balancing interval */
 	if (((env.flags & LBF_ALL_PINNED) &&
 			sd->balance_interval < MAX_PINNED_INTERVAL) ||
@@ -4438,8 +5819,8 @@ out_one_pinned:
 		sd->balance_interval *= 2;
 
 	ld_moved = 0;
-out:
-	return ld_moved;
+
+	goto out;
 }
 
 /*
@@ -4457,12 +5838,14 @@ void idle_balance(int this_cpu, struct rq *this_rq)
 	if (this_rq->avg_idle < sysctl_sched_migration_cost)
 		return;
 
+	update_rq_runnable_avg(this_rq, 1);
+
 	/*
 	 * Drop the rq->lock, but keep IRQ/preempt disabled.
 	 */
 	raw_spin_unlock(&this_rq->lock);
 
-	update_shares(this_cpu);
+	update_blocked_averages(this_cpu);
 	rcu_read_lock();
 	for_each_domain(this_cpu, sd) {
 		unsigned long interval;
@@ -4508,7 +5891,7 @@ static int active_load_balance_cpu_stop(void *data)
 {
 	struct rq *busiest_rq = data;
 	int busiest_cpu = cpu_of(busiest_rq);
-	int target_cpu = busiest_rq->push_cpu;
+	int target_cpu = busiest_rq->ab_dst_cpu;
 	struct rq *target_rq = cpu_rq(target_cpu);
 	struct sched_domain *sd;
 
@@ -4546,17 +5929,23 @@ static int active_load_balance_cpu_stop(void *data)
 			.sd		= sd,
 			.dst_cpu	= target_cpu,
 			.dst_rq		= target_rq,
-			.src_cpu	= busiest_rq->cpu,
+			.src_cpu	= busiest_cpu,
 			.src_rq		= busiest_rq,
-			.idle		= CPU_IDLE,
+			.flags		= busiest_rq->ab_flags,
+			.failed		= busiest_rq->ab_failed,
+			.idle		= busiest_rq->ab_idle,
 		};
+		env.iteration = lb_max_iteration(&env);
 
 		schedstat_inc(sd, alb_count);
 
-		if (move_one_task(&env))
+		if (move_one_task(&env)) {
 			schedstat_inc(sd, alb_pushed);
-		else
+			update_sd_failed(&env, 1);
+		} else {
 			schedstat_inc(sd, alb_failed);
+			update_sd_failed(&env, 0);
+		}
 	}
 	rcu_read_unlock();
 	double_unlock_balance(busiest_rq, target_rq);
@@ -4717,7 +6106,7 @@ static void rebalance_domains(int cpu, enum cpu_idle_type idle)
 	int update_next_balance = 0;
 	int need_serialize;
 
-	update_shares(cpu);
+	update_blocked_averages(cpu);
 
 	rcu_read_lock();
 	for_each_domain(cpu, sd) {
@@ -4954,6 +6343,11 @@ static void task_tick_fair(struct rq *rq, struct task_struct *curr, int queued)
 		cfs_rq = cfs_rq_of(se);
 		entity_tick(cfs_rq, se, queued);
 	}
+
+	update_rq_runnable_avg(rq, 1);
+
+	if (sched_feat_numa(NUMA) && nr_node_ids > 1)
+		task_tick_numa(rq, curr);
 }
 
 /*
@@ -5046,6 +6440,20 @@ static void switched_from_fair(struct rq *rq, struct task_struct *p)
 		place_entity(cfs_rq, se, 0);
 		se->vruntime -= cfs_rq->min_vruntime;
 	}
+
+#if defined(CONFIG_FAIR_GROUP_SCHED) && defined(CONFIG_SMP)
+	/*
+	* Remove our load from contribution when we leave sched_fair
+	* and ensure we don't carry in an old decay_count if we
+	* switch back.
+	*/
+	if (p->se.avg.decay_count) {
+		struct cfs_rq *cfs_rq = cfs_rq_of(&p->se);
+		__synchronize_entity_decay(&p->se);
+		subtract_blocked_load_contrib(cfs_rq,
+				p->se.avg.load_avg_contrib);
+	}
+#endif
 }
 
 /*
@@ -5092,11 +6500,16 @@ void init_cfs_rq(struct cfs_rq *cfs_rq)
 #ifndef CONFIG_64BIT
 	cfs_rq->min_vruntime_copy = cfs_rq->min_vruntime;
 #endif
+#if defined(CONFIG_FAIR_GROUP_SCHED) && defined(CONFIG_SMP)
+	atomic64_set(&cfs_rq->decay_counter, 1);
+	atomic64_set(&cfs_rq->removed_load, 0);
+#endif
 }
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
 static void task_move_group_fair(struct task_struct *p, int on_rq)
 {
+	struct cfs_rq *cfs_rq;
 	/*
 	 * If the task was not on the rq at the time of this cgroup movement
 	 * it must have been asleep, sleeping tasks keep their ->vruntime
@@ -5128,8 +6541,19 @@ static void task_move_group_fair(struct task_struct *p, int on_rq)
 	if (!on_rq)
 		p->se.vruntime -= cfs_rq_of(&p->se)->min_vruntime;
 	set_task_rq(p, task_cpu(p));
-	if (!on_rq)
-		p->se.vruntime += cfs_rq_of(&p->se)->min_vruntime;
+	if (!on_rq) {
+		cfs_rq = cfs_rq_of(&p->se);
+		p->se.vruntime += cfs_rq->min_vruntime;
+#ifdef CONFIG_SMP
+		/*
+		 * migrate_task_rq_fair() will have removed our previous
+		 * contribution, but we must synchronize for ongoing future
+		 * decay.
+		 */
+		p->se.avg.decay_count = atomic64_read(&cfs_rq->decay_counter);
+		cfs_rq->blocked_load_avg += p->se.avg.load_avg_contrib;
+#endif
+	}
 }
 
 void free_fair_sched_group(struct task_group *tg)
@@ -5214,10 +6638,6 @@ void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq,
 
 	cfs_rq->tg = tg;
 	cfs_rq->rq = rq;
-#ifdef CONFIG_SMP
-	/* allow initial update_cfs_load() to truncate */
-	cfs_rq->load_stamp = 1;
-#endif
 	init_cfs_rq_runtime(cfs_rq);
 
 	tg->cfs_rq[cpu] = cfs_rq;
@@ -5264,8 +6684,11 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares)
 		se = tg->se[i];
 		/* Propagate contribution to hierarchy */
 		raw_spin_lock_irqsave(&rq->lock, flags);
-		for_each_sched_entity(se)
+		for_each_sched_entity(se) {
 			update_cfs_shares(group_cfs_rq(se));
+			/* update contribution to parent */
+			update_entity_load_avg(se, 1);
+		}
 		raw_spin_unlock_irqrestore(&rq->lock, flags);
 	}
 
@@ -5319,7 +6742,7 @@ const struct sched_class fair_sched_class = {
 
 #ifdef CONFIG_SMP
 	.select_task_rq		= select_task_rq_fair,
-
+	.migrate_task_rq	= migrate_task_rq_fair,
 	.rq_online		= rq_online_fair,
 	.rq_offline		= rq_offline_fair,
 
diff --git a/kernel/sched/features.h b/kernel/sched/features.h
index eebefca..737d2c8 100644
--- a/kernel/sched/features.h
+++ b/kernel/sched/features.h
@@ -32,6 +32,11 @@ SCHED_FEAT(LAST_BUDDY, true)
 SCHED_FEAT(CACHE_HOT_BUDDY, true)
 
 /*
+ * Allow wakeup-time preemption of the current task:
+ */
+SCHED_FEAT(WAKEUP_PREEMPTION, true)
+
+/*
  * Use arch dependent cpu power functions
  */
 SCHED_FEAT(ARCH_POWER, true)
@@ -61,3 +66,13 @@ SCHED_FEAT(TTWU_QUEUE, true)
 SCHED_FEAT(FORCE_SD_OVERLAP, false)
 SCHED_FEAT(RT_RUNTIME_SHARE, true)
 SCHED_FEAT(LB_MIN, false)
+SCHED_FEAT(IDEAL_CPU,			true)
+SCHED_FEAT(IDEAL_CPU_THREAD_BIAS,	false)
+
+#ifdef CONFIG_NUMA_BALANCING
+/* Do the working set probing faults: */
+SCHED_FEAT(NUMA,             true)
+SCHED_FEAT(NUMA_FAULTS_UP,   true)
+SCHED_FEAT(NUMA_FAULTS_DOWN, true)
+SCHED_FEAT(NUMA_SETTLE,      true)
+#endif
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 7a7db09..bb9475c 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -3,6 +3,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/stop_machine.h>
+#include <linux/slab.h>
 
 #include "cpupri.h"
 
@@ -112,6 +113,8 @@ struct task_group {
 	unsigned long shares;
 
 	atomic_t load_weight;
+	atomic64_t load_avg;
+	atomic_t runnable_avg;
 #endif
 
 #ifdef CONFIG_RT_GROUP_SCHED
@@ -222,22 +225,29 @@ struct cfs_rq {
 	unsigned int nr_spread_over;
 #endif
 
+#ifdef CONFIG_SMP
+/*
+ * Load-tracking only depends on SMP, FAIR_GROUP_SCHED dependency below may be
+ * removed when useful for applications beyond shares distribution (e.g.
+ * load-balance).
+ */
 #ifdef CONFIG_FAIR_GROUP_SCHED
-	struct rq *rq;	/* cpu runqueue to which this cfs_rq is attached */
-
 	/*
-	 * leaf cfs_rqs are those that hold tasks (lowest schedulable entity in
-	 * a hierarchy). Non-leaf lrqs hold other higher schedulable entities
-	 * (like users, containers etc.)
-	 *
-	 * leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This
-	 * list is used during load balance.
+	 * CFS Load tracking
+	 * Under CFS, load is tracked on a per-entity basis and aggregated up.
+	 * This allows for the description of both thread and group usage (in
+	 * the FAIR_GROUP_SCHED case).
 	 */
-	int on_list;
-	struct list_head leaf_cfs_rq_list;
-	struct task_group *tg;	/* group that "owns" this runqueue */
+	u64 runnable_load_avg, blocked_load_avg;
+	atomic64_t decay_counter, removed_load;
+	u64 last_decay;
+#endif /* CONFIG_FAIR_GROUP_SCHED */
+/* These always depend on CONFIG_FAIR_GROUP_SCHED */
+#ifdef CONFIG_FAIR_GROUP_SCHED
+	u32 tg_runnable_contrib;
+	u64 tg_load_contrib;
+#endif /* CONFIG_FAIR_GROUP_SCHED */
 
-#ifdef CONFIG_SMP
 	/*
 	 *   h_load = weight * f(tg)
 	 *
@@ -245,26 +255,30 @@ struct cfs_rq {
 	 * this group.
 	 */
 	unsigned long h_load;
+#endif /* CONFIG_SMP */
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+	struct rq *rq;	/* cpu runqueue to which this cfs_rq is attached */
 
 	/*
-	 * Maintaining per-cpu shares distribution for group scheduling
+	 * leaf cfs_rqs are those that hold tasks (lowest schedulable entity in
+	 * a hierarchy). Non-leaf lrqs hold other higher schedulable entities
+	 * (like users, containers etc.)
 	 *
-	 * load_stamp is the last time we updated the load average
-	 * load_last is the last time we updated the load average and saw load
-	 * load_unacc_exec_time is currently unaccounted execution time
+	 * leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This
+	 * list is used during load balance.
 	 */
-	u64 load_avg;
-	u64 load_period;
-	u64 load_stamp, load_last, load_unacc_exec_time;
+	int on_list;
+	struct list_head leaf_cfs_rq_list;
+	struct task_group *tg;	/* group that "owns" this runqueue */
 
-	unsigned long load_contribution;
-#endif /* CONFIG_SMP */
 #ifdef CONFIG_CFS_BANDWIDTH
 	int runtime_enabled;
 	u64 runtime_expires;
 	s64 runtime_remaining;
 
-	u64 throttled_timestamp;
+	u64 throttled_clock, throttled_clock_task;
+	u64 throttled_clock_task_time;
 	int throttled, throttle_count;
 	struct list_head throttled_list;
 #endif /* CONFIG_CFS_BANDWIDTH */
@@ -407,17 +421,29 @@ struct rq {
 	unsigned long cpu_power;
 
 	unsigned char idle_balance;
-	/* For active balancing */
 	int post_schedule;
+
+	/* For active balancing */
 	int active_balance;
-	int push_cpu;
-	struct cpu_stop_work active_balance_work;
+	int ab_dst_cpu;
+	int ab_flags;
+	int ab_failed;
+	int ab_idle;
+	struct cpu_stop_work ab_work;
+
 	/* cpu of this runqueue: */
 	int cpu;
 	int online;
 
 	struct list_head cfs_tasks;
 
+#ifdef CONFIG_NUMA_BALANCING
+	unsigned long numa_weight;
+	unsigned long nr_numa_running;
+	unsigned long nr_ideal_running;
+#endif
+	unsigned long nr_shared_running;	/* 0 on non-NUMA */
+
 	u64 rt_avg;
 	u64 age_stamp;
 	u64 idle_stamp;
@@ -467,6 +493,8 @@ struct rq {
 #ifdef CONFIG_SMP
 	struct llist_head wake_list;
 #endif
+
+	struct sched_avg avg;
 };
 
 static inline int cpu_of(struct rq *rq)
@@ -486,6 +514,18 @@ DECLARE_PER_CPU(struct rq, runqueues);
 #define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
 #define raw_rq()		(&__raw_get_cpu_var(runqueues))
 
+#ifdef CONFIG_NUMA_BALANCING
+extern void sched_setnuma(struct task_struct *p, int node, int shared);
+static inline void task_numa_free(struct task_struct *p)
+{
+	kfree(p->numa_faults);
+}
+#else /* CONFIG_NUMA_BALANCING */
+static inline void task_numa_free(struct task_struct *p)
+{
+}
+#endif /* CONFIG_NUMA_BALANCING */
+
 #ifdef CONFIG_SMP
 
 #define rcu_dereference_check_sched_domain(p) \
@@ -529,6 +569,7 @@ static inline struct sched_domain *highest_flag_domain(int cpu, int flag)
 
 DECLARE_PER_CPU(struct sched_domain *, sd_llc);
 DECLARE_PER_CPU(int, sd_llc_id);
+DECLARE_PER_CPU(struct sched_domain *, sd_node);
 
 extern int group_balance_cpu(struct sched_group *sg);
 
@@ -648,6 +689,12 @@ extern struct static_key sched_feat_keys[__SCHED_FEAT_NR];
 #define sched_feat(x) (sysctl_sched_features & (1UL << __SCHED_FEAT_##x))
 #endif /* SCHED_DEBUG && HAVE_JUMP_LABEL */
 
+#ifdef CONFIG_NUMA_BALANCING
+#define sched_feat_numa(x) sched_feat(x)
+#else
+#define sched_feat_numa(x) (0)
+#endif
+
 static inline u64 global_rt_period(void)
 {
 	return (u64)sysctl_sched_rt_period * NSEC_PER_USEC;
@@ -1212,4 +1259,3 @@ static inline u64 irq_time_read(int cpu)
 }
 #endif /* CONFIG_64BIT */
 #endif /* CONFIG_IRQ_TIME_ACCOUNTING */
-
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index ee376be..5af44b5 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -396,25 +396,29 @@ int __secure_computing(int this_syscall)
 #ifdef CONFIG_SECCOMP_FILTER
 	case SECCOMP_MODE_FILTER: {
 		int data;
+		struct pt_regs *regs = task_pt_regs(current);
 		ret = seccomp_run_filters(this_syscall);
 		data = ret & SECCOMP_RET_DATA;
 		ret &= SECCOMP_RET_ACTION;
 		switch (ret) {
 		case SECCOMP_RET_ERRNO:
 			/* Set the low-order 16-bits as a errno. */
-			syscall_set_return_value(current, task_pt_regs(current),
+			syscall_set_return_value(current, regs,
 						 -data, 0);
 			goto skip;
 		case SECCOMP_RET_TRAP:
 			/* Show the handler the original registers. */
-			syscall_rollback(current, task_pt_regs(current));
+			syscall_rollback(current, regs);
 			/* Let the filter pass back 16 bits of data. */
 			seccomp_send_sigsys(this_syscall, data);
 			goto skip;
 		case SECCOMP_RET_TRACE:
 			/* Skip these calls if there is no tracer. */
-			if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP))
+			if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) {
+				syscall_set_return_value(current, regs,
+							 -ENOSYS, 0);
 				goto skip;
+			}
 			/* Allow the BPF to provide the event message */
 			ptrace_event(PTRACE_EVENT_SECCOMP, data);
 			/*
@@ -425,6 +429,9 @@ int __secure_computing(int this_syscall)
 			 */
 			if (fatal_signal_pending(current))
 				break;
+			if (syscall_get_nr(current, regs) < 0)
+				goto skip;  /* Explicit request to skip. */
+
 			return 0;
 		case SECCOMP_RET_ALLOW:
 			return 0;
diff --git a/kernel/signal.c b/kernel/signal.c
index 0af8868..580a91e 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1159,8 +1159,9 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
 	return __send_signal(sig, info, t, group, from_ancestor_ns);
 }
 
-static void print_fatal_signal(struct pt_regs *regs, int signr)
+static void print_fatal_signal(int signr)
 {
+	struct pt_regs *regs = signal_pt_regs();
 	printk("%s/%d: potentially unexpected fatal signal %d.\n",
 		current->comm, task_pid_nr(current), signr);
 
@@ -1752,7 +1753,7 @@ static void do_notify_parent_cldstop(struct task_struct *tsk,
 	 * see comment in do_notify_parent() about the following 4 lines
 	 */
 	rcu_read_lock();
-	info.si_pid = task_pid_nr_ns(tsk, parent->nsproxy->pid_ns);
+	info.si_pid = task_pid_nr_ns(tsk, task_active_pid_ns(parent));
 	info.si_uid = from_kuid_munged(task_cred_xxx(parent, user_ns), task_uid(tsk));
 	rcu_read_unlock();
 
@@ -1908,7 +1909,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
 		preempt_disable();
 		read_unlock(&tasklist_lock);
 		preempt_enable_no_resched();
-		schedule();
+		freezable_schedule();
 	} else {
 		/*
 		 * By the time we got the lock, our tracer went away.
@@ -1930,13 +1931,6 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
 	}
 
 	/*
-	 * While in TASK_TRACED, we were considered "frozen enough".
-	 * Now that we woke up, it's crucial if we're supposed to be
-	 * frozen that we freeze now before running anything substantial.
-	 */
-	try_to_freeze();
-
-	/*
 	 * We are back.  Now reacquire the siglock before touching
 	 * last_siginfo, so that we are sure to have synchronized with
 	 * any signal-sending on another CPU that wants to examine it.
@@ -2092,7 +2086,7 @@ static bool do_signal_stop(int signr)
 		}
 
 		/* Now we don't run again until woken by SIGCONT or SIGKILL */
-		schedule();
+		freezable_schedule();
 		return true;
 	} else {
 		/*
@@ -2138,10 +2132,9 @@ static void do_jobctl_trap(void)
 	}
 }
 
-static int ptrace_signal(int signr, siginfo_t *info,
-			 struct pt_regs *regs, void *cookie)
+static int ptrace_signal(int signr, siginfo_t *info)
 {
-	ptrace_signal_deliver(regs, cookie);
+	ptrace_signal_deliver();
 	/*
 	 * We do not check sig_kernel_stop(signr) but set this marker
 	 * unconditionally because we do not know whether debugger will
@@ -2200,15 +2193,14 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
 	if (unlikely(uprobe_deny_signal()))
 		return 0;
 
-relock:
 	/*
-	 * We'll jump back here after any time we were stopped in TASK_STOPPED.
-	 * While in TASK_STOPPED, we were considered "frozen enough".
-	 * Now that we woke up, it's crucial if we're supposed to be
-	 * frozen that we freeze now before running anything substantial.
+	 * Do this once, we can't return to user-mode if freezing() == T.
+	 * do_signal_stop() and ptrace_stop() do freezable_schedule() and
+	 * thus do not need another check after return.
 	 */
 	try_to_freeze();
 
+relock:
 	spin_lock_irq(&sighand->siglock);
 	/*
 	 * Every stopped thread goes here after wakeup. Check to see if
@@ -2265,8 +2257,7 @@ relock:
 			break; /* will return 0 */
 
 		if (unlikely(current->ptrace) && signr != SIGKILL) {
-			signr = ptrace_signal(signr, info,
-					      regs, cookie);
+			signr = ptrace_signal(signr, info);
 			if (!signr)
 				continue;
 		}
@@ -2351,7 +2342,7 @@ relock:
 
 		if (sig_kernel_coredump(signr)) {
 			if (print_fatal_signals)
-				print_fatal_signal(regs, info->si_signo);
+				print_fatal_signal(info->si_signo);
 			/*
 			 * If it was able to dump core, this kills all
 			 * other threads in the group and synchronizes with
@@ -2360,7 +2351,7 @@ relock:
 			 * first and our do_group_exit call below will use
 			 * that value and ignore the one we pass it.
 			 */
-			do_coredump(info, regs);
+			do_coredump(info);
 		}
 
 		/*
diff --git a/kernel/softirq.c b/kernel/softirq.c
index cc96bdc..ed567ba 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -221,7 +221,7 @@ asmlinkage void __do_softirq(void)
 	current->flags &= ~PF_MEMALLOC;
 
 	pending = local_softirq_pending();
-	vtime_account(current);
+	vtime_account_irq_enter(current);
 
 	__local_bh_disable((unsigned long)__builtin_return_address(0),
 				SOFTIRQ_OFFSET);
@@ -272,7 +272,7 @@ restart:
 
 	lockdep_softirq_exit();
 
-	vtime_account(current);
+	vtime_account_irq_exit(current);
 	__local_bh_enable(SOFTIRQ_OFFSET);
 	tsk_restore_flags(current, old_flags, PF_MEMALLOC);
 }
@@ -341,7 +341,7 @@ static inline void invoke_softirq(void)
  */
 void irq_exit(void)
 {
-	vtime_account(current);
+	vtime_account_irq_exit(current);
 	trace_hardirq_exit();
 	sub_preempt_count(IRQ_EXIT_OFFSET);
 	if (!in_interrupt() && local_softirq_pending())
diff --git a/kernel/srcu.c b/kernel/srcu.c
index 97c465e..2b85982 100644
--- a/kernel/srcu.c
+++ b/kernel/srcu.c
@@ -16,8 +16,10 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
  * Copyright (C) IBM Corporation, 2006
+ * Copyright (C) Fujitsu, 2012
  *
  * Author: Paul McKenney <paulmck@us.ibm.com>
+ *	   Lai Jiangshan <laijs@cn.fujitsu.com>
  *
  * For detailed explanation of Read-Copy Update mechanism see -
  * 		Documentation/RCU/ *.txt
@@ -34,6 +36,10 @@
 #include <linux/delay.h>
 #include <linux/srcu.h>
 
+#include <trace/events/rcu.h>
+
+#include "rcu.h"
+
 /*
  * Initialize an rcu_batch structure to empty.
  */
@@ -92,9 +98,6 @@ static inline void rcu_batch_move(struct rcu_batch *to, struct rcu_batch *from)
 	}
 }
 
-/* single-thread state-machine */
-static void process_srcu(struct work_struct *work);
-
 static int init_srcu_struct_fields(struct srcu_struct *sp)
 {
 	sp->completed = 0;
@@ -464,7 +467,9 @@ static void __synchronize_srcu(struct srcu_struct *sp, int trycount)
  */
 void synchronize_srcu(struct srcu_struct *sp)
 {
-	__synchronize_srcu(sp, SYNCHRONIZE_SRCU_TRYCOUNT);
+	__synchronize_srcu(sp, rcu_expedited
+			   ? SYNCHRONIZE_SRCU_EXP_TRYCOUNT
+			   : SYNCHRONIZE_SRCU_TRYCOUNT);
 }
 EXPORT_SYMBOL_GPL(synchronize_srcu);
 
@@ -637,7 +642,7 @@ static void srcu_reschedule(struct srcu_struct *sp)
 /*
  * This is the work-queue function that handles SRCU grace periods.
  */
-static void process_srcu(struct work_struct *work)
+void process_srcu(struct work_struct *work)
 {
 	struct srcu_struct *sp;
 
@@ -648,3 +653,4 @@ static void process_srcu(struct work_struct *work)
 	srcu_invoke_callbacks(sp);
 	srcu_reschedule(sp);
 }
+EXPORT_SYMBOL_GPL(process_srcu);
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index dbff751..395084d 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -25,6 +25,7 @@ cond_syscall(sys_swapoff);
 cond_syscall(sys_kexec_load);
 cond_syscall(compat_sys_kexec_load);
 cond_syscall(sys_init_module);
+cond_syscall(sys_finit_module);
 cond_syscall(sys_delete_module);
 cond_syscall(sys_socketpair);
 cond_syscall(sys_bind);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 26f65ea..693e0ed 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -256,9 +256,11 @@ static int min_sched_granularity_ns = 100000;		/* 100 usecs */
 static int max_sched_granularity_ns = NSEC_PER_SEC;	/* 1 second */
 static int min_wakeup_granularity_ns;			/* 0 usecs */
 static int max_wakeup_granularity_ns = NSEC_PER_SEC;	/* 1 second */
+#ifdef CONFIG_SMP
 static int min_sched_tunable_scaling = SCHED_TUNABLESCALING_NONE;
 static int max_sched_tunable_scaling = SCHED_TUNABLESCALING_END-1;
-#endif
+#endif /* CONFIG_SMP */
+#endif /* CONFIG_SCHED_DEBUG */
 
 #ifdef CONFIG_COMPACTION
 static int min_extfrag_threshold;
@@ -301,6 +303,7 @@ static struct ctl_table kern_table[] = {
 		.extra1		= &min_wakeup_granularity_ns,
 		.extra2		= &max_wakeup_granularity_ns,
 	},
+#ifdef CONFIG_SMP
 	{
 		.procname	= "sched_tunable_scaling",
 		.data		= &sysctl_sched_tunable_scaling,
@@ -347,7 +350,45 @@ static struct ctl_table kern_table[] = {
 		.extra1		= &zero,
 		.extra2		= &one,
 	},
-#endif
+#endif /* CONFIG_SMP */
+#ifdef CONFIG_NUMA_BALANCING
+	{
+		.procname	= "sched_numa_scan_delay_ms",
+		.data		= &sysctl_sched_numa_scan_delay,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "sched_numa_scan_period_min_ms",
+		.data		= &sysctl_sched_numa_scan_period_min,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "sched_numa_scan_period_max_ms",
+		.data		= &sysctl_sched_numa_scan_period_max,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "sched_numa_scan_size_mb",
+		.data		= &sysctl_sched_numa_scan_size,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "sched_numa_settle_count",
+		.data		= &sysctl_sched_numa_settle_count,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+#endif /* CONFIG_NUMA_BALANCING */
+#endif /* CONFIG_SCHED_DEBUG */
 	{
 		.procname	= "sched_rt_period_us",
 		.data		= &sysctl_sched_rt_period,
@@ -367,10 +408,8 @@ static struct ctl_table kern_table[] = {
 		.procname	= "sched_autogroup_enabled",
 		.data		= &sysctl_sched_autogroup_enabled,
 		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec_minmax,
-		.extra1		= &zero,
-		.extra2		= &one,
+		.mode		= 0444,
+		.proc_handler	= proc_dointvec,
 	},
 #endif
 #ifdef CONFIG_CFS_BANDWIDTH
@@ -565,7 +604,7 @@ static struct ctl_table kern_table[] = {
 		.extra2		= &one,
 	},
 #endif
-#ifdef CONFIG_HOTPLUG
+
 	{
 		.procname	= "hotplug",
 		.data		= &uevent_helper,
@@ -573,7 +612,7 @@ static struct ctl_table kern_table[] = {
 		.mode		= 0644,
 		.proc_handler	= proc_dostring,
 	},
-#endif
+
 #ifdef CONFIG_CHR_DEV_SG
 	{
 		.procname	= "sg-big-buff",
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index 65bdcf1..5a63844 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -1344,7 +1344,7 @@ static ssize_t binary_sysctl(const int *name, int nlen,
 		goto out_putname;
 	}
 
-	mnt = current->nsproxy->pid_ns->proc_mnt;
+	mnt = task_active_pid_ns(current)->proc_mnt;
 	file = file_open_root(mnt->mnt_root, mnt, pathname, flags);
 	result = PTR_ERR(file);
 	if (IS_ERR(file))
diff --git a/kernel/time.c b/kernel/time.c
index d226c6a..dd6705d 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -232,7 +232,7 @@ EXPORT_SYMBOL(current_fs_time);
  * Avoid unnecessary multiplications/divisions in the
  * two most common HZ cases:
  */
-inline unsigned int jiffies_to_msecs(const unsigned long j)
+unsigned int jiffies_to_msecs(const unsigned long j)
 {
 #if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
 	return (MSEC_PER_SEC / HZ) * j;
@@ -248,7 +248,7 @@ inline unsigned int jiffies_to_msecs(const unsigned long j)
 }
 EXPORT_SYMBOL(jiffies_to_msecs);
 
-inline unsigned int jiffies_to_usecs(const unsigned long j)
+unsigned int jiffies_to_usecs(const unsigned long j)
 {
 #if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
 	return (USEC_PER_SEC / HZ) * j;
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
index e2fd74b..ff7d9d2 100644
--- a/kernel/time/Makefile
+++ b/kernel/time/Makefile
@@ -1,4 +1,4 @@
-obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o timecompare.o
+obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o
 obj-y += timeconv.o posix-clock.o alarmtimer.o
 
 obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD)		+= clockevents.o
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index a402608..7587672 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -98,6 +98,49 @@ static ktime_t tick_init_jiffy_update(void)
 	return period;
 }
 
+
+static void tick_sched_do_timer(ktime_t now)
+{
+	int cpu = smp_processor_id();
+
+#ifdef CONFIG_NO_HZ
+	/*
+	 * Check if the do_timer duty was dropped. We don't care about
+	 * concurrency: This happens only when the cpu in charge went
+	 * into a long sleep. If two cpus happen to assign themself to
+	 * this duty, then the jiffies update is still serialized by
+	 * xtime_lock.
+	 */
+	if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE))
+		tick_do_timer_cpu = cpu;
+#endif
+
+	/* Check, if the jiffies need an update */
+	if (tick_do_timer_cpu == cpu)
+		tick_do_update_jiffies64(now);
+}
+
+static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs)
+{
+#ifdef CONFIG_NO_HZ
+	/*
+	 * When we are idle and the tick is stopped, we have to touch
+	 * the watchdog as we might not schedule for a really long
+	 * time. This happens on complete idle SMP systems while
+	 * waiting on the login prompt. We also increment the "start of
+	 * idle" jiffy stamp so the idle accounting adjustment we do
+	 * when we go busy again does not account too much ticks.
+	 */
+	if (ts->tick_stopped) {
+		touch_softlockup_watchdog();
+		if (is_idle_task(current))
+			ts->idle_jiffies++;
+	}
+#endif
+	update_process_times(user_mode(regs));
+	profile_tick(CPU_PROFILING);
+}
+
 /*
  * NOHZ - aka dynamic tick functionality
  */
@@ -526,6 +569,8 @@ void tick_nohz_irq_exit(void)
 	if (!ts->inidle)
 		return;
 
+	/* Cancel the timer because CPU already waken up from the C-states*/
+	menu_hrtimer_cancel();
 	__tick_nohz_idle_enter(ts);
 }
 
@@ -621,6 +666,8 @@ void tick_nohz_idle_exit(void)
 
 	ts->inidle = 0;
 
+	/* Cancel the timer because CPU already waken up from the C-states*/
+	menu_hrtimer_cancel();
 	if (ts->idle_active || ts->tick_stopped)
 		now = ktime_get();
 
@@ -648,40 +695,12 @@ static void tick_nohz_handler(struct clock_event_device *dev)
 {
 	struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
 	struct pt_regs *regs = get_irq_regs();
-	int cpu = smp_processor_id();
 	ktime_t now = ktime_get();
 
 	dev->next_event.tv64 = KTIME_MAX;
 
-	/*
-	 * Check if the do_timer duty was dropped. We don't care about
-	 * concurrency: This happens only when the cpu in charge went
-	 * into a long sleep. If two cpus happen to assign themself to
-	 * this duty, then the jiffies update is still serialized by
-	 * xtime_lock.
-	 */
-	if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE))
-		tick_do_timer_cpu = cpu;
-
-	/* Check, if the jiffies need an update */
-	if (tick_do_timer_cpu == cpu)
-		tick_do_update_jiffies64(now);
-
-	/*
-	 * When we are idle and the tick is stopped, we have to touch
-	 * the watchdog as we might not schedule for a really long
-	 * time. This happens on complete idle SMP systems while
-	 * waiting on the login prompt. We also increment the "start
-	 * of idle" jiffy stamp so the idle accounting adjustment we
-	 * do when we go busy again does not account too much ticks.
-	 */
-	if (ts->tick_stopped) {
-		touch_softlockup_watchdog();
-		ts->idle_jiffies++;
-	}
-
-	update_process_times(user_mode(regs));
-	profile_tick(CPU_PROFILING);
+	tick_sched_do_timer(now);
+	tick_sched_handle(ts, regs);
 
 	while (tick_nohz_reprogram(ts, now)) {
 		now = ktime_get();
@@ -794,7 +813,7 @@ void tick_check_idle(int cpu)
 #ifdef CONFIG_HIGH_RES_TIMERS
 /*
  * We rearm the timer until we get disabled by the idle code.
- * Called with interrupts disabled and timer->base->cpu_base->lock held.
+ * Called with interrupts disabled.
  */
 static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
 {
@@ -802,45 +821,15 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
 		container_of(timer, struct tick_sched, sched_timer);
 	struct pt_regs *regs = get_irq_regs();
 	ktime_t now = ktime_get();
-	int cpu = smp_processor_id();
-
-#ifdef CONFIG_NO_HZ
-	/*
-	 * Check if the do_timer duty was dropped. We don't care about
-	 * concurrency: This happens only when the cpu in charge went
-	 * into a long sleep. If two cpus happen to assign themself to
-	 * this duty, then the jiffies update is still serialized by
-	 * xtime_lock.
-	 */
-	if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE))
-		tick_do_timer_cpu = cpu;
-#endif
 
-	/* Check, if the jiffies need an update */
-	if (tick_do_timer_cpu == cpu)
-		tick_do_update_jiffies64(now);
+	tick_sched_do_timer(now);
 
 	/*
 	 * Do not call, when we are not in irq context and have
 	 * no valid regs pointer
 	 */
-	if (regs) {
-		/*
-		 * When we are idle and the tick is stopped, we have to touch
-		 * the watchdog as we might not schedule for a really long
-		 * time. This happens on complete idle SMP systems while
-		 * waiting on the login prompt. We also increment the "start of
-		 * idle" jiffy stamp so the idle accounting adjustment we do
-		 * when we go busy again does not account too much ticks.
-		 */
-		if (ts->tick_stopped) {
-			touch_softlockup_watchdog();
-			if (is_idle_task(current))
-				ts->idle_jiffies++;
-		}
-		update_process_times(user_mode(regs));
-		profile_tick(CPU_PROFILING);
-	}
+	if (regs)
+		tick_sched_handle(ts, regs);
 
 	hrtimer_forward(timer, now, tick_period);
 
diff --git a/kernel/time/timecompare.c b/kernel/time/timecompare.c
deleted file mode 100644
index a9ae369..0000000
--- a/kernel/time/timecompare.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2009 Intel Corporation.
- * Author: Patrick Ohly <patrick.ohly@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/timecompare.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/math64.h>
-#include <linux/kernel.h>
-
-/*
- * fixed point arithmetic scale factor for skew
- *
- * Usually one would measure skew in ppb (parts per billion, 1e9), but
- * using a factor of 2 simplifies the math.
- */
-#define TIMECOMPARE_SKEW_RESOLUTION (((s64)1)<<30)
-
-ktime_t timecompare_transform(struct timecompare *sync,
-			      u64 source_tstamp)
-{
-	u64 nsec;
-
-	nsec = source_tstamp + sync->offset;
-	nsec += (s64)(source_tstamp - sync->last_update) * sync->skew /
-		TIMECOMPARE_SKEW_RESOLUTION;
-
-	return ns_to_ktime(nsec);
-}
-EXPORT_SYMBOL_GPL(timecompare_transform);
-
-int timecompare_offset(struct timecompare *sync,
-		       s64 *offset,
-		       u64 *source_tstamp)
-{
-	u64 start_source = 0, end_source = 0;
-	struct {
-		s64 offset;
-		s64 duration_target;
-	} buffer[10], sample, *samples;
-	int counter = 0, i;
-	int used;
-	int index;
-	int num_samples = sync->num_samples;
-
-	if (num_samples > ARRAY_SIZE(buffer)) {
-		samples = kmalloc(sizeof(*samples) * num_samples, GFP_ATOMIC);
-		if (!samples) {
-			samples = buffer;
-			num_samples = ARRAY_SIZE(buffer);
-		}
-	} else {
-		samples = buffer;
-	}
-
-	/* run until we have enough valid samples, but do not try forever */
-	i = 0;
-	counter = 0;
-	while (1) {
-		u64 ts;
-		ktime_t start, end;
-
-		start = sync->target();
-		ts = timecounter_read(sync->source);
-		end = sync->target();
-
-		if (!i)
-			start_source = ts;
-
-		/* ignore negative durations */
-		sample.duration_target = ktime_to_ns(ktime_sub(end, start));
-		if (sample.duration_target >= 0) {
-			/*
-			 * assume symetric delay to and from source:
-			 * average target time corresponds to measured
-			 * source time
-			 */
-			sample.offset =
-				(ktime_to_ns(end) + ktime_to_ns(start)) / 2 -
-				ts;
-
-			/* simple insertion sort based on duration */
-			index = counter - 1;
-			while (index >= 0) {
-				if (samples[index].duration_target <
-				    sample.duration_target)
-					break;
-				samples[index + 1] = samples[index];
-				index--;
-			}
-			samples[index + 1] = sample;
-			counter++;
-		}
-
-		i++;
-		if (counter >= num_samples || i >= 100000) {
-			end_source = ts;
-			break;
-		}
-	}
-
-	*source_tstamp = (end_source + start_source) / 2;
-
-	/* remove outliers by only using 75% of the samples */
-	used = counter * 3 / 4;
-	if (!used)
-		used = counter;
-	if (used) {
-		/* calculate average */
-		s64 off = 0;
-		for (index = 0; index < used; index++)
-			off += samples[index].offset;
-		*offset = div_s64(off, used);
-	}
-
-	if (samples && samples != buffer)
-		kfree(samples);
-
-	return used;
-}
-EXPORT_SYMBOL_GPL(timecompare_offset);
-
-void __timecompare_update(struct timecompare *sync,
-			  u64 source_tstamp)
-{
-	s64 offset;
-	u64 average_time;
-
-	if (!timecompare_offset(sync, &offset, &average_time))
-		return;
-
-	if (!sync->last_update) {
-		sync->last_update = average_time;
-		sync->offset = offset;
-		sync->skew = 0;
-	} else {
-		s64 delta_nsec = average_time - sync->last_update;
-
-		/* avoid division by negative or small deltas */
-		if (delta_nsec >= 10000) {
-			s64 delta_offset_nsec = offset - sync->offset;
-			s64 skew; /* delta_offset_nsec *
-				     TIMECOMPARE_SKEW_RESOLUTION /
-				     delta_nsec */
-			u64 divisor;
-
-			/* div_s64() is limited to 32 bit divisor */
-			skew = delta_offset_nsec * TIMECOMPARE_SKEW_RESOLUTION;
-			divisor = delta_nsec;
-			while (unlikely(divisor >= ((s64)1) << 32)) {
-				/* divide both by 2; beware, right shift
-				   of negative value has undefined
-				   behavior and can only be used for
-				   the positive divisor */
-				skew = div_s64(skew, 2);
-				divisor >>= 1;
-			}
-			skew = div_s64(skew, divisor);
-
-			/*
-			 * Calculate new overall skew as 4/16 the
-			 * old value and 12/16 the new one. This is
-			 * a rather arbitrary tradeoff between
-			 * only using the latest measurement (0/16 and
-			 * 16/16) and even more weight on past measurements.
-			 */
-#define TIMECOMPARE_NEW_SKEW_PER_16 12
-			sync->skew =
-				div_s64((16 - TIMECOMPARE_NEW_SKEW_PER_16) *
-					sync->skew +
-					TIMECOMPARE_NEW_SKEW_PER_16 * skew,
-					16);
-			sync->last_update = average_time;
-			sync->offset = offset;
-		}
-	}
-}
-EXPORT_SYMBOL_GPL(__timecompare_update);
diff --git a/kernel/timeconst.pl b/kernel/timeconst.pl
index eb51d76..0461239 100644
--- a/kernel/timeconst.pl
+++ b/kernel/timeconst.pl
@@ -370,7 +370,7 @@ if ($hz eq '--can') {
 	}
 
 	@val = @{$canned_values{$hz}};
-	if (!defined(@val)) {
+	if (!@val) {
 		@val = compute_values($hz);
 	}
 	output($hz, @val);
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 4cea4f4..5d89335 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -119,6 +119,7 @@ config TRACING
 	select BINARY_PRINTF
 	select EVENT_TRACING
 	select TRACE_CLOCK
+	select IRQ_WORK
 
 config GENERIC_TRACER
 	bool
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 9dcf15d..4451aa3 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -2868,7 +2868,7 @@ static int __init ftrace_mod_cmd_init(void)
 {
 	return register_ftrace_command(&ftrace_mod_cmd);
 }
-device_initcall(ftrace_mod_cmd_init);
+core_initcall(ftrace_mod_cmd_init);
 
 static void function_trace_probe_call(unsigned long ip, unsigned long parent_ip,
 				      struct ftrace_ops *op, struct pt_regs *pt_regs)
@@ -4055,7 +4055,7 @@ static int __init ftrace_nodyn_init(void)
 	ftrace_enabled = 1;
 	return 0;
 }
-device_initcall(ftrace_nodyn_init);
+core_initcall(ftrace_nodyn_init);
 
 static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; }
 static inline void ftrace_startup_enable(int command) { }
@@ -4381,7 +4381,7 @@ ftrace_pid_write(struct file *filp, const char __user *ubuf,
 	if (strlen(tmp) == 0)
 		return 1;
 
-	ret = strict_strtol(tmp, 10, &val);
+	ret = kstrtol(tmp, 10, &val);
 	if (ret < 0)
 		return ret;
 
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index b979426..3c7834c 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -460,9 +460,10 @@ struct ring_buffer_per_cpu {
 	unsigned long			lost_events;
 	unsigned long			last_overrun;
 	local_t				entries_bytes;
-	local_t				commit_overrun;
-	local_t				overrun;
 	local_t				entries;
+	local_t				overrun;
+	local_t				commit_overrun;
+	local_t				dropped_events;
 	local_t				committing;
 	local_t				commits;
 	unsigned long			read;
@@ -1820,7 +1821,7 @@ rb_add_time_stamp(struct ring_buffer_event *event, u64 delta)
 }
 
 /**
- * ring_buffer_update_event - update event type and data
+ * rb_update_event - update event type and data
  * @event: the even to update
  * @type: the type of event
  * @length: the size of the event field in the ring buffer
@@ -2155,8 +2156,10 @@ rb_move_tail(struct ring_buffer_per_cpu *cpu_buffer,
 			 * If we are not in overwrite mode,
 			 * this is easy, just stop here.
 			 */
-			if (!(buffer->flags & RB_FL_OVERWRITE))
+			if (!(buffer->flags & RB_FL_OVERWRITE)) {
+				local_inc(&cpu_buffer->dropped_events);
 				goto out_reset;
+			}
 
 			ret = rb_handle_head_page(cpu_buffer,
 						  tail_page,
@@ -2720,8 +2723,8 @@ EXPORT_SYMBOL_GPL(ring_buffer_discard_commit);
  * and not the length of the event which would hold the header.
  */
 int ring_buffer_write(struct ring_buffer *buffer,
-			unsigned long length,
-			void *data)
+		      unsigned long length,
+		      void *data)
 {
 	struct ring_buffer_per_cpu *cpu_buffer;
 	struct ring_buffer_event *event;
@@ -2929,12 +2932,12 @@ rb_num_of_entries(struct ring_buffer_per_cpu *cpu_buffer)
  * @buffer: The ring buffer
  * @cpu: The per CPU buffer to read from.
  */
-unsigned long ring_buffer_oldest_event_ts(struct ring_buffer *buffer, int cpu)
+u64 ring_buffer_oldest_event_ts(struct ring_buffer *buffer, int cpu)
 {
 	unsigned long flags;
 	struct ring_buffer_per_cpu *cpu_buffer;
 	struct buffer_page *bpage;
-	unsigned long ret;
+	u64 ret;
 
 	if (!cpumask_test_cpu(cpu, buffer->cpumask))
 		return 0;
@@ -2995,7 +2998,8 @@ unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu)
 EXPORT_SYMBOL_GPL(ring_buffer_entries_cpu);
 
 /**
- * ring_buffer_overrun_cpu - get the number of overruns in a cpu_buffer
+ * ring_buffer_overrun_cpu - get the number of overruns caused by the ring
+ * buffer wrapping around (only if RB_FL_OVERWRITE is on).
  * @buffer: The ring buffer
  * @cpu: The per CPU buffer to get the number of overruns from
  */
@@ -3015,7 +3019,9 @@ unsigned long ring_buffer_overrun_cpu(struct ring_buffer *buffer, int cpu)
 EXPORT_SYMBOL_GPL(ring_buffer_overrun_cpu);
 
 /**
- * ring_buffer_commit_overrun_cpu - get the number of overruns caused by commits
+ * ring_buffer_commit_overrun_cpu - get the number of overruns caused by
+ * commits failing due to the buffer wrapping around while there are uncommitted
+ * events, such as during an interrupt storm.
  * @buffer: The ring buffer
  * @cpu: The per CPU buffer to get the number of overruns from
  */
@@ -3036,6 +3042,28 @@ ring_buffer_commit_overrun_cpu(struct ring_buffer *buffer, int cpu)
 EXPORT_SYMBOL_GPL(ring_buffer_commit_overrun_cpu);
 
 /**
+ * ring_buffer_dropped_events_cpu - get the number of dropped events caused by
+ * the ring buffer filling up (only if RB_FL_OVERWRITE is off).
+ * @buffer: The ring buffer
+ * @cpu: The per CPU buffer to get the number of overruns from
+ */
+unsigned long
+ring_buffer_dropped_events_cpu(struct ring_buffer *buffer, int cpu)
+{
+	struct ring_buffer_per_cpu *cpu_buffer;
+	unsigned long ret;
+
+	if (!cpumask_test_cpu(cpu, buffer->cpumask))
+		return 0;
+
+	cpu_buffer = buffer->buffers[cpu];
+	ret = local_read(&cpu_buffer->dropped_events);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ring_buffer_dropped_events_cpu);
+
+/**
  * ring_buffer_entries - get the number of entries in a buffer
  * @buffer: The ring buffer
  *
@@ -3864,9 +3892,10 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer)
 	local_set(&cpu_buffer->reader_page->page->commit, 0);
 	cpu_buffer->reader_page->read = 0;
 
-	local_set(&cpu_buffer->commit_overrun, 0);
 	local_set(&cpu_buffer->entries_bytes, 0);
 	local_set(&cpu_buffer->overrun, 0);
+	local_set(&cpu_buffer->commit_overrun, 0);
+	local_set(&cpu_buffer->dropped_events, 0);
 	local_set(&cpu_buffer->entries, 0);
 	local_set(&cpu_buffer->committing, 0);
 	local_set(&cpu_buffer->commits, 0);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 31e4f55..5bc3590 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -19,6 +19,7 @@
 #include <linux/seq_file.h>
 #include <linux/notifier.h>
 #include <linux/irqflags.h>
+#include <linux/irq_work.h>
 #include <linux/debugfs.h>
 #include <linux/pagemap.h>
 #include <linux/hardirq.h>
@@ -78,6 +79,21 @@ static int dummy_set_flag(u32 old_flags, u32 bit, int set)
 }
 
 /*
+ * To prevent the comm cache from being overwritten when no
+ * tracing is active, only save the comm when a trace event
+ * occurred.
+ */
+static DEFINE_PER_CPU(bool, trace_cmdline_save);
+
+/*
+ * When a reader is waiting for data, then this variable is
+ * set to true.
+ */
+static bool trace_wakeup_needed;
+
+static struct irq_work trace_work_wakeup;
+
+/*
  * Kill all tracing for good (never come back).
  * It is initialized to 1 but will turn to zero if the initialization
  * of the tracer is successful. But that is the only place that sets
@@ -139,6 +155,18 @@ static int __init set_ftrace_dump_on_oops(char *str)
 }
 __setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops);
 
+
+static char trace_boot_options_buf[MAX_TRACER_SIZE] __initdata;
+static char *trace_boot_options __initdata;
+
+static int __init set_trace_boot_options(char *str)
+{
+	strncpy(trace_boot_options_buf, str, MAX_TRACER_SIZE);
+	trace_boot_options = trace_boot_options_buf;
+	return 0;
+}
+__setup("trace_options=", set_trace_boot_options);
+
 unsigned long long ns2usecs(cycle_t nsec)
 {
 	nsec += 500;
@@ -198,20 +226,9 @@ static struct trace_array	max_tr;
 
 static DEFINE_PER_CPU(struct trace_array_cpu, max_tr_data);
 
-/* tracer_enabled is used to toggle activation of a tracer */
-static int			tracer_enabled = 1;
-
-/**
- * tracing_is_enabled - return tracer_enabled status
- *
- * This function is used by other tracers to know the status
- * of the tracer_enabled flag.  Tracers may use this function
- * to know if it should enable their features when starting
- * up. See irqsoff tracer for an example (start_irqsoff_tracer).
- */
 int tracing_is_enabled(void)
 {
-	return tracer_enabled;
+	return tracing_is_on();
 }
 
 /*
@@ -333,12 +350,18 @@ unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK |
 static int trace_stop_count;
 static DEFINE_RAW_SPINLOCK(tracing_start_lock);
 
-static void wakeup_work_handler(struct work_struct *work)
+/**
+ * trace_wake_up - wake up tasks waiting for trace input
+ *
+ * Schedules a delayed work to wake up any task that is blocked on the
+ * trace_wait queue. These is used with trace_poll for tasks polling the
+ * trace.
+ */
+static void trace_wake_up(struct irq_work *work)
 {
-	wake_up(&trace_wait);
-}
+	wake_up_all(&trace_wait);
 
-static DECLARE_DELAYED_WORK(wakeup_work, wakeup_work_handler);
+}
 
 /**
  * tracing_on - enable tracing buffers
@@ -393,22 +416,6 @@ int tracing_is_on(void)
 }
 EXPORT_SYMBOL_GPL(tracing_is_on);
 
-/**
- * trace_wake_up - wake up tasks waiting for trace input
- *
- * Schedules a delayed work to wake up any task that is blocked on the
- * trace_wait queue. These is used with trace_poll for tasks polling the
- * trace.
- */
-void trace_wake_up(void)
-{
-	const unsigned long delay = msecs_to_jiffies(2);
-
-	if (trace_flags & TRACE_ITER_BLOCK)
-		return;
-	schedule_delayed_work(&wakeup_work, delay);
-}
-
 static int __init set_buf_size(char *str)
 {
 	unsigned long buf_size;
@@ -431,7 +438,7 @@ static int __init set_tracing_thresh(char *str)
 
 	if (!str)
 		return 0;
-	ret = strict_strtoul(str, 0, &threshold);
+	ret = kstrtoul(str, 0, &threshold);
 	if (ret < 0)
 		return 0;
 	tracing_thresh = threshold * 1000;
@@ -477,10 +484,12 @@ static const char *trace_options[] = {
 static struct {
 	u64 (*func)(void);
 	const char *name;
+	int in_ns;		/* is this clock in nanoseconds? */
 } trace_clocks[] = {
-	{ trace_clock_local,	"local" },
-	{ trace_clock_global,	"global" },
-	{ trace_clock_counter,	"counter" },
+	{ trace_clock_local,	"local",	1 },
+	{ trace_clock_global,	"global",	1 },
+	{ trace_clock_counter,	"counter",	0 },
+	ARCH_TRACE_CLOCKS
 };
 
 int trace_clock_id;
@@ -757,6 +766,40 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
 }
 #endif /* CONFIG_TRACER_MAX_TRACE */
 
+static void default_wait_pipe(struct trace_iterator *iter)
+{
+	DEFINE_WAIT(wait);
+
+	prepare_to_wait(&trace_wait, &wait, TASK_INTERRUPTIBLE);
+
+	/*
+	 * The events can happen in critical sections where
+	 * checking a work queue can cause deadlocks.
+	 * After adding a task to the queue, this flag is set
+	 * only to notify events to try to wake up the queue
+	 * using irq_work.
+	 *
+	 * We don't clear it even if the buffer is no longer
+	 * empty. The flag only causes the next event to run
+	 * irq_work to do the work queue wake up. The worse
+	 * that can happen if we race with !trace_empty() is that
+	 * an event will cause an irq_work to try to wake up
+	 * an empty queue.
+	 *
+	 * There's no reason to protect this flag either, as
+	 * the work queue and irq_work logic will do the necessary
+	 * synchronization for the wake ups. The only thing
+	 * that is necessary is that the wake up happens after
+	 * a task has been queued. It's OK for spurious wake ups.
+	 */
+	trace_wakeup_needed = true;
+
+	if (trace_empty(iter))
+		schedule();
+
+	finish_wait(&trace_wait, &wait);
+}
+
 /**
  * register_tracer - register a tracer with the ftrace system.
  * @type - the plugin for the tracer
@@ -875,32 +918,6 @@ int register_tracer(struct tracer *type)
 	return ret;
 }
 
-void unregister_tracer(struct tracer *type)
-{
-	struct tracer **t;
-
-	mutex_lock(&trace_types_lock);
-	for (t = &trace_types; *t; t = &(*t)->next) {
-		if (*t == type)
-			goto found;
-	}
-	pr_info("Tracer %s not registered\n", type->name);
-	goto out;
-
- found:
-	*t = (*t)->next;
-
-	if (type == current_trace && tracer_enabled) {
-		tracer_enabled = 0;
-		tracing_stop();
-		if (current_trace->stop)
-			current_trace->stop(&global_trace);
-		current_trace = &nop_trace;
-	}
-out:
-	mutex_unlock(&trace_types_lock);
-}
-
 void tracing_reset(struct trace_array *tr, int cpu)
 {
 	struct ring_buffer *buffer = tr->buffer;
@@ -1131,10 +1148,14 @@ void trace_find_cmdline(int pid, char comm[])
 
 void tracing_record_cmdline(struct task_struct *tsk)
 {
-	if (atomic_read(&trace_record_cmdline_disabled) || !tracer_enabled ||
-	    !tracing_is_on())
+	if (atomic_read(&trace_record_cmdline_disabled) || !tracing_is_on())
 		return;
 
+	if (!__this_cpu_read(trace_cmdline_save))
+		return;
+
+	__this_cpu_write(trace_cmdline_save, false);
+
 	trace_save_cmdline(tsk);
 }
 
@@ -1178,27 +1199,36 @@ trace_buffer_lock_reserve(struct ring_buffer *buffer,
 	return event;
 }
 
+void
+__buffer_unlock_commit(struct ring_buffer *buffer, struct ring_buffer_event *event)
+{
+	__this_cpu_write(trace_cmdline_save, true);
+	if (trace_wakeup_needed) {
+		trace_wakeup_needed = false;
+		/* irq_work_queue() supplies it's own memory barriers */
+		irq_work_queue(&trace_work_wakeup);
+	}
+	ring_buffer_unlock_commit(buffer, event);
+}
+
 static inline void
 __trace_buffer_unlock_commit(struct ring_buffer *buffer,
 			     struct ring_buffer_event *event,
-			     unsigned long flags, int pc,
-			     int wake)
+			     unsigned long flags, int pc)
 {
-	ring_buffer_unlock_commit(buffer, event);
+	__buffer_unlock_commit(buffer, event);
 
 	ftrace_trace_stack(buffer, flags, 6, pc);
 	ftrace_trace_userstack(buffer, flags, pc);
-
-	if (wake)
-		trace_wake_up();
 }
 
 void trace_buffer_unlock_commit(struct ring_buffer *buffer,
 				struct ring_buffer_event *event,
 				unsigned long flags, int pc)
 {
-	__trace_buffer_unlock_commit(buffer, event, flags, pc, 1);
+	__trace_buffer_unlock_commit(buffer, event, flags, pc);
 }
+EXPORT_SYMBOL_GPL(trace_buffer_unlock_commit);
 
 struct ring_buffer_event *
 trace_current_buffer_lock_reserve(struct ring_buffer **current_rb,
@@ -1215,29 +1245,21 @@ void trace_current_buffer_unlock_commit(struct ring_buffer *buffer,
 					struct ring_buffer_event *event,
 					unsigned long flags, int pc)
 {
-	__trace_buffer_unlock_commit(buffer, event, flags, pc, 1);
+	__trace_buffer_unlock_commit(buffer, event, flags, pc);
 }
 EXPORT_SYMBOL_GPL(trace_current_buffer_unlock_commit);
 
-void trace_nowake_buffer_unlock_commit(struct ring_buffer *buffer,
-				       struct ring_buffer_event *event,
-				       unsigned long flags, int pc)
+void trace_buffer_unlock_commit_regs(struct ring_buffer *buffer,
+				     struct ring_buffer_event *event,
+				     unsigned long flags, int pc,
+				     struct pt_regs *regs)
 {
-	__trace_buffer_unlock_commit(buffer, event, flags, pc, 0);
-}
-EXPORT_SYMBOL_GPL(trace_nowake_buffer_unlock_commit);
-
-void trace_nowake_buffer_unlock_commit_regs(struct ring_buffer *buffer,
-					    struct ring_buffer_event *event,
-					    unsigned long flags, int pc,
-					    struct pt_regs *regs)
-{
-	ring_buffer_unlock_commit(buffer, event);
+	__buffer_unlock_commit(buffer, event);
 
 	ftrace_trace_stack_regs(buffer, flags, 0, pc, regs);
 	ftrace_trace_userstack(buffer, flags, pc);
 }
-EXPORT_SYMBOL_GPL(trace_nowake_buffer_unlock_commit_regs);
+EXPORT_SYMBOL_GPL(trace_buffer_unlock_commit_regs);
 
 void trace_current_buffer_discard_commit(struct ring_buffer *buffer,
 					 struct ring_buffer_event *event)
@@ -1269,7 +1291,7 @@ trace_function(struct trace_array *tr,
 	entry->parent_ip		= parent_ip;
 
 	if (!filter_check_discard(call, entry, buffer, event))
-		ring_buffer_unlock_commit(buffer, event);
+		__buffer_unlock_commit(buffer, event);
 }
 
 void
@@ -1362,7 +1384,7 @@ static void __ftrace_trace_stack(struct ring_buffer *buffer,
 	entry->size = trace.nr_entries;
 
 	if (!filter_check_discard(call, entry, buffer, event))
-		ring_buffer_unlock_commit(buffer, event);
+		__buffer_unlock_commit(buffer, event);
 
  out:
 	/* Again, don't let gcc optimize things here */
@@ -1458,7 +1480,7 @@ ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc)
 
 	save_stack_trace_user(&trace);
 	if (!filter_check_discard(call, entry, buffer, event))
-		ring_buffer_unlock_commit(buffer, event);
+		__buffer_unlock_commit(buffer, event);
 
  out_drop_count:
 	__this_cpu_dec(user_stack_count);
@@ -1559,10 +1581,10 @@ static int alloc_percpu_trace_buffer(void)
 	return -ENOMEM;
 }
 
+static int buffers_allocated;
+
 void trace_printk_init_buffers(void)
 {
-	static int buffers_allocated;
-
 	if (buffers_allocated)
 		return;
 
@@ -1571,7 +1593,38 @@ void trace_printk_init_buffers(void)
 
 	pr_info("ftrace: Allocated trace_printk buffers\n");
 
+	/* Expand the buffers to set size */
+	tracing_update_buffers();
+
 	buffers_allocated = 1;
+
+	/*
+	 * trace_printk_init_buffers() can be called by modules.
+	 * If that happens, then we need to start cmdline recording
+	 * directly here. If the global_trace.buffer is already
+	 * allocated here, then this was called by module code.
+	 */
+	if (global_trace.buffer)
+		tracing_start_cmdline_record();
+}
+
+void trace_printk_start_comm(void)
+{
+	/* Start tracing comms if trace printk is set */
+	if (!buffers_allocated)
+		return;
+	tracing_start_cmdline_record();
+}
+
+static void trace_printk_start_stop_comm(int enabled)
+{
+	if (!buffers_allocated)
+		return;
+
+	if (enabled)
+		tracing_start_cmdline_record();
+	else
+		tracing_stop_cmdline_record();
 }
 
 /**
@@ -1622,7 +1675,7 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
 
 	memcpy(entry->buf, tbuffer, sizeof(u32) * len);
 	if (!filter_check_discard(call, entry, buffer, event)) {
-		ring_buffer_unlock_commit(buffer, event);
+		__buffer_unlock_commit(buffer, event);
 		ftrace_trace_stack(buffer, flags, 6, pc);
 	}
 
@@ -1693,7 +1746,7 @@ int trace_array_vprintk(struct trace_array *tr,
 	memcpy(&entry->buf, tbuffer, len);
 	entry->buf[len] = '\0';
 	if (!filter_check_discard(call, entry, buffer, event)) {
-		ring_buffer_unlock_commit(buffer, event);
+		__buffer_unlock_commit(buffer, event);
 		ftrace_trace_stack(buffer, flags, 6, pc);
 	}
  out:
@@ -2426,6 +2479,10 @@ __tracing_open(struct inode *inode, struct file *file)
 	if (ring_buffer_overruns(iter->tr->buffer))
 		iter->iter_flags |= TRACE_FILE_ANNOTATE;
 
+	/* Output in nanoseconds only if we are using a clock in nanoseconds. */
+	if (trace_clocks[trace_clock_id].in_ns)
+		iter->iter_flags |= TRACE_FILE_TIME_IN_NS;
+
 	/* stop the trace while dumping */
 	tracing_stop();
 
@@ -2794,26 +2851,19 @@ static void set_tracer_flags(unsigned int mask, int enabled)
 
 	if (mask == TRACE_ITER_OVERWRITE)
 		ring_buffer_change_overwrite(global_trace.buffer, enabled);
+
+	if (mask == TRACE_ITER_PRINTK)
+		trace_printk_start_stop_comm(enabled);
 }
 
-static ssize_t
-tracing_trace_options_write(struct file *filp, const char __user *ubuf,
-			size_t cnt, loff_t *ppos)
+static int trace_set_options(char *option)
 {
-	char buf[64];
 	char *cmp;
 	int neg = 0;
-	int ret;
+	int ret = 0;
 	int i;
 
-	if (cnt >= sizeof(buf))
-		return -EINVAL;
-
-	if (copy_from_user(&buf, ubuf, cnt))
-		return -EFAULT;
-
-	buf[cnt] = 0;
-	cmp = strstrip(buf);
+	cmp = strstrip(option);
 
 	if (strncmp(cmp, "no", 2) == 0) {
 		neg = 1;
@@ -2832,10 +2882,25 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
 		mutex_lock(&trace_types_lock);
 		ret = set_tracer_option(current_trace, cmp, neg);
 		mutex_unlock(&trace_types_lock);
-		if (ret)
-			return ret;
 	}
 
+	return ret;
+}
+
+static ssize_t
+tracing_trace_options_write(struct file *filp, const char __user *ubuf,
+			size_t cnt, loff_t *ppos)
+{
+	char buf[64];
+
+	if (cnt >= sizeof(buf))
+		return -EINVAL;
+
+	if (copy_from_user(&buf, ubuf, cnt))
+		return -EFAULT;
+
+	trace_set_options(buf);
+
 	*ppos += cnt;
 
 	return cnt;
@@ -2940,56 +3005,6 @@ static const struct file_operations tracing_saved_cmdlines_fops = {
 };
 
 static ssize_t
-tracing_ctrl_read(struct file *filp, char __user *ubuf,
-		  size_t cnt, loff_t *ppos)
-{
-	char buf[64];
-	int r;
-
-	r = sprintf(buf, "%u\n", tracer_enabled);
-	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
-}
-
-static ssize_t
-tracing_ctrl_write(struct file *filp, const char __user *ubuf,
-		   size_t cnt, loff_t *ppos)
-{
-	struct trace_array *tr = filp->private_data;
-	unsigned long val;
-	int ret;
-
-	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
-	if (ret)
-		return ret;
-
-	val = !!val;
-
-	mutex_lock(&trace_types_lock);
-	if (tracer_enabled ^ val) {
-
-		/* Only need to warn if this is used to change the state */
-		WARN_ONCE(1, "tracing_enabled is deprecated. Use tracing_on");
-
-		if (val) {
-			tracer_enabled = 1;
-			if (current_trace->start)
-				current_trace->start(tr);
-			tracing_start();
-		} else {
-			tracer_enabled = 0;
-			tracing_stop();
-			if (current_trace->stop)
-				current_trace->stop(tr);
-		}
-	}
-	mutex_unlock(&trace_types_lock);
-
-	*ppos += cnt;
-
-	return cnt;
-}
-
-static ssize_t
 tracing_set_trace_read(struct file *filp, char __user *ubuf,
 		       size_t cnt, loff_t *ppos)
 {
@@ -3019,6 +3034,31 @@ static void set_buffer_entries(struct trace_array *tr, unsigned long val)
 		tr->data[cpu]->entries = val;
 }
 
+/* resize @tr's buffer to the size of @size_tr's entries */
+static int resize_buffer_duplicate_size(struct trace_array *tr,
+					struct trace_array *size_tr, int cpu_id)
+{
+	int cpu, ret = 0;
+
+	if (cpu_id == RING_BUFFER_ALL_CPUS) {
+		for_each_tracing_cpu(cpu) {
+			ret = ring_buffer_resize(tr->buffer,
+					size_tr->data[cpu]->entries, cpu);
+			if (ret < 0)
+				break;
+			tr->data[cpu]->entries = size_tr->data[cpu]->entries;
+		}
+	} else {
+		ret = ring_buffer_resize(tr->buffer,
+					size_tr->data[cpu_id]->entries, cpu_id);
+		if (ret == 0)
+			tr->data[cpu_id]->entries =
+				size_tr->data[cpu_id]->entries;
+	}
+
+	return ret;
+}
+
 static int __tracing_resize_ring_buffer(unsigned long size, int cpu)
 {
 	int ret;
@@ -3030,6 +3070,10 @@ static int __tracing_resize_ring_buffer(unsigned long size, int cpu)
 	 */
 	ring_buffer_expanded = 1;
 
+	/* May be called before buffers are initialized */
+	if (!global_trace.buffer)
+		return 0;
+
 	ret = ring_buffer_resize(global_trace.buffer, size, cpu);
 	if (ret < 0)
 		return ret;
@@ -3039,23 +3083,8 @@ static int __tracing_resize_ring_buffer(unsigned long size, int cpu)
 
 	ret = ring_buffer_resize(max_tr.buffer, size, cpu);
 	if (ret < 0) {
-		int r = 0;
-
-		if (cpu == RING_BUFFER_ALL_CPUS) {
-			int i;
-			for_each_tracing_cpu(i) {
-				r = ring_buffer_resize(global_trace.buffer,
-						global_trace.data[i]->entries,
-						i);
-				if (r < 0)
-					break;
-			}
-		} else {
-			r = ring_buffer_resize(global_trace.buffer,
-						global_trace.data[cpu]->entries,
-						cpu);
-		}
-
+		int r = resize_buffer_duplicate_size(&global_trace,
+						     &global_trace, cpu);
 		if (r < 0) {
 			/*
 			 * AARGH! We are left with different
@@ -3193,17 +3222,11 @@ static int tracing_set_tracer(const char *buf)
 
 	topts = create_trace_option_files(t);
 	if (t->use_max_tr) {
-		int cpu;
 		/* we need to make per cpu buffer sizes equivalent */
-		for_each_tracing_cpu(cpu) {
-			ret = ring_buffer_resize(max_tr.buffer,
-						global_trace.data[cpu]->entries,
-						cpu);
-			if (ret < 0)
-				goto out;
-			max_tr.data[cpu]->entries =
-					global_trace.data[cpu]->entries;
-		}
+		ret = resize_buffer_duplicate_size(&max_tr, &global_trace,
+						   RING_BUFFER_ALL_CPUS);
+		if (ret < 0)
+			goto out;
 	}
 
 	if (t->init) {
@@ -3325,6 +3348,10 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
 	if (trace_flags & TRACE_ITER_LATENCY_FMT)
 		iter->iter_flags |= TRACE_FILE_LAT_FMT;
 
+	/* Output in nanoseconds only if we are using a clock in nanoseconds. */
+	if (trace_clocks[trace_clock_id].in_ns)
+		iter->iter_flags |= TRACE_FILE_TIME_IN_NS;
+
 	iter->cpu_file = cpu_file;
 	iter->tr = &global_trace;
 	mutex_init(&iter->mutex);
@@ -3385,19 +3412,6 @@ tracing_poll_pipe(struct file *filp, poll_table *poll_table)
 	}
 }
 
-
-void default_wait_pipe(struct trace_iterator *iter)
-{
-	DEFINE_WAIT(wait);
-
-	prepare_to_wait(&trace_wait, &wait, TASK_INTERRUPTIBLE);
-
-	if (trace_empty(iter))
-		schedule();
-
-	finish_wait(&trace_wait, &wait);
-}
-
 /*
  * This is a make-shift waitqueue.
  * A tracer might use this callback on some rare cases:
@@ -3438,7 +3452,7 @@ static int tracing_wait_pipe(struct file *filp)
 			return -EINTR;
 
 		/*
-		 * We block until we read something and tracing is disabled.
+		 * We block until we read something and tracing is enabled.
 		 * We still block if tracing is disabled, but we have never
 		 * read anything. This allows a user to cat this file, and
 		 * then enable tracing. But after we have read something,
@@ -3446,7 +3460,7 @@ static int tracing_wait_pipe(struct file *filp)
 		 *
 		 * iter->pos will be 0 if we haven't read anything.
 		 */
-		if (!tracer_enabled && iter->pos)
+		if (tracing_is_enabled() && iter->pos)
 			break;
 	}
 
@@ -3955,7 +3969,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
 	} else
 		entry->buf[cnt] = '\0';
 
-	ring_buffer_unlock_commit(buffer, event);
+	__buffer_unlock_commit(buffer, event);
 
 	written = cnt;
 
@@ -4016,6 +4030,14 @@ static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
 	if (max_tr.buffer)
 		ring_buffer_set_clock(max_tr.buffer, trace_clocks[i].func);
 
+	/*
+	 * New clock may not be consistent with the previous clock.
+	 * Reset the buffer so that it doesn't have incomparable timestamps.
+	 */
+	tracing_reset_online_cpus(&global_trace);
+	if (max_tr.buffer)
+		tracing_reset_online_cpus(&max_tr);
+
 	mutex_unlock(&trace_types_lock);
 
 	*fpos += cnt;
@@ -4037,13 +4059,6 @@ static const struct file_operations tracing_max_lat_fops = {
 	.llseek		= generic_file_llseek,
 };
 
-static const struct file_operations tracing_ctrl_fops = {
-	.open		= tracing_open_generic,
-	.read		= tracing_ctrl_read,
-	.write		= tracing_ctrl_write,
-	.llseek		= generic_file_llseek,
-};
-
 static const struct file_operations set_tracer_fops = {
 	.open		= tracing_open_generic,
 	.read		= tracing_set_trace_read,
@@ -4260,13 +4275,11 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
 		return -ENOMEM;
 
 	if (*ppos & (PAGE_SIZE - 1)) {
-		WARN_ONCE(1, "Ftrace: previous read must page-align\n");
 		ret = -EINVAL;
 		goto out;
 	}
 
 	if (len & (PAGE_SIZE - 1)) {
-		WARN_ONCE(1, "Ftrace: splice_read should page-align\n");
 		if (len < PAGE_SIZE) {
 			ret = -EINVAL;
 			goto out;
@@ -4377,13 +4390,27 @@ tracing_stats_read(struct file *filp, char __user *ubuf,
 	cnt = ring_buffer_bytes_cpu(tr->buffer, cpu);
 	trace_seq_printf(s, "bytes: %ld\n", cnt);
 
-	t = ns2usecs(ring_buffer_oldest_event_ts(tr->buffer, cpu));
-	usec_rem = do_div(t, USEC_PER_SEC);
-	trace_seq_printf(s, "oldest event ts: %5llu.%06lu\n", t, usec_rem);
+	if (trace_clocks[trace_clock_id].in_ns) {
+		/* local or global for trace_clock */
+		t = ns2usecs(ring_buffer_oldest_event_ts(tr->buffer, cpu));
+		usec_rem = do_div(t, USEC_PER_SEC);
+		trace_seq_printf(s, "oldest event ts: %5llu.%06lu\n",
+								t, usec_rem);
 
-	t = ns2usecs(ring_buffer_time_stamp(tr->buffer, cpu));
-	usec_rem = do_div(t, USEC_PER_SEC);
-	trace_seq_printf(s, "now ts: %5llu.%06lu\n", t, usec_rem);
+		t = ns2usecs(ring_buffer_time_stamp(tr->buffer, cpu));
+		usec_rem = do_div(t, USEC_PER_SEC);
+		trace_seq_printf(s, "now ts: %5llu.%06lu\n", t, usec_rem);
+	} else {
+		/* counter or tsc mode for trace_clock */
+		trace_seq_printf(s, "oldest event ts: %llu\n",
+				ring_buffer_oldest_event_ts(tr->buffer, cpu));
+
+		trace_seq_printf(s, "now ts: %llu\n",
+				ring_buffer_time_stamp(tr->buffer, cpu));
+	}
+
+	cnt = ring_buffer_dropped_events_cpu(tr->buffer, cpu);
+	trace_seq_printf(s, "dropped events: %ld\n", cnt);
 
 	count = simple_read_from_buffer(ubuf, count, ppos, s->buffer, s->len);
 
@@ -4815,9 +4842,6 @@ static __init int tracer_init_debugfs(void)
 
 	d_tracer = tracing_init_dentry();
 
-	trace_create_file("tracing_enabled", 0644, d_tracer,
-			&global_trace, &tracing_ctrl_fops);
-
 	trace_create_file("trace_options", 0644, d_tracer,
 			NULL, &tracing_iter_fops);
 
@@ -5089,6 +5113,7 @@ __init static int tracer_alloc_buffers(void)
 
 	/* Only allocate trace_printk buffers if a trace_printk exists */
 	if (__stop___trace_bprintk_fmt != __start___trace_bprintk_fmt)
+		/* Must be called before global_trace.buffer is allocated */
 		trace_printk_init_buffers();
 
 	/* To save memory, keep the ring buffer size to its minimum */
@@ -5136,6 +5161,7 @@ __init static int tracer_alloc_buffers(void)
 #endif
 
 	trace_init_cmdlines();
+	init_irq_work(&trace_work_wakeup, trace_wake_up);
 
 	register_tracer(&nop_trace);
 	current_trace = &nop_trace;
@@ -5147,6 +5173,13 @@ __init static int tracer_alloc_buffers(void)
 
 	register_die_notifier(&trace_die_notifier);
 
+	while (trace_boot_options) {
+		char *option;
+
+		option = strsep(&trace_boot_options, ",");
+		trace_set_options(option);
+	}
+
 	return 0;
 
 out_free_cpumask:
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index c15f528..c75d798 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -285,8 +285,8 @@ struct tracer {
 	int			(*set_flag)(u32 old_flags, u32 bit, int set);
 	struct tracer		*next;
 	struct tracer_flags	*flags;
-	int			print_max;
-	int			use_max_tr;
+	bool			print_max;
+	bool			use_max_tr;
 };
 
 
@@ -327,7 +327,6 @@ trace_buffer_iter(struct trace_iterator *iter, int cpu)
 
 int tracer_init(struct tracer *t, struct trace_array *tr);
 int tracing_is_enabled(void);
-void trace_wake_up(void);
 void tracing_reset(struct trace_array *tr, int cpu);
 void tracing_reset_online_cpus(struct trace_array *tr);
 void tracing_reset_current(int cpu);
@@ -349,9 +348,6 @@ trace_buffer_lock_reserve(struct ring_buffer *buffer,
 			  unsigned long len,
 			  unsigned long flags,
 			  int pc);
-void trace_buffer_unlock_commit(struct ring_buffer *buffer,
-				struct ring_buffer_event *event,
-				unsigned long flags, int pc);
 
 struct trace_entry *tracing_get_trace_entry(struct trace_array *tr,
 						struct trace_array_cpu *data);
@@ -359,6 +355,9 @@ struct trace_entry *tracing_get_trace_entry(struct trace_array *tr,
 struct trace_entry *trace_find_next_entry(struct trace_iterator *iter,
 					  int *ent_cpu, u64 *ent_ts);
 
+void __buffer_unlock_commit(struct ring_buffer *buffer,
+			    struct ring_buffer_event *event);
+
 int trace_empty(struct trace_iterator *iter);
 
 void *trace_find_next_entry_inc(struct trace_iterator *iter);
@@ -367,7 +366,6 @@ void trace_init_global_iter(struct trace_iterator *iter);
 
 void tracing_iter_reset(struct trace_iterator *iter, int cpu);
 
-void default_wait_pipe(struct trace_iterator *iter);
 void poll_wait_pipe(struct trace_iterator *iter);
 
 void ftrace(struct trace_array *tr,
@@ -407,12 +405,7 @@ void tracing_sched_switch_assign_trace(struct trace_array *tr);
 void tracing_stop_sched_switch_record(void);
 void tracing_start_sched_switch_record(void);
 int register_tracer(struct tracer *type);
-void unregister_tracer(struct tracer *type);
 int is_tracing_stopped(void);
-enum trace_file_type {
-	TRACE_FILE_LAT_FMT	= 1,
-	TRACE_FILE_ANNOTATE	= 2,
-};
 
 extern cpumask_var_t __read_mostly tracing_buffer_mask;
 
@@ -841,6 +834,7 @@ extern const char *__start___trace_bprintk_fmt[];
 extern const char *__stop___trace_bprintk_fmt[];
 
 void trace_printk_init_buffers(void);
+void trace_printk_start_comm(void);
 
 #undef FTRACE_ENTRY
 #define FTRACE_ENTRY(call, struct_name, id, tstruct, print, filter)	\
diff --git a/kernel/trace/trace_branch.c b/kernel/trace/trace_branch.c
index 8d3538b..95e9684 100644
--- a/kernel/trace/trace_branch.c
+++ b/kernel/trace/trace_branch.c
@@ -77,7 +77,7 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect)
 	entry->correct = val == expect;
 
 	if (!filter_check_discard(call, entry, buffer, event))
-		ring_buffer_unlock_commit(buffer, event);
+		__buffer_unlock_commit(buffer, event);
 
  out:
 	atomic_dec(&tr->data[cpu]->disabled);
@@ -199,7 +199,7 @@ __init static int init_branch_tracer(void)
 	}
 	return register_tracer(&branch_trace);
 }
-device_initcall(init_branch_tracer);
+core_initcall(init_branch_tracer);
 
 #else
 static inline
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index d608d09..880073d 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -491,19 +491,6 @@ static void t_stop(struct seq_file *m, void *p)
 	mutex_unlock(&event_mutex);
 }
 
-static int
-ftrace_event_seq_open(struct inode *inode, struct file *file)
-{
-	const struct seq_operations *seq_ops;
-
-	if ((file->f_mode & FMODE_WRITE) &&
-	    (file->f_flags & O_TRUNC))
-		ftrace_clear_events();
-
-	seq_ops = inode->i_private;
-	return seq_open(file, seq_ops);
-}
-
 static ssize_t
 event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
 		  loff_t *ppos)
@@ -980,6 +967,9 @@ show_header(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
 	return r;
 }
 
+static int ftrace_event_avail_open(struct inode *inode, struct file *file);
+static int ftrace_event_set_open(struct inode *inode, struct file *file);
+
 static const struct seq_operations show_event_seq_ops = {
 	.start = t_start,
 	.next = t_next,
@@ -995,14 +985,14 @@ static const struct seq_operations show_set_event_seq_ops = {
 };
 
 static const struct file_operations ftrace_avail_fops = {
-	.open = ftrace_event_seq_open,
+	.open = ftrace_event_avail_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = seq_release,
 };
 
 static const struct file_operations ftrace_set_event_fops = {
-	.open = ftrace_event_seq_open,
+	.open = ftrace_event_set_open,
 	.read = seq_read,
 	.write = ftrace_event_write,
 	.llseek = seq_lseek,
@@ -1078,6 +1068,26 @@ static struct dentry *event_trace_events_dir(void)
 	return d_events;
 }
 
+static int
+ftrace_event_avail_open(struct inode *inode, struct file *file)
+{
+	const struct seq_operations *seq_ops = &show_event_seq_ops;
+
+	return seq_open(file, seq_ops);
+}
+
+static int
+ftrace_event_set_open(struct inode *inode, struct file *file)
+{
+	const struct seq_operations *seq_ops = &show_set_event_seq_ops;
+
+	if ((file->f_mode & FMODE_WRITE) &&
+	    (file->f_flags & O_TRUNC))
+		ftrace_clear_events();
+
+	return seq_open(file, seq_ops);
+}
+
 static struct dentry *
 event_subsystem_dir(const char *name, struct dentry *d_events)
 {
@@ -1489,6 +1499,9 @@ static __init int event_trace_enable(void)
 		if (ret)
 			pr_warn("Failed to enable trace event: %s\n", token);
 	}
+
+	trace_printk_start_comm();
+
 	return 0;
 }
 
@@ -1505,15 +1518,13 @@ static __init int event_trace_init(void)
 		return 0;
 
 	entry = debugfs_create_file("available_events", 0444, d_tracer,
-				    (void *)&show_event_seq_ops,
-				    &ftrace_avail_fops);
+				    NULL, &ftrace_avail_fops);
 	if (!entry)
 		pr_warning("Could not create debugfs "
 			   "'available_events' entry\n");
 
 	entry = debugfs_create_file("set_event", 0644, d_tracer,
-				    (void *)&show_set_event_seq_ops,
-				    &ftrace_set_event_fops);
+				    NULL, &ftrace_set_event_fops);
 	if (!entry)
 		pr_warning("Could not create debugfs "
 			   "'set_event' entry\n");
@@ -1749,7 +1760,7 @@ function_test_events_call(unsigned long ip, unsigned long parent_ip,
 	entry->ip			= ip;
 	entry->parent_ip		= parent_ip;
 
-	trace_nowake_buffer_unlock_commit(buffer, event, flags, pc);
+	trace_buffer_unlock_commit(buffer, event, flags, pc);
 
  out:
 	atomic_dec(&per_cpu(ftrace_test_event_disable, cpu));
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index c154797..e5b0ca8 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -1000,9 +1000,9 @@ static int init_pred(struct filter_parse_state *ps,
 		}
 	} else {
 		if (field->is_signed)
-			ret = strict_strtoll(pred->regex.pattern, 0, &val);
+			ret = kstrtoll(pred->regex.pattern, 0, &val);
 		else
-			ret = strict_strtoull(pred->regex.pattern, 0, &val);
+			ret = kstrtoull(pred->regex.pattern, 0, &val);
 		if (ret) {
 			parse_error(ps, FILT_ERR_ILLEGAL_INTVAL, 0);
 			return -EINVAL;
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c
index 507a7a9..bb227e3 100644
--- a/kernel/trace/trace_functions.c
+++ b/kernel/trace/trace_functions.c
@@ -366,7 +366,7 @@ ftrace_trace_onoff_callback(struct ftrace_hash *hash,
 	 * We use the callback data field (which is a pointer)
 	 * as our counter.
 	 */
-	ret = strict_strtoul(number, 0, (unsigned long *)&count);
+	ret = kstrtoul(number, 0, (unsigned long *)&count);
 	if (ret)
 		return ret;
 
@@ -411,5 +411,4 @@ static __init int init_function_trace(void)
 	init_func_cmd_traceon();
 	return register_tracer(&function_trace);
 }
-device_initcall(init_function_trace);
-
+core_initcall(init_function_trace);
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 99b4378..4edb4b7 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -223,7 +223,7 @@ int __trace_graph_entry(struct trace_array *tr,
 	entry	= ring_buffer_event_data(event);
 	entry->graph_ent			= *trace;
 	if (!filter_current_check_discard(buffer, call, entry, event))
-		ring_buffer_unlock_commit(buffer, event);
+		__buffer_unlock_commit(buffer, event);
 
 	return 1;
 }
@@ -327,7 +327,7 @@ void __trace_graph_return(struct trace_array *tr,
 	entry	= ring_buffer_event_data(event);
 	entry->ret				= *trace;
 	if (!filter_current_check_discard(buffer, call, entry, event))
-		ring_buffer_unlock_commit(buffer, event);
+		__buffer_unlock_commit(buffer, event);
 }
 
 void trace_graph_return(struct ftrace_graph_ret *trace)
@@ -1474,4 +1474,4 @@ static __init int init_graph_trace(void)
 	return register_tracer(&graph_trace);
 }
 
-device_initcall(init_graph_trace);
+core_initcall(init_graph_trace);
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c
index d98ee82..5ffce7b 100644
--- a/kernel/trace/trace_irqsoff.c
+++ b/kernel/trace/trace_irqsoff.c
@@ -604,7 +604,7 @@ static struct tracer irqsoff_tracer __read_mostly =
 	.reset		= irqsoff_tracer_reset,
 	.start		= irqsoff_tracer_start,
 	.stop		= irqsoff_tracer_stop,
-	.print_max	= 1,
+	.print_max	= true,
 	.print_header   = irqsoff_print_header,
 	.print_line     = irqsoff_print_line,
 	.flags		= &tracer_flags,
@@ -614,7 +614,7 @@ static struct tracer irqsoff_tracer __read_mostly =
 #endif
 	.open           = irqsoff_trace_open,
 	.close          = irqsoff_trace_close,
-	.use_max_tr	= 1,
+	.use_max_tr	= true,
 };
 # define register_irqsoff(trace) register_tracer(&trace)
 #else
@@ -637,7 +637,7 @@ static struct tracer preemptoff_tracer __read_mostly =
 	.reset		= irqsoff_tracer_reset,
 	.start		= irqsoff_tracer_start,
 	.stop		= irqsoff_tracer_stop,
-	.print_max	= 1,
+	.print_max	= true,
 	.print_header   = irqsoff_print_header,
 	.print_line     = irqsoff_print_line,
 	.flags		= &tracer_flags,
@@ -647,7 +647,7 @@ static struct tracer preemptoff_tracer __read_mostly =
 #endif
 	.open		= irqsoff_trace_open,
 	.close		= irqsoff_trace_close,
-	.use_max_tr	= 1,
+	.use_max_tr	= true,
 };
 # define register_preemptoff(trace) register_tracer(&trace)
 #else
@@ -672,7 +672,7 @@ static struct tracer preemptirqsoff_tracer __read_mostly =
 	.reset		= irqsoff_tracer_reset,
 	.start		= irqsoff_tracer_start,
 	.stop		= irqsoff_tracer_stop,
-	.print_max	= 1,
+	.print_max	= true,
 	.print_header   = irqsoff_print_header,
 	.print_line     = irqsoff_print_line,
 	.flags		= &tracer_flags,
@@ -682,7 +682,7 @@ static struct tracer preemptirqsoff_tracer __read_mostly =
 #endif
 	.open		= irqsoff_trace_open,
 	.close		= irqsoff_trace_close,
-	.use_max_tr	= 1,
+	.use_max_tr	= true,
 };
 
 # define register_preemptirqsoff(trace) register_tracer(&trace)
@@ -698,4 +698,4 @@ __init static int init_irqsoff_tracer(void)
 
 	return 0;
 }
-device_initcall(init_irqsoff_tracer);
+core_initcall(init_irqsoff_tracer);
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 1a21170..1865d5f 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -444,7 +444,7 @@ static int create_trace_probe(int argc, char **argv)
 			return -EINVAL;
 		}
 		/* an address specified */
-		ret = strict_strtoul(&argv[1][0], 0, (unsigned long *)&addr);
+		ret = kstrtoul(&argv[1][0], 0, (unsigned long *)&addr);
 		if (ret) {
 			pr_info("Failed to parse address.\n");
 			return ret;
@@ -751,8 +751,8 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs)
 	store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize);
 
 	if (!filter_current_check_discard(buffer, call, entry, event))
-		trace_nowake_buffer_unlock_commit_regs(buffer, event,
-						       irq_flags, pc, regs);
+		trace_buffer_unlock_commit_regs(buffer, event,
+						irq_flags, pc, regs);
 }
 
 /* Kretprobe handler */
@@ -784,8 +784,8 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri,
 	store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize);
 
 	if (!filter_current_check_discard(buffer, call, entry, event))
-		trace_nowake_buffer_unlock_commit_regs(buffer, event,
-						       irq_flags, pc, regs);
+		trace_buffer_unlock_commit_regs(buffer, event,
+						irq_flags, pc, regs);
 }
 
 /* Event entry printers */
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index 123b189..194d796 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -610,24 +610,54 @@ lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu)
 	return trace_print_lat_fmt(s, entry);
 }
 
-static unsigned long preempt_mark_thresh = 100;
+static unsigned long preempt_mark_thresh_us = 100;
 
 static int
-lat_print_timestamp(struct trace_seq *s, u64 abs_usecs,
-		    unsigned long rel_usecs)
+lat_print_timestamp(struct trace_iterator *iter, u64 next_ts)
 {
-	return trace_seq_printf(s, " %4lldus%c: ", abs_usecs,
-				rel_usecs > preempt_mark_thresh ? '!' :
-				  rel_usecs > 1 ? '+' : ' ');
+	unsigned long verbose = trace_flags & TRACE_ITER_VERBOSE;
+	unsigned long in_ns = iter->iter_flags & TRACE_FILE_TIME_IN_NS;
+	unsigned long long abs_ts = iter->ts - iter->tr->time_start;
+	unsigned long long rel_ts = next_ts - iter->ts;
+	struct trace_seq *s = &iter->seq;
+
+	if (in_ns) {
+		abs_ts = ns2usecs(abs_ts);
+		rel_ts = ns2usecs(rel_ts);
+	}
+
+	if (verbose && in_ns) {
+		unsigned long abs_usec = do_div(abs_ts, USEC_PER_MSEC);
+		unsigned long abs_msec = (unsigned long)abs_ts;
+		unsigned long rel_usec = do_div(rel_ts, USEC_PER_MSEC);
+		unsigned long rel_msec = (unsigned long)rel_ts;
+
+		return trace_seq_printf(
+				s, "[%08llx] %ld.%03ldms (+%ld.%03ldms): ",
+				ns2usecs(iter->ts),
+				abs_msec, abs_usec,
+				rel_msec, rel_usec);
+	} else if (verbose && !in_ns) {
+		return trace_seq_printf(
+				s, "[%016llx] %lld (+%lld): ",
+				iter->ts, abs_ts, rel_ts);
+	} else if (!verbose && in_ns) {
+		return trace_seq_printf(
+				s, " %4lldus%c: ",
+				abs_ts,
+				rel_ts > preempt_mark_thresh_us ? '!' :
+				  rel_ts > 1 ? '+' : ' ');
+	} else { /* !verbose && !in_ns */
+		return trace_seq_printf(s, " %4lld: ", abs_ts);
+	}
 }
 
 int trace_print_context(struct trace_iterator *iter)
 {
 	struct trace_seq *s = &iter->seq;
 	struct trace_entry *entry = iter->ent;
-	unsigned long long t = ns2usecs(iter->ts);
-	unsigned long usec_rem = do_div(t, USEC_PER_SEC);
-	unsigned long secs = (unsigned long)t;
+	unsigned long long t;
+	unsigned long secs, usec_rem;
 	char comm[TASK_COMM_LEN];
 	int ret;
 
@@ -644,8 +674,13 @@ int trace_print_context(struct trace_iterator *iter)
 			return 0;
 	}
 
-	return trace_seq_printf(s, " %5lu.%06lu: ",
-				secs, usec_rem);
+	if (iter->iter_flags & TRACE_FILE_TIME_IN_NS) {
+		t = ns2usecs(iter->ts);
+		usec_rem = do_div(t, USEC_PER_SEC);
+		secs = (unsigned long)t;
+		return trace_seq_printf(s, " %5lu.%06lu: ", secs, usec_rem);
+	} else
+		return trace_seq_printf(s, " %12llu: ", iter->ts);
 }
 
 int trace_print_lat_context(struct trace_iterator *iter)
@@ -659,36 +694,29 @@ int trace_print_lat_context(struct trace_iterator *iter)
 			   *next_entry = trace_find_next_entry(iter, NULL,
 							       &next_ts);
 	unsigned long verbose = (trace_flags & TRACE_ITER_VERBOSE);
-	unsigned long abs_usecs = ns2usecs(iter->ts - iter->tr->time_start);
-	unsigned long rel_usecs;
 
 	/* Restore the original ent_size */
 	iter->ent_size = ent_size;
 
 	if (!next_entry)
 		next_ts = iter->ts;
-	rel_usecs = ns2usecs(next_ts - iter->ts);
 
 	if (verbose) {
 		char comm[TASK_COMM_LEN];
 
 		trace_find_cmdline(entry->pid, comm);
 
-		ret = trace_seq_printf(s, "%16s %5d %3d %d %08x %08lx [%08llx]"
-				       " %ld.%03ldms (+%ld.%03ldms): ", comm,
-				       entry->pid, iter->cpu, entry->flags,
-				       entry->preempt_count, iter->idx,
-				       ns2usecs(iter->ts),
-				       abs_usecs / USEC_PER_MSEC,
-				       abs_usecs % USEC_PER_MSEC,
-				       rel_usecs / USEC_PER_MSEC,
-				       rel_usecs % USEC_PER_MSEC);
+		ret = trace_seq_printf(
+				s, "%16s %5d %3d %d %08x %08lx ",
+				comm, entry->pid, iter->cpu, entry->flags,
+				entry->preempt_count, iter->idx);
 	} else {
 		ret = lat_print_generic(s, entry, iter->cpu);
-		if (ret)
-			ret = lat_print_timestamp(s, abs_usecs, rel_usecs);
 	}
 
+	if (ret)
+		ret = lat_print_timestamp(iter, next_ts);
+
 	return ret;
 }
 
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index daa9980..412e959 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -441,7 +441,7 @@ static const struct fetch_type *find_fetch_type(const char *type)
 			goto fail;
 
 		type++;
-		if (strict_strtoul(type, 0, &bs))
+		if (kstrtoul(type, 0, &bs))
 			goto fail;
 
 		switch (bs) {
@@ -501,8 +501,8 @@ int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset)
 
 	tmp = strchr(symbol, '+');
 	if (tmp) {
-		/* skip sign because strict_strtol doesn't accept '+' */
-		ret = strict_strtoul(tmp + 1, 0, offset);
+		/* skip sign because kstrtoul doesn't accept '+' */
+		ret = kstrtoul(tmp + 1, 0, offset);
 		if (ret)
 			return ret;
 
@@ -533,7 +533,7 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t,
 			else
 				ret = -EINVAL;
 		} else if (isdigit(arg[5])) {
-			ret = strict_strtoul(arg + 5, 10, &param);
+			ret = kstrtoul(arg + 5, 10, &param);
 			if (ret || param > PARAM_MAX_STACK)
 				ret = -EINVAL;
 			else {
@@ -579,7 +579,7 @@ static int parse_probe_arg(char *arg, const struct fetch_type *t,
 
 	case '@':	/* memory or symbol */
 		if (isdigit(arg[1])) {
-			ret = strict_strtoul(arg + 1, 0, &param);
+			ret = kstrtoul(arg + 1, 0, &param);
 			if (ret)
 				break;
 
@@ -597,14 +597,14 @@ static int parse_probe_arg(char *arg, const struct fetch_type *t,
 		break;
 
 	case '+':	/* deref memory */
-		arg++;	/* Skip '+', because strict_strtol() rejects it. */
+		arg++;	/* Skip '+', because kstrtol() rejects it. */
 	case '-':
 		tmp = strchr(arg, '(');
 		if (!tmp)
 			break;
 
 		*tmp = '\0';
-		ret = strict_strtol(arg, 0, &offset);
+		ret = kstrtol(arg, 0, &offset);
 
 		if (ret)
 			break;
diff --git a/kernel/trace/trace_sched_switch.c b/kernel/trace/trace_sched_switch.c
index 7e62c0a..3374c79 100644
--- a/kernel/trace/trace_sched_switch.c
+++ b/kernel/trace/trace_sched_switch.c
@@ -102,9 +102,7 @@ tracing_sched_wakeup_trace(struct trace_array *tr,
 	entry->next_cpu			= task_cpu(wakee);
 
 	if (!filter_check_discard(call, entry, buffer, event))
-		ring_buffer_unlock_commit(buffer, event);
-	ftrace_trace_stack(tr->buffer, flags, 6, pc);
-	ftrace_trace_userstack(tr->buffer, flags, pc);
+		trace_buffer_unlock_commit(buffer, event, flags, pc);
 }
 
 static void
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c
index 02170c0..bc64fc1 100644
--- a/kernel/trace/trace_sched_wakeup.c
+++ b/kernel/trace/trace_sched_wakeup.c
@@ -589,7 +589,7 @@ static struct tracer wakeup_tracer __read_mostly =
 	.reset		= wakeup_tracer_reset,
 	.start		= wakeup_tracer_start,
 	.stop		= wakeup_tracer_stop,
-	.print_max	= 1,
+	.print_max	= true,
 	.print_header	= wakeup_print_header,
 	.print_line	= wakeup_print_line,
 	.flags		= &tracer_flags,
@@ -599,7 +599,7 @@ static struct tracer wakeup_tracer __read_mostly =
 #endif
 	.open		= wakeup_trace_open,
 	.close		= wakeup_trace_close,
-	.use_max_tr	= 1,
+	.use_max_tr	= true,
 };
 
 static struct tracer wakeup_rt_tracer __read_mostly =
@@ -610,7 +610,7 @@ static struct tracer wakeup_rt_tracer __read_mostly =
 	.start		= wakeup_tracer_start,
 	.stop		= wakeup_tracer_stop,
 	.wait_pipe	= poll_wait_pipe,
-	.print_max	= 1,
+	.print_max	= true,
 	.print_header	= wakeup_print_header,
 	.print_line	= wakeup_print_line,
 	.flags		= &tracer_flags,
@@ -620,7 +620,7 @@ static struct tracer wakeup_rt_tracer __read_mostly =
 #endif
 	.open		= wakeup_trace_open,
 	.close		= wakeup_trace_close,
-	.use_max_tr	= 1,
+	.use_max_tr	= true,
 };
 
 __init static int init_wakeup_tracer(void)
@@ -637,4 +637,4 @@ __init static int init_wakeup_tracer(void)
 
 	return 0;
 }
-device_initcall(init_wakeup_tracer);
+core_initcall(init_wakeup_tracer);
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
index 2c00a69..4762316 100644
--- a/kernel/trace/trace_selftest.c
+++ b/kernel/trace/trace_selftest.c
@@ -320,7 +320,6 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
 					   int (*func)(void))
 {
 	int save_ftrace_enabled = ftrace_enabled;
-	int save_tracer_enabled = tracer_enabled;
 	unsigned long count;
 	char *func_name;
 	int ret;
@@ -331,7 +330,6 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
 
 	/* enable tracing, and record the filter function */
 	ftrace_enabled = 1;
-	tracer_enabled = 1;
 
 	/* passed in by parameter to fool gcc from optimizing */
 	func();
@@ -395,7 +393,6 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
 
  out:
 	ftrace_enabled = save_ftrace_enabled;
-	tracer_enabled = save_tracer_enabled;
 
 	/* Enable tracing on all functions again */
 	ftrace_set_global_filter(NULL, 0, 1);
@@ -452,7 +449,6 @@ static int
 trace_selftest_function_recursion(void)
 {
 	int save_ftrace_enabled = ftrace_enabled;
-	int save_tracer_enabled = tracer_enabled;
 	char *func_name;
 	int len;
 	int ret;
@@ -465,7 +461,6 @@ trace_selftest_function_recursion(void)
 
 	/* enable tracing, and record the filter function */
 	ftrace_enabled = 1;
-	tracer_enabled = 1;
 
 	/* Handle PPC64 '.' name */
 	func_name = "*" __stringify(DYN_FTRACE_TEST_NAME);
@@ -534,7 +529,6 @@ trace_selftest_function_recursion(void)
 	ret = 0;
 out:
 	ftrace_enabled = save_ftrace_enabled;
-	tracer_enabled = save_tracer_enabled;
 
 	return ret;
 }
@@ -569,7 +563,6 @@ static int
 trace_selftest_function_regs(void)
 {
 	int save_ftrace_enabled = ftrace_enabled;
-	int save_tracer_enabled = tracer_enabled;
 	char *func_name;
 	int len;
 	int ret;
@@ -586,7 +579,6 @@ trace_selftest_function_regs(void)
 
 	/* enable tracing, and record the filter function */
 	ftrace_enabled = 1;
-	tracer_enabled = 1;
 
 	/* Handle PPC64 '.' name */
 	func_name = "*" __stringify(DYN_FTRACE_TEST_NAME);
@@ -648,7 +640,6 @@ trace_selftest_function_regs(void)
 	ret = 0;
 out:
 	ftrace_enabled = save_ftrace_enabled;
-	tracer_enabled = save_tracer_enabled;
 
 	return ret;
 }
@@ -662,7 +653,6 @@ int
 trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
 {
 	int save_ftrace_enabled = ftrace_enabled;
-	int save_tracer_enabled = tracer_enabled;
 	unsigned long count;
 	int ret;
 
@@ -671,7 +661,6 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
 
 	/* start the tracing */
 	ftrace_enabled = 1;
-	tracer_enabled = 1;
 
 	ret = tracer_init(trace, tr);
 	if (ret) {
@@ -708,7 +697,6 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
 	ret = trace_selftest_function_regs();
  out:
 	ftrace_enabled = save_ftrace_enabled;
-	tracer_enabled = save_tracer_enabled;
 
 	/* kill ftrace totally if we failed */
 	if (ret)
@@ -1106,6 +1094,7 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr)
 	tracing_stop();
 	/* check both trace buffers */
 	ret = trace_test_buffer(tr, NULL);
+	printk("ret = %d\n", ret);
 	if (!ret)
 		ret = trace_test_buffer(&max_tr, &count);
 
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index 0c1b1657..42ca822 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -33,7 +33,6 @@ static unsigned long max_stack_size;
 static arch_spinlock_t max_stack_lock =
 	(arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
 
-static int stack_trace_disabled __read_mostly;
 static DEFINE_PER_CPU(int, trace_active);
 static DEFINE_MUTEX(stack_sysctl_mutex);
 
@@ -116,9 +115,6 @@ stack_trace_call(unsigned long ip, unsigned long parent_ip,
 {
 	int cpu;
 
-	if (unlikely(!ftrace_enabled || stack_trace_disabled))
-		return;
-
 	preempt_disable_notrace();
 
 	cpu = raw_smp_processor_id();
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index 2485a7d..7609dd6 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -21,9 +21,6 @@ static int syscall_enter_register(struct ftrace_event_call *event,
 static int syscall_exit_register(struct ftrace_event_call *event,
 				 enum trace_reg type, void *data);
 
-static int syscall_enter_define_fields(struct ftrace_event_call *call);
-static int syscall_exit_define_fields(struct ftrace_event_call *call);
-
 static struct list_head *
 syscall_get_enter_fields(struct ftrace_event_call *call)
 {
@@ -32,30 +29,6 @@ syscall_get_enter_fields(struct ftrace_event_call *call)
 	return &entry->enter_fields;
 }
 
-struct trace_event_functions enter_syscall_print_funcs = {
-	.trace		= print_syscall_enter,
-};
-
-struct trace_event_functions exit_syscall_print_funcs = {
-	.trace		= print_syscall_exit,
-};
-
-struct ftrace_event_class event_class_syscall_enter = {
-	.system		= "syscalls",
-	.reg		= syscall_enter_register,
-	.define_fields	= syscall_enter_define_fields,
-	.get_fields	= syscall_get_enter_fields,
-	.raw_init	= init_syscall_trace,
-};
-
-struct ftrace_event_class event_class_syscall_exit = {
-	.system		= "syscalls",
-	.reg		= syscall_exit_register,
-	.define_fields	= syscall_exit_define_fields,
-	.fields		= LIST_HEAD_INIT(event_class_syscall_exit.fields),
-	.raw_init	= init_syscall_trace,
-};
-
 extern struct syscall_metadata *__start_syscalls_metadata[];
 extern struct syscall_metadata *__stop_syscalls_metadata[];
 
@@ -432,7 +405,7 @@ void unreg_event_syscall_exit(struct ftrace_event_call *call)
 	mutex_unlock(&syscall_trace_lock);
 }
 
-int init_syscall_trace(struct ftrace_event_call *call)
+static int init_syscall_trace(struct ftrace_event_call *call)
 {
 	int id;
 	int num;
@@ -457,6 +430,30 @@ int init_syscall_trace(struct ftrace_event_call *call)
 	return id;
 }
 
+struct trace_event_functions enter_syscall_print_funcs = {
+	.trace		= print_syscall_enter,
+};
+
+struct trace_event_functions exit_syscall_print_funcs = {
+	.trace		= print_syscall_exit,
+};
+
+struct ftrace_event_class event_class_syscall_enter = {
+	.system		= "syscalls",
+	.reg		= syscall_enter_register,
+	.define_fields	= syscall_enter_define_fields,
+	.get_fields	= syscall_get_enter_fields,
+	.raw_init	= init_syscall_trace,
+};
+
+struct ftrace_event_class event_class_syscall_exit = {
+	.system		= "syscalls",
+	.reg		= syscall_exit_register,
+	.define_fields	= syscall_exit_define_fields,
+	.fields		= LIST_HEAD_INIT(event_class_syscall_exit.fields),
+	.raw_init	= init_syscall_trace,
+};
+
 unsigned long __init __weak arch_syscall_addr(int nr)
 {
 	return (unsigned long)sys_call_table[nr];
@@ -537,7 +534,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id)
 	perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head, NULL);
 }
 
-int perf_sysenter_enable(struct ftrace_event_call *call)
+static int perf_sysenter_enable(struct ftrace_event_call *call)
 {
 	int ret = 0;
 	int num;
@@ -558,7 +555,7 @@ int perf_sysenter_enable(struct ftrace_event_call *call)
 	return ret;
 }
 
-void perf_sysenter_disable(struct ftrace_event_call *call)
+static void perf_sysenter_disable(struct ftrace_event_call *call)
 {
 	int num;
 
@@ -615,7 +612,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
 	perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head, NULL);
 }
 
-int perf_sysexit_enable(struct ftrace_event_call *call)
+static int perf_sysexit_enable(struct ftrace_event_call *call)
 {
 	int ret = 0;
 	int num;
@@ -636,7 +633,7 @@ int perf_sysexit_enable(struct ftrace_event_call *call)
 	return ret;
 }
 
-void perf_sysexit_disable(struct ftrace_event_call *call)
+static void perf_sysexit_disable(struct ftrace_event_call *call)
 {
 	int num;
 
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index 03003cd..fa803e6 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -22,6 +22,7 @@
 #include <linux/uaccess.h>
 #include <linux/uprobes.h>
 #include <linux/namei.h>
+#include <linux/string.h>
 
 #include "trace_probe.h"
 
@@ -252,7 +253,7 @@ static int create_trace_uprobe(int argc, char **argv)
 	if (ret)
 		goto fail_address_parse;
 
-	ret = strict_strtoul(arg, 0, &offset);
+	ret = kstrtoul(arg, 0, &offset);
 	if (ret)
 		goto fail_address_parse;
 
@@ -263,16 +264,15 @@ static int create_trace_uprobe(int argc, char **argv)
 
 	/* setup a probe */
 	if (!event) {
-		char *tail = strrchr(filename, '/');
+		char *tail;
 		char *ptr;
 
-		ptr = kstrdup((tail ? tail + 1 : filename), GFP_KERNEL);
-		if (!ptr) {
+		tail = kstrdup(kbasename(filename), GFP_KERNEL);
+		if (!tail) {
 			ret = -ENOMEM;
 			goto fail_address_parse;
 		}
 
-		tail = ptr;
 		ptr = strpbrk(tail, ".-_");
 		if (ptr)
 			*ptr = '\0';
diff --git a/kernel/user.c b/kernel/user.c
index 750acff..33acb5e 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/export.h>
 #include <linux/user_namespace.h>
+#include <linux/proc_fs.h>
 
 /*
  * userns count is 1 for root user, 1 for init_uts_ns,
@@ -51,6 +52,7 @@ struct user_namespace init_user_ns = {
 	},
 	.owner = GLOBAL_ROOT_UID,
 	.group = GLOBAL_ROOT_GID,
+	.proc_inum = PROC_USER_INIT_INO,
 };
 EXPORT_SYMBOL_GPL(init_user_ns);
 
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 456a6b9..f5975cc 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -9,6 +9,7 @@
 #include <linux/nsproxy.h>
 #include <linux/slab.h>
 #include <linux/user_namespace.h>
+#include <linux/proc_fs.h>
 #include <linux/highuid.h>
 #include <linux/cred.h>
 #include <linux/securebits.h>
@@ -26,6 +27,24 @@ static struct kmem_cache *user_ns_cachep __read_mostly;
 static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
 				struct uid_gid_map *map);
 
+static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns)
+{
+	/* Start with the same capabilities as init but useless for doing
+	 * anything as the capabilities are bound to the new user namespace.
+	 */
+	cred->securebits = SECUREBITS_DEFAULT;
+	cred->cap_inheritable = CAP_EMPTY_SET;
+	cred->cap_permitted = CAP_FULL_SET;
+	cred->cap_effective = CAP_FULL_SET;
+	cred->cap_bset = CAP_FULL_SET;
+#ifdef CONFIG_KEYS
+	key_put(cred->request_key_auth);
+	cred->request_key_auth = NULL;
+#endif
+	/* tgcred will be cleared in our caller bc CLONE_THREAD won't be set */
+	cred->user_ns = user_ns;
+}
+
 /*
  * Create a new user namespace, deriving the creator from the user in the
  * passed credentials, and replacing that user with the new root user for the
@@ -39,6 +58,7 @@ int create_user_ns(struct cred *new)
 	struct user_namespace *ns, *parent_ns = new->user_ns;
 	kuid_t owner = new->euid;
 	kgid_t group = new->egid;
+	int ret;
 
 	/* The creator needs a mapping in the parent user namespace
 	 * or else we won't be able to reasonably tell userspace who
@@ -52,38 +72,45 @@ int create_user_ns(struct cred *new)
 	if (!ns)
 		return -ENOMEM;
 
+	ret = proc_alloc_inum(&ns->proc_inum);
+	if (ret) {
+		kmem_cache_free(user_ns_cachep, ns);
+		return ret;
+	}
+
 	kref_init(&ns->kref);
+	/* Leave the new->user_ns reference with the new user namespace. */
 	ns->parent = parent_ns;
 	ns->owner = owner;
 	ns->group = group;
 
-	/* Start with the same capabilities as init but useless for doing
-	 * anything as the capabilities are bound to the new user namespace.
-	 */
-	new->securebits = SECUREBITS_DEFAULT;
-	new->cap_inheritable = CAP_EMPTY_SET;
-	new->cap_permitted = CAP_FULL_SET;
-	new->cap_effective = CAP_FULL_SET;
-	new->cap_bset = CAP_FULL_SET;
-#ifdef CONFIG_KEYS
-	key_put(new->request_key_auth);
-	new->request_key_auth = NULL;
-#endif
-	/* tgcred will be cleared in our caller bc CLONE_THREAD won't be set */
-
-	/* Leave the new->user_ns reference with the new user namespace. */
-	/* Leave the reference to our user_ns with the new cred. */
-	new->user_ns = ns;
+	set_cred_user_ns(new, ns);
 
 	return 0;
 }
 
+int unshare_userns(unsigned long unshare_flags, struct cred **new_cred)
+{
+	struct cred *cred;
+
+	if (!(unshare_flags & CLONE_NEWUSER))
+		return 0;
+
+	cred = prepare_creds();
+	if (!cred)
+		return -ENOMEM;
+
+	*new_cred = cred;
+	return create_user_ns(cred);
+}
+
 void free_user_ns(struct kref *kref)
 {
 	struct user_namespace *parent, *ns =
 		container_of(kref, struct user_namespace, kref);
 
 	parent = ns->parent;
+	proc_free_inum(ns->proc_inum);
 	kmem_cache_free(user_ns_cachep, ns);
 	put_user_ns(parent);
 }
@@ -372,7 +399,7 @@ static int uid_m_show(struct seq_file *seq, void *v)
 	struct user_namespace *lower_ns;
 	uid_t lower;
 
-	lower_ns = current_user_ns();
+	lower_ns = seq_user_ns(seq);
 	if ((lower_ns == ns) && lower_ns->parent)
 		lower_ns = lower_ns->parent;
 
@@ -393,7 +420,7 @@ static int gid_m_show(struct seq_file *seq, void *v)
 	struct user_namespace *lower_ns;
 	gid_t lower;
 
-	lower_ns = current_user_ns();
+	lower_ns = seq_user_ns(seq);
 	if ((lower_ns == ns) && lower_ns->parent)
 		lower_ns = lower_ns->parent;
 
@@ -669,10 +696,14 @@ ssize_t proc_uid_map_write(struct file *file, const char __user *buf, size_t siz
 {
 	struct seq_file *seq = file->private_data;
 	struct user_namespace *ns = seq->private;
+	struct user_namespace *seq_ns = seq_user_ns(seq);
 
 	if (!ns->parent)
 		return -EPERM;
 
+	if ((seq_ns != ns) && (seq_ns != ns->parent))
+		return -EPERM;
+
 	return map_write(file, buf, size, ppos, CAP_SETUID,
 			 &ns->uid_map, &ns->parent->uid_map);
 }
@@ -681,10 +712,14 @@ ssize_t proc_gid_map_write(struct file *file, const char __user *buf, size_t siz
 {
 	struct seq_file *seq = file->private_data;
 	struct user_namespace *ns = seq->private;
+	struct user_namespace *seq_ns = seq_user_ns(seq);
 
 	if (!ns->parent)
 		return -EPERM;
 
+	if ((seq_ns != ns) && (seq_ns != ns->parent))
+		return -EPERM;
+
 	return map_write(file, buf, size, ppos, CAP_SETGID,
 			 &ns->gid_map, &ns->parent->gid_map);
 }
@@ -709,6 +744,21 @@ ssize_t proc_projid_map_write(struct file *file, const char __user *buf, size_t
 static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
 				struct uid_gid_map *new_map)
 {
+	/* Allow mapping to your own filesystem ids */
+	if ((new_map->nr_extents == 1) && (new_map->extent[0].count == 1)) {
+		u32 id = new_map->extent[0].lower_first;
+		if (cap_setid == CAP_SETUID) {
+			kuid_t uid = make_kuid(ns->parent, id);
+			if (uid_eq(uid, current_fsuid()))
+				return true;
+		}
+		else if (cap_setid == CAP_SETGID) {
+			kgid_t gid = make_kgid(ns->parent, id);
+			if (gid_eq(gid, current_fsgid()))
+				return true;
+		}
+	}
+
 	/* Allow anyone to set a mapping that doesn't require privilege */
 	if (!cap_valid(cap_setid))
 		return true;
@@ -722,6 +772,65 @@ static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
 	return false;
 }
 
+static void *userns_get(struct task_struct *task)
+{
+	struct user_namespace *user_ns;
+
+	rcu_read_lock();
+	user_ns = get_user_ns(__task_cred(task)->user_ns);
+	rcu_read_unlock();
+
+	return user_ns;
+}
+
+static void userns_put(void *ns)
+{
+	put_user_ns(ns);
+}
+
+static int userns_install(struct nsproxy *nsproxy, void *ns)
+{
+	struct user_namespace *user_ns = ns;
+	struct cred *cred;
+
+	/* Don't allow gaining capabilities by reentering
+	 * the same user namespace.
+	 */
+	if (user_ns == current_user_ns())
+		return -EINVAL;
+
+	/* Threaded many not enter a different user namespace */
+	if (atomic_read(&current->mm->mm_users) > 1)
+		return -EINVAL;
+
+	if (!ns_capable(user_ns, CAP_SYS_ADMIN))
+		return -EPERM;
+
+	cred = prepare_creds();
+	if (!cred)
+		return -ENOMEM;
+
+	put_user_ns(cred->user_ns);
+	set_cred_user_ns(cred, get_user_ns(user_ns));
+
+	return commit_creds(cred);
+}
+
+static unsigned int userns_inum(void *ns)
+{
+	struct user_namespace *user_ns = ns;
+	return user_ns->proc_inum;
+}
+
+const struct proc_ns_operations userns_operations = {
+	.name		= "user",
+	.type		= CLONE_NEWUSER,
+	.get		= userns_get,
+	.put		= userns_put,
+	.install	= userns_install,
+	.inum		= userns_inum,
+};
+
 static __init int user_namespaces_init(void)
 {
 	user_ns_cachep = KMEM_CACHE(user_namespace, SLAB_PANIC);
diff --git a/kernel/utsname.c b/kernel/utsname.c
index 679d97a..f6336d5 100644
--- a/kernel/utsname.c
+++ b/kernel/utsname.c
@@ -32,18 +32,25 @@ static struct uts_namespace *create_uts_ns(void)
  * @old_ns: namespace to clone
  * Return NULL on error (failure to kmalloc), new ns otherwise
  */
-static struct uts_namespace *clone_uts_ns(struct task_struct *tsk,
+static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns,
 					  struct uts_namespace *old_ns)
 {
 	struct uts_namespace *ns;
+	int err;
 
 	ns = create_uts_ns();
 	if (!ns)
 		return ERR_PTR(-ENOMEM);
 
+	err = proc_alloc_inum(&ns->proc_inum);
+	if (err) {
+		kfree(ns);
+		return ERR_PTR(err);
+	}
+
 	down_read(&uts_sem);
 	memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
-	ns->user_ns = get_user_ns(task_cred_xxx(tsk, user_ns));
+	ns->user_ns = get_user_ns(user_ns);
 	up_read(&uts_sem);
 	return ns;
 }
@@ -55,9 +62,8 @@ static struct uts_namespace *clone_uts_ns(struct task_struct *tsk,
  * versa.
  */
 struct uts_namespace *copy_utsname(unsigned long flags,
-				   struct task_struct *tsk)
+	struct user_namespace *user_ns, struct uts_namespace *old_ns)
 {
-	struct uts_namespace *old_ns = tsk->nsproxy->uts_ns;
 	struct uts_namespace *new_ns;
 
 	BUG_ON(!old_ns);
@@ -66,7 +72,7 @@ struct uts_namespace *copy_utsname(unsigned long flags,
 	if (!(flags & CLONE_NEWUTS))
 		return old_ns;
 
-	new_ns = clone_uts_ns(tsk, old_ns);
+	new_ns = clone_uts_ns(user_ns, old_ns);
 
 	put_uts_ns(old_ns);
 	return new_ns;
@@ -78,6 +84,7 @@ void free_uts_ns(struct kref *kref)
 
 	ns = container_of(kref, struct uts_namespace, kref);
 	put_user_ns(ns->user_ns);
+	proc_free_inum(ns->proc_inum);
 	kfree(ns);
 }
 
@@ -102,19 +109,31 @@ static void utsns_put(void *ns)
 	put_uts_ns(ns);
 }
 
-static int utsns_install(struct nsproxy *nsproxy, void *ns)
+static int utsns_install(struct nsproxy *nsproxy, void *new)
 {
+	struct uts_namespace *ns = new;
+
+	if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN))
+		return -EPERM;
+
 	get_uts_ns(ns);
 	put_uts_ns(nsproxy->uts_ns);
 	nsproxy->uts_ns = ns;
 	return 0;
 }
 
+static unsigned int utsns_inum(void *vp)
+{
+	struct uts_namespace *ns = vp;
+
+	return ns->proc_inum;
+}
+
 const struct proc_ns_operations utsns_operations = {
 	.name		= "uts",
 	.type		= CLONE_NEWUTS,
 	.get		= utsns_get,
 	.put		= utsns_put,
 	.install	= utsns_install,
+	.inum		= utsns_inum,
 };
-
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 9d4c8d5..45dca06 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -116,7 +116,7 @@ static unsigned long get_timestamp(int this_cpu)
 	return cpu_clock(this_cpu) >> 30LL;  /* 2^30 ~= 10^9 */
 }
 
-static unsigned long get_sample_period(void)
+static u64 get_sample_period(void)
 {
 	/*
 	 * convert watchdog_thresh from seconds to ns
@@ -125,7 +125,7 @@ static unsigned long get_sample_period(void)
 	 * and hard thresholds) to increment before the
 	 * hardlockup detector generates a warning
 	 */
-	return get_softlockup_thresh() * (NSEC_PER_SEC / 5);
+	return get_softlockup_thresh() * ((u64)NSEC_PER_SEC / 5);
 }
 
 /* Commands for resetting the watchdog */
@@ -239,10 +239,12 @@ static void watchdog_overflow_callback(struct perf_event *event,
 		if (__this_cpu_read(hard_watchdog_warn) == true)
 			return;
 
-		if (hardlockup_panic)
+		if (hardlockup_panic) {
+			trigger_all_cpu_backtrace();
 			panic("Watchdog detected hard LOCKUP on cpu %d", this_cpu);
-		else
+		} else {
 			WARN(1, "Watchdog detected hard LOCKUP on cpu %d", this_cpu);
+		}
 
 		__this_cpu_write(hard_watchdog_warn, true);
 		return;
@@ -323,8 +325,10 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
 		else
 			dump_stack();
 
-		if (softlockup_panic)
+		if (softlockup_panic) {
+			trigger_all_cpu_backtrace();
 			panic("softlockup: hung tasks");
+		}
 		__this_cpu_write(soft_watchdog_warn, true);
 	} else
 		__this_cpu_write(soft_watchdog_warn, false);
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 042d221..8244cf2 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -739,8 +739,10 @@ void wq_worker_waking_up(struct task_struct *task, unsigned int cpu)
 {
 	struct worker *worker = kthread_data(task);
 
-	if (!(worker->flags & WORKER_NOT_RUNNING))
+	if (!(worker->flags & WORKER_NOT_RUNNING)) {
+		WARN_ON_ONCE(worker->pool->gcwq->cpu != cpu);
 		atomic_inc(get_pool_nr_running(worker->pool));
+	}
 }
 
 /**
@@ -1477,7 +1479,11 @@ bool mod_delayed_work_on(int cpu, struct workqueue_struct *wq,
 	} while (unlikely(ret == -EAGAIN));
 
 	if (likely(ret >= 0)) {
-		__queue_delayed_work(cpu, wq, dwork, delay);
+		if (!delay)
+			__queue_work(cpu, wq, &dwork->work);
+		else
+			__queue_delayed_work(cpu, wq, dwork, delay);
+
 		local_irq_restore(flags);
 	}
 
@@ -2407,8 +2413,10 @@ static int rescuer_thread(void *__wq)
 repeat:
 	set_current_state(TASK_INTERRUPTIBLE);
 
-	if (kthread_should_stop())
+	if (kthread_should_stop()) {
+		__set_current_state(TASK_RUNNING);
 		return 0;
+	}
 
 	/*
 	 * See whether any cpu is asking for help.  Unbounded
@@ -3475,7 +3483,7 @@ unsigned int work_busy(struct work_struct *work)
 	unsigned int ret = 0;
 
 	if (!gcwq)
-		return false;
+		return 0;
 
 	spin_lock_irqsave(&gcwq->lock, flags);
 
diff --git a/lib/Kconfig b/lib/Kconfig
index 4b31a46..75cdb77 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -42,6 +42,9 @@ config GENERIC_IO
 config STMP_DEVICE
 	bool
 
+config PERCPU_RWSEM
+	boolean
+
 config CRC_CCITT
 	tristate "CRC-CCITT functions"
 	help
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 28e9d6c9..ad84944 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -972,7 +972,7 @@ config RCU_CPU_STALL_TIMEOUT
 	int "RCU CPU stall timeout in seconds"
 	depends on TREE_RCU || TREE_PREEMPT_RCU
 	range 3 300
-	default 60
+	default 21
 	help
 	  If a given RCU grace period extends more than the specified
 	  number of seconds, a CPU stall warning is printed.  If the
@@ -1195,6 +1195,7 @@ config MEMORY_NOTIFIER_ERROR_INJECT
 config PSERIES_RECONFIG_NOTIFIER_ERROR_INJECT
 	tristate "pSeries reconfig notifier error injection module"
 	depends on PPC_PSERIES && NOTIFIER_ERROR_INJECTION
+	depends on BROKEN
 	help
 	  This option provides the ability to inject artifical errors to
 	  pSeries reconfig notifier chain callbacks.  It is controlled
diff --git a/lib/Makefile b/lib/Makefile
index 821a162..201eaf8 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -12,7 +12,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
 	 idr.o int_sqrt.o extable.o \
 	 sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \
 	 proportions.o flex_proportions.o prio_heap.o ratelimit.o show_mem.o \
-	 is_single_threaded.o plist.o decompress.o
+	 is_single_threaded.o plist.o decompress.o earlycpio.o kobject_uevent.o
 
 lib-$(CONFIG_MMU) += ioremap.o
 lib-$(CONFIG_SMP) += cpumask.o
@@ -31,7 +31,6 @@ CFLAGS_kobject.o += -DDEBUG
 CFLAGS_kobject_uevent.o += -DDEBUG
 endif
 
-lib-$(CONFIG_HOTPLUG) += kobject_uevent.o
 obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
 obj-$(CONFIG_GENERIC_PCI_IOMAP) += pci_iomap.o
 obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
@@ -40,6 +39,7 @@ obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
 obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
 lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
+lib-$(CONFIG_PERCPU_RWSEM) += percpu-rwsem.o
 
 CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS))
 obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
diff --git a/lib/cpumask.c b/lib/cpumask.c
index 402a54a..d327b87 100644
--- a/lib/cpumask.c
+++ b/lib/cpumask.c
@@ -161,6 +161,6 @@ EXPORT_SYMBOL(free_cpumask_var);
  */
 void __init free_bootmem_cpumask_var(cpumask_var_t mask)
 {
-	free_bootmem((unsigned long)mask, cpumask_size());
+	free_bootmem(__pa(mask), cpumask_size());
 }
 #endif
diff --git a/lib/decompress_unlzo.c b/lib/decompress_unlzo.c
index 4531294..960183d 100644
--- a/lib/decompress_unlzo.c
+++ b/lib/decompress_unlzo.c
@@ -31,7 +31,7 @@
  */
 
 #ifdef STATIC
-#include "lzo/lzo1x_decompress.c"
+#include "lzo/lzo1x_decompress_safe.c"
 #else
 #include <linux/decompress/unlzo.h>
 #endif
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index d84beb9..5e396ac 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -45,6 +45,12 @@ enum {
 	dma_debug_coherent,
 };
 
+enum map_err_types {
+	MAP_ERR_CHECK_NOT_APPLICABLE,
+	MAP_ERR_NOT_CHECKED,
+	MAP_ERR_CHECKED,
+};
+
 #define DMA_DEBUG_STACKTRACE_ENTRIES 5
 
 struct dma_debug_entry {
@@ -57,6 +63,7 @@ struct dma_debug_entry {
 	int              direction;
 	int		 sg_call_ents;
 	int		 sg_mapped_ents;
+	enum map_err_types  map_err_type;
 #ifdef CONFIG_STACKTRACE
 	struct		 stack_trace stacktrace;
 	unsigned long	 st_entries[DMA_DEBUG_STACKTRACE_ENTRIES];
@@ -114,6 +121,12 @@ static struct device_driver *current_driver                    __read_mostly;
 
 static DEFINE_RWLOCK(driver_name_lock);
 
+static const char *const maperr2str[] = {
+	[MAP_ERR_CHECK_NOT_APPLICABLE] = "dma map error check not applicable",
+	[MAP_ERR_NOT_CHECKED] = "dma map error not checked",
+	[MAP_ERR_CHECKED] = "dma map error checked",
+};
+
 static const char *type2name[4] = { "single", "page",
 				    "scather-gather", "coherent" };
 
@@ -376,11 +389,12 @@ void debug_dma_dump_mappings(struct device *dev)
 		list_for_each_entry(entry, &bucket->list, list) {
 			if (!dev || dev == entry->dev) {
 				dev_info(entry->dev,
-					 "%s idx %d P=%Lx D=%Lx L=%Lx %s\n",
+					 "%s idx %d P=%Lx D=%Lx L=%Lx %s %s\n",
 					 type2name[entry->type], idx,
 					 (unsigned long long)entry->paddr,
 					 entry->dev_addr, entry->size,
-					 dir2name[entry->direction]);
+					 dir2name[entry->direction],
+					 maperr2str[entry->map_err_type]);
 			}
 		}
 
@@ -844,16 +858,16 @@ static void check_unmap(struct dma_debug_entry *ref)
 	struct hash_bucket *bucket;
 	unsigned long flags;
 
-	if (dma_mapping_error(ref->dev, ref->dev_addr)) {
-		err_printk(ref->dev, NULL, "DMA-API: device driver tries "
-			   "to free an invalid DMA memory address\n");
-		return;
-	}
-
 	bucket = get_hash_bucket(ref, &flags);
 	entry = bucket_find_exact(bucket, ref);
 
 	if (!entry) {
+		if (dma_mapping_error(ref->dev, ref->dev_addr)) {
+			err_printk(ref->dev, NULL,
+				   "DMA-API: device driver tries "
+				   "to free an invalid DMA memory address\n");
+			return;
+		}
 		err_printk(ref->dev, NULL, "DMA-API: device driver tries "
 			   "to free DMA memory it has not allocated "
 			   "[device address=0x%016llx] [size=%llu bytes]\n",
@@ -910,6 +924,15 @@ static void check_unmap(struct dma_debug_entry *ref)
 			   dir2name[ref->direction]);
 	}
 
+	if (entry->map_err_type == MAP_ERR_NOT_CHECKED) {
+		err_printk(ref->dev, entry,
+			   "DMA-API: device driver failed to check map error"
+			   "[device address=0x%016llx] [size=%llu bytes] "
+			   "[mapped as %s]",
+			   ref->dev_addr, ref->size,
+			   type2name[entry->type]);
+	}
+
 	hash_bucket_del(entry);
 	dma_entry_free(entry);
 
@@ -1017,7 +1040,7 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
 	if (unlikely(global_disable))
 		return;
 
-	if (unlikely(dma_mapping_error(dev, dma_addr)))
+	if (dma_mapping_error(dev, dma_addr))
 		return;
 
 	entry = dma_entry_alloc();
@@ -1030,6 +1053,7 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
 	entry->dev_addr  = dma_addr;
 	entry->size      = size;
 	entry->direction = direction;
+	entry->map_err_type = MAP_ERR_NOT_CHECKED;
 
 	if (map_single)
 		entry->type = dma_debug_single;
@@ -1045,6 +1069,30 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
 }
 EXPORT_SYMBOL(debug_dma_map_page);
 
+void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+	struct dma_debug_entry ref;
+	struct dma_debug_entry *entry;
+	struct hash_bucket *bucket;
+	unsigned long flags;
+
+	if (unlikely(global_disable))
+		return;
+
+	ref.dev = dev;
+	ref.dev_addr = dma_addr;
+	bucket = get_hash_bucket(&ref, &flags);
+	entry = bucket_find_exact(bucket, &ref);
+
+	if (!entry)
+		goto out;
+
+	entry->map_err_type = MAP_ERR_CHECKED;
+out:
+	put_hash_bucket(bucket, &flags);
+}
+EXPORT_SYMBOL(debug_dma_mapping_error);
+
 void debug_dma_unmap_page(struct device *dev, dma_addr_t addr,
 			  size_t size, int direction, bool map_single)
 {
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index e7f7d99..1db1fc6 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -62,13 +62,6 @@ static LIST_HEAD(ddebug_tables);
 static int verbose = 0;
 module_param(verbose, int, 0644);
 
-/* Return the last part of a pathname */
-static inline const char *basename(const char *path)
-{
-	const char *tail = strrchr(path, '/');
-	return tail ? tail+1 : path;
-}
-
 /* Return the path relative to source root */
 static inline const char *trim_prefix(const char *path)
 {
@@ -154,7 +147,7 @@ static int ddebug_change(const struct ddebug_query *query,
 			/* match against the source filename */
 			if (query->filename &&
 			    strcmp(query->filename, dp->filename) &&
-			    strcmp(query->filename, basename(dp->filename)) &&
+			    strcmp(query->filename, kbasename(dp->filename)) &&
 			    strcmp(query->filename, trim_prefix(dp->filename)))
 				continue;
 
diff --git a/lib/earlycpio.c b/lib/earlycpio.c
new file mode 100644
index 0000000..8078ef4
--- /dev/null
+++ b/lib/earlycpio.c
@@ -0,0 +1,145 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2012 Intel Corporation; author H. Peter Anvin
+ *
+ *   This file is part of the Linux kernel, and is made available
+ *   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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * earlycpio.c
+ *
+ * Find a specific cpio member; must precede any compressed content.
+ * This is used to locate data items in the initramfs used by the
+ * kernel itself during early boot (before the main initramfs is
+ * decompressed.)  It is the responsibility of the initramfs creator
+ * to ensure that these items are uncompressed at the head of the
+ * blob.  Depending on the boot loader or package tool that may be a
+ * separate file or part of the same file.
+ */
+
+#include <linux/earlycpio.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+enum cpio_fields {
+	C_MAGIC,
+	C_INO,
+	C_MODE,
+	C_UID,
+	C_GID,
+	C_NLINK,
+	C_MTIME,
+	C_FILESIZE,
+	C_MAJ,
+	C_MIN,
+	C_RMAJ,
+	C_RMIN,
+	C_NAMESIZE,
+	C_CHKSUM,
+	C_NFIELDS
+};
+
+/**
+ * cpio_data find_cpio_data - Search for files in an uncompressed cpio
+ * @path:   The directory to search for, including a slash at the end
+ * @data:   Pointer to the the cpio archive or a header inside
+ * @len:    Remaining length of the cpio based on data pointer
+ * @offset: When a matching file is found, this is the offset to the
+ *          beginning of the cpio. It can be used to iterate through
+ *          the cpio to find all files inside of a directory path
+ *
+ * @return: struct cpio_data containing the address, length and
+ *          filename (with the directory path cut off) of the found file.
+ *          If you search for a filename and not for files in a directory,
+ *          pass the absolute path of the filename in the cpio and make sure
+ *          the match returned an empty filename string.
+ */
+
+struct cpio_data __cpuinit find_cpio_data(const char *path, void *data,
+					  size_t len,  long *offset)
+{
+	const size_t cpio_header_len = 8*C_NFIELDS - 2;
+	struct cpio_data cd = { NULL, 0, "" };
+	const char *p, *dptr, *nptr;
+	unsigned int ch[C_NFIELDS], *chp, v;
+	unsigned char c, x;
+	size_t mypathsize = strlen(path);
+	int i, j;
+
+	p = data;
+
+	while (len > cpio_header_len) {
+		if (!*p) {
+			/* All cpio headers need to be 4-byte aligned */
+			p += 4;
+			len -= 4;
+			continue;
+		}
+
+		j = 6;		/* The magic field is only 6 characters */
+		chp = ch;
+		for (i = C_NFIELDS; i; i--) {
+			v = 0;
+			while (j--) {
+				v <<= 4;
+				c = *p++;
+
+				x = c - '0';
+				if (x < 10) {
+					v += x;
+					continue;
+				}
+
+				x = (c | 0x20) - 'a';
+				if (x < 6) {
+					v += x + 10;
+					continue;
+				}
+
+				goto quit; /* Invalid hexadecimal */
+			}
+			*chp++ = v;
+			j = 8;	/* All other fields are 8 characters */
+		}
+
+		if ((ch[C_MAGIC] - 0x070701) > 1)
+			goto quit; /* Invalid magic */
+
+		len -= cpio_header_len;
+
+		dptr = PTR_ALIGN(p + ch[C_NAMESIZE], 4);
+		nptr = PTR_ALIGN(dptr + ch[C_FILESIZE], 4);
+
+		if (nptr > p + len || dptr < p || nptr < dptr)
+			goto quit; /* Buffer overrun */
+
+		if ((ch[C_MODE] & 0170000) == 0100000 &&
+		    ch[C_NAMESIZE] >= mypathsize &&
+		    !memcmp(p, path, mypathsize)) {
+			*offset = (long)nptr - (long)data;
+			if (ch[C_NAMESIZE] - mypathsize >= MAX_CPIO_FILE_NAME) {
+				pr_warn(
+				"File %s exceeding MAX_CPIO_FILE_NAME [%d]\n",
+				p, MAX_CPIO_FILE_NAME);
+			}
+			strlcpy(cd.name, p + mypathsize, MAX_CPIO_FILE_NAME);
+
+			cd.data = (void *)dptr;
+			cd.size = ch[C_FILESIZE];
+			return cd; /* Found it! */
+		}
+		len -= (nptr - p);
+		p = nptr;
+	}
+
+quit:
+	return cd;
+}
diff --git a/lib/interval_tree_test_main.c b/lib/interval_tree_test_main.c
index b259039..245900b 100644
--- a/lib/interval_tree_test_main.c
+++ b/lib/interval_tree_test_main.c
@@ -30,7 +30,8 @@ static void init(void)
 {
 	int i;
 	for (i = 0; i < NODES; i++) {
-		u32 a = prandom32(&rnd), b = prandom32(&rnd);
+		u32 a = prandom_u32_state(&rnd);
+		u32 b = prandom_u32_state(&rnd);
 		if (a <= b) {
 			nodes[i].start = a;
 			nodes[i].last = b;
@@ -40,7 +41,7 @@ static void init(void)
 		}
 	}
 	for (i = 0; i < SEARCHES; i++)
-		queries[i] = prandom32(&rnd);
+		queries[i] = prandom_u32_state(&rnd);
 }
 
 static int interval_tree_test_init(void)
@@ -51,7 +52,7 @@ static int interval_tree_test_init(void)
 
 	printk(KERN_ALERT "interval tree insert/remove");
 
-	prandom32_seed(&rnd, 3141592653589793238ULL);
+	prandom_seed_state(&rnd, 3141592653589793238ULL);
 	init();
 
 	time1 = get_cycles();
diff --git a/lib/kstrtox.c b/lib/kstrtox.c
index c3615ea..f78ae0c 100644
--- a/lib/kstrtox.c
+++ b/lib/kstrtox.c
@@ -104,6 +104,22 @@ static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
 	return 0;
 }
 
+/**
+ * kstrtoull - convert a string to an unsigned long long
+ * @s: The start of the string. The string must be null-terminated, and may also
+ *  include a single newline before its terminating null. The first character
+ *  may also be a plus sign, but not a minus sign.
+ * @base: The number base to use. The maximum supported base is 16. If base is
+ *  given as 0, then the base of the string is automatically detected with the
+ *  conventional semantics - If it begins with 0x the number will be parsed as a
+ *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
+ *  parsed as an octal number. Otherwise it will be parsed as a decimal.
+ * @res: Where to write the result of the conversion on success.
+ *
+ * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
+ * Used as a replacement for the obsolete simple_strtoull. Return code must
+ * be checked.
+ */
 int kstrtoull(const char *s, unsigned int base, unsigned long long *res)
 {
 	if (s[0] == '+')
@@ -112,6 +128,22 @@ int kstrtoull(const char *s, unsigned int base, unsigned long long *res)
 }
 EXPORT_SYMBOL(kstrtoull);
 
+/**
+ * kstrtoll - convert a string to a long long
+ * @s: The start of the string. The string must be null-terminated, and may also
+ *  include a single newline before its terminating null. The first character
+ *  may also be a plus sign or a minus sign.
+ * @base: The number base to use. The maximum supported base is 16. If base is
+ *  given as 0, then the base of the string is automatically detected with the
+ *  conventional semantics - If it begins with 0x the number will be parsed as a
+ *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
+ *  parsed as an octal number. Otherwise it will be parsed as a decimal.
+ * @res: Where to write the result of the conversion on success.
+ *
+ * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
+ * Used as a replacement for the obsolete simple_strtoull. Return code must
+ * be checked.
+ */
 int kstrtoll(const char *s, unsigned int base, long long *res)
 {
 	unsigned long long tmp;
@@ -168,6 +200,22 @@ int _kstrtol(const char *s, unsigned int base, long *res)
 }
 EXPORT_SYMBOL(_kstrtol);
 
+/**
+ * kstrtouint - convert a string to an unsigned int
+ * @s: The start of the string. The string must be null-terminated, and may also
+ *  include a single newline before its terminating null. The first character
+ *  may also be a plus sign, but not a minus sign.
+ * @base: The number base to use. The maximum supported base is 16. If base is
+ *  given as 0, then the base of the string is automatically detected with the
+ *  conventional semantics - If it begins with 0x the number will be parsed as a
+ *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
+ *  parsed as an octal number. Otherwise it will be parsed as a decimal.
+ * @res: Where to write the result of the conversion on success.
+ *
+ * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
+ * Used as a replacement for the obsolete simple_strtoull. Return code must
+ * be checked.
+ */
 int kstrtouint(const char *s, unsigned int base, unsigned int *res)
 {
 	unsigned long long tmp;
@@ -183,6 +231,22 @@ int kstrtouint(const char *s, unsigned int base, unsigned int *res)
 }
 EXPORT_SYMBOL(kstrtouint);
 
+/**
+ * kstrtoint - convert a string to an int
+ * @s: The start of the string. The string must be null-terminated, and may also
+ *  include a single newline before its terminating null. The first character
+ *  may also be a plus sign or a minus sign.
+ * @base: The number base to use. The maximum supported base is 16. If base is
+ *  given as 0, then the base of the string is automatically detected with the
+ *  conventional semantics - If it begins with 0x the number will be parsed as a
+ *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
+ *  parsed as an octal number. Otherwise it will be parsed as a decimal.
+ * @res: Where to write the result of the conversion on success.
+ *
+ * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
+ * Used as a replacement for the obsolete simple_strtoull. Return code must
+ * be checked.
+ */
 int kstrtoint(const char *s, unsigned int base, int *res)
 {
 	long long tmp;
diff --git a/lib/lru_cache.c b/lib/lru_cache.c
index a07e726..d71d894 100644
--- a/lib/lru_cache.c
+++ b/lib/lru_cache.c
@@ -44,8 +44,8 @@ MODULE_LICENSE("GPL");
 } while (0)
 
 #define RETURN(x...)     do { \
-	clear_bit(__LC_PARANOIA, &lc->flags); \
-	smp_mb__after_clear_bit(); return x ; } while (0)
+	clear_bit_unlock(__LC_PARANOIA, &lc->flags); \
+	return x ; } while (0)
 
 /* BUG() if e is not one of the elements tracked by lc */
 #define PARANOIA_LC_ELEMENT(lc, e) do {	\
@@ -55,9 +55,40 @@ MODULE_LICENSE("GPL");
 	BUG_ON(i >= lc_->nr_elements);	\
 	BUG_ON(lc_->lc_element[i] != e_); } while (0)
 
+
+/* We need to atomically
+ *  - try to grab the lock (set LC_LOCKED)
+ *  - only if there is no pending transaction
+ *    (neither LC_DIRTY nor LC_STARVING is set)
+ * Because of PARANOIA_ENTRY() above abusing lc->flags as well,
+ * it is not sufficient to just say
+ *	return 0 == cmpxchg(&lc->flags, 0, LC_LOCKED);
+ */
+int lc_try_lock(struct lru_cache *lc)
+{
+	unsigned long val;
+	do {
+		val = cmpxchg(&lc->flags, 0, LC_LOCKED);
+	} while (unlikely (val == LC_PARANOIA));
+	/* Spin until no-one is inside a PARANOIA_ENTRY()/RETURN() section. */
+	return 0 == val;
+#if 0
+	/* Alternative approach, spin in case someone enters or leaves a
+	 * PARANOIA_ENTRY()/RETURN() section. */
+	unsigned long old, new, val;
+	do {
+		old = lc->flags & LC_PARANOIA;
+		new = old | LC_LOCKED;
+		val = cmpxchg(&lc->flags, old, new);
+	} while (unlikely (val == (old ^ LC_PARANOIA)));
+	return old == val;
+#endif
+}
+
 /**
  * lc_create - prepares to track objects in an active set
  * @name: descriptive name only used in lc_seq_printf_stats and lc_seq_dump_details
+ * @max_pending_changes: maximum changes to accumulate until a transaction is required
  * @e_count: number of elements allowed to be active simultaneously
  * @e_size: size of the tracked objects
  * @e_off: offset to the &struct lc_element member in a tracked object
@@ -66,6 +97,7 @@ MODULE_LICENSE("GPL");
  * or NULL on (allocation) failure.
  */
 struct lru_cache *lc_create(const char *name, struct kmem_cache *cache,
+		unsigned max_pending_changes,
 		unsigned e_count, size_t e_size, size_t e_off)
 {
 	struct hlist_head *slot = NULL;
@@ -98,12 +130,13 @@ struct lru_cache *lc_create(const char *name, struct kmem_cache *cache,
 	INIT_LIST_HEAD(&lc->in_use);
 	INIT_LIST_HEAD(&lc->lru);
 	INIT_LIST_HEAD(&lc->free);
+	INIT_LIST_HEAD(&lc->to_be_changed);
 
 	lc->name = name;
 	lc->element_size = e_size;
 	lc->element_off = e_off;
 	lc->nr_elements = e_count;
-	lc->new_number = LC_FREE;
+	lc->max_pending_changes = max_pending_changes;
 	lc->lc_cache = cache;
 	lc->lc_element = element;
 	lc->lc_slot = slot;
@@ -117,6 +150,7 @@ struct lru_cache *lc_create(const char *name, struct kmem_cache *cache,
 		e = p + e_off;
 		e->lc_index = i;
 		e->lc_number = LC_FREE;
+		e->lc_new_number = LC_FREE;
 		list_add(&e->list, &lc->free);
 		element[i] = e;
 	}
@@ -175,15 +209,15 @@ void lc_reset(struct lru_cache *lc)
 	INIT_LIST_HEAD(&lc->in_use);
 	INIT_LIST_HEAD(&lc->lru);
 	INIT_LIST_HEAD(&lc->free);
+	INIT_LIST_HEAD(&lc->to_be_changed);
 	lc->used = 0;
 	lc->hits = 0;
 	lc->misses = 0;
 	lc->starving = 0;
-	lc->dirty = 0;
+	lc->locked = 0;
 	lc->changed = 0;
+	lc->pending_changes = 0;
 	lc->flags = 0;
-	lc->changing_element = NULL;
-	lc->new_number = LC_FREE;
 	memset(lc->lc_slot, 0, sizeof(struct hlist_head) * lc->nr_elements);
 
 	for (i = 0; i < lc->nr_elements; i++) {
@@ -194,6 +228,7 @@ void lc_reset(struct lru_cache *lc)
 		/* re-init it */
 		e->lc_index = i;
 		e->lc_number = LC_FREE;
+		e->lc_new_number = LC_FREE;
 		list_add(&e->list, &lc->free);
 	}
 }
@@ -208,14 +243,14 @@ size_t lc_seq_printf_stats(struct seq_file *seq, struct lru_cache *lc)
 	/* NOTE:
 	 * total calls to lc_get are
 	 * (starving + hits + misses)
-	 * misses include "dirty" count (update from an other thread in
+	 * misses include "locked" count (update from an other thread in
 	 * progress) and "changed", when this in fact lead to an successful
 	 * update of the cache.
 	 */
 	return seq_printf(seq, "\t%s: used:%u/%u "
-		"hits:%lu misses:%lu starving:%lu dirty:%lu changed:%lu\n",
+		"hits:%lu misses:%lu starving:%lu locked:%lu changed:%lu\n",
 		lc->name, lc->used, lc->nr_elements,
-		lc->hits, lc->misses, lc->starving, lc->dirty, lc->changed);
+		lc->hits, lc->misses, lc->starving, lc->locked, lc->changed);
 }
 
 static struct hlist_head *lc_hash_slot(struct lru_cache *lc, unsigned int enr)
@@ -224,16 +259,8 @@ static struct hlist_head *lc_hash_slot(struct lru_cache *lc, unsigned int enr)
 }
 
 
-/**
- * lc_find - find element by label, if present in the hash table
- * @lc: The lru_cache object
- * @enr: element number
- *
- * Returns the pointer to an element, if the element with the requested
- * "label" or element number is present in the hash table,
- * or NULL if not found. Does not change the refcnt.
- */
-struct lc_element *lc_find(struct lru_cache *lc, unsigned int enr)
+static struct lc_element *__lc_find(struct lru_cache *lc, unsigned int enr,
+		bool include_changing)
 {
 	struct hlist_node *n;
 	struct lc_element *e;
@@ -241,29 +268,48 @@ struct lc_element *lc_find(struct lru_cache *lc, unsigned int enr)
 	BUG_ON(!lc);
 	BUG_ON(!lc->nr_elements);
 	hlist_for_each_entry(e, n, lc_hash_slot(lc, enr), colision) {
-		if (e->lc_number == enr)
+		/* "about to be changed" elements, pending transaction commit,
+		 * are hashed by their "new number". "Normal" elements have
+		 * lc_number == lc_new_number. */
+		if (e->lc_new_number != enr)
+			continue;
+		if (e->lc_new_number == e->lc_number || include_changing)
 			return e;
+		break;
 	}
 	return NULL;
 }
 
-/* returned element will be "recycled" immediately */
-static struct lc_element *lc_evict(struct lru_cache *lc)
+/**
+ * lc_find - find element by label, if present in the hash table
+ * @lc: The lru_cache object
+ * @enr: element number
+ *
+ * Returns the pointer to an element, if the element with the requested
+ * "label" or element number is present in the hash table,
+ * or NULL if not found. Does not change the refcnt.
+ * Ignores elements that are "about to be used", i.e. not yet in the active
+ * set, but still pending transaction commit.
+ */
+struct lc_element *lc_find(struct lru_cache *lc, unsigned int enr)
 {
-	struct list_head  *n;
-	struct lc_element *e;
-
-	if (list_empty(&lc->lru))
-		return NULL;
-
-	n = lc->lru.prev;
-	e = list_entry(n, struct lc_element, list);
-
-	PARANOIA_LC_ELEMENT(lc, e);
+	return __lc_find(lc, enr, 0);
+}
 
-	list_del(&e->list);
-	hlist_del(&e->colision);
-	return e;
+/**
+ * lc_is_used - find element by label
+ * @lc: The lru_cache object
+ * @enr: element number
+ *
+ * Returns true, if the element with the requested "label" or element number is
+ * present in the hash table, and is used (refcnt > 0).
+ * Also finds elements that are not _currently_ used but only "about to be
+ * used", i.e. on the "to_be_changed" list, pending transaction commit.
+ */
+bool lc_is_used(struct lru_cache *lc, unsigned int enr)
+{
+	struct lc_element *e = __lc_find(lc, enr, 1);
+	return e && e->refcnt;
 }
 
 /**
@@ -280,22 +326,34 @@ void lc_del(struct lru_cache *lc, struct lc_element *e)
 	PARANOIA_LC_ELEMENT(lc, e);
 	BUG_ON(e->refcnt);
 
-	e->lc_number = LC_FREE;
+	e->lc_number = e->lc_new_number = LC_FREE;
 	hlist_del_init(&e->colision);
 	list_move(&e->list, &lc->free);
 	RETURN();
 }
 
-static struct lc_element *lc_get_unused_element(struct lru_cache *lc)
+static struct lc_element *lc_prepare_for_change(struct lru_cache *lc, unsigned new_number)
 {
 	struct list_head *n;
+	struct lc_element *e;
+
+	if (!list_empty(&lc->free))
+		n = lc->free.next;
+	else if (!list_empty(&lc->lru))
+		n = lc->lru.prev;
+	else
+		return NULL;
+
+	e = list_entry(n, struct lc_element, list);
+	PARANOIA_LC_ELEMENT(lc, e);
 
-	if (list_empty(&lc->free))
-		return lc_evict(lc);
+	e->lc_new_number = new_number;
+	if (!hlist_unhashed(&e->colision))
+		__hlist_del(&e->colision);
+	hlist_add_head(&e->colision, lc_hash_slot(lc, new_number));
+	list_move(&e->list, &lc->to_be_changed);
 
-	n = lc->free.next;
-	list_del(n);
-	return list_entry(n, struct lc_element, list);
+	return e;
 }
 
 static int lc_unused_element_available(struct lru_cache *lc)
@@ -308,45 +366,7 @@ static int lc_unused_element_available(struct lru_cache *lc)
 	return 0;
 }
 
-
-/**
- * lc_get - get element by label, maybe change the active set
- * @lc: the lru cache to operate on
- * @enr: the label to look up
- *
- * Finds an element in the cache, increases its usage count,
- * "touches" and returns it.
- *
- * In case the requested number is not present, it needs to be added to the
- * cache. Therefore it is possible that an other element becomes evicted from
- * the cache. In either case, the user is notified so he is able to e.g. keep
- * a persistent log of the cache changes, and therefore the objects in use.
- *
- * Return values:
- *  NULL
- *     The cache was marked %LC_STARVING,
- *     or the requested label was not in the active set
- *     and a changing transaction is still pending (@lc was marked %LC_DIRTY).
- *     Or no unused or free element could be recycled (@lc will be marked as
- *     %LC_STARVING, blocking further lc_get() operations).
- *
- *  pointer to the element with the REQUESTED element number.
- *     In this case, it can be used right away
- *
- *  pointer to an UNUSED element with some different element number,
- *          where that different number may also be %LC_FREE.
- *
- *          In this case, the cache is marked %LC_DIRTY (blocking further changes),
- *          and the returned element pointer is removed from the lru list and
- *          hash collision chains.  The user now should do whatever housekeeping
- *          is necessary.
- *          Then he must call lc_changed(lc,element_pointer), to finish
- *          the change.
- *
- * NOTE: The user needs to check the lc_number on EACH use, so he recognizes
- *       any cache set change.
- */
-struct lc_element *lc_get(struct lru_cache *lc, unsigned int enr)
+static struct lc_element *__lc_get(struct lru_cache *lc, unsigned int enr, bool may_change)
 {
 	struct lc_element *e;
 
@@ -356,8 +376,12 @@ struct lc_element *lc_get(struct lru_cache *lc, unsigned int enr)
 		RETURN(NULL);
 	}
 
-	e = lc_find(lc, enr);
-	if (e) {
+	e = __lc_find(lc, enr, 1);
+	/* if lc_new_number != lc_number,
+	 * this enr is currently being pulled in already,
+	 * and will be available once the pending transaction
+	 * has been committed. */
+	if (e && e->lc_new_number == e->lc_number) {
 		++lc->hits;
 		if (e->refcnt++ == 0)
 			lc->used++;
@@ -366,6 +390,26 @@ struct lc_element *lc_get(struct lru_cache *lc, unsigned int enr)
 	}
 
 	++lc->misses;
+	if (!may_change)
+		RETURN(NULL);
+
+	/* It has been found above, but on the "to_be_changed" list, not yet
+	 * committed.  Don't pull it in twice, wait for the transaction, then
+	 * try again */
+	if (e)
+		RETURN(NULL);
+
+	/* To avoid races with lc_try_lock(), first, mark us dirty
+	 * (using test_and_set_bit, as it implies memory barriers), ... */
+	test_and_set_bit(__LC_DIRTY, &lc->flags);
+
+	/* ... only then check if it is locked anyways. If lc_unlock clears
+	 * the dirty bit again, that's not a problem, we will come here again.
+	 */
+	if (test_bit(__LC_LOCKED, &lc->flags)) {
+		++lc->locked;
+		RETURN(NULL);
+	}
 
 	/* In case there is nothing available and we can not kick out
 	 * the LRU element, we have to wait ...
@@ -375,71 +419,109 @@ struct lc_element *lc_get(struct lru_cache *lc, unsigned int enr)
 		RETURN(NULL);
 	}
 
-	/* it was not present in the active set.
-	 * we are going to recycle an unused (or even "free") element.
-	 * user may need to commit a transaction to record that change.
-	 * we serialize on flags & TF_DIRTY */
-	if (test_and_set_bit(__LC_DIRTY, &lc->flags)) {
-		++lc->dirty;
+	/* It was not present in the active set.  We are going to recycle an
+	 * unused (or even "free") element, but we won't accumulate more than
+	 * max_pending_changes changes.  */
+	if (lc->pending_changes >= lc->max_pending_changes)
 		RETURN(NULL);
-	}
 
-	e = lc_get_unused_element(lc);
+	e = lc_prepare_for_change(lc, enr);
 	BUG_ON(!e);
 
 	clear_bit(__LC_STARVING, &lc->flags);
 	BUG_ON(++e->refcnt != 1);
 	lc->used++;
-
-	lc->changing_element = e;
-	lc->new_number = enr;
+	lc->pending_changes++;
 
 	RETURN(e);
 }
 
-/* similar to lc_get,
- * but only gets a new reference on an existing element.
- * you either get the requested element, or NULL.
- * will be consolidated into one function.
+/**
+ * lc_get - get element by label, maybe change the active set
+ * @lc: the lru cache to operate on
+ * @enr: the label to look up
+ *
+ * Finds an element in the cache, increases its usage count,
+ * "touches" and returns it.
+ *
+ * In case the requested number is not present, it needs to be added to the
+ * cache. Therefore it is possible that an other element becomes evicted from
+ * the cache. In either case, the user is notified so he is able to e.g. keep
+ * a persistent log of the cache changes, and therefore the objects in use.
+ *
+ * Return values:
+ *  NULL
+ *     The cache was marked %LC_STARVING,
+ *     or the requested label was not in the active set
+ *     and a changing transaction is still pending (@lc was marked %LC_DIRTY).
+ *     Or no unused or free element could be recycled (@lc will be marked as
+ *     %LC_STARVING, blocking further lc_get() operations).
+ *
+ *  pointer to the element with the REQUESTED element number.
+ *     In this case, it can be used right away
+ *
+ *  pointer to an UNUSED element with some different element number,
+ *          where that different number may also be %LC_FREE.
+ *
+ *          In this case, the cache is marked %LC_DIRTY,
+ *          so lc_try_lock() will no longer succeed.
+ *          The returned element pointer is moved to the "to_be_changed" list,
+ *          and registered with the new element number on the hash collision chains,
+ *          so it is possible to pick it up from lc_is_used().
+ *          Up to "max_pending_changes" (see lc_create()) can be accumulated.
+ *          The user now should do whatever housekeeping is necessary,
+ *          typically serialize on lc_try_lock_for_transaction(), then call
+ *          lc_committed(lc) and lc_unlock(), to finish the change.
+ *
+ * NOTE: The user needs to check the lc_number on EACH use, so he recognizes
+ *       any cache set change.
  */
-struct lc_element *lc_try_get(struct lru_cache *lc, unsigned int enr)
+struct lc_element *lc_get(struct lru_cache *lc, unsigned int enr)
 {
-	struct lc_element *e;
-
-	PARANOIA_ENTRY();
-	if (lc->flags & LC_STARVING) {
-		++lc->starving;
-		RETURN(NULL);
-	}
+	return __lc_get(lc, enr, 1);
+}
 
-	e = lc_find(lc, enr);
-	if (e) {
-		++lc->hits;
-		if (e->refcnt++ == 0)
-			lc->used++;
-		list_move(&e->list, &lc->in_use); /* Not evictable... */
-	}
-	RETURN(e);
+/**
+ * lc_try_get - get element by label, if present; do not change the active set
+ * @lc: the lru cache to operate on
+ * @enr: the label to look up
+ *
+ * Finds an element in the cache, increases its usage count,
+ * "touches" and returns it.
+ *
+ * Return values:
+ *  NULL
+ *     The cache was marked %LC_STARVING,
+ *     or the requested label was not in the active set
+ *
+ *  pointer to the element with the REQUESTED element number.
+ *     In this case, it can be used right away
+ */
+struct lc_element *lc_try_get(struct lru_cache *lc, unsigned int enr)
+{
+	return __lc_get(lc, enr, 0);
 }
 
 /**
- * lc_changed - tell @lc that the change has been recorded
+ * lc_committed - tell @lc that pending changes have been recorded
  * @lc: the lru cache to operate on
- * @e: the element pending label change
+ *
+ * User is expected to serialize on explicit lc_try_lock_for_transaction()
+ * before the transaction is started, and later needs to lc_unlock() explicitly
+ * as well.
  */
-void lc_changed(struct lru_cache *lc, struct lc_element *e)
+void lc_committed(struct lru_cache *lc)
 {
+	struct lc_element *e, *tmp;
+
 	PARANOIA_ENTRY();
-	BUG_ON(e != lc->changing_element);
-	PARANOIA_LC_ELEMENT(lc, e);
-	++lc->changed;
-	e->lc_number = lc->new_number;
-	list_add(&e->list, &lc->in_use);
-	hlist_add_head(&e->colision, lc_hash_slot(lc, lc->new_number));
-	lc->changing_element = NULL;
-	lc->new_number = LC_FREE;
-	clear_bit(__LC_DIRTY, &lc->flags);
-	smp_mb__after_clear_bit();
+	list_for_each_entry_safe(e, tmp, &lc->to_be_changed, list) {
+		/* count number of changes, not number of transactions */
+		++lc->changed;
+		e->lc_number = e->lc_new_number;
+		list_move(&e->list, &lc->in_use);
+	}
+	lc->pending_changes = 0;
 	RETURN();
 }
 
@@ -458,13 +540,12 @@ unsigned int lc_put(struct lru_cache *lc, struct lc_element *e)
 	PARANOIA_ENTRY();
 	PARANOIA_LC_ELEMENT(lc, e);
 	BUG_ON(e->refcnt == 0);
-	BUG_ON(e == lc->changing_element);
+	BUG_ON(e->lc_number != e->lc_new_number);
 	if (--e->refcnt == 0) {
 		/* move it to the front of LRU. */
 		list_move(&e->list, &lc->lru);
 		lc->used--;
-		clear_bit(__LC_STARVING, &lc->flags);
-		smp_mb__after_clear_bit();
+		clear_bit_unlock(__LC_STARVING, &lc->flags);
 	}
 	RETURN(e->refcnt);
 }
@@ -504,16 +585,24 @@ unsigned int lc_index_of(struct lru_cache *lc, struct lc_element *e)
 void lc_set(struct lru_cache *lc, unsigned int enr, int index)
 {
 	struct lc_element *e;
+	struct list_head *lh;
 
 	if (index < 0 || index >= lc->nr_elements)
 		return;
 
 	e = lc_element_by_index(lc, index);
-	e->lc_number = enr;
+	BUG_ON(e->lc_number != e->lc_new_number);
+	BUG_ON(e->refcnt != 0);
 
+	e->lc_number = e->lc_new_number = enr;
 	hlist_del_init(&e->colision);
-	hlist_add_head(&e->colision, lc_hash_slot(lc, enr));
-	list_move(&e->list, e->refcnt ? &lc->in_use : &lc->lru);
+	if (enr == LC_FREE)
+		lh = &lc->free;
+	else {
+		hlist_add_head(&e->colision, lc_hash_slot(lc, enr));
+		lh = &lc->lru;
+	}
+	list_move(&e->list, lh);
 }
 
 /**
@@ -553,8 +642,10 @@ EXPORT_SYMBOL(lc_try_get);
 EXPORT_SYMBOL(lc_find);
 EXPORT_SYMBOL(lc_get);
 EXPORT_SYMBOL(lc_put);
-EXPORT_SYMBOL(lc_changed);
+EXPORT_SYMBOL(lc_committed);
 EXPORT_SYMBOL(lc_element_by_index);
 EXPORT_SYMBOL(lc_index_of);
 EXPORT_SYMBOL(lc_seq_printf_stats);
 EXPORT_SYMBOL(lc_seq_dump_details);
+EXPORT_SYMBOL(lc_try_lock);
+EXPORT_SYMBOL(lc_is_used);
diff --git a/lib/lzo/Makefile b/lib/lzo/Makefile
index e764116..f0f7d7c 100644
--- a/lib/lzo/Makefile
+++ b/lib/lzo/Makefile
@@ -1,5 +1,5 @@
 lzo_compress-objs := lzo1x_compress.o
-lzo_decompress-objs := lzo1x_decompress.o
+lzo_decompress-objs := lzo1x_decompress_safe.o
 
 obj-$(CONFIG_LZO_COMPRESS) += lzo_compress.o
 obj-$(CONFIG_LZO_DECOMPRESS) += lzo_decompress.o
diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c
index a604099..236eb21 100644
--- a/lib/lzo/lzo1x_compress.c
+++ b/lib/lzo/lzo1x_compress.c
@@ -1,194 +1,243 @@
 /*
- *  LZO1X Compressor from MiniLZO
+ *  LZO1X Compressor from LZO
  *
- *  Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *  Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
  *
  *  The full LZO package can be found at:
  *  http://www.oberhumer.com/opensource/lzo/
  *
- *  Changed for kernel use by:
+ *  Changed for Linux kernel use by:
  *  Nitin Gupta <nitingupta910@gmail.com>
  *  Richard Purdie <rpurdie@openedhand.com>
  */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/lzo.h>
 #include <asm/unaligned.h>
+#include <linux/lzo.h>
 #include "lzodefs.h"
 
 static noinline size_t
-_lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
-		unsigned char *out, size_t *out_len, void *wrkmem)
+lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
+		    unsigned char *out, size_t *out_len,
+		    size_t ti, void *wrkmem)
 {
+	const unsigned char *ip;
+	unsigned char *op;
 	const unsigned char * const in_end = in + in_len;
-	const unsigned char * const ip_end = in + in_len - M2_MAX_LEN - 5;
-	const unsigned char ** const dict = wrkmem;
-	const unsigned char *ip = in, *ii = ip;
-	const unsigned char *end, *m, *m_pos;
-	size_t m_off, m_len, dindex;
-	unsigned char *op = out;
+	const unsigned char * const ip_end = in + in_len - 20;
+	const unsigned char *ii;
+	lzo_dict_t * const dict = (lzo_dict_t *) wrkmem;
 
-	ip += 4;
+	op = out;
+	ip = in;
+	ii = ip;
+	ip += ti < 4 ? 4 - ti : 0;
 
 	for (;;) {
-		dindex = ((size_t)(0x21 * DX3(ip, 5, 5, 6)) >> 5) & D_MASK;
-		m_pos = dict[dindex];
-
-		if (m_pos < in)
-			goto literal;
-
-		if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET))
-			goto literal;
-
-		m_off = ip - m_pos;
-		if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
-			goto try_match;
-
-		dindex = (dindex & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f);
-		m_pos = dict[dindex];
-
-		if (m_pos < in)
-			goto literal;
-
-		if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET))
-			goto literal;
-
-		m_off = ip - m_pos;
-		if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
-			goto try_match;
-
-		goto literal;
-
-try_match:
-		if (get_unaligned((const unsigned short *)m_pos)
-				== get_unaligned((const unsigned short *)ip)) {
-			if (likely(m_pos[2] == ip[2]))
-					goto match;
-		}
-
+		const unsigned char *m_pos;
+		size_t t, m_len, m_off;
+		u32 dv;
 literal:
-		dict[dindex] = ip;
-		++ip;
+		ip += 1 + ((ip - ii) >> 5);
+next:
 		if (unlikely(ip >= ip_end))
 			break;
-		continue;
-
-match:
-		dict[dindex] = ip;
-		if (ip != ii) {
-			size_t t = ip - ii;
+		dv = get_unaligned_le32(ip);
+		t = ((dv * 0x1824429d) >> (32 - D_BITS)) & D_MASK;
+		m_pos = in + dict[t];
+		dict[t] = (lzo_dict_t) (ip - in);
+		if (unlikely(dv != get_unaligned_le32(m_pos)))
+			goto literal;
 
+		ii -= ti;
+		ti = 0;
+		t = ip - ii;
+		if (t != 0) {
 			if (t <= 3) {
 				op[-2] |= t;
-			} else if (t <= 18) {
+				COPY4(op, ii);
+				op += t;
+			} else if (t <= 16) {
 				*op++ = (t - 3);
+				COPY8(op, ii);
+				COPY8(op + 8, ii + 8);
+				op += t;
 			} else {
-				size_t tt = t - 18;
-
-				*op++ = 0;
-				while (tt > 255) {
-					tt -= 255;
+				if (t <= 18) {
+					*op++ = (t - 3);
+				} else {
+					size_t tt = t - 18;
 					*op++ = 0;
+					while (unlikely(tt > 255)) {
+						tt -= 255;
+						*op++ = 0;
+					}
+					*op++ = tt;
 				}
-				*op++ = tt;
+				do {
+					COPY8(op, ii);
+					COPY8(op + 8, ii + 8);
+					op += 16;
+					ii += 16;
+					t -= 16;
+				} while (t >= 16);
+				if (t > 0) do {
+					*op++ = *ii++;
+				} while (--t > 0);
 			}
-			do {
-				*op++ = *ii++;
-			} while (--t > 0);
 		}
 
-		ip += 3;
-		if (m_pos[3] != *ip++ || m_pos[4] != *ip++
-				|| m_pos[5] != *ip++ || m_pos[6] != *ip++
-				|| m_pos[7] != *ip++ || m_pos[8] != *ip++) {
-			--ip;
-			m_len = ip - ii;
+		m_len = 4;
+		{
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ64)
+		u64 v;
+		v = get_unaligned((const u64 *) (ip + m_len)) ^
+		    get_unaligned((const u64 *) (m_pos + m_len));
+		if (unlikely(v == 0)) {
+			do {
+				m_len += 8;
+				v = get_unaligned((const u64 *) (ip + m_len)) ^
+				    get_unaligned((const u64 *) (m_pos + m_len));
+				if (unlikely(ip + m_len >= ip_end))
+					goto m_len_done;
+			} while (v == 0);
+		}
+#  if defined(__LITTLE_ENDIAN)
+		m_len += (unsigned) __builtin_ctzll(v) / 8;
+#  elif defined(__BIG_ENDIAN)
+		m_len += (unsigned) __builtin_clzll(v) / 8;
+#  else
+#    error "missing endian definition"
+#  endif
+#elif defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ32)
+		u32 v;
+		v = get_unaligned((const u32 *) (ip + m_len)) ^
+		    get_unaligned((const u32 *) (m_pos + m_len));
+		if (unlikely(v == 0)) {
+			do {
+				m_len += 4;
+				v = get_unaligned((const u32 *) (ip + m_len)) ^
+				    get_unaligned((const u32 *) (m_pos + m_len));
+				if (v != 0)
+					break;
+				m_len += 4;
+				v = get_unaligned((const u32 *) (ip + m_len)) ^
+				    get_unaligned((const u32 *) (m_pos + m_len));
+				if (unlikely(ip + m_len >= ip_end))
+					goto m_len_done;
+			} while (v == 0);
+		}
+#  if defined(__LITTLE_ENDIAN)
+		m_len += (unsigned) __builtin_ctz(v) / 8;
+#  elif defined(__BIG_ENDIAN)
+		m_len += (unsigned) __builtin_clz(v) / 8;
+#  else
+#    error "missing endian definition"
+#  endif
+#else
+		if (unlikely(ip[m_len] == m_pos[m_len])) {
+			do {
+				m_len += 1;
+				if (ip[m_len] != m_pos[m_len])
+					break;
+				m_len += 1;
+				if (ip[m_len] != m_pos[m_len])
+					break;
+				m_len += 1;
+				if (ip[m_len] != m_pos[m_len])
+					break;
+				m_len += 1;
+				if (ip[m_len] != m_pos[m_len])
+					break;
+				m_len += 1;
+				if (ip[m_len] != m_pos[m_len])
+					break;
+				m_len += 1;
+				if (ip[m_len] != m_pos[m_len])
+					break;
+				m_len += 1;
+				if (ip[m_len] != m_pos[m_len])
+					break;
+				m_len += 1;
+				if (unlikely(ip + m_len >= ip_end))
+					goto m_len_done;
+			} while (ip[m_len] == m_pos[m_len]);
+		}
+#endif
+		}
+m_len_done:
 
-			if (m_off <= M2_MAX_OFFSET) {
-				m_off -= 1;
-				*op++ = (((m_len - 1) << 5)
-						| ((m_off & 7) << 2));
-				*op++ = (m_off >> 3);
-			} else if (m_off <= M3_MAX_OFFSET) {
-				m_off -= 1;
+		m_off = ip - m_pos;
+		ip += m_len;
+		ii = ip;
+		if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) {
+			m_off -= 1;
+			*op++ = (((m_len - 1) << 5) | ((m_off & 7) << 2));
+			*op++ = (m_off >> 3);
+		} else if (m_off <= M3_MAX_OFFSET) {
+			m_off -= 1;
+			if (m_len <= M3_MAX_LEN)
 				*op++ = (M3_MARKER | (m_len - 2));
-				goto m3_m4_offset;
-			} else {
-				m_off -= 0x4000;
-
-				*op++ = (M4_MARKER | ((m_off & 0x4000) >> 11)
-						| (m_len - 2));
-				goto m3_m4_offset;
+			else {
+				m_len -= M3_MAX_LEN;
+				*op++ = M3_MARKER | 0;
+				while (unlikely(m_len > 255)) {
+					m_len -= 255;
+					*op++ = 0;
+				}
+				*op++ = (m_len);
 			}
+			*op++ = (m_off << 2);
+			*op++ = (m_off >> 6);
 		} else {
-			end = in_end;
-			m = m_pos + M2_MAX_LEN + 1;
-
-			while (ip < end && *m == *ip) {
-				m++;
-				ip++;
-			}
-			m_len = ip - ii;
-
-			if (m_off <= M3_MAX_OFFSET) {
-				m_off -= 1;
-				if (m_len <= 33) {
-					*op++ = (M3_MARKER | (m_len - 2));
-				} else {
-					m_len -= 33;
-					*op++ = M3_MARKER | 0;
-					goto m3_m4_len;
-				}
-			} else {
-				m_off -= 0x4000;
-				if (m_len <= M4_MAX_LEN) {
-					*op++ = (M4_MARKER
-						| ((m_off & 0x4000) >> 11)
+			m_off -= 0x4000;
+			if (m_len <= M4_MAX_LEN)
+				*op++ = (M4_MARKER | ((m_off >> 11) & 8)
 						| (m_len - 2));
-				} else {
-					m_len -= M4_MAX_LEN;
-					*op++ = (M4_MARKER
-						| ((m_off & 0x4000) >> 11));
-m3_m4_len:
-					while (m_len > 255) {
-						m_len -= 255;
-						*op++ = 0;
-					}
-
-					*op++ = (m_len);
+			else {
+				m_len -= M4_MAX_LEN;
+				*op++ = (M4_MARKER | ((m_off >> 11) & 8));
+				while (unlikely(m_len > 255)) {
+					m_len -= 255;
+					*op++ = 0;
 				}
+				*op++ = (m_len);
 			}
-m3_m4_offset:
-			*op++ = ((m_off & 63) << 2);
+			*op++ = (m_off << 2);
 			*op++ = (m_off >> 6);
 		}
-
-		ii = ip;
-		if (unlikely(ip >= ip_end))
-			break;
+		goto next;
 	}
-
 	*out_len = op - out;
-	return in_end - ii;
+	return in_end - (ii - ti);
 }
 
-int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
-			size_t *out_len, void *wrkmem)
+int lzo1x_1_compress(const unsigned char *in, size_t in_len,
+		     unsigned char *out, size_t *out_len,
+		     void *wrkmem)
 {
-	const unsigned char *ii;
+	const unsigned char *ip = in;
 	unsigned char *op = out;
-	size_t t;
+	size_t l = in_len;
+	size_t t = 0;
 
-	if (unlikely(in_len <= M2_MAX_LEN + 5)) {
-		t = in_len;
-	} else {
-		t = _lzo1x_1_do_compress(in, in_len, op, out_len, wrkmem);
+	while (l > 20) {
+		size_t ll = l <= (M4_MAX_OFFSET + 1) ? l : (M4_MAX_OFFSET + 1);
+		uintptr_t ll_end = (uintptr_t) ip + ll;
+		if ((ll_end + ((t + ll) >> 5)) <= ll_end)
+			break;
+		BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS);
+		memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t));
+		t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem);
+		ip += ll;
 		op += *out_len;
+		l  -= ll;
 	}
+	t += l;
 
 	if (t > 0) {
-		ii = in + in_len - t;
+		const unsigned char *ii = in + in_len - t;
 
 		if (op == out && t <= 238) {
 			*op++ = (17 + t);
@@ -198,16 +247,21 @@ int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
 			*op++ = (t - 3);
 		} else {
 			size_t tt = t - 18;
-
 			*op++ = 0;
 			while (tt > 255) {
 				tt -= 255;
 				*op++ = 0;
 			}
-
 			*op++ = tt;
 		}
-		do {
+		if (t >= 16) do {
+			COPY8(op, ii);
+			COPY8(op + 8, ii + 8);
+			op += 16;
+			ii += 16;
+			t -= 16;
+		} while (t >= 16);
+		if (t > 0) do {
 			*op++ = *ii++;
 		} while (--t > 0);
 	}
@@ -223,4 +277,3 @@ EXPORT_SYMBOL_GPL(lzo1x_1_compress);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("LZO1X-1 Compressor");
-
diff --git a/lib/lzo/lzo1x_decompress.c b/lib/lzo/lzo1x_decompress.c
deleted file mode 100644
index f2fd098..0000000
--- a/lib/lzo/lzo1x_decompress.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- *  LZO1X Decompressor from MiniLZO
- *
- *  Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
- *
- *  The full LZO package can be found at:
- *  http://www.oberhumer.com/opensource/lzo/
- *
- *  Changed for kernel use by:
- *  Nitin Gupta <nitingupta910@gmail.com>
- *  Richard Purdie <rpurdie@openedhand.com>
- */
-
-#ifndef STATIC
-#include <linux/module.h>
-#include <linux/kernel.h>
-#endif
-
-#include <asm/unaligned.h>
-#include <linux/lzo.h>
-#include "lzodefs.h"
-
-#define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x))
-#define HAVE_OP(x, op_end, op) ((size_t)(op_end - op) < (x))
-#define HAVE_LB(m_pos, out, op) (m_pos < out || m_pos >= op)
-
-#define COPY4(dst, src)	\
-		put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
-
-int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
-			unsigned char *out, size_t *out_len)
-{
-	const unsigned char * const ip_end = in + in_len;
-	unsigned char * const op_end = out + *out_len;
-	const unsigned char *ip = in, *m_pos;
-	unsigned char *op = out;
-	size_t t;
-
-	*out_len = 0;
-
-	if (*ip > 17) {
-		t = *ip++ - 17;
-		if (t < 4)
-			goto match_next;
-		if (HAVE_OP(t, op_end, op))
-			goto output_overrun;
-		if (HAVE_IP(t + 1, ip_end, ip))
-			goto input_overrun;
-		do {
-			*op++ = *ip++;
-		} while (--t > 0);
-		goto first_literal_run;
-	}
-
-	while ((ip < ip_end)) {
-		t = *ip++;
-		if (t >= 16)
-			goto match;
-		if (t == 0) {
-			if (HAVE_IP(1, ip_end, ip))
-				goto input_overrun;
-			while (*ip == 0) {
-				t += 255;
-				ip++;
-				if (HAVE_IP(1, ip_end, ip))
-					goto input_overrun;
-			}
-			t += 15 + *ip++;
-		}
-		if (HAVE_OP(t + 3, op_end, op))
-			goto output_overrun;
-		if (HAVE_IP(t + 4, ip_end, ip))
-			goto input_overrun;
-
-		COPY4(op, ip);
-		op += 4;
-		ip += 4;
-		if (--t > 0) {
-			if (t >= 4) {
-				do {
-					COPY4(op, ip);
-					op += 4;
-					ip += 4;
-					t -= 4;
-				} while (t >= 4);
-				if (t > 0) {
-					do {
-						*op++ = *ip++;
-					} while (--t > 0);
-				}
-			} else {
-				do {
-					*op++ = *ip++;
-				} while (--t > 0);
-			}
-		}
-
-first_literal_run:
-		t = *ip++;
-		if (t >= 16)
-			goto match;
-		m_pos = op - (1 + M2_MAX_OFFSET);
-		m_pos -= t >> 2;
-		m_pos -= *ip++ << 2;
-
-		if (HAVE_LB(m_pos, out, op))
-			goto lookbehind_overrun;
-
-		if (HAVE_OP(3, op_end, op))
-			goto output_overrun;
-		*op++ = *m_pos++;
-		*op++ = *m_pos++;
-		*op++ = *m_pos;
-
-		goto match_done;
-
-		do {
-match:
-			if (t >= 64) {
-				m_pos = op - 1;
-				m_pos -= (t >> 2) & 7;
-				m_pos -= *ip++ << 3;
-				t = (t >> 5) - 1;
-				if (HAVE_LB(m_pos, out, op))
-					goto lookbehind_overrun;
-				if (HAVE_OP(t + 3 - 1, op_end, op))
-					goto output_overrun;
-				goto copy_match;
-			} else if (t >= 32) {
-				t &= 31;
-				if (t == 0) {
-					if (HAVE_IP(1, ip_end, ip))
-						goto input_overrun;
-					while (*ip == 0) {
-						t += 255;
-						ip++;
-						if (HAVE_IP(1, ip_end, ip))
-							goto input_overrun;
-					}
-					t += 31 + *ip++;
-				}
-				m_pos = op - 1;
-				m_pos -= get_unaligned_le16(ip) >> 2;
-				ip += 2;
-			} else if (t >= 16) {
-				m_pos = op;
-				m_pos -= (t & 8) << 11;
-
-				t &= 7;
-				if (t == 0) {
-					if (HAVE_IP(1, ip_end, ip))
-						goto input_overrun;
-					while (*ip == 0) {
-						t += 255;
-						ip++;
-						if (HAVE_IP(1, ip_end, ip))
-							goto input_overrun;
-					}
-					t += 7 + *ip++;
-				}
-				m_pos -= get_unaligned_le16(ip) >> 2;
-				ip += 2;
-				if (m_pos == op)
-					goto eof_found;
-				m_pos -= 0x4000;
-			} else {
-				m_pos = op - 1;
-				m_pos -= t >> 2;
-				m_pos -= *ip++ << 2;
-
-				if (HAVE_LB(m_pos, out, op))
-					goto lookbehind_overrun;
-				if (HAVE_OP(2, op_end, op))
-					goto output_overrun;
-
-				*op++ = *m_pos++;
-				*op++ = *m_pos;
-				goto match_done;
-			}
-
-			if (HAVE_LB(m_pos, out, op))
-				goto lookbehind_overrun;
-			if (HAVE_OP(t + 3 - 1, op_end, op))
-				goto output_overrun;
-
-			if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
-				COPY4(op, m_pos);
-				op += 4;
-				m_pos += 4;
-				t -= 4 - (3 - 1);
-				do {
-					COPY4(op, m_pos);
-					op += 4;
-					m_pos += 4;
-					t -= 4;
-				} while (t >= 4);
-				if (t > 0)
-					do {
-						*op++ = *m_pos++;
-					} while (--t > 0);
-			} else {
-copy_match:
-				*op++ = *m_pos++;
-				*op++ = *m_pos++;
-				do {
-					*op++ = *m_pos++;
-				} while (--t > 0);
-			}
-match_done:
-			t = ip[-2] & 3;
-			if (t == 0)
-				break;
-match_next:
-			if (HAVE_OP(t, op_end, op))
-				goto output_overrun;
-			if (HAVE_IP(t + 1, ip_end, ip))
-				goto input_overrun;
-
-			*op++ = *ip++;
-			if (t > 1) {
-				*op++ = *ip++;
-				if (t > 2)
-					*op++ = *ip++;
-			}
-
-			t = *ip++;
-		} while (ip < ip_end);
-	}
-
-	*out_len = op - out;
-	return LZO_E_EOF_NOT_FOUND;
-
-eof_found:
-	*out_len = op - out;
-	return (ip == ip_end ? LZO_E_OK :
-		(ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
-input_overrun:
-	*out_len = op - out;
-	return LZO_E_INPUT_OVERRUN;
-
-output_overrun:
-	*out_len = op - out;
-	return LZO_E_OUTPUT_OVERRUN;
-
-lookbehind_overrun:
-	*out_len = op - out;
-	return LZO_E_LOOKBEHIND_OVERRUN;
-}
-#ifndef STATIC
-EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("LZO1X Decompressor");
-
-#endif
diff --git a/lib/lzo/lzo1x_decompress_safe.c b/lib/lzo/lzo1x_decompress_safe.c
new file mode 100644
index 0000000..569985d
--- /dev/null
+++ b/lib/lzo/lzo1x_decompress_safe.c
@@ -0,0 +1,237 @@
+/*
+ *  LZO1X Decompressor from LZO
+ *
+ *  Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ *  The full LZO package can be found at:
+ *  http://www.oberhumer.com/opensource/lzo/
+ *
+ *  Changed for Linux kernel use by:
+ *  Nitin Gupta <nitingupta910@gmail.com>
+ *  Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#ifndef STATIC
+#include <linux/module.h>
+#include <linux/kernel.h>
+#endif
+#include <asm/unaligned.h>
+#include <linux/lzo.h>
+#include "lzodefs.h"
+
+#define HAVE_IP(x)      ((size_t)(ip_end - ip) >= (size_t)(x))
+#define HAVE_OP(x)      ((size_t)(op_end - op) >= (size_t)(x))
+#define NEED_IP(x)      if (!HAVE_IP(x)) goto input_overrun
+#define NEED_OP(x)      if (!HAVE_OP(x)) goto output_overrun
+#define TEST_LB(m_pos)  if ((m_pos) < out) goto lookbehind_overrun
+
+int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
+			  unsigned char *out, size_t *out_len)
+{
+	unsigned char *op;
+	const unsigned char *ip;
+	size_t t, next;
+	size_t state = 0;
+	const unsigned char *m_pos;
+	const unsigned char * const ip_end = in + in_len;
+	unsigned char * const op_end = out + *out_len;
+
+	op = out;
+	ip = in;
+
+	if (unlikely(in_len < 3))
+		goto input_overrun;
+	if (*ip > 17) {
+		t = *ip++ - 17;
+		if (t < 4) {
+			next = t;
+			goto match_next;
+		}
+		goto copy_literal_run;
+	}
+
+	for (;;) {
+		t = *ip++;
+		if (t < 16) {
+			if (likely(state == 0)) {
+				if (unlikely(t == 0)) {
+					while (unlikely(*ip == 0)) {
+						t += 255;
+						ip++;
+						NEED_IP(1);
+					}
+					t += 15 + *ip++;
+				}
+				t += 3;
+copy_literal_run:
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+				if (likely(HAVE_IP(t + 15) && HAVE_OP(t + 15))) {
+					const unsigned char *ie = ip + t;
+					unsigned char *oe = op + t;
+					do {
+						COPY8(op, ip);
+						op += 8;
+						ip += 8;
+						COPY8(op, ip);
+						op += 8;
+						ip += 8;
+					} while (ip < ie);
+					ip = ie;
+					op = oe;
+				} else
+#endif
+				{
+					NEED_OP(t);
+					NEED_IP(t + 3);
+					do {
+						*op++ = *ip++;
+					} while (--t > 0);
+				}
+				state = 4;
+				continue;
+			} else if (state != 4) {
+				next = t & 3;
+				m_pos = op - 1;
+				m_pos -= t >> 2;
+				m_pos -= *ip++ << 2;
+				TEST_LB(m_pos);
+				NEED_OP(2);
+				op[0] = m_pos[0];
+				op[1] = m_pos[1];
+				op += 2;
+				goto match_next;
+			} else {
+				next = t & 3;
+				m_pos = op - (1 + M2_MAX_OFFSET);
+				m_pos -= t >> 2;
+				m_pos -= *ip++ << 2;
+				t = 3;
+			}
+		} else if (t >= 64) {
+			next = t & 3;
+			m_pos = op - 1;
+			m_pos -= (t >> 2) & 7;
+			m_pos -= *ip++ << 3;
+			t = (t >> 5) - 1 + (3 - 1);
+		} else if (t >= 32) {
+			t = (t & 31) + (3 - 1);
+			if (unlikely(t == 2)) {
+				while (unlikely(*ip == 0)) {
+					t += 255;
+					ip++;
+					NEED_IP(1);
+				}
+				t += 31 + *ip++;
+				NEED_IP(2);
+			}
+			m_pos = op - 1;
+			next = get_unaligned_le16(ip);
+			ip += 2;
+			m_pos -= next >> 2;
+			next &= 3;
+		} else {
+			m_pos = op;
+			m_pos -= (t & 8) << 11;
+			t = (t & 7) + (3 - 1);
+			if (unlikely(t == 2)) {
+				while (unlikely(*ip == 0)) {
+					t += 255;
+					ip++;
+					NEED_IP(1);
+				}
+				t += 7 + *ip++;
+				NEED_IP(2);
+			}
+			next = get_unaligned_le16(ip);
+			ip += 2;
+			m_pos -= next >> 2;
+			next &= 3;
+			if (m_pos == op)
+				goto eof_found;
+			m_pos -= 0x4000;
+		}
+		TEST_LB(m_pos);
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+		if (op - m_pos >= 8) {
+			unsigned char *oe = op + t;
+			if (likely(HAVE_OP(t + 15))) {
+				do {
+					COPY8(op, m_pos);
+					op += 8;
+					m_pos += 8;
+					COPY8(op, m_pos);
+					op += 8;
+					m_pos += 8;
+				} while (op < oe);
+				op = oe;
+				if (HAVE_IP(6)) {
+					state = next;
+					COPY4(op, ip);
+					op += next;
+					ip += next;
+					continue;
+				}
+			} else {
+				NEED_OP(t);
+				do {
+					*op++ = *m_pos++;
+				} while (op < oe);
+			}
+		} else
+#endif
+		{
+			unsigned char *oe = op + t;
+			NEED_OP(t);
+			op[0] = m_pos[0];
+			op[1] = m_pos[1];
+			op += 2;
+			m_pos += 2;
+			do {
+				*op++ = *m_pos++;
+			} while (op < oe);
+		}
+match_next:
+		state = next;
+		t = next;
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+		if (likely(HAVE_IP(6) && HAVE_OP(4))) {
+			COPY4(op, ip);
+			op += t;
+			ip += t;
+		} else
+#endif
+		{
+			NEED_IP(t + 3);
+			NEED_OP(t);
+			while (t > 0) {
+				*op++ = *ip++;
+				t--;
+			}
+		}
+	}
+
+eof_found:
+	*out_len = op - out;
+	return (t != 3       ? LZO_E_ERROR :
+		ip == ip_end ? LZO_E_OK :
+		ip <  ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN);
+
+input_overrun:
+	*out_len = op - out;
+	return LZO_E_INPUT_OVERRUN;
+
+output_overrun:
+	*out_len = op - out;
+	return LZO_E_OUTPUT_OVERRUN;
+
+lookbehind_overrun:
+	*out_len = op - out;
+	return LZO_E_LOOKBEHIND_OVERRUN;
+}
+#ifndef STATIC
+EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZO1X Decompressor");
+
+#endif
diff --git a/lib/lzo/lzodefs.h b/lib/lzo/lzodefs.h
index b6d482c..5a4beb2 100644
--- a/lib/lzo/lzodefs.h
+++ b/lib/lzo/lzodefs.h
@@ -1,19 +1,37 @@
 /*
  *  lzodefs.h -- architecture, OS and compiler specific defines
  *
- *  Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *  Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
  *
  *  The full LZO package can be found at:
  *  http://www.oberhumer.com/opensource/lzo/
  *
- *  Changed for kernel use by:
+ *  Changed for Linux kernel use by:
  *  Nitin Gupta <nitingupta910@gmail.com>
  *  Richard Purdie <rpurdie@openedhand.com>
  */
 
-#define LZO_VERSION		0x2020
-#define LZO_VERSION_STRING	"2.02"
-#define LZO_VERSION_DATE	"Oct 17 2005"
+
+#define COPY4(dst, src)	\
+		put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
+#if defined(__x86_64__)
+#define COPY8(dst, src)	\
+		put_unaligned(get_unaligned((const u64 *)(src)), (u64 *)(dst))
+#else
+#define COPY8(dst, src)	\
+		COPY4(dst, src); COPY4((dst) + 4, (src) + 4)
+#endif
+
+#if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN)
+#error "conflicting endian definitions"
+#elif defined(__x86_64__)
+#define LZO_USE_CTZ64	1
+#define LZO_USE_CTZ32	1
+#elif defined(__i386__) || defined(__powerpc__)
+#define LZO_USE_CTZ32	1
+#elif defined(__arm__) && (__LINUX_ARM_ARCH__ >= 5)
+#define LZO_USE_CTZ32	1
+#endif
 
 #define M1_MAX_OFFSET	0x0400
 #define M2_MAX_OFFSET	0x0800
@@ -34,8 +52,10 @@
 #define M3_MARKER	32
 #define M4_MARKER	16
 
-#define D_BITS		14
-#define D_MASK		((1u << D_BITS) - 1)
+#define lzo_dict_t      unsigned short
+#define D_BITS		13
+#define D_SIZE		(1u << D_BITS)
+#define D_MASK		(D_SIZE - 1)
 #define D_HIGH		((D_MASK >> 1) + 1)
 
 #define DX2(p, s1, s2)	(((((size_t)((p)[2]) << (s2)) ^ (p)[1]) \
diff --git a/lib/percpu-rwsem.c b/lib/percpu-rwsem.c
new file mode 100644
index 0000000..ba2708f
--- /dev/null
+++ b/lib/percpu-rwsem.c
@@ -0,0 +1,165 @@
+#include <linux/atomic.h>
+#include <linux/rwsem.h>
+#include <linux/percpu.h>
+#include <linux/wait.h>
+#include <linux/lockdep.h>
+#include <linux/percpu-rwsem.h>
+#include <linux/rcupdate.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+
+int __percpu_init_rwsem(struct percpu_rw_semaphore *brw,
+			const char *name, struct lock_class_key *rwsem_key)
+{
+	brw->fast_read_ctr = alloc_percpu(int);
+	if (unlikely(!brw->fast_read_ctr))
+		return -ENOMEM;
+
+	/* ->rw_sem represents the whole percpu_rw_semaphore for lockdep */
+	__init_rwsem(&brw->rw_sem, name, rwsem_key);
+	atomic_set(&brw->write_ctr, 0);
+	atomic_set(&brw->slow_read_ctr, 0);
+	init_waitqueue_head(&brw->write_waitq);
+	return 0;
+}
+
+void percpu_free_rwsem(struct percpu_rw_semaphore *brw)
+{
+	free_percpu(brw->fast_read_ctr);
+	brw->fast_read_ctr = NULL; /* catch use after free bugs */
+}
+
+/*
+ * This is the fast-path for down_read/up_read, it only needs to ensure
+ * there is no pending writer (atomic_read(write_ctr) == 0) and inc/dec the
+ * fast per-cpu counter. The writer uses synchronize_sched() to serialize
+ * with the preempt-disabled section below.
+ *
+ * The nontrivial part is that we should guarantee acquire/release semantics
+ * in case when
+ *
+ *	R_W: down_write() comes after up_read(), the writer should see all
+ *	     changes done by the reader
+ * or
+ *	W_R: down_read() comes after up_write(), the reader should see all
+ *	     changes done by the writer
+ *
+ * If this helper fails the callers rely on the normal rw_semaphore and
+ * atomic_dec_and_test(), so in this case we have the necessary barriers.
+ *
+ * But if it succeeds we do not have any barriers, atomic_read(write_ctr) or
+ * __this_cpu_add() below can be reordered with any LOAD/STORE done by the
+ * reader inside the critical section. See the comments in down_write and
+ * up_write below.
+ */
+static bool update_fast_ctr(struct percpu_rw_semaphore *brw, unsigned int val)
+{
+	bool success = false;
+
+	preempt_disable();
+	if (likely(!atomic_read(&brw->write_ctr))) {
+		__this_cpu_add(*brw->fast_read_ctr, val);
+		success = true;
+	}
+	preempt_enable();
+
+	return success;
+}
+
+/*
+ * Like the normal down_read() this is not recursive, the writer can
+ * come after the first percpu_down_read() and create the deadlock.
+ *
+ * Note: returns with lock_is_held(brw->rw_sem) == T for lockdep,
+ * percpu_up_read() does rwsem_release(). This pairs with the usage
+ * of ->rw_sem in percpu_down/up_write().
+ */
+void percpu_down_read(struct percpu_rw_semaphore *brw)
+{
+	might_sleep();
+	if (likely(update_fast_ctr(brw, +1))) {
+		rwsem_acquire_read(&brw->rw_sem.dep_map, 0, 0, _RET_IP_);
+		return;
+	}
+
+	down_read(&brw->rw_sem);
+	atomic_inc(&brw->slow_read_ctr);
+	/* avoid up_read()->rwsem_release() */
+	__up_read(&brw->rw_sem);
+}
+
+void percpu_up_read(struct percpu_rw_semaphore *brw)
+{
+	rwsem_release(&brw->rw_sem.dep_map, 1, _RET_IP_);
+
+	if (likely(update_fast_ctr(brw, -1)))
+		return;
+
+	/* false-positive is possible but harmless */
+	if (atomic_dec_and_test(&brw->slow_read_ctr))
+		wake_up_all(&brw->write_waitq);
+}
+
+static int clear_fast_ctr(struct percpu_rw_semaphore *brw)
+{
+	unsigned int sum = 0;
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		sum += per_cpu(*brw->fast_read_ctr, cpu);
+		per_cpu(*brw->fast_read_ctr, cpu) = 0;
+	}
+
+	return sum;
+}
+
+/*
+ * A writer increments ->write_ctr to force the readers to switch to the
+ * slow mode, note the atomic_read() check in update_fast_ctr().
+ *
+ * After that the readers can only inc/dec the slow ->slow_read_ctr counter,
+ * ->fast_read_ctr is stable. Once the writer moves its sum into the slow
+ * counter it represents the number of active readers.
+ *
+ * Finally the writer takes ->rw_sem for writing and blocks the new readers,
+ * then waits until the slow counter becomes zero.
+ */
+void percpu_down_write(struct percpu_rw_semaphore *brw)
+{
+	/* tell update_fast_ctr() there is a pending writer */
+	atomic_inc(&brw->write_ctr);
+	/*
+	 * 1. Ensures that write_ctr != 0 is visible to any down_read/up_read
+	 *    so that update_fast_ctr() can't succeed.
+	 *
+	 * 2. Ensures we see the result of every previous this_cpu_add() in
+	 *    update_fast_ctr().
+	 *
+	 * 3. Ensures that if any reader has exited its critical section via
+	 *    fast-path, it executes a full memory barrier before we return.
+	 *    See R_W case in the comment above update_fast_ctr().
+	 */
+	synchronize_sched();
+
+	/* exclude other writers, and block the new readers completely */
+	down_write(&brw->rw_sem);
+
+	/* nobody can use fast_read_ctr, move its sum into slow_read_ctr */
+	atomic_add(clear_fast_ctr(brw), &brw->slow_read_ctr);
+
+	/* wait for all readers to complete their percpu_up_read() */
+	wait_event(brw->write_waitq, !atomic_read(&brw->slow_read_ctr));
+}
+
+void percpu_up_write(struct percpu_rw_semaphore *brw)
+{
+	/* release the lock, but the readers can't use the fast-path */
+	up_write(&brw->rw_sem);
+	/*
+	 * Insert the barrier before the next fast-path in down_read,
+	 * see W_R case in the comment above update_fast_ctr().
+	 */
+	synchronize_sched();
+	/* the last writer unblocks update_fast_ctr() */
+	atomic_dec(&brw->write_ctr);
+}
diff --git a/lib/raid6/Makefile b/lib/raid6/Makefile
index de06dfe..8c2e22b 100644
--- a/lib/raid6/Makefile
+++ b/lib/raid6/Makefile
@@ -1,6 +1,6 @@
 obj-$(CONFIG_RAID6_PQ)	+= raid6_pq.o
 
-raid6_pq-y	+= algos.o recov.o recov_ssse3.o tables.o int1.o int2.o int4.o \
+raid6_pq-y	+= algos.o recov.o recov_ssse3.o recov_avx2.o tables.o int1.o int2.o int4.o \
 		   int8.o int16.o int32.o altivec1.o altivec2.o altivec4.o \
 		   altivec8.o mmx.o sse1.o sse2.o
 hostprogs-y	+= mktables
diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
index 589f5f5..8b7f55c 100644
--- a/lib/raid6/algos.c
+++ b/lib/raid6/algos.c
@@ -72,6 +72,9 @@ EXPORT_SYMBOL_GPL(raid6_datap_recov);
 
 const struct raid6_recov_calls *const raid6_recov_algos[] = {
 #if (defined(__i386__) || defined(__x86_64__)) && !defined(__arch_um__)
+#ifdef CONFIG_AS_AVX2
+	&raid6_recov_avx2,
+#endif
 	&raid6_recov_ssse3,
 #endif
 	&raid6_recov_intx1,
diff --git a/lib/raid6/recov_avx2.c b/lib/raid6/recov_avx2.c
new file mode 100644
index 0000000..43a9bab
--- /dev/null
+++ b/lib/raid6/recov_avx2.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2012 Intel Corporation
+ * Author: Jim Kukunas <james.t.kukunas@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#if (defined(__i386__) || defined(__x86_64__)) && !defined(__arch_um__)
+
+#if CONFIG_AS_AVX2
+
+#include <linux/raid/pq.h>
+#include "x86.h"
+
+static int raid6_has_avx2(void)
+{
+	return boot_cpu_has(X86_FEATURE_AVX2) &&
+		boot_cpu_has(X86_FEATURE_AVX);
+}
+
+static void raid6_2data_recov_avx2(int disks, size_t bytes, int faila,
+		int failb, void **ptrs)
+{
+	u8 *p, *q, *dp, *dq;
+	const u8 *pbmul;	/* P multiplier table for B data */
+	const u8 *qmul;		/* Q multiplier table (for both) */
+	const u8 x0f = 0x0f;
+
+	p = (u8 *)ptrs[disks-2];
+	q = (u8 *)ptrs[disks-1];
+
+	/* Compute syndrome with zero for the missing data pages
+	   Use the dead data pages as temporary storage for
+	   delta p and delta q */
+	dp = (u8 *)ptrs[faila];
+	ptrs[faila] = (void *)raid6_empty_zero_page;
+	ptrs[disks-2] = dp;
+	dq = (u8 *)ptrs[failb];
+	ptrs[failb] = (void *)raid6_empty_zero_page;
+	ptrs[disks-1] = dq;
+
+	raid6_call.gen_syndrome(disks, bytes, ptrs);
+
+	/* Restore pointer table */
+	ptrs[faila]   = dp;
+	ptrs[failb]   = dq;
+	ptrs[disks-2] = p;
+	ptrs[disks-1] = q;
+
+	/* Now, pick the proper data tables */
+	pbmul = raid6_vgfmul[raid6_gfexi[failb-faila]];
+	qmul  = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila] ^
+		raid6_gfexp[failb]]];
+
+	kernel_fpu_begin();
+
+	/* ymm0 = x0f[16] */
+	asm volatile("vpbroadcastb %0, %%ymm7" : : "m" (x0f));
+
+	while (bytes) {
+#ifdef CONFIG_X86_64
+		asm volatile("vmovdqa %0, %%ymm1" : : "m" (q[0]));
+		asm volatile("vmovdqa %0, %%ymm9" : : "m" (q[32]));
+		asm volatile("vmovdqa %0, %%ymm0" : : "m" (p[0]));
+		asm volatile("vmovdqa %0, %%ymm8" : : "m" (p[32]));
+		asm volatile("vpxor %0, %%ymm1, %%ymm1" : : "m" (dq[0]));
+		asm volatile("vpxor %0, %%ymm9, %%ymm9" : : "m" (dq[32]));
+		asm volatile("vpxor %0, %%ymm0, %%ymm0" : : "m" (dp[0]));
+		asm volatile("vpxor %0, %%ymm8, %%ymm8" : : "m" (dp[32]));
+
+		/*
+		 * 1 = dq[0]  ^ q[0]
+		 * 9 = dq[32] ^ q[32]
+		 * 0 = dp[0]  ^ p[0]
+		 * 8 = dp[32] ^ p[32]
+		 */
+
+		asm volatile("vbroadcasti128 %0, %%ymm4" : : "m" (qmul[0]));
+		asm volatile("vbroadcasti128 %0, %%ymm5" : : "m" (qmul[16]));
+
+		asm volatile("vpsraw $4, %ymm1, %ymm3");
+		asm volatile("vpsraw $4, %ymm9, %ymm12");
+		asm volatile("vpand %ymm7, %ymm1, %ymm1");
+		asm volatile("vpand %ymm7, %ymm9, %ymm9");
+		asm volatile("vpand %ymm7, %ymm3, %ymm3");
+		asm volatile("vpand %ymm7, %ymm12, %ymm12");
+		asm volatile("vpshufb %ymm9, %ymm4, %ymm14");
+		asm volatile("vpshufb %ymm1, %ymm4, %ymm4");
+		asm volatile("vpshufb %ymm12, %ymm5, %ymm15");
+		asm volatile("vpshufb %ymm3, %ymm5, %ymm5");
+		asm volatile("vpxor %ymm14, %ymm15, %ymm15");
+		asm volatile("vpxor %ymm4, %ymm5, %ymm5");
+
+		/*
+		 * 5 = qx[0]
+		 * 15 = qx[32]
+		 */
+
+		asm volatile("vbroadcasti128 %0, %%ymm4" : : "m" (pbmul[0]));
+		asm volatile("vbroadcasti128 %0, %%ymm1" : : "m" (pbmul[16]));
+		asm volatile("vpsraw $4, %ymm0, %ymm2");
+		asm volatile("vpsraw $4, %ymm8, %ymm6");
+		asm volatile("vpand %ymm7, %ymm0, %ymm3");
+		asm volatile("vpand %ymm7, %ymm8, %ymm14");
+		asm volatile("vpand %ymm7, %ymm2, %ymm2");
+		asm volatile("vpand %ymm7, %ymm6, %ymm6");
+		asm volatile("vpshufb %ymm14, %ymm4, %ymm12");
+		asm volatile("vpshufb %ymm3, %ymm4, %ymm4");
+		asm volatile("vpshufb %ymm6, %ymm1, %ymm13");
+		asm volatile("vpshufb %ymm2, %ymm1, %ymm1");
+		asm volatile("vpxor %ymm4, %ymm1, %ymm1");
+		asm volatile("vpxor %ymm12, %ymm13, %ymm13");
+
+		/*
+		 * 1  = pbmul[px[0]]
+		 * 13 = pbmul[px[32]]
+		 */
+		asm volatile("vpxor %ymm5, %ymm1, %ymm1");
+		asm volatile("vpxor %ymm15, %ymm13, %ymm13");
+
+		/*
+		 * 1 = db = DQ
+		 * 13 = db[32] = DQ[32]
+		 */
+		asm volatile("vmovdqa %%ymm1, %0" : "=m" (dq[0]));
+		asm volatile("vmovdqa %%ymm13,%0" : "=m" (dq[32]));
+		asm volatile("vpxor %ymm1, %ymm0, %ymm0");
+		asm volatile("vpxor %ymm13, %ymm8, %ymm8");
+
+		asm volatile("vmovdqa %%ymm0, %0" : "=m" (dp[0]));
+		asm volatile("vmovdqa %%ymm8, %0" : "=m" (dp[32]));
+
+		bytes -= 64;
+		p += 64;
+		q += 64;
+		dp += 64;
+		dq += 64;
+#else
+		asm volatile("vmovdqa %0, %%ymm1" : : "m" (*q));
+		asm volatile("vmovdqa %0, %%ymm0" : : "m" (*p));
+		asm volatile("vpxor %0, %%ymm1, %%ymm1" : : "m" (*dq));
+		asm volatile("vpxor %0, %%ymm0, %%ymm0" : : "m" (*dp));
+
+		/* 1 = dq ^ q;  0 = dp ^ p */
+
+		asm volatile("vbroadcasti128 %0, %%ymm4" : : "m" (qmul[0]));
+		asm volatile("vbroadcasti128 %0, %%ymm5" : : "m" (qmul[16]));
+
+		/*
+		 * 1 = dq ^ q
+		 * 3 = dq ^ p >> 4
+		 */
+		asm volatile("vpsraw $4, %ymm1, %ymm3");
+		asm volatile("vpand %ymm7, %ymm1, %ymm1");
+		asm volatile("vpand %ymm7, %ymm3, %ymm3");
+		asm volatile("vpshufb %ymm1, %ymm4, %ymm4");
+		asm volatile("vpshufb %ymm3, %ymm5, %ymm5");
+		asm volatile("vpxor %ymm4, %ymm5, %ymm5");
+
+		/* 5 = qx */
+
+		asm volatile("vbroadcasti128 %0, %%ymm4" : : "m" (pbmul[0]));
+		asm volatile("vbroadcasti128 %0, %%ymm1" : : "m" (pbmul[16]));
+
+		asm volatile("vpsraw $4, %ymm0, %ymm2");
+		asm volatile("vpand %ymm7, %ymm0, %ymm3");
+		asm volatile("vpand %ymm7, %ymm2, %ymm2");
+		asm volatile("vpshufb %ymm3, %ymm4, %ymm4");
+		asm volatile("vpshufb %ymm2, %ymm1, %ymm1");
+		asm volatile("vpxor %ymm4, %ymm1, %ymm1");
+
+		/* 1 = pbmul[px] */
+		asm volatile("vpxor %ymm5, %ymm1, %ymm1");
+		/* 1 = db = DQ */
+		asm volatile("vmovdqa %%ymm1, %0" : "=m" (dq[0]));
+
+		asm volatile("vpxor %ymm1, %ymm0, %ymm0");
+		asm volatile("vmovdqa %%ymm0, %0" : "=m" (dp[0]));
+
+		bytes -= 32;
+		p += 32;
+		q += 32;
+		dp += 32;
+		dq += 32;
+#endif
+	}
+
+	kernel_fpu_end();
+}
+
+static void raid6_datap_recov_avx2(int disks, size_t bytes, int faila,
+		void **ptrs)
+{
+	u8 *p, *q, *dq;
+	const u8 *qmul;		/* Q multiplier table */
+	const u8 x0f = 0x0f;
+
+	p = (u8 *)ptrs[disks-2];
+	q = (u8 *)ptrs[disks-1];
+
+	/* Compute syndrome with zero for the missing data page
+	   Use the dead data page as temporary storage for delta q */
+	dq = (u8 *)ptrs[faila];
+	ptrs[faila] = (void *)raid6_empty_zero_page;
+	ptrs[disks-1] = dq;
+
+	raid6_call.gen_syndrome(disks, bytes, ptrs);
+
+	/* Restore pointer table */
+	ptrs[faila]   = dq;
+	ptrs[disks-1] = q;
+
+	/* Now, pick the proper data tables */
+	qmul  = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila]]];
+
+	kernel_fpu_begin();
+
+	asm volatile("vpbroadcastb %0, %%ymm7" : : "m" (x0f));
+
+	while (bytes) {
+#ifdef CONFIG_X86_64
+		asm volatile("vmovdqa %0, %%ymm3" : : "m" (dq[0]));
+		asm volatile("vmovdqa %0, %%ymm8" : : "m" (dq[32]));
+		asm volatile("vpxor %0, %%ymm3, %%ymm3" : : "m" (q[0]));
+		asm volatile("vpxor %0, %%ymm8, %%ymm8" : : "m" (q[32]));
+
+		/*
+		 * 3 = q[0] ^ dq[0]
+		 * 8 = q[32] ^ dq[32]
+		 */
+		asm volatile("vbroadcasti128 %0, %%ymm0" : : "m" (qmul[0]));
+		asm volatile("vmovapd %ymm0, %ymm13");
+		asm volatile("vbroadcasti128 %0, %%ymm1" : : "m" (qmul[16]));
+		asm volatile("vmovapd %ymm1, %ymm14");
+
+		asm volatile("vpsraw $4, %ymm3, %ymm6");
+		asm volatile("vpsraw $4, %ymm8, %ymm12");
+		asm volatile("vpand %ymm7, %ymm3, %ymm3");
+		asm volatile("vpand %ymm7, %ymm8, %ymm8");
+		asm volatile("vpand %ymm7, %ymm6, %ymm6");
+		asm volatile("vpand %ymm7, %ymm12, %ymm12");
+		asm volatile("vpshufb %ymm3, %ymm0, %ymm0");
+		asm volatile("vpshufb %ymm8, %ymm13, %ymm13");
+		asm volatile("vpshufb %ymm6, %ymm1, %ymm1");
+		asm volatile("vpshufb %ymm12, %ymm14, %ymm14");
+		asm volatile("vpxor %ymm0, %ymm1, %ymm1");
+		asm volatile("vpxor %ymm13, %ymm14, %ymm14");
+
+		/*
+		 * 1  = qmul[q[0]  ^ dq[0]]
+		 * 14 = qmul[q[32] ^ dq[32]]
+		 */
+		asm volatile("vmovdqa %0, %%ymm2" : : "m" (p[0]));
+		asm volatile("vmovdqa %0, %%ymm12" : : "m" (p[32]));
+		asm volatile("vpxor %ymm1, %ymm2, %ymm2");
+		asm volatile("vpxor %ymm14, %ymm12, %ymm12");
+
+		/*
+		 * 2  = p[0]  ^ qmul[q[0]  ^ dq[0]]
+		 * 12 = p[32] ^ qmul[q[32] ^ dq[32]]
+		 */
+
+		asm volatile("vmovdqa %%ymm1, %0" : "=m" (dq[0]));
+		asm volatile("vmovdqa %%ymm14, %0" : "=m" (dq[32]));
+		asm volatile("vmovdqa %%ymm2, %0" : "=m" (p[0]));
+		asm volatile("vmovdqa %%ymm12,%0" : "=m" (p[32]));
+
+		bytes -= 64;
+		p += 64;
+		q += 64;
+		dq += 64;
+#else
+		asm volatile("vmovdqa %0, %%ymm3" : : "m" (dq[0]));
+		asm volatile("vpxor %0, %%ymm3, %%ymm3" : : "m" (q[0]));
+
+		/* 3 = q ^ dq */
+
+		asm volatile("vbroadcasti128 %0, %%ymm0" : : "m" (qmul[0]));
+		asm volatile("vbroadcasti128 %0, %%ymm1" : : "m" (qmul[16]));
+
+		asm volatile("vpsraw $4, %ymm3, %ymm6");
+		asm volatile("vpand %ymm7, %ymm3, %ymm3");
+		asm volatile("vpand %ymm7, %ymm6, %ymm6");
+		asm volatile("vpshufb %ymm3, %ymm0, %ymm0");
+		asm volatile("vpshufb %ymm6, %ymm1, %ymm1");
+		asm volatile("vpxor %ymm0, %ymm1, %ymm1");
+
+		/* 1 = qmul[q ^ dq] */
+
+		asm volatile("vmovdqa %0, %%ymm2" : : "m" (p[0]));
+		asm volatile("vpxor %ymm1, %ymm2, %ymm2");
+
+		/* 2 = p ^ qmul[q ^ dq] */
+
+		asm volatile("vmovdqa %%ymm1, %0" : "=m" (dq[0]));
+		asm volatile("vmovdqa %%ymm2, %0" : "=m" (p[0]));
+
+		bytes -= 32;
+		p += 32;
+		q += 32;
+		dq += 32;
+#endif
+	}
+
+	kernel_fpu_end();
+}
+
+const struct raid6_recov_calls raid6_recov_avx2 = {
+	.data2 = raid6_2data_recov_avx2,
+	.datap = raid6_datap_recov_avx2,
+	.valid = raid6_has_avx2,
+#ifdef CONFIG_X86_64
+	.name = "avx2x2",
+#else
+	.name = "avx2x1",
+#endif
+	.priority = 2,
+};
+
+#else
+#warning "your version of binutils lacks AVX2 support"
+#endif
+
+#endif
diff --git a/lib/raid6/test/Makefile b/lib/raid6/test/Makefile
index c76151d..d919c98 100644
--- a/lib/raid6/test/Makefile
+++ b/lib/raid6/test/Makefile
@@ -23,7 +23,7 @@ RANLIB	 = ranlib
 all:	raid6.a raid6test
 
 raid6.a: int1.o int2.o int4.o int8.o int16.o int32.o mmx.o sse1.o sse2.o \
-	 altivec1.o altivec2.o altivec4.o altivec8.o recov.o recov_ssse3.o algos.o \
+	 altivec1.o altivec2.o altivec4.o altivec8.o recov.o recov_ssse3.o recov_avx2.o algos.o \
 	 tables.o
 	 rm -f $@
 	 $(AR) cq $@ $^
diff --git a/lib/raid6/x86.h b/lib/raid6/x86.h
index d55d632..b759548 100644
--- a/lib/raid6/x86.h
+++ b/lib/raid6/x86.h
@@ -45,19 +45,23 @@ static inline void kernel_fpu_end(void)
 #define X86_FEATURE_XMM3	(4*32+ 0) /* "pni" SSE-3 */
 #define X86_FEATURE_SSSE3	(4*32+ 9) /* Supplemental SSE-3 */
 #define X86_FEATURE_AVX	(4*32+28) /* Advanced Vector Extensions */
+#define X86_FEATURE_AVX2        (9*32+ 5) /* AVX2 instructions */
 #define X86_FEATURE_MMXEXT	(1*32+22) /* AMD MMX extensions */
 
 /* Should work well enough on modern CPUs for testing */
 static inline int boot_cpu_has(int flag)
 {
-	u32 eax = (flag & 0x20) ? 0x80000001 : 1;
-	u32 ecx, edx;
+	u32 eax, ebx, ecx, edx;
+
+	eax = (flag & 0x100) ? 7 :
+		(flag & 0x20) ? 0x80000001 : 1;
+	ecx = 0;
 
 	asm volatile("cpuid"
-		     : "+a" (eax), "=d" (edx), "=c" (ecx)
-		     : : "ebx");
+		     : "+a" (eax), "=b" (ebx), "=d" (edx), "+c" (ecx));
 
-	return ((flag & 0x80 ? ecx : edx) >> (flag & 31)) & 1;
+	return ((flag & 0x100 ? ebx :
+		(flag & 0x80) ? ecx : edx) >> (flag & 31)) & 1;
 }
 
 #endif /* ndef __KERNEL__ */
diff --git a/lib/random32.c b/lib/random32.c
index 938bde5..52280d5 100644
--- a/lib/random32.c
+++ b/lib/random32.c
@@ -42,13 +42,13 @@
 static DEFINE_PER_CPU(struct rnd_state, net_rand_state);
 
 /**
- *	prandom32 - seeded pseudo-random number generator.
+ *	prandom_u32_state - seeded pseudo-random number generator.
  *	@state: pointer to state structure holding seeded state.
  *
  *	This is used for pseudo-randomness with no outside seeding.
- *	For more random results, use random32().
+ *	For more random results, use prandom_u32().
  */
-u32 prandom32(struct rnd_state *state)
+u32 prandom_u32_state(struct rnd_state *state)
 {
 #define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b)
 
@@ -58,32 +58,81 @@ u32 prandom32(struct rnd_state *state)
 
 	return (state->s1 ^ state->s2 ^ state->s3);
 }
-EXPORT_SYMBOL(prandom32);
+EXPORT_SYMBOL(prandom_u32_state);
 
 /**
- *	random32 - pseudo random number generator
+ *	prandom_u32 - pseudo random number generator
  *
  *	A 32 bit pseudo-random number is generated using a fast
  *	algorithm suitable for simulation. This algorithm is NOT
  *	considered safe for cryptographic use.
  */
-u32 random32(void)
+u32 prandom_u32(void)
 {
 	unsigned long r;
 	struct rnd_state *state = &get_cpu_var(net_rand_state);
-	r = prandom32(state);
+	r = prandom_u32_state(state);
 	put_cpu_var(state);
 	return r;
 }
-EXPORT_SYMBOL(random32);
+EXPORT_SYMBOL(prandom_u32);
+
+/*
+ *	prandom_bytes_state - get the requested number of pseudo-random bytes
+ *
+ *	@state: pointer to state structure holding seeded state.
+ *	@buf: where to copy the pseudo-random bytes to
+ *	@bytes: the requested number of bytes
+ *
+ *	This is used for pseudo-randomness with no outside seeding.
+ *	For more random results, use prandom_bytes().
+ */
+void prandom_bytes_state(struct rnd_state *state, void *buf, int bytes)
+{
+	unsigned char *p = buf;
+	int i;
+
+	for (i = 0; i < round_down(bytes, sizeof(u32)); i += sizeof(u32)) {
+		u32 random = prandom_u32_state(state);
+		int j;
+
+		for (j = 0; j < sizeof(u32); j++) {
+			p[i + j] = random;
+			random >>= BITS_PER_BYTE;
+		}
+	}
+	if (i < bytes) {
+		u32 random = prandom_u32_state(state);
+
+		for (; i < bytes; i++) {
+			p[i] = random;
+			random >>= BITS_PER_BYTE;
+		}
+	}
+}
+EXPORT_SYMBOL(prandom_bytes_state);
+
+/**
+ *	prandom_bytes - get the requested number of pseudo-random bytes
+ *	@buf: where to copy the pseudo-random bytes to
+ *	@bytes: the requested number of bytes
+ */
+void prandom_bytes(void *buf, int bytes)
+{
+	struct rnd_state *state = &get_cpu_var(net_rand_state);
+
+	prandom_bytes_state(state, buf, bytes);
+	put_cpu_var(state);
+}
+EXPORT_SYMBOL(prandom_bytes);
 
 /**
- *	srandom32 - add entropy to pseudo random number generator
+ *	prandom_seed - add entropy to pseudo random number generator
  *	@seed: seed value
  *
- *	Add some additional seeding to the random32() pool.
+ *	Add some additional seeding to the prandom pool.
  */
-void srandom32(u32 entropy)
+void prandom_seed(u32 entropy)
 {
 	int i;
 	/*
@@ -95,13 +144,13 @@ void srandom32(u32 entropy)
 		state->s1 = __seed(state->s1 ^ entropy, 1);
 	}
 }
-EXPORT_SYMBOL(srandom32);
+EXPORT_SYMBOL(prandom_seed);
 
 /*
  *	Generate some initially weak seeding values to allow
- *	to start the random32() engine.
+ *	to start the prandom_u32() engine.
  */
-static int __init random32_init(void)
+static int __init prandom_init(void)
 {
 	int i;
 
@@ -114,22 +163,22 @@ static int __init random32_init(void)
 		state->s3 = __seed(LCG(state->s2), 15);
 
 		/* "warm it up" */
-		prandom32(state);
-		prandom32(state);
-		prandom32(state);
-		prandom32(state);
-		prandom32(state);
-		prandom32(state);
+		prandom_u32_state(state);
+		prandom_u32_state(state);
+		prandom_u32_state(state);
+		prandom_u32_state(state);
+		prandom_u32_state(state);
+		prandom_u32_state(state);
 	}
 	return 0;
 }
-core_initcall(random32_init);
+core_initcall(prandom_init);
 
 /*
  *	Generate better values after random number generator
  *	is fully initialized.
  */
-static int __init random32_reseed(void)
+static int __init prandom_reseed(void)
 {
 	int i;
 
@@ -143,8 +192,8 @@ static int __init random32_reseed(void)
 		state->s3 = __seed(seeds[2], 15);
 
 		/* mix it in */
-		prandom32(state);
+		prandom_u32_state(state);
 	}
 	return 0;
 }
-late_initcall(random32_reseed);
+late_initcall(prandom_reseed);
diff --git a/lib/rbtree_test.c b/lib/rbtree_test.c
index 268b239..da96578 100644
--- a/lib/rbtree_test.c
+++ b/lib/rbtree_test.c
@@ -96,8 +96,8 @@ static void init(void)
 {
 	int i;
 	for (i = 0; i < NODES; i++) {
-		nodes[i].key = prandom32(&rnd);
-		nodes[i].val = prandom32(&rnd);
+		nodes[i].key = prandom_u32_state(&rnd);
+		nodes[i].val = prandom_u32_state(&rnd);
 	}
 }
 
@@ -155,7 +155,7 @@ static int rbtree_test_init(void)
 
 	printk(KERN_ALERT "rbtree testing");
 
-	prandom32_seed(&rnd, 3141592653589793238ULL);
+	prandom_seed_state(&rnd, 3141592653589793238ULL);
 	init();
 
 	time1 = get_cycles();
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 3675452b..7874b01 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -248,7 +248,8 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents,
 	unsigned int left;
 
 #ifndef ARCH_HAS_SG_CHAIN
-	BUG_ON(nents > max_ents);
+	if (WARN_ON_ONCE(nents > max_ents))
+		return -EINVAL;
 #endif
 
 	memset(table, 0, sizeof(*table));
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index f114bf6..196b069 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -57,7 +57,7 @@ int swiotlb_force;
  * swiotlb_tbl_sync_single_*, to see if the memory was in fact allocated by this
  * API.
  */
-static char *io_tlb_start, *io_tlb_end;
+static phys_addr_t io_tlb_start, io_tlb_end;
 
 /*
  * The number of IO TLB blocks (in groups of 64) between io_tlb_start and
@@ -70,7 +70,7 @@ static unsigned long io_tlb_nslabs;
  */
 static unsigned long io_tlb_overflow = 32*1024;
 
-static void *io_tlb_overflow_buffer;
+static phys_addr_t io_tlb_overflow_buffer;
 
 /*
  * This is a free list describing the number of free entries available from
@@ -125,27 +125,38 @@ static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
 void swiotlb_print_info(void)
 {
 	unsigned long bytes = io_tlb_nslabs << IO_TLB_SHIFT;
-	phys_addr_t pstart, pend;
+	unsigned char *vstart, *vend;
 
-	pstart = virt_to_phys(io_tlb_start);
-	pend = virt_to_phys(io_tlb_end);
+	vstart = phys_to_virt(io_tlb_start);
+	vend = phys_to_virt(io_tlb_end);
 
 	printk(KERN_INFO "software IO TLB [mem %#010llx-%#010llx] (%luMB) mapped at [%p-%p]\n",
-	       (unsigned long long)pstart, (unsigned long long)pend - 1,
-	       bytes >> 20, io_tlb_start, io_tlb_end - 1);
+	       (unsigned long long)io_tlb_start,
+	       (unsigned long long)io_tlb_end,
+	       bytes >> 20, vstart, vend - 1);
 }
 
 void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
 {
+	void *v_overflow_buffer;
 	unsigned long i, bytes;
 
 	bytes = nslabs << IO_TLB_SHIFT;
 
 	io_tlb_nslabs = nslabs;
-	io_tlb_start = tlb;
+	io_tlb_start = __pa(tlb);
 	io_tlb_end = io_tlb_start + bytes;
 
 	/*
+	 * Get the overflow emergency buffer
+	 */
+	v_overflow_buffer = alloc_bootmem_low_pages(PAGE_ALIGN(io_tlb_overflow));
+	if (!v_overflow_buffer)
+		panic("Cannot allocate SWIOTLB overflow buffer!\n");
+
+	io_tlb_overflow_buffer = __pa(v_overflow_buffer);
+
+	/*
 	 * Allocate and initialize the free list array.  This array is used
 	 * to find contiguous free memory regions of size up to IO_TLB_SEGSIZE
 	 * between io_tlb_start and io_tlb_end.
@@ -156,12 +167,6 @@ void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
 	io_tlb_index = 0;
 	io_tlb_orig_addr = alloc_bootmem_pages(PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t)));
 
-	/*
-	 * Get the overflow emergency buffer
-	 */
-	io_tlb_overflow_buffer = alloc_bootmem_low_pages(PAGE_ALIGN(io_tlb_overflow));
-	if (!io_tlb_overflow_buffer)
-		panic("Cannot allocate SWIOTLB overflow buffer!\n");
 	if (verbose)
 		swiotlb_print_info();
 }
@@ -173,6 +178,7 @@ void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
 static void __init
 swiotlb_init_with_default_size(size_t default_size, int verbose)
 {
+	unsigned char *vstart;
 	unsigned long bytes;
 
 	if (!io_tlb_nslabs) {
@@ -185,11 +191,11 @@ swiotlb_init_with_default_size(size_t default_size, int verbose)
 	/*
 	 * Get IO TLB memory from the low pages
 	 */
-	io_tlb_start = alloc_bootmem_low_pages(PAGE_ALIGN(bytes));
-	if (!io_tlb_start)
+	vstart = alloc_bootmem_low_pages(PAGE_ALIGN(bytes));
+	if (!vstart)
 		panic("Cannot allocate SWIOTLB buffer");
 
-	swiotlb_init_with_tbl(io_tlb_start, io_tlb_nslabs, verbose);
+	swiotlb_init_with_tbl(vstart, io_tlb_nslabs, verbose);
 }
 
 void __init
@@ -207,6 +213,7 @@ int
 swiotlb_late_init_with_default_size(size_t default_size)
 {
 	unsigned long bytes, req_nslabs = io_tlb_nslabs;
+	unsigned char *vstart = NULL;
 	unsigned int order;
 	int rc = 0;
 
@@ -223,14 +230,14 @@ swiotlb_late_init_with_default_size(size_t default_size)
 	bytes = io_tlb_nslabs << IO_TLB_SHIFT;
 
 	while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) {
-		io_tlb_start = (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN,
-							order);
-		if (io_tlb_start)
+		vstart = (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN,
+						  order);
+		if (vstart)
 			break;
 		order--;
 	}
 
-	if (!io_tlb_start) {
+	if (!vstart) {
 		io_tlb_nslabs = req_nslabs;
 		return -ENOMEM;
 	}
@@ -239,9 +246,9 @@ swiotlb_late_init_with_default_size(size_t default_size)
 		       "for software IO TLB\n", (PAGE_SIZE << order) >> 20);
 		io_tlb_nslabs = SLABS_PER_PAGE << order;
 	}
-	rc = swiotlb_late_init_with_tbl(io_tlb_start, io_tlb_nslabs);
+	rc = swiotlb_late_init_with_tbl(vstart, io_tlb_nslabs);
 	if (rc)
-		free_pages((unsigned long)io_tlb_start, order);
+		free_pages((unsigned long)vstart, order);
 	return rc;
 }
 
@@ -249,14 +256,25 @@ int
 swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
 {
 	unsigned long i, bytes;
+	unsigned char *v_overflow_buffer;
 
 	bytes = nslabs << IO_TLB_SHIFT;
 
 	io_tlb_nslabs = nslabs;
-	io_tlb_start = tlb;
+	io_tlb_start = virt_to_phys(tlb);
 	io_tlb_end = io_tlb_start + bytes;
 
-	memset(io_tlb_start, 0, bytes);
+	memset(tlb, 0, bytes);
+
+	/*
+	 * Get the overflow emergency buffer
+	 */
+	v_overflow_buffer = (void *)__get_free_pages(GFP_DMA,
+						     get_order(io_tlb_overflow));
+	if (!v_overflow_buffer)
+		goto cleanup2;
+
+	io_tlb_overflow_buffer = virt_to_phys(v_overflow_buffer);
 
 	/*
 	 * Allocate and initialize the free list array.  This array is used
@@ -266,7 +284,7 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
 	io_tlb_list = (unsigned int *)__get_free_pages(GFP_KERNEL,
 	                              get_order(io_tlb_nslabs * sizeof(int)));
 	if (!io_tlb_list)
-		goto cleanup2;
+		goto cleanup3;
 
 	for (i = 0; i < io_tlb_nslabs; i++)
  		io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
@@ -277,18 +295,10 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
 				 get_order(io_tlb_nslabs *
 					   sizeof(phys_addr_t)));
 	if (!io_tlb_orig_addr)
-		goto cleanup3;
+		goto cleanup4;
 
 	memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(phys_addr_t));
 
-	/*
-	 * Get the overflow emergency buffer
-	 */
-	io_tlb_overflow_buffer = (void *)__get_free_pages(GFP_DMA,
-	                                          get_order(io_tlb_overflow));
-	if (!io_tlb_overflow_buffer)
-		goto cleanup4;
-
 	swiotlb_print_info();
 
 	late_alloc = 1;
@@ -296,42 +306,42 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
 	return 0;
 
 cleanup4:
-	free_pages((unsigned long)io_tlb_orig_addr,
-		   get_order(io_tlb_nslabs * sizeof(phys_addr_t)));
-	io_tlb_orig_addr = NULL;
-cleanup3:
 	free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs *
 	                                                 sizeof(int)));
 	io_tlb_list = NULL;
+cleanup3:
+	free_pages((unsigned long)v_overflow_buffer,
+		   get_order(io_tlb_overflow));
+	io_tlb_overflow_buffer = 0;
 cleanup2:
-	io_tlb_end = NULL;
-	io_tlb_start = NULL;
+	io_tlb_end = 0;
+	io_tlb_start = 0;
 	io_tlb_nslabs = 0;
 	return -ENOMEM;
 }
 
 void __init swiotlb_free(void)
 {
-	if (!io_tlb_overflow_buffer)
+	if (!io_tlb_orig_addr)
 		return;
 
 	if (late_alloc) {
-		free_pages((unsigned long)io_tlb_overflow_buffer,
+		free_pages((unsigned long)phys_to_virt(io_tlb_overflow_buffer),
 			   get_order(io_tlb_overflow));
 		free_pages((unsigned long)io_tlb_orig_addr,
 			   get_order(io_tlb_nslabs * sizeof(phys_addr_t)));
 		free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs *
 								 sizeof(int)));
-		free_pages((unsigned long)io_tlb_start,
+		free_pages((unsigned long)phys_to_virt(io_tlb_start),
 			   get_order(io_tlb_nslabs << IO_TLB_SHIFT));
 	} else {
-		free_bootmem_late(__pa(io_tlb_overflow_buffer),
+		free_bootmem_late(io_tlb_overflow_buffer,
 				  PAGE_ALIGN(io_tlb_overflow));
 		free_bootmem_late(__pa(io_tlb_orig_addr),
 				  PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t)));
 		free_bootmem_late(__pa(io_tlb_list),
 				  PAGE_ALIGN(io_tlb_nslabs * sizeof(int)));
-		free_bootmem_late(__pa(io_tlb_start),
+		free_bootmem_late(io_tlb_start,
 				  PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT));
 	}
 	io_tlb_nslabs = 0;
@@ -339,21 +349,21 @@ void __init swiotlb_free(void)
 
 static int is_swiotlb_buffer(phys_addr_t paddr)
 {
-	return paddr >= virt_to_phys(io_tlb_start) &&
-		paddr < virt_to_phys(io_tlb_end);
+	return paddr >= io_tlb_start && paddr < io_tlb_end;
 }
 
 /*
  * Bounce: copy the swiotlb buffer back to the original dma location
  */
-void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
-		    enum dma_data_direction dir)
+static void swiotlb_bounce(phys_addr_t orig_addr, phys_addr_t tlb_addr,
+			   size_t size, enum dma_data_direction dir)
 {
-	unsigned long pfn = PFN_DOWN(phys);
+	unsigned long pfn = PFN_DOWN(orig_addr);
+	unsigned char *vaddr = phys_to_virt(tlb_addr);
 
 	if (PageHighMem(pfn_to_page(pfn))) {
 		/* The buffer does not have a mapping.  Map it in and copy */
-		unsigned int offset = phys & ~PAGE_MASK;
+		unsigned int offset = orig_addr & ~PAGE_MASK;
 		char *buffer;
 		unsigned int sz = 0;
 		unsigned long flags;
@@ -364,32 +374,31 @@ void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
 			local_irq_save(flags);
 			buffer = kmap_atomic(pfn_to_page(pfn));
 			if (dir == DMA_TO_DEVICE)
-				memcpy(dma_addr, buffer + offset, sz);
+				memcpy(vaddr, buffer + offset, sz);
 			else
-				memcpy(buffer + offset, dma_addr, sz);
+				memcpy(buffer + offset, vaddr, sz);
 			kunmap_atomic(buffer);
 			local_irq_restore(flags);
 
 			size -= sz;
 			pfn++;
-			dma_addr += sz;
+			vaddr += sz;
 			offset = 0;
 		}
+	} else if (dir == DMA_TO_DEVICE) {
+		memcpy(vaddr, phys_to_virt(orig_addr), size);
 	} else {
-		if (dir == DMA_TO_DEVICE)
-			memcpy(dma_addr, phys_to_virt(phys), size);
-		else
-			memcpy(phys_to_virt(phys), dma_addr, size);
+		memcpy(phys_to_virt(orig_addr), vaddr, size);
 	}
 }
-EXPORT_SYMBOL_GPL(swiotlb_bounce);
 
-void *swiotlb_tbl_map_single(struct device *hwdev, dma_addr_t tbl_dma_addr,
-			     phys_addr_t phys, size_t size,
-			     enum dma_data_direction dir)
+phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
+				   dma_addr_t tbl_dma_addr,
+				   phys_addr_t orig_addr, size_t size,
+				   enum dma_data_direction dir)
 {
 	unsigned long flags;
-	char *dma_addr;
+	phys_addr_t tlb_addr;
 	unsigned int nslots, stride, index, wrap;
 	int i;
 	unsigned long mask;
@@ -453,7 +462,7 @@ void *swiotlb_tbl_map_single(struct device *hwdev, dma_addr_t tbl_dma_addr,
 				io_tlb_list[i] = 0;
 			for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE - 1) && io_tlb_list[i]; i--)
 				io_tlb_list[i] = ++count;
-			dma_addr = io_tlb_start + (index << IO_TLB_SHIFT);
+			tlb_addr = io_tlb_start + (index << IO_TLB_SHIFT);
 
 			/*
 			 * Update the indices to avoid searching in the next
@@ -471,7 +480,7 @@ void *swiotlb_tbl_map_single(struct device *hwdev, dma_addr_t tbl_dma_addr,
 
 not_found:
 	spin_unlock_irqrestore(&io_tlb_lock, flags);
-	return NULL;
+	return SWIOTLB_MAP_ERROR;
 found:
 	spin_unlock_irqrestore(&io_tlb_lock, flags);
 
@@ -481,11 +490,11 @@ found:
 	 * needed.
 	 */
 	for (i = 0; i < nslots; i++)
-		io_tlb_orig_addr[index+i] = phys + (i << IO_TLB_SHIFT);
+		io_tlb_orig_addr[index+i] = orig_addr + (i << IO_TLB_SHIFT);
 	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
-		swiotlb_bounce(phys, dma_addr, size, DMA_TO_DEVICE);
+		swiotlb_bounce(orig_addr, tlb_addr, size, DMA_TO_DEVICE);
 
-	return dma_addr;
+	return tlb_addr;
 }
 EXPORT_SYMBOL_GPL(swiotlb_tbl_map_single);
 
@@ -493,11 +502,10 @@ EXPORT_SYMBOL_GPL(swiotlb_tbl_map_single);
  * Allocates bounce buffer and returns its kernel virtual address.
  */
 
-static void *
-map_single(struct device *hwdev, phys_addr_t phys, size_t size,
-	   enum dma_data_direction dir)
+phys_addr_t map_single(struct device *hwdev, phys_addr_t phys, size_t size,
+		       enum dma_data_direction dir)
 {
-	dma_addr_t start_dma_addr = swiotlb_virt_to_bus(hwdev, io_tlb_start);
+	dma_addr_t start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
 
 	return swiotlb_tbl_map_single(hwdev, start_dma_addr, phys, size, dir);
 }
@@ -505,20 +513,19 @@ map_single(struct device *hwdev, phys_addr_t phys, size_t size,
 /*
  * dma_addr is the kernel virtual address of the bounce buffer to unmap.
  */
-void
-swiotlb_tbl_unmap_single(struct device *hwdev, char *dma_addr, size_t size,
-			enum dma_data_direction dir)
+void swiotlb_tbl_unmap_single(struct device *hwdev, phys_addr_t tlb_addr,
+			      size_t size, enum dma_data_direction dir)
 {
 	unsigned long flags;
 	int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
-	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
-	phys_addr_t phys = io_tlb_orig_addr[index];
+	int index = (tlb_addr - io_tlb_start) >> IO_TLB_SHIFT;
+	phys_addr_t orig_addr = io_tlb_orig_addr[index];
 
 	/*
 	 * First, sync the memory before unmapping the entry
 	 */
-	if (phys && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)))
-		swiotlb_bounce(phys, dma_addr, size, DMA_FROM_DEVICE);
+	if (orig_addr && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)))
+		swiotlb_bounce(orig_addr, tlb_addr, size, DMA_FROM_DEVICE);
 
 	/*
 	 * Return the buffer to the free list by setting the corresponding
@@ -547,26 +554,27 @@ swiotlb_tbl_unmap_single(struct device *hwdev, char *dma_addr, size_t size,
 }
 EXPORT_SYMBOL_GPL(swiotlb_tbl_unmap_single);
 
-void
-swiotlb_tbl_sync_single(struct device *hwdev, char *dma_addr, size_t size,
-			enum dma_data_direction dir,
-			enum dma_sync_target target)
+void swiotlb_tbl_sync_single(struct device *hwdev, phys_addr_t tlb_addr,
+			     size_t size, enum dma_data_direction dir,
+			     enum dma_sync_target target)
 {
-	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
-	phys_addr_t phys = io_tlb_orig_addr[index];
+	int index = (tlb_addr - io_tlb_start) >> IO_TLB_SHIFT;
+	phys_addr_t orig_addr = io_tlb_orig_addr[index];
 
-	phys += ((unsigned long)dma_addr & ((1 << IO_TLB_SHIFT) - 1));
+	orig_addr += (unsigned long)tlb_addr & ((1 << IO_TLB_SHIFT) - 1);
 
 	switch (target) {
 	case SYNC_FOR_CPU:
 		if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
-			swiotlb_bounce(phys, dma_addr, size, DMA_FROM_DEVICE);
+			swiotlb_bounce(orig_addr, tlb_addr,
+				       size, DMA_FROM_DEVICE);
 		else
 			BUG_ON(dir != DMA_TO_DEVICE);
 		break;
 	case SYNC_FOR_DEVICE:
 		if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL))
-			swiotlb_bounce(phys, dma_addr, size, DMA_TO_DEVICE);
+			swiotlb_bounce(orig_addr, tlb_addr,
+				       size, DMA_TO_DEVICE);
 		else
 			BUG_ON(dir != DMA_FROM_DEVICE);
 		break;
@@ -589,12 +597,15 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 		dma_mask = hwdev->coherent_dma_mask;
 
 	ret = (void *)__get_free_pages(flags, order);
-	if (ret && swiotlb_virt_to_bus(hwdev, ret) + size - 1 > dma_mask) {
-		/*
-		 * The allocated memory isn't reachable by the device.
-		 */
-		free_pages((unsigned long) ret, order);
-		ret = NULL;
+	if (ret) {
+		dev_addr = swiotlb_virt_to_bus(hwdev, ret);
+		if (dev_addr + size - 1 > dma_mask) {
+			/*
+			 * The allocated memory isn't reachable by the device.
+			 */
+			free_pages((unsigned long) ret, order);
+			ret = NULL;
+		}
 	}
 	if (!ret) {
 		/*
@@ -602,25 +613,29 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 		 * GFP_DMA memory; fall back on map_single(), which
 		 * will grab memory from the lowest available address range.
 		 */
-		ret = map_single(hwdev, 0, size, DMA_FROM_DEVICE);
-		if (!ret)
+		phys_addr_t paddr = map_single(hwdev, 0, size, DMA_FROM_DEVICE);
+		if (paddr == SWIOTLB_MAP_ERROR)
 			return NULL;
-	}
 
-	memset(ret, 0, size);
-	dev_addr = swiotlb_virt_to_bus(hwdev, ret);
+		ret = phys_to_virt(paddr);
+		dev_addr = phys_to_dma(hwdev, paddr);
 
-	/* Confirm address can be DMA'd by device */
-	if (dev_addr + size - 1 > dma_mask) {
-		printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n",
-		       (unsigned long long)dma_mask,
-		       (unsigned long long)dev_addr);
+		/* Confirm address can be DMA'd by device */
+		if (dev_addr + size - 1 > dma_mask) {
+			printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n",
+			       (unsigned long long)dma_mask,
+			       (unsigned long long)dev_addr);
 
-		/* DMA_TO_DEVICE to avoid memcpy in unmap_single */
-		swiotlb_tbl_unmap_single(hwdev, ret, size, DMA_TO_DEVICE);
-		return NULL;
+			/* DMA_TO_DEVICE to avoid memcpy in unmap_single */
+			swiotlb_tbl_unmap_single(hwdev, paddr,
+						 size, DMA_TO_DEVICE);
+			return NULL;
+		}
 	}
+
 	*dma_handle = dev_addr;
+	memset(ret, 0, size);
+
 	return ret;
 }
 EXPORT_SYMBOL(swiotlb_alloc_coherent);
@@ -636,7 +651,7 @@ swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
 		free_pages((unsigned long)vaddr, get_order(size));
 	else
 		/* DMA_TO_DEVICE to avoid memcpy in swiotlb_tbl_unmap_single */
-		swiotlb_tbl_unmap_single(hwdev, vaddr, size, DMA_TO_DEVICE);
+		swiotlb_tbl_unmap_single(hwdev, paddr, size, DMA_TO_DEVICE);
 }
 EXPORT_SYMBOL(swiotlb_free_coherent);
 
@@ -677,9 +692,8 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
 			    enum dma_data_direction dir,
 			    struct dma_attrs *attrs)
 {
-	phys_addr_t phys = page_to_phys(page) + offset;
+	phys_addr_t map, phys = page_to_phys(page) + offset;
 	dma_addr_t dev_addr = phys_to_dma(dev, phys);
-	void *map;
 
 	BUG_ON(dir == DMA_NONE);
 	/*
@@ -690,23 +704,19 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
 	if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
 		return dev_addr;
 
-	/*
-	 * Oh well, have to allocate and map a bounce buffer.
-	 */
+	/* Oh well, have to allocate and map a bounce buffer. */
 	map = map_single(dev, phys, size, dir);
-	if (!map) {
+	if (map == SWIOTLB_MAP_ERROR) {
 		swiotlb_full(dev, size, dir, 1);
-		map = io_tlb_overflow_buffer;
+		return phys_to_dma(dev, io_tlb_overflow_buffer);
 	}
 
-	dev_addr = swiotlb_virt_to_bus(dev, map);
+	dev_addr = phys_to_dma(dev, map);
 
-	/*
-	 * Ensure that the address returned is DMA'ble
-	 */
+	/* Ensure that the address returned is DMA'ble */
 	if (!dma_capable(dev, dev_addr, size)) {
 		swiotlb_tbl_unmap_single(dev, map, size, dir);
-		dev_addr = swiotlb_virt_to_bus(dev, io_tlb_overflow_buffer);
+		return phys_to_dma(dev, io_tlb_overflow_buffer);
 	}
 
 	return dev_addr;
@@ -729,7 +739,7 @@ static void unmap_single(struct device *hwdev, dma_addr_t dev_addr,
 	BUG_ON(dir == DMA_NONE);
 
 	if (is_swiotlb_buffer(paddr)) {
-		swiotlb_tbl_unmap_single(hwdev, phys_to_virt(paddr), size, dir);
+		swiotlb_tbl_unmap_single(hwdev, paddr, size, dir);
 		return;
 	}
 
@@ -773,8 +783,7 @@ swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
 	BUG_ON(dir == DMA_NONE);
 
 	if (is_swiotlb_buffer(paddr)) {
-		swiotlb_tbl_sync_single(hwdev, phys_to_virt(paddr), size, dir,
-				       target);
+		swiotlb_tbl_sync_single(hwdev, paddr, size, dir, target);
 		return;
 	}
 
@@ -831,9 +840,9 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
 
 		if (swiotlb_force ||
 		    !dma_capable(hwdev, dev_addr, sg->length)) {
-			void *map = map_single(hwdev, sg_phys(sg),
-					       sg->length, dir);
-			if (!map) {
+			phys_addr_t map = map_single(hwdev, sg_phys(sg),
+						     sg->length, dir);
+			if (map == SWIOTLB_MAP_ERROR) {
 				/* Don't panic here, we expect map_sg users
 				   to do proper error handling. */
 				swiotlb_full(hwdev, sg->length, dir, 0);
@@ -842,7 +851,7 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
 				sgl[0].dma_length = 0;
 				return 0;
 			}
-			sg->dma_address = swiotlb_virt_to_bus(hwdev, map);
+			sg->dma_address = phys_to_dma(hwdev, map);
 		} else
 			sg->dma_address = dev_addr;
 		sg->dma_length = sg->length;
@@ -925,7 +934,7 @@ EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
 int
 swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
 {
-	return (dma_addr == swiotlb_virt_to_bus(hwdev, io_tlb_overflow_buffer));
+	return (dma_addr == phys_to_dma(hwdev, io_tlb_overflow_buffer));
 }
 EXPORT_SYMBOL(swiotlb_dma_mapping_error);
 
@@ -938,6 +947,6 @@ EXPORT_SYMBOL(swiotlb_dma_mapping_error);
 int
 swiotlb_dma_supported(struct device *hwdev, u64 mask)
 {
-	return swiotlb_virt_to_bus(hwdev, io_tlb_end - 1) <= mask;
+	return phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
 }
 EXPORT_SYMBOL(swiotlb_dma_supported);
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 39c99fe..4d48bb7 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -23,12 +23,12 @@
 #include <linux/ctype.h>
 #include <linux/kernel.h>
 #include <linux/kallsyms.h>
+#include <linux/math64.h>
 #include <linux/uaccess.h>
 #include <linux/ioport.h>
 #include <net/addrconf.h>
 
 #include <asm/page.h>		/* for PAGE_SIZE */
-#include <asm/div64.h>
 #include <asm/sections.h>	/* for dereference_function_descriptor() */
 
 #include "kstrtox.h"
@@ -38,6 +38,8 @@
  * @cp: The start of the string
  * @endp: A pointer to the end of the parsed string will be placed here
  * @base: The number base to use
+ *
+ * This function is obsolete. Please use kstrtoull instead.
  */
 unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
 {
@@ -61,6 +63,8 @@ EXPORT_SYMBOL(simple_strtoull);
  * @cp: The start of the string
  * @endp: A pointer to the end of the parsed string will be placed here
  * @base: The number base to use
+ *
+ * This function is obsolete. Please use kstrtoul instead.
  */
 unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
 {
@@ -73,6 +77,8 @@ EXPORT_SYMBOL(simple_strtoul);
  * @cp: The start of the string
  * @endp: A pointer to the end of the parsed string will be placed here
  * @base: The number base to use
+ *
+ * This function is obsolete. Please use kstrtol instead.
  */
 long simple_strtol(const char *cp, char **endp, unsigned int base)
 {
@@ -88,6 +94,8 @@ EXPORT_SYMBOL(simple_strtol);
  * @cp: The start of the string
  * @endp: A pointer to the end of the parsed string will be placed here
  * @base: The number base to use
+ *
+ * This function is obsolete. Please use kstrtoll instead.
  */
 long long simple_strtoll(const char *cp, char **endp, unsigned int base)
 {
@@ -2013,7 +2021,11 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
 	char digit;
 	int num = 0;
 	u8 qualifier;
-	u8 base;
+	unsigned int base;
+	union {
+		long long s;
+		unsigned long long u;
+	} val;
 	s16 field_width;
 	bool is_sign;
 
@@ -2053,8 +2065,11 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
 
 		/* get field width */
 		field_width = -1;
-		if (isdigit(*fmt))
+		if (isdigit(*fmt)) {
 			field_width = skip_atoi(&fmt);
+			if (field_width <= 0)
+				break;
+		}
 
 		/* get conversion qualifier */
 		qualifier = -1;
@@ -2154,58 +2169,61 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
 		    || (base == 0 && !isdigit(digit)))
 			break;
 
+		if (is_sign)
+			val.s = qualifier != 'L' ?
+				simple_strtol(str, &next, base) :
+				simple_strtoll(str, &next, base);
+		else
+			val.u = qualifier != 'L' ?
+				simple_strtoul(str, &next, base) :
+				simple_strtoull(str, &next, base);
+
+		if (field_width > 0 && next - str > field_width) {
+			if (base == 0)
+				_parse_integer_fixup_radix(str, &base);
+			while (next - str > field_width) {
+				if (is_sign)
+					val.s = div_s64(val.s, base);
+				else
+					val.u = div_u64(val.u, base);
+				--next;
+			}
+		}
+
 		switch (qualifier) {
 		case 'H':	/* that's 'hh' in format */
-			if (is_sign) {
-				signed char *s = (signed char *)va_arg(args, signed char *);
-				*s = (signed char)simple_strtol(str, &next, base);
-			} else {
-				unsigned char *s = (unsigned char *)va_arg(args, unsigned char *);
-				*s = (unsigned char)simple_strtoul(str, &next, base);
-			}
+			if (is_sign)
+				*va_arg(args, signed char *) = val.s;
+			else
+				*va_arg(args, unsigned char *) = val.u;
 			break;
 		case 'h':
-			if (is_sign) {
-				short *s = (short *)va_arg(args, short *);
-				*s = (short)simple_strtol(str, &next, base);
-			} else {
-				unsigned short *s = (unsigned short *)va_arg(args, unsigned short *);
-				*s = (unsigned short)simple_strtoul(str, &next, base);
-			}
+			if (is_sign)
+				*va_arg(args, short *) = val.s;
+			else
+				*va_arg(args, unsigned short *) = val.u;
 			break;
 		case 'l':
-			if (is_sign) {
-				long *l = (long *)va_arg(args, long *);
-				*l = simple_strtol(str, &next, base);
-			} else {
-				unsigned long *l = (unsigned long *)va_arg(args, unsigned long *);
-				*l = simple_strtoul(str, &next, base);
-			}
+			if (is_sign)
+				*va_arg(args, long *) = val.s;
+			else
+				*va_arg(args, unsigned long *) = val.u;
 			break;
 		case 'L':
-			if (is_sign) {
-				long long *l = (long long *)va_arg(args, long long *);
-				*l = simple_strtoll(str, &next, base);
-			} else {
-				unsigned long long *l = (unsigned long long *)va_arg(args, unsigned long long *);
-				*l = simple_strtoull(str, &next, base);
-			}
+			if (is_sign)
+				*va_arg(args, long long *) = val.s;
+			else
+				*va_arg(args, unsigned long long *) = val.u;
 			break;
 		case 'Z':
 		case 'z':
-		{
-			size_t *s = (size_t *)va_arg(args, size_t *);
-			*s = (size_t)simple_strtoul(str, &next, base);
-		}
-		break;
+			*va_arg(args, size_t *) = val.u;
+			break;
 		default:
-			if (is_sign) {
-				int *i = (int *)va_arg(args, int *);
-				*i = (int)simple_strtol(str, &next, base);
-			} else {
-				unsigned int *i = (unsigned int *)va_arg(args, unsigned int*);
-				*i = (unsigned int)simple_strtoul(str, &next, base);
-			}
+			if (is_sign)
+				*va_arg(args, int *) = val.s;
+			else
+				*va_arg(args, unsigned int *) = val.u;
 			break;
 		}
 		num++;
diff --git a/localversion-next b/localversion-next
new file mode 100644
index 0000000..83a0b90
--- /dev/null
+++ b/localversion-next
@@ -0,0 +1 @@
+-next-20121129
diff --git a/mm/Kconfig b/mm/Kconfig
index a3f8ddd..1680a012 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -143,6 +143,14 @@ config NO_BOOTMEM
 config MEMORY_ISOLATION
 	boolean
 
+config MOVABLE_NODE
+	boolean "Enable to assign a node which has only movable memory"
+	depends on HAVE_MEMBLOCK
+	depends on NO_BOOTMEM
+	depends on X86_64
+	depends on NUMA
+	default y
+
 # eventually, we can have this option just 'select SPARSEMEM'
 config MEMORY_HOTPLUG
 	bool "Allow for memory hot-add"
@@ -188,6 +196,21 @@ config SPLIT_PTLOCK_CPUS
 	default "4"
 
 #
+# support for memory balloon compaction
+config BALLOON_COMPACTION
+	bool "Allow for balloon memory compaction/migration"
+	def_bool y
+	depends on COMPACTION && VIRTIO_BALLOON
+	help
+	  Memory fragmentation introduced by ballooning might reduce
+	  significantly the number of 2MB contiguous memory blocks that can be
+	  used within a guest, thus imposing performance penalties associated
+	  with the reduced number of transparent huge pages that could be used
+	  by the guest workload. Allowing the compaction & migration for memory
+	  pages enlisted as being part of memory balloon devices avoids the
+	  scenario aforementioned and helps improving memory defragmentation.
+
+#
 # support for memory compaction
 config COMPACTION
 	bool "Allow for memory compaction"
diff --git a/mm/Makefile b/mm/Makefile
index 6b025f8..74046e1 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -16,7 +16,8 @@ obj-y			:= filemap.o mempool.o oom_kill.o fadvise.o \
 			   readahead.o swap.o truncate.o vmscan.o shmem.o \
 			   util.o mmzone.o vmstat.o backing-dev.o \
 			   mm_init.o mmu_context.o percpu.o slab_common.o \
-			   compaction.o interval_tree.o $(mmu-y)
+			   compaction.o balloon_compaction.o \
+			   interval_tree.o $(mmu-y)
 
 obj-y += init-mm.o
 
@@ -34,6 +35,7 @@ obj-$(CONFIG_FRONTSWAP)	+= frontswap.o
 obj-$(CONFIG_HAS_DMA)	+= dmapool.o
 obj-$(CONFIG_HUGETLBFS)	+= hugetlb.o
 obj-$(CONFIG_NUMA) 	+= mempolicy.o
+obj-$(CONFIG_ARCH_USES_NUMA_GENERIC_PGPROT) += numa.o
 obj-$(CONFIG_SPARSEMEM)	+= sparse.o
 obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o
 obj-$(CONFIG_SLOB) += slob.o
diff --git a/mm/balloon_compaction.c b/mm/balloon_compaction.c
new file mode 100644
index 0000000..2c8ce49
--- /dev/null
+++ b/mm/balloon_compaction.c
@@ -0,0 +1,304 @@
+/*
+ * mm/balloon_compaction.c
+ *
+ * Common interface for making balloon pages movable by compaction.
+ *
+ * Copyright (C) 2012, Red Hat, Inc.  Rafael Aquini <aquini@redhat.com>
+ */
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/balloon_compaction.h>
+
+/*
+ * balloon_devinfo_alloc - allocates a balloon device information descriptor.
+ * @balloon_dev_descriptor: pointer to reference the balloon device which
+ *                          this struct balloon_dev_info will be servicing.
+ *
+ * Driver must call it to properly allocate and initialize an instance of
+ * struct balloon_dev_info which will be used to reference a balloon device
+ * as well as to keep track of the balloon device page list.
+ */
+struct balloon_dev_info *balloon_devinfo_alloc(void *balloon_dev_descriptor)
+{
+	struct balloon_dev_info *b_dev_info;
+	b_dev_info = kmalloc(sizeof(*b_dev_info), GFP_KERNEL);
+	if (!b_dev_info)
+		return ERR_PTR(-ENOMEM);
+
+	b_dev_info->balloon_device = balloon_dev_descriptor;
+	b_dev_info->mapping = NULL;
+	b_dev_info->isolated_pages = 0;
+	spin_lock_init(&b_dev_info->pages_lock);
+	INIT_LIST_HEAD(&b_dev_info->pages);
+
+	return b_dev_info;
+}
+EXPORT_SYMBOL_GPL(balloon_devinfo_alloc);
+
+/*
+ * balloon_page_enqueue - allocates a new page and inserts it into the balloon
+ *			  page list.
+ * @b_dev_info: balloon device decriptor where we will insert a new page to
+ *
+ * Driver must call it to properly allocate a new enlisted balloon page
+ * before definetively removing it from the guest system.
+ * This function returns the page address for the recently enqueued page or
+ * NULL in the case we fail to allocate a new page this turn.
+ */
+struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info)
+{
+	unsigned long flags;
+	struct page *page = alloc_page(balloon_mapping_gfp_mask() |
+					__GFP_NOMEMALLOC | __GFP_NORETRY);
+	if (!page)
+		return NULL;
+
+	/*
+	 * Block others from accessing the 'page' when we get around to
+	 * establishing additional references. We should be the only one
+	 * holding a reference to the 'page' at this point.
+	 */
+	BUG_ON(!trylock_page(page));
+	spin_lock_irqsave(&b_dev_info->pages_lock, flags);
+	balloon_page_insert(page, b_dev_info->mapping, &b_dev_info->pages);
+	spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
+	unlock_page(page);
+	return page;
+}
+EXPORT_SYMBOL_GPL(balloon_page_enqueue);
+
+/*
+ * balloon_page_dequeue - removes a page from balloon's page list and returns
+ *			  the its address to allow the driver release the page.
+ * @b_dev_info: balloon device decriptor where we will grab a page from.
+ *
+ * Driver must call it to properly de-allocate a previous enlisted balloon page
+ * before definetively releasing it back to the guest system.
+ * This function returns the page address for the recently dequeued page or
+ * NULL in the case we find balloon's page list temporarily empty due to
+ * compaction isolated pages.
+ */
+struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info)
+{
+	struct page *page, *tmp;
+	unsigned long flags;
+	bool dequeued_page;
+
+	dequeued_page = false;
+	list_for_each_entry_safe(page, tmp, &b_dev_info->pages, lru) {
+		/*
+		 * Block others from accessing the 'page' while we get around
+		 * establishing additional references and preparing the 'page'
+		 * to be released by the balloon driver.
+		 */
+		if (trylock_page(page)) {
+			spin_lock_irqsave(&b_dev_info->pages_lock, flags);
+			/*
+			 * Raise the page refcount here to prevent any wrong
+			 * attempt to isolate this page, in case of coliding
+			 * with balloon_page_isolate() just after we release
+			 * the page lock.
+			 *
+			 * balloon_page_free() will take care of dropping
+			 * this extra refcount later.
+			 */
+			get_page(page);
+			balloon_page_delete(page);
+			spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
+			unlock_page(page);
+			dequeued_page = true;
+			break;
+		}
+	}
+
+	if (!dequeued_page) {
+		/*
+		 * If we are unable to dequeue a balloon page because the page
+		 * list is empty and there is no isolated pages, then something
+		 * went out of track and some balloon pages are lost.
+		 * BUG() here, otherwise the balloon driver may get stuck into
+		 * an infinite loop while attempting to release all its pages.
+		 */
+		spin_lock_irqsave(&b_dev_info->pages_lock, flags);
+		if (unlikely(list_empty(&b_dev_info->pages) &&
+			     !b_dev_info->isolated_pages))
+			BUG();
+		spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
+		page = NULL;
+	}
+	return page;
+}
+EXPORT_SYMBOL_GPL(balloon_page_dequeue);
+
+#ifdef CONFIG_BALLOON_COMPACTION
+/*
+ * balloon_mapping_alloc - allocates a special ->mapping for ballooned pages.
+ * @b_dev_info: holds the balloon device information descriptor.
+ * @a_ops: balloon_mapping address_space_operations descriptor.
+ *
+ * Driver must call it to properly allocate and initialize an instance of
+ * struct address_space which will be used as the special page->mapping for
+ * balloon device enlisted page instances.
+ */
+struct address_space *balloon_mapping_alloc(struct balloon_dev_info *b_dev_info,
+				const struct address_space_operations *a_ops)
+{
+	struct address_space *mapping;
+
+	mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
+	if (!mapping)
+		return ERR_PTR(-ENOMEM);
+
+	/*
+	 * Give a clean 'zeroed' status to all elements of this special
+	 * balloon page->mapping struct address_space instance.
+	 */
+	address_space_init_once(mapping);
+
+	/*
+	 * Set mapping->flags appropriately, to allow balloon pages
+	 * ->mapping identification.
+	 */
+	mapping_set_balloon(mapping);
+	mapping_set_gfp_mask(mapping, balloon_mapping_gfp_mask());
+
+	/* balloon's page->mapping->a_ops callback descriptor */
+	mapping->a_ops = a_ops;
+
+	/*
+	 * Establish a pointer reference back to the balloon device descriptor
+	 * this particular page->mapping will be servicing.
+	 * This is used by compaction / migration procedures to identify and
+	 * access the balloon device pageset while isolating / migrating pages.
+	 *
+	 * As some balloon drivers can register multiple balloon devices
+	 * for a single guest, this also helps compaction / migration to
+	 * properly deal with multiple balloon pagesets, when required.
+	 */
+	mapping->private_data = b_dev_info;
+	b_dev_info->mapping = mapping;
+
+	return mapping;
+}
+EXPORT_SYMBOL_GPL(balloon_mapping_alloc);
+
+static inline void __isolate_balloon_page(struct page *page)
+{
+	struct balloon_dev_info *b_dev_info = page->mapping->private_data;
+	unsigned long flags;
+	spin_lock_irqsave(&b_dev_info->pages_lock, flags);
+	list_del(&page->lru);
+	b_dev_info->isolated_pages++;
+	spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
+}
+
+static inline void __putback_balloon_page(struct page *page)
+{
+	struct balloon_dev_info *b_dev_info = page->mapping->private_data;
+	unsigned long flags;
+	spin_lock_irqsave(&b_dev_info->pages_lock, flags);
+	list_add(&page->lru, &b_dev_info->pages);
+	b_dev_info->isolated_pages--;
+	spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
+}
+
+static inline int __migrate_balloon_page(struct address_space *mapping,
+		struct page *newpage, struct page *page, enum migrate_mode mode)
+{
+	return page->mapping->a_ops->migratepage(mapping, newpage, page, mode);
+}
+
+/* __isolate_lru_page() counterpart for a ballooned page */
+bool balloon_page_isolate(struct page *page)
+{
+	/*
+	 * Avoid burning cycles with pages that are yet under __free_pages(),
+	 * or just got freed under us.
+	 *
+	 * In case we 'win' a race for a balloon page being freed under us and
+	 * raise its refcount preventing __free_pages() from doing its job
+	 * the put_page() at the end of this block will take care of
+	 * release this page, thus avoiding a nasty leakage.
+	 */
+	if (likely(get_page_unless_zero(page))) {
+		/*
+		 * As balloon pages are not isolated from LRU lists, concurrent
+		 * compaction threads can race against page migration functions
+		 * as well as race against the balloon driver releasing a page.
+		 *
+		 * In order to avoid having an already isolated balloon page
+		 * being (wrongly) re-isolated while it is under migration,
+		 * or to avoid attempting to isolate pages being released by
+		 * the balloon driver, lets be sure we have the page lock
+		 * before proceeding with the balloon page isolation steps.
+		 */
+		if (likely(trylock_page(page))) {
+			/*
+			 * A ballooned page, by default, has just one refcount.
+			 * Prevent concurrent compaction threads from isolating
+			 * an already isolated balloon page by refcount check.
+			 */
+			if (__is_movable_balloon_page(page) &&
+			    page_count(page) == 2) {
+				__isolate_balloon_page(page);
+				balloon_event_count(COMPACTBALLOONISOLATED);
+				unlock_page(page);
+				return true;
+			}
+			unlock_page(page);
+		}
+		put_page(page);
+	}
+	return false;
+}
+
+/* putback_lru_page() counterpart for a ballooned page */
+void balloon_page_putback(struct page *page)
+{
+	/*
+	 * 'lock_page()' stabilizes the page and prevents races against
+	 * concurrent isolation threads attempting to re-isolate it.
+	 */
+	lock_page(page);
+
+	if (__is_movable_balloon_page(page)) {
+		__putback_balloon_page(page);
+		/* drop the extra ref count taken for page isolation */
+		put_page(page);
+		balloon_event_count(COMPACTBALLOONRETURNED);
+	} else {
+		WARN_ON(1);
+		dump_page(page);
+	}
+	unlock_page(page);
+}
+
+/* move_to_new_page() counterpart for a ballooned page */
+int balloon_page_migrate(struct page *newpage,
+			 struct page *page, enum migrate_mode mode)
+{
+	struct address_space *mapping;
+	int rc = -EAGAIN;
+
+	/*
+	 * Block others from accessing the 'newpage' when we get around to
+	 * establishing additional references. We should be the only one
+	 * holding a reference to the 'newpage' at this point.
+	 */
+	BUG_ON(!trylock_page(newpage));
+
+	if (WARN_ON(!__is_movable_balloon_page(page))) {
+		dump_page(page);
+		unlock_page(newpage);
+		return rc;
+	}
+
+	mapping = page->mapping;
+	if (mapping)
+		rc = __migrate_balloon_page(mapping, newpage, page, mode);
+
+	unlock_page(newpage);
+	return rc;
+}
+#endif /* CONFIG_BALLOON_COMPACTION */
diff --git a/mm/bootmem.c b/mm/bootmem.c
index f468185..19262ac 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -147,21 +147,21 @@ unsigned long __init init_bootmem(unsigned long start, unsigned long pages)
 
 /*
  * free_bootmem_late - free bootmem pages directly to page allocator
- * @addr: starting address of the range
+ * @addr: starting physical address of the range
  * @size: size of the range in bytes
  *
  * This is only useful when the bootmem allocator has already been torn
  * down, but we are still initializing the system.  Pages are given directly
  * to the page allocator, no bootmem metadata is updated because it is gone.
  */
-void __init free_bootmem_late(unsigned long addr, unsigned long size)
+void __init free_bootmem_late(unsigned long physaddr, unsigned long size)
 {
 	unsigned long cursor, end;
 
-	kmemleak_free_part(__va(addr), size);
+	kmemleak_free_part(__va(physaddr), size);
 
-	cursor = PFN_UP(addr);
-	end = PFN_DOWN(addr + size);
+	cursor = PFN_UP(physaddr);
+	end = PFN_DOWN(physaddr + size);
 
 	for (; cursor < end; cursor++) {
 		__free_pages_bootmem(pfn_to_page(cursor), 0);
@@ -229,6 +229,22 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
 	return count;
 }
 
+static void reset_node_lowmem_managed_pages(pg_data_t *pgdat)
+{
+	struct zone *z;
+
+	/*
+	 * In free_area_init_core(), highmem zone's managed_pages is set to
+	 * present_pages, and bootmem allocator doesn't allocate from highmem
+	 * zones. So there's no need to recalculate managed_pages because all
+	 * highmem pages will be managed by the buddy system. Here highmem
+	 * zone also includes highmem movable zone.
+	 */
+	for (z = pgdat->node_zones; z < pgdat->node_zones + MAX_NR_ZONES; z++)
+		if (!is_highmem(z))
+			z->managed_pages = 0;
+}
+
 /**
  * free_all_bootmem_node - release a node's free pages to the buddy allocator
  * @pgdat: node to be released
@@ -238,6 +254,7 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
 unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
 {
 	register_page_bootmem_info_node(pgdat);
+	reset_node_lowmem_managed_pages(pgdat);
 	return free_all_bootmem_core(pgdat->bdata);
 }
 
@@ -250,6 +267,10 @@ unsigned long __init free_all_bootmem(void)
 {
 	unsigned long total_pages = 0;
 	bootmem_data_t *bdata;
+	struct pglist_data *pgdat;
+
+	for_each_online_pgdat(pgdat)
+		reset_node_lowmem_managed_pages(pgdat);
 
 	list_for_each_entry(bdata, &bdata_list, list)
 		total_pages += free_all_bootmem_core(bdata);
@@ -377,21 +398,21 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
 
 /**
  * free_bootmem - mark a page range as usable
- * @addr: starting address of the range
+ * @addr: starting physical address of the range
  * @size: size of the range in bytes
  *
  * Partial pages will be considered reserved and left as they are.
  *
  * The range must be contiguous but may span node boundaries.
  */
-void __init free_bootmem(unsigned long addr, unsigned long size)
+void __init free_bootmem(unsigned long physaddr, unsigned long size)
 {
 	unsigned long start, end;
 
-	kmemleak_free_part(__va(addr), size);
+	kmemleak_free_part(__va(physaddr), size);
 
-	start = PFN_UP(addr);
-	end = PFN_DOWN(addr + size);
+	start = PFN_UP(physaddr);
+	end = PFN_DOWN(physaddr + size);
 
 	mark_bootmem(start, end, 0, 0);
 }
@@ -575,27 +596,6 @@ find_block:
 	return NULL;
 }
 
-static void * __init alloc_arch_preferred_bootmem(bootmem_data_t *bdata,
-					unsigned long size, unsigned long align,
-					unsigned long goal, unsigned long limit)
-{
-	if (WARN_ON_ONCE(slab_is_available()))
-		return kzalloc(size, GFP_NOWAIT);
-
-#ifdef CONFIG_HAVE_ARCH_BOOTMEM
-	{
-		bootmem_data_t *p_bdata;
-
-		p_bdata = bootmem_arch_preferred_node(bdata, size, align,
-							goal, limit);
-		if (p_bdata)
-			return alloc_bootmem_bdata(p_bdata, size, align,
-							goal, limit);
-	}
-#endif
-	return NULL;
-}
-
 static void * __init alloc_bootmem_core(unsigned long size,
 					unsigned long align,
 					unsigned long goal,
@@ -604,9 +604,8 @@ static void * __init alloc_bootmem_core(unsigned long size,
 	bootmem_data_t *bdata;
 	void *region;
 
-	region = alloc_arch_preferred_bootmem(NULL, size, align, goal, limit);
-	if (region)
-		return region;
+	if (WARN_ON_ONCE(slab_is_available()))
+		return kzalloc(size, GFP_NOWAIT);
 
 	list_for_each_entry(bdata, &bdata_list, list) {
 		if (goal && bdata->node_low_pfn <= PFN_DOWN(goal))
@@ -704,11 +703,9 @@ void * __init ___alloc_bootmem_node_nopanic(pg_data_t *pgdat,
 {
 	void *ptr;
 
+	if (WARN_ON_ONCE(slab_is_available()))
+		return kzalloc(size, GFP_NOWAIT);
 again:
-	ptr = alloc_arch_preferred_bootmem(pgdat->bdata, size,
-					   align, goal, limit);
-	if (ptr)
-		return ptr;
 
 	/* do not panic in alloc_bootmem_bdata() */
 	if (limit && goal + size > limit)
diff --git a/mm/compaction.c b/mm/compaction.c
index 9eef558..d33e6d0 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -14,6 +14,7 @@
 #include <linux/backing-dev.h>
 #include <linux/sysctl.h>
 #include <linux/sysfs.h>
+#include <linux/balloon_compaction.h>
 #include "internal.h"
 
 #if defined CONFIG_COMPACTION || defined CONFIG_CMA
@@ -214,60 +215,6 @@ static bool suitable_migration_target(struct page *page)
 	return false;
 }
 
-static void compact_capture_page(struct compact_control *cc)
-{
-	unsigned long flags;
-	int mtype, mtype_low, mtype_high;
-
-	if (!cc->page || *cc->page)
-		return;
-
-	/*
-	 * For MIGRATE_MOVABLE allocations we capture a suitable page ASAP
-	 * regardless of the migratetype of the freelist is is captured from.
-	 * This is fine because the order for a high-order MIGRATE_MOVABLE
-	 * allocation is typically at least a pageblock size and overall
-	 * fragmentation is not impaired. Other allocation types must
-	 * capture pages from their own migratelist because otherwise they
-	 * could pollute other pageblocks like MIGRATE_MOVABLE with
-	 * difficult to move pages and making fragmentation worse overall.
-	 */
-	if (cc->migratetype == MIGRATE_MOVABLE) {
-		mtype_low = 0;
-		mtype_high = MIGRATE_PCPTYPES;
-	} else {
-		mtype_low = cc->migratetype;
-		mtype_high = cc->migratetype + 1;
-	}
-
-	/* Speculatively examine the free lists without zone lock */
-	for (mtype = mtype_low; mtype < mtype_high; mtype++) {
-		int order;
-		for (order = cc->order; order < MAX_ORDER; order++) {
-			struct page *page;
-			struct free_area *area;
-			area = &(cc->zone->free_area[order]);
-			if (list_empty(&area->free_list[mtype]))
-				continue;
-
-			/* Take the lock and attempt capture of the page */
-			if (!compact_trylock_irqsave(&cc->zone->lock, &flags, cc))
-				return;
-			if (!list_empty(&area->free_list[mtype])) {
-				page = list_entry(area->free_list[mtype].next,
-							struct page, lru);
-				if (capture_free_page(page, cc->order, mtype)) {
-					spin_unlock_irqrestore(&cc->zone->lock,
-									flags);
-					*cc->page = page;
-					return;
-				}
-			}
-			spin_unlock_irqrestore(&cc->zone->lock, flags);
-		}
-	}
-}
-
 /*
  * Isolate free pages onto a private freelist. Caller must hold zone->lock.
  * If @strict is true, will abort returning 0 on any invalid PFNs or non-free
@@ -565,9 +512,24 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc,
 			goto next_pageblock;
 		}
 
-		/* Check may be lockless but that's ok as we recheck later */
-		if (!PageLRU(page))
+		/*
+		 * Check may be lockless but that's ok as we recheck later.
+		 * It's possible to migrate LRU pages and balloon pages
+		 * Skip any other type of page
+		 */
+		if (!PageLRU(page)) {
+			if (unlikely(balloon_page_movable(page))) {
+				if (locked && balloon_page_isolate(page)) {
+					/* Successfully isolated */
+					cc->finished_update_migrate = true;
+					list_add(&page->lru, migratelist);
+					cc->nr_migratepages++;
+					nr_isolated++;
+					goto check_compact_cluster;
+				}
+			}
 			continue;
+		}
 
 		/*
 		 * PageLRU is set. lru_lock normally excludes isolation
@@ -621,6 +583,7 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc,
 		cc->nr_migratepages++;
 		nr_isolated++;
 
+check_compact_cluster:
 		/* Avoid isolating too much */
 		if (cc->nr_migratepages == COMPACT_CLUSTER_MAX) {
 			++low_pfn;
@@ -928,6 +891,60 @@ unsigned long compaction_suitable(struct zone *zone, int order)
 	return COMPACT_CONTINUE;
 }
 
+static void compact_capture_page(struct compact_control *cc)
+{
+	unsigned long flags;
+	int mtype, mtype_low, mtype_high;
+
+	if (!cc->page || *cc->page)
+		return;
+
+	/*
+	 * For MIGRATE_MOVABLE allocations we capture a suitable page ASAP
+	 * regardless of the migratetype of the freelist is is captured from.
+	 * This is fine because the order for a high-order MIGRATE_MOVABLE
+	 * allocation is typically at least a pageblock size and overall
+	 * fragmentation is not impaired. Other allocation types must
+	 * capture pages from their own migratelist because otherwise they
+	 * could pollute other pageblocks like MIGRATE_MOVABLE with
+	 * difficult to move pages and making fragmentation worse overall.
+	 */
+	if (cc->migratetype == MIGRATE_MOVABLE) {
+		mtype_low = 0;
+		mtype_high = MIGRATE_PCPTYPES;
+	} else {
+		mtype_low = cc->migratetype;
+		mtype_high = cc->migratetype + 1;
+	}
+
+	/* Speculatively examine the free lists without zone lock */
+	for (mtype = mtype_low; mtype < mtype_high; mtype++) {
+		int order;
+		for (order = cc->order; order < MAX_ORDER; order++) {
+			struct page *page;
+			struct free_area *area;
+			area = &(cc->zone->free_area[order]);
+			if (list_empty(&area->free_list[mtype]))
+				continue;
+
+			/* Take the lock and attempt capture of the page */
+			if (!compact_trylock_irqsave(&cc->zone->lock, &flags, cc))
+				return;
+			if (!list_empty(&area->free_list[mtype])) {
+				page = list_entry(area->free_list[mtype].next,
+							struct page, lru);
+				if (capture_free_page(page, cc->order, mtype)) {
+					spin_unlock_irqrestore(&cc->zone->lock,
+									flags);
+					*cc->page = page;
+					return;
+				}
+			}
+			spin_unlock_irqrestore(&cc->zone->lock, flags);
+		}
+	}
+}
+
 static int compact_zone(struct zone *zone, struct compact_control *cc)
 {
 	int ret;
@@ -978,7 +995,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
 		switch (isolate_migratepages(zone, cc)) {
 		case ISOLATE_ABORT:
 			ret = COMPACT_PARTIAL;
-			putback_lru_pages(&cc->migratepages);
+			putback_movable_pages(&cc->migratepages);
 			cc->nr_migratepages = 0;
 			goto out;
 		case ISOLATE_NONE:
@@ -1001,9 +1018,9 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
 		trace_mm_compaction_migratepages(nr_migrate - nr_remaining,
 						nr_remaining);
 
-		/* Release LRU pages not migrated */
+		/* Release isolated pages not migrated */
 		if (err) {
-			putback_lru_pages(&cc->migratepages);
+			putback_movable_pages(&cc->migratepages);
 			cc->nr_migratepages = 0;
 			if (err == -ENOMEM) {
 				ret = COMPACT_PARTIAL;
diff --git a/mm/dmapool.c b/mm/dmapool.c
index c5ab33b..668f263 100644
--- a/mm/dmapool.c
+++ b/mm/dmapool.c
@@ -50,7 +50,6 @@ struct dma_pool {		/* the pool */
 	size_t allocation;
 	size_t boundary;
 	char name[32];
-	wait_queue_head_t waitq;
 	struct list_head pools;
 };
 
@@ -62,8 +61,6 @@ struct dma_page {		/* cacheable header for 'allocation' bytes */
 	unsigned int offset;
 };
 
-#define	POOL_TIMEOUT_JIFFIES	((100 /* msec */ * HZ) / 1000)
-
 static DEFINE_MUTEX(pools_lock);
 
 static ssize_t
@@ -135,6 +132,7 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev,
 {
 	struct dma_pool *retval;
 	size_t allocation;
+	int node;
 
 	if (align == 0) {
 		align = 1;
@@ -159,7 +157,9 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev,
 		return NULL;
 	}
 
-	retval = kmalloc_node(sizeof(*retval), GFP_KERNEL, dev_to_node(dev));
+	node = WARN_ON(!dev) ? -1 : dev_to_node(dev);
+
+	retval = kmalloc_node(sizeof(*retval), GFP_KERNEL, node);
 	if (!retval)
 		return retval;
 
@@ -172,7 +172,6 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev,
 	retval->size = size;
 	retval->boundary = boundary;
 	retval->allocation = allocation;
-	init_waitqueue_head(&retval->waitq);
 
 	if (dev) {
 		int ret;
@@ -227,7 +226,6 @@ static struct dma_page *pool_alloc_page(struct dma_pool *pool, gfp_t mem_flags)
 		memset(page->vaddr, POOL_POISON_FREED, pool->allocation);
 #endif
 		pool_initialise_page(pool, page);
-		list_add(&page->page_list, &pool->page_list);
 		page->in_use = 0;
 		page->offset = 0;
 	} else {
@@ -315,30 +313,21 @@ void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags,
 	might_sleep_if(mem_flags & __GFP_WAIT);
 
 	spin_lock_irqsave(&pool->lock, flags);
- restart:
 	list_for_each_entry(page, &pool->page_list, page_list) {
 		if (page->offset < pool->allocation)
 			goto ready;
 	}
-	page = pool_alloc_page(pool, GFP_ATOMIC);
-	if (!page) {
-		if (mem_flags & __GFP_WAIT) {
-			DECLARE_WAITQUEUE(wait, current);
 
-			__set_current_state(TASK_UNINTERRUPTIBLE);
-			__add_wait_queue(&pool->waitq, &wait);
-			spin_unlock_irqrestore(&pool->lock, flags);
+	/* pool_alloc_page() might sleep, so temporarily drop &pool->lock */
+	spin_unlock_irqrestore(&pool->lock, flags);
 
-			schedule_timeout(POOL_TIMEOUT_JIFFIES);
+	page = pool_alloc_page(pool, mem_flags);
+	if (!page)
+		return NULL;
 
-			spin_lock_irqsave(&pool->lock, flags);
-			__remove_wait_queue(&pool->waitq, &wait);
-			goto restart;
-		}
-		retval = NULL;
-		goto done;
-	}
+	spin_lock_irqsave(&pool->lock, flags);
 
+	list_add(&page->page_list, &pool->page_list);
  ready:
 	page->in_use++;
 	offset = page->offset;
@@ -346,9 +335,32 @@ void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags,
 	retval = offset + page->vaddr;
 	*handle = offset + page->dma;
 #ifdef	DMAPOOL_DEBUG
+	{
+		int i;
+		u8 *data = retval;
+		/* page->offset is stored in first 4 bytes */
+		for (i = sizeof(page->offset); i < pool->size; i++) {
+			if (data[i] == POOL_POISON_FREED)
+				continue;
+			if (pool->dev)
+				dev_err(pool->dev,
+					"dma_pool_alloc %s, %p (corruped)\n",
+					pool->name, retval);
+			else
+				pr_err("dma_pool_alloc %s, %p (corruped)\n",
+					pool->name, retval);
+
+			/*
+			 * Dump the first 4 bytes even if they are not
+			 * POOL_POISON_FREED
+			 */
+			print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1,
+					data, pool->size, 1);
+			break;
+		}
+	}
 	memset(retval, POOL_POISON_ALLOCATED, pool->size);
 #endif
- done:
 	spin_unlock_irqrestore(&pool->lock, flags);
 	return retval;
 }
@@ -435,8 +447,6 @@ void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t dma)
 	page->in_use--;
 	*(int *)vaddr = page->offset;
 	page->offset = offset;
-	if (waitqueue_active(&pool->waitq))
-		wake_up_locked(&pool->waitq);
 	/*
 	 * Resist a temptation to do
 	 *    if (!is_page_busy(page)) pool_free_page(pool, page);
diff --git a/mm/filemap.c b/mm/filemap.c
index 83efee7..653f1d0 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -35,6 +35,9 @@
 #include <linux/cleancache.h>
 #include "internal.h"
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/filemap.h>
+
 /*
  * FIXME: remove all knowledge of the buffer layer from the core VM
  */
@@ -113,6 +116,7 @@ void __delete_from_page_cache(struct page *page)
 {
 	struct address_space *mapping = page->mapping;
 
+	trace_mm_filemap_delete_from_page_cache(page);
 	/*
 	 * if we're uptodate, flush out into the cleancache, otherwise
 	 * invalidate any existing cleancache entries.  We can't leave
@@ -463,6 +467,7 @@ int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
 		if (likely(!error)) {
 			mapping->nrpages++;
 			__inc_zone_page_state(page, NR_FILE_PAGES);
+			trace_mm_filemap_add_to_page_cache(page);
 			spin_unlock_irq(&mapping->tree_lock);
 		} else {
 			page->mapping = NULL;
@@ -2056,7 +2061,7 @@ EXPORT_SYMBOL(iov_iter_fault_in_readable);
 /*
  * Return the count of just the current iov_iter segment.
  */
-size_t iov_iter_single_seg_count(struct iov_iter *i)
+size_t iov_iter_single_seg_count(const struct iov_iter *i)
 {
 	const struct iovec *iov = i->iov;
 	if (i->nr_segs == 1)
diff --git a/mm/highmem.c b/mm/highmem.c
index 2da13a5..b32b70c 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -99,12 +99,13 @@ struct page *kmap_to_page(void *vaddr)
 	unsigned long addr = (unsigned long)vaddr;
 
 	if (addr >= PKMAP_ADDR(0) && addr < PKMAP_ADDR(LAST_PKMAP)) {
-		int i = (addr - PKMAP_ADDR(0)) >> PAGE_SHIFT;
+		int i = PKMAP_NR(addr);
 		return pte_page(pkmap_page_table[i]);
 	}
 
 	return virt_to_page(addr);
 }
+EXPORT_SYMBOL(kmap_to_page);
 
 static void flush_all_zero_pkmaps(void)
 {
@@ -137,8 +138,7 @@ static void flush_all_zero_pkmaps(void)
 		 * So no dangers, even with speculative execution.
 		 */
 		page = pte_page(pkmap_page_table[i]);
-		pte_clear(&init_mm, (unsigned long)page_address(page),
-			  &pkmap_page_table[i]);
+		pte_clear(&init_mm, PKMAP_ADDR(i), &pkmap_page_table[i]);
 
 		set_page_address(page, NULL);
 		need_flush = 1;
@@ -324,11 +324,7 @@ struct page_address_map {
 	struct list_head list;
 };
 
-/*
- * page_address_map freelist, allocated from page_address_maps.
- */
-static struct list_head page_address_pool;	/* freelist */
-static spinlock_t pool_lock;			/* protects page_address_pool */
+static struct page_address_map page_address_maps[LAST_PKMAP];
 
 /*
  * Hash table bucket
@@ -393,14 +389,7 @@ void set_page_address(struct page *page, void *virtual)
 
 	pas = page_slot(page);
 	if (virtual) {		/* Add */
-		BUG_ON(list_empty(&page_address_pool));
-
-		spin_lock_irqsave(&pool_lock, flags);
-		pam = list_entry(page_address_pool.next,
-				struct page_address_map, list);
-		list_del(&pam->list);
-		spin_unlock_irqrestore(&pool_lock, flags);
-
+		pam = &page_address_maps[PKMAP_NR((unsigned long)virtual)];
 		pam->page = page;
 		pam->virtual = virtual;
 
@@ -413,9 +402,6 @@ void set_page_address(struct page *page, void *virtual)
 			if (pam->page == page) {
 				list_del(&pam->list);
 				spin_unlock_irqrestore(&pas->lock, flags);
-				spin_lock_irqsave(&pool_lock, flags);
-				list_add_tail(&pam->list, &page_address_pool);
-				spin_unlock_irqrestore(&pool_lock, flags);
 				goto done;
 			}
 		}
@@ -425,20 +411,14 @@ done:
 	return;
 }
 
-static struct page_address_map page_address_maps[LAST_PKMAP];
-
 void __init page_address_init(void)
 {
 	int i;
 
-	INIT_LIST_HEAD(&page_address_pool);
-	for (i = 0; i < ARRAY_SIZE(page_address_maps); i++)
-		list_add(&page_address_maps[i].list, &page_address_pool);
 	for (i = 0; i < ARRAY_SIZE(page_address_htable); i++) {
 		INIT_LIST_HEAD(&page_address_htable[i].lh);
 		spin_lock_init(&page_address_htable[i].lock);
 	}
-	spin_lock_init(&pool_lock);
 }
 
 #endif	/* defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL) */
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 40f17c3..e0de3c9 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -12,12 +12,15 @@
 #include <linux/mmu_notifier.h>
 #include <linux/rmap.h>
 #include <linux/swap.h>
+#include <linux/shrinker.h>
 #include <linux/mm_inline.h>
 #include <linux/kthread.h>
 #include <linux/khugepaged.h>
 #include <linux/freezer.h>
 #include <linux/mman.h>
 #include <linux/pagemap.h>
+#include <linux/migrate.h>
+
 #include <asm/tlb.h>
 #include <asm/pgalloc.h>
 #include "internal.h"
@@ -37,7 +40,8 @@ unsigned long transparent_hugepage_flags __read_mostly =
 	(1<<TRANSPARENT_HUGEPAGE_REQ_MADV_FLAG)|
 #endif
 	(1<<TRANSPARENT_HUGEPAGE_DEFRAG_FLAG)|
-	(1<<TRANSPARENT_HUGEPAGE_DEFRAG_KHUGEPAGED_FLAG);
+	(1<<TRANSPARENT_HUGEPAGE_DEFRAG_KHUGEPAGED_FLAG)|
+	(1<<TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG);
 
 /* default scan 8*512 pte (or vmas) every 30 second */
 static unsigned int khugepaged_pages_to_scan __read_mostly = HPAGE_PMD_NR*8;
@@ -159,6 +163,77 @@ static int start_khugepaged(void)
 	return err;
 }
 
+static atomic_t huge_zero_refcount;
+static unsigned long huge_zero_pfn __read_mostly;
+
+static inline bool is_huge_zero_pfn(unsigned long pfn)
+{
+	unsigned long zero_pfn = ACCESS_ONCE(huge_zero_pfn);
+	return zero_pfn && pfn == zero_pfn;
+}
+
+static inline bool is_huge_zero_pmd(pmd_t pmd)
+{
+	return is_huge_zero_pfn(pmd_pfn(pmd));
+}
+
+static unsigned long get_huge_zero_page(void)
+{
+	struct page *zero_page;
+retry:
+	if (likely(atomic_inc_not_zero(&huge_zero_refcount)))
+		return ACCESS_ONCE(huge_zero_pfn);
+
+	zero_page = alloc_pages((GFP_TRANSHUGE | __GFP_ZERO) & ~__GFP_MOVABLE,
+			HPAGE_PMD_ORDER);
+	if (!zero_page) {
+		count_vm_event(THP_ZERO_PAGE_ALLOC_FAILED);
+		return 0;
+	}
+	count_vm_event(THP_ZERO_PAGE_ALLOC);
+	preempt_disable();
+	if (cmpxchg(&huge_zero_pfn, 0, page_to_pfn(zero_page))) {
+		preempt_enable();
+		__free_page(zero_page);
+		goto retry;
+	}
+
+	/* We take additional reference here. It will be put back by shrinker */
+	atomic_set(&huge_zero_refcount, 2);
+	preempt_enable();
+	return ACCESS_ONCE(huge_zero_pfn);
+}
+
+static void put_huge_zero_page(void)
+{
+	/*
+	 * Counter should never go to zero here. Only shrinker can put
+	 * last reference.
+	 */
+	BUG_ON(atomic_dec_and_test(&huge_zero_refcount));
+}
+
+static int shrink_huge_zero_page(struct shrinker *shrink,
+		struct shrink_control *sc)
+{
+	if (!sc->nr_to_scan)
+		/* we can free zero page only if last reference remains */
+		return atomic_read(&huge_zero_refcount) == 1 ? HPAGE_PMD_NR : 0;
+
+	if (atomic_cmpxchg(&huge_zero_refcount, 1, 0) == 1) {
+		unsigned long zero_pfn = xchg(&huge_zero_pfn, 0);
+		BUG_ON(zero_pfn == 0);
+		__free_page(__pfn_to_page(zero_pfn));
+	}
+
+	return 0;
+}
+
+static struct shrinker huge_zero_page_shrinker = {
+	.shrink = shrink_huge_zero_page,
+	.seeks = DEFAULT_SEEKS,
+};
+
 #ifdef CONFIG_SYSFS
 
 static ssize_t double_flag_show(struct kobject *kobj,
@@ -284,6 +359,20 @@ static ssize_t defrag_store(struct kobject *kobj,
 static struct kobj_attribute defrag_attr =
 	__ATTR(defrag, 0644, defrag_show, defrag_store);
 
+static ssize_t use_zero_page_show(struct kobject *kobj,
+		struct kobj_attribute *attr, char *buf)
+{
+	return single_flag_show(kobj, attr, buf,
+				TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG);
+}
+static ssize_t use_zero_page_store(struct kobject *kobj,
+		struct kobj_attribute *attr, const char *buf, size_t count)
+{
+	return single_flag_store(kobj, attr, buf, count,
+				 TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG);
+}
+static struct kobj_attribute use_zero_page_attr =
+	__ATTR(use_zero_page, 0644, use_zero_page_show, use_zero_page_store);
 #ifdef CONFIG_DEBUG_VM
 static ssize_t debug_cow_show(struct kobject *kobj,
 				struct kobj_attribute *attr, char *buf)
@@ -305,6 +394,7 @@ static struct kobj_attribute debug_cow_attr =
 static struct attribute *hugepage_attr[] = {
 	&enabled_attr.attr,
 	&defrag_attr.attr,
+	&use_zero_page_attr.attr,
 #ifdef CONFIG_DEBUG_VM
 	&debug_cow_attr.attr,
 #endif
@@ -550,6 +640,8 @@ static int __init hugepage_init(void)
 		goto out;
 	}
 
+	register_shrinker(&huge_zero_page_shrinker);
+
 	/*
 	 * By default disable transparent hugepages on smaller systems,
 	 * where the extra memory used could hurt more than TLB overhead
@@ -606,6 +698,15 @@ static inline pmd_t maybe_pmd_mkwrite(pmd_t pmd, struct vm_area_struct *vma)
 	return pmd;
 }
 
+static inline pmd_t mk_huge_pmd(struct page *page, struct vm_area_struct *vma)
+{
+	pmd_t entry;
+	entry = mk_pmd(page, vma->vm_page_prot);
+	entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
+	entry = pmd_mkhuge(entry);
+	return entry;
+}
+
 static int __do_huge_pmd_anonymous_page(struct mm_struct *mm,
 					struct vm_area_struct *vma,
 					unsigned long haddr, pmd_t *pmd,
@@ -629,9 +730,7 @@ static int __do_huge_pmd_anonymous_page(struct mm_struct *mm,
 		pte_free(mm, pgtable);
 	} else {
 		pmd_t entry;
-		entry = mk_pmd(page, vma->vm_page_prot);
-		entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
-		entry = pmd_mkhuge(entry);
+		entry = mk_huge_pmd(page, vma);
 		/*
 		 * The spinlocking to take the lru_lock inside
 		 * page_add_new_anon_rmap() acts as a full memory
@@ -671,6 +770,19 @@ static inline struct page *alloc_hugepage(int defrag)
 }
 #endif
 
+static void set_huge_zero_page(pgtable_t pgtable, struct mm_struct *mm,
+		struct vm_area_struct *vma, unsigned long haddr, pmd_t *pmd,
+		unsigned long zero_pfn)
+{
+	pmd_t entry;
+	entry = pfn_pmd(zero_pfn, vma->vm_page_prot);
+	entry = pmd_wrprotect(entry);
+	entry = pmd_mkhuge(entry);
+	set_pmd_at(mm, haddr, pmd, entry);
+	pgtable_trans_huge_deposit(mm, pgtable);
+	mm->nr_ptes++;
+}
+
 int do_huge_pmd_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
 			       unsigned long address, pmd_t *pmd,
 			       unsigned int flags)
@@ -684,6 +796,25 @@ int do_huge_pmd_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
 			return VM_FAULT_OOM;
 		if (unlikely(khugepaged_enter(vma)))
 			return VM_FAULT_OOM;
+		if (!(flags & FAULT_FLAG_WRITE) &&
+				transparent_hugepage_use_zero_page()) {
+			pgtable_t pgtable;
+			unsigned long zero_pfn;
+			pgtable = pte_alloc_one(mm, haddr);
+			if (unlikely(!pgtable))
+				return VM_FAULT_OOM;
+			zero_pfn = get_huge_zero_page();
+			if (unlikely(!zero_pfn)) {
+				pte_free(mm, pgtable);
+				count_vm_event(THP_FAULT_FALLBACK);
+				goto out;
+			}
+			spin_lock(&mm->page_table_lock);
+			set_huge_zero_page(pgtable, mm, vma, haddr, pmd,
+					zero_pfn);
+			spin_unlock(&mm->page_table_lock);
+			return 0;
+		}
 		page = alloc_hugepage_vma(transparent_hugepage_defrag(vma),
 					  vma, haddr, numa_node_id(), 0);
 		if (unlikely(!page)) {
@@ -710,7 +841,8 @@ out:
 	 * run pte_offset_map on the pmd, if an huge pmd could
 	 * materialize from under us from a different thread.
 	 */
-	if (unlikely(__pte_alloc(mm, vma, pmd, address)))
+	if (unlikely(pmd_none(*pmd)) &&
+	    unlikely(__pte_alloc(mm, vma, pmd, address)))
 		return VM_FAULT_OOM;
 	/* if an huge pmd materialized from under us just retry later */
 	if (unlikely(pmd_trans_huge(*pmd)))
@@ -725,6 +857,165 @@ out:
 	return handle_pte_fault(mm, vma, address, pte, pmd, flags);
 }
 
+#ifdef CONFIG_NUMA_BALANCING
+/*
+ * Handle a NUMA fault: check whether we should migrate and
+ * mark it accessible again.
+ */
+void do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
+			   unsigned long address, pmd_t *pmd,
+			   unsigned int flags, pmd_t entry)
+{
+	unsigned long haddr = address & HPAGE_PMD_MASK;
+	struct mem_cgroup *memcg = NULL;
+	struct page *new_page;
+	struct page *page = NULL;
+	int last_cpu;
+	int node = -1;
+
+	spin_lock(&mm->page_table_lock);
+	if (unlikely(!pmd_same(*pmd, entry)))
+		goto unlock;
+
+	if (unlikely(pmd_trans_splitting(entry))) {
+		spin_unlock(&mm->page_table_lock);
+		wait_split_huge_page(vma->anon_vma, pmd);
+		return;
+	}
+
+	page = pmd_page(entry);
+	if (page) {
+		int page_nid = page_to_nid(page);
+
+		VM_BUG_ON(!PageCompound(page) || !PageHead(page));
+		last_cpu = page_last_cpu(page);
+
+		get_page(page);
+		/*
+		 * Note that migrating pages shared by others is safe, since
+		 * get_user_pages() or GUP fast would have to fault this page
+		 * present before they could proceed, and we are holding the
+		 * pagetable lock here and are mindful of pmd races below.
+		 */
+		node = mpol_misplaced(page, vma, haddr);
+		if (node != -1 && node != page_nid)
+			goto migrate;
+	}
+
+fixup:
+	/* change back to regular protection */
+	entry = pmd_modify(entry, vma->vm_page_prot);
+	set_pmd_at(mm, haddr, pmd, entry);
+	update_mmu_cache_pmd(vma, address, &entry);
+
+unlock:
+	spin_unlock(&mm->page_table_lock);
+	if (page) {
+		task_numa_fault(page_to_nid(page), last_cpu, HPAGE_PMD_NR);
+		put_page(page);
+	}
+	return;
+
+migrate:
+	spin_unlock(&mm->page_table_lock);
+
+	lock_page(page);
+	spin_lock(&mm->page_table_lock);
+	if (unlikely(!pmd_same(*pmd, entry))) {
+		spin_unlock(&mm->page_table_lock);
+		unlock_page(page);
+		put_page(page);
+		return;
+	}
+	spin_unlock(&mm->page_table_lock);
+
+	new_page = alloc_pages_node(node,
+	    (GFP_TRANSHUGE | GFP_THISNODE) & ~__GFP_WAIT, HPAGE_PMD_ORDER);
+	if (!new_page)
+		goto alloc_fail;
+
+	if (isolate_lru_page(page)) {	/* Does an implicit get_page() */
+		put_page(new_page);
+		goto alloc_fail;
+	}
+
+	__set_page_locked(new_page);
+	SetPageSwapBacked(new_page);
+
+	/* anon mapping, we can simply copy page->mapping to the new page: */
+	new_page->mapping = page->mapping;
+	new_page->index = page->index;
+
+	migrate_page_copy(new_page, page);
+
+	WARN_ON(PageLRU(new_page));
+
+	spin_lock(&mm->page_table_lock);
+	if (unlikely(!pmd_same(*pmd, entry))) {
+		spin_unlock(&mm->page_table_lock);
+
+		/* Reverse changes made by migrate_page_copy() */
+		if (TestClearPageActive(new_page))
+			SetPageActive(page);
+		if (TestClearPageUnevictable(new_page))
+			SetPageUnevictable(page);
+		mlock_migrate_page(page, new_page);
+
+		unlock_page(new_page);
+		put_page(new_page);		/* Free it */
+
+		unlock_page(page);
+		putback_lru_page(page);
+		put_page(page);			/* Drop the local reference */
+		return;
+	}
+	/*
+	 * Traditional migration needs to prepare the memcg charge
+	 * transaction early to prevent the old page from being
+	 * uncharged when installing migration entries.  Here we can
+	 * save the potential rollback and start the charge transfer
+	 * only when migration is already known to end successfully.
+	 */
+	mem_cgroup_prepare_migration(page, new_page, &memcg);
+
+	entry = mk_pmd(new_page, vma->vm_page_prot);
+	entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
+	entry = pmd_mkhuge(entry);
+
+	page_add_new_anon_rmap(new_page, vma, haddr);
+
+	set_pmd_at(mm, haddr, pmd, entry);
+	update_mmu_cache_pmd(vma, address, &entry);
+	page_remove_rmap(page);
+	/*
+	 * Finish the charge transaction under the page table lock to
+	 * prevent split_huge_page() from dividing up the charge
+	 * before it's fully transferred to the new page.
+	 */
+	mem_cgroup_end_migration(memcg, page, new_page, true);
+	spin_unlock(&mm->page_table_lock);
+
+	task_numa_fault(node, last_cpu, HPAGE_PMD_NR);
+
+	unlock_page(new_page);
+	unlock_page(page);
+	put_page(page);			/* Drop the rmap reference */
+	put_page(page);			/* Drop the LRU isolation reference */
+	put_page(page);			/* Drop the local reference */
+	return;
+
+alloc_fail:
+	unlock_page(page);
+	spin_lock(&mm->page_table_lock);
+	if (unlikely(!pmd_same(*pmd, entry))) {
+		put_page(page);
+		page = NULL;
+		goto unlock;
+	}
+	goto fixup;
+}
+#endif
+
 int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
 		  pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long addr,
 		  struct vm_area_struct *vma)
@@ -748,6 +1039,24 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
 		pte_free(dst_mm, pgtable);
 		goto out_unlock;
 	}
+	/*
+	 * mm->page_table_lock is enough to be sure that huge zero pmd is not
+	 * under splitting since we don't split the page itself, only pmd to
+	 * a page table.
+	 */
+	if (is_huge_zero_pmd(pmd)) {
+		unsigned long zero_pfn;
+		/*
+		 * get_huge_zero_page() will never allocate a new page here,
+		 * since we already have a zero page to copy. It just takes a
+		 * reference.
+		 */
+		zero_pfn = get_huge_zero_page();
+		set_huge_zero_page(pgtable, dst_mm, vma, addr, dst_pmd,
+				zero_pfn);
+		ret = 0;
+		goto out_unlock;
+	}
 	if (unlikely(pmd_trans_splitting(pmd))) {
 		/* split huge page running from under us */
 		spin_unlock(&src_mm->page_table_lock);
@@ -777,6 +1086,92 @@ out:
 	return ret;
 }
 
+void huge_pmd_set_accessed(struct mm_struct *mm,
+			   struct vm_area_struct *vma,
+			   unsigned long address,
+			   pmd_t *pmd, pmd_t orig_pmd,
+			   int dirty)
+{
+	pmd_t entry;
+	unsigned long haddr;
+
+	spin_lock(&mm->page_table_lock);
+	if (unlikely(!pmd_same(*pmd, orig_pmd)))
+		goto unlock;
+
+	entry = pmd_mkyoung(orig_pmd);
+	haddr = address & HPAGE_PMD_MASK;
+	if (pmdp_set_access_flags(vma, haddr, pmd, entry, dirty))
+		update_mmu_cache_pmd(vma, address, pmd);
+
+unlock:
+	spin_unlock(&mm->page_table_lock);
+}
+
+static int do_huge_pmd_wp_zero_page_fallback(struct mm_struct *mm,
+		struct vm_area_struct *vma, unsigned long address,
+		pmd_t *pmd, unsigned long haddr)
+{
+	pgtable_t pgtable;
+	pmd_t _pmd;
+	struct page *page;
+	int i, ret = 0;
+	unsigned long mmun_start;	/* For mmu_notifiers */
+	unsigned long mmun_end;		/* For mmu_notifiers */
+
+	page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
+	if (!page) {
+		ret |= VM_FAULT_OOM;
+		goto out;
+	}
+
+	if (mem_cgroup_newpage_charge(page, mm, GFP_KERNEL)) {
+		put_page(page);
+		ret |= VM_FAULT_OOM;
+		goto out;
+	}
+
+	clear_user_highpage(page, address);
+	__SetPageUptodate(page);
+
+	mmun_start = haddr;
+	mmun_end   = haddr + HPAGE_PMD_SIZE;
+	mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
+
+	spin_lock(&mm->page_table_lock);
+	pmdp_clear_flush(vma, haddr, pmd);
+	/* leave pmd empty until pte is filled */
+
+	pgtable = pgtable_trans_huge_withdraw(mm);
+	pmd_populate(mm, &_pmd, pgtable);
+
+	for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) {
+		pte_t *pte, entry;
+		if (haddr == (address & PAGE_MASK)) {
+			entry = mk_pte(page, vma->vm_page_prot);
+			entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+			page_add_new_anon_rmap(page, vma, haddr);
+		} else {
+			entry = pfn_pte(my_zero_pfn(haddr), vma->vm_page_prot);
+			entry = pte_mkspecial(entry);
+		}
+		pte = pte_offset_map(&_pmd, haddr);
+		VM_BUG_ON(!pte_none(*pte));
+		set_pte_at(mm, haddr, pte, entry);
+		pte_unmap(pte);
+	}
+	smp_wmb(); /* make pte visible before pmd */
+	pmd_populate(mm, pmd, pgtable);
+	spin_unlock(&mm->page_table_lock);
+	put_huge_zero_page();
+
+	mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
+
+	ret |= VM_FAULT_WRITE;
+out:
+	return ret;
+}
+
 static int do_huge_pmd_wp_page_fallback(struct mm_struct *mm,
 					struct vm_area_struct *vma,
 					unsigned long address,
@@ -883,19 +1278,21 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
 			unsigned long address, pmd_t *pmd, pmd_t orig_pmd)
 {
 	int ret = 0;
-	struct page *page, *new_page;
+	struct page *page = NULL, *new_page;
 	unsigned long haddr;
 	unsigned long mmun_start;	/* For mmu_notifiers */
 	unsigned long mmun_end;		/* For mmu_notifiers */
 
 	VM_BUG_ON(!vma->anon_vma);
+	haddr = address & HPAGE_PMD_MASK;
+	if (is_huge_zero_pmd(orig_pmd))
+		goto alloc;
 	spin_lock(&mm->page_table_lock);
 	if (unlikely(!pmd_same(*pmd, orig_pmd)))
 		goto out_unlock;
 
 	page = pmd_page(orig_pmd);
 	VM_BUG_ON(!PageCompound(page) || !PageHead(page));
-	haddr = address & HPAGE_PMD_MASK;
 	if (page_mapcount(page) == 1) {
 		pmd_t entry;
 		entry = pmd_mkyoung(orig_pmd);
@@ -907,7 +1304,7 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
 	}
 	get_page(page);
 	spin_unlock(&mm->page_table_lock);
-
+alloc:
 	if (transparent_hugepage_enabled(vma) &&
 	    !transparent_hugepage_debug_cow())
 		new_page = alloc_hugepage_vma(transparent_hugepage_defrag(vma),
@@ -917,24 +1314,34 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
 
 	if (unlikely(!new_page)) {
 		count_vm_event(THP_FAULT_FALLBACK);
-		ret = do_huge_pmd_wp_page_fallback(mm, vma, address,
-						   pmd, orig_pmd, page, haddr);
-		if (ret & VM_FAULT_OOM)
-			split_huge_page(page);
-		put_page(page);
+		if (is_huge_zero_pmd(orig_pmd)) {
+			ret = do_huge_pmd_wp_zero_page_fallback(mm, vma,
+					address, pmd, haddr);
+		} else {
+			ret = do_huge_pmd_wp_page_fallback(mm, vma, address,
+					pmd, orig_pmd, page, haddr);
+			if (ret & VM_FAULT_OOM)
+				split_huge_page(page);
+			put_page(page);
+		}
 		goto out;
 	}
 	count_vm_event(THP_FAULT_ALLOC);
 
 	if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) {
 		put_page(new_page);
-		split_huge_page(page);
-		put_page(page);
+		if (page) {
+			split_huge_page(page);
+			put_page(page);
+		}
 		ret |= VM_FAULT_OOM;
 		goto out;
 	}
 
-	copy_user_huge_page(new_page, page, haddr, vma, HPAGE_PMD_NR);
+	if (is_huge_zero_pmd(orig_pmd))
+		clear_huge_page(new_page, haddr, HPAGE_PMD_NR);
+	else
+		copy_user_huge_page(new_page, page, haddr, vma, HPAGE_PMD_NR);
 	__SetPageUptodate(new_page);
 
 	mmun_start = haddr;
@@ -942,7 +1349,8 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
 	mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
 
 	spin_lock(&mm->page_table_lock);
-	put_page(page);
+	if (page)
+		put_page(page);
 	if (unlikely(!pmd_same(*pmd, orig_pmd))) {
 		spin_unlock(&mm->page_table_lock);
 		mem_cgroup_uncharge_page(new_page);
@@ -950,16 +1358,19 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
 		goto out_mn;
 	} else {
 		pmd_t entry;
-		VM_BUG_ON(!PageHead(page));
-		entry = mk_pmd(new_page, vma->vm_page_prot);
-		entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
-		entry = pmd_mkhuge(entry);
+		entry = mk_huge_pmd(new_page, vma);
 		pmdp_clear_flush(vma, haddr, pmd);
 		page_add_new_anon_rmap(new_page, vma, haddr);
 		set_pmd_at(mm, haddr, pmd, entry);
 		update_mmu_cache_pmd(vma, address, pmd);
-		page_remove_rmap(page);
-		put_page(page);
+		if (is_huge_zero_pmd(orig_pmd)) {
+			add_mm_counter(mm, MM_ANONPAGES, HPAGE_PMD_NR);
+			put_huge_zero_page();
+		} else {
+			VM_BUG_ON(!PageHead(page));
+			page_remove_rmap(page);
+			put_page(page);
+		}
 		ret |= VM_FAULT_WRITE;
 	}
 	spin_unlock(&mm->page_table_lock);
@@ -1028,15 +1439,21 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
 		pmd_t orig_pmd;
 		pgtable = pgtable_trans_huge_withdraw(tlb->mm);
 		orig_pmd = pmdp_get_and_clear(tlb->mm, addr, pmd);
-		page = pmd_page(orig_pmd);
 		tlb_remove_pmd_tlb_entry(tlb, pmd, addr);
-		page_remove_rmap(page);
-		VM_BUG_ON(page_mapcount(page) < 0);
-		add_mm_counter(tlb->mm, MM_ANONPAGES, -HPAGE_PMD_NR);
-		VM_BUG_ON(!PageHead(page));
-		tlb->mm->nr_ptes--;
-		spin_unlock(&tlb->mm->page_table_lock);
-		tlb_remove_page(tlb, page);
+		if (is_huge_zero_pmd(orig_pmd)) {
+			tlb->mm->nr_ptes--;
+			spin_unlock(&tlb->mm->page_table_lock);
+			put_huge_zero_page();
+		} else {
+			page = pmd_page(orig_pmd);
+			page_remove_rmap(page);
+			VM_BUG_ON(page_mapcount(page) < 0);
+			add_mm_counter(tlb->mm, MM_ANONPAGES, -HPAGE_PMD_NR);
+			VM_BUG_ON(!PageHead(page));
+			tlb->mm->nr_ptes--;
+			spin_unlock(&tlb->mm->page_table_lock);
+			tlb_remove_page(tlb, page);
+		}
 		pte_free(tlb->mm, pgtable);
 		ret = 1;
 	}
@@ -1108,6 +1525,8 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
 		pmd_t entry;
 		entry = pmdp_get_and_clear(mm, addr, pmd);
 		entry = pmd_modify(entry, newprot);
+		if (is_huge_zero_pmd(entry))
+			entry = pmd_wrprotect(entry);
 		set_pmd_at(mm, addr, pmd, entry);
 		spin_unlock(&vma->vm_mm->page_table_lock);
 		ret = 1;
@@ -1146,22 +1565,14 @@ pmd_t *page_check_address_pmd(struct page *page,
 			      unsigned long address,
 			      enum page_check_address_pmd_flag flag)
 {
-	pgd_t *pgd;
-	pud_t *pud;
 	pmd_t *pmd, *ret = NULL;
 
 	if (address & ~HPAGE_PMD_MASK)
 		goto out;
 
-	pgd = pgd_offset(mm, address);
-	if (!pgd_present(*pgd))
-		goto out;
-
-	pud = pud_offset(pgd, address);
-	if (!pud_present(*pud))
+	pmd = mm_find_pmd(mm, address);
+	if (!pmd)
 		goto out;
-
-	pmd = pmd_offset(pud, address);
 	if (pmd_none(*pmd))
 		goto out;
 	if (pmd_page(*pmd) != page)
@@ -1296,6 +1707,7 @@ static void __split_huge_page_refcount(struct page *page)
 		page_tail->mapping = page->mapping;
 
 		page_tail->index = page->index + i;
+		page_xchg_last_cpu(page, page_last_cpu(page_tail));
 
 		BUG_ON(!PageAnon(page_tail));
 		BUG_ON(!PageUptodate(page_tail));
@@ -1363,6 +1775,8 @@ static int __split_huge_page_map(struct page *page,
 				BUG_ON(page_mapcount(page) != 1);
 			if (!pmd_young(*pmd))
 				entry = pte_mkold(entry);
+			if (pmd_numa(vma, *pmd))
+				entry = pte_mknuma(vma, entry);
 			pte = pte_offset_map(&_pmd, haddr);
 			BUG_ON(!pte_none(*pte));
 			set_pte_at(mm, haddr, pte, entry);
@@ -1458,6 +1872,7 @@ int split_huge_page(struct page *page)
 	struct anon_vma *anon_vma;
 	int ret = 1;
 
+	BUG_ON(is_huge_zero_pfn(page_to_pfn(page)));
 	BUG_ON(!PageAnon(page));
 	anon_vma = page_lock_anon_vma(page);
 	if (!anon_vma)
@@ -1701,64 +2116,49 @@ static void release_pte_pages(pte_t *pte, pte_t *_pte)
 	}
 }
 
-static void release_all_pte_pages(pte_t *pte)
-{
-	release_pte_pages(pte, pte + HPAGE_PMD_NR);
-}
-
 static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
 					unsigned long address,
 					pte_t *pte)
 {
 	struct page *page;
 	pte_t *_pte;
-	int referenced = 0, isolated = 0, none = 0;
+	int referenced = 0, none = 0;
 	for (_pte = pte; _pte < pte+HPAGE_PMD_NR;
 	     _pte++, address += PAGE_SIZE) {
 		pte_t pteval = *_pte;
 		if (pte_none(pteval)) {
 			if (++none <= khugepaged_max_ptes_none)
 				continue;
-			else {
-				release_pte_pages(pte, _pte);
+			else
 				goto out;
-			}
 		}
-		if (!pte_present(pteval) || !pte_write(pteval)) {
-			release_pte_pages(pte, _pte);
+		if (!pte_present(pteval) || !pte_write(pteval))
 			goto out;
-		}
 		page = vm_normal_page(vma, address, pteval);
-		if (unlikely(!page)) {
-			release_pte_pages(pte, _pte);
+		if (unlikely(!page))
 			goto out;
-		}
+
 		VM_BUG_ON(PageCompound(page));
 		BUG_ON(!PageAnon(page));
 		VM_BUG_ON(!PageSwapBacked(page));
 
 		/* cannot use mapcount: can't collapse if there's a gup pin */
-		if (page_count(page) != 1) {
-			release_pte_pages(pte, _pte);
+		if (page_count(page) != 1)
 			goto out;
-		}
 		/*
 		 * We can do it before isolate_lru_page because the
 		 * page can't be freed from under us. NOTE: PG_lock
 		 * is needed to serialize against split_huge_page
 		 * when invoked from the VM.
 		 */
-		if (!trylock_page(page)) {
-			release_pte_pages(pte, _pte);
+		if (!trylock_page(page))
 			goto out;
-		}
 		/*
 		 * Isolate the page to avoid collapsing an hugepage
 		 * currently in use by the VM.
 		 */
 		if (isolate_lru_page(page)) {
 			unlock_page(page);
-			release_pte_pages(pte, _pte);
 			goto out;
 		}
 		/* 0 stands for page_is_file_cache(page) == false */
@@ -1771,12 +2171,11 @@ static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
 		    mmu_notifier_test_young(vma->vm_mm, address))
 			referenced = 1;
 	}
-	if (unlikely(!referenced))
-		release_all_pte_pages(pte);
-	else
-		isolated = 1;
+	if (likely(referenced))
+		return 1;
 out:
-	return isolated;
+	release_pte_pages(pte, _pte);
+	return 0;
 }
 
 static void __collapse_huge_page_copy(pte_t *pte, struct page *page,
@@ -1918,14 +2317,26 @@ static struct page
 }
 #endif
 
+static bool hugepage_vma_check(struct vm_area_struct *vma)
+{
+	if ((!(vma->vm_flags & VM_HUGEPAGE) && !khugepaged_always()) ||
+	    (vma->vm_flags & VM_NOHUGEPAGE))
+		return false;
+
+	if (!vma->anon_vma || vma->vm_ops)
+		return false;
+	if (is_vma_temporary_stack(vma))
+		return false;
+	VM_BUG_ON(vma->vm_flags & VM_NO_THP);
+	return true;
+}
+
 static void collapse_huge_page(struct mm_struct *mm,
 				   unsigned long address,
 				   struct page **hpage,
 				   struct vm_area_struct *vma,
 				   int node)
 {
-	pgd_t *pgd;
-	pud_t *pud;
 	pmd_t *pmd, _pmd;
 	pte_t *pte;
 	pgtable_t pgtable;
@@ -1960,28 +2371,12 @@ static void collapse_huge_page(struct mm_struct *mm,
 	hend = vma->vm_end & HPAGE_PMD_MASK;
 	if (address < hstart || address + HPAGE_PMD_SIZE > hend)
 		goto out;
-
-	if ((!(vma->vm_flags & VM_HUGEPAGE) && !khugepaged_always()) ||
-	    (vma->vm_flags & VM_NOHUGEPAGE))
-		goto out;
-
-	if (!vma->anon_vma || vma->vm_ops)
-		goto out;
-	if (is_vma_temporary_stack(vma))
-		goto out;
-	VM_BUG_ON(vma->vm_flags & VM_NO_THP);
-
-	pgd = pgd_offset(mm, address);
-	if (!pgd_present(*pgd))
+	if (!hugepage_vma_check(vma))
 		goto out;
-
-	pud = pud_offset(pgd, address);
-	if (!pud_present(*pud))
+	pmd = mm_find_pmd(mm, address);
+	if (!pmd)
 		goto out;
-
-	pmd = pmd_offset(pud, address);
-	/* pmd can't go away or become huge under us */
-	if (!pmd_present(*pmd) || pmd_trans_huge(*pmd))
+	if (pmd_trans_huge(*pmd))
 		goto out;
 
 	anon_vma_lock(vma->anon_vma);
@@ -2028,9 +2423,7 @@ static void collapse_huge_page(struct mm_struct *mm,
 	__SetPageUptodate(new_page);
 	pgtable = pmd_pgtable(_pmd);
 
-	_pmd = mk_pmd(new_page, vma->vm_page_prot);
-	_pmd = maybe_pmd_mkwrite(pmd_mkdirty(_pmd), vma);
-	_pmd = pmd_mkhuge(_pmd);
+	_pmd = mk_huge_pmd(new_page, vma);
 
 	/*
 	 * spin_lock() below is not the equivalent of smp_wmb(), so
@@ -2064,8 +2457,6 @@ static int khugepaged_scan_pmd(struct mm_struct *mm,
 			       unsigned long address,
 			       struct page **hpage)
 {
-	pgd_t *pgd;
-	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte, *_pte;
 	int ret = 0, referenced = 0, none = 0;
@@ -2076,16 +2467,10 @@ static int khugepaged_scan_pmd(struct mm_struct *mm,
 
 	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
 
-	pgd = pgd_offset(mm, address);
-	if (!pgd_present(*pgd))
+	pmd = mm_find_pmd(mm, address);
+	if (!pmd)
 		goto out;
-
-	pud = pud_offset(pgd, address);
-	if (!pud_present(*pud))
-		goto out;
-
-	pmd = pmd_offset(pud, address);
-	if (!pmd_present(*pmd) || pmd_trans_huge(*pmd))
+	if (pmd_trans_huge(*pmd))
 		goto out;
 
 	pte = pte_offset_map_lock(mm, pmd, address, &ptl);
@@ -2193,20 +2578,11 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages,
 			progress++;
 			break;
 		}
-
-		if ((!(vma->vm_flags & VM_HUGEPAGE) &&
-		     !khugepaged_always()) ||
-		    (vma->vm_flags & VM_NOHUGEPAGE)) {
-		skip:
+		if (!hugepage_vma_check(vma)) {
+skip:
 			progress++;
 			continue;
 		}
-		if (!vma->anon_vma || vma->vm_ops)
-			goto skip;
-		if (is_vma_temporary_stack(vma))
-			goto skip;
-		VM_BUG_ON(vma->vm_flags & VM_NO_THP);
-
 		hstart = (vma->vm_start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK;
 		hend = vma->vm_end & HPAGE_PMD_MASK;
 		if (hstart >= hend)
@@ -2356,19 +2732,65 @@ static int khugepaged(void *none)
 	return 0;
 }
 
-void __split_huge_page_pmd(struct mm_struct *mm, pmd_t *pmd)
+static void __split_huge_zero_page_pmd(struct vm_area_struct *vma,
+		unsigned long haddr, pmd_t *pmd)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	pgtable_t pgtable;
+	pmd_t _pmd;
+	int i;
+
+	pmdp_clear_flush(vma, haddr, pmd);
+	/* leave pmd empty until pte is filled */
+
+	pgtable = pgtable_trans_huge_withdraw(mm);
+	pmd_populate(mm, &_pmd, pgtable);
+
+	for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) {
+		pte_t *pte, entry;
+		entry = pfn_pte(my_zero_pfn(haddr), vma->vm_page_prot);
+		entry = pte_mkspecial(entry);
+		pte = pte_offset_map(&_pmd, haddr);
+		VM_BUG_ON(!pte_none(*pte));
+		set_pte_at(mm, haddr, pte, entry);
+		pte_unmap(pte);
+	}
+	smp_wmb(); /* make pte visible before pmd */
+	pmd_populate(mm, pmd, pgtable);
+	put_huge_zero_page();
+}
+
+void __split_huge_page_pmd(struct vm_area_struct *vma, unsigned long address,
+		pmd_t *pmd)
 {
 	struct page *page;
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long haddr = address & HPAGE_PMD_MASK;
+	unsigned long mmun_start;	/* For mmu_notifiers */
+	unsigned long mmun_end;		/* For mmu_notifiers */
+
+	BUG_ON(vma->vm_start > haddr || vma->vm_end < haddr + HPAGE_PMD_SIZE);
 
+	mmun_start = haddr;
+	mmun_end   = haddr + HPAGE_PMD_SIZE;
+	mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
 	spin_lock(&mm->page_table_lock);
 	if (unlikely(!pmd_trans_huge(*pmd))) {
 		spin_unlock(&mm->page_table_lock);
+		mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
+		return;
+	}
+	if (is_huge_zero_pmd(*pmd)) {
+		__split_huge_zero_page_pmd(vma, haddr, pmd);
+		spin_unlock(&mm->page_table_lock);
+		mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
 		return;
 	}
 	page = pmd_page(*pmd);
 	VM_BUG_ON(!page_count(page));
 	get_page(page);
 	spin_unlock(&mm->page_table_lock);
+	mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
 
 	split_huge_page(page);
 
@@ -2376,31 +2798,31 @@ void __split_huge_page_pmd(struct mm_struct *mm, pmd_t *pmd)
 	BUG_ON(pmd_trans_huge(*pmd));
 }
 
+void split_huge_page_pmd_mm(struct mm_struct *mm, unsigned long address,
+		pmd_t *pmd)
+{
+	struct vm_area_struct *vma;
+
+	vma = find_vma(mm, address);
+	BUG_ON(vma == NULL);
+	split_huge_page_pmd(vma, address, pmd);
+}
+
 static void split_huge_page_address(struct mm_struct *mm,
 				    unsigned long address)
 {
-	pgd_t *pgd;
-	pud_t *pud;
 	pmd_t *pmd;
 
 	VM_BUG_ON(!(address & ~HPAGE_PMD_MASK));
 
-	pgd = pgd_offset(mm, address);
-	if (!pgd_present(*pgd))
-		return;
-
-	pud = pud_offset(pgd, address);
-	if (!pud_present(*pud))
-		return;
-
-	pmd = pmd_offset(pud, address);
-	if (!pmd_present(*pmd))
+	pmd = mm_find_pmd(mm, address);
+	if (!pmd)
 		return;
 	/*
 	 * Caller holds the mmap_sem write mode, so a huge pmd cannot
 	 * materialize from under us.
 	 */
-	split_huge_page_pmd(mm, pmd);
+	split_huge_page_pmd_mm(mm, address, pmd);
 }
 
 void __vma_adjust_trans_huge(struct vm_area_struct *vma,
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 59a0059..8518efc 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1057,7 +1057,7 @@ static void return_unused_surplus_pages(struct hstate *h,
 	 * on-line nodes with memory and will handle the hstate accounting.
 	 */
 	while (nr_pages--) {
-		if (!free_pool_huge_page(h, &node_states[N_HIGH_MEMORY], 1))
+		if (!free_pool_huge_page(h, &node_states[N_MEMORY], 1))
 			break;
 	}
 }
@@ -1180,14 +1180,14 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma,
 int __weak alloc_bootmem_huge_page(struct hstate *h)
 {
 	struct huge_bootmem_page *m;
-	int nr_nodes = nodes_weight(node_states[N_HIGH_MEMORY]);
+	int nr_nodes = nodes_weight(node_states[N_MEMORY]);
 
 	while (nr_nodes) {
 		void *addr;
 
 		addr = __alloc_bootmem_node_nopanic(
 				NODE_DATA(hstate_next_node_to_alloc(h,
-						&node_states[N_HIGH_MEMORY])),
+						&node_states[N_MEMORY])),
 				huge_page_size(h), huge_page_size(h), 0);
 
 		if (addr) {
@@ -1259,7 +1259,7 @@ static void __init hugetlb_hstate_alloc_pages(struct hstate *h)
 			if (!alloc_bootmem_huge_page(h))
 				break;
 		} else if (!alloc_fresh_huge_page(h,
-					 &node_states[N_HIGH_MEMORY]))
+					 &node_states[N_MEMORY]))
 			break;
 	}
 	h->max_huge_pages = i;
@@ -1527,7 +1527,7 @@ static ssize_t nr_hugepages_store_common(bool obey_mempolicy,
 		if (!(obey_mempolicy &&
 				init_nodemask_of_mempolicy(nodes_allowed))) {
 			NODEMASK_FREE(nodes_allowed);
-			nodes_allowed = &node_states[N_HIGH_MEMORY];
+			nodes_allowed = &node_states[N_MEMORY];
 		}
 	} else if (nodes_allowed) {
 		/*
@@ -1537,11 +1537,11 @@ static ssize_t nr_hugepages_store_common(bool obey_mempolicy,
 		count += h->nr_huge_pages - h->nr_huge_pages_node[nid];
 		init_nodemask_of_node(nodes_allowed, nid);
 	} else
-		nodes_allowed = &node_states[N_HIGH_MEMORY];
+		nodes_allowed = &node_states[N_MEMORY];
 
 	h->max_huge_pages = set_max_huge_pages(h, count, nodes_allowed);
 
-	if (nodes_allowed != &node_states[N_HIGH_MEMORY])
+	if (nodes_allowed != &node_states[N_MEMORY])
 		NODEMASK_FREE(nodes_allowed);
 
 	return len;
@@ -1800,7 +1800,7 @@ static void hugetlb_unregister_all_nodes(void)
 	 * remove hstate attributes from any nodes that have them.
 	 */
 	for (nid = 0; nid < nr_node_ids; nid++)
-		hugetlb_unregister_node(&node_devices[nid]);
+		hugetlb_unregister_node(node_devices[nid]);
 }
 
 /*
@@ -1844,8 +1844,8 @@ static void hugetlb_register_all_nodes(void)
 {
 	int nid;
 
-	for_each_node_state(nid, N_HIGH_MEMORY) {
-		struct node *node = &node_devices[nid];
+	for_each_node_state(nid, N_MEMORY) {
+		struct node *node = node_devices[nid];
 		if (node->dev.id == nid)
 			hugetlb_register_node(node);
 	}
@@ -1939,8 +1939,8 @@ void __init hugetlb_add_hstate(unsigned order)
 	for (i = 0; i < MAX_NUMNODES; ++i)
 		INIT_LIST_HEAD(&h->hugepage_freelists[i]);
 	INIT_LIST_HEAD(&h->hugepage_activelist);
-	h->next_nid_to_alloc = first_node(node_states[N_HIGH_MEMORY]);
-	h->next_nid_to_free = first_node(node_states[N_HIGH_MEMORY]);
+	h->next_nid_to_alloc = first_node(node_states[N_MEMORY]);
+	h->next_nid_to_free = first_node(node_states[N_MEMORY]);
 	snprintf(h->name, HSTATE_NAME_LEN, "hugepages-%lukB",
 					huge_page_size(h)/1024);
 	/*
@@ -2035,11 +2035,11 @@ static int hugetlb_sysctl_handler_common(bool obey_mempolicy,
 		if (!(obey_mempolicy &&
 			       init_nodemask_of_mempolicy(nodes_allowed))) {
 			NODEMASK_FREE(nodes_allowed);
-			nodes_allowed = &node_states[N_HIGH_MEMORY];
+			nodes_allowed = &node_states[N_MEMORY];
 		}
 		h->max_huge_pages = set_max_huge_pages(h, tmp, nodes_allowed);
 
-		if (nodes_allowed != &node_states[N_HIGH_MEMORY])
+		if (nodes_allowed != &node_states[N_MEMORY])
 			NODEMASK_FREE(nodes_allowed);
 	}
 out:
@@ -3014,7 +3014,7 @@ same_page:
 	return i ? i : -EFAULT;
 }
 
-void hugetlb_change_protection(struct vm_area_struct *vma,
+unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
 		unsigned long address, unsigned long end, pgprot_t newprot)
 {
 	struct mm_struct *mm = vma->vm_mm;
@@ -3022,6 +3022,7 @@ void hugetlb_change_protection(struct vm_area_struct *vma,
 	pte_t *ptep;
 	pte_t pte;
 	struct hstate *h = hstate_vma(vma);
+	unsigned long pages = 0;
 
 	BUG_ON(address >= end);
 	flush_cache_range(vma, address, end);
@@ -3032,12 +3033,15 @@ void hugetlb_change_protection(struct vm_area_struct *vma,
 		ptep = huge_pte_offset(mm, address);
 		if (!ptep)
 			continue;
-		if (huge_pmd_unshare(mm, &address, ptep))
+		if (huge_pmd_unshare(mm, &address, ptep)) {
+			pages++;
 			continue;
+		}
 		if (!huge_pte_none(huge_ptep_get(ptep))) {
 			pte = huge_ptep_get_and_clear(mm, address, ptep);
 			pte = pte_mkhuge(pte_modify(pte, newprot));
 			set_huge_pte_at(mm, address, ptep, pte);
+			pages++;
 		}
 	}
 	spin_unlock(&mm->page_table_lock);
@@ -3049,6 +3053,8 @@ void hugetlb_change_protection(struct vm_area_struct *vma,
 	 */
 	flush_tlb_range(vma, start, end);
 	mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex);
+
+	return pages << h->order;
 }
 
 int hugetlb_reserve_pages(struct inode *inode,
diff --git a/mm/hugetlb_cgroup.c b/mm/hugetlb_cgroup.c
index a3f358f..b5bde7a 100644
--- a/mm/hugetlb_cgroup.c
+++ b/mm/hugetlb_cgroup.c
@@ -77,7 +77,7 @@ static inline bool hugetlb_cgroup_have_usage(struct cgroup *cg)
 	return false;
 }
 
-static struct cgroup_subsys_state *hugetlb_cgroup_create(struct cgroup *cgroup)
+static struct cgroup_subsys_state *hugetlb_cgroup_css_alloc(struct cgroup *cgroup)
 {
 	int idx;
 	struct cgroup *parent_cgroup;
@@ -101,7 +101,7 @@ static struct cgroup_subsys_state *hugetlb_cgroup_create(struct cgroup *cgroup)
 	return &h_cgroup->css;
 }
 
-static void hugetlb_cgroup_destroy(struct cgroup *cgroup)
+static void hugetlb_cgroup_css_free(struct cgroup *cgroup)
 {
 	struct hugetlb_cgroup *h_cgroup;
 
@@ -155,18 +155,13 @@ out:
  * Force the hugetlb cgroup to empty the hugetlb resources by moving them to
  * the parent cgroup.
  */
-static int hugetlb_cgroup_pre_destroy(struct cgroup *cgroup)
+static void hugetlb_cgroup_css_offline(struct cgroup *cgroup)
 {
 	struct hstate *h;
 	struct page *page;
-	int ret = 0, idx = 0;
+	int idx = 0;
 
 	do {
-		if (cgroup_task_count(cgroup) ||
-		    !list_empty(&cgroup->children)) {
-			ret = -EBUSY;
-			goto out;
-		}
 		for_each_hstate(h) {
 			spin_lock(&hugetlb_lock);
 			list_for_each_entry(page, &h->hugepage_activelist, lru)
@@ -177,8 +172,6 @@ static int hugetlb_cgroup_pre_destroy(struct cgroup *cgroup)
 		}
 		cond_resched();
 	} while (hugetlb_cgroup_have_usage(cgroup));
-out:
-	return ret;
 }
 
 int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages,
@@ -411,8 +404,8 @@ void hugetlb_cgroup_migrate(struct page *oldhpage, struct page *newhpage)
 
 struct cgroup_subsys hugetlb_subsys = {
 	.name = "hugetlb",
-	.create     = hugetlb_cgroup_create,
-	.pre_destroy = hugetlb_cgroup_pre_destroy,
-	.destroy    = hugetlb_cgroup_destroy,
-	.subsys_id  = hugetlb_subsys_id,
+	.css_alloc	= hugetlb_cgroup_css_alloc,
+	.css_offline	= hugetlb_cgroup_css_offline,
+	.css_free	= hugetlb_cgroup_css_free,
+	.subsys_id	= hugetlb_subsys_id,
 };
diff --git a/mm/internal.h b/mm/internal.h
index a4fa284..8228054 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -12,6 +12,7 @@
 #define __MM_INTERNAL_H
 
 #include <linux/mm.h>
+#include <linux/rmap.h>
 
 void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
 		unsigned long floor, unsigned long ceiling);
@@ -92,6 +93,11 @@ extern int isolate_lru_page(struct page *page);
 extern void putback_lru_page(struct page *page);
 
 /*
+ * in mm/rmap.c:
+ */
+extern pmd_t *mm_find_pmd(struct mm_struct *mm, unsigned long address);
+
+/*
  * in mm/page_alloc.c
  */
 extern void __free_pages_bootmem(struct page *page, unsigned int order);
@@ -212,11 +218,12 @@ static inline void mlock_migrate_page(struct page *newpage, struct page *page)
 {
 	if (TestClearPageMlocked(page)) {
 		unsigned long flags;
+		int nr_pages = hpage_nr_pages(page);
 
 		local_irq_save(flags);
-		__dec_zone_page_state(page, NR_MLOCK);
+		__mod_zone_page_state(page_zone(page), NR_MLOCK, -nr_pages);
 		SetPageMlocked(newpage);
-		__inc_zone_page_state(newpage, NR_MLOCK);
+		__mod_zone_page_state(page_zone(newpage), NR_MLOCK, nr_pages);
 		local_irq_restore(flags);
 	}
 }
@@ -367,4 +374,51 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
 #define ALLOC_CPUSET		0x40 /* check for correct cpuset */
 #define ALLOC_CMA		0x80 /* allow allocations from CMA areas */
 
+/*
+ * Unnecessary readahead harms performance, especially for SSD devices, where
+ * large reads are significantly more expensive than small ones.
+ * These implements simple swap random access detection. In swap page fault: if
+ * the page is found in swapcache, decrease a counter in the vma, otherwise we
+ * need to perform sync swapin and the counter is increased.  Optionally swapin
+ * will perform readahead if the counter is below a threshold.
+ */
+#ifdef CONFIG_SWAP
+#define SWAPRA_MISS_THRESHOLD  (100)
+#define SWAPRA_MAX_MISS ((SWAPRA_MISS_THRESHOLD) * 10)
+static inline void swap_cache_hit(struct vm_area_struct *vma)
+{
+	if (vma && vma->anon_vma)
+		atomic_dec_if_positive(&vma->anon_vma->swapra_miss);
+}
+
+static inline void swap_cache_miss(struct vm_area_struct *vma)
+{
+	if (!vma || !vma->anon_vma)
+		return;
+	if (atomic_read(&vma->anon_vma->swapra_miss) < SWAPRA_MAX_MISS)
+		atomic_inc(&vma->anon_vma->swapra_miss);
+}
+
+static inline int swap_cache_skip_readahead(struct vm_area_struct *vma)
+{
+	if (!vma || !vma->anon_vma)
+		return 0;
+	return atomic_read(&vma->anon_vma->swapra_miss) >
+		SWAPRA_MISS_THRESHOLD;
+}
+#else
+static inline void swap_cache_hit(struct vm_area_struct *vma)
+{
+}
+
+static inline void swap_cache_miss(struct vm_area_struct *vma)
+{
+}
+
+static inline int swap_cache_skip_readahead(struct vm_area_struct *vma)
+{
+	return 0;
+}
+#endif	/* CONFIG_SWAP */
+
 #endif	/* __MM_INTERNAL_H */
diff --git a/mm/ksm.c b/mm/ksm.c
index ae539f0..382d930 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -778,8 +778,6 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
 			struct page *kpage, pte_t orig_pte)
 {
 	struct mm_struct *mm = vma->vm_mm;
-	pgd_t *pgd;
-	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *ptep;
 	spinlock_t *ptl;
@@ -792,18 +790,10 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
 	if (addr == -EFAULT)
 		goto out;
 
-	pgd = pgd_offset(mm, addr);
-	if (!pgd_present(*pgd))
+	pmd = mm_find_pmd(mm, addr);
+	if (!pmd)
 		goto out;
-
-	pud = pud_offset(pgd, addr);
-	if (!pud_present(*pud))
-		goto out;
-
-	pmd = pmd_offset(pud, addr);
 	BUG_ON(pmd_trans_huge(*pmd));
-	if (!pmd_present(*pmd))
-		goto out;
 
 	mmun_start = addr;
 	mmun_end   = addr + PAGE_SIZE;
@@ -1929,12 +1919,9 @@ static ssize_t run_store(struct kobject *kobj, struct kobj_attribute *attr,
 	if (ksm_run != flags) {
 		ksm_run = flags;
 		if (flags & KSM_RUN_UNMERGE) {
-			int oom_score_adj;
-
-			oom_score_adj = test_set_oom_score_adj(OOM_SCORE_ADJ_MAX);
+			set_current_oom_origin();
 			err = unmerge_and_remove_all_rmap_items();
-			compare_swap_oom_score_adj(OOM_SCORE_ADJ_MAX,
-								oom_score_adj);
+			clear_current_oom_origin();
 			if (err) {
 				ksm_run = KSM_RUN_STOP;
 				count = err;
diff --git a/mm/memblock.c b/mm/memblock.c
index 6259055..10ea908 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -889,6 +889,11 @@ int __init memblock_is_reserved(phys_addr_t addr)
 
 int __init_memblock memblock_is_memory(phys_addr_t addr)
 {
+
+	if (unlikely(addr < memblock_start_of_DRAM() ||
+		addr >= memblock_end_of_DRAM()))
+		return 0;
+
 	return memblock_search(&memblock.memory, addr) != -1;
 }
 
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index dd39ba0..f3009b4 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -10,6 +10,10 @@
  * Copyright (C) 2009 Nokia Corporation
  * Author: Kirill A. Shutemov
  *
+ * Kernel Memory Controller
+ * Copyright (C) 2012 Parallels Inc. and Google Inc.
+ * Authors: Glauber Costa and Suleiman Souhlal
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -59,6 +63,8 @@
 #include <trace/events/vmscan.h>
 
 struct cgroup_subsys mem_cgroup_subsys __read_mostly;
+EXPORT_SYMBOL(mem_cgroup_subsys);
+
 #define MEM_CGROUP_RECLAIM_RETRIES	5
 static struct mem_cgroup *root_mem_cgroup __read_mostly;
 
@@ -266,6 +272,10 @@ struct mem_cgroup {
 	};
 
 	/*
+	 * the counter to account for kernel memory usage.
+	 */
+	struct res_counter kmem;
+	/*
 	 * Per cgroup active and inactive list, similar to the
 	 * per zone LRU lists.
 	 */
@@ -280,6 +290,7 @@ struct mem_cgroup {
 	 * Should the accounting and control be hierarchical, per subtree?
 	 */
 	bool use_hierarchy;
+	unsigned long kmem_account_flags; /* See KMEM_ACCOUNTED_*, below */
 
 	bool		oom_lock;
 	atomic_t	under_oom;
@@ -330,8 +341,61 @@ struct mem_cgroup {
 #if defined(CONFIG_MEMCG_KMEM) && defined(CONFIG_INET)
 	struct tcp_memcontrol tcp_mem;
 #endif
+#if defined(CONFIG_MEMCG_KMEM)
+	/* analogous to slab_common's slab_caches list. per-memcg */
+	struct list_head memcg_slab_caches;
+	/* Not a spinlock, we can take a lot of time walking the list */
+	struct mutex slab_caches_mutex;
+        /* Index in the kmem_cache->memcg_params->memcg_caches array */
+	int kmemcg_id;
+#endif
+};
+
+/* internal only representation about the status of kmem accounting. */
+enum {
+	KMEM_ACCOUNTED_ACTIVE = 0, /* accounted by this cgroup itself */
+	KMEM_ACCOUNTED_ACTIVATED, /* static key enabled. */
+	KMEM_ACCOUNTED_DEAD, /* dead memcg with pending kmem charges */
 };
 
+/* We account when limit is on, but only after call sites are patched */
+#define KMEM_ACCOUNTED_MASK \
+		((1 << KMEM_ACCOUNTED_ACTIVE) | (1 << KMEM_ACCOUNTED_ACTIVATED))
+
+#ifdef CONFIG_MEMCG_KMEM
+static inline void memcg_kmem_set_active(struct mem_cgroup *memcg)
+{
+	set_bit(KMEM_ACCOUNTED_ACTIVE, &memcg->kmem_account_flags);
+}
+
+static bool memcg_kmem_is_active(struct mem_cgroup *memcg)
+{
+	return test_bit(KMEM_ACCOUNTED_ACTIVE, &memcg->kmem_account_flags);
+}
+
+static void memcg_kmem_set_activated(struct mem_cgroup *memcg)
+{
+	set_bit(KMEM_ACCOUNTED_ACTIVATED, &memcg->kmem_account_flags);
+}
+
+static void memcg_kmem_clear_activated(struct mem_cgroup *memcg)
+{
+	clear_bit(KMEM_ACCOUNTED_ACTIVATED, &memcg->kmem_account_flags);
+}
+
+static void memcg_kmem_mark_dead(struct mem_cgroup *memcg)
+{
+	if (test_bit(KMEM_ACCOUNTED_ACTIVE, &memcg->kmem_account_flags))
+		set_bit(KMEM_ACCOUNTED_DEAD, &memcg->kmem_account_flags);
+}
+
+static bool memcg_kmem_test_and_clear_dead(struct mem_cgroup *memcg)
+{
+	return test_and_clear_bit(KMEM_ACCOUNTED_DEAD,
+				  &memcg->kmem_account_flags);
+}
+#endif
+
 /* Stuffs for move charges at task migration. */
 /*
  * Types of charges to be moved. "move_charge_at_immitgrate" is treated as a
@@ -386,9 +450,13 @@ enum charge_type {
 };
 
 /* for encoding cft->private value on file */
-#define _MEM			(0)
-#define _MEMSWAP		(1)
-#define _OOM_TYPE		(2)
+enum res_type {
+	_MEM,
+	_MEMSWAP,
+	_OOM_TYPE,
+	_KMEM,
+};
+
 #define MEMFILE_PRIVATE(x, val)	((x) << 16 | (val))
 #define MEMFILE_TYPE(val)	((val) >> 16 & 0xffff)
 #define MEMFILE_ATTR(val)	((val) & 0xffff)
@@ -485,6 +553,75 @@ static void disarm_sock_keys(struct mem_cgroup *memcg)
 }
 #endif
 
+#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 current size of the caches array is stored in
+ * memcg_limited_groups_array_size.  It will double each time we have to
+ * increase it.
+ */
+static DEFINE_IDA(kmem_limited_groups);
+int memcg_limited_groups_array_size;
+
+/*
+ * MIN_SIZE is different than 1, because we would like to avoid going through
+ * the alloc/free process all the time. In a small machine, 4 kmem-limited
+ * 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
+ * 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
+ * increase ours as well if it increases.
+ */
+#define MEMCG_CACHES_MIN_SIZE 4
+#define MEMCG_CACHES_MAX_SIZE 65535
+
+/*
+ * A lot of the calls to the cache allocation functions are expected to be
+ * inlined by the compiler. Since the calls to memcg_kmem_get_cache are
+ * conditional to this static branch, we'll have to allow modules that does
+ * kmem_cache_alloc and the such to see this symbol as well
+ */
+struct static_key memcg_kmem_enabled_key;
+EXPORT_SYMBOL(memcg_kmem_enabled_key);
+
+static void disarm_kmem_keys(struct mem_cgroup *memcg)
+{
+	if (memcg_kmem_is_active(memcg)) {
+		static_key_slow_dec(&memcg_kmem_enabled_key);
+		ida_simple_remove(&kmem_limited_groups, memcg->kmemcg_id);
+	}
+	/*
+	 * This check can't live in kmem destruction function,
+	 * since the charges will outlive the cgroup
+	 */
+	WARN_ON(res_counter_read_u64(&memcg->kmem, RES_USAGE) != 0);
+}
+#else
+static void disarm_kmem_keys(struct mem_cgroup *memcg)
+{
+}
+#endif /* CONFIG_MEMCG_KMEM */
+
+static void disarm_static_keys(struct mem_cgroup *memcg)
+{
+	disarm_sock_keys(memcg);
+	disarm_kmem_keys(memcg);
+}
+
 static void drain_all_stock_async(struct mem_cgroup *memcg);
 
 static struct mem_cgroup_per_zone *
@@ -800,7 +937,7 @@ static unsigned long mem_cgroup_nr_lru_pages(struct mem_cgroup *memcg,
 	int nid;
 	u64 total = 0;
 
-	for_each_node_state(nid, N_HIGH_MEMORY)
+	for_each_node_state(nid, N_MEMORY)
 		total += mem_cgroup_node_nr_lru_pages(memcg, nid, lru_mask);
 	return total;
 }
@@ -1015,13 +1152,10 @@ void mem_cgroup_iter_break(struct mem_cgroup *root,
 	     iter != NULL;				\
 	     iter = mem_cgroup_iter(NULL, iter, NULL))
 
-void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx)
+void __mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx)
 {
 	struct mem_cgroup *memcg;
 
-	if (!mm)
-		return;
-
 	rcu_read_lock();
 	memcg = mem_cgroup_from_task(rcu_dereference(mm->owner));
 	if (unlikely(!memcg))
@@ -1040,7 +1174,7 @@ void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx)
 out:
 	rcu_read_unlock();
 }
-EXPORT_SYMBOL(mem_cgroup_count_vm_event);
+EXPORT_SYMBOL(__mem_cgroup_count_vm_event);
 
 /**
  * mem_cgroup_zone_lruvec - get the lru list vector for a zone and memcg
@@ -1454,6 +1588,10 @@ done:
 		res_counter_read_u64(&memcg->memsw, RES_USAGE) >> 10,
 		res_counter_read_u64(&memcg->memsw, RES_LIMIT) >> 10,
 		res_counter_read_u64(&memcg->memsw, RES_FAILCNT));
+	printk(KERN_INFO "kmem: usage %llukB, limit %llukB, failcnt %llu\n",
+		res_counter_read_u64(&memcg->kmem, RES_USAGE) >> 10,
+		res_counter_read_u64(&memcg->kmem, RES_LIMIT) >> 10,
+		res_counter_read_u64(&memcg->kmem, RES_FAILCNT));
 }
 
 /*
@@ -1498,8 +1636,8 @@ static u64 mem_cgroup_get_limit(struct mem_cgroup *memcg)
 	return limit;
 }
 
-void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
-			      int order)
+static void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
+				     int order)
 {
 	struct mem_cgroup *iter;
 	unsigned long chosen_points = 0;
@@ -1644,9 +1782,9 @@ static void mem_cgroup_may_update_nodemask(struct mem_cgroup *memcg)
 		return;
 
 	/* make a nodemask where this memcg uses memory from */
-	memcg->scan_nodes = node_states[N_HIGH_MEMORY];
+	memcg->scan_nodes = node_states[N_MEMORY];
 
-	for_each_node_mask(nid, node_states[N_HIGH_MEMORY]) {
+	for_each_node_mask(nid, node_states[N_MEMORY]) {
 
 		if (!test_mem_cgroup_node_reclaimable(memcg, nid, false))
 			node_clear(nid, memcg->scan_nodes);
@@ -1717,7 +1855,7 @@ static bool mem_cgroup_reclaimable(struct mem_cgroup *memcg, bool noswap)
 	/*
 	 * Check rest of nodes.
 	 */
-	for_each_node_state(nid, N_HIGH_MEMORY) {
+	for_each_node_state(nid, N_MEMORY) {
 		if (node_isset(nid, memcg->scan_nodes))
 			continue;
 		if (test_mem_cgroup_node_reclaimable(memcg, nid, noswap))
@@ -2061,20 +2199,28 @@ struct memcg_stock_pcp {
 static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock);
 static DEFINE_MUTEX(percpu_charge_mutex);
 
-/*
- * Try to consume stocked charge on this cpu. If success, one page is consumed
- * from local stock and true is returned. If the stock is 0 or charges from a
- * cgroup which is not current target, returns false. This stock will be
- * refilled.
+/**
+ * consume_stock: Try to consume stocked charge on this cpu.
+ * @memcg: memcg to consume from.
+ * @nr_pages: how many pages to charge.
+ *
+ * The charges will only happen if @memcg matches the current cpu's memcg
+ * stock, and at least @nr_pages are available in that stock.  Failure to
+ * service an allocation will refill the stock.
+ *
+ * returns true if successful, false otherwise.
  */
-static bool consume_stock(struct mem_cgroup *memcg)
+static bool consume_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
 {
 	struct memcg_stock_pcp *stock;
 	bool ret = true;
 
+	if (nr_pages > CHARGE_BATCH)
+		return false;
+
 	stock = &get_cpu_var(memcg_stock);
-	if (memcg == stock->cached && stock->nr_pages)
-		stock->nr_pages--;
+	if (memcg == stock->cached && stock->nr_pages >= nr_pages)
+		stock->nr_pages -= nr_pages;
 	else /* need to call res_counter_charge */
 		ret = false;
 	put_cpu_var(memcg_stock);
@@ -2251,7 +2397,8 @@ enum {
 };
 
 static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
-				unsigned int nr_pages, bool oom_check)
+				unsigned int nr_pages, unsigned int min_pages,
+				bool oom_check)
 {
 	unsigned long csize = nr_pages * PAGE_SIZE;
 	struct mem_cgroup *mem_over_limit;
@@ -2274,18 +2421,18 @@ static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
 	} else
 		mem_over_limit = mem_cgroup_from_res_counter(fail_res, res);
 	/*
-	 * nr_pages can be either a huge page (HPAGE_PMD_NR), a batch
-	 * of regular pages (CHARGE_BATCH), or a single regular page (1).
-	 *
 	 * Never reclaim on behalf of optional batching, retry with a
 	 * single page instead.
 	 */
-	if (nr_pages == CHARGE_BATCH)
+	if (nr_pages > min_pages)
 		return CHARGE_RETRY;
 
 	if (!(gfp_mask & __GFP_WAIT))
 		return CHARGE_WOULDBLOCK;
 
+	if (gfp_mask & __GFP_NORETRY)
+		return CHARGE_NOMEM;
+
 	ret = mem_cgroup_reclaim(mem_over_limit, gfp_mask, flags);
 	if (mem_cgroup_margin(mem_over_limit) >= nr_pages)
 		return CHARGE_RETRY;
@@ -2298,7 +2445,7 @@ static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
 	 * unlikely to succeed so close to the limit, and we fall back
 	 * to regular pages anyway in case of failure.
 	 */
-	if (nr_pages == 1 && ret)
+	if (nr_pages <= (1 << PAGE_ALLOC_COSTLY_ORDER) && ret)
 		return CHARGE_RETRY;
 
 	/*
@@ -2370,10 +2517,9 @@ static int __mem_cgroup_try_charge(struct mm_struct *mm,
 again:
 	if (*ptr) { /* css should be a valid one */
 		memcg = *ptr;
-		VM_BUG_ON(css_is_removed(&memcg->css));
 		if (mem_cgroup_is_root(memcg))
 			goto done;
-		if (nr_pages == 1 && consume_stock(memcg))
+		if (consume_stock(memcg, nr_pages))
 			goto done;
 		css_get(&memcg->css);
 	} else {
@@ -2398,7 +2544,7 @@ again:
 			rcu_read_unlock();
 			goto done;
 		}
-		if (nr_pages == 1 && consume_stock(memcg)) {
+		if (consume_stock(memcg, nr_pages)) {
 			/*
 			 * It seems dagerous to access memcg without css_get().
 			 * But considering how consume_stok works, it's not
@@ -2433,7 +2579,8 @@ again:
 			nr_oom_retries = MEM_CGROUP_RECLAIM_RETRIES;
 		}
 
-		ret = mem_cgroup_do_charge(memcg, gfp_mask, batch, oom_check);
+		ret = mem_cgroup_do_charge(memcg, gfp_mask, batch, nr_pages,
+		    oom_check);
 		switch (ret) {
 		case CHARGE_OK:
 			break;
@@ -2510,9 +2657,9 @@ static void __mem_cgroup_cancel_local_charge(struct mem_cgroup *memcg,
 
 /*
  * A helper function to get mem_cgroup from ID. must be called under
- * rcu_read_lock(). The caller must check css_is_removed() or some if
- * it's concern. (dropping refcnt from swap can be called against removed
- * memcg.)
+ * rcu_read_lock().  The caller is responsible for calling css_tryget if
+ * the mem_cgroup is used for charging. (dropping refcnt from swap can be
+ * called against removed memcg.)
  */
 static struct mem_cgroup *mem_cgroup_lookup(unsigned short id)
 {
@@ -2626,199 +2773,969 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg,
 	memcg_check_events(memcg, page);
 }
 
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static DEFINE_MUTEX(set_limit_mutex);
+
+#ifdef CONFIG_MEMCG_KMEM
+static inline bool memcg_can_account_kmem(struct mem_cgroup *memcg)
+{
+	return !mem_cgroup_disabled() && !mem_cgroup_is_root(memcg) &&
+		(memcg->kmem_account_flags & KMEM_ACCOUNTED_MASK);
+}
 
-#define PCGF_NOCOPY_AT_SPLIT (1 << PCG_LOCK | 1 << PCG_MIGRATION)
 /*
- * Because tail pages are not marked as "used", set it. We're under
- * zone->lru_lock, 'splitting on pmd' and compound_lock.
- * charge/uncharge will be never happen and move_account() is done under
- * compound_lock(), so we don't have to take care of races.
+ * This is a bit cumbersome, but it is rarely used and avoids a backpointer
+ * in the memcg_cache_params struct.
  */
-void mem_cgroup_split_huge_fixup(struct page *head)
+static struct kmem_cache *memcg_params_to_cache(struct memcg_cache_params *p)
 {
-	struct page_cgroup *head_pc = lookup_page_cgroup(head);
-	struct page_cgroup *pc;
-	int i;
+	struct kmem_cache *cachep;
 
-	if (mem_cgroup_disabled())
-		return;
-	for (i = 1; i < HPAGE_PMD_NR; i++) {
-		pc = head_pc + i;
-		pc->mem_cgroup = head_pc->mem_cgroup;
-		smp_wmb();/* see __commit_charge() */
-		pc->flags = head_pc->flags & ~PCGF_NOCOPY_AT_SPLIT;
-	}
+	VM_BUG_ON(p->is_root_cache);
+	cachep = p->root_cache;
+	return cachep->memcg_params->memcg_caches[memcg_cache_id(p->memcg)];
 }
-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
-/**
- * mem_cgroup_move_account - move account of the page
- * @page: the page
- * @nr_pages: number of regular pages (>1 for huge pages)
- * @pc:	page_cgroup of the page.
- * @from: mem_cgroup which the page is moved from.
- * @to:	mem_cgroup which the page is moved to. @from != @to.
- *
- * The caller must confirm following.
- * - page is not on LRU (isolate_page() is useful.)
- * - compound_lock is held when nr_pages > 1
- *
- * This function doesn't do "charge" to new cgroup and doesn't do "uncharge"
- * from old cgroup.
- */
-static int mem_cgroup_move_account(struct page *page,
-				   unsigned int nr_pages,
-				   struct page_cgroup *pc,
-				   struct mem_cgroup *from,
-				   struct mem_cgroup *to)
+#ifdef CONFIG_SLABINFO
+static int mem_cgroup_slabinfo_read(struct cgroup *cont, struct cftype *cft,
+					struct seq_file *m)
 {
-	unsigned long flags;
-	int ret;
-	bool anon = PageAnon(page);
+	struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
+	struct memcg_cache_params *params;
 
-	VM_BUG_ON(from == to);
-	VM_BUG_ON(PageLRU(page));
-	/*
-	 * The page is isolated from LRU. So, collapse function
-	 * will not handle this page. But page splitting can happen.
-	 * Do this check under compound_page_lock(). The caller should
-	 * hold it.
-	 */
-	ret = -EBUSY;
-	if (nr_pages > 1 && !PageTransHuge(page))
-		goto out;
+	if (!memcg_can_account_kmem(memcg))
+		return -EIO;
 
-	lock_page_cgroup(pc);
+	print_slabinfo_header(m);
 
-	ret = -EINVAL;
-	if (!PageCgroupUsed(pc) || pc->mem_cgroup != from)
-		goto unlock;
+	mutex_lock(&memcg->slab_caches_mutex);
+	list_for_each_entry(params, &memcg->memcg_slab_caches, list)
+		cache_show(memcg_params_to_cache(params), m);
+	mutex_unlock(&memcg->slab_caches_mutex);
 
-	move_lock_mem_cgroup(from, &flags);
+	return 0;
+}
+#endif
 
-	if (!anon && page_mapped(page)) {
-		/* Update mapped_file data for mem_cgroup */
-		preempt_disable();
-		__this_cpu_dec(from->stat->count[MEM_CGROUP_STAT_FILE_MAPPED]);
-		__this_cpu_inc(to->stat->count[MEM_CGROUP_STAT_FILE_MAPPED]);
-		preempt_enable();
-	}
-	mem_cgroup_charge_statistics(from, anon, -nr_pages);
+static int memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp, u64 size)
+{
+	struct res_counter *fail_res;
+	struct mem_cgroup *_memcg;
+	int ret = 0;
+	bool may_oom;
+
+	ret = res_counter_charge(&memcg->kmem, size, &fail_res);
+	if (ret)
+		return ret;
 
-	/* caller should have done css_get */
-	pc->mem_cgroup = to;
-	mem_cgroup_charge_statistics(to, anon, nr_pages);
-	/*
-	 * We charges against "to" which may not have any tasks. Then, "to"
-	 * can be under rmdir(). But in current implementation, caller of
-	 * this function is just force_empty() and move charge, so it's
-	 * guaranteed that "to" is never removed. So, we don't check rmdir
-	 * status here.
-	 */
-	move_unlock_mem_cgroup(from, &flags);
-	ret = 0;
-unlock:
-	unlock_page_cgroup(pc);
 	/*
-	 * check events
+	 * Conditions under which we can wait for the oom_killer. Those are
+	 * the same conditions tested by the core page allocator
 	 */
-	memcg_check_events(to, page);
-	memcg_check_events(from, page);
-out:
-	return ret;
-}
+	may_oom = (gfp & __GFP_FS) && !(gfp & __GFP_NORETRY);
 
-/*
- * move charges to its parent.
- */
+	_memcg = memcg;
+	ret = __mem_cgroup_try_charge(NULL, gfp, size >> PAGE_SHIFT,
+				      &_memcg, may_oom);
 
-static int mem_cgroup_move_parent(struct page *page,
-				  struct page_cgroup *pc,
-				  struct mem_cgroup *child)
-{
-	struct mem_cgroup *parent;
-	unsigned int nr_pages;
-	unsigned long uninitialized_var(flags);
-	int ret;
+	if (ret == -EINTR)  {
+		/*
+		 * __mem_cgroup_try_charge() chosed to bypass to root due to
+		 * OOM kill or fatal signal.  Since our only options are to
+		 * either fail the allocation or charge it to this cgroup, do
+		 * it as a temporary condition. But we can't fail. From a
+		 * kmem/slab perspective, the cache has already been selected,
+		 * by mem_cgroup_kmem_get_cache(), so it is too late to change
+		 * our minds.
+		 *
+		 * This condition will only trigger if the task entered
+		 * memcg_charge_kmem in a sane state, but was OOM-killed during
+		 * __mem_cgroup_try_charge() above. Tasks that were already
+		 * dying when the allocation triggers should have been already
+		 * directed to the root cgroup in memcontrol.h
+		 */
+		res_counter_charge_nofail(&memcg->res, size, &fail_res);
+		if (do_swap_account)
+			res_counter_charge_nofail(&memcg->memsw, size,
+						  &fail_res);
+		ret = 0;
+	} else if (ret)
+		res_counter_uncharge(&memcg->kmem, size);
 
-	/* Is ROOT ? */
-	if (mem_cgroup_is_root(child))
-		return -EINVAL;
+	return ret;
+}
 
-	ret = -EBUSY;
-	if (!get_page_unless_zero(page))
-		goto out;
-	if (isolate_lru_page(page))
-		goto put;
+static void memcg_uncharge_kmem(struct mem_cgroup *memcg, u64 size)
+{
+	res_counter_uncharge(&memcg->res, size);
+	if (do_swap_account)
+		res_counter_uncharge(&memcg->memsw, size);
 
-	nr_pages = hpage_nr_pages(page);
+	/* Not down to 0 */
+	if (res_counter_uncharge(&memcg->kmem, size))
+		return;
 
-	parent = parent_mem_cgroup(child);
-	/*
-	 * If no parent, move charges to root cgroup.
-	 */
-	if (!parent)
-		parent = root_mem_cgroup;
+	if (memcg_kmem_test_and_clear_dead(memcg))
+		mem_cgroup_put(memcg);
+}
 
-	if (nr_pages > 1)
-		flags = compound_lock_irqsave(page);
+void memcg_cache_list_add(struct mem_cgroup *memcg, struct kmem_cache *cachep)
+{
+	if (!memcg)
+		return;
 
-	ret = mem_cgroup_move_account(page, nr_pages,
-				pc, child, parent);
-	if (!ret)
-		__mem_cgroup_cancel_local_charge(child, nr_pages);
+	mutex_lock(&memcg->slab_caches_mutex);
+	list_add(&cachep->memcg_params->list, &memcg->memcg_slab_caches);
+	mutex_unlock(&memcg->slab_caches_mutex);
+}
 
-	if (nr_pages > 1)
-		compound_unlock_irqrestore(page, flags);
-	putback_lru_page(page);
-put:
-	put_page(page);
-out:
-	return ret;
+/*
+ * helper for acessing a memcg's index. It will be used as an index in the
+ * child cache array in kmem_cache, and also to derive its name. This function
+ * will return -1 when this is not a kmem-limited memcg.
+ */
+int memcg_cache_id(struct mem_cgroup *memcg)
+{
+	return memcg ? memcg->kmemcg_id : -1;
 }
 
 /*
- * Charge the memory controller for page usage.
- * Return
- * 0 if the charge was successful
- * < 0 if the cgroup is over its limit
+ * This ends up being protected by the set_limit mutex, during normal
+ * operation, because that is its main call site.
+ *
+ * But when we create a new cache, we can call this as well if its parent
+ * is kmem-limited. That will have to hold set_limit_mutex as well.
  */
-static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
-				gfp_t gfp_mask, enum charge_type ctype)
+int memcg_update_cache_sizes(struct mem_cgroup *memcg)
 {
-	struct mem_cgroup *memcg = NULL;
-	unsigned int nr_pages = 1;
-	bool oom = true;
-	int ret;
+	int num, ret;
 
-	if (PageTransHuge(page)) {
-		nr_pages <<= compound_order(page);
-		VM_BUG_ON(!PageTransHuge(page));
-		/*
-		 * Never OOM-kill a process for a huge page.  The
-		 * fault handler will fall back to regular pages.
-		 */
-		oom = false;
-	}
+	num = ida_simple_get(&kmem_limited_groups,
+				0, MEMCG_CACHES_MAX_SIZE, GFP_KERNEL);
+	if (num < 0)
+		return num;
+	/*
+	 * After this point, kmem_accounted (that we test atomically in
+	 * the beginning of this conditional), is no longer 0. This
+	 * guarantees only one process will set the following boolean
+	 * to true. We don't need test_and_set because we're protected
+	 * by the set_limit_mutex anyway.
+	 */
+	memcg_kmem_set_activated(memcg);
 
-	ret = __mem_cgroup_try_charge(mm, gfp_mask, nr_pages, &memcg, oom);
-	if (ret == -ENOMEM)
+	ret = memcg_update_all_caches(num+1);
+	if (ret) {
+		ida_simple_remove(&kmem_limited_groups, num);
+		memcg_kmem_clear_activated(memcg);
 		return ret;
-	__mem_cgroup_commit_charge(memcg, page, nr_pages, ctype, false);
+	}
+
+	memcg->kmemcg_id = num;
+	INIT_LIST_HEAD(&memcg->memcg_slab_caches);
+	mutex_init(&memcg->slab_caches_mutex);
 	return 0;
 }
 
-int mem_cgroup_newpage_charge(struct page *page,
-			      struct mm_struct *mm, gfp_t gfp_mask)
+static size_t memcg_caches_array_size(int num_groups)
 {
-	if (mem_cgroup_disabled())
+	ssize_t size;
+	if (num_groups <= 0)
 		return 0;
-	VM_BUG_ON(page_mapped(page));
-	VM_BUG_ON(page->mapping && !PageAnon(page));
-	VM_BUG_ON(!mm);
-	return mem_cgroup_charge_common(page, mm, gfp_mask,
-					MEM_CGROUP_CHARGE_TYPE_ANON);
+
+	size = 2 * num_groups;
+	if (size < MEMCG_CACHES_MIN_SIZE)
+		size = MEMCG_CACHES_MIN_SIZE;
+	else if (size > MEMCG_CACHES_MAX_SIZE)
+		size = MEMCG_CACHES_MAX_SIZE;
+
+	return size;
+}
+
+/*
+ * We should update the current array size iff all caches updates succeed. This
+ * can only be done from the slab side. The slab mutex needs to be held when
+ * calling this.
+ */
+void memcg_update_array_size(int num)
+{
+	if (num > memcg_limited_groups_array_size)
+		memcg_limited_groups_array_size = memcg_caches_array_size(num);
+}
+
+int memcg_update_cache_size(struct kmem_cache *s, int num_groups)
+{
+	struct memcg_cache_params *cur_params = s->memcg_params;
+
+	VM_BUG_ON(s->memcg_params && !s->memcg_params->is_root_cache);
+
+	if (num_groups > memcg_limited_groups_array_size) {
+		int i;
+		ssize_t size = memcg_caches_array_size(num_groups);
+
+		size *= sizeof(void *);
+		size += sizeof(struct memcg_cache_params);
+
+		s->memcg_params = kzalloc(size, GFP_KERNEL);
+		if (!s->memcg_params) {
+			s->memcg_params = cur_params;
+			return -ENOMEM;
+		}
+
+		s->memcg_params->is_root_cache = true;
+
+		/*
+		 * There is the chance it will be bigger than
+		 * memcg_limited_groups_array_size, if we failed an allocation
+		 * in a cache, in which case all caches updated before it, will
+		 * have a bigger array.
+		 *
+		 * But if that is the case, the data after
+		 * memcg_limited_groups_array_size is certainly unused
+		 */
+		for (i = 0; i < memcg_limited_groups_array_size; i++) {
+			if (!cur_params->memcg_caches[i])
+				continue;
+			s->memcg_params->memcg_caches[i] =
+						cur_params->memcg_caches[i];
+		}
+
+		/*
+		 * Ideally, we would wait until all caches succeed, and only
+		 * then free the old one. But this is not worth the extra
+		 * pointer per-cache we'd have to have for this.
+		 *
+		 * It is not a big deal if some caches are left with a size
+		 * bigger than the others. And all updates will reset this
+		 * anyway.
+		 */
+		kfree(cur_params);
+	}
+	return 0;
+}
+
+int memcg_register_cache(struct mem_cgroup *memcg, struct kmem_cache *s,
+			 struct kmem_cache *root_cache)
+{
+	size_t size = sizeof(struct memcg_cache_params);
+
+	if (!memcg_kmem_enabled())
+		return 0;
+
+	if (!memcg)
+		size += memcg_limited_groups_array_size * sizeof(void *);
+
+	s->memcg_params = kzalloc(size, GFP_KERNEL);
+	if (!s->memcg_params)
+		return -ENOMEM;
+
+	if (memcg) {
+		s->memcg_params->memcg = memcg;
+		s->memcg_params->root_cache = root_cache;
+	}
+	return 0;
+}
+
+void memcg_release_cache(struct kmem_cache *s)
+{
+	struct kmem_cache *root;
+	struct mem_cgroup *memcg;
+	int id;
+
+	/*
+	 * This happens, for instance, when a root cache goes away before we
+	 * add any memcg.
+	 */
+	if (!s->memcg_params)
+		return;
+
+	if (s->memcg_params->is_root_cache)
+		goto out;
+
+	memcg = s->memcg_params->memcg;
+	id  = memcg_cache_id(memcg);
+
+	root = s->memcg_params->root_cache;
+	root->memcg_params->memcg_caches[id] = NULL;
+	mem_cgroup_put(memcg);
+
+	mutex_lock(&memcg->slab_caches_mutex);
+	list_del(&s->memcg_params->list);
+	mutex_unlock(&memcg->slab_caches_mutex);
+
+out:
+	kfree(s->memcg_params);
+}
+
+/*
+ * During the creation a new cache, we need to disable our accounting mechanism
+ * altogether. This is true even if we are not creating, but rather just
+ * enqueing new caches to be created.
+ *
+ * This is because that process will trigger allocations; some visible, like
+ * explicit kmallocs to auxiliary data structures, name strings and internal
+ * cache structures; some well concealed, like INIT_WORK() that can allocate
+ * objects during debug.
+ *
+ * If any allocation happens during memcg_kmem_get_cache, we will recurse back
+ * to it. This may not be a bounded recursion: since the first cache creation
+ * failed to complete (waiting on the allocation), we'll just try to create the
+ * cache again, failing at the same point.
+ *
+ * memcg_kmem_get_cache is prepared to abort after seeing a positive count of
+ * memcg_kmem_skip_account. So we enclose anything that might allocate memory
+ * inside the following two functions.
+ */
+static inline void memcg_stop_kmem_account(void)
+{
+	VM_BUG_ON(!current->mm);
+	current->memcg_kmem_skip_account++;
+}
+
+static inline void memcg_resume_kmem_account(void)
+{
+	VM_BUG_ON(!current->mm);
+	current->memcg_kmem_skip_account--;
+}
+
+static void kmem_cache_destroy_work_func(struct work_struct *w)
+{
+	struct kmem_cache *cachep;
+	struct memcg_cache_params *p;
+
+	p = container_of(w, struct memcg_cache_params, destroy);
+
+	cachep = memcg_params_to_cache(p);
+
+	/*
+	 * If we get down to 0 after shrink, we could delete right away.
+	 * However, memcg_release_pages() already puts us back in the workqueue
+	 * in that case. If we proceed deleting, we'll get a dangling
+	 * reference, and removing the object from the workqueue in that case
+	 * is unnecessary complication. We are not a fast path.
+	 *
+	 * Note that this case is fundamentally different from racing with
+	 * shrink_slab(): if memcg_cgroup_destroy_cache() is called in
+	 * kmem_cache_shrink, not only we would be reinserting a dead cache
+	 * into the queue, but doing so from inside the worker racing to
+	 * destroy it.
+	 *
+	 * So if we aren't down to zero, we'll just schedule a worker and try
+	 * again
+	 */
+	if (atomic_read(&cachep->memcg_params->nr_pages) != 0) {
+		kmem_cache_shrink(cachep);
+		if (atomic_read(&cachep->memcg_params->nr_pages) == 0)
+			return;
+	} else
+		kmem_cache_destroy(cachep);
+}
+
+void mem_cgroup_destroy_cache(struct kmem_cache *cachep)
+{
+	if (!cachep->memcg_params->dead)
+		return;
+
+	/*
+	 * There are many ways in which we can get here.
+	 *
+	 * We can get to a memory-pressure situation while the delayed work is
+	 * still pending to run. The vmscan shrinkers can then release all
+	 * cache memory and get us to destruction. If this is the case, we'll
+	 * be executed twice, which is a bug (the second time will execute over
+	 * bogus data). In this case, cancelling the work should be fine.
+	 *
+	 * But we can also get here from the worker itself, if
+	 * kmem_cache_shrink is enough to shake all the remaining objects and
+	 * get the page count to 0. In this case, we'll deadlock if we try to
+	 * cancel the work (the worker runs with an internal lock held, which
+	 * is the same lock we would hold for cancel_work_sync().)
+	 *
+	 * Since we can't possibly know who got us here, just refrain from
+	 * running if there is already work pending
+	 */
+	if (work_pending(&cachep->memcg_params->destroy))
+		return;
+	/*
+	 * We have to defer the actual destroying to a workqueue, because
+	 * we might currently be in a context that cannot sleep.
+	 */
+	schedule_work(&cachep->memcg_params->destroy);
+}
+
+static char *memcg_cache_name(struct mem_cgroup *memcg, struct kmem_cache *s)
+{
+	char *name;
+	struct dentry *dentry;
+
+	rcu_read_lock();
+	dentry = rcu_dereference(memcg->css.cgroup->dentry);
+	rcu_read_unlock();
+
+	BUG_ON(dentry == NULL);
+
+	name = kasprintf(GFP_KERNEL, "%s(%d:%s)", s->name,
+			 memcg_cache_id(memcg), dentry->d_name.name);
+
+	return name;
+}
+
+static struct kmem_cache *kmem_cache_dup(struct mem_cgroup *memcg,
+					 struct kmem_cache *s)
+{
+	char *name;
+	struct kmem_cache *new;
+
+	name = memcg_cache_name(memcg, s);
+	if (!name)
+		return NULL;
+
+	new = kmem_cache_create_memcg(memcg, name, s->object_size, s->align,
+				      (s->flags & ~SLAB_PANIC), s->ctor, s);
+
+	if (new)
+		new->allocflags |= __GFP_KMEMCG;
+
+	kfree(name);
+	return new;
+}
+
+/*
+ * This lock protects updaters, not readers. We want readers to be as fast as
+ * they can, and they will either see NULL or a valid cache value. Our model
+ * allow them to see NULL, in which case the root memcg will be selected.
+ *
+ * We need this lock because multiple allocations to the same cache from a non
+ * will span more than one worker. Only one of them can create the cache.
+ */
+static DEFINE_MUTEX(memcg_cache_mutex);
+static struct kmem_cache *memcg_create_kmem_cache(struct mem_cgroup *memcg,
+						  struct kmem_cache *cachep)
+{
+	struct kmem_cache *new_cachep;
+	int idx;
+
+	BUG_ON(!memcg_can_account_kmem(memcg));
+
+	idx = memcg_cache_id(memcg);
+
+	mutex_lock(&memcg_cache_mutex);
+	new_cachep = cachep->memcg_params->memcg_caches[idx];
+	if (new_cachep)
+		goto out;
+
+	new_cachep = kmem_cache_dup(memcg, cachep);
+	if (new_cachep == NULL) {
+		new_cachep = cachep;
+		goto out;
+	}
+
+	mem_cgroup_get(memcg);
+	atomic_set(&new_cachep->memcg_params->nr_pages , 0);
+
+	cachep->memcg_params->memcg_caches[idx] = new_cachep;
+	/*
+	 * the readers won't lock, make sure everybody sees the updated value,
+	 * so they won't put stuff in the queue again for no reason
+	 */
+	wmb();
+out:
+	mutex_unlock(&memcg_cache_mutex);
+	return new_cachep;
+}
+
+void kmem_cache_destroy_memcg_children(struct kmem_cache *s)
+{
+	struct kmem_cache *c;
+	int i;
+
+	if (!s->memcg_params)
+		return;
+	if (!s->memcg_params->is_root_cache)
+		return;
+
+	/*
+	 * If the cache is being destroyed, we trust that there is no one else
+	 * requesting objects from it. Even if there are, the sanity checks in
+	 * kmem_cache_destroy should caught this ill-case.
+	 *
+	 * Still, we don't want anyone else freeing memcg_caches under our
+	 * noses, which can happen if a new memcg comes to life. As usual,
+	 * we'll take the set_limit_mutex to protect ourselves against this.
+	 */
+	mutex_lock(&set_limit_mutex);
+	for (i = 0; i < memcg_limited_groups_array_size; i++) {
+		c = s->memcg_params->memcg_caches[i];
+		if (!c)
+			continue;
+
+		/*
+		 * We will now manually delete the caches, so to avoid races
+		 * we need to cancel all pending destruction workers and
+		 * proceed with destruction ourselves.
+		 *
+		 * kmem_cache_destroy() will call kmem_cache_shrink internally,
+		 * and that could spawn the workers again: it is likely that
+		 * the cache still have active pages until this very moment.
+		 * This would lead us back to mem_cgroup_destroy_cache.
+		 *
+		 * But that will not execute at all if the "dead" flag is not
+		 * set, so flip it down to guarantee we are in control.
+		 */
+		c->memcg_params->dead = false;
+		cancel_work_sync(&c->memcg_params->destroy);
+		kmem_cache_destroy(c);
+	}
+	mutex_unlock(&set_limit_mutex);
+}
+
+struct create_work {
+	struct mem_cgroup *memcg;
+	struct kmem_cache *cachep;
+	struct work_struct work;
+};
+
+static void mem_cgroup_destroy_all_caches(struct mem_cgroup *memcg)
+{
+	struct kmem_cache *cachep;
+	struct memcg_cache_params *params;
+
+	if (!memcg_kmem_is_active(memcg))
+		return;
+
+	mutex_lock(&memcg->slab_caches_mutex);
+	list_for_each_entry(params, &memcg->memcg_slab_caches, list) {
+		cachep = memcg_params_to_cache(params);
+		cachep->memcg_params->dead = true;
+		INIT_WORK(&cachep->memcg_params->destroy,
+				  kmem_cache_destroy_work_func);
+		schedule_work(&cachep->memcg_params->destroy);
+	}
+	mutex_unlock(&memcg->slab_caches_mutex);
+}
+
+static void memcg_create_cache_work_func(struct work_struct *w)
+{
+	struct create_work *cw;
+
+	cw = container_of(w, struct create_work, work);
+	memcg_create_kmem_cache(cw->memcg, cw->cachep);
+	/* Drop the reference gotten when we enqueued. */
+	css_put(&cw->memcg->css);
+	kfree(cw);
+}
+
+/*
+ * Enqueue the creation of a per-memcg kmem_cache.
+ * Called with rcu_read_lock.
+ */
+static void __memcg_create_cache_enqueue(struct mem_cgroup *memcg,
+					 struct kmem_cache *cachep)
+{
+	struct create_work *cw;
+
+	cw = kmalloc(sizeof(struct create_work), GFP_NOWAIT);
+	if (cw == NULL)
+		return;
+
+	/* The corresponding put will be done in the workqueue. */
+	if (!css_tryget(&memcg->css)) {
+		kfree(cw);
+		return;
+	}
+
+	cw->memcg = memcg;
+	cw->cachep = cachep;
+
+	INIT_WORK(&cw->work, memcg_create_cache_work_func);
+	schedule_work(&cw->work);
+}
+
+static void memcg_create_cache_enqueue(struct mem_cgroup *memcg,
+				       struct kmem_cache *cachep)
+{
+	/*
+	 * We need to stop accounting when we kmalloc, because if the
+	 * corresponding kmalloc cache is not yet created, the first allocation
+	 * in __memcg_create_cache_enqueue will recurse.
+	 *
+	 * However, it is better to enclose the whole function. Depending on
+	 * the debugging options enabled, INIT_WORK(), for instance, can
+	 * trigger an allocation. This too, will make us recurse. Because at
+	 * this point we can't allow ourselves back into memcg_kmem_get_cache,
+	 * the safest choice is to do it like this, wrapping the whole function.
+	 */
+	memcg_stop_kmem_account();
+	__memcg_create_cache_enqueue(memcg, cachep);
+	memcg_resume_kmem_account();
+}
+/*
+ * Return the kmem_cache we're supposed to use for a slab allocation.
+ * We try to use the current memcg's version of the cache.
+ *
+ * If the cache does not exist yet, if we are the first user of it,
+ * we either create it immediately, if possible, or create it asynchronously
+ * in a workqueue.
+ * In the latter case, we will let the current allocation go through with
+ * the original cache.
+ *
+ * Can't be called in interrupt context or from kernel threads.
+ * This function needs to be called with rcu_read_lock() held.
+ */
+struct kmem_cache *__memcg_kmem_get_cache(struct kmem_cache *cachep,
+					  gfp_t gfp)
+{
+	struct mem_cgroup *memcg;
+	int idx;
+
+	VM_BUG_ON(!cachep->memcg_params);
+	VM_BUG_ON(!cachep->memcg_params->is_root_cache);
+
+	if (!current->mm || current->memcg_kmem_skip_account)
+		return cachep;
+
+	rcu_read_lock();
+	memcg = mem_cgroup_from_task(rcu_dereference(current->mm->owner));
+	rcu_read_unlock();
+
+	if (!memcg_can_account_kmem(memcg))
+		return cachep;
+
+	idx = memcg_cache_id(memcg);
+
+	/*
+	 * barrier to mare sure we're always seeing the up to date value.  The
+	 * code updating memcg_caches will issue a write barrier to match this.
+	 */
+	read_barrier_depends();
+	if (unlikely(cachep->memcg_params->memcg_caches[idx] == NULL)) {
+		/*
+		 * If we are in a safe context (can wait, and not in interrupt
+		 * context), we could be be predictable and return right away.
+		 * This would guarantee that the allocation being performed
+		 * already belongs in the new cache.
+		 *
+		 * However, there are some clashes that can arrive from locking.
+		 * For instance, because we acquire the slab_mutex while doing
+		 * kmem_cache_dup, this means no further allocation could happen
+		 * with the slab_mutex held.
+		 *
+		 * Also, because cache creation issue get_online_cpus(), this
+		 * creates a lock chain: memcg_slab_mutex -> cpu_hotplug_mutex,
+		 * that ends up reversed during cpu hotplug. (cpuset allocates
+		 * a bunch of GFP_KERNEL memory during cpuup). Due to all that,
+		 * better to defer everything.
+		 */
+		memcg_create_cache_enqueue(memcg, cachep);
+		return cachep;
+	}
+
+	return cachep->memcg_params->memcg_caches[idx];
+}
+EXPORT_SYMBOL(__memcg_kmem_get_cache);
+
+/*
+ * We need to verify if the allocation against current->mm->owner's memcg is
+ * possible for the given order. But the page is not allocated yet, so we'll
+ * need a further commit step to do the final arrangements.
+ *
+ * It is possible for the task to switch cgroups in this mean time, so at
+ * commit time, we can't rely on task conversion any longer.  We'll then use
+ * the handle argument to return to the caller which cgroup we should commit
+ * against. We could also return the memcg directly and avoid the pointer
+ * passing, but a boolean return value gives better semantics considering
+ * the compiled-out case as well.
+ *
+ * Returning true means the allocation is possible.
+ */
+bool
+__memcg_kmem_newpage_charge(gfp_t gfp, struct mem_cgroup **_memcg, int order)
+{
+	struct mem_cgroup *memcg;
+	int ret;
+
+	*_memcg = NULL;
+	memcg = try_get_mem_cgroup_from_mm(current->mm);
+
+	/*
+	 * very rare case described in mem_cgroup_from_task. Unfortunately there
+	 * isn't much we can do without complicating this too much, and it would
+	 * be gfp-dependent anyway. Just let it go
+	 */
+	if (unlikely(!memcg))
+		return true;
+
+	if (!memcg_can_account_kmem(memcg)) {
+		css_put(&memcg->css);
+		return true;
+	}
+
+	ret = memcg_charge_kmem(memcg, gfp, PAGE_SIZE << order);
+	if (!ret)
+		*_memcg = memcg;
+
+	css_put(&memcg->css);
+	return (ret == 0);
+}
+
+void __memcg_kmem_commit_charge(struct page *page, struct mem_cgroup *memcg,
+			      int order)
+{
+	struct page_cgroup *pc;
+
+	VM_BUG_ON(mem_cgroup_is_root(memcg));
+
+	/* The page allocation failed. Revert */
+	if (!page) {
+		memcg_uncharge_kmem(memcg, PAGE_SIZE << order);
+		return;
+	}
+
+	pc = lookup_page_cgroup(page);
+	lock_page_cgroup(pc);
+	pc->mem_cgroup = memcg;
+	SetPageCgroupUsed(pc);
+	unlock_page_cgroup(pc);
+}
+
+void __memcg_kmem_uncharge_pages(struct page *page, int order)
+{
+	struct mem_cgroup *memcg = NULL;
+	struct page_cgroup *pc;
+
+
+	pc = lookup_page_cgroup(page);
+	/*
+	 * Fast unlocked return. Theoretically might have changed, have to
+	 * check again after locking.
+	 */
+	if (!PageCgroupUsed(pc))
+		return;
+
+	lock_page_cgroup(pc);
+	if (PageCgroupUsed(pc)) {
+		memcg = pc->mem_cgroup;
+		ClearPageCgroupUsed(pc);
+	}
+	unlock_page_cgroup(pc);
+
+	/*
+	 * We trust that only if there is a memcg associated with the page, it
+	 * is a valid allocation
+	 */
+	if (!memcg)
+		return;
+
+	VM_BUG_ON(mem_cgroup_is_root(memcg));
+	memcg_uncharge_kmem(memcg, PAGE_SIZE << order);
+}
+#else
+static inline void mem_cgroup_destroy_all_caches(struct mem_cgroup *memcg)
+{
+}
+#endif /* CONFIG_MEMCG_KMEM */
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+#define PCGF_NOCOPY_AT_SPLIT (1 << PCG_LOCK | 1 << PCG_MIGRATION)
+/*
+ * Because tail pages are not marked as "used", set it. We're under
+ * zone->lru_lock, 'splitting on pmd' and compound_lock.
+ * charge/uncharge will be never happen and move_account() is done under
+ * compound_lock(), so we don't have to take care of races.
+ */
+void mem_cgroup_split_huge_fixup(struct page *head)
+{
+	struct page_cgroup *head_pc = lookup_page_cgroup(head);
+	struct page_cgroup *pc;
+	int i;
+
+	if (mem_cgroup_disabled())
+		return;
+	for (i = 1; i < HPAGE_PMD_NR; i++) {
+		pc = head_pc + i;
+		pc->mem_cgroup = head_pc->mem_cgroup;
+		smp_wmb();/* see __commit_charge() */
+		pc->flags = head_pc->flags & ~PCGF_NOCOPY_AT_SPLIT;
+	}
+}
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+
+/**
+ * mem_cgroup_move_account - move account of the page
+ * @page: the page
+ * @nr_pages: number of regular pages (>1 for huge pages)
+ * @pc:	page_cgroup of the page.
+ * @from: mem_cgroup which the page is moved from.
+ * @to:	mem_cgroup which the page is moved to. @from != @to.
+ *
+ * The caller must confirm following.
+ * - page is not on LRU (isolate_page() is useful.)
+ * - compound_lock is held when nr_pages > 1
+ *
+ * This function doesn't do "charge" to new cgroup and doesn't do "uncharge"
+ * from old cgroup.
+ */
+static int mem_cgroup_move_account(struct page *page,
+				   unsigned int nr_pages,
+				   struct page_cgroup *pc,
+				   struct mem_cgroup *from,
+				   struct mem_cgroup *to)
+{
+	unsigned long flags;
+	int ret;
+	bool anon = PageAnon(page);
+
+	VM_BUG_ON(from == to);
+	VM_BUG_ON(PageLRU(page));
+	/*
+	 * The page is isolated from LRU. So, collapse function
+	 * will not handle this page. But page splitting can happen.
+	 * Do this check under compound_page_lock(). The caller should
+	 * hold it.
+	 */
+	ret = -EBUSY;
+	if (nr_pages > 1 && !PageTransHuge(page))
+		goto out;
+
+	lock_page_cgroup(pc);
+
+	ret = -EINVAL;
+	if (!PageCgroupUsed(pc) || pc->mem_cgroup != from)
+		goto unlock;
+
+	move_lock_mem_cgroup(from, &flags);
+
+	if (!anon && page_mapped(page)) {
+		/* Update mapped_file data for mem_cgroup */
+		preempt_disable();
+		__this_cpu_dec(from->stat->count[MEM_CGROUP_STAT_FILE_MAPPED]);
+		__this_cpu_inc(to->stat->count[MEM_CGROUP_STAT_FILE_MAPPED]);
+		preempt_enable();
+	}
+	mem_cgroup_charge_statistics(from, anon, -nr_pages);
+
+	/* caller should have done css_get */
+	pc->mem_cgroup = to;
+	mem_cgroup_charge_statistics(to, anon, nr_pages);
+	move_unlock_mem_cgroup(from, &flags);
+	ret = 0;
+unlock:
+	unlock_page_cgroup(pc);
+	/*
+	 * check events
+	 */
+	memcg_check_events(to, page);
+	memcg_check_events(from, page);
+out:
+	return ret;
+}
+
+/**
+ * mem_cgroup_move_parent - moves page to the parent group
+ * @page: the page to move
+ * @pc: page_cgroup of the page
+ * @child: page's cgroup
+ *
+ * move charges to its parent or the root cgroup if the group has no
+ * parent (aka use_hierarchy==0).
+ * Although this might fail (get_page_unless_zero, isolate_lru_page or
+ * mem_cgroup_move_account fails) the failure is always temporary and
+ * it signals a race with a page removal/uncharge or migration. In the
+ * first case the page is on the way out and it will vanish from the LRU
+ * on the next attempt and the call should be retried later.
+ * Isolation from the LRU fails only if page has been isolated from
+ * the LRU since we looked at it and that usually means either global
+ * reclaim or migration going on. The page will either get back to the
+ * LRU or vanish.
+ * Finaly mem_cgroup_move_account fails only if the page got uncharged
+ * (!PageCgroupUsed) or moved to a different group. The page will
+ * disappear in the next attempt.
+ */
+static int mem_cgroup_move_parent(struct page *page,
+				  struct page_cgroup *pc,
+				  struct mem_cgroup *child)
+{
+	struct mem_cgroup *parent;
+	unsigned int nr_pages;
+	unsigned long uninitialized_var(flags);
+	int ret;
+
+	VM_BUG_ON(mem_cgroup_is_root(child));
+
+	ret = -EBUSY;
+	if (!get_page_unless_zero(page))
+		goto out;
+	if (isolate_lru_page(page))
+		goto put;
+
+	nr_pages = hpage_nr_pages(page);
+
+	parent = parent_mem_cgroup(child);
+	/*
+	 * If no parent, move charges to root cgroup.
+	 */
+	if (!parent)
+		parent = root_mem_cgroup;
+
+	if (nr_pages > 1) {
+		VM_BUG_ON(!PageTransHuge(page));
+		flags = compound_lock_irqsave(page);
+	}
+
+	ret = mem_cgroup_move_account(page, nr_pages,
+				pc, child, parent);
+	if (!ret)
+		__mem_cgroup_cancel_local_charge(child, nr_pages);
+
+	if (nr_pages > 1)
+		compound_unlock_irqrestore(page, flags);
+	putback_lru_page(page);
+put:
+	put_page(page);
+out:
+	return ret;
+}
+
+/*
+ * Charge the memory controller for page usage.
+ * Return
+ * 0 if the charge was successful
+ * < 0 if the cgroup is over its limit
+ */
+static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
+				gfp_t gfp_mask, enum charge_type ctype)
+{
+	struct mem_cgroup *memcg = NULL;
+	unsigned int nr_pages = 1;
+	bool oom = true;
+	int ret;
+
+	if (PageTransHuge(page)) {
+		nr_pages <<= compound_order(page);
+		VM_BUG_ON(!PageTransHuge(page));
+		/*
+		 * Never OOM-kill a process for a huge page.  The
+		 * fault handler will fall back to regular pages.
+		 */
+		oom = false;
+	}
+
+	ret = __mem_cgroup_try_charge(mm, gfp_mask, nr_pages, &memcg, oom);
+	if (ret == -ENOMEM)
+		return ret;
+	__mem_cgroup_commit_charge(memcg, page, nr_pages, ctype, false);
+	return 0;
+}
+
+int mem_cgroup_newpage_charge(struct page *page,
+			      struct mm_struct *mm, gfp_t gfp_mask)
+{
+	if (mem_cgroup_disabled())
+		return 0;
+	VM_BUG_ON(page_mapped(page));
+	VM_BUG_ON(page->mapping && !PageAnon(page));
+	VM_BUG_ON(!mm);
+	return mem_cgroup_charge_common(page, mm, gfp_mask,
+					MEM_CGROUP_CHARGE_TYPE_ANON);
 }
 
 /*
@@ -2904,7 +3821,6 @@ __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *memcg,
 		return;
 	if (!memcg)
 		return;
-	cgroup_exclude_rmdir(&memcg->css);
 
 	__mem_cgroup_commit_charge(memcg, page, 1, ctype, true);
 	/*
@@ -2918,12 +3834,6 @@ __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *memcg,
 		swp_entry_t ent = {.val = page_private(page)};
 		mem_cgroup_uncharge_swap(ent);
 	}
-	/*
-	 * At swapin, we may charge account against cgroup which has no tasks.
-	 * So, rmdir()->pre_destroy() can be called while we do this charge.
-	 * In that case, we need to call pre_destroy() again. check it here.
-	 */
-	cgroup_release_and_wakeup_rmdir(&memcg->css);
 }
 
 void mem_cgroup_commit_charge_swapin(struct page *page,
@@ -3288,15 +4198,18 @@ void mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
 				  struct mem_cgroup **memcgp)
 {
 	struct mem_cgroup *memcg = NULL;
+	unsigned int nr_pages = 1;
 	struct page_cgroup *pc;
 	enum charge_type ctype;
 
 	*memcgp = NULL;
 
-	VM_BUG_ON(PageTransHuge(page));
 	if (mem_cgroup_disabled())
 		return;
 
+	if (PageTransHuge(page))
+		nr_pages <<= compound_order(page);
+
 	pc = lookup_page_cgroup(page);
 	lock_page_cgroup(pc);
 	if (PageCgroupUsed(pc)) {
@@ -3358,7 +4271,7 @@ void mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
 	 * charged to the res_counter since we plan on replacing the
 	 * old one and only one page is going to be left afterwards.
 	 */
-	__mem_cgroup_commit_charge(memcg, newpage, 1, ctype, false);
+	__mem_cgroup_commit_charge(memcg, newpage, nr_pages, ctype, false);
 }
 
 /* remove redundant charge if migration failed*/
@@ -3371,8 +4284,7 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 
 	if (!memcg)
 		return;
-	/* blocks rmdir() */
-	cgroup_exclude_rmdir(&memcg->css);
+
 	if (!migration_ok) {
 		used = oldpage;
 		unused = newpage;
@@ -3406,13 +4318,6 @@ void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 	 */
 	if (anon)
 		mem_cgroup_uncharge_page(used);
-	/*
-	 * At migration, we may charge account against cgroup which has no
-	 * tasks.
-	 * So, rmdir()->pre_destroy() can be called while we do this charge.
-	 * In that case, we need to call pre_destroy() again. check it here.
-	 */
-	cgroup_release_and_wakeup_rmdir(&memcg->css);
 }
 
 /*
@@ -3490,8 +4395,6 @@ void mem_cgroup_print_bad_page(struct page *page)
 }
 #endif
 
-static DEFINE_MUTEX(set_limit_mutex);
-
 static int mem_cgroup_resize_limit(struct mem_cgroup *memcg,
 				unsigned long long val)
 {
@@ -3712,17 +4615,22 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
 	return nr_reclaimed;
 }
 
-/*
+/**
+ * mem_cgroup_force_empty_list - clears LRU of a group
+ * @memcg: group to clear
+ * @node: NUMA node
+ * @zid: zone id
+ * @lru: lru to to clear
+ *
  * Traverse a specified page_cgroup list and try to drop them all.  This doesn't
- * reclaim the pages page themselves - it just removes the page_cgroups.
- * Returns true if some page_cgroups were not freed, indicating that the caller
- * must retry this operation.
+ * reclaim the pages page themselves - pages are moved to the parent (or root)
+ * group.
  */
-static bool mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
+static void mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
 				int node, int zid, enum lru_list lru)
 {
 	struct lruvec *lruvec;
-	unsigned long flags, loop;
+	unsigned long flags;
 	struct list_head *list;
 	struct page *busy;
 	struct zone *zone;
@@ -3731,11 +4639,8 @@ static bool mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
 	lruvec = mem_cgroup_zone_lruvec(zone, memcg);
 	list = &lruvec->lists[lru];
 
-	loop = mem_cgroup_get_lru_size(lruvec, lru);
-	/* give some margin against EBUSY etc...*/
-	loop += 256;
 	busy = NULL;
-	while (loop--) {
+	do {
 		struct page_cgroup *pc;
 		struct page *page;
 
@@ -3761,76 +4666,80 @@ static bool mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
 			cond_resched();
 		} else
 			busy = NULL;
-	}
-	return !list_empty(list);
+	} while (!list_empty(list));
 }
 
 /*
- * make mem_cgroup's charge to be 0 if there is no task.
+ * make mem_cgroup's charge to be 0 if there is no task by moving
+ * all the charges and pages to the parent.
  * This enables deleting this mem_cgroup.
+ *
+ * Caller is responsible for holding css reference on the memcg.
  */
-static int mem_cgroup_force_empty(struct mem_cgroup *memcg, bool free_all)
+static void mem_cgroup_reparent_charges(struct mem_cgroup *memcg)
 {
-	int ret;
-	int node, zid, shrink;
-	int nr_retries = MEM_CGROUP_RECLAIM_RETRIES;
-	struct cgroup *cgrp = memcg->css.cgroup;
-
-	css_get(&memcg->css);
+	int node, zid;
+	u64 usage;
 
-	shrink = 0;
-	/* should free all ? */
-	if (free_all)
-		goto try_to_free;
-move_account:
 	do {
-		ret = -EBUSY;
-		if (cgroup_task_count(cgrp) || !list_empty(&cgrp->children))
-			goto out;
 		/* This is for making all *used* pages to be on LRU. */
 		lru_add_drain_all();
 		drain_all_stock_sync(memcg);
-		ret = 0;
 		mem_cgroup_start_move(memcg);
-		for_each_node_state(node, N_HIGH_MEMORY) {
-			for (zid = 0; !ret && zid < MAX_NR_ZONES; zid++) {
+		for_each_node_state(node, N_MEMORY) {
+			for (zid = 0; zid < MAX_NR_ZONES; zid++) {
 				enum lru_list lru;
 				for_each_lru(lru) {
-					ret = mem_cgroup_force_empty_list(memcg,
+					mem_cgroup_force_empty_list(memcg,
 							node, zid, lru);
-					if (ret)
-						break;
 				}
 			}
-			if (ret)
-				break;
 		}
 		mem_cgroup_end_move(memcg);
 		memcg_oom_recover(memcg);
 		cond_resched();
-	/* "ret" should also be checked to ensure all lists are empty. */
-	} while (res_counter_read_u64(&memcg->res, RES_USAGE) > 0 || ret);
-out:
-	css_put(&memcg->css);
-	return ret;
 
-try_to_free:
+		/*
+		 * Kernel memory may not necessarily be trackable to a specific
+		 * process. So they are not migrated, and therefore we can't
+		 * expect their value to drop to 0 here.
+		 * Having res filled up with kmem only is enough.
+		 *
+		 * This is a safety check because mem_cgroup_force_empty_list
+		 * could have raced with mem_cgroup_replace_page_cache callers
+		 * so the lru seemed empty but the page could have been added
+		 * right after the check. RES_USAGE should be safe as we always
+		 * charge before adding to the LRU.
+		 */
+		usage = res_counter_read_u64(&memcg->res, RES_USAGE) -
+			res_counter_read_u64(&memcg->kmem, RES_USAGE);
+	} while (usage > 0);
+}
+
+/*
+ * Reclaims as many pages from the given memcg as possible and moves
+ * the rest to the parent.
+ *
+ * Caller is responsible for holding css reference for memcg.
+ */
+static int mem_cgroup_force_empty(struct mem_cgroup *memcg)
+{
+	int nr_retries = MEM_CGROUP_RECLAIM_RETRIES;
+	struct cgroup *cgrp = memcg->css.cgroup;
+
 	/* returns EBUSY if there is a task or if we come here twice. */
-	if (cgroup_task_count(cgrp) || !list_empty(&cgrp->children) || shrink) {
-		ret = -EBUSY;
-		goto out;
-	}
+	if (cgroup_task_count(cgrp) || !list_empty(&cgrp->children))
+		return -EBUSY;
+
 	/* we call try-to-free pages for make this cgroup empty */
 	lru_add_drain_all();
 	/* try to free all pages in this cgroup */
-	shrink = 1;
 	while (nr_retries && res_counter_read_u64(&memcg->res, RES_USAGE) > 0) {
 		int progress;
 
-		if (signal_pending(current)) {
-			ret = -EINTR;
-			goto out;
-		}
+		if (signal_pending(current))
+			return -EINTR;
+
 		progress = try_to_free_mem_cgroup_pages(memcg, GFP_KERNEL,
 						false);
 		if (!progress) {
@@ -3841,13 +4750,23 @@ try_to_free:
 
 	}
 	lru_add_drain();
-	/* try move_account...there may be some *locked* pages. */
-	goto move_account;
+	mem_cgroup_reparent_charges(memcg);
+
+	return 0;
 }
 
 static int mem_cgroup_force_empty_write(struct cgroup *cont, unsigned int event)
 {
-	return mem_cgroup_force_empty(mem_cgroup_from_cont(cont), true);
+	struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
+	int ret;
+
+	if (mem_cgroup_is_root(memcg))
+		return -EINVAL;
+	css_get(&memcg->css);
+	ret = mem_cgroup_force_empty(memcg);
+	css_put(&memcg->css);
+
+	return ret;
 }
 
 
@@ -3938,7 +4857,8 @@ static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft,
 	struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
 	char str[64];
 	u64 val;
-	int type, name, len;
+	int name, len;
+	enum res_type type;
 
 	type = MEMFILE_TYPE(cft->private);
 	name = MEMFILE_ATTR(cft->private);
@@ -3959,6 +4879,9 @@ static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft,
 		else
 			val = res_counter_read_u64(&memcg->memsw, name);
 		break;
+	case _KMEM:
+		val = res_counter_read_u64(&memcg->kmem, name);
+		break;
 	default:
 		BUG();
 	}
@@ -3966,6 +4889,125 @@ static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft,
 	len = scnprintf(str, sizeof(str), "%llu\n", (unsigned long long)val);
 	return simple_read_from_buffer(buf, nbytes, ppos, str, len);
 }
+
+static int memcg_update_kmem_limit(struct cgroup *cont, u64 val)
+{
+	int ret = -EINVAL;
+#ifdef CONFIG_MEMCG_KMEM
+	bool must_inc_static_branch = false;
+
+	struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
+	/*
+	 * For simplicity, we won't allow this to be disabled.  It also can't
+	 * be changed if the cgroup has children already, or if tasks had
+	 * already joined.
+	 *
+	 * If tasks join before we set the limit, a person looking at
+	 * kmem.usage_in_bytes will have no way to determine when it took
+	 * place, which makes the value quite meaningless.
+	 *
+	 * After it first became limited, changes in the value of the limit are
+	 * of course permitted.
+	 *
+	 * Taking the cgroup_lock is really offensive, but it is so far the only
+	 * way to guarantee that no children will appear. There are plenty of
+	 * other offenders, and they should all go away. Fine grained locking
+	 * is probably the way to go here. When we are fully hierarchical, we
+	 * can also get rid of the use_hierarchy check.
+	 */
+	cgroup_lock();
+	mutex_lock(&set_limit_mutex);
+	if (!memcg->kmem_account_flags && val != RESOURCE_MAX) {
+		if (cgroup_task_count(cont) || (memcg->use_hierarchy &&
+						!list_empty(&cont->children))) {
+			ret = -EBUSY;
+			goto out;
+		}
+		ret = res_counter_set_limit(&memcg->kmem, val);
+		VM_BUG_ON(ret);
+
+		ret = memcg_update_cache_sizes(memcg);
+		if (ret) {
+			res_counter_set_limit(&memcg->kmem, RESOURCE_MAX);
+			goto out;
+		}
+		must_inc_static_branch = true;
+		/*
+		 * kmem charges can outlive the cgroup. In the case of slab
+		 * pages, for instance, a page contain objects from various
+		 * processes, so it is unfeasible to migrate them away. We
+		 * need to reference count the memcg because of that.
+		 */
+		mem_cgroup_get(memcg);
+	} else
+		ret = res_counter_set_limit(&memcg->kmem, val);
+out:
+	mutex_unlock(&set_limit_mutex);
+	cgroup_unlock();
+
+	/*
+	 * We are by now familiar with the fact that we can't inc the static
+	 * branch inside cgroup_lock. See disarm functions for details. A
+	 * worker here is overkill, but also wrong: After the limit is set, we
+	 * must start accounting right away. Since this operation can't fail,
+	 * we can safely defer it to here - no rollback will be needed.
+	 *
+	 * The boolean used to control this is also safe, because
+	 * KMEM_ACCOUNTED_ACTIVATED guarantees that only one process will be
+	 * able to set it to true;
+	 */
+	if (must_inc_static_branch) {
+		static_key_slow_inc(&memcg_kmem_enabled_key);
+		/*
+		 * setting the active bit after the inc will guarantee no one
+		 * starts accounting before all call sites are patched
+		 */
+		memcg_kmem_set_active(memcg);
+	}
+
+#endif
+	return ret;
+}
+
+static int memcg_propagate_kmem(struct mem_cgroup *memcg)
+{
+	int ret = 0;
+	struct mem_cgroup *parent = parent_mem_cgroup(memcg);
+	if (!parent)
+		goto out;
+
+	memcg->kmem_account_flags = parent->kmem_account_flags;
+#ifdef CONFIG_MEMCG_KMEM
+	/*
+	 * When that happen, we need to disable the static branch only on those
+	 * memcgs that enabled it. To achieve this, we would be forced to
+	 * complicate the code by keeping track of which memcgs were the ones
+	 * that actually enabled limits, and which ones got it from its
+	 * parents.
+	 *
+	 * It is a lot simpler just to do static_key_slow_inc() on every child
+	 * that is accounted.
+	 */
+	if (!memcg_kmem_is_active(memcg))
+		goto out;
+
+	/*
+	 * destroy(), called if we fail, will issue static_key_slow_inc() and
+	 * mem_cgroup_put() if kmem is enabled. We have to either call them
+	 * unconditionally, or clear the KMEM_ACTIVE flag. I personally find
+	 * this more consistent, since it always leads to the same destroy path
+	 */
+	mem_cgroup_get(memcg);
+	static_key_slow_inc(&memcg_kmem_enabled_key);
+
+	mutex_lock(&set_limit_mutex);
+	ret = memcg_update_cache_sizes(memcg);
+	mutex_unlock(&set_limit_mutex);
+#endif
+out:
+	return ret;
+}
+
 /*
  * The user of this function is...
  * RES_LIMIT.
@@ -3974,7 +5016,8 @@ static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
 			    const char *buffer)
 {
 	struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
-	int type, name;
+	enum res_type type;
+	int name;
 	unsigned long long val;
 	int ret;
 
@@ -3996,8 +5039,12 @@ static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
 			break;
 		if (type == _MEM)
 			ret = mem_cgroup_resize_limit(memcg, val);
-		else
+		else if (type == _MEMSWAP)
 			ret = mem_cgroup_resize_memsw_limit(memcg, val);
+		else if (type == _KMEM)
+			ret = memcg_update_kmem_limit(cont, val);
+		else
+			return -EINVAL;
 		break;
 	case RES_SOFT_LIMIT:
 		ret = res_counter_memparse_write_strategy(buffer, &val);
@@ -4050,7 +5097,8 @@ out:
 static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
 {
 	struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
-	int type, name;
+	int name;
+	enum res_type type;
 
 	type = MEMFILE_TYPE(event);
 	name = MEMFILE_ATTR(event);
@@ -4062,14 +5110,22 @@ static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
 	case RES_MAX_USAGE:
 		if (type == _MEM)
 			res_counter_reset_max(&memcg->res);
-		else
+		else if (type == _MEMSWAP)
 			res_counter_reset_max(&memcg->memsw);
+		else if (type == _KMEM)
+			res_counter_reset_max(&memcg->kmem);
+		else
+			return -EINVAL;
 		break;
 	case RES_FAILCNT:
 		if (type == _MEM)
 			res_counter_reset_failcnt(&memcg->res);
-		else
+		else if (type == _MEMSWAP)
 			res_counter_reset_failcnt(&memcg->memsw);
+		else if (type == _KMEM)
+			res_counter_reset_failcnt(&memcg->kmem);
+		else
+			return -EINVAL;
 		break;
 	}
 
@@ -4120,7 +5176,7 @@ static int memcg_numa_stat_show(struct cgroup *cont, struct cftype *cft,
 
 	total_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL);
 	seq_printf(m, "total=%lu", total_nr);
-	for_each_node_state(nid, N_HIGH_MEMORY) {
+	for_each_node_state(nid, N_MEMORY) {
 		node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid, LRU_ALL);
 		seq_printf(m, " N%d=%lu", nid, node_nr);
 	}
@@ -4128,7 +5184,7 @@ static int memcg_numa_stat_show(struct cgroup *cont, struct cftype *cft,
 
 	file_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL_FILE);
 	seq_printf(m, "file=%lu", file_nr);
-	for_each_node_state(nid, N_HIGH_MEMORY) {
+	for_each_node_state(nid, N_MEMORY) {
 		node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
 				LRU_ALL_FILE);
 		seq_printf(m, " N%d=%lu", nid, node_nr);
@@ -4137,7 +5193,7 @@ static int memcg_numa_stat_show(struct cgroup *cont, struct cftype *cft,
 
 	anon_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL_ANON);
 	seq_printf(m, "anon=%lu", anon_nr);
-	for_each_node_state(nid, N_HIGH_MEMORY) {
+	for_each_node_state(nid, N_MEMORY) {
 		node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
 				LRU_ALL_ANON);
 		seq_printf(m, " N%d=%lu", nid, node_nr);
@@ -4146,7 +5202,7 @@ static int memcg_numa_stat_show(struct cgroup *cont, struct cftype *cft,
 
 	unevictable_nr = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_UNEVICTABLE));
 	seq_printf(m, "unevictable=%lu", unevictable_nr);
-	for_each_node_state(nid, N_HIGH_MEMORY) {
+	for_each_node_state(nid, N_MEMORY) {
 		node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
 				BIT(LRU_UNEVICTABLE));
 		seq_printf(m, " N%d=%lu", nid, node_nr);
@@ -4386,7 +5442,7 @@ static int mem_cgroup_usage_register_event(struct cgroup *cgrp,
 	struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
 	struct mem_cgroup_thresholds *thresholds;
 	struct mem_cgroup_threshold_ary *new;
-	int type = MEMFILE_TYPE(cft->private);
+	enum res_type type = MEMFILE_TYPE(cft->private);
 	u64 threshold, usage;
 	int i, size, ret;
 
@@ -4469,7 +5525,7 @@ static void mem_cgroup_usage_unregister_event(struct cgroup *cgrp,
 	struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
 	struct mem_cgroup_thresholds *thresholds;
 	struct mem_cgroup_threshold_ary *new;
-	int type = MEMFILE_TYPE(cft->private);
+	enum res_type type = MEMFILE_TYPE(cft->private);
 	u64 usage;
 	int i, j, size;
 
@@ -4547,7 +5603,7 @@ static int mem_cgroup_oom_register_event(struct cgroup *cgrp,
 {
 	struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
 	struct mem_cgroup_eventfd_list *event;
-	int type = MEMFILE_TYPE(cft->private);
+	enum res_type type = MEMFILE_TYPE(cft->private);
 
 	BUG_ON(type != _OOM_TYPE);
 	event = kmalloc(sizeof(*event),	GFP_KERNEL);
@@ -4572,7 +5628,7 @@ static void mem_cgroup_oom_unregister_event(struct cgroup *cgrp,
 {
 	struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
 	struct mem_cgroup_eventfd_list *ev, *tmp;
-	int type = MEMFILE_TYPE(cft->private);
+	enum res_type type = MEMFILE_TYPE(cft->private);
 
 	BUG_ON(type != _OOM_TYPE);
 
@@ -4631,12 +5687,33 @@ static int mem_cgroup_oom_control_write(struct cgroup *cgrp,
 #ifdef CONFIG_MEMCG_KMEM
 static int memcg_init_kmem(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
 {
+	int ret;
+
+	memcg->kmemcg_id = -1;
+	ret = memcg_propagate_kmem(memcg);
+	if (ret)
+		return ret;
+
 	return mem_cgroup_sockets_init(memcg, ss);
 };
 
 static void kmem_cgroup_destroy(struct mem_cgroup *memcg)
 {
 	mem_cgroup_sockets_destroy(memcg);
+
+	memcg_kmem_mark_dead(memcg);
+
+	if (res_counter_read_u64(&memcg->kmem, RES_USAGE) != 0)
+		return;
+
+	/*
+	 * Charges already down to 0, undo mem_cgroup_get() done in the charge
+	 * path here, being careful not to race with memcg_uncharge_kmem: it is
+	 * possible that the charges went down to 0 between mark_dead and the
+	 * res_counter read, so in that case, we don't need the put
+	 */
+	if (memcg_kmem_test_and_clear_dead(memcg))
+		mem_cgroup_put(memcg);
 }
 #else
 static int memcg_init_kmem(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
@@ -4745,6 +5822,37 @@ static struct cftype mem_cgroup_files[] = {
 		.read = mem_cgroup_read,
 	},
 #endif
+#ifdef CONFIG_MEMCG_KMEM
+	{
+		.name = "kmem.limit_in_bytes",
+		.private = MEMFILE_PRIVATE(_KMEM, RES_LIMIT),
+		.write_string = mem_cgroup_write,
+		.read = mem_cgroup_read,
+	},
+	{
+		.name = "kmem.usage_in_bytes",
+		.private = MEMFILE_PRIVATE(_KMEM, RES_USAGE),
+		.read = mem_cgroup_read,
+	},
+	{
+		.name = "kmem.failcnt",
+		.private = MEMFILE_PRIVATE(_KMEM, RES_FAILCNT),
+		.trigger = mem_cgroup_reset,
+		.read = mem_cgroup_read,
+	},
+	{
+		.name = "kmem.max_usage_in_bytes",
+		.private = MEMFILE_PRIVATE(_KMEM, RES_MAX_USAGE),
+		.trigger = mem_cgroup_reset,
+		.read = mem_cgroup_read,
+	},
+#ifdef CONFIG_SLABINFO
+	{
+		.name = "kmem.slabinfo",
+		.read_seq_string = mem_cgroup_slabinfo_read,
+	},
+#endif
+#endif
 	{ },	/* terminate */
 };
 
@@ -4812,16 +5920,29 @@ out_free:
 }
 
 /*
- * Helpers for freeing a kmalloc()ed/vzalloc()ed mem_cgroup by RCU,
- * but in process context.  The work_freeing structure is overlaid
- * on the rcu_freeing structure, which itself is overlaid on memsw.
+ * At destroying mem_cgroup, references from swap_cgroup can remain.
+ * (scanning all at force_empty is too costly...)
+ *
+ * Instead of clearing all references at force_empty, we remember
+ * the number of reference from swap_cgroup and free mem_cgroup when
+ * it goes down to 0.
+ *
+ * Removal of cgroup itself succeeds regardless of refs from swap.
  */
-static void free_work(struct work_struct *work)
+
+static void __mem_cgroup_free(struct mem_cgroup *memcg)
 {
-	struct mem_cgroup *memcg;
+	int node;
 	int size = sizeof(struct mem_cgroup);
 
-	memcg = container_of(work, struct mem_cgroup, work_freeing);
+	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);
+
+	free_percpu(memcg->stat);
+
 	/*
 	 * We need to make sure that (at least for now), the jump label
 	 * destruction code runs outside of the cgroup lock. This is because
@@ -4833,45 +5954,34 @@ static void free_work(struct work_struct *work)
 	 * to move this code around, and make sure it is outside
 	 * the cgroup_lock.
 	 */
-	disarm_sock_keys(memcg);
+	disarm_static_keys(memcg);
 	if (size < PAGE_SIZE)
 		kfree(memcg);
 	else
 		vfree(memcg);
 }
 
-static void free_rcu(struct rcu_head *rcu_head)
-{
-	struct mem_cgroup *memcg;
-
-	memcg = container_of(rcu_head, struct mem_cgroup, rcu_freeing);
-	INIT_WORK(&memcg->work_freeing, free_work);
-	schedule_work(&memcg->work_freeing);
-}
 
 /*
- * At destroying mem_cgroup, references from swap_cgroup can remain.
- * (scanning all at force_empty is too costly...)
- *
- * Instead of clearing all references at force_empty, we remember
- * the number of reference from swap_cgroup and free mem_cgroup when
- * it goes down to 0.
- *
- * Removal of cgroup itself succeeds regardless of refs from swap.
+ * Helpers for freeing a kmalloc()ed/vzalloc()ed mem_cgroup by RCU,
+ * but in process context.  The work_freeing structure is overlaid
+ * on the rcu_freeing structure, which itself is overlaid on memsw.
  */
-
-static void __mem_cgroup_free(struct mem_cgroup *memcg)
+static void free_work(struct work_struct *work)
 {
-	int node;
+	struct mem_cgroup *memcg;
 
-	mem_cgroup_remove_from_trees(memcg);
-	free_css_id(&mem_cgroup_subsys, &memcg->css);
+	memcg = container_of(work, struct mem_cgroup, work_freeing);
+	__mem_cgroup_free(memcg);
+}
 
-	for_each_node(node)
-		free_mem_cgroup_per_zone_info(memcg, node);
+static void free_rcu(struct rcu_head *rcu_head)
+{
+	struct mem_cgroup *memcg;
 
-	free_percpu(memcg->stat);
-	call_rcu(&memcg->rcu_freeing, free_rcu);
+	memcg = container_of(rcu_head, struct mem_cgroup, rcu_freeing);
+	INIT_WORK(&memcg->work_freeing, free_work);
+	schedule_work(&memcg->work_freeing);
 }
 
 static void mem_cgroup_get(struct mem_cgroup *memcg)
@@ -4883,7 +5993,7 @@ static void __mem_cgroup_put(struct mem_cgroup *memcg, int count)
 {
 	if (atomic_sub_and_test(count, &memcg->refcnt)) {
 		struct mem_cgroup *parent = parent_mem_cgroup(memcg);
-		__mem_cgroup_free(memcg);
+		call_rcu(&memcg->rcu_freeing, free_rcu);
 		if (parent)
 			mem_cgroup_put(parent);
 	}
@@ -4953,7 +6063,7 @@ err_cleanup:
 }
 
 static struct cgroup_subsys_state * __ref
-mem_cgroup_create(struct cgroup *cont)
+mem_cgroup_css_alloc(struct cgroup *cont)
 {
 	struct mem_cgroup *memcg, *parent;
 	long error = -ENOMEM;
@@ -4990,6 +6100,8 @@ mem_cgroup_create(struct cgroup *cont)
 	if (parent && parent->use_hierarchy) {
 		res_counter_init(&memcg->res, &parent->res);
 		res_counter_init(&memcg->memsw, &parent->memsw);
+		res_counter_init(&memcg->kmem, &parent->kmem);
+
 		/*
 		 * We increment refcnt of the parent to ensure that we can
 		 * safely access it on res_counter_charge/uncharge.
@@ -5000,6 +6112,7 @@ mem_cgroup_create(struct cgroup *cont)
 	} else {
 		res_counter_init(&memcg->res, NULL);
 		res_counter_init(&memcg->memsw, NULL);
+		res_counter_init(&memcg->kmem, NULL);
 		/*
 		 * Deeper hierachy with use_hierarchy == false doesn't make
 		 * much sense so let cgroup subsystem know about this
@@ -5034,14 +6147,15 @@ free_out:
 	return ERR_PTR(error);
 }
 
-static int mem_cgroup_pre_destroy(struct cgroup *cont)
+static void mem_cgroup_css_offline(struct cgroup *cont)
 {
 	struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
 
-	return mem_cgroup_force_empty(memcg, false);
+	mem_cgroup_reparent_charges(memcg);
+	mem_cgroup_destroy_all_caches(memcg);
 }
 
-static void mem_cgroup_destroy(struct cgroup *cont)
+static void mem_cgroup_css_free(struct cgroup *cont)
 {
 	struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
 
@@ -5631,16 +6745,15 @@ static void mem_cgroup_move_task(struct cgroup *cont,
 struct cgroup_subsys mem_cgroup_subsys = {
 	.name = "memory",
 	.subsys_id = mem_cgroup_subsys_id,
-	.create = mem_cgroup_create,
-	.pre_destroy = mem_cgroup_pre_destroy,
-	.destroy = mem_cgroup_destroy,
+	.css_alloc = mem_cgroup_css_alloc,
+	.css_offline = mem_cgroup_css_offline,
+	.css_free = mem_cgroup_css_free,
 	.can_attach = mem_cgroup_can_attach,
 	.cancel_attach = mem_cgroup_cancel_attach,
 	.attach = mem_cgroup_move_task,
 	.base_cftypes = mem_cgroup_files,
 	.early_init = 0,
 	.use_id = 1,
-	.__DEPRECATED_clear_css_refs = true,
 };
 
 #ifdef CONFIG_MEMCG_SWAP
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 6c5899b..108c52f 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -781,16 +781,16 @@ static struct page_state {
 	{ compound,	compound,	"huge",		me_huge_page },
 #endif
 
-	{ sc|dirty,	sc|dirty,	"swapcache",	me_swapcache_dirty },
-	{ sc|dirty,	sc,		"swapcache",	me_swapcache_clean },
+	{ sc|dirty,	sc|dirty,	"dirty swapcache",	me_swapcache_dirty },
+	{ sc|dirty,	sc,		"clean swapcache",	me_swapcache_clean },
 
-	{ unevict|dirty, unevict|dirty,	"unevictable LRU", me_pagecache_dirty},
-	{ unevict,	unevict,	"unevictable LRU", me_pagecache_clean},
+	{ unevict|dirty, unevict|dirty,	"dirty unevictable LRU", me_pagecache_dirty },
+	{ unevict,	unevict,	"clean unevictable LRU", me_pagecache_clean },
 
-	{ mlock|dirty,	mlock|dirty,	"mlocked LRU",	me_pagecache_dirty },
-	{ mlock,	mlock,		"mlocked LRU",	me_pagecache_clean },
+	{ mlock|dirty,	mlock|dirty,	"dirty mlocked LRU",	me_pagecache_dirty },
+	{ mlock,	mlock,		"clean mlocked LRU",	me_pagecache_clean },
 
-	{ lru|dirty,	lru|dirty,	"LRU",		me_pagecache_dirty },
+	{ lru|dirty,	lru|dirty,	"dirty LRU",	me_pagecache_dirty },
 	{ lru|dirty,	lru,		"clean LRU",	me_pagecache_clean },
 
 	/*
@@ -812,14 +812,14 @@ static struct page_state {
 #undef slab
 #undef reserved
 
+/*
+ * "Dirty/Clean" indication is not 100% accurate due to the possibility of
+ * setting PG_dirty outside page lock. See also comment above set_page_dirty().
+ */
 static void action_result(unsigned long pfn, char *msg, int result)
 {
-	struct page *page = pfn_to_page(pfn);
-
-	printk(KERN_ERR "MCE %#lx: %s%s page recovery: %s\n",
-		pfn,
-		PageDirty(page) ? "dirty " : "",
-		msg, action_name[result]);
+	pr_err("MCE %#lx: %s page recovery: %s\n",
+		pfn, msg, action_name[result]);
 }
 
 static int page_action(struct page_state *ps, struct page *p,
@@ -1385,7 +1385,7 @@ static int get_any_page(struct page *p, unsigned long pfn, int flags)
 	 * Isolate the page, so that it doesn't get reallocated if it
 	 * was free.
 	 */
-	set_migratetype_isolate(p);
+	set_migratetype_isolate(p, true);
 	/*
 	 * When the target page is a free hugepage, just remove it
 	 * from free hugepage list.
@@ -1476,9 +1476,17 @@ int soft_offline_page(struct page *page, int flags)
 {
 	int ret;
 	unsigned long pfn = page_to_pfn(page);
+	struct page *hpage = compound_trans_head(page);
 
 	if (PageHuge(page))
 		return soft_offline_huge_page(page, flags);
+	if (PageTransHuge(hpage)) {
+		if (PageAnon(hpage) && unlikely(split_huge_page(hpage))) {
+			pr_info("soft offline: %#lx: failed to split THP\n",
+				pfn);
+			return -EBUSY;
+		}
+	}
 
 	ret = get_any_page(page, pfn, flags);
 	if (ret < 0)
diff --git a/mm/memory.c b/mm/memory.c
index 221fc9f..3db03ed 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -36,6 +36,8 @@
  *		(Gerhard.Wichert@pdb.siemens.de)
  *
  * Aug/Sep 2004 Changed to four level page tables (Andi Kleen)
+ *
+ * 2012 - NUMA placement page faults (Andrea Arcangeli, Peter Zijlstra)
  */
 
 #include <linux/kernel_stat.h>
@@ -57,6 +59,8 @@
 #include <linux/swapops.h>
 #include <linux/elf.h>
 #include <linux/gfp.h>
+#include <linux/migrate.h>
+#include <linux/string.h>
 
 #include <asm/io.h>
 #include <asm/pgalloc.h>
@@ -67,6 +71,10 @@
 
 #include "internal.h"
 
+#ifdef LAST_CPU_NOT_IN_PAGE_FLAGS
+#warning Unfortunate NUMA config, growing page-frame for last_cpu.
+#endif
+
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 /* use the per-pgdat data instead for discontigmem - mbligh */
 unsigned long max_mapnr;
@@ -724,13 +732,6 @@ static inline int is_zero_pfn(unsigned long pfn)
 }
 #endif
 
-#ifndef my_zero_pfn
-static inline unsigned long my_zero_pfn(unsigned long addr)
-{
-	return zero_pfn;
-}
-#endif
-
 /*
  * vm_normal_page -- This function gets the "struct page" associated with a pte.
  *
@@ -1250,7 +1251,7 @@ static inline unsigned long zap_pmd_range(struct mmu_gather *tlb,
 					BUG();
 				}
 #endif
-				split_huge_page_pmd(vma->vm_mm, pmd);
+				split_huge_page_pmd(vma, addr, pmd);
 			} else if (zap_huge_pmd(tlb, vma, pmd, addr))
 				goto next;
 			/* fall through */
@@ -1517,9 +1518,11 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
 		page = follow_huge_pmd(mm, address, pmd, flags & FOLL_WRITE);
 		goto out;
 	}
+	if ((flags & FOLL_NUMA) && pmd_numa(vma, *pmd))
+		goto no_page_table;
 	if (pmd_trans_huge(*pmd)) {
 		if (flags & FOLL_SPLIT) {
-			split_huge_page_pmd(mm, pmd);
+			split_huge_page_pmd(vma, address, pmd);
 			goto split_fallthrough;
 		}
 		spin_lock(&mm->page_table_lock);
@@ -1546,6 +1549,8 @@ split_fallthrough:
 	pte = *ptep;
 	if (!pte_present(pte))
 		goto no_page;
+	if ((flags & FOLL_NUMA) && pte_numa(vma, pte))
+		goto no_page;
 	if ((flags & FOLL_WRITE) && !pte_write(pte))
 		goto unlock;
 
@@ -1697,6 +1702,19 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 			(VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
 	vm_flags &= (gup_flags & FOLL_FORCE) ?
 			(VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
+
+	/*
+	 * If FOLL_FORCE and FOLL_NUMA are both set, handle_mm_fault
+	 * would be called on PROT_NONE ranges. We must never invoke
+	 * handle_mm_fault on PROT_NONE ranges or the NUMA hinting
+	 * page faults would unprotect the PROT_NONE ranges if
+	 * _PAGE_NUMA and _PAGE_PROTNONE are sharing the same pte/pmd
+	 * bitflag. So to avoid that, don't set FOLL_NUMA if
+	 * FOLL_FORCE is set.
+	 */
+	if (!(gup_flags & FOLL_FORCE))
+		gup_flags |= FOLL_NUMA;
+
 	i = 0;
 
 	do {
@@ -2966,7 +2984,8 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
 		ret = VM_FAULT_HWPOISON;
 		delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
 		goto out_release;
-	}
+	} else if (!(flags & FAULT_FLAG_TRIED))
+		swap_cache_hit(vma);
 
 	locked = lock_page_or_retry(page, mm, flags);
 
@@ -3431,6 +3450,66 @@ static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 	return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte);
 }
 
+static int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
+			unsigned long address, pte_t *ptep, pmd_t *pmd,
+			unsigned int flags, pte_t entry)
+{
+	struct page *page = NULL;
+	int node, page_nid = -1;
+	int last_cpu = -1;
+	spinlock_t *ptl;
+
+	ptl = pte_lockptr(mm, pmd);
+	spin_lock(ptl);
+	if (unlikely(!pte_same(*ptep, entry)))
+		goto out_unlock;
+
+	page = vm_normal_page(vma, address, entry);
+	if (page) {
+		get_page(page);
+		page_nid = page_to_nid(page);
+		last_cpu = page_last_cpu(page);
+		node = mpol_misplaced(page, vma, address);
+		if (node != -1 && node != page_nid)
+			goto migrate;
+	}
+
+out_pte_upgrade_unlock:
+	flush_cache_page(vma, address, pte_pfn(entry));
+
+	ptep_modify_prot_start(mm, address, ptep);
+	entry = pte_modify(entry, vma->vm_page_prot);
+	ptep_modify_prot_commit(mm, address, ptep, entry);
+
+	/* No TLB flush needed because we upgraded the PTE */
+
+	update_mmu_cache(vma, address, ptep);
+
+out_unlock:
+	pte_unmap_unlock(ptep, ptl);
+
+	if (page) {
+		task_numa_fault(page_nid, last_cpu, 1);
+		put_page(page);
+	}
+out:
+	return 0;
+
+migrate:
+	pte_unmap_unlock(ptep, ptl);
+
+	if (migrate_misplaced_page(page, node)) {
+		goto out;
+	}
+	page = NULL;
+
+	ptep = pte_offset_map_lock(mm, pmd, address, &ptl);
+	if (!pte_same(*ptep, entry))
+		goto out_unlock;
+
+	goto out_pte_upgrade_unlock;
+}
+
 /*
  * These routines also need to handle stuff like marking pages dirty
  * and/or accessed for architectures that don't do it in hardware (most
@@ -3451,7 +3530,7 @@ int handle_pte_fault(struct mm_struct *mm,
 	pte_t entry;
 	spinlock_t *ptl;
 
-	entry = *pte;
+	entry = ACCESS_ONCE(*pte);
 	if (!pte_present(entry)) {
 		if (pte_none(entry)) {
 			if (vma->vm_ops) {
@@ -3469,6 +3548,9 @@ int handle_pte_fault(struct mm_struct *mm,
 					pte, pmd, flags, entry);
 	}
 
+	if (pte_numa(vma, entry))
+		return do_numa_page(mm, vma, address, pte, pmd, flags, entry);
+
 	ptl = pte_lockptr(mm, pmd);
 	spin_lock(ptl);
 	if (unlikely(!pte_same(*pte, entry)))
@@ -3533,13 +3615,18 @@ retry:
 							  pmd, flags);
 	} else {
 		pmd_t orig_pmd = *pmd;
-		int ret;
+		int ret = 0;
 
 		barrier();
-		if (pmd_trans_huge(orig_pmd)) {
-			if (flags & FAULT_FLAG_WRITE &&
-			    !pmd_write(orig_pmd) &&
-			    !pmd_trans_splitting(orig_pmd)) {
+		if (pmd_trans_huge(orig_pmd) && !pmd_trans_splitting(orig_pmd)) {
+			unsigned int dirty = flags & FAULT_FLAG_WRITE;
+
+			if (pmd_numa(vma, orig_pmd)) {
+				do_huge_pmd_numa_page(mm, vma, address, pmd,
+						      flags, orig_pmd);
+			}
+
+			if (dirty && !pmd_write(orig_pmd)) {
 				ret = do_huge_pmd_wp_page(mm, vma, address, pmd,
 							  orig_pmd);
 				/*
@@ -3549,18 +3636,23 @@ retry:
 				 */
 				if (unlikely(ret & VM_FAULT_OOM))
 					goto retry;
-				return ret;
+			} else {
+				huge_pmd_set_accessed(mm, vma, address, pmd,
+						      orig_pmd, dirty);
 			}
-			return 0;
+
+			return ret;
 		}
 	}
 
+
 	/*
 	 * Use __pte_alloc instead of pte_alloc_map, because we can't
 	 * run pte_offset_map on the pmd, if an huge pmd could
 	 * materialize from under us from a different thread.
 	 */
-	if (unlikely(pmd_none(*pmd)) && __pte_alloc(mm, vma, pmd, address))
+	if (unlikely(pmd_none(*pmd)) &&
+	    unlikely(__pte_alloc(mm, vma, pmd, address)))
 		return VM_FAULT_OOM;
 	/* if an huge pmd materialized from under us just retry later */
 	if (unlikely(pmd_trans_huge(*pmd)))
@@ -3940,15 +4032,12 @@ void print_vma_addr(char *prefix, unsigned long ip)
 		struct file *f = vma->vm_file;
 		char *buf = (char *)__get_free_page(GFP_KERNEL);
 		if (buf) {
-			char *p, *s;
+			char *p;
 
 			p = d_path(&f->f_path, buf, PAGE_SIZE);
 			if (IS_ERR(p))
 				p = "?";
-			s = strrchr(p, '/');
-			if (s)
-				p = s+1;
-			printk("%s%s[%lx+%lx]", prefix, p,
+			printk("%s%s[%lx+%lx]", prefix, kbasename(p),
 					vma->vm_start,
 					vma->vm_end - vma->vm_start);
 			free_page((unsigned long)buf);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index e4eeaca..ea71d0d 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -106,6 +106,7 @@ static void get_page_bootmem(unsigned long info,  struct page *page,
 void __ref put_page_bootmem(struct page *page)
 {
 	unsigned long type;
+	static DEFINE_MUTEX(ppb_lock);
 
 	type = (unsigned long) page->lru.next;
 	BUG_ON(type < MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE ||
@@ -115,7 +116,14 @@ void __ref put_page_bootmem(struct page *page)
 		ClearPagePrivate(page);
 		set_page_private(page, 0);
 		INIT_LIST_HEAD(&page->lru);
+
+		/*
+		 * Please refer to comment for __free_pages_bootmem()
+		 * for why we serialize here.
+		 */
+		mutex_lock(&ppb_lock);
 		__free_pages_bootmem(page, 0);
+		mutex_unlock(&ppb_lock);
 	}
 
 }
@@ -205,7 +213,7 @@ static void grow_zone_span(struct zone *zone, unsigned long start_pfn,
 	zone_span_writelock(zone);
 
 	old_zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
-	if (start_pfn < zone->zone_start_pfn)
+	if (!zone->spanned_pages || start_pfn < zone->zone_start_pfn)
 		zone->zone_start_pfn = start_pfn;
 
 	zone->spanned_pages = max(old_zone_end_pfn, end_pfn) -
@@ -214,13 +222,134 @@ static void grow_zone_span(struct zone *zone, unsigned long start_pfn,
 	zone_span_writeunlock(zone);
 }
 
+static void resize_zone(struct zone *zone, unsigned long start_pfn,
+		unsigned long end_pfn)
+{
+	zone_span_writelock(zone);
+
+	if (end_pfn - start_pfn) {
+		zone->zone_start_pfn = start_pfn;
+		zone->spanned_pages = end_pfn - start_pfn;
+	} else {
+		/*
+		 * make it consist as free_area_init_core(),
+		 * if spanned_pages = 0, then keep start_pfn = 0
+		 */
+		zone->zone_start_pfn = 0;
+		zone->spanned_pages = 0;
+	}
+
+	zone_span_writeunlock(zone);
+}
+
+static void fix_zone_id(struct zone *zone, unsigned long start_pfn,
+		unsigned long end_pfn)
+{
+	enum zone_type zid = zone_idx(zone);
+	int nid = zone->zone_pgdat->node_id;
+	unsigned long pfn;
+
+	for (pfn = start_pfn; pfn < end_pfn; pfn++)
+		set_page_links(pfn_to_page(pfn), zid, nid, pfn);
+}
+
+static int __meminit move_pfn_range_left(struct zone *z1, struct zone *z2,
+		unsigned long start_pfn, unsigned long end_pfn)
+{
+	int ret;
+	unsigned long flags;
+	unsigned long z1_start_pfn;
+
+	if (!z1->wait_table) {
+		ret = init_currently_empty_zone(z1, start_pfn,
+			end_pfn - start_pfn, MEMMAP_HOTPLUG);
+		if (ret)
+			return ret;
+	}
+
+	pgdat_resize_lock(z1->zone_pgdat, &flags);
+
+	/* can't move pfns which are higher than @z2 */
+	if (end_pfn > z2->zone_start_pfn + z2->spanned_pages)
+		goto out_fail;
+	/* the move out part mast at the left most of @z2 */
+	if (start_pfn > z2->zone_start_pfn)
+		goto out_fail;
+	/* must included/overlap */
+	if (end_pfn <= z2->zone_start_pfn)
+		goto out_fail;
+
+	/* use start_pfn for z1's start_pfn if z1 is empty */
+	if (z1->spanned_pages)
+		z1_start_pfn = z1->zone_start_pfn;
+	else
+		z1_start_pfn = start_pfn;
+
+	resize_zone(z1, z1_start_pfn, end_pfn);
+	resize_zone(z2, end_pfn, z2->zone_start_pfn + z2->spanned_pages);
+
+	pgdat_resize_unlock(z1->zone_pgdat, &flags);
+
+	fix_zone_id(z1, start_pfn, end_pfn);
+
+	return 0;
+out_fail:
+	pgdat_resize_unlock(z1->zone_pgdat, &flags);
+	return -1;
+}
+
+static int __meminit move_pfn_range_right(struct zone *z1, struct zone *z2,
+		unsigned long start_pfn, unsigned long end_pfn)
+{
+	int ret;
+	unsigned long flags;
+	unsigned long z2_end_pfn;
+
+	if (!z2->wait_table) {
+		ret = init_currently_empty_zone(z2, start_pfn,
+			end_pfn - start_pfn, MEMMAP_HOTPLUG);
+		if (ret)
+			return ret;
+	}
+
+	pgdat_resize_lock(z1->zone_pgdat, &flags);
+
+	/* can't move pfns which are lower than @z1 */
+	if (z1->zone_start_pfn > start_pfn)
+		goto out_fail;
+	/* the move out part mast at the right most of @z1 */
+	if (z1->zone_start_pfn + z1->spanned_pages >  end_pfn)
+		goto out_fail;
+	/* must included/overlap */
+	if (start_pfn >= z1->zone_start_pfn + z1->spanned_pages)
+		goto out_fail;
+
+	/* use end_pfn for z2's end_pfn if z2 is empty */
+	if (z2->spanned_pages)
+		z2_end_pfn = z2->zone_start_pfn + z2->spanned_pages;
+	else
+		z2_end_pfn = end_pfn;
+
+	resize_zone(z1, z1->zone_start_pfn, start_pfn);
+	resize_zone(z2, start_pfn, z2_end_pfn);
+
+	pgdat_resize_unlock(z1->zone_pgdat, &flags);
+
+	fix_zone_id(z2, start_pfn, end_pfn);
+
+	return 0;
+out_fail:
+	pgdat_resize_unlock(z1->zone_pgdat, &flags);
+	return -1;
+}
+
 static void grow_pgdat_span(struct pglist_data *pgdat, unsigned long start_pfn,
 			    unsigned long end_pfn)
 {
 	unsigned long old_pgdat_end_pfn =
 		pgdat->node_start_pfn + pgdat->node_spanned_pages;
 
-	if (start_pfn < pgdat->node_start_pfn)
+	if (!pgdat->node_spanned_pages || start_pfn < pgdat->node_start_pfn)
 		pgdat->node_start_pfn = start_pfn;
 
 	pgdat->node_spanned_pages = max(old_pgdat_end_pfn, end_pfn) -
@@ -460,8 +589,96 @@ static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages,
 	return 0;
 }
 
+#ifdef CONFIG_MOVABLE_NODE
+/* when CONFIG_MOVABLE_NODE, we allow online node don't have normal memory */
+static bool can_online_high_movable(struct zone *zone)
+{
+	return true;
+}
+#else /* #ifdef CONFIG_MOVABLE_NODE */
+/* ensure every online node has NORMAL memory */
+static bool can_online_high_movable(struct zone *zone)
+{
+	return node_state(zone_to_nid(zone), N_NORMAL_MEMORY);
+}
+#endif /* #ifdef CONFIG_MOVABLE_NODE */
+
+/* check which state of node_states will be changed when online memory */
+static void node_states_check_changes_online(unsigned long nr_pages,
+	struct zone *zone, struct memory_notify *arg)
+{
+	int nid = zone_to_nid(zone);
+	enum zone_type zone_last = ZONE_NORMAL;
+
+	/*
+	 * If we have HIGHMEM or movable node, node_states[N_NORMAL_MEMORY]
+	 * contains nodes which have zones of 0...ZONE_NORMAL,
+	 * set zone_last to ZONE_NORMAL.
+	 *
+	 * If we don't have HIGHMEM nor movable node,
+	 * node_states[N_NORMAL_MEMORY] contains nodes which have zones of
+	 * 0...ZONE_MOVABLE, set zone_last to ZONE_MOVABLE.
+	 */
+	if (N_MEMORY == N_NORMAL_MEMORY)
+		zone_last = ZONE_MOVABLE;
+
+	/*
+	 * if the memory to be online is in a zone of 0...zone_last, and
+	 * the zones of 0...zone_last don't have memory before online, we will
+	 * need to set the node to node_states[N_NORMAL_MEMORY] after
+	 * the memory is online.
+	 */
+	if (zone_idx(zone) <= zone_last && !node_state(nid, N_NORMAL_MEMORY))
+		arg->status_change_nid_normal = nid;
+	else
+		arg->status_change_nid_normal = -1;
+
+#ifdef CONFIG_HIGHMEM
+	/*
+	 * If we have movable node, node_states[N_HIGH_MEMORY]
+	 * contains nodes which have zones of 0...ZONE_HIGH,
+	 * set zone_last to ZONE_HIGH.
+	 *
+	 * If we don't have movable node, node_states[N_NORMAL_MEMORY]
+	 * contains nodes which have zones of 0...ZONE_MOVABLE,
+	 * set zone_last to ZONE_MOVABLE.
+	 */
+	zone_last = ZONE_HIGH;
+	if (N_MEMORY == N_HIGH_MEMORY)
+		zone_last = ZONE_MOVABLE;
+
+	if (zone_idx(zone) <= zone_last && !node_state(nid, N_HIGH_MEMORY))
+		arg->status_change_nid_high = nid;
+	else
+		arg->status_change_nid_high = -1;
+#else
+	arg->status_change_nid_high = arg->status_change_nid_normal;
+#endif
+
+	/*
+	 * if the node don't have memory befor online, we will need to
+	 * set the node to node_states[N_MEMORY] after the memory
+	 * is online.
+	 */
+	if (!node_state(nid, N_MEMORY))
+		arg->status_change_nid = nid;
+	else
+		arg->status_change_nid = -1;
+}
 
-int __ref online_pages(unsigned long pfn, unsigned long nr_pages)
+static void node_states_set_node(int node, struct memory_notify *arg)
+{
+	if (arg->status_change_nid_normal >= 0)
+		node_set_state(node, N_NORMAL_MEMORY);
+
+	if (arg->status_change_nid_high >= 0)
+		node_set_state(node, N_HIGH_MEMORY);
+
+	node_set_state(node, N_MEMORY);
+}
+
+
+int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_type)
 {
 	unsigned long onlined_pages = 0;
 	struct zone *zone;
@@ -471,13 +688,40 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages)
 	struct memory_notify arg;
 
 	lock_memory_hotplug();
+	/*
+	 * This doesn't need a lock to do pfn_to_page().
+	 * The section can't be removed here because of the
+	 * memory_block->state_mutex.
+	 */
+	zone = page_zone(pfn_to_page(pfn));
+
+	if ((zone_idx(zone) > ZONE_NORMAL || online_type == ONLINE_MOVABLE) &&
+	    !can_online_high_movable(zone)) {
+		unlock_memory_hotplug();
+		return -1;
+	}
+
+	if (online_type == ONLINE_KERNEL && zone_idx(zone) == ZONE_MOVABLE) {
+		if (move_pfn_range_left(zone - 1, zone, pfn, pfn + nr_pages)) {
+			unlock_memory_hotplug();
+			return -1;
+		}
+	}
+	if (online_type == ONLINE_MOVABLE && zone_idx(zone) == ZONE_MOVABLE - 1) {
+		if (move_pfn_range_right(zone, zone + 1, pfn, pfn + nr_pages)) {
+			unlock_memory_hotplug();
+			return -1;
+		}
+	}
+
+	/* Previous code may changed the zone of the pfn range */
+	zone = page_zone(pfn_to_page(pfn));
+
 	arg.start_pfn = pfn;
 	arg.nr_pages = nr_pages;
-	arg.status_change_nid = -1;
+	node_states_check_changes_online(nr_pages, zone, &arg);
 
 	nid = page_to_nid(pfn_to_page(pfn));
-	if (node_present_pages(nid) == 0)
-		arg.status_change_nid = nid;
 
 	ret = memory_notify(MEM_GOING_ONLINE, &arg);
 	ret = notifier_to_errno(ret);
@@ -487,23 +731,21 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages)
 		return ret;
 	}
 	/*
-	 * This doesn't need a lock to do pfn_to_page().
-	 * The section can't be removed here because of the
-	 * memory_block->state_mutex.
-	 */
-	zone = page_zone(pfn_to_page(pfn));
-	/*
 	 * If this zone is not populated, then it is not in zonelist.
 	 * This means the page allocator ignores this zone.
 	 * So, zonelist must be updated after online.
 	 */
 	mutex_lock(&zonelists_mutex);
-	if (!populated_zone(zone))
+	if (!populated_zone(zone)) {
 		need_zonelists_rebuild = 1;
+		build_all_zonelists(NULL, zone);
+	}
 
 	ret = walk_system_ram_range(pfn, nr_pages, &onlined_pages,
 		online_pages_range);
 	if (ret) {
+		if (need_zonelists_rebuild)
+			zone_pcp_reset(zone);
 		mutex_unlock(&zonelists_mutex);
 		printk(KERN_DEBUG "online_pages [mem %#010llx-%#010llx] failed\n",
 		       (unsigned long long) pfn << PAGE_SHIFT,
@@ -514,12 +756,13 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages)
 		return ret;
 	}
 
+	zone->managed_pages += onlined_pages;
 	zone->present_pages += onlined_pages;
 	zone->zone_pgdat->node_present_pages += onlined_pages;
 	if (onlined_pages) {
-		node_set_state(zone_to_nid(zone), N_HIGH_MEMORY);
+		node_states_set_node(zone_to_nid(zone), &arg);
 		if (need_zonelists_rebuild)
-			build_all_zonelists(NULL, zone);
+			build_all_zonelists(NULL, NULL);
 		else
 			zone_pcp_update(zone);
 	}
@@ -847,7 +1090,7 @@ check_pages_isolated_cb(unsigned long start_pfn, unsigned long nr_pages,
 {
 	int ret;
 	long offlined = *(long *)data;
-	ret = test_pages_isolated(start_pfn, start_pfn + nr_pages);
+	ret = test_pages_isolated(start_pfn, start_pfn + nr_pages, true);
 	offlined = nr_pages;
 	if (!ret)
 		*(long *)data += offlined;
@@ -867,6 +1110,129 @@ check_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
 	return offlined;
 }
 
+#ifdef CONFIG_MOVABLE_NODE
+/* when CONFIG_MOVABLE_NODE, we allow online node don't have normal memory */
+static bool can_offline_normal(struct zone *zone, unsigned long nr_pages)
+{
+	return true;
+}
+#else /* #ifdef CONFIG_MOVABLE_NODE */
+/* ensure the node has NORMAL memory if it is still online */
+static bool can_offline_normal(struct zone *zone, unsigned long nr_pages)
+{
+	struct pglist_data *pgdat = zone->zone_pgdat;
+	unsigned long present_pages = 0;
+	enum zone_type zt;
+
+	for (zt = 0; zt <= ZONE_NORMAL; zt++)
+		present_pages += pgdat->node_zones[zt].present_pages;
+
+	if (present_pages > nr_pages)
+		return true;
+
+	present_pages = 0;
+	for (; zt <= ZONE_MOVABLE; zt++)
+		present_pages += pgdat->node_zones[zt].present_pages;
+
+	/*
+	 * we can't offline the last normal memory until all
+	 * higher memory is offlined.
+	 */
+	return present_pages == 0;
+}
+#endif /* #ifdef CONFIG_MOVABLE_NODE */
+
+/* check which state of node_states will be changed when offline memory */
+static void node_states_check_changes_offline(unsigned long nr_pages,
+		struct zone *zone, struct memory_notify *arg)
+{
+	struct pglist_data *pgdat = zone->zone_pgdat;
+	unsigned long present_pages = 0;
+	enum zone_type zt, zone_last = ZONE_NORMAL;
+
+	/*
+	 * If we have HIGHMEM or movable node, node_states[N_NORMAL_MEMORY]
+	 * contains nodes which have zones of 0...ZONE_NORMAL,
+	 * set zone_last to ZONE_NORMAL.
+	 *
+	 * If we don't have HIGHMEM nor movable node,
+	 * node_states[N_NORMAL_MEMORY] contains nodes which have zones of
+	 * 0...ZONE_MOVABLE, set zone_last to ZONE_MOVABLE.
+	 */
+	if (N_MEMORY == N_NORMAL_MEMORY)
+		zone_last = ZONE_MOVABLE;
+
+	/*
+	 * check whether node_states[N_NORMAL_MEMORY] will be changed.
+	 * If the memory to be offline is in a zone of 0...zone_last,
+	 * and it is the last present memory, 0...zone_last will
+	 * become empty after offline , thus we can determind we will
+	 * need to clear the node from node_states[N_NORMAL_MEMORY].
+	 */
+	for (zt = 0; zt <= zone_last; zt++)
+		present_pages += pgdat->node_zones[zt].present_pages;
+	if (zone_idx(zone) <= zone_last && nr_pages >= present_pages)
+		arg->status_change_nid_normal = zone_to_nid(zone);
+	else
+		arg->status_change_nid_normal = -1;
+
+#ifdef CONIG_HIGHMEM
+	/*
+	 * If we have movable node, node_states[N_HIGH_MEMORY]
+	 * contains nodes which have zones of 0...ZONE_HIGH,
+	 * set zone_last to ZONE_HIGH.
+	 *
+	 * If we don't have movable node, node_states[N_NORMAL_MEMORY]
+	 * contains nodes which have zones of 0...ZONE_MOVABLE,
+	 * set zone_last to ZONE_MOVABLE.
+	 */
+	zone_last = ZONE_HIGH;
+	if (N_MEMORY == N_HIGH_MEMORY)
+		zone_last = ZONE_MOVABLE;
+
+	for (; zt <= zone_last; zt++)
+		present_pages += pgdat->node_zones[zt].present_pages;
+	if (zone_idx(zone) <= zone_last && nr_pages >= present_pages)
+		arg->status_change_nid_high = zone_to_nid(zone);
+	else
+		arg->status_change_nid_high = -1;
+#else
+	arg->status_change_nid_high = arg->status_change_nid_normal;
+#endif
+
+	/*
+	 * node_states[N_HIGH_MEMORY] contains nodes which have 0...ZONE_MOVABLE
+	 */
+	zone_last = ZONE_MOVABLE;
+
+	/*
+	 * check whether node_states[N_HIGH_MEMORY] will be changed
+	 * If we try to offline the last present @nr_pages from the node,
+	 * we can determind we will need to clear the node from
+	 * node_states[N_HIGH_MEMORY].
+	 */
+	for (; zt <= zone_last; zt++)
+		present_pages += pgdat->node_zones[zt].present_pages;
+	if (nr_pages >= present_pages)
+		arg->status_change_nid = zone_to_nid(zone);
+	else
+		arg->status_change_nid = -1;
+}
+
+static void node_states_clear_node(int node, struct memory_notify *arg)
+{
+	if (arg->status_change_nid_normal >= 0)
+		node_clear_state(node, N_NORMAL_MEMORY);
+
+	if ((N_MEMORY != N_NORMAL_MEMORY) &&
+	    (arg->status_change_nid_high >= 0))
+		node_clear_state(node, N_HIGH_MEMORY);
+
+	if ((N_MEMORY != N_HIGH_MEMORY) &&
+	    (arg->status_change_nid >= 0))
+		node_clear_state(node, N_MEMORY);
+}
+
 static int __ref __offline_pages(unsigned long start_pfn,
 		  unsigned long end_pfn, unsigned long timeout)
 {
@@ -893,16 +1259,19 @@ static int __ref __offline_pages(unsigned long start_pfn,
 	node = zone_to_nid(zone);
 	nr_pages = end_pfn - start_pfn;
 
+	ret = -EINVAL;
+	if (zone_idx(zone) <= ZONE_NORMAL && !can_offline_normal(zone, nr_pages))
+		goto out;
+
 	/* set above range as isolated */
-	ret = start_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
+	ret = start_isolate_page_range(start_pfn, end_pfn,
+				       MIGRATE_MOVABLE, true);
 	if (ret)
 		goto out;
 
 	arg.start_pfn = start_pfn;
 	arg.nr_pages = nr_pages;
-	arg.status_change_nid = -1;
-	if (nr_pages >= node_present_pages(node))
-		arg.status_change_nid = node;
+	node_states_check_changes_offline(nr_pages, zone, &arg);
 
 	ret = memory_notify(MEM_GOING_OFFLINE, &arg);
 	ret = notifier_to_errno(ret);
@@ -943,10 +1312,10 @@ repeat:
 			goto repeat;
 		}
 	}
-	/* drain all zone's lru pagevec, this is asyncronous... */
+	/* drain all zone's lru pagevec, this is asynchronous... */
 	lru_add_drain_all();
 	yield();
-	/* drain pcp pages , this is synchrouns. */
+	/* drain pcp pages, this is synchronous. */
 	drain_all_pages();
 	/* check again */
 	offlined_pages = check_pages_isolated(start_pfn, end_pfn);
@@ -955,12 +1324,13 @@ repeat:
 		goto failed_removal;
 	}
 	printk(KERN_INFO "Offlined Pages %ld\n", offlined_pages);
-	/* Ok, all of our target is islaoted.
+	/* Ok, all of our target is isolated.
 	   We cannot do rollback at this point. */
 	offline_isolated_pages(start_pfn, end_pfn);
 	/* reset pagetype flags and makes migrate type to be MOVABLE */
 	undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
 	/* removal success */
+	zone->managed_pages -= offlined_pages;
 	zone->present_pages -= offlined_pages;
 	zone->zone_pgdat->node_present_pages -= offlined_pages;
 	totalram_pages -= offlined_pages;
@@ -975,10 +1345,9 @@ repeat:
 	} else
 		zone_pcp_update(zone);
 
-	if (!node_present_pages(node)) {
-		node_clear_state(node, N_HIGH_MEMORY);
+	node_states_clear_node(node, &arg);
+	if (arg.status_change_nid >= 0)
 		kswapd_stop(node);
-	}
 
 	vm_total_pages = nr_free_pagecache_pages();
 	writeback_set_ratelimit();
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index d04a8a5..1782b4c 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -111,12 +111,30 @@ enum zone_type policy_zone = 0;
 /*
  * run-time system-wide default policy => local allocation
  */
-static struct mempolicy default_policy = {
-	.refcnt = ATOMIC_INIT(1), /* never free it */
-	.mode = MPOL_PREFERRED,
-	.flags = MPOL_F_LOCAL,
+
+static struct mempolicy default_policy_local = {
+	.refcnt		= ATOMIC_INIT(1), /* never free it */
+	.mode		= MPOL_PREFERRED,
+	.flags		= MPOL_F_LOCAL,
+};
+
+/*
+ * .v.nodes is set by numa_policy_init():
+ */
+static struct mempolicy default_policy_shared = {
+	.refcnt			= ATOMIC_INIT(1), /* never free it */
+	.mode			= MPOL_INTERLEAVE,
+	.flags			= 0,
 };
 
+static struct mempolicy *default_policy(void)
+{
+	if (task_numa_shared(current) == 1)
+		return &default_policy_shared;
+
+	return &default_policy_local;
+}
+
 static const struct mempolicy_operations {
 	int (*create)(struct mempolicy *pol, const nodemask_t *nodes);
 	/*
@@ -212,9 +230,9 @@ static int mpol_set_nodemask(struct mempolicy *pol,
 	/* if mode is MPOL_DEFAULT, pol is NULL. This is right. */
 	if (pol == NULL)
 		return 0;
-	/* Check N_HIGH_MEMORY */
+	/* Check N_MEMORY */
 	nodes_and(nsc->mask1,
-		  cpuset_current_mems_allowed, node_states[N_HIGH_MEMORY]);
+		  cpuset_current_mems_allowed, node_states[N_MEMORY]);
 
 	VM_BUG_ON(!nodes);
 	if (pol->mode == MPOL_PREFERRED && nodes_empty(*nodes))
@@ -511,7 +529,7 @@ static inline int check_pmd_range(struct vm_area_struct *vma, pud_t *pud,
 	pmd = pmd_offset(pud, addr);
 	do {
 		next = pmd_addr_end(addr, end);
-		split_huge_page_pmd(vma->vm_mm, pmd);
+		split_huge_page_pmd(vma, addr, pmd);
 		if (pmd_none_or_trans_huge_or_clear_bad(pmd))
 			continue;
 		if (check_pte_range(vma, pmd, addr, next, nodes,
@@ -789,7 +807,7 @@ out:
 static void get_policy_nodemask(struct mempolicy *p, nodemask_t *nodes)
 {
 	nodes_clear(*nodes);
-	if (p == &default_policy)
+	if (p == default_policy())
 		return;
 
 	switch (p->mode) {
@@ -864,7 +882,7 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
 		return -EINVAL;
 
 	if (!pol)
-		pol = &default_policy;	/* indicates default behavior */
+		pol = default_policy();	/* indicates default behavior */
 
 	if (flags & MPOL_F_NODE) {
 		if (flags & MPOL_F_ADDR) {
@@ -880,7 +898,7 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
 			goto out;
 		}
 	} else {
-		*policy = pol == &default_policy ? MPOL_DEFAULT :
+		*policy = pol == default_policy() ? MPOL_DEFAULT :
 						pol->mode;
 		/*
 		 * Internal mempolicy flags must be masked off before exposing
@@ -1388,7 +1406,7 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode,
 		goto out_put;
 	}
 
-	if (!nodes_subset(*new, node_states[N_HIGH_MEMORY])) {
+	if (!nodes_subset(*new, node_states[N_MEMORY])) {
 		err = -EINVAL;
 		goto out_put;
 	}
@@ -1568,7 +1586,7 @@ struct mempolicy *get_vma_policy(struct task_struct *task,
 		}
 	}
 	if (!pol)
-		pol = &default_policy;
+		pol = default_policy();
 	return pol;
 }
 
@@ -1907,7 +1925,6 @@ alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
 		unsigned long addr, int node)
 {
 	struct mempolicy *pol;
-	struct zonelist *zl;
 	struct page *page;
 	unsigned int cpuset_mems_cookie;
 
@@ -1926,23 +1943,11 @@ retry_cpuset:
 
 		return page;
 	}
-	zl = policy_zonelist(gfp, pol, node);
-	if (unlikely(mpol_needs_cond_ref(pol))) {
-		/*
-		 * slow path: ref counted shared policy
-		 */
-		struct page *page =  __alloc_pages_nodemask(gfp, order,
-						zl, policy_nodemask(gfp, pol));
-		__mpol_put(pol);
-		if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page))
-			goto retry_cpuset;
-		return page;
-	}
-	/*
-	 * fast path:  default or task policy
-	 */
-	page = __alloc_pages_nodemask(gfp, order, zl,
+	page = __alloc_pages_nodemask(gfp, order,
+				      policy_zonelist(gfp, pol, node),
 				      policy_nodemask(gfp, pol));
+	if (unlikely(mpol_needs_cond_ref(pol)))
+		__mpol_put(pol);
 	if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page))
 		goto retry_cpuset;
 	return page;
@@ -1974,7 +1979,7 @@ struct page *alloc_pages_current(gfp_t gfp, unsigned order)
 	unsigned int cpuset_mems_cookie;
 
 	if (!pol || in_interrupt() || (gfp & __GFP_THISNODE))
-		pol = &default_policy;
+		pol = default_policy();
 
 retry_cpuset:
 	cpuset_mems_cookie = get_mems_allowed();
@@ -2175,6 +2180,151 @@ static void sp_free(struct sp_node *n)
 	kmem_cache_free(sn_cache, n);
 }
 
+/*
+ * Multi-stage node selection is used in conjunction with a periodic
+ * migration fault to build a temporal task<->page relation. By
+ * using a two-stage filter we remove short/unlikely relations.
+ *
+ * Using P(p) ~ n_p / n_t as per frequentist probability, we can
+ * equate a task's usage of a particular page (n_p) per total usage
+ * of this page (n_t) (in a given time-span) to a probability.
+ *
+ * Our periodic faults will then sample this probability and getting
+ * the same result twice in a row, given these samples are fully
+ * independent, is then given by P(n)^2, provided our sample period
+ * is sufficiently short compared to the usage pattern.
+ *
+ * This quadric squishes small probabilities, making it less likely
+ * we act on an unlikely task<->page relation.
+ *
+ * Return the best node ID this page should be on, or -1 if it should
+ * stay where it is.
+ */
+static int
+numa_migration_target(struct page *page, int page_nid,
+		      struct task_struct *p, int this_cpu,
+		      int cpu_last_access)
+{
+	int nid_last_access;
+	int this_nid;
+
+	if (task_numa_shared(p) < 0)
+		return -1;
+
+	/*
+	 * Possibly migrate towards the current node, depends on
+	 * task_numa_placement() and access details.
+	 */
+	nid_last_access = cpu_to_node(cpu_last_access);
+	this_nid = cpu_to_node(this_cpu);
+
+	if (nid_last_access != this_nid) {
+		/*
+		 * 'Access miss': the page got last accessed from a remote node.
+		 */
+		return -1;
+	}
+	/*
+	 * 'Access hit': the page got last accessed from our node.
+	 *
+	 * Migrate the page if needed.
+	 */
+
+	/* The page is already on this node: */
+	if (page_nid == this_nid)
+		return -1;
+
+	return this_nid;
+}
+
+/**
+ * mpol_misplaced - check whether current page node is valid in policy
+ *
+ * @page   - page to be checked
+ * @vma    - vm area where page mapped
+ * @addr   - virtual address where page mapped
+ * @multi  - use multi-stage node binding
+ *
+ * Lookup current policy node id for vma,addr and "compare to" page's
+ * node id.
+ *
+ * Returns:
+ *	-1	- not misplaced, page is in the right node
+ *	node	- node id where the page should be
+ *
+ * Policy determination "mimics" alloc_page_vma().
+ * Called from fault path where we know the vma and faulting address.
+ */
+int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long addr)
+{
+	int best_nid = -1, page_nid;
+	int cpu_last_access, this_cpu;
+	struct mempolicy *pol;
+	struct zone *zone;
+
+	BUG_ON(!vma);
+
+	this_cpu = raw_smp_processor_id();
+	page_nid = page_to_nid(page);
+
+	cpu_last_access = page_xchg_last_cpu(page, this_cpu);
+
+	pol = get_vma_policy(current, vma, addr);
+	if (!(task_numa_shared(current) >= 0))
+		goto out_keep_page;
+
+	switch (pol->mode) {
+	case MPOL_INTERLEAVE:
+	{
+		int shift;
+
+		BUG_ON(addr >= vma->vm_end);
+		BUG_ON(addr < vma->vm_start);
+
+#ifdef CONFIG_HUGETLB_PAGE
+		if (transparent_hugepage_enabled(vma) || vma->vm_flags & VM_HUGETLB)
+			shift = HPAGE_SHIFT;
+		else
+#endif
+			shift = PAGE_SHIFT;
+
+		best_nid = interleave_nid(pol, vma, addr, shift);
+		break;
+	}
+
+	case MPOL_PREFERRED:
+		if (pol->flags & MPOL_F_LOCAL)
+			best_nid = numa_migration_target(page, page_nid, current, this_cpu, cpu_last_access);
+		else
+			best_nid = pol->v.preferred_node;
+		break;
+
+	case MPOL_BIND:
+		/*
+		 * allows binding to multiple nodes.
+		 * use current page if in policy nodemask,
+		 * else select nearest allowed node, if any.
+		 * If no allowed nodes, use current [!misplaced].
+		 */
+		if (node_isset(page_nid, pol->v.nodes))
+			goto out_keep_page;
+		(void)first_zones_zonelist(
+				node_zonelist(numa_node_id(), GFP_HIGHUSER),
+				gfp_zone(GFP_HIGHUSER),
+				&pol->v.nodes, &zone);
+		best_nid = zone->node;
+		break;
+
+	default:
+		BUG();
+	}
+
+out_keep_page:
+	mpol_cond_put(pol);
+
+	return best_nid;
+}
+
 static void sp_delete(struct shared_policy *sp, struct sp_node *n)
 {
 	pr_debug("deleting %lx-l%lx\n", n->start, n->end);
@@ -2355,13 +2505,15 @@ void __init numa_policy_init(void)
 				     sizeof(struct sp_node),
 				     0, SLAB_PANIC, NULL);
 
+	default_policy_shared.v.nodes = node_online_map;
+
 	/*
 	 * Set interleaving policy for system init. Interleaving is only
 	 * enabled across suitably sized nodes (default is >= 16MB), or
 	 * fall back to the largest node if they're all smaller.
 	 */
 	nodes_clear(interleave_nodes);
-	for_each_node_state(nid, N_HIGH_MEMORY) {
+	for_each_node_state(nid, N_MEMORY) {
 		unsigned long total_pages = node_present_pages(nid);
 
 		/* Preserve the largest node */
@@ -2442,7 +2594,7 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
 		*nodelist++ = '\0';
 		if (nodelist_parse(nodelist, nodes))
 			goto out;
-		if (!nodes_subset(nodes, node_states[N_HIGH_MEMORY]))
+		if (!nodes_subset(nodes, node_states[N_MEMORY]))
 			goto out;
 	} else
 		nodes_clear(nodes);
@@ -2476,7 +2628,7 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
 		 * Default to online nodes with memory if no nodelist
 		 */
 		if (!nodelist)
-			nodes = node_states[N_HIGH_MEMORY];
+			nodes = node_states[N_MEMORY];
 		break;
 	case MPOL_LOCAL:
 		/*
@@ -2575,7 +2727,7 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context)
 	 */
 	VM_BUG_ON(maxlen < strlen("interleave") + strlen("relative") + 16);
 
-	if (!pol || pol == &default_policy)
+	if (!pol || pol == default_policy())
 		mode = MPOL_DEFAULT;
 	else
 		mode = pol->mode;
diff --git a/mm/migrate.c b/mm/migrate.c
index 77ed2d7..108d74d 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -35,6 +35,7 @@
 #include <linux/hugetlb.h>
 #include <linux/hugetlb_cgroup.h>
 #include <linux/gfp.h>
+#include <linux/balloon_compaction.h>
 
 #include <asm/tlbflush.h>
 
@@ -79,7 +80,30 @@ void putback_lru_pages(struct list_head *l)
 		list_del(&page->lru);
 		dec_zone_page_state(page, NR_ISOLATED_ANON +
 				page_is_file_cache(page));
-		putback_lru_page(page);
+			putback_lru_page(page);
+	}
+}
+
+/*
+ * Put previously isolated pages back onto the appropriate lists
+ * from where they were once taken off for compaction/migration.
+ *
+ * This function shall be used instead of putback_lru_pages(),
+ * whenever the isolated pageset has been built by isolate_migratepages_range()
+ */
+void putback_movable_pages(struct list_head *l)
+{
+	struct page *page;
+	struct page *page2;
+
+	list_for_each_entry_safe(page, page2, l, lru) {
+		list_del(&page->lru);
+		dec_zone_page_state(page, NR_ISOLATED_ANON +
+				page_is_file_cache(page));
+		if (unlikely(balloon_page_movable(page)))
+			balloon_page_putback(page);
+		else
+			putback_lru_page(page);
 	}
 }
 
@@ -91,8 +115,6 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma,
 {
 	struct mm_struct *mm = vma->vm_mm;
 	swp_entry_t entry;
- 	pgd_t *pgd;
- 	pud_t *pud;
  	pmd_t *pmd;
 	pte_t *ptep, pte;
  	spinlock_t *ptl;
@@ -103,19 +125,11 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma,
 			goto out;
 		ptl = &mm->page_table_lock;
 	} else {
-		pgd = pgd_offset(mm, addr);
-		if (!pgd_present(*pgd))
-			goto out;
-
-		pud = pud_offset(pgd, addr);
-		if (!pud_present(*pud))
+		pmd = mm_find_pmd(mm, addr);
+		if (!pmd)
 			goto out;
-
-		pmd = pmd_offset(pud, addr);
 		if (pmd_trans_huge(*pmd))
 			goto out;
-		if (!pmd_present(*pmd))
-			goto out;
 
 		ptep = pte_offset_map(pmd, addr);
 
@@ -279,14 +293,14 @@ static int migrate_page_move_mapping(struct address_space *mapping,
 		struct page *newpage, struct page *page,
 		struct buffer_head *head, enum migrate_mode mode)
 {
-	int expected_count;
+	int expected_count = 0;
 	void **pslot;
 
 	if (!mapping) {
 		/* Anonymous page without mapping */
 		if (page_count(page) != 1)
 			return -EAGAIN;
-		return 0;
+		return MIGRATEPAGE_SUCCESS;
 	}
 
 	spin_lock_irq(&mapping->tree_lock);
@@ -356,7 +370,7 @@ static int migrate_page_move_mapping(struct address_space *mapping,
 	}
 	spin_unlock_irq(&mapping->tree_lock);
 
-	return 0;
+	return MIGRATEPAGE_SUCCESS;
 }
 
 /*
@@ -372,7 +386,7 @@ int migrate_huge_page_move_mapping(struct address_space *mapping,
 	if (!mapping) {
 		if (page_count(page) != 1)
 			return -EAGAIN;
-		return 0;
+		return MIGRATEPAGE_SUCCESS;
 	}
 
 	spin_lock_irq(&mapping->tree_lock);
@@ -399,7 +413,7 @@ int migrate_huge_page_move_mapping(struct address_space *mapping,
 	page_unfreeze_refs(page, expected_count - 1);
 
 	spin_unlock_irq(&mapping->tree_lock);
-	return 0;
+	return MIGRATEPAGE_SUCCESS;
 }
 
 /*
@@ -407,7 +421,7 @@ int migrate_huge_page_move_mapping(struct address_space *mapping,
  */
 void migrate_page_copy(struct page *newpage, struct page *page)
 {
-	if (PageHuge(page))
+	if (PageHuge(page) || PageTransHuge(page))
 		copy_huge_page(newpage, page);
 	else
 		copy_highpage(newpage, page);
@@ -486,11 +500,11 @@ int migrate_page(struct address_space *mapping,
 
 	rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode);
 
-	if (rc)
+	if (rc != MIGRATEPAGE_SUCCESS)
 		return rc;
 
 	migrate_page_copy(newpage, page);
-	return 0;
+	return MIGRATEPAGE_SUCCESS;
 }
 EXPORT_SYMBOL(migrate_page);
 
@@ -513,7 +527,7 @@ int buffer_migrate_page(struct address_space *mapping,
 
 	rc = migrate_page_move_mapping(mapping, newpage, page, head, mode);
 
-	if (rc)
+	if (rc != MIGRATEPAGE_SUCCESS)
 		return rc;
 
 	/*
@@ -549,7 +563,7 @@ int buffer_migrate_page(struct address_space *mapping,
 
 	} while (bh != head);
 
-	return 0;
+	return MIGRATEPAGE_SUCCESS;
 }
 EXPORT_SYMBOL(buffer_migrate_page);
 #endif
@@ -628,7 +642,7 @@ static int fallback_migrate_page(struct address_space *mapping,
  *
  * Return value:
  *   < 0 - error code
- *  == 0 - success
+ *  MIGRATEPAGE_SUCCESS - success
  */
 static int move_to_new_page(struct page *newpage, struct page *page,
 				int remap_swapcache, enum migrate_mode mode)
@@ -665,7 +679,7 @@ static int move_to_new_page(struct page *newpage, struct page *page,
 	else
 		rc = fallback_migrate_page(mapping, newpage, page, mode);
 
-	if (rc) {
+	if (rc != MIGRATEPAGE_SUCCESS) {
 		newpage->mapping = NULL;
 	} else {
 		if (remap_swapcache)
@@ -778,6 +792,18 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
 		}
 	}
 
+	if (unlikely(balloon_page_movable(page))) {
+		/*
+		 * A ballooned page does not need any special attention from
+		 * physical to virtual reverse mapping procedures.
+		 * Skip any attempt to unmap PTEs or to remap swap cache,
+		 * in order to avoid burning cycles at rmap level, and perform
+		 * the page migration right away (proteced by page lock).
+		 */
+		rc = balloon_page_migrate(newpage, page, mode);
+		goto uncharge;
+	}
+
 	/*
 	 * Corner case handling:
 	 * 1. When a new swap-cache page is read into, it is added to the LRU
@@ -814,7 +840,9 @@ skip_unmap:
 		put_anon_vma(anon_vma);
 
 uncharge:
-	mem_cgroup_end_migration(mem, page, newpage, rc == 0);
+	mem_cgroup_end_migration(mem, page, newpage,
+				 (rc == MIGRATEPAGE_SUCCESS ||
+				  rc == MIGRATEPAGE_BALLOON_SUCCESS));
 unlock:
 	unlock_page(page);
 out:
@@ -846,6 +874,19 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
 			goto out;
 
 	rc = __unmap_and_move(page, newpage, force, offlining, mode);
+
+	if (unlikely(rc == MIGRATEPAGE_BALLOON_SUCCESS)) {
+		/*
+		 * A ballooned page has been migrated already.
+		 * Now, it's the time to wrap-up counters,
+		 * handle the page back to Buddy and return.
+		 */
+		dec_zone_page_state(page, NR_ISOLATED_ANON +
+				    page_is_file_cache(page));
+		balloon_page_free(page);
+		balloon_event_count(COMPACTBALLOONMIGRATED);
+		return MIGRATEPAGE_SUCCESS;
+	}
 out:
 	if (rc != -EAGAIN) {
 		/*
@@ -987,7 +1028,7 @@ int migrate_pages(struct list_head *from,
 			case -EAGAIN:
 				retry++;
 				break;
-			case 0:
+			case MIGRATEPAGE_SUCCESS:
 				break;
 			default:
 				/* Permanent failure */
@@ -996,15 +1037,12 @@ int migrate_pages(struct list_head *from,
 			}
 		}
 	}
-	rc = 0;
+	rc = nr_failed + retry;
 out:
 	if (!swapwrite)
 		current->flags &= ~PF_SWAPWRITE;
 
-	if (rc)
-		return rc;
-
-	return nr_failed + retry;
+	return rc;
 }
 
 int migrate_huge_page(struct page *hpage, new_page_t get_new_page,
@@ -1024,7 +1062,7 @@ int migrate_huge_page(struct page *hpage, new_page_t get_new_page,
 			/* try again */
 			cond_resched();
 			break;
-		case 0:
+		case MIGRATEPAGE_SUCCESS:
 			goto out;
 		default:
 			rc = -EIO;
@@ -1201,7 +1239,7 @@ static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes,
 			if (node < 0 || node >= MAX_NUMNODES)
 				goto out_pm;
 
-			if (!node_state(node, N_HIGH_MEMORY))
+			if (!node_state(node, N_MEMORY))
 				goto out_pm;
 
 			err = -EACCES;
@@ -1403,4 +1441,104 @@ int migrate_vmas(struct mm_struct *mm, const nodemask_t *to,
  	}
  	return err;
 }
-#endif
+
+/*
+ * Returns true if this is a safe migration target node for misplaced NUMA
+ * pages. Currently it only checks the watermarks which is a bit crude.
+ */
+static bool migrate_balanced_pgdat(struct pglist_data *pgdat,
+				   int nr_migrate_pages)
+{
+	int z;
+
+	for (z = pgdat->nr_zones - 1; z >= 0; z--) {
+		struct zone *zone = pgdat->node_zones + z;
+
+		if (!populated_zone(zone))
+			continue;
+
+		if (zone->all_unreclaimable)
+			continue;
+
+		/* Avoid waking kswapd by allocating pages_to_migrate pages. */
+		if (!zone_watermark_ok(zone, 0,
+				       high_wmark_pages(zone) +
+				       nr_migrate_pages,
+				       0, 0))
+			continue;
+		return true;
+	}
+	return false;
+}
+
+static struct page *alloc_misplaced_dst_page(struct page *page,
+					   unsigned long data,
+					   int **result)
+{
+	int nid = (int) data;
+	struct page *newpage;
+
+	newpage = alloc_pages_exact_node(nid,
+					 (GFP_HIGHUSER_MOVABLE | GFP_THISNODE |
+					  __GFP_NOMEMALLOC | __GFP_NORETRY |
+					  __GFP_NOWARN) &
+					 ~GFP_IOFS, 0);
+	return newpage;
+}
+
+/*
+ * Attempt to migrate a misplaced page to the specified destination
+ * 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 isolated = 0;
+	LIST_HEAD(migratepages);
+
+	/*
+	 * 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;
+
+	/* Avoid migrating to a node that is nearly full */
+	if (migrate_balanced_pgdat(NODE_DATA(node), 1)) {
+		int page_lru;
+
+		if (isolate_lru_page(page)) {
+			put_page(page);
+			goto out;
+		}
+		isolated = 1;
+
+		/*
+		 * Page is isolated which takes a reference count so now the
+		 * callers reference can be safely dropped without the page
+		 * disappearing underneath us during migration
+		 */
+		put_page(page);
+
+		page_lru = page_is_file_cache(page);
+		inc_zone_page_state(page, NR_ISOLATED_ANON + page_lru);
+		list_add(&page->lru, &migratepages);
+	}
+
+	if (isolated) {
+		int nr_remaining;
+
+		nr_remaining = migrate_pages(&migratepages,
+				alloc_misplaced_dst_page,
+				node, false, MIGRATE_ASYNC);
+		if (nr_remaining) {
+			putback_lru_pages(&migratepages);
+			isolated = 0;
+		}
+	}
+	BUG_ON(!list_empty(&migratepages));
+out:
+	return isolated;
+}
+
+#endif /* CONFIG_NUMA */
diff --git a/mm/mmap.c b/mm/mmap.c
index 9a796c4..9ed3a06 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -31,6 +31,7 @@
 #include <linux/audit.h>
 #include <linux/khugepaged.h>
 #include <linux/uprobes.h>
+#include <linux/rbtree_augmented.h>
 
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
@@ -89,6 +90,20 @@ int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
 struct percpu_counter vm_committed_as ____cacheline_aligned_in_smp;
 
 /*
+ * The global memory commitment made in the system can be a metric
+ * that can be used to drive ballooning decisions when Linux is hosted
+ * as a guest. On Hyper-V, the host implements a policy engine for dynamically
+ * balancing memory across competing virtual machines that are hosted.
+ * Several metrics drive this policy engine including the guest reported
+ * memory commitment.
+ */
+unsigned long vm_memory_committed(void)
+{
+	return percpu_counter_read_positive(&vm_committed_as);
+}
+EXPORT_SYMBOL_GPL(vm_memory_committed);
+
+/*
  * Check that a process has enough memory to allocate a new virtual
  * mapping. 0 means there is enough memory for the allocation to
  * succeed and -ENOMEM implies there is not.
@@ -297,40 +312,88 @@ out:
 	return retval;
 }
 
+static long vma_compute_subtree_gap(struct vm_area_struct *vma)
+{
+	unsigned long max, subtree_gap;
+	max = vma->vm_start;
+	if (vma->vm_prev)
+		max -= vma->vm_prev->vm_end;
+	if (vma->vm_rb.rb_left) {
+		subtree_gap = rb_entry(vma->vm_rb.rb_left,
+				struct vm_area_struct, vm_rb)->rb_subtree_gap;
+		if (subtree_gap > max)
+			max = subtree_gap;
+	}
+	if (vma->vm_rb.rb_right) {
+		subtree_gap = rb_entry(vma->vm_rb.rb_right,
+				struct vm_area_struct, vm_rb)->rb_subtree_gap;
+		if (subtree_gap > max)
+			max = subtree_gap;
+	}
+	return max;
+}
+
 #ifdef CONFIG_DEBUG_VM_RB
 static int browse_rb(struct rb_root *root)
 {
-	int i = 0, j;
+	int i = 0, j, bug = 0;
 	struct rb_node *nd, *pn = NULL;
 	unsigned long prev = 0, pend = 0;
 
 	for (nd = rb_first(root); nd; nd = rb_next(nd)) {
 		struct vm_area_struct *vma;
 		vma = rb_entry(nd, struct vm_area_struct, vm_rb);
-		if (vma->vm_start < prev)
-			printk("vm_start %lx prev %lx\n", vma->vm_start, prev), i = -1;
-		if (vma->vm_start < pend)
+		if (vma->vm_start < prev) {
+			printk("vm_start %lx prev %lx\n", vma->vm_start, prev);
+			bug = 1;
+		}
+		if (vma->vm_start < pend) {
 			printk("vm_start %lx pend %lx\n", vma->vm_start, pend);
-		if (vma->vm_start > vma->vm_end)
-			printk("vm_end %lx < vm_start %lx\n", vma->vm_end, vma->vm_start);
+			bug = 1;
+		}
+		if (vma->vm_start > vma->vm_end) {
+			printk("vm_end %lx < vm_start %lx\n",
+				vma->vm_end, vma->vm_start);
+			bug = 1;
+		}
+		if (vma->rb_subtree_gap != vma_compute_subtree_gap(vma)) {
+			printk("free gap %lx, correct %lx\n",
+			       vma->rb_subtree_gap,
+			       vma_compute_subtree_gap(vma));
+			bug = 1;
+		}
 		i++;
 		pn = nd;
 		prev = vma->vm_start;
 		pend = vma->vm_end;
 	}
 	j = 0;
-	for (nd = pn; nd; nd = rb_prev(nd)) {
+	for (nd = pn; nd; nd = rb_prev(nd))
 		j++;
+	if (i != j) {
+		printk("backwards %d, forwards %d\n", j, i);
+		bug = 1;
+	}
+	return bug ? -1 : i;
+}
+
+static void validate_mm_rb(struct rb_root *root, struct vm_area_struct *ignore)
+{
+	struct rb_node *nd;
+
+	for (nd = rb_first(root); nd; nd = rb_next(nd)) {
+		struct vm_area_struct *vma;
+		vma = rb_entry(nd, struct vm_area_struct, vm_rb);
+		BUG_ON(vma != ignore &&
+		       vma->rb_subtree_gap != vma_compute_subtree_gap(vma));
 	}
-	if (i != j)
-		printk("backwards %d, forwards %d\n", j, i), i = 0;
-	return i;
 }
 
 void validate_mm(struct mm_struct *mm)
 {
 	int bug = 0;
 	int i = 0;
+	unsigned long highest_address = 0;
 	struct vm_area_struct *vma = mm->mmap;
 	while (vma) {
 		struct anon_vma_chain *avc;
@@ -338,20 +401,73 @@ void validate_mm(struct mm_struct *mm)
 		list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
 			anon_vma_interval_tree_verify(avc);
 		vma_unlock_anon_vma(vma);
+		highest_address = vma->vm_end;
 		vma = vma->vm_next;
 		i++;
 	}
-	if (i != mm->map_count)
-		printk("map_count %d vm_next %d\n", mm->map_count, i), bug = 1;
+	if (i != mm->map_count) {
+		printk("map_count %d vm_next %d\n", mm->map_count, i);
+		bug = 1;
+	}
+	if (highest_address != mm->highest_vm_end) {
+		printk("mm->highest_vm_end %lx, found %lx\n",
+		       mm->highest_vm_end, highest_address);
+		bug = 1;
+	}
 	i = browse_rb(&mm->mm_rb);
-	if (i != mm->map_count)
-		printk("map_count %d rb %d\n", mm->map_count, i), bug = 1;
+	if (i != mm->map_count) {
+		printk("map_count %d rb %d\n", mm->map_count, i);
+		bug = 1;
+	}
 	BUG_ON(bug);
 }
 #else
+#define validate_mm_rb(root, ignore) do { } while (0)
 #define validate_mm(mm) do { } while (0)
 #endif
 
+RB_DECLARE_CALLBACKS(static, vma_gap_callbacks, struct vm_area_struct, vm_rb,
+		     unsigned long, rb_subtree_gap, vma_compute_subtree_gap)
+
+/*
+ * Update augmented rbtree rb_subtree_gap values after vma->vm_start or
+ * vma->vm_prev->vm_end values changed, without modifying the vma's position
+ * in the rbtree.
+ */
+static void vma_gap_update(struct vm_area_struct *vma)
+{
+	/*
+	 * As it turns out, RB_DECLARE_CALLBACKS() already created a callback
+	 * function that does exacltly what we want.
+	 */
+	vma_gap_callbacks_propagate(&vma->vm_rb, NULL);
+}
+
+static inline void vma_rb_insert(struct vm_area_struct *vma,
+				 struct rb_root *root)
+{
+	/* All rb_subtree_gap values must be consistent prior to insertion */
+	validate_mm_rb(root, NULL);
+
+	rb_insert_augmented(&vma->vm_rb, root, &vma_gap_callbacks);
+}
+
+static void vma_rb_erase(struct vm_area_struct *vma, struct rb_root *root)
+{
+	/*
+	 * All rb_subtree_gap values must be consistent prior to erase,
+	 * with the possible exception of the vma being erased.
+	 */
+	validate_mm_rb(root, vma);
+
+	/*
+	 * Note rb_erase_augmented is a fairly large inline function,
+	 * so make sure we instantiate it only once with our desired
+	 * augmented rbtree callbacks.
+	 */
+	rb_erase_augmented(&vma->vm_rb, root, &vma_gap_callbacks);
+}
+
 /*
  * vma has some anon_vma assigned, and is already inserted on that
  * anon_vma's interval trees.
@@ -421,8 +537,25 @@ static int find_vma_links(struct mm_struct *mm, unsigned long addr,
 void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma,
 		struct rb_node **rb_link, struct rb_node *rb_parent)
 {
+	/* Update tracking information for the gap following the new vma. */
+	if (vma->vm_next)
+		vma_gap_update(vma->vm_next);
+	else
+		mm->highest_vm_end = vma->vm_end;
+
+	/*
+	 * vma->vm_prev wasn't known when we followed the rbtree to find the
+	 * correct insertion point for that vma. As a result, we could not
+	 * update the vma vm_rb parents rb_subtree_gap values on the way down.
+	 * So, we first insert the vma with a zero rb_subtree_gap value
+	 * (to be consistent with what we did on the way down), and then
+	 * immediately update the gap to the correct value. Finally we
+	 * rebalance the rbtree after all augmented values have been set.
+	 */
 	rb_link_node(&vma->vm_rb, rb_parent, rb_link);
-	rb_insert_color(&vma->vm_rb, &mm->mm_rb);
+	vma->rb_subtree_gap = 0;
+	vma_gap_update(vma);
+	vma_rb_insert(vma, &mm->mm_rb);
 }
 
 static void __vma_link_file(struct vm_area_struct *vma)
@@ -498,12 +631,12 @@ static inline void
 __vma_unlink(struct mm_struct *mm, struct vm_area_struct *vma,
 		struct vm_area_struct *prev)
 {
-	struct vm_area_struct *next = vma->vm_next;
+	struct vm_area_struct *next;
 
-	prev->vm_next = next;
+	vma_rb_erase(vma, &mm->mm_rb);
+	prev->vm_next = next = vma->vm_next;
 	if (next)
 		next->vm_prev = prev;
-	rb_erase(&vma->vm_rb, &mm->mm_rb);
 	if (mm->mmap_cache == vma)
 		mm->mmap_cache = prev;
 }
@@ -525,6 +658,7 @@ int vma_adjust(struct vm_area_struct *vma, unsigned long start,
 	struct rb_root *root = NULL;
 	struct anon_vma *anon_vma = NULL;
 	struct file *file = vma->vm_file;
+	bool start_changed = false, end_changed = false;
 	long adjust_next = 0;
 	int remove_next = 0;
 
@@ -615,8 +749,14 @@ again:			remove_next = 1 + (end > next->vm_end);
 			vma_interval_tree_remove(next, root);
 	}
 
-	vma->vm_start = start;
-	vma->vm_end = end;
+	if (start != vma->vm_start) {
+		vma->vm_start = start;
+		start_changed = true;
+	}
+	if (end != vma->vm_end) {
+		vma->vm_end = end;
+		end_changed = true;
+	}
 	vma->vm_pgoff = pgoff;
 	if (adjust_next) {
 		next->vm_start += adjust_next << PAGE_SHIFT;
@@ -645,6 +785,15 @@ again:			remove_next = 1 + (end > next->vm_end);
 		 * (it may either follow vma or precede it).
 		 */
 		__insert_vm_struct(mm, insert);
+	} else {
+		if (start_changed)
+			vma_gap_update(vma);
+		if (end_changed) {
+			if (!next)
+				mm->highest_vm_end = end;
+			else if (!adjust_next)
+				vma_gap_update(next);
+		}
 	}
 
 	if (anon_vma) {
@@ -678,10 +827,13 @@ again:			remove_next = 1 + (end > next->vm_end);
 		 * we must remove another next too. It would clutter
 		 * up the code too much to do both in one go.
 		 */
-		if (remove_next == 2) {
-			next = vma->vm_next;
+		next = vma->vm_next;
+		if (remove_next == 2)
 			goto again;
-		}
+		else if (next)
+			vma_gap_update(next);
+		else
+			mm->highest_vm_end = end;
 	}
 	if (insert && file)
 		uprobe_mmap(insert);
@@ -1153,8 +1305,9 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
 		 * memory so no accounting is necessary
 		 */
 		file = hugetlb_file_setup(HUGETLB_ANON_FILE, addr, len,
-						VM_NORESERVE, &user,
-						HUGETLB_ANONHUGE_INODE);
+				VM_NORESERVE,
+				&user, HUGETLB_ANONHUGE_INODE,
+				(flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK);
 		if (IS_ERR(file))
 			return PTR_ERR(file);
 	}
@@ -1335,7 +1488,11 @@ munmap_back:
 		 *
 		 * Answer: Yes, several device drivers can do it in their
 		 *         f_op->mmap method. -DaveM
+		 * Bug: If addr is changed, prev, rb_link, rb_parent should
+		 *      be updated for vma_link()
 		 */
+		WARN_ON_ONCE(addr != vma->vm_start);
+
 		addr = vma->vm_start;
 		pgoff = vma->vm_pgoff;
 		vm_flags = vma->vm_flags;
@@ -1400,6 +1557,206 @@ unacct_error:
 	return error;
 }
 
+unsigned long unmapped_area(struct vm_unmapped_area_info *info)
+{
+	/*
+	 * We implement the search by looking for an rbtree node that
+	 * immediately follows a suitable gap. That is,
+	 * - gap_start = vma->vm_prev->vm_end <= info->high_limit - length;
+	 * - gap_end   = vma->vm_start        >= info->low_limit  + length;
+	 * - gap_end - gap_start >= length
+	 */
+
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	unsigned long length, low_limit, high_limit, gap_start, gap_end;
+
+	/* Adjust search length to account for worst case alignment overhead */
+	length = info->length + info->align_mask;
+	if (length < info->length)
+		return -ENOMEM;
+
+	/* Adjust search limits by the desired length */
+	if (info->high_limit < length)
+		return -ENOMEM;
+	high_limit = info->high_limit - length;
+
+	if (info->low_limit > high_limit)
+		return -ENOMEM;
+	low_limit = info->low_limit + length;
+
+	/* Check if rbtree root looks promising */
+	if (RB_EMPTY_ROOT(&mm->mm_rb))
+		goto check_highest;
+	vma = rb_entry(mm->mm_rb.rb_node, struct vm_area_struct, vm_rb);
+	if (vma->rb_subtree_gap < length)
+		goto check_highest;
+
+	while (true) {
+		/* Visit left subtree if it looks promising */
+		gap_end = vma->vm_start;
+		if (gap_end >= low_limit && vma->vm_rb.rb_left) {
+			struct vm_area_struct *left =
+				rb_entry(vma->vm_rb.rb_left,
+					 struct vm_area_struct, vm_rb);
+			if (left->rb_subtree_gap >= length) {
+				vma = left;
+				continue;
+			}
+		}
+
+		gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0;
+check_current:
+		/* Check if current node has a suitable gap */
+		if (gap_start > high_limit)
+			return -ENOMEM;
+		if (gap_end >= low_limit && gap_end - gap_start >= length)
+			goto found;
+
+		/* Visit right subtree if it looks promising */
+		if (vma->vm_rb.rb_right) {
+			struct vm_area_struct *right =
+				rb_entry(vma->vm_rb.rb_right,
+					 struct vm_area_struct, vm_rb);
+			if (right->rb_subtree_gap >= length) {
+				vma = right;
+				continue;
+			}
+		}
+
+		/* Go back up the rbtree to find next candidate node */
+		while (true) {
+			struct rb_node *prev = &vma->vm_rb;
+			if (!rb_parent(prev))
+				goto check_highest;
+			vma = rb_entry(rb_parent(prev),
+				       struct vm_area_struct, vm_rb);
+			if (prev == vma->vm_rb.rb_left) {
+				gap_start = vma->vm_prev->vm_end;
+				gap_end = vma->vm_start;
+				goto check_current;
+			}
+		}
+	}
+
+check_highest:
+	/* Check highest gap, which does not precede any rbtree node */
+	gap_start = mm->highest_vm_end;
+	gap_end = ULONG_MAX;  /* Only for VM_BUG_ON below */
+	if (gap_start > high_limit)
+		return -ENOMEM;
+
+found:
+	/* We found a suitable gap. Clip it with the original low_limit. */
+	if (gap_start < info->low_limit)
+		gap_start = info->low_limit;
+
+	/* Adjust gap address to the desired alignment */
+	gap_start += (info->align_offset - gap_start) & info->align_mask;
+
+	VM_BUG_ON(gap_start + info->length > info->high_limit);
+	VM_BUG_ON(gap_start + info->length > gap_end);
+	return gap_start;
+}
+
+unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	unsigned long length, low_limit, high_limit, gap_start, gap_end;
+
+	/* Adjust search length to account for worst case alignment overhead */
+	length = info->length + info->align_mask;
+	if (length < info->length)
+		return -ENOMEM;
+
+	/*
+	 * Adjust search limits by the desired length.
+	 * See implementation comment at top of unmapped_area().
+	 */
+	gap_end = info->high_limit;
+	if (gap_end < length)
+		return -ENOMEM;
+	high_limit = gap_end - length;
+
+	if (info->low_limit > high_limit)
+		return -ENOMEM;
+	low_limit = info->low_limit + length;
+
+	/* Check highest gap, which does not precede any rbtree node */
+	gap_start = mm->highest_vm_end;
+	if (gap_start <= high_limit)
+		goto found_highest;
+
+	/* Check if rbtree root looks promising */
+	if (RB_EMPTY_ROOT(&mm->mm_rb))
+		return -ENOMEM;
+	vma = rb_entry(mm->mm_rb.rb_node, struct vm_area_struct, vm_rb);
+	if (vma->rb_subtree_gap < length)
+		return -ENOMEM;
+
+	while (true) {
+		/* Visit right subtree if it looks promising */
+		gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0;
+		if (gap_start <= high_limit && vma->vm_rb.rb_right) {
+			struct vm_area_struct *right =
+				rb_entry(vma->vm_rb.rb_right,
+					 struct vm_area_struct, vm_rb);
+			if (right->rb_subtree_gap >= length) {
+				vma = right;
+				continue;
+			}
+		}
+
+check_current:
+		/* Check if current node has a suitable gap */
+		gap_end = vma->vm_start;
+		if (gap_end < low_limit)
+			return -ENOMEM;
+		if (gap_start <= high_limit && gap_end - gap_start >= length)
+			goto found;
+
+		/* Visit left subtree if it looks promising */
+		if (vma->vm_rb.rb_left) {
+			struct vm_area_struct *left =
+				rb_entry(vma->vm_rb.rb_left,
+					 struct vm_area_struct, vm_rb);
+			if (left->rb_subtree_gap >= length) {
+				vma = left;
+				continue;
+			}
+		}
+
+		/* Go back up the rbtree to find next candidate node */
+		while (true) {
+			struct rb_node *prev = &vma->vm_rb;
+			if (!rb_parent(prev))
+				return -ENOMEM;
+			vma = rb_entry(rb_parent(prev),
+				       struct vm_area_struct, vm_rb);
+			if (prev == vma->vm_rb.rb_right) {
+				gap_start = vma->vm_prev ?
+					vma->vm_prev->vm_end : 0;
+				goto check_current;
+			}
+		}
+	}
+
+found:
+	/* We found a suitable gap. Clip it with the original high_limit. */
+	if (gap_end > info->high_limit)
+		gap_end = info->high_limit;
+
+found_highest:
+	/* Compute highest gap address at the desired alignment */
+	gap_end -= info->length;
+	gap_end -= (gap_end - info->align_offset) & info->align_mask;
+
+	VM_BUG_ON(gap_end < info->low_limit);
+	VM_BUG_ON(gap_end < gap_start);
+	return gap_end;
+}
+
 /* Get an address range which is currently unmapped.
  * For shmat() with addr=0.
  *
@@ -1418,7 +1775,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
-	unsigned long start_addr;
+	struct vm_unmapped_area_info info;
 
 	if (len > TASK_SIZE)
 		return -ENOMEM;
@@ -1433,40 +1790,13 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 		    (!vma || addr + len <= vma->vm_start))
 			return addr;
 	}
-	if (len > mm->cached_hole_size) {
-	        start_addr = addr = mm->free_area_cache;
-	} else {
-	        start_addr = addr = TASK_UNMAPPED_BASE;
-	        mm->cached_hole_size = 0;
-	}
 
-full_search:
-	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
-		/* At this point:  (!vma || addr < vma->vm_end). */
-		if (TASK_SIZE - len < addr) {
-			/*
-			 * Start a new search - just in case we missed
-			 * some holes.
-			 */
-			if (start_addr != TASK_UNMAPPED_BASE) {
-				addr = TASK_UNMAPPED_BASE;
-			        start_addr = addr;
-				mm->cached_hole_size = 0;
-				goto full_search;
-			}
-			return -ENOMEM;
-		}
-		if (!vma || addr + len <= vma->vm_start) {
-			/*
-			 * Remember the place where we stopped the search:
-			 */
-			mm->free_area_cache = addr + len;
-			return addr;
-		}
-		if (addr + mm->cached_hole_size < vma->vm_start)
-		        mm->cached_hole_size = vma->vm_start - addr;
-		addr = vma->vm_end;
-	}
+	info.flags = 0;
+	info.length = len;
+	info.low_limit = TASK_UNMAPPED_BASE;
+	info.high_limit = TASK_SIZE;
+	info.align_mask = 0;
+	return vm_unmapped_area(&info);
 }
 #endif	
 
@@ -1491,7 +1821,8 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 {
 	struct vm_area_struct *vma;
 	struct mm_struct *mm = current->mm;
-	unsigned long addr = addr0, start_addr;
+	unsigned long addr = addr0;
+	struct vm_unmapped_area_info info;
 
 	/* requested length too big for entire address space */
 	if (len > TASK_SIZE)
@@ -1509,53 +1840,12 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 			return addr;
 	}
 
-	/* check if free_area_cache is useful for us */
-	if (len <= mm->cached_hole_size) {
- 	        mm->cached_hole_size = 0;
- 		mm->free_area_cache = mm->mmap_base;
- 	}
-
-try_again:
-	/* either no address requested or can't fit in requested address hole */
-	start_addr = addr = mm->free_area_cache;
-
-	if (addr < len)
-		goto fail;
-
-	addr -= len;
-	do {
-		/*
-		 * Lookup failure means no vma is above this address,
-		 * else if new region fits below vma->vm_start,
-		 * return with success:
-		 */
-		vma = find_vma(mm, addr);
-		if (!vma || addr+len <= vma->vm_start)
-			/* remember the address as a hint for next time */
-			return (mm->free_area_cache = addr);
-
- 		/* remember the largest hole we saw so far */
- 		if (addr + mm->cached_hole_size < vma->vm_start)
- 		        mm->cached_hole_size = vma->vm_start - addr;
-
-		/* try just below the current vma->vm_start */
-		addr = vma->vm_start-len;
-	} while (len < vma->vm_start);
-
-fail:
-	/*
-	 * if hint left us with no space for the requested
-	 * mapping then try again:
-	 *
-	 * Note: this is different with the case of bottomup
-	 * which does the fully line-search, but we use find_vma
-	 * here that causes some holes skipped.
-	 */
-	if (start_addr != mm->mmap_base) {
-		mm->free_area_cache = mm->mmap_base;
-		mm->cached_hole_size = 0;
-		goto try_again;
-	}
+	info.flags = VM_UNMAPPED_AREA_TOPDOWN;
+	info.length = len;
+	info.low_limit = PAGE_SIZE;
+	info.high_limit = mm->mmap_base;
+	info.align_mask = 0;
+	addr = vm_unmapped_area(&info);
 
 	/*
 	 * A failed mmap() very likely causes application failure,
@@ -1563,14 +1853,13 @@ fail:
 	 * can happen with large stack limits and large mmap()
 	 * allocations.
 	 */
-	mm->cached_hole_size = ~0UL;
-  	mm->free_area_cache = TASK_UNMAPPED_BASE;
-	addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
-	/*
-	 * Restore the topdown base:
-	 */
-	mm->free_area_cache = mm->mmap_base;
-	mm->cached_hole_size = ~0UL;
+	if (addr & ~PAGE_MASK) {
+		VM_BUG_ON(addr != -ENOMEM);
+		info.flags = 0;
+		info.low_limit = TASK_UNMAPPED_BASE;
+		info.high_limit = TASK_SIZE;
+		addr = vm_unmapped_area(&info);
+	}
 
 	return addr;
 }
@@ -1783,6 +2072,10 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
 				anon_vma_interval_tree_pre_update_vma(vma);
 				vma->vm_end = address;
 				anon_vma_interval_tree_post_update_vma(vma);
+				if (vma->vm_next)
+					vma_gap_update(vma->vm_next);
+				else
+					vma->vm_mm->highest_vm_end = address;
 				perf_event_mmap(vma);
 			}
 		}
@@ -1837,6 +2130,7 @@ int expand_downwards(struct vm_area_struct *vma,
 				vma->vm_start = address;
 				vma->vm_pgoff -= grow;
 				anon_vma_interval_tree_post_update_vma(vma);
+				vma_gap_update(vma);
 				perf_event_mmap(vma);
 			}
 		}
@@ -1959,14 +2253,17 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma,
 	insertion_point = (prev ? &prev->vm_next : &mm->mmap);
 	vma->vm_prev = NULL;
 	do {
-		rb_erase(&vma->vm_rb, &mm->mm_rb);
+		vma_rb_erase(vma, &mm->mm_rb);
 		mm->map_count--;
 		tail_vma = vma;
 		vma = vma->vm_next;
 	} while (vma && vma->vm_start < end);
 	*insertion_point = vma;
-	if (vma)
+	if (vma) {
 		vma->vm_prev = prev;
+		vma_gap_update(vma);
+	} else
+		mm->highest_vm_end = prev ? prev->vm_end : 0;
 	tail_vma->vm_next = NULL;
 	if (mm->unmap_area == arch_unmap_area)
 		addr = prev ? prev->vm_end : mm->mmap_base;
diff --git a/mm/mprotect.c b/mm/mprotect.c
index a409926..d74a6fb 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -28,19 +28,13 @@
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
-#ifndef pgprot_modify
-static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
-{
-	return newprot;
-}
-#endif
-
-static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
+static unsigned long change_pte_range(struct mm_struct *mm, pmd_t *pmd,
 		unsigned long addr, unsigned long end, pgprot_t newprot,
 		int dirty_accountable)
 {
 	pte_t *pte, oldpte;
 	spinlock_t *ptl;
+	unsigned long pages = 0;
 
 	pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
 	arch_enter_lazy_mmu_mode();
@@ -60,6 +54,7 @@ static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
 				ptent = pte_mkwrite(ptent);
 
 			ptep_modify_prot_commit(mm, addr, pte, ptent);
+			pages++;
 		} else if (IS_ENABLED(CONFIG_MIGRATION) && !pte_file(oldpte)) {
 			swp_entry_t entry = pte_to_swp_entry(oldpte);
 
@@ -72,54 +67,65 @@ static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
 				set_pte_at(mm, addr, pte,
 					swp_entry_to_pte(entry));
 			}
+			pages++;
 		}
 	} while (pte++, addr += PAGE_SIZE, addr != end);
 	arch_leave_lazy_mmu_mode();
 	pte_unmap_unlock(pte - 1, ptl);
+
+	return pages;
 }
 
-static inline void change_pmd_range(struct vm_area_struct *vma, pud_t *pud,
+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)
 {
 	pmd_t *pmd;
 	unsigned long next;
+	unsigned long pages = 0;
 
 	pmd = pmd_offset(pud, addr);
 	do {
 		next = pmd_addr_end(addr, end);
 		if (pmd_trans_huge(*pmd)) {
 			if (next - addr != HPAGE_PMD_SIZE)
-				split_huge_page_pmd(vma->vm_mm, pmd);
-			else if (change_huge_pmd(vma, pmd, addr, newprot))
+				split_huge_page_pmd(vma, addr, pmd);
+			else if (change_huge_pmd(vma, pmd, addr, newprot)) {
+				pages += HPAGE_PMD_NR;
 				continue;
+			}
 			/* fall through */
 		}
 		if (pmd_none_or_clear_bad(pmd))
 			continue;
-		change_pte_range(vma->vm_mm, pmd, addr, next, newprot,
+		pages += change_pte_range(vma->vm_mm, pmd, addr, next, newprot,
 				 dirty_accountable);
 	} while (pmd++, addr = next, addr != end);
+
+	return pages;
 }
 
-static inline void change_pud_range(struct vm_area_struct *vma, pgd_t *pgd,
+static inline unsigned long change_pud_range(struct vm_area_struct *vma, pgd_t *pgd,
 		unsigned long addr, unsigned long end, pgprot_t newprot,
 		int dirty_accountable)
 {
 	pud_t *pud;
 	unsigned long next;
+	unsigned long pages = 0;
 
 	pud = pud_offset(pgd, addr);
 	do {
 		next = pud_addr_end(addr, end);
 		if (pud_none_or_clear_bad(pud))
 			continue;
-		change_pmd_range(vma, pud, addr, next, newprot,
+		pages += change_pmd_range(vma, pud, addr, next, newprot,
 				 dirty_accountable);
 	} while (pud++, addr = next, addr != end);
+
+	return pages;
 }
 
-static void change_protection(struct vm_area_struct *vma,
+static unsigned long change_protection_range(struct vm_area_struct *vma,
 		unsigned long addr, unsigned long end, pgprot_t newprot,
 		int dirty_accountable)
 {
@@ -127,6 +133,7 @@ static void change_protection(struct vm_area_struct *vma,
 	pgd_t *pgd;
 	unsigned long next;
 	unsigned long start = addr;
+	unsigned long pages = 0;
 
 	BUG_ON(addr >= end);
 	pgd = pgd_offset(mm, addr);
@@ -135,10 +142,32 @@ static void change_protection(struct vm_area_struct *vma,
 		next = pgd_addr_end(addr, end);
 		if (pgd_none_or_clear_bad(pgd))
 			continue;
-		change_pud_range(vma, pgd, addr, next, newprot,
+		pages += change_pud_range(vma, pgd, addr, next, newprot,
 				 dirty_accountable);
 	} while (pgd++, addr = next, addr != end);
-	flush_tlb_range(vma, start, end);
+
+	/* Only flush the TLB if we actually modified any entries: */
+	if (pages)
+		flush_tlb_range(vma, start, end);
+
+	return pages;
+}
+
+unsigned long change_protection(struct vm_area_struct *vma, unsigned long start,
+		       unsigned long end, pgprot_t newprot,
+		       int dirty_accountable)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long pages;
+
+	mmu_notifier_invalidate_range_start(mm, start, end);
+	if (is_vm_hugetlb_page(vma))
+		pages = hugetlb_change_protection(vma, start, end, newprot);
+	else
+		pages = change_protection_range(vma, start, end, newprot, dirty_accountable);
+	mmu_notifier_invalidate_range_end(mm, start, end);
+
+	return pages;
 }
 
 int
@@ -213,12 +242,8 @@ success:
 		dirty_accountable = 1;
 	}
 
-	mmu_notifier_invalidate_range_start(mm, start, end);
-	if (is_vm_hugetlb_page(vma))
-		hugetlb_change_protection(vma, start, end, vma->vm_page_prot);
-	else
-		change_protection(vma, start, end, vma->vm_page_prot, dirty_accountable);
-	mmu_notifier_invalidate_range_end(mm, start, end);
+	change_protection(vma, start, end, vma->vm_page_prot, dirty_accountable);
+
 	vm_stat_account(mm, oldflags, vma->vm_file, -nrpages);
 	vm_stat_account(mm, newflags, vma->vm_file, nrpages);
 	perf_event_mmap(vma);
diff --git a/mm/mremap.c b/mm/mremap.c
index 1b61c2d..eabb24d 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -182,7 +182,7 @@ unsigned long move_page_tables(struct vm_area_struct *vma,
 				need_flush = true;
 				continue;
 			} else if (!err) {
-				split_huge_page_pmd(vma->vm_mm, old_pmd);
+				split_huge_page_pmd(vma, old_addr, old_pmd);
 			}
 			VM_BUG_ON(pmd_trans_huge(*old_pmd));
 		}
diff --git a/mm/nobootmem.c b/mm/nobootmem.c
index bd82f6b..b8294fc 100644
--- a/mm/nobootmem.c
+++ b/mm/nobootmem.c
@@ -137,6 +137,22 @@ unsigned long __init free_low_memory_core_early(int nodeid)
 	return count;
 }
 
+static void reset_node_lowmem_managed_pages(pg_data_t *pgdat)
+{
+	struct zone *z;
+
+	/*
+	 * In free_area_init_core(), highmem zone's managed_pages is set to
+	 * present_pages, and bootmem allocator doesn't allocate from highmem
+	 * zones. So there's no need to recalculate managed_pages because all
+	 * highmem pages will be managed by the buddy system. Here highmem
+	 * zone also includes highmem movable zone.
+	 */
+	for (z = pgdat->node_zones; z < pgdat->node_zones + MAX_NR_ZONES; z++)
+		if (!is_highmem(z))
+			z->managed_pages = 0;
+}
+
 /**
  * free_all_bootmem_node - release a node's free pages to the buddy allocator
  * @pgdat: node to be released
@@ -146,6 +162,7 @@ unsigned long __init free_low_memory_core_early(int nodeid)
 unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
 {
 	register_page_bootmem_info_node(pgdat);
+	reset_node_lowmem_managed_pages(pgdat);
 
 	/* free_low_memory_core_early(MAX_NUMNODES) will be called later */
 	return 0;
@@ -158,6 +175,11 @@ unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
  */
 unsigned long __init free_all_bootmem(void)
 {
+	struct pglist_data *pgdat;
+
+	for_each_online_pgdat(pgdat)
+		reset_node_lowmem_managed_pages(pgdat);
+
 	/*
 	 * We need to use MAX_NUMNODES instead of NODE_DATA(0)->node_id
 	 *  because in some case like Node0 doesn't have RAM installed
diff --git a/mm/nommu.c b/mm/nommu.c
index 45131b4..79c3cac 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -66,6 +66,21 @@ int heap_stack_gap = 0;
 
 atomic_long_t mmap_pages_allocated;
 
+/*
+ * The global memory commitment made in the system can be a metric
+ * that can be used to drive ballooning decisions when Linux is hosted
+ * as a guest. On Hyper-V, the host implements a policy engine for dynamically
+ * balancing memory across competing virtual machines that are hosted.
+ * Several metrics drive this policy engine including the guest reported
+ * memory commitment.
+ */
+unsigned long vm_memory_committed(void)
+{
+	return percpu_counter_read_positive(&vm_committed_as);
+}
+
+EXPORT_SYMBOL_GPL(vm_memory_committed);
+
 EXPORT_SYMBOL(mem_map);
 EXPORT_SYMBOL(num_physpages);
 
diff --git a/mm/numa.c b/mm/numa.c
new file mode 100644
index 0000000..8d18800
--- /dev/null
+++ b/mm/numa.c
@@ -0,0 +1,73 @@
+/*
+ * Generic NUMA page table entry support. This code reuses
+ * PROT_NONE: an architecture can choose to use its own
+ * implementation, by setting CONFIG_ARCH_SUPPORTS_NUMA_BALANCING
+ * and not setting CONFIG_ARCH_WANTS_NUMA_GENERIC_PGPROT.
+ */
+#include <linux/mm.h>
+
+static inline pgprot_t vma_prot_none(struct vm_area_struct *vma)
+{
+	/*
+	 * obtain PROT_NONE by removing READ|WRITE|EXEC privs
+	 */
+	vm_flags_t vmflags = vma->vm_flags & ~(VM_READ|VM_WRITE|VM_EXEC);
+
+	return pgprot_modify(vma->vm_page_prot, vm_get_page_prot(vmflags));
+}
+
+bool pte_numa(struct vm_area_struct *vma, pte_t pte)
+{
+	/*
+	 * For NUMA page faults, we use PROT_NONE ptes in VMAs with
+	 * "normal" vma->vm_page_prot protections.  Genuine PROT_NONE
+	 * VMAs should never get here, because the fault handling code
+	 * will notice that the VMA has no read or write permissions.
+	 *
+	 * This means we cannot get 'special' PROT_NONE faults from genuine
+	 * PROT_NONE maps, nor from PROT_WRITE file maps that do dirty
+	 * tracking.
+	 *
+	 * Neither case is really interesting for our current use though so we
+	 * don't care.
+	 */
+	if (pte_same(pte, pte_modify(pte, vma->vm_page_prot)))
+		return false;
+
+	return pte_same(pte, pte_modify(pte, vma_prot_none(vma)));
+}
+
+pte_t pte_mknuma(struct vm_area_struct *vma, pte_t pte)
+{
+	return pte_modify(pte, vma_prot_none(vma));
+}
+
+#ifdef CONFIG_ARCH_USES_NUMA_GENERIC_PGPROT_HUGEPAGE
+bool pmd_numa(struct vm_area_struct *vma, pmd_t pmd)
+{
+	/*
+	 * See pte_numa() above
+	 */
+	if (pmd_same(pmd, pmd_modify(pmd, vma->vm_page_prot)))
+		return false;
+
+	return pmd_same(pmd, pmd_modify(pmd, vma_prot_none(vma)));
+}
+#endif
+
+/*
+ * The scheduler uses this function to mark a range of virtual
+ * memory inaccessible to user-space, for the purposes of probing
+ * the composition of the working set.
+ *
+ * The resulting page faults will be demultiplexed into:
+ *
+ *    mm/memory.c::do_numa_page()
+ *    mm/huge_memory.c::do_huge_pmd_numa_page()
+ *
+ * This generic version simply uses PROT_NONE.
+ */
+unsigned long change_prot_numa(struct vm_area_struct *vma, unsigned long start, unsigned long end)
+{
+	return change_protection(vma, start, end, vma_prot_none(vma), 0);
+}
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 79e0f3e..0399f14 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -44,48 +44,6 @@ int sysctl_oom_kill_allocating_task;
 int sysctl_oom_dump_tasks = 1;
 static DEFINE_SPINLOCK(zone_scan_lock);
 
-/*
- * compare_swap_oom_score_adj() - compare and swap current's oom_score_adj
- * @old_val: old oom_score_adj for compare
- * @new_val: new oom_score_adj for swap
- *
- * Sets the oom_score_adj value for current to @new_val iff its present value is
- * @old_val.  Usually used to reinstate a previous value to prevent racing with
- * userspacing tuning the value in the interim.
- */
-void compare_swap_oom_score_adj(int old_val, int new_val)
-{
-	struct sighand_struct *sighand = current->sighand;
-
-	spin_lock_irq(&sighand->siglock);
-	if (current->signal->oom_score_adj == old_val)
-		current->signal->oom_score_adj = new_val;
-	trace_oom_score_adj_update(current);
-	spin_unlock_irq(&sighand->siglock);
-}
-
-/**
- * test_set_oom_score_adj() - set current's oom_score_adj and return old value
- * @new_val: new oom_score_adj value
- *
- * Sets the oom_score_adj value for current to @new_val with proper
- * synchronization and returns the old value.  Usually used to temporarily
- * set a value, save the old value in the caller, and then reinstate it later.
- */
-int test_set_oom_score_adj(int new_val)
-{
-	struct sighand_struct *sighand = current->sighand;
-	int old_val;
-
-	spin_lock_irq(&sighand->siglock);
-	old_val = current->signal->oom_score_adj;
-	current->signal->oom_score_adj = new_val;
-	trace_oom_score_adj_update(current);
-	spin_unlock_irq(&sighand->siglock);
-
-	return old_val;
-}
-
 #ifdef CONFIG_NUMA
 /**
  * has_intersects_mems_allowed() - check task eligiblity for kill
@@ -193,7 +151,7 @@ unsigned long oom_badness(struct task_struct *p, struct mem_cgroup *memcg,
 	if (!p)
 		return 0;
 
-	adj = p->signal->oom_score_adj;
+	adj = (long)p->signal->oom_score_adj;
 	if (adj == OOM_SCORE_ADJ_MIN) {
 		task_unlock(p);
 		return 0;
@@ -257,7 +215,7 @@ static enum oom_constraint constrained_alloc(struct zonelist *zonelist,
 	 * the page allocator means a mempolicy is in effect.  Cpuset policy
 	 * is enforced in get_page_from_freelist().
 	 */
-	if (nodemask && !nodes_subset(node_states[N_HIGH_MEMORY], *nodemask)) {
+	if (nodemask && !nodes_subset(node_states[N_MEMORY], *nodemask)) {
 		*totalpages = total_swap_pages;
 		for_each_node_mask(nid, *nodemask)
 			*totalpages += node_spanned_pages(nid);
@@ -310,26 +268,20 @@ enum oom_scan_t oom_scan_process_thread(struct task_struct *task,
 	if (!task->mm)
 		return OOM_SCAN_CONTINUE;
 
-	if (task->flags & PF_EXITING) {
+	/*
+	 * If task is allocating a lot of memory and has been marked to be
+	 * killed first if it triggers an oom, then select it.
+	 */
+	if (oom_task_origin(task))
+		return OOM_SCAN_SELECT;
+
+	if (task->flags & PF_EXITING && !force_kill) {
 		/*
-		 * If task is current and is in the process of releasing memory,
-		 * allow the "kill" to set TIF_MEMDIE, which will allow it to
-		 * access memory reserves.  Otherwise, it may stall forever.
-		 *
-		 * The iteration isn't broken here, however, in case other
-		 * threads are found to have already been oom killed.
+		 * If this task is not being ptraced on exit, then wait for it
+		 * to finish before killing some other task unnecessarily.
 		 */
-		if (task == current)
-			return OOM_SCAN_SELECT;
-		else if (!force_kill) {
-			/*
-			 * If this task is not being ptraced on exit, then wait
-			 * for it to finish before killing some other task
-			 * unnecessarily.
-			 */
-			if (!(task->group_leader->ptrace & PT_TRACE_EXIT))
-				return OOM_SCAN_ABORT;
-		}
+		if (!(task->group_leader->ptrace & PT_TRACE_EXIT))
+			return OOM_SCAN_ABORT;
 	}
 	return OOM_SCAN_OK;
 }
@@ -412,7 +364,7 @@ static void dump_tasks(const struct mem_cgroup *memcg, const nodemask_t *nodemas
 			continue;
 		}
 
-		pr_info("[%5d] %5d %5d %8lu %8lu %7lu %8lu         %5d %s\n",
+		pr_info("[%5d] %5d %5d %8lu %8lu %7lu %8lu         %5hd %s\n",
 			task->pid, from_kuid(&init_user_ns, task_uid(task)),
 			task->tgid, task->mm->total_vm, get_mm_rss(task->mm),
 			task->mm->nr_ptes,
@@ -428,7 +380,7 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,
 {
 	task_lock(current);
 	pr_warning("%s invoked oom-killer: gfp_mask=0x%x, order=%d, "
-		"oom_score_adj=%d\n",
+		"oom_score_adj=%hd\n",
 		current->comm, gfp_mask, order,
 		current->signal->oom_score_adj);
 	cpuset_print_task_mems_allowed(current);
@@ -639,43 +591,6 @@ void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_mask)
 	spin_unlock(&zone_scan_lock);
 }
 
-/*
- * Try to acquire the oom killer lock for all system zones.  Returns zero if a
- * parallel oom killing is taking place, otherwise locks all zones and returns
- * non-zero.
- */
-static int try_set_system_oom(void)
-{
-	struct zone *zone;
-	int ret = 1;
-
-	spin_lock(&zone_scan_lock);
-	for_each_populated_zone(zone)
-		if (zone_is_oom_locked(zone)) {
-			ret = 0;
-			goto out;
-		}
-	for_each_populated_zone(zone)
-		zone_set_flag(zone, ZONE_OOM_LOCKED);
-out:
-	spin_unlock(&zone_scan_lock);
-	return ret;
-}
-
-/*
- * Clears ZONE_OOM_LOCKED for all system zones so that failed allocation
- * attempts or page faults may now recall the oom killer, if necessary.
- */
-static void clear_system_oom(void)
-{
-	struct zone *zone;
-
-	spin_lock(&zone_scan_lock);
-	for_each_populated_zone(zone)
-		zone_clear_flag(zone, ZONE_OOM_LOCKED);
-	spin_unlock(&zone_scan_lock);
-}
-
 /**
  * out_of_memory - kill the "best" process when we run out of memory
  * @zonelist: zonelist pointer
@@ -706,11 +621,11 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
 		return;
 
 	/*
-	 * If current has a pending SIGKILL, then automatically select it.  The
-	 * goal is to allow it to allocate so that it may quickly exit and free
-	 * its memory.
+	 * If current has a pending SIGKILL or is exiting, then automatically
+	 * select it.  The goal is to allow it to allocate so that it may
+	 * quickly exit and free its memory.
 	 */
-	if (fatal_signal_pending(current)) {
+	if (fatal_signal_pending(current) || current->flags & PF_EXITING) {
 		set_thread_flag(TIF_MEMDIE);
 		return;
 	}
@@ -756,15 +671,16 @@ out:
 
 /*
  * The pagefault handler calls here because it is out of memory, so kill a
- * memory-hogging task.  If a populated zone has ZONE_OOM_LOCKED set, a parallel
- * oom killing is already in progress so do nothing.  If a task is found with
- * TIF_MEMDIE set, it has been killed so do nothing and allow it to exit.
+ * memory-hogging task.  If any populated zone has ZONE_OOM_LOCKED set, a
+ * parallel oom killing is already in progress so do nothing.
  */
 void pagefault_out_of_memory(void)
 {
-	if (try_set_system_oom()) {
+	struct zonelist *zonelist = node_zonelist(first_online_node,
+						  GFP_KERNEL);
+
+	if (try_set_zonelist_oom(zonelist, GFP_KERNEL)) {
 		out_of_memory(NULL, 0, 0, NULL, false);
-		clear_system_oom();
+		clear_zonelist_oom(zonelist, GFP_KERNEL);
 	}
-	schedule_timeout_killable(1);
 }
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 830893b..6f42712 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -1069,7 +1069,7 @@ static void bdi_update_bandwidth(struct backing_dev_info *bdi,
 }
 
 /*
- * After a task dirtied this many pages, balance_dirty_pages_ratelimited_nr()
+ * After a task dirtied this many pages, balance_dirty_pages_ratelimited()
  * will look to see if it needs to start dirty throttling.
  *
  * If dirty_poll_interval is too low, big NUMA machines will call the expensive
@@ -1436,9 +1436,8 @@ static DEFINE_PER_CPU(int, bdp_ratelimits);
 DEFINE_PER_CPU(int, dirty_throttle_leaks) = 0;
 
 /**
- * balance_dirty_pages_ratelimited_nr - balance dirty memory state
+ * balance_dirty_pages_ratelimited - balance dirty memory state
  * @mapping: address_space which was dirtied
- * @nr_pages_dirtied: number of pages which the caller has just dirtied
  *
  * Processes which are dirtying memory should call in here once for each page
  * which was newly dirtied.  The function will periodically check the system's
@@ -1449,8 +1448,7 @@ DEFINE_PER_CPU(int, dirty_throttle_leaks) = 0;
  * limit we decrease the ratelimiting by a lot, to prevent individual processes
  * from overshooting the limit by (ratelimit_pages) each.
  */
-void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
-					unsigned long nr_pages_dirtied)
+void balance_dirty_pages_ratelimited(struct address_space *mapping)
 {
 	struct backing_dev_info *bdi = mapping->backing_dev_info;
 	int ratelimit;
@@ -1484,6 +1482,7 @@ void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
 	 */
 	p = &__get_cpu_var(dirty_throttle_leaks);
 	if (*p > 0 && current->nr_dirtied < ratelimit) {
+		unsigned long nr_pages_dirtied;
 		nr_pages_dirtied = min(*p, ratelimit - current->nr_dirtied);
 		*p -= nr_pages_dirtied;
 		current->nr_dirtied += nr_pages_dirtied;
@@ -1493,7 +1492,7 @@ void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
 	if (unlikely(current->nr_dirtied >= ratelimit))
 		balance_dirty_pages(mapping, current->nr_dirtied);
 }
-EXPORT_SYMBOL(balance_dirty_pages_ratelimited_nr);
+EXPORT_SYMBOL(balance_dirty_pages_ratelimited);
 
 void throttle_vm_writeout(gfp_t gfp_mask)
 {
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index bcb72c6..965f003 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -90,6 +90,9 @@ nodemask_t node_states[NR_NODE_STATES] __read_mostly = {
 #ifdef CONFIG_HIGHMEM
 	[N_HIGH_MEMORY] = { { [0] = 1UL } },
 #endif
+#ifdef CONFIG_MOVABLE_NODE
+	[N_MEMORY] = { { [0] = 1UL } },
+#endif
 	[N_CPU] = { { [0] = 1UL } },
 #endif	/* NUMA */
 };
@@ -368,8 +371,7 @@ static int destroy_compound_page(struct page *page, unsigned long order)
 	int nr_pages = 1 << order;
 	int bad = 0;
 
-	if (unlikely(compound_order(page) != order) ||
-	    unlikely(!PageHead(page))) {
+	if (unlikely(compound_order(page) != order)) {
 		bad_page(page);
 		bad++;
 	}
@@ -667,11 +669,13 @@ static void free_pcppages_bulk(struct zone *zone, int count,
 			/* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */
 			__free_one_page(page, zone, 0, mt);
 			trace_mm_page_pcpu_drain(page, 0, mt);
-			if (is_migrate_cma(mt))
-				__mod_zone_page_state(zone, NR_FREE_CMA_PAGES, 1);
+			if (likely(get_pageblock_migratetype(page) != MIGRATE_ISOLATE)) {
+				__mod_zone_page_state(zone, NR_FREE_PAGES, 1);
+				if (is_migrate_cma(mt))
+					__mod_zone_page_state(zone, NR_FREE_CMA_PAGES, 1);
+			}
 		} while (--to_free && --batch_free && !list_empty(list));
 	}
-	__mod_zone_page_state(zone, NR_FREE_PAGES, count);
 	spin_unlock(&zone->lock);
 }
 
@@ -730,6 +734,13 @@ static void __free_pages_ok(struct page *page, unsigned int order)
 	local_irq_restore(flags);
 }
 
+/*
+ * Read access to zone->managed_pages is safe because it's unsigned long,
+ * but we still need to serialize writers. Currently all callers of
+ * __free_pages_bootmem() except put_page_bootmem() should only be used
+ * at boot time. So for shorter boot time, we shift the burden to
+ * put_page_bootmem() to serialize writers.
+ */
 void __meminit __free_pages_bootmem(struct page *page, unsigned int order)
 {
 	unsigned int nr_pages = 1 << order;
@@ -745,6 +756,7 @@ void __meminit __free_pages_bootmem(struct page *page, unsigned int order)
 		set_page_count(p, 0);
 	}
 
+	page_zone(page)->managed_pages += 1 << order;
 	set_page_refcounted(page);
 	__free_pages(page, order);
 }
@@ -1392,21 +1404,22 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype)
 
 	zone = page_zone(page);
 	order = page_order(page);
+	mt = get_pageblock_migratetype(page);
 
-	/* Obey watermarks as if the page was being allocated */
-	watermark = low_wmark_pages(zone) + (1 << order);
-	if (!zone_watermark_ok(zone, 0, watermark, 0, 0))
-		return 0;
+	if (mt != MIGRATE_ISOLATE) {
+		/* Obey watermarks as if the page was being allocated */
+		watermark = low_wmark_pages(zone) + (1 << order);
+		if (!zone_watermark_ok(zone, 0, watermark, 0, 0))
+			return 0;
+
+		__mod_zone_freepage_state(zone, -(1UL << alloc_order), mt);
+	}
 
 	/* Remove page from free list */
 	list_del(&page->lru);
 	zone->free_area[order].nr_free--;
 	rmv_page_order(page);
 
-	mt = get_pageblock_migratetype(page);
-	if (unlikely(mt != MIGRATE_ISOLATE))
-		__mod_zone_freepage_state(zone, -(1UL << alloc_order), mt);
-
 	if (alloc_order != order)
 		expand(zone, page, alloc_order, order,
 			&zone->free_area[order], migratetype);
@@ -1422,7 +1435,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype)
 		}
 	}
 
-	return 1UL << order;
+	return 1UL << alloc_order;
 }
 
 /*
@@ -1692,7 +1705,7 @@ bool zone_watermark_ok_safe(struct zone *z, int order, unsigned long mark,
  *
  * If the zonelist cache is present in the passed in zonelist, then
  * returns a pointer to the allowed node mask (either the current
- * tasks mems_allowed, or node_states[N_HIGH_MEMORY].)
+ * tasks mems_allowed, or node_states[N_MEMORY].)
  *
  * If the zonelist cache is not available for this zonelist, does
  * nothing and returns NULL.
@@ -1721,7 +1734,7 @@ static nodemask_t *zlc_setup(struct zonelist *zonelist, int alloc_flags)
 
 	allowednodes = !in_interrupt() && (alloc_flags & ALLOC_CPUSET) ?
 					&cpuset_current_mems_allowed :
-					&node_states[N_HIGH_MEMORY];
+					&node_states[N_MEMORY];
 	return allowednodes;
 }
 
@@ -1871,7 +1884,7 @@ zonelist_scan:
 	 */
 	for_each_zone_zonelist_nodemask(zone, z, zonelist,
 						high_zoneidx, nodemask) {
-		if (NUMA_BUILD && zlc_active &&
+		if (IS_ENABLED(CONFIG_NUMA) && zlc_active &&
 			!zlc_zone_worth_trying(zonelist, z, allowednodes))
 				continue;
 		if ((alloc_flags & ALLOC_CPUSET) &&
@@ -1917,7 +1930,8 @@ zonelist_scan:
 				    classzone_idx, alloc_flags))
 				goto try_this_zone;
 
-			if (NUMA_BUILD && !did_zlc_setup && nr_online_nodes > 1) {
+			if (IS_ENABLED(CONFIG_NUMA) &&
+					!did_zlc_setup && nr_online_nodes > 1) {
 				/*
 				 * we do zlc_setup if there are multiple nodes
 				 * and before considering the first zone allowed
@@ -1936,7 +1950,7 @@ zonelist_scan:
 			 * As we may have just activated ZLC, check if the first
 			 * eligible zone has failed zone_reclaim recently.
 			 */
-			if (NUMA_BUILD && zlc_active &&
+			if (IS_ENABLED(CONFIG_NUMA) && zlc_active &&
 				!zlc_zone_worth_trying(zonelist, z, allowednodes))
 				continue;
 
@@ -1962,11 +1976,11 @@ try_this_zone:
 		if (page)
 			break;
 this_zone_full:
-		if (NUMA_BUILD)
+		if (IS_ENABLED(CONFIG_NUMA))
 			zlc_mark_zone_full(zonelist, z);
 	}
 
-	if (unlikely(NUMA_BUILD && page == NULL && zlc_active)) {
+	if (unlikely(IS_ENABLED(CONFIG_NUMA) && page == NULL && zlc_active)) {
 		/* Disable zlc cache for second zonelist scan */
 		zlc_active = 0;
 		goto zonelist_scan;
@@ -2266,7 +2280,7 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,
 		return NULL;
 
 	/* After successful reclaim, reconsider all zones for allocation */
-	if (NUMA_BUILD)
+	if (IS_ENABLED(CONFIG_NUMA))
 		zlc_clear_zones_full(zonelist);
 
 retry:
@@ -2378,6 +2392,15 @@ bool gfp_pfmemalloc_allowed(gfp_t gfp_mask)
 	return !!(gfp_to_alloc_flags(gfp_mask) & ALLOC_NO_WATERMARKS);
 }
 
+/* Returns true if the allocation is likely for THP */
+static bool is_thp_alloc(gfp_t gfp_mask, unsigned int order)
+{
+	if (order == pageblock_order &&
+	    (gfp_mask & (__GFP_MOVABLE|__GFP_REPEAT)) == __GFP_MOVABLE)
+		return true;
+	return false;
+}
+
 static inline struct page *
 __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
 	struct zonelist *zonelist, enum zone_type high_zoneidx,
@@ -2412,11 +2435,14 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
 	 * allowed per node queues are empty and that nodes are
 	 * over allocated.
 	 */
-	if (NUMA_BUILD && (gfp_mask & GFP_THISNODE) == GFP_THISNODE)
+	if (IS_ENABLED(CONFIG_NUMA) &&
+			(gfp_mask & GFP_THISNODE) == GFP_THISNODE)
 		goto nopage;
 
 restart:
-	wake_all_kswapd(order, zonelist, high_zoneidx,
+	/* The decision whether to wake kswapd for THP is made later */
+	if (!is_thp_alloc(gfp_mask, order))
+		wake_all_kswapd(order, zonelist, high_zoneidx,
 					zone_idx(preferred_zone));
 
 	/*
@@ -2487,15 +2513,21 @@ rebalance:
 		goto got_pg;
 	sync_migration = true;
 
-	/*
-	 * If compaction is deferred for high-order allocations, it is because
-	 * sync compaction recently failed. In this is the case and the caller
-	 * requested a movable allocation that does not heavily disrupt the
-	 * system then fail the allocation instead of entering direct reclaim.
-	 */
-	if ((deferred_compaction || contended_compaction) &&
-	    (gfp_mask & (__GFP_MOVABLE|__GFP_REPEAT)) == __GFP_MOVABLE)
-		goto nopage;
+	if (is_thp_alloc(gfp_mask, order)) {
+		/*
+		 * If compaction is deferred for high-order allocations, it is
+		 * because sync compaction recently failed. If this is the case
+		 * and the caller requested a movable allocation that does not
+		 * heavily disrupt the system then fail the allocation instead
+		 * of entering direct reclaim.
+		 */
+		if (deferred_compaction || contended_compaction)
+			goto nopage;
+
+		/* If process is willing to reclaim/compact then wake kswapd */
+		wake_all_kswapd(order, zonelist, high_zoneidx,
+					zone_idx(preferred_zone));
+	}
 
 	/* Try direct reclaim and then allocating */
 	page = __alloc_pages_direct_reclaim(gfp_mask, order,
@@ -2595,6 +2627,7 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
 	int migratetype = allocflags_to_migratetype(gfp_mask);
 	unsigned int cpuset_mems_cookie;
 	int alloc_flags = ALLOC_WMARK_LOW|ALLOC_CPUSET;
+	struct mem_cgroup *memcg = NULL;
 
 	gfp_mask &= gfp_allowed_mask;
 
@@ -2613,6 +2646,13 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
 	if (unlikely(!zonelist->_zonerefs->zone))
 		return NULL;
 
+	/*
+	 * Will only have any effect when __GFP_KMEMCG is set.  This is
+	 * verified in the (always inline) callee
+	 */
+	if (!memcg_kmem_newpage_charge(gfp_mask, &memcg, order))
+		return NULL;
+
 retry_cpuset:
 	cpuset_mems_cookie = get_mems_allowed();
 
@@ -2648,6 +2688,8 @@ out:
 	if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page))
 		goto retry_cpuset;
 
+	memcg_kmem_commit_charge(page, memcg, order);
+
 	return page;
 }
 EXPORT_SYMBOL(__alloc_pages_nodemask);
@@ -2700,6 +2742,31 @@ void free_pages(unsigned long addr, unsigned int order)
 
 EXPORT_SYMBOL(free_pages);
 
+/*
+ * __free_memcg_kmem_pages and free_memcg_kmem_pages will free
+ * pages allocated with __GFP_KMEMCG.
+ *
+ * Those pages are accounted to a particular memcg, embedded in the
+ * corresponding page_cgroup. To avoid adding a hit in the allocator to search
+ * for that information only to find out that it is NULL for users who have no
+ * interest in that whatsoever, we provide these functions.
+ *
+ * The caller knows better which flags it relies on.
+ */
+void __free_memcg_kmem_pages(struct page *page, unsigned int order)
+{
+	memcg_kmem_uncharge_pages(page, order);
+	__free_pages(page, order);
+}
+
+void free_memcg_kmem_pages(unsigned long addr, unsigned int order)
+{
+	if (addr != 0) {
+		VM_BUG_ON(!virt_addr_valid((void *)addr));
+		__free_memcg_kmem_pages(virt_to_page((void *)addr), order);
+	}
+}
+
 static void *make_alloc_exact(unsigned long addr, unsigned order, size_t size)
 {
 	if (addr) {
@@ -2818,7 +2885,7 @@ unsigned int nr_free_pagecache_pages(void)
 
 static inline void show_node(struct zone *zone)
 {
-	if (NUMA_BUILD)
+	if (IS_ENABLED(CONFIG_NUMA))
 		printk("Node %d ", zone_to_nid(zone));
 }
 
@@ -2876,6 +2943,31 @@ out:
 
 #define K(x) ((x) << (PAGE_SHIFT-10))
 
+static void show_migration_types(unsigned char type)
+{
+	static const char types[MIGRATE_TYPES] = {
+		[MIGRATE_UNMOVABLE]	= 'U',
+		[MIGRATE_RECLAIMABLE]	= 'E',
+		[MIGRATE_MOVABLE]	= 'M',
+		[MIGRATE_RESERVE]	= 'R',
+#ifdef CONFIG_CMA
+		[MIGRATE_CMA]		= 'C',
+#endif
+		[MIGRATE_ISOLATE]	= 'I',
+	};
+	char tmp[MIGRATE_TYPES + 1];
+	char *p = tmp;
+	int i;
+
+	for (i = 0; i < MIGRATE_TYPES; i++) {
+		if (type & (1 << i))
+			*p++ = types[i];
+	}
+
+	*p = '\0';
+	printk("(%s) ", tmp);
+}
+
 /*
  * Show free area list (used inside shift_scroll-lock stuff)
  * We also calculate the percentage fragmentation. We do this by counting the
@@ -2950,6 +3042,7 @@ void show_free_areas(unsigned int filter)
 			" isolated(anon):%lukB"
 			" isolated(file):%lukB"
 			" present:%lukB"
+			" managed:%lukB"
 			" mlocked:%lukB"
 			" dirty:%lukB"
 			" writeback:%lukB"
@@ -2979,6 +3072,7 @@ void show_free_areas(unsigned int filter)
 			K(zone_page_state(zone, NR_ISOLATED_ANON)),
 			K(zone_page_state(zone, NR_ISOLATED_FILE)),
 			K(zone->present_pages),
+			K(zone->managed_pages),
 			K(zone_page_state(zone, NR_MLOCK)),
 			K(zone_page_state(zone, NR_FILE_DIRTY)),
 			K(zone_page_state(zone, NR_WRITEBACK)),
@@ -3004,6 +3098,7 @@ void show_free_areas(unsigned int filter)
 
 	for_each_populated_zone(zone) {
  		unsigned long nr[MAX_ORDER], flags, order, total = 0;
+		unsigned char types[MAX_ORDER];
 
 		if (skip_free_areas_node(filter, zone_to_nid(zone)))
 			continue;
@@ -3012,12 +3107,24 @@ void show_free_areas(unsigned int filter)
 
 		spin_lock_irqsave(&zone->lock, flags);
 		for (order = 0; order < MAX_ORDER; order++) {
-			nr[order] = zone->free_area[order].nr_free;
+			struct free_area *area = &zone->free_area[order];
+			int type;
+
+			nr[order] = area->nr_free;
 			total += nr[order] << order;
+
+			types[order] = 0;
+			for (type = 0; type < MIGRATE_TYPES; type++) {
+				if (!list_empty(&area->free_list[type]))
+					types[order] |= 1 << type;
+			}
 		}
 		spin_unlock_irqrestore(&zone->lock, flags);
-		for (order = 0; order < MAX_ORDER; order++)
+		for (order = 0; order < MAX_ORDER; order++) {
 			printk("%lu*%lukB ", nr[order], K(1UL) << order);
+			if (nr[order])
+				show_migration_types(types[order]);
+		}
 		printk("= %lukB\n", K(total));
 	}
 
@@ -3194,7 +3301,7 @@ static int find_next_best_node(int node, nodemask_t *used_node_mask)
 		return node;
 	}
 
-	for_each_node_state(n, N_HIGH_MEMORY) {
+	for_each_node_state(n, N_MEMORY) {
 
 		/* Don't want a node to appear more than once */
 		if (node_isset(n, *used_node_mask))
@@ -3336,7 +3443,7 @@ static int default_zonelist_order(void)
  	 * local memory, NODE_ORDER may be suitable.
          */
 	average_size = total_size /
-				(nodes_weight(node_states[N_HIGH_MEMORY]) + 1);
+				(nodes_weight(node_states[N_MEMORY]) + 1);
 	for_each_online_node(nid) {
 		low_kmem_size = 0;
 		total_size = 0;
@@ -3816,8 +3923,11 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
 		 * exist on hotplugged memory.
 		 */
 		if (context == MEMMAP_EARLY) {
-			if (!early_pfn_valid(pfn))
+			if (!early_pfn_valid(pfn)) {
+				pfn = ALIGN(pfn + MAX_ORDER_NR_PAGES,
+						MAX_ORDER_NR_PAGES) - 1;
 				continue;
+			}
 			if (!early_pfn_in_nid(pfn, nid))
 				continue;
 		}
@@ -4432,6 +4542,26 @@ void __init set_pageblock_order(void)
 
 #endif /* CONFIG_HUGETLB_PAGE_SIZE_VARIABLE */
 
+static unsigned long __paginginit calc_memmap_size(unsigned long spanned_pages,
+						   unsigned long present_pages)
+{
+	unsigned long pages = spanned_pages;
+
+	/*
+	 * Provide a more accurate estimation if there are holes within
+	 * the zone and SPARSEMEM is in use. If there are holes within the
+	 * zone, each populated memory region may cost us one or two extra
+	 * memmap pages due to alignment because memmap pages for each
+	 * populated regions may not naturally algined on page boundary.
+	 * So the (present_pages >> 4) heuristic is a tradeoff for that.
+	 */
+	if (spanned_pages > present_pages + (present_pages >> 4) &&
+	    IS_ENABLED(CONFIG_SPARSEMEM))
+		pages = present_pages;
+
+	return PAGE_ALIGN(pages * sizeof(struct page)) >> PAGE_SHIFT;
+}
+
 /*
  * Set up the zone data structures:
  *   - mark all pages reserved
@@ -4455,48 +4585,56 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
 
 	for (j = 0; j < MAX_NR_ZONES; j++) {
 		struct zone *zone = pgdat->node_zones + j;
-		unsigned long size, realsize, memmap_pages;
+		unsigned long size, realsize, freesize, memmap_pages;
 
 		size = zone_spanned_pages_in_node(nid, j, zones_size);
-		realsize = size - zone_absent_pages_in_node(nid, j,
+		realsize = freesize = size - zone_absent_pages_in_node(nid, j,
 								zholes_size);
 
 		/*
-		 * Adjust realsize so that it accounts for how much memory
+		 * Adjust freesize so that it accounts for how much memory
 		 * is used by this zone for memmap. This affects the watermark
 		 * and per-cpu initialisations
 		 */
-		memmap_pages =
-			PAGE_ALIGN(size * sizeof(struct page)) >> PAGE_SHIFT;
-		if (realsize >= memmap_pages) {
-			realsize -= memmap_pages;
+		memmap_pages = calc_memmap_size(size, realsize);
+		if (freesize >= memmap_pages) {
+			freesize -= memmap_pages;
 			if (memmap_pages)
 				printk(KERN_DEBUG
 				       "  %s zone: %lu pages used for memmap\n",
 				       zone_names[j], memmap_pages);
 		} else
 			printk(KERN_WARNING
-				"  %s zone: %lu pages exceeds realsize %lu\n",
-				zone_names[j], memmap_pages, realsize);
+				"  %s zone: %lu pages exceeds freesize %lu\n",
+				zone_names[j], memmap_pages, freesize);
 
 		/* Account for reserved pages */
-		if (j == 0 && realsize > dma_reserve) {
-			realsize -= dma_reserve;
+		if (j == 0 && freesize > dma_reserve) {
+			freesize -= dma_reserve;
 			printk(KERN_DEBUG "  %s zone: %lu pages reserved\n",
 					zone_names[0], dma_reserve);
 		}
 
 		if (!is_highmem_idx(j))
-			nr_kernel_pages += realsize;
-		nr_all_pages += realsize;
+			nr_kernel_pages += freesize;
+		/* Charge for highmem memmap if there are enough kernel pages */
+		else if (nr_kernel_pages > memmap_pages * 2)
+			nr_kernel_pages -= memmap_pages;
+		nr_all_pages += freesize;
 
 		zone->spanned_pages = size;
-		zone->present_pages = realsize;
+		zone->present_pages = freesize;
+		/*
+		 * Set an approximate value for lowmem here, it will be adjusted
+		 * when the bootmem allocator frees pages into the buddy system.
+		 * And all highmem pages will be managed by the buddy system.
+		 */
+		zone->managed_pages = is_highmem_idx(j) ? realsize : freesize;
 #ifdef CONFIG_NUMA
 		zone->node = nid;
-		zone->min_unmapped_pages = (realsize*sysctl_min_unmapped_ratio)
+		zone->min_unmapped_pages = (freesize*sysctl_min_unmapped_ratio)
 						/ 100;
-		zone->min_slab_pages = (realsize * sysctl_min_slab_ratio) / 100;
+		zone->min_slab_pages = (freesize * sysctl_min_slab_ratio) / 100;
 #endif
 		zone->name = zone_names[j];
 		spin_lock_init(&zone->lock);
@@ -4687,7 +4825,7 @@ unsigned long __init find_min_pfn_with_active_regions(void)
 /*
  * early_calculate_totalpages()
  * Sum pages in active regions for movable zone.
- * Populate N_HIGH_MEMORY for calculating usable_nodes.
+ * Populate N_MEMORY for calculating usable_nodes.
  */
 static unsigned long __init early_calculate_totalpages(void)
 {
@@ -4700,7 +4838,7 @@ static unsigned long __init early_calculate_totalpages(void)
 
 		totalpages += pages;
 		if (pages)
-			node_set_state(nid, N_HIGH_MEMORY);
+			node_set_state(nid, N_MEMORY);
 	}
   	return totalpages;
 }
@@ -4717,9 +4855,9 @@ static void __init find_zone_movable_pfns_for_nodes(void)
 	unsigned long usable_startpfn;
 	unsigned long kernelcore_node, kernelcore_remaining;
 	/* save the state before borrow the nodemask */
-	nodemask_t saved_node_state = node_states[N_HIGH_MEMORY];
+	nodemask_t saved_node_state = node_states[N_MEMORY];
 	unsigned long totalpages = early_calculate_totalpages();
-	int usable_nodes = nodes_weight(node_states[N_HIGH_MEMORY]);
+	int usable_nodes = nodes_weight(node_states[N_MEMORY]);
 
 	/*
 	 * If movablecore was specified, calculate what size of
@@ -4754,7 +4892,7 @@ static void __init find_zone_movable_pfns_for_nodes(void)
 restart:
 	/* Spread kernelcore memory as evenly as possible throughout nodes */
 	kernelcore_node = required_kernelcore / usable_nodes;
-	for_each_node_state(nid, N_HIGH_MEMORY) {
+	for_each_node_state(nid, N_MEMORY) {
 		unsigned long start_pfn, end_pfn;
 
 		/*
@@ -4846,23 +4984,27 @@ restart:
 
 out:
 	/* restore the node_state */
-	node_states[N_HIGH_MEMORY] = saved_node_state;
+	node_states[N_MEMORY] = saved_node_state;
 }
 
-/* Any regular memory on that node ? */
-static void __init check_for_regular_memory(pg_data_t *pgdat)
+/* Any regular or high memory on that node ? */
+static void check_for_memory(pg_data_t *pgdat, int nid)
 {
-#ifdef CONFIG_HIGHMEM
 	enum zone_type zone_type;
 
-	for (zone_type = 0; zone_type <= ZONE_NORMAL; zone_type++) {
+	if (N_MEMORY == N_NORMAL_MEMORY)
+		return;
+
+	for (zone_type = 0; zone_type <= ZONE_MOVABLE - 1; zone_type++) {
 		struct zone *zone = &pgdat->node_zones[zone_type];
 		if (zone->present_pages) {
-			node_set_state(zone_to_nid(zone), N_NORMAL_MEMORY);
+			node_set_state(nid, N_HIGH_MEMORY);
+			if (N_NORMAL_MEMORY != N_HIGH_MEMORY &&
+			    zone_type <= ZONE_NORMAL)
+				node_set_state(nid, N_NORMAL_MEMORY);
 			break;
 		}
 	}
-#endif
 }
 
 /**
@@ -4945,8 +5087,8 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
 
 		/* Any memory on that node */
 		if (pgdat->node_present_pages)
-			node_set_state(nid, N_HIGH_MEMORY);
-		check_for_regular_memory(pgdat);
+			node_set_state(nid, N_MEMORY);
+		check_for_memory(pgdat, nid);
 	}
 }
 
@@ -5174,10 +5316,6 @@ static void __setup_per_zone_wmarks(void)
 		zone->watermark[WMARK_LOW]  = min_wmark_pages(zone) + (tmp >> 2);
 		zone->watermark[WMARK_HIGH] = min_wmark_pages(zone) + (tmp >> 1);
 
-		zone->watermark[WMARK_MIN] += cma_wmark_pages(zone);
-		zone->watermark[WMARK_LOW] += cma_wmark_pages(zone);
-		zone->watermark[WMARK_HIGH] += cma_wmark_pages(zone);
-
 		setup_zone_migrate_reserve(zone);
 		spin_unlock_irqrestore(&zone->lock, flags);
 	}
@@ -5575,7 +5713,8 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags,
  * MIGRATE_MOVABLE block might include unmovable pages. It means you can't
  * expect this function should be exact.
  */
-bool has_unmovable_pages(struct zone *zone, struct page *page, int count)
+bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
+			 bool skip_hwpoisoned_pages)
 {
 	unsigned long pfn, iter, found;
 	int mt;
@@ -5610,6 +5749,13 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count)
 			continue;
 		}
 
+		/*
+		 * The HWPoisoned page may be not in buddy system, and
+		 * page_count() is not 0.
+		 */
+		if (skip_hwpoisoned_pages && PageHWPoison(page))
+			continue;
+
 		if (!PageLRU(page))
 			found++;
 		/*
@@ -5652,7 +5798,7 @@ bool is_pageblock_removable_nolock(struct page *page)
 			zone->zone_start_pfn + zone->spanned_pages <= pfn)
 		return false;
 
-	return !has_unmovable_pages(zone, page, 0);
+	return !has_unmovable_pages(zone, page, 0, true);
 }
 
 #ifdef CONFIG_CMA
@@ -5679,7 +5825,7 @@ static int __alloc_contig_migrate_range(struct compact_control *cc,
 	unsigned int tries = 0;
 	int ret = 0;
 
-	migrate_prep_local();
+	migrate_prep();
 
 	while (pfn < end || !list_empty(&cc->migratepages)) {
 		if (fatal_signal_pending(current)) {
@@ -5710,58 +5856,10 @@ static int __alloc_contig_migrate_range(struct compact_control *cc,
 				    0, false, MIGRATE_SYNC);
 	}
 
-	putback_lru_pages(&cc->migratepages);
+	putback_movable_pages(&cc->migratepages);
 	return ret > 0 ? 0 : ret;
 }
 
-/*
- * Update zone's cma pages counter used for watermark level calculation.
- */
-static inline void __update_cma_watermarks(struct zone *zone, int count)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&zone->lock, flags);
-	zone->min_cma_pages += count;
-	spin_unlock_irqrestore(&zone->lock, flags);
-	setup_per_zone_wmarks();
-}
-
-/*
- * Trigger memory pressure bump to reclaim some pages in order to be able to
- * allocate 'count' pages in single page units. Does similar work as
- *__alloc_pages_slowpath() function.
- */
-static int __reclaim_pages(struct zone *zone, gfp_t gfp_mask, int count)
-{
-	enum zone_type high_zoneidx = gfp_zone(gfp_mask);
-	struct zonelist *zonelist = node_zonelist(0, gfp_mask);
-	int did_some_progress = 0;
-	int order = 1;
-
-	/*
-	 * Increase level of watermarks to force kswapd do his job
-	 * to stabilise at new watermark level.
-	 */
-	__update_cma_watermarks(zone, count);
-
-	/* Obey watermarks as if the page was being allocated */
-	while (!zone_watermark_ok(zone, 0, low_wmark_pages(zone), 0, 0)) {
-		wake_all_kswapd(order, zonelist, high_zoneidx, zone_idx(zone));
-
-		did_some_progress = __perform_reclaim(gfp_mask, order, zonelist,
-						      NULL);
-		if (!did_some_progress) {
-			/* Exhausted what can be done so it's blamo time */
-			out_of_memory(zonelist, gfp_mask, order, NULL, false);
-		}
-	}
-
-	/* Restore original watermark levels. */
-	__update_cma_watermarks(zone, -count);
-
-	return count;
-}
-
 /**
  * alloc_contig_range() -- tries to allocate given range of pages
  * @start:	start PFN to allocate
@@ -5785,7 +5883,6 @@ static int __reclaim_pages(struct zone *zone, gfp_t gfp_mask, int count)
 int alloc_contig_range(unsigned long start, unsigned long end,
 		       unsigned migratetype)
 {
-	struct zone *zone = page_zone(pfn_to_page(start));
 	unsigned long outer_start, outer_end;
 	int ret = 0, order;
 
@@ -5823,7 +5920,8 @@ int alloc_contig_range(unsigned long start, unsigned long end,
 	 */
 
 	ret = start_isolate_page_range(pfn_max_align_down(start),
-				       pfn_max_align_up(end), migratetype);
+				       pfn_max_align_up(end), migratetype,
+				       false);
 	if (ret)
 		return ret;
 
@@ -5862,18 +5960,13 @@ int alloc_contig_range(unsigned long start, unsigned long end,
 	}
 
 	/* Make sure the range is really isolated. */
-	if (test_pages_isolated(outer_start, end)) {
+	if (test_pages_isolated(outer_start, end, false)) {
 		pr_warn("alloc_contig_range test_pages_isolated(%lx, %lx) failed\n",
 		       outer_start, end);
 		ret = -EBUSY;
 		goto done;
 	}
 
-	/*
-	 * Reclaim enough pages to make sure that contiguous allocation
-	 * will not starve the system.
-	 */
-	__reclaim_pages(zone, GFP_HIGHUSER_MOVABLE, end-start);
 
 	/* Grab isolated pages from freelists. */
 	outer_end = isolate_freepages_range(&cc, outer_start, end);
@@ -5896,8 +5989,13 @@ done:
 
 void free_contig_range(unsigned long pfn, unsigned nr_pages)
 {
-	for (; nr_pages--; ++pfn)
-		__free_page(pfn_to_page(pfn));
+	struct page *page = pfn_to_page(pfn);
+	int count = 0;
+	for (; nr_pages--; page++) {
+		count += page_count(page) != 1;
+		__free_page(page);
+	}
+	WARN(count != 0, "%d pages are still in use!\n", count);
 }
 #endif
 
@@ -5931,7 +6029,6 @@ void __meminit zone_pcp_update(struct zone *zone)
 }
 #endif
 
-#ifdef CONFIG_MEMORY_HOTREMOVE
 void zone_pcp_reset(struct zone *zone)
 {
 	unsigned long flags;
@@ -5951,6 +6048,7 @@ void zone_pcp_reset(struct zone *zone)
 	local_irq_restore(flags);
 }
 
+#ifdef CONFIG_MEMORY_HOTREMOVE
 /*
  * All pages in the range must be isolated before calling this.
  */
@@ -5977,6 +6075,16 @@ __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
 			continue;
 		}
 		page = pfn_to_page(pfn);
+		/*
+		 * The HWPoisoned page may be not in buddy system, and
+		 * page_count() is not 0.
+		 */
+		if (unlikely(!PageBuddy(page) && PageHWPoison(page))) {
+			pfn++;
+			SetPageReserved(page);
+			continue;
+		}
+
 		BUG_ON(page_count(page));
 		BUG_ON(!PageBuddy(page));
 		order = page_order(page);
@@ -5987,8 +6095,6 @@ __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
 		list_del(&page->lru);
 		rmv_page_order(page);
 		zone->free_area[order].nr_free--;
-		__mod_zone_page_state(zone, NR_FREE_PAGES,
-				      - (1UL << order));
 		for (i = 0; i < (1 << order); i++)
 			SetPageReserved((page+i));
 		pfn += (1 << order);
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c
index 5ddad0c..6d757e3 100644
--- a/mm/page_cgroup.c
+++ b/mm/page_cgroup.c
@@ -251,6 +251,9 @@ static int __meminit page_cgroup_callback(struct notifier_block *self,
 				mn->nr_pages, mn->status_change_nid);
 		break;
 	case MEM_CANCEL_ONLINE:
+		offline_page_cgroup(mn->start_pfn,
+				mn->nr_pages, mn->status_change_nid);
+		break;
 	case MEM_GOING_OFFLINE:
 		break;
 	case MEM_ONLINE:
@@ -271,7 +274,7 @@ void __init page_cgroup_init(void)
 	if (mem_cgroup_disabled())
 		return;
 
-	for_each_node_state(nid, N_HIGH_MEMORY) {
+	for_each_node_state(nid, N_MEMORY) {
 		unsigned long start_pfn, end_pfn;
 
 		start_pfn = node_start_pfn(nid);
diff --git a/mm/page_isolation.c b/mm/page_isolation.c
index f2f5b48..9d2264e 100644
--- a/mm/page_isolation.c
+++ b/mm/page_isolation.c
@@ -30,7 +30,7 @@ static void restore_pageblock_isolate(struct page *page, int migratetype)
 	zone->nr_pageblock_isolate--;
 }
 
-int set_migratetype_isolate(struct page *page)
+int set_migratetype_isolate(struct page *page, bool skip_hwpoisoned_pages)
 {
 	struct zone *zone;
 	unsigned long flags, pfn;
@@ -66,7 +66,8 @@ int set_migratetype_isolate(struct page *page)
 	 * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself.
 	 * We just check MOVABLE pages.
 	 */
-	if (!has_unmovable_pages(zone, page, arg.pages_found))
+	if (!has_unmovable_pages(zone, page, arg.pages_found,
+				 skip_hwpoisoned_pages))
 		ret = 0;
 
 	/*
@@ -134,7 +135,7 @@ __first_valid_page(unsigned long pfn, unsigned long nr_pages)
  * Returns 0 on success and -EBUSY if any part of range cannot be isolated.
  */
 int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
-			     unsigned migratetype)
+			     unsigned migratetype, bool skip_hwpoisoned_pages)
 {
 	unsigned long pfn;
 	unsigned long undo_pfn;
@@ -147,7 +148,8 @@ int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
 	     pfn < end_pfn;
 	     pfn += pageblock_nr_pages) {
 		page = __first_valid_page(pfn, pageblock_nr_pages);
-		if (page && set_migratetype_isolate(page)) {
+		if (page &&
+		    set_migratetype_isolate(page, skip_hwpoisoned_pages)) {
 			undo_pfn = pfn;
 			goto undo;
 		}
@@ -190,7 +192,8 @@ int undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
  * Returns 1 if all pages in the range are isolated.
  */
 static int
-__test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn)
+__test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn,
+				  bool skip_hwpoisoned_pages)
 {
 	struct page *page;
 
@@ -220,6 +223,14 @@ __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn)
 		else if (page_count(page) == 0 &&
 			get_freepage_migratetype(page) == MIGRATE_ISOLATE)
 			pfn += 1;
+		else if (skip_hwpoisoned_pages && PageHWPoison(page)) {
+			/*
+			 * The HWPoisoned page may be not in buddy
+			 * system, and page_count() is not 0.
+			 */
+			pfn++;
+			continue;
+		}
 		else
 			break;
 	}
@@ -228,7 +239,8 @@ __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn)
 	return 1;
 }
 
-int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
+int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn,
+			bool skip_hwpoisoned_pages)
 {
 	unsigned long pfn, flags;
 	struct page *page;
@@ -251,7 +263,8 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
 	/* Check all pages are free or Marked as ISOLATED */
 	zone = page_zone(page);
 	spin_lock_irqsave(&zone->lock, flags);
-	ret = __test_page_isolated_in_pageblock(start_pfn, end_pfn);
+	ret = __test_page_isolated_in_pageblock(start_pfn, end_pfn,
+						skip_hwpoisoned_pages);
 	spin_unlock_irqrestore(&zone->lock, flags);
 	return ret ? 0 : -EBUSY;
 }
diff --git a/mm/pagewalk.c b/mm/pagewalk.c
index 6c118d0..35aa294 100644
--- a/mm/pagewalk.c
+++ b/mm/pagewalk.c
@@ -58,7 +58,7 @@ again:
 		if (!walk->pte_entry)
 			continue;
 
-		split_huge_page_pmd(walk->mm, pmd);
+		split_huge_page_pmd_mm(walk->mm, addr, pmd);
 		if (pmd_none_or_trans_huge_or_clear_bad(pmd))
 			goto again;
 		err = walk_pte_range(pmd, addr, next, walk);
diff --git a/mm/percpu.c b/mm/percpu.c
index ddc5efb..ec25896 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -631,7 +631,7 @@ static void pcpu_free_chunk(struct pcpu_chunk *chunk)
 	if (!chunk)
 		return;
 	pcpu_mem_free(chunk->map, chunk->map_alloc * sizeof(chunk->map[0]));
-	kfree(chunk);
+	pcpu_mem_free(chunk, pcpu_chunk_struct_size);
 }
 
 /*
diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c
index e642627..0c8323f 100644
--- a/mm/pgtable-generic.c
+++ b/mm/pgtable-generic.c
@@ -12,8 +12,8 @@
 
 #ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 /*
- * Only sets the access flags (dirty, accessed, and
- * writable). Furthermore, we know it always gets set to a "more
+ * Only sets the access flags (dirty, accessed), as well as write 
+ * permission. Furthermore, we know it always gets set to a "more
  * permissive" setting, which allows most architectures to optimize
  * this. We return whether the PTE actually changed, which in turn
  * instructs the caller to do things like update__mmu_cache.  This
@@ -27,7 +27,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma,
 	int changed = !pte_same(*ptep, entry);
 	if (changed) {
 		set_pte_at(vma->vm_mm, address, ptep, entry);
-		flush_tlb_page(vma, address);
+		flush_tlb_fix_spurious_fault(vma, address);
 	}
 	return changed;
 }
@@ -88,7 +88,8 @@ pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long address,
 {
 	pte_t pte;
 	pte = ptep_get_and_clear((vma)->vm_mm, address, ptep);
-	flush_tlb_page(vma, address);
+	if (pte_accessible(pte))
+		flush_tlb_page(vma, address);
 	return pte;
 }
 #endif
diff --git a/mm/rmap.c b/mm/rmap.c
index 2ee1ef0..f8ca7cf 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -367,6 +367,9 @@ static void anon_vma_ctor(void *data)
 
 	mutex_init(&anon_vma->mutex);
 	atomic_set(&anon_vma->refcount, 0);
+#ifdef CONFIG_SWAP
+	atomic_set(&anon_vma->swapra_miss, 0);
+#endif
 	anon_vma->rb_root = RB_ROOT;
 }
 
@@ -562,6 +565,27 @@ unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma)
 	return address;
 }
 
+pmd_t *mm_find_pmd(struct mm_struct *mm, unsigned long address)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd = NULL;
+
+	pgd = pgd_offset(mm, address);
+	if (!pgd_present(*pgd))
+		goto out;
+
+	pud = pud_offset(pgd, address);
+	if (!pud_present(*pud))
+		goto out;
+
+	pmd = pmd_offset(pud, address);
+	if (!pmd_present(*pmd))
+		pmd = NULL;
+out:
+	return pmd;
+}
+
 /*
  * Check that @page is mapped at @address into @mm.
  *
@@ -574,8 +598,6 @@ unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma)
 pte_t *__page_check_address(struct page *page, struct mm_struct *mm,
 			  unsigned long address, spinlock_t **ptlp, int sync)
 {
-	pgd_t *pgd;
-	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
 	spinlock_t *ptl;
@@ -586,17 +608,10 @@ pte_t *__page_check_address(struct page *page, struct mm_struct *mm,
 		goto check;
 	}
 
-	pgd = pgd_offset(mm, address);
-	if (!pgd_present(*pgd))
-		return NULL;
-
-	pud = pud_offset(pgd, address);
-	if (!pud_present(*pud))
+	pmd = mm_find_pmd(mm, address);
+	if (!pmd)
 		return NULL;
 
-	pmd = pmd_offset(pud, address);
-	if (!pmd_present(*pmd))
-		return NULL;
 	if (pmd_trans_huge(*pmd))
 		return NULL;
 
@@ -1139,9 +1154,11 @@ void page_remove_rmap(struct page *page)
 	 * containing the swap entry, but page not yet written to swap.
 	 *
 	 * And we can skip it on file pages, so long as the filesystem
-	 * participates in dirty tracking; but need to catch shm and tmpfs
-	 * and ramfs pages which have been modified since creation by read
-	 * fault.
+	 * participates in dirty tracking (note that this is not only an
+	 * optimization but also solves problems caused by dirty flag in
+	 * storage key getting set by a write from inside kernel); but need to
+	 * catch shm and tmpfs and ramfs pages which have been modified since
+	 * creation by read fault.
 	 *
 	 * Note that mapping must be decided above, before decrementing
 	 * mapcount (which luckily provides a barrier): once page is unmapped,
@@ -1345,8 +1362,6 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount,
 		struct vm_area_struct *vma, struct page *check_page)
 {
 	struct mm_struct *mm = vma->vm_mm;
-	pgd_t *pgd;
-	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
 	pte_t pteval;
@@ -1366,16 +1381,8 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount,
 	if (end > vma->vm_end)
 		end = vma->vm_end;
 
-	pgd = pgd_offset(mm, address);
-	if (!pgd_present(*pgd))
-		return ret;
-
-	pud = pud_offset(pgd, address);
-	if (!pud_present(*pud))
-		return ret;
-
-	pmd = pmd_offset(pud, address);
-	if (!pmd_present(*pmd))
+	pmd = mm_find_pmd(mm, address);
+	if (!pmd)
 		return ret;
 
 	mmun_start = address;
diff --git a/mm/shmem.c b/mm/shmem.c
index 89341b6..2f4f153 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -922,6 +922,7 @@ static struct page *shmem_swapin(swp_entry_t swap, gfp_t gfp,
 	pvma.vm_pgoff = index + info->vfs_inode.i_ino;
 	pvma.vm_ops = NULL;
 	pvma.vm_policy = spol;
+	pvma.anon_vma = NULL;
 	return swapin_readahead(swap, gfp, &pvma, 0);
 }
 
diff --git a/mm/slab.c b/mm/slab.c
index 33d3363..23daffa 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -87,7 +87,6 @@
  */
 
 #include	<linux/slab.h>
-#include	"slab.h"
 #include	<linux/mm.h>
 #include	<linux/poison.h>
 #include	<linux/swap.h>
@@ -128,6 +127,8 @@
 
 #include	"internal.h"
 
+#include	"slab.h"
+
 /*
  * DEBUG	- 1 for kmem_cache_create() to honour; SLAB_RED_ZONE & SLAB_POISON.
  *		  0 for faster, smaller code (especially in the critical paths).
@@ -162,23 +163,6 @@
  */
 static bool pfmemalloc_active __read_mostly;
 
-/* Legal flag mask for kmem_cache_create(). */
-#if DEBUG
-# define CREATE_MASK	(SLAB_RED_ZONE | \
-			 SLAB_POISON | SLAB_HWCACHE_ALIGN | \
-			 SLAB_CACHE_DMA | \
-			 SLAB_STORE_USER | \
-			 SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
-			 SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \
-			 SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE | SLAB_NOTRACK)
-#else
-# define CREATE_MASK	(SLAB_HWCACHE_ALIGN | \
-			 SLAB_CACHE_DMA | \
-			 SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
-			 SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \
-			 SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE | SLAB_NOTRACK)
-#endif
-
 /*
  * kmem_bufctl_t:
  *
@@ -662,6 +646,26 @@ static void init_node_lock_keys(int q)
 	}
 }
 
+static void on_slab_lock_classes_node(struct kmem_cache *cachep, int q)
+{
+	struct kmem_list3 *l3;
+	l3 = cachep->nodelists[q];
+	if (!l3)
+		return;
+
+	slab_set_lock_classes(cachep, &on_slab_l3_key,
+			&on_slab_alc_key, q);
+}
+
+static inline void on_slab_lock_classes(struct kmem_cache *cachep)
+{
+	int node;
+
+	VM_BUG_ON(OFF_SLAB(cachep));
+	for_each_node(node)
+		on_slab_lock_classes_node(cachep, node);
+}
+
 static inline void init_lock_keys(void)
 {
 	int node;
@@ -678,6 +682,14 @@ static inline void init_lock_keys(void)
 {
 }
 
+static inline void on_slab_lock_classes(struct kmem_cache *cachep)
+{
+}
+
+static inline void on_slab_lock_classes_node(struct kmem_cache *cachep, int node)
+{
+}
+
 static void slab_set_debugobj_lock_classes_node(struct kmem_cache *cachep, int node)
 {
 }
@@ -1406,6 +1418,9 @@ static int __cpuinit cpuup_prepare(long cpu)
 		free_alien_cache(alien);
 		if (cachep->flags & SLAB_DEBUG_OBJECTS)
 			slab_set_debugobj_lock_classes_node(cachep, node);
+		else if (!OFF_SLAB(cachep) &&
+			 !(cachep->flags & SLAB_DESTROY_BY_RCU))
+			on_slab_lock_classes_node(cachep, node);
 	}
 	init_node_lock_keys(node);
 
@@ -1921,6 +1936,7 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 		if (page->pfmemalloc)
 			SetPageSlabPfmemalloc(page + i);
 	}
+	memcg_bind_pages(cachep, cachep->gfporder);
 
 	if (kmemcheck_enabled && !(cachep->flags & SLAB_NOTRACK)) {
 		kmemcheck_alloc_shadow(page, cachep->gfporder, flags, nodeid);
@@ -1957,9 +1973,11 @@ static void kmem_freepages(struct kmem_cache *cachep, void *addr)
 		__ClearPageSlab(page);
 		page++;
 	}
+
+	memcg_release_pages(cachep, cachep->gfporder);
 	if (current->reclaim_state)
 		current->reclaim_state->reclaimed_slab += nr_freed;
-	free_pages((unsigned long)addr, cachep->gfporder);
+	free_memcg_kmem_pages((unsigned long)addr, cachep->gfporder);
 }
 
 static void kmem_rcu_free(struct rcu_head *head)
@@ -2331,11 +2349,8 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp)
 
 /**
  * __kmem_cache_create - Create a cache.
- * @name: A string which is used in /proc/slabinfo to identify this cache.
- * @size: The size of objects to be created in this cache.
- * @align: The required alignment for the objects.
+ * @cachep: cache management descriptor
  * @flags: SLAB flags
- * @ctor: A constructor for the objects.
  *
  * Returns a ptr to the cache on success, NULL on failure.
  * Cannot be called within a int, but can be interrupted.
@@ -2378,11 +2393,6 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
 	if (flags & SLAB_DESTROY_BY_RCU)
 		BUG_ON(flags & SLAB_POISON);
 #endif
-	/*
-	 * Always checks flags, a caller might be expecting debug support which
-	 * isn't available.
-	 */
-	BUG_ON(flags & ~CREATE_MASK);
 
 	/*
 	 * Check that size is in terms of words.  This is needed to avoid
@@ -2566,7 +2576,8 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
 		WARN_ON_ONCE(flags & SLAB_DESTROY_BY_RCU);
 
 		slab_set_debugobj_lock_classes(cachep);
-	}
+	} else if (!OFF_SLAB(cachep) && !(flags & SLAB_DESTROY_BY_RCU))
+		on_slab_lock_classes(cachep);
 
 	return 0;
 }
@@ -3530,6 +3541,8 @@ slab_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid,
 	if (slab_should_failslab(cachep, flags))
 		return NULL;
 
+	cachep = memcg_kmem_get_cache(cachep, flags);
+
 	cache_alloc_debugcheck_before(cachep, flags);
 	local_irq_save(save_flags);
 
@@ -3615,6 +3628,8 @@ slab_alloc(struct kmem_cache *cachep, gfp_t flags, unsigned long caller)
 	if (slab_should_failslab(cachep, flags))
 		return NULL;
 
+	cachep = memcg_kmem_get_cache(cachep, flags);
+
 	cache_alloc_debugcheck_before(cachep, flags);
 	local_irq_save(save_flags);
 	objp = __do_cache_alloc(cachep, flags);
@@ -3928,6 +3943,9 @@ EXPORT_SYMBOL(__kmalloc);
 void kmem_cache_free(struct kmem_cache *cachep, void *objp)
 {
 	unsigned long flags;
+	cachep = cache_from_obj(cachep, objp);
+	if (!cachep)
+		return;
 
 	local_irq_save(flags);
 	debug_check_no_locks_freed(objp, cachep->object_size);
@@ -3969,12 +3987,6 @@ void kfree(const void *objp)
 }
 EXPORT_SYMBOL(kfree);
 
-unsigned int kmem_cache_size(struct kmem_cache *cachep)
-{
-	return cachep->object_size;
-}
-EXPORT_SYMBOL(kmem_cache_size);
-
 /*
  * This initializes kmem_list3 or resizes various caches for all nodes.
  */
@@ -4081,7 +4093,7 @@ static void do_ccupdate_local(void *info)
 }
 
 /* Always called with the slab_mutex held */
-static int do_tune_cpucache(struct kmem_cache *cachep, int limit,
+static int __do_tune_cpucache(struct kmem_cache *cachep, int limit,
 				int batchcount, int shared, gfp_t gfp)
 {
 	struct ccupdate_struct *new;
@@ -4124,12 +4136,49 @@ static int do_tune_cpucache(struct kmem_cache *cachep, int limit,
 	return alloc_kmemlist(cachep, gfp);
 }
 
+static int do_tune_cpucache(struct kmem_cache *cachep, int limit,
+				int batchcount, int shared, gfp_t gfp)
+{
+	int ret;
+	struct kmem_cache *c = NULL;
+	int i = 0;
+
+	ret = __do_tune_cpucache(cachep, limit, batchcount, shared, gfp);
+
+	if (slab_state < FULL)
+		return ret;
+
+	if ((ret < 0) || !is_root_cache(cachep))
+		return ret;
+
+	VM_BUG_ON(!mutex_is_locked(&slab_mutex));
+	for_each_memcg_cache_index(i) {
+		c = cache_from_memcg(cachep, i);
+		if (c)
+			/* return value determined by the parent cache only */
+			__do_tune_cpucache(c, limit, batchcount, shared, gfp);
+	}
+
+	return ret;
+}
+
 /* Called with slab_mutex held always */
 static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp)
 {
 	int err;
-	int limit, shared;
+	int limit = 0;
+	int shared = 0;
+	int batchcount = 0;
+
+	if (!is_root_cache(cachep)) {
+		struct kmem_cache *root = memcg_root_cache(cachep);
+		limit = root->limit;
+		shared = root->shared;
+		batchcount = root->batchcount;
+	}
 
+	if (limit && shared && batchcount)
+		goto skip_setup;
 	/*
 	 * The head array serves three purposes:
 	 * - create a LIFO ordering, i.e. return objects that are cache-warm
@@ -4171,7 +4220,9 @@ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp)
 	if (limit > 32)
 		limit = 32;
 #endif
-	err = do_tune_cpucache(cachep, limit, (limit + 1) / 2, shared, gfp);
+	batchcount = (limit + 1) / 2;
+skip_setup:
+	err = do_tune_cpucache(cachep, limit, batchcount, shared, gfp);
 	if (err)
 		printk(KERN_ERR "enable_cpucache failed for %s, error %d.\n",
 		       cachep->name, -err);
@@ -4276,54 +4327,8 @@ out:
 }
 
 #ifdef CONFIG_SLABINFO
-
-static void print_slabinfo_header(struct seq_file *m)
+void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo)
 {
-	/*
-	 * Output format version, so at least we can change it
-	 * without _too_ many complaints.
-	 */
-#if STATS
-	seq_puts(m, "slabinfo - version: 2.1 (statistics)\n");
-#else
-	seq_puts(m, "slabinfo - version: 2.1\n");
-#endif
-	seq_puts(m, "# name            <active_objs> <num_objs> <objsize> "
-		 "<objperslab> <pagesperslab>");
-	seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>");
-	seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
-#if STATS
-	seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> "
-		 "<error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>");
-	seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>");
-#endif
-	seq_putc(m, '\n');
-}
-
-static void *s_start(struct seq_file *m, loff_t *pos)
-{
-	loff_t n = *pos;
-
-	mutex_lock(&slab_mutex);
-	if (!n)
-		print_slabinfo_header(m);
-
-	return seq_list_start(&slab_caches, *pos);
-}
-
-static void *s_next(struct seq_file *m, void *p, loff_t *pos)
-{
-	return seq_list_next(p, &slab_caches, pos);
-}
-
-static void s_stop(struct seq_file *m, void *p)
-{
-	mutex_unlock(&slab_mutex);
-}
-
-static int s_show(struct seq_file *m, void *p)
-{
-	struct kmem_cache *cachep = list_entry(p, struct kmem_cache, list);
 	struct slab *slabp;
 	unsigned long active_objs;
 	unsigned long num_objs;
@@ -4378,13 +4383,20 @@ static int s_show(struct seq_file *m, void *p)
 	if (error)
 		printk(KERN_ERR "slab: cache %s error: %s\n", name, error);
 
-	seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d",
-		   name, active_objs, num_objs, cachep->size,
-		   cachep->num, (1 << cachep->gfporder));
-	seq_printf(m, " : tunables %4u %4u %4u",
-		   cachep->limit, cachep->batchcount, cachep->shared);
-	seq_printf(m, " : slabdata %6lu %6lu %6lu",
-		   active_slabs, num_slabs, shared_avail);
+	sinfo->active_objs = active_objs;
+	sinfo->num_objs = num_objs;
+	sinfo->active_slabs = active_slabs;
+	sinfo->num_slabs = num_slabs;
+	sinfo->shared_avail = shared_avail;
+	sinfo->limit = cachep->limit;
+	sinfo->batchcount = cachep->batchcount;
+	sinfo->shared = cachep->shared;
+	sinfo->objects_per_slab = cachep->num;
+	sinfo->cache_order = cachep->gfporder;
+}
+
+void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *cachep)
+{
 #if STATS
 	{			/* list3 stats */
 		unsigned long high = cachep->high_mark;
@@ -4414,31 +4426,8 @@ static int s_show(struct seq_file *m, void *p)
 			   allochit, allocmiss, freehit, freemiss);
 	}
 #endif
-	seq_putc(m, '\n');
-	return 0;
 }
 
-/*
- * slabinfo_op - iterator that generates /proc/slabinfo
- *
- * Output layout:
- * cache-name
- * num-active-objs
- * total-objs
- * object size
- * num-active-slabs
- * total-slabs
- * num-pages-per-slab
- * + further values on SMP and with statistics enabled
- */
-
-static const struct seq_operations slabinfo_op = {
-	.start = s_start,
-	.next = s_next,
-	.stop = s_stop,
-	.show = s_show,
-};
-
 #define MAX_SLABINFO_WRITE 128
 /**
  * slabinfo_write - Tuning for the slab allocator
@@ -4447,7 +4436,7 @@ static const struct seq_operations slabinfo_op = {
  * @count: data length
  * @ppos: unused
  */
-static ssize_t slabinfo_write(struct file *file, const char __user *buffer,
+ssize_t slabinfo_write(struct file *file, const char __user *buffer,
 		       size_t count, loff_t *ppos)
 {
 	char kbuf[MAX_SLABINFO_WRITE + 1], *tmp;
@@ -4490,19 +4479,6 @@ static ssize_t slabinfo_write(struct file *file, const char __user *buffer,
 	return res;
 }
 
-static int slabinfo_open(struct inode *inode, struct file *file)
-{
-	return seq_open(file, &slabinfo_op);
-}
-
-static const struct file_operations proc_slabinfo_operations = {
-	.open		= slabinfo_open,
-	.read		= seq_read,
-	.write		= slabinfo_write,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
-};
-
 #ifdef CONFIG_DEBUG_SLAB_LEAK
 
 static void *leaks_start(struct seq_file *m, loff_t *pos)
@@ -4631,6 +4607,16 @@ static int leaks_show(struct seq_file *m, void *p)
 	return 0;
 }
 
+static void *s_next(struct seq_file *m, void *p, loff_t *pos)
+{
+	return seq_list_next(p, &slab_caches, pos);
+}
+
+static void s_stop(struct seq_file *m, void *p)
+{
+	mutex_unlock(&slab_mutex);
+}
+
 static const struct seq_operations slabstats_op = {
 	.start = leaks_start,
 	.next = s_next,
@@ -4665,7 +4651,6 @@ static const struct file_operations proc_slabstats_operations = {
 
 static int __init slab_proc_init(void)
 {
-	proc_create("slabinfo",S_IWUSR|S_IRUSR,NULL,&proc_slabinfo_operations);
 #ifdef CONFIG_DEBUG_SLAB_LEAK
 	proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations);
 #endif
diff --git a/mm/slab.h b/mm/slab.h
index 7deeb44..9fc04b0 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -35,16 +35,190 @@ extern struct kmem_cache *kmem_cache;
 /* Functions provided by the slab allocators */
 extern int __kmem_cache_create(struct kmem_cache *, unsigned long flags);
 
+struct mem_cgroup;
 #ifdef CONFIG_SLUB
-struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
-	size_t align, unsigned long flags, void (*ctor)(void *));
+struct kmem_cache *
+__kmem_cache_alias(struct mem_cgroup *memcg, const char *name, size_t size,
+		   size_t align, unsigned long flags, void (*ctor)(void *));
 #else
-static inline struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
-	size_t align, unsigned long flags, void (*ctor)(void *))
+static inline struct kmem_cache *
+__kmem_cache_alias(struct mem_cgroup *memcg, const char *name, size_t size,
+		   size_t align, unsigned long flags, void (*ctor)(void *))
 { return NULL; }
 #endif
 
 
+/* Legal flag mask for kmem_cache_create(), for various configurations */
+#define SLAB_CORE_FLAGS (SLAB_HWCACHE_ALIGN | SLAB_CACHE_DMA | SLAB_PANIC | \
+			 SLAB_DESTROY_BY_RCU | SLAB_DEBUG_OBJECTS )
+
+#if defined(CONFIG_DEBUG_SLAB)
+#define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER)
+#elif defined(CONFIG_SLUB_DEBUG)
+#define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
+			  SLAB_TRACE | SLAB_DEBUG_FREE)
+#else
+#define SLAB_DEBUG_FLAGS (0)
+#endif
+
+#if defined(CONFIG_SLAB)
+#define SLAB_CACHE_FLAGS (SLAB_MEM_SPREAD | SLAB_NOLEAKTRACE | \
+			  SLAB_RECLAIM_ACCOUNT | SLAB_TEMPORARY | SLAB_NOTRACK)
+#elif defined(CONFIG_SLUB)
+#define SLAB_CACHE_FLAGS (SLAB_NOLEAKTRACE | SLAB_RECLAIM_ACCOUNT | \
+			  SLAB_TEMPORARY | SLAB_NOTRACK)
+#else
+#define SLAB_CACHE_FLAGS (0)
+#endif
+
+#define CACHE_CREATE_MASK (SLAB_CORE_FLAGS | SLAB_DEBUG_FLAGS | SLAB_CACHE_FLAGS)
+
 int __kmem_cache_shutdown(struct kmem_cache *);
 
+struct seq_file;
+struct file;
+
+struct slabinfo {
+	unsigned long active_objs;
+	unsigned long num_objs;
+	unsigned long active_slabs;
+	unsigned long num_slabs;
+	unsigned long shared_avail;
+	unsigned int limit;
+	unsigned int batchcount;
+	unsigned int shared;
+	unsigned int objects_per_slab;
+	unsigned int cache_order;
+};
+
+void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo);
+void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s);
+ssize_t slabinfo_write(struct file *file, const char __user *buffer,
+		       size_t count, loff_t *ppos);
+
+#ifdef CONFIG_MEMCG_KMEM
+static inline bool is_root_cache(struct kmem_cache *s)
+{
+	return !s->memcg_params || s->memcg_params->is_root_cache;
+}
+
+static inline bool cache_match_memcg(struct kmem_cache *cachep,
+				     struct mem_cgroup *memcg)
+{
+	return (is_root_cache(cachep) && !memcg) ||
+				(cachep->memcg_params->memcg == memcg);
+}
+
+static inline void memcg_bind_pages(struct kmem_cache *s, int order)
+{
+	if (!is_root_cache(s))
+		atomic_add(1 << order, &s->memcg_params->nr_pages);
+}
+
+static inline void memcg_release_pages(struct kmem_cache *s, int order)
+{
+	if (is_root_cache(s))
+		return;
+
+	if (atomic_sub_and_test((1 << order), &s->memcg_params->nr_pages))
+		mem_cgroup_destroy_cache(s);
+}
+
+static inline bool slab_equal_or_root(struct kmem_cache *s,
+					struct kmem_cache *p)
+{
+	return (p == s) ||
+		(s->memcg_params && (p == s->memcg_params->root_cache));
+}
+
+/*
+ * We use suffixes to the name in memcg because we can't have caches
+ * created in the system with the same name. But when we print them
+ * locally, better refer to them with the base name
+ */
+static inline const char *cache_name(struct kmem_cache *s)
+{
+	if (!is_root_cache(s))
+		return s->memcg_params->root_cache->name;
+	return s->name;
+}
+
+static inline struct kmem_cache *cache_from_memcg(struct kmem_cache *s, int idx)
+{
+	return s->memcg_params->memcg_caches[idx];
+}
+
+static inline struct kmem_cache *memcg_root_cache(struct kmem_cache *s)
+{
+	if (is_root_cache(s))
+		return s;
+	return s->memcg_params->root_cache;
+}
+#else
+static inline bool is_root_cache(struct kmem_cache *s)
+{
+	return true;
+}
+
+static inline bool cache_match_memcg(struct kmem_cache *cachep,
+				     struct mem_cgroup *memcg)
+{
+	return true;
+}
+
+static inline void memcg_bind_pages(struct kmem_cache *s, int order)
+{
+}
+
+static inline void memcg_release_pages(struct kmem_cache *s, int order)
+{
+}
+
+static inline bool slab_equal_or_root(struct kmem_cache *s,
+				      struct kmem_cache *p)
+{
+	return true;
+}
+
+static inline const char *cache_name(struct kmem_cache *s)
+{
+	return s->name;
+}
+
+static inline struct kmem_cache *cache_from_memcg(struct kmem_cache *s, int idx)
+{
+	return NULL;
+}
+
+static inline struct kmem_cache *memcg_root_cache(struct kmem_cache *s)
+{
+	return s;
+}
+#endif
+
+static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x)
+{
+	struct kmem_cache *cachep;
+	struct page *page;
+
+	/*
+	 * When kmemcg is not being used, both assignments should return the
+	 * same value. but we don't want to pay the assignment price in that
+	 * case. If it is not compiled in, the compiler should be smart enough
+	 * to not do even the assignment. In that case, slab_equal_or_root
+	 * will also be a constant.
+	 */
+	if (!memcg_kmem_enabled() && !unlikely(s->flags & SLAB_DEBUG_FREE))
+		return s;
+
+	page = virt_to_head_page(x);
+	cachep = page->slab_cache;
+	if (slab_equal_or_root(cachep, s))
+		return cachep;
+
+	pr_err("%s: Wrong slab cache. %s but object is from %s\n",
+		__FUNCTION__, cachep->name, s->name);
+	WARN_ON_ONCE(1);
+	return s;
+}
 #endif
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 069a24e6..34743d8 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -13,9 +13,12 @@
 #include <linux/module.h>
 #include <linux/cpu.h>
 #include <linux/uaccess.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/page.h>
+#include <linux/memcontrol.h>
 
 #include "slab.h"
 
@@ -25,7 +28,8 @@ DEFINE_MUTEX(slab_mutex);
 struct kmem_cache *kmem_cache;
 
 #ifdef CONFIG_DEBUG_VM
-static int kmem_cache_sanity_check(const char *name, size_t size)
+static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name,
+				   size_t size)
 {
 	struct kmem_cache *s = NULL;
 
@@ -51,7 +55,13 @@ static int kmem_cache_sanity_check(const char *name, size_t size)
 			continue;
 		}
 
-		if (!strcmp(s->name, name)) {
+		/*
+		 * For simplicity, we won't check this in the list of memcg
+		 * caches. We have control over memcg naming, and if there
+		 * aren't duplicates in the global list, there won't be any
+		 * duplicates in the memcg lists as well.
+		 */
+		if (!memcg && !strcmp(s->name, name)) {
 			pr_err("%s (%s): Cache name already exists.\n",
 			       __func__, name);
 			dump_stack();
@@ -64,12 +74,41 @@ static int kmem_cache_sanity_check(const char *name, size_t size)
 	return 0;
 }
 #else
-static inline int kmem_cache_sanity_check(const char *name, size_t size)
+static inline int kmem_cache_sanity_check(struct mem_cgroup *memcg,
+					  const char *name, size_t size)
 {
 	return 0;
 }
 #endif
 
+#ifdef CONFIG_MEMCG_KMEM
+int memcg_update_all_caches(int num_memcgs)
+{
+	struct kmem_cache *s;
+	int ret = 0;
+	mutex_lock(&slab_mutex);
+
+	list_for_each_entry(s, &slab_caches, list) {
+		if (!is_root_cache(s))
+			continue;
+
+		ret = memcg_update_cache_size(s, num_memcgs);
+		/*
+		 * See comment in memcontrol.c, memcg_update_cache_size:
+		 * Instead of freeing the memory, we'll just leave the caches
+		 * up to this point in an updated state.
+		 */
+		if (ret)
+			goto out;
+	}
+
+	memcg_update_array_size(num_memcgs);
+out:
+	mutex_unlock(&slab_mutex);
+	return ret;
+}
+#endif
+
 /*
  * kmem_cache_create - Create a cache.
  * @name: A string which is used in /proc/slabinfo to identify this cache.
@@ -95,8 +134,10 @@ static inline int kmem_cache_sanity_check(const char *name, size_t size)
  * as davem.
  */
 
-struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align,
-		unsigned long flags, void (*ctor)(void *))
+struct kmem_cache *
+kmem_cache_create_memcg(struct mem_cgroup *memcg, const char *name, size_t size,
+			size_t align, unsigned long flags, void (*ctor)(void *),
+			struct kmem_cache *parent_cache)
 {
 	struct kmem_cache *s = NULL;
 	int err = 0;
@@ -104,11 +145,18 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align
 	get_online_cpus();
 	mutex_lock(&slab_mutex);
 
-	if (!kmem_cache_sanity_check(name, size) == 0)
+	if (!kmem_cache_sanity_check(memcg, name, size) == 0)
 		goto out_locked;
 
+	/*
+	 * Some allocators will constraint the set of valid flags to a subset
+	 * of all flags. We expect them to define CACHE_CREATE_MASK in this
+	 * case, and we'll just provide them with a sanitized version of the
+	 * passed flags.
+	 */
+	flags &= CACHE_CREATE_MASK;
 
-	s = __kmem_cache_alias(name, size, align, flags, ctor);
+	s = __kmem_cache_alias(memcg, name, size, align, flags, ctor);
 	if (s)
 		goto out_locked;
 
@@ -117,6 +165,13 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align
 		s->object_size = s->size = size;
 		s->align = align;
 		s->ctor = ctor;
+
+		if (memcg_register_cache(memcg, s, parent_cache)) {
+			kmem_cache_free(kmem_cache, s);
+			err = -ENOMEM;
+			goto out_locked;
+		}
+
 		s->name = kstrdup(name, GFP_KERNEL);
 		if (!s->name) {
 			kmem_cache_free(kmem_cache, s);
@@ -126,10 +181,9 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align
 
 		err = __kmem_cache_create(s, flags);
 		if (!err) {
-
 			s->refcount = 1;
 			list_add(&s->list, &slab_caches);
-
+			memcg_cache_list_add(memcg, s);
 		} else {
 			kfree(s->name);
 			kmem_cache_free(kmem_cache, s);
@@ -157,10 +211,20 @@ out_locked:
 
 	return s;
 }
+
+struct kmem_cache *
+kmem_cache_create(const char *name, size_t size, size_t align,
+		  unsigned long flags, void (*ctor)(void *))
+{
+	return kmem_cache_create_memcg(NULL, name, size, align, flags, ctor, NULL);
+}
 EXPORT_SYMBOL(kmem_cache_create);
 
 void kmem_cache_destroy(struct kmem_cache *s)
 {
+	/* Destroy all the children caches if we aren't a memcg cache */
+	kmem_cache_destroy_memcg_children(s);
+
 	get_online_cpus();
 	mutex_lock(&slab_mutex);
 	s->refcount--;
@@ -172,6 +236,7 @@ void kmem_cache_destroy(struct kmem_cache *s)
 			if (s->flags & SLAB_DESTROY_BY_RCU)
 				rcu_barrier();
 
+			memcg_release_cache(s);
 			kfree(s->name);
 			kmem_cache_free(kmem_cache, s);
 		} else {
@@ -192,3 +257,146 @@ int slab_is_available(void)
 {
 	return slab_state >= UP;
 }
+
+#ifdef CONFIG_SLABINFO
+void print_slabinfo_header(struct seq_file *m)
+{
+	/*
+	 * Output format version, so at least we can change it
+	 * without _too_ many complaints.
+	 */
+#ifdef CONFIG_DEBUG_SLAB
+	seq_puts(m, "slabinfo - version: 2.1 (statistics)\n");
+#else
+	seq_puts(m, "slabinfo - version: 2.1\n");
+#endif
+	seq_puts(m, "# name            <active_objs> <num_objs> <objsize> "
+		 "<objperslab> <pagesperslab>");
+	seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>");
+	seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
+#ifdef CONFIG_DEBUG_SLAB
+	seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> "
+		 "<error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>");
+	seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>");
+#endif
+	seq_putc(m, '\n');
+}
+
+static void *s_start(struct seq_file *m, loff_t *pos)
+{
+	loff_t n = *pos;
+
+	mutex_lock(&slab_mutex);
+	if (!n)
+		print_slabinfo_header(m);
+
+	return seq_list_start(&slab_caches, *pos);
+}
+
+static void *s_next(struct seq_file *m, void *p, loff_t *pos)
+{
+	return seq_list_next(p, &slab_caches, pos);
+}
+
+static void s_stop(struct seq_file *m, void *p)
+{
+	mutex_unlock(&slab_mutex);
+}
+
+static void
+memcg_accumulate_slabinfo(struct kmem_cache *s, struct slabinfo *info)
+{
+	struct kmem_cache *c;
+	struct slabinfo sinfo;
+	int i;
+
+	if (!is_root_cache(s))
+		return;
+
+	for_each_memcg_cache_index(i) {
+		c = cache_from_memcg(s, i);
+		if (!c)
+			continue;
+
+		memset(&sinfo, 0, sizeof(sinfo));
+		get_slabinfo(c, &sinfo);
+
+		info->active_slabs += sinfo.active_slabs;
+		info->num_slabs += sinfo.num_slabs;
+		info->shared_avail += sinfo.shared_avail;
+		info->active_objs += sinfo.active_objs;
+		info->num_objs += sinfo.num_objs;
+	}
+}
+
+int cache_show(struct kmem_cache *s, struct seq_file *m)
+{
+	struct slabinfo sinfo;
+
+	memset(&sinfo, 0, sizeof(sinfo));
+	get_slabinfo(s, &sinfo);
+
+	memcg_accumulate_slabinfo(s, &sinfo);
+
+	seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d",
+		   cache_name(s), sinfo.active_objs, sinfo.num_objs, s->size,
+		   sinfo.objects_per_slab, (1 << sinfo.cache_order));
+
+	seq_printf(m, " : tunables %4u %4u %4u",
+		   sinfo.limit, sinfo.batchcount, sinfo.shared);
+	seq_printf(m, " : slabdata %6lu %6lu %6lu",
+		   sinfo.active_slabs, sinfo.num_slabs, sinfo.shared_avail);
+	slabinfo_show_stats(m, s);
+	seq_putc(m, '\n');
+	return 0;
+}
+
+static int s_show(struct seq_file *m, void *p)
+{
+	struct kmem_cache *s = list_entry(p, struct kmem_cache, list);
+
+	if (!is_root_cache(s))
+		return 0;
+	return cache_show(s, m);
+}
+
+/*
+ * slabinfo_op - iterator that generates /proc/slabinfo
+ *
+ * Output layout:
+ * cache-name
+ * num-active-objs
+ * total-objs
+ * object size
+ * num-active-slabs
+ * total-slabs
+ * num-pages-per-slab
+ * + further values on SMP and with statistics enabled
+ */
+static const struct seq_operations slabinfo_op = {
+	.start = s_start,
+	.next = s_next,
+	.stop = s_stop,
+	.show = s_show,
+};
+
+static int slabinfo_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &slabinfo_op);
+}
+
+static const struct file_operations proc_slabinfo_operations = {
+	.open		= slabinfo_open,
+	.read		= seq_read,
+	.write          = slabinfo_write,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+static int __init slab_proc_init(void)
+{
+	proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations);
+	return 0;
+}
+module_init(slab_proc_init);
+#endif /* CONFIG_SLABINFO */
diff --git a/mm/slob.c b/mm/slob.c
index 1e921c5..52381c4 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -28,9 +28,8 @@
  * from kmalloc are prepended with a 4-byte header with the kmalloc size.
  * If kmalloc is asked for objects of PAGE_SIZE or larger, it calls
  * alloc_pages() directly, allocating compound pages so the page order
- * does not have to be separately tracked, and also stores the exact
- * allocation size in page->private so that it can be used to accurately
- * provide ksize(). These objects are detected in kfree() because slob_page()
+ * does not have to be separately tracked.
+ * These objects are detected in kfree() because PageSlab()
  * is false for them.
  *
  * SLAB is emulated on top of SLOB by simply calling constructors and
@@ -59,7 +58,6 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include "slab.h"
 
 #include <linux/mm.h>
 #include <linux/swap.h> /* struct reclaim_state */
@@ -74,6 +72,7 @@
 
 #include <linux/atomic.h>
 
+#include "slab.h"
 /*
  * slob_block has a field 'units', which indicates size of block if +ve,
  * or offset of next block if -ve (in SLOB_UNITs).
@@ -455,11 +454,6 @@ __do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller)
 		if (likely(order))
 			gfp |= __GFP_COMP;
 		ret = slob_new_pages(gfp, order, node);
-		if (ret) {
-			struct page *page;
-			page = virt_to_page(ret);
-			page->private = size;
-		}
 
 		trace_kmalloc_node(caller, ret,
 				   size, PAGE_SIZE << order, gfp, node);
@@ -506,7 +500,7 @@ void kfree(const void *block)
 		unsigned int *m = (unsigned int *)(block - align);
 		slob_free(m, *m + align);
 	} else
-		put_page(sp);
+		__free_pages(sp, compound_order(sp));
 }
 EXPORT_SYMBOL(kfree);
 
@@ -514,18 +508,20 @@ EXPORT_SYMBOL(kfree);
 size_t ksize(const void *block)
 {
 	struct page *sp;
+	int align;
+	unsigned int *m;
 
 	BUG_ON(!block);
 	if (unlikely(block == ZERO_SIZE_PTR))
 		return 0;
 
 	sp = virt_to_page(block);
-	if (PageSlab(sp)) {
-		int align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
-		unsigned int *m = (unsigned int *)(block - align);
-		return SLOB_UNITS(*m) * SLOB_UNIT;
-	} else
-		return sp->private;
+	if (unlikely(!PageSlab(sp)))
+		return PAGE_SIZE << compound_order(sp);
+
+	align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
+	m = (unsigned int *)(block - align);
+	return SLOB_UNITS(*m) * SLOB_UNIT;
 }
 EXPORT_SYMBOL(ksize);
 
@@ -558,12 +554,12 @@ void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
 
 	if (c->size < PAGE_SIZE) {
 		b = slob_alloc(c->size, flags, c->align, node);
-		trace_kmem_cache_alloc_node(_RET_IP_, b, c->size,
+		trace_kmem_cache_alloc_node(_RET_IP_, b, c->object_size,
 					    SLOB_UNITS(c->size) * SLOB_UNIT,
 					    flags, node);
 	} else {
 		b = slob_new_pages(flags, get_order(c->size), node);
-		trace_kmem_cache_alloc_node(_RET_IP_, b, c->size,
+		trace_kmem_cache_alloc_node(_RET_IP_, b, c->object_size,
 					    PAGE_SIZE << get_order(c->size),
 					    flags, node);
 	}
@@ -608,12 +604,6 @@ void kmem_cache_free(struct kmem_cache *c, void *b)
 }
 EXPORT_SYMBOL(kmem_cache_free);
 
-unsigned int kmem_cache_size(struct kmem_cache *c)
-{
-	return c->size;
-}
-EXPORT_SYMBOL(kmem_cache_size);
-
 int __kmem_cache_shutdown(struct kmem_cache *c)
 {
 	/* No way to check for remaining objects */
diff --git a/mm/slub.c b/mm/slub.c
index a0d6984..b62a044 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -31,6 +31,7 @@
 #include <linux/fault-inject.h>
 #include <linux/stacktrace.h>
 #include <linux/prefetch.h>
+#include <linux/memcontrol.h>
 
 #include <trace/events/kmem.h>
 
@@ -112,9 +113,6 @@
  * 			the fast path and disables lockless freelists.
  */
 
-#define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
-		SLAB_TRACE | SLAB_DEBUG_FREE)
-
 static inline int kmem_cache_debug(struct kmem_cache *s)
 {
 #ifdef CONFIG_SLUB_DEBUG
@@ -205,13 +203,14 @@ enum track_item { TRACK_ALLOC, TRACK_FREE };
 static int sysfs_slab_add(struct kmem_cache *);
 static int sysfs_slab_alias(struct kmem_cache *, const char *);
 static void sysfs_slab_remove(struct kmem_cache *);
-
+static void memcg_propagate_slab_attrs(struct kmem_cache *s);
 #else
 static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; }
 static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
 							{ return 0; }
 static inline void sysfs_slab_remove(struct kmem_cache *s) { }
 
+static inline void memcg_propagate_slab_attrs(struct kmem_cache *s) { }
 #endif
 
 static inline void stat(const struct kmem_cache *s, enum stat_item si)
@@ -1092,11 +1091,11 @@ static noinline struct kmem_cache_node *free_debug_processing(
 	if (!check_object(s, page, object, SLUB_RED_ACTIVE))
 		goto out;
 
-	if (unlikely(s != page->slab)) {
+	if (unlikely(s != page->slab_cache)) {
 		if (!PageSlab(page)) {
 			slab_err(s, page, "Attempt to free object(0x%p) "
 				"outside of slab", object);
-		} else if (!page->slab) {
+		} else if (!page->slab_cache) {
 			printk(KERN_ERR
 				"SLUB <none>: no slab for object 0x%p.\n",
 						object);
@@ -1348,6 +1347,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
 	void *start;
 	void *last;
 	void *p;
+	int order;
 
 	BUG_ON(flags & GFP_SLAB_BUG_MASK);
 
@@ -1356,8 +1356,10 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
 	if (!page)
 		goto out;
 
+	order = compound_order(page);
 	inc_slabs_node(s, page_to_nid(page), page->objects);
-	page->slab = s;
+	memcg_bind_pages(s, order);
+	page->slab_cache = s;
 	__SetPageSlab(page);
 	if (page->pfmemalloc)
 		SetPageSlabPfmemalloc(page);
@@ -1365,7 +1367,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
 	start = page_address(page);
 
 	if (unlikely(s->flags & SLAB_POISON))
-		memset(start, POISON_INUSE, PAGE_SIZE << compound_order(page));
+		memset(start, POISON_INUSE, PAGE_SIZE << order);
 
 	last = start;
 	for_each_object(p, s, start, page->objects) {
@@ -1406,10 +1408,12 @@ static void __free_slab(struct kmem_cache *s, struct page *page)
 
 	__ClearPageSlabPfmemalloc(page);
 	__ClearPageSlab(page);
+
+	memcg_release_pages(s, order);
 	reset_page_mapcount(page);
 	if (current->reclaim_state)
 		current->reclaim_state->reclaimed_slab += pages;
-	__free_pages(page, order);
+	__free_memcg_kmem_pages(page, order);
 }
 
 #define need_reserve_slab_rcu						\
@@ -1424,7 +1428,7 @@ static void rcu_free_slab(struct rcu_head *h)
 	else
 		page = container_of((struct list_head *)h, struct page, lru);
 
-	__free_slab(page->slab, page);
+	__free_slab(page->slab_cache, page);
 }
 
 static void free_slab(struct kmem_cache *s, struct page *page)
@@ -2325,6 +2329,7 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
 	if (slab_pre_alloc_hook(s, gfpflags))
 		return NULL;
 
+	s = memcg_kmem_get_cache(s, gfpflags);
 redo:
 
 	/*
@@ -2459,7 +2464,6 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
 	void *prior;
 	void **object = (void *)x;
 	int was_frozen;
-	int inuse;
 	struct page new;
 	unsigned long counters;
 	struct kmem_cache_node *n = NULL;
@@ -2472,13 +2476,17 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
 		return;
 
 	do {
+		if (unlikely(n)) {
+			spin_unlock_irqrestore(&n->list_lock, flags);
+			n = NULL;
+		}
 		prior = page->freelist;
 		counters = page->counters;
 		set_freepointer(s, object, prior);
 		new.counters = counters;
 		was_frozen = new.frozen;
 		new.inuse--;
-		if ((!new.inuse || !prior) && !was_frozen && !n) {
+		if ((!new.inuse || !prior) && !was_frozen) {
 
 			if (!kmem_cache_debug(s) && !prior)
 
@@ -2503,7 +2511,6 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
 
 			}
 		}
-		inuse = new.inuse;
 
 	} while (!cmpxchg_double_slab(s, page,
 		prior, counters,
@@ -2529,25 +2536,17 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
                 return;
         }
 
+	if (unlikely(!new.inuse && n->nr_partial > s->min_partial))
+		goto slab_empty;
+
 	/*
-	 * was_frozen may have been set after we acquired the list_lock in
-	 * an earlier loop. So we need to check it here again.
+	 * Objects left in the slab. If it was not on the partial list before
+	 * then add it.
 	 */
-	if (was_frozen)
-		stat(s, FREE_FROZEN);
-	else {
-		if (unlikely(!inuse && n->nr_partial > s->min_partial))
-                        goto slab_empty;
-
-		/*
-		 * Objects left in the slab. If it was not on the partial list before
-		 * then add it.
-		 */
-		if (unlikely(!prior)) {
-			remove_full(s, page);
-			add_partial(n, page, DEACTIVATE_TO_TAIL);
-			stat(s, FREE_ADD_PARTIAL);
-		}
+	if (kmem_cache_debug(s) && unlikely(!prior)) {
+		remove_full(s, page);
+		add_partial(n, page, DEACTIVATE_TO_TAIL);
+		stat(s, FREE_ADD_PARTIAL);
 	}
 	spin_unlock_irqrestore(&n->list_lock, flags);
 	return;
@@ -2619,19 +2618,10 @@ redo:
 
 void kmem_cache_free(struct kmem_cache *s, void *x)
 {
-	struct page *page;
-
-	page = virt_to_head_page(x);
-
-	if (kmem_cache_debug(s) && page->slab != s) {
-		pr_err("kmem_cache_free: Wrong slab cache. %s but object"
-			" is from  %s\n", page->slab->name, s->name);
-		WARN_ON_ONCE(1);
+	s = cache_from_obj(s, x);
+	if (!s)
 		return;
-	}
-
-	slab_free(s, page, x, _RET_IP_);
-
+	slab_free(s, virt_to_head_page(x), x, _RET_IP_);
 	trace_kmem_cache_free(_RET_IP_, x);
 }
 EXPORT_SYMBOL(kmem_cache_free);
@@ -3127,15 +3117,6 @@ error:
 	return -EINVAL;
 }
 
-/*
- * Determine the size of a slab object
- */
-unsigned int kmem_cache_size(struct kmem_cache *s)
-{
-	return s->object_size;
-}
-EXPORT_SYMBOL(kmem_cache_size);
-
 static void list_slab_objects(struct kmem_cache *s, struct page *page,
 							const char *text)
 {
@@ -3208,8 +3189,19 @@ int __kmem_cache_shutdown(struct kmem_cache *s)
 {
 	int rc = kmem_cache_close(s);
 
-	if (!rc)
+	if (!rc) {
+		/*
+		 * We do the same lock strategy around sysfs_slab_add, see
+		 * __kmem_cache_create. Because this is pretty much the last
+		 * operation we do and the lock will be released shortly after
+		 * that in slab_common.c, we could just move sysfs_slab_remove
+		 * to a later point in common code. We should do that when we
+		 * have a common sysfs framework for all allocators.
+		 */
+		mutex_unlock(&slab_mutex);
 		sysfs_slab_remove(s);
+		mutex_lock(&slab_mutex);
+	}
 
 	return rc;
 }
@@ -3372,7 +3364,7 @@ static void *kmalloc_large_node(size_t size, gfp_t flags, int node)
 	struct page *page;
 	void *ptr = NULL;
 
-	flags |= __GFP_COMP | __GFP_NOTRACK;
+	flags |= __GFP_COMP | __GFP_NOTRACK | __GFP_KMEMCG;
 	page = alloc_pages_node(node, flags, get_order(size));
 	if (page)
 		ptr = page_address(page);
@@ -3424,7 +3416,7 @@ size_t ksize(const void *object)
 		return PAGE_SIZE << compound_order(page);
 	}
 
-	return slab_ksize(page->slab);
+	return slab_ksize(page->slab_cache);
 }
 EXPORT_SYMBOL(ksize);
 
@@ -3449,8 +3441,8 @@ bool verify_mem_not_deleted(const void *x)
 	}
 
 	slab_lock(page);
-	if (on_freelist(page->slab, page, object)) {
-		object_err(page->slab, page, object, "Object is on free-list");
+	if (on_freelist(page->slab_cache, page, object)) {
+		object_err(page->slab_cache, page, object, "Object is on free-list");
 		rv = false;
 	} else {
 		rv = true;
@@ -3478,10 +3470,10 @@ void kfree(const void *x)
 	if (unlikely(!PageSlab(page))) {
 		BUG_ON(!PageCompound(page));
 		kmemleak_free(x);
-		__free_pages(page, compound_order(page));
+		__free_memcg_kmem_pages(page, compound_order(page));
 		return;
 	}
-	slab_free(page->slab, page, object, _RET_IP_);
+	slab_free(page->slab_cache, page, object, _RET_IP_);
 }
 EXPORT_SYMBOL(kfree);
 
@@ -3573,7 +3565,7 @@ static void slab_mem_offline_callback(void *arg)
 	struct memory_notify *marg = arg;
 	int offline_node;
 
-	offline_node = marg->status_change_nid;
+	offline_node = marg->status_change_nid_normal;
 
 	/*
 	 * If the node still has available memory. we need kmem_cache_node
@@ -3606,7 +3598,7 @@ static int slab_mem_going_online_callback(void *arg)
 	struct kmem_cache_node *n;
 	struct kmem_cache *s;
 	struct memory_notify *marg = arg;
-	int nid = marg->status_change_nid;
+	int nid = marg->status_change_nid_normal;
 	int ret = 0;
 
 	/*
@@ -3692,11 +3684,11 @@ static void __init kmem_cache_bootstrap_fixup(struct kmem_cache *s)
 
 		if (n) {
 			list_for_each_entry(p, &n->partial, lru)
-				p->slab = s;
+				p->slab_cache = s;
 
 #ifdef CONFIG_SLUB_DEBUG
 			list_for_each_entry(p, &n->full, lru)
-				p->slab = s;
+				p->slab_cache = s;
 #endif
 		}
 	}
@@ -3891,7 +3883,7 @@ static int slab_unmergeable(struct kmem_cache *s)
 	return 0;
 }
 
-static struct kmem_cache *find_mergeable(size_t size,
+static struct kmem_cache *find_mergeable(struct mem_cgroup *memcg, size_t size,
 		size_t align, unsigned long flags, const char *name,
 		void (*ctor)(void *))
 {
@@ -3927,17 +3919,21 @@ static struct kmem_cache *find_mergeable(size_t size,
 		if (s->size - size >= sizeof(void *))
 			continue;
 
+		if (!cache_match_memcg(s, memcg))
+			continue;
+
 		return s;
 	}
 	return NULL;
 }
 
-struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
-		size_t align, unsigned long flags, void (*ctor)(void *))
+struct kmem_cache *
+__kmem_cache_alias(struct mem_cgroup *memcg, const char *name, size_t size,
+		   size_t align, unsigned long flags, void (*ctor)(void *))
 {
 	struct kmem_cache *s;
 
-	s = find_mergeable(size, align, flags, name, ctor);
+	s = find_mergeable(memcg, size, align, flags, name, ctor);
 	if (s) {
 		s->refcount++;
 		/*
@@ -3964,6 +3960,7 @@ int __kmem_cache_create(struct kmem_cache *s, unsigned long flags)
 	if (err)
 		return err;
 
+	memcg_propagate_slab_attrs(s);
 	mutex_unlock(&slab_mutex);
 	err = sysfs_slab_add(s);
 	mutex_lock(&slab_mutex);
@@ -5197,10 +5194,95 @@ static ssize_t slab_attr_store(struct kobject *kobj,
 		return -EIO;
 
 	err = attribute->store(s, buf, len);
+#ifdef CONFIG_MEMCG_KMEM
+	if (slab_state >= FULL && err >= 0 && is_root_cache(s)) {
+		int i;
+
+		mutex_lock(&slab_mutex);
+		if (s->max_attr_size < len)
+			s->max_attr_size = len;
 
+		/*
+		 * This is a best effort propagation, so this function's return
+		 * value will be determined by the parent cache only. This is
+		 * basically because not all attributes will have a well
+		 * defined semantics for rollbacks - most of the actions will
+		 * have permanent effects.
+		 *
+		 * Returning the error value of any of the children that fail
+		 * is not 100 % defined, in the sense that users seeing the
+		 * error code won't be able to know anything about the state of
+		 * the cache.
+		 *
+		 * Only returning the error code for the parent cache at least
+		 * has well defined semantics. The cache being written to
+		 * directly either failed or succeeded, in which case we loop
+		 * through the descendants with best-effort propagation.
+		 */
+		for_each_memcg_cache_index(i) {
+			struct kmem_cache *c = cache_from_memcg(s, i);
+			if (c)
+				attribute->store(c, buf, len);
+		}
+		mutex_unlock(&slab_mutex);
+	}
+#endif
 	return err;
 }
 
+static void memcg_propagate_slab_attrs(struct kmem_cache *s)
+{
+#ifdef CONFIG_MEMCG_KMEM
+	int i;
+	char *buffer = NULL;
+
+	if (!is_root_cache(s))
+		return;
+
+	/*
+	 * This mean this cache had no attribute written. Therefore, no point
+	 * in copying default values around
+	 */
+	if (!s->max_attr_size)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(slab_attrs); i++) {
+		char mbuf[64];
+		char *buf;
+		struct slab_attribute *attr = to_slab_attr(slab_attrs[i]);
+
+		if (!attr || !attr->store || !attr->show)
+			continue;
+
+		/*
+		 * It is really bad that we have to allocate here, so we will
+		 * do it only as a fallback. If we actually allocate, though,
+		 * we can just use the allocated buffer until the end.
+		 *
+		 * Most of the slub attributes will tend to be very small in
+		 * size, but sysfs allows buffers up to a page, so they can
+		 * theoretically happen.
+		 */
+		if (buffer)
+			buf = buffer;
+		else if (s->max_attr_size < ARRAY_SIZE(mbuf))
+			buf = mbuf;
+		else {
+			buffer = (char *) get_zeroed_page(GFP_KERNEL);
+			if (WARN_ON(!buffer))
+				continue;
+			buf = buffer;
+		}
+
+		attr->show(s->memcg_params->root_cache, buf);
+		attr->store(s, buf, strlen(buf));
+	}
+
+	if (buffer)
+		free_page((unsigned long)buffer);
+#endif
+}
+
 static const struct sysfs_ops slab_sysfs_ops = {
 	.show = slab_attr_show,
 	.store = slab_attr_store,
@@ -5257,6 +5339,12 @@ static char *create_unique_id(struct kmem_cache *s)
 	if (p != name + 1)
 		*p++ = '-';
 	p += sprintf(p, "%07d", s->size);
+
+#ifdef CONFIG_MEMCG_KMEM
+	if (!is_root_cache(s))
+		p += sprintf(p, "-%08d", memcg_cache_id(s->memcg_params->memcg));
+#endif
+
 	BUG_ON(p > name + ID_STR_LENGTH - 1);
 	return name;
 }
@@ -5405,49 +5493,14 @@ __initcall(slab_sysfs_init);
  * The /proc/slabinfo ABI
  */
 #ifdef CONFIG_SLABINFO
-static void print_slabinfo_header(struct seq_file *m)
-{
-	seq_puts(m, "slabinfo - version: 2.1\n");
-	seq_puts(m, "# name            <active_objs> <num_objs> <object_size> "
-		 "<objperslab> <pagesperslab>");
-	seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>");
-	seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
-	seq_putc(m, '\n');
-}
-
-static void *s_start(struct seq_file *m, loff_t *pos)
-{
-	loff_t n = *pos;
-
-	mutex_lock(&slab_mutex);
-	if (!n)
-		print_slabinfo_header(m);
-
-	return seq_list_start(&slab_caches, *pos);
-}
-
-static void *s_next(struct seq_file *m, void *p, loff_t *pos)
-{
-	return seq_list_next(p, &slab_caches, pos);
-}
-
-static void s_stop(struct seq_file *m, void *p)
-{
-	mutex_unlock(&slab_mutex);
-}
-
-static int s_show(struct seq_file *m, void *p)
+void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo)
 {
 	unsigned long nr_partials = 0;
 	unsigned long nr_slabs = 0;
-	unsigned long nr_inuse = 0;
 	unsigned long nr_objs = 0;
 	unsigned long nr_free = 0;
-	struct kmem_cache *s;
 	int node;
 
-	s = list_entry(p, struct kmem_cache, list);
-
 	for_each_online_node(node) {
 		struct kmem_cache_node *n = get_node(s, node);
 
@@ -5460,41 +5513,21 @@ static int s_show(struct seq_file *m, void *p)
 		nr_free += count_partial(n, count_free);
 	}
 
-	nr_inuse = nr_objs - nr_free;
-
-	seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", s->name, nr_inuse,
-		   nr_objs, s->size, oo_objects(s->oo),
-		   (1 << oo_order(s->oo)));
-	seq_printf(m, " : tunables %4u %4u %4u", 0, 0, 0);
-	seq_printf(m, " : slabdata %6lu %6lu %6lu", nr_slabs, nr_slabs,
-		   0UL);
-	seq_putc(m, '\n');
-	return 0;
+	sinfo->active_objs = nr_objs - nr_free;
+	sinfo->num_objs = nr_objs;
+	sinfo->active_slabs = nr_slabs;
+	sinfo->num_slabs = nr_slabs;
+	sinfo->objects_per_slab = oo_objects(s->oo);
+	sinfo->cache_order = oo_order(s->oo);
 }
 
-static const struct seq_operations slabinfo_op = {
-	.start = s_start,
-	.next = s_next,
-	.stop = s_stop,
-	.show = s_show,
-};
-
-static int slabinfo_open(struct inode *inode, struct file *file)
+void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s)
 {
-	return seq_open(file, &slabinfo_op);
 }
 
-static const struct file_operations proc_slabinfo_operations = {
-	.open		= slabinfo_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
-};
-
-static int __init slab_proc_init(void)
+ssize_t slabinfo_write(struct file *file, const char __user *buffer,
+		       size_t count, loff_t *ppos)
 {
-	proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations);
-	return 0;
+	return -EIO;
 }
-module_init(slab_proc_init);
 #endif /* CONFIG_SLABINFO */
diff --git a/mm/sparse.c b/mm/sparse.c
index fac95f2..6b5fb76 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -617,7 +617,7 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
 {
 	return; /* XXX: Not implemented yet */
 }
-static void free_map_bootmem(struct page *page, unsigned long nr_pages)
+static void free_map_bootmem(struct page *memmap, unsigned long nr_pages)
 {
 }
 #else
@@ -638,7 +638,6 @@ static struct page *__kmalloc_section_memmap(unsigned long nr_pages)
 got_map_page:
 	ret = (struct page *)pfn_to_kaddr(page_to_pfn(page));
 got_map_ptr:
-	memset(ret, 0, memmap_size);
 
 	return ret;
 }
@@ -658,10 +657,11 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
 			   get_order(sizeof(struct page) * nr_pages));
 }
 
-static void free_map_bootmem(struct page *page, unsigned long nr_pages)
+static void free_map_bootmem(struct page *memmap, unsigned long nr_pages)
 {
 	unsigned long maps_section_nr, removing_section_nr, i;
 	unsigned long magic;
+	struct page *page = virt_to_page(memmap);
 
 	for (i = 0; i < nr_pages; i++, page++) {
 		magic = (unsigned long) page->lru.next;
@@ -710,13 +710,10 @@ static void free_section_usemap(struct page *memmap, unsigned long *usemap)
 	 */
 
 	if (memmap) {
-		struct page *memmap_page;
-		memmap_page = virt_to_page(memmap);
-
 		nr_pages = PAGE_ALIGN(PAGES_PER_SECTION * sizeof(struct page))
 			>> PAGE_SHIFT;
 
-		free_map_bootmem(memmap_page, nr_pages);
+		free_map_bootmem(memmap, nr_pages);
 	}
 }
 
@@ -760,6 +757,8 @@ int __meminit sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
 		goto out;
 	}
 
+	memset(memmap, 0, sizeof(struct page) * nr_pages);
+
 	ms->section_mem_map |= SECTION_MARKED_PRESENT;
 
 	ret = sparse_init_one_section(ms, section_nr, memmap, usemap);
@@ -773,6 +772,27 @@ out:
 	return ret;
 }
 
+#ifdef CONFIG_MEMORY_FAILURE
+static void clear_hwpoisoned_pages(struct page *memmap, int nr_pages)
+{
+	int i;
+
+	if (!memmap)
+		return;
+
+	for (i = 0; i < PAGES_PER_SECTION; i++) {
+		if (PageHWPoison(&memmap[i])) {
+			atomic_long_sub(1, &mce_bad_pages);
+			ClearPageHWPoison(&memmap[i]);
+		}
+	}
+}
+#else
+static inline void clear_hwpoisoned_pages(struct page *memmap, int nr_pages)
+{
+}
+#endif
+
 void sparse_remove_one_section(struct zone *zone, struct mem_section *ms)
 {
 	struct page *memmap = NULL;
@@ -786,6 +806,7 @@ void sparse_remove_one_section(struct zone *zone, struct mem_section *ms)
 		ms->pageblock_flags = NULL;
 	}
 
+	clear_hwpoisoned_pages(memmap, PAGES_PER_SECTION);
 	free_section_usemap(memmap, usemap);
 }
 #endif
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 0cb36fb..d1f6c2d 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -20,6 +20,7 @@
 #include <linux/page_cgroup.h>
 
 #include <asm/pgtable.h>
+#include "internal.h"
 
 /*
  * swapper_space is a fiction, retained to simplify the path through
@@ -379,6 +380,10 @@ struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask,
 	unsigned long mask = (1UL << page_cluster) - 1;
 	struct blk_plug plug;
 
+	swap_cache_miss(vma);
+	if (swap_cache_skip_readahead(vma))
+		goto skip;
+
 	/* Read a page_cluster sized and aligned cluster around offset. */
 	start_offset = offset & ~mask;
 	end_offset = offset | mask;
@@ -397,5 +402,6 @@ struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask,
 	blk_finish_plug(&plug);
 
 	lru_add_drain();	/* Push any new pages onto the LRU now */
+skip:
 	return read_swap_cache_async(entry, gfp_mask, vma, addr);
 }
diff --git a/mm/swapfile.c b/mm/swapfile.c
index f91a255..e97a0e5 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1443,13 +1443,12 @@ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span)
 	return generic_swapfile_activate(sis, swap_file, span);
 }
 
-static void enable_swap_info(struct swap_info_struct *p, int prio,
+static void _enable_swap_info(struct swap_info_struct *p, int prio,
 				unsigned char *swap_map,
 				unsigned long *frontswap_map)
 {
 	int i, prev;
 
-	spin_lock(&swap_lock);
 	if (prio >= 0)
 		p->prio = prio;
 	else
@@ -1472,10 +1471,25 @@ static void enable_swap_info(struct swap_info_struct *p, int prio,
 		swap_list.head = swap_list.next = p->type;
 	else
 		swap_info[prev]->next = p->type;
+}
+
+static void enable_swap_info(struct swap_info_struct *p, int prio,
+				unsigned char *swap_map,
+				unsigned long *frontswap_map)
+{
+	spin_lock(&swap_lock);
+	_enable_swap_info(p, prio, swap_map, frontswap_map);
 	frontswap_init(p->type);
 	spin_unlock(&swap_lock);
 }
 
+static void reinsert_swap_info(struct swap_info_struct *p)
+{
+	spin_lock(&swap_lock);
+	_enable_swap_info(p, p->prio, p->swap_map, frontswap_map_get(p));
+	spin_unlock(&swap_lock);
+}
+
 SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 {
 	struct swap_info_struct *p = NULL;
@@ -1484,7 +1498,6 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 	struct address_space *mapping;
 	struct inode *inode;
 	struct filename *pathname;
-	int oom_score_adj;
 	int i, type, prev;
 	int err;
 
@@ -1543,19 +1556,13 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 	p->flags &= ~SWP_WRITEOK;
 	spin_unlock(&swap_lock);
 
-	oom_score_adj = test_set_oom_score_adj(OOM_SCORE_ADJ_MAX);
+	set_current_oom_origin();
 	err = try_to_unuse(type, false, 0); /* force all pages to be unused */
-	compare_swap_oom_score_adj(OOM_SCORE_ADJ_MAX, oom_score_adj);
+	clear_current_oom_origin();
 
 	if (err) {
-		/*
-		 * reading p->prio and p->swap_map outside the lock is
-		 * safe here because only sys_swapon and sys_swapoff
-		 * change them, and there can be no other sys_swapon or
-		 * sys_swapoff for this swap_info_struct at this point.
-		 */
 		/* re-insert swap space back into swap_list */
-		enable_swap_info(p, p->prio, p->swap_map, frontswap_map_get(p));
+		reinsert_swap_info(p);
 		goto out_dput;
 	}
 
diff --git a/mm/truncate.c b/mm/truncate.c
index d51ce92..db1b216 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -151,14 +151,20 @@ int truncate_inode_page(struct address_space *mapping, struct page *page)
  */
 int generic_error_remove_page(struct address_space *mapping, struct page *page)
 {
+	struct inode *inode;
+
 	if (!mapping)
 		return -EINVAL;
+	inode = mapping->host;
 	/*
 	 * Only punch for normal data pages for now.
 	 * Handling other types like directories would need more auditing.
 	 */
-	if (!S_ISREG(mapping->host->i_mode))
+	if (!S_ISREG(inode->i_mode))
 		return -EIO;
+	pr_info("MCE %#lx: file info pgoff:%lu, inode:%lu, dev:%s\n",
+		page_to_pfn(page), page_index(page),
+		inode->i_ino, inode->i_sb->s_id);
 	return truncate_inode_page(mapping, page);
 }
 EXPORT_SYMBOL(generic_error_remove_page);
diff --git a/mm/util.c b/mm/util.c
index dc3036c..c55e26b 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -152,7 +152,7 @@ EXPORT_SYMBOL(__krealloc);
  *
  * The contents of the object pointed to are preserved up to the
  * lesser of the new and old sizes.  If @p is %NULL, krealloc()
- * behaves exactly like kmalloc().  If @size is 0 and @p is not a
+ * behaves exactly like kmalloc().  If @new_size is 0 and @p is not a
  * %NULL pointer, the object pointed to is freed.
  */
 void *krealloc(const void *p, size_t new_size, gfp_t flags)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 78e0830..5123a16 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -2550,7 +2550,7 @@ static void s_stop(struct seq_file *m, void *p)
 
 static void show_numa_info(struct seq_file *m, struct vm_struct *v)
 {
-	if (NUMA_BUILD) {
+	if (IS_ENABLED(CONFIG_NUMA)) {
 		unsigned int nr, *counters = m->private;
 
 		if (!counters)
@@ -2615,7 +2615,7 @@ static int vmalloc_open(struct inode *inode, struct file *file)
 	unsigned int *ptr = NULL;
 	int ret;
 
-	if (NUMA_BUILD) {
+	if (IS_ENABLED(CONFIG_NUMA)) {
 		ptr = kmalloc(nr_node_ids * sizeof(unsigned int), GFP_KERNEL);
 		if (ptr == NULL)
 			return -ENOMEM;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 48550c6..53dcde9 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1679,13 +1679,24 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
 
 	if (global_reclaim(sc)) {
 		free  = zone_page_state(zone, NR_FREE_PAGES);
-		/* If we have very few page cache pages,
-		   force-scan anon pages. */
 		if (unlikely(file + free <= high_wmark_pages(zone))) {
+			/*
+			 * If we have very few page cache pages, force-scan
+			 * anon pages.
+			 */
 			fraction[0] = 1;
 			fraction[1] = 0;
 			denominator = 1;
 			goto out;
+		} else if (!inactive_file_is_low_global(zone)) {
+			/*
+			 * There is enough inactive page cache, do not
+			 * reclaim anything from the working set right now.
+			 */
+			fraction[0] = 0;
+			fraction[1] = 1;
+			denominator = 1;
+			goto out;
 		}
 	}
 
@@ -1752,7 +1763,7 @@ out:
 /* Use reclaim/compaction for costly allocs or under memory pressure */
 static bool in_reclaim_compaction(struct scan_control *sc)
 {
-	if (COMPACTION_BUILD && sc->order &&
+	if (IS_ENABLED(CONFIG_COMPACTION) && sc->order &&
 			(sc->order > PAGE_ALLOC_COSTLY_ORDER ||
 			 sc->priority < DEF_PRIORITY - 2))
 		return true;
@@ -2005,7 +2016,7 @@ static bool shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
 			if (zone->all_unreclaimable &&
 					sc->priority != DEF_PRIORITY)
 				continue;	/* Let kswapd poll it */
-			if (COMPACTION_BUILD) {
+			if (IS_ENABLED(CONFIG_COMPACTION)) {
 				/*
 				 * If we already have plenty of memory free for
 				 * compaction in this zone, don't free any more.
@@ -2207,9 +2218,12 @@ static bool pfmemalloc_watermark_ok(pg_data_t *pgdat)
  * Throttle direct reclaimers if backing storage is backed by the network
  * and the PFMEMALLOC reserve for the preferred node is getting dangerously
  * depleted. kswapd will continue to make progress and wake the processes
- * when the low watermark is reached
+ * when the low watermark is reached.
+ *
+ * Returns true if a fatal signal was delivered during throttling. If this
+ * happens, the page allocator should not consider triggering the OOM killer.
  */
-static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
+static bool throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
 					nodemask_t *nodemask)
 {
 	struct zone *zone;
@@ -2224,13 +2238,20 @@ static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
 	 * processes to block on log_wait_commit().
 	 */
 	if (current->flags & PF_KTHREAD)
-		return;
+		goto out;
+
+	/*
+	 * If a fatal signal is pending, this process should not throttle.
+	 * It should return quickly so it can exit and free its memory
+	 */
+	if (fatal_signal_pending(current))
+		goto out;
 
 	/* Check if the pfmemalloc reserves are ok */
 	first_zones_zonelist(zonelist, high_zoneidx, NULL, &zone);
 	pgdat = zone->zone_pgdat;
 	if (pfmemalloc_watermark_ok(pgdat))
-		return;
+		goto out;
 
 	/* Account for the throttling */
 	count_vm_event(PGSCAN_DIRECT_THROTTLE);
@@ -2246,12 +2267,20 @@ static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
 	if (!(gfp_mask & __GFP_FS)) {
 		wait_event_interruptible_timeout(pgdat->pfmemalloc_wait,
 			pfmemalloc_watermark_ok(pgdat), HZ);
-		return;
+
+		goto check_pending;
 	}
 
 	/* Throttle until kswapd wakes the process */
 	wait_event_killable(zone->zone_pgdat->pfmemalloc_wait,
 		pfmemalloc_watermark_ok(pgdat));
+
+check_pending:
+	if (fatal_signal_pending(current))
+		return true;
+
+out:
+	return false;
 }
 
 unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
@@ -2273,13 +2302,12 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
 		.gfp_mask = sc.gfp_mask,
 	};
 
-	throttle_direct_reclaim(gfp_mask, zonelist, nodemask);
-
 	/*
-	 * Do not enter reclaim if fatal signal is pending. 1 is returned so
-	 * that the page allocator does not consider triggering OOM
+	 * Do not enter reclaim if fatal signal was delivered while throttled.
+	 * 1 is returned so that the page allocator does not OOM kill at this
+	 * point.
 	 */
-	if (fatal_signal_pending(current))
+	if (throttle_direct_reclaim(gfp_mask, zonelist, nodemask))
 		return 1;
 
 	trace_mm_vmscan_direct_reclaim_begin(order,
@@ -2397,6 +2425,20 @@ static void age_active_anon(struct zone *zone, struct scan_control *sc)
 	} while (memcg);
 }
 
+static bool zone_balanced(struct zone *zone, int order,
+			  unsigned long balance_gap, int classzone_idx)
+{
+	if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone) +
+				    balance_gap, classzone_idx, 0))
+		return false;
+
+	if (IS_ENABLED(CONFIG_COMPACTION) && order &&
+			!compaction_suitable(zone, order))
+		return false;
+
+	return true;
+}
+
 /*
  * pgdat_balanced is used when checking if a node is balanced for high-order
  * allocations. Only zones that meet watermarks and are in a zone allowed
@@ -2475,8 +2517,7 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, long remaining,
 			continue;
 		}
 
-		if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone),
-							i, 0))
+		if (!zone_balanced(zone, order, 0, i))
 			all_zones_ok = false;
 		else
 			balanced += zone->present_pages;
@@ -2585,8 +2626,7 @@ loop_again:
 				break;
 			}
 
-			if (!zone_watermark_ok_safe(zone, order,
-					high_wmark_pages(zone), 0, 0)) {
+			if (!zone_balanced(zone, order, 0, 0)) {
 				end_zone = i;
 				break;
 			} else {
@@ -2656,15 +2696,14 @@ loop_again:
 			 * Do not reclaim more than needed for compaction.
 			 */
 			testorder = order;
-			if (COMPACTION_BUILD && order &&
+			if (IS_ENABLED(CONFIG_COMPACTION) && order &&
 					compaction_suitable(zone, order) !=
 						COMPACT_SKIPPED)
 				testorder = 0;
 
 			if ((buffer_heads_over_limit && is_highmem_idx(i)) ||
-				    !zone_watermark_ok_safe(zone, testorder,
-					high_wmark_pages(zone) + balance_gap,
-					end_zone, 0)) {
+			    !zone_balanced(zone, testorder,
+					   balance_gap, end_zone)) {
 				shrink_zone(zone, &sc);
 
 				reclaim_state->reclaimed_slab = 0;
@@ -2691,8 +2730,7 @@ loop_again:
 				continue;
 			}
 
-			if (!zone_watermark_ok_safe(zone, testorder,
-					high_wmark_pages(zone), end_zone, 0)) {
+			if (!zone_balanced(zone, testorder, 0, end_zone)) {
 				all_zones_ok = 0;
 				/*
 				 * We are still under min water mark.  This
@@ -2802,7 +2840,7 @@ out:
 				continue;
 
 			/* Would compaction fail due to lack of free memory? */
-			if (COMPACTION_BUILD &&
+			if (IS_ENABLED(CONFIG_COMPACTION) &&
 			    compaction_suitable(zone, order) == COMPACT_SKIPPED)
 				goto loop_again;
 
@@ -2944,7 +2982,7 @@ static int kswapd(void *p)
 	classzone_idx = new_classzone_idx = pgdat->nr_zones - 1;
 	balanced_classzone_idx = classzone_idx;
 	for ( ; ; ) {
-		int ret;
+		bool ret;
 
 		/*
 		 * If the last balance_pgdat was unsuccessful it's unlikely a
@@ -3112,7 +3150,7 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
 	int nid;
 
 	if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN) {
-		for_each_node_state(nid, N_HIGH_MEMORY) {
+		for_each_node_state(nid, N_MEMORY) {
 			pg_data_t *pgdat = NODE_DATA(nid);
 			const struct cpumask *mask;
 
@@ -3168,7 +3206,7 @@ static int __init kswapd_init(void)
 	int nid;
 
 	swap_setup();
-	for_each_node_state(nid, N_HIGH_MEMORY)
+	for_each_node_state(nid, N_MEMORY)
  		kswapd_run(nid);
 	hotcpu_notifier(cpu_callback, 0);
 	return 0;
diff --git a/mm/vmstat.c b/mm/vmstat.c
index c737057..103c50b 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -781,7 +781,14 @@ const char * const vmstat_text[] = {
 	"compact_stall",
 	"compact_fail",
 	"compact_success",
-#endif
+
+#ifdef CONFIG_BALLOON_COMPACTION
+	"compact_balloon_isolated",
+	"compact_balloon_migrated",
+	"compact_balloon_returned",
+#endif /* CONFIG_BALLOON_COMPACTION */
+
+#endif /* CONFIG_COMPACTION */
 
 #ifdef CONFIG_HUGETLB_PAGE
 	"htlb_buddy_alloc_success",
@@ -801,6 +808,8 @@ const char * const vmstat_text[] = {
 	"thp_collapse_alloc",
 	"thp_collapse_alloc_failed",
 	"thp_split",
+	"thp_zero_page_alloc",
+	"thp_zero_page_alloc_failed",
 #endif
 
 #endif /* CONFIG_VM_EVENTS_COUNTERS */
@@ -930,7 +939,7 @@ static int pagetypeinfo_show(struct seq_file *m, void *arg)
 	pg_data_t *pgdat = (pg_data_t *)arg;
 
 	/* check memoryless node */
-	if (!node_state(pgdat->node_id, N_HIGH_MEMORY))
+	if (!node_state(pgdat->node_id, N_MEMORY))
 		return 0;
 
 	seq_printf(m, "Page block order: %d\n", pageblock_order);
@@ -992,14 +1001,16 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
 		   "\n        high     %lu"
 		   "\n        scanned  %lu"
 		   "\n        spanned  %lu"
-		   "\n        present  %lu",
+		   "\n        present  %lu"
+		   "\n        managed  %lu",
 		   zone_page_state(zone, NR_FREE_PAGES),
 		   min_wmark_pages(zone),
 		   low_wmark_pages(zone),
 		   high_wmark_pages(zone),
 		   zone->pages_scanned,
 		   zone->spanned_pages,
-		   zone->present_pages);
+		   zone->present_pages,
+		   zone->managed_pages);
 
 	for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
 		seq_printf(m, "\n    %-12s %lu", vmstat_text[i],
@@ -1292,7 +1303,7 @@ static int unusable_show(struct seq_file *m, void *arg)
 	pg_data_t *pgdat = (pg_data_t *)arg;
 
 	/* check memoryless node */
-	if (!node_state(pgdat->node_id, N_HIGH_MEMORY))
+	if (!node_state(pgdat->node_id, N_MEMORY))
 		return 0;
 
 	walk_zones_in_node(m, pgdat, unusable_show_print);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index ee07072..afba51e 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -294,7 +294,7 @@ static void vlan_transfer_features(struct net_device *dev,
 	else
 		vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN;
 
-#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+#if IS_ENABLED(CONFIG_FCOE)
 	vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid;
 #endif
 
@@ -529,7 +529,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
 	switch (args.cmd) {
 	case SET_VLAN_INGRESS_PRIORITY_CMD:
 		err = -EPERM;
-		if (!capable(CAP_NET_ADMIN))
+		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 			break;
 		vlan_dev_set_ingress_priority(dev,
 					      args.u.skb_priority,
@@ -539,7 +539,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
 
 	case SET_VLAN_EGRESS_PRIORITY_CMD:
 		err = -EPERM;
-		if (!capable(CAP_NET_ADMIN))
+		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 			break;
 		err = vlan_dev_set_egress_priority(dev,
 						   args.u.skb_priority,
@@ -548,7 +548,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
 
 	case SET_VLAN_FLAG_CMD:
 		err = -EPERM;
-		if (!capable(CAP_NET_ADMIN))
+		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 			break;
 		err = vlan_dev_change_flags(dev,
 					    args.vlan_qos ? args.u.flag : 0,
@@ -557,7 +557,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
 
 	case SET_VLAN_NAME_TYPE_CMD:
 		err = -EPERM;
-		if (!capable(CAP_NET_ADMIN))
+		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 			break;
 		if ((args.u.name_type >= 0) &&
 		    (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
@@ -573,14 +573,14 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
 
 	case ADD_VLAN_CMD:
 		err = -EPERM;
-		if (!capable(CAP_NET_ADMIN))
+		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 			break;
 		err = register_vlan_device(dev, args.u.VID);
 		break;
 
 	case DEL_VLAN_CMD:
 		err = -EPERM;
-		if (!capable(CAP_NET_ADMIN))
+		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 			break;
 		unregister_vlan_dev(dev, NULL);
 		err = 0;
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 4024424..4a6d31a 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -409,7 +409,7 @@ static int vlan_dev_neigh_setup(struct net_device *dev, struct neigh_parms *pa)
 	return err;
 }
 
-#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+#if IS_ENABLED(CONFIG_FCOE)
 static int vlan_dev_fcoe_ddp_setup(struct net_device *dev, u16 xid,
 				   struct scatterlist *sgl, unsigned int sgc)
 {
@@ -531,6 +531,10 @@ static const struct header_ops vlan_header_ops = {
 	.parse	 = eth_header_parse,
 };
 
+static struct device_type vlan_type = {
+	.name	= "vlan",
+};
+
 static const struct net_device_ops vlan_netdev_ops;
 
 static int vlan_dev_init(struct net_device *dev)
@@ -564,7 +568,7 @@ static int vlan_dev_init(struct net_device *dev)
 	if (is_zero_ether_addr(dev->broadcast))
 		memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);
 
-#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+#if IS_ENABLED(CONFIG_FCOE)
 	dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid;
 #endif
 
@@ -579,6 +583,8 @@ static int vlan_dev_init(struct net_device *dev)
 
 	dev->netdev_ops = &vlan_netdev_ops;
 
+	SET_NETDEV_DEVTYPE(dev, &vlan_type);
+
 	if (is_vlan_dev(real_dev))
 		subclass = 1;
 
@@ -741,7 +747,7 @@ static const struct net_device_ops vlan_netdev_ops = {
 	.ndo_do_ioctl		= vlan_dev_ioctl,
 	.ndo_neigh_setup	= vlan_dev_neigh_setup,
 	.ndo_get_stats64	= vlan_dev_get_stats64,
-#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+#if IS_ENABLED(CONFIG_FCOE)
 	.ndo_fcoe_ddp_setup	= vlan_dev_fcoe_ddp_setup,
 	.ndo_fcoe_ddp_done	= vlan_dev_fcoe_ddp_done,
 	.ndo_fcoe_enable	= vlan_dev_fcoe_enable,
diff --git a/net/9p/Kconfig b/net/9p/Kconfig
index d9ea09b..a75174a 100644
--- a/net/9p/Kconfig
+++ b/net/9p/Kconfig
@@ -23,7 +23,7 @@ config NET_9P_VIRTIO
 	  guest partitions and a host partition.
 
 config NET_9P_RDMA
-	depends on INET && INFINIBAND && INFINIBAND_ADDR_TRANS && EXPERIMENTAL
+	depends on INET && INFINIBAND && INFINIBAND_ADDR_TRANS
 	tristate "9P RDMA Transport (Experimental)"
 	help
 	  This builds support for an RDMA transport.
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index 35b8911..fd05c81 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -39,6 +39,7 @@
 #include <linux/inet.h>
 #include <linux/idr.h>
 #include <linux/file.h>
+#include <linux/highmem.h>
 #include <linux/slab.h>
 #include <net/9p/9p.h>
 #include <linux/parser.h>
@@ -325,7 +326,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
 		int count = nr_pages;
 		while (nr_pages) {
 			s = rest_of_page(data);
-			pages[index++] = virt_to_page(data);
+			pages[index++] = kmap_to_page(data);
 			data += s;
 			nr_pages--;
 		}
diff --git a/net/Kconfig b/net/Kconfig
index 30b48f5..7bdab26 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -90,7 +90,6 @@ config NETWORK_SECMARK
 
 config NETWORK_PHY_TIMESTAMPING
 	bool "Timestamping in PHY devices"
-	depends on EXPERIMENTAL
 	help
 	  This allows timestamping of network packets by PHYs with
 	  hardware timestamping capabilities. This option adds some
@@ -278,7 +277,7 @@ config NET_PKTGEN
 
 config NET_TCPPROBE
 	tristate "TCP connection probing"
-	depends on INET && EXPERIMENTAL && PROC_FS && KPROBES
+	depends on INET && PROC_FS && KPROBES
 	---help---
 	This module allows for capturing the changes to TCP connection
 	state in response to incoming packets. It is used for debugging
@@ -295,7 +294,7 @@ config NET_TCPPROBE
 
 config NET_DROP_MONITOR
 	tristate "Network packet drop alerting service"
-	depends on INET && EXPERIMENTAL && TRACEPOINTS
+	depends on INET && TRACEPOINTS
 	---help---
 	This feature provides an alerting service to userspace in the
 	event that packets are discarded in the network stack.  Alerts
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 4819d315..8eb6fbe 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -74,6 +74,7 @@ struct br2684_vcc {
 	struct br2684_filter filter;
 #endif /* CONFIG_ATM_BR2684_IPFILTER */
 	unsigned int copies_needed, copies_failed;
+	atomic_t qspace;
 };
 
 struct br2684_dev {
@@ -181,18 +182,15 @@ static struct notifier_block atm_dev_notifier = {
 static void br2684_pop(struct atm_vcc *vcc, struct sk_buff *skb)
 {
 	struct br2684_vcc *brvcc = BR2684_VCC(vcc);
-	struct net_device *net_dev = skb->dev;
 
-	pr_debug("(vcc %p ; net_dev %p )\n", vcc, net_dev);
+	pr_debug("(vcc %p ; net_dev %p )\n", vcc, brvcc->device);
 	brvcc->old_pop(vcc, skb);
 
-	if (!net_dev)
-		return;
-
-	if (atm_may_send(vcc, 0))
-		netif_wake_queue(net_dev);
-
+	/* If the queue space just went up from zero, wake */
+	if (atomic_inc_return(&brvcc->qspace) == 1)
+		netif_wake_queue(brvcc->device);
 }
+
 /*
  * Send a packet out a particular vcc.  Not to useful right now, but paves
  * the way for multiple vcc's per itf.  Returns true if we can send,
@@ -256,16 +254,19 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev,
 	ATM_SKB(skb)->atm_options = atmvcc->atm_options;
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += skb->len;
-	atmvcc->send(atmvcc, skb);
 
-	if (!atm_may_send(atmvcc, 0)) {
+	if (atomic_dec_return(&brvcc->qspace) < 1) {
+		/* No more please! */
 		netif_stop_queue(brvcc->device);
-		/*check for race with br2684_pop*/
-		if (atm_may_send(atmvcc, 0))
-			netif_start_queue(brvcc->device);
+		/* We might have raced with br2684_pop() */
+		if (unlikely(atomic_read(&brvcc->qspace) > 0))
+			netif_wake_queue(brvcc->device);
 	}
 
-	return 1;
+	/* If this fails immediately, the skb will be freed and br2684_pop()
+	   will wake the queue if appropriate. Just return an error so that
+	   the stats are updated correctly */
+	return !atmvcc->send(atmvcc, skb);
 }
 
 static inline struct br2684_vcc *pick_outgoing_vcc(const struct sk_buff *skb,
@@ -504,6 +505,13 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
 	brvcc = kzalloc(sizeof(struct br2684_vcc), GFP_KERNEL);
 	if (!brvcc)
 		return -ENOMEM;
+	/*
+	 * Allow two packets in the ATM queue. One actually being sent, and one
+	 * for the ATM 'TX done' handler to send. It shouldn't take long to get
+	 * the next one from the netdev queue, when we need it. More than that
+	 * would be bufferbloat.
+	 */
+	atomic_set(&brvcc->qspace, 2);
 	write_lock_irq(&devs_lock);
 	net_dev = br2684_find_dev(&be.ifspec);
 	if (net_dev == NULL) {
diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig
index 53f5244..8d8afb1 100644
--- a/net/batman-adv/Kconfig
+++ b/net/batman-adv/Kconfig
@@ -6,6 +6,7 @@ config BATMAN_ADV
 	tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
 	depends on NET
 	select CRC16
+	select LIBCRC32C
         default n
 	help
           B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is
@@ -25,6 +26,16 @@ config BATMAN_ADV_BLA
 	  more than one mesh node in the same LAN, you can safely remove
 	  this feature and save some space.
 
+config BATMAN_ADV_DAT
+	bool "Distributed ARP Table"
+	depends on BATMAN_ADV && INET
+	default n
+	help
+	  This option enables DAT (Distributed ARP Table), a DHT based
+	  mechanism that increases ARP reliability on sparse wireless
+	  mesh networks. If you think that your network does not need
+	  this option you can safely remove it and save some space.
+
 config BATMAN_ADV_DEBUG
 	bool "B.A.T.M.A.N. debugging"
 	depends on BATMAN_ADV
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index 8676d2b..e45e3b4 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -23,6 +23,7 @@ batman-adv-y += bat_iv_ogm.o
 batman-adv-y += bitarray.o
 batman-adv-$(CONFIG_BATMAN_ADV_BLA) += bridge_loop_avoidance.o
 batman-adv-y += debugfs.o
+batman-adv-$(CONFIG_BATMAN_ADV_DAT) += distributed-arp-table.o
 batman-adv-y += gateway_client.o
 batman-adv-y += gateway_common.o
 batman-adv-y += hard-interface.o
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index b02b75d..9f3925a 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -57,20 +57,22 @@ out:
 static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
 {
 	struct batadv_ogm_packet *batadv_ogm_packet;
+	unsigned char *ogm_buff;
 	uint32_t random_seqno;
 	int res = -ENOMEM;
 
 	/* randomize initial seqno to avoid collision */
 	get_random_bytes(&random_seqno, sizeof(random_seqno));
-	atomic_set(&hard_iface->seqno, random_seqno);
+	atomic_set(&hard_iface->bat_iv.ogm_seqno, random_seqno);
 
-	hard_iface->packet_len = BATADV_OGM_HLEN;
-	hard_iface->packet_buff = kmalloc(hard_iface->packet_len, GFP_ATOMIC);
-
-	if (!hard_iface->packet_buff)
+	hard_iface->bat_iv.ogm_buff_len = BATADV_OGM_HLEN;
+	ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC);
+	if (!ogm_buff)
 		goto out;
 
-	batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
+	hard_iface->bat_iv.ogm_buff = ogm_buff;
+
+	batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
 	batadv_ogm_packet->header.packet_type = BATADV_IV_OGM;
 	batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION;
 	batadv_ogm_packet->header.ttl = 2;
@@ -87,15 +89,16 @@ out:
 
 static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
 {
-	kfree(hard_iface->packet_buff);
-	hard_iface->packet_buff = NULL;
+	kfree(hard_iface->bat_iv.ogm_buff);
+	hard_iface->bat_iv.ogm_buff = NULL;
 }
 
 static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
 {
 	struct batadv_ogm_packet *batadv_ogm_packet;
+	unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
 
-	batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
+	batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
 	memcpy(batadv_ogm_packet->orig,
 	       hard_iface->net_dev->dev_addr, ETH_ALEN);
 	memcpy(batadv_ogm_packet->prev_sender,
@@ -106,8 +109,9 @@ static void
 batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
 {
 	struct batadv_ogm_packet *batadv_ogm_packet;
+	unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
 
-	batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
+	batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
 	batadv_ogm_packet->flags = BATADV_PRIMARIES_FIRST_HOP;
 	batadv_ogm_packet->header.ttl = BATADV_TTL;
 }
@@ -407,9 +411,11 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
 
 	if ((atomic_read(&bat_priv->aggregated_ogms)) &&
 	    (packet_len < BATADV_MAX_AGGREGATION_BYTES))
-		skb_size = BATADV_MAX_AGGREGATION_BYTES + ETH_HLEN;
+		skb_size = BATADV_MAX_AGGREGATION_BYTES;
 	else
-		skb_size = packet_len + ETH_HLEN;
+		skb_size = packet_len;
+
+	skb_size += ETH_HLEN + NET_IP_ALIGN;
 
 	forw_packet_aggr->skb = dev_alloc_skb(skb_size);
 	if (!forw_packet_aggr->skb) {
@@ -418,7 +424,7 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
 		kfree(forw_packet_aggr);
 		goto out;
 	}
-	skb_reserve(forw_packet_aggr->skb, ETH_HLEN);
+	skb_reserve(forw_packet_aggr->skb, ETH_HLEN + NET_IP_ALIGN);
 
 	INIT_HLIST_NODE(&forw_packet_aggr->list);
 
@@ -590,8 +596,10 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
 static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
 {
 	struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
+	unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff;
 	struct batadv_ogm_packet *batadv_ogm_packet;
 	struct batadv_hard_iface *primary_if;
+	int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len;
 	int vis_server, tt_num_changes = 0;
 	uint32_t seqno;
 	uint8_t bandwidth;
@@ -600,17 +608,16 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
 	primary_if = batadv_primary_if_get_selected(bat_priv);
 
 	if (hard_iface == primary_if)
-		tt_num_changes = batadv_tt_append_diff(bat_priv,
-						       &hard_iface->packet_buff,
-						       &hard_iface->packet_len,
+		tt_num_changes = batadv_tt_append_diff(bat_priv, ogm_buff,
+						       ogm_buff_len,
 						       BATADV_OGM_HLEN);
 
-	batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
+	batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff);
 
 	/* change sequence number to network order */
-	seqno = (uint32_t)atomic_read(&hard_iface->seqno);
+	seqno = (uint32_t)atomic_read(&hard_iface->bat_iv.ogm_seqno);
 	batadv_ogm_packet->seqno = htonl(seqno);
-	atomic_inc(&hard_iface->seqno);
+	atomic_inc(&hard_iface->bat_iv.ogm_seqno);
 
 	batadv_ogm_packet->ttvn = atomic_read(&bat_priv->tt.vn);
 	batadv_ogm_packet->tt_crc = htons(bat_priv->tt.local_crc);
@@ -631,8 +638,8 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
 	}
 
 	batadv_slide_own_bcast_window(hard_iface);
-	batadv_iv_ogm_queue_add(bat_priv, hard_iface->packet_buff,
-				hard_iface->packet_len, hard_iface, 1,
+	batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff,
+				hard_iface->bat_iv.ogm_buff_len, hard_iface, 1,
 				batadv_iv_ogm_emit_send_time(bat_priv));
 
 	if (primary_if)
@@ -1015,7 +1022,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
 		return;
 
 	/* could be changed by schedule_own_packet() */
-	if_incoming_seqno = atomic_read(&if_incoming->seqno);
+	if_incoming_seqno = atomic_read(&if_incoming->bat_iv.ogm_seqno);
 
 	if (batadv_ogm_packet->flags & BATADV_DIRECTLINK)
 		has_directlink_flag = 1;
diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c
index aea174c..5453b17 100644
--- a/net/batman-adv/bitarray.c
+++ b/net/batman-adv/bitarray.c
@@ -79,20 +79,17 @@ int batadv_bit_get_packet(void *priv, unsigned long *seq_bits,
 	 * or the old packet got delayed somewhere in the network. The
 	 * packet should be dropped without calling this function if the
 	 * seqno window is protected.
+	 *
+	 * seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE
+	 * or
+	 * seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE
 	 */
-	if (seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE ||
-	    seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE) {
+	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+		   "Other host probably restarted!\n");
 
-		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-			   "Other host probably restarted!\n");
-
-		bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
-		if (set_mark)
-			batadv_set_bit(seq_bits, 0);
-
-		return 1;
-	}
+	bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
+	if (set_mark)
+		batadv_set_bit(seq_bits, 0);
 
-	/* never reached */
-	return 0;
+	return 1;
 }
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index fd8d5af..5aebe93 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -40,15 +40,11 @@ static void batadv_bla_send_announce(struct batadv_priv *bat_priv,
 /* return the index of the claim */
 static inline uint32_t batadv_choose_claim(const void *data, uint32_t size)
 {
-	const unsigned char *key = data;
+	struct batadv_claim *claim = (struct batadv_claim *)data;
 	uint32_t hash = 0;
-	size_t i;
 
-	for (i = 0; i < ETH_ALEN + sizeof(short); i++) {
-		hash += key[i];
-		hash += (hash << 10);
-		hash ^= (hash >> 6);
-	}
+	hash = batadv_hash_bytes(hash, &claim->addr, sizeof(claim->addr));
+	hash = batadv_hash_bytes(hash, &claim->vid, sizeof(claim->vid));
 
 	hash += (hash << 3);
 	hash ^= (hash >> 11);
@@ -61,15 +57,11 @@ static inline uint32_t batadv_choose_claim(const void *data, uint32_t size)
 static inline uint32_t batadv_choose_backbone_gw(const void *data,
 						 uint32_t size)
 {
-	const unsigned char *key = data;
+	struct batadv_claim *claim = (struct batadv_claim *)data;
 	uint32_t hash = 0;
-	size_t i;
 
-	for (i = 0; i < ETH_ALEN + sizeof(short); i++) {
-		hash += key[i];
-		hash += (hash << 10);
-		hash ^= (hash >> 6);
-	}
+	hash = batadv_hash_bytes(hash, &claim->addr, sizeof(claim->addr));
+	hash = batadv_hash_bytes(hash, &claim->vid, sizeof(claim->vid));
 
 	hash += (hash << 3);
 	hash ^= (hash >> 11);
@@ -85,8 +77,15 @@ static int batadv_compare_backbone_gw(const struct hlist_node *node,
 {
 	const void *data1 = container_of(node, struct batadv_backbone_gw,
 					 hash_entry);
+	const struct batadv_backbone_gw *gw1 = data1, *gw2 = data2;
+
+	if (!batadv_compare_eth(gw1->orig, gw2->orig))
+		return 0;
+
+	if (gw1->vid != gw2->vid)
+		return 0;
 
-	return (memcmp(data1, data2, ETH_ALEN + sizeof(short)) == 0 ? 1 : 0);
+	return 1;
 }
 
 /* compares address and vid of two claims */
@@ -95,8 +94,15 @@ static int batadv_compare_claim(const struct hlist_node *node,
 {
 	const void *data1 = container_of(node, struct batadv_claim,
 					 hash_entry);
+	const struct batadv_claim *cl1 = data1, *cl2 = data2;
+
+	if (!batadv_compare_eth(cl1->addr, cl2->addr))
+		return 0;
+
+	if (cl1->vid != cl2->vid)
+		return 0;
 
-	return (memcmp(data1, data2, ETH_ALEN + sizeof(short)) == 0 ? 1 : 0);
+	return 1;
 }
 
 /* free a backbone gw */
@@ -362,7 +368,7 @@ out:
  */
 static struct batadv_backbone_gw *
 batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
-			   short vid)
+			   short vid, bool own_backbone)
 {
 	struct batadv_backbone_gw *entry;
 	struct batadv_orig_node *orig_node;
@@ -386,6 +392,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
 	entry->crc = BATADV_BLA_CRC_INIT;
 	entry->bat_priv = bat_priv;
 	atomic_set(&entry->request_sent, 0);
+	atomic_set(&entry->wait_periods, 0);
 	memcpy(entry->orig, orig, ETH_ALEN);
 
 	/* one for the hash, one for returning */
@@ -409,6 +416,16 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
 					  "became a backbone gateway");
 		batadv_orig_node_free_ref(orig_node);
 	}
+
+	if (own_backbone) {
+		batadv_bla_send_announce(bat_priv, entry);
+
+		/* this will be decreased in the worker thread */
+		atomic_inc(&entry->request_sent);
+		atomic_set(&entry->wait_periods, BATADV_BLA_WAIT_PERIODS);
+		atomic_inc(&bat_priv->bla.num_requests);
+	}
+
 	return entry;
 }
 
@@ -424,7 +441,7 @@ batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv,
 
 	backbone_gw = batadv_bla_get_backbone_gw(bat_priv,
 						 primary_if->net_dev->dev_addr,
-						 vid);
+						 vid, true);
 	if (unlikely(!backbone_gw))
 		return;
 
@@ -632,7 +649,8 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv,
 	if (memcmp(an_addr, batadv_announce_mac, 4) != 0)
 		return 0;
 
-	backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid);
+	backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid,
+						 false);
 
 	if (unlikely(!backbone_gw))
 		return 1;
@@ -730,7 +748,8 @@ static int batadv_handle_claim(struct batadv_priv *bat_priv,
 
 	/* register the gateway if not yet available, and add the claim. */
 
-	backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid);
+	backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid,
+						 false);
 
 	if (unlikely(!backbone_gw))
 		return 1;
@@ -1140,6 +1159,24 @@ static void batadv_bla_periodic_work(struct work_struct *work)
 			backbone_gw->lasttime = jiffies;
 
 			batadv_bla_send_announce(bat_priv, backbone_gw);
+
+			/* request_sent is only set after creation to avoid
+			 * problems when we are not yet known as backbone gw
+			 * in the backbone.
+			 *
+			 * We can reset this now after we waited some periods
+			 * to give bridge forward delays and bla group forming
+			 * some grace time.
+			 */
+
+			if (atomic_read(&backbone_gw->request_sent) == 0)
+				continue;
+
+			if (!atomic_dec_and_test(&backbone_gw->wait_periods))
+				continue;
+
+			atomic_dec(&backbone_gw->bat_priv->bla.num_requests);
+			atomic_set(&backbone_gw->request_sent, 0);
 		}
 		rcu_read_unlock();
 	}
@@ -1212,8 +1249,7 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
 /**
  * batadv_bla_check_bcast_duplist
  * @bat_priv: the bat priv with all the soft interface information
- * @bcast_packet: encapsulated broadcast frame plus batman header
- * @bcast_packet_len: length of encapsulated broadcast frame plus batman header
+ * @skb: contains the bcast_packet to be checked
  *
  * check if it is on our broadcast list. Another gateway might
  * have sent the same packet because it is connected to the same backbone,
@@ -1225,20 +1261,17 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
  * the same host however as this might be intended.
  */
 int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
-				   struct batadv_bcast_packet *bcast_packet,
-				   int bcast_packet_len)
+				   struct sk_buff *skb)
 {
-	int i, length, curr, ret = 0;
-	uint8_t *content;
-	uint16_t crc;
+	int i, curr, ret = 0;
+	__be32 crc;
+	struct batadv_bcast_packet *bcast_packet;
 	struct batadv_bcast_duplist_entry *entry;
 
-	length = bcast_packet_len - sizeof(*bcast_packet);
-	content = (uint8_t *)bcast_packet;
-	content += sizeof(*bcast_packet);
+	bcast_packet = (struct batadv_bcast_packet *)skb->data;
 
 	/* calculate the crc ... */
-	crc = crc16(0, content, length);
+	crc = batadv_skb_crc32(skb, (u8 *)(bcast_packet + 1));
 
 	spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);
 
@@ -1585,23 +1618,11 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
 	struct hlist_head *head;
 	uint32_t i;
 	bool is_own;
-	int ret = 0;
 	uint8_t *primary_addr;
 
-	primary_if = batadv_primary_if_get_selected(bat_priv);
-	if (!primary_if) {
-		ret = seq_printf(seq,
-				 "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
-				 net_dev->name);
-		goto out;
-	}
-
-	if (primary_if->if_status != BATADV_IF_ACTIVE) {
-		ret = seq_printf(seq,
-				 "BATMAN mesh %s disabled - primary interface not active\n",
-				 net_dev->name);
+	primary_if = batadv_seq_print_text_primary_if_get(seq);
+	if (!primary_if)
 		goto out;
-	}
 
 	primary_addr = primary_if->net_dev->dev_addr;
 	seq_printf(seq,
@@ -1628,7 +1649,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
 out:
 	if (primary_if)
 		batadv_hardif_free_ref(primary_if);
-	return ret;
+	return 0;
 }
 
 int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
@@ -1643,23 +1664,11 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
 	int secs, msecs;
 	uint32_t i;
 	bool is_own;
-	int ret = 0;
 	uint8_t *primary_addr;
 
-	primary_if = batadv_primary_if_get_selected(bat_priv);
-	if (!primary_if) {
-		ret = seq_printf(seq,
-				 "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
-				 net_dev->name);
-		goto out;
-	}
-
-	if (primary_if->if_status != BATADV_IF_ACTIVE) {
-		ret = seq_printf(seq,
-				 "BATMAN mesh %s disabled - primary interface not active\n",
-				 net_dev->name);
+	primary_if = batadv_seq_print_text_primary_if_get(seq);
+	if (!primary_if)
 		goto out;
-	}
 
 	primary_addr = primary_if->net_dev->dev_addr;
 	seq_printf(seq,
@@ -1693,5 +1702,5 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
 out:
 	if (primary_if)
 		batadv_hardif_free_ref(primary_if);
-	return ret;
+	return 0;
 }
diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h
index 789cb73..196d9a0 100644
--- a/net/batman-adv/bridge_loop_avoidance.h
+++ b/net/batman-adv/bridge_loop_avoidance.h
@@ -31,8 +31,7 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq,
 					     void *offset);
 int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig);
 int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
-				   struct batadv_bcast_packet *bcast_packet,
-				   int hdr_size);
+				   struct sk_buff *skb);
 void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
 				    struct batadv_hard_iface *primary_if,
 				    struct batadv_hard_iface *oldif);
@@ -81,8 +80,7 @@ static inline int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv,
 
 static inline int
 batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
-			       struct batadv_bcast_packet *bcast_packet,
-			       int hdr_size)
+			       struct sk_buff *skb)
 {
 	return 0;
 }
diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c
index 391d4fb..6f58ddd 100644
--- a/net/batman-adv/debugfs.c
+++ b/net/batman-adv/debugfs.c
@@ -31,6 +31,7 @@
 #include "vis.h"
 #include "icmp_socket.h"
 #include "bridge_loop_avoidance.h"
+#include "distributed-arp-table.h"
 
 static struct dentry *batadv_debugfs;
 
@@ -99,15 +100,17 @@ int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...)
 
 static int batadv_log_open(struct inode *inode, struct file *file)
 {
+	if (!try_module_get(THIS_MODULE))
+		return -EBUSY;
+
 	nonseekable_open(inode, file);
 	file->private_data = inode->i_private;
-	batadv_inc_module_count();
 	return 0;
 }
 
 static int batadv_log_release(struct inode *inode, struct file *file)
 {
-	batadv_dec_module_count();
+	module_put(THIS_MODULE);
 	return 0;
 }
 
@@ -278,6 +281,19 @@ static int batadv_bla_backbone_table_open(struct inode *inode,
 
 #endif
 
+#ifdef CONFIG_BATMAN_ADV_DAT
+/**
+ * batadv_dat_cache_open - Prepare file handler for reads from dat_chache
+ * @inode: inode which was opened
+ * @file: file handle to be initialized
+ */
+static int batadv_dat_cache_open(struct inode *inode, struct file *file)
+{
+	struct net_device *net_dev = (struct net_device *)inode->i_private;
+	return single_open(file, batadv_dat_cache_seq_print_text, net_dev);
+}
+#endif
+
 static int batadv_transtable_local_open(struct inode *inode, struct file *file)
 {
 	struct net_device *net_dev = (struct net_device *)inode->i_private;
@@ -307,7 +323,17 @@ struct batadv_debuginfo batadv_debuginfo_##_name = {	\
 		}					\
 };
 
+/* the following attributes are general and therefore they will be directly
+ * placed in the BATADV_DEBUGFS_SUBDIR subdirectory of debugfs
+ */
 static BATADV_DEBUGINFO(routing_algos, S_IRUGO, batadv_algorithms_open);
+
+static struct batadv_debuginfo *batadv_general_debuginfos[] = {
+	&batadv_debuginfo_routing_algos,
+	NULL,
+};
+
+/* The following attributes are per soft interface */
 static BATADV_DEBUGINFO(originators, S_IRUGO, batadv_originators_open);
 static BATADV_DEBUGINFO(gateways, S_IRUGO, batadv_gateways_open);
 static BATADV_DEBUGINFO(transtable_global, S_IRUGO,
@@ -317,6 +343,9 @@ static BATADV_DEBUGINFO(bla_claim_table, S_IRUGO, batadv_bla_claim_table_open);
 static BATADV_DEBUGINFO(bla_backbone_table, S_IRUGO,
 			batadv_bla_backbone_table_open);
 #endif
+#ifdef CONFIG_BATMAN_ADV_DAT
+static BATADV_DEBUGINFO(dat_cache, S_IRUGO, batadv_dat_cache_open);
+#endif
 static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
 			batadv_transtable_local_open);
 static BATADV_DEBUGINFO(vis_data, S_IRUGO, batadv_vis_data_open);
@@ -329,6 +358,9 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
 	&batadv_debuginfo_bla_claim_table,
 	&batadv_debuginfo_bla_backbone_table,
 #endif
+#ifdef CONFIG_BATMAN_ADV_DAT
+	&batadv_debuginfo_dat_cache,
+#endif
 	&batadv_debuginfo_transtable_local,
 	&batadv_debuginfo_vis_data,
 	NULL,
@@ -336,7 +368,7 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
 
 void batadv_debugfs_init(void)
 {
-	struct batadv_debuginfo *bat_debug;
+	struct batadv_debuginfo **bat_debug;
 	struct dentry *file;
 
 	batadv_debugfs = debugfs_create_dir(BATADV_DEBUGFS_SUBDIR, NULL);
@@ -344,17 +376,23 @@ void batadv_debugfs_init(void)
 		batadv_debugfs = NULL;
 
 	if (!batadv_debugfs)
-		goto out;
+		goto err;
 
-	bat_debug = &batadv_debuginfo_routing_algos;
-	file = debugfs_create_file(bat_debug->attr.name,
-				   S_IFREG | bat_debug->attr.mode,
-				   batadv_debugfs, NULL, &bat_debug->fops);
-	if (!file)
-		pr_err("Can't add debugfs file: %s\n", bat_debug->attr.name);
+	for (bat_debug = batadv_general_debuginfos; *bat_debug; ++bat_debug) {
+		file = debugfs_create_file(((*bat_debug)->attr).name,
+					   S_IFREG | ((*bat_debug)->attr).mode,
+					   batadv_debugfs, NULL,
+					   &(*bat_debug)->fops);
+		if (!file) {
+			pr_err("Can't add general debugfs file: %s\n",
+			       ((*bat_debug)->attr).name);
+			goto err;
+		}
+	}
 
-out:
 	return;
+err:
+	debugfs_remove_recursive(batadv_debugfs);
 }
 
 void batadv_debugfs_destroy(void)
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
new file mode 100644
index 0000000..8e1d89d
--- /dev/null
+++ b/net/batman-adv/distributed-arp-table.c
@@ -0,0 +1,1066 @@
+/* Copyright (C) 2011-2012 B.A.T.M.A.N. contributors:
+ *
+ * Antonio Quartulli
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
+
+#include "main.h"
+#include "hash.h"
+#include "distributed-arp-table.h"
+#include "hard-interface.h"
+#include "originator.h"
+#include "send.h"
+#include "types.h"
+#include "translation-table.h"
+#include "unicast.h"
+
+static void batadv_dat_purge(struct work_struct *work);
+
+/**
+ * batadv_dat_start_timer - initialise the DAT periodic worker
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+static void batadv_dat_start_timer(struct batadv_priv *bat_priv)
+{
+	INIT_DELAYED_WORK(&bat_priv->dat.work, batadv_dat_purge);
+	queue_delayed_work(batadv_event_workqueue, &bat_priv->dat.work,
+			   msecs_to_jiffies(10000));
+}
+
+/**
+ * batadv_dat_entry_free_ref - decrements the dat_entry refcounter and possibly
+ * free it
+ * @dat_entry: the oentry to free
+ */
+static void batadv_dat_entry_free_ref(struct batadv_dat_entry *dat_entry)
+{
+	if (atomic_dec_and_test(&dat_entry->refcount))
+		kfree_rcu(dat_entry, rcu);
+}
+
+/**
+ * batadv_dat_to_purge - checks whether a dat_entry has to be purged or not
+ * @dat_entry: the entry to check
+ *
+ * Returns true if the entry has to be purged now, false otherwise
+ */
+static bool batadv_dat_to_purge(struct batadv_dat_entry *dat_entry)
+{
+	return batadv_has_timed_out(dat_entry->last_update,
+				    BATADV_DAT_ENTRY_TIMEOUT);
+}
+
+/**
+ * __batadv_dat_purge - delete entries from the DAT local storage
+ * @bat_priv: the bat priv with all the soft interface information
+ * @to_purge: function in charge to decide whether an entry has to be purged or
+ *	      not. This function takes the dat_entry as argument and has to
+ *	      returns a boolean value: true is the entry has to be deleted,
+ *	      false otherwise
+ *
+ * Loops over each entry in the DAT local storage and delete it if and only if
+ * the to_purge function passed as argument returns true
+ */
+static void __batadv_dat_purge(struct batadv_priv *bat_priv,
+			       bool (*to_purge)(struct batadv_dat_entry *))
+{
+	spinlock_t *list_lock; /* protects write access to the hash lists */
+	struct batadv_dat_entry *dat_entry;
+	struct hlist_node *node, *node_tmp;
+	struct hlist_head *head;
+	uint32_t i;
+
+	if (!bat_priv->dat.hash)
+		return;
+
+	for (i = 0; i < bat_priv->dat.hash->size; i++) {
+		head = &bat_priv->dat.hash->table[i];
+		list_lock = &bat_priv->dat.hash->list_locks[i];
+
+		spin_lock_bh(list_lock);
+		hlist_for_each_entry_safe(dat_entry, node, node_tmp, head,
+					  hash_entry) {
+			/* if an helper function has been passed as parameter,
+			 * ask it if the entry has to be purged or not
+			 */
+			if (to_purge && !to_purge(dat_entry))
+				continue;
+
+			hlist_del_rcu(node);
+			batadv_dat_entry_free_ref(dat_entry);
+		}
+		spin_unlock_bh(list_lock);
+	}
+}
+
+/**
+ * batadv_dat_purge - periodic task that deletes old entries from the local DAT
+ * hash table
+ * @work: kernel work struct
+ */
+static void batadv_dat_purge(struct work_struct *work)
+{
+	struct delayed_work *delayed_work;
+	struct batadv_priv_dat *priv_dat;
+	struct batadv_priv *bat_priv;
+
+	delayed_work = container_of(work, struct delayed_work, work);
+	priv_dat = container_of(delayed_work, struct batadv_priv_dat, work);
+	bat_priv = container_of(priv_dat, struct batadv_priv, dat);
+
+	__batadv_dat_purge(bat_priv, batadv_dat_to_purge);
+	batadv_dat_start_timer(bat_priv);
+}
+
+/**
+ * batadv_compare_dat - comparing function used in the local DAT hash table
+ * @node: node in the local table
+ * @data2: second object to compare the node to
+ *
+ * Returns 1 if the two entry are the same, 0 otherwise
+ */
+static int batadv_compare_dat(const struct hlist_node *node, const void *data2)
+{
+	const void *data1 = container_of(node, struct batadv_dat_entry,
+					 hash_entry);
+
+	return (memcmp(data1, data2, sizeof(__be32)) == 0 ? 1 : 0);
+}
+
+/**
+ * batadv_arp_hw_src - extract the hw_src field from an ARP packet
+ * @skb: ARP packet
+ * @hdr_size: size of the possible header before the ARP packet
+ *
+ * Returns the value of the hw_src field in the ARP packet
+ */
+static uint8_t *batadv_arp_hw_src(struct sk_buff *skb, int hdr_size)
+{
+	uint8_t *addr;
+
+	addr = (uint8_t *)(skb->data + hdr_size);
+	addr += ETH_HLEN + sizeof(struct arphdr);
+
+	return addr;
+}
+
+/**
+ * batadv_arp_ip_src - extract the ip_src field from an ARP packet
+ * @skb: ARP packet
+ * @hdr_size: size of the possible header before the ARP packet
+ *
+ * Returns the value of the ip_src field in the ARP packet
+ */
+static __be32 batadv_arp_ip_src(struct sk_buff *skb, int hdr_size)
+{
+	return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN);
+}
+
+/**
+ * batadv_arp_hw_dst - extract the hw_dst field from an ARP packet
+ * @skb: ARP packet
+ * @hdr_size: size of the possible header before the ARP packet
+ *
+ * Returns the value of the hw_dst field in the ARP packet
+ */
+static uint8_t *batadv_arp_hw_dst(struct sk_buff *skb, int hdr_size)
+{
+	return batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN + 4;
+}
+
+/**
+ * batadv_arp_ip_dst - extract the ip_dst field from an ARP packet
+ * @skb: ARP packet
+ * @hdr_size: size of the possible header before the ARP packet
+ *
+ * Returns the value of the ip_dst field in the ARP packet
+ */
+static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size)
+{
+	return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN * 2 + 4);
+}
+
+/**
+ * batadv_hash_dat - compute the hash value for an IP address
+ * @data: data to hash
+ * @size: size of the hash table
+ *
+ * Returns the selected index in the hash table for the given data
+ */
+static uint32_t batadv_hash_dat(const void *data, uint32_t size)
+{
+	const unsigned char *key = data;
+	uint32_t hash = 0;
+	size_t i;
+
+	for (i = 0; i < 4; i++) {
+		hash += key[i];
+		hash += (hash << 10);
+		hash ^= (hash >> 6);
+	}
+
+	hash += (hash << 3);
+	hash ^= (hash >> 11);
+	hash += (hash << 15);
+
+	return hash % size;
+}
+
+/**
+ * batadv_dat_entry_hash_find - looks for a given dat_entry in the local hash
+ * table
+ * @bat_priv: the bat priv with all the soft interface information
+ * @ip: search key
+ *
+ * Returns the dat_entry if found, NULL otherwise
+ */
+static struct batadv_dat_entry *
+batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip)
+{
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct batadv_dat_entry *dat_entry, *dat_entry_tmp = NULL;
+	struct batadv_hashtable *hash = bat_priv->dat.hash;
+	uint32_t index;
+
+	if (!hash)
+		return NULL;
+
+	index = batadv_hash_dat(&ip, hash->size);
+	head = &hash->table[index];
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(dat_entry, node, head, hash_entry) {
+		if (dat_entry->ip != ip)
+			continue;
+
+		if (!atomic_inc_not_zero(&dat_entry->refcount))
+			continue;
+
+		dat_entry_tmp = dat_entry;
+		break;
+	}
+	rcu_read_unlock();
+
+	return dat_entry_tmp;
+}
+
+/**
+ * batadv_dat_entry_add - add a new dat entry or update it if already exists
+ * @bat_priv: the bat priv with all the soft interface information
+ * @ip: ipv4 to add/edit
+ * @mac_addr: mac address to assign to the given ipv4
+ */
+static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
+				 uint8_t *mac_addr)
+{
+	struct batadv_dat_entry *dat_entry;
+	int hash_added;
+
+	dat_entry = batadv_dat_entry_hash_find(bat_priv, ip);
+	/* if this entry is already known, just update it */
+	if (dat_entry) {
+		if (!batadv_compare_eth(dat_entry->mac_addr, mac_addr))
+			memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN);
+		dat_entry->last_update = jiffies;
+		batadv_dbg(BATADV_DBG_DAT, bat_priv,
+			   "Entry updated: %pI4 %pM\n", &dat_entry->ip,
+			   dat_entry->mac_addr);
+		goto out;
+	}
+
+	dat_entry = kmalloc(sizeof(*dat_entry), GFP_ATOMIC);
+	if (!dat_entry)
+		goto out;
+
+	dat_entry->ip = ip;
+	memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN);
+	dat_entry->last_update = jiffies;
+	atomic_set(&dat_entry->refcount, 2);
+
+	hash_added = batadv_hash_add(bat_priv->dat.hash, batadv_compare_dat,
+				     batadv_hash_dat, &dat_entry->ip,
+				     &dat_entry->hash_entry);
+
+	if (unlikely(hash_added != 0)) {
+		/* remove the reference for the hash */
+		batadv_dat_entry_free_ref(dat_entry);
+		goto out;
+	}
+
+	batadv_dbg(BATADV_DBG_DAT, bat_priv, "New entry added: %pI4 %pM\n",
+		   &dat_entry->ip, dat_entry->mac_addr);
+
+out:
+	if (dat_entry)
+		batadv_dat_entry_free_ref(dat_entry);
+}
+
+#ifdef CONFIG_BATMAN_ADV_DEBUG
+
+/**
+ * batadv_dbg_arp - print a debug message containing all the ARP packet details
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: ARP packet
+ * @type: ARP type
+ * @hdr_size: size of the possible header before the ARP packet
+ * @msg: message to print together with the debugging information
+ */
+static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
+			   uint16_t type, int hdr_size, char *msg)
+{
+	struct batadv_unicast_4addr_packet *unicast_4addr_packet;
+	struct batadv_bcast_packet *bcast_pkt;
+	uint8_t *orig_addr;
+	__be32 ip_src, ip_dst;
+
+	if (msg)
+		batadv_dbg(BATADV_DBG_DAT, bat_priv, "%s\n", msg);
+
+	ip_src = batadv_arp_ip_src(skb, hdr_size);
+	ip_dst = batadv_arp_ip_dst(skb, hdr_size);
+	batadv_dbg(BATADV_DBG_DAT, bat_priv,
+		   "ARP MSG = [src: %pM-%pI4 dst: %pM-%pI4]\n",
+		   batadv_arp_hw_src(skb, hdr_size), &ip_src,
+		   batadv_arp_hw_dst(skb, hdr_size), &ip_dst);
+
+	if (hdr_size == 0)
+		return;
+
+	/* if the ARP packet is encapsulated in a batman packet, let's print
+	 * some debug messages
+	 */
+	unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
+
+	switch (unicast_4addr_packet->u.header.packet_type) {
+	case BATADV_UNICAST:
+		batadv_dbg(BATADV_DBG_DAT, bat_priv,
+			   "* encapsulated within a UNICAST packet\n");
+		break;
+	case BATADV_UNICAST_4ADDR:
+		batadv_dbg(BATADV_DBG_DAT, bat_priv,
+			   "* encapsulated within a UNICAST_4ADDR packet (src: %pM)\n",
+			   unicast_4addr_packet->src);
+		switch (unicast_4addr_packet->subtype) {
+		case BATADV_P_DAT_DHT_PUT:
+			batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DAT_DHT_PUT\n");
+			break;
+		case BATADV_P_DAT_DHT_GET:
+			batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DAT_DHT_GET\n");
+			break;
+		case BATADV_P_DAT_CACHE_REPLY:
+			batadv_dbg(BATADV_DBG_DAT, bat_priv,
+				   "* type: DAT_CACHE_REPLY\n");
+			break;
+		case BATADV_P_DATA:
+			batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DATA\n");
+			break;
+		default:
+			batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: Unknown (%u)!\n",
+				   unicast_4addr_packet->u.header.packet_type);
+		}
+		break;
+	case BATADV_BCAST:
+		bcast_pkt = (struct batadv_bcast_packet *)unicast_4addr_packet;
+		orig_addr = bcast_pkt->orig;
+		batadv_dbg(BATADV_DBG_DAT, bat_priv,
+			   "* encapsulated within a BCAST packet (src: %pM)\n",
+			   orig_addr);
+		break;
+	default:
+		batadv_dbg(BATADV_DBG_DAT, bat_priv,
+			   "* encapsulated within an unknown packet type (0x%x)\n",
+			   unicast_4addr_packet->u.header.packet_type);
+	}
+}
+
+#else
+
+static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
+			   uint16_t type, int hdr_size, char *msg)
+{
+}
+
+#endif /* CONFIG_BATMAN_ADV_DEBUG */
+
+/**
+ * batadv_is_orig_node_eligible - check whether a node can be a DHT candidate
+ * @res: the array with the already selected candidates
+ * @select: number of already selected candidates
+ * @tmp_max: address of the currently evaluated node
+ * @max: current round max address
+ * @last_max: address of the last selected candidate
+ * @candidate: orig_node under evaluation
+ * @max_orig_node: last selected candidate
+ *
+ * Returns true if the node has been elected as next candidate or false othrwise
+ */
+static bool batadv_is_orig_node_eligible(struct batadv_dat_candidate *res,
+					 int select, batadv_dat_addr_t tmp_max,
+					 batadv_dat_addr_t max,
+					 batadv_dat_addr_t last_max,
+					 struct batadv_orig_node *candidate,
+					 struct batadv_orig_node *max_orig_node)
+{
+	bool ret = false;
+	int j;
+
+	/* Check if this node has already been selected... */
+	for (j = 0; j < select; j++)
+		if (res[j].orig_node == candidate)
+			break;
+	/* ..and possibly skip it */
+	if (j < select)
+		goto out;
+	/* sanity check: has it already been selected? This should not happen */
+	if (tmp_max > last_max)
+		goto out;
+	/* check if during this iteration an originator with a closer dht
+	 * address has already been found
+	 */
+	if (tmp_max < max)
+		goto out;
+	/* this is an hash collision with the temporary selected node. Choose
+	 * the one with the lowest address
+	 */
+	if ((tmp_max == max) &&
+	    (batadv_compare_eth(candidate->orig, max_orig_node->orig) > 0))
+		goto out;
+
+	ret = true;
+out:
+	return ret;
+}
+
+/**
+ * batadv_choose_next_candidate - select the next DHT candidate
+ * @bat_priv: the bat priv with all the soft interface information
+ * @cands: candidates array
+ * @select: number of candidates already present in the array
+ * @ip_key: key to look up in the DHT
+ * @last_max: pointer where the address of the selected candidate will be saved
+ */
+static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
+					 struct batadv_dat_candidate *cands,
+					 int select, batadv_dat_addr_t ip_key,
+					 batadv_dat_addr_t *last_max)
+{
+	batadv_dat_addr_t max = 0, tmp_max = 0;
+	struct batadv_orig_node *orig_node, *max_orig_node = NULL;
+	struct batadv_hashtable *hash = bat_priv->orig_hash;
+	struct hlist_node *node;
+	struct hlist_head *head;
+	int i;
+
+	/* if no node is eligible as candidate, leave the candidate type as
+	 * NOT_FOUND
+	 */
+	cands[select].type = BATADV_DAT_CANDIDATE_NOT_FOUND;
+
+	/* iterate over the originator list and find the node with closest
+	 * dat_address which has not been selected yet
+	 */
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
+			/* the dht space is a ring and addresses are unsigned */
+			tmp_max = BATADV_DAT_ADDR_MAX - orig_node->dat_addr +
+				  ip_key;
+
+			if (!batadv_is_orig_node_eligible(cands, select,
+							  tmp_max, max,
+							  *last_max, orig_node,
+							  max_orig_node))
+				continue;
+
+			if (!atomic_inc_not_zero(&orig_node->refcount))
+				continue;
+
+			max = tmp_max;
+			if (max_orig_node)
+				batadv_orig_node_free_ref(max_orig_node);
+			max_orig_node = orig_node;
+		}
+		rcu_read_unlock();
+	}
+	if (max_orig_node) {
+		cands[select].type = BATADV_DAT_CANDIDATE_ORIG;
+		cands[select].orig_node = max_orig_node;
+		batadv_dbg(BATADV_DBG_DAT, bat_priv,
+			   "dat_select_candidates() %d: selected %pM addr=%u dist=%u\n",
+			   select, max_orig_node->orig, max_orig_node->dat_addr,
+			   max);
+	}
+	*last_max = max;
+}
+
+/**
+ * batadv_dat_select_candidates - selects the nodes which the DHT message has to
+ * be sent to
+ * @bat_priv: the bat priv with all the soft interface information
+ * @ip_dst: ipv4 to look up in the DHT
+ *
+ * An originator O is selected if and only if its DHT_ID value is one of three
+ * closest values (from the LEFT, with wrap around if needed) then the hash
+ * value of the key. ip_dst is the key.
+ *
+ * Returns the candidate array of size BATADV_DAT_CANDIDATE_NUM
+ */
+static struct batadv_dat_candidate *
+batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
+{
+	int select;
+	batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key;
+	struct batadv_dat_candidate *res;
+
+	if (!bat_priv->orig_hash)
+		return NULL;
+
+	res = kmalloc(BATADV_DAT_CANDIDATES_NUM * sizeof(*res), GFP_ATOMIC);
+	if (!res)
+		return NULL;
+
+	ip_key = (batadv_dat_addr_t)batadv_hash_dat(&ip_dst,
+						    BATADV_DAT_ADDR_MAX);
+
+	batadv_dbg(BATADV_DBG_DAT, bat_priv,
+		   "dat_select_candidates(): IP=%pI4 hash(IP)=%u\n", &ip_dst,
+		   ip_key);
+
+	for (select = 0; select < BATADV_DAT_CANDIDATES_NUM; select++)
+		batadv_choose_next_candidate(bat_priv, res, select, ip_key,
+					     &last_max);
+
+	return res;
+}
+
+/**
+ * batadv_dat_send_data - send a payload to the selected candidates
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: payload to send
+ * @ip: the DHT key
+ * @packet_subtype: unicast4addr packet subtype to use
+ *
+ * In this function the skb is copied by means of pskb_copy() and is sent as
+ * unicast packet to each of the selected candidates
+ *
+ * Returns true if the packet is sent to at least one candidate, false otherwise
+ */
+static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
+				 struct sk_buff *skb, __be32 ip,
+				 int packet_subtype)
+{
+	int i;
+	bool ret = false;
+	int send_status;
+	struct batadv_neigh_node *neigh_node = NULL;
+	struct sk_buff *tmp_skb;
+	struct batadv_dat_candidate *cand;
+
+	cand = batadv_dat_select_candidates(bat_priv, ip);
+	if (!cand)
+		goto out;
+
+	batadv_dbg(BATADV_DBG_DAT, bat_priv, "DHT_SEND for %pI4\n", &ip);
+
+	for (i = 0; i < BATADV_DAT_CANDIDATES_NUM; i++) {
+		if (cand[i].type == BATADV_DAT_CANDIDATE_NOT_FOUND)
+			continue;
+
+		neigh_node = batadv_orig_node_get_router(cand[i].orig_node);
+		if (!neigh_node)
+			goto free_orig;
+
+		tmp_skb = pskb_copy(skb, GFP_ATOMIC);
+		if (!batadv_unicast_4addr_prepare_skb(bat_priv, tmp_skb,
+						      cand[i].orig_node,
+						      packet_subtype)) {
+			kfree_skb(tmp_skb);
+			goto free_neigh;
+		}
+
+		send_status = batadv_send_skb_packet(tmp_skb,
+						     neigh_node->if_incoming,
+						     neigh_node->addr);
+		if (send_status == NET_XMIT_SUCCESS) {
+			/* count the sent packet */
+			switch (packet_subtype) {
+			case BATADV_P_DAT_DHT_GET:
+				batadv_inc_counter(bat_priv,
+						   BATADV_CNT_DAT_GET_TX);
+				break;
+			case BATADV_P_DAT_DHT_PUT:
+				batadv_inc_counter(bat_priv,
+						   BATADV_CNT_DAT_PUT_TX);
+				break;
+			}
+
+			/* packet sent to a candidate: return true */
+			ret = true;
+		}
+free_neigh:
+		batadv_neigh_node_free_ref(neigh_node);
+free_orig:
+		batadv_orig_node_free_ref(cand[i].orig_node);
+	}
+
+out:
+	kfree(cand);
+	return ret;
+}
+
+/**
+ * batadv_dat_hash_free - free the local DAT hash table
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+static void batadv_dat_hash_free(struct batadv_priv *bat_priv)
+{
+	if (!bat_priv->dat.hash)
+		return;
+
+	__batadv_dat_purge(bat_priv, NULL);
+
+	batadv_hash_destroy(bat_priv->dat.hash);
+
+	bat_priv->dat.hash = NULL;
+}
+
+/**
+ * batadv_dat_init - initialise the DAT internals
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+int batadv_dat_init(struct batadv_priv *bat_priv)
+{
+	if (bat_priv->dat.hash)
+		return 0;
+
+	bat_priv->dat.hash = batadv_hash_new(1024);
+
+	if (!bat_priv->dat.hash)
+		return -ENOMEM;
+
+	batadv_dat_start_timer(bat_priv);
+
+	return 0;
+}
+
+/**
+ * batadv_dat_free - free the DAT internals
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+void batadv_dat_free(struct batadv_priv *bat_priv)
+{
+	cancel_delayed_work_sync(&bat_priv->dat.work);
+
+	batadv_dat_hash_free(bat_priv);
+}
+
+/**
+ * batadv_dat_cache_seq_print_text - print the local DAT hash table
+ * @seq: seq file to print on
+ * @offset: not used
+ */
+int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
+{
+	struct net_device *net_dev = (struct net_device *)seq->private;
+	struct batadv_priv *bat_priv = netdev_priv(net_dev);
+	struct batadv_hashtable *hash = bat_priv->dat.hash;
+	struct batadv_dat_entry *dat_entry;
+	struct batadv_hard_iface *primary_if;
+	struct hlist_node *node;
+	struct hlist_head *head;
+	unsigned long last_seen_jiffies;
+	int last_seen_msecs, last_seen_secs, last_seen_mins;
+	uint32_t i;
+
+	primary_if = batadv_seq_print_text_primary_if_get(seq);
+	if (!primary_if)
+		goto out;
+
+	seq_printf(seq, "Distributed ARP Table (%s):\n", net_dev->name);
+	seq_printf(seq, "          %-7s          %-13s %5s\n", "IPv4", "MAC",
+		   "last-seen");
+
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(dat_entry, node, head, hash_entry) {
+			last_seen_jiffies = jiffies - dat_entry->last_update;
+			last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
+			last_seen_mins = last_seen_msecs / 60000;
+			last_seen_msecs = last_seen_msecs % 60000;
+			last_seen_secs = last_seen_msecs / 1000;
+
+			seq_printf(seq, " * %15pI4 %14pM %6i:%02i\n",
+				   &dat_entry->ip, dat_entry->mac_addr,
+				   last_seen_mins, last_seen_secs);
+		}
+		rcu_read_unlock();
+	}
+
+out:
+	if (primary_if)
+		batadv_hardif_free_ref(primary_if);
+	return 0;
+}
+
+/**
+ * batadv_arp_get_type - parse an ARP packet and gets the type
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: packet to analyse
+ * @hdr_size: size of the possible header before the ARP packet in the skb
+ *
+ * Returns the ARP type if the skb contains a valid ARP packet, 0 otherwise
+ */
+static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv,
+				    struct sk_buff *skb, int hdr_size)
+{
+	struct arphdr *arphdr;
+	struct ethhdr *ethhdr;
+	__be32 ip_src, ip_dst;
+	uint16_t type = 0;
+
+	/* pull the ethernet header */
+	if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN)))
+		goto out;
+
+	ethhdr = (struct ethhdr *)(skb->data + hdr_size);
+
+	if (ethhdr->h_proto != htons(ETH_P_ARP))
+		goto out;
+
+	/* pull the ARP payload */
+	if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN +
+				    arp_hdr_len(skb->dev))))
+		goto out;
+
+	arphdr = (struct arphdr *)(skb->data + hdr_size + ETH_HLEN);
+
+	/* Check whether the ARP packet carries a valid
+	 * IP information
+	 */
+	if (arphdr->ar_hrd != htons(ARPHRD_ETHER))
+		goto out;
+
+	if (arphdr->ar_pro != htons(ETH_P_IP))
+		goto out;
+
+	if (arphdr->ar_hln != ETH_ALEN)
+		goto out;
+
+	if (arphdr->ar_pln != 4)
+		goto out;
+
+	/* Check for bad reply/request. If the ARP message is not sane, DAT
+	 * will simply ignore it
+	 */
+	ip_src = batadv_arp_ip_src(skb, hdr_size);
+	ip_dst = batadv_arp_ip_dst(skb, hdr_size);
+	if (ipv4_is_loopback(ip_src) || ipv4_is_multicast(ip_src) ||
+	    ipv4_is_loopback(ip_dst) || ipv4_is_multicast(ip_dst))
+		goto out;
+
+	type = ntohs(arphdr->ar_op);
+out:
+	return type;
+}
+
+/**
+ * batadv_dat_snoop_outgoing_arp_request - snoop the ARP request and try to
+ * answer using DAT
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: packet to check
+ *
+ * Returns true if the message has been sent to the dht candidates, false
+ * otherwise. In case of true the message has to be enqueued to permit the
+ * fallback
+ */
+bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
+					   struct sk_buff *skb)
+{
+	uint16_t type = 0;
+	__be32 ip_dst, ip_src;
+	uint8_t *hw_src;
+	bool ret = false;
+	struct batadv_dat_entry *dat_entry = NULL;
+	struct sk_buff *skb_new;
+	struct batadv_hard_iface *primary_if = NULL;
+
+	if (!atomic_read(&bat_priv->distributed_arp_table))
+		goto out;
+
+	type = batadv_arp_get_type(bat_priv, skb, 0);
+	/* If the node gets an ARP_REQUEST it has to send a DHT_GET unicast
+	 * message to the selected DHT candidates
+	 */
+	if (type != ARPOP_REQUEST)
+		goto out;
+
+	batadv_dbg_arp(bat_priv, skb, type, 0, "Parsing outgoing ARP REQUEST");
+
+	ip_src = batadv_arp_ip_src(skb, 0);
+	hw_src = batadv_arp_hw_src(skb, 0);
+	ip_dst = batadv_arp_ip_dst(skb, 0);
+
+	batadv_dat_entry_add(bat_priv, ip_src, hw_src);
+
+	dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
+	if (dat_entry) {
+		primary_if = batadv_primary_if_get_selected(bat_priv);
+		if (!primary_if)
+			goto out;
+
+		skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
+				     primary_if->soft_iface, ip_dst, hw_src,
+				     dat_entry->mac_addr, hw_src);
+		if (!skb_new)
+			goto out;
+
+		skb_reset_mac_header(skb_new);
+		skb_new->protocol = eth_type_trans(skb_new,
+						   primary_if->soft_iface);
+		bat_priv->stats.rx_packets++;
+		bat_priv->stats.rx_bytes += skb->len + ETH_HLEN;
+		primary_if->soft_iface->last_rx = jiffies;
+
+		netif_rx(skb_new);
+		batadv_dbg(BATADV_DBG_DAT, bat_priv, "ARP request replied locally\n");
+		ret = true;
+	} else {
+		/* Send the request on the DHT */
+		ret = batadv_dat_send_data(bat_priv, skb, ip_dst,
+					   BATADV_P_DAT_DHT_GET);
+	}
+out:
+	if (dat_entry)
+		batadv_dat_entry_free_ref(dat_entry);
+	if (primary_if)
+		batadv_hardif_free_ref(primary_if);
+	return ret;
+}
+
+/**
+ * batadv_dat_snoop_incoming_arp_request - snoop the ARP request and try to
+ * answer using the local DAT storage
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: packet to check
+ * @hdr_size: size of the encapsulation header
+ *
+ * Returns true if the request has been answered, false otherwise
+ */
+bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
+					   struct sk_buff *skb, int hdr_size)
+{
+	uint16_t type;
+	__be32 ip_src, ip_dst;
+	uint8_t *hw_src;
+	struct sk_buff *skb_new;
+	struct batadv_hard_iface *primary_if = NULL;
+	struct batadv_dat_entry *dat_entry = NULL;
+	bool ret = false;
+	int err;
+
+	if (!atomic_read(&bat_priv->distributed_arp_table))
+		goto out;
+
+	type = batadv_arp_get_type(bat_priv, skb, hdr_size);
+	if (type != ARPOP_REQUEST)
+		goto out;
+
+	hw_src = batadv_arp_hw_src(skb, hdr_size);
+	ip_src = batadv_arp_ip_src(skb, hdr_size);
+	ip_dst = batadv_arp_ip_dst(skb, hdr_size);
+
+	batadv_dbg_arp(bat_priv, skb, type, hdr_size,
+		       "Parsing incoming ARP REQUEST");
+
+	batadv_dat_entry_add(bat_priv, ip_src, hw_src);
+
+	dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
+	if (!dat_entry)
+		goto out;
+
+	primary_if = batadv_primary_if_get_selected(bat_priv);
+	if (!primary_if)
+		goto out;
+
+	skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
+			     primary_if->soft_iface, ip_dst, hw_src,
+			     dat_entry->mac_addr, hw_src);
+
+	if (!skb_new)
+		goto out;
+
+	/* to preserve backwards compatibility, here the node has to answer
+	 * using the same packet type it received for the request. This is due
+	 * to that if a node is not using the 4addr packet format it may not
+	 * support it.
+	 */
+	if (hdr_size == sizeof(struct batadv_unicast_4addr_packet))
+		err = batadv_unicast_4addr_send_skb(bat_priv, skb_new,
+						    BATADV_P_DAT_CACHE_REPLY);
+	else
+		err = batadv_unicast_send_skb(bat_priv, skb_new);
+
+	if (!err) {
+		batadv_inc_counter(bat_priv, BATADV_CNT_DAT_CACHED_REPLY_TX);
+		ret = true;
+	}
+out:
+	if (dat_entry)
+		batadv_dat_entry_free_ref(dat_entry);
+	if (primary_if)
+		batadv_hardif_free_ref(primary_if);
+	if (ret)
+		kfree_skb(skb);
+	return ret;
+}
+
+/**
+ * batadv_dat_snoop_outgoing_arp_reply - snoop the ARP reply and fill the DHT
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: packet to check
+ */
+void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
+					 struct sk_buff *skb)
+{
+	uint16_t type;
+	__be32 ip_src, ip_dst;
+	uint8_t *hw_src, *hw_dst;
+
+	if (!atomic_read(&bat_priv->distributed_arp_table))
+		return;
+
+	type = batadv_arp_get_type(bat_priv, skb, 0);
+	if (type != ARPOP_REPLY)
+		return;
+
+	batadv_dbg_arp(bat_priv, skb, type, 0, "Parsing outgoing ARP REPLY");
+
+	hw_src = batadv_arp_hw_src(skb, 0);
+	ip_src = batadv_arp_ip_src(skb, 0);
+	hw_dst = batadv_arp_hw_dst(skb, 0);
+	ip_dst = batadv_arp_ip_dst(skb, 0);
+
+	batadv_dat_entry_add(bat_priv, ip_src, hw_src);
+	batadv_dat_entry_add(bat_priv, ip_dst, hw_dst);
+
+	/* Send the ARP reply to the candidates for both the IP addresses that
+	 * the node got within the ARP reply
+	 */
+	batadv_dat_send_data(bat_priv, skb, ip_src, BATADV_P_DAT_DHT_PUT);
+	batadv_dat_send_data(bat_priv, skb, ip_dst, BATADV_P_DAT_DHT_PUT);
+}
+/**
+ * batadv_dat_snoop_incoming_arp_reply - snoop the ARP reply and fill the local
+ * DAT storage only
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: packet to check
+ * @hdr_size: siaze of the encapsulation header
+ */
+bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
+					 struct sk_buff *skb, int hdr_size)
+{
+	uint16_t type;
+	__be32 ip_src, ip_dst;
+	uint8_t *hw_src, *hw_dst;
+	bool ret = false;
+
+	if (!atomic_read(&bat_priv->distributed_arp_table))
+		goto out;
+
+	type = batadv_arp_get_type(bat_priv, skb, hdr_size);
+	if (type != ARPOP_REPLY)
+		goto out;
+
+	batadv_dbg_arp(bat_priv, skb, type, hdr_size,
+		       "Parsing incoming ARP REPLY");
+
+	hw_src = batadv_arp_hw_src(skb, hdr_size);
+	ip_src = batadv_arp_ip_src(skb, hdr_size);
+	hw_dst = batadv_arp_hw_dst(skb, hdr_size);
+	ip_dst = batadv_arp_ip_dst(skb, hdr_size);
+
+	/* Update our internal cache with both the IP addresses the node got
+	 * within the ARP reply
+	 */
+	batadv_dat_entry_add(bat_priv, ip_src, hw_src);
+	batadv_dat_entry_add(bat_priv, ip_dst, hw_dst);
+
+	/* if this REPLY is directed to a client of mine, let's deliver the
+	 * packet to the interface
+	 */
+	ret = !batadv_is_my_client(bat_priv, hw_dst);
+out:
+	/* if ret == false -> packet has to be delivered to the interface */
+	return ret;
+}
+
+/**
+ * batadv_dat_drop_broadcast_packet - check if an ARP request has to be dropped
+ * (because the node has already got the reply via DAT) or not
+ * @bat_priv: the bat priv with all the soft interface information
+ * @forw_packet: the broadcast packet
+ *
+ * Returns true if the node can drop the packet, false otherwise
+ */
+bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
+				      struct batadv_forw_packet *forw_packet)
+{
+	uint16_t type;
+	__be32 ip_dst;
+	struct batadv_dat_entry *dat_entry = NULL;
+	bool ret = false;
+	const size_t bcast_len = sizeof(struct batadv_bcast_packet);
+
+	if (!atomic_read(&bat_priv->distributed_arp_table))
+		goto out;
+
+	/* If this packet is an ARP_REQUEST and the node already has the
+	 * information that it is going to ask, then the packet can be dropped
+	 */
+	if (forw_packet->num_packets)
+		goto out;
+
+	type = batadv_arp_get_type(bat_priv, forw_packet->skb, bcast_len);
+	if (type != ARPOP_REQUEST)
+		goto out;
+
+	ip_dst = batadv_arp_ip_dst(forw_packet->skb, bcast_len);
+	dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
+	/* check if the node already got this entry */
+	if (!dat_entry) {
+		batadv_dbg(BATADV_DBG_DAT, bat_priv,
+			   "ARP Request for %pI4: fallback\n", &ip_dst);
+		goto out;
+	}
+
+	batadv_dbg(BATADV_DBG_DAT, bat_priv,
+		   "ARP Request for %pI4: fallback prevented\n", &ip_dst);
+	ret = true;
+
+out:
+	if (dat_entry)
+		batadv_dat_entry_free_ref(dat_entry);
+	return ret;
+}
diff --git a/net/batman-adv/distributed-arp-table.h b/net/batman-adv/distributed-arp-table.h
new file mode 100644
index 0000000..d060c03
--- /dev/null
+++ b/net/batman-adv/distributed-arp-table.h
@@ -0,0 +1,167 @@
+/* Copyright (C) 2011-2012 B.A.T.M.A.N. contributors:
+ *
+ * Antonio Quartulli
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#ifndef _NET_BATMAN_ADV_ARP_H_
+#define _NET_BATMAN_ADV_ARP_H_
+
+#ifdef CONFIG_BATMAN_ADV_DAT
+
+#include "types.h"
+#include "originator.h"
+
+#include <linux/if_arp.h>
+
+#define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0)
+
+bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
+					   struct sk_buff *skb);
+bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
+					   struct sk_buff *skb, int hdr_size);
+void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
+					 struct sk_buff *skb);
+bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
+					 struct sk_buff *skb, int hdr_size);
+bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
+				      struct batadv_forw_packet *forw_packet);
+
+/**
+ * batadv_dat_init_orig_node_addr - assign a DAT address to the orig_node
+ * @orig_node: the node to assign the DAT address to
+ */
+static inline void
+batadv_dat_init_orig_node_addr(struct batadv_orig_node *orig_node)
+{
+	uint32_t addr;
+
+	addr = batadv_choose_orig(orig_node->orig, BATADV_DAT_ADDR_MAX);
+	orig_node->dat_addr = (batadv_dat_addr_t)addr;
+}
+
+/**
+ * batadv_dat_init_own_addr - assign a DAT address to the node itself
+ * @bat_priv: the bat priv with all the soft interface information
+ * @primary_if: a pointer to the primary interface
+ */
+static inline void
+batadv_dat_init_own_addr(struct batadv_priv *bat_priv,
+			 struct batadv_hard_iface *primary_if)
+{
+	uint32_t addr;
+
+	addr = batadv_choose_orig(primary_if->net_dev->dev_addr,
+				  BATADV_DAT_ADDR_MAX);
+
+	bat_priv->dat.addr = (batadv_dat_addr_t)addr;
+}
+
+int batadv_dat_init(struct batadv_priv *bat_priv);
+void batadv_dat_free(struct batadv_priv *bat_priv);
+int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset);
+
+/**
+ * batadv_dat_inc_counter - increment the correct DAT packet counter
+ * @bat_priv: the bat priv with all the soft interface information
+ * @subtype: the 4addr subtype of the packet to be counted
+ *
+ * Updates the ethtool statistics for the received packet if it is a DAT subtype
+ */
+static inline void batadv_dat_inc_counter(struct batadv_priv *bat_priv,
+					  uint8_t subtype)
+{
+	switch (subtype) {
+	case BATADV_P_DAT_DHT_GET:
+		batadv_inc_counter(bat_priv,
+				   BATADV_CNT_DAT_GET_RX);
+		break;
+	case BATADV_P_DAT_DHT_PUT:
+		batadv_inc_counter(bat_priv,
+				   BATADV_CNT_DAT_PUT_RX);
+		break;
+	}
+}
+
+#else
+
+static inline bool
+batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
+				      struct sk_buff *skb)
+{
+	return false;
+}
+
+static inline bool
+batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
+				      struct sk_buff *skb, int hdr_size)
+{
+	return false;
+}
+
+static inline bool
+batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
+				    struct sk_buff *skb)
+{
+	return false;
+}
+
+static inline bool
+batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
+				    struct sk_buff *skb, int hdr_size)
+{
+	return false;
+}
+
+static inline bool
+batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
+				 struct batadv_forw_packet *forw_packet)
+{
+	return false;
+}
+
+static inline void
+batadv_dat_init_orig_node_addr(struct batadv_orig_node *orig_node)
+{
+}
+
+static inline void batadv_dat_init_own_addr(struct batadv_priv *bat_priv,
+					    struct batadv_hard_iface *iface)
+{
+}
+
+static inline void batadv_arp_change_timeout(struct net_device *soft_iface,
+					     const char *name)
+{
+}
+
+static inline int batadv_dat_init(struct batadv_priv *bat_priv)
+{
+	return 0;
+}
+
+static inline void batadv_dat_free(struct batadv_priv *bat_priv)
+{
+}
+
+static inline void batadv_dat_inc_counter(struct batadv_priv *bat_priv,
+					  uint8_t subtype)
+{
+}
+
+#endif /* CONFIG_BATMAN_ADV_DAT */
+
+#endif /* _NET_BATMAN_ADV_ARP_H_ */
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 15d67ab..dd07c7e 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -477,22 +477,11 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
 	struct batadv_hard_iface *primary_if;
 	struct batadv_gw_node *gw_node;
 	struct hlist_node *node;
-	int gw_count = 0, ret = 0;
+	int gw_count = 0;
 
-	primary_if = batadv_primary_if_get_selected(bat_priv);
-	if (!primary_if) {
-		ret = seq_printf(seq,
-				 "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
-				 net_dev->name);
+	primary_if = batadv_seq_print_text_primary_if_get(seq);
+	if (!primary_if)
 		goto out;
-	}
-
-	if (primary_if->if_status != BATADV_IF_ACTIVE) {
-		ret = seq_printf(seq,
-				 "BATMAN mesh %s disabled - primary interface not active\n",
-				 net_dev->name);
-		goto out;
-	}
 
 	seq_printf(seq,
 		   "      %-12s (%s/%i) %17s [%10s]: gw_class ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
@@ -519,7 +508,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
 out:
 	if (primary_if)
 		batadv_hardif_free_ref(primary_if);
-	return ret;
+	return 0;
 }
 
 static bool batadv_is_type_dhcprequest(struct sk_buff *skb, int header_len)
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index d112fd6..365ed74 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -18,6 +18,7 @@
  */
 
 #include "main.h"
+#include "distributed-arp-table.h"
 #include "hard-interface.h"
 #include "soft-interface.h"
 #include "send.h"
@@ -58,6 +59,45 @@ out:
 	return hard_iface;
 }
 
+/**
+ * batadv_is_on_batman_iface - check if a device is a batman iface descendant
+ * @net_dev: the device to check
+ *
+ * If the user creates any virtual device on top of a batman-adv interface, it
+ * is important to prevent this new interface to be used to create a new mesh
+ * network (this behaviour would lead to a batman-over-batman configuration).
+ * This function recursively checks all the fathers of the device passed as
+ * argument looking for a batman-adv soft interface.
+ *
+ * Returns true if the device is descendant of a batman-adv mesh interface (or
+ * if it is a batman-adv interface itself), false otherwise
+ */
+static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
+{
+	struct net_device *parent_dev;
+	bool ret;
+
+	/* check if this is a batman-adv mesh interface */
+	if (batadv_softif_is_valid(net_dev))
+		return true;
+
+	/* no more parents..stop recursion */
+	if (net_dev->iflink == net_dev->ifindex)
+		return false;
+
+	/* recurse over the parent device */
+	parent_dev = dev_get_by_index(&init_net, net_dev->iflink);
+	/* if we got a NULL parent_dev there is something broken.. */
+	if (WARN(!parent_dev, "Cannot find parent device"))
+		return false;
+
+	ret = batadv_is_on_batman_iface(parent_dev);
+
+	if (parent_dev)
+		dev_put(parent_dev);
+	return ret;
+}
+
 static int batadv_is_valid_iface(const struct net_device *net_dev)
 {
 	if (net_dev->flags & IFF_LOOPBACK)
@@ -70,7 +110,7 @@ static int batadv_is_valid_iface(const struct net_device *net_dev)
 		return 0;
 
 	/* no batman over batman */
-	if (batadv_softif_is_valid(net_dev))
+	if (batadv_is_on_batman_iface(net_dev))
 		return 0;
 
 	return 1;
@@ -109,6 +149,8 @@ static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv,
 	if (!primary_if)
 		goto out;
 
+	batadv_dat_init_own_addr(bat_priv, primary_if);
+
 	skb = bat_priv->vis.my_info->skb_packet;
 	vis_packet = (struct batadv_vis_packet *)skb->data;
 	memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
@@ -450,8 +492,8 @@ batadv_hardif_add_interface(struct net_device *net_dev)
 	/* This can't be called via a bat_priv callback because
 	 * we have no bat_priv yet.
 	 */
-	atomic_set(&hard_iface->seqno, 1);
-	hard_iface->packet_buff = NULL;
+	atomic_set(&hard_iface->bat_iv.ogm_seqno, 1);
+	hard_iface->bat_iv.ogm_buff = NULL;
 
 	return hard_iface;
 
diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h
index 977de9c..e053339 100644
--- a/net/batman-adv/hash.h
+++ b/net/batman-adv/hash.h
@@ -82,6 +82,28 @@ static inline void batadv_hash_delete(struct batadv_hashtable *hash,
 }
 
 /**
+ *	batadv_hash_bytes - hash some bytes and add them to the previous hash
+ *	@hash: previous hash value
+ *	@data: data to be hashed
+ *	@size: number of bytes to be hashed
+ *
+ *	Returns the new hash value.
+ */
+static inline uint32_t batadv_hash_bytes(uint32_t hash, void *data,
+					 uint32_t size)
+{
+	const unsigned char *key = data;
+	int i;
+
+	for (i = 0; i < size; i++) {
+		hash += key[i];
+		hash += (hash << 10);
+		hash ^= (hash >> 6);
+	}
+	return hash;
+}
+
+/**
  *	batadv_hash_add - adds data to the hashtable
  *	@hash: storage hash table
  *	@compare: callback to determine if 2 hash elements are identical
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index bde3cf747..87ca809 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -42,12 +42,16 @@ static int batadv_socket_open(struct inode *inode, struct file *file)
 	unsigned int i;
 	struct batadv_socket_client *socket_client;
 
+	if (!try_module_get(THIS_MODULE))
+		return -EBUSY;
+
 	nonseekable_open(inode, file);
 
 	socket_client = kmalloc(sizeof(*socket_client), GFP_KERNEL);
-
-	if (!socket_client)
+	if (!socket_client) {
+		module_put(THIS_MODULE);
 		return -ENOMEM;
+	}
 
 	for (i = 0; i < ARRAY_SIZE(batadv_socket_client_hash); i++) {
 		if (!batadv_socket_client_hash[i]) {
@@ -59,6 +63,7 @@ static int batadv_socket_open(struct inode *inode, struct file *file)
 	if (i == ARRAY_SIZE(batadv_socket_client_hash)) {
 		pr_err("Error - can't add another packet client: maximum number of clients reached\n");
 		kfree(socket_client);
+		module_put(THIS_MODULE);
 		return -EXFULL;
 	}
 
@@ -71,7 +76,6 @@ static int batadv_socket_open(struct inode *inode, struct file *file)
 
 	file->private_data = socket_client;
 
-	batadv_inc_module_count();
 	return 0;
 }
 
@@ -96,7 +100,7 @@ static int batadv_socket_release(struct inode *inode, struct file *file)
 	spin_unlock_bh(&socket_client->lock);
 
 	kfree(socket_client);
-	batadv_dec_module_count();
+	module_put(THIS_MODULE);
 
 	return 0;
 }
@@ -173,13 +177,13 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
 	if (len >= sizeof(struct batadv_icmp_packet_rr))
 		packet_len = sizeof(struct batadv_icmp_packet_rr);
 
-	skb = dev_alloc_skb(packet_len + ETH_HLEN);
+	skb = dev_alloc_skb(packet_len + ETH_HLEN + NET_IP_ALIGN);
 	if (!skb) {
 		len = -ENOMEM;
 		goto out;
 	}
 
-	skb_reserve(skb, ETH_HLEN);
+	skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
 	icmp_packet = (struct batadv_icmp_packet_rr *)skb_put(skb, packet_len);
 
 	if (copy_from_user(icmp_packet, buff, packet_len)) {
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index b4aa470..f65a222 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -17,6 +17,8 @@
  * 02110-1301, USA
  */
 
+#include <linux/crc32c.h>
+#include <linux/highmem.h>
 #include "main.h"
 #include "sysfs.h"
 #include "debugfs.h"
@@ -29,6 +31,7 @@
 #include "hard-interface.h"
 #include "gateway_client.h"
 #include "bridge_loop_avoidance.h"
+#include "distributed-arp-table.h"
 #include "vis.h"
 #include "hash.h"
 #include "bat_algo.h"
@@ -128,6 +131,10 @@ int batadv_mesh_init(struct net_device *soft_iface)
 	if (ret < 0)
 		goto err;
 
+	ret = batadv_dat_init(bat_priv);
+	if (ret < 0)
+		goto err;
+
 	atomic_set(&bat_priv->gw.reselect, 0);
 	atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE);
 
@@ -155,21 +162,13 @@ void batadv_mesh_free(struct net_device *soft_iface)
 
 	batadv_bla_free(bat_priv);
 
+	batadv_dat_free(bat_priv);
+
 	free_percpu(bat_priv->bat_counters);
 
 	atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
 }
 
-void batadv_inc_module_count(void)
-{
-	try_module_get(THIS_MODULE);
-}
-
-void batadv_dec_module_count(void)
-{
-	module_put(THIS_MODULE);
-}
-
 int batadv_is_my_mac(const uint8_t *addr)
 {
 	const struct batadv_hard_iface *hard_iface;
@@ -188,6 +187,42 @@ int batadv_is_my_mac(const uint8_t *addr)
 	return 0;
 }
 
+/**
+ * batadv_seq_print_text_primary_if_get - called from debugfs table printing
+ *  function that requires the primary interface
+ * @seq: debugfs table seq_file struct
+ *
+ * Returns primary interface if found or NULL otherwise.
+ */
+struct batadv_hard_iface *
+batadv_seq_print_text_primary_if_get(struct seq_file *seq)
+{
+	struct net_device *net_dev = (struct net_device *)seq->private;
+	struct batadv_priv *bat_priv = netdev_priv(net_dev);
+	struct batadv_hard_iface *primary_if;
+
+	primary_if = batadv_primary_if_get_selected(bat_priv);
+
+	if (!primary_if) {
+		seq_printf(seq,
+			   "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
+			   net_dev->name);
+		goto out;
+	}
+
+	if (primary_if->if_status == BATADV_IF_ACTIVE)
+		goto out;
+
+	seq_printf(seq,
+		   "BATMAN mesh %s disabled - primary interface not active\n",
+		   net_dev->name);
+	batadv_hardif_free_ref(primary_if);
+	primary_if = NULL;
+
+out:
+	return primary_if;
+}
+
 static int batadv_recv_unhandled_packet(struct sk_buff *skb,
 					struct batadv_hard_iface *recv_if)
 {
@@ -274,6 +309,8 @@ static void batadv_recv_handler_init(void)
 
 	/* batman icmp packet */
 	batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet;
+	/* unicast with 4 addresses packet */
+	batadv_rx_handler[BATADV_UNICAST_4ADDR] = batadv_recv_unicast_packet;
 	/* unicast packet */
 	batadv_rx_handler[BATADV_UNICAST] = batadv_recv_unicast_packet;
 	/* fragmented unicast packet */
@@ -385,6 +422,38 @@ int batadv_algo_seq_print_text(struct seq_file *seq, void *offset)
 	return 0;
 }
 
+/**
+ * batadv_skb_crc32 - calculate CRC32 of the whole packet and skip bytes in
+ *  the header
+ * @skb: skb pointing to fragmented socket buffers
+ * @payload_ptr: Pointer to position inside the head buffer of the skb
+ *  marking the start of the data to be CRC'ed
+ *
+ * payload_ptr must always point to an address in the skb head buffer and not to
+ * a fragment.
+ */
+__be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr)
+{
+	u32 crc = 0;
+	unsigned int from;
+	unsigned int to = skb->len;
+	struct skb_seq_state st;
+	const u8 *data;
+	unsigned int len;
+	unsigned int consumed = 0;
+
+	from = (unsigned int)(payload_ptr - skb->data);
+
+	skb_prepare_seq_read(skb, from, to, &st);
+	while ((len = skb_seq_read(consumed, &data, &st)) != 0) {
+		crc = crc32c(crc, data, len);
+		consumed += len;
+	}
+	skb_abort_seq_read(&st);
+
+	return htonl(crc);
+}
+
 static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
 {
 	struct batadv_algo_ops *bat_algo_ops;
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index d57b746..2f85577 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -26,7 +26,7 @@
 #define BATADV_DRIVER_DEVICE "batman-adv"
 
 #ifndef BATADV_SOURCE_VERSION
-#define BATADV_SOURCE_VERSION "2012.4.0"
+#define BATADV_SOURCE_VERSION "2012.5.0"
 #endif
 
 /* B.A.T.M.A.N. parameters */
@@ -44,6 +44,7 @@
 #define BATADV_TT_LOCAL_TIMEOUT 3600000 /* in milliseconds */
 #define BATADV_TT_CLIENT_ROAM_TIMEOUT 600000 /* in milliseconds */
 #define BATADV_TT_CLIENT_TEMP_TIMEOUT 600000 /* in milliseconds */
+#define BATADV_DAT_ENTRY_TIMEOUT (5*60000) /* 5 mins in milliseconds */
 /* sliding packet range of received originator messages in sequence numbers
  * (should be a multiple of our word size)
  */
@@ -73,6 +74,11 @@
 
 #define BATADV_LOG_BUF_LEN 8192	  /* has to be a power of 2 */
 
+/* msecs after which an ARP_REQUEST is sent in broadcast as fallback */
+#define ARP_REQ_DELAY 250
+/* numbers of originator to contact for any PUT/GET DHT operation */
+#define BATADV_DAT_CANDIDATES_NUM 3
+
 #define BATADV_VIS_INTERVAL 5000	/* 5 seconds */
 
 /* how much worse secondary interfaces may be to be considered as bonding
@@ -89,6 +95,7 @@
 #define BATADV_BLA_PERIOD_LENGTH	10000	/* 10 seconds */
 #define BATADV_BLA_BACKBONE_TIMEOUT	(BATADV_BLA_PERIOD_LENGTH * 3)
 #define BATADV_BLA_CLAIM_TIMEOUT	(BATADV_BLA_PERIOD_LENGTH * 10)
+#define BATADV_BLA_WAIT_PERIODS		3
 
 #define BATADV_DUPLIST_SIZE		16
 #define BATADV_DUPLIST_TIMEOUT		500	/* 500 ms */
@@ -117,6 +124,9 @@ enum batadv_uev_type {
 
 #define BATADV_GW_THRESHOLD	50
 
+#define BATADV_DAT_CANDIDATE_NOT_FOUND	0
+#define BATADV_DAT_CANDIDATE_ORIG	1
+
 /* Debug Messages */
 #ifdef pr_fmt
 #undef pr_fmt
@@ -150,9 +160,9 @@ extern struct workqueue_struct *batadv_event_workqueue;
 
 int batadv_mesh_init(struct net_device *soft_iface);
 void batadv_mesh_free(struct net_device *soft_iface);
-void batadv_inc_module_count(void);
-void batadv_dec_module_count(void);
 int batadv_is_my_mac(const uint8_t *addr);
+struct batadv_hard_iface *
+batadv_seq_print_text_primary_if_get(struct seq_file *seq);
 int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
 			   struct packet_type *ptype,
 			   struct net_device *orig_dev);
@@ -164,14 +174,24 @@ void batadv_recv_handler_unregister(uint8_t packet_type);
 int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops);
 int batadv_algo_select(struct batadv_priv *bat_priv, char *name);
 int batadv_algo_seq_print_text(struct seq_file *seq, void *offset);
+__be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr);
 
-/* all messages related to routing / flooding / broadcasting / etc */
+/**
+ * enum batadv_dbg_level - available log levels
+ * @BATADV_DBG_BATMAN: OGM and TQ computations related messages
+ * @BATADV_DBG_ROUTES: route added / changed / deleted
+ * @BATADV_DBG_TT: translation table messages
+ * @BATADV_DBG_BLA: bridge loop avoidance messages
+ * @BATADV_DBG_DAT: ARP snooping and DAT related messages
+ * @BATADV_DBG_ALL: the union of all the above log levels
+ */
 enum batadv_dbg_level {
 	BATADV_DBG_BATMAN = BIT(0),
-	BATADV_DBG_ROUTES = BIT(1), /* route added / changed / deleted */
-	BATADV_DBG_TT	  = BIT(2), /* translation table operations */
-	BATADV_DBG_BLA    = BIT(3), /* bridge loop avoidance */
-	BATADV_DBG_ALL    = 15,
+	BATADV_DBG_ROUTES = BIT(1),
+	BATADV_DBG_TT	  = BIT(2),
+	BATADV_DBG_BLA    = BIT(3),
+	BATADV_DBG_DAT    = BIT(4),
+	BATADV_DBG_ALL    = 31,
 };
 
 #ifdef CONFIG_BATMAN_ADV_DEBUG
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index ac9bdf8..8c32cf1 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -18,6 +18,7 @@
  */
 
 #include "main.h"
+#include "distributed-arp-table.h"
 #include "originator.h"
 #include "hash.h"
 #include "translation-table.h"
@@ -220,9 +221,9 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
 	atomic_set(&orig_node->refcount, 2);
 
 	orig_node->tt_initialised = false;
-	orig_node->tt_poss_change = false;
 	orig_node->bat_priv = bat_priv;
 	memcpy(orig_node->orig, addr, ETH_ALEN);
+	batadv_dat_init_orig_node_addr(orig_node);
 	orig_node->router = NULL;
 	orig_node->tt_crc = 0;
 	atomic_set(&orig_node->last_ttvn, 0);
@@ -415,23 +416,10 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset)
 	int last_seen_msecs;
 	unsigned long last_seen_jiffies;
 	uint32_t i;
-	int ret = 0;
 
-	primary_if = batadv_primary_if_get_selected(bat_priv);
-
-	if (!primary_if) {
-		ret = seq_printf(seq,
-				 "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
-				 net_dev->name);
-		goto out;
-	}
-
-	if (primary_if->if_status != BATADV_IF_ACTIVE) {
-		ret = seq_printf(seq,
-				 "BATMAN mesh %s disabled - primary interface not active\n",
-				 net_dev->name);
+	primary_if = batadv_seq_print_text_primary_if_get(seq);
+	if (!primary_if)
 		goto out;
-	}
 
 	seq_printf(seq, "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
 		   BATADV_SOURCE_VERSION, primary_if->net_dev->name,
@@ -485,7 +473,7 @@ next:
 out:
 	if (primary_if)
 		batadv_hardif_free_ref(primary_if);
-	return ret;
+	return 0;
 }
 
 static int batadv_orig_node_add_if(struct batadv_orig_node *orig_node,
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 2d23a14..1c5454d 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -23,14 +23,29 @@
 #define BATADV_ETH_P_BATMAN  0x4305 /* unofficial/not registered Ethertype */
 
 enum batadv_packettype {
-	BATADV_IV_OGM	    = 0x01,
-	BATADV_ICMP	    = 0x02,
-	BATADV_UNICAST	    = 0x03,
-	BATADV_BCAST	    = 0x04,
-	BATADV_VIS	    = 0x05,
-	BATADV_UNICAST_FRAG = 0x06,
-	BATADV_TT_QUERY	    = 0x07,
-	BATADV_ROAM_ADV	    = 0x08,
+	BATADV_IV_OGM		= 0x01,
+	BATADV_ICMP		= 0x02,
+	BATADV_UNICAST		= 0x03,
+	BATADV_BCAST		= 0x04,
+	BATADV_VIS		= 0x05,
+	BATADV_UNICAST_FRAG	= 0x06,
+	BATADV_TT_QUERY		= 0x07,
+	BATADV_ROAM_ADV		= 0x08,
+	BATADV_UNICAST_4ADDR	= 0x09,
+};
+
+/**
+ * enum batadv_subtype - packet subtype for unicast4addr
+ * @BATADV_P_DATA: user payload
+ * @BATADV_P_DAT_DHT_GET: DHT request message
+ * @BATADV_P_DAT_DHT_PUT: DHT store message
+ * @BATADV_P_DAT_CACHE_REPLY: ARP reply generated by DAT
+ */
+enum batadv_subtype {
+	BATADV_P_DATA			= 0x01,
+	BATADV_P_DAT_DHT_GET		= 0x02,
+	BATADV_P_DAT_DHT_PUT		= 0x03,
+	BATADV_P_DAT_CACHE_REPLY	= 0x04,
 };
 
 /* this file is included by batctl which needs these defines */
@@ -106,13 +121,16 @@ struct batadv_bla_claim_dst {
 	uint8_t magic[3];	/* FF:43:05 */
 	uint8_t type;		/* bla_claimframe */
 	__be16 group;		/* group id */
-} __packed;
+};
 
 struct batadv_header {
 	uint8_t  packet_type;
 	uint8_t  version;  /* batman version field */
 	uint8_t  ttl;
-} __packed;
+	/* the parent struct has to add a byte after the header to make
+	 * everything 4 bytes aligned again
+	 */
+};
 
 struct batadv_ogm_packet {
 	struct batadv_header header;
@@ -137,7 +155,7 @@ struct batadv_icmp_packet {
 	__be16   seqno;
 	uint8_t  uid;
 	uint8_t  reserved;
-} __packed;
+};
 
 #define BATADV_RR_LEN 16
 
@@ -153,13 +171,44 @@ struct batadv_icmp_packet_rr {
 	uint8_t  uid;
 	uint8_t  rr_cur;
 	uint8_t  rr[BATADV_RR_LEN][ETH_ALEN];
-} __packed;
+};
+
+/* All packet headers in front of an ethernet header have to be completely
+ * divisible by 2 but not by 4 to make the payload after the ethernet
+ * header again 4 bytes boundary aligned.
+ *
+ * A packing of 2 is necessary to avoid extra padding at the end of the struct
+ * caused by a structure member which is larger than two bytes. Otherwise
+ * the structure would not fulfill the previously mentioned rule to avoid the
+ * misalignment of the payload after the ethernet header. It may also lead to
+ * leakage of information when the padding it not initialized before sending.
+ */
+#pragma pack(2)
 
 struct batadv_unicast_packet {
 	struct batadv_header header;
 	uint8_t  ttvn; /* destination translation table version number */
 	uint8_t  dest[ETH_ALEN];
-} __packed;
+	/* "4 bytes boundary + 2 bytes" long to make the payload after the
+	 * following ethernet header again 4 bytes boundary aligned
+	 */
+};
+
+/**
+ * struct batadv_unicast_4addr_packet - extended unicast packet
+ * @u: common unicast packet header
+ * @src: address of the source
+ * @subtype: packet subtype
+ */
+struct batadv_unicast_4addr_packet {
+	struct batadv_unicast_packet u;
+	uint8_t src[ETH_ALEN];
+	uint8_t subtype;
+	uint8_t reserved;
+	/* "4 bytes boundary + 2 bytes" long to make the payload after the
+	 * following ethernet header again 4 bytes boundary aligned
+	 */
+};
 
 struct batadv_unicast_frag_packet {
 	struct batadv_header header;
@@ -176,7 +225,12 @@ struct batadv_bcast_packet {
 	uint8_t  reserved;
 	__be32   seqno;
 	uint8_t  orig[ETH_ALEN];
-} __packed;
+	/* "4 bytes boundary + 2 bytes" long to make the payload after the
+	 * following ethernet header again 4 bytes boundary aligned
+	 */
+};
+
+#pragma pack()
 
 struct batadv_vis_packet {
 	struct batadv_header header;
@@ -187,7 +241,7 @@ struct batadv_vis_packet {
 	uint8_t  vis_orig[ETH_ALEN];	/* originator reporting its neighbors */
 	uint8_t  target_orig[ETH_ALEN]; /* who should receive this packet */
 	uint8_t  sender_orig[ETH_ALEN]; /* who sent or forwarded this packet */
-} __packed;
+};
 
 struct batadv_tt_query_packet {
 	struct batadv_header header;
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 376b4cc..1aa1722 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -28,6 +28,7 @@
 #include "vis.h"
 #include "unicast.h"
 #include "bridge_loop_avoidance.h"
+#include "distributed-arp-table.h"
 
 static int batadv_route_unicast_packet(struct sk_buff *skb,
 				       struct batadv_hard_iface *recv_if);
@@ -284,7 +285,6 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
 {
 	struct batadv_hard_iface *primary_if = NULL;
 	struct batadv_orig_node *orig_node = NULL;
-	struct batadv_neigh_node *router = NULL;
 	struct batadv_icmp_packet_rr *icmp_packet;
 	int ret = NET_RX_DROP;
 
@@ -306,10 +306,6 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
 	if (!orig_node)
 		goto out;
 
-	router = batadv_orig_node_get_router(orig_node);
-	if (!router)
-		goto out;
-
 	/* create a copy of the skb, if needed, to modify it. */
 	if (skb_cow(skb, ETH_HLEN) < 0)
 		goto out;
@@ -321,14 +317,12 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
 	icmp_packet->msg_type = BATADV_ECHO_REPLY;
 	icmp_packet->header.ttl = BATADV_TTL;
 
-	batadv_send_skb_packet(skb, router->if_incoming, router->addr);
-	ret = NET_RX_SUCCESS;
+	if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+		ret = NET_RX_SUCCESS;
 
 out:
 	if (primary_if)
 		batadv_hardif_free_ref(primary_if);
-	if (router)
-		batadv_neigh_node_free_ref(router);
 	if (orig_node)
 		batadv_orig_node_free_ref(orig_node);
 	return ret;
@@ -339,7 +333,6 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
 {
 	struct batadv_hard_iface *primary_if = NULL;
 	struct batadv_orig_node *orig_node = NULL;
-	struct batadv_neigh_node *router = NULL;
 	struct batadv_icmp_packet *icmp_packet;
 	int ret = NET_RX_DROP;
 
@@ -361,10 +354,6 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
 	if (!orig_node)
 		goto out;
 
-	router = batadv_orig_node_get_router(orig_node);
-	if (!router)
-		goto out;
-
 	/* create a copy of the skb, if needed, to modify it. */
 	if (skb_cow(skb, ETH_HLEN) < 0)
 		goto out;
@@ -376,14 +365,12 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
 	icmp_packet->msg_type = BATADV_TTL_EXCEEDED;
 	icmp_packet->header.ttl = BATADV_TTL;
 
-	batadv_send_skb_packet(skb, router->if_incoming, router->addr);
-	ret = NET_RX_SUCCESS;
+	if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+		ret = NET_RX_SUCCESS;
 
 out:
 	if (primary_if)
 		batadv_hardif_free_ref(primary_if);
-	if (router)
-		batadv_neigh_node_free_ref(router);
 	if (orig_node)
 		batadv_orig_node_free_ref(orig_node);
 	return ret;
@@ -397,7 +384,6 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
 	struct batadv_icmp_packet_rr *icmp_packet;
 	struct ethhdr *ethhdr;
 	struct batadv_orig_node *orig_node = NULL;
-	struct batadv_neigh_node *router = NULL;
 	int hdr_size = sizeof(struct batadv_icmp_packet);
 	int ret = NET_RX_DROP;
 
@@ -446,10 +432,6 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
 	if (!orig_node)
 		goto out;
 
-	router = batadv_orig_node_get_router(orig_node);
-	if (!router)
-		goto out;
-
 	/* create a copy of the skb, if needed, to modify it. */
 	if (skb_cow(skb, ETH_HLEN) < 0)
 		goto out;
@@ -460,12 +442,10 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
 	icmp_packet->header.ttl--;
 
 	/* route it */
-	batadv_send_skb_packet(skb, router->if_incoming, router->addr);
-	ret = NET_RX_SUCCESS;
+	if (batadv_send_skb_to_orig(skb, orig_node, recv_if))
+		ret = NET_RX_SUCCESS;
 
 out:
-	if (router)
-		batadv_neigh_node_free_ref(router);
 	if (orig_node)
 		batadv_orig_node_free_ref(orig_node);
 	return ret;
@@ -549,25 +529,18 @@ batadv_find_ifalter_router(struct batadv_orig_node *primary_orig,
 		if (tmp_neigh_node->if_incoming == recv_if)
 			continue;
 
-		if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
+		if (router && tmp_neigh_node->tq_avg <= router->tq_avg)
 			continue;
 
-		/* if we don't have a router yet
-		 * or this one is better, choose it.
-		 */
-		if ((!router) ||
-		    (tmp_neigh_node->tq_avg > router->tq_avg)) {
-			/* decrement refcount of
-			 * previously selected router
-			 */
-			if (router)
-				batadv_neigh_node_free_ref(router);
+		if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
+			continue;
 
-			router = tmp_neigh_node;
-			atomic_inc_not_zero(&router->refcount);
-		}
+		/* decrement refcount of previously selected router */
+		if (router)
+			batadv_neigh_node_free_ref(router);
 
-		batadv_neigh_node_free_ref(tmp_neigh_node);
+		/* we found a better router (or at least one valid router) */
+		router = tmp_neigh_node;
 	}
 
 	/* use the first candidate if nothing was found. */
@@ -687,21 +660,8 @@ int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
 	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
 	struct batadv_roam_adv_packet *roam_adv_packet;
 	struct batadv_orig_node *orig_node;
-	struct ethhdr *ethhdr;
-
-	/* drop packet if it has not necessary minimum size */
-	if (unlikely(!pskb_may_pull(skb,
-				    sizeof(struct batadv_roam_adv_packet))))
-		goto out;
-
-	ethhdr = (struct ethhdr *)skb_mac_header(skb);
-
-	/* packet with unicast indication but broadcast recipient */
-	if (is_broadcast_ether_addr(ethhdr->h_dest))
-		goto out;
 
-	/* packet with broadcast sender address */
-	if (is_broadcast_ether_addr(ethhdr->h_source))
+	if (batadv_check_unicast_packet(skb, sizeof(*roam_adv_packet)) < 0)
 		goto out;
 
 	batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX);
@@ -730,12 +690,6 @@ int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
 			     BATADV_TT_CLIENT_ROAM,
 			     atomic_read(&orig_node->last_ttvn) + 1);
 
-	/* Roaming phase starts: I have new information but the ttvn has not
-	 * been incremented yet. This flag will make me check all the incoming
-	 * packets for the correct destination.
-	 */
-	bat_priv->tt.poss_change = true;
-
 	batadv_orig_node_free_ref(orig_node);
 out:
 	/* returning NET_RX_DROP will make the caller function kfree the skb */
@@ -907,8 +861,8 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
 			   skb->len + ETH_HLEN);
 
 	/* route it */
-	batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-	ret = NET_RX_SUCCESS;
+	if (batadv_send_skb_to_orig(skb, orig_node, recv_if))
+		ret = NET_RX_SUCCESS;
 
 out:
 	if (neigh_node)
@@ -918,80 +872,161 @@ out:
 	return ret;
 }
 
+/**
+ * batadv_reroute_unicast_packet - update the unicast header for re-routing
+ * @bat_priv: the bat priv with all the soft interface information
+ * @unicast_packet: the unicast header to be updated
+ * @dst_addr: the payload destination
+ *
+ * Search the translation table for dst_addr and update the unicast header with
+ * the new corresponding information (originator address where the destination
+ * client currently is and its known TTVN)
+ *
+ * Returns true if the packet header has been updated, false otherwise
+ */
+static bool
+batadv_reroute_unicast_packet(struct batadv_priv *bat_priv,
+			      struct batadv_unicast_packet *unicast_packet,
+			      uint8_t *dst_addr)
+{
+	struct batadv_orig_node *orig_node = NULL;
+	struct batadv_hard_iface *primary_if = NULL;
+	bool ret = false;
+	uint8_t *orig_addr, orig_ttvn;
+
+	if (batadv_is_my_client(bat_priv, dst_addr)) {
+		primary_if = batadv_primary_if_get_selected(bat_priv);
+		if (!primary_if)
+			goto out;
+		orig_addr = primary_if->net_dev->dev_addr;
+		orig_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
+	} else {
+		orig_node = batadv_transtable_search(bat_priv, NULL, dst_addr);
+		if (!orig_node)
+			goto out;
+
+		if (batadv_compare_eth(orig_node->orig, unicast_packet->dest))
+			goto out;
+
+		orig_addr = orig_node->orig;
+		orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
+	}
+
+	/* update the packet header */
+	memcpy(unicast_packet->dest, orig_addr, ETH_ALEN);
+	unicast_packet->ttvn = orig_ttvn;
+
+	ret = true;
+out:
+	if (primary_if)
+		batadv_hardif_free_ref(primary_if);
+	if (orig_node)
+		batadv_orig_node_free_ref(orig_node);
+
+	return ret;
+}
+
 static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
 				     struct sk_buff *skb) {
-	uint8_t curr_ttvn;
+	uint8_t curr_ttvn, old_ttvn;
 	struct batadv_orig_node *orig_node;
 	struct ethhdr *ethhdr;
 	struct batadv_hard_iface *primary_if;
 	struct batadv_unicast_packet *unicast_packet;
-	bool tt_poss_change;
 	int is_old_ttvn;
 
-	/* I could need to modify it */
-	if (skb_cow(skb, sizeof(struct batadv_unicast_packet)) < 0)
+	/* check if there is enough data before accessing it */
+	if (pskb_may_pull(skb, sizeof(*unicast_packet) + ETH_HLEN) < 0)
+		return 0;
+
+	/* create a copy of the skb (in case of for re-routing) to modify it. */
+	if (skb_cow(skb, sizeof(*unicast_packet)) < 0)
 		return 0;
 
 	unicast_packet = (struct batadv_unicast_packet *)skb->data;
+	ethhdr = (struct ethhdr *)(skb->data + sizeof(*unicast_packet));
 
-	if (batadv_is_my_mac(unicast_packet->dest)) {
-		tt_poss_change = bat_priv->tt.poss_change;
-		curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
-	} else {
+	/* check if the destination client was served by this node and it is now
+	 * roaming. In this case, it means that the node has got a ROAM_ADV
+	 * message and that it knows the new destination in the mesh to re-route
+	 * the packet to
+	 */
+	if (batadv_tt_local_client_is_roaming(bat_priv, ethhdr->h_dest)) {
+		if (batadv_reroute_unicast_packet(bat_priv, unicast_packet,
+						  ethhdr->h_dest))
+			net_ratelimited_function(batadv_dbg, BATADV_DBG_TT,
+						 bat_priv,
+						 "Rerouting unicast packet to %pM (dst=%pM): Local Roaming\n",
+						 unicast_packet->dest,
+						 ethhdr->h_dest);
+		/* at this point the mesh destination should have been
+		 * substituted with the originator address found in the global
+		 * table. If not, let the packet go untouched anyway because
+		 * there is nothing the node can do
+		 */
+		return 1;
+	}
+
+	/* retrieve the TTVN known by this node for the packet destination. This
+	 * value is used later to check if the node which sent (or re-routed
+	 * last time) the packet had an updated information or not
+	 */
+	curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
+	if (!batadv_is_my_mac(unicast_packet->dest)) {
 		orig_node = batadv_orig_hash_find(bat_priv,
 						  unicast_packet->dest);
-
+		/* if it is not possible to find the orig_node representing the
+		 * destination, the packet can immediately be dropped as it will
+		 * not be possible to deliver it
+		 */
 		if (!orig_node)
 			return 0;
 
 		curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
-		tt_poss_change = orig_node->tt_poss_change;
 		batadv_orig_node_free_ref(orig_node);
 	}
 
-	/* Check whether I have to reroute the packet */
+	/* check if the TTVN contained in the packet is fresher than what the
+	 * node knows
+	 */
 	is_old_ttvn = batadv_seq_before(unicast_packet->ttvn, curr_ttvn);
-	if (is_old_ttvn || tt_poss_change) {
-		/* check if there is enough data before accessing it */
-		if (pskb_may_pull(skb, sizeof(struct batadv_unicast_packet) +
-				  ETH_HLEN) < 0)
-			return 0;
+	if (!is_old_ttvn)
+		return 1;
 
-		ethhdr = (struct ethhdr *)(skb->data + sizeof(*unicast_packet));
+	old_ttvn = unicast_packet->ttvn;
+	/* the packet was forged based on outdated network information. Its
+	 * destination can possibly be updated and forwarded towards the new
+	 * target host
+	 */
+	if (batadv_reroute_unicast_packet(bat_priv, unicast_packet,
+					  ethhdr->h_dest)) {
+		net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv,
+					 "Rerouting unicast packet to %pM (dst=%pM): TTVN mismatch old_ttvn=%u new_ttvn=%u\n",
+					 unicast_packet->dest, ethhdr->h_dest,
+					 old_ttvn, curr_ttvn);
+		return 1;
+	}
 
-		/* we don't have an updated route for this client, so we should
-		 * not try to reroute the packet!!
-		 */
-		if (batadv_tt_global_client_is_roaming(bat_priv,
-						       ethhdr->h_dest))
-			return 1;
+	/* the packet has not been re-routed: either the destination is
+	 * currently served by this node or there is no destination at all and
+	 * it is possible to drop the packet
+	 */
+	if (!batadv_is_my_client(bat_priv, ethhdr->h_dest))
+		return 0;
 
-		orig_node = batadv_transtable_search(bat_priv, NULL,
-						     ethhdr->h_dest);
-
-		if (!orig_node) {
-			if (!batadv_is_my_client(bat_priv, ethhdr->h_dest))
-				return 0;
-			primary_if = batadv_primary_if_get_selected(bat_priv);
-			if (!primary_if)
-				return 0;
-			memcpy(unicast_packet->dest,
-			       primary_if->net_dev->dev_addr, ETH_ALEN);
-			batadv_hardif_free_ref(primary_if);
-		} else {
-			memcpy(unicast_packet->dest, orig_node->orig,
-			       ETH_ALEN);
-			curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
-			batadv_orig_node_free_ref(orig_node);
-		}
+	/* update the header in order to let the packet be delivered to this
+	 * node's soft interface
+	 */
+	primary_if = batadv_primary_if_get_selected(bat_priv);
+	if (!primary_if)
+		return 0;
 
-		batadv_dbg(BATADV_DBG_ROUTES, bat_priv,
-			   "TTVN mismatch (old_ttvn %u new_ttvn %u)! Rerouting unicast packet (for %pM) to %pM\n",
-			   unicast_packet->ttvn, curr_ttvn, ethhdr->h_dest,
-			   unicast_packet->dest);
+	memcpy(unicast_packet->dest, primary_if->net_dev->dev_addr, ETH_ALEN);
+
+	batadv_hardif_free_ref(primary_if);
+
+	unicast_packet->ttvn = curr_ttvn;
 
-		unicast_packet->ttvn = curr_ttvn;
-	}
 	return 1;
 }
 
@@ -1000,7 +1035,19 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
 {
 	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
 	struct batadv_unicast_packet *unicast_packet;
+	struct batadv_unicast_4addr_packet *unicast_4addr_packet;
+	uint8_t *orig_addr;
+	struct batadv_orig_node *orig_node = NULL;
 	int hdr_size = sizeof(*unicast_packet);
+	bool is4addr;
+
+	unicast_packet = (struct batadv_unicast_packet *)skb->data;
+	unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
+
+	is4addr = unicast_packet->header.packet_type == BATADV_UNICAST_4ADDR;
+	/* the caller function should have already pulled 2 bytes */
+	if (is4addr)
+		hdr_size = sizeof(*unicast_4addr_packet);
 
 	if (batadv_check_unicast_packet(skb, hdr_size) < 0)
 		return NET_RX_DROP;
@@ -1008,12 +1055,28 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
 	if (!batadv_check_unicast_ttvn(bat_priv, skb))
 		return NET_RX_DROP;
 
-	unicast_packet = (struct batadv_unicast_packet *)skb->data;
-
 	/* packet for me */
 	if (batadv_is_my_mac(unicast_packet->dest)) {
+		if (is4addr) {
+			batadv_dat_inc_counter(bat_priv,
+					       unicast_4addr_packet->subtype);
+			orig_addr = unicast_4addr_packet->src;
+			orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
+		}
+
+		if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb,
+							  hdr_size))
+			goto rx_success;
+		if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb,
+							hdr_size))
+			goto rx_success;
+
 		batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size,
-				    NULL);
+				    orig_node);
+
+rx_success:
+		if (orig_node)
+			batadv_orig_node_free_ref(orig_node);
 
 		return NET_RX_SUCCESS;
 	}
@@ -1050,8 +1113,17 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb,
 		if (!new_skb)
 			return NET_RX_SUCCESS;
 
+		if (batadv_dat_snoop_incoming_arp_request(bat_priv, new_skb,
+							  hdr_size))
+			goto rx_success;
+		if (batadv_dat_snoop_incoming_arp_reply(bat_priv, new_skb,
+							hdr_size))
+			goto rx_success;
+
 		batadv_interface_rx(recv_if->soft_iface, new_skb, recv_if,
 				    sizeof(struct batadv_unicast_packet), NULL);
+
+rx_success:
 		return NET_RX_SUCCESS;
 	}
 
@@ -1124,14 +1196,8 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
 
 	spin_unlock_bh(&orig_node->bcast_seqno_lock);
 
-	/* keep skb linear for crc calculation */
-	if (skb_linearize(skb) < 0)
-		goto out;
-
-	bcast_packet = (struct batadv_bcast_packet *)skb->data;
-
 	/* check whether this has been sent by another originator before */
-	if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, skb->len))
+	if (batadv_bla_check_bcast_duplist(bat_priv, skb))
 		goto out;
 
 	/* rebroadcast packet */
@@ -1143,9 +1209,16 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
 	if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size))
 		goto out;
 
+	if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, hdr_size))
+		goto rx_success;
+	if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, hdr_size))
+		goto rx_success;
+
 	/* broadcast for me */
 	batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size,
 			    orig_node);
+
+rx_success:
 	ret = NET_RX_SUCCESS;
 	goto out;
 
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 570a8bc..c7f7023 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -18,6 +18,7 @@
  */
 
 #include "main.h"
+#include "distributed-arp-table.h"
 #include "send.h"
 #include "routing.h"
 #include "translation-table.h"
@@ -77,6 +78,39 @@ send_skb_err:
 	return NET_XMIT_DROP;
 }
 
+/**
+ * batadv_send_skb_to_orig - Lookup next-hop and transmit skb.
+ * @skb: Packet to be transmitted.
+ * @orig_node: Final destination of the packet.
+ * @recv_if: Interface used when receiving the packet (can be NULL).
+ *
+ * Looks up the best next-hop towards the passed originator and passes the
+ * skb on for preparation of MAC header. If the packet originated from this
+ * host, NULL can be passed as recv_if and no interface alternating is
+ * attempted.
+ *
+ * Returns TRUE on success; FALSE otherwise.
+ */
+bool batadv_send_skb_to_orig(struct sk_buff *skb,
+			     struct batadv_orig_node *orig_node,
+			     struct batadv_hard_iface *recv_if)
+{
+	struct batadv_priv *bat_priv = orig_node->bat_priv;
+	struct batadv_neigh_node *neigh_node;
+
+	/* batadv_find_router() increases neigh_nodes refcount if found. */
+	neigh_node = batadv_find_router(bat_priv, orig_node, recv_if);
+	if (!neigh_node)
+		return false;
+
+	/* route it */
+	batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+
+	batadv_neigh_node_free_ref(neigh_node);
+
+	return true;
+}
+
 void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface)
 {
 	struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
@@ -209,6 +243,9 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
 	if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
 		goto out;
 
+	if (batadv_dat_drop_broadcast_packet(bat_priv, forw_packet))
+		goto out;
+
 	/* rebroadcast packet */
 	rcu_read_lock();
 	list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h
index 643329b..0078dec 100644
--- a/net/batman-adv/send.h
+++ b/net/batman-adv/send.h
@@ -23,6 +23,9 @@
 int batadv_send_skb_packet(struct sk_buff *skb,
 			   struct batadv_hard_iface *hard_iface,
 			   const uint8_t *dst_addr);
+bool batadv_send_skb_to_orig(struct sk_buff *skb,
+			     struct batadv_orig_node *orig_node,
+			     struct batadv_hard_iface *recv_if);
 void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface);
 int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
 				    const struct sk_buff *skb,
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index ce0684a..54800c7 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -20,6 +20,7 @@
 #include "main.h"
 #include "soft-interface.h"
 #include "hard-interface.h"
+#include "distributed-arp-table.h"
 #include "routing.h"
 #include "send.h"
 #include "debugfs.h"
@@ -146,13 +147,16 @@ static int batadv_interface_tx(struct sk_buff *skb,
 	struct batadv_bcast_packet *bcast_packet;
 	struct vlan_ethhdr *vhdr;
 	__be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN);
-	static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00, 0x00,
-						   0x00};
+	static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00,
+						   0x00, 0x00};
+	static const uint8_t ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00,
+						    0x00, 0x00};
 	unsigned int header_len = 0;
 	int data_len = skb->len, ret;
 	short vid __maybe_unused = -1;
 	bool do_bcast = false;
 	uint32_t seqno;
+	unsigned long brd_delay = 1;
 
 	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
 		goto dropped;
@@ -180,10 +184,16 @@ static int batadv_interface_tx(struct sk_buff *skb,
 
 	/* don't accept stp packets. STP does not help in meshes.
 	 * better use the bridge loop avoidance ...
+	 *
+	 * The same goes for ECTP sent at least by some Cisco Switches,
+	 * it might confuse the mesh when used with bridge loop avoidance.
 	 */
 	if (batadv_compare_eth(ethhdr->h_dest, stp_addr))
 		goto dropped;
 
+	if (batadv_compare_eth(ethhdr->h_dest, ectp_addr))
+		goto dropped;
+
 	if (is_multicast_ether_addr(ethhdr->h_dest)) {
 		do_bcast = true;
 
@@ -216,6 +226,13 @@ static int batadv_interface_tx(struct sk_buff *skb,
 		if (!primary_if)
 			goto dropped;
 
+		/* in case of ARP request, we do not immediately broadcasti the
+		 * packet, instead we first wait for DAT to try to retrieve the
+		 * correct ARP entry
+		 */
+		if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb))
+			brd_delay = msecs_to_jiffies(ARP_REQ_DELAY);
+
 		if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0)
 			goto dropped;
 
@@ -237,7 +254,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
 		seqno = atomic_inc_return(&bat_priv->bcast_seqno);
 		bcast_packet->seqno = htonl(seqno);
 
-		batadv_add_bcast_packet_to_list(bat_priv, skb, 1);
+		batadv_add_bcast_packet_to_list(bat_priv, skb, brd_delay);
 
 		/* a copy is stored in the bcast list, therefore removing
 		 * the original skb.
@@ -252,7 +269,12 @@ static int batadv_interface_tx(struct sk_buff *skb,
 				goto dropped;
 		}
 
-		ret = batadv_unicast_send_skb(skb, bat_priv);
+		if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb))
+			goto dropped;
+
+		batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb);
+
+		ret = batadv_unicast_send_skb(bat_priv, skb);
 		if (ret != 0)
 			goto dropped_freed;
 	}
@@ -347,7 +369,51 @@ out:
 	return;
 }
 
+/* batman-adv network devices have devices nesting below it and are a special
+ * "super class" of normal network devices; split their locks off into a
+ * separate class since they always nest.
+ */
+static struct lock_class_key batadv_netdev_xmit_lock_key;
+static struct lock_class_key batadv_netdev_addr_lock_key;
+
+/**
+ * batadv_set_lockdep_class_one - Set lockdep class for a single tx queue
+ * @dev: device which owns the tx queue
+ * @txq: tx queue to modify
+ * @_unused: always NULL
+ */
+static void batadv_set_lockdep_class_one(struct net_device *dev,
+					 struct netdev_queue *txq,
+					 void *_unused)
+{
+	lockdep_set_class(&txq->_xmit_lock, &batadv_netdev_xmit_lock_key);
+}
+
+/**
+ * batadv_set_lockdep_class - Set txq and addr_list lockdep class
+ * @dev: network device to modify
+ */
+static void batadv_set_lockdep_class(struct net_device *dev)
+{
+	lockdep_set_class(&dev->addr_list_lock, &batadv_netdev_addr_lock_key);
+	netdev_for_each_tx_queue(dev, batadv_set_lockdep_class_one, NULL);
+}
+
+/**
+ * batadv_softif_init - Late stage initialization of soft interface
+ * @dev: registered network device to modify
+ *
+ * Returns error code on failures
+ */
+static int batadv_softif_init(struct net_device *dev)
+{
+	batadv_set_lockdep_class(dev);
+
+	return 0;
+}
+
 static const struct net_device_ops batadv_netdev_ops = {
+	.ndo_init = batadv_softif_init,
 	.ndo_open = batadv_interface_open,
 	.ndo_stop = batadv_interface_release,
 	.ndo_get_stats = batadv_interface_stats,
@@ -414,6 +480,9 @@ struct net_device *batadv_softif_create(const char *name)
 	atomic_set(&bat_priv->aggregated_ogms, 1);
 	atomic_set(&bat_priv->bonding, 0);
 	atomic_set(&bat_priv->bridge_loop_avoidance, 0);
+#ifdef CONFIG_BATMAN_ADV_DAT
+	atomic_set(&bat_priv->distributed_arp_table, 1);
+#endif
 	atomic_set(&bat_priv->ap_isolation, 0);
 	atomic_set(&bat_priv->vis_mode, BATADV_VIS_TYPE_CLIENT_UPDATE);
 	atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
@@ -436,7 +505,6 @@ struct net_device *batadv_softif_create(const char *name)
 #endif
 	bat_priv->tt.last_changeset = NULL;
 	bat_priv->tt.last_changeset_len = 0;
-	bat_priv->tt.poss_change = false;
 
 	bat_priv->primary_if = NULL;
 	bat_priv->num_ifaces = 0;
@@ -556,6 +624,13 @@ static const struct {
 	{ "tt_response_rx" },
 	{ "tt_roam_adv_tx" },
 	{ "tt_roam_adv_rx" },
+#ifdef CONFIG_BATMAN_ADV_DAT
+	{ "dat_get_tx" },
+	{ "dat_get_rx" },
+	{ "dat_put_tx" },
+	{ "dat_put_rx" },
+	{ "dat_cached_reply_tx" },
+#endif
 };
 
 static void batadv_get_strings(struct net_device *dev, uint32_t stringset,
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index 66518c7..84a55cb 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -20,6 +20,7 @@
 #include "main.h"
 #include "sysfs.h"
 #include "translation-table.h"
+#include "distributed-arp-table.h"
 #include "originator.h"
 #include "hard-interface.h"
 #include "gateway_common.h"
@@ -122,55 +123,6 @@ ssize_t batadv_show_##_name(struct kobject *kobj,			\
 			   batadv_store_##_name)
 
 
-#define BATADV_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func)	\
-ssize_t batadv_store_##_name(struct kobject *kobj,			\
-			     struct attribute *attr, char *buff,	\
-			     size_t count)				\
-{									\
-	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);	\
-	struct batadv_hard_iface *hard_iface;				\
-	ssize_t length;							\
-									\
-	hard_iface = batadv_hardif_get_by_netdev(net_dev);		\
-	if (!hard_iface)						\
-		return 0;						\
-									\
-	length = __batadv_store_uint_attr(buff, count, _min, _max,	\
-					  _post_func, attr,		\
-					  &hard_iface->_name, net_dev);	\
-									\
-	batadv_hardif_free_ref(hard_iface);				\
-	return length;							\
-}
-
-#define BATADV_ATTR_HIF_SHOW_UINT(_name)				\
-ssize_t batadv_show_##_name(struct kobject *kobj,			\
-			    struct attribute *attr, char *buff)		\
-{									\
-	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);	\
-	struct batadv_hard_iface *hard_iface;				\
-	ssize_t length;							\
-									\
-	hard_iface = batadv_hardif_get_by_netdev(net_dev);		\
-	if (!hard_iface)						\
-		return 0;						\
-									\
-	length = sprintf(buff, "%i\n", atomic_read(&hard_iface->_name));\
-									\
-	batadv_hardif_free_ref(hard_iface);				\
-	return length;							\
-}
-
-/* Use this, if you are going to set [name] in hard_iface to an
- * unsigned integer value
- */
-#define BATADV_ATTR_HIF_UINT(_name, _mode, _min, _max, _post_func)	\
-	static BATADV_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func)\
-	static BATADV_ATTR_HIF_SHOW_UINT(_name)				\
-	static BATADV_ATTR(_name, _mode, batadv_show_##_name,		\
-			   batadv_store_##_name)
-
-
 static int batadv_store_bool_attr(char *buff, size_t count,
 				  struct net_device *net_dev,
 				  const char *attr_name, atomic_t *attr)
@@ -469,6 +421,9 @@ BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
 #ifdef CONFIG_BATMAN_ADV_BLA
 BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL);
 #endif
+#ifdef CONFIG_BATMAN_ADV_DAT
+BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR, NULL);
+#endif
 BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu);
 BATADV_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
 static BATADV_ATTR(vis_mode, S_IRUGO | S_IWUSR, batadv_show_vis_mode,
@@ -494,6 +449,9 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
 #ifdef CONFIG_BATMAN_ADV_BLA
 	&batadv_attr_bridge_loop_avoidance,
 #endif
+#ifdef CONFIG_BATMAN_ADV_DAT
+	&batadv_attr_distributed_arp_table,
+#endif
 	&batadv_attr_fragmentation,
 	&batadv_attr_ap_isolation,
 	&batadv_attr_vis_mode,
@@ -730,7 +688,7 @@ int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type,
 			enum batadv_uev_action action, const char *data)
 {
 	int ret = -ENOMEM;
-	struct batadv_hard_iface *primary_if = NULL;
+	struct batadv_hard_iface *primary_if;
 	struct kobject *bat_kobj;
 	char *uevent_env[4] = { NULL, NULL, NULL, NULL };
 
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index baae715..22457a7 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -238,92 +238,134 @@ static int batadv_tt_local_init(struct batadv_priv *bat_priv)
 	return 0;
 }
 
+static void batadv_tt_global_free(struct batadv_priv *bat_priv,
+				  struct batadv_tt_global_entry *tt_global,
+				  const char *message)
+{
+	batadv_dbg(BATADV_DBG_TT, bat_priv,
+		   "Deleting global tt entry %pM: %s\n",
+		   tt_global->common.addr, message);
+
+	batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
+			   batadv_choose_orig, tt_global->common.addr);
+	batadv_tt_global_entry_free_ref(tt_global);
+
+}
+
 void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
 			 int ifindex)
 {
 	struct batadv_priv *bat_priv = netdev_priv(soft_iface);
-	struct batadv_tt_local_entry *tt_local_entry = NULL;
-	struct batadv_tt_global_entry *tt_global_entry = NULL;
+	struct batadv_tt_local_entry *tt_local;
+	struct batadv_tt_global_entry *tt_global;
 	struct hlist_head *head;
 	struct hlist_node *node;
 	struct batadv_tt_orig_list_entry *orig_entry;
 	int hash_added;
+	bool roamed_back = false;
 
-	tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
+	tt_local = batadv_tt_local_hash_find(bat_priv, addr);
+	tt_global = batadv_tt_global_hash_find(bat_priv, addr);
 
-	if (tt_local_entry) {
-		tt_local_entry->last_seen = jiffies;
-		/* possibly unset the BATADV_TT_CLIENT_PENDING flag */
-		tt_local_entry->common.flags &= ~BATADV_TT_CLIENT_PENDING;
-		goto out;
+	if (tt_local) {
+		tt_local->last_seen = jiffies;
+		if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) {
+			batadv_dbg(BATADV_DBG_TT, bat_priv,
+				   "Re-adding pending client %pM\n", addr);
+			/* whatever the reason why the PENDING flag was set,
+			 * this is a client which was enqueued to be removed in
+			 * this orig_interval. Since it popped up again, the
+			 * flag can be reset like it was never enqueued
+			 */
+			tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING;
+			goto add_event;
+		}
+
+		if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) {
+			batadv_dbg(BATADV_DBG_TT, bat_priv,
+				   "Roaming client %pM came back to its original location\n",
+				   addr);
+			/* the ROAM flag is set because this client roamed away
+			 * and the node got a roaming_advertisement message. Now
+			 * that the client popped up again at its original
+			 * location such flag can be unset
+			 */
+			tt_local->common.flags &= ~BATADV_TT_CLIENT_ROAM;
+			roamed_back = true;
+		}
+		goto check_roaming;
 	}
 
-	tt_local_entry = kmalloc(sizeof(*tt_local_entry), GFP_ATOMIC);
-	if (!tt_local_entry)
+	tt_local = kmalloc(sizeof(*tt_local), GFP_ATOMIC);
+	if (!tt_local)
 		goto out;
 
 	batadv_dbg(BATADV_DBG_TT, bat_priv,
 		   "Creating new local tt entry: %pM (ttvn: %d)\n", addr,
 		   (uint8_t)atomic_read(&bat_priv->tt.vn));
 
-	memcpy(tt_local_entry->common.addr, addr, ETH_ALEN);
-	tt_local_entry->common.flags = BATADV_NO_FLAGS;
+	memcpy(tt_local->common.addr, addr, ETH_ALEN);
+	tt_local->common.flags = BATADV_NO_FLAGS;
 	if (batadv_is_wifi_iface(ifindex))
-		tt_local_entry->common.flags |= BATADV_TT_CLIENT_WIFI;
-	atomic_set(&tt_local_entry->common.refcount, 2);
-	tt_local_entry->last_seen = jiffies;
-	tt_local_entry->common.added_at = tt_local_entry->last_seen;
+		tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
+	atomic_set(&tt_local->common.refcount, 2);
+	tt_local->last_seen = jiffies;
+	tt_local->common.added_at = tt_local->last_seen;
 
 	/* the batman interface mac address should never be purged */
 	if (batadv_compare_eth(addr, soft_iface->dev_addr))
-		tt_local_entry->common.flags |= BATADV_TT_CLIENT_NOPURGE;
+		tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE;
 
 	/* The local entry has to be marked as NEW to avoid to send it in
 	 * a full table response going out before the next ttvn increment
 	 * (consistency check)
 	 */
-	tt_local_entry->common.flags |= BATADV_TT_CLIENT_NEW;
+	tt_local->common.flags |= BATADV_TT_CLIENT_NEW;
 
 	hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
-				     batadv_choose_orig,
-				     &tt_local_entry->common,
-				     &tt_local_entry->common.hash_entry);
+				     batadv_choose_orig, &tt_local->common,
+				     &tt_local->common.hash_entry);
 
 	if (unlikely(hash_added != 0)) {
 		/* remove the reference for the hash */
-		batadv_tt_local_entry_free_ref(tt_local_entry);
+		batadv_tt_local_entry_free_ref(tt_local);
 		goto out;
 	}
 
-	batadv_tt_local_event(bat_priv, addr, tt_local_entry->common.flags);
+add_event:
+	batadv_tt_local_event(bat_priv, addr, tt_local->common.flags);
 
-	/* remove address from global hash if present */
-	tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr);
-
-	/* Check whether it is a roaming! */
-	if (tt_global_entry) {
+check_roaming:
+	/* Check whether it is a roaming, but don't do anything if the roaming
+	 * process has already been handled
+	 */
+	if (tt_global && !(tt_global->common.flags & BATADV_TT_CLIENT_ROAM)) {
 		/* These node are probably going to update their tt table */
-		head = &tt_global_entry->orig_list;
+		head = &tt_global->orig_list;
 		rcu_read_lock();
 		hlist_for_each_entry_rcu(orig_entry, node, head, list) {
-			orig_entry->orig_node->tt_poss_change = true;
-
-			batadv_send_roam_adv(bat_priv,
-					     tt_global_entry->common.addr,
+			batadv_send_roam_adv(bat_priv, tt_global->common.addr,
 					     orig_entry->orig_node);
 		}
 		rcu_read_unlock();
-		/* The global entry has to be marked as ROAMING and
-		 * has to be kept for consistency purpose
-		 */
-		tt_global_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
-		tt_global_entry->roam_at = jiffies;
+		if (roamed_back) {
+			batadv_tt_global_free(bat_priv, tt_global,
+					      "Roaming canceled");
+			tt_global = NULL;
+		} else {
+			/* The global entry has to be marked as ROAMING and
+			 * has to be kept for consistency purpose
+			 */
+			tt_global->common.flags |= BATADV_TT_CLIENT_ROAM;
+			tt_global->roam_at = jiffies;
+		}
 	}
+
 out:
-	if (tt_local_entry)
-		batadv_tt_local_entry_free_ref(tt_local_entry);
-	if (tt_global_entry)
-		batadv_tt_global_entry_free_ref(tt_global_entry);
+	if (tt_local)
+		batadv_tt_local_entry_free_ref(tt_local);
+	if (tt_global)
+		batadv_tt_global_entry_free_ref(tt_global);
 }
 
 static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff,
@@ -434,22 +476,10 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
 	struct hlist_node *node;
 	struct hlist_head *head;
 	uint32_t i;
-	int ret = 0;
 
-	primary_if = batadv_primary_if_get_selected(bat_priv);
-	if (!primary_if) {
-		ret = seq_printf(seq,
-				 "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
-				 net_dev->name);
-		goto out;
-	}
-
-	if (primary_if->if_status != BATADV_IF_ACTIVE) {
-		ret = seq_printf(seq,
-				 "BATMAN mesh %s disabled - primary interface not active\n",
-				 net_dev->name);
+	primary_if = batadv_seq_print_text_primary_if_get(seq);
+	if (!primary_if)
 		goto out;
-	}
 
 	seq_printf(seq,
 		   "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n",
@@ -479,7 +509,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
 out:
 	if (primary_if)
 		batadv_hardif_free_ref(primary_if);
-	return ret;
+	return 0;
 }
 
 static void
@@ -501,24 +531,57 @@ batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
 		   tt_local_entry->common.addr, message);
 }
 
-void batadv_tt_local_remove(struct batadv_priv *bat_priv, const uint8_t *addr,
-			    const char *message, bool roaming)
+/**
+ * batadv_tt_local_remove - logically remove an entry from the local table
+ * @bat_priv: the bat priv with all the soft interface information
+ * @addr: the MAC address of the client to remove
+ * @message: message to append to the log on deletion
+ * @roaming: true if the deletion is due to a roaming event
+ *
+ * Returns the flags assigned to the local entry before being deleted
+ */
+uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
+				const uint8_t *addr, const char *message,
+				bool roaming)
 {
-	struct batadv_tt_local_entry *tt_local_entry = NULL;
-	uint16_t flags;
+	struct batadv_tt_local_entry *tt_local_entry;
+	uint16_t flags, curr_flags = BATADV_NO_FLAGS;
 
 	tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
 	if (!tt_local_entry)
 		goto out;
 
+	curr_flags = tt_local_entry->common.flags;
+
 	flags = BATADV_TT_CLIENT_DEL;
-	if (roaming)
+	/* if this global entry addition is due to a roaming, the node has to
+	 * mark the local entry as "roamed" in order to correctly reroute
+	 * packets later
+	 */
+	if (roaming) {
 		flags |= BATADV_TT_CLIENT_ROAM;
+		/* mark the local client as ROAMed */
+		tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
+	}
+
+	if (!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) {
+		batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags,
+					    message);
+		goto out;
+	}
+	/* if this client has been added right now, it is possible to
+	 * immediately purge it
+	 */
+	batadv_tt_local_event(bat_priv, tt_local_entry->common.addr,
+			      curr_flags | BATADV_TT_CLIENT_DEL);
+	hlist_del_rcu(&tt_local_entry->common.hash_entry);
+	batadv_tt_local_entry_free_ref(tt_local_entry);
 
-	batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message);
 out:
 	if (tt_local_entry)
 		batadv_tt_local_entry_free_ref(tt_local_entry);
+
+	return curr_flags;
 }
 
 static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
@@ -721,12 +784,23 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
 			 const unsigned char *tt_addr, uint8_t flags,
 			 uint8_t ttvn)
 {
-	struct batadv_tt_global_entry *tt_global_entry = NULL;
+	struct batadv_tt_global_entry *tt_global_entry;
+	struct batadv_tt_local_entry *tt_local_entry;
 	int ret = 0;
 	int hash_added;
 	struct batadv_tt_common_entry *common;
+	uint16_t local_flags;
 
 	tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr);
+	tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr);
+
+	/* if the node already has a local client for this entry, it has to wait
+	 * for a roaming advertisement instead of manually messing up the global
+	 * table
+	 */
+	if ((flags & BATADV_TT_CLIENT_TEMP) && tt_local_entry &&
+	    !(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW))
+		goto out;
 
 	if (!tt_global_entry) {
 		tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC);
@@ -738,6 +812,12 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
 
 		common->flags = flags;
 		tt_global_entry->roam_at = 0;
+		/* node must store current time in case of roaming. This is
+		 * needed to purge this entry out on timeout (if nobody claims
+		 * it)
+		 */
+		if (flags & BATADV_TT_CLIENT_ROAM)
+			tt_global_entry->roam_at = jiffies;
 		atomic_set(&common->refcount, 2);
 		common->added_at = jiffies;
 
@@ -755,19 +835,31 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
 			goto out_remove;
 		}
 	} else {
+		common = &tt_global_entry->common;
 		/* If there is already a global entry, we can use this one for
 		 * our processing.
-		 * But if we are trying to add a temporary client we can exit
-		 * directly because the temporary information should never
-		 * override any already known client state (whatever it is)
+		 * But if we are trying to add a temporary client then here are
+		 * two options at this point:
+		 * 1) the global client is not a temporary client: the global
+		 *    client has to be left as it is, temporary information
+		 *    should never override any already known client state
+		 * 2) the global client is a temporary client: purge the
+		 *    originator list and add the new one orig_entry
 		 */
-		if (flags & BATADV_TT_CLIENT_TEMP)
-			goto out;
+		if (flags & BATADV_TT_CLIENT_TEMP) {
+			if (!(common->flags & BATADV_TT_CLIENT_TEMP))
+				goto out;
+			if (batadv_tt_global_entry_has_orig(tt_global_entry,
+							    orig_node))
+				goto out_remove;
+			batadv_tt_global_del_orig_list(tt_global_entry);
+			goto add_orig_entry;
+		}
 
 		/* if the client was temporary added before receiving the first
 		 * OGM announcing it, we have to clear the TEMP flag
 		 */
-		tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP;
+		common->flags &= ~BATADV_TT_CLIENT_TEMP;
 
 		/* the change can carry possible "attribute" flags like the
 		 * TT_CLIENT_WIFI, therefore they have to be copied in the
@@ -782,33 +874,81 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
 		 * We should first delete the old originator before adding the
 		 * new one.
 		 */
-		if (tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM) {
+		if (common->flags & BATADV_TT_CLIENT_ROAM) {
 			batadv_tt_global_del_orig_list(tt_global_entry);
-			tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
+			common->flags &= ~BATADV_TT_CLIENT_ROAM;
 			tt_global_entry->roam_at = 0;
 		}
 	}
+add_orig_entry:
 	/* add the new orig_entry (if needed) or update it */
 	batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn);
 
 	batadv_dbg(BATADV_DBG_TT, bat_priv,
 		   "Creating new global tt entry: %pM (via %pM)\n",
-		   tt_global_entry->common.addr, orig_node->orig);
+		   common->addr, orig_node->orig);
+	ret = 1;
 
 out_remove:
+
 	/* remove address from local hash if present */
-	batadv_tt_local_remove(bat_priv, tt_global_entry->common.addr,
-			       "global tt received",
-			       flags & BATADV_TT_CLIENT_ROAM);
-	ret = 1;
+	local_flags = batadv_tt_local_remove(bat_priv, tt_addr,
+					     "global tt received",
+					     !!(flags & BATADV_TT_CLIENT_ROAM));
+	tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;
+
+	if (!(flags & BATADV_TT_CLIENT_ROAM))
+		/* this is a normal global add. Therefore the client is not in a
+		 * roaming state anymore.
+		 */
+		tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
+
 out:
 	if (tt_global_entry)
 		batadv_tt_global_entry_free_ref(tt_global_entry);
+	if (tt_local_entry)
+		batadv_tt_local_entry_free_ref(tt_local_entry);
 	return ret;
 }
 
-/* print all orig nodes who announce the address for this global entry.
- * it is assumed that the caller holds rcu_read_lock();
+/* batadv_transtable_best_orig - Get best originator list entry from tt entry
+ * @tt_global_entry: global translation table entry to be analyzed
+ *
+ * This functon assumes the caller holds rcu_read_lock().
+ * Returns best originator list entry or NULL on errors.
+ */
+static struct batadv_tt_orig_list_entry *
+batadv_transtable_best_orig(struct batadv_tt_global_entry *tt_global_entry)
+{
+	struct batadv_neigh_node *router = NULL;
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct batadv_tt_orig_list_entry *orig_entry, *best_entry = NULL;
+	int best_tq = 0;
+
+	head = &tt_global_entry->orig_list;
+	hlist_for_each_entry_rcu(orig_entry, node, head, list) {
+		router = batadv_orig_node_get_router(orig_entry->orig_node);
+		if (!router)
+			continue;
+
+		if (router->tq_avg > best_tq) {
+			best_entry = orig_entry;
+			best_tq = router->tq_avg;
+		}
+
+		batadv_neigh_node_free_ref(router);
+	}
+
+	return best_entry;
+}
+
+/* batadv_tt_global_print_entry - print all orig nodes who announce the address
+ * for this global entry
+ * @tt_global_entry: global translation table entry to be printed
+ * @seq: debugfs table seq_file struct
+ *
+ * This functon assumes the caller holds rcu_read_lock().
  */
 static void
 batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
@@ -816,21 +956,37 @@ batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
 {
 	struct hlist_head *head;
 	struct hlist_node *node;
-	struct batadv_tt_orig_list_entry *orig_entry;
+	struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
 	struct batadv_tt_common_entry *tt_common_entry;
 	uint16_t flags;
 	uint8_t last_ttvn;
 
 	tt_common_entry = &tt_global_entry->common;
+	flags = tt_common_entry->flags;
+
+	best_entry = batadv_transtable_best_orig(tt_global_entry);
+	if (best_entry) {
+		last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn);
+		seq_printf(seq,	" %c %pM  (%3u) via %pM     (%3u)   [%c%c%c]\n",
+			   '*', tt_global_entry->common.addr,
+			   best_entry->ttvn, best_entry->orig_node->orig,
+			   last_ttvn,
+			   (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
+			   (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
+			   (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
+	}
 
 	head = &tt_global_entry->orig_list;
 
 	hlist_for_each_entry_rcu(orig_entry, node, head, list) {
-		flags = tt_common_entry->flags;
+		if (best_entry == orig_entry)
+			continue;
+
 		last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
-		seq_printf(seq,	" * %pM  (%3u) via %pM     (%3u)   [%c%c%c]\n",
-			   tt_global_entry->common.addr, orig_entry->ttvn,
-			   orig_entry->orig_node->orig, last_ttvn,
+		seq_printf(seq,	" %c %pM  (%3u) via %pM     (%3u)   [%c%c%c]\n",
+			   '+', tt_global_entry->common.addr,
+			   orig_entry->ttvn, orig_entry->orig_node->orig,
+			   last_ttvn,
 			   (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
 			   (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
 			   (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
@@ -848,22 +1004,10 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
 	struct hlist_node *node;
 	struct hlist_head *head;
 	uint32_t i;
-	int ret = 0;
-
-	primary_if = batadv_primary_if_get_selected(bat_priv);
-	if (!primary_if) {
-		ret = seq_printf(seq,
-				 "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
-				 net_dev->name);
-		goto out;
-	}
 
-	if (primary_if->if_status != BATADV_IF_ACTIVE) {
-		ret = seq_printf(seq,
-				 "BATMAN mesh %s disabled - primary interface not active\n",
-				 net_dev->name);
+	primary_if = batadv_seq_print_text_primary_if_get(seq);
+	if (!primary_if)
 		goto out;
-	}
 
 	seq_printf(seq,
 		   "Globally announced TT entries received via the mesh %s\n",
@@ -887,7 +1031,7 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
 out:
 	if (primary_if)
 		batadv_hardif_free_ref(primary_if);
-	return ret;
+	return 0;
 }
 
 /* deletes the orig list of a tt_global_entry */
@@ -933,21 +1077,6 @@ batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv,
 	spin_unlock_bh(&tt_global_entry->list_lock);
 }
 
-static void
-batadv_tt_global_del_struct(struct batadv_priv *bat_priv,
-			    struct batadv_tt_global_entry *tt_global_entry,
-			    const char *message)
-{
-	batadv_dbg(BATADV_DBG_TT, bat_priv,
-		   "Deleting global tt entry %pM: %s\n",
-		   tt_global_entry->common.addr, message);
-
-	batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
-			   batadv_choose_orig, tt_global_entry->common.addr);
-	batadv_tt_global_entry_free_ref(tt_global_entry);
-
-}
-
 /* If the client is to be deleted, we check if it is the last origantor entry
  * within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the
  * timer, otherwise we simply remove the originator scheduled for deletion.
@@ -996,7 +1125,7 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv,
 				 const unsigned char *addr,
 				 const char *message, bool roaming)
 {
-	struct batadv_tt_global_entry *tt_global_entry = NULL;
+	struct batadv_tt_global_entry *tt_global_entry;
 	struct batadv_tt_local_entry *local_entry = NULL;
 
 	tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr);
@@ -1008,8 +1137,8 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv,
 						orig_node, message);
 
 		if (hlist_empty(&tt_global_entry->orig_list))
-			batadv_tt_global_del_struct(bat_priv, tt_global_entry,
-						    message);
+			batadv_tt_global_free(bat_priv, tt_global_entry,
+					      message);
 
 		goto out;
 	}
@@ -1032,7 +1161,7 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv,
 	if (local_entry) {
 		/* local entry exists, case 2: client roamed to us. */
 		batadv_tt_global_del_orig_list(tt_global_entry);
-		batadv_tt_global_del_struct(bat_priv, tt_global_entry, message);
+		batadv_tt_global_free(bat_priv, tt_global_entry, message);
 	} else
 		/* no local entry exists, case 1: check for roaming */
 		batadv_tt_global_del_roaming(bat_priv, tt_global_entry,
@@ -1203,15 +1332,12 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
 	struct batadv_tt_local_entry *tt_local_entry = NULL;
 	struct batadv_tt_global_entry *tt_global_entry = NULL;
 	struct batadv_orig_node *orig_node = NULL;
-	struct batadv_neigh_node *router = NULL;
-	struct hlist_head *head;
-	struct hlist_node *node;
-	struct batadv_tt_orig_list_entry *orig_entry;
-	int best_tq;
+	struct batadv_tt_orig_list_entry *best_entry;
 
 	if (src && atomic_read(&bat_priv->ap_isolation)) {
 		tt_local_entry = batadv_tt_local_hash_find(bat_priv, src);
-		if (!tt_local_entry)
+		if (!tt_local_entry ||
+		    (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING))
 			goto out;
 	}
 
@@ -1226,25 +1352,15 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
 	    _batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
 		goto out;
 
-	best_tq = 0;
-
 	rcu_read_lock();
-	head = &tt_global_entry->orig_list;
-	hlist_for_each_entry_rcu(orig_entry, node, head, list) {
-		router = batadv_orig_node_get_router(orig_entry->orig_node);
-		if (!router)
-			continue;
-
-		if (router->tq_avg > best_tq) {
-			orig_node = orig_entry->orig_node;
-			best_tq = router->tq_avg;
-		}
-		batadv_neigh_node_free_ref(router);
-	}
+	best_entry = batadv_transtable_best_orig(tt_global_entry);
 	/* found anything? */
+	if (best_entry)
+		orig_node = best_entry->orig_node;
 	if (orig_node && !atomic_inc_not_zero(&orig_node->refcount))
 		orig_node = NULL;
 	rcu_read_unlock();
+
 out:
 	if (tt_global_entry)
 		batadv_tt_global_entry_free_ref(tt_global_entry);
@@ -1477,11 +1593,11 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
 	tt_tot = tt_len / sizeof(struct batadv_tt_change);
 
 	len = tt_query_size + tt_len;
-	skb = dev_alloc_skb(len + ETH_HLEN);
+	skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
 	if (!skb)
 		goto out;
 
-	skb_reserve(skb, ETH_HLEN);
+	skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
 	tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len);
 	tt_response->ttvn = ttvn;
 
@@ -1526,7 +1642,6 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
 {
 	struct sk_buff *skb = NULL;
 	struct batadv_tt_query_packet *tt_request;
-	struct batadv_neigh_node *neigh_node = NULL;
 	struct batadv_hard_iface *primary_if;
 	struct batadv_tt_req_node *tt_req_node = NULL;
 	int ret = 1;
@@ -1543,11 +1658,11 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
 	if (!tt_req_node)
 		goto out;
 
-	skb = dev_alloc_skb(sizeof(*tt_request) + ETH_HLEN);
+	skb = dev_alloc_skb(sizeof(*tt_request) + ETH_HLEN + NET_IP_ALIGN);
 	if (!skb)
 		goto out;
 
-	skb_reserve(skb, ETH_HLEN);
+	skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
 
 	tt_req_len = sizeof(*tt_request);
 	tt_request = (struct batadv_tt_query_packet *)skb_put(skb, tt_req_len);
@@ -1564,23 +1679,15 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
 	if (full_table)
 		tt_request->flags |= BATADV_TT_FULL_TABLE;
 
-	neigh_node = batadv_orig_node_get_router(dst_orig_node);
-	if (!neigh_node)
-		goto out;
-
-	batadv_dbg(BATADV_DBG_TT, bat_priv,
-		   "Sending TT_REQUEST to %pM via %pM [%c]\n",
-		   dst_orig_node->orig, neigh_node->addr,
-		   (full_table ? 'F' : '.'));
+	batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]\n",
+		   dst_orig_node->orig, (full_table ? 'F' : '.'));
 
 	batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
 
-	batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-	ret = 0;
+	if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL))
+		ret = 0;
 
 out:
-	if (neigh_node)
-		batadv_neigh_node_free_ref(neigh_node);
 	if (primary_if)
 		batadv_hardif_free_ref(primary_if);
 	if (ret)
@@ -1598,9 +1705,8 @@ static bool
 batadv_send_other_tt_response(struct batadv_priv *bat_priv,
 			      struct batadv_tt_query_packet *tt_request)
 {
-	struct batadv_orig_node *req_dst_orig_node = NULL;
+	struct batadv_orig_node *req_dst_orig_node;
 	struct batadv_orig_node *res_dst_orig_node = NULL;
-	struct batadv_neigh_node *neigh_node = NULL;
 	struct batadv_hard_iface *primary_if = NULL;
 	uint8_t orig_ttvn, req_ttvn, ttvn;
 	int ret = false;
@@ -1626,10 +1732,6 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
 	if (!res_dst_orig_node)
 		goto out;
 
-	neigh_node = batadv_orig_node_get_router(res_dst_orig_node);
-	if (!neigh_node)
-		goto out;
-
 	primary_if = batadv_primary_if_get_selected(bat_priv);
 	if (!primary_if)
 		goto out;
@@ -1658,11 +1760,11 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
 		tt_tot = tt_len / sizeof(struct batadv_tt_change);
 
 		len = sizeof(*tt_response) + tt_len;
-		skb = dev_alloc_skb(len + ETH_HLEN);
+		skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
 		if (!skb)
 			goto unlock;
 
-		skb_reserve(skb, ETH_HLEN);
+		skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
 		packet_pos = skb_put(skb, len);
 		tt_response = (struct batadv_tt_query_packet *)packet_pos;
 		tt_response->ttvn = req_ttvn;
@@ -1701,14 +1803,13 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
 		tt_response->flags |= BATADV_TT_FULL_TABLE;
 
 	batadv_dbg(BATADV_DBG_TT, bat_priv,
-		   "Sending TT_RESPONSE %pM via %pM for %pM (ttvn: %u)\n",
-		   res_dst_orig_node->orig, neigh_node->addr,
-		   req_dst_orig_node->orig, req_ttvn);
+		   "Sending TT_RESPONSE %pM for %pM (ttvn: %u)\n",
+		   res_dst_orig_node->orig, req_dst_orig_node->orig, req_ttvn);
 
 	batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
 
-	batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-	ret = true;
+	if (batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL))
+		ret = true;
 	goto out;
 
 unlock:
@@ -1719,8 +1820,6 @@ out:
 		batadv_orig_node_free_ref(res_dst_orig_node);
 	if (req_dst_orig_node)
 		batadv_orig_node_free_ref(req_dst_orig_node);
-	if (neigh_node)
-		batadv_neigh_node_free_ref(neigh_node);
 	if (primary_if)
 		batadv_hardif_free_ref(primary_if);
 	if (!ret)
@@ -1733,8 +1832,7 @@ static bool
 batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 			   struct batadv_tt_query_packet *tt_request)
 {
-	struct batadv_orig_node *orig_node = NULL;
-	struct batadv_neigh_node *neigh_node = NULL;
+	struct batadv_orig_node *orig_node;
 	struct batadv_hard_iface *primary_if = NULL;
 	uint8_t my_ttvn, req_ttvn, ttvn;
 	int ret = false;
@@ -1759,10 +1857,6 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 	if (!orig_node)
 		goto out;
 
-	neigh_node = batadv_orig_node_get_router(orig_node);
-	if (!neigh_node)
-		goto out;
-
 	primary_if = batadv_primary_if_get_selected(bat_priv);
 	if (!primary_if)
 		goto out;
@@ -1785,11 +1879,11 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 		tt_tot = tt_len / sizeof(struct batadv_tt_change);
 
 		len = sizeof(*tt_response) + tt_len;
-		skb = dev_alloc_skb(len + ETH_HLEN);
+		skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
 		if (!skb)
 			goto unlock;
 
-		skb_reserve(skb, ETH_HLEN);
+		skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
 		packet_pos = skb_put(skb, len);
 		tt_response = (struct batadv_tt_query_packet *)packet_pos;
 		tt_response->ttvn = req_ttvn;
@@ -1826,14 +1920,14 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
 		tt_response->flags |= BATADV_TT_FULL_TABLE;
 
 	batadv_dbg(BATADV_DBG_TT, bat_priv,
-		   "Sending TT_RESPONSE to %pM via %pM [%c]\n",
-		   orig_node->orig, neigh_node->addr,
+		   "Sending TT_RESPONSE to %pM [%c]\n",
+		   orig_node->orig,
 		   (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
 
 	batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
 
-	batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-	ret = true;
+	if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+		ret = true;
 	goto out;
 
 unlock:
@@ -1841,8 +1935,6 @@ unlock:
 out:
 	if (orig_node)
 		batadv_orig_node_free_ref(orig_node);
-	if (neigh_node)
-		batadv_neigh_node_free_ref(neigh_node);
 	if (primary_if)
 		batadv_hardif_free_ref(primary_if);
 	if (!ret)
@@ -1899,7 +1991,7 @@ static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
 static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
 				  struct batadv_tt_query_packet *tt_response)
 {
-	struct batadv_orig_node *orig_node = NULL;
+	struct batadv_orig_node *orig_node;
 
 	orig_node = batadv_orig_hash_find(bat_priv, tt_response->src);
 	if (!orig_node)
@@ -1941,7 +2033,7 @@ static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
 
 bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr)
 {
-	struct batadv_tt_local_entry *tt_local_entry = NULL;
+	struct batadv_tt_local_entry *tt_local_entry;
 	bool ret = false;
 
 	tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
@@ -1950,7 +2042,8 @@ bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr)
 	/* Check if the client has been logically deleted (but is kept for
 	 * consistency purpose)
 	 */
-	if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING)
+	if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) ||
+	    (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM))
 		goto out;
 	ret = true;
 out:
@@ -2001,10 +2094,6 @@ void batadv_handle_tt_response(struct batadv_priv *bat_priv,
 
 	/* Recalculate the CRC for this orig_node and store it */
 	orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node);
-	/* Roaming phase is over: tables are in sync again. I can
-	 * unset the flag
-	 */
-	orig_node->tt_poss_change = false;
 out:
 	if (orig_node)
 		batadv_orig_node_free_ref(orig_node);
@@ -2110,7 +2199,6 @@ unlock:
 static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
 				 struct batadv_orig_node *orig_node)
 {
-	struct batadv_neigh_node *neigh_node = NULL;
 	struct sk_buff *skb = NULL;
 	struct batadv_roam_adv_packet *roam_adv_packet;
 	int ret = 1;
@@ -2123,11 +2211,11 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
 	if (!batadv_tt_check_roam_count(bat_priv, client))
 		goto out;
 
-	skb = dev_alloc_skb(sizeof(*roam_adv_packet) + ETH_HLEN);
+	skb = dev_alloc_skb(sizeof(*roam_adv_packet) + ETH_HLEN + NET_IP_ALIGN);
 	if (!skb)
 		goto out;
 
-	skb_reserve(skb, ETH_HLEN);
+	skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
 
 	roam_adv_packet = (struct batadv_roam_adv_packet *)skb_put(skb, len);
 
@@ -2143,23 +2231,17 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
 	memcpy(roam_adv_packet->dst, orig_node->orig, ETH_ALEN);
 	memcpy(roam_adv_packet->client, client, ETH_ALEN);
 
-	neigh_node = batadv_orig_node_get_router(orig_node);
-	if (!neigh_node)
-		goto out;
-
 	batadv_dbg(BATADV_DBG_TT, bat_priv,
-		   "Sending ROAMING_ADV to %pM (client %pM) via %pM\n",
-		   orig_node->orig, client, neigh_node->addr);
+		   "Sending ROAMING_ADV to %pM (client %pM)\n",
+		   orig_node->orig, client);
 
 	batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
 
-	batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-	ret = 0;
+	if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+		ret = 0;
 
 out:
-	if (neigh_node)
-		batadv_neigh_node_free_ref(neigh_node);
-	if (ret)
+	if (ret && skb)
 		kfree_skb(skb);
 	return;
 }
@@ -2295,7 +2377,6 @@ static int batadv_tt_commit_changes(struct batadv_priv *bat_priv,
 	batadv_dbg(BATADV_DBG_TT, bat_priv,
 		   "Local changes committed, updating to ttvn %u\n",
 		   (uint8_t)atomic_read(&bat_priv->tt.vn));
-	bat_priv->tt.poss_change = false;
 
 	/* reset the sending counter */
 	atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
@@ -2407,11 +2488,6 @@ void batadv_tt_update_orig(struct batadv_priv *bat_priv,
 		 */
 		if (orig_node->tt_crc != tt_crc)
 			goto request_table;
-
-		/* Roaming phase is over: tables are in sync again. I can
-		 * unset the flag
-		 */
-		orig_node->tt_poss_change = false;
 	} else {
 		/* if we missed more than one change or our tables are not
 		 * in sync anymore -> request fresh tt data
@@ -2444,12 +2520,38 @@ bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
 	if (!tt_global_entry)
 		goto out;
 
-	ret = tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM;
+	ret = !!(tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM);
 	batadv_tt_global_entry_free_ref(tt_global_entry);
 out:
 	return ret;
 }
 
+/**
+ * batadv_tt_local_client_is_roaming - tells whether the client is roaming
+ * @bat_priv: the bat priv with all the soft interface information
+ * @addr: the MAC address of the local client to query
+ *
+ * Returns true if the local client is known to be roaming (it is not served by
+ * this node anymore) or not. If yes, the client is still present in the table
+ * to keep the latter consistent with the node TTVN
+ */
+bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
+				       uint8_t *addr)
+{
+	struct batadv_tt_local_entry *tt_local_entry;
+	bool ret = false;
+
+	tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
+	if (!tt_local_entry)
+		goto out;
+
+	ret = tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM;
+	batadv_tt_local_entry_free_ref(tt_local_entry);
+out:
+	return ret;
+
+}
+
 bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
 					  struct batadv_orig_node *orig_node,
 					  const unsigned char *addr)
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index 811fffd..46d4451 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -24,9 +24,9 @@ int batadv_tt_len(int changes_num);
 int batadv_tt_init(struct batadv_priv *bat_priv);
 void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
 			 int ifindex);
-void batadv_tt_local_remove(struct batadv_priv *bat_priv,
-			    const uint8_t *addr, const char *message,
-			    bool roaming);
+uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
+				const uint8_t *addr, const char *message,
+				bool roaming);
 int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset);
 void batadv_tt_global_add_orig(struct batadv_priv *bat_priv,
 			       struct batadv_orig_node *orig_node,
@@ -59,6 +59,8 @@ int batadv_tt_append_diff(struct batadv_priv *bat_priv,
 			  int packet_min_len);
 bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
 					uint8_t *addr);
+bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
+				       uint8_t *addr);
 bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
 					  struct batadv_orig_node *orig_node,
 					  const unsigned char *addr);
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index ac1e07a..ae9ac9a 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -28,20 +28,41 @@
 	(ETH_HLEN + max(sizeof(struct batadv_unicast_packet), \
 			sizeof(struct batadv_bcast_packet)))
 
+#ifdef CONFIG_BATMAN_ADV_DAT
+
+/* batadv_dat_addr_t is the type used for all DHT addresses. If it is changed,
+ * BATADV_DAT_ADDR_MAX is changed as well.
+ *
+ * *Please be careful: batadv_dat_addr_t must be UNSIGNED*
+ */
+#define batadv_dat_addr_t uint16_t
+
+#endif /* CONFIG_BATMAN_ADV_DAT */
+
+/**
+ * struct batadv_hard_iface_bat_iv - per hard interface B.A.T.M.A.N. IV data
+ * @ogm_buff: buffer holding the OGM packet
+ * @ogm_buff_len: length of the OGM packet buffer
+ * @ogm_seqno: OGM sequence number - used to identify each OGM
+ */
+struct batadv_hard_iface_bat_iv {
+	unsigned char *ogm_buff;
+	int ogm_buff_len;
+	atomic_t ogm_seqno;
+};
+
 struct batadv_hard_iface {
 	struct list_head list;
 	int16_t if_num;
 	char if_status;
 	struct net_device *net_dev;
-	atomic_t seqno;
 	atomic_t frag_seqno;
-	unsigned char *packet_buff;
-	int packet_len;
 	struct kobject *hardif_obj;
 	atomic_t refcount;
 	struct packet_type batman_adv_ptype;
 	struct net_device *soft_iface;
 	struct rcu_head rcu;
+	struct batadv_hard_iface_bat_iv bat_iv;
 };
 
 /**
@@ -63,6 +84,9 @@ struct batadv_orig_node {
 	uint8_t orig[ETH_ALEN];
 	uint8_t primary_addr[ETH_ALEN];
 	struct batadv_neigh_node __rcu *router; /* rcu protected pointer */
+#ifdef CONFIG_BATMAN_ADV_DAT
+	batadv_dat_addr_t dat_addr;
+#endif
 	unsigned long *bcast_own;
 	uint8_t *bcast_own_sum;
 	unsigned long last_seen;
@@ -77,13 +101,6 @@ struct batadv_orig_node {
 	spinlock_t tt_buff_lock; /* protects tt_buff */
 	atomic_t tt_size;
 	bool tt_initialised;
-	/* The tt_poss_change flag is used to detect an ongoing roaming phase.
-	 * If true, then I sent a Roaming_adv to this orig_node and I have to
-	 * inspect every packet directed to it to check whether it is still
-	 * the true destination or not. This flag will be reset to false as
-	 * soon as I receive a new TTVN from this orig_node
-	 */
-	bool tt_poss_change;
 	uint32_t last_real_seqno;
 	uint8_t last_ttl;
 	DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
@@ -139,7 +156,7 @@ struct batadv_neigh_node {
 #ifdef CONFIG_BATMAN_ADV_BLA
 struct batadv_bcast_duplist_entry {
 	uint8_t orig[ETH_ALEN];
-	uint16_t crc;
+	__be32 crc;
 	unsigned long entrytime;
 };
 #endif
@@ -162,6 +179,13 @@ enum batadv_counters {
 	BATADV_CNT_TT_RESPONSE_RX,
 	BATADV_CNT_TT_ROAM_ADV_TX,
 	BATADV_CNT_TT_ROAM_ADV_RX,
+#ifdef CONFIG_BATMAN_ADV_DAT
+	BATADV_CNT_DAT_GET_TX,
+	BATADV_CNT_DAT_GET_RX,
+	BATADV_CNT_DAT_PUT_TX,
+	BATADV_CNT_DAT_PUT_RX,
+	BATADV_CNT_DAT_CACHED_REPLY_TX,
+#endif
 	BATADV_CNT_NUM,
 };
 
@@ -181,7 +205,6 @@ struct batadv_priv_tt {
 	atomic_t vn;
 	atomic_t ogm_append_cnt;
 	atomic_t local_changes;
-	bool poss_change;
 	struct list_head changes_list;
 	struct batadv_hashtable *local_hash;
 	struct batadv_hashtable *global_hash;
@@ -228,6 +251,20 @@ struct batadv_priv_vis {
 	struct batadv_vis_info *my_info;
 };
 
+/**
+ * struct batadv_priv_dat - per mesh interface DAT private data
+ * @addr: node DAT address
+ * @hash: hashtable representing the local ARP cache
+ * @work: work queue callback item for cache purging
+ */
+#ifdef CONFIG_BATMAN_ADV_DAT
+struct batadv_priv_dat {
+	batadv_dat_addr_t addr;
+	struct batadv_hashtable *hash;
+	struct delayed_work work;
+};
+#endif
+
 struct batadv_priv {
 	atomic_t mesh_state;
 	struct net_device_stats stats;
@@ -237,6 +274,9 @@ struct batadv_priv {
 	atomic_t fragmentation;		/* boolean */
 	atomic_t ap_isolation;		/* boolean */
 	atomic_t bridge_loop_avoidance;	/* boolean */
+#ifdef CONFIG_BATMAN_ADV_DAT
+	atomic_t distributed_arp_table;	/* boolean */
+#endif
 	atomic_t vis_mode;		/* VIS_TYPE_* */
 	atomic_t gw_mode;		/* GW_MODE_* */
 	atomic_t gw_sel_class;		/* uint */
@@ -255,7 +295,7 @@ struct batadv_priv {
 	struct hlist_head forw_bcast_list;
 	struct batadv_hashtable *orig_hash;
 	spinlock_t forw_bat_list_lock; /* protects forw_bat_list */
-	spinlock_t forw_bcast_list_lock; /* protects  */
+	spinlock_t forw_bcast_list_lock; /* protects forw_bcast_list */
 	struct delayed_work orig_work;
 	struct batadv_hard_iface __rcu *primary_if;  /* rcu protected pointer */
 	struct batadv_algo_ops *bat_algo_ops;
@@ -265,6 +305,9 @@ struct batadv_priv {
 	struct batadv_priv_gw gw;
 	struct batadv_priv_tt tt;
 	struct batadv_priv_vis vis;
+#ifdef CONFIG_BATMAN_ADV_DAT
+	struct batadv_priv_dat dat;
+#endif
 };
 
 struct batadv_socket_client {
@@ -318,6 +361,7 @@ struct batadv_backbone_gw {
 	struct hlist_node hash_entry;
 	struct batadv_priv *bat_priv;
 	unsigned long lasttime;	/* last time we heard of this backbone gw */
+	atomic_t wait_periods;
 	atomic_t request_sent;
 	atomic_t refcount;
 	struct rcu_head rcu;
@@ -437,4 +481,36 @@ struct batadv_algo_ops {
 	void (*bat_ogm_emit)(struct batadv_forw_packet *forw_packet);
 };
 
+/**
+ * struct batadv_dat_entry - it is a single entry of batman-adv ARP backend. It
+ * is used to stored ARP entries needed for the global DAT cache
+ * @ip: the IPv4 corresponding to this DAT/ARP entry
+ * @mac_addr: the MAC address associated to the stored IPv4
+ * @last_update: time in jiffies when this entry was refreshed last time
+ * @hash_entry: hlist node for batadv_priv_dat::hash
+ * @refcount: number of contexts the object is used
+ * @rcu: struct used for freeing in an RCU-safe manner
+ */
+struct batadv_dat_entry {
+	__be32 ip;
+	uint8_t mac_addr[ETH_ALEN];
+	unsigned long last_update;
+	struct hlist_node hash_entry;
+	atomic_t refcount;
+	struct rcu_head rcu;
+};
+
+/**
+ * struct batadv_dat_candidate - candidate destination for DAT operations
+ * @type: the type of the selected candidate. It can one of the following:
+ *	  - BATADV_DAT_CANDIDATE_NOT_FOUND
+ *	  - BATADV_DAT_CANDIDATE_ORIG
+ * @orig_node: if type is BATADV_DAT_CANDIDATE_ORIG this field points to the
+ *	       corresponding originator node structure
+ */
+struct batadv_dat_candidate {
+	int type;
+	struct batadv_orig_node *orig_node;
+};
+
 #endif /* _NET_BATMAN_ADV_TYPES_H_ */
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
index f397232..10aff49 100644
--- a/net/batman-adv/unicast.c
+++ b/net/batman-adv/unicast.c
@@ -291,14 +291,118 @@ out:
 	return ret;
 }
 
-int batadv_unicast_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv)
+/**
+ * batadv_unicast_push_and_fill_skb - extends the buffer and initializes the
+ * common fields for unicast packets
+ * @skb: packet
+ * @hdr_size: amount of bytes to push at the beginning of the skb
+ * @orig_node: the destination node
+ *
+ * Returns false if the buffer extension was not possible or true otherwise
+ */
+static bool batadv_unicast_push_and_fill_skb(struct sk_buff *skb, int hdr_size,
+					     struct batadv_orig_node *orig_node)
+{
+	struct batadv_unicast_packet *unicast_packet;
+	uint8_t ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
+
+	if (batadv_skb_head_push(skb, hdr_size) < 0)
+		return false;
+
+	unicast_packet = (struct batadv_unicast_packet *)skb->data;
+	unicast_packet->header.version = BATADV_COMPAT_VERSION;
+	/* batman packet type: unicast */
+	unicast_packet->header.packet_type = BATADV_UNICAST;
+	/* set unicast ttl */
+	unicast_packet->header.ttl = BATADV_TTL;
+	/* copy the destination for faster routing */
+	memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
+	/* set the destination tt version number */
+	unicast_packet->ttvn = ttvn;
+
+	return true;
+}
+
+/**
+ * batadv_unicast_prepare_skb - encapsulate an skb with a unicast header
+ * @skb: the skb containing the payload to encapsulate
+ * @orig_node: the destination node
+ *
+ * Returns false if the payload could not be encapsulated or true otherwise
+ */
+static bool batadv_unicast_prepare_skb(struct sk_buff *skb,
+				       struct batadv_orig_node *orig_node)
+{
+	size_t uni_size = sizeof(struct batadv_unicast_packet);
+	return batadv_unicast_push_and_fill_skb(skb, uni_size, orig_node);
+}
+
+/**
+ * batadv_unicast_4addr_prepare_skb - encapsulate an skb with a unicast4addr
+ * header
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: the skb containing the payload to encapsulate
+ * @orig_node: the destination node
+ * @packet_subtype: the batman 4addr packet subtype to use
+ *
+ * Returns false if the payload could not be encapsulated or true otherwise
+ */
+bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv,
+				      struct sk_buff *skb,
+				      struct batadv_orig_node *orig,
+				      int packet_subtype)
+{
+	struct batadv_hard_iface *primary_if;
+	struct batadv_unicast_4addr_packet *unicast_4addr_packet;
+	bool ret = false;
+
+	primary_if = batadv_primary_if_get_selected(bat_priv);
+	if (!primary_if)
+		goto out;
+
+	/* pull the header space and fill the unicast_packet substructure.
+	 * We can do that because the first member of the unicast_4addr_packet
+	 * is of type struct unicast_packet
+	 */
+	if (!batadv_unicast_push_and_fill_skb(skb,
+					      sizeof(*unicast_4addr_packet),
+					      orig))
+		goto out;
+
+	unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
+	unicast_4addr_packet->u.header.packet_type = BATADV_UNICAST_4ADDR;
+	memcpy(unicast_4addr_packet->src, primary_if->net_dev->dev_addr,
+	       ETH_ALEN);
+	unicast_4addr_packet->subtype = packet_subtype;
+	unicast_4addr_packet->reserved = 0;
+
+	ret = true;
+out:
+	if (primary_if)
+		batadv_hardif_free_ref(primary_if);
+	return ret;
+}
+
+/**
+ * batadv_unicast_generic_send_skb - send an skb as unicast
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: payload to send
+ * @packet_type: the batman unicast packet type to use
+ * @packet_subtype: the batman packet subtype. It is ignored if packet_type is
+ *		    not BATADV_UNICAT_4ADDR
+ *
+ * Returns 1 in case of error or 0 otherwise
+ */
+int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,